summaryrefslogtreecommitdiffstats
path: root/contrib/gcc
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2003-07-11 03:40:53 +0000
committerkan <kan@FreeBSD.org>2003-07-11 03:40:53 +0000
commitb2a8872fbe1ec1c49094559ac7b78e6ea4ab7180 (patch)
treef6b0610f4a17fd26aa234354f050080f789861a4 /contrib/gcc
parent52e69d78eee5612ac195e0701a5cebe40d1ab0e1 (diff)
downloadFreeBSD-src-b2a8872fbe1ec1c49094559ac7b78e6ea4ab7180.zip
FreeBSD-src-b2a8872fbe1ec1c49094559ac7b78e6ea4ab7180.tar.gz
Gcc 3.3.1-pre as of 2003-07-11.
Diffstat (limited to 'contrib/gcc')
-rw-r--r--contrib/gcc/ChangeLog22733
-rw-r--r--contrib/gcc/ChangeLog.012
-rw-r--r--contrib/gcc/ChangeLog.132
-rw-r--r--contrib/gcc/ChangeLog.234
-rw-r--r--contrib/gcc/ChangeLog.350
-rw-r--r--contrib/gcc/ChangeLog.454
-rw-r--r--contrib/gcc/ChangeLog.542
-rw-r--r--contrib/gcc/ChangeLog.640
-rw-r--r--contrib/gcc/ChangeLog.721543
-rw-r--r--contrib/gcc/FSFChangeLog.1010
-rw-r--r--contrib/gcc/FSFChangeLog.1142
-rw-r--r--contrib/gcc/LANGUAGES2
-rw-r--r--contrib/gcc/Makefile.in1187
-rw-r--r--contrib/gcc/ONEWS98
-rw-r--r--contrib/gcc/README.Portability51
-rw-r--r--contrib/gcc/aclocal.m4448
-rw-r--r--contrib/gcc/alias.c485
-rw-r--r--contrib/gcc/ansidecl.h35
-rw-r--r--contrib/gcc/attribs.c1093
-rw-r--r--contrib/gcc/basic-block.h200
-rw-r--r--contrib/gcc/bb-reorder.c71
-rw-r--r--contrib/gcc/bitmap.c187
-rw-r--r--contrib/gcc/bitmap.h103
-rw-r--r--contrib/gcc/builtin-attrs.def90
-rw-r--r--contrib/gcc/builtin-types.def47
-rw-r--r--contrib/gcc/builtins.c578
-rw-r--r--contrib/gcc/builtins.def536
-rw-r--r--contrib/gcc/c-aux-info.c4
-rw-r--r--contrib/gcc/c-common.c3549
-rw-r--r--contrib/gcc/c-common.def30
-rw-r--r--contrib/gcc/c-common.h521
-rw-r--r--contrib/gcc/c-config-lang.in26
-rw-r--r--contrib/gcc/c-convert.c12
-rw-r--r--contrib/gcc/c-decl.c1370
-rw-r--r--contrib/gcc/c-dump.c196
-rw-r--r--contrib/gcc/c-errors.c9
-rw-r--r--contrib/gcc/c-format.c201
-rw-r--r--contrib/gcc/c-lang.c117
-rw-r--r--contrib/gcc/c-lex.c856
-rw-r--r--contrib/gcc/c-objc-common.c86
-rw-r--r--contrib/gcc/c-opts.c1799
-rw-r--r--contrib/gcc/c-parse.in532
-rw-r--r--contrib/gcc/c-pragma.c68
-rw-r--r--contrib/gcc/c-pragma.h10
-rw-r--r--contrib/gcc/c-pretty-print.c1493
-rw-r--r--contrib/gcc/c-pretty-print.h165
-rw-r--r--contrib/gcc/c-semantics.c22
-rw-r--r--contrib/gcc/c-tree.h154
-rw-r--r--contrib/gcc/c-typeck.c547
-rw-r--r--contrib/gcc/caller-save.c35
-rw-r--r--contrib/gcc/calls.c292
-rw-r--r--contrib/gcc/cfg.c241
-rw-r--r--contrib/gcc/cfganal.c368
-rw-r--r--contrib/gcc/cfgbuild.c218
-rw-r--r--contrib/gcc/cfgcleanup.c429
-rw-r--r--contrib/gcc/cfglayout.c581
-rw-r--r--contrib/gcc/cfglayout.h11
-rw-r--r--contrib/gcc/cfgloop.c1085
-rw-r--r--contrib/gcc/cfgrtl.c715
-rw-r--r--contrib/gcc/collect2.c43
-rw-r--r--contrib/gcc/collect2.h1
-rw-r--r--contrib/gcc/combine.c1150
-rw-r--r--contrib/gcc/config.gcc1715
-rw-r--r--contrib/gcc/config.in138
-rw-r--r--contrib/gcc/config/alpha/alpha-interix.h79
-rw-r--r--contrib/gcc/config/alpha/alpha-protos.h79
-rw-r--r--contrib/gcc/config/alpha/alpha.c2046
-rw-r--r--contrib/gcc/config/alpha/alpha.h350
-rw-r--r--contrib/gcc/config/alpha/alpha.md1839
-rw-r--r--contrib/gcc/config/alpha/elf.h261
-rw-r--r--contrib/gcc/config/alpha/ev4.md147
-rw-r--r--contrib/gcc/config/alpha/ev5.md190
-rw-r--r--contrib/gcc/config/alpha/ev6.md173
-rw-r--r--contrib/gcc/config/alpha/freebsd.h25
-rw-r--r--contrib/gcc/config/alpha/gnu.h30
-rw-r--r--contrib/gcc/config/alpha/linux-elf.h14
-rw-r--r--contrib/gcc/config/alpha/linux.h27
-rw-r--r--contrib/gcc/config/alpha/netbsd.h63
-rw-r--r--contrib/gcc/config/alpha/openbsd.h11
-rw-r--r--contrib/gcc/config/alpha/osf.h38
-rw-r--r--contrib/gcc/config/alpha/osf5.h13
-rw-r--r--contrib/gcc/config/alpha/t-crtfm3
-rw-r--r--contrib/gcc/config/alpha/unicosmk.h122
-rw-r--r--contrib/gcc/config/alpha/vms-cc.c20
-rw-r--r--contrib/gcc/config/alpha/vms-crt0-64.c2
-rw-r--r--contrib/gcc/config/alpha/vms-crt0.c2
-rw-r--r--contrib/gcc/config/alpha/vms-ld.c3
-rw-r--r--contrib/gcc/config/alpha/vms-psxcrt0-64.c2
-rw-r--r--contrib/gcc/config/alpha/vms-psxcrt0.c2
-rw-r--r--contrib/gcc/config/alpha/vms.h47
-rw-r--r--contrib/gcc/config/alpha/vxworks.h12
-rw-r--r--contrib/gcc/config/arm/README-interworking2
-rw-r--r--contrib/gcc/config/arm/aof.h12
-rw-r--r--contrib/gcc/config/arm/aout.h27
-rw-r--r--contrib/gcc/config/arm/arm-modes.def46
-rw-r--r--contrib/gcc/config/arm/arm-protos.h21
-rw-r--r--contrib/gcc/config/arm/arm.c810
-rw-r--r--contrib/gcc/config/arm/arm.h373
-rw-r--r--contrib/gcc/config/arm/arm.md321
-rw-r--r--contrib/gcc/config/arm/coff.h38
-rw-r--r--contrib/gcc/config/arm/conix-elf.h8
-rw-r--r--contrib/gcc/config/arm/crti.asm2
-rw-r--r--contrib/gcc/config/arm/crtn.asm2
-rw-r--r--contrib/gcc/config/arm/elf.h55
-rw-r--r--contrib/gcc/config/arm/freebsd.h3
-rw-r--r--contrib/gcc/config/arm/linux-elf.h22
-rw-r--r--contrib/gcc/config/arm/linux-gas.h2
-rw-r--r--contrib/gcc/config/arm/netbsd-elf.h177
-rw-r--r--contrib/gcc/config/arm/netbsd.h54
-rw-r--r--contrib/gcc/config/arm/pe.c24
-rw-r--r--contrib/gcc/config/arm/pe.h31
-rw-r--r--contrib/gcc/config/arm/rtems-elf.h8
-rw-r--r--contrib/gcc/config/arm/semi.h4
-rw-r--r--contrib/gcc/config/arm/semiaof.h7
-rw-r--r--contrib/gcc/config/arm/t-arm-elf6
-rw-r--r--contrib/gcc/config/arm/t-pe3
-rw-r--r--contrib/gcc/config/arm/unknown-elf-oabi.h5
-rw-r--r--contrib/gcc/config/arm/unknown-elf.h10
-rw-r--r--contrib/gcc/config/arm/vxarm.h6
-rw-r--r--contrib/gcc/config/arm/xscale-coff.h2
-rw-r--r--contrib/gcc/config/arm/xscale-elf.h2
-rw-r--r--contrib/gcc/config/darwin-c.c3
-rw-r--r--contrib/gcc/config/darwin-crt2.c151
-rw-r--r--contrib/gcc/config/darwin-protos.h57
-rw-r--r--contrib/gcc/config/darwin.c297
-rw-r--r--contrib/gcc/config/darwin.h561
-rw-r--r--contrib/gcc/config/dbx.h4
-rw-r--r--contrib/gcc/config/dbxcoff.h5
-rw-r--r--contrib/gcc/config/dbxelf.h3
-rw-r--r--contrib/gcc/config/elfos.h264
-rw-r--r--contrib/gcc/config/fp-bit.c450
-rw-r--r--contrib/gcc/config/fp-bit.h176
-rw-r--r--contrib/gcc/config/freebsd-spec.h51
-rw-r--r--contrib/gcc/config/freebsd.h16
-rw-r--r--contrib/gcc/config/frv/cmovd.c47
-rw-r--r--contrib/gcc/config/frv/cmovh.c43
-rw-r--r--contrib/gcc/config/frv/cmovw.c47
-rw-r--r--contrib/gcc/config/frv/frv-abi.h181
-rw-r--r--contrib/gcc/config/frv/frv-asm.h49
-rw-r--r--contrib/gcc/config/frv/frv-modes.def30
-rw-r--r--contrib/gcc/config/frv/frv-protos.h247
-rw-r--r--contrib/gcc/config/frv/frv.c9788
-rw-r--r--contrib/gcc/config/frv/frv.h3592
-rw-r--r--contrib/gcc/config/frv/frv.md7441
-rw-r--r--contrib/gcc/config/frv/frvbegin.c150
-rw-r--r--contrib/gcc/config/frv/frvend.c63
-rw-r--r--contrib/gcc/config/frv/lib1funcs.asm275
-rw-r--r--contrib/gcc/config/frv/modi.c4
-rw-r--r--contrib/gcc/config/frv/t-frv93
-rw-r--r--contrib/gcc/config/frv/uitod.c4
-rw-r--r--contrib/gcc/config/frv/uitof.c4
-rw-r--r--contrib/gcc/config/frv/ulltod.c4
-rw-r--r--contrib/gcc/config/frv/ulltof.c4
-rw-r--r--contrib/gcc/config/frv/umodi.c4
-rw-r--r--contrib/gcc/config/gnu.h1
-rw-r--r--contrib/gcc/config/gofast.h22
-rw-r--r--contrib/gcc/config/i386/athlon.md206
-rw-r--r--contrib/gcc/config/i386/att.h7
-rw-r--r--contrib/gcc/config/i386/beos-elf.h52
-rw-r--r--contrib/gcc/config/i386/biarch64.h4
-rw-r--r--contrib/gcc/config/i386/bsd.h26
-rw-r--r--contrib/gcc/config/i386/crtdll.h7
-rw-r--r--contrib/gcc/config/i386/cygwin.h162
-rw-r--r--contrib/gcc/config/i386/darwin.h120
-rw-r--r--contrib/gcc/config/i386/djgpp.h67
-rw-r--r--contrib/gcc/config/i386/freebsd-aout.h134
-rw-r--r--contrib/gcc/config/i386/freebsd.h37
-rw-r--r--contrib/gcc/config/i386/freebsd64.h5
-rw-r--r--contrib/gcc/config/i386/gas.h44
-rw-r--r--contrib/gcc/config/i386/gnu.h27
-rw-r--r--contrib/gcc/config/i386/gstabs.h4
-rw-r--r--contrib/gcc/config/i386/gthr-win32.c174
-rw-r--r--contrib/gcc/config/i386/i386-aout.h12
-rw-r--r--contrib/gcc/config/i386/i386-coff.h45
-rw-r--r--contrib/gcc/config/i386/i386-interix.h168
-rw-r--r--contrib/gcc/config/i386/i386-interix3.h10
-rw-r--r--contrib/gcc/config/i386/i386-modes.def46
-rw-r--r--contrib/gcc/config/i386/i386-protos.h42
-rw-r--r--contrib/gcc/config/i386/i386.c4197
-rw-r--r--contrib/gcc/config/i386/i386.h1139
-rw-r--r--contrib/gcc/config/i386/i386.md5687
-rw-r--r--contrib/gcc/config/i386/i386elf.h10
-rw-r--r--contrib/gcc/config/i386/k6.md136
-rw-r--r--contrib/gcc/config/i386/linux-aout.h29
-rw-r--r--contrib/gcc/config/i386/linux.h49
-rw-r--r--contrib/gcc/config/i386/linux64.h41
-rw-r--r--contrib/gcc/config/i386/lynx-ng.h51
-rw-r--r--contrib/gcc/config/i386/lynx.h49
-rw-r--r--contrib/gcc/config/i386/mach.h17
-rw-r--r--contrib/gcc/config/i386/mingw32.h95
-rw-r--r--contrib/gcc/config/i386/mmintrin.h43
-rw-r--r--contrib/gcc/config/i386/moss.h16
-rw-r--r--contrib/gcc/config/i386/netbsd-elf.h51
-rw-r--r--contrib/gcc/config/i386/netbsd.h32
-rw-r--r--contrib/gcc/config/i386/netbsd64.h59
-rw-r--r--contrib/gcc/config/i386/openbsd.h26
-rw-r--r--contrib/gcc/config/i386/pentium.md312
-rw-r--r--contrib/gcc/config/i386/ppro.md150
-rw-r--r--contrib/gcc/config/i386/ptx4-i.h17
-rw-r--r--contrib/gcc/config/i386/rtemself.h21
-rw-r--r--contrib/gcc/config/i386/sco5.h196
-rw-r--r--contrib/gcc/config/i386/sol2.h124
-rw-r--r--contrib/gcc/config/i386/svr3dbx.h8
-rw-r--r--contrib/gcc/config/i386/svr3gas.h75
-rw-r--r--contrib/gcc/config/i386/sysv3.h29
-rw-r--r--contrib/gcc/config/i386/sysv4-cpp.h32
-rw-r--r--contrib/gcc/config/i386/sysv4.h12
-rw-r--r--contrib/gcc/config/i386/sysv5.h2
-rw-r--r--contrib/gcc/config/i386/t-cygwin2
-rw-r--r--contrib/gcc/config/i386/t-interix4
-rw-r--r--contrib/gcc/config/i386/t-linux646
-rw-r--r--contrib/gcc/config/i386/t-mingw323
-rw-r--r--contrib/gcc/config/i386/t-sco5gas2
-rw-r--r--contrib/gcc/config/i386/unix.h22
-rw-r--r--contrib/gcc/config/i386/uwin.h29
-rw-r--r--contrib/gcc/config/i386/vsta.h19
-rw-r--r--contrib/gcc/config/i386/vxi386.h52
-rw-r--r--contrib/gcc/config/i386/win32.h104
-rw-r--r--contrib/gcc/config/i386/winnt.c85
-rw-r--r--contrib/gcc/config/i386/x86-64.h15
-rw-r--r--contrib/gcc/config/i386/xm-vsta.h9
-rw-r--r--contrib/gcc/config/i386/xmmintrin.h1519
-rw-r--r--contrib/gcc/config/ia64/aix.h151
-rw-r--r--contrib/gcc/config/ia64/crtbegin.asm15
-rw-r--r--contrib/gcc/config/ia64/crtend.asm12
-rw-r--r--contrib/gcc/config/ia64/elf.h6
-rw-r--r--contrib/gcc/config/ia64/freebsd.h3
-rw-r--r--contrib/gcc/config/ia64/hpux.h160
-rw-r--r--contrib/gcc/config/ia64/hpux_longdouble.h14
-rw-r--r--contrib/gcc/config/ia64/ia64-c.c191
-rw-r--r--contrib/gcc/config/ia64/ia64-modes.def29
-rw-r--r--contrib/gcc/config/ia64/ia64-protos.h22
-rw-r--r--contrib/gcc/config/ia64/ia64.c1427
-rw-r--r--contrib/gcc/config/ia64/ia64.h329
-rw-r--r--contrib/gcc/config/ia64/ia64.md1207
-rw-r--r--contrib/gcc/config/ia64/linux.h13
-rw-r--r--contrib/gcc/config/ia64/quadlib.c19
-rw-r--r--contrib/gcc/config/ia64/sysv4.h162
-rw-r--r--contrib/gcc/config/ia64/t-aix6
-rw-r--r--contrib/gcc/config/ia64/t-hpux33
-rw-r--r--contrib/gcc/config/ia64/t-ia6428
-rw-r--r--contrib/gcc/config/ia64/unwind-ia64.c27
-rw-r--r--contrib/gcc/config/interix.h9
-rw-r--r--contrib/gcc/config/libgloss.h2
-rw-r--r--contrib/gcc/config/linux-aout.h8
-rw-r--r--contrib/gcc/config/linux.h18
-rw-r--r--contrib/gcc/config/lynx-ng.h10
-rw-r--r--contrib/gcc/config/lynx.h34
-rw-r--r--contrib/gcc/config/netbsd-aout.h84
-rw-r--r--contrib/gcc/config/netbsd-elf.h59
-rw-r--r--contrib/gcc/config/netbsd.h154
-rw-r--r--contrib/gcc/config/openbsd-oldgas.h23
-rw-r--r--contrib/gcc/config/openbsd.h67
-rw-r--r--contrib/gcc/config/psos.h6
-rw-r--r--contrib/gcc/config/ptx4.h31
-rw-r--r--contrib/gcc/config/rs6000/aix.h53
-rw-r--r--contrib/gcc/config/rs6000/aix31.h52
-rw-r--r--contrib/gcc/config/rs6000/aix41.h23
-rw-r--r--contrib/gcc/config/rs6000/aix43.h76
-rw-r--r--contrib/gcc/config/rs6000/aix51.h98
-rw-r--r--contrib/gcc/config/rs6000/aix52.h191
-rw-r--r--contrib/gcc/config/rs6000/altivec.h16
-rw-r--r--contrib/gcc/config/rs6000/altivec.md1915
-rw-r--r--contrib/gcc/config/rs6000/beos.h18
-rw-r--r--contrib/gcc/config/rs6000/darwin-tramp.asm2
-rw-r--r--contrib/gcc/config/rs6000/darwin.h66
-rw-r--r--contrib/gcc/config/rs6000/eabi.asm4
-rw-r--r--contrib/gcc/config/rs6000/eabi.h24
-rw-r--r--contrib/gcc/config/rs6000/eabiaix.h3
-rw-r--r--contrib/gcc/config/rs6000/eabisim.h16
-rw-r--r--contrib/gcc/config/rs6000/eabispe.h51
-rw-r--r--contrib/gcc/config/rs6000/freebsd.h11
-rw-r--r--contrib/gcc/config/rs6000/gnu.h2
-rw-r--r--contrib/gcc/config/rs6000/linux.h44
-rw-r--r--contrib/gcc/config/rs6000/linux64.h81
-rw-r--r--contrib/gcc/config/rs6000/lynx.h25
-rw-r--r--contrib/gcc/config/rs6000/mach.h15
-rw-r--r--contrib/gcc/config/rs6000/netbsd.h113
-rw-r--r--contrib/gcc/config/rs6000/ppc-asm.h39
-rw-r--r--contrib/gcc/config/rs6000/ppc64-fp.c146
-rw-r--r--contrib/gcc/config/rs6000/rs6000-c.c128
-rw-r--r--contrib/gcc/config/rs6000/rs6000-modes.def31
-rw-r--r--contrib/gcc/config/rs6000/rs6000-protos.h39
-rw-r--r--contrib/gcc/config/rs6000/rs6000.c4684
-rw-r--r--contrib/gcc/config/rs6000/rs6000.h685
-rw-r--r--contrib/gcc/config/rs6000/rs6000.md3855
-rw-r--r--contrib/gcc/config/rs6000/rtems.h14
-rw-r--r--contrib/gcc/config/rs6000/spe.h1096
-rw-r--r--contrib/gcc/config/rs6000/spe.md2488
-rw-r--r--contrib/gcc/config/rs6000/sysv4.h333
-rw-r--r--contrib/gcc/config/rs6000/sysv4le.h3
-rw-r--r--contrib/gcc/config/rs6000/t-aix4319
-rw-r--r--contrib/gcc/config/rs6000/t-aix5252
-rw-r--r--contrib/gcc/config/rs6000/t-darwin33
-rw-r--r--contrib/gcc/config/rs6000/t-linux643
-rw-r--r--contrib/gcc/config/rs6000/t-netbsd42
-rw-r--r--contrib/gcc/config/rs6000/t-ppccomm1
-rw-r--r--contrib/gcc/config/rs6000/t-ppcendian12
-rw-r--r--contrib/gcc/config/rs6000/t-rs6000-c-rule4
-rw-r--r--contrib/gcc/config/rs6000/vxppc.h23
-rw-r--r--contrib/gcc/config/rs6000/windiss.h47
-rw-r--r--contrib/gcc/config/rs6000/xcoff.h179
-rw-r--r--contrib/gcc/config/s390/fixdfdi.h7
-rw-r--r--contrib/gcc/config/s390/libgcc-glibc.ver20
-rw-r--r--contrib/gcc/config/s390/linux.h302
-rw-r--r--contrib/gcc/config/s390/s390-modes.def38
-rw-r--r--contrib/gcc/config/s390/s390-protos.h27
-rw-r--r--contrib/gcc/config/s390/s390.c3534
-rw-r--r--contrib/gcc/config/s390/s390.h1354
-rw-r--r--contrib/gcc/config/s390/s390.md3328
-rw-r--r--contrib/gcc/config/s390/t-crtstuff4
-rw-r--r--contrib/gcc/config/s390/t-linux649
-rw-r--r--contrib/gcc/config/sol2.h207
-rw-r--r--contrib/gcc/config/sparc/aout.h34
-rw-r--r--contrib/gcc/config/sparc/cypress.md51
-rw-r--r--contrib/gcc/config/sparc/freebsd.h14
-rw-r--r--contrib/gcc/config/sparc/gmon-sol2.c4
-rw-r--r--contrib/gcc/config/sparc/hypersparc.md83
-rw-r--r--contrib/gcc/config/sparc/lb1spc.asm8
-rw-r--r--contrib/gcc/config/sparc/lb1spl.asm2
-rw-r--r--contrib/gcc/config/sparc/linux-aout.h2
-rw-r--r--contrib/gcc/config/sparc/linux.h10
-rw-r--r--contrib/gcc/config/sparc/linux64.h24
-rw-r--r--contrib/gcc/config/sparc/litecoff.h14
-rw-r--r--contrib/gcc/config/sparc/liteelf.h6
-rw-r--r--contrib/gcc/config/sparc/lynx.h3
-rw-r--r--contrib/gcc/config/sparc/netbsd-elf.h120
-rw-r--r--contrib/gcc/config/sparc/netbsd.h27
-rw-r--r--contrib/gcc/config/sparc/openbsd.h6
-rw-r--r--contrib/gcc/config/sparc/pbd.h6
-rw-r--r--contrib/gcc/config/sparc/sol2-bi.h81
-rw-r--r--contrib/gcc/config/sparc/sol2.h177
-rw-r--r--contrib/gcc/config/sparc/sol26-sld.h6
-rw-r--r--contrib/gcc/config/sparc/sp64-elf.h2
-rw-r--r--contrib/gcc/config/sparc/sp86x-elf.h6
-rw-r--r--contrib/gcc/config/sparc/sparc-modes.def42
-rw-r--r--contrib/gcc/config/sparc/sparc-protos.h6
-rw-r--r--contrib/gcc/config/sparc/sparc.c1564
-rw-r--r--contrib/gcc/config/sparc/sparc.h407
-rw-r--r--contrib/gcc/config/sparc/sparc.md3030
-rw-r--r--contrib/gcc/config/sparc/sparclet.md44
-rw-r--r--contrib/gcc/config/sparc/sunos4.h2
-rw-r--r--contrib/gcc/config/sparc/supersparc.md93
-rw-r--r--contrib/gcc/config/sparc/sysv4.h34
-rw-r--r--contrib/gcc/config/sparc/ultra1_2.md252
-rw-r--r--contrib/gcc/config/sparc/ultra3.md169
-rw-r--r--contrib/gcc/config/sparc/vxsim.h4
-rw-r--r--contrib/gcc/config/sparc/vxsparc64.h4
-rw-r--r--contrib/gcc/config/svr3.h81
-rw-r--r--contrib/gcc/config/svr4.h27
-rw-r--r--contrib/gcc/config/t-darwin22
-rw-r--r--contrib/gcc/config/t-libc-ok2
-rw-r--r--contrib/gcc/config/t-linux4
-rw-r--r--contrib/gcc/config/t-linux-gnulibc12
-rw-r--r--contrib/gcc/config/t-netbsd3
-rwxr-xr-xcontrib/gcc/configure2433
-rw-r--r--contrib/gcc/configure.in777
-rw-r--r--contrib/gcc/conflict.c17
-rw-r--r--contrib/gcc/convert.c57
-rw-r--r--contrib/gcc/cp-demangle.c54
-rw-r--r--contrib/gcc/cp/ChangeLog3913
-rw-r--r--contrib/gcc/cp/ChangeLog.14
-rw-r--r--contrib/gcc/cp/ChangeLog.24
-rw-r--r--contrib/gcc/cp/Make-lang.in82
-rw-r--r--contrib/gcc/cp/NEWS4
-rw-r--r--contrib/gcc/cp/call.c1810
-rw-r--r--contrib/gcc/cp/cfns.gperf108
-rw-r--r--contrib/gcc/cp/class.c2197
-rw-r--r--contrib/gcc/cp/config-lang.in2
-rw-r--r--contrib/gcc/cp/cp-lang.c207
-rw-r--r--contrib/gcc/cp/cp-tree.def66
-rw-r--r--contrib/gcc/cp/cp-tree.h1318
-rw-r--r--contrib/gcc/cp/cvt.c159
-rw-r--r--contrib/gcc/cp/decl.c3706
-rw-r--r--contrib/gcc/cp/decl.h8
-rw-r--r--contrib/gcc/cp/decl2.c1862
-rw-r--r--contrib/gcc/cp/dump.c30
-rw-r--r--contrib/gcc/cp/error.c290
-rw-r--r--contrib/gcc/cp/except.c173
-rw-r--r--contrib/gcc/cp/expr.c27
-rw-r--r--contrib/gcc/cp/friend.c50
-rw-r--r--contrib/gcc/cp/g++spec.c29
-rw-r--r--contrib/gcc/cp/init.c1259
-rw-r--r--contrib/gcc/cp/lang-options.h4
-rw-r--r--contrib/gcc/cp/lang-specs.h25
-rw-r--r--contrib/gcc/cp/lex.c294
-rw-r--r--contrib/gcc/cp/lex.h6
-rw-r--r--contrib/gcc/cp/mangle.c424
-rw-r--r--contrib/gcc/cp/method.c245
-rw-r--r--contrib/gcc/cp/operators.def4
-rw-r--r--contrib/gcc/cp/optimize.c34
-rw-r--r--contrib/gcc/cp/parse.y953
-rw-r--r--contrib/gcc/cp/pt.c1222
-rw-r--r--contrib/gcc/cp/ptree.c18
-rw-r--r--contrib/gcc/cp/repo.c25
-rw-r--r--contrib/gcc/cp/rtti.c87
-rw-r--r--contrib/gcc/cp/search.c635
-rw-r--r--contrib/gcc/cp/semantics.c512
-rw-r--r--contrib/gcc/cp/spew.c530
-rw-r--r--contrib/gcc/cp/tree.c341
-rw-r--r--contrib/gcc/cp/typeck.c1838
-rw-r--r--contrib/gcc/cp/typeck2.c280
-rw-r--r--contrib/gcc/cplus-dem.c367
-rw-r--r--contrib/gcc/cppdefault.h42
-rw-r--r--contrib/gcc/cpperror.c250
-rw-r--r--contrib/gcc/cppexp.c2038
-rw-r--r--contrib/gcc/cppfiles.c178
-rw-r--r--contrib/gcc/cpphash.c3
-rw-r--r--contrib/gcc/cpphash.h247
-rw-r--r--contrib/gcc/cppinit.c1109
-rw-r--r--contrib/gcc/cpplex.c778
-rw-r--r--contrib/gcc/cpplib.c432
-rw-r--r--contrib/gcc/cpplib.h295
-rw-r--r--contrib/gcc/cppmacro.c761
-rw-r--r--contrib/gcc/cppmain.c360
-rw-r--r--contrib/gcc/cppspec.c36
-rw-r--r--contrib/gcc/cpptrad.c1216
-rw-r--r--contrib/gcc/crtstuff.c85
-rw-r--r--contrib/gcc/cse.c378
-rw-r--r--contrib/gcc/cselib.c98
-rw-r--r--contrib/gcc/cselib.h16
-rw-r--r--contrib/gcc/dbxout.c103
-rw-r--r--contrib/gcc/debug.c6
-rw-r--r--contrib/gcc/debug.h30
-rw-r--r--contrib/gcc/defaults.h237
-rw-r--r--contrib/gcc/demangle.h12
-rw-r--r--contrib/gcc/df.c542
-rw-r--r--contrib/gcc/df.h13
-rw-r--r--contrib/gcc/diagnostic.c1207
-rw-r--r--contrib/gcc/diagnostic.def16
-rw-r--r--contrib/gcc/diagnostic.h261
-rw-r--r--contrib/gcc/doc/bugreport.texi322
-rw-r--r--contrib/gcc/doc/c-tree.texi47
-rw-r--r--contrib/gcc/doc/collect2.texi2
-rw-r--r--contrib/gcc/doc/compat.texi4
-rw-r--r--contrib/gcc/doc/contrib.texi200
-rw-r--r--contrib/gcc/doc/cpp.texi588
-rw-r--r--contrib/gcc/doc/cppenv.texi24
-rw-r--r--contrib/gcc/doc/cppopts.texi114
-rw-r--r--contrib/gcc/doc/extend.texi1055
-rw-r--r--contrib/gcc/doc/frontends.texi7
-rw-r--r--contrib/gcc/doc/gcc.texi65
-rw-r--r--contrib/gcc/doc/gccint.texi58
-rw-r--r--contrib/gcc/doc/gcov.texi268
-rw-r--r--contrib/gcc/doc/gty.texi328
-rw-r--r--contrib/gcc/doc/headerdirs.texi2
-rw-r--r--contrib/gcc/doc/include/fdl.texi223
-rw-r--r--contrib/gcc/doc/include/gcc-common.texi7
-rw-r--r--contrib/gcc/doc/include/gpl.texi9
-rw-r--r--contrib/gcc/doc/include/texinfo.tex859
-rw-r--r--contrib/gcc/doc/interface.texi2
-rw-r--r--contrib/gcc/doc/invoke.texi2948
-rw-r--r--contrib/gcc/doc/makefile.texi14
-rw-r--r--contrib/gcc/doc/md.texi933
-rw-r--r--contrib/gcc/doc/objc.texi40
-rw-r--r--contrib/gcc/doc/passes.texi42
-rw-r--r--contrib/gcc/doc/rtl.texi213
-rw-r--r--contrib/gcc/doc/service.texi8
-rw-r--r--contrib/gcc/doc/sourcebuild.texi354
-rw-r--r--contrib/gcc/doc/standards.texi19
-rw-r--r--contrib/gcc/doc/tm.texi1456
-rw-r--r--contrib/gcc/doc/trouble.texi169
-rw-r--r--contrib/gcc/doloop.c69
-rw-r--r--contrib/gcc/dominance.c372
-rw-r--r--contrib/gcc/doschk.c6
-rw-r--r--contrib/gcc/dummy-conditions.c34
-rw-r--r--contrib/gcc/dwarf2.h6
-rw-r--r--contrib/gcc/dwarf2asm.c19
-rw-r--r--contrib/gcc/dwarf2asm.h28
-rw-r--r--contrib/gcc/dwarf2out.c944
-rw-r--r--contrib/gcc/dwarf2out.h2
-rw-r--r--contrib/gcc/dwarfout.c237
-rw-r--r--contrib/gcc/emit-rtl.c1818
-rw-r--r--contrib/gcc/errors.h2
-rw-r--r--contrib/gcc/et-forest.c680
-rw-r--r--contrib/gcc/et-forest.h83
-rw-r--r--contrib/gcc/except.c746
-rw-r--r--contrib/gcc/except.h25
-rw-r--r--contrib/gcc/explow.c132
-rw-r--r--contrib/gcc/expmed.c190
-rw-r--r--contrib/gcc/expr.c2040
-rw-r--r--contrib/gcc/expr.h50
-rw-r--r--contrib/gcc/f/ChangeLog552
-rw-r--r--contrib/gcc/f/ChangeLog.04
-rw-r--r--contrib/gcc/f/Make-lang.in54
-rw-r--r--contrib/gcc/f/bad.c7
-rw-r--r--contrib/gcc/f/bit.c1
-rw-r--r--contrib/gcc/f/bld.c1
-rw-r--r--contrib/gcc/f/bugs.texi7
-rw-r--r--contrib/gcc/f/com.c680
-rw-r--r--contrib/gcc/f/com.h54
-rw-r--r--contrib/gcc/f/config-lang.in4
-rw-r--r--contrib/gcc/f/data.c31
-rw-r--r--contrib/gcc/f/expr.c19
-rw-r--r--contrib/gcc/f/ffe.texi4
-rw-r--r--contrib/gcc/f/g77.texi486
-rw-r--r--contrib/gcc/f/g77spec.c36
-rw-r--r--contrib/gcc/f/intdoc.in75
-rw-r--r--contrib/gcc/f/intdoc.texi73
-rw-r--r--contrib/gcc/f/invoke.texi28
-rw-r--r--contrib/gcc/f/lang-specs.h9
-rw-r--r--contrib/gcc/f/lex.c50
-rw-r--r--contrib/gcc/f/news.texi74
-rw-r--r--contrib/gcc/f/parse.c11
-rw-r--r--contrib/gcc/f/root.texi9
-rw-r--r--contrib/gcc/f/stc.c15
-rw-r--r--contrib/gcc/f/std.c6
-rw-r--r--contrib/gcc/f/ste.c48
-rw-r--r--contrib/gcc/f/target.c20
-rw-r--r--contrib/gcc/f/target.h349
-rw-r--r--contrib/gcc/f/top.c1
-rw-r--r--contrib/gcc/f/where.c134
-rw-r--r--contrib/gcc/f/where.h6
-rw-r--r--contrib/gcc/fibheap.c2
-rw-r--r--contrib/gcc/fibheap.h4
-rw-r--r--contrib/gcc/final.c544
-rw-r--r--contrib/gcc/fix-header.c29
-rwxr-xr-xcontrib/gcc/fixproto4
-rw-r--r--contrib/gcc/flags.h91
-rw-r--r--contrib/gcc/flow.c373
-rw-r--r--contrib/gcc/fold-const.c1788
-rw-r--r--contrib/gcc/function.c799
-rw-r--r--contrib/gcc/function.h110
-rw-r--r--contrib/gcc/gbl-ctors.h9
-rw-r--r--contrib/gcc/gcc.c970
-rw-r--r--contrib/gcc/gcc.h33
-rwxr-xr-xcontrib/gcc/gccbug.in2
-rw-r--r--contrib/gcc/gccspec.c8
-rw-r--r--contrib/gcc/gcov-io.h133
-rw-r--r--contrib/gcc/gcov.c1370
-rw-r--r--contrib/gcc/gcse.c2041
-rw-r--r--contrib/gcc/gdbinit.in13
-rw-r--r--contrib/gcc/genattr.c141
-rw-r--r--contrib/gcc/genattrtab.c263
-rw-r--r--contrib/gcc/genattrtab.h43
-rw-r--r--contrib/gcc/genautomata.c9742
-rw-r--r--contrib/gcc/gencodes.c24
-rw-r--r--contrib/gcc/genconditions.c240
-rw-r--r--contrib/gcc/genconfig.c4
-rw-r--r--contrib/gcc/genemit.c67
-rw-r--r--contrib/gcc/genflags.c67
-rw-r--r--contrib/gcc/gengenrtl.c114
-rw-r--r--contrib/gcc/gengtype-lex.l328
-rw-r--r--contrib/gcc/gengtype-yacc.y300
-rw-r--r--contrib/gcc/gengtype.c2625
-rw-r--r--contrib/gcc/gengtype.h181
-rw-r--r--contrib/gcc/genopinit.c2
-rw-r--r--contrib/gcc/genpreds.c2
-rw-r--r--contrib/gcc/genrecog.c44
-rw-r--r--contrib/gcc/gensupport.c409
-rw-r--r--contrib/gcc/gensupport.h42
-rw-r--r--contrib/gcc/getopt.c6
-rw-r--r--contrib/gcc/getopt.h19
-rw-r--r--contrib/gcc/getruntime.c116
-rw-r--r--contrib/gcc/ggc-common.c716
-rw-r--r--contrib/gcc/ggc-none.c15
-rw-r--r--contrib/gcc/ggc-page.c521
-rw-r--r--contrib/gcc/ggc-simple.c46
-rw-r--r--contrib/gcc/ggc.h159
-rw-r--r--contrib/gcc/ginclude/float.h162
-rw-r--r--contrib/gcc/ginclude/stdarg.h15
-rw-r--r--contrib/gcc/ginclude/varargs.h141
-rw-r--r--contrib/gcc/glimits.h98
-rw-r--r--contrib/gcc/global.c133
-rw-r--r--contrib/gcc/graph.c9
-rw-r--r--contrib/gcc/graph.h2
-rw-r--r--contrib/gcc/gthr-dce.h104
-rw-r--r--contrib/gcc/gthr-posix.h212
-rw-r--r--contrib/gcc/gthr-rtems.h2
-rw-r--r--contrib/gcc/gthr-single.h46
-rw-r--r--contrib/gcc/gthr-solaris.h101
-rw-r--r--contrib/gcc/gthr-vxworks.h58
-rw-r--r--contrib/gcc/gthr-win32.h263
-rw-r--r--contrib/gcc/gthr.h2
-rw-r--r--contrib/gcc/haifa-sched.c813
-rw-r--r--contrib/gcc/hard-reg-set.h15
-rw-r--r--contrib/gcc/hashtab.c88
-rw-r--r--contrib/gcc/hashtab.h41
-rw-r--r--contrib/gcc/hashtable.c8
-rw-r--r--contrib/gcc/hashtable.h7
-rw-r--r--contrib/gcc/hex.c81
-rw-r--r--contrib/gcc/hooks.c81
-rw-r--r--contrib/gcc/hooks.h19
-rw-r--r--contrib/gcc/hwint.h15
-rw-r--r--contrib/gcc/ifcvt.c973
-rw-r--r--contrib/gcc/input.h1
-rw-r--r--contrib/gcc/insn-addr.h4
-rw-r--r--contrib/gcc/integrate.c171
-rw-r--r--contrib/gcc/integrate.h2
-rw-r--r--contrib/gcc/jump.c92
-rw-r--r--contrib/gcc/langhooks-def.h123
-rw-r--r--contrib/gcc/langhooks.c189
-rw-r--r--contrib/gcc/langhooks.h219
-rw-r--r--contrib/gcc/lbasename.c16
-rw-r--r--contrib/gcc/lcm.c470
-rw-r--r--contrib/gcc/libfuncs.h2
-rw-r--r--contrib/gcc/libgcc-std.ver9
-rw-r--r--contrib/gcc/libgcc2.c593
-rw-r--r--contrib/gcc/libgcc2.h19
-rw-r--r--contrib/gcc/libiberty.h20
-rw-r--r--contrib/gcc/line-map.h2
-rw-r--r--contrib/gcc/lists.c37
-rw-r--r--contrib/gcc/local-alloc.c93
-rw-r--r--contrib/gcc/location.h38
-rw-r--r--contrib/gcc/longlong.h413
-rw-r--r--contrib/gcc/loop.c815
-rw-r--r--contrib/gcc/loop.h16
-rw-r--r--contrib/gcc/machmode.def21
-rw-r--r--contrib/gcc/machmode.h9
-rw-r--r--contrib/gcc/mbchar.c4
-rw-r--r--contrib/gcc/md5.c114
-rw-r--r--contrib/gcc/mkconfig.sh16
-rw-r--r--contrib/gcc/mkheaders.in101
-rw-r--r--contrib/gcc/mklibgcc.in23
-rw-r--r--contrib/gcc/mkmap-symver.awk14
-rw-r--r--contrib/gcc/objc/Make-lang.in13
-rw-r--r--contrib/gcc/objc/config-lang.in2
-rw-r--r--contrib/gcc/objc/lang-specs.h14
-rw-r--r--contrib/gcc/objc/objc-act.c865
-rw-r--r--contrib/gcc/objc/objc-act.h21
-rw-r--r--contrib/gcc/objc/objc-lang.c100
-rw-r--r--contrib/gcc/optabs.c795
-rw-r--r--contrib/gcc/optabs.h15
-rw-r--r--contrib/gcc/output.h82
-rw-r--r--contrib/gcc/params.c9
-rw-r--r--contrib/gcc/params.def168
-rw-r--r--contrib/gcc/params.h18
-rw-r--r--contrib/gcc/partition.h8
-rw-r--r--contrib/gcc/physmem.c305
-rw-r--r--contrib/gcc/predict.c804
-rw-r--r--contrib/gcc/predict.def19
-rw-r--r--contrib/gcc/predict.h3
-rw-r--r--contrib/gcc/prefix.c76
-rw-r--r--contrib/gcc/pretty-print.h100
-rw-r--r--contrib/gcc/print-rtl.c109
-rw-r--r--contrib/gcc/print-tree.c68
-rw-r--r--contrib/gcc/profile.c477
-rw-r--r--contrib/gcc/profile.h54
-rw-r--r--contrib/gcc/protoize.c1548
-rw-r--r--contrib/gcc/ra-build.c3274
-rw-r--r--contrib/gcc/ra-colorize.c2742
-rw-r--r--contrib/gcc/ra-debug.c1120
-rw-r--r--contrib/gcc/ra-rewrite.c1987
-rw-r--r--contrib/gcc/ra.c899
-rw-r--r--contrib/gcc/ra.h624
-rw-r--r--contrib/gcc/read-rtl.c23
-rw-r--r--contrib/gcc/real.c9558
-rw-r--r--contrib/gcc/real.h680
-rw-r--r--contrib/gcc/recog.c376
-rw-r--r--contrib/gcc/recog.h5
-rw-r--r--contrib/gcc/reg-stack.c179
-rw-r--r--contrib/gcc/regclass.c368
-rw-r--r--contrib/gcc/regmove.c71
-rw-r--r--contrib/gcc/regrename.c198
-rw-r--r--contrib/gcc/regs.h11
-rw-r--r--contrib/gcc/reload.c346
-rw-r--r--contrib/gcc/reload.h4
-rw-r--r--contrib/gcc/reload1.c356
-rw-r--r--contrib/gcc/reorg.c64
-rw-r--r--contrib/gcc/resource.c69
-rw-r--r--contrib/gcc/rtl-error.c23
-rw-r--r--contrib/gcc/rtl.c141
-rw-r--r--contrib/gcc/rtl.def209
-rw-r--r--contrib/gcc/rtl.h731
-rw-r--r--contrib/gcc/rtlanal.c591
-rw-r--r--contrib/gcc/sbitmap.c388
-rw-r--r--contrib/gcc/sbitmap.h55
-rw-r--r--contrib/gcc/scan-decls.c4
-rw-r--r--contrib/gcc/scan.c4
-rw-r--r--contrib/gcc/sched-deps.c49
-rw-r--r--contrib/gcc/sched-ebb.c35
-rw-r--r--contrib/gcc/sched-int.h12
-rw-r--r--contrib/gcc/sched-rgn.c307
-rw-r--r--contrib/gcc/sched-vis.c44
-rw-r--r--contrib/gcc/sdbout.c71
-rw-r--r--contrib/gcc/sibcall.c52
-rw-r--r--contrib/gcc/simplify-rtx.c777
-rw-r--r--contrib/gcc/splay-tree.c6
-rw-r--r--contrib/gcc/splay-tree.h4
-rw-r--r--contrib/gcc/ssa-ccp.c76
-rw-r--r--contrib/gcc/ssa-dce.c55
-rw-r--r--contrib/gcc/ssa.c344
-rw-r--r--contrib/gcc/ssa.h5
-rw-r--r--contrib/gcc/stab.def10
-rw-r--r--contrib/gcc/stmt.c816
-rw-r--r--contrib/gcc/stor-layout.c540
-rw-r--r--contrib/gcc/stringpool.c4
-rw-r--r--contrib/gcc/system.h45
-rw-r--r--contrib/gcc/target-def.h126
-rw-r--r--contrib/gcc/target.h130
-rw-r--r--contrib/gcc/timevar.c45
-rw-r--r--contrib/gcc/timevar.def5
-rw-r--r--contrib/gcc/timevar.h9
-rw-r--r--contrib/gcc/tlink.c242
-rw-r--r--contrib/gcc/toplev.c1430
-rw-r--r--contrib/gcc/toplev.h17
-rw-r--r--contrib/gcc/tracer.c378
-rw-r--r--contrib/gcc/tree-dump.c204
-rw-r--r--contrib/gcc/tree-dump.h16
-rw-r--r--contrib/gcc/tree-inline.c579
-rw-r--r--contrib/gcc/tree-inline.h4
-rw-r--r--contrib/gcc/tree.c687
-rw-r--r--contrib/gcc/tree.def33
-rw-r--r--contrib/gcc/tree.h475
-rw-r--r--contrib/gcc/tsystem.h11
-rw-r--r--contrib/gcc/unroll.c534
-rw-r--r--contrib/gcc/unwind-c.c186
-rw-r--r--contrib/gcc/unwind-dw2-fde-darwin.c241
-rw-r--r--contrib/gcc/unwind-dw2-fde-glibc.c8
-rw-r--r--contrib/gcc/unwind-dw2-fde.c123
-rw-r--r--contrib/gcc/unwind-dw2-fde.h18
-rw-r--r--contrib/gcc/unwind-dw2.c243
-rw-r--r--contrib/gcc/unwind-pe.h16
-rw-r--r--contrib/gcc/unwind-sjlj.c24
-rw-r--r--contrib/gcc/unwind.h40
-rw-r--r--contrib/gcc/unwind.inc72
-rw-r--r--contrib/gcc/varasm.c2172
-rw-r--r--contrib/gcc/varray.c72
-rw-r--r--contrib/gcc/varray.h167
-rw-r--r--contrib/gcc/version.c16
-rw-r--r--contrib/gcc/version.h3
-rw-r--r--contrib/gcc/vmsdbg.h4
-rw-r--r--contrib/gcc/vmsdbgout.c222
-rw-r--r--contrib/gcc/xcoffout.c5
-rw-r--r--contrib/gcc/xcoffout.h29
-rw-r--r--contrib/gcc/xmemdup.c38
726 files changed, 201558 insertions, 85638 deletions
diff --git a/contrib/gcc/ChangeLog b/contrib/gcc/ChangeLog
index c8f8970..c6496ff 100644
--- a/contrib/gcc/ChangeLog
+++ b/contrib/gcc/ChangeLog
@@ -1,12039 +1,16664 @@
-2003-02-05 Release Manager
+2003-07-09 Mark Mitchell <mark@codesourcery.com>
- * GCC 3.2.2 Released.
+ PR c++/10032
+ * doc/invoke.texi (C++ Dialect Options): Change documentation of
+ -fpermissive.
-2003-02-03 Chris Lingard <chris@stockwith.co.uk>
- Dan Osterrath <do3@mail.inf.tu-dresden.de>
+2003-07-10 Matt Kraai <kraai@alumni.cmu.edu>
- * configure.in: Handle binutils versions with 4 dot separated
- numbers.
- * configure: Rebuilt.
+ * doc/invoke.texi: Fix misspelling of "@item".
-2003-02-03 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+2003-07-09 Hans-Peter Nilsson <hp@bitrange.com>
- Backport following patch:
+ * doc/install.texi (Configuration): Document the valgrind option
+ to --enable-checking.
- 2002-08-01 Richard Henderson <rth@redhat.com>
+2003-07-08 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
- * integrate.c (copy_rtx_and_substitute): Squash MEM_EXPR when it
- refers to a subroutine parameter.
+ PR Target/11453
+ * pa.md: Disparage all mtsar constraints.
+ (extzv, extv, insv): Don't fail on length of {32|64}.
-2003-02-03 Eric Botcazou <ebotcazou@libertysurf.fr>
+2003-07-08 James E Wilson <wilson@tuliptree.org>
- PR ice-on-legal-code/9493
- * cfgcleanup.c (try_forward_edges): Check for null insn.
+ PR target/10021
+ * emit-rtl.c (set_mem_attribute_minus_bitpos): When handle ARRAY_REF,
+ loop over new variable t2 instead of t.
-2003-02-03 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
- Eric Botcazou <ebotcazou@libertysurf.fr>
+2003-07-08 Stephane Carrez <stcarrez@nerim.fr>
- PR wrong-code/9492
- Backport following patches:
+ * config/m68hc11/m68hc11.h (HAVE_AS_DWARF2_DEBUG_LINE): Don't define
+ as .file/.loc directives are incompatible with linker relaxation.
- 2002-09-16 Richard Henderson <rth@redhat.com>
+2003-07-08 Jakub Jelinek <jakub@redhat.com>
- * emit-rtl.c (set_mem_attributes_minus_bitpos): Adjust SIZE
- as well as OFFSET for BITPOS.
+ PR c/11420
+ * config/i386/i386.c (ix86_check_movabs): New function.
+ * config/i386/i386-protos.h (ix86_check_movabs): New prototype.
+ * config/i386/i386.md (movabs[shqd]i_1_rex64): Kill broken alternative.
+ (movabs[shqd]i_[12]_rex64): Add ix86_check_movabs check to conditions.
- 2002-09-08 Jan Hubicka <jh@suse.cz>
+ * config/i386/i386.md (movdi_1_rex64): Set Y<-m alternative's type
+ to ssemov.
- * emit-rtl.c (set_mem_attributes_minus_bitpos): Fix array_ref
- handling.
+2003-07-08 Jakub Jelinek <jakub@redhat.com>
- 2002-07-29 Richard Henderson <rth@redhat.com>
+ * unroll.c (reg_dead_after_loop): Check for reg in REG_EQUAL and
+ REG_EQUIV notes as well.
- * emit-rtl.c (set_mem_attributes_minus_bitpos): Rename from
- set_mem_attributes and add BITPOS argument. Subtract it from
- OFFSET when same is adjusted.
- (set_mem_attributes): New wrapper function.
- * expr.c (expand_assignment): Use set_mem_attributes_minus_bitpos;
- remove offset adjustment hack.
- * expr.h (set_mem_attributes_minus_bitpos): Declare.
+2003-07-07 Dale Johannesen <dalej@apple.com>
- 2002-07-25 Richard Henderson <rth@redhat.com>
+ PR 10900
+ * config/rs6000/darwin-tramp.asm: Fix trampolines.
- * emit-rtl.c (set_mem_attributes): Fix size and alignment thinkos
- in ARRAY_REF of DECL_P case.
+2003-07-07 Andrew Pinski <pinskia@physics.uc.edu>
- 2002-07-21 Richard Henderson <rth@redhat.com>
+ PR optimization/11368
+ * doc/invoke.texi (-falign-functions): Document that
+ when n is zero then a machine-dependent default is used.
+ (-falign-labels): Document that when n is zero then a
+ machine-dependent default is used and that -falign-labels =1
+ is equivalent to -fno-align-labels.
+ (-falign-loops): Likewise.
+ (-falign-jumps): Likewise.
- * emit-rtl.c (set_mem_attributes): Preserve indirection of PARM_DECL
- when flag_argument_noalias == 2.
- * alias.c (nonoverlapping_memrefs_p): Handle that.
- * print-rtl.c (print_mem_expr): Likewise.
+2003-07-07 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ Eric Botcazou <ebotcazou@libertysurf.fr>
- 2002-06-03 Dan Nicolaescu <dann@godzilla.ics.uci.edu>
+ PR optimization/11198
+ * alias.c (objects_must_conflict_p): Return 1 if the types have
+ the same alias set, not if the alias sets only conflict.
- * alias.c (nonoverlapping_memrefs_p): Fix off by one error.
+2003-07-06 Matthias Klose <doko@debian.org>
-2003-02-03 Steve Ellcey <sje@cup.hp.com>
+ Backport from mainline:
- * config/pa/pa64-hpux.h (INIT_ENVIRONMENT): New.
+ 2003-07-04 Zack Weinberg <zack@codesourcery.com>
-2003-02-01 Jakub Jelinek <jakub@redhat.com>
+ * doc/extend.texi: Delete entire section on multiline strings.
- PR preprocessor/9465
- * tradcpp.c (fixup_newlines): Use memchr instead of strchr.
+2003-07-04 H.J. Lu <hongjiu.lu@intel.com>
-2003-01-31 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
+ * Makefile.in: Replace PWD with PWD_COMMAND.
- * pa.c (pa_output_function_prologue, pa_output_function_epilogue): Move
- updating of total_code_bytes from prologue to epilogue.
- (get_last_nonnote_insn): New function.
+2003-07-03 Eric Botcazou <ebotcazou@libertysurf.fr>
-2003-01-31 Jan Hubicka <jh@suse.cz>
+ PR optimization/11304
+ Backport from mainline:
- PR c/9506
- * i386.c (override_options): Use DEFAULT_PCC_STRUCT_RETURN.
+ 2003-04-18 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
-2003-01-30 Andreas Schwab <schwab@suse.de>
+ * cfgcleanup.c (flow_find_cross_jump): Use INSN_P, not active_insn_p.
- * config/m68k/m68k.md (tablejump+2): Don't sign extend an address
- register.
- * config/m68k/apollo68.h (ASM_RETURN_CASE_JUMP): Likewise.
- * config/m68k/coff.h (ASM_RETURN_CASE_JUMP): Likewise.
- * config/m68k/linux.h (ASM_RETURN_CASE_JUMP): Likewise.
- * config/m68k/m68kelf.h (ASM_RETURN_CASE_JUMP): Likewise.
- * config/m68k/mot3300.h (ASM_RETURN_CASE_JUMP): Likewise.
- * config/m68k/netbsd-elf.h (ASM_RETURN_CASE_JUMP): Likewise.
- * config/m68k/pbb.h (ASM_RETURN_CASE_JUMP): Likewise.
+2003-07-03 Roger Sayle <roger@eyesopen.com>
-2003-01-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+ PR target/10700
+ * fold-const.c (extract_muldiv_1): There's nothing that can be done
+ if the expression is a SAVE_EXPR.
- PR target/9316
- * config/rs6000/rtems.h: Add CPP_OS_DEFAULT_SPEC.
- * config/rs6000/sysv4.h: Add CPP_OS_RTEMS_SPEC.
- * config/rs6000/t-rtems: New file. multilib variants to match OS.
- * config.gcc (powerpc-*-rtems*): Use rs6000/t-rtems instead of
- rs6000/t-ppcgas so we get the desired multilibs.
+2003-07-03 Eric Botcazou <ebotcazou@libertysurf.fr>
-2003-01-29 Joel Sherrill <joel@OARcorp.com>
+ PR optimization/11381
+ * simplify-rtx.c (simplify_relational_operation): Check that
+ two equal operands have no side-effects before simplifying
+ the comparison.
- PR bootstrap/9296
- * gthr-rtems.h: Define __GTHREAD_MUTEX_INIT. Apparently no code
- depended on it being defined until now.
+2003-07-01 Zack Weinberg <zack@codesourcery.com>
-2003-01-29 Joel Sherrill <joel@OARcorp.com>
+ PR 2873
+ * fixinc/inclhack.def (avoid_wchar_t_type): Add bypass
+ expressions to prevent triggering on recent curses.h,
+ linux/nls.h, or X11/Xlib.h.
+ (stdio_va_list): Add _G_va_list to bypass pattern.
+ (strict_ansi_not): Add bypass pattern for __SCO_VERSION__.
+ * fixinc/fixincl.x: Regenerate.
- PR target/9295
- * config/mips/rtems.h: Predefine __USE_INIT_FINI__ so generic
- RTEMS code knows which C++ initialization style the toolset
- configuration is using.
+2003-07-02 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
-2003-01-29 Joel Sherrill <joel@OARcorp.com>
+ * fixinc/inclhack.def (irix_stdio_va_list): Apply to IRIX 6.5
+ <internal/stdio_core.h> too.
+ (stdio_va_list): Apply to IRIX 6.5 <internal/stdio_core.h> and
+ <internal/wchar_core.h> too.
+ Substitute va_list uses in inline definition.
+ * fixinc/fixincl.x: Regenerate.
- PR bootstrap/9293
- * config/m68k/t-crtstuff: Replace spaces with tabs, add
- $(MULTILIB_CFLAGS) as compiler option and multilib crtbegin/end.o.
+2003-07-01 Richard Henderson <rth@redhat.com>
+ (blame to: Loren James Rittle <ljrittle@acm.org>)
-2003-01-29 Joel Sherrill <joel@OARcorp.com>
+ * real.h (ieee_extended_intel_96_round_53_format): New.
+ * real.c (ieee_extended_intel_96_round_53_format): New.
+ * config/i386/freebsd.h (SUBTARGET_OVERRIDE_OPTIONS): Use it
+ for XFmode and TFmode.
- PR bootstrap/9292
- * config.gcc (hppa1.1-rtems): Did not include t-rtems nor enable
- RTEMS threads.
- * config/pa/rtems.h (LIB_SPEC): Use -N when linking.
+2003-07-01 Kazu Hirata <kazu@cs.umass.edu>
-2003-01-28 Christian Cornelssen <ccorn@cs.tu-berlin.de>
+ * doc/contrib.texi: Fix typos.
+ * doc/sourcebuild.texi: Likewise.
- * doc/install.texi: Add documentation for installation into
- tooldirs and with DESTDIR.
+2003-06-29 Aaron W. LaFramboise <awlaframboise@aol.com>
- * Makefile.in (ORDINARY_FLAGS_TO_PASS): Also pass DESTDIR.
- (install-cpp, uninstall-cpp, installdirs, install-common)
- (install-driver, install-info, install-man)
- (install-headers, install-include-dir, install-headers-tar)
- (install-headers-cpio, install-headers-cp, install-collect2)
- (uninstall): Prepend $(DESTDIR) to destination paths in all
- (un)installation commands.
- (install-driver): Rewrite $(LN) commands to support DESTDIR
- with "ln" as well as with "ln -s".
- (installdirs): Simply use mkinstalldirs.
- (install-libgcc, install-multilib): Also pass DESTDIR.
- * mklibgcc.in: Prepend $(DESTDIR) to $(libsubdir) in the
- installation destination variable ldir.
- * config/alpha/t-osf4 (SHLIB_INSTALL): Prepend $$(DESTDIR)
- to $$(slibdir) in the installation commands.
- * config/arm/t-netbsd (SHLIB_INSTALL): Likewise.
- * config/mips/t-iris6 (SHLIB_INSTALL): Likewise.
- * config/pa/t-hpux-shlib (SHLIB_INSTALL): Likewise.
- * config/rs6000/t-aix43 (SHLIB_INSTALL): Likewise.
- * config/t-slibgcc-elf-ver (SHLIB_INSTALL): Likewise.
- * config/t-slibgcc-sld (SHLIB_INSTALL): Likewise.
- * config/arc/t-arc (install-multilib-arc): Prepend $(DESTDIR) to
- $(libsubdir) in the installation commands.
+ * config/i386/gthr-win32.h (__GTHREAD_HIDE_WIN32API): Define to 1.
-2003-01-28 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
- Backport patches
-
- 2002-10-04 Loren J. Rittle <ljrittle@acm.org>
+2003-06-27 Gunther Nikl <gni@gecko.de>
- * gcc/ginclude/stddef.h: Support the FreeBSD 5 typedef system.
+ PR target/11014
+ * config/m68k/m68k.c (m68k_output_mi_thunk): Use correct assembly
+ syntax for MIT / MOTOROLA.
- 2002-08-01 Stan Shebs <shebs@apple.com>
- Andreas Tobler <toa@pop.agri.ch>
+2003-06-27 Ulrich Weigand <uweigand@de.ibm.com>
- * ginclude/stddef.h (_BSD_SIZE_T_DEFINED_): Define if not defined,
- plays nice with Darwin headers.
- (_BSD_RUNE_T_DEFINED_): Likewise.
-
-2003-01-27 Gabriel Dos_Reis <gdosreis@sophia.inria.fr>
-
- PR objc/9267
- * c-parse.in: Remove '%expect 31' directive in objc mode.
+ * config/s390/s390.h (SECONDARY_OUTPUT_RELOAD_CLASS): Define.
+ * config/s390/s390.c (s390_secondary_output_reload_class): New function.
+ * config/s390/s390-protos.h (s390_secondary_output_reload_class):
+ Declare it.
+ * config/s390/s390.md ("reload_outti", "reload_outdi",
+ "reload_outdf"): New expanders.
-2003-01-27 Richard Earnshaw <rearnsha@arm.com>
-
- * function.c (purge_addressof_1): After pushing anaddressed register
- onto the stack, simplify the result.
-
-2003-01-25 Eric Botcazou <ebotcazou@libertysurf.fr>
+ * config/s390/s390.md ("movti" + splitters): Handle non-offsettable
+ memory operands as source.
+ ("movdi" + splitters): Likewise.
+ ("movdf" + splitters): Likewise.
+ * config/s390/s390.c (s390_split_ok_p): New function.
+ * config/s390/s390-protos.h (s390_split_ok_p): Declare it.
- * combine.c (nonzero_bits): Revert 2003-01-25 change.
- (num_sign_bit_copies): Likewise.
+2003-06-27 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
-2003-01-27 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
+ * config/mips/mips.md (trap): Use break 0 when !TARGET_GAS.
- * doc/passes.texi: Fix typo.
+ * config/mips/iris6-o32.h (MIPS_ISA_DEFAULT): Remove.
+ (MIPS_CPU_STRING_DEFAULT): Redefine to mips2.
-2003-01-25 Bruce Korb <bkorb@gnu.org>
+ * config/mips/mips.c (TARGET_ASM_UNALIGNED_DI_OP) [TARGET_IRIX5 &&
+ !TARGET_IRIX6]: Define as NULL.
- * fixinc/fixfixes.c(wrap_fix): the wrapper guard must be a function
- of *both* the file name and the fix name.
+ * config/mips/iris5gas.h (MDEBUG_ASM_SPEC): Override to match
+ DWARF 2 default.
-2003-01-25 Eric Botcazou <ebotcazou@libertysurf.fr>
- Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de>
+ * config/mips/dbxmdebug.h: New file.
+ * config.gcc (mips-sgi-irix6*o32, mips-sgi-irix5*): Use it with
+ gas and --with-stabs.
- PR optimization/9279
+2003-06-27 Andreas Schwab <schwab@suse.de>
- Merge from mainline:
+ * config.gcc (m68k-*-linux*): Don't override extra_parts and
+ gnu_ld, use the generic *-*-linux* settings instead.
- 2002-07-10 Roger Sayle <roger@eyesopen.com>
+2003-06-26 Roger Sayle <roger@eyesopen.com>
- PR c/2454
- * combine.c (nonzero_bits): LOAD_EXTEND_OP should only apply
- to SUBREGs of MEMs. (num_sign_bit_copies): Likewise.
+ PR optimization/11054
+ * rtlanal.c (reg_overlap_mentioned_p): Handle ZERO_EXTRACT
+ and SIGN_EXTRACT.
-2003-01-25 Jan Hubicka <jh@suse.cz>
+2003-06-25 Zack Weinberg <zack@codesourcery.com>
- PR fortran/9258
- * global.c (struct allocno): Add no_stack_reg.
- (global_conflicts): Set no_stack_reg.
- (find_reg): Use it.
+ PR bootstrap/3163
+ * aclocal.m4 (AC_FUNC_MMAP_ANYWHERE, AC_FUNC_MMAP_FILE): Delete.
+ (gcc_AC_FUNC_MMAP_BLACKLIST): New.
+ * configure.in: Check for sys/mman.h and mmap in AC_CHECK_HEADERS
+ and AC_CHECK_FUNCS lists, respectively. Use
+ gcc_AC_FUNC_MMAP_BLACKLIST, not AC_FUNC_MMAP_ANYWHERE nor
+ AC_FUNC_MMAP_FILE.
+ * configure, config.in: Regenerate.
-2003-01-24 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
+ * ggc-page.c (init_gcc): Call fatal_io_error, not abort,
+ if opening /dev/zero fails.
- * doc/passes.texi: Fix typo.
+2003-06-25 Roger Sayle <roger@eyesopen.com>
-2003-01-24 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
+ * builtins.c (expand_builtin_strcpy): Construct new argument list
+ manually instead of using chainon to modify the original arglist.
+ (expand_builtin_strcmp): Likewise.
- * pa.md (call_internal_reg, call_value_internal_reg): If TARGET_GAS and
- not TARGET_SOM, use $PIC_pcrel$0 rather than symbol difference for long
- PIC calls to $$dyncall.
- * pa.c (output_call): Likewise.
+2003-06-25 David O'Brien <obrien@FreeBSD.org>
-2003-01-23 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+ * config/i386/i386.h (builtin_define): Remove duplicate __amd64
+ and __amd64__.
- PR java/6748
- * config/rs6000/linux.h (MD_FALLBACK_FRAME_STATE_FOR): Don't destroy
- regs->nip. Fix rt_sigreturn frame layout. Add support for newer
- kernels.
+2003-06-25 Dhananjay Deshpande <dhananjayd@kpitcummins.com>
- * config/rs6000/rs6000.c (rs6000_binds_local_p): New functiion.
- (rs6000_encode_section_info): Use it.
+ * config/sh/sh.c (sh_register_move_cost):
+ Add case for moving between MAC_REGS.
-2003-01-23 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
+2003-06-24 Jerry Quinn <jlquinn@optonline.net>
- PR other/7341
- * invoke.texi (ftest-coverage): Fix broken cross-reference.
- Change @code to @command for gcov command.
+ PR other/11280
+ * gcc/doc/invoke.texi (Optimization Options): Remove -Os from
+ -freorder-functions description.
- * gcc.texi: Adjust title of gcov section.
- * gcov.texi: Likewise.
+2003-06-25 Richard Sandiford <rsandifo@redhat.com>
-2003-01-23 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
+ PR target/11084
+ * config/mips/mips.c (mips_expand_prologue): Fix setting of regno
+ for the end of a variable argument list.
- PR other/7448
- * doc/passes.texi (fssa-ccp): Remove misplaced line.
+2003-06-25 Josef Zlomek <zlomekj@suse.cz>
-2003-01-21 Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de>
+ * dwarf2out.c (gen_field_die): Return if type of decl is error mark.
- PR opt/7507
- * calls.c (fix_unsafe_tree): Split out from ...
- (expand_call): ... here. Use it on the function address too.
+2003-06-24 Falk Hueffner <falk.hueffner@student.uni-tuebingen.de>
-2003-01-19 Roger Sayle <roger@eyesopen.com>
+ PR target/11260
+ * config/alpha/alpha.md (sqrtdf2): Fix operand substitution.
- * config/pa/pa.md (muldi3): Avoid invalid sharing of SUBREG RTXs.
+2003-06-24 Jakub Jelinek <jakub@redhat.com>
-2003-01-19 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
+ * builtins.c (expand_builtin_strcpy): Don't evaluate side-effects in
+ src twice.
- * pa-linux.h (DWARF2_UNWIND_INFO, INCOMING_RETURN_ADDR_RTX,
- DWARF_FRAME_RETURN_COLUMN): Delete defines.
- (FUNCTION_OK_FOR_SIBCALL): Define to 1.
+2003-06-23 Jakub Jelinek <jakub@redhat.com>
-2003-01-17 Jim Wilson <wilson@redhat.com>
+ * config/s390/s390.c (s390_output_mi_thunk): Avoid .plt in -m31
+ mode, as it requires pic register loaded.
- * dbxout.c (dbxout_fptype_value): New.
- (dbxout_type, case COMPLEX_TYPE): Call it. Use 'R' instead of 'r'.
+2003-06-23 Kazu Hirata <kazu@cs.umass.edu>
-2003-01-15 Stephane Carrez <stcarrez@nerim.fr>
+ * doc/extend.texi: Fix typos.
+ * doc/md.texi: Likewise.
- * config/m68hc11/m68hc11.md ("return"): Use emit_jump_insn to emit
- the return code.
+2003-06-23 Roger Sayle <roger@eyesopen.com>
+ Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2003-01-12 Alan Modra <amodra@bigpond.net.au>
+ * doc/contrib.texi (Contributors): Add a note on testing and
+ remove duplicates from testers list.
- * expr.c (expand_expr <RDIV_EXPR>): Correct recursive call args.
+2003-06-23 Kazu Hirata <kazu@cs.umass.edu>
-2003-01-10 Josef Zlomek <zlomekj@suse.cz>
+ * doc/invoke.texi: Document dump options, dT and dW.
- * jump.c (next_nonnote_insn_in_loop): New function.
- (copy_loop_headers): Use next_nonnote_insn_in_loop instead of
- next_nonnote_insn.
- (duplicate_loop_exit_test). Likewise.
+2003-06-23 Andreas Schwab <schwab@suse.de>
-2003-01-10 Josef Zlomek <zlomj9am@artax.karlin.mff.cuni.cz>
+ * doc/invoke.texi: Remove leading `-' from options in index.
- * Makefile.in (optabs.o): Add dependencies on basic-block.h and
- hard-reg-set.h.
- * basic-block.h (control_flow_insn_p): Fuction was exported.
- * cfgbuild.c (control_flow_insn_p): Fuction was made non-static.
- * optabs.c (emit_libcall_block): Emit REG_LIBCALL and REG_RETVAL
- notes only when the region is contained in a single basic block.
+2003-06-22 Kazu Hirata <kazu@cs.umass.edu>
-2003-01-09 Eric Botcazou <ebotcazou@libertysurf.fr>
+ * doc/invoke.texi: Document dump, .cfg.
- PR inline-asm/8832
- * tree.h (expand_asm): New prototype.
- * stmt.c (expand_asm): Set the MEM_VOLATILE_P flag if instructed
- to do so.
- * c-semantics (genrtl_asm_stmt): Pass the RID_VOLATILE qualifier
- down to expand_asm.
- * c-typeck.c (simple_asm_stmt): Set the RID_VOLATILE qualifier.
- * rtlanal.c (volatile_insn_p) [ASM_INPUT]: Test the MEM_VOLATILE_P flag.
- (volatile_refs_p) [ASM_INPUT]: Likewise.
- (side_effects_p) [ASM_INPUT]: Likewise.
+2003-06-22 Kazu Hirata <kazu@cs.umass.edu>
-2003-01-09 Eric Botcazou <ebotcazou@libertysurf.fr>
+ * doc/invoke.texi: Alphabetize dump options.
- PR c/8032
- * c-typeck.c (process_init_element) [RECORD_TYPE]: For
- an empty element, do not advance the pointer to unfilled
- fields if there are pending initializers.
+2003-06-22 Kazu Hirata <kazu@cs.umass.edu>
-2003-01-07 Janis Johnson <janis187@us.ibm.com>
+ * doc/invoke.texi: Remove a duplicate -dk.
- PR other/8947
- * doc/invoke.texi (-malign-double): Explain that the option breaks
- binary compatibility.
+2003-06-22 Kazu Hirata <kazu@cs.umass.edu>
-2003-01-07 Benjamin Kosnik <bkoz@redhat.com>
- Sunil Davasam <sunil.k.davasam@intel.com>
+ * doc/rtl.texi: Fix the @findex for pre_modify.
- PR libstdc++/9076
- * unwind-dw2.c (execute_cfa_program): DW_CFA_undefined,
- DW_CFA_same_value, read next and ignore.
+Sat Jun 21 13:37:52 CEST 2003 Jan Hubicka <jh@suse.cz>
-2003-01-07 Richard Henderson <rth@redhat.com>
+ * i386.c (ix86_va_arg): Fix allocation of temporary slot.
- * cfganal.c (flow_call_edges_add): Don't crash on noreturn call.
+2003-06-21 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2003-01-01 Neil Booth <neil@daikokuya.co.uk>
+ * doc/contrib.texi (Contributors): Use Windows instead of Win32.
- PR preprocessor/8880
- * gcc.c (cpp_unique_options): Handle -fshort-wchar later so it
- overrides any target CPU specs.
+ Update Andreas Jaeger's entry.
-2002-12-28 John David Anglin <dave.anglin@nrc.ca>
+ Merge the two entries of Kaveh Ghazi, David Edelsohn, and
+ Loren J. Rittle.
- * pa.h (TARGET_SOM): Define if not defined.
- * som.h (OBJ_SOM): Rename to TARGET_SOM.
- * pa.c (pa_output_function_prologue): Don't accumulate the total code
- bytes in the translation unit when using gas, som and not the portable
- runtime, or when using function sections.
+2003-06-20 Geoffrey Keating <geoffk@apple.com>
-2002-12-21 Eric Botcazou <ebotcazou@libertysurf.fr>
+ PR c++/9393
+ * doc/invoke.texi (Debugging Options): Document -frandom-seed.
+ * configure.in: Check for gettimeofday.
+ * tree.c (flag_random_seed): Define.
+ (default_flag_random_seed): New.
+ (append_random_chars): Use flag_random_seed rather than trying
+ to acquire randomness here.
+ * tree.h (default_flag_random_seed): Declare.
+ * toplev.c (display_help): Add -frandom-seed and -fstack-limit-*
+ descriptions.
+ (decode_f_option): Handle -frandom-seed.
+ (print_switch_values): Call default_flag_random_seed.
+ * flags.h (flag_random_seed): Declare.
+ * configure: Regenerate.
+ * config.in: Regenerate.
- PR optimization/8599
- * doloop.c (doloop_modify_runtime): Fix loop count computation
- for preconditioned unrolled loops.
+2003-06-20 Mark Mitchell <mark@codesourcery.com>
-2002-12-21 Eric Botcazou <ebotcazou@libertysurf.fr>
+ PR c++/10888
+ * tree-inline.c (expand_call_inline): Do not warn about failing to
+ inline functions declared in system headers.
+ * doc/invoke.texi (-Winline): Expand on documentation.
- PR optimization/8599
- * doloop.c (doloop_modify_runtime): Revert 2002-11-22 change.
- * loop.c (loop_invariant_p): Likewise.
+2003-06-20 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
-2002-12-19 Eric Botcazou <ebotcazou@libertysurf.fr>
+ * configure.in (gcc_cv_as_gstabs_flag): Disable if assembler warns.
+ * configure: Regenerate.
+ Fixes PR driver/9362.
+
+2003-06-19 Vladimir Makarov <vmakarov@redhat.com>
+
+ * haifa-sched.c (max_isse): Backport from the mainline.
+ (choice_entry): New structure.
+ (choice_stack, cycle_issued_insns, max_lookahead_tries,
+ cached_first_cycle_multipass_dfa_lookahead, cached_issue_rate):
+ New variables.
+ (choose_ready): Calculate max_lookahead_tries. Initiate
+ ready_try.
+ (schedule_block): Allocate/deallocate choice_stack. Change
+ cycle_issued_insns value as necessary.
+ (sched_init): Check cached_issue_rate.
+
+2003-06-20 Daniel Egger <degger@fhm.edu>
+ Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
- PR optimization/8988
- * loop.c (maybe_eliminate_biv): Kill REG_EQUAL notes mentioning
- the biv when eliminating.
+ * doc/install.texi (Building): Correct and improve statement
+ about parallel builds.
-2002-12-17 Jakub Jelinek <jakub@redhat.com>
+2003-06-20 Eric Botcazou <ebotcazou@libertysurf.fr>
- PR opt/8794
- * combine.c (force_to_mode) [MINUS]: Only replace with (not Y) if all
- bits in fuller_mask (not just mask) are set in C.
+ * doc/install.texi (--with-gnu-as): Mention SPARC/Solaris and
+ SPARC64/Solaris as platforms where --with-gnu-as makes a difference.
+ (--with-as): Add @anchor.
+ (--with-gnu-ld): Fix typo.
+ (--with-ld): Add @uref to --with-as.
-2002-12-12 John David Anglin <dave@hiauly1.hia.nrc.ca>
+2003-06-19 Kazu Hirata <kazu@cs.umass.edu>
- * pa.h (BIGGEST_ALIGNMENT): Change 32-bit value to 64 bits.
- (MAX_PARM_BOUNDARY, STACK_BOUNDARY): Express in terms of
- BIGGEST_ALIGNMENT.
- (PREFERRED_STACK_BOUNDARY): Express in terms of STACK_BOUNDARY.
- (FUNCTION_BOUNDARY): Express in terms of BITS_PER_WORD.
+ * flow.c (initialize_uninitialized_subregs): Use
+ emit_move_insn instead of emitting a hardcoded move.
-2002-12-10 Janis Johnson <janis187@us.ibm.com>
+2003-06-19 David Edelsohn <edelsohn@gnu.org>
- PR other/8882
- * doc/tm.texi (PUSH_ARGS): Remove misplaced line.
+ * config/rs6000/rs6000.c (init_cumulative_args): Limit CALL_LIBCALL
+ to ABI_V4.
-2002-12-05 Dale Johannesen <dalej@apple.com>
+2003-06-19 DJ Delorie <dj@redhat.com>
- * tree.c (unsafe_for_reeval): Consider callee child of CALL_EXPR.
+ PR preprocessor/11022
+ * cppmacro.c (warn_of_redefinition): Handle cases where the two
+ definitions have different numbers of tokens.
-2002-12-05 Danny Smith <dannysmith@users.sourceforge.net>
+2003-06-18 Richard Henderson <rth@redhat.com>
- * config/i386/cygwin.h (SUBTARGET_PROLOGUE): Replace with
- PROFILE_HOOK.
- * config/i386/mingw32.h (SUBTARGET_PROLOGUE): Don't undef.
+ * config/ia64/unwind-ia64.c (_Unwind_GetCFA): New.
+ (_Unwind_FindEnclosingFunction): Implement.
-2002-12-05 Nick Clifton <nickc@redhat.com>
+2003-06-18 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
- * config/fr30/fr30.h (GO_IF_LEGITIMATE_ADDRESS): Check for frame
- pointer and arg pointer by examining the register number.
+ * config/rs6000/rs6000.c (init_cumulative_args): Add and handle LIBCALL
+ argument.
+ (function_arg): Handle CALL_LIBCALL flag.
+ * config/rs6000/rs6000-protos.h (init_cumulative_args): Update
+ prototype.
+ * config/rs6000/rs6000.h (CALL_LIBCALL): New macro.
+ (INIT_CUMULATIVE_LIBCALL_ARGS): New macro.
+ (INIT_CUMULATIVE_ARGS): Add LIBCALL argument.
+ (INIT_CUMULATIVE_INCOMING_ARGS): Likewise.
-2002-12-05 Matthias Klose <doko@debian.org>
+2003-06-17 Jason Merrill <jason@redhat.com>
- * doc/invoke.texi: Remove last reference to -a.
+ PR c++/10929
+ * tree-inline.c (expand_call_inline): Don't warn about failing to
+ inline a function which was made inline by -finline-functions.
-2002-12-04 Eric Botcazou <ebotcazou@libertysurf.fr>
+2003-06-17 Ranjit Mathew <rmathew@hotmail.com>
- PR c/7622
- * c-semantics (genrtl_scope_stmt): Do not output inlined
- nested functions that contain no code.
+ * install.texi (Testing): Add information on how to run Java
+ runtime tests separately.
-2002-12-04 Jakub Jelinek <jakub@redhat.com>
+2003-06-17 Christopher Faylor <cgf@redhat.com>
- * fold-const.c (associate_trees): Only optimize NEGATE_EXPR in one
- of the operands into MINUS_EXPR if code is PLUS_EXPR.
+ * doc/install.texi: Add msvc rebuild caveat.
-2002-12-02 Bob Wilson <bob.wilson@acm.org>
+2003-06-17 Kazu Hirata <kazu@cs.umass.edu>
- * config/xtensa/xtensa.c (xtensa_emit_call): Use a static buffer.
- * config/xtensa/xtensa.h (MAX_WCHAR_TYPE_SIZE): Delete.
+ * doc/contrib.texi: Replace Hitachi with Renesas.
+ * doc/install.texi: Likewise.
+ * doc/invoke.texi: Likewise.
-2002-12-01 Mark Mitchell <mark@codesourcery.com>
+2003-06-17 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
- * builtin-types.def (BT_SIZE): Use size_type_node.
- * builtins.c (fold_builtin): Make the builtin strlen returns a
- size_t, not a sizetype.
- * c-common.c (c_alignof): Use size_type_node, not c_size_type_node.
- (c_alignof_expr): Likewise.
- (c_common_nodes_and_builtins): Likewise.
- * c-common.h (CTI_C_SIZE_TYPE): Remove.
- (c_size_type_node): Likewise.
- * c-format.c (T_ST): Use size_type_node, not c_size_type_node.
- * tree.h (TI_SIZE_TYPE): New enumeral.
- (size_type_node): Likewise.
-
-2002-11-26 Neil Booth <neil@daikokuya.co.uk>
+ * config/rs6000/linux.h (MD_FALLBACK_FRAME_STATE_FOR): Partly revert
+ 2003-01-23 patch. Corrected to handle kernels with changed ucontext.
- PR preprocessor/8524
- * cpplib.c (run_directive): Remove previous kludge to _Pragma.
- Add a new one in its place, which hopefully works.
- (skip_rest_of_line): Change test for bottom-of-context-stack.
+ * config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS): Error on invalid
+ -msdata=eabi usages.
-2002-11-26 David Edelsohn <edelsohn@gnu.org>
+2003-06-14 Richard Earnshaw <rearnsha@arm.com>
- * config/rs6000/rs6000.c (rs6000_flag_pic): New variable.
- (rs6000_override_options): Save original flag_pic value.
- (rs6000_encode_section_info): More accurate test for "local" symbol.
+ PR optimization/10842
+ From trunk:
+ 2003-01-20 Nick Clifton <nickc@redhat.com>
- PR 8362
- * config/rs6000/rs6000.c (rs6000_outout_load_multiple): New function.
- * config/rs6000/rs6000.md (ldmsi[3-8]): New patterns.
+ * config/arm/arm.md (sibcall_epilogue): Add an
+ UNSPEC_PROLOGUE_USE to prevent the link register from being
+ considered dead.
-2002-11-25 Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de>
+ 2003-02-02 Richard Earnshaw <rearnsha@arm.com>
- PR c/8639
- * fold-const.c (extract_muldiv): Don't propagate division unless
- both arguments are multiples of C.
+ * arm.md (sibcall_epilogue): Set the "conds" to "clob".
+ (epilogue_insns): Likewise.
-2002-11-24 Eric Botcazou <ebotcazou@libertysurf.fr>
+2003-06-14 Richard Earnshaw <rearnsha@arm.com>
- PR optimization/8275
+ PR target/11183
+ * arm.c (output_move_double): Pass SImode to adjust_address.
- Merge from mainline:
- 2002-09-19 Dale Johannesen <dalej@apple.com>
+2003-06-13 Janis Johnson <janis187@us.ibm.com>
- * combine.c (make_extraction): Don't create
- invalid subreg.
+ * doc/install.texi (m32r-*-elf): Change company to Renesas.
-2002-11-23 Marek Michalkiewicz <marekm@amelek.gda.pl>
+2003-06-13 Richard Earnshaw <rearnsha@arm.com>
- 2002-09-26 Theodore A. Roth <troth@verinet.com>
- * config/avr/avr.c: Eliminate use of _PC_ in pc relative insns.
- * config/avr/avr.md: Ditto.
+ * arm.c (output_call_mem): If the address references the link-register
+ use an instruction sequence that avoids early-clobbering IP.
+ (eliminate_lr2ip): Delete.
-2002-11-23 Eric Botcazou <ebotcazou@libertysurf.fr>
+2003-06-12 Richard Henderson <rth@redhat.com>
- PR c/8588
- * optabs.c (expand_binop): Convert CONST_INTs in shift
- operations too.
+ PR target/11089
+ * config/i386/i386.md (sse_movaps): Use an expander to force
+ one operand to be a register.
+ (sse_movups): Likewise.
-2002-11-23 Eric Botcazou <ebotcazou@libertysurf.fr>
+2003-06-12 Richard Henderson <rth@redhat.com>
- PR c/8518
- * c-decl.c (duplicate_decls): Outline the second definition
- of an extern inline function in all cases.
+ PR middle-end/10557
+ * rtlanal.c (subreg_offset_representable_p): Relax subreg check.
-2002-11-22 Eric Botcazou <ebotcazou@libertysurf.fr>
+2003-06-13 Eric Botcazou <ebotcazou@libertysurf.fr>
+ Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de>
- PR c/8439
- * recog.c (validate_replace_rtx_1) [PLUS]: Simplify only
- if there is something new to be simplified.
+ PR target/10142
+ * config/sparc/sparc.c (function_arg_record_value_parms): Add
+ new 'stack' field.
+ (function_arg_record_value_1): Set 'stack' to 1 if we run out of
+ integer slots for an integer field.
+ (function_arg_record_value_3): Shift vector index.
+ (function_arg_record_value_2): Likewise.
+ (function_arg_record_value): Initialize 'stack' to 0.
+ Set 'stack' to 1 if we run out of integer slots for an integer field.
+ Generate (parallel [(expr_list (nil) ...) ...]) if 'stack' is set to 1.
-2002-11-22 Toon Moene <toon@moene.indiv.nluug.nl>
+2003-06-13 Eric Botcazou <ebotcazou@libertysurf.fr>
- * c-decl.c (c_init_decl_processing): Move generation of
- decls for g77_integer_type_node and friends from here ...
- * c-common.c (c_common_nodes_and_builtins): ... to here.
+ PR optimization/10955
+ * unroll.c (unroll_loop): Fix off-by-one bug.
-2002-11-22 Eric Botcazou <ebotcazou@libertysurf.fr>
+2003-06-12 Richard Henderson <rth@redhat.com>
- PR optimization/8599
+ PR middle-end/10475
+ * expmed.c (emit_store_flag): Use simplify_gen_subreg directly
+ for extracting sub-words.
- Merge from mainline:
- 2002-11-04 Dale Johannesen <dalej@apple.com>
+2003-06-12 Richard Henderson <rth@redhat.com>
- * doloop.c (doloop_modify_runtime): Fix loop count computation
- for unrolled loops.
- * loop.c (loop_invariant_p): Support calling from unroller.
+ PR target/7594
+ * config/m68k/m68k.md (zero_extendhisi2): Use gen_lowpart_SUBREG.
+ (zero_extendqihi2, zero_extendqisi2): Likewise.
-2002-11-22 Daniel Jacobowitz <drow@mvista.com>
+2003-06-12 Richard Henderson <rth@redhat.com>
- * config/sh/sh.md (ashrdi3+1, ashrdi3+2): Predicate on
- reload_completed.
+ PR inline-asm/4823
+ * reg-stack.c (any_malformed_asm): New.
+ (check_asm_stack_operands): Set it.
+ (convert_regs_1): Check it before aborting.
-2002-11-21 Bob Wilson <bob.wilson@acm.org>
+2003-06-12 Jakub Jelinek <jakub@redhat.com>
- * config/xtensa/xtensa-protos.h (xtensa_copy_incoming_a7): Declare.
- * config/xtensa/xtensa.c (struct machine_function): Add
- incoming_a7_copied flag.
- (xtensa_copy_incoming_a7): Define.
- (xtensa_emit_move_sequence): Use xtensa_copy_incoming_a7.
- * config/xtensa/xtensa.md (movdi, movsf, movdf): Ditto.
+ * c-decl.c (c_expand_body): Save input_filename and lineno,
+ set it before tree inlining and restore before return.
-2002-11-19 Release Manager
+2003-06-12 Ulrich Weigand <uweigand@de.ibm.com>
- * GCC 3.2.1 Released.
+ * config/s390/s390.c (s390_emit_prologue): Use LA instead of AR
+ to initialize GOT register.
-2002-11-19 Release Manager
+2003-06-12 Jakub Jelinek <jakub@redhat.com>
- * GCC 3.2.1 Released.
+ * c-opts.c (complain_wrong_lang): Add on argument.
+ Print no- switch if on is false.
+ (c_common_decode_option): Adjust caller.
-2002-11-18 Release Manager
+2003-06-11 Richard Henderson <rth@redhat.com>
- * GCC 3.2.1 Released.
+ * stmt.c (expand_asm_operands): Don't warn for memories with
+ queued addresses.
-Sat Nov 16 02:54:29 CET 2002 Jan Hubicka <jh@suse.cz>
+2003-06-11 Andrew Pinski <pinskia@physics.uc.edu>
- * jump.c (tablejump_p): New.
- * cfgcleanup.c (try_optimize_cfg): Do not merge blocks across tablejump.
- * rtl.h (tablejump_p): Declare.
+ PR target/8787
+ * config/i386/djgpp.h (ASM_FILE_START): emit `.intel_syntax'
+ if -masm=intel.
-2002-11-16 Graham Stott <graham.stott@btinternet.com>
+2003-06-10 Andrew Haley <aph@redhat.com>
- * flow.c (life_analysis): Update LABEL_NUSES before purging
- dead jumptables.
+ * langhooks-def.h (LANG_HOOKS_DECL_OK_FOR_SIBCALL): New.
+ (LANG_HOOKS_DECLS): Add LANG_HOOKS_DECL_OK_FOR_SIBCALL.
+ (lhd_decl_ok_for_sibcall): New.
+ * langhooks.c (lhd_decl_ok_for_sibcall): New.
+ * langhooks.h (lang_hooks_for_decls.ok_for_sibcall): New field.
+ * calls.c (expand_call): Check lang_hook before generating a
+ sibcall.
-2002-11-13 Janis Johnson <janis187@us.ibm.com>
+2003-06-09 Richard Henderson <rth@redhat.com>
- * doc/install.texi (Testing): Document extra Java testing.
- * doc/sourcebuild.texi (Test Suites): Document libgcj testing.
+ 2003-05-11 Ulrich Weigand <uweigand@de.ibm.com>
+ * except.c (EH_RETURN_STACKADJ_RTX): Do not define.
+ (EH_RETURN_HANDLER_RTX): Likewise.
+ (expand_builtin_eh_return): Do not copy stack adjustment
+ if EH_RETURN_STACKADJ_RTX is not defined.
+ (expand_eh_return): Likewise. Also, do not pass stack
+ adjustment as argument to the eh_return pattern.
+ * except.h (MUST_USE_SJLJ_EXCEPTIONS): Do not define just
+ because EH_RETURN_STACKADJ_RTX is not defined.
+ * unwind-dw.c (uw_update_context_1): If EH_RETURN_STACKADJ_RTX
+ is not defined, treat stack pointer like a regular register.
+ (uw_init_context_1): Set up fake initial stack pointer register.
+ (uw_install_context_1): Do not compute stack adjustment if
+ EH_RETURN_STACKADJ_RTX is not defined.
-2002-11-12 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+ * config/i386/i386.md ("eh_return"): Remove first argument.
+ * config/mips/mips.md ("eh_return"): Likewise.
+ * config/rs6000/rs6000.md ("eh_return"): Likewise.
+ * config/sh/sh.md ("eh_return"): Likewise.
- * doc/install.texi (powerpc-*-linux-gnu*): Update binutils requirement.
+ * config/s390/s390.h (EH_RETURN_STACKADJ_RTX): Remove.
-2002-11-12 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+2003-06-08 Richard Henderson <rth@redhat.com>
- * doc/contrib.texi (Contributors): Use GCJ instead of gcj to refer
- to that entire project.
+ * stmt.c (expand_asm_operands): Re-word warning.
-2002-11-12 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+2003-06-08 Richard Henderson <rth@redhat.com>
- * config/mips/t-iris6 (MULTILIB_OSDIRNAMES): Restore old
- directories.
+ * expr.h (EXPAND_MEMORY): New.
+ * expr.c (expand_expr): Check it.
+ * stmt.c (expand_asm_operands): Provide it when the constraint
+ requires a memory. Warn for memory input constraints without
+ a memory operand.
-2002-11-11 Janis Johnson <janis187@us.ibm.com>
+2003-06-07 Richard Henderson <rth@redhat.com>
- * doc/contrib.texi: Merge in the list from the libstdc++ web pages.
+ * c-common.c (cb_register_builtins): Define __EXCEPTIONS for C also.
-2002-11-11 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+2003-06-07 Kelley Cook <kelleycook@wideopenwest.com>
- PR c/8467
- * stmt.c (tail_recursion_args): Handle DECL_MODE differing from the
- mode of DECL_RTL case.
+ * configure.in (HAVE_LD_RO_RW_SECTION_MIXING): Remove quotes in
+ section names.
+ * configure: Regenerate.
-2002-11-11 Neil Booth <neil@daikokuya.co.uk>
+2003-06-07 Alan Modra <amodra@bigpond.net.au>
- PR preprocessor/4890
- * tradcpp.c (output_line_command): When leaving a file,
- system_include_depth has not yet been decremented.
+ * config/rs6000/linux64.h (CRT_CALL_STATIC_FUNCTION): Define.
-2002-11-10 Joel Sherrill <joel@gcc.gnu.org>
+2003-06-06 James E Wilson <wilson@tuliptree.org>
- * config/m68k/t-crtstuff (crti.o): Use this...
- ($(T)crti.o): ... instead.
- (crtn.o): Use this...
- ($(T)crtn.o): ... instead.
+ PR inline-asm/10890
+ * reload1.c (merge_assigned_reloads): Abort only if two reloads have
+ different in fields.
-2002-11-10 Ralf Corsepius <corepiu@faw.uni-ulm.de>
+2003-06-06 Richard Earnshaw <rearnsha@arm.com>
- * config/mips/mips.md (movdi_usd): Use %z1 in place of %1.
+ PR target/11052
+ * ifcvt.c (noce_process_if_block): Fail if the destination has
+ side-effects.
-2002-11-11 Graham Stott <graham.stott@btinternet.com>
- Jan Hubicka <jh@suse.cz>
+2003-06-06 Dan Kegel <dank@kegel.com>
+ Kaz Kojima <kkojima@gcc.gnu.org>
- PR 8502
- * cfgrtl.c (try_redirect_by_replacing_jump): Do not kill computed
- jumps post reload.
+ PR target/10331
+ * config/sh/t-linux (STMP_FIXPROTO): Define.
-2002-11-08 H.J. Lu <hjl@gnu.org>
+ PR target/11096
+ * config/sh/linux.h (CPLUSPLUS_CPP_SPEC): Redefine so to include
+ -D_GNU_SOURCE.
- Fix c/5351 and optimization/7591.
+2003-06-05 David Miller <davem@redhat.com>
+ Richard Henderson <rth@redhat.com>
- * calls.c (store_one_arg): Remove ATTRIBUTE_UNUSED on
- variable_size. Mark any slots used for the argument as in-use
- only if we can't pass all arguments to a library call in
- registers.
+ * optabs.c (HAVE_conditional_trap): Provide default.
+ (gen_conditional_trap): Likewise.
+ (init_optabs): Merge init_traps.
+ (gen_cond_trap): Use prepare_operand. Restructure and avoid ifdef.
-2002-11-07 H.J. Lu <hjl@gnu.org>
+2003-06-05 Eric Botcazou <ebotcazou@libertysurf.fr>
- Fix bootstrap/8146 and
- gcc.c-torture/execute/20020307-2.c with -march=i686.
+ * doc/md.texi (Machine Constraints): Correct the meaning of
+ constraints related to floating-point registers on SPARC.
- * calls.c (PUSH_ARGS_REVERSED): Define only if not defined.
- * expr.c (PUSH_ARGS_REVERSED): Likewise.
+2003-06-05 Eric Botcazou <ebotcazou@libertysurf.fr>
+ Paolo Bonzini <bonzini@gnu.org>
- * config/i386/i386.h (PUSH_ARGS_REVERSED): Set to 1.
+ PR target/10663
+ * configure.in (HAVE_LD_RO_RW_SECTION_MIXING): Redirect
+ assembler and linker output to /dev/null.
+ Use a 'sed' construct instead of 'grep -A1'.
+ * configure: Regenerate.
-2002-11-04 Aldy Hernandez <aldyh@redhat.com>
+2003-06-04 David Edelsohn <edelsohn@gnu.org>
- Fix c/8252.
+ * doc/install.texi (*-ibm-aix*): Native as and ld required
+ to bootstrap on AIX 5L.
- * config/rs6000/rs6000.c (rs6000_legitimate_address): Disallow
- vectors from PRE_INC/DEC.
+2003-06-04 Richard Henderson <rth@redhat.com>
-2002-11-06 Richard Henderson <rth@redhat.com>
+ * c-common.c (handle_cleanup_attribute): New.
+ (c_common_attributes): Add it.
+ * c-decl.c (finish_decl): Honor the cleanup attribute.
+ * doc/extend.texi (Variable Attributes): Document it.
- PR optimization/7520
- * cfganal.c (flow_active_insn_p): New.
- (forwarder_block_p): Use it.
+ * unwind-c.c: New file.
+ * Makefile.in (LIB2ADDEH): Add it.
+ * config/t-darwin, config/t-linux, config/t-linux-gnulibc1,
+ config/ia64/t-ia64: Likewise.
-2002-11-06 Janis Johnson <janis187@us.ibm.com>
+2003-06-04 Eric Botcazou <ebotcazou@libertysurf.fr>
- * doc/contrib.texi: Merge in the list from the Java web pages.
+ PR optimization/11018
+ * config/sparc/sparc.c (sparc_v8plus_shift): Use which_alternative
+ consistently to decide whether the scratch register is really
+ required.
-2002-11-06 David O'Brien <obrien@FreeBSD.org>
+2003-06-04 Eric Botcazou <ebotcazou@libertysurf.fr>
- * config/sparc/freebsd.h: Fix typo.
+ PR optimization/10876
+ * config/sparc/sparc.h (CONST_OK_FOR_LETTER): Add
+ new 'O' constraint for constant 4096.
+ (CONST_DOUBLE_OK_FOR_LETTER_P): Likewise.
+ * config/sparc/sparc.md (adddi3 expander): Canonicalize pattern.
+ Do not transform into MINUS insn for constant 4096.
+ (*adddi3_sp64 insn): Canonicalize pattern. Add new alternative
+ for constant 4096 as third operand.
+ (addsi3 expander): Remove.
+ (*addsi3 insn): Rename into 'addsi3'. Canonicalize pattern. Add
+ new alternative for constant 4096 as third operand.
+ (subdi3 expander): Do not transform into PLUS insn for constant 4096.
+ (*subdi3_sp64 insn): Add new alternative for constant 4096 as third
+ operand.
+ (subsi3 expander): Remove.
+ (*subsi3 insn): Rename into 'subsi3'. Add new alternative for
+ constant 4096 as third operand.
+ * doc/md.texi (Machine Constraints): Document new 'O' constraint for
+ the SPARC port.
-2002-11-05 Bob Wilson <bob.wilson@acm.org>
+2003-06-03 Richard Henderson <rth@redhat.com>
- * config/xtensa/elf.h (LIB_SPEC): Add "-lhal".
+ * unwind.inc (_Unwind_Resume_or_Rethrow): Fix return type.
+ * unwind.h (_Unwind_Resume_or_Rethrow): Update.
+ (_Unwind_SjLj_Resume_or_Rethrow): Likewise.
-2002-11-04 Aldy Hernandez <aldyh@redhat.com>
+2003-06-03 Douglas B Rupp <rupp@gnat.com>
- Backport patch to fix PR c/8451.
+ * Makefile.in (TEXI_GCC_FILES): Remove vms.texi entry.
+ * doc/gcc.texi: Remove vms.texi section.
+ * doc/vms.texi: Remove obsolete file.
- 2002-04-25 Richard Henderson <rth@redhat.com>
+2003-06-03 Richard Henderson <rth@redhat.com>
- * expmed.c (extract_bit_field): Fall through to generic code rather
- than aborting on subreg special case.
+ PR target/10673
+ * config/i386/i386.c (ix86_split_long_move): Fix base register
+ mode for XFmode splits for TARGET_64BIT.
-2002-11-01 Mark Mitchell <mark@codesourcery.com>
+2003-06-02 Kazuhiro Inaoka <inaoka.kazuhiro@renesas.com>
- PR c++/8391
- * toplev.c (rest_of_compilation): Do not refuse to output code for
- an inline function in a local class.
+ * gcc/config.gcc Add support multilib parts for m32rx processor.
-2002-11-01 David O'Brien <obrien@FreeBSD.org>
+2003-06-01 Eric Botcazou <ebotcazou@libertysurf.fr>
- * config/sparc/freebsd.h (CPP_CPU64_DEFAULT_SPEC): Define __arch64__.
- Add comment.
+ PR target/11044
+ * config/i386/i386.md (length attribute): Set length to 4
+ for instructions of type "fcmp".
-2002-11-01 David O'Brien <obrien@FreeBSD.org>
+2003-06-01 Josef Zlomek <zlomekj@suse.cz>
- * config/sparc/freebsd.h (TRANSFER_FROM_TRAMPOLINE): Define
- __enable_execute_stack function.
+ * rtl.def (CONST_DOUBLE): Update comment.
-2002-11-01 Richard Earnshaw (rearnsha@arm.com)
+2003-06-01 Seth Arnold <sarnold@wirex.com>
+ Aldy Hernandez <aldyh@redhat.com>
- PR target/7856
- * arm.c (use_return_insn): Don't use a return insn if there are
- saved integer regs, but LR is not one of them.
+ PR10871
+ * config/rs6000/rs6000.c (rs6000_stack_info): Do not add
+ vrsave_size twice.
-Thu Oct 31 18:31:22 CET 2002 Jan Hubicka <jh@suse.cz>
+2003-05-31 Eric Botcazou <ebotcazou@libertysurf.fr>
- * i386.c (override_options): Set defaults for flag_omit_frame_pointer,
- flag_asynchronous_unwind_tables, flag_pcc_struct_return.
- * i386.c (optimization_options): Set flag_omit_frame_pointer,
- flag_asynchronous_unwind_tables, flag_pcc_struct_return to 2.
- Do not clear -momit-leaf-frame-pointer when profiling.
- (ix86_frame_pointer_required): Frame pointer is allways required when
- profiling.
+ * doc/install.texi (mips-sgi-irix5): Add missing
+ HTML <hr> marker.
-2002-10-30 Mark Mitchell <mark@codesourcery.com>
+2003-05-31 Eric Botcazou <ebotcazou@libertysurf.fr>
- * varasm.c (asm_output_aligned_bss): Do not call
- ASM_GLOBALIZE_LABEL.
+ * doc/md.texi (Machine Constraints): Document
+ missing SPARC constraints.
-2002-10-29 Janis Johnson <janis187@us.ibm.com>
+2003-05-31 Eric Botcazou <ebotcazou@libertysurf.fr>
- * doc/invoke.texi (-profile-arcs): Remove references to -a and -ax.
+ * doc/md.texi (Automaton pipeline description): Use
+ "type" instead of "cpu" as the attribute in the examples.
-2002-10-29 Eric Botcazou <ebotcazou@libertysurf.fr>
+2003-05-30 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
- PR optimization/8334
- * expr.c (expand_expr) [PLUS]: Don't use simplify_binary_operation;
- check for zero operands explicitly.
+ * config/mips/mips.h (SUBTARGET_ASM_DEBUGGING_SPEC): Move
+ -mdebug/-no-mdebug switches ...
+ (MDEBUG_ASM_SPEC): ... here.
+ Use only with gas.
+ (EXTRA_SPECS): Initialize mdebug_asm_spec.
+ (CONSTANT_ADDRESS_P): Allow native IRIX 6 O32 assembler.
-2002-10-21 Dale Johannesen <dalej@apple.com>
+2003-05-29 Gabriel Dos Reis <gdr@integrable-solutions.net>
- PR target/7133
- * config/rs6000/rs6000.c (rs6000_reverse_condition): Handle
- unsafe math reversals correctly for RTL generation.
- (output_cbranch): Replace rs6000_reverse_condition call
- by its former definition.
+ * diagnostic.h (output_verbatim): Remove printf attribute.
+ (verbatim): Likewise.
+ * diagnostic.c (output_pointer): New function.
+ (output_format): Use it. Handle %p format specifier.
-Sun Oct 27 10:12:27 CET 2002 Jan Hubicka <jh@suse.cz>
+2003-05-27 Denis Chertykov <denisc@overta.ru>
- * linux64.h (DEFAULT_PCC_STRUCT_RETURN): Define.
+ * cselib.c (cselib_invalidate_regno): Abort if hardreg have a
+ VOIDmode.
+ * cselib.c (cselib_process_insn): Pass reg_raw_mode for hardreg in
+ call of cselib_invalidate_regno.
- PR target/6890
- * xmmintrin.h (_MM_TRANSPOSE4_PS): New.
+2003-05-25 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-10-25 Zack Weinberg <zack@codesourcery.com>
+ * doc/contrib.texi (Contributors): Update Kean Johnston.
- PR middle-end/6994
- * c-objc-common.c (inline_forbidden_p): Can not inline
- functions containing structures or unions containing VLAs.
- * tree-inline.c (walk_tree): For all class 't' nodes, walk
- TYPE_SIZE and TYPE_SIZE_UNIT. #undef WALK_SUBTREE_TAIL at end.
- (copy_tree_r): Copy types if they are variably modified.
+Fri May 23 21:19:31 CEST 2003 Jan Hubicka <jh@suse.cz>
+ Andreas Jaeger <aj@suse.de>
- * hooks.c (hook_tree_bool_false): New.
- * hooks.h: Prototype it.
- * langhooks.h (struct lang_hooks_for_tree_inlining): Add
- var_mod_type_p.
- * langhooks-def.h: Default for tree_inlining.var_mod_type_p is
- hook_tree_bool_false.
+ * i386.h (TARGET_CPU_CPP_BUILTINS): Define __amd64 and __amd64__;
+ do not use assertion.
- * tree.c (variably_modified_type_p): Moved here from
- cp/tree.c. Use lang_hooks.tree_inlining.var_mod_type_p for
- language-specific cases. Due to this, must weaken some 'if
- and only if' checks to merely 'if'.
- * tree.h: Prototype variably_modified_type_p.
+Fri May 23 20:55:39 CEST 2003 Jan Hubicka <jh@suse.cz>
-2002-10-22 Jim Wilson <wilson@redhat.com>
+ * i386.md (sse_loadss, sse_loadss_1, sse2_loadsd, sse2_loadsd_1):
+ Rewrite
- * config/i386/i386.md (subdi3_1): Add call to ix86_binary_operator_ok.
+2003-05-23 Eric Botcazou <ebotcazou@libertysurf.fr>
-2002-10-15 Jim Wilson <wilson@redhat.com>
+ * doc/install.texi: Remove sparc64-*-*. Add sparc64-*-solaris2*.
+ Document sparcv9-*-solaris2* as a synonym for sparc64-*-solaris2*.
- PR target/6981
- * config/i386/i386.md (adddi3_1): Add call to ix86_binary_operator_ok.
+2003-05-22 Eric Botcazou <ebotcazou@libertysurf.fr>
-2002-10-24 Richard Henderson <rth@redhat.com>
+ PR bootstrap/10805
+ * doc/install.texi (sparc-sun-solaris2.7): Document bootstrap
+ failure with Sun assembler 5.0 Alpha 03/27/98.
- PR opt/7944
- * reload.c (find_reloads_toplev): Use simplify_gen_subreg; mode
- of X is not important when simplifying subregs of constants.
+2003-03-21 Loren James Rittle <ljrittle@acm.org>
-2002-10-23 Robert Lipe <robertlipe@usa.net>
+ * config/sparc/freebsd.h (CPP_CPU64_DEFAULT_SPEC): Add -D__sparcv9
+ -D__sparc__ to match system compiler convention.
- * config.gcc (i[34567]86-*-sco3.2v5*): Fix tm_file.
+2003-05-20 Kevin Ryde <user42@zip.com.au>
+ Wolfgang Bangerth <bangerth@dealii.org>
-2002-10-23 Roger Sayle <roger@eyesopen.com>
+ PR c/10355
+ * doc/extend.texi: Put a warning into the documentation
+ of attribute regparm.
- PR c/761
- * doc/invoke.texi: Fix some overfull hboxes in "make dvi".
- Document --version, -fno-sched-interblock, -fno-sched-spec,
- -fsched-spec-load, -fsched-spec-load-dangerous,
- -fsched-verbose=n, -fno-branch-count-reg and -fbounds-check.
+2003-05-20 Ulrich Weigand <uweigand@de.ibm.com>
-2002-10-23 Ulrich Weigand <uweigand@de.ibm.com>
+ * config/s390/s390.md ("*iordi3_oi"): Do not mark commutative.
+ ("*iorsi3_oi"): Likewise.
- * config/s390/s390.md ("*movdi_64"): Fix op_type attribute.
- ("*movdf_64"): Likewise.
- ("*lshrdi3_64"): Likewise.
+2003-05-19 John David Anglin <dave.anglin@nrc-gnrc.gc.ca>
-2002-10-21 Matthias Klose <doko@debian.org>
+ * pa/milli64.S ($$mulI): Fix typo.
- * Backport, without whitespace change:
- 2002-06-19 Akim Demaille <akim@epita.fr>
- * c-parse.in (initelt: identifier ':' initval): Add an empty
- action to fix a type clash.
- (aliasdecl, classdef): Add the missing closing `;'.
+2003-05-19 Gabriel Dos Reis <gdr@integrable-solutions.net>
-Sat Oct 19 15:49:14 CEST 2002 Jan Hubicka <jh@suse.cz>
+ * hashtable.h (struct ht_identifier): Add new field "hash_value".
+ * hashtable.c (ht_lookup): Use it.
+ (ht_expand): Likewise. Avoid doing the same computation twice.
+ * tree.h (IDENTIFIER_HASH_VALUE): New macro.
- * mmintrin.h (__m64): typedef it to v2si.
- (_mm_cvtsi32_si64, _mm_cvtsi32_si64_mm_sll_pi16,
- _mm_sll_pi32, _mm_sll_pi64, _mm_slli_pi64, _mm_sra_pi16,
- _mm_sra_pi32, _mm_srl_pi16, _mm_srl_pi32, _mm_srl_pi64,
- _mm_srli_pi64, _mm_and_si64, _mm_andnot_si64,
- _mm_or_si64, _mm_xor_si64): Add neccesary casts.
- * xmmintrin.h (_mm_setzero_si64): Likewise.
+2003-05-19 Nick Clifton <nickc@redhat.com>
- PR target/7693
- Patch by Shawn Wagner
- * mmintrin.h: Replace pi64 by si64.
+ * config/arm/arm.c (use_return_insn): Do not use a single return
+ instruction for interrupt handlers which have to create a stack
+ frame.
+ (arm_expand_prologue): Do not pre-bias the return address of
+ interrupt handlers which create a stack frame.
-2002-10-18 Zack Weinberg <zack@codesourcery.com>
+2003-05-19 Eric Botcazou <ebotcazou@libertysurf.fr>
- * decl.c (start_decl): Point users of the old initialized-
- typedef extension at __typeof__.
+ Backport from mainline:
-Thu Oct 17 17:14:07 CEST 2002 Jan Hubicka <jh@suse.cz>
+ 2003-05-10 Alexander Aganichev <aaganichev@yandex.ru>
- PR opt/7630
- * reload.c (reload_inner_reg_of_subreg): New argument output;
- (push_reload): Update call.
+ * config/i386/i386.h (MODES_TIEABLE_P): Fix typo.
- PR c++/6419
- * expr.c (expand_expr): Use DECL_RTL_SET_P.
+2003-05-16 Wolfgang Bangerth <bangerth@dealii.org>
-Wed Apr 24 23:45:37 2002 J"orn Rennecke <joern.rennecke@superh.com>
+ * doc/bugreport.texi: Remove most of the preface of the
+ bugs section.
- * calls.c (expand_call): Take current_function_pretend_args_size
- into account when setting argblock for sibcalls.
+2003-05-16 Nick Clifton <nickc@redhat.com>
-Wed Oct 16 19:43:38 CEST 2002 Jan Hubicka <jh@suse.cz>
+ * config/mcore/mcore.md (jump): Use emit_jump_insn to generate the
+ jump insn.
- PR target/7396
- * i386.c (builtin_description):Drop cmpg[te]s[sd].
- * xmmintrin.h (__mm_cmpg[te]_s[sd]): Rewrite using
- swapped alternative.
+2003-05-15 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-10-16 Jakub Jelinek <jakub@redhat.com>
+ * doc/invoke.texi (Warning Options): Mark -Wmissing-declarations
+ as a C only option.
- * fold-const.c (fold): Fix a typo.
+2003-05-15 Wolfgang Bangerth <bangerth@dealii.org>
-2002-10-15 Ulrich Weigand <uweigand@de.ibm.com>
+ * doc/bugreport.texi: Remove most of the bug reporting
+ instructions and merge them into bugs.html.
- PR target/7370
- * config/s390/s390.md ("*addsi3_inv"): New pattern.
+2003-05-14 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- PR target/8232
- * config/s390/s390.md ("cmpstrsi"): Convert length operand
- from SImode to Pmode.
+ * sparc.c (print_operand): Fix uninitialized warning.
-2002-10-15 Janis Johnson <janis187@us.ibm.com>
+2003-05-14 Mark Mitchell <mark@codesourcery.com>
- * doc/install.texi: Formatting changes for conformance to HTML 4.01.
+ * version.c: Reset to prerelease format.
+ * doc/include/gcc-common.texi: Update version number.
-2002-10-15 Ulrich Weigand <uweigand@de.ibm.com>
+2003-05-13 Release Manager
- PR opt/7409
- * loop.c (loop_regs_scan): Mark registers used for function
- argument passing as MAY_NOT_OPTIMIZE.
+ * GCC 3.3 Released.
-2002-10-14 Neil Booth <neil@daikokuya.co.uk>
+2003-05-12 Mark Mitchell <mark@codesourcery.com>
- PR preprocessor/7862
- PR preprocessor/8190
- * gcc.c (cpp_unique_options): Don't delete .d files.
- Remove stray whitespace.
+ PR other/10745
+ * configure.in: Correct detection of GNU ld version number.
+ * configure: Regenerated.
-2002-10-14 Jakub Jelinek <jakub@redhat.com>
+2003-05-08 J"orn Rennecke <joern.rennecke@superh.com>
- * config/i386/i386.h (ASM_OUTPUT_REG_PUSH, ASM_OUTPUT_REG_POP):
- Handle TARGET_64BIT.
+ * sh.c (gen_block_redirect, split_branches): Use
+ CODE_FOR_jump_compact instead of CODE_FOR_jump
-2002-10-14 Mark Mitchell <mark@codesourcery.com>
+2003-05-06 Eric Christopher <echristo@redhat.com>
- PR optimization/6631
- * Makefile.in (function.o): Depend on langhooks.h.
- * alias.c (objects_must_conflict_p): Check honor_readonly when
- examining TYPE_READONLY.
- * function.c (assign_stack_temp_for_type): Likewise.
+ * config/mips/linux.h: Fix typo.
-2002-10-12 John David Anglin <dave@hiauly1.hia.nrc.ca>
+2003-05-06 Ulrich Weigand <uweigand@de.ibm.com>
- * tree.c (tree_size): Revise expressions using TREE_CODE_LENGTH and
- TREE_VEC_LENGTH to ensure values are promoted before doing subtraction.
+ PR other/10650
+ * unwind-dw2.c (uw_update_context_1): Don't set sp as cfa on s390.
+ (uw_init_context_1): Set initial sp to outer cfa on s390.
-2002-10-11 Janis Johnson <janis187@us.ibm.com>
+2003-05-06 Mark Mitchell <mark@codesourcery.com>
- * doc/compat.texi: Add info about C++ libraries.
+ PR other/10658
+ * gcc.c (process_command): Update copyright date.
-Thu Oct 10 19:47:41 CEST 2002 Jan Hubicka <jh@suse.cz>
+2003-05-06 Bruce Korb <bkorb@gnu.org>
- PR target/5610
- * invoke.texi (-msse-math): Kill
- (-msse): Add note to mfpmath=sse.
+ * inclhack.def: fix up whitespace differences from mainline.
+ mark fix tests that fail on BSD systems (like mainline).
+ Fixup the solaris_mutex_init test to cope with Sol. 2.6 (like mainline).
+ Removed unused SONY commentary (its obsolete anyway).
+ (svr4_mach_defines): remove i860 machine from comment (like mainline).
+ * gcc/fixinc/tests/base/pthread.h: solaris_mutex_init fix tests
+ * gcc/fixinc/tests/base/testing.h: remove ^M chars from some mistake
+ * gcc/fixinc/tests/base/Xm/Traversal.h: accommodate BSD's sed
+ * gcc/fixinc/tests/base/sys/stat.h: accommodate BSD's sed
+ * gcc/fixinc/fixincl.x: regenerated
-Thu Oct 10 17:38:29 CEST 2002 Jan Hubicka <jh@suse.cz>
+2003-05-06 Phil Edwards <pme@gcc.gnu.org>
- PR ice/7951
- * reload1.c (emit_input_reload_insns): Use constrain_operands
- instead of constraint_accepts_reg_p to verify optimization.
- (constraint_accepts_reg_p): Kill
+ * doc/install.texi (mips-*-*): Add note about libstdc++.
-Thu Oct 10 17:05:22 CEST 2002 Jan Hubicka <jh@suse.cz>
+2003-05-05 Mark Mitchell <mark@codesourcery.com>
+ Kean Johnston <jkj@sco.com>
- PR target/7723
- * i386.c (ix86_expand_vector_move): Do not generate const0->mem moves.
+ * toplev.c (check_global_declarations): Do not warn about unused
+ static consts.
-2002-10-09 Zack Weinberg <zack@codesourcery.com>
+2003-05-05 Richard Henderson <rth@redhat.com>
- PR c/7353
- * c-decl.c (start_decl): Unconditionally issue error for
- 'typedef foo = bar'.
- (finish_decl): Remove special case for TYPE_DECL with initializer.
+ * builtins.c (expand_builtin) <BUILT_IN_DWARF_FP_REGNUM>: Remove.
+ <BUILT_IN_DWARF_SP_COLUMN>: New.
+ * builtins.def (BUILT_IN_DWARF_FP_REGNUM): Remove.
+ (BUILT_IN_DWARF_SP_COLUMN): New.
+ * dwarf2out.c (expand_builtin_dwarf_fp_regnum): Remove.
+ (expand_builtin_dwarf_sp_column): New.
+ * except.h: Update to match.
+ * unwind-dw2.c (execute_stack_op): Correct stack push typo.
+ (execute_cfa_program): Record location expression address
+ before extracting length.
+ (uw_update_context_1): Install old CFA into stack pointer column.
+ (uw_init_context_1): Set cfa_reg to stack pointer column.
- * doc/extend.texi: Delete "Naming Types" section. Change all
- cross-references to that section to refer to "Typeof" instead.
- Add the useful safe-max()-macro example from "Naming Types" to
- "Typeof", rewritten using that extension. Add some compatibility
- notes to "Typeof."
+2003-05-05 David O'Brien <obrien@FreeBSD.org>
-2002-10-02 Richard Henderson <rth@redhat.com>
+ * config/rs6000/sysv4.h (CPP_OS_FREEBSD_SPEC): Add __ELF__ to mirror
+ other FreeBSD ports.
+ (LINK_OS_FREEBSD_SPEC): Mirror conventions on other FreeBSD ports.
- PR opt/7124
- * config/i386/i386.c (ix86_register_move_cost): Increase cost
- for secondary_memory_needed pairs.
+2003-05-05 Jason Merrill <jason@redhat.com>
-Wed Oct 9 19:09:13 CEST 2002 Jan Hubicka <jh@suse.cz>
+ * stor-layout.c (update_alignment_for_field): Set DECL_ALIGN for
+ the field.
- PR opt/7912
- PR opt/7390
- * i386.c (athlon_cost): Fix the move costs.
+2003-05-02 Zack Weinberg <zack@codesourcery.com>
-2002-10-09 Alan Modra <amodra@bigpond.net.au>
+ PR c/10604
+ * c-opts.c (c_common_decode_option <OPT_Wall>): Set
+ warn_sign_compare for C++ only.
+ * doc/invoke.texi: Clarify documentation of -Wsign-compare.
- * libgcc2.c (__floatdisf): Properly cure double rounding.
+2003-05-03 Falk Hueffner <falk.hueffner@student.uni-tuebingen.de>
+ Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-10-09 Gabriel Dos Reis <gdr@integrable-solutions.net>
+ * doc/contrib.texi (Contributors): Add Zdenek Dvorak, Aldy
+ Hernandez, and Kazu Hirata.
- PR doc/7484
- * doc/invoke.texi (Option Summary): List
- -Wmissing-declarations as a C only option.
+2003-05-02 Richard Henderson <rth@redhat.com>
-2002-10-08 Jakub Jelinek <jakub@redhat.com>
+ PR c++/10570
+ * except.c: Revert 04-01 and 04-02 forced-unwind changes.
+ * flags.h, toplev.c, doc/invoke.texi: Likewise.
- * config/sparc/t-linux64 (MULTILIB_OPTIONS): Remove
- mno-app-regs|mcmodel=medany.
- (MULTILIB_DIRNAMES, MULTILIB_OSDIRNAMES): Remove alt.
- (MULTILIB_EXCEPTIONS, MULTILIB_EXCLUSIONS, MULTILIB_MATCHES): Remove.
- (CRTSTUFF_T_CFLAGS): Define.
+ * unwind-dw2.c (_Unwind_GetCFA): Fix ptr->int conversion warning.
+ * unwind.inc (_Unwind_DeleteException): Check for null
+ exception_cleanup.
-2002-09-25 Eric Botcazou <ebotcazou@libertysurf.fr>
- Volker Reichelt <reichelt@igpm.rwth-aachen.de>
+ * unwind-sjlj.c (_Unwind_SjLj_Resume_or_Rethrow): New.
+ * unwind.inc (_Unwind_Resume_or_Rethrow): New.
+ * unwind.h: Declare them.
+ * libgcc-std.ver (GCC_3.3): Export them.
- PR c/7411
- * expr.c (expand_expr) [PLUS]: Simplify after the operands
- have been expanded in EXPAND_NORMAL mode.
+2003-05-02 Steven Bosscher <steven@gcc.gnu.org>
-2002-10-06 Richard Henderson <rth@redhat.com>
+ * tree-inline.c (find_alloca_call):
+ Use walk_tree_without_duplicates, instead of walk_tree.
+ (find_builtin_longjmp_call): Ditto.
+ * c-objc-common.c (c_cannot_inline_fn): Ditto.
- * config/rs6000/rs6000.md (load_toc_v4_PIC_2): Fix base constraint.
+2003-05-02 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-10-06 Roger Sayle <roger@eyesopen.com>
+ * doc/contrib.texi (Contributors): Add Daniel Berlin.
- PR optimization/6627
- * toplev.c (force_align_functions_log): New global variable.
- * flags.h (force_align_functions_log): Add extern prototype.
- * varasm.c (assemble_start_function): Use it to force minimum
- function alignment.
- * config/i386/i386.h (FUNCTION_BOUNDARY): Set the correct
- minimum function alignment to one byte.
- (TARGET_PTRMEMFUNC_VBIT_LOCATION): Store the virtual bit in
- the least significant bit of vtable member function pointers.
- * tree.h (enum ptrmemfunc_vbit_where_t): Move definition to
- here from cp/cp-tree.h.
+2003-05-01 Rodney Brown <rbrown64@csc.com.au>
-2002-10-06 Neil Booth <neil@daikokuya.co.uk>
+ * rtl.h (subreg_offset_representable_p): Prototype.
- Debian BTS Bug #157416
- * cpplib.c (destringize_and_run): Kludge around getting
- tokens from in-progress macros.
- (_cpp_do__Pragma): Simplify.
+2003-05-01 Roger Sayle <roger@eyesopen.com>
-2002-10-06 Frank Ch. Eigler <fche@redhat.com>
+ PR fortran/9974
+ * gcse.c (reg_killed_on_edge): New function to test whether the
+ given reg is overwritten by any instruction queued on an edge.
+ (bypass_block): Ignore substitutions killed on incoming edges.
+ Don't bypass outgoing edges that have queued instructions.
- * cppinit.c (init_standard_includes, parse_option): Use strncmp.
+2003-04-30 Andreas Schwab <schwab@suse.de>
-2002-10-05 Jakub Jelinek <jakub@redhat.com>
+ * doc/extend.texi (Other Builtins): Enclose multiple word data
+ type in braces for @deftypefn.
- * gcc.c (set_multilib_dir): Don't access *end.
- Use memcpy instead of strncpy. Don't write beyond malloced buffer.
- (print_multilib_info): Don't show paths starting with ".:".
- * genmultilib: Add new option, "yes" if multilibs are enabled.
- Update comments. If multilibs not enabled, print .:${osdirout}
- for each directory. If multilibs are enabled, always print
- ${dirout}:${osdirout}, even if the two are the same.
- * Makefile.in (s-mlib): Pass @enable_multilib@ to genmultilib.
- Pass all MULTILIB_* variables to genmultilib even if
- --disable-multilib but MULTILIB_OSDIRNAMES is not empty.
+2003-04-29 Jason Merrill <jason@redhat.com>
- * gcc.c (print_multi_os_directory): New variable.
- (option_map): Support --print-multi-os-directory.
- (struct prefix_list): Add os_multilib field.
- (multilib_os_dir): New variable.
- (static_specs): Add multilib_options.
- (find_a_file): Add multilib argument. Search in GCC or OS multilib
- subdirs if non-zero.
- (read_specs, execute): Update callers.
- (find_file): Likewise. Don't prefix name with multilib_dir, instead
- pass 1 as multilib option.
- (display_help): Include --print-multi-os-directory.
- (add_prefix): Add os_multilib argument. Initialize pl->os_multilib.
- (process_command): Update callers. Handle --print-multi-os-directory.
- (do_spec_1) ['D']: Use multilib_os_directory if pl->os_multilib is
- set.
- (main): Update find_a_file and add_prefix callers.
- Handle print_multi_os_directory.
- (struct mdswitchstr): New.
- (mdswitches, n_mdswitches): New variables.
- (used_arg): Add MULTILIB_DEFAULT switches too if they are not
- present on the command line nor their mutually incompatible
- switches.
- (default_arg): Optimize.
- (set_multilib_dir): Compute multilib_os_dir. Initialize mdswitches
- array.
- (print_multilib_info): Only print GCC multilib dir name, not OS
- multilib dirname.
- * genmultilib: Add osdirnames parameter. Output multilib_options
- variable. If osdirnames is specified, output dirnames as
- dirname:osdirname.
- * mklibgcc.in: Use MULTILIB_OSDIRNAMES, --print-multi-directory
- and --print-multi-os-directory instead of SHLIB_SLIBDIR_SUFFIXES
- to compute libgcc_s soname and install path.
- * Makefile.in (libgcc.mk): Pass MULTILIB_OSDIRNAMES instead of
- SHLIB_SLIBDIR_SUFFIXES to mklibgcc.
- (s_mlib): Pass MULTILIB_OSDIRNAMES or nothing as last genmultilib
- argument.
+ PR middle-end/10336
+ * jump.c (never_reached_warning): Really stop looking if we reach
+ the beginning of the function.
- * config/sparc/t-linux64 (MULTILIB_OSDIRNAMES): Set.
- (SHLIB_SLIBDIR_SUFFIXES): Remove.
- * config/sparc/linux64.h (STARTFILE_SPEC32, STARTFILE_SPEC64,
- ENDFILE_SPEC32, ENDFILE_SPEC64, ENDFILE_COMMON): Remove.
- (STARTFILE_SPEC, ENDFILE_SPEC): Don't distinguish between -m32
- and -m64.
- * config/sparc/t-sol2-64 (MULTILIB_OSDIRNAMES): Set.
- (SHLIB_SLIBDIR_SUFFIXES): Remove.
- * config/sparc/sol2-bi.h (STARTFILE_SPEC32, STARTFILE_SPEC64): Remove.
- (STARTFILE_ARCH_SPEC): Remove.
- (STARTFILE_SPEC): Add values-X*.o here.
- * config/i386/t-linux64 (MULTILIB_OSDIRNAMES): Set.
- (SHLIB_SLIBDIR_SUFFIXES): Remove.
- * config/i386/linux64.h (STARTFILE_PREFIX_SPEC): Remove.
- (STARTFILE_SPEC, ENDFILE_SPEC): Don't distinguish between m32 and
- !m32.
- * config/mips/t-iris6 (MULTILIB_OSDIRNAMES): Set.
- (SHLIB_SLIBDIR_SUFFIXES): Remove.
+Tue Apr 29 21:07:00 CEST 2003 Jan Hubicka <jh@suse.cz>
-2002-10-05 Neil Booth <neil@daikokuya.co.uk>
+ * cse.c (count_reg_usage): Revert my previous patch.
- PR preprocessor/8120
- * doc/cpp.texi: Update documentation of bad use of ##.
+2003-04-29 Alexander Kabaev <kan@FreeBSD.ORG>
-Thu Oct 3 23:15:15 CEST 2002 Jan Hubicka <jh@suse.cz>
+ bootstrap/10452
+ * gengtype-yacc.y: Improve portability.
- * i386.h (CPP_SPECS): fix defines for -msse, -msse2, -mpentium2,3.
+2003-04-29 Zack Weinberg <zack@codesourcery.com>
-Thu Oct 3 21:35:36 CEST 2002 Jan Hubicka <jh@suse.cz>
+ * config.gcc: Install obsolete target list for GCC 3.3.
+ * doc/install.texi: Mention in specific-target instructions
+ that certain configurations are deprecated.
- * toplev.c (rest_of_compilation): Dump loops before clobbering
- the structure.
+2003-04-29 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
- * expr.c (force_operand): Use expand_simple_* to handle more
- cases.
+ * c-pragma.c (maybe_apply_renaming_pragma): Fix typo.
+ * gcc.c (display_help): Likewise.
+ * toplev.c (f_options): Likewise.
+ * params.def (PARAM_MAX_INLINE_SCOPE): Likewise.
+ * config/c4x/c4x.h (TARGET_SWITCHES): Likewise.
+ * config/mcore/mcore.h (TARGET_SWITCHES): Likewise.
+ * config/s390/s390.h (TARGET_SWITCHES): Likewise.
+ * config/v850/v850.h (TARGET_SWITCHES): Likewise.
- * i386.c (q_regs_operand): Use ANY_QI_REG_P.
+2003-04-29 Danny Smith <dannysmith@users.sourceforge.net>
- * i386.c (override_options): Fix stack alignment.
- (classify_argument): Handle variable sized types.
- (ix86_expand_int_movcc): Avoid RTL sharing problem.
+ * config/i386/mingw32.h (LIBGCC_SPEC): Add libmingwex.a.
+ Update copyright.
+ * config/i386/cygwin.h (LIBGCC_SPEC): Add libmingwex.a, for
+ -mno-cygwin case.
- * i386.md (prefetch_sse_rex, prefetch_3dnow_rex): New.
- (prefetch): Properly handle 64bit case.
+2003-04-29 J"orn Rennecke <joern.rennecke@superh.com>
- * i386.c (classify_argument): Properly compute word size of the analyzed object.
+ * varasm.c (default_assemble_visibility): Use assemble_name.
- * jump.c (reg_or_subregno): New function.
- * rtl.h (reg_or_subregno): Declare
- * unroll.c (find_splittable_givs): Handle subregs.
+2003-04-29 David O'Brien <obrien@FreeBSD.org>
- Richard Sandiford <rsandifo@redhat.com>:
+ * config/i386/freebsd64.h (LINK_SPEC): Mirror FreeBSD linker.
+ * config/rs6000/freebsd.h (LINK_SHLIB_SPEC): New macro.
+ (SIZE_TYPE): New macro.
+ * config/i386/freebsd-aout.h (NO_PROFILE_COUNTERS): New macro.
+ (SET_ASM_OP): New macro.
+ (HANDLE_SYSV_PRAGMA): New macro.
+ (ASM_WEAKEN_LABEL): New macro.
- * expr.c (force_operand): Fix reversed move.
+2003-04-28 Mark Mitchell <mark@codesourcery.com>
- Andreas Jaeger <aj@suse.de>:
+ PR c++/10180
+ * tree-inline.c (expand_call_inline): Call push_srcloc when
+ encountering EXPR_WITH_FILE_LOCATION. Honor warn_inline.
- * config/i386/linux64.h (STARTFILE_PREFIX_SPEC): New.
+2003-04-28 Mike Stump <mrs@apple.com>
- Janis Johnson <janis187@us.ibm.com>:
+ * gdbinit.in: Update to reflect new identifier structure.
- * loop.c (emit_prefetch_instructions): Several small fixes.
+2003-04-28 Richard Henderson <rth@redhat.com>
-Thu Sep 5 00:34:33 2002 J"orn Rennecke <joern.rennecke@superh.com>
+ * config/sparc/sparc.c (print_operand): Add 's' to sign-extend.
+ * config/sparc/sparc.md (const_mulsidi3_v8plus): Fix mode of
+ integral constant mult operand.
+ (const_mulsidi3_sp32, const_mulsidi3_sp64): Likewise.
+ (const_smulsi3_highpart_v8plus): Likewise.
+ (const_smulsi3_highpart): Likewise.
+ (const_umulsidi3_sp32): Likewise; sign-extend it in the output.
+ (const_umulsidi3_sp64, const_umulsidi3_v8plus): Likewise.
+ (const_umulsi3_highpart_v8plus): Likewise.
+ (const_umulsi3_highpart): Likewise.
- * loop.c (scan_loop): Don't mark separate insns out of a libcall
- for moving.
- (move_movables): Abort if we see the first insn of a libcall.
+2003-04-28 David O'Brien <obrien@FreeBSD.org>
-2002-10-01 David S. Miller <davem@redhat.com>
+ * config/i386/i386.h (builtin_define): Add __amd64 and __amd64__.
- PR middle-end/7151
- * config/sparc/sparc.md (movdi_insn_sp32_v9): Accept 'e' regs.
- (movdi reg/reg split): Match only on sparc32, and v9 when int regs.
+Mon Apr 28 09:54:56 CEST 2003 Jan Hubicka <jh@suse.cz>
-2002-10-01 David S. Miller <davem@redhat.com>
- Jan Hubicka <jh@suse.cz>
+ PR c/10308
+ * reload.c (find_reloads_address_1): Reload plus at the place of
+ index register.
- * reload1.c (gen_reload:SECONDARY_MEMORY_NEEDED): Handle SUBREG.
- * reload.c (push_reload:SECONDARY_MEMORY_NEEDED): Likewise.
+2003-04-26 Richard Henderson <rth@redhat.com>
-2002-09-30 Bob Wilson <bob.wilson@acm.org>
+ * config/ia64/ia64.c (ia64_compute_frame_size): Allow inline asm
+ to clobber ar.pfs and ar.unat.
+ (ia64_expand_prologue): Force alloc instruction if ar.pfs saved;
+ fix test for spilling ar.pfs to the stack.
- * config/xtensa/xtensa.h (REG_CLASS_NAMES, REG_CLASS_CONTENTS):
- Add new RL_REGS register class.
- (PREFERRED_RELOAD_CLASS, PREFERRED_OUTPUT_RELOAD_CLASS):
- Call xtensa_preferred_reload_class for both input and output reloads.
- * config/xtensa/xtensa.c (xtensa_regno_to_class): Use new RL_REGS class.
- (xtensa_preferred_reload_class): Handle output reloads; use RL_REGS
- instead of either AR_REGS or GR_REGS classes.
- (xtensa_secondary_reload_class): Use new RL_REGS class.
- * config/xtensa/xtensa-protos.h (xtensa_preferred_reload_class): Update.
+2003-04-26 Stephane Carrez <stcarrez@nerim.fr>
-2002-08-21 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ * doc/install.texi (Binaries): Mention binaries for HC11/HC12.
- * cppinit.c (remove_dup_nonsys_dirs): Fix warning and return value.
+2003-04-26 Stephane Carrez <stcarrez@nerim.fr>
-2002-08-20 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ * doc/extend.texi (Function Attributes): Document "near" and "far"
+ for 68HC11 and 68HC12.
- * cppinit.c (remove_dup_dir): Add head_ptr argument to handle removal
- at head.
- (remove_dup_nonsys_dirs): New function.
- (remove_dup_dirs): Change argument head to head_ptr. Remove warnings.
- (merge_include_chains): Remove non-system include directories from
- quote and bracket include chains when they duplicate equivalent system
- directories.
- * doc/cpp.texi (-I): Update.
- * doc/cppopts.texi (-I): Update.
- * doc/install.texi (--with-local-prefix): Further document usage of
- this option.
- * doc/invoke.texi (-I): Update.
+2003-04-25 Bob Wilson <bob.wilson@acm.org>
-2002-09-30 Richard Earnshaw <rearnsha@arm.com>
+ * config/xtensa/linux.h (TARGET_OS_CPP_BUILTINS): Back out previous
+ addition of __PIC__ and __pic__ macros.
+ * config/xtensa/xtensa.h: Clean up indentation.
- * arm.h (BASE_REG_CLASS): Always return LO_REGS for Thumb.
- (MODE_BASE_REG_CLASS, case Thumb): Only return BASE_REGS if we know
- that we have a SImode access, and only then if reload hasn't completed;
- for all other cases, use LO_REGS.
+2003-04-25 Bob Wilson <bob.wilson@acm.org>
-2002-09-29 David S. Miller <davem@redhat.com>
+ * config/xtensa/linux.h (TARGET_OS_CPP_BUILTINS): Remove definition of
+ _GNU_SOURCE. Add definitions of __PIC__ and __pic__.
+ (SUBTARGET_CPP_SPEC): Define.
+ (LIB_SPEC): Delete.
+ * config/xtensa/xtensa-protos.h (xtensa_declare_object): Delete.
+ * config/xtensa/xtensa.c (xtensa_declare_object): Delete.
+ * config/xtensa/xtensa.h (CPP_SPEC, SUBTARGET_CPP_SPEC, EXTRA_SPECS):
+ Define.
+ (ASM_OUTPUT_COMMON, ASM_OUTPUT_LOCAL): Delete.
+ (ASM_OUTPUT_ALIGNED_BSS, BSS_SECTION_ASM_OP): Define.
+
+2003-04-25 Richard Henderson <rth@redhat.com>
+
+ PR opt/10315
+ * config/rs6000/rs6000.c (rs6000_emit_move): Only elide proper
+ checks during reload; use validize_mem instead of adjust_address.
+
+Fri Apr 25 15:43:23 CEST 2003 Jan Hubicka <jh@suse.cz>
+
+ * emit-rtl.c (subreg_hard_regno): Check that register is
+ representable.
+ * reload.c (reload_inner_reg_of_subreg): When register is not
+ representable, reload the whole thing.
+ (find_reloads): Likewsie.
+ * rtlanal.c (subreg_representable_p): New function.
+
+Sun Apr 20 18:23:18 CEST 2003 Richard Henderson <rth@redhat.com>
+
+ (backported to 3.3 by Jan Hubicka)
+
+ * config/ia64/ia64.md (UNSPECV_SETJMP_RECEIVER): New.
+ (builtin_setjmp_receiver): Delay call to ia64_reload_gp
+ until after reload.
+
+ * emit-rtl.c (try_split): Handle 1-1 splits of call insns properly.
+
+ * config/ia64/ia64.c (TARGET_FUNCTION_OK_FOR_SIBCALL): New.
+ (ia64_gp_save_reg): Remove.
+ (struct ia64_frame_info): Move to the beginning of the file;
+ add reg_save_gp.
+ (ia64_expand_call): Rearrange for new call patterns.
+ (ia64_reload_gp): New.
+ (ia64_split_call): New.
+ (ia64_compute_frame_size): Allocate reg_save_gp.
+ (ia64_expand_prologue): Save reg_save_gp.
+ (ia64_expand_epilogue): Don't restore gp.
+ (ia64_hard_regno_rename_ok): Remove R4 hack.
+ (ia64_function_ok_for_sibcall): New.
+ (ia64_output_mi_thunk): Set reload_completed, no_new_pseudos;
+ call try_split on sibcall pattern.
+ * config/ia64/ia64-protos.h: Update.
+ * config/ia64/ia64.md (call_nogp, call_value_nogp, sibcall_nogp):
+ Rename from nopic versions. Confiscate 2nd argument to call as
+ a marker.
+ (call_pic, call_value_pic, sibcall_pic): Remove.
+ (call_gp, call_value_gp, sibcall_gp): New.
+ (builtin_setjmp_setup): Remove.
+ (builtin_setjmp_receiver): Call ia64_reload_gp.
- * config/sparc/linux64.h (STARTFILE_SPEC32, ENDFILE_SPEC32): Kill
- hardcoded paths.
+2003-04-24 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
-2002-09-27 Alexander N. Kabaev <ak03@gte.com>
+ PR opt/8705
+ * gcse.c (try_replace_reg): On a successful substitution of a constant
+ into a single set, try to simplify the source of the set.
+ * loop.c (scan_loop): Don't try to optimize a MODE_CC set with a
+ constant source.
- PR preprocessor/8055
- * cppmacro.c (stringify_arg): Do not overflow the buffer
- with the terminating NUL when the argument to be stringified
- has no tokens.
+2003-04-24 Alexander Kabaev <kan@FreeBSD.ORG>
-2002-09-26 David S. Miller <davem@redhat.com>
+ bootstrap/10453
+ * config/sparc/sparc.md (umulsidi3, mulsidi3): Avoid using
+ const_umulsidi3_sp32 and const_mulsidi3_sp32 on 64bit targets
+ where they might be not present. Use their _sp64 equivalent
+ instead.
- PR optimization/7335
- * calls.c (emit_library_call_value_1): Passing args by reference
- converts a CONST function into a PURE one.
+2003-04-23 Richard Henderson <rth@redhat.com>
-2002-09-26 Richard Henderson <rth@redhat.com>
+ PR opt/8300
+ * toplev.c (rest_of_compilation): Delay no_new_pseudos until
+ after initialize_uninitialized_subregs; update reg info assuming
+ new pseudos were created.
- PR c/7160
- * sched-deps.c (sched_analyze_insn): Make clobber insns depend
- on call insns.
+2003-04-23 Olivier Hainque <hainque@act-europe.fr>
-2002-09-27 Alan Modra <amodra@bigpond.net.au>
+ * config/pa/pa.md (extv, extzv): FAIL if the bitfield length is zero.
- * doloop.c (doloop_modify_runtime <biv skips initial incr>): Adjust
- by absolute loop increment, not loop increment.
+2003-04-23 James A Morrison <ja2morri@uwaterloo.ca>
-2002-09-25 David S. Miller <davem@redhat.com>
+ * invoke.texi: Eliminate extra white-space caused by @gccoptlist{
+ on its own line.
+ Ensure there are two spaces between each pair of options and add
+ @gol where appropriate.
- PR target/7842
- * config/sparc/sparc.c (set_extends): SImode ASHIFT does not
- extend.
+2003-04-23 Ulrich Weigand <uweigand@de.ibm.com>
-2002-09-20 Jeroen Dobbelaere <jeroen.dobbelaere@acunia.com>
+ * config/s390/s390.c (s390_expand_cmpstr): Disable CLC loop.
- * config/arm/arm.md (sign_extract_onebit, not_signextract_onebit):
- Add clobber of the condition code register.
+2003-04-22 Devang Patel <dpatel@apple.com>
-2002-09-18 Richard Earnshaw (rearnsha@arm.com)
+ * cpptrad.c (_cpp_replacement_text_len): Add check for macro parameter count.
+ (_cpp_copy_replacement_text): Same.
- PR optimization/7967
- * arm.md (ne_zeroextractsi): Add clobber of the condition code
- register.
+2003-04-22 Richard Henderson <rth@redhat.com>
-2002-09-17 Richard Henderson <rth@redhat.com>
+ PR 8866
+ * rtl.h (MEM_NOTRAP_P): New.
+ (MEM_COPY_ATTRIBUTES): Copy it.
+ * rtlanal.c (may_trap_p): Check it.
+ * expr.c (do_tablejump): Set it.
- * sibcall.c (optimize_sibling_and_tail_recursive_call): Also remove
- RTX_UNCHANGING_P markers for successful tail-recursive replacement.
+ * cfgrtl.c (try_redirect_by_replacing_jump): Revert last three changes.
-2002-09-16 Richard Henderson <rth@redhat.com>
+2003-04-22 David Turner <novalis@gnu.org>
- PR opt/7515
- * c-objc-common.c (c_cannot_inline_tree_fn): Don't auto-inline
- functions that don't bind locally.
+ * gbl-ctors.h: Add special license exception.
+ * libgcc2.h: Likewise.
+ * tsystem.h: Likewise.
+ * gcov-io.h: Likewise.
-2002-09-17 Alan Modra <amodra@bigpond.net.au>
+2003-04-21 Mark Mitchell <mark@codesourcery.com>
- Merge from mainline.
- 2002-07-20 Alan Modra <amodra@bigpond.net.au>
- PR optimization/7130
- * loop.h (struct loop_info): Add "preconditioned".
- * unroll.c (unroll_loop): Set it.
- * doloop.c (doloop_modify_runtime): Correct count for unrolled loops.
+ * Makefile.in (calls.o): Depend on except.h.
+ * calls.c: Include except.h.
+ (emit_call_1): Call note_eh_region_may_contain_throw if
+ appropriate.
+ * except.c (eh_region): Add may_contain_throw.
+ (expand_eh_region_end_cleanup): Do not include handler code when
+ it cannot be reached.
+ (note_eh_region_may_contain_throw): New function.
+ * except.h (note_eh_region_may_contain_throw): New function.
- 2002-06-24 Alan Modra <amodra@bigpond.net.au>
- PR optimization/6984
- * doloop.c (doloop_valid_p): Correct comment.
- (doloop_modify_runtime <abs_inc != 1>): Simplify.
- (doloop_modify_runtime <do-while>): Don't emit code when NE.
+2003-04-21 Mark Mitchell <mark@codesourcery.com>
-2002-09-16 Jeff Law <law@redhat.com>
+ * config/i386/winnt.c (i386_pe_mark_dllimport): Revert previous
+ changes.
- * libgcc2.c: Do not include machmode.h.
+2003-04-21 Mark Mitchell <mark@codesourcery.com>
-2002-09-16 Jason Merrill <jason@redhat.com>
- Danny Smith <dannysmith@users.sourceforge.net>
+ * config/i386/winnt.c (i386_pe_mark_dllimport): Make the new RTL
+ have the same form as the old RTL.
- * config/i386/winnt.c (ix86_handle_dll_attribute): Set
- DECL_EXTERN and TREE_PUBLIC for dllimported variables here...
- (i386_pe_mark_dllimport): Not here.
+2003-04-18 Mark Mitchell <mark@codesourcery.com>
-2002-09-14 Stephane Carrez <stcarrez@nerim.fr>
+ * cfgrtl.c (try_redirect_by_replacing_jump): Create a basic block
+ for orphaned jump tables.
- * config/m68hc11/m68hc11.md ("movdi_internal"): Allow any offsetable
- memory operand when source is 0 (K constraint).
- ("movsi_internal"): Likewise.
- ("movdf_internal"): Likewise.
- ("movsf_internal"): Likewise.
+2003-04-20 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
-2002-09-14 Alan Modra <amodra@bigpond.net.au>
+ PR/8705
+ * pa.md (movccfp): New expander.
+ (setccfp0, setccfp1): Rename to movccfp0 and movccfp1, respectively.
+ Reverse fcmp conditions.
- Merge from mainline.
- 2002-09-14 Alan Modra <amodra@bigpond.net.au>
- * doc/tm.texi (DBX_OUTPUT_NFUN): Describe.
- * dbxout.c (dbxout_function_end): Use DBX_OUTPUT_NFUN.
- * config/rs6000/linux64.h (DBX_OUTPUT_NFUN): Define.
+2003-04-20 Marek Michalkiewicz <marekm@amelek.gda.pl>
- 2002-08-27 David Edelsohn <edelsohn@gnu.org>
- * config/rs6000/linux64.h (ADJUST_FIELD_ALIGN): Undef before define.
+ * config/avr/avr.md (*cmpqi_sign_extend): Handle negative values
+ of operand 1 correctly.
- 2002-08-02 Alan Modra <amodra@bigpond.net.au>
- * config/rs6000/linux64.h (DBX_OUTPUT_BRAC): Define.
- (DBX_OUTPUT_LBRAC, DBX_OUTPUT_RBRAC): Define.
- * config/rs6000/rs6000.c (output_toc): Don't use lshift_double when
- HOST_BITS_PER_WIDE_INT == 64.
+2003-04-19 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
- 2002-07-27 Alan Modra <amodra@bigpond.net.au>
- * config/rs6000/rs6000.c (output_profile_hook): Don't generate profile
- label reference when NO_PROFILE_COUNTERS.
+ * cfgrtl.c (try_redirect_by_replacing_jump): Remove unused variables.
+ * flow.c (life_analysis): Fix warning.
- 2002-07-11 Alan Modra <amodra@bigpond.net.au>
- * config/rs6000/linux64.h (ASM_SPEC): Define.
+2003-04-18 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-09-13 Alan Modra <amodra@bigpond.net.au>
+ * doc/contrib.texi (Contributors): Prefer "bug fix" over "bugfix".
+ Add Segher Boessenkool.
- Merge from mainline.
- 2002-07-24 Alan Modra <amodra@bigpond.net.au>
- PR c/7150, target/7380
- * config/rs6000/rs6000.md: Remove scratch reg on insns using
- addze and similar (plus (comparison r1 r2) r3) insns. Add
- missing scratch reg in one case. Formatting fixes.
+2003-04-18 Alexander Sotirov <sluncho@mirizma.org>
- 2002-07-18 Alan Modra <amodra@bigpond.net.au>
- PR other/7114, target/5967
- * config/rs6000/rs6000.c (first_reg_to_save): Remove bogus
- adjustments to first_reg for profiling case.
- (output_function_profiler): Correct lr save slot for ABI_AIX_NODESC.
- Disable profiling for 64 bit code on both ABI_V4 and ABI_AIX_NODESC.
- Save static chain reg to sp + 12 on ABI_AIX_NODESC.
- * config/rs6000/sysv4.h (ASM_OUTPUT_REG_PUSH): Define.
- (ASM_OUTPUT_REG_POP): Define.
- * config/rs6000/linux64.h (ASM_OUTPUT_REG_PUSH): Undef.
- (ASM_OUTPUT_REG_POP): Undef.
+ PR c/9177
+ * c-decl.c (c_expand_body): Don't garbage collect the function
+ body if we are going to dump it later.
- 2002-06-30 Alan Modra <amodra@bigpond.net.au>
- PR optimization/7120
- * unroll.c (loop_iterations): Handle EQ loops.
+2003-04-18 Eric Botcazou <ebotcazou@libertysurf.fr>
-2002-09-13 Alan Modra <amodra@bigpond.net.au>
+ PR optimization/7675
+ * c-typeck.c (build_external_ref): Set the DECL_NONLOCAL flag
+ on VAR_DECL, PARM_DECL and FUNCTION_DECL from within
+ nested functions if they refer to declarations from parent functions.
+ * stmt.c (expand_decl): Don't put automatic variables in registers
+ if the DECL_NONLOCAL flag is set.
- * config/rs6000/rs6000.c (rs6000_emit_load_toc_table): Remove "if"
- nesting. Correct test for non-PowerPC64 ELF ABI_AIX.
- * config/rs6000/rs6000.md (load_toc_v4_PIC*): Disable when ABI_AIX.
+2003-04-17 Janis Johnson <janis187@us.ibm.com>
-2002-09-12 Janis Johnson <janis187@us.ibm.com>
+ * doc/sourcebuild.texi (Test Suites): Document support for testing
+ binary compatibility (moved from testsuite/README.compat).
- * doc/compat.texi: New file with new chapter, Binary Compatibility.
+2003-04-17 Simon Law <sfllaw@engmail.uwaterloo.ca>
-2002-09-12 Jason Merrill <jason@redhat.com>
+ * doc/include/gpl.texi: Fix double-spacing after "MA" to match
+ the one provided by the FSF.
- * calls.c (store_one_arg): Use size_in_bytes to determine the
- amount of space to push.
+2003-04-17 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-09-12 Jakub Jelinek <jakub@redhat.com>
+ * doc/install.texi (Binaries): Update URL and list of platforms
+ provided by ftp.thewrittenword.com.
- * config/sparc/linux64.h (STARTFILE_SPEC32): Fix a typo.
+2003-04-17 Eric Botcazou <ebotcazou@libertysurf.fr>
-2002-09-12 Alan Modra <amodra@bigpond.net.au>
+ * doc/invoke.texi (inline-limit): Fix pasto.
- * emit-rtl.c (set_mem_size): New function.
- * expr.h (set_mem_size): Declare.
- * config/rs6000/rs6000.c (expand_block_move_mem): Exterminate.
- (expand_block_move): Instead, use adjust_address and
- replace_equiv_address to generate proper aliasing info.
- Move common code out of conditionals. Localize vars.
+2003-04-16 Mark Mitchell <mark@codesourcery.com>
-2002-09-11 Alexander Kabaev <kan@FreeBSD.ORG>
+ PR middle-end/8866
+ * cfgtrl.c (try_redirect_by_replacing_jump): Do not delete
+ jumptables.
- Wed Apr 24 13:48:25 CEST 2002 Jan Hubicka <jh@suse.cz>
- * loop.c (canonicalize_condition): Use gen_int_mode.
+2003-04-16 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
-2002-09-11 Janis Johnson <janis187@us.ibm.com>
+ PR/10271
+ * pa-protos.h (function_arg): Remove last argument.
+ * pa.c (function_arg): Likewise. Use CUMULATIVE_ARGS struct instead.
+ * pa.h (struct hppa_args): Add member incoming.
+ (INIT_CUMULATIVE_ARGS, INIT_CUMULATIVE_INCOMING_ARGS): Initialize
+ member incoming.
+ (FUNCTION_ARG): Revise call to function_arg.
+ (FUNCTION_INCOMING_ARG): Delete.
- * Makefile.in (TEXI_GCC_FILES): Add compat.texi.
- * doc/gcc.texi (Top): Add new chapter, Binary Compatibility, and
- include its file, compat.texi.
- * doc/trouble.texi (Interoperation): Update information about C++ ABI
- issues.
- * doc/invoke.texi (-fshort-wchar): Move to Code Generation Options.
- (-fpcc-struct-return, -freg-struct-return, -fshort-enums,
- -fshort-double, -fshort-wchar, -fpack-struct, -fleading-underscore):
- Warn that these options can break ABI compatibility.
- (Many places): Fix overfull hboxes.
+2003-04-15 J"orn Rennecke <joern.rennecke@superh.com>
- * doc/extend.texi: Fix a broken link; fix overfull hboxes.
- * doc/install.texi: Fix a typo, some formatting directives, and
- overfull hboxes.
- * doc/c-tree.texi: Fix overfull hboxes.
- * doc/cppopts.texi: Ditto.
- * doc/makefile.texi: Ditto.
- * doc/rtl.texi: Ditto.
- * doc/standards.texi: Ditto.
- * doc/tm.texi: Ditto.
+ PR target/9594:
+ * sh.c (barrier_align): Also recognize stuff_delay_slot as
+ an indicator that a barrier was created by branch splitting.
-2002-09-08 Alan Modra <amodra@bigpond.net.au>
+ merge from mainline:
- * reload.c (find_reloads <p constraint>): Pass operand_mode to
- find_reloads_address.
+ 2003-03-05 J"orn Rennecke <joern.rennecke@superh.com>
-2002-09-07 Scott Snyder <snyder@fnal.gov>
+ * sh.h (OVERRIDE_OPTIONS): For TARGET_SHMEDIA, the minimum value
+ for align_jumps is 4.
- PR target/7374
- * config/alpha/alpha.md (abstf2): Fix typo: 'neg' for 'abs'.
+ (SECONDARY_INPUT_RELOAD_CLASS): If reloading a PLUS into FPUL,
+ use GENERAL_REGS.
-2002-09-07 Glen Nakamura <glen@imodulo.com>
+ 2003-03-03 J"orn Rennecke <joern.rennecke@superh.com>
- PR opt/7814
- * sched-deps.c (sched_analyze_insn): Make sure to add insn
- to reg_last->sets after flushing the dependency lists to guarantee
- that subsequent clobbers will be dependent on it.
+ * sh.h (OVERRIDE_OPTIONS): Set default values for align_loops
+ and align_jumps if not set.
+ Force align_jumps to be at least 2.
+ When relaxing, force align_functions to be at least the maximum of
+ align_loops, align_jumps and 4.
+ * sh.c (find_barrier, barrier_align): Honour align_jumps_log.
+ (sh_loop_align): Honour align_loops_log.
-2002-09-07 Alan Modra <amodra@bigpond.net.au>
+ * sh.md (length attribute): Use prev_nonnote_insn instead of PREV_INSN
+ to check for indirect_jump_scratch.
+ (indirect_jump_scratch): Add second set.
+ * sh.c (output_far_jump): Use prev_nonnote_insn instead of PREV_INSN
+ when looking for indirect_jump_scratch.
+ Extract scratch register taking new structure of indirect_jump_scratch
+ into account.
+ (gen_block_redirect): Set INSN_SCOPE for indirect_jump_scratch.
- * config/rs6000/linux64.h (ASM_PREFERRED_EH_DATA_FORMAT): Define.
+2003-04-15 James A. Morrison <ja2morri@uwaterloo.ca>
-2002-09-06 Jakub Jelinek <jakub@redhat.com>
+ * invoke.texi (Spec Files): Wrap if-exists-else example.
+ (MCore): Remove duplicate @itemx entries and @opindex entries.
- * configure.in (HAVE_AS_OFFSETABLE_LO10): Use -xarch=v9
- unconditionally when gcc_cv_as_flags64 checks are gone.
- * configure: Rebuilt.
+2003-04-15 Ulrich Weigand <uweigand@de.ibm.com>
-2002-09-04 Eric Botcazou <ebotcazou@multimania.com>
+ * unwind.inc (_Unwind_Backtrace): New function.
+ * unwind.h (_Unwind_Backtrace): Declare it.
+ * libgcc-std.ver (_Unwind_Backtrace): Export it.
- PR c/7102
- * optabs.c (expand_binop): Convert CONST_INTs in all cases.
+2003-04-15 Jason Merrill <jason@redhat.com>
-2002-09-04 Jason Thorpe <thorpej@wasabisystems.com>
+ PR middle-end/10336, c++/10401
+ * jump.c (never_reached_warning): Also stop looking if we reach the
+ beginning of the function.
- * config/sparc/t-netbsd64: Disable multilib for now.
+2003-04-15 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-09-01 Alexandre Oliva <aoliva@redhat.com>
+ PR target/10338
+ PR bootstrap/10198
+ PR bootstrap/10140
+ * fixinc/gnu-regex.c (regerror): Use mempcpy not __mempcpy.
- * c-tree.h (skip_evaluation): Move declaration...
- * c-common.h: ... here.
- * c-typeck.c (build_external_ref): Don't assemble_external nor
- mark a tree as used if skip_evaluation is set.
- * c-parse.in (typeof): New non-terminal to set skip_evaluation
- around TYPEOF.
- (typespec_nonreserved_nonattr): Use it.
+2003-04-15 Jakub Jelinek <jakub@redhat.com>
-2002-09-01 Marek Michalkiewicz <marekm@amelek.gda.pl>
+ * config/rs6000/rs6000.h (EPILOGUE_USES): Use register 2,
+ instead of TOC_REGISTER in epilogue in
+ current_function_calls_eh_return functions.
- 2002-08-13 Denis Chertykov <denisc@overta.ru>
- * config/avr/avr.md: Call CC_STATUS_INIT in all peepnoles
- which can change CC0.
+2003-04-14 Hans-Peter Nilsson <hp@axis.com>
-2002-08-29 Rodney Brown <rbrown64@csc.com.au>
+ PR target/10377
+ * config/cris/cris.md ("*mov_sideqi", "*mov_sidehi")
+ ("*mov_sidesi", "*mov_sideqi_mem", "*mov_sidehi_mem")
+ ("*mov_sidesi_mem", "*clear_sidesi", "*clear_sidehi")
+ ("*clear_sideqi", "*ext_sideqihi", "*ext_sideqisi")
+ ("*ext_sidehisi", "*op_sideqi", "*op_sidehi", "*op_sidesi")
+ ("*op_swap_sideqi", "*op_swap_sidehi", "*op_swap_sidesi")
+ ("*extopqihi_side", "*extopqisi_side", "*extophisi_side")
+ ("*extopqihi_swap_side", "*extopqisi_swap_side")
+ ("*extophisi_swap_side", 8th, 9th, 10th, 11th, 14th peepholes):
+ When next to constraint R, replace constraint i with n.
- * doc/install.texi (Specific, alpha*-dec-osf*): Add "virtual
- memory exhausted" workarounds.
+Mon Apr 14 16:14:37 CEST 2003 Jan Hubicka <jh@suse.cz>
-2002-08-29 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ PR opt/10024
+ * cfgrtl.c (force_nonfallthru_and_redirect): Use unchecked_make_edge.
- * install.texi (hppa64-hp-hpux11*): Document installation procedure.
+2003-04-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
-2002-08-28 Jason Merrill <jason@redhat.com>
+ * doc/contrib.texi (Contributors): Correct my entry.
- * c-common.c (c_expand_expr) [STMT_EXPR]: If the last expression is
- a VAR_DECL with RTL that matches the target, just return that RTL.
+2003-04-12 Stephane Carrez <stcarrez@nerim.fr>
-2002-08-28 Daniel Berlin <dberlin@dberlin.org>
+ * config/m68hc11/m68hc11-protos.h
+ (m68hc11_eq_compare_operator): Declare
+ * config/m68hc11/m68hc11.h (PREDICATE_CODES): Register new predicate.
+ * config/m68hc11/m68hc11.c (m68hc11_eq_compare_operator): New predicate
+ (d_register_operand): Check the operand mode.
+ (hard_addr_reg_operand): Likewise.
- * tree-inline.c (expand_call_inline): Make the statement
- expression we generate have a COMPOUND_STMT.
+2003-04-12 Stephane Carrez <stcarrez@nerim.fr>
-2002-08-27 Mark Mitchell <mark@codesourcery.com>
+ * config/m68hc11/m68hc11.md ("decrement_and_branch_until_zero"): New
+ pattern for dbcc/ibcc generation for 68HC12.
+ ("doloop_end"): New pattern.
+ ("m68hc12_dbcc_dec_hi"): New pattern for dbeq/dbne.
+ ("m68hc12_dbcc_inc_hi"): New pattern for ibeq/ibne.
+ ("m68hc12_dbcc_dec_qi"): New pattern.
+ ("m68hc12_dbcc_inc_qi"): New pattern.
+ (split): Add split for the above when we can't use dbcc/ibcc due to
+ reloading.
+ (peephole2): Add peephole2 to generate the above when possible.
- * doc/invoke.texi: Document -Wabi.
+2003-04-12 Stephane Carrez <stcarrez@nerim.fr>
-2002-08-23 David Edelsohn <edelsohn@gnu.org>
+ * config/m68hc11/m68hc11.md ("bitcmpqi" split): No need to test the
+ mode of operand 0.
+ (peephole2 optimize const load): Likewise for operand 2.
+ ("*rotlhi3_with_carry"): Change pattern to a const 1 rotate which
+ clobbers CC_REGNUM.
+ ("*rotrhi3_with_carry"): Likewise.
+ (ashift:DI 1 split): Update pattern to create the above rotate.
+ (lshiftrt:DI 1 split): Likewise.
- * config/rs6000/rs6000.c (rs6000_select_section): Treat
- DEFAULT_ABI == ABI_AIX like PIC. Test PIC & reloc for readonly
- default.
- (rs6000_unique_section): Likewise.
+2003-04-12 Stephane Carrez <stcarrez@nerim.fr>
-2002-08-22 Jason Merrill <jason@redhat.com>
+ * config/m68hc11/m68hc11.md (SOFT_Z_REGNUM): New constant.
+ ("tstqi_z_used" split): Use it.
+ ("cmphi_z_used"): Likewise.
+ ("bitcmpqi_z_used"): Likewise; also use SP_REGNUM constant.
+ ("cmpqi_z_used"): Likewise.
- * langhooks-def.h (LANG_HOOKS_EXPR_SIZE): New macro.
- * langhooks.c (lhd_expr_size): Define default.
- * langhooks.h (struct lang_hooks): Add expr_size.
- * explow.c (expr_size): Call it.
- (int_expr_size): New fn.
- * expr.h: Declare it.
- * expr.c (expand_expr) [CONSTRUCTOR]: Use it to calculate how
- much to store.
+2003-04-12 Mark Mitchell <mark@codesourcery.com>
-2002-08-23 Alan Modra <amodra@bigpond.net.au>
+ PR c++/7910
+ * config/i386/winnt.c (i386_pe_mark_dllimport): Fix thinko.
- * config/rs6000/rs6000.c (output_mi_thunk): Don't determine insns
- for loading delta with num_insns_constant_wide. Calculate
- delta_low, delta_high without using a conditional.
+2003-04-12 Stephane Carrez <stcarrez@nerim.fr>
-2002-08-20 Andreas Jaeger <aj@suse.de>
+ * config/m68hc11/m68hc11.h (TARGET_SWITCHES): Fix -mnominmax option;
+ recognize -mnorelax.
+ (reg_class): Add Z_OR_S_REGS to represent soft registers with Z
+ (REG_CLASS_NAMES): Add its name.
+ (REG_CLASS_CONTENTS): Define its content.
- Merge from trunk:
- Wed Jul 17 00:20:48 CEST 2002 Jan Hubicka <jh@suse.cz>
+2003-04-12 Stephane Carrez <stcarrez@nerim.fr>
- * i386.md (prefetch): Fix for 64bit mode.
- (prefetch_sse_rex, prefetch_3dnow_rex): New patterns.
+ * config/m68hc11/larith.asm (memcpy): Use ARG macro to access stack
+ parameters so that offsets are valid for far definition.
+ (__mulsi3): Likewise and use ret to return.
+ (___adddi3, ___subdi3, ___notdi2, ): Don't use it to save the result.
- 2002-08-11 Andreas Jaeger <aj@suse.de>
- PR target/7531:
- * doc/invoke.texi (i386 and x86-64 Options): Document -mcmodel.
+2003-04-11 Geoffrey Keating <geoffk@apple.com>
-2002-06-24 Jeff Law <law@redhat.com>
+ * doc/extend.texi (Empty Structures): New.
- * flow.c (propagate_one_insn): When removing an insn
- with a REG_LIBCALL note but not the entire libcall sequence,
- delete the associated REG_RETVAL note.
+2003-04-11 Richard Henderson <rth@redhat.com>
-2002-06-04 Jeff Law <law@redhat.com.
- David Edelsohn <edelsohn@gnu.org>
- Michael Matz <matz@kde.org>
+ PR c++/10202
+ * expr.c (expand_expr): Use COMPLETE_OR_UNBOUND_ARRAY_TYPE_P
+ not COMPLETE_TYPE_P for re-invoking layout_decl.
- * sched-int.h (struct deps): New field libcall_block_tail_insn.
- * sched_deps.c (init_deps): Initialize libcall_block_tail_insn.
- * sched_deps.c (sched_analyze_insn): If libcall_block_tail_insn
- is set, then mark the current insn as being part of a libcall
- scheduling group.
- (sched_analyze): Set and clear libcall_block_tail_insn appropriately.
+2003-04-11 Simon Law <sfllaw@engmail.uwaterloo.ca>
- * haifa-sched.c (schedule_block): Do not count USE or CLOBBER
- insns against the issue rate.
+ * doc/bugreport.texi: Fix paragraph breaking between sections
+ in preparation for TeXinfo's paragraph indentation fixes.
+ * doc/extend.texi: Ditto.
+ * doc/invoke.texi: Ditto.
+ * doc/objc.texi: Ditto.
+ * doc/gcov.texi: Wrap 'gcov' in @command{}.
+ * doc/invoke.texi (Darwin Options): Add a preamble.
-2002-05-30 Jeff Law <law@redhat.com>
+2003-04-11 Richard Henderson <rth@redhat.com>
- * flow.c (propagate_one_insn): Revise yesterday's patch. Delete
- a dead insn with a REG_RETVAL note when the entire libcall is not
- dead and remove the associated REG_LIBCALL note at the same time.
+ PR c/10201
+ * expr.c (expand_expr): Move DECL_RTL frobbing ...
+ * stor-layout.c (layout_decl): ... here.
-2002-05-29 Jeff Law <law@redhat.com>
+2003-04-11 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
- * flow.c (propagate_one_insn): Do not remove a dead insn if it
- contains a REG_RETVAL note.
+ * doc/install.texi (hppa): Update links for HP-UX patches. Revise
+ notes on linker selection and configuration for 64-bit HP-UX port.
+ * doc/invoke.texi (hppa): Remove hppa text from description for
+ -ffunction-sections and -fdata-sections. Document -static, -nolibdld
+ and -threads options.
- * haifa-sched (sched_analyze): Remove another useless clearing
- of SCHED_GROUP_P I missed yesterday.
+ * pa-hpux10.h (LIB_SPEC): Add link options to resolve dependency of
+ libc.a on libdld.sl when -static is specified and -nolibdld is not
+ specified.
+ * pa64-hpux.h (LIB_SPEC): Likewise.
+ * pa-hpux11.h (LIB_SPEC): Likewise.
+ (LINK_SPEC): Add __gcc_plt_call as an undefined symbol when -shared
+ is not specified.
-2002-05-28 David Edelsohn <edelsohn@gnu.org>
- Jeff Law <law@redhat.com>
+2003-04-08 Jonathan Wakely <redi@gcc.gnu.org>
- * optabs.c (expand_binop): Fix nwords sign warnings.
- generate pseudo for add_optab.
+ * doc/extend.texi (Template Instantiation): Refer to ISO standard,
+ not Working Paper.
+ * doc/invoke.texi (C++ Dialect Options): Same.
- * sched-deps.c (sched_analyze): Do not clear SCHED_GROUP_P.
- * haifa-sched.c (move_insn): Clear SCHED_GROUP_P after it is used.
+Fri Apr 11 00:12:14 CEST 2003 Jan Hubicka <jh@suse.cz>
-2002-08-18 Neil Booth <neil@daikokuya.co.uk>
+ PR inline-asm/8803
+ * function.c (instantate_virtual_regs): Verify that all ASM statements
+ match after the virutal regs instantiation.
- PR preprocessor/7602
- * cppinit.c (path_include): Treat the system environment
- variables as being cxx_aware.
+2003-04-10 Steve Ellcey <sje@cup.hp.com>
-2002-08-16 David Edelsohn <edelsohn@gnu.org>
+ * ia64-protos.h (addp4_optimize_ok): New.
+ * ia64.c (addp4_optimize_ok): New.
+ * ia64.md (*ptr_extend_plus_1): Use addp4_optimize_ok.
+ (*ptr_extend_plus_2): Ditto.
- * collect2.c (is_ctor_dtor): Add other possible JOINER values.
+2003-04-10 Steve Ellcey <sje@cup.hp.com>
- * config/rs6000/rs6000.c (output_mi_thunk): Return to function
- section on TARGET_ELF.
+ * expr.c (expand_assignment): Extend offset_rtx with convert_to_mode
+ not with convert_memory_address.
+ (store_constructor): Ditto, and same for copy_size_rtx.
+ (expand_expr): Ditto.
- * doc/install.texi (*-ibm-aix*): Explain AIX shared object versioning.
- (Binaries): Update Bull Freeware URL.
+2003-04-10 Ulrich Weigand <uweigand@de.ibm.com>
-2002-08-15 Neil Booth <neil@daikokuya.co.uk>
+ * config/s390/s390.c (larl_operand): Do not allow symbols
+ marked with '@'.
+ (s390_encode_section_info): Mark symbols with forced 1-byte
+ alignment with '@'.
+ (s390_strip_name_encoding): Strip '@'.
+ (legitimize_pic_address): Handle symbols that are not valid
+ LARL operands in 64-bit mode.
- PR preprocessor/7358
- PR preprocessor/7357
- PR preprocessor/7526
- * cppfiles.c (stack_include_file): Ignore main file if
- appropriate. Correct test of whether a dependency should
- be output.
- * cppinit.c (init_dependency_output): Ignore main file
- for SUNPRO_DEPENDENCIES.
- (struct lang_flags): Rename trigraphs std.
- (set_lang): Update.
- * cpplib.c (run_directive): Kludge so _Pragma dependency works.
- * cpplib.h (struct cpp_options): New members.
- * cppmacro.c (collect_args): Flag whether to swallow a possible
- future comma pasted with varargs.
- (replace_args): Use this flag.
- * doc/cpp.texi: Update varargs extension documentation.
- * doc/cppenv.texi: Update.
+2003-04-10 Andrew Haley <aph@redhat.com>
-2002-08-14 Release Manager
+ * tree-inline.c (inlinable_function_p): Disable inlining for
+ synchronized methods.
- * GCC 3.2 Released.
+2003-04-09 Alexandre Oliva <aoliva@redhat.com>
-2002-08-08 Jakub Jelinek <jakub@redhat.com>
+ * config/fp-bit.c (unpack_d): Handle pair of doubles with
+ different signs correctly.
- * config/rs6000/rs6000.h, config/rs6000/aix.h,
- config/rs6000/darwin.h, config/rs6000/linux64.h: Revert last
- two patches.
- * config/rs6000/sysv4.h: Likewise, remove #undef ADJUST_FIELD_ALIGN.
+2003-04-08 Richard Henderson <rth@redhat.com>
-2002-08-08 Jakub Jelinek <jakub@redhat.com>
+ PR target/9886
+ * config/ia64/ia64.md (cmovdi_internal): Use 'n' not 'i' constraints.
+ (cmovsi_internal): Likewise.
- * config/rs6000/rs6000-protos.h (rs6000_field_alignment): Remove.
- * config/rs6000/rs6000.c (rs6000_field_alignment): Move...
- * config/rs6000/rs6000.h (ADJUST_FIELD_ALIGN): ...inline into the
- macro.
+2003-04-07 Matt Kraai <kraai@alumni.cmu.edu>
-2002-08-08 Jakub Jelinek <jakub@redhat.com>
-
- * stor-layout.c (place_union_field): For bitfields if
- PCC_BITFIELD_TYPE_MATTERS and TYPE_USER_ALIGN, set record's
- TYPE_USER_ALIGN.
+ * doc/install.texi: Use @command and @samp for single- and
+ multi-word commands respectively.
+ * doc/makefile.texi: Likewise.
+ * doc/sourcebuild.texi: Likewise.
-2002-08-07 Jakub Jelinek <jakub@redhat.com>
+2003-04-07 Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de>
Richard Henderson <rth@redhat.com>
- * stor-layout.c (place_union_field): Apply ADJUST_FIELD_ALIGN
- to type_align when PCC_BITFIELD_TYPE_MATTERS. Only apply
- ADJUST_FIELD_ALIGN if not DECL_USER_ALIGN resp. TYPE_USER_ALIGN.
- (place_field): Likewise.
- * config/i386/i386.c (x86_field_alignment): Don't check
- TARGET_ALIGN_DOUBLE for the second time.
- Apply min for all MODE_INT and MODE_CLASS_INT modes.
- * config/rs6000/rs6000.c (rs6000_field_alignment): New.
- * config/rs6000/rs6000-protos.h (rs6000_field_alignment): New
- prototype.
- * config/rs6000/rs6000.h (ADJUST_FIELD_ALIGN): Define.
- * config/rs6000/aix.h (ADJUST_FIELD_ALIGN): Remove.
- * config/rs6000/darwin.h (ADJUST_FIELD_ALIGN): Remove.
- * config/rs6000/linux64.h (ADJUST_FIELD_ALIGN): Remove.
- * config/rs6000/sysv4.h (ADJUST_FIELD_ALIGN): Remove.
- * doc/tm.texi (ADJUST_FIELD_ALIGN): Update description.
+ PR c/9516
+ * expr.c (safe_from_p): Rearrange to avoid deep recursion in
+ favour of looping and tail recursion for TREE_LIST and binops.
-2002-08-06 Jakub Jelinek <jakub@redhat.com>
+2003-04-07 Glen Nakamura <glen@imodulo.com>
- * config/i386/mmintrin.h (__m64): Make the type 64-bit aligned.
+ PR opt/8634
+ * explow.c (maybe_set_unchanging): Don't flag non-static const
+ aggregate type initializers with RTX_UNCHANGING_P.
-2002-08-06 Jakub Jelinek <jakub@redhat.com>
+2003-04-07 Richard Henderson <rth@redhat.com>
- * config.gcc (*-*-linux*): Default to --enable-threads=posix if no
- --{enable,disable}-threads is given to configure.
- (alpha*-*-linux*, hppa*-*-linux*, i[34567]86-*-linux*,
- x86_64-*-linux*, ia64*-*-linux*, m68k-*-linux*, mips*-*-linux*,
- powerpc-*-linux-gnualtivec*, powerpc-*-linux*, s390-*-linux*,
- s390x-*-linux*, sh-*-linux*, sparc-*-linux*, sparc64-*-linux*):
- Remove thread_file setting here.
+ PR opt/8634
+ * function.c (purge_addressof_1): Don't try arithmetics for
+ unchanging memories.
-2002-08-04 Mark Mitchell <mark@codesourcery.com>
+2003-04-07 Janis Johnson <janis187@us.ibm.com>
- * doc/install.texi (Installing GCC): Refer to buildstat.html,
- rather than listing version-specific build status files.
+ * doc/sourcebuild.texi (Test Suites): Document testing support for
+ gcov and profile-directed optimizations; describe gcc.misc-tests.
-2002-08-04 Joseph S. Myers <jsm@polyomino.org.uk>
+2003-04-07 Eric Botcazou <ebotcazou@libertysurf.fr>
- * doc/include/gcc-common.texi (version-GCC): Increase to 3.2.
+ * doc/rtl.texi (Comparison operations): Update to
+ record the allowed comparison modes.
-2002-08-01 Benjamin Kosnik <bkoz@redhat.com>
+Mon Apr 7 22:13:38 CEST 2003 Jan Hubicka <jh@suse.cz>
- * gcc.c: Set __GXX_ABI_VERSION to 102.
+ PR target/10077
+ * i386.md (movsi_1): Fix SSEMOV alternative.
-2002-07-30 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+Mon Apr 7 15:56:30 CEST 2003 Jan Hubicka <jh@suse.cz>
- * gcc.c (cpp_unique_options): Define __GXX_ABI_VERSION, bump it to 101.
+ PR opt/10024
+ Revert Zack's change
+ * cfglayout.c (cfg_layout_redirect_edge):
+ Redirect any branch edges unified with the fallthru one.
+ * cfgrtl.c (force_nonfallthru_and_redirect): Do not special
+ case fallthru edges when called via cfglayout.c
-2002-07-24 Frank van der Linden <fvdl@wasabisystems.com>
+2003-04-07 James A Morrison <ja2morri@student.math.uwaterloo.ca>
- PR optimization/7291
- * config/i386/i386.c (ix86_expand_clrstr): Fix bzero alignment
- problem on x86_64.
+ * doc/extend.texi (Darwin Pragmas): Fix spelling of Mac OS.
-2002-05-16 Jason Merrill <jason@redhat.com>
+2003-04-05 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * config/mips/mips.c (mips_output_external): Don't do sdata
- optimization for a variable with DECL_COMDAT set.
+ * c-decl.c (set_save_expr_context): Prototype.
-2002-01-03 Jakub Jelinek <jakub@redhat.com>
+2003-04-05 David Edelsohn <edelsohn@gnu.org>
- * c-decl.c (build_compound_literal): Set decl TREE_READONLY from TYPE.
+ * config/rs6000/rs6000.h (RTX_COSTS): Halve Power multiply costs.
+ * config/rs6000/rs6000.md: Correct Power4 multiply latency.
- * c-decl.c (build_compound_literal): Defer compound literal decls
- until until file end to emit them only if they are actually used.
+2003-04-05 Zack Weinberg <zack@codesourcery.com>
-2002-07-25 Release Manager
+ PR optimization/10024
+ * cfgrtl.c (force_nonfallthru_and_redirect): If e is the edge
+ we want, use it.
- * GCC 3.1.1 Released.
+2003-04-05 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-07-21 Nick Clifton <nickc@redhat.com>
+ PR bootstrap/10267
+ * doc/install.texi (*-*-solaris2): /bin/ksh is not just recommended
+ for configuring.
- * Import following patch from mainline:
+2003-04-04 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- 2002-03-18 Bernd Schmidt <bernds@redhat.com>
+ * c-decl.c (set_save_expr_context): Use traditional-style function
+ definition.
- * config/arm/arm.c (arm_gen_movstrqi): Use gen_lowpart
- instead of gen_rtx_SUBREG.
- (arm_reload_out_hi): Use gen_lowpart instead of
- gen_rtx_SUBREG to access QImode components.
- * config/arm/arm.md: Disable zero_extend split for QImode
- subregs in BIG_ENDIAN mode.
- (storehi_bigend): Match use of least significant byte.
- (storeinthi): Remove extraneous SUBREG.
- Add missing construction of operands[2].
- (movhi): Use gen_lowpart in place of gen_rtx_SUBREG.
- (movqi): Use gen_lowpart in place of gen_rtx_SUBREG.
- Replace gen_rtx (SUBREG) with gen_rtx_SUBREG.
+2003-04-04 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-07-18 Richard Henderson <rth@redhat.com>
+ * doc/contrib.texi (Contributors): Add entries for Wolfgang
+ Bangerth, DJ Delorie, Christian Ehrhardt, Christopher Faylor,
+ Nathanael Nerode, Diego Novillo, Hartmut Penner, Volker Reichelt,
+ Danny Smith, and Ulrich Weigand.
+ Update Kriang Lerdsuwanakij and fix a typo in Janis Johnson's
+ entry.
- PR optimization/7147
- * ifcvt.c (noce_get_condition): Make certain that the condition
- is valid at JUMP.
+2003-04-04 Zack Weinberg <zack@codesourcery.com>
-2002-07-16 Hans-Peter Nilsson <hp@axis.com>
+ PR bootstrap/10216
+ * configure.in: Check whether it is necessary to link against
+ libm to use ldexp.
+ * configure: Regenerate.
+ * Makefile.in: Add LDEXP_LIB substitution variable.
- * config/cris/linux.h (CRIS_LINK_SUBTARGET_SPEC): Don't
- --gc-sections if -r.
+2003-04-03 Jason Merrill <jason@redhat.com>
-2002-07-15 Eric Botcazou <ebotcazou@multimania.com>
+ PR c/10175
+ * jump.c (never_reached_warning): Revert patch of 2002-11-02.
+ Look backwards for a line note.
- PR optimization/7153
- * regmove.c (optimize_reg_copy_3): Don't optimize if the register
- dies in more than one insn.
+2003-04-02 Mike Stump <mrs@apple.com>
-2002-07-15 Jason Thorpe <thorpej@wasabisystems.com>
+ * doc/extend.texi (PowerPC AltiVec Built-in Functions): Split up
+ some to avoid faulting makeinfo --html.
- * config/sparc/netbsd-elf.h (TRANSFER_FROM_TRAMPOLINE): Remove.
+2003-04-02 Richard Henderson <rth@redhat.com>
-2002-07-15 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ * libgcc-std.ver (_Unwind_GetCFA): New.
+ * unwind-dw2.c (_Unwind_GetCFA): New.
+ * unwind-sjlj.c (_Unwind_GetCFA): New.
+ * unwind.h: Declare it.
- * bb-reorder.c (make_reorder_chain_1): Search harder for the vax
- casesi fallthru edge.
- * cfgrtl.c (force_nonfallthru_and_redirect): Place redirection
- block after ADDR_VEC.
- * vax.md (casesi): Use emit_jump_insn. Remove unused constraints.
+2003-04-02 Mike Stump <mrs@apple.com>
-2002-07-15 Jakub Jelinek <jakub@redhat.com>
+ * doc/install.texi (Specific): Update pointers to apple.com.
- PR middle-end/7245
- * config/i386/i386.c (const_int_1_31_operand): New.
- * config/i386/i386.h (PREDICATE_CODES): Add it.
- * config/i386/i386.md (ashlsi3_cmp, ashlsi3_cmp_zext, ashlhi3_cmp,
- ashlqi3_cmp, ashrsi3_cmp, ashrsi3_cmp_zext, ashrhi3_cmp, ashrqi3_cmp,
- lshrsi3_cmp, lshrsi3_cmp_zext, lshrhi3_cmp, lshrqi3_cmp): Use it.
+2003-04-01 Jan Hubicka <jh@suse.cz>
-2002-06-11 Andreas Schwab <schwab@suse.de>
+ PR inline-asm/8088
+ * i386.c (ix86_hard_regno_mode_ok): Return 0 for MMX/SSE registers
+ when MMX/SSE is not available.
- * config/m68k/m68k.h (PREDICATE_CODES): Define.
+2003-04-02 Richard Henderson <rth@redhat.com>
-2002-07-15 Alan Modra <amodra@bigpond.net.au>
+ * except.c (sjlj_find_directly_reachable_regions): Recognize when
+ must-not-throw region has been deleted.
- PR target/7282
- * config/rs6000/rs6000.md (floatsidf2): Enable for POWERPC64.
- (floatunssidf2): Likewise.
- (floatsidf_ppc64): New insn_and_split.
- (floatunssidf_ppc64): Likewise.
+2003-04-02 Richard Henderson <rth@redhat.com>
-2002-07-12 Stephane Carrez <stcarrez@nerim.fr>
+ * dwarf2out.c (output_call_frame_info): Ignore fde->nothrow as an
+ optimization when flag_exceptions not enabled.
- * config/m68hc11/m68hc11.md ("zero_extendsidi2"): Use D_REG only for
- the scratch register.
- ("*movhi2_push"): Accept Z_REG because a split pattern can make use
- of it, forbid reload to use it.
+2003-04-01 Richard Henderson <rth@redhat.com>
-2002-07-12 Marek Michalkiewicz <marekm@amelek.gda.pl>
+ * except.c (convert_from_eh_region_ranges_1): Smash REG_EH_REGION
+ notes for nothrow calls if flag_forced_unwind_exceptions.
+ (build_post_landing_pads): Mind flag_forced_unwind_exceptions.
+ (sjlj_find_directly_reachable_regions): Likewise.
+ (reachable_handlers): Likewise.
+ (can_throw_external): Likewise.
+ (collect_one_action_chain): Record cleanups after catch-all and
+ must-not-throw if flag_forced_unwind_exceptions.
+ * flags.h (flag_forced_unwind_exceptions): Declare.
+ * toplev.c (flag_forced_unwind_exceptions): New.
+ (lang_independent_options): Add it.
+ * doc/invoke.texi: Add it.
- * config/avr/avr.c (test_hard_reg_class): Fix TEST_HARD_REG_BIT
- usage on 64-bit hosts, return value was truncated to 32 bits.
+2003-04-01 Geoffrey Keating <geoffk@apple.com>
-2002-07-11 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ * unwind-dw2-fde-darwin.c (DESTRUCTOR_MAY_BE_CALLED_LIVE): New.
+ (live_image_destructor): Reset image to initial state.
+ (examine_objects): Set DESTRUCTOR_MAY_BE_CALLED_LIVE.
- * pa.md (adddi3): Change predicate of operand 2 to adddi3_operand.
- Remove comment. Change predicate of 32-bit adddi3 insn pattern to
- arith11_operand.
- * pa-protos.h (adddi3_operand): Add prototype.
- * pa.c (cint_ok_for_move): Fix comment.
- (adddi3_operand): New function.
- (emit_move_sequence): Don't directly split DImode constants on
- 32-bit targets.
+2003-04-01 Dale Johannesen <dalej@apple.com>
-2002-07-05 Stephane Carrez <stcarrez@nerim.fr>
+ * cse.c (count_reg_usage): Fix handling of REG_EQUAL notes.
+ (Zdenek Dvorak's fix from 3.4 branch)
- * config/m68hc11/m68hc11.md ("*movqi_68hc12"): Avoid allocating
- QI mode registers in soft registers.
- ("zero_extendqihi2"): Do not take into account soft registers
- for register allocation (use '*' constraint).
+2003-04-01 Ulrich Weigand <uweigand@de.ibm.com>
-2002-07-05 Stephane Carrez <stcarrez@nerim.fr>
+ * config/s390/s390.c (s390_fixup_clobbered_return_reg):
+ Do nothing if __builtin_return_address was not used.
- * config/m68hc11/m68hc11.md ("*ashlsi3"): Avoid saving y if we know
- it is dead.
- ("*ashrsi3"): Likewise.
- ("*lshrsi3"): Likewise.
+2003-04-01 David Edelsohn <edelsohn@gnu.org>
-2002-07-05 Stephane Carrez <stcarrez@nerim.fr>
+ * config/rs6000/rs6000.c (function_arg_pass_by_reference):
+ Return true for variable sized types.
+ (rs6000_va_arg): Handle variable sized types passed by reference
+ on non-SVR4 ABI.
- * config/m68hc11/m68hc11.md (peephole2): New peephole2 to optimize
- address computation and memory moves.
+2003-03-31 Mark Mitchell <mark@codesourcery.com>
-2002-07-03 Mark Mitchell <mark@codesourcery.com>
+ PR c/9936
+ * c-decl.c (grokdeclarator): Clear SAVE_EXPR_CONTEXT for
+ variably-sized arrays in parameters.
+ (set_save_expr_context): New function.
+ (c_expand_body): Use it, via walk_tree.
- PR c++/6706
- * dwarfout.c (output_reg_number): Fix warning message.
- (output_bound_representation): Check SAVE_EXPR_RTL is not NULL
- before using it.
+2003-03-31 Stephane Carrez <stcarrez@nerim.fr>
-2002-07-03 Richard Henderson <rth@redhat.com>
+ * config/m68hc11/m68hc11.c (hard_reg_operand): Check the mode.
- * config/i386/i386.md (prologue_get_pc): Issue pop here ...
- * config/i386/i386.c (load_pic_register): ... not here.
+2003-03-31 Stephane Carrez <stcarrez@nerim.fr>
-2002-07-03 David Edelsohn <edelsohn@gnu.org>
+ * config/m68hc11/m68hc11.c (m68hc11_gen_movhi): Don't rely on REG_WAS_0
+ notes as they are boggus.
+ (m68hc11_gen_movqi): Likewise.
- * config/rs6000/rs6000.md (fix_truncdfsi2_internal): Ignore DImode
- in FPR as preference.
- (fctiwz): Same.
- (floatdidf2, fix_truncdfdi2): Same.
- (floatdisf2, floatditf2, fix_trunctfdi2): Same.
- (floatditf2): Same.
- (floatsitf2, fix_trunctfsi2): SImode in GPR.
- (ctrdi): Remove FPR alternative and splitter.
+2003-03-31 Stephane Carrez <stcarrez@nerim.fr>
-2002-07-02 Hans-Peter Nilsson <hp@axis.com>
+ * config/m68hc11/m68hc11.c (expand_prologue): For an interrupt handler
+ save the soft registers after the frame pointer so that gdb can unwind
+ the frame more easily.
+ (expand_epilogue): Likewise in opposite order; allow to use X register
+ as scratch if the return value is by reference.
- PR target/7177
- * config/cris/cris.h (LEGITIMIZE_RELOAD_ADDRESS): Correct number
- of indirections for register inside sign-extended mem part.
+2003-03-31 Jason Merrill <jason@redhat.com>
-2002-07-01 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ PR java/10145
+ * stor-layout.c (update_alignment_for_field): Respect
+ DECL_USER_ALIGN for zero-length bitfields, too.
+ * c-decl.c (finish_struct): Don't set DECL_ALIGN for normal
+ fields.
- * emit-rtl.c (init_emit_once): Add missing cast to HOST_WIDE_INT.
+2003-03-30 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-06-30 David Edelsohn <edelsohn@gnu.org>
+ PR other/6955
+ * collect2.c (collect_wait): Use WCOREDUMP and fix output message.
+ * system.h (WCOREDUMP, WCOREFLG): Define if necessary.
- * config/rs6000/rs6000.md (ctrdi): Allocate pseudo for FPR
- constraint in define_expand, not splitter.
+2003-03-30 Richard Henderson <rth@redhat.com>
-2002-06-28 Phil Edwards <pme@gcc.gnu.org>
+ PR c/10083
+ * config/alpha/alpha.md (umuldi3_highpart): Change to expander;
+ don't zero_extend const inputs.
- * configure.in (gcc_gxx_include_dir): Change to match versioned
- C++ headers if --enable-version-specific-runtime-libs is used.
- * configure: Regenerate.
+2003-03-29 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-06-28 Stephane Carrez <stcarrez@nerim.fr>
+ * doc/contrib.texi: Add Eric Botcazou and Roger Sayle.
+ Uniformly use bugfix instead of bug fix.
- * config/m68hc11/m68hc11.md ("*addsi3"): Use 'o' constraint to
- avoid the auto increment addressing modes.
- ("*subsi3"): Likewise.
- (split for add/sub on address): For 68HC12 push the value on
- the stack and do the operation with a pop.
+2003-03-29 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-06-28 Stephane Carrez <stcarrez@nerim.fr>
+ PR doc/895
+ * ONEWS: Remove those items that already appear in the EGCS
+ release notes on our web pages.
- * config/m68hc11/m68hc11.h (OPTIMIZATION_OPTIONS): Define.
- * config/m68hc11/m68hc11-protos.h (m68hc11_optimization_options):
- Declare.
- * config/m68hc11/m68hc11.c (m68hc11_optimization_options): New,
- do not reorder basic blocks at the end when optimizing for size.
+2003-03-29 Alan Modra <amodra@bigpond.net.au>
-2002-06-28 Stephane Carrez <stcarrez@nerim.fr>
+ * config/rs6000/rs6000.h (FUNCTION_VALUE_REGNO_P): Respect
+ TARGET_HARD_FLOAT. Reformat.
+ (FUNCTION_ARG_REGNO_P): Likewise, and remove unneeded casts.
- * config/m68hc11/m68hc11.c (autoinc_mode): New function.
- (m68hc11_make_autoinc_notes): New function.
- (m68hc11_split_move): Be very cautious when spliting a move with
- auto increment/decrement modes because this may result in incompatible
- directions; add REG_INC notes to the resulting insn for CSE reg.
+2003-03-29 Ulrich Weigand <uweigand@de.ibm.com>
-2002-06-28 Stephane Carrez <Stephane.Carrez@nerim.fr>
+ * config/s390/s390.c (s390_emit_prologoue): Make sure backchain is
+ set up before any trapping memory access if flag_non_call_exceptions.
- * config/m68hc11/m68hc11.c (register_indirect_p): For 68HC12 a constant
- can be a valid address.
+2003-03-29 Alan Modra <amodra@bigpond.net.au>
-2002-06-28 Bob Wilson <bob.wilson@acm.org>
+ * reload1.c (reload_as_needed): Allow a USE in asm reloads.
- * config/xtensa/xtensa-protos.h (xtensa_return_addr): Declare.
- config/xtensa/xtensa.c (xtensa_return_addr): New function.
- config/xtensa/xtensa.h (RETURN_ADDR_RTX): Use xtensa_return_addr.
- config/xtensa/xtensa.md (fix_return_addr): New pattern.
+ * loop.c: (find_mem_in_note_1, find_mem_in_note): Comment.
-2002-06-28 Bob Wilson <bob.wilson@acm.org>
+2003-03-28 Loren James Rittle <ljrittle@acm.org>
- * config/xtensa/xtensa.h (FUNCTION_PROFILER): Respect flag_pic
- when generating the call to _mcount.
- (NO_PROFILE_COUNTERS): Define.
+ * doc/install.texi (*-*-freebsd*): Update with known status.
-2001-06-08 Bernd Schmidt <bernds@redhat.com>
+2003-03-28 Ulrich Weigand <uweigand@de.ibm.com>
- * emit-rtl.c (gen_lowpart_common): Don't create paradoxical FLOAT_MODE
- subregs.
- * recog.c (general_operand, register_operand): Disallow them.
+ * config/s390/s390.md ("literal_pool_31"): Output pool anchor
+ label even if pool empty when generating PIC.
+ ("literal_pool_31", "literal_pool_64"): Coding style cleanup.
-2002-06-27 Bob Wilson <bob.wilson@acm.org>
+2003-03-28 Kazu Hirata <kazu@cs.umass.edu>,
+ Dhananjay Deshpande <dhananjayd@kpit.com>
- * config/xtensa/xtensa.h (ASM_OUTPUT_POOL_PROLOGUE): Pass
- flag_function_sections as new 3rd arg to resolve_unique_section.
+ PR target/10205
+ * config/h8300/h8300.c (h8300_initial_elimination_offset):
+ Correct the offset computation when TARGET_NORMAL.
-2002-06-27 Neil Booth <neil@daikokuya.co.uk>
+2003-03-28 Eric Botcazou <ebotcazou@libertysurf.fr>
- PR preprocessor/7070
- * c-lex.c (cb_def_pragma): Don't try to spell CPP_EOF.
+ PR target/10067
+ * config/sparc/sparc.md (jump pattern): Correct order
+ when issuing the annuling marker.
-2002-06-27 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+2003-03-28 Alan Modra <amodra@bigpond.net.au>
- * doc/install.texi (Binaries): Add Sinix/Reliant Unix. Move
- Hitachi entry. Make punctuation more consistent.
+ * loop.c: (find_mem_in_note_1, find_mem_in_note): New functions.
+ (replace_loop_mems): Add "written" param. Remove invalid REG_EQUAL
+ notes after hoisting.
+ (load_mems): Adjust replace_loop_mems call.
-2002-06-27 Matt Kraai <kraai@alumni.cmu.edu>
+2003-03-28 Eric Botcazou <ebotcazou@libertysurf.fr>
- * doc/install.texi: Change ` bit' to `-bit'.
- * doc/md.texi: Change `-bits' to `-bit'.
- * doc/tm.texi: Change `-bits' to ` bits'.
+ PR c/8281
+ * config/sparc/sparc.md (movdi_insn_sp32_v9): Remove 'f-f' alternative.
+ (movdi reg/reg split): Match only on sparc32, and v9 when int regs.
-2002-06-24 David S. Miller <davem@redhat.com>
+2003-03-28 Eric Botcazou <ebotcazou@libertysurf.fr>
+ Richard Henderson <rth@redhat.com>
- * config/sparc/sparc.h (INIT_TARGET_OPTABS): If ARCH64, set the
- 32-bit ABI libfuncs to NULL.
+ PR target/10114 and PR target/10084
+ * dwarf2out.c (mem_loc_descriptor): Handle LO_SUM.
+
+2003-03-27 Olivier Hainque <hainque@act-europe.fr>
- * expmed.c (expand_divmod): Do not set optab1/optab2 to the shift
- optabs if op1 is const0_rtx.
+ PR ada/9953
+ * ada/Makefile.in (gnatlib configuration for HPUX): Split
+ the general section for HPUX into specific sections for
+ HPUX 10 and HPUX 11. Fix the setting of TGT_LIB in the HPUX
+ 11 case.
+
+2003-03-26 Ulrich Weigand <uweigand@de.ibm.com>
-2002-06-23 Jan Hubicka <jh@suse.cz>
+ * config/s390/s390.c (s390_optimize_prolog): Do not save/restore
+ registers used for global asm variables.
+ (s390_frame_info, s390_arg_frame_offset): Likewise.
+ (s390_emit_prologue, s390_emit_epilogue): Likewise.
- * reg-stack.c (convert_regs_exit): Push the registers to stack in
- proper order.
+2003-03-26 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-06-22 Ulrich Weigand <uweigand@de.ibm.com>
+ * doc/contrib.texi (Contributors): Update Janis Johnson.
- PR middle-end/6963
- * function.c (assign_stack_temp_for_type): Do not return
- the same MEM rtx for multiple uses of a stack slot.
+2003-03-26 Jakub Jelinek <jakub@redhat.com>
-2002-06-22 David S. Miller <davem@redhat.com>
+ * config/ia64/ia64.c (ia64_expand_op_and_fetch): Fix comment.
+ (ia64_expand_compare_and_swap): Use always DImode ar.ccv,
+ zero extend old to it.
+ * config/ia64/ia64.md (cmpxchg_acq_si): Remove mode from ccv
+ operand.
- PR target/6841 target/6770 target/6719
- * config/sparc/sparc.h (PREFERRED_RELOAD_CLASS): Return
- NO_REGS for constant X when CLASS is GENERAL_OR_FP_REGS or
- GENERAL_OR_EXTRA_FP_REGS.
+2003-03-26 Eric Botcazou <ebotcazou@libertysurf.fr>
-2002-06-21 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+ PR target/7784
+ * reload.c (find_reloads_address): Handle
+ (PLUS (PLUS (REG) (REG)) (CONST_INT)) form for
+ all base registers.
- * config/sparc/t-crtfm (crtfastmath.o): Prefix with $(T) for
- multilibs.
- * config/sparc/t-sol2-64 (EXTRA_MULTILIB_PARTS): Add crtfastmath.o.
- * config/sparc/t-linux64 (EXTRA_MULTILIB_PARTS): Likewise.
- Fixes PR other/6836.
+2003-03-25 Marcelo Abreu <mmabreu@inf.ufrgs.br>
-2002-06-21 Bo Thorsen <bo@suse.de>
+ PR other/10203
+ * version.c: Reference the GCC web site in the URL.
- * config/i386/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Add i386
- support so multilib works again. And don't define this at all
- when -Dinhibit_libc is used.
+2003-03-25 Jan Hubicka <jh@suse.cz>
-Thu Jun 20 16:41:40 CEST 2002 Jan Hubicka <jh@suse.cz>
+ PR opt/10056
+ * cfglayout.c (fixup_reorder_chain): Fix dealing with the conditional
+ jump jumping to the next instruction.
+ * cfgrtl.c (force_nonfallthru_and_redirect): Likewise.
+ * cfg.c (unchecked_make_edge): New.
+ * basic-block.h (unchecked_make_edge): Declare.
- * combine.c (gen_lowpart_for_combine): Avoid calling of
- simplify_gen_subreg on VOIDmode.
+2003-03-25 Jason Merrill <jason@redhat.com>
- * combine.c (subst): Be prepared for simplify_subreg to return VOIDmode.
+ PR optimization/10171
+ * unroll.c (unroll_loop): Don't delete the jump at the end unless
+ we also delete a jump at the beginning.
-2002-06-20 Richard Henderson <rth@redhat.com>
+2003-03-25 Stephane Carrez <stcarrez@nerim.fr>
- * c-common.c (c_common_get_alias_set): Correctly handle characters.
- Rearrange order of expressions; don't handle vectors here.
- * alias.c (get_alias_set): Let vectors match their components.
+ * doc/contrib.texi (Contributors): Mention self as 68HC11/68HC12
+ contributor.
-2002-06-17 Hans-Peter Nilsson <hp@axis.com>
+2003-03-25 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
- PR target/7042
- * config/cris/cris.c (cris_simple_epilogue): Kludge around reorg.c
- bug by saing that the epilogue isn't simple if there's a
- non-empty current_function_epilogue_delay_list.
- * config/cris/cris.md ("return"): Add sanity check asserting that
- current_function_epilogue_delay_list is empty.
+ * doc/passes.texi (Passes): Properly document that we do not
+ perform jump2 any longer; remove command-line option -dJ.
-2002-06-17 Richard Henderson <rth@redhat.com>
+2003-03-25 Eric Botcazou <ebotcazou@libertysurf.fr>
- * config/i386/i386.h (BIGGEST_FIELD_ALIGNMENT): Define instead
- of ADJUST_FIELD_ALIGN if IN_TARGET_LIBS.
+ PR optimization/8746
+ * config/i386/i386.md (and promoting splitters): Disable HImode to
+ SImode promoting when the sign bit matters and is not preserved, or
+ when TARGET_FAST_PREFIX is true. Disable promoting when optimizing
+ for size.
-2002-06-17 Richard Henderson <rth@redhat.com>
+2003-03-24 Stephane Carrez <stcarrez@nerim.fr>
- PR target/6922
- * expmed.c (make_tree): Handle SIGN_EXTEND/ZERO_EXTEND.
+ * config/m68hc11/t-m68hc11-gas (LIB1ASMFUNCS): Add _call_far and
+ _return_far
+ (MULTILIB_OPTIONS): Don't multilib on -mlong-calls.
+ (MULTILIB_EXCEPTIONS): Likewise.
+ * config/m68hc11/m68hc11.md ("call"): Support far calls for 68HC11
+ by calling some board support routine.
+ ("call_value"): Likewise.
+ ("*return_void"): Likewise for return.
+ ("*return_16bit"): Likewise.
+ ("*return_32bit"): Likewise.
+ * config/m68hc11/m68hc11.h (ASM_DECLARE_FUNCTION_NAME): Generate .far
+ for 68HC11 too.
+ (DWARF2_ADDR_SIZE): Use 4 so that addresses can
+ * config/m68hc11/m68hc11.c (m68hc11_override_options): Accept
+ -mlong-calls for 68HC11.
+ * config/m68hc11/larith.asm (declare_near): New macro.
+ (__premain, ___negsi2, ___one_cmplsi2, ___ashlsi3): Use it.
+ (___ashrsi3, ___lshrsi3, ___lshrhi3, ___lshlhi3): Likewise.
+ (___rotrhi3, ___rotlhi3, ___ashrhi3, ___ashrqi3): Likewise.
+ (___lshlqi3, __divmodhi4, ___mulqi3, ___mulhi3): Likewise.
+ (__mulhi32): Likewise.
+ (ret): Update macro for 68HC11.
+ (__far_trampoline): Implement for 68HC11.
+ (__call_a16, __call_a32, __return_void, __return_16): New support
+ routines for 68HC11 memory bank switching calling support.
+ (__return_32): Likewise.
-Mon Jun 17 00:31:46 CEST 2002 Jan Hubicka <jH@suse.cz>
+2003-03-21 Glen Nakamura <glen@imodulo.com>
- * i386-protos.h (x86_field_alignment): Declare.
- * i386.c (x86_field_alignment): Define.
- * i386.h (ADJUST_FIELD_ALIGNMENT): New.
- (BIGGEST_FIELD_ALIGNMENT): Kill.
+ PR opt/10087
+ * loop.c (loop_givs_reduce): Skip bivs with duplicate locations
+ while incrementing giv.
+ (record_biv): Check for duplicate biv locations and
+ set (struct induction *) v->same if found.
-2002-06-16 Richard Henderson <rth@redhat.com>
+2003-03-24 Janis Johnson <janis187@us.ibm.com>
- PR opt/6722
- * regclass.c (globalize_reg): Update regs_invalidated_by_call.
+ * doc/install.texi (Testing): Mention test result links from build
+ status pages.
-2002-06-16 Richard Henderson <rth@redhat.com>
+2003-03-24 Mark Mitchell <mark@codesourcery.com>
- PR c/7030
- * dwarf2out.c (modified_type_die): Don't assign the qualified die
- to the unqualified type.
+ * function.c (put_var_into_stack): Change bool parameter to int.
+ (gen_mem_addressof): Likewise.
+ * rtl.h (gen_mem_addressof): Likewise.
+ * tree.h (put_var_into_stack): Likewise.
+ * config/alpha/alpha.c (alpha_gp_save_rtx): Adjust call to
+ gen_mem_addressof or put_var_into_stack.
+ * config/c4x/c4x.c (c4x_expand_builtin): Likewise.
-2002-06-14 Jeff Sturm <jsturm@one-point.com>
+2003-03-24 Andreas Schwab <schwab@suse.de>
- * config/sparc/sparc.h (DYNAMIC_CHAIN_ADDRESS): Add
- SPARC_STACK_BIAS.
+ * config/ia64/ia64.c (spill_tfmode_operand): Adjust calls to
+ gen_mem_addressof.
-2002-06-14 Eric Botcazou <ebotcazou@multimania.com>
+2003-03-24 Jakub Jelinek <jakub@redhat.com>
- * loop.c (check_final_value): Use v->always_executed
- instead of v->always_computable.
- * unroll.c (final_giv_value): Don't calculate the final
- value as a function of the biv if the giv is not computed
- for every loop iteration.
+ * expr.c (do_jump): Handle UNSAVE_EXPR specially.
-2002-06-14 Eric Botcazou <ebotcazou@multimania.com>
+2003-03-23 Eric Botcazou <ebotcazou@libertysurf.fr>
- PR c/6677
- * convert.c (convert_to_integer) [LSHIFT_EXPR]: Don't pass
- the truncation down when the target type is signed.
- [trunc1]: Use unsigned arithmetic for LSHIFT_EXPR.
- * fold-const.c (extract_muldiv) [NOP_EXPR]: Don't pass through
- the conversion if the target type is a smaller type.
+ PR target/10072
+ * combine.c (simplify_if_then_else): Check that the mode
+ has MODE_INT class before applying the (OP Z (mult COND C2))
+ transformation.
+
+2003-03-23 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ PR optimization/9414
+ * config/sparc/sparc.md (widening peepholes): Use
+ widen_memory_access instead of change_address.
+
+2003-03-23 Mark Mitchell <mark@codesourcery.com>
-Thu Jun 13 18:27:05 CEST 2002 Jan Hubicka <jh@suse.cz>
+ PR c++/7086
+ * c-typeck.c (c_mark_addressable): Adjust calls to
+ put_var_into_stack.
+ * expr.c (expand_expr): Likewise.
+ * function.c (put_var_into_stack): Add rescan parameter. Do not
+ call fixup_var_refs when rescan is false.
+ (gen_mem_addressof): Likewise.
+ (assign_parms): Adjust calls to put_var_into_stack.
+ (setjmp_protect): Likewise.
+ (setjmp_protect_args): Likewise.
+ * rtl.h (gen_mem_addressof): Change prototype.
+ * stmt.c (expand_decl): Adjust calls to put_var_into_stack.
+ * tree.h (put_var_into_stack): Change prototype.
+
+2003-03-23 Arpad Beszedes <beszedes@cc.u-szeged.hu>
+
+ PR middle-end/9967
+ * builtins.c (expand_builtin_fputs): When optimizing for size,
+ don't transform fputs into fwrite.
+
+2003-03-24 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/sysv4.h (ASM_OUTPUT_ALIGNED_BSS): Remove unnecessary
+ globalize_label.
- * i386.c (ix86_expand_movstr): Fix pasto.
+ Merge from mainline.
+ 2003-01-13 Andreas Schwab <schwab@suse.de>
+ * config/rs6000/sysv4.h (ASM_OUTPUT_ALIGNED_LOCAL): Output type
+ directive.
-Thu Jun 13 18:02:11 CEST 2002 Jan Hubicka <jh@suse.cz>
+2003-03-23 Glen Nakamura <glen@imodulo.com>
- * reload.c (find_valid_class): Fix thinko in my previous patch.
+ PR c/8224
+ * fold-const.c (extract_muldiv_1): Don't pass through type conversions
+ when signedness changes for division or modulus.
-2002-06-13 Hans-Peter Nilsson <hp@axis.com>
+2003-03-23 Richard Henderson <rth@redhat.com>
- PR target/6997
- * config/cris/cris.md ("sleu"): Set attribute "cc" to "none".
+ * cfgcleanup.c (try_optimize_cfg): Allow merging of tablejumps
+ before flow2.
+ * cfgrtl.c (try_redirect_by_replacing_jump): Similarly.
-2002-06-12 Daniel Jacobowitz <drow@mvista.com>
+2003-03-23 Richard Henderson <rth@redhat.com>
- * config/mips/elf.h (DWARF2_DEBUG_INFO): Define.
- * config/mips/mips.c (mips_output_filename): Don't print a
- ".file" directive if we are using DWARF-2.
- (mips_output_function_prologue): Do not emit source file
- name for TARGET_GAS.
+ PR opt/10116
+ * ifcvt.c (find_if_block): Disallow tablejump insns outgoing
+ from then_bb or else_bb after flow2.
+ * jump.c (tablejump_p): New.
+ * rtl.h: Declare it.
-2002-06-11 Ulrich Weigand <uweigand@de.ibm.com>
+2003-03-22 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
- * config/s390/s390.md (movsi): Only use floating point
- register alternatives when operands are already fprs.
- (movdi_31, movdi_64): Likewise.
+ * pa.c (output_cbranch): Fix typo in comment.
-2002-06-11 Ulrich Weigand <uweigand@de.ibm.com>
+2003-03-22 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
- * config/s390/s390.md (reload_base, ltorg): Remove.
- * s390.c (s390_stop_dump_lit_p, s390_dump_literal_pool,
- s390_asm_output_pool_prologue, s390_pool_start_insn): Remove.
- * s390-protos.h (s390_stop_dump_lit_p, s390_dump_literal_pool,
- s390_asm_output_pool_prologue): Likewise.
- * s390.h (s390_pool_start_insn): Likewise.
+ * pa.c (output_cbranch, output_bb, output_bvb): Output nop for
+ conditional branch to the following instruction. Use next_real_insn
+ instead of next_active_insn.
+ (output_dbra, output_movb, jump_in_call_delay): Use next_real_insn
+ instead of next_active_insn.
- * s390.c (s390_output_symbolic_const): Remove support for
- old-style pool chunks.
- (s390_function_epilogue): Likewise.
- (s390_output_constant_pool): Likewise. Also, fix incorrect
- alignment for 64-bit literal pools.
- (print_operand_address): Remove 'y' and 'Y' format flags.
- * s390.h (ASM_OUTPUT_POOL_PROLOGUE): Remove support for
- old-style pool chunks.
- (ASM_OUTPUT_SPECIAL_POOL_ENTRY): Likewise.
- (ASM_OUTPUT_POOL_EPILOGUE): Remove.
- (S390_CHUNK_MAX, S390_CHUNK_OV, S390_POOL_MAX): Remove.
+2003-03-22 Ulrich Weigand <uweigand@de.ibm.com>
- * s390.c (consttable_operand): New function.
- * s390-protos.h (consttable_operand): Declare it.
- * s390.h (PREDICATE_CODES): Add consttable_operand.
- * s390.md (consttable_qi, consttable_hi, consttable_si, consttable_di,
- consttable_sf, consttable_df, pool_start_31, pool_end_31,
- pool_start_64, pool_end_64, reload_base, reload_base2): New insns.
- * s390.c (struct constant, struct constant_pool): New data types.
- (constant_modes, gen_consttable): New variables.
- (s390_start_pool, s390_end_pool, s390_add_pool,
- s390_dump_pool, s390_free_pool): New functions.
- (s390_chunkify_pool): Completely reimplement literal pool
- overflow handling.
+ * config/s390/s390.md ("movti", "*movdi_31", "*movdf_31"): Use 'o' instead
+ of 'm' constraint in forced-split alternatives.
+ ("*adddi3_31", "*subdi3_31"): Likewise. Also, pass 0 instead of 1 as
+ VALIDATE_ADDRESS parameter to operand_subword.
- * s390.c (s390_pool_overflow): New variable.
- * s390.h (s390_pool_overflow): Declare it.
- * s390.md (cjump, icjump): Use it to adapt length for out-of-range
- jumps in literal pool overflow situations.
+2003-03-22 Svein E. Seldal <Svein.Seldal@solidas.com>
- * s390.c (s390_decompose_address): Accept new-style pool chunk offsets.
- (s390_frame_info): Account for possible use of RETURN_REGNUM
- by new literal pool overflow code.
- (s390_emit_prologue): Likewise.
+ * config/c4x/t-c4x (MULTILIB_MATCHES): Make gcc recognize a c33 as
+ a c30 instead of a c40 processor.
-2002-06-10 Jakub Jelinek <jakub@redhat.com>
+2003-03-21 Richard Henderson <rth@redhat.com>
- PR optimization/6759
- * cse.c (cse_insn): Fold src_eqv just once, store it folded back into
- the REQ_EQUAL note.
+ PR opt/2001
+ * bb-reorder.c (maybe_duplicate_computed_goto_succ): New.
+ (make_reorder_chain_1): Call it.
-2002-06-10 Jakub Jelinek <jakub@redhat.com>
+ * function.h (struct function): Add computed_goto_common_label,
+ computed_goto_common_reg.
+ * function.c (free_after_compilation): Zap them.
+ * stmt.c (expand_computed_goto): Use them to produce one
+ indirect branch per function.
- PR c/6660
- * c-decl.c (grokfield): Allow user defined types if they declare
- structs or unions for unnamed fields.
+2003-03-22 Stephane Carrez <stcarrez@nerim.fr>
-2002-06-10 Jakub Jelinek <jakub@redhat.com>
+ * config/m68hc11/m68hc11.md ("call_value"): Fix trap check.
- PR c/6809
- * print-rtl.c (print_mem_expr): Don't crash on unnamed fields.
+2003-03-22 Stephane Carrez <stcarrez@nerim.fr>
-2002-06-10 Jakub Jelinek <jakub@redhat.com>
+ * config/m68hc11/m68hc11.h (ASM_DECLARE_FUNCTION_NAME): Fix typo in
+ writing .interrupt command.
+ * config/m68hc11/m68hc11.md ("call"): Look at the symbol to see
+ if it's a far or near function.
+ ("call_value"): Likewise.
+ * config/m68hc11/m68hc11.c (m68hc11_attribute_table): Add far and
+ near attributes.
+ (m68hc11_handle_fntype_attribute): Accept attributes on methods.
+ (m68hc11_override_options): Ignore -mlong-calls for 68HC11.
+ (m68hc11_initial_elimination_offset): Set current_function_far
+ according to attributes.
+ (expand_prologue): Likewise.
+ (trap_handler_symbol): New global to keep track of trap handlers.
+ (m68hc11_encode_section_info): Mark symbol as far if needed; set
+ trap symbol.
+ (m68hc11_is_far_symbol): New function.
+ (m68hc11_is_trap_symbol): New function.
+ * config/m68hc11/m68hc11-protos.h (m68hc11_is_far_symbol): Declare.
+ (m68hc11_is_trap_symbol): Declare.
- * varasm.c (const_hash): Handle FDESC_EXPR like ADDR_EXPR.
- (compare_constant): Likewise.
- (output_addressed_constants): Likewise.
+2003-03-21 Jan Hubicka <jh@suse.cz>
-2002-06-10 Jakub Jelinek <jakub@redhat.com>
+ PR inline-asm/7916
- * cfgcleanup.c (try_optimize_cfg): Make sure merge_blocks doesn't
- merge bb with itself.
+ * function.c (instantiate_virtual_regs_lossage): New function.
+ (instantiate_virtual_regs_1): Use it.
+ (instantiate_virtual_regs): Do not continue in substition when insn has
+ been deleted.
-2002-06-07 Jason Thorpe <thorpej@wasabisystems.com>
+2003-03-21 Ulrich Weigand <uweigand@de.ibm.com>
- * config.gcc (mips*-*-netbsd*): Add mips/t-netbsd to ${tmake_file}.
- * config/mips/t-netbsd: New file.
+ * config/s390/s390.h: Do not include fixdfdi.h on s390x.
+ (TARGET_64BIT): Define as compile-time constant when IN_LIBGCC2.
+ (MIN_UNITS_PER_WORD): Do not define when IN_LIBGCC2.
-2002-06-07 H.J. Lu (hjl@gnu.org)
+2003-03-21 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
- * configure.in: Add --enable-__cxa_atexit.
- * configure: Regenerated.
- * config.in: Likewise.
+ PR doc-bug/9813
+ * doc/extend.texi: Move misplaced paragraph about underscores in
+ variables in macros.
- * defaults.h (DEFAULT_USE_CXA_ATEXIT): New. Defined to be 0 if
- not defined.
+2003-03-21 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
-2002-06-07 Jason Thorpe <thorpej@wasabisystems.com>
+ * doc/invoke.texi: Fix table environment.
- * config/mips/netbsd.h (CACHE_FLUSH_FUNC): Define.
+2003-03-21 Richard Earnshaw <rearnsha@arm.com>
-Thu Jun 6 07:17:43 2002 Nicola Pero <n.pero@mi.flashnet.it>
+ * ifcvt.c (find_if_case_1): If we add a new bb, update the dominance
+ information.
- PR objc/6834
- * objc/objc-lang.c (LANG_HOOKS_GET_ALIAS_SET): Define to be
- c_common_get_alias_set.
- (LANG_HOOKS_SAFE_FROM_P): Define to be c_safe_from_p.
+2003-03-21 Eric Botcazou <ebotcazou@libertysurf.fr>
+ Richard Henderson <rth@redhat.com>
-2002-06-05 Jeff Law <law@redhat.com>
+ PR optimization/8366
+ * config/sparc/sparc.h: (SYMBOLIC_CONST): New macro.
+ (GO_IF_LEGITIMATE_ADDRESS): Use it. Reject the form
+ PIC+SYMBOLIC_CONST in other modes than Pmode.
+ (GO_IF_MODE_DEPENDENT_ADDRESS): Use it. Mark
+ the form PIC+SYMBOLIC_CONST as mode dependent.
- * pa.h (EXTRA_CONSTRAINT, T case): Further refine so that it
- rejects (mem (lo_sum (reg) (unspec))), but will allow
- (mem (lo_sum (reg) (symbol_ref)) for PA2.0.
+2003-03-20 Richard Henderson <rth@redhat.com>
-2002-06-05 Alan Modra <amodra@bigpond.net.au>
+ * fold-const.c (extract_muldiv_1): Revert changing order of
+ operands in case MULT_EXPR of 2003-02-16 patch.
- * config/rs6000/linux64.h (ASM_OUTPUT_SOURCE_LINE): Define.
+2003-03-20 Richard Henderson <rth@redhat.com>
-Tue Jun 4 18:16:50 CEST 2002 Jan Hubicka <jh@suse.cz>
+ PR c/8602
+ * integrate.c (output_inline_function): Reset input_filename
+ and lineno from the decl before rest_of_compilation.
- * dwarf2out.c (expand_builtin_init_dwarf_reg_sizes): Do not initialize
- fields past the register table.
+2003-03-20 Richard Earnshaw <rearnsha@arm.com>
- * i386.c (classify_argument): Properly handle base classes.
+ PR 10066
+ * arm.md (UNSPEC_PIC_BASE): New constant.
+ (pic_add_dot_plus_four): Wrap with unspec.
+ (pic_add_dot_plus_eight): Likewise.
-Tue Jun 4 13:09:18 CEST 2002 Jan Hubicka <jh@suse.cz>
+2003-03-19 Ulrich Weigand <uweigand@de.ibm.com>
- * loop.c (emit_prefetch_instructions): Properly place the address
- computation.
+ * config/s390/s390.c (s390_preferred_reload_class): Do not
+ force constants to the pool unless necessary.
+ (s390_decompose_address): Prefer to use pointer as base,
+ not index register.
+ * config/s390/s390.md ("*tsthiCCT_only"): Remove '?' from
+ Q alternative.
+ ("*movdi_64", "*movsi", "movhi", "movqi_64", "movqi",
+ "*movdf_64", "*movsf"): Add '?' to Q->Q alternatives.
+ ("*extractqi", "*extracthi", "*zero_extendhisi2_31",
+ "*zero_extendqisi2_31", "*zero_extendqihi2_31",
+ "*adddi3_31", "*subdi3_31"): Do not set "type" attribute.
- * dwarf2out.c (output_call_frame_info): Do not skip unwind info
- when flag_asynchronous_unwind_tables is set.
+2003-03-19 Jakub Jelinek <jakub@redhat.com>
- * i386-protos.h (x86_output_mi_thunk): Declare.
- * unix.h (ASM_OUTPUT_MI_THUNK): Move offline to ...
- * i386.c (x86_output_mi_thunk): ... here; handle 64bits.
+ * config/rs6000/rs6000.c (rs6000_emit_load_toc_table): Don't call
+ rs6000_maybe_dead if !fromprolog.
- * config/i386/i386.c (ix86_expand_int_movcc): Truncate to proper
- mode.
+2003-03-19 Jakub Jelinek <jakub@redhat.com>
- * i386.md (movabsdi): Kill broken alternative.
+ * ifcvt.c (dead_or_predicable): Fail if there are any references
+ to tablejump in merge_bb other than the final JUMP_INSN.
- * i386.c (dbx64_register_map): Fix typo
+2003-03-19 Jakub Jelinek <jakub@redhat.com>
-2002-06-03 Jason Thorpe <thorpej@wasabisystems.com>
+ * stmt.c (expand_start_case): Call emit_queue ().
- * config/rs6000/netbsd.h (DRAFT_V4_STRUCT_RET): Remove.
+2003-03-19 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
-2002-05-31 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ PR 10062
+ * config/pa/pa-hpux.h (TARGET_HPUX_UNWIND_LIBRARY): Redefine.
+ * pa-protos.h (output_lbranch): New prototype.
+ * pa.c (compute_frame_size): Change size of the frame marker on the
+ 64-bit ports to 48 bytes.
+ (pa_output_function_prologue): Document why SAVE_SP is set.
+ (hppa_expand_prologue): Save previous stack pointer into frame marker
+ on targets which use the hpux unwind library.
+ (output_cbranch): Use output_lbranch.
+ (output_lbranch): New function to output long unconditional branches.
+ * pa.h (TARGET_HPUX_UNWIND_LIBRARY): Define.
+ (STACK_POINTER_OFFSET): Update offset for 48-byte frame marker on
+ 64-bit ports.
+ * pa.md (jump): Use output_lbranch.
+ (allocate_stack): New expander for dynamic stack allocation.
- * pa-linux.h (WCHAR_UNSIGNED): Define to 0.
- * pa.h (WCHAR_UNSIGNED): Define to 1.
+2003-03-18 Alexandre Oliva <aoliva@redhat.com>
-2002-05-31 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ * toplev.c (independent_decode_option): Return success for --help,
+ --target-help and --version.
- * pa.c (output_millicode_call): Correct "be,l" insn for TARGET_PA_20.
- (output_call): Likewise.
+2003-03-19 Alan Modra <amodra@bigpond.net.au>
-2002-05-30 Richard Henderson <rth@redhat.com>
- Eric Botcazou <ebotcazou@multimania.com>
+ PR target/10073
+ * combine.c (force_to_mode <NOT>): Use gen_int_mode.
- PR optimization/6822
- * config/i386/i386.c (ix86_expand_int_movcc): Don't cast INTVAL
- to unsigned int for op1 comparisons. Use gen_int_mode.
+2003-03-18 Andreas Schwab <schwab@suse.de>
-2002-05-30 Marc Espie <espie@openbsd.org>
+ PR target/7248
+ * config/m68k/m68k.md (iordi3): Fix setting low half to -1. From
+ martin@blom.org.
- * config.gcc (sparc64-*-openbsd*): New.
- * config/sparc/openbsd1-64.h: New.
- * config/sparc/openbsd64.h: New.
+2003-03-17 Jason Merrill <jason@redhat.com>
-2002-05-30 Jason Thorpe <thorpej@wasabisystems.com>
+ PR c++/10091
+ * expr.c (expand_expr) [ADDR_EXPR]: Disallow taking the address of
+ an unaligned member of TREE_ADDRESSABLE type.
- * config/m68k/netbsd-elf.h (LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Set to
- 96 if not __mc68010__.
+2003-03-17 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-05-30 Andreas Schwab <schwab@suse.de>
+ * dwarf2asm.h: Delete obsolete comment.
+ (dw2_asm_output_data, dw2_asm_output_delta, dw2_asm_output_offset,
+ dw2_asm_output_pcrel, dw2_asm_output_addr,
+ dw2_asm_output_addr_rtx, dw2_asm_output_encoded_addr_rtx,
+ dw2_asm_output_nstring, dw2_asm_output_data_uleb128,
+ dw2_asm_output_data_sleb128, dw2_asm_output_delta_uleb128,
+ dw2_asm_output_delta_sleb128): Add ATTRIBUTE_NULL_PRINTF.
- * config/ia64/sysv4.h (DO_SELECT_SECTION): Also handle
- FUNCTION_DECLs.
+2003-03-17 Steve Ellcey <sje@cup.hp.com>
-2002-05-30 Jason Thorpe <thorpej@wasabisystems.com>
+ * stmt.c (tail_recursion_args): Call promote_mode to set
+ unsignedp flag correctly before calling convert_move.
- * config/i386/netbsd64.h (CPP_LP64_SPEC): Define.
- (CPP_SUBTARGET_SPEC): Define.
- (SUBTARGET_EXTRA_SPECS): Redefine, adding cpp_lp64 and
- cpp_subtarget specs.
- (CPP_SPEC): Redefine to include %(cpp_subtarget).
+2003-03-17 Dave Love <fx@gnu.org>
+ Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
-2002-05-29 Hans-Peter Nilsson <hp@axis.com>
+ * config/alpha/osf.h (TARGET_OS_CPP_BUILTINS): Define __digital__,
+ __arch64__ to match Compaq cc.
- * doc/md.texi (Patterns): Note pattern condition pitfall
- for unnamed insn.
+2003-03-17 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-2002-05-29 Jason Thorpe <thorpej@wasabisystems.com>
+ * function.c (thread_prologue_and_epilogue_insns): Set delete_unused
+ argument to 0 for redirect_jump.
- * config/sparc/netbsd-elf.c (CPP_SUBTARGET_SPEC64): Remove
- -D__arch64__. Add -D_LP64.
- (CPP_ARCH32_SPEC): Redefine to match the non-bi-arch version
- from sparc.h.
- (CPP_ARCH64_SPEC): Likewise.
- (NO_BUILTIN_PTRDIFF_TYPE): Undef.
- (NO_BUILTIN_SIZE_TYPE): Undef.
+2003-03-16 Mark Mitchell <mark@codesourcery.com>
-2002-05-29 Jason Thorpe <thorpej@wasabisystems.com>
+ PR c++/8805
+ * except.c (eh_region_u_cleanup): Add prev_try.
+ (expand_eh_region_end_cleanup): Set it.
+ (reachable_handlers): Use it to skip over cleanup blocks.
- * config.gcc (alpha-*-netbsd*): Don't use crtstuff.
+2003-03-16 Richard Henderson <rth@redhat.com>
-2002-05-29 Jason Thorpe <thorpej@wasabisystems.com>
+ PR opt/6798
+ * cfgcleanup.c: Include params.h.
+ (try_crossjump_bb): Use PARAM_MAX_CROSSJUMP_EDGES. Fix test for
+ too many outgoing edges from a block.
+ * Makefile.in (cfgcleanup.o): Depend on PARAMS_H.
+ * params.def (max-crossjump-edges): New.
+ * doc/invoke.texi: Document it.
- * config/alpha/netbsd.h (CPP_PREDEFINES): Add -D_LP64.
+2003-03-16 Richard Henderson <rth@redhat.com>
-2002-05-29 Richard Henderson <rth@redhat.com>
+ * config/i386/i386.md (movstrictqi, movstrictqi_1): Check
+ optimize_size as well.
- * config/i386/i386.c (ix86_compute_frame_layout): Do add bottom
- alignment for alloca.
+2003-03-16 Stephane Carrez <stcarrez@nerim.fr>
-2002-05-29 Neil Booth <neil@daikokuya.demon.co.uk>
+ * config/m68hc11/m68hc11.c (print_operand): Handle 'b' modifier
+ for D register to specify the low part of it, aka B.
+ (m68hc11_gen_movhi): Use REG_WAS_0 note and increment or decrement
+ the register if we are loading 1 or -1 to it; avoid using temp
+ register when moving X/Y to Y/X.
+ (m68hc11_gen_movqi): Likewise.
+ (m68hc11_check_z_replacement): Fix last insn setting for compare case.
- PR preprocessor/6844
- * cppmacro.c (cpp_macro_definition): Reserve space for terminating
- NUL.
+2003-03-14 Mark Mitchell <mark@codesourcery.com>
-2002-05-29 Joel Sherrill <joel@OARcorp.com>
+ PR optimization/9016
+ * config/i386/i386.c (ix86_expand_move): Force more CONST_DOUBLEs
+ into the constant pool.
- * config/rs6000/rs6000.h (ASM_CPU_SPEC): Use -m403 and -m405.
+2003-03-16 Falk Hueffner <falk.hueffner@student.uni-tuebingen.de>
-2002-05-29 Hans-Peter Nilsson <hp@axis.com>
+ PR target/9164
+ * tree.c (get_narrower): For extensions with unchanged bit number,
+ return the unsignedness of the outer mode.
- PR target/6838
- * config/cris/cris.md: Fix typos and thinkos in comments.
- (splitter for mov_sideqi_mem, mov_sidehi_mem, mov_sidesi_mem):
- Remove spurious mode specifier on operand 2.
+2003-03-16 Roger Sayle <roger@eyesopen.com>
-2002-05-29 Ulrich Weigand <uweigand@de.ibm.com>
+ * c-typeck.c (build_component_ref): Turn "for" into "do .. while"
+ to avoid "may be used uninitialized" warning on ia64-hpux.
+ * config/ia64/ia64-c.c: Include "tm_p.h" for function prototypes.
- * config/s390/s390.c (legitimate_pic_operand_p): Do not
- accept symbolic LARL operands.
- (s390_emit_epilogue): Do not set FRAME_RELATED_P on
- epilogue insns.
+2003-03-16 Neil Booth <neil@daikokuya.co.uk>
-2002-05-28 Marc Espie <espie@openbsd.org>
- * config/i386/openbsd.h (HAVE_GAS_MAX_SKIP_P2ALIGN): Remove,
- inherited from gas.h.
- (ASM_QUAD): Undef. OpenBSD does not support it.
+ * cppinit.c: Remove support of -A-.
+ * doc/cppopts.texi: Remove documentation of -A-.
-2002-05-28 Danny Smith <dannysmith@users.sourceforge.net>
+2003-03-15 Richard Henderson <rth@redhat.com>
- * doc/install.texi (binaries): Change mingw binaries
- link to www.mingw.org.
+ 2003-01-14 Richard Henderson <rth@redhat.com>
+ * config/alpha/alpha.c (alpha_expand_mov): Use correct mode
+ for force_const_mem.
-2002-05-28 Richard Henderson <rth@redhat.com>
+2003-03-15 Richard Henderson <rth@redhat.com>
- * config/i386/i386.c (ix86_compute_frame_layout): Do not add
- bottom alignment for leaf functions.
+ PR target/9700
+ * config/alpha/alpha.c (alpha_va_start): Account for
+ current_function_pretend_args_size in the AP offset.
-Mon May 27 10:37:28 CEST 2002 Jan Hubicka <jh@suse.cz>
+2003-03-15 Jason Merrill <jason@redhat.com>
- * reload.c (find_valid_class): Accept new argument DEST,
- choose class accordingly.
- (push_reload): Update callers.
+ PR debug/6387
+ * dwarf2out.c (dwarf2out_decl): If we're at -g1, just stick nested
+ function DIEs at toplevel.
+ (decls_for_scope): At -g1, don't descend into subblocks.
-2002-05-26 Richard Henderson <rth@redhat.com>
+2003-03-15 Ulrich Weigand <uweigand@de.ibm.com>
- 2002-05-25 Richard Henderson <rth@redhat.com>
- * c-pragma.c (apply_pragma_weak): Convert value identifier to
- string for decl_attributes.
- (handle_pragma_weak): Call assemble_alias if we're modifying
- an existing decl.
+ * varasm.c (struct rtx_const): Change type of un.addr member
+ to struct holding an additional 'symbol' member.
+ (decode_rtx_const): Re-enable optimization to count SYMBOL_REFs
+ with equal string addresses as equal.
+ (simplify_subtraction): Adapt to struct rtx_const change.
- 2002-05-15 Richard Henderson <rth@redhat.com>
- * varasm.c (merge_weak): Remove special case for extern and common.
+2003-03-15 Glen Nakamura <glen@imodulo.com>
- 2002-05-15 Richard Henderson <rth@redhat.com>
- * varasm.c (merge_weak): Error for any weakening after definition.
- Adjust weakening after use warning to catch more cases.
- (assemble_alias): Set TREE_USED and TREE_ASM_WRITTEN consistently.
- * config/alpha/alpha.c (alpha_encode_section_info): Do not abort.
+ * reload1.c (choose_reload_regs): Use && instead of ||
+ with REG_CANNOT_CHANGE_MODE_P condition.
- 2002-03-02 Richard Henderson <rth@redhat.com>
- * attribs.c (handle_alias_attribute): Don't call assemble_alias.
- * toplev.c (rest_of_decl_compilation): Invoke assemble_alias when
- needed.
+2003-03-15 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-2002-05-26 Jakub Jelinek <jakub@redhat.com>
+ PR optimization/9387
+ * function.c (thread_prologue_and_epilogue_insns): Use redirect jump
+ for conditional returns.
- * cse.c (fold_rtx): Don't optimize if SUBREG changes mode class.
+2003-03-14 Jason Merrill <jason@redhat.com>
-2002-05-25 Richard Henderson <rth@redhat.com>
+ PR optimization/6871
+ * varasm.c (assemble_variable): Leave constant zeroes in .rodata.
- PR target/6788
- * config/sparc/sparc.c (sparc_output_mi_thunk): New implementation
- using rtl instead of fprintf.
- * config/sparc/sparc.h (ASM_OUTPUT_MI_THUNK): Use it.
- * config/sparc/sparc-protos.h: Update.
+2003-03-12 Andrew Lewycky <andrew@mxc.ca>
-2002-05-25 Marek Michalkiewicz <marekm@amelek.gda.pl>
+ PR c++/7050
+ * expr.c (store_expr): Don't attempt to store void-typed trees,
+ just evaluate them for side effects.
- * config/avr/avr.c (avr_handle_progmem_attribute): Handle TYPE_DECL.
+2003-03-14 Eric Botcazou <ebotcazou@libertysurf.fr>
- * config/avr/avr.c (machine_dependent_reorg): Sign extend the
- CONST_INT operand to the correct mode after adding 1 to it.
+ PR optimization/8396
+ * tree-inline.c (initialize_inlined_parameters): Make sure the value
+ of read-only constant arguments is passed with the right type.
-2002-05-24 Roman Lechtchinsky <rl@cs.tu-berlin.de>
+2003-03-14 Andreas Jaeger <aj@suse.de>
+ Gwenole Beauchesne <gbeauchesne@mandrakesoft.com>
- * config/alpha/unicosmk.h (REAL_VALUE_TO_TARGET_SINGLE,
- REAL_VALUE_TO_TARGET_DOUBLE): Define for native builds.
+ * linux64.h (TARGET_OS_CPP_BUILTINS): Define _LP64 and __LP64__ in
+ 64-bit mode.
-2002-05-24 Jakub Jelinek <jakub@redhat.com>
+2003-03-13 Mike Stump <mrs@apple.com>
- PR other/6782
- * final.c (get_mem_expr_from_op): Return 0 if op is NULL.
+ * ggc-page.c (struct page_entry): Remove varray.h header.
+ Add index_by_depth field.
+ Remove save_in_use_p field.
+ (struct globals): Add depth_in_use, depth_max, by_depth_in_use,
+ by_depth_max, by_depth, and save_in_use fields.
+ (INITIAL_PTE_COUNT): Add.
+ (save_in_use_p_i): Add.
+ (save_in_use_p): Add.
+ (adjust_depth): Add.
+ (push_depth): Add.
+ (push_by_depth): Add.
+ (prefetch): Add.
+ (free_page): Add support for and use faster data structures.
+ (ggc_alloc): Likewise.
+ (init_ggc): Likewise.
+ (ggc_recalculate_in_use_p): Likewise.
+ (ggc_pop_context): Likewise.
+ (clear_marks): Likewise.
+ * Makefile.in (ggc-page.o): Remove varray.h.
-2002-05-24 David Edelsohn <edelsohn@gnu.org>
+2003-03-12 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
- * config/rs6000/aix43.h (LINK_SPEC): Add PE initializer.
- (STARTFILE_SPEC): Delete PE crt0.o.
- * config/rs6000/aix51.h: Same.
- * config/rs6000/rs6000.h (ASM_WEAKEN_DECL): Append [DS] to
- function descriptor symbol. Use RS6000_OUTPUT_BASENAME.
- (ASM_OUTPUT_DEF_FROM_DECLS): Use RS6000_OUTPUT_BASENAME.
- * config/rs6000/xcoff.h (ASM_OUTPUT_DEF): Define.
+ * pa.c (pa_init_builtins): Fix warning.
-2002-05-24 Richard Henderson <rth@redhat.com>
+2003-03-12 Richard Henderson <rth@redhat.com>
- * varasm.c (asm_output_bss): Always output one byte.
- * config/alpha/elf.h (ASM_OUTPUT_ALIGNED_LOCAL): Likewise.
+ PR opt/8178
+ * config/i386/i386.md (ffssi2): Tighten op1 predicate to
+ the requirements of the output insns.
-2002-05-24 Neil Booth <neil@daikokuya.demon.co.uk>
+2003-03-12 Steve Ellcey <sje@cup.hp.com>
- PR preprocessor/6780
- * cppmacro.c (enter_macro_context): Clear state.angled_headers.
+ * config/ia64/ia64.h (ASM_OUTPUT_XDATA_CHAR): Remove.
+ (ASM_OUTPUT_XDATA_SHORT): Remove.
+ (ASM_OUTPUT_XDATA_INT): Remove.
+ (ASM_OUTPUT_XDATA_DOUBLE_INT): Remove.
+ (ASM_OUTPUT_ADDR_DIFF_ELT): Handled 32 bit address diffs.
+ (ASM_PREFERRED_EH_DATA_FORMAT): Handle 32 bit EH pointers.
+ (CASE_VECTOR_MODE): Handle 32 bit pointers in case statement.
-2002-05-21 Richard Earnshaw <rearnsha@arm.com>
+2003-03-12 Andrew Lewycky <andrew@mxc.ca>
- * bitmap.c (bitmap_find_bit): Return early if we have the correct
- element cached.
+ PR c++/7050
+ * expr.c (store_expr): Don't attempt to store void-typed trees,
+ just evaluate them for side effects.
-2002-05-24 Neil Booth <neil@daikokuya.demon.co.uk>
+2003-03-12 Bob Wilson <bob.wilson@acm.org>
- * cppinit.c (mark_named_operators): Split out from init_builtins.
- (struct builtin): Remove operator.
- (CPLUS, OPERATOR, O): Kill
- (struct named_op): New.
- (cpp_finish_options): Call it from here instead.
- (init_builtins): Don't do named operators.
+ Backport from mainline:
+ 2003-03-12 Bob Wilson <bob.wilson@acm.org>
-2002-05-20 David S. Miller <davem@redhat.com>
+ * config/xtensa/xtensa.md (adddi3): Don't clobber source operand used
+ to detect carry.
+ (subdi3): Reorder emitted instructions.
- * cselib.c (max_value_regs): New.
- (cselib_lookup, cselib_invalidate_regno): Initialize it when
- adding new entries to the REG_VALUES table and we are dealing with
- a hard register.
- (clear_table): Initialize it.
- (cselib_invalidate_regno): Use it to determine which hard
- registers to scan when mode is not VOIDmode.
+2003-03-12 Jan Hubicka <jh@suse.cz>
-2002-05-24 Alan Modra <amodra@bigpond.net.au>
+ * i386.c (ix86_setup_incoming_varargs): Set stack_alignment_needed to 128.
- * config/rs6000/rs6000.c (output_toc): Mask longs to 32 bits.
+2003-03-12 Daniel Jacobowitz <drow@mvista.com>
-2002-05-23 Hans Boehm <Hans_Boehm@hp.com>
- * config/ia64/linux.h (IA64_GATE_AREA_END): Adjust for 64K
- pages.
+ Fix PR target/9797 and PR c/9853.
+ * stmt.c (expand_decl_init): Call push_temp_slots () and
+ pop_temp_slots ().
-2002-05-23 Neil Booth <neil@daikokuya.demon.co.uk>
+2003-03-12 Hans-Peter Nilsson <hp@bitrange.com>
- PR preprocessor/6517
- * Makefile.in: Update.
- * c-common.c (c_common_post_options): Add preprocessor
- errors to the error count.
- * c-lang.c (c_post_options): Kill.
- (LANG_HOOKS_POST_OPTIONS): Use c_common_post_options.
- * hooks.h: Add header guards.
- * langhooks-def.h: Include hooks.h.
- (LANG_HOOKS_POST_OPTIONS): Update.
- * langhooks.h (struct lang_hooks): Update post_options.
- * toplev.c (parse_options_and_default_flags): Update.
-objc:
- * objc-lang.c (objc_post_options): Kill.
- (LANG_HOOKS_POST_OPTIONS): Use c_common_post_options.
+ * configure.in (rlim_t): Define to long if no valid definition
+ found in sys/resource.h.
+ * config.in, configure: Regenerate.
-2002-05-23 Jakub Jelinek <jakub@redhat.com>
+2003-03-12 Eric Botcazou <ebotcazou@libertysurf.fr>
- PR target/6753
- * config/i386/i386.md (sse_movdfcc, sse_movdfcc_eq): Use Y instead
- of x in constraints for clarity.
- (sse_mov?fcc split): abort if op2 == op3.
- (sse_movsfcc_const0_1, sse_movsfcc_const0_2, sse_movsfcc_const0_3,
- sse_movsfcc_const0_4): Add earlyclobber.
- (sse_movdfcc_const0_1, sse_movdfcc_const0_2, sse_movdfcc_const0_3,
- sse_movdfcc_const0_4): Likewise. Use DFmode, not SFmode.
- Use Y instead of x in constraints.
+ PR c/9928
+ * c-decl.c (duplicate_decls): Discard the initializer of the new decl
+ only if it is a VAR_DECL.
-2002-05-23 Jakub Jelinek <jakub@redhat.com>
+2003-03-12 Eric Botcazou <ebotcazou@libertysurf.fr>
- PR c/6643
- * emit-rtl.c (widen_memory_access): Only call compare_tree_int
- if DECL_SIZE_UNIT is INTEGER_CST.
+ PR optimization/9888
+ * config/i386/i386.md (jcc_1): Fix range.
+ (jcc_2): Likewise.
+ (jump): LIkewise.
+ (doloop_end_internal): Likewise.
-2002-05-23 Jakub Jelinek <jakub@redhat.com>
+2003-03-12 Eric Botcazou <ebotcazou@libertysurf.fr>
- * combine.c (force_to_mode): Use gen_int_mode.
- Don't clear CONST_INT bits outside of mode.
+ PR optimization/9888
+ * config/i386/i386.md (movsi_1): Remove special alternatives
+ for %eax register.
+ (movhi_1): Likewise.
+ * config/i386/i386.c (memory_address_length): Do not use
+ short displacement when there is no base.
+ (ix86_attr_length_address_default): Handle LEA instructions.
-2002-05-23 Jakub Jelinek <jakub@redhat.com>
+2003-03-11 Loren James Rittle <ljrittle@acm.org>
- * configure.in: Fix as version test for binutils 2.12.1 releases
- (without dates).
- * configure: Rebuilt.
+ (per-port preprocessor fix, concurrent to Neil's cppinit.c fix)
+ * config/freebsd-spec.h (FBSD_CPP_PREDEFINES): Remove.
+ (FBSD_TARGET_OS_CPP_BUILTINS): New port-specific macro.
+ (FBSD_TARGET_CPU_CPP_BUILTINS): New port-specific macro.
+ * config/freebsd.h (CPP_PREDEFINES): Remove.
+ (TARGET_OS_CPP_BUILTINS): New.
+ * config/alpha/freebsd.h: Use overridden FBSD_TARGET_CPU_CPP_BUILTINS
+ instead of TARGET_OS_CPP_BUILTINS.
+ * config/sparc/freebsd.h (CPP_PREDEFINES): Remove.
-Wed May 22 14:16:07 CEST 2002 Jan Hubicka <jh@suse.cz>
+2003-03-11 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
- * i386.c (expand_movstr, expand_clrstr): Fix inline-all-stringops
- sequence.
- (ix86_expand_clrstr): Fix typo.
+ PR bootstrap/9994
+ Backport from mainline:
-2002-05-22 Duraid Madina <duraid@fl.net.au>
+ 2003-02-18 Roger Sayle <roger@eyesopen.com>
- * tradcpp.c (fixup_newlines): Use old-style function header.
+ * sbitmap.c (sbitmap_resize): New function.
+ * sbitmap.h (sbitmap_resize): Prototype here.
+ * recog.c (split_all_insns): Use sbitmap_resize.
-2002-05-21 Richard Henderson <rth@redhat.com>
+ Mon Feb 17 16:16:54 CET 2003 Jan Hubicka <jh@suse.cz>
- * system.h (BLOCK_PROFILER, BLOCK_PROFILER_CODE,
- FUNCTION_BLOCK_PROFILER, FUNCTION_BLOCK_PROFILER_EXIT,
- MACHINE_STATE_SAVE, MACHINE_STATE_RESTORE): Poison.
+ * recog.c (split_all_insns): Fix memory overflow.
- * toplev.c (display_help): Kill -a -ax help.
+ 2003-02-15 Richard Henderson <rth@redhat.com>
- * config/1750a/1750a.h, config/alpha/alpha.h,
- config/clipper/clipper.h, config/dsp16xx/dsp16xx.h,
- config/h8300/h8300.h, config/i960/i960.h, config/m68k/tower-as.h,
- config/m88k/m88k.h, config/vax/vax.h, config/we32k/we32k.h:
- (FUNCTION_BLOCK_PROFILER, BLOCK_PROFILER): Kill.
+ * recog.c (split_all_insns): Include new blocks in life update;
+ do a global life update.
- * libgcc2.c [L_bb] (BLOCK_PROFILER_CODE): Kill.
- * config/m68k/sun3.h (BLOCK_PROFILER_CODE): Kill.
+2003-03-11 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/cris/cris.md: Remove lingering EGCS reference.
+ ("*extopqihi_side_biap"): For HI operation, match
+ cris_additive_operand_extend_operator, not
+ cris_operand_extend_operator. Adjust condition.
+ ("*extopqihi_side", "*extopqihi"): Ditto.
+ ("*extopqisi_side_biap"): Correct operand numbers in condition.
+ ("*extophisi_side_biap", "*extopqisi_swap_side_biap"): Ditto.
+ ("*extophisi_swap_side_biap", "*extopqisi_swap"): Ditto.
+ ("*extophisi_swap"): Ditto.
+ ("*extopqihi_swap_side_biap"): For HI operation, match a simple
+ PLUS, not cris_operand_extend_operator. Adjust condition and
+ output template.
+ ("*extopqihi_swap_side", "*extopqihi_swap"): Ditto.
+ * config/cris/cris.h (PREDICATE_CODES): Add
+ cris_additive_operand_extend_operator.
+ * config/cris/cris.c (cris_additive_operand_extend_operator):
+ New predicate.
+
+ * config/cris/aout.h (ENDFILE_SPEC): Undef.
+ (CRIS_CPP_SUBTARGET_SPEC): Move -D__AOUT__ to...
+ (TARGET_OS_CPP_BUILTINS): New macro.
+ (HAVE_GAS_HIDDEN): Undef.
+ * config/cris/cris.h: Remove EGCS references.
+ (CPP_SPEC): Remove "-$".
+ (INIT_CUMULATIVE_ARGS): Correct comment.
+ * config/cris/cris.h (CRIS_CPP_SUBTARGET_SPEC): Move -D__ELF__ to...
+ (TARGET_OS_CPP_BUILTINS): New macro.
+ (CPP_PREDEFINES): Don't define. Move old definitions and...
+ (CPP_SPEC): ...move -D__CRIS_ABI_version=2 to...
+ (TARGET_CPU_CPP_BUILTINS): New macro.
+ * config/cris/linux.h (CRIS_CPP_SUBTARGET_SPEC): Move constant
+ definitions and the optional __PIC__, __pic__ and
+ __NO_UNDERSCORES__ definitions to...
+ (TARGET_OS_CPP_BUILTINS): New macro.
+
+2003-03-10 Devang Patel <dpatel@apple.com>
+
+ PR c++/9394
+ * gcc.c (DEFAULT_SWITCH_TAKES_ARG): Remove.
+ (DEFAULT_WORD_SWITCH_TAKES_ARG): Remove.
+ * gcc.h (DEFAULT_SWITCH_TAKES_ARG): Add.
+ (DEFAULT_WORD_SWITCH_TAKES_ARG): Add.
+ * cppspec.c (DEFAULT_SWTICH_TAKES_ARG): Remove.
+ (DEFAULT_WORD_SWITCH_TAKES_ARG): Remove.
+
+2003-03-10 Stephane Carrez <stcarrez@nerim.fr>
+
+ * config/m68hc11/m68hc11.h (HARD_REGNO_RENAME_OK): Define.
+ * config/m68hc11/m68hc11-protos.h (m68hc11_hard_regno_rename_ok):
+ Declare.
+ * config/m68hc11/m68hc11.c (m68hc11_hard_regno_rename_ok): New function
+ for reg rename optimization to avoid using Z and Y registers.
- * config/i386/i386-protos.h (ix86_output_block_profiler): Kill.
- (ix86_output_function_block_profiler): Kill.
- * config/m68hc11/m68hc11.c (m68hc11_block_profiler): Kill.
- (m68hc11_function_block_profiler): Kill.
- * config/m68hc11/m68hc11-protos.h: Update.
- * config/m88k/m88k.c (output_block_profiler): Kill.
- (output_function_block_profiler): Kill.
- * config/m88k/m88k-protos.h: Update.
+2003-03-10 Stephane Carrez <stcarrez@nerim.fr>
-2002-05-21 NIIBE Yutaka <gniibe@m17n.org>
+ * config/m68hc11/m68hc11.md ("*addhi3_68hc12"): Accept any constant
+ when adding to X and Y since leax/leay are fast.
+ ("*addhi3"): Accept 'I' constraint when adding to address register.
+ ("rotlhi3"): Operand 1 must be a register_operand.
+ (peephole2): New peephole to optimize some adds.
+ * config/m68hc11/m68hc11.h (CONST_OK_FOR_LETTER_P): Use 'I' constraint
+ to represent -2 .. 2 small integer range.
- * reload1.c (do_output_reload): Run delete_output_reload
- only if optimizing.
+2003-03-10 Stephane Carrez <stcarrez@nerim.fr>
-2002-05-20 Richard Henderson <rth@redhat.com>
+ * config/m68hc11/m68hc11.c (m68hc11_gen_rotate): Set carry before
+ each 16-bit rotation.
- * cse.c (canon_hash): Reorder do_not_record test. Always
- allow pic_offset_table_rtx.
+2003-03-10 Aldy Hernandez <aldyh@redhat.com>
-2002-05-19 Neil Booth <neil@daikokuya.demon.co.uk>
+ * config/rs6000/spe.h: Merge from mainline.
- * doc/contrib.texi: Update my entry.
+2003-03-10 Jan Hubicka <jh@suse.cz>
-2002-05-19 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * toplev.c (rest_of_compilation): Revert the previous patch.
- * mips/iris6.h (CPLUSPLUS_CPP_SPEC): Define.
+2003-03-09 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
-2002-05-19 Marek Michalkiewicz <marekm@amelek.gda.pl>
+ PR middle-end/9986
+ * c-common.c (c_common_nodes_and_builtins): Initialize target builtins
+ after the common builtins.
+ * pa-hpux.h (DONT_HAVE_FPUTC_UNLOCKED): Define.
+ * pa.c (TARGET_INIT_BUILTINS): Define.
+ (pa_init_builtins): New function.
- 2002-02-28 Marek Michalkiewicz <marekm@amelek.gda.pl>
- * config/avr/avr.c (avr_hard_regno_mode_ok): Do not allow r29
- which may overwrite the high byte of the frame pointer.
+ * pa.md (call, call_value, sibcall, sibcall_value): When sufficient
+ space has been allocated for the outgoing arguments, set the arg
+ pointer for a call emitted after virtuals have been instantiated
+ using the stack pointer offset, otherwise abort.
-2002-03-19 Lars Brinkhoff <lars@nocrew.org>
+2003-03-06 Jan Hubicka <jh@suse.cz>
- * emit-rtl.c (gen_int_mode): New function.
- * rtl.h: Prototype for it.
+ * toplev.c (rest_of_compilation): Defer RTL compilation only when
+ RTL inlining is done.
-Sat May 18 23:09:19 CEST 2002 Jan Hubicka <jh@suse.cz>
+ * i386.c (ix86_expand_vector_move): Do not crash when offloading
+ to memory in PIC mode.
- * i386.md (pushqi2, ashrqi_*): Fix constraint.
+2003-03-08 Neil Booth <neil@daikokuya.co.uk>
-2002-05-18 Aldy Hernandez <aldyh@redhat.com>
+ * cppinit.c (cpp_finish_options): Set first_unused_line to -1.
- * config/rs6000/altivec.h: Cleanups.
+2003-03-08 Eric Botcazou <ebotcazou@libertysurf.fr>
-2002-05-17 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+ PR middle-end/7796
+ * unroll.c (calculate_giv_inc): Handle constants being
+ loaded with LSHIFTRT.
- * doc/install.texi (Specific, mips-sgi-irix6): Document need to
- bootstrap with -mips3.
+2003-03-07 Eric Botcazou <ebotcazou@libertysurf.fr>
-2002-05-17 David S. Miller <davem@redhat.com>
+ PR optimization/8726
+ Backport patch from mainline:
- PR c/6689, PR optimization/6615
- * local-alloc.c (struct equivalence): Rename 'src' to 'src_p'
- and make it a pointer to rtx. Update comments.
- (update_equiv_regs): When scanning for equivalences, record
- address of SET_SRC (set) in reg_equiv[].src_p. Dereference
- it while making the equiv replacements.
+ 2003-01-08 Dale Johannesen <dalej@apple.com>
-2002-05-17 Kurt Wall <kwall@kurtwerks.com>
+ * function.c (assign_parms): Don't set pretend_args_size if
+ REG_PARM_STACK_SPACE.
- * doc/install.texi (Testing): Mention two common DejaGnu warnings
- that can be ignored.
+2003-03-06 Kurt Garloff <garloff@suse.de>
+ Geoffrey Keating <geoffk@apple.com>
+ Dale Johannesen <dalej@apple.com>
+ * params.def: Introduce parameter max-inline-insns-rtl for
+ a separate limit for the RTL inliner.
+ * params.h: Likewise.
+ * integrate.c (function_cannot_inline_p): Use it.
+ * toplev.c (decode_f_option): Set multiple parameters
+ controlling inlining with -finline-limit.
+ * params.def: Fix orthographic and typographic errors.
+ * doc/invoke.texi: Document parameters controlling inlining
+ and the way -finline-limit sets multiple of them.
+ * tree.h (struct tree_decl): Introduce inlined_function_flag,
+ recording whether the function became eligible for inlining
+ by a compiler flag rather than the declaration.
+ Provide DID_INLINE_FUNC macro to access it.
+ * c-decl.c (grokdeclarator): Set DID_INLINE_FUNC.
+ * cp/decl.c (grokfndecl): Likewise.
+ * toplev.c (rest_of_compilation): Likewise.
+ * cp/optimize (maybe_clone_body): Copy DID_INLINE_FUNC.
+ * print-tree.c (print_node): Report it.
+ * params.def: Introduce new max-inline-insns-auto limit.
+ * params.h: Likewise.
+ * tree-inline.c (inlinable_function_p): Apply it to functions
+ with DID_INLINE_FUNC set.
+ * toplev.c (decode_f_option): Initialize it from -finline-limit
+ value.
+ * doc/invoke.texi: Document new parameter.
-2002-05-16 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+2003-03-06 Michael Matz <matz@suse.de>
- * doc/install.texi (Final install): Recommend to install into a
- "clean" target directory.
+ * i386/i386.c (ix86_save_reg): Also test
+ current_function_uses_const_pool.
-2002-05-17 Andreas Schwab <schwab@suse.de>
+2003-03-05 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
- * config/ia64/sysv4.h (DO_SELECT_SECTION): Factored out of
- SELECT_SECTION.
- (UNIQUE_SECTION): Define to get small data correctly.
+ * pa.md (return_external_pic): Add !TARGET_PA_20 to constraint.
+ (epilogue): Don't generate return_external_pic when emitting PA 2.0
+ code.
- * varasm.c (resolve_unique_section): Add third parameter
- flag_function_or_data_sections and use it instead of
- flag_function_sections.
- (assemble_start_function): Pass flag_function_sections.
- (asm_emit_uninitialised): Pass flag_data_sections.
- (assemble_variable): Likewise.
+2003-03-05 Stephane Carrez <stcarrez@nerim.fr>
-2002-05-15 Eric Botcazou <ebotcazou@multimania.com>
+ * config/m68hc11/m68hc11.h (PAD_VARARGS_DOWN): Define and return
+ according to va_arg type.
+ (EXPAND_BUILTIN_VA_ARG): Remove.
+ * config/m68hc11/m68hc11.c (m68hc11_va_arg): Remove.
+ * config/m68hc11/m68hc11-protos.h (m68hc11_va_arg): Remove.
- * fold-const.c (fold) [LT_EXPR]: Move the transformation of a
- comparison against the highest or lowest integer value before
- the 'X >= CST to X > (CST - 1)' and 'X < CST to X <= (CST - 1)'
- transformation and that of an unsigned comparison against 0
- right after.
+2003-03-05 Jan Hubicka <jh@suse.cz>
-2002-05-16 Richard Henderson <rth@redhat.com>
+ * toplev.c (rest_of_compilation): Do duplicate loop headers when
+ optimizing for size.
- PR c/3467
- * c-decl.c (grokdeclarator): Don't pedwarn variable sized arrays
- for c99.
+2003-03-05 Michael Matz <matz@suse.de>
-2002-05-16 Mark Mitchell <mark@codesourcery.com>
+ * unwind.h: Add the GPL exception.
+ * Makefile.in (USER_H): Add unwind.h.
- * cfgrtl.c (purge_dead_edges): Correct handling of EDGE_EH.
+2003-03-05 Eric Botcazou <ebotcazou@libertysurf.fr>
-2002-05-09 David S. Miller <davem@redhat.com>
+ PR c/9799
+ * c-typeck.c (push_init_level): Add sanity check.
- * config/sparc/sol2.h (ASM_CPU_SPEC): Handle -mcpu=v9.
+2003-03-04 Steve Ellcey <sje@cup.hp.com>
-2002-05-07 David S. Miller <davem@redhat.com>
+ * expr.c (convert_modes): Check for legal hard register.
- PR target/6103
- * config/sparc/sparc.h (TARGET_BUGGY_QP_LIB): Define to zero.
- * config/sparc/sol2.h (TARGET_BUGGY_QP_LIB): Override to one.
- * config/sparc/sparc.c (emit_soft_tfmode_libcall): If the Qp
- library implementation clobbers the output before the inputs
- are fully consumed, use stack temporary for the output.
+2003-03-04 Andreas Schwab <schwab@suse.de>
-Wed May 15 10:38:27 CEST 2002 Jan Hubicka <jh@suse.cz>
+ * config/m68k/m68k.c (m68k_output_function_prologue): Fix CFA
+ offset without frame pointer.
- * invoke.texi (-malign-double): Re-add lost warning.
+2003-03-04 Steve Ellcey <sje@cup.hp.com>
-2002-05-14 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+ * expr.c (expand_expr): Call promote_mode to set unsignedp.
- * doc/install.texi: Remove special markup originally required for
- HTML generation with texi2html.
+2003-03-04 Roger Sayle <roger@eyesopen.com>
-2002-05-14 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+ PR c++/9367
+ * builtin-types.def (DEF_FUNCTION_TYPE_VAR_3): New macro.
+ (BT_FN_INT_CONST_STRING_VALIST_ARG,
+ BT_FN_INT_STRING_CONST_STRING_VALIST_ARG,
+ BT_FN_INT_CONST_STRING_CONST_STRING_VALIST_ARG,
+ BT_FN_INT_STRING_SIZE_CONST_STRING_VALIST_ARG,
+ BT_FN_INT_STRING_CONST_STRING_VAR,
+ BT_FN_INT_CONST_STRING_CONST_STRING_VAR,
+ BT_FN_INT_STRING_SIZE_CONST_STRING_VAR): New built-in types.
+ * builtin-attrs.def (ATTR_NONNULL_1, ATTR_NONNULL_2,
+ ATTR_NONNULL_3): Also include the nothrow attribute.
+ (sprintf, scanf, sscanf, vprintf, vsprintf, snprintf,
+ vsnprintf, vscanf, vsscanf): Don't define attributes here.
+ * builtins.def (putchar, puts): Make full C89 built-ins.
+ (snprintf, sprintf, scanf, sscanf, vprintf, vscanf,
+ vsscanf, vsnprintf, vsprintf): New built-ins.
+ * c-common.c (c_common_nodes_and_builtins): Handle new macro
+ DEF_FUNCTION_TYPE_VAR_3.
- * doc/install.texi (Specific, *-*-solaris2*): Update passus on
- setting CONFIG_SHELL to /bin/ksh and remove alternate trick to
- (possibly) work around broken /bin/sh.
+ * doc/extend.texi: Document these new built-in functions.
-2002-05-08 Jason Merrill <jason@redhat.com>
+2003-03-04 Jan Hubicka <jh@suse.cz>
- PR c++/6381
- * dwarf2out.c (rtl_for_decl_location): Only expand INTEGER_CST and
- REAL_CST.
+ * calls.c (rtx_for_function_call): Take the address as an argument
+ (expand_call): Do not modify the expression.
-2002-05-14 Release Manager
+2003-03-04 Kevin Buettner <kevinb@redhat.com>
- * GCC 3.1 Released.
+ * dwarf2out.c (rtl_for_decl_location): Don't return NULL_RTX for
+ global register variables.
-2002-05-10 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+2003-03-03 Richard Henderson <rth@redhat.com>
- * config/mips/t-iris6 (SHLIB_SLIBDIR_SUFFIXES): Use mabi=64 and
- . as N64/N32 libgcc_s.so subdirs.
+ * configure.in (HAVE_AS_LTOFFX_LDXMOV_RELOCS): New ia64 test.
+ * config.in, configure: Rebuild.
+ * config/ia64/ia64.c (ia64_ld_address_bypass_p): Accept lo_sum.
+ * config/ia64/ia64.md (load_symptr): Use high/lo_sum for the
+ paired ldtoffx and ldxmov annotations.
+ (load_symptr_internal1): Remove.
+ (load_symptr_high, load_symptr_low): New.
+ * config/ia64/ia64.h (HAVE_AS_LTOFFX_LDXMOV_RELOCS): Default to 0.
-2002-05-09 Mark Mitchell <mark@codesourcery.com>
+2003-03-03 Jason Merrill <jason@redhat.com>
- * config/rs6000/rs6000.h: Revert previous patch.
+ * calls.c (compute_argument_addresses): Give the new MEMs a
+ minimum alignment of PARM_BOUNDARY.
-2002-05-09 Joel Sherrill <joel@OARcorp.com>
+2003-03-03 Geoffrey Keating <geoffk@apple.com>
- * config/rs6000/rs6000.h CPP_CPU_SPEC): Correct
- 403 and 405 arguments for binutils 2.12.
+ * doc/install.texi (Specific): Update entry for powerpc-darwin.
-Thu May 9 12:21:48 2002 Jeffrey A Law (law@redhat.com)
+2003-03-03 Jan Hubicka <jh@suse.cz>
+ * toplev.c (rest_of_compilation): Avoid cfg_cleanup calls when not
+ optimizing.
- * pa.c (hppa_profile_hook): Use force_reg to get the address
- of the profile hook into an appropriate pseudo register.
+2003-02-28 Jan Hubicka <jh@suse.cz>
-2002-05-09 Jakub Jelinek <jakub@redhat.com>
+ * combine.c (gen_lowpart_for_combine): Update handling of subregs_of_mode
+ * flow.c (life_analysis, mark_used_regs): Likewise.
+ * regclass.c (subregs_of_mode): Turn into single bitmap.
+ (cannot_change-mode_set_regs, invalid_mode_change_p): Update
+ dealing with subregs_of_mode
+ * regs.h (subregs_of_mode): Update prototype.
- * mklibgcc.in: Set shlib_slibdir_qual to empty string if
- SHLIB_SLIBDIR_SUFFIXES is empty.
+2003-02-28 Jan Hubicka <jh@suse.cz>
-2002-05-09 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+ * toplev.c (rest_of_compilation): Rearrange insn splitting
+ * reg-stack.c (reg_to_stack): Do not split insns.
- * config/mips/t-iris6 (SHLIB_SLIBDIR_SUFFIXES): Define.
- (SHLIB_LINK, SHLIB_INSTALL): Adjust.
+2003-03-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-05-09 Jakub Jelinek <jakub@redhat.com>
+ * ggc-common.c (ggc_rlimit_bound): Cast RLIM_INFINITY to avoid
+ warnings.
- * config/sparc/t-linux64 (SHLIB_MAPFILES): Set.
- * config/sparc/libgcc-sparc-glibc.ver: New file.
- * config/i386/t-linux64 (SHLIB_MAPFILES): Add libgcc-x86_64-glibc.ver.
- * config/i386/libgcc-x86_64-glibc.ver: New file.
- * config/cris/t-linux (SHLIB_MAPFILES): Remove.
- * mklibgcc.in: Preprocess SHLIB_MAPFILES with ml flags.
+2003-03-02 Stephane Carrez <stcarrez@nerim.fr>
-2002-05-09 Jakub Jelinek <jakub@redhat.com>
+ * config/m68hc11/m68hc11.c (m68hc11_override_options): Don't enable
+ min/max instructions by default as may result in reload errors.
- PR target/6429
- * Makefile.in (libgcc.mk): Pass SHLIB_SLIBDIR_SUFFIXES to mklibgcc.
- * mklibgcc.in: If SHLIB_SLIBDIR_SUFFIXES is defined, put libgcc_s
- shared libraries into multilib dirs, with SONAME libgcc_s.so.1 for
- base multilibs.
- * config/t-slibgcc-elf-ver (SHLIB_LINK): Adjust for the above.
- * config/t-slibgcc-sld (SHLIB_LINK): Likewise.
- * config/i386/t-linux64 (SHLIB_SLIBDIR_SUFFIXES): Define.
- * config/sparc/t-linux64 (SHLIB_SLIBDIR_SUFFIXES): Define.
- * config/sparc/t-sol2-64 (SHLIB_SLIBDIR_SUFFIXES): Define.
+2003-03-02 Stephane Carrez <stcarrez@nerim.fr>
-2002-05-08 Mark Mitchell <mark@codesourcery.com>
+ * config/m68hc11/m68hc11.md ("mulqi3"): Allow address register to
+ avoid reload problems; define split for it.
- PR c/6569.
- * varasm.c (mark_weak): New function.
- (merge_weak): Use it. Do not call declare_weak.
- (declare_weak): Use merge_weak.
+2003-03-02 Stephane Carrez <stcarrez@nerim.fr>
-2002-05-07 Geoffrey Keating <geoffk@redhat.com>
+ * config/m68hc11/m68hc11.c (m68hc11_shift_operator): New function.
+ * config/m68hc11/m68hc11-protos.h (m68hc11_shift_operator): Declare.
+ * config/m68hc11/m68hc11.h (PREDICATE_CODES): Register.
+ * config/m68hc11/m68hc11.md ("rotrhi3", "rotlhi3"): New patterns for
+ rotatert and rotate.
+ ("rotrhi3_const", "rotlhi3_const"): Rename of old 'rotrhi3' insns.
+ ("*rotrhi3", "*rotlhi3"): New insn pattern for non-const rotatert.
+ ("*rotrhi3_addr"): New split for shift insns on address register.
+ ("*lshrhi3", "*ashrhi3", "*ashlhi3_2"): Use new split.
+ * config/m68hc11/larith.asm (___rotlhi3): New asm function.
+ (___rotrhi3): Likewise.
+ * config/m68hc11/t-m68hc11-gas (LIB1ASMFUNCS): Build them.
- * configure.in: Don't pass -Wno-long-long to a ADA compiler
- that doesn't support it.
- * configure: Regenerate.
+2003-03-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-05-07 Jason Merrill <jason@redhat.com>
+ * fp-bit.h (float_to_usi): Fix condition wrapping prototype.
- * dwarf2out.c (rtl_for_decl_location): Don't try to extract a
- constant value from DECL_INITIAL.
+2003-03-02 Ashif Harji <asharji@uwaterloo.ca>
-2002-05-07 Richard Henderson <rth@redhat.com>
+ * gcc.c (default_compilers): Add -no-integrated-cpp flag to invoke
+ an external cpp during compilation.
+ (option_map): Likewise.
+ * objc/lang-specs.h (default_compilers): Similarly.
+ * doc/invoke.texi: Document -no-integrated-cpp flag.
- PR c++/6212
- * expr.c (highest_pow2_factor_for_type): New.
- (expand_assignment): Use it.
+2003-03-01 Jason Thorpe <thorpej@wasabisystems.com>
-2002-05-07 Jakub Jelinek <jakub@redhat.com>
+ * config.gcc (*-*-netbsd[2-9]*, *-*-netbsdelf[2-9]*): Enable
+ POSIX thread support by default.
- * configure.in: If as or ld segfaults, don't clutter with it stdout.
- * configure: Rebuilt.
+2003-03-01 Roger Sayle <roger@eyesopen.com>
+
+ PR bootstrap/7389.
+ * basic-block.h (flow_bb_inside_loop_p): Correct prototype.
-2002-05-05 Jakub Jelinek <jakub@redhat.com>
+2003-02-28 Jason Thorpe <thorpej@wasabisystems.com>
- PR target/6561
- * config/sparc/sparc.md (muldi3_v8plus): Handle %1 equal to %2.
+ * config/netbsd.h: Update copyright years.
+ (NETBSD_CPP_SPEC): Define _REENTRANT and _PTHREADS if
+ -pthread is specified on the command line.
-2002-05-05 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+2003-02-28 Bob Wilson <bob.wilson@acm.org>
- * doc/install.texi (powerpc-*-linux-gnu*): Update build requirements.
+ Backport following patch:
+
+ 2003-02-28 Bob Wilson <bob.wilson@acm.org>
+ * config.gcc (xtensa-*-linux*): Add t-slibgcc-elf-ver to tmake_file.
-2002-05-04 David Edelsohn <edelsohn@gnu.org>
+2003-02-27 Joel Sherrill <joel@OARcorp.com>
- PR c/6543
- * config/rs6000/rs6000.md (sCC pattern and splitter): Remove
- clobber and use result as temporary value.
+ PR 9638/other
+ * config/i386/i386.c (DEFAULT_PCC_STRUCT_RETURN): Ensure the
+ this constant defaults to 1.
-2002-05-03 Jakub Jelinek <jakub@redhat.com>
+2003-02-28 Richard Sandiford <rsandifo@redhat.com>
- PR target/6542
- * config/sparc/sparc.h (leaf_reg_remap): Remove const.
- (CONDITIONAL_REGISTER_USAGE): For TARGET_FLAT make
- fill leaf_reg_remap with identity.
- * config/sparc/sparc.c (leaf_reg_remap): Remove const.
+ * config/mips/mips.md: Disable the movstrsi define_split.
-2002-05-03 Jakub Jelinek <jakub@redhat.com>
+2003-02-28 Richard Sandiford <rsandifo@redhat.com>
- PR target/6522
- * dwarf2out.c (simple_decl_align_in_bits): Renamed to...
- (simple_field_decl_align_in_bits): this. Apply
- BIGGEST_FIELD_ALIGNMENT and ADJUST_FIELD_ALIGN if defined.
+ * config/mips/mips.h (CRT_CALL_STATIC_FUNCTION): Wrap in
+ #ifndef __mips16.
-2002-05-03 Richard Henderson <rth@redhat.com>
+2003-02-27 Geert Bosch <bosch@gnat.com>
- PR opt/6534
- * ifcvt.c (noce_try_store_flag, noce_try_store_flag_constants,
- noce_try_store_flag_inc, noce_try_store_flag_mask, noce_try_cmove,
- noce_try_cmove_arith, noce_try_minmax, noce_try_abs): Insert new
- code before JUMP, not EARLIEST.
+ * toplev.c (print_version): Add indentation for GGC heuristics and
+ output after printing version information.
-2002-05-03 Jakub Jelinek <jakub@redhat.com>
+2003-02-27 James E Wilson <wilson@tuliptree.org>
- PR preprocessor/6489
- * tradcpp.c (fixup_newlines): New.
- (main, finclude): Use it.
+ PR bootstrap/9255
+ * combine.c (simplify_comparison): Require integral mode when
+ permuting SUBREG with AND.
-2002-05-03 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+2003-02-27 Steve Ellcey <sje@cup.hp.com>
- * doc/install.texi (Installing): Mention GCC 3.1 buildstats.
- (Specific): Removed buildstats references.
- (Specific, hppa*-hp-hpux11): Adjust for GCC versions > 3.0.
- (Specific, sparc-sun-solaris2*): Update 64-bit hints for GCC 3.1.
- Accomodate Solaris versions beyond 8.
- (Specific, sparc-sun-solaris2.7): Update as path for GCC 3.1.
- (Specific, *-*-solaris2.8): Removed, obsolete.
+ * config/ia64/hpux.h (STARTFILE_PREFIX_SPEC): Remove.
-2002-05-02 Jason Merrill <jason@redhat.com>
+2003-02-27 Alan Modra <amodra@bigpond.net.au>
- * defaults.h (BOOL_TYPE_SIZE): Move default here from cp/decl.c.
- * c-decl.c (c_init_decl_processing): Use it.
- * config/rs6000/darwin.h (BOOL_TYPE_SIZE): Define to INT_TYPE_SIZE.
- * config/i960/i960.h (BOOL_TYPE_SIZE): Don't define.
- * config/mcore/mcore.h (BOOL_TYPE_SIZE): Don't define.
+ * config/rs6000/rs6000.md: Add TI constant splitter.
-2002-05-02 Loren J. Rittle <ljrittle@acm.org>
+2003-02-26 Jan Hubicka <jh@suse.cz>
- * doc/install.texi (*-*-freebsd*): Update to latest status.
+ * expr.c (emit_group_store): Fix crash when converting single
+ register into complex register.
-2002-05-02 Jakub Jelinek <jakub@redhat.com>
+2003-02-26 Michael Matz <matz@suse.de>
- PR target/6540
- * config.gcc (sparc*-*-solaris2*): Set float_format to i128.
- * config/float-sparc.h: Assume 128-bit long double if
- __LONG_DOUBLE_128__ is defined.
+ * ra-colorize.c (merge_moves): Fix list handling.
- PR target/6512, PR target/5628
- * config/sparc/sparc.md (movdf_insn_v9only_novis): Don't allow >= %f32
- when memory is not aligned.
- (movdf_insn_v9only_vis): Likewise.
- * config/sparc/sparc.h (SECONDARY_INPUT_RELOAD_CLASS): Request a FP_REGS
- temporary for EXTRA_FP_REGS DFmode load from unaligned memory.
- (SECONDARY_OUTPUT_RELOAD_CLASS): Similarly.
+2003-02-26 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
-2002-05-02 Joseph S. Myers <jsm28@cam.ac.uk>
+ * pa.c (compute_frame_size): Don't assume PREFERRED_STACK_BOUNDARY
+ is 8 * STACK_BOUNDARY.
+ * pa.h (PREFERRED_STACK_BOUNDARY): Change to 128 on 64-bit port.
- * doc/install.texi: State GNAT version requirements.
+2003-02-26 Alan Modra <amodra@bigpond.net.au>
-2002-05-01 Jeff Law <law@redhat.com>
+ PR target/9681
+ * tlink.c (scan_linker_output): Drop leading '.' from symbol names.
- * pa.h (EXTRA_CONSTRAINT): Don't accept PIC addresses for the
- 'T' constraint.
+2003-02-25 Richard Henderson <rth@redhat.com>
-2002-05-01 Joel Brobecker <brobecker@gnat.com>
+ * config/i386/i386.c (function_arg): Pass variable sized
+ structures correctly on the stack.
- * dbxout.c (dbxout_type): Emit size information for range types,
- as well, but only when using GDB extensions.
+2003-02-25 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
-2002-05-01 Richard Henderson <rth@redhat.com>
+ PR target/9732
+ * config/rs6000/rs6000.c (first_reg_to_save): Handle
+ PIC_OFFSET_TABLE_REGNUM for -fPIC too.
+ (rs6000_emit_prologue): Likewise.
+ (rs6000_emit_epilogue): Likewise.
+ * config/rs6000/rs6000.h (CONDITIONAL_REGISTER_USAGE): Make
+ PIC_OFFSET_TABLE_REGNUM a fixed register for -fPIC.
- * configure.in (HAVE_GAS_HIDDEN): Replace SPARC feature test with
- target-independent gnu binutils date test.
+2003-02-25 Richard Henderson <rth@redhat.com>
-2002-05-01 Jakub Jelinek <jakub@redhat.com>
+ * real.c (real_to_integer2): Force overflow result only for
+ unsigned overflow.
- * cppinit.c (cpp_handle_option) [-dM]: Don't set no_output here...
- (cpp_post_options): ...but here. Disable -dD, -dN and -dI when
- -M -or -MM is in effect.
+2003-02-25 Jan Hubicka <jh@suse.cz>
-2002-05-01 Zack Weinberg <zack@codesourcery.com>
+ PR target/8343
+ * m68k.md (umulsidi, mulsidi expanders): Use register operand.
- * config.gcc: Correct test of --enable-obsolete. Obsolete all
- A29k configurations.
- * doc/install.texi: Update to match.
+2003-02-24 Svein E. Seldal <Svein.Seldal@solidas.com>
-2002-05-01 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+ * config/c4x/c4x.h (ASM_FILE_START): Added support for the c33
+ processor.
- PR bootstrap/6514
- * varasm.c (globalize_decl): Compare DECL_ASSEMBLER_NAME to check
- for duplicates. Always loop over whole list.
+2003-02-24 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
-Wed May 1 10:32:37 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * config/mips/iris6.h (TARGET_OS_CPP_BUILTINS): Define __c99 for
+ ISO C99 and C++.
- * reload.c (find_reloads, case 'p'): Set BADOP to 0.
+ * fixinc/inclhack.def (irix___restrict): Don't change __restrict
+ for C++ on IRIX 6.5.1[89].
+ * fixinc/tests/base/internal/sgimacros.h: New file.
-2002-05-01 Joel Sherrill <joel@OARcorp.com>
+ * fixinc/inclhack.def (irix_wcsftime): Use XPG5 variant for C99.
+ * fixinc/tests/base/internal/wchar_core.h: New file.
- * config/sparc/t-elf (sparc-rtems, sparc-elf): Build assembly
- support routines.
+ * fixinc/inclhack.def (irix_socklen_t): Fix broken IRIX 6.5.1[78]
+ socklen_t definition.
+ * fixinc/fixincl.x: Regenerate.
+ * fixinc/tests/base/sys/socket.h: New file.
+ Fixes PR libgcj/9652.
-2002-05-01 Joseph S. Myers <jsm28@cam.ac.uk>
+2003-02-24 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
- * doc/install.texi: Update Texinfo version requirement
+ * config/alpha/osf.h (TARGET_OS_CPP_BUILTINS): Rename
+ __EXTERN_PREFIX to __PRAGMA_EXTERN_PREFIX.
+ * doc/extend.texi (Tru64 Pragmas): Reflect this.
+
+ * fixinc/inclhack.def (alpha___extern_prefix): Indicate #pragma
+ extern_prefix support for Tru64 UNIX V5 <sys/stat.h>.
+ * fixinc/fixincl.x: Regenerate.
+ * fixinc/tests/base/sys/stat.h [ALPHA___EXTERN_PREFIX_CHECK]: New
+ testcase.
+ Fixes PR c/5059, c/6126, other/9671.
+
+2003-02-24 Alan Modra <amodra@bigpond.net.au>
+
+ PR 9297, PR 9722
+ * calls.c (store_one_arg): Revert 1999-02-16 change. Revert
+ 2000-12-17 change. Pass EXPAND_STACK_PARM to expand_expr.
+ * expr.h (enum expand_modifier): Define EXPAND_STACK_PARM.
+ (enum block_op_methods): Reorder for better store_expr optimization.
+ * expr.c (store_expr): Test bit 1 of "want_value" for call param
+ stores, test bit 0 for original want_value meaning. Pass
+ BLOCK_OP_CALL_PARM to emit_block_move when bit 1 set. Adjust
+ recursive calls, and calls to expand_param.
+ (expand_expr): Handle EXPAND_STACK_PARM modifier. When cse
+ expected, set target to 0 rather than to subtarget. Formatting.
+
+2003-02-23 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * doc/invoke.texi (ggc-min-expand, ggc-min-heapsize): Document
+ new default behavior.
+ * ggc-common.c: Include sys/resource.h.
+ (ggc_rlimit_bound): New function.
+ (ggc_min_expand_heuristic, ggc_min_heapsize_heuristic): Update
+ defaults to account for rlimits.
+
+2003-02-22 Jan Hubicka <jh@suse.cz>
+
+ * config/linux.h (TARGET_HAS_F_SETLKW): Define.
+ * config/alpha/linux.h (TARGET_HAS_F_SETLKW): Likewise
+
+2003-02-22 Hans-Peter Nilsson <hp@axis.com>
+
+ * regmove.c (optimize_reg_copy_1): Do not replace a hard register
+ in an asm.
+
+2003-02-22 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (builtin_description): Add __builtin_ia32_paddq and
+ __builtin_ia32_psubq. Fix __builtin_ia32_paddq128
+ and __builtin_ia32_psubq128.
+ * i386.h (IX86_BUILTIN_PADDQ, IX86_BUILTIN_PSUBQ): New.
+ * i386.md (addv*, mmx_ior*, mmx_xoe*, mmx_and*): Add missing '%'.
+ (mmx_adddi3, mmx_subdi3): New.
+ * mmintrin.h (_mm_add_si64, _mm_sub_si64): New.
+ * xmmintrin.h (_mm_movepi64_pi64): New.
+ (_mm_add_epi64, _mm_sub_epi64): fix.
+ (_mm_mul_pu16): Rename to...
+ (_mm_mul_su32): ... this one.
+
+ * i386.c (def_builtin): Special case 64bit builtins.
+ (MASK_SSE164, MASK_SSE264): New constants.
+ (builtin_description): Add 64bit builtins.
+ (ix86_init_mmx_sse_builtins): Likewise.
+ * i386.h (enum ix86_builtins): Likewise.
+ * i386.md (cvtss2siq, cvttss2siq, cvtsd2siq, cvttsd2siq, cvtsi2sdq,
+ sse2_movq2dq_rex64, sse2_movsq2q_rex64): New.
+ (sse2_movq2dq, sse2_movsq2q): Disable for 64bit.
+ * mmintrin.h (_mm_cvtsi64x_si64, _mm_set_pi64x, _mm_cvtsi64_si64x): New.
+ * xmmintrin.h (_mm_cvtss_si64x, _mm_cvttss_si64x, _mm_cvtsi64x_ss,
+ _mm_set_epi64x, _mm_set1_epi64x, _mm_cvtsd_si64x, _mm_cvttsd_si64x,
+ _mm_cvtsi64x_sd, _mm_cvtsi64x_si128, _mm_cvtsi128_si64x): New.
+
+ * builtins.c (expand_builtin_expect): Do not predict
+ flag_guess_branch_prob is not set.
+ * c-semantics.c (expand_stmt): Likewise.
+ * predict.c (predict_insn): Likewise.
+ * stmt.c (expand_continue_loop): Likewise.
+ * toplev.c (rest_of_compilation): Do not call
+ note_prediction_to_br_prob and note_prediction_to_br_prob
+ when not optimizing.
+
+ * basic-block.h (tidy_fallthru_edges): Kill.
+ * cfgrtl.c (tidy_fallthru_edges): Kill.
+ * cfgbuild.c (find_basic_blocks): Do not call tidy_fallthru_edges.
+ * cfgcleanup.c (delete_unreachable_blocks): Likewise.
+
+2003-02-22 Steven Bosscher <s.bosscher@student.tudelft.nl>
+
+ PR other/3782
+ * toplev.c (process_options): If flag_detailed_statistics is set,
+ then set time_report as well.
+
+ PR c/8828
+ * jump.c (never_reached_warning): Don't fall through BARRRIER
+ insns. Update comments to reflect what the function really does.
+
+2003-02-21 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * doc/invoke.texi (ggc-min-expand, ggc-min-heapsize): Update
documentation.
+ * ggc-common.c: Include params.h
+ (ggc_min_expand_heuristic, ggc_min_heapsize_heuristic,
+ init_ggc_heuristics): New functions.
+ * ggc.h (ggc_min_expand_heuristic, ggc_min_heapsize_heuristic,
+ init_ggc_heuristics): Prototype.
+ * toplev.c (print_version): Output GGC heuristics.
+ (parse_options_and_default_flags): Call init_ggc_heuristics.
-2002-04-30 Richard Henderson <rth@redhat.com>
+2003-02-21 Jan Hubicka <jh@suse.cz>
- * config/sparc/sol27-sld.h: Rename from sol26-sld.h.
- (PREFERRED_DEBUGGING_TYPE, ASM_DEBUG_SPEC): Undef.
- * config.gcc (sparc-solaris): Adjust test for native ld bug.
- Add it after the biarch headers.
+ * cfgrtl.c (commit_edge_insertions): Call
+ find_many_sub_basic_block only when some code has been emitted.
+ (commit_edge_insertions_watch_calls): Bring into sync with
+ commit_edge_insertions
-2002-04-30 Richard Henderson <rth@redhat.com>
+2003-02-21 Zack Weinberg <zack@codesourcery.com>
- PR opt/6516
- * toplev.c (rest_of_compilation): Don't run cross-jump before
- bb-reorder.
+ * cpphash.h (struct lexer_state): Add directive_wants_padding.
+ * cpplib.c (_cpp_handle_directive): Set directive_wants_padding
+ for directives of type INCL.
+ (glue_header_name, parse_include): Use get_token_no_padding.
+ * cppmacro.c (replace_args): If directive_wants_padding,
+ provide padding tokens.
-2002-04-30 Joel Sherrill <joel@OARcorp.com>
+2003-02-21 Jan Hubicka <jh@suse.cz>
- * config/arm/rtems-elf.h: Add #undef TARGET_VERSION to prevent warning.
+ * cfgrtl.c (commit_one_edge_insertion): Only mark BB for splitting.
+ (commit_edge_insertions): Call find_many_sub_basic_blocks
-2002-04-30 Richard Henderson <rth@redhat.com>
+ * reg-stack.c (convert_regs): Cleax aux for blocks.
- * config/sparc/sparc.c (emit_soft_tfmode_libcall,
- emit_soft_tfmode_binop, emit_soft_tfmode_unop, emit_soft_tfmode_cvt,
- emit_hard_tfmode_operation, emit_tfmode_binop, emit_tfmode_unop,
- emit_tfmode_cvt): New.
- * config/sparc/sparc.md (extendsftf2, extenddftf2, trunctfsf2,
- trunctfdf2, floatsitf2, floatunssitf2, floatditf2, floatunsditf2,
- fix_trunctfsi2, fixuns_trunctfsi2, fix_trunctfdi2, fixuns_trunctfdi2,
- addtf3, subtf3, multf3, divtf3, sqrttf2): Use them.
- * config/sparc/sparc-protos.h: Update.
+2003-02-21 Glen Nakamura <glen@imodulo.com>
-2002-04-30 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ PR optimization/8613
+ * builtins.c (expand_builtin): Emit postincrements before expanding
+ builtin functions.
- * config.gcc (hppa1.1-*-pro*, hppa1.1-*-osf*, hppa1.1-*-rtems*,
- hppa1.0-*-osf*, hppa1.1-*-bsd*, hppa1.1-*-hpux10*, hppa2*-*-hpux10*,
- hppa1.0-*-hpux10*, hppa*64*-*-hpux11*, hppa1.1-*-hpux11*,
- hppa2*-*-hpux11*, hppa1.0-*-hpux11*, hppa*-*-lites*): Define xmake_file.
- * ada/Make-lang.in (ADA_FLAGS_TO_PASS): Don't pass ADA_CFLAGS.
- * pa/t-linux, pa/t-pa, pa/t-pa64, t-pro (T_ADAFLAGS): Delete.
- * pa/x-ada: New file. Define ADA_CFLAGS.
+2003-02-21 Toon Moene <toon@moene.indiv.nluug.nl>
-2002-04-30 Janis Johnson <janis187@us.ibm.com>
+ PR fortran/9038
+ * c-opts.c (sanitize_cpp_opts): Add Fortran front end
+ options to be ignored.
+ (c_common_decode_option): Ignore them when preprocessing.
- * doc/install.texi (Final install): Add to the list of info to include
- in a report of a successful bootstrap, and add link to 3.1 list.
+2003-02-21 Ben Elliston <bje@redhat.com>
-2002-04-30 Jakub Jelinek <jakub@redhat.com>
+ PR other/5634
+ * doc/install.texi (Configuration): Explain using $HOME instead of
+ the ~ metacharacter when referring to home directories.
- PR c++/6396
- * toplev.c (rest_of_compilation): Only run regrename and copy
- propagation if optimizing.
+2003-02-20 Richard Earnshaw <rearnsha@arm.com>
-2002-04-30 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+ * arm.c (arm_reload_in_hi): Ensure that the scratch register does
+ not overlap the final result register.
- * doc/contrib.texi (Contributors): Use MIPS instead of Mips and
- mips. Add two missing commas.
+2003-02-20 Josef Zlomek <zlomekj@suse.cz>
-2002-04-30 Paolo Carlini <pcarlini@unitus.it>
+ * combine.c (distribute_notes): Kill REG_EXEC_COUNT.
+ * rtl.c (reg_note_name): Likewise.
+ * rtl.h (enum reg_note): Likewise.
+ * doc/invoke.texi: Likewise.
+ * doc/rtl.texi: Likewise.
- * doc/contrib.texi (Contributors): Update Paolo Carlini's
- and Benjamin Kosnik's entries.
+2003-01-30 Richard Henderson <rth@redhat.com>
-2002-04-29 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+ * tree-inline.c (walk_tree): Streamline duplicate hash table lookup.
- * combine.c (find_split_point): Use trunc_int_for_mode.
+2003-02-19 Daniel Jacobowitz <drow@mvista.com>
-Mon Apr 29 17:19:10 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * expr.c (expand_expr): Use gen_int_mode for the argument
+ to gen_rtx_MULT.
- * reload1.c (eliminate_regs, case SUBREG): Fix typo in
- adjust_address_nv call.
+2003-02-19 Jan Hubicka <jh@suse.cz>
-2002-04-29 Janis Johnson <janis187@us.ibm.com>
+ * i386.md (cosxf2): Fix conditional.
- * doc/install.texi (Testing): Provide additional information, and
- a stronger encouragement, for running the testsuites.
+2003-02-18 Matt Austern <austern@apple.com>
+ * toplev.c, langhooks.c, langhooks-def.h: Move
+ write_global_declarations from toplev.c to langhooks.c.
-2002-04-29 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+2003-02-18 Kazu Hirata <kazu@cs.umass.edu>
- * fixinc/inclhack.def (solaris_widec): Include <wchar.h> in
- Solaris 2 <widec.h> if missing.
- * fixinc/fixincl.x: Regenerate.
- * fixinc/tests/base/widec.h: New file.
+ * config/h8300/h8300.c (general_operand_src): Always check
+ MODE.
+ (general_operand_dst): Likewise.
-2002-04-29 Jakub Jelinek <jakub@redhat.com>
+2003-02-18 Richard Henderson <rth@redhat.com>
- PR target/6476
- * configure.in: Check whether linker eh_frame optimizations work
- properly.
- * configure: Rebuilt.
+ * c-common.c (handle_used_attribute): Accept static data too.
-Mon Apr 29 17:08:09 CEST 2002 Jan Hubicka <jh@suse.cz>
+2003-02-18 Jim Wilson <wilson@redhat.com>
- * i386.c (dbx64_register_map): Fix typo.
+ * config/ia64/ia64.md (floatdidf2, floatdisf2): Add %, before second
+ instruction in output template.
+ (bsp_value): Change output template from string to C code, add %,
+ before actual instruction.
+ (flushrs): Mark as not predicable.
-Mon Apr 29 14:48:33 CEST 2002 Jan Hubicka <jh@suse.cz>
+2003-02-18 Kazu Hirata <kazu@cs.umass.edu>
- * i386.md (sse_mov?fcc*): Revert patch of Apr 18th.
+ * config/h8300/h8300.md (*zero_extendhisi2_h8300): Fix the
+ insn length.
+ (extendqisi2): Likewise.
+ (*extendhisi2_h8300): Likewise.
-2002-04-29 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+2003-02-18 Matt Austern <austern@apple.com>
- * doc/contrib.texi (Contributors): Add Paolo Carlini and
- Janis Johnson.
- Update Richard Henderson, Jakub Jelinek, and Mark Mitchell.
- Refer to Objective-C instead of ObjC, SPARC instead of sparc,
- and CPU instead of cpu.
+ * langhooks.h, langhooks-def.h: introduce new langhook,
+ final_write_globals, with write_global_declarations as default.
+ * toplev.c: Move invocation of wrapup_global_declarations from
+ compile_file to new function, write_global_declarations. Change
+ compile_file to use final_write_globals hook. Change
+ wrapup_global_declarations so writing to DECL_DEFER_OUTPUT is
+ conditional.
-2002-04-29 Alexandre Oliva <aoliva@redhat.com>
+2003-02-18 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
- * config.gcc: Revert i386 changes inadvertently brought in
- from mainline along with 2002-04-04's change.
+ * pa.md: Correct and enhance comment.
-2002-04-28 David S. Miller <davem@redhat.com>
+2003-02-16 Kai Henningsen <kaih@khms.westfalen.de>
+ Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
- PR target/6496
- * config/sparc/sparc.md (call followed by jump peephole): Do not
- match for TARGET_V9, kill TARGET_ARCH64 variants.
+ * doc/install.texi (Specific): Fix link for m68k-att-sysv.
+ (Binaries): Ditto for Sinix/Reliant Unix.
- PR target/6500
- * config/sparc/sparc.md (prefetch): Emit properly for 32-bit vs.
- 64-bit TARGET_V9. Do not use prefetch page, use prefetch for
- several {reads,writes} instead.
- * config/sparc/sparc.h (PREFETCH_BLOCK, SIMULTANEOUS_PREFETCHES):
- Define.
+2003-02-16 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
-2002-04-27 David S. Miller <davem@redhat.com>
+ * config/i386/i386-protos.h (function_arg_pass_by_reference): Declare.
+ * config/i386/i386.h (FUNCTION_ARG_PASS_BY_REFERENCE): Use it.
+ * config/i386/i386.c (function_arg_pass_by_reference): New.
+ (ix86_va_arg): Support arguments passed by reference.
- PR target/6494
- * config/sparc/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Be mindful
- of the stack bias.
+2003-02-16 Arend Bayer <arend.bayer@web.de>
+ Richard Henderson <rth@redhat.com>
- * config/sparc/linux.h, config/sparc/linux64.h: Don't bother
- including signal.h and sys/ucontext.h, not needed.
+ PR c/8068
+ * fold-const.c (extract_muldiv_1): Rename from extract_muldiv;
+ rearrange mult arguments for less recursion.
+ (extract_muldiv): New. Prevent runaway recursion.
-2002-04-28 Richard Henderson <rth@redhat.com>
+2003-02-16 Danny Smith <dannysmith@users.sourceforge.net>
- PR c/5154
- * ggc-common.c (ggc_mark_rtx_children_1): Rename from...
- (ggc_mark_rtx_children): New.
+ * config/i386/cygwin.h (TARGET_SUBTARGET_DEFAULT): Set
+ MASK_ALIGN_DOUBLE.
-2002-04-28 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+2003-02-15 Adam Nemet <anemet@lnxw.com>
- PR c/6497
- * config/rs6000/rs6000.md (sCC patterns): Remove clobber and use
- result as temporary value.
+ PR opt/2391
+ * combine.c: Fix spelling in comment.
+ (cached_nonzero_bits): New function.
+ (cached_num_sign_bit_copies): New function.
+ (nonzero_bits_with_known): New macro.
+ (num_sign_bit_copies_with_known): New macro.
+ (nonzero_bits1): Rename from nonzero_bits. Add three new
+ arguments. Change calls from nonzero_bits to
+ nonzero_bits_with_known.
+ (num_sign_bit_copies1): Rename from num_sign_bit_copies. Add
+ three new arguments. Change calls from num_sign_bit_copies to
+ num_sign_bit_copies_with_known.
+ (nonzero_bits): New macro.
+ (num_sign_bit_copies): New macro.
+ (update_table_tick): Don't traverse identical subexpression more
+ than once.
+ (get_last_value_validate): Likewise.
-2002-04-28 Jakub Jelinek <jakub@redhat.com>
+2003-02-15 Falk Hueffner <falk.hueffner@student.uni-tuebingen.de>
- PR optimization/6475
- * reload1.c (alter_reg): Only call set_mem_expr if I is home pseudo
- register of REGNO_DECL (i).
- * Makefile.in (reload1.o): Add $(TREE_H).
+ PR optimization/7702
+ * reload1.c (reload_cse_simplify_set): Honor
+ CANNOT_CHANGE_MODE_CLASS.
-2002-04-28 Bruce Korb <bkorb@gnu.org>
+2003-02-15 Jan Hubicka <jh@suse.cz>
- * fixinc/check.tpl (set-writable): verify that it exists before
- invoking.
+ PR optimization/9258, PR fortran/7681
+ * global.c (struct allocno): Add no_stack_reg.
+ (global_conflicts): Set it.
+ (find_reg): Use it.
-2002-04-28 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+2003-02-14 Alexandre Oliva <aoliva@redhat.com>
- PR c/6343
- * c-decl.c (duplicate_decls): Call merge_weak.
- * c-pragma.c (apply_pragma_weak): Warn about misuse.
- * output.h (merge_weak): Prototype merge_weak.
- * varasm.c (merge_weak): New function.
- (declare_weak): Make sure we don't give an error on VAR_DECLs.
- Mark RTL with SYMBOL_REF_WEAK.
+ * config/mn10300/mn10300.c (mn10300_wide_const_load_uses_clr): New
+ function.
+ * config/mn10300/mn10300-protos.h: Declare it.
+ * config/mn10300/mn10300.md (movdi, movdf): Use it to compute
+ attribute cc of instructions that may use clr.
-2002-04-25 David S. Miller <davem@redhat.com>
+2003-02-13 John David Anglin <dave.anglin@nrc-crnc.gc.ca>
- PR target/6422
- * reorg.c (optimize_skip): Do not allow exception causing
- instructions to be considered for delay slots.
- (fill_simply_delay_slots, fill_slots_from_thread): Likewise.
- (relax_delay_slots): Do not try to consider exception causing
- instructions as redundant.
+ * inclhack.def (hpux_long_double): Tighten select and add bypass
+ regexp.
+ * fixincl.x: Rebuilt.
-2002-04-26 Alexandre Oliva <aoliva@redhat.com>
+2003-01-30 Richard Henderson <rth@redhat.com>
- * tree.c (tree_int_cst_lt): Compare constants whose types differ
- in unsigned-ness correctly.
+ * ggc-page.c (G.context_depth_allocations): New.
+ (G.context_depth_collections): New.
+ (alloc_page): Set G.context_depth_allocations.
+ (ggc_collect): Set G.context_depth_collections.
+ (ggc_push_context): Limit to HOST_BITS_PER_LONG contexts.
+ (ggc_pop_context): Early exit for no allocations or collections.
-2002-04-26 Chris Demetriou <cgd@broadcom.com>
+2003-01-25 Segher Boessenkool <segher@koffie.nl>
- * config/mips/mips.h (SUBTARGET_CPP_SIZE_SPEC): Get closer to
- correct for MEABI (used by mipsisa32-elf).
+ * bitmap.h (BITMAP_WORD): New typedef: fundamental storage
+ type for bitmaps. Use unsigned long.
+ (nBITMAP_WORD_BITS): New macro.
+ (BITMAP_WORD_BITS): New macro.
+ (rest of file): Use it.
+ * bitmap.c: Use it.
-2002-04-26 Mark Mitchell <mark@codesourcery.com>
+2003-02-13 Josef Zlomek <zlomekj@suse.cz>
- PR bootstrap/6445
- * config/i386/i386.md (untyped_call): Return the value in a float
- register if TARGET_FLOAT_RETURNS_IN_80387, not just if
- TARGET_80387.
+ * cfgcleanup.c (outgoing_edges_match): When there is single outgoing
+ edge and block ends with a jump insn it must be simple jump.
-2002-04-26 Ulrich Weigand <uweigand@de.ibm.com>
+2003-02-13 Robert Lipe <robertlipe@usa.net>
+ Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
- * config/s390/linux.h: Revert 2002-04-22 change.
+ * doc/install.texi (Specific): Update three SCO-related URLs.
-2002-04-26 John David Anglin <dave@hiauly1.hia.nrc.ca>
+2003-02-12 Ranjit Mathew <rmathew@hotmail.com>
- * pa.h (FUNCTION_OK_FOR_SIBCALL): Don't do sibcalls when using the
- portable runtime model.
+ * doc/tm.texi (MODIFY_JNI_METHOD_CALL): Document.
+ * config/i386/cygwin.h (MODIFY_JNI_METHOD_CALL): New macro.
-2002-04-26 David Edelsohn <edelsohn@gnu.org>
- Richard Henderson <rth@redhat.com>
+2003-02-11 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
- * config/rs6000/rs6000.md (sCC pattern): Remove clobber and use
- result as temporary value.
+ * doc/install.texi (Specific): Update AVR- and Darwin-related URLs.
-2002-04-26 Richard Henderson <rth@redhat.com>
+2003-02-11 Eric Botcazou <ebotcazou@libertysurf.fr>
- PR c/3581
- * c-common.c (combine_strings): Use xmalloc, not alloca.
+ PR c/9100
+ Backport patch from mainline:
- * c-common.c (combine_strings): Tweak __FUNCTION__ warning text.
+ 2003-01-12 Mark Mitchell <mark@codesourcery.com>
-2002-04-26 Bo Thorsen <bo@suse.co.uk>
+ PR c++/9264
+ * c-lex.c (c_lex): Set the token value to error_mark_node for
+ invalid numeric constants.
- * config/i386/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Define for
- x86-64.
-
-2002-04-25 David S. Miller <davem@redhat.com>
-
- * config/sparc/sparc.h (FUNCTION_OK_FOR_SIBCALL): Add back check
- for DECL being NULL.
-
-2002-04-25 Eric Botcazou <ebotcazou@multimania.com>
-
- * c-decl.c (grokdeclarator): Remove outdated ??? note
- on invalid declaration of flexible array members.
-
-2002-04-25 Richard Henderson <rth@redhat.com>
-
- * doc/invoke.texi: Document -gdwarf{,-2} vs debug level.
-
-2002-04-25 Ulrich Weigand <uweigand@de.ibm.com>
-
- * config/s390/s390.c (s390_emit_epilogue): Always restore registers
- needed by the compiler, even if they are used as global regs.
-
-2002-04-25 Steven Bosscher <S.Bosscher@student.tudelft.nl>
-
- * doc/c-tree.texi: Fix typo in introduction.
-
-2002-04-24 Richard Henderson <rth@redhat.com>
-
- * configure.in (HAVE_GAS_HIDDEN): Detect sparc binutils 2.12
- linker bug.
-
-2002-04-24 Jason Merrill <jason@redhat.com>
-
- * dwarf2.h (enum dwarf_attribute): Add DW_AT_GNU_vector.
- * dwarf2out.c (dwarf_attr_name): Support it.
- (gen_array_type_die): Emit it.
- (lookup_type_die): No special handling for VECTOR_TYPE.
- (gen_type_die): Hand VECTOR_TYPE off to gen_array_type_die.
-
-2002-04-24 Richard Henderson <rth@redhat.com>
-
- * config/mips/mips.md (movdi_usd): Renumber.
-
-2002-04-24 Robert Lipe <robertlipe@usa.net>
-
- * config/i386/sco5.h(i386.h, att.h): Eliminate double inclusion.
-
-2002-04-24 David S. Miller <davem@redhat.com>
-
- * config/sparc/sparc.h (FUNCTION_OK_FOR_SIBCALL): Return false if
- 32-bit Sparc and current_function_returns_struct is true.
-
-2002-04-24 Aldy Hernandez <aldyh@redhat.com>
-
- * config/rs6000/altivec.h: Cleanup file. Add non individual
- variants.
- (vec_vaddubm): New.
- (vec_vadduhm): New.
- (vec_vadduwm): New.
- (vec_vaddfp): New.
- (vec_vaddcuw): New.
- (vec_vaddubs): New.
- (vec_vaddsbs): New.
- (vec_vadduhs): New.
- (vec_vadduws): New.
- (vec_vaddsws): New.
- (vec_vand): New.
- (vec_vandc): New.
- (vec_vavgub): New.
- (vec_vavgsb): New.
- (vec_vavguh): New.
- (vec_vavgsh): New.
- (vec_vavguw): New.
- (vec_vavgsw): New.
- (vec_vrfip): New.
- (vec_vcmpbfp): New.
- (vec_vcmpequb): New.
- (vec_vcmpequh): New.
- (vec_vcmpequw): New.
- (vec_vcmpeqfp): New.
- (vec_vcmpgefp): New.
- (vec_vcmpgtub): New.
- (vec_vcmpgtsb): New.
- (vec_vcmpgtuh): New.
- (vec_vcmpgtsh): New.
- (vec_vcmpgtuw): New.
- (vec_vcmpgtsw): New.
- (vec_vcmpgtfp): New.
- (vec_vcmpgefp): New.
- (vec_vcfux): New.
- (vec_vcfsx): New.
- (vec_vctsxs): New.
- (vec_vctuxs): New.
- (vec_vexptefp): New.
- (vec_vrfim): New.
- (vec_lvx): New.
- (vec_lvebx): New.
- (vec_lvehx): New.
- (vec_lde): Add vector float variant.
- (vec_lvewx): New.
- (vec_lvxl): New.
- (vec_vlogefp): New.
- (vec_vmaddfp): New.
- (vec_vmhaddshs): New.
- (vec_vmaxub): New.
- (vec_vmaxsb): New.
- (vec_vmaxuh): New.
- (vec_vmaxsh): New.
- (vec_vmaxuw): New.
- (vec_vmaxsw): New.
- (vec_vmaxsw): New.
- (vec_vmaxfp): New.
- (vec_vmrghb): New.
- (vec_vmrghh): New.
- (vec_vmrghw): New.
- (vec_vmrglb): New.
- (vec_vmrglh): New.
- (vec_vmrglw): New.
- (vec_vminub): New.
- (vec_vminsb): New.
- (vec_vminuh): New.
- (vec_vminsh): New.
- (vec_vminuw): New.
- (vec_vminsw): New.
- (vec_vminfp): New.
- (vec_vmladduhm): New.
- (vec_vmhraddshs): New.
- (vec_msumubm): New.
- (vec_vmsummbm): New.
- (vec_vmsumuhm): New.
- (vec_vmsumshm): New.
- (vec_vmsumuhs): New.
- (vec_vmsumshs): New.
- (vec_vmuleub): New.
- (vec_vmulesb): New.
- (vec_vmuleuh): New.
- (vec_vmulesh): New.
- (vec_vmuloub): New.
- (vec_mulosb): New.
- (vec_vmulouh): New.
- (vec_vmulosh): New.
- (vec_vnmsubfp): New.
- (vec_vnor): New.
- (vec_vor): New.
- (vec_vpkuhum): New.
- (vec_vpkuwum): New.
- (vec_vpkpx): New.
- (vec_vpkuhus): New.
- (vec_vpkshss): New.
- (vec_vpkuwus): New.
- (vec_vpkswss): New.
- (vec_vpkshus): New.
- (vec_vpkswus): New.
- (vec_vperm): New.
- (vec_vrefp): New.
- (vec_vrlb): New.
- (vec_vrlh): New.
- (vec_vrlw): New.
- (vec_vrfin): New.
- (vec_vrsqrtefp): New.
- (vec_vsel): New.
- (vec_vslb): New.
- (vec_vslh): New.
- (vec_vslw): New.
- (vec_vsldoi): New.
- (vec_vsl): New.
- (vec_vslo): New.
- (vec_vspltb): New.
- (vec_vsplth): New.
- (vec_vspltw): New.
- (vec_vspltisb): New.
- (vec_vspltish): New.
- (vec_vspltisw): New.
- (vec_vsrb): New.
- (vec_vsrh): New.
- (vec_vsrw): New.
- (vec_vsrab): New.
- (vec_vsrah): New.
- (vec_vsraw): New.
- (vec_vsr): New.
- (vec_vsro): New.
- (vec_stvx): New.
- (vec_stvebx): New.
- (vec_stvehx): New.
- (vec_stvewx): New.
- (vec_stvxl): New.
- (vec_vsububm): New.
- (vec_vsubuhm): New.
- (vec_vsubuwm): New.
- (vec_vsubfp): New.
- (vec_vsubcuw): New.
- (vec_vsububs): New.
- (vec_vsubsbs): New.
- (vec_vsubuhs): New.
- (vec_vsubshs): New.
- (vec_vsubuws): New.
- (vec_vsubsws): New.
- (vec_vsum4ubs): New.
- (vec_vsum4sbs): New.
- (vec_vsum4shs): New.
- (vec_vsum2sws): New.
- (vec_vsumsws): New.
- (vec_vrfiz): New.
- (vec_vupkhsb): New.
- (vec_vupkhpx): New.
- (vec_vupkhsh): New.
- (vec_vupklsb): New.
- (vec_vupklpx): New.
- (vec_vupklsh): New.
- (vec_vxor): New.
-
-2002-04-23 Zack Weinberg <zack@codesourcery.com>
-
- * doc/install.texi: Clarify which versions of alpha*-dec-osf*
- are obsoleted.
-
-2002-04-23 Eric Botcazou <ebotcazou@multimania.com>
-
- PR c/5430
- * fold-const.c (split_tree): Add MINUS_LITP parameter; separate
- added literals from substracted literals.
- (associate_trees): Don't convert MINUS_EXPR into PLUS_EXPR.
- (fold) [associate]: Preserve MINUS_EXPR if needed.
-
-2002-04-23 Tom Tromey <tromey@redhat.com>
-
- * gcc.c: Added --resource. For PR java/6314.
-
-2002-04-23 David O'Brien <obrien@FreeBSD.org>
-
- * config/freebsd.h(OBJECT_FORMAT_ELF): Define.
-
-2002-04-23 David O'Brien <obrien@FreeBSD.org>
-
- * cp/g++spec.c: Use profiled libstdc++ and libm with -p/-pg.
- * config/freebsd.h (MATH_LIBRARY_PROFILE): Use the _p verions of
- these libraries.
-
-2002-04-23 Alan Modra <amodra@bigpond.net.au>
-
- PR target/6413
- * function.h: (struct function): Add profile_label_no field.
- (current_function_profile_label_no): Define.
- * function.c: (profile_label_no): New static var.
- (expand_function_start): Increment it, and copy to
- current_function_profile_label_no.
- * output.h (profile_label_no): Delete.
- * final.c (profile_label_no): Delete.
- (profile_function): Use current_function_profile_label_no.
- (final_end_function): Don't increment profile_label_no here.
- * config/i386/i386.c (ix86_osf_output_function_prologue): Replace
- profile_label_no with current_function_profile_label_no.
- * config/pa/pa.c (current_function_number): Delete.
- (pa_output_function_prologue): Don't output profile label here.
- (hppa_profile_hook): Use label_no param rather than
- current_function_number.
- (FUNC_BEGIN_PROLOG_LABEL): Move to ..
- * config/pa/pa.h: .. here.
- (FUNCTION_PROFILER): Output profile label here.
-
-2002-04-23 Aldy Hernandez <aldyh@redhat.com>
-
- * config/rs6000/altivec.h (vec_step): Remove extraneous
- parentheses.
- (vec_ctu): Cast return.
-
-2002-04-22 Aldy Hernandez <aldyh@redhat.com>
-
- * config/rs6000/rs6000.md ("*movv4si_internal"): Change 'm'
- constraint to 'o' for m=r and r=m alternatives.
- ("*movv8hi_internal1"): Same.
- ("*movv16qi_internal1"): Same.
- ("*movv4sf_internal1"): Same.
+2003-02-11 Jan Hubicka <jh@suse.cz>
-2002-04-22 Zack Weinberg <zack@codesourcery.com>
+ * i386.md (ahi?v*3): Set third operand type to TImode.
+ * i386.c (ix86_expand_binop_builtin): Extend operand when needed.
- * c-lex.c (lex_charconst): Call convert to get constant in
- proper type; don't just smash the type field.
- Fixes PR c/6300.
+ * i386.c (contains_128bit_aligned_vector_p): New function
+ (ix86_function_arg_boundary): Properly align vector modes.
- * config.gcc: Add list of obsolete configurations. Disallow
- building these without --enable-obsolete.
- * doc/install.texi: Document --enable-obsolete and obsoletion
- policy. Mention obsoletion of individual targets in
- appropriate places.
+2003-02-11 Bob Wilson <bob.wilson@acm.org>
-2002-04-22 Richard Henderson <rth@redhat.com>
+ Backport following patch:
- * config/sparc/sol2-bi.h (ASM_DEBUG_SPEC): New.
+ 2003-02-11 Bob Wilson <bob.wilson@acm.org>
-2002-04-22 Mark Mitchell <mark@codesourcery.com>
+ * config/xtensa/xtensa.md (set_frame_ptr): Change rtl to set reg a7.
+ * config/xtensa/xtensa.c (xtensa_reorg): Search for UNSPECV_SET_FP
+ as a SET pattern.
- PR f/6138.
- * function.c (fixup_memory_subreg): Add promoted_mode parameter.
- (walk_fixup_memory_subreg): Likewise.
- (fixup_var_refs_insn): Adjust accordingly.
- (fixup_var_refs_1): Likewise.
+2003-02-11 Jan Hubicka <jh@suse.cz>
-2002-04-22 Joel Sherrill <joel@OARcorp.com>
+ * simplify-rtx.c (simplify_subreg): Fix conversion from vector into
+ integer mode.
- * gthr-rtems.h: Correct prototypes to remove warnings.
+ * rtl.def (VEC_MERGE, VEC_SELECT, VEC_CONCAT, VEC_DUPLICATE):
+ Change code so they are arithmetic expressions now.
+ * simplify-rtx.c (simplify_unary_operation, simplify_binary_operation,
+ simplify_ternary_operation): Deal with VEC_* expressions.
-2002-04-22 Richard Henderson <rth@redhat.com>
+2003-02-11 Richard Henderson <rth@redhat.com>
- PR c/6344
- * alias.c (canon_true_dependence): Special case (mem:blk (scratch)).
+ 2003-01-15 Richard Henderson <rth@redhat.com>
+ * config/alpha/alpha.c (find_lo_sum_using_gp): Rename from find_lo_sum;
+ also check that GP is being used.
+ (alpha_find_lo_sum_using_gp): New.
+ (alpha_does_function_need_gp): Use get_attr_usegp.
+ * config/alpha/alpha-protos.h: Update.
+ * config/alpha/alpha.md (attr usegp): New. Annotate patterns
+ as needed.
- * gcse.c (free_insn_expr_list_list): New.
- (clear_modify_mem_tables): Use it. Fix bit set usage.
- (canon_list_insert): Use EXPR_LISTs for expressions.
- (record_last_mem_set_info): Factor BLOCK_NUM (insn).
+2003-02-11 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
-2002-04-22 Ulrich Weigand <uweigand@de.ibm.com>
+ * inclhack.def (hpux_long_double, hpux10_ctype_declarations1,
+ hpux10_ctype_declarations2, hpux_ctype_macros): New hacks.
+ * fixincl.x: Rebuilt.
+ * tests/base/stdlib.h: Update.
+ * tests/base/ctype.h: New file.
- * config/s390/linux.h: (LIBPATH_SPEC, LIBPATH_ARCH31_SPEC,
- LIBPATH_ARCH64_SPEC): Define.
- (EXTRA_SPECS): Add libpath, libpath_arch31, libpath_arch64.
- (STARTFILE_SPEC, ENDFILE_SPEC): Define; use libpath.
- (LINK_ARCH31_SPEC): Add libpath_arch31 to search path.
- (LINK_ARCH64_SPEC): Add libpath_arch64 to search path.
+2003-02-11 Janis Johnson <janis187@us.ibm.com>
-2002-04-22 Aldy Hernandez <aldyh@redhat.com>
+ * config/rs6000/ppc64-fp.c: New file.
+ * config/rs6000/t-linux64 (LIB2FUNCS_EXTRA): Add ppc64-fp.c.
- * config/rs6000/altivec.h (vec_xor): Add variant for both args
- being vector signed int.
- (vec_andc): Same.
- (vec_xor): Add variant for both args being vector signed char.
- Remove redundant variant.
- (vec_andc): Same.
+2003-02-11 Falk Hueffner <falk.hueffner@student.uni-tuebingen.de>
-2002-04-21 David S. Miller <davem@redhat.com>
+ PR optimization/9651
+ * rtlanal.c (may_trap_p): Handle FIX.
- * config/sparc/sparc.md (set then compare DI mode peephole2): Fix
- compare mode in output RTL.
+2003-02-11 Jan Hubicka <jh@suse.cz>
-2002-04-22 David Edelsohn <edelsohn@gnu.org>
+ * predict.c (choose_function_section): Choose sections correctly.
- * config/rs6000/rs6000.c (rs6000_override_options): Correct
- style and formatting of previous patch.
+2003-02-10 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
-2002-04-22 Alan Modra <amodra@bigpond.net.au>
+ * reload1.c (first_label_num): New.
+ (reload): Index offsets_known_at and offsets_at using difference of
+ label number and first label number. Don't use offset pointers.
+ (set_label_offsets, set_initial_label_offsets): Likewise.
- * config/rs6000/rs6000.c (rs6000_override_options): Always clear
- flag_pic for ABI_AIX.
+2003-02-10 Eric Botcazou <ebotcazou@libertysurf.fr>
+ Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de>
-2002-04-21 Neil Booth <neil@daikokuya.demon.co.uk>
+ PR c/7741
+ * c-decl.c (duplicate_decls): Discard the initializer of the
+ new decl when the types are conflicting.
- * cppmacro.c (funlike_invocation_p): Don't step back
- over CPP_EOF.
+2003-02-09 Wolfgang Bangerth <bangerth@ticam.utexas.edu>
-2002-04-21 David Edelsohn <edelsohn@gnu.org>
+ * doc/install.texi: Squeeze and streamline section on
+ testing and regression checking.
- * config/rs6000/rs6000.c (output_profile_hook): Do not increment
- labelno.
+2003-02-07 Jason Thorpe <thorpej@wasabisystems.com>
-2002-04-20 Joseph S. Myers <jsm28@cam.ac.uk>
+ * config/t-netbsd (USER_H): Revert previous change.
- * doc/invoke.texi: Remove Chill references.
- * doc/gcc.texi: Update last modified date.
+2003-02-07 Richard Henderson <rth@redhat.com>
-2002-04-19 David S. Miller <davem@redhat.com>
+ PR 9226
+ * gcse.c (local_cprop_find_used_regs): New.
+ (local_cprop_pass): Use it.
- * config/sparc/linux.h (MD_FALLBACK_FRAME_STATE_FOR): Define.
- * config/sparc/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Likewise.
+2003-02-07 Jan Hubicka <jh@suse.cz>
-Sat Apr 20 02:17:38 CEST 2002 Jan Hubicka <jh@suse.cz>
+ * i386.md (sse2_nandv2di3): Fix.
- * i386.md (movsi_1, movhi_1): Force reload to use more flexible
- alternative.
+ * i386.md (movdi_rex64_1): Fix mmx<->int move opcode.
-2002-04-19 Jakub Jelinek <jakub@redhat.com>
+2003-02-07 Andrey Petrov <petrov@netbsd.org>
- PR c/6358
- * function.c: Reapply patch for c/6358.
- (expand_function_end): Copy decl_rtl's mode, not
- current_function_return_rtx mode.
+ * optabs.c (expand_float): Search wider integer modes first.
-2002-04-19 Joel Sherrill <joel@OARcorp.com>
+2003-02-06 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
- * config/rtems.h (STARTFILE_SPEC, ENDFILE_SPEC): Fix for non-ELF
- targets.
+ * config.gcc (hppa*-*-linux*): Set MASK_NO_SPACE_REGS in
+ target_cpu_default.
+ * pa.c (attr_length_call): Add 8 to call length (long indirect PA 1.X)
+ if not MASK_NO_SPACE_REGS.
+ (output_call): Adjust return pointer, don't load new space register
+ into %sr0, and use %sr4 for call if TARGET_NO_SPACE_REGS is true.
+ (pa_asm_output_mi_thunk): Don't load new space register into %sr0 if
+ TARGET_NO_SPACE_REGS is true.
+ * pa.md (return_external_pic): Add TARGET_NO_SPACE_REGS to insn
+ conditions.
+ (epilogue): Always use return_internal if TARGET_NO_SPACE_REGS is true.
+ (interspace_jump): Add new pattern for when TARGET_NO_SPACE_REGS is
+ true. Use bve when TARGET_64BIT is true.
-2002-04-19 Tom Tromey <tromey@redhat.com>
+2003-02-06 Eric Botcazou <ebotcazou@libertysurf.fr>
+ Richard Henderson <rth@redhat.com>
- * doc/install.texi (Specific): Update status of Solaris 2.8.
- For PR libgcj/6158.
+ PR c/9530
+ * config/i386/i386.h (FUNCTION_OK_FOR_SIBCALL): Forbid sibcalls
+ from functions that return a float to functions that don't.
-2002-04-19 Dan Nicolaescu <dann@godzilla.ics.uci.edu>
- Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+2003-02-04 Ulrich Weigand <uweigand@de.ibm.com>
- * doc/install.texi (Specific, sparc-sun-solaris2*): Mention that
- binutils 2.11.2 and higher generate smaller binaries than Sun's
- native tools.
+ * reload.c (find_reloads): Do not use the mode specified in the insn
+ pattern as reload mode for address operands. Do not generate optional
+ reloads for operands where a mandatory reload was already pushed.
-2002-04-19 Mark Mitchell <mark@codesourcery.com>
+2003-02-04 Jan Hubicka <jh@suse.cz>
- PR c++/6352
- * toplev.c (rest_of_compilation): Do not defer functions for which
- TREE_SYMBOL_REFERENCED has already been set.
+ * i386.md (movti_rex64): Fix constraint.
-2002-04-18 Richard Henderson <rth@redhat.com>
+2003-02-04 Rodney Brown <rbrown64@csc.com.au>
- * function.c: Revert patch for c/6358.
+ * config/i386/i386.c (x86_function_profiler): Fix typo in format.
-2002-04-18 Richard Henderson <rth@redhat.com>
+2003-01-23 Mike Stump <mrs@apple.com>
- * ifcvt.c (find_cond_trap): Handle cases with no proper THEN or JOIN
- blocks. Handle multiple references to the TRAP block. Handle
- non-adjacent THEN and OTHER blocks.
+ * regclass.c (init_reg_autoinc): New function.
+ (regclass): Move initialization of forbidden_inc_dec_class from
+ here...
+ (init_regs): to here. Avoids reinitialization for each function,
+ saving compilation time.
-2002-04-18 Richard Henderson <rth@redhat.com>
+2003-02-04 Phil Edwards <pme@gcc.gnu.org>
- * config/ia64/ia64.c (ia64_function_arg_pass_by_reference): Don't
- crash with no type for by-mode libcalls.
+ * doc/install.texi (*-*-linux-gnu): Mention glibc requirements
+ for recent libstdc++. Remove formatting cruft.
- * config/ia64/ia64.md (conditional_trap): Fix predicate polarity.
+2003-02-04 Joseph S. Myers <jsm@polyomino.org.uk>
-2002-04-18 David S. Miller <davem@redhat.com>
+ * doc/gcc.texi, doc/gccint.texi, doc/gcov.texi,
+ doc/include/fdl.texi, doc/invoke.texi: Update to GFDL 1.2.
+ * doc/install.texi: Update copyright dates. Update to GFDL 1.2.
- * config/sparc/sparc.h (BRANCH_COST): Define.
+2003-02-03 Bob Wilson <bob.wilson@acm.org>
- * fold-const.c (BRANCH_COST): Don't provide default here, expr.h
- does it.
+ * config/xtensa/xtensa.c (order_regs_for_local_alloc): Order the
+ coprocessor registers before floating-point registers.
+ * config/xtensa/xtensa.h (REG_ALLOC_ORDER): Adjust register numbers
+ to account for a previously removed register.
+ (SPEC_REG_FIRST, SPEC_REG_LAST, SPEC_REG_NUM, COUNT_REGISTER_REGNUM):
+ Delete unused macros.
-2002-04-18 Richard Henderson <rth@redhat.com>
+2003-02-03 Jan Hubicka <jh@suse.cz>
- * config/ia64/ia64.c (ia64_function_arg_pass_by_reference): New.
- (ia64_va_arg): Expect variable sized types by reference.
- * config/ia64/ia64-protos.h: Update.
- * config/ia64/ia64.h (FUNCTION_ARG_PASS_BY_REFERENCE): Use
- ia64_function_arg_pass_by_reference.
+ * i386.c (ix86_expand_store_builtin): Always force op1 to register.
+ (mov*_internal): Fix predicates; require one of operands to not be memory.
+ (SSE?MMX move expanders): Fix predicates; force one of operands to register.
+ (SSE/MMX push patterns): Reorganize; fix x86-64 code generation.
+ (movups/movupd/movdqu patterns): Force one of operands to not be memory.
-2002-04-18 Hans-Peter Nilsson <hp@bitrange.com>
+2003-02-03 Jan Hubicka <jh@suse.cz>
- * flow.c (update_life_info): Ignore return value of cleanup_cfg.
- Mask out PROP_SCAN_DEAD_CODE | PROP_KILL_DEAD_CODE in
- propagate_block calls after relaxation loop using new variable
- stabilized_prop_flags.
+ * regclass.c (cannot_change_mode_set_regs): Correct argument order.
-2002-04-18 Richard Henderson <rth@redhat.com>
+2003-02-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * ifcvt.c: Include except.h.
- (block_has_only_trap): Break out from find_cond_trap.
- (find_cond_trap): Use it. Always delete the trap block.
- (merge_if_block): Allow then block null. Be less simplistic about
- what insns can end a block.
- * Makefile.in (ifcvt.o): Depend on except.h.
+ * mips/_tilib.c: Don't include tsystem.h. Don't define
+ LIBGCC2_WORDS_BIG_ENDIAN.
- * config/ia64/ia64.md (trap, conditional_trap): New.
+2003-02-02 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
-2002-04-18 Jakub Jelinek <jakub@redhat.com>
+ * doc/install.texi (hppa*-hp-hpux11*): Update installation notes.
- PR c/6358
- * function.c (assign_parms): Assign hard current_function_return_rtx
- register here...
- (expand_function_end): ...not here.
+2003-02-02 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
-2002-04-18 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+ * pa-protos.h (attr_length_millicode_call): Remove second argument.
+ (attr_length_indirect_call, attr_length_indirect_call,
+ attr_length_save_restore_dltp): New prototypes.
+ * pa.c (attr_length_millicode_call): Remove second argument. Check
+ INSN_ADDRESSES_SET_P in distance calculation.
+ (output_millicode_call): Check INSN_ADDRESSES_SET_P before using
+ INSN_ADDRESSES.
+ (attr_length_call): Check INSN_ADDRESSES_SET_P in distance calculation.
+ (output_call): Check INSN_ADDRESSES_SET_P before using INSN_ADDRESSES.
+ Call attr_length_call directly.
+ (attr_length_indirect_call, output_indirect_call,
+ attr_length_save_restore_dltp): New functions.
+ * pa.md (attr_length_millicode_call): Drop second argument from all
+ patterns.
+ (return_internal_pic): Delete.
+ (return_external_pic): Remove use of PIC register and pic operand and
+ flag checks.
+ (epilogue): Use return_internal for both normal and pic code.
+ (call, call_value): Emit new 32-bit pic patterns for symref and
+ indirect calls. Remove uses for arg pointer and pic register.
+ (call_symref_pic, call_symref_pic_post_reload, call_reg_pic,
+ call_reg_pic_post_reload, call_val_symref_pic,
+ call_val_symref_pic_post_reload, call_val_reg_pic,
+ call_val_reg_pic_post_reload): New pre and post reload insn patterns.
+ Implement define_split and define_peephole2 patterns for pre reload
+ patterns.
+ (call_symref_64bit, call_internal_reg_64bit, call_value_symref_64bit,
+ call_value_internal_reg_64bit): Shorten names.
+ (all call patterns): Explicitly indicate registers used and clobbered.
+ Use attr_length_indirect_call and attr_length_save_restore_dltp for
+ attribute length calculation. Move code generation for indirect calls
+ to output_indirect_call.
+ (sibcall, sibcall_value): Don't restore PIC register.
+ (exception_receiver, builtin_setjmp_receiver): Add blockage after PIC
+ register retore.
- * doc/install.texi (Downloading the source): Do not mention Chill
- any longer, but mention Ada.
- (Configuration): Do not mention Chill any longer.
+2003-02-02 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-04-18 Hans-Peter Nilsson <hp@axis.com>
+ * doc/install.texi (Testing): Simplify and compress instructions
+ concerning Dejagnu.
- * config/cris/cris.h (TARGET_VERSION): Remove local version number.
+2003-02-01 Daniel Jacobowitz <drow@mvista.com>
-Thu Apr 18 15:49:12 CEST 2002 Jan Hubicka <jh@suse.cz>
+ * dwarf2out.c (gen_type_die): Check for typedefs before calling
+ for TYPE_MAIN_VARIANT.
- * i386.h (SSE_FLOAT_MODE_P): Kill bogus TARGET_SSE_MATH check.
- * i386.md (sse_mov?fcc*): Swap operands for cases they will be swapped
- later.
+2003-02-01 Ulrich Weigand <uweigand@de.ibm.com>
-2002-04-18 Jakub Jelinek <jakub@redhat.com>
+ * reload.c: Revert 2003-01-31 change.
- PR middle-end/6205
- * config/i386/i386.md (movsf_1): Use pxor only if TARGET_SSE2,
- otherwise xorps.
+2003-02-01 Jan Hubicka <jh@suse.cz>
-2002-04-18 Loren J. Rittle <ljrittle@acm.org>
+ PR c/9506
+ * i386.c (override_options): Use DEFAULT_PCC_STRUCT_RETURN.
- Revert this change:
+2003-01-31 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
- * doc/install.texi (Installing GCC: Configuration): Clarify
- the only supported ways to configure gcc.
+ * pa.c (pa_output_function_prologue, pa_output_function_epilogue): Move
+ updating of total_code_bytes from prologue to epilogue.
-2002-04-17 Dale Johannesen <dalej@apple.com>
+2003-01-31 Ulrich Weigand <uweigand@de.ibm.com>
- * config/rs6000/rs6000.c (rs6000_emit_cmove): Fail if modes of
- comparison operands do not match each other or if modes of
- conditions do not match result.
- (rs6000_output_function_prologue): Compute instruction addresses.
- (rs6000_output_function_epilogue): Likewise.
+ * regclass.c (record_reg_classes): Fix incorrect argument
+ to EXTRA_ADDRESS_CONSTRAINT macro.
-2002-04-17 Ulrich Weigand <uweigand@de.ibm.com>
+2003-01-31 Ulrich Weigand <uweigand@de.ibm.com>
- * config/s390/s390.c (legitimize_pic_address): Do not generate
- illegal address constant without CONST.
+ * reload.c (find_reloads): Do not use the mode specified in the insn
+ pattern as reload mode for address operands. Do not generate optional
+ reloads for operands where a mandatory reload was already pushed.
+ Generate optional reloads only in the final pass though find_reloads.
+ (have_replacement_p): New function.
-2002-04-17 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+2003-01-31 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
- * sparc/linux64.h (CC1_SPEC): Error for -m32 and -m64.
- * sparc/netbsd-elf.h (CC1_SPEC32, CC1_SPEC64): Likewise.
+ * doc/install.texi (Testing): Remove a reference to our obsolete
+ /testresults web pages and strip redundant information concerning
+ test results.
+ (Binaries): Refer to Microsoft Windows instead of listing all
+ possible variants.
-2002-04-17 Ulrich Weigand <uweigand@de.ibm.com>
+2003-02-01 Jan Hubicka <jh@suse.cz>
- PR optimization/6305
- * config/s390/s390.c (s390_expand_plus_operand): Use find_replacement
- to make sure previous reloads are taken into account. Generate
- better code if one operand is an in-range immediate constant.
+ * loop.c (emit_prefetch_instructions): Do conversion at right place in
+ RTL chain.
-2002-04-16 Andrew Haley <aph@cambridge.redhat.com>
+ * combine.c (simplify_set): Reverse order of ragumetns to
+ REG_CANNOT_CHANGE_MODE_P
+ * df.c (df_def_record_1): Likewise.
+ * recog.c (register_operand): Likewise.
+ * simplify-rtx.c (simplify_subreg): Likewise.
+ * hard-reg-set.h (REG_CANNOT_CHANGE_MODE_P): Update use of
+ CANNOT_CHANGE_MODE_CLASS.
+ * regclass.c (cannot_change_mode_set_regs, invalid_mode_change_p):
+ Likewise.
+ * reload.c (push_reload): Likewise.
+ * alpha.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * ia64.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * mips.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * mips-protos.h (mips_cannot_change_mode_class): Update prototype.
+ * mips.c (mips_cannot_change_mode_class): Update.
+ * pa64-regs.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * rs6000.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * s390.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * sh.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * sh-protos.h (sh_cannot_change_mode_class): Update prototype.
+ * sh.c (sh_cannot_change_mode_class): Update.
+ * i386.h (CANNOT_CHANGE_MODE_CLASS): New.
+ * tm.texi (CANNOT_CHANGE_MODE_CLASS): Update documentation.
- * doc/install.texi (Building): libgcj requires GNU make.
+2003-01-31 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
-2002-04-17 Jakub Jelinek <jakub@redhat.com>
+ * pa32-regs.h (REGNO_REG_CLASS, REG_CLASS_FROM_LETTER): Delete
+ duplicated code.
- PR bootstrap/6315
- * config/sparc/sparc.md (movtf reg<-reg split): Allow spliting
- even if hard quad and register is not floating.
- (movtf reg<-mem split): Disallow splitting if hard quad and
- register is floating.
- (movtf mem<-reg split): Likewise.
- * config/sparc/sparc.c (fp_register_operand): New predicate.
- * config/sparc/sparc.h (PREDICATE_CODES): Add fp_register_operand.
+2003-01-30 Richard Earnshaw <rearnsha@arm.com>
-2002-04-17 Zack Weinberg <zack@codesourcery.com>
+ * arm.c (arm_compute_initial_elimination_offset): If optimizing for
+ size, the link register is always saved if any other register is
+ saved.
- * Makefile.in (PROTO_OBJS): Add cppdefault.o.
- (protoize.o): Take $(PREPROCESSOR_DEFINES) off command line.
- (unprotoize.o): Ditto. Build from protoize.c. Define
- UNPROTOIZE on command line.
- * protoize.c: Include cppdefault.h. Delete include_defaults.
- (in_system_include_dir): Use cpp_include_defaults (defined in
- cppdefault.o).
- * unprotoize.c: Delete file.
+2003-01-30 Jerry Quinn <jlquinn@optonline.net>
-2002-04-17 Aldy Hernandez <aldyh@redhat.com>
+ * gcc/doc/invoke.texi (Optimization Options): Group together
+ optional and experimental flags. Move trapv and bounds-check
+ out of this section. Group floating point flags together.
+ (Code Gen Options): Move trapv and bounds-check to here.
- * config/rs6000/altivec.h (vec_ld): Add array variants.
- (vec_lde): Same.
- (vec_ldl): Same.
+2003-01-30 Jerry Quinn <jlquinn@optonline.net>
-2002-04-17 Alan Matsuoka <alanm@redhat.com>
- Aldy Hernandez <aldyh@redhat.com>
+ * gcc/doc/invoke.texi (Optimization Options): List -O levels
+ for each optimization flag.
- * config/rs6000/altivec.h: Define __ALTIVEC__.
- (bool): New.
- (__pixel): New.
- (pixel): New.
- (vec_cfux): New.
- (vec_vmaddfp): New.
- (vec_vsldoi): New.
- Add parentheses to all macro arguments.
+2003-01-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
-2002-04-16 Richard Henderson <rth@redhat.com>
+ PR target/9316
+ * config/rs6000/rtems.h: Add CPP_OS_DEFAULT_SPEC.
+ * config/rs6000/sysv4.h: Add CPP_OS_RTEMS_SPEC.
+ * config/rs6000/t-rtems: New file. multilib variants to match OS.
+ * config.gcc (powerpc-*-rtems*): Use rs6000/t-rtems instead of
+ rs6000/t-ppcgas so we get the desired multilibs.
- PR c++/6320
- * except.c (remove_eh_handler): Insert inner regions at beginning
- of sibling chain. Refactor expressions.
+2003-01-30 Alexandre Oliva <aoliva@redhat.com>
-2002-04-16 Mark Mitchell <mark@codesourcery.com>
+ * config/fp-bit.h (__make_dp): Declare if TMODES.
- * c-common.h (STMT_EXPR_NO_SCOPE): New macro.
- * c-common.c (c_expand_expr): Respect STMT_EXPR_NO_SCOPE.
- * tree.h (expand_start_stmt_expr): Update prototype.
- * stmt.c (expand_start_stmt_expr): Add has_scope parameter.
- * tree-inline.c (expand_call_inline): Set STMT_EXPR_NO_SCOPE
- on the STMT_EXPR created for the inline function.
+2003-01-29 Steve Ellcey <sje@cup.hp.com>
-2002-04-16 Richard Henderson <rth@redhat.com>
+ * config/ia64/ia64.c (ia64_rwreloc_section_type_flags): New.
+ * config/ia64/hpux.h (TARGET_SECTION_TYPE_FLAGS): New.
- * config/sparc/sol2-bi.h (AS_SPARC64_FLAG): New.
- * config/sparc/sol2-gas-bi.h: New file.
- * config.gcc (sparc*-solaris): Add it as needed.
- * configure.in (AS_SPARC64_FLAG): Remove check.
- * config.in, configure: Regenerate.
+2003-01-29 Steve Ellcey <sje@cup.hp.com>
- * config/sparc/sol2-bi.h (CC1_SPEC): Error for -m32 and -m64.
+ * config/ia64/ia64.c (ia64_rwreloc_select_rtx_section): Rename
+ from ia64_aix_select_rtx_section.
+ (ia64_rwreloc_select_section): Simlarly; use default*_1 function
+ instead of saving and restoring flag_pic.
+ (ia64_rwreloc_unique_section): Similarly.
+ * config/ia64/aix.h (TARGET_ASM_SELECT_SECTION,
+ TARGET_ASM_UNIQUE_SECTION, TARGET_ASM_SELECT_RTX_SECTION): Update.
+ * config/ia64/hpux.h (TARGET_ASM_SELECT_SECTION,
+ TARGET_ASM_UNIQUE_SECTION, TARGET_ASM_SELECT_RTX_SECTION): New.
-2002-04-16 Richard Henderson <rth@redhat.com>
+2003-01-29 Joel Sherrill <joel@OARcorp.com>
- * config/mips/mips.c (override_options): Don't override N32 for
- a 64-bit ISA.
+ PR bootstrap/9296
+ * gthr-rtems.h: Define __GTHREAD_MUTEX_INIT. Apparently no code
+ depended on it being defined until now.
- PR c/6202
- * config/mips/mips.md (can_delay): Split out of existing define_delays.
- (HILO_delay): Set can_delay false.
+2003-01-29 Joel Sherrill <joel@OARcorp.com>
-2002-04-16 Paolo Carlini <pcarlini@unitus.it>
+ PR target/9295
+ * config/mips/rtems.h: Predefine __USE_INIT_FINI__ so generic
+ RTEMS code knows which C++ initialization style the toolset
+ configuration is using.
- * c-parse.in (poplevel, compstmt_start, compstmt_primary_start):
- Add ending ';', in accordance with POSIX.
+2003-01-29 Joel Sherrill <joel@OARcorp.com>
-2002-04-16 Richard Henderson <rth@redhat.com>
+ PR bootstrap/9293
+ * config/m68k/t-crtstuff: Replace spaces with tabs, add
+ $(MULTILIB_CFLAGS) as compiler option and multilib crtbegin/end.o.
- * config.gcc (sparcv9-solaris): Configure for 64-bit default.
- Adjust tm_file order to get TARGET_DEFAULT set properly.
- (sparc-solaris): Configure 2.[78] for 64-bit multilibs.
- * doc/install.texi (sparc-solaris): Update.
+2003-01-29 Joel Sherrill <joel@OARcorp.com>
-2002-04-16 Hartmut Penner <hpenner@de.ibm.com>
+ PR bootstrap/9292
+ * config.gcc (hppa1.1-rtems): Did not include t-rtems nor enable
+ RTEMS threads.
+ * config/pa/rtems.h (LIB_SPEC): Use -N when linking.
- PR target/6305
- * config/s390/s390.md (mulsidi3): Set both subregs of the
- multiword register.
+2003-01-25 Andrew Haley <aph@redhat.com>
-2002-04-16 Aldy Hernandez <aldyh@redhat.com>
+ * tree-inline.c (walk_tree): Add CHAR_TYPE.
- * config/rs6000/altivec.h (vec_addc): Type check.
+2003-01-28 Christian Cornelssen <ccorn@cs.tu-berlin.de>
-2002-04-16 Jakub Jelinek <jakub@redhat.com>
+ * doc/install.texi: Add documentation for installation into
+ tooldirs and with DESTDIR.
- PR middle-end/6279
- * expr.c (store_expr): Don't copy if DECL_RTL (exp) == target.
+2003-01-28 Andreas Schwab <schwab@suse.de>
- * expr.c (safe_from_p): Cleanup: use DECL_RTL_IF_SET.
+ * config/m68k/m68k.md (tablejump+2): Don't sign extend an address
+ register.
+ * config/m68k/apollo68.h (ASM_RETURN_CASE_JUMP): Likewise.
+ * config/m68k/coff.h (ASM_RETURN_CASE_JUMP): Likewise.
+ * config/m68k/linux.h (ASM_RETURN_CASE_JUMP): Likewise.
+ * config/m68k/m68kelf.h (ASM_RETURN_CASE_JUMP): Likewise.
+ * config/m68k/mot3300.h (ASM_RETURN_CASE_JUMP): Likewise.
+ * config/m68k/netbsd-elf.h (ASM_RETURN_CASE_JUMP): Likewise.
+ * config/m68k/pbb.h (ASM_RETURN_CASE_JUMP): Likewise.
+
+2003-01-28 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.md (movti_string): Remove clobber.
+ * config/rs6000/rs6000.c (rs6000_emit_move, TImode): Explicitly
+ generate PARALLEL with clobber for TARGET_POWER.
+
+2003-01-28 Richard Henderson <rth@redhat.com>
+
+ * ifcvt.c (noce_process_if_block): Re-add check vs X being changed
+ in no-else-block case. Add commentary.
+
+2003-01-28 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/mips/mips.h (UNITS_PER_HWFPVALUE): Renamed from...
+ (UNITS_PER_FPVALUE): Defined as the width of a long double, or
+ zero if no hardware floating point.
+ (LONG_DUBLE_TYPE_SIZE): Set to 128 on N32 and N64.
+ (MAX_FIXED_MODE_SIZE): Define to LONG_DOUBLE_TYPE_SIZE.
+ (LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Define.
+ (BIGGEST_ALIGNMENT): Same as LONG_DOUBLE_TYPE_SIZE.
+ (FUNCTION_VALUE_REGNO_P): Set for FP_RETURN+2 on N32 and N64.
+ * config/mips/iris6.h (MIPS_TFMODE_FORMAT): Define.
+ * config/mips/mips.c (override_options): Use it.
+ (mips_arg_info): Pass TFmode values in even FP registers on N32
+ and N64.
+ (mips_setup_incoming_varargs): Use UNITS_PER_HWFPVALUE.
+ (mips_va_start): Adjust alignment of ARG_POINTER_REGNUM.
+ (mips_va_arg): Use UNITS_PER_HWFPVALUE. Impose additional
+ even-register-like alignment to 128-bit arguments.
+ (save_restore_insns): Use UNITS_PER_HWFPVALUE.
+ (mips_function_value): Likewise. Return TFmode in $f0 and $f2
+ on N32 or N64.
+ * config/mips/_tilib.c (__negti2, __ashlti3, __lshrti3): New.
+ * config/mips/t-iris6 (LIB2FUNCS_EXTRA): Add _tilib.c.
+ (TPBIT): Set to tp-bit.c.
+ (tp-bit.c): Create out of fp-bit.c.
-2002-04-15 Richard Henderson <rth@redhat.com>
+2003-01-27 Gabriel Dos_Reis <gdosreis@sophia.inria.fr>
- * config/mips/abi64.h (SUBTARGET_CONDITIONAL_REGISTER_USAGE): Set
- call_really_used_regs too.
+ * c-parse.in: Remove '%expect 32' directive when in objc mode.
-2002-04-15 David S. Miller <davem@redhat.com>
+2003-01-27 Josef Zlomek <zlomekj@suse.cz>
- * rtlanal.c (note_stores): Don't present PARALLEL SET_DESTs
- as being CLOBBERed.
+ * gcse.c (constprop_register): Check NEXT_INSN (insn) != NULL.
-2002-04-16 Jakub Jelinek <jakub@redhat.com>
+2003-01-27 Richard Earnshaw <rearnsha@arm.com>
- PR c/6290
- * config/rs6000/rs6000.c (easy_vector_constant): Return 1 if the
- CONST_VECTOR is { 0, ... 0 }.
+ PR optimization/9090
+ * function.c (purge_addressof_1): After pushing an addressed register
+ onto the stack, simplify the result.
-2002-04-15 Loren J. Rittle <ljrittle@acm.org>
+2003-01-27 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
- * doc/install.texi (Installing GCC: Configuration): Clarify
- the only supported ways to configure gcc.
+ * doc/extend.texi: Fix typo.
-2002-04-15 Richard Henderson <rth@redhat.com>
+2003-01-27 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
- * config/alpha/linux.h, config/arm/linux-elf.h, config/i370/linux.h,
- config/i386/linux-aout.h, config/i386/linux-oldld.h,
- config/i386/linux.h, config/i386/linux64.h, config/ia64/linux.h,
- config/m68k/linux-aout.h, config/m68k/linux.h, config/mips/linux.h,
- config/pa/pa-linux.h, config/pj/linux.h, config/s390/linux.h,
- config/sh/linux.h, config/sparc/linux-aout.h, config/sparc/linux.h,
- config/sparc/linux64.h, config/xtensa/linux.h (CPP_PREDEFINES):
- Define __gnu_linux__, not gnu_linux.
- * config/rs6000/sysv4.h (CPP_OS_GNU_SPEC): Likewise for gnu_hurd.
+ * doc/cppopts.texi: Fix typo.
+ * doc/objc.texi: Likewise.
+ * doc/passes.texi: Likewise.
-2002-04-15 Mark Mitchell <mark@codesourcery.com>
+2003-01-27 Alexandre Oliva <aoliva@redhat.com>
- Remove Chill front end.
- * gcc.c (default_compilers): Remove Chill entries.
- * ch: Remove directory.
- * doc/frontends.texi: Remove information about Chill.
- * doc/sourcebuild.texi: Likewise.
- * doc/standards.texi: Likewise.
+ * real.c (ibm_extended_format): Add 53 to minimum exponent.
+ (encode_ibm_extended): Adjust.
-2002-04-15 Douglas B Rupp <rupp@gnat.com>
+2003-01-26 Kazu Hirata <kazu@cs.umass.edu>
- * config/alpha/vms.h (INCLUDE_DEFAULTS): Add /gnu/lib/gcc-lib/include.
- (LONGLONG_STANDALONE): Define.
+ * doc/gccint.texi: Update the copyright.
-2002-04-15 David S. Miller <davem@redhat.com>
+2003-01-26 Kazu Hirata <kazu@cs.umass.edu>
- * config/sparc/sparc.c (sparc_emit_float_lib_cmp):
- Call emit_library_call with LCT_NORMAL.
- (sparc_initialize_trampoline): Use LCT_foo instead of
- magic constant in emit_library_call invocations.
- (sparc64_initialize_trampoline): Likewise.
- (sparc_profile_hook): Likewise.
- * config/sparc/sparc.md: Likewise.
+ * doc/cpp.texi: Fix typos.
+ * doc/extend.texi: Likewise.
+ * doc/gty.texi: Likewise.
+ * doc/install.texi: Likewise.
+ * doc/passes.texi: Likewise.
+ * doc/rtl.texi: Likewise.
- * config/sparc/sparc.c (sparc_extra_constraint_check):
- Fix type of argument 'c'.
- * config/sparc/sparc-protos.h (sparc_extra_constraint_check):
- Likewise.
+2003-01-26 Christian Cornelssen <ccorn@cs.tu-berlin.de>
+
+ * Makefile.in (ORDINARY_FLAGS_TO_PASS): Also pass DESTDIR.
+ (install-cpp, installdirs, install-common)
+ (install-driver, install-info, install-man)
+ (install-headers, install-include-dir, install-headers-tar)
+ (install-headers-cpio, install-headers-cp, install-mkheaders)
+ (install-collect2, uninstall): Prepend $(DESTDIR) to
+ destination paths in all (un)installation commands.
+ (install-driver): Rewrite $(LN) commands to support DESTDIR
+ with "ln" as well as with "ln -s".
+ (installdirs): Simply use mkinstalldirs.
+ (install-libgcc, install-multilib): Also pass DESTDIR.
+ * mklibgcc.in: Prepend $(DESTDIR) to $(libsubdir) in the
+ installation destination variable ldir.
+ * config/alpha/t-osf4 (SHLIB_INSTALL): Prepend $$(DESTDIR)
+ to $$(slibdir) in the installation commands.
+ * config/arm/t-netbsd (SHLIB_INSTALL): Likewise.
+ * config/ia64/t-hpux (SHLIB_INSTALL): Likewise.
+ * config/mips/t-iris5-6 (SHLIB_INSTALL): Likewise.
+ * config/pa/t-hpux-shlib (SHLIB_INSTALL): Likewise.
+ * config/rs6000/t-aix43 (SHLIB_INSTALL): Likewise.
+ * config/rs6000/t-aix52 (SHLIB_INSTALL): Likewise.
+ * config/t-slibgcc-elf-ver (SHLIB_INSTALL): Likewise.
+ * config/t-slibgcc-sld (SHLIB_INSTALL): Likewise.
+ * config/arc/t-arc (install-multilib-arc): Prepend $(DESTDIR) to
+ $(libsubdir) in the installation commands.
-2002-04-14 Andreas Schwab <schwab@suse.de>
+2003-01-26 Alexandre Oliva <aoliva@redhat.com>
+
+ * fp-bit.h: Define macros for TFmode floating-point constants
+ in IBM-extended TFmode types.
+ (TMODES): Define if __LDBL_MANT_DIG__ has the newly-supported
+ widths.
+ * config/fp-bit.c (pack_d, unpack_d): Support IBM-extended
+ TFmode type.
+
+ * config/fp-bit.h: Define macros for TFmode floating-point
+ constants in IEEE quad TFmode type. Declare functions according
+ to L_ macros.
+ (TMODES): Define if __LDBL_MANT_DIG__ is 113.
+ (TFtype, TItype, UTItype): Define if TMODES is defined.
+ (MAX_UDI_INT, MAX_DI_INT, BITS_PER_DI): Likewise.
+ (F_T_BITOFF, D_T_BITOFF): Define.
+ (IMPLICIT_1, IMPLICIT_2): Cast constants to types that are
+ guaranteed to be wide enough.
+ * config/fp-bit.c: Check for L_ macros for tf functions.
+ (__thenan_tf): New.
+ (nan): Adjust.
+ (pack_d, unpack_d): Support IEEE 854 quad type.
+ (_fpmul_parts): Support TFmode. Compute exponent adjustment
+ from FRAC_NBITS, FRAC_BITS and NGARDS.
+ (usi_to_float): Cast constants to be shifted to fractype
+ instead of assuming long long is wide enough.
+ (sf_to_tf, df_to_tf, __make_tp, tf_to_df, tf_to_sf): New.
+
+ * Makefile.in (FPBIT_FUNCS): Added _sf_to_tf.
+ (DBBIT_FUNCS): Added _df_to_tf.
+ (TPBIT_FUNCS): New.
+ (libgcc.mk): Pass TPBIT and TPBIT_FUNCS down.
+ (LIBGCC_DEPS): Added TPBIT.
+ * mklibgcc.in: Support TPBIT and TPBIT_FUNCS.
+
+ * optabs.c (expand_binop) <add, sub>: Return xtarget if we haven't
+ been able to move the result to target.
+
+ * expr.c (emit_group_store): Initialize dst with CONST0_RTX
+ for the appropriate mode.
+
+ * calls.c (emit_library_call_value_1): Handle return values
+ in a PARALLEL.
+
+ * rtl.c (get_mode_alignment): Moved to...
+ * stor-layout.c: ... here.
+
+ * print-rtl.c (print_rtx): Don't print MEM details in
+ GENERATOR_FILEs.
+
+2003-01-26 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * df.c (df_uses_record): Handle CC0.
- * config/ia64/linux.h (CPP_PREDEFINES): Fix missing backslash.
+2003-01-25 Jan Hubicka <jh@suse.cz>
+ Eric Botcazou <ebotcazou@libertysurf.fr>
+ PR opt/8492
+ * gcse.c (one_cprop_pass): Delete unreachable blocks.
-2002-04-14 Jeroen Dobbelaere <jeroen.dobbelaere@acunia.com>
+2003-01-25 Ulrich Weigand <uweigand@de.ibm.com>
- * config/arm/linux-elf.h (CPLUSPLUS_CPP_SPEC): Define.
+ * reload.c (maybe_memory_address_p): New function.
+ (find_reloads_address): Use it instead of memory_address_p.
-2002-04-13 Mark Mitchell <mark@codesourcery.com>
+2003-01-25 Kaz Kojima <kkojima@gcc.gnu.org>
- * config/alpha/linux.h (CPP_PREDEFINES): Fix typo.
- * config/i386/gnu.h (CPP_PREDEFINES): Define __gnu_hurd__,
- not gnu_hurd.
+ * final.c (shorten_branches): Align the address of code label
+ when computing initial lengths and addresses.
-2002-04-13 Hans-Peter Nilsson <hp@axis.com>
+2003-01-25 Richard Henderson <rth@redhat.com>
- * config/cris/linux.h (CRIS_CPP_SUBTARGET_SPEC): Fix typo.
+ 2002-02-19 Robert Lipe <robertlipe@usa.net>
+ * config/i386/t-sco5gas: (CRTSTUFF_T_CFLAGS_S): Delete -mcoff.
-2002-04-13 Joel Sherrill <joel@OARcorp.com>
+2003-01-23 Andreas Schwab <schwab@suse.de>
- * config/sparc/t-elf: Enable v8 multilibs. Impacts
- sparc-elf and sparc-rtems targets.
+ * config/ia64/crtend.asm [HAVE_INITFINI_ARRAY]: Make
+ __do_global_ctors_aux hidden global and don't put it in
+ .init_array.
+ * config/ia64/crtbegin.asm [HAVE_INITFINI_ARRAY]: Put it here
+ instead so that it comes first.
-2002-04-13 Mark Mitchell <mark@codesourcery.com>
+2003-01-25 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * alpha/linux.h: Define __gnu_linux__ wherever __linux__ is
- defined, and __gnu_hurd__ wherever __GNU__ is defined.
- * arm/linux-elf.h: Likewise.
- * cris/aout.h: Likewise.
- * cris/linux.h: Likewise.
- * i370/linux.h: Likewise.
- * i386/gnu.h: Likewise.
- * i386/linux-aout.h: Likewise.
- * i386/linux-oldld.h: Likewise.
- * i386/linux.h: Likewise.
- * i386/linux64.h: Likewise.
- * ia64/linux.h: Likewise.
- * m68k/linux-aout.h: Likewise.
- * m68k/linux.h: Likewise.
- * mips/linux.h: Likewise.
- * pa/pa-linux.h: Likewise.
- * pj/linux.h: Likewise.
- * rs6000/sysv4.h: Likewise.
- * s390/linux.h: Likewise.
- * sh/linux.h: Likewise.
- * sparc/linux-aout.h: Likewise.
- * sparc/linux.h: Likewise.
- * sparc/linux64.h: Likewise.
- * xtensa/linux.h: Likewise.
+ * config/c4x/c4x.h (ASM_SPEC): Fix for new gas format.
-2002-04-13 Andreas Schwab <schwab@suse.de>
+2003-01-24 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * config/ia64/ia64.h (CPP_SPEC): Include %(cpp_cpu).
+ * calls.c (fix_unsafe_tree): Prototype.
+ * loop.c (loop_invariant_p): Avoid signed/unsigned warning.
-2002-04-12 Mark Mitchell <mark@codesourcery.com>
+2003-01-24 Richard Henderson <rth@redhat.com>
- Revert these changes:
+ PR optimization/4382
+ * tree-inline.c (find_builtin_longjmp_call_1): New.
+ (find_builtin_longjmp_call): New.
+ (inlinable_function_p): Use it.
- 2002-04-06 Mark Mitchell <mark@codesourcery.com>
+2003-01-24 Ulrich Weigand <uweigand@de.ibm.com>
- PR c++/5571
- * stor-layout.c (layout_decl): Reset the RTL for the decl.
+ * configure.in (HAVE_AS_TLS): Add s390-*-* and s390x-*-* cases.
+ * configure: Regenerate.
+
+ * config/s390/s390-protos.h (tls_symbolic_operand): Add prototype.
+ (tls_symbolic_reference_mentioned_p): Add prototype.
+ (s390_tls_get_offset): Add prototype.
+ (emit_pic_move): Remove prototype, replace by ...
+ (emit_symbolic_move): .. this new prototype.
+
+ * config/s390/s390.c (TARGET_HAVE_TLS): Conditionally define.
+ (tls_model_chars): New global variable.
+ (s390_encode_section_info): Encode TLS model.
+ Use targetm.binds_local_p to check for local symbols.
+ (s390_strip_name_encoding): New function.
+ (TARGET_STRIP_NAME_ENCODING): Define.
+
+ (get_thread_pointer): New function.
+ (legitimize_tls_address): New function.
+ (legitimize_address): Call it.
+ (emit_pic_move): Remove, replace by ...
+ (emit_symbolic_move): ... this new function.
+
+ (larl_operand): Handle TLS operands.
+ (legitimate_constant_p): Likewise.
+ (s390_decompose_address): Likewise.
+ (s390_cannot_force_const_mem): New function.
+ (TARGET_CANNOT_FORCE_CONST_MEM): Define.
+
+ (s390_output_symbolic_const): Handle TLS unspecs.
+ (print_operand): New code 'J'.
+ (machine_function): Add struct member 'some_ld_name'.
+ (get_some_local_dynamic_name, get_some_local_dynamic_name_1): New.
+
+ (enum s390_builtin): New type.
+ (code_for_builtin_64, code_for_builtin_31): New global variables.
+ (s390_init_builtins, s390_expand_builtin): New functions.
+ (TARGET_INIT_BUILTINS, TARGET_EXPAND_BUILTIN): Define.
+
+ * config/s390/s390.h (TLS_SYMBOLIC_CONST): New macro.
+ (ASM_OUTPUT_LABELREF): Define.
+ (ASM_OUTPUT_SPECIAL_POOL_ENTRY): Handle TLS constants.
+
+ * config/s390/s390.md: Define TLS UNSPEC constants.
+ ("movdi", "movsi"): Handle TLS operands.
+ ("get_tp_64", "get_tp_31", "set_tp_64", "set_tp_31"): New insns.
+ ("*tls_load_64", "*tls_load_31"): New insns.
+ ("call_value_tls", "call_value_tls_exp"): New expanders.
+ ("brasl_tls", "bras_tls", "basr_tls_64", "basr_tls_31",
+ "bas_tls_64", "bas_tls_31"): New insns.
- 2002-03-15 Mark Mitchell <mark@codesourcery.com>
+2003-01-24 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
- * expr.c (expand_expr): Tidy.
+ * doc/passes.texi: Fix typo.
+2003-02-01 Jan Hubicka <jh@suse.cz>
+
+ * loop.c (emit_prefetch_instructions): Do conversion at right place in
+ RTL chain.
+
+ * combine.c (simplify_set): Reverse order of ragumetns to
+ REG_CANNOT_CHANGE_MODE_P
+ * df.c (df_def_record_1): Likewise.
+ * recog.c (register_operand): Likewise.
+ * simplify-rtx.c (simplify_subreg): Likewise.
+ * hard-reg-set.h (REG_CANNOT_CHANGE_MODE_P): Update use of
+ CANNOT_CHANGE_MODE_CLASS.
+ * regclass.c (cannot_change_mode_set_regs, invalid_mode_change_p):
+ Likewise.
+ * reload.c (push_reload): Likewise.
+ * alpha.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * ia64.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * mips.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * mips-protos.h (mips_cannot_change_mode_class): Update prototype.
+ * mips.c (mips_cannot_change_mode_class): Update.
+ * pa64-regs.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * rs6000.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * s390.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * sh.h (CANNOT_CHANGE_MODE_CLASS): Update definition.
+ * sh-protos.h (sh_cannot_change_mode_class): Update prototype.
+ * sh.c (sh_cannot_change_mode_class): Update.
+ * i386.h (CANNOT_CHANGE_MODE_CLASS): New.
+ * tm.texi (CANNOT_CHANGE_MODE_CLASS): Update documentation.
+
+2003-01-24 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * timevar.def (TV_NAME_LOOKUP, TV_OVERLOAD,
+ TV_TEMPLATE_INSTANTIATION): New timevar_id eumerations.
+ * timevar.h (POP_TIMEVAR_AND_RETURN): New macro.
+ * timevar.c (timevar_pop): Be verbose when aborting. Include
+ "toplev.h".
-2002-04-12 Richard Henderson <rth@redhat.com>
+2003-01-24 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
+
+ * doc/bugreport.texi: Use @command instead of @code for commands.
+ * doc/collect2.texi: Likewise.
+ * doc/headerdirs.texi: Likewise.
+ * doc/invoke.texi: Likewise.
+ * doc/standards.texi: Likewise.
+ * doc/tm.texi: Likewise.
+ * doc/trouble.texi: Likewise.
+
+2003-01-23 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ PR java/6748
+ * config/rs6000/linux.h (MD_FALLBACK_FRAME_STATE_FOR): Don't destroy
+ regs->nip. Fix rt_sigreturn frame layout. Add support for newer
+ kernels.
- * config.gcc (sparcv9-*-solaris2): Default to 32-bit code.
- (sparc*-*-solaris): Clean up header files.
- * configure.in (AS_SPARC64_FLAG): Error out if can't find it
- and plan on generating 64-bit code.
- * toplev.c (decode_g_option): Remove LINKER_DOES_NOT_WORK_WITH_DWARF2.
- * config/sparc/sol2-64.h: Delete and reuse for default 64-bit code.
- * config/sparc/sol2-sld-64.h: Rename ...
- * config/sparc/sol2-bi.h: ... here. Remove the bits that checked
- for AS_SPARC64_FLAG not defined.
- * config/sparc/sol2-gld-bi.h: New.
- * config/sparc/sol2-sld.h: Remove.
- * config/sparc/sol26-sld.h: New.
- * config/sparc/sol2.h: Tidy comments.
- * doc/install.texi: Document sparc-solaris configury changes.
+2003-01-23 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
-2002-04-12 Richard Henderson <rth@redhat.com>
+ PR other/7341
+ * invoke.texi (ftest-coverage): Fix broken cross-reference.
+ Change @code to @command for gcov command.
- * recog.c (offsettable_address_p): Match the logic in adjust_address.
+ * gcc.texi: Adjust title of gcov section.
+ Adjust copyright.
+ * gcov.texi: Likewise.
- * config/sparc/sparc.h (LEGITIMIZE_RELOAD_ADDRESS): Handle TFmode
- in 64-bit mode only. Use only for 32-bit or MEDLOW.
+2003-01-23 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
-2002-04-12 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+ PR other/7448
+ * doc/passes.texi (fssa-ccp): Remove misplaced line.
- * config/alpha/osf.h (LINK_SPEC): Pass -S to silence ld warnings.
+2003-01-22 Ulrich Weigand <uweigand@de.ibm.com>
-Fri Apr 12 15:42:59 2002 Jeffrey A Law (law@redhat.com)
+ * config/s390/s390.h (HARD_REGNO_MODE_OK): Fix warning regression
+ introduced by last change.
- * pa.c (pa_can_combine_p): Call extract_insn before calling
- constrain_operands.
+2003-01-22 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-04-12 Douglas B Rupp <rupp@gnat.com>
+ * configure.in: Make --disable-checking the default.
+ * configure: Regenerate.
- * hwint.h (HAVE___INT64): Correct spelling.
+2003-01-22 Ulrich Weigand <uweigand@de.ibm.com>
- * config/i386/i386-interix.h (EH_FRAME_IN_DATA_SECTION): Define.
- (TARGET_ASM_NAMED_SECTION, RETURN_IN_MEMORY) Define.
- (DEFAULT_PCC_STRUCT_RETURN): Define as 0.
- (CPP_PREDEFINES): Handle __declspec.
- * config/i386/t-interix (USER_H): Remove.
+ * config/s390/s390-protos.h (preferred_la_operand_p):
+ Remove second parameter.
+ * config/s390/s390.c (preferred_la_operand_p): Likewise.
+ * config/s390/s390.h (FRAME_REGNO_P, FRAME_REG_P): New macros.
+ (HARD_REGNO_MODE_OK): Use FRAME_REGNO_P.
+ * config/s390/s390.md ("*la_cc_64", "*la_cc_31", splitters): Remove.
+ Add peepholes to transform ADD to LOAD ADDRESS.
-2002-04-12 DJ Delorie <dj@redhat.com>
+2003-01-20 Jan Hubicka <jh@suse.cz>
- * integrate.c (compare_blocks): Make comparisons safe for when
- sizeof(int) < sizeof(char *).
- (find_block): Likewise.
+ * i386.md (SSE cmov splitter): Handle memory operand in operand 5.
-2002-04-12 Andreas Schwab <schwab@suse.de>
+2003-01-21 Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de>
- * config/ia64/ia64.h (ASM_SPEC): Moved from here ...
- * config/ia64/sysv4.h (ASM_SPEC): ... to here, so that it
- overrides the definition in config/svr4.h.
+ PR opt/7507
+ * calls.c (fix_unsafe_tree): Split out from ...
+ (expand_call): ... here. Use it on the function address too.
-2002-04-12 Eric Norum <eric.norum@usask.ca>
+2003-01-20 Richard Henderson <rth@redhat.com>
- * config/rtems.h, config/a29k/rtems.h, config/arm/rtems-elf.h,
- config/c4x/rtems.h, config/h8300/rtems.h, config/i386/rtems.h,
- config/i386/rtemself.h, config/i960/rtems.h, config/m68k/rtems.h,
- config/m68k/rtemself.h, config/mips/rtems.h, config/mips/rtems64.h,
- config/pa/rtems.h, config/rs6000/rtems.h, config/sh/rtems.h,
- config/sh/rtemself.h, config/sparc/rtems.h, config/sparc/rtemself.h,
- config/v850/rtems.h (*-rtems*): Cleanup pass to move common
- definitions to config/rtems.h and make the targets more similar.
+ PR opt/7154
+ * stmt.c (expand_asm_operands): Validize memory operands.
-Fri Apr 12 08:06:54 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2003-01-20 Richard Henderson <rth@redhat.com>
- * expr.c (expand_assigment): Remove duplicate conversions #ifdef
- POINTERS_EXTEND_UNSIGNED.
- (store_constructor, expand_expr, case COMPONENT_REF): Likewise.
- (store_expr): Use TYPE_MODE (sizetype), not ptr_mode.
+ PR opt/8848
+ * ifcvt.c (noce_process_if_block): Correct arguments to
+ modified_between_p for no-else-block case.
- * emit-rtl.c (widen_memory_access): Don't do anything if MEMOFFSET
- not specified.
+2003-01-20 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
-2002-04-12 Hans-Peter Nilsson <hp@bitrange.com>
+ * ifcvt.c (noce_emit_store_flag): Don't emit store flag if mode of x
+ is not a scalar int mode.
- * function.c (fixup_var_refs_1) <SET, handling VAR in SET_SRC>:
- For paradoxical (subreg VAR), replace VAR, don't try the subreg.
+2003-01-20 Kazu Hirata <kazu@cs.umass.edu>
-2002-04-12 Andreas Schwab <schwab@suse.de>
+ * config/h8300/h8300.c (notice_update_cc): Don't assume that
+ recog_data.operands[0] is always associated with cc0.
- * config/ia64/ia64.h (EXTRA_SPECS): Fix missing backslash.
+2003-01-19 Stephane Carrez <stcarrez@nerim.fr>
-2002-04-12 Richard Henderson <rth@redhat.com>
+ * config/m68hc11/m68hc11.c (stack_push_word, stack_pop_word,
+ z_reg, z_reg_qi): Declare static and GTY().
+ (da_reg): Remove.
+ (create_regs_rtx): Don't create da_reg.
+ ("gt-m68hc11.h"): Include for GTY roots.
+ (m68hc11_autoinc_compatible_p): Remove.
+ (autoinc_mode): Declare prototype.
+ (m68hc11_make_autoinc_notes): Likewise.
+ * config/m68hc11/m68hc11.h (ix_reg, iy_reg, d_reg): Declare extern
+ and GTY() here.
+ (m68hc11_compare_op0, m68hc11_compare_op1): Likewise.
+ (m68hc11_soft_tmp_reg): Likewise.
+ * config/m68hc11/m68hc11-protos.h: Remove above declarations.
- PR bootstrap/4191
- * config/d30v/d30v.h (INIT_SECTION_ASM_OP): Don't undef.
+2003-01-18 Roger Sayle <roger@eyesopen.com>
- * flow.c (mark_used_reg): Manage reg_cond_dead properly for
- modes spanning multiple hard regs.
+ * config/pa/pa.md (muldi3): Avoid invalid sharing of SUBREG RTXs.
- * recog.c (peephole2_optimize): Rebuild jump labels as needed.
+2003-01-10 Geoffrey Keating <geoffk@apple.com>
-2002-04-11 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ * varasm.c (struct constant_descriptor_rtx): Remove unused
+ `label' field.
- * pa.c (output_millicode_call): Check attribute type as well as length
- when length is 28.
+ * ggc-page.c (ggc_collect): Avoid overflow computing
+ min_expand.
-2002-04-11 David O'Brien <obrien@FreeBSD.org>
+2002-12-20 Geoffrey Keating <geoffk@apple.com>
- * config/freebsd.h (NO_IMPLICIT_EXTERN_C, SCCS_DIRECTIVE): Give value.
- (DEFAULT_PCC_STRUCT_RETURN) Do not redefine.
- (USER_LABEL_PREFIX, HANDLE_SYSV_PRAGMA, IDENT_ASM_OP,
- DWARF2_DEBUGGING_INFO, DBX_DEBUGGING_INFO, PREFERRED_DEBUGGING_TYPE):
- elfos.h and dbxelf.h values are fine now.
- * config/i386/freebsd.h, config/alpha/freebsd.h
- (DEFAULT_PCC_STRUCT_RETURN): Define to 0.
+ * integrate.c (output_inline_function): Don't hold private
+ pointers to 'struct function' over GC calls.
-2002-04-11 David O'Brien <obrien@FreeBSD.org>
+2003-01-17 Alexandre Oliva <aoliva@redhat.com>
- * config/ia64/aix.h (CPP_PREDEFINES): Do not define _LP64/__LP64__
- or set Acpu or Amachine. Reformat.
- (ASM_SPEC, DONT_USE_BUILTIN_SETJMP, PROFILE_BEFORE_PROLOGUE): Do not
- define.
- (LINK_SPEC): Do not need to undef.
- * config/ia64/elf.h (ASM_EXTRA_SPEC): Define.
- * config/ia64/freebsd.h (LINK_SPEC): Do not need to undef.
- (ASM_SPEC, DONT_USE_BUILTIN_SETJMP, PROFILE_BEFORE_PROLOGUE): Do not
- define.
- * config/ia64/hpux.h (ASM_EXTRA_SPEC): Define.
- (ASM_SPEC): Do not define, use ASM_EXTRA_SPEC instead.
- (LINK_SPEC): Do not need to undef.
- (DONT_USE_BUILTIN_SETJMP): Do not define.
- * config/ia64/ia64.h (ASM_SPEC, ASM_EXTRA_SPEC): Add.
- (CPP_CPU_SPEC): Define _LP64, set Acpu and Amachine. Remove -Dia64.
- (DONT_USE_BUILTIN_SETJMP, PROFILE_BEFORE_PROLOGUE): Define.
- Remove trailing spaces.
- * config/ia64/linux.h (CPP_PREDEFINES): Do not define _LP64/__LP64__,
- __ELF__, or set Acpu or Amachine. Reformat.
- (ASM_SPEC, DONT_USE_BUILTIN_SETJMP, PROFILE_BEFORE_PROLOGUE): Do not
- define.
+ * config/mips/mips.h: Don't use #elif. Reported by Kaveh
+ R. Ghazi.
-2002-04-11 David O'Brien <obrien@FreeBSD.org>
+2003-01-16 Kaz Kojima <kkojima@gcc.gnu.org>
- * config.gcc (ia64-*-freebsd*): Fix ordering of tm_files to match
- all other *-*-freebsd* targets.
+ * config/sh/sh.c (sh_initialize_trampoline): Emit rotrdi3_mextr
+ instead of rotldi3_mextr.
-2002-04-11 Richard Sandiford <rsandifo@redhat.com>
+2003-01-16 Stephane Carrez <stcarrez@nerim.fr>
- * doc/extend.texi: Remove old claim that typedefs cannot have
- an alignment attribute.
+ * config/m68hc11/m68hc11.c (m68hc11_check_z_replacement): Fix handling
+ 68HC12 pre/post inc/dec side effects.
-2002-04-11 Jakub Jelinek <jakub@redhat.com>
+2003-01-16 Stephane Carrez <stcarrez@nerim.fr>
- PR optimization/6177
- * expr.c (expand_expr) [COMPONENT_REF]: Handle op0 CONCAT if
- bitpos is 0 and bitsize CONCAT size.
+ * config/m68hc11/m68hc11.h (MASK_M6812): Define.
-2002-04-11 Jakub Jelinek <jakub@redhat.com>
+2003-01-16 Stephane Carrez <stcarrez@nerim.fr>
- PR c/6223
- * combine.c (if_then_else_cond): Use trunc_int_for_mode on nz.
+ * config/m68hc11/m68hc11.c (expand_prologue): Use push/pop to
+ allocate 4-bytes of locals on 68HC11.
+ (expand_epilogue): Likewise.
+ (m68hc11_memory_move_cost): Increase cost of HI/QI soft registers.
-2002-04-11 David O'Brien <obrien@FreeBSD.org>
+2003-01-15 John David Anglin <dave@hiauly1.hia.nrc.ca>
- * config/alpha/freebsd.h: Minor reformatting.
- (CPP_SPEC): Define ELF and add cpp_subtarget.
- (ASM_SPEC): No longer needed.
+ * som.h (SUPPORTS_WEAK, SUPPORTS_ONE_ONLY, MAKE_DECL_ONE_ONLY,
+ ASM_WEAKEN_LABEL, GTHREAD_USE_WEAK): Define.
+ * pa.h (TARGET_SOM_SDEF): Define.
+ * pa-hpux11.h (TARGET_SOM_SDEF): Define.
-2002-04-11 Richard Henderson <rth@redhat.com>
+2003-01-15 Stephane Carrez <stcarrez@nerim.fr>
- * config/sparc/sparc.md (movdi_insn_sp32): Add o/J alternative.
- (movdi_insn_sp32_v9): Likewise. Only allow stx with aligned memory.
- (dimode mem/zero splitter): New.
+ * config/m68hc11/m68hc11.h (ASM_SPEC): Handle -m68hcs12; Pass -mshort
+ and -mshort-double to the assembler to specify the ABI.
+ (LINK_SPEC): Likewise.
+ (CPP_SPEC): Pass HCS12 specific define.
+ (MASK_M68S12): New define.
+ (TARGET_M68S12): Likewise.
+ (TARGET_SWITCHES): New options -m68hcs12 and -m68S12.
+ (TARGET_VERSION): Update.
+ * config/m68hc11/m68hc12.h (CPP_SPEC): Pass HCS12 specific define.
+ (LINK_SPEC): Update.
+ (ASM_SPEC): Update.
+ * config/m68hc11/m68hc11.c (m68hc11_asm_file_start): Update.
+ * doc/invoke.texi (M68hc1x Options): Document -m68hcs12.
+
+2003-01-15 John David Anglin <dave.anglin@nrc.gc.ca>
+
+ * gengtype-lex.l (malloc, realloc): Move defines after include of
+ system.h.
-2002-04-11 Hans-Peter Nilsson <hp@axis.com>
+2003-01-15 Stephane Carrez <stcarrez@nerim.fr>
- * config/cris/cris.c (cris_override_options): Tweak error message
- for PIC not implemented.
+ * config/m68hc11/m68hc11.md ("return"): Use emit_jump_insn to emit
+ the return code.
- * config/cris/cris.h: Tweak comments related to parameter-passing.
+2003-01-15 Josef Zlomek <zlomekj@suse.cz>
- * config/cris/t-cris (TARGET_LIBGCC2_CFLAGS): Don't -Dinhibit_libc here.
+ * cfganal.c (set_edge_can_fallthru_flag): Clear the EDGE_CAN_FALLTHRU
+ flag before setting it.
- * config/cris/cris.c (cris_target_asm_function_prologue): Cast
- uses of PIC_OFFSET_TABLE_REGNUM to int to silence warnings.
- (cris_target_asm_function_epilogue): Ditto.
- (cris_initial_frame_pointer_offset): Ditto.
- (cris_simple_epilogue): Ditto.
- (cris_expand_builtin_va_arg): Variable-size types come in
- by-reference.
+2003-01-15 Josef Zlomek <zlomekj@suse.cz>
-2002-04-10 Richard Henderson <rth@redhat.com>
+ Segher Boessenkool <segher@koffie.nl>
- * except.c (add_ehl_entry): Allow duplicates after landing pad
- creation.
+ * predict.c (real_inv_br_prob_base): New variable.
+ (propagate_freq): Use multiply by reciprocal instead of
+ division. Don't divide by 1.0 at all.
+ (estimate_bb_frequencies): Similar.
-2002-04-10 David Edelsohn <edelsohn@gnu.org>
+2003-01-15 Alexandre Oliva <aoliva@redhat.com>
- * config/rs6000/t-aix43 (SHLIB_NM_FLAGS): Add -X32_64.
+ * configure.in (libgcc_visibility): Force disabled on IRIX 6 too.
+ * configure: Rebuilt.
-2002-04-10 Ulrich Weigand <uweigand@de.ibm.com>
+ * config/mips/mips.h (CRT_CALL_STATIC_FUNCTION): Define so as
+ to set $gp before the call.
- * reload1.c (choose_reload_regs): HARD_FRAME_POINTER_REGNUM
- is only used as frame pointer when frame_pointer_needed is true.
+2003-01-10 Andrew Haley <aph@redhat.com>
-2002-04-10 Richard Earnshaw <rearnsha@arm.com>
+ * config/i386/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Rename
+ registers to be in correct order. Add rip.
- PR target/817
- * arm.md (arm_movdi): Adjust neg_pool_range attribute to allow
- for the fact that the pool entry uses two words.
- (movdf_hard_insn): Similarly. Also, ADR instruction can span
- 1k bytes.
- (movdf_soft_insn): Similarly.
- (movxf_hard_insn): Adjust neg_pool_range attribute to allow
- for the fact that the pool entry uses three words.
+2003-01-14 Denis Chertykov <denisc@overta.ru>
-2002-04-10 Richard Henderson <rth@redhat.com>
+ * config/ip2k/ip2k.h (VALID_MACHINE_DECL_ATTRIBUTE): Remove.
+ (VALID_MACHINE_TYPE_ATTRIBUTE): Remove.
- * expr.c (expand_expr) [INTEGER_CST]: Don't force into registers
- if EXPAND_INITIALIZER.
+ * config/ip2k/ip2k.c (ip2k_attribute_table): New table of
+ attributes.
+ (TARGET_ATTRIBUTE_TABLE): New macro.
+ (valid_machine_type_attribute): Remove.
+ (valid_machine_decl_attribute): Remove.
+ (ip2k_handle_progmem_attribute): New function.
+ (ip2k_handle_fndecl_attribute): New function.
-2002-04-10 Alan Modra <amodra@bigpond.net.au>
+2003-01-14 Eric Botcazou <ebotcazou@libertysurf.fr>
- PR optimization/6233
- * rtlanal.c (pure_call_p): New function.
- * rtl.h (pure_call_p): Declare.
- * loop.c (prescan_loop): Use it to set has_nonconst_call.
- * gcse.c (store_killed_in_insn): Use pure_call_p here too.
+ PR target/8870, PR target/9195
-2002-04-09 Richard Henderson <rth@redhat.com>
+ Backport from mainline:
- * config/alpha/alpha.md (movdi_er_maybe_g): New.
- * config/alpha/alpha.c (alpha_expand_mov): Use it.
+ 2003-01-10 Richard Henderson <rth@redhat.com>
-2002-04-09 Richard Henderson <rth@redhat.com>
+ * combine.c (make_compound_operation): Use SCALAR_INT_MODE_P,
+ not INTEGRAL_MODE_P when widening extensions.
- PR c/5078
- * expr.c (expand_expr) [INTEGER_CST]: Force overflows into registers.
+2003-01-13 Alexandre Oliva <aoliva@redhat.com>
-2002-04-09 Andrew MacLeod <amacleod@redhat.com>
+ * aclocal.m4 (gcc_AC_PROG_GNAT): Don't try to prepend
+ ${ac_tool_prefix} to ADAC or CC. Protect them from word
+ splitting.
+ * configure: Rebuilt.
- * expr.c (expand_expr): A RESULT_DECL is part of a call.
+2003-01-12 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-04-09 Richard Henderson <rth@redhat.com>
+ * unwind-dw2-fde.h (last_fde): Mark parameter with __attribute__
+ ((__unused__)).
- * cfg.c (expunge_block): Decrement num_elements here ...
- (expunge_block_nocompact): ... not here.
- * cfgcleanup.c (delete_unreachable_blocks): Set num_elements.
+2003-01-12 Alan Modra <amodra@bigpond.net.au>
-2002-04-09 Richard Henderson <rth@redhat.com>
+ * expr.c (expand_expr <RDIV_EXPR>): Correct recursive call args.
- * basic-block.h (flow_delete_block_noexpunge): Declare.
- (expunge_block_nocompact): Declare.
- * cfg.c (expunge_block_nocompact): Split out from ...
- (expunge_block): ... here.
- * cfgrtl.c (can_delete_label_p): Don't use exception_handler_labels.
- (flow_delete_block_noexpunge): Split out from ...
- (flow_delete_block): ... here.
- * cfgcleanup.c (delete_unreachable_blocks): Compact while
- removing dead blocks.
- * except.c (exception_handler_labels): Remove.
- (exception_handler_label_map): New.
- (struct eh_region): Add aka member.
- (mark_ehl_map_entry, mark_ehl_map, free_region): New.
- (ehl_hash, ehl_eq, ehl_free, add_ehl_entry): New.
- (for_each_eh_label, for_each_eh_label_1): New.
- (init_eh): Register exception_handler_label_map.
- (free_eh_status): Use free_region.
- (find_exception_handler_labels): Use the map, not the list.
- (remove_exception_handler_label): Likewise.
- (maybe_remove_eh_handler): Likewise.
- (remove_eh_handler): Use the region aka bitmap.
- * except.h (exception_handler_labels): Remove.
- (for_each_eh_label): Declare.
- * jump.c (rebuild_jump_labels): Don't check exception_handler_labels.
- * loop.c (invalidate_loops_containing_label): New.
- (find_and_verify_loops): Use it. Use for_each_eh_label.
- * sched-rgn.c (is_cfg_nonregular): Use
- current_function_has_exception_handlers.
+2003-01-11 Jan Hubicka <jh@suse.cz>
-2002-04-08 Richard Henderson <rth@redhat.com>
+ PR target/9068
+ * i386.c (output_fp_compare): Fix typo
- * reorg.c (get_branch_condition): Use reversed_comparison_code.
+2003-01-10 Josef Zlomek <zlomekj@suse.cz>
-2002-04-08 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+ * jump.c (next_nonnote_insn_in_loop): New function.
+ (copy_loop_headers): Use next_nonnote_insn_in_loop instead of
+ next_nonnote_insn.
+ (duplicate_loop_exit_test). Likewise.
- * config/m68hc11/larith.asm (__map_data_section): Fix condition
- and optimize for size.
- (__do_global_ctors): Fix pointer comparison.
- (__do_global_dtors): Likewise.
+2003-01-08 Jan Hubicka <jh@suse.cz>
-2002-04-09 David S. Miller <davem@redhat.com>
+ PR target/8213
+ * i386.c (ix86_expand_int_movcc): Fix RTL sharing problem.
- * config/sparc/sparc.c (sparc_extra_constraint_check): New
- function, implementing EXTRA_CONSTRAINTS. For memory constraints,
- allow reloading pseudos.
- * config/sparc/sparc.h (EXTRA_CONSTRAINTS): Use it.
- * config/sparc/sparc-protos.h: Declare it.
+2003-01-09 Kazu Hirata <kazu@cs.umass.edu>
- * config/sparc/sparc.c (const64_is_2insns): Kill signed vs.
- unsigned comparison warning.
- (output_restore_regs): Mark leaf_function as unused.
+ * config/h8300/h8300.md (*extzv_1_r_h8300): Correct the insn
+ length.
+ (*extzv_1_r_h8300hs): Likewise.
+ (*extzv_1_r_inv_h8300): Likewise.
+ (*extzv_1_r_inv_h8300hs): Likewise.
-Tue Apr 9 09:35:45 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2003-01-09 Josef Zlomek <zlomj9am@artax.karlin.mff.cuni.cz>
- * expr.c (is_aligning_offset): New function.
- (expand_expr, case COMPONENT_EXPR): Call it.
+ * Makefile.in (optabs.o): Add dependency on basic-block.h.
+ * basic-block.h (control_flow_insn_p): Fuction was exported.
+ * cfgbuild.c (control_flow_insn_p): Fuction was made non-static.
+ * optabs.c (emit_libcall_block): Emit REG_LIBCALL and REG_RETVAL
+ notes only when the region is contained in a single basic block.
-2002-04-09 Alan Modra <amodra@bigpond.net.au>
+2003-01-09 Josef Zlomek <zlomj9am@artax.karlin.mff.cuni.cz>
- * configure.in (auto-build.h): Use target_alias and build_alias
- when running configure.
- (gcc_cv_as): Use $target_alias in directory searchs rather than
- $target. Heed program_prefix and program_transform_name. Search
- for gas in cross-compiler case too. "test -x" rather than "test -f".
- (gcc_cv_ld): Likewise.
- (gcc_cv_nm): Set for cross compilers too. Heed program_prefix and
- program_transform_name.
- (gcc_cv_objdump): Likewise.
- * configure: Regenerate.
+ * Makefile.in (PARTITION_H): New.
+ (BASIC_BLOCK_H): Added hard-reg-set.h and $(PARTITION_H).
+ * basic-block.h: Include hard-reg-set.h.
-2002-04-08 Hans-Peter Nilsson <hp@bitrange.com>
+2003-01-09 Eric Botcazou <ebotcazou@libertysurf.fr>
- * config/mmix/t-mmix (TARGET_LIBGCC2_CFLAGS): Don't -Dinhibit_libc
- here.
+ PR inline-asm/8832
+ * tree.h (expand_asm): New prototype.
+ * stmt.c (expand_asm): Set the MEM_VOLATILE_P flag if instructed
+ to do so.
+ * c-semantics (genrtl_asm_stmt): Pass the RID_VOLATILE qualifier
+ down to expand_asm.
+ * c-typeck.c (simple_asm_stmt): Set the RID_VOLATILE qualifier.
+ * rtlanal.c (volatile_insn_p) [ASM_INPUT]: Test the MEM_VOLATILE_P flag.
+ (volatile_refs_p) [ASM_INPUT]: Likewise.
+ (side_effects_p) [ASM_INPUT]: Likewise.
- * config/mmix/mmix.h (INITIAL_ELIMINATION_OFFSET): Remove spurious
- semicolon.
+2003-01-09 Eric Botcazou <ebotcazou@libertysurf.fr>
- * config/mmix/mmix.c (mmix_expand_builtin_va_arg): Variable-size
- types come in by-reference. Fix typo in comment.
+ PR c/8032
+ * c-typeck.c (process_init_element) [RECORD_TYPE]: For
+ an empty element, do not advance the pointer to unfilled
+ fields if there are pending initializers.
-2002-04-08 Richard Henderson <rth@redhat.com>
+2003-01-09 Kaz Kojima <kkojima@gcc.gnu.org>
- PR opt/6007
- * toplev.c (rest_of_compilation): Disable cross-jumping for
- highly connected graphs.
+ * config/sh/sh.h (CASE_VECTOR_MODE): Use SImode for a
+ non-optimizing compile.
+ (ASM_OUTPUT_ADDR_VEC_ELT): Use .long for a non-optimizing
+ compile.
-2002-04-08 David S. Miller <davem@redhat.com>
+2003-01-09 Andreas Jaeger <aj@suse.de>
- PR target/6082
- * config/sparc/freebsd.h (SPARC_DEFAULT_CMODEL): Set to CM_MEDLOW
+ * unwind-dw2-fde.h (last_fde): Revert last patch.
- Make init_priority work on Sparc when using GNU ld.
- * config/sparc/linux.h, config/sparc/linux64.h,
- config/sparc/netbsd-elf.h, config/sparc/freebsd.h
- (CTORS_SECTION_ASM_OP, DTORS_SECTION_ASM_OP): Undefine.
- * config/sparc/sol2-gld.h: New file to do the same.
- * config.gcc (sparc*-*-solaris2*): If gnu_ld=yes add
- sparc/sol2-gld.h to tm_file.
+2003-01-08 Danny Smith <dannysmith@users.sourceforge.net>
- PR optimization/4328
- * config/sparc/sparc.h (EXTRA_CONSTRAINT): Add new constraint 'W'.
- * doc/md.texi: Document it.
- * config/sparc/sparc.md (movdi_insn_sp64_novis,
- movdi_insn_sp64_vis, movdf_insn_sp32, movdf_insn_v9only_novis,
- movdf_insn_v9only_vis, movdf_insn_sp64_novis,
- movdf_insn_sp64_vis): Use it as MEM constraing with 'e' registers.
- * config/sparc/sparc.c (mem_min_alignment): Fix comment.
+ PR optimization/8750
+ * config/i386/i386.c (ix86_expand_prologue): Don't allow
+ scheduling pass to move insns across __alloca call.
-2002-04-08 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+2003-01-08 Jeff Sturm <jsturm@one-point.com>
- * doc/contrib.texi (Contributors): Add John David Anglin and Loren
- J. Rittle (the latter also to Testers). Update David O'Brien's entry.
+ PR target/9210
+ * config/rs6000/rs6000.c (rs6000_elf_encode_section_info):
+ Set SYMBOL_REF_FLAG on local data sym_ref.
-2002-04-07 David S. Miller <davem@redhat.com>
+2003-01-08 Jan Hubicka <jh@suse.cz>
- * config.gcc (sparc64-*-linux*): Add t-crtfm to tmake_file.
+ PR target/8322
+ * i386.c (ix86_init_mmx_sse_builtins): Constify arguments of loads.
+ * xmmintrin.h (_mm_load*_si128. _mm_store*_si128): Add casts.
-2002-04-07 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ PR target/7782
+ * reload1.c (delete_output_reload): Avoid repeated attempts
+ to delete insn.
- PR 5933
- * pa.h (ASM_OUTPUT_MI_THUNK): Use indirect jump to target function when
- generating 32-bit pic code.
+ * cselib.c (cselib_current_insn_in_libcall): New static variable.
+ (new_elt_loc_list, cselib_process_insn, cselib_init): Keep track on whether
+ we are inside libcall.
+ * cselib.h (elt_loc_list): Add in_libcall.
+ * gcse.c (do_local_cprop): Do not copy propagate using insns
+ in libcalls.
-2002-04-07 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+2003-01-07 Janis Johnson <janis187@us.ibm.com>
- * config/rs6000/rs6000.h (RS6000_PIC_OFFSET_TABLE_REGNUM): New.
- (PIC_OFFSET_TABLE_REGNUM): Use it and return INVALID_REGNUM if
- !flag_pic.
- (CONDITIONAL_REGISTER_USAGE): Adjust accordingly.
- * config/rs6000/rs6000.h: Use RS6000_PIC_OFFSET_TABLE_REGNUM instead
- of PIC_OFFSET_TABLE_REGNUM thruout.
- * config/rs6000/rs6000.md: Likewise.
- * config/rs6000/darwin.h: Likewise.
+ PR other/8947
+ * doc/invoke.texi (-malign-double): Explain that the option breaks
+ binary compatibility.
-2002-04-06 John David Anglin <dave@hiauly1.hia.nrc.ca>
+2003-01-07 Richard Henderson <rth@redhat.com>
- * reorg.c (dbr_schedule): Don't reposition prologue and epilogue notes.
+ * alias.c (find_base_value): Only use new_reg_base_value shortcut
+ if the register is set once.
-2002-04-06 Mark Mitchell <mark@codesourcery.com>
+2003-01-07 Sylvain Pion <Sylvain.Pion@mpi-sb.mpg.de>
- PR c++/5571
- * stor-layout.c (layout_decl): Reset the RTL for the decl.
+ * config/i386/i386.c (ix86_init_mmx_sse_builtins):
+ __builtin_ia32_ldmxcsr and __builtin_ia32_stmxcsr are SSE, not MXX.
+ * config/i386/i386.md (ldmxcsr, stmxcsr): SSE, not MMX.
- PR opt/5120
- * sibcall.c (optimize_sibling_and_tail_recursive_call): Clear
- RTX_UNCHANGING_P for the functions arguments when a tail call
- is made.
+2003-01-07 Benjamin Kosnik <bkoz@redhat.com>
+ Sunil Davasam <sunil.k.davasam@intel.com>
-2002-04-06 Jason Merrill <jason@redhat.com>
+ PR libstdc++/9076
+ * unwind-dw2.c (execute_cfa_program): DW_CFA_undefined,
+ DW_CFA_same_value, read next and ignore.
- * toplev.c (flag_no_inline, flag_really_no_inline): Default to 2.
- (parse_options_and_default_flags): Set them appropriately.
- * c-common.c (c_common_post_options): Don't set flag_really_no_inline.
+2003-01-07 Richard Henderson <rth@redhat.com>
-Sat Apr 6 18:26:32 CEST 2002 Jan Hubicka <jh@suse.cz>
+ * cfganal.c (flow_call_edges_add): Don't crash on noreturn call.
- * ifcvt.c (if_convert): Clear aux fields of blocks.
+2003-01-06 Aldy Hernandez <aldyh@redhat.com>
-2002-04-05 David S. Miller <davem@redhat.com>
+ Segher Boessenkool <segher@koffie.nl>
- * config/sparc/freebsd.h (ENDFILE_SPEC): Add crtfastmath bits.
- * config.gcc (sparc64-wrs-vxworks, sparc-*-chorusos,
- sparc-*-rtems*, sparclite-*-elf* sparc86x-*-elf*, sparc64-*-elf*,
- {sparc64,ultrasparc}-*-freebsd*): Add sparc/t-crtfm to tmake_file.
+ * config/rs6000/rs6000.c (rs6000_reg_names): Add missing registers.
+ (alt_reg_names): Ditto, fix formatting.
+ * config/rs6000/rs6000.h (DEBUG_REGISTER_NAMES): Fix formatting.
-2002-04-05 Jan Hubicka <jh@suse.cz>
+2003-01-06 Bruce Korb <bkorb@gnu.org>
- * optabs.c (emit_no_conflict_block, emit_libcall_block): Avoid nesting
- of libcall regions.
+ * fixinc/fixfixes.c(wrap_fix): the wrapper guard must be a function
+ of *both* the file name and the fix name.
-2002-04-05 David S. Miller <davem@redhat.com>
+2003-01-06 Richard Henderson <rth@redhat.com>
- * config/sparc/sparc.c (sparc_nonflat_function_epilogue): If we
- are not going to emit return instructions, emit at least a nop
- for the sake of sane backtraces.
+ * config/alpha/alpha.c (alpha_encode_section_info): Adjust symbol_str
+ properly when changing "local-ness".
+ * config/alpha/alpha.md (movdi_er_high_g): Allow all symbols.
-2002-04-05 Jakub Jelinek <jakub@redhat.com>
+2003-01-05 Andreas Jaeger <aj@suse.de>
- * mklibgcc.in: Use separate libgcc.map for each multilib.
- * Makefile.in (distclean): Don't remove libgcc.map here.
+ * unwind-dw2-fde.h (last_fde): Add unused attribute for obj.
-2002-04-05 Jakub Jelinek <jakub@redhat.com>
+2003-01-05 John David Anglin <dave@hiauly1.hia.nrc.ca>
- * Makefile.in (s-mlib): Handle --disable-multilib by separate
- genmultilib invocation.
+ * pa64-hpux.h (JCR_SECTION_NAME): Define.
+ (PA_INIT_FRAME_DUMMY_ASM_OP): Check EH_FRAME_SECTION_NAME instead of
+ USE_EH_FRAME_REGISTRY when defining.
-2002-04-04 David S. Miller <davem@redhat.com>
+2003-01-04 John David Anglin <dave.anglin@nrc.ca>
- * config/sparc/crtfastmath.c: New file.
- * config/sparc/t-crtfm: New file.
- * config/sparc/linux.h (ENDFILE_SPEC): Use crtfastmath.o
- * config/sparc/linux64.h (ENDFILE_SPEC): Likewise.
- * config/sparc/sol2.h (ENDFILE_SPEC): Likewise.
- * config/sparc/sp64-elf.h (ENDFILE_SPEC): Likewise.
- * config/sparc/elf.h (ENDFILE_SPEC): Likewise.
- * config.gcc (sparc*-*-{elf*,linux*,solaris2*}): Add
- sparc/t-crtfm to tmake_file.
+ * config.gcc (hppa*64*-*-hpux11*): Define extra_parts. Don't use
+ collect2.
+ * pa-hpux11.h (LDD_SUFFIX, PARSE_LDD_OUTPUT): Undefine.
+ (HAS_INIT_SECTION, LD_INIT_SWITCH, LD_FINI_SWITCH): Define.
+ * pa64-hpux.h (HP_INIT_ARRAY_SECTION_ASM_OP,
+ GNU_INIT_ARRAY_SECTION_ASM_OP, HP_FINI_ARRAY_SECTION_ASM_OP,
+ GNU_FINI_ARRAY_SECTION_ASM_OP): Define.
+ (CTORS_SECTION_ASM_OP, DTORS_SECTION_ASM_OP): Define when not using
+ elfos.h.
+ (EH_FRAME_IN_DATA_SECTION): Delete define.
+ (HAS_INIT_SECTION, LD_INIT_SWITCH, LD_FINI_SWITCH): Undefine.
+ (STARTFILE_SPEC): Use crtbegin.o.
+ (ENDFILE_SPEC): Use crtend.o.
+ (INIT_SECTION_ASM_OP, FINI_SECTION_ASM_OP, CRT_CALL_STATIC_FUNCTION,
+ SUPPORTS_INIT_PRIORITY, PA_CXA_FINALIZE_STUB, PA_INIT_FINI_HACK,
+ PA_INIT_FRAME_DUMMY_ASM_OP, PA_JV_REGISTERCLASSES_STUB,
+ DTOR_LIST_BEGIN): Define.
+ * pa.c (TARGET_ASM_CONSTRUCTOR): Define.
+ (pa_asm_out_constructor, pa_asm_out_destructor): New functions.
+ * som.h (SUPPORTS_INIT_PRIORITY): Delete define.
-2002-04-05 Alan Modra <amodra@bigpond.net.au>
+2003-01-02 Eric Christopher <echristo@redhat.com>
- * config/rs6000/t-linux64 (EXTRA_MULTILIB_PARTS): Add crtsavres.o
- Add rules to make null object file.
+ * config/mips/mips.md (movdf_internal2): Fix constraints.
-2002-04-04 David S. Miller <davem@redhat.com>
+2003-01-03 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
- * calls.c (store_one_arg): If ECF_SIBCALL, use tail_call_reg.
+ * doc/install.texi (Configuration): Fix markup for reference to
+ gcc/config.gcc.
-2002-04-04 Richard Henderson <rth@redhat.com>
+2003-01-02 Kazu Hirata <kazu@cs.umass.edu>
- PR opt/6165
- * alias.c (true_dependence): Force (mem:blk (scratch)) to conflict.
- (write_dependence_p): Likewise.
+ * config/h8300/h8300.c (stack_pointer_operand): New.
+ (const_int_gt_2_operand): Likewise.
+ (const_int_ge_8_operand): Likewise.
+ * config/h8300/h8300.md (a splitter): Likewise.
+ (a peephole2): Likewise.
+ * config/h8300/h8300-protos.h: Add prototypes for the new
+ functions above.
-2002-04-04 Richard Henderson <rth@redhat.com>
+2003-01-02 Neil Booth <neil@daikokuya.co.uk>
- * predict.c (estimate_bb_frequencies): Do frequency calculation
- with a volatile temporary.
+ * gccbug.in: Update for new categories.
-2002-04-04 Ulrich Weigand <uweigand@de.ibm.com>
+2002-12-31 Tom Tromey <tromey@redhat.com>
- * config/s390/linux.h (LOCAL_LABEL_PREFIX): Define.
+ * doc/install.texi (Testing): Fixed typo.
-2002-04-04 Jakub Jelinek <jakub@redhat.com>
+2002-12-31 Jerry Quinn <jlquinn@optonline.net>
- PR c++/6119
- * final.c (final_start_function): Don't bump profile_label_no here...
- (final_end_function): ...but here.
+ * gcc/doc/invoke.texi (Optimization Options): Clean up -O flag
+ descriptions.
-2002-04-04 Jakub Jelinek <jakub@redhat.com>
+2002-12-31 Jerry Quinn <jlquinn@optonline.net>
- * config/sparc/sparc.md (pic): New attribute.
- (do_builtin_setjmp_setup): Save %fp, %i7 and %l7 for TARGET_V9
- into stack slots.
- (split after do_builtin_setjmp_setup): New.
+ * gcc/doc/invoke.texi (Optimization Options): List the options
+ enabled by each -O flag.
-2002-04-04 Jakub Jelinek <jakub@redhat.com>
+2002-12-31 David Edelsohn <edelsohn@gnu.org>
- PR fortran/6106
- * config/sparc/sparc.h (MIN_UNITS_PER_WORD): Backout 2001-01-01
- change.
+ * config/rs6000/rs6000.h (WIDEST_HARDWARE_FP_SIZE): Define.
-2002-04-04 Jakub Jelinek <jakub@redhat.com>
+2002-12-31 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
- * config/sparc/sparc.c (sparc_va_arg): Adjust va_list by
- UNITS_PER_WORD for zero sized aggregates.
+ * doc/install.texi (Configuration): Explicitly refer
+ gcc/config.gcc for a list of cpu models.
-2002-04-04 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+2002-12-30 Joseph S. Myers <jsm@polyomino.org.uk>
- * doc/contrib.texi (Contributors): Add David O'Brien.
+ * doc/gcc.texi, doc/gccint.texi: Update last modification dates.
-2002-04-03 David S. Miller <davem@redhat.com>
+2002-12-30 Tom Tromey <tromey@redhat.com>
- * gcc.c (LINK_GCC_C_SEQUENCE_SPEC): No need for a new
- one-character spec for this, just use %(link_gcc_c_sequence).
+ * doc/install.texi (Testing): Mention Jacks.
-2002-04-04 Alan Modra <amodra@bigpond.net.au>
+2002-12-30 Joseph S. Myers <jsm@polyomino.org.uk>
- * config/rs6000/t-linux64 (EXTRA_MULTILIB_PARTS): Define.
+ * doc/service.texi: Uncomment and update FAQ link.
-2002-04-03 David S. Miller <davem@redhat.com>
+2002-12-28 Joseph S. Myers <jsm@polyomino.org.uk>
- * gcc.c (LINK_GCC_C_SEQUENCE_SPEC): New spec to override the gcc/c
- library sequence passed to the linker.
- (LINK_COMMAND_SPEC): Use it.
- * doc/tm.texi: Document it, and mention from LINK_COMMAND_SPEC as
- a macro a target can use to avoid overriding LINK_COMMAND_SPEC.
- * config/sparc/sparc.h (LINK_GCC_C_SEQUENCE_SPEC): Define.
+ * doc/cpp.texi, doc/gcc.texi, doc/gccint.texi, doc/install.texi:
+ Use @copying.
-2002-04-03 Jason Merrill <jason@redhat.com>
+2002-12-28 Joseph S. Myers <jsm@polyomino.org.uk>
- PR c++/5636
- * tree.h (CLEANUP_EH_ONLY): New macro.
- * stmt.c (expand_decl_cleanup_eh): New fn.
- (expand_cleanups): Check CLEANUP_EH_ONLY.
- * c-semantics.c (genrtl_decl_cleanup): Just take the CLEANUP_STMT.
- Use expand_decl_cleanup_eh.
- (expand_stmt): Adjust.
- * c-common.h: Adjust prototype.
+ * configure.in: Increase makeinfo version requirement to 4.[2-9].
+ * configure: Regenerate.
+ * doc/install.texi: Update Texinfo version requirement.
-2002-04-03 Jakub Jelinek <jakub@redhat.com>
+2002-12-27 Joseph S. Myers <jsm@polyomino.org.uk>
- * configure.in (HAVE_SPARC_UA_PCREL_HIDDEN): Test whether %r_disp32()
- works properly with .hidden symbols.
- * configure: Rebuilt.
- * config.in: Rebuilt.
- * config/sparc/sparc.h (ASM_PREFERRED_EH_DATA_FORMAT): Use
- DW_EH_PE_absptr for flag_pic && GLOBAL if %r_disp32() doesn't work
- properly with .hidden symbols.
+ * doc/include/texinfo.tex: Update to version 2002-12-26.16.
-2002-04-03 Jakub Jelinek <jakub@redhat.com>
+2002-12-26 Joseph S. Myers <jsm@polyomino.org.uk>
- PR middle-end/6102
- * df.c (df_insn_refs_record): Use XEXP not SET_DEST to access
- USE argument.
+ * doc/standards.texi, doc/invoke.texi: Point to 3.3 version of
+ c99status.html.
-2002-04-03 Richard Henderson <rth@redhat.com>
+2002-12-26 Kazu Hirata <kazu@cs.umass.edu>
- PR opt/4120
- * sched-rgn.c (sets_likely_spilled): New.
- (sets_likely_spilled_1): New.
- (add_branch_dependences): Use it.
+ * config/h8300/h8300.h (IDENT_ASM_OP): End with a tab.
-2002-04-02 Richard Henderson <rth@redhat.com>
+2002-12-23 Larin Hennessy <larin@science.oregonstate.edu>
- PR opt/4311
- * loop.h (LOOP_FIRST_PASS): New.
- * loop.c (strength_reduce): Mind it when deciding to unroll.
- * toplev.c (rest_of_compilation): Set it.
+ * doc/install.texi: Remove i386-*-isc, i860-*-bsd,
+ m68k-altos-sysv, m68k-isi-bsd, m68k-sony-bsd entries.
+ * doc/invoke.texi: Remove AMD 29K, ARM RISC/iX, Clipper, Convex,
+ DG/UX entries.
+ * doc/md.texi: Remove AMD 29K entries.
+ * doc/trouble.texi: Remove Alliant, DG/UX, Iris 4.0.5F, GAS
+ 1.38.1, NewsOS, RT PC, WE32K entries.
-2002-04-02 David S. Miller <davem@redhat.com>
+2002-12-23 Aldy Hernandez <aldyh@redhat.com>
- * config/sparc/sparc.md (ldd peephole2s): Fix final arg to
- mems_ok_for_ldd_peep when the order of the loads being examined
- is reversed.
- * config/sparc/sparc.c (mems_ok_for_ldd_peep): Expand upon
- existing comment to increase comprehension of this situation.
+ PR/8763
+ * config/rs6000/altivec.md (mulv4sf3): Rewrite to add -0.0 vector.
+ (altivec_vspltisw_v4sf): Name pattern.
+ (altivec_vslw_v4sf): New pattern.
-2002-04-02 Richard Henderson <rth@redhat.com>
+2002-12-23 Joseph S. Myers <jsm@polyomino.org.uk>
- * libgcc2.c (__bb_exit_func): Revert 03-31 change.
+ * doc/include/gcc-common.texi: Clear DEVELOPMENT.
-2002-04-02 Eric Botcazou <ebotcazou@multimania.com>
- Richard Henderson <rth@redhat.com>
+2002-12-23 David Edelsohn <edelsohn@gnu.org>
- PR c/5484
- * function.c (assign_temp): Accept either type or decl argument.
- Detect variables whose size is too large to fit into an integer.
- * stmt.c (expand_decl): Pass the decl, not the type.
+ PR middle-end/8784
+ * expr.c (expand_assignment): Apply special treatment to
+ ARRAY_TYPE.
-2002-04-02 David O'Brien <obrien@FreeBSD.org>
+2002-12-21 Kazu Hirata <kazu@cs.umass.edu>
- * protoize.c: Match include directory usage with cppdefault.c.
+ * config/h8300/h8300.md (zero_extendqisi2): Correct the
+ length.
-2002-04-03 Jeffrey A Law (law@redhat.com)
- Hans-Peter Nilsson <hp@bitrange.com>
+2002-12-19 Devang Patel <dpatel@apple.com>
- * combine.c (simplify_comparison): Avoid narrowing a comparison
- with a paradoxical subreg when doing so would drop signficant bits.
+ * config/darwin.h (TARGET_OPTION_TRANSLATE_TABLE): Add support for -dynamic.
+ (CPP_SPEC): Define __STATIC__ and __DYNAMIC__ depending on -dynamic.
+ (LINK_SPEC): Pass -dynamic to linker.
+ * config/rs6000/darwin.h: Reject conflicting -static and -dynamic.
-2002-04-02 David Edelsohn <edelsohn@gnu.org>
+2002-12-19 Kazu Hirata <kazu@cs.umass.edu>
- * config/rs6000/rs6000.h (WIDEST_HARDWARE_FP_SIZE): Define.
+ * config/h8300/h8300.md (pushqi_h8300): Don't push the stack
+ pointer.
+ (pushqi_h8300hs): Likewise.
+ (pushhi_h8300): Likewise.
+ (pushhi_h8300hs): Likewise.
-2002-04-02 Alan Modra <amodra@bigpond.net.au>
+2002-12-19 Eric Botcazou <ebotcazou@libertysurf.fr>
- * config/rs6000/rs6000.md (ctrdi*): Add FPR constraint and
- associated splitter. Remove MQ constraint.
- (ctrdi_internal4): Correct CCmode clobber.
+ PR optimization/8988
+ * loop.c (maybe_eliminate_biv): Kill REG_EQUAL notes mentioning
+ the biv when eliminating.
-2002-04-03 Hans-Peter Nilsson <hp@bitrange.com>
+2002-12-19 Aldy Hernandez <aldyh@redhat.com>
- * config/mmix/mmix.md (define_constants): Remove misleading
- FIXME. Add MMIX_fp_rO_OFFSET.
- ("nonlocal_goto_receiver"): Don't have stack-frame address of
- saved rO as part of the pattern. Remove FIXME.
- ("*nonlocal_goto_receiver_expanded"): Similar. Generate address
- here, at output-time.
- * config/mmix/crti.asm (_init): Register _fini with atexit.
- * config/mmix/crtn.asm (_fini): Add omitted "POP 0,0".
- * config/mmix/mmix.c (mmix_target_asm_function_prologue): Correct
- unwind information when frame_pointer_needed.
- (mmix_assemble_integer): Tweak wording in comment.
+ PR 8553
+ * config/rs6000/altivec.md ("absv8hi2"): Add & to clobbered
+ registers.
+ ("absv16qi2"): Same.
+ ("absv4si2"): Same.
+ ("absv4sf2"): Same.
+ ("altivec_abss_v16qi"): Same.
+ ("altivec_abss_v8hi"): Same.
+ ("altivec_abss_v4si"): Same.
-2002-04-02 Richard Henderson <rth@redhat.com>
+2002-12-19 Ulrich Weigand <uweigand@de.ibm.com>
- PR opt/3967
- * local-alloc.c (contains_replace_regs): LO_SUM may contain
- replace regs.
+ * config/s390/s390.md ("*tsthiCCT", "*tsthiCCT_cconly",
+ "*tstqiCCT", "*tstqiCCT_cconly"): New insns.
-2002-04-02 Richard Henderson <rth@redhat.com>
+2002-12-18 Aldy Hernandez <aldyh@redhat.com>
- * doc/standards.texi: Document required freestanding libc entry points.
+ * config/rs6000/altivec.h (vec_cmplt macro): Reverse arguments in
+ macro.
+ (vec_cmplt C++ functions): Reverse arguments.
-2002-04-02 Alexandre Oliva <aoliva@redhat.com>
+2002-12-17 Kazu Hirata <kazu@cs.umass.edu>
- * config/mips/mips.c (mips_va_arg): Apply big-endianness address
- offset before loading address of argument passed by transparent
- reference.
+ * doc/c-tree.texi: Restore deliberate spelling mistakes.
-2002-04-02 Richard Henderson <rth@redhat.com>
+2002-12-17 Kazu Hirata <kazu@cs.umass.edu>
- * fixinc/inclhack.def (AAB_solaris_sys_varargs_h): Move and
- rename solaris_sys_varargs_h.
+ * doc/c-tree.texi: Fix typos and follow spelling conventions.
+ * doc/cpp.texi: Likewise.
+ * doc/extend.texi: Likewise.
+ * doc/gty.texi: Likewise.
+ * doc/install.texi: Likewise.
+ * doc/invoke.texi: Likewise.
+ * doc/md.texi: Likewise.
+ * doc/passes.texi: Likewise.
+ * doc/rtl.texi: Likewise.
+ * doc/sourcebuild.texi: Likewise.
+ * doc/tm.texi: Likewise.
-Tue Apr 2 06:47:40 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2002-12-17 Jerry Quinn <jlquinn@optonline.net>
- * stor-layout.c (layout_type, case ARRAY_TYPE): Give one-element array
- the same mode as its component.
+ * doc/invoke.texi: Minor spelling and grammar fixes.
-2002-04-02 Richard Henderson <rth@redhat.com>
+2002-12-16 Mark Mitchell <mark@codesourcery.com>
- PR opt/420
- * config/m68k/m68k.md (dbcc peepholes): Match four forms of dbra.
+ * version.c (version_string): Mark as prerelease.
-2002-04-01 Richard Henderson <rth@redhat.com>
+2002-12-13 John David Anglin <dave@hiauly1.hia.nrc.ca>
- PR target/1538
- * fixinc/inclhack.def (solaris_sys_varargs_h): New.
- * fixinc/fixincl.x: Rebuild.
+ * pa.c (output_millicode_call): Correct typo.
+ (output_call): Likewise.
-2002-04-01 Richard Henderson <rth@redhat.com>
+2002-12-13 Alexandre Oliva <aoliva@redhat.com>
- * config/ia64/unwind-ia64.c: Include ia64intrin.h.
- (atomic_alloc, atomic_free): New.
- (SIZE, MASK_FOR, PTR_IN): New.
- (emergency_reg_state, emergency_reg_state_free): New.
- (emergency_labeled_state, emergency_labeled_state_free): New.
- (reg_state_alloced, labeled_state_alloced): New.
- (alloc_reg_state, free_reg_state): New.
- (alloc_label_state, free_label_state, free_label_states): New.
- (push, pop, dup_state_stack, free_state_stack): Use them.
- (desc_label_state): Likewise.
- (uw_frame_state_for): Free label states and state stack.
- (uw_update_reg_address): Eliminate warnings.
+ * config/mn10300/mn10300.c (print_operand) <case N>: Check
+ operand's range. Print value directly, without aid from
+ output_address.
+ <case U>: New.
+ <case S>: Make sure argument to fprintf has the right type.
+ * config/mn10300/mn10300.h (OK_FOR_T): New macro.
+ (EXTRA_CONSTRAINT): Adjust.
+ * config/mn10300/mn10300.md: Add new all-QImode pattern for
+ bclr. Use %U for immediate operands of bset and bclr.
+ (iorqi3): New expand, with insns for AM33 and mn10300.
-2002-04-01 Loren J. Rittle <ljrittle@acm.org>
+2002-12-13 J"orn Rennecke <joern.rennecke@superh.com>
- * doc/install.texi (*-*-freebsd*): Update.
+ * sh.c (sh_register_operand): New function.
+ (prepare_move_operands): Use it.
+ * sh.h (PREDICATE_CODES): Add entry for sh_register_operand.
+ * sh.md (movsi_media, movsi_media_nofpu): Allow stores of 0.
+ (movqi_media, movhi_media, movdi_media, movdi_media_nofpu): Likewise.
+ (movdf_media, movdf_media_nofpu, movv4sf_i, movsf_media): Likewise.
+ (movsf_media_nofpu, movv2hi_i, movv4hi_i, movv8qi_i): Likewise.
+ (movv2si_i): Likewise.
-2002-04-01 Phil Edwards <pme@gcc.gnu.org>
+2002-12-13 Jim Wilson <wilson@redhat.com>
- * version.c: Fix misplaced leading blanks on first line.
+ * doc/extend.texi (Complex Numbers): Update info on debug info.
-2002-04-01 Vladimir Makarov <vmakarov@redhat.com>
+2002-12-13 Kazu Hirata <kazu@cs.umass.edu>
- * config/pa/pa-pro-end.h (ASM_OUTPUT_ALIGNED_COMMON,
- ASM_OUTPUT_ALIGNED_LOCAL): Redefine them.
+ * config/h8300/h8300.md (addhi3_h8300): Remove the last
+ alternative.
-2002-04-01 Jim Blandy <jimb@redhat.com>
+2002-12-12 Devang Patel <dpatel@apple.com>
- * cppmacro.c (cpp_macro_definition): Do not emit spaces after
- macro formal parameter names.
+ * doc/invoke.texi: Document Darwin linker options, -bundle
+ -bind_at_load, -all_load and -arch_errors_fatal
-2002-04-01 Bob Wilson <bob.wilson@acm.org>
+2002-12-12 Jim Wilson <wilson@redhat.com>
- * config/xtensa/xtensa.c (xtensa_va_arg): Fix compiler warning
- in previous change.
+ * dbxout.c (dbxout_fptype_value): New.
+ (dbxout_type, case COMPLEX_TYPE): Call it. Use 'R' instead of 'r'.
-2002-04-01 Bob Wilson <bob.wilson@acm.org>
+2002-12-12 Kazu Hirata <kazu@cs.umass.edu>
- * config/xtensa/xtensa.c (xtensa_va_arg): Fix to handle arguments
- for which MUST_PASS_IN_STACK is true (e.g., variable-sized types).
+ * c-decl.c: Fix a comment typo.
+ * cfg.c: Likewise.
+ * cfgcleanup.c: Likewise.
+ * cfglayout.c: Likewise.
+ * cfgrtl.c: Likewise.
+ * c-typeck.c: Likewise.
+ * dominance.c: Likewise.
+ * dwarf2asm.c: Likewise.
+ * dwarfout.c: Likewise.
+ * expmed.c: Likewise.
+ * expr.c: Likewise.
+ * final.c: Likewise.
+ * flow.c: Likewise.
+ * function.c: Likewise.
+ * gcc.c: Likewise.
+ * genautomata.c: Likewise.
+ * integrate.c: Likewise.
+ * loop.c: Likewise.
+ * loop.h: Likewise.
+ * output.h: Likewise.
+ * profile.c: Likewise.
+ * ra.h: Likewise.
+ * reload1.c: Likewise.
+ * reload.c: Likewise.
+ * sched-rgn.c: Likewise.
+ * stmt.c: Likewise.
+ * tree.h: Likewise.
+ * vmsdbgout.c: Likewise.
-2002-03-31 Richard Henderson <rth@redhat.com>
+2002-12-12 Kazu Hirata <kazu@cs.umass.edu>
- * config/ia64/unwind-ia64.c (alloc_spill_area): Fix offset.
- (desc_frgr_mem): Fix reference to f16-f31.
+ * config/h8300/h8300.md: Add a new peephole2.
-Sun Mar 31 14:43:24 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2002-12-12 Kazu Hirata <kazu@cs.umass.edu>
- * emit-rtl.c (adjust_address_1, offset_address): Cast value to
- unsigned HOST_WIDE_INT, not unsigned int.
+ * config/h8300/h8300.md (a peephole2): Accept a constant
+ that's accepted by CONST_OK_FOR_J.
-2002-03-31 Jakub Jelinek <jakub@redhat.com>
+2002-12-12 Kazu Hirata <kazu@cs.umass.edu>
- PR middle-end/6096, middle-end/6098, middle-end/6099
- * reorg.c (emit_delay_sequence): Only increment LABEL_NUSES for
- CODE_LABELs.
- (fill_slots_from_thread): Likewise.
+ * config/h8300/h8300.h (CONST_OK_FOR_J): New.
+ (CONST_OK_FOR_LETTER_P): Use CONST_OK_FOR_J.
+ * config/h8300/h8300.md (*addhi_h8300): Add a new alternative.
+ (*addhi_h8300hs): Likewise.
-2002-03-31 Jakub Jelinek <jakub@redhat.com>
+2002-12-12 J"orn Rennecke <joern.rennecke@superh.com>
- * config/sparc/sparc.c (function_arg_record_value_1): Pass complex
- floating fields in float regs.
- (function_arg_record_value_2): Likewise.
+ * sh.c (reg_class_from_letter): No longer const. Add 'e' entry.
+ (sh_register_move_cost): Add clause for SImode fp-fp moves.
+ Increase cost for moves involving multiple general purpose registers.
+ * sh.h (OVERRIDE_OPTIONS): Set reg_class_from_letter['e'] according to
+ TARGET_FMOVD.
+ (HARD_REGNO_MODE_OK): Allow V2SFmode and V4SFmode in general purpose
+ registers, and SImode in fp registers, for ! TARGET_SHMEDIA.
+ (enum reg_class reg_class_from_letter): No longer const.
+ (SECONDARY_OUTPUT_RELOAD_CLASS): Use REGCLASS_HAS_FP_REG /
+ REGCLASS_HAS_GENERAL_REG.
+ Handle SImode moves from/to fp registers.
+ ! TARGET_SHMEDIA && TARGET_FMOVD.
+ (SECONDARY_INPUT_RELOAD_CLASS): Use REGCLASS_HAS_FP_REG.
+ * sh.md (movsi_ie): Add alternatives to move from / to fp regisyters.
-2002-03-31 Jakub Jelinek <jakub@redhat.com>
+2002-12-12 Andreas Schwab <schwab@suse.de>
- PR middle-end/6100
- * config/sparc/sparc.c (output_cbranch): Use REG_BR_PROB, not
- REG_BR_PRED.
- (output_v9branch): Likewise.
+ * config/ia64/ia64.c (ia64_hpux_asm_file_end): Fix typo in last
+ change and some warnings.
-2002-03-31 Alexandre Oliva <aoliva@redhat.com>
+2002-12-12 Kazu Hirata <kazu@cs.umass.edu>
- * gcc.c: Revert previous patch for now.
- * config/i386/djgpp.h: Likewise.
+ * doc/md.texi (pushm): Fix a typo.
-2002-03-31 Richard Henderson <rth@redhat.com>
+2002-12-12 Alexandre Oliva <aoliva@redhat.com>
- PR target/3997
- * config/alpha/elf.h (ASM_OUTPUT_DEF): Tidy.
- (ASM_OUTPUT_DEF_FROM_DECLS): New.
+ * config/mips/mips.c (mips_output_conditional_branch): Support
+ PIC-safe out-of-range branch and branch-likely.
+ * config/mips/mips.md (attr length): PIC-safe out-of-range
+ branches are longer.
+ ("jump"): Support PIC-safe out-of-range-for-branch jumps. Remove
+ unused code to support indirect jumps.
-2002-03-31 Richard Henderson <rth@redhat.com>
+2002-12-11 John David Anglin <dave@hiauly1.hia.nrc.ca>
- * libgcc2.c (__bb_exit_func): Make static.
+ * pa.h (BIGGEST_ALIGNMENT): Change 32-bit value to 64 bits.
+ (MAX_PARM_BOUNDARY, STACK_BOUNDARY): Express in terms of
+ BIGGEST_ALIGNMENT.
+ (PREFERRED_STACK_BOUNDARY): Express in terms of STACK_BOUNDARY.
+ (FUNCTION_BOUNDARY): Express in terms of BITS_PER_WORD.
- * config/alpha/alpha.md (trap): New.
+2002-12-11 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-31 Alexandre Oliva <aoliva@redhat.com>
+ * doc/invoke.texi: Correct dump file names.
- * gcc.c (LIBGCC_SPEC): Folded %L and duplicate %G here...
- (LINK_COMMAND_SPEC): ... from here.
- (init_gcc_specs): Duplicate it here too, omitting
- shared_name in the second copy.
- (init_spec): Test for duplicate
- * config/i386/djgpp.h (LINK_COMMAND_SPEC): Remove `%L %G'.
+2002-12-09 Steve Ellcey <sje@cup.hp.com>
-2002-03-31 Richard Henderson <rth@redhat.com>
+ * config/ia64/ia64.c (ia64_hpux_asm_file_end): Don't send stripped
+ name to globalize_label or assemble_name.
- * builtins.c (expand_builtin_va_arg): Give warnings not errors for
- promoted argument types; build trap.
- (expand_builtin_trap): New.
- (expand_builtin): Use it.
- * stmt.c (expand_nl_goto_receivers): Likewise.
- * expr.h (expand_builtin_trap): Declare.
- * libfuncs.h (LTI_abort, abort_libfunc): New.
- * optabs.c (init_optabs): Init abort_libfunc.
+2002-12-11 J"orn Rennecke <joern.rennecke@superh.com>
-2002-03-30 David S. Miller <davem@redhat.com>
+ * sh.h (REG_CLASS_HAS_GENERAL_REG): Only true for SIBCALL_REGS
+ if not TARGET_SHMEDIA.
- * config/sparc/linux.h (HANDLE_PRAGMA_PACK_PUSH_POP): Define.
- * config/sparc/linux64.h (HANDLE_PRAGMA_PACK_PUSH_POP): Likewise.
+2002-12-11 J"orn Rennecke <joern.rennecke@superh.com>
-2002-03-30 Roger Sayle <roger@eyesopen.com>
- Richard Henderson <rth@redhat.com>
+ * sh.h (REG_CLASS_HAS_FP_REG): New.
+ (REGISTER_MOVE_COST) Use it. Put body into a function and
+ move it into:
+ * sh.c (sh_register_move_cost).
+ * sh-protos.h (sh_register_move_cost): Declare.
- * regmove.c (combine_stack_adjustments_for_block): Avoid
- emitting a stack adjustment of zero bytes. Let delete_insn
- update bb->head.
+ * sh.c (sh_expand_builtin): Abort for unexpected nop values.
+ (sh_adjust_cost): Always return a value.
-2002-03-30 Richard Henderson <rth@redhat.com>
+2002-12-11 J"orn Rennecke <joern.rennecke@superh.com>
- * config/sparc/sparc.c: Remove all references to TARGET_EPILOGUE.
- (sparc_emitting_epilogue): New.
- (leaf_label, output_return, sparc_return_peephole_ok): Remove.
- * config/sparc/sparc-protos.h: Update.
- * config/sparc/sparc.h (MASK_EPILOGUE, TARGET_EPILOGUE): Remove.
- (TARGET_SWITCHES): Update.
- * config/sparc/sparc.md (return): Remove.
- (return_*): Use sparc_emitting_epilogue, not !TARGET_EPILOGUE.
- * config/sparc/freebsd.h, config/sparc/linux64.h, config/sparc/lite.h,
- config/sparc/liteelf.h, config/sparc/netbsd-elf.h,
- config/sparc/sol2-sld-64.h, config/sparc/sol2.h,
- config/sparc/sp64-aout.h, config/sparc/sp64-elf.h,
- config/sparc/sp86x-aout.h, config/sparc/sp86x-elf.h,
- config/sparc/splet.h, config/sparc/vxsparc64.h (TARGET_DEFAULT):
- Remove MASK_EPILOGUE.
- * doc/invoke.texi: Update.
+ * sh.h (REG_CLASS_HAS_GENERAL_REG): New.
+ (REGISTER_MOVE_COST): Use it.
-2002-03-30 Daniel Berlin <dan@dberlin.org>
+2002-12-11 Richard Henderson <rth@redhat.com>
- * dwarf2out.c (dwarf2out_define): Remove start_source_file call,
- CPP will start the file for us.
+ * tree.h (MODULE_LOCAL_P): Kill.
+ * varasm.c (default_binds_local_p_1): Use decl_visibility instead.
-2002-03-30 Richard Henderson <rth@redhat.com>
+2002-12-11 Kazu Hirata <kazu@cs.umass.edu>
- PR target/5446
- * config/ia64/ia64.c (group_barrier_needed_p): Special case
- prologue_allocate_stack.
- (ia64_single_set): Use insn codes for recognition of special
- cases, not rtl matching.
- * config/ia64/ia64.md (prologue_allocate_stack): Op 3 is in-out.
+ * config/h8300/h8300.md (two define_peephole2): New.
-2002-03-30 Richard Henderson <rth@redhat.com>
+2002-12-11 Kazu Hirata <kazu@cs.umass.edu>
- PR target/6032
- * config/sparc/sparc.h (OVERRIDE_OPTIONS): Don't override -fpic
- or -fomit-frame-pointer with profiling.
- (SUBTARGET_OVERRIDE_OPTIONS): Remove.
- (FUNCTION_PROFILER): Do nothing.
- (PROFILE_HOOK): New.
- * config/sparc/sparc.c (sparc_override_options): Don't check
- code models for profiling.
- (sparc_function_profiler): Remove.
- (sparc_profile_hook): New.
- * config/sparc/sparc-protos.h: Update.
+ * config/h8300/h8300.h (CONST_OK_FOR_J): Remove.
+ (CONST_OK_FOR_K): Likewise.
+ (CONST_OK_FOR_M): Likewise.
+ (CONST_OK_FOR_LETTER_P): Do not use the above macros.
-2002-03-30 Jakub Jelinek <jakub@redhat.com>
+2002-12-11 Neil Booth <neil@daikokuya.co.uk>
- PR optimization/6086
- * combine.c (combine_simplify_rtx): If simplify_rtx failed because
- of SUBREG of volatile MEM or because the MEM was mode dependent,
- return CLOBBER instead of unmodified SUBREG.
+ * c-common.c (builtin_define_type_max): Handle unsigned
+ types too.
-2002-03-30 David O'Brien <obrien@FreeBSD.org>
+2002-12-10 Janis Johnson <janis187@us.ibm.com>
- * config/i370/linux.h: Update copyright.
+ PR other/8882
+ * doc/tm.texi (PUSH_ARGS): Remove misplaced line.
-2002-03-30 Alexandre Oliva <aoliva@redhat.com>
+2002-12-10 Devang Patel <dpatel@appple.com>
- * config/mips/mips.c (function_arg_pass_by_reference): Force to 0
- in o32 and o64 ABIs.
- * config/mips/abi64.h (MUST_PASS_IN_STACK): Define as in expr.h,
- but getting fixed-size structs passed in registers regardless of
- padding in o32 and o64 ABIs.
+ * config/darwin.h(LINK_SPEC): Add darwin specific linker options.
+ * doc/invoke.texi: Add new "Darwin Options" section.
-2002-03-29 Richard Henderson <rth@redhat.com>
+2002-12-10 Jim Wilson <wilson@redhat.com>
- PR target/5672
- * expr.c (expand_expr): Pass along EXPAND_INITIALIZER one more place.
+ * rs6000.h (RETURN_IN_MEMORY): If ABI_V4, then TFmode is returned in
+ memory.
-2002-03-29 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+2002-12-10 Andrew Haley <aph@redhat.com>
- * config/rs6000/rs6000.c (rs6000_va_arg): Correctly set register count
- for aggregate and TFmode types.
+ * cse.c (cse_insn): Don't cse past a basic block boundary.
-2002-03-29 Richard Henderson <rth@redhat.com>
+2002-12-10 Jakub Jelinek <jakub@redhat.com>
- PR target/5886
- * config/ia64/aix.h (CPP_PREDEFINES): Add -D_LP64.
- * config/ia64/hpux.h, config/ia64/linux.h: Likewise.
+ * config/linux.h (LIB_SPEC): If -pthread, add -lpthread even if
+ -shared.
+ * config/alpha/linux-elf.h (LIB_SPEC): Likewise.
+ * config/alpha/linux.h (LIB_SPEC): Likewise.
+ * config/arm/linux-elf.h (LIB_SPEC): Likewise.
+ * config/pa/pa-linux.h (LIB_SPEC): Likewise.
+ * config/sparc/linux.h (LIB_SPEC): Likewise.
+ * config/sparc/linux64.h (LIB_SPEC): Likewise.
-2002-03-29 Loren J. Rittle <ljrittle@acm.org>
+2002-12-09 Larin Hennessy <larin@science.oregonstate.edu>
- * doc/install.texi (*-*-freebsd*): Fix last commit.
+ * doc/invoke.texi: Document UltraSparc III option.
-2002-03-29 Richard Henderson <rth@redhat.com>
+2002-12-09 Richard Henderson <rth@redhat.com>
- PR target/6041
- * config/i386/i386.c (x86_arch_always_fancy_math_387): New.
- (override_options): Disable NO_FANCY_MATH_387 if the arch allows.
- * config/i386/i386.h (x86_arch_always_fancy_math_387): New.
- * config/i386/i386.md (sqrtxf2, sqrtextendsfxf2, sinxf2): Fix
- conditional.
- * docs/invoke.texi: Update -mno-fancy-math-387 docs.
+ * config/i386/i386.h (TARGET_CPU_CPP_BUILTINS): Define
+ __tune_pentium2__ and __tune_pentium3__ as necessary.
-2002-03-29 Loren J. Rittle <ljrittle@acm.org>
+2002-12-09 Richard Henderson <rth@redhat.com>
- * config.gcc (*-*-freebsd*): Enable creation of libgcc_s.so.
- * config/t-slibgcc-elf-ver (SHLIB_LC): Add macro and use it.
- No functional change except ...
- * config/t-slibgcc-nolc-override (SHLIB_LC): Override it. New file.
- * doc/install.texi (*-*-freebsd*): Document port configuration.
+ * target.h (gcc_target): Add cannot_force_const_mem.
+ * target-def.h (TARGET_CANNOT_FORCE_CONST_MEM): New.
+ (TARGET_INITIALIZER): Add it.
+ * varasm.c (force_const_mem): Fail if cannot_force_const_mem.
+ * expr.c (emit_move_insn): Be prepared for force_const_mem to fail.
+ * reload1.c (reload): Likewise.
+ * hooks.c (hook_bool_rtx_false): New.
+ * hooks.h: Declare it.
-2002-03-29 Jakub Jelinek <jakub@redhat.com>
+ * config/i386/i386.c (ix86_cannot_force_const_mem): New.
+ (TARGET_CANNOT_FORCE_CONST_MEM): New.
+ (ix86_expand_move): Remove de-const-pooling hack.
- PR c++/5964
- * config/sparc/sparc.md (empty_delay_slot, branch_type): New
- attributes.
- (length): Compute variable length for branches/calls/jumps here.
- (branch, inverted_branch, normal_fp_branch, inverted_fp_branch,
- normal_fpe_branch, inverted_fpe_branch): Remove length attribute,
- define branch_type attribute.
- (divsi3_sp32): Maximum length is 6 not 7.
- (call_address_struct_value_sp32, call_symbolic_struct_value_sp32,
- call_address_untyped_struct_value_sp32,
- call_symbolic_untyped_struct_value_sp32): Set length to 3 not 2.
- * config/sparc/sparc.c (empty_delay_slot): New function.
- * config/sparc/sparc.h (ADJUST_INSN_LENGTH): Remove.
- * config/sparc/sparc-protos.h (empty_delay_slot): Add prototype.
+2002-12-09 Jan Hubicka <jh@suse.cz>
-2002-03-29 Jakub Jelinek <jakub@redhat.com>
+ * toplev.c (dump_file): Fix order to match reality.
- * combine.c (set_nonzero_bits_and_sign_copies): Don't call
- nonzero_bits if not needed.
- (nonzero_bits) [XOR]: Likewise.
- (nonzero_bits) [REG]: Use reg_last_set_nonzero_bits even if
- reg_last_set_mode and mode are both MODE_INT, but not equal.
- (record_value_for_reg): Compute reg_last_set_nonzero_bits
- in nonzero_bits_mode for MODE_INT modes.
+2002-12-08 Geoffrey Keating <geoffk@apple.com>
-2002-03-28 Richard Henderson <rth@redhat.com>
+ * config/rs6000/rs6000.md (load_multiple): Use adjust_address_nv.
+ (store_multiple): Likewise.
- PR target/5715
- * config/alpha/osf.h (ASM_SPEC): Don't pass any special options
- to GAS. Correct drift between alternatives.
+2002-12-09 John David Anglin <dave@hiauly1.hia.nrc.ca>
-2002-03-28 Richard Henderson <rth@redhat.com>
+ * pa/fptr.c (__canonicalize_funcptr_for_compare): Don't canonicalize
+ function pointers in page 0.
- PR target/6087
- * reload1.c (fixup_abnormal_edges): Move insn to edge via sequence.
+2002-12-09 Steve Ellcey <sje@cup.hp.com>
-2002-03-28 Alexandre Oliva <aoliva@redhat.com>
+ * config/ia64/hpux.h (TARGET_STRUCT_ARG_REG_LITTLE_ENDIAN): Remove
+ definition
+ (MEMBER_TYPE_FORCES_BLK): Move.
+ * config/ia64/ia64.c (ia64_function_arg): Use PARALLEL to pass
+ aggregate arguments.
+ (ia64_function_value): Use PARALLEL to return aggregate values.
- * config/i386/freebsd.h (LINK_SPEC): Don't pass default
- emulation to the linker.
+2002-12-09 Steve Ellcey <sje@cup.hp.com>
-2002-03-28 Loren J. Rittle <ljrittle@acm.org>
+ * doc/tm.texi (FUNCTION_ARG_REG_LITTLE_ENDIAN): Remove definition.
+ * defaults.h (FUNCTION_ARG_REG_LITTLE_ENDIAN): Remove definition.
+ * calls.c (store_unaligned_arguments_into_pseudos) Remove
+ FUNCTION_ARG_REG_LITTLE_ENDIAN.
+ * stmt.c (expand_return): Ditto.
+ * expr.c (move_block_from_reg): Ditto.
+ (copy_blkmode_from_reg): Ditto.
+ * expmed.c (store_bit_field): Ditto.
- * config/alpha/freebsd.h (LINK_SPEC): Likewise.
- * config/sparc/freebsd.h (LINK_SPEC): Likewise.
+2002-12-09 Svein E. Seldal <Svein.Seldal@solidas.com>
-2002-03-28 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ * config.gcc: Added tic4x-* target as an alias to c4x-*
- * pa-linux.h (LOCAL_LABEL_PREFIX): Define.
+2002-12-08 Jan Hubicka <jh@suse.cz>
-Thu Mar 28 16:33:13 2002 Jeffrey A Law (law@redhat.com)
+ * i386.c (ix86_expand_int_movcc): Use force_operand instead of
+ constructing insn directly.
- * combine.c (simplify_and_const_int): Make sure to apply mask
- when force_to_mode returns a constant integer. PR3311.
+2002-12-07 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-28 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+ * config/h8300/h8300.md (*iorhi_shift_8): New.
- * doc/invoke.texi (Warning Options): Refer to C++ Dialect Options
- and Objective-C Dialect Options.
+2002-12-06 Bernd Schmidt <bernds@redhat.com>
-2002-03-28 Richard Henderson <rth@redhat.com>
+ * doc/invoke.texi: Document FRV port options.
+ * doc/md.texi: Document FRV register classes.
- * config/alpha/alpha.c (alpha_emit_conditional_branch): TFmode NE
- comparison should be done vs !=0 not >0 return code. Tidy cases.
+2002-12-07 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-03-28 Richard Henderson <rth@redhat.com>
+ * doc/install.texi (Configuration): Improve description of cases
+ where `make distclean` may fail; clarify --with-gnu-as; fix grammar.
- * c-decl.c (finish_function): New arg can_defer_p. Pass it
- on to c_expand_body.
- * c-tree.h (finish_function): Update decl.
- * c-objc-common.c, c-parse.in, objc/objc-act.c: Update calls.
+2002-12-06 Dhananjay Deshpande <dhananjayd@kpit.com>
-2002-03-27 Andreas Schwab <schwab@suse.de>
+ * gcc/config/sh/sh.c (calc_live_regs): Save fpscr only if target has
+ FPU.
+ (push): Generate push_fpscr.
+ (pop): Generate pop_fpscr.
+ * gcc/config/sh/sh.md : Add define_expand "push_fpscr", "pop_fpscr".
+ (fpu_switch): Add alternative to push fpscr. Enable for TARGET_SH3E.
- * config/i386/i386.c (classify_argument): Also check for
- QUAL_UNION_TYPE.
+2002-12-06 J"orn Rennecke <joern.rennecke@superh.com>
-2002-03-27 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+ * sh.c (dump_table): DImode pool constants need only 32 bit alignment.
+ DFmode alignment depends on TARGET_FMOVD && TARGET_ALIGN_DOUBLE.
- * doc/install.texi (alpha*-dec-osf*): Don't need --enable-libgcj
- any more.
+2002-12-06 J"orn Rennecke <joern.rennecke@superh.com>
-Wed Mar 27 22:52:02 CET 2002 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+ * sh.md (movdi_i): Name. Remove inappropriate comment.
- * cfgrtl.c (merge_blocks_nomove): Use set_block_for_insn instead of
- assigning to BLOCK_FOR_INSN directly.
+2002-12-06 J"orn Rennecke <joern.rennecke@superh.com>
+ Merged from basic improvements branch (excerpt):
-Wed Mar 27 22:46:04 CET 2002 Jan Hubicka <jh@suse.cz>
+ 2002-11-19 Kaz Kojima <kkojima@gcc.gnu.org>
+ * config/sh/sh.h (SH_DBX_REGISTER_NUMBER): Handle PR_MEDIA_REG.
- * i386.c (ix86_output_addr_diff_elt): Remove binutils bug workaround.
+2002-12-06 Jakub Jelinek <jakub@redhat.com>
-2002-03-27 Richard Henderson <rth@redhat.com>
+ * expr.c (expand_expr) <case COND_EXPR>: Never modify exp in place.
- * toplev.c (rest_of_compilation): Don't compile if we've had errors.
+2002-12-05 John David Anglin <dave@hiauly1.hia.nrc.ca>
-2002-03-27 Richard Henderson <rth@redhat.com>
+ * pa32-linux.h (CANONICALIZE_FUNCPTR_FOR_COMPARE_LIBCALL): Move define.
+ * pa.h (CANONICALIZE_FUNCPTR_FOR_COMPARE_LIBCALL): To here.
- * config/sparc/freebsd.h, config/sparc/linux.h, config/sparc/linux64.h,
- config/sparc/netbsd-elf.h, config/sparc/pbd.h, config/sparc/sol2.h,
- config/sparc/vxsim.h (LOCAL_LABEL_PREFIX): Define.
+2002-12-05 Dale Johannesen <dalej@apple.com>
-2002-03-27 Richard Henderson <rth@redhat.com>
+ * tree.c (unsafe_for_reeval): Consider callee child of CALL_EXPR.
- PR target/6054
- * config/ia64/ia64.c (ia64_expand_call): Use pic patterns for
- TARGET_CONST_GP. Simplify conditions.
+2002-12-05 Danny Smith <dannysmith@users.sourceforge.net>
-2002-03-26 Vladimir Makarov <vmakarov@redhat.com>
+ * config/i386/cygwin.h (SUBTARGET_PROLOGUE): Replace with
+ PROFILE_HOOK.
+ * config/i386/mingw32.h (SUBTARGET_PROLOGUE): Don't undef.
- * pa/pa-pro-end.h (CPP_PREDEFINES): Add -D__pro__.
+2002-12-05 Aldy Hernandez <aldyh@redhat.com>
- * pa/lib2funcs.asm: Don't use .SPACE and .SUBSPACE if __pro__
- or __rtems_ is defined.
+ * config/rs6000/spe.h (__ev_mwlufi): Remove.
+ (__ev_mwlufia): Remove.
+ (__ev_mwlumfaaw): Remove.
+ (__ev_mwlusfaaw): Remove.
+ (__ev_mwlumfanw): Remove.
+ (__ev_mwlusfanw): Remove.
-2002-03-26 Richard Henderson <rth@redhat.com>
+2002-12-05 Kazu Hirata <kazu@cs.umass.edu>
- * config/alpha/alpha.c (alpha_emit_set_const): Add a REG_EQUAL note
- if a non-trivial load was emitted.
- (alpha_emit_set_const_1): Remove obsolete extension. Fix thinko
- in high+extra+low case.
+ * config/h8300/h8300.md (*andorsi3_shift_8): New.
-2002-03-26 Richard Henderson <rth@redhat.com>
+2002-12-05 Kazu Hirata <kazu@cs.umass.edu>
- * config.gcc (sparc*-solaris): Use float_format=sparc.
+ * config/h8300/h8300.c (shift_alg_si): Optimize ashift:HI and
+ lshiftrt:SI by 28, 29, and 30 bits when !TARGET_H8300.
+ (get_shift_alg): Return optimal assembly instructions for the
+ shifts mentioned above.
-2002-03-26 Richard Henderson <rth@redhat.com>
+2002-12-04 Kazu Hirata <kazu@cs.umass.edu>
- * config/sparc/sparc.h (MAX_WCHAR_TYPE_SIZE): Don't define.
- * config/sparc/linux-aout.h (MAX_WCHAR_TYPE_SIZE): Don't undef.
- * config/sparc/linux.h, config/sparc/linux64.h: Likewise.
- * config/sparc/sol2.h (WCHAR_TYPE, WCHAR_TYPE_SIZE): Redefine.
- (WINT_TYPE_SIZE): Fix at 32.
+ * config/h8300/h8300.c (h8300_init_once): Do not use loop to
+ implement ashiftrt:HI by 13 bits on H8S.
-2002-03-26 Richard Henderson <rth@redhat.com>
+2002-12-04 John David Anglin <dave@hiauly1.hia.nrc.ca>
- * toplev.c (rest_of_compilation): Delay emit_initial_value_sets
- until after eh landing pad generation.
- * config/alpha/alpha.c (alpha_gp_save_rtx): Use gen_mem_addressof.
- * config/alpha/alpha.md (exception_receiver_2): Only accept MEMs.
+ * pa/fptr.c (__canonicalize_funcptr_for_compare): New file and function.
+ * pa.md (canonicalize_funcptr_for_compare): Output library call to
+ canonicalize_funcptr_for_compare_libfunc on TARGET_ELF32.
+ * pa32-linux.h (CANONICALIZE_FUNCPTR_FOR_COMPARE_LIBCALL,
+ CTOR_LIST_BEGIN): New defines.
+ * pa/t-linux (LIB2FUNCS_EXTRA): New define.
+ (fptr.c): Add make rules.
-2002-03-26 Richard Henderson <rth@redhat.com>
+2002-12-04 Geoffrey Keating <geoffk@apple.com>
- * expr.h (ADD_PARM_SIZE): One more convert for INC.
+ * combine.c (combine_simplify_rtx): Add new canonicalizations.
+ * doc/md.texi (Insn Canonicalizations): Document new
+ canonicalizations for multiply/add combinations.
+ * config/rs6000/rs6000.md: Add and modify floating add/multiply
+ patterns to ensure they're used whenever they can be.
-2002-03-26 David Edelsohn <edelsohn@gnu.org>
+2002-12-04 Kazu Hirata <kazu@cs.umass.edu>
- * config/rs6000/aix51.h (WCHAR_TYPE): Define.
+ * config/h8300/h8300.c: Update the comments related to shifts.
-2002-03-26 Hans Boehm <Hans_Boehm@hp.com>
+2002-12-04 Chris Demetriou <cgd@broadcom.com>
- * config/ia64/linux.h (MD_FALLBACK_FRAME_STATE_FOR):
- Restore more of the signal context. Set no_reg_stack_frame.
- * config/ia64/unwind-ia64.c (unw_state_record):
- Add no_reg_stack_frame, comments.
- (uw_frame_state_for): Initialize when field to UNW_WHEN_NEVER.
- (uw_update_context): Adjust bsp when unwinding from leaf,
- but not signal frame.
+ * config/mips/mips.md (get_fnaddr): Correct length attribute.
-2002-03-26 Bob Wilson <bob.wilson@acm.org>
+2002-12-04 Kazu Hirata <kazu@cs.umass.edu>
- * config/xtensa/xtensa.c (xtensa_va_arg): Handle variable-sized types.
+ * config/h8300/h8300.md (*extzv_8_8): New.
+ (*extzv_8_16): Likewise.
-2002-03-26 Richard Earnshaw <rearnsha@arm.com>
+2002-12-04 Jason Merrill <jason@redhat.com>
- PR target/5621
- * arm.md (define_asm_attributes): Reapply patch of Thu Sep 9, 1999:
- "Add a pool_range attribute", which was lost during the ARM/Thumb
- merge.
+ PR c++/8461, c++/8625
+ * integrate.c (copy_decl_for_inlining): Handle explicit invisible
+ references.
+ * tree-inline.c (initialize_inlined_parameters): Likewise.
-2002-03-26 Bob Wilson <bob.wilson@acm.org>
+ * tree.c (variably_modified_type_p): Just return an error_mark_node.
- * config/xtensa/xtensa.c (xtensa_valid_move): Allow move from
- a register into the MAC16 accumulator.
+2002-12-04 Chris Demetriou <cgd@broadcom.com>
-2002-03-26 Hartmut Penner <hpenner@de.ibm.com>
+ * config/mips/mips.md (get_fnaddr): Avoid placing an "la"
+ macro instruction in a branch delay slot, to avoid assembler
+ warnings.
- * config/s390/s390.c (s390_emit_epilogue): Change epilogue
- code to not restoring global registers.
+2002-12-04 Eric Botcazou <ebotcazou@libertysurf.fr>
-2002-03-26 Richard Henderson <rth@redhat.com>
+ PR c/7622
+ * c-semantics (genrtl_scope_stmt): Do not output inlined
+ nested functions that contain no code.
- * expr.h (ADD_PARM_SIZE): Cast INC to ssizetype.
- (SUB_PARM_SIZE): Cast DEC to ssizetype.
+2002-12-04 Jan Hubicka <jh@suse.cz>
- * config/alpha/alpha.c (alpha_va_arg): Read MUST_PASS_IN_STACK
- types from the normal argument frame.
+ * cfgrtl.c (force_nonfallthru_and_redirect): Allow abnormal edge
+ to be forced into nonfallthru.
- * config/sparc/sparc.c (function_arg_pass_by_reference): Pass
- variable sized objects by reference.
- (sparc_va_arg): Receive them by reference too.
+2002-12-03 Jason Thorpe <thorpej@wasabisystems.com>
-2002-03-25 Bruce Korb <bkorb@gnu.org>
+ * config/t-netbsd (USER_H): Set to $(EXTRA_HEADERS).
- * Makefile.in(check-fixinc): run "$(MAKE) check" in the fixinc
- directory when autogen is detected.
+2002-12-03 Aldy Hernandez <aldyh@redhat.com>
-2002-03-25 Richard Henderson <rth@redhat.com>
+ * config/rs6000/spe.md (*movv1di_const0): New pattern.
- * recog.c (peephole2_optimize): Distribute EH_REGION -1 notes
- anywhere in the block. Don't refer to insns that have been
- removed from the chain. Iterate backward through the new insns.
- Don't refer to edges that have been removed.
+2002-12-03 Richard Henderson <rth@redhat.com>
-2002-03-26 Alan Modra <amodra@bigpond.net.au>
+ * libgcc-std.ver: Inherit GCC_3.3 from GCC_3.0.
- * combine.c (simplify_comparison <ASHIFTRT, LSHIFTRT>): Correct
- test for overflow of constant.
+2002-12-03 Hans-Peter Nilsson <hp@bitrange.com>
-2002-03-25 Richard Earnshaw <rearnsha@arm.com>
+ * bitmap.c (bitmap_ior_and_compl, bitmap_union_of_diff):
+ Initialize tmp.using_obstack to 0.
- PR target/2623
- * arm.md (loadhi_preinc, loadhi_predec, loadhi_shiftpreinc)
- (loadhi_shiftpredec, loadhi-with-writeback peephole): Don't use
- these patterns on arm_archv4.
+2002-12-03 Andreas Schwab <schwab@suse.de>
-2002-03-22 Nick Clifton <nickc@cambridge.redhat.com>
+ * config/m68k/m68k.h (EH_RETURN_DATA_REGNO): Define.
+ (EH_RETURN_STACKADJ_RTX): Define.
+ (EH_RETURN_HANDLER_RTX): Define.
+ (ASM_PREFERRED_EH_DATA_FORMAT): Define.
+ * config/m68k/m68k.c (m68k_save_reg): New function. Handle eh
+ registers and don't save fixed registers.
+ (m68k_output_function_prologue): Use it.
+ (use_return_insn): Likewise.
+ (m68k_output_function_epilogue): Likewise.
- * config/mcore/mcore.h (CC1_SPEC): Define only if not already
- defined. Do not disable exceptions or rtti.
- * config/mcore/mcore-pe.h (CC1_SPEC): Define before including
- mcore.h. Disable exceptions and rtti, since they are not
- supported by EPOC.
+2002-12-03 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-25 Jakub Jelinek <jakub@redhat.com>
+ * config/h8300/h8300.c (single_one_operand): Fix a warning.
+ (single_zero_operand): Likewise.
- * regrename.c (build_def_use): Move recog_memoized
- before extract_insn.
+2002-12-02 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-25 Jakub Jelinek <jakub@redhat.com>
+ * config/h8300/h8300.c (dosize): Replace argument op with
+ sign.
+ (h8300_output_function_prologue): Update the call to dosize.
+ (h8300_output_function_epilogue): Likewise.
- PR target/6043
- * expr.c (emit_group_store): Handle storing into CONCAT.
+2002-12-02 Bob Wilson <bob.wilson@acm.org>
-2002-03-25 Jakub Jelinek <jakub@redhat.com>
+ * config/xtensa/xtensa.h: Delete ifndefs with nothing inside them.
- * regrename.c (build_def_use): Share RTL between MATCH_OPERATOR and
- corresponding MATCH_DUP.
+2002-12-02 Craig Rodrigues <rodrigc@gcc.gnu.org>
-2002-03-24 Richard Henderson <rth@redhat.com>
+ * configure.in: Use "missing" script to generate warning if
+ flex or bison programs not found, instead of invoking "false".
+ * configure: Rebuilt.
- * unroll.c (unroll_loop): Zero label_map.
+2002-12-02 Jan Hubicka <jh@suse.cz>
- * gcse.c: Include except.h.
- * Makefile.in (gcse.o): Update.
+ * unroll.c (copy_loop_body): Copy CONST_OR_PURE_CALL_P.
-2002-03-24 Richard Henderson <rth@redhat.com>
+2002-12-02 Jan Hubicka <jh@suse.cz>
- * varasm.c (asm_emit_uninitialised): Revert 2002-03-14 change.
- Do resolve_unique_section before shared data clause.
+ * i386.c (ix86_expand_int_movcc): Avoid overflow.
-2002-03-24 Richard Henderson <rth@redhat.com>
+2002-12-02 Kazu Hirata <kazu@cs.umass.edu>
- * config/alpha/elf.h (STARTFILE_SPEC): Use crtbeginT with -static.
+ * config/h8300/h8300.c (dosize): Output r7/er7 instead of sp.
+ (push): Likewise.
+ (pop): Likewise.
+ (h8300_output_function_prologue): Likewise.
+ (h8300_output_function_epilogue): Likewise.
-2002-03-24 Richard Henderson <rth@redhat.com>
+2002-12-02 J"orn Rennecke <joern.rennecke@superh.com>
- * recog.c (peephole2_optimize): Split blocks when EH insns are
- generated in the middle of a block. Do global life update if
- zapped EH edges.
+ * expmed.c (store_bit_field): Use int_mode_for_mode to find
+ corresponding mode of non-integer mode, unless it is VOIDmode.
-2002-03-24 Richard Henderson <rth@redhat.com>
+2002-12-02 Kazu Hirata <kazu@cs.umass.edu>
- * mips.c (mips_function_value): Only promote_mode for non-libcalls.
+ * config/h8300/h8300.md (stm_h8300s_2): New.
+ (stm_h8300s_3): Likewise.
+ (stm_h8300s_4): Likewise.
+ (five define_peephole2): Likewise.
-2002-03-24 Neil Booth <neil@daikokuya.demon.co.uk>
+2002-12-02 Kazu Hirata <kazu@cs.umass.edu>
- preprocessor/3951
- * gcc.c (cpp_options): Pass -MD through as -MD not -M -MF.
- * cppinit.c (cpp_handle_option): Set no_ouput if -MD or -MMD.
- (init_dependency_output): Don't make no_output decision here.
+ * ra-build.c: Fix a comment typo.
-2002-03-24 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+2002-12-01 Kazu Hirata <kazu@cs.umass.edu>
- * config/m68hc11/m68hc11.c (m68hc11_autoinc_compatible_p): New function.
- (m68hc11_split_move): Call it to see if the source and destination
- operands use the same direction auto inc/dec mode, otherwise make the
- source an offsetable memory operand and generate an add.
+ * config/h8300/h8300.c (h8300_output_function_prologue):
+ Remove variable idx.
+ (h8300_output_function_epilogue): Likewise.
-2002-03-24 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+2002-12-01 Zack Weinberg <zack@codesourcery.com>
- * config/m68hc11/m68hc11.md ("*subsi3_zero_extendhi"): Allow address
- register for operand 2.
- ("*subsi3_zero_extendqi"): Likewise.
- ("*iorhi3_gen"): Do the operation on the upper bits and then lower
- bits so that it is compatible with a pop.
- ("*andhi3_gen"): Likewise.
- ("xorhi3"): Likewise.
+ * config/frv/xm-frv.h: Delete, unnecessary.
-2002-03-24 Richard Henderson <rth@redhat.com>
+2002-12-01 Kazu Hirata <kazu@cs.umass.edu>
- PR optimization/5742
- * machmode.def: Add inner mode field to complex modes.
- * config/mips/mips.c (mips_function_value): Always define. Add
- new argument to handle libcalls.
- * config/mips/mips.h (LIBCALL_VALUE): Use mips_function_value.
- (FUNCTION_VALUE): Likewise.
- * config/mips/abi64.h (FUNCTION_VALUE): Remove.
- * config/mips/mips-protos.h: Update.
+ * config/h8300/h8300.md: Add comments for define_peephole2.
-2002-03-23 Richard Henderson <rth@redhat.com>
+2002-12-01 Mark Mitchell <mark@codesourcery.com>
- * config/sparc/sparc.c (sparc_emit_floatunsdi): New.
- * config/sparc/sparc-protos.h: Update.
- * config/sparc/sparc.md (floatunsdisf2, floatunsdidf2): New.
+ * builtin-types.def (BT_SIZE): Use size_type_node.
+ * builtins.c (fold_builtin): Make the builtin strlen returns a
+ size_t, not a sizetype.
+ * c-common.c (c_sizeof_or_alignof_type): Use size_type_node, not
+ c_size_type_node.
+ (c_alignof_expr): Likewise.
+ (c_common_nodes_and_builtins): Likewise.
+ * c-common.h (CTI_C_SIZE_TYPE): Remove.
+ (c_size_type_node): Likewise.
+ * c-format.c (T_ST): Use size_type_node, not c_size_type_node.
+ * tree.h (TI_SIZE_TYPE): New enumeral.
+ (size_type_node): Likewise.
-2002-03-23 Richard Henderson <rth@redhat.com>
+2002-11-30 John David Anglin <dave@hiauly1.hia.nrc.ca>
- * config/sparc/gmon-sol2.c (internal_mcount): Assume either
- _start or _init begins the text segment.
+ * cfg.c (dump_flow_info): Use max_reg_num () to determine the largest
+ pseudo register number plus 1.
-2002-03-23 Alan Modra <amodra@bigpond.net.au>
+2002-11-29 Hans-Peter Nilsson <hp@bitrange.com>
- * combine.c (simplify_comparison): When widening modes, ignore
- sign extension on CONST_INTs.
+ * cpplib.c (_cpp_test_assertion): Default *value to 0.
-2002-03-22 Bob Wilson <bob.wilson@acm.org>
+ * cppexp.c (num_part_mul): Initialize result.unsignedp, to 1.
- * config/xtensa/xtensa.c (print_operand): Fix incorrect mode
- passed to adjust_address. Fix comment formatting.
+2002-11-29 Ulrich Weigand <uweigand@de.ibm.com>
-2002-03-22 Alexandre Oliva <aoliva@redhat.com>
+ * config/s390/t-crtstuff: New target makefile fragment.
+ * config.gcc [s390-*-linux, s390x-*-linux]: Use it.
- * config/mips/mips.h (MASK_RETURN_ADDR): Define.
- (TARGET_PTRMEMFUNC_VBIT_LOCATION): Define.
+2002-11-29 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-22 Richard Henderson <rth@redhat.com>
+ * config/h8300/h8300.md (movsi_h8300hs): Change the order of
+ alternatives to correct the length when the memory operand is
+ either pre_dec or post_inc.
- * c-pragma.c (maybe_apply_renaming_pragma): New.
- (handle_pragma_redefine_extname, pending_redefine_extname): New.
- (handle_pragma_extern_prefix, pragma_extern_prefix): New.
- (init_pragma): Register them.
- * c-pragma.h (maybe_apply_renaming_pragma): Declare.
- * c-decl.c (finish_decl): Call it.
- * cp/decl.c (cp_finish_decl): Likewise.
- * doc/extend.texi: Document the new pragmas.
+2002-11-29 Kazu Hirata <kazu@cs.umass.edu>
- * config/alpha/osf.h (CPP_SUBTARGET_SPEC): Add __EXTERN_PREFIX.
- (HANDLE_PRAGMA_EXTERN_PREFIX): New.
+ * config/h8300/h8300.md (an anonymous pattern): Give an
+ internal name *tst_extzv_bitqi_1_n.
+ Accept bit_operand instead of bit_memory_operand.
+ Do not accept bit tests with the MSB.
+ (*tst_extzv_memqi_1_n): New.
- * config/i386/sol2.h (CPP_PREDEFINES): Add __PRAGMA_REDEFINE_EXTNAME.
- (HANDLE_PRAGMA_REDEFINE_EXTNAME): New.
- * config/sparc/sol2.h: Likewise.
+2002-11-28 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-22 Bob Wilson <bob.wilson@acm.org>
-
- * config/xtensa/xtensa-protos.h (non_acc_reg_operand): Remove.
- (xtensa_valid_move, xtensa_preferred_reload_class): Define.
- * config/xtensa/xtensa.c (non_acc_reg_operand): Remove.
- (xtensa_valid_move, xtensa_preferred_reload_class): Define to
- prevent use of sp as a reload register.
- (xtensa_emit_move_sequence): Use xtensa_valid_move instead of
- non_acc_reg_operand.
- * config/xtensa/xtensa.h (PREDICATE_CODES): Remove non_acc_reg_operand.
- (PREFERRED_RELOAD_CLASS): Move code to xtensa_preferred_reload_class.
- * config/xtensa/xtensa.md (movsi_internal, movhi_internal,
- movqi_internal): Use xtensa_valid_move instead of non_acc_reg_operand.
-
-2002-03-22 Jakub Jelinek <jakub@redhat.com>
-
- PR optimization/5854
- * config/m68hc11/m68hc11.h (CONST_OK_FOR_LETTER_VALUE_P): Use K for 0.
- Shut up warnings.
- (CONST_DOUBLE_OK_FOR_LETTER_P): Use G for 0.0.
- (EXTRA_CONSTRAINT): Use S for non-push memory operand.
- * config/m68hc11/m68hc11.c (m68hc11_split_move): Handle setting from
- const0 if scratch register was not allocated.
- (m68hc11_reload_operands, m68hc11_gen_lowpart, m68hc11_gen_highpart,
- m68hc11_z_replacement): Replace gen_rtx (CONST_INT, VOIDmode, ...)
- with GEN_INT (...).
- (m68hc11_reorg): Compute BLOCK_FOR_INSN before reload_cse_regs.
- * config/m68hc11/m68hc11.md: Replace gen_rtx (CONST_INT, VOIDmode, ...)
- with GEN_INT (...) everywhere. Remove constraints in define_split
- patterns.
- (movdi_internal, movdf_internal, movsi_internal, movsf_internal): Don't
- require scratch register for setting 0 into regs/non-pushable memory.
+ * config/h8300/h8300.c (h8300_eightbit_constant_address_p):
+ Fix a comment typo.
+ (h8300_tiny_constant_address_p): Likewise.
-2002-03-22 Alexandre Oliva <aoliva@redhat.com>
+2002-11-28 Michael Matz <matz@suse.de>
- * flow.c (calculate_global_regs_live): Clear aux fields of
- ENTRY and EXIT.
+ * doc/passes.texi: Mention the other register allocator.
-2002-03-22 Jakub Jelinek <jakub@redhat.com>
+2002-11-28 Kazu Hirata <kazu@cs.umass.edu>
- * config/v850/v850.c (v850_reorg): Only call alter_subreg on
- REG or MEM subregs, pass rtx * instead of rtx to it.
- * config/i860/i860.c (output_delayed_branch, output_delay_insn): Pass
- rtx * instead of rtx to alter_subreg.
- * config/m32r/m32r.c (gen_split_move_double): Likewise.
- * config/pj/pj.c (pj_output_rval): Likewise.
+ * config/h8300/h8300.md (6 new peephole2 patterns): New.
-2002-03-22 Richard Henderson <rth@redhat.com>
+2002-11-28 Jakub Jelinek <jakub@redhat.com>
- PR target/3177
- * config/ia64/ia64.h (CUMULATIVE_ARGS): Add int_regs.
- (INIT_CUMULATIVE_ARGS, INIT_CUMULATIVE_INCOMING_ARGS): Update.
- * config/ia64/ia64.c (ia64_function_arg_advance): Set int_regs.
- (ia64_expand_prologue): Look at int_regs, not words, for number
- of incomming int regs.
+ * config.gcc (x86_64-*-linux*) [tmake_file]: Remove i386/t-crtstuff.
+ * config/t-linux (CRTSTUFF_T_CFLAGS_S): Add $(CRTSTUFF_T_CFLAGS).
+ * config/i386/t-linux64 (CRTSTUFF_T_CFLAGS): Define.
-Fri Mar 22 16:00:06 CET 2002 Jan Hubicka <jh@suse.cz>
+2002-11-28 Kazu Hirata <kazu@cs.umass.edu>
- * cfgcleanup.c (outgoing_edges_math): Fix condition; relax
- frequencies match; avoid match on different loop depths.
- (try_crossjump_to_bb): Kill tests that no longer brings time
- savings.
- * cfgrtl.c (force_nonfallthru_and_redirect): Fix loop_depth
- updating code.
- (split_edge): Likewise.
+ * config/h8300/h8300.c (h8300_and_costs): New.
+ * config/h8300/h8300.h (RTX_COSTS): Use h8300_and_costs.
+ * config/h8300/h8300-protos.h: Add a prototype for
+ h8300_and_costs.
-2002-03-21 Richard Henderson <rth@redhat.com>
+2002-11-27 Zack Weinberg <zack@codesourcery.com>
- PR target/5996
- * fixinc/inclhack.def (solaris_stdio_tag): New.
- * fixinc/fixincl.x: Regenerate.
+ * config/rs6000/rs6000.c (altivec_init_builtins): Make the
+ pointer argument in the prototypes of the following builtins
+ be (const TYPE *) rather than (TYPE *):
+ + __builtin_altivec_ld_internal_4sf
+ + __builtin_altivec_ld_internal_4si
+ + __builtin_altivec_ld_internal_8hi
+ + __builtin_altivec_ld_internal_16qi
+ + __builtin_altivec_lvsl
+ + __builtin_altivec_lvsr
+ + __builtin_altivec_lvebx
+ + __builtin_altivec_lvehx
+ + __builtin_altivec_lvewx
+ + __builtin_altivec_lvxl
+ + __builtin_altivec_lvx
+ + __builtin_altivec_dst
+ + __builtin_altivec_dstt
+ + __builtin_altivec_dstst
+ + __builtin_altivec_dststt
-2002-03-21 Eric Botcazou <ebotcazou@multimania.com>
+2002-11-27 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- PR c/5597
- * c-typeck.c (process_init_element): Flag non-static
- initialization of a flexible array member as illegal.
+ * except.c (default_exception_section): Move variable into the
+ scope where it is used.
-2002-03-22 Alan Modra <amodra@bigpond.net.au>
+2002-11-27 Krister Walfridsson <cato@df.lth.se>
- * config/rs6000/t-linux64: New.
- * config.gcc (powerpc64-*-linux* <tmake_file>): Drop t-ppcos and
- t-ppccomm. Use t-rs6000 and t-linux64.
- (powerpc64-*-gnu* <tmake_file>): Likewise.
- * mklibgcc.in (SHLIB_MKMAP_OPTS): New variable.
- * mkmap-symver.awk (dotsyms): If set, output .foo as well as foo.
- * Makefile.in (SHLIB_MKMAP_OPTS): Pass to mklibgcc.
+ * config.gcc (*-*-netbsd[2-9]*, *-*-netbsdelf[2-9]*): Test for
+ correct version.
-2002-03-21 Aldy Hernandez <aldyh@redhat.com>
+2002-11-27 Kazu Hirata <kazu@cs.umass.edu>
- * langhooks.c (lhd_tree_inlining_cannot_inline_tree_fn): Check
- flag_really_no_inline instead of optimize == 0.
+ * config/h8300/h8300.h (OK_FOR_U): Remove extra parentheses.
- * c-objc-common.c (c_cannot_inline_tree_fn): Same.
+2002-11-27 Kazu Hirata <kazu@cs.umass.edu>
- * cp/tree.c (cp_cannot_inline_tree_fn): Same.
+ * config/h8300/h8300.c (h8300_shift_costs): New.
+ * config/h8300/h8300.h (RTX_COSTS): Use h8300_shift_costs.
+ * config/h8300/h8300-protos.h: Add a prototype for
+ h8300_shift_costs.
- * flags.h (flag_really_no_inline): New.
+2002-11-27 Jim Wilson <wilson@redhat.com>
- * c-common.c (c_common_post_options): Initialzie
- flag_really_no_inline.
+ * config/rs6000/spe.md (spu_evsplatfi, spu_evsplati): Swap operands
+ in output template.
- * toplev.c (flag_really_no_inline): New.
+2002-11-27 Casper S. Hornstrup <chorns@users.sourceforge.net>
-2002-03-21 Jakub Jelinek <jakub@redhat.com>
+ * config/i386/i386.h (DLL_IMPORT_EXPORT_PREFIX): Define.
+ * config/i386/winnt.c (i386_pe_dllexport_name_p): Use
+ DLL_IMPORT_EXPORT_PREFIX, not '@'.
+ (i386_pe_dllimport_name_p): Likewise.
+ (i386_pe_mark_dllexport): Likewise.
+ (i386_pe_mark_dllimport): Likewise.
+ (i386_pe_encode_section_info): Likewise.
+ (i386_pe_strip_name_encoding): Likewise.
- * config/avr/avr.md (length): Fix length computation for
- conditional branches.
+2002-11-27 Richard Henderson <rth@redhat.com>
-2002-03-21 Richard Henderson <rth@redhat.com>
+ * mkmap-symver.awk (BEGIN): Set sawsymbol false.
+ (nm && NF == 3): Set sawsymbol true.
+ (END): Exit if no symbols seen.
+ (output): Fix map syntax error if no globals for the version.
- * config/rs6000/rs6000.c (rs6000_select_rtx_section): Put symbolic
- constants in .data when -fpic.
+2002-11-27 Jan Hubicka <jh@suse.cz>
-2002-03-21 Tom Tromey <tromey@redhat.com>
+ * builtins.def (DEF_C99_BUILTIN): Fix.
- * config/i386/sol2.h (ASM_QUAD): Undef. Fixes PR bootstrap/5948.
+2002-11-26 Andrew Haley <aph@redhat.com>
-2002-03-21 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+ * unwind-sjlj.c (_Unwind_FindEnclosingFunction): Rename
+ from_Unwind_Find_Enclosing_Function.
+ * unwind-dw2.c (_Unwind_FindEnclosingFunction): Likewise.
+ * config/ia64/unwind-ia64.c (_Unwind_FindEnclosingFunction): Likewise.
+ * libgcc-std.ver (_Unwind_FindEnclosingFunction): Rename from
+ _Unwind_Find_Enclosing_Function, export @@GCC_3.3.
+ * unwind.h (_Unwind_FindEnclosingFunction): Add.
- * doc/contrib.texi (Contributors): Use GNU/Linux instead of Linux
- where appropriate.
+2002-11-26 Hartmut Penner <hpenner@de.ibm.com>
-Thu Mar 21 09:50:48 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * config/s390/s390.c (390_output_constant_pool): Set alignment
+ before label in 64 bit mode, behind otherwise.
- * config/ia64/ia64.c (hfa_element_mode, case ARRAY_TYPE): Recurse.
+2002-11-26 Richard Henderson <rth@redhat.com>
- * expr.c (emit_group_store): Don't copy const0_rtx to a CONCAT.
+ * c-common.c (handle_visibility_attribute): Accept "default".
+ * tree.h (enum symbol_visibility): New.
+ (decl_visibility): Declare.
+ * target.h (gcc_target.visibility): Take visibility arg as integer.
+ * varasm.c (default_assemble_visibility): Likewise.
+ (decl_visibility): New.
+ (maybe_assemble_visibility): Use it.
+ * output.h (default_assemble_visibility): Update prototype.
+ * config/rs6000/rs6000.c (rs6000_assemble_visibility): Take
+ visibility arg as integer.
+ * doc/extend.texi: Document default visibility.
-2002-03-21 Eric Botcazou <ebotcazou@multimania.com>
- Richard Henderson <rth@redhat.com>
+2002-11-26 Kazu Hirata <kazu@cs.umass.edu>
- PR c/5354:
- * c-common.c (c_expand_expr): Preserve result of a statement
- expression if needed.
+ * config/h8300/h8300.c: Adjust spacing.
+ * config/h8300/h8300.h: Likewise.
-2002-03-21 Jakub Jelinek <jakub@redhat.com>
+2002-11-26 Richard Henderson <rth@redhat.com>
+
+ * hooks.c (hook_bool_void_false, hook_void_tree_int,
+ hook_void_FILEptr_constcharptr): Rename so that the return
+ type is first.
+ (hook_int_tree_tree_1, hook_void_tree, hook_void_tree_treeptr,
+ hook_bool_tree_false): New.
+ * hooks.h: Update.
+ * langhooks-def.h: Update for renames.
+ * target-def.h: Likewise.
+ * tree.c (default_comp_type_attributes,
+ default_set_default_type_attributes, default_insert_attributes,
+ default_function_attribute_inlinable_p,
+ default_ms_bitfield_layout_p): Remove.
+ * tree.h: Update.
+
+2002-11-26 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa-protos.h (function_value): New prototype.
+ * pa.c (function_value): Use a PARALLEL to return small aggregates on
+ TARGET_64BIT.
+ * pa.h (FUNCTION_VALUE): Use function_value.
+ * pa.md (call_value_internal_symref, call_value_internal_reg_64bit,
+ call_value_internal_reg, sibcall_value_internal_symref,
+ sibcall_value_internal_symref_64bit): Remove =rf constraint on return
+ value.
- PR bootstrap/4195
- * genrecog.c (maybe_both_true_mode): Remove.
- (maybe_both_true_2, write_switch): Revert 2001-07-17 changes.
- * machmode.def (Pmode): Likewise.
+2002-11-26 John David Anglin <dave@hiauly1.hia.nrc.ca>
-2002-03-21 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+ * expr.c (gen_group_rtx, emit_group_move): New functions.
+ * expr.h (gen_group_rtx, emit_group_move): Prototype.
+ * function.c (expand_function_start): Use gen_group_rtx to create a
+ PARALLEL rtx to hold the return value when the real return rtx is a
+ PARALLEL.
+ (expand_function_end): Use emit_group_move to move the return value
+ from a PARALLEL to the real return registers.
+ * rtl.h (REG_FUNCTION_VALUE_P): Allow function values to be returned
+ in PARALLELs.
- * fixinc/inclhack.def (alpha_assert): Fix assert macro in Tru64
- UNIX assert.h.
- * fixinc/fixincl.x: Regenerate.
+2002-11-26 Jason Thorpe <thorpej@wasabisystems.com>
-2002-03-20 Jason Merrill <jason@redhat.com>
+ * config/t-libc-ok: Fix typo.
- * config/i386/cygwin.h (DWARF2_UNWIND_INFO): Define to 0.
+2002-11-26 Jakub Jelinek <jakub@redhat.com>
-2002-03-20 Bob Wilson <bob.wilson@acm.org>
+ * configure.in: Move AC_CANONICAL_SYSTEM and AC_ARG_PROGRAM back
+ before AC_PROG_CC.
+ * configure: Rebuilt.
- * config/xtensa/xtensa.h (ASM_OUTPUT_POOL_PROLOGUE): Emit a
- ".literal_position" directive before the constant pool.
+2002-11-26 Nathan Sidwell <nathan@codesourcery.com>
-2002-03-20 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+ * c-decl.c: (start_struct): Commonize flag setting.
- * doc/contrib.texi (Contributors): Update Geoffrey Keating.
- Add Craig Rodrigues.
- Add Brad Lucier to testers.
+2002-11-26 Jason Thorpe <thorpej@wasabisystems.com>
-2002-03-20 Jakub Jelinek <jakub@redhat.com>
+ * config/rs6000/rs6000.h (RS6000_CPU_CPP_ENDIAN_BUILTINS): New.
+ * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Use
+ RS6000_CPU_CPP_ENDIAN_BUILTINS.
+ * config/rs6000/netbsd.h (RS6000_CPU_CPP_ENDIAN_BUILTINS): Redefine.
- PR target/4792
- * config/arc/arc.md (movsicc, movdicc, movsfcc, movdfcc): Add mode
- to if_then_else.
- (movsicc_insn, movdicc_insn, movsfcc_insn, movdfcc_insn): Likewise.
- * config/arc/arc.c (arc_final_prescan_insn): Use extract_insn_cached
- instead of insn_extract.
+2002-11-26 Hartmut Penner <hpenner@de.ibm.com>
-2002-03-20 Jakub Jelinek <jakub@redhat.com>
+ * config/s390/s390.md (literal_pool_64, literal_pool_31 ): New
+ insns.
+ * config/s390/s390.c (struct machine_function): Introduction of
+ struct machine_function.
+ (s390_output_symbolic_const): Use of cfun.
+ (s390_optimize_prolog): Likewise.
+ (s390_fixup_clobbered_return_reg): Likewise.
+ (s390_frame_info): Likewise.
+ (s390_emit_prologue, s390_emit_epilogue): Likewise.
+ (s390_init_machine_status): New function.
+ (override_options): call s390_init_machine_status.
+ * config/s390/s390-protos.h (s390_output_constant_pool): Changed
+ prototype.
- PR bootstrap/4192
- * config/fr30/fr30.md (jump): Remove clobber of fixed register.
+2002-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ * varasm.c (output_constant_pool): For pool constants in mergeable
+ section ensure each constant is padded to multiple of entity size.
+
+2002-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ * varasm.c (default_exception_section): Move to...
+ * except.c (default_exception_section): ... here. Make
+ .gcc_except_table read-only if it is not expected to have any
+ dynamic relocations and linker handles it.
+ * dwarf2out.c (default_eh_frame_section): Make .eh_frame read-only
+ if it is not expected to have any dynamic relocations and linker
+ handles it.
+ * configure.in (HAVE_LD_RO_RW_SECTION_MIXING): Check what ld does
+ when linking read-only and read-write sections together.
+ * configure, config.in: Rebuilt.
+ * crtstuff.c (EH_FRAME_SECTION_CONST): Define.
+ (__EH_FRAME_BEGIN__, __FRAME_END__): Add it.
+
+2002-11-25 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/spe.h (__ev_create_sfix32_fs): Change macro into
+ new function.
+ (__ev_create_ufix32_fs): Same.
+ (__ev_get_sfix32_fs_internal): New.
+ (__ev_get_sfix32_fs): Define to use function.
+ (__ev_get_ufix32_fs_internal): New.
+ (__ev_get_ufix32_fs): Define to use function.
+ (__ev_get_upper_ufix32_fs): Call __ev_get_ufix32_fs.
+ (__ev_get_lower_ufix32_fs): Same.
+ (__ev_get_upper_sfix32_fs): Call __ev_get_sfix32_fs.
+ (__ev_get_lower_sfix32_fs): Same.
+ (__ev_set_sfix32_fs_internal): New.
+ (__ev_set_ufix32_fs_internal): New.
+ (__ev_set_sfix32_fs): Call __ev_set_sfix32_fs_internal.
+ (__ev_set_ufix32_fs): Call __ev_set_ufix32_fs_internal.
+ (__ev_set_upper_sfix32_fs): Call function.
+ (__ev_set_lower_sfix32_fs): Same.
+ (__ev_set_upper_ufix32_fs): Same.
+ (__ev_set_lower_ufix32_fs): Same.
+
+2002-11-25 Douglas B Rupp <rupp@gnat.com>
+
+ * gcc.c (do_spec_1): Reset delete_this_arg to zero.
+
+2002-11-25 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/elfos.h (HANDLE_SYSV_PRAGMA): Define as 1.
+ * config/interix.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/linux-aout.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/lynx-ng.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/lynx.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/netbsd.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/openbsd.h (HANDLE_SYSV_PRAGMA: Likewise.
+ * config/alpha/elf.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/arm/netbsd.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/cris/aout.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/d30v/d30v.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/frv/frv.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/i386/djgpp.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/i386/i386-interix.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/i386/vxi386.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/ia64/ia64.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/m88k/m88k.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/mmix/mmix.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/rs6000/aix.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/rs6000/darwin.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/sparc/linux-aout.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/sparc/vxsparc64.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/stormy16/stormy16.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/alpha/osf.h (HANDLE_SYSV_PRAGMA): Don't undef before
+ defining.
+ * config/i386/sco5.h (HANDLE_SYSV_PRAGMA): Likewise.
+ * config/mips/iris5.h (HANDLE_SYSV_PRAGMA): Likewise.
+
+2002-11-25 Dave Pitts <dpitts@cozx.com>
+
+ * gcc/fixinc/mkfixinc.sh: add i370-*-openedition to bypass fixinc list
+
+2002-11-25 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/h8300.md (an anonymous pattern): New.
+
+2002-11-25 Richard Henderson <rth@redhat.com>
+
+ * alias.c (find_base_value): Use new_reg_base_value if it's live.
+ (copying_arguments): Make boolean.
+
+2002-11-25 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * gcc.c (static_spec_functions): Add if-exists-else spec
+ function.
+ (if_exists_else_spec_function): New function.
+ * doc/invoke.texi: Document the if-exists-else spec function.
- * genemit.c (output_added_clobbers_hard_reg_p): Only output return
- stmt if some case has been output.
+ * config/netbsd-elf.h (NETBSD_STARTFILE_SPEC): For -static, use
+ "%:if-exists-else(crtbeginT%O%s crtbegin%O%s)".
-2002-03-20 Jakub Jelinek <jakub@redhat.com>
+2002-11-25 Jason Thorpe <thorpej@wasabisystems.com>
- PR c/5972
- * config/i386/i386.md (movdicc_c_rex64, movsicc_noc, movhicc_noc,
- movsfcc_1, movdfcc_1): Add %O2.
- * config/i386/i386.c (print_operand): Handle %ON.
- Print . before float condition codes in Sun as cmov syntax.
- * config/i386/sol2.h (CMOV_SUN_AS_SYNTAX): Define for Sun as.
- * config.gcc (i[34567]86-*-solaris2*): Remove comment which is
- no longer true.
+ * config.gcc (powerpc-*-netbsd*): Replace "svr4.h" with
+ "netbsd.h netbsd-elf.h" in tm_file. Set tmake_file to
+ "${tmake_file} rs6000/t-netbsd".
+ * config/rs6000/netbsd.h: Rewrite.
+ * config/rs6000/t-netbsd: New file.
-2002-03-20 Philip Blundell <pb@nexus.co.uk>
+2002-11-25 Kazu Hirata <kazu@cs.umass.edu>
- * config/arm/arm.c (arm_output_epilogue): Don't generate separate
- return instruction if PC was popped.
+ * config/h8300/h8300.md (an anonymous pattern): Relax the
+ condition for the pattern.
-2002-03-20 Hans-Peter Nilsson <hp@bitrange.com>
+2002-11-25 Aldy Hernandez <aldyh@redhat.com>
- * config/mmix/mmix.md ("fixuns_truncdfdi2"): Use (unsigned_fix:DI
- (unsigned_fix:DF op1)), not (unsigned_fix:DI (fix:DF op1)).
- ("truncdfsf2"): Correct operator is float_truncate, not fix.
- ("*truncdfsf2_real"): Ditto.
- ("*nonlocal_goto_receiver_expanded"): Fix output template formatting.
+ * config/rs6000/rs6000.h (enum rs6000_builtins): Remove evmwlssf,
+ evmwlsmf, evmwlssfa, evmwlsmfa, evmwlssfaaw, evmwlsmfaaw,
+ evmwlssfanw, evmwlsmfanw.
- * config/mmix/mmix.h (WCHAR_TYPE, WCHAR_TYPE_SIZE): Don't define.
+ * config/rs6000/rs6000.c (bdesc_2arg): Same.
-2002-03-19 Jim Blandy <jimb@redhat.com>
+ * config/rs6000/spe.md: Same for patterns.
- * c-lex.c (cb_file_change): Pass the #inclusion's line number to
- the start_source_file debug hook, not the current line number.
+2002-11-25 Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de>
- * cppmacro.c (cpp_macro_definition): Emit a space after the macro
- name, even if the replacement list contains no tokens, as required
- by Dwarf.
+ PR c/8639
+ * fold-const.c (extract_muldiv): Don't propagate division unless
+ both arguments are multiples of C.
-2002-03-19 David Edelsohn <edelsohn@gnu.org>
+2002-11-25 Andrew Haley <aph@redhat.com>
- * config/rs6000/rs6000.c (rs6000_override_options): Only warn
- about -fpic/-fPIC if extra_warnings set.
+ * libgcc-std.ver (_Unwind_Find_Enclosing_Function): Add.
+ * config/ia64/unwind-ia64.c (_Unwind_Find_Enclosing_Function): New.
+ * unwind-sjlj.c (_Unwind_Find_Enclosing_Function): Likewise.
+ * unwind-dw2.c (_Unwind_Find_Enclosing_Function): Likewise.
-2002-03-19 Richard Henderson <rth@redhat.com>
+2002-11-24 Kazu Hirata <kazu@cs.umass.edu>
- * flow.c (EH_USES): Provide default.
- (calculate_global_regs_live): Use it for EH edges and noreturn calls.
- * doc/tm.texi (EH_USES): New.
+ * config/h8300/h8300.c (h8300_init_once): Fix a typo in the
+ target help message.
- * config/ia64/ia64.c (ia64_eh_uses): New.
- * config/ia64/ia64-protos.h: Update.
- * config/ia64/ia64.h (EH_USES): New.
+2002-11-24 Jason Thorpe <thorpej@wasabisystems.com>
-2002-03-20 Alan Modra <amodra@bigpond.net.au>
+ * config.gcc (*-*-netbsd*1.[7-9]*, *-*-netbsd*[2-9]*): Set
+ extra_parts to "crtbegin.o crtend.o crtbeginS.o crtendS.o
+ crtbeginT.o".
+ (arm*-*-netbsd*, i[34567]86-*-netbsd*, m68k*-*-netbsd*)
+ (ns32k-*-netbsd*, sparc-*-netbsd*, vax-*-netbsd*): Set extra_parts
+ to "" for a.out configurations.
+ * config/t-netbsd (CRTSTUFF_T_CFLAGS): Set to "-fPIC".
- * defaults.h (SUPPORTS_WEAK): Set if ASM_WEAKEN_DECL.
- * varasm.c (assemble_alias): Use ASM_WEAKEN_DECL.
- * doc/tm.texi (ASM_WEAKEN_DECL): Document.
- (ASM_WEAKEN_LABEL): Mention ASM_WEAKEN_DECL.
- (SUPPORTS_WEAK): Likewise.
+2002-11-24 Jason Thorpe <thorpej@wasabisystems.com>
-2002-03-19 Richard Henderson <rth@redhat.com>
+ * config/alpha/netbsd.h (CPP_SUBTARGET_SPEC): Just use
+ NETBSD_CPP_SPEC directly.
+ (SUBTARGET_EXTRA_SPECS): Remove netbsd_cpp_spec. Add
+ netbsd_endfile_spec.
+ (ENDFILE_SPEC): Use %(netbsd_endfile_spec).
- PR 5879
- * except.c (current_function_has_exception_handlers): New.
- * except.h: Declare it.
- * sibcall.c (optimize_sibling_and_tail_recursive_call): Use it.
- Combine tests that disable all sibcalls for the function.
+2002-11-24 Jason Thorpe <thorpej@wasabisystems.com>
-2002-03-19 Richard Henderson <rth@redhat.com>
+ * config/netbsd-elf.h (STARTFILE_SPEC): Rename to
+ NETBSD_STARTFILE_SPEC.
+ (STARTFILE_SPEC): Redefine in terms of NETBSD_STARTFILE_SPEC.
+ (ENDFILE_SPEC): Likewise.
+ * config/netbsd.h (LIB_SPEC, LIBGCC_SPEC): Likewise.
- PR 5977, 5991
- * config/ia64/ia64.c: Revert 2002-03-01 patch.
- * config/ia64/ia64.h (INIT_EXPANDERS): New.
+2002-11-24 Andreas Schwab <schwab@suse.de>
-2002-03-19 Olivier Hainque <hainque@act-europe.fr>
+ * Makefile.in (install-driver): Remove versioned link before
+ trying to create it.
- * varasm.c (output_constant_def): Don't call ENCODE_SECTION_INFO
- for INTEGER_CST.
+ * config/m68k/m68k.c: Fix typo in last change defining
+ TARGET_ASM_CAN_OUTPUT_MI_THUNK.
-2002-03-19 Jason Merrill <jason@redhat.com>
+2002-11-23 Kazu Hirata <kazu@cs.umass.edu>
- * varasm.c (globalize_decl): Get the name from the RTL, not
- DECL_ASSEMBLER_NAME.
+ * config/h8300/h8300.c (print_operand): Update the use of
+ h8300_tiny_constant_address_p.
+ (h8300_adjust_insn_length): Likewise.
+ (h8300_tiny_constant_address_p): Check if the given rtx is a
+ variable declared with __attribute__ ((tiny_data)).
- * Makefile.in (LIBGCC2_DEBUG_CFLAGS): Set to -g.
+2002-11-22 Dale Johannesen <dalej@apple.com>
-2002-03-19 Dale Johannesen <dalej@apple.com>
+ * toplev.c (rest_of_compilation): Fix comments.
- PR optimization/5999, middle-end/5731
- * expr.c (expand_expr) [RDIV_EXPR]: Only convert real divisions into
- multiplications by reciprocals.
+2002-11-22 Geoffrey Keating <geoffk@apple.com>
-2002-03-19 Bob Wilson <bob.wilson@acm.org>
+ * aclocal.m4 (ac_cv_func_mmap_dev_zero): Darwin does not
+ allow mmap from /dev/zero. Don't make decisions for the host
+ based on presence or absence of /dev/zero on the build machine.
+ (ac_cv_func_mmap_anon): Darwin does have working MMAP_ANON.
+ (AC_FUNC_MMAP_FILE): Darwin does have mmap of a file.
+ * configure: Regenerate.
- * config/xtensa/xtensa.md (adddi3, adddi_carry, subdi3,
- subdi_carry): Define.
+2002-11-22 Daniel Jacobowitz <drow@mvista.com>
-Tue Mar 19 14:12:32 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * gcc.c (make_relative_prefix, split_directories)
+ (free_split_directories): Removed.
- * config/sparc/sparc.h (CAN_ELMINIATE): Can only eliminate FP
- in favor of SP if FRAME_POINTER_REQUIRED is false.
+2002-11-22 Daniel Jacobowitz <drow@mvista.com>
-2002-03-19 Jakub Jelinek <jakub@redhat.com>
+ * configure.in: Set insn=nop for DWARF-2 tests on ARM.
+ * configure: Regenerated.
- PR c/5656
- * langhooks.h (struct lang_hooks_for_tree_inlining): Add
- convert_parm_for_inlining.
- * c-lang.c (LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING):
- Define.
- * langhooks-def.h: Likewise.
- * objc/objc-lang.c: Likewise.
- * langhooks.c (lhd_tree_inlining_convert_parm_for_inlining): New
- function.
- * tree-inline.c (initialize_inlined_parameters):
- Call convert_parm_for_inlining lang hook if needed.
- * c-typeck.c (c_convert_parm_for_inlining): New function.
- * c-tree.h (c_convert_parm_for_inlining): Add prototype.
+2002-11-22 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * config/h8300/h8300.c (compute_a_shift_length): Fix the insn
+ length computation when xor.l is output.
- * gcse.c (insert_insn_end_bb): Fix typo in last change.
+2002-11-21 Jim Wilson <wilson@redhat.com>
-2002-03-18 Mark Mitchell <mark@codesourcery.com>
+ * config/rs6000/rs6000.c (function_arg): Set inner mode of SPE
+ vectors to SI.
- * calls.c (precompute_arguments): Do not assume that temporaries
- can be destroyed after expanding the argument.
- (expand_call): Likewise.
+2002-11-21 Bob Wilson <bob.wilson@acm.org>
-2002-03-18 Ashif Harji <asharji@uwaterloo.ca>
+ * config/xtensa/xtensa-protos.h (xtensa_copy_incoming_a7): Declare.
+ * config/xtensa/xtensa.c (struct machine_function): Add
+ incoming_a7_copied flag.
+ (xtensa_copy_incoming_a7): Define.
+ (xtensa_emit_move_sequence): Use xtensa_copy_incoming_a7.
+ * config/xtensa/xtensa.md (movdi, movsf, movdf): Ditto.
- * gcc.c (struct compiler default_compilers): Add
- -no-integrated-cpp flag to invoke an external cpp.
- (struct option_map option_map[]): Likewise.
- * objc/lang-specs.h (struct compiler default_compilers): Add
- -no-integrated-cpp flag to invoke an external cpp.
- * doc/invoke.texi: Document -no-integrated-cpp flag.
+2002-11-21 Jan Hubicka <jH@suse.cz>
-2002-03-18 Alan Modra <amodra@bigpond.net.au>
- David Edelsohn <edelsohn@gnu.org>
+ * i386-protos.h (x86_64_sign_extended_value): Fix prototype.
+ * i386.c (x86_64_general_operand, x86_64_szext_general_operand,
+ x86_64_nonmemory_operand, x86_64_movabs_operand,
+ x86_64_szext_nonmemory_operand, x86_64_immediate_operand,
+ ix86_expand_int_movcc): Update call of x86_64_sign_extended_value.
+ (local_symbolic_operand): Do not care the 64bit limits.
+ (x86_64_sign_extended_value): Remove allow_rip support.
+ (legitimate_pic_address_disp_p): Handle all cases allowed
+ with RIP addressing.
+ (legitimate_address_p): Use legitimate_pic_address_disp_p for PIC.
+ (legitimize_pic_address): Reorganize.
+ * i386.h (EXTRA_CONSTRAINT): Update call of x86_64_sign_extended_value.
- * c-pragma.h (HANDLE_PRAGMA_WEAK): Define if ASM_WEAKEN_DECL too.
- * config/rs6000/linux64.h (ASM_DECLARE_FUNCTION_NAME): Don't emit
- .weak for code sym. Do emit .size for descriptor sym.
- (ASM_DECLARE_FUNCTION_SIZE): Define.
- * config/rs6000/rs6000.h (ASM_WEAKEN_DECL): Define.
- (ASM_OUTPUT_DEF_FROM_DECLS): Don't emit .weak here. Don't output
- .lglobl unless TARGET_XCOFF. Formatting fixes.
- (PREDICATE_CODES): Add any_operand and zero_constant.
- (HANDLE_PRAGMA_PACK): Delete.
- * config/rs6000/xcoff.h (ASM_DECLARE_FUNCTION_NAME): Don't emit
- .weak for code sym.
- (HANDLE_PRAGMA_WEAK): Remove.
- (ASM_WEAKEN_LABEL): Remove.
- (COLLECT_EXPORT_LIST): Delete.
- * config/rs6000/aix.h (HANDLE_SYSV_PRAGMA): Define.
- * config/rs6000/darwin.h (HANDLE_SYSV_PRAGMA): Define.
+2002-11-21 Jason Thorpe <thorpej@wasabisystems.com>
-2002-03-18 Bob Wilson <bob.wilson@acm.org>
+ * config.gcc (arm*-*-netbsdelf*): Enable configuration.
+ * config/arm/netbsd-elf.h: New file.
- * config/xtensa/xtensa.h (GO_IF_MODE_DEPENDENT_ADDRESS): Treat
- constant-pool addresses as "mode-dependent".
+2002-11-21 Jason Thorpe <thorpej@wasabisystems.com>
-Mon Mar 18 18:12:48 CET 2002 Jan Hubicka <jh@suse.cz>
+ * config/arm/elf.h (SUBTARGET_EXTRA_SPECS): Add
+ subtarget_asm_float_spec.
+ (SUBTARGET_ASM_FLOAT_SPEC): Define, moving the
+ defaults from...
+ (ASM_SPEC): ...here. Use subtarget_asm_float_spec.
- * i386.c (override_options): Disallow preferred_stack_boundary to be
- less than 16 bytes
- (construct_container): Fix end of array check.
- (ix86_va_start): Force alignemnt to be 16 bytes.
+2002-11-21 Nick Clifton <nickc@redhat.com>
- * linux64.h (MULTILIB_DEFAULTS): Set to "m64".
- (t-linux64): Add multilibing
+ * config/fr30/fr30.md (movsf_constant_store): Move code to
+ detect 0.0 into fr30.c.
+ * config/fr30/fr30-protos.h (fr30_const_double_is_zero):
+ Prototype.
+ * config/fr30/fr30.c (fr30_const_double_is_zero): New
+ function. Return true if the rtx is 0.0.
- * i386.h (PROMOTE_PROTOTYPES): Set to 0 for x86_64.
+2002-11-21 Jason Thorpe <thorpej@wasabisystems.com>
- * gcse.c (hash_scan_set): Refuse instructions with EH edges.
+ * config/arm/elf.h (ASM_SPEC, LINK_SPEC): Pass -EL
+ if -mlittle-endian is specified.
- * basic-block.h (fixup_abnormal_edges): Declare.
- * reload1.c (fixup_abnormal_edges): Make global.
- * reg-stack.c (convert_regs): Use it.
+2002-11-21 Richard Earnshaw <rearnsha@arm.com>
- * gcse.c (insert_insn_end_bb): Handle trapping insns.
+ PR optimization/2903
+ * arm.md (anddi_notzesidi_di): Operand 2 is inverted not operand 1.
+ (anddi_notsesidi_di): Likewise.
- * reload1.c (reload_cse_delete_noop_set): Purge dead edges.
+2002-11-21 Kazu Hirata <kazu@cs.umass.edu>
- * recog.c (peephole2_optimize): Re-distribute EH edges.
+ * config/h8300/h8300.c (print_operand): Use
+ h8300_eightbit_constant_address_p and
+ h8300_tiny_constant_address_p.
+ (h8300_adjust_insn_length): Likewise.
+ * config/h8300/h8300.h (EIGHTBIT_CONSTANT_ADDRESS_P): Remove.
+ (TINY_CONSTANT_ADDRESS_P): Likewise.
+ (OK_FOR_U): Use eightbit_constant_address_p.
-2002-03-18 Jason Merrill <jason@redhat.com>
+2002-11-21 Ulrich Weigand <uweigand@de.ibm.com>
- * configure.in: Disable checking by default on release branch.
+ * config/s390/libgcc-libc.ver: Add multilib support.
+ * config/s390/linux.h (MULTILIB_DEFAULT): Define.
+ * config/s390/t-linux64 (MULTILIB_OPTIONS, MULTILIB_DIRNAMES,
+ MULTILIB_OSDIRNAMES, LIBGCC, INSTALL_LIBGCC,
+ EXTRA_MULTILIB_PARTS): Define.
-2002-03-18 Jakub Jelinek <jakub@redhat.com>
+2002-11-21 Richard Earnshaw <rearnsha@arm.com>
- PR target/5740
- * expr.c (emit_group_load): Use extract_bit_field if
- needed for CONCAT arguments.
+ * arm.c (arm_get_frame_size): A leaf function does not need its
+ stack padding to an aligned boundary if it has no frame.
+ (thumb_get_frame_size): Likewise.
-2002-03-18 Richard Earnshaw <rearnsha@arm.com>
+2002-11-20 Steve Ellcey <sje@cup.hp.com>
- PR target/4863
- * arm.md (tablejump): Make this a define_expand. For PIC add the
- offset to the base of the table.
- (thumb_tablejump): Matcher for Thumb tablejump insn.
- * config/arm/aout.h (ASM_OUTPUT_ADDR_DIFF_ELT): Output thumb entries
- as the difference of two labels.
- * config/arm/aof.h (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
- * config/arm/elf.h (JUMP_TABLES_IN_TEXT_SECTION): Only put ARM jump
- tables in the code.
- * config/arm/coff.h (JUMP_TABLES_IN_TEXT_SECTION): Likewise.
- * arm.c (get_jump_table_size): If the table is not in the text
- section, return zero.
+ * emit-rtl.c (gen_reg_rtx): Simplify mapping of Complex type
+ to component type using GET_MODE_INNER.
+ * expr.c (emit_move_insn_1): Ditto.
+ * optabs.c (expand_binop): Ditto.
+ (expand_unop): Ditto.
+ (expand_complex_abs): Ditto.
-2002-03-17 Richard Henderson <rth@redhat.com>
+2002-11-20 Douglas B Rupp <rupp@gnat.com>
- * config/alpha/alpha.c (alpha_emit_set_const_1): Build add insns
- explicitly.
+ * hwint.h (HAVE___INT64): Fix typo (was HAVE__INT64).
-2002-03-17 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+2002-11-20 DJ Delorie <dj@redhat.com>
- * ifcvt.c (dead_or_predicable): Fix uninitialized variable.
+ * config/stormy16/stormy16.c (s16builtins,
+ xstormy16_init_builtins, xstormy16_expand_builtin): New.
+ * config/stormy16/stormy16.md (divmodhi4, sdivlh, udivlh): New.
-2002-03-17 David Edelsohn <edelsohn@gnu.org>
+2002-11-20 Hans-Peter Nilsson <hp@bitrange.com>
- * expr.c (expand_expr): Sign-extend CONST_INT generated from
- TREE_STRING_POINTER.
+ * Makefile.in (RUN_GEN, VALGRIND_DRIVER_DEFINES): New variables.
+ (DRIVER_DEFINES): Add $(VALGRIND_DRIVER_DEFINES).
+ (executing gencheck, genconfigs, genconditions, genflags,
+ gencodes, genconstants, genemit, genrecog, genopinit, genextract,
+ genpeep, genattr, genattrtab, genoutput, gengenrtl, genpreds,
+ gengtype, genprotos): Prepend $(RUN_GEN).
+ * configure.in: Move host compiler tests before --enable-checking
+ tests.
+ (--enable-checking=valgrind): New.
+ * config.in, configure: Regenerate.
+ * cppfiles.c [!ENABLE_VALGRIND_CHECKING] (VALGRIND_DISCARD):
+ Define as empty.
+ (read_include_file): When doing the mmap+1 trick,
+ valgrind-annotate the byte after the mmap:ed area as readable.
+ (purge_cache): Remove above annotation.
+ * gcc.c (execute) [ENABLE_VALGRIND_CHECKING]: Arrange to prepend
+ VALGRIND_PATH -q to each command.
-2002-03-16 Richard Henderson <rth@redhat.com>
+ * ggc-common.c [!ENABLE_VALGRIND_CHECKING] (VALGRIND_DISCARD):
+ Define as empty.
+ (ggc_realloc): Update valgrind annotations.
+ * ggc-page.c [!ENABLE_VALGRIND_CHECKING] (VALGRIND_DISCARD):
+ Define as empty.
+ (alloc_anon, free_page, ggc_alloc, poison_pages): Add machinery to
+ valgrind-annotate memory.
- * config/ia64/ia64.c (ia64_attribute_table): Move before
- targetm definition. Make static.
+2002-11-20 Ulrich Weigand <uweigand@de.ibm.com>
-2002-03-16 Neil Booth <neil@daikokuya.demon.co.uk>
+ * recog.c (constrain_operands): Prefer exact match over reloadable
+ EXTRA_MEMORY_CONSTRAINT or EXTRA_ADDRESS_CONSTRAINT.
- * cppinit.c (print_help): Display -MD and -MMD.
- Don't display usage string. Update assertion syntax and
- typo.
+ * reload.c (find_reloads): Always reload EXTRA_ADDRESS_CONSTRAINT
+ operands in Pmode.
-2002-03-16 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+2002-11-20 Eric Botcazou <ebotcazou@libertysurf.fr>
- * config/m68hc11/m68hc11.c (m68hc11_override_options): Don't use
- soft registers by default for 68HC12.
- (m68hc11_conditional_register_usage): Don't use Z register for 68HC12
- when compiling with -fomit-frame-pointer.
- (expand_prologue): Use push/pop to allocate 4-bytes of locals on 68HC12.
- (expand_epilogue): Likewise.
- (m68hc11_gen_rotate): Use exg when rotating by 8.
-
-2002-03-16 Stephane Carrez <Stephane.Carrez@worldnet.fr>
-
- * config/m68hc11/m68hc11-protos.h (ix_reg): Declare.
- * config/m68hc11/m68hc11.md ("addsi3"): Use general_operand for sources.
- (splits): Remove unused add splits.
- ("*addhi3_68hc12"): Tune constraints.
- ("addhi_sp"): Try to use X instead of Y in all cases and if the
- constant fits in 8-bits and D is dead use abx/aby instructions.
- ("*addhi3"): Remove extern declaration of ix_reg.
- ("*subsi3"): Optimize and provide new split.
- ("subhi3"): Cleanup.
- ("*subhi3_sp"): Avoid saving X if we know it is dead.
- (arith splits): For 68hc12 save the address register on the stack
- and do the arithmetic operation with a pop.
-
-2002-03-16 Stephane Carrez <Stephane.Carrez@worldnet.fr>
-
- * config/m68hc11/m68hc11.md ("*movqi_68hc12"): Fix constraints, avoid
- allocating QImode in address registers.
- ("*movqi_m68hc11"): Likewise.
-
-2002-03-15 Mark Mitchell <mark@codesourcery.com>
-
- * expr.c (expand_expr): Revert previous change.
-
- * c-common.c (statement_code_p): Handle CLEANUP_STMT.
- * c-common.def (CLEANUP_STMT): New tree node.
- * c-common.h (CLEANUP_DECL): New macro.
- (CLEANUP_EXPR): Likewise.
- * c-semantics.c (expand_stmt): Handle CLEANUP_STMT.
- * expr.c (expand_expr): Tidy.
- * tree-dump.c (dequeue_and_dump): Handle CLEANUP_STMT.
- * tree-inline.c (initialize_inlined_parameters): Clean up
- new local variables.
-
-2002-03-15 Richard Henderson <rth@redhat.com>
-
- * c-decl.c: Include c-pragma.h.
- (start_decl, start_function): Invoke maybe_apply_pragma_weak.
- (finish_function): Tidy.
- * c-pragma.c: Include c-common.h.
- (pending_weaks, apply_pragma_weak, maybe_apply_pragma_weak): New.
- (handle_pragma_weak): Use them.
- (init_pragma): Register pending_weaks.
- * c-pragma.h (maybe_apply_pragma_weak): Declare.
- * print-tree.c (print_node): Print DECL_WEAK.
- * varasm.c (mark_weak_decls): Remove.
- (remove_from_pending_weak_list): Remove.
- (add_weak): Remove.
- (asm_emit_uninitialised): Call globalize_decl for weak commons.
- (weak_decls): Make a tree_list.
- (declare_weak): Cons weak_decls directly.
- (globalize_decl): Remove weak_decls elements directly.
- (weak_finish): Simplify weak_decls walk. Don't weaken unused
- symbols. Don't pretend to handle aliases.
- (init_varasm_once): Update weak_decls registry.
- * Makefile.in: Update dependencies.
-
-2002-03-15 Richard Henderson <rth@redhat.com>
-
- * config/alpha/alpha.c (alpha_va_arg): Manipulate the type
- size as a tree.
-
-2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
-
- * config/m68hc11/m68hc11.md ("tstqi_1"): Try to use ldab instead of tst.
- ("tstqi" split): Avoid using memory for tstqi on address register.
- (splits): Remove constraints.
- ("cmphi_1_hc12"): New from "cmphi_1" and tuned for 68HC12.
- ("cmpdf", "cmpsf"): Remove since not used.
- ("*tbeq", "*tbne", "*tbeq8", "*tbne8"): Also look in cc_status.value2.
- (peephole2): New peepholes to optimize tstqi and pre inc/dec addressing.
-
-2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
-
- * config/m68hc11/m68hc11.md ("negsi2"): Optimize inline case.
- ("neghi2"): Tighten constraints.
- ("one_cmplsi2"): Optimize and simplify split.
- * config/m68hc11/larith.asm (__negsi2): Likewise for library.
-
-2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
-
- * config/m68hc11/m68hc11.md ("logicalsi3_zexthi"): Fix constraints
- and split of AND operation to clear the upper bits.
- ("*logicalsi3_zextqi"): Likewise.
- ("*logicallhi3_zexthi_ashift8"): Likewise.
- ("*logicalsi3_silshr16"): Likewise.
- ("logicalsi3_silshl16"): Likewise.
- ("anddi3", "iordi3", "xordi3" splits): Remove constraints.
-
-2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
-
- * config/m68hc11/m68hc11.c (m68hc11_symbolic_p): New function.
- (m68hc11_indirect_p): New function.
- (m68hc11_override_options): Must set MASK_NO_DIRECT_MODE for 68HC12.
- (m68hc11_gen_highpart): Use TARGET_NO_DIRECT_MODE instead of
- TARGET_M6812.
- (asm_print_register): Likewise.
- * config/m68hc11/m68hc11-protos.h (m68hc11_symbolic_p): Declare.
- (m68hc11_indirect_p): Declare.
- * config/m68hc11/m68hc11.h (EXTRA_CONSTRAINT): New constraint 'R', 'Q'.
- (TARGET_NO_DIRECT_MODE, TARGET_RELAX): New.
- (TARGET_SWITCHES): New option -mrelax.
- * config/m68hc11/m68hc11.md ("andsi3"): Allow soft register for
- destination.
- ("iorsi3", "xorsi3"): Likewise.
- ("andhi3", "andqi3", "iorhi3", "iorqi3"): Use a define_expand.
- ("*andhi3_mem"): New to handle destination in memory with bclr
- and a scratch register.
- ("*andqi3_mem", "*iorhi3_mem", "*iorqi3_mem"): Likewise.
- ("*andhi3_const"): New when operand2 is constant.
- ("*andqi3_const", "*iorhi3_const", "*iorqi3_const"): Likewise.
- ("*andhi3_gen"): Cleanup of the old "andhi3".
- ("*andqi3_gen", "*iorhi3_gen", "*iorqi3_gen"): Likewise.
- ("xorqi3"): Update constraints.
-
-2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
-
- * config/m68hc11/m68hc11.c (m68hc11_small_indexed_indirect_p): Look
- for reg_equiv_memory_loc when the operand is a register that does
- not get a hard register (stack location).
- (tst_operand): After reload, accept all memory operand.
- (symbolic_memory_operand): Fix detection of symbolic references.
- * config/m68hc11/m68hc11.h (VALID_CONSTANT_OFFSET_P): For 68HC12
- accept symbols and any constant.
-
-2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
-
- * config/m68hc11/m68hc11.c (emit_move_after_reload): Add a REG_INC
- note on the insn that sets the soft frame register.
- (must_parenthesize): ix and iy are also reserved names.
- (print_operand_address): One more place where parenthesis are required
- to avoid confusion with register names.
- (m68hc11_gen_movhi): Allow push of stack pointer.
- (m68hc11_check_z_replacement): Fix handling of parallel with a
- clobber.
- (m68hc11_z_replacement): Must update the REG_INC notes to tell what
- the replacement register is.
- * config/m68hc11/m68hc11.h (REG_CLASS_CONTENTS): Switch Z_REGS
- and D8_REGS classes.
- (MODES_TIEABLE_P): All modes are tieable except QImode.
-
-2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
-
- * config/m68hc11/larith.asm (___adddi3): Optimize saving of result.
- (___subdi3): Likewise.
- (__mulsi3, __mulhi32): Avoid using _.tmp scratch location.
- (__map_data_section): Optimize 68hc11 case.
-
-2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
-
- * config/m68hc11/m68hc11.c (m6812_cost): Make cost of add higher
- than a shift to avoid adding a register with itself.
- (m68hc11_memory_move_cost): Take into account NO_REGS.
- (m68hc11_register_move_cost): Update and use memory move cost
- for soft registers.
- (m68hc11_address_cost): Make cost of valid offset not 0 so that
- it gives more opportunities to cse to optimize.
- * config/m68hc11/m68hc11.h (REGISTER_MOVE_COST): Pass the mode.
- * config/m68hc11/m68hc11-protos.h (m68hc11_register_move_cost): Update.
-
-2002-03-15 Jason Merrill <jason@redhat.com>
-
- * varasm.c (globalize_decl): New fn.
- (assemble_start_function): Use it.
- (asm_emit_uninitialized): Use it.
- (assemble_alias): Use it.
- (assemble_variable): Use it.
-
-2002-03-15 Jason Merrill <jason@redhat.com>
-
- * varasm.c (assemble_variable): Use zeros for a decl with DECL_INITIAL
- of error_mark_node.
-
-2002-03-15 Jakub Jelinek <jakub@redhat.com>
-
- PR bootstrap/4128
- * config/sparc/sparc.c (gen_v9_scc): Move early clobber test
- before movrXX only, use reg_overlap_mentioned_p.
- Only special case NE if just one insn can be generated.
-
-2002-03-15 Richard Earnshaw <rearnsha@arm.com>
-
- PR target/5712
- * arm.md (movaddr, movaddr_insn): Delete.
-
-2002-03-15 Jason Merrill <jason@redhat.com>
-
- * toplev.c (wrapup_global_declarations): Clarify variable handling.
- -fkeep-static-consts doesn't apply to comdats.
-
-2002-03-14 Richard Henderson <rth@redhat.com>
-
- PR target/5312
- * config/ia64/ia64.c: Include tm_p.h last.
- (gen_nop_type): Remove duplicate definition.
- (cycle_end_fill_slots): Set sched_data for second L slot.
- (maybe_rotate): Call cycle_end_fill_slots to fill in nop slots.
- (nop_cycles_until): Fix typos.
-
-2002-03-15 Jakub Jelinek <jakub@redhat.com>
-
- PR optimization/5891
- * unroll.c (copy_loop_body) [CALL_INSN]: Copy SIBLING_CALL_P flag.
-
-2002-03-14 David Mosberger <davidm@hpl.hp.com>, Hans Boehm <Hans_Boehm@hp.com>
-
- * config/ia64/unwind-ia64.c: Handle copy_state and label_state
- descriptors correctly.
-
-2002-03-14 Zack Weinberg <zack@codesourcery.com>
-
- * cpphash.h (struct lexer_state): Remove line_extension member.
- * cpplib.c (dequote_string, do_linemarker): New functions.
- (linemarker_dir): New data object.
- (DIRECTIVE_TABLE): No longer need to interpret #line in
- preprocessed source. Delete obsolete comment about return
- values of handlers.
- (end_directive, directive_diagnostics, _cpp_handle_directive):
- Don't muck with line_extension.
- (directive_diagnostics): No need to issue warnings for
- linemarkers here.
- (_cpp_handle_directive): Issue warnings for linemarkers here,
- when appropriate. Dispatch linemarkers to do_linemarker, not
- do_line.
- (do_line): Code to handle linemarkers split out to do_linemarker.
- Convert escape sequences in filename argument, both places.
-
- * cppmacro.c (quote_string): Rename cpp_quote_string and
- export. All callers changed.
- * cpplib.h (cpp_quote_string): Prototype.
- * cppmain.c (print_line): Call cpp_quote_string on to_file
- before printing it.
+ PR c/8518
+ * c-decl.c (duplicate_decls): Outline the second definition
+ of an extern inline function in all cases.
- * doc/cpp.texi: Document that escapes are now interpreted in
- #line and in linemarkers, and that non-printing characters are
- converted to octal escapes when linemarkers are generated.
+2002-11-20 Richard Sandiford <rsandifo@redhat.com>
-2002-03-14 Richard Earnshaw <rearnsha@arm.com>
- Jeroen Dobbelaere <jeroen.dobbelaere@acunia.com>
+ * stor-layout.c (place_field): Update rli->offset as well as
+ rli->bitpos.
- PR target/5828
- * arm.c (arm_output_epilogue): Fix floating-point register save
- adjustment when using a frame pointer.
+2002-11-20 Richard Sandiford <rsandifo@redhat.com>
-2002-03-13 Hans-Peter Nilsson <hp@bitrange.com>
+ * sched-deps.c (sched_analyze): Check HARD_REGNO_CALL_PART_CLOBBERED.
- * config/mmix/mmix.c: Improve comments.
- (mmix_target_asm_function_prologue): Drop variable
- empty_stack_frame. Don't allocate unused slot above fp.
- (mmix_target_asm_function_epilogue): Mirror prologue changes.
- (mmix_expand_builtin_va_arg): Do all computations on trees.
- * config/mmix/mmix.h (MMIX_GNU_ABI_REG_ALLOC_ORDER): Don't have
- brace in first column.
- (enum reg_class): Ditto.
- (FIRST_PARM_OFFSET): Now 0.
- (USER_LABEL_PREFIX): Remove #if 0:d definition.
- (LINK_SPEC): Don't defsym __.MMIX.start..text if linking
- relocatably. Always produce ELF, not mmo if linking relocatably.
+2002-11-20 Richard Sandiford <rsandifo@redhat.com>
-2002-03-13 David Edelsohn <edelsohn@gnu.org>
+ * config/sh/sh.md (udivsi3): Don't put udivsi3_i4_media instructions
+ into a libcall block.
+ (divsi3): Likewise divsi3_i4_media.
- * config/rs6000/rs6000.h (PAD_VARARGS_DOWN): Define.
- * config/rs6000/rs6000.c (rs6000_va_arg): Use
- std_expand_builtin_va_arg if not ABI_V4.
+2002-11-20 Richard Sandiford <rsandifo@redhat.com>
-2002-03-13 Jakub Jelinek <jakub@redhat.com>
+ * global.c (find_reg): Check HARD_REGNO_NREGS before kicking
+ out another register.
- PR target/5626
- * config/sparc/sparc.md (normal_branch, inverted_branch,
- normal_fp_branch, inverted_fp_branch, normal_fpe_branch,
- inverted_fp_branch): Adjust calls to output_cbranch.
- Set length attribute.
- (normal_int_branch_sp64, inverted_int_branch_sp64): Adjust calls to
- output_v9branch. Set length attribute.
- * config/sparc/sparc.c (fcc0_reg_operand, noov_compare64_op): New
- predicates.
- (noov_compare_op): Handle CCX_NOOVmode the same way as CC_NOOVmode.
- (output_cbranch): Likewise. Handle far branches.
- (output_v9branch): Handle far branches.
- * config/sparc/sparc-protos.h (output_cbranch, output_v9branch):
- Adjust prototypes.
- * config/sparc/sparc.h (PREDICATE_CODES): Add fcc0_reg_operand and
- noov_compare64_op predicates.
+2002-11-20 Jakub Jelinek <jakub@redhat.com>
-2002-03-13 Jason Merrill <jason@redhat.com>
+ * combine.c (force_to_mode): Only replace with (not Y) if all bits in fuller_mask
+ (not just mask) are set in C.
- * gthr-posix.h (__gthread_active_p): Move __gthread_active_ptr
- into the function and constify it.
- * gthr-dce.h, gthr-solaris.h: Likewise.
+2002-11-19 Andreas Jaeger <aj@suse.de>
-2002-03-12 Hans-Peter Nilsson <hp@axis.com>
+ * loop.c (record_giv): Initialize not_replaceable.
+ (check_final_value): Likewise.
- * config/cris/cris.c (cris_print_operand): Avoid
- traditional-warning for 0xffffffff.
- (cris_expand_builtin_va_arg): Do all computations on trees.
+2002-11-19 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-13 Ulrich Weigand <uweigand@de.ibm.com>
+ * config/h8300/h8300.c (h8300_init_once): Replace 1 with
+ MASK_H8300S.
- * expr.c (expand_expr, case NE_EXPR): Do not call copy_to_reg with
- VOIDmode operand. Add compile-time optimization for constant results.
+2002-11-19 Vijay L. Khuspe <vijayk1@kpit.com>
-2002-03-13 Hartmut Penner <hpenner@de.ibm.com>
+ * config/h8300/h8300.c (h8300_init_once): Allow -mn switch
+ only if -mh or -ms present.
+ (h8300_eightbit_constant_address_p): Support the normal mode.
+ (h8300_tiny_constant_address_p): Likewise.
+ * config/h8300/h8300.h (TARGET_NORMAL_MODE): New.
+ (POINTER_SIZE): Add 16 bit pointer for the normal mode.
+ (Pmode): Evaluate to HImode for the normal mode.
+ (SIZE_TYPE): Evaluate to unsigned int for normal mode.
+ (PTRDIFF_TYPE): Evaluate to int for the normal mode.
+ (ASM_WORD_OP): Evaluate to word for the normal mode.
+ * config/h8300/h8300.md (tablejump_normal_mode): New.
+ (indirect_jump_normal_mode): New.
+ * config/h8300/t-h8300 (MULTILIB_OPTIONS): Pass -mn option to
+ directory.
+ (MULTILIB_DIRNAMES): Create target dependent directory
+ 'normal'.
+ (MULTILIB_EXCEPTIONS): Don't turn on -mn on H8/300.
+ * doc/invoke.texi (gccoptlist): Describe the new switch -mn.
- * config/s390/s390.h (PROFILE_BEFORE_PROLOGUE): Emit profile code
- before prologue, to avoid scheduling problems.
+2002-11-19 Jan Hubicka <jh@suse.cz>
-2002-03-13 Jakub Jelinek <jakub@redhat.com>
+ * i386.md (length_immediate): Do not refer to insn address.
+ (jcc*, jmp patterns): Compute length explicitly.
- * config/sparc/sparc.h (INITIAL_FRAME_POINTER_OFFSET): Remove.
- (ELIMINABLE_REGS): Add sfp->sp.
- (INITIAL_ELIMINATION_OFFSET): Compute sfp->sp offset too.
+2002-11-19 Eric Botcazou <ebotcazou@libertysurf.fr>
-2002-03-13 Jakub Jelinek <jakub@redhat.com>
+ PR c/8588
+ * optabs.c (expand_binop): Convert CONST_INTs in shift
+ operations too.
- PR optimization/5892
- * config/ia64/ia64.c (rotate_one_bundle): Update current packet.
+2002-11-19 Roger Sayle <roger@eyesopen.com>
-2002-03-13 Jakub Jelinek <jakub@redhat.com>
+ * gcse.c (gcse_emit_move_after): Correct typo in REG_EQUAL note.
- * loop.c (basic_induction_var): Don't call convert_modes if mode
- classes are different.
+2002-11-19 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-12 Richard Henderson <rth@redhat.com>
+ * config/h8300/h8300.md (an anonymous pattern): Relax the
+ condition to accept the same operands and/or subregs.
- PR optimization/5901
- * function.c (reposition_prologue_and_epilogue_notes): Position
- the markers after/before the last/first insn not deleted.
+2002-11-19 Daniel Jacobowitz <drow@mvista.com>
-2002-03-12 Richard Henderson <rth@redhat.com>
+ * config/sh/sh.c (gen_shl_and): Revert previous patch.
+ * config/sh/sh.md (ashrdi3+1, ashrdi3+2): Predicate on
+ reload_completed.
- PR optimization/5878
- * config/arc/arc.h, config/cris/cris.h, config/i386/i386.h,
- config/m68k/m68k.h, config/s390/s390.h, config/sparc/sparc.h
- (PIC_OFFSET_TABLE_REGNUM): Conditionalize on flag_pic.
+2002-11-19 Kazu Hirata <kazu@cs.umass.edu>
- * config/arm/arm.h config/i386/i386.h, config/m68k/m68k.h,
- config/sparc/sparc.h (CONDITIONAL_REGISTER_USAGE): Set
- PIC_OFFSET_TABLE_REGNUM based on INVALID_REGNUM not flag_pic.
+ * config/h8300/h8300.c (print_operand): Update the use of
+ EIGHTBIT_CONSTANT_ADDRESS_P.
+ (h8300_adjust_insn_length): Likewise.
+ (h8300_eightbit_constant_address_p): Check if the given rtx is
+ a variable with __attribute__((eightbit_data)).
+ * config/h8300/h8300.h (OK_FOR_U): Update the use of
+ EIGHTBIT_CONSTANT_ADDRESS_P.
- * config/arc/arc.h (CONDITIONAL_REGISTER_USAGE): New.
- * config/arm/arm.c (arm_pic_register): Init to INVALID_REGNUM.
- (arm_override_options): Set arm_pic_register if TARGET_APCS_STACK
- also. Don't set it if not flag_pic.
- * config/i386/i386.c (ix86_save_reg): Trust PIC_OFFSET_TABLE_REGNUM
- to be INVALID_REGNUM when not used.
+2002-11-19 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-03-13 Aldy Hernandez <aldyh@redhat.com>
+ * doc/contrib.texi (Contributors): Add self as second contact in
+ addition to Jeff Law.
- * expmed.c (store_bit_field): Reset alias set for memory.
- (extract_bit_field): Same.
+2002-11-19 Andreas Jaeger <aj@suse.de>
-2002-03-12 Chris Meyer <cmeyer@gatan.com>
+ * tree-inline.c: Move prototpyes of find_alloca_call_1 and
+ find_alloca_call to right place.
- * genflags.c (gen_insn): Use IS_VSPACE.
- * genoutput.c (output_insn_data): Likewise.
- (process_template): Likewise.
+2002-11-19 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-12 Bob Wilson <bob.wilson@acm.org>
+ * cppfiles.c: Fix formatting.
- * config/xtensa/xtensa.c (xtensa_expand_block_move): Use
- validize_mem() instead of change_address to avoid clobbering
- memory attributes.
+2002-11-19 Jason Thorpe <thorpej@wasabisystems.com>
-2002-03-12 Jakub Jelinek <jakub@redhat.com>
+ * gcc.c (The Specs Language): Document spec functions.
+ (static_spec_functions, lookup_spec_function)
+ (eval_spec_function, handle_spec_function)
+ (if_exists_spec_function, alloc_args): New.
+ (execute): Abort if processing_spec_function is true.
+ (do_spec_1): Hand off spec to handle_spec_function if %:
+ is encountered. If processing_spec_function is true,
+ end any pending argument when the end of the string is reached.
+ (main): Use alloc_args to allocate the initial argument vector.
+ * gcc.h (struct spec_function): New.
+ (lang_specific_spec_functions): New extern.
- * c-lex.c (cb_ident, c_lex): Remove unnecessary cast.
- (lex_string): Use unsigned char pointers.
+ * config/netbsd-elf.h (STARTFILE_SPEC): Add if-exists(crti%O%s).
+ (ENDFILE_SPEC): Add if-exists(crtn%O%s).
+ * config/alpha/netbsd.h (ENDFILE_SPEC): Likewise.
-2002-03-12 Ulrich Weigand <uweigand@de.ibm.com>
+ * doc/invoke.texi: Document spec functions.
- * reload1.c (reload): Ignore MEM REG_EQUIV notes if the equivalent
- is not a valid memory_operand.
+ * cppspec.c (lang_specific_spec_functions): New.
+ * gccspec.c: Likewise.
-2002-03-12 Bob Wilson <bob.wilson@acm.org>
+2002-11-18 Steve Ellcey <sje@cup.hp.com>
- * config/xtensa/xtensa-config.h: Define XCHAL_HAVE_LOOPS.
- * config/xtensa/lib1funcs.asm: Fix copyright to include
- special case for libgcc files.
- (__udivsi3): Avoid loop instructions when XCHAL_HAVE_LOOPS is 0.
- (__divsi3): Likewise.
- (__umodsi3): Likewise.
- (__modsi3): Likewise.
- * config/xtensa/lib2funcs.S: Fix copyright to include
- special case for libgcc files.
+ * config/ia64/hpux_longdouble.h (FIXUNS_TRUNCTFSI2_LIBCALL): New.
+ (FIXUNS_TRUNCTFDI2_LIBCALL): New.
+ (fixunstfsi_libfunc): Change.
+ (fixunstfdi_libfunc): Change.
+ (sdiv_optab): Don't zero out SImode handler.
+ (udiv_optab): Don't zero out SImode handler.
+ (smod_optab): Don't zero out SImode handler.
+ (umod_optab): Don't zero out SImode handler.
-2002-03-12 Michael Matz <matz@suse.de>
+2002-11-18 Neil Booth <neil@daikokuya.co.uk>
- * config/rs6000/rs6000.md (ne0+4): Add extra CLOBBER.
- (ne0+5): Use new clobber to generate proper shift pattern.
+ PR preprocessor/8524
+ * cpplib.c (run_directive): Remove previous kludge to _Pragma.
+ Add a new one in its place, which hopefully works.
+ (skip_rest_of_line): Change test for bottom-of-context-stack.
-2002-03-12 Bob Wilson <bob.wilson@acm.org>
+2002-11-18 Jan Hubicka <jh@suse.cz>
- * config/xtensa/t-xtensa (CRTSTUFF_T_CFLAGS_S): Define.
+ * i386.md (addqi_1_slp): Fix output template.
+ (subqi_1_slp): Fix type.
-2002-03-12 Bob Wilson <bob.wilson@acm.org>
+2002-11-17 Jan Hubicka <jh@suse.cz>
- * config/xtensa/xtensa.h (ASM_OUTPUT_POOL_PROLOGUE): Switch
- to function_section before writing out the constant pool.
+ * calls.c (alloca_call_p): New global function.
+ * tree.h (alloca_call_p): New.
+ * tree-inline.c (inlinable_function_p): Do not inline when
+ function calls alloca.
+ (find_alloca_call, find_alloca_call_1): New functions.
-2002-03-12 Zack Weinberg <zack@codesourcery.com>
+2002-11-18 Kazu Hirata <kazu@cs.umass.edu>
- * Makefile.in: Give texi2pod its input file as a command
- line argument, not on stdin.
+ * config/h8300/h8300.md (*andorqi3): Use bor between bld and
+ bst. Update the insn length.
+ (*andorhi3): Likewise.
+ (*andorsi3): Likewise.
-2002-03-12 Andrew MacLeod <amacleod@redhat.com>
+2002-11-18 Richard Sandiford <rsandifo@redhat.com>
- * config/sparc/sparc.h (RETURN_ADDR_RTX): Include v9 stack bias in
- address calculation.
+ * config/sh/sh-protos.h (sh_mark_label): Declare.
+ * config/sh/sh.c (sh_mark_label): New function, taken from
+ movdi_const, but fixing the case when the address has an addend.
+ * config/sh/sh.md (movdi_const, movdi_const_32bit): Use it.
-2002-03-12 Ulrich Weigand <uweigand@de.ibm.com>
+2002-11-18 Richard Sandiford <rsandifo@redhat.com>
- * config/s390/s390.md (reload_insi, reload_indi): Change mode of
- scratch register to DImode / TImode.
- config/s390/s390.c (s390_expand_plus_operand): Make sure scratch
- register used does not overlap the target.
+ * config/sh/sh.c (pool_node): New field: part_of_sequence_p.
+ (add_constant): Set it.
+ (dump_table): Don't reorder a constant if part_of_sequence_p.
+ (machine_dependent_reorg): Assume that float constants will
+ stay in their original order if used as a sequence.
-2002-03-11 Neil Booth <neil@daikokuya.demon.co.uk>
+2002-11-18 Richard Sandiford <rsandifo@redhat.com>
- * Makefile.in: Update.
-doc:
- * cppenv.texi, cppopts.texi: Split out of cpp.texi and gcc.texi.
- Update documentation.
- * gcc.texi: Include cppopts.texi and cppenv.texi.
- * cpp.texi: Include cppopts.texi and cppenv.texi.
+ * config/sh/sh.c (calc_live_regs): Update check for PIC liveness
+ in compact code.
-2002-03-11 Ulrich Weigand <uweigand@de.ibm.com>
+2002-11-18 Richard Sandiford <rsandifo@redhat.com>
- * config/s390/s390.h (REG_ALLOC_ORDER): Add missing register.
+ * config/sh/sh.md (initialize_trampoline): Do not force the
+ trampoline address into R0_REGS here.
-2002-03-11 Douglas B Rupp <rupp@gnat.com>
+2002-11-17 Kazu Hirata <kazu@cs.umass.edu>
- * toplev.c (vms_fopen): Remove, not needed.
+ * df.c: Fix formatting.
- * vmsdbgout.c (lookup_filename): Adjust creation date for GMT.
+2002-11-17 Kazu Hirata <kazu@cs.umass.edu>
- * config/alpha/xm-vms.h (__UNIX_FWRITE): Define.
+ * config/h8300/h8300.md (two anonymous patterns): Fix insn
+ lengths.
- * config/alpha/alpha.c (alpha_sa_size, VMS): Don't reserve space
- for FP, already done later.
+2002-11-17 Daniel Jacobowitz <drow@mvista.com>
- * toplev.c (debug_args): Add entry for VMS_DEBUG.
- * vmsdbgout.c (vmsdbgout_init): Fix typo in call to xmalloc.
+ * sh.c (gen_shl_and): Don't create a zero_extend if the operand
+ is not an arith_reg_operand.
-2002-03-10 Richard Henderson <rth@redhat.com>
+2002-11-17 Graham Stott <graham.stott@btinternet.com>
- PR 5693
- * reload.c (copy_replacements_1): New.
- (copy_replacements): Use it to recurse through the rtx.
+ * real.c (real_to_decimal): Fix buffer overrun when buffer size
+ is smaller than representation.
-2002-03-10 Richard Henderson <rth@redhat.com>
+2002-11-17 Kazu Hirata <kazu@cs.umass.edu>
- * sched-rgn.c (add_branch_dependences): Don't allow insns that throw
- to move away from the end of the block.
+ * builtins.c: Fix formatting.
-2002-03-10 Neil Booth <neil@daikokuya.demon.co.uk>
+2002-11-16 Kazu Hirata <kazu@cs.umass.edu>
- PR preprocessor/5899
- * cppinit.c (init_dependency_output): Don't ignore -dM etc.
+ * config/h8300/h8300.md (two anonymous patterns): Fix typos.
-2002-03-10 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+2002-11-16 Kazu Hirata <kazu@cs.umass.edu>
- * combine.c (make_extraction): Fix error in last change.
+ * config/h8300/h8300.md: Fix formatting.
-2002-03-09 Jakub Jelinek <jakub@redhat.com>
+2002-11-16 Kazu Hirata <kazu@cs.umass.edu>
- PR optimization/5172, optimization/5200
- * gcse.c (gcse_main): Disable store_motion.
+ * config/h8300/h8300.md: Replace spaces with tabs.
+ * config/h8300/t-h8300: Remove a trailing empty line.
-2002-03-09 Andreas Schwab <schwab@suse.de>
+2002-11-16 Kazu Hirata <kazu@cs.umass.edu>
- * gcc.c (validate_all_switches): Also handle `%W{...}'.
+ * tlink.c: Fix formatting.
-2002-03-09 Jakub Jelinek <jakub@redhat.com>
+2002-11-16 David Edelsohn <edelsohn@gnu.org>
- PR middle-end/5877
- * expr.c (highest_pow2_factor): Check TREE_INT_CST_LOW
- even for non-representable constants.
+ PR 8362
+ * config/rs6000/rs6000.c (rs6000_outout_load_multiple): New function.
+ * config/rs6000/rs6000.md (movti_string): Remove output modifier
+ when scratch register never needed.
+ (ldmsi[3-8]): New patterns.
-Sat Mar 9 07:20:01 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2002-11-16 Kazu Hirata <kazu@cs.umass.edu>
- * emit-rtl.c (copy_most_rtx): Accept EXPR_LIST for may_share.
- * function.c (fixup_var_refs): Add MAY_SHARE parameter.
- (fixup_var_refs_insns, fixup_var_refs_insns_with_has): Likewise.
- (fixup_var_refs_insn, fixup_var_refs_1): Likewise.
- (pop_function_context): Compute MAY_SHARE parameter for
- fixup_var_refs.
- (fixup_var_refs_1, case MEM): Pass MAY_SHARE to copy_most_rtx, not VAR.
- (gen_mem_addressof): Call fixup_var_refs with new parm.
+ * hard-reg-set.h: Follow spelling conventions.
+ * real.c: Likewise.
+ * target.h: Likewise.
- * combine.c (make_extraction): Don't make extension of CONST_INT.
+2002-11-16 Jakub Jelinek <jakub@redhat.com>
-2002-03-08 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ * config/i386/x86-64.h (MCOUNT_NAME): Change into string literal.
- * sparc.c (arith_4096_operand): Fix error in last change.
+2002-11-16 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-08 Aldy Hernandez <aldyh@redhat.com>
+ * optabs.c: Fix formatting.
- * config/rs6000/rs6000.c (rs6000_va_arg): Fix alignment for
- vectors.
+2002-11-16 Jan Hubicka <jh@suse.cz>
-2002-03-08 Aldy Hernandez <aldyh@redhat.com>
+ * athlon.md, k6.md, pentium.md, ppro.md: Handle shift1, rotate1
+ * i386.md (attribute type): Add type shift1 and rotate1.
+ (*_slp): Rewrite to have just two operands to avoid reload problems.
- * config/rs6000/sysv4.h (BIGGEST_ALIGNMENT): Change for altivec.
+2002-11-15 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-08 Craig Rodrigues <rodrigc@gcc.gnu.org>
+ * config/h8300/h8300.md (4 anonymous patterns): New.
- * doc/install.texi (--with-libiconv-prefix): Document.
+2002-11-15 Geoffrey Keating <geoffk@apple.com>
-2002-03-08 Michael Y. Brukman <myb2@cornell.edu>
+ * params.def (GGC_MIN_HEAPSIZE): Fix GGC_ALWAYS_COLLECT problem.
+ * doc/invoke.texi: Correct description of what needs to be done to
+ force collection at every ggc_collect call.
- * doc/sourcebuild.texi: Fix typo.
+2002-11-15 Ulrich Weigand <uweigand@de.ibm.com>
-2002-03-08 Jakub Jelinek <jakub@redhat.com>
+ * config/s390/s390.c (optimization_options): Set
+ flag_asynchronous_unwind_tables to 1 by default.
- PR c/3711
- * builtins.c (std_expand_builtin_va_arg): Do all computations on
- trees.
+2002-11-15 Ulrich Weigand <uweigand@de.ibm.com>
-Fri Mar 8 06:48:45 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * config/s390/s390.h (ASM_PREFERRED_EH_DATA_FORMAT): Define.
- * rtl.c (copy_most_rtx): Move from here ...
- * emit-rtl.c (copy_most_rtx): ... to here.
+2002-11-15 Jan Hubicka <jh@suse.cz>
-2002-03-08 Richard Earnshaw <rearnsha@arm.com>
+ * i386-protos.h (x86_function_profiler): New function
+ * i386.h (MCOUNT_NAME): New.
+ (PROFILE_COUNT_REGISTER): New.
+ (FUNCTION_PROFILER): Move offline to ...
+ * i386.c (x86_function_profiler) ... here; fix 64bit support
+ * beos-elf.h (FUNCTION_PROFILER): Kill.
+ (MCOUNT_NAME): New.
+ * freebsd-aout.h (FUNCTION_PROFILER): Kill.
+ (MCOUNT_NAME): New.
+ (PROFILE_COUNT_REGISTER): New.
+ * linux.h (FUNCTION_PROFILER): Kill.
+ (MCOUNT_NAME): New.
+ * x86-64.h (FUNCTION_PROFILER): Kill.
+ (MCOUNT_NAME): New.
+ * freebsd.h (FUNCTION_PROFILER): Kill.
+ (MCOUNT_NAME): New.
- * combine.c (simplify_comparison): If simplifying a logical shift
- right and compare with constant, force the comparison to unsigned.
+2002-11-14 Jeroen Dobbelaere <jeroen.dobbelaere@acunia.com>
-2002-03-07 Ulrich Weigand <uweigand@de.ibm.com>
+ * config/arm/arm.h (EXPAND_BUILTIN_VA_ARG,
+ FUNCTION_ARG_PASS_BY_REFERENCE): Define.
+ * config/arm/arm.c (arm_va_arg,
+ arm_function_arg_pass_by_reference): New.
+ * config/arm/arm-protos.h: Add prototypes.
- * genextract.c (walk_rtx): Recurse into MATCH_PAR_DUP.
- genoutput.c (scan_operands): Recurse into MATCH_PAR_DUP
- and MATCH_OP_DUP.
+2002-11-14 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-07 Aldy Hernandez <aldyh@redhat.com>
+ * gthr-single.h: Fix formatting.
- * doc/invoke.texi: Add documentation for -mabi=no-altivec.
+2002-11-14 Zack Weinberg <zack@codesourcery.com>
- * config/rs6000/rs6000.c (rs6000_parse_abi_options): Add
- -mabi=no-altivec
- (alt_reg_names): Remove % for vrsave.
+ * tree.c (tree_vec_elt_check_failed): New function.
+ * tree.h (TREE_VEC_ELT_CHECK): New checking macro.
+ (TREE_VEC_ELT): Use it.
-2002-03-06 Jeffrey A Law (law@redhat.com)
+ * tree-inline.c (optimize_inline_calls): Don't copy a
+ zero-length vector.
- * ssa-ccp.c (ssa_fast_dce): Update the DF def-use chains
- after completing fast dead code elimination.
+2002-11-14 Gabriel Dos Reis <gdr@integrable-solutions.net>
-2002-03-06 Richard Henderson <rth@redhat.com>
+ * diagnostic.c (sorry): Don't repeat "sorry, unimplemented" text.
- PR optimization/5844
- * genemit.c (gen_exp): New argument used. Invoke copy_rtx
- if used indicates we've already emitted one copy of an operand.
- (gen_insn, gen_expand, output_add_clobbers): Supply a null used.
- (gen_split): Supply a non-null used.
+2002-11-14 Jakub Jelinek <jakub@redhat.com>
-2002-03-06 Ulrich Weigand <uweigand@de.ibm.com>
+ * varasm.c (output_addressed_constants) [MINUS_EXPR]: Clear reloc if
+ both operands contain local relocations.
+ (categorize_decl_for_section): Don't use mergeable sections if
+ initializer has any relocations.
- * simplify-rtx.c (simplify_plus_minus): Do not abort,
- but simply fail if the expression is too complex to simplify.
- (simplify_gen_binary): Handle simplify_plus_minus failures.
+2002-11-14 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-06 Ulrich Weigand <uweigand@de.ibm.com>
+ * gthr-vxworks.h: Fix formatting.
- * reload1.c (reload): Unshare all rtl after reload is done.
+2002-11-13 Janis Johnson <janis187@us.ibm.com>
-2002-03-06 Jakub Jelinek <jakub@redhat.com>
+ * doc/install.texi (Testing): Document extra Java testing.
+ * doc/sourcebuild.texi (Test Suites): Document libgcj testing.
- * ssa-ccp.c (ssa_ccp_substitute_constants): Backout 2002-03-05
- patch.
+2002-11-13 John David Anglin <dave@hiauly1.hia.nrc.ca>
-2002-03-05 Zack Weinberg <zack@codesourcery.com>
+ * pa64-hpux.h (LINK_SPEC): Move "+Accept TypeMismatch" switch to the
+ beginning of the spec.
+ (LDD_SUFFIX, PARSE_LDD_OUTPUT): Delete.
+ (LD_INIT_SWITCH, LD_FINI_SWITCH): Define but don't enable. Add comment
+ regarding problems with global constructors when using GNU ld.
- * cppmain.c (setup_callbacks): Disable #pragma and #ident
- callbacks when processing assembly language.
+2002-11-13 Kazu Hirata <kazu@cs.umass.edu>
-2002-03-06 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ * gthr-solaris.h: Fix formatting.
- * pa.h (ASM_FILE_END): Define.
- * som.h (ASM_FILE_END): Delete.
+2002-11-13 Kazu Hirata <kazu@cs.umass.edu>
- * pa.c (function_arg): Don't pass floats in general registers in
- indirect calls if TARGET_ELF32.
+ * gthr-posix.h: Fix formatting.
-2002-03-05 Richard Henderson <rth@redhat.com>
+2002-11-12 Kazu Hirata <kazu@cs.umass.edu>
- * config/i386/i386.md (floatsidf2): Conditionalize on hard-float.
+ * config/h8300/h8300.md (*andorsi3): New.
-2002-03-05 Jakub Jelinek <jakub@redhat.com>
+2002-11-12 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
- * mklibgcc.in: Prepend a tab before .hidden, add $flags to gcc
- -r command line. Don't hide any symbols if not building
- shared libgcc.
+ * doc/install.texi (powerpc-*-linux-gnu*): Update binutils requirement.
-2002-03-05 Jakub Jelinek <jakub@redhat.com>
+2002-11-12 Kazu Hirata <kazu@cs.umass.edu>
- * expmed.c (emit_store_flag): Don't test BITS_PER_WORD * 2
- wide volatile memory by parts.
+ * config/h8300/h8300.c (tiny_constant_address_p): Parenthesize
+ expressions appropriately.
-2002-03-05 Jakub Jelinek <jakub@redhat.com>
+2002-11-12 Kazu Hirata <kazu@cs.umass.edu>
- * ssa-ccp.c (ssa_ccp_substitute_constants): Don't crash if def
- is NULL.
+ * gthr-win32.h: Fix formatting.
-2002-03-05 Richard Henderson <rth@redhat.com>
+2002-11-12 Kazu Hirata <kazu@cs.umass.edu>
- * config/rs6000/rs6000.h (TOTAL_ALTIVEC_REGS): Fix off-by-one error.
+ * config/h8300/h8300.c (single_one_operand): Correctly compute
+ mask when mode is SImode.
+ (single_zero_operand): Likewise.
+ * config/h8300/h8300.md (two new anonymous insns): New.
-2002-03-04 Krister Walfridsson <cato@df.lth.se>
+2002-11-12 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
- * config.gcc (*-*-netbsd*): Add t-slibgcc-elf-ver to tmake_file.
+ * doc/contrib.texi (Contributors): Use GCJ instead of gcj to refer
+ to that entire project.
-2002-03-05 Joseph S. Myers <jsm28@cam.ac.uk>
+2002-11-12 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
- * configure.in: Increase required makeinfo version to 4.1.
- * configure: Regenerate.
+ * config/mips/t-iris6 (MULTILIB_OSDIRNAMES): Restore old
+ directories.
-2002-03-04 Joseph S. Myers <jsm28@cam.ac.uk>
+2002-11-11 Zack Weinberg <zack@codesourcery.com>
- * doc/include/texinfo.tex: Update to version 2002-03-01.06.
- * doc/invoke.texi: Fix @math uses.
+ * params.def (ggc-min-expand, ggc-min-heapsize): New parameters.
+ * doc/invoke.texi: Document them.
-2002-03-02 Per Bothner <per@bothner.com>
+ * ggc-page.c: Include params.h. Remove definitions of
+ GGC_MIN_EXPAND_FOR_GC, GGC_MIN_LAST_ALLOCATED. Replace
+ GGC_POISON with ENABLE_GC_CHECKING in ifdefs, delete #define.
+ (init_gcc): Don't set G.allocated_last_gc here.
+ (ggc_collect): Use PARAM_VALUE (GGC_MIN_HEAPSIZE) and
+ PARAM_VALUE (GGC_MIN_EXPAND) to decide whether or not to
+ perform collection.
+ * ggc-simple.c: Similarly.
+ * Makefile.in (ggc-common.o, ggc-simple.o): Add $(PARAMS_H) to
+ dependencies.
- * gcc.c (option_map): Suport new --bootclasspath option.
- --CLASSPATH is now just an alias for --classpath.
+2002-11-11 Kazu Hirata <kazu@cs.umass.edu>
-Sat Mar 2 06:30:14 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * gthr-dce.h: Fix formatting.
- * config/sparc/sparc.c (sparc_initialize_trampoline): Use
- trunc_int_for_mode.
+2002-11-11 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
- * emit-rtl.c (offset_address): Call update_temp_slot_address.
+ PR c/8467
+ * stmt.c (tail_recursion_args): Handle DECL_MODE differing from the
+ mode of DECL_RTL case.
-2002-03-01 Richard Henderson <rth@redhat.com>
+2002-11-11 Janis Johnson <janis187@us.ibm.com>
- * config/ia64/ia64.c (ia64_initial_elimination_offset): Do not
- adjust argument_pointer by pretend_args_size.
- (ia64_va_start): Adjust va_start address by -pretend_args_size.
+ * doc/contrib.texi: Merge in the list from the libstdc++ web pages.
-2002-03-01 Zack Weinberg <zack@codesourcery.com>
+2002-11-11 Jan Hubicka <jh@suse.cz>
- * doc/cpp.texi: Clarify documentation of relationship between
- #line and #include.
+ * i386.c (construct_container): Fix handling of SSE_CLASS.
-2002-02-28 Richard Henderson <rth@redhat.com>
+2002-11-10 Joel Sherrill <joel@gcc.gnu.org>
- * expmed.c (store_bit_field): Prevent generation of CONCATs;
- pun complex values as integers; use gen_lowpart instead of
- gen_rtx_SUBREG.
- (extract_bit_field): Likewise.
+ * config/m68k/t-crtstuff (crti.o): Use this...
+ ($(T)crti.o): ... instead.
+ (crtn.o): Use this...
+ ($(T)crtn.o): ... instead.
-2002-02-28 David O'Brien <obrien@FreeBSD.org>
+2002-11-10 Eric Botcazou <ebotcazou@libertysurf.fr>
- * config.gcc (sparc64-*-freebsd): Explicitly accept a cpu specification
- of "ultrasparc".
- * config/sparc/freebsd.h: Do not use MASK_FASTER_STRUCTS. It appears
- to be broken.
+ PR c/8439
+ * recog.c (validate_replace_rtx_1) [PLUS]: Simplify only
+ if there is something new to be simplified.
-2002-02-28 Alexandre Oliva <aoliva@redhat.com>
+2002-11-10 H.J. Lu <hjl@gnu.org>
- * gcc.c (init_gcc_specs): Get -static and -static-libgcc to
- override -shared and -shared-libgcc.
+ * calls.c (PUSH_ARGS_REVERSED): Define only if not defined.
+ * expr.c (PUSH_ARGS_REVERSED): Likewise.
-2002-02-28 Andrew MacLeod <amacleod@redhat.com>
+ * config/i386/i386.h (PUSH_ARGS_REVERSED): Set to 1.
- * dwarf2out.c (stack_adjust_offset): Add support for POST_INC,
- POST_DEC, and POST_MODIFY.
+2002-11-10 Zack Weinberg <zack@codesourcery.com>
-2002-02-28 Joseph S. Myers <jsm28@cam.ac.uk>
+ * config/rs6000/sysv4.h: Define NO_IMPLICIT_EXTERN_C here...
+ * config/rs6000/linux.h, config/rs6000/linux64.h,
+ config/rs6000/windiss.h: ... not here.
- * doc/invoke.texi, doc/standards.texi: Link to
- gcc-3.1/c99status.html.
+2002-11-10 Jason Thorpe <thorpej@wasabisystems.com>
-2002-02-28 Richard Henderson <rth@redhat.com>
+ * config/mips/netbsd.h (TARGET_OS_CPP_BUILTINS): Define
+ __ABICALLS__ if TARGET_ABICALLS.
- * config/ia64/ia64.c (ia64_adjust_cost): All non-MM consumers have
- 4 cycle latency from MM producers.
- (ia64_internal_sched_reorder): Likewise with pipeline flush.
+2002-11-10 Jan Hubicka <jh@suse.cz>
-2002-02-28 Jakub Jelinek <jakub@redhat.com>
+ * i386.h (MIN_UNITS_PER_WORD): Define to 8 for x86-64 libgcc.
- * mklibgcc.in: Don't use GNU make extension.
+2002-11-10 Joseph S. Myers <jsm@polyomino.org.uk>
-2002-02-28 Richard Henderson <rth@redhat.com>
+ * c-decl.c (grokdeclarator): Make error for duplicate type
+ qualifiers into a pedwarn, disabled for C99.
- * haifa-sched.c (sched_emit_insn): New.
- (schedule_block): Use last_scheduled_insn to track last insn.
- * sched-int.h (sched_emit_insn): Prototype.
- * config/ia64/ia64.c (last_issued): Remove.
- (ia64_variable_issue): Don't set it.
- (nop_cycles_until): Use sched_emit_insn.
+2002-11-10 Hans-Peter Nilsson <hp@bitrange.com>
-2002-02-28 Bo Thorsen <bo@suse.de>
+ * config/mmix/mmix.h (FUNCTION_ARG_CALLEE_COPIES): Define the same
+ as FUNCTION_ARG_PASS_BY_REFERENCE.
- * config/i386/linux64.h (LINK_SPEC): Fix 32/64 bit compilation.
- (STARTFILE_SPEC): Add 64 bit files.
- (ENDFILE_SPEC): Likewise.
+2002-11-09 John David Anglin <dave@hiauly1.hia.nrc.ca>
-Don Feb 28 16:41:19 CET 2002 Jan Hubicka <jh@suse.cz>
+ * pa.h (STARTING_FRAME_OFFSET): Change offset for TARGET_64BIT to 16.
- * cfgrtl.c (purge_dead_edges): Fix handling of EH edges.
+ * config.gcc (hppa*64*-*-linux*): Shorten lines in tm_file define.
+ (hppa*64*-*-hpux11*): Likewise. Use elfos.h with gas.
+ * pa.c (output_millicode_call): Use symbol difference rather than
+ $PIC_pcrel$0 when using HP assembler.
+ * pa64-hpux.h (TARGET_GAS): Define to 1 or 0 depending on whether or
+ not elfos.h (i.e., gas) is being used.
+ (ASM_FILE_START, STRING_ASM_OP, TEXT_SECTION_ASM_OP,
+ DATA_SECTION_ASM_OP, BSS_SECTION_ASM_OP, ASM_OUTPUT_ALIGNED_COMMON,
+ ASM_OUTPUT_ALIGNED_LOCAL, GLOBAL_ASM_OP, ASM_DECLARE_FUNCTION_NAME,
+ ASM_OUTPUT_EXTERNAL, ASM_OUTPUT_EXTERNAL_LIBCALL,
+ ASM_OUTPUT_INTERNAL_LABEL, ASM_GENERATE_INTERNAL_LABEL): Define when
+ using elfos.h.
+ (TARGET_ASM_GLOBALIZE_LABEL): Undefine when using elfos.h.
+ (DWARF2_ASM_LINE_DEBUG_INFO): Delete.
+ (ASM_FILE_START): Add standard .SPACE and .SUBSPA defines when not
+ using elfos.h.
+ (TEXT_SECTION_ASM_OP, READONLY_DATA_SECTION_ASM_OP, DATA_SECTION_ASM_OP,
+ BSS_SECTION_ASM_OP): New HP style defines when not using elfos.h.
+ (TARGET_ASM_NAMED_SECTION, MAKE_DECL_ONE_ONLY, ASM_WEAKEN_LABEL):
+ Don't define when not using elfos.h.
+ (ASM_DECLARE_RESULT): Don't define.
+ * doc/install.texi (hppa*-hp-hpux*): Remove statement that HP assembler
+ doesn't work on hppa64-hp-hpux11.
+ (hppa*-hp-hpux11): Update.
- * i386.h (CONDITIONAL_REGISTER_USAGE): Do not write to
- PIC_OFFSET_TABLE_REGNUM when it is INVALID_REGNUM
+2002-11-09 Jason Thorpe <thorpej@wasabisystems.com>
- * x86-64.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Always define.
+ * config/mips/netbsd.h (SUBTARGET_ASM_SPEC): Don't pass -KPIC
+ to the assembler if -mno-abicalls was specified.
-2002-02-28 David Edelsohn <edelsohn@gnu.org>
+2002-11-09 John David Anglin <dave@hiauly1.hia.nrc.ca>
- * config/rs6000/aix43.h (THREAD_MODEL_SPEC): Delete.
- * config/rs6000/aix51.h (THREAD_MODEL_SPEC): Delete.
+ * pa-linux.h (PREFERRED_DEBUGGING_TYPE, DWARF2_ASM_LINE_DEBUG_INFO,
+ ASM_OUTPUT_DEF): Delete.
-2002-02-28 Alan Modra <amodra@bigpond.net.au>
+2002-11-09 Neil Booth <neil@daikokuya.co.uk>
- * config/rs6000/rs6000.md (load_toc_aix_di): Handle TARGET_RELOCATABLE.
+ * c-opts.c (COMMAND_LINE_OPTIONS): Fix -Wimplicit.
-2002-02-28 Jason Merrill <jason@redhat.com>
+2002-11-08 Dale Johannesen <dalej@apple.com>
- * c-decl.c (finish_function): Only warn about missing return
- statement with -Wreturn-type.
+ * dbxout.c (dbxout_type): Fix stabs info for vector types.
-2002-02-27 Zack Weinberg <zack@codesourcery.com>
+2002-11-08 Neil Booth <neil@daikokuya.co.uk>
- * mklibgcc.in: Don't use \n in a line subject to
- interpretation by echo.
+ PR preprocessor/8497
+ PR preprocessor/8501
+ * cpptrad.c (scan_out_logical_line): A '#' from a macro doesn't
+ start a directive. In assembler, #NUM is not a line directive.
-2002-02-27 Ulrich Weigand <uweigand@de.ibm.com>
+2002-11-08 Neil Booth <neil@daikokuya.co.uk>
- * config/s390/s390.c (s390_chunkify_pool): Do not confuse
- insn UIDs with insn addresses.
+ * cppmain.c (cpp_preprocess_file): Loop to pop any -included
+ buffers.
-2002-02-27 Graham Stott <grahams@redhat.com>
+2002-11-08 Kazu Hirata <kazu@cs.umass.edu>
- * config/rs6000/rs6000.h (ASM_OUTPUT_DEF_FROM_DECL):
- Constify NAME.
+ * config/h8300/h8300.md (two anonymous test insns): New.
- * loop.c (prescan_loop): Handle PARALLEL.
+2002-11-08 Jan Hubicka <jh@suse.cz>
- * unroll.c (loop_iterations): Return 0 if the add_val for
- a BIV is REG.
+ * jump.c (mark_jump_label): Handle subregs of label_refs.
- * final.c (output_operand_lossage): Constify PFX_STR.
+2002-11-07 David Mosberger <davidm@hpl.hp.com>
- * df.c (df_insn_refs_record): Use XEXP (x, 0) for USE.
+ * config/ia64/crtend.asm: Include "auto-host.h".
+ [HAVE_INITFINI_ARRAY]: Invoke __do_global_ctors_aux via .init_array.
+ * config/ia64/crtbegin.asm: Similarly.
+ * config/ia64/t-ia64 (crtbegin.o): Include from current directory.
+ (crtend.o, crtbeginS.o, crtendS.o): Likewise.
-2002-02-26 Richard Henderson <rth@redhat.com>
+ * aclocal.m4 (gcc_AC_INITFINI_ARRAY): New.
+ * configure.in: Use it if --enable-initfini-array not specified.
+ * doc/install.texi (Configuration): Document --enable-initfini-array.
+ * configure, config.in: Rebuild.
- * config/alpha/alpha.md (ashldi_se): Re-enable.
+2002-11-07 Jason Thorpe <thorpej@wasabisystems.com>
-2002-02-26 Kelley Cook <kelleycook@comcast.net>
+ * config/arm/arm-protos.h (arm_get_frame_size)
+ (thumb_get_frame_size): New prototypes.
+ * config/arm/arm.c (arm_get_frame_size)
+ (thumb_get_frame_size): New functions.
+ (use_return_insn, arm_output_epilogue, arm_output_function_epilogue)
+ (arm_compute_initial_elimination_offset, arm_expand_prologue): Use
+ arm_get_frame_size.
+ (thumb_expand_prologue, thumb_expand_epilogue): Use
+ thumb_get_frame_size.
+ * config/arm/arm.h (PREFERRED_STACK_BOUNDARY): Define.
+ (machine_function): Add frame_size member.
+ (THUMB_INITIAL_ELIMINATION_OFFSET): Use thumb_get_frame_size.
- * config/i386/i386.c (print_operand): Don't append ATT-style
- length suffixs to x87 opcodes when in Intel mode.
+2002-11-07 Richard Earnshaw <rearnsha@arm.com>
-2002-02-26 Ryan T. Sammartino <ryants@shaw.ca>
+ * arm.c (bit_count): Make argument unsigned long. Return unsigned.
+ Adjust code to use portable unsigned bit manipulation.
+ (insn_flags, tune_flags): Change type to unsigned.
+ (struct processors): Make flags unsigned long.
+ (arm_override_options): Change type of count and current_bit_count
+ to unsigned.
- * emit-rtl.c (gen_const_vector_0): Remove TYPE argument.
- (init_emit_once): Update calls.
- * fixinc/gnu-regex.c (_GNU_SOURCE): Remove.
- (init_syntax_once): Prototype.
+2002-11-07 Richard Earnshaw <rearnsha@arm.com>
+
+ * arm/elf.h (TYPE_OPERAND_FMT): Prefix type with %.
-2002-02-26 John David Anglin <dave@hiauly1.hia.nrc.ca>
+2002-11-07 J"orn Rennecke <joern.rennecke@superh.com>
- * pa-linux.h (LIB_SPEC): Update definition.
- * pa32-linux.h (LINK_COMMAND_SPEC): Delete.
+ * sh.h (DWARF_FRAME_RETURN_COLUMN): Use DWARF_FRAME_REGNUM.
-2002-02-26 Alexandre Oliva <aoliva@redhat.com>
+2002-11-07 Jan Hubicka <jh@suse.cz>
- * dwarf2out.c (gen_inlined_subroutine_die): If block is abstract,
- generate a die for the lexical block.
+ * reg-stack.c (compensate_edge): Fix sanity check.
-2002-02-26 Richard Henderson <rth@redhat.com>
+2002-11-05 Geoffrey Keating <geoffk@apple.com>
- * expr.c (expand_expr) [MULT_EXPR]: Do not apply distributive law
- in EXPAND_SUM case. Use host_integerp/tree_low_cst.
+ * config.gcc: Don't create crtbegin, crtend on Darwin; do create
+ crt2.o. Rearrange t-darwin makefiles.
+ * crtstuff.c [OBJECT_FORMAT_MACHO]: Delete.
+ * unwind-dw2-fde-darwin.c: New.
+ * unwind-dw2-fde-glibc.c: Correct comment.
+ * unwind-dw2-fde.c (__register_frame_info_bases)
+ [DWARF2_OBJECT_END_PTR_EXTENSION]: Clear fde_end.
+ (classify_object_over_fdes): Use last_fde.
+ (add_fdes): Likewise.
+ (linear_search_fdes): Likewise.
+ * unwind-dw2-fde.h (struct object)
+ [DWARF2_OBJECT_END_PTR_EXTENSION]: Add fde_end field.
+ (last_fde): New.
+ * config/darwin.h (STARTFILE_SPEC): Include crt2.o not crtbegin.o.
+ (ENDFILE_SPEC): No crtend.o.
+ * config/t-darwin: New.
+ * config/i386/t-darwin: Delete.
+ * config/darwin-crt2.c: New.
+ * config/rs6000/t-darwin: Delete contents duplicated in t-rs6000
+ or config/t-darwin.
-2002-02-26 Richard Henderson <rth@redhat.com>
+2002-11-06 David Edelsohn <edelsohn@gnu.org>
- * config/ia64/ia64.c (nop_cycles_until): Do init_insn_group_barriers
- if we emitted a stop bit.
+ PR target/8480
+ * config/rs6000/rs6000.md (movdi_internal64): Discourage
+ FPR to FPR moves.
-2002-02-26 Jakub Jelinek <jakub@redhat.com>
+2002-11-06 Janis Johnson <janis187@us.ibm.com>
- * configure.in (libgcc_visibility): Substitute.
- * configure: Rebuilt.
- * mklibgcc.in: If libgcc_visibility = yes, make libgcc.a global
- defined symbols .hidden.
+ * doc/contrib.texi: Merge in the list from the Java web pages.
-2002-02-26 Jakub Jelinek <jakub@redhat.com>
+2002-11-06 David O'Brien <obrien@FreeBSD.org>
- PR debug/5770
- * dwarf2out.c (rtl_for_decl_location): Return CONST_STRING for
- STRING_CST initializer spanning the whole variable without
- embedded zeros.
- If expand_expr returned MEM, don't use it.
+ * config/sparc/freebsd: Fix typo.
-2002-02-25 Jakub Jelinek <jakub@redhat.com>
+2002-11-06 John David Anglin <dave@hiauly1.hia.nrc.ca>
- PR target/5755
- * config/i386/i386.c (ix86_return_pops_args): Only pop
- fake structure return argument if it was passed on the stack.
+ * pa64-hpux.h (LDD_SUFFIX, PARSE_LDD_OUTPUT): Define.
-2002-02-25 Jason Merrill <jason@redhat.com>
+2002-11-06 Alexandre Oliva <aoliva@redhat.com>
- * attribs.c (decl_attributes): Also re-layout PARM_DECL and
- RESULT_DECL.
+ * config/mips/mips.md (call_value_multiple_internal2): Use dla for
+ non-SImode addresses.
-2002-02-25 Alexandre Oliva <aoliva@redhat.com>
+2002-11-05 Bob Wilson <bob.wilson@acm.org>
- * gcc.c (init_gcc_specs): Get -shared-libgcc along with -shared to
- link with shared_name only.
- * doc/invoke.texi (Link Options): Document new behavior.
+ * config/xtensa/elf.h (LIB_SPEC): Add "-lhal".
-2002-02-25 Aldy Hernandez <aldyh@redhat.com>
+2002-11-05 John David Anglin <dave2hiauly1.hia.nrc.ca>
- * c-typeck.c (push_init_level): Handle vectors.
+ * pa64-hpux.h (LIB_SPEC): Fix p and pg options.
+ (STARTFILE_SPEC): Remove p and pg options.
-2002-02-25 Alexandre Oliva <aoliva@redhat.com>
+2002-11-05 Andrew Haley <aph@redhat.com>
- * config/sparc/sparc.c (const64_high_operand): Zero-extend
- operands of SPARC_SETHI_P.
- (input_operand): Likewise.
- (sparc_emit_set_const32): Likewise.
- * config/sparc/sparc.h (SPARC_SETHI_P): Disregard TARGET_ARCH64.
- (SPARC_SETHI32_P): Zero-extend operand from 32 bits.
- (CONST_OK_FOR_LETTER_P): Use SETHI32 for `K'. Add `N' as SETHI.
- * config/sparc/sparc.md (movdi_insn_sp64_novis): Use `N'.
- (movdi_insn_sp64_vis): Likewise.
- (movdi split, movdf split): Use SETHI32.
- * doc/md.texi: Document SPARC constraints L, M and N.
+ * fold-const.c (fold): Don't transform (a0 op compound(a1,a2))
+ to (compound(a1,a0 op a2)) if a0 or a1 have side effects.
-2002-02-25 Aldy Hernandez <aldyh@redhat.com>
+2002-11-05 Richard Sandiford <rsandifo@redhat.com>
- * config/rs6000/rs6000.md ("get_vrsave_internal"): New.
- ("*set_vrsave_internal"): use mfspr for Darwin.
+ * config/mips/mips.h (CANNOT_CHANGE_MODE_CLASS): Move comment to...
+ * config/mips/mips.c (mips_cannot_change_mode_class): ...here.
- * config/rs6000/rs6000.c (rs6000_emit_prologue): Call
- gen_get_vrsave_internal.
+2002-11-04 Dale Johannesen <dalej@apple.com>
-Sun Feb 24 16:38:56 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * doloop.c (doloop_modify_runtime): Fix loop count computation
+ for unrolled loops.
+ * loop.c (loop_invariant_p): Support calling from unroller.
- * optabs.c (widen_operand): Properly handle CONST_INT for NO_EXTEND.
+2002-11-04 Ulrich Weigand <uweigand@de.ibm.com>
-2002-02-24 Neil Booth <neil@daikokuya.demon.co.uk>
+ * config/s390/s390.c (s390_decompose_address): Use arg_pointer_rtx
+ for comparison.
- * cpplex.c (cpp_interpret_charconst): Get signedness or
- otherwise of wide character constants correct.
- * cppexp.c (lex): Get signedness of wide charconsts correct.
+2002-11-04 Aldy Hernandez <aldyh@redhat.com>
-Sun Feb 24 07:41:31 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * hard-reg-set.h (REG_CANNOT_CHANGE_MODE_P): New.
- * optabs.c (widen_operand): Only call convert_modes for
- promoted SUBREG if signedness matches.
- * config/alpha/alpha.md (*addsi_se2, *subsi_se2): New patterns.
+ * config/rs6000/rs6000.h (CLASS_CANNOT_CHANGE_MODE_P): Remove.
+ (CLASS_CANNOT_CHANGE_MODE): Remove.
+ (CANNOT_CHANGE_MODE_CLASS): New.
-2002-02-23 Neil Booth <neil@daikokuya.demon.co.uk>
+ * config/alpha/alpha.h: Same.
- * cpplib.c (glue_header_name): Use local buffer to build up
- header name.
+ * config/ia64/ia64.h: Same.
-2002-02-23 Neil Booth <neil@daikokuya.demon.co.uk>
+ * config/mips/mips.h: Same.
- * doc/cpp.texi, doc/invoke.texi: Update documentation for -MM.
+ * config/s390/s390.h: Same.
-2002-02-23 Kazu Hirata <kazu@hxi.com>
+ * config/sh/sh.h: Same.
- * config/h8300/h8300.c (output_simode_bld): Handle H8/300 and
- H8/300[HS] separately.
- * config/h8300/h8300.md: Remove the early clobber constraint
- from bit field patterns.
+ * config/pa/pa64-regs.h: Same.
-2002-02-23 Kazu Hirata <kazu@hxi.com>
+ * config/sh/sh-protos.h (sh_cannot_change_mode_class): Add prototype.
- * config/h8300/h8300.md (mulqihi3): Tighten predicates to
- register_operand.
- (mulhisi3): Likewise.
- (umulqisi3): Likewise.
- (umulhisi3): Likewise.
+ * config/sh/sh.c (sh_cannot_change_mode_class): New.
-2002-02-23 Neil Booth <neil@daikokuya.demon.co.uk>
+ * config/mips/mips-protos.h (mips_cannot_change_mode_class): Add
+ prototype.
- * cppinit.c (output_deps): Correct test for stdout output.
- (init_dependency_output): Cure warning.
+ * config/mips/mips.c (mips_cannot_change_mode_class): New.
-Sat Feb 23 08:42:47 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * doc/tm.texi (Register Classes): Remove
+ CLASS_CANNOT_CHANGE_MODE and CLASS_CANNOT_CHANGE_MODE_P.
+ Document CANNOT_CHANGE_MODE_CLASS.
- * expr.c (store_expr): When converting expression to promoted
- equivalent type, allow using SUBREG_REG of TARGET as the target
- of the expansion of EXP.
- * loop.c (basic_induction_var, case SUBREG): Always look inside.
- * config/alpha/alpha.c (rtx_equiv_function_matters): Delete decl.
- (alpha_emit_set_const): Handle SImode when can't make new pseudos.
- (alpha_emit_set_const_1, alpha_sa_mask): Use no_new_pseudos.
- * config/alpha/alpha.md (addsi3, subsi3): Don't use if optimizing.
+ * reload.c (push_reload): Use CANNOT_CHANGE_MODE_CLASS.
+ (push_reload): Same.
-2002-02-23 Joseph S. Myers <jsm28@cam.ac.uk>
+ * simplify-rtx.c (simplify_subreg): Same.
- * doc/contribute.texi, doc/extend.texi, doc/install.texi,
- doc/invoke.texi, doc/md.texi, doc/passes.texi, doc/rtl.texi,
- doc/standards.texi, doc/tm.texi: Remove trailing whitespace.
+ * reload1.c (choose_reload_regs): Same.
-2002-02-23 Jakub Jelinek <jakub@redhat.com>
+ * recog.c (register_operand): Same.
- PR optimization/5747
- * loop.c (scan_loop): Update reg info if move_movables created new
- pseudos.
+ * regrename.c (mode_change_ok): Change to use new
+ CANNOT_CHANGE_MODE_CLASS infrastructure.
-2002-02-23 David Edelsohn <edelsohn@gnu.org>
+ * regclass.c (cannot_change_mode_set_regs): New.
+ Declare subregs_of_mode.
+ (regclass): Use subregs_of_mode.
+ Remove references to reg_changes_mode.
+ (init_reg_sets_1): Remove class_can_change_mode and
+ reg_changes_mode code.
+ (invalid_mode_change_p): New.
+ (dump_regclass): Use invalid_mode_change_p instead of
+ class_can_change_mode.
+ (regclass): Same.
+ (record_operand_costs): Do not set reg_changes_mode.
- * gcc.c (init_gcc_spec): Revert last change.
+ * local-alloc.c (struct qty): Remove changes_mode field.
+ (alloc_qty): Remove changes_mode initialization.
+ (update_qty_class): Remove set of changes_mode.
+ (find_free_reg): Use subregs_of_mode.
-2002-02-23 David Edelsohn <edelsohn@gnu.org>
+ * global.c (find_reg): Use subregs_of_mode info.
- * config/rs6000/rs6000.md (load_toc_aix_{si,di}): Use
- gpc_reg_operand constraint.
+ * rtl.h (cannot_change_mode_set_regs): New prototype.
+ (invalid_mode_change_p): Same.
+ (REG_CANNOT_CHANGE_MODE_P): New macro.
-2002-02-23 Alan Modra <amodra@bigpond.net.au>
+ * flow.c (mark_used_regs): Calculate subregs_of_mode. Remove
+ REG_CHANGES_MODE.
+ (life_analysis): Clear subregs_of_mode.
- * config/rs6000/rs6000.c (num_insns_constant): Fix formatting.
- Simplify comparison of `low'.
- (add_operand): Fix formatting.
- (non_add_cint_operand): Use CONST_OK_FOR_LETTER_P.
- (mask_operand): Disallow mask to wrap in 64-bit mode.
- (rs6000_stack_info): Remove redundant test setting push_p.
- (output_toc): Fix formatting.
- * config/rs6000/rs6000.md (boolsi3, boolcsi3 splitters): Use
- cc_reg_not_cr0_operand constraint.
- (booldi3, boolcdi3 splitters): Same.
+ * combine.c (subst): Pass class to CLASS_CANNOT_CHANGE_MODE_P.
+ Remove use of CLASS_CANNOT_CHANGE_MODE.
+ (simplify_set): Same.
+ (gen_lowpart_for_combine): Calculate subregs_of_mode. Remove
+ REG_CHANGES_MODE.
-2002-02-23 Aldy Hernandez <aldyh@redhat.com>
+ * regs.h: Add extern for subregs_of_mode;
+ Include hard-reg-set and basic-block.
+ (REG_CHANGES_MODE): Delete.
- * config/rs6000/altivec.h: Add extra level of parentheses on casts.
+2002-11-03 John David Anglin <dave@hiauly1.hia.nrc.ca>
-2002-02-22 David Edelsohn <edelsohn@gnu.org>
+ * jump.c (never_reached_warning): Don't set contains_insn until the
+ first line note is seen.
- * gcc.c (init_gcc_spec): Do not link with static libgcc.a if
- gcc invoked with -shared-libgcc.
+2002-11-03 David Edelsohn <edelsohn@gnu.org>
-2002-02-22 Jakub Jelinek <jakub@redhat.com>
+ * config/rs6000/rs6000.md (movti_string): Use string instructions.
- PR c++/5748
- * stmt.c (expand_anon_union_decl): Set TREE_USED on the anon union
- decl if any of elements was TREE_USED.
+2002-11-03 Roger Sayle <roger@eyesopen.com>
-2002-02-22 Alexandre Oliva <aoliva@redhat.com>
+ PR c/7128
+ * c-typeck.c (c_expand_asm_operands): Defend against
+ error_mark_nodes in the output argument to avoid ICE.
- * config/sparc/sol2.h: Don't include sys/mman.h.
- * config/sparc/sparc.c (arith_operand): Use SMALL_INT32.
- (arith_4096_operand): Don't throw high bits away.
- (const64_operand): Take sign extension of CONST_INTs into account.
- (const64_high_operand, sparc_emit_set_const32): Likewise.
- (GEN_HIGHINT64): Likewise.
- (sparc_emit_set_const64_quick1): Likewise.
- (const64_is_2insns): Likewise.
- (print_operand): Use trunc_int_for_mode for sign extension.
- * config/sparc/sparc.h (SMALL_INT32): Likewise.
- * config/sparc/sparc.md (movqi): Sign-extend CONST_DOUBLE
- chars. Assume CONST_INT is already properly sign-extended.
- (movdi split): Sign-extend each SImode part.
- (andsi3 split): Don't mask high bits off, so that result
- remains properly sign-extend.
- (iorsi3 split): Likewise.
- (xorsi3 split): Likewise.
+2002-11-03 Eric Botcazou <ebotcazou@libertysurf.fr>
-2002-02-22 Richard Sandiford <rsandifo@redhat.com>
+ PR middle-end/8408
+ * genrecog.c (preds): Handle ADDRESSOF.
+ (validate_pattern): Mark it as an lvalue.
- * fold-const.c (fold): Fix typo in comments.
+2002-11-02 David Edelsohn <edelsohn@gnu.org>
-2002-02-21 Diego Novillo <dnovillo@redhat.com>
+ * config/rs6000/rs6000.c (rs6000_override_options): Use string
+ instructions when optimizing for size.
- * Makefile.in (langhooks.o): Update dependencies.
+2002-11-02 Kazu Hirata <kazu@cs.umass.edu>
-2002-02-21 Diego Novillo <dnovillo@redhat.com>
+ * config/h8300/h8300.h: Fix comment typos.
+ * config/h8300/h8300.md: Likewise.
+ * config/h8300/lib1funcs.asm: Likewise.
- * langhooks.c: Include flags.h.
+2002-11-02 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
-2002-02-21 Aldy Hernandez <aldyh@redhat.com>
+ Revert this change:
- * testsuite/gcc.dg/attr-alwaysinline.c: New.
+ *doc/install.texi (Installing GCC: Configuration): Clarify
+ the only supported ways to configure gcc.
- * c-common.c (c_common_post_options): Set inline trees by
- default.
+2002-11-01 Kazu Hirata <kazu@cs.umass.edu>
- * doc/extend.texi (Function Attributes): Document always_inline
- attribute.
- Update documentation about inlining when not optimizing.
+ * config/h8300/h8300.md (anonymous and:QI pattern): Use 'n'
+ instead of 'O' for the constraint for the second operand.
- * cp/decl.c (duplicate_decls): Merge always_inline attribute.
+2002-11-01 Mark Mitchell <mark@codesourcery.com>
- * cp/tree.c (cp_cannot_inline_tree_fn): Do not inline at -O0
- unless DECL_ALWAYS_INLINE.
+ PR c++/8391
+ * toplev.c (rest_of_compilation): Do not refuse to output code for
+ an inline function in a local class.
- * c-objc-common.c (c_cannot_inline_tree_fn): Do not inline at -O0
- unless DECL_ALWAYS_INLINE.
- (c_disregard_inline_limits): Disregard if always_inline set.
+2002-11-01 David O'Brien <obrien@FreeBSD.org>
- * langhooks.c (lhd_tree_inlining_disregard_inline_limits):
- Disregard if always_inline set.
- (lhd_tree_inlining_cannot_inline_tree_fn): Do not inline at -O0
- unless DECL_ALWAYS_INLINE.
+ * config/sparc/freebsd.h (CPP_CPU64_DEFAULT_SPEC): Define __arch64__.
+ (TRANSFER_FROM_TRAMPOLINE): Reformat.
+ Add comment.
- * attribs.c (handle_always_inline_attribute): New.
- (c_common_attribute_table): Add always_inline.
+2002-11-01 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/h8300.h (CAN_ELIMINATE): Simplify.
+
+2002-11-01 Toshiyasu Morita <toshiyasu.morita@hsa.hitachi.com>
+
+ * config/h8300/h8300.h (OPTIMIZATION_OPTIONS): New.
+
+2002-11-01 Steve Ellcey <sje@cup.hp.com>
+
+ * config/ia64/ia64.h (MASK_INLINE_DIV_LAT): Remove.
+ (MASK_INLINE_DIV_THR): Remove.
+ (TARGET_INLINE_DIV_LAT): Remove.
+ (TARGET_INLINE_DIV_THR): Remove.
+ (TARGET_INLINE_DIV): Remove.
+ (MASK_INLINE_FLOAT_DIV_LAT): New macro.
+ (MASK_INLINE_FLOAT_DIV_THR): New macro.
+ (MASK_INLINE_INT_DIV_LAT): New macro.
+ (MASK_INLINE_INT_DIV_THR): New macro.
+ (TARGET_INLINE_FLOAT_DIV_LAT): New macro.
+ (TARGET_INLINE_FLOAT_DIV_THR): New macro.
+ (TARGET_INLINE_INT_DIV_LAT): New macro.
+ (TARGET_INLINE_INT_DIV_THR): New macro.
+ (TARGET_INLINE_FLOAT_DIV): New macro.
+ (TARGET_INLINE_INT_DIV): New macro.
+ * config/ia64/ia64.md (divsi3): Change to use new macros.
+ (modsi3): Ditto.
+ (udivsi3): Ditto.
+ (umodsi3): Ditto.
+ (divsi3_internal): Ditto.
+ (divdi3): Ditto.
+ (moddi3): Ditto.
+ (udivdi3): Ditto.
+ (umoddi3): Ditto.
+ (divdi3_internal_lat): Ditto.
+ (divdi3_internal_thr): Ditto.
+ (divsf3): Ditto.
+ (divsf3_internal_lat): Ditto.
+ (divsf3_internal_thr): Ditto.
+ (divdf3): Ditto.
+ (divdf3_internal_lat): Ditto.
+ (divdf3_internal_thr): Ditto.
+ (divtf3): Ditto.
+ (divtf3_internal_lat): Ditto.
+ (divtf3_internal_thr): Ditto.
+ * config/ia64/ia64.c (ia64_override_options): Change
+ to check new macros for conflicts in settings.
+ * doc/invoke.texi (-minline-divide-min-latency): Remove.
+ (-minline-divide-max-throughput): Remove.
+ (-minline-float-divide-min-latency): New.
+ (-minline-float-divide-max-throughput): New.
+ (-minline-int-divide-min-latency): New.
+ (-minline-int-divide-max-throughput): New.
- * config/rs6000/altivec.h: Add prototypes for builtins
- requiring the always_inline attribute.
+2002-11-01 Richard Earnshaw (rearnsha@arm.com)
-2002-02-21 Eric Christopher <echristo@redhat.com>
+ PR target/7856
+ * arm.c (use_return_insn): Don't use a return insn if there are
+ saved integer regs, but LR is not one of them.
- * expmed.c (store_bit_field): Try to simplify the subreg
- before generating a new one when when the mode size of
- value is less than maxmode.
+2002-11-01 Jan Hubicka <jh@suse.cz>
-2002-02-21 Richard Henderson <rth@redhat.com>
+ * expr.c (emit_move_insn): Use SCALAR_FLOAT_MODE_P
+ * machmode.h (SCALAR_FLOAT_MODE_P): New macro.
- * emit-rtl.c (offset_address): Use simplify_gen_binary rather
- than gen_rtx_PLUS to form the sum.
- * explow.c (force_reg): Rearrange to not allocate new pseudo
- when force_operand returns a register.
- * expr.c (expand_assignment): Allow offset_rtx expansion to
- return a sum. Do not force addresses into registers.
- (expand_expr): Likewise.
- * simplify-rtx.c (simplify_gen_binary): Use simplify_plus_minus
- to canonicalize arithmetic that didn't simpify.
- (simplify_plus_minus): New argument force; update
- all callers. Don't split CONST unless we can do something with it,
- and wouldn't lose the constness of the operands.
+2002-10-31 Nathanael Nerode <neroden@gcc.gnu.org>
- * config/i386/i386.c (legitimize_pic_address): Recognize UNSPECs
- that we generated earlier.
+ PR optimization/6162
+ * doc/md.texi: Document restriction on commutative operand
+ specification.
-2002-02-21 Tom Tromey <tromey@redhat.com>
+2002-10-31 Eric Christopher <echristo@redhat.com>
- * dwarf2out.c (DWARF_LINE_MIN_INSTR_LENGTH): Removed.
- (output_line_info): Use constant `1', with a long explanatory
- comment.
- * system.h (DWARF_LINE_MIN_INSTR_LENGTH): Poison.
+ * explow.c (convert_memory_address): Use shallow_copy_rtx.
-Thu Feb 21 22:43:44 2002 J"orn Rennecke <joern.rennecke@superh.com>
+2002-10-31 Steve Ellcey <sje@cup.hp.com>
- * jump.c (redirect_jump): If old label has no UID, don't try to
- delete it.
+ * expmed.c (store_bit_field): Check FUNCTION_ARG_REG_LITTLE_ENDIAN.
-Thu Feb 21 21:17:21 2002 J"orn Rennecke <joern.rennecke@superh.com>
+2002-10-31 Steve Ellcey <sje@cup.hp.com>
- * sh.md (insv): Provide byte offsets for gen_rtx_SUBREG.
- If input is constant, do shifts at compile time.
+ * config/ia64/hpux.h (MEMBER_TYPE_FORCES_BLK): Set for non-floats.
-2002-02-21 Joseph S. Myers <jsm28@cam.ac.uk>
+Thu Oct 31 Dale Johannesen <dalej@apple.com>
- * doc/extend.texi: Fix some more overfull hboxes.
+ * config/rs6000/darwin.h: Correct formatting in previous.
-2002-02-21 Jakub Jelinek <jakub@redhat.com>
+Thu Oct 31 Dale Johannesen <dalej@apple.com>
- PR optimization/4994
- * config/i386/i386.md (movsi_1, movsf_1): Support MMX -> MMX
- register moves.
+ * config/rs6000/darwin.h: Enable -falign-xxx options.
-2002-02-21 Jakub Jelinek <jakub@redhat.com>
+2002-10-31 Jan Hubicka <jh@suse.cz>
- PR c++/4574
- * expr.h (expand_and): Add mode argument.
- * expmed.c (expand_and): Add mode argument.
- (expand_mult_highpart_adjust, emit_store_flag): Adjust callers.
- * expr.c (store_field, expand_expr, do_store_flag): Likewise.
- * except.c (expand_builtin_extract_return_addr): Likewise.
- * config/alpha/alpha.c (alpha_initialize_trampoline): Likewise.
- * config/sparc/sparc.c (sparc_initialize_trampoline): Likewise.
- * config/c4x/c4x.h (INITIALIZE_TRAMPOLINE): Likewise.
- Use GEN_INT (x) instead of gen_rtx (CONST_INT, VOIDmode, x).
- * config/c4x/c4x.md: Use GEN_INT (x) instead of
- gen_rtx (CONST_INT, VOIDmode, x).
+ * i386.c (override_options): Set defaults for flag_omit_frame_pointer,
+ flag_asynchronous_unwind_tables, flag_pcc_struct_return.
+ * i386.c (optimization_options): Set flag_omit_frame_pointer,
+ flag_asynchronous_unwind_tables, flag_pcc_struct_return to 2.
+ Do not clear -momit-leaf-frame-pointer when profiling.
+ (ix86_frame_pointer_required): Frame pointer is always required when
+ profiling.
-2002-02-21 Jakub Jelinek <jakub@redhat.com>
+2002-10-31 Jan Hubicka <jh@suse.cz>
- PR c/4697:
- * stmt.c (warn_if_unused_value): Move side effects test once more.
+ * i386.md (negdf2_ifs_rex64): Don't allow GPR operand.
-2002-02-20 Torbjorn Granlund <tege@swox.com>
+2002-10-31 J"orn Rennecke <joern.rennecke@superh.com>
- * config/avr/avr.md: Add more patterns for mized-mode add and subtract
- (addsi3_zero_extend, subhi3_zero_extend1, subsi3_zero_extend).
+ * sh.h (binary_logical_operator): Declare.
+ * sh.c (binary_logical_operator): New function.
+ * sh.md (xordi3+1): New combiner splitter pattern.
-Thu Feb 21 16:20:46 2002 Alexandre Oliva <aoliva@redhat.com>
+2002-10-31 David O'Brien <obrien@FreeBSD.org>
- * rtlanal.c (replace_rtx): Don't make a CONST_INT the operand of
- SUBREG or ZERO_EXTEND.
+ * config/sparc/freebsd.h (TRANSFER_FROM_TRAMPOLINE): Define
+ __enable_execute_stack function.
-Thu Feb 21 15:35:46 2002 J"orn Rennecke <joern.rennecke@superh.com>
+2002-10-30 Aldy Hernandez <aldyh@redhat.com>
+
+ * c-common.c: Add GTY to vector_type_node_list.
+
+2002-10-30 John David Anglin <dave@hiauly.hia.nrc.ca>
+
+ * pa-linux.h (ASM_OUTPUT_EXTERNAL_LIBCALL): Define.
+ * pa-protos.h (attr_length_millicode_call, attr_length_call,
+ pa_init_machine_status): Declare new global functions.
+ * pa.c (void copy_fp_args, length_fp_args, get_plabel): Declare and
+ implement new functions.
+ (attr_length_millicode_call, attr_length_call): Implement.
+ (total_code_bytes): Change type to long.
+ (pa_output_function_prologue): Compute total_code_bytes on TARGET_64BIT.
+ Reset counter if flag_function_sections.
+ (output_deferred_plabels): Set output alignment to 3 for TARGET_64BIT.
+ (output_cbranch): Move call to gen_label_rtx.
+ (output_millicode_call): Rewrite adding long TARGET_64BIT call, expose
+ delay slot in all variants, shorten pc-relative calls.
+ (output_call): Rewrite adding long TARGET_64BIT call, improved delay
+ slot usage and exposure, various new call variants, and shortened
+ sequences for some variants on TARGET_PA_20.
+ Miscellaneous format changes.
+ * pa.h (total_code_bytes): Change type to long.
+ (MASK_LONG_CALLS, TARGET_LONG_CALLS, TARGET_LONG_ABS_CALL,
+ TARGET_LONG_PIC_SDIFF_CALL, TARGET_LONG_PIC_PCREL_CALL): Define.
+ (TARGET_SWITCHES): Add "-mlong-calls" and "-mno-long-calls" options.
+ (EXTRA_CONSTRAINT, GO_IF_LEGITIMATE_ADDRESS,
+ LEGITIMIZE_RELOAD_ADDRESS): Don't use long floating point loads and
+ stores on TARGET_ELF32.
+ *pa.md (define_delay): Allow insns in delay on TARGET_PORTABLE_RUNTIME.
+ (unnamed patterns for mulsi3, divsi3, udivsi3, modsi3, umodsi3 and
+ canonicalize_funcptr_for_compare expanders): Calculate attribute length
+ attr_length_millicode_call().
+ (call_internal_symref, call_value_internal_symref): Clobber register 1.
+ Calculate attribute length using attr_length_call().
+ (call_internal_reg_64bit, call_value_internal_reg_64bit): Move gp load
+ to delay slot.
+ (sibcall, sibcall_value): Rewrite.
+ (sibcall_internal_symref, sibcall_value_internal_symref): Clobber
+ register 1. Use attr_length_call().
+ (sibcall_internal_symref_64bit, sibcall_value_internal_symref_64bit):
+ New patterns.
+ (unamed pattern for canonicalize_funcptr_for_compare): Rewrite.
+ * som.h (MEMBER_TYPE_FORCES_BLK): Define.
+ * t-pa64 (TARGET_LIBGCC2_CFLAGS): Add "-mlong-calls".
+ * doc/invoke.texi (mlong-calls): Document.
+
+2002-10-30 Roger Sayle <roger@eyesopen.com>
+
+ * fold-const.c (fold_binary_op_with_conditional_arg): Improve
+ handling of cases where one or both branches of the conditional
+ have void type, i.e. throw an exception or don't return.
+ (fold): Only apply (and undo) type conversion to the non-void
+ branches of a COND_EXPR.
- * sh.h (current_function_anonymous_args): Remove.
- (SETUP_INCOMING_VARARGS): Don't set it - just check that one
- of current_function_varargs and current_function_stdarg is set.
- * sh.c (sh_expand_prologue): Check current_function_varargs /
- current_function_stdarg / TARGET_SH5 instead of
- current_function_anonymous_args.
+2002-10-30 Mark Mitchell <mark@codesourcery.com>
- * sh64.h (TARGET_VERSION): Define.
+ PR c++/8333
+ * varasm.c (asm_output_aligned_bss): Do not call
+ ASM_GLOBALIZE_LABEL.
-2002-02-20 David Edelsohn <edelsohn@gnu.org>
+2002-10-30 David Edelsohn <edelsohn@gnu.org>
+ Torbjorn Granlund <tege@swox.com>
- * config/rs6000/rs6000.h (EPILOGUE_USES): Conditionalize
- VRSAVE_REGNO on TARGET_ALTIVEC.
+ * config/rs6000/rs6000.md (load_toc_v4_PIC_1): Use preferred form
+ for addressibility.
+ (load_toc_v4_PIC_1b): Same.
-2002-02-20 Alan Modra <amodra@bigpond.net.au>
+2002-10-30 Kazu Hirata <kazu@cs.umass.edu>
- * config/rs6000/rs6000.c (includes_lshift_p): Mask irrelevant
- bits of SImode const_int.
- (includes_rshift_p): Likewise.
- (print_operand): Call mask_operand and mask64_operand with correct
- mode.
- (rs6000_output_function_epilogue): Pad traceback table to word.
- * config/rs6000/rs6000.h (MASK_64BIT): Correct comment.
- (EXTRA_CONSTRAINT, 'S' and 'T'): Call mask_operand and
- mask64_operand with correct mode.
- (FUNCTION_ARG_REGNO_P): Correct parentheses.
+ * config/h8300/h8300.c (h8300_eightbit_constant_address_p):
+ Truncate the addresses for H8/300 using HImode.
-2002-02-20 Jakub Jelinek <jakub@redhat.com>
+2002-10-29 Hans-Peter Nilsson <hp@bitrange.com>
- PR debug/4461
- * varasm.c (get_pool_constant_mark): New.
- * rtl.h (get_pool_constant_mark): Add prototype.
- * dwarf2out.c (mem_loc_descriptor): A pool constant cannot
- be represented if it has not been output.
+ * toplev.c (rest_of_type_compilation): Return early in case of
+ errors.
+ (check_global_declarations): Don't call debug_hooks->global_decl
+ in case of errors.
-2002-02-20 Alexandre Oliva <aoliva@redhat.com>
+2002-10-28 Andreas Bauer <baueran@in.tum.de>
- * combine.c (do_SUBST): Sanity check substitutions of
- CONST_INTs, and reject them in SUBREGs and ZERO_EXTENDs.
- (subst): Simplify SUBREG or ZERO_EXTEND instead of SUBSTing a
- CONST_INT into its operand.
- (known_cond): Likewise, for ZERO_EXTEND.
- * simplify-rtx.c (simplify_unary_operation): Fix condition to
- allow for simplification of wide modes. Reject CONST_INTs in
- ZERO_EXTEND when their actual mode is not given.
+ * doc/c-tree.texi (Tree overview): Fix typos.
-2002-02-20 Alexandre Oliva <aoliva@redhat.com>
+2002-10-29 Phil Edwards <pme@gcc.gnu.org>
- * c-decl.c (pushdecl): If no global declaration is found for an
- extern declaration in block scope, try a limbo one.
+ * Makefile.in (gnucompare*): Only record bad comparisons
+ if there really was a bad comparison.
-2002-02-20 Jakub Jelinek <jakub@redhat.com>
+2002-10-29 Jan Hubicka <jh@suse.cz>
- PR c++/4401
- * c-common.c (pointer_int_sum): Moved from...
- * c-typeck.c (pointer_int_sum): ...here.
- * c-common.h (pointer_int_sum): Add prototype.
+ * i386.h (CONST_DOUBLE_OK_FOR_LETTER_P): Remove 'H'
+ * i386.md (movsf*, movdf*): Use 'C' instead of 'H'
+ * md.texi (machine dependent constraints): Document 'C'
-2002-02-20 Jakub Jelinek <jakub@redhat.com>
+ * simplify-rtx.c (simplify_subreg): Fix const_int->vector subregging.
- PR c++/5713
- * c-decl.c (duplicate_decls): Return 0 if issued error about
- redeclaration.
+ * i386.c (ix86_expand_vector_move): Fix.
-2002-02-20 Roger Sayle <roger@eyesopen.com>
- Jakub Jelinek <jakub@redhat.com>
+ * i386.c (ix86_expand_builtin): Use sse2_maskmovdqu_rex64.
+ * i386.md (sse2_maskmovdqu_rex64): New pattern
- PR c/4389
- * tree.c (host_integerp): Ensure that the constant integer is
- representable in a HOST_WIDE_INT or an unsigned HOST_WIDE_INT
- when pos is zero or non-zero respectively. Clarify comment.
- * c-format.c (check_format_info_recurse): Fix host_integerp
- usage; the pos argument should be zero when assigning to a
- signed HOST_WIDE_INT.
+ PR target/8322
+ * xmmintrin.h (_mm_stream_pi, _mm_stream_pd): Fix cast.
+ (ix86_init_mmx_sse_builtins): Fix type.
-2002-02-20 Richard Henderson <rth@redhat.com>
+2002-10-29 Jason Thorpe <thorpej@wasabisystems.com>
- * config/i386/i386.c (ix86_expand_vector_move): Use the mode
- of the operand, rather than assuming TImode.
- (ix86_expand_binop_builtin): Cope with commutative patterns
- using nonimmediate_operand for both operands.
- (ix86_expand_timode_binop_builtin): Likewise.
- (ix86_expand_store_builtin): Validate operand 1.
- (ix86_expand_unop1_builtin): Likewise.
+ * gthr-posix.h: Include <unistd.h> for feature tests.
+ (sched_get_priority_max, sched_get_priority_min)
+ (pthread_getschedparam, pthread_setschedparam): Only use
+ if _POSIX_THREAD_PRIORITY_SCHEDULING is defined.
+ (__gthread_objc_thread_set_priority): Don't treat all non-zero
+ returns from sched_get_priority_max and sched_get_priority_min
+ as an error.
-2002-02-20 Philip Blundell <philb@gnu.org>
+2002-10-29 Kazu Hirata <kazu@cs.umass.edu>
- PR 5705
- * config/arm/arm.h (HARD_REGNO_RENAME_OK): New macro.
+ * config/h8300/h8300.h (TARGET_DEFAULT): Make it
+ MASK_QUICKCALL.
-2002-02-20 Richard Henderson <rth@redhat.com>
+2002-10-29 Kazu Hirata <kazu@cs.umass.edu>
- PR c/5615
- * expr.h (ARGS_SIZE_TREE): Convert size.var to ssizetype.
+ * config/h8300/h8300.c (h8300_eightbit_constant_address_p): New.
+ (h8300_tiny_constant_address_p): Likewise.
+ * config/h8300/h8300.h (EIGHTBIT_CONSTANT_ADDRESS_P): Use
+ h8300_eightbit_constant_address_p.
+ (TINY_CONSTANT_ADDRESS_P): Use h8300_tiny_constant_address_p.
+ * config/h8300/h8300-protos.h: Add the prototypes for the two
+ new functions.
-2002-02-20 Tom Tromey <tromey@redhat.com>
+2002-10-29 Kazu Hirata <kazu@cs.umass.edu>
- * config/fr30/fr30.h (DWARF_LINE_MIN_INSTR_LENGTH): Removed.
- * config/sh/sh.h (DWARF_LINE_MIN_INSTR_LENGTH): Removed.
- * config/pj/pj.h (DWARF_LINE_MIN_INSTR_LENGTH): Removed.
- * config/cris/cris.h (DWARF_LINE_MIN_INSTR_LENGTH): Removed.
- * dwarf2out.c (DWARF_LINE_MIN_INSTR_LENGTH): Define
- unconditionally.
+ * reload1.c (update_eliminables): Unconditionally check if
+ frame_pointer_needed has changed.
-Wed Feb 20 00:03:25 EST 2002 Alan Matsuoka <alanm@redhat.com>
+2002-10-29 Jan Hubicka <jh@suse.cz>
- * config/rs6000/rs6000.h (LEGITIMATE_OFFSET_ADDRESS_P): Look
- for (const_int 0) in X not just INTVAL.
+ * toplev.c (rest_of_compilation): Reorganize way reg_scan is called
+ before final pass.
-2002-02-20 Joseph S. Myers <jsm28@cam.ac.uk>
+2002-10-29 Eric Botcazou <ebotcazou@libertysurf.fr>
- * doc/extend.texi: Avoid or reduce overfull hboxes.
+ PR optimization/8334
+ * expr.c (expand_expr) [PLUS]: Don't use simplify_binary_operation;
+ check for zero operands explicitly.
-2002-02-20 Diego Novillo <dnovillo@redhat.com>
+2002-10-29 Richard Sandiford <rsandifo@redhat.com>
- * expmed.c (store_bit_field): Do not store bit fields using SUBREG
- operations if the field does not start at a mode boundary.
+ * config/mips/mips.md (extv, extzv, insv): Set size of referenced
+ memory after adjusting to BLKmode.
-2001-02-20 Joel Sherrill <joel@OARcorp.com>
+2002-10-29 Kazu Hirata <kazu@cs.umass.edu>
- * config/a29k/rtems.h, config/arm/rtems-elf.h, config/h8300/rtems.h,
- config/mips/rtems.h: Use new style of -Asystem= rather than -Asystem().
- Also done for -Acpu and -Amachine.
+ * config/h8300/h8300.h (MASK_*): New.
+ (TARGET_*): Use MASK_*.
-2002-02-20 Neil Booth <neil@daikokuya.demon.co.uk>
+2002-10-28 Jason Thorpe <thorpej@wasabisystems.com>
- * cppinit.c (init_dependency_output): Take deps output file
- from -o if none given with -MF. Suppress normal output.
- * gcc.c (cpp_unique_options): Have -M and -MM imply -E.
- * doc/cpp.texi, doc/invoke.texi: Update.
+ * config.gcc (*-*-netbsd*): Add NETBSD_ENABLE_PTHREADS to
+ tm_defines if pthreads are enabled.
+ * config/netbsd.h (LIB_SPEC): Only support the -pthread option
+ if NETBSD_ENABLE_PTHREADS is defined.
-2002-02-19 Zack Weinberg <zack@codesourcery.com>
+2002-10-28 Kazu Hirata <kazu@cs.umass.edu>
- * toplev.c (output_quoted_string): Write unprintable
- characters with octal escapes.
+ * ChangeLog.1: Fix typos.
+ * cse.c: Fix a comment typo.
+ * reload1.c: Likewise.
-2002-02-19 David Edelsohn <edelsohn@gnu.org>
+2002-10-27 Hans-Peter Nilsson <hp@bitrange.com>
- * config/rs6000/rs6000.h (CONDITIONAL_REGISTER_USAGE): Set
- really_call_used[VRSAVE_REGNO] if not Altivec.
+ * fixinc/inclhack.def (libc1_G_va_list): Correct test_text.
+ * fixinc/tests/base/_G_config.h: New file.
-2002-02-19 Alan Modra <amodra@bigpond.net.au>
+2002-10-27 Kazu Hirata <kazu@cs.umass.edu>
- * config/rs6000/rs6000.c (u_short_cint_operand): Mask op with
- MODE_MASK.
- (constant_pool_expr_1): Fix formatting.
- (rs6000_legitimize_reload_address): Likewise.
+ * combine.c: Fix comment formatting.
+ * loop.c: Likewise.
+ * real.c: Likewise.
+ * regclass.c: Likewise.
+ * regmove.c: Likewise.
+ * regrename.c: Likewise.
+ * reg-stack.c: Likewise.
+ * reload1.c: Likewise.
+ * reload.c: Likewise.
+ * reload.h: Likewise.
+ * unroll.c: Likewise.
-Tue Feb 19 20:13:57 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2002-10-27 Kazu Hirata <kazu@cs.umass.edu>
- * config/sparc/sparc.md (nonlocal_goto): Use hard_frame_pointer_rtx
- now that we have one.
+ * reload1.c (reload): Fix a comment typo.
-2002-02-19 Zack Weinberg <zack@codesourcery.com>
+2002-10-27 Jan Hubicka <jh@suse.cz>
- * tree.h (struct tree_common): Remove aux. Add unused_0 at
- end of first block of bitfields (which was only seven bits);
- rename dummy to unused_1; remove comment which is no longer true.
+ * linux64.h (DEFAULT_PCC_STRUCT_RETURN): Define.
-2002-02-19 Gaute B Strokkenes <gs234@cam.ac.uk>
+2002-10-27 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
- * doc/c-tree.texi (Classes, TYPE_BINFO): Fix typo.
+ * Makefile.in (dwarf2out.o): Add dependendcy on hashtab.h.
+ * dwarf2out.c: Include hashtab.h.
+ (is_main_source): New static variable.
+ (attr_checksum, die_checksum): Modified to handle die references.
+ (same_loc_p, same_dw_val_p, same_attr_p, same_die_p, same_die_p_wrap,
+ unmark_all_dies, htab_cu_hash, htab_cu_eq, htab_cu_del, check_duplicate_cu,
+ record_comdat_symbol_number): New static functions.
+ (output_comp_unit, compute_section_prefix, is_type_die, break_out_includes,
+ mark_dies, unmark_dies, dwarf2out_start_source_file): Modified.
+ * toplev.c (rest_of_decl_compilation): Call of dwarf2out_decl for type
+ declarations added.
-2002-02-19 Philip Blundell <pb@nexus.co.uk>
+2002-10-26 Kazu Hirata <kazu@cs.umass.edu>
- PR 5399
- * config/arm/arm.h (THUMB_LEGITIMATE_CONSTANT_P): Accept anything
- if generating PIC.
+ * config/h8300/h8300.c (initial_offset): Change to
+ h8300_initial_elimination_offset.
+ * config/h8300/h8300.h (INITIAL_ELIMINATION_OFFSET): Use
+ h8300_initial_elimination_offset.
+ * config/h8300/h8300-protos.h: Update the prototype.
- PR 5054
- * config/arm/arm.md (call_insn) [TARGET_THUMB]: Use
- arm_is_longcall_p rather than inspecting call-type cookie
- directly.
- (call_value_insn) [TARGET_THUMB]: Likewise.
+2002-10-26 Hans-Peter Nilsson <hp@bitrange.com>
-2002-02-19 Graham Stott <grahams@redhat.com>
+ * config/mmix/mmix.h (LIBCALL_VALUE): Use
+ MMIX_RETURN_VALUE_REGNUM, not MMIX_OUTGOING_RETURN_VALUE_REGNUM.
+ (FUNCTION_VALUE_REGNO_P): Similar, but move code to...
+ * config/mmix/mmix.c (mmix_function_value_regno_p): New.
+ * config/mmix/mmix-protos.h: Remove needless ifdefs on TREE_CODE
+ and RTX_CODE.
+ (mmix_function_value_regno_p): Declare.
- * config/i386/i386.c (ix86_expand_builtin): Fix typo.
+ * config/mmix/mmix.md ("fixuns_truncdfdi2"): Replace unsigned_fix,
+ invalid for floating point mode result, with fix.
-2002-02-19 David Edelsohn <edelsohn@gnu.org>
+2002-10-25 Mike Stump <mrs@apple.com>
- * config/rs6000/linux64.h (LINK_OS_LINUX_SPEC): Look in /lib64.
- ({STARTFILE,ENDFILE}_LINUX_SPEC): Define.
- (FP_SAVE_INLINE): Delete.
+ Fixes gcc.dg/warn-1.c.
+ * c-typeck.c (warn_for_assignment): Don't print argument number, if zero.
- * config/rs6000/sysv4.h (ENDFILE_SPEC): Add crtsaveres.o.
- * config/rs6000/eabi.asm: Remove ABI save restore routines.
- * config/rs6000/t-ppccomm: Build crtsavres.o.
- * config/rs6000/crtsavres.asm: New file.
+2002-10-26 Jan Hubicka <jh@suse.cz>
-2002-02-19 Philip Blundell <philb@gnu.org>
+ * toplev.c (dump_file_index): Add DFI_ce3.
+ (dump_file_info): Likewise.
+ (rest_of_compilation): Run first ifcvt pass before tracer.
- * config/arm/arm.c (use_return_insn): Don't reject interrupt
- functions.
- (arm_compute_save_reg_mask): Save LR for interrupt functions too.
- (output_return_instruction): Allow interrupt functions to return with
- ldmfd sp!, {... pc}^. Use LDR to restore any single register.
- (arm_expand_prologue): Subtract 4 before stacking LR in an
- interrupt function.
+2002-10-25 Steve Ellcey <sje@cup.hp.com>
-2002-02-19 Philip Blundell <pb@nexus.co.uk>
+ * config/ia64/hpux.h (BITS_BIG_ENDIAN): Remove.
- * config/arm/arm.c (arm_encode_call_attribute): Operate on any
- decl, not just FUNCTION_DECL.
- (legitimize_pic_address): Handle local SYMBOL_REF like LABEL_REF.
- (arm_assemble_integer): Likewise.
- * config/arm/arm.h (ARM_ENCODE_CALL_TYPE): Allow any decl to be
- marked local.
+2002-10-25 Richard Henderson <rth@redhat.com>
-2002-02-19 matthew green <mrg@eterna.com.au>
+ * real.c (real_to_decimal): If the >1 tens reduction loop results
+ in a negative exponent, fall into the <1 pten computation.
- * config.gcc (sparc-*-netbsdelf*): Enable target.
- (sparc64-*-netbsd*): New target.
- * config/sparc/netbsd-elf.h: New file.
- * config/sparc/t-netbsd64: New file.
+2002-10-25 Zack Weinberg <zack@codesourcery.com>
-2002-02-19 Gaute B Strokkenes <gs234@cam.ac.uk>
+ PR middle-end/6994
+ * c-objc-common.c (inline_forbidden_p): Can not inline
+ functions containing structures or unions containing VLAs.
+ * tree-inline.c (walk_tree): For all class 't' nodes, walk
+ TYPE_SIZE and TYPE_SIZE_UNIT.
+ (copy_tree_r): Copy types if they are variably modified.
- * doc/rtl.texi (Flags, MEM_SCALAR_P): Fix typo.
+2002-10-25 Ulrich Weigand <uweigand@de.ibm.com>
-2002-02-19 Ryan T. Sammartino <ryants@shaw.ca>
+ * config/s390/s390.md: Remove old-style peepholes.
- * doc/invoke.texi: explicitly list the style guidelines that
- -Weffc++ checks for.
+2002-10-25 Ulrich Weigand <uweigand@de.ibm.com>
-Tue Feb 19 12:37:23 CET 2002 Jan Hubicka <jh@suse.cz>
+ * config/s390/s390.c (s390_decompose_address): Do not range check the
+ displacement if base or index is the argument pointer register.
- * regmove.c (regmove_optimize): Avoid increasing of register pressure.
+2002-10-24 Hans-Peter Nilsson <hp@bitrange.com>
-2002-02-19 Neil Booth <neil@daikokuya.demon.co.uk>
+ PR other/3337
+ PR bootstrap/6763
+ PR bootstrap/8122
+ * fixinc/inclhack.def (libc1_G_va_list): New fix.
+ * fixinc/fixincl.x: Regenerate.
+ * config/i386/linux.h: Move MD_FALLBACK_FRAME_STATE_FOR inside
+ ifndef IN_LIBGCC2. Wrap it together with signal.h and
+ sys/ucontext.h inclusion in ifndef USE_GNULIBC_1.
+ * configure.in (gcc_AC_CHECK_DECLS): Check vasprintf too.
+ * config.in, configure: Regenerate.
- PR other/5718
- * gcc.c (cpp_unique_options): Treat -o as indicating object file
- only if not -E. If -E, pass -o through to the preprocessor.
+2002-10-24 Igor Shevlyakov <igor@microunity.com>
-2002-02-19 Kazu Hirata <kazu@hxi.com>
+ * varasm.c (struct rtx_const): Array size 16 for V16QImode.
- * config/h8300/h8300.h (REGNO_REG_CLASS): Replace a literal
- register number with an appropriate macro.
+2002-10-24 Richard Henderson <rth@redhat.com>
-2002-02-19 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
+ * config/i386/i386.c (x86_output_mi_thunk): Fix x86_64 pic jump.
- * doc/rtl.texi (Constants): Close @code tag.
+2002-10-24 Kazu Hirata <kazu@cs.umass.edu>
-2002-02-19 Aldy Hernandez <aldyh@redhat.com>
+ * config/h8300/h8300.c (initial_offset): Simplify by using
+ round_frame_size.
- * config/i386/i386.md ("mmx_uavgv8qi3"): Use const_vector.
- ("mmx_uavgv4hi3"): Same.
- ("pmulhrwv4hi3"): Same.
+2002-10-24 Marek Michalkiewicz <marekm@amelek.gda.pl>
- * tree-inline.c (walk_tree): Handle vectors.
+ * doc/install.texi (avr): Update required binutils version.
- * c-common.c (constant_expression_warning): Handle vectors.
- (overflow_warning): Same.
+2002-10-24 Theodore A. Roth <troth@openavr.org>
- * sched-deps.c (sched_analyze_2): Handle vectors.
+ * doc/install.texi: Point avr users at more up-to-date information.
- * rtlanal.c (rtx_unstable_p): Handle vectors.
- (rtx_varies_p): Same.
- (count_occurrences): Same.
- (regs_set_between_p): Same.
- (modified_between_p): Same.
- (modified_in_p): Same.
- (volatile_insn_p): Same.
- (volatile_refs_p): Same.
- (side_effects_p): Same.
- (may_trap_p): Same.
- (inequality_comparisons_p): Same.
- (replace_regs): Same.
- (computed_jump_p_1): Same.
+2002-10-24 Ulrich Weigand <uweigand@de.ibm.com>
- * rtl.c (DEF_MACHMODE): Change all definitions to accept 8th
- argument.
- (inner_mode_array): New.
- (copy_rtx): Handle vectors.
- (copy_most_rtx): Same.
- (rtx_equal_p): Same.
- (get_mode_alignment): Adjust for vectors.
+ * config/s390/s390.md (movdi, movsi, movhi, movqi): Add peepholes2
+ to pull operands out of the literal pool where possible.
- * resource.c (mark_referenced_resources): Handle vectors.
- (mark_set_resources): Same.
+2002-10-24 Denis Chertykov <denisc@overta.ru>
- * reload1.c (eliminate_regs): Handle vectors.
- (elimination_effects): Same.
- (scan_paradoxical_subregs): Same.
+ * config/avr/avr.c (init_cumulative_args): Test fntype for zero.
- * reload.c (subst_reg_equivs): Handle vectors.
+2002-10-24 Steve Ellcey <sje@cup.hp.com>
- * regrename.c (scan_rtx): Handle vectors.
+ * expr.c (convert_move): If unsignedp is less then zero there
+ is no equivalent code.
- * regclass.c (reg_scan_mark_refs): Handle vectors.
+2002-10-24 Zack Weinberg <zack@codesourcery.com>
- * recog.c (find_single_use_1): Handle vectors.
+ * tree.def: Delete mention of nonexistent ARRAY_TYPE fields.
- * local-alloc.c (equiv_init_varies_p): Handle vectors.
- (contains_replace_regs): Same.
- (memref_referenced_p): Same.
+2002-10-24 Ulrich Weigand <uweigand@de.ibm.com>
- * integrate.c (copy_rtx_and_substitute): Handle vectors.
- (subst_constants): Same.
+ * config/s390/s390.h: Rework comments; re-sort target macro definitions
+ according to the sequence they are defined in the manual.
+ (POINTER_BOUNDARY): Remove.
- * genattrtab.c (attr_copy_rtx): Handle vectors.
- (encode_units_mask): Same.
- (clear_struct_flag): Same.
- (count_sub_rtxs): Same.
+2002-10-24 Kazu Hirata <kazu@cs.umass.edu>
- * gcse.c (want_to_gcse_p): Handle vectors.
- (oprs_unchanged_p): Same.
- (hash_expr_1): Same.
- (oprs_not_set_p): Same.
- (expr_killed_p): Same.
- (compute_transp): Same.
- (store_ops_ok): Same.
+ * config/h8300/h8300.c (round_frame_size): Replace 8 with
+ BITS_PER_UNIT.
- * function.c (purge_addressof_1): Do not allow paradoxical subregs
- of vectors.
- (fixup_var_refs_1): Same.
- (instantiate_virtual_regs_1): Same.
+2002-10-24 Kazu Hirata <kazu@cs.umass.edu>
- * fold-const.c (operand_equal_p): Handle vectors.
- (fold): Same.
- (rtl_expr_nonnegative_p): Same.
+ * config/h8300/h8300.h (EIGHTBIT_CONSTANT_ADDRESS_P): Make it
+ 64-bit safe.
+ (TINY_CONSTANT_ADDRESS_P): Likewise.
- * flow.c (mark_used_regs): Handle vectors.
+2002-10-24 Richard Henderson <rth@redhat.com>
- * df.c (df_uses_record): Handle vectors.
+ * config/ia64/ia64.c (TARGET_ASM_CAN_OUTPUT_MI_THUNK): True.
+ (ia64_output_mi_thunk): Rewrite to use rtl, and to handle the
+ vcall offset.
- * cselib.c (cselib_subst_to_values): Handle vectors.
- (cselib_mem_conflict_p): Same.
- (hash_rtx): Same.
+2002-10-24 Richard Henderson <rth@redhat.com>
- * cse.c (canon_reg): Handle vectors.
- (fold_rt): Same.
- (cse_process_notes): Same.
- (count_reg_usage): Same.
- (canon_hash): Same.
+ PR opt/7944
+ * reload.c (find_reloads_toplev): Mode of X is not important
+ when simplifying subregs of constants.
- * alias.c (nonlocal_mentioned_p): Add case for CONST_VECTOR.
+2002-10-24 Richard Sandiford <rsandifo@redhat.com>
- * combine.c (mark_used_regs_combine): Add case for CONST_VECTOR.
+ * config.gcc (mips64vr-*-elf*, mips64vrel-*-elf*): Add
+ MIPS_MARCH_CONTROLS_SOFT_FLOAT=1 to $tm_defines.
+ * config/mips/mips.c (MIPS_MARCH_CONTROLS_SOFT_FLOAT): Default to 0.
+ (override_options): Base default setting of MASK_SOFT_FLOAT on -march
+ if MIPS_MARCH_CONTROLS_SOFT_FLOAT.
- * emit-rtl.c (init_emit_once): Generate const0_rtx for vectors.
- (gen_rtx): Handle CONST_VECTOR.
- (gen_const_vector_0): New.
- (copy_rtx_if_shared): CONST_VECTORs can be shared.
- (reset_used_flags): Same.
- (copy_insn_1): Same.
- (initializer_constant_valid_p): Handle VECTOR_CST.
+2002-10-24 Richard Sandiford <rsandifo@redhat.com>
- * doc/c-tree.texi (Expression trees): Document VECTOR_CST.
+ * optabs.c (expand_binop): Don't reuse the shift target in the
+ middle of shift sequences.
- * doc/rtl.texi (Constants): Document const_vector.
- (CONST0_RTX): Update for vectors.
- (RTL sharing): Same.
+2002-10-23 Ziemowit Laski <zlaski@apple.com>
- * print-tree.c (print_node): Add case for VECTOR_CST.
+ * objc/objc-act.c (get_static_reference): Remove unneeded
+ TYPE_BINFO initialization.
+ (get_object-reference): Likewise.
+ (build_constructor): Tighten precondition check.
+ (finish_message_expr): Likewise.
- * tree.h (TREE_VECTOR_CST_ELTS): New.
- (struct tree_vector): New.
- (union tree_node): Add vector node.
- (build_vector): Add prototype.
+2002-10-23 Jakub Jelinek <jakub@redhat.com>
- * tree.def (VECTOR_CST): New.
+ * config/i386/i386.c (local_symbolic_operand): Move LABEL_REF test
+ after CONST test.
- * tree.c (build_vector): New.
+2002-10-23 Steve Ellcey <sje@cup.hp.com>
- * expmed.c (make_tree): Handle CONST_VECTOR.
+ * config/ia64/ia64.c (hfa_element_mode): Don't allow 128 bit floats
+ in HFAs.
- * rtl.h (CONSTANT_P): CONST_VECTORs are constants too.
- (CONST_VECTOR_ELT): New.
- (CONST_VECTOR_NUNITS): New.
+2002-10-23 Richard Henderson <rth@redhat.com>
- * machmode.h (GET_MODE_INNER): New.
- (DEF_MACHMODE): Accept 8th arg.
+ * config/alpha/alpha.c (TARGET_ASM_CAN_OUTPUT_MI_THUNK): True.
+ (alpha_output_mi_thunk_osf): Handle vcall_offset.
- * machmode.def: Add 8th argument for vector inner mode.
- Add inner vector modes for vectors.
+2002-10-23 Zack Weinberg <zack@codesourcery.com>
- * rtl.def (VEC_CONST): Remove.
- (CONST_VECTOR): New.
+ * langhooks.h (struct lang_hooks_for_tree_inlining): Add
+ var_mod_type_p.
+ * langhooks-def.h: Default for tree_inlining.var_mod_type_p is
+ hook_tree_bool_false.
- * expr.c (clear_storage): Allow vectors.
- (is_zeros_p): Handle VECTOR_CST.
+ * tree.c (variably_modified_type_p): Moved here from
+ cp/tree.c. Use lang_hooks.tree_inlining.var_mod_type_p for
+ language-specific cases. Due to this, must weaken some 'if
+ and only if' checks to merely 'if'.
+ * tree.h: Prototype variably_modified_type_p.
- * varasm.c (output_constant_pool): Handle vectors.
- (rtx_const): Add veclo and vechi fields.
- (kind): Add RTX_VECTOR.
- (decode_rtx_const): Add case for vector.
+ * tree-inline.c (walk_tree): #undef WALK_SUBTREE_TAIL at end.
- * config/rs6000/rs6000-protos.h: Add zero_constant.
+2002-10-23 Ulrich Weigand <uweigand@de.ibm.com>
- * config/rs6000/rs6000.c (rs6000_emit_move): Handle vector
- constants. Force easy vector constants into memory.
- (easy_vector_constant): New.
- (emit_easy_vector_constant): New.
- (rs6000_legitimize_reload_address): Do not generate bad reloads on
- darwin.
+ * config/s390/linux.h (CC1_SPEC, CC1PLUS_SPEC): Remove.
+ * config/s390/s390.c (optimization_options): Disable -fcaller-saves.
+
+ * config/s390/s390-protos.h (fp_operand): Remove.
+ * config/s390/s390.c (fp_operand): Remove.
+ * config/s390/s390.md ("movdi"): Replace fp_operand by FP_REG_P.
+ ("*movdi_lhi", "*movdi_lli", "*movdi_larl"): Likewise.
+ ("movsi", "*movsi_lhi", "*movsi_lli"): Likewise.
+ (movdi_31, movdf_31 splitters): Likewise.
+
+ * config/s390/s390.h (IEEE_FLOAT): Remove.
+ (TARGET_FLOAT_FORMAT): Define in terms of TARGET_IEEE_FLOAT.
+ (INT_REGNO_P): Rename to ...
+ (GENERAL_REGNO_P): ... this.
+ (FLOAT_REGNO_P): Rename to ...
+ (FP_REGNO_P): ... this.
+ (ADDR_REGNO_P): New macro.
+ (GENERAL_REG_P, ADDR_REG_P, FP_REG_P, CC_REG_P): New macros.
+ (REGNO_OK_FOR_DATA_P, REGNO_OK_FOR_FP_P): Remove.
+ (DATA_REG_P, FP_REG_P, ADDRESS_REG_P): Likewise.
+ (HARD_REGNO_NREGS): Adapt to macro renaming.
+ (HARD_REGNO_MODE_OK): Likewise.
- * config/rs6000/rs6000.md ("altivec_lvx"): Reflect what
- instruction does.
- ("altivec_lvxl"): Same.
- (altivec_lvebx): Same.
- (altivec_lvehx): Same.
- (altivec_lvewx): Same.
- ("*movv4si_const0"): New.
- ("*movv4sf_const0"): New.
- ("*movv8hi_const0"): New.
- ("*movv16qi_const0"): New.
+2002-10-23 David Edelsohn <edelsohn@gnu.org>
+ Geoff Keating <geoffk@apple.com>
-2002-02-18 Kazu Hirata <kazu@hxi.com>
+ * config/rs6000/rs6000.c (rs6000_register_move_cost): New function.
+ (rs6000_memory_move_cost): New function.
+ * config/rs6000/rs6000-protos.h: Declare them.
+ * config/rs6000/rs6000.h: Use them.
- * config/h8300/h8300.c (notice_update_cc): Use
- cc_status.value2.
+2002-10-23 Ulrich Weigand <uweigand@de.ibm.com>
-2002-02-18 Kazu Hirata <kazu@hxi.com>
+ * libgcc2.c (__udiv_w_sdiv): Use attribute ((always_inline)) when
+ inlining it into other libgcc2 routines.
+ (__udivmoddi4): Likewise.
- * config/h8300/h8300.md (divmod patterns): Change the
- constraints for operands[1] to register_operand.
+2002-10-22 Nathanael Nerode <neroden@gcc.gnu.org>
-2002-02-18 Kazu Hirata <kazu@hxi.com>
+ * doc/sourcebuild.texi (Test Suites): Improve.
- * config/h8300/h8300-protos.h: Remove the prototype for
- p_operand.
- * config/h8300/h8300.c (p_operand): Remove.
- * config/h8300/h8300.md: Replace p_operand with
- const_int_operand.
+2002-10-22 Stan Shebs <shebs@apple.com>
-2002-02-18 Philip Blundell <pb@nexus.co.uk>
+ * config/rs6000/rs6000.c (rs6000_output_mi_thunk): Add missing
+ case for Darwin.
- * config/arm/arm.c (arm_compute_save_reg_mask): Fix typo in
- comment.
- (output_return_instruction): Allow use of LDR to unstack
- return addresss even for interrupt handlers or when
- interworking. If compiling for ARMv5, use interworking-safe
- return instructions by default. Remove duplicated code and
- lengthy "strcat" sequences.
+2002-10-22 Jim Wilson <wilson@redhat.com>
-2002-02-18 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+ * config/i386/i386.md (subdi3_1): Add call to ix86_binary_operator_ok.
- * config/rs6000/sysv4.h (STARTFILE_SPEC): Use crtbeginT.o for -static.
- (LINK_EH_SPEC): Define.
- * config/rs6000/t-ppccomm (EXTRA_MULTILIB_PARTS): Add crtbeginT.o.
+2002-10-23 Jan Hubicka <jh@suse.cz>
-2002-02-18 Ulrich Weigand <uweigand@de.ibm.com>
+ PR other/8289
+ * xmmintrin.h: Add const to the argument of loads.
- * config/s390/s390.c (s390_emit_prologue): Do not set the
- frame_related flag for call-clobbered registers.
+ * i386.md (pushv2di): New pattern.
+ PR target/6890
+ * xmmintrin.h (_MM_TRANSPOSE4_PS): New.
+
+2002-10-22 Richard Henderson <rth@redhat.com>
+
+ * target.h (gcc_target.asm_out): Merge output_mi_thunk and
+ output_mi_vcall_thunk into a single hook. Add can_output_mi_thunk.
+ * target-def.h (TARGET_ASM_OUTPUT_MI_THUNK): Don't conditionalize.
+ (TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Remove.
+ (TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
+ (TARGET_ASM_OUT): Update.
+ * hooks.c (hook_bool_tree_hwi_hwi_tree_false): New.
+ (hook_bool_tree_hwi_hwi_tree_true): New.
+ (default_can_output_mi_thunk_no_vcall): New.
+ * hooks.h: Declare them.
+ * system.h (ASM_OUTPUT_MI_THUNK): Poison.
+
+ * config/alpha/alpha.c (TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
+ (alpha_output_mi_thunk_osf): Add VCALL_OFFSET parameter.
+ * config/arm/arm.c, config/cris/cris.c, config/frv/frv.c,
+ config/i960/i960.c, config/ia64/ia64.c, config/m68k/m68k.c,
+ config/mmix/mmix.c, config/pa/pa.c, config/sparc/sparc.c,
+ config/stormy16/stormy16.c: Similarly.
+
+ * config/i386/i386.c (x86_output_mi_thunk): Merge vcall_offset code.
+ Handle 64-bit properly. Streamline.
+ (x86_output_mi_vcall_thunk): Remove.
+ (x86_this_parameter): Rename from ia32_this_parameter; handle 64-bit.
+ (x86_can_output_mi_thunk): New.
+ (TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Remove.
+ (TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
+ (override_options): Don't zap targetm.asm_out.output_mi_vcall_thunk.
+
+ * config/rs6000/rs6000.c (rs6000_output_mi_thunk): Rename from
+ output_mi_thunk; make static; always use function_section.
+ (TARGET_ASM_OUTPUT_MI_THUNK): New.
+ (TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
+ (rs6000_ra_ever_killed): Test no_new_pseudos not
+ targetm.asm_out.output_mi_thunk in conjunction with thunks.
+ * config/rs6000/rs6000-protos.h: Update.
+ * config/rs6000/sysv4.h (TARGET_ASM_OUTPUT_MI_THUNK): Remove.
+ * config/rs6000/xcoff.h (ASM_DECLARE_FUNCTION_NAME): Don't call
+ xcoffout_declare_function when using rs6000_output_mi_thunk.
+
+ * config/s390/s390.c (s390_output_mi_thunk): Rename from
+ s390_output_mi_vcall_thunk.
+ (TARGET_ASM_OUTPUT_MI_THUNK): Remove.
+ (TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
+
+ * config/vax/vax.c (vax_output_mi_thunk): Static; add vcall_offset.
+ (TARGET_ASM_OUTPUT_MI_THUNK, TARGET_ASM_CAN_OUTPUT_MI_THUNK): New.
+ * config/vax/vax-protos.h: Update.
+ * config/vax/vax.h (ASM_OUTPUT_MI_THUNK): Remove.
+
+2002-10-23 Jan Hubicka <jh@suse,cz>
+
+ * i386.c (standard_sse_constant_p): Accept vector and integer zeros too.
+ * i386.h (EXTRA_CONSTRAINT): Recognize 'C'
+ * i386.md (movti_internal): Use 'C'
+
+ * xmmintrin.h (_mm_cmplt_epi*): New.
+
+2002-10-22 Ulrich Weigand <uweigand@de.ibm.com>
-Mon Feb 18 15:07:35 CET 2002 Jan Hubicka <jh@suse.cz>
+ * config/s390/s390.md ("*movdi_64"): Fix op_type attribute.
+ ("*movdf_64"): Likewise.
+ ("*lshrdi3_64"): Likewise.
+ ("blockage"): Add length attribute.
+ ("lit"): Likewise.
+
+2002-10-22 Jan Hubicka <jh@suse.cz>
+
+ * i386.md: FIx typo.
+ (sse2_cvtsi2sd, sse2_pslrdq): Fix template.
+ (sse2_umulv2siv2di3): Fix predicate.
+ (sse2_psadbw, ashrv8hi3, ashrv4si3, lshrv8hi3 lshrv4si3,
+ lshrv2di3, ashlv8hi3, ashlv4si3, ashlv2di3): Likewise.
+ * xmmintrin.h (_mm_mul_epu16): Rename to...
+ (_mm_mul_epu32): This one.
+ (_mm_cvtsi32_si128, _mm_cvtsi128_si32): New.
+
+ (contains_128bit_aligned_vector_p): Undo accidental checkin.
+
+2002-10-22 Eric Christopher <echristo@redhat.com>
+
+ * config/sparc/sparc.h: Add #error.
+
+2002-10-22 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config.gcc [s390-*-linux]: Remove s390/t-linux from tmake_file.
+ [s390x-*-linux*]: Likewise.
+ * config/s390/t-linux: Remove.
+ * config/s390/s390.h: Include fixdfdi.h when building libgcc2.
+
+2002-10-22 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (builtin_description): Add IX86_BUILTIN_PUNPCKHQDQ128.
+ (ix86_expand_builtin): Fix MASKMOVDQU expasion.
+ * i386.h (ix86_builtins): Add IX86_BUILTIN_PUNPCKHQDQ128.
+ * i386.md (mmx_punpck?dq): Simplify.
+ (sse2_pubpcklqdq): Fix.
+ (sse2_pubpckhqdq): New.
+ * xmmintrin.h (_mm_unpackhi_epi32): New.
+
+ * xmmintrin.h (_mm_cvt*, _mm_stream_pd): Fix prototypes.
+ (_mm_shufflehi_epi16, _mm_shufflelo_epi16): Fix typo.
+
+2002-10-22 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/7209
+ * fold_const.c (fold_binary_op_with_conditional_arg): Always
+ build compound_expr if we used save_expr.
+
+2002-10-22 Alan Modra <amodra@bigpond.net.au>
+
+ * output.h (SECTION_NOTYPE): Define.
+ * varasm.c (default_section_type_flags_1): Set SECTION_NOTYPE for
+ init array sections.
+ (default_elf_asm_named_section): Mind SECTION_NOTYPE.
+ * config/arm/arm.c (arm_elf_asm_named_section): Likewise. Also
+ merge TLS support.
+
+2002-10-21 Richard Henderson <rth@redhat.com>
+
+ * real.c (sticky_rshift_significand): Return inexact, don't
+ or it in immediately.
+ (sub_significands): Accept incomming carry.
+ (div_significands, rtd_divmod): Update for sub_significands change.
+ (round_for_format): Update for sticky_rshift_significand change.
+ (do_add): Don't involve the inexact bit in addition, do give the
+ inexact bit as the subtraction carry-in.
+ (encode_internal, decode_internal, real_internal_format): New.
+ * real.h (real_internal_format): Declare.
+
+2002-10-21 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * libgcc2.c: Fix __udiv_w_sdiv breakage on platforms that
+ don't define sdiv_qrnnd.
+
+2002-10-21 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/h8300.h (EIGHTBIT_CONSTANT_ADDRESS_P): Simplify
+ using IN_RANGE.
+ (TINY_CONSTANT_ADDRESS_P): Likewise.
+
+2002-10-22 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (builtin_description): Add punpcklqdq and movdq2q
+ (ix86_init_mmx_sse_builtins): Add v2di_ftype_void, di_ftype_v2di,
+ v16qi_ftype_pchar, void_ftype_pchar_v16qi, v4si_ftype_pchar,
+ void_ftype_pchar_v4si; Initialize __builtin_ia32_movdq2q,
+ __builtin_ia32_loaddqa, __builtin_ia32_loaddqu, __builtin_ia32_loadd
+ __builtin_ia32_storedqa, __builtin_ia32_storedqu, __builtin_ia32_stored
+ __builtin_ia32_setzero128.
+ (ix86_expand_builtin): Handle IX86_BUILTIN_CLRTI, IX86_BUILTIN_LOADDQA,
+ IX86_BUILTIN_LOADDQU, IX86_BUILTIN_LOADD, IX86_BUILTIN_STOREDQA,
+ IX86_BUILTIN_STOREDQU, IX86_BUILTIN_STORED, Ix86_BUILTIN_MOVQ.
+ * i386.h (ix86_builtins): Add IX86_BUILTIN_LOADDQA, IX86_BUILTIN_LOADDQU,
+ IX86_BUILTIN_STOREDQA, IX86_BUILTIN_STOREDQU, IX86_BUILTIN_LOADD,
+ IX86_BUILTIN_STORED, IX86_BUILTIN_CLRTI, IX86_BUILTIN_MOVDQ2Q,
+ IX86_BUILTIN_PUNPCKLQDQ128, Ix86_BUILTIN_MOVQ.
+ * i386.md (sse2_punpcklqdq, sse2_movqsse2_loadd, sse2_stored,
+ sse2_movq): New patterns.
+ (sse2_movdqa, sse2_movdqu, sse2_movdq2q): Fix.
+ * xmmintrin.h (_mm_load_si128, _mm_loadu_si128, _mm_loadl_epi64,
+ _mm_store_si128, _mm_storeu_si128, _mm_storel_epi64,
+ _mm_setzero_si128, _mm_set_epi64, _mm_set_epi32, _mm_set_epi16,
+ _mm_set_epi8, _mm_set1_epi64, _mm_set1_epi32, _mm_set1_epi16,
+ _mm_set1_epi8, _mm_setr_epi64, _mm_setr_epi32, _mm_setr_epi16,
+ _mm_setr_epi8, _mm_unpacklo_epi64,_mm_set_moveq): New functions.
+ (_mm_insert_epi16): Fix.
+
+2002-10-21 Dale Johannesen <dalej@apple.com>
+
+ * config/rs6000/rs6000.c (rs6000_reverse_condition): Handle
+ unsafe math reversals correctly for RTL generation.
+ (output_cbranch): Replace rs6000_reverse_condition call
+ by its former definition.
+
+2002-10-21 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (x86_64_sign_extended_value): Add allow_rip
+ argument. In CM_SMALL_PIC model consider SYMBOL_REFs binding locally or
+ from constant pool or LABEL_REFs as sign extended if allow_rip.
+ Change all +-1GB limits to +-16MB.
+ (x86_64_general_operand, x86_64_szext_general_operand,
+ x86_64_nonmemory_operand, x86_64_movabs_operand,
+ x86_64_szext_nonmemory_operand, x86_64_immediate_operand,
+ legitimate_address_p, ix86_expand_int_movcc): Update callers.
+ (local_symbolic_operand): Don't allow offsets bigger than +-16MB
+ in CM_SMALL_PIC model.
+ (legitimate_pic_address_disp_p): Don't check offsets before
+ calling local_symbolic_operand.
+ (legitimize_pic_address): Force offsets bigger than +-16MB into
+ register.
+ * config/i386/i386.h (EXTRA_CONSTRAINT, CONST_COSTS): Likewise.
+ * config/i386/i386-protos.h (x86_64_sign_extended_value): Update
+ prototype.
+
+ * configure.in: Test for @GOTNTPOFF and @INDNTPOFF on IA-32 too.
+ Add x86-64 test. Set tls_first_minor to 14 on IA-32 and x86-64.
+ * configure: Rebuilt.
+ * config/i386/i386.c (x86_64_sign_extended_value): Don't allow TLS
+ SYMBOL_REFs unless enclosed in UNSPEC. Handle UNSPEC_DTPOFF,
+ UNSPEC_GOTNTPOFF and UNSPEC_NTPOFF.
+ (legitimate_address_p): Allow foo@dtpoff(base) even on TARGET_64BIT
+ -fpic.
+ (ix86_encode_section_info): Don't ever generate TLSGD or TLSLD for
+ non-pic code if TARGET_64BIT.
+ (legitimize_address): Generate 64-bit TLS sequences.
+ (output_pic_addr_const): Support x86-64 TLS operators.
+ (i386_output_dwarf_dtprel): Output 64-bit DTPOFF as .long f@DTPOFF, 0.
+ (print_operand_address): Use %fs instead of %gs on TARGET_64BIT.
+ Don't append (%rip) in 64-bit TLSGD and TLSLD sequences.
+ (output_addr_const_extra): Support x86-64 TLS operators.
+ (maybe_get_pool_constant): Handle TARGET_64BIT -fpic.
+ (ix86_tls_get_addr): Use __tls_get_addr on TARGET_64BIT
+ unconditionally.
+ * config/i386/i386.md (*tls_global_dynamic_gnu): Renamed to...
+ (*tls_global_dynamic_32_gnu): ..., add !TARGET_64BIT.
+ (*tls_global_dynamic_sun): Renamed to...
+ (*tls_global_dynamic_32_sun): ..., add !TARGET_64BIT.
+ (tls_global_dynamic): Renamed to...
+ (tls_global_dynamic_32): ... this.
+ (tls_global_dynamic_64, *tls_global_dynamic_64): New.
+ (*tls_local_dynamic_base_dynamic_gnu): Renamed to...
+ (*tls_local_dynamic_base_dynamic_32_gnu): ..., add !TARGET_64BIT.
+ (*tls_local_dynamic_base_dynamic_sun): Renamed to...
+ (*tls_local_dynamic_base_dynamic_32_sun): ..., add !TARGET_64BIT.
+ (tls_local_dynamic_base_dynamic): Renamed to...
+ (tls_local_dynamic_base_dynamic_32): ... this.
+ (tls_local_dynamic_base_dynamic_64,
+ *tls_local_dynamic_base_dynamic_64): New.
+ (*tls_local_dynamic_once): Renamed to...
+ (*tls_local_dynamic_32_once): ... this.
+
+2002-10-21 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * libgcc2.c: Inline __udiv_w_sdiv when compiling __udivdi3,
+ __divdi3, __umoddi3, or __moddi3.
+
+2002-10-21 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * c-opts.c (missing_arg): Use cl_options[opt_index].opt_code
+ instead of just opt_index as switch expression.
+
+ * calls.c (store_one_arg): Change type of 'excess_align'
+ to unsigned int.
+
+ * profile.c (output_gcov_string): Change type of 'temp'
+ to size_t.
+
+2002-10-21 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/fixdfdi.h (__fixunsdfdi, __fixdfdi): Add prototypes.
+ (__fixunssfdi, __fixsfdi): Likewise.
+ * config/s390/s390.c (s390_single_hi): Initialize 'value'.
+ (s390_single_qi): Likewise.
+ (s390_emit_epilogue): Initialize 'offset'. Remove signed vs.
+ unsigned comparison warning.
+ (s390_return_addr_rtx): New function.
+ * config/s390/s390-protos.h (s390_return_addr_rtx): Declare it.
+ * config/s390/s390.h (RETURN_ADDR_RTX): Use it.
+ (HARD_REGNO_MODE_OK): Rewrite condition to silence warnings.
- * i386.c (classify_argument): Properly classify SSE/MMX modes and VOIDmode.
- (construct_container): Fix handling of SSE operands.
- (ix86_expand_builtin): Fix handling of 64bit pointers.
- (mmx_maskmovq_rex): New pattern.
+2002-10-21 Ulrich Weigand <uweigand@de.ibm.com>
-Mon Feb 18 11:55:55 CET 2002 Jan Hubicka <jh@suse.cz>
+ * config/s390/s390.c (s390_output_mi_vcall_thunk): New function.
+ (TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Define target hook.
+ (s390_output_mi_thunk): Remove.
+ (TARGET_ASM_OUTPUT_MI_THUNK): Remove.
- * regrename.c (kill_set_value): Handle subregs properly.
+2002-10-21 Kazu Hirata <kazu@cs.umass.edu>
-2002-02-18 David Billinghurst <David.Billinghurst@riotinto.com>
+ * config/h8300/h8300.h (N_REG_CLASSES): Parenthesize.
- * objc/objc-act.c (handle_impent): Remove leading '*'
- from objc_class_name.
+2002-10-20 Richard Henderson <rth@redhat.com>
-2002-02-17 Richard Henderson <rth@redhat.com>
+ * target.h (struct gcc_target): Line wrap.
- * config/alpha/alpha.c (some_small_symbolic_operand,
- some_small_symbolic_operand_1, split_small_symbolic_operand,
- split_small_symbolic_operand_1): Rename from *symbolic_mem_op*.
- Handle small SYMBOL_REFs anywhere, not just inside memories.
+ * config/alpha/alpha.c (alpha_output_mi_thunk_osf): Static.
+ (TARGET_ASM_OUTPUT_MI_THUNK): Define here...
+ * config/alpha/alpha.h: ... not here.
* config/alpha/alpha-protos.h: Update.
- * config/alpha/alpha.h (PREDICATE_CODES): Update.
- * config/alpha/alpha.md (small symbolic operand splitter): Update.
-2002-02-17 Roland McGrath <roland@frob.com>
+ * config/arm/arm.c, config/arm/arm.h, config/arm/arm-protos.h
+ config/cris/cris-protos.h, config/cris/cris.c, config/cris/cris.h,
+ config/frv/frv-protos.h, config/frv/frv.c, config/frv/frv.h,
+ config/i386/i386-protos.h, config/i386/i386.c, config/i386/openbsd.h,
+ config/i386/unix.h, config/i960/i960-protos.h, config/i960/i960.c,
+ config/i960/i960.h, config/ia64/ia64-protos.h, config/ia64/ia64.c,
+ config/ia64/ia64.h, config/m68k/linux.h, config/m68k/m68k-protos.h,
+ config/m68k/m68k.c, config/m68k/netbsd-elf.h, config/m68k/openbsd.h,
+ config/mmix/mmix-protos.h, config/mmix/mmix.c, config/mmix/mmix.h,
+ config/pa/pa-protos.h, config/pa/pa.c, config/pa/pa.h,
+ config/s390/s390-protos.h, config/s390/s390.c, config/s390/s390.h,
+ config/sparc/openbsd.h, config/sparc/sparc-protos.h,
+ config/sparc/sparc.c, config/sparc/sparc.h,
+ config/stormy16/stormy16-protos.h, config/stormy16/stormy16.c,
+ config/stormy16/stormy16.h: Similarly.
- * config.gcc (powerpc-*-gnu-gnualtivec*,
- powerpc-*-gnu*, powerpc64-*-gnu*): New configurations.
- * config/rs6000/gnu.h: New file.
- * config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS):
- Grok "gnu" in rs6000_abi_name.
- (ASM_SPEC, CC1_SPEC, LINK_START_SPEC, LINK_OS_SPEC,
- CPP_ENDIAN_SPEC, CPP_SPEC, STARTFILE_SPEC, LIB_SPEC, ENDFILE_SPEC):
- Grok -mcall-gnu analogous to -mcall-linux et al.
- (LIB_GNU_SPEC, STARTFILE_GNU_SPEC, ENDFILE_GNU_SPEC,
- LINK_START_GNU_SPEC, LINK_OS_GNU_SPEC, CPP_OS_GNU_SPEC): New macros.
- (SUBTARGET_EXTRA_SPECS): Add *_os_gnu specs using them.
+ * config/m68k/m68k.c (m68k_output_mi_thunk): Replicate mnemonic
+ selection logic from call patterns.
-2002-02-17 Jakub Jelinek <jakub@redhat.com>
+2002-10-20 Mark Mitchell <mark@codesourcery.com>
- PR c/3444:
- * c-typeck.c (build_binary_op) [BIT_XOR_EXPR]: Remove explicit
- shortening.
+ * config/m68k/m68k.c (m68k_output_mi_thunk): Fix typo.
-2002-02-17 Philipp Thomas <pthomas@suse.de>
+2002-10-20 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
- * config/cris/cris.h: Undefine STARTFILE_SPEC and
- ENDFILE_SPEC before (re)defining them.
+ PR other/8202
+ * i386.c (ix86_init_mmx_sse_builtins, ix86_expand_builtin): Define and
+ expand __builtin_ia32_pslldqi128 and __builtin_ia32_psrldqi128.
+ * i386.h (IX86_BUILTIN_PSLLDQI128, IX86_BUILTIN_PSRLDQI128): New.
+ * xmmintrin.h (_mm_srli_si128, _mm_slli_si128): New.
-2002-02-17 Kazu Hirata <kazu@hxi.com>
+2002-10-20 Roger Sayle <roger@eyesopen.com>
- * config/h8300/h8300.c: Fix formatting.
- * config/h8300/h8300.h: Likewise.
+ PR c/761
+ * toplev.c (flag_unsafe_profile_arcs): Remove.
+ (flag_bounded_pointers): Remove.
+ (flag_bounds_check): Correct comments.
+ (lang_independent_options): Remove -funsafe-profile-arcs and
+ -fbounded-pointers. Correct -fbounds-check comments.
-2002-02-17 Philipp Thomas <pthomas@suse.de>
+ * flags.h: Correct flag_schedule_interblock comments.
+ (flag_bounded_pointers): Remove prototype.
+ (flag_bounds_check): Correct comments.
- * doc/tm.texi: Explain why empty strings should not be
- marked for translation.
+ * c-opts.c (c_common_init_options): No need to mark
+ flag_bounds_check as unspecified.
+ (c_common_post_options): And no need to set it from
+ flag_bounded_pointers if its still unspecified.
-2002-02-17 Philipp Thomas <pthomas@suse.de>
+ * doc/invoke.texi: Fix some overfull hboxes in "make dvi".
+ Document --version, -feliminate-dwarf-2-dups, -fno-sched-interblock,
+ -fno-sched-spec, -fsched-spec-load, -fsched-spec-load-dangerous,
+ -fsched-verbose=n, -fno-branch-count-reg and -fbounds-check.
- * final.c (output_operand_lossage): Changed to accept
- printf style arguments. Change calls where necessary.
- * output.h (output_operand_lossage): Change declaration
- accordingly. Update copyright.
- * config/arc/arc.c config/fr30/fr30.c config/m32r/m32r.c
- config/m88k/m88k.c : Adapt all calls to output_operand_lossage.
- Update copyright date where necessary.
+2002-10-19 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ Mark Mitchell <mark@codesourcery.com>
+
+ * alpha-protos.h (alpha_output_mi_thunk_osf): Update signature to
+ match target.h.
+ * arm-protos.h, arm.c (arm_output_mi_thunk): Likewise.
+ * cris-protos.h, cris.c (cris_asm_output_mi_thunk): Likewise.
+ * frv-protos.h, frv.c (frv_asm_output_mi_thunk): Likewise.
+ * i386-protos.h, i386.c (x86_output_mi_vcall_thunk,
+ x86_output_mi_thunk): Likewise.
+ * i960-protos.h, i960.c (i960_output_mi_thunk): Likewise.
+ * ia64-protos.h, ia64.c (ia64_output_mi_thunk): Likewise.
+ * m68k-protos.h, m68k.c (m68k_output_mi_thunk): Likewise.
+ * mmix-protos.h, mmix.c (mmix_asm_output_mi_thunk): Likewise.
+ * rs6000-protos.h, rs6000.c (output_mi_thunk): Likewise.
+ * s390-protos.h, s390.c (s390_output_mi_thunk): Likewise.
+ * stormy16-protos.h, stormy16.c (xstormy16_asm_output_mi_thunk):
+ Likewise.
+ * vax-protos.h, vax.c (vax_output_mi_thunk): Likewise.
- * config/i386/i386.c (print_operand): Likewise. Remove use of
- sprintf.
+ * target.h (gcc_target): Update output_mi_thunk and
+ output_mi_vcall_thunk to take a HOST_WIDE_INT delta and
+ vcall_index.
- * config/cris/cris.c (cris_operand_lossage): Likewise.
- Rename parameter so that exgettext recognizes it as
- translatable message.
- (LOSE_AND_RETURN): Rename parameter to msgid.
+ * config/alpha/alpha.c: Replace ASM_OUTPUT_MI_THUNK with
+ TARGET_ASM_OUTPUT_MI_THUNK in comments.
+ * config/alpha/vms.h (ASM_OUTPUT_MI_THUNK): Don't #undef it.
+ (TARGET_ASM_OUTPUT_MI_THUNK): #undef it.
+ * config/frv/frv.h (DEFAULT_VTABLE_THUNKS): Remove definition.
+ * config/i386/i386-protos.h (x86_output_mi_vcall_thunk): Update
+ signature.
+ * config/i386/i386.c (x86_output_mi_vcall_thunk): Likewise.
+ * config/i386/openbsd.h: Replace ASM_OUTPUT_MI_THUNK with
+ TARGET_ASM_OUTPUT_MI_THUNK in comments.
+ * config/i960/i960.h (ASM_OUTPUT_MI_THUNK): Don't define.
+ (TARGET_ASM_OUTPUT_MI_THUNK): Do define.
+ * config/m68k/openbsd.h: Replace ASM_OUTPUT_MI_THUNK with
+ TARGET_ASM_OUTPUT_MI_THUNK in comments.
+ * config/rs6000/rs6000.c (rs6000_ra_ever_killed): Remove #ifdef
+ ASM_OUTPUT_MI_THUNK and replace with check of targetm.
-2002-02-17 Kazu Hirata <kazu@hxi.com>
+ * doc/tm.texi (TARGET_ASM_OUTPUT_MI_THUNK): Update signature.
+ (TARGET_ASM_OUTPU_MI_VCALL_THUNK): Likewise.
- * config/h8300/h8300.h (CONDITIONAL_REGISTER_USAGE): Replace a
- hard coded register number with an appropriate macro.
- (HARD_REGNO_MODE_OK): Likewise.
- (ARG_POINTER_REGNUM): Likewise.
- (STATIC_CHAIN_REGNUM): Likewise.
- (RETURN_ADDRESS_POINTER_REGNUM): Likewise.
- * config/h8300/h8300.md (define_constants): Define more
- register numbers.
+2002-10-19 Brad Lucier <lucier@math.purdue.edu>
-2002-02-17 Philipp Thomas <pthomas@suse.de>
+ * real.c (do_add): Fix 0+0 sign corner case.
+ (do_divide): Fix Inf/0 corner case.
- * config/i386/i386.h: Don't mark empty strings for translation.
+2002-10-20 Jan Hubicka <jh@suse.cz>
-2002-02-16 H.J. Lu <hjl@gnu.org>
+ * i386.c (classify_argument): Pass MMX arguments in memory
+ (ix86_expand_builtin): Expand proper address mode for cflush.
+ * i386.md (movdqa): Fix typo.
+ (sse2_cflush): Accept DImode addresses.
- * config/mips/linux.h (ASM_PREFERRED_EH_DATA_FORMAT): New.
+ * xmmintrin.h (_mm_sqrt_sd): Accept two arguments.
+ (_mm_max_sd): Fix pasto.
+ (_mm_storeh_pd, _mm_storel_pd): Fix.
-2002-02-16 Zack Weinberg <zack@codesourcery.com>
+ * i386.c (bdesc_comi): Fix to match specification.
+ (ix86_expand_sse_comi): Emit the comparison properly.
+ * i386.md (sse_comi, sse2_comi, sse_ucomi, sse2_ucomi):
+ Do not use comparison operator.
+ (vnmaskcmp): Fix template.
- * cppinit.c (merge_include_chains): Check for brack being
- NULL before attempting to merge it with qtail.
+ * xmmintrin.h (_mm_cvtps_pi16): Fix.
-2002-02-16 Andrew Cagney <ac131313@redhat.com>
+2002-10-19 Sebastian Pop <s.pop@laposte.net>
- * config/rs6000/netbsd.h (PREFERRED_DEBUGGING_TYPE): Set to
- DBX_DEBUG.
+ * dependence.c : Removed.
+ * Makefile.in : Remove dependence.o.
-2002-02-16 John David Anglin <dave@hiauly1.hia.nrc.ca>
+2002-10-19 Jan Hubicka <jh@suse.cz>
- * pa/t-pa, pa/t-pro, som.h: Revert last patch.
+ * mmintrin.h (__m64): typedef it to v2si.
+ (_mm_cvtsi32_si64, _mm_cvtsi32_si64_mm_sll_pi16,
+ _mm_sll_pi32, _mm_sll_pi64, _mm_slli_pi64, _mm_sra_pi16,
+ _mm_sra_pi32, _mm_srl_pi16, _mm_srl_pi32, _mm_srl_pi64,
+ _mm_srli_pi64, _mm_and_si64, _mm_andnot_si64,
+ _mm_or_si64, _mm_xor_si64): Add neccesary casts.
+ * xmmintrin.h (_mm_setzero_si64): Likewise.
-2002-02-16 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ * i386.h (ALIGN_MODE_128): Update comment; add missing modes
+ (SSE_REG_MODE_P, MMX_REG_MODE_P): New macros.
- * pa/t-pa (LIB2FUNCS_EXTRA): Don't build lib2funcs.asm.
- * pa/t-pro (LIB2FUNCS_EXTRA): Likewise.
- * som.h (DO_GLOBAL_DTORS_BODY): Delete define.
+ PR target/7693
+ Patch by Shawn Wagner
+ * mmintrin.h: Replace pi64 by si64.
-Sat Feb 16 13:48:50 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2002-10-18 David Edelsohn <edelsohn@gnu.org>
- * config/alpha/alpha.md (*movsi_nt_vms_nofix): Was *movsi_nt_vms;
- now only if !TARGET_FIX.
- (*movsi_nt_vms_fix): New pattern.
+ * rs6000.md (movdf_hardfloat32): Order alternatives consistently.
+ Use length of 4 not *.
+ (movdf_hardfloat64): Same. Support DFmode moves to/from CTR/LR.
+ (movdf_softfloat64): Likewise.
+ (movdi_internal32): Use length of 4 not *.
+ (movti_power): Same.
+ (ctrsi, ctrdi): Same.
-2002-02-16 Douglas B Rupp <rupp@gnat.com>
+2002-10-18 Zack Weinberg <zack@codesourcery.com>
- * config/alpha/alpha.c: Implement null frame procedure types on VMS.
- (alpha_procedure_type): Replaces alpha_is_stack_procedure.
- (alpha_sa_mask, alpha_sa_size): Reflect above change.
- (alpha_pv_save_size, alpha_expand_prologue): Likewise.
- (alpha_start_function, alpha_expand_epilogue): Likewise.
- (unicosmk_gen_dsib): Likewise.
+ * c-decl.c (start_decl): Point users of the old initialized-
+ typedef extension at __typeof__.
-Sat Feb 16 13:39:09 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2002-10-18 Richard Henderson <rth@redhat.com>
+
+ * real.c (cmp_significand_0, rtd_divmod, ten_to_mptwo): New.
+ (real_to_decimal): Re-implement using the logic from the
+ gcc 3.2 etoasc. Comment heavily.
+ (div_significands): Simplify loop startup and comparison logic.
+
+2002-10-18 Mark Mitchell <mark@codesourcery.com>
+
+ * target-def.h (TARGET_ASM_OUTPUT_MI_THUNK): Default to NULL.
+ (TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Likewise.
+ (TARGET_ASM_OUT): Add them.
+ * target.h (asm_out): Add output_mi_thunk and
+ output_mi_vcall_thunk.
+ * config/alpha/alpha.h (ASM_OUTPUT_MI_THUNK): Rename to ...
+ (TARGET_ASM_OUTPUT_MI_THUNK): ... this.
+ * config/arm/arm-protos.h (arm_output_mi_thunk): Declare.
+ * config/arm/arm.c (arm_output_mi_thunk): Define.
+ * config/arm/arm.h (ASM_OUTPUT_MI_THUNK): Rename to ...
+ (TARGET_ASM_OUTPUT_MI_THUNK): ... this.
+ * config/cris/cris.h (ASM_OUTPUT_MI_THUNK): Rename to ...
+ (TARGET_ASM_OUTPUT_MI_THUNK): ... this.
+ * config/frv/frv.h (ASM_OUTPUT_MI_THUNK): Rename to ...
+ (TARGET_ASM_OUTPUT_MI_THUNK): ... this.
+ * config/i386/i386-protos.h (x86_output_mi_thunk): Adjust
+ prototype.
+ (x86_output_mi_vcall_thunk): Declare.
+ * config/i386/i386.c (override_options): Clear
+ output_mi_vcall_thunk in 64-bit mode.
+ (ix86_fntype_regparm): New function.
+ (ix86_return_pops_args): Use it.
+ (ia32_this_parameter): New function.
+ (x86_output_mi_vcall_thunk): New function.
+ (x86_output_mi_thunk): Use it
+ * config/i386/unix.h (TARGET_ASM_OUTPUT_MI_THUNK): Adjust.
+ (TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Define.
+ * config/i960/i960-protos.h (i960_output_mi_thunk): Declare.
+ * config/i960/i960.c (i960_output_mi_thunk): New function.
+ * config/i960/i960.h (ASM_OUTPUT_MI_THUNK): Adjust.
+ * config/ia64/ia64-protos.h (ia64_output_mi_thunk): Declare.
+ * config/ia64/ia64.c (ia64_output_mi_thunk): Define.
+ * config/ia64/ia64.h (ASM_OUTPUT_MI_THUNK): Rename to ...
+ (TARGET_ASM_OUTPUT_MI_THUNK): ... this.
+ * config/m68k/m68k-protos.h (m68k_output_mi_thunk): New function.
+ * config/m68k/linux.h (ASM_OUTPUT_MI_THUNK): Rename to ...
+ (TARGET_ASM_OUTPUT_MI_THUNK): ... this.
+ * config/m68k/netbsd-elf.h (ASM_OUTPUT_MI_THUNK): Rename to ...
+ (TARGET_ASM_OUTPUT_MI_THUNK): ... this.
+ * config/mmix/mmix.h (ASM_OUTPUT_MI_THUNK): Rename to ...
+ (TARGET_ASM_OUTPUT_MI_THUNK): ... this.
+ * config/pa/pa.h (ASM_OUTPUT_MI_THUNK): Rename to ...
+ (TARGET_ASM_OUTPUT_MI_THUNK): ... this.
+ * config/rs6000/sysv4.h (ASM_OUTPUT_MI_THUNK): Rename to ...
+ (TARGET_ASM_OUTPUT_MI_THUNK): ... this.
+ * config/s390/s390-protos.h (s390_output_mi_thunk): Declare.
+ * config/s390/s390.c (s390_output_mi_thunk): Define.
+ * config/s390/s390.h (ASM_OUTPUT_MI_THUNK): Rename to ...
+ (TARGET_ASM_OUTPUT_MI_THUNK): ... this.
+ * config/sparc/sparc.h (ASM_OUTPUT_MI_THUNK): Rename to ...
+ (TARGET_ASM_OUTPUT_MI_THUNK): ... this.
+ * config/stormy16/stormy16.h (ASM_OUTPUT_MI_THUNK): Rename to ...
+ (TARGET_ASM_OUTPUT_MI_THUNK): ... this.
+ * config/vax/vax-protos.h (vax_output_mi_thunk): Declare.
+ * config/vax/vax.c (vax_output_mi_thunk): Define.
+ * config/vax/vax.h (ASM_OUTPUT_MI_THUNK): Rename to ...
+ (TARGET_ASM_OUTPUT_MI_THUNK): ... this.
+ * doc/tm.texi: Adjust documentation.
+
+2002-10-18 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/netbsd.h (NETBSD_ENABLE_EXECUTE_STACK): Define
+ __enable_execute_stack function.
+ * config/alpha/netbsd.h (TRANSFER_FROM_TRAMPOLINE): Define
+ as NETBSD_ENABLE_EXECUTE_STACK.
+ * config/i386/netbsd-elf.h (TRANSFER_FROM_TRAMPOLINE): Ditto.
+ * config/i386/netbsd.h (TRANSFER_FROM_TRAMPOLINE): Ditto.
+ * config/i386/netbsd64.h (TRANSFER_FROM_TRAMPOLINE): Ditto.
+ * config/sparc/netbsd-elf.h (TRANSFER_FROM_TRAMPOLINE): Ditto.
+ * config/sparc/netbsd.h (TRANSFER_FROM_TRAMPOLINE): Ditto.
- * expr.c (store_constructor): Handle target REG case for ARRAY_TYPE.
+2002-10-18 Jason Thorpe <thorpej@wasabisystems.com>
-2002-02-16 Ulrich Weigand <uweigand@de.ibm.com>
+ * config/i386/i386.c (x86_initialize_trampoline): Emit a call
+ to __enable_execute_stack with the address of the trampoline
+ if TRANSFER_FROM_TRAMPOLINE is defined.
+ * config/i386/i386.h (TARGET_64BIT): Expand to a compile-time
+ constant if building libgcc2.
- * config/s390/s390.c (pool_stop_uid, other_chunk, far_away,
- check_and_change_labels, s390_final_chunkify): Delete.
- (s390_split_branches, s390_chunkify_pool): New functions.
- (s390_function_prologue): Call them.
+2002-10-17 Roger Sayle <roger@eyesopen.com>
- * config/s390/s390.h (S390_REL_MAX): Delete.
- (S390_CHUNK_MAX, S390_CHUNK_OV): Adjust values.
+ * doc/c-tree.texi: Update description of COND_EXPR tree nodes.
- * config/s390/s390.md (cjump, icjump, jump): Fix length
- attribute calculation.
+2002-10-17 Geoffrey Keating <geoffk@apple.com>
+ * config/rs6000/rs6000.h (HARD_REGNO_MODE_OK): Allow arbitrary modes
+ in CTR/LR/MQ.
+ * config/rs6000/rs6000.md (movcc_internal1): Support CCmode moves
+ to/from CTR/LR/MQ.
+ (movsf_hardfloat): Support SFmode moves to/from CTR/LR/MQ.
+ (movsf_softfloat): Likewise.
-2002-02-15 David Edelsohn <edelsohn@gnu.org>
+2002-10-17 Janis Johnson <janis187@us.ibm.com>
- * config/rs6000/linux64.h (STRIP_NAME_ENCODING): Delete.
- * config/rs6000/ppc-asm.h (JUMP_TARGET): Define for powerpc64.
+ * Makefile.in (site.exp): Add ALT_CXX_UNDER_TEST and COMPAT_OPTIONS.
-2002-02-15 John David Anglin <dave@hiauly1.hia.nrc.ca>
+2002-10-17 Jason Thorpe <thorpej@wasabisystems.com>
- * gcc.c (init_gcc_specs): Revert patch from 2002-02-15.
- * config/pa/pa-linux.h (LIB_SPEC): Likewise.
- * config/pa/pa32-linux.h (LINK_COMMAND_SPEC): Likewise.
+ * config/alpha/alpha.c (alpha_initialize_trampoline): Use
+ tramp, not addr, to pass the trampoline address to
+ __enable_execute_stack.
-2002-02-15 Richard Sandiford <rsandifo@redhat.com>
+2002-10-17 Jan Hubicka <jh@suse.cz>
- * c-decl.c (grokdeclarator): Prevent a segfault on unnamed decls.
+ * mmintrin.h: Guard by __MMX__
+ * xmmintrin.h: Guard by __SSE__
-2002-02-15 Richard Sandiford <rsandifo@redhat.com>
+ PR other/8062
+ * xmmintrin.h (_MM_SHUFFLE2): New macro.
+ (_mm_load*_?d): New functions.
+ (_mm_set*_?d): New functions.
+ (_mm_store*_?d): New functions.
- * reload.c (find_dummy_reload): Check that an output register
- is valid for its mode.
+2002-10-16 Jan Hubicka <jh@suse.cz>
-2002-02-14 Alexandre Oliva <aoliva@redhat.com>
+ Really commit patch announced at Oct 14
+ PR c/7344
+ * predict.c (can_predict_insn_p): New function.
+ (estimate_probability): Avoid unnecesary work.
+ (process_note_prediction): Likewise.
+ * toplev.c (rest_of_compilation): Account early branch prediction pass
+ as TV_BRANCH_PROB.
- * combine.c (known_cond): After replacing the REG of a SUBREG, try
- to simplify it.
+ PR other/8048
+ Found by Ian Ollmann
+ * xmmintrin.h (_mm_shuffle_pd): Fix typo.
+ (_mm_load?_pd): Likewise.
+ (_mm_store?_pd): Likewise.
- * function.c (assign_parms): Demote promoted argument passed by
- transparent reference.
+ PR target/7386
+ * i386.c (builtin_description):Drop cmpg[te]s[sd].
+ * xmmintrin.h (__mm_cmpg[te]_s[sd]): Rewrite using
+ swapped alternative.
-2001-02-14 Joel Sherrill <joel@OARcorp.com>
+ PR opt/7630
+ * reload1.c (reload_inner_reg_of_subreg): New argument output;
+ (push_reload): Update call.
- * config/arm/rtems-elf.h, config/h8300/rtems.h: Removed redundant
- -Acpu() and -Amachine() to eliminate warnings.
+2002-10-17 Richard Sandiford <rsandifo@redhat.com>
+
+ * config.gcc (mips*-*-*): Add OBJECT_FORMAT_ELF to $tm_defines
+ if using mips/elf.h or mips/elf64.h.
+ * config/mips/elf.h (OBJECT_FORMAT_ELF): Remove.
+ * config/mips/elf64.h (OBJECT_FORMAT_ELF): Remove.
+
+2002-10-16 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c (function_arg): Set inner mode of V1DI to
+ SI.
+
+2002-10-16 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/linux.h (ASM_DOUBLE, _ASM_OUTPUT_LONG): Remove.
+ (LPREFIX): Likewise.
+ (ASM_COMMENT_START, LOCAL_LABEL_PREFIX, ASM_FORMAT_PRIVATE_NAME,
+ ASM_OUTPUT_ADDR_VEC_ELT, ASM_OUTPUT_ADDR_DIFF_ELT,
+ ASM_OUTPUT_ALIGN, ASM_OUTPUT_SKIP, ASM_OUTPUT_ALIGNED_BSS,
+ TEXT_SECTION_ASM_OP, DATA_SECTION_ASM_OP, BSS_SECTION_ASM_OP,
+ GLOBAL_ASM_OP, ASM_OUTPUT_MI_THUNK): Move to s390.h.
+
+ * config/s390/s390.h (ASM_COMMENT_START, LOCAL_LABEL_PREFIX,
+ ASM_FORMAT_PRIVATE_NAME, ASM_OUTPUT_ALIGN, ASM_OUTPUT_SKIP,
+ ASM_OUTPUT_ALIGNED_BSS, TEXT_SECTION_ASM_OP, DATA_SECTION_ASM_OP,
+ BSS_SECTION_ASM_OP): Move from linux.h.
+ (ASM_OUTPUT_ADDR_VEC_ELT, ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
+ Also, use ASM_GENERATE_INTERNAL_LABEL instead of LPREFIX.
+
+ * config/s390/s390.c (s390_function_profiler): Use
+ ASM_GENERATE_INTERNAL_LABEL instead of LPREFIX.
+
+2002-10-15 Richard Henderson <rth@redhat.com>
+
+ * real.c (real_to_decimal): Accept BUF_SIZE and CROP_TRAILING_ZEROS
+ as arguments. Bound DIGITS by the available buffer size.
+ (real_to_hexadecimal): Likewise.
+ * real.h (real_to_decimal, real_to_hexadecimal): Update prototypes.
+ (REAL_VALUE_TO_DECIMAL): Remove.
+ * c-common.c, c-pretty-print.c, print-rtl.c, print-tree.c,
+ sched-vis.c, config/arc/arc.c, config/c4x/c4x.c, config/fr30/fr30.c,
+ config/i370/i370.h, config/i386/i386.c, config/i960/i960.c,
+ config/ip2k/ip2k.c, config/m32r/m32r.c, config/m68hc11/m68hc11.c,
+ config/m68k/hp320.h, config/m68k/m68k.h, config/m68k/sun2o4.h,
+ config/m68k/sun3.h, config/mips/mips.c, config/ns32k/ns32k.c,
+ config/pdp11/pdp11.h, config/vax/vax.h: Update all callers to
+ use real_to_decimal directly, and with the proper arguments.
+ * doc/tm.texi (REAL_VALUE_TO_DECIMAL): Remove.
-2002-02-14 Ulrich Weigand <uweigand@de.ibm.com>
+2002-10-15 Jim Wilson <wilson@redhat.com>
- * config/s390/linux.h (ASM_OUTPUT_ALIGNED_BSS): New.
+ * reload1.c (merge_assigned_reloads): After converting overlapping
+ reloads to RELOAD_OTHER, abort if there are now conflicting reloads.
-2002-02-14 Kazu Hirata <kazu@hxi.com>
+ * config/i386/i386.md (adddi3_1): Add call to ix86_binary_operator_ok.
- * config/h8300/h8300-protos.h: Update the prototype for
- const_costs.
- * config/h8300/h8300.c (const_costs): Treat SET as a little
- more expensive operation.
- * config/h8300/h8300.h (DEFAULT_RTX_COSTS): Update the
- reference to const_costs.
+2002-10-15 Jan Hubicka <jh@suse.cz>
-2002-02-14 Hans-Peter Nilsson <hp@axis.com>
+ * expr.c (do_tablejump): Fix typo in my previous commit.
- * config.gcc (c4x-*-rtems*): Fix typo in tm_file setting.
+2002-10-15 Richard Sandiford <rsandifo@redhat.com>
-2002-02-14 Jakub Jelinek <jakub@redhat.com>
+ * config/mips/vr.h (DRIVER_SELF_SPECS): Change %<mgp32 to %{<mgp32}.
- PR c/5503:
- * c-decl.c (duplicate_decls): If builtin type has TYPE_ARG_TYPES NULL,
- use arguments from newtype.
+2002-10-15 Ulrich Weigand <uweigand@de.ibm.com>
-2002-02-13 Eric Christopher <echristo@redhat.com>
+ * config/s390/s390.c (s390_split_branches): Add return
+ value. Add parameters TEMP_REG and TEMP_USED. Use unspec 104.
+
+ (find_base_register_in_addr): New function.
+ (find_base_register_ref): New function.
+ (replace_base_register_ref): New function.
+
+ (struct constant_pool): Add members pool_insn, insns, and anchor.
+ Remove member last_insn.
+ (s390_start_pool): Initialize them.
+ (s390_end_pool): Emit pool placeholder insn.
+ (s390_add_pool_insn): New function.
+ (s390_find_pool): Use insns bitmap instead of addresses.
+ (s390_dump_pool): Replace placeholder insn. Emit anchor.
+ Replace unspec 104 by local-pool-relative references.
+ (s390_output_constant_pool): Output anchor label if required.
+ (s390_output_symbolic_const): Handle unspec 104 and 105.
+ (s390_add_pool): Remove, replace by ...
+ (s390_add_constant, s390_find_constant): ... these new functions.
+ (s390_add_anchor): New function.
+
+ (s390_chunkify_pool): Delete, replace by ...
+ (s390_chunkify_start, s390_chunkify_finish,
+ s390_chunkify_cancel): ... these new functions.
+ (s390_optimize_prolog): Add parameter TEMP_REGNO.
+ Recompute register live data for special registers.
+ (s390_fixup_clobbered_return_reg): New function.
+ (s390_machine_dependent_reorg): Rewrite to use new
+ s390_chunkify_... routines.
+
+ config/s390/s390.md ("reload_base"): Rename to ...
+ ("reload_base_31"): ... this.
+ ("reload_base_64"): New insn.
+ ("reload_base2"): Remove.
+ ("reload_anchor"): New insn.
+ ("pool"): New insn.
+
+ s390.c (s390_pool_overflow): Remove.
+ s390.h (s390_pool_overflow): Likewise.
+ s390.md ("cjump", "icjump", "doloop_si"): Remove s390_pool_overflow.
+
+2002-10-15 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.md (movv8qi_i+2): Don't split if source is -1.
- * config/mips/mips.c (override_options): Add check for march/mipsX
- on the same command line. Fix error message in cpu processing.
- Remove architecture and ISA checks.
+2002-10-15 Janis Johnson <janis187@us.ibm.com>
-2002-02-14 Aldy Hernandez <aldyh@redhat.com>
+ * doc/install.texi: Formatting changes for conformance to HTML 4.01.
- * config/rs6000/darwin.h (ROUND_TYPE_ALIGN): Adjust for vectors.
+2002-10-15 Ulrich Weigand <uweigand@de.ibm.com>
- * config/rs6000/sysv4.h (ROUND_TYPE_ALIGN): Add MAX.
+ PR opt/7409
+ * loop.c (loop_regs_scan): Mark registers used for function
+ argument passing as MAY_NOT_OPTIMIZE.
-2002-02-14 Aldy Hernandez <aldyh@redhat.com>
+2002-10-14 Jan Hubicka <jh@suse.cz>
- * config/rs6000/rs6000.md ("*movv4si_internal"): Add m<-r and r<-r
- alternatives.
- ("*movv8hi_internal1"): Same.
- ("*movv16qi_internal1"): Same.
- ("*movv4sf_internal1"): Same.
+ * i386.md (movv2di_internal): New pattern.
+ (movv2df_internal, movv8hi_internal, movv16qi_internal): Fix predicate.
+ (movv2di): New expander.
+ * i386.c (ix86_preferred_reload_class): Return NO_REGS for vector operands.
- * config/rs6000/rs6000.c (rs6000_legitimize_reload_address): Do
- not push_reload for altivec modes.
+ * i386.c (ix86_expand_timode_binop_builtin): Delete.
+ (builtin_description): Add SSE1 logicals; rename SSE2 logicals.
+ (ix86_init_mmx_sse_builtins): Kill SSE1 logicals.
+ (ix86_expand_builtin): Likewise.
+ * i386.h (sse_andti4_df_1, sse_andti3_df_2, sse_andti3_sf_1, sse_andti3_sf_2,
+ sse_andti3,
+ sse_andnti4_df_1, sse_andti3_df_2, sse_andti3_sf_1, sse_andti3_sf_2,
+ sse_andnti3,
+ sse_orti4_df_1, sse_orti3_df_2, sse_orti3_sf_1, sse_orti3_sf_2,
+ sse_orti3,
+ sse_xorti4_df_1, sse_xorti3_df_2, sse_xorti3_sf_1, sse_xorti3_sf_2,
+ sse_xorti3): Kill.
+ (sse_andv4sf3, sse_andnv4sf3, sse_orv2df3, sse_xorv2df3, sse_andv2df3,
+ sse_andnv2df3, sse_orv2df3, sse_xorv2df3): New expanders.
+ (*sse_andv4sf3, *sse_andnv2df3, *sse_orv4sf3, *sse_xorv4sf3, *sse_andv2df3,
+ *sse_andnv2df3, *sse_orv2df3, *sse_xorv2df3): New patterns.
+ (*sse_andsf3, *sse_andndf3, *sse_ordf3, *sse_xordf3, *sse_anddf3,
+ *sse_andndf3, *sse_orv2df3, *sse_xorv2df3): New patterns.
+
+ * xmmintrin.h (__m128i): Define as __v2di.
-2002-02-13 Joel Sherrill <joel@OARcorp.com>
+ PR c++/6419
+ (expand_expr): Use DECL_RTL_SET_P.
- * config.gcc (a29k-*-rtems), config/a29k/rtems.h: General cleanup across
- all RTEMS targets including removal of #includes from config/*/rtems*.h
- file and adding them to tm_file setting. Added xm_defines=POSIX to
- many targets.
- * config.gcc (c4x-*-rtems), config/c4x/rtems.h: Ditto.
- * config.gcc (h8300-*-rtems), config/h8300/rtems.h: Ditto.
- * config.gcc (hppa1.1-*-rtems), config/pa/rtems.h: Ditto.
- * config.gcc (i960-*-rtems), config/i960/rtems.h: Ditto.
- * config.gcc (m68k-*-rtems*), config/m68k/rtems.h,
- config/m68k/rtemself.h: Ditto.
- * config.gcc (mips*-*-rtems*), config/mips/rtems.h,
- config/mips/rtems64.h: Ditto.
- * config.gcc (powerpc-*-rtems*), config/rs6000/rtems.h: Ditto.
- * config.gcc (sh-*-rtems*), config/sh/rtems.h, config/sh/rtemself.h:
- Ditto.
- * config.gcc (sparc-*-rtems*), config/sparc/rtems.h,
- config/sparc/rtemself.h: Ditto.
- * config.gcc (v850-*-rtems*), config/v850/rtems.h: Ditto.
- * config.gcc (arm-rtems), config/arm/rtems-elf.h: Ditto plus moved
- arm-rtems stanza closer to other arm-elf targets and made arm-rtems
- more like arm-elf.
- * config.gcc (i[34567]86-*-rtems*), config/i386/djgpp-rtems.h,
- config/i386/rtems.h, config/i386/rtemself.h: Ditto plus i386-rtemself
- target made more similar to i386-elf.
- * config/i386/t-rtems-i386: Added soft float support and multilibs.
- * config/m68k/t-m68kbare: Add 68040 and 68060 as multilib alternatives to
- be similar to config/m68k/t-m68kelf.
- * gthr-rtems.h: Encapsulate with extern "C" for C++.
+2002-10-14 Roger Sayle <roger@eyesopen.com>
-Wed Feb 13 23:41:15 CET 2002 Jan Hubicka <jh@suse.cz>
+ * combine.c (simplify_set): Treat MODE_CC registers like cc0.
- * regmove.c (kill_value): Handle subregs.
+2002-10-14 Roger Sayle <roger@eyesopen.com>
+ Zack Weinberg <zack@codesourcery.com>
-Wed Feb 13 23:34:30 CET 2002 Jan Hubicka <jh@suse.cz>
+ * config/i386/i386.c (k6_cost): Correct typo.
- * i386.md (mul patterns): Allow memory operand to be first;
- add expanders where needed; fix constraints.
- (min?f_nonieee, max?f_nonieee, SSE TImode patterns):
- Allow memory operand to be the first.
+2002-10-14 Mark Mitchell <mark@codesourcery.com>
- * i386.c (ix86_prepare_fp_compare_args): Fix condition for swapping
- operands.
+ PR optimization/6631
+ * alias.c (objects_must_conflict_p): Check honor_readonly when
+ examining TYPE_READONLY.
+ * function.c (assign_stack_temp_for_type): Likewise.
-2002-02-13 Jakub Jelinek <jakub@redhat.com>
+2002-10-14 Falk Hueffner <falk.hueffner@student.uni-tuebingen.de>
- PR c/5681:
- * expr.c (safe_from_p): Pass VOIDmode to true_dependence instead of
- GET_MODE (x).
+ * config/alpha/alpha.md (extendsidi2_nofix, extendsidi2_fix):
+ Swap zero extension arguments.
+ (umaxhi3): Fix instruction class.
+ PR target/7211
+ (prefetch): Fix prefetch instructions.
+ PR target/7238
+ (pkwb): Fix output constraint.
-2002-02-13 Jakub Jelinek <jakub@redhat.com>
+2002-10-14 Alexandre Oliva <aoliva@redhat.com>
- PR optimization/5547:
- * config/i386/i386.c (i386_simplify_dwarf_addr): Simplify
- all valid IA-32 address modes involving non-scaled %ebx and
- GOT/GOTOFF as displacement.
+ * config/mips/mips.c (print_operand): Increase buffer size for
+ real numbers.
-2002-02-13 Ulrich Weigand <uweigand@de.ibm.com>
+2002-10-14 Richard Henderson <rth@redhat.com>
- * config/s390/s390.c (s390_final_chunkify): Re-run shorten_branches
- after emitting ltorg insns.
+ PR opt/8165
+ * gcse.c (adjust_libcall_notes): Revert last change.
+ * simplify-rtx.c (simplify_replace_rtx): Handle LO_SUM.
- * config/s390/s390.md (*cmpdf_ccs_0, *cmpdf_ccs, *cmpsf_ccs_0,
- *cmpsf_ccs, truncdfsf2_ieee, *adddf3, *addsf3, *subdf3, *subsf3,
- *muldf3, *mulsf3, *divdf3, *divsf3, *negdf2, *negsf2, *absdf2,
- *abssf2): Fix "op_type" attribute.
+2002-10-14 Andrew Haley <aph@redhat.com>
-2002-02-13 Douglas B Rupp <rupp@gnat.com>
+ * tree-inline.c (remap_block): All local class initialization
+ flags go in the outermost scope.
+ (expand_call_inline): Call java_inlining_map_static_initializers.
+ (expand_call_inline): Call java_inlining_merge_static_initializers.
+ * java/lang.c (merge_init_test_initialization): New.
+ (java_inlining_merge_static_initializers): New.
+ (inline_init_test_initialization): New.
+ (java_inlining_map_static_initializers): New.
- * mkconfig.sh: Avoid using a subshell redirect.
- ($output.T): Change to $(output)T.
- (ENABLE_NLS): Remove unneeded undef.
+ * tree-inline.c (expand_call_inline): Convert retvar to expected
+ type.
- * config/alpha/vms.h (MD_EXEC_PREFIX, MD_STARTFILE_PREFIX): Define.
- * config/alpha/x-vms (libsubdir): Define.
+2002-10-14 Graham Stott <graham.stott@btinternet.com>
- * config/alpha/vms.h (MD_FALLBACK_FRAME_STATE_FOR): Handle
- register frame procedures. Optimize retrieving context.
+ * stmt.c (decl_conflicts_with_clobbers_p): Add REG_P check.
- * config/alpha/t-vms (MULTILIB_OPTIONS): Define.
- (MULTILIB_DIRNAME, LIBGCC, INSTALL_LIBGCC): Likewise.
- * config/alpha/vms.h (ASM_FILE_START): Write .arch directive.
+2002-10-14 Aldy Hernandez <aldyh@redhat.com>
-Wed Feb 13 09:45:08 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * stmt.c: Fix typo in comment.
- * alias.c (find_base_term, case ZERO_EXTEND, case SIGN_EXTEND):
- Make same change as for find_base_value.
+2002-10-14 J"orn Rennecke <joern.rennecke@superh.com>
-2002-02-13 Kazu Hirata <kazu@hxi.com>
+ * c-common.c (c_common_type_for_mode): Add V2HImode case.
+ * tree.c (build_common_tree_nodes_2): Initialize
+ unsigned_V2HI_type_node and V2HI_type_node.
+ * tree.h (enum tree_index): Add TI_UV2HI_TYPE and TI_V2HI_TYPE.
+ (unsigned_V2HI_type_node, V2HI_type_node): Define.
- * config/h8300/h8300.h (MODES_TIEABLE_P): Accept a combination
- of QImode and SImode.
+2002-10-14 Jakub Jelinek <jakub@redhat.com>
-2002-02-13 Kazu Hirata <kazu@hxi.com>
+ * config/i386/i386.h (ASM_OUTPUT_REG_PUSH, ASM_OUTPUT_REG_POP):
+ Handle TARGET_64BIT.
- * config/h8300/h8300.c (h8300_adjust_insn_length): Correct the
- length computation of movsi.
- * config/h8300/h8300.md (movsi_h8300hs): Correct the length.
+2002-10-14 Richard Sandiford <rsandifo@redhat.com>
-2002-02-13 Kazu Hirata <kazu@hxi.com>
+ * config/mips/vr.h (DRIVER_SELF_SPECS): Define.
+ * config/mips/t-vr (MULTILIB_OPTIONS): Remove mlong32.
+ (MULTILIB_DIRNAMES): Remove long32.
+ (MULTILIB_EXCEPTIONS): Don't build -mabi=32 -mgp32 multilibs.
+ (MULTILIB_REDUNDANT_DIRS): Remove.
- * config/h8300/h8300.md (subqi3): Tighten the predicate for
- operands[2] to register_operand.
+2002-10-14 Richard Sandiford <rsandifo@redhat.com>
-Wed Feb 13 10:35:56 CET 2002 Jan Hubicka <jh@suse.cz>
+ * doc/tm.texi (DRIVER_SELF_SPECS): Document.
+ * gcc.c (driver_self_specs): New variable.
+ (do_self_spec): New function.
+ (main): Use it to process driver_self_specs.
- * i386.md (fop_*_comm_*): allow nonimmediate in the first operand.
+2002-10-13 Richard Henderson <rth@redhat.com>
-2002-02-12 Aldy Hernandez <aldyh@redhat.com>
+ * rtl.c (shallow_copy_rtx): Use memcpy for the entire node.
- * config/rs6000/rs6000.md: Use predicate altivec_register_operand
- for altivec_lvx* and altivec_stvx*.
- ("*movv4si_internal"): Add constraint for loading from GPRs.
- ("*movv8hi_internal1"): Same.
- ("*movv16qi_internal1"): Same.
- ("*movv4sf_internal1"): Same.
+2002-10-12 Neil Booth <neil@daikokuya.co.uk>
- * config/rs6000/rs6000.c (altivec_register_operand): New.
+ PR preprocessor/7862
+ PR preprocessor/8190
+ * gcc.c (cpp_unique_options): Don't delete .d files.
+ Remove stray whitespace.
- * config/rs6000/rs6000.h (PREDICATE_CODES): Add
- altivec_register_operand.
+2002-10-12 Naohiko Shimizu <pshimizu@fa2.so-net.ne.jp>
-2002-02-13 Hans-Peter Nilsson <hp@bitrange.com>
+ * pdp11.h (ASM_OUTPUT_SKIP): Add preceding 0 for octal constant.
+ (ASM_OUTPUT_COMMON, ASM_OUTPUT_LOCAL): Likewise.
+ * pdp11.c (pdp11_output_function_prologue): 0%o -> %#o.
+ (pdp11_output_function_epilogue, output_ascii): Likewise.
+ (output_addr_const_pdp11): Likewise.
+ * pdp11.md (movdi): Use offsetable memory for floating store.
+ (lshrsi3, negsi2): Delete irrelevant comment.
- * config/mmix/mmix.c (mmix_assemble_integer) <case 4>: Don't
- handle SYMBOL_REF.
+2002-10-11 Geoffrey Keating <geoffk@apple.com>
-2002-02-13 Stan Shebs <shebs@apple.com>
+ * cse.c (mention_regs): Set SUBREG_TICKED to the register number,
+ not the address of the REG.
+ (struct cse_reg_info): Make subreg_ticked unsigned.
- * c-typeck.c (digest_init): Handle vectors.
- (really_start_incremental_init): Same.
- (pop_init_level): Same.
- (process_init_element): Same.
+2002-10-11 Janis Johnson <janis187@us.ibm.com>
- * varasm.c (output_constant): Same.
+ * doc/compat.texi: Add info about C++ libraries.
- * expr.c (clear_storage): Same.
- (store_constructor): Same.
+2002-10-11 Richard Henderson <rth@redhat.com>
-2002-02-12 Eric Christopher <echristo@redhat.com>
+ PR opt/8165
+ * gcse.c (adjust_libcall_notes): Also adjust notes for INSN.
- * explow.c (hard_function_value): Add comment explaining
- signed/unsigned comparison.
+2002-10-11 John David Anglin <dave@hiauly1.hia.nrc.ca>
-2002-02-12 Jakub Jelinek <jakub@redhat.com>
+ * cfganal.c (dfs_enumerate_from): Use PARAMS.
+ * genautomata.c (output_insn_code_cases): Likewise.
+ * real.c (real_format): Likewise.
+ * tree.c (tree_size): Revise expressions using TREE_CODE_LENGTH to
+ ensure value is promoted before doing subtraction.
- * jump.c (never_reached_warning): Add finish argument.
- If finish is NULL, stop on CODE_LABEL, otherwise stop before first
- real insn after end.
- * rtl.h (never_reached_warning): Adjust prototype.
- * cse.c (cse_insn): Pass NULL as finish to never_reached_warning.
- * cfgrtl.c (flow_delete_block): Pass b->end as finish to
- never_reached_warning.
+2002-10-11 Jan Hubicka <jh@suse.cz>
-2002-02-12 Graham Stott <grahams@redhat.com>
+ * calls.c (expand_call): Simplify noreturn call.
- * config/hp/pa.h (GO_IF_LEGITIMATE_ADDRESS): Fix typos.
+ PR c/7344
+ * cfgbuild.c (make_edges): Create edge cache when we do have
+ large jumptable.
+ * expr.c (do_tablejump): Note size of maximal jumptable.
+ * function.c (prepare_function_start): Zero out size.
+ * function.h (function): Add max_jumptable_ents.
-2002-02-12 Kazu Hirata <kazu@hxi.com>
+ * cfgcleanup.c (insn_match_p): Verify sibcall flag for calls to.
- * config/h8300/h8300.c (shift_alg_hi): Improve the 15-bit
- logical shifts on H8/300.
- (shift_alg_si): Improve several shifts on H8/300.
- (get_shift_alg): Likewise.
+2002-10-11 J"orn Rennecke <joern.rennecke@superh.com>
-2002-02-12 Graham Stott <grahams@redhat.com>
+ * sh.md (movv8qi_i+2): For V8QI destinations, generate V4HI
+ register for mperm_w operation.
- * config/pa/pa.c (compute_movstrsi_length): Fix typos.
+2002-10-11 J"orn Rennecke <joern.rennecke@superh.com>
-Tue Feb 12 10:12:56 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * emit-rtl.c (gen_lowpart_common): When asked to make a vector from
+ an integer, use simplify_gen_subreg.
- * alias.c (find_base_value, case ZERO_EXTEND, case SIGN_EXTEND):
- Handle #ifdef POINTERS_EXTEND_UNSIGNED.
+2002-10-10 Aldy Hernandez <aldyh@redhat.com>
-2002-02-11 Hans-Peter Nilsson <hp@bitrange.com>
+ * extend.texi (Vector Extensions): Remove comment about single
+ element vectors.
- * config/mmix/mmix.c (mmix_assemble_integer) <case 1, 2>: Handle
- non-CONST_INT through default_assemble_integer.
- <case 4>: Likewise, for non-CONST_INT, non-SYMBOL_REF.
- <case 8>: Abort for CONST_DOUBLE.
+2002-10-10 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-02-11 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ * fold-const.c (size_htab_hash): Use htab_hash_pointer.
+ * function.c (insns_for_mem_hash): Likewise.
+ * varasm.c (STRHASH): Likewise.
- * gcc.c (init_gcc_specs): Add static libgcc to link when "-shared"
- is specified.
- * config/pa/pa-linux.h (LIB_SPEC): Delete.
- * config/pa/pa32-linux.h (LINK_COMMAND_SPEC): Delete.
+2002-10-10 Stuart Hastings <stuart@apple.com>
-2002-02-11 Andrew Haley <aph@cambridge.redhat.com>
+ * cse.c (struct cse_reg_info): Add subreg_ticked.
+ (SUBREG_TICKED): New.
+ (get_cse_reg_info): Initialize SUBREG_TICKED.
+ (mention_regs): Use it.
+ (invalidate): Set SUBREG_TICKED.
+ (invalidate_for_call): Likewise.
+ (addr_affects_sp_p): Likewise.
- * config/stormy16/stormy16.md (zero_extendqihi2): New.
+2002-10-10 Jakub Jelinek <jakub@redhat.com>
-2002-02-11 Alexandre Oliva <aoliva@redhat.com>
+ * config/i386/i386.md (tls_local_dynamic_base): Put pic reg
+ into proper operand.
- * regrename.c (regrename_optimize): Don't accept a
- part-clobbered register if the replaced register is not part
- clobbered.
+2002-10-10 Denis Chertykov <denisc@overta.ru>
- * calls.c (store_one_arg): In the non-BLKmode non-partial case,
- take padding into account when computing the argument value.
+ * config/ip2k/ip2k.c (function_epilogue): Optimize stack
+ deallocation.
+ * config/ip2k/libgcc.S: Combine routines used by function
+ epilogue.
- * config/sh/sh.h (FUNCTION_ARG_REGNO_P): Fix parenthesizing error.
+2002-10-10 Jim Wilson <wilson@redhat.com>
- * combine.c (try_combine): Apply substitutions in
- CALL_INSN_FUNCTION_USAGE too.
+ * cse.c (fold_rtx): Don't perform associative optimization for DIV and
+ UDIV.
-2002-02-11 Aldy Hernandez <aldyh@redhat.com>
+2002-10-10 David Edelsohn <edelsohn@gnu.org>
- * config/rs6000/rs6000.c (altivec_init_builtins): Handle
- __builtin_altivec_abs*.
- (bdesc_abs): New.
+ * config/rs6000/aix52.h: New file.
+ * config/rs6000/t-aix52: New File.
+ * config.gcc (rs6000-ibm-aix5.1.*): New entry.
+ (rs6000-ibm-aix[56789].*): Default to AIX 5.2.
- * config/rs6000/rs6000.h (rs6000_builtins): Add
- ALTIVEC_BUILTIN_ABS*.
+2002-10-10 Jan Hubicka <jh@suse.cz>
- * config/rs6000/altivec.h: Use const char for builtins expecting
- literals.
- (vec_abs): New versions for C and C++.
- (vec_abss): Same.
+ PR target/5610
+ * invoke.texi (-msse-math): Kill
+ (-msse): Add note to mfpmath=sse.
-2002-02-10 Kazu Hirata <kazu@hxi.com>
+2002-10-10 Jan Hubicka <jh@suse.cz>
- * config/h8300/h8300.h (INITIALIZE_TRAMPOLINE): Simplify by
- using Pmode.
+ PR target/7723
+ * i386.c (ix86_expand_vector_move): Do not generate const0->mem moves.
-2002-02-10 Kazu Hirata <kazu@hxi.com>
+2002-10-10 Neil Booth <neil@daikokuya.co.uk>
- * config/h8300/h8300.h (STACK_POINTER_REGNUM): Use the
- constant definition from h8300.md.
- (FRAME_POINTER_REGNUM): Likewise.
- * config/h8300/h8300.md (define_constants): Add FP_REG.
+ PR preprocessor/8179
+ * gcc.c (cpp_options): Add {ansi}, move %{m*} to same location
+ as cc1_options.
+ (default_compilers): Pass debug options when preprocessing
+ stdin.
-2002-02-10 Kazu Hirata <kazu@hxi.com>
+2002-10-06 Richard Henderson <rth@redhat.com>
- * config/h8300/h8300.c (print_operand): Remove redundant code.
+ * toplev.c (rest_of_compilation): Revert opt/2960 change.
-2002-02-10 Kazu Hirata <kazu@hxi.com>
+2002-10-09 Zack Weinberg <zack@codesourcery.com>
- * config/h8300/h8300-protos.h: Remove the prototype for byte_reg.
- * config/h8300/h8300.c (byte_reg): Make it static.
+ PR c/7353
+ * c-decl.c (start_decl): Unconditionally issue error for
+ 'typedef foo = bar'.
+ (finish_decl): Remove special case for TYPE_DECL with initializer.
-2002-02-10 Richard Henderson <rth@redhat.com>
+ * doc/extend.texi: Delete "Naming Types" section. Change all
+ cross-references to that section to refer to "Typeof" instead.
+ Add the useful safe-max()-macro example from "Naming Types" to
+ "Typeof", rewritten using that extension. Add some compatibility
+ notes to "Typeof."
- PR c/5623
- * c-typeck.c (incomplete_type_error): Handle flexible array members.
+2002-10-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-02-10 Richard Henderson <rth@redhat.com>
+ * loop.c: Revert 2002-08-15 change.
+ (LOOP_REGNO_NREGS): Ensure type is int.
- PR c++/5624
- * tree.c (append_random_chars): Don't abort if main_input_filename
- does not exist.
+2002-10-09 David Edelsohn <edelsohn@gnu.org>
-2002-02-10 Hans-Peter Nilsson <hp@bitrange.com>
+ * config/rs6000/rs6000.md (extenddftf2): Change to define_insn
+ which copies first FPR and clears second.
+ (extendsftf2): Same.
+ (floatditf2): Fix typo.
+ (floatsitf2): Same.
+ (fix_trunctfdi2): Same.
+ (fix_trunctfsi2): Same.
- * config/mmix/t-mmix (MULTILIB_EXTRA_OPTS): Disable.
+2002-10-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-02-10 Kazu Hirata <kazu@hxi.com>
+ * conflict.c (arc_hash): Change return type to hashval_t.
+ * cselib.c (get_value_hash): Likewise.
+ * genautomata.c (automaton_decl_hash, insn_decl_hash, decl_hash,
+ state_hash, automata_list_hash): Likewise.
+ * read-rtl.c (def_hash): Likewise.
+ * tree.c (type_hash_hash): Likewise.
- * config/h8300/h8300.md (pushhi1_h8300): Correct the mode used.
- (pushhi1): Likewise.
+2002-10-08 Aldy Hernandez <aldyh@redhat.com>
-2002-02-10 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ * config/rs6000/rs6000.c (rs6000_ra_ever_killed): Call
+ prologue_epilogue_contains instead of using REG_MAYBE_DEAD notes.
- * pa.c (reg_before_reload_operand): Don't accept a SUBREG operand.
- * pa.h (PREDICATE_CODES): Adjust codes for reg_before_reload_operand.
+2002-10-09 J"orn Rennecke <joern.rennecke@superh.com>
-2002-02-09 David O'Brien <obrien@FreeBSD.org>
+ * sh.md (ffssi2): Fix emitted code.
- * config/sparc/freebsd.h(TARGET_DEFAULT): Add MASK_EPILOGUE setting and
- remove MASK_VIS.
- (ASM_CPU_DEFAULT_SPEC): Remove. Default setting is fine.
+2002-10-09 Ulrich Weigand <uweigand@de.ibm.com>
-2002-02-09 Kazu Hirata <kazu@hxi.com>
+ * cse.c (insn_live_p): Pass insn pattern, not full insn
+ to may_trap_p.
- * config/h8300/h8300.c (output_logical_op): Use sub.w to clear
- a half of an SImode register on H8/300.
+2002-10-09 Neil Booth <neil@daikokuya.co.uk>
-Sat Feb 9 18:28:02 CET 2002 Jan Hubicka <jh@suse.cz>
+ * cppmacro.c (paste_tokens): Only allow / to paste with =.
- * i386.md (movdi_2): Add missing '!'.
+2002-10-09 David Edelsohn <edelsohn@gnu.org>
-2002-02-09 Kazu Hirata <kazu@hxi.com>
+ * config/rs6000/rs6000.md (movdf splitter): Use gen_int_mode on
+ 64-bit hosts.
+ (movtf_internal): Reference correct displacement for second value
+ in memory.
+ (movtf splitter): Correct generation of constants in 64-bit mode.
- * config/h8300/h8300.h: Fix formatting. Remove commented-out
- definitions.
+2002-10-09 Alan Modra <amodra@bigpond.net.au>
-2002-02-09 Kazu Hirata <kazu@hxi.com>
-
- * config/h8300/h8300.md (length): Correct the distance valid
- for the short branch.
-
-2002-02-09 Kazu Hirata <kazu@hxi.com>
-
- * config/h8300/h8300.md (iorhi3): Tighten the predicates.
-
-2002-02-09 Alexandre Oliva <aoliva@redhat.com>
-
- * config/sh/sh.h (REGISTER_NATURAL_MODE): Save part-clobbered
- registers in SImode.
- (HARD_REGNO_CALL_PART_CLOBBERED) [TARGET_SHMEDIA32]: Set r18 as
- part-clobbered.
-
- * config/sh/sh.c (expand_prologue): Fix mis-applied 2001-11-09's
- patch.
-
- Contribute sh64-elf.
- 2002-02-09 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.c (TARGET_CANNOT_MODIFY_JUMPS_P): Define to...
- (sh_cannot_modify_jumps_p): New function.
- 2002-02-05 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.c (TARGET_MS_BITFIELD_LAYOUT_P): Define to...
- (sh_ms_bitfield_layout_p): New function.
- 2002-02-04 Alexandre Oliva <aoliva@redhat.com>
- Zack Weinberg <zack@codesourcery.com>
- * config/sh/sh.h (TRAMPOLINE_ADJUST_ADDRESS): Use
- expand_simple_binop instead of expand_binop.
- 2002-02-03 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (OVERRIDE_OPTIONS) [! TARGET_SH5]: Disable
- use of .quad and .uaquad.
- * config/sh/sh.c (TARGET_ASM_UNALIGNED_DI_OP,
- TARGET_ASM_ALIGNED_DI_OP): Add comment pointing to the above.
- 2002-01-24 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (movdi_const, movdi_const_32bit,
- movdi_const_16bit): Make sure all CONSTs have modes.
- (sym2PIC): Ditto, but by adjusting all callers.
- * config/sh/sh.c (calc_live_regs) [TARGET_SHCOMPACT]: Set pr_live
- if the prologue calls the SHmedia argument decoder or register
- saver.
- 2002-01-24 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.c (TARGET_ASM_UNALIGNED_DI_OP): Define.
- (TARGET_ASM_ALIGNED_DI_OP): Likewise.
- (sh_expand_epilogue): Don't emit USE of return target register.
- (prepare_move_operands): Legitimize DImode PIC addresses.
- (sh_media_register_for_return): Skip tr0, used to initialize the
- PIC register.
- (sh_expand_prologue): Remove explicit USE of return register.
- (nonpic_symbol_mentioned_p): PC is non-PIC. Don't recurse in
- CONST_DOUBLEs. UNSPEC_GOTPLT is PIC.
- * config/sh/sh.h (ASM_OUTPUT_DOUBLE_INT): Removed, obsolete.
- (OVERRIDE_OPTIONS): Don't disable PIC on SH5.
- (EXTRA_CONSTRAINT_S): Use MOVI_SHORI_BASE_OPERAND_P instead of
- EXTRA_CONSTRAINT_T.
- (GOT_ENTRY_P, GOTPLT_ENTRY_P, GOTOFF_P, PIC_ADDR_P): New.
- (MOVI_SHORI_BASE_OPERAND_P): New.
- (NON_PIC_REFERENCE_P, PIC_REFERENCE_P): New.
- (EXTRA_CONSTRAINT_T): Define in terms of them.
- (OUTPUT_ADDR_CONST_EXTRA): Handle UNSPEC_GOTPLT.
- * config/sh/sh.md (movsi_media, movsi_media_nofpu,
- movdi_media, movdi_media_nofpu): Add SIBCALL_REGS class to
- alternatives supporting TARGET_REGS.
- (UNSPEC_GOTPLT): New constant.
- (movdi split): Move incrementing of LABEL_NUSES...
- (movdi_const, movdi_const_32bit): Here. Use
- MOVI_SHORI_BASE_OPERAND_P instead of EXTRA_CONSTRAINT_T.
- (movdi_const_16bit): New.
- (call, call_value) [flag_pic]: Use GOTPLT.
- (call_pop, call_value_pop): New expands.
- (call_pop_compact, call_pop_rettramp): New insns.
- (call_value_pop_compact, call_value_pop_rettramp): New insns.
- (sibcall) [flag_pic]: Use GOT.
- (builtint_setjmp_receiver): Remove bogus, unused expand.
- (GOTaddr2picreg): Implement for SHcompact and SHmedia.
- (*pt, *ptb, ptrel): New insns.
- (sym2GOT): Handle DImode GOT.
- (sym2GOTPLT, symGOTPLT2reg): New expands.
- (sym2PIC): New expand.
- (shcompact_return_tramp): Use GOTPLT to return trampoline.
- (shcompact_return_tramp_i): Use return register explicitly.
- * config/sh/sh.h (OVERRIDE_OPTIONS) [TARGET_SHMEDIA]: Don't
- disable flag_reorder_blocks.
- 2002-01-19 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (sibcall_compact): Reorder return, uses and
- clobbers, for clarity.
- (sibcall_epilogue) [TARGET_SHCOMPACT]: Mark saving and
- restoring of r0 in macl as MAYBE_DEAD.
- 2002-01-18 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (LONG_DOUBLE_TYPE_SIZE): Define.
- * config/sh/sh.md (movv4sf_i, movv16sf_i): Fix uses of
- alter_subreg all over.
- (jump) [TARGET_SHMEDIA]: FAIL to create new jumps after
- reload, instead of emitting instructions that would require
- reloading.
- (casesi_load_media): Add missing modes.
- 2001-11-09 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.c (sh_expand_prologue): Mark the PIC register
- as used if the argument decoder is called.
- 2001-08-28 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (udivsi3, divsi3): Load libcall symbol name in
- Pmode, then extend it to DImode if necessary.
- 2001-08-28 Stephen Clarke <Stephen.Clarke@st.com>
- * config/sh/sh.h (LEGITIMATE_CONSTANT_P): Don't accept DFmode
- constants in FPU-enabled SHmedia, let them be loaded from memory.
- 2001-08-28 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (cmpeqdi_media, cmpgtdi_media, cmpgtudi_media):
- Adjust whitespace in assembly output templates.
- 2001-08-28 Stephen Clarke <Stephen.Clarke@st.com>
- * config/sh/sh.md (movdicc_false, movdicc_true, movdicc): Adjust
- mode of if_then_else.
- 2001-08-04 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh64.h (CPP_DEFAULT_CPU_SPEC): Override definition in
- sh.h.
- 2001-07-26 Andrew Haley <aph@cambridge.redhat.com>
- Joern Rennecke <amylaar@redhat.com>
- * config/sh/sh64.h (CPP_DEFAULT_CPU_SPEC): New.
- (SUBTARGET_CPP_PTR_SPEC): New.
- (SUBTARGET_CPP_SPEC): Remove.
- 2001-07-06 Chandrakala Chavva <cchavva@redhat.com>
- * config/sh/sh.md (movsf_media_nofpu+1, movdf_media_nofpu+1):
- Fix typo in previous checkin.
- 2001-07-11 Chandrakala Chavva <cchavva@redhat.com>
- * config/sh/sh.h (MODES_TIEABLE_P): Fix redact indentations.
- 2001-07-10 Chandrakala Chavva <cchavva@cygnus.com>
- Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (MODES_TIEABLE_P): Don't tie modes wider than
- what single FP register can hold for SHmedia target.
- 2001-07-06 Chandrakala Chavva <cchavva@redhat.com>
- Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (movsf_media_nofpu+1, movdf_media_nofpu+1):
- Do not split into SUBREG.
- 2001-06-14 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/ushmedia.h, config/sh/sshmedia.h: Updated signatures
- and added new functions as specified in SH5 ABI r9.
- 2001-06-04 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/lib1funcs.asm (GCC_nested_trampoline): Align to an
- 8-byte boundary.
- 2001-06-03 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.c (dump_table): Add const0_rtx in calls of
- gen_consttable_4 and gen_consttable_8. Emit multiple labels
- and consttable_window_ends.
- 2001-06-03 Graham Stott <grahams@redhat,com>
- * config/sh/sh.md (movdi split): Remove unused variable last_insn.
- 2001-05-16 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.c (print_operand): Handle floating-point pair,
- vector and matrix registers.
- * config/sh/sh.h (REGISTER_MOVE_COST): Take floating-pointer
- vector modes into account.
- * config/sh/sh.md (movv2sf): Split move between registers into
- movdf.
- (movv4sf, movv16sf): Introduce insns that get split only after
- reload.
- * config/sh/shmedia.h: Fix Copyright dates.
- * config/sh/ushmedia.h: Likewise. Move loop counter
- declarations into conditionals that uses them.
- (sh_media_FVADD_S, sh_media_FVSUB_S): Fix off-by-one error in
- loop boundary.
- * config/sh/sshmedia.h: Fix Copyright dates.
- (sh_media_PUTCFG): Fix constraints.
- 2001-05-12 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (TARGET_PTRMEMFUNC_VBIT_LOCATION): Define to
- ptrmemfunc_vbit_in_delta for SH5.
- 2001-05-08 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (TARGET_SWITCHES): Document -m5-*.
- * invoke.texi: Likewise.
- 2001-04-14 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/lib1funcs.asm (GCC_push_shmedia_regs,
- GCC_push_shmedia_regs_nofpu, GCC_pop_shmedia_regs,
- GCC_pop_shmedia_regs_nofpu): New global symbols.
- * config/sh/t-sh64 (LIB1ASMFUNCS): Add them.
- * config/sh/sh.h (SHMEDIA_REGS_STACK_ADJUST): New macro.
- * config/sh/sh.c (calc_live_regs): Account for PR's saving in
- compact function with nonlocal labels.
- (sh_expand_prologue) [SHcompact]: Push SHmedia regs if needed.
- (sh_expand_epilogue) [SHcompact]: Pop them when appropriate.
- (initial_elimination_offset): Account for their stack space.
- * config/sh/sh.md (shmedia_save_restore_regs_compact): New insn.
- * config/sh/sh.md (movsi_media, movsi_media_nofpu, movqi_media,
- movhi_media, movdi_media, movdi_media_nofpu, movdf_media,
- movdf_media_nofpu, movsf_media, movsf_media_nofpu): Require at
- least one of the operands to be a register.
- (movv2sf): Likewise. Renamed to movv2sf_i.
- (movdi, movdf, movv2sf, movv4sf, movv16sf, movsf):
- prepare_move_operands() before emitting SHmedia insns.
- 2001-04-03 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/crti.asm (init, fini) [__SH5__ && ! __SHMEDIA__]:
- Don't save nor initialize r12. Don't mis-align the stack.
- Pad the code with a nop.
- * config/sh/crti.asm: Don't restore r12. Don't mis-align the
- stack.
- 2001-03-13 Alexandre Oliva <aoliva@redhat.com>
- * gcc/longlong.h (__umulsidi3, count_leading_zeros)
- [__SHMEDIA__]: Implement.
- 2001-03-11 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md: Set latency of `pt' closer to reality.
- (movsi_media, movsi_media_nofpu, movdi_media, movdi_media_nofpu,
- movdf_media, movdf_media_nofpu, movsf_media, movsf_media_nofpu):
- Set move, load and store type attributes.
- * config/sh/sh.c (sh_loop_align) [TARGET_SH5]: Set to 3.
- * config/sh/sh.h (OVERRIDE_OPTIONS) [TARGET_SH5]: Disable
- profiling.
- * config/sh/sh.h (PROMOTE_MODE): Sign-extend SImode to DImode.
- * config/sh/sh-protos.h (sh_media_register_for_return): Declare.
- * config/sh/sh.c (sh_media_register_for_return): New function.
- (sh_expand_prologue) [TARGET_SHMEDIA]: Copy r18 to an available
- branch-target register.
- (sh_expand_epilogue) [TARGET_SHMEDIA]: Explicitly USE it.
- * config/sh/sh.md (return_media_i): Use any call-clobbered
- branch-target register.
- (return_media): If r18 wasn't copied in the prologue, copy it
- here.
- * config/sh/sh.h (CONDITIONAL_REGISTER_USAGE) [TARGET_SHMEDIA]:
- Clear class FP0_REGS.
- * config/sh/sh64.h (LINK_SPEC): Removed incorrect default copied
- from elf.h.
- 2001-03-08 DJ Delorie <dj@redhat.com>
- * config/sh/sh.h (OVERRIDE_OPTIONS): Disable relaxing for SHMEDIA.
- 2001-02-09 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (sibcall_compact): Set fp_mode to single.
- 2001-02-07 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (INT_ASM_OP) [SHMEDIA64]: Use `.quad'.
- 2001-02-03 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (INIT_CUMULATIVE_ARGS): Compute size of BLKmode
- return value correctly for call_cookie.
- 2001-02-01 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/crt1.asm (start): Modified so as to call
- ___setup_argv_and_call_main.
- 2001-01-26 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Don't count stack_regs in
- SHmedia mode.
- 2001-01-20 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (STRIP_DATALABEL_ENCODING): New macro.
- (STRIP_NAME_ENCODING): Use it.
- (ASM_OUTPUT_LABELREF): Likewise. Don't call assemble_name().
- 2001-01-19 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (sgeu) [! SHMEDIA]: Fix invocation of
- prepare_scc_operands().
- * config/sh/sh.h (SH_DATALABEL_ENCODING): Change to "#"...
- (DATALABEL_SYMNAME_P): ... so that we don't need memcmp here.
- 2001-01-17 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (STRIP_NAME_ENCODING): Strip leading `*'.
- 2001-01-13 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (shcompact_incoming_args): Use R0_REG.
- * config/sh/sh.md (R7_REG, R8_REG, R9_REG): Define as constants,
- used in shcompact_incoming_args.
- * config/sh/sh.c (sh_expand_epilogue): Fix thinko in previous
- change.
- * config/sh/crt1.asm (start) [SH5]: Switch to single-precision
- mode.
- * config/sh/lib1funcs.asm (sdivsi3_i4, udivsi3_i4, set_fpscr):
- Adjust accordingly.
- * config/sh/sh.c (sh_expand_prologue, sh_expand_epilogue):
- Simplify. Adjust. Add sanity check.
- * config/sh/sh.h (TARGET_SWITCHES) [5-compact]: Set
- FPU_SINGLE_BIT.
- * config/sh/sh.md (udivsi3_i4_single, divsi3_i4_single): Match
- TARGET_SHCOMPACT.
- (udivsi3, divsi3): Use them.
- (force_mode_for_call): New insn.
- (call, call_value, sibcall_value): Emit it before SHcompact
- calls.
- 2001-01-11 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (call, call_value, sibcall): Make sure the
- call cookie is non-NULL before taking its value.
- 2001-01-10 Alexandre Oliva <aoliva@redhat.com>
- * config.gcc (sh64): Set target_requires_64bit_host_wide_int.
- 2001-01-09 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (shcompact_incoming_args): Set argument memory
- block.
- * config/sh/sh.h (STATIC_CHAIN_REGNUM) [SH5]: Use r1.
- * config/sh/sh.c (sh_expand_prologue) [SH5]: Use r0 as
- temporary for stack adjusts. Use MACL and MACH to pass
- arguments to shcompact_incoming_args.
- * config/sh/sh.md (shcompact_incoming_args): Adjust. Don't
- clobber r1.
- * config/sh/lib1funcs.asm (shcompact_incoming_args): Likewise.
- (nested_trampoline): Load static chain address into r1.
- * config/sh/sh.md (movdi_media splits): Fix sign-extension.
- 2001-01-07 Alexandre Oliva <aoliva@redhat.com
- * config/sh/sh.c (fpul_operand) [SHMEDIA]: Just call
- fp_arith_reg_operand().
- 2001-01-06 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (casesi): Sign-extend the first two operands,
- and use signed compares for them.
- * config/sh/sh.c (dump_table): Don't emit 8-byte constants after
- 4-byte ones. Instead, inter-leave them, maintaining the 8-byte
- ones properly aligned.
- (find_barrier): Account for extra alignment needed for 8-byte wide
- constants.
- (machine_dependent_reorg): Require a label for the second 4-byte
- constant after an 8-byte one.
- * config/sh/lib1funcs.asm (sdivsi3): Fix typo in yesterday's
- change.
- 2001-01-05 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.c (machine_dependent_reorg) [SHCOMPACT]: Reset
- last_float when switching float modes.
- * config/sh/sh.md (movdf) [SH5]: Don't use stack-pointer
- auto-increment for general-purpose registers.
- * config/sh/lib1funcs.asm (sdivsi3) [SHMEDIA]: Sign-extend the
- result.
- * config/sh/sh.c (sh_expand_prologue) [SH5]: Use r1 as temporary
- for stack adjust.
- * config/sh/sh.c (sh_builtin_saveregs): Support using all
- registers for varargs.
- 2001-01-01 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Simplify.
- * config/sh/sh.h (CALL_COOKIE_STACKSEQ,
- CALL_COOKIE_STACKSEQ_SHIFT, CALL_COOKIE_STACKSEQ_GET): New macros.
- (CALL_COOKIE_INT_REG_SHIFT): Adjust.
- (FUNCTION_ARG_ADVANCE): Use SHCOMPACT_FORCE_ON_STACK. Adjust
- call_cookie accordingly.
- (FUNCTION_ARG): Test SHCOMPACT_FORCE_ON_STACK.
- (SHCOMPACT_BYREF): Likewise.
- (SHCOMPACT_FORCE_ON_STACK): New macro.
- * config/sh/sh.c (sh_expand_prologue): Use new call_cookie format.
- (sh_builtin_saveregs): Likewise.
- * config/sh/lib1funcs.asm (shcompact_call_trampoline,
- shcompact_incoming_args): Use new shift values. Support
- sequences of consecutive and non-consecutive pushes/pops.
- * config/sh/sh.md (return): Don't explicitly use PR_REG.
- 2001-01-05 Hans-Peter Nilsson <hpn@cygnus.com>
- * config/sh/sh.h (TEXT_SECTION): Define.
- * config/sh/elf.h (ASM_FILE_START): Output TEXT_SECTION_ASM_OP.
- 2001-01-05 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (INIT_CUMULATIVE_LIBCALL_ARGS): New macro.
- * config/sh/sh.h (BASE_RETURN_VALUE_REG): Use FP regs for
- return values on FPU-enabled SHmedia.
- (FUNCTION_VALUE_REGNO_P): Mark FIRST_FP_RET_REG as used on
- FPU-enabled SHmedia.
- (INIT_CUMULATIVE_ARGS): Set up return trampoline only if
- value is returned in a non-FP reg and is not returned by
- reference.
- * config/sh/sh.md (shcompact_return_tramp_i): Change type to
- jump_ind.
- 2000-01-04 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (SH_MIN_ALIGN_FOR_CALLEE_COPY): New.
- (FUNCTION_ARG_CALLEE_COPIES): Require argument to be
- quad-aligned to be passed by callee-copy reference.
- 2001-01-03 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/elf.h (MAX_WCHAR_TYPE_SIZE): Define.
- * config/sh/sh64.h (MAX_WCHAR_TYPE_SIZE): Undefine.
- 2001-01-02 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/lib1funcs.asm (shcompact_call_trampoline): Fix error in
- copying low-numbered FP regs to r7 and r8.
- * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Don't request copying of
- FP regs to general-purpose regs only if the copy was passed on the
- stack.
- * config/sh/lib1funcs.asm (shcompact_call_trampoline): Fix typo in
- copying FP reg to r9.
- * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Use trampoline to
- copy FP regs to general-purpose regs only in outgoing calls.
- * config/sh/sh.md (movdf_media, movsf_media): Revert incorrect
- change from 2000-10-30. Adjust for 64-bit (or 32-bit)
- HOST_WIDE_INT.
- * config/sh/sh.h (struct sh_args): Document all fields.
- (FUNCTION_OK_FOR_SIBCALL): Functions that receive arguments
- passed partially on the stack should not consider making
- sibcalls.
- * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Add byref regs to
- stack_regs only for incoming calls. When passing FP args,
- make sure there are FP regs available before modifying
- call_cookie.
- (SHCOMPACT_BYREF): Pass double args in general-purpose
- registers by reference.
- 2000-12-30 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (FUNCTION_OK_FOR_SIBCALL) [SHCOMPACT]: Don't
- attempt to generate sibcalls if the caller got any arguments
- by reference.
- * config/sh/lib1funcs.asm (set_fpscr) [SH5]: Default to double.
- * config/sh/sh.c (dump_table) [SHCOMPACT]: Align DImode and DFmode
- to 8-byte boundaries.
- * config/sh/sh.md (shcompact_preserve_incoming_args): New insn.
- * config/sh/sh.h (CALL_COOKIE_INT_REG_GET): New macro.
- * config/sh/sh.c (sh_expand_prologue): Preserve args that will be
- stored in the stack.
- * config/sh/lib1funcs.asm (ct_main_table, ia_main_table): Arrange
- for the offsets to have the ISA bit set.
- (shcompact_call_trampoline): Document. Swap r0 and r1, to match
- invocation. Use beq instead of bgt to mark end of sequence of
- loads.
- (shcompact_incoming_args): Fix store of r2. Use beq instead of
- bgt to mark end of sequence of stores.
- * config/sh/sh.c (arith_operand): Don't check whether
- CONST_OK_FOR_J for now.
- * config/sh/sh.md (movdf_media, movsf_media): Use HOST_WIDE_INT
- instead of long for conversion.
- 2000-12-29 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.c (print_operand_address): Convert INTVAL to int
- before passing it to fprintf.
- 2000-12-28 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/crt1.asm (start): Reset SR.FD, to enable the FP unit.
- Call set_fpscr before reading/writing SR.
- * config/sh/crt1.asm (start): Set SR.SZ and SR.PR, but not SR.FR.
- Call set_fpscr.
- * config/sh/lib1funcs.asm: Add `.align 2' directives before
- SHmedia code.
- (FMOVD_WORKS): Define on SH5 with FPU.
- (set_fpscr): Define on SH5. Remove separate _fpscr_values
- setting.
- * config/sh/t-sh64 (LIB1ASMFUNCS): Add _set_fpscr instead of
- _fpscr_values.
- 2000-12-28 Hans-Peter Nilsson <hpn@cygnus.com>
- * config/sh/lib1funcs.asm (ct_main_table): Align contents to even
- address.
- (ia_main_table): Ditto.
- 2000-12-27 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (MAX_WCHAR_TYPE_SIZE): Don't define.
- * config/sh/sh64.h (WCHAR_TYPE, WCHAR_TYPE_SIZE): Reinstate
- the definitions from sh.h.
- * config/sh/sh.h (PTRDIFF_TYPE): Define as conditional on
- TARGET_SH5.
- (SUBTARGET_CPP_SPEC): Arrange for __PTRDIFF_TYPE__ to be defined.
- * config/sh/elf.h (PTRDIFF_TYPE): Likewise.
- * config/sh/sh64.h (SUBTARGET_CPP_SPEC): Likewise.
- 2000-12-26 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (movdi_media split): Don't add REG_LABEL notes.
- Increment LABEL_NUSES.
-
- * config/sh/sh.h (SIZE_TYPE): Define as conditional on
- TARGET_SH5.
- (SUBTARGET_CPP_SPEC): Arrange for __SIZE_TYPE__ to be always
- defined.
- * config/sh/elf.h (SIZE_TYPE): Likewise.
- * config/sh/sh64.h (SUBTARGET_CPP_SPEC): Likewise.
- * config/sh/lib1funcs.asm (shcompact_call_trampoline,
- shcompact_incoming_args): Load switch table addresses using
- datalabel.
- * config/sh/sh.h (SUBTARGET_CPP_SPEC): Define __SIZE_TYPE__.
- (NO_BUILTIN_SIZE_TYPE): Define.
- (SIZE_TYPE): Don't define.
- * config/sh/sh64.h (SUBTARGET_CPP_SPEC): Define __SIZE_TYPE__.
- * config/sh/sh.h (CPP_SPEC): Fixed typo that prevented the
- definition of __SH5__=32 for -m5-compact-nofpu.
- * config/sh/sh.c (barrier_align): Ensure 32-bit alignment after
- ADDR_DIFF_VEC.
- 2000-12-24 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (FUNCTION_ARG_PADDING): Removed.
- 2000-12-23 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (TARGET_CACHE32): Enable on SH5.
- (FUNCTION_BOUNDARY): Ensure 32-bit alignment for SHmedia.
- (INSN_LENGTH_ALIGNMENT): Likewise.
- 2000-12-22 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (call, call_value, sibcall): Simplify
- copying of non-branch-target register.
- 2000-12-22 Alexandre Oliva <aoliva@redhat.com>
- * glimits.h (__LONG_MAX__): Revert 2000-12-13's patch.
- * config/sh/sh.h (CPP_SPEC): Define it here for 64-bit SHmedia.
- 2000-12-22 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (GET_SH_ARG_CLASS): Handle complex
- floating-point values as structs.
- (FUNCTION_ARG): Use SH5_PROTOTYPED_FLOAT_ARG.
- (SH5_PROTOTYPELESS_FLOAT_ARG): List FP registers before
- general-purpose register.
- (SH5_PROTOTYPED_FLOAT_ARG): New macro.
- 2000-12-20 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (addsi3): Force operand1 to reg for SHmedia.
- * config/sh/sh.md (movsi_media): Split CONST_DOUBLE loads too.
- * config/sh/sh.h (DATALABEL_REF_P): Don't require the CONST.
- (ENCODE_SECTION_INFO): Enclose variables and constants in
- DATALABEL unspecs.
- (SH_DATALABEL_ENCODING, DATALABEL_SYMNAME_P): Define.
- (STRIP_NAME_ENCODING): Strip SH_DATALABEL_ENCODING off.
- (ASM_OUTPUT_LABELREF, AMS_OUTPUT_SYMBOL_REF): Define.
- * config/sh/sh.c (gen_datalabel_ref): Use UNSPEC_DATALABEL
- only for LABEL_REFs. For SYMBOL_REFs, prepend
- SH_DATALABEL_ENCODING to the symbol name.
- * config/sh/sh.md (indirect_jump): Use SUBREG instead of
- convert_mode().
- 2000-12-20 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (casesi): Enclose ADDR_DIFF_VEC address in
- UNSPEC_DATALABEL.
- * config/sh/sh.c (gen_datalabel_ref): Accept LABEL_REFs.
- * config/sh/sh.h (DATALABEL_REF_NO_CONST_P): Likewise.
- (DATALABEL_REF_P): Don't require CONST.
- (ASM_OUTPUT_ADDR_DIFF_ELT): On SH5, output datalabel before
- REL label.
- 2000-12-19 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (extendhidi2, extendqidi2): Use arithmetic shift
- right.
- 2000-12-18 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (movsi_media, call, call_value, sibcall):
- Use shallow_copy_rtx and PUT_MODE to change the mode of
- SYMBOL_REFs, LABEL_REFs, CONSTs, etc.
- * config/sh/sh.h (PREFERRED_RELOAD_CLASS): Reload SYMBOL_REFs
- on SHmedia using GENERAL_REGs.
- * config/sh/sh.md (ble_media_i, blt_media_i, bleu_media_i,
- bltu_media_i): Fix reversion of conditions.
- 2000-12-18 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.md (zero_extendhidi2): Use logical shift right.
- * config/sh/sh.c (output_far_jump): Save r13 in macl.
- 2000-12-17 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.c (gen_datalabel_ref): Fix mode of the UNSPEC.
- 2000-12-16 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/lib1funcs.asm (ic_invalidate): Define for SH5.
- (GCC_nested_trampoline): Likewise.
- * config/sh/sh-protos.h (gen_datalabel_ref): Declare.
- * config/sh/sh.c (gen_datalabel_ref): Define.
- * config/sh/sh.h (TRAMPOLINE_SIZE): Adjust for SH5.
- (INITIALIZE_TRAMPOLINE): Likewise.
- (TRAMPOLINE_ADJUST_ADDRESS): Define.
- (DATALABEL_REF_NO_CONST_P, DATALABEL_REF_P): Define.
- (EXTRA_CONSTRAINT_T): Match DATALABEL unspecs.
- (OUTPUT_ADDR_CONST_EXTRA): Handle DATALABEL unspecs.
- * config/sh/sh.md (UNSPEC_DATALABEL): New constant.
- (ic_invalidate): Adjust for SH5.
- (ic_invalidate_line_media, ic_invalidate_line_compact): New insns.
- * config/sh/t-sh64 (LIB1ASMFUNCS): Added _ic_invalidate and
- _nested_trampoline.
- 2000-12-15 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (MOVE_MAX): Set to 8 for SHmedia, 4 elsewhere.
- (MOVE_MAX_PIECES): Set to 8 on SHmedia too.
- 2000-12-14 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (DBX_REGISTER_NUMBER): Adjust for sh64-elf-gdb.
- * config/sh/elf.h (DBX_REGISTER_NUMBER): Likewise.
- 2000-12-14 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.c (target_reg_operand): Match only target-branch
- registers and pseudos that aren't virtual registers.
- * config/sh/sh.md (call, call_value, sibcall) [TARGET_SHMEDIA]:
- Copy operands that don't match target_reg_operand to pseudos.
- (call_media, call_value_media, sibcall_media): Use
- target_reg_operand instead of target_operand.
- 2000-12-13 Alexandre Oliva <aoliva@redhat.com>
- * glimits.h (__LONG_MAX__) [SH5 == 64]: Adjust for 64 bits.
- * config/sh/sh.c (target_reg_operand): Match hardware registers
- other than branch-target registers.
- * config/sh/sh.md (zero_extendqidi2): Input operand is %1.
- * config/sh/lib1funcs.asm (sdivsi3) [SH5]: Make it global.
- (fpscr_values) [SH5 == 32]: Define.
- * config/sh/t-sh64 (LIB1ASMFUNCS): Add fpscr_values.
- * config/sh/sh.md (call, call_value, sibcall) [TARGET_SHMEDIA]:
- Handle function addresses coming in SUBREGs.
- 2000-12-12 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/lib1funcs.asm (shcompact_call_trampoline,
- shcompact_return_trampoline): Use datalabel where appropriate.
- 2000-12-09 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (SECONDARY_OUTPUT_RELOAD_CLASS): Use a
- general-purpose register to copy one branch-target register to
- another.
- 2000-12-06 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.c (target_operand): Accept LABEL_REFs and
- SYMBOL_REFs with VOIDmode.
- * config/sh/sh.md (ble_media_i, blt_media_i, bleu_media_i,
- bltu_media_i): New insns.
- 2000-12-06 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (RETURN_IN_MEMORY): Adjust for SH5 ABI.
- (INIT_CUMULATIVE_ARGS): Likewise.
- 2000-12-01 Alexandre Oliva <aoliva@redhat.com>
- * machmode.def (V16SFmode): New mode.
- * c-common.c (type_for_mode): Support V2SF and V16SF.
- * tree.c (build_common_tree_nodes_2): Likewise.
- * tree.h (tree_index): Likewise.
- * calls.c (emit_call_1): Take args_so_far. Adjust all
- callers. Introduce CALL_POPS_ARGS.
- * tm.texi (CALL_POPS_ARGS): Document.
- * config/sh/crt1.asm: Implement in SHmedia mode.
- * config/sh/crti.asm, config/sh/crtn.asm: Likewise
- * config/sh/elf.h (ASM_SPEC, LINK_SPEC): Support SH5 flags.
- (DBX_REGISTER_NUMBER): Renumber registers for SH5.
- * config/sh/lib1funcs.asm: Disable functions unused in SH5.
- Implement divsi and udivsi in SHmedia mode. Introduce
- SHcompact trampolines.
- * config/sh/sh.c (GEN_MOV, GEN_ADD3, GEN_SUB3): Use DImode
- only in SHmedia64.
- (regno_reg_class): Rewrite.
- (fp_reg_names): Remove.
- (sh_register_names, sh_additional_register_names): New.
- (print_operand): Added `u'. Support SUBREGs in addresses.
- Add parentheses around shifted CONSTs.
- (output_file_start): Output .mode and .abi directives.
- (shiftcosts, addsubcosts, multcosts): Adjust.
- (output_stack_adjust): Compute alignment. Sanity-check SIZE.
- (push_regs): Take array of HOST_WIDE_INTs. Adjust callers.
- (calc_live_regs): Output to array of HOST_WIDE_INTs. Count
- bytes, not registers. Take into account the need for the
- SHcompact incoming args trampoline. Adjust all callers.
- (sh_expand_prologue): Take stack_regs into account. Call
- incoming args trampoline. Keep stack aligned as per SH5 ABI.
- (sh_expand_epilogue): Take stack_regs into accoutn. Keep
- stack aligned as per SH5 ABI.
- (sh_builtin_saveregs): Support SH5 ABI.
- (sh_build_va_list, sh_va_start): Likewise.
- (initial_elimination_offset): Take alignment into account.
- Compute location of PR according to the SH5 stack frame.
- (arith_reg_operand): Reject branch-target registers.
- (shmedia_6bit_operand): New.
- (logical_operand): Use CONST_OK_FOR_P on SHmedia.
- (target_reg_operand): Match DImode only. Accept SUBREGs.
- (target_operand): New.
- * config/sh/sh.h (CPP_SPEC, SUBTARGET_CPP_SPEC): Support SH5 flags.
- (CONDITIONAL_REGISTER_USAGE): Implement SH5 ABI. Initialize
- SIBCALL_REGS for SHmedia.
- (TARGET_SH3E, TARGET_SH4): Only if SH1_BIT is set too.
- (TARGET_FPU_DOUBLE, TARGET_FPU_ANY): New.
- (TARGET_SHMEDIA32, TARGET_SHMEDIA64): New.
- (TARGET_SWITCHES): New SH5 flags.
- (OVERRIDE_OPTIONS): Set SH5-specific options. Use
- VALID_REGISTER_P to disable unsupported registers.
- (LONG_TYPE_SIZE, LONG_LONG_TYPE_SIZE): Set.
- (POINTER_SIZE, PARM_BOUNDARY): Adjust.
- (FUNCTION_ARG_PADDING): Define.
- (FASTEST_ALIGNMENT): Adjust.
- (SH_REGISTER_NAMES_INITIALIZER): New.
- (sh_register_names): Declare.
- (DEBUG_REGISTER_NAMES): Define.
- (REGISTER_NAMES): Define based on sh_register_names.
- (SH_ADDITIONAL_REGISTER_NAMES_INITIALIZER): New.
- (sh_additional_register_names): Declare.
- (LAST_GENERAL_REG, LAST_FP_REG, LAST_XD_REG): Adjust for SHmedia.
- (FIRST_TARGET_REG, LAST_TARGET_REG): Define.
- (TARGET_REGISTER_P, SHMEDIA_REGISTER_P, VALID_REGISTER_P): Define.
- (REGISTER_NATURAL_MODE): Define.
- (FIRST_PSEUDO_REGISTER): Adjust.
- (FIXED_REGISTERS, CALL_USED_REGISTERS): Adjust.
- (HARD_REGNO_CALL_PART_CLOBBERED): Define.
- (HARD_REGNO_NREGS, HARD_REGNO_MODE_OK): Adjust.
- (VECTOR_MODE_SUPPORTED_P): Define.
- (REG_CLASS_CONTENTS): Adjust.
- (SMALL_REGISTER_CLASSES): Adjust.
- (REG_ALLOC_ORDER): Adjust.
- (INDEX_REG_CLASS): Adjust.
- (CONST_OK_FOR_O, CONST_OK_FOR_P): New.
- (CONST_OK_FOR_LETTER_P): Adjust.
- (PREFERRED_RELOAD_CLASS): Adjust.
- (SECONDARY_OUTPUT_RELOAD_CLASS): Adjust.
- (SECONDARY_INPUT_RELOAD_CLASS): Adjust.
- (NPARM_REGS, FIRST_PARM_REG, FIRST_RET_REG): Adjust.
- (FIRST_FP_PARM_REG): Adjust.
- (CALL_POPS_ARGS): Define.
- (FUNCTION_ARG_REGNO_P): Adjust.
- (struct sh_args): New fields.
- (GET_SH_ARG_CLASS): Adjust.
- (INIT_CUMULATIVE_ARGS): Adjust.
- (INIT_CUMULATIVE_INCOMING_ARGS): Define.
- (FUNCTION_ARG_ADVANCE): Adjust.
- (FUNCTION_ARG): Adjust.
- (FUNCTION_ARG_PASS_BY_REFERENCE, SHCOMPACT_BYREF): Define.
- (FUNCTION_ARG_CALLEE_COPIES): Define.
- (SH5_PROTOTYPELESS_FLOAT_ARG): Define.
- (STRICT_ARGUMENT_NAMING): Define.
- (PRETEND_OUTGOING_VARARGS_NAMED): Adjust.
- (FUNCTION_ARG_PARTIAL_NREGS): Adjust.
- (SH5_WOULD_BE_PARTIAL_NREGS): Define.
- (SETUP_INCOMING_VARARGS): Adjust.
- (HAVE_POST_INCREMENT, HAVE_PRE_DECREMENT): Adjust.
- (USE_LOAD_POST_INCREMENT, USE_STORE_PRE_DECREMENT): Adjust.
- (REGNO_OK_FOR_INDEX_P, REG_OK_FOR_INDEX_P): Adjust.
- (SUBREG_OK_FOR_INDEX_P): Adjust.
- (EXTRA_CONSTRAINT_S): Update.
- (EXTRA_CONSTRAINT_T): New.
- (EXTRA_CONSTRAINT): Adjust.
- (GO_IF_LEGITIMATE_INDEX): Adjust.
- (GO_IF_LEGITIMATE_ADDRESS): Adjust.
- (LEGITIMIZE_ADDRESS, LEGITIMIZE_RELOAD_ADDRESS): Adjust.
- (MOVE_MAX): Adjust.
- (MAX_MOVE_MAX): Define.
- (Pmode): Adjust.
- (CONST_COSTS): Adjust.
- (REGISTER_MOVE_COST): Adjust.
- (BRANCH_COST): Adjust.
- (TEXT_SECTION_ASM_OP): Adjust.
- (DBX_REGISTER_NUMBER): Adjust.
- (ASM_OUTPUT_DOUBLE_INT): New.
- (UNALIGNED_DOUBLE_INT_ASM_OP): New.
- (PREDICATE_CODES): Adjust.
- (PROMOTE_MODE): Adjust.
- (CRT_CALL_STATIC_FUNCTION): Do not define for SHmedia.
- * config/sh/sh.md (AP_REG, PR_REG, T_REG, GBR_REG): Renumber.
- (MACH_REG, MACL_REG, FPUL_REG, RAP_REG, FPSCR_REG): Renumber.
- (PR_MEDIA_REG, T_MEDIA_REG, R10_REG): New.
- (DR0_REG, DR2_REG, DR4_REG): Renumber.
- (TR0_REG, TR1_REG, TR2_REG): New.
- (XD0_REG): Renumber.
- (UNSPEC_COMPACT_ARGS): New.
- (type): Added pt and ptabs.
- (length): Default to 4 on SHmedia. Default pt length to 12
- and 20 on SHmedia32 and SHmedia64, respectively.
- (pt): New function unit.
- (movdi, movsi): Add types pt and ptabs. Don't increment LABEL_NUSES.
- Add whitespace between operands of SHmedia instructions.
- (movdicc): Fix.
- (adddi3_media, addsi3_media): Adjust constraints.
- (subsi3) [SHmedia]: Force operand 1 into a register.
- (udivsi3_i1_media, udivsi3_i4_media): New.
- (udivsi3): Support SHmedia.
- (divsi3_i1_media, divsi3_i4_media): New.
- (divsi3): Support SHmedia.
- (anddi3, iordi3, xordi3): Adjust constraints.
- (zero_extendhidi2, zero_extendqidi2): New.
- (extendsidi2, extendhidi2, extendqidi2): New.
- (push, pop, push_e, push_fpul, push_4): Disable on SH5.
- (pop_e, pop_fpul, pop_4): Likewise.
- (movsi_media): Support FP and BT registers.
- (movsi_media_nofpu): New. Adjust splits to DImode.
- (lduw, ldub): Renamed to zero_extend* above.
- (movqi_media): Fix typo.
- (movdi_media): Support FP and BT registers.
- (movdi_media_nofpu): New. Adjust splits for SHmedia32.
- (movdi_const_32bit): New.
- (shori_media): Require immediate operand. Use `u' for output.
- (movdf_media, movsf_media): Simplified.
- (movdf_media_nofpu, movsf_media_nofpu): New.
- (movdf, movsf): Adjust
- (movv2sf, movv2sf, movv16sf): New.
- (beq_media, beq_media_i): Adjust constraints. Don't use
- scratch BT register.
- (bne_media, bne_media_i): Likewise.
- (bgt_media, bgt_media_i): Likewise.
- (bge_media, bge_media_i): Likewise.
- (bgtu_media, bgtu_media_i): Likewise.
- (bgeu_media, bgeu_media_i): Likewise.
- (beq, bne, bgt, blt, ble, bge, bgtu, bltu, bgeu, bleu,
- bunordered): Emit jump insn. Force operands to registers when
- needed.
- (jump_media, jump): Simplify.
- (call_compact, call_compact_rettramp): New.
- (call_value_compact, call_value_compact_rettramp): New.
- (call_media, call_value_media): Simplify.
- (sibcall_compact, sibcall_media): New.
- (call, call_value): Adjust for SHmedia and SHcompact.
- (sibcall, sibcall_value, untyped_call): Likewise.
- (sibcall_epilogue): Preserve r0 across epilogue for SHcompact.
- (indirect_jump): Adjust for SHmedia.
- (casesi_jump_media): New.
- (nop): Re-enable for SHmedia.
- (call_site): Restrict to SH1.
- (casesi): Adjust for SHmedia.
- (casesi_shift_media, casesi_load_media): New.
- (return): Explicitly use PR register. Call return trampoline
- on SHcompact.
- (return_i): Explicitly use PR register.
- (shcompact_return_tramp, shcompact_return_tramp_i): New.
- (return_media): Adjust.
- (shcompact_incoming_args): New.
- (epilogue): Adjust.
- (seq, slt, sle, sgt, sge, sgtu, sltu, sleu, sgeu, sne): Adjust.
- (movstrsi): Disable on SH5.
- (fpu_switch0, fpu_switch1, movpsi): Enable on SH4.
- (addsf3, addsf3_media): Test TARGET_SHMEDIA_FPU.
- (subsf3, subsf3_media): Likewise.
- (mulsf3, mulsf3_media, mac_media): Likewise.
- (divsf3, divsf3_media): Likewise.
- (floatdisf2, floatsisf2_media): Likewise. Adjust constraints.
- (floatsisf2, fux_truncsfsi2): Likewise.
- (fix_truncsfdi2, fix_truncsfsi2_media): Likewise. Adjust
- constraints.
- (cmpeqsf_media, cmpgtsf_media, cmpgesf_media): Likewise.
- (cmpunsf_media, cmpsf): Likewise.
- (negsf2, negsf2_media, sqrtsf2, sqrtsf2_media): Likewise.
- (abssf2, abssf2_media): Likewise.
- (adddf3, adddf3_media, subdf3, subdf3_media): Likewise.
- (muldf3, muldf3_media, divdf3, divdf3_media): Likewise.
- (floatdidf2, floatsidf2_media): Likewise. Adjust constraints.
- (floatsidf2, fix_truncdfsi2): Likewise.
- (fix_truncdfdi2, fix_truncdfsi2_media): Likewise. Adjust
- constraints.
- (cmpeqdf_media, cmpgtdf_media): Likewise.
- (cmpgedf_media, cmpundf_media, cmpdf): Likewise.
- (negdf2, negdf2_media, sqrtdf2, sqrtdf2_media): Likewise.
- (absdf2, absdf2_media): Likewise.
- (extendsfdf2, extendsfdf2_media): Likewise.
- (truncsfdf2, truncsfdf2_media): Likewise.
- * config/sh/sh64.h: New file.
- * config/sh/t-sh64: New file.
- * config/sh/shmedia.h: New file.
- * config/sh/ushmedia.h: New file.
- * config/sh/sshmedia.h: New file.
- * configure.in: Added sh64-*-elf.
- * configure: Rebuilt.
- 2000-10-10 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.c (GEN_MOV, GEN_ADD3, GEN_SUB3): New macros.
- (reg_class_from_letter): Use `b' for TARGET_REGS.
- (print_operand): Support `%M', `%m', `AND' and
- `ASHIFTRT'. Do not precede constants with `#' on SHmedia.
- (andcosts): Adjust for SHmedia.
- (output_stack_adjust, sh_expand_prologue, sh_expand_epilogue):
- Likewise.
- (target_reg_operand): New function.
- * config/sh/sh-protos.h (target_reg_operand): Declare.
- * config/sh/sh.h (CONDITIONAL_REGISTER_USAGE): Don't disable
- FP registers on SH5.
- (HARD_REGNO_MODE_OK): Accept them whenever they're acceptable
- on SH4.
- (TARGET_REGISTER_P): New macro.
- (reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS): Added TARGET_REGS.
- (FUNCTION_VALUE): Use DImode for promoted types on SHmedia.
- (EXTRA_CONSTRAINT_S): New macro.
- (EXTRA_CONSTRAINT): Adjust.
- (FLOAT_TYPE_SIZE): Define to 32.
- (Pmode): DImode on SHmedia.
- (CONST_COSTS): Adjust for SHmedia literals.
- (PREDICATE_CODES): Added target_reg_operand.
- (PROMOTE_MODE): Promote signed types to DImode on SHmedia.
- * config/sh/sh.md: Remove all attrs from SHmedia insns.
- (cmpeqdi_media, cmpgtdi_media, cmpgtudi_media): New insns.
- (cmpdi): Accept SHmedia.
- (movdicc_false, movdicc_true): New insns.
- (movdicc): New expand.
- (adddi3): Accept arith_operand for op2, but FAIL on SH1 if
- no_new_pseudos.
- (addsi3_media): Match `S' constraint.
- (anddi3, andcdi3, iordi3, xordi3, negdi_media): New insns.
- (negdi2): Expand for SHmedia.
- (one_cmpldi2): New expand.
- (zero_extendsidi2): Change from expand to insn.
- (extendsidi2): Add constraints.
- (movdi_media, movsi_media): Change `%x' to `%M'. Use `%m' for
- LD/ST address. Fix SI immediate loading split.
- (movhi_media, movqi_media, lduw, ldub): New insns.
- (movhi, movqi): Accept SHmedia.
- (shori_media, movdi_media): Relax input constraints. Split
- symbolic constants.
- (movdf_media, movsf_media): New insn. New split to movdi.
- (movdf, movsf): Match on SHmedia.
- (beq_media, bne_media, bgt_media, bge_media, bgtu_media,
- bgeu_media): New insns and splits. New insns with `_i' suffix.
- (beq, bne, bgt, blt, ble, bge, bgtu, bltu, bgeu, bleu): Adjust.
- (bunordered): New expand.
- (jump_compact): Renamed from `jump'.
- (jump_media): New insn.
- (jump): New expand.
- (call_media, call_value_media): New insns.
- (call, call_value): Adjust.
- (indirect_jump_compact): Renamed from `indirect_jump'.
- (indirect_jump_media): New insn.
- (indirect_jump): New expand.
- (untyped_call, return): Accept SHmedia.
- (return_media): New insn.
- (prologue, epilogue, blockage): Accept SHmedia.
- (seq, slt, sle, sgt, sge, sgtu, sltu, sleu, sgeu, sne): Adjust.
- (sunordered): New expand.
- (addsf3, subsf3, mulsf3, divsf3, floatsisf2, fix_truncsfsi2,
- cmpsf, negsf2, sqrtsf2, abssf2): Adjust for SHmedia.
- (addsf3_media, subsf3_media, mulsf3_media, mac_media,
- divsf3_media, floatdisf2, floatsisf2_media, fix_truncsfdi2,
- fix_truncsfsi2_media, cmpeqsf_media, cmpgtsf_media,
- cmpgesf_media, cmpunsf_media, negsf2_media, sqrtsf2_media,
- abssf2_media): New insns.
- (adddf3, subdf3, muldf3, divdf3, floatsidf2, fix_truncdfsi2,
- cmpdf, negdf2, sqrtdf2, absdf2): Adjust for SHmedia.
- (adddf3_media, subdf3_media, muldf3_media, divdf3_media,
- floatdidf2, floatsidf2_media, fix_truncdfdi2,
- fix_truncdfsi2_media, cmpeqdf_media, cmpgtdf_media,
- cmpgedf_media, cmpundf_media, negdf2_media, sqrtdf2_media,
- absdf2_media): New insns.
- (extendsfdf2, truncdfsf2): Adjust for SHmedia.
- (extendsfdf2_media, truncdfsf2_media): New insns.
- 2000-09-14 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.c (machine_dependent_reorg): On shmedia, skip for now.
- * config/sh/sh.h (CONST_OK_FOR_J): Document.
- (LEGITIMATE_CONSTANT_P): Accept CONST_DOUBLEs on shmedia.
- * config/sh/sh.md (adddi3): New expand.
- (adddi3_media, adddi3z_media): New insns.
- (adddi3_compact): Renamed from adddi3.
- (addsi3_media): Use add.l r63 to add constant zero.
- (subdi3): New expand.
- (subdi3_media): New insn.
- (subdi3_compact): Renamed from subdi3.
- (mulsidi3): New expand.
- (mulsidi3_media): New insn.
- (mulsidi3_compact): Renamed from mulsidi3.
- (umulsidi3): New expand.
- (umulsidi3_media): New insn.
- (umulsidi3_compact): Renamed from umulsidi3.
- (ashlsi3_media, ashrsi3_media, lshrsi3_media): New insns.
- (ashlsi3, ashrsi3, lshrsi3): Use them.
- (ashldi3_media, ashrdi3_media, lshrdi3_media): New insns.
- (ashldi3, ashrdi3, lshrdi3): Use them.
- (zero_extendsidi2): New expand.
- (extendsidi2): New insn.
- (movsi_media): New insn. Split to movdi to load constants.
- (movsi): Enable for shmedia.
- (movdi_media): New insn. Use shori_media to load wide constants.
- (short_media): New insn.
- (movdi): Enable for shmedia.
- 2000-09-08 Alexandre Oliva <aoliva@redhat.com>
- * config/sh/sh.h (CPP_SPEC): Added `m5'.
- (SUBTARGET_CPP_SPEC): Added `!m5'.
- (SH5_BIT, TARGET_SH5, TARGET_SHMEDIA, TARGET_SHCOMPACT): New macros.
- (TARGET_SWITCHES): Added `5' and `5-compact'. Added SH1_BIT
- to all other SH variants.
- (TARGET_DEFAULT): Set to SH1_BIT.
- (OVERRIDE_OPTIONS): Recognize sh5 CPU.
- (BITS_PER_WORD): Raise to 64 on shmedia.
- (MAX_BITS_PER_WORD): Change to 64.
- (MAX_LONG_TYPE_SIZE, MAX_WCHAR_TYPE_SIZE): Set to MAX_BITS_PER_WORD.
- (INT_TYPE_SIZE): Keep as 32.
- (UNITS_PER_WORD): Raise to 8 on shmedia.
- (MIN_UNITS_PER_WORD): Keep as 4.
- (POINTER_SIZE): Raise to 64 on shmedia.
- (CONST_OK_FOR_J): New macro.
- (CONST_OK_FOR_LETTER_P): Use it.
- (processor_type): Add PROCESSOR_SH5.
- * config/sh/sh.md: Conditionalize all expands, insns and
- splits to TARGET_SH1.
- (cpu): Added sh5.
- (addsi3_compact): Renamed from...
- (addsi3): Now an expand.
- (addsi3_media, subsi3_media): New insns.
- (subsi3): Don't negate constants with SHmedia.
-
- * hooks.c: New file.
- * hooks.h: New file.
- * Makefile.in (HOOKS_H): New.
- (TARGET_DEF_H): Added $(HOOKS_H).
- (OBJS): Added hooks.o.
- (cfgcleanup.o, bb-reorder.o): Added target.h.
- (hooks.o): Added dependencies.
- * target-def.h (TARGET_CANNOT_MODIFY_JUMPS_P): New, added to...
- (TARGET_INITIALIZER): this.
- * doc/tm.texi (TARGET_CANNOT_MODIFY_JUMPS_P): Document.
- * target.h (struct gcc_target): Added cannot_modify_jumps_p.
- * bb-reorder.c: Include target.h.
- (reorder_basic_blocks): Skip if cannot modify jumps.
- * cfgcleanup.c: Include target.h.
- (try_optimize_cfg): Skip merge blocking if cannot modify jumps.
-
-2002-02-08 Chris Demetriou <cgd@broadcom.com>
-
- * config/mips/mips.md (casesi_internal, casesi_internal_di):
- Protect jump delay slot instructions with .set noreorder and
- .set nomacro.
-
-2002-02-08 Chris Demetriou <cgd@broadcom.com>
-
- * config/mips/mips.md (casesi_internal_di): Calculate
- the index into the target offset table correctly.
-
-2002-02-08 Richard Henderson <rth@redhat.com>
-
- * expr.c (expand_expr): Mind EXPAND_INITIALIZER for truncation also.
- * final.c (output_addr_const): Accept and discard SUBREG.
- * varasm.c (decode_addr_const): Don't abort on unknown expressions --
- mark them unknown instead.
- (simplify_subtraction): Handle RTX_UNKNOWN.
- (initializer_constant_valid_p): Strip NOP_EXPRs that narrow the mode.
-
-2002-02-08 David Edelsohn <edelsohn@gnu.org>
-
- * doc/invoke.texi (RS/6000 and PowerPC Options): Fix typo.
-
-2002-02-08 Richard Henderson <rth@redhat.com>
-
- * config/alpha/elf.h (ASM_OUTPUT_ALIGNED_BSS): New.
-
-2002-02-08 Andreas Jaeger <aj@suse.de>
-
- * config.gcc (x86_64-*-linux): Add t-linux64 makefile fragment.
- * config/i386/t-linux64: New file.
-
-2002-02-08 Jakub Jelinek <jakub@redhat.com>
-
- * c-common.c (c_expand_expr): Revert 2002-02-06 patch.
- * c-parse.in (compstmt): Clear last_expr_type.
-
-2002-02-07 Richard Henderson <rth@redhat.com>
-
- * loop.c (strength_reduce): Sink final_value when not
- eliminating a biv.
-
-2002-02-07 David O'Brien <obrien@FreeBSD.org>
-
- * config/sparc/freebsd.h: Fix mismatched spec {.
-
-2002-02-07 Richard Henderson <rth@redhat.com>
-
- * cfgrtl.c: Include recog.h and insn-config.h.
- (keep_with_call_p): Fix general_operand invocation.
- * Makefile.in (cfgrtl.o): Update dependencies.
-
-2002-02-07 Kazu Hirata <kazu@hxi.com>
-
- * config/h8300/h8300.c (two_insn_adds_subs_operand): Revise a
- comment. Accept HImode only if TARGET_H8300.
-
-2002-02-07 Eric Christopher <echristo@redhat.com>
-
- * config/mips/crtn.asm: Cleanup #ifdefs.
-
-2002-02-07 Eric Christopher <echristo@redhat.com>
-
- * config/mips/crti.asm: Add changes for mips16. mips16 uses
- register 7 as RA instead of $31.
- * config/mips/crtn.asm: Ditto.
- * config/mips/mips.c (mips_move_2words): Add case for
- TARGET_MIPS16 when HOST_BITS_PER_WIDE_INT >= 64.
- (compute_frame_size): Fix typo.
- (save_restore_insns): Ditto. Make documentation about using
- register $7 as return register more precise.
- (mips_expand_epilogue): Fix comment. Add code to work around not
- being able to add to the stack pointer directly.
- * config/mips/mips.h (EH_RETURN_DATA_REGNO): Change register number
- to 2 for TARGET_MIPS16 as we need 6 and 7 as clobbers in the
- epilogue.
+ * libgcc2.c (__floatdisf): Properly cure double rounding.
-2002-02-07 Tom Rix <trix@redhat.com>
+2002-10-09 Gabriel Dos Reis <gdr@integrable-solutions.net>
- * config/rs6000/rs6000.c (reg_or_aligned_short_operand): New. For
- immediates in ldu and stdu DS opcode field.
- * config/rs6000/rs6000.md (movdi_update, movdi_update1): Use.
- * config/rs6000/rs6000-protos.h: Add reg_or_aligned_short_operand.
- * config/rs6000/rs6000.h (PREDICATE_CODES): Same.
+ * c-common.c (cb_register_builtins): Define __WCHAR_MAX__.
+ * doc/cpp.texi (Common Predefined Macros): Document.
-2002-02-07 Jeff Sturm <jsturm@one-point.com>
+2002-10-09 Gabriel Dos Reis <gdr@integrable-solutions.net>
- * config/sparc/sparc.c (compute_frame_size): Don't correct frame
- offset for stack bias.
+ PR doc/7484
+ * doc/invoke.texi (Option Summary): List
+ -Wmissing-declarations as a C only option.
-2002-02-07 H.J. Lu <hjl@gnu.org>
+2002-10-08 Jakub Jelinek <jakub@redhat.com>
- * config/mips/linux.h (SUBTARGET_ASM_DEBUGGING_SPEC): Defined.
+ * config/sparc/t-linux64 (MULTILIB_OPTIONS): Remove
+ mno-app-regs|mcmodel=medany.
+ (MULTILIB_DIRNAMES, MULTILIB_OSDIRNAMES): Remove alt.
+ (MULTILIB_EXCEPTIONS, MULTILIB_EXCLUSIONS, MULTILIB_MATCHES): Remove.
+ (CRTSTUFF_T_CFLAGS): Define.
-2002-02-07 Ulrich Weigand <uweigand@de.ibm.com>
+2002-10-08 Roger Sayle <roger@eyesopen.com>
- * testsuite/gcc.dg/cpp/charconst-2.c: Add -fsigned-char option.
+ PR target/8087
+ * simplify-rtx.c (avoid_constant_pool_reference): Allow constant
+ pool references that are constructed using LO_SUM.
-Thu Feb 7 12:14:17 CET 2002 Jan Hubicka <jh@suse.cz>
+2002-10-08 Nathan Sidwell <nathan@codesourcery.com>
- * i386-protos.h (x86_order_regs_for_local_alloc): Declare
- * i386.c (x86_order_regs_for_local_alloc): New global function.
- * i386.h (REG_ALLOC_ORDER): CLeanup.
- (ORDER_REGS_FOR_LOCAL_ALLOC): New.
+ * c-opts.c (c_common_decode_option): Add warn_strict_aliasing to
+ -Wall.
+ * c-typeck.c (build_c_cast): Use warn_strict_aliasing, tweak
+ message.
+ * flags.h (warn_strict_aliasing): Declare.
+ * toplev.c (warn_strict_aliasing): Define.
+ (lang_independent_options): Add it.
+ * doc/invoke.texi (-Wstrict-aliasing): Document it.
-2002-02-07 Richard Henderson <rth@redhat.com>
+2002-10-08 Zack Weinberg <zack@codesourcery.com>
- PR optimization/2463
- * alias.c (find_base_value): Recall base values for fixed hard regs.
- * loop.c (loop_regs_update): Don't use single_set on non-insns.
+ * system.h (GCCBUGURL): Delete.
+ * version.c (bug_report_url): New. Add commentary about
+ modifying both these strings in modified distributions.
+ * version.h: Declare bug_report_url.
-2002-02-07 Alexandre Oliva <aoliva@redhat.com>
+ * diagnostic.c, gcc.c, gcov.c: Globally replace GCCBUGURL with
+ bug_report_url.
- * config/mips/mips.md (define_delay) [mips16]: Adjust required
- length.
+2002-10-08 Nick Clifton <nickc@redhat.com>
-2002-02-06 Richard Henderson <rth@redhat.com>
-
- PR c/5609
- * stmt.c (resolve_operand_name_1): Take more care with mixed
- named and unnamed operands.
-
-2002-02-06 Janis Johnson <janis187@us.ibm.com>
- Jan Hubicka <jh@suse.cz>
-
- * loop.c (remove_constant_addition): Avoid clobbering a shared
- CONST expression.
-
-2002-02-06 Ulrich Weigand <uweigand@de.ibm.com>
-
- * config.gcc (s390x-*-linux*): Add t-linux64 makefile fragment.
- * config/s390/t-linux64: New file.
- * config/s390/libgcc-glibc.ver: New file.
-
-2002-02-06 Ulrich Weigand <uweigand@de.ibm.com>
-
- * config/s390/linux64.h: Delete file.
- * config/s390/s390x.h: New file.
- * config.gcc (s390x-*-linux*): Use s390x.h instead of linux64.h
- as target header file.
- * config/s390/linux.h (TARGET_VERSION): Define depending on
- DEFAULT_TARGET_64BIT.
- (CPP_SPEC, ASM_SPEC, LINK_SPEC): Likewise.
- (SIZE_TYPE, PTRDIFF_TYPE): Likewise.
- (NO_BUILTIN_SIZE_TYPE, NO_BUILTIN_PTRDIFF_TYPE): Define.
- (CPP_ARCH31_SPEC, CPP_ARCH64_SPEC): New defines.
- (LINK_ARCH31_SPEC, LINK_ARCH64_SPEC): New defines.
- (EXTRA_SPEC): New define.
- * config/s390/s390.h (TARGET_VERSION): Define depending on
- DEFAULT_TARGET_64BIT.
- (MASK_RETURN_ADDR): Add run-time check for TARGET_64BIT.
-
-2002-02-06 Jason Merrill <jason@redhat.com>
-
- * c-decl.c (finish_function): Warn about a non-void function with
- no return statement and no abnormal exit.
- (current_function_returns_abnormally): New variable.
- (start_function): Clear it.
- (struct c_language_function): Add returns_abnormally.
- (push_c_function_context): Save it.
- (pop_c_function_context): Restore it.
- (builtin_function): Set TREE_THIS_VOLATILE on return fns.
- (grokdeclarator): Set C_FUNCTION_IMPLICIT_INT on functions without
- an explicit return type.
- * c-tree.h: Declare current_function_returns_abnormally.
- (C_FUNCTION_IMPLICIT_INT): New macro.
- * c-typeck.c (build_function_call): Set it.
- (c_expand_return): Set current_function_returns_value even if the
- value is erroneous.
-
-2002-02-06 Jakub Jelinek <jakub@redhat.com>
-
- PR c/5420:
- * c-common.c (c_unsafe_for_reeval): Make COMPOUND_LITERAL_EXPR
- unsafe for reevaluation.
-
-2002-02-06 Jakub Jelinek <jakub@redhat.com>
-
- PR c/5482:
- * c-common.c (c_expand_expr) [STMT_EXPR]: If last expression is not
- EXPR_STMT, but COMPOUND_STMT, recurse into it.
-
-2002-02-06 Richard Henderson <rth@redhat.com>
-
- * cfganal.c (keep_with_call_p): Source for fixed_reg dest must
- be a general_operand. Dest for function value must be a pseudo.
-
-2002-02-06 Nick Clifton <nickc@cambridge.redhat.com>
-
- * dbxout.c (dbxout_symbol_location): Accept LABEL_REFs as well
- as SYMBOL_REFs from the constant pool.
-
-2002-02-06 Alexandre Oliva <aoliva@redhat.com>
-
- * dbxout.c (dbxout_parms): Apply DEBUGGER_ARG_OFFSET to parameters
- passed by invisible reference.
-
-2002-02-05 Richard Henderson <rth@redhat.com>
-
- * config/sparc/sparc.h (ARG_POINTER_CFA_OFFSET): No stack bias.
-
-2002-02-06 Hans-Peter Nilsson <hp@bitrange.com>
-
- Implement using "base addresses" in insn operands as default.
- * config/mmix/mmix.c (mmix_conditional_register_usage): if
- -mabi=gnu, modify fixed_regs to fit the GNU ABI.
- (mmix_extra_constraint): Use 'R' to indicate that GETA should be
- used to read the rtx value.
- (mmix_target_asm_function_epilogue): Fix spacing.
- (mmix_constant_address_p): Handle TARGET_BASE_ADDRESSES.
- (mmix_legitimate_address): Ditto.
- (mmix_encode_section_info): Set SYMBOL_REF_FLAG on rtx:es that
- should be loaded with a GETA insn. Don't allocate needless extra
- char for nul termination and fix misleading comment.
- (mmix_print_operand_address): Handle constants if
- TARGET_BASE_ADDRESSES.
- (mmix_output_register_setting): Use base addressing if
- TARGET_BASE_ADDRESSES and the number of insns is 3.
- * config/mmix/t-mmix (MULTILIB_EXTRA_OPTS): New.
- * config/mmix/mmix.md ("movdi"): Change the alternative with GETA
- to use R as constraint, add LDA to match s.
- * config/mmix/mmix.h (TARGET_BASE_ADDRESSES): New.
- (TARGET_DEFAULT): Add TARGET_MASK_BASE_ADDRESSES.
- (TARGET_SWITCHES): Add -mbase-addresses, -mno-base-addresses.
- (FIXED_REGISTERS): Make registers $231..$246 fixed by default.
- (MMIX_MMIXWARE_ABI_REG_ALLOC_ORDER): Move $231..$246 last, in
- order with other fixed registers.
- (MMIX_GNU_ABI_REG_ALLOC_ORDER): Put forward $231, in order with
- other parameter/call-clobbered registers.
- * doc/invoke.texi (Option Summary) <MMIX Options>: Add
- -mbase-addresses, -mno-base-addresses.
- (MMIX Options): Ditto.
-
-2002-02-05 John David Anglin <dave@hiauly1.hia.nrc.ca>
-
- * pa.h (PREDICATE_CODES): Add reg_before_reload_operand.
-
-2002-02-06 Aldy Hernandez <aldyh@redhat.com>
-
- * config/rs6000/altivec.h: Change elem to _S_elem.
-
-2002-02-05 Jason Thorpe <thorpej@wasabisystems.com>
-
- * config/netbsd.h (WCHAR_TYPE): Define.
- (WCHAR_TYPE_SIZE): Ditto.
- (WINT_TYPE): Ditto.
- * config/alpha/netbsd.h (WCHAR_TYPE): Remove.
- (WCHAR_UNSIGNED): Ditto.
- (WCHAR_TYPE_SIZE): Ditto.
- (WINT_TYPE): Ditto.
- * config/arm/netbsd.h: Likewise.
- * config/i386/netbsd-elf.h: Likewise.
- * config/i386/netbsd.h: Likewise.
- * config/m68k/netbsd-elf.h: Likewise.
- * config/m68k/netbsd.h: Likewise.
- * config/ns32k/netbsd.h: Likewise.
- * config/sparc/netbsd.h: Likewise.
- * config/vax/netbsd.: Likewise.
+ * config/rs6000/spe.h (__ev_set_acc_u64): Use __ev_create_u64 to
+ convert uint64_t into __ev64_opaque__.
+ (__ev_set_acc_s64): Likewise, but using signed types.
-2002-02-05 Alexandre Oliva <aoliva@redhat.com>
+2002-10-08 Ulrich Weigand <uweigand@de.ibm.com>
- * target.h (struct gcc_target): Added ms_bitfield_layout_p.
- * target-def.h (TARGET_MS_BITFIELD_LAYOUT_P): New. Added to...
- (TARGET_INITIALIZER): this.
- * doc/tm.texi (TARGET_MS_BITFIELD_LAYOUT_P): Document.
- (BITFIELD_NBYTES_LIMITED): Markup fix.
- * tree.h (default_ms_bitfield_layout_p): Declare.
- (record_layout_info): Added prev_field.
- * tree.c (default_ms_bitfield_layout_p): New fn.
- * c-decl.c (finish_struct): Disregard EMPTY_FIELD_BOUNDARY and
- PCC_BITFIELD_TYPE_MATTERS for MS bit-field layout.
- * stor-layout.c: Include target.h.
- (start_record_layout): Initialize prev_field.
- (place_field): Handle MS bit-field layout, and disregard
- EMPTY_FIELD_BOUNDARY, BITFIELD_NBYTES_LIMITED and
- PCC_BITFIELD_TYPE_MATTERS in this case. Update prev_field.
- * Makefile.in (stor-layout.o): Adjust dependencies.
+ * config/s390/s390.md ("*doloop_si_long"): Add missing operand.
+ ("*doloop_di_long"): Likewise.
-2002-02-05 Jason Merrill <jason@redhat.com>
+2002-10-08 Jan Hubicka <jh@suse.cz>
- * collect2.c (dump_file): Pass DMGL_VERBOSE to cplus_demangle.
+ * print-rtl.c (print_rtx): Increase buffer size for real numbers.
-2002-02-05 Andreas Jaeger <aj@suse.de>
+2002-10-08 Richard Sandiford <rsandifo@redhat.com>
- * crtstuff.c: Fix comments.
+ * config/mips/mips.md (define_attr cpu): Add r4111.
-2002-02-05 Richard Henderson <rth@redhat.com>
+2002-10-08 Anthony Green <green@redhat.com>
- PR fortran/3393
- * loop.c (loop_iv_add_mult_emit_before): Copy multiplier as well.
- (loop_iv_add_mult_sink, loop_iv_add_mult_hoist): Likewise.
+ * bitmap.c (bitmap_equal_p): Clear all bitmap_head fields.
- PR fortran/3392
- * config/mips/mips.c (function_arg): Handle TImode.
- (function_arg_advance): Likewise.
+2002-10-08 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
-2002-02-05 Aldy Hernandez <aldyh@redhat.com>
+ * config/c4x/c4x.c (c4x_print_operand): Enlarge buffer
+ for REAL_VALUE_TO_DECIMAL output.
- * config/rs6000/altivec.h (vec_step_help): Rename to
- __vec_step_help.
+2002-10-07 David Edelsohn <edelsohn@gnu.org>
-2002-02-05 Aldy Hernandez <aldyh@redhat.com>
+ * config/rs6000/rs6000.c (rs6000_override_options): Set
+ real_format_for_mode for IBM extended format, if enabled.
+ (easy_fp_constant): Add TFmode.
+ (rs6000_legitimize_address): Add TFmode.
+ (rs6000_legitimate_address): Same.
+ (function_arg_advance): TFmode uses two FPRs.
+ (rs6000_emit_prologue): Fix warning.
+ (rs6000_output_function_epilogue): Add TFmode.
+ (output_toc): Add TFmode.
+ * rs6000.h (SLOW_UNALIGNED_ACCESS): Add TFmode.
+ (LEGITIMATE_OFFSET_ADDRESS_P): Add TFmode.
+ * rs6000.md (movtf splitter): Load TFmode constant.
- * config/rs6000/altivec.h: Fix typos.
+2002-10-07 Dale Johannesen <dalej@apple.com>
-2002-02-05 Jason Thorpe <thorpej@wasabisystems.com>
+ * rtl.h: Add NOTE_PRECONDITIONED.
+ * unroll.c: Set it.
+ * loop.c: Set loop_info->preconditioned from it.
+ * doloop.c: Permit doloop treatment when loop_info->preconditoned.
- * config/arm/netbsd.h: Correct a comment.
+2002-10-07 Richard Henderson <rth@redhat.com>
-2002-02-05 Aldy Hernandez <aldyh@redhat.com>
+ * config/i960/i960.c (i960_setup_incoming_varargs): Create a
+ new rtx for comparing the argument pointer against zero.
+ (i960_va_start): Similarly.
- * config/rs6000/rs6000.c (altivec_init_builtins): Fix typo
- building void typed builtins.
+2002-10-07 Richard Henderson <rth@redhat.com>
- * config/rs6000/altivec.h (vec_ld*): Fix typos.
- (vec_step): Implement for C++.
+ * config/i960/i960.md (*): Use TFmode, not XFmode.
+ * config/i960/i960.c (*): Likewise.
+ (i960_arg_size_and_align): Remove XFmode alignment hack.
+ (i960_round_align): Merge code from ROUND_TYPE_ALIGN.
+ * config/i960/i960.h (LONG_DOUBLE_TYPE_SIZE): Use 128, not 96.
+ (MAX_LONG_DOUBLE_TYPE_SIZE): Likewise.
+ (DATA_ALIGNMENT, ROUND_TYPE_SIZE): Remove.
-Mon Feb 4 19:23:19 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2002-10-07 Richard Henderson <rth@redhat.com>
- * final.c (final_scan_insn): Add case for NOTE_INSN_LOOP_END_TOP_COND.
+ * config/fp-bit.c (EXTENDED_FLOAT_STUBS): Flush out all XF/TFmode
+ entry points; use void return value and argument list.
-2002-02-04 Richard Henderson <rth@redhat.com>
+2002-10-05 Naohiko Shimizu <nshimizu@keyaki.cc.u-tokai.ac.jp>
- * combine.c (nonzero_bits): Re-introduce special case for
- sp/fp/ap wrt REGNO_POINTER_ALIGN.
+ * t-pdp11: Add MULTILIB support for msoft-float.
+ * pdp11.h (LEGITIMATE_CONSTANT_P): Fix soft-float case.
+
+ * t-pdp11: Add LIB2FUNCS_EXTRA.
+ * pdp11.c (pdp11_output_function_prologue): Restrict offset to 16bit,
+ add preceding 0 to the octal constant, rename 'fp' to 'r5', rename
+ 'fldd' to 'ldd', rename 'fstd' to 'std'.
+ (pdp11_output_function_epilogue): Likewise.
+ (output_move_quad): Make the comment gas compatible.
+ (output_ascii): Add preceding 0 to the octal constant.
+ (print_operand_address): Add pre_modify, post_modify.
+ (output_addr_const_pdp11): Add preceding 0 to the octal constant.
+ * pdp11.h (GO_IF_LEGITIMATE_ADDRESS) : Add 'movb' pre_modify case
+ with the indication of Paul Koning.
+ (PRINT_OPERAND): Fix floating constant.
+ * pdp11.md (movdi): Restrict matching pattern.
+ (movqi): Generalize the matching pattern.
+ (movdf): Restrict matching pattern.
+ (zero_extendqihi2): Change constant representation.
+ (floatsidf2): Fix wrong operands.
+ (addqi3): Fix wrong instruction name.
+ (subqi3): Fix wrong instruction name.
+ (andsi3, andhi3, andqi3): Simplify and fix to use 'bic'.
+ (xorsi3): Fix wrong insn.
+ (one_cmplqi2): Add two operand pattern.
+ (lsrsi3): New.
+ (negsi2): New.
+ (call): Add register indirect case.
+ (mod): Fix wrong subreg.
+
+2002-10-06 Eric Botcazou <ebotcazou@libertysurf.fr>
+ Volker Reichelt <reichelt@igpm.rwth-aachen.de>
-2002-02-05 Aldy Hernandez <aldyh@redhat.com>
+ PR c/7411
+ * expr.c (expand_expr) [PLUS]: Simplify after the operands
+ have been expanded in EXPAND_NORMAL mode.
- * doc/extend.texi: Warn about unsupported usage of altivec
- builtins.
+2002-10-06 Richard Henderson <rth@redhat.com>
- * config/rs6000/rs6000.md (altivec_vcmp*_p): Remove.
- (altivec_predicate_*): New.
+ * config/rs6000/rs6000.md (load_toc_v4_PIC_2): Fix base constraint.
- * config/rs6000/altivec.h: Rewrite predicates to use new builtins.
- Add C++ version of vec_*() functions.
+2002-10-06 Richard Henderson <rth@redhat.com>
- * config/rs6000/rs6000.c (bdesc_altivec_preds): New.
- (bdesc_2arg): Remove altivec predicates.
- (altivec_expand_builtin): Handle predicates.
- (altivec_init_builtins): Handle predicates.
- (altivec_expand_predicate_builtin): New.
+ PR optimization/2960
+ * toplev.c (rest_of_compilation): Don't copy_loop_headers if
+ optimize_size.
-2002-02-04 John David Anglin <dave@hiauly1.hia.nrc.ca>
+2002-10-06 Alexandre Oliva <aoliva@redhat.com>
- * pa.c (DO_FRAME_NOTES): Move forward.
- (store_reg): Revise handling of frame notes.
- (load_reg): Likewise.
- (set_reg_plus_d): Likewise.
- (hppa_expand_prologue): Likewise.
- (hppa_expand_epilogue): Likewise.
+ * config/mips/mips.h (SIZE_TYPE, PTRDIFF_TYPE): Override
+ previously definitions.
-2002-02-04 John David Anglin <dave@hiauly1.hia.nrc.ca>
+2002-10-06 Frank Ch. Eigler <fche@redhat.com>
- * unwind-dw2-fde-glibc.c: Define _GNU_SOURCE if not defined.
+ * cppinit.c (init_standard_includes, parse_option): Use strncmp.
+ * c-opts.c (find_opt): Similarly.
-2002-02-04 Jakub Jelinek <jakub@redhat.com>
+2002-10-05 Jakub Jelinek <jakub@redhat.com>
- PR c/4475, c++/3780:
- * c-common.def (SWITCH_STMT): Add SWITCH_TYPE operand.
- * c-common.h (SWITCH_TYPE): Define.
- * c-typeck.c (c_start_case): Set SWITCH_TYPE.
- * stmt.c (all_cases_count): Set lastval to thisval at end of loop.
- Rename spareness variable to sparseness.
- (expand_end_case_type): Renamed from expand_end_case, use orig_type
- if non-NULL instead of TREE_TYPE (orig_index).
- * tree.h (expand_end_case_type): Renamed from expand_end_case.
- (expand_end_case): Define using expand_end_case_type.
- * c-semantics.c (genrtl_switch_stmt): Pass SWITCH_TYPE
- to expand_end_case_type.
- * doc/c-tree.texi (SWITCH_STMT): Document SWITCH_TYPE.
+ * gcc.c (set_multilib_dir): Don't access *end.
+ Use memcpy instead of strncpy. Don't write beyond malloced buffer.
+ (print_multilib_info): Don't show paths starting with ".:".
+ * genmultilib: Add new option, "yes" if multilibs are enabled.
+ Update comments. If multilibs not enabled, print .:${osdirout}
+ for each directory. If multilibs are enabled, always print
+ ${dirout}:${osdirout}, even if the two are the same.
+ * Makefile.in (s-mlib): Pass @enable_multilib@ to genmultilib.
+ Pass all MULTILIB_* variables to genmultilib even if
+ --disable-multilib but MULTILIB_OSDIRNAMES is not empty.
-2002-02-04 John David Anglin <dave@hiauly1.hia.nrc.ca>
+2002-10-04 Bruce Korb <bkorb@gnu.org>
- * pa.h (PREFERRED_STACK_BOUNDARY): Define to match standard rounding.
- (BIGGEST_ALIGNMENT): Change to 128.
+ * fixinc/inclhack.def(hpux11_abs): use format fix
+ * fixinc/fixincl.x: regenerate
+ * fixinc/tests/base/stdlib.h: accommodate new fix test
-2002-02-04 John David Anglin <dave@hiauly1.hia.nrc.ca>
+2002-10-05 Jan Hubicka <jh@suse.cz>
- * pa32-linux.h (LINK_COMMAND_SPEC): Define.
+ * c-common.c (cb_register_builtins): Use really_no_inline.
-2002-02-04 John David Anglin <dave@hiauly1.hia.nrc.ca>
+2002-10-04 David Edelsohn <edelsohn@gnu.org>
- * pa.md (call_internal_reg_64bit): Remove unused variable.
+ * unroll.c (copy_loop_body): Remove REG_EQUAL note attached to
+ copied instruction if the note is not loop invariant.
-2002-02-04 Nick Clifton <nickc@cambridge.redhat.com>
+2002-10-04 Loren J. Rittle <ljrittle@acm.org>
- * config/arm/arm.h (machine_function): Add uses_anonymous_args
- field.
- (SETUP_INCOMING_VARARGS): Set uses_anonymous_args.
- * config/arm/arm.c (current_function_anonymous_args): Delete,
- replace uses with cfun->machine->uses_anonymous_args.
- (arm_reorg): Do not reset uses_anonymous_args.
-
- * config/arm/arm.c (arm_hard_regno_mode_ok): Allow any value in
- any geenral register.
-
-2001-02-04 Bernd Schmidt <bernds@redhat.com>
-
- * cfgrtl.c (force_nonfallthru_and_redirect): Don't try to redirect
- the entry block.
-
-2002-02-04 Richard Henderson <rth@redhat.com>
-
- * combine.c (force_to_mode): Remove STACK_BIAS code.
- (nonzero_bits): Likewise. Replace sp/fp special case with
- REGNO_POINTER_ALIGN.
-
- * config/sparc/sparc.h (FRAME_POINTER_REGNUM): Change to SFP.
- (HARD_FRAME_POINTER_REGNUM): New.
- (FIRST_PSEUDO_REGISTER, REG_CLASS_CONTENTS): Update.
- (FIXED_REGS, CALL_USED_REGS): Update.
- (REG_ALLOC_ORDER, REGISTER_NAMES): Update.
- (CONDITIONAL_REGISTER_USAGE): Update for HFP.
- (HARD_REGNO_NREGS): Update for SFP.
- (STACK_POINTER_OFFSET): Include bias here ...
- (FIRST_PARM_OFFSET): ... not here.
- (STACK_BIAS): Remove.
- (INIT_EXPANDERS): New.
- (STARTING_FRAME_OFFSET): Do not include bias.
- (ELIMINABLE_REGS, CAN_ELIMINATE, INITIAL_ELIMINATION_OFFSET): New.
- (REGNO_OK_FOR_INDEX_P, REGNO_OK_FOR_BASE_P): Update for SFP.
- (REG_OK_FOR_INDEX_P, REG_OK_FOR_BASE_P): Likewise.
- * config/sparc/aout.h (DBX_REGISTER_NUMBER): Update for HFP.
- * config/sparc/litecoff.h, config/sparc/sol2.h: Likewise.
- * config/sparc/sparc.c (mem_min_alignment): Update for HFP.
- (sparc_nonflat_function_prologue, epilogue_renumber): Likewise.
- (MUST_SAVE_REGISTER): Likewise.
- (sparc_flat_function_prologue): Likewise.
- (sparc_flat_function_epilogue): Likewise.
- (HARD_FRAME_POINTER_MASK): Rename from FRAME_POINTER_MASK.
- (sparc_init_modes): SFP is GENERAL_REGS.
- (sparc_builtin_saveregs): SFP does not have bias applied.
-
-2002-02-04 Richard Henderson <rth@redhat.com>
-
- * config/alpha/alpha.c (current_function_is_thunk): Don't check
- current_function_is_thunk.
- (alpha_sa_mask): Distinguish between current_function_is_thunk
- called from ASM_OUTPUT_MI_THUNK and not.
- (alpha_does_function_need_gp): Thunks always need gp.
- (alpha_start_function, alpha_output_function_end_prologue): Likewise.
- (alpha_output_mi_thunk_osf): New.
- * config/alpha/alpha-protos.h: Update.
- * config/alpha/alpha.h (ASM_OUTPUT_MI_THUNK): New.
+ * gcc/ginclude/stddef.h: Support the FreeBSD 5 typedef system.
-2002-02-04 Richard Sandiford <rsandifo@redhat.com>
+2002-10-04 Steve Ellcey <sje@cup.hp.com>
- * c-typeck.c (build_c_cast): Warn when qualifiers are added to
- function types, not when they're taken away.
+ * doc/invoke.texi (HPPA): Add -mlinker-opt, -mgnu-ld,
+ and -mhp-ld options to list of options. Add -mgnu-ld
+ and -mhp-ld option descriptions.
-Mon Feb 4 09:05:58 2002 Jeffrey A Law (law@redhat.com)
+2002-10-04 Steve Ellcey <sje@cup.hp.com>
- * cfgrtl.c (try_redirect_by_replacing_jump): Remove associated
- CODE_LABEL and jump table when replacing a table jump with a
- simple jump.
+ * fixinc/inclhack.def (hpux11_abs): New.
+ (stdio_va_list): change __va_list__ to __gnuc_va_list.
+ * fixinc/fixincl.x: Rebuild.
-2002-02-04 Ulrich Weigand <uweigand@de.ibm.com>
+2002-10-04 Roger Sayle <roger@eyesopen.com>
- * config/s390/s390-protos.h (legitimize_la_operand,
- s390_secondary_input_reload_class, s390_plus_operand,
- s390_expand_plus_operand): Add prototypes.
+ * config/i386/i386.h (processor_costs): Add new fields fadd,
+ fmul, fdiv, fabs, fchs and fsqrt to costs structure.
+ (RTX_COSTS): Use these fields to determine the RTX costs
+ of floating point addition/subtraction, multiplication,
+ division, fabs, negation and square root respectively.
+ * config/i386/i386.c (size_cost): Provide instruction sizes
+ for these new fields.
+ (i386_cost, i486_cost, pentium_cost, pentiumpro_cost,
+ k6_cost, athlon_cost, pentium4_cost): Provide typical cycle
+ counts for these new fields for all x86 processor variants.
- config/s390/s390.c (s390_secondary_input_reload_class,
- s390_plus_operand, s390_expand_plus_operand): New functions.
+2002-10-04 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- (struct s390_address): New member 'pointer'.
- (s390_decompose_address): Compute it.
- (legitimate_la_operand_p): Use it.
- (legitimize_la_operand): New function.
- (movti, movdi, movdf splitters): Call it.
+ * mips.c (mips_const_double_ok): Delete unused variable.
- config/s390/s390.h (SECONDARY_INPUT_RELOAD_CLASS): Define.
- (PREDICATE_CODES): Add s390_plus_operand.
+ * gengtype.c (rtx_next): Change type to int.
- config/s390/s390.md (adddi3_inv_64, addaddr_ccclobber): Delete.
- (la_ccclobber): Allow GENERAL_REGS as output operand.
+2002-10-04 Andreas Jaeger <aj@suse.de>
- (reload_load_address, *reload_load_address_reg_0, *la, *do_la_reg_0,
- *reload_la_64, *reload_la_31 and splitters): Delete, replace by ...
- (*la_64, *la_31, reload_indi, reload_insi): ... these.
+ * config/i386/t-linux64 (MULTILIB_OSDIRNAMES): Fix value.
-2002-02-04 Ulrich Weigand <uweigand@de.ibm.com>
+2002-10-04 Richard Henderson <rth@redhat.com>
- * gcc/config/s390/s390.h (CRT_CALL_STATIC_FUNCTION): Fixed
- register names for regular asm () construct.
+ * real.h (SIGNIFICAND_BITS): Add one more word.
+ (CONST_DOUBLE_FORMAT): Accomodate 6 words.
+ * real.c (times_pten): New.
+ (real_to_decimal, real_from_string): Use it.
+ (sticky_rshift_significand): Use & to find modulus.
+ (rshift_significand, lshift_significand): Likewise.
+ (do_divide): Apply sticky bit after normalization.
+ (real_to_decimal, real_to_hexadecimal): Fix sign of Inf and NaN.
-2002-02-04 Jakub Jelinek <jakub@redhat.com>
+2002-10-03 Andreas Jaeger <aj@suse.de>
- * config/i386/i386.md (movsf_1): Allow moving SF values in MMX
- registers.
+ * gengtype.c (adjust_field_rtx_def): Cast variables of type size_t
+ to unsigned long, adjust printf format string.
+ (output_mangled_typename): Likewise.
-2002-02-04 Jakub Jelinek <jakub@redhat.com>
+2002-10-03 Jason Thorpe <thorpej@wasabisystems.com>
- * combine.c (recog_for_combine): Create a dummy insn with PATTERN
- pat for recog.
+ * config/vax/vax.c (vax_output_function_prologue): Use asm_fprintf.
+ * config/vax/vax.h (VAX_FUNCTION_PROFILER_NAME): New.
+ (FUNCTION_PROFILER): Rewrite to use ASM_GENERATE_INTERNAL_LABEL,
+ assemble_name, asm_fprintf, and VAX_FUNCTION_PROFILER_NAME.
+ (ASM_OUTPUT_MI_THUNK): Use asm_fprintf instead of REGISTER_PREFIX.
+ (PRINT_OPERAND_PUNCT_VALID_P): Fix comment.
+ * config/vax/elf.h (FUNCTION_PROFILER): Remove.
+ (VAX_FUNCTION_PROFILER_NAME): Redefine as "__mcount".
-2002-02-04 Hartmut Penner <hpenner@de.ibm.com>
+2002-10-03 Mark Mitchell <mark@codesourcery.com>
- * varasm.c (decode_rtx_const): Allow unspec (symbol_ref) in
- constant pool to be identical by string address and index.
+ * doc/invoke.texi (-Wabi): Document mangling bug.
-2002-02-04 Anthony Green <green@redhat.com>
+2002-10-04 Alan Modra <amodra@bigpond.net.au>
- * output.h (SECTION_OVERRIDE): Define.
- * varasm.c (named_section): Obey SECTION_OVERRIDE.
+ * config/rs6000/rs6000.c (rs6000_output_function_epilogue): Use a
+ name for the tbtab label that depends on the function asm name.
+ Don't output tbtab label unless optional_tbtab.
+ (output_mi_thunk): Formatting.
-2002-02-03 Jason Thorpe <thorpej@wasabisystems.com>
+2002-10-03 Richard Henderson <rth@redhat.com>
- * config.gcc (arm*-*-netbsdelf*): Placeholder to prevent match
- by existing arm*-*-netbsd* (a.out) target.
- (ns32k-*-netbsdelf*): Likewise.
- (sparc-*-netbsdelf*): Likewise.
- (vax-*-netbsdelf*): Likewise.
+ * config/m68k/m68k.h (OVERRIDE_OPTIONS): Move additional code ...
+ * config/m68k/m68k.c (override_options): ... here.
+ * config/m68k/m68kelf.h (OVERRIDE_OPTIONS): Remove.
+ * config/m68k/m68kv4.h (OVERRIDE_OPTIONS): Remove.
+ * config/m68k/linux.h (SUBTARGET_OVERRIDE_OPTIONS): Remove.
+ * config/m68k/netbsd-elf.h (SUBTARGET_OVERRIDE_OPTIONS): Remove.
-2002-02-03 Danny Smith <dannysmith@users.sourceforge.net>
+2002-10-03 Richard Henderson <rth@redhat.com>
- * gthr-win32.h: Protect against conflicting typedef for BOOL in windows
- headers and libobjc headers.
+ * real.h (struct real_value): Use ENUM_BITFIELD.
-2002-02-03 Mumit Khan <khan@nanotech.wisc.edu>
+2002-10-03 Richard Henderson <rth@redhat.com>
- * gthr-win32.h (__mingwthr_key_dtor): Use extern "C" linkage for C++.
- (_mingw.h): Remove duplicate include.
+ * config/i960/i960.md (call, call_value): Use emit_call_insn.
-2002-02-03 Jason Thorpe <thorpej@wasabisystems.com>
+2002-10-03 Steve Ellcey <sje@cup.hp.com>
- * config.gcc: Set cpu_type to m68k for 68010, as well.
- (m68010-*-netbsdelf*): New...
- (m68k*-*-netbsdelf*): ...targets.
- * config/m68k/netbsd-elf.h: New file.
+ * config/pa/pa64-hpux.h (INIT_ENVIRONMENT): New.
-2002-02-02 Kazu Hirata <kazu@hxi.com>
+2002-10-03 Steve Ellcey <sje@cup.hp.com>
- * config/h8300/h8300.c (hand_list): Move inside function_arg.
+ * config.gcc (hppa*64*-*-hpux11*): Check gnu_ld.
+ * config/pa/pa.h (MASK_GNU_LD): New.
+ (TARGET_GNU_LD): New.
+ * config/pa/pa64-hpux.h (LINK_SPEC): Set based
+ on gnu-ld and MASK_GNU_LD.
+ (SUBTARGET_SWITCHES): New gnu-ld & hp-ld flags.
-2002-02-02 Kazu Hirata <kazu@hxi.com>
+2002-10-03 Jan Hubicka <jh@suse.cz>
- * config/h8300/h8300.c (h8_push_ops): Move inside
- h8300_init_once.
- (h8_pop_ops): Likewise.
- (h8_move_ops): Likewise.
+ * i386.c (athlon_cost): Fix the move costs.
-2002-02-02 Kazu Hirata <kazu@hxi.com>
+2002-10-03 Jan Hubicka <jh@suse.cz>
- * config/h8300/h8300.c (os_task): Make it static.
- (monitor): Likewise.
- (pragma_saveall): Likewise.
+ * final.c (final): Use symbol name as function name for profiling.
+ * profile.c (get_exec_counts): Likewise.
+ (branch_prob): Likewise.
-2002-02-02 Alexandre Oliva <aoliva@redhat.com>
+2002-10-03 Jakub Jelinek <jakub@redhat.com>
- * config/sh/sh.md (ic_invalidate_line): Make sure the immediate
- constant is a valid sign-extension for Pmode.
+ * longlong.h (__udiv_qrnnd): Remove PARAMS from prototype.
-2002-02-02 Kazu Hirata <kazu@hxi.com>
+2002-10-03 Jakub Jelinek <jakub@redhat.com>
- * config/h8300/h8300.c: Fix formatting.
+ * gcc.c (print_multi_os_directory): New variable.
+ (option_map): Support --print-multi-os-directory.
+ (struct prefix_list): Add os_multilib field.
+ (multilib_os_dir): New variable.
+ (static_specs): Add multilib_options.
+ (find_a_file): Add multilib argument. Search in GCC or OS multilib
+ subdirs if non-zero.
+ (read_specs, execute): Update callers.
+ (find_file): Likewise. Don't prefix name with multilib_dir, instead
+ pass 1 as multilib option.
+ (display_help): Include --print-multi-os-directory.
+ (add_prefix): Add os_multilib argument. Initialize pl->os_multilib.
+ (process_command): Update callers. Handle --print-multi-os-directory.
+ (do_spec_1) ['D']: Use multilib_os_directory if pl->os_multilib is
+ set.
+ (main): Update find_a_file and add_prefix callers.
+ Handle print_multi_os_directory.
+ (struct mdswitchstr): New.
+ (mdswitches, n_mdswitches): New variables.
+ (used_arg): Add MULTILIB_DEFAULT switches too if they are not
+ present on the command line nor their mutually incompatible
+ switches.
+ (default_arg): Optimize.
+ (set_multilib_dir): Compute multilib_os_dir. Initialize mdswitches
+ array.
+ (print_multilib_info): Only print GCC multilib dir name, not OS
+ multilib dirname.
+ * genmultilib: Add osdirnames parameter. Output multilib_options
+ variable. If osdirnames is specified, output dirnames as
+ dirname:osdirname.
+ * mklibgcc.in: Use MULTILIB_OSDIRNAMES, --print-multi-directory
+ and --print-multi-os-directory instead of SHLIB_SLIBDIR_SUFFIXES
+ to compute libgcc_s soname and install path.
+ * Makefile.in (libgcc.mk): Pass MULTILIB_OSDIRNAMES instead of
+ SHLIB_SLIBDIR_SUFFIXES to mklibgcc.
+ (s_mlib): Pass MULTILIB_OSDIRNAMES or nothing as last genmultilib
+ argument.
-2002-02-02 Kazu Hirata <kazu@hxi.com>
+ * config/sparc/t-linux64 (MULTILIB_OSDIRNAMES): Set.
+ (SHLIB_SLIBDIR_SUFFIXES): Remove.
+ * config/sparc/linux64.h (STARTFILE_SPEC32, STARTFILE_SPEC64,
+ ENDFILE_SPEC32, ENDFILE_SPEC64, ENDFILE_COMMON): Remove.
+ (STARTFILE_SPEC, ENDFILE_SPEC): Don't distinguish between -m32
+ and -m64.
+ * config/sparc/t-sol2-64 (MULTILIB_OSDIRNAMES): Set.
+ (SHLIB_SLIBDIR_SUFFIXES): Remove.
+ * config/sparc/sol2-bi.h (STARTFILE_ARCH64_SPEC): Remove.
+ (STARTFILE_ARCH_SPEC): Remove.
+ * config/i386/t-linux64 (MULTILIB_OSDIRNAMES): Set.
+ (SHLIB_SLIBDIR_SUFFIXES): Remove.
+ * config/i386/linux64.h (STARTFILE_PREFIX_SPEC): Remove.
+ * config/mips/t-iris6 (MULTILIB_OSDIRNAMES): Set.
+ (SHLIB_SLIBDIR_SUFFIXES): Remove.
- * config/h8300/h8300.md: Fix formatting.
+2002-10-03 Jan Hubicka <jh@suse.cz>
-2002-02-02 Kazu Hirata <kazu@hxi.com>
-
- * config/h8300/h8300.md (one_cmpl patterns): Tighten the
- predicates of operands[1]. Split the patterns for each
- processor variant.
-
-2002-02-02 Kazu Hirata <kazu@hxi.com>
-
- * config/h8300/h8300.md (xor patterns): Tighten the predicates
- of operands[1] to register_operand.
-
-2002-02-02 Neil Booth <neil@daikokuya.demon.co.uk>
-
- * cpphash.h (struct spec_nodes): Remove n__CHAR_UNSIGNED__.
- * cpphash.c (_cpp_init_hashtable): Similarly.
- * cppinit.c (cpp_create_reader): Default the signed_char flag.
- (init_builtins): Define __CHAR_UNSIGNED__ appropriately.
- (COMMAND_LINE_OPTIONS): Recognise -f{un,}signed-char.
- (cpp_handle_option): Handle the new options.
- * cpplex.c (cpp_interpret_charconst): Use new flag.
- * cpplib.h (struct cpp_options): New member signed_char.
- * gcc.c (cpp_unique_options): Remove %c spec and documentation.
- (cpp_options): Handle -fsigned-char and -funsigned-char.
- (static_specs): Remove signed_char_spec.
- (do_spec1): Don't handle %c.
- * system.h: Poison SIGNED_CHAR_SPEC.
- * tradcif.y (yylex): Use flag_signed_char.
- * tradcpp.h (flag_signed_char): New.
- * tradcpp.c (flag_signed_char): New.
- (main): Handle new command-line options.
- (initialize_builtins): Define __CHAR_UNSIGNED__ if appropriate.
-config:
- * alpha/alpha.h (SIGNED_CHAR_SPEC): Remove.
- * avr/avr.h: Remove old comments.
- * i960/i960.h (CPP_SPEC): Pass -fsigned-char if -mic*.
- (CC1_SPEC): Pass -fsigned-char if -mic*.
- (SIGNED_CHAR_SPEC): Remove.
-doc:
- * tm.texi (SIGNED_CHAR_SPEC): Remove documentation.
-
-2002-02-01 Eric Christopher <echristo@redhat.com>
-
- From Daniel Jacobowitz <dmj+@andrew.cmu.edu>
- * config/mips/mips.h (FUNCTION_PROFILER): Fix function profiling.
- * config/mips/linux.h (ASM_OUTPUT_REG_PUSH): Undefine.
- (ASM_OUTPUT_REG_POP): Ditto.
-
-2002-02-02 Neil Booth <neil@daikokuya.demon.co.uk>
-
- * c-decl.c, tree.c, tree.h, objc/objc-act.c: Revert bitfield
- patch.
-
-2002-02-02 Jakub Jelinek <jakub@redhat.com>
-
- * config/i386/i386.h (CPP_CPUCOMMON_SPEC): Add missing | separators.
-
-2002-02-02 Jakub Jelinek <jakub@redhat.com>
-
- PR c/5304:
- * expmed.c (expand_mult_highpart): Use immed_double_const for wide_op1
- unconditionally.
+ * predict.c (choose_function_section): Avoid choice for linkonce functions.
-2002-02-01 Janis Johnson <janis187@us.ibm.com>
+2002-10-03 Jan Hubicka <jh@suse.cz>
- * cfganal.c: Include tm_p.h.
- (keep_with_call_p): Fix the test that determines if a register holds
- the return value of a call.
+ * i386.md (lea to mul peep2): Fix condition.
-2002-02-01 DJ Delorie <dj@redhat.com>
+2002-10-02 John David Anglin <dave@hiauly1.hia.nrc.ca>
- * config/sparc/sparc.c (sparc_emit_set_symbolic_const64): If
- we are given conflicting registers, switch to the other one we
- had allocated for us.
- * config/sparc/sparc.md (reload_indi, reload_outdi): Pass op[2]
- as TImode so we know when the "other" register is available.
+ * pa-linux.h (FUNCTION_OK_FOR_SIBCALL): Delete macro.
+ * pa32-linux.h (FUNCTION_OK_FOR_SIBCALL): Define.
-2002-02-01 David O'Brien <obrien@FreeBSD.org>
+2002-10-02 Richard Henderson <rth@redhat.com>
- * config/sparc/sol2-sld-64.h: Include sparc/biarch64.h rather than
- sparc/sparc_bi.h.
+ PR opt/7124
+ * config/i386/i386.c (ix86_register_move_cost): Increase cost
+ for secondary_memory_needed pairs.
-2002-02-01 Janis Johnson <janis187@us.ibm.com>
+2002-10-02 Nathanael Nerode <neroden@gcc.gnu.org>
- * cfganal.c (keep_with_call_p): New function.
- (flow_call_edges_add): Prevent splitting a block between a call and
- a single-set instruction that should be kept in the same block.
+ * doc/vms.texi: Blow away false include file section.
-2002-02-01 Craig Rodrigues <rodrigc@gcc.gnu.org>
+2002-10-02 Roger Sayle <roger@eyesopen.com>
- * doc/install.texi (avr): Update outdated URL.
+ PR optimization/6627
+ * toplev.c (force_align_functions_log): New global variable.
+ * flags.h (force_align_functions_log): Add extern prototype.
+ * varasm.c (assemble_start_function): Use it to force minimum
+ function alignment.
+ * config/i386/i386.h (FUNCTION_BOUNDARY): Set the correct
+ minimum function alignment to one byte.
+ (TARGET_PTRMEMFUNC_VBIT_LOCATION): Store the virtual bit in
+ the least significant bit of vtable member function pointers.
+ * tree.h (enum ptrmemfunc_vbit_where_t): Move definition to
+ here from cp/cp-tree.h.
-2002-01-30 Andrew Haley <aph@cambridge.redhat.com>
+2002-10-02 Jan Hubicka <jh@suse.cz>
- * config/stormy16/stormy16.md (pushqi): New.
- (popqi): New.
- (pushhi): New.
- (pophi): New.
- (movhi): Remove stack operands.
- (movqi): Likewise.
- * config/stormy16/stormy16.h (PREDICATE_CODES): Add
- nonimmediate_nonstack_operand.
- * config/stormy16/stormy16.c (nonimmediate_nonstack_operand):
- New.
- * config/stormy16/stormy16-protos.h (nonimmediate_nonstack_operand)
- New.
+ * i386.c (print_operand_address): Use RIP addressing for offsetted
+ label refs too.
-2002-01-31 Jason Merrill <jason@redhat.com>
+2002-09-30 David S. Miller <davem@redhat.com>
- * Makefile.in (c-parse.c): Handle .output file.
- * objc/Make-lang.in (objc-parse.c): Likewise.
+ PR middle-end/7151
+ * config/sparc/sparc.md (movdi_insn_sp32_v9): Accept 'e' regs.
+ (movdi reg/reg split): Match only on sparc32, and v9 when int regs.
-2002-02-01 Alexandre Oliva <aoliva@redhat.com>
+2002-10-01 Roger Sayle <roger@eyesopen.com>
- * config/mips/mips.h (ENDIAN_SPEC): Output the endianness flag if
- the -me[lb] option is given. Don't output the default flag
- twice.
+ * unroll.c (loop_iterations): Revert 2002-09-08 change.
-2002-01-31 Zack Weinberg <zack@codesourcery.com>
+2002-10-01 Richard Henderson <rth@redhat.com>
- * c-lex.c (yyparse): Call debug_hooks->start_source_file for
- the primary source file; this has not been done yet.
- * c-decl.c (c_expand_body): Reset input_filename from
- DECL_SOURCE_FILE (fndecl) before calling init_function_start.
+ * real.c (real_to_decimal): Crop trailing zeros for DIGITS < 0.
+ (real_to_hexadecimal): Likewise.
+ * print-rtl.c (print_rtx): If we are linked with real.c, don't
+ dump the XWINT fields of a floating point CONST_DOUBLE.
-2002-01-31 Kazu Hirata <kazu@hxi.com>
+2002-10-01 Jason Thorpe <thorpej@wasabisystems.com>
- * rtlanal.c (subreg_regno_offset): Do not use
- SUBREG_REGNO_OFFSET.
- * system.h: Add SUBREG_REGNO_OFFSET to the GCC poison list.
- * doc/tm.texi (SUBREG_REGNO_OFFSET): Remove.
+ * config/vax/elf.h (FUNCTION_PROFILER): Fix __mcount call.
-2002-01-31 Joseph S. Myers <jsm28@cam.ac.uk>
+2002-10-01 Richard Henderson <rth@redhat.com>
- * gccbug.in: Follow GNU Coding Standards for --version. Use GCC
- version rather than GNATS version in --version output.
+ * calls.c (precompute_register_parameters): Force non-legitimate
+ constants into pseudos.
-2002-01-31 Richard Sandiford <rsandifo@redhat.com>
+2002-10-01 Nick Clifton <nickc@redhat.com>
- * ifcvt.c (noce_process_if_block): Make a copy of the destination
- when copying back from a temporary.
+ * config/rs6000/spe.md (spe_evrlwi): Add missing third operand
+ to assembler template.
-2002-01-30 Richard Henderson <rth@redhat.com>
+2002-10-01 Richard Henderson <rth@redhat.com>
- * ifcvt.c (dead_or_predicable): Handling merging when other_bb
- and new_dest are the same.
+ * dwarf2out.c (loc_descriptor_from_tree): Relax requirement
+ for TLS debug info to !DECL_EXTERNAL.
-2002-01-30 Richard Henderson <rth@redhat.com>
+2002-10-01 Matt Thomas <matt@3am-software.com>
+ Jason Thorpe <thorpej@wasabisystems.com>
- PR opt/5076
- * rtl.h (NOTE_INSN_LOOP_END_TOP_COND): New.
- * rtl.c (note_insn_name): Update.
- * emit-rtl.c (remove_unnecessary_notes): Kill it.
- * stmt.c (expand_end_loop): Kill jump opt code. Use LOOP_END_TOP_COND
- to perform loop rotation.
- (expand_exit_loop_top_cond): New.
- * tree.h (expand_exit_loop_top_cond): Declare it.
- * c-semantics.c (genrtl_while_stmt): Use it.
- (genrtl_for_stmt): Likewise.
+ * config.gcc (vax-*-netbsdelf*): Enable configuration.
+ * config/elfos.h (PCC_BITFIELD_TYPE_MATTERS): Define only
+ if not already defined.
+ * config/vax/elf.h: New file.
+ * config/vax/netbsd-elf.h: New file.
+ * config/vax/vax.c: Include "debug.h".
+ (vax_output_function_prologue): Add dwarf2 support. Use
+ MAIN_NAME_P when checking for VMS_TARGET stack adjust.
+ * config/vax/vax.h (CONST_OK_FOR_LETTER_P): Add cases for
+ 'J' [0..63], 'K' [-128..127], 'L' [-32768..32767],
+ 'M' [0..255], 'N' [0..65535], and, 'O' [-63..-1].
+ (VAX_ISTREAM_SYNC): Remove.
+ (INITIALIZE_TRAMPOLINE): Use gen_sync_istream.
+ (JUMP_TABLES_IN_TEXT_SECTION): Define.
+ (ASM_OUTPUT_REG_POP): Use reg_names for the stack pointer.
+ (ASM_OUTPUT_ADDR_VEC_ELT): Use ASM_GENERATE_INTERNAL_LABEL
+ and assemble_name.
+ (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
+ (PRINT_OPERAND_PUNCT_VALID_P): Accept '|'.
+ (PRINT_OPERAND): Output REGISTER_PREFIX for '|'.
+ (INCOMING_RETURN_ADDR_RTX): Define.
+ * config/vax/vax.md (VUNSPEC_BLOCKAGE)
+ (VUNSPEC_SYNC_ISTREAM): Define.
+ (blockage): Use VUNSPEC_BLOCKAGE.
+ (sync_istream): New insn.
-2002-01-30 Alexandre Oliva <aoliva@redhat.com>
+2002-10-01 Richard Henderson <rth@redhat.com>
- * config/mips/mips.h (PARM_BOUNDARY): Guarantee alignment of
- arguments to 64-bit boundaries on 64-bit ABIs.
+ * config/vax/vax.md (call_pop, *call_pop, call_value_pop)
+ (*call_value_pop, call, call_value): Add dwarf2 EH support.
+ (*call): New insn.
-2002-01-30 Steve Ellcey <sje@cup.hp.com>
+2002-10-01 Nathan Sidwell <nathan@codesourcery.com>
- * loop.c (loop_invariant_p): Special case pic_offset_table_rtx.
+ PR c/8083
+ * c-typeck.c (build_c_cast): Warn about type punning which breaks
+ type based aliasing.
-2002-01-31 Joseph S. Myers <jsm28@cam.ac.uk>
+2002-10-01 Mark Mitchell <mark@codesourcery.com>
- * c-decl.c (grokdeclarator): Handle type being a typedef for an
- invalid type.
+ * stor-layout.c (update_alignment_for_field): New function.
+ (place_union_field): Use it.
+ (place_field): Likewise.
-2002-01-30 David O'Brien <obrien@FreeBSD.org>
+2002-10-01 Nathan Sidwell <nathan@codesourcery.com>
- * config.gcc: Include sparc/biarch64.h rather than sparc/sparc_bi.h.
- * config/sparc/sparc_bi.h: Remove file.
- * config/sparc/biarch64.h: New file (rename of sparc_bi.h).
+ PR other/8077
+ * gcc.c (cc1_options): Add space on -auxbase-strip.
-2002-01-30 Richard Henderson <rth@redhat.com>
+2002-10-01 Jim Wilson <wilson@redhat.com>
- * sched-deps.c (sched_analyze): Make a call read the frame pointer.
+ * config/v850/v850.h (EPILOGUE_USES): Define.
-2002-01-30 Zack Weinberg <zack@codesourcery.com>
+2002-09-30 Andrew Haley <aph@redhat.com>
- * expmed.c (emit_store_flag): Call protect_from_queue on op0 and op1.
+ * flow.c (insn_dead_p): When using non-call-exceptions, don't
+ eliminate insns that may trap.
+ * cse.c (insn_live_p): Likewise.
-2002-01-30 Jason Merrill <jason@redhat.com>
+2002-10-01 Richard Sandiford <rsandifo@redhat.com>
- * dwarf2out.c (dwarf_cfi_name): Add other DWARF 3 codes.
- (output_cfi): Likewise. Disable DW_CFA_GNU_negative_offset_extended.
- (reg_save): Use DW_CFA_offset_extended_sf instead.
+ * config/mips/mips.h (PROCESSOR_R4121): Rename to PROCESSOR_R4120.
+ (TARGET_MIPS4121): Rename to TARGET_MIPS4120.
+ * config/mips/mips.c (mips_cpu_info): Rename vr4121 to vr4120.
+ * config/mips/mips.md: Apply same renaming here.
- * dwarf2out.c (dwarf2out_finish): Don't abort if there were errors.
+2002-10-01 Richard Sandiford <rsandifo@redhat.com>
-2002-01-29 Jakub Jelinek <jakub@redhat.com>
+ * config/mips/mips.c (PROCESSOR_R4320, TARGET_MIPS4320): Remove.
+ (GENERATE_MULT3_SI): Remove use of TARGET_MIPS4320.
+ * config/mips/mips.c (mips_cpu_info): Remove vr4320 entry.
+ * config/mips/mips.md (define_attr cpu): Remove r4320.
+ Remove vr4320 scheduler and uses of TARGET_MIPS4320.
- * cselib.c (cselib_record_sets): Use IF_THEN_ELSE result
- in cselib_lookup.
+2002-10-01 Richard Sandiford <rsandifo@redhat.com>
-2002-01-29 Aldy Hernandez <aldyh@redhat.com>
+ * config/mips/mips.c (mips16_strings): New variable.
+ (mips_output_function_epilogue): Clear the SYMBOL_REF_FLAG of every
+ symbol in mips16_strings. Free the list.
+ (mips_encode_section_info): Keep track of local strings.
- * rs6000.md ("*call_value_local32"): Remove constraints.
- ("*call_value_local64"): Same.
- ("*call_value_indirect_nonlocal_aix32"): Same.
- ("*call_value_nonlocal_aix32"): Same.
- ("*call_value_indirect_nonlocal_aix64"): Same.
- ("*call_value_nonlocal_aix64"): Same.
- ("*call_value_nonlocal_sysv"): Same.
+2002-10-01 Richard Sandiford <rsandifo@redhat.com>
-2002-01-29 Richard Henderson <rth@redhat.com>
+ * config/mips/mips.md (bunge, bltgt, bungt): New define_expands.
+ (sordered_df, sordered_sf): Remove.
+ * config/mips/mips.c (get_float_compare_codes): New fn.
+ (gen_int_relational, gen_conditional_move): Use it.
- * config/alpha/elf.h (SDB_DEBUGGING_INFO): Undef.
+2002-10-01 Richard Sandiford <rsandifo@redhat.com>
-2002-01-29 Richard Henderson <rth@redhat.com>
+ * config/mips/mips-protos.h (mips_emit_fcc_reload): Declare.
+ * config/mips/mips.h (PREDICATE_CODES): Add fcc_register_operand.
+ * config/mips/mips.c (fcc_register_operand): New function.
+ (mips_emit_fcc_reload): New function, extracted from reload_incc.
+ (override_options): Allow TFmode values in float registers
+ if ISA_HAS_8CC.
+ * cnfig/mips/mips.md (reload_incc): Change destination prediate
+ to fcc_register_operand. Remove misleading source constraint.
+ Use mips_emit_fcc_reload.
+ (reload_outcc): Duplicate reload_incc.
- * expr.c (force_operand): Ignore flag_pic for detecting pic
- address loads.
- * regclass.c (init_reg_sets_1): Test fixed_regs not flag_pic
- for determining if PIC_OFFSET_TABLE_REGNUM is call-clobbered.
- * resource.c (mark_target_live_regs): Use regs_invalidated_by_call
- instead of open-coded loop.
- * doc/tm.texi (PIC_OFFSET_TABLE_REGNUM): Clarify that it must
- be fixed when in use.
+2002-09-30 Ulrich Weigand <uweigand@de.ibm.com>
-2002-01-29 Richard Henderson <rth@redhat.com>
+ * longlong.h: Partially synchronize with GMP-4.1 version:
+ Use i370 definitions also for s390.
+ Add generic definition of umul_ppmm in terms of smul_ppmm.
+ [s390] (umul_ppmm): Remove.
+ [s390] (smul_ppmm): Fix incorrect assembler constraints.
+ [s390] (smul_ppmm, sdiv_qrnnd): Rename __xx to __x.
- * sched-int.h (struct deps_reg): Add uses_length, clobbers_length.
- * sched-rgn.c (propagate_deps): Update them.
- * sched-deps.c (sched_analyze_insn): Update them. Flush the
- clobbers list when either gets too long.
+2002-09-30 Bob Wilson <bob.wilson@acm.org>
-2002-01-29 Jakub Jelinek <jakub@redhat.com>
+ * config/xtensa/xtensa.h (REG_CLASS_NAMES, REG_CLASS_CONTENTS):
+ Add new RL_REGS register class.
+ (PREFERRED_RELOAD_CLASS, PREFERRED_OUTPUT_RELOAD_CLASS):
+ Call xtensa_preferred_reload_class for both input and output reloads.
+ * config/xtensa/xtensa.c (xtensa_regno_to_class): Use new RL_REGS class.
+ (xtensa_preferred_reload_class): Handle output reloads; use RL_REGS
+ instead of either AR_REGS or GR_REGS classes.
+ (xtensa_secondary_reload_class): Use new RL_REGS class.
+ * config/xtensa/xtensa-protos.h (xtensa_preferred_reload_class): Update.
- * config/i386/i386.h (LIMIT_RELOAD_CLASS): Handle LEGACY_REGS
- and INDEX_REGS the same as GENERAL_REGS.
- (SECONDARY_OUTPUT_RELOAD_CLASS): Likewise.
+2002-09-30 John David Anglin <dave@hiauly1.hia.nrc.ca>
-2002-01-29 Neil Booth <neil@daikokuya.demon.co.uk>
+ * pa.c (hppa_encode_label): Don't drop '*' from function labels.
+ (pa_strip_name_encoding): Strip '@' and '*', in that order.
+ * pa.h (ASM_OUTPUT_LABELREF): Output user_label_prefix except when
+ there is a '*' prefix in NAME.
- * tree.c (build_nonstandard_integer_type): Correct prototype.
+2002-09-30 Jan Hubicka <jh@suse.cz>
-2002-01-29 Ulrich Weigand <uweigand@de.ibm.com>
+ * reload.c (push_reload): Handle subregs and secondary memory.
+ * reload1.c (gen_reload): Likewise.
- * config/s390/s390.md (movstrsico, movstrdix_64,
- movstrsix_31): Remove, replace by ...
- (movstrdi_short, movstrsi_short, movstrdi_long,
- movstrsi_long): ... these. New.
- (movstrdi, movstrsi): Adapt.
+ * jump.c (reg_or_subregno): New function.
+ * rtl.h (reg_or_subregno): Declare
+ * unroll.c (find_splittable_givs): Handle subregs.
- (rotldi3, rotlsi3, ashldi3, *ashldi3_31, *ashldi3_64,
- ashlsi3, lshrdi3, *lshrdi3_31, *lshrdi3_64, lshrsi3):
- Remove unnecessary CC clobber.
- (*ashrdi3_cc_31, *ashrdi3_cconly_31, *ashrdi3_cc_64,
- *ashrdi3_cconly_64, *ashrsi3_cc, *ashrsi3_cconly): New.
+2002-09-30 Mark Mitchell <mark@codesourcery.com>
- (divmoddi4): Don't partially initialize TImode register.
+ * store-layout.c (finish_record_layout): Add free_p parameter.
+ (layout_type): Pass it.
+ * tree.h (finish_record_layout): Update prototype.
-2002-01-29 Geoffrey Keating <geoffk@redhat.com>
+2002-09-30 Jan Hubicka <jh@suse.cz>
- * doc/sourcebuild.texi (C Tests): Document gcc.dg/debug directory.
+ * i386.h (TARGET_CPP_CPU_BUILTINS): Define __SSE_MATH__.
-2002-01-29 Richard Henderson <rth@redhat.com>
+ * gcse.c (cprop_jump): Check that the register has not
+ been modified
+ (cprop_jump): Likewise.
- * flow.c (print_rtl_and_abort): Remove.
- (print_rtl_and_abort_fcn): Remove.
- (verify_local_live_at_start): Use dump_bb instead.
- (verify_wide_reg): Likewise. Take a basic_block, not rtl endpoints.
- (verify_wide_reg_1): Return 2 on mode test failure.
+2002-09-30 Richard Earnshaw <rearnsha@arm.com>
-2002-01-29 Neil Booth <neil@daikokuya.demon.co.uk>
+ * arm.h (BASE_REG_CLASS): Always return LO_REGS for Thumb.
+ (MODE_BASE_REG_CLASS, case Thumb): Only return BASE_REGS if we know
+ that we have a SImode access, and only then if reload hasn't completed;
+ for all other cases, use LO_REGS.
- PR c/3325, c/3326, c/2511, c/3347
- * c-decl.c (enum_decl_context): Remove BITFIELD.
- (grokdeclarator): Take bitfield width as an input.
- Ensure bitfields are given the correct type. Perform
- bitfield width validation with build_bitfield_integer_type
- rather than waiting for finish_struct.
- (grok_typename, grok_typename_in_parm_context, start_decl,
- push_parmdecl, grokfield, start_function): Update calls to
- grokdeclarator.
- (build_bitfield_integer_type): New function.
- (finish_struct): Move bitfield validation to grokdeclarator
- and build_bitfield_integer_type.
- * tree.c (build_nonstandard_integer_type): New function.
- * tree.h (build_nonstandard_integer_type): New prototype.
-objc:
- * objc-act.c (objc_copy_list): Remove DECL_INITIAL kludge.
+2002-09-29 Richard Henderson <rth@redhat.com>
-2002-01-29 Jakub Jelinek <jakub@redhat.com>
+ * real.c (real_from_string): Apply sign last. Tidy exponent handling.
- PR other/1502:
- * cppinit.c (cpp_handle_option): Add ignore argument, if it is zero,
- don't ignore unrecognized -W* options.
- (cpp_handle_options): Pass 1 as last argument to cpp_handle_option.
- * cpplib.h (cpp_handle_option): Adjust prototype.
- * c-decl.c (c_decode_options): Pass 0 as last argument to
- cpp_handle_option.
+2002-09-29 Richard Henderson <rth@redhat.com>
- PR c/2896:
- * gcc.c (cpp_unique_options): Split from cpp_options.
- (cpp_options): Source cpp_unique_options.
- (default_compilers): Use cpp_unique_options instead of cpp_options
- when used together with cc1_options.
- (static_specs): Add cpp_unique_options.
- * objc/lang-specs.h: Use cpp_unique_options instead of cpp_options
- when used together with cc1_options.
+ PR c/8002
+ * combine.c (force_to_mode): Handle FLOAT_MODE destinations
+ for CONST_INT.
-2002-01-29 Kazu Hirata <kazu@hxi.com>
+2002-09-29 David Edelsohn <edelsohn@gnu.org>
- * config/h8300/h8300-protos.h: Update the prototype of
- output_a_shift.
- * config/h8300/h8300.c (output_a_shift): Remove an unused
- argument 'insn'. Remove redundant code.
- * config/h8300/h8300.md: Adust to the new prototype of
- output_a_shift.
+ * real.h (ibm_extended_format): Declare.
+ * real.c (encode_ibm_extended, decode_ibm_extended): New
+ functions.
-2002-01-29 Kazu Hirata <kazu@hxi.com>
+2002-09-29 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * config/h8300/h8300-protos.h: Update the prototypes of
- emit_a_rotate and expand_a_rotate.
- * config/h8300/h8300.c (emit_a_rotate): Change the type of the
- first argument to 'enum rtx_code'.
- (expand_a_rotate): Likewise.
+ * darwin-protos.h (darwin_asm_output_dwarf_delta): Prototype.
-2002-01-28 Kazu Hirata <kazu@hxi.com>
+ * ia64.c (ia64_hpux_asm_file_end): Const-ify.
- * config/h8300/h8300-protos.h: Update the prototype of
- output_simode_bld.
- * config/h8300/h8300.c (output_simode_bld): Remove an argumen
- 'log2'.
- * config/h8300/h8300.md: Adjust to the new prototype.
+2002-09-29 John David Anglin <dave@hiauly1.hia.nrc.ca>
-2002-01-28 Kazu Hirata <kazu@hxi.com>
+ * expmed.c (extract_bit_field): Fix bit-field extraction from SUBREGs.
- * conifg/h8300/h8300.c (h8300_adjust_insn_length): Remove
- redundant code.
+2002-09-29 Kazu Hirata <kazu@cs.umass.edu>
-2002-01-28 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ * builtins.def: Fix comment formatting.
+ * c-common.def: Likewise.
+ * cfgcleanup.c: Likewise.
+ * combine.c: Likewise.
+ * gengtype.c: Likewise.
+ * params.def: Likewise.
+ * predict.def: Likewise.
+ * rtl.def: Likewise.
+ * stab.def: Likewise.
+ * stor-layout.c: Likewise.
+ * tree.def: Likewise.
+ * config/darwin.c: Likewise.
+ * config/darwin.h: Likewise.
+ * config/dbxcoff.h: Likewise.
+ * config/elfos.h: Likewise.
+ * config/fp-bit.c: Likewise.
+ * config/freebsd-spec.h: Likewise.
+ * config/interix.h: Likewise.
+ * config/libgloss.h: Likewise.
+ * config/linux-aout.h: Likewise.
+ * config/linux.h: Likewise.
+ * config/lynx-ng.h: Likewise.
+ * config/lynx.h: Likewise.
+ * config/netbsd-aout.h: Likewise.
+ * config/netbsd.h: Likewise.
+ * config/netware.h: Likewise.
+ * config/psos.h: Likewise.
+ * config/ptx4.h: Likewise.
+
+2002-09-28 Kazu Hirata <kazu@cs.umass.edu>
+
+ * ChangeLog.4: Fix typos.
+ * ChangeLog.6: Likewise.
+ * FSFChangeLog.10: Likewise.
+ * genattrtab.c: Fix comment typos.
+ * haifa-sched.c: Likewise.
+ * real.c: Likewise.
+ * tree.h: Likewise.
+ * config/arm/arm.c: Likewise.
+ * config/arm/crti.asm: Likewise.
+ * config/arm/crtn.asm: Likewise.
+ * config/frv/frv.c: Likewise.
+ * config/frv/frv.md: Likewise.
+ * config/h8300/h8300.md: Likewise.
+ * config/i386/rtemself.h: Likewise.
+ * config/ia64/unwind-ia64.c: Likewise.
+ * config/ip2k/ip2k.h: Likewise.
+ * config/m88k/m88k.c: Likewise.
+ * config/m88k/m88k.md: Likewise.
+ * config/mips/sr71k.md: Likewise.
+ * config/mmix/mmix.c: Likewise.
+ * config/rs6000/rs6000.c: Likewise.
+ * config/sh/sh.md: Likewise.
- * emit-rtl.c (gen_rtx_REG): Check that the PIC_OFFSET_TABLE_REGNUM
- is a fixed register before returning pic_offset_table_rtx.
- * loop.c (scan_loop): Don't hoist insns that set pic_offset_table_rtx
- when PIC_OFFSET_TABLE_REG_CALL_CLOBBERED is defined.
+2002-09-26 Theodore A. Roth <troth@verinet.com>
-2002-01-28 Jason Merrill <jason@redhat.com>
+ * config/avr/avr.c: Eliminate use of _PC_ in pc relative insns.
+ * config/avr/avr.md: Ditto.
- * dwarf2.h: Sync with src version.
+2002-09-27 Alexander N. Kabaev <ak03@gte.com>
-2002-01-28 Paul Koning <pkoning@equallogic.com>
+ PR preprocessor/8055
+ * cppmacro.c (stringify_arg): Do not overflow the buffer
+ with the terminating NUL when the argument to be stringified
+ has no tokens.
- * builtin-types.def (BT_FN_VOID_CONST_PTR_VAR): Replace
- BT_FN_VOID_PTR_VAR.
- * builtins.def (BUILT_IN_PREFETCH): Change first argument to be const.
- * doc/extend.texi (__builtin_prefetch): Update documentation:
- first argument is now const void ptr.
+2002-09-27 Richard Henderson <rth@redhat.com>
-2002-01-28 Kazu Hirata <kazu@hxi.com>
+ * unroll.c (simplify_cmp_and_jump_insns): New.
+ (unroll_loop): Use it. Use simplify_gen_foo+force_operand
+ instead of expand_simple_foo.
- * config/h8300/h8300-protos.h: Remove an unused prototype.
+2002-09-27 Richard Henderson <rth@redhat.com>
-2002-01-28 Roman Zippel <zippel@linux-m68k.org>
+ PR optimization/7520
+ * cfganal.c (flow_active_insn_p): New.
+ (forwarder_block_p): Use it.
+
+2002-09-27 Richard Henderson <rth@redhat.com>
+
+ * emit-rtl.c (active_insn_p): Revert last change.
+
+2002-09-27 Jakub Jelinek <jakub@redhat.com>
+
+ * doc/extend.texi (tls_model): Document.
+ * varasm.c (decl_tls_model): New.
+ * c-common.c (handle_tls_model_attribute): New.
+ (c_common_attribute_table): Add tls_model.
+ * config/alpha/alpha.c (alpha_encode_section_info): Use
+ decl_tls_model.
+ * flags.h (enum tls_model, flag_tls_default): Move...
+ * tree.h (enum tls_model, flag_tls_default): ...here.
+ (decl_tls_model): New prototype.
+ * config/ia64/ia64.c (ia64_encode_section_info): Likewise.
+ * config/i386/i386.c (ix86_encode_section_info): Likewise.
+ * config/i386/i386.md (tls_global_dynamic, tls_local_dynamic_base):
+ Allow !flag_pic.
+
+2002-09-27 Kazu Hirata <kazu@cs.umass.edu>
+
+ * LANGUAGES: Follow spelling conventions.
+ * rtl.def: Likewise.
+ * sbitmap.c: Likewise.
+ * sched-int.h: Likewise.
+ * sched-rgn.c: Likewise.
+ * sibcall.c: Likewise.
+ * simplify-rtx.c: Likewise.
+ * ssa.c: Likewise.
+ * stab.def: Likewise.
+ * stmt.c: Likewise.
+ * stor-layout.c: Likewise.
+ * target.h: Likewise.
+ * timevar.c: Likewise.
+ * toplev.c: Likewise.
+ * tree-dump.c: Likewise.
+ * tree-inline.c: Likewise.
+ * tree.c: Likewise.
+ * tree.def: Likewise.
+ * tree.h: Likewise.
+ * unroll.c: Likewise.
+ * varasm.c: Likewise.
+ * vmsdbgout.c: Likewise.
+ * treelang/treelang.texi: Likewise.
+ * treelang/treetree.c: Likewise.
+
+2002-09-27 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/h8300.c (compute_saved_regs): Use a macro
+ instead of a hard register number.
+ (get_shift_alg): Use an enumerated type instead of numbers.
+ (h8300_shift_needs_scratch_p): Likewise.
+
+2002-09-26 David S. Miller <davem@redhat.com>
+
+ PR optimization/7335
+ * calls.c (emit_library_call_value_1): Passing args by reference
+ converts a CONST function into a PURE one.
+
+2002-09-26 David Edelsohn <edelsohn@gnu.org>
+
+ * dbxout.c (FORCE_TEXT): Switch to current_function_decl, not
+ text_section.
+ * xcoffout.h (DBX_STATIC_BLOCK_START): Remove explicit change to
+ text section.
+ * config/rs6000/rs6000.c (rs6000_override_options): Allow
+ function-sections and data-sections functionality on AIX.
- * toplev.c (lang_independent_init): Round up identifier size.
+2002-09-26 David Edelsohn <edelsohn@gnu.org>
+ Dale Johannesen <dalej@apple.com>
-2002-01-28 Richard Earnshaw <rearnsha@arm.com>
+ * config/rs6000/rs6000.c (rs6000_emit_move): Insert zero-extend
+ in RTL for sub-word loads from memory.
- * config.gcc: Revert previous change.
+2002-09-26 Richard Henderson <rth@redhat.com>
-2002-01-28 Andris Pavenis <pavenis@latnet.lv>
+ PR c/7160
+ * sched-deps.c (sched_analyze_insn): Make clobber insns depend
+ on call insns.
- * config/i386/djgpp.h: Use STRIP_NAME_ENCODING in macro UNIQUE_SECTION
+2002-09-26 Richard Henderson <rth@redhat.com>
-2002-01-28 Richard Earnshaw <rearnsha@arm.com>
+ * emit-rtl.c (const_double_htab_eq): Remove unused variable.
- * config.gcc (*-*-netbsdelf*): Set up generic parameters.
- (*-*-netbsd*): Always use collect2. Remove collect2 settings from
- other non-elf netbsd config frags.
- * config/netbsd-aout.h (STARTFILE_SPEC): Don't pull in c++rt0 since
- collect2 will does that.
- * config/netbsd.h (LIBGCC_SPEC): Add white space before -lgcc, so that
- shared-lib frobbing will work.
+2002-09-26 Chris Lattner <sabre@nondot.org>
-2002-01-28 Kazu Hirata <kazu@hxi.com>
+ * ssa.c (rename_insn_1): Handle RENAME_NO_RTX correctly when
+ handling undefined values.
- * config/h8300/h8300.h: Fix formatting.
+2002-09-26 Richard Henderson <rth@redhat.com>
+
+ PR opt/7520
+ * emit-rtl.c (active_insn_p): Consider a clobber of the
+ function return value to be active even after reload.
+
+2002-09-27 Alan Modra <amodra@bigpond.net.au>
+
+ * doloop.c (doloop_modify_runtime <biv skips initial incr>): Adjust
+ by absolute loop increment, not loop increment.
+
+2002-09-26 Kazu Hirata <kazu@cs.umass.edu>
+
+ * c-common.h: Follow spelling conventions.
+ * cpplex.c: Likewise.
+ * cpplib.h: Likewise.
+ * gthr-dce.h: Likewise.
+ * gthr-posix.h: Likewise.
+ * optabs.c: Likewise.
+ * output.h: Likewise.
+ * profile.c: Likewise.
+ * protoize.c: Likewise.
+ * ra-rewrite.c: Likewise.
+ * real.c: Likewise.
+ * recog.c: Likewise.
+ * reg-stack.c: Likewise.
+ * regclass.c: Likewise.
+ * regmove.c: Likewise.
+ * reload.c: Likewise.
+ * reload.h: Likewise.
+ * reload1.c: Likewise.
+ * reorg.c: Likewise.
+ * resource.c: Likewise.
+ * rtl.h: Likewise.
+ * rtlanal.c: Likewise.
+
+2002-09-26 Steve Ellcey <sje@cup.hp.com>
+
+ * config/ia64/ia64.c (ia64_expand_load_address): Ensure correct mode
+ for symbol address.
+
+2002-09-24 Eric Christopher <echristo@redhat.com>
+
+ * config/mips/elf.h: Add HANDLE_SYSV_PRAGMA.
+ * config/mips/elf64.h: Ditto.
+
+2002-09-24 Eric Christopher <echristo@redhat.com>
+
+ * except.c (expand_builtin_extract_return_address): Handle case
+ where Pmode != ptr_mode.
+
+2002-09-26 Steve Ellcey <sje@cup.hp.com>
+
+ * config/ia64/hpux.h (ASM_OUTPUT_EXTERNAL_LIBCALL): New
+
+2002-09-26 Steve Ellcey <sje@cup.hp.com>
+
+ * config/ia64/hpux.h (TARGET_DEFAULT): Include TARGET_ILP32.
+
+2002-09-26 Igor Shevlyakov <igor@microunity.com>
+
+ * combine.c (simplify_set): Don't call to force_to_mode if size
+ of integer type is larger than HOST_BITS_PER_WIDE_INT.
+
+2002-09-26 Janis Johnson <janis187@us.ibm.com>
+
+ * Makefile.in (qmtest-g++): Fix file path.
+
+2002-09-26 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * expr.c (expand_expr) [MINUS_EXPR]: Convert A - const to
+ A + (-const) on RTX level, even for unsigned types.
+
+2002-09-26 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * reload.c (dup_replacements): New function.
+ (find_reloads): Use it to duplicate replacements at the top level
+ of match_dup operands.
+
+2002-09-26 Miles Bader <miles@gnu.org>
+
+ * v850.md ("length"): Change default value to 4.
+
+2002-09-26 Kazu Hirata <kazu@cs.umass.edu>
+
+ * ChangeLog.1: Follow spelling conventions.
+ * ChangeLog.4: Likewise.
+ * ChangeLog.6: Likewise.
+ * FSFChangeLog.11: Likewise.
+ * doc/cpp.texi: Likewise.
+ * doc/invoke.texi: Likewise.
+ * doc/tm.texi: Likewise.
+
+2002-09-26 Nick Clifton <nickc@redhat.com>
+
+ * config.gcc: Add x prefix to v850e case for handling
+ --with-cpu=v850e.
+
+2002-09-25 David S. Miller <davem@redhat.com>
+
+ PR target/7842
+ * config/sparc/sparc.c (set_extends): SImode ASHIFT does not
+ extend.
+
+2002-09-25 Richard Henderson <rth@redhat.com>
+
+ * emit-rtl.c (const_double_htab_eq): Distinguish integer and
+ fp CONST_DOUBLE; use real_identical.
+
+2002-09-25 Mark Mitchell <mark@codesourcery.com>
+
+ * doc/invoke.texi: Add more -Wabi examples.
+
+2002-09-25 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips.h (TARGET_MIPS4100): Add missing bracket.
+
+2002-09-24 Denis Chertykov <denisc@overta.ru>
+
+ * config/ip2k/ip2k.c (function_epilogue): Fix wrong numbers in
+ cases of optimizing "add sp,w" to "inc sp".
+
+2002-09-24 Adam Nemet <anemet@lnxw.com>
+
+ * config/arm/arm.c (thumb_unexpanded_epilogue): Don't generate
+ epilogue for naked functions.
+
+2002-09-24 Adam Nemet <anemet@lnxw.com>
+ Nick Clifton <nickc@redhat.com>
+
+ * config/arm/arm.h (THUMB_FUNCTION_PROFILER): Remove.
+ (FUNCTION_PROFILER): Only invoke THUMB_FUNCTION_PROFILER if it
+ is defined.
+
+2002-09-24 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.c (preferred_la_operand_p): New function.
+ * config/s390/s390-protos.h (preferred_la_operand_p): Declare it.
+ * config/s390/s390.md ("addaddr_esame", "*la_ccclobber"): Replace by ...
+ ("*la_64_cc", "*la_31_cc", splitters): ... these.
+ ("*la_31"): Deactivate for TARGET_64BIT.
+ ("*la_31_and", "*la_31_and_cc"): New.
+
+2002-09-24 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * real.h (real_value): Make `exp' explicitly signed.
+
+2002-09-24 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/elfos.h: Follow spelling conventions.
+ * config/alpha/alpha.h: Likewise.
+ * config/arc/arc.h: Likewise.
+ * config/arm/arm.md: Likewise.
+ * config/avr/avr.h: Likewise.
+ * config/cris/cris.md: Likewise.
+ * config/d30v/d30v.h: Likewise.
+ * config/frv/frv.c: Likewise.
+ * config/frv/frv.h: Likewise.
+ * config/h8300/h8300.c: Likewise.
+ * config/h8300/h8300.h: Likewise.
* config/h8300/h8300.md: Likewise.
+ * config/i386/cygwin.h: Likewise.
+ * config/i386/i386.h: Likewise.
+ * config/i386/sysv3.h: Likewise.
+ * config/i960/i960.h: Likewise.
+ * config/ia64/ia64.h: Likewise.
+ * config/ia64/ia64.md: Likewise.
+ * config/ip2k/ip2k.h: Likewise.
+ * config/m32r/m32r.h: Likewise.
+ * config/m68k/m68k.h: Likewise.
+ * config/m88k/m88k.h: Likewise.
+ * config/mcore/mcore.c: Likewise.
+ * config/mcore/mcore.h: Likewise.
+ * config/mcore/mcore.md: Likewise.
+ * config/mips/mips.h: Likewise.
+ * config/mmix/mmix.h: Likewise.
+ * config/mmix/mmix.md: Likewise.
+ * config/ns32k/netbsd.h: Likewise.
+ * config/ns32k/ns32k.h: Likewise.
+ * config/ns32k/ns32k.md: Likewise.
+ * config/pa/pa.h: Likewise.
+ * config/romp/romp.h: Likewise.
+ * config/rs6000/rs6000.h: Likewise.
+ * config/rs6000/rs6000.md: Likewise.
+ * config/sparc/sparc.h: Likewise.
+ * config/stormy16/stormy-abi: Likewise.
+ * config/stormy16/stormy16.h: Likewise.
+ * config/vax/vax.h: Likewise.
+
+2002-09-23 Zack Weinberg <zack@codesourcery.com>
+
+ * version.c (version_string): Now const char[].
+ * version.h: Update to match.
+
+2002-09-23 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.h (MASK_ACCUMULATE_OUTGOING_ARGS_SET, MASK_MMX_SET,
+ MASK_SSE_SET, MASK_SSE2_SET, MASK_3DNOW_SET, MASK_3DNOW_A_SET): Kill.
+ (TARGET_SWITCHES): Don't reference them.
+ * config/i386/i386.c (override_options): Use target_flags_explicit
+ to examine bits set by the user.
+
+2002-09-23 Dale Johannesen <dalej@apple.com>
+
+ * dbxout.c (dbxout_parms): Set current_sym_code for params
+ passed on stack by invisible reference.
+
+2002-09-23 Richard Earnshaw <rearnsha@arm.com>
+
+ * arm/unknown-elf.h (ASM_OUTPUT_ALIGNED_DECL_LOCAL): Always allocate
+ at least one byte of space.
+
+2002-09-23 Mark Mitchell <mark@codesourcery.com>
+
+ * c-common.h (flag_abi_version): Fix typo in comment.
+ * doc/invoke.texi (flag_abi_version): Document default value.
+
+2002-09-23 Hans-Peter Nilsson <hp@axis.com>
+
+ * doc/extend.texi (Extended Asm): Clarify that overlap between
+ asm-declared register variables used in an asm and the asm clobber
+ list is not allowed.
+ * stmt.c (decl_conflicts_with_clobbers_p): New function.
+ (expand_asm_operands): Keep track of clobbered registers. Call
+ decl_conflicts_with_clobbers_p for each input and output operand.
+ If no conflicts found before, also do conflict sanity check when
+ emitting clobbers.
+
+2002-09-23 Richard Henderson <rth@redhat.com>
+
+ * c-common.c (cpp_define_data_format): Remove.
+ (cb_register_builtins): Don't define __WCHAR_BIT__, __SHRT_BIT__,
+ __INT_BIT__, __LONG_BIT__, __LONG_LONG_BIT__, __FLOAT_BIT__,
+ __DOUBLE_BIT__, __LONG_DOUBLE_BIT__.
+ * doc/cpp.texi: Don't document them either.
+ (__SCHAR_MAX__, __SHRT_MAX__, __INT_MAX__, __LONG_MAX__,
+ __LONG_LONG_MAX__): Document.
+ (__TARGET_FLOAT_FORMAT__): Remove.
+
+2002-09-23 Richard Henderson <rth@redhat.com>
+
+ * real.c (do_multiply): Normalize U before addition.
+
+2002-09-23 Mark Mitchell <mark@codesourcery.com>
+
+ * c-common.c (flag_abi_version): New variable.
+ * c-common.h (flag_abi_version): Declare it.
+ * c-opts.c (missing_arg): Add -fabi-version.
+ (c_common_decode_option): Process -fabi-version.
+ * doc/invoke.texi (-fabi-version): Document it.
+ (-Wabi): Add information about bit-fields in unions.
+
+2002-09-22 Jason Thorpe <thorpej@wasabisystems.com>
-2002-01-28 Loren J. Rittle <ljrittle@acm.org>
+ * config/mips/netbsd.h (SUBTARGET_ASM_SPEC): Always pass -KPIC
+ unless -fno-pic or -fno-PIC is specified.
- * fixinc/inclhack.def (strict_ansi_not): Add a bypass based on
- the old, removed AAA_standards fix.
- * fixinc/fixincl.x: Rebuilt.
+2002-09-22 John David Anglin <dave@hiauly1.hia.nrc.ca>
-2002-01-28 Hans-Peter Nilsson <hp@axis.com>
-
- * config/cris/cris.h (CRT_CALL_STATIC_FUNCTION): Change to emit
- atexit call in crtbegin, hooked in after call to frame_dummy;
- register EH before registering __fini__start.
+ * c-common.c (preprocessing_trad_p): Define.
+ * pa-hiux.h, pa-hpux.h, pa-hpux7.h (CPP_PREDEFINES): Delete.
+ (TARGET_OS_CPP_BUILTINS, SUBTARGET_SWITCHES): Define.
+ * pa-hpux10.h (TARGET_OS_CPP_BUILTINS, CPP_SPEC): Define.
+ * pa-hpux11.h (TARGET_OS_CPP_BUILTINS): Define.
+ * pa-linux.h (CPP_PREDEFINES): Delete.
+ (TARGET_OS_CPP_BUILTINS, CPP_SPEC): Define.
+ * pa32-linux.h, pa64-linux.h (CPP_SPEC): Delete.
+ * pa-osf.h, pa-pro-end.h, rtems.h (CPP_PREDEFINES): Delete.
+ (TARGET_OS_CPP_BUILTINS): Define.
+ * pa.h (MASK_SIO, TARGET_SIO, TARGET_PA_10): Define.
+ (TARGET_SWITCHES): Reformat. Use N_() macro. Add SUBTARGET_SWITCHES.
+ (SUBTARGET_SWITCHES): Provide default definition.
+ (TARGET_OPTIONS): Reformat. Use N_() macro.
+ (CPP_PA10_SPEC, CPP_PA11_SPEC, CPP_PA20_SPEC, CPP_64BIT_SPEC,
+ CPP_CPU_DEFAULT_SPEC, CPP_64BIT_DEFAULT_SPEC, SUBTARGET_EXTRA_SPECS,
+ EXTRA_SPECS, CPP_SPEC, CPLUSPLUS_CPP_SPEC, CPP_PREDEFINES): Delete.
+ (TARGET_CPU_CPP_BUILTINS): Define.
+ (TARGET_OS_CPP_BUILTINS): Define for BSD-like systems.
+ * doc/invoke.texi (msio, mwsio): Document new hppa options.
+ * doc/tm.texi (TARGET_CPU_CPP_BUILTINS): Document macro
+ preprocessing_trad_p().
-2002-01-28 Aldy Hernandez <aldyh@redhat.com>
+2002-09-22 Jason Thorpe <thorpej@wasabisystems.com>
- * config/rs6000/altivec.h: Remove spurious semicolons.
+ * doc/install.texi: Document behavior of --with-headers and
+ --with-libs when arguments are omitted.
-2002-01-27 Kazu Hirata <kazu@hxi.com>
+2002-09-22 Kazu Hirata <kazu@cs.umass.edu>
- * config/h8300/h8300.md: Replace dead bit extraction patterns
- with ones that work.
+ * dbxout.c: Follow spelling conventions.
+ * defaults.h: Likewise.
+ * df.c: Likewise.
+ * diagnostic.h: Likewise.
+ * doloop.c: Likewise.
+ * dwarf2out.c: Likewise.
+ * dwarfout.c: Likewise.
+ * emit-rtl.c: Likewise.
+ * except.c: Likewise.
+ * explow.c: Likewise.
+ * expmed.c: Likewise.
+ * expr.c: Likewise.
+ * expr.h: Likewise.
+ * flags.h: Likewise.
+ * flow.c: Likewise.
+ * fold-const.c: Likewise.
+ * function.c: Likewise.
+ * function.h: Likewise.
+ * gcc.c: Likewise.
+ * gcov-io.h: Likewise.
+ * gcov.c: Likewise.
+ * gcse.c: Likewise.
+ * genattrtab.c: Likewise.
+ * genconfig.c: Likewise.
+ * genrecog.c: Likewise.
+ * ggc-page.c: Likewise.
+ * ggc.h: Likewise.
+ * global.c: Likewise.
+ * gthr-win32.h: Likewise.
+ * integrate.c: Likewise.
+ * jump.c: Likewise.
+ * langhooks.c: Likewise.
+ * langhooks.h: Likewise.
+ * line-map.h: Likewise.
+ * local-alloc.c: Likewise.
+ * longlong.h: Likewise.
+ * loop.c: Likewise.
+ * loop.h: Likewise.
+
+2002-08-27 Jan Hubicka <jh@suse.cz>
+
+ * i386.h (BIGGEST_FIELD_ALIGNMENT): Set proper default for x86_64.
+
+2002-08-27 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (overwrite_options): Set -mpreferred-stack-boundary to 128
+ for -Os/TARGET_64BIT too.
+
+2002-09-21 Kazu Hirata <kazu@cs.umass.edu>
+
+ * ChangeLog: Follow spelling conventions.
+ * ChangeLog.0: Likewise.
+ * ChangeLog.1: Likewise.
+ * ChangeLog.2: Likewise.
+ * ChangeLog.3: Likewise.
+ * ChangeLog.4: Likewise.
+ * ChangeLog.5: Likewise.
+ * ChangeLog.6: Likewise.
+ * FSFChangeLog.10: Likewise.
+ * FSFChangeLog.11: Likewise.
+ * alias.c: Likewise.
+ * basic-block.h: Likewise.
+ * c-aux-info.c: Likewise.
+ * c-common.c: Likewise.
+ * c-common.h: Likewise.
+ * c-decl.c: Likewise.
+ * c-format.c: Likewise.
+ * c-semantics.c: Likewise.
+ * c-typeck.c: Likewise.
+ * calls.c: Likewise.
+ * cfganal.c: Likewise.
+ * cfgloop.c: Likewise.
+ * collect2.c: Likewise.
+ * combine.c: Likewise.
+ * conflict.c: Likewise.
+ * cppexp.c: Likewise.
+ * cppfiles.c: Likewise.
+ * cpphash.h: Likewise.
+ * cppinit.c: Likewise.
+ * cpplex.c: Likewise.
+ * cpplib.c: Likewise.
+ * cpplib.h: Likewise.
+ * cppmacro.c: Likewise.
+ * cse.c: Likewise.
+
+2002-09-21 Richard Earnshaw <rearnsha@arm.com>
+
+ * netbsd-aout.h (NETBSD_LINK_SPEC_AOUT): New, takes old definition of
+ LINK_SPEC.
+ (LINK_SPEC): Define to NETBSD_LINK_SPEC_AOUT.
+ * arm/netbsd.h (SUBTARGET_EXTRA_SEPCS): Add NETBSD_LINK_SPEC_AOUT.
+ (LINK_SPEC): Rework to use NETBSD_LINK_SPEC_AOUT).
+
+2002-09-21 Richard Earnshaw <rearnsha@arm.com>
+
+ PR opt/7930
+ * cse.c (fold_rtx): Calculate old_cost before we fold each
+ operand.
+
+2002-09-21 Richard Henderson <rth@redhat.com>
+
+ * c-common.c (cpp_define_data_format): Remove __GCC_LITTLE_ENDIAN__,
+ __GCC_BIG_ENDIAN__, __TARGET_BITS_ORDER__, __TARGET_BYTES_ORDER__,
+ __TARGET_INT_WORDS_ORDER__, __TARGET_FLOAT_WORDS_ORDER__,
+ __TARGET_USES_VAX_F_FLOAT__, __TARGET_USES_VAX_D_FLOAT__,
+ __TARGET_USES_VAX_G_FLOAT__, __TARGET_USES_VAX_H_FLOAT__.
+ * doc/cpp.texi: Don't document them.
+
+2002-09-21 Richard Henderson <rth@redhat.com>
+
+ * c-common.c (builtin_define_float_constants): Use real_format
+ to get the floating-point parameters.
+
+2002-09-21 Richard Henderson <rth@redhat.com>
+
+ * real.c (struct real_format): Move to real.h.
+ (real_format_for_mode): Rename from fmt_for_mode; update all users;
+ initialize with ieee defaults.
+ (real_to_target_fmt, real_from_target_fmt): New.
+ (ieee_single_format, ieee_double_format, ieee_extended_motorola_format,
+ ieee_extended_intel_96_format, ieee_extended_intel_128_format,
+ ieee_quad_format, i370_single_format, i370_double_format,
+ c4x_single_format, c4x_extended_format): Rename from s/_format//.
+ (ieee_quad_format): Fix emin.
+ (format_for_size, init_real_once): Remove.
+ * real.h (struct real_format): Move from real.c.
+ (real_format_for_mode): Declare.
+ (real_to_target_fmt, real_from_target_fmt): Declare.
+ (ieee_single_format, ieee_double_format, ieee_extended_motorola_format,
+ ieee_extended_intel_96_format, ieee_extended_intel_128_format,
+ ieee_quad_format, vax_f_format, vax_d_format, vax_g_format,
+ i370_single_format, i370_double_format, c4x_single_format,
+ c4x_extended_format): Declare.
+ * toplev.c (do_compile): Don't call init_real_once.
+
+ * defaults.h (INTEL_EXTENDED_IEEE_FORMAT): Remove.
+ * doc/tm.texi (INTEL_EXTENDED_IEEE_FORMAT): Remove.
+
+ * config/alpha/alpha.h (TARGET_FLOAT_FORMAT): Define.
+ * config/alpha/osf5.h (LONG_DOUBLE_TYPE_SIZE): 64, if vax mode.
+ * config/alpha/alpha.c (override_options): Set real_format_for_mode
+ for VAX, if enabled.
+
+ * config/c4x/c4x.c (c4x_override_options): Set real_format_for_mode
+ for C4X.
+
+ * config/i370/i370.h (OVERRIDE_OPTIONS): New.
+ * config/i370/i370.c (override_options): New.
+ * config/i370/i370-protos.h: Update.
+
+ * config/i386/i386.c (override_options): Set real_format_for_mode
+ for Intel 80-bit extended.
+ * config/i386/i386.h (INTEL_EXTENDED_IEEE_FORMAT): Remove.
+
+ * config/i960/i960.h (LONG_DOUBLE_TYPE_SIZE): Mind -mlong-double-64.
+ (OVERRIDE_OPTIONS): Move code...
+ * config/i960/i960.c (i960_initialize): ... here. Set
+ real_format_for_mode for Intel 80-bit extended.
+
+ * config/ia64/ia64.c (ia64_override_options): Set real_format_for_mode
+ for Intel 80-bit extended, if enabled.
+
+ * config/m68k/m68k.c (override_options): Set real_format_for_mode
+ for Motorola 96-bit extended.
+
+ * config/vax/vax.h (OVERRIDE_OPTIONS): New.
+ * config/vax/vax.c (override_options): New.
+ * config/vax/vax-protos.h: Update.
+
+2002-09-21 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.md (builtin_setjmp_receiver): Add
+ #if TARGET_MACHO.
+
+ * config/rs6000/rs6000.md (floatdisf2_internal2): Combine
+ insns. Supply missing clobber of scratch reg.
+
+2002-09-20 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/m32r/m32r.c: Follow spelling conventions.
+ * config/m32r/m32r.h: Likewise.
+ * config/m32r/m32r.md: Likewise.
+ * config/m68k/m68k.c: Likewise.
+ * config/m88k/m88k.c: Likewise.
+ * config/mcore/mcore.c: Likewise.
+ * config/mips/mips.c: Likewise.
+ * config/mips/mips.h: Likewise.
+ * config/mmix/mmix.c: Likewise.
+ * config/mn10200/mn10200.c: Likewise.
+ * config/ns32k/ns32k.h: Likewise.
+ * config/pa/pa.c: Likewise.
+ * config/pa/pa64-linux.h: Likewise.
+ * config/pdp11/pdp11.h: Likewise.
+ * config/romp/romp.c: Likewise.
+ * config/romp/romp.h: Likewise.
+ * config/rs6000/eabi.asm: Likewise.
+ * config/rs6000/linux64.h: Likewise.
+ * config/rs6000/rs6000.c: Likewise.
+ * config/rs6000/rs6000.h: Likewise.
+ * config/rs6000/rs6000.md: Likewise.
+ * config/rs6000/sysv4.h: Likewise.
+ * config/rs6000/xcoff.h: Likewise.
-Sun Jan 27 13:23:40 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2002-09-20 Jim Wilson <wilson@redhat.com>
- * emit-rtl.c (get_mem_attrs): Don't default alignment for non-BLKmode
- if not STRICT_ALIGNMENT.
- * rtl.h (MEM_ALIGN): Likewise.
+ * config/v850/v850/lib1funcs.asm (__muldi3): Change r5 to r28.
-2002-01-27 Craig Rodrigues <rodrigc@gcc.gnu.org>
+2002-09-20 Jakub Jelinek <jakub@redhat.com>
- * doc/invoke.texi (-fdump-translation-unit): Revert this
- patch: 2001-10-21 Craig Rodrigues <rodrigc@gcc.gnu.org>
+ * config/i386/i386.md (UNSPEC_GOTNTPOFF, UNSPEC_INDNTPOFF): New.
+ * config/i386/i386.c (legitimate_pic_address_disp_p): Handle
+ UNSPEC_GOTNTPOFF and UNSPEC_INDNTPOFF like UNSPEC_GOTTPOFF.
+ (legitimate_address_p): Likewise.
+ (legitimize_address): Use @gotntpoff and @indntpoff.
+ (output_pic_addr_const): Handle UNSPEC_GOTNTPOFF and UNSPEC_INDNTPOFF.
+ (output_addr_const_extra): Likewise.
-2002-01-27 Kazu Hirata <kazu@hxi.com>
+2002-09-20 Jim Wilson <wilson@redhat.com>
- * config/h8300/h8300.md (define_constants): New.
- (anonymous patterns) Use defined constants appropriately.
+ * combine.c (try_combine): When split an instruction pair, where the
+ first has a sign_extend src, verify that the src and dest modes match.
-2002-01-27 Kazu Hirata <kazu@hxi.com>
+2002-09-20 Richard Henderson <rth@redhat.com>
- * config/h8300/h8300.c (function_arg): Remove redundant code.
+ * config/mips/mips.c (dfhigh, dflow, sfhigh, sflow): Remove.
+ (override_options): Do not initialize them.
+ (mips_const_double_ok): Allow no fp constants except zero,
+ and not even that for mips16.
+ (const_float_1_operand): Use dconst1.
+ * config/mips/mips.md (movsf, movsf_internal1, movsf_internal2,
+ movdf, movdf_internal1, movdf_internal1a, movdf_internal2):
+ Don't allow arbitrary constants; fix predicates and C constraint.
-2002-01-26 Richard Henderson <rth@redhat.com>
+2002-09-20 Neil Booth <neil@daikokuya.co.uk>
- * sched-deps.c (reg_pending_uses_head): New.
- (reg_pending_barrier): Rename from reg_pending_sets_all.
- (find_insn_list): Don't mark inline.
- (find_insn_mem_list): Remove.
- (add_dependence_list, add_dependence_list_and_free): New.
- (flush_pending_lists): Replace only_write param with separate
- for_read and for_write parameters. Update all callers. Use
- add_dependence_list_and_free.
- (sched_analyze_1): Do not add reg dependencies here; just set
- the pending bits. Use add_dependence_list.
- (sched_analyze_2): Likewise.
- (sched_analyze_insn): Replace schedule_barrier_found with
- reg_pending_barrier. Add all dependencies for pending reg
- uses, sets, and clobbers.
- (sched_analyze): Don't add reg dependencies for calls, just
- set pending bits. Use regs_invalidated_by_call. Treat
- sched_before_next_call as a normal list, not a fake insn.
- (init_deps): No funny init for sched_before_next_call.
- (free_deps): Free pending mems lists. Don't zero reg_last.
- (init_deps_global): Init reg_pending_uses.
- (finish_deps_global): Free it.
- * sched-int.h (deps): Make in_post_call_group_p boolean. Update docs.
- (find_insn_mem_list): Remove.
- * sched-rgn.c (concat_INSN_LIST, concat_insn_mem_list): New.
- (propagate_deps): Use them. Zero temp mem lists.
+ * cppmacro.c: Don't warn about function-like macros without
+ '(' during pre-expansion.
-2002-01-26 Richard Henderson <rth@redhat.com>
+2002-09-20 Jim Wilson <wilson@redhat.com>
- * Makefile.in (CRTSTUFF_CFLAGS): New.
- (crtbegin.o, crtend.o, crtbeginS.o, crtendS.o, crtbeginT.o): Use it.
- * config.gcc (alpha-linux, alpha-freebsd, alpha-netbsd): Use plain
- crtstuff.c instead of alpha assembly version.
- * crtstuff.c (CRT_CALL_STATIC_FUNCTION): Rewrite to assume the
- entire dummy function sequence. Use FORCE_CODE_SECTION_ALIGN
- not FORCE_{INIT,FINI}_SECTION_ALIGN.
- (__do_global_dtors_aux): Mark used.
- (frame_dummy, __do_global_ctors_aux): Mark used.
- (fini_dummy, init_dummy): Remove.
+ * config/v850/v850.c (current_function_anonymous_args): Delete.
+ (expand_prologue): Use current_function_args_info.anonymous_args.
+ (expand_epilogue): Delete use of current_function_anonymous_args.
+ * config/v850/v850.h (struct cum_arg): Add anonymous_args field.
+ (INIT_CUMULATIVE_ARGS): Clear anonymous_args field.
+ (current_function_anonymous_args): Delete extern declaration.
+ (SETUP_INCOMING_VARARGS): Set anonymous_args field.
- * config/alpha/crtbegin.asm: Remove file.
- * config/alpha/crtend.asm: Remove file.
- * config/alpha/t-crtbe: Remove file.
- * config/alpha/elf.h (CRT_CALL_STATIC_FUNCTION): New.
- (LINK_EH_SPEC): New.
+2002-09-20 Geoffrey Keating <geoffk@apple.com>
- * config/cris/cris.h (CRT_CALL_STATIC_FUNCTION): Rewrite old
- FORCE_INIT_SECTION_ALIGN hack. Register __fini_start before
- calling constructors.
- * config/cris/linux.h (CRT_CALL_STATIC_FUNCTION): Undef.
+ * config/rs6000/rs6000.c (rs6000_emit_prologue): Update for change
+ to load_macho_picbase.
+ * config/rs6000/rs6000.md: Document Darwin-specific unspec IDs.
+ (load_macho_picbase): Take the symbol to use as a parameter.
+ (macho_correct_pic): New insn.
+ (builtin_setjmp_reciever): On Darwin, restore the PIC register.
- * config/i386/i386.h (CRT_CALL_STATIC_FUNCTION): New.
- * config/i386/linux.h (CRT_CALL_STATIC_FUNCTION): Replace old
- CRT_END_INIT_DUMMY hack.
- * config/i386/sol2.h (FORCE_CODE_SECTION_ALIGN): Replace
- FORCE_{INIT,FINI}_SECTION_ALIGN.
+ * config/rs6000/rs6000.h (ELIMINABLE_REGS): Use
+ RS6000_PIC_OFFSET_TABLE_REGNUM rather than hardcoding 30.
+ (CAN_ELIMINATE): Likewise.
+ (INITIAL_ELIMINATION_OFFSET): Likewise.
+ (TOC_REGISTER): Likewise.
+
+2002-09-20 Richard Henderson <rth@redhat.com>
+
+ * real.c (real_hash): New.
+ * real.h: Declare it.
+ * cse.c (canon_hash): Use it.
+ * cselib.c (hash_rtx): Likewise.
+ * emit-rtl.c (const_double_htab_hash): Likewise.
+ * rtl.h (CONST_DOUBLE_REAL_VALUE): New.
+ * varasm.c (struct rtx_const): Reduce vector size; separate
+ integer and fp vectors.
+ (HASHBITS): Remove.
+ (const_hash_1): Rename from const_hash. Use real_hash. Do not
+ take modulus MAX_HASH_TABLE.
+ (const_hash): New. Do take modulus MAX_HASH_TABLE.
+ (output_constant_def): Do not take modulus MAX_HASH_TABLE.
+ (SYMHASH): Don't use HASHBITS.
+ (decode_rtx_const): Copy only active bits from REAL_VALUE_TYPE.
+ Fix CONST_VECTOR thinko wrt fp vectors. Fix kind comparison.
+ (simplify_subtraction): Fix kind comparison.
+ (const_hash_rtx): Return unsigned int. Don't use HASHBITS.
+ Use a union to pun integer array.
+ * config/rs6000/rs6000.c (rs6000_hash_constant): Use real_hash;
+ only hash two words of integral CONST_DOUBLE.
+
+2002-09-20 Steve Ellcey <sje@cup.hp.com>
+
+ * config/ia64/hpux.h (STARTFILE_SPEC): Modify.
+ (STARTFILE_PREFIX_SPEC): New.
+ (LINK_SPEC): Modify.
+ (LIB_SPEC): Modify.
+ (LIBGCC_SPEC): New.
+
+2002-09-20 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (legitimate_pic_address_disp_p): Allow
+ UNSPEC_NTPOFF and UNSPEC_DTPOFF to be offsetted by constant.
- * config/mcore/mcore-elf.h (FORCE_CODE_SECTION_ALIGN): Replace
- FORCE_{INIT,FINI}_SECTION_ALIGN.
+2002-09-20 Jeroen Dobbelaere <jeroen.dobbelaere@acunia.com>
- * config/s390/s390.h (CRT_CALL_STATIC_FUNCTION): Update for new
- invocation sequence.
- * config/sh/sh.h (CRT_CALL_STATIC_FUNCTION): Likewise.
+ * config/arm/arm.md (sign_extract_onebit, not_signextract_onebit):
+ Add clobber of the condition code register.
- * doc/tm.texi (CRT_CALL_STATIC_FUNCTION): Update.
- (FORCE_CODE_SECTION_ALIGN): New.
+2002-09-20 Richard Henderson <rth@redhat.com>
+
+ * real.c (do_fix_trunc): Static.
+ (encode_ieee_single, encode_ieee_double, encode_ieee_extended,
+ encode_ieee_quad, encode_vax_f, encode_vax_d, encode_vax_g,
+ encode_i370_single, encode_i370_double, encode_c4x_single,
+ encode_c4x_extended): Add default abort case.
+
+2002-09-20 Richard Henderson <rth@redhat.com>
+
+ * real.h (enum real_value_class, SIGNIFICAND_BITS, EXP_BITS,
+ MAX_EXP, SIGSZ, SIG_MSB, struct real_value): Move from real.c.
+ (struct realvaluetype): Remove.
+ (REAL_VALUE_TYPE): Use struct real_value.
+ (REAL_VALUE_TYPE_SIZE): Use SIGNIFICAND_BITS.
+ (test_real_width): New.
+ * real.c: Global replace struct real_value with REAL_VALUE_TYPE.
+ (real_arithmetic): Avoid hoops for REAL_VALUE_TYPE parameters.
+ (real_compare, real_exponent, real_ldexp, real_isinf, real_isnan,
+ real_isneg, real_isnegzero, real_identical, exact_real_inverse,
+ real_to_integer, real_to_integer2, real_to_decimal,
+ real_to_hexadecimal, real_from_string, real_from_integer,
+ real_inf, real_nan, real_2expN, real_convert, real_to_target,
+ real_from_target): Likewise.
+ * tree.h (struct tree_real_cst): Use real_value not realvaluetype.
+ * gengtype-yacc.y (bitfieldopt): Accept an ID as well.
+
+2002-09-20 Richard Henderson <rth@redhat.com>
+
+ * real.h (UNKNOWN_FLOAT_FORMAT, IEEE_FLOAT_FORMAT, VAX_FLOAT_FORMAT,
+ IBM_FLOAT_FORMAT, C4X_FLOAT_FORMAT, TARGET_FLOAT_FORMAT): Move ...
+ * defaults.h: ... here.
+ * config/arm/arm.h, config/avr/avr.h, config/d30v/d30v.h,
+ config/fr30/fr30.h, config/frv/frv.h, config/ia64/ia64.h,
+ config/ip2k/ip2k.h, config/mips/mips.h, config/stormy16/stormy16.h,
+ config/xtensa/xtensa.h (TARGET_FLOAT_FORMAT): Remove.
+
+2002-09-20 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.md ("negdf2"): Rewrite.
+ ("*expanded_negdf2"): New.
+
+2002-09-19 Jim Wilson <wilson@redhat.com>
+
+ * combine.c (simplify_set): When optimizing a subreg src with a
+ cc0 dest, use GET_MODE (src) for mask instead of inner_mode.
+
+2002-09-19 Dale Johannesen <dalej@apple.com>
+ * combine.c (make_extraction): Don't create
+ invalid subreg.
-2002-01-26 Richard Henderson <rth@redhat.com>
+2002-09-19 Ulrich Weigand <uweigand@de.ibm.com>
- * config/cris/cris.c (cris_print_operand): Handle 64-bit CONST_INT.
+ * config/s390/s390.c (addr_generation_dependency_p): Handle SUBREG
+ and STRICT_LOW_PART within SET_DEST.
+ * config/s390/s390.md ("*extractqi", "*extracthi"): New insns with
+ splitters, replacing pre-reload splitters.
+ ("*zero_extendhisi2_31", "*zero_extendqisi2_31",
+ "*zero_extendqihi2_31"): New insns.
+ ("*zero_extendqihi2_64"): Do not clobber CC.
-2002-01-26 Richard Henderson <rth@redhat.com>
+2002-09-19 Steve Ellcey <sje@cup.hp.com>
- * config/alpha/alpha.c (alpha_sa_mask): Mark RA for unicos here too.
- (alpha_sa_size): Use alpha_sa_mask to compute size of saved regs.
+ * config/ia64/hpux.h (CTORS_SECTION_ASM_OP): New.
+ (DTORS_SECTION_ASM_OP): Ditto.
+ (READONLY_DATA_SECTION_ASM_OP): Moved.
+ (DATA_SECTION_ASM_OP): New.
+ (SDATA_SECTION_ASM_OP): New.
+ (BSS_SECTION_ASM_OP): New.
+ (SBSS_SECTION_ASM_OP): New.
+ (TEXT_SECTION_ASM_OP): New.
-2002-01-26 Kazu Hirata <kazu@hxi.com>
+2002-09-19 Kazu Hirata <kazu@cs.umass.edu>
- * config/h8300/h8300.md: Remove bit extraction patterns that
- cannot be triggered.
- Restrict each bit extraction pattern to a variant on which the
- pattern is tested.
+ * config/fp-bit.c: Follow spelling conventions.
+ * config/d30v/d30v.c: Likewise.
+ * config/d30v/d30v.h: Likewise.
+ * config/fr30/fr30.c: Likewise.
+ * config/fr30/fr30.h: Likewise.
+ * config/fr30/fr30.md: Likewise.
+ * config/frv/frv.c: Likewise.
+ * config/frv/frv.h: Likewise.
+ * config/h8300/h8300.c: Likewise.
+ * config/h8300/lib1funcs.asm: Likewise.
+ * config/i370/i370.c: Likewise.
+ * config/i386/i386.h: Likewise.
+ * config/i386/i386.md: Likewise.
+ * config/i386/pentium.md: Likewise.
+ * config/i386/winnt.c: Likewise.
+ * config/i960/i960.c: Likewise.
+ * config/ia64/ia64.h: Likewise.
+ * config/ip2k/ip2k.c: Likewise.
+ * config/ip2k/ip2k.h: Likewise.
+ * config/ip2k/ip2k.md: Likewise.
+ * config/ip2k/libgcc.S: Likewise.
-2002-01-26 Joseph S. Myers <jsm28@cam.ac.uk>
+2002-09-19 Stephen Clarke <stephen.clarke@superh.com>
- * doc/include/texinfo.tex: Update to version 2002-01-04.07.
+ * config/sh/sh.h (UNSPEC_GOTOFF_P): Define.
+ (GOTOFF_P): Extend to allow gotoff plus constant.
-2002-01-26 Kazu Hirata <kazu@hxi.com>
+2002-09-18 Richard Henderson <rth@redhat.com>
- * config/h8300/h8300.md: Remove bit test patterns that cannot
- be triggered.
- Restrict each bit test pattern to a variant on which the
- pattern is tested.
+ * ifcvt.c (noce_process_if_block): Correctly detect X modified
+ with INSN_B before COND_EARLIEST. Don't check A and B for
+ modification in condition range. Reorder INSN_B for A==B properly.
+ (if_convert): Iterate until no matches for a block.
-2002-01-26 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+2002-09-18 Richard Henderson <rth@redhat.com>
- * builtins.c (expand_builtin_strncat): Remove redundant check for
- INTEGER_CST.
+ * calls.c (store_one_arg): Rename default_align to parm_align;
+ always adjust parm_align for downward padding.
-2002-01-25 David O'Brien <obrien@FreeBSD.org>
+2002-09-18 Richard Henderson <rth@redhat.com>
- * config/i386/x86-64.h (DEFAULT_PCC_STRUCT_RETURN): Do not overide
- default setting.
- * config/i386/freebsd64.h (DEFAULT_PCC_STRUCT_RETURN): Do not override
- existing setting.
+ * toplev.c (backend_init): Move init_real_once invocation ...
+ (do_compile): ... here.
-2002-01-25 Geoffrey Keating <geoffk@redhat.com>
+2002-09-18 Richard Henderson <rth@redhat.com>
- * dbxout.c (dbxout_init): Use assemble_name rather than just
- stripping off the first character.
- (dbxout_source_file): Likewise.
+ * sibcall.c (optimize_sibling_and_tail_recursive_call): Also remove
+ RTX_UNCHANGING_P markers for successful tail-recursive replacement.
-2002-01-25 DJ Delorie <dj@redhat.com>
+2002-09-18 Richard Henderson <rth@redhat.com>
- * config/sparc/sparc.c (sparc_emit_set_symbolic_const64): Compare
- using rtx_equal_p, not by comparing pointers.
+ * real.c (round_for_format): Collect sticky as unsigned long, not bool.
-2002-01-25 Steve Ellcey <sje@cup.hp.com>
+2002-09-19 Alan Modra <amodra@bigpond.net.au>
- * emit-rtl.c (gen_rtx_REG): Always return the same rtx
- for PIC_OFFSET_TABLE_REGNUM.
- (init_emit_once): Use gen_raw_REG to initialize pic_offset_table_rtx.
+ * config/rs6000/rs6000.md: (floatdisf2): Rename to
+ floatdisf2_internal1.
+ (floatdisf2): New define_expand.
+ (floatdisf2_internal2): Likewise.
-2002-01-25 David O'Brien <obrien@FreeBSD.org>
+2002-09-18 Richard Henderson <rth@redhat.com>
- * config.gcc (x86_64-*-freebsd*): New target.
- (x86_64-*-netbsd*,x86_64-*-linux*): Use ${tm_file} rather than its
- value.
- (i[34567]86-*-freebsd*): Don't include svr4.h.
- * config/i386/freebsd64.h: New file.
+ * real.c (sticky_rshift_significand): Collect sticky as
+ unsigned long, not bool.
-2002-01-25 Douglas B Rupp <rupp@gnat.com>
+2002-09-18 Ulrich Weigand <uweigand@de.ibm.com>
- * config/alpha/x-vms (version): Make static.
+ * config/s390/s390.c (s390_address_cost): New function.
+ config/s390/s390-protos.h (s390_address_cost): Add prototype.
+ config/s390/s390.h (ADDRESS_COST): Call s390_address_cost.
+ (RTX_COST): Use COSTS_N_INSNS.
- * config/alpha/vms.h (MD_FALLBACK_FRAME_STATE_FOR): Fix error
- in previous checkin.
+2002-09-18 Douglas Rupp <rupp@gnat.com>
+ Donn Terry <donnte@microsoft.com>
- * Makefile.in (install-headers-cp): New target.
- * config.gcc (alpha-dec-*vms*): Install headers with
- install-headers-cp
+ * stor-layout.c (place_field): Handle alignment of whole
+ structures when MSVC compatible bitfields are involved.
+ Change method of computing location of MS bitfields to
+ be compatible with #pragma pack(n).
-Fri Jan 25 22:42:49 CET 2002 Jan Hubicka <jh@suse.cz>
+ * tree.h (record_layout_info): Add new field
+ remaining_in_alignment.
- * unroll.c (unroll_loop): Lower final_value to nonmemory operand;
- avoid it's copies.
+ * doc/tm.texi: (TARGET_MS_BITFIELD_LAYOUT_P): Update.
+ (pragma pack): Add paragraph on MSVC bit-field packing.
-Fri Jan 25 08:26:19 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2002-09-18 Richard Earnshaw (reanrsha@arm.com)
- * builtins.c (expand_builtin_strncpy): Use integer_zerop instead
- of compare_tree_int.
- (expand_builtin_strncat): Likewise.
- * c-decl.c (finish_struct): Use tree_low_cst.
- * tree.h (compare_tree_int): Arg is unsigned HOST_WIDE_INT.
- * tree.c (compare_tree_int): Likewise.
+ PR optimization/7967
+ * arm.md (ne_zeroextractsi): Add clobber of the condition code
+ register.
-2002-01-25 Ulrich Weigand <uweigand@de.ibm.com>
+2002-09-18 Kazu Hirata <kazu@cs.umass.edu>
- * reload1.c (eliminate_regs_in_insn): Recognize frame pointer
- adjustments even if they are implemented by more than two insns.
+ * config/s390/s390.c: Follow spelling conventions.
+ * config/sh/lib1funcs.asm: Likewise.
+ * config/sh/sh.c: Likewise.
+ * config/sh/sh.h: Likewise.
+ * config/sparc/sparc.c: Likewise.
+ * config/sparc/sparc.h: Likewise.
+ * config/sparc/sparc.md: Likewise.
+ * config/stormy16/stormy16.c: Likewise.
+ * config/stormy16/stormy16.h: Likewise.
+ * config/v850/v850.c: Likewise.
+ * config/v850/v850.h: Likewise.
+ * config/vax/vax.c: Likewise.
+ * config/vax/vax.h: Likewise.
-Fri Jan 25 20:43:56 CET 2002 Jan Hubicka <jh@suse.cz>
+2002-09-18 Nick Clifton <nickc@redhat.com>
- * df.c (df_ref_create, df_ref_record_1, df_ref_record): Kill BB arg.
- * df.h (struct ref): Kill B.
- (DF_REF_BB, DF_REF_BBNO): Use BLOCK_FOR_INSN.
+ * config/rs60000/rs6000.c (rs6000_emit_move): Handle V1DImode moves.
+ * config/rs60000/rs6000.c (SPE_VECTOR_MODE): Include V1DImode.
+ * config/rs6000/spe.md (movv1di, movv1di_internal): New patterns.
- * basic-block.h (PROP_EQUAL_NOTES): New flag.
- * flow.c (propagate_one_insn): Use it.
- (mark_used_regs): Handle NIL.
+2002-09-17 Zack Weinberg <zack@codesourcery.com>
-2002-01-25 Geoffrey Keating <geoffk@redhat.com>
+ * ABOUT-GCC-NLS: Remove reference to enquire, and out-of-date
+ statement that the only translation is to en_UK.
- * config/stormy16/stormy16.md (tablejump_pcrel): Use a MEM
- to help folding.
+2002-09-17 Kazu Hirata <kazu@cs.umass.edu>
-2002-01-25 David Edelsohn <edelsohn@gnu.org>
+ * config/alpha/alpha.c: Follow spelling conventions.
+ * config/alpha/alpha.h: Likewise.
+ * config/alpha/alpha.md: Likewise.
+ * config/arc/arc.h: Likewise.
+ * config/arm/arm.c: Likewise.
+ * config/arm/arm.h: Likewise.
+ * config/arm/arm.md: Likewise.
+ * config/arm/pe.c: Likewise.
+ * config/arm/unknown-elf.h: Likewise.
+ * config/avr/avr.c: Likewise.
+ * config/avr/avr.h: Likewise.
+ * config/c4x/c4x.c: Likewise.
+ * config/cris/cris.c: Likewise.
+ * config/cris/cris.h: Likewise.
+
+2002-09-17 Samuel Figueroa <figueroa@apple.com>
+
+ * final.c (final_scan_insn): Use new macro ASM_OUTPUT_ALIGN_WITH_NOP.
+ * config/sparc/sparc.h (ASM_OUTPUT_ALIGN_WITH_NOP) New macro.
+ * doc/tm.texi (ASM_OUTPUT_ALIGN_WITH_NOP) New description.
+
+2002-09-17 Dale Johannesen <dalej@apple.com>
+
+ * cfgcleanup.c (try_forward_edges): Do not forward a
+ branch to just after a loop exit before loop optimization;
+ this interfered with doloop detection.
- * rs6000.md (prefetch): Make address V4SI mode so that the address
- is restricted to legitimate form for instruction.
+2002-09-17 Nick Clifton <nickc@redhat.com>
-2002-01-25 Bob Wilson <bob.wilson@acm.org>
+ * config/arm/arm.c (output_return_instruction): Do not
+ writeback the stack pointer when it is being loaded.
+ (arm_output_epilogue): Likewise.
- * doc/install.texi (xtensa-*-elf): New target.
- (xtensa-*-linux*): New target.
- * doc/contrib.texi: Add myself.
+2002-09-17 Kazu Hirata <kazu@cs.umass.edu>
-2002-01-25 Nick Clifton <nickc@cambridge.redhat.com>
+ * optabs.c (prepare_cmp_insn): Let emit_library_call_value
+ generate a pseudo reg that receives the result of a libcall.
+ (prepare_float_lib_cmp): Likewise.
- * config/arm/arm.c (arm_hard_regno_mode_ok): Allow any general
- purpose register to hold an SImode (or smaller) value.
+2002-09-17 Steve Ellcey <sje@cup.hp.com>
-2002-01-25 Jakub Jelinek <jakub@redhat.com>
+ * config/ia64/elf.h: Remove CPP_PREDEFINES.
- * unwind-dw2-fde-glibc.c: If inhibit_libc, use __register_frame*
- registry only.
- * crtstuff.c: Likewise.
+2002-09-17 Nicola Pero <n.pero@mi.flashnet.it>
-2002-01-25 Kazu Hirata <kazu@hxi.com>
+ Fix PR/7014 and related objc bugs:
+ * c-typeck.c (comp_target_types): Added a reflexive argument.
+ Pass it to ObjC when/if calling objc_comptypes(). Updated all
+ callers to provide the appropriate reflexive argument.
+ * objc/objc-act.c (objc_comptypes): Carefully checked and fixed
+ typechecking for all cases of comparisons and assignments,
+ particularly the obscure and less common ones involving protocols.
- * config/h8300/h8300.md (negation patterns): Tighten
- predicates to register_operand.
+2002-09-17 Nick Clifton <nickc@redhat.com>
-2002-01-24 Aldy Hernandez <aldyh@redhat.com>
+ * machmode.def (V1DImode): New mode. A single element vector.
+ * tree.h (TI_UV1DI_TYPE, TI_V1DI_TYPE): New tree_index enums.
+ (unsigned_V1DI_type_node, V1D1_type_node): New type nodes.
+ * tree.c (build_common_tree_nodes_2): Build
+ unsigned_V1DI_type_node and V1D1_type_node.
+ * c-common.c (c_common_type_for_mode): Return
+ unsigned_V1DI_type_node or V1D1_type_node for V1DImode.
+ * rtl.c (class_narrowest_): Start integer vector nodes with V1DImode.
- * loop.c (emit_prefetch_instructions): Use the prefetch insn's
- mode, not Pmode.
+2002-09-17 Nicola Pero <n.pero@mi.flashnet.it>
- * builtins.c (expand_builtin_prefetch): Same.
+ * doc/objc.texi (Constant string objects): Extended documentation
+ to make clear that the constant string class ivar layout is
+ completely fixed.
-2002-01-24 Alexandre Oliva <aoliva@redhat.com>
+2002-09-17 Roger Sayle <roger@eyesopen.com>
- * config/sh/sh.md (sym_label2reg): Make sure all CONSTs have
- modes.
+ * cfgrtl.c (flow_delete_block_noexpunge): Delete orphaned
+ NOTE_INSN_LOOP_CONT notes when deleting basic blocks.
-2002-01-24 Kazu Hirata <kazu@hxi.com>
+2002-09-16 Richard Henderson <rth@redhat.com>
- * config/h8300/h8300.c (print_operand): Remove support for
- operand character 'A'.
- * config/h8300/h8300.md (three anonymous patterns): Replace
- operand character 'A' with either 'T' or 'S'.
+ * expr.c (emit_block_move): Set memory block size as appropriate
+ for the copy.
-2002-01-24 Kazu Hirata <kazu@hxi.com>
+2002-09-16 Richard Henderson <rth@redhat.com>
- * config/h8300/h8300.c (print_operand): Remove support for
- operand character 'U'.
+ PR fortran/3924
+ * sdbout.c (sdbout_symbol): Don't handle offsets from a symbol.
-2002-01-24 Andris Pavenis <pavenis@latnet.lv>
+2002-09-16 Richard Henderson <rth@redhat.com>
+
+ * emit-rtl.c (set_mem_attributes_minus_bitpos): Adjust SIZE
+ as well as OFFSET for BITPOS.
+
+2002-09-16 Jeff Garzik <jgarzik@mandrakesoft.com>
+
+ * config.gcc: Treat winchip_c6-*|winchip2-*|c3-* as pentium-mmx.
+ * config/i386/i386.c (processor_alias_table): Add winchip-c6,
+ winchip2 and c3.
+ * doc/invoke.texi: Mention new aliases.
+
+2002-09-16 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * calls.c (store_one_arg): Set default alignment for BLKmode arguments
+ to BITS_PER_UNIT when ARGS_GROW_DOWNWARD and the padding direction is
+ downward.
+ * function.c (pad_below): Always compile.
+ (locate_and_pad_parm): If defined ARGS_GROW_DOWNWARD, pad argument to
+ alignment when it is not in a register or REG_PARM_STACK_SPACE is true.
+ Pad below when the argument is not in a register and the padding
+ direction is downward.
+
+ * pa-64.h (MUST_PASS_IN_STACK): Move define to pa.h.
+ (PAD_VARARGS_DOWN): Define.
+ * pa.c (function_arg_padding): Revise padding directions to make them
+ compatible with the 32 and 64-bit runtime architecture documentation.
+ (hppa_va_arg): Add code to handle variable and size zero arguments
+ passed by reference on TARGET_64BIT. Reformat.
+ (function_arg): Use a PARALLEL for BLKmode and aggregates args on
+ TARGET_64BIT. Use a DImode PARALLEL for BLKmode args 5 to 8 bytes
+ wide when !TARGET_64BIT. Move forward check for mode==VOIDmode.
+ Add comments.
+ * pa.h (MAX_PARM_BOUNDARY): Correct define for TARGET_64BIT.
+ (RETURN_IN_MEMORY): Return size zero types in memory.
+ (FUNCTION_VALUE): Return TFmode in general registers.
+ (MUST_PASS_IN_STACK): Define.
+ (FUNCTION_ARG_BOUNDARY): Simplify.
+ (FUNCTION_ARG_PASS_BY_REFERENCE): Pass variable and zero sized types
+ by reference.
+ (FUNCTION_ARG_CALLEE_COPIES): Define to FUNCTION_ARG_PASS_BY_REFERENCE.
- * config/i386/t-djgpp: Use NATIVE_SYSTEM_HEADER_DIR.
+2002-09-16 Richard Henderson <rth@redhat.com>
-2002-01-24 Nick Clifton <nickc@cambridge.redhat.com>
+ * real.c (do_fix_trunc): New.
+ (real_arithmetic): Call it.
+ * simplify-rtx.c (simplify_unary_operation): Handle FIX
+ with a floating-point result mode.
- * config/arm/arm.c (arm_hard_regno_mode_ok): Allow SImode
- values to be assigned to the stack pointer.
+2002-09-16 Richard Henderson <rth@redhat.com>
-2002-01-14 Hartmut Penner <hpenner@de.ibm.com>
+ * builtin-types.def (BT_FN_FLOAT_CONST_STRING): New.
+ (BT_FN_DOUBLE_CONST_STRING, BT_FN_LONG_DOUBLE_CONST_STRING): New.
+ * builtins.def (__builtin_nan, __builtin_nanf, __builtin_nanl): New.
+ (__builtin_nans, __builtin_nansf, __builtin_nansl): New.
+ * builtins.c (fold_builtin_nan): New.
+ (fold_builtin): Call it.
+ * real.c (real_nan): Parse a non-empty string.
+ (round_for_format): Fix NaN significand truncation.
+ * real.h (real_nan): Return bool.
+ * doc/extend.texi: Document new builtins.
- * emit_rtl.c (gen_lowpart_common): Conversion from const_int
- to const_double needs to be done right for big-endian systems.
+2002-09-16 Jason Merrill <jason@redhat.com>
+ Danny Smith <dannysmith@users.sourceforge.net>
-2002-01-24 Jason Merrill <jason@redhat.com>
+ * config/i386/winnt.c (ix86_handle_dll_attribute): Set
+ DECL_EXTERN and TREE_PUBLIC for dllimported variables here...
+ (i386_pe_mark_dllimport): Not here.
- PR c++/2432
- * config/sparc/sparc.md (call-jump peepholes): Pass the right insn
- to can_throw_internal.
+2002-09-16 Nathan Sidwell <nathan@codesourcery.com>
+
+ * c-semantics.c (genrtl_do_stmt): Cope with NULL cond.
+
+2002-09-16 Geoffrey Keating <geoffk@redhat.com>
+
+ * config/rs6000/rs6000.c (build_mask64_2_operands): Suppress
+ warnings about unused operands when HOST_BITS_PER_WIDE_INT is
+ < 64.
+ (rs6000_emit_cmove): Use real_isinf not target_isinf.
+
+2002-09-16 Kazu Hirata <kazu@cs.umass.edu>
+
+ * calls.c (emit_library_call_value_1): Don't refer to
+ hard_libcall_value.
+ * optabs.c (prepare_float_lib_cmp): Likewise.
+
+2002-09-16 Geoffrey Keating <geoffk@apple.com>
+
+ * ggc-common.c (ggc_mark_rtx_children_1): Update for changed name
+ mangling.
+
+ The following changes are merged from pch-branch:
+
+ * doc/gty.texi (GTY Options): Document %a.
+ * gengtype.c (do_scalar_typedef): New function.
+ (process_gc_options): Handle `length' option.
+ (set_gc_used_type): A pointer to an array of structures doesn't
+ qualify as a pointer to a structure.
+ (output_escaped_param): Add `%a' escape.
+ (write_gc_structure_fields): Allow 'desc' on array of unions.
+ (main): Define `uint8', `jword' and `JCF_u2' as scalars; use
+ do_scalar_typedef.
+
+ * gengtype.c (enum rtx_code): Make global.
+ (rtx_format): Make global.
+ (rtx_next): New.
+ (gen_rtx_next): New.
+ (write_rtx_next): New.
+ (adjust_field_rtx_def): Skip fields marked by chain_next.
+ (open_base_files): Delete redundant prototype.
+ (write_enum_defn): New.
+ (output_mangled_typename): Correct abort call.
+ (write_gc_marker_routine_for_structure): Handle chain_next and
+ chain_prev options.
+ (finish_root_table): Don't output redundant \n.
+ (main): Call gen_rtx_next, write_rtx_next, write_enum_defn.
+ * c-tree.h (union lang_tree_node): Add chain_next option.
+
+ * gengtype.h (NUM_PARAM): New definition.
+ (struct type): For TYPE_PARAM_STRUCT, allow multiple parameters.
+ * gengtype.c (find_param_structure): New.
+ (adjust_field_type): Handle param<n>_is option.
+ (process_gc_options): Detect use_params option. Update callers.
+ (set_gc_used_type): Add 'param' parameter, update callers. Handle
+ 'use_params' option.
+ (open_base_files): Add splay-tree.h to list of files included.
+ (output_mangled_typename): New.
+ (write_gc_structure_fields): Update 'param' parameter to support
+ multiple parameters. Change name mangling. Allow parameterized
+ fields to have an apparent scalar type. Handle param<n>_is options,
+ use_param option.
+ (write_gc_marker_routine_for_structure): Update for change to name
+ mangling. Better guess the output file for parameterized types.
+ (write_gc_types): Update for change to name mangling.
+ (write_gc_root): Update for change to name mangling. Handle (ignore)
+ param<n>_is options.
+ * doc/gty.texi (GTY Options): Add description of param<n>_is
+ options, use_params option.
+ * ggc.h (ggc_mark_rtx): Update for changed name mangling.
+ * gengtype-lex.l: Produce token for param<n>_is.
+ * gengtype-yacc.y: Parse param<n>_is.
+
+ * gengtype.c (adjust_field_tree_exp): Don't name a variable 'rindex'.
+
+ * rtl.c: Update comment describing rtx_format.
+ * rtl.h (union rtunion): Separate definition and typedef.
+ (struct rtx_def): Use gengtype to mark.
+ * Makefile.in (gengtype.o): Also depend on rtl.def.
+ * ggc.h (ggc_mark_rtx_children): Delete prototype.
+ (ggc_mark_rtx): Change to alias of gengtype-generated routine.
+ * ggc-common.c (ggc_mark_rtx_children): Delete.
+ (ggc_mark_rtx_children_1): Delete.
+ (gt_ggc_m_rtx_def): Delete.
+ * gengtype.c (adjust_field_rtx_def): New.
+ (adjust_field_type): Call adjust_field_rtx_def.
+ (write_gc_structure_fields): Add 'default' case to switch if none
+ is specified; remove unused code.
+
+ * tree.h (struct tree_exp): Update for change to meaning
+ of special.
+ * gengtype.c (adjust_field_tree_exp): New function.
+ (adjust_field_type): Handle `tree_exp' special here.
+ (write_gc_structure_fields): Don't handle `tree_exp' special here.
+ Handle new `dot' option.
+
+ * gengtype.h: Make `info' a pointer-to-const.
+ * gengtype-yacc.y (yacc_ids): Use xasprintf.
+
+ * gengtype.c (write_gc_structure_fields): Remove implementation
+ of `always' option, add `default' option.
+ * doc/gty.texi (GTY Options): Remove documentation of `always',
+ add `default'.
+
+2002-09-16 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * output.h: Remove #ifdef RTX_CODE and #ifdef TREE_CODE.
+
+2002-09-16 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * m68hc11.md (addhi_sp): Fix uninitialized variable bug.
+
+ * c4x-c.c, c4x.c, darwin.c, i370-c.c, m32r.c: Include tm_p.h
+ instead of the *-protos.h file directly.
+ * t-c4x, t-i370, t-v850: Depend on $(TM_P_H).
+ * darwin.c (machopic_output_stub): Move prototype ...
+ * darwin-protos.h (machopic_output_stub): ... here.
+ * rs6000-protos.h (machopic_output_stub): Don't declare.
-2002-01-23 Richard Henderson <rth@redhat.com>
+2002-09-16 Richard Henderson <rth@redhat.com>
- * fold-const.c (fold): Change UINT_MAX test to check vs precision
- rather than TYPE_MAX_VALUE. Fix indentation and a bogus negation.
+ * c-common.c (builtin_define_float_constants): Emit __FOO_DENORM_MIN__.
-2002-01-24 Alexandre Oliva <aoliva@redhat.com>
+2002-09-16 Richard Henderson <rth@redhat.com>
- * config/sh/sh.md (symGOT_load, sym2GOT, sym2GOTOFF): New expands.
- (symGOT2reg): Use them, then set as GOT value as unchanging.
- (symGOTOFF2reg): Set REG_EQUAL note. Use a different pseudo
- as a temporary, if possible.
- (symPLT_label2reg): Enclose (pc) in UNSPEC_PIC. Emit
- sym@PLT-(.LPCS#+2-.) instead of sym@PLT+.-(.LPCS#+2).
+ * real.c, real.h: Rewrite from scratch.
+
+ * Makefile.in (simplify-rtx.o): Depend on TREE_H.
+ (paranoia): New target.
+ * builtins.c (fold_builtin_inf): Use new real.h interface.
+ * c-common.c (builtin_define_with_hex_fp_value): Likewise.
+ * c-lex.c (interpret_float): Likewise.
+ * emit-rtl.c (gen_lowpart_common): Likewise.
+ * optabs.c (expand_float): Use real_2expN.
+ * config/ia64/ia64.md (divsi3, udivsi3): Likewise.
+ * defaults.h (INTEL_EXTENDED_IEEE_FORMAT): New.
+ (FLOAT_WORDS_BIG_ENDIAN): New.
+ * cse.c (find_comparison_args): Don't pass FLOAT_STORE_FLAG_VALUE
+ directly to REAL_VALUE_NEGATIVE.
+ * loop.c (canonicalize_condition): Likewise.
+ * simplify-rtx.c: Include tree.h.
+ (simplify_unary_operation): Don't handle FIX and UNSIGNED_FIX
+ with floating-point result modes.
+ * toplev.c (backend_init): Call init_real_once.
+
+ * fold-const.c (force_fit_type): Don't call CHECK_FLOAT_VALUE.
+ * tree.c (build_real): Likewise.
+ * config/alpha/alpha.c, config/vax/vax.c (float_strings,
+ float_values, inited_float_values, check_float_value): Remove.
+ * config/alpha/alpha.h, config/m68hc11/m68hc11.h,
+ config/m88k/m88k.h, config/vax/vax.h (CHECK_FLOAT_VALUE): Remove.
+ * doc/tm.texi (CHECK_FLOAT_VALUE): Remove.
+ (VAX_HALFWORD_ORDER): Remove.
+
+2002-09-16 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.c: (legitimize_la_operand): Remove, replace by ...
+ (s390_load_address): ... this new function.
+ (s390_decompose_address): Allow the argument pointer and all
+ virtual registers as 'pointer' registers.
+ (s390_expand_plus_operand): Use s390_load_address.
+ config/s390/s390.md (movti, movdi, movdf splitters): Likewise.
+ ("force_la_31"): New insn pattern.
+ config/s390/s390-protos.h (legitimize_la_operand): Remove.
+ (s390_load_address): Add prototype.
+
+ * config/s390/s390.c: Include "optabs.h".
+ (s390_expand_movstr, s390_expand_clrstr, s390_expand_cmpstr): New.
+ config/s390/s390-protos.h (s390_expand_movstr, s390_expand_clrstr,
+ s390_expand_cmpstr): Add prototypes.
+ config/s390/s390.md ("movstrdi", "movstrsi"): Call s390_expand_movstr.
+ ("movstrdi_short"): Rename to "movstr_short_64". Change predicates
+ for operands 0 and 1 to "memory_operand". Add type attribute.
+ ("movstrsi_short"): Rename to "movstr_short_31". Change predicates
+ for operands 0 and 1 to "memory_operand". Add type attribute.
+ ("movstrdi_long", "movstrsi_long"): Remove.
+ ("movstrdi_64"): Rename to "movstr_long_64". Add type attribute.
+ ("movstrsi_31"): Rename to "movstr_long_31". Add type attribute.
+ ("clrstrdi", "clrstrsi"): Call s390_expand_clrstr.
+ ("clrstrsico"): Remove, replace by ...
+ ("clrstr_short_64", "clrstr_short_31"): ... these new patterns.
+ ("clrstrsi_64"): Rename to "clrstr_long_64".
+ ("clrstrsi_31"): Rename to "clrstr_long_31".
+ ("cmpstrdi", "cmpstrsi"): Call s390_expand_cmpstr.
+ ("cmpstr_const"): Remove, replace by ...
+ ("cmpstr_short_64", "cmpstr_short_31"): ... these new patterns.
+ ("cmpstr_64"): Rename to "cmpstr_long_64".
+ ("cmpstr_31"): Rename to "cmpstr_long_31".
+
+2002-09-16 Kazu Hirata <kazu@cs.umass.edu>
+
+ * ABOUT-NLS: Follow spelling conventions.
+ * ChangeLog: Likewise.
+ * ChangeLog.1: Likewise.
+ * ChangeLog.2: Likewise.
+ * ChangeLog.3: Likewise.
+ * ChangeLog.4: Likewise.
+ * ChangeLog.5: Likewise.
+ * ChangeLog.6: Likewise.
+ * FSFChangeLog.10: Likewise.
+ * FSFChangeLog.11: Likewise.
+ * c-common.c: Likewise.
+ * c-lex.c: Likewise.
+ * c-objc-common.c: Likewise.
+ * cppexp.c: Likewise.
+ * cppinit.c: Likewise.
+ * cpplex.c: Likewise.
+ * doloop.c: Likewise.
+ * flow.c: Likewise.
+ * function.c: Likewise.
+ * integrate.c: Likewise.
+ * loop.c: Likewise.
+ * reg-stack.c: Likewise.
+ * reload.h: Likewise.
+ * ssa.c: Likewise.
-2002-01-23 Kazu Hirata <kazu@hxi.com>
+2002-09-15 Kazu Hirata <kazu@cs.umass.edu>
- * config/h8300/h8300.md: Fix xorqi and xorqi so that they will
- accept to accept 0x80 as operands[2].
+ * ChangeLog: Follow spelling conventions.
+ * ChangeLog.0: Likewise.
+ * ChangeLog.1: Likewise.
+ * ChangeLog.2: Likewise.
+ * ChangeLog.4: Likewise.
+ * ChangeLog.6: Likewise.
+ * config.gcc: Likewise.
+ * dwarfout.c: Likewise.
+ * reload1.c: Likewise.
+ * simplify-rtx.c: Likewise.
+ * unwind-sjlj.c: Likewise.
+ * config/avr/avr.h: Likewise.
+ * config/d30v/d30v.h: Likewise.
+ * config/frv/frv.c: Likewise.
+ * config/frv/frv.h: Likewise.
+ * config/ip2k/ip2k.h: Likewise.
+ * config/m88k/m88k-move.sh: Likewise.
+ * config/stormy16/stormy16.c: Likewise.
+ * config/stormy16/stormy16.h: Likewise.
+ * doc/extend.texi: Likewise.
+ * doc/interface.texi: Likewise.
+ * doc/invoke.texi: Likewise.
+ * doc/md.texi: Likewise.
+ * doc/rtl.texi: Likewise.
+ * doc/tm.texi: Likewise.
+ * doc/trouble.texi: Likewise.
+ * ginclude/float.h: Likewise.
+ * treelang/treelang.texi: Likewise.
+
+2002-09-15 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * i386-protos.h (i386_pe_dllexport_name_p,
+ i386_pe_dllimport_name_p, i386_pe_unique_section,
+ i386_pe_declare_function_type, i386_pe_record_external_function,
+ i386_pe_record_exported_symbol, i386_pe_asm_file_end): Add
+ prototype.
+ * i386/t-cygwin (winnt.o): Depend on $(TM_P_H).
+ * i386/t-interix (winnt.o): Likewise.
+
+ * v850-protos.h (v850_output_addr_const_extra): Prototype.
+
+2002-09-15 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/mips/netbsd.h (TARGET_OS_CPP_BUILTINS): Add
+ MIPS ABI CPP macros.
+ (TARGET_CPU_CPP_BUILTINS): Redefine.
+ (SUBTARGET_EXTRA_SPECS): Remove subtarget_endian_default.
+ (SUBTARGET_ENDIAN_DEFAULT_SPEC): Remove.
+
+2002-09-15 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * ia64/aix.h (TARGET_OS_CPP_BUILTINS): Fix typo.
+
+2002-09-15 Kazu Hirata <kazu@cs.umass.edu>
+
+ * ChangeLog: Follow spelling conventions.
+ * ChangeLog.0: Likewise.
+ * ChangeLog.1: Likewise.
+ * ChangeLog.2: Likewise.
+ * ChangeLog.3: Likewise.
+ * ChangeLog.4: Likewise.
+ * ChangeLog.5: Likewise.
+ * ChangeLog.6: Likewise.
+ * FSFChangeLog.10: Likewise.
+ * FSFChangeLog.11: Likewise.
+ * c-common.c: Likewise.
+ * c-common.h: Likewise.
+ * c-format.c: Likewise.
+ * c-opts.c: Likewise.
+ * cpplib.c: Likewise.
+ * langhooks.h: Likewise.
+ * real.c: Likewise.
+ * reg-stack.c: Likewise.
+ * toplev.c: Likewise.
+ * config/arm/arm.c: Likewise.
+ * config/arm/arm.md: Likewise.
+ * config/arm/linux-gas.h: Likewise.
+ * config/arm/netbsd.h: Likewise.
+ * config/c4x/c4x.c: Likewise.
+ * config/c4x/c4x.h: Likewise.
+ * config/c4x/c4x.md: Likewise.
+ * config/c4x/libgcc.S: Likewise.
+ * config/fr30/fr30.md: Likewise.
+ * config/frv/frv.md: Likewise.
+ * config/ia64/ia64.md: Likewise.
+ * config/mips/mips.h: Likewise.
+ * config/mn10300/mn10300.c: Likewise.
+ * config/stormy16/stormy16.c: Likewise.
+ * config/v850/v850.md: Likewise.
+ * doc/extend.texi: Likewise.
+ * doc/invoke.texi: Likewise.
+ * doc/md.texi: Likewise.
-2002-01-24 Alexandre Oliva <aoliva@redhat.com>
+2002-09-15 Jason Thorpe <thorpej@wasabisystems.com>
- * config/sparc/sparc.md (fix_trunctfdi2): Correct typo in mode.
+ * config/netbsd.h (LIB_SPEC): Include the appropriate pthread
+ library if -pthread is specified.
-2002-01-23 Richard Henderson <rth@redhat.com>
+2002-09-15 Jason Thorpe <thorpej@wasabisystems.com>
- * config/alpha/alpha.md (call_value_osf_1_er peepholes): Fix typo.
+ * config.gcc (*-*-netbsd*): Set thread_file to 'posix'
+ for --enable-threads=yes and --enable-threads=posix.
-2002-01-23 Aldy Hernandez <aldyh@redhat.com>
+2002-09-15 Kazu Hirata <kazu@cs.umass.edu>
- * c-parse.in (parmlist_or_identifiers): Add maybe_attribute.
- (parmlist_or_identifiers_1): Verify that only a parmlist follows
- an attribute.
+ * config/sparc/cypress.md: Replace Sparc with SPARC.
+ * config/sparc/freebsd.h: Likewise.
+ * config/sparc/gmon-sol2.c: Likewise.
+ * config/sparc/hypersparc.md: Likewise.
+ * config/sparc/lb1spc.asm: Likewise.
+ * config/sparc/lb1spl.asm: Likewise.
+ * config/sparc/linux.h: Likewise.
+ * config/sparc/linux64.h: Likewise.
+ * config/sparc/lynx.h: Likewise.
+ * config/sparc/sol2.h: Likewise.
+ * config/sparc/sparc-modes.def: Likewise.
+ * config/sparc/sparc.c: Likewise.
+ * config/sparc/sparc.h: Likewise.
+ * config/sparc/sparc.md: Likewise.
+ * config/sparc/sparclet.md: Likewise.
+ * config/sparc/supersparc.md: Likewise.
+ * config/sparc/sysv4.h: Likewise.
+ * config/sparc/vxsim.h: Likewise.
+ * config/sparc/vxsparc64.h: Likewise.
-2002-01-23 Richard Henderson <rth@redhat.com>
+2002-09-14 Marek Michalkiewicz <marekm@amelek.gda.pl>
- * expr.c (move_by_pieces_1): Extend size before negation.
+ * config/avr/avr.c (output.h): Move after inclusion of tree.h.
- * config/m68k/t-m68kbare (MULTILIB_OPTIONS): Add 68040 and 68060.
- (MULTILIB_MATCHES): Remove 68040 and 68060 aliases.
- (MULTILIB_EXCEPTIONS): Ignore 68881 and soft-float for 68040 and 68060.
- * config/m68k/t-m68kelf: Likewise.
+2002-09-14 Kazu Hirata <kazu@cs.umass.edu>
-2002-01-23 Bob Wilson <bob.wilson@acm.org>
+ * ChangeLog: Follow spelling conventions.
+ * ChangeLog.0: Likewise.
+ * ChangeLog.2: Likewise.
+ * ChangeLog.3: Likewise.
+ * ChangeLog.4: Likewise.
+ * ChangeLog.5: Likewise.
+ * ChangeLog.6: Likewise.
+ * cppfiles.c: Likewise.
+ * cppinit.c: Likewise.
+ * cpplib.h: Likewise.
+ * cse.c: Likewise.
+ * debug.h: Likewise.
+ * df.c: Likewise.
+ * dominance.c: Likewise.
+ * hashtable.c: Likewise.
+ * hashtable.h: Likewise.
+ * loop.c: Likewise.
+ * config/arm/README-interworking: Likewise.
+ * config/arm/arm.c: Likewise.
+ * config/arm/arm.h: Likewise.
+ * config/arm/arm.md: Likewise.
+ * config/dsp16xx/dsp16xx.h: Likewise.
+ * config/frv/frv.c: Likewise.
+ * config/frv/frv.h: Likewise.
+ * config/ip2k/ip2k.h: Likewise.
+ * config/rs6000/rs6000.c: Likewise.
+ * config/stormy16/stormy-abi: Likewise.
+ * config/stormy16/stormy16.h: Likewise.
+ * config/v850/v850.c: Likewise.
- * config/xtensa/elf.h: New file.
- * config/xtensa/lib1funcs.asm: New file.
- * config/xtensa/lib2funcs.S: New file.
- * config/xtensa/linux.h: New file.
- * config/xtensa/t-xtensa: New file.
- * config/xtensa/xtensa-config.h: New file.
- * config/xtensa/xtensa-protos.h: New file.
- * config/xtensa/xtensa.c: New file.
- * config/xtensa/xtensa.h: New file.
- * config/xtensa/xtensa.md: New file.
- * config.gcc (xtensa-*-elf*): New target.
- (xtensa-*-linux*): New target.
- * cse.c (canon_hash): Compare rtx pointers instead of register
- numbers. This is required for the Xtensa port.
- * integrate.c (copy_insn_list): Handle case where the static
- chain is in memory and the memory address has to be copied to
- a register.
- * doc/invoke.texi (Option Summary): Add Xtensa options.
- (Xtensa Options): New node.
- * doc/md.texi (Machine Constraints): Add Xtensa machine constraints.
+2002-09-14 Kazu Hirata <kazu@cs.umass.edu>
-2002-01-23 Zack Weinberg <zack@codesourcery.com>
+ * loop.c: Fix a comment typo.
- * diagnostic.c (internal_error): Do ICE suppression only
- when ENABLE_CHECKING is not defined.
+2002-09-14 Kazu Hirata <kazu@cs.umass.edu>
- * c-typeck.c (require_complete_type): Return error_mark_node
- if type is error_mark_node.
+ * config/fr30/fr30.h: Fix comment typos.
+ * config/frv/frv.c: Likewise.
+ * config/i386/xmmintrin.h: Likewise.
+ * config/mips/mips.c: Likewise.
+ * config/sh/sh.c: Likewise.
-2002-01-23 Janis Johnson <janis187@us.ibm.com>
+2002-09-14 Kazu Hirata <kazu@cs.umass.edu>
- * toplev.c (process_options): Disable -fprefetch-loop-arrays with
- -Os and issue a warning.
+ * haifa-sched.c: Follow spelling conventions.
+ * regclass.c: Likewise.
+ * regrename.c: Likewise.
+ * config/fp-bit.c: Likewise.
+ * config/frv/frv.h: Likewise.
+ * config/m88k/m88k.c: Likewise.
+ * config/mcore/mcore.c: Likewise.
+ * config/rs6000/darwin.h: Likewise.
+ * config/rs6000/gnu.h: Likewise.
+ * config/rs6000/linux.h: Likewise.
+ * config/rs6000/linux64.h: Likewise.
+ * config/rs6000/rs6000.c: Likewise.
+ * config/rs6000/rs6000.h: Likewise.
+ * config/sh/sh.c: Likewise.
+ * config/sparc/sparc.c: Likewise.
+ * config/sparc/ultra1_2.md: Likewise.
-2002-01-23 Zack Weinberg <zack@codesourcery.com>
+2002-09-14 Stephane Carrez <stcarrez@nerim.fr>
- * doc/fragments.texi, doc/hostconfig.texi: Update to reflect
- current (lack of) need for host configuration by hand.
+ * config/m68hc11/m68hc11.md ("movdi_internal"): Allow any offsetable
+ memory operand when source is 0 (K constraint).
+ ("movsi_internal"): Likewise.
+ ("movdf_internal"): Likewise.
+ ("movsf_internal"): Likewise.
- * doc/gccint.texi, doc/rtl.texi, doc/tm.texi: Adjust cross
- references. Documentation of some target macros moved from
- hostconfig.texi to tm.texi.
+2002-09-14 Alan Modra <amodra@bigpond.net.au>
-2002-01-23 Will Cohen <wcohen@redhat.com>
+ * config/rs6000/rs6000.c (rs6000_elf_encode_section_info): Use
+ targetm.binds_local_p to set SYMBOL_REF_FLAG.
+ (rs6000_xcoff_encode_section_info): Likewise.
+ * config/rs6000/xcoff.h (ASM_DECLARE_FUNCTION_NAME): Likewise.
- * config/arm/arm.h (THUMB_FUNCTION_PROFILER): Define if not currently
- defined.
+2002-09-10 Theodore A. Roth <troth@verinet.com>
-2002-01-23 Kazu Hirata <kazu@hxi.com>
+ * gcc/config/avr/avr.h: Set default options for C++ for avr.
- * config/h8300/h8300.md (*andorhi3): Accept 0x8000 as an
- operand[3].
+2002-09-13 Richard Henderson <rth@redhat.com>
-2002-01-23 Jason Merrill <jason@redhat.com>
+ * Makefile.in (toplev.o): Depend on real.h.
+ (print-rtl.o, varasm.o, ifcvt.o): Likewise.
- * tree.c (build1): Don't set TREE_READONLY on INDIRECT_REF.
+2002-09-14 Alan Modra <amodra@bigpond.net.au>
- * function.c (assign_parms): Don't put args of inline functions
- into registers when not optimizing.
+ * doc/tm.texi (DBX_OUTPUT_NFUN): Describe.
+ * dbxout.c (dbxout_function_end): Use DBX_OUTPUT_NFUN.
+ * config/rs6000/linux64.h (DBX_OUTPUT_NFUN): Define.
-2002-01-23 Nick Clifton <nickc@cambridge.redhat.com>
+2002-09-13 Nathan Sidwell <nathan@codesourcery.com>
- * config/arm/arm.md (UNSPEC_PROLOGUE_USE): New unspec constant.
- (prologue_use): New pattern.
- * config/arm/arm.c (expand_prologue): Use gen_prologue_use in
- preference to gen_rtx_USE.
- (thumb_expand_prologue): Use gen_prologue_use in preference to
- gen_rtx_USE.
- (thumb_expand_epilogue): Use gen_prologue_use in preference to
- gen_rtx_USE.
+ * ggc-common.c (ggc_mark_roots): Don't iterate NULL hash tables.
-2002-01-23 Hans-Peter Nilsson <hp@bitrange.com>
+2002-09-13 Steve Ellcey <sje@cup.hp.com>
- * loop.c [!HAVE_prefetch] (CODE_FOR_prefetch): Define to 0.
+ * config.gcc (ia64*-*-aix*, ia64*-*-elf*, ia64*-*-freebsd*,
+ ia64*-*-linux*): Set extra_parts.
+ * config/ia64/t-aix (EXTRA_PARTS): Remove.
+ * config/ia64/t-ia64 (EXTRA_PARTS): Remove.
-2002-01-23 Neil Booth <neil@daikokuya.demon.co.uk>
+2002-09-13 Kazu Hirata <kazu@cs.umass.edu>
- PR c/3504
- * doc/extend.texi: Correct documentation of __alignof__.
+ * config/h8300/fixunssfsi.c: Replace H8/S with H8S.
+ * config/h8300/h8300.c: Likewise.
+ * config/h8300/h8300.h: Likewise.
+ * config/h8300/h8300.md: Likewise.
+ * doc/invoke.texi: Likewise.
+
+2002-09-13 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/h8300.c (h8300_init_once): Fix formatting.
+
+2002-09-13 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.md (attr type): Add callpal.
+ (imb, trap, load_tp, set_tp): Use it.
+ * config/alpha/ev4.md (ev4_callpal): New.
+ * config/alpha/ev5.md (ev5_callpal): New.
+ * config/alpha/ev6.md (ev6_ibr): Handle callpal.
+ * config/alpha/alpha.c (alphaev4_insn_pipe): Handle TYPE_CALLPAL.
+ (alphaev5_insn_pipe): Likewise.
+
+2002-09-13 Andreas Jaeger <aj@suse.de>
+
+ * Makefile.in (print-rtl.o): Depend on CONFIG_H.
+
+2002-09-13 Steve Ellcey <sje@cup.hp.com>
+
+ * config/ia64/t-hpux (LIBGCC1_TEST, STMP_FIXPROTO,
+ LIB2ADDEH): New, set to NULL.
+ (SHLIB_EXT, SHLIB_LINK, SHLIB_INSTALL, SHLIB_MKMAP): New.
+
+2002-09-13 Steve Ellcey <sje@cup.hp.com>
+
+ * config/ia64/quadlib.c (_U_Qfcmp): Make extern.
+ (_U_Qfcnvfxt_quad_to_sgl): Remove declaration.
+ (_U_Qfeq, _U_Qfne, _U_Qfgt, _U_Qfge, U_Qflt, U_Qfle, _U_Qfcomp):
+ Add declarations.
+ (_U_Qfneg): Remove.
+
+2002-09-13 Dhananjay Deshpande <dhananjayd@kpit.com>
+
+ * config/h8300/h8300.h (EIGHTBIT_CONSTANT_ADDRESS_P): Add support
+ for H8/300, H8S aa:8 mode.
+ (TINY_CONSTANT_ADDRESS_P): Add support for H8S aa:16 mode.
+ * config/h8300/h8300.c (h8300_adjust_insn_length): Adjust length
+ for H8/300 aa:8 mode.
+
+2002-09-13 Hartmut Penner <hpenner@de.ibm.com>
+
+ * config/s390/s390.md ("trap", "conditional_trap", "*trap"): New
+ insns.
+
+2002-09-12 Richard Henderson <rth@redhat.com>
+
+ * Makefile.in (HOST_PRINT): Use print-rtl1.o
+ (print-rtl.o): Don't define GENERATOR_FILE.
+ (print-rtl1.o): Rename from $(BUILD_PREFIX_1)print-rtl.o.
+ * print-rtl.c (print_rtx): Include CONST_DOUBLE fp decimal output
+ unless GENERATOR_FILE.
+
+2002-09-12 Stan Shebs <shebs@apple.com>
+
+ * config/darwin.h (USER_LABEL_PREFIX): Define here...
+ * config/i386/darwin.h: ... instead of here.
+
+ * target.h (struct gcc_target): New field
+ terminate_dw2_eh_frame_info.
+ * target-def.h (TARGET_TERMINATE_DW2_EH_FRAME_INFO): Define.
+ (TARGET_INITIALIZER): Add it.
+ * dwarf2out.c (output_call_frame_info): Use target hook.
+ * dwarf2asm.c (dw2_asm_output_delta): Use macro
+ ASM_OUTPUT_DWARF_DELTA if defined.
+ * doc/tm.texi (TARGET_TERMINATE_DW2_EH_FRAME_INFO): Document.
+ (ASM_OUTPUT_DWARF_DELTA): Ditto.
+ (ASM_OUTPUT_DWARF_OFFSET): Ditto.
+ (ASM_OUTPUT_DWARF_PCREL): Ditto.
+ * config.gcc (i[34567]86-*-darwin*): Define extra_parts.
+ (powerpc-*-darwin*): Ditto.
+ * crtstuff.c [OBJECT_FORMAT_MACHO]: Update the Mach-O bits
+ to work correctly for Darwin.
+ * config/darwin.h (OBJECT_FORMAT_MACHO): Define.
+ (STARTFILE_SPEC): Add crtbegin.o.
+ (ENDFILE_SPEC): Define.
+ (EXTRA_SECTION_FUNCTIONS): Put gcc_except_tab in data segment.
+ (ASM_PREFERRED_EH_DATA_FORMAT): Handle more cases.
+ (ASM_OUTPUT_DWARF_DELTA): Define.
+ (TARGET_TERMINATE_DW2_EH_FRAME_INFO): Define.
+ * config/darwin.c (darwin_asm_output_dwarf_delta): New function.
-2002-01-22 Zack Weinberg <zack@codesourcery.com>
+2002-09-13 Alan Modra <amodra@bigpond.net.au>
- * params.h: Rename arguments of DEFPARAM so that it will be
- recognized as a translation keyword.
+ * config/rs6000/rs6000.c (rs6000_emit_load_toc_table): Remove "if"
+ nesting. Correct test for non-PowerPC64 ELF ABI_AIX.
+ * config/rs6000/rs6000.md (load_toc_v4_PIC*): Disable when ABI_AIX.
-2002-01-22 Aldy Hernandez <aldyh@redhat.com>
+2002-09-12 Zack Weinberg <zack@codesourcery.com>
- * extend.texi: Document altivec functions.
- Fix N-bit adjectives in X86 builtin documentation.
+ * toplev.c: Move default definition of USER_LABEL_PREFIX...
+ * defaults.h: ... here.
-2002-01-22 Alexandre Oliva <aoliva@redhat.com>
+2002-09-12 Richard Henderson <rth@redhat.com>
- * reload.c (reg_overlap_mentioned_for_reload_p): Handle PLUS and
- auto_inc_dec values.
+ * vax.c: Include tree.h earlier.
-2002-01-22 Richard Earnshaw <rearnsha@arm.com>
+2002-09-12 Stan Shebs <shebs@apple.com>
- * config/netbsd-aout.h (SWITCH_TAKES_ARG): Remove bogus white space
- after backslash.
- (ASM_DECLARE_OBJECT_NAME): Add missing backslash before final line.
+ * config/darwin.c (machopic_finish): Remove #if 0 chunks.
+ (machopic_operand_p): Ditto.
-2002-01-22 Alexandre Oliva <aoliva@redhat.com>
+2002-09-12 Kazu Hirata <kazu@cs.umass.edu>
- * config/i386/freebsd-aout.h (ASM_QUAD): Undefine.
+ * config/arm/arm.c (arm_compute_initial_elimination_offset):
+ Fix a comment typo.
-2002-01-22 Richard Henderson <rth@redhat.com>
+2002-09-12 Kazu Hirata <kazu@cs.umass.edu>
- * config/alpha/alpha.c (split_small_symbolic_mem_operand): Use
- copy_insn not copy_rtx.
+ * toplev.c (do_abort): Fix a comment typo.
-2002-01-23 Alan Modra <amodra@bigpond.net.au>
+2002-09-12 Kazu Hirata <kazu@cs.umass.edu>
- * combine.c (simplify_and_const_int): Don't trunc_int_for_mode
- "nonzero" as that might add "1" bits. Ensure "constop" is
- properly sign extened.
- (force_to_mode): Tweak for sign extended constop.
+ * cselib.c: Fix comment formatting.
+ * gengtype.c: Likewise.
-2002-01-22 Richard Henderson <rth@redhat.com>
+2002-09-12 Kazu Hirata <kazu@cs.umass.edu>
- * config/alpha/alpha.c (some_small_symbolic_mem_operand) Use
- for_each_rtx instead of assuming we're already looking at the MEM.
- (split_small_symbolic_mem_operand): Likewise.
- * config/alpha/alpha.h (PREDICATE_CODES): Update.
- * config/alpha/alpha.md (small symbolic memory splitters): Update.
+ * config/h8300/h8300.md (udivmodqi4): Do not use an expander.
+ (udivmodhi4): Likewise.
-2002-01-22 Richard Henderson <rth@redhat.com>
+2002-09-12 Graham Stott <graham.stott@btinternet.com>
+ Roger Sayle <roger@eyesopen.com>
- * config/alpha/alpha.md (divmodsi_internal_er): Generate lituse
- sequence number for the literal.
- (divmoddi_internal_er): Likewise.
+ * i386.c (any_fp_register_operand, fp_register_operand,
+ register_and_not_any_fp_reg_operand, register_and_not_fp_reg_operand):
+ New predicate functions.
+ * i386-protos.h: Add their prototypes.
+ * i386.h: Add them to PREDICATE_CODES.
+ * i386.md ("*pushsf_rex64"+2, "*pushsf_rex64"+3, "*pushdf_integer"+1,
+ "*pushdf_integer"+2, "*pushtf_integer"+1, "*pushtf_integer"+2,
+ "*pushtf_integer"+3, "*pushtf_integer"+4, "*dummy_extendsfdf2"+1,
+ "*dummy_extendsfdf2"+2, "*dummy_extendsfxf2"+1,
+ "*dummy_extendsftf2"+1, "*dummy_extendsftf2"+2,
+ "*dummy_extenddfxf2"+1, "*dummy_extenddftf2"+1,
+ "*dummy_extenddftf2"+2, "*negsf2_if"+1, "*negsf2_if"+2,
+ "*negdf2_if_rex64"+1, "*negdf2_if_rex64"+2, "*negxf2_if"+1,
+ "*negxf2_if"+2, "*negtf2_if"+1, "*negtf2_if"+2, "*abssf2_if"+1,
+ "*abssf2_if"+2, "*absdf2_if_rex64"+1, "*absdf2_if_rex64"+2,
+ "*absxf2_if"+1, "*absxf2_if"+2, "*abstf2_if"+1, "*abstf2_if"+2):
+ Use these new predicates to simplify and correct the use of
+ FP_REG_P, ANY_FP_REG_P, FP_REGNO_P and any ANY_FP_REGNO_P.
-2002-01-22 Craig Rodrigues <rodrigc@gcc.gnu.org>
+2002-09-12 Jason Merrill <jason@redhat.com>
- PR java/4972
- * aclocal.m4 (AM_ICONV): Put linking flags for libiconv
- in LIBICONV variable.
- * configure: Regenerated.
+ * diagnostic.c (output_add_identifier): New fn.
+ * diagnostic.h: Declare it.
-2002-01-22 Krister Walfridsson <cato@df.lth.se>
+ * calls.c (store_one_arg): Use size_in_bytes to determine the
+ amount of space to push.
- * dependence.c (build_def_use): Remove array_idx.
+2002-09-12 Jakub Jelinek <jakub@redhat.com>
- * dwarfout.c (last_filename): Remove.
- (output_compile_unit_die): Remove last_filename.
+ * config/sparc/linux64.h (STARTFILE_SPEC32): Fix a typo.
-2002-01-22 Roger Sayle <roger@eyesopen.com>
- Richard Henderson <rth@redhat.com>
+2002-09-12 Ulrich Weigand <uweigand@de.ibm.com>
- PR opt/3640
- * fold-const.c (fold): Optimize unsigned comparisons against
- UINT_MAX (and similar unsigned constants).
+ * config/s390/s390-modes.def (CCAPmode, CCANmode): New CC modes.
+ * config/s390/s390.c (s390_match_ccmode_set): Support new CC modes.
+ (s390_select_ccmode): Likewise.
+ (s390_branch_condition_mask): Likewise.
+ (optimization_options): Do not set flag_branch_on_count.
+ (s390_split_branches): Handle doloop branches.
+ (s390_chunkify_pool): Likewise.
+ * config/s390/s390.md ("*adddi3_imm_cc", "*addsi3_imm_cc"): New insns.
+ ("doloop_end"): New expander.
+ ("doolop_si", "*doloop_si_long", "doloop_di", "*doloop_di_long",
+ associated splitters): New.
-2002-01-22 Janis Johnson <janis187@us.ibm.com>
+2002-09-11 Hartmut Penner <hpenner@de.ibm.com>
- * Makefile.in (loop.o): Depend on OPTABS_H.
- * loop.c (emit_prefetch_instructions): Check the prefetch operand
- against the predicate.
+ * fold-const.c (make_range): Only narrow to signed range if
+ the signed range is smaller than the unsigned range.
- PR target/5379
- * config/i386/i386.md (prefetch_sse): Specify "p" as a constraint
- for the address operand.
+2002-09-12 Alan Modra <amodra@bigpond.net.au>
-2002-01-22 Richard Henderson <rth@redhat.com>
+ * emit-rtl.c (set_mem_size): New function.
+ * expr.h (set_mem_size): Declare.
+ * config/rs6000/rs6000.c (expand_block_move_mem): Exterminate.
+ (expand_block_move): Instead, use adjust_address and
+ replace_equiv_address to generate proper aliasing info.
+ Move common code out of conditionals. Localize vars.
- * config/alpha/freebsd.h (FUNCTION_PROFILER): Remove.
+2002-09-11 Eric Botcazou <ebotcazou@libertysurf.fr>
-2002-01-22 Craig Rodrigues <rodrigc@gcc.gnu.org>
+ * optabs.c (expand_binop): Minor cleanup.
+ (expand_twoval_binop): Convert CONST_INTs like in expand_binop.
- PR other/5450
- * config/i386/sysv4.h (CPP_SPEC): Define, and add CPU
- preprocessor flags.
+2002-09-11 Dan Nicolaescu <dann@ics.uci.edu>
-2002-01-22 Jason Thorpe <thorpej@wasabisystems.com>
+ * print-tree.c (print_node): Print the restrict qualifier.
- * config.gcc (x86_64-*-netbsd*): New target.
- * config/i386/netbsd64.h: New file.
+2002-09-11 Janis Johnson <janis187@us.ibm.com>
-2002-01-22 Aldy Hernandez <aldyh@redhat.com>
+ * doc/install.texi: Fix typos.
- * regrename.c (kill_value): Fix typo.
+2002-09-11 Zack Weinberg <zack@codesourcery.com>
-2002-01-22 Aldy Hernandez <aldyh@redhat.com>
+ * Makefile.in: Remove all references to s-under and underscore.c.
+ * collect2.c, tlink.c: Change all uses of prepends_underscore
+ to look directly at USER_LABEL_PREFIX.
- * doc/tm.texi: Remove STARTING_FRAME_PHASE.
+2002-09-11 David Edelsohn <edelsohn@gnu.org>
- * config/rs6000/rs6000.h: Same.
+ * config/rs6000/rs6000.c (rs6000_xcoff_asm_named_section): Append
+ alignment to csect.
+ (rs6000_xcoff_unique_section): Only set section name for public
+ data.
+ (rs6000_xcoff_section_type_flags): Store log2 alignment in flags.
+ * config/rs6000/xcoff.h (TARGET_ASM_SELECT_SECTION): Remove
+ duplicate definition.
- * function.c (instantiate_virtual_regs): Remove
- STARTING_FRAME_PHASE.
- (assign_stack_local_1): Same.
- Calculate frame phase.
+2002-09-10 John David Anglin <dave@hiauly1.hia.nrc.ca>
-2002-01-22 Nick Clifton <nickc@redhat.com>
+ * pa.md (extzv): Check predicates before emitting extzv_32.
+ (insv): Likewise.
- * config/arm/arm.h (CONDITIONAL_REGISTER_USAGE): Move 'regno'
- variable declaration to outer scope in order to simplify
- future extensions.
- (HARD_REGNO_MODE_OK): Replace macro body with a with a call to
- arm_hard_regno_mode_ok.
- * config/arm/arm-protos.h: Add a prototype for
- arm_hard_regno_mode_ok.
- * config/arm/arm.c (soft_df_operand): Remove now redundant
- check for DImode values using IP_REGNUM.
- (nonimmediate_soft_df_operand): Remove now redundant check for
- DImode values using IP_REGNUM.
- (arm_hard_regno_mode_ok): New function. New check: make sure
- that DImode values are not stored in IP_REGNUM.
+2002-09-10 Ulrich Weigand <uweigand@de.ibm.com>
- * config/arm/arm.c (arm_expand_prologue): Replace REG_MAYBE_DEAD
- note with a USE.
- (thumb_expand_prologue): Replace REG_MAYBE_DEAD note with a USE.
+ * config/s390/s390.h (MOVE_MAX): Define to correct value.
+ (MAX_MOVE_MAX): Define.
+ (MOVE_BY_PIECES_P): Define.
+ (CLEAR_BY_PIECES_P): Define.
-2002-01-22 Jason Merrill <jason@redhat.com>
+2002-09-10 Denis Chertykov <denisc@overta.ru>
- * c-semantics.c (genrtl_compound_stmt): Only check nesting
- consistency if this COMPOUND_STMT is scoped.
+ * config/avr/avr.md (movstrhi): Use right operands for conversion.
-2002-01-22 Kazu Hirata <kazu@hxi.com>
+2002-09-10 Richard Earnshaw <rearnsha@arm.com>
- * predict.c: Fix formatting.
- * print-tree.c: Likewise.
- * protoize.c: Likewise.
- * real.h: Likewise.
- * rtl.h: Likewise.
- * sbitmap.h: Likewise.
- * scan.c: Likewise.
- * sched-deps.c: Likewise.
- * sched-vis.c: Likewise.
- * sdbout.c: Likewise.
- * sibcall.c: Likewise.
- * ssa.c: Likewise.
- * ssa-ccp.c: Likewise.
- * ssa-dce.c: Likewise.
- * stmt.c: Likewise.
- * stor-layout.c: Likewise.
- * system.h: Likewise.
+ PR c/7873
+ * arm.md (insv): Use reg_or_int_operand for operand[3].
-Tue Jan 22 06:26:33 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2002-09-10 David Edelsohn <edelsohn@gnu.org>
- * tree.c (int_fits_type_p): If bounds of a subtype are variable, see
- if fits in bounds of base type.
+ * rs6000.c (rs6000_assemble_visibility): Protect declaration
+ inside macro. Correct function definition typo.
+ (rs6000_xcoff_section_type_flags): New function.
+ (TARGET_SECTION_TYPE_FLAGS): Remove definition.
+ (rs6000_elf_section_type_flags): Call default_section_type_flags_1
+ with appropriate PIC test.
+ (rs6000_xcoff_select_section): Use decl_readonly_section_1 to
+ determine readonly.
+ (rs6000_binds_local_p): Combine PIC flags.
+ * sysv4.h (TARGET_SECTION_TYPE_FLAGS): Define.
+ * xcoff.h (TARGET_SECTION_TYPE_FLAGS): Define.
- * dwarf2out.c (equate_decl_number_to_die): Add "int" to decls.
- (loc_descriptor_from_tree, case CALL_EXPR, case ADDR_EXPR): New.
- (add_bound_info, default): If can't find a context, make a
- SAVE_EXPR.
- (dwarf2out_finish): Check for SAVE_EXPR in node->created_for.
+2002-09-09 Per Bothner <per@bothner.com>
-2002-01-22 Hans-Peter Nilsson <hp@axis.com>
+ * print-tree.c (print_node): In a STRING_CST, escape non-ascii
+ characters, and only print TREE_STRING_LENGTH chars.
- * c-typeck.c (parser_build_binary_op): If result from
- build_binary_op is ERROR_MARK just return error_mark_node without
- further processing.
+2002-09-09 Steve Ellcey <sje@cup.hp.com>
-2002-01-21 Jason Thorpe <thorpej@wasabisystems.com>
+ * config/ia64/hpux.h (TARGET_HPUX_LD): New, define true.
+ (ASM_FILE_END) New.
+ * config/ia64/ia64.h (TARGET_HPUX_LD): New, define false.
+ * config/ia64/ia64-protos.h (ia64_hpux_asm_file_end): New.
+ * config/ia64/ia64.c (ia64_asm_output_external): Create list
+ of external functions if TARGET_HPUX_LD is true.
+ (ia64_hpux_add_extern_decl): New, routine to put names on
+ list of external functions.
+ (ia64_hpux_asm_file_end): Put out declarations for external
+ functions if and only if they are used.
- * config/netbsd.h (TARGET_HAS_F_SETLKW): define.
- Split a.out-specific bits into...
- * config/netbsd-aout.h: ...this.
- * config/netbsd-elf.h: New file.
- * config/alpha/netbsd-elf.h: Remove.
- * config/alpha/netbsd.h: Rewrite for a NetBSD/alpha ELF target.
- * config/i386/netbsd-elf.h (LIB_SPEC): Remove.
- (STARTFILE_SPEC): Remove redundant definition.
- (ENDFILE_SPEC): Likewise.
- (LINK_SPEC): Likewise.
- (CPP_SPEC): Likewise.
- (ASM_SPEC): Likewise.
- (LIB_SPEC): Likewise.
- (SWITCH_TAKES_ARG): Likewise.
- (TARGET_MEM_FUNCTIONS): Likewise.
- (CPP_PREDEFINES): Redefine.
- (ASM_FINAL_SPEC): Remove redefinition.
- (ASM_COMMENT_START): Redefine.
- (FUNCTION_PROFILER): Define.
- (TARGET_VERSION): Redefine.
- Comment and formatting cleanup.
- * config/i386/netbsd.h: Include <netbsd-aout.h>.
- * config/m68k/netbsd.h: Include <netbsd-aout.h>.
- * config/mips/netbsd.h: Rewrite for NetBSD/mips ELF target,
- big- or little-endian.
- * config/ns32k/netbsd.h: Include <netbsd-aout.h>.
- * config.gcc (*-*-netbsd*): Add definitions common to all
- NetBSD configs.
- (alpha*-*-netbsd*): Remove redundant xm_defines, gas, and
- gnu_ld definitions. Add netbsd-elf.h to and remove
- alpha/netbsd-elf.h from tm_file. Remove alpha/t-crtfm from
- tmake_file, and don't lose previous tmake_file contents.
- (arm*-*-netbsd*): Add netbsd-aout.h to tm_file.
- (i[34567]86-*-netbsdelf*): Remove redundant xm_defines, gas, and
- gnu_ld definitions. Add netbsd-elf.h to tm_file.
- (mips-dec-netbsd*): Remove as alias for mipsel-*-netbsd*.
- (mipsel-*-netbsd*): Rename this to...
- (mips*-*-netbsd*): ...this. Add elfos.h to tm_file. Add
- mips/little.h to tm_file for mips*el-*.
- (powerpc-*-netbsd*): Remove redundant xm_defines definition.
- (sparc-*-netbsd*): Add netbsd-aout.h to tm_file.
- (vax-*-netbsd*): Add netbsd-aout.h to tm_file.
-
-2002-01-21 John David Anglin <dave@hiauly1.hia.nrc.ca>
-
- * pa-protos.h (reg_before_reload_operand): New function prototype.
- * pa.c (reg_before_reload_operand): New function implementation.
- * pa.md (decrement_and_branch_until_zero, movb): Use it. Change "!*m"
- contraints to "*m".
-
-2002-01-21 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
-
- * combine.c (simplify_and_const_int): Properly sign-extend CONSTOP.
-
-2002-01-21 John David Anglin <dave@hiauly1.hia.nrc.ca>
-
- * pa64-hpux.h (MD_EXEC_PREFIX): Set to "/usr/ccs/bin".
- (MD_STARTFILE_PREFIX): Set to "/usr/ccs/lib/pa20_64/".
- (MD_STARTFILE_PREFIX_1): Set to "/opt/langtools/lib/pa20_64/".
- (EH_FRAME_IN_DATA_SECTION): Define and update comment on init sections.
- (ENDFILE_SPEC): Undefine.
- (STARTFILE_SPEC): Redefine for PA.
-
-2002-01-21 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
-
- * config/rs6000/t-ppccomm (CRTSTUFF_T_CFLAGS_S): Re-add -fPIC.
-
-2002-01-21 Daniel Jacobowitz <drow@mvista.com>
-
- * config.gcc: Add entries to supported PowerPC --with-cpu
- types.
-
-2002-01-21 Jakub Jelinek <jakub@redhat.com>
-
- * config/i386/i386.c (ix86_function_arg_regno_p): Never return
- true for 64-bit mode only SSE registers in 32-bit mode.
-
-2002-01-21 Kazu Hirata <kazu@hxi.com>
-
- * unwind-dw2.c: Fix formatting.
- * unwind-dw2-fde.c: Likewise.
- * unwind-dw2-fde.h: Likewise.
- * unwind-pe.h: Likewise.
- * varasm.c: Likewise.
- * varray.h: Likewise.
-
-2002-01-21 Hans-Peter Nilsson <hp@bitrange.com>
-
- Remove workaround for register stack overwrite bug in mmix.
- * config/mmix/mmix.c (mmix_target_asm_function_prologue): Remove
- support for TARGET_REG_STACK_FILL_BUG.
- * config/mmix/mmix.h: Remove member has_call_without_parameters.
- (TARGET_MASK_REG_STACK_FILL_BUG, TARGET_REG_STACK_FILL_BUG):
- Delete.
- (TARGET_DEFAULT): Remove TARGET_MASK_REG_STACK_FILL_BUG.
- (TARGET_SWITCHES): Remove -mreg-stack-fill-bug-workaround and
- -mno-reg-stack-fill-bug-workaround.
- * config/mmix/mmix.md ("call", "call_value"): Don't set struct
- machine member has_call_without_parameters.
- * doc/invoke.texi (Option Summary) <MMIX Options>: Remove
- -mreg-stack-fill-bug-workaround and
- -mno-reg-stack-fill-bug-workaround.
- (MMIX Options): Ditto.
-
-2002-01-21 Kazu Hirata <kazu@hxi.com>
-
- * config/h8300/h8300.c (function_arg): Replace 0 with NULL_RTX
- as appropriate.
- Remove redundant code.
+2002-09-09 John David Anglin <dave@hiauly1.hia.nrc.ca>
-2002-01-21 Joseph S. Myers <jsm28@cam.ac.uk>
+ * pa.md (exception_receiver, builtin_setjmp_receiver): Add blockage
+ on TARGET_64BIT before pic register restore.
- * config/alpha/alpha.h, config/arc/arc.h, config/avr/avr.h,
- config/c4x/c4x.h, config/d30v/d30v.h, config/dsp16xx/dsp16xx.h,
- config/fr30/fr30.h, config/ia64/ia64.h, config/m68hc11/m68hc11.h,
- config/mips/mips.h, config/rs6000/rs6000.h, config/sparc/sparc.h,
- config/stormy16/stormy16.h, config/v850/v850.h: Remove commented
- out target macro definitions and non-target-specific comments
- mostly taken from old versions of the manual.
+2002-09-09 David Edelsohn <edelsohn@gnu.org>
-2002-01-20 Kazu Hirata <kazu@hxi.com>
+ * doc/tm.texi (TARGET_HAVE_SRODATA_SECTION): New description.
+ (TARGET_HAVE_TLS): New description.
- * config/h8300/h8300.h: Fix comment formatting.
- * config/ia64/aix.h: Likewise.
- * config/ia64/ia64-protos.h: Likewise.
- * config/ia64/ia64.c: Likewise.
- * config/ia64/ia64.h: Likewise.
- * config/ia64/ia64intrin.h: Likewise.
- * config/ia64/linux.h: Likewise.
- * config/ia64/unwind-aix.c: Likewise.
- * config/ia64/unwind-ia64.c: Likewise.
+2002-09-09 Janis Johnson <janis187@us.ibm.com>
-2002-01-20 Kazu Hirata <kazu@hxi.com>
+ * doc/extend.texi (Statement Exprs): Fix broken link.
- * config/h8300/h8300.c: Revise comments about shift code.
+2002-09-09 Denis Chertykov <denisc@overta.ru>
-2002-01-20 Kazu Hirata <kazu@hxi.com>
+ * config/avr/avr.md (movstrhi, clrstrhi): Use gen_int_mode for
+ right conversion of operands[1].
- * config/h8300/h8300.c (function_arg): Update a comment.
+2002-09-09 Ulrich Weigand <uweigand@de.ibm.com>
-2002-01-20 Kazu Hirata <kazu@hxi.com>
+ * config/s390/s390.md ("*tmdi_reg", "*tmsi_reg"): Do not mark as
+ commutative. Use "nonimmediate_operand" instead of "register_operand"
+ as predicate for operand 0. Move to after the "*tmXX_mem" insns.
- * config/h8300/h8300.md: Update the comments at the beginning
- of the file.
+ ("*tmdi_mem", "*tmsi_mem", "*tmhi_mem", "*tmqi_mem"): Do not mark
+ as commutative.
-2002-01-20 Kazu Hirata <kazu@hxi.com>
+ ("*anddi3_ni", "*andsi3_ni", "*iordi3_ni", "*iorsi3_ni"): Do not
+ mark as commutative. Use "nonimmediate_operand" instead of
+ "register_operand" as predicate for operand 1.
- * config/i370/i370.c: Fix comment formatting.
- * config/i370/i370.h: Likewise.
- * config/i370/i370.md: Likewise.
- * config/i370/linux.h: Likewise.
+ ("movstrictsi"): Fix typo in insn name.
-Sun Jan 20 18:40:14 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2002-09-09 Jan Hubicka <jh@suse.cz>
- * reg-stack.c (subst_stack_regs): Properly check for deleted insn.
+ * i386.c (index_register_operand): New.
+ * i386.h (predicate_codes): Add new predicate.
+ * i386.md (lea_general_*): Use index_register_operand
+ (ashift to lea splitter): Do not produce invalid leas
+ (ashift to mov+ashift split): New.
- * dwarf2out.c (loc_descriptor_from_tree): Add TRUTH_*_EXPR cases.
- (gen_struct_or_union_type_die): Don't SIGSEGV if no TYPE_STUB_DECL
- in incomplete case.
+2002-09-09 Nick Clifton <nickc@redhat.com>
-2002-01-20 Graham Stott <grahams@redhat.com>
+ * config/fr30/fr30.c (output.h): Move after inclusion of tree.h.
+ Fix folding marks.
- * cfgloop.c (flow_loop_preheader_scan): Fix typo.
+2002-09-09 Toshiyasu Morita <toshiyasu.morita@hsa.hitachi.com>
+ J"orn Rennecke <joern.rennecke@superh.com>
-2002-01-19 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ * sh/sh.h (OVERRIDE_OPTIONS): align_functions is in bytes, not bits.
- * config.gcc (hppa*64*-*-hpux11*): Fix tmake_file.
+2002-09-09 Alan Modra <amodra@bigpond.net.au>
-2002-01-19 Tom Rix <trix@redhat.com>
+ * config/rs6000/rs6000.c (rs6000_binds_local_p): Return bool.
+ (function_ok_for_sibcall): Use binds_local_p. Respect longcall
+ attributes.
- * config/rs6000/rs6000.md: Fix DF split for 64 bit hosts.
+2002-09-08 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-01-18 Aldy Hernandez <aldyh@redhat.com>
+ * fr30.c (fr30_print_operand): Fix bug in output of CONST_DOUBLE.
- * doc/tm.texi (STARTING_FRAME_PHASE): Document.
+2002-09-08 Richard Henderson <rth@redhat.com>
- * function.c (assign_stack_local_1): Adjust x_frame_offset with
- STARTING_FRAME_PHASE.
- (STARTING_FRAME_PHASE): New.
- (instantiate_virtual_regs): Check saneness of
- STARTING_FRAME_PHASE.
+ * dwarf2.h (DW_OP_call_ref): Rename from DW_OP_calli.
+ (DW_OP_GNU_push_tls_address): New.
+ (DW_OP_lo_user): Fix.
+ * dwarf2out.c (INTERNAL_DW_OP_tls_addr): New.
+ (dwarf_stack_op_name): Handle it, plus other dwarf3 opcodes.
+ (size_of_loc_descr): Likewise.
+ (output_loc_operands): Handle INTERNAL_DW_OP_tls_addr.
+ (add_AT_location_description): Take a dw_loc_descr_ref not an rtx.
+ (loc_descriptor_from_tree): Handle TLS variables.
+ (rtl_for_decl_location): Do avoid_constant_pool_reference here ...
+ (add_location_or_const_value_attribute): ... not here. Defer
+ to loc_descriptor_from_tree for TLS variables.
- * config/rs6000/rs6000.h (STARTING_FRAME_PHASE): New.
+ * config/i386/i386.h (ASM_OUTPUT_DWARF_DTPREL): New.
+ * config/i386/i386.c (i386_output_dwarf_dtprel): New.
+ * config/i386/i386-protos.h: Update.
-2002-01-19 Alexandre Oliva <aoliva@redhat.com>
+2002-09-08 Roger Sayle <roger@eyesopen.com>
- * config/sh/sh.md (movdf_i4 split): Fix alter_subreg calls.
+ PR optimization/6405
+ * unroll.c (loop_iterations): last_loop_insn should be the previous
+ non-note instruction before loop->end.
+ * loop.c (strength_reduce): The conditional jump is the last
+ non-note instruction before loop->end (as above).
-2002-01-18 Craig Rodrigues <rodrigc@gcc.gnu.org>
+2002-09-08 Roger Sayle <roger@eyesopen.com>
- * doc/install.texi (hppa*-hp-hpux11): Clarify that GCC 2.95.x cannot
- be used for bootstrapping GCC 3.0.
+ * combine.c (try_combine): Handle the case that undobuf.other_insn
+ has been turned into a return or unconditional jump, by inserting
+ a BARRIER if necessary.
+ (simplify_set): Test if a condition code setter has a constant
+ comparison at compile time, if so convert this insn to a no-op move
+ and update/simplify the condition code user (undobuf.other_insn).
-2002-01-18 Kazu Hirata <kazu@hxi.com>
+2002-09-08 Krister Walfridsson <cato@df.lth.se>
- * config/h8300/h8300.md: Fix an insn length.
+ * config/arm/netbsd.h (INITIALIZE_TRAMPOLINE): Redefine.
+ (CLEAR_INSN_CACHE): Define.
-2002-01-18 Kazu Hirata <kazu@hxi.com>
+2002-09-08 Kazu Hirata <kazu@cs.umass.edu>
- * bitmap.h: Fix comment formatting.
- * combine.c: Likewise.
- * cppfiles.c: Likewise.
- * c-pragma.h: Likewise.
- * c-typeck.c: Likewise.
- * df.c: Likewise.
- * dwarf2out.c: Likewise.
- * function.c: Likewise.
- * gcc.c: Likewise.
+ * basic-block.h: Fix comment formatting.
+ * c-common.c: Likewise.
+ * c-common.h: Likewise.
+ * c-lex.c: Likewise.
+ * c-pretty-print.c: Likewise.
+ * cfglayout.c: Likewise.
+ * cfgloop.c: Likewise.
+ * defaults.h: Likewise.
+ * et-forest.c: Likewise.
+ * explow.c: Likewise.
+ * function.h: Likewise.
+ * gcov.c: Likewise.
* genattrtab.c: Likewise.
- * gthr-win32.h: Likewise.
- * haifa-sched.c: Likewise.
- * predict.c: Likewise.
- * rtlanal.c: Likewise.
+ * gengtype.c: Likewise.
+ * ifcvt.c: Likewise.
+ * libgcc2.c: Likewise.
+ * loop.c: Likewise.
+ * profile.c: Likewise.
+ * ra-build.c: Likewise.
+ * real.c: Likewise.
* rtl.h: Likewise.
- * unwind-dw2-fde.h: Likewise.
- * unwind-pe.h: Likewise.
- * vmsdbgout.c: Likewise.
+ * tracer.c: Likewise.
+ * tree-inline.c: Likewise.
+ * varasm.c: Likewise.
-Thu Jan 17 15:28:26 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2002-09-08 Jan Hubicka <jh@suse.cz>
- * attribs.c (decl_attributes): Clear ATTR_FLAG_TYPE_IN_PLACE
- if type_required and passed decl.
+ * emit-rtl.c (set_mem_attributes_minus_bitpos): Fix array_ref
+ handling.
-2002-01-17 Aldy Hernandez <aldyh@redhat.com>
+ * loop.c (loop_givs_reduce): Emit addition after.
- * config.gcc (cpu_type): Include altivec.h in powerpc
- extra_headers.
- Same for darwin.
+2002-09-08 Alan Modra <amodra@bigpond.net.au>
- * config/rs6000/altivec.h: New.
+ * varasm.c (default_assemble_visibility): Rename from
+ assemble_visibility.
+ * output.h: Here too.
+ * target-def.h (TARGET_ASM_ASSEMBLE_VISIBILITY): And here.
+ * config/rs6000/rs6000.c (rs6000_assemble_visibility): And here.
-2002-01-17 David Edelsohn <edelsohn@gnu.org>
+2002-09-08 Alan Modra <amodra@bigpond.net.au>
- * doc/install.texi (*-ibm-aix*): Update assembler and exception
- handling information.
- * doc/trouble.texi (Interoperation): Add libstdc++ information
- for AIX.
- (Misunderstandings): Add template instantiation and static template
- member information for AIX.
+ * reload.c (find_reloads <p constraint>): Pass operand_mode to
+ find_reloads_address.
-2002-01-17 Jason Merrill <jason@redhat.com>
+2002-09-08 Kazu Hirata <kazu@cs.umass.edu>
- * dbxout.c (dbxout_type): Support const and volatile.
+ * config/h8300/h8300.md (udivmodqi4): Enable on H8/300.
+ (anonymous pattern): Likewise.
- * except.c (add_partial_entry): Remove backwards compatibility code.
- (end_protect_partials): Likewise.
+2002-09-07 Scott Snyder <snyder@fnal.gov>
-2002-01-17 Jakub Jelinek <jakub@redhat.com>
+ PR target/7374
+ * config/alpha/alpha.md (abstf2): Fix typo: 'neg' for 'abs'.
- * config/ia64/ia64.md (prologue_use): New.
- * config/ia64/ia64.c (ia64_expand_prologue): Use
- gen_prologue_use instead of gen_rtx_USE.
- (group_barrier_needed_p): Handle CODE_FOR_prologue_use the same way
- as CODE_FOR_pred_rel_mutex.
- (ia64_sched_reorder2): Likewise.
+2002-09-07 Roger Sayle <roger@eyesopen.com>
-2002-01-16 Eric Christopher <echristo@redhat.com>
+ * basic-block.h (struct loop): Remove unused cont_dominator field.
- * config/mips/r3900.h: Reformat.
- (SUBTARGET_CPP_SIZE_SPEC): Remove.
- * config/mips/isa3264.h (SUBTARGET_CPP_SIZE_SPEC): Ditto.
- * config/mips/mips.h (ABI_GAS_ASM_SPEC): Default to "".
- (SUBTARGET_CPP_SIZE_SPEC): Rewrite.
- * config/mips/t-elf: Remove mips3 multilib.
+2002-09-07 Igor Shevlyakov <igor@microunity.com>
-2002-01-16 H.J. Lu <hjl@gnu.org>
+ * varasm.c (decode_rtx_const): Don't check undefined field for
+ CONST_VECTOR.
- * config/mips/linux.h: Include "mips/abi64.h".
+2002-09-07 Glen Nakamura <glen@imodulo.com>
-2002-01-16 H.J. Lu <hjl@gnu.org>
+ PR opt/7814
+ * sched-deps.c (sched_analyze_insn): Make sure to add insn
+ to reg_last->sets after flushing the dependency lists to guarantee
+ that subsequent clobbers will be dependent on it.
- * config/mips/t-linux: New.
+2002-09-07 Igor Shevlyakov <igor@microunity.com>
- * config.gcc: Add mips/t-linux to tmake_file for mips*-*-linux*.
+ * combine.c (simplify_shift_const): Calculate rotate count
+ correctly for vector operands.
- * config/mips/linux.h: Don't include "gofast.h".
- (INIT_SUBTARGET_OPTABS): Removed.
+2002-09-07 Ansgar Esztermann <ansgar@thphy.uni-duesseldorf.de>
-2002-01-16 Kazu Hirata <kazu@hxi.com>
+ * c-typeck.c (c_tree_expr_nonnegative_p): New function.
+ (build_binary_op): Call c_tree_expr_nonnegative_p rather than
+ tree_expr_nonnegative_p.
+ (build_conditional_expr): Likewise.
+ * c-tree.h (c_tree_expr_nonnegative_p): Declare.
- * config/h8300/h8300-protos.h: Replace emit_a_shift with
- output_a_shift.
- * config/h8300/h8300.c: Likewise.
+2002-09-07 Richard Henderson <rth@redhat.com>
+
+ * builtins.def (inf, inff, infl): Mark const.
+ (huge_val, huge_valf, huge_vall): Likewise.
+ (BUILT_IN_GETEXP, BUILT_IN_GETMAN): Remove.
+
+ * real.c (ereal_inf): Clear E before use.
+
+2002-09-07 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/h8300.md (udivmodqi4): Split the pattern into
+ an expander and an anonymous pattern. Zero out the upper half
+ of the dividend in the expander.
+ (udivmodqi4): Likewise.
+
+2002-09-07 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/h8300.c: Fix formatting.
+ * config/h8300/h8300.h: Likewise.
* config/h8300/h8300.md: Likewise.
-2002-01-16 Kazu Hirata <kazu@hxi.com>
+2002-09-07 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
- * config/h8300/h8300.md (pushqi1_h8300): Use a tab instead of
- spaces after an opcode name.
- (pushqi1_h8300hs): Likewise.
- (pushhi1_h8300hs): Likewise.
+ * cfgcleanup.c (try_crossjump_to_edge): Fix updating of liveness
+ information.
-2002-01-16 Kazu Hirata <kazu@hxi.com>
+2002-09-07 Graham Stott <graham.stott@btinternet.com>
- * doc/extend.texi: Replace "option" with "attribute"
- appropriately.
+ * rtlanal.c (dead_or_set_regno_p): Fix typo.
-2002-01-16 Jakub Jelinek <jakub@redhat.com>
+2002-09-07 Alan Modra <amodra@bigpond.net.au>
- * config/alpha/alpha.c (some_small_symbolic_mem_operand): Look into
- (and:DI () (const_int -8)).
- (split_small_symbolic_mem_operand): Split
- (mem (and:DI () (const_int -8)).
+ * config/rs6000/linux64.h (ASM_PREFERRED_EH_DATA_FORMAT): Define.
-2002-01-16 Jakub Jelinek <jakub@redhat.com>
+ * doc/tm.texi (TARGET_ASM_ASSEMBLE_VISIBILITY): Describe.
+ * target-def.h (TARGET_ASM_ASSEMBLE_VISIBILITY): Define.
+ (TARGET_ASM_OUT): Add the above here.
+ * target.h (struct gcc_target): Add "visibility" field.
+ * varasm.c (maybe_assemble_visibility): Call targetm visibility func.
+ * config/rs6000/rs6000.c (rs6000_assemble_visibility): New function.
+ (TARGET_ASM_ASSEMBLE_VISIBILITY): Define.
+ (rs6000_legitimize_reload_address, first_reg_to_save): Formatting.
+
+2002-09-06 Ziemowit Laski <zlaski@apple.com>
+
+ * c-lang.c (objc_is_id): New stub.
+ * c-tree.h (objc_is_id): New forward declaration.
+ * c-typeck.c (build_c_cast): Do not strip protocol
+ qualifiers from 'id' type.
+ * objc/objc-act.c (objc_comptypes): Correct handling
+ of protocol qualifiers.
+ (objc_is_id): New.
+
+2002-09-06 Jeffrey A Law (law@redhat.com)
+
+ * pentium.md (pentium-firstvboth): Fix typo.
+
+2002-09-06 Dhananjay Deshpande <dhananjayd@kpit.com>
+
+ * h8300.c (enum shift_alg): Move to earlier in h8300.c.
+ (enum shift_type, enum h8_cpu): Likewise.
+ (INL, ROT, LOP, SPC macros): Likewise.
+ (shift_alg_qi, shift_alg_hi, shift_alg_si): Likewise. Lose
+ const designator.
+ (h8300_init_once): Update shift_alg_{qi,hi,si} to use more
+ space efficient algorithms when optimize for codesize.
+
+2002-09-06 Nicola Pero <n.pero@mi.flashnet.it>
+
+ Fix PR/1727 and long-standing failing testcase
+ objc/formal-protocol-6.m.
+ * objc-act.c (build_protocol_expr): If compiling for the GNU
+ runtime, create a list of Protocol statically allocated instances
+ if it doesn't exist, then add the Protocol object to this same
+ list.
+ (get_objc_string_decl): Fixed typo/bug - TREE_VALUE had been used
+ instead of TREE_CHAIN.
+
+2002-09-06 Nicola Pero <n.pero@mi.flashnet.it>
+
+ * objc/objc-act.c (dump_interface): Enlarged the char * buffer to
+ 10k. Fixed category dumping - print out category names with the
+ proper syntax. Print '@end\n' and not '\n@end' at the end of the
+ interface.
+ (finish_objc): Fixed the -gen-decls option. It was printing out
+ only the last class. Dump an interface declaration of all classes
+ being compiled instead.
+
+2002-09-06 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/arm/arm-protos.h (arm_gen_return_addr_mask): New
+ prototype.
+ * config/arm/arm.c (arm_gen_return_addr_mask): New function.
+ * config/arm/arm.h (MASK_RETURN_ADDR): Use arm_gen_return_addr_mask
+ if not APCS26 and not Thumb or ARMv4-or-higher. Use gen_int_mode
+ rather than GEN_INT.
+ * config/arm/arm.md (UNSPEC_CHECK_ARCH): Define.
+ (return_addr_mask, *check_arch2): New.
+
+2002-09-06 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.md ("*adddi3_cc", "*adddi3_cconly",
+ "*adddi3_cconly2", "*adddi3_64", "*adddi3_31", "adddi3",
+ "*addsi3_carry1_cc", "*addsi3_carry1_cconly",
+ "*addsi3_carry2_cc", "*addsi3_carry2_cconly",
+ "*addsi3_cc", "*addsi3_cconly", "*addsi3_cconly2", "addsi3",
+ "adddf3", "*adddf3", "*adddf3_ibm",
+ "addsf3", "*addsf3", "*addsf3_ibm",
+ "muldi3", "mulsi3", "mulsidi3",
+ "muldf3", "*muldf3", "*muldf3_ibm",
+ "mulsf3", "*mulsf3", "*mulsf3_ibm",
+ "*anddi3_cc", "*anddi3_cconly", "anddi3",
+ "*andsi3_cc", "*andsi3_cconly", "andsi3",
+ "*iordi3_cc", "*iordi3_cconly", "iordi3",
+ "*iorsi3_cc", "*iorsi3_cconly", "iorsi3",
+ "*xordi3_cc", "*xordi3_cconly", "xordi3",
+ "*xorsi3_cc", "*xorsi3_cconly", "xorsi3"): Use "nonimmediate_operand"
+ instead of "register_operand" as predicate for "%0" operand.
- PR target/5309:
- * config/sparc/sparc.c (ultrasparc_adjust_cost): Handle TYPE_IDIV the
- same way as TYPE_IMUL.
- (ultrasparc_sched_reorder): Likewise.
- * config/sparc/sparc.md (type): Add comment to update
- ultrasparc_sched_reorder when making changes.
+2002-09-06 Jakub Jelinek <jakub@redhat.com>
-2002-01-16 Kazu Hirata <kazu@hxi.com>
+ * configure.in (HAVE_AS_OFFSETABLE_LO10): Use -xarch=v9
+ unconditionally when gcc_cv_as_flags64 checks are gone.
+ * configure: Rebuilt.
- * doc/invoke.texi: Change the dump file name of block
- reordering pass from 28.bbro to 29.bbro.
- Mention -dk option.
+2002-09-06 Alan Modra <amodra@bigpond.net.au>
-Wed Jan 16 17:54:22 CET 2002 Jan Hubicka <jh@suse.cz>
+ * config/rs6000/rs6000.md (extzvsi_internal2): Revert most of
+ 2002-07-26 change. Comment.
- * i386.md (minsf splitter): Fix pasto.
+2002-09-05 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-01-16 Nick Clifton <nickc@cambridge.redhat.com>
+ * frv.c (frv_unique_section, frv_select_section,
+ frv_select_rtx_section): Delete.
+ (frv_in_small_data_p): New.
+ (TARGET_ASM_UNIQUE_SECTION, TARGET_ASM_SELECT_SECTION,
+ TARGET_ASM_SELECT_RTX_SECTION): Delete.
+ (TARGET_IN_SMALL_DATA_P): Define.
- * config/arm/arm.c (arm_expand_prologue): Add REG_MAYBE_DEAD note
- to frame pointer initialisation instruction.
- (thumb_expand_prologue): Add REG_MAYBE_DEAD note to frame pointer
- initialisation instruction.
- (soft_df_operand): Do not accept the IP register.
- (nonimmediate_soft_df_operand): Do not accept the IP register.
+2002-09-05 Dale Johannesen <dalej@apple.com>
-2002-01-16 Jakub Jelinek <jakub@redhat.com>
+ * reload1.c (reload): Retain only those memory clobbers
+ added for variable-array handling.
- PR target/5357:
- * config/sparc/sparc.c (sparc_override_options): Avoid MASK_V9 and
- MASK_V8 being both set.
+2002-09-05 Jason Thorpe <thorpej@wasabisystems.com>
-2002-01-16 Ulrich Weigand <uweigand@de.ibm.com>
+ * config/arm/arm.c (arm_return_in_memory): Implement ATPCS
+ return-in-memory rules.
+ * config/arm/arm.h (ARM_FLAG_ATPCS, TARGET_ATPCS): Define.
- * config/s390/s390.c (s390_emit_prologue): Do not emit USE
- insn for GOT register; add REG_MAYBE_DEAD notes instead.
- config/s390/s390.md (call, call_value): Add GOT register to
- CALL_INSN_FUNCTION_USAGE where needed.
- (call_exp, call_value_exp): New.
+2002-09-05 David Edelsohn <edelsohn@gnu.org>
-2002-01-16 Nick Clifton <nickc@cambridge.redhat.com>
+ * config/rs6000/xcoff.h (HOT_TEXT_SECTION_NAME): Delete.
+ (UNLIKELY_EXECUTED_TEXT_SECTION_NAME): Delete.
- * config/arm/arm.c: General formatting tidy up.
+2002-09-05 Jason Thorpe <thorpej@wasabisystems.com>
-2002-01-16 Graham Stott <grahams@redhat.com>
+ * real.c: Avoid parse error if FLOAT_WORDS_BIG_ENDIAN is
+ not a compile-time constant for the non-IBM case.
+ * config/arm/arm-protos.h (arm_float_words_big_endian): New
+ prototype.
+ * config/arm/arm.c (arm_float_words_big_endian): New function.
+ * config/arm/arm.h (TARGET_CPU_CPP_BUILTINS): Define __VFP_FP__
+ if TARGET_VFP and not TARGET_HARD_FLOAT.
+ (ARM_FLAG_VFP, TARGET_VFP): Define.
+ (FLOAT_WORDS_BIG_ENDIAN): Use arm_float_words_big_endian.
- * calls.c (try_to_integrate): Use "(size_t)" intermediate
- cast and when casting an integer literal to "rtx" pointer.
- (expand_call): Likewise.
- * flow.c (try_pre_increment): Likewise.
- (find_use_as_address): Likewise.
- * integrate.c (expand_iline_function): Likewise.
- * regmove.c (try_auto_increment): Likewise.
+2002-09-05 David Edelsohn <edelsohn@gnu.org>
-2002-01-16 Graham Stott <grahams@redhat.com>
+ * doc/install.texi: Correct text of s390-*-linux* and s390x-*-linux*
+ URLs. Fix AIX wording.
- * sched-rgn.c (passed): Use sbitmap_free.
- (header): Likewise.
- (inner): Likewise.
- (in_queue): Likewise.
- (in_stack): Likewise.
+2002-09-05 Stan Shebs <shebs@apple.com>
-2002-01-15 Eric Christopher <echristo@redhat.com>
+ * config/rs6000/rs6000.c (rs6000_override_options): Make -fpic and
+ -fPIC equivalent on Darwin.
- * flow.c (propagate_one_insn): Change to use fatal_insn.
+2002-09-05 J"orn Rennecke <joern.rennecke@superh.com>
-2002-01-15 Kazu Hirata <kazu@hxi.com>
+ * sh.c (sh_expand_builtin): Return early if encountering an
+ error_mark for a type.
- * expmed.c (extract_fixed_bit_field): Remove unused code.
- * system.h: Poison SLOW_ZERO_EXTEND.
- * doc/tm.texi: Remove.
- * config/1750a/1750a.h (SLOW_ZERO_EXTEND): Remove.
- * config/arm/arm.h: Likewise.
- * config/avr/avr.h: Likewise.
- * config/clipper/clipper.h: Likewise.
- * config/convex/convex.h: Likewise.
- * config/d30v/d30v.h: Likewise.
- * config/dsp16xx/dsp16xx.h: Likewise.
- * config/elxsi/elxsi.h: Likewise.
- * config/fr30/fr30.h: Likewise.
+2002-09-05 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.c (s390_expand_plus_operand): Do not require
+ double-word scratch register.
+ config/s390/s390.md ("reload_indi", "reload_insi"): Adapt.
+
+ ("*tmqi_ext", "*tmdi_mem", "*tmsi_mem", "*tmhi_mem", "*tmqi_mem",
+ "*cli"): Replace s_operand by memory_operand.
+ ("cmpstrdi", "cmpstrsi"): Replace s_operand by general_operand.
+
+2002-09-05 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/h8300.c (asm_file_start): Add a missing
+ semicolon.
+
+2002-09-04 Krister Walfridsson <cato@df.lth.se>
+
+ * config/i386/i386.h (GOT_SYMBOL_NAME): Define.
+ * config/i386/i386.c (output_set_got): Use GOT_SYMBOL_NAME.
+ (ix86_output_addr_diff_elt) Likewise.
+ (x86_output_mi_thunk) Likewise.
+ * config/i386/netbsd.h (GOT_SYMBOL_NAME): Redefine.
+
+2002-09-04 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * frv.c (frv_encode_section_info): Fix error in last change.
+
+2002-09-04 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.c (rs6000_flag_pic): New variable.
+ (rs6000_elf_encode_section_info): ATTRIBUTE_UNUSED.
+ (TARGET_BINDS_LOCAL_P): Define.
+ (rs6000_override_options): Save original flag_pic value.
+ (rs6000_elf_select_section): Call default_elf_select_section_1.
+ (rs6000_elf_unique_section): Call default_unique_section_1.
+ (rs6000_elf_in_small_data_p): New function.
+ (rs6000_xcoff_asm_named_section): Determine storage mapping class.
+ (rs6000_xcoff_select_section): Update based on defaults.
+ (rs6000_xcoff_unique_section): Set to basic name if not common.
+ (rs6000_binds_local_p): New function.
+ * config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS): Set
+ targetm.have_srodata_section if SDATA_EABI.
+ (TARGET_IN_SMALL_DATA_P): Define.
+
+2002-09-04 Dale Johannesen <dalej@apple.com>
+
+ * varasm.c (struct rtx_const, decode_rtx_const):
+ Make veclo and vechi fields not share storage.
+
+2002-09-05 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * loop.c (scan_loop): Don't mark separate insns out of a libcall
+ for moving.
+ (move_movables): Abort if we see the first insn of a libcall.
+
+2002-09-04 Richard Henderson <rth@redhat.com>
+
+ * builtin-types.def (BT_FN_FLOAT): New.
+ (BT_FN_DOUBLE, BT_FN_LONG_DOUBLE): New.
+ * builtins.def (BUILT_IN_INF, BUILT_IN_INFF, BUILT_IN_INFL,
+ BUILT_IN_HUGE_VAL, BUILT_IN_HUGE_VALF, BUILT_IN_HUGE_VALL): New.
+ * builtins.c (fold_builtin_inf): New.
+ (fold_builtin): Call it.
+ * real.c (ereal_inf): New.
+ * real.h: Declare it.
+ * doc/extend.texi: Document new builtins.
+
+2002-09-04 Richard Henderson <rth@redhat.com>
+
+ * cse.c (cse_insn): Avoid subreg games if the equivalence
+ is already in the proper mode.
+
+2002-09-04 Eric Botcazou <ebotcazou@multimania.com>
+
+ PR c/7102
+ * optabs.c (expand_binop): Convert CONST_INTs in all cases.
+
+2002-09-04 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.md (setccfp0, setccfp1): New patterns.
+
+2002-09-04 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * frv-protos.h (frv_init_builtins, frv_expand_builtin,
+ frv_select_section, frv_select_rtx_section,
+ frv_encode_section_info, frv_unique_section): Delete.
+ * frv.c: Update for target hooks.
+ * frv.h (STRIP_NAME_ENCODING, SLOW_ZERO_EXTEND, SELECT_SECTION,
+ SELECT_RTX_SECTION, ENCODE_SECTION_INFO, UNIQUE_SECTION,
+ EASY_DIV_EXPR, MD_INIT_BUILTINS, MD_EXPAND_BUILTIN): Delete.
+
+2002-09-04 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * ip2k-protos.h (function_prologue, function_epilogue,
+ encode_section_info): Update to match target hook specification.
+ * ip2k.c: Wrap `MDR' code in IP2K_MD_REORG_PASS.
+ (function_prologue, function_epilogue, encode_section_info):
+ Update to match target hook specification.
+ * ip2k.h (SELECT_SECTION, SELECT_RTX_SECTION, ASM_OPEN_PAREN,
+ ASM_CLOSE_PAREN, EASY_DIV_EXPR): Delete.
+ (NOTICE_UPDATE_CC): Cast to void.
+ * ip2k.md: Add defaults in switch statements.
+
+2002-09-04 Janis Johnson <janis187@us.ibm.com>
+
+ * doc/trouble.texi (Interoperation): Update information about C++ ABI
+ issues.
+
+2002-09-04 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/sparc/t-netbsd64: Disable multilib for now.
+
+2002-09-04 David Edelsohn <edelsohn@gnu.org>
+
+ * target-def.h (TARGET_HAVE_SRODATA_SECTION): New macro.
+ * target.h (gcc_target): Add have_srodata_section member.
+ * varasm.c (section_category): Add SECCAT_SRODATA.
+ (categorize_decl_for_section): Return SECCAT_SRODATA for sdata if
+ READONLY_SDATA_SECTION defined.
+ (decl_readonly_section_1): True for SECCAT_SRODATA also.
+ (default_elf_select_section_1): Map SECCAT_SRODATA to .sdata2.
+ (default_unique_section_1): Likewise.
+
+2002-09-04 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * expr.c (emit_group_load): Revise to allow splitting TCmode source
+ into DImode pieces.
+
+ * pa-64.h (LONG_DOUBLE_TYPE_SIZE): Define to 128.
+ * pa64-regs.h (CLASS_CANNOT_CHANGE_MODE_P): Inhibit changes from SImode
+ for floating-point register class.
+ * pa.c (function_arg): Fix handling of modes wider than one word for
+ TARGET_64BIT.
+
+2002-09-04 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * combine.c (make_compound_operation): Don't generate zero / sign
+ extensions in floating point modes.
+
+2002-09-04 Janis Johnson <janis187@us.ibm.com>
+
+ * doc/c-tree.texi: Fix overfull hboxes.
+ * doc/cppopts.texi: Ditto.
+ * doc/extend.texi: Ditto.
+ * doc/gty.texi: Ditto.
+ * doc/invoke.texi: Ditto.
+ * doc/makefile.texi: Ditto.
+ * doc/rtl.texi: Ditto.
+ * doc/standards.texi: Ditto.
+ * doc/tm.texi: Ditto.
+
+2002-09-04 Richard Henderson <rth@redhat.com>
+
+ * c-common.c (builtin_define_with_hex_fp_value): New.
+ (builtin_define_float_constants): Use it. Fix H_FLOAT mant_dig.
+
+2002-09-04 Janis Johnson <janis187@us.ibm.com>
+
+ * doc/invoke.texi (-fshort-wchar): Move to Code Generation Options.
+ (-fpcc-struct-return, -freg-struct-return, -fshort-enums,
+ -fshort-double, -fshort-wchar, -fpack-struct, -fleading-underscore):
+ Warn that these options can break ABI compatibility.
+
+2002-09-04 Richard Henderson <rth@redhat.com>
+
+ * real.c (ereal_to_decimal): Add digits parameter.
+ * real.h (REAL_VALUE_TO_DECIMAL): Remove format; add digits parameter.
+ * c-pretty-print.c (pp_c_real_literal): Update call.
+ * print-rtl.c (print_rtx): Likewise.
+ * print-tree.c (print_node_brief, print_node): Likewise.
+ * sched-vis.c (print_value): Likewise.
+ * config/arc/arc.c (arc_print_operand): Likewise.
+ * config/c4x/c4x.c (c4x_print_operand): Likewise.
+ * config/i370/i370.h (PRINT_OPERAND): Likewise.
+ * config/i386/i386.c (print_operand): Likewise.
+ * config/i960/i960.c (i960_print_operand): Likewise.
+ * config/ip2k/ip2k.c (asm_output_float): Likewise.
+ * config/m32r/m32r.c (m32r_print_operand): Likewise.
+ * config/m68hc11/m68hc11.c (print_operand): Likewise.
+ * config/m68k/hp320.h (PRINT_OPERAND, ASM_OUTPUT_FLOAT_OPERAND,
+ ASM_OUTPUT_DOUBLE_OPERAND, ASM_OUTPUT_LONG_DOUBLE_OPERAND): Likewise.
+ * config/m68k/m68k.h (ASM_OUTPUT_FLOAT_OPERAND,
+ ASM_OUTPUT_DOUBLE_OPERAND, ASM_OUTPUT_LONG_DOUBLE_OPERAND): Likewise.
+ * config/m68k/sun2o4.h (ASM_OUTPUT_FLOAT_OPERAND,
+ ASM_OUTPUT_DOUBLE_OPERAND): Likewise.
+ * config/m68k/sun3.h (ASM_OUTPUT_FLOAT_OPERAND,
+ ASM_OUTPUT_DOUBLE_OPERAND): Likewise.
+ * config/mips/mips.c (print_operand): Likewise.
+ * config/ns32k/ns32k.c (print_operand): Likewise.
+ * config/pdp11/pdp11.h (PRINT_OPERAND): Likewise.
+ * config/vax/vax.h (PRINT_OPERAND): Likewise.
+ * doc/tm.texi (REAL_VALUE_TO_DECIMAL): Update docs.
+
+2002-09-04 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/elf.h (TARGET_SECTION_TYPE_FLAGS): Define to
+ xtensa_multibss_section_type_flags.
+ * config/xtensa/xtensa.c (xtensa_multibss_section_type_flags): Define.
+
+2002-09-04 Richard Henderson <rth@redhat.com>
+
+ * doc/install-old.texi: Don't mention enquire.
+ * doc/sourcebuild.texi: Update float.h description.
+
+2002-09-04 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.md (mperm_w_little, mperm_w_big): Supply mode for zero_extract.
+
+2002-09-03 David Edelsohn <edelsohn@gnu.org>
+
+ * varasm.c (default_section_type_flags): Append _1 to name with
+ shlib parameter. Use original name to call new function with
+ implicit flag_pic.
+ (decl_readonly_section): Likewise.
+ (default_elf_select_section): Likewise.
+ (default_unique_section): Likewise.
+ (default_bind_local_p): Likewise.
+ (categorize_decl_for_section): Add shlib parameter to use in place
+ of implicit flag_pic.
+ * output.h: Declare new functions with _1 and shlib argument.
+
+2002-09-03 Janis Johnson <janis187@us.ibm.com>
+
+ * doc/install.texi: Fix typos, formatting problems, and obvious
+ overfull/underfull boxes.
+
+ * Makefile.in (TEXI_GCC_FILES): Add compat.texi.
+ * doc/gcc.texi (Top): Add new chapter, Binary Compatibility, and
+ include its file, compat.texi.
+ * doc/compat.texi: New file with new chapter, Binary Compatibility.
+
+2002-09-03 Neil Booth <neil@daikokuya.co.uk>
+
+ Debian BTS Bug #157416
+ * cpphash.h (FIRST, LAST, CUR, RLIMIT): Fix definitions.
+ * cpplib.c (destringize_and_run): Kludge around getting
+ tokens from in-progress macros.
+ (_cpp_do__Pragma): Simplify.
+
+2002-09-03 Steve Ellcey <sje@cup.hp.com>
+
+ * config/ia64/ia64.h (EXTRA_SPECS): Remove cpp_cpu.
+ (CPP_CPU_SPEC): Remove.
+ (TARGET_CPU_CPP_BUILTINS): New.
+ * config/ia64/hpux.h (CPP_PREDEFINES): Remove.
+ (CPP_SPEC): Remove.
+ (TARGET_OS_CPP_BUILTINS): New.
+ * config/ia64/linux.h (CPP_PREDEFINES): Remove.
+ (TARGET_OS_CPP_BUILTINS): New.
+ * config/ia64/aix.h (CPP_SPEC): Move some stuff to
+ TARGET_OS_CPP_BUILTINS.
+ (CPP_PREDEFINES): Remove.
+ (CPLUSPLUS_CPP_SPEC): Remove.
+ (TARGET_OS_CPP_BUILTINS): New.
+
+2002-09-03 Richard Henderson <rth@redhat.com>
+
+ * Makefile.in (USER_H): Add ginclude/float.h.
+ (FLOAT_H): Remove.
+ (stmp-int-hdrs, install-mkheaders): Don't handle FLOAT_H.
+ (mostlyclean): Don't remove float.h intermediate files.
+ (distclean): Don't remove float.h.
+ * config.gcc: Remove all float_format references.
+ * configure.in (float_format, float_h_file): Remove.
+
+ * c-common.c: Include tree-inline.h.
+ (builtin_define_with_int_value): New.
+ (builtin_define_type_precision): Use it.
+ (builtin_define_float_constants): New.
+ (cb_register_builtins): Use it. Define __FLT_RADIX__ and
+ __FLT_EVAL_METHOD__.
+ * defaults.h (TARGET_FLT_EVAL_METHOD): New.
+ * config/i386/i386.h (TARGET_FLT_EVAL_METHOD): New.
+ * config/m68k/m68k.h (TARGET_FLT_EVAL_METHOD): New.
+ * doc/tm.texi (INTEL_EXTENDED_IEEE_FORMAT): Mention moto 96-bit format.
+ (TARGET_FLT_EVAL_METHOD): New.
+
+ * config/float-c4x.h, config/float-i128.h, config/float-i32.h,
+ config/float-i386.h, config/float-i64.h, config/float-m68k.h,
+ config/float-sh.h, config/float-sparc.h, config/float-vax.h: Remove.
+ * ginclude/float.h: New.
+
+2002-09-03 Stan Shebs <shebs@apple.com>
+
+ * config/darwin.h (WARN_FOUR_CHAR_CONSTANTS): Remove, never used.
+ (DWARF2_DEBUGGING_INFO): Remove until assembler accepts Dwarf-2.
+ (PREFERRED_DEBUGGING_TYPE): Ditto.
+ (ASM_OUTPUT_IDENT): Remove empty definition.
+
+2002-09-03 Steve Ellcey <sje@cup.hp.com>
+
+ * config.gcc (ia64*-*-hpux*): Add ia64-c.o to c_target and
+ cxx_target.
+ * config/ia64/hpux.h (REGISTER_TARGET_PRAGMAS): Register pragma
+ handling routine for builtin pragma.
+ * config/ia64/ia64-protos.h (ia64_hpux_handle_builtin_pragma):
+ Registered pragma handling routine.
+ * ia64-c.c (ia64_hpux_handle_builtin_pragma): Ditto.
+ (ia64_hpux_add_pragma_builtin) New subroutine used by above.
+ If builtin pragma seen for math routine and C89 conformance is
+ requested use different math function in order to set errno.
+ * t-ia64 (ia64-c.o): Add new rule for new file.
+
+2002-09-03 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.md ("movti"): Add Q->Q alternative.
+ ("*movdi_64", "*movdi_31", "*movsi", "movhi", "movqi_64",
+ "movqi", "*movdf_64", "*movdf_31", "*movsf"): Likewise.
+
+ ("*movti_ss", "*movdi_ss", "*movsi_ss", "*movdf_ss",
+ "*movsf_ss"): Remove.
+
+2002-09-03 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa32-regs.h (CLASS_CANNOT_CHANGE_MODE, CLASS_CANNOT_CHANGE_MODE_P):
+ Delete macros.
+
+2002-09-03 Arati Dikey <aratid@kpit.com>
+
+ * h8300.c (asm_file_start): Corrected optimization comment.
+
+2002-09-03 Stan Shebs <shebs@apple.com>
+
+ * c-lang.c (recognize_objc_keyword): Remove, no longer used.
+ * c-tree.h (recognize_objc_keyword): Remove decl.
+ * c-typeck.c (comp_target_types): Update a comment.
+
+2002-09-03 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.c (s390_decompose_address): Remove STRICT parameter
+ and register validity checks.
+ (general_s_operand): Adapt to s390_decompose_address interface change.
+ (q_constraint): Likewise.
+ (s390_expand_plus_operand): Likewise.
+ (legitimiate_address_p): Likewise.
+ (legitimate_la_operand_p): Likewise.
+ (legitimize_la_operand): Likewise.
+ (print_operand_address): Likewise.
+ (print_operand): Likewise.
+
+2002-09-03 Nicola Pero <n.pero@mi.flashnet.it>
+
+ PR objc/5956:
+ * objc/objc-act.c (build_typed_selector_reference): Fix typo which
+ was causing the new selector never to match the existing ones
+ (Patch by Alexander Malmberg <alexander@malmberg.org>).
+
+2002-09-03 Graham Stott <graham.stott@btinternet.com>
+
+ * config/i386/i386.md ("femms"): Add "memory" attr "none".
+
+2002-09-03 Graham Stott <graham.stott@btinternet.com>
+
+ * expr.c (expand_expr): Remove extraneous comment and code.
+
+2002-08-31 Richard Henderson <rth@redhat.com>
+
+ * expr.c (block_move_libcall_safe_for_call_parm): Fix thinko.
+
+2002-08-31 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.c (pa_globalize_label): Add ATTRIBUTE_UNUSED to prototype.
+
+2002-08-30 Richard Henderson <rth@redhat.com>
+
+ PR opt/7515
+ * c-objc-common.c: Include target.h.
+ (c_cannot_inline_tree_fn): Don't auto-inline functions that
+ don't bind locally. Factor setting DECL_UNINLINABLE.
+ * Makefile.in (c-objc-common.o): Update.
+
+2002-08-30 Janis Johnson <janis187@us.ibm.com>
+
+ * doc/install.texi (Configuration, Building): Fix a typo and
+ some formatting directives.
+
+2002-08-30 Paul Koning <pkoning@equallogic.com>
+
+ * doc/c-tree.texi (RDIV_EXPR): Fix typo.
+ * doc/rtl.texi (post_modify): Remove misplaced text, remove "not
+ implemented" note.
+ * doc/md.texi (IP2K): Move machine-specific constraints before MIPS
+ for alphabetic order.
+ * doc/tm.texi (TARGET_FLOAT_FORMAT): Update description for
+ VAX_FLOAT_FORMAT. Remove reference to HOST_FLOAT_FORMAT.
+ (VAX_HALFWORD_ORDER): Document.
+ (LARGEST_EXPONENT_IS_NORMAL): Remove note about being only for
+ IEEE float format.
+ (TARGET_SCHED_ISSUE_RATE): Reword reference to MAX_DFA_ISSUE_RATE.
+ (ASM_OUTPUT_LABEL_REF): Fix font.
+ (CASE_VECTOR_SHORTEN_MODE): Ditto.
+
+2002-08-30 Denis Chertykov <denisc@overta.ru>
+
+ * config/ip2k/ip2k.c (ip2k_set_compare): Remove all const_double
+ stuff.
+ (ip2k_gen_unsigned_comp_branch): Handle CONST_INT and
+ CONST_DOUBLE constants.
+
+2002-08-30 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/alpha/alpha.h (TARGET_CPU_CPP_BUILTINS): Move language-
+ related defines to...
+ (SUBTARGET_LANGUAGE_CPP_BUILTINS): ...here.
+ * config/alpha/netbsd.h (SUBTARGET_LANGUAGE_CPP_BUILTINS): Redefine
+ as a no-op.
+
+2002-08-30 Krister Walfridsson <cato@df.lth.se>
+
+ * config/arm/arm.c (arm_asm_output_labelref): New function.
+ * config/arm/arm.h (ASM_OUTPUT_LABELREF): Call arm_asm_output_labelref.
+ * config/arm/arm-protos.h: Add prototype for arm_asm_output_labelref.
+
+2002-08-29 Rodney Brown <rbrown64@csc.com.au>
+
+ * doc/install.texi (Specific, alpha*-dec-osf*): Add "virtual
+ memory exhausted" workarounds.
+
+2002-08-30 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * diagnostic.c (fancy_abort): Don't repeat "internal error".
+ * toplev.c (crash_signal): Likewise.
+
+2002-08-30 Nicola Pero <n.pero@mi.flashnet.it>
+
+ * doc/cpp.texi (__NEXT_RUNTIME__): Extended documentation.
+ * doc/invoke.texi (-fnext-runtime, -Wno-protocol, -Wselector):
+ Extended, updated documentation.
+ (-Wundeclared-selector): Documented.
+
+2002-08-29 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/chorus.h: Consistently define *_DEBUGGING_INFO with
+ the value 1. Do not undef before defining.
+ * config/darwin.h: Likewise.
+ * config/dbx.h: Likewise.
+ * config/dbxcoff.h: Likewise.
+ * config/dbxelf.h: Likewise.
+ * config/elfos.h: Likewise.
+ * config/interix.h: Likewise.
+ * config/lynx-ng.h: Likewise.
+ * config/lynx.h: Likewise.
+ * config/netware.h: Likewise.
+ * config/psos.h: Likewise.
+ * config/svr3.h: Likewise.
+ * config/alpha/alpha.h: Likewise.
+ * config/alpha/elf.h: Likewise.
+ * config/alpha/vms.h: Likewise.
+ * config/arc/arc.h: Likewise.
+ * config/arm/aout.h: Likewise.
+ * config/arm/coff.h: Likewise.
+ * config/c4x/c4x.h: Likewise.
* config/h8300/h8300.h: Likewise.
- * config/i370/i370.h: Likewise.
- * config/i386/i386.h: Likewise.
- * config/m68k/m68k.h: Likewise.
+ * config/i386/cygwin.h: Likewise.
+ * config/i386/djgpp.h: Likewise.
+ * config/i386/gas.h: Likewise.
+ * config/i386/gstabs.h: Likewise.
+ * config/i386/i386-coff.h: Likewise.
+ * config/i386/i386-interix.h: Likewise.
+ * config/i386/sco5.h: Likewise.
+ * config/i386/svr3dbx.h: Likewise.
+ * config/i386/sysv3.h: Likewise.
+ * config/i386/win32.h: Likewise.
+ * config/i386/x86-64.h: Likewise.
+ * config/i960/i960.h: Likewise.
+ * config/ia64/ia64.h: Likewise.
+ * config/ip2k/ip2k.h: Likewise.
+ * config/m32r/m32r.h: Likewise.
+ * config/m68k/3b1.h: Likewise.
+ * config/m68k/3b1g.h: Likewise.
+ * config/m68k/ccur-GAS.h: Likewise.
+ * config/m68k/coff.h: Likewise.
+ * config/m68k/hp2bsd.h: Likewise.
+ * config/m68k/hp310g.h: Likewise.
+ * config/m68k/hp320g.h: Likewise.
+ * config/m68k/hp3bsd.h: Likewise.
+ * config/m68k/hp3bsd44.h: Likewise.
+ * config/m68k/linux-aout.h: Likewise.
+ * config/m68k/m68k-aout.h: Likewise.
+ * config/m68k/mot3300.h: Likewise.
+ * config/m68k/netbsd.h: Likewise.
+ * config/m68k/openbsd.h: Likewise.
+ * config/m68k/pbb.h: Likewise.
+ * config/m68k/plexus.h: Likewise.
+ * config/m68k/sun2.h: Likewise.
+ * config/m68k/sun3.h: Likewise.
+ * config/m68k/tower-as.h: Likewise.
+ * config/m68k/vxm68k.h: Likewise.
+ * config/m88k/aout-dbx.h: Likewise.
+ * config/m88k/m88k-aout.h: Likewise.
+ * config/mcore/mcore-elf.h: Likewise.
+ * config/mcore/mcore-pe.h: Likewise.
+ * config/mips/elf.h: Likewise.
+ * config/mips/elf64.h: Likewise.
+ * config/mips/iris5gas.h: Likewise.
+ * config/mips/iris6.h: Likewise.
* config/mips/mips.h: Likewise.
- * config/ns32k/ns32k.h: Likewise.
- * config/pdp11/pdp11.h: Likewise.
- * config/pj/pj.h: Likewise.
- * config/s390/s390.h: Likewise.
- * config/sh/sh.h: Likewise.
- * config/stormy16/stormy16.h: Likewise.
- * config/v850/v850.h: Likewise.
+ * config/mips/sni-gas.h: Likewise.
+ * config/mmix/mmix.h: Likewise.
+ * config/ns32k/netbsd.h: Likewise.
+ * config/pa/pa64-hpux.h: Likewise.
+ * config/romp/romp.h: Likewise.
+ * config/rs6000/sysv4.h: Likewise.
+ * config/rs6000/xcoff.h: Likewise.
+ * config/sh/coff.h: Likewise.
+ * config/sh/elf.h: Likewise.
+ * config/sparc/linux64.h: Likewise.
+ * config/sparc/liteelf.h: Likewise.
+ * config/sparc/netbsd.h: Likewise.
+ * config/sparc/openbsd.h: Likewise.
+ * config/sparc/pbd.h: Likewise.
+ * config/sparc/sp64-elf.h: Likewise.
+ * config/sparc/sp86x-elf.h: Likewise.
+ * config/sparc/sparc.h: Likewise.
* config/vax/vax.h: Likewise.
- * config/we32k/we32k.h: Likewise.
+ * config/vax/vaxv.h: Likewise.
-2002-01-15 Aldy Hernandez <aldyh@redhat.com>
+2002-08-29 "Dhananjay R. Deshpande" <dhananjayd@kpit.com>
- * config/rs6000/rs6000.md (altivec_stvx): Add parallels to stvx.
- (altivec_lvsl): Change constraint to b.
- (altivec_lvsr): Same.
- (altivec_lvebx): Same.
- (altivec_lvehx): Same.
- (altivec_lvewx): Same.
- (altivec_lvxl): Same.
- (altivec_lvx): Same.
- (altivec_stvx): Add parallel.
- (altivec_stvxl): Same.
- (altivec_stvehx): Same.
- (altivec_stvebx): Same.
- (altivec_stvebx): Same.
+ * h8300.c (shift_alg_hi): Various tweaks to improve performance
+ of HImode shifts.
+ (get_shift_alg): Corresponding changes.
-2002-01-15 Aldy Hernandez <aldyh@redhat.com>
+2002-08-29 John David Anglin <dave@hiauly1.hia.nrc.ca>
- * config.gcc: Change altivec.h to altivec-defs.h.
+ * som.h (ALWAYS_STRIP_DOTDOT): Define to 1.
+
+2002-08-29 Richard Henderson <rth@redhat.com>
+
+ * expr.h (enum block_op_methods): New.
+ (emit_block_move): Update prototype.
+ * expr.c (block_move_libcall_safe_for_call_parm): New.
+ (emit_block_move_via_loop): New.
+ (emit_block_move): Use them. New argument METHOD.
+ (emit_push_insn): Always respect the given alignment.
+ (expand_assignment): Update call to emit_block_move.
+ (store_expr, store_field, expand_expr): Likewise.
+ * builtins.c (expand_builtin_apply): Likewise.
+ (expand_builtin_memcpy, expand_builtin_va_copy): Likewise.
+ * function.c (expand_function_end): Likewise.
+ * config/sh/sh.c (sh_initialize_trampoline): Likewise.
+ * config/sparc/sparc.c (sparc_va_arg): Likewise.
+ * calls.c (expand_call, emit_library_call_value_1): Likewise.
+ (save_fixed_argument_area): Use emit_block_move with
+ BLOCK_OP_CALL_PARM instead of move_by_pieces.
+ (restore_fixed_argument_area): Likewise.
+ (store_one_arg): Fix alignment parameter to emit_push_insn.
- * config/rs6000/altivec.h: Delete.
+2002-08-29 John David Anglin <dave@hiauly1.hia.nrc.ca>
- * config/rs6000/altivec-defs.h: Add.
+ * install.texi (hppa64-hp-hpux11*): Document installation procedure.
-2002-01-15 John David Anglin <dave@hiauly1.hia.nrc.ca>
+2002-08-29 Catherine Moore <clm@redhat.com>
- * vax.c (vax_rtx_cost): Return MAX_COST for unsupported MULT, UDIV
- and UMOD modes.
+ * config/v850/v850.h (MULDI3_LIBCALL, UCMPDI2_LIBCALL, CMPDI2_LIBCALL,
+ NEGDI2_LIBCALL, INIT_TARGET_OPTABS, MASK_STRICT_ALIGN): Define.
+ (PREDICATE_CODES): Include new predicates.
+ (RTX_COSTS): Handle UMOD and UDIV. Tune MULT for v850e.
+ (TARGET_SWITCHES): Add strict-align.
+ (TARGET_STRICT_ALIGN): New.
+ (MASK_DEFAULT, STRICT_ALIGNMENT): Redefine.
+ * config/v850/t-v850 (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
+ Define.
+ (LIB1ASMFUNCS): Add v850_negdi2, v850_cmpdi2, v850_ucmpdi2,
+ v850_muldi3.
+ * config/v850/lib1funcs.asm (L_callt_save_r2_r29, L_return_r2_r29,
+ L_callt_save_r2_r31, L_return_r2_r31,
+ L_save_all_interrupt): Change addi to add.
+ (L_save_interrupt, L_return_interrupt): Rework.
+ (__return_r31): Correct .size directive.
+ (mulsi3, divsi3, udivsi3, umodsi3, modsi3): Tune for v850e.
+ (v850_negdi2, v850_cmpdi2, v850_ucmpdi2, v850_muldi3):
+ New routines.
+ * config/v850/v850.c (expand_prologue): Call
+ gen_callt_save_interrupt, gen_callt_restore_all_interrupt,
+ gen_callt_return_interrupt and gen_callt_save_all_interrupt.
+ (reg_or_int9_operand): New predicate.
+ (reg_or_const_operand): New routine.
+ * config/v850/v850.md (return_interrupt): Changed from
+ restore_interrupt.
+ (callt_save_all_interrupt): Changed from save_all_interrupt_v850e.
+ (callt_save_interrupt): Change save sequence.
+ (callt_return_interrupt): New.
+ (save_interrupt): Don't use runtime function for LONG_CALLS
+ and TARGET_PROLOG_FUNCTION.
+ (save_all_interrupt): Likewise.
+ (mulsi3): Use new predicate.
+ (moviscc): Disallow some combination of constants.
+ Fix define_split for sasf insns, so that it will not generate bad
+ code if operand0 and operand5 are the same.
+ * config/v850/v850-protos.h: Prototype new predicates.
+
+2002-08-28 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * c-common.c (builtin_define_type_precision): New function.
+ (cb_register_builtins): Use it. Define __WCHAR_UNSIGNED__ is
+ wchar_t is unsigned in C++.
+ * doc/cpp.texi (Common Predefined Macros): Document
+ __WCHAR_UNSIGNED__, __CHAR_BIT__, __WCHAR_BIT__, __SHRT_BIT__,
+ __INT_BIT__, __LONG_BIT__, __LONG_LONG_BIT__, __FLOAT_BIT__,
+ __DOUBLE_BIT__, __LONG_DOUBLE_BIT__.
+
+2002-08-28 Sylvain Pion <pion@cs.nyu.edu>
+
+ * doc/invoke.texi (-Wreorder): Remove remaining pieces from the generic
+ section. Mention that it is enabled by -Wall.
+ (-Wall): Mention that there can be language-specific warnings as well.
+ (-Wctor-dtor-privacy): Mention that it is enabled by default.
+ (-Wnon-virtual-dtor): Mention that it is enabled by -Wall.
+
+2002-08-28 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.c (calc_live_regs): Save FPSCR_REG in an interrupt handler
+ if it is ever live.
+
+ * sh.c (sh_handle_interrupt_handler_attribute): Reject interrupt_handler
+ attribute for SHCOMPACT.
+
+ * sh.h (OVERRIDE_OPTIONS): If align_function isn't set, set it
+ appropriately.
+ (FUNCTION_BOUNDARY): Specify only the minimum alignment required
+ by the ABI.
- * vax.h (INDEX_TERM_P): Restrict indexing to modes which have a size
- less than or equal to eight bytes.
+ * sh.h (SH5_WOULD_BE_PARTIAL_NREGS): Also handle TImode case.
- * vax.md (andsi3): Remove constraints and change SET destination
- operand type to nonimmediate_operand.
- (andhi3, andqi3): Likewise. Don't clear high order bits of operand 1
- when it is a CONST_INT.
+2002-08-28 Jason Thorpe <thorpej@wasabisystems.com>
-2002-01-15 Jason Merrill <jason@redhat.com>
+ * config.gcc (mips*-*-netbsd*): Set target_cpu_default to
+ "MASK_GAS|MASK_ABICALLS".
+ * config/mips/netbsd.h (TARGET_ENDIAN_DEFAULT)
+ (TARGET_DEFAULT): Remove.
+ (MACHINE_TYPE): Undefine before defining.
+ (DBX_DEBUGGING_INFO, PREFERRED_DEBUGGING_TYPE): Remove.
- * c-common.def (FILE_STMT): New code.
- * c-common.c (statement_code_p): It's a statement.
- * c-common.h (stmt_tree_s): Add x_last_filename.
- (FILE_STMT_FILENAME_NODE, FILE_STMT_FILENAME): New macros.
- (last_expr_filename): New macro.
- * c-semantics.c (begin_stmt_tree): Initialize it.
- (add_stmt): If the filename changed, also insert a
- FILE_STMT.
- (expand_stmt): Handle seeing one.
+2002-08-27 Mark Mitchell <mark@codesourcery.com>
-2002-01-15 Eric Christopher <echristo@redhat.com>
+ * c-common.c (warn_abi): New variable.
+ * c-common.h (warn_abi): Likewise.
+ * c-opts.c (COMMAND_LINE_OPTIONS): Add -Wabi.
+ (c_common_decode_option): Handle it.
+ * doc/invoke.texi: Document -Wabi.
- * flow.c (propagate_one_insn): Add error message and print out
- insn for debugging.
+2002-08-27 Nicola Pero <n.pero@mi.flashnet.it>
-2002-01-15 Joseph S. Myers <jsm28@cam.ac.uk>
+ * c-common.c (warn_undeclared_selector): New variable.
+ * c-common.h (warn_undeclared_selector): Idem.
+ * c-opts.c (c_common_decode_option): Set warn_undeclared_selector
+ to on when -Wundeclared-selector is found.
+ (COMMAND_LINE_OPTIONS): Added -Wundeclared-selector.
+ * objc/objc-act.c (build_selector_expr): If
+ warn_undeclared_selector is set, check that the selector has
+ already been defined, and emit a warning if not.
- * system.h (ASM_IDENTIFY_GCC, STDC_VALUE, TRAMPOLINE_ALIGN,
- ASM_IDENTIFY_GCC_AFTER_SOURCE): Poison.
- * config/pdp11/pdp11.h (TRAMPOLINE_ALIGN): Rename to
- TRAMPOLINE_ALIGNMENT.
- * config/arm/arm.h, config/mcore/mcore.h: Likewise. Change value
- to be in bits.
- * config/i386/cygwin.h (PCC_BITFIELDS_TYPE_MATTERS): Rename to
- PCC_BITFIELD_TYPE_MATTERS.
- * config/interix.h (STDC_VALUE): Remove. Use
- STDC_0_IN_SYSTEM_HEADERS.
- * config/darwin.h (ASM_IDENTIFY_GCC), config/dsp16xx/dsp16xx.h
- (ASM_IDENTIFY_GCC), config/stormy16/stormy16.h (ASM_IDENTIFY_GCC,
- ASM_IDENTIFY_GCC_AFTER_SOURCE): Remove.
+2002-08-27 Nick Clifton <nickc@redhat.com>
+ Catherine Moore <clm@redhat.com>
+ Jim Wilson <wilson@cygnus.com>
-2002-01-15 Craig Rodrigues <rodrigc@gcc.gnu.org>
+ * config.gcc: Add v850e-*-* target.
+ Add --with-cpu= support for v850.
+ * config/v850/lib1funcs.asm: Add v850e callt functions.
+ * config/v850/v850.h: Add support for v850e target.
+ * config/v850/v850.c: Add functions to support v850e target.
+ * config/v850/v850-protos.h: Add prototypes for new functions in v850.c.
+ * config/v850/v850.md: Add patterns for v850e instructions.
+ * doc/invoke.texi: Document new v850e command line switches.
- * doc/install.texi (hppa*-hp-hpux11): --enable-threads does
- not work on this platform currently.
+2002-08-27 J"orn Rennecke <joern.rennecke@superh.com>
+ Aldy Hernandez <aldyh at redhat dot com>
-2002-01-15 Joseph S. Myers <jsm28@cam.ac.uk>
+ * doc/tm.texi: Applied numerous fixes to the automaton based
+ scheduler descrition.
- * c-typeck.c (build_unary_op): Don't wrap msgid argument of
- readonly_warning in _().
+2002-08-27 Jan Hubicka <jh@suse.cz>
-2002-01-15 Douglas B Rupp <rupp@gnat.com>
+ * i386.c (classify_argument): Handle variable sized objects.
- * gcc.c (delete_if_ordinary): Backout previous change.
+2002-08-27 Jan Hubicka <jh@suse.cz>
-2002-01-15 Kazu Hirata <kazu@hxi.com>
+ * i386.c (ix86_expand_int_movcc): Fix RTL sharing problem
- * config/h8300/h8300.c (print_operand): Remove support for
- unused operand characters.
+2002-08-27 Jan Hubicka <jh@suse.cz>
- * read-rtl.c: Fix formatting.
- * real.c: Likewise.
- * recog.c: Likewise.
- * regclass.c: Likewise.
- * regmove.c: Likewise.
- * reg-stack.c: Likewise.
- * reload1.c: Likewise.
- * rtlanal.c: Likewise.
+ * libgcc2.c (__bb_exit_func): Properly write the summarized statistics.
-2002-01-15 Kazu Hirata <kazu@hxi.com>
+2002-08-27 Jan Hubicka <jh@suse.cz>
- * config/i386/i386.c: Fix formatting.
+ * i386.c (classify_argument): Properly compute word size of the analyzed object.
-2002-01-15 Jakub Jelinek <jakub@redhat.com>
+2002-08-27 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.md (attribute type): Add types mt_group, fload, pcfload, fpul_gp,
+ mac_gp ftrc_s and cwb. Add / Adjust definitions in individual insn
+ accordingly.
+ (attribute insn_class): Provide default definitions based on type.
+ Remove all insn-specific settings.
+ (various function units): Remove old SH4 scheduling.
+ (branch_zero, dfp_comp, late_fp_use, any_fp_comp, any_int_load):
+ New attributes. Set them where appropriate.
+ (cpu unit FS): Don't define / use.
+ (F3, load_store): New cpu units.
+ (F01): New reservation.
+ (all insn_reservations): Make dependent on sh4 pipeline model.
+ Fix latencies.
+ (nil, reg_mov, freg_mov, sh4_fpul_gp, sh4_call): New insn_reservations.
+ (sh4_mac_gp, fp_arith_ftrc, arith3, arith3b): Likewise.
+ (mt insn_reservation): Use type mt_group.
+ (insn_reservation load_store): Split into sh4_load, sh4_load_si,
+ sh4_fload and sh4_store.
+ (insn_reservation branch_zero and branch): Replace with sh4_branch.
+ (insn_reservation branch_far): Replace with sh4_return.
+ (insn_reservation return_from_exp): Rename to:
+ (sh4_return_from_exp). Change to be just d_lock*5.
+ (insn_reservation lds_to_pr): Rename to:
+ (sh4_lds_to_pr). Change to be just d_lock*2.
+ (insn_reservation ldsmem_to_pr, sts_from_pr): Change to be just
+ d_lock*2.
+ (insn_reservation prload_mem): Rename to:
+ (sh4_prstore_mem). Change to d_lock*2,nothing,memory.
+ (insn_reservation fpscr_store): Rename to:
+ (fpscr_load). Change to d_lock,nothing,F1*3.
+ (insn_reservation fpscr_store_mem): Rename to:
+ (fpscr_load_mem). Change to d_lock,nothing,(F1+memory),F1*2.
+ (insn_reservation multi): Change to
+ d_lock,(d_lock+f1_1),(f1_1|f1_2)*3,F2.
+ (insn_reservation fp_arith): Change to issue,F01,F2.
+ (insn_reservation fp_div: Change to issue,F01+F3,F2+F3,F3*7,F1+F3,F2.
+ (insn_reservation dp_float): Change to issue,F01,F1+F2,F2.
+ (insn_reservation fp_double_arith): Change to issue,F01,F1+F2,fpu*4,F2.
+ (insn_reservation fp_double_cmp): Change to
+ d_lock,(d_lock+F01),F1+F2,F2.
+ (insn_reservation dp_div): Change to
+ issue,F01+F3,F1+F2+F3,F2+F3,F3*16,F1+F3,(fpu+F3)*2,F2.
+ * sh.c (flow_dependent_p, flow_dependent_p_1): New functions.
+ (sh_adjust_cost, SHcompact): Differentiate between different
+ kinds of dependencies. Drop factor of ten for superscalar.
+ Use new instruction types. Add new exception rules.
+
+ * sh.md (mulhisi3, umulhisi3: Add a REG_EQUAL note.
+
+ * sh.md (mperm_w): Add DONE.
+
+2002-08-27 David Edelsohn <edelsohn@gnu.org>
+
+ * longlong.h: Import current PowerPC defintion from GMP-4.1.
+
+ * config/rs6000/rs6000.h (MIN_UNITS_PER_WORD): Add IN_LIBGCC2 case.
- * c-typeck.c (process_init_element): Don't save_expr
- COMPOUND_LITERAL_EXPR if just its initializer will be used.
+ * config/rs6000/linux64.h (ADJUST_FIELD_ALIGN): Undef before define.
+
+2002-08-27 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.h (MAX_FIXED_MODE_SIZE): Define.
-2002-01-15 David Edelsohn <edelsohn@gnu.org>
+2002-08-27 Gabriel Dos Reis <gdr@soliton.integrable-solutions.net>
- * config/rs6000/rs6000.c (rs6000_output_function_epilogue): Do not
- emit optional traceback table if optimize_size or TARGET_ELF.
- * config/rs6000/rs6000.md (prefetch): New.
+ * doc/cpp.texi (Common Predefined Macros): Don't mess with table
+ delimiter.
-2002-01-15 Andreas Jaeger <aj@suse.de>
+2002-08-27 Gabriel Dos Reis <gdr@integrable-solutions.net>
- * config.gcc (x86_64-*-*): Install mmintrin.h and xmmintrin.h.
+ * c-common.c (cpp_define_data_format): New function.
+ (cb_register_builtins): Call it.
-2002-01-15 Kazu Hirata <kazu@hxi.com>
+ * doc/cpp.texi (Common Predefined Macros): Document
+ __TARGET_BITS_ORDER__, __TARGET_BYTES_ORDER__,
+ __TARGET_INT_WORDS_ORDER__, __TARGET_FLOAT_WORDS_ORDER__,
+ __TARGET_FLOAT_FORMAT__, __TARGET_USES_VAX_F_FLOAT__,
+ __TARGET_USES_VAX_D_FLOAT__, __TARGET_USES_VAX_G_FLOAT__,
+ __TARGET_USES_VAX_H_FLOAT__.
- * mips-tfile.c: Fix formatting.
+2002-08-26 Ziemowit Laski <zlaski@apple.com>
-Tue Jan 15 00:56:11 CET 2002 Jan Hubicka <jh@suse.cz>
+ * objc/objc-act.c (get_super_receiver): If inside a class method
+ of a category, cast the receiver to 'id' before accessing the 'isa'
+ field so that <objc/objc-class.h> is not needed. For NeXT runtime.
- * unroll.c (final_reg_note_copy): Fix previous commit.
+2002-08-26 Ulrich Weigand <uweigand@de.ibm.com>
-2002-01-14 Kazu Hirata <kazu@hxi.com>
+ * config/s390/s390-protos.h (s390_function_prologue,
+ s390_function_epilogue): Remove.
+ config/s390/s390.c (s390_function_prologue, s390_function_epilogue,
+ TARGET_ASM_FUNCTION_PROLOGUE, TARGET_ASM_FUNCTION_EPILOGUE): Remove.
- * config/h8300/h8300-protos.h: Remove the prototype for
- eq_operator.
- * config/h8300/h8300.c (eq_operator): Remove.
+ config/s390/s390.c (s390_machine_dependent_recorg): New function.
+ config/s390/s390-protos.h (s390_machine_dependent_reorg): Declare it.
+ config/s390/s390.h (MACHINE_DEPENDENT_REORG): Call it.
+ config/s390/s390.c (s390_split_branches, s390_chunkify_pool): Adapt
+ to being called from MACHINE_DEPENDENT_REORG. Update regs_ever_live.
-2002-01-14 Richard Henderson <rth@redhat.com>
+ config/s390/s390.c (s390_frame_info): Inline save_fprs_p. Always
+ assume BASE_REGISTER and RETURN_REGNUM need to be saved.
+ (s390_emit_prologue): Assume RETURN_REGNUM to be saved iff
+ function is not a leaf function. Use save_gprs and restore_gprs.
+ (s390_emit_epilogue): Likewise.
+ (save_gprs, restore_gprs): New functions.
+ (struct s390_frame): Remove return_reg_saved_p member.
+ (save_fprs_p): Remove.
+ (s390_optimize_prolog): New function.
+ (s390_legitimate_reload_constant): Remove now unnecessary check.
- * config/i386/i386.md (prefetch): Tidy.
- (prefetch_3dnow): Fix locality operand.
+ (s390_function_count): Remove.
+ (s390_output_symbolic_const): Replace s390_function_count by
+ current_function_funcdef_no.
+ (s390_output_constant_pool): Likewise.
+
+ (legitimize_pic_address): Use regs_ever_live to track PIC register
+ instead of current_function_uses_pic_offset_table.
+ (s390_emit_prologue): Likewise.
+ config/s390/s390.md ("call", "call_value"): Likewise.
-2002-01-14 Richard Henderson <rth@redhat.com>
+2002-08-26 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-opts.c (find_opt): Don't complain about wrong languages
+ here. Return exact matches even for wrong language.
+ (c_common_decode_option): Complain about wrong languages
+ here.
+
+2002-08-24 Stuart Hastings <stuart@apple.com>
+
+ * function.h (struct function): Add flag
+ all_throwers_are_sibcalls.
+ * except.c (set_nothrow_function_flags): Replaces
+ nothrow_function_p. Set new flag.
+ * except.h (set_nothrow_function_flags): Replaces
+ nothrow_function_p.
+ * dwarf2out.c (struct dw_fde_struct): Add flag
+ all_throwers_are_sibcalls.
+ (output_call_frame_info): Test it.
+ (dwarf2out_begin_prologue) Propagate it from cfun to
+ dw_fde_struct.
+ * toplev.c (rest_of_compilation): Update calls to
+ nothrow_function_p.
+
+2002-08-23 Zack Weinberg <zack@codesourcery.com>
+
+ * ggc-page.c (compute_inverse): Short circuit calculation for
+ object sizes larger than half a page.
+
+2002-08-23 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.c (rs6000_elf_select_section): Treat
+ DEFAULT_ABI == ABI_AIX like PIC. Test PIC & reloc for readonly
+ default.
+ (rs6000_elf_unique_section): Likewise.
+
+2002-08-23 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * ns32k.c (ns32k_globalize_label): Delete.
+ * ns32k.h (ASM_OUTPUT_LABEL, TARGET_ASM_GLOBALIZE_LABEL): Delete.
+
+2002-08-23 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.c (output_mi_thunk): Don't determine insns
+ for loading delta with num_insns_constant_wide. Calculate
+ delta_low, delta_high without using a conditional.
+
+2002-08-22 Jason Merrill <jason@redhat.com>
- * config/mips/mips.h (HI_AND_FP_REGS): New register class.
- (CLASS_CANNOT_CHANGE_MODE): Disallow HI in little-endian mode.
+ * c-common.h (RETURN_STMT_EXPR): Rename from RETURN_EXPR.
+ * c-common.def: Adjust.
+ * c-dump.c (c_dump_tree): Adjust.
+ * c-semantics.c (genrtl_return_stmt): Adjust.
+ * c-pretty-print.c (pp_c_statement): Adjust.
+ * tree-inline.c (copy_body_r): Adjust.
-2002-01-14 Hans-Peter Nilsson <hp@bitrange.com>
+2002-08-22 Zack Weinberg <zack@codesourcery.com>
- * reload1.c (reload_combine): Pass reg_sum replacement through
- copy_rtx in loop performing multiple changes.
+ * ggc-page.c: Avoid division in ggc_set_mark.
+ (DIV_MULT, DIV_SHIFT, OFFSET_TO_BIT, inverse_table,
+ compute_inverse): New.
+ (ggc_set_mark, ggc_marked_p): Use OFFSET_TO_BIT.
+ (init_ggc): Initialize inverse_table.
-2002-01-14 Jakub Jelinek <jakub@redhat.com>
+2002-08-22 Tom Tromey <tromey@redhat.com>
- * except.c (remove_unreachable_regions): New.
- (free_eh_status): Clear exception_handler_labels.
- (convert_from_eh_region_ranges): Call remove_unreachable_regions.
- (find_exception_handler_labels): Don't add the same label more than
- once.
- (remove_exception_handler_label): Don't die if
- find_exception_handler_labels hasn't been called for the current
- function yet.
+ * doc/install.texi (Configuration): Document --datadir.
-Mon Jan 14 21:26:13 CET 2002 Jan Hubicka <jh@suse.cz>
+2002-08-22 Alexandre Oliva <aoliva@redhat.com>
- * toplev.c (rest_of_compilation): Rebuild jump labels after
- gcse.
+ * Makefile.in ($(BUILD_PREFIX_1)varray.o): Depend on $(GGC_H).
-2002-01-14 Joseph S. Myers <jsm28@cam.ac.uk>
+2002-08-22 Hans-Peter Nilsson <hp@bitrange.com>
- * doc/extend.texi: Move documentation of X86 built-in functions
+ * gengtype-lex.l (ID): Allow underscore as first character.
+
+2002-08-21 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.c (rs6000_xcoff_asm_globalize_label): New
+ function.
+ (rs6000_xcoff_asm_named_section): Rename.
+ * config/rs6000/xcoff.h (TARGET_ASM_GLOBALIZE_LABEL): Define.
+
+2002-08-21 Tom Tromey <tromey@redhat.com>
+
+ For PR java/6005 and PR java/7611:
+ * fold-const.c (fold_truthop): Use can_use_bit_fields_p.
+ (fold): Likewise.
+ * langhooks.c (lhd_can_use_bit_fields_p): New function.
+ * langhooks-def.h (lhd_can_use_bit_fields_p): Declare.
+ (LANG_HOOKS_CAN_USE_BIT_FIELDS_P): New define.
+ (LANG_HOOKS_INITIALIZER): Use it.
+ * langhooks.h (struct lang_hooks) [can_use_bit_fields_p]: New
+ field.
+
+2002-08-21 Stan Shebs <shebs@apple.com>
+
+ * tree.c (finish_vector_type): Fix a typo in a comment.
+ * Makefile.in: Fix "the the" stutters in comments.
+ * genautomata.c: Ditto.
+ * ifcvt.c: Ditto.
+ * regrename.c: Ditto.
+ * config/alpha/alpha.c: Ditto.
+ * config/alpha/vms-crt0-64.c: Ditto.
+ * config/alpha/vms-crt0.c: Ditto.
+ * config/alpha/vms-psxcrt0-64.c: Ditto.
+ * config/alpha/vms-psxcrt0.c: Ditto.
+ * config/d30v/d30v.h: Ditto.
+ * config/fr30/fr30.h: Ditto.
+ * config/rs6000/rs6000.c: Ditto.
+ * config/stormy16/stormy16.h: Ditto.
+ * doc/md.texi: Ditto.
+
+2002-08-21 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * cppinit.c (remove_dup_nonsys_dirs): Fix warning and return value.
+
+2002-08-21 Joseph S. Myers <jsm@polyomino.org.uk>
+
+ * c-decl.c (grokdeclarator): Make invalid combinations with long,
+ short, signed or unsigned into hard errors. Fixes PR c/4319.
+ Also make duplicate modifiers such as "short short" into hard
+ errors.
+
+2002-08-21 Andrew Pinski <pinskia@physics.uc.edu>
+ Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * doc/tm.texi (TARGET_ASM_GLOBALIZE_LABEL): Move '@end deftypefn'
+ to the actual end. Add '@end table' and '@table @code'.
+
+2002-08-20 Geoffrey Keating <geoffk@redhat.com>
+
+ * doc/tm.texi (Label Output): Add missing '@end deftypefn'.
+
+ * unroll.c (biv_total_increment): Don't try to compute the total
+ increment for FP BIVs.
+
+2002-08-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * alpha.c (TARGET_ASM_GLOBALIZE_LABEL): Define for unicosmk.
+ * alpha/elf.h (ASM_OUTPUT_EXTERNAL_LIBCALL,
+ ASM_OUTPUT_ALIGNED_BSS): Use target hook.
+ * alpha/osf.h (ASM_OUTPUT_WEAK_ALIAS): Likewise.
+ * alpha/unicosmk.h (ASM_GLOBALIZE_LABEL): Delete.
+ * arm/aof.h (ASM_GLOBALIZE_LABEL): Likewise.
+ (GLOBAL_ASM_OP): Define.
+ * arm.c (aof_globalize_label): New function.
+ (TARGET_ASM_GLOBALIZE_LABEL): Define for AOF.
+ * arm/unknown-elf.h (ASM_OUTPUT_ALIGNED_BSS): Use target hook.
+ * c4x.c (c4x_globalize_label): New function.
+ (TARGET_ASM_GLOBALIZE_LABEL): Define for c4x.
+ * c4x.h (ASM_GLOBALIZE_LABEL): Delete.
+ (GLOBAL_ASM_OP): Define.
+ * cris/aout.h (ASM_OUTPUT_EXTERNAL_LIBCALL): Use target hook.
+ * darwin-protos.h (darwin_globalize_label): Declare.
+ * darwin.c (darwin_globalize_label): New function.
+ * darwin.h (ASM_DECLARE_CLASS_REFERENCE): Use target hook.
+ (ASM_GLOBALIZE_LABEL): Delete.
+ (GLOBAL_ASM_OP, TARGET_ASM_GLOBALIZE_LABEL): Define.
+ * dsp16xx.c (asm_output_common): Use target hook.
+ * elfos.h (ASM_OUTPUT_EXTERNAL_LIBCALL): Likewise.
+ * frv.h (ASM_GLOBALIZE_LABEL): Delete.
+ (GLOBAL_ASM_OP): Define.
+ * i370.c (i370_globalize_label): New function.
+ (TARGET_ASM_GLOBALIZE_LABEL): Define for i370.
+ * i370.h (ASM_GLOBALIZE_LABEL): Delete.
+ * i386.c (ix86_asm_file_end): Use target hook.
+ * i386/sco5.h (ASM_GLOBALIZE_LABEL): Don't undef.
+ (ASM_OUTPUT_EXTERNAL_LIBCALL): Use target hook.
+ * ia64.c (ia64_asm_output_external): Likewise.
+ * ia64/sysv4.h: Update comment.
+ * m32r.h (ASM_OUTPUT_ALIGNED_BSS): Use target hook.
+ * mips/elf.h (ASM_OUTPUT_ALIGNED_BSS): Likewise.
+ * mips/iris5.h (ASM_OUTPUT_WEAK_ALIAS): Use target hook.
+ * mips/linux.h (ASM_OUTPUT_ALIGNED_BSS): Likewise.
+ * mips.h (ASM_OUTPUT_ALIGNED_DECL_COMMON): Use target hook.
+ * mmix-protos.h (mmix_asm_globalize_label): Delete.
+ * mmix.c (mmix_asm_globalize_label): Likewise.
+ * mmix.h (ASM_GLOBALIZE_LABEL): Likewise.
+ (GLOBAL_ASM_OP): Define.
+ * ns32k.c (ns32k_globalize_label): New function.
+ * ns32k.h (TARGET_ASM_GLOBALIZE_LABEL): Define for ns32k.
+ (ASM_GLOBALIZE_LABEL): Delete.
+ * pa/pa-linux.h (ASM_GLOBALIZE_LABEL): Don't undef.
+ (TARGET_ASM_GLOBALIZE_LABEL): Undefine.
+ * pa.c (pa_globalize_label): New function.
+ * pa.h (ASM_GLOBALIZE_LABEL): Delete.
+ (TARGET_ASM_GLOBALIZE_LABEL): Define for pa.
+ * rs6000/darwin.h (ASM_GLOBALIZE_LABEL): Delete.
+ (GLOBAL_ASM_OP): Define.
+ (TARGET_ASM_GLOBALIZE_LABEL): Undef.
+ * rs6000/sysv4.h (ASM_OUTPUT_ALIGNED_BSS): Use target hook.
+ * rs6000/xcoff.h (ASM_GLOBALIZE_LABEL): Delete.
+ (GLOBAL_ASM_OP): Define.
+ * v850.c (v850_output_aligned_bss): Use target hook.
+ * vax.c (vms_globalize_label): New function.
+ (TARGET_ASM_GLOBALIZE_LABEL): Define for vms.
+ * vax/vms.h (ASM_GLOBALIZE_LABEL): Delete.
+ (GLOBAL_ASM_OP): Define.
+ * defaults.h (ASM_GLOBALIZE_LABEL): Delete.
+ * doc/tm.texi: Update docs.
+ * dwarf2out.c (default_eh_frame_section, output_die_symbol): Use
+ target hook.
+ * final.c (output_alternate_entry_point): Likewise.
+ * hooks.c (hook_FILEptr_constcharptr_void): New function.
+ * hooks.h (hook_FILEptr_constcharptr_void): Declare.
+ * output.h (assemble_global): Delete.
+ (default_globalize_label): Declare.
+ * system.h (ASM_GLOBALIZE_LABEL): Poison.
+ * target-def.h (TARGET_ASM_GLOBALIZE_LABEL): Define.
+ (TARGET_ASM_OUT): Add TARGET_ASM_GLOBALIZE_LABEL.
+ * target.h (gcc_target): Add globalize_label member.
+ * varasm.c (asm_output_bss, asm_output_aligned_bss,
+ globalize_decl): Use target hook.
+ (assemble_global): Delete.
+ (default_globalize_label): New function.
+
+2002-08-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * dsp16xx.h (dsp16xx_umulhi3_libcall): Delete.
+
+2002-08-20 Devang Patel <dpatel@apple.com>
+ * tree.c (get_qualified_type): Add TYPE_CONTEXT check.
+
+2002-08-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * arc.c (output_shift): Use stdio instead of asm_fprintf.
+ * arm.c (thumb_output_function_prologue): Likewise.
+ * avr.c (print_operand): Likewise.
+ * c4x.c (c4x_print_operand): Likewise.
+ * c4x.h (ASM_OUTPUT_INTERNAL_LABEL, TRAMPOLINE_TEMPLATE,
+ ASM_OUTPUT_REG_PUSH, ASM_OUTPUT_REG_POP): Likewise.
+ * cris.c (cris_target_asm_function_prologue,
+ cris_asm_output_mi_thunk): Likewise.
+ * h8300.c (print_operand): Likewise.
+ * h8300.h (ASM_OUTPUT_ADDR_VEC_ELT): Likewise.
+ * ip2k.c (print_operand): Likewise. Fix format specifier.
+ * m68hc11.c (asm_print_register, print_operand,
+ print_operand_address): Use stdio instead of asm_fprintf.
+ (print_operand_address): Fix format specifier.
+ * m68hc11.h (FUNCTION_PROFILER, ASM_OUTPUT_ADDR_DIFF_ELT,
+ ASM_OUTPUT_ADDR_VEC_ELT, ASM_OUTPUT_ALIGN): Use stdio instead of
+ asm_fprintf.
+ * m68k/amix.h (ASM_OUTPUT_INTERNAL_LABEL): Likewise.
+ * m68k/atari.h (ASM_OUTPUT_INTERNAL_LABEL): Likewise.
+ * m68k.c (m68k_output_function_prologue,
+ m68k_output_function_epilogue, print_operand): Likewise.
+ * mmix.c (mmix_asm_output_mi_thunk, mmix_asm_weaken_label):
+ Likewise. Fix format specifier.
+ * mn10200.h (ASM_OUTPUT_ADDR_VEC_ELT): Likewise.
+ * mn10300.h (ASM_OUTPUT_ADDR_VEC_ELT): Likewise.
+ * v850.h (ASM_OUTPUT_ADDR_VEC_ELT): Likewise.
+
+2002-08-15 Eric Christopher <echristo@redhat.com>
+ Jeff Knaggs <jknaggs@redhat.com>
+
+ * config.gcc (mipsisa64sr71k-elf): New target.
+ * config/mips/sr71k.md: New file.
+ * config/mips/mips.md: Use it.
+ (rot*): Add sr71k specifics.
+ * config/mips/t-sr71k: New file.
+ * config/mips/mips.h (sr71k): New cpu.
+ (TARGET_SR71K): Use it.
+ (TUNE_SR71K): Ditto.
+ (GENERATE_BRANCHLIKELY): Ditto.
+ (ISA_HAS_MULHI, ISA_HAS_MULS, ISA_HAS_MSAC, ISA_HAS_MACC,
+ ISA_HAS_ROTR_SIISA_HAS_ROTR_DI): Ditto.
+ * config/mips/mips.c (sr71k): New cpu.
+ (mips_use_dfa_pipeline_interface): Use.
+
+2002-08-15 Eric Christopher <echristo@redhat.com>
+ Richard Sandiford <rsandifo@redhat.com>
+ Aldy Hernandez <aldyh@redhat.com>
+ Graham Stott <grahams@redhat.com>
+ Michael Meissner <meissner@redhat.com>
+ Gavin Romig-Koch <gavin@redhat.com>
+ Ken Raeburn <raeburn@cygnus.com>
+ Alexandre Oliva <aoliva@redhat.com>
+
+ * config.gcc (mips64vr-elf): New target.
+ * config/mips/5400.md: New file.
+ * config/mips/5500.md: Ditto.
+ * config/mips/mips.md: Use them.
+ (frsqrt): New.
+ * config/mips/mips.c (vr4111, vr4121, vr4320, vr5400, vr5500): New
+ cpus.
+ (mips_issue_rate): Use them.
+ (mips_use_dfa_pipeline_interface): New function. Use for 5400 and 5500.
+ (TARGET_SCHEDUSE_DFA_PIPELINE_INTERFACE): Define. Use above.
+ * config/mips/mips.h (vr4111, vr4121, vr4320, vr5400, vr5500): New
+ cpus.
+ (TARGET_MIPSx): Use them.
+ (TUNE_MIPSx): Ditto.
+ (GETNATE_MULT3_SI): Ditto.
+ (ISA_HAS_BRANCHLIKELY): Ditto.
+ (ISA_HAS_CONDMOVE): Ditto.
+ (ISA_HAS_NMADD_NMSUB): Ditto.
+ (ISA_HAS_MULHI): New. Ditto.
+ (ISA_HAS_MULS): Ditto.
+ (ISA_HAS_MSAC): Ditto.
+ (ISA_HAS_MACC): Ditto.
+ (ISA_HAS_ROTR_SI): Ditto.
+ (ISA_HAS_ROTR_DI): Ditto.
+ (RTX_COSTS): Use.
+
+2002-08-20 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * cppinit.c (remove_dup_dir): Add head_ptr argument to handle removal
+ at head.
+ (remove_dup_nonsys_dirs): New function.
+ (remove_dup_dirs): Change argument head to head_ptr. Remove warnings.
+ (merge_include_chains): Remove non-system include directories from
+ quote and bracket include chains when they duplicate equivalent system
+ directories.
+ * doc/cpp.texi (-I): Update.
+ * doc/cppopts.texi (-I): Update.
+ * doc/install.texi (--with-local-prefix): Further document usage of
+ this option.
+ * doc/invoke.texi (-I): Update.
+
+2002-08-20 Richard Henderson <rth@redhat.com>
+
+ * expr.c (TARGET_MEM_FUNCTIONS): Transform to boolean.
+ (emit_block_move): Split out subroutines.
+ (emit_block_move_via_movstr): New.
+ (emit_block_move_via_libcall): New. Emit bcopy via normal call also.
+ (emit_block_move_libcall_fn): New. Construct function prototype for
+ bcopy as well.
+ (clear_storage): Split out subroutines.
+ (clear_storage_via_clrstr): New.
+ (clear_storage_via_libcall): New. Emit bzero as a normal call also.
+ (clear_storage_libcall_fn): New. Construct function prototype for
+ bzero as well.
+ (emit_push_insn): Use emit_block_move.
+ (expand_assignment): Booleanize TARGET_MEM_FUNCTIONS.
+ (store_constructor): Likewise.
+
+2002-08-19 Ziemowit Laski <zlaski@apple.com>
+
+ * objc/objc-act.c (building_objc_message_expr): Rename to
+ current_objc_message_selector.
+
+2002-08-19 Ziemowit Laski <zlaski@apple.com>
+
+ * objc/objc-act.c (build_ivar_chain): Remove.
+ (objc_copy_list): Likewise.
+ (get_class_ivars): Inline call to removed build_ivar_chain
+ function. Save off a clean copy of ivars in the CLASS_OWN_IVARS
+ slot; use that slot (rather than CLASS_IVARS) when accessing
+ ivars for base classes. Call copy_list and chainon instead of
+ objc_copy_list.
+ (build_private_template): Call get_class_ivars instead of
+ build_ivar_chain.
+ (start_class): Allocate room for the CLASS_OWN_IVARS slot.
+ (continue_class): Call get_class_ivars instead of
+ build_ivar_chain.
+ (encode_field_decl): Check for DECL_BIT_FIELD_TYPE instead
+ of DECL_BIT_FIELD (which may have been cleared).
+ * objc/objc-act.h (CLASS_OWN_IVARS): New accessor macro.
+
+2002-08-19 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * genautomata.c (output_translate_vect, output_state_ainsn_table,
+ output_min_issue_delay_table): Mark variable with ATTRIBUTE_UNUSED
+ in output file.
+ (output_internal_min_issue_delay_func): Initialize variable in
+ output file.
+
+2002-08-19 Alexandre Oliva <aoliva@redhat.com>
+
+ * Makefile.in (GCC_FOR_TARGET): Prepend STAGE_CC_WRAPPER.
+ (stage2_build, stage3_build, stage4_build): Likewise, to CC.
+
+2002-08-19 Geoffrey Keating <geoffk@redhat.com>
+ Steve Ellcey <sje@cup.hp.com>
+
+ * machmode.h (SCALAR_INT_MODE_P): New macro to test for
+ scaler integer mode (MODE_INT or MODE_PARTIAL_INT).
+ * explow.c (trunc_int_for_mode): Abort when the mode is not
+ a scaler integer mode.
+ * combine.c (expand_compound_operation): Don't expand Vector
+ or Complex modes into shifts.
+ (expand_field_assignment): Don't do bitwise arithmatic and
+ shifts on Vector or Complex modes.
+ (simplify_comparison): Don't call trunc_int_for_mode
+ for VOIDmode.
+ * recog.c (general_operand): Likewise.
+ (immediate_operand): Likewise.
+ (nonmemory_operand): Likewise.
+
+2002-08-19 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.c (rs6000_emit_set_const): Inline
+ multi-instruction SImode constant. Add REG_EQUAL note.
+ * config/rs6000/rs6000.md (movsi splitter): Use
+ rs6000_emit_set_const.
+
+2002-08-19 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * tree-inline.c (initialize_inlined_parameters): Wrap variable in
+ the macro test controlling its use.
+
+2002-08-18 H.J. Lu (hjl@gnu.org)
+
+ * config.gcc (*-*-linux*): Set extra_parts="crtbegin.o
+ crtbeginS.o crtbeginT.o crtend.o crtendS.o", gas=yes and
+ gnu_ld=yes.
+ (alpha*-*-linux*, cris-*-linux*, i370-*-linux*,
+ i[34567]86-*-linux*, x86_64-*-linux*, mips*-*-linux*,
+ s390-*-linux*, s390x-*-linux*, sparc-*-linux*, sparc64-*-linux*,
+ xtensa-*-linux*): Remove setting extra_parts, gas, and gnu_ld
here.
- * doc/invoke.texi: From here.
- * doc/sourcebuild.texi: Document location of documentation for
- machine built-in functions.
+ (cris-*-linux*): Remove setting thread_file here.
+
+2002-08-18 Neil Booth <neil@daikokuya.co.uk>
+
+ PR preprocessor/7602
+ * cppinit.c (path_include): Treat the system environment
+ variables as being cxx_aware.
-2002-01-13 Christopher Faylor <cgf@redhat.com>
+2002-08-17 Joseph S. Myers <jsm@polyomino.org.uk>
- * cppfiles.c (TEST_THRESHOLD): New macro.
- (SHOULD_MMAP): Ditto.
- (read_include_file): Use SHOULD_MMAP macro to decide when mmap should
- be used.
+ * c-decl.c (flexible_array_type_p): New function.
+ (grokdeclarator, finish_struct): Use it.
+ * doc/extend.texi: Document constraints on use of structures with
+ flexible array members.
-Mon Jan 14 20:23:34 CET 2002 Jan Hubicka <jh@suse.cz>
+2002-08-17 Richard Sandiford <rsandifo@redhat.com>
- * unroll.c (final_reg_note_copy): Properly handle
- REG_LABEL
- (unroll_loops): Fix LOOP_CONDITION heuristics.
+ * config/mips/t-coff, config/mips/t-elf, config/mips/t-isa3264,
+ config/mips/t-r3900 (MULTILIB_MATCHES): Define.
+ * config/mips/mips.h (ASM_SPEC): Use %(endian_spec).
-2002-01-14 Geoffrey Keating <geoffk@redhat.com>
+2002-08-16 Stan Shebs <shebs@apple.com>
- * doc/invoke.texi (Xstormy16 Options): Add xstormy16 option.
- * doc/md.texi (Machine Constraints): Use @minus{} where appropriate.
+ * c-common.c (cb_register_builds): Define __NEXT_RUNTIME__
+ for ObjC with -fnext-runtime.
+ * doc/cpp.texi: Document it.
-Mon Jan 14 20:18:19 CET 2002 Jan Hubicka <jh@suse.cz>
+2002-08-16 Janis Johnson <janis187@us.ibm.com>
- * cfgcleanup.c (try_forward_edges): Avoid infinite loop at infinite
- threaded loop.
+ * doc/install.texi (Final installation): Replace links to individual
+ build status pages with a link to a common page that lists them all.
-2002-01-14 Tom Rix <trix@redhat.com>
+2002-08-16 Sylvain Pion <pion@cs.nyu.edu>
- * config/rs6000/rs6000.md: Fix typo with sradi.
+ * doc/invoke.texi: Fix typo.
-2002-01-14 Ulrich Weigand <uweigand@de.ibm.com>
+2002-08-16 David Edelsohn <edelsohn@gnu.org>
+
+ * doc/install.texi (*-ibm-aix*): Explain AIX shared object versioning.
+
+2002-08-16 Andrew Haley <aph@redhat.com>
+
+ * tree-inline.c: Add includes for Java inliner.
+ (remap_decl): Don't handle anonymous types for Java.
+ (remap_block): Add handling for Java trees.
+ (copy_scope_stmt): Conditionalize for non-Java use only.
+ (copy_body_r): Handle Java trees. Add handling for
+ LABELED_BLOCK_EXPR, EXIT_BLOCK_EXPR, Java blocks.
+ (initialize_inlined_parameters): Handle Java trees.
+ (declare_return_variable): Likewise.
+ (expand_call_inline): Handle Java trees.
+ (walk_tree): Likewise.
+ (copy_tree_r): Don't handle SCOPE_STMTs for Java.
+ (add_stmt_to_compound): New function.
+
+2002-08-15 Richard Henderson <rth@redhat.com>
+
+ * Makefile.in (LOOSE_WARN): Remove -fno-common.
+ (NOCOMMON_FLAG): New substitution point.
+ (GCC_WARN_CFLAGS): Include it.
+ * configure.in (ac_checking): Set nocommon_flag.
+ (nocommon_flag): New substitution point.
+
+2002-08-15 Alexandre Oliva <aoliva@redhat.com>
+
+ * c-tree.h (skip_evaluation): Move declaration...
+ * c-common.h: ... here.
+ * c-typeck.c (build_external_ref): Don't assemble_external nor
+ mark a tree as used if skip_evaluation is set.
+ * c-parse.in (typeof): New non-terminal to set skip_evaluation
+ around TYPEOF.
+ (typespec_nonreserved_nonattr): Use it.
- * config/s390/s390.md (movstrdix_64, movstrsix_31, movstrdi_64,
- movstrsi_31, clrstrsi_64, clrstrsi_31): Improve RTL templates.
- (clrstrdi, clrstrsi): Adapt callers.
+2002-08-15 Douglas B Rupp <rupp@gnat.com>
+
+ * dbxout.c (dbx_debug_hooks): Update end_prologue, end_epilogue.
+ (xcoff_debug_hooks): Update end_prologue.
+ * debug.c (do_nothing_debug_hooks): Update end_prologue, end_epilogue.
+ * debug.h (end_prologue): Add file arg.
+ (end_epilogue): Add line and file args.
+ (dwarf2out_end_epilogue): Add line and file args.
+ (vmsdbgout_after_prologue): Remove.
+ * dwarf2out.c (dwarf2out_end_epilogue): Add line and file args.
+ (dwarf2_debug_hooks): Update end_prologue.
+ * dwarfout.c (dwarfout_end_epilogue): Add line and file args.
+ (dwarfout_end_prologue): Add file arg.
+ * final.c (vmsdbgout_after_prologue): Remove
+ (final_end_function): Update end_epilogue call.
+ (final_scan_insn): Update end_prologue call.
+ * sdbout.c (sdbout_end_epilogue): Add line and file args.
+ (sdbout_end_prologue): Add file arg.
+ (sdb_debug_hooks): Update end_prologue.
+ (sdb_begin_prologue): Update sdbout_end_prologue call.
+ * vmsdbgout.c (vmsdbg_debug_hooks): Add vmsdbgout_end_prologue,
+ vmsdbgout_end_function.
+ (vmsdbgout_end_prologue): New function renamed from
+ vmsdbgout_after_prologue. Call vmsdbgout_source_line.
+ (vmsdbgout_end_function): New function.
+ (vmsdbgout_end_epilogue): Add line and file args. Call
+ vmsdbgout_source_line.
+ (write_pclines): Write only valid line numbers.
+ (write_srccorr): Don't write source correlation records if 0 lines.
+ * xcoffout.c (xcoffout_end_epilogue): Add line and file args.
+
+2002-08-15 Steve Ellcey <sje@cup.hp.com>
+
+ * gcc/unwind.h (_Unwind_Ptr): Make 64 bits on IA64 HP-UX.
+ (_Unwind_Internal_Ptr): 32 bit version for use in
+ read_encoded_value_with_base.
+ * gcc/unwind-pe.h (read_encoded_value_with_base): Use
+ _Unwind_Internal_Ptr instead of _Unwind_Ptr in order to get the
+ right size.
+
+2002-08-15 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * loop.c (scan_loop, move_movables, count_one_set): Cast to avoid
+ signed/unsigned warnings.
+
+ * regclass.c (init_reg_sets_1, choose_hard_reg_mode,
+ record_reg_classes): Likewise.
+
+ * reload.c (reload_inner_reg_of_subreg, push_reload,
+ find_reloads_address_1): Likewise.
+
+2002-08-15 David Edelsohn <edelsohn@gnu.org>
+
+ * rs6000.c (output_mi_thunk): Return to function section on
+ TARGET_ELF.
+
+ * rs6000-c.c (rs6000_cpu_cpp_builtins): Define __PPC405__ if PPC405.
+
+2002-08-15 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.c (legitimize_address): Optimize loading
+ of large displacements.
+
+2002-08-14 Douglas B Rupp <rupp@gnat.com>
- (extendsidi2, zero_extendsidi2): Remove no-conflict blocks.
+ * config/alpha/alpha-protos.h: Update.
- (movti splitter): Never use register 0 as base register.
+ * config/alpha/alpha.c: (LINKAGE_SYMBOL_REF_P): New macro.
+ (alpha_legitimate_address_p): Test LINKAGE_SYMBOL_REF_P.
+ (alpha_linkage_symbol_p): New static function.
+ (print_operand_address): Print linkage operand.
-2002-01-14 Hartmut Penner <hpenner@de.ibm.com>
+ (alpha_funcs_num, alpha_funcs_tree, alpha_links_tree): New static
+ variables.
+ (reloc_kind): New enum.
+ (struct alpha_funcs): New struct.
+ (struct alpha_links): Add reloc_kind field. Rename links_kind field.
- * combine.c (simplify_shift_const): Always generate new rtx
- for shift expression instead of reusing given expression.
+ (alpha_need_linkage): Rewrite.
+ (alpha_use_linkage): New global function.
+ (alpha_write_linkage): Rewrite and make static.
+ (alpha_write_one_linkage): Rewrite
-Mon Jan 14 07:08:55 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ (alpha_start_function): Remove procedure descriptor output.
+ (alpha_end_function): Write linkages at end of each function.
- * config/alpha/alpha.c (alpha_expand_mov): Don't call
- alpha_legitimize_address unless mode is Pmode.
+ * config/alpha/alpha.md (call_vms, call_value_vms): Rewrite.
+ (call_vms_1, call_value_vms_1): Rewrite.
-2002-01-13 Geoffrey Keating <geoffk@redhat.com>
+ * config/alpha/vms.h (ASM_FILE_END): Remove.
- * doc/md.texi (Modifiers): Document the '*' constraint for the
- user.
+2002-08-14 Richard Henderson <rth@redhat.com>
- * doc/md.texi (Machine Constraints): Add constraints for xstormy16.
- * doc/extend.texi (Function Attributes): 'interrupt' is valid
- for xstormy16 too.
+ * ggc-page.c (RTL_SIZE): New.
+ (extra_order_size_table): Add specializations for 2 and 10 rtl slots.
+ * rtl.def (BARRIER, NOTE): Pad to 9 slots.
-2002-01-13 Richard Henderson <rth@redhat.com>
+2002-08-14 Richard Henderson <rth@redhat.com>
- * reload.c (find_reloads): Use a hard reg destination as reload reg
- for an input reload of the source.
+ * calls.c: Include target.h.
+ * Makefile.in (calls.o): Update.
-2002-01-13 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+ * config/alpha/alpha.c (alpha_end_function): Use targetm.binds_local_p.
+ * config/alpha/alpha.h (FUNCTION_OK_FOR_SIBCALL): Likewise.
- * doc/install.texi (Binaries): Make link to ftp.writtenword.com
- more generic.
+2002-08-14 Richard Henderson <rth@redhat.com>
-Sun Jan 13 07:23:01 2002 Douglas B Rupp <rupp@gnat.com>
+ * Makefile.in (LOOSE_WARN): Add -fno-common.
+ * c-common.h (constant_string_class_name): Add missing extern.
- * Makefile.in (LIB2FUNCS): Split into LIB2FUNCS_1 and LIB2FUNCS_2.
- * mklibgcc.in (LIB2FUNCS): Split into LIB2FUNCS_1 and LIB2FUNCS_2.
+2002-08-15 Neil Booth <neil@daikokuya.co.uk>
- * config/alpha/x-vms (USE_COLLECT2): Set to empty.
+ PR preprocessor/7358
+ * c-opts.c (check_deps_environment_vars): Ignore main file
+ for SUNPRO_DEPENDENCIES.
+ * cppfiles.c (stack_include_file): Ignore main file if
+ appropriate.
+ * cpplib.h (struct cpp_options): New member in deps.
+ * doc/cppenv.texi: Update.
-Sun Jan 13 06:55:31 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2002-08-14 Neil Booth <neil@daikokuya.co.uk>
- * dwarf2out.c (mem_loc_descriptor, case ADDRESSOF): New case.
+ PR preprocessor/7526
+ * cpplib.c (run_directive): Kludge so _Pragma dependency works.
-2002-01-12 Tom Rix <trix@redhat.com>
+2002-08-14 Nathan Sidwell <nathan@codesourcery.com>
- * config/rs6000/rs6000.c (rs6000_emit_set_long_const): Use ior for
- TARGET_POWERPC64.
+ * doc/invoke.texi (-a): Remove documentation.
+ (-fprofile-arcs): Remove reference to -a, -ax options.
+ * doc/gcov.texi (Gcov Data Files): Data might be merged.
-2002-01-12 Richard Henderson <rth@redhat.com>
+2002-08-14 Gabriel Dos Reis <gdr@nerim.net>
- * config/i386/i386.c (bdesc_2arg): Mark psadbw MASK_3DNOW_A.
+ Fix PR/7566
+ * c-semantics.c (genrtl_case_label): Don't (mis)use
+ warning_with_decl.
- * doc/invoke.texi: Update Alpha options.
+2002-08-14 Dale Johannesen <dalej@apple.com>
- * doc/invoke.texi: Update i386 built-in function lists.
+ * explow.c (emit_stack_restore): Emit memory clobbers
+ preceding the stack pop, to prevent the scheduler from
+ moving refs to variable arrays below this pop.
+ * reload1.c (reload): Preserve these clobbers for sched2.
+ * doc/rtl.texi: Document clobber (mem:BLK (scratch)).
-Sat Jan 12 17:38:11 CET 2002 Jan Hubicka <jh@suse.cz>
+2002-08-14 Neil Booth <neil@daikokuya.co.uk>
- * unroll.c (final_reg_note_copy): Avoid crash on REG_LABEL note
- referencing outside.
+ * c-opts.c (c_common_post_options): Correct test.
-Sat Jan 12 08:54:51 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+2002-08-14 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * diagnostic.c (warn_deprecated_use): Rework to lower indentation.
- * expr.c (emit_move_insn_1): Remove warning, use HOST_WIDE_INT for
- offsets, and change line folding.
- * optabs.c (expand_binop): Remove warnings.
- * sdbout.c (sdbout_record_type_name): Constify NAME to avoid warning.
+ * m88k.h (ASM_OUTPUT_SOURCE_FILENAME): Fix incorrect argument
+ order in call to fprintf.
-2002-01-12 Graham Stott <grahams@redhat.com>
+2002-08-14 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
- * attribs.c (handle_deprecated_attribute): constify WHAT.
- * diagnostic.c (warn_deprecated_use): Add braces, fixes
- dangling else warning and constify WHAT.
- * except.h (struct function, struct inline_remap): Move
- struct tag forward defs before all prototypes.
- (duplicate_eh_regions): Whitespace.
+ * config/sparc/sol2.h (SUBTARGET_EXTRA_SPECS): Define.
-2002-01-12 Nick Clifton <nickc@cambridge.redhat.com>
+2002-08-14 Ulrich Weigand <uweigand@de.ibm.com>
- * config/arm/arm.h (ARM_LEGITIMIZE_RELOAD_ADDRESS): Use
- MODE_BASE_REG_CLASS.
- (THUMB_LEGITIMIZE_RELOAD_ADDRESS): Use MODE_BASE_REG_CLASS.
+ * reload.c (find_reloads): Handle constraint letters marked by
+ EXTRA_ADDRESS_CONSTRAINT and EXTRA_MEMORY_CONSTRAINT.
+ (alternative_allows_memconst): Likewise.
+ * reload1.c (maybe_fix_stack_asms): Likewise.
+ * recog.c (asm_operand_ok, preprocess_constraints,
+ constrain_operands): Likewise.
+ * regclass.c (record_operand_costs, record_reg_classes): Likewise.
+ * local-alloc.c (block_alloc, requires_inout): Likewise.
+ * stmt.c (parse_output_constraint, parse_input_constraint): Likewise.
-2002-01-12 Richard Henderson <rth@redhat.com>
+ * defaults.h (EXTRA_MEMORY_CONSTRAINT): Provide a default.
+ (EXTRA_ADDRESS_CONSTRAINT): Likewise.
+ * doc/tm.texi: Document these two new target macros.
- * config/i386/i386.c (override_options): If SSE, enable sse prefetch.
- (ix86_expand_vector_move): New.
- (bdesc_2arg): Remove andps, andnps, orps, xorps.
- (ix86_init_mmx_sse_builtins): Make static. Remove composite builtins.
- Remove old prefetch builtins. Special case the logicals removed above.
- (ix86_expand_builtin): Likewise.
- (safe_vector_operand): Use V4SFmode, not TImode.
- (ix86_expand_store_builtin): Remove shuffle arg. Update callers.
- (ix86_expand_timode_binop_builtin): New.
- * config/i386/i386-protos.h: Update.
- * config/i386/i386.h (enum ix86_builtins): Update.
- * config/i386/i386.md: Correct predicates on MMX/SSE patterns.
- Use ix86_expand_vector_move in vector move expanders.
- (movti_internal, movti_rex64): Add xorps alternative.
- (sse_clrv4sf): Rename and adjust from sse_clrti.
- (prefetch): Don't work so hard.
- (prefetch_sse, prefetch_3dnow): Use PREFETCH rtx, not UNSPEC.
- * config/i386/xmmintrin.h (__m128): Use V4SFmode.
- (_mm_getcsr, _mm_setcsr): Fix typo in builtin name.
+ * config/s390/s390.c (s390_expand_plus_operand): Accept already
+ valid operands.
+ (q_constraint): New function.
+ config/s390/s390-protos.h (q_constraint): Declare it.
+ config/s390/s390.h (EXTRA_CONSTRAINT): Use it.
+ (EXTRA_MEMORY_CONSTRAINT): New macro.
-2002-01-11 Richard Henderson <rth@redhat.com>
+ * config/s390/s390.md: Throughout the machine description,
+ replace all instances of the constraint combinations 'Qo'
+ or 'oQ' with simply 'Q'.
- * config/i386/mmintrin.h: New file.
- * config/i386/xmmintrin.h: New file.
- * config.gcc (i?86-*-*): Add extra_headers.
- * simplify-rtx.c (simplify_unary_operation): Handle saturating
- truncation codes.
- (simplify_binary_operation): Handle saturating arithmetic codes.
- * config/i386/i386.c (ix86_expand_sse_comi): Return the full result,
- not the lowpart subreg.
- (ix86_expand_builtin): Return a TImode dummy register instead of 0
- on error.
- * config/i386/i386.md (mmx_clrdi): Override memory attribute.
+2002-08-14 Stephane Carrez <stcarrez@nerim.fr>
-2002-01-12 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+ * config/m68hc11/m68hc11.h (LINK_SPEC): Support -mrelax.
+ * config/m68hc11/t-m68hc11-gas (LIBGCC2_DEBUG_CFLAGS): Can use -g now.
+ (LIBGCC2_CFLAGS): Compile with -mrelax.
- * conflict.c (conflict_graph_compute): Free regsets when finished.
- * ssa.c (compute_coalesced_reg_partition): Likewise.
+2002-08-14 Stephane Carrez <stcarrez@nerim.fr>
-2002-01-12 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+ * doc/invoke.texi: Document -minmax for 68HC12.
- * global.c (find_reg): Check for HARD_REGNO_CALL_PART_CLOBBERED
- every where we allocate a register.
+ * config/m68hc11/m68hc11.md ("umaxqi3"): Use TARGET_MIN_MAX.
+ ("uminqi3"): Likewise.
+ ("uminhi3", "umaxhi3"): Likewise.
-2002-01-12 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+ * config/m68hc11/m68hc11.h (MASK_MIN_MAX): Define.
+ (TARGET_MIN_MAX): Define.
+ (TARGET_SWITCHES): New option -minmax/-mnominmax.
- * gcse.c (compute_pre_data, pre_gcse): Use sbitmap_free.
- * lcm.c (compute_earliest, compute_farthest): Likewise.
+2002-08-14 Stephane Carrez <stcarrez@nerim.fr>
-2002-01-11 Janis Johnson <janis187@us.ibm.com>
+ * config/m68hc11/t-m68hc11-gas (LIB1ASMFUNCS): Build __far_trampoline.
+ (MULTILIB_OPTIONS): Must also generate for -mlong-calls.
- * expr.c (expand_assignment): Fix misuse of MEM_KEEP_ALIAS_SET.
+ * config/m68hc11/larith.asm: Put a mode for ELF ABI flags.
+ (ret, declare, farsym): New gas macros.
+ (__premain, exit, abort, _cleanup, memcpy, memset, ___adddi3,
+ ___subdi3, ___notdi2, __mulhi32, __mulsi3): Use them to use 'rtc'
+ and declare the symbol far when compiled with -mlong-calls.
+ (__far_trampoline): New for 68HC12 trampoline code to invoke a
+ far handler using jsr/bsr.
-2002-01-11 Janis Johnson <janis187@us.ibm.com>
+ * config/m68hc11/m68hc11-crt0.S: Put a mode for ELF ABI flags.
+ (jsr): New macro to transform a 'jsr' into a 'call'.
- * doc/rtl.texi (Insns): Fix 2 typos.
+2002-08-14 Stephane Carrez <stcarrez@nerim.fr>
-2002-01-11 Joseph S. Myers <jsm28@cam.ac.uk>
+ * doc/invoke.texi: Document -mlong-calls for 68HC12.
- * doc/invoke.texi: Avoid overfull hboxes. Add summary of D30V
- options. Use @table @gcctabopt for MMIX options. Add index
- entries for MMIX options. Start new paragraph with first
- heading of the machine-dependent options.
+ * config/m68hc11/m68hc11.h (CPP_SPEC): Pass -D__USE_RTC__ when
+ -mlong-calls is specified.
+ (ASM_DECLARE_FUNCTION_NAME): Define to generate .far and .interrupt
+ assembler directives.
+ (TARGET_LONG_CALL, MASK_LONG_CALL): Declare.
+ (TARGET_SWITCHES): Add -mlong-calls options.
+ (current_function_far): Declare.
-2002-01-11 Craig Rodrigues <rodrigc@gcc.gnu.org>
+ * config/m68hc11/m68hc11.c (m68hc11_initial_elimination_offset): Take
+ into account the page register saved on the stack.
+ (m68hc11_override_options): Take into account -mlong-calls option.
+ (m68hc11_asm_file_start): Put a mode for the ELF flags ABI.
- PR other/5299
- * config/ns32k/ns32k.md: Fix spelling mistake of "than" in comments.
- * combine.c (force_to_mode): Same.
- * reload1.c (clear_reload_reg_in_use): Same.
+ * config/m68hc11/m68hc11.md ("*return_32bit"): Return rtc
+ if the function is going to be in 68HC12 banked memory (-mlong-calls).
+ ("*return_16bit"): Likewise.
+ ("*return_void"): Likewise.
+ ("call", "call_value"): Use call for a far function call.
-2002-01-11 Nick Clifton <nickc@cambridge.redhat.com>
+2002-08-14 Neil Booth <neil@daikokuya.co.uk>
- * config/arm/arm.c (arm_gen_constant): Correct test of 'remainder'
- and 'subtargets'.
+ * toplev.c (parse_options_and_default_flags): Don't call
+ post_options here.
+ (general_init): Initialize GC, pools and tree hash here,
+ instead of lang_independent_init.
+ (lang_independent_init): Rename backend_init.
+ (do_compile): Call post_options hook; exit early if there
+ have been errors after switch processing.
+ (toplev_main): Update.
+
+2002-08-14 Gabriel Dos Reis <gdr@nerim.net>
+
+ * c-pretty-print.h: Guard against multiple inclusion.
+ Robustify macros.
+ (pp_c_attributes): Declare.
+ * c-pretty-print.c (pp_c_attributes): New function.
+
+2002-08-13 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * m68k.c (m68k_output_function_prologue,
+ m68k_output_function_epilogue): Delete versions for DPX2/MOTOROLA
+ and NEWS/MOTOROLA.
+ * genattrtab.c: Remove dpx2 comment.
+ * libgcc2.c (__enable_execute_stack): Delete versions for
+ NeXT/__MACH__, __convex__, __sysV88__, __pyr__ and
+ sony_news/SYSTYPE_BSD.
+ * longlong.h: Delete code for __a29k__, _AM29K, __clipper__,
+ __gmicro__, __i860__, __NeXT__ and __pyr__.
+ * rtl.h: Remove convex comment.
+ * varasm.c: Likewise.
-2002-01-11 Andreas Jaeger <aj@suse.de>,
- Brad Lucier <lucier@math.purdue.edu>
+2002-08-13 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * config/i386/i386.h (CPP_CPUCOMMON_SPEC): Remove wrong
- mcpu.
+ * c-opts.c (lang_flags): Const-ify.
+ * ra-build.c (undef_table): Likewise.
+ * ra.c (eliminables): Likewise.
-Fri Jan 11 07:35:12 2002 Douglas B Rupp <rupp@gnat.com>
+2002-08-14 Gabriel Dos Reis <gdr@nerim.net>
- * config/alpha/vms.h: (MD_FALLBACK_FRAME_STATE_FOR): Fix errors.
- Protect with IN_LIBGCC.
- (LINK_EH_SPEC): Add required trailing space.
+ * tree.h: Guard against multiple inclusion.
-Fri Jan 11 09:25:05 2002 Nicola Pero <n.pero@mi.flashnet.it>
+2002-08-14 Hans-Peter Nilsson <hp@bitrange.com>
- * c-tree.h: Move function declarations so that they are listed
- under the filename which contains them.
- (check_identifier, finish_decl_top_level,
- lookup_name_current_level_global, shadow_record_fields): Remove.
+ * reload1.c (reload_cse_simplify): Before checking
+ REG_FUNCTION_VALUE_P, check REG_P.
-2002-01-11 Andreas Jaeger <aj@suse.de>
+2002-08-13 Geoffrey Keating <geoffk@redhat.com>
- * config/i386/i386.h (CPP_CPUCOMMON_SPEC): Remove duplicated
- march.
+ * Makefile.in (attribs.o): Remove $(OBSTACK_H) dependency.
-2002-01-10 Richard Henderson <rth@redhat.com>
+2002-08-13 Neil Booth <neil@daikokuya.co.uk>
- * config/alpha/alpha.c (print_operand): Add 'J'.
- * config/alpha/alpha.md (call_osf_1_er, call_value_osf_1_er): Take a
- new operand with the sequence number for the lituse. When splitting
- the insns, use gen_movdi_er_high_g and generate a sequence number.
- (gen_movdi_er_high_g): Print the sequence number if non-zero.
+ * c-opts.c (c_common_init_options): Extra braces needed.
-2002-01-10 Aldy Hernandez <aldyh@redhat.com>
+2002-08-13 J"orn Rennecke <joern.rennecke@superh.com>
- * config/rs6000/rs6000.c (altivec_init_builtins): Add support for
- lvebx, lvehx, lvewx, lvxl, lvx, stvx, stvebx, stvehx, stvewx,
- stvxl.
- (altivec_expand_builtin): Same.
- (altivec_expand_stv_builtin): New.
+ * sh.c (sh_init_builtins): Add PARAMS to declaration.
+ (sh_media_init_builtins, sh_expand_builtin): Likewise.
+ (sh_expand_unop_v2sf): Use PARAMS for variable declaration.
+ (sh_expand_binop_v2sf): Likewise.
+ * sh-protos.h (sh_expand_unop_v2sf): Add PARAMS to declaration.
+ (sh_expand_binop_v2sf, sh_cfun_interrupt_handler_p): Likewise.
+ (sh_initialize_trampoline): Likewise.
- * config/rs6000/rs6000.h (rs6000_builtins): Same.
+2002-08-13 Ulrich Weigand <uweigand@de.ibm.com>
- * config/rs6000/rs6000.md ("altivec_lvebx"): New.
- ("altivec_lvehx"): New.
- ("altivec_lvewx"): New.
- ("altivec_lvxl"): New.
- ("altivec_lvx"): New.
- ("altivec_stvx"): New.
- ("altivec_stvebx"): New.
- ("altivec_stvehx"): New.
- ("altivec_stvewx"): New.
- ("altivec_stvxl"): New.
+ * s390-modes.def [CCL1, CCL2, CCT1, CCT2, CCT3, CCUR, CCSR]: Declare
+ new condition code modes.
+ s390.c (s390_match_ccmode_set): Handle those new CC modes.
+ (s390_select_ccmode): Likewise.
+ (s390_branch_condition_mask): Likewise.
-2002-01-10 Richard Henderson <rth@redhat.com>
+ * s390-protos.h (s390_tm_ccmode): Declare.
+ s390.c (s390_tm_ccmode): New function.
+ (s390_match_ccmode): Allow VOIDmode as REQ_MODE.
- * cfgrtl.c (delete_insn): Assert insn hasn't been deleted yet.
- * reload1.c (delete_output_reload): Zap spill_reg_store. Take
- care not to delete instructions twice.
+ * s390.md ("*cmpdi_tm2"): Rename to "*tmdi_ext".
+ ("*cmpsi_tm2"): Rename to "*tmsi_ext".
+ ("*cmpqi_tm2"): Rename to "*tmqi_ext".
-2002-01-10 Zack Weinberg <zack@codesourcery.com>
+ ("*cmpdi_tm_reg", "*cmpdi_tm_mem", "*cmpsi_tm_reg", "*cmpsi_tm_mem",
+ "*cmphi_tm_sub","*cmphi_cct_0", "*cmpqi_tm", "*cmpqi_tm_sub",
+ "*cmpqi_cct_0", "*tm_0"): Remove, replace by ...
+ ("*tmdi_reg", "*tmsi_reg", "*tmdi_mem", "*tmsi_mem", "*tmhi_mem",
+ "*tmqi_mem", "*tmhi_full", "*tmqi_full"): ... these new patterns.
- * toplev.c: Don't declare environ (it's not used anywhere).
- * configure.in: Don't check for declaration of environ.
- * config/i386/xm-mingw32.h: Don't #define environ.
- * config.in, configure: Regenerate.
+ ("*ltgr", "*cmpdi_ccs_0_64", "*cmpdi_ccs_0_31", "*ltr", "*icm15",
+ "*icm15_cconly", "*cmpsi_ccs_0", "*icm3", "*cmphi_ccs_0", "*icm1",
+ "*cmpqi_ccs_0"): Remove, replace by ...
+ ("*tstdi_sign", "*tstdi", "*tstdi_cconly", "*tstdi_cconly_31",
+ "*tstsi", "*tstsi_cconly", "*tstsi_cconly2", "*tsthi", "*tsthi_cconly",
+ "*tstqi", "*tstqi_cconly"): ... these new patterns.
-2002-01-10 Zack Weinberg <zack@codesourcery.com>
+ ("*cmpsidi_ccs"): Remove, replace by ...
+ ("*cmpsi_ccs_sign"): ... this new pattern.
+ ("*cmpdi_ccs_sign", "*cmpdi_ccu_zero"): New patterns.
- * configure.in: Set stage1_cflags for powerpc-*-darwin*.
- * configure: Regenerate.
+ ("*cmpqi_ccu_0", "*cmpqi_ccu_immed"): Remove, replace by ...
+ ("*cli"): ... this new pattern.
- * config/interix.h: Set DO_GLOBAL_CTORS_BODY and
- DO_GLOBAL_DTORS_BODY here, not in xm-interix.h.
- * config/alpha/vms.h: Set INCLUDE_DEFAULTS here, not in
- alpha/xm-vms.h.
- * config/m68k/t-next: Set OTHER_FIXINCLUDES_DIRS and
- LIMITS_H_TEST here, not in m68k/x-next.
- * config/rs6000/beos.h: Set STANDARD_INCLUDE_DIR and
- SYSTEM_INCLUDE_DIR here, not in rs6000/xm-beos.h.
+ ("*adddi3_sign", "*adddi3_zero_cc", "*adddi3_zero_cconly",
+ "*adddi3_zero", "*adddi3_cc", "*adddi3_cconly", "*adddi3_cconly2"):
+ New patterns.
+ ("adddi3_64"): Rename to "*adddi3_64".
+ ("adddi3_31"): Replace by insn and splitter "*adddi3_31".
+ ("adddi3"): Adapt expander.
- * config/x-interix: Don't set RANLIB, RANLIB_TEST, SHELL,
- LIBGCC2_INCLUDES, or SYSTEM_HEADER_DIR.
- * config/alpha/x-vms: Don't set USE_COLLECT2. Add comments.
+ ("*addsi3_cc"): Allow "general_operand" for operand 2.
+ ("*addsi3_carry1_cc", "*addsi3_carry1_cconly",
+ "*addsi3_carry2_cc", "*addsi3_carry2_cconly"): New patterns.
- * config/i386/x-djgpp: Renamed i386/t-djgpp.
- * config/m88k/x-dolph: Renamed m88k/t-dolph.
- * config/m88k/x-texXD88: Renamed m88k/t-texXD88.
- * config/pa/x-pa-mpeix: Renamed pa/t-mpeix. Update for
- replacement of quadlib.asm with quadlib.c.
+ ("addhi3", "addqi3"): Remove, replace by ...
+ ("*addsi3_sign", "*addsi3_sub"): ... these new patterns.
- * config/x-interix3, config/xm-interix.h, config/i386/x-beos,
- config/i386/xm-osf1elf.h, config/rs6000/x-darwin,
- config/rs6000/xm-beos.h: Delete file.
+ ("*subdi3_sign", "*subdi3_zero_cc", "*subdi3_zero_cconly",
+ "*subdi3_zero", "*subdi3_cc", "*subdi3_cconly"): New patterns.
+ ("subdi3"): Replace by insn and splitter "*subdi3_31".
+ ("subdi3"): New expander.
- * config.gcc: Update to match above changes.
+ ("*subsi3_borrow_cc", "*subsi3_borrow_cconly"): New patterns.
-2002-01-10 Kazu Hirata <kazu@hxi.com>
+ ("subhi3", "subqi3"): Remove, replace by ...
+ ("*subsi3_sign", "*subsi3_sub"): ... these new patterns.
- * config/h8300/h8300.h: Fix comment typos.
- * config/h8300/h8300.md: Likewise.
- * config/h8300/lib1funcs.asm: Likewise.
+ ("*muldi3_sign"): New pattern.
+ ("muldi3"): Do not clobber CC.
+ ("mulsi3"): Likewise.
+ ("mulsi_6432"): Likewise.
-2002-01-10 Dale Johannesen <dalej@apple.com>
+2002-08-13 Denis Chertykov <denisc@overta.ru>
- PR optimization/5269
- * unroll.c (precondition_loop_p): Make *increment be the correct
- sign when n_iterations known, to avoid confusing caller.
+ * config/avr/avr.md: Call CC_STATUS_INIT in all peepnoles
+ which can change CC0.
-2002-01-10 Kazu Hirata <kazu@hxi.com>
+2002-08-13 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * gcse.c (adjust_libcall_notes): New function.
+ (do_local_cprop): Use it. Add fourth parameter. Changed caller.
+
+2002-08-13 Nathan Sidwell <nathan@codesourcery.com>
+
+ * libgcc2.c (L_bb): Remove unneeded #includes.
+ (__global_counters, __gthreads_active): Remove unused globals.
+ (__bb_exit_func): Merge counts into files rather than appending.
+ * Makefile.in (INTERNAL_CFLAGS): Move COVERAGE_FLAGS from here ...
+ (ALL_CFLAGS): ... to here.
+
+2002-08-13 Denis Chertykov <denisc@overta.ru>
+
+ * config/ip2k/ip2k.c (commands_in_file): Variable removed.
+ (function_epilogue): Don't calculate function size.
+ (ip2k_set_compare): Don't use lookup_const_double.
+ (asm_file_start): Initialization of commands_in_file removed.
+ (asm_file_end): Output of commands_in_file removed.
+
+ * config/ip2k/ip2k.c (CPP_PREDEFINES): Remove definition of
+ __INT_MAX__.
+
+2002-08-13 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-opts.c (c_common_init_options): Check option array is
+ sorted if checking enabled.
+
+2002-08-13 Gabriel Dos Reis <gdr@nerim.net>
+
+ * c-pretty-print.c: #include "c-tree.h".
+ (pp_c_simple_type_specifier): Tweak.
+ (pp_c_storage_class_specifier): New.
+ (pp_c_function_specifier): Likewise.
+ (pp_c_declaration_specifiers): Likewise.
+ (pp_c_init_declarator): Likewise.
+ (pp_c_declaration): Likewise.
+ (pp_c_direct_declarator): Stub.
+ (pp_c_declarator): Likewise.
+ (pp_c_parameter_declaration): Likewise.
+
+2002-08-13 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-opts.c (deps_seen, deps_file, deferred_count, deferred_size,
+ handle_deferred_opts, sanitize_cpp_opts, defer_opt,
+ struct deferred_opt): New.
+ (COMMAND_LINE_OPTIONS): Add -M*.
+ (missing_arg): Update.
+ (c_common_decode_option): Handle -M*.
+ (c_common_post_options): Handle -M*. Use sanitize_cpp_opts;
+ don't call cpp_post_options.
+ (c_common_finish, check_deps_environment_vars): Update.
+ * cppfiles.c (stack_include_file, handle_missing_header): Update.
+ * cpphash.h (CPP_PRINT_DEPS): Remove.
+ * cppinit.c: Don't include version.h.
+ (cpp_create_reader): Don't call deps_init. Initialize
+ warn_long_long.
+ (cpp_read_main_file): Init deps if necessary.
+ (cpp_destroy): Conditionally free deps.
+ (cpp_finish): Update.
+ (no_tgt): Remove.
+ (COMMAND_LINE_OPTIONS, cpp_handle_option): Remove -M*.
+ (cpp_post_options): Rename post_options.
+ * cpplib.h (struct cpp_options): Remove some dependency options;
+ move others to a new structure.
+ (cpp_post_options): Remove.
+ (cpp_finish): Comment.
+ * fix-header.c (read_scan_file): Don't call cpp_post_options.
+
+2002-08-12 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.md (define_constants): Add MMIX_rR_REGNUM.
+ ("divdi3", "*divdi3_nonknuth", "moddi3", "*moddi3_nonknuth"): Mark
+ MMIX_rR_REGNUM as clobbered.
+ * config/mmix/mmix.h (MMIX_REMAINDER_REGNUM): Use MMIX_rR_REGNUM.
+
+2002-08-12 Gabriel Dos Reis <gdr@nerim.net>
+
+ * diagnostic.h (output_formatted_scalar): Rename from
+ output_formatted_integer.
+ * diagnostic.def: Add DK_DEBUG.
+ * diagnostic.c (output_decimal): Adjust.
+ (output_long_decimal): Likewise.
+ (output_unsigned_decimal): Likewise.
+ (output_octal): Likewise.
+ (output_long_octal): Likewise.
+ (output_hexadecimal): Likewise.
+ (output_long_hexadecimal): Likewise.
+ * c-pretty-print.c (pp_c_type_specifier): New function.
+ (pp_c_specifier_qualifier_list): Likewise.
+ (pp_c_abstract_declarator): Likewise.
+ (pp_c_char): Replace pp_format_integer with pp_format_scalar.
+
+2002-08-12 David Edelsohn <edelsohn@gnu.org>
+
+ * doc/trouble.texi (Disappointments): Add static constructor and
+ destructor dependency information for AIX.
+
+2002-08-12 Neil Booth <neil@daikokuya.co.uk>
+
+ * cpphash.h (struct printer): New from cppmain.c.
+ (cpp_reader): New member.
+ * cppmain.c (struct printer): Move to cpphash.h.
+ (options, print): Remove.
+ (account_for_newlines, print_line, maybe_print_line,
+ cpp_preprocess_file, setup_callbacks, scan_translation_unit,
+ scan_translation_unit_trad, cb_line_change, cb_ident,
+ cb_define, cb_undef, cb_include, cb_file_change, dump_macro,
+ cb_def_pragma): Make reentrant.
+
+2002-08-12 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * real.c (ieee_64): Always define.
+ (ieee_113): Guard with INTEL_EXTENDED_IEEE_FORMAT == 0.
+ (dec_h): Not used yet, hide it.
+ (emdnorm): Mark parameter in ATTRIBUTE_UNUSED. Guard label with
+ macro controlling use.
+ (TFbignan, TFlittlenan): Guard with INTEL_EXTENDED_IEEE_FORMAT == 0.
+
+2002-08-12 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (tablejump): Sign extend the operand.
+ * i386.c (classify_argument): Fix missed case from previous patch.
+
+2002-08-12 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-common.c (STDC_0_IN_SYSTEM_HEADERS, c_common_init): Move
+ to c-copts.c.
+ (warn_multichar): Die.
+ (cb_register_builtins): Export.
+ * c-common.h (warn_multichar, preprocess_file): Remove.
+ (cb_register_builtins): New.
+ * c-lang.c (c_init): Remove.
+ (LANG_HOOKS_INIT): Use c_objc_common_init.
+ * c-lex.c (init_c_lex): Don't canonicalize filename.
+ * c-opts.c (in_fname, STDC_0_IN_SYSTEM_HEADERS): New.
+ (preprocess_file): Make static. Update for cpplib.
+ (c_common_decode_option): Remove warn_multichar. Use in_fname.
+ (c_common_post_options): Set some cpp options here.
+ (c_common_init): Move from c-common.c.
+ * cppinit.c (cpp_post_options): Don't canonicalize in_fname.
+ * cpplib.h (struct cpp_options): Remove in_fname.
+ (cpp_preprocess_file): Update.
+ * cppmain.c (cpp_preprocess_file): Update for new prototypes.
+
+2002-08-11 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * config.gcc (mips*-*-netbsd*): Include ${tm_file}.
+
+2002-08-11 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * i370.h (TARGET_CPU_CPP_BUILTINS): Remove spurious trailing
+ backslash in comment preceeding macro definition.
+ * i370/linux.h (TARGET_OS_CPP_BUILTINS): Likewise.
+ * i370/mvs.h (TARGET_OS_CPP_BUILTINS): Likewise.
+ * i370/oe.h (TARGET_OS_CPP_BUILTINS): Likewise.
+
+2002-08-12 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * expr.c (store_expr): In condition for checking if value is
+ generated in TARGET, move call to expr_size last.
+
+2002-08-11 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-common.c (c_common_init): Call preprocess_file instead.
+ (c_common_finish): Move to c-opts.c.
+ * c-common.h (preprocess_file): new.
+ * c-opts.c (out_fname, out_stream, deps_append, preprocess_file,
+ check_deps_environment_vars, c_common_finish): New.
+ (c_common_decode_option): Update for out_fname and dependencies.
+ * cppinit.c (init_dependency_output, output_deps): Remove.
+ (cpp_destroy): Update prototype.
+ (cpp_add_dependency_target): New.
+ (cpp_read_main_file): Don't overlay a buffer.
+ (cpp_finish): Take a deps output stream and write deps to it.
+ Return the error count.
+ (cpp_post_options): Don't canonicalize out_fname, or do anything
+ with dependencies.
+ * cpplib.h (struct cpp_options): Remove out_fname and
+ preprocess_only.
+ (cpp_add_dependency_target): New.
+ (cpp_destroy, cpp_finish, cpp_preprocess_file): Update.
+ * cppmain.c (cpp_preprocess_file): Update prototype. Don't
+ set preprocess_only. Don't handle the output stream directly.
+
+2002-08-11 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * dsp16xx.c (print_operand): Fix format specifier.
+ * dsp16xx.md: Avoid automatic aggregate initialization.
+ * frv.h (REG_CLASS_FROM_LETTER): Avoid char as array index.
+ * h8300.c (emit_a_rotate, h8300_adjust_insn_length): Avoid U
+ integer constant modifier.
+ * ip2k.c (ip2k_set_compare): Avoid signed/unsigned warning.
+ * mmix-protos.h (mmix_use_simple_return): Move outside TREE_CODE
+ guards.
+ * sh/netbsd-elf.h (FUNCTION_PROFILER): Fix format specifier.
+ * v850.c (v850_select_section): Mark parameter with
+ ATTRIBUTE_UNUSED.
+ * global.c (global_alloc): Const-ify.
+ * ra-colorize.c (hardregset_to_string): Fix format specifier.
+
+2002-08-11 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * darwin-c.c (darwin_pragma_options): Const-ify.
+ * darwin.c (machopic_non_lazy_ptr_name,
+ machopic_validate_stub_or_non_lazy_ptr): Likewise.
+ (machopic_indirect_data_reference): Wrap variables in macros
+ controlling their use.
+ (machopic_finish, update_non_lazy_ptrs, update_stubs): Const-ify.
+ (machopic_select_section): Use parentheses around && within ||.
+ * i386/darwin.h (ASM_OUTPUT_ALIGN): Avoid ambiguous-else.
+
+2002-08-11 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * ip2k.c (mdr_resequence_xy_yx, mdr_propagate_reg_equivs,
+ mdr_try_move_dp_reload, ip2k_check_can_adjust_stack_ref,
+ ip2k_adjust_stack_ref, mdr_try_move_pushes, mdr_try_propagate_clr,
+ ip2k_xexp_not_uses_reg_for_mem, mdr_try_propagate_move,
+ mdr_try_remove_redundant_insns, track_w_reload,
+ mdr_try_wreg_elim): Make function static to match prototype.
+ * mmix.c (mmix_target_asm_function_epilogue): Likewise. Mark
+ parameter with ATTRIBUTE_UNUSED.
+
+2002-08-11 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * arc.c (arc_init): Don't use ISO C style function definitions.
+ * arm.c (count_insns_for_constant, thumb_far_jump_used_p,
+ arm_get_strip_length, arm_strip_name_encoding): Likewise.
+ * avr.h (progmem_section): Likewise.
+ * h8300.c h8300_asm_insn_count): Likewise.
+ * m32r.c (init_idents): Likewise.
+ * s390.c (s390_split_branches, s390_chunkify_pool): Likewise.
+ * sh.c (sh_cfun_interrupt_handler_p): Likewise.
+ * xtensa.c (xtensa_build_va_list): Likewise.
+
+2002-08-11 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-common.h (enum c_language_kind): Emphasize that clk_c is 0.
+ * c-opts.c (parse_option): Rename find_opt.
+ (set_std_c99): New function.
+ (COMMAND_LINE_OPTIONS): Handle -remap and -o. Remove OPT_std_bad.
+ (missing_arg): Remove OPT_std_bad. Handle -o.
+ (c_common_decode_option): Handle input and output file names,
+ -o and -remap. Clean up -std= handling.
+ * cppinit.c (COMMAND_LINE_OPTIONS): Remove OPT_o and OPT_remap.
+ (cpp_handle_option): Similarly. Don't handle filenames.
+
+2002-08-11 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (classify_argument): Fix computing of field's offsets.
+
+2002-08-11 Andreas Jaeger <aj@suse.de>
- * doc/extend.texi (deprecated): Fix a typo.
+ PR target/7531:
+ * doc/invoke.texi (i386 and x86-64 Options): Document -mcmodel.
-Thu Jan 10 22:35:54 CET 2002 Jan Hubicka <jh@suse.cz>
+2002-08-10 Ziemowit Laski <zlaski@apple.com>
- * basic-block.h (update_br_prob_note): Declare.
- * cfgcleanup.c (try_simplify_condjump): Call update_br_prob_note.
- (try_forward_edges): Care negative frequencies and update note.
- (outgoing_edges_match): Tweek conditional merging heuristics.
- (try_crossjump_to_edge): use update_br_prob_note.
- * cfglayout.c (fixup_reorder_chain): Likewise.
- * cfrtl.c (update_br_prob_note): New.
- * ifcvt.c (dead_or_predicable): Call update_br_prob_note.
+ * config/alpha/alpha.h (TARGET_CPU_CPP_BUILTINS): Replace
+ reference to clk_objective_c with flag_objc.
+ * config/i386/i386-interix.h (TARGET_OS_CPP_BUILTINS):
+ Likewise.
+ * config/mips/mips.h (TARGET_CPU_CPP_BUILTINS): Likewise.
+
+2002-08-10 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-opts.c (set_std_cxx98, set_std_c89): New.
+ (COMMAND_LINE_OPTIONS): Move more from cppinit.c.
+ (c_common_decode_option): Handle new switches from cppinit.c.
+ Add -std=gnu++98.
+ * cppinit.c (set_lang): Rename cpp_set_lang. Export.
+ (no_arg, no_num): Remove.
+ (COMMAND_LINE_OPTIONS): Move more to c-opts.c. Drop all lang-
+ switches apart from -lang-objc and lang-asm.
+ (cpp_handle_option): Similarly.
+ * cpplib.h (cpp_set_lang): New.
+ * doc/cppopts.texi, doc/invoke.texi: Document -std=c++98,
+ -std=gnu++98.
+ * objc/lang-specs.h: Remove -ansi.
+
+2002-08-10 Jan Hubicka <jh@suse.cz>
+ Graham Stott
+
+ * cfg.c (redirect_edge_succ_nodup): Avoid overflows due to roundoff
+ errors.
+
+2002-08-10 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * emit-rtl.c (emit_jump_insn_before, emit_call_insn_before,
+ emit_jump_insn): Fix uninitialized variable.
+ * gcov.c (init_line_info): Likewise.
+ * genautomata.c (transform_3): Add braces around ambiguous
+ else.
+ * ifcvt.c (cond_exec_process_insns): Mark parameter with
+ ATTRIBUTE_UNUSED.
+ * ra-build.c (parts_to_webs_1): Fix uninitialized variable.
+ * regrename.c (copyprop_hardreg_forward): Fix uninitialized
+ variable.
+
+ * gengtype.c (write_gc_structure_fields): Avoid signed/unsigned
+ warnings in output files.
+
+2002-08-09 Ziemowit Laski <zlaski@apple.com>
+
+ * c-common.c (flag_objc): New.
+ * c-common.h (c_language_kind): Get rid of clk_objective_c
+ enum value.
+ (flag_objc): New extern declaration.
+ * c-decl.c (implicitly_declare): Call objc_check_decl
+ instead of maybe_objc_check_decl.
+ (finish_decl): Likewise.
+ (grokfield): Likewise.
+ (finish_struct): Likewise.
+ * c-lang.c (maybe_objc_check_decl): Rename to objc_check_decl.
+ (maybe_objc_comptypes): Rename to objc_comptypes.
+ (maybe_building_objc_message_expr): Rename to
+ objc_message_selector.
+ * c-lex.c (lex_charconst): Remove uses of clk_objective_c,
+ replace with flag_objc as needed.
+ * c-opts.c (c_common_init_options): Likewise.
+ (c_common_decode_option): Likewise.
+ * c-parse.in (init_reswords): Likewise.
+ * c-tree.h (maybe_objc_check_decl): Rename to objc_check_decl.
+ (maybe_objc_comptypes): Rename to objc_comptypes.
+ (maybe_building_objc_message_expr): Rename to
+ objc_message_selector.
+ * c-typeck.c (comptypes): Call objc_comptypes instead of
+ maybe_objc_comptypes, and/or objc_message_selector instead of
+ maybe_building_objc_message_expr.
+ (comp_target_types): Likewise.
+ (convert_for_assignment): Likewise.
+ (warn_for_assignment): Likewise.
+ * cppinit.c (init_builtins): Set __OBJC__ manifest constant
+ independently of those for other languages.
+ * objc/objc-act.c (maybe_objc_comptypes): Delete.
+ (maybe_objc_check_decl): Delete.
+ (maybe_building_objc_message_expr): Rename to
+ objc_message_selector.
+ * objc/objc-lang.c (objc_init_options): Use clk_c instead of
+ clk_objective_c; set flag_objc flag.
+
+2002-08-09 Toshiyasu Morita <toshiyasu.morita@hsa.hitachi.com>
+
+ * ifcvt.c (find_if_case_2): Test correct basic block for size.
+
+2002-08-09 Dale Johannesen <dalej@apple.com>
+
+ * config/rs6000/rs6000.md: Add sibcall patterns.
+ * config/rs6000/rs6000.h (FUNCTION_OK_FOR_SIBCALL): Define.
+ * config/rs6000/rs6000.c (rs6000_ra_ever_killed):
+ Rewritten to handle sibcalls.
+ * config/rs6000/rs6000.c (function_ok_for_sibcall): New.
+ * config/rs6000/rs6000-protos.h (function_ok_for_sibcall): New.
+
+2002-08-08 Nathan Sidwell <nathan@codesourcery.com>
+
+ * profile.c (da_file_name): New static var.
+ (init_branch_prob): Initialize it.
+ (end_branch_prob): Remove da file.
+
+ * Makefile.in (stage1_build): Pass empty COVERAGE_FLAGS.
+ * configure.in (coverage_flags): Default to nothing.
+ * configure: Rebuilt.
- * i386.c (ix86_decompose_address): Return -1 if address contains
- shift.
- (legitimate_address_p): Require ix86_decompose_address to return 1.
+2002-08-09 Neil Booth <neil@daikokuya.co.uk>
+
+ * Makefile.in (c-opts.o): Update
+ * c-opts.c: Include intl.h.
+ (print_help): Move from cppinit.c. Remove unused options.
+ (COMMAND_LINE_OPTIONS): Move more from cppinit.c.
+ (missing_arg): Complain for switches without an argument.
+ (c_common_decode_option): Reject missing joined arguments.
+ Handle new switches from cppinit.c.
+ * cppinit.c (COMMAND_LINE_OPTIONS): Move some switches to c-opts.c.
+ (cpp_handle_option): Similarly.
+ (print_help): Moved to c-opts.c.
+ * cpplib.h (struct cpp_options): Remove help_only.
+ * gcc.c (cpp_unique_options): Remove -$.
+ * doc/cppopts.texi: Undocument -h.
- * gcse.c (hash_scan_set): Use CONSTANT_INSN_P.
- (cprop_insn): Likewise.
+2002-08-08 Jakub Jelinek <jakub@redhat.com>
-2002-01-10 Kazu Hirata <kazu@hxi.com>
+ * config/i386/i386.c (legitimate_constant_p): UNSPEC_TP is not
+ legitimate constant.
+ (legitimate_pic_operand_p): Neither pic operand.
+ (legitimate_address_p): But legitimate address.
+ (get_thread_pointer): Generate MEM/u instead of CONST around
+ UNSPEC_TP.
+ (print_operand): Remove printing of UNSPEC_TP.
+ (print_operand_address): And print it here.
- * toplev.c: Fix formatting.
- * tree.c: Likewise.
- * tree-dump.c: Likewise.
- * unroll.c: Likewise.
- * unwind-dw2.c: Likewise.
- * unwind-dw2-fde.c: Likewise.
- * unwind-dw2-fde-glibc.c: Likewise.
- * unwind-sjlj.c: Likewise.
+2002-08-08 Devang Patel <dpatel@apple.com>
-2002-01-10 Joseph S. Myers <jsm28@cam.ac.uk>
-
- * doc/invoke.texi: Document PDP-11 options.
-
-2002-01-10 Kazu Hirata <kazu@hxi.com>
-
- * config/h8300/h8300.h: Fix formatting.
-
-2002-01-10 Ira Ruben <ira@apple.com>
-
- Add __attribute__ ((deprecated)).
- * extend.texi: Document __attribute__ ((deprecated)).
- * invoke.texi: Document -Wno-deprecated-declarations.
- * testsuite/g++.dg/other/deprecated.C: New C++ test.
- * testsuite/gcc.dg/deprecated.c: New C test.
- * attribs.c (enum attrs): Declare handle_deprecated_attribute().
- (c_common_attribute_table): Add "deprecated" entry.
- (handle_deprecated_attribute): New function.
- * c-decl.c (deprecated_states): New enum.
- deprecated_state: State of "deprecated" handling.
- (start_decl): Set deprecated_state based on attributes.
- (grokdeclarator): Test for deprecated uses, propagate attribute.
- * c-typeck.c (build_component_ref): Test for deprecated fields.
- (build_external_ref): Test for deprecated primaries.
- * diagnostic.c (warn_deprecated_use) New function to issue
- warnings about __attribute__ ((depricated)) references.
- * flags.h (warn_deprecated_decl): Extern declared for
- -W[no-]deprecated-declarations option.
- * print-tree.c (print_node): Show deprecated flag status.
- * toplev.c (warn_deprecated_decl): Defined.
- (W_options): Added "deprecated-declaration".
- * toplev.h (warn_deprecated_use): Extern declared.
- * tree.h (struct tree_common): Define deprecated_flag.
- (TREE_DEPRECATED): New macro to access flag.
- * cp/call.c (build_call): Test for deprecated calls.
- * cp/class.c (add_implicitly_declared_members): Set global
- flag to tell grokdeclarator to not issue deprecated warnings.
- * cp/cp-tree.h: Add extern for adding_implicit_members.
- * cp/decl.c (deprecated_states): New enum.
- (start_decl): Set deprecated_state based on attributes.
- (grokdeclarator): Test for deprecated uses, propagate attribute.
- * cp/lex.c (do_identifier): Test for deprecated primaries.
- * cp/typeck.c (build_component_ref): Test for deprecated fields.
-
-2002-01-10 Ira Ruben <ira@apple.com>
-
- Fix to assign attributes to inline member functions.
- * cp/decl.c (start_method): Handle attrlist.
-
-2002-01-10 Kazu Hirata <kazu@hxi.com>
-
- * combine.c (expand_field_assignment): Use subreg_lsb().
-
-2002-01-10 David Edelsohn <edelsohn@gnu.org>
-
- * alias.c (find_base_value): Add cases for HIGH, PRE_INC, PRE_DEC,
- POST_INC, POST_DEC, PRE_MODIFY, and POST_MODIFY.
- (find_base_term): Add cases for TRUNCATE, PRE_MODIFY, and POST_MODIFY.
- Recurse for any operand of AND as long as constant is non-zero.
-
-2002-01-10 Kazu Hirata <kazu@hxi.com>
-
- * config/h8300/h8300.md: Remove constraints from expanders.
-
-2002-01-10 Kazu Hirata <kazu@hxi.com>
-
- * varasm.c: Fix formatting.
- * varray.c: Likewise.
- * vmsdbgout.c: Likewise.
- * xcoffout.c: Likewise.
+ * objc/objc-act.c (build_selector_translation_table): Issue warning,
+ when -Wselector is used,if method for which selector is being
+ created does not exist.
-Thu Jan 10 17:19:12 CET 2002 Jan Hubicka <jh@suse.cz>
+2002-08-08 Stephen Clarke <stephen.clarke@superh.com>
- * cfgcleanup.c (try_forward_edges): Properly initialize nthreaded_edges;
- update edge probabilities to match.
+ * config/sh/sh.c (prepare_move_operands): Only call
+ target_reg_operand if TARGET_SHMEDIA.
-2002-01-10 Joseph S. Myers <jsm28@cam.ac.uk>
+2002-08-08 Jakub Jelinek <jakub@redhat.com>
- * Makefile.in ($(docdir)/gccint.info, gccint.dvi): Add additional
- dependencies.
- * doc/languages.texi, doc/sourcebuild.texi: New files.
- * doc/configfiles.texi: Make a subsubsection. Update.
- * doc/configterms.texi: Add @node. Remove warning that this isn't
- instructions for building GCC.
- * doc/makefile.texi: Make a subsection.
- * doc/gccint.texi: Update.
+ * config/rs6000/rs6000.h, config/rs6000/aix.h,
+ config/rs6000/darwin.h, config/rs6000/linux64.h: Revert last
+ two patches.
+ * config/rs6000/sysv4.h: Likewise, remove #undef ADJUST_FIELD_ALIGN.
-Thu Jan 10 16:39:58 CET 2002 Jan Hubicka <jh@suse.cz>
+2002-08-08 Lars Brinkhoff <lars@nocrew.org>
+ Richard Henderson <rth@redhat.com>
- * i386.md (sse_mov?fcc_const0_?): Fix constraints.
+ * emit-rtl.c (gen_rtx_REG): After reload, only return
+ frame_pointer_rtx or hard_frame_pointer_rtx if frame_pointer_needed.
-Thu Jan 10 12:45:50 2002 Nicola Pero <n.pero@mi.flashnet.it>
+2002-08-08 Jakub Jelinek <jakub@redhat.com>
- * doc/cpp.texi: Document the __OBJC__ preprocessor macro.
+ * config/rs6000/rs6000-protos.h (rs6000_field_alignment): Remove.
+ * config/rs6000/rs6000.c (rs6000_field_alignment): Move...
+ * config/rs6000/rs6000.h (ADJUST_FIELD_ALIGN): ...inline into the
+ macro.
-Thu Jan 10 11:19:18 CET 2002 Jan Hubicka <jh@suse.cz>
+2002-08-08 Adam Nemet <anemet@lnxw.com>
- * optabs.c (expand_fix): Look for wider integer modes first.
+ * config/arm/arm.c (thumb_unexpanded_epilogue): Stack the PIC
+ register.
+ (thumb_expand_prologue): Likewise.
+ (thumb_output_function_prologue): Likewise.
+ * config/arm/arm.h (THUMB_INITIAL_ELIMINATION_OFFSET): Account for
+ the additional push of the PIC register.
- * i386.md (mov?f): Avoid the fake const double trick for medium
- memory model.
- (min?f*/max?f*): Prohibit memory operands for i387 variant.
- (fop_df_4): Disable for SSE compilation.
+2002-08-08 Nathan Sidwell <nathan@codesourcery.com>
-2002-01-10 Graham Stott <grahams@redhat.com>
+ * configure.in (enable_coverage): New enable switch.
+ * configure: Rebuilt.
+ * Makefile.in (COVERAGE_FLAGS, coverageexts): New variables.
+ (INTERNAL_CFLAGS): Append COVERAGE_FLAGS.
+ (ALL_FLAGS): Reorder so INTERNAL_CFLAGS comes after CFLAGS.
+ (mostlyclean): Remove coverage files.
+ * doc/install.texi: Document enable_coverage.
- * dwarf2out.c (indirect_string_alloc, output_indirect_string):
- Move prototype into DWARF2_DEBUGGING_INFO conditional block.
+ * cp/Make-lang.in (c++.mostlyclean): Remove coverage files.
+ * ada/Make-lang.in (ada.mostlyclean): Remove coverage files.
+ * f/Make-lang.in (f.mostlyclean): Remove coverage files.
+ * java/Make-lang.in (java.mostlyclean): Remove coverage files.
+ * objc/Make-lang.in (objc.mostlyclean): Remove coverage files.
+ * treelang/Make-lang.in (treelang.mostlyclean): Remove coverage
+ files.
-2002-01-10 Richard Henderson <rth@redhat.com>
+2002-08-08 Neil Booth <neil@daikokuya.co.uk>
- * config/alpha/alpha.md (extendsidi2_fix): Penalize f/f alternative.
+ * c-opts.c (cpp_opts): New.
+ (COMMAND_LINE_OPTIONS): Add switches from cppinit.c.
+ (c_common_decode_options): Handle cpplib switches.
+ (c_common_init_options): Set cpp_opts.
+ * cppinit.c (COMMAND_LINE_OPTIONS): Move some switches to c-opts.c.
+ (cpp_handle_option): Similarly.
-2002-01-10 Richard Henderson <rth@redhat.com>
+2002-08-08 David Edelsohn <edelsohn@gnu.org>
- * regrename.c (find_oldest_value_reg): Fix typo in mode change check.
- (copyprop_hardreg_forward_1): Likewise. Use mode_change_ok.
+ * config/rs6000/aix.h (TARGET_ALTIVEC): Define to 0.
+ (TARGET_ALTIVEC_ABI): Same.
+ (TARGET_ALTIVEC_VRSAVE): Same.
-2002-01-10 Kazu Hirata <kazu@hxi.com>
+ * config/rs6000/rs6000.c (rs6000_expand_ternop_builtin): Check
+ icode not CODE_FOR_nothing. Change switch to if.
- * combine.c (can_combine_p): Fix a comment typo.
+2002-08-08 Alan Modra <amodra@bigpond.net.au>
-2002-01-09 Zack Weinberg <zack@codesourcery.com>
+ * config/rs6000/rs6000.h (ASM_CPU_SPEC): Pass -mpower4 when cpu=power4.
- * Makefile.in (s-gencheck, s-options, s-specs): Handle an
- empty list correctly. Change loop index $t to $f for
- consistency with rest of Makefile.
+2002-08-08 Jakub Jelinek <jakub@redhat.com>
-2002-01-08 Aldy Hernandez <aldyh@redhat.com>
+ * stor-layout.c (place_union_field): For bitfields if
+ PCC_BITFIELD_TYPE_MATTERS and TYPE_USER_ALIGN, set record's
+ TYPE_USER_ALIGN.
- * testuite/gcc.dg/altivec-4.c: Add test for mtvscr, dssall,
- mfvscr, dss, lvsl, lvsr, dstt, dstst, dststt, dst.
+2002-08-07 John David Anglin <dave@hiauly1.hia.nrc.ca>
- * config/rs6000/rs6000.c (altivec_expand_builtin): Add support for
- mtvscr, dssall, mfvscr, dss, lvsl, lvsr, dstt, dst, dstst, dststt.
- (altivec_init_builtins): Same.
- (altivec_expand_unop_builtin): Return NULL_RTX on error.
- (altivec_expand_binop_builtin): Same.
- (altivec_expand_ternop_builtin): Same.
- (bdesc_dst): New.
+ * pa.c (struct deferred_plabel): Constify name field.
- * config/rs6000/rs6000.md ("altivec_mtvscr"): New.
- ("altivec_vctuxs"): Fix typo.
- ("altivec_vnmsubfp"): Same.
- ("altivec_dssall"): New.
- ("altivec_mfvscr"): New.
- ("altivec_dss"): New.
- ("altivec_lvsl"): New.
- ("altivec_lvsr"): New.
- ("altivec_dstt"): New.
- ("altivec_dstst"): New.
- ("altivec_dststt"): New.
- ("altivec_dst"): New.
+2002-08-07 Neil Booth <neil@daikokuya.co.uk>
- * config/rs6000/rs6000.h (rs6000_builtins): Add mtvscr, dssall,
- mfvscr, dss, lvsl, lvsr, dstt, dstst, dststt, dst.
+ * cppmacro.c (_cpp_builtin_macro_text): Remove unused variable.
-2002-01-09 Richard Henderson <rth@redhat.com>
+2002-08-07 John David Anglin <dave@hiauly1.hia.nrc.ca>
- * config/alpha/alpha.md (prologue_mcount): Remove lituse_jsr reloc.
+ * configure.in (PREFIX_INCLUDE_DIR): Don't define if prefix and
+ local_prefix are the same.
+ * configure: Rebuilt.
-2002-01-10 Hans-Peter Nilsson <hp@bitrange.com>
+2002-08-07 Jakub Jelinek <jakub@redhat.com>
+ Richard Henderson <rth@redhat.com>
- * config/mmix/mmix.c (mmix_asm_identify_gcc): Remove unused
- function.
- * config/mmix/mmix-protos.h (mmix_asm_identify_gcc): Don't
+ * stor-layout.c (place_union_field): Apply ADJUST_FIELD_ALIGN
+ to type_align when PCC_BITFIELD_TYPE_MATTERS. Only apply
+ ADJUST_FIELD_ALIGN if not DECL_USER_ALIGN resp. TYPE_USER_ALIGN.
+ (place_field): Likewise.
+ * config/i386/i386.c (x86_field_alignment): Don't check
+ DECL_USER_ALIGN here.
+ * config/rs6000/rs6000.c (rs6000_field_alignment): New.
+ * config/rs6000/rs6000-protos.h (rs6000_field_alignment): New
prototype.
- * config/mmix/mmix.h (ASM_IDENTIFY_GCC): Remove unused macro.
+ * config/rs6000/rs6000.h (ADJUST_FIELD_ALIGN): Define.
+ * config/rs6000/aix.h (ADJUST_FIELD_ALIGN): Remove.
+ * config/rs6000/darwin.h (ADJUST_FIELD_ALIGN): Remove.
+ * config/rs6000/linux64.h (ADJUST_FIELD_ALIGN): Remove.
+ * config/rs6000/sysv4.h (ADJUST_FIELD_ALIGN): Remove.
+ * doc/tm.texi (ADJUST_FIELD_ALIGN): Update description.
-2002-01-09 Kazu Hirata <kazu@hxi.com>
+2002-08-07 Neil Booth <neil@daikokuya.co.uk>
- * read-rtl.c: Fix formatting.
- * real.c: Likewise.
- * regclass.c: Likewise.
- * regrename.c: Likewise.
- * reg-stack.c: Likewise.
+ * Makefile.in (c-opts.o, c-common.o, C_AND_OBJC_OBJS): Update.
+ * c-common.c: Don't include tree-inline.h.
+ (c_common_init_options, c_common_post_options): Move to c-opts.c.
+ * c-common.h (c_common_decode_option): New.
+ * c-decl.c (c_decode_option): Remove.
+ * c-lang.c (LANG_HOOKS_DECODE_OPTION): Use c_common_decode_option.
+ * c-opts.c: New file.
+ * c-tree.h (c_decode_option): Remove.
+ * doc/passes.texi: Update.
+ * objc/objc-act.c (objc_decode_option): Remove.
+ * objc/objc-act.h (objc_decode_option): Remove.
+ * objc/ojbc-lang.c (LANG_HOOKS_DECODE_OPTION): Use
+ c_common_decode_option.
+
+2002-08-07 Chris Demetriou <cgd@broadcom.com>
+
+ * config/mips/mips.md (sunlt_sf, suneq_sf, sunle_sf): Remove
+ dependency on TARGET_DOUBLE_FLOAT.
+
+2002-08-07 Stephen Clarke <stephen.clarke@superh.com>
+
+ * config/sh/lib1funcs.asm (GCC_shcompact_incoming_args): Don't
+ overwrite callee-save registers. Fix comment.
+
+2002-08-06 Chris Demetriou <cgd@broadcom.com>
+
+ * config/mips/mips.c (override_options): Set MASK_BRANCHLIKELY
+ in target_flags based on ISA, if it was not set on the command
+ line. Warn if MASK_BRANCHLIKLEY is set but the ISA does not
+ support Branch Likely instructions.
+ * config/mips/mips.h (MASK_BRANCHLIKLEY): New macro.
+ (TARGET_BRANCHLIKELY): Likewise.
+ (TARGET_SWITCHES): Add -mbranch-likely and -mno-branch-likely.
+ (GENERATE_BRANCHLIKELY): Use TARGET_BRANCHLIKELY rather than
+ ISA_HAS_BRANCHLIKELY.
+ (ISA_HAS_BRANCHLIKELY): Do not include MIPS16 check.
+ * doc/invoke.texi: Document new MIPS -mbranch-likely and
+ -mno-branch-likely options.
+
+2002-08-06 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * ip2k.c (ip2k_set_compare): Add missing iteration variable.
+
+ * Makefile.in (dummy-conditions.o): Depend on $(HCONFIG_H) not
+ $(GCONFIG_H).
+
+2002-08-06 Aldy Hernandez <aldyh@redhat.com>
+
+ * c-decl.c (duplicate_decls): Error out for incompatible TLS
+ declarations.
+
+ * testsuite/gcc.dg/tls/diag-3.c: New.
+
+2002-08-06 Dale Johannesen <dalej@apple.com>
+
+ * c-common.c (fname_decl): Use line number 0 for
+ __func__, to avoid confusing debuggers.
+
+2002-08-06 Nathan Sidwell <nathan@codesourcery.com>
+
+ * gcov.c: Tidy.
+ (struct line_info, struct coverage): New structures.
+ (gcov_file_name, gcov_file): Remove globals.
+ (output_data): Take source file parameter. Fix memory leak. Break
+ up into ...
+ (init_line_info, output_line_info, make_gcov_file_name,
+ accumulate_branch_counts): ... here.
+ (calculate_branch_probs, function_summary): Adjust.
+ (main): Adjust.
+ (function_*): Remove global variables.
+
+2002-08-06 Neil Booth <neil@daikokuya.co.uk>
+
+ * dwarf2out.c: Remove unused macros.
+
+2002-08-06 Neil Booth <neil@daikokuya.co.uk>
+
+ * function.c (TRAMPOLINE_ALIGNMENT): Always defined.
+
+2002-08-06 Neil Booth <neil@daikokuya.co.uk>
+
+ * cppinit.c (struct lang_flags): Rename trigraphs std.
+ (set_lang): Update.
+ * cpplib.h (struct cpp_options): New member std.
+ * cppmacro.c (_cpp_builtin_macro_text): Use std.
+ (collect_args): Flag whether to swallow a possible future
+ comma pasted with varargs.
+ (replace_args): Use this flag.
+ * doc/cpp.texi: Update varargs extension documentation.
+
+2002-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/mmintrin.h (__m64): Make the type 64-bit aligned.
+
+2002-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (x86_field_alignment): Apply min for all MODE_INT
+ and MODE_CLASS_INT modes.
+
+2002-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ * config.gcc (*-*-linux*): Default to --enable-threads=posix if no
+ --{enable,disable}-threads is given to configure.
+ (alpha*-*-linux*, hppa*-*-linux*, i[34567]86-*-linux*,
+ x86_64-*-linux*, ia64*-*-linux*, m68k-*-linux*, mips*-*-linux*,
+ powerpc-*-linux-gnualtivec*, powerpc-*-linux*, s390-*-linux*,
+ s390x-*-linux*, sh-*-linux*, sparc-*-linux*, sparc64-*-linux*):
+ Remove thread_file setting here.
+
+2002-08-06 David Edelsohn <edelsohn@gnu.org>
+
+ * doc/install.texi (Binaries): Update Bull Freeware URL.
+
+2002-08-06 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/gcc.texi (Top): Rename Index to Keyword Index.
+
+2002-08-05 Nathan Sidwell <nathan@codesourcery.com>
+
+ * gcov.c (output_data): Round to % to nearest, tweak formatting.
+
+2002-08-05 Jakub Jelinek <jakub@redhat.com>
+
+ * fold-const.c (associate_trees): Only optimize NEGATE_EXPR in one
+ of the operands into MINUS_EXPR if code is PLUS_EXPR.
+
+2002-08-05 Douglas B Rupp <rupp@gnat.com>
+
+ * config.gcc (i[34567]86-*-interix*): Replace interix.o with winnt.o
+ * config/i386/i386-interix.h (TARGET_NOP_FUN_DLLIMPORT,
+ drectve_section): Define.
+ * config/i386/t-interix: Replace interix.o rule with winnt.o.
+ * config/i386/interix.c: Remove.
+
+2002-08-05 Geoffrey Keating <geoffk@redhat.com>
+
+ * attribs.c: Don't include obstack.h.
+ * builtins.c: Likewise.
+ * cfganal.c: Likewise.
+ * cfgbuild.c: Likewise.
+ * cfgcleanup.c: Likewise.
+ * emit-rtl.c: Likewise.
+ * loop.c: Likewise.
+ * stmt.c: Likewise.
+
+ * Makefile.in (s-gtype): Re-add dependency on $(GTFILES).
+
+2002-08-05 Gabriel Dos Reis <gdr@nerim.net>
+
+ * doc/c-tree.texi (Expression trees): Document VA_ARG_EXPR
+
+2002-08-04 Chris Demetriou <cgd@broadcom.com>
+
+ * doc/invoke.texi: Remove duplicated paragraph describing
+ TARGET_SWITCHES.
+
+2002-08-04 Geoffrey Keating <geoffk@redhat.com>
+
+ * Makefile.in (sdbout.o): Doesn't need $(OBSTACK_H).
+ * collect2.h (permanent_obstack): Delete declaration.
+ * collect2.c (permanent_obstack): Delete definition.
+ (main): Don't initialize permanent_obstack. Use xstrdup instead.
+ * expr.c: Don't include obstack.h.
+ (permanent_obstack): Delete declaration.
+ * function.c: Don't include obstack.h.
+ (permanent_obstack): Delete declaration.
+ * integrate.c: Don't include obstack.h.
+ (function_maybepermanent_obstack): Delete declaration.
+ * print-tree.c (debug_tree): Use x*alloc not permalloc.
+ * sdbout.c (gen_fake_label): Use x*alloc not permalloc.
+ * tlink.c (pfgets): Use xstrdup not permanent_obstack.
+ * toplev.c (lang_independent_init): Rename init_obstacks to init_ttree.
+ * tree.h: Rename init_obstacks to init_ttree. Remove declarations
+ of permalloc, expralloc, perm_calloc.
+ * tree.c (permanent_obstack): Delete definition.
+ (init_ttree): Rename from init_obstacks.
+ (permalloc): Delete.
+ (perm_calloc): Delete.
+ (dump_tree_statistics): Don't print information about
+ permanent_obstack.
+ * varasm.c (assemble_start_function): Use xstrdup instead of
+ permalloc/strcpy.
+ (assemble_variable): Likewise.
+ * config/alpha/alpha.c (unicosmk_need_dex): Use xmalloc instead of
+ permalloc.
+ (unicosmk_add_extern): Likewise.
+ * config/c4x/c4x.c (c4x_external_ref): Likewise.
+ (c4x_global_label): Likewise.
+ * config/frv/frv.c (frv_encode_section_info): Likewise.
+ * config/i386/winnt.c (i386_pe_record_external_function): Likewise.
+ (i386_pe_record_exported_symbol): Likewise.
+ * config/mips/mips.c (mips_output_external): Likewise.
+ (mips_output_external_libcall): Likewise.
+ * config/pa/pa.c: (permanent_obstack): Delete declaration.
+ (output_call): Use ggc_strdup instead of allocating on
+ permanent_obstack.
+ * config/romp/romp.c: Include ggc.h.
+ (get_symref): Don't declare permanent_obstack, use ggc_strdup
+ intead of permanent_obstack.
+ * config/rs6000/aix31.h (ASM_OUTPUT_EXTERNAL): Use concat
+ instead of permalloc.
+ * config/rs6000/rs6000.c (rs6000_gen_section_name): Use xmalloc
+ instead of permalloc
+ * config/rs6000/xcoff.h (ASM_OUTPUT_EXTERNAL): Use concat
+ instead of permalloc.
+ * config/vax/vax.c (vms_check_external): Use xmalloc instead of
+ permalloc.
+
+2002-08-04 Bernd Schmidt <bernds@redhat.com>
+
+ Contribute a port developed primarily by Michael Meissner,
+ Catherine Moore, and Richard Sandiford <rsandifo@redhat.com>.
+ * config.gcc: Add frv-elf target.
+ * config/frv/cmovd.c: New file.
+ * config/frv/cmovh.c: New file.
+ * config/frv/cmovw.c: New file.
+ * config/frv/frv-abi.h: New file.
+ * config/frv/frv-asm.h: New file.
+ * config/frv/frv-modes.def: New file.
+ * config/frv/frv-protos.h: New file.
+ * config/frv/frv.c: New file.
+ * config/frv/frv.h: New file.
+ * config/frv/frv.md: New file.
+ * config/frv/frvbegin.c: New file.
+ * config/frv/frvend.c: New file.
+ * config/frv/lib1funcs.asm: New file.
+ * config/frv/media.h: New file.
+ * config/frv/modi.c: New file.
+ * config/frv/t-frv: New file.
+ * config/frv/uitod.c: New file.
+ * config/frv/uitof.c: New file.
+ * config/frv/ulltod.c: New file.
+ * config/frv/ulltof.c: New file.
+ * config/frv/umodi.c: New file.
+ * config/frv/xm-frv.h: New file.
+
+ * config/frv/media.h: Removed again.
+
+2002-08-04 Nathan Sidwell <nathan@codesourcery.com>
+
+ * gcov.c (bb_file_time): New static variable.
+ (object_directory): May also be object file.
+ (preserve_paths): New static variable.
+ (print_usage): Adjust.
+ (options): Adjust.
+ (process_args): Adjust.
+ (open_files): Simplify. Cope when OBJECT_DIRECTORY is an object
+ file. Find modification date on bb file.
+ (read_profile): Don't rewind a NULL file.
+ (format_hwint): New static function.
+ (function_summary): Use format_hwint.
+ (output_data): SOURCE_FILE_NAME is never relative to
+ OBJECT_DIRECTORY. Use format_hwint. Adjust gcov file name
+ mangling. Adjust output format to make it more machine readable.
+ * doc/gcov.texi: Document & clarify semantics.
+
+2002-08-04 Joseph S. Myers <jsm@polyomino.org.uk>
+
+ * doc/include/gcc-common.texi (version-GCC): Increase to 3.3.
+
+2002-08-04 Nathan Sidwell <nathan@codesourcery.com>
+
+ * gcc.c (cc1_options): Pass output file as auxbase when
+ appropriate.
+ * profile.c (init_branch_prob): FILENAME has already had ending
+ stripped.
+ * final.c (end_final): Likewise.
+ * toplev.c (aux_base_name): New global.
+ (compile_file): Pass aux_base_name to init init_branch_prob and
+ end_final.
+ (independent_decode_option, case 'a'): New auxinfo options.
+ (case 'd'): Protect against mising basename.
+ (do_compile): Initialize aux_base_name.
+ * toplev.h (aux_base_name): New global.
+ * doc/invoke.texi: Adjust documentation.
+
+2002-08-04 Nathan Sidwell <nathan@codesourcery.com>
+
+ * config/i386/i386.c (x86_field_alignment): Remove duplicate test
+ of TARGET_ALIGN_DOUBLE.
+
+2002-08-04 Gabriel Dos Reis <gdr@nerim.net>
+
+ * diagnostic.c (inform): New function.
+ * diagnostic.h (inform): Declare.
+
+2002-08-03 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.md (movsi_internal1): Add nop mnemonic.
+ (movhi_internal): Same.
+ (movqi_internal): Same.
+ (movdi_internal64): Same.
+
+ * config/rs6000/t-ppccomm (MULTILIB_MATCHES_FLOAT): Add mcpu=405.
+
+ * config/rs6000/xcoff.h (SKIP_ASM_OP): Define.
+ (ASM_OUTPUT_SKIP): Use it. SIZE unsigned.
+ (COMMON_ASM_OP): Define.
+ (ASM_OUTPUT_ALIGNED_COMMON): Use it. SIZE unsigned.
+ Use ALIGN parameter.
+ (LOCAL_COMMON_ASM_OP): Define.
+ (ASM_OUTPUT_LOCAL): Use it. SIZE unsigned.
+
+2002-08-03 Roger Sayle <roger@eyesopen.com>
+
+ * builtins.def: Define new builtin functions exp, expf, expl,
+ log, logf and logl (and their __builtin_* variants).
+ * optabs.h (enum optab_index): Add new OTI_exp and OTI_log.
+ Define exp_optab and log_optab.
+ * optabs.c (init_optans): Initialize exp_optab and log_optab.
+ * genopinit.c (optabs): Implement exp_optab and log_optab
+ using exp?f2 and log?f2 patterns.
+ * builtins.c (expand_builtin_mathfn): Handle BUILT_IN_EXP*
+ and BUILT_IN_LOG* using exp_optab and log_optab respectively.
+ (expand_builtin): Ignore the new builtins (and all cos and
+ sin variants) when not optimizing. Expand new builtins via
+ expand_builtin_mathfn when flag_unsafe_math_optimizations.
+
+ * doc/extend.texi: Document new exp and log builtins.
+ * doc/md.texi: Document new exp?f2 and log?f2 patterns
+ (and previously undocumented cos?f2 and sin?f2 patterns).
+
+2002-08-03 Jason Merrill <jason@redhat.com>
+
+ * explow.c (int_expr_size): New fn.
+ * expr.c (expand_expr) [CONSTRUCTOR]: Use it.
+ * expr.h: Declare it.
+
+2002-08-02 Krister Walfridsson <cato@df.lth.se>
+
+ * Makefile.in (gengtype-lex.o, gengtype-yacc.o): Add path to
+ gengtype-* dependencies.
+
+2002-08-02 Eric Christopher <echristo@redhat.com>
+
+ * config.gcc (mips*-*-linux*): Fix ordering of tm_file.
+ * config/mips/mips.h (READONLY_DATA_SECTION_ASM_OP): Change
+ #ifndef to #undef.
+ (TARGET_MEM_FUNCTIONS): Define instead of define to 1.
+
+2002-08-02 David Edelsohn <edelsohn@gnu.org>
+
+ PR optimize/7067
+ * config/rs6000/rs6000.h (RTX_COSTS): Artificially make MULT
+ small if optimizing for size.
+
+2002-08-02 Daniel Jacobowitz <drow@mvista.com>
+
+ * configure.in (FORBUILD): Use $build_alias.
+ * configure: Regenerated.
+
+2002-08-02 Richard Sandiford <rsandifo@redhat.com>
+
+ * config.gcc: Don't include mips/abi64.h in $tm_file.
+ * hard-reg-set.h (call_really_used_regs): Declare.
+ * config/mips/abi64.h: Remove file.
+ * config/mips/linux.h,
+ * config/mips/iris6.h: Don't include it.
+ * config/mips/mips-protos.h (mips_conditional_register_usage): Declare.
+ * config/mips/mips.h (CONDITIONAL_REGISTER_USAGE): Use it.
+ (REG_PARM_STACK_SPACE, STACK_BOUNDARY, STRICT_ARGUMENT_NAMING,
+ FUNCTION_ARG_PASS_BY_REFERENCE, FUNCTION_ARG_PADDING,
+ FUNCTION_ARG_CALLEE_COPIES, MUST_PASS_IN_STACK, MIPS_STACK_ALIGN):
+ Bring across definitions from abi64.h.
+ (GP_ARG_LAST, FP_ARG_LAST): Use MAX_ARGS_IN_REGISTERS.
+ (BIGGEST_MAX_ARGS_IN_REGISTERS): New.
+ (struct mips_args): Use it.
+ * config/mips/mips.c (mips_conditional_register_usage): Define.
+
+2002-08-02 Jason Merrill <jason@redhat.com>
+
+ * langhooks-def.h (LANG_HOOKS_EXPR_SIZE): New macro.
+ * langhooks.c (lhd_expr_size): Define default.
+ * langhooks.h (struct lang_hooks): Add expr_size.
+ * explow.c (expr_size): Call it.
+ * expr.c (store_expr): Don't copy an expression of size zero.
+ (expand_expr) [CONSTRUCTOR]: Use expr_size to calculate how much
+ to store.
+ * Makefile.in (builtins.o): Depend on langhooks.h.
+
+2002-08-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Makefile.in (ra-debug.o): Depend on $(TM_P_H).
+ * ra-debug.c: Include "tm_p.h".
+ * ra-rewrite.c (is_partly_live_1): Change return type to bool.
+
+2002-08-02 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ * simplify-rtx.c (simplify_binary_operation): x * 1 is allowed
+ when not honoring signalling NaNs.
+ (simplify_ternary_operation): a == b has a definite value
+ when not honoring NaNs.
+
+2002-08-02 Jason Merrill <jason@redhat.com>
+
+ * gdbinit.in (pct): New macro.
+
+2002-08-01 Stan Shebs <shebs@apple.com>
+ Andreas Tobler <toa@pop.agri.ch>
+
+ * ginclude/stddef.h (_BSD_SIZE_T_DEFINED_): Define if not defined,
+ plays nice with Darwin headers.
+ (_BSD_RUNE_T_DEFINED_): Likewise.
+
+2002-08-01 Zack Weinberg <zack@codesourcery.com>
+
+ * c-common.c (c_common_init): -Wtraditional also implies -Wlong-long.
+ * cppinit.c (cpp_post_options): Likewise.
+
+ * cppexp.c (cpp_classify_number): Suppress -Wtraditional
+ warning about 'LL' suffix (but not 'ULL' etc) when
+ -Wno-long-long is in effect.
+
+ * cppmacro.c (_cpp_builtin_macro_text) [BT_TIME, BT_DATE]:
+ Check for failing time()/localtime(), issue a warning, and
+ make __TIME__ and __DATE__ expand to fallback strings.
+
+ * doc/cpp.texi, doc/extend.texi: Document behavior of __DATE__
+ and __TIME__ when the date and time cannot be determined.
+
+2002-08-02 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.c (output_cbranch): Hint differently for power4.
+
+2002-08-01 Daniel Jacobowitz <drow@mvista.com>
+
+ * Makefile.in ($(BUILD_PREFIX_1)ggc-none.o): Use $(GGC_H).
+
+2002-08-01 Chris Demetriou <cgd@broadcom.com>
+
+ * config.gcc (mipsisa64sb1-*-elf*): New configuration.
+ (mipsisa64sb1el-*-elf*): Likewise.
+ * config/mips/mips.c (mips_cpu_info_table): Add sb1.
+ * config/mips/mips.h (processor_type): Add PROCESSOR_SB1.
+ (TARGET_SB1, TUNE_SB1): New macros.
+ * doc/invoke.texi: Add sb1 to documentation for MIPS -march and
+ -mtune flags.
+
+2002-08-01 David Edelsohn <edelsohn@gnu.org>
+
+ * varasm.c (asm_emit_uninitialized): Return false if global BSS
+ and ASM_EMIT_BSS not supported by target.
+ (assemble_variable): Do not duplicate uninitialized logic.
+ Fall through if asm_emit_uninitialized failed.
+
+2002-08-01 Chris Demetriou <cgd@broadcom.com>
+
+ * config/mips/mips.h (BRANCH_LIKELY_P): Remove unused macro.
+
+2002-08-02 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/linux64.h (DBX_OUTPUT_BRAC): Define.
+ (DBX_OUTPUT_LBRAC, DBX_OUTPUT_RBRAC): Define.
+
+ * config/rs6000/rs6000.c (output_toc): Don't use lshift_double when
+ HOST_BITS_PER_WIDE_INT == 64.
+
+2002-08-01 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * df.c (df_insn_table_realloc): Change parameter to unsigned.
+ * optabs.c (expand_binop): Make variable unsigned.
+ * simplify-rtx.c (simplify_subreg): Likewise.
+ * unroll.c (unroll_loop): Cast to avoid signed/unsigned warnings.
+
+2002-08-01 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ * c-common.c (cb_register_builtins): Always define __GXX_ABI_VERSION.
+
+2002-08-01 Richard Henderson <rth@redhat.com>
+
+ * toplev.c (parse_options_and_default_flags): Don't set
+ flag_reorder_blocks for -Os.
+
+ * config/avr/avr.c (avr_optimization_options): Remove.
+ * config/avr/avr.h (OPTIMIZATION_OPTIONS): Remove.
+ * config/m68hc11/m68hc11.c (m68hc11_optimization_options): Remove.
+ * config/m68hc11/m68hc11.h (OPTIMIZATION_OPTIONS): Remove.
+
+2002-08-01 H.J. Lu <hjl@gnu.org>
+ Richard Henderson <rth@redhat.com>
+
+ * output.h (DECL_READONLY_SECTION): Remove.
+ (decl_readonly_section): Declare.
+ * varasm.c (decl_readonly_section): New.
+ (default_section_type_flags, default_select_section): Use it.
+ * config/arm/pe.c (arm_pe_unique_section): Likewise.
+ * config/i386/interix.c (i386_pe_unique_section): Likewise.
+ * config/i386/winnt.c (i386_pe_unique_section): Likewise.
+ * config/mcore/mcore.c (mcore_unique_section): Likewise.
+ * config/mips/mips.c (mips_unique_section): Likewise.
+
+2002-08-01 Richard Henderson <rth@redhat.com>
+
+ * integrate.c (copy_rtx_and_substitute): Squash MEM_EXPR when it
+ refers to a subroutine parameter.
+
+2002-08-01 Jakub Jelinek <jakub@redhat.com>
+
+ * varasm.c (assemble_visibility): Strip name encoding.
+
+2002-08-01 Ian Dall <ian@sibyl.beware.dropbear.id.au>
+
+ * config/ns32k/ns32k.h (TARGET_IEEE_COMPARE): Correct earlier patch.
+ (RETURN_ADDR_RTX): Cannot determine return address for FRAME > 0
+ when there is no frame pointer.
+ (INITIAL_FRAME_POINTER_OFFSET): Count stack space for saved fp
+ registers properly.
+ * config/ns32k/__unorddf2.c: New file.
+ * config/ns32k/__unordsf2.c: New file.
+ * config/ns32k/t-ns32k: New file.
+ * config.gcc (ns32k-*-netbsd*): Use it.
+
+2002-08-01 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.h (SPU_CONST_OFFSET_OK): Change to 0xff.
+
+2002-08-01 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-common.c (__GXX_ABI_VERSION): Correct spelling.
+
+2002-08-01 Benjamin Kosnik <bkoz@redhat.com>
+
+ * c-common.c (cb_register_builtins): Set __GXX_ABI_VERSION__ to 102.
+
+2002-08-01 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips.md: Add [!]TARGET_MIPS16 to sgtu conditions.
+
+2002-08-01 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * gcse.c (expr_hash_table_size, n_exprs, set_hash_table_size,
+ n_sets): Removed.
+ (expr_hash_table, set_hash_table): Type changed to ...
+ (struct hash_table): New type.
+ (hash_scan_insn, hash_scan_set, hash_scan_clobber, hash_scan_call,
+ insert_expr_in_table, insert_set_in_table, compute_hash_table,
+ dump_hash_table, lookup_expr, lookup_set, compute_local_properties,
+ compute_ae_gen, compute_ae_kill): Modified to pass the table explicitly.
+ (alloc_set_hash_table, alloc_expr_hash_table): Merged to ...
+ (alloc_hash_table): New.
+ (free_set_hash_table, free_expr_hash_table): Merged to ...
+ (free_hash_table): New.
+ (compute_set_hash_table, compute_expr_hash_table): Merged to ...
+ (compute_hash_table_work): New.
+ (classic_gcse, one_classic_gcse_pass, compute_cprop_data,
+ find_avail_set, one_cprop_pass, find_bypass_set, compute_pre_data,
+ pre_edge_insert, pre_insert_copies, pre_delete, pre_gcse,
+ one_pre_gcse_pass, compute_transpout, compute_code_hoist_vbeinout,
+ hoist_code, one_code_hoisting_pass,
+ trim_ld_motion_mems): Altered due to changed type of hash tables.
+
+2002-08-01 Zack Weinberg <zack@codesourcery.com>
+
+ * final.c (output_alternate_entry_point):
+ If ASM_OUTPUT_TYPE_DIRECTIVE is defined, use it.
+
+2002-08-01 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * objc/objc-act.c (encode_complete_bitfield): Add prototype and
+ avoid ISO C style function definition.
+
+ * expr.c (expand_assignment): Delete unused variable.
+
+2002-08-01 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ * c-common.c (cb_register_builtins): Set
+ __FINITE_MATH_ONLY__ to 1 if -ffinite-math-only
+ is given, and to 0 otherwise.
+ * combine.c (simplify_if_then_else): HONOR_NANS
+ implies FLOAT_MODE_P.
+
+2002-08-01 Neil Booth <neil@daikokuya.co.uk>
+
+ * cppinit.c (COMMAND_LINE_OPTIONS): Remove OPT_dollar.
+ (cpp_handle_option): Don't handle it.
+ (print_help): Update.
+ * doc/cppopts.texi: Update.
+
+2002-08-01 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-common.c (cb_register_builtins): If C++, define
+ __EXCEPTIONS, __DEPRECATED and __GXX_ABI_VERSION as appropriate.
+ * gcc.c (cpp_unique_options): Remove __GXX_ABI_VERSION.
+cp:
+ * lang-specs.h: Simplify in accordance with new code in
+ c-common.c.
+
+2002-08-01 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-common.c: Define all C/ObjC/C++ warning and flag variables.
+ * c-common.h: Declare all C/ObjC/C++ warning and flag variables.
+ * c-decl.c: Move all warning and flag variables to c-common.c.
+ * c-format.c: Move all warning variables to c-common.c.
+ * c-tree.h: Move all warning and flag declarations to c-common.h.
+ * objc/objc-act.c: Move all warning variables to c-common.c.
+ (flag_warn_protocol): Rename warn_protocol.
+
+2002-07-31 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa-linux.h (GLOBAL_ASM_OP): Fix typo.
+
+2002-07-31 Graham Stott <graham.stott@btinternet.com>
+
+ * config/stormy16/stormy16.h (BSS_SECTION_ASM_OP): Add missing
+ .section prefix.
+
+2002-07-31 Stan Shebs <shebs@apple.com>
+
+ * config.gcc (i[34567]86-*-darwin*): New configuration.
+ * config/darwin.h (TARGET_ENCODE_SECTION_INFO): Undefine before
+ defining.
+ (TARGET_ENCODE_SECTION_INFO): Ditto.
+ (ASM_PREFERRED_EH_DATA_FORMAT): Ditto.
+ * config/darwin.c (machopic_indirect_data_reference): Remove
+ setting of RTX_UNCHANGING_P.
+ (machopic_legitimize_pic_address): Move RTX_UNCHANGING_P up so as
+ not to be applied to sums.
+ * config/i386/t-darwin: New file.
+ * config/i386/darwin.h: New file.
+ * config/i386/i386.h (TARGET_MACHO): Add default definition.
+ * config/i386/i386.md (tablejump): Add TARGET_MACHO case.
+ * config/i386/i386.c (output_set_got): For Mach-O, output Mach-O
+ label and not the GOT add.
+ (constant_address_p): For Mach-O, seeing a CONST is enough.
+ (legitimate_pic_address_disp_p): Add a Mach-O case.
+ (legitimate_address_p): Also test machopic_operand_p if Mach-O.
+ (legitimize_pic_address): Use generic Mach-O code to legitimize.
+ (output_pic_addr_const): Suppress @PLT if Mach-O, and parens
+ if outputting a difference.
+ (ix86_output_addr_diff_elt): Add Mach-O case.
+ (ix86_expand_move): Similarly.
+ (ix86_expand_call): Similarly.
+ (current_machopic_label_num): New global.
+ (machopic_output_stub): New function.
+ (ix86_value_regno): New function.
+ (ix86_function_value): Use it instead of VALUE_REGNO.
+ (ix86_libcall_value): Ditto.
+ * config/i386/unix.h (VALUE_REGNO): Remove.
+
+2002-07-31 Graham Stott <grahas@btinternet.com>
+
+ * config/rs6000/rs6000.c(rs6000_hash_constant): Fix
+ hash for LABEL_REF's.
+
+2002-07-31 Graham Stott <grahams@btinternet.com>
+
+ * config/rs6000/rs6000.c (spe_init_builtins,
+ altivec_init_builtins, rs6000_common_init_builtins):
+ Replace ANSI with K&R function def.
+
+2002-07-31 David Edelsohn <edelsohn@gnu.org>
+
+ * rs6000.c (validate_condition_mode): Test flag_finite_math_only
+ for CCFPmode.
+
+2002-07-31 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/crtn.asm: Don't use __mips16 to determine the
+ return-address offset. Define RA to a suitable temporary
+ register for the return address.
+
+2002-07-31 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips.md (eh_set_lr_si, eh_set_lr_di): Change
+ constraints to 'd'.
+
+2002-07-30 Chris Demetriou <cgd@broadcom.com>
+
+ * config/mips/elf.h (STARTFILE_SPEC): Define differently if
+ default ABI is MEABI. (Undoes incorrect change in Eric Christopher's
+ patch on 2002-07-29.)
+ * config/mips/elf64.h (STARTFILE_SPEC): Likewise.
+
+2002-07-30 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * alpha.h, arc.h, arm/aout.h, avr.h, cris.h, d30v.h, dsp16xx.h,
+ fr30.h, h8300.h, i370.h, i386/sco5.h, i386/unix.h, i960.h, ia64.h,
+ ip2k.h, m32r.h, mcore.h, mips.h, mn10200.h, mn10300.h, ns32k.h,
+ openbsd.h, pa/pa-linux.h, pdp11.h, romp.h, rs6000/sysv4.h,
+ s390/linux.h, sh.h, sparc.h, stormy16.h, v850.h, vax.h, xtensa.h:
+ (ASM_GLOBALIZE_LABEL): Delete.
+ (GLOBAL_ASM_OP): Define.
+
+ * m68hc11.h, m68k.h, m88k.h (ASM_GLOBALIZE_LABEL): Delete.
+
+ * defaults.h (ASM_GLOBALIZE_LABEL): Provide a default.
+ * doc/tm.texi (ASM_GLOBALIZE_LABEL): Update docs.
+
+2002-07-30 Geoffrey Keating <geoffk@redhat.com>
+
+ * doc/extend.texi (Hints implementation): Document that GCC
+ mostly ignores `register'.
+
+2002-07-30 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ * flags.h: Declare flag_finite_math_only.
+ Use it in definition of HONOR_NANS and
+ HONOR_INFINITIES.
+ * c-common.c (cb_register_builtins): Emit
+ __FINITE_MATH_ONLY__ when flag_finite_math_only
+ is set.
+ * combine.c (simplify_if_then_else): If
+ flag_finite_math_only is set, a == b has a
+ definite value.
+ * toplev.c: Initialize flag_finite_math_only.
+ (set_flags_fast_math): Set it on -ffast-math.
+ (flag_fast_math_set_p): Test it.
+ * doc/invoke.texi: Document -ffinite-math-only.
+
+2002-07-30 Richard Henderson <rth@redhat.com>
+
+ * ifcvt.c (noce_get_alt_condition): Use reg_overlap_mentioned_p.
+ (noce_process_if_block): Likewise.
+
+2002-07-30 Bernd Schmidt <bernds@redhat.com>
+
+ * ifcvt.c (cond_exec_process_if_block): Fix a merging error.
+ Bail out early if false_expr is NULL and we'd crash due to this.
+ * genemit.c (gen_expand): Recognize return insns even if the return
+ appears in a parallel.
+ * libgcc2.c: Expand macro DECLARE_LIBRARY_RENAMES if it is defined.
+ * config/fp-bit.c: Likewise.
+ * doc/tm.texi: Document it.
+
+2002-07-30 David Edelsohn <edelsohn@gnu.org>
+ Zack Weinberg <zack@codesourcery.com>
+
+ * rs6000.c (rs6000_expand_unop_builtin): Check icode not
+ CODE_FOR_nothing. Change switch to if.
+ (rs6000_expand_binop_builtin): Same.
+ (rs6000_expand_builtin): Expand builtin if target support enabled.
+ (rs6000_init_builtins): Init builtin if target support enabled.
+ (rs6000_common_init_builtins): Check icode not CODE_FOR_nothing.
+
+2002-07-30 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ * gcc.c (cpp_unique_options): Define __GXX_ABI_VERSION, bump it to 101.
+
+2002-07-30 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips.h (SUBTARGET_ASM_DEBUGGING_SPEC): Fix typo.
+
+2002-07-30 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.md (cond_delay_slot): New attribute.
+ (cbranch delay): Use it for anulled-true case.
+ (stuff_delay_slot): New pattern.
+ * sh.c (print_operand, case '.'): Don't print .s / /s fore zero-length
+ delay slot insn.
+ (gen_far_branch): Emit stuff_delay_slot pattern.
+
+2002-07-30 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * unroll.c (copy_loop_body): Don't copy NOTE_INSN_LOOP_CONT.
+
+2002-07-30 Kazu Hirata <kazu@cs.umass.edu>
+
+ * fold-const.c: Fix comment typos.
+ * gcse.c: Likewise.
* reload1.c: Likewise.
- * reload.c: Likewise.
- * rtl.c: Likewise.
-2002-01-09 Kazu Hirata <kazu@hxi.com>
+2002-07-29 Aldy Hernandez <aldyh@redhat.com>
- * rtlanal.c (find_reg_fusage): Use XEXP instead of SET_DEST
- to extract items in the expr_list chain.
+ * config/rs6000/rs6000.md: Disallow CCEQ compare with crnor/crnot
+ for TARGET_SPE.
-2002-01-09 Richard Henderson <rth@redhat.com>
+2002-07-30 Gabriel Dos Reis <gdr@nerim.net>
- * config/vax/vax.c (vax_rtx_cost): Never abort.
+ * c-pretty-print.h (pp_c_statement): Declare.
+ * c-pretty-print.c (pp_c_postfix_expression): #if 0 support for SRCLOC.
+ (pp_c_statement): Define.
- * config/vax/vax.h (REAL_ARITHMETIC): Define.
+2002-07-30 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-01-09 Jan Hubicka <jh@suse.cz>
+ * alpha.h, arc.h, arm/aout.h, avr.h, c4x.h, cris.h, d30v.h,
+ darwin.h, dsp16xx.h, fr30.h, h8300.h, i370.h, i386.h, i960.h,
+ ip2k.h, m32r.h, m68hc11.h, m68k.h, m88k.h, mcore.h, mips.h,
+ mn10200.h, mn10300.h, ns32k.h, pa/pa-linux.h, pdp11.h, romp.h,
+ rs6000/sysv4.h, s390/linux.h, sh.h, sparc.h, stormy16.h,
+ v850.h, vax.h, xtensa.h (ASM_OUTPUT_LABEL): Delete definition.
- * gcse.c (cprop_jump): Delete insn if simplified jump is no-op.
+ * defaults.h (ASM_OUTPUT_LABEL): Provide a default.
+ * doc/tm.texi (ASM_OUTPUT_LABEL): Update docs.
-2002-01-09 Richard Henderson <rth@redhat.com>
+2002-07-30 Gabriel Dos Reis <gdr@nerim.net>
- * config/arm/arm.c (arm_gen_constant): Use trunc_int_for_mode.
- Unify code from various alternatives.
+ * c-pretty-print.c (pp_c_primary_expression): Handle STMT_EXPR.
+ (pp_c_postfix_expression): Handle ARROW_EXPR, FFS_EXPR,
+ COMPOUND_LITERAL_EXPR, VA_ARG_EXPR.
+ (pp_c_expression): Update.
-2002-01-09 Richard Henderson <rth@redhat.com>
+2002-07-29 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * regrename.c (copy_value): Ignore the copy if the source register
- is present in the value chain with a narrower mode.
+ * alpha/vms-cc.c (preprocess_args, main): Use xstrdup and/or
+ concat in lieu of xmalloc/strcpy/memcpy/sprintf.
+ * alpha/vms-ld.c (main): Likewise.
+ * dsp16xx.c (double_reg_to_memory): Likewise.
+ * mcore.c (mcore_expand_prolog): Likewise.
+ * cppfiles.c (read_name_map): Likewise.
+ * gensupport.c (process_rtx, identify_predicable_attribute,
+ alter_test_for_insn): Likewise.
+ * vmsdbgout.c (write_rtnbeg, vmsdbgout_init): Likewise.
-2002-01-09 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+2002-07-29 Roger Sayle <roger@eyesopen.com>
- * real.c (c4xtoe, toc4x): Do some special conversion on long doubles
- for the c4x target. Also improve layout.
+ * builtins.c (expand_builtin): Change the default behavior to
+ only issue an error if the builtin function doesn't have a
+ fallback library call. Remove several cases handled by the
+ new default.
-2002-01-09 Richard Henderson <rth@redhat.com>
+2002-07-29 John David Anglin <dave@hiauly1.hia.nrc>
- * config/m32r/m32r.c (move_src_operand): Fix 32-bit int test.
- * config/m32r/m32r.md (and ior xor splitters): Swap operands
- to match insn patterns.
+ * real.c (ieee_24, ieee_53, ieee_64, ieee_113): Define only if the
+ floating point format of the target is IEEE.
+ * (dec_f, dec_d, dec_g, dec_h): Define only if the floating point
+ format of the target is DEC.
-2002-01-09 Richard Henderson <rth@redhat.com>
+2002-07-29 Richard Henderson <rth@redhat.com>
- * regrename.c (find_oldest_value_reg): Use gen_rtx_raw_REG.
- (copyprop_hardreg_forward_1): Likewise.
+ * unroll.c (verify_addresses): Remove.
+ (find_splittable_givs): Never split DEST_ADDR givs.
-2002-01-09 John David Anglin <dave@hiauly1.hia.nrc.ca>
+2002-07-29 Geoffrey Keating <geoffk@redhat.com>
- * pa.md (decrement_and_branch_until_zero): Change predicate for
- operand 0 from register_operand to reg_or_nonsymb_mem_operand.
+ * doc/gty.texi (GGC Roots): Clarify that the list of syntaxes
+ is exhaustive.
+ (Files): Improve documentation on generated source files.
-2002-01-09 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
+ * doc/extend.texi (Translation implementation): Document what
+ diagnostics look like.
+ (Identifiers implementation): Document that there's normally no
+ limit on identifier names.
+ (Integers implementation): Document two's complement.
+ (Hints implementation): Document that GCC honors 'inline', mostly.
+ (Preprocessing directives implementation): Document that GCC
+ requires the current time.
- * ginclude/stddef.h: Define _BSD_WCHAR_T_DEFINED_ if _BSD_WCHAR_T_
- gets undefined. For Darwin.
+2002-07-30 Gabriel Dos Reis <gdr@nerim.net>
-2002-01-09 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+ * c-pretty-print.h (struct c_pretty_print_info): Add new member.
+ (pp_initializer): New macro.
+ (pp_c_initializer): Declare.
+ * c-pretty-print.c (pp_c_primary_expression): HAndle TARGET_EXPR.
+ (pp_c_initializer): Define.
+ (pp_c_initializer_list): New function.
+ (pp_c_postfix_expression): Handle ABS_EXPR, COMPLEX_CST,
+ VECTOR_CST, CONSTRUCTOR.
+ (pp_c_unary_expression): Handle CONJ_EXPR, REALPART_EXPR,
+ IMAGPART_EXPR.
+ (pp_c_cast_expression): Handle FLOAT_EXPR.
+ (pp_c_assignment_expression): Handle INIT_EXPR.
+ (pp_c_expression): Update.
- * config/c4x/c4x.h: Use PUSH_ARGS and PUSH_ROUNDING for stack passing.
+2002-07-30 Neil Booth <neil@daikokuya.co.uk>
-2002-01-09 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+ * objc/objc-act.c (objc_init): Return immediately if filename
+ is NULL.
- * config/c4x/c4x/md: Remove extraneous constraints from define_splits.
+2002-07-29 Eric Christopher <echristo@redhat.com>
+
+ * config/mips/elf.h: Remove ecoff.h and gofast includes.
+ (DWARF2_DEBUGGING_INFO, DBX_DEBUGGING_INFO): Define unconditionally.
+ (SDB_DEBUGGING_INFO): Undefine.
+ (PREFERRED_DEBUGGING_TYPE): Set to DWARF2_DEBUG.
+ (PUT_SDB_SIZE): Remove.
+ (SUBTARGET_ASM_DEBUGGING_SPEC): Redefine.
+ (STARTFILE_SPEC): Add isa3264 define.
+ * config/mips/elf64.h: Ditto. Move TARGET_MEM_FUNCTIONS from here...
+ * config/mips/ecoff.h: Remove. and here...
+ * config/mips/iris3.h: and here...
+ * config/mips/sni-svr4.h: and here...
+ * config/mips/mips.h: To here. Remove OBJECT_FORMAT_ROSE ifdefs.
+ Add assembler -mmdebug options for non-dwarf debugging.
+ * config/mips/r3900.h: Remove debug info defines.
+ * config/mips/isa32-linux.h: Remove, move functionality to config.gcc.
+ * config/mips/isa3264.h: Ditto.
+ * config/mips/t-isa3264: Fix up for file removal and gofast configure
+ change.
+ * config/mips/t-elf: Ditto.
+ * config/mips/t-ecoff: Ditto.
+ * config/mips/t-r3900: Ditto.
+ * config/mips/t-iris5-6: Ditto.
+ * config/mips/t-isa3264: Ditto.
+ * config/mips/t-linux: Remove.
+ * config/mips/t-netbsd: Remove.
+ * config/mips/t-mips: New file.
+ * config/mips/t-gofast: Ditto.
+ * config/mips/netbsd.h: Remove unnecessary undefines.
+ * config/mips/linux.h: Remove #include of mips.h.
+ * config.gcc: Add mips.h include for elf targets. Remove tm_file
+ for ecoff. Add gofast configure option for mips.
+
+2002-07-29 Chris Demetriou <cgd@broadcom.com>
+
+ * configure.in (mips*-*-*): Add a test to see if MIPS libgloss
+ linker scripts use STARTUP directives consistently.
+ * configure: Regenerate.
+ * config.in: Regenerate.
+ * config/mips/elf.h (STARTFILE_SPEC): Define conditionally, based
+ on whether HAVE_MIPS_LIBGLOSS_STARTUP_DIRECTIVES is defined.
+ * config/mips/elf64.h (STARTFILE_SPEC): Likewise.
+ * config/mips/isa3264.h (STARTFILE_SPEC): Do not redefine if
+ HAVE_MIPS_LIBGLOSS_STARTUP_DIRECTIVES is set; the result
+ will be the same.
+
+2002-07-29 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.md ("cpu"): Add ppc8540 to attribute.
+
+2002-07-29 Aldy Hernandez <aldyh@redhat.com>
-2002-01-08 Richard Henderson <rth@redhat.com>
+ * config/rs6000/rs6000.h (RTX_COSTS): Add MULT case for 8540.
- * regrename.c (copy_value): Ignore overlapping copies.
+2002-07-29 Aldy Hernandez <aldy@quesejoda.com>
-2002-01-08 Richard Henderson <rth@redhat.com>
+ * config/rs6000/rs6000.md: Move altivec patterns from here...
+
+ * config/rs6000/altivec.md: ...to here.
- * config/alpha/alpha.c (alpha_split_conditional_move): Call copy_rtx
- as needed to avoid shared structure.
+2002-07-29 Aldy Hernandez <aldyh@redhat.com>
-2002-01-08 Kazu Hirata <kazu@hxi.com>
+ * config/rs6000/spe.md ("spe_evmra"): Change to unspec.
- * config/h8300/h8300.c (get_shift_alg): Fix 15-bit LSHIFTRT on
- H8/300H and H8/S.
+2002-07-29 Richard Henderson <rth@redhat.com>
-2002-01-08 Joseph S. Myers <jsm28@cam.ac.uk>
+ * emit-rtl.c (set_mem_attributes_minus_bitpos): Rename from
+ set_mem_attributes and add BITPOS argument. Subtract it from
+ OFFSET when same is adjusted.
+ (set_mem_attributes): New wrapper function.
+ * expr.c (expand_assignment): Use set_mem_attributes_minus_bitpos;
+ remove offset adjustment hack.
+ * expr.h (set_mem_attributes_minus_bitpos): Declare.
- * doc/tm.texi (EASY_DIV_EXPR, IMPLICIT_FIX_EXPR,
- LONGJMP_RESTORE_FROM_STACK, MAX_INT_TYPE_SIZE): Remove
- documentation of obsolete macros.
- * system.h: Poison these macros.
- * config/1750a/1750a.h, config/a29k/a29k.h, config/alpha/alpha.h,
- config/arc/arc.h, config/arm/arm.h, config/avr/avr.h,
- config/c4x/c4x.h, config/clipper/clipper.h,
- config/convex/convex.h, config/cris/cris.h, config/d30v/d30v.h,
- config/dsp16xx/dsp16xx.h, config/elxsi/elxsi.h,
- config/fr30/fr30.h, config/h8300/h8300.h, config/i370/i370.h,
- config/i386/i386.h, config/i860/i860.h, config/i960/i960.h,
- config/ia64/ia64.h, config/m32r/m32r.h, config/m68hc11/m68hc11.h,
- config/m68k/m68k.h, config/m88k/m88k.h, config/mcore/mcore.h,
- config/mips/mips.h, config/mmix/mmix.h, config/mn10200/mn10200.h,
- config/mn10300/mn10300.h, config/ns32k/ns32k.h, config/pa/pa.h,
- config/pdp11/pdp11.h, config/pj/pj.h, config/romp/romp.h,
- config/rs6000/rs6000.h, config/s390/s390.h, config/sh/sh.h,
- config/sparc/sparc.h, config/stormy16/stormy16.h,
- config/v850/v850.h, config/vax/vax.h, config/we32k/we32k.h: Remove
- definitions and commented out definitions of obsolete macros.
- * config/mips/iris5.h (MAX_WCHAR_TYPE_SIZE): Don't define in terms
- of MAX_INT_TYPE_SIZE.
+2002-07-29 Gabriel Dos Reis <gdr@nerim.net>
-2002-01-08 Ulrich Weigand <uweigand@de.ibm.com>
+ * Makefile.in (C_OBJS): Include c-pretty-print.o
+ (c-pretty-print.o): Add depency rule.
+ * pretty-print.h: Add more macros.
+ * c-pretty-print.c: New file.
+ * c-pretty-print.h: Likewise.
- * config/s390/s390.c (s390_preferred_reload_class): Never
- return ADDR_REGS if it isn't a subset of the given class.
- * config/s390/s390.h (REGISTER_MOVE_COST): Penalize not just
- FP_REGS, but all superclasses as well.
+2002-07-29 Aldy Hernandez <aldyh@redhat.com>
- * config/s390/s390.c (s390_function_profiler): Fix thinko.
+ * config/rs6000/spe.h (__internal_ev_mwhgumian): Cast vector
+ constants to __ev64_s32__.
+ (__internal_ev_mwhgsmian): Same.
+ (__internal_ev_mwhgsmfan): Same.
+ (__internal_ev_mwhgssfan): Same.
+ (__internal_ev_mwhgumiaa): Same.
+ (__internal_ev_mwhgsmiaa): Same.
+ (__internal_ev_mwhgsmfaa): Same.
+ (__internal_ev_mwhgssfaa): Same.
- * config/s390/s390.md (cmpdi_ccu_mem, cmpsi_ccu_mem,
- cmphi_ccu_mem, cmpqi_ccu_mem): First operand of compare
- must not be a const_int.
+2002-07-29 David Edelsohn <edelsohn@gnu.org>
-2002-01-08 Richard Henderson <rth@redhat.com>
+ * varasm.c (assemble_variable): Narrow test for uninitialized
+ without BSS target support.
- * Makefile.in (toplev.o): Depend on options.h.
- (gcc.o): Depend on specs.h.
+2002-07-29 Nathan Sidwell <nathan@codesourcery.com>
-2002-01-08 Jakub Jelinek <jakub@redhat.com>
+ * profile.c: Add file comment describing the overall algorithm and
+ structures.
+ (struct edge_info): Add comments.
+ (struct bb_info): Add comments.
+ * basic-block.h (EDGE_*): Add comments.
+ * doc/gcov.texi (Gcov Data Files): Document bit flags.
- * expr.c (store_expr): Convert VOIDmode constants back to target's
- mode.
+2002-07-29 Bob Wilson <bob.wilson@acm.org>
-2002-01-08 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+ * config/xtensa/elf.h, config/xtensa/linux.h
+ (TARGET_OS_CPP_BUILTINS): Define.
+ (CPP_PREDEFINES): Remove.
+ * config/xtensa/xtensa.h (TARGET_CPU_CPP_BUILTINS): Define.
+ (CPP_SPEC): Remove.
- * doc/invoke.texi: Markup gcc as @command. Refer to
- http://gcc.gnu.org/onlinedocs/gcc/Contributors.html instead
- of http://gcc.gnu.org/thanks.html.
+2002-07-29 Zack Weinberg <zack@codesourcery.com>
-2002-01-08 Dale Johannesen <dalej@apple.com>
+ * gensupport.c: Include hashtab.h.
+ (insn_elision, condition_table, hash_c_test, cmp_c_test,
+ maybe_eval_c_test): New routines and data structures to
+ support insn elision.
+ (init_md_reader): Read and initialize the condition_table.
+ (read_md_rtx): Discard insn patterns whose C test is provably
+ always false.
+ * gensupport.h: Declare new functions and data structures.
- * config/rs6000/rs6000.md: Add missing int register
- target case to movdf_low.
+ * genconditions.c, dummy-conditions.c: New files.
+ * Makefile.in: Build genconditions; run it to construct
+ insn-conditions.c; build that and link it into most gen*
+ programs.
+ (HOST_SUPPORT, HOST_EARLY_SUPPORT): New variables.
+ (GEN): Delete, unused.
+ (STAGESTUFF): Update.
-2002-01-08 Zack Weinberg <zack@codesourcery.com>
+ * gencodes.c: (gen_insn): #define CODE_FOR_xxx equal to
+ CODE_FOR_nothing for all elided patterns.
+ (main): Tweaked to support this.
+ * genflags.c (gen_proto): Emit a static inline generator
+ function here for all elided patterns, which simply returns
+ NULL_RTX.
+ (gen_insn): Do not define HAVE_xxx for elided patterns.
+ (main): Tweaked to support this. No need to forward-declare
+ struct rtx_def.
+ * genrecog.c: Do not bother emitting the C test if it's known
+ to be true at compile time.
- * Makefile.in (cs-tconfig.h): Don't depend on $(CONFIG_H) or
- except.h. Remove commands to define USING_SJLJ_EXCEPTIONS.
- (cppinit.o): Depend on except.h.
- (gencheck.h, options.h, specs.h, s-gencheck, s-options,
- s-specs): New rules.
+2002-07-29 Mike Stump <mrs@apple.com>
- * configure.in: Don't AC_DEFINE_UNQUOTED PACKAGE or VERSION.
- Don't create specs.h/options.h/gencheck.h here. Remove
- unnecessary variable settings from last argument of AC_OUTPUT.
- * config.in, configure: Regenerate.
- * intl.c: Hardcode package name as "gcc".
+ * config.gcc (target_gtfiles): Initialize, as otherwise cross
+ compilers hosted on powerpc-apple-darwin6.0 won't even build.
- * cppinit.c: Include except.h.
- (builtin_array): Define __USING_SJLJ_EXCEPTIONS__ when
- appropriate.
- * unwind-dw2.c, unwind-sjlj.c, config/ia64/unwind-ia64.c:
- Use #if(n)def __USING_SJLJ_EXCEPTIONS, not #if
- (!)USING_SJLJ_EXCEPTIONS.
- * doc/cpp.texi: Document __USING_SJLJ_EXCEPTIONS__.
-
-2002-01-08 Joseph S. Myers <jsm28@cam.ac.uk>
-
- * doc/tm.texi (ASM_OUTPUT_EH_REGION_BEG, ASM_OUTPUT_EH_REGION_END,
- ASM_OUTPUT_LABELREF_AS_INT, DOESNT_NEED_UNWINDER, EH_TABLE_LOOKUP,
- OBJC_SELECTORS_WITHOUT_LABELS, OMIT_EH_TABLE): Remove
- documentation of obsolete macros.
- * system.h: Poison these macros.
- * config/d30v/d30v.h, config/ns32k/encore.h,
- config/stormy16/stormy16.h: Remove definitions and commented out
- definitions of obsolete macros.
-
-Tue Jan 8 15:56:41 2002 Nicola Pero <nicola@brainstorm.co.uk>
-
- * objc/objc-act.c (handle_class_ref): Mark the declaration of
- %sobjc_class_ref_%s as used - to prevent unwanted compiler
- warnings.
+2002-07-29 Richard Earnshaw <rearnsha@arm.com>
-2002-01-08 Ulrich Weigand <uweigand@de.ibm.com>
+ * arm.md (sibcall, sibcall_value): Add RETURN as part of the pattern,
+ remove clobber of LR.
+ (sibcall_insn, sibcall_value_insn): Update accordingly.
+ (sibcall_epilogue): Remove debugging comment from assembler stream.
- * config/s390/linux.h (ASM_OUTPUT_LABELREF): Remove.
- * config/s390/s390.c (s390_emit_epilog): Add REG_FRAME_RELATED_EXPR
- to insn adjusting stack/frame pointer.
- * config/s390/s390.md (reload_la_64, reload_la_31): Do not
- accept operands that cause the insn to be non-splittable.
+2002-07-29 Gabriel Dos Reis <gdr@nerim.net>
-2002-01-08 Graham Stott <grahams@redhat.com>
+ * pretty-print.h: Define more macros.
+ * diagnostic.h (output_formatted_integer): Moved from...
+ * diagnostic.c: ... here.
- * c-tree.h (C_TYPE_FIELDS_READONLY): Uppercase macro parameter.
- (C_TYPE_FIELDS_VOLATILE): Likewise.
- (C_TYPE_BEING_DEFINED): Likewise.
- (C_IS_RESERVED_WORD): Likewise.
- (C_TYPE_VARIABLE_SIZE): Likewise.
- (C_DECL_VARIABLE_SIZE): Likewise.
- (C_MISSING_PROTOTYPE_WARNED): Likewise.
- (C_SET_EXP_ORIGINAL_CODE): Likewise.
- (C_TYPEDEF_EXPLICITLY_SIGNED): Uppercase macro parameter and remove
- parenthesis.
- (C_DECL_ANTICIPATED): Likewise.
- (c_build_type_variant): Add parenthesis.
+2002-07-28 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-01-08 Joseph S. Myers <jsm28@cam.ac.uk>
+ * stormy16.h (ASM_OUTPUT_SYMBOL_REF): Use ASM_OUTPUT_LABEL_REF.
- * gcc.c (option_map): Remove --version.
- (process_command): Handle -fversion following the GNU Coding
- Standards. Partially addresses PR other/704.
+2002-07-28 Zack Weinberg <zack@codesourcery.com>
-2002-01-08 Graham Stott <grahams@redhat.com>
+ * defaults.h (ASM_OUTPUT_MEASURED_SIZE): Take only two
+ arguments. Always use ".-symbol" as expression argument.
+ * doc/tm.texi: Update to match. Document requirement for
+ ".size symbol, .-symbol" to be acceptable to assembler.
- * combine.c (combine_instructions): Fix typo.
+ * config/elfos.h, config/netbsd-aout.h, config/openbsd.h,
+ config/arm/elf.h, config/avr/avr.h, config/cris/aout.h,
+ config/i386/freebsd-aout.h, config/i386/sco5.h,
+ config/ip2k/ip2k.h, config/m88k/m88k.h, config/xtensa/elf.h,
+ config/xtensa/linux.h: Update uses of ASM_OUTPUT_MEASURED_SIZE.
-2002-01-08 Graham Stott <grahams@redhat.com>
+2002-07-28 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * debug.h: Use "tree" and "rtx" throughout.
+ * Makefile.in (gengtype-lex.c): Fix error in last change.
- * debug.c: Likewise.
+ * alpha/freebsd.h (TARGET_OS_CPP_BUILTINS): Add missing
+ backslash.
-2002-01-08 Nick Clifton <nickc@cambridge.redhat.com>
+ * Makefile.in (vmsdbgout.o): Depend on function.h.
- * dbxout.c (dbxout_symbol_location): If a symbol ref is in the
- constant pool, use the pool's version of the symbol instead.
+ * vmsdbgout.c: Include function.h.
-2002-01-07 Richard Henderson <rth@redhat.com>
+2002-07-28 Alan Modra <amodra@bigpond.net.au>
- * regrename.c (find_oldest_value_reg): Ignore the value chain if
- the original register was copied in a mode with a fewer number of
- hard registers than the desired mode.
- (copyprop_hardreg_forward_1): Likewise.
- (debug_value_data): Fix loop test.
- * toplev.c (parse_options_and_default_flags): Reenable
- -fcprop-registers at -O1.
+ * prefix.c (update_path): Don't strip single `.' path components
+ unless stripping a later `..' component. Exit loop as soon as
+ a valid path is found.
-2002-01-07 Aldy Hernandez <aldyh@redhat.com>
+2002-07-27 Roger Sayle <roger@eyesopen.com>
- * config/rs6000/rs6000.c (bdesc_2arg): Add altivec predicates.
- (altivec_init_builtins): New node v4si_ftype_v16qi_v16qi.
+ * builtins.def [DEF_GCC_BUILTIN]: Require an explicit ATTRS
+ argument. Mark BUILT_IN_RETURN, BUILT_IN_EH_RETURN,
+ BUILT_IN_LONGJMP and BUILT_IN_TRAP as noreturn, the ISO C99
+ floating point unordered comparisons (e.g. __builtin_isgreater)
+ as const, and leave the remaining GCC_BUILTINs unchanged.
- * config/rs6000/rs6000.h (rs6000_builtins): Add enums for altivec
- predicates.
+ * c-decl.c (builtin_function): No need to explicitly mark
+ BUILT_IN_RETURN and BUILT_IN_EH_RETURN as noreturn.
- * config/rs6000/rs6000.md: Add altivec predicate patterns.
+2002-07-27 Roger Sayle <roger@eyesopen.com>
-2002-01-07 John David Anglin <dave@hiauly1.hia.nrc.ca>
+ * Makefile.in: rtlanal.o now depends upon real.h.
- * pa.c (FUNC_BEGIN_PROLOG_LABEL, current_function_number): Define.
- (pa_output_function_prologue): Output local label at the beginning of
- the prologue when profiling.
- (hppa_profile_hook): Use the local label rather than the function label.
- * pa.h (PROFILE_BEFORE_PROLOGUE): Define.
+ * flags.h [flag_signaling_nans]: New flag.
+ [HONOR_SNANS]: New macro.
-2002-01-07 Aldy Hernandez <aldyh@redhat.com>
+ * toplev.c [flag_signaling_nans]: Initialize to false.
+ (f_options): Add processing for "-fsignaling-nans".
+ (set_fast_math_flags): Clear flag_signaling_nans with -ffast-math.
+ (process_options): flag_signaling_nans implies flag_trapping_math.
- * config/rs6000/rs6000.c (print_operand): Remove extra space.
- (altivec_expand_unop_builtin): Fix thinko.
- (altivec_expand_binop_builtin): Same.
- (altivec_expand_ternop_builtin): Same.
- (altivec_expand_builtin): Same.
+ * c-common.c (cb_register_builtins): Define __SUPPORT_SNAN__
+ when -fsignaling-nans. First step to implementing WG14's N965.
-2002-01-07 Richard Henderson <rth@redhat.com>
+ * fold-const.c (fold) [MULT_EXPR]: Conditionalize transforming
+ 1.0 * x into x, and -1.0 * x into -x on !HONOR_SNANS.
+ [RDIV_EXPR]: Conditionalize x/1.0 into x on !HONOR_SNANS.
- * config/rs6000/xcoff.h (ASM_FILE_START): Reverted to profile_flag.
+ * simplify-rtx.c (simplify_relational_operation): Conditionalize
+ transforming abs(x) < 0.0 into false on !HONOR_SNANS.
-2002-01-07 Jason Merrill <jason@redhat.com>
+ * rtlanal.c: #include real.c for TARGET_FLOAT_FORMAT definitions
+ required by HONOR_SNANS. (may_trap_p): Floating point DIV, MOD,
+ UDIV, UMOD, GE, GT, LE, LT and COMPARE may always trap with
+ -fsignaling_nans. EQ and NE only trap for flag_signaling_nans
+ not flag_trapping_math (i.e. HONOR_SNANS but not HONOR_NANS).
- * unwind-dw2.c (execute_cfa_program): Use < again.
+ * doc/invoke.texi: Document new -fsignaling-nans compiler option.
-2002-01-07 Jakub Jelinek <jakub@redhat.com>
+2002-07-27 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * predict.c (combine_predictions_for_insn): Avoid division by zero.
+ * Makefile.in (gengtype-lex.c): Work around a bug in flex.
+ * gengtype-lex.l (YY_USE_PROTOS): Undef.
+ (YY_DECL): Define.
-2002-01-07 Jakub Jelinek <jakub@redhat.com>
+2002-07-27 Roger Sayle <roger@eyesopen.com>
- * simplify-rtx.c (simplify_plus_minus): Bump n_ops for NOT.
- Don't allow -1 - x -> ~x simplifications in the first pass.
+ * doc/invoke.texi: Document that both -fno-builtin-foo and
+ -fno-builtin are supported by the g++ front-end.
-2002-01-07 Aldy Hernandez <aldyh@redhat.com>
+2002-07-27 Stan Shebs <shebs@apple.com>
- * rs6000.c (altivec_expand_ternop_builtin): Don't die on invalid
- arguments.
- (altivec_expand_binop_builtin): Same.
- (altivec_expand_unop_builtin): Same.
- (print_operand): Fix typo.
- (bdesc_1arg): Add vupk* variants.
+ * configure.in: Rename config_gtfiles to target_gtfiles.
+ * configure: Regenerate.
+ * doc/gty.texi: Update reference.
+ * config.gcc (powerpc-*-darwin*): Set target_gtfiles
+ instead of appending to it.
- * rs6000.h (rs6000_builtins): Add vupk* enums.
+2002-07-25 Aldy Hernandez <aldyh@redhat.com>
- * rs6000.md: Add altivec_vupk* variants.
+ * config/rs6000/rs6000.c (function_arg_advance): SPE vararg
+ vectors are split into two registers.
+ (function_arg): Same.
-2002-01-07 Joseph S. Myers <jsm28@cam.ac.uk>
+2002-07-26 J"orn Rennecke <joern.rennecke@superh.com>
- * doc/gcc.texi, doc/gccint.texi, doc/cppinternals.texi,
- doc/install.texi, doc/invoke.texi, doc/rtl.texi: Update copyright
- and last update dates.
+ * pa.md (extv): Check predicates before emitting extv_32.
-2002-01-07 Janis Johnson <janis187@us.ibm.com>
+2002-07-27 Alan Modra <amodra@bigpond.net.au>
- * doc/rtl.texi (Flags): Clean up documentation of RTL flags
+ * config/rs6000/rs6000.c (rs6000_traceback_name): New var.
+ (rs6000_traceback): New var.
+ (rs6000_override_options): Set rs6000_traceback.
+ (rs6000_output_function_epilogue): Implement traceback options.
+ * config/rs6000/rs6000.h (TARGET_OPTIONS): Add "traceback=".
+ (rs6000_traceback_name): Declare.
-2002-01-07 Marek Michalkiewicz <marekm@amelek.gda.pl>
+ * config/rs6000/rs6000.c (output_profile_hook): Don't generate profile
+ label reference when NO_PROFILE_COUNTERS.
- * config/avr/avr.c (avr_mcu_types): Add new MCU types.
- * config/avr/avr.h (CPP_SPEC): Likewise.
- (LINK_SPEC): Likewise.
- (CRT_BINUTILS_SPECS): Likewise.
- * config/avr/t-avr (MULTILIB_MATCHES): Likewise.
- * doc/invoke.texi (AVR Options): Document them.
-
-Mon Jan 7 11:59:34 CET 2002 Jan Hubicka <jh@suse.cz>
-
- * unroll.c (copy_loop_body): Always properly update JUMP_LABEL and
- LABEL_NUSES.
-
-2002-01-07 Graham Stott <grahams@redhat.com>
-
- * config/i386/i386.h: Update copyright date.
- (HALF_PIC_PTR): Add parenthesis.
- (OPTIMIZATION_OPTIONS): Whitespace, add parenthesis and wrap.
- (CONSTANT_ALIGNMENT): Add parenthesis.
- (DATA_ALIGNMENT): Likewise.
- (LOCAL_ALIGNMENT): Likewise.
- (FUNCTION_ARG_BOUNDARY): Whitespace, add parenthesis and wrap.
- (IS_STACK_MODE): Uppercase macro parameter, add parenthesis and wrap.
- (CONDITIONAL_REGISTER_USAGE): Wrap in do {...} while (0).
- (HARD_REGNO_NREGS): Add paranethesis.
- (VALID_SSE_REG_MODE): Whitespace.
- (VALID_MMX_REG_MODE): Whitespace.
- (VALID_FP_MODE_P): Uppercase macros parameter and whitespace.
- (ix86_hard_regno_mode_ok): Add parenthesis.
- (HARD_REGNO_CALLER_SAVE_MODE): Whitespace.
- (RETURN_IN_MEMORY): Whitespace.
- (N_REG_CLASSES): Add parenthesis.
- (INTEGER_CLASS_P): Add parenthesis and wrap.
- (FLOAT_CLASS_P): Likewise.
- (SSE_CLASS_P): Likewise.
- (MMX_CLASS_P): Likewise.
- (MAYBE_INTEGER_CLASS_P): Likewise.
- (MAYBE_FLOAT_CLASS_P): Likewise.
- (MAYBE_SSE_CLASS_P): Likewise.
- (MAYBE_MMX_CLASS_P): Likewise.
- (Q_CLASS_P): Likewise.
- (GENERAL_REGNO_P): Uppercase macro parameter.
- (REX_INT_REGNO_P): Uppercase macro parameter and wrap.
- (FP_REGNO_P): Likewise.
- (ANY_FP_REGNO_P): Uppercase macro parameter.
- (SSE_REGNO_P): Likewise.
- (SSE_REGNO): Likewise.
- (SSE_REG_P): Likewise.
- (SSE_FLOAT_MODE_P): Likewise.
- (MMX_REGNO_P): Likewise.
- (MMX_REG_P):Likewise.
- (STACK_REG_P): Likewise.
- (NON_STACK_REG_P): Likewise.
- (STACK_TOP_P): Likewise.
- (CONVERT_HARD_REGISTER_TO_SSA_P): Add parenthesis.
- (PREFERRED_RELOAD_CLASS): Add parenthesis and whitespace.
- (SECONDARY_MEMORY_NEEDED): Likewise.
- (SECONDARY_OUTPUT_RELOAD_CLASS): Whitespace.
- (MD_ASM_CLOBBERS): Whitespace and wrap.
- (MUST_PASS_IN_STACK): Whitespace and wrap.
- (RETURN_POPS_ARGS): Add parenthesis.
- (INIT_CUMULATIVE_ARGS): Likewise.
- (FUNCTION_ARG): Likewise.
- (FUNCTION_OK_FOR_SIBCALL): Add parenthesis and whitespace.
- (SETUP_INCOMING_VARARGS): Likewise.
- (BUILD_VA_LIST_TYPE): Add parenthesis.
- (EXPAND_BUILTIN_VA_START): Uppercase macro paremeters and add
- parenthsis.
- (EXPAND_BUILTIN_VA_ARG): Likewise.
- (FUNCTION_PROFILER): Wrap in do { ... } while (0) and add parenthesis.
- (INITIALIZE_TRAMPOLINE): Add parenthesis.
- (INITIAL_ELIMINATION_OFFSET): Likewise.
- (REGNO_OK_FOR_INDEX_P): Add parenthesis.
- (REGNO_OK_FOR_BASE_P): Likewise.
- (REGNO_OK_FOR_SIREG_P): Add parenthesis and wrap.
- (REGNO_OK_FOR_DIREG_P): Likewise.
- (REG_OK_FOR_INDEX_P): Whitespace.
- (REG_OK_FOR_BASE_P): Whitespace.
- (GO_IF_LEGITIMATE_ADDRESS): Wrap in do { ... } while (0) and add
- parenthesis.
- (FIND_BASE_TERM): Fix typo.
- (LEGITIMIZE_ADDRESS): Wrap in { .. } while (0) and add parenthesis.
- (REWRITE_ADDRESS): Uppercase macro parameter and whitespace.
- (SYMBOLIC_CONST; Whitespace.
- (GO_IF_MODE_DEPENDENT_ADDRESS):Wrap in { .. } while (0) and wrap.
- (ENCODE_SECTION_INFO): Whitespace.
- (FINALIZE_PIC): Remove do { ... } while (0).
- (PROMOTE_MODE): Wrap in do { ... } while (0).
- (CONST_COSTS): Whitespace.
- (RTX_COSTS): Add paramethesis, whitespace and wrap.
- (REGISTER_MOVE_COST): Add parenthesis.
- (MEMORY_MOVE_COST): Likewise.
- (EXTRA_CC_MODES): Whitespace.
- (SELECT_CC_MODE): Add parenthesis and whitespace.
- (DBX_REGISTER_NUMBER): Uppercase macro parameter and add parenthsis.
- (ASM_PREFERRED_EH_DATA_FORMAT): Add parenthesis and whitespace.
- (ASM_OUTPUT_LABEL): Add paramethesis.
- (ASM_OUTPUT_REG_PUSH): Add parenthesis and whitespace.
+2002-07-26 Jason Merrill <jason@redhat.com>
+
+ * function.c (assign_parms): Handle frontend-directed pass by
+ invisible reference.
+
+2002-07-26 Neil Booth <neil@daikokuya.co.uk>
+
+ * doc/cppopts.texi: Update.
+
+2002-07-26 Neil Booth <neil@daikokuya.co.uk>
+
+ * cppmacro.c (_cpp_create_definition): Don't attempt redefinition
+ warnings on assertions.
+
+2002-07-26 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-common.h (RID_AND, RID_AND_EQ, RID_NOT, RID_NOT_EQ,
+ RID_OR, RID_OR_EQ, RID_XOR, RID_XOR_EQ, RID_BITAND, RID_BITOR,
+ RID_COMPL): Remove.
+ * c-parse.in (rid_to_yy): Similarly.
+
+2002-07-26 Jason Merrill <jason@redhat.com>
+
+ * c-dump.c: Resurrect.
+ * tree-dump.c: Move C-specific stuff to c-dump.c.
+ * c-common.h: Declare c_dump_tree.
+ * c-lang.c (LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN): Define.
+ * Makefile.in (C_AND_OBJC_OBJS): Add c-dump.o.
+ (c-dump.o): New rule.
+
+2002-07-26 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.md: Enable patterns using rlwinm for
+ PowerPC64. Replace "T" and "S" constraints with "n" when the
+ predicate will do. Formatting fixes.
+ (extzvsi_internal2): Use "andi.", "andis." and attr type of "compare"
+ as for extzvsi_internal1.
+
+2002-07-25 Neil Booth <neil@daikokuya.co.uk>
+
+ * dwarfout.c (VERSION_ASM_OP, DERIV_BEGIN_LABEL_FMT,
+ DERIV_END_LABEL_FMT): Remove.
+ (SL_BEGIN_LABEL_FMT, SL_END_LABEL_FMT): Move.
+
+2002-07-25 Neil Booth <neil@daikokuya.co.uk>
+
+ * objc/objc-act.c (UTAG_STATICS, UTAG_PROTOCOL_LIST, USERTYPE):
+ Remove.
+
+2002-07-25 Stan Shebs <shebs@apple.com>
+
+ * config/rs6000/rs6000.c (rs6000_emit_prologue): Remove unused
+ local var dwarfp.
+ (output_compiler_stub): Remove unused locals.
+ (output_call): Always initialize line number.
+
+2002-07-25 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.h (LOAD_EXTEND_OP): QImode zero-extends on SHmedia.
+ * sh.md (truncdiqi2, movqi_media): Likewise.
+
+2002-07-25 Neil Booth <neil@daikokuya.co.uk>
+
+ * gcse.c (obstack_chunk_alloc): Remove.
+ (gcse_alloc): Fix to count allocated bytes.
+ * collect2.c (SYMBOL__MAIN): Remove.
+
+2002-07-25 Neil Booth <neil@daikokuya.co.uk>
+
+ * gcc.c (TARGET_EXECUTABLE_SUFFIX): Only used if
+ HAVE_TARGET_EXECUTABLE_SUFFIX.
+
+2002-07-25 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * rtl.h (mem_attrs): Spell out more clearly the roles of ALIGN,
+ SIZE, EXPR and OFFSET.
+
+2002-07-25 Richard Henderson <rth@redhat.com>
+
+ * emit-rtl.c (set_mem_attributes): Fix size and alignment thinkos
+ in ARRAY_REF of DECL_P case.
+
+2002-07-25 Richard Sandiford <rsandifo@redhat.com>
+
+ * doc/invoke.texi: Document -mabi=meabi, and expand on the EABI
+ description. Document -mips32, -mips64, and the associated -march
+ values. Describe the "mipsN" arguments to -march. Say that the
+ -mipsN options are equivalent to -march. Reword the description
+ of default type sizes.
+ * toplev.h (target_flags_explicit): Declare.
+ * toplev.c (target_flags_explicit): New var.
+ (set_target_switch): Update target_flags_explicit.
+ * config/mips/abi64.h (SUBTARGET_TARGET_OPTIONS): Undefine.
+ * config/mips/elf64.h (MIPS_ISA_DEFAULT): Undefine.
+ * config/mips/iris6.h (SUBTARGET_ASM_SPEC): -mabi=64 implies -mips3.
+ * config/mips/isa3264.h (MIPS_ENABLE_EMBEDDED_O32): Undefine.
+ * config/mips/mips.h (mips_cpu_info): New struct.
+ (mips_cpu_string, mips_explicit_type_size_string): Remove.
+ (mips_cpu_info_table, mips_arch_info, mips_tune_info): Declare.
+ (MIPS_CPP_SET_PROCESSOR): New macro.
+ (TARGET_CPP_BUILTINS): Declare a macro for each supported processor.
+ Define _MIPS_ARCH and _MIPS_TUNE.
+ (MIPS_ISA_DEFAULT): Don't provide a default value. Instead...
+ (MIPS_CPU_STRING_DEFAULT): Set to "from-abi" if neither it nor
+ MIPS_ISA_DEFAULT were already defined.
+ (MULTILIB_DEFAULTS): Add MULTILIB_ABI_DEFAULT.
+ (TARGET_OPTIONS): Remove -mcpu and -mexplicit-type-size.
+ (ABI_NEEDS_32BIT_REGS, ABI_NEEDS_64BIT_REGS): New.
+ (GAS_ASM_SPEC): Remove -march, -mcpu, -mgp* and -mabi rules.
+ (ABI_GAS_ASM_SPEC): Remove.
+ (MULTILIB_ABI_DEFAULT, ASM_ABI_DEFAULT_SPEC): New macros.
+ (ASM_SPEC): Add -mgp32, -mgp64, -march, -mabi=eabi and -mabi=o64.
+ Invoke %(asm_abi_default_spec) if no ABI was specified.
+ (CC1_SPEC): Remove ISA -> register-size rules.
+ (EXTRA_SPECS): Remove abi_gas_asm_spec. Add asm_abi_default_spec.
+ * config/mips/mips.c (mips_arch_info, mips_tune_info): New vars.
+ (mips_cpu_string, mips_explicit_type_size_string): Remove.
+ (mips_cpu_info_table): New array.
+ (mips_set_architecture, mips_set_tune): New fns.
+ (override_options): Rework to make -mipsN equivalent to -march.
+ Detect more erroneous cases, including those removed from CC1_SPEC.
+ Don't change the ABI based on architecture, or vice versa.
+ Unify logic with GAS.
+ (mips_asm_file_start): Get architecture name from mips_arch_info.
+ (mips_strict_matching_cpu_name_p, mips_matching_cpu_name_p): New fns.
+ (mips_parse_cpu): Take the name of the option as argument. Handle
+ 'from-abi'. Raise an error if the option is wrong.
+ (mips_cpu_info_from_isa): New fn.
+
+2002-07-25 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips.md (tablejump_mips161): Use gen_rtx_LABEL_REF.
+ (tablejump_mips162): Likewise.
+
+2002-07-25 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * simpify-rtx.c (simplify_subreg): Don't pass MODE_CC mode to
+ int_mode_for_mode.
+
+2002-07-25 Gabriel Dos Reis <gdr@nerim.net>
+
+ * c-common.c (c_sizeof_or_alignof_type): Take a third argument for
+ complaining.
+ * c-common.h (c_sizeof): Adjust definition.
+ (c_alignof): Likewise.
+ * c-tree.h (c_sizeof_nowarn): Now macro.
+ * c-typeck.c (c_sizeof_nowarn): Remove definition.
+
+2002-07-25 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-decl.c (c_decode_option): No need to handle switches
+ cpplib handles.
+
+2002-07-24 Zack Weinberg <zack@codesourcery.com>
+
+ * defaults.h (ASM_OUTPUT_TYPE_DIRECTIVE, ASM_OUTPUT_SIZE_DIRECTIVE,
+ ASM_OUTPUT_MEASURED_SIZE): New default definitions of new macros.
+ * doc/tm.texi: Document them. Also document SIZE_ASM_OP,
+ TYPE_ASM_OP, and TYPE_OPERAND_FMT.
+
+ * config/elfos.h, config/netbsd-aout.h, config/openbsd.h,
+ config/alpha/elf.h, config/arm/elf.h, config/avr/avr.h,
+ config/cris/aout.h, config/i386/freebsd-aout.h,
+ config/i386/sco5.h, config/ia64/ia64.c, config/ip2k/ip2k.h,
+ config/m68k/m68kelf.h, config/m68k/m68kv4.h, config/m88k/m88k.h,
+ config/mcore/mcore-elf.h, config/mips/elf.h, config/mips/elf64.h,
+ config/mips/iris6.h, config/mips/linux.h, config/pa/pa-linux.h,
+ config/pa/pa64-hpux.h, config/rs6000/sysv4.h,
+ config/xtensa/elf.h, config/xtensa/linux.h:
+ Use the new macros.
+ Where possible, remove redundant definitions of SIZE_ASM_OP,
+ TYPE_ASM_OP, and TYPE_OPERAND_FMT.
+
+2002-07-24 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/eabi.h: Define TARGET_SPE_ABI, TARGET_SPE,
+ TARGET_ISEL, and TARGET_FPRS.
+
+ * doc/invoke.texi (RS/6000 and PowerPC Options): Document
+ -mabi=spe, -mabi=no-spe, and -misel=.
+
+ * config/rs6000/rs6000-protos.h: Add output_isel.
+ Move vrsave_operation prototype here.
+
+ * config/rs6000/rs6000.md (sminsi3): Allow pattern for TARGET_ISEL.
+ (smaxsi3): Same.
+ (uminsi3): Same.
+ (umaxsi3): Same.
+ (abssi2_nopower): Disallow when TARGET_ISEL.
+ (*ne0): Same.
+ (negsf2): Change to expand and rename old pattern to *negsf2.
+ (abssf2): Change to expand and rename old pattern to *abssf2.
+
+ New expanders: fix_truncsfsi2, floatunssisf2, floatsisf2,
+ fixunssfsi2.
+
+ Change patterns that check for TARGET_HARD_FLOAT or
+ TARGET_SOFT_FLOAT to also check TARGET_FPRS.
+
+ * config/rs6000/rs6000.c: New globals: rs6000_spe_abi,
+ rs6000_isel, rs6000_fprs, rs6000_isel_string.
+ (rs6000_override_options): Add 8540 case to
+ processor_target_table.
+ Set rs6000_isel for the 8540.
+ Call rs6000_parse_isel_option.
+ (enable_mask_for_builtins): New.
+ (rs6000_parse_isel_option): New.
+ (rs6000_parse_abi_options): Add spe and no-spe.
+ (easy_fp_constant): Treat !TARGET_FPRS as soft-float.
+ (rs6000_legitimize_address): Check for TARGET_FPRS when checking
+ for TARGET_HARD_FLOAT.
+ Add case for SPE_VECTOR_MODE.
+ (rs6000_legitimize_reload_address): Handle SPE vector modes.
+ (rs6000_legitimate_address): Disallow PRE_INC/PRE_DEC for SPE
+ vector modes.
+ Check for TARGET_FPRS when checking for TARGET_HARD_FLOAT.
+ (rs6000_emit_move): Check for TARGET_FPRS.
+ Add cases for SPE vector modes.
+ (function_arg_boundary): Return 64 for SPE vector modes.
+ (function_arg_advance): Check for TARGET_FPRS and
+ Handle SPE vectors.
+ (function_arg): Same.
+ (setup_incoming_varargs): Check for TARGET_FPRS.
+ (rs6000_va_arg): Same.
+ (struct builtin_description): Un-constify mask field. Move up in
+ file.
+ (bdesc_2arg): Un-constify and add SPE builtins.
+ (bdesc_1arg): Same.
+ (bdesc_spe_predicates): New.
+ (bdesc_spe_evsel): New.
+ (rs6000_expand_unop_builtin): Add SPE 5-bit literal builtins.
+ (rs6000_expand_binop_builtin): Same.
+ (bdesc_2arg_spe): New.
+ (spe_expand_builtin): New.
+ (spe_expand_predicate_builtin): New.
+ (spe_expand_evsel_builtin): New.
+ (rs6000_expand_builtin): Call spe_expand_builtin for SPE.
+ (rs6000_init_builtins): Initialize SPE builtins. Call
+ rs6000_common_init_builtins.
+ (altivec_init_builtins): Move all non-altivec builtin code to...
+ (rs6000_common_init_builtins): ...here. New function.
+ (branch_positive_comparison_operator): Allow NE code for SPE.
+ (ccr_bit): Return correct ccr bit for SPE fp.
+ (print_operand): Emit crnor in 'D' case for SPE.
+ New case 't'.
+ Add SPE code for 'y' case.
+ (rs6000_generate_compare): Generate rtl for SPE fp.
+ (output_cbranch): Handle SPE hard floats.
+ (rs6000_emit_cmove): Handle isel.
+ (rs6000_emit_int_cmove): New.
+ (output_isel): New.
+ (rs6000_stack_info): Adjust stack frame so GPRs are saved in
+ 64-bits for SPE.
+ (debug_stack_info): Add SPE info.
+ (gen_frame_mem_offset): New.
+ (rs6000_emit_prologue): Save GPRs in 64-bits for SPE abi.
+ Change mode of frame pointer, when saving it, to Pmode.
+ (rs6000_emit_epilogue): Restore GPRs in 64-bits for SPE abi.
+ Misc cleanups and use gen_frame_mem_offset when appropriate.
+
+ * config/rs6000/rs6000.h (processor_type): Add PROCESSOR_PPC8540.
+ (TARGET_SPE_ABI): New.
+ (TARGET_SPE): New.
+ (TARGET_ISEL): New.
+ (TARGET_FPRS): New.
+ (FIXED_SCRATCH): New.
+ (RTX_COSTS): Add PROCESSOR_PPC8540.
+ (ASM_CPU_SPEC): Add case for 8540.
+ (TARGET_OPTIONS): Add isel= case.
+ (rs6000_spe_abi): New.
+ (rs6000_isel): New.
+ (rs6000_fprs): New.
+ (rs6000_isel_string): New.
+ (UNITS_PER_SPE_WORD): New.
+ (LOCAL_ALIGNMENT): Adjust for SPE.
+ (HARD_REGNO_MODE_OK): Same.
+ (DATA_ALIGNMENT): Same.
+ (MEMBER_TYPE_FORCES_BLK): New.
+ (FIRST_PSEUDO_REGISTER): Set to 113.
+ (FIXED_REGISTERS): Add SPE registers.
+ (reg_class): Same.
+ (REG_CLASS_NAMES): Same.
+ (REG_CLASS_CONTENTS): Same.
+ (REGNO_REG_CLASS): Same.
+ (REGISTER_NAMES): Same.
+ (DEBUG_REGISTER_NAMES): Same.
+ (ADDITIONAL_REGISTER_NAMES): Same.
+ (CALL_USED_REGISTERS): Same.
+ (CALL_REALLY_USED_REGISTERS): Same.
+ (SPE_ACC_REGNO): New.
+ (SPEFSCR_REGNO): New.
+ (SPE_SIMD_REGNO_P): New.
+ (HARD_REGNO_NREGS): Adjust for SPE.
+ (VECTOR_MODE_SUPPORTED_P): Same.
+ (REGNO_REG_CLASS): Same.
+ (FUNCTION_VALUE): Same.
+ (LIBCALL_VALUE): Same.
+ (LEGITIMATE_OFFSET_ADDRESS_P): Same.
+ (SPE_VECTOR_MODE): New.
+ (CONDITIONAL_REGISTER_USAGE): Disable FPRs when target does FP on
+ the GPRs. Set FIXED_SCRATCH fixed in SPE case.
+ (rs6000_stack): Add spe_gp_size, spe_padding_size,
+ spe_gp_save_offset.
+ (USE_FP_FOR_ARG_P): Check for TARGET_FPRS.
+ (LEGITIMATE_LO_SUM_ADDRESS_P): Same.
+ (SPE_CONST_OFFSET_OK): New.
+ (rs6000_builtins): Add SPE builtins.
+
+ * testsuite/gcc.dg/ppc-spe.c: New.
+
+ * config/rs6000/eabispe.h: New.
+
+ * config/rs6000/spe.h: New.
+
+ * config/rs600/spe.md: New.
+
+ * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define
+ __SIMD__ for TARGET_SPE.
+
+ * config.gcc: Add powerpc-*-eabispe* case.
+ Add spe.h to user headers for powerpc.
+
+2002-07-24 Chris Demetriou <cgd@broadcom.com>
+
+ * config/mips/elf.h (STARTFILE_SPEC): Undo previous change.
+ * config/mips/elf64.h (STARTFILE_SPEC): Likewise.
+ * config/mips/isa3264.h (STARTFILE_SPEC): Likewise.
+
+2002-07-24 Richard Henderson <rth@redhat.com>
+
+ * expr.c (expand_expr) [TRY_FINALLY_EXPR]: Use GOTO_SUBROUTINE_EXPR
+ form when not optimizing.
+
+2002-07-24 David Mosberger <davidm@hpl.hp.com>
+
+ * config/ia64/ia64.c (gen_thread_pointer): Fix typo in marking
+ thread_pointer_rtx as unchanging.
+
+2002-07-24 Michael Matz <matz@suse.de>
+
+ * ra-colorize.c (INV_REG_ALLOC_ORDER): New macro.
+ (free_reg): Use it.
+
+2002-07-24 Richard Earnshaw <rearnsha@arm.com>
+
+ * arm.md (arm_buneq, arm_bltgt): put '\' before ';' in output
+ pattern.
+ (arm_buneq_reversed, arm_bltgt_reversed): Likewise.
+ (movsicc, movsfcc, movdfcc): FAIL if UNEQ or LTGT.
+
+2002-07-24 Chris Demetriou <cgd@broadcom.com>
+
+ * config/mips/elf.h (STARTFILE_SPEC): Never include crt0.o.
+ * config/mips/elf64.h (STARTFILE_SPEC): Likewise.
+ * config/mips/isa3264.h (STARTFILE_SPEC): Do not redefine.
+
+2002-07-24 Jan Hubicka <jh@suse.cz>
+
+ * toplev.c (rest_of_compilation): Dump loops before clobbering
+ the structure.
+
+2002-07-24 Jan Hubicka <jh@suse.cz>
+
+ * rtlanal.c (keep_with_call_p): Avoid overflow in fixed_regs.
+
+2002-07-24 Frank van der Linden <fvdl@wasabisystems.com>
+
+ PR optimization/7291
+ * config/i386/i386.c (ix86_expand_clrstr): Fix bzero alignment
+ problem on x86_64.
+
+2002-07-24 Gabriel Dos Reis <gdr@nerim.net>
+
+ * pretty-print.h: Add macros from cp/error.c
+
+2002-07-24 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000-protos.h (mask_operand_wrap): Declare.
+ (mask64_2_operand): Declare.
+ (build_mask64_2_operands): Declare.
+ (and64_2_operand): Declare.
+ (extract_MB): Declare.
+ (extract_ME): Declare.
+ * config/rs6000/rs6000.c (mask64_operand): Allow all ones. Remove
+ CONST_DOUBLE code.
+ (mask_operand_wrap): New insn predicate.
+ (mask64_2_operand): Likewise.
+ (and64_2_operand): Likewise.
+ (build_mask64_2_operands): New function.
+ (extract_MB): New function.
+ (extract_ME): New function.
+ (print_operand <case m,M>): Use extract_MB and extract_ME.
+ (print_operand <case S>): Allow all ones. Remove CONST_DOUBLE support.
+ * config/rs6000/rs6000.h (EXTRA_CONSTRAINT): Add 't'.
+ (PREDICATE_CODES): Add and64_2_operand, mask_operand_wrap and
+ mask64_2_operand. Remove CONST_DOUBLE from mask64_operand.
+ * config/rs6000/rs6000.md (andsi3_internal3): New
+ (andsi3_internal3+1): Enable split for powerpc64.
+ (andsi3_internal3+2): New split.
+ (andsi3_internal4): Renamed old andsi3_internal3.
+ (andsi3_internal5): New.
+ (andsi3_internal5+1): Enable split for powerpc64.
+ (andsi3_internal5+2): New split.
+ (andsi3_internal6, andsi3_internal7, andsi3_internal8): New.
+ (anddi3): Handle 't' constraint.
+ (anddi3+1): New split.
+ (anddi3_internal2): Handle 't' constraint.
+ (anddi3_internal2+1): New split.
+ (anddi3_internal3): Handle 't' constraint.
+ (anddi3_internal3+1): New split.
+
+2002-07-24 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.md: Remove scratch reg on insns using
+ addze and similar (plus (comparison r1 r2) r3) insns. Add
+ missing scratch reg in one case. Formatting fixes.
+
+2002-07-24 Neil Booth <neil@daikokuya.co.uk>
+
+ * cppexp.c (parse_defined): Mark macro used.
+ * cpphash.h (struct cpp_macro): New member "used".
+ (_cpp_mark_macro_used, _cpp_warn_if_unused_macro): New.
+ (struct cpp_reader): New member.
+ * cppinit.c (cpp_finish_options): Set first_unused_line.
+ (cpp_finish): Warn of unused macros if requested.
+ (OPT_TABLE): New switches.
+ (cpp_handle_option): Handle them.
+ * cpplib.c (do_undef): Warn if macro unused.
+ (do_ifdef, do_ifndef): Mark macro used.
+ * cpplib.h (struct cpp_options): New member.
+ * cppmacro.c (_cpp_warn_if_unused_macro): New.
+ (enter_macro_context): Mark macro used.
+ (_cpp_create_definition): Mark macro unused; warn if unused
+ when redefined.
+ * cpptrad.c (scan_out_logcial_line, push_replacement_text):
+ Mark macros used.
+ * doc/cppopts.texi: Update.
+
+2002-07-23 Neil Booth <neil@daikokuya.co.uk>
+
+ * dwarf2out.c (SECTION_ASM_OP,
+ ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL): Remove.
+ * system.h (SECTION_ASM_OP): Poison.
+ * tree.c (FILE_FUNCTION_PREFIX_LEN): Remove.
+ * config/alpha/alpha-interix.h, config/mips/linux.h
+ (ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL): Remove.
+ * config/mmix/mmix-protos.h, config/mmix/mmix.c
+ (mmix_asm_output_define_label_difference_symbol): Remove.
+ * config/mmix/mmix.h
+ (ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL): Remove.
+ * doc/tm.texi: Remove documentation.
+
+2002-07-23 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * recog.c (asm_operand_ok): Allow float CONST_VECTORs for 'F'.
+ (constrain_operands): Likewise.
+ * regclass.c (record_reg_classes): Likewise.
+ * reload.c (find_reloads): Likewise.
+ * doc/md.texi: Likewise.
+
+ * reload.c (find_reloads_toplev): Use simplify_gen_subreg.
+ * simplify-rtx.c (simplify_subreg): When converting to a non-int
+ mode, try to convert to an integer mode of matching size first.
+
+ * simplify-rtx.x (simplify_subreg): When constructing a CONST_VECTOR
+ from individual subregs, check that each subreg has been generated
+ sucessfully.
+
+2002-07-23 Neil Booth <neil@daikokuya.co.uk>
+
+ * genautomata.c (VLA_HWINT_SHORTEN, VLA_HWINT_LAST): Remove.
+ * df.c (HANDLE_SUBREG, FOR_EACH_BB_IN_BITMAP_REV,
+ FOR_EACH_BB_IN_SBITMAP): Remove.
+ * gcse.c (NEVER_SET, FOLLOW_BACK_EDGES): Remove.
+ * haifa-sched.c (DONE_PRIORITY, MAX_PRIORITY, TAIL_PRIORITY,
+ LAUNCH_PRIORITY, DONE_PRIORITY_P, LOW_PRIORITY_P): Remove.
+ * loop.c (PREFETCH_BLOACK_IN_LOOP_MIN,
+ PREFETCH_LIMIT_TO_SIMULTANEOUS): Remove.
+ * regrename.c (REGNO_MODE_OK_FOR_BASE_P): Remove.
+
+2002-07-23 Gabriel Dos Reis <gdr@nerim.net>
+
+ * pretty-print.h: New file.
+
+2002-07-23 Paul Koning <pkoning@equallogic.com>
+
+ * real.c (REAL_WORDS_BIG_ENDIAN): Make 1 for DEC.
+ (LARGEST_EXPONENT_IS_NORMAL): Ditto.
+ (VAX_HALFWORD_ORDER): Define (1 for DEC VAX, 0 otherwise).
+ (TARGET_G_FLOAT): Default to 0 if not defined.
+ (ieeetoe): New, common routine to convert target format floats
+ to internal form.
+ (e24toe, e53toe): Change to use ieeetoe, distinguish DEC
+ vs. others.
+ (e113toe): Change to use ieeetoe.
+
+2002-07-23 Roman Lechtchinsky <rl@cs.tu-berlin.de>
+
+ * real.c (REAL_WORDS_BIG_ENDIAN): Make sure it is 0 for DEC and 1 for
+ IBM.
+ (e53toe): Assume IEEE if non of DEC, IBM and C4X is defined.
+ (e64toe): Remove special cases for DEC and IBM. Remove support for
+ ARM_EXTENDED_IEEE_FORMAT.
+ (e24toe): Remove special cases for DEC.
+ (significand_size): Simplify. Indent.
+ (ieee_format, ieee_24, ieee_53, ieee_64, ieee_113): New.
+ (etoieee, toieee): New.
+ (etoe113, toe113, etoe64, toe64, etoe53, toe53, etoe24, toe24): Use
+ etoieee and toieee for IEEE arithmetic.
+
+2002-07-23 Gabriel Dos Reis <gdr@nerim.net>
+
+ * doc/extend.texi: Say ISO C90, not ISO C89.
+ * doc/invoke.texi: Likewise.
+ * doc/standards.texi: Likewise.
+
+2002-07-23 Steve Ellcey <sje@cup.hp.com>
+
+ * gcc/explow.c (convert_memory_address): Fix conversion of CONSTs.
+ Fix permutation of conversion and plus/mult.
+ * gcc/builtins.c (expand_builtin_memcpy) Ensure return pointer is
+ ptr_mode and not Pmode when POINTERS_EXTEND_UNSIGNED is defined.
+ (expand_builtin_strncpy) Ditto.
+ (expand_builtin_memset) Ditto.
+
+2002-07-23 Gabriel Dos Reis <gdr@nerim.net>
+
+ Fix PR/7363:
+ * c-common.c (c_sizeof_or_alignof_type): New function.
+ (c_alignof): Remove definition.
+ * c-common.h (c_sizeof, c_alignof): Define as macros.
+ (c_sizeof_or_alignof_type): Declare.
+ (my_friendly_assert): Moved from cp/cp-tree.h
+ * c-typeck.c (c_sizeof): Remove definition.
+
+2002-07-23 Jan Hubicka <jh@suse.cz>
+
+ * gcse.c (try_replace_reg): Use num_changes_pending.
+ * recog.c (num_changes_pending): New function.
+ (validate_replace_src): Use validate_repalce_src_group.
+ (validate_replace_src_group): New.
+ * recog.h (validate_repalce_src_group): New.
+ (num_changes_pending): Likewise.
+
+2002-07-23 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * calls.c (emit_library_call_value_1): If
+ FUNCTION_ARG_PASS_BY_REFERENCE is true, pretend this is neither
+ libcall, const call nor pure call.
+
+2002-07-23 Neil Booth <neil@daikokuya.co.uk>
+
+ * config/m88k/m88k.h (SECTION_ASM_OP): Remove.
+
+2002-07-23 Neil Booth <neil@daikokuya.co.uk>
+
+ * vmsdbgout.c (SECTION_ASM_OP): Remove.
+
+2002-07-23 Neil Booth <neil@daikokuya.co.uk>
+
+ * config/i386/i386.c (AT_BP): Remove.
+
+2002-07-23 Neil Booth <neil@daikokuya.co.uk>
+
+ * defaults.h (obstack_chunk_alloc, obstack_chunk_free):
+ Default definition.
+ * gcse.c: Don't define obstack_chunk_free.
+ * collect2.c, conflict.c, df.c, diagnostic.c, fix-header.c,
+ flow.c, gcc.c, genattrtab.c, genautomata.c, genflags.c, gensupport.c,
+ integrate.c, loop.c, ra.c, read-rtl.c, regrename.c, reload1.c,
+ reorg.c, tlink.c, tree.c, config/arm/arm.c, objc/objc-act.c:
+ Don't define obstack macros.
+
+2002-07-22 Stephane Carrez <stcarrez@nerim.fr>
+
+ PR target/6744
+ * config/m68hc11/m68hc11.c (m68hc11_z_replacement): Also replace
+ ASM_OPERANDS instructions.
+
+2002-07-22 Stephane Carrez <stcarrez@nerim.fr>
+
+ PR target/7361
+ * config/m68hc11/m68hc11.c (go_if_legitimate_address_internal): Accept
+ constant addresses only on 68HC12.
+
+2002-07-22 Neil Booth <neil@daikokuya.co.uk>
+
+ * cppfiles.c (stack_include_file): Correct test of whether
+ a dependency should be output.
+
+2002-07-22 David Edelsohn <edelsohn@gnu.org>
+
+ * collect2.c (is_ctor_dtor): Add other possible JOINER values.
+
+2002-07-22 Richard Earnshaw <rearnsha@arm.com>
+
+ * arm.md (movqi): If optimizing and we can create pseudos, use
+ a ZERO_EXTEND to load from memory, then copy the result into the
+ target.
+ (movhi): Likewise, but only for ARMv4.
+
+2002-07-22 Neil Booth <neil@daikokuya.co.uk>
+
+ * ssa-ccp.c (PHI_PARMS): Remove.
+
+2002-07-22 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips.h (CLASS_CANNOT_CHANGE_MODE): Include FP_REGS
+ on big-endian targets.
+
+2002-07-22 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * hwint.h (HOST_WIDE_INT_PRINT_DEC_SPACE,
+ HOST_WIDE_INT_PRINT_UNSIGNED_SPACE,
+ HOST_WIDEST_INT_PRINT_DEC_SPACE, HOST_WIDEST_INT_PRINT_DEC_SPACE):
+ New formatting macros.
+
+ * ra-debug.c (dump_static_insn_cost): Avoid string concatenation.
+
+2002-07-22 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * rtlanal.c (subreg_regno_offset): Return correct offset for
+ big endian paradoxical subregs.
+
+ * optabs.c (expand_vector_unop): Don't expand using sub_optab
+ if we got the wrong mode.
+
+ * hwint.c (define HOST_WIDE_INT_PRINT_DEC_C): New define.
+ * genrecog.c (write_switch, write_cond): Use it.
+ * genemit.c (gen_exp): Likewise.
+
+2002-07-22 Jakub Jelinek <jakub@redhat.com>
+
+ * c-decl.c (build_compound_literal): Set decl TREE_READONLY from TYPE.
+
+2002-07-22 Jakub Jelinek <jakub@redhat.com>
+
+ * c-decl.c (build_compound_literal): Defer compound literal decls
+ until until file end to emit them only if they are actually used.
+
+2002-07-21 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * ra-build.c (check_conflict_numbers): Hide unused function.
+ (livethrough_conflicts_bb): Avoid automatic aggregate
+ initialization.
+ (parts_to_webs_1): Avoid `U' integer constant modifier.
+ (conflicts_between_webs): Wrap a variable in the macro controlling
+ its usage.
+ * ra-debug.c (ra_debug_msg): Use VA_OPEN/VA_CLOSE.
+ (dump_igraph, dump_graph_cost): Avoid string concatenation
+ (dump_static_insn_cost): Avoid automatic aggregate
+ initialization.
+ * ra-rewrite.c (insert_stores): Avoid automatic aggregate
+ initialization.
+ (dump_cost): Avoid string concatenation
+
+2002-07-21 Richard Henderson <rth@redhat.com>
+
+ * expr.c (expand_expr) [TRY_FINALLY_EXPR]: Don't use
+ GOTO_SUBROUTINE_EXPR when finally_block can be re-expanded.
+
+2002-07-21 Richard Henderson <rth@redhat.com>
+
+ * unroll.c (find_splittable_givs): Do not split DEST_ADDR givs
+ that are not unrolled completely.
+
+2002-07-21 Richard Henderson <rth@redhat.com>
+
+ * loop.h (LOOP_AUTO_UNROLL): Rename from LOOP_FIRST_PASS.
+ * loop.c (strength_reduce): Update.
+ * toplev.c (rest_of_compilation): Do unrolling in the first
+ loop pass, not the second.
+
+2002-07-21 Richard Henderson <rth@redhat.com>
+
+ * emit-rtl.c (set_mem_attributes): Preserve indirection of PARM_DECL
+ when flag_argument_noalias == 2.
+ * alias.c (nonoverlapping_memrefs_p): Handle that.
+ * print-rtl.c (print_mem_expr): Likewise.
+
+2002-07-21 Hartmut Schirmer <hartmut.schirmer@arcor.de>
+
+ * libgcc2.c (__divdi3, __moddi3): Use unary minus operator
+ instead of __negdi2 directly.
+
+2002-07-21 Neil Booth <neil@daikokuya.co.uk>
+
+ * gengenrtl.c (gencode): Don't define obstack_alloc_rtx.
+ * function.c (SYMBOL__MAIN): Remove definition.
+ * global.c (SET_CONFLICT, REGBITP, ALLOCNO_LIVE_P): Remove.
+ * predict.c (PROB_NEVER, PROB_LIKELY, PROB_UNLIKELY): Remove.
+ * profile.c (GCOV_INDEX_TO_BB): Remove.
+ * sched-rgn.c (ABS_VALUE, MIN_DIFF_PRIORITY, MIN_PROB_DIFF): Remove.
+ * simplify-rtx.c (FIXED_BASE_PLUS_P): Remove.
+
+2002-07-21 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-lex.c (GET_ENVIRONMENT): Remove.
+ * collect2.c (GET_ENV_PATH_LIST): Remove.
+ (prefix_from_env): Use GET_ENVIRONMENT.
+ * cppinit.c (GET_ENV_PATH_LIST): Remove.
+ (init_standard_includes): Use GET_ENVIRONMENT.
+ * defaults.h (GET_ENVIRONMENT): Define here if not already.
+ * gcc.c (GET_ENV_PATH_LIST): Remove.
+ (make_relative_prefix, process_command): Update.
+ * protoize.c (GET_ENV_PATH_LIST): Remove.
+ (do_processing): Update.
+
+2002-07-21 Gabriel Dos Reis <gdr@nerim.net>
+
+ * c-decl.c (build_array_declarator): Say 'ISO C90', not 'ISO C89'.
+ (grokdeclarator): Likewise.
+ * c-format.c (C_STD_NAME): Likewise.
+ * c-lex.c (interpret_integer): Likewise.
+ * c-typeck.c (build_array_ref): Likewise.
+ * cpplex.c (_cpp_lex_direct): Likewise.
+ * toplev.c (documented_lang_options): Likewise.
+
+2002-07-21 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-format.c (T99_I, T99_UI): Remove.
+
+2002-07-21 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-typeck.c (SAVE_SPELLING_DEPTH): Remove.
+
+2002-07-21 Jan Hubicka <jh@suse.cz>
+
+ * gcse.c (do_local_cprop): Do not extend lifetimes of registers set by
+ do_local_cprop.
+
+2002-07-21 Andreas Jaeger <aj@suse.de>
+
+ * reload1.c (fixup_abnormal_edges): Remove unused variable.
+
+2002-07-21 Bernd Schmidt <bernds@redhat.com>
+
+ Improvements for the ifcvt pass from Michael Meissner, with patches
+ by Richard Sandiford <rsandifo@redhat.com>
+ * basic-block.h (struct ce_if_block, ce_if_block_t): New types.
+ * ifcvt.c (cond_exec_changed_p): New static variable.
+ (last_active_insn): New function, renamed from last_active_insn_p
+ and changed to return the last active insn in a basic block. All
+ callers updated.
+ (block_fallthru): New function.
+ (cond_exec_process_insns): New argument CE_INFO. Pass it to
+ IFCVT_MODIFY_INSN. All callers updated.
+ Return false if START or END are NULL.
+ Handle case where we're processing an insn that is already
+ conditional.
+
+ (noce_process_if_block): CE_INFO argument rather than
+ multiple args containing the involved basic blocks. All callers
+ changed.
+ (process_if_block, merge_if_block, find_if_block,
+ cond_exec_process_if_block): Likewise.
+
+ (cond_exec_process_if_block): New arg DO_MULTIPLE_P. All callers
+ changed.
+ Use new function last_active_insn to simplify some code.
+ New code to handle multiple tests.
+ Call IFCVT_MODIFY_CANCEL in all failure cases, otherwise set
+ cond_exec_changed_p to TRUE.
+
+ (process_if_block): New code to handle multiple tests.
+ (merge_if_block): Likewise.
+ (find_if_header): New arg PASS. Changed to return the currently
+ processed basic block or NULL instead of true/false. All callers
+ changed.
+ Call IFCVT_INIT_EXTRA_FIELDS.
+ (block_jumps_and_fallthru_p): New function.
+ (find_if_block): Discover opportunities to convert multiple tests.
+ Add additional debugging output.
+ Update the ce_info structure before returning.
+
+ (if_convert): Run multiple passes of if-conversion.
+ * doc/tm.texi (IFCVT_MODIFY_TESTS, IFCVT_MODIFY_INSN,
+ IFCVT_MODIFY_FINAL, IFCVT_MODIFY_CANCEL, IFCVT_MODIFY_MULTIPLE_TESTS,
+ IFCVT_INIT_EXTRA_FIELDS, IFCVT_EXTRA_FIELDS): Update documentation for
+ these macros.
+
+2002-07-21 Jan Hubicka <jh@suse.cz>
+
+ * gcse.c: Include cselib.h
+ (constptop_register): Break out from ...
+ (cprop_insn): ... here; kill basic_block argument.
+ (do_local_cprop, local_cprop_pass): New functions.
+ (one_cprop_pass): Call local_cprop_pass.
+
+2002-07-20 Roger Sayle <roger@eyesopen.com>
+
+ * simplify-rtx.c (simplify_relational_operation): Optimize
+ abs(x) < 0.0 (and abs(x) >= 0.0 when using -ffast-math).
+
+2002-07-20 Michae Matz <matz@suse.de>
+
+ * ra-build.c: (remember_web_was_spilled): Use GENERAL_REGS.
+
+2002-07-20 Neil Booth <neil@daikokuya.co.uk>
+
+ * cppexp.c (struct op): Add token pointer.
+ (check_promotion, CHECK_PROMOTION): New.
+ (optab): Update.
+ (_cpp_parse_expr): Update, use token pointer of struct op.
+ (reduce): Warn about change of sign owing to promotion.
+ * cppinit.c (cpp_handle_option): New warning if -Wall.
+ * cpplib.h (struct cpp_options): New member.
+
+2002-07-19 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.md: Remove ppc630 fpcompare from single
+ fpu list. Separate Power4 compare and delayed_compare. Correct
+ Power4 fpcompare.
+ (fix_truncdfsi2_internal): Restore FPR preference.
+ * config/rs6000/t-aix43 (MULTILIB_MATCHES): Add mcpu?power3,
+ mcpu?power4, mcpu?604e. Remove mpower, mpower2, mpowerpc.
+
+2002-07-19 Momchil Velikov <velco@fadata.bg>
+
+ * reload1.c (reload_as_needed): Duplicate oldpat.
+
+2002-07-20 Alan Modra <amodra@bigpond.net.au>
+
+ PR optimization/7130
+ * loop.h (struct loop_info): Add "preconditioned".
+ * unroll.c (unroll_loop): Set it.
+ * doloop.c (doloop_modify_runtime): Correct count for unrolled loops.
+
+2002-07-19 Zack Weinberg <zack@codesourcery.com>
+
+ * rtl.def (CODE_LABEL): Remove slot 8.
+ * rtl.h (struct rtx_def): Document new uses of jump and call fields.
+ (LABEL_ALTERNATE_NAME): Delete.
+ (LABEL_KIND, SET_LABEL_KIND, LABEL_ALT_ENTRY_P): New.
+ * defaults.h: Remove default for ASM_OUTPUT_ALTERNATE_LABEL_NAME.
+
+ * final.c (output_alternate_entry_point): New.
+ (final_scan_insn): Use it instead of
+ ASM_OUTPUT_ALTERNATE_LABEL_NAME. Do not consider possibility
+ of a case label being an alternate entry point.
+
+ * cfgbuild.c (make_edges, find_bb_boundaries): Use LABEL_ALT_ENTRY_P.
+ * emit-rtl.c (gen_label_rtx): Adjust call to gen_rtx_CODE_LABEL.
+ Do not clear LABEL_NUSES (unnecessary) or LABEL_ALTERNATE_NAME
+ (field deleted).
+ * print-rtl.c, ra-debug.c: Update code to output CODE_LABELs.
+
+ * doc/rtl.texi: Document LABEL_KIND, SET_LABEL_KIND, and
+ LABEL_ALT_ENTRY_P; not LABEL_ALTERNATE_NAME.
+ * doc/tm.texi: Delete documentation of
+ ASM_OUTPUT_ALTERNATE_LABEL_NAME.
+
+2002-07-19 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * config/mips/iris5gas.h (DWARF2_DEBUGGING_INFO): Define.
+ (PREFERRED_DEBUGGING_TYPE): Use DWARF2_DEBUG.
+ (LINK_SPEC): Define.
+ (STARTFILE_SPEC): Define.
+ (ENDFILE_SPEC): Define.
+
+ * config/mips/iris6-o32.h (LINK_SPEC): Move ...
+ * config/mips/iris6-o32-as.h (LINK_SPEC): ... here.
+
+ * config/mips/iris6-o32-gas.h: New file.
+ * config.gcc (mips-sgi-irix6*o32): Use it.
+
+ * config/mips/t-iris5-gas: New file.
+ * config.gcc (mips-sgi-irix6*o32, mips-sgi-irix5*): Use it.
+
+2002-07-19 Neil Booth <neil@daikokuya.co.uk>
+
+ * cppexp.c (ALWAYS_EVAL): Remove.
+ (optab, reduce): Always evaluate.
+ (num_unary_op, num_binary_op, num_div_op): Issue diagnostics
+ only if not skipping evaluation.
+
+2002-07-19 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (debug_hard_reg_set): Remove.
+
+2002-07-19 Chris Demetriou <cgd@broadcom.com>
+
+ * gcc.c (cpp_options): Include "%1" (cc1_spec).
+
+2002-07-19 Richard Henderson <rth@redhat.com>
+
+ * loop.c (loop_givs_rescan): Delete the REG_EQUAL note, not the insn.
+
+2002-07-19 Alan Modra <amodra@bigpond.net.au>
+
+ * prefix.c (update_path): Don't zap single `.' path components
+ unless followed by another `.' and fix typo last patch.
+
+2002-07-18 Neil Booth <neil@daikokuya.co.uk>
+
+ * cppexp.c (cpp_num_mul): Remove unused parameter.
+ (UNARY, BINARY, OTHER, binary_handler): Remove.
+ (ALWAYS_EVAL): New.
+ (optab): Update.
+ (reduce): Refactor to a large switch, don't use a function
+ pointer.
+
+2002-07-18 Bo Thorsen <bo@berlioz.suse.de>
+
+ * config/i386/linux64.h (STARTFILE_PREFIX_SPEC): Define this always.
+
+2002-07-18 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh-protos.h (sh_expand_unop_v2sf): Move inside #ifdef RTX_CODE guard.
+ (sh_expand_binop_v2sf): Likewise.
+ * sh.c (machine_dependent_reorg): Add move for UNSPEC_MOVA.
+ (int_gpr_dest, trunc_hi_operand): New functions.
+ * sh.h (PREDICATE_CODES): Add any_register_operand, int_gpr_dest and
+ trunc_hi_operand.
+ (SPECIAL_MODE_PREDICATES, any_register_operand): Define.
+ * sh.md (cmpeqdi_t+1): Remove comments that genrecog warns about.
+ (adddi3_compact+1, subdi3_compact+1, ashlsi3_n+1, ashlhi3+1): Likewise.
+ (ashrsi2_16+1, ashrsi2_31+1, lshrsi3_n+1, ashrdi3+[12]): Likewise.
+ (and_shl_scratch+[12], zero_extendhidi2+1): Likewise.
+ (zero_extendhisi2_media+1, extendhidi2+1, extendqidi2+1): Likewise.
+ (extendhisi2_media+1, extendqisi2_media+1): Likewise.
+ (movsi_media_nofpu+[12], movhi_media+1, movdi_media_nofpu+1): Likewise.
+ (movdi_const_16bit+[12], movdf_i4+[123], reload_outdf+[2-5]): Likewise.
+ (movsf_ie+1): Likewise.
+ (loaddi_trunc): Use int_gpr_dest predicate.
+ (use_sfunc_addr, indirect_jump_scratch, sibcall_compact): Add mode(s).
+ (mova, mova_const, GOTaddr2picreg, ptrel, casesi_worker_0): Likewise.
+ (casesi_worker_0+[12], casesi_worker): Likewise.
+ (shcompact_preserve_incoming_args): Likewise.
+ (mov_nop): Use any_register_operand predicate.
+ (mperm_w0): Use trunc_hi_operand predicate.
+
+2002-07-18 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa-linux.h (DWARF2_UNWIND_INFO): Delete define.
+ * pa.h (EH_RETURN_DATA_REGNO): Revise TARGET_64BIT and correct
+ numbering.
+
+2002-07-18 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.c (output_deferred_plabels): Remove unused millicode enum mulU.
+
+2002-07-18 Richard Henderson <rth@redhat.com>
+
+ PR optimization/7147
+ * ifcvt.c (noce_get_condition): Make certain that the condition
+ is valid at JUMP.
+
+2002-07-18 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.c (barrier_align, push): Shut up compiler warnings.
+ (initial_elimination_offset,sh_media_init_builtins): Likewise.
+ (reg_no_subreg_operand): Delete.
+
+2002-07-17 Bo Thorsen <bo@suse.de>
+
+ * config/i386/linux64.h (LINK_SPEC): Remove bogus -Y option.
+ (STARTFILE_PREFIX_SPEC): Define for NATIVE_CROSS compilations.
+ (STARTFILE_SPEC): Remove hardcoded library paths.
+ (ENDFILE_SPEC): Likewise.
+
+2002-07-18 Jan Hubicka <jh@suse.cz>
+
+ * gcse.c (hoist_expr_reaches_here_p): Stop once expr_bb is reached.
+
+ * gcse.c (try_replace_reg): Do not return false positives.
+
+2002-07-18 Alan Modra <amodra@bigpond.net.au>
+
+ * prefix.c: (update_path): Strip ".." components when prior dir
+ doesn't exist. Pass correct var to UPDATE_PATH_HOST_CANONICALIZE.
+
+ * config/rs6000/sysv4.h (ASM_OUTPUT_REG_PUSH): Remove 64-bit support.
(ASM_OUTPUT_REG_POP): Likewise.
- (ASM_OUTPUT_ADDR_VEC_ELT): Add parenthesis.
- (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
- * config/i386/i386.c: Update copyright.
- (CHECK_STACK_LIMIT): Add parenthesis.
- (AT_BP): Uppercase macro parameter.
- (x86_64_int_parameter_registers): Constify.
- (x86_64_int_return_registers): Likewise.
- (ix86_compare_op0): Use rtx.
- (construct_container): Constify INTREG parameter.
- (function_arg): Use rtx.
+2002-07-18 Alan Modra <amodra@bigpond.net.au>
- * diagnostic.h: Update copyright date.
- (output_buffer_state): Add parenthesis.
- (output_buffer_format_args): Likewise.
+ * config/rs6000/rs6000.c (first_reg_to_save): Remove bogus
+ adjustments to first_reg for profiling case.
+ (output_function_profiler): Correct lr save slot for ABI_AIX_NODESC.
+ Disable profiling for 64 bit code on both ABI_V4 and ABI_AIX_NODESC.
+ Save static chain reg to sp + 12 on ABI_AIX_NODESC.
+ * config/rs6000/sysv4.h (ASM_OUTPUT_REG_PUSH): Define.
+ (ASM_OUTPUT_REG_POP): Define.
+ * config/rs6000/linux64.h (ASM_OUTPUT_REG_PUSH): Undef.
+ (ASM_OUTPUT_REG_POP): Undef.
- * combine.c (combine_instructions): Replace XEXP (links, 0)
- with link.
+2002-07-17 Neil Booth <neil@daikokuya.co.uk>
-2002-01-06 H.J. Lu <hjl@gnu.org>
+ * cpplib.c (do_sccs): Handle #sccs on all systems.
+ * system.h (SCCS_DIRECTIVE): Poison.
+ * config/darwin.h, config/freebsd.h, config/netbsd.h,
+ config/ptx4.h, config/svr3.h, config/svr4.h, config/alpha/elf.h,
+ config/arm/linux-elf.h, config/c4x/c4x.h, config/d30v/d30v.h,
+ config/i370/i370.h, config/i386/gas.h, config/i386/sco5.h,
+ config/i960/i960.h, config/m68hc11/m68hc11.h, config/m68k/3b1.h,
+ config/m68k/3b1g.h, config/m68k/crds.h, config/m68k/mot3300.h,
+ config/m68k/pbb.h, config/m88k/m88k.h, config/mips/mips.h,
+ config/sparc/pbd.h, config/stormy16/stormy16.h, config/vax/vaxv.h:
+ Remove all references to SCCS_DIRECTIVE.
+ * doc/cpp.texi, doc/tm.texi: Update.
- * cfgcleanup.c (thread_jump): Fix 2 typos.
+2002-07-17 J"orn Rennecke <joern.rennecke@superh.com>
-2002-01-06 Aldy Hernandez <aldyh@redhat.com>
+ * regrename.c (maybe_mode_change): New function.
+ (find_oldest_value_reg, copyprop_hardreg_forward_1): Use it.
- * config.gcc: Add support for --enable-altivec.
+2002-07-17 Rodney Brown <rbrown64@csc.com.au>
-2002-01-06 Craig Rodrigues <rodrigc@gcc.gnu.org>
+ * config/i386/i386.c (ix86_expand_int_movcc): In the general case
+ suppress addition when either ct or cf are zero.
- * emit-rtl.c (gen_highpart): Add check for NULL_RTX.
+2002-07-17 Eric Botcazou <ebotcazou@multimania.com>
+ Glen Nakamura <glen@imodulo.com>
-2002-01-06 Jakub Jelinek <jakub@redhat.com>
+ PR optimization/6713
+ * loop.c (loop_givs_rescan): Explicitly delete the insn that
+ sets a non-replaceable giv after issuing the new one.
- * objc/objc-act.c (handle_impent): Use assemble_variable to emit
- __objc_class_name_*.
+2002-07-17 Neil Booth <neil@daikokuya.co.uk>
-2002-01-06 Craig Rodrigues <rodrigc@gcc.gnu.org>
+ * cppexp.c (cpp_interpret_integer, append_digit, parse_defined,
+ eval_token): Clarify and correct use of "bool" variables.
+ * cpplib.h (struct cpp_options): Similarly.
+ * cppmacro.c (parse_params, _cpp_save_parameter): Ditto.
+ * cpptrad.c (recursive_macro): Similarly.
- * doc/install.texi (sparcv9-*-solaris2*): Add documentation.
+2002-07-17 J"orn Rennecke <joern.rennecke@superh.com>
-2002-01-06 Richard Henderson <rth@redhat.com>
+ * config/sh/lib1funcs.asm (udivsi3_i4): Implement SHcompact version in
+ SHmedia code.
- * reorg.c (emit_delay_sequence): Remove death notes, not merely
- nop them out. Increment label reference count for REG_LABEL.
- (fill_slots_from_thread): Frob label reference count around
- delete_related_insns.
+ * sh.md (cmpgtudi_media): Remove spurious @.
+
+ * config/sh/lib1funcs.asm (FMOVD_WORKS): Don't define for little endian.
+ * sh.h (OVERRIDE_OPTIONS): Don't set FMOVD_BIT for little endian.
+
+ * config/sh/lib1funcs.asm (init_trampoline): New entry point.
+ * sh-protos.h (sh_initialize_trampoline): Declare.
+ * sh.c (sh_initialize_trampoline): New function.
+ * sh.h (TRAMPOLINE_SIZE): Only 24 for TARGET_SHMEDIA32.
+ (TRAMPOLINE_ALIGNMENT): Need cache-line alignment for TARGET_SHMEDIA.
+ (INITIALIZE_TRAMPOLINE): Call sh_initialize_trampoline.
+ (TRAMPOLINE_ADJUST_ADDRESS): Not needed for SHcompact.
+ * sh.md (initialize_trampoline, double_shori): New patterns.
+ (initialize_trampoline_compact): Likewise.
+ (shmedia32_initialize_trampoline_big): Remove.
+ (shmedia32_initialize_trampoline_little): Likewise.
+
+ * sh-protos.h (binary_float_operator): Remove declaration.
+ (sh_expand_unop_v2sf, sh_expand_binop_v2sf): Declare.
+ * sh.c (print_operand, case 'N'): Check against CONST0_RTX.
+ (unary_float_operator, sh_expand_unop_v2sf): New functions.
+ (sh_expand_binop_v2sf): Likewise.
+ (zero_vec_operand): Delete.
+ (SH_BLTIN_UDI): New builtin shared signature define. Renumbered
+ all non-shared ones.
+ (bdesc): Change all the mextr builtins to use SH_BLTIN_UDI.
+ Enable nsb and byterev.
+ * sh.h (CONDITIONAL_REGISTER_USAGE): Initialize DF_HI_REGS.
+ (HARD_REGNO_MODE_OK): Allow TImode in fp regs. Allow V2SFmode
+ in general regs.
+ (enum reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS): Add DF_HI_REGS.
+ (SECONDARY_OUTPUT_RELOAD_CLASS): Likewise. Remove clause for
+ immediate operands.
+ (SECONDARY_INPUT_RELOAD_CLASS): Add clause for immediate operands.
+ Add DF_HI_REGS.
+ (CLASS_CANNOT_CHANGE_MODE, CLASS_CANNOT_CHANGE_MODE_P): Allow
+ lowpart fp regs - only for big endian for now.
+ (LEGITIMATE_CONSTANT_P): Don't allow nonzero float vectors
+ when FPU is in use.
+ (EXTRA_CONTRAINT_U): Check against CONST0_RTX.
+ (LOAD_EXTEND_OP): NIL for SImode.
+ (REGISTER_MOVE_COST): Add DF_HI_REGS. Const for moves between
+ general and fp registers is 4.
+ PREDICATE_CODES: Amend binary_float_operator entry.
+ Remove zero_vec_operand. Add unary_float_operator.
+ * sh.md (udivsi3_i4_media): Use truncate instead of paradoxical
+ subreg SET_DEST.
+ (truncdisi2, truncdihi2, movv2sf): Allow memory destinations.
+ (truncdiqi2): Do sign extension.
+ (movsi_media, movdi_media): Allow to use r63 to an fp register.
+ (movdf_media, movsf_media): Likewise.
+ (movv2sf_i, movv2sf_i+1): Don't use f{ld,st}.p or SUBREGS.
+ Collapse to one define_insn_and_split. Allow immediate sources.
+ (addv2sf3, subv2sf3, mulv2sf3, divv2sf3): New patterns.
+ (movv4sf_i): Allow immediate sources. Use simplify_gen_subreg.
+ (movv4sf): Allow immediate sources.
+ (movsf_media_nofpu+1): Don't split moves to FP registers.
+ (unary_sf_op, binary_sf_op, mshflo_w_x, concat_v2sf): New patterns.
+ (movv8qi_i+3): Check against CONST0_RTX.
+ (mextr1, mextr2. mextr3. mextr4, mextr5, mextr6, mextr7): Use DImode
+ for input and output operands. Fix argument 3 to gen_mextr_rl.
+ (mmul23_wl, mmul01_wl, mmulsum_wq_i): s/const_vector/parallel/
+ (msad_ubq_i, mshf4_b, mshf0_b, mshf4_l, mshf0_l, mshf4_w): Likewise.
+ (mshf0_w, fipr, ftrv): Likewise.
+ (mshfhi_l_di): Now insn_and_split. Can handle FP regs.
+
+2002-07-17 Jeroen Dobbelaere <jeroen.dobbelaere@acunia.com>
+
+ * arm.h (ARM_NUM_INTS, ARM_NUM_REGS, ARM_NUM_REGS2): Renamed from
+ NUM_INTS, NUM_REGS and ARM_NUM_REGS2 respectively. All uses changed.
+ * arm.c: Similarly.
+
+2002-07-17 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips-protos.h (mips_sign_extend): Declare.
+ * config/mips/mips.h (MASK_DEBUG_H, TARGET_DEBUG_H_MODE): Remove.
+ (TARGET_SWITCHES): Remove debugh.
+ (ISA_HAS_TRUNC_W): New macro.
+ (CLASS_CANNOT_CHANGE_MODE): Include FP_REGS if TARGET_FLOAT64.
+ (PREDICATE_CODES): Remove se_nonimmediate_operand.
+ * config/mips/mips.c (movdi_operand): Allow sign-extensions of
+ any SImode move_operand.
+ (se_nonimmediate_operand): Remove.
+ (mips_sign_extend): New.
+ (mips_move_2words): Use it for sign-extended source operands.
+ (override_options): Allow integers to be put into single FPRs.
+ (mips_secondary_reload_class): Handle integers in float registers.
+ * config/mips/mips.md (extendsidi2): Turn into a define_expand.
+ (fix_truncsfsi2, fix_truncdfsi2): Likewise.
+ (fix_truncdfsi2_insn, fix_truncdfsi2_macro): New.
+ (fix_truncsfsi2_insn, fix_truncsfsi2_macro): New.
+ (fix_truncdfdi2): Provide only a single alternative, in which the
+ integer is in a float register. Depend on TARGET_FLOAT64 rather
+ than TARGET_64BIT.
+ (fix_truncsfdi2, floatdidf2, floatdisf2): Likewise.
+ (floatsidf2, floatsisf2): Likewise, but no TARGET_FLOAT64 dependency.
+ (movdi_internal2): Don't allow the source operand to be sign-extended.
+ Add alternatives for float registers.
+ (*movdi_internal2_extend): New. Version of movdi_internal2 that
+ allows sign-extension.
+ (*movdi_internal2_mips16): Name the existing mips16 movdi pattern.
+ (movsi_internal2): Rename to movsi_internal. Add alternatives for
+ float registers. Remove TARGET_DEBUG_H_MODE test.
+ (movhi_internal1): Rename to movhi_internal. Don't check
+ TARGET_DEBUG_H_MODE. Fix transposed *d and *f source constraints.
+ (movqi_internal1): Rename to movqi_internal and remove
+ TARGET_DEBUG_H_MODE dependency.
+ (movsi_internal1, movhi_internal2, movqi_internal2): Remove.
+
+2002-07-16 Jim Wilson <wilson@redhat.com>
+
+ * toplev.c (lang_dependent_init): Create function context for
+ init_expr_once.
-2002-01-05 Richard Henderson <rth@redhat.com>
+2002-07-16 Hans-Peter Nilsson <hp@axis.com>
- * cfgcleanup.c (try_forward_edges): Detect infinite loops while
- jump threading.
+ * config/cris/linux.h (CRIS_LINK_SUBTARGET_SPEC): Don't
+ --gc-sections if -r.
+ * config/cris/cris.h: Ditto.
-2002-01-05 Richard Henderson <rth@redhat.com>
+2002-07-16 Rodney Brown <rbrown64@csc.com.au>
- * c-decl.c (c_expand_body): Don't call outlining_inline_function.
- * integrate.c (output_inline_function): Likewise.
- * toplev.c (rest_of_compilation): Do it here instead. Move call
- to remove_unnecessary_notes after emitting abstract instance.
- Force an emitted nested function to have its parent emited as well.
- * dwarf2out.c (loc_descriptor_from_tree): Read mode after checking
- for null.
- (rtl_for_decl_location): Do not look at reload data structures
- before reload has run.
+ * config/i386/i386.c (ix86_expand_int_movcc): In the case where
+ the comparison directly gives a mask suppress addition when cf is
+ zero by complementing the mask.
-2002-01-05 Kazu Hirata <kazu@hxi.com>
+2002-07-16 Nathanael Nerode <neroden@gcc.gnu.org>
- * cse.c: Fix formatting.
- * dwarf2asm.c: Likewise.
- * dwarf2out.c: Likewise.
- * explow.c: Likewise.
- * expmed.c: Likewise.
- * function.c: Likewise.
- * gcov.c: Likewise.
- * gencheck.c: Likewise.
- * genrecog.c: Likewise.
- * ggc-common.c: Likewise.
- * ggc-page.c: Likewise.
- * global.c: Likewise.
+ * Makefile.in: Delete references to enquire.
+ * enquire.c: Move to contrib.
-2002-01-05 Kazu Hirata <kazu@hxi.com>
+2002-07-16 Stan Shebs <shebs@apple.com>
- * combine.c: Fix formatting.
+ * config/darwin.h (ASM_OUTPUT_LABEL): Move to here from
+ config/rs6000/darwin.h.
+ (ASM_OUTPUT_SKIP): Ditto.
+ (TEXT_SECTION_ASM_OP): Ditto.
+ (DATA_SECTION_ASM_OP): Ditto.
+ (ASM_APP_ON): Define.
+ (ASM_APP_OFF): Define.
+ * config/rs6000/darwin.h (ASM_OUTPUT_LABEL, ASM_OUTPUT_SKIP,
+ TEXT_SECTION_ASM_OP, DATA_SECTION_ASM_OP): Remove.
-2002-01-05 Craig Rodrigues <crodrigu@bbn.com>
+ * config/darwin.c (func_name_maybe_scoped): Remove unused decl.
+ (machopic_function_base_name): Declare result to be const.
+ (machopic_non_lazy_ptr_name): Ditto.
+ (machopic_stub_name): Ditto.
+ * config/darwin-protos.h: Ditto for the prototypes.
- PR middle-end/1557
- * config/ia64/ia64.h (RENAME_EXTENDED_BLOCKS): Remove.
+2002-07-17 Jan Hubicka <jh@suse.cz>
-2002-01-05 David Edelsohn <edelsohn@gnu.org>
+ * m68hc11.c (m68hc11_reorg): Do not rebuild CFG.
- * config/rs6000/rs6000.h (TARGET_POWERPC): For IN_LIBGCC2, define
- as 1 for __powerpc64__ as well.
+2002-07-17 Jan Hubicka <jh@suse.cz>
- * config/rs6000/t-aix43 (T_ADAFLAGS): Define.
+ * i386.md (prefetch): Fix for 64bit mode.
+ (prefetch_sse_rex, prefetch_3dnow_rex): New patterns.
- * alias.c (find_base_value, PLUS/MINUS): If we found a base,
- return it.
+2002-07-17 Jan Hubicka <jh@suse.cz>
-2002-01-05 Daniel Berlin <dan@dberlin.org>
+ * i386.h (MACHINE_DEPENDENT_REORG): New macro.
+ * i386.c (x86_machine_dependent_reorg): New function.
+ * i386-protos.h (x86_machine_dependent_reorg): Declare.
- * lcm.c: Revert change, due to performance regression it causes on
- SPEC because it's slightly more conservative (sigh, I hate
- edge-based LCM).
+2002-07-16 Zack Weinberg <zack@codesourcery.com>
-Sat Jan 5 11:52:05 CET 2002 Jan Hubicka <jh@suse.cz>
+ * builtins.c (std_expand_builtin_va_start): Remove unused
+ first argument.
+ (expand_builtin_va_start): Call EXPAND_BUILTIN_VA_START and
+ std_expand_builtin_va_start with just two arguments.
+ * expr.h: Update prototypes.
- * cfgcleanup.c (try_forward_edges): Allow multiple jump threading.
+ * alpha-protos.h, alpha.h, alpha.c, arc-protos.h, arc.h,
+ arc.c, d30v-protos.h, d30v.h, d30v.c, i386-protos.h, i386.h,
+ i386.c, i960-protos.h, i960.h, i960.c, m88k-protos.h, m88k.h,
+ m88k.c, mips-protos.h, mips.h, mips.c, mn10300-protos.h,
+ mn10300.h, mn10300.c, pa-protos.h, pa.h, pa.c,
+ rs6000-protos.h, rs6000.h, rs6000.c, s390-protos.h, s390.h,
+ s390.c, sh-protos.h, sh.h, sh.c, sparc-protos.h, sparc.h,
+ sparc.c, stormy16-protos.h, stormy16.h, stormy16.c,
+ xtensa-protos.h, xtensa.h, xtensa.c: Remove unused first
+ argument from all implementations of EXPAND_BUILTIN_VA_START
+ and all uses of std_expand_builtin_va_start.
-2002-01-05 Neil Booth <neil@daikokuya.demon.co.uk>
+2002-07-16 J"orn Rennecke <joern.rennecke@superh.com>
- * doc/cppinternals.texi: Update.
+ * regrename.c (copy_value): Don't record high part copies.
-2002-01-05 Hans-Peter Nilsson <hp@bitrange.com>
+2002-07-16 Steve Ellcey <sje@cup.hp.com>
- * doc/invoke.texi (Option Summary) <MMIX Options>: Document
- -mbranch-predict, -mreg-stack-fill-bug-workaround and their
- negatives.
- (MMIX Options): Ditto. Fix item/itemx typo for -mno-zero-extend.
- * config/mmix/mmix.c (mmix_target_asm_function_prologue): Rework
- kludge for pre-october-14th mmix versions to handle new-found bug
- with PUSHJ/PUSHGO and the register stack.
- * config/mmix/mmix.h (struct machine_function): Rename member
- has_call_value_without_parameters to has_call_without_parameters.
- All referers changed.
- (TARGET_MASK_REG_STACK_FILL_BUG, TARGET_DEFAULT
- TARGET_MASK_BRANCH_PREDICT): New macros.
- (TARGET_SWITCHES): New options -mreg-stack-fill-bug-workaround,
- -mno-reg-stack-fill-bug-workaround.
- * config/mmix/mmix.md ("call"): Set struct machine member
- has_call_without_parameters.
+ * gcc/config/pa/long_double.h (FIXUNS_TRUNCTFDI2_LIBCALL): New define.
+ (fixunstfdi_libfunc): Change to use FIXUNS_TRUNCTFDI2_LIBCALL.
+ * gcc/config/pa/quadlib.c (_U_Qfcnvfxt_quad_to_udbl): New function.
-Sat Jan 5 02:20:22 CET 2002 Jan Hubicka <jh@suse.cz>
+2002-07-16 Ian Dall <ian@sibyl.beware.dropbear.id.au>
- * cfgcleanup.c (thread_jump): Fix handling of reversed branches.
+ * doc/invoke.texi (NS32K Options): Document -mieee-compare option
-Sat Jan 5 01:35:29 CET 2002 Jan Hubicka <jh@suse.cz>
+ * config/ns32k/ns32k.md (addsi3, *frame_addr, *stack_addr): merge
+ into addsi3 using register class "x" and "y".
- * cfgcleanup.c: Include tm_p.h
- (mark_effect): Fix handling of hard register; fix handling of SET
+ * config/ns32k/ns32k.md (*madddf, *maddsf, *msubdf, *msubsf):
+ "earlyclobber" constraint modifier for some alternative.
-2002-01-04 Kazu Hirata <kazu@hxi.com>
+ * config/ns32k/ns32k.md (tstdf, tstsf, cmpdf, cmpsf, blt, ble)
+ (*ble, *blt): Flag to indicate bCOND and sCOND should check for
+ unordered.
+ config/ns32k/ns32k.h (CC_UNORD): define corresponding mask.
- * config/h8300/h8300.md (anonymous patterns): Check that
- operands are registers before using REGNO on them.
+ * config/ns32k/ns32k.h (TARGET_IEEE_COMPARE, MASK_IEEE_COMPARE)
+ (TARGET_SWITCHES): Add -mieee-compare option.
+ (OVERRIDE_OPTIONS): 32332 is a subset of
+ 32532. Don't use IEEE_COMPARE -funsafe-math-optimizations.
+ (TARGET_SWITCHES): Fix description of bit-field option.
+ * config/ns32k/netbsd.h (TARGET_DEFAULT): Add
+ -mieee-compare option. Remove 32332 flag.
-2002-01-03 Roland McGrath <roland@frob.com>
+2002-07-16 Steve Ellcey <sje@cup.hp.com>
- * doc/invoke.texi (RS/6000 and PowerPC Options): Add -mcall-gnu.
+ * explow.c (convert_memory_address): Remove special handling
+ when POINTERS_EXTEND_UNSIGNED < 0.
+ * config/ia64.md (movsi_symbolic): New instruction for ILP32 mode.
+ (movedi_symbolic): Fix typo.
+ (load_fptr): Remove mode restriction so it works for SI and DI.
+ (load_fptr_internal1): Ditto.
+ (load_gprel): Ditto.
+ (load_symptr_internal1): Ditto.
+ (call_pic): Ditto.
+ * config/ia64.c (call_operand): Modify mode check.
+ (ia64_expand_load_address): Handle DI and SI addresses and symbols.
+ (ia64_expand_move): Ditto.
+ (ia64_assemble_integer): Handle SImode function pointers.
+ (ia64_expand_fetch_and_op): Handle SImode mem addresses.
+ (ia64_expand_op_and_fetch): Ditto.
+ (ia64_expand_compare_and_swap): Ditto.
+ (ia64_expand_lock_test_and_set): Ditto.
+ (ia64_expand_lock_release): Ditto.
-2002-01-04 Jakub Jelinek <jakub@redhat.com>
+2002-07-16 Jeroen Dobbelaere <jeroen.dobbelaere@acunia.com>
- * tree.h (expand_expr_stmt_value): Add maybe_last argument.
- * c-common.h (genrtl_expr_stmt_value): Likewise.
- * stmt.c (expand_expr_stmt): Pass 1 as maybe_last.
- (expand_expr_stmt_value): Add maybe_last argument.
- Don't warn about statement with no effect if it is the last statement
- in expression statement.
- * c-semantics.c (genrtl_expr_stmt): Pass 1 as maybe_last.
- (genrtl_expr_stmt_value): Add maybe_last argument, pass it down to
- expand_expr_stmt_value.
- (expand_stmt) [EXPR_STMT]: Pass 1 as maybe_last to
- genrtl_expr_stmt_value if t is the last EXPR_STMT in its scope.
- * expr.c (expand_expr) [LABELED_BLOCK_EXPR, LOOP_EXPR]: Pass 1
- as maybe_last to expand_expr_stmt_value.
+ * arm.c (emit_sfm): Don't set RTX_FRAME_RELATED_P on DWARF.
-Fri Jan 4 11:45:05 2002 Jeffrey A Law (law@redhat.com)
+2002-07-16 Jeroen Dobbelaere <jeroen.dobbelaere@acunia.com>
+ Richard Earnshaw <rearnsha@arm.com>
- * c-common.c (c_expand_start_cond): Expect the IF_STMT node to
- be passed in, do not build it.
- (c_begin_if_stmt): New function.
- (c_begin_while_stmt, c_finish_while_stmt_cond): Likewise.
- * c-common.h (c_expand_start_cond): Update prototype.
- (c_begin_if_stmt): Prototype new function.
- (c_begin_while_stmt, c_finish_while_stmt_cond): Likewise.
- * c-parse.in (if_prefix): Use c_begin_if_stmt,
- c_begin_while_stmt and c_finish_while_stmt_cond.
+ * arm.h (LEGITIMATE_PIC_OPERAND_P): Only test
+ CONSTANT_POOL_ADDRESS_P if a SYMBOL_REF. Simplify logic.
-2002-01-04 William Cohen <wcohen@redhat.com>
+2002-07-16 Richard Earnshaw <rearnsha@arm.com>
- * config/pa/elf.h (ASM_FILE_START): Reverted to profile_flag.
- * config/pa/pa-linux.h (ASM_FILE_START): Likewise.
- * config/pa/pa64-hpux.h (ASM_FILE_START): Likewise.
- * config/pa/som.h (ASM_FILE_START): Likewise.
+ * arm.md (stack_tie): New insn. Use an idiom that the alias code
+ understands to be a memory clobber.
+ * arm.c (arm_expand_prologue): Use it.
-2002-01-04 Daniel Berlin <dan@cgsoftware.com>
+2002-07-16 Daniel Berlin <dberlin@dberlin.org>
- * lcm.c: Include df.h.
- Add available_transfer_function prototype.
- (compute_available): Rework to use iterative dataflow framework.
- (struct bb_info): s/bb_info/lcm_bb_info/g to avoid conflict
- with bb_info in df.h
- (available_transfer_function): New function.
-
- * Makefile.in (lcm.o): add df.h to dependencies.
-
-2002-01-04 Richard Henderson <rth@redhat.com>
-
- * config/alpha/alpha.c (some_operand): Accept HIGH.
- (input_operand): Likewise; accept simple references to globals.
- (alpha_const_ok_for_letter_p): New, outlined from alpha.h.
- (alpha_const_double_ok_for_letter_p): Likewise.
- (alpha_extra_constraint): Likewise.
- (alpha_preferred_reload_class): Likewise. Do not force
- symbolic constants to memory.
- (alpha_legitimate_address_p): Accept simple references
- to small_symbolic_operand.
- (alpha_legitimize_address): New arg scratch. Be prepared to be
- called when no_new_pseudos. Emit simple symbolic references.
- Split integers into low, high, and rest.
- (alpha_expand_mov): Use alpha_legitimize_address.
- (some_small_symbolic_mem_operand): New.
- (split_small_symbolic_mem_operand): New.
- * config/alpha/alpha-protos.h: Update.
- * config/alpha/alpha.h (CONST_OK_FOR_LETTER_P): Out-line.
- (CONST_DOUBLE_OK_FOR_LETTER_P): Likewise.
- (EXTRA_CONSTRAINT): Likewise.
- (PREFERRED_RELOAD_CLASS): Likewise.
- (LEGITIMIZE_ADDRESS): Update for alpha_legitimize_address change.
- (PREDICATE_CODES): Update.
- * config/alpha/alpha.md: New post-reload splitters to convert
- simplfied symbolic operands to the form that references $29.
- (divide expanders): Use emit_move_insn, not gen_movdi_er_high_g.
- (movdi_er_nofix, movdi_er_fix): Accept any symbolic operand.
+ * ra-rewrite.c: #include reload.h, insn-config.h
+ * ra-build.c: #include reload.h
+ * Makefile.in: Update ra-rewrite.o, ra-build.o dependencies to
+ depend on reload.h, insn-config.h.
-2002-01-03 Richard Henderson <rth@redhat.com>
+2002-07-16 J"orn Rennecke <joern.rennecke@superh.com>
- * local-alloc.c (function_invariant_p): Update commentary.
+ * expr.c (emit_move_insn_1): Handle arbitrary moves that are
+ the same size as a word.
-2002-01-04 H.J. Lu <hjl@gnu.org>
+ * regrename.c (find_oldest_value_reg): Take WORDS_BIG_ENDIAN /
+ BYTES_BIG_ENDIAN into account.
- * toplev.c (rest_of_compilation): Fix a typo when calling
- cleanup_cfg.
+2002-07-16 Jan Hubicka <jh@suse.cz>
-2002-01-03 Kazu Hirata <kazu@hxi.com>
+ * i386.md (prefetch): Fix for 64bit mode.
+ (prefetch_sse_rex, prefetch_3dnow_rex): New patterns.
- * c-common.c: Fix formatting.
- * diagnostic.c: Likewise.
- * doloop.c: Likewise.
- * dwarf2out.c: Likewise.
+ * i386.md (movss, movsd): Use xorps/xorpd for Athlon.
+
+2002-07-16 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * hard-reg-set.h (TEST_HARD_REG_BIT): Return 1 if the bit is set.
+
+2002-07-15 Zack Weinberg <zack@codesourcery.com>
+
+ * ginclude/varargs.h: Replace with stub which issues #error.
+ * ginclude/stdarg.h: __builtin_stdarg_start is renamed
+ __builtin_va_start.
+
+ * builtins.def (BUILT_IN_VARARGS_START): Delete.
+ (BUILT_IN_VA_START): New.
+ * builtins.c (expand_builtin_va_start): Eliminate first
+ argument and code to implement pre-ISO varargs.
+ (std_expand_builtin_va_start): Ignore first argument; it is
+ always 1.
+ (expand_builtin): Handle BUILT_IN_VA_START and
+ BUILT_IN_STDARG_START identically. Delete
+ BUILT_IN_VARARGS_START case.
+
+ * function.c (assign_parms): Delete hide_last_arg and all
+ its uses.
+ (mark_varargs): Delete function.
+ * function.h (struct function): Delete 'varargs' bit.
+ (current_function_varargs): Delete macro.
+ * tree.h: Don't declare mark_varargs.
+
+ * c-decl.c (c_function_varargs, c_mark_varargs): Delete.
+ (c_expand_body): Don't call mark_varargs.
+ * c-objc-common.c: Handle BUILT_IN_VA_START and
+ BUILT_IN_STDARG_START identically. Delete
+ BUILT_IN_VARARGS_START case.
+ * c-tree.h: Don't declare c_mark_varargs.
+ * c-parse.in: Remove grammar rules for '&...' (which has been
+ commented out since before 2.7.2) and for '...' in K+R
+ argument declarations.
+
+ * builtins.c, function.c, integrate.c, sibcall.c,
+ config/alpha/unicosmk.h, config/arc/arc.c, config/arc/arc.h,
+ config/avr/avr.c, config/cris/cris.c, config/fr30/fr30.c,
+ config/i960/i960.c, config/i960/i960.md, config/m32r/m32r.c,
+ config/m32r/m32r.h, config/m88k/m88k.c, config/m88k/m88k.h,
+ config/mips/mips.c, config/mmix/mmix.c, config/mmix/mmix.h,
+ config/mn10300/mn10300.c, config/pa/som.h, config/s390/s390.c,
+ config/sh/sh.c, config/sh/sh.h, config/sparc/sparc.h,
+ config/stormy16/stormy16.c: Delete all references to
+ current_function_varargs, and code predicated on that flag.
+
+ * config/alpha/alpha.c (alpha_va_start),
+ config/arc/arc.c (arc_va_start),
+ config/i386/i386.c (ix86_va_start),
+ config/mips/mips.c (mips_va_start),
+ config/mn10300/mn10300.c (mn10300_va_start),
+ config/rs6000/rs6000.c (rs6000_va_start),
+ config/s390/s390.c (s390_va_start),
+ config/sh/sh.c (sh_va_start),
+ Ignore first argument; it is always 1.
+
+ * config/c4x/c4x-protos.h, config/c4x/c4x.c: Delete c4x_va_start.
+ * config/ia64/ia64-protos.h, config/ia64/ia64.c: Delete ia64_va_start.
+ * config/m68hc11/m68hc11-protos.h, config/m68hc11/m68hc11.c:
+ Delete m68hc11_va_start.
+ * config/c4x/c4x.h, config/ia64/ia64.h, config/m68hc11/m68hc11.h:
+ No need to define EXPAND_BUILTIN_VA_START.
+
+ * doc/invoke.texi, doc/sourcebuild.texi, doc/tm.texi,
+ doc/trouble.texi: Remove references to GCC-provided <varargs.h>.
-2002-01-03 Kazu Hirata <kazu@hxi.com>
-
- * config/h8300/h8300.c (output_logical_op): Use 'not.w' instead
- of 'neg.w' when xoring with 0x0000ffff or 0xffff0000.
-
-2002-01-03 Neil Booth <neil@daikokuya.demon.co.uk>
-
- * cpperror.c: Update comments and copyright.
- * cppexp.c, cppfiles.c, cpphash.c, cpphash.h, cppinit.c,
- cpplex.c, cpplib.c, cpplib.h, cppmacro.c, cppmain.c: Similarly.
-
-2002-01-03 John David Anglin <dave@hiauly1.hia.nrc.ca>
-
- * collect2.c (main): Use strcmp when testing for "-shared".
-
-2002-01-03 Neil Booth <neil@daikokuya.demon.co.uk>
-
- * cppmacro.c: Don't include intl.h. Update comments.
- (new_number_token): Allocate enough buffer for 64-bit unsigned
- integers; update prototype.
- * cppmain.c: Update comments.
-
-2002-01-03 William Cohen <wcohen@redhat.com>
-
- * function.h (struct function): Add profile.
- (current_function_profile): New.
- doc/extend.texi: Update documentation.
- * final.c (final_start_function): Use current_function_profile
- instead of profile_flag.
- (profile_after_prologue): Likewise.
- * function.c (expand_function_start): Likewise.
- (expand_function_start): Likewise.
- * config/alpha/alpha.c (direct_call_operand):
- (alpha_does_function_need_gp): Likewise.
- (alpha_expand_prologue): Likewise.
- * config/arm/arm.c (arm_expand_prologue): Likewise.
- thumb_expand_prologue: Likewise.
- * config/d30v/d30v.c (d30v_stack_info): Likewise.
- * config/fr30/fr30.c (MUST_SAVE_RETURN_POINTER): Likewise.
- (fr30_expand_prologue): Likewise.
- * config/i386/cygwin.h (SUBTARGET_PROLOGUE): Likewise.
- * config/i386/i386.c (ix86_osf_output_function_prologue): Likewise.
- * config/i386/i386.h (FINALIZE_PIC): Likewise.
- * config/i386/win32.h (SUBTARGET_PROLOGUE): Likewise.
- * config/i960/i960.c (i960_output_function_prologue): Likewise.
- * config/ia64/ia64.c (ia64_compute_frame_size): Likewise.
- * config/m32r/m32r.c (MUST_SAVE_RETURN_ADDR): Likewise.
- (m32r_expand_prologue): Likewise.
- * config/m88k/m88k.c (m88k_layout_frame): Likewise.
- (m88k_expand_prologue): Likewise.
- * config/m88k/m88k.h (ADJUST_INSN_LENGTH): Likewise.
- * config/mips/mips.c (compute_frame_size): Likewise.
- (mips_expand_prologue): Likewise.
- (mips_can_use_return_insn): Likewise.
- * config/pa/elf.h (ASM_FILE_START): Likewise.
- * config/pa/pa-linux.h (ASM_FILE_START): Likewise.
- * config/pa/pa64-hpux.h (ASM_FILE_START): Likewise.
- * config/pa/som.h (ASM_FILE_START): Likewise.
- * config/romp/romp.c (romp_using_r14): Likewise.
- * config/rs6000/rs6000.c (first_reg_to_save): Likewise.
- (rs6000_stack_info): Likewise.
- * config/rs6000/sysv4.h (ASM_DECLARE_FUNCTION_NAME): Likewise.
- * config/rs6000/xcoff.h (ASM_FILE_START): Likewise.
- * config/v850/v850.c (compute_register_save_size): Likewise.
-
-2002-01-03 Jakub Jelinek <jakub@redhat.com>
-
- * simplify-rtx.c (simplify_binary_operation) [DIV]: If
- gen_lowpart_common fails, use gen_lowpart_SUBREG.
-
-2002-01-03 Turly O'Connor <turly@apple.com>
-
- * darwin.c (machopic_output_possible_stub_label): Don't generate
- stub routines for pseudo-stubs which we've just defined.
-
-2002-01-03 Kazu Hirata <kazu@hxi.com>
+2002-07-15 Eric Botcazou <ebotcazou@multimania.com>
- * builtins.c: Fix formatting.
- * c-typeck.c: Likewise.
- * combine.c: Likewise.
- * expr.c: Likewise.
- * loop.c: Likewise.
+ PR optimization/7153
+ * regmove.c (optimize_reg_copy_3): Don't optimize if the register
+ dies in more than one insn.
-2002-01-03 Andreas Schwab <schwab@suse.de>
+2002-07-15 Jason Thorpe <thorpej@wasabisystems.com>
- * cppfiles.c (_cpp_pop_file_buffer): Change return type to bool
- and return true if _cpp_push_next_buffer pushed a new include
- file.
- * cpplib.c (_cpp_pop_buffer): Only call obstack_free if
- _cpp_pop_file_buffer did not push a new file.
- * cpphash.h (_cpp_pop_file_buffer): Update declaration.
-
-2002-01-02 Eric Christopher <echristo@redhat.com>
-
- * final.c (final_scan_insn): Change 0 -> NULL_RTX in
- FIND_REG_INC_NOTE call. Update copyright.
- * loop.c (canonicalize_condition): Ditto.
- * reorg.c (delete_scheduled_jump): Ditto.
-
-2002-01-03 Kazu Hirata <kazu@hxi.com>
-
- * gcse.c: Fix formatting.
-
-2002-01-03 Graham Stott <grahams@redhat.com>
-
- * mkconfig.sh: Output to config.h, hconfig.h and tconfig.h
- forward defs for struct tags rtx_def, union_tree, rtvec_def
- also output corresponding typedefs for rtx, tree, and rtvec.
-
- * system.h: Move forward defs for struct tags rtx_def, union_tree,
- rtvec_def along with corresponding typedefs for rtx, tree, and
- rtvec to config.h, hconfig.h, tconfig.h.
-
-2002-01-03 Graham Stott <grahams@redhat.com>
-
- * tree.h: Update copyright date.
- (IS_EXPR_CODE_CLASS): Add parenthesis.
- (TREE_SET_CODE): Add whitespace.
- (TREE_CHECK): Add parenthesis.
- (TREE_CLASS_CODE): Add parenthesis and wrap long line.
- (CST_OR_CONSTRUCTOR_CHECK):
- (EXPR_CHECK): Add parenthis, whitespace and wrap line.
- (TREE_SYMBOL_REFERENCED): Whitespace.
- (INT_CST_LT): Likewise.
- (INT_CST_LT_UNSIGNED): Likewise.
- (tree_real_cst): Unwrap comment.
- (tree_string): Likewise.
- (tree_complex): Likewise.
- (IDENTIFIER_POINTER): correct cast.
- (SAVE_EXPR_CONTEXT): Whitespace.
- (EXPR_WFL_FILENAME_NODE): Likewise.
- (EXPR_WFL_FILENAME): Remove parenthesis.
- (DECL_ORIGIN): Add parenthesis.
- (DECL_FROM_INLINE): Use NULL_TREE.
- (build_int_2): Whitespace.
- (build_type_variant): Add parenthesis.
-
- * gcc/jcf-parse.c: Update copyright date.
- (yyparse): Constify resource_filename.
-
-2002-01-03 Graham Stott <grahams@redhat.com>
-
- * rtl.h: Update copyright date.
- (RTL_CHECK1): Wrap long line.
- (RTL_CHECK2): Likewise.
- (RTL_CHECKC1): Wrap long line and whitespace.
- (RTL_CHECKC2): Likewise.
- (XWINT): Whitespace.
- (XINT): Likewise.
- (XSTR): Likewise.
- (XEXP): Likewise.
- (XVEC): Likewise.
- (XMODE): Likewise.
- (XBITMAP): Likewise.
- (XTREE): Likewise.
- (XBBDEF): Likewise.
- (XTMPL): Likewise.
- (X0WINT): Likewise.
- (X0INT):Likewise.
- (X0UINT): Likewise.
- (X0STR): Likewise.
- (X0EXP): Likewise.
- (X0VEC): Likewise.
- (X0MODE): Likewise.
- (X0BITMAP): Likewise.
- (X0TREE): Likewise.
- (X0BBDEF): Likewise.
- (X0ADVFLAGS): Likewise.
- (X0CSELIB): Likewise.
- (X0MEMATTR): Likewise.
- (XCWINT): Likewise.
- (XCINT): Likewise.
- (XCUINT): Likewise.
- (XCSTR): Likewise.
- (XCEXP): Likewise.
- (XCVEC): Likewise.
- (XCMODE): Likewise.
- (XCBITMAP): Likewise.
- (XCTREE): Likewise.
- (XCBBDEF): Likewise.
- (XCADVFLAGS): Likewise.
- (XCCSELIB): Likewise.
- (XC2EXP): Likewise.
- (INSN_UID): Likewise.
- (PREV_INSN): Likewise.
- (PATTERN): Likewise.
- (INSN_CODE): Likewise.
- (PUT_REG_NOTE_KIND): Likewise.
- (CODE_LABEL_NUMBER): Likewise.
- (NOTE_SOURCE_FILE): Likewise.
- (NOTE_BLOCK): Likewise.
- (NOTE_EH_HANDLER): Likewise.
- (NOTE_RANGE_INFO): Likewise.
- (NOTE_LIVE_INFO): Likewise.
- (NOTE_BASIC_BLOCK): Likewise.
- (NOTE_EXPECTED_VALUE): Likewise.
- (NOTE_LINE_NUMBER): Likewise.
- (LABEL_NAME): Likewise.
- (LABEL_NUSES): Likewise.
- (LABEL_ALTERNATE_NAME): Likewise.
- (ADDRESSOF_DECL): Likewise.
- (JUMP_LABEL): Likewise.
- (LABEL_NEXTREF): Likewise.
- (REGNO): Likewise.
- (ORIGINAL_REGNO: Likewise.
- (HARD_REGISTER_NUM_P): Add parenthesis.
- (SUBREG_REG): Whitespace.
- (SUBREG_BYTE): Likewise.
- (ASM_OPERANDS_TEMPLATE): Remove parenthesis.
- (ASM_OPERANDS_OUTPUT_CONSTRAINT): Likewise.
- (ASM_OPERANDS_OUTPUT_IDX): Likewise.
- (ASM_OPERANDS_INPUT_VEC): Likewise.
- (ASM_OPERANDS_INPUT_CONSTRAINT_VEC): Likewise.
- (ASM_OPERANDS_INPUT): Likewise.
- (ASM_OPERANDS_INPUT_LENGTH): Likewise.
- (ASM_OPERANDS_INPUT_CONSTRAINT_EXP): Likewise.
- (ASM_OPERANDS_INPUT_CONSTRAINT): Likewise.
- (ASM_OPERANDS_INPUT_MODE): Likewise.
- (ASM_OPERANDS_SOURCE_FILE): Likewise.
- (ASM_OPERANDS_SOURCE_LINE): Likewise.
- (MEM_SET_IN_STRUCT_P): Minor reformat.
- (TRAP_CONDITION): Whitespace.
- (TRAP_CODE): Likewise.
- (COND_EXEC_TEST): Likewise.
- (COND_EXEC_CODE): Likewise.
- (FIND_REG_INC_NOTE): Uppercase macro args and add parenthesis.
- (PHI_NODE_P): Add parenthesis.
- (plus_constant): Whitespace and add parenthesis.
-
-2002-01-03 Kazu Hirata <kazu@hxi.com>
-
- * config/avr/avr.c: Fix comment typos.
- * config/c4x/c4x.md: Likewise.
- * config/dsp16xx/dsp16xx.h: Likewise.
- * config/dsp16xx/dsp16xx.md: Likewise.
- * config/i386/i386.md: Likewise.
- * config/ia64/ia64.c: Likewise.
- * config/m32r/m32r.h: Likewise.
- * config/m68hc11/m68hc11.md: Likewise.
- * config/mmix/mmix.c: Likewise.
- * config/mn10200/mn10200.c: Likewise.
- * config/romp/romp.c: Likewise.
- * config/sh/sh.c: Likewise.
- * config/stormy16/stormy16.c: Likewise.
- * config/stormy16/stormy16.h: Likewise.
- * config/stormy16/stormy16.md: Likewise.
+ * config/sparc/netbsd-elf.h (TRANSFER_FROM_TRAMPOLINE): Remove.
-2002-01-03 Graham Stott <grahams@redhat.com>
+2002-07-15 Michael Matz <matz@suse.de>,
+ Daniel Berlin <dberlin@dberlin.org>,
+ Denis Chertykov <denisc@overta.ru>
- * loop.h: Update copyright date.
- (LOOP_MOVABLES): Fix typo.
- (LOOP_REGS): Likewise.
- (LOOP_IVS): Likewise.
+ Add a new register allocator.
-2002-01-03 Graham Stott <grahams@redhat.com>
+ * ra.c: New file.
+ * ra.h: New file.
+ * ra-build.c: New file.
+ * ra-colorize.c: New file.
+ * ra-debug.c: New file.
+ * ra-rewrite.c: New file.
- * cppinit.c: Update copyright date.
- Don't include output.h
- * Makefile.in: Update copyright date.
- Update dependency.
+ * Makefile.in (ra.o, ra-build.o, ra-colorize.o, ra-debug.o,
+ (ra-rewrite.o): New .o files for libbackend.a.
+ (GTFILES): Add basic-block.h.
-2002-01-02 Craig Rodrigues <rodrigc@gcc.gnu.org>
+ * toplev.c (flag_new_regalloc): New.
+ (f_options): New option "new-ra".
+ (rest_of_compilation): Call initialize_uninitialized_subregs()
+ only for the old allocator. If flag_new_regalloc is set, call
+ new allocator, instead of local_alloc(), global_alloc() and
+ friends.
- PR c/5226
- * invoke.texi (-mthreads): Remove from documented RS/6000 options.
- (-pthread) Add to RS/6000 options.
+ * doc/invoke.texi: Document -fnew-ra.
+ * basic-block.h (FOR_ALL_BB): New.
+ * config/rs6000/rs6000.c (print_operand): Write small constants
+ as @l+80.
-2002-01-02 Kazu Hirata <kazu@hxi.com>
+ * df.c (read_modify_subreg_p): Narrow down cases for a rmw subreg.
+ (df_reg_table_realloc): Make size at least as large as max_reg_num().
+ (df_insn_table_realloc): Size argument now is absolute, not relative.
+ Changed all callers.
- * except.c: Fix comment typos.
- * loop.c: Likewise.
- * varasm.c: Likewise.
- * doc/tm.texi: Fix a typo.
+ * gengtype.c (main): Add the pseudo-type "HARD_REG_SET".
+ * regclass.c (reg_scan_mark_refs): Ignore NULL rtx's.
-2002-01-02 Jakub Jelinek <jakub@redhat.com>
+ 2002-06-20 Michael Matz <matz@suse.de>
- * c-typeck.c (output_init_element): Allow initializing static storage
- duration objects with compound literals.
+ * df.h (struct ref.id): Make unsigned.
+ * df.c (df_bb_reg_def_chain_create): Remove unsigned cast.
-2002-01-02 Richard Henderson <rth@redhat.com>
+ 2002-06-13 Michael Matz <matz@suse.de>
- * objc/objc-act.c (hack_method_prototype): Clear current_function_decl
- after abusing it.
+ * df.h (DF_REF_MODE_CHANGE): New flag.
+ * df.c (df_def_record_1, df_uses_record): Set this flag for refs
+ involving subregs with invalid mode changes, when
+ CLASS_CANNOT_CHANGE_MODE is defined.
-2002-01-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+ 2002-05-07 Michael Matz <matz@suse.de>
- * gcc.c (default_compilers): Const-ify.
- * mips-tdump.c (stab_names): Likewise.
- * mips-tfile.c (map_coff_types, map_coff_storage,
- map_coff_sym_type, map_coff_derived_type, stabs_symbol,
- pseudo_ops_t, pseudo_ops): Likewise.
- * protoize.c (default_include): Likewise
+ * reload1.c (fixup_abnormal_edges): Don't insert on NULL edge.
- * real.c (GET_REAL, PUT_REAL): Don't cast away const-ness.
- (ezero, ehalf, eone, etwo, e32, elog2, esqrt2, epi): Const-ify.
- Add array size in declaration.
- (endian, emov, eisneg, eisinf, eisnan, eiisnan, eiisneg, emovi,
- emovo, emovz, eiisinf, ecmpm, eaddm, esubm, m16m, edivm, emulm,
- esub, eadd, eadd1, ediv, emul, e53toe, e64toe, e113toe, e24toe,
- etoe113, etoe64, etoe53, etoe24, ecmp, eround, ltoe, ultoe,
- eifrac, euifrac, e24toasc, e53toasc, e64toasc, e113toasc, etoasc,
- efloor, efrexp, eldexp, eremain, dectoe, etodec, ibmtoe, etoibm,
- c4xtoe, etoc4x, uditoe, ditoe, etoudi, etodi, esqrt, etens,
- emtens, make_nan): Const-ify.
- (TFbignan, TFlittlenan, XFbignan, XFlittlenan, DFbignan,
- DFlittlenan, SFbignan, SFlittlenan): Make static and const-ify.
+ 2002-05-03 Michael Matz <matz@suse.de>
-2002-01-02 Joseph S. Myers <jsm28@cam.ac.uk>
+ * sbitmap.c (sbitmap_difference): Accept sbitmaps of different size.
- * config.gcc (ia64-*-*): Set extra_headers.
- (alpha*-dec-osf*): Likewise. Don't use alpha/t-osf.
- * config/alpha/t-osf: Remove.
- * config/ia64/t-ia64 (EXTRA_HEADERS): Remove.
+ Sat Feb 2 18:58:07 2002 Denis Chertykov <denisc@overta.ru>
-2002-01-02 David Edelsohn <edelsohn@gnu.org>
+ * regclass.c (regclass): Work with all regs which have sets or
+ refs.
+ (reg_scan_mark_refs): Count regs inside (clobber ...).
- * config/rs6000/t-aix43: Revert previous change.
+ 2002-01-04 Michael Matz <matzmich@cs.tu-berlin.de>
-2002-01-02 Jason Merrill <jason@redhat.com>
+ * df.c (df_ref_record): Correctly calculate SUBREGs of hardregs.
+ (df_bb_reg_def_chain_create, df_bb_reg_use_chain_create): Only
+ add new refs.
+ (df_bb_refs_update): Don't clear insns_modified here, ...
+ (df_analyse): ... but here.
- * c-decl.c (c_expand_body): Call outlining_inline_function when
- emitting an inline function out of line.
+ * sbitmap.c (dump_sbitmap_file): New.
+ (debug_sbitmap): Use it.
-2002-01-02 Richard Henderson <rth@redhat.com>
+ * sbitmap.h (dump_sbitmap_file): Add prototype.
- * dwarf2out.c (limbo_die_node): Add created_for member.
- (new_die): New argument created_for. Update all callers.
- (mark_limbo_die_list): New.
- (dwarf2out_init): Register limbo_die_list as a root.
- (dwarf2out_finish): Force insert limbo dies into their function
- context.
+ 2001-08-07 Daniel Berlin <dan@cgsoftware.com>
-2002-01-02 Nathan Sidwell <nathan@codesourcery.com>
+ * df.c (df_insn_modify): Grow the UID table if necessary, rather
+ than assume all emits go through df_insns_modify.
- PR c++/5089
- * doc/invoke.texi (-Wold-style-cast): Only warn about non-void casts.
+ 2001-07-26 Daniel Berlin <dan@cgsoftware.com>
-2002-01-02 Kazu Hirata <kazu@hxi.com>
+ * regclass.c (reg_scan_mark_refs): When we increase REG_N_SETS,
+ increase REG_N_REFS (like flow does), so that regclass doesn't
+ think a reg is useless, and thus, not calculate a class, when it
+ really should have.
- * config/h8300/fixunssfsi.c: Update copyright.
- Fix comment typos.
- Fix formatting.
- * config/h8300/h8300.c: Update copyright.
- Eliminate warnings.
+ 2001-01-28 Daniel Berlin <dberlin@redhat.com>
-2002-01-02 Kazu Hirata <kazu@hxi.com>
+ * sbitmap.h (EXECUTE_IF_SET_IN_SBITMAP_REV): New macro, needed for
+ dataflow analysis.
- * config/romp/romp.c: Fix comment formatting.
- * config/romp/romp.h: Likewise.
- * config/romp/romp.md: Likewise.
- * config/s390/s390.c: Likewise.
- * config/stormy16/stormy16.c: Likewise.
- * config/stormy16/stormy16.h: Likewise.
+2002-07-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/7245
+ * config/i386/i386.c (const_int_1_31_operand): New.
+ * config/i386/i386.h (PREDICATE_CODES): Add it.
+ * config/i386/i386.md (ashlsi3_cmp, ashlsi3_cmp_zext, ashlhi3_cmp,
+ ashlqi3_cmp, ashrsi3_cmp, ashrsi3_cmp_zext, ashrhi3_cmp, ashrqi3_cmp,
+ lshrsi3_cmp, lshrsi3_cmp_zext, lshrhi3_cmp, lshrqi3_cmp): Use it.
+
+2002-07-14 Alan Modra <amodra@bigpond.net.au>
+
+ PR target/7282
+ * config/rs6000/rs6000.md (floatsidf2): Enable for POWERPC64.
+ (floatunssidf2): Likewise.
+ (floatsidf_ppc64): New insn_and_split.
+ (floatunssidf_ppc64): Likewise.
+
+2002-07-14 Andreas Jaeger <aj@suse.de>
-2002-01-02 Alexandre Oliva <aoliva@redhat.com>
-
- * c-common.h (genrtl_expr_stmt_value): Declare.
- * c-semantics.c (genrtl_goto_stmt): Redirect to...
- (genrtl_goto_stmt_value): ... this new function. Pass new
- argument down to expand_expr_stmt_value, taking
- TREE_ADDRESSABLE into account.
- * c-common.c (c_expand_expr): Mark the last EXPR_STMT of a
- STMT_EXPR as addressable, i.e., one whose result we want.
- * expr.c (expand_expr): Don't save expression statement value
- of labeled_blocks or loop_exprs.
- * stmt.c (expand_expr_stmt): Redirect to...
- (expand_expr_stmt_value): ... this new function. Use new
- argument to tell whether to save expression value.
- (expand_end_stmt_expr): Reset last_expr_type and
- last_expr_value if we don't have either.
- * tree-inline.c (declare_return_variable): Mark its use
- statement as addressable.
- * tree.h: Document new use of TREE_ADDRESSABLE.
- (expand_expr_stmt_value): Declare.
-
-2002-01-01 Tom Rix <trix@redhat.com>
-
- * config/rs6000/rs6000.c (rs6000_emit_set_long_const): Fix for use by
- rs6000_emit_allocate_stack.
-
-2002-01-01 Joseph S. Myers <jsm28@cam.ac.uk>
-
- * configure.in: Prepend ${srcdir}/config/${cpu_type}/ instead of
- ${srcdir}/ginclude/ to every entry in extra_headers.
+ * config.gcc (sh64): Remove unused
+ target_requires_64bit_host_wide_int.
+
+2002-07-12 Roger Sayle <roger@eyesopen.com>
+
+ * expr.c [CLEAR_RATIO]: New macro defining the maximum number
+ of move instructions to use when clearing memory, c.f. MOVE_RATIO.
+ [CLEAR_BY_PIECES]: New macro, using CLEAR_RATIO, to determine
+ whether clear_by_pieces should be used to clear storage.
+ (clear_storage): Use CLEAR_BY_PIECES instead of MOVE_BY_PIECES.
+
+ * doc/tm.texi: Document these two new target macros.
+
+2002-07-12 Stephane Carrez <stcarrez@nerim.fr>
+
+ * config/m68hc11/m68hc11.md ("zero_extendsidi2"): Use D_REG only for
+ the scratch register.
+ ("*movhi2_push"): Accept Z_REG because a split pattern can make use
+ of it, forbid reload to use it.
+
+2002-07-12 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (test_hard_reg_class): Fix TEST_HARD_REG_BIT
+ usage on 64-bit hosts, return value was truncated to 32 bits.
+
+2002-07-12 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * simplify-rtx.c (simplify_subreg): Handle floating point
+ CONST_DOUBLEs. When an integer subreg of a smaller mode than
+ the element mode is requested, compute a subreg with an
+ integer mode of the same size as the element mode first.
+
+2002-07-11 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * combine.c (try_combine): When converting a paradoxical subreg
+ to an extension, take LOAD_EXTEND_OP into account.
+
+2002-07-11 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * config.gcc (mips-sgi-irix6*o32): New configuration.
+
+ * configure.in (libgcc_visibility): Disable for mips-sgi-irix6*o32
+ configurations.
* configure: Regenerate.
- * ginclude/math-3300.h: Rename to config/m68k/math-3300.h.
- * ginclude/math-68881.h: Rename to config/m68k/math-68881.h.
- * ginclude/ppc-asm.h: Rename to config/rs6000/ppc-asm.h.
- * ginclude/proto.h: Rename to config/convex/proto.h.
-
-Tue Jan 1 17:12:56 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
-
- * attribs.c (handle_vector_size_attribute): Use host_integerp
- and tree_int_cst; remove warnings.
- * caller-save.c (insert_restore): Add cast to get rid of warning.
- (insert_save): Likewise.
- * emit-rtl.c (adjust_address_1, offset_address): Likewise.
- * regmove.c (find_matches): Add temporary var to kill a warning.
-
-2002-01-01 Douglas B Rupp <rupp@gnat.com>
-
- * config/alpha/vms.h (DWARF2_UNWIND_INFO, EH_RETURN_HANDLER_RTX,
- LINK_EH_SPEC, MD_FALLBACK_FRAME_STATE_FOR): Define.
- * config/alpha/t-vms (EXTRA_PARTS): Add vms-dwarf2eh.o
- (vms-dwarf2eh.o): Add Makefile rule.
- * config/alpha/vms-ld.c (main): Handle vms-dwarf2eh.o.
- * config/alpha/vms-dwarf2eh.asm: New file.
-
- * gcc.c (delete_if_ordinary): Delete all versions.
-
-2002-01-01 Hans-Peter Nilsson <hp@bitrange.com>
-
- * config/mmix/mmix.md: Update FIXME to not mention
- define_constants.
- (MMIX_rJ_REGNUM): New define_constants constant.
- ("movqi", "movsi", "movdi", "*movdicc_real_foldable",
- "*movdicc_real"): Adjust contraints formatting.
- ("*bCC_foldable"): Add %+ for P in output format and delete FIXME
- for branch prediction.
- ("*bCC", "*bCC_inverted_foldable", "*bCC_inverted"): Add %+ in
- output template.
- ("*call_real", "*call_value_real", "nonlocal_goto_receiver",
- "*nonlocal_goto_receiver_expanded"): Use MMIX_rJ_REGNUM instead of
- number. Delete related FIXMEs.
- * config/mmix/mmix.h (MMIX_INCOMING_RETURN_ADDRESS_REGNUM): Change
- from number to MMIX_rJ_REGNUM.
- (TARGET_MASK_BRANCH_PREDICT): New.
- (TARGET_DEFAULT): Change to TARGET_MASK_BRANCH_PREDICT.
- (TARGET_SWITCHES): Update comment. Correct -mno-toplevel-symbols
- value. Add -mbranch-predict and -mno-branch-predict.
- (TARGET_VERSION): Drop date.
- (ADDITIONAL_REGISTER_NAMES): Use MMIX_rJ_REGNUM, not number.
- * config/mmix/mmix.c (mmix_encode_section_info): Correct condition
- for finding out global symbols.
- (mmix_asm_output_labelref): Revert condition for global symbol.
- (mmix_print_operand): <case '+'>: Emit P for a likely branch.
- (mmix_print_operand_punct_valid_p): A '+' is valid.
-
-See ChangeLog.6 for earlier changes.
+
+ * config/mips/iris6-o32-as.h: New file.
+ * config/mips/iris6-o32.h: New file.
+
+ * config/mips/iris5gas.h (TARGET_ASM_NAMED_SECTION): Define.
+ (NM_FLAGS): Define.
+ (HAVE_AS_SHF_MERGE): Undefine.
+
+ * config/mips/t-iris5-as: New file.
+ * config.gcc (mips-sgi-irix6*o32, mips-sgi-irix5*): Use it.
+
+ * config/mips/t-iris6 (SHLIB_EXT, SHLIB_SOLINK, SHLIB_SONAME,
+ SHLIB_NAME, SHLIB_MAP, SHLIB_OBJS, SHLIB_SLIBDIR_QUAL, SHLIB_LINK,
+ SHLIB_INSTALL, SHLIB_MKMAP, SHLIB_MAPFILES, FPBIT, DPBIT,
+ dp-bit.c, fp-bit.c): Move ...
+ * config/mips/t-iris5-6: ... here.
+ New file, shared by IRIX 5 and IRIX 6.
+ * config.gcc (mips-sgi-irix6*o32, mips-sgi-irix6*,
+ mips-sgi-irix5*): Use it.
+
+ * config/mips/iris6.h: Remove duplicate comment.
+
+ * config/mips/mips.c (TARGET_ASM_UNALIGNED_DI_OP) [TARGET_IRIX5 &&
+ !TARGET_IRIX6]: Define.
+ (mips_asm_file_start): Don't emit mdebug.<ABI> sections on IRIX 5/6.
+
+ * config/mips/mips.h (ASM_DECLARE_FUNCTION_NAME): Fix comment.
+
+2002-07-11 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.md (adddi3): Change predicate of operand 2 to adddi3_operand
+ and delete code to force constant to register.
+ * pa-protos.h (adddi3_operand): Add prototype.
+ * pa.c (adddi3_operand): New function.
+
+2002-07-11 Roger Sayle <roger@eyesopen.com>
+
+ * c-decl.c (duplicate_decls): Preserve the noreturn attribute on
+ non-ANSI builtin functions.
+
+2002-07-11 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * rtl.h (gen_rtx_CONST_VECTOR): Declare.
+ * gengenrtl.c (special_rtx): Check for CONST_VECTOR.
+ * emit-rtl.c (gen_rtx_CONST_VECTOR): New function.
+ (gen_const_vector_0): Use it.
+
+2002-07-11 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.md (adddi3): For 32-bit targets, force constants to a register
+ if they don't fit in an 11-bit immediate. Change insn predicate to
+ arith11_operand. Remove comment.
+ * pa.c (cint_ok_for_move): Fix comment.
+ (emit_move_sequence): Don't directly split DImode constants on 32-bit
+ targets.
+
+2002-07-11 Tim Josling <tej@melbpc.org.au>
+
+ Remove front end hard coding from gengtype.c.
+
+ * Makefile.in
+ (STAGESTUFF): add gtyp-gen.h
+ (GTFILES): Remove front end specific files.
+ (GTFILES_FILES_LANGS): New, from configure..
+ (GTFILES_FILES_FILES): Likewise.
+ (GTFILES_LANG_DIR_NAMES): Likewise.
+ (GTFILES_SRCDIR): Likewise.
+ (gtyp-gen.h): Build from configure information.
+ (s-gtype): Remove command line parameters from gengtype.
+ (gengtype.o): Remove dependency on GTFILES. Depend on gtyp-gen.h.
+ (mostlyclean): Delete files generated by and for gengtype.
+
+ * c-config-lang.in: New file.
+
+ * configure.in (all_gtfiles_files_langs): New. Accumulate files
+ for each language.
+ (all_gtfiles_files_files): New. Accumulate language for each file
+ accumulated.
+ (gtfiles): Pick up value for C.
+ (srcdir): AC-SUBST this variable.
+ (all_gtfiles_files_langs): AC-SUBST this variable.
+ (all_gtfiles_files_files): AC-SUBST this variable.
+
+ * configure: Regenerate.
+
+ * gengtype-lex.l (parse_file): Make parameter const.
+
+ * gengtype.c (toplevel): include gtyp-gen.h.
+ (BASE_FILE_<language> unnamed enum): Delete.
+ (lang_names): Delete (replaced by gtyp-gen.h)
+ (lang_dir_names): From gtyp-gen.h, replaces lang_names; changed
+ all references.
+ (NUM_GT_FILES): New.
+ (NUM_LANG_FILES): New.
+ (srcdir_len): New.
+ (NUM_BASE_FILES): Change calculation.
+ (open_base_files): Change prototype to avoid warning.
+ (startswith): Delete.
+ (get_file_basename): Iterate through generated language list not
+ hard coded list.
+ (get_base_file_bitmap): Use generated list of files and languages.
+ (close_output_files): Add prototype to rmove warning.
+ (main): Iterate through list of generated files from gtyp-gen.h
+ rather than command line paramaters. Ignore duplicated file
+ names.
+
+ * gengtype.h (parse_file): Amend prototype for const parameter.
+
+ * doc/sourcebuild.texi: Document gtfiles variable.
+
+ * doc/gty.texi: Document changes to gtfiles variable for front
+ ends.
+
+ * objc/config-lang.in (gtfiles): Add files needed for objc front
+ end.
+
+2002-07-10 Roger Sayle <roger@eyesopen.com>
+
+ PR c/2454
+ * combine.c (nonzero_bits): LOAD_EXTEND_OP should only apply
+ to SUBREGs of MEMs. (num_sign_bit_copies): Likewise.
+
+2002-07-10 Roger Sayle <roger@eyesopen.com>
+ Zack Weinberg <zack@codesourcery.com>
+
+ * builtins.def: Make the argument types of abort and exit
+ independent of the front-end.
+
+2002-07-11 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/linux64.h (ASM_SPEC): Define.
+
+2002-07-10 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c (emit_frame_save): New.
+ (rs6000_frame_related): Replace reg2 before reg.
+ (rs6000_emit_prologue): Use emit_frame_save for saving gprs, fprs,
+ and eh_return registers.
+
+2002-07-10 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ Revert all patches for optimization of Complex .op. Real.
+ * complex_part_zero_p: Remove
+ * expand_cmplxdiv_straight: Replace complex_part_zero_p(x)
+ with x.
+ * expand_cmplxdiv_wide: Ditto.
+ * expand_binop: Ditto.
+
+2002-07-10 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.md: Fix two 0x80000000 constants to make them
+ negative also on 64-bit hosts.
+
+ Default to -fno-reorder-blocks when optimizing for size.
+ * config/avr/avr-protos.h (avr_optimization_options): Declare.
+ * config/avr/avr.c (avr_optimization_options): New function.
+ * config/avr/avr.h (OPTIMIZATION_OPTIONS): New.
+
+ Optimize returning from simple functions.
+ * config/avr/avr-protos.h (avr_simple_epilogue): Declare.
+ * config/avr/avr.c (avr_simple_epilogue): New function.
+ * config/avr/avr.md (return): New insn.
+
+2002-07-10 Douglas B Rupp <rupp@gnat.com>
+
+ * config/i386/i386.c (ix86_svr3_asm_out_constructor): Add
+ HAS_INIT_SECTION to protection.
+
+2002-07-10 Mark Mitchell <mark@codesourcery.com>
+
+ * doc/invoke.texi (Debugging Options): Mention that -gdwarf is
+ deprecated.
+
+2002-07-10 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * combine.c (gen_lowpart_for_combine): Handle vector modes.
+ Supply non-VOID mode to simplify_gen_subreg.
+
+2002-07-10 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (ix86_init_mmx_sse_builtins): Fix thinko.
+
+2002-07-10 Jeffrey A Law <law@redhat.com>
+
+ * mn10200.c (expand_prologue): Create REG_MAYBE_DEAD notes
+ as appropriate.
+
+ * mn10200.c (expand_epilogue): Fix test to determine which scratch
+ register to use.
+
+2002-07-10 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * cse.c (cse_insn): Supply proper SUBREG_BYTE to simplify_gen_subreg.
+ Get mode from dest.
+ If simplify_gen_subreg fails, try next equivalent.
+
+2002-07-09 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * diagnostic.h: #include location.h
+ (location_t): Move definition to..
+ * location.h: ... here. New file.
+ * tree.h: #include location.h
+ (DECL_SOURCE_LOCATION): New macro.
+ (DECL_SOURCE_FILE): Use.
+ (DECL_SOURCE_LINE): Likewise.
+ (struct tree_decl): REplace filename and linenum with locus.
+ * Makefile.in (TREE_H): add location.h
+ (diagnostic.o): Depends on gt-location.h
+ (gt-location.h): Depends on s-gtype
+
+2002-07-09 Matt Kraai <kraai@alumni.cmu.edu>
+
+ * config/rs6000/aix.h: Convert CPP_PREDEFINES to
+ TARGET_OS_CPP_BUILTINS.
+ * config/rs6000/aix31.h: Likewise.
+ * config/rs6000/aix41.h: Likewise.
+ * config/rs6000/aix43.h: Likewise.
+ * config/rs6000/aix51.h: Likewise.
+ * config/rs6000/beos.h: Likewise.
+ * config/rs6000/darwin.h: Likewise.
+ * config/rs6000/eabi.h: Likewise.
+ * config/rs6000/eabisim.h: Likewise.
+ * config/rs6000/linux.h: Likewise.
+ * config/rs6000/linux64.h: Likewise.
+ * config/rs6000/lynx.h: Likewise.
+ * config/rs6000/mach.h: Likewise.
+ * config/rs6000/rtems.h: Likewise.
+ * config/rs6000/sysv4.h: Likewise.
+ * config/rs6000/vxppc.h: Likewise.
+
+2002-07-09 Devang Patel <dpatel@apple.com>
+ * objc/objc-act.c (adjust_type_for_id_default): Fix my previous patch.
+ Do not allow ObjC objects as a parameter type for Objective-C methods.
+ My previous patch restricted 'struct' also.
+
+2002-07-09 Neil Booth <neil@daikokuya.co.uk>
+
+ * cpperror.c (cpp_error): Default to directive_line within
+ directives here.
+ * cppexp.c (cpp_interpret_integer): Only use traditional
+ number semantics in directives.
+ * cpplib.c (prepare_directive_trad): Don't reset pfile->line.
+ (do_include_common): Similarly.
+ * cpptrad.c (scan_out_logical_line): Implement accurate
+ quoting of <> in #include.
+ * doc/cpp.texi: Update.
+
+2002-07-09 Stephen Clarke <stephen.clarke@superh.com>
+ J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.c (sh_adjust_cost): Special handling of SHMEDIA code.
+ * sh.md (attribute issues): Replace with:
+ (attribute pipe_model). All users changed.
+ (attribute type): Change pt / ptabs to pt_media / ptabs_media.
+ All users changed.
+ (function units sh5issue, sh5fds): New.
+ (attribute is_mac_media): New.
+ (adddi3_media, subdi3_media, divsi3_i1_media, anddi3): Add type.
+ (andcdi3, iordi3, xordi3, ashldi3_media, lshrdi3_media): Likewise.
+ (ashrdi3_media, negdi_media, extendsidi2, movqi_media): Likewise.
+ (movhi_media, shori_media, movv2sf_i, jump_media): Likewise.
+ (call_media, call_value_media, sibcall_media): Likewise.
+ (casesi_jump_media, casesi_shift_media, casesi_load_media): Likewise.
+ (return_media_i, addsf3_media, subsf3_media, mulsf3_media): Likewise.
+ (mac_media, divsf3_media, floatdisf2, floatsisf2_media): Likewise.
+ (fix_truncsfdi2, fix_truncsfsi2_media, cmpeqsf_media): Likewise.
+ (cmpgtsf_media, cmpgesf_media, cmpunsf_media, negsf2_media): Likewise.
+ (sqrtsf2_media, abssf2_media, adddf3_media, subdf3_media): Likewise.
+ (muldf3_media, divdf3_media, floatdidf2, floatsidf2_media): Likewise.
+ (fix_truncdfdi2, fix_truncdfsi2_media, cmpeqdf_media): Likewise.
+ (cmpgtdf_media, cmpgedf_media,cmpundf_media, negdf2_media): Likewise.
+ (sqrtdf2_media, absdf2_media, extendsfdf2_media): Likewise.
+ (truncdfsf2_media): Likewise.
+ (movsi_media, movsi_media_nofpu, movdi_media): Use new types.
+ (movdi_media_nofpui, movdf_media, movdf_media_nofpu): Likewise.
+
+2002-07-09 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.h (PREDICATE_CODES): Add general_extend_operand and inqhi_operand.
+ * sh.c (general_extend_operand, inqhi_operand): New functions.
+ * sh.md (cmpeqdi_media, cmpgtdi_media, cmpgtudi_media): Collapse
+ alternatives using 'N' modifier. Add type.
+ (adddi3z_media): Likewise. Enable generator function generation.
+ (movdicc_false, movdicc_true, addsi3_media, subsi3_media): Use more
+ exact predicates / constraints. Add type.
+ (subsi3): Allow 0 for SHMEDIA.
+ (udivsi3_i4_media): Use match_operand for input values
+ rather than hard registers.
+ (udivsi3 - TARGET_SHMEDIA_FPU case): Don't ferry values
+ unnecessarily through hard registers. Keep copies of pseudo
+ registers outside of the libcall sequence.
+ (mulsidi3_media, umulsidi3_media): Use more exact predicates. Add type.
+ (ashlsi3_media, ashrsi3_media, lshrsi3_media): Likewise.
+ (zero_extendsidi2, zero_extendhidi2, zero_extendqidi2): Likewise.
+ (extendhidi2, extendqidi2): Likewise.
+ (andsi3_compact): Name.
+ (andcdi3): Enable generator function generation.
+ (zero_extendhisi2, zero_extendqisi2): Rename to
+ (zero_extendhisi2_compact, zero_extendqisi2_compact).
+ (extendhisi2, extendqisi2): Rename to
+ (extendhisi2_compact, extendqisi2_compact).
+ (rotldi3, rotldi3_mextr, rotrdi3, rotrdi3_mextr): New patterns.
+ (loaddi_trunc, zero_extendhisi2, zero_extendhisi2_media): Likewise.
+ (zero_extendhisi2_media+1, zero_extendqisi2): Likewise.
+ (zero_extendqisi2_media, extendhisi2, extendhisi2_media): Likewise.
+ (extendhisi2_media, extendhisi2_media+1, extendqisi2): Likewise.
+ (extendqisi2_media, extendqisi2_media+1, truncdisi2): Likewise.
+ (truncdihi2, truncdiqi2, reload_inqi, reload_inhi): Likewise.
+ (shmedia32_initialize_trampoline_big): Likewise.
+ (shmedia32_initialize_trampoline_little): Likewise.
+ (nsb, nsbsi, nsbdi, ffsdi2, ffssi2, byterev): Likewise.
+ (negdi2): Remove spurious T clobber.
+ (zero_extendhidi2+1, extendhidi2+1, extendqidi2+1): Handle TRUNCATE.
+ (movsi_media, movsi_media_nofpu): Remove spurious *k after b.
+ (movdi_media, movdi_media_nofpu, pt, ptb): Likewise.
+ (movsi_media_nofpu+2, movhi_media+1): Only do split after reload.
+ (ic_invalidate_line_media): Write back data cache before invalidating
+ instruction cache. Add type.
+ (movsf_media): Sign-extend when the destination is a general
+ purpose register. Add type.
+ (bgt_media, bge_media, bgtu_media, bgeu_media, blt_media_i): Allow 0.
+ (casesi_worker_0+1): Only increment ref count for proper label.
+ (casesi_worker_0+2): Likewise.
+
+2002-07-09 Mark Mitchell <mark@codesourcery.com>
+
+ * dwarfout.c (dwarfout_init): Warn that DWARF1 is deprecated.
+
+2002-07-09 Steve Ellcey <sje@cup.hp.com>
+
+ * gcc/except.c (expand_eh_region_end_cleanup): Change exception pointer
+ from Pmode to ptr_mode.
+ (get_exception_pointer): Ditto.
+ (connect_post_landing_pads): Ditto.
+ (dw2_build_landing_pads): Ditto.
+
+2002-07-08 Steve Ellcey <sje@cup.hp.com>
+ * gcc/c-pragma.h (add_to_renaming_pragma_list): New function.
+ * gcc/c-pragma.c (add_to_renaming_pragma_list): New function.
+ (handle_pragma_redefine_extname): Change to use new function.
+
+2002-07-08 Roger Sayle <roger@eyesopen.com>
+
+ * combine.c (combine_simplify_rtx): Add an explicit cast
+ to avoid signed/unsigned comparison warning.
+ (simplify_if_then_else): Likewise.
+ (extended_count): Likewise.
+ (simplify_shift_const): Likewise.
+ (simplify_comparison): Likewise.
+
+2002-07-08 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips.md: Add imadd type. Update scheduler description
+ to use imadd as well as imul.
+ (*mul_acc_si, *madsi): Change imul alternatives to imadd.
+ (*mul_acc_di, *mul_acc_64bit_di): Likewise.
+ (*mul_sub_si): Likewise for first alternative. Change second
+ alternative from imul to multi.
+
+2002-07-07 Neil Booth <neil@daikokuya.co.uk>
+
+ * c-common.c (c_common_post_options): Update prototype;
+ don't init backends if preprocessing only.
+ * langhooks-def.h (LANG_HOOKS_POST_OPTIONS): Update.
+ * langhooks.h (struct lang_hooks): Update post_options to
+ return a boolean.
+ * toplev.c (parse_options_and_default_flags, do_compile,
+ lang_independent_init): Update prototypes. Allow the
+ front end to specify that there is no need to initialize
+ the back end.
+ (general_init): Move call to hex_init here...
+ (toplev_main): ...from here. Pass flag for back end init
+ suppression.
+
+2002-07-07 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.h (PRINT_OPERAND_PUNCT_VALID_P): Allow '\''.
+ (PREDICATE_CODES): Add entries for equality_comparison_operator,
+ greater_comparison_operator and less_comparison_operator.
+ * sh.c (print_operand): Add '\'' code. Make 'o' handle
+ more operators.
+ (equality_comparison_operator): New function.
+ (greater_comparison_operator, less_comparison_operator): Likewise.
+ * sh.md (beq_media_i): Disable generator function generation.
+ Use match_operator to handle a whole class of comparisons. Add
+ modifier in output template to provide branch prediction. Add type.
+ (bgt_media_i, ble_media_i): Likewise. Allow zero operands.
+ (bne_media_i, bge_media_i, bgtu_media_i, bgeu_media_i): Delete.
+ (blt_media_i, bleu_media_i, bltu_media_i): Likewise.
+ (bgt, blt, ble, bge, bgtu, bltu, bgeu, bleu): Allow zero operands.
+
+2002-07-07 Hans-Peter Nilsson <hp@bitrange.com>
+
+ Emit MMIX function prologue and epilogue as rtl.
+ * config/mmix/mmix.md ("call"): Use mmix_get_hard_reg_initial_val,
+ not unprototyped get_hard_reg_initial_val.
+ ("call_value", "nonlocal_goto_receiver"): Ditto.
+ ("return"): Make define_expand. Move real insn to...
+ ("*expanded_return"): New pattern.
+ ("prologue", "epilogue"): New define_expands.
+ * config/mmix/mmix.h (MMIX_rO_REGNUM): New macro.
+ (struct machine_function): New member in_prologue.
+ (FIRST_PSEUDO_REGISTER): Adjust for including rO as register.
+ (FIXED_REGISTERS, CALL_USED_REGISTERS): Ditto.
+ (MMIX_MMIXWARE_ABI_REG_ALLOC_ORDER): Ditto.
+ (MMIX_GNU_ABI_REG_ALLOC_ORDER, REG_CLASS_CONTENTS): Ditto.
+ (REGISTER_NAMES, ADDITIONAL_REGISTER_NAMES): Ditto.
+ (LOCAL_REGNO): Define. Adjust comment.
+ * config/mmix/mmix.c (MMIX_CFUN_NEEDS_SAVED_EH_RETURN_ADDRESS):
+ Consider regs_ever_live[MMIX_rJ_REGNUM], not just
+ leaf_function_p.
+ (MMIX_OUTPUT_REGNO): Don't translate registers while outputting
+ the prologue.
+ (mmix_target_asm_function_prologue): Make static. Just mark that
+ the prologue is being emitted. Move guts to...
+ (mmix_expand_prologue): New function. Adjust for emitting
+ prologue as rtl. For sizes, use HOST_WIDE_INT only.
+ (mmix_target_asm_function_epilogue): Make static. Simply emit a
+ \n. Move guts to...
+ (mmix_expand_epilogue): New function. Adjust for emitting
+ epilogue as rtl. For sizes, use HOST_WIDE_INT only.
+ (mmix_target_asm_function_end_prologue): Mark that the prologue
+ has ended.
+ (TARGET_ASM_FUNCTION_END_PROLOGUE): Define.
+ (mmix_conditional_register_usage): Improve comments.
+ (mmix_local_regno): New function.
+ (mmix_emit_sp_add, mmix_get_hard_reg_initial_val): Ditto.
+ * config/mmix/mmix-protos.h (mmix_local_regno): Prototype.
+ (mmix_expand_prologue, mmix_expand_epilogue): Ditto.
+ (mmix_get_hard_reg_initial_val): Ditto.
+
+2002-07-06 Andreas Jaeger <aj@suse.de>
+
+ * toplev.c (set_fast_math_flags): Don't use ISO C style function
+ definitions.
+ * gengtype.c (open_base_files): Likewise.
+ (close_output_files): Likewise.
+ * tracer.c (find_best_predecessor): Likewise.
+ (find_best_successor): Likewise.
+ (ignore_bb_p): Likewise.
+
+2002-07-05 Roger Sayle <roger@eyesopen.com>
+
+ PR c++/7099
+ * builtin-attrs.def: Define new attribute lists for use in
+ builtins.def.
+ * builtins.def [DEF_BUILTIN]: Modify to take an additional
+ ATTRS argument, an enumerated value defined in builtin-attrs.def
+ that represents the attribute list for the builtins. Modify
+ all builtin functions to pass an appropriate attribute list.
+ Specify "abort", "exit", "_exit" and "_Exit" builtins here with
+ their required noreturn attributes.
+ * tree.h (enum_builtin_function): Ignore the additional parameter
+ to DEF_BUILTIN.
+ * builtins.c (built_in_names): Likewise.
+ * c-common.c: (builtin_function_2): Replace the "int noreturn_p"
+ argument with a tree representing the functions attribute list.
+ Pass this "attrs" argument to builtin_function. No longer handle
+ the noreturn_p processing manually.
+ (built_in_attributes): Move the definitions from builtin-attrs.def
+ before c_common_nodes_and_builtins.
+ (c_common_nodes_and_builtins): Handle the new ATTRS parameter in
+ DEF_BUILTIN, passing it to both builtin_function and the changed
+ builtin_function_2.
+
+ * doc/extend.texi: Document __builtin_abort, __builtin_exit,
+ __builtin__exit and __builtin__Exit.
+
+2002-07-05 Stephane Carrez <stcarrez@nerim.fr>
+
+ * config/m68hc11/m68hc11.md ("*movqi_68hc12"): Avoid allocating
+ QI mode registers in soft registers.
+ ("zero_extendqihi2"): Do not take into account soft registers
+ for register allocation (use '*' constraint).
+
+2002-07-05 Stephane Carrez <stcarrez@nerim.fr>
+
+ * config/m68hc11/m68hc11.md ("*ashlsi3"): Avoid saving y if we know
+ it is dead.
+ ("*ashrsi3"): Likewise.
+ ("*lshrsi3"): Likewise.
+
+2002-07-05 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (output_max_insn_queue_index_def): Take latencies
+ into account.
+
+2002-07-05 Stephane Carrez <stcarrez@nerim.fr>
+
+ * config/m68hc11/m68hc11.md (peephole2): New peephole2 to optimize
+ address computation and memory moves.
+
+2002-07-03 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/6706
+ * dwarfout.c (output_reg_number): Fix warning message.
+ (output_bound_representation): Check SAVE_EXPR_RTL is not NULL
+ before using it.
+
+2002-07-05 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * gcc/gcc.c (asm_debug): Move initialization ...
+ (init_spec): ... here.
+
+2002-07-05 Nathan Sidwell <nathan@codesourcery.com>
+
+ * c-parse.in (extdef): Append ';'.
+ (old_style_parm_decls): Append ';'.
+
+2002-07-04 Daniel Jacobowitz <drow@mvista.com>
+
+ * configure.in: Correct typos: gcc_cv_as_gdwarf2_debug_flag to
+ gcc_cv_as_gdwarf2_flag and gcc_cv_as_gstabs_debug_flag
+ to gcc_cv_as_gstabs_flag.
+ * configure: Rebuilt.
+
+2002-07-04 Geoffrey Keating <geoffk@redhat.com>
+
+ * ggc.h (ggc_add_root): Document as obsolete.
+
+2002-07-04 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.md (mshfhi_b, mshflo_b, mshfhi_l, mshflo_l, mshfhi_w): Add DONE.
+ (mshflo_w): Likewise.
+
+2002-07-04 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * simplify-rtx.c (simplify_subreg): Reduce problem of finding
+ vector mode subregs of constants to finding integer mode
+ subregs of constants.
+ * cse.c (cse_insn): Use simplify_gen_subreg.
+ * convert.c (convert_to_integer): Don't strip a NOP_EXPR
+ From a vector mode expression of different size than the
+ target mode.
+
+2002-07-03 Eric Christopher <echristo@redhat.com>
+
+ * config/mips/linux.h: Add #undef for SUBTARGET_CPP_SPEC.
+ * config/mips/mips.h: Remove deprecated -m<processor> options
+ and cc1_cpu_spec associated.
+ (CONSTANT_ADDRESS_P): Fix last patch.
+ (ASM_DECLARE_FUNCTION_NAME): Declare. Fix comment.
+ * config/mips/mips.md (bungt, bunge, sungt_df, sungt_sf, sunge_df,
+ sunge_sf): Remove.
+
+2002-07-03 Stan Shebs <shebs@apple.com>
+
+ * config/darwin.h (APPLE_CC): Remove, not meaningful in FSF GCC.
+ (STRINGIFY_THIS, REALLY_STRINGIFY): Remove.
+ (CPP_SPEC): Remove insertion of APPLE_CC definition.
+
+2002-07-03 Roger Sayle <roger@eyesopen.com>
+
+ * combine.c (struct_undo): Change types of recorded substitutions
+ to be either "int" or "rtx", instead of "unsigned int" and "rtx".
+ (do_SUBST_INT): Change types of the substitution from unsigned int
+ to int, to avoid compilation warning from SUBST_INT's only caller.
+
+ (make_extraction): Add cast to avoid compilation warning.
+ (force_to_mode): Remove cast to avoid compilation warning.
+
+2002-07-03 Eric Botcazou <ebotcazou@multimania.com>
+ Jeff Law <law@redhat.com>
+
+ * i386.md (length_immediate attribute): Fix typo.
+ (length_address attribute): Likewise.
+ (modrm attribute): Set it to 0 for immediate call instructions.
+ (jcc_1 pattern): Set modrm attribute to 0.
+ (jcc_2 pattern ): Likewise.
+ (jump pattern): Likewise.
+ (doloop_end_internal pattern): Explicitly set length.
+ (leave pattern): Fix typo.
+ (leave_rex64 pattern): Likewise.
+
+2002-07-03 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.md (fix_truncdfsi2_internal): Ignore DImode
+ in FPR as preference.
+ (fctiwz): Same.
+ (floatdidf2, fix_truncdfdi2): Same.
+ (floatdisf2, floatditf2, fix_trunctfdi2): Same.
+ (floatditf2): Same.
+ (floatsitf2, fix_trunctfsi2): SImode in GPR.
+ (ctrdi): Remove FPR alternative and splitter.
+
+2002-07-03 Will Cohen <wcohen@redhat.com>
+
+ * config/i386/i386.c (x86_integer_DFmode_moves): Disable for PPro.
+
+2002-07-03 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * optabs.c (expand_vector_binop): Don't store using a SUBREG smaller
+ than UNITS_PER_WORD, unless this is little endian and the first unit
+ in this word. Let extract_bit_field decide how to load an element.
+ Force arguments to matching mode.
+ (expand_vector_unop): Likewise.
+
+ * simplify-rtx.c (simplify_subreg): Don't assume that all vectors
+ consist of word_mode elements.
+ * c-typeck.c (build_binary_op): Allow vector types for BIT_AND_EXPR,
+ BIT_ANDTC_EXPR, BIT_IOR_EXPR and BIT_XOR_EXPR.
+ (build_unary_op): Allow vector types for BIT_NOT_EPR.
+ * emit-rtl.c (gen_lowpart_common): Use simplify_gen_subreg for
+ CONST_VECTOR.
+ * optabs.c (expand_vector_binop): Try to perform operation in
+ smaller vector modes with same inner size. Add handling of AND, IOR
+ and XOR. Reject expansion to inner-mode sized scalars when using
+ OPTAB_DIRECT. Use simplify_gen_subreg on constants.
+ (expand_vector_unop): Try to perform operation in smaller vector
+ modes with same inner size. Add handling of one's complement.
+ When there is no vector negate operation, try a vector subtract
+ operation. Use simplify_gen_subreg on constants.
+ * simplify-rtx.c (simplify_subreg): Add capability to convert vector
+ constants into smaller vectors with same inner mode, and to
+ integer CONST_DOUBLEs.
+
+2002-07-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * c-parse.in (parsing_iso_function_signature): New variable.
+ (extdef_1): New, copied from...
+ (extdef): ... here. Reset parsing_iso_function_signature.
+ (old_style_parm_decls): Reset parsing_iso_function_signature.
+ (old_style_parm_decls_1): New, copied from old_style_parm_decls.
+ Warn about ISO C style function definitions.
+ (nested_function, notype_nested_function): Reset
+ parsing_iso_function_signature.
+ (parmlist_2): Set parsing_iso_function_signature.
+
+ * doc/invoke.texi (-Wtraditional): Document new behavior.
+
+2002-07-02 Chris Demetriou <cgd@broadcom.com>
+
+ * config.gcc (mips*el-*-*): Use tm_defines to set
+ TARGET_ENDIAN_DEFAULT, rather than including mips/little.h.
+ * config/mips/little.h: Remove.
+
+2002-07-02 Devang Patel <dpatel@apple.com>
+
+ * objc/objc-act.c (adjust_type_for_id_default): Do not allow an
+ object as parameter. Prevent something like 'NSObject' to be
+ used as the type for a method argument.
+
+2002-07-03 Neil Booth <neil@daikokuya.co.uk>
+
+ * cpptrad.c: Update comment.
+
+2002-07-02 Neil Booth <neil@daikokuya.co.uk>
+
+ * doc/cpp.texi: Update for traditional preprocessing changes.
+ * goc/cppopts.texi: Similarly.
+
+2002-07-02 Ziemowit Laski <zlaski@apple.com>
+
+ * c-parse.in (designator): Enable designated initializers if ObjC.
+ (objcmessageexpr): Remove references to objc_receiver_context.
+ * objc/objc-act.h (objc_receiver_context): Remove decl.
+ * objc/objc-act.c (objc_receiver_context): Remove.
+ (lookup_objc_ivar): Test objc_method_context instead of
+ objc_receiver_context.
+
+2002-07-02 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.c (print_operand, case 'N'): Allow zero vector.
+ (arith_reg_or_0_operand): Likewise.
+ (zero_vec_operand): Check for CONST_VECTOR, not PARALLEL.
+ * sh.h (CONST_COSTS): 0 has 0 cost. Check OUTER_CODE for
+ IOR, XOR, PLUS and SET and take their respective constant
+ ranges into account.
+ (PREDICATE_CODES, arith_reg_or_0_operand): Can be CONST_VECTOR.
+ * sh.md (subdi3, subdi3_media): Allow zero operand.
+ (movv8qi_i+3): Only vector that is not split is the zero vector.
+ Fix operand 3 to simplify_subreg.
+ (movv2si_i): Split alternative 1.
+ (mshfhi_l_di_rev+1): New splitter.
+
+2002-07-02 Neil Booth <neil@daikokuya.co.uk>
+
+ PR preprocessor/7029
+ * cppinit.c (cpp_handle_option): Suppress warnings with an
+ implicit "-w" for "-M" and "-MM".
+ * doc/cppopts.texi: Update.
+
+2002-07-01 Roger Sayle <roger@eyesopen.com>
+
+ * config/sh/sh.c (sh_media_init_builtins): Change use of poisoned
+ identifier "bzero" to "memset". Pass extra NULL_TREE argument to
+ builtin_function.
+
+2002-07-02 Alan Modra <amodra@bigpond.net.au>
+
+ * README.Portability: Fix typos.
+
+2002-07-01 Hans-Peter Nilsson <hp@axis.com>
+
+ PR target/7177
+ * config/cris/cris.h (LEGITIMIZE_RELOAD_ADDRESS): Correct number
+ of indirections for register inside sign-extended mem part.
+
+2002-07-01 Roger Sayle <roger@eyesopen.com>
+
+ * tree.h: Modify builtin_function interface to take an extra
+ argument ATTRS, which is a tree representing an attribute list.
+
+ * c-decl.c (builtin_function): Accept additional parameter.
+ * objc/objc-act.c (builtin_function): Likewise.
+ * f/com.c (builtin_function): Likewise.
+ * java/decl.c (builtin_function): Likewise.
+ * ada/utils.c (builtin_function): Likewise.
+ * cp/decl.c (builtin_function): Likewise.
+ (builtin_function_1): Likewise.
+
+ * c-common.c (c_common_nodes_and_builtins): Pass an additional
+ NULL_TREE argument to builtin_function. (builtin_function_2):
+ Likewise.
+ * cp/call.c (build_java_interface_fn_ref): Likewise.
+ * objc/objc-act.c (synth_module_prologue): Likewise.
+ * java/decl.c (java_init_decl_processing): Likewise.
+ * f/com.c (ffe_com_init_0): Likewise.
+
+ * config/alpha/alpha.c (alpha_init_builtins): Pass an additional
+ NULL_TREE argument to builtin_function.
+ * config/arm/arm.c (def_builtin): Likewise.
+ * config/c4x/c4x.c (c4x_init_builtins): Likewise.
+ * config/i386/i386.c (def_builtin): Likewise.
+ * config/ia64/ia64.c (def_builtin): Likewise.
+ * config/rs6000/rs6000.c (def_builtin): Likewise.
+
+2002-07-01 Zack Weinberg <zack@codesourcery.com>
+
+ * config/ip2k/t-ip2k: Remove LIBGCC1, CROSS_LIBGCC1, and LIBGCC1_TEST.
+ * config/mips/t-isa3264: Likewise.
+ * config/mmix/t-mmix: Likewise.
+
+2002-07-01 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * emit-rtl.c (init_emit_once): Add missing cast to HOST_WIDE_INT.
+
+2002-07-01 Roger Sayle <roger@eyesopen.com>
+
+ PR opt/4046
+ * fold-const.c (fold) [COND_EXPR]: Simplify A ? 0 : 1 to !A,
+ A ? B : 0 to A && B and A ? B : 1 into !A || B if both A and
+ B are truth values.
+
+2002-07-01 Nathanael Nerode <neroden@gcc.gnu.org>
+
+ * config/mmix/t-mmix: Eliminate last reference to LIBGCC1_TEST.
+
+2002-07-01 Matt Kraai <kraai@alumni.cmu.edu>
+
+ * README.Portability (Function prototypes): Give an example of
+ declaring and defining a function with no arguments.
+
+ * README.Portability (Function prototypes): Document new
+ variable-argument function macros.
+
+2002-07-01 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.c (langhooks.h): Include.
+ (sh_init_builtins, sh_media_init_builtins): New functions.
+ (sh_expand_builtin, arith_reg_dest,and_operand): Likewise.
+ (mextr_bit_offset, extend_reg_operand, zero_vec_operand): Likewise.
+ (sh_rep_vec, sh_1el_vec, sh_const_vec): Likewise.
+ (builtin_description): New struct tag.
+ (signature_args, bdesc): New arrays.
+ (TARGET_INIT_BUILTINS, TARGET_EXPAND_BUILTIN): Undef / define.
+ (print_operand): Add 'N' modifier.
+ * sh.h (VECTOR_MODE_SUPPORTED_P): Add SHmedia vector modes.
+ (EXTRA_CONSTRAINT_U, EXTRA_CONSTRAINT_W): New macros.
+ (EXTRA_CONSTRAINT): Add 'U' and 'W' cases.
+ (CONST_COSTS): Add special case for SHmedia AND.
+ (PREDICATE_CODES): Add and_operand, arith_reg_dest,
+ extend_reg_operand, extend_reg_or_0_operand, mextr_bit_offset,
+ sh_const_vec, sh_1el_vec, sh_rep_vec, zero_vec_operand.
+ target_operand can also be const or unspec.
+ * sh.md (UNSPEC_INIT_TRAMP, UNSPEC_FCOSA UNSPEC_FSRRA): New constants.
+ (UNSPEC_FSINA, UNSPEC_NSB, UNSPEC_ALLOCO): Likewise.
+ (attribute type): Add new types.
+ (anddi3): Add splitter.
+ (movdi_const_16bit+1): Add code to handle vector constants and
+ bitmasks efficiently.
+ (shori_media): Have generator function made.
+ (movv8qi, movv8qi_i, movv8qi_i+1, movv8qi_i+2): New patterns.
+ (movv8qi_i+3, movv2hi, movv2hi_i, movv4hi, movv4hi_i): Likewise.
+ (movv2si, movv2si_i, absv2si2, absv4hi2, addv2si3, addv4hi3): Likewise.
+ (ssaddv2si3, usaddv8qi3, ssaddv4hi3, negcmpeqv8qi): Likewise.
+ (negcmpeqv2si, negcmpeqv4hi, negcmpgtuv8qi, negcmpgtv2si): Likewise.
+ (negcmpgtv4hi, mcmv, mcnvs_lw, mcnvs_wb, mcnvs_wub): Likewise.
+ (mextr_rl, mextr_lr, mextr1, mextr2, mextr3, mextr4, mextr5): Likewise.
+ (mextr6, mextr7, mmacfx_wl, mmacfx_wl_i, mmacnfx_wl): Likewise.
+ (mmacnfx_wl_i, mulv2si3, mulv4hi3, mmulfx_l, mmulfx_w): Likewise.
+ (mmulfxrp_w, mmulhi_wl, mmullo_wl, mmul23_wl, mmul01_wl): Likewise.
+ (mmulsum_wq, mmulsum_wq_i, mperm_w, mperm_w_little): LIkewise.
+ (mperm_w_big, mperm_w0, msad_ubq, msad_ubq_i, mshalds_l): Likewise.
+ (mshalds_w, ashrv2si3, ashrv4hi3, mshards_q, mshfhi_b): Likewise.
+ (mshflo_b, mshf4_b, mshf0_b, mshfhi_l, mshflo_l, mshf4_l): Likewsie.
+ (mshf0_l, mshfhi_w, mshflo_w, mshf4_w, mshf0_w, mshfhi_l_di): Likewise.
+ (mshfhi_l_di_rev, mshflo_l_di, mshflo_l_di_rev): Likewise.
+ (mshflo_l_di_x, mshflo_l_di_x_rev, ashlv2si3, ashlv4hi3): Likewise.
+ (lshrv2si3, lshrv4hi3, subv2si3, subv4hi3, sssubv2si3): Likewise.
+ (ussubv8qi3, sssubv4hi3, fcosa_s, fsina_s, fipr, fsrra_s): Likewise.
+ (ftrv): Likewise.
+
+ (fpu_switch+1, fpu_switch+2): Remove constraint.
+
+2002-07-01 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree.c (build_function_type_list): Update function comment.
+ Rename first argument to return_type.
+
+2002-07-01 Neil Booth <neil@daikokuya.co.uk>
+
+ * Makefile.in: Remove all trace of tradcpp.c, tradcpp.h,
+ tradcif.y and related files.
+
+2002-07-01 Neil Booth <neil@daikokuya.co.uk>
+
+ * cpptrad.c (skip_whitespace): Pass pointer to prior char.
+
+2002-07-01 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * mips.h (FUNCTION_ARG_REGNO_P): Fix parentheses.
+
+See ChangeLog.7 for earlier changes.
diff --git a/contrib/gcc/ChangeLog.0 b/contrib/gcc/ChangeLog.0
index 5cd3fdb..4ed0652 100644
--- a/contrib/gcc/ChangeLog.0
+++ b/contrib/gcc/ChangeLog.0
@@ -2670,7 +2670,7 @@ Thu Jun 4 01:26:57 1998 Craig Burley <burley@gnu.org>
Thu Jun 4 00:54:21 1998 Graham <grahams@rcp.co.uk>
- * loop.c (check_dbra_loop): Initialise final_value before
+ * loop.c (check_dbra_loop): Initialize final_value before
normalizing the loop.
Wed Jun 3 20:00:04 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
@@ -4435,7 +4435,7 @@ Sun May 3 23:57:25 1998 Robert Lipe <robertl@dgii.com>
Sun May 3 13:51:34 1998 Richard Henderson <rth@cygnus.com>
- Support for official Sparc V9 ABI:
+ Support for official SPARC V9 ABI:
* sparc.c (sparc_override_options): Force stack bias off for !arch64.
Care for flag_pcc_struct_return default.
(output_move_quad): Rewrite to move by halves on v9 and in the
@@ -6574,8 +6574,8 @@ Wed Mar 11 12:05:20 1998 Teemu Torma <tot@trema.com>
* gthr.h: Changed the comment about return values.
* gthr-solaris.h (__gthread_once): Do not use errno; return the
error number instead of -1.
- (__gthread_key_create): Any non-zero return value is an error.
- * libgcc2.c (eh_context_initialize): Check for non-zero return
+ (__gthread_key_create): Any nonzero return value is an error.
+ * libgcc2.c (eh_context_initialize): Check for nonzero return
value from __gthread_once.
Check that the value of get_eh_context was really changed.
@@ -10440,7 +10440,7 @@ Tue Nov 4 20:36:50 1997 Richard Henderson (rth@cygnus.com)
* alpha.c (alpha_handle_trap_shadows): Init sum.defd to zero.
- * alpha.md (attr trap): Make TRAP_YES non-zero for sanity's sake.
+ * alpha.md (attr trap): Make TRAP_YES nonzero for sanity's sake.
Tue Nov 4 18:49:42 1997 Jeffrey A Law (law@cygnus.com)
@@ -12000,7 +12000,7 @@ Wed Sep 10 11:49:20 1997 Jason Merrill <jason@yorick.cygnus.com>
EXCEPTION_SECTION, mark the start of the frame info with a
collectible tag.
* collect2.c (frame_tables): New list.
- (is_ctor_dtor): Recognise frame entries.
+ (is_ctor_dtor): Recognize frame entries.
(scan_prog_file): Likewise.
(main): Pass -fno-exceptions to sub-compile. Also do collection
if there are any frame entries.
diff --git a/contrib/gcc/ChangeLog.1 b/contrib/gcc/ChangeLog.1
index 0530536..ef67034 100644
--- a/contrib/gcc/ChangeLog.1
+++ b/contrib/gcc/ChangeLog.1
@@ -469,7 +469,7 @@ Sun May 2 15:16:42 1999 Joseph S. Myers <jsm28@cam.ac.uk>
(ASSEMBLER_DIALECT): Define.
(CONDITIONAL_REGISTER_USAGE): Rename floating point registers if
required for the UNIX assembler.
- (ASM_OUTPUT_INT): Remove. The compiler will synthesise it.
+ (ASM_OUTPUT_INT): Remove. The compiler will synthesize it.
(ASM_OUTPUT_ADDR_VEC_PROLOGUE): Remove.
(ASM_OPEN_PAREN, ASM_CLOSE_PAREN): Change to "[" and "]".
(TRAMPOLINE_TEMPLATE): Use ASM_OUTPUT_SHORT.
@@ -1732,7 +1732,7 @@ Fri Apr 9 10:40:10 1999 Kaveh R. Ghazi <ghazi@snafu.rutgers.edu>
Thu Apr 8 19:20:18 1999 Jeffrey A Law (law@cygnus.com)
* expr.c (expand_expr, case ARRAY_REF, COMPONENT_REF, BIT_FIELD_REF):
- Do not try to optimize a aggregate address which has VOIDmode.
+ Do not try to optimize an aggregate address which has VOIDmode.
Mirrors March 23 change to expand_assignment.
* flow.c (delete_unreachable_blocks): Do not require EDGE_FALLTHRU
@@ -2152,7 +2152,7 @@ Fri Apr 2 12:58:26 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
Fri Apr 2 12:19:17 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
* config/c4x/c4x.md (*db): Enable pattern if TARGET_LOOP_UNSIGNED
- is non-zero.
+ is nonzero.
(movstrqi_small, movstrqi_large, *cmpstrqi): Add + modifier to address
register constraints.
(*movhi_clobber+1): Modify splitter pattern to handle destination
@@ -2625,7 +2625,7 @@ Tue Mar 23 23:32:14 1999 Jeffrey A Law (law@cygnus.com)
left using a variable rotate right. Provide anonymous pattern for
rotate left by a constant value.
- * expr.c (expand_assignment): Do not try to optimize a aggregate
+ * expr.c (expand_assignment): Do not try to optimize an aggregate
address which has VOIDmode.
Tue Mar 23 22:51:48 1999 Mumit Khan <khan@xraylith.wisc.edu>
@@ -4287,7 +4287,7 @@ Thu Feb 25 21:52:54 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
in registers.
* expr.h (PRETEND_OUTGOING_VARARGS_NAMED): Provide default definition.
- * function.c (assign_parms): Honour PRETEND_OUTGOING_VARARGS_NAMED.
+ * function.c (assign_parms): Honor PRETEND_OUTGOING_VARARGS_NAMED.
* calls.c (expand_call): Likewise.
* sh.c (sh_expand_prologue): For TARGET_HITACHI, don't push varargs /
@@ -4454,7 +4454,7 @@ Mon Feb 22 19:36:33 1999 Andrew Cagney <cagney@b1.cygnus.com>
StrongARM.
(arm_is_6_or_7): New variable: true iff the target processor is an
ARM6 or and ARM7.
- (arm_select): Fields reorganised.
+ (arm_select): Fields reorganized.
(struct processors): processor_type field removed.
(all_procs): Remove.
(all_cores): New array: Definitions of all known ARM cpu cores.
@@ -5184,10 +5184,10 @@ Mon Feb 8 21:31:06 1999 Richard Henderson <rth@cygnus.com>
(scan_loop): ... moved out of here. Always initialize.
Test loop_has_call instead of reg_single_usage not zero.
Free reg_single_usage after strength reduction.
- (count_loop_regs_set): Assume single_usage non-zero.
+ (count_loop_regs_set): Assume single_usage nonzero.
(combine_givs_used_by_other): Test reg_single_usage.
(load_mems_and_recount_loop_regs_set): Remove reg_single_usage
- as a parameter. Assume non-zero.
+ as a parameter. Assume nonzero.
1999-02-08 Zack Weinberg <zack@midnite.ec.rhno.columbia.edu>
@@ -7018,7 +7018,7 @@ Thu Jan 7 03:08:17 1999 Richard Henderson <rth@cygnus.com>
Thu Jan 7 03:03:42 1999 Stan Cox <scox@cygnus.com>
Richard Henderson <rth@cygnus.com>
- Support for Hypersparc and Sparclite86x:
+ Support for HyperSPARC and SPARClite86x:
* sparc.h (TARGET_CPU_hypersparc, TARGET_CPU_sparclite86x): New.
(CPP_CPU32_DEFAULT_SPEC): Fix up for the new targets.
(ASM_CPU32_DEFAULT_SPEC): Likewise.
@@ -10282,7 +10282,7 @@ Wed Oct 28 16:46:07 1998 Andreas Schwab <schwab@issan.cs.uni-dortmund.de>
Wed Oct 28 14:06:49 1998 Jim Wilson <wilson@cygnus.com>
* dwarfout.c (dwarfout_file_scope_decl): If DECL_CONTEXT, don't abort
- if pending_types is non-zero.
+ if pending_types is nonzero.
(dwarfout_finish): Verify pending_types is zero before finishing.
Wed Oct 28 10:29:09 1998 Nick Clifton <nickc@cygnus.com>
@@ -11967,7 +11967,7 @@ Fri Oct 9 14:26:44 1998 Jeffrey A Law (law@cygnus.com)
Fri Oct 9 11:44:47 1998 David Edelsohn <edelsohn@gnu.org>
- * loop.c (insert_bct): Ensure loop_iteration_var non-zero before use.
+ * loop.c (insert_bct): Ensure loop_iteration_var nonzero before use.
Thu Oct 8 21:59:47 1998 Dave Brolley <brolley@cygnus.com>
@@ -13059,7 +13059,7 @@ Sat Sep 19 12:05:09 1998 Richard Henderson <rth@cygnus.com>
Sat Sep 19 07:33:36 1998 Richard Earnshaw (rearnsha@arm.com)
* arm.c (add_constant): New parameter address_only, change caller.
- Set it non-zero if taking the address of an item in the pool.
+ Set it nonzero if taking the address of an item in the pool.
(arm_reorg): Handle cases where we need the address of an item in
the pool.
@@ -13371,7 +13371,7 @@ Sun Sep 13 08:13:39 1998 Ben Elliston <bje@cygnus.com>
runtime library will do this.
* objc/Make-lang.in: Do not build the runtime library or install
- the Objective C header files. The Makefile for the runtime
+ the Objective-C header files. The Makefile for the runtime
library will do this.
* objc/Makefile.in (all.indirect): Only build the front-end.
@@ -15068,7 +15068,7 @@ Mon Aug 10 19:02:55 1998 John Carr <jfc@mit.edu>
Mon Aug 10 04:28:13 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
Richard Henderson <rth@cygnus.com>
- Rewrite Sparc backend for better code generation and
+ Rewrite SPARC backend for better code generation and
improved sparc64 support.
* config/sparc/sp64-elf.h: Set JUMP_TABLES_IN_TEXT_SECTION to
zero.
@@ -15155,7 +15155,7 @@ Mon Aug 10 04:28:13 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
(define_function_unit ieu1): New, executes compare, call, and
uncond_branch type insns.
(define_function_units for type fdivs, fdivd, fsqrt): These
- execute in the fpu multiply unit not the adder on UltraSparc.
+ execute in the fpu multiply unit not the adder on UltraSPARC.
(define_expand cmpdi): Disallow TARGET_V8PLUS.
(define_insn cmpsi_insn): Rename to cmpsi_insn_sp32.
(define_insn cmpsi_insn_sp64): New, same as sp32 variant except it
@@ -15570,7 +15570,7 @@ Mon Jul 27 14:22:36 1998 Dave Brolley <brolley@cygnus.com>
Mon Jul 27 11:43:54 1998 Stan Cox <scox@cygnus.com>
- * longlong.h (count_leading_zeros): Sparclite scan instruction was
+ * longlong.h (count_leading_zeros): SPARClite scan instruction was
being invoked incorrectly.
* i386.c (ix86_prologue): Added SUBTARGET_PROLOGUE invocation.
diff --git a/contrib/gcc/ChangeLog.2 b/contrib/gcc/ChangeLog.2
index e49d764..a7cff36 100644
--- a/contrib/gcc/ChangeLog.2
+++ b/contrib/gcc/ChangeLog.2
@@ -262,7 +262,7 @@ Fri Dec 24 12:34:26 1999 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
Thu Dec 23 23:15:22 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
- * reload1.c (emit_input_reload_insns): Restore old behaviour
+ * reload1.c (emit_input_reload_insns): Restore old behavior
wrt. 'special' reloads.
1999-12-23 Zack Weinberg <zack@wolery.cumb.org>
@@ -1531,7 +1531,7 @@ Thu Dec 2 18:59:48 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
1999-12-02 Nick Clifton <nickc@cygnus.com>
- * config/fp-bit.c: Initialise all fields of the NAN
+ * config/fp-bit.c: Initialize all fields of the NAN
constants.
* c-lex.c (check_newline): Pass pragma_getc and pragma_ungetc
@@ -2434,10 +2434,10 @@ Thu Nov 18 11:10:03 1999 Jan Hubicka <hubicka@freesoft.cz>
1999-11-18 Nick Clifton <nickc@cygnus.com>
- * toplev.c (main): Correctly detect an unrecognised option.
+ * toplev.c (main): Correctly detect an unrecognized option.
* cppinit.c (cpp_handle_option): Do not claim to have consumed
- a -f option if it has not been recognised.
+ a -f option if it has not been recognized.
Thu Nov 18 00:59:11 1999 Michael Gschwind <mikeg@alagoas.watson.ibm.com>
@@ -3184,13 +3184,13 @@ Wed Nov 3 15:11:27 1999 David S. Miller <davem@redhat.com>
* config/sparc/sparc.md: Remove insn type fpsqrt, add fpsqrts
and fpsqrtd. Use them and create fdiv function unit to more
- accurately represent fpu sqrt pipeline semantics on UltraSparc.
+ accurately represent fpu sqrt pipeline semantics on UltraSPARC.
* config/sparc/sparc.c: Account for fpsqrt{s,d} changes.
Wed Nov 3 15:11:27 1999 Matteo Frigo <athena@fftw.org>
* config/sparc/sparc.md: Adjust FADD/FMUL result latencies to
- 3 on UltraSparc.
+ 3 on UltraSPARC.
* config/sparc/sparc.c (ultra_schedule_insn): Insert launched
insn into ready list, do not use just a raw swap.
@@ -3567,7 +3567,7 @@ Sat Oct 30 14:31:48 1999 Richard Henderson <rth@cygnus.com>
(ggc_alloc_obj): Likewise. Use a different pattern than poison_pages.
(ggc_collect): Poison before sweeping.
* ggc-simple.c: Update pre-function commentary.
- (ggc_alloc_obj): Poison non-zeroed memory.
+ (ggc_alloc_obj): Poison nonzeroed memory.
Sat Oct 30 14:28:52 1999 Mark Mitchell <mark@codesourcery.com>
@@ -4002,7 +4002,7 @@ Mon Oct 18 21:16:06 1999 Fred Fish <fnf@be.com>
Thu Oct 28 10:00:48 1999 Nick Clifton <nickc@cygnus.com>
- * config/arm/arm.c: Initialise arm_structure_size_boundary to
+ * config/arm/arm.c: Initialize arm_structure_size_boundary to
DEFAULT_STRUCTURE_SIZE_BOUNDARY.
* config/arm/arm.h (DEFAULT_STRUCTURE_SIZE_BOUNDARY): Define
to the value 32 if it has not already been defined.
@@ -4782,7 +4782,7 @@ Tue Oct 19 15:26:11 1999 Richard Earnshaw (rearnsha@arm.com)
Tue Oct 19 14:01:34 1999 Nick Clifton <nickc@cygnus.com>
* toplev.c (main): Do not generate an error message if an
- unrecognised command line switch is recognisable by another
+ unrecognized command line switch is recognisable by another
language. If extra_warnings are enabled, then generate a
warning message instead.
@@ -4960,7 +4960,7 @@ Sat Oct 16 13:42:29 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
Sat Oct 16 13:37:46 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * config/c4x/c4x.md (movstrqi_small): Utilise parallel move
+ * config/c4x/c4x.md (movstrqi_small): Utilize parallel move
instructions.
Sat Oct 16 13:26:47 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
@@ -6509,15 +6509,15 @@ Sat Sep 25 09:03:17 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
Sat Sep 25 13:42:15 1999 Nick Clifton <nickc@cygnus.com>
* varasm.c (asm_emit_uninitialised): New function: Generate
- the assembler statements necessary to declare an uninitialised
+ the assembler statements necessary to declare an uninitialized
variable.
- (ASM_EMIT_LOCAL): New macro: Emit a local, uninitialised
+ (ASM_EMIT_LOCAL): New macro: Emit a local, uninitialized
variable.
(ASM_EMIT_BSS): New macro: Emit an entry in the bss section.
(ASM_EMIT_COMMON): New macro: Emit an entry in the common
section.
(assemble_variable): Use asm_emit_uninitialised to emit an
- uninitialised variable.
+ uninitialized variable.
Fri Sep 24 17:10:56 1999 Nick Clifton <nickc@cygnus.com>
@@ -8316,7 +8316,7 @@ Thu Sep 9 13:46:06 1999 Geoffrey Keating <geoffk@cygnus.com>
* cppexp.c (cpp_lex): Handle `defined (xxx)' for poisoned xxx.
Include cpphash.h.
* cpphash.c (special_symbol): Handle plain `xxx' for poisoned xxx.
- * cpplib.c (do_define): Generalise to handle poisoned definitions,
+ * cpplib.c (do_define): Generalize to handle poisoned definitions,
redefining poisoned identifiers, etc.
(do_undef): Don't allow poisoned identifiers to be undefined.
(do_pragma): Add #pragma poison.
@@ -8325,7 +8325,7 @@ Thu Sep 9 13:46:06 1999 Geoffrey Keating <geoffk@cygnus.com>
* cccp.c: Add T_POISON node type.
(special_symbol): Handle `defined(xxx)' and plain `xxx' for
poisoned xxx.
- (do_define): Generalise to handle poisoned definitions,
+ (do_define): Generalize to handle poisoned definitions,
redefining poisoned identifiers, etc.
(do_undef): Don't allow poisoned identifiers to be undefined.
(do_pragma): Add #pragma poison.
@@ -9759,7 +9759,7 @@ Sun Aug 29 04:30:52 1999 John Wehle (john@feith.com)
All uses updated.
(prescan_loop, strength_reduce): New argument loop_info. All callers
updated.
- (scan_loop): New variable loop_info, initialise to address of
+ (scan_loop): New variable loop_info, initialize to address of
this_loop_info.
(prescan_loop): Set loop_info->vtop if find NOTE_INSN_LOOP_VTOP.
Delete variable loop_has_multiple_exit targets and replace with
@@ -14093,7 +14093,7 @@ Wed Jun 2 12:25:55 1999 Richard Henderson <rth@cygnus.com>
Wed Jun 2 08:42:55 1999 Nick Clifton <nickc@cygnus.com>
- * config/arm/tcoff.h (USER_LABEL_PREFIX): Synchronise with
+ * config/arm/tcoff.h (USER_LABEL_PREFIX): Synchronize with
definition in config/arm/coff.h
* config/arm/coff.h: Add comment about USER_LABEL_PREFIX.
diff --git a/contrib/gcc/ChangeLog.3 b/contrib/gcc/ChangeLog.3
index c3a4461..067d9ad 100644
--- a/contrib/gcc/ChangeLog.3
+++ b/contrib/gcc/ChangeLog.3
@@ -1353,7 +1353,7 @@ Wed Jun 7 20:34:33 2000 Denis Chertykov <denisc@overta.ru>
* c-common.h (c_language_kind): New type.
(c_language): New variab.e
* c-common.c (lang_get_alias_set): Don't put structures in
- non-zero alias sets in C++.
+ nonzero alias sets in C++.
* c-decl.c (c_language): Define it.
* c-lex.c (doing_objc_thang): Remove.
* c-tree.h (doing_objc_thang): Make it a macro.
@@ -1538,7 +1538,7 @@ Mon Jun 5 06:46:28 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
2000-06-04 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * Makefile.in (intl.*): Honor non-zero exit codes in the intl
+ * Makefile.in (intl.*): Honor nonzero exit codes in the intl
subdir.
2000-06-03 Geoff Keating <geoffk@cygnus.com>
@@ -2036,7 +2036,7 @@ Sun May 28 18:37:07 2000 Clinton Popetz <cpopetz@cygnus.com>
Sun May 28 23:26:59 2000 Philippe De Muyter <phdm@macqel.be>
- * mklibgcc.in (all): Variable initialised to `libgcc'.
+ * mklibgcc.in (all): Variable initialized to `libgcc'.
2000-05-28 Gabriel Dos Reis <gdr@codesourcery.com>
@@ -2088,10 +2088,10 @@ Sun May 28 23:26:59 2000 Philippe De Muyter <phdm@macqel.be>
* regclass.c [CLASS_CANNOT_CHANGE_SIZE]
(class_can_change_size): New variable.
(reg_changes_size): New variable.
- (init_reg_sets_1): Initialise class_can_change_size.
+ (init_reg_sets_1): Initialize class_can_change_size.
(record_operand_costs): Remove subreg_changes_size.
Don't pass it around. Instead update reg_changes_size.
- (regclass): Initialise and free reg_changes_size. If a register
+ (regclass): Initialize and free reg_changes_size. If a register
changes size, don't preference it to a class that contains
registers that can't change size.
(record_reg_classes): Don't look at subreg_changes_size.
@@ -2161,7 +2161,7 @@ Sun May 28 23:26:59 2000 Philippe De Muyter <phdm@macqel.be>
* reload.c (get_secondary_mem): Don't widen floating-point modes.
- * combine.c (subst): Honour CLASS_CANNOT_CHANGE_SIZE when
+ * combine.c (subst): Honor CLASS_CANNOT_CHANGE_SIZE when
substituting the REG in a (subreg:X (reg:Y ...)).
2000-05-28 Neil Booth <NeilB@earthling.net>
@@ -2174,7 +2174,7 @@ Sun May 28 23:26:59 2000 Philippe De Muyter <phdm@macqel.be>
2000-05-28 Neil Booth <NeilB@earthling.net>
- * cpplex.c (_cpp_init_toklist): No comment space to initialise.
+ * cpplex.c (_cpp_init_toklist): No comment space to initialize.
(_cpp_free_toklist): No comment space to free.
(expand_comment_space): Remove.
(save_comment_space): Place the comment in the current token and
@@ -2340,7 +2340,7 @@ Sat May 27 11:01:27 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
boolean_operator for the boolean patterns without NOTs.
* config/rs6000/rs6000.c (reg_or_logical_cint_operand): Rename
- from reg_or_u_cint_operand. Change comment and behaviour.
+ from reg_or_u_cint_operand. Change comment and behavior.
(logical_operand): Clean up, add assertion.
(non_logical_cint_operand): Also check for
reg_or_logical_cint_operand.
@@ -3133,7 +3133,7 @@ Fri May 19 06:49:35 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
2000-05-18 Nick Clifton <nickc@cygnus.com>
* config/arm/unknown-elf.h (UNIQUE_SECTION): Place constant,
- uninitialised data in .rodata not .bss, and do not interpret an
+ uninitialized data in .rodata not .bss, and do not interpret an
error in the initialisation value as meaning that the variable
should be placed in the .bss section.
@@ -3225,7 +3225,7 @@ Thu May 18 12:10:18 2000 Philippe De Muyter <phdm@macqel.be>
2000-05-18 Neil Booth <NeilB@earthling.net>
- * cppinit.c (cpp_reader_init): Initialise col_adjust and
+ * cppinit.c (cpp_reader_init): Initialize col_adjust and
default tab stop size.
(no_num, OPT_ftabstop): New.
(handle_option): Handle "ftabstop=" command-line option.
@@ -7957,7 +7957,7 @@ Wed Apr 5 18:03:31 2000 Toshiyasu Morita (toshi.morita@sega.com)
2000-04-05 Chris Demetriou <cgd@netbsd.org>
* mips.h (MASK_DEBUG_A, MASK_DEBUG_B, MASK_DEBUG_C): Zero the
- remaining non-zero debugging masks.
+ remaining nonzero debugging masks.
Wed Apr 5 09:44:07 2000 Jeffrey A Law (law@cygnus.com)
@@ -10256,7 +10256,7 @@ Thu Mar 16 02:14:16 2000 Hans-Peter Nilsson <hp@bitrange.com>
2000-02-03 Geoff Keating <geoffk@cygnus.com>
* rs6000.c (rs6000_sr_alias_set): New variable.
- (rs6000_override_options): Initialise rs6000_sr_alias_set.
+ (rs6000_override_options): Initialize rs6000_sr_alias_set.
(rs6000_emit_stack_tie): New function.
(rs6000_emit_allocate_stack): Specify RTX_FRAME_RELATED_P
in a way that dwarf2out can understand.
@@ -10804,8 +10804,8 @@ Wed Feb 23 13:00:06 CET 2000 Jan Hubicka <jh@suse.cz>
2000-03-14 Nick Clifton <nickc@cygnus.com>
* gcc.c (do_spec_1): Catch the case where %* is used in a
- substitution pattern, but it has not been initialised.
- Issue a meaningful error message if an unrecognised operator
+ substitution pattern, but it has not been initialized.
+ Issue a meaningful error message if an unrecognized operator
is encountered in a spec string.
2000-03-14 Richard Earnshaw <rearnsha@arm.com>
@@ -15005,7 +15005,7 @@ Mon Jan 24 16:50:08 MET 2000 Jan Hubicka <jh@suse.cz>
* basic-block.h (struct loops): New field `levels'.
* flow.c (flow_loops_level_compute): Traverse all outer loops.
- (flow_loop_level_compute): Initialise level to 1.
+ (flow_loop_level_compute): Initialize level to 1.
(flow_loops_find): Set loops->levels.
(flow_loops_dump): Print loops->levels.
@@ -15047,7 +15047,7 @@ Mon Jan 24 16:50:08 MET 2000 Jan Hubicka <jh@suse.cz>
2000-01-22 Alan Modra <alan@SPRI.Levels.UniSA.Edu.Au>
- * config/elfos.h (UNIQUE_SECTION): Restore uninitialised data
+ * config/elfos.h (UNIQUE_SECTION): Restore uninitialized data
section naming to that prior to 2000-01-07 patch.
* config/mips/elf.h (UNIQUE_SECTION): Ditto.
* config/mips/elf64.h (UNIQUE_SECTION): Ditto.
@@ -15242,7 +15242,7 @@ Wed Jan 19 19:12:36 2000 J"orn Rennecke <amylaar@cygnus.co.uk>
* loop.c (current_loop_info): Renamed from loop_info_data
and changed to a pointer.
(loop_optimize): Allocate loop_info structure for each loop
- and initialise to zero.
+ and initialize to zero.
(scan_loop): Set current_loop_info.
* unroll.c (loop_iterations): Don't abort if REG_USERVAR_P set
@@ -15281,7 +15281,7 @@ Wed Jan 19 19:12:36 2000 J"orn Rennecke <amylaar@cygnus.co.uk>
(expand_end_bindings): Likewise.
(expand_decl): Likewise. Consult optimize not obey_regdecls.
* toplev.c (obey_regdecls): Remove.
- (rest_of_compilation): Don't set it. Kill stupid in favour of
+ (rest_of_compilation): Don't set it. Kill stupid in favor of
flow1, local-alloc, and reload.
(main): Don't set obey_regdecls.
@@ -16500,25 +16500,25 @@ Thu Jan 6 13:44:59 CET 2000 Jan Hubicka <jh@suse.cz>
uninitialized data decls.
* config/i386/winnt.c (i386_pe_unique_section): Cope with
- being called for uninitialised data.
+ being called for uninitialized data.
* config/i386/interix.c (i386_pe_unique_section): Cope with
- being called for uninitialised data.
+ being called for uninitialized data.
* config/mips/elf.h (UNIQUE_SECTION): Cope with being called
- for uninitialised data.
+ for uninitialized data.
* config/mips/elf64.h (UNIQUE_SECTION): Cope with being called
- for uninitialised data.
+ for uninitialized data.
* config/mips/iri6gld.h (UNIQUE_SECTION): Cope with being called
- for uninitialised data.
+ for uninitialized data.
* config/arm/unknown-elf.h (IN_NAMED_SECTION): Define.
(UNIQUE_SECTION_P): Always generate a unique section if
flag_data_sections is true.
(UNIQUE_SECTION): Also generate unique sections for
- uninitialised data.
+ uninitialized data.
(ASM_OUTPUT_ALIGNED_BSS): Redefine to use named_section().
(ASM_OUTPUT_ALIGNED_DECL_LOCAL): Redefine to use
named_section().
@@ -16611,7 +16611,7 @@ Tue Jan 4 22:30:16 2000 Jeffrey A Law (law@cygnus.com)
2000-01-05 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
- * config/c4x/c4x.h (IS_XXX_REG, IS_XXX_REGNO): Swap behaviour of
+ * config/c4x/c4x.h (IS_XXX_REG, IS_XXX_REGNO): Swap behavior of
macros so that they're consistent with their names.
* config/c4x/c4x.c (IS_XXX_REG, IS_XXX_REGNO): Likewise.
* config/c4x/c4x.md (IS_XXX_REG, IS_XXX_REGNO): Likewise.
diff --git a/contrib/gcc/ChangeLog.4 b/contrib/gcc/ChangeLog.4
index 129c1f9..ac0f7e0 100644
--- a/contrib/gcc/ChangeLog.4
+++ b/contrib/gcc/ChangeLog.4
@@ -142,7 +142,7 @@
* c-parse.in (select_or_iter_stmt): Use truthvalue_conversion
on the condition of a FOR statement, so that it gets typechecked
- and optimised.
+ and optimized.
2000-12-29 Alexandre Oliva <aoliva@redhat.com>
@@ -300,7 +300,7 @@
scavenging it.
* dwarf2out_frame_debug_expr: Allow the (scratch) frame
- pointer to be initialised from the stack pointer plus a
+ pointer to be initialized from the stack pointer plus a
constant.
2000-12-22 Bernd Schmidt <bernds@redhat.com>
@@ -355,7 +355,7 @@
* reload.c (update_auto_inc_notes): New, broken out from ...
(find_reloads_address_1): ... use here, also correct possible
- use of uninitialised reloadnum.
+ use of uninitialized reloadnum.
2000-12-21 David O'Brien <obrien@FreeBSD.org>
@@ -1235,7 +1235,7 @@ Mon Dec 11 13:51:09 2000 Jeffrey A Law (law@cygnus.com)
arm_compute_save_reg_mask.
(arm_expand_prologue): Use arm_current_func_type and
arm_compute_save_reg_mask.
- (arm_init_machine_status): Initialise func_type field, if
+ (arm_init_machine_status): Initialize func_type field, if
necessary.
(thumb_expand_prologue): Use arm_current_func_type.
(output_thumb_prologue): Use arm_current_func_type.
@@ -2120,7 +2120,7 @@ Tue Dec 5 20:09:14 2000 Jeffrey A Law (law@cygnus.com)
(expand_builtin_strrchr): Use it.
(builtin_memset_read_str): New function.
(expand_builtin_memset): Use target_char_cast.
- Try to optimize memset with second argument non-zero using
+ Try to optimize memset with second argument nonzero using
store_by_pieces.
2000-11-30 Marek Michalkiewicz <marekm@linux.org.pl>
@@ -2923,9 +2923,9 @@ Sun Nov 26 10:02:37 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
(cxx_target_objs): Substitute in the makefile.
* configure: Regenerate.
- * Makefile.in (C_TARGET_OBJS): Define and initialise from
+ * Makefile.in (C_TARGET_OBJS): Define and initialize from
c_target_objs.
- (CXX_TARGET_OBJS): Define and initialise from
+ (CXX_TARGET_OBJS): Define and initialize from
cxx_target_objs.
(C_AND_OBJC_OBJS): Include C_TARGET_OBJS.
@@ -3046,7 +3046,7 @@ Fri Nov 24 19:48:09 2000 J"orn Rennecke <amylaar@redhat.com>
2000-11-23 Graham Stott <grahams@redhat.com>
- * cse.c (cse_insn): Initialise all regcost variables.
+ * cse.c (cse_insn): Initialize all regcost variables.
Fix a typo add missing '='.
Only compare costs if there is a replacement insn.
@@ -3247,7 +3247,7 @@ Wed Nov 22 00:52:55 2000 J"orn Rennecke <amylaar@redhat.com>
2000-11-21 Jakub Jelinek <jakub@redhat.com>
- * configure.in (HAVE_AS_DWARF2_DEBUG_LINE): Sparc has .file/.loc
+ * configure.in (HAVE_AS_DWARF2_DEBUG_LINE): SPARC has .file/.loc
support in as as well.
* configure: Regenerate.
@@ -3811,7 +3811,7 @@ Tue Nov 14 12:34:56 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
2000-11-14 Jakub Jelinek <jakub@redhat.com>
- * reload1.c (emit_input_reload_insns): Honour forcing of constants
+ * reload1.c (emit_input_reload_insns): Honor forcing of constants
into memory by PREFERRED_RELOAD_CLASS NO_REGS.
2000-11-14 Michael Matz <matzmich@cs.tu-berlin.de>
@@ -5216,13 +5216,13 @@ Tue Oct 31 15:33:27 2000 J"orn Rennecke <amylaar@redhat.com>
hash table.
* cppinit.c (cpp_reader_init): Move cpp_init_completed test to top.
- Initialise various members of cpp_reader, memory pools, and the
+ Initialize various members of cpp_reader, memory pools, and the
special nodes.
(cpp_printer_init): Delete.
(cpp_cleanup): Update.
(struct builtin, builtin_array, initialize_builtins): Update for new
hashnode definition and builtin handling.
- (cpp_start_read, cpp_finish): Don't take or initialise a
+ (cpp_start_read, cpp_finish): Don't take or initialize a
printer. Update.
* cpplib.h (cpp_printer, cpp_toklist, CPP_DEFINED, BOL,
@@ -7147,7 +7147,7 @@ Fri Sep 29 13:20:42 MET DST 2000 Jan Hubicka <jh@suse.cz>
error" tests.
* cppinit.c (cpp_handle_option): Remove surplus \n.
* cpplex.c (ON_REST_ARG): Delete.
- (skip_block_comment): Initialise prevc.
+ (skip_block_comment): Initialize prevc.
(parse_args): Improve error messages.
(maybe_paste_with_next): Use CONTEXT_VARARGS rather
than ON_REST_ARG.
@@ -8018,14 +8018,14 @@ Mon 18-Sep-2000 19:21:35 BST Neil Booth <NeilB@earthling.net>
* cpplib.c (_cpp_check_directive, _cpp_check_linemarker):
New implementations.
(do_assert): Don't bother setting the answer's list's line.
- (cpp_push_buffer): Initialise new pfile and read_ahead members
+ (cpp_push_buffer): Initialize new pfile and read_ahead members
of struct cpp_buffer.
* cpplib.h (cppchar_t): New typedef.
(struct cpp_buffer): read_ahead, pfile and col_adjust are
new members.
(struct lexer_state): New structure that determines the state
- and behaviour of the lexer.
+ and behavior of the lexer.
(IN_DIRECTIVE, KNOWN_DIRECTIVE): New macros.
(struct cpp_reader): New member "state". Rename
multiline_string_line and multiline_string_column. Delete
@@ -8101,7 +8101,7 @@ Mon 18-Sep-2000 19:21:35 BST Neil Booth <NeilB@earthling.net>
2000-09-18 Joseph S. Myers <jsm28@cam.ac.uk>
- * c-common.c (check_format_types): Reorganise and clean up,
+ * c-common.c (check_format_types): Reorganize and clean up,
checking earlier for ERROR_MARKs and making cur_type into its
TYPE_MAIN_VARIANT where convenient.
@@ -8547,9 +8547,9 @@ Fri 15-Sep-2000 06:49:07 BST Neil Booth <NeilB@earthling.net>
* config/h8300.h (TARGET_MAC): New.
(TARGET_SWITCHES): Add -ms2600 and -mno-s2600.
(CONDITIONA_REGISTER_USAGE): Disable the mac register on any
- machine other than H8/S2600.
- * config/h8300.md: Accept mac instructions on the H8/S2600 instead
- of the H8/S2000.
+ machine other than H8S/2600.
+ * config/h8300.md: Accept mac instructions on the H8S/2600 instead
+ of the H8S/2000.
2000-09-14 Alexandre Oliva <aoliva@redhat.com>, Bernd Schmidt <bernds@redhat.co.uk>
@@ -9445,7 +9445,7 @@ Thu 07-Sep-2000 21:29:00 BST Neil Booth <NeilB@earthling.net>
yy_lim, or yy_get_token. Don't define get_directive_line if
USE_CPPLIB.
* c-common.h: Add multiple include guard. Define RID values
- for every keyword in C, C++, and Objective C. Put all the
+ for every keyword in C, C++, and Objective-C. Put all the
modifiers first.
(struct c_fileinfo, get_fileinfo, dump_time_statistics): New.
* c-decl.c (c_decode_option): Handle -lang-objc here.
@@ -11108,7 +11108,7 @@ Sun 20-Aug-2000 09:25:45 BST Neil Booth <NeilB@earthling.net>
instructions in it before checking for indirect jumps.
* ifcvt.c (find_if_block): Do not consider a THEN block that ends
- in a indirect jump as a potential for conditional execution.
+ in an indirect jump as a potential for conditional execution.
* d30v.h (d30v_init_expanders): Don't declare here.
* d30v-protos.h (d30v_init_expanders): Declare here with a valid
@@ -11556,7 +11556,7 @@ Mon Aug 14 18:51:44 2000 J"orn Rennecke <amylaar@cygnus.co.uk>
rather than DECL_OFFSET_ALIGN.
(place_field): Likewise.
* expmed.c (store_bit_field): Abort on align==0 to avoid
- antisocial machine behaviour.
+ antisocial machine behavior.
2000-08-12 Richard Henderson <rth@cygnus.com>
@@ -12487,7 +12487,7 @@ Thu Aug 3 15:53:03 2000 J"orn Rennecke <amylaar@cygnus.co.uk>
2000-08-03 Kazu Hirata <kazu@hxi.com>
* h8300.c: Fix a comment typo.
- * h8300.h (OK_FOR_U): Accept a 32-bit constant address on H8/S.
+ * h8300.h (OK_FOR_U): Accept a 32-bit constant address on H8S.
* jump.c: Fix formatting.
@@ -12911,7 +12911,7 @@ Mon Jul 31 20:35:50 2000 Denis Chertykov <denisc@overta.ru>
* h8300.h (MODES_TIEABLE_P): Accept a combination of QImode and
HImode on all architectures and a combination of HImode and SImode
- on H8/300H and H8/S.
+ on H8/300H and H8S.
* h8300.c (split_adds_subs): Rearrange code for conciseness.
@@ -13799,7 +13799,7 @@ Wed Jul 19 01:22:15 CEST 2000 Marc Espie <espie@cvs.openbsd.org>
2000-07-18 Jakub Jelinek <jakub@redhat.com>
- * calls.c (store_arg): Return non-zero if sibcall_failure is desired.
+ * calls.c (store_arg): Return nonzero if sibcall_failure is desired.
(expand_call): Adjust caller.
2000-07-17 Gabriel Dos Reis <gdr@codesourcery.com>
@@ -14169,7 +14169,7 @@ Fri Jul 14 10:25:53 2000 Clinton Popetz <cpopetz@cygnus.com>
* c-common.h (flag_digraphs): New.
* c-decl.c (c_decode_option): Set flag_digraphs as appropriate.
* c-lex.c (yylex): Use flag_digraphs to decide whether to
- honour digraphs.
+ honor digraphs.
2000-07-13 Zack Weinberg <zack@wolery.cumb.org>
@@ -14482,7 +14482,7 @@ Tue Jul 11 16:26:17 2000 Clinton Popetz <cpopetz@cygnus.com>
(handle_option): Set digraphs according to standard.
Merge OPT_lang_c89 handler with OPT_std_c89.
- * cpplex.c: (lex_line, can_paste): Honour digraphs in
+ * cpplex.c: (lex_line, can_paste): Honor digraphs in
accordance with the digraphs flag.
* cpplib.h: (struct cpp_options): New option digraphs.
diff --git a/contrib/gcc/ChangeLog.5 b/contrib/gcc/ChangeLog.5
index 40eccd1..9bd21c1 100644
--- a/contrib/gcc/ChangeLog.5
+++ b/contrib/gcc/ChangeLog.5
@@ -24,7 +24,7 @@
* gcc.c (process_command): Append a DIR_SEPARATOR to a path
specified by the -B switch, if doing so would create a valid
directory name.
- * doc/invoke.texi: Document changed behaviour of -B.
+ * doc/invoke.texi: Document changed behavior of -B.
2001-06-29 DJ Delorie <dj@redhat.com>
@@ -77,7 +77,7 @@ Fri Jun 29 12:27:24 2001 Jeffrey A Law (law@cygnus.com)
* config/arc/arc-protos.h, config/arc/arc.c, config/arc/arc.h
(arc_comp_type_attributes, arc_set_default_type_attributes,
COMP_TYPE_ATTRIBUTES, SET_DEFAULT_TYPE_ATTRIBUTES): Remove
- functions and macros with default behaviour.
+ functions and macros with default behavior.
* config/m32r/m32r-protos.h, config/m32r/m32r.c,
config/m32r/m32r.h (m32r_comp_type_attributes,
m32r_set_default_type_attributes, COMP_TYPE_ATTRIBUTES,
@@ -1070,7 +1070,7 @@ Mon Jun 18 15:43:10 CEST 2001 Jan Hubicka <jh@suse.cz>
2001-06-18 Ben Elliston <bje@redhat.com>
- * except.c (resolve_fixup_regions): Initialise "cleanup".
+ * except.c (resolve_fixup_regions): Initialize "cleanup".
2001-06-17 Neil Booth <neil@daikokuya.demon.co.uk>
@@ -1131,7 +1131,7 @@ Fri Jun 15 18:05:22 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
Fri Jun 15 19:35:38 CEST 2001 Jan Hubicka <jh@suse.cz>
- * optabs.c (expand_twoval_binop): Avoid undefined behaviour.
+ * optabs.c (expand_twoval_binop): Avoid undefined behavior.
2001-06-15 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
@@ -2885,7 +2885,7 @@ Thu May 24 15:56:48 CEST 2001 Jan Hubicka <jh@suse.cz>
2001-05-22 Richard Henderson <rth@redhat.com>
- * unwind-dw2-fde.c (__deregister_frame_info): Stubbify in favour of...
+ * unwind-dw2-fde.c (__deregister_frame_info): Stubbify in favor of...
(__deregister_frame_info_bases): New.
* unwind-dw2-fde.h: Declare it.
* libgcc-std.ver: Export it.
@@ -2903,7 +2903,7 @@ Thu May 24 15:56:48 CEST 2001 Jan Hubicka <jh@suse.cz>
* config/ia64/ia64.md (nonlocal_goto): Reverse label and frame pointer
parameters to __ia64_nonlocal_goto. Flag as NO_RETURN.
* config/ia64/ia64.c (ia64_expand_epilogue): Make sure we are issuing
- "r2" to the assembly file. Only issue allocs with non-zero parameters.
+ "r2" to the assembly file. Only issue allocs with nonzero parameters.
2001-05-22 Loren J. Rittle <ljrittle@acm.org>
David O'Brien <obrien@freebsd.org>
@@ -4498,7 +4498,7 @@ Fri May 4 13:10:03 CEST 2001 Jan Hubicka <jh@suse.cz>
(ix86_align_loops): Delete.
(ix86_align_jumps): Delete.
(override_options): Mark -malign-* as obsolete. Emulate their
- behaviour with the -falign-* options. Default -falign-* from
+ behavior with the -falign-* options. Default -falign-* from
the processor table.
* i386.h (FUNCTION_BOUNDARY): Define to 16; revert Richard Kenner's
patch of Wed May 2 13:09:36 2001.
@@ -5194,7 +5194,7 @@ Wed Apr 25 17:09:50 2001 J"orn Rennecke <amylaar@redhat.com>
2001-04-25 Jakub Jelinek <jakub@redhat.com>
* emit-rtl.c (subreg_hard_regno): Only do HARD_REGNO_MODE_OK check
- if check_mode is non-zero.
+ if check_mode is nonzero.
2001-04-25 Jakub Jelinek <jakub@redhat.com>
@@ -10795,7 +10795,7 @@ Fri Feb 9 15:05:27 2001 Christopher Faylor <cgf@cygnus.com>
* config/i386/i386.c (ix86_frame_pointer_required): New.
(ix86_setup_frame_addresses): New.
- (struct machine_funciton): Add accesses_prev_frame.
+ (struct machine_function): Add accesses_prev_frame.
* config/i386/i386.h (FRAME_POINTER_REQUIRED): Call
ix86_frame_pointer_required.
(SUBTARGET_FRAME_POINTER_REQUIRED): New.
@@ -11536,7 +11536,7 @@ Mon Jan 29 20:38:19 2001 Christopher Faylor <cgf@cygnus.com>
2001-01-27 Michael Sokolov <msokolov@ivan.Harhan.ORG>
- * fixproto: Correctly install synthesised unistd.h and stdlib.h when
+ * fixproto: Correctly install synthesized unistd.h and stdlib.h when
they didn't need fixing.
2001-01-27 Janis Johnson <janis@us.ibm.com>
@@ -11558,7 +11558,7 @@ Mon Jan 29 20:38:19 2001 Christopher Faylor <cgf@cygnus.com>
(really_start_incremental_init): Clear it.
(push_init_level): Save constructor_range_stack and clear it if
pushing explicit braces.
- (pop_init_level): abort if constructor_range_stack is non-zero at
+ (pop_init_level): abort if constructor_range_stack is nonzero at
explicit closing brace. Restore saved constructor_range_stack if
not implicit.
@@ -11587,10 +11587,10 @@ Mon Jan 29 20:38:19 2001 Christopher Faylor <cgf@cygnus.com>
* loop.c (loop_giv_reduce_benefit): Copy mode size into
int variable.
- (check_ext_dependant_givs): Initialise u_start_val and
+ (check_ext_dependant_givs): Initialize u_start_val and
u_end_val.
(load_mems): Make last_max_reg unsigned.
- (try_swap_copy_prop): Use INSN_P and initialise set.
+ (try_swap_copy_prop): Use INSN_P and initialize set.
Fri Jan 26 23:22:58 2001 Denis Chertykov <denisc@overta.ru>
@@ -11700,7 +11700,7 @@ Wed Jan 24 23:51:55 2001 J"orn Rennecke <amylaar@redhat.com>
* cppinit.c (cpp_start_read): Remove deps_add_dep call.
* tradcpp.c (main): Add -imacros or -include'd dependencies
for -M*.
- * cpp.texi (-M, -MM): Document -M -include behaviour.
+ * cpp.texi (-M, -MM): Document -M -include behavior.
2001-01-24 Roger Collins <roger@ProProject.com>
@@ -11922,7 +11922,7 @@ Sun Jan 21 09:44:17 2001 Denis Chertykov <denisc@overta.ru>
* config/avr/avr.c (ret_cond_branch): New argument (reverse) added.
If REVERSE nonzero then condition code in X must be reversed.
- (encode_section_info): Optimise if/else.
+ (encode_section_info): Optimize if/else.
(avr_function_value): Fix formatting.
* config/avr/avr.md (branch): Call to ret_cond_branch changed.
@@ -12652,7 +12652,7 @@ Sat Jan 13 09:53:32 MET 2001 Jan Hubicka <jh@suse.cz>
(pending_init_member): Rename to...
(find_init_member): ...this function. Call set_nonincremental_init
if necessary. Compare values of purpose index trees, not the trees
- themselves. Return the actual value, not just non-zero if something
+ themselves. Return the actual value, not just nonzero if something
is found.
(output_init_element): Remove checks for duplicates.
If field has zero size, only check the initializer for correctness.
@@ -12892,7 +12892,7 @@ Fri Jan 12 00:04:00 MET 2001 Jan Hubicka <jh@suse.cz>
2001-01-10 Nick Clifton <nickc@redhat.com>
- * config/d30v/d30v.c (d30v_init_machine_status): Initialise
+ * config/d30v/d30v.c (d30v_init_machine_status): Initialize
machine_function structure to zero.
Add prototypes for machine_status functions.
@@ -13097,7 +13097,7 @@ Wed Jan 10 16:38:31 MET 2001 Jan Hubicka <jh@suse.cz>
* config/d30v/d30v.h (struct_machine): Move here.
Add eh_epilogue_sp_ofs field.
- *config/d30v/d30v.md (epilogue): Initialise eh_epilogue_sp_ofs
+ *config/d30v/d30v.md (epilogue): Initialize eh_epilogue_sp_ofs
field in cfun->machine structure.
Tue Jan 9 21:34:57 2001 John David Anglin <dave@hiauly1.hia.nrc.ca>
@@ -13179,7 +13179,7 @@ Tue Jan 9 21:25:19 2001 Jeffrey A Law (law@cygnus.com)
(emit_a_shift): Adopt to the new calling prototype of
get_shift_alg.
(function_prologue): Fix code for a monitor
- function. Support H8/S.
+ function. Support H8S.
(function_epilogue): Do not output pop for a monitor function.
2001-01-09 Nick Clifton <nickc@redhat.com>
@@ -13264,7 +13264,7 @@ Tue Jan 9 21:25:19 2001 Jeffrey A Law (law@cygnus.com)
20001-01-09 Graham Stott <grahams@redhat.com>
* cppfiles.c (_cpp_execute_include): Move `len` initialisation
- after `ptr` is initialised.
+ after `ptr` is initialized.
2001-01-09 Alexandre Oliva <aoliva@redhat.com>
@@ -13876,7 +13876,7 @@ Fri Jan 5 16:29:49 MET 2001 Jan Hubicka <jh@suse.cz>
2001-01-05 Neil Booth <neil@daikokuya.demon.co.uk>
- * cpp.texi: Update for -MP. Clarify behaviour of -MT.
+ * cpp.texi: Update for -MP. Clarify behavior of -MT.
* cppinit.c (initialize_dependency_output): Update.
(cpp_finish): Output dummy targets for -MP.
(OPT_MP): New.
diff --git a/contrib/gcc/ChangeLog.6 b/contrib/gcc/ChangeLog.6
index d0e9a23..5618eaa 100644
--- a/contrib/gcc/ChangeLog.6
+++ b/contrib/gcc/ChangeLog.6
@@ -995,7 +995,7 @@ Mon Dec 17 18:27:52 CET 2001 Jan Hubicka <jh@suse.cz>
Mon Dec 17 17:57:05 CET 2001 Jan Hubicka <jh@suse.cz>
- * Makefile.in (cfgcleanup.o): Add cselib.h dependancy.
+ * Makefile.in (cfgcleanup.o): Add cselib.h dependency.
* basic-block.h (CLEANUP_THREADING): New constant.
* cfgcleanup.c: Include cselib.h
(thread_jump, mark_effect): New functions.
@@ -1020,10 +1020,10 @@ Mon Dec 17 17:57:05 CET 2001 Jan Hubicka <jh@suse.cz>
* target.h (asm_out.byte_op, asm_out.aligned_op, asm_out.unaligned_op,
asm_out.integer): New fields.
* target-def.h (TARGET_ASM_BYTE_OP, TARGET_ASM_ALIGNED_[HSDT]I_OP,
- TARGET_ASM_UNALIGNED_[HSDT]I_OP, TARGET_ASM_INTEGER): New initialisers.
+ TARGET_ASM_UNALIGNED_[HSDT]I_OP, TARGET_ASM_INTEGER): New initializers.
(TARGET_ASM_ALIGNED_INT_OP, TARGET_ASM_UNALIGNED_INT_OP): Collect
- the individual initialisers together.
- (TARGET_ASM_OUT): Add the new initialisers.
+ the individual initializers together.
+ (TARGET_ASM_OUT): Add the new initializers.
* output.h (assemble_integer): Return bool.
(integer_asm_op): Declare.
(default_assemble_integer): Declare.
@@ -5339,9 +5339,9 @@ Wed Nov 14 06:37:54 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
2001-11-13 Kazu Hirata <kazu@hxi.com>
* config/h8300/h8300.c (shift_alg_si): Use special code for
- 25-bit shifts on H8/S.
+ 25-bit shifts on H8S.
(get_shift_alg): Generate special code for 25-bit shifts on
- H8/S.
+ H8S.
2001-11-13 Jakub Jelinek <jakub@redhat.com>
@@ -5449,10 +5449,10 @@ Tue Nov 13 05:45:40 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
2001-11-12 Kazu Hirata <kazu@hxi.com>
* config/h8300/h8300.c (shift_alg_qi): Use rotations when
- doing 6-bit logical shifts on H8/S.
- (shift_alg_qi): Use special code for 21-bit shifts on H8/S.
+ doing 6-bit logical shifts on H8S.
+ (shift_alg_qi): Use special code for 21-bit shifts on H8S.
(get_shift_alg): Generate special code for 21-bit shifts on
- H8/S.
+ H8S.
2001-11-12 Kazu Hirata <kazu@hxi.com>
@@ -6891,7 +6891,7 @@ Sat Nov 3 10:37:56 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
2001-11-01 David S. Miller <davem@redhat.com>
* doc/install.texi (Specific, sparc-sun-solaris2*): Bring
- 64-bit Sparc description more in line with reality.
+ 64-bit SPARC description more in line with reality.
2001-11-01 Joseph S. Myers <jsm28@cam.ac.uk>
@@ -9881,7 +9881,7 @@ Fri Sep 28 14:59:34 CEST 2001 Jan Hubicka <jh@suse.cz>
2001-09-27 Richard Henderson <rth@redhat.com>
* dwarf2out.c (dwarf2out_frame_finish): Never elide .debug_frame
- in favour of .eh_frame.
+ in favor of .eh_frame.
2001-09-27 Aldy Hernandez <aldyh@redhat.com>
@@ -10036,7 +10036,7 @@ Tue Sep 25 17:13:56 CEST 2001 Jan Hubicka <jh@suse.cz>
(builtin_decsription): Add new field mask which is used to determine
when to define the builtin via the macro def_builtin.
- (bdesc_comi): Initialise new mask fields.
+ (bdesc_comi): Initialize new mask fields.
(bdesc_2srg): Likewise.
(bdesc_1arg): Likewise.
@@ -12374,7 +12374,7 @@ Thu Aug 30 10:21:43 2001 J"orn Rennecke <amylaar@redhat.com>
(INIT_SECTION_ASM_OP): Define.
(FINI_SECTION_ASM_OP): Define.
(SUBTARGET_EXTRA_SECTIONS): Remove trailing comma.
- (RDATA_SECTION_FUNCITON): Provide prototype.
+ (RDATA_SECTION_FUNCTION): Provide prototype.
2001-08-29 Geoffrey Keating <geoffk@redhat.com>
@@ -16219,7 +16219,7 @@ Thu Jul 26 14:04:03 EDT 2001 John Wehle (john@feith.com)
* flow.c (update_life_info): Simplify the CFG and
recalculate the global regs which are alive when
removing dead code during a global update.
- (propagate_block): Return non-zero if an INSN is
+ (propagate_block): Return nonzero if an INSN is
deleted.
2001-07-26 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
@@ -16689,7 +16689,7 @@ Sun Jul 22 21:31:04 CEST 2001 Jan Hubicka <jh@suse.cz>
(xcoff_debug_hooks, dbx_debug_hooks): Use it.
* sdbout.c (sdbout_finish): New.
(sdbout_debug_hooks): Use it, add comments.
- (sdbout_global_decl): Defer initialised public vars to
+ (sdbout_global_decl): Defer initialized public vars to
sdbout_finish.
* varasm.c (assemble_variable): Don't output debug information
for file-scope variables.
@@ -16721,7 +16721,7 @@ Sun Jul 22 21:31:04 CEST 2001 Jan Hubicka <jh@suse.cz>
(xcoff_debug_hooks, dbx_debug_hooks): Use it.
* sdbout.c (sdbout_finish): New.
(sdbout_debug_hooks): Use it, add comments.
- (sdbout_global_decl): Defer initialised public vars to
+ (sdbout_global_decl): Defer initialized public vars to
sdbout_finish.
* varasm.c (assemble_variable): Don't output debug information
for file-scope variables.
@@ -16990,7 +16990,7 @@ Fri Jul 20 13:24:16 CEST 2001 Jan Hubicka <jh@suse.cz>
* Makefile.in (toplev.o, dwarfout.o, final.o): Don't depend on
dwarfout.h.
- * dbxout.c (dbxout_function): Rename dbxout_funciton_decl, move
+ * dbxout.c (dbxout_function): Rename dbxout_function_decl, move
to conditionally compiled block.
(dbx_debug_hooks, xcoff_debug_hooks): Update.
* dbxout.h (dbxout_function): Remove.
@@ -18418,7 +18418,7 @@ Mon Jul 9 06:41:07 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* config/ia64/ia64.c (ia64_output_end_prologue): Rename to
ia64_output_function_end_prologue. Use in target struct
and make static.
- (ia64_function_prologue, ia64_funciton_epilogue): Rename
+ (ia64_function_prologue, ia64_function_epilogue): Rename
mistyped prototypes.
* config/ia64/ia64.h (FUNCTION_END_PROLOGUE): Delete.
* config/m88k/m88k-protos.h (m88k_end_prologue, m88k_begin_epilogue):
@@ -19186,13 +19186,13 @@ Sun Jul 1 11:53:52 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* c-parse.in (OBJC_STRING): Kill.
(objc_string): Decompose to [objc_string] '@' STRING.
- (reswords): Take the leading '@' off all the Objective C keywords.
+ (reswords): Take the leading '@' off all the Objective-C keywords.
(objc_rid_sans_at): Kill.
(init_reswords): Don't initialize it.
(yylexname): Use OBJC_IS_AT_KEYWORD and OBJC_IS_PQ_KEYWORD.
(_yylex): Kill reconsider label. Look ahead one token after
an '@'; if we get an identifier, check whether it's an
- Objective C @-keyword. If so, return the keyword. Otherwise,
+ Objective-C @-keyword. If so, return the keyword. Otherwise,
put back the token and return the '@' as a terminal.
* cpplib.c (lex_macro_node): Remove unnecessary check for
diff --git a/contrib/gcc/ChangeLog.7 b/contrib/gcc/ChangeLog.7
new file mode 100644
index 0000000..dc7282b
--- /dev/null
+++ b/contrib/gcc/ChangeLog.7
@@ -0,0 +1,21543 @@
+2002-06-30 Devang Patel <dpatel@apple.com>
+
+ * objc/objc-act.c (finish_file): Avoid finish_objc() if
+ -fsyntax-only.
+
+Fri Jun 28 17:22:37 2002 Denis Chertykov <denisc@overta.ru>
+ Frank Ch. Eigler <fche@redhat.com>
+ Matthew Green <mrg@redhat.com>
+ Richard Henderson <rtl@redhat.com>
+ Dave Hudson <dave.hudson@ubicom.com>
+ Jeff Johnston <jjohnstn@redhat.com>
+ Alan Lehotsky <apl@alum.mit.edu>
+ Bernd Schmidt <bernds@redhat.com>
+ Graham Stott <grahams@redhat.com>
+
+ * doc/extend.texi: Add ip2k port to description of attribute
+ naked.
+ * doc/install.texi (Specific): Add ip2k description.
+ * doc/install-old.texi (Configurations): Add ip2k to possible
+ cpu types.
+ * doc/md.texi: Document ip2k constraints.
+ * config/ip2k/crt0.S: New file.
+ * config/ip2k/ip2k-protos.h: New file.
+ * config/ip2k/ip2k.c: New file.
+ * config/ip2k/ip2k.h: New file.
+ * config/ip2k/ip2k.md: New file.
+ * config/ip2k/libgcc.S: New file.
+ * config/ip2k/t-ip2k: New file.
+
+2002-06-30 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.md ("return"): New pattern.
+ * config/mmix/mmix.h (TARGET_MASK_USE_RETURN_INSN)
+ (TARGET_USE_RETURN_INSN): New macros.
+ (TARGET_DEFAULT): Include TARGET_MASK_USE_RETURN_INSN.
+ (TARGET_SWITCHES): Add -msingle-exit and -mno-single-exit.
+ * config/mmix/mmix.c (MMIX_OUTPUT_REGNO): Fix spacing.
+ (MMIX_POP_ARGUMENT): New macro.
+ (mmix_target_asm_function_prologue): When no epilogue is executed,
+ just emit a blank line. Use MMIX_POP_ARGUMENT with final POP insn.
+ (mmix_print_operand) <case '.'>: New case.
+ (mmix_print_operand_punct_valid_p): Match '.'.
+ (mmix_use_simple_return): New function.
+ * config/mmix/mmix-protos.h (mmix_use_simple_return): Prototype.
+ * doc/invoke.texi (Option Summary) <MMIX Summary>: Add
+ -msingle-exit, -mno-single-exit.
+ (MMIX Options): Ditto.
+
+2002-06-30 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/i386/i386.c (ix86_init_mmx_sse_builtins): Fix typos.
+
+2002-06-30 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * gengtype.c (oprintf): Move VA_CLOSE after all fixedarg uses.
+
+2002-06-30 Alan Modra <amodra@bigpond.net.au>
+
+ * unroll.c (loop_iterations): Handle EQ loops.
+
+2002-06-29 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.md (ctrdi): Allocate pseudo for FPR
+ constraint in define_expand, not splitter.
+ Formatting.
+
+2002-06-29 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/i386/i386.c (ix86_init_mmx_sse_builtins): Use
+ build_function_type_list instead of build_function_type.
+
+ * config/ia64/ia64.c (ia64_init_builtins): Same.
+
+ * config/alpha/alpha.c (alpha_init_builtins): Same.
+
+ * config/rs6000/rs6000.c (altivec_init_builtins): Same.
+
+ * config/arm/arm.c (arm_init_builtins): Same.
+
+ * tree.h: Add build_function_type_list prototype.
+
+ * tree.c (build_function_type_list): New.
+
+2002-06-29 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * collect2.c (scan_prog_file): Fix typo in message.
+
+2002-06-28 Aaron Lehmann <aaronl@vitelus.com>
+
+ * fold-cont.c: Remove unused CHARMASK.
+
+2002-06-29 Neil Booth <neil@daikokuya.co.uk>
+
+ PR preprocessor/7150
+ * cppmain.c (scan_translation_unit_trad): Simplify.
+ * cppmacro.c (cpp_scan_nooutput): Handle traditional case.
+
+2002-06-29 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * config/i386/crtdll.h: Define EXTRA_OS_CPP_BUILTINS.
+ Don't use CPP_PREDEFINES.
+ * config/i386/cygwin.h (EXTRA_OS_CPP_BUILTINS): New.
+ Used TARGET_OS_CPP_BUILTINS in preference to CPP_PREDEFINES.
+ * config/i386/djgpp.h, config/i386/i386-coff.h,
+ config/i386/i386-interix.h, config/i386/i386-interix3.h,
+ config/i386/lynx-ng.h, config/i386/lynx.h, config/i386/mingw32.h,
+ config/i386/openbsd.h, config/i386/ptx4-i.h, config/i386/sysv3.h,
+ config/i386/uwin.h: Similarly.
+
+2002-06-29 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+
+ * c4x.h: (TARGET_CPU_CPP_BUILTINS): Check flag_inline_functions and
+ flag_inline_trees to enable inlining.
+
+2002-06-28 Phil Edwards <pme@gcc.gnu.org>
+
+ * configure.in (gcc_gxx_include_dir): Change to match versioned
+ C++ headers if --enable-version-specific-runtime-libs is used.
+ * configure: Regenerate.
+
+2002-06-28 Jan Hubicka <jh@suse.cz>
+
+ * gcse.c (gcse_emit_move_after): Use gen_move_insn to produce the move.
+
+2002-06-28 Stephen Clarke <stephen.clarke@superh.com>
+
+ * combine.c (combine_simplify_rtx): Pass the mode of the
+ shift count, not the shift operation when trying to simplify
+ a shift on a SHIFT_COUNT_TRUNCATED target.
+
+2002-06-28 Stephane Carrez <stcarrez@nerim.fr>
+
+ * config/m68hc11/m68hc11.md ("*addsi3"): Use 'o' constraint to
+ avoid the auto increment addressing modes.
+ ("*subsi3"): Likewise.
+ (split for add/sub on address): For 68HC12 push the value on
+ the stack and do the operation with a pop.
+
+2002-06-28 Neil Booth <neil@daikokuya.co.uk>
+
+ * cpplib.c (_cpp_handle_directive): Move #define-specific
+ code to the #define handler...
+ (do_define): ...here.
+ (lex_macro_node): No longer a need to check for comments here.
+
+2002-06-28 Stephane Carrez <stcarrez@nerim.fr>
+
+ * config/m68hc11/m68hc11.h (OPTIMIZATION_OPTIONS): Define.
+ * config/m68hc11/m68hc11-protos.h (m68hc11_optimization_options):
+ Declare.
+ * config/m68hc11/m68hc11.c (m68hc11_optimization_options): New,
+ do not reorder basic blocks at the end when optimizing for size.
+
+2002-06-28 Stephane Carrez <stcarrez@nerim.fr>
+
+ * config/m68hc11/m68hc11.c (autoinc_mode): New function.
+ (m68hc11_make_autoinc_notes): New function.
+ (m68hc11_split_move): Be very cautious when spliting a move with
+ auto increment/decrement modes because this may result in incompatible
+ directions; add REG_INC notes to the resulting insn for CSE reg.
+
+2002-06-28 Stephane Carrez <Stephane.Carrez@nerim.fr>
+
+ * config/m68hc11/m68hc11.c (register_indirect_p): For 68HC12 a constant
+ can be a valid address.
+
+2002-06-28 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c: Remove unusued variables from last
+ patch.
+
+2002-06-27 Aldy Hernandez <aldyh@redhat.com>
+
+ Revert:
+ * config/rs6000/rs6000.c (rs6000_override_options): Move
+ *SUBTARGET_OVERRIDE_OPTIONS before the -m options.
+
+2002-06-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c (altivec_expand_builtin): Move
+ lvx/stv/dst builtins...
+ (altivec_expand_ld_builtin): ...to here.
+ (altivec_expand_st_builtin): ...here.
+ (altivec_expand_dst_builtin): ...and here (respectively).
+
+2002-06-28 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.h (RETURN_IN_MEMORY): Update comment.
+
+2001-06-08 Bernd Schmidt <bernds@redhat.com>
+
+ * emit-rtl.c (gen_lowpart_common): Don't create paradoxical FLOAT_MODE
+ subregs.
+ * recog.c (general_operand, register_operand): Disallow them.
+
+2002-06-28 Neil Booth <neil@daikokuya.co.uk>
+
+ PR preprocessor/7138
+ * cpplib.c (_cpp_handle_directive): Do traditional
+ preparation after setting state.angled_headers.
+ * cpptrad.c (scan_out_logical_line): Fix potential
+ quote bug.
+
+2002-06-27 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c (rs6000_override_options): Move
+ *SUBTARGET_OVERRIDE_OPTIONS before the -m options.
+
+2002-06-27 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.md: Give "*xxx" names to all unnamed insn's.
+ (*lsiu, *ssiu, movstrsi_internal, zero_cost_loop_start,
+ zero_cost_loop_end): Remove unnecessary "parallel" from insns.
+
+2002-06-27 Roger Sayle <roger@eyesopen.com>
+
+ * config/d30v/d30v.h: Remove commented out STACK_REGS #defines.
+ * config/stormy16/stormy16.h: Likewise.
+
+ * config/stormy16/stormy16.h (CUMULATIVE_ARGS): Replace typedef
+ with #define.
+
+2002-06-26 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/install.texi (Binaries): Add Sinix/Reliant Unix. Move
+ Hitachi entry. Make punctuation more consistent.
+
+2002-06-27 Matt Kraai <kraai@alumni.cmu.edu>
+
+ * doc/install.texi: Change ` bit' to `-bit'.
+ * doc/md.texi: Change `-bits' to `-bit'.
+ * doc/tm.texi: Change `-bits' to ` bits'.
+
+2002-06-27 Daniel Berlin <dberlin@dberlin.org>
+
+ * gcse.c (hoist_code): Rewrite to only get list of dominated
+ blocks once per BB. Also fix reversed test (by removing need for
+ the test at all).
+
+2002-06-27 Neil Booth <neil@daikokuya.co.uk>
+
+ * cpphash.h (_cpp_set_trad_context): Remove.
+ * cpplib.c (prepare_directive_trad): Do nothing for #define.
+ (cpp_push_buffer, _cpp_pop_buffer): Don't call _cpp_set_trad_context.
+ * cpptrad.c: Update comments.
+ (_cpp_read_logical_line_trad): Let scan_logical_line handle
+ updating the current context.
+ (scan_logical_line): Update the current context.
+ (_cpp_create_trad_definition): Similarly.
+ (_cpp_set_trad_context): Remove.
+
+2002-06-27 Neil Booth <neil@daikokuya.co.uk>
+
+ PR preprocessor/7070
+ * c-lex.c (cb_def_pragma): Don't try to spell CPP_EOF.
+
+2002-06-26 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa-protos.h (xtensa_return_addr): Declare.
+ config/xtensa/xtensa.c (xtensa_return_addr): New function.
+ config/xtensa/xtensa.h (RETURN_ADDR_RTX): Use xtensa_return_addr.
+ config/xtensa/xtensa.md (fix_return_addr): New pattern.
+
+2002-06-26 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * mips.c (coprocessor_operand, coprocessor2_operand,
+ symbolic_operand): Move prototypes from here...
+ * mips-protos.h (coprocessor_operand, coprocessor2_operand,
+ symbolic_operand): ...to here.
+
+Wed Jun 26 16:32:57 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * config/sh/crt1.asm: remove _stack label definition
+ and sentinel value.
+
+2002-06-26 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * varasm.c: Include real.h before output.h.
+
+2002-06-26 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.h (ALTIVEC_VECTOR_MODE): Revert change to
+ check for TARGET_ALTIVEC.
+
+2002-06-26 Nathanael Nerode <neroden@gcc.gnu.org>
+
+ * config.gcc (vax-*-vms*): Make obselete.
+
+2002-06-25 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * gcc.c (warn_std): Delete.
+
+2002-06-25 Loren J. Rittle <ljrittle@acm.org>
+
+ * doc/extend.texi: Fix formatting of last checkin.
+
+2002-06-25 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * config/alpha/alpha.h (TARGET_CPU_CPP_BUILTINS): Remove leading
+ underscore from __IEEE_FP and __IEEE_FP_INEXACT.
+
+2002-06-25 Aldy Hernandez <aldyh@redhat.com>
+
+ * doc/extend.texi (PowerPC AltiVec Built-in Functions): Document
+ discrepancies from motorola's documentation.
+
+Tue Jun 25 21:51:13 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * optabs.c (expand_vector_binop, expand_vector_unop): Don't assume
+ GET_MODE_UNIT_SIZE (mode) == UNITS_PER_WORD.
+
+ * config/sh/lib1funcs.asm (udivdi3): Make first divide step
+ produce a 32 bit result before normalization, then normalize with a
+ left shift. Compute approximative error of 2nd reciprocal
+ approximation in 2's complement. Fix mask generation from upper
+ longword of second divide stage result.
+ For large divisor, fix shift count used to truncate first stage
+ divide result; make decision if to adjust upwards based on comparison
+ of higher parts of normalized values.
+ (udivdi): Likewise. Undo normalization of result for large divisor
+ case.
+
+2002-06-25 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.md: Change \\{t,n} to \{t,n}.
+
+2002-06-25 Neil Booth <neil@daikokuya.co.uk>
+
+ * cpplib.c (do_include_common): Revert to correct line number
+ if -traditional.
+ * cpptrad.c (scan_out_logical_line): Treat null directive as
+ white space. Invlidate MI optimization for non-whitespace
+ text outside a directive.
+
+2002-06-24 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Makefile.in (SHELL): Set to @SHELL@.
+ * fixinc/Makefile.in (SHELL): Likewise.
+
+ * mips.md (fixuns_truncdfsi2, fixuns_truncdfdi2,
+ fixuns_truncsfsi2, fixuns_truncsfdi2): Avoid automatic aggregate
+ initialization.
+
+2002-06-24 Jeff Law <law@redhat.com>
+
+ * flow.c (propagate_one_insn): When removing an insn
+ with a REG_LIBCALL note but not the entire libcall sequence,
+ delete the associated REG_RETVAL note.
+
+Mon Jun 24 21:05:09 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * lib1funcs.asm (sdivsi3): Add optimized SH64 implementations.
+ (udivsi3): Likewise. Rewrite SH1 implementation.
+ (udivdi3, divdi3, umoddi3, moddi3): New SHmedia functions.
+ * sh.md (R20_REG, R21_REG, R22_REG, R23_REG, FR23_REG): New constants.
+ (udivsi3_i1_media, divsi3_i1_media): Fix clobber list.
+ * config/sh/t-sh64 (LIB1ASMFUNCS): (_udivdi3, _divdi3, _umoddi3): Add.
+ (_moddi3): Likewise.
+
+ * lib1funcs.asm (ic_invalidate): Add data cache line writeback.
+
+ * sh.h (FUNCTION_ARG_ADVANCE): Take SHCOMPACT_FORCE_ON_STACK
+ arguments into account for stack_regs.
+
+2002-06-24 Matt Kraai <kraai@alumni.cmu.edu>
+
+ * doc/extend.texi: Change `@dots{}' to `/* @r{@dots{}} */'
+ in examples.
+
+2002-06-24 Art Haas <ahaas@neosoft.com>
+
+ * doc/extend.texi (Other Builtins): Change `...' to `@dots{}'.
+ * doc/tm.texi (Frame Layout): Likewise.
+
+2002-06-20 Steve Ellcey <sje@cup.hp.com>
+
+ * gcc/config.gcc (ia64*-*-hpux*): Set use_collect2 to no.
+ Set float_format to i128.
+
+2002-06-24 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.c (INIT_TARGET_OPTABS): If ARCH64, set the
+ 32-bit ABI libfuncs to NULL.
+
+ * config/sparc/sparc.md: Use define_insn_and_split. Use braced
+ strings instead of quoted strings for code blocks.
+
+ * expmed.c (expand_divmod): Do not set optab1/optab2 to the shift
+ optabs if op1 is const0_rtx.
+
+ * Makefile.in (GTFILES): Add basic-block.h
+ * basic-block.h (label_value_list, tail_recursion_label_list):
+ Mark with GTY.
+
+2002-06-24 Neil Booth <neil@daikokuya.co.uk>
+
+ * cpptrad.c (scan_out_logical_line): Check recursing only when
+ we know we have a macro invocation in the function-like case.
+ Only call _cpp_handle_directive if we know we have a good
+ directive, or we want to reject a bad directive.
+
+2002-06-24 Alan Modra <amodra@bigpond.net.au>
+
+ * doloop.c (doloop_valid_p): Correct comment.
+ (doloop_modify_runtime <abs_inc != 1>): Simplify.
+ (doloop_modify_runtime <do-while>): Don't emit code when NE.
+
+Thu Jun 20 00:26:53 2002 Denis Chertykov <denisc@overta.ru>
+
+ * config.gcc: Add support for ip2k.
+
+2002-06-23 Jan Hubicka <jh@suse.cz>
+ Jeff Law <law@redhat.com>
+
+ * function.h (struct emit_status): Clarify potential contents
+ of regno_reg_rtx array.
+ * integrate.c (copy_rtx_and_substitute): Update comments. Make
+ sure entry in regno_reg_rtx is a REG before checking REG_POINTER.
+
+ * reg-stack.c (convert_regs_exit): Push the registers to stack in
+ proper order.
+
+2002-06-22 Ulrich Weigand <uweigand@de.ibm.com>
+
+ PR middle-end/6963
+ * function.c (assign_stack_temp_for_type): Do not return
+ the same MEM rtx for multiple uses of a stack slot.
+
+2002-06-22 David S. Miller <davem@redhat.com>
+
+ PR target/6841 target/6770 target/6719
+ * config/sparc/sparc.h (PREFERRED_RELOAD_CLASS): Return
+ NO_REGS for constant X when CLASS is GENERAL_OR_FP_REGS or
+ GENERAL_OR_EXTRA_FP_REGS.
+
+2002-06-22 Neil Booth <neil@daikokuya.co.uk>
+
+ * cpptrad.c (struct fun_macro): Add line number.
+ (scan_out_logical_line): Set it, and use it to report unterminated
+ macro invocations.
+
+2002-06-21 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * genautomata.c (copy_node, VLA_PTR_CREATE, VLA_PTR_EXPAND,
+ VLA_PTR_ADD, VLA_HWINT_CREATE, VLA_HWINT_EXPAND, VLA_HWINT_ADD,
+ DECL_UNIT, DECL_BYPASS, DECL_AUTOMATON, DECL_EXCL, DECL_PRESENCE,
+ DECL_ABSENCE, DECL_RESERV, DECL_INSN_RESERV, REGEXP_UNIT,
+ REGEXP_RESERV, REGEXP_SEQUENCE, REGEXP_REPEAT, REGEXP_ALLOF,
+ REGEXP_ONEOF, check_name): Const-ify.
+
+2002-06-21 Matt Thomas <matt@3am-software.com>
+
+ * config/vax/vax.c (vax_output_function_prologue): Use
+ REGISTER_PREFIX. Fix some indentation.
+ * config/vax/vax.h (FUNCTION_PROFILER): Use reg_names[].
+ (VAX_ISTREAM_SYNC): Define.
+ (INITIALIZE_TRAMPOLINE): Use VAX_ISTREAM_SYNC. Move the
+ i-stream sync to the end.
+ (REGISTER_PREFIX): Define as "".
+ (ASM_OUTPUT_MI_THUNK): Use REGISTER_PREFIX.
+
+2002-06-21 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config.gcc (ns32k-*-netbsd*): Remove from list of obsolete
+ configurations.
+
+2002-06-21 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * tree.c (tree_node_kind, tree_node_counts, tree_node_sizes,
+ tree_node_kind_names): Wrap in GATHER_STATISTICS macro.
+
+2002-06-21 Matt Thomas <matt@3am-software.com>
+
+ * config/vax/netbsd.h: Adjust a comment.
+ (TARGET_DEFAULT): Redefine as 0.
+
+2002-06-21 Richard Henderson <rth@redhat.com>
+
+ * bb-reorder.c (make_reorder_chain_1): Search harder for the
+ vax casesi fallthru edge.
+ * cfglayout.c (cleanup_unconditional_jumps): Use
+ redirect_edge_succ_nodup. Do not delete ADDR_VEC insns as dead.
+ * cfgrtl.c (force_nonfallthru_and_redirect): Place redirection
+ block after ADDR_VEC.
+
+2002-06-21 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * config/sparc/t-linux64 (EXTRA_MULTILIB_PARTS): Add crtfastmath.o.
+
+2002-06-21 Neil Booth <neil@daikokuya.co.uk>
+
+ * cpperror.c (cpp_error): For traditional CPP, default to
+ diagnostics on pfile->line.
+ * cpplib.c (prepare_directive_trad): Set line number for
+ diagnostics for #define too.
+ * cpptrad.c (skip_whitespace): Skip comments properly.
+ (_cpp_expansions_different_trad): Initialize quote2.
+
+2002-06-21 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.md: Change GNU CC to GCC in file header comment.
+ * config/mmix/mmix.h: Ditto.
+ * config/mmix/mmix-protos.h: Ditto.
+ * config/mmix/mmix.c: Ditto. Fix typo in comment.
+ * config/mmix/mmix-modes.def: Change GNU CC to GCC in file header
+ comment. Comment extra CC modes.
+
+2002-06-20 Jan Hubicka <jh@suse.cz>
+
+ * cfglayout.c (scope_to_insns_initialize): Call set_block_levels.
+ (scope_to_insns_finalize): Do not call set_block_levels; handle
+ sequences.
+ (choose_inner_scope): New.
+ * rtl.h (choose_inner_scope): Declare.
+
+2002-06-20 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa-protos.h (pa_asm_output_mi_thunk): Change third argument to
+ HOST_WIDE_INT.
+ * pa.c (pa_asm_output_mi_thunk): Likewise.
+ (n_deferred_plabels): Change type to size_t.
+ (output_deferred_plabels, output_call): Use size_t instead of int.
+
+2002-06-20 Richard Henderson <rth@redhat.com>
+
+ PR target/4041
+ * config/m68k/m68k.md (zero_extendsidi2): Create expander; duplicate
+ pattern and adjust constraints for coldfire.
+
+2002-06-20 Richard Henderson <rth@redhat.com>
+
+ * explow.c (probe_stack_range): Use gen_rtx_fmt_ee.
+
+2002-06-20 Chris Demetriou <cgd@broadcom.com>
+
+ * config.gcc (mipsisa64-*-elf*, mipsisa64el-*-elf*): New targets.
+
+2002-06-20 Chris Demetriou <cgd@broadcom.com>
+
+ * config/mips/mips.h (ISA_HAS_FP4): Fix comment to reflect use.
+
+2002-06-20 Stan Shebs <shebs@apple.com>
+
+ * dominance.c: Include errors.h instead of error.h.
+
+2002-06-20 Neil Booth <neil@daikokuya.co.uk>
+
+ * cppexp.c (cpp_interpret_integer): Don't force traditional
+ numbers to be unsigned.
+ * cpplib.c (prepare_directive_trad): Set line number for
+ diagnostics.
+ * cpptrad.c (scan_out_logical_line): Continue scanning out
+ at start of buffer.
+ * gcc.c (trad_capable_cpp): Use cc1 always.
+
+2002-06-20 Jeffrey Law <law@redhat.com>
+
+ * i386.h (TARGET_DEFAULT): Do not turn on frame pointer
+ elimination in leaf functions by default yet.
+
+2002-06-20 Richard Sandiford <rsandifo@redhat.com>
+
+ * combine.c (make_extraction): Reapply to the argument of an ASHIFT.
+
+2002-06-20 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * config/sparc/t-crtfm (crtfastmath.o): Prefix with $(T) for
+ multilibs.
+ * config/sparc/t-sol2-64 (EXTRA_MULTILIB_PARTS): Add crtfastmath.o.
+ Fixes PR other/6836.
+
+Thu Jun 20 19:42:21 CEST 2002 Jan Hubicka <jh@suse.cz>
+ Pavel Nejedly <bim@atrey.karlin.mff.cuni.cz>
+
+ Mon Jun 10 20:42:34 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * basic-block.h: Do not include et-forest.h
+ (dominance_info): Declare as struct dominance-info.
+ * cfglayout.c (cleanup_unconditional_jumps): Remove the edge before
+ deleting block.
+ * dominance.c (struct dominance_info): Define.
+ (BB_NODE, SET_BB_NODE): New macros.
+ (bb_hash_func, bb_eq_func): Kill.
+ (calculate_dominace_info, free_dominacne_info, set_immediate_dominator,
+ nearest_common_dominator, dominated_by_p, recount_dominator,
+ add_to_dominance_info, delete_from_dominance_info): update for new
+ representation.
+ (get_dominated_by, redirect_immediate_dominators): Rewrite using
+ enumerate_sons.
+ * ifcvt.c (process_double_test_block, merge_if_block, find_cond_trap,
+ find_if_case_1, find_if_case_2): Remove killed blocks from dominance
+ structure.
+
+ * et-forest.h: Update copyright; revamp all function to operate on
+ nodes
+ (et_forest_value): Kill.
+ (et_forest_enumerate_sons, et_forest_node_value): New.
+ * et-forest.c: Update copyright.
+ * et-forest.h: Update copyright; revamp all function to operate on
+ nodes
+ (et_forest_value): Kill.
+ (et_forest_enumerate_sons, et_forest_node_value): New.
+
+ Thu Jun 6 22:43:43 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * basic-block.h: Inlude et-forest.h
+ (basic_block_def): Kill dominator.
+ (dominance_info): New type.
+ (loops): Use dominace_info.
+ (dominace handling functions): Take dominace_info as argument
+ instead of bitmaps.
+ (create_preheader): Likewise.
+ * cfg.c (entry_exit_blocks): Kill dominator.
+ (dump_flow_info): Do not dump dominators.
+ * cfglayout.c (cleanup_unconditonal_jumps): Delete deleted block from
+ dominators.
+ * cfgloop.c (flow_pre_header_find): Use dominacne_info.
+ (flow_loops_pre_header_scan, make_forwarder_block,
+ canonicale_loop_headers, flow_loops_find): Likewise.
+ * dominance.c: Include error.h
+ (idoms_to_doms): Kill.
+ (bb_hash_func, bb_eq_func): New static functions.
+ (debug_dominace_info): New global function.
+ (calculate_dominance_info): Use new et forest structure.
+ (free_dominace_info, get_immediate_dominator, set_immediate_dominator,
+ get_dominated_by, redirect_immediate_dominators,
+ nearest_common_dominator, dominated_by_p, verify_dominators,
+ recount_dominator, iterate_fix_dominators, add_to_dominace_info,
+ delete_from_dominance_info): New global functions.
+ * gcse.c (domnators): CHange to dominance_info.
+ (alloc_hoist_mem): Do not alloc dominators
+ (free_code_hoist_mem): Use free_dominance_info.
+ (compute_code_hoist_data): Use dominance_info.
+ (hoist_code): Likewise.
+ * ifcvt.c (post_dominators): Likewise.
+ (find_if_case_2, if_convert): Likewise.
+ * predict.c (process_note_predictions, process_note_prediction,
+ estimate-probability): Likewise.
+ * sched-rgn.c (find_rgns, init_regions): Likewise.
+ * ssa-dce.c (find_all_control_dependences, fint_control_depemndence,
+ find_pdom, delete_insn_bb, ssa_eliminate_dead_code): Likewise.
+ * ssa.c (compute_dominance_frontiers_1, rename_block, rename_registers,
+ find_evaluations, convert_to_ssa): Likewise.
+ * ssa.h (compute_dominance_frontiers): Likewise.
+
+ Thu Jun 6 22:57:34 CEST 2002 Pavel Nejedly <bim@atrey.karlin.mff.cuni.cz>
+
+ * Makefile.in (et-forest.c): Add.
+ * et-forest.c: New file.
+ * at-forest.h: New file.
+
+2002-06-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * c-decl.c (c_decode_option): Use ARRAY_SIZE in lieu of explicit
+ array size calculation.
+ * gengtype.c (NUM_BASE_FILES, create_file, write_gc_root):
+ Likewise.
+
+ * diagnostic.c (diagnostic_kind_text): Const-ify.
+ * gengtype.c (lang_names): Likewise.
+
+Thu Jun 20 17:25:29 CEST 2002 JAn HUbicka <jh@suse.cz>
+
+ * combine.c (subst): Be prepared for simplify_subreg to return VOIDmode.
+
+2002-06-20 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * config/sol2.h: New file.
+ * config.gcc (i?86-*-solaris2*): Include it before i386/sol2.h.
+ (sparc64-wrs-vxworks*): Include it before sparc/sol2.h.
+ (sparc-*-chorusos*): Likewise.
+ (sparc-*-elf*): Likewise.
+ (sparc-*-rtems*, sparc-*-rtemself*): Likewise.
+ (sparc64-*-solaris2*, sparcv9-*-solaris2*): Likewise.
+ (sparc-hal-solaris2*): Likewise.
+ (sparc-*-solaris2*): Likewise.
+ (sparclite-*-elf*): Likewise.
+ (sparc86x-*-elf*): Likewise.
+ (sparc64-*-elf*): Likewise.
+
+ * config/i386/sol2.h (PREFERRED_DEBUGGING_TYPE): Moved to
+ config/sol2.h.
+ (ASM_SPEC): Override config/sol2.h version for now.
+ Removed obsolete GAS_REJECTS_MINUS_S variant.
+ (WINT_TYPE, WINT_TYPE_SIZE): Moved to config/sol2.h.
+ (HANDLE_PRAGMA_REDEFINE_EXTNAME): Likewise.
+ (TARGET_OS_CPP_BUILTINS): Likewise.
+ Assert system=unix.
+ (CPP_SPEC): Simplified using new CPP_SUBTARGET_SPEC.
+ (LIB_SPEC, ENDFILE_SPEC, STARTFILE_SPEC, LINK_SPEC): Moved to
+ config/sol2.h.
+ (SWITCH_TAKES_ARG, STDC_0_IN_SYSTEM_HEADERS): Likewise.
+ (ASM_CPU_SPEC): Define.
+ (SUBTARGET_EXTRA_SPECS): Define.
+
+ * config/sparc/sol2-bi.h (LONG_DOUBLE_TYPE_SIZE): Removed, already
+ in config/sparc/sol2.h.
+ (ASM_SPEC): Moved to config/sol2.h.
+ (CPP_CPU_SPEC): Simplified.
+ (STARTFILE_SPEC32): Likewise, renamed to STARTFILE_ARCH32_SPEC for
+ consistency.
+ (STARTFILE_SPEC64): Renamed to STARTFILE_ARCH64_SPEC.
+ (STARTFILE_ARCH_SPEC): Use new names STARTFILE_ARCH32_SPEC,
+ STARTFILE_ARCH64_SPEC.
+ (STARTFILE_SPEC): Moved to config/sol2.h
+ (SUBTARGET_EXTRA_SPECS): Add startfile_arch.
+ (LINK_ARCH32_SPEC): Moved to config/sol2.h.
+ (LINK_ARCH64_SPEC): Simplified.
+ (LINK_ARCH_SPEC): Redefined config/sol2.h version for 64-bit support.
+ (LINK_SPEC): Moved to config/sol2.h
+
+ * config/sparc/sol2.h (WCHAR_TYPE, WCHAR_TYPE_SIZE): Moved to
+ config/sol2.h.
+ Use BITS_PER_WORD for size.
+ (WINT_TYPE, WINT_TYPE_SIZE): Likewise.
+ (HANDLE_PRAGMA_REDEFINE_EXTNAME): Likewise.
+ (CPP_PREDEFINES): Removed OS-specific part handled by
+ TARGET_OS_CPP_BUILTINS.
+ (CPP_SUBTARGET_SPEC): Moved to config/sol2.h.
+ (CPLUSPLUS_CPP_SPEC): Removed, handled by TARGET_OS_CPP_BUILTINS.
+ (ASM_SPEC): Moved to config/sol2.h.
+ (PREFERRED_DEBUGGING_TYPE): Likewise.
+ (STARTFILE_SPEC, LIB_SPEC, LINK_SPEC): Likewise.
+ (SWITCH_TAKES_ARG, STDC_0_IN_SYSTEM_HEADERS): Likewise.
+ (TARGET_DEFAULT): Reordered to match config/sparc/sol2-bi.h version.
+ (TRANSFER_FROM_TRAMPOLINE): Moved to config/sol2.h
+
+ * config.gcc (i?86-*-solaris2*): Removed obsolete gas support.
+ * config/i386/sol2gas.h: Removed.
+
+Thu Jun 20 12:14:01 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (xorqi_1_slp, xorqi_2_slp): New patterns.
+
+2002-06-16 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.c-torture/execute/simd-1.c: New.
+
+ * gcc.dg/simd-1.c: New.
+
+ * doc/extend.texi (Vector Extensions): Document that we can
+ specify simd types not specifically supported by the hardware.
+ Document that simd types can be used as function arguments.
+ Document that signness does make a difference in SIMD types.
+ Misc cleanups and revisions to the vector extensions section.
+
+ * simplify-rtx.c (simplify_subreg): Simplify subregs of vector
+ constants.
+
+ * expr.c (vector_mode_valid_p): New.
+
+ * expr.h: Add vector_mode_valid_p.
+
+ * defaults.h (VECTOR_MODE_SUPPORTED_P): Set default.
+
+ * c-common.c (type_for_mode): Always build vector nodes regardless
+ of VECTOR_MODE_SUPPORTED_P.
+ (handle_mode_attribute): Error if we can't emulate a nonexisting
+ vector mode.
+ (handle_vector_size_attribute): Same.
+
+ * optabs.c (expand_binop): Open-code vector operations.
+ (expand_unop): Open-code vector unops.
+ (expand_vector_binop): New.
+ (expand_vector_unop): New.
+
+ * c-typeck.c (build_binary_op): Allow vectors in binops.
+ Allow vectors in conditional operatiors.
+ (build_unary_op): Allow vectors in unary minus.
+
+ * config/rs6000/rs6000.h (ALTIVEC_VECTOR_MODE): Conditionalize on
+ TARGET_ALTIVEC.
+
+2002-05-20 Richard Henderson <rth@redhat.com>
+
+ * c-common.c (c_common_get_alias_set): Correctly handle characters.
+ Rearrange order of expressions; don't handle vectors here.
+ * alias.c (get_alias_set): Let vectors match their components.
+
+2002-06-19 Chris Demetriou <cgd@broadcom.com>
+
+ * config/mips/mips.c (mips_emit_prefetch): Use hints which
+ match desired locality.
+
+2002-06-19 Dhananjay R. Deshpande <dhananjayd@kpit.com>
+
+ * config/h8300/h8300.c (TARGET_INSERT_ATTRIBUTES): Define.
+ (h8300_insert_attributes): New.
+
+2002-06-19 Akim Demaille <akim@epita.fr>
+
+ * c-parse.in (initelt: identifier ':' initval): Add an empty
+ action to fix a type clash.
+ (aliasdecl, classdef): Add the missing closing `;'.
+ Whitespace changes.
+ * gengtype-yacc.y (typedef_struct): Add an empty action to preevnt
+ $$ = $1 type clashes.
+
+2002-06-19 Eric Christopher <echristo@redhat.com>
+
+ * config/mips/mips.c (symbol_operand): New function.
+ (mips_emit_prefetch): Ditto.
+ * config/mips/mips-protos.h: Define.
+ * config/mips/mips.h (ISA_HAS_PREFETCH): Define.
+ (CONSTANT_ADDRESS_P): Adjust, use TARGET_GAS.
+ (LEGITIMIZE_ADDRESS): Ditto.
+ * config/mips/mips.md (prefetch, prefetch_si_address,
+ prefetch_si, prefetch_di_address, prefetch_di): New patterns.
+
+2002-06-19 Eric Christopher <echristo@redhat.com>
+
+ * config/fp-bit.h: Add unordered defines for gofast.
+
+2002-06-19 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (DECL_UNIT, DECL_BYPASS, DECL_AUTOMATON,
+ DECL_EXCL, DECL_PRESENCE, DECL_ABSENCE, DECL_RESERV,
+ DECL_INSN_RESERV, REGEXP_UNIT, REGEXP_RESERV, REGEXP_SEQUENCE,
+ REGEXP_REPEAT, REGEXP_ALLOF, REGEXP_ONEOF): New macros with
+ checking and without it.
+ (decl_name, decl_mode_check_failed, regexp_name,
+ regexp_mode_check_failed): New functions.
+ (gen_cpu_unit, gen_query_cpu_unit, gen_bypass, gen_excl_set,
+ gen_presence_set, gen_absence_set, gen_automaton,
+ gen_regexp_repeat, gen_regexp_allof, gen_regexp_oneof,
+ gen_regexp_sequence, gen_reserv, gen_insn_reserv,
+ automaton_decl_hash, automaton_decl_eq_p): Use the macros.
+ (find_automaton_decl): Ditto. Set up mode of work_automaton_decl.
+ (insn_decl_hash, insn_decl_hash, insn_decl_eq_p): Use the macros.
+ (find_insn_decl): Ditto. Set up mode of work_insn_decl.
+ (decl_hash, decl_eq_p): Use the macros.
+ (find_decl): Ditto. Set up mode of work_decl.
+ (process_excls, process_presence_absence, process_decls,
+ check_automaton_usage, process_regexp, process_regexp_decls,
+ check_usage, loop_in_regexp, check_loops_in_regexps,
+ process_regexp_cycles, add_advance_cycle_insn_decl,
+ initiate_states, initiate_excl_sets,
+ initiate_presence_absence_sets, copy_insn_regexp, transform_1,
+ transform_2): Use the macros.
+ (transform_3): Ditto. Check mode before making transformations of
+ ALLOF.
+ (regexp_transform_func, transform_insn_regexps,
+ process_unit_to_form_the_same_automaton_unit_lists,
+ form_the_same_automaton_unit_lists_from_regexp,
+ form_the_same_automaton_unit_lists,
+ process_seq_for_forming_states, process_alts_for_forming_states,
+ create_alt_states, form_ainsn_with_same_reservs, make_automaton,
+ form_arcs_marked_by_insn, NDFA_to_DFA, set_new_cycle_flags,
+ estimate_one_automaton_bound, compare_max_occ_cycle_nums,
+ units_to_automata_heuristic_distr, create_ainsns,
+ units_to_automata_distr, create_automata): Use the macros.
+ (form_regexp): Ditto. Fix typo in access to fields of ALLOF.
+ (longest_path_length, min_issue_delay_pass_states,
+ output_dead_lock_vect, output_tables, output_insn_code_cases,
+ output_internal_insn_latency_func, output_print_reservation_func,
+ output_description, output_automaton_units, generate): Use the
+ macros.
+ (make_insn_alts_attr): Ditto. Check case when there are not
+ alternatives in the reservation.
+ (make_internal_dfa_insn_code_attr, make_default_insn_latency_attr,
+ make_bypass_attr, form_important_insn_automata_lists,
+ expand_automata): Use the macros.
+
+2002-06-20 Tim Josling <tej@melbpc.org.au>
+
+ * Makefile.in: Clean up code to check for misspecified languages
+ in enable-languages.
+
+2002-06-19 Andrew Pinski <pinskia@physics.uc.edu>
+
+ * cpptrad.c (_cpp_replacement_text_len): initialize len.
+
+2002-06-19 Jason Merrill <jason@redhat.com>
+
+ * Makefile.in (unstrap, restrap): New targets.
+ (bootstrap): Mention restrap.
+
+2002-06-19 Matt Kraai <kraai@alumni.cmu.edu>
+
+ * except.c (ehl_free): Remove.
+
+ * doc/tm.texi (TARGET_CPU_CPP_BUILTINS): Correct misnamings of
+ builtin_define and builtin_define_std.
+
+2002-06-19 Ian Dall <ian@sibyl.beware.dropbear.id.au>
+
+ * config/ns32k/ns32k.md: Give "*xxx" names to all unnamed insn's.
+ (sCOND): Restrict operand class so that gcc knows how to reload them.
+ (bitfield_set): Merge two unnamed insn's using alternatives.
+ (call_value): Remove constraint on unused uperand.
+ (udivmodhi4, udivmodsi4, udivmoddihi4_internal): Remove.
+ (udivmoddiqi4_internal, udivmoddihi4, udivmoddiqi4): Remove.
+
+ * longlong.h (count_trailing_zeros): Escape newline and beautify.
+
+2002-06-19 Mark Mitchell <mark@codesourcery.com>
+
+ * Makefile.in (QMTEST_DIR): Simplify definition.
+
+2002-06-19 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/d30v/d30v.h (CUMULATIVE_ARGS): Replace typedef with
+ #define.
+
+2002-06-19 Neil Booth <neil@daikokuya.co.uk>
+
+ * cpphash.h (struct cpp_reader): Make date and time strings.
+ (_cpp_builtin_macro_text, _cpp_copy_replacement_text,
+ _cpp_replacement_text_len): New.
+ * cppinit.c (cpp_create_reader): Update.
+ (init_builtins): Register appropriate builtins for -traditional-cpp.
+ * cppmacro.c (new_number_token): Remove.
+ (_cpp_builtin_macro_text): New.
+ (builtin_macro): Use it.
+ (cpp_macro_definition): Update to handle traditional macros.
+ * cppmain.c (cb_line_change): Don't do column positioning for
+ traditional output.
+ * cpptrad.c (enum ls): Rename ls_fun_macro to ls_fun_open. New
+ state ls_fun_close.
+ (skip_whitespace): Fix.
+ (maybe_start_funlike): Don't set state.parsing_args.
+ (scan_out_logical_line): Remove duplicate error. Use lex_state
+ rather than state.parsing_args.
+ (push_replacement_text): Handle builtins.
+ (_cpp_replacement_text_len, _cpp_copy_replacement_text): New.
+
+2002-06-18 Hans-Peter Nilsson <hp@axis.com>
+ Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * config/fp-bit.c (_fpmul_parts, _fpdiv_parts): Mark with
+ attribute __always_inline__.
+
+2002-06-18 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.h (FUNCTION_PROFILER): Respect flag_pic
+ when generating the call to _mcount.
+ (NO_PROFILE_COUNTERS): Define.
+
+2002-06-18 Richard Henderson <rth@redhat.com>
+
+ * print-rtl.c (print_rtx): Adjust NOTE argument numbers for
+ 2002-06-02 change.
+
+Tue Jun 18 20:53:32 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * t-sh (MULTILIB_EXCEPTIONS): Set to ml.
+ config/sh/t-linux (MULTILIB_EXCEPTIONS): Clear.
+ * config/sh/t-netbsd (MULTILIB_EXCEPTIONS): Likewise.
+ * config/sh/t-sh64 (MULTILIB_EXCEPTIONS): Likewise.
+
+ * sh-protos.h (sh_pr_interrupt): Declare.
+ * sh.c (sh_pr_interrupt): New function.
+ (print_operand, calc_live_regs, sh_expand_prologue): Use it.
+ (sh_hard_regno_rename_ok): Likewise.
+ * sh.h (NORMAL_MODE): FP_MODE_NONE for interupt handlers.
+
+2002-06-18 Vladimir Makarov <vmakarov@redhat.com>
+
+ * rtl.def (DEFINE_AUTOMATON): Add description of new options
+ `time' and `v'. Fix incorrect description of option `w'.
+
+ * doc/md.texi: Ditto.
+
+ * genautomata.c (TIME_OPTION, V_OPTION): New macros.
+ (gen_automata_option): Process the new options.
+ (transform_2, transform_3): Initialize some variables.
+ (initiate_automaton_gen): Use the new macros.
+
+2002-06-18 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips-protos.h (mips_initial_elimination_offset): Declare.
+ (mips_set_return_address, mips_restore_gp): Declare.
+ * config/mips/mips.h (struct mips_frame_info): Move to mips.c
+ (current_frame_info): Remove.
+ (INITIAL_ELIMINATION_OFFSET): Use mips_initial_elimination_offset.
+ * config/mips/mips.c: Remove uses of current_frame_info.
+ (struct mips_frame_info): Moved from mips.h. Remove 'insns_len'.
+ (struct machine_function): Add 'frame' and 'insns_len'.
+ (current_frame_info, zero_frame_info): Remove.
+ (mips_restore_gp, mips_set_return_address): New.
+ (mips_initial_elimination_offset): New.
+ * config/mips/mips.md (exception_receiver): Use mips_restore_gp.
+ (eh_return define_split): Use mips_set_return_address.
+
+2002-06-18 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpplib.c (dtable): Update.
+ (end_directive): Decrement expansion prevention count.
+ Clear state.in_expression.
+ (prepare_directive_trad): Set state.in_expression.
+ Increment expansion prevention count.
+ * cpptrad.c (enum ls): New.
+ (_cpp_overlay_buffer): Set overlaid_buffer.
+ (_cpp_remove_overlay): Use overlaid_buffer.
+ (_cpp_read_logcial_line_trad): Update buffer when it might
+ have changed.
+ (scan_out_logical_line): Handle state transitions for assertions
+ and defined() in #if, and for funlike invocations including the
+ directive case. Handle '<' and '>' as a quote mechanism in
+ #include. Warn about unterminated macro invocations.
+ * cpphash.h (struct lexer_state): New member in_expression.
+ (struct cpp_reader): New member overlaid buffer.
+
+2002-06-18 Hans-Peter Nilsson <hp@axis.com>
+
+ * config/cris/arit.c (do_31div, __Udiv, __Umod): Mark prototype
+ __always_inline__.
+
+2002-06-18 Alan Modra <amodra@bigpond.net.au>
+
+ * config/ia64/ia64.md (doloop_end_internal): Correct rtl.
+
+ * doloop.c (doloop_optimize): Extract pattern from insn.
+
+2002-06-17 Matt Kraai <kraai@alumni.cmu.edu>
+
+ * doc/extend.texi (Function Attributes): Remove `,...' from @var.
+
+2002-06-17 Jeff Law <law@redhat.com>
+
+ * libgcc2.c: Do not include symcat.h or machmode.h.
+
+2002-06-17 Richard Henderson <rth@redhat.com>
+
+ PR target/6922
+ * expmed.c (make_tree): Handle SIGN_EXTEND/ZERO_EXTEND.
+
+2002-06-17 Tom Tromey <tromey@redhat.com>
+
+ * dwarfout.c: Include function.h.
+
+2002-06-17 Andreas Schwab <schwab@suse.de>
+
+ * print-rtl.c (print_rtx): Print space before vector, not after.
+ (debug_rtx): Clear sawclose before printing.
+ (debug_rtx_list): Print newline after each list element.
+ (debug_rtx_range): Likewise.
+
+2002-06-17 Richard Henderson <rth@redhat.com>
+
+ * function.h (struct function) [funcdef_no]: Rename profile_label_no.
+ (current_function_funcdef_no): Similarly.
+ * function.c (funcdef_no): Similarly.
+ (prepare_function_start): Set current_function_funcdef_no.
+ (expand_function_start): Don't set current_function_profile_label_no.
+ * dwarf2out.h (current_funcdef_number): Remove.
+ * dwarf2out.c (current_funcdef_number): Remove. Replace with
+ current_function_funcdef_no throughout.
+ * dwarfout.c, vmsdbgout.c: Similarly.
+ * except.c (sjlj_funcdef_number): Remove.
+ (sjlj_emit_function_enter): Use current_function_funcdef_no instead.
+ (output_function_exception_table): Likewise.
+ * final.c (profile_function): Use current_function_funcdef_no
+ instead of current_function_profile_label_no.
+
+2002-06-17 Vladimir Makarov <vmakarov@redhat.com>
+
+ * sched-ebb.c (init_ready_list): Check INSN_P first.
+
+Mon Jun 17 17:26:15 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.md (divsi3): Update way how to find insns in a sequence.
+
+ * reload1.c (merge_assigned_reloads): Don't change reloads
+ other than RELOAD_FOR_INPUT_ADDRESS / RELOAD_FOR_INPADDR_ADDRESS
+ to RELOAD_OTHER when there are conflicting input reloads.
+
+2002-06-17 Richard Earnshaw (rearnsha@arm.com)
+
+ * function.c (epilogue_done): Correctly build a sequence of insns for
+ a sibcall epilogue.
+
+2002-06-17 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/fr30/fr30.h (CUMULATIVE_ARGS): Replace typedef with
+ #define.
+
+ * config/m32r/m32r.md: Replace gen_sequence with get_insns.
+
+2002-06-16 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.h (BIGGEST_FIELD_ALIGNMENT): Define instead
+ of ADJUST_FIELD_ALIGN if IN_TARGET_LIBS.
+
+2002-06-16 Richard Henderson <rth@redhat.com>
+
+ PR opt/6722
+ * regclass.c (globalize_reg): Update regs_invalidated_by_call.
+
+2002-06-16 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * config.gcc: Add i386/sysv4-cpp.h; remove i386-aout.h from vxworks.
+ * config/i386/i386-aout.h, config/i386/i386elf.h,
+ config/i386/sysv4.h: Remove CPP_PREDEFINES.
+ * config/i386/linux64.h, config/i386/i386elf.h, config/i386/mach.h,
+ config/i386/netware.h, config/i386/rtemself.h, config/i386/sco5.h,
+ config/i386/sol2.h, config/i386/vsta.h, config/i386/vxi386.h,
+ config/i386/win32.h: Use TARGET_OS_CPP_BUILTINS rather than
+ CPP_PREDEFINES and part of CPP_SPEC.
+ * config/i386/sysv4-cpp.h: New.
+
+2002-06-16 Richard Henderson <rth@redhat.com>
+
+ PR c/7030
+ * dwarf2out.c (modified_type_die): Don't assign the qualified die
+ to the unqualified type.
+
+Sun Jun 16 22:16:10 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386-protos.h (x86_field_alignment): Declare.
+ * i386.c (x86_field_alignment): Define.
+ * i386.h (ADJUST_FIELD_ALIGNMENT): New.
+ (BIGGEST_FIELD_ALIGNMENT): Kill.
+
+2002-06-16 Richard Henderson <rth@redhat.com>
+
+ * vax.md (casesi): Use emit_jump_insn. Tidy expander pattern.
+
+2002-06-16 Richard Henderson <rth@redhat.com>
+
+ * c-common.c (flag_ms_extensions): Move from c++ front end.
+ * c-common.h (flag_ms_extensions): Declare.
+ * c-decl.c (c_decode_option): Add -fms-extensions.
+ (grokfield): Don't accept anonymous structures in ISO C mode;
+ accept only unnamed anonymous structures in GNU C mode; accept
+ Plan 9 extensions in MS mode.
+ * c-parse.in (SAVE_EXT_FLAGS, RESTORE_EXT_FLAGS): Rename from
+ SAVE/RESTORE_WARN_FLAGS; add flag_iso frobbing; update all callers.
+ (extension): Clear flag_iso.
+ * doc/invoke.texi (C Dialect Options): Add -fms-extensions.
+
+2002-06-16 Hans-Peter Nilsson <hp@axis.com>
+
+ PR target/7042
+ * reorg.c (make_return_insns) [DELAY_SLOTS_FOR_EPILOGUE]: Exit
+ early if current_function_epilogue_delay_list is non-empty.
+ * config/cris/cris.md ("return"): Add sanity check asserting that
+ current_function_epilogue_delay_list is empty.
+
+2002-06-16 Jeff Law <law@redhat.com>
+
+ * emit-rtl.c (gen_rtx_REG): Temporarily turn off automatic
+ sharing of hard registers.
+
+ * toplev.c (rest_of_compilation): Remove redundant conditional.
+
+ * toplev.c (rest_of_compilation): Perform a simpler, less costly
+ cleanup of the CFG when not optimizing.
+
+2002-06-16 Alan Modra <amodra@bigpond.net.au>
+
+ * gcc.c (main): Correct startfile_prefix_spec check.
+
+2002-06-12 Geoffrey Keating <geoffk@redhat.com>
+
+ * config.gcc: Revert rth's patch of 2002-05-18. Instead,
+ include both darwin.o and rs6000-c.o.
+
+2002-06-15 Roger Sayle <roger@eyesopen.com>
+
+ * expr.c (compare_from_rtx): Call simplify_relational_operation
+ on all comparisons, not just those between integer constants,
+ with the correct (possibly unsigned) comparison code.
+ (do_compare_rtx_and_jump): Likewise.
+
+2002-06-15 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * Makefile.in (tm_defines): New configuration variable.
+ (cs-config.h, cs-hconfig.h, cs-tconfig.h): Rename DEFINES to XM_DEFINES.
+ Pass tm_defines in TM_DEFINES.
+ (cs-tm_p.h): Rename DEFINES to XM_DEFINES. Pass TM_DEFINES.
+ * config.gcc (tm_defines): New configuration variable.
+ (hppa*-*-* | parisc*-*-*): Use tm_defines instead of pa-700.h and
+ pa-7100.h headers. Change hppa1* scheduling default to 7100LC.
+ * configure.in: Substitute tm_defines.
+ * configure: Rebuilt.
+ * mkconfig.sh: Rename DEFINES to XM_DEFINES. Output TM_DEFINES.
+ * doc/install.texi: Update.
+ * pa/pa-700.h: Delete file.
+ * pa/pa-7100.h: Delete file.
+
+2002-06-15 Roger Sayle <roger@eyesopen.com>
+
+ * fold-const.c (comparison_to_compcode): New function to convert
+ an comparison TREE CODE into a bit-based representation.
+ (compcode_to_comparison): New function to convert from this bit
+ based representation back to a comparison TREE CODE.
+ (fold_truthop): Simplify (x<y) && (x==y) and related composite
+ comparisons.
+
+2002-06-15 Aldy Hernandez <aldyh@redhat.com>
+
+ * tm.texi (MEMBER_TYPE_FORCES_BLK): Document MODE argument.
+
+ * stor-layout.c (compute_record_mode): Remove check for
+ FUNCTION_ARG_REG_LITTLE_ENDIAN and VOIDmode when checking for
+ MEMBER_TYPE_FORCES_BLK. Pass new mode field to
+ MEMBER_TYPE_FORCES_BLK.
+
+ * config/ia64/hpux.h (MEMBER_TYPE_FORCES_BLK): Same.
+
+ * config/c4x/c4x.h (MEMBER_TYPE_FORCES_BLK): Same.
+
+2002-06-14 Jeff Sturm <jsturm@one-point.com>
+
+ * config/sparc/sparc.h (DYNAMIC_CHAIN_ADDRESS): Add SPARC_STACK_BIAS.
+
+2002-06-14 Steve Ellcey <sje@cup.hp.com>
+
+ * configure.in (USE_UNWIND_EXCEPTIONS): Add support to set
+ USE_UNWIND_EXCEPTIONS if --enable-libunwind-exceptions is set.
+ * configure, config.in: Regenerate.
+
+2002-06-14 Eric Botcazou <ebotcazou@multimania.com>
+
+ * loop.c (check_final_value): Use v->always_executed
+ instead of v->always_computable.
+ * unroll.c (final_giv_value): Don't calculate the final
+ value as a function of the biv if the giv is not computed
+ for every loop iteration.
+
+2002-06-14 Eric Botcazou <ebotcazou@multimania.com>
+
+ * loop.c (for_each_insn_in_loop): Fix formatting and comments.
+
+2002-06-14 Eric Botcazou <ebotcazou@multimania.com>
+
+ PR c/6677
+ * convert.c (convert_to_integer) [LSHIFT_EXPR]: Don't pass
+ the truncation down when the target type is signed.
+ [trunc1]: Use unsigned arithmetic for LSHIFT_EXPR.
+ * fold-const.c (extract_muldiv) [NOP_EXPR]: Don't pass through
+ the conversion if the target type is a smaller type.
+
+2002-06-14 Richard Henderson <rth@redhat.com>
+
+ * fold-const.c (fold) [compare ops]: Move X>=C / X<C transfomation
+ earlier. Re-factor comparisons vs extrema.
+
+2002-06-14 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.md (builtin_zapnot): Fix op2 mode.
+
+2002-06-14 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ * rtl.h (SCHED_GROUP_P): Disallow CODE_LABEL, BARRIER and NOTE.
+ * sched-deps.c (add_dependence): Likewise.
+ (group_leader): Likewise.
+ * sched-rgn.c (init_ready_list): Likewise.
+ * doc/rtl.texi: Adjust accordingly.
+
+2002-06-13 Jeffrey Law <law@redhat.com>
+
+ * gcse.c (delete_null_pointer_checks_1): Inform caller if any
+ null pointer checks were eliminated. Update prototype.
+ (delete_null_pointer_checks): Similarly.
+ * rtl.h (delete_null_pointer_checks): Update prototype.
+ * toplev.c (rest_of_compilation): Only run cleanup_cfg if
+ delete_null_pointer_checks deletes one or more null
+ pointer checks. Do not run cleanup_cfg before gcse, the
+ CFG is accurate and optimized at that point..
+
+ * rs6000.c (rs6000_frame_related): Avoid unwanted sharing
+ of hard registers.
+
+2002-06-14 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * Makefile.in (libgcc.mk): Depend on specs.
+
+Fri Jun 14 12:15:11 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.md (mulsi3): Update way how to find insns in a sequence.
+
+Fri Jun 14 12:04:02 2002 Dhananjay R. Deshpande <dhananjayd@kpit.com>
+
+ * sh.h: Define HARD_REGNO_RENAME_OK
+ * sh.c: sh_hard_regno_rename_ok: New. If current function has
+ interrupt_handler attribute, only registers saved on stack are OK.
+ * sh-protos.h: Declare sh_hard_regno_rename_ok.
+
+2002-06-14 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ * config/sh/sh.md (jump): Emit jump insn.
+ (call_pcrel): Get pattern of the result of gen_call_site.
+ (call_value_pcrel, sibcall_pcrel, GOTaddr2picreg): Likewise.
+
+2002-06-14 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpphash.h (struct cpp_buffer): Remove saved_line_base.
+ * cpptrad.c: Update comments.
+ (skip_whitespace, copy_comment): Take a new parameter.
+ (skip_escaped_newlines): Don't duplicate escaped newline test.
+ (copy_comment): Different location for CUR, decide here how
+ to copy / replace the comment.
+ (skip_whitespace): Copy whitespace.
+ (_cpp_overlay_buffer, _cpp_remove_overlay): Don't play with line_base.
+ (scan_out_logical_line): Let copy comment handle keeping or
+ replacing comments.
+ (scan_parameters, _cpp_create_trad_definition): Update.
+
+2002-06-13 Alan Lehotsky <apl@alum.mit.edu>
+
+ * reload.c (get_secondary_mem,find_reloads_address,
+ find_reloads_address_1): Pass reference to MEM to find_reloads_address
+ so that LEGITIMIZE_RELOAD_ADDRESS will be called.
+
+2002-06-13 Jessica Han <jessica@cup.hp.com>
+
+ * defaults.h (TARGET_VTABLE_ENTRY_ALIGN): New.
+ (TARGET_VTABLE_DATA_ENTRY_DISTANCE): New.
+ * doc/tm.texi: Document them.
+ * config/ia64/ia64.h (TARGET_VTABLE_ENTRY_ALIGN): New.
+ (TARGET_VTABLE_DATA_ENTRY_DISTANCE): New.
+ (TARGET_VTABLE_USES_DESCRIPTORS): 4 word descriptors for 32-bit mode.
+ (ASM_OUTPUT_FDESC): Likewise.
+
+2002-06-13 Eric Christopher <echristo@redhat.com>
+
+ * diagnostic.c (output_format): Fix thinko.
+
+Thu Jun 13 22:34:33 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * config/sh/coff.h (HAS_INIT_SECTION, INVOKE__MAIN): Don't define.
+ (DWARF2_UNWIND_INFO): Define to 0.
+
+ * config/sh/sh.c (calc_live_regs): Don't use initial_value
+ optimization for PR_MEDIA_REG.
+
+2002-06-13 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpphash.h (_cpp_lex_identifier_trad): Remove.
+ * cpplib.c (end_directive): Don't skip, always remove overlay
+ apart from #define.
+ (prepare_directive_trad): Handle NULL pfile->directive.
+ (_cpp_handle_directive): Always call prepare_directive_trad
+ if traditional.
+ * cppmain.c (check_multiline_token): Rename account_for_newlines,
+ generalize inputs.
+ (scan_translation_unit_trad): Use it.
+ * cpptrad.c (skip_comment): Rename copy_comment, copy comment to
+ output, get escaped newline in comment close correct.
+ (check_output_buffer, skip_whitespace): Update.
+ (_cpp_lex_identifier_trad): Remove.
+ (scan_out_logical_line): Handle -C and comments in directives
+ properly.
+
+Thu Jun 13 20:18:38 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * config.gcc: Add support for sh[234]*-*-elf*, sh[2346lbe]*-*-linux*.
+ * config/sh/linux.h (TARGET_DEFAULT): Use TARGET_CPU_DEFAULT.
+ * sh.h (SELECT_SH1, SELECT_SH2, SELECT_SH3, SELECT_SH3E): New macros.
+ (SELECT_SH4_NOFPU, SELECT_SH4_SINGLE_ONLY, SELECT_SH4): Likewise.
+ (SELECT_SH4_SINGLE, SELECT_SH5_64, SELECT_SH5_64_NOFPU): Likewise.
+ (SELECT_SH5_32, SELECT_SH5_32_NOFPU, SELECT_SH5_COMPACT): Likewise.
+ (SELECT_SH5_COMPACT_NOFPU): Likewise.
+ (TARGET_SWITCHES): Use them.
+ (TARGET_CPU_DEFAULT): Define if not already defined.
+ (TARGET_DEFAULT): Use it.
+ (LINK_DEFAULT_CPU_EMUL): Value now depends on TARGET_CPU_DEFAULT.
+ * config/sh/t-linux (MULTILIB_OPTIONS): Use MULTILIB_ENDIAN.
+ * config/sh/t-monolib: New file.
+
+2002-06-13 Roger Sayle <roger@eyesopen.com>
+
+ * toplev.c (rest_of_compilation): Simplify (and correct) the
+ logic of the first delete-null-pointer-checks pass.
+
+Thu Jun 13 18:24:17 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (ix86_expand_movstr): Fix pasto.
+
+Thu Jun 13 18:18:17 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * reload.c (find_valid_class): Fix thinko in my previous patch.
+
+2002-06-13 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.h (TARGET_CPU_CPP_BUILTINS): New macro.
+ * config/s390/linux.h (TARGET_OS_CPP_BUILTINS): New macro.
+ (CPP_PREDEFINES, CPP_SPEC, CPP_ARCH31_SPEC, CPP_ARCH64_SPEC): Remove.
+ (EXTRA_SPECS): Remove cpp_arch31 and cpp_arch64.
+
+2002-06-13 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * tree-inline.c (expand_call_inline): Don' mess with _DECL
+ fields.
+
+2002-06-13 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * diagnostic.c (output_format): Recognize "%H" as a format
+ specifier for a location_t.
+ (text_specifies_location): New function.
+ (diagnostic_set_info): Use it.
+
+2002-06-13 Jeffrey Law <law@redhat.com>
+
+ * emit-rtl.c (static_regno_reg_rtx): Define.
+ (init_emit_once): Initialize static_regno_reg_rtx.
+ (init_emit): Copy static_regno_reg_rtx into regno_reg_rtx instead
+ of building new hard reg objects once per function.
+ (gen_rtx_REG): Try to share hard regs.
+ * regclass.c (init_fake_stack_mems): New function broken out from
+ init_regs.
+ * rtl.h (init_fake_stack_mems): Declare.
+ * toplev.c (lang_independent_init): Call init_regs before
+ init_emit_once. Call init_fake_stack_mems after init_emit_once.
+
+ * i386.md (extenddfxf2, extenddftf2): Fix typo/thinko.
+
+ * alias.c (argument_registers): Remove.
+ (init_alias_once): Initialize static_reg_base_value here. Remove
+ initialization of argument_registers.
+ (init_alias_once_per_function): Remove.
+ (init_alias_analysis): Copy all the entries from static_reg_base_value
+ into new_reg_base_value all at once.
+ * rtl.h (init_alias_once_per_function): Remove declaration.
+ * function.c (prepare_function_start): Do not call
+ init_alias_once_per_function.
+
+ * caller-save.c (init_caller_save): Use gen_rtx_INSN instead of
+ starting a sequence and emitting an INSN.
+
+2002-06-13 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/r3900.h (MIPS_CPU_STRING_DEFAULT): Make lower case.
+
+2002-06-13 David S. Miller <davem@redhat.com>
+
+ * expmed.c (init_expmed): Remove duplicate init of 'reg'.
+
+2002-06-13 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpplib.c (end_directive): Handle line skipping. Only remove
+ the rest of the line if the directive was valid.
+ * cppmacro.c (_cpp_push_text_context): Set NODE_DISABLED when
+ expanding a traditional macro.
+ * cpptrad.c (recursive_macro): New.
+ (read_logical_line_trad): Handle skipping.
+ (scan_out_logical_line): Continue after a successful directive.
+ Don't expand macros whilst skipping, or if recursing.
+ (_cpp_create_trad_definition): scan_out_logical_line now sets
+ the output current position.
+
+2002-06-12 Eric Christopher <echristo@redhat.com>
+
+ From Chris Demetriou <cgd@broadcom.com>
+ * config/mips/mips.h (ISA_HAS_FP4): Add ISA_MIPS64 and fix
+ comment.
+ (ISA_HAS_MADD_MSUB): Ditto.
+ (ISA_HAS_NMADD_NMSUB): Ditto.
+
+2002-06-12 Eric Christopher <echristo@redhat.com>
+
+ * config.gcc: Consolidate little endian handling and
+ little/big endian targets.
+ * config/mips/elfl.h: Remove file.
+ * config/mips/elfl64.h: Ditto.
+ * config/mips/ecoffl.h: Ditto.
+ * config/mips/r3900.h (SUBTARGET_CPP_SPEC): Remove.
+
+2002-06-12 Geoffrey Keating <geoffk@redhat.com>
+
+ * gengtype.h (xvasprintf): New prototype.
+ (xasprintf): New prototype.
+ (struct outf): New.
+ (get_output_file): Return an outf_p.
+ (header_file): Is now an outf_p.
+ (base_files): Now are outf_p.
+ (oprintf): New.
+ * gengtype.c: Replace all output FILE * with outf_p; use oprintf
+ rather than stdio operations. Use xasprintf in a few places,
+ when appropriate.
+ (xvasprintf): New.
+ (xasprintf): New.
+ (struct filemap): Delete.
+ (files): Delete.
+ (output_files): New.
+ (oprintf): New.
+ (create_file): Create an outf_p. Add parameter to indicate output
+ file name, change all callers.
+ (open_base_files): Create gtype-desc.c here.
+ (get_output_file_with_visibility): Rewrite.
+ (get_output_file_name): Just look at 'name' field in struct outf.
+ (close_output_files): Rewrite.
+
+2002-06-12 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/vax/vax.h (MASK_UNIX_ASM, MASK_VAXC_ALIGNMENT)
+ (MASK_G_FLOAT): Define.
+ (TARGET_UNIX_ASM, TARGET_VAXC_ALIGNMENT, TARGET_G_FLOAT): Use them.
+ (TARGET_SWITCHES): Likewise.
+ (TARGET_DEFAULT): Likewise.
+
+2002-06-12 Daniel Jacobowitz <drow@mvista.com>
+
+ * config/mips/elf.h (DWARF2_DEBUG_INFO): Define.
+ * config/mips/mips.c (mips_output_filename): Don't print a
+ ".file" directive if we are using DWARF-2.
+ (mips_output_function_prologue): Do not emit source file
+ name for TARGET_GAS.
+
+Wed Jun 12 16:45:13 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (shift patterns): Use (TARGET_SHIFT1 || optimize_size) to
+ decide whether emit the short opcode.
+ * i386.h (x86_shift1): Declare.
+ (TARGET_SHIFT1): New macro.
+ * i386.c (x86_shift1): New global variable.
+
+ * toplev.c (rest_of_compilation): Call find_basic_block pre-loop
+ unconditionally; make loop to rebuild CFG; kill unnecesary
+ find_basic_block calls; kill compute_bb_for_insn call.
+ * cfgbuild.c (find_basic_blocks): Kill compute_bb_for_insn call.
+ * haifa-sched.c (sched_init): Likewise.
+ * ssa-ccp.c (ssa_const_prop): Likewise.
+ * ssa-dce.c (ssa_eliminate_dead_code): Likewise.
+
+2002-06-11 David S. Miller <davem@redhat.com>
+
+ * emit-rtl.c (emit_*_scope): Only access INSN_SCOPE if
+ active_insn_p.
+
+2002-06-11 Richard Henderson <rth@redhat.com>
+
+ * c-common.c (builtin_define_type_max): New.
+ (cb_register_builtins): Define __SCHAR_MAX__, __SHRT_MAX__,
+ __INT_MAX__, __LONG_MAX__, __LONG_LONG_MAX__, __CHAR_BIT__.
+
+ From Joseph S. Myers:
+ * glimits.h: Rewrite to expect the double underscore definitions
+ from the compiler.
+
+ * config/alpha/unicosmk.h, config/avr/avr.h, config/h8300/h8300.h,
+ config/i386/linux64.h, config/ia64/aix.h, config/ia64/hpux.h,
+ config/ia64/ia64.h, config/m68hc11/m68hc11.h, config/m68hc11/m68hc12.h,
+ config/mips/mips.h, config/mmix/mmix.h, config/mn10200/mn10200.h,
+ config/pa/pa.h, config/rs6000/aix43.h, config/rs6000/aix51.h,
+ config/rs6000/linux64.h, config/s390/linux.h, config/sh/sh.h,
+ config/stormy16/stormy16.h: Don't define any of __SHRT_MAX__,
+ __INT_MAX__, __LONG_MAX__, or __LONG_LONG_MAX__.
+
+2002-06-11 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (ALPHA_BUILTIN_THREAD_POINTER): New.
+ (ALPHA_BUILTIN_SET_THREAD_POINTER): New.
+ (code_for_builtns): Update.
+ (alpha_init_builtins): Add __builtin_thread_pointer and
+ __builtin_set_thread_pointer.
+ (alpha_expand_builtin): Handle void builtins.
+ * doc/extend.texi (Alpha Built-in Functions): Update.
+
+2002-06-11 Hans-Peter Nilsson <hp@axis.com>
+
+ PR target/6997
+ * config/cris/cris.md ("sleu"): Set attribute "cc" to "none".
+
+2002-06-11 Zack Weinberg <zack@codesourcery.com>
+
+ * config.gcc: Make the name of the extra-modes file adjustable
+ by target stanzas.
+ (s390x, strongarm, xscale stanzas): Use this facility.
+ * configure.in: Update to match.
+ * configure: Regenerate.
+
+2002-06-11 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c (rs6000_emit_minmax): Treat unsigned
+ max/mins as unsigned GE compares.
+
+2002-06-11 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config.gcc (vax-*-bsd*): Add vax/bsd.h to ${tm_file}.
+ * config/vax/bsd.h: New file.
+ * config/vax/netbsd.h: Add missing notice.
+ (CPP_PREDEFINES): Remove.
+ (TARGET_OS_CPP_BUILTINS): Define.
+ (CPP_SPEC): Use NETBSD_CPP_SPEC.
+ * config/vax/openbsd.h: Update copyright years.
+ (CPP_PREDEFINES): Remove.
+ (TARGET_OS_CPP_BUILTINS): Define.
+ * config/vax/ultrix.h: Likewise.
+ * config/vax/vaxv.h: Likewise.
+ * config/vax/vms.h: Likewise.
+ * config/vax/vax.h (TARGET_CPU_CPP_BUILTINS): Define.
+ (CPP_PREDEFINES, CPP_SPEC): Remove.
+
+Wed Jun 12 01:50:28 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (addqi_1_slp, subqi_1_slp
+ (andqi_ext0, testqi_ext0): Remove unnecesary check.
+ (addhi*, addqi*): Simplify "dec" condition.
+ (testsi to testqi splitters): Remove TARGET_PROMOTE_QImode check.
+ (and, or, xor to QImode splitters): New.
+ (iorqi_ext*): New.
+ (xorqi_ext_0): New.
+ (xorqi_ext_1): Rename to xorqi_ext_2; bring to sync with and versions.
+ (andqi_ext_1_rex64): New.
+ (ashrqi*_slp): New.
+ (ashlqi*_slp): New.
+ (lshlqi*_slp): New.
+ (rotrqi3*_slp): New.
+ (rotlqi3*_slp): New.
+
+2002-06-11 Geoffrey Keating <geoffk@redhat.com>
+
+ * config.gcc (powerpc*-*-*, rs6000-*-*-*): Don't bother including
+ softfloat.h.
+ * config/rs6000/vxppc.h (CPP_ENDIAN_BIG_SPEC): Delete.
+ (CPP_ENDIAN_LITTLE_SPEC): Delete.
+ * config/rs6000/sysv4le.h (CPP_ENDIAN_DEFAULT_SPEC): Delete.
+ * config/rs6000/sysv4.h (CPP_SYSV_SPEC): Delete _SOFT_FLOAT setting,
+ __LONG_DOUBLE_128__ setting, _CALL_* setting.
+ (CPP_DEFAULT_SPEC): Delete.
+ (CPP_FLOAT_DEFAULT_SPEC): Delete.
+ (CPP_LONGDOUBLE_DEFAULT_SPEC): Delete.
+ (CPP_SYSV_DEFAULT_SPEC): Delete.
+ (CPP_ENDIAN_BIG_SPEC): Delete.
+ (CPP_ENDIAN_LITTLE_SPEC): Delete.
+ (CPP_ENDIAN_SPEC): Delete.
+ (CPP_SPEC): Don't include cpp_endian, cpp_cpu.
+ (SUBTARGET_EXTRA_SPECS): Delete cpp_sysv_default, cpp_endian_default,
+ cpp_endian, cpp_endian_big, cpp_endian_little, cpp_float_default,
+ cpp_longdouble_default.
+ * config/rs6000/softfloat.h: Delete.
+ * config/rs6000/rs6000.h (CPP_CPU_SPEC): Delete.
+ (EXTRA_SPECS): Delete cpp_cpu.
+ (TARGET_CPU_CPP_BUILTINS): New.
+ * config/rs6000/rs6000-protos.h (rs6000_cpu_cpp_builtins): New
+ prototype.
+ * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): New.
+ * config/rs6000/linux64.h (CPP_PREDEFINES): Remove endianness defines.
+ (CPP_DEFAULT_SPEC): Delete.
+ * config/rs6000/eabiaix.h (CPP_SYSV_DEFAULT_SPEC): Delete.
+ * config/rs6000/darwin.h (CPP_PREDEFINES): Don't define __BIG_ENDIAN__.
+ * config/rs6000/beos.h (CPP_SPEC): Remove cpp_cpu.
+ (CPP_DEFAULT_SPEC): Delete.
+ * config/rs6000/aix51.h (CPP_SPEC): Remove cpp_cpu, -D_ARCH_PPC.
+ (CPLUSPLUS_CPP_SPEC): Likewise.
+ (CPP_CPU_SPEC): Delete.
+ (CPP_DEFAULT_SPEC): Delete.
+ * config/rs6000/aix43.h (CPP_SPEC): Remove cpp_cpu, -D_ARCH_PPC.
+ (CPLUSPLUS_CPP_SPEC): Likewise.
+ (CPP_CPU_SPEC): Delete.
+ (CPP_DEFAULT_SPEC): Delete.
+ * config/rs6000/aix41.h (CPP_SPEC): Remove cpp_cpu.
+ (CPP_DEFAULT_SPEC): Delete.
+ * config/rs6000/aix.h (CPP_SPEC): Remove cpp_cpu.
+ (CPP_DEFAULT_SPEC): Delete.
+
+ * doc/gty.texi: Small updates.
+
+2002-06-12 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * objc/objc-act.c (warn_with_ivar): Adjust calls to
+ diagnostic_count_error.
+ (warn_with_method): Likewise.
+
+ * diagnostic.h (warnings_are_errors_message): New field of
+ diagnostic_context.
+ (diagnostic_count_error): Rename to diagnostic_count_diagnostic to
+ match semantics.
+ * diagnostic.c: Adjust calls to diagnostic_count_error through out.
+ (diagnostic_count_diagnostic): Make aware of other kinds of
+ diagnostics.
+ (diagnostic_initialize): Initialize warnings_are_errors_message field.
+
+2002-06-11 Tom Tromey <tromey@redhat.com>
+
+ For PR java/6520:
+ * fold-const.c (fold_convert): Don't modify existing tree's type.
+
+2002-06-11 Geoffrey Keating <geoffk@redhat.com>
+
+ * config/rs6000/ppc-asm.h: Remove some Windows NT leftovers.
+
+2002-06-11 Richard Henderson <rth@redhat.com>
+
+ * caller-save.c (init_caller_save): Clear INSN_CODE each iteration.
+
+2002-06-11 Richard Henderson <rth@redhat.com>
+
+ * defaults.h (EH_FRAME_SECTION_NAME): Don't define if
+ DWARF2_UNWIND_INFO is false.
+
+2002-06-11 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/t-xtensa (LIBGCC1_TEST, CROSS_LIBGCC1): Delete.
+
+ * config/s390/s390.c (emit_prologue): gen_store_multiple
+ returns an insn now, not a pattern.
+
+2002-06-11 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * Makefile.in (gccinstall.dvi): Pass absolute pathnames to
+ $(TEXI2DVI) -o.
+
+Tue Jun 11 21:53:37 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (x86_promote_QImode): Set for Athlon
+ (x86_fast_prefix): New global variable.
+ (x86_arch_always_fancy_math_387): Fix formating.
+ * i386.h (x86_fast_prefix): Declare
+ (TARGET_FAST_PREFIX): define.
+ * i386.md (and to strict_low_part, HI to SI
+ promoting splitter): Use new macro.
+
+ * i386.h (RTX_COSTS): float_extend is not for free for SSE.
+
+2002-06-11 Zack Weinberg <zack@codesourcery.com>
+
+ * Makefile.in (distclean): Delete junk left in testsuite
+ directory, too.
+
+2002-06-11 Jeffrey Law <law@redhat.com>
+
+ * emit-rtl.c (try_split): Use INSN_LAST, not LAST_INSN to get the
+ last insn created by the splitter.
+
+ * caller-save.c (init_caller_save): Move creation of SAVEINSN
+ and RESTINSN into into the scope of the sequence.
+
+ * mips.c (mips_expand_prologue): Use emit_jump_insn for trivial
+ RETURN insns.
+
+ * loop.c (loop_regs_scan): Avoid useless generation of REG objects.
+
+ * mips.c (function_arg_advance): gen_ashldi3 returns an INSN now,
+ not the pattern. So extract the pattern from the insn.
+
+ * mips.c (embedded_pic_fnaddr_reg): Fix typo.
+
+2002-06-11 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.md (movsi): Only use floating point
+ register alternatives when operands are already fprs.
+ (movdi_31, movdi_64): Likewise.
+
+2002-06-11 David S. Miller <davem@redhat.com>
+
+ * emit-rtl.c (try_split): Do not abort on non-INSN_P.
+ Only run RTX equality checks on INSN_P rtl.
+
+2002-06-11 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.md (reload_base, ltorg): Remove.
+ * s390.c (s390_stop_dump_lit_p, s390_dump_literal_pool,
+ s390_asm_output_pool_prologue, s390_pool_start_insn): Remove.
+ * s390-protos.h (s390_stop_dump_lit_p, s390_dump_literal_pool,
+ s390_asm_output_pool_prologue): Likewise.
+ * s390.h (s390_pool_start_insn): Likewise.
+
+ * s390.c (s390_output_symbolic_const): Remove support for
+ old-style pool chunks.
+ (s390_function_epilogue): Likewise.
+ (s390_output_constant_pool): Likewise. Also, fix incorrect
+ alignment for 64-bit literal pools.
+ (print_operand_address): Remove 'y' and 'Y' format flags.
+ * s390.h (ASM_OUTPUT_POOL_PROLOGUE): Remove support for
+ old-style pool chunks.
+ (ASM_OUTPUT_SPECIAL_POOL_ENTRY): Likewise.
+ (ASM_OUTPUT_POOL_EPILOGUE): Remove.
+ (S390_CHUNK_MAX, S390_CHUNK_OV, S390_POOL_MAX): Remove.
+
+ * s390.c (consttable_operand): New function.
+ * s390-protos.h (consttable_operand): Declare it.
+ * s390.h (PREDICATE_CODES): Add consttable_operand.
+ * s390.md (consttable_qi, consttable_hi, consttable_si, consttable_di,
+ consttable_sf, consttable_df, pool_start_31, pool_end_31,
+ pool_start_64, pool_end_64, reload_base, reload_base2): New insns.
+ * s390.c (struct constant, struct constant_pool): New data types.
+ (constant_modes, gen_consttable): New variables.
+ (s390_start_pool, s390_end_pool, s390_add_pool,
+ s390_dump_pool, s390_free_pool): New functions.
+ (s390_chunkify_pool): Completely reimplement literal pool
+ overflow handling.
+
+ * s390.c (s390_pool_overflow): New variable.
+ * s390.h (s390_pool_overflow): Declare it.
+ * s390.md (cjump, icjump): Use it to adapt length for out-of-range
+ jumps in literal pool overflow situations.
+
+ * s390.c (s390_decompose_address): Accept new-style pool chunk offsets.
+ (s390_frame_info): Account for possible use of RETURN_REGNUM
+ by new literal pool overflow code.
+ (s390_emit_prologue): Likewise.
+
+2002-06-05 David S. Miller <davem@redhat.com>
+
+ Delete SEQUENCE rtl usage outside of reorg and ssa passes.
+ * rtl.h (gen_sequence, emit_insns, emit_insns_before,
+ emit_insns_before_scope, emit_insns_after,
+ emit_insns_after_scope): Delete declaration.
+ * ada/misc.c (insert_code_for): Use emit_insn* instead of
+ emit_insns_foo.
+ * config/alpha/alpha.c (alpha_set_memflags_1): Abort on SEQUENCE.
+ (alpha_set_memflags): Fix comment.
+ (set_frame_related_p): Use get_insns instead of gen_sequence.
+ * config/alpha/alpha.md (setjmp receiver splitter): Avoid
+ emitting no insns.
+ * config/arm/arm.c (arm_finalize_pic): Use get_insns instead of
+ gen_sequence.
+ (arm_gen_load_multiple, arm_gen_store_multiple): Likewise.
+ * config/fr30/fr30.c (fr30_move_double): Likewise.
+ * config/i386/i386.c (ix86_expand_int_movcc, ix86_expand_movstr):
+ Likewise.
+ * config/ia64/ia64.c (spill_restore_mem): Likewise.
+ * config/ia64/ia64.md (conditional move spliiter): Avoid emitting
+ no insns.
+ * config/m32r/m32r.c (gen_split_move_double): Use get_insns
+ instead of gen_sequence.
+ * config/mips/mips.c (embedded_pic_fnaddr_reg): Likewise.
+ (mips_expand_prologue, mips16_gp_pseudo_reg): Likewise.
+ * config/sh/sh.c (sh_need_epilogue): Likewise.
+ * config/sparc/sparc.md (current_function_calls_alloca, flat): New
+ attributes.
+ (setjmp pattern and split): Use them to avoid splitter which emits
+ no RTL.
+ * genattrtab.c (main): Emit include of function.h
+ * config/stormy16/stormy16.c (xstormy16_split_cbranch): Use
+ get_insns instead of gen_sequence.
+ * config/cris/cris.c (cris_split_movdx): Likewise.
+ * emit-rtl.c (emit_insns*): Kill.
+ (try_split): Expect insn list instead of SEQUENCE.
+ (make_jump_insn_raw, make_call_insn_raw): Fix comments.
+ (emit_*insn*): Reimplement to work with INSN lists and PATTERNs.
+ Make them abort if a SEQUENCE is given and RTL checking is
+ enabled.
+ (emit_*_scope): Don't forget to set scope on final insn.
+ (gen_sequence): Move from here...
+ * ssa.c (gen_sequence): To here as private function.
+ * builtins.c (expand_builtin_apply_args): Use emit_insn_foo, fix
+ comments.
+ (expand_builtin_return, expand_builtin_mathfn): Likewise.
+ (expand_builtin_strlen): Use get_insns instead of gen_sequence.
+ (expand_builtin_saveregs): Use emit_insn_foo, fix comments.
+ (expand_builtin_expect_jump): Use get_insns and fix comments.
+ * calls.c (try_to_integrate): Use emit_insn_foo.
+ (expand_call, emit_library_call_value_1): Likewise.
+ * expr.c (emit_queue): Handle insn lists instead of SEQUENCE.
+ (emit_move_insn_1): Use get_insns instead of gen_sequence.
+ (expand_expr): Use emit_insn_foo.
+ * cfgrtl.c (commit_one_edge_insertion): Use emit_insn_foo.
+ * except.c (build_post_landing_pads): Likewise.
+ * flow.c (attempt_auto_inc): Likewise.
+ * stmt.c (expand_fixup, fixup_gotos, expand_nl_handler_label,
+ expand_nl_goto_receivers, expand_decl_cleanup): Likewise.
+ * function.c (fixup_var_refs_insn): Use get_insns instead of
+ gen_sequence.
+ (fixup_var_refs_1): Likewise and expect insn list from gen_foo.
+ (fixup_memory_subreg): Use get_insns instead of gen_sequence.
+ (fixup_stack_1, purge_addressof_1, expand_main_function,
+ get_arg_pointer_save_area): Likewise.
+ (optimize_bit_field, instantiate_virtual_regs_1, assign_parms,
+ expand_function_end): Use emit_insn_foo.
+ (record_insns, keep_stack_depressed): Work with insn list instead
+ of SEQUENCE, fix comments.
+ * ifcvt.c (noce_emit_store_flag, noce_try_store_flag,
+ noce_try_store_flag_constants, noce_try_store_flag_inc,
+ noce_try_store_flag_mask, noce_emit_cmove, noce_try_cmove_arith,
+ noce_try_minmax, noce_try_abs): Use emit_insn_foo.
+ (noce_process_if_block): Use get_insns instead of gen_sequence.
+ * optabs.c (add_equal_note): Work with insn list, fix comments.
+ (expand_binop): Expect insn list from GEN_FCN(), use emit_insn_foo.
+ (expand_unop, expand_complex_abs, expand_unop_insn,
+ expand_no_conflict_block): Likewise.
+ (gen_move_insn): Use get_insns instead of gen_sequence.
+ (gen_cond_trap): Likewise.
+ * integrate.c (copy_rtx_and_substitute): Likewise.
+ (emit_initial_value_sets): Use emit_insn_foo.
+ * reload1.c (emit_output_reload_insns, emit_reload_insns): Likewise.
+ (fixup_abnormal_edges): Avoid losing REG_NOTES more intelligently
+ now that RTL generators give insn lists.
+ * sibcall.c (replace_call_placeholder): Use emit_insn_foo.
+ * doloop.c (doloop_modify, doloop_modify_runtime): Use get_insns
+ instead of gen_sequence.
+ (doloop_optimize): Work with insn lists instead of SEQUENCE rtl.
+ * explow.c (emit_stack_save, emit_stack_restore): Use get_insns
+ instead of gen_sequence.
+ * loop.c (move_movables, emit_prefetch_instructions,
+ gen_add_mult, check_dbra_loop, gen_load_of_final_value):
+ Likewise.
+ (loop_regs_update): Work with insn list instead of SEQUENCE rtl.
+ (product_cheap_p): Likewise, and add commentary about RTL wastage
+ here.
+ * lcm.c (optimize_mode_switching): Use get_insns instead of
+ gen_sequence.
+ * profile.c (gen_edge_profiler): Likewise.
+ * regmove.c (copy_src_to_dest): Likewise.
+ * reg-stack.c (compensate_edge): Likewise and fix comment.
+ * gcse.c (process_insert_insn): Likewise.
+ (insert_insn_end_bb): Work with insn list instead of SEQUENCE rtl.
+ * jump.c (delete_prior_computation): Update comment.
+ * genemit.c (gen_expand, gen_split, main): Use get_insns instead
+ of gen_sequence, update comments to match.
+ * recog.c (peephole2_optimize): Work with insn lists instead of
+ SEQUENCE rtl.
+ * sched-vis.c (print_pattern): Abort on SEQUENCE.
+ * unroll.c (unroll_loop, find_splittable_givs, final_giv_value):
+ Use get_insns instead of gen_sequence.
+ (copy_loop_body): Likewise and don't emit dummy NOTE.
+ * genrecog.c: Don't mention SEQUENCE rtl in comments.
+ * combine.c (try_combine): Expect insn lists from split generator.
+ * reorg.c (relax_delay_slots): Emit SEQUENCE into insn list by
+ hand.
+
+2002-06-11 Roger Sayle <roger@eyesopen.com>
+ Andreas Jaeger <aj@suse.de>
+
+ * cfgbuild.c: Update copyright years.
+
+2002-06-11 Andreas Schwab <schwab@suse.de>
+
+ * config/m68k/m68k.h (PREDICATE_CODES): Define.
+
+2002-06-11 Eric Christopher <echristo@redhat.com>
+
+ * doc/tm.texi (Run-time Target): Add comment about flag_iso
+ and strict ANSI.
+ * config/mips/ecoff.h (CPP_PREDEFINES): Remove.
+ * config/mips/ecoffl.h: Ditto.
+ * config/mips/elf64.h (SUBTARGET_CPP_SPEC): Remove.
+ (CPP_PREDEFINES): Ditto.
+ * config/mips/elfl64.h: Ditto.
+ * config/mips/elfl.h: Ditto.
+ * config/mips/iris3.h (CPP_PREDEFINES, SUBTARGET_CPP_SPEC): #if 0
+ out until irix header consolidation.
+ * config/mips/iris5.h (CPP_PREDEFINES, SUBTARGET_CPP_SPEC): Replace
+ with SUBTARGET_OS_CPP_BUILTINS.
+ * config/mips/iris6.h: Ditto.
+ (CPLUSPLUS_CPP_SPEC): Remove.
+ * config/mips/linux.h: Ditto.
+ * config/mips/netbsd.h: Ditto.
+ * config/mips/openbsd.h: Ditto.
+ * config/mips/rtems.h: Ditto.
+ * config/mips/rtems64.h: Ditto.
+ * config/mips/sni-svr4.h: Ditto.
+ * config/mips/mips.h (ISA_MIPS1, ISA_MIPS2, ISA_MIPS3, ISA_MIPS4,
+ ISA_MIPS32, ISA_MIPS64): New defines.
+ (GENERATE_MULT3_SI, HAVE_SQRT_P, ISA_HAS_64BIT_REGS,
+ ISA_HAS_BRANCHLIKELY, ISA_HAS_CONDMOVE, ISA_HAS_8CC, ISA_HAS_FP4,
+ ISA_HAS_COND_TRAP, ISA_HAS_MADD_MSUB, ISA_HAS_NMADD_NMSUB,
+ ISA_HAS_CLZ_CLO, ISA_HAS_DCLZ_DCLO): Use.
+ (TARGET_CPU_CPP_BUILTINS): Define.
+ (CPP_PREDEFINES, LONG_MAX_SPEC, CPP_FPR_SPEC, CPP_SPEC): Remove.
+ * config/mips/mips.md (mulsi3_mult3): Use ISA_MIPS32/64.
+ (movdicc): Remove check for ISA_MIPS32.
+ (bunordered, bordered, bungt, bunlt, buneq, bunge, bunle,
+ sunordered_df, sunordered_sf, sordered_df, sordered_sf,
+ sunlt_df, sunlt_sf, sungt_df, sungt_sf, suneq_df, suneq_sf, sunge_df,
+ sunge_sf, sunle_df, sunle_sf): New patterns.
+
+2002-06-11 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in: Update cppmain.o.
+ * cpphash.h (struct cpp_reader): Move some members to a
+ nested structure.
+ (trad_line): Rename saved_line.
+ (_cpp_read_logical_line_trad): Update.
+ (_cpp_remove_overlay): New.
+ * cppinit.c (cpp_create_reader): No need to set saved_line.
+ (cpp_destroy): Update.
+ (cpp_read_main_file): Only overlay if compiling.
+ * cpplex.c (continue_after_nul): Return false if in directive.
+ * cpplib.c (EXPAND): New.
+ (directive_table, SEEN_EOL): Update.
+ (end_directive): Remove overlay if traditional; don't skip
+ line in traditional #define.
+ (prepare_directive_trad): New.
+ (_cpp_handle_directive, run_directive): Update for traditional
+ directives.
+ (lex_macro_node): Simplify, don't use lex_identifier_trad.
+ * cpplib.h (struct options): Add preprocess_only.
+ * cppmain.c: Don't include intl.h.
+ (cpp_preprocess_file): Set options->preprocess_only.
+ (scan_translation_unit_trad): Fix, and print line numbers.
+ * cpptrad.c (check_output_buffer, lex_identifier, scan_parameters,
+ maybe_start_funlike, scan_out_logical_line, replace_args_and_push,
+ save_replacement_text, _cpp_create_trad_definition): Update for
+ variable renaming.
+ (_cpp_overlay_buffer): Save line number.
+ (_cpp_remove_overlay): Rename from restore_buff, restore line.
+ (_cpp_read_logical_line_trad): Don't handle overlays here.
+ (scan_out_logical_line): Process directives.
+
+2002-06-11 Danny Smith <dannysmith@users.sourforge.net>
+
+ * gthr-win32.h: Wrap functions in extern "C".
+ (__gthread_key_t): Typedef as unsigned long,
+ not win32 DWORD.
+ (__GTHREAD_ONCE_INIT): Use 0, not win32 FALSE.
+ (__gthread_mutex_t): Typedef as void*, not win32 HANDLE.
+ (__gthr_win32_once, __gthr_win32_key_create,
+ __gthr_win32_key_delete, __gthr_win32_getspecific,
+ __gthr_win32_setspecific, __gthr_win32_mutex_init_function,
+ __gthr_win32_mutex_lock,__gthr_win32_mutex_trylock,
+ __gthr_win32_mutex_unlock): Declare.
+ (__gthread_once,__gthread_key_create,
+ __gthread_key_delete, __gthread_getspecific,
+ __gthread_setspecific, __gthread_mutex_init_function,
+ __gthread_mutex_lock,__gthread_mutex_trylock,
+ __gthread_mutex_unlock): Call corresponding
+ __gthr_win32_* extern implementations if #defined
+ __GTHREAD_HIDE_WIN32API.
+ * config/i386/t-mingw32 (LIB2FUNCS_EXTRA): Set to
+ $(srcdir)/config/i386/gthr-win32.c
+ * config/i386/gthr-win32.c: New implementation file.
+ (__gthr_win32_once, __gthr_win32_key_create,
+ __gthr_win32_key_delete, __gthr_win32_getspecific,
+ __gthr_win32_setspecific, __gthr_win32_mutex_init_function,
+ __gthr_win32_mutex_lock,__gthr_win32_mutex_trylock,
+ __gthr_win32_mutex_unlock): New functions, based on
+ static inlines in gthr-win32.h.
+
+2002-06-10 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.c (override_options): Don't warn about
+ using -fpic or -fPIC when PIC is enabled by default.
+
+2002-06-10 Roger Sayle <roger@eyesopen.com>
+
+ * toplev.c (rest_of_compilation): Revert flag_if_conversion change.
+
+2002-06-10 Zack Weinberg <zack@codesourcery.com>
+
+ * Makefile.in (MACHMODE_H): Add @extra_modes_file@.
+ * configure.in: If $srcdir/config/${cpu_type}/${cpu_type}-modes.def
+ exists, substitute its pathname as @extra_modes_file@, define
+ EXTRA_MODES_FILE to be an appropriate string to #include it
+ with, and define EXTRA_CC_MODES to 1.
+
+ * machmode.def: Update comments. Include EXTRA_MODES_FILE if
+ it's defined. Get rid of redundancy in calling sequence for
+ CC; don't use it to define CCmode, to avoid a warning.
+ * libgcc2.c: Include symcat.h for the sake of machmode.def.
+
+ * arc-modes.def, arm-modes.def, c4x-modes.def, i386-modes.def,
+ i960-modes.def, ia64-modes.def, m88k-modes.def, mmix-modes.def,
+ pa-modes.def, pdp11-modes.def, rs6000-modes.def, sparc-modes.def:
+ New files.
+ * arc.h, arm.h, c4x.h, i386.h, i960.h, ia64.h, m88k.h, mmix.h,
+ pa.h, pdp11.h, rs6000.h, sparc.h: Don't define EXTRA_CC_MODES.
+
+ * doc/sourcebuild.texi, doc/tm.texi: Document new scheme for
+ defining extra CC modes.
+
+2002-06-10 Roger Sayle <roger@eyesopen.com>
+ Andreas Jaeger <aj@suse.de>
+
+ * cfgrtl.c (create_basic_block_structure): Remove index argument
+ and use last_basic_block++ instead. (create_basic_block): Update.
+ * cfgbuild.c (find_basic_blocks_1): Likewise.
+
+ * cfgrtl.c (compute_bb_for_insn): Remove unused "max" argument.
+ * haifa-sched.c (sched_init): Update compute_bb_for_insn caller.
+ * sched-ebb.c (schedule_ebbs): Likewise.
+ * sched-rgn.c (schedule_insns): Likewise.
+ * ssa-ccp.c (ssa_const_prop): Likewise.
+ * ssa-dcs.c (ssa_eliminate_dead_code): Likewise.
+ * toplev.c (rest_of_compilation): Likewise.
+ * config/ia64/ia64.c (ia64_reorg): Likewise.
+
+2002-06-10 Roger Sayle <roger@eyesopen.com>
+
+ * simplify-rtx.c (simplify_replace_rtx): Allow replacement
+ of matching registers.
+
+2002-06-10 Roger Sayle <roger@eyesopen.com>
+
+ * toplev.c (rest_of_compilation): Disable early if-conversion pass.
+ * gcse.c (bypass_conditional_jumps): Fix typo in setcc test.
+
+2002-06-10 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.h: Improve comments.
+ (CPP_SPEC, CPP_PREDEFINES): Don't define.
+ (TARGET_CPU_CPP_BUILTINS): Define.
+ (CANONICALIZE_COMPARISON): Don't define, replace with comment.
+ (PREDICATE_CODES) <"mmix_reg_or_8bit_or_256_operand">: Remove
+ unused predicate.
+ * config/mmix/mmix.c (MMIX_OUTPUT_REGNO): Add cast to avoid
+ compiler warning.
+ (mmix_constant_address_p): Remove another
+ redundant test before case.
+ (mmix_canonicalize_comparison): Remove unused function.
+ (mmix_print_operand_address): Don't test and adjust for operand in
+ non-canonical format.
+ (mmix_reg_or_8bit_or_256_operand): Remove unused predicate.
+ (mmix_gen_compare_reg): Don't use CANONICALIZE_COMPARISON.
+
+2002-06-10 Zack Weinberg <zack@codesourcery.com>
+
+ * config/m32r/m32r.h: Don't define SELECT_CC_MODE.
+ * config/m32r/m32r-protos.h: Don't prototype m32r_select_cc_mode.
+ * config/m32r/m32r.c: Don't define m32r_select_cc_mode.
+ (gen_compare): Use CCmode unconditionally.
+
+2002-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR optimization/6759
+ * cse.c (cse_insn): Fold src_eqv just once, store it folded back into
+ the REQ_EQUAL note.
+
+2002-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/6660
+ * c-decl.c (grokfield): Allow user defined types if they declare
+ structs or unions for unnamed fields.
+
+2002-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/6809
+ * print-rtl.c (print_mem_expr): Don't crash on unnamed fields.
+
+2002-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR optimization/6842
+ * combine.c (combine_simplify_rtx) [SUBREG]: Don't ICE if VOIDmode
+ operand subreg cannot be simplified.
+
+2002-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ * varasm.c (const_hash): Handle FDESC_EXPR like ADDR_EXPR.
+ (compare_constant): Likewise.
+ (output_addressed_constants): Likewise.
+
+2002-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ * cfgcleanup.c (try_optimize_cfg): Make sure merge_blocks doesn't
+ merge bb with itself.
+
+2002-06-10 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.md (builtin_zap): Fix thinkos expanding mask.
+ (builtin_zapnot): Likewise.
+
+ * config/alpha/ev5.md: Don't combine shift and mvi insns in one
+ reservation.
+
+2002-06-10 Eric Christopher <echristo@redhat.com>
+
+ * config/i386/i386.c (ix86_osf_output_function_prologue): Remove
+ prototype and function.
+ (TARGET_ASM_FUNCTION_PROLOGUE): Remove OSF version.
+ (call_insn_operand): Remove half pic references.
+ (legitimate_address_p): Ditto.
+ * config/i386/i386.h: Remove half pic defines.
+
+2002-06-10 Eric Christopher <echristo@redhat.com>
+
+ * doc/extend.texi (Return Address): Add note explaining the side-
+ effects of inlining on __builtin_return_address.
+
+2002-06-10 Tom Tromey <tromey@redhat.com>
+
+ * Makefile.in (LANGHOOKS_DEF_H): Include langhooks-def.h.
+ (c-common.o): Depend on langhooks.h.
+
+2002-06-10 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpphash.h (_cpp_read_logical_line_trad,
+ _cpp_expansions_different_trad): Update prototypes.
+ * cpplex.c (continue_after_nul): New.
+ * cppmain.c: Include cpphash.h.
+ (scan_translation_unit_trad): New.
+ (cpp_preprocess_file): Call it.
+ * cpptrad.c (_cpp_read_logical_line_trad): Take new parameter
+ overlay.
+ (_cpp_expansions_different_trad): Update prototype.
+
+Mon Jun 10 18:02:24 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ Fix cfi generation for SH[1-4]:
+
+ * sh.c (frame_insn): New function.
+ (output_stack_adjust): Add parameter emit_fn. All callers changed.
+ (push): Now returns rtx. Use frame_insn.
+ (sh_expand_prologue): Clear RTX_FRAME_RELATED_P for second push
+ of a DF register.
+ * sh.h (INCOMING_RETURN_ADDR_RTX, DWARF_FRAME_RETURN_COLUMN): Define.
+
+2002-06-10 Zack Weinberg <zack@codesourcery.com>
+
+ * Makefile.in (STAGESTUFF): Add s-gtype, gt-*.h, gtype-*.h,
+ and gtype-desc.c.
+ (mostlyclean): Delete specs.h, options.h, gencheck.h here...
+ (distclean): ... not here. But do delete all testsuite/*.log,
+ testsuite/*.sum files here. Delete mkheaders. Delete
+ po/*.gmo and the testsuite directory in a split tree build.
+
+2002-06-10 Jeffrey Law <law@redhat.com>
+
+ * alias.c (static_reg_base_value): New to hold RTL for
+ items allocated once per function for the aliasing code.
+ (init_alias_once_per_function): Initialize static_reg_base_value.
+ (init_alias_analysis): Avoid throw-away allocations of RTL by
+ using pre-computed values in static_reg_base_value.
+ * function.c (prepare_function_start): Call
+ init_alias_once_per_function appropriately.
+ * rtl.h (init_alias_once_per_function): Declare.
+ * caller-save (init_caller_save): Restructure slightly to
+ avoid lots of silly RTL generation.
+ * expr.c (init_expr_once): Likewise.
+ * reload1.c (reload_cse_regs_1): Allocate throw-away register
+ RTL object here. Pass it into children.
+ (reload_cse_simplify_operands): Use passed-in register RTL
+ object.
+ (reload_cse_simplify): Pass through throw-away register
+ RTL object.
+
+2002-06-10 Daniel Berlin <dberlin@dberlin.org>
+
+ * Makefile.in (ssa.o): Add dependency on $(RTL_H), which was missing.
+
+2002-06-10 Richard Sandiford <rsandifo@redhat.com>
+
+ * gcc.c (process_command): Avoid assignment to read-only location.
+ Fix sizeof calculation.
+
+2002-06-10 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpphash.h (struct cpp_macro): Put comments on their own lines.
+ (_cpp_expansions_different_trad): New.
+ * cppmacro.c (warn_of_redefinition): Fix for traditional case.
+ * cpptrad.c (canonicalize_text): New.
+ (scan_out_logical_line): Handle no arguments correctly.
+ (save_replacement_text): Commit memory when finished.
+ (_cpp_expansions_different_trad): New.
+
+2002-06-10 Tim Josling <tej@melbpc.org.au>
+
+ * gengtype.c (unnamed enum containing BASE_FILE_*): Add languages
+ TREELANG and COBOL.
+ (lang_names): Add treelang and cobol.
+ (get_file_basename): Add code to support treelang and cobol as
+ 4th and 5th users of c-common.c.
+
+2002-06-09 Geoffrey Keating <geoffk@redhat.com>
+
+ * Makefile.in (install-driver): Install driver as
+ $(target_alias)-gcc-$(version).
+ * gcc.c (spec_version): Make const.
+ (process_command): Handle -V and -b by using exec.
+ * doc/invoke.texi (Target Options): Restore -V option,
+ update docs for -b option.
+
+2002-06-10 Tim Josling <tej@melbpc.org.au>
+
+ * configure.in (remaining_languages_check):
+ Added check that all languages specified were found.
+ Exit if not found. Previous behavior was silent failure.
+ * configure: Regenerated.
+
+2002-06-10 Tim Josling <tej@melbpc.org.au>
+
+ First steps to making treelang documentation compliant, based on
+ instructions in sourcebuild.texi. Also add to gcc.c list of
+ default languages.
+
+ * doc/contrib.texi: Add self as contributor of treelang.
+
+ * doc/frontends.texi: Add mention of treelang.
+
+ * doc/invoke.texi (Overall Options): Add mention of treelang.
+
+ * doc/standards.texi: Add mention of treelang.
+
+2002-06-09 Hans-Peter Nilsson <hp@axis.com>
+
+ * config/cris/cris.c: Include ggc.h
+
+2002-06-09 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpphash.h (_cpp_push_text_context): Update.
+ (_cpp_arguments_ok): New.
+ * cppmacro.c (_cpp_arguments_ok): New, split out from...
+ (collect_args): ...here.
+ (_cpp_push_text_context): Change inputs.
+ * cpptrad.c (struct fun_macro, maybe_start_funlike, save_argument,
+ replace_args_and_push): New.
+ (lex_identifier, _cpp_lex_identifier_trad, scan_parameters):
+ Don't use IS macros directly.
+ (scan_out_logical_line): Handle function-like macro argument
+ collection.
+ (push_replacement_text): Update.
+ (replacement_length): Remove.
+ (_cpp_create_trad_definition): Don't skip whitespace before
+ checking for '('.
+
+2002-06-09 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (avr_mcu_types): Update for new devices.
+ * config/avr/avr.h (TARGET_SWITCHES, AVR_MEGA): Add -mshort-calls.
+ (LINK_SPEC, CRT_BINUTILS_SPECS): Update for new devices.
+ * config/avr/avr.md ("type" and "length" attributes): New type
+ "xcall", length 1 or 2 if AVR_MEGA. Use in all patterns that
+ output a single "call" or "rcall" insn depending on device size.
+ * config/avr/t-avr (MULTILIB_MATCHES): Update for new devices.
+
+2002-06-09 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/{aix43.h,aix5.1} (ASM_CPU_SPEC): Add power3
+ synonym for 630. Add power4. Remove embedded processors. Use -m604
+ assembler option.
+ (CPP_CPU_SPEC): Add power3 and power4.
+ (PROCESSOR_DEFAULT): Change to 604e.
+ * config/rs6000/rs6000.h (ASM_CPU_SPEC): Similar additions.
+ (CPP_CPU_SPEC): Similar additions.
+ (enum process_type): Add POWER4.
+ (RTX_COSTS): Add POWER4.
+ (CPP_CPU_SPEC): Similar additions.
+ * config/rs6000/linux64.h (PROCESSOR_DEFAULT): Define.
+ (PROCESSOR_DEFAULT64): Define.
+ * config/rs6000/rs6000.c (rs6000_override_options): Add power4.
+ (rs6000_adjust_cost): Add 603, 604, 604e, 620, 630, Power4 to
+ branch adjustment.
+ (rs6000_issue_rate): Add Power4.
+ * config/rs6000/rs6000.md (cpu attr): Add power4.
+ (iu compare): Remove 604, 604e, 620, 630.
+ Add basic Power4 scheduling information.
+ (mfcr/mtcrf): Change type attribute to cr_logical.
+
+2002-06-08 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * gengtype.h (error_at_line): Use PARAMS, not VPARAMS. Add
+ ATTRIBUTE_PRINTF_2.
+ * gengtype-lex.l: Fix format specifier warning.
+
+ * genautomata.c: Don't include ctype.h or limits.h. Use ISSPACE,
+ not isspace.
+ * gengtype-lex.l: Don't include ctype.h and use ISSPACE/ISIDNUM in
+ lieu of isspace/IDchar.
+ * gengtype.c: Likewise for ctype.h and ISALNUM vs isalnum.
+ * read-rtl.c: Likewise for ctype.h. Don't define ISDIGIT or
+ ISSPACE.
+
+2002-06-08 Zack Weinberg <zack@codesourcery.com>
+
+ * Makefile.in (LIBCPP_OBJS): Take out version.o.
+ * cpphash.h (cpp_reader): Take out print_version member.
+ * cppinit.c: (cpp_handle_option): Don't do anything with
+ -version. Just set help_only for --version, --target-help.
+ Just set verbose option for -v.
+ (cpp_post_options): Don't print a version string.
+
+2002-06-08 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (TARGET_SECTION_TYPE_FLAGS): New.
+ (avr_section_type_flags): New, handle .noinit* sections.
+
+2002-06-08 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/sh/netbsd-elf.h (SUBTARGET_EXTRA_SPECS): Define
+ and include netbsd_entry_point.
+ (SUBTARGET_LINK_SPEC): Define as NETBSD_LINK_SPEC_ELF.
+ (NETBSD_ENTRY_POINT): Define.
+
+2002-06-08 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/sh/sh.h (SUBTARGET_EXTRA_SPECS): Define empty
+ if not already defined.
+ (EXTRA_SPECS): Add SUBTARGET_EXTRA_SPECS.
+
+2002-06-08 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (avr_regs_to_save): No need to save any registers
+ in a noreturn function.
+ (avr_output_function_prologue, avr_output_function_epilogue):
+ Correct function size calculation. Do not crash on empty function.
+ (avr_output_function_epilogue): No need for epilogue after a BARRIER.
+
+2002-06-08 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/mips/netbsd.h (SUBTARGET_EXTRA_SPECS): Add
+ netbsd_link_spec and netbsd_entry_point.
+ (LINK_SPEC): Use %(netbsd_link_spec).
+ (NETBSD_ENTRY_POINT): Define.
+
+2002-06-08 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/sparc/netbsd-elf.h (LINK_ARCH32_SPEC): Only specify
+ linker emulation.
+ (LINK_ARCH64_SPEC): Likewise.
+ (LINK_SPEC, NETBSD_ENTRY_POINT): Define.
+ (SUBTARGET_EXTRA_SPECS): Add netbsd_link_spec and netbsd_entry_point.
+
+2002-06-08 Marc Espie <espie@openbsd.org>
+
+ * lists.c (free_list): Fix typo in comment.
+
+2002-06-08 Andreas Jaeger <aj@suse.de>
+
+ * lcm.c (optimize_mode_switching): Add unused attribute for
+ variable.
+
+ * sched-deps.c (sched_analyze): Remove unused variable.
+
+2002-06-08 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * diagnostic.def: Don't capitalize diagnostict descriptors.
+
+2002-06-08 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/m68k/netbsd-elf.h (EXTRA_SPECS): Add netbsd_entry_point.
+ (LINK_SPEC): Define as NETBSD_LINK_SPEC_ELF.
+ (NETBSD_ENTRY_POINT): Define.
+
+2002-06-08 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/i386/netbsd-elf.h (LINK_SPEC): Define as
+ NETBSD_LINK_SPEC_ELF.
+ (SUBTARGET_EXTRA_SPECS): Add netbsd_entry_point.
+ (NETBSD_ENTRY_POINT): Define.
+ * config/i386/netbsd64.h (LINK_SPEC): Use %(netbsd_link_spec).
+ (SUBTARGET_EXTRA_SPECS): Add netbsd_link_spec and
+ netbsd_entry_point.
+ (NETBSD_ENTRY_POINT): Define.
+
+2002-06-08 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/alpha/netbsd.h (SUBTARGET_EXTRA_SPECS): Add
+ netbsd_link_spec and netbsd_entry_point.
+ (LINK_SPEC): Use %(netbsd_link_spec).
+ (NETBSD_ENTRY_POINT): Define.
+
+2002-06-08 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/netbsd-elf.h (LINK_SPEC): Rename to...
+ (NETBSD_LINK_SPEC_ELF): ...this. Use %(netbsd_entry_point)
+ to specify program entry point.
+
+2002-06-07 Jeff Law <law@redhat.com
+
+ * emit-rtl.c (init_emit): Add hard registers to regno_reg_rtx.
+ * combine.c (move_deaths): Use regno_reg_rtx for hard regs rather
+ than creating a new register.
+ (distribute_notes): Likewise.
+ * df.c (df_reg_use_gen): Likewise.
+ (df_reg_clobber_gen): Likewise.
+ (df_ref_record): Likewise.
+ * expr.c (use_regs): Likewise.
+ * flow.c (propagate_one_insn): Likewise.
+ (mark_set_1): Likewise.
+ (mark_used_reg): Likewise.
+ * reload.c (emit_reload_insns): Likewise.
+
+2002-06-07 Roger Sayle <roger@eyesopen.com>
+
+ * simplify-rtx.c (simplify_gen_relational): Simplify RTL of the form
+ (ne (comp x y) 0) into (comp x y) where comp is a comparison code.
+ Simplify (eq (comp x y) 0) into (revcomp x y) if the sense of the
+ comparison code comp can be reversed.
+
+2002-06-07 Roger Sayle <roger@eyesopen.com>
+
+ * fold-const.c (fold) [EQ_EXPR]: Place both integer and real
+ constants last in comparisons. Optimize (x+1.0)>0.0 into the
+ equivalent x > -1.0 when -ffast-math.
+
+2002-06-07 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config.gcc (mips*-*-netbsd*): Add mips/t-netbsd to ${tmake_file}.
+ * config/mips/t-netbsd: New file.
+
+2002-06-07 Zack Weinberg <zack@codesourcery.com>
+
+ * cppinit.c (COMMAND_LINE_OPTIONS): Give all relevant -W
+ options their own entries.
+ (parse_option): Clarify comment.
+ (cpp_handle_option): Remove 'ignore' parameter and OPT_W
+ special case. Replace if/strcmp chain for -W options with
+ use of new OPT_* entries for them.
+ (cpp_handle_options): Update to match.
+ * cpplib.h: Remove last parameter to cpp_handle_option from prototype.
+ * c-decl.c: Update call to cpp_handle_option.
+
+2002-06-07 Akim Demaille <akim@epita.fr>
+
+ * gengtype-yacc.y (optionseqopt): Add the ending `;' to the action.
+ Whitespace changes.
+
+2002-06-07 Jeffrey Law <law@redhat.com>
+
+ * sched-deps.c (free_deps): Avoid calling free_INSN_LIST_list
+ on empty lists.
+
+2002-06-07 H.J. Lu (hjl@gnu.org)
+
+ * configure.in: Add --enable-__cxa_atexit.
+ * configure: Regenerated.
+ * config.in: Likewise.
+
+ * defaults.h (DEFAULT_USE_CXA_ATEXIT): New. Defined to be 0 if
+ not defined.
+
+2002-06-07 Gabriel Dos Reis <gdr@merlin.nerim.net>
+
+ * diagnostic.c (diagnostic_build_prefix): Fix initialization.
+
+2002-06-07 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/mips/netbsd.h (CACHE_FLUSH_FUNC): Define.
+
+2002-06-07 Jason Merrill <jason@redhat.com>
+
+ * cppexp.c (num_equality_op): Use a temporary variable to work
+ around gcc 3.0.4 bug.
+
+2002-06-07 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * diagnostic.c (diagnostic_build_prefix): Tidy.
+
+2002-06-07 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpptrad.c (struct block, BLOCK_HEADER_LEN, BLOCK_LEN,
+ scan_parameters, save_replacement_text, replacement_length): New.
+ (scan_out_logical_line): Take a macro and save parameters if
+ non-NULL.
+ (_cpp_logical_line_trad): Update.
+ (_cpp_create_trad_definition): Update to handle function-like
+ macros.
+ * cpplex.c (new_buff): Update.
+ (struct dummy, DEFAULT_ALIGNMENT, CPP_ALIGN): Move...
+ * cpphash.h: ...here.
+ (CPP_ALIGN2, _cpp_save_parameter): New.
+ * cppmacro.c (save_parameter): Rename, export.
+ (parse_params): Update.
+
+2002-06-07 Andreas Jaeger <aj@suse.de>
+
+ * config/mmix/mmix.c: Remove extra broken prototype for
+ mmix_init_machine_status.
+
+2002-06-06 Geoffrey Keating <geoffk@redhat.com>
+
+ * gengtype.c: Add comments before all the routines.
+
+2002-06-07 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config.gcc (sh5*-*-netbsd*): Remove sh/t-netbsd-sh5-32
+ from and add t-sh64 to ${tmake_file}.
+ (sh64*-*-netbsd*): Add t-sh64 to ${tmake_file}.
+ * config/sh/t-netbsd-sh5 (LIB1ASMFUNCS): Remove.
+ * config/sh/t-netbsd-sh5-32: Remove.
+ * config/sh/t-netbsd-sh5-64 (MULTILIB_OPTIONS): Use
+ MULTILIB_ENDIAN.
+ (MULTILIB_DIRNAMES): Define.
+
+Thu Jun 6 23:14:46 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (and promoting splitters): Disable QI to SImode promoting
+ when doing so changes immediate to be 32bit.
+
+ * rtl.h (emit_*_scope): Declare.
+ * emit-rtl.c (emit_*_scope): New global functions.
+ (try_split): Copy scope.
+ * ifcvt.c (noce_try_store_flag, noce_try_store_flag_constants,
+ noce_try_flag_inc, noce_try_store_flag_mask, noce_try_cmove,
+ noce_try_cmove_arith, noce_try_minmax, noce_try_abs,
+ noce_process_if_block, find_cond_trap): Copy scopes.
+ * recog.c (peephole2_optimize): likewise.
+
+2002-06-06 Jeffrey Law <law@redhat.com>
+
+ * h8300.h (OK_FOR_U): Fix thinko exposed by flag checking.
+
+Thu Jun 6 21:06:25 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * gengtype-lex.l (INITIAL): New rule for "'"("\\".|[^\\])"'".
+
+2002-06-06 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * Makefile.in (TEXI_GCCINSTALL_FILES): Define.
+ ($(docdir)/gccinstall.info): New target.
+ (info): Depend on it.
+ (gccinstall.dvi): New target.
+ (dvi): Depend on it.
+ * doc/.cvsignore: Ignore new info files.
+ * doc/install.texi (@setfilename): Reflect new info filename.
+
+Thu Jun 6 15:57:23 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.c (machine_dependent_reorg): Don't set RTX_UNCHANGING_P
+ on an UNSPEC.
+
+Thu Jun 6 07:17:43 2002 Nicola Pero <n.pero@mi.flashnet.it>
+
+ PR objc/6834
+ * objc/objc-lang.c (LANG_HOOKS_GET_ALIAS_SET): Define to be
+ c_common_get_alias_set.
+ (LANG_HOOKS_SAFE_FROM_P): Define to be c_safe_from_p.
+
+2002-06-06 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * emit-rtl.c (get_first_nonnote_insn, get_last_nonnote_insn): New
+ functions.
+ * rtl.h (get_first_nonnote_insn, get_last_nonnote_insn): Declare.
+ * avr/avr.c (avr_output_function_epilogue): Use above to determine
+ function size.
+ * pa/pa.c (pa_output_function_prologue): Likewise.
+
+2002-06-05 David S. Miller <davem@redhat.com>
+
+ * integrate.c (subst_constants): Handle 'B' RTL format.
+
+2002-06-05 Eric Christopher <echristo@redhat.com>
+
+ * varasm.c (make_decl_rtl): Fix comment for removed
+ halfpic.c.
+
+2002-06-05 Eric Christopher <echristo@redhat.com>
+
+ * Makefile.in: Remove missed halfpic bits.
+
+2002-06-05 Eric Christopher <echristo@redhat.com>
+
+ * toplev.c: Remove half-pic.
+ * config/mips/mips.c: Ditto.
+ * config/mips/mips.h: Ditto. Remove unused defines.
+ * config/mips/openbsd.h: Update comment to reflect above.
+ * config/mips/mips.md: Remove half-pic constraints.
+ * halfpic.h: Delete.
+ * halfpic.c: Ditto.
+
+2002-06-05 Jeffrey Law <law@redhat.com>
+
+ * pa.h (EXTRA_CONSTRAINT, T case): Further refine so that it
+ rejects (mem (lo_sum (reg) (unspec))), but will allow
+ (mem (lo_sum (reg) (symbol_ref)) for PA2.0.
+
+2002-06-05 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpphash.h (_cpp_create_definition): Update prototype.
+ (_cpp_push_text_context, _cpp_create_trad_definition): New.
+ ( cpp_lex_identifier_trad): New.
+ (_cpp_set_trad_context): New.
+ * cppinit.c (cpp_finish_options): Don't conditionalize builtins.
+ * cpplib.c (SEEN_EOL): Update.
+ (lex_macro_node): Update for -traditional.
+ (cpp_push_buffer, _cpp_pop_buffer): Similarly.
+ * cppmacro.c (_cpp_create_definition): Split into
+ create_iso_definition() and _cpp_create_trad_definition().
+ (warn_of_redefinition): Update prototype; handle traditional
+ macros.
+ (_cpp_push_text_context): New.
+ * cpptrad.c (skip_whitespace, push_replacement_text): New.
+ (lex_identifier): Call ht_lookup with correct start.
+ (_cpp_lex_identifier_tradm _cpp_create_trad_definition,
+ _cpp_set_trad_context): New.
+ (scan_out_logical_line): Update to handle changing contexts.
+
+Wed Jun 5 20:42:31 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * config.gcc (sh-*-elf*, sh64*-*-elf*): Unify.
+ (shl*-*-elf*): Add.
+ * config/sh/t-be (MULTILIB_ENDIAN): Set.
+ * config/sh/t-le (MULTILIB_ENDIAN): Likewise.
+ * t-sh (MULTILIB_ENDIAN): Set.
+ (MULTILIB_OPTIONS): Use it.
+ * t-sh64 (MULTILIB_OPTIONS): Likewise.
+ (MULTILIB_DIRNAMES): Likewise.
+
+2002-06-05 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * toplev.h (report_error_function): Remove.
+
+ * diagnostic.h (location_t): New datatype.
+ (text_info): Likewise.
+ (diagnostic_info): Likewise.
+ (output_prefix): New macro.
+ (diagnostic_last_function_changed): Likewise.
+ (diagnostic_set_last_function): Likewise.
+ (diagnostic_last_module_changed): Likewise.
+ (diagnostic_set_last_module): Likewise.
+ (report_diagnostic): Now macro.
+ (diagnostic_set_info): Declare.
+
+ * diagnostic.c (report_problematic_module): Rename to
+ diagnostic_repor_current_module.
+ (set_diagnostic_context): Remove.
+ (count_error): Rename to diagnostic_error_count.
+ (error_function_changed): Remove.
+ (record_last_error_function): Likewise.
+ (error_module_changed): Likewise.
+ (record_last_error_module): Likewise.
+ (context_as_prefix): Rename to diagnostic_build_prefix.
+ (flush_diagnostic_buffer): Rename to diagnostic_flush_buffer.
+ (diagnostic_set_info): New function.
+
+ * objc/objc-act.c: #include diagnostic.h
+ (error_with_ivar): Adjust call to count_error.
+ (warn_with_method): Likewise.
+ * objc/Make-lang.in (objc-act.o): Depend on diagnostic.h
+
+2002-06-05 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.c (xtensa_build_va_list): Use
+ lang_hooks.types.make_type instead of make_node; set up
+ __va_list_tag type decl.
+ (xtensa_builtin_saveregs): Remove broken use of
+ RTX_UNCHANGING_P and unnecessary use of MEM_IN_STRUCT_P
+ for saved registers; add varargs alias set.
+
+2002-06-05 Neil Booth <neil@daikokuya.demon.co.uk>
+
+config:
+ * alpha/gnu.h: Undef TARGET_OS_CPP_BUILTINS.
+ * i386/beos-elf.h: Use TARGET_OS_CPP_BUILTINS rather than
+ CPP_PREDEFINES and part of CPP_SPEC.
+ i386/freebsd-aout.h, i386/gas.h, i386/gnu.h, i386/linux-aout.h,
+ i386/linux.h, i386/moss.h, i386/xm-vsta.h: Similarly.
+
+Wed Jun 5 15:20:58 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * reg-stack.c (reg_to_stack): Do not call find_basic_blocks.
+
+2002-06-05 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/linux64.h (ASM_OUTPUT_SOURCE_LINE): Define.
+
+2002-06-04 Zack Weinberg <zack@codesourcery.com>
+
+ * gengtype-yacc.y: Make sure all rules end with a semicolon.
+
+2002-06-04 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.c (xtensa_init_machine_status): Fix
+ typo in function prototype and include "ggc.h" header.
+
+2002-06-04 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (mode_mask_operand): Simplify without ifdefs.
+ (print_operand) ['U']: Likewise.
+ (alpha_expand_unaligned_store): Correct constants for 32-bit cross.
+ (alpha_expand_unaligned_store_words): Likewise.
+ (alpha_expand_builtin_vector_binop): Fix typo.
+ (enum alpha_builtin, code_for_builtin): Add remaining ext, ins, msk,
+ umulh, and cix insns.
+ (one_arg_builtins): Add cix builtins.
+ (two_arg_builtins): Add ext, ins, msk, umulh builtins.
+ (alpha_expand_builtin): Fix typo in arity.
+ * config/alpha/alpha.md (UNSPEC_CTLZ, UNSPEC_CTPOP): New.
+ (builtin_extbl, builtin_extwl, builtin_extll, builtin_extwh,
+ builtin_extlh, builtin_insbl, builtin_inswl, builtin_insll,
+ builtin_insql, builtin_inswh, builtin_inslh, builtin_insqh,
+ builtin_mskbl, builtin_mskwl, builtin_mskll, builtin_mskql,
+ builtin_mskwh, builtin_msklh, builtin_mskqh, builtin_cttz,
+ builtin_ctlz, builtin_ctpop): New.
+ * doc/extend.texi (Alpha Built-in Functions): Update.
+
+2002-06-04 Geoffrey Keating <geoffk@redhat.com>
+
+ * gengtype.c (write_gc_root): Don't unnecessarily prevent
+ global variable-length arrays being roots.
+
+ * config.gcc (powerpc-*-darwin*): Set config_gtfiles.
+ * configure.in (config_gtfiles): New variable.
+ (all_gtfiles): Initialize from config_gtfiles.
+ * configure: Regenerate.
+
+2002-06-04 Neil Booth <neil@daikokuya.demon.co.uk>
+
+config/i386:
+ * beos-elf.h, cygwin.h, djgpp.h, gas.h, gnu.h, i386-interix.h,
+ i386-interix3.h, i386elf.h, linux-aout.h, linux.h, linux64.h,
+ mingw32.h, netbsd-elf.h, netbsd.h, netbsd64.h, rtemself.h,
+ sco5.h, sol2.h, sysv3.h, sysv4.h, sysv5.h, uwin.h, vxi386.h,
+ win32.h (CPP_SPEC): Remove cpp_cpu.
+ * i386.h (TARGET_CPU_CPP_BUILTINS): Use.
+ (CPP_CPU_DEFAULT_SPEC, CPP_CPU_SPEC): Die!
+
+2002-06-04 Janis Johnson <janis187@us.ibm.com>
+
+ * config/ia64/ia64.c (gen_thread_pointer): Fix variable name.
+
+2002-06-04 Jeff Law <law@redhat.com.
+ David Edelsohn <edelsohn@gnu.org>
+ Michael Matz <matz@kde.org>
+
+ * sched-int.h (struct deps): New field libcall_block_tail_insn.
+ * sched_deps.c (init_deps): Initialize libcall_block_tail_insn.
+ * sched_deps.c (sched_analyze_insn): If libcall_block_tail_insn
+ is set, then mark the current insn as being part of a libcall
+ scheduling group.
+ (sched_analyze): Set and clear libcall_block_tail_insn appropriately.
+
+ * haifa-sched.c (schedule_block): Do not count USE or CLOBBER
+ insns against the issue rate.
+
+Tue Jun 4 19:29:42 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfglayout.c (duplicate_insn_chain): Kill NOTE_INSN_RANGE notes.
+ * final.c (final_scan_insn): Likewise.
+ * ggc-common.c (ggc_mark_rtx_children_1): Likewise; use
+ NOTE_EXPECTED_VALUE instead of NOTE_RANGE.
+ * haifa-sched.c (unlink_other_notes): Likeewise.
+ (reemit_notes): Likewise.
+ * print-rtl.c (print_rtx): Likewise.
+ * sched-deps (sched-analyze): Likewise.
+ * rtl.c (note_insn_name): Likewise.
+ * rtl.h (NOTE_RANGE_INFO, NOTE_LIVE_INFO): Kill.
+ (enum insn_note): Kill NOTE_INSN_RANGE_*, NOTE_INSN_LIVE.
+ (RANGE_*): Kill.
+
+2002-06-04 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * varasm.c (mark_constants): Handle RTX format 'B'.
+
+2002-06-04 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpphash.h (FIRST, LAST, CUR, RLIMIT): New.
+ (struct cpp_context): Add traditional fields.
+ * cppmacro.c (paste_all_tokens, push_ptoken_context,
+ push_token_context, cpp_get_token, _cpp_backup_tokens): Update.
+ * cpptrad.c (skip_comment, lex_identifier,
+ _cpp_read_logical_line_trad, scan_out_logical_line): Update.
+
+2002-06-04 Kazu Hirata <kazu@cs.umass.edu>
+
+ * gbl-ctors.h: Fix formatting.
+ * gcc.c: Likewise.
+ * gccspec.c: Likewise.
+ * gcov.c: Likewise.
+ * gcov-io.h: Likewise.
+ * gcse.c: Likewise.
+ * ggc-common.c: Likewise.
+ * ggc.h: Likewise.
+ * ggc-page.c: Likewise.
+ * ggc-simple.c: Likewise.
+ * global.c: Likewise.
+ * graph.h: Likewise.
+ * gthr-dce.h: Likewise.
+ * gthr.h: Likewise.
+ * gthr-posix.h: Likewise.
+ * gthr-rtems.h: Likewise.
+ * gthr-solaris.h: Likewise.
+ * gthr-win32.h: Likewise.
+
+2002-06-03 Geoffrey Keating <geoffk@redhat.com>
+
+ Merge from pch-branch:
+
+ * gengtype.h (UNION_OR_STRUCT_P): New macro.
+ * gengtype.c (write_gc_structure_fields): Use it.
+ (write_gc_root): Use it here too.
+
+ * gengtype.c (write_gc_structure_fields): Assume that lengths
+ of typenames fit into an 'int'; don't pass a size_t to "%d" in
+ printf.
+ (write_gc_marker_routine_for_structure): Likewise.
+ (write_gc_types): Likewise.
+ (write_gc_root): Likewise.
+
+ * varray.h (VARRAY_CLEAR): New.
+ (varray_clear): Prototype.
+ * varray.c (varray_clear): New.
+ * cselib.c (reg_values_old): New.
+ (used_regs_old): New.
+ (cselib_init): Use cached varrays if available to avoid
+ generating large amounts of garbage.
+ (cselib_finish): Don't throw away old varrays.
+
+ * final.c (insn_addresses_): Move out of ifdef.
+
+ * varray.c (uses_ggc): Make more varray kinds GCable.
+ * varray.h (union varray_data_tag): Let gengtype see
+ fields 'generic' and 'te'.
+ * reg-stack.c: Include gt-reg-stack.h, ggc.h.
+ (stack_regs_mentioned_data): Move out of ifdef; mark with gengtype.
+ (reg_to_stack): Don't call VARRAY_FREE.
+ * insn-addr.h (INSN_ADDRESSES_FREE): Don't use VARRAY_FREE.
+ (insn_addresses_): Use gengtype to mark.
+ * gengtype.c (write_gc_structure_fields): Handle arrays of generic
+ pointers; handle generic pointers in unused union fields.
+ (get_output_file_with_visibility): Include cselib.h,
+ insn-addr.h in gtype-desc.c.
+ * function.c (prologue): Use gengtype to mark.
+ (epilogue): Likewise.
+ (sibcall_epilogue): Likewise.
+ * dependence.c: Include gt-dependence.h, ggc.h.
+ (struct def_use): Use gengtype to mark.
+ (struct loop): Likewise.
+ (struct induction): Likewise.
+ (struct dependence): Likewise.
+ (def_use_chain): Likewise.
+ (dep_chain): Likewise.
+ (loop_chain): Likewise.
+ (induction_chain): Likewise.
+ (init_dependence_analysis): Don't free anything, just clear pointers.
+ (build_def_use): Use GGC to allocate def_use.
+ (add_loop): Use GGC to allocate loop.
+ (find_induction_variable): Use GGC to allocate induction.
+ (check_node_dependence): Use GGC to allocate induction, dependence.
+ (dump_node_dependence): Don't free varrays.
+ (end_dependence_analysis): Likewise.
+ * cselib.h (struct cselib_val_struct): Use gengtype to mark.
+ (struct elt_loc_list): Likewise.
+ (struct elt_list): Likewise.
+ * cselib.c: Don't include obstack.h.
+ (hash_table): Use gengtype to mark.
+ (reg_values): Use gengtype to mark.
+ (used_regs): Use gengtype to mark.
+ (cselib_obstack): Delete.
+ (cselib_startobj): Delete.
+ (empty_vals): Mark as deletable.
+ (empty_elt_lists): Mark as deletable.
+ (empty_elt_loc_lists): Mark as deletable.
+ (new_elt_list): Use GGC to allocate struct elt_list.
+ (new_elt_loc_list): Use GGC to allocate struct elt_loc_list.
+ (clear_table): Don't delete obstack; don't unnecessarily clear
+ deletable variables.
+ (new_cselib_val): Use GGC to allocate struct cselib_val.
+ (cselib_init): Don't set up obstacks. Use GGC to allocate
+ hash table.
+ (cselib_finish): Just clear variables, don't free anything.
+ * Makefile.in (cselib.o): Remove dependency on $(OBSTACK_H).
+ (reg-stack.o): Add dependency on gt-reg-stack.h, $(GGC_H).
+ (dependence.o): Add dependency on gt-dependence.h, $(GGC_H).
+ (GTFILES): Add insn-addr.h, cselib.h, dependence.c, reg-stack.c.
+ (gt-reg-stack.h): New rule.
+ (gt-dependence.h): New rule.
+ (gtype-desc.o): Add cselib.h, insn-addr.h.
+
+ * varray.c: Use only necessary headers.
+ (element_size): New.
+ (uses_ggc): New.
+ (varray_init): Take type, not size. Use GGC if appropriate.
+ (varray_grow): Update for change to struct varray_head_tag.
+ Use GGC if appropriate.
+ * varray.h (struct const_equiv_data): Use gengtype.
+ (enum varray_data_enum): New.
+ (union varray_data_tag): Use gengtype.
+ (struct varray_head_tag): Use gengtype. Replace size field with
+ enum varray_data_enum.
+ (varray_init): Update prototype.
+ (VARRAY_SCHED_INIT): Delete.
+ (VARRAY_*_INIT): Update for change to varray_init.
+ (VARRAY_SCHED): Delete.
+ (VARRAY_PUSH_SCHED): Delete.
+ (VARRAY_TOP_SCHED): Delete.
+ * tree.h: Update for change to length specifier.
+ * tree-inline.c (optimize_inline_calls): Don't use VARRAY_FREE.
+ (clone_body): Likewise.
+ * ssa.h (ssa_definition): Use gengtype to mark.
+ * ssa.c (convert_from_ssa): Don't use VARRAY_FREE.
+ * ssa-dce.c (ssa_eliminate_dead_code): Don't use VARRAY_FREE.
+ * rtl.h (struct rtvec_def): Update for change to length specifier.
+ * integrate.c (expand_inline_function): Don't use VARRAY_FREE.
+ (struct initial_value_struct): Update for change to length specifier.
+ * ggc.h (ggc_add_rtx_varray_root): Delete prototype.
+ (ggc_add_tree_varray_root): Delete prototype.
+ (ggc_mark_rtx_varray): Delete prototype.
+ (ggc_mark_tree_varray): Delete prototype.
+ * ggc-common.c (ggc_add_rtx_varray_root): Delete.
+ (ggc_add_tree_varray_root): Delete.
+ (ggc_mark_rtx_varray): Delete.
+ (ggc_mark_tree_varray): Delete.
+ (ggc_mark_rtx_varray_ptr): Delete.
+ (ggc_mark_tree_varray_ptr): Delete.
+ * gengtype.h (enum typekind): Remove TYPE_VARRAY.
+ (create_varray): Delete prototype.
+ * gengtype.c (varrays): Delete.
+ (create_varray): Delete.
+ (adjust_field_type): Detect array of string pointers.
+ (process_gc_options): Remove code to handle varray_type option.
+ (set_gc_used_type): Remove TYPE_VARRAY case.
+ (output_escaped_param): New.
+ (write_gc_structure_fields): Use output_escaped_param on all
+ parameters. Handle 'skip' with 'use_param' option. Handle
+ arrays of strings. Remove TYPE_VARRAY handling.
+ (write_gc_roots): Use boolean to detect 'length' option.
+ * gengtype-yacc.y (VARRAY_TYPE): Delete token.
+ (struct_fields): Call adjust_field_type on array fields.
+ (type): Remove VARRAY_TYPE case.
+ (type_option): Likewise.
+ * gengtype-lex.l: Don't consider varray_type a keyword.
+ * function.h: Update for change to length specifier.
+ (free_eh_status): Delete prototype.
+ * function.c (free_after_compilation): Don't call free_eh_status.
+ (reorder_blocks): Don't use VARRAY_FREE.
+ * except.c (struct eh_status): Update for change to length specifier.
+ remove varray_type specifier.
+ (free_eh_status): Delete.
+ * dwarf2out.c: Include gt-dwarf2out.h.
+ (used_rtx_varray): Use gengtype to mark, move
+ outside ifdefs.
+ (incomplete_types): Likewise.
+ (decl_scope_table): Likewise.
+ (dwarf2out_init): Don't call ggc_add_tree_varray_root.
+ * cfglayout.c (scope_to_insns_finalize): Don't use VARRAY_FREE.
+ * c-tree.h (struct lang_type): Update for change to length specifier.
+ * c-parse.in (yylexstring): Don't use VARRAY_FREE.
+ * c-objc-common.c: Include gt-c-objc-common.h.
+ (deferred_fns): Mark for gengtype.
+ (c_objc_common_init): Don't call ggc_add_tree_varray_root.
+ (expand_deferred_fns): Just set deferred_fns to 0 to free it.
+ * Makefile.in (c-objc-common.o): Add gt-c-objc-common.h.
+ (gtype-desc.o): Update dependencies.
+ (dwarf2out.o): Add gt-dwarf2out.h.
+ (varray.o): Update dependencies.
+ (GTFILES): Add varray.h, ssa.h, dwarf2out.c, c-objc-common.c.
+ (gt-c-objc-common.h): New rule.
+ (gt-dwarf2out.h): New rule.
+ * objc/objc-act.c (build_objc_string_object): Don't use VARRAY_FREE.
+
+ * doc/gty.texi (GTY Options): Correct spelling.
+ (GGC Roots): Likewise.
+ * Makefile.in (TEXI_CPP_FILES): New.
+ (TEXI_GCC_FILES): New.
+ (TEXI_GCCINT_FILES): New.
+ (TEXI_CPPINT_FILES): New.
+ ($(docdir)/cpp.info): Use new macros.
+ ($(docdir)/gcc.info): Likewise.
+ ($(docdir)/gccint.info): Likewise.
+ ($(docdir)/cppinternals.info): Likewise.
+ (cpp.dvi): Likewise.
+ (gcc.dvi): Likewise.
+ (gccint.dvi): Likewise.
+ (cppinternals.dvi): Likewise.
+
+ * Makefile.in ($(docdir)/gccint.info): Depend on gty.texi.
+ * doc/gccint.texi (Top): Include gty.texi.
+ * doc/gty.texi: New file.
+
+ * bitmap.c: Include ggc.h, gt-bitmap.h.
+ (bitmap_ggc_free): New.
+ (bitmap_elem_to_freelist): New.
+ (bitmap_element_free): Use bitmap_elem_to_freelist.
+ (bitmap_element_allocate): Allow use of GGC.
+ (bitmap_clear): Use bitmap_elem_to_freelist.
+ (bitmap_copy): Update for change to bitmap_element_allocate.
+ (bitmap_set_bit): Likewise.
+ (bitmap_operation): Update for changes elsewhere.
+ (bitmap_initialize): Allow to create bitmaps that will use GGC.
+ * bitmap.h (struct bitmap_element_def): Use gengtype.
+ (struct bitmap_head_def): Likewise. Also add 'using_obstack' field.
+ (bitmap_initialize): Add extra parameter.
+ (BITMAP_OBSTACK_ALLOC): Update for change to bitmap_initialize.
+ (BITMAP_ALLOCA): Delete.
+ (BITMAP_XMALLOC): Update for change to bitmap_initialize.
+ (BITMAP_GGC_ALLOC): New.
+ * Makefile.in (gtype-desc.o): Add bitmap.h.
+ (bitmap.o): Add gt-bitmap.h, $(GGC_H).
+ (GTFILES): Add bitmap.c.
+ (gt-bitmap.h): New rule.
+ ($(HOST_PREFIX_1)bitmap.o): Add gt-bitmap.h.
+ * basic-block.h: Update for changes to bitmap_initialize.
+ * except.c (exception_handler_label_map): Move into...
+ (struct eh_status): Here.
+ (struct eh_region): Make 'aka' GCable.
+ (free_eh_status): Don't need to specially handle
+ exception_handler_label_map.
+ (add_ehl_entry): Update for changes to exception_handler_label_map.
+ (find_exception_handler_labels): Likewise.
+ (remove_exception_handler_label): Likewise.
+ (maybe_remove_eh_handler): Likewise.
+ (for_each_eh_label): Likewise.
+ (remove_eh_handler): Allocate 'aka' using GGC.
+ * gengtype.c (get_output_file_with_visibility): Add bitmap.h
+ to list of includes.
+
+ * gengtype.c (write_gc_marker_routine_for_structure): Name
+ the routines 'gt_ggc_mx_*' instead of 'gt_ggc_m_*'.
+ (write_gc_types): Arrange for the tests with NULL to be inlined.
+ (write_gc_roots): Update uses of procedure pointers.
+ * ggc-common.c (gt_ggc_mx_rtx_def): Rename from gt_ggc_m_rtx_def.
+
+ * Makefile.in (explow.o): Add dependency on gt-explow.h.
+ (sdbout.o): Add dependency on gt-sdbout.h.
+
+ * emit-rtl.c (const_int_htab): Use gengtype to clear unused entries.
+ (mem_attrs_htab): Likewise.
+ (init_emit_once): Don't call ggc_add_deletable_htab.
+ * fold-const.c (size_htab): Use gengtype to clear unused entries.
+ (size_int_type_wide): Don't call ggc_add_deletable_htab.
+ * gengtype.c (finish_root_table): Add LASTNAME and TNAME
+ parameters, use them, change callers.
+ (write_gc_root): Add IF_MARKED parameter, use it, change callers.
+ (write_gc_roots): Handle 'if_marked' option.
+ (main): Don't need to call set_gc_used_type any more.
+ * ggc.h (ggc_htab_marked_p): Delete.
+ (ggc_htab_mark): Delete.
+ (struct ggc_cache_tab): New.
+ (gt_ggc_cache_rtab): New declaration.
+ * ggc-common.c (struct d_htab_root): Delete.
+ (d_htab_roots): Delete.
+ (ggc_add_deletable_htab): Delete.
+ (ggc_htab_delete): Handle new htab-deleting mechanism.
+ (ggc_mark_roots): Use new htab-deleting mechanism.
+ * tree.c (type_hash_table): Use gengtype to clear unused entries.
+ Make static.
+ (init_obstacks): Don't call ggc_add_deletable_htab.
+
+ * objc/objc-act.h (struct hashed_attribute): Use gengtype.
+ (struct hashed_entry): Likewise.
+ (nst_method_hash_list): Likewise.
+ (cls_method_hash_list): Likewise.
+ (HASH_ALLOC_LIST_SIZE): Delete.
+ (ATTR_ALLOC_LIST_SIZE): Delete.
+ * objc/objc-act.c (hash_init): Use ggc to allocate
+ nst_method_hash_list, cls_method_hash_list.
+ (hash_enter): Use ggc to allocate; allocate one entry at a time.
+ (hash_add_attr): Likewise.
+ (ggc_mark_hash_table): Delete.
+ (objc_act_parse_init): Delete.
+ (objc_init): Delete reference to objc_act_parse_init.
+ * tlink.c: Replace hash.h with hashtab.h. Explicitly include
+ obstack.h. Replace references to 'struct hash_table' with htab_t.
+ (struct symbol_hash_entry): Replace hash header with key field.
+ (struct file_hash_entry): Replace hash header with key field.
+ (struct demangled_hash_entry): Replace hash header with key field.
+ (hash_string_eq): New.
+ (hash_string_hash): New.
+ (symbol_hash_newfunc): Delete.
+ (symbol_hash_lookup): Modify to use htab_t.
+ (file_hash_newfunc): Delete.
+ (file_hash_lookup): Modify to use htab_t.
+ (demangled_hash_newfunc): Delete.
+ (demangled_hash_lookup): Modify to use htab_t.
+ (tlink_init): Modify to use htab_t.
+ * hash.h: Delete.
+ * hash.c: Delete.
+ * ggc.h: Delete forward structure declarations.
+ Delete prototypes for deleted functions.
+ * ggc-common.c: Don't include hash.h.
+ (ggc_add_tree_hash_table_root): Delete.
+ (ggc_mark_tree_hash_table_entry): Delete.
+ (ggc_mark_tree_hash_table): Delete.
+ (ggc_mark_tree_hash_table_ptr): Delete.
+ * gengtype.c (write_gc_structure_fields): Allow param_is option.
+ (write_gc_marker_routine_for_structure): Use visibility of
+ the parameter if there is one.
+ * function.c: Replace hash.h with hashtab.h. Replace references
+ to 'struct hash_table *' with htab_t.
+ (struct insns_for_mem_entry): Include a plain key.
+ (fixup_var_refs_insns_with_hash): Update to use htab_t.
+ (insns_for_mem_newfunc): Delete.
+ (insns_for_mem_hash): Update to use htab_t.
+ (insns_for_mem_comp): Likewise.
+ (insns_for_mem_walk): Likewise.
+ * c-lang.c: Include ggc.h.
+ * Makefile.in (OBJS): Remove hash.o.
+ (c-lang.o): Add GGC_H.
+ (COLLECT2_OBJS): Remove hash.o.
+ (tlink.o): Remove hash.h, add HASHTAB_H and OBSTACK_H.
+ (ggc-common.o): Remove hash.h.
+ (function.o): Remove hash.h, add HASHTAB_H.
+ (genautomata.o): Remove hash.h, add HASHTAB_H.
+
+ * varasm.c (mark_const_str_htab_1): Delete.
+ (mark_const_str_htab): Delete.
+ (const_str_htab_del): Delete.
+ (const_str_htab): Use gengtype to mark.
+ (init_varasm_once): Use gengtype to mark hashtables. Use GC to
+ allocate them.
+ * tree.c (mark_tree_hashtable_entry): Delete.
+ (mark_tree_hashtable): Delete.
+ * tree.h (mark_tree_hashtable): Delete prototype.
+ * ggc.h (ggc_test_and_set_mark): Treat (void *)1 like NULL.
+ (ggc_mark): Likewise.
+ (ggc_calloc): New.
+ (htab_create_ggc): New.
+ * ggc-common.c (ggc_calloc): New.
+ * gengtype.h (enum typekind): Add TYPE_PARAM_STRUCT.
+ (struct type): Add param_struct structure.
+ * gengtype.c (param_structs): New.
+ (adjust_field_type): Handle param_is option.
+ (set_gc_used_type): Handle TYPE_PARAM_STRUCT.
+ (get_output_file_with_visibility): Include hashtab.h in gtype-desc.c.
+ (write_gc_structure_fields): Add new PARAM parameter. Update
+ callers. Handle use_param option. Handle TYPE_PARAM_STRUCT.
+ (write_gc_marker_routine_for_structure): Add new PARAM parameter.
+ Use it to generate function name. Update callers.
+ (write_gc_types): Add new PARAM_STRUCTS parameter. Update callers.
+ Process them.
+ (write_gc_roots): Handle TYPE_PARAM_STRUCT. Allow param_is
+ option.
+ (main): Define PTR as pointer-to-scalar. Don't specially
+ mark deferred_string or ehl_map_entry.
+ * gengtype-yacc.y (PARAM_IS): Add new token.
+ (externstatic): Use adjust_field_type.
+ (type_option): Add PARAM_IS.
+ * gengtype-lex.l: Add rule for typedef of function pointers.
+ Add rule for PARAM_IS.
+ (IWORD): Add size_t.
+ * except.c (exception_handler_label_map): Use gengtype to mark.
+ (type_to_runtime_map): Likewise.
+ (mark_ehl_map_entry): Delete.
+ (mark_ehl_map): Delete.
+ (init_eh): Use gengtype for roots; use GC to allocate hash tables.
+ (t2r_mark_1): Delete.
+ (t2r_mark): Delete.
+ * Makefile.in (gtype-desc.o): Correct dependencies.
+ (GTFILES): Add hashtab.h.
+ (genautomata.o): Actually uses hashtab.h.
+
+ * Makefile.in (stringpool.o): Add $(GGC_H).
+ (dwarf2asm.o): Likewise.
+ (GTFILES): Add hashtable.h.
+ * c-common.h (struct c_common_identifier): Use gengtype.
+ * c-decl.h (c_mark_tree): Delete.
+ * c-lang.c (LANG_HOOKS_MARK_TREE): Delete.
+ * c-tree.h (struct lang_identifier): Use gengtype.
+ (union lang_tree_node): New.
+ (c_mark_tree): Delete prototype.
+ * dwarf2out.c [!DWARF2_DEBUGGING_INFO]: Define dummy
+ dwarf2_debug_hooks.
+ * gengtype-lex.l (IWORD): Allow 'bool'.
+ (ptr_alias): Match.
+ * gengtype-yacc.y (ALIAS): New token.
+ (type_option): New rule.
+ (option): Use type_option.
+ * gengtype.c (process_gc_options): New.
+ (set_gc_used_type): Use it.
+ (write_gc_structure_fields): Add 'bitmap' parameter, change callers.
+ Add new variable 't' to hold the type of the field being processed.
+ Add more error checking. Use UNION_P when looking at 'desc' option.
+ Handle language-specific structures containing other
+ language-specific structures.
+ (write_gc_types): Handle 'ptr_alias' option.
+ (main): Don't need to specially output lang_type, lang_decl, lang_id2.
+ * ggc-common.c (ggc_pending_trees): Delete.
+ (ggc_mark_roots): Don't manipulate ggc_pending_trees.
+ (ggc_mark_trees): Delete.
+ (gt_ggc_m_tree_node): Delete.
+ * ggc.h (ggc_pending_trees): Delete.
+ (ggc_mark_tree): Make alias of gt_ggc_m_tree_node.
+ * hashtable.h (ht_identifier): Use gengtype.
+ * langhooks-def.h (LANG_HOOKS_MARK_TREE): Delete.
+ * langhooks.h (struct lang_hooks): Delete mark_tree.
+ * sdbout.c [! SDB_DEBUGGING_INFO]: Define dummy sdb_debug_hooks
+ anyway.
+ * system.h: Poison LANG_HOOKS_MARK_TREE.
+ * tree.c (tree_node_structure): New.
+ * tree.h (struct tree_common): Use gengtype.
+ (struct tree_int_cst): Likewise.
+ (struct tree_real_cst): Likewise.
+ (struct tree_string): Likewise.
+ (struct tree_complex): Likewise.
+ (struct tree_vector): Likewise.
+ (struct tree_identifier): Likewise.
+ (struct tree_list): Likewise.
+ (struct tree_vec): Likewise.
+ (struct tree_exp): Likewise.
+ (struct tree_block): Likewise.
+ (struct tree_type): Likewise.
+ (struct tree_decl): Likewise.
+ (enum tree_structure_enum): New.
+ (union tree_node): Use gengtype, with an alias.
+ (tree_node_structure): Prototype.
+ * objc/objc-lang.c (LANG_HOOKS_MARK_TREE): Delete.
+
+ Merge to tag pch-merge-20020430. The LANG_HOOKS_FUNCTION_MARK
+ macro was deleted. The LANG_HOOKS_FUNCTION_FREE macro was renamed
+ to LANG_HOOKS_FUNCTION_FINAL.
+ * Makefile.in (GTFILES): Add bitmap.h.
+ * except.c (struct eh_region): Mark field 'aka' to be skipped.
+
+ * config/alpha/alpha.c [TARGET_ABI_UNICOSMK]
+ (alpha_init_machine_status): Give proper type.
+ * Makefile.in (c-lang.o): Depend on gtype-c.h.
+ (optabs.o): Depend on gt-optabs.h.
+ (GTFILES): Add optabs.o.
+ (gt-optabs.h): Add rule.
+ * optabs.c: Include gt-optabs.h.
+
+ * gengtype.c (set_gc_used_type): Correct some errors in last change.
+ (write_gc_structure_fields): If a field which should be NULL is
+ not, abort.
+ * c-pragma.c: Move struct align_stack and variable alignment_stack
+ out from the ifdef.
+
+ * config/xtensa/t-xtensa: Add dependencies for gt-xtensa.h.
+ * config/xtensa/xtensa.c: Include gt-cris.h.
+ (struct machine_function): Use gengtype to mark.
+ * config/mmix/mmix.h (struct machine_function): Use gengtype
+ to mark.
+ * config/cris/t-cris: Add dependencies for gt-cris.h.
+ * config/cris/cris.c: Include gt-cris.h.
+ (struct machine_function): Use gengtype to mark.
+ * config/rs6000/rs6000.h (struct machine_function): Use gengtype
+ to mark.
+ * doc/tm.texi (Per-Function Data): Delete references to
+ mark_machine_status.
+ * config/ia64/ia64.c (ia64_override_options): Don't set
+ mark_machine_status.
+ * config/i386/i386.c (override_options): Likewise.
+ * config/d30v/d30v.c (d30v_init_expanders): Likewise.
+ * config/arm/arm.c (arm_init_expanders): Likewise.
+ * config/alpha/alpha.c (override_options): Likewise.
+ * gengtype.h (enum gc_used_enum): Add GC_MAYBE_POINTED_TO.
+ * gengtype.c (set_gc_used_type): Handle 'maybe_null' option.
+ (write_gc_structure_fields): Don't handle 'really' option.
+ Handle 'maybe_null' option.
+ (write_gc_types): Handle 'maybe_null' option.
+ * function.h (struct function): Don't use "really".
+ (mark_machine_status): Delete declaration.
+ (mark_lang_status): Delete declaration.
+ (gt_ggc_mr_machine_function): Delete prototype.
+ (gt_ggc_mr_language_function): Delete prototype.
+ * function.c (mark_machine_status): Delete.
+ (mark_lang_status): Delete.
+ (gt_ggc_mr_machine_function): Delete.
+ (gt_ggc_mr_language_function): Delete.
+ * c-tree.h (mark_c_function_context): Delete prototype.
+ * c-objc-common.c (c_objc_common_init): Don't set mark_lang_status.
+ * c-decl.c (struct language_function): Rename from struct
+ c_language_function. Update uses. Use gengtype to mark.
+ (mark_c_function_context): Delete.
+ * c-common.h (struct c_language_function): Rename from struct
+ language_function.
+ (mark_stmt_tree): Delete prototype.
+ (c_mark_lang_decl): Delete prototype.
+ (mark_c_language_function): Delete prototype.
+ * c-common.c (mark_stmt_tree): Delete.
+ (c_mark_lang_decl): Delete.
+ (mark_c_language_function): Delete.
+
+ * gengtype.h (enum typekind): Add TYPE_LANG_STRUCT.
+ (lang_bitmap): New typedef. Use where appropriate.
+ (struct type): Add gc_used field, lang_struct field.
+ (UNION_P): New macro.
+ (new_structure): New prototype.
+ (find_structure): Remove 'pos' parameter. Change all callers.
+ * gengtype-lex.l: Update for changes to find_structure.
+ * gengtype-yacc.y (typedef_struct): Use new_structure.
+ (yacc_ids): Suppress warning.
+ (type): Use new_structure.
+ * gengtype.c (string_type): Update for changes to struct type.
+ (find_structure): Just find a structure, don't worry about
+ creating one.
+ (new_structure): New.
+ (note_yacc_type): Use new_structure.
+ (set_gc_used_type): New.
+ (set_gc_used): New.
+ (write_gc_structure_fields): Allow for pointers to TYPE_LANG_STRUCT.
+ (write_gc_types): Handle TYPE_LANG_STRUCT.
+ (write_gc_marker_routine_for_structure): New.
+ (main): Call set_gc_used. Add some calls to set_gc_used_type
+ for places where GCC doesn't use gengtype properly yet.
+ * ggc.h (gt_ggc_m_rtx_def): Don't prototype.
+ (gt_ggc_m_tree_node): Likewise.
+
+ * varasm.c (copy_constant): Call expand_constant if we hit
+ something we can't recognize.
+
+ * ggc-common.c (ggc_mark_rtvec_children): Delete.
+ (ggc_mark_rtx_children): Use generic name for ggc_mark_rtvec.
+ (lang_mark_false_label_stack): Delete.
+ * rtl.h (struct rtvec_def): Use gengtype to mark.
+ * ggc.h (ggc_mark_rtvec): Delete.
+ (gt_ggc_m_rtvec_def): Delete.
+ (ggc_mark_nonnull_tree): Delete.
+ (ggc_mark_rtvec_children): Delete prototype.
+ (lang_mark_false_label_stack): Delete declaration.
+
+ * gengtype.h (note_yacc_type): Add prototype.
+ * gengtype.c (note_yacc_type): New function.
+ * gengtype-lex.l: Add lexer support for yacc files.
+ * gengtype-yacc.y (start): Extract union from yacc files.
+ (yacc_union): New rule.
+ (yacc_typematch): New rule.
+ (yacc_ids): New rule.
+ (enum_items): Tweak for efficiency.
+ (optionseq): Likewise.
+
+ * c-common.h (struct language_function): Use gengtype.
+ (struct c_lang_decl): Likewise.
+ * c-tree.h (struct lang_decl): Likewise.
+ (struct lang_type): Likewise.
+ * c-decl.c (lang_mark_tree): Use generated marker routines to mark
+ tree language substructures.
+
+ * stringpool.c (mark_ident): Replace ggc_mark_nonnull_tree with
+ ggc_mark_tree.
+ * dwarf2asm.c (mark_indirect_pool_entry): Likewise.
+
+ * varasm.c (struct rtx_const): Remove 'skip' tags for scalar arrays.
+
+ * stmt.c (struct nesting): Add discriminator. Use gengtype to
+ mark. Remove 'data.block.cleanup_ptr' field.
+ (struct stmt_status): Use usual technique to mark struct nesting.
+ (gt_ggc_mr_nesting_cond): Delete.
+ (gt_ggc_mr_nesting_loop): Delete.
+ (gt_ggc_mr_nesting_block): Delete.
+ (gt_ggc_mr_nesting_case_stmt): Delete.
+ (expand_start_cond): Set discriminator.
+ (expand_start_loop): Likewise.
+ (expand_start_null_loop): Likewise.
+ (expand_start_bindings_and_block): Set discriminator. Don't set
+ deleted fields.
+ (expand_decl_cleanup): Replace 'cleanup_ptr' with
+ &thisblock->data.block.cleanups.
+ (expand_start_case): Set discriminator.
+ (expand_start_case_dummy): Set discriminator.
+
+ * ggc-callbacks.c: Remove.
+
+ * gengtype.h (struct type): Add 'u.s.bitmap' field.
+ (find_structure): Add 'pos' parameter.
+ * gengtype-lex.l: Update callers to find_structure.
+ * gengtype-yacc.y: Likewise.
+ * gengtype.c (find_structure): Allow for structures to be defined
+ in multiple language backends.
+ (get_output_file_with_visibility): Include debug.h in gtype-desc.c.
+ (counter): Rename to gc_counter.
+ (write_gc_structure_fields): Fail when writing out fields for
+ an incomplete structure. Ignore arrays of scalars. Handle
+ 'tree_vec' special.
+ (write_gc_types): Reset counter for each procedure written.
+
+ * stmt.c (add_case_node): Use GGC to allocate struct case_node.
+ (free_case_nodes): Delete.
+ (expand_end_case_type): Delete call to free_case_nodes.
+
+ * Makefile.in (cselib.o): Include gt-<filename>.h.
+ (gcse.o): Likewise.
+ (profile.o): Likewise.
+ (alias.o): Likewise.
+ (GTFILES): Add alias.c, cselib.c, gcse.c, profile.c, and
+ alphabetize backend files.
+ (gt-alias.h, gt-cselib.h, gt-gcse.h, gt-profile.h): New rules.
+ * alias.c: Use gengtype for roots.
+ * c-common.h (struct stmt_tree_s): Use gengtype.
+ * c-decl.c: Use gengtype for roots.
+ * cselib.c: Use gengtype for roots.
+ * expr.c: Use gengtype for roots.
+ * fold-const.c: Use gengtype for roots.
+ * gcse.c: Use gengtype for roots.
+ * gengtype-lex.l: Handle typedefs of function types.
+ Allow for empty array bounds.
+ Allow processing to stop on initializers.
+ * gengtype-yacc.y (externstatic): Stop processing on initializers.
+ (semiequal): New rule.
+ * gengtype.c (create_file): Tidy output files.
+ (get_output_file_with_visibility): Fix paren warning. Fix bug
+ involving multiple input files mapping to one output file.
+ (write_gc_structure_fields): Skip arrays of scalars.
+ (write_gc_types): Tidy output files.
+ (write_gc_root): New function.
+ (write_gc_roots): Fix bugs, add support for roots that are
+ structures.
+ * ggc-common.c (ggc_mark_rtx_ptr): Delete.
+ (ggc_mark_tree_ptr): Delete.
+ (ggc_add_rtx_root): Delete.
+ (ggc_add_tree_root): Delete.
+ (ggc_del_root): Delete.
+ * integrate.c (get_func_hard_reg_initial_val): Use ggc_alloc to
+ allocate struct initial_value_struct.
+ * profile.c: Use gengtype for roots.
+ * sdbout.c: Use gengtype for roots.
+ * varasm.c (mark_weak_decls): Delete unused prototype.
+ (mark_const_hash_entry): Delete unused function.
+ * config/darwin-protos.h: Use gengtype for roots.
+ (machopic_add_gc_roots): Delete.
+ * config/arm/arm.c: Use gengtype for roots.
+ * config/arm/arm.h: Use gengtype for roots.
+ * config/c4x/c4x-protos.h: Use gengtype for roots.
+ * config/c4x/c4x.c (c4x_add_gc_roots): Delete.
+ * config/d30v/d30v-protos.h: Use gengtype for roots.
+ * config/d30v/d30v.c (d30v_add_gc_roots): Delete.
+ * config/dsp16xx/dsp16xx.c (override_options): Use gengtype for roots.
+ * config/dsp16xx/dsp16xx.h: Use gengtype for roots.
+ * config/ia64/ia64-protos.h: Use gengtype for roots.
+ * config/ia64/ia64.c (ia64_add_gc_roots): Delete.
+ * config/m68hc11/m68hc11-protos.h: Use gengtype for roots.
+ * config/m68hc11/m68hc11.c (z_reg): Make global.
+ (z_reg_qi): Make global.
+ (m68hc11_add_gc_roots): Delete.
+ * config/mcore/mcore-protos.h: Use gengtype for roots.
+ * config/mcore/mcore.c (mcore_add_gc_roots): Delete.
+ * config/mips/mips.c (mips_add_gc_roots): Delete.
+ * config/mips/mips.h: Use gengtype for roots.
+ * config/mmix/mmix.c (override_options): Use gengtype for roots.
+ * config/mmix/mmix.h: Use gengtype for roots.
+ * config/mn10200/mn10200.c (asm_file_start): Use gengtype for roots.
+ * config/mn10200/mn10200.h: Use gengtype for roots.
+ * config/pa/pa.c: Use gengtype for roots, marking.
+ (struct deferred_plabel): Use GGC, gengtype.
+ (pa_add_gc_roots): Delete.
+ (mark_deferred_plabels): Delete.
+ * config/pj/pj-protos.h: Use gengtype for roots.
+ * config/pj/pj.h (OVERRIDE_OPTIONS): Don't define.
+ * config/rs6000/rs6000.c: Use gengtype for roots. Don't call
+ machopic_add_gc_roots.
+ * config/rs6000/rs6000.h: Use gengtype for roots.
+ * config/rs6000/t-darwin (darwin.o): Add dependency on gt-darwin.h.
+ (gt-darwin.h): Add rule.
+ * config/sh/sh.c: Use gengtype for roots.
+ * config/sh/t-sh ($(out_object_file)): Add dependency on gt-sh.h.
+ (gt-sh.h): Add rule.
+ * config/sparc/sparc.c: Use gengtype for roots.
+ (sparc_add_gc_roots): Delete.
+ (struct ultrasparc_pipeline_state): Use GGC, gengtype.
+ (mark_ultrasparc_pipeline_state): Delete.
+ * config/sparc/sparc.h: Use gengtype for roots.
+
+ * Makefile.in (c-parse.o): Update dependencies.
+ (c-common.o): Likewise.
+ (GTFILES): Add c-common.h, c-tree.h, c-common.c, c-parse.in.
+ Add dependencies for the files they generate.
+ * c-common.c: Replace ggc_add_* uses with GTY annotations.
+ * c-common.h: Likewise.
+ * c-decl.c: Likewise.
+ (gt_ggc_mp_binding_level): Delete.
+ * c-lang.c: Include gtype-c.h.
+ * c-parse.in: Replace ggc_add_* uses with GTY annotations. Include
+ gt-c-parse.h.
+ * c-pragma.h: Replace ggc_add_* uses with GTY annotations.
+ (gt_ggc_mp_align_stack): Delete.
+ * c-tree.h: Replace ggc_add_* uses with GTY annotations.
+ * function.c: Replace ggc_add_* uses with GTY annotations.
+ (gt_ggc_mp_function): Delete.
+ * function.h: Replace ggc_add_* uses with GTY annotations.
+ * gengtype.c (lang_names): New.
+ (NUM_BASE_FILES): New.
+ (open_base_files): Create language base files.
+ (startswith): New.
+ (get_file_basename): New.
+ (get_base_file_bitmap): New.
+ (get_output_file_with_visibility): Rename from get_output_file.
+ Add more mappings for various C/Objc filenames.
+ (finish_root_table): New.
+ (write_gc_roots): Handle dependencies and scoping properly.
+ * gengtype.h: Add prototypes for new functions.
+ * ggc-common.c (struct deletable_root): Delete.
+ (deletables): Delete.
+ (ggc_add_deletable_root): Delete.
+ (ggc_mark_roots): No need to deal with deleted functionality.
+ * ggc.h (ggc_add_deletable_root): Delete prototype.
+ * objc/Make-lang.in (objc-act.o): Add gtype-objc.h dependency.
+ (gtype-objc.h): Add rule to create.
+ * objc/config-lang.in (gtfiles): New.
+ * objc/objc-act.c: Allocate imp_list using GGC. Replace uses of
+ ggc_add_* with GTY markers. Include gtype-objc.h.
+ (ggc_mark_imp_list): Delete.
+ * objc/objc-act.h: Replace uses of ggc_add_* with GTY markers.
+ * objc/objc-lang.c: Random Whitespace Change.
+
+ * except.h (exception_handler_labels): Delete.
+ (get_exception_handler_labels): New.
+ * except.c (exception_handler_labels): Delete.
+ (struct eh_status): Add exception_handler_labels field.
+ (doing_eh): Don't add exception_handler_labels as root.
+ (free_eh_status): Don't need to free exception_handler_labels.
+ (get_exception_handler_labels): New.
+ (find_exception_handler_labels): Update for move of
+ exception_handler_labels.
+ (remove_exception_handler_label): Likewise.
+ * cfgrtl.c (can_delete_label_p): Use get_exception_handler_labels.
+ * jump.c (rebuild_jump_labels): Likewise.
+ * loop.c (find_and_verify_loops): Likewise.
+ * sched-rgn.c (is_cfg_nonregular): Likewise.
+
+ * gengtype.c (write_gc_structure_fields): Handle variable-length
+ TYPE_ARRAYs.
+
+ * varasm.c (struct weak_syms): Use GGC, gengtype.
+ (mark_weak_decls): Delete.
+ (weak_decls): Likewise.
+ (add_weak): Likewise.
+ (remove_from_pending_weak_list): Likewise.
+ (init_varasm_once): Likewise.
+
+ * Makefile.in (gtype-desc.o): Add libfuncs.h dependency.
+ (GTFILES): Add tree.h, libfuncs.h, emit-rtl.c, explow.c,
+ stor-layout.c, regclass.c, and lists.c.
+ Add dependencies of gt-emit-rtl.h gt-explow.h gt-stor-layout.h
+ gt-regclass.h and gt-lists.h on s-gtype.
+ * emit-rtl.c: Use gengtype for roots. Include gt-emit-rtl.h.
+ * except.c: Use gengtype for roots.
+ * explow.c: Use gengtype for roots. Include gt-explow.h.
+ * expr.h (init_stor_layout_once): Delete prototype.
+ * function.c: Use gengtype for roots.
+ * gengtype-lex.l: Add ENT_EXTERNSTATIC lexing.
+ * gengtype-yacc.y (start): Can also be an externstatic.
+ (externstatic): New production.
+ (struct_fields): Correct array bounds inversion for 2-d arrays.
+ * gengtype.c (variables): New variable.
+ (note_variable): New function.
+ (get_output_file): Include libfuncs.h into gtype-desc.c.
+ (get_output_file_name): New function.
+ (write_gc_structure_fields): Suppress warnings.
+ (write_gc_types): Make static.
+ (put_mangled_filename): New function.
+ (write_gc_roots): New function.
+ (main): Call write_gc_roots.
+ * gengtype.h (note_variable): Prototype.
+ (get_output_file_name): Prototype.
+ (write_gc_types): Delete prototype.
+ * ggc.h: Clean up unnecessary structure predefinitions.
+ (struct ggc_root_tab): Define.
+ (gt_ggc_m_rtx_def): Make function, not macro.
+ (gt_ggc_m_tree_node): Likewise.
+ * libfuncs.h: Use gengtype for roots.
+ * lists.c: Use gengtype for roots. Include gt-lists.h.
+ (init_EXPR_INSN_LIST_cache): Delete.
+ * optabs.c: Use gengtype for roots.
+ (gt_ggc_mp_optab): Delete.
+ * optabs.h: Use gengtype for roots.
+ * regclass.c: Use gengtype for roots. Include gt-regclass.h.
+ * rtl.h: Use gengtype for roots.
+ (init_EXPR_INSN_LIST_cache): Delete prototype.
+ * stor-layout.c: Use gengtype for roots.
+ Include gt-stor-layout.h.
+ (init_stor_layout_once): Delete.
+ * toplev.c: Use gengtype for roots. Delete calls to deleted
+ routines.
+ * tree.c: Use gengtype for roots.
+ * tree.h: Use gengtype for roots.
+ * varasm.c: Use gengtype for roots.
+
+ * Makefile.in (GTFILES): Add @all_gtfiles@.
+ * configure: Regenerate.
+ * configure.in: Construct all_gtfiles from the gtfiles definitions
+ in config-lang.in.
+ * gengtype-yacc.y (type): Warn about duplicate structure names.
+ * gengtype.c (get_output_file): Handle .c files in language
+ subdirectories.
+
+ * Makefile.in (GTFILES): Run gengtype on all the config files
+ and on the target .c file.
+ * except.c (mark_eh_region): Delete.
+ (init_eh_for_function): Use GGC on struct eh_status.
+ (mark_eh_status): Delete.
+ (free_eh_status): Use GGC.
+ (expand_eh_region_start): Use GGC to
+ (collect_eh_region_array): Allocate last_region_number using GGC.
+ (duplicate_eh_region_1): Use GGC to allocate struct eh_region.
+ (remove_eh_handler): Let GGC free struct eh_region.
+ (add_call_site): Use GGC to reallocate call_site_record array.
+ * function.c (init_machine_status): Update calling sequence.
+ (mark_machine_status): Likewise.
+ (mark_lang_status): Likewise.
+ (prepare_function_start): Update init_machine_status call.
+ (mark_function_status): Delete.
+ (maybe_mark_struct_function): Delete.
+ (ggc_mark_struct_function): Delete.
+ (gt_ggc_mp_function): New.
+ (gt_ggc_mr_machine_function): New.
+ (gt_ggc_mr_language_function): New.
+ (init_function_once): Use canonical names.
+ * function.h (struct function): Use gengtype.
+ (init_machine_status): Return the structure.
+ (mark_machine_status): Take a 'void *'.
+ (mark_lang_status): Likewise.
+ * ggc-common.c (ggc_mark_trees): Use canonical name for
+ ggc_mark_struct_function.
+ * tree.h (ggc_mark_struct_function): Delete prototype.
+ * config/alpha/alpha.c (alpha_mark_machine_status): Delete.
+ (alpha_init_machine_status): Likewise.
+ (override_options): Use canonical name for alpha_mark_machine_status.
+ * config/alpha/unicosmk.h (struct machine_function): Use gengtype.
+ * config/arm/arm.h (struct machine_function): Use gengtype.
+ * config/arm/arm.c (arm_mark_machine_status): Delete.
+ (arm_init_machine_status): Update calling sequence.
+ (arm_init_expanders): Use canonical name for arm_mark_machine_status.
+ * config/cris/cris.c (cris_init_machine_status): Update
+ calling sequence.
+ * config/d30v/d30v.h (struct machine_function): Use gengtype.
+ * config/d30v/d30v.c (d30v_init_machine_status): Update
+ calling sequence.
+ (d30v_mark_machine_status): Delete.
+ * config/i386/i386.c: Include gt-i386.h.
+ (struct machine_function): Use gengtype.
+ (ix86_init_machine_status): Update calling sequence.
+ (ix86_mark_machine_status): Delete.
+ (override_options): Use canonical namke for ix86_mark_machine_status.
+ * config/ia64/ia64.h (struct machine_function): Use gengtype.
+ * config/ia64/ia64.c (ia64_init_machine_status): Update calling
+ sequence.
+ (ia64_mark_machine_status): Delete.
+ (ia64_override_options): Use canonical name for
+ ia64_mark_machine_status.
+ * config/mmix/mmix.c (mmix_init_machine_status): Update calling
+ sequence.
+ * config/rs6000/rs6000.c (rs6000_init_machine_status): Likewise.
+ * config/xtensa/xtensa.c (xtensa_init_machine_status): Likewise.
+ * gengtype.c (get_output_file): Fix warning.
+ (main): Add prototype to suppress warning.
+ * tree.c: Remove tree_hash_mark prototype.
+
+ * tree.h (init_stmt): Delete prototype.
+ * toplev.c (lang_independent_init): Don't call init_stmt.
+ * stmt.c (ALLOC_NESTING): Use GGC for 'struct nesting'.
+ (stmt_obstack): Delete.
+ (POPSTACK): No need to free 'struct nesting'.
+ (gt_ggc_mr_nesting_cond): Use canonical names.
+ (gt_ggc_mr_nesting_loop): Use canonical names.
+ (gt_ggc_mr_nesting_block): Use canonical names.
+ (gt_ggc_mr_nesting_case_stmt): Use canonical names.
+ (mark_stmt_status): Delete.
+ (init_stmt): Delete.
+ (clear_last_expr): Clear both last_expr_type and last_expr_value.
+ Use it everywhere that last_expr_type was cleared.
+ * lists.c (init_EXPR_INSN_LIST_cache): Use ggc_add_deletable_root.
+ (zap_lists): Delete.
+ * ggc.h (ggc_add_deletable_root): Prototype.
+ (mark_stmt_status): Remove prototype.
+ * ggc-common.c (ggc_add_deletable_root): New.
+ (ggc_mark_roots): Handle deletable roots.
+ * function.c (ggc_mark_struct_function): Use canonical name
+ for mark_stmt_status.
+ * emit-rtl.c (free_sequence_stack): New.
+ (start_sequence): Use a freelist for sequences.
+ (end_sequence): Likewise.
+ (init_emit_once): Add free_sequence_stack as a deleteable root.
+ * c-pragma.c Include gt-c-pragma.h.
+ (struct align_stack): Use gengtype.
+ (push_alignment): Use GGC for struct align_stack.
+ (mark_align_stack): Delete.
+ (gt_ggc_mp_align_stack): New.
+ (init_pragma): Use canonical name for mark_align_stack.
+ * c-decl.c: Include gt-c-decl.h.
+ (struct binding_level): Use gengtype.
+ (make_binding_level): Use GGC; handle the freelist here.
+ (pop_binding_level): New.
+ (pushlevel): Move code into make_binding_level.
+ (push_label_level): Likewise.
+ (poplevel): Move code into pop_binding_level.
+ (pop_label_level): Likewise.
+ (mark_binding_level): Delete.
+ (gt_ggc_mp_binding_level): New.
+ (c_init_decl_processing): Use canonical name for mark_binding_level.
+ Add free_binding_level as deletable root.
+ (mark_c_function_context): Use canonical name for mark_binding_level.
+ * Makefile.in (c-decl.o): Add gt-c-decl.h.
+ (c-pragma.o): Add gt-c-pragma.h.
+ (GTFILES): Add c-decl.c and c-pragma.c.
+ (gt-c-decl.h, gt-c-pragma.h): Create using gengtype.
+
+ * tree.c (struct type_hash): Use gengtype.
+ (init_obstacks): Use canonical name for type_hash_mark.
+ (type_hash_mark): Delete.
+ Include gt-tree.h.
+ * rtl.h (struct mem_attrs): Use gengtype.
+ * optabs.h (struct optab): Use gengtype.
+ * optabs.c (expand_binop): Squish signed/unsigned warning.
+ (mark_optab): Make local, use canonical name, use autogenerated
+ marker procedure.
+ (init_optabs): Use canonical name for mark_optab.
+ (new_optab): Use GGC to allocate optabs.
+ * ggc.h: Delete mark_optab prototype.
+ * ggc-common.c (ggc_mark_rtx_children): Use canonical name for
+ mem_attrs marker procedure.
+ * gengtype.c (get_output_file): Include headers in gtype-desc.c
+ explicitly rather than deducing them from file names.
+ (write_gc_structure_fields): Handle arrays of structures.
+ (main): Return nonzero exit code if errors occur during output.
+ * emit-rtl.c (mem_attrs_mark): Delete.
+ (init_emit_once): Use canonical name for mem_attrs marker procedure.
+ * Makefile.in (gtype-desc.o): Explicitly name dependencies.
+ (tree.o): Depend on gt-tree.h.
+ (GTFILES): Add rtl.h, optabs.h, tree.c.
+ (gt-tree.h): Add it to s-gtype rule.
+
+ * .cvsignore: Ignore gengtype flex/bison generated files.
+ * Makefile.in (GGC_H): Add gtype-desc.h.
+ (OBJS): Add gtype-desc.o.
+ (GEN): Add gengtype.
+ (STAGESTUFF): Add gengtype.
+ (varasm.o): Add gt-varasm.h.
+ (stmt.o): Add gt-stmt.h.
+ (except.o): Add gt-except.h.
+ (integrate.o): Add gt-integrate.h.
+ (GTFILES): New.
+ Add new rules for new files.
+ * configure: Regenerate.
+ * configure.in: Correct defaults.h paths.
+ * emit-rtl.c (mark_sequence_stack): Delete.
+ (mark_emit_status): Delete.
+ (start_sequence): Allocate sequence structures using GGC.
+ (end_sequence): Allocate sequence structures using GGC.
+ * except.c: Use gengtype for various structures. Include
+ gt-except.h.
+ * expr.c (mark_expr_status): Delete.
+ * function.c: Use gengtype for various structures. Include
+ gt-function.h.
+ (mark_function_status): Use standard gt_ggc names for marker functions.
+ (ggc_mark_struct_function): Likewise.
+ * function.h: Use gengtype for various structures.
+ * gengtype-lex.l: New file.
+ * gengtype-yacc.y: New file.
+ * gengtype.c: New file.
+ * gengtype.h: New file.
+ * ggc.h: Include gtype-desc.h. Alias some marker procedures to
+ the standard names. Remove some now-unnecessary prototypes.
+ * integrate.c: Use gengtype for various structures. Include
+ gt-integrate.h.
+ (mark_hard_reg_initial_vals): Delete.
+ * integrate.h (mark_hard_reg_initial_vals): Delete.
+ * stmt.c: Use gengtype for various structures. Include
+ gt-stmt.h.
+ (mark_case_node): Delete.
+ (mark_goto_fixup): Delete.
+ (mark_stmt_status): Use standard gt_ggc names for marker functions.
+ * system.h: Define GTY to empty. In flex/bison files,
+ don't poison malloc or realloc, instead just define them to
+ xmalloc and xrealloc.
+ * varasm.c: Use gengtype for various structures. Include
+ gt-varasm.h. Use standard gt_ggc names for marker functions.
+ (mark_pool_constant): Delete.
+ (mark_varasm_status): Delete.
+ (decode_rtx_const): #if 0 out non-typesafe hack.
+
+ * function.h (free_lang_status): Mark as obsolete.
+ * function.c (free_lang_status): Mark as obsolete.
+ * c-decl.c (push_c_function_context): Use GC to allocate and free
+ struct language_function.
+ (pop_c_function_context): Likewise.
+ * c-common.c (mark_c_language_function): Mark struct
+ language_function.
+
+ * doc/tm.texi (Per-Function Data): Don't document free_machine_status.
+ Document that the machine_function structures must be allocated
+ using GC. Update mark_machine_status documentation.
+ * function.h: Don't declare free_machine_status.
+ * function.c (free_machine_status): Don't define.
+ (free_after_compilation): Don't call free_machine_status.
+ (ggc_mark_struct_function): Mark f->machine. Call
+ mark_machine_status only on non-NULL pointers.
+ * system.h: Poison free_machine_status.
+ * config/xtensa/xtensa.c (xtensa_init_machine_status): Use GC on
+ struct machine_function.
+ (xtensa_free_machine_status): Delete.
+ (override_options): Don't set free_machine_status.
+ * config/rs6000/rs6000.c (rs6000_override_options): Don't set
+ free_machine_status.
+ (rs6000_init_machine_status): Use GC on struct machine_function.
+ (rs6000_free_machine_status): Delete.
+ * config/ia64/ia64.c (ia64_init_machine_status): Use GC on struct
+ machine_function.
+ (ia64_mark_machine_status): Likewise.
+ (ia64_free_machine_status): Delete.
+ (ia64_override_options): Don't set free_machine_status.
+ * config/i386/i386.c (override_options): Don't set
+ free_machine_status.
+ (ix86_init_machine_status): Use GC on struct machine_function.
+ (ix86_mark_machine_status): Likewise.
+ (ix86_free_machine_status): Delete.
+ * config/d30v/d30v.c: (d30v_init_machine_status): Use GC on struct
+ machine_function.
+ (d30v_mark_machine_status): Likewise.
+ (d30v_free_machine_status): Delete.
+ (d30v_init_expanders): Don't set free_machine_status.
+ * config/arm/arm.c (arm_mark_machine_status): Use GC on struct
+ machine_function.
+ (arm_init_machine_status): Likewise.
+ (arm_free_machine_status): Delete.
+ (arm_init_expanders): Don't set free_machine_status.
+ * config/alpha/alpha.c (override_options): Don't set
+ free_machine_status.
+ (alpha_init_machine_status): Use GC on struct machine_function.
+ (alpha_mark_machine_status): Likewise.
+ (alpha_free_machine_status): Delete.
+
+ * varasm.c (compare_constant): Fix typo.
+
+ * varasm.c: Don't include obstack.h.
+ (struct varasm_status): x_const_rtx_hash_table is a hash of rtxes.
+ (struct rtx_const): Give substructures names, improve formatting.
+ (struct constant_descriptor): Delete.
+ (struct constant_descriptor_tree): New, based on constant_descriptor.
+ (const_hash_table): Is a hash table of trees.
+ (mark_const_hash_entry): Is used for hashes of trees. Mark
+ constant_descriptor_tree structure.
+ (mark_const_str_htab_1): Mark deferred_string structure.
+ (compare_constant): Rewrite to compare trees.
+ (compare_constant_1): Delete.
+ (record_constant): Delete.
+ (record_constant_1): Delete.
+ (output_constant_def): Use struct constant_descriptor_tree.
+ Don't duplicate trees twice.
+ (struct constant_descriptor_rtx): New.
+ (struct pool_constant): Used for rtx constants.
+ (init_varasm_status): Update for change to struct varasm_status.
+ (mark_varasm_status): Likewise.
+ (free_varasm_status): Delete.
+ (compare_constant_rtx): Rewrite to handle constant_descriptor_rtx.
+ (record_constant_rtx): Likewise.
+ (mem_for_const_double): Update to use struct constant_descriptor_rtx.
+ (force_const_mem): Likewise.
+ * Makefile.in (varasm.o): Doesn't depend on obstack.h.
+ * function.c (free_after_compilation): Don't use free_varasm_status.
+ * function.h: Don't prototype free_varasm_status.
+
+ * ggc-common.c (ggc_realloc): Handle X being NULL.
+
+ * ggc-common.c (ggc_realloc): New function.
+ * ggc.h: Prototype it.
+ * emit-rtl.c (free_emit_status): Delete.
+ (init_emit): Allocate emit subarrays using GC.
+ (gen_reg_rtx): Reallocate subarrays using GC.
+ (init_emit): Use GC to allocate 'struct emit_status' and its
+ subarrays.
+ (mark_emit_status): Mark structure and its subarrays.
+ * stmt.c (free_stmt_status): Delete.
+ * expr.c (free_expr_status): Delete.
+ * function.h: Remove prototypes for deleted functions.
+ * function.c (free_after_compilation): Don't use deleted functions.
+ Don't call free() on x_parm_reg_stack_loc.
+ (free_after_parsing): Don't use free_stmt_status.
+ (assign_parms): Use GC to allocate and resize x_parm_reg_stack_loc.
+ (mark_function_status): Mark x_parm_reg_stack_loc.
+
+ * varasm.c (init_varasm_status): Use GC to allocate
+ 'struct varasm_status' and its fields x_const_rtx_hash_table
+ and x_const_rtx_sym_hash_table.
+ (mark_varasm_status): Mark them.
+ (free_varasm_status): Use GC to free them.
+ * expr.c (init_expr): Use GC to allocate 'struct expr_status'.
+ (mark_expr_status): Mark the structure itself.
+ (free_expr_status): Use GC to free the structure.
+ * stmt.c (free_stmt_status): Use GC to free 'struct stmt_status'.
+ (mark_stmt_status): Mark the 'struct stmt_status' itself.
+ (init_stmt_for_function): Allocate the structure for GC.
+
+ * dwarf2out.c (lookup_type_die): Use TYPE_SYMTAB_DIE.
+ (equate_type_number_to_die): Likewise.
+ * tree.h (TYPE_SYMTAB_DIE): New macro.
+ (struct die_struct): Predeclare.
+ (struct tree_type): Add field symtab.die. Add a tag
+ to the union type of field symtab.
+
+ * varray.h (VARRAY_RTVEC_INIT): A varray of rtvec contains
+ 'struct rtvec_def *', not 'struct rtvec_def'.
+
+ * function.h (original_arg_vector): Make a real rtvec.
+ * function.c (ggc_mark_struct_function): Adjust.
+ * integrate.c (expand_inline_function): Adjust.
+
+2002-06-04 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config.gcc (sh5-*-netbsd*, sh5l*-*-netbsd*)
+ (sh64-*-netbsd*, sh64l*-*-netbsd*): New targets.
+ * config/sh/netbsd-elf.h (TARGET_VERSION_ENDIAN)
+ (TARGET_VERSION_CPU): Define according to the
+ default target.
+ (TARGET_VERSION): Use TARGET_VERSION_ENDIAN and
+ TARGET_VERSION_CPU.
+ (TARGET_OS_CPP_BUILTINS): Use NETBSD_OS_CPP_BUILTINS_LP64
+ if TARGET_SHMEDIA64.
+ (LINK_DEFAULT_CPU_EMUL): Define according to the
+ default target.
+ (SUBTARGET_LINK_EMUL_SUFFIX): Define.
+ (SUBTARGET_LINK_SPEC): Define.
+ (LINK_SPEC): Use SH_LINK_SPEC.
+ (ASM_SPEC): Remove.
+ (TARGET_DEFAULT): Use TARGET_CPU_DEFAULT.
+ (FUNCTION_PROFILER): Add cases for TARGET_SHMEDIA32
+ and TARGET_SHMEDIA64 which abort, for now.
+ * config/sh/t-netbsd-sh5: New file.
+ * config/sh/t-netbsd-sh5-32: New file.
+ * config/sh/t-netbsd-sh5-64: New file.
+
+2002-06-03 Falk Hueffner <falk.hueffner@student.uni-tuebingen.de>
+ Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (reg_or_const_int_operand): New.
+ (some_operand, input_operand): Accept CONST_VECTOR.
+ (alpha_extra_constraint): Add 'W'.
+ (alpha_expand_zap_mask): New.
+ (alpha_expand_builtin_vector_binop): New.
+ (enum alpha_builtin): New.
+ (zero_arg_builtins, one_arg_builtins, two_arg_builtins): New.
+ (alpha_init_builtins, alpha_expand_builtin): New.
+ (TARGET_INIT_BUILTINS, TARGET_EXPAND_BUILTIN): New.
+ * config/alpha/alpha.h (VECTOR_MODE_SUPPORTED_P): New.
+ (PREDICATE_CODES): Update.
+ * config/alpha/alpha-protos.h: Update.
+ * config/alpha/alpha.md (UNSPEC_CMPBGE, UNSPEC_ZAP,
+ UNSPEC_AMASK, UNSPEC_IMPLVER, UNSPEC_PERR, UNSPECV_RPCC): New.
+ (movv8qi, movv8qi_fix, movv8qi_nofix): New.
+ (movv4hi, movv4hi_fix, movv4hi_nofix): New.
+ (movv2si, movv2si_fix, movv2si_nofix): New.
+ (uminv8qi3, sminv8qi3, uminv4hi3, sminv4hi3): New.
+ (umaxv8qi3, smaxv8qi3, umaxv4hi3, smaxv4hi3): New.
+ (builtin_cmpbge, builtin_extql, builtin_extqh, builtin_zap,
+ builtin_zap_1, builtin_zapnot, builtin_zapnot_1, builtin_amask,
+ builtin_implver, builtin_rpcc, builtin_minub8, builtin_minsb8,
+ builtin_minuw4, builtin_minsw4, builtin_maxub8, builtin_maxsb8,
+ builtin_maxuw4, builtin_maxsw4, builtin_perr, builtin_pklb,
+ pklb, builtin_pkwb, pkwb, builtin_unpkbl, unpkbl,
+ builtin_unpkbw, unpkbw): New.
+ * doc/extend.texi (Alpha Built-in Functions): New.
+
+2002-06-03 Richard Henderson <rth@redhat.com>
+
+ * crtstuff.c (__EH_FRAME_BEGIN__): Conditionalize on
+ USE_EH_FRAME_REGISTRY, not EH_FRAME_SECTION_NAME.
+
+2002-06-03 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha-protos.h: Eliminate unneeded ifdefs.
+
+ * config/alpha/alpha.c (reg_or_0_operand): Use CONST0_RTX.
+ (const0_operand): New.
+ (reg_or_fp0_operand, fp0_operand): Remove.
+ * config/alpha/alpha.h (PREDICATE_CODES): Update.
+ * config/alpha/alpha-protos.h: Update.
+ * config/alpha/alpha.md: Replace all uses of reg_or_fp0_operand
+ and fp0_operand with reg_or_0_operand and const0_operand.
+
+2002-06-03 Dan Nicolaescu <dann@godzilla.ics.uci.edu>
+
+ * alias.c (nonoverlapping_memrefs_p): Fix off by one error.
+
+2002-06-03 Roger Sayle <roger@eyesopen.com>
+
+ * gcse.c (cprop_jump): Use single_set to get the pattern
+ from the setcc argument.
+
+2002-06-03 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * diagnostic.h (diagnostic_count): Move from output_buffer to
+ diagnostic_context.
+ (diagnostic_kind_count): Adjust definition.
+
+Mon Jun 3 19:11:53 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * except.c (except.c): Do not rebuild CFG.
+ * toplev.c (rest_of_compilation): Recompute CFG after sibcall
+ optimization.
+
+Mon Jun 3 11:53:01 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * integrate.c (copy_insn_list): Properly pace the INSN_SCOPE copies.
+ * toplev.c: Include cfglahout.h
+ * Makefile.in (toplev.c): Add dependnecy.
+
+2002-06-03 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * config/i386/i386.h (TARGET_CPU_CPP_BUILTINS): New.
+ (CPP_CPU32_SPEC, CPP_CPU64_SPEC): Kill.
+ (CPP_CPUCOMMON_SPEC): Rename CPP_CPU_SPEC.
+
+2002-06-03 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/ns32k/netbsd.h: Update copyright years.
+ (TARGET_OS_CPP_BUILTINS): Define.
+ (CPP_PREDEFINES): Remove.
+ * config/ns32k/ns32k.h (CPP_PREDEFINES): Remove.
+ (TARGET_CPU_CPP_BUILTINS): Define.
+
+2002-06-02 Kazu Hirata <kazu@cs.umass.edu>
+
+ * emit-rtl.c: Fix formatting.
+ * errors.h: Likewise.
+ * except.c: Likewise.
+ * explow.c: Likewise.
+ * expmed.c: Likewise.
+ * expr.c: Likewise.
+ * expr.h: Likewise.
+
+2002-06-02 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/elf.h: Fix formatting.
+ * config/h8300/rtems.h: Likewise.
+
+2002-06-03 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/rs6000/netbsd.h (DRAFT_V4_STRUCT_RET): Remove.
+
+2002-06-02 Tom Tromey <tromey@redhat.com>
+
+ * fixinc/fixincl.x: Rebuilt.
+ * fixinc/inclhack.def (thread_keyword): Match `*__thread'.
+
+2002-06-02 Neil Booth <neil@daikokuya.demon.co.uk>
+
+config/i370:
+ * i370.h (TARGET_CPU_CPP_BUILTINS): Use.
+ * linux.h: Use TARGET_OS_CPP_BUILTINS rather than CPP_PREDEFINES.
+ * mvs.h: Similarly.
+ * oe.h: Similarly.
+
+Mon Jun 3 00:18:20 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * final.c (final): Allow notes to not have computed addresses;
+ kill no longer needed STACK_REGS ifdef.
+
+2002-06-02 Richard Henderson <rth@redhat.com>
+
+ * gcse.c (bypass_conditional_jumps): Fix typo last change.
+
+Sun Jun 2 23:02:11 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * loop.c (emit_prefetch_instructions): Properly place the address
+ computation.
+
+Sun Jun 2 22:56:48 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * basic-block.h (basic_block_for_insn, BLOCK_FOR_INSN): Kill.
+ (set_block_for_insn): Turn into macro.
+ * cfgbuild.c (find_basic_block): Do not clear basic_block_for_insn.
+ * cfglayout.c (insn_scopes): Kill.
+ (scope_to_insns_initialize): Do not use insn_scopes.
+ (scope_to_insns_finalize): Likewise.
+ (duplicate_insn_chain): Likewise.
+ (cfg_layout_initialize, cfg_layout_finalize): Do not turn scopes to notes.
+ * cfgrtl.c (basic_block_for_insn): Kill.
+ (delete_insn_and_edges, delete_insn_chain_and_edges): Simplify.
+ (create_basic_block_structure): Use reorder_insns.
+ (compute_bb_for_insn): Do not use basic_block_for_insn.
+ (merge_blocks_nomove): Likewise.
+ (update_bb_for_insn): Likewise.
+ (verify_flow_info): Likewise.
+ (set_block_for_insn): Kill.
+ * combine.c (try_combine): Update gen_rtx_INSN call.
+ * emit-rtl.c (gen_label_rtx): Update gen_rtx_CODE_LABEL call.
+ (mark_insn_raw, make_jump_insn_raw, make_call_insn_raw): Clear
+ scopes and BBs.
+ (add_insn_after, add_insn_before, remove_insn, reorder_insns): Simplify.
+ (emit_note_before, emit_note_after, emit_line_note_after, emit_note):
+ Clear BB.
+ (emit_insns_after): Simplify.
+ (emit_copy_of_insn_after): Copy scope.
+ * final.c (final_start_function): Lower scopes.
+ * flow.c (check_function_return_warnings): Do not rely on deleted insn.
+ * integrate.c (copy_insn_list): Cope scopes.
+ * jump.c (duplicate_loop_exit_test): LIkewise; simplify.
+ * loop.c (loop_optimize): Do not care block notes.
+ * print-rtl.c (print_rtx): Print BB.
+ * recog.c (apply_change_group): Simplify.
+ * rtl.c (copy_rtx): Handle 'B'.
+ * rtl.def (INSN, CALL_INSN, JUMP_INSN, NOTE): Add extra fields.
+ * rtl.h (Field accessors): Update indexes.
+ * sched-ebb.c (schedule_ebbs): Do not lower notes.
+ * sched-rgn.c (schedule_insns): Likewise.
+ * toplev.c (rest_of_compilation): Lower notes.
+ * unroll.c (unroll_loop): Do not care scoping notes.
+ (copy_loop_body): Copy scopes.
+
+2002-06-02 Neil Booth <neil@daikokuya.demon.co.uk>
+
+config/h8300:
+ * elf.h: Use TARGET_OS_CPP_BUILTINS rather than
+ SUBTARGET_SPEC.
+ * rtems.h: Similarly.
+ * h8300.h (CPP_PREDEFINES, CPP_SPEC, SUBTARGET_CPP_SPEC,
+ EXTRA_SPECS, SUBTARGET_EXTRA_SPECS): Remove.
+ (TARGET_CPU_CPP_BUILTINS): Use.
+
+2002-06-02 Richard Henderson <rth@redhat.com>
+
+ * alias.c: Include target.h.
+ (mark_constant_function): Use targetm.binds_local_p instead
+ of checking TREE_PUBLIC ourselves.
+ * Makefile.in (alias.o): Add TARGET_H.
+
+2002-06-02 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-lex.c: Update copyright and file description.
+
+2002-06-02 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * config/fr30/fr30.h: Update to new CPP macros.
+
+2002-06-02 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * config/dsp16xx/dsp16xx.h: Update to new CPP macros.
+
+2002-06-02 Neil Booth <neil@daikokuya.demon.co.uk>
+ Zack Weinberg <zack@codesourcery.com>
+
+ * c-common.c (c_common_init): Override cpplib's default
+ warn_long_long setting.
+ * c-lex.c (lex_number): Replace with interpret_integer,
+ interpret_float, narrowest_unsigned_type and
+ narrowest_signed_type, taking advantage of the new
+ cpplib functionality.
+ * cpperror.c (_cpp_begin_message): If a warning is turned
+ into an error, avoid printing "warning:".
+ * cppexp.c (cpp_num_sign_extend): New.
+ * cppinit.c: Update comment.
+ * cpplib.h (cpp_num_sign_extend): New.
+ * tree.h: Update comment.
+
+2002-06-02 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * diagnostic.h (struct diagnostic_context): Add new member
+ internal_error.
+ (internal_error_function): Remove declaration.
+ * diagnostic.c (internal_error_function): Remove definition..
+ (internal_error): Adjust use.
+
+2002-06-02 Richard Henderson <rth@redhat.com>
+
+ * rtl.h (CC0_P): New.
+ * gcse.c (cprop_jump): Use it with single_set. Tweak dump text.
+ (cprop_insn): Allow any mode register; use CC0_P. CSE out single_set.
+ (bypass_block): Save old dest block for dump text.
+ (bypass_conditional_jumps): Allow any mode register; use CC0_P.
+ Allow only true SET insns, not single_set.
+
+2002-06-02 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * diagnostic.c (diagnostic_finish): Rename to output_flush.
+ (clear_disgnostic_info): Rename to output_clear_data. Use false
+ instead of 0 for boolean value.
+ Adjust function call throughout.
+
+Sun Jun 2 19:15:27 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgrtl.c (commit_one_edge_insertion): Fix warning.
+ * gcse.c (bypass_conditional_jumps): CSE out single_set call.
+
+2002-06-02 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * d30v.h (CPP_PREDEFINES): Replace with
+ (TARGET_CPU_CPP_BUILTINS): New.
+
+2002-06-02 Roger Sayle <roger@eyesopen.com>
+
+ * config/alpha/alpha.h [ASM_OUTPUT_LABELREF]: Fix typo.
+
+Sun Jun 2 12:11:52 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * gcse.c (bypass_conditional_jumps): Use single set to obtain set.
+
+2002-06-02 Richard Henderson <rth@redhat.com>
+
+ * rtlanal.c (volatile_refs_p): Not automatically true for CALL.
+
+2002-06-02 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ Support for C++ constructors/destructors.
+ * config/avr/avr.c (avr_output_function_epilogue): Jump to exit()
+ instead of looping if main() returns.
+ (asm_file_start): Output global symbols that cause .data and .bss
+ initialization code to be linked in, unconditionally for now.
+ (avr_asm_out_ctor, avr_asm_out_dtor): New functions.
+ * config/avr/avr.h (CTORS_SECTION_ASM_OP, DTORS_SECTION_ASM_OP): New.
+ (TARGET_ASM_CONSTRUCTOR, TARGET_ASM_DESTRUCTOR): New.
+ (LIBSTDCXX): New.
+ * config/avr/libgcc.S (_exit): Split in .fini9 and .fini0 sections.
+ (__tablejump__): New.
+ (__do_copy_data, __do_clear_bss): New.
+ (__do_global_ctors, __do_global_dtors): New.
+ * config/avr/t-avr (LIB1ASMFUNCS): Add _copy_data, _clear_bss,
+ _ctors, _dtors.
+
+2002-06-02 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c4x/c4x.h (TARGET_CPU_CPP_BUILTINS): New.
+ (CPP_SPEC, CPP_PREDEFINES): Kill.
+ * c4x/rtems.h (CPP_PREDEFINES): Kill.
+ (TARGET_OS_CPP_BUILTINS): New.
+
+Sat Jun 1 23:29:51 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * Makefile.in (tracer.o): New.
+ * params.def (TRACER_*): New options.
+ * rtl.h (tracer): Declare.
+ * timevar.def (TV_TRACER): New.
+ * toplev.c (dump_file_index): Add DFI_tracer.
+ (dump_file_info): Add tracer.
+ (flag_tracer): New.
+ (lang_indepdenent_options): Add tracer.
+ (rest_of_compilation): Call tracer.
+ * tracer.c: New file.
+ * invoke.texi (-ftracer): Document.
+ (--param tracer-*): Document.
+
+2002-06-01 Daniel Berlin <dberlin@dberlin.org>
+
+ * tree-inline.c (expand_call_inline): Make the statement
+ expression we generate have a COMPOUND_STMT.
+
+2002-06-01 Roger Sayle <roger@eyesopen.com>
+
+ * gcse.c (cprop_cc0_jump): Function deleted.
+ (cprop_jump): Take an additional argument which is the possibly
+ NULL cc setting insn immediately before the conditional jump.
+ When a MODE_CC set is present, substitute it into the JUMP_INSN
+ before attempting the constant propagation.
+ (cprop_insn): Recognize cc setters followed by conditional jumps
+ as a special case. Use cprop_jump instead of cprop_cc0_jump.
+ (cprop_one_pass): Call bypass_conditional_jumps if altering jumps.
+ (find_bypass_set): New function based upon find_avail_set used by
+ cprop, but finds constant expressions available at the end of
+ basic blocks.
+ (bypass_block): New function. Given a basic block that begins
+ with a conditional jump and multiple incoming edges, perform
+ the jump bypass optimization.
+ (bypass_conditional_jumps): New function. Call bypass_block with
+ each suitable basic block in the CFG using a simple single pass.
+
+2002-06-01 Roger Sayle <roger@eyesopen.com>
+
+ * tree.c (real_minus_onep): New function to test for -1.0.
+ * fold-const.c (fold) [MULT_EXPR]: Optimize -1.0*x into -x.
+
+2002-06-01 Roger Sayle <roger@eyesopen.com>
+
+ * fold-const.c (fold_truthop): Transform "a || b" into "(a|b) != 0"
+ and "!p && !q" into "(p|q) == 0" under suitable conditions.
+
+2002-06-01 Andreas Jaeger <aj@suse.de>
+
+ * cppexp.c (cpp_classify_number): Cast precission to int for
+ correct printf format.
+
+2002-06-01 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (avr_mcu_types): Remove devices that were once
+ expected, but don't really exist: atmega83, atmega85, attiny10.
+ * config/avr/avr.h (LINK_SPEC): Update to use the new avr[1-5] ld
+ emulations for all devices.
+ (CRT_BINUTILS_SPECS): Remove atmega83, atmega85, attiny10.
+ * config/avr/t-avr (MULTILIB_MATCHES): Remove atmega83, atmega85.
+
+2002-06-01 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/h8300-protos.h: Add a prototype for
+ h8300_shift_needs_scratch_p.
+ * config/h8300/h8300.c (h8300_shift_needs_scratch_p): New.
+ * config/h8300/h8300.h (OK_FOR_R): New.
+ (OK_FOR_S): Likewise.
+ (OK_FOR_T): Likewise.
+ (EXTRA_CONSTRAINT): Call OK_FOR_R, OK_FOR_S, and OK_FOR_T.
+ * config/h8300/h8300.md (anonymous shift patterns): Use
+ constraints R, S, and T.
+
+Sat Jun 1 11:23:22 CEST 2002 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * basic-block.h (struct basic_block_def): New field loop_father.
+ (BB_VISITED): New flag.
+ (struct loop): New field pred, removed field shared.
+ (struct loops): New field parray.
+ (LOOP_EXITS_DOMS): Removed.
+ (flow_loop_tree_node_add, flow_loop_tree_node_remove,
+ flow_loop_nested_p, flow_bb_inside_loop_p, get_loop_body,
+ dfs_enumerate_from, loop_preheader_edge, loop_latch_edge,
+ add_bb_to_loop, remove_bb_from_loops, find_common_loop,
+ verify_loop_structure): Declare.
+ * cfg.c (entry_exit_blocks): Initialize loop_father field.
+ * cfganal.c (dfs_enumerate_from): New function.
+ * cfgloop.c (HEAVY_EDGE_RATIO): New constant.
+ (flow_loop_entry_edges_find, flow_loop_exit_edges_find,
+ flow_loop_nodes_find, flow_loop_level_compute, flow_loop_nested_p,
+ flow_loop_dump, flow_loops_dump, flow_loops_free,
+ flow_loop_tree_node_add, flow_loop_level_compute,
+ flow_loops_level_compute, flow_loop_scan, flow_loops_update,
+ flow_loop_outside_edge_p): Modified for new infrastructure.
+ (make_forwarder_block, canonicalize_loop_headers, glb_enum_p,
+ redirect_edge_with_latch_update, flow_loop_free): New static functions.
+ (flow_loop_tree_node_remove, flow_bb_inside_loop_p,
+ get_loop_body, add_bb_to_loop, remove_bb_from_loops,
+ find_common_loop, verify_loop_structure, loop_latch_edge,
+ loop_preheader_edge): New functions.
+ (flow_loops_cfg_dump): Do not show dominators, as this information
+ does not remain up to date long.
+ (flow_loops_find): Store results in new format.
+ * predict.c (propagate_freq, estimate_probability,
+ estimate_loops_at_level, estimate_bb_frequencies): Use new loop
+ infrastructure.
+
+2002-06-01 Alan Lehotsky <apl@alum.mit.edu>
+
+ * except.c (nothrow_function_p): Walk epilogue delay list
+ checking the insn, not the chain for potential throws.
+
+2002-05-31 Zack Weinberg <zack@codesourcery.com>
+
+ * Makefile.in (INSTALL_CPP, UNINSTALL_CPP): Remove.
+ (install): Refer to install-cpp directly.
+ (uninstall-cpp): Folded into uninstall rule.
+ * configure.in: Delete all code relating to --disable-cpp.
+ * configure: Regenerate.
+ * config/t-install-cpp: Delete.
+
+2002-05-31 Richard Henderson <rth@redhat.com>
+
+ * configure.in (HAVE_AS_TLS): Add alpha tests.
+ * configure: Rebuild.
+ * config/alpha/alpha.c (TARGET_AS_TLS): New.
+ (alpha_tls_size, alpha_tls_size_string): New.
+ (overide_options): Set it. Always install machine_status hooks.
+ (input_operand): Accept got tls predicates.
+ (local_symbol_p): Merge into ...
+ (local_symbolic_operand): ... here. Reject tls symbols.
+ (global_symbolic_operand): Likewise.
+ (tls_symbolic_operand_1, dtp16_symbolic_operand): New.
+ (dtp32_symbolic_operand, gotdtp_symbolic_operand): New.
+ (tp16_symbolic_operand, tp32_symbolic_operand): New.
+ (gottp_symbolic_operand, tls_symbolic_operand_type): New.
+ (alpha_encode_section_info): Handle TLS symbols.
+ (alpha_strip_name_encoding): Likewise.
+ (alpha_legitimate_address_p): Likewise.
+ (alpha_legitimize_address): Likewise.
+ (alpha_expand_mov): Early exit to avoid nop moves.
+ (struct machine_function): Move from unicosmk.h. Add some_ld_name.
+ (alpha_init_machine_status, alpha_mark_machine_status,
+ alpha_free_machine_status): Always define.
+ (get_some_local_dynamic_name, get_some_local_dynamic_name_1): New.
+ (print_operand, print_operand_address): Add TLS relocs.
+ * config/alpha/alpha.h (HAVE_AS_TLS): Default 0.
+ (MASK_TLS_KERNEL, TARGET_TLS_KERNEL): New.
+ (TARGET_SWITCHES): Add -mtls-kernel.
+ (alpha_tls_size, alpha_tls_size_string): New.
+ (TARGET_OPTIONS): Add -mtls-size=.
+ (reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS,
+ REGNO_REG_CLASS, REG_CLASS_FROM_LETTER): Add R0_REG.
+ (ASM_OUTPUT_LABELREF): Skip %.
+ (PRINT_OPERAND_PUNCT_VALID_P): Add &.
+ (PREDICATE_CODES): Update.
+ * config/alpha/alpha.md (UNSPEC_TLSGD_CALL, UNSPEC_TLSLDM_CALL,
+ UNSPEC_TLSGD, UNSPEC_TLSLDM, UNSPEC_DTPREL, UNSPEC_TPREL,
+ UNSPEC_TP, UNSPECV_SET_TP): New.
+ (adddi_er_lo16_dtp, adddi_er_hi32_dtp, adddi_er_lo32_dtp,
+ adddi_er_lo16_tp, adddi_er_hi32_tp, adddi_er_lo32_tp, load_tp,
+ set_tp, movdi_er_tlsgd, movdi_er_tlsldm, movdi_er_gotdtp,
+ movdi_er_gottp, call_value_osf_tlsgd, call_value_osf_tlsldm): New.
+ (call_value_osf_2_er): Accept anything as op4.
+ * config/alpha/alpha-protos.h: Update.
+ * config/alpha/unicosmk.h (struct machine_function): Move to alpha.c.
+
+2002-05-31 Zack Weinberg <zack@codesourcery.com>
+
+ * cppinit.c (append_include_chain): Always pay attention to
+ cxx_aware when setting new->sysp. Remove ATTRIBUTE_UNUSED
+ marker on argument.
+
+2002-05-31 Kazu Hirata <kazu@cs.umass.edu>
+
+ * target.h: Fix formatting.
+ * timevar.h: Likewise.
+ * tlink.c: Likewise.
+ * toplev.c: Likewise.
+ * toplev.h: Likewise.
+ * tree.c: Likewise.
+ * tree-dump.h: Likewise.
+ * tree.h: Likewise.
+ * tree-inline.h: Likewise.
+ * unroll.c: Likewise.
+ * unwind-dw2.c: Likewise.
+ * unwind-dw2-fde.c: Likewise.
+ * unwind-dw2-fde-glibc.c: Likewise.
+ * unwind-dw2-fde.h: Likewise.
+ * unwind.h: Likewise.
+ * unwind-sjlj.c: Likewise.
+ * varasm.c: Likewise.
+ * varray.h: Likewise.
+ * vmsdbg.h: Likewise.
+ * vmsdbgout.c: Likewise.
+ * xcoffout.h: Likewise.
+
+2002-05-31 Igor Shevlyakov <igor@microunity.com>
+
+ * expr.c (compare_from_rtx): Generate comparison between op0 and op1
+ rather than cc0 and 0 in a case when HAVE_cc0 is not defined.
+
+2002-05-31 Matthew Woodcraft <mattheww@chiark.greenend.org.uk>
+
+ * gcc.c (cpp_unique_options): Remove "-d" options.
+ (cpp_debug_options): New spec string.
+ (default_compilers): Use it.
+ * objc/lang-specs.h: Likewise.
+
+2002-05-31 Nathanael Nerode <neroden@twcny.rr.com>
+
+ * gcc/Makefile.in: Replace HOST_PREFIX, HOST_PREFIX_1 with
+ BUILD_PREFIX, BUILD_PREFIX_1, to correct nomenclature.
+ * gcc/mklibgcc.in: Likewise.
+ * gcc/config/arc/t-arc: Likewise.
+ * gcc/configure.in: Likewise.
+ * gcc/configure: Regenerate.
+
+2002-05-31 Stan Shebs <shebs@apple.com>
+ Turly O'Connor <turly@apple.com>
+
+ * c-decl.c (struct binding_level): Change int field n_incomplete
+ to tree list incomplete_list.
+ (clear_binding_level): Init field with NULL.
+ (pushdecl): Add incomplete type to list.
+ (mark_binding_level): Mark the incomplete list.
+ (finish_struct): Scan the incomplete list for types instead
+ of all decls in the current binding level.
+
+2002-05-31 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.c (output_millicode_call): Add missing '%' characters.
+ (output_call): Likewise.
+
+2002-05-31 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/xcoff.h (HOT_TEXT_SECTION_NAME): Define.
+ (UNLIKELY_EXECUTED_TEXT_SECTION_NAME): Define.
+
+2002-05-31 Alan Lehotsky <apl@alum.mit.edu>
+
+ * varasm.c (mark_constant_pool): Walk epilogue delay list
+ checking the insn, not the chain for potential constants.
+
+Fri May 31 12:38:43 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * config/sh/elf.h (ASM_SPEC): Use subtarget_endian_asm_spec.
+
+Fri May 31 13:50:19 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (classify_argument): Properly handle base types.
+
+ * dwarf2out.c (expand_builin_init_dwarf_reg_sizes):
+ Store first DWARF_FRAME_REGISTERS dwarf registers, not pseudo
+ registers.
+
+Fri May 31 13:37:54 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * gcse.c (gcse_emit_move_after): New.
+ (pre_delete, hoist_store): Use it.
+
+ * reload1.c (emit_input_reload_insns): Use constrain_operands
+ instead of constraint_accepts_reg_p to verify optimization.
+ (constraint_accepts_reg_p): Kill.
+
+ * reload1.c (reload_cse_delete_noop_set): Kill.
+ (reload_cse_simplify): Use delete_insn_and_edges.
+
+2002-05-31 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * cfgloop.c (flow_loops_find): Initialize first and last fields
+ correctly.
+
+2002-05-31 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (builtin_define_std): Correct logic.
+
+2002-05-31 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.c (output_millicode_call): Correct "be,l" insn for TARGET_PA_20.
+ (output_call): Likewise.
+
+2002-05-31 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.c: Move output.h include after tree.h include.
+ (pa_asm_output_mi_thunk): Constify identifier lab.
+
+2002-05-31 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/ns32k/ns32k.h: Define named constants for the
+ bits in target_flags and use them.
+ * config/ns32k/netbsd.h (TARGET_DEFAULT): Use named constants.
+
+2002-05-30 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * config.gcc (tm_file): Prefix pa/pa-700.h to tm_file list for PA1.0
+ architecture and pa/pa-7100.h for PA1.1 architecture, respectively.
+ * pa/pa.c (override_options): Use TARGET_SCHED_DEFAULT to select
+ default scheduling model.
+ * pa/pa.h (TARGET_SCHED_DEFAULT): Define if not defined to "8000".
+ * pa/pa-700.h (TARGET_SCHED_DEFAULT): New file for "700" scheduling.
+ * pa/pa-7100.h (TARGET_SCHED_DEFAULT): New file for "7100" scheduling.
+ * doc/install.texi (hppa*-*-*): Document default scheduling.
+
+2002-05-30 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.c (following_call): Check TARGET_JUMP_IN_DELAY.
+
+2002-05-31 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config.gcc (ns32k-*-netbsd*): Set tm_file to
+ "${tm_file} netbsd.h netbsd-aout.h ns32k/netbsd.h"
+ * config/ns32k/netbsd.h: Don't include ns32k/ns32k.h,
+ netbsd.h, or netbsd-aout.h.
+
+2002-05-31 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * longlong.h (count_trailing_zeros): Add missing \, and clean up
+ whitespace in __ns32000__ case.
+
+2002-05-31 Aldy Hernandez <aldyh@redhat.com>
+
+ * expr.c (expand_expr): Output partially zeroed out vectors with
+ output_constant_def.
+
+2002-05-30 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config.gcc (sh[123456789l]*-*-*): Set cpu_type to sh.
+ (sh-*-netbsdelf*)
+ (shl*-*-netbsdelf*): New targets.
+ * config/sh/netbsd-elf.h: New file.
+ * config/sh/t-netbsd: New file.
+
+2002-05-30 Richard Henderson <rth@redhat.com>
+ Eric Botcazou <ebotcazou@multimania.com>
+
+ PR optimization/6822
+ * config/i386/i386.c (ix86_expand_int_movcc): Don't cast INTVAL
+ to unsigned int for op1 comparisons. Use gen_int_mode.
+
+2002-05-30 Eric Botcazou <ebotcazou@multimania.com>
+
+ * expmed.c (const_mult_add_overflow_p): New.
+ * expr.h: Declare it.
+ * loop.c (maybe_eliminate_biv_1) [COMPARE]: Use it.
+ Don't eliminate the biv if the giv has a constant multiplier and
+ the rhs argument of the comparison does satisfy the predicate.
+ Use expand_mult_add to compute the replacement constant.
+
+2002-05-30 Osku Salerma <osku@iki.fi>
+
+ * c-common.c (c_common_attribute_table): Add "may_alias" entry.
+ (c_common_get_alias_set): Handle it.
+ * doc/extend.texi: Document it.
+
+2002-05-30 Richard Henderson <rth@redhat.com>
+
+ * defaults.h (TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER): Kill.
+ * toplev.c (process_options): Don't check it.
+ * doc/tm.texi: Don't document it.
+ * config/i386/linux.h (SUBTARGET_FRAME_POINTER_REQUIRED): New.
+ (TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER): Kill.
+ * config/i386/i386.c (ix86_frame_pointer_required): Suppress leaf
+ frame pointer optimization if current_function_profile.
+
+2002-05-30 Kazu Hirata <kazu@cs.umass.edu>
+
+ * langhooks.c: Fix formatting.
+ * langhooks.h: Likewise.
+ * lcm.c: Likewise.
+ * libgcc2.c: Likewise.
+ * lists.c: Likewise.
+ * local-alloc.c: Likewise.
+ * loop.c: Likewise.
+ * loop.h: Likewise.
+
+2002-05-30 Marc Espie <espie@openbsd.org>
+
+ * config.gcc (sparc64-*-openbsd*): New.
+ * config/sparc/openbsd1-64.h: New.
+ * config/sparc/openbsd64.h: New.
+
+2002-05-30 Jeff Law <law@redhat.com>
+
+ * flow.c (propagate_one_insn): Revise yesterday's patch. Delete
+ a dead insn with a REG_RETVAL note when the entire libcall is not
+ dead and remove the associated REG_LIBCALL note at the same time.
+
+Thu May 30 19:54:30 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * lcm.c (output.h): #include.
+ (compute_earliest): Remove hack to treat renumbered EXIT_BLOCK
+ as an ordinary block.
+ (optimize_mode_switching): Don't pretend that the exit block is
+ an ordinary block, or handle sucessors of entry block specially.
+ Instead, split edges from entry block and to exit block, and
+ put a computing definition on the thus gained post-entry-block,
+ and a need on the pre-exit-block.
+
+Thu May 30 20:28:01 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * gengenrtl.c (type_from_format, accessor_from_format): Support 'B'.
+ * rtl.texi: Document 'B'
+
+2002-05-30 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/m68k/netbsd-elf.h (LONG_DOUBLE_TYPE_SIZE): Compute
+ at run-time.
+ (LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Set to 96 if not __mc68010__.
+
+2002-05-30 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c (rs6000_expand_unop_builtin): Return
+ const0_rtx instead of NULL_RTX when in error.
+ (altivec_expand_abs_builtin): Same.
+ (rs6000_expand_binop_builtin): Same.
+ (altivec_expand_predicate_builtin): Same.
+ (altivec_expand_stv_builtin): Same.
+ (rs6000_expand_ternop_builtin): Same.
+ (altivec_expand_builtin): Same.
+
+2002-05-29 David S. Miller <davem@redhat.com>
+
+ * rtl.h (clear_emit_caches): Delete.
+ * integrate.c (output_inline_function): Don't call it.
+ * emit-rtl.c (restore_emit_status, init_emit): Likewise.
+ (clear_emit_caches): Delete definition.
+ (SEQUENCE_RESULT_SIZE, sequence_result, free_insn): Likewise.
+
+2002-05-30 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.c: Include real.h.
+ (mmix_constant_address_p): Remove redundant test before switch.
+
+2002-05-29 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/mips/mips.h (READONLY_DATA_SECTION_ASM_OP): Define
+ only if not already defined.
+
+2002-05-29 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/h8300-protos.h: Remove prototypes for
+ ok_for_bclr and small_power_of_two.
+ * config/h8300/h8300.c (small_power_of_two): Remove.
+ (ok_for_blcr): Likewise.
+ (fix_bit_operand): Make WHAT deal with an integer instead of a
+ constraint character.
+ * config/h8300/h8300.h (CONST_OK_FOR_O): Remove.
+ (CONST_OK_FOR_P): Likewise.
+ (CONST_OK_FOR_LETTER_P): Do not call CONST_OK_FOR_O or
+ CONST_OK_FOR_P any more.
+ * config/h8300/h8300.md (andqi3): Adjust to the new prototype
+ of fix_bit_operand.
+ (iorqi3): Likewise.
+ (xorqi3): Likewise.
+
+2002-05-29 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/mips/netbsd.h (TARGET_OS_CPP_BUILTINS): Define.
+ (CPP_PREDEFINES): Make sure this is undefined.
+ (CPP_SPEC): Place -D__mips=1 at the beginning of the spec,
+ since it is no longer in CPP_PREDEFINES. Don't -U__MIPSEL__
+ or -U__MIPSEB__ before defining one or the other. Instead,
+ use %(subtarget_endian_default) if neither -EB nor -EL are
+ specified.
+ (SUBTARGET_EXTRA_SPECS): Define.
+ (SUBTARGET_CPP_SPEC): Remove __LONG64 handling. Use
+ %(netbsd_cpp_spec).
+
+2002-05-29 Hans-Peter Nilsson <hp@axis.com>
+
+ * doc/md.texi (Patterns): Note pattern condition pitfall
+ for unnamed insn.
+
+2002-05-29 Aldy Hernandez <aldyh@redhat.com>
+
+ * rs6000.c: (altivec_expand_builtin): Only expand altivec builtins
+ when TARGET_ALTIVEC. Move handling of generic unary, binary, and
+ ternary operations from here...
+ (rs6000_expand_builtin): ...to here.
+ New argument expandedp.
+ Change all instances of altivec_expand_binop_builtin to
+ rs6000_expand_binop_builtin.
+ (altivec_expand_unop_builtin): Rename to
+ rs6000_expand_unop_builtin.
+ (altivec_expand_binop_builtin): Rename to
+ rs6000_expand_binop_builtin.
+ (altivec_expand_ternop_builtin): Rename to
+ rs6000_expand_ternop_builtin.
+
+2002-05-29 Richard Henderson <rth@redhat.com>
+
+ * config/i386/biarch64.h (TARGET_64BIT_DEFAULT): Define with value.
+ (TARGET_BI_ARCH): Likewise.
+ * config/i386/i386.h: Test TARGET_64BIT_DEFAULT by value.
+ (TARGET_SWITCHES): Combine target defaults here not in TARGET_DEFAULT.
+ (TARGET_64BIT_DEFAULT): Default to 0.
+ (TARGET_DEFAULT): Default to MASK_OMIT_LEAF_FRAME_POINTER.
+
+2002-05-29 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (USE_HIDDEN_LINKONCE): New.
+ (get_pc_thunk_name): New.
+ (output_set_got): Use it.
+ (ix86_asm_file_end): If USE_HIDDEN_LINKONCE, emit get_pc thunks
+ into linkonce sections.
+
+2002-05-29 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/sparc/netbsd-elf.h (TARGET_OS_CPP_BUILTINS): Define.
+ (CPP_PREDEFINES): Make sure this is undefined.
+ (CPP_SUBTARGET_SPEC64, CPP_SUBTARGET_SPEC32): Remove.
+ (CPP_SUBTARGET_SPEC): Don't provide different versions for
+ default-32 and default-64. Just always use %(netbsd_cpp_spec).
+ (SUBTARGET_EXTRA_SPECS): Remove cpp_subtarget_spec32 and
+ cpp_subtarget_spec64. Add netbsd_cpp_spec.
+ * config/sparc/netbsd.h (TARGET_OS_CPP_BUILTINS): Define.
+ (CPP_PREDEFINES): Make sure this is undefined.
+ (SUBTARGET_EXTRA_SPECS): Define.
+ (CPP_SPEC): Use %(netbsd_cpp_spec).
+
+2002-05-29 Jeff Law <law@redhat.com>
+
+ * pa.h (ASM_OUTPUT_MI_THUNK): Remove unwanted semi-colon.
+
+ * flow.c (propagate_one_insn): Do not remove a dead insn if it
+ contains a REG_RETVAL note.
+
+ * haifa-sched (sched_analyze): Remove another useless clearing
+ of SCHED_GROUP_P I missed yesterday.
+
+ * pa.h (ASM_OUTPUT_MI_THUNK): Move implementation into pa.c.
+ * pa.c (pa_asm_output_mi_thunk): New function.
+ * pa-protos.h (pa_asm_output_mi_thunk): Declare.
+
+2002-05-29 Neil Booth <neil@daikokuya.demon.co.uk>
+ Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (avr_base_arch_macro, avr_extra_arch_macro): New.
+ (avr_asm_only_p): Make non-static.
+ (enum avr_arch): Remove.
+ (avr_arch_types): New.
+ (avr_mcu_types): Update.
+ (avr_override_options): Use avr_arch_types table instead of switch.
+ * avr.h (CPP_PREDEFINES): Die.
+ (avr_base_arch_macro, avr_extra_arch_macro): New.
+ (TARGET_CPU_CPP_BUILTINS): New.
+ (CPP_SPEC, EXTRA_SPECS): Simplify.
+ (CPP_AVR1_SPEC, CPP_AVR2_SPEC, CPP_AVR3_SPEC, CPP_AVR4_SPEC,
+ CPP_AVR5_SPEC): Die.
+
+2002-05-29 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/arm/netbsd.h (TARGET_OS_CPP_BUILTINS): Use
+ NETBSD_OS_CPP_BUILTINS_AOUT.
+ (SUBTARGET_EXTRA_SPECS): Define.
+ (CPP_SPEC): Use %(netbsd_cpp_spec).
+
+2002-05-29 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (ix86_output_function_epilogue): New.
+ (TARGET_ASM_FUNCTION_EPILOGUE): New.
+ (pic_label_name): Remove.
+ (pic_labels_used): New.
+ (ix86_asm_file_end): Emit one pc load stub for each register used.
+ (output_set_got): Generate deep pc load to any register.
+ (ix86_select_alt_pic_regnum): New.
+ (ix86_save_reg): Don't save pic register if we can find a valid
+ call-clobbered replacement.
+ (ix86_expand_prologue): If we found a valid replacement, renumber
+ pic_offset_table_rtx.
+ * config/i386/i386.h (PIC_OFFSET_TABLE_REGNUM): Look at
+ pic_offset_table_rtx after reload.
+ (REAL_PIC_OFFSET_TABLE_REGNUM): New.
+ * config/i386/i386.md (set_got): Make insn, not expander.
+ (set_got_nopic, set_got_deep, set_got_nodeep): Remove.
+
+2002-05-29 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (ix86_compute_frame_layout): Do add bottom
+ alignment for alloca.
+
+2002-05-29 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (output_pic_addr_const): Lowercase rip.
+ (print_operand_address): Only add rip for symbolic addresses
+ for which we do not have another relocation type.
+
+2002-05-29 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/m68k/netbsd-elf.h (TARGET_OS_CPP_BUILTINS): Define.
+ (EXTRA_SPECS): Add netbsd_cpp_spec.
+ (CPP_SPEC): Use %(netbsd_cpp_spec).
+ (CPP_PREDEFINES): Remove.
+ * config/m68k/netbsd.h (TARGET_OS_CPP_BUILTINS): Define.
+ (EXTRA_SPECS): Define.
+ (CPP_SPEC): Use %(netbsd_cpp_spec).
+ (CPP_PREDEFINES): Remove.
+
+2002-05-29 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ PR preprocessor/6844
+ * cppmacro.c (cpp_macro_definition): Reserve space for terminating
+ NUL.
+
+2002-05-29 Eric Christopher <echristo@redhat.com>
+
+ * config/mips/linux.h (SUBTARGET_CPP_SPEC): Add support for
+ mips5/mips32/mips64 and _MIPS_ISA_MIPSXX.
+
+2002-05-29 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/fr30/fr30.md: Remove previous restriction on splits.
+ Enforce conformance through gen_lowpart and cont_int_operand.
+ * config/fr30/fr30.h (BSS_SECTION_ASM_OP): Use ".section .bss"
+ as the assembler does not support ".bss".
+
+2002-05-29 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/i386/netbsd-elf.h (TARGET_OS_CPP_BUILTINS): Define.
+ (CPP_PREDEFINES): Remove.
+ (SUBTARGET_EXTRA_SPECS): Define.
+ (CPP_SPEC): Use %(netbsd_cpp_spec).
+ * config/i386/netbsd.h (TARGET_OS_CPP_BUILTINS): Define.
+ (CPP_PREDEFINES): Remove.
+ (SUBTARGET_EXTRA_SPECS): Define.
+ (CPP_SPEC): Use %(netbsd_cpp_spec).
+ * config/i386/netbsd64.h (TARGET_OS_CPP_BUILTINS): Define.
+ (CPP_PREDEFINES, CPP_LP64_SPEC, CPP_SUBTARGET_SPEC): Remove.
+ (SUBTARGET_EXTRA_SPECS): Remove cpp_lp64 and cpp_subtarget.
+ Add netbsd_cpp_spec.
+ (CPP_SPEC): Remove %(cpp_subtarget), add %(netbsd_cpp_spec).
+
+2002-05-29 Neil Booth <neil@daikokuya.demon.co.uk>
+ Zack Weinberg <zack@codesourcery.com>
+
+ * cppexp.c (cpp_num): Move to cpplib.h.
+ (CPP_ERROR): Remove.
+ (interpret_float_suffix, interpret_int_suffix): New.
+ (struct suffix, vsuf_1, vsuf_2, vsuf_3): Remove.
+ (cpp_classify_number, cpp_interpret_integer): New.
+ (interpret_number): Remove.
+ (eval_token): Update to use new routines.
+ * cpphash.h (cpp_num_part): Move to cpplib.h.
+ * cppinit.c (cpp_post_options): Set warn_long_long.
+ * cpplib.h (struct cpp_options): Add warn_long_long.
+ (cpp_num, cpp_num_part, CPP_N_CATEGORY, CPP_N_INVALID,
+ CPP_N_INTEGER, CPP_N_FLOATING, CPP_N_WIDTH, CPP_N_SMALL,
+ CPP_N_MEDIUM, CPP_N_LARGE, CPP_N_RADIX, CPP_N_DEC, CPP_N_HEX,
+ CPP_N_OCTAL, CPP_N_UNSIGNED, CPP_N_IMAGINARY, cpp_classify_number,
+ cpp_interpret_integer): New.
+
+2002-05-29 Joel Sherrill <joel@OARcorp.com>
+
+ * config/rs6000/rs6000.h (ASM_CPU_SPEC): Use -m403 and -m405.
+
+2002-05-29 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/alpha/netbsd.h (TARGET_OS_CPP_BUILTINS): Use
+ NETBSD_OS_CPP_BUILTINS_ELF and NETBSD_OS_CPP_BUILTINS_LP64.
+ (CPP_SUBTARGET_SPEC): Define.
+ (SUBTARGET_EXTRA_SPECS): Define.
+ (CPP_SPEC): Remove.
+
+2002-05-29 Chris Lattner <sabre@nondot.org>
+
+ * ssa.c (rename_insn_1): Rename uses of undefined registers to
+ prevent confusion if/when the register is defined.
+
+2002-05-29 Hans-Peter Nilsson <hp@axis.com>
+
+ PR target/6838
+ * config/cris/cris.md: Fix typos and thinkos in comments.
+ ("*mov_sideqi_biap_mem"): Remove '*' in constraint for operand 4,
+ second alternative.
+ ("*mov_sidehi_biap_mem", "*mov_sidesi_biap_mem"): Ditto.
+ ("*mov_sideqi_mem"): Similar, but for operand 3.
+ ("*mov_sidehi_mem", "*mov_sidesi_mem"): Ditto.
+ (splitter for mov_sideqi_mem, mov_sidehi_mem, mov_sidesi_mem):
+ Remove spurious mode specifier on operand 2.
+
+2002-05-29 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/h8300-protos.h: Remove the prototype for
+ o_operand.
+ Add prototypes for single_one_operand and single_zero_operand.
+ * config/h8300/h8300.c (o_operand): Remove.
+ (single_one_operand): New.
+ (single_zero_operand): Likewise.
+ (print_operand): For 'V' operand, and the operand with 0xff.
+ For 'V' and 'W' operands, do not and the bit position with 7.
+ * config/h8300/h8300.md (various anonymous patterns): Replace
+ use of exact_log2 with single_one_operand/single_zero_operand.
+
+2002-05-29 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/linux.h (MD_FALLBACK_FRAME_STATE_FOR): New.
+
+2002-05-29 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.c (legitimate_pic_operand_p): Do not
+ accept symbolic LARL operands.
+ (s390_emit_epilogue): Do not set FRAME_RELATED_P on
+ epilogue insns.
+
+2002-05-29 Hartmut Penner <hpenner@de.ibm.com>
+
+ * config/s390/s390.md (cmpstr_64/31): Mark whole
+ input registers as used.
+
+2002-05-28 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (ix86_save_reg): Examine regs_ever_live,
+ not current_function_uses_pic_offset_table and
+ current_function_uses_const_pool; examine current_function_profile.
+ (ix86_expand_prologue): Likewise. Add pic_offset_table_rtx as
+ input to blockage if needed.
+ (ix86_expand_call): Do not set current_function_uses_pic_offset_table.
+ (legitimize_pic_address): Likewise. Set regs_ever_live for
+ pic_offset_table_rtx when invoked during reload.
+ * config/i386/i386.h (FINALIZE_PIC): Remove.
+ * config/i386/i386.md (tablejump): Reformat. Do not set
+ current_function_uses_pic_offset_table.
+ (tls_global_dynamic, tls_local_dynamic_base): Likewise.
+ (blockage): Accept anything as operand 0.
+
+2002-05-28 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/netbsd-aout.h (NETBSD_OS_CPP_BUILTINS_AOUT): Define
+ common CPP built-ins for all NetBSD a.out targets.
+ * config/netbsd-elf.h (NETBSD_OS_CPP_BUILTINS_ELF): Define
+ common CPP built-ins for all NetBSD ELF targets.
+ * config/netbsd.h: Add missing notice.
+ (NETBSD_OS_CPP_BUILTINS_COMMON): Define common CPP built-ins
+ for all NetBSD targets.
+ (NETBSD_OS_CPP_BUILTINS_LP64): Define common CPP built-ins
+ for all NetBSD targets using an LP64 code model.
+ (NETBSD_CPP_SPEC): Define CPP_SPEC parts common to all
+ NetBSD targets.
+
+2002-05-28 Richard Henderson <rth@redhat.com>
+
+ * flow.c (update_life_info_in_dirty_blocks): Only do a partial
+ update if UPDATE_LIFE_LOCAL.
+
+2002-05-28 Toshiyasu Morita <toshiyasu.morita@hsa.hitachi.com>
+
+ * config/sh/sh.c: Include real.h for REAL_VALUE_TYPE.
+
+Tue May 28 21:16:18 2002 J"orn Rennecke <joern.rennecke@superh.com>
+ Jason R. Thorpe <thorpej@wasabisystems.com>
+
+ config/sh reorganization to factor out endianness and coff:
+
+ * config/sh/little.h: New file.
+ * config/sh/sh.h (TARGET_ENDIAN_DEFAULT): If not already
+ defined, define to 0 to select big-endian.
+ (SUBTARGET_ASM_ENDIAN_SPEC): Define according to TARGET_ENDIAN_DEFAULT.
+ (TARGET_DEFAULT): Include TARGET_ENDIAN_DEFAULT.
+ * config/sh/sh64.h (TARGET_DEFAULT): Include TARGET_ENDIAN_DEFAULT.
+ * config/sh/t-be: New file.
+ * config/sh/t-le: New file.
+
+ * sh.h (SDB_DEBUGGING_INFO, #include "dbxcoff.h"): Moved to sh/coff.h.
+ (SDB_DELIM, MAX_OFILE_ALIGNMENT, IDENT_ASM_OP): Likewise.
+ (TARGET_ASM_NAMED_SECTION, ASM_OUTPUT_SKIP): Likewise.
+ (USER_LABEL_PREFIX, LOCAL_LABEL_PREFIX): Likewise.
+ (ASM_GENERATE_INTERNAL_LABEL, ASM_OUTPUT_INTERNAL_LABEL): Likewise.
+ (ASM_OUTPUT_COMMON, ASM_OUTPUT_LOCAL): Likewise.
+ (ASM_FILE_END, ASM_DECLARE_FUNCTION_NAME): Deleted.
+ (CPP_SPEC, SUBTARGET_CPP_ENDIAN_SPEC): Likewise.
+ (SUBTARGET_CPP_SPEC, CPP_DEFAULT_CPU_SPEC, CPP_PREDEFINES): Likewise.
+ (EXTRA_SPECS): Remove SUBTARGET_CPP_ENDIAN_SPEC and
+ CPP_DEFAULT_CPU_SPEC. Add LINK_EMUL_PREFIX, LINK_DEFAULT_CPU_EMUL,
+ SUBTARGET_LINK_EMUL_SUFFIX and SUBTARGET_LINK_SPEC.
+ (LINK_SPEC): Define to SH_LINK_SPEC.
+ (TARGET_CPU_CPP_BUILTINS, SH_LINK_SPEC): Define.
+ (LINK_EMUL_PREFIX, LINK_DEFAULT_CPU_EMUL): Likewise.
+ (SUBTARGET_LINK_EMUL_SUFFIX, SUBTARGET_LINK_SPEC): Likewise.
+ (CPP_SPEC): Reduce to %(subtarget_cpp_spec).
+ (TARGET_ENDIAN_DEFAULT): Define if not already defined.
+ * config/sh/coff.h: New file.
+ (TARGET_ASM_NAMED_SECTION): Now default_coff_asm_named_section
+ (TARGET_OBJFMT_CPP_BUILTINS): Define.
+ * config/sh/elf.h (IDENT_ASM_OP): No need to #undef at the start.
+ (ASM_FILE_END, ASM_OUTPUT_SOURCE_LINE): Likewise.
+ (DBX_OUTPUT_MAIN_SOURCE_FILE_END, TARGET_ASM_NAMED_SECTION): Likewise.
+ (ASM_DECLARE_FUNCTION_NAME, MAX_OFILE_ALIGNMENT, SIZE_TYPE): Likewise.
+ (PTRDIFF_TYPE): Likewise.
+ ("dbxelf.h", "elfos.h", "svr4.h"): Don't #include.
+ (CPP_PREDEFINES): Don't define.
+ (TARGET_OBJFMT_CPP_BUILTINS): Define.
+ (LINK_SPEC): Define to SH_LINK_SPEC.
+ (LINK_EMUL_PREFIX): Redefine.
+ * config/sh/linux.h: (SUBTARGET_CPP_SPEC): Remove -fpic / -fPIC cases.
+ (SUBTARGET_CPP_ENDIAN_SPEC, CPP_DEFAULT_CPU_SPEC): Remove redefinition.
+ (CPP_PREDEFINES, SUBTARGET_ASM_ENDIAN_SPEC): Likewise.
+ (CC1_SPEC, CC1PLUS_SPEC, LINK_SPEC): Likewise.
+ (TARGET_OS_CPP_BUILTINS): Define.
+ (TARGET_DEFAULT): Redefine.
+ (SUBTARGET_LINK_EMUL_SUFFIX, SUBTARGET_LINK_SPEC): Likewise.
+ * config/sh/sh64.h (CPP_DEFAULT_CPU_SPEC): Remove.
+ (LINK_SPEC): Don't redefine.
+ (LINK_DEFAULT_CPU_EMUL): Redefine.
+ (TARGET_DEFAULT): Include TARGET_ENDIAN_DEFAULT.
+ * sh.c (sh_asm_named_section): Don't declare / define.
+ * t-linux (MULTILIB_OPTIONS): Rely on pre-set endianness option.
+ * config.gcc (sh-*-elf* tm_file): Add dbxelf.h elfos.h svr4.h.
+ (sh64-*-elf* tm_file): Likewise.
+ (sh-*-rtemself* tm_file): Likewise.
+ (sh-*-linux* tm_file): Likewise. Add sh/little.h.
+ (sh-*-linux* tmake_file): Add sh/t-le.
+ (sh-*-rtems* tm_file): Add sh/coff.h
+ (sh-*-* tm_file): Likewise.
+
+Tue May 28 21:16:18 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.h (LEGITIMATE_PIC_OPERAND_P): Check for SYMBOL_REF before using
+ CONSTANT_POOL_ADDRESS_P.
+
+ * coff.h (HAS_INIT_SECTION, INVOKE__MAIN): Define.
+
+2002-05-28 David Edelsohn <edelsohn@gnu.org>
+ Jeff Law <law@redhat.com>
+
+ * optabs.c (expand_binop): Fix nwords sign warnings.
+ generate pseudo for add_optab.
+
+ * sched-deps.c (sched_analyze): Do not clear SCHED_GROUP_P.
+ * haifa-sched.c (move_insn): Clear SCHED_GROUP_P after it is used.
+
+2002-05-28 Marc Espie <espie@openbsd.org>
+
+ * config/i386/openbsd.h (HAVE_GAS_MAX_SKIP_P2ALIGN): Remove,
+ inherited from gas.h.
+ (ASM_QUAD): Undef. OpenBSD does not support it.
+
+2002-05-28 Danny Smith <dannysmith@users.sourceforge.net>
+
+ * doc/install.texi (binaries): Change mingw binaries
+ link to www.mingw.org.
+
+2002-05-28 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * cfgloop.c (flow_loops_cfg_dump): Use bb->index, not i.
+
+2002-05-28 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (ix86_compute_frame_layout): Do not add
+ bottom alignment for leaf functions.
+
+2002-05-28 Zack Weinberg <zack@codesourcery.com>
+
+ * config/pa/milli32.S, config/pa/lib1funcs.asm,
+ config/sparc/sol2-g1.asm: Delete unused files.
+
+2002-05-28 Richard Henderson <rth@redhat.com>
+
+ * cfg.c (dump_flow_info): Print bb->index, not i, for block number.
+
+ * flow.c (calculate_global_regs_live): Rename call_used to
+ invalidated_by_call. Initialize from regs_invalidated_by_call
+ instead of call_used_regs.
+
+ * varasm.c (default_binds_local_p): Check TREE_PUBLIC before
+ DECL_EXTERNAL.
+
+2002-05-28 Zack Weinberg <zack@codesourcery.com>
+
+ * tree.h: Don't include real.h.
+ Forward-declare struct realvaluetype.
+ (struct tree_real_cst): Point to the REAL_VALUE_TYPE, do not
+ contain it.
+ (TREE_REAL_CST_PTR): New accessor.
+ (TREE_REAL_CST): Update.
+ * real.h: Include machmode.h.
+ (realvaluetype): Make it struct realvaluetype, not a typedef.
+ (build_real): Prototype here.
+
+ * tree.c: Include real.h.
+ (build_real): Allocate the REAL_VALUE_TYPE as a separate
+ object in GC memory, set TREE_REAL_CST_PTR to point to it.
+ (build_real_from_int_cst): Use build_real.
+ * ggc-common.c (ggc_mark_trees): Mark TREE_REAL_CST_PTR of a
+ REAL_CST.
+
+ * builtins.c, c-common.c, c-lex.c, dwarf2out.c, expr.c,
+ fold-const.c, print-tree.c, real.c: Include real.h.
+ * Makefile.in: Update dependency lists.
+
+2002-05-28 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * basic-block.h (last_basic_block): Declare.
+ (expunge_block_nocompact): Declaration removed.
+ (compact_blocks): Declare.
+ * cfg.c (last_basic_block): New variable.
+ (expunge_block_nocompact): Removed.
+ (expunge_block): Do not compact basic blocks.
+ (compact_blocks): New.
+ * cfganal.c (flow_call_edges_add): Use the fact that bb indices no
+ longer change.
+ * cfgbuild.c (find_basic_blocks_1, find_basic_blocks): Set
+ last_basic_block.
+ * cfgcleanup.c (merge_blocks_move_predecessor_nojumps): Do not change
+ real positions of blocks.
+ (delete_unreachable_blocks): Simplified -- quadratic behavior now
+ cannot occur.
+ (cleanup_cfg): Compact blocks.
+ * cfgrtl.c (create_basic_block): Insert basic blocks to the end of
+ basic_block_info varray.
+ (flow_delete_block): Comment update.
+ (back_edge_of_syntactic_loop_p): Modify position check code.
+ (verify_flow_info): Update checking.
+ * flow.c (calculate_global_regs_live): Use FOR_EACH_BB.
+ * ifcvt.c (SET_ORIG_INDEX, ORIG_INDEX): Removed.
+ (find_if_case_1, find_if_case_2, if_convert): Use the fact that bb
+ indices no longer change.
+ * lcm.c (optimize_mode_switching): Replace n_basic_blocks with
+ last_basic_block.
+ * predict.c (estimate_bb_frequencies): Remove unneccessary code.
+ * profile.c (branch_prob): Compact blocks.
+ * sched-rgn.c (find_rgns): Replace n_basic_blocks with
+ last_basic_block.
+
+2002-05-28 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/h8300.md (two anonymous patterns): New.
+
+2002-05-28 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.md (cpu): Tidy.
+ (type): Delete 'return', add 'ialuX', 'flushw', 'iflush', and
+ 'trap'.
+ (in_call_delay): Delete reference to 'return' type.
+ (eligible_for_return_delay, in_return_delay, define_delay
+ referencing those): Delete.
+ (rest of file): Use new type attributes as appropriate.
+ * config/sparc/sparc-protos.h (eligible_for_return_delay): Delete.
+ * config/sparc/sparc.c (eligible_for_return_delay): Likewise.
+ * config/sparc/ultra1_2.md (us1_single): New reservation.
+ (us1_ialuX): Likewise.
+ * config/sparc/ultra3.md (us3_single): Likewise.
+ (us3_ialuX): Likewise.
+ (us3_imul, us3_idiv): Tweak.
+
+2002-05-28 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (alpha_in_small_data_p): Return false for
+ STRING_CST.
+
+2002-05-28 Richard Henderson <rth@redhat.com>
+
+ * config.gcc: Obsolete mn10200.
+
+2002-05-28 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppexp.c (interpret_number): Optimize for single-digit
+ and less-than-half-precision cases.
+ (num_trim, num_positive, num_div_op): Cast constants.
+
+2002-05-27 Bo Thorsen <bo@suse.de>
+
+ * config/i386/libgcc-x86_64-glibc.ver: Copy this file from the
+ 3.1 branch. The file was made by Jakub Jelinek.
+ * config/i386/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Add i386
+ support so multilib doesn't break. And don't define this at all
+ when -Dinhibit_libc is used.
+ (MULTILIB_DEFAULTS): Always set default to 64 bit compilation.
+ * config/i386/t-linux64: Implement full multilib support. Patch
+ originally done by Andreas Jaeger and Jakub Jelinek.
+
+2002-05-27 Roger Sayle <roger@eyesopen.com>
+
+ * c-common.c: Add support for __attribute__((nothrow)) to specify
+ that a function cannot throw an exception (using TREE_NOTHROW).
+ (handle_nothrow_attribute): New function to process this attribute.
+
+ * doc/extend.texi: Document the new nothrow function attribute.
+
+2002-05-27 H.J. Lu (hjl@gnu.org)
+
+ * cppexp.c (num_trim): Use 1UL instead of 1 for long int.
+ (num_positive): Likewise.
+ (num_div_op): Likewise.
+
+2002-05-27 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (c_common_init): Always use intmax_t.
+
+2002-05-27 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (c_common_init): Use intmax_t for now.
+
+2002-05-24 Andrew Haley <aph@redhat.com>
+
+ * fold-const.c (fold): Don't convert (T)(x & c) into (T)x & (T)c
+ if T is a boolean type.
+
+2002-05-27 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * basic-block.h (last_basic_block): Defined as synonym for
+ n_basic_blocks.
+ * cfganal.c (mark_dfs_back_edges, flow_reverse_top_sort_order_compute,
+ flow_depth_first_order_compute, flow_preorder_transversal_compute,
+ flow_dfs_compute_reverse_init): Replaced relevant occurences of
+ n_basic_blocks with last_basic_block.
+ * cfgbuild.c (make_edges): Likewise.
+ * cfgloop.c (flow_loop_scan, flow_loops_find): Likewise.
+ * cfgrtl.c (verify_flow_info, purge_all_dead_edges): Likewise.
+ * combine.c (combine_instructions): Likewise.
+ * df.c (df_alloc, df_analyse_1, df_analyse, iterative_dataflow_sbitmap,
+ iterative_dataflow_bitmap): Likewise.
+ * dominance.c (init_dom_info, calc_dfs_tree_nonrec, calc_dfs_tree,
+ calc_idoms, idoms_to_doms): Likewise.
+ * flow.c (update_life_info_in_dirty_blocks, free_basic_block_vars):
+ Likewise.
+ * gcse.c (gcse_main, alloc_gcse_mem, compute_local_properties,
+ compute_hash_table, expr_reaches_here_p, one_classic_gcse_pass,
+ one_cprop_pass, compute_pre_data, pre_expr_reaches_here_p,
+ one_pre_gcse_pass, compute_transpout, delete_null_pointer_checks_1,
+ delete_null_pointer_checks, compute_code_hoist_vbeinout,
+ hoist_expr_reaches_here_p, hoist_code, one_code_hoisting_pass,
+ compute_store_table, build_store_vectors): Likewise.
+ * haifa-sched.c (sched_init): Likewise.
+ * ifcvt.c (if_convert): Likewise.
+ * lcm.c (compute_antinout_edge, compute_laterin, compute_insert_delete,
+ pre_edge_lcm, compute_available, compute_nearerout,
+ compute_rev_insert_delete, pre_edge_rev_lcm, optimize_mode_switching):
+ Likewise.
+ * predict.c (estimate_probability, process_note_prediction,
+ note_prediction_to_br_prob): Likewise.
+ * profile.c (GCOV_INDEX_TO_BB, BB_TO_GCOV_INDEX): Likewise.
+ * recog.c (split_all_insns, peephole2_optimize): Likewise.
+ * regrename.c (copyprop_hardreg_forward): Likewise.
+ * resource.c (init_resource_info): Likewise.
+ * sched-rgn.c (build_control_flow, find_rgns, compute_trg_info,
+ init_regions, schedule_insns): Likewise.
+ * ssa-ccp.c (ssa_const_prop): Likewise.
+ * ssa-dce.c (ssa_eliminate_dead_code): Likewise.
+ * ssa.c (compute_dominance_frontiers,
+ compute_iterated_dominance_frontiers, convert_to_ssa): Likewise.
+
+ * df.c (df_refs_unlink): Fix FOR_EACH_BB usage (in #if 0'ed code)
+ * gcse.c (alloc_rd_mem, alloc_avail_expr_mem): Use n_blocks for vector
+ sizes consistently.
+
+Mon May 27 14:28:12 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * basic-block.h (can_hoist_p, hoist_insn_after, hoist_insn_to_edge):
+ new.
+ * rtlanal.c (hoist_test_store, can_hoist_insn_p, hoist_update_store,
+ hoist_insn_after, hoist_insn_to_edge): New.
+
+Mon May 27 12:14:02 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * basic-block.h (PEOP_SCAN_DEAD_STORES): New.
+ (PROP_FINAL): Include.
+ * flow.c (life_analysis, update_life_info,
+ init_propagate_block_info, mark_set_1, mark_used_rgs):
+ Support SCAN_DEAD_STORE.
+
+2002-05-27 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (c_common_init): Set CPP arithmetic precision.
+ * cppexp.c (cpp_num_part): Move typedef ...
+ * cpphash.h: ...here; make unsigned HOST_WIDE_INT.
+ * cppinit.c (cpp_create_reader): Default to host long arithmetic.
+ (sanity_checks): Update.
+
+2002-05-26 Geoffrey Keating <geoffk@redhat.com>
+
+ * Makefile.in (INSTALL_HEADERS): Add 'install-mkheaders'.
+ (mkheaders): New rule.
+ (install-mkheaders): New rule.
+ * configure.in (all_outputs): Add mkheaders.
+ * configure: Regenerate.
+ * mkheaders.in: New file.
+
+2002-05-26 Jakub Jelinek <jakub@redhat.com>
+
+ * cse.c (fold_rtx): Don't optimize if SUBREG changes mode class.
+
+2002-05-26 Andreas Jaeger <aj@suse.de>
+
+ * cfg.c (dump_flow_info): Remove extra argument to fprintf.
+
+2002-05-26 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppexp.c (possible_sum_sign, integer_overflow, left_shift,
+ right_shift): Remove.
+ (cpp_num, cpp_num_part, PART_PRECISION, HALF_MASK, LOW_PART,
+ HIGH_PART): New.
+ (struct op): Use cpp_num.
+ (num_zerop, num_eq, num_positive, num_greater_freq, num_trim,
+ num_part_mul, num_unary_op, num_binary_op, num_negate,
+ num_bitwise_op, num_inequality_op, num_equality_op, num_mul,
+ num_div_op, num_lshift, num_rshift, append_digit): New.
+ (interpret_number, parse_defined, eval_token, reduce): Update
+ for two-integer arithmetic.
+ (binary_handler): New typedef.
+ (optab): Update.
+ (COMPARE, EQUALITY, BITWISE, MINMAX, UNARY, SHIFT): Delete.
+ (_cpp_parse_expr, reduce): Update to handle two-integers.
+ * cpplib.c (_cpp_test_assertion): Back up on CPP_EOF.
+
+2002-05-26 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr-protos.h (avr_out_sbxx_branch): Declare.
+ * config/avr/avr.c (jump_over_one_insn_p): Take length of the
+ branch insn into account, do not assume 1.
+ (avr_out_sbxx_branch): New function. Optimize cases of skipping
+ over single word insn. Handle upper half of I/O space too.
+ * config/avr/avr.md (*sbrx_branch): Use it.
+ (*sbrx_and_branchhi, *sbrx_and_branchsi): Likewise.
+ (*sbix_branch, *sbix_branch_bit7): Likewise.
+ (*sbix_branch_tmp, *sbix_branch_tmp_bit7): New.
+ Use RTL peepholes to optimize register operand sign tests.
+
+2002-05-26 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (avr_asm_only_p): New variable.
+ (avr_override_options): Set it here if AVR1.
+ (asm_file_start): Test it here, report an error if set.
+
+2002-05-26 Kazu Hirata <kazu@cs.umass.edu>
+
+ * alias.c: Fix formatting.
+ * attribs.c: Likewise.
+ * bb-reorder.c: Likewise.
+ * bitmap.c: Likewise.
+ * bitmap.h: Likewise.
+ * builtins.c: Likewise.
+
+Sun May 26 14:00:44 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * reload.c (find_valid_class): Accept new argument DEST,
+ choose class accordingly.
+ (push_reload): Update callers.
+
+2002-05-26 Andreas Jaeger <aj@suse.de>
+
+ * combine.c (combine_instructions): Do not indent #if for
+ traditional C.
+
+2002-05-25 Richard Henderson <rth@redhat.com>
+
+ * c-pragma.c (apply_pragma_weak): Convert value identifier to
+ string for decl_attributes.
+ (handle_pragma_weak): Call assemble_alias if we're modifying
+ an existing decl.
+
+2002-05-25 Richard Henderson <rth@redhat.com>
+
+ PR target/6788
+ * config/sparc/sparc.c (sparc_output_mi_thunk): New implementation
+ using rtl instead of fprintf.
+ * config/sparc/sparc.h (ASM_OUTPUT_MI_THUNK): Use it.
+ * config/sparc/sparc-protos.h: Update.
+
+2002-05-25 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in (C_COMMON_H): Fix.
+ Update other targets.
+ * c-common.c: Don't include c-lex.h.
+ (builtin_define_with_value): Make static and prototype.
+ (builtin_define_std): Move from c-lex.h.
+ * c-common.h (init_c_lex): Move from c-lex.h.
+ * c-decl.c: Don't include c-lex.h.
+ (make_pointer_declarator): Move from c-parse.in.
+ * c-lex.c: Don't include c-lex.h.
+ * c-lex.h: Remove.
+ * c-parse.in: Don't include c-lex.h; include c-pragma.h.
+ (make_pointer_declarator): Move to c-decl.c.
+ * c-pragma.c: Don't include c-lex.h.
+ * c-pragma.h (yydebug, YYDEBUG, parse_in, c_lex): Move from c-lex.h.
+ * c-tree.h (make_pointer_declarator): New.
+doc:
+ * passes.texi, tm.texi: Update.
+objc:
+ * Make-lang.in: Update and correct.
+ * objc-act.c: Don't include c-lex.h or cpplib.h.
+treelang:
+ * treetree.c: Don't include c-lex.h.
+config:
+ * darwin-c.c: Don't include c-lex.h.
+ * c4x/c4x-c.c: Don't include c-lex.h.
+ * c4x/t-c4x: Update.
+ * i370/i370-c.c: Don't include c-lex.h.
+ * i370/t-i370: Update.
+ * i960/i960-c.c: Don't include c-lex.h.
+ * i960/i960.c: Don't include cpplib.h, c-lex.h or c-pragma.h.
+ * i960/t-960bare: Update.
+ * i960/t-vxworks: Update.
+ * rs6000/rs6000-c.c: Don't include c-lex.h; include c-pragma.h.
+ * rs6000/t-darwin: Update.
+ * rs6000/t-rs6000-c-rule: Update.
+ * v850/v850-c.c: Don't include c-lex.h.
+ * v850/v850.c: Don't include c-lex.h or cpplib.h.
+
+
+2002-05-25 Kazu Hirata <kazu@cs.umass.edu>
+
+ * tree.def: Fix typos.
+ * doc/install.texi: Likewise.
+
+2002-05-25 Richard Henderson <rth@redhat.com>
+
+ * configure.in (HAVE_AS_TLS): Add ia64 test.
+ * configure: Rebuild.
+ * config/ia64/ia64.c (ia64_tls_size_string, ia64_tls_size): New.
+ (override_options): Set it.
+ (TARGET_HAVE_TLS): New.
+ (sdata_symbolic_operand): Look for 's'.
+ (tls_symbolic_operand): New.
+ (ia64_expand_load_address): Abort for tls symbols.
+ (gen_tls_get_addr): New.
+ (gen_thread_pointer): New.
+ (ia64_expand_move): Split out from movdi. Handle tls symbols.
+ (rtx_needs_barrier): Add new unspecs.
+ (ia64_encode_section_info): Handle tls symbols.
+ (ia64_strip_name_encoding): Strip two encoding chars.
+ * config/ia64/ia64.h (ia64_tls_size, ia64_tls_size_string): New.
+ (TARGET_TLS14, TARGET_TLS22, TARGET_TLS64): New.
+ (TARGET_OPTIONS): Add tls-size.
+ (ENCODE_SECTION_INFO_CHAR): Rename from SDATA_NAME_FLAG_CHAR.
+ * config/ia64/ia64.md (UNSPEC_LTOFF_DTPMOD, UNSPEC_LTOFF_DTPREL,
+ UNSPEC_DTPREL, UNSPEC_LTOFF_TPREL, UNSPEC_TPREL, UNSPEC_LD_BASE): New.
+ (movqi, movhi, movsi, movdi, movti): Use ia64_expand_move.
+ (movsf, movdf): Likewise.
+ (movdi_symbolic): Use match_scratch. Don't split if we won't
+ have a scratch availiable.
+ (load_ltoff_dtpmod, load_dtprel, load_dtprel64, load_dtprel22,
+ add_dtprel, add_dtprel14, add_dtprel22, load_ltoff_tprel, load_tprel,
+ load_tprel64, load_tprel22, add_tprel, add_tprel14, add_tprel22): New.
+ * config/ia64/ia64-protos.h: Update.
+ * config/ia64/sysv4.h (ASM_OUTPUT_ALIGNED_DECL_LOCAL): Use
+ sdata_symbolic_operand.
+ (ASM_OUTPUT_LABELREF): Strip two characters.
+
+2002-05-25 Kazu Hirata <kazu@cs.umass.edu>
+
+ * combine.c (simplify_set): Remove an unnecessary subreg.
+
+2002-05-25 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (avr_handle_progmem_attribute): Handle TYPE_DECL.
+
+ * config/avr/avr.h (BSS_SECTION_ASM_OP, ASM_OUTPUT_BSS): New.
+
+2002-05-25 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * toplev.c (output_clean_symbol_name): Fix another thinko. Gosh.
+
+2002-05-25 Roger Sayle <roger@eyesopen.com>
+
+ * simplify-rtx.c (simplify_gen_relational): Simplify the RTX
+ (cond (compare x y) 0) into the equivalent (cond x y).
+
+2002-05-25 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * toplev.c (output_clean_symbol_name): Use xstrdup. Fix thinko.
+
+2002-05-24 Zack Weinberg <zack@codesourcery.com>
+
+ * config.gcc: Remove all stanzas for previously obsoleted
+ systems. Where necessary, add explicit error stanzas to
+ prevent removed systems from being misidentified as something
+ else. Begin a fresh obsoletions list, with the systems that
+ were reprieved last round.
+ * doc/install.texi: Remove all mention of dead targets.
+ * fixinc/mkfixinc.sh: Likewise.
+
+ * config/arm/arm.h: Bit 31 of target_flags is no longer
+ reserved.
+
+ * config/1750a/1750a-protos.h, config/1750a/1750a.c,
+ config/1750a/1750a.h, config/1750a/1750a.md, config/1750a/ms1750.inc,
+ config/a29k/a29k-protos.h, config/a29k/a29k.c, config/a29k/a29k.h,
+ config/a29k/a29k.md, config/a29k/rtems.h, config/a29k/t-a29kbare,
+ config/a29k/t-vx29k, config/a29k/unix.h, config/a29k/vx29k.h,
+ config/alpha/osf12.h, config/alpha/osf2or3.h,
+ config/arm/arm-wince-pe.h, config/arm/arm.h, config/arm/riscix.h,
+ config/arm/riscix1-1.h, config/arm/rix-gas.h, config/arm/t-riscix,
+ config/clipper/clipper-protos.h, config/clipper/clipper.c,
+ config/clipper/clipper.h, config/clipper/clipper.md,
+ config/clipper/clix.h, config/convex/convex-protos.h,
+ config/convex/convex.c, config/convex/convex.h,
+ config/convex/convex.md, config/convex/fixinc.convex,
+ config/convex/proto.h, config/elxsi/elxsi-protos.h,
+ config/elxsi/elxsi.c, config/elxsi/elxsi.h, config/elxsi/elxsi.md,
+ config/i386/386bsd.h, config/i386/aix386.h, config/i386/aix386ng.h,
+ config/i386/bsd386.h, config/i386/dgux.h, config/i386/djgpp-rtems.h,
+ config/i386/isc.h, config/i386/iscdbx.h, config/i386/linux-oldld.h,
+ config/i386/next.h, config/i386/osf1-ci.asm, config/i386/osf1-cn.asm,
+ config/i386/osf1elf.h, config/i386/osf1elfgdb.h, config/i386/osfelf.h,
+ config/i386/osfrose.h, config/i386/rtems.h, config/i386/seq-gas.h,
+ config/i386/seq-sysv3.h, config/i386/seq2-sysv3.h,
+ config/i386/sequent.h, config/i386/sun.h, config/i386/sun386.h,
+ config/i386/t-dgux, config/i386/t-next, config/i386/t-osf,
+ config/i386/t-osf1elf, config/i860/bsd-gas.h, config/i860/bsd.h,
+ config/i860/fx2800.h, config/i860/i860-protos.h, config/i860/i860.c,
+ config/i860/i860.h, config/i860/i860.md, config/i860/mach.h,
+ config/i860/paragon.h, config/i860/sysv3.h, config/i860/sysv4.h,
+ config/i860/t-fx2800, config/i860/varargs.asm, config/m68k/a-ux.h,
+ config/m68k/altos3068.h, config/m68k/apollo68.h,
+ config/m68k/aux-crt1.c, config/m68k/aux-crt2.asm,
+ config/m68k/aux-crtn.asm, config/m68k/aux-exit.c,
+ config/m68k/aux-low.gld, config/m68k/aux-mcount.c,
+ config/m68k/auxas.h, config/m68k/auxgas.h, config/m68k/auxgld.h,
+ config/m68k/auxld.h, config/m68k/ctix.h, config/m68k/dpx2.h,
+ config/m68k/dpx2.ifile, config/m68k/dpx2cdbx.h, config/m68k/dpx2g.h,
+ config/m68k/isi-nfp.h, config/m68k/isi.h, config/m68k/lynx-ng.h,
+ config/m68k/lynx.h, config/m68k/math-3300.h, config/m68k/news.h,
+ config/m68k/news3.h, config/m68k/news3gas.h, config/m68k/newsgas.h,
+ config/m68k/next.h, config/m68k/next21.h, config/m68k/rtems.h,
+ config/m68k/t-aux, config/m68k/t-lynx, config/m68k/t-next,
+ config/m68k/x-next, config/m88k/dgux.h, config/m88k/dgux.ld,
+ config/m88k/dguxbcs.h, config/m88k/dolph.h, config/m88k/dolphin.ld,
+ config/m88k/luna.h, config/m88k/m88k-coff.h, config/m88k/sysv3.h,
+ config/m88k/t-bug, config/m88k/t-dgux, config/m88k/t-dgux-gas,
+ config/m88k/t-dguxbcs, config/m88k/t-dolph, config/m88k/t-m88k-gas,
+ config/m88k/t-tekXD88, config/m88k/tekXD88.h, config/m88k/tekXD88.ld,
+ config/mips/bsd-4.h, config/mips/bsd-5.h, config/mips/dec-bsd.h,
+ config/mips/dec-osf1.h, config/mips/elflorion.h,
+ config/mips/iris4loser.h, config/mips/mips-5.h, config/mips/news4.h,
+ config/mips/news5.h, config/mips/nws3250v4.h, config/mips/osfrose.h,
+ config/mips/svr3-4.h, config/mips/svr3-5.h, config/mips/svr4-4.h,
+ config/mips/svr4-5.h, config/mips/svr4-t.h, config/mips/t-bsd,
+ config/mips/t-bsd-gas, config/mips/t-svr3, config/mips/t-svr3-gas,
+ config/mips/t-svr4, config/mips/t-svr4-gas, config/mips/t-ultrix,
+ config/mips/ultrix.h, config/nextstep-protos.h, config/nextstep.c,
+ config/nextstep.h, config/nextstep21.h, config/ns32k/encore.h,
+ config/ns32k/merlin.h, config/ns32k/pc532-mach.h,
+ config/ns32k/pc532-min.h, config/ns32k/pc532.h,
+ config/ns32k/sequent.h, config/ns32k/tek6000.h,
+ config/ns32k/tek6100.h, config/ns32k/tek6200.h, config/pj/lib1funcs.S,
+ config/pj/linux.h, config/pj/pj-protos.h, config/pj/pj.c,
+ config/pj/pj.h, config/pj/pj.md, config/pj/pjl.h, config/pj/t-pj,
+ config/sparc/rtems.h, config/we32k/we32k-protos.h,
+ config/we32k/we32k.c, config/we32k/we32k.h, config/we32k/we32k.md:
+ Delete file.
+
+2002-05-24 Richard Henderson <rth@redhat.com>
+
+ * flags.h (TLS_MODEL_GLOBAL_DYNAMIC): Set to 1.
+ * toplev.c (flag_tls_default) Set to TLS_MODEL_GLOBAL_DYNAMIC.
+ * config/i386/i386.c (tls_model_chars): Add leading space.
+ (tls_symbolic_operand): Don't bias by 1.
+ (legitimize_address): Don't unbias by 1.
+
+2002-05-24 Toshiyasu Morita <toshiyasu.morita@hsa.hitachi.com>
+
+ * lcm.c (optimize_mode_switching): Change bb used as indices
+ to bb->index.
+
+2002-05-24 Richard Henderson <rth@redhat.com>
+
+ * config/ia64/ia64.c (ia64_reorg): Use update_life_info instead
+ of update_life_info_in_dirty_blocks.
+
+2002-05-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/6782
+ * final.c (get_mem_expr_from_op): Return 0 if op is NULL.
+
+2002-05-24 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ PR preprocessor/6780
+ * cppmacro.c (enter_macro_context): Clear state.angled_headers.
+
+2002-05-24 Jim Blandy <jimb@redhat.com>
+
+ * dwarf2out.c (dwarf2out_finish): Don't forget to emit a final
+ entry with a type code of zero, marking the end of the compilation
+ unit's macro info.
+
+2002-05-24 Richard Henderson <rth@redhat.com>
+
+ * varasm.c (asm_output_bss): Always output one byte.
+ * config/alpha/elf.h (ASM_OUTPUT_ALIGNED_LOCAL): Likewise.
+
+2002-05-24 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
+
+ * tree.c (decl_type_context): Return NULL_TREE if decl's context is a
+ namespace.
+
+2002-05-24 Andreas Jaeger <aj@suse.de>
+
+ * ggc-page.c (alloc_page): Cast variables of type size_t to
+ unsigned long, adjust printf format string.
+ (ggc_alloc): Likewise.
+ (ggc_print_statistics): Likewise.
+ (ggc_print_statistics): Correct printf format string for SCALE to
+ use unsigned long.
+
+2002-05-24 Danny Smith <dannysmith@users.sourceforge.net>
+
+ * config/i386/mingw32.h (CPP_SPEC): Remove -remap.
+
+2002-05-23 Gabriel Dos Reis <gdr@codesourcery.com>
+ Zack Weinberg <zack@codesourcery.com>
+
+ * config/i386/mingw32.h (OUTPUT_QUOTED_STRING): Properly output
+ quoted strings.
+ * dwarf2out.c (lookup_filename): Properly quote filename in .file
+ directive in assembly file.
+ * config/m68k/dpx2.h (ASM_OUTPUT_SOURCE_FILENAME): Likewise.
+ * config/m88k/m88k.h (ASM_OUTPUT_SOURCE_FILENAME): Likewise.
+ * config/pj/pj.h (ASM_FILE_START): Likewise.
+ * config/rs6000/xcoff.h (ASM_FILE_START): Likewise.
+ * config/avr/avr.c (asm_file_end): Likewise.
+ * toplev.c (output_quoted_string): Handle possibly signed plain
+ char.
+ * toplev.h (output_clean_symbol_name): Declare
+ * toplev.c (output_clean_symbol_name): Define.
+ * config/alpha/alpha.c (unicosmk_output_module_name): Use it.
+ * config/1750a/1750a.h (ASM_FILE_START): Likewise.
+
+2002-05-24 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.c (output_toc): Mask longs to 32 bits.
+
+2002-05-23 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (reserv_sets_hash_value): Use shift equal to 3/4
+ of size of unsigned.
+
+2002-05-23 Richard Henderson <rth@redhat.com>
+
+ * configure.in (HAVE_AS_TLS): New test.
+ * config.in, configure: Rebuild.
+ * config/i386/i386.c (TARGET_HAVE_TLS): Set if HAVE_AS_TLS.
+ (ix86_tls_dialect_string, ix86_tls_dialect): New.
+ (override_options): Set it.
+ (tls_model_chars, tls_symbolic_operand): New.
+ (tls_symbolic_operand_1, global_dynamic_symbolic_operand): New.
+ (local_dynamic_symbolic_operand, initial_exec_symbolic_operand): New.
+ (local_exec_symbolic_operand): New.
+ (get_pic_label_name): Merge into output_set_got.
+ (ix86_asm_file_end): Emit pic_label_name if defined.
+ (legitimate_constant_p, constant_address_p): New.
+ (legitimate_pic_operand_p): New.
+ (legitimate_pic_address_disp_p): Handle GOTTPOFF, NTPOFF, DTPOFF.
+ (legitimate_address_p): Likewise.
+ (ix86_encode_section_info): Rename from i386_; handle tls decls.
+ (ix86_strip_name_encoding): New.
+ (get_thread_pointer): New.
+ (legitimize_address): Handle tls symbols.
+ (output_pic_addr_const): Handle GOTTPOFF, TPOFF, NTPOFF, DTPOFF.
+ Remove UNSPEC_PLT.
+ (struct machine_function): Add some_ld_name.
+ (get_some_local_dynamic_name, get_some_local_dynamic_name_1): Set it.
+ (print_operand) [&]: Use it. Handle UNSPEC_TP.
+ (output_addr_const_extra): New.
+ (maybe_get_pool_constant): New.
+ (ix86_split_to_parts): Use it.
+ (ix86_expand_move): Handle tls symbols.
+ (ix86_tls_get_addr): New.
+ * config/i386/i386.h (TARGET_GNU_TLS, TARGET_SUN_TLS): New.
+ (TARGET_OPTIONS): Add tls-dialect.
+ (CONSTANT_ADDRESS_P): Use new out-of-line function.
+ (LEGITIMATE_CONSTANT_P): Likewise.
+ (LEGITIMATE_PIC_OPERAND_P): Likewise.
+ (TARGET_STRIP_NAME_ENCODING): New.
+ (ASM_OUTPUT_LABELREF): New.
+ (PRINT_OPERAND_PUNCT_VALID_P): Add '&'.
+ (OUTPUT_ADDR_CONST_EXTRA): New.
+ (PREDICATE_CODES): Update.
+ (ix86_tls_dialect, ix86_tls_dialect_string): New.
+ * config/i386/i386.md: Regroup and renumber unspec constants.
+ (tls_global_dynamic_gnu, tls_global_dynamic_sun): New.
+ (tls_local_dynamic_base_gnu, tls_local_dynamic_base_sun): New.
+ (tls_global_dynamic, tls_local_dynamic_base): New.
+ (tls_local_dynamic_once): New.
+ * config/i386/i386-protos.h: Update.
+
+2002-05-23 Richard Henderson <rth@redhat.com>
+
+ * genemit.c (gen_insn): Print file:lineno comment before function.
+ (main): likewise.
+ * gensupport.c (struct queue_elem): Add filename member.
+ (queue_pattern): Initialize it; update all callers.
+ (process_include): Don't free filename.
+ (read_md_rtx): Set read_rtx_filename.
+
+2002-05-23 Hans Boehm <Hans_Boehm@hp.com>
+
+ * config/ia64/linux.h (IA64_GATE_AREA_END): Adjust for 64K pages.
+
+2002-05-23 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (output_set_got): Fix typo in pic no-deep case.
+
+2002-05-23 Richard Henderson <rth@redhat.com>
+
+ * doc/extend.texi (C++98 Thread-Local Edits): Update with
+ commentary from Mark.
+
+2002-05-23 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * bb-reorder.c (make_reorder_chain, make_reorder_chain_1):
+ Use FOR_EACH_BB macros to iterate over basic block chain.
+ * cfg.c (clear_edges, clear_bb_flags, dump_flow_info,
+ alloc_aux_for_blocks, clear_aux_for_blocks, alloc_aux_for_edges):
+ Likewise.
+ * cfganal.c (set_edge_can_fallthru_flag, flow_call_edges_add,
+ find_unreachable_blocks, create_edge_list, verify_edge_list,
+ remove_fake_edges, add_noreturn_fake_exit_edges,
+ flow_preorder_transversal_compute, flow_dfs_compute_reverse_execute):
+ Likewise.
+ * cfgbuild.c (make_edges, find_basic_blocks, find_many_sub_basic_blocks,
+ find_sub_basic_blocks): Likewise.
+ * cfgcleanup.c (try_optimize_cfg, delete_unreachable_blocks):
+ Likewise.
+ * cfglayout.c (record_effective_endpoints, cleanup_unconditional_jumps):
+ Likewise.
+ * cfgloop.c (flow_loops_cfg_dump, flow_loops_find):
+ Likewise.
+ * cfgrtl.c (compute_bb_for_insn, tidy_fallthru_edges,
+ commit_edge_insertions, commit_edge_insertions_watch_calls,
+ print_rtl_with_bb, verify_flow_info, purge_all_dead_edges): Likewise.
+ * combine.c (combine_instructions, reg_dead_at_p): Likewise.
+ * conflict.c (conflict_graph_compute): Likewise.
+ * df.c (df_bitmaps_alloc, df_bitmaps_free, df_alloc, df_analyse_1,
+ df_modified_p, df_refs_unlink, df_dump): Likewise.
+ * dominance.c (calc_dfs_tree, calculate_dominance_info): Likewise.
+ * final.c (compute_alignments): Likewise.
+ * flow.c (update_life_info, update_life_info_in_dirty_blocks,
+ delete_noop_moves, calculate_global_regs_live, allocate_bb_life_data,
+ count_or_remove_death_notes): Likewise.
+ * gcse.c (oprs_unchanged_p, record_last_reg_set_info,
+ compute_hash_table, compute_kill_rd, compute_rd, compute_ae_kill,
+ classic_gcse, compute_transp, cprop, compute_pre_data,
+ compute_transpout, invalidate_nonnull_info,
+ delete_null_pointer_checks_1, delete_null_pointer_checks,
+ compute_code_hoist_vbeinout, hoist_code, compute_ld_motion_mems,
+ compute_store_table, build_store_vectors, store_motion): Likewise.
+ * global.c (global_conflicts, mark_elimination): Likewise.
+ * graph.c (print_rtl_graph_with_bb): Likewise.
+ * haifa-sched.c (sched_init): Likewise.
+ * ifcvt.c (if_convert): Likewise.
+ * lcm.c (compute_antinout_edge, compute_laterin, compute_insert_delete,
+ compute_available, compute_nearerout, compute_rev_insert_delete,
+ optimize_mode_switching): Likewise.
+ * local-alloc.c (local_alloc, update_equiv_regs): Likewise.
+ * predict.c (estimate_probability, note_prediction_to_br_prob,
+ propagate_freq, counts_to_freqs, expensive_function_p,
+ estimate_bb_frequencies): Likewise.
+ * profile.c (instrument_edges, get_exec_counts,
+ compute_branch_probabilities, compute_checksum, branch_prob,
+ find_spanning_tree): Likewise.
+ * recog.c (split_all_insns, peephole2_optimize): Likewise.
+ * reg-stack.c (reg_to_stack, convert_regs_entry, convert_regs):
+ Likewise.
+ * regclass.c (scan_one_insn, regclass): Likewise.
+ * regmove.c (mark_flags_life_zones, regmove_optimize,
+ record_stack_memrefs): Likewise.
+ * regrename.c (regrename_optimize, copyprop_hardreg_forward): Likewise.
+ * reload1.c (reload, reload_combine, fixup_abnormal_edges): Likewise.
+ * resource.c (find_basic_block): Likewise.
+ * sched-ebb.c (schedule_ebbs): Likewise.
+ * sched-rgn.c (is_cfg_nonregular, build_control_flow,
+ find_single_block_region, find_rgns, schedule_insns)
+ * sibcall.c (optimize_sibling_and_tail_recursive_call)
+ * ssa-ccp.c (optimize_unexecutable_edges,
+ ssa_ccp_df_delete_unreachable_insns): Likewise.
+ * ssa-dce.c (ssa_eliminate_dead_code): Likewise.
+ * ssa.c (find_evaluations, compute_dominance_frontiers_1,
+ rename_block, convert_to_ssa, compute_conservative_reg_partition,
+ compute_coalesced_reg_partition, rename_equivalent_regs,
+ convert_from_ssa): Likewise.
+ * config/ia64/ia64.c (emit_predicate_relation_info, process_epilogue,
+ process_for_unwind_directive): Likewise.
+
+ * df.c (FOR_ALL_BBS): Removed.
+ * gcse.c (struct null_pointer_info): Type of current_block field
+ changed.
+ (struct reg_avail_info): Type of last_bb field changed.
+ * config/ia64/ia64.c (block_num): Removed.
+ (need_copy_state): Type changed.
+ (last_block): New.
+
+2002-05-23 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppinit.c (mark_named_operators): Split out from init_builtins.
+ (cpp_finish_options): Call it from here instead.
+
+2002-05-23 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * builtin-attrs.def: Update copyright years.
+ (ATTR_NONNULL): New attribute identifier.
+ (ATTR_NONNULL_1, ATTR_NONNULL_2, ATTR_NONNULL_3): New
+ attribute tree lists.
+ (DEF_FORMAT_ATTRIBUTE): Chain a nonnull attribute for the
+ format operand.
+ (ATTR_FORMAT_ARG_1, ATTR_FORMAT_ARG_2): Use...
+ (DEF_FORMAT_ARG_ATTRIBUTE): ...this to generate format_arg
+ attribute lists. Chain the appropriate nonnull attribute.
+ * c-format.c (check_format_arg): Remove null format string
+ warning.
+ * testsuite/gcc.dg/format/null-1.c: New test.
+
+2002-05-23 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * Makefile.in (ADAC): Define.
+ (SYSLIBS): Define.
+ (.SUFFIXES): Move before language makefile fragments.
+ (STAGE2_FLAGS_TO_PASS): Use stage CC as ADAC.
+
+2002-05-23 Mark Mitchell <mark@codesourcery.com>
+
+ * varasm.c (make_decl_rtl): Don't allow weak variables to be
+ placed in common.
+
+Thu May 23 19:43:41 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfg.c (dump_flow_info): Print results of
+ maybe_hot/probably_never_executed predicates.
+ * toplev.c (open_dump_file): Print function frequency.
+
+2002-05-23 David S. Miller <davem@redhat.com>
+
+ * cse.c (approx_reg_cost_1, approx_reg_cost): Recode to not use
+ regsets.
+
+2002-05-23 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * c-common.c (warn_nonnull): Declare.
+ (c_common_attribute_table): Add "nonnull" attribute.
+ (handle_nonnull_attribute, check_function_nonnull, nonnull_check_p,
+ check_nonnull_arg, get_nonnull_operand, check_function_arguments,
+ check_function_arguments_recurse): New functions.
+ * c-common.h (warn_nonnull): Declare extern.
+ (check_function_arguments, check_function_arguments_recurse): New
+ prototypes.
+ * c-decl.c (c_decode_option): Add -Wnonnull option.
+ * c-format.c (set_Wformat): Set warn_nonnull if enabling
+ format checking.
+ (format_check_context): New structure.
+ (check_format_info_recurse): Remove recursion and rename to...
+ (check_format_arg): ...this. Update comment.
+ (check_format_info): Use check_function_arguments_recurse.
+ * c-typeck.c (build_function_call): Call check_function_arguments
+ instead of check_function_format.
+ * doc/extend.texi: Document "nonnull" attribute.
+ * doc/invoke.texi: Docuemnt -Wnonnull option.
+ * testsuite/gcc.dg/nonnull-1.c: New test.
+ * testsuite/gcc.dg/nonnull-2.c: New test.
+
+2002-05-23 David S. Miller <davem@redhat.com>
+
+ * basic-block.h (CLEANUP_NO_INSN_DEL): Define it.
+ * cfgcleanup.c (cleanup_cfg): If it is set do not
+ attempt to delete trivially dead insns.
+ * except.c (finish_eh_generation): Pass it to cleanup_cfg.
+ * toplev.c (rest_of_compilation): Document non-trivial aspect
+ the RTL before optimize_save_area_alloca is run.
+
+2002-05-23 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-lex.c (indent_level): Remove.
+ (cb_file_change, c_lex): Remove indent level handling.
+ * c-lex.h (indent_level): Remove.
+ * input.h (struct file_stack): Remove indent_level.
+ * toplev.c (push_srcloc): Remove indent_level handling.
+
+2002-05-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/6753
+ * config/i386/i386.md (sse_movdfcc, sse_movdfcc_eq): Use Y instead
+ of x in constraints for clarity.
+ (sse_mov?fcc split): abort if op2 == op3.
+ (sse_movsfcc_const0_1, sse_movsfcc_const0_2, sse_movsfcc_const0_3,
+ sse_movsfcc_const0_4): Add earlyclobber.
+ (sse_movdfcc_const0_1, sse_movdfcc_const0_2, sse_movdfcc_const0_3,
+ sse_movdfcc_const0_4): Likewise. Use DFmode, not SFmode.
+ Use Y instead of x in constraints.
+
+2002-05-23 Richard Henderson <rth@redhat.com>
+
+ * doc/extend.texi (C99 Thread-Local Edits): New subsection.
+ (C++98 Thread-Local Edits): New subsection.
+
+ * config/i386/i386.c, config/i386/i386.h: Tidy comments and whitespace.
+ (ix86_arch): Set type to enum processor_type.
+
+ * config/i386/i386.md (movsi_1, movdi_1_rex64): Use
+ LEGITIMATE_PIC_OPERAND_P not SYMBOLIC_CONST.
+
+2002-05-23 Jakub Jelinek <jakub@redhat.com>
+
+ * configure.in: Fix as version test for binutils 2.12.1 releases
+ (without dates).
+ * configure: Rebuilt.
+
+2002-05-23 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (get_pic_label_name): New.
+ (load_pic_register): Remove.
+ (output_set_got): New.
+ (ix86_expand_prologue): Use gen_set_got; mark insn REG_MAYBE_DEAD.
+ * config/i386/i386.md (UNSPEC_SET_GOT): New.
+ (UNSPECV_PROLOGUE_SET_GOT, UNSPECV_PROLOGUE_GET_PC): Remove.
+ (prologue_set_got, prologue_get_pc): Remove.
+ (set_got, set_got_nopic, set_got_deep, set_got_nodeep): New.
+ (builtin_setjmp_receiver): Use gen_set_got.
+ * config/i386/i386-protos.h: Update.
+
+Thu May 23 09:22:23 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * gcse.c (hash_expr): Do not use alias set for hashing.
+
+2002-05-22 Kevin Buettner <kevinb@redhat.com>
+
+ * dbxout.c (dbxout_class_name_qualifiers): New function.
+ (dbxout_symbol): Output class/struct qualifiers for a .stabs entry.
+
+2002-05-23 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpperror.c (_cpp_begin_message): No special casing
+ of CPP_FATAL_LIMIT.
+ * cppinit.c (sanity_checks): s/DL_FATAL/DL_ICE/.
+ (output_deps, cpp_handle_option, cpp_post_options): Use DL_ERROR.
+ * cpplib.c (do_include_common): Use DL_ERROR.
+ * cpplib.h (CPP_FATAL_LIMIT, CPP_FATAL_ERRORS, DL_FATAL): Remove.
+ (DL_ICE): Renumber.
+ * fix-header.c (read_scan_file): Update.
+
+2002-05-22 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (ix86_expand_call): New function, extracted
+ from md call patterns. Add pic_offset_table_rtx to
+ CALL_INSN_FUNCTION_USAGE when needed.
+ * config/i386/i386.md (call_pop, call): Use ix86_expand_call.
+ (call_value_pop, call_value, untyped_call): Likewise.
+ (call_exp, call_value_exp): Remove.
+ * config/i386/i386-protos.h: Update.
+
+2002-05-22 Richard Henderson <rth@redhat.com>
+
+ * varasm.c (default_section_type_flags): Check for VAR_DECL
+ before using DECL_THREAD_LOCAL.
+
+2002-05-22 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/aix43.h (LINK_SPEC): Add PE initializer.
+ (STARTFILE_SPEC): Delete PE crt0.o.
+ * config/rs6000/aix51.h: Same.
+ * config/rs6000/rs6000.c: Use TARGET_XCOFF, not OBJECT_FORMAT_COFF.
+ * config/rs6000/rs6000.h (ASM_WEAKEN_DECL): Append [DS] to
+ function descriptor symbol. Use RS6000_OUTPUT_BASENAME.
+ (ASM_OUTPUT_DEF_FROM_DECLS): Use RS6000_OUTPUT_BASENAME.
+ * config/rs6000/xcoff.h (ASM_OUTPUT_DEF): Define.
+
+2002-05-22 Richard Henderson <rth@redhat.com>
+
+ * varasm.c (default_section_type_flags): Handle tls data and
+ default sections.
+ (default_unique_section): Handle tls sections.
+
+2002-05-23 Alan Modra <amodra@bigpond.net.au>
+
+ * configure.in (CROSS): Define NATIVE_CROSS.
+ * configure: Regenerate.
+ * gcc.c (STARTFILE_PREFIX_SPEC): Define.
+ (startfile_prefix_spec): New var.
+ (static_specs): Add startfile_prefix_spec.
+ (do_spec_2): Split out from..
+ (do_spec): ..here.
+ (main): Process startfile_prefix_spec.
+ * config/rs6000/linux64.h (LINK_OS_LINUX_SPEC) Change name of
+ dynamic linker.
+ (STARTFILE_PREFIX_SPEC): Define.
+ (STARTFILE_LINUX_SPEC, ENDFILE_LINUX_SPEC): Rewrite without
+ absolute paths.
+
+2002-05-22 Kazu Hirata <kazu@cs.umass.edu>
+
+ * cpperror.c: Fix formatting.
+ * cppexp.c: Likewise.
+ * cppfiles.c: Likewise.
+ * cpphash.c: Likewise.
+ * cpphash.h: Likewise.
+ * cppinit.c: Likewise.
+ * cpplex.c: Likewise.
+ * cpplib.c: Likewise.
+ * cppmacro.c: Likewise.
+ * cppmain.c: Likewise.
+ * cppspec.c: Likewise.
+
+2002-05-22 Jakub Jelinek <jakub@redhat.com>
+
+ * combine.c (force_to_mode): Use gen_int_mode.
+ Don't clear CONST_INT bits outside of mode.
+
+2002-05-22 Richard Henderson <rth@redhat.com>
+
+ * fixinc/inclhack.def (thread_keyword): Match __thread as last arg.
+ * fixinc/fixincl.x, fixinc/tests/base/pthread.h: Rebuild.
+
+2002-05-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/6643
+ * emit-rtl.c (widen_memory_access): Only call compare_tree_int
+ if DECL_SIZE_UNIT is INTEGER_CST.
+
+2002-05-22 Richard Henderson <rth@redhat.com>
+
+ * flow.c (life_analysis): Delete broken reg_label check.
+
+2002-05-22 Richard Henderson <rth@redhat.com>
+
+ * fixinc/inclhack.def (thread_keyword): Allow as any prototype arg.
+ * fixinc/fixincl.x, fixinc/tests/base/pthread.h: Rebuild.
+
+Wed May 22 18:39:57 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * t-sh (LIB2FUNCS_EXTRA): Now embed-bb.c.
+ (embed-bb.c): New rule.
+ * t-sh64 (LIB2FUNCS_EXTRA): Don't change.
+ * config/sh/embed_bb.c: Delete.
+
+Wed May 22 18:25:29 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * c-common.c (cb_register_builtins): Don't indent '#' of #define.
+
+2002-05-22 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/h8300.md (*andorqi3): New.
+
+2002-05-22 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ PR preprocessor/6517
+ * Makefile.in: Update.
+ * c-common.c (c_common_post_options): Add preprocessor
+ errors to the error count.
+ * c-lang.c (c_post_options): Kill.
+ (LANG_HOOKS_POST_OPTIONS): Use c_common_post_options.
+ * hooks.h: Add header guards.
+ * langhooks-def.h: Include hooks.h.
+ (LANG_HOOKS_POST_OPTIONS): Update.
+ * langhooks.h (struct lang_hooks): Update post_options.
+ * toplev.c (parse_options_and_default_flags): Update.
+objc:
+ * objc-lang.c (objc_post_options): Kill.
+ (LANG_HOOKS_POST_OPTIONS): Use c_common_post_options.
+
+2002-05-21 Bruce Korb <bkorb@gnu.org>
+
+ * fixinc/tests/base/pthread.h(THREAD_KEYWORD_CHECK): add fix check
+ * fixinc/inclhack.def(thread_keyword): use c_fix = format.
+ * fixinc/fixincl.x: regen.
+
+2002-05-21 Kazu Hirata <kazu@cs.umass.edu>
+
+ * cfgbuild.c: Fix formatting.
+ * cfg.c: Likewise.
+ * cfgcleanup.c: Likewise.
+ * cfglayout.c: Likewise.
+ * cfgloop.c: Likewise.
+ * cfgrtl.c: Likewise.
+
+2002-05-21 Richard Henderson <rth@redhat.com>
+
+ * c-common.h (enum rid): Add RID_THREAD.
+ * c-decl.c (start_decl): Do not set DECL_COMMON for tls variables.
+ (grokdeclarator): Grok __thread.
+ * c-parse.in (reswords): Add __thread.
+ (rid_to_yy): Add RID_THREAD.
+
+ * tree.h (DECL_THREAD_LOCAL): New.
+ (struct tree_decl): Add thread_local_flag.
+ * print-tree.c (print_node): Dump DECL_THREAD_LOCAL.
+ * tree.c (staticp): TLS variables are not static.
+
+ * target-def.h (TARGET_HAVE_TLS): New.
+ * target.h (have_tls): New.
+ * output.h (SECTION_TLS): New.
+ * varasm.c (assemble_variable): TLS variables can't be common for now.
+ (default_section_type_flags): Handle .tdata and .tbss.
+ (default_elf_asm_named_section): Handle SECTION_TLS.
+ (categorize_decl_for_section): Handle DECL_THREAD_LOCAL.
+
+ * flags.h (flag_tls_default): Declare.
+ * toplev.c (flag_tls_default): Define.
+ (display_help): Display help for it.
+ (decode_f_option): Set it.
+
+ * doc/extend.texi (Thread-Local): New node describing language-level
+ thread-local storage.
+ * doc/invoke.texi (-ftls-model): Document.
+
+ * fixinc/inclhack.def (thread_keyword): New.
+ * fixinc/fixincl.x: Rebuild.
+
+2002-05-21 Jeffrey A Law <law@redhat.com>
+
+ * optabs.c (expand_binop): For double-word integer multiplies,
+ do not compute intermediate results into something that is
+ not a register (such as a SUBREG or MEM).
+
+ * i386.c (ix86_sched_reorder_ppro): Fix typo/thinko.
+ (ix86_sched_reorder): Make sure to initialize scheduling
+ data even when there's only one insn in the ready queue.
+
+2002-05-21 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (reserv_sets_hash_value): Fix a typo.
+
+2002-05-21 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (reserv_sets_hash_value): Define hash_value as
+ set_el_t. Transform the hash value into unsigned.
+ (output_cycle_reservs): Fix bug with output of repeated `nothing'.
+ (transform_3): Add code to process `(A,B)+(D,E)'.
+
+2002-05-21 NIIBE Yutaka <gniibe@m17n.org>
+
+ * reload1.c (do_output_reload): Run delete_output_reload
+ only if optimizing.
+
+2002-05-21 Roger Sayle <roger@eyesopen.com>
+
+ PR middle-end/6600
+ * expr.c (STORE_MAX_PIECES): New macro to avoid immediate constants
+ larger than INTEGER_CST. (store_by_pieces_1): Use it here...
+ (can_store_by_pieces): ... and here to limit the largest mode used.
+ Add a comment to document this function.
+
+2002-05-21 Richard Henderson <rth@redhat.com>
+
+ * flow.c (life_analysis): Fix test for deleted label.
+
+2002-05-21 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * doc/tm.texi: Fix typo.
+
+2002-05-21 Zack Weinberg <zack@codesourcery.com>
+
+ * c-common.c (c_common_init): Set options->unsigned_char from
+ flag_signed_char.
+ (cb_register_builtins): Define __STRICT_ANSI__ and
+ __CHAR_UNSIGNED__ here...
+ * cppinit.c (init_builtins): Not here.
+ (cpp_create_reader): unsigned_char option defaults to 0, not
+ !DEFAULT_SIGNED_CHAR.
+ (COMMAND_LINE_OPTIONS, cpp_handle_option): Lose -fsigned-char
+ and -funsigned-char.
+
+ * cpphash.h (struct spec_nodes): Kill n__STRICT_ANSI__.
+ * cpphash.c (_cpp_init_hashtable): Don't set it.
+ * cppmacro.c (builtin_macro) [BT_STDC]: Use the language setting
+ directly. Clarify comment.
+
+2002-05-21 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * bb-reorder.c (make_reorder_chain_1): Use prev_bb/next_bb to get to
+ neighboring basic blocks. Use ENTRY_BLOCK_PTR->next_bb instead of
+ BASIC_BLOCK (0). Use EXIT_BLOCK_PTR->prev_bb instead of
+ BASIC_BLOCK (n_basic_blocks - 1).
+ * cfganal.c (can_fallthru, flow_call_edges_add,
+ flow_preorder_transversal_compute): Too.
+ * cfgbuild.c (make_edges, find_basic_blocks, find_many_sub_basic_blocks,
+ find_sub_basic_blocks): Too.
+ * cfgcleanup.c (try_simplify_condjump, try_optimize_cfg): Too.
+ * cfglayout.c (skip_insns_after_block, fixup_reorder_chain,
+ fixup_fallthru_exit_predecessor, cfg_layout_redirect_edge): Too.
+ * cfgrtl.c (tidy_fallthru_edges, verify_flow_info): Too.
+ * combine.c (this_basic_block): Type changed to basic_block.
+ (combine_instructions, set_nonzero_bits_and_sign_copies, try_combine,
+ nonzero_bits, num_sign_bit_copies, get_last_value_validate,
+ get_last_value, distribute_notes, distribute_links): Too.
+ * final.c (compute_alignments): Too.
+ * flow.c (regno_uninitialized, regno_clobbered_at_setjmp): Too.
+ * function.c (thread_prologue_and_epilogue_insns): Too.
+ * gcse.c (compute_code_hoist_vbeinout): Too.
+ * global.c (build_insn_chain): Too.
+ * ifcvt.c (find_if_block, find_cond_trap): Too.
+ * predict.c (last_basic_block_p, note_prediction_to_br_prob): Too.
+ * regmove.c (regmove_optimize): Too.
+ * resource.c (find_basic_block): Too.
+ * sched-ebb.c (schedule_ebbs): Too.
+ * ssa-dce.c (find_control_dependence, find_pdom): Too.
+
+2002-05-21 Andreas Jaeger <aj@suse.de>
+
+ * cppinit.c (sanity_checks): Avoid printf mismatch warnings.
+
+2002-05-21 Richard Henderson <rth@redhat.com>
+
+ * reg-stack.c (swap_rtx_condition, subst_stack_regs_pat): Use
+ unspec names, not numbers.
+
+2002-05-21 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/sourcebuild.texi: Mention snapshot-README and
+ snapshot-index.html as needing updating for new front ends.
+
+2002-05-21 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * rtl.h (SUBREG_PROMOTED_UNSIGNED_SET): Avoid warnings when
+ disabling checking, and avoid multiple evaluation of RTX.
+
+2002-05-21 Richard Earnshaw <rearnsha@arm.com>
+
+ * bitmap.c (bitmap_find_bit): Return early if we have the correct
+ element cached.
+
+Tue May 21 10:51:54 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * profile.c (gen_edge_profiler): Set alias set before the memory is
+ used.
+
+2002-05-20 David S. Miller <davem@redhat.com>
+
+ * cselib.c (max_value_regs): New.
+ (cselib_lookup, cselib_invalidate_regno): Initialize it when
+ adding new entries to the REG_VALUES table and we are dealing with
+ a hard register.
+ (clear_table): Initialize it.
+ (cselib_invalidate_regno): Use it to determine which hard
+ registers to scan when mode is not VOIDmode.
+
+2002-05-20 Duraid Madina <duraid@fl.net.au>
+
+ * tradcpp.c (fixup_newlines): Use old-style function header.
+
+2002-05-20 Krister Walfridsson <cato@df.lth.se>
+
+ * reload1.c (reload_cse_simplify): Fix typo in rtx code check.
+
+2002-05-20 H.J. Lu (hjl@gnu.org)
+
+ Base on suggestions from Zhang Fuxin <fxzhang@ict.ac.cn>:
+
+ * config/mips/mips.h (DFMODE_NAN): Defined.
+ (SFMODE_NAN): Likewise.
+
+2002-05-20 Dale Johannesen <dalej@apple.com>
+
+ * combine.c (cant_combine_insn_p): Back out my
+ previous patch.
+
+2002-05-20 Kazu Hirata <kazu@cs.umass.edu>
+
+ * params.c: Fix formatting.
+ * params.h: Likewise.
+ * predict.c: Likewise.
+ * prefix.c: Likewise.
+ * print-rtl.c: Likewise.
+ * print-tree.c: Likewise.
+ * profile.c: Likewise.
+
+2002-05-20 H.J. Lu (hjl@gnu.org)
+
+ * gcc/config/mips/linux.h (SDB_DEBUGGING_INFO): Undefine.
+
+2002-05-20 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/arm/arm-wince-pe.h (ASM_SPEC): Pass -mcpu and -march
+ switches straight on to the assembler, do not abbreviate them.
+ * config/arm/elf.h (ASM_SPEC): As above.
+ * config/arm/semi.h (ASM_SPEC): As above.
+ * config/arm/unknown-elf-oabi.h (ASM_SPEC): As above.
+ * config/arm/xscale-coff.h (SUBTARGET_ASM_SPEC): Pass
+ -mcpu=xscale on to the assembler by default.
+ * config/arm/xscale-elf.h (SUBTARGET_ASM_SPEC): As above.
+
+2002-05-20 Richard Henderson <rth@redhat.com>
+
+ * cse.c (canon_hash): Reorder do_not_record test. Always
+ allow pic_offset_table_rtx.
+
+2002-05-19 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ * optabs.c (expand_cmplxdiv_wide): Use complex_part_zero_p.
+ (expand_binop): Ditto (3 times).
+
+2002-05-19 Mark Mitchell <mitchell@doubledemon.codesourcery.com>
+
+ * Makefile.in (distclean): Remove QMTest stuff.
+ (QMTEST_PATH): New variable.
+ (QMTESTFLAGS): Likewise.
+ (QMTESTRUNFLAGS): Likewise.
+ (QMTEST): Likewise.
+ (QMTEST_GPP_TESTS): Likewise.
+ (QMTEST_DIR): Likewise.
+ (QMTEST_DIR/context): New target.
+ (qmtest-g++): Likeise.
+ (qmtest-gui): Likewise.
+ (QMTEST_DIR/gpp-expected.qmr): Likewise.
+
+2002-05-19 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.h (FUNCTION_VALUE): Only return vectors in
+ an altivec register if TARGET_ALTIVEC.
+
+ * config/rs600/rs6000.c (rs6000_emit_move): Change VECTOR_MODE_P
+ to ALTIVEC_VECTOR_MODE.
+ (rs6000_va_arg): Only vectors of type AltiVec are 16 byte aligned.
+ (rs6000_va_arg): Vectors may go in registers if they are not
+ altivec vectors.
+
+2002-05-19 Kazu Hirata <kazu@cs.umass.edu>
+
+ * protoize.c: Fix formatting.
+
+2002-05-19 Richard Henderson <rth@redhat.com>
+
+ * gensupport.c (init_include_reader): Merge into ...
+ (process_include): ... here. Simplify composite path creation.
+ Plug memory leaks. Fix file/line number tracking. Do not
+ process_define_cond_exec. Return void.
+ (process_rtx): Don't check process_include return value.
+
+2002-05-20 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * basic_block.h (struct basic_block_def): Added prev_bb and next_bb
+ fields.
+ (FOR_BB_BETWEEN, FOR_ALL_BB, FOR_ALL_BB_REVERSE): New macros for
+ traversing basic block chain.
+ (create_basic_block_structure, create_basic_block): Declaration changed.
+ (link_block, unlink_block): Declare.
+ * cfg.c (entry_exit_blocks): Initialize new fields.
+ (link_block, unlink_block): New.
+ (expunge_block_nocompact): Unlink basic block.
+ (dump_flow_info): Print prev_bb/next_bb fields.
+ * cfgbuild.c (find_basic_blocks_1, find_basic_blocks): Modified.
+ * cfgcleanup.c (merge_blocks_move_predecessor_nojumps): Modified.
+ * cfglayout.c (fixup_reorder_chain, cfg_layout_duplicate_bb): Modified.
+ * cfgrtl.c (create_basic_block_structure, create_basic_block,
+ split_block, force_nonfallthru_and_redirect, split_edge): Modified.
+ (verify_flow_info): Check that list agrees with numbering.
+
+2002-05-19 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (preprocessing_asm): New macro.
+ * c-lex.h (builtin_define, builtin_assert): Use pfile.
+doc:
+ * tm.texi: Update.
+config/alpha:
+ * alpha.h (CPLUSPLUS_CPP_SPEC): Remove.
+ (CPP_SPEC): Simplify.
+ (TARGET_CPU_CPP_BUILTINS): Update.
+ * freebsd.h (TARGET_OS_CPP_BUILTINS): New.
+ (CPP_SPEC): Simplify.
+ * linux.h (CPLUSPLUS_CPP_SPEC): Remove.
+ (TARGET_OS_CPP_BUILTINS): Update.
+ * osf.h (CPP_XFLOAT_SPEC): Kill.
+ (TARGET_OS_CPP_BUILTINS): Update.
+ (CPP_SUBTARGET_SPEC, SUBTARGET_EXTRA_SPECS): Simplify.
+ * osf5.h (CPP_XFLOAT_SPEC): Kill.
+ * vms.h (CPP_SUBTARGET_SPEC): Kill.
+ (TARGET_OS_CPP_BUILTINS): Update.
+
+2002-05-19 Richard Henderson <rth@redhat.com>
+
+ * varasm.c (default_binds_local_p): Fix typo.
+
+2002-05-19 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (machine_dependent_reorg): Sign extend the
+ CONST_INT operand to the correct mode after adding 1 to it.
+
+2002-05-19 Mark Mitchell <mark@codesourcery.com>
+
+ * config.gcc (powerpc-wrs-windiss*): New target.
+
+2002-05-19 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ * config/rs6000/rs6000.md (ashrdi3_no_power): New.
+ (ashrdi3): Use it.
+
+2002-05-18 Mark Mitchell <mark@codesourcery.com>
+
+ * configure.in (AC_CHECK_FUNCS): Add checks for scandir and
+ alphasort.
+ * config.in: Regenerated.
+ * configure: Regenerated.
+
+2002-05-19 Richard Henderson <rth@redhat.com>
+
+ * target-def.h (TARGET_BINDS_LOCAL_P): New.
+ * target.h (struct gcc_target): Move boolean fields to the end.
+ Add binds_local_p.
+ * varasm.c (default_binds_local_p): New.
+ * output.h: Declare it.
+
+ * config/alpha/alpha.c (alpha_encode_section_info): Use the new hook.
+ * config/cris/cris.c (cris_encode_section_info): Likewise.
+ * config/i386/i386.c (i386_encode_section_info): Likewise.
+ * config/ia64/ia64.c (ia64_encode_section_info): Likewise.
+ * config/sh/sh.c (sh_encode_section_info): Likewise.
+
+ * doc/tm.texi (TARGET_IN_SMALL_DATA_P): New.
+ (TARGET_BINDS_LOCAL_P): New.
+
+2002-05-19 Richard Henderson <rth@redhat.com>
+
+ * system.h (BLOCK_PROFILER, BLOCK_PROFILER_CODE,
+ FUNCTION_BLOCK_PROFILER, FUNCTION_BLOCK_PROFILER_EXIT,
+ MACHINE_STATE_SAVE, MACHINE_STATE_RESTORE): Poison.
+
+ * toplev.c (display_help): Kill -a -ax help.
+
+ * config/1750a/1750a.h, config/alpha/alpha.h,
+ config/clipper/clipper.h, config/dsp16xx/dsp16xx.h,
+ config/h8300/h8300.h, config/i960/i960.h, config/m68k/tower-as.h,
+ config/m88k/m88k.h, config/vax/vax.h, config/we32k/we32k.h:
+ (FUNCTION_BLOCK_PROFILER, BLOCK_PROFILER): Kill.
+
+ * libgcc2.c [L_bb] (BLOCK_PROFILER_CODE): Kill.
+ * config/m68k/sun3.h (BLOCK_PROFILER_CODE): Kill.
+
+ * config/i386/i386-protos.h (ix86_output_block_profiler): Kill.
+ (ix86_output_function_block_profiler): Kill.
+ * config/m68hc11/m68hc11.c (m68hc11_block_profiler): Kill.
+ (m68hc11_function_block_profiler): Kill.
+ * config/m68hc11/m68hc11-protos.h: Update.
+ * config/m88k/m88k.c (output_block_profiler): Kill.
+ (output_function_block_profiler): Kill.
+ * config/m88k/m88k-protos.h: Update.
+
+2002-05-19 Richard Henderson <rth@redhat.com>
+
+ * system.h (STRIP_NAME_ENCODING): Poison it.
+ * output.h (STRIP_NAME_ENCODING): Remove.
+ (default_strip_name_encoding): Declare.
+ * target-def.h (TARGET_STRIP_NAME_ENCODING): New.
+ * target.h (strip_name_encoding): New.
+ * varasm.c (default_strip_name_encoding): New.
+
+ * dwarf2asm.c, varasm.c, config/darwin.c, config/darwin.h,
+ config/alpha/alpha.c, config/arm/pe.c, config/avr/avr.c,
+ config/cris/cris.c, config/i386/cygwin.h, config/i386/interix.c,
+ config/i386/winnt.c, config/m32r/m32r.h, config/mcore/mcore-elf.h,
+ config/mcore/mcore-pe.h, config/mcore/mcore.c, config/mcore/mcore.h,
+ config/mips/mips.c, config/mn10200/mn10200.h, config/mn10300/mn10300.h,
+ config/pa/pa.c, config/pa/pa.h, config/pa/som.h,
+ config/rs6000/rs6000.c, config/rs6000/sysv4.h, config/rs6000/xcoff.h,
+ config/v850/v850.h: Use the hook, not the macro.
+
+ * config/darwin-protos.h, config/darwin.c, config/darwin.h,
+ config/alpha/alpha.c, config/alpha/alpha.h, config/h8300/h8300.c,
+ config/h8300/h8300.h, config/i386/cygwin.h, config/i386/i386-interix.h,
+ config/i386/i386-protos.h, config/i386/win32.h, config/i386/winnt.c,
+ config/ia64/ia64.c, config/ia64/ia64.h, config/m32r/m32r.c,
+ config/m32r/m32r.h, config/mcore/mcore.c, config/mcore/mcore.h,
+ config/pa/pa.c, config/rs6000/rs6000.c, config/rs6000/sysv4.h,
+ config/rs6000/xcoff.h, config/sh/sh.c, config/sh/sh.h,
+ config/v850/v850.c, config/v850/v850.h:
+ Move STRIP_NAME_ENCODING to out-of-line function and add
+ TARGET_STRIP_NAME_ENCODING.
+
+ * config/arm/arm.c, config/arm/arm.h, config/mmix/mmix-protos.h,
+ config/mmix/mmix.c, config/mmix/mmix.h: Replace STRIP_NAME_ENCODING
+ with TARGET_STRIP_NAME_ENCODING referencing existing function;
+ make function static.
+
+ * xcoffout.c: Include target.h
+ * Makefile.in (xcoffout.o): Update.
+
+ * config/avr/avr.c (avr_encode_section_info): Correct prototype.
+ * config/avr/avr.h (STRIP_NAME_ENCODING): Remove.
+ * config/rs6000/rs6000.c (rs6000_xcoff_unique_section): Mark
+ reloc argument unused.
+ * config/sh/sh.c (TARGET_ENCODE_SECTION_INFO): New.
+
+ * doc/tm.texi (TARGET_STRIP_NAME_ENCODING): Update from previous
+ STRIP_NAME_ENCODING docs.
+
+2002-05-19 Andreas Jaeger <aj@suse.de>
+
+ * gengenrtl.c: Add prototype for excluded_rtx.
+
+ * real.h: Add prototype for exact_real_truncate.
+
+2002-05-18 Richard Henderson <rth@redhat.com>
+
+ * system.h (ENCODE_SECTION_INFO): Poison it.
+ * target-def.h (TARGET_ENCODE_SECTION_INFO): New.
+ * target.h (encode_section_info): New.
+ * varasm.c (make_decl_rtl, output_constant_def): Use it.
+ * hooks.c (hook_tree_int_void): New.
+ * hooks.h: Declare it.
+
+ * config/darwin.h, config/alpha/alpha-protos.h, config/alpha/alpha.c,
+ config/alpha/alpha.h, config/arm/pe.h, config/avr/avr-protos.h,
+ config/avr/avr.c, config/avr/avr.h, config/c4x/c4x-protos.h,
+ config/c4x/c4x.c, config/c4x/c4x.h, config/cris/cris-protos.h,
+ config/cris/cris.c, config/cris/cris.h, config/i386/cygwin.h,
+ config/i386/win32.h, config/ia64/ia64-protos.h, config/ia64/ia64.c,
+ config/ia64/ia64.h, config/m32r/m32r-protos.h, config/m32r/m32r.c,
+ config/m32r/m32r.h, config/m68hc11/m68hc11-protos.h,
+ config/m68hc11/m68hc11.c, config/m68hc11/m68hc11.h,
+ config/mcore/mcore-protos.h, config/mcore/mcore.c,
+ config/mcore/mcore.h, config/mmix/mmix-protos.h, config/mmix/mmix.c,
+ config/mmix/mmix.h, config/rs6000/rs6000-protos.h,
+ config/rs6000/sysv4.h, config/stormy16/stormy16-protos.h,
+ config/stormy16/stormy16.c, config/stormy16/stormy16.h:
+ Replace ENCODE_SECTION_INFO with TARGET_ENCODE_SECTION_INFO
+ referencing existing function. Make function static.
+
+ * config/a29k/a29k.c, config/a29k/a29k.h, config/arc/arc.c,
+ config/arc/arc.h, config/arm/arm.c, config/arm/arm.h,
+ config/h8300/h8300.c, config/h8300/h8300.h, config/i370/i370.c,
+ config/i370/i370.h, config/i386/i386-interix.h, config/i386/i386.c,
+ config/i386/i386.h, config/i386/interix.c, config/m88k/m88k.c,
+ config/m88k/m88k.h, config/mips/mips.c, config/mips/mips.h,
+ config/ns32k/ns32k.c, config/ns32k/ns32k.h, config/pa/pa.c,
+ config/pa/pa.h, config/romp/romp.c, config/romp/romp.h,
+ config/rs6000/linux64.h, config/rs6000/xcoff.h, config/s390/s390.c,
+ config/s390/s390.h, config/sh/sh.c, config/sh/sh.h,
+ config/sparc/sparc.c, config/sparc/sparc.h, config/v850/v850.c,
+ config/v850/v850.h, config/vax/vax.c, config/vax/vms.h,
+ config/xtensa/xtensa.c, config/xtensa/xtensa.h:
+ Move ENCODE_SECTION_INFO to out-of-line function and add
+ TARGET_ENCODE_SECTION_INFO.
+
+ * config/darwin.h (ASM_DECLARE_FUNCTION_NAME): Use hook, not macro.
+ (ASM_DECLARE_OBJECT_NAME, ASM_OUTPUT_ALIGNED_DECL_LOCAL): Likewise.
+
+ * config/arm/pe.h (EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS): Rename
+ from SUBTARGET_*
+ (switch_to_section): Replace in_rdata case with in_readonly_data.
+
+ * config/h8300/h8300.c (h8300_encode_label): Make static.
+ * config/h8300/h8300-protos.h: Update.
+
+ * config/rs6000/rs6000.c (rs6000_elf_encode_section_info): Rename
+ from rs6000_encode_section_info; make static.
+ (rs6000_xcoff_encode_section_info): New.
+
+ * config/v850/v850.c (v850_encode_data_area): Make static.
+ * config/v850/v850-protos.h: Update.
+
+ * config/vax/vax.c: Include flags.h.
+ (vms_select_section): Fix typo.
+
+ * doc/tm.texi (TARGET_ENCODE_SECTION_INFO): Update from previous
+ ENCODE_SECTION_INFO docs.
+
+2002-05-18 Richard Henderson <rth@redhat.com>
+
+ * config/darwin.h (DARWIN_REGISTER_TARGET_PRAGMAS): Rename from
+ REGISTER_TARGET_PRAGMAS.
+ * config/rs6000/darwin.h (REGISTER_TARGET_PRAGMAS): Redefine.
+
+ * config.gcc: Do not use rs6000-c.c on powerpc-darwin.
+
+2002-05-18 Richard Henderson <rth@redhat.com>
+
+ * system.h (SELECT_RTX_SECTION): Poison.
+ * target-def.h (TARGET_ASM_SELECT_RTX_SECTION): New.
+ * target.h (select_rtx_section): New.
+ * varasm.c (output_constant_pool): Use it.
+ (default_select_rtx_section, default_elf_select_rtx_section): New.
+ * output.h: Declare them.
+
+ * config/darwin.h (SELECT_RTX_SECTION): Move ...
+ * config/darwin.c (machopic_select_rtx_section): ... here.
+ * config/darwin-protos.h: Update.
+
+ * config/nextstep.h (SELECT_RTX_SECTION): Move ...
+ * config/nextstep.c (machopic_select_rtx_section): ... here.
+ (nextstep_select_section): Rename variable to avoid macro clash.
+ * config/nextstep-protos.h: Update.
+
+ * config/elfos.h, config/svr3.h, config/arm/aof.h, config/c4x/c4x.h,
+ config/i386/dgux.h, config/i386/osfrose.h, config/i386/sco5.h,
+ config/i386/svr3gas.h, config/i860/paragon.h, config/ia64/aix.h,
+ config/m32r/m32r.h, config/m68k/dpx2.h, config/m68k/lynx.h,
+ config/m68k/m68k.h, config/m68k/tower-as.h, config/m88k/dgux.h,
+ config/mcore/mcore-pe.h, config/mips/mips.h, config/mmix/mmix.h,
+ config/pa/pa-linux.h, config/pa/pa.h, config/romp/romp.h,
+ config/rs6000/lynx.h, config/rs6000/sysv4.h, config/s390/linux.h,
+ config/sparc/sysv4.h, config/xtensa/elf.h, config/xtensa/linux.h
+ (SELECT_RTX_SECTION): Remove.
+
+ * config/darwin.h, config/elfos.h, config/nextstep.h,
+ config/ia64/aix.h, config/ia64/sysv4.h, config/alpha/alpha.c,
+ config/mips/mips.c, config/romp/romp.c, config/rs6000/sysv4.h,
+ config/rs6000/xcoff.h, config/s390/s390.c, config/sparc/aout.h,
+ config/sparc/lynx.h, config/xtensa/xtensa.c
+ (TARGET_ASM_SELECT_RTX_SECTION): New.
+
+ * config/alpha/elf.h (SELECT_RTX_SECTION): Move ...
+ * config/alpha/alpha.c (alpha_elf_select_rtx_section): ... here.
+ * config/ia64/sysv4.h (SELECT_RTX_SECTION): Move ...
+ * config/ia64/ia64.c (ia64_select_rtx_section): ... here.
+ (ia64_aix_select_rtx_section): New.
+ * config/mips/iris6.h (READONLY_DATA_SECTION_ASM_OP): Undef before
+ redefining.
+ * config/mips/mips.c (mips_select_rtx_section): Make static.
+ Support ELF SHF_MERGE features.
+ * config/mips/mips-protos.h: Update.
+ * config/rs6000/xcoff.h (SELECT_RTX_SECTION): Move ...
+ * config/rs6000/rs6000.c (rs6000_xcoff_select_rtx_section): ... here.
+ (rs6000_elf_select_rtx_section): Rename from rs6000_select_rtx_section;
+ make static, fall back to default_elf_select_rtx_section.
+ * config/rs6000/rs6000-protos.h: Update.
+ * config/sparc/sparc.h (SELECT_RTX_SECTION): Move ...
+ * config/sparc/sparc.c (sparc_aout_select_rtx_section): ... here.
+ * config/sparc/sunos4.h (on_exit): Declare only if IN_LIBGCC2.
+ * config/romp/romp.c (romp_select_rtx_section): New.
+ * config/s390/s390.c (s390_select_rtx_section): New.
+ * config/xtensa/xtensa.c: Include output.h. Shuffle local function
+ declarations before target macro definition.
+ (xtensa_emit_call): Use static buffer.
+ (xtensa_select_rtx_section): New.
+ * config/xtensa/xtensa.h (MAX_INT_TYPE_SIZE): Remove.
+ (IMPLICIT_FIX_EXPR, EASY_DIV_EXPR): Remove.
+ (ASM_OUTPUT_POOL_PROLOGUE): Update call to resolve_unique_section.
+
+ * doc/tm.texi (TARGET_ASM_SELECT_RTX_SECTION): Update from
+ SELECT_RTX_SECTION docs.
+
+Sun May 19 00:24:23 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (movsi/movdi): Fix template.
+ (sse2 patterns): Set attributes consistently.
+
+ * i386.md (pushqi2, ashrqi_*): Fix constraint.
+
+2002-05-18 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ * optabs.c (complex_part_zero_p): New.
+ * (expand_cmplxdiv_straight): Use it.
+ * (expand_cmplxdiv_wide): Ditto.
+ * (expand_binop): Ditto.
+
+2002-05-18 Richard Henderson <rth@redhat.com>
+
+ * final.c (HAVE_READONLY_DATA_SECTION): New.
+ (shorten_branches): Use it instead of ifdefs.
+ * varasm.c (enum in_section): Add in_readonly_data.
+ (text_section, data_section): Tidy.
+ (readonly_data_section): Use READONLY_DATA_SECTION_ASM_OP if present.
+
+ * config/darwin.h, config/nextstep.h, config/h8300/elf.h,
+ config/i860/paragon.h, config/m68k/dpx2.h, config/m68k/hp320.h
+ (READONLY_DATA_SECTION): Don't undef.
+
+ * config/alpha/unicosmk.h, config/h8300/elf.h, config/i386/aix386ng.h,
+ config/i860/paragon.h, config/m68k/dpx2.h, config/m68k/hp320.h,
+ config/rs6000/lynx.h (READONLY_DATA_SECTION_ASM_OP): Undef.
+
+ * config/elfos.h, config/svr3.h, config/alpha/alpha-interix.h,
+ config/alpha/elf.h, config/c4x/c4x.h, config/i386/i386-interix.h,
+ config/i386/sco5.h, config/i386/svr3gas.h, config/i860/sysv3.h,
+ config/m88k/m88k.h, config/pa/pa64-hpux.h (USE_CONST_SECTION): Remove.
+
+ * config/elfos.h, config/netware.h, config/alpha/alpha-interix.h,
+ config/alpha/elf.h, config/alpha/vms.h, config/arc/arc.h,
+ config/arm/coff.h, config/c4x/c4x.h, config/dsp16xx/dsp16xx.h,
+ config/i386/dgux.h, config/i386/i386-interix.h, config/i386/sco5.h,
+ config/ia64/hpux.h, config/m32r/m32r.h, config/m68k/tower-as.h,
+ config/m88k/m88k.h, config/mcore/mcore-pe.h, config/mips/iris6.h,
+ config/mips/mips.h, config/mmix/mmix.h, config/pa/pa64-hpux.h,
+ config/sparc/sysv4.h (READONLY_DATA_SECTION_ASM_OP): Rename from
+ CONST_SECTION_ASM_OP/READONLY_SECTION_ASM_OP/RDATA_SECTION_ASM_OP.
+
+ * config/elfos.h, config/netware.h, config/1750a/1750a.h,
+ config/a29k/a29k.h, config/alpha/alpha-interix.h, config/alpha/alpha.h,
+ config/arm/coff.h, config/h8300/h8300.h, config/i386/aix386ng.h,
+ config/i386/i386-interix.h, config/i386/osfrose.h, config/mmix/mmix.h,
+ config/pa/pa64-hpux.h, config/sparc/litecoff.h
+ (EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS): Remove.
+
+ * config/elfos.h, config/netware.h, config/svr3.h,
+ config/alpha/alpha-interix.h, config/alpha/alpha.h, config/alpha/elf.h,
+ config/arm/coff.h, config/c4x/c4x.h, config/dsp16xx/dsp16xx.h,
+ config/h8300/h8300.h, config/i386/i386-interix.h,
+ config/i386/osfrose.h, config/i386/svr3gas.h, config/mmix/mmix.h,
+ config/pa/pa64-hpux.h (READONLY_DATA_SECTION): Remove.
+
+ * config/elfos.h, config/netware.h, config/svr3.h,
+ config/alpha/alpha-interix.h, config/alpha/alpha.h, config/alpha/elf.h,
+ config/c4x/c4x.h, config/i386/aix386ng.h, config/i386/i386-interix.h,
+ config/i386/sco5.h, config/i386/svr3gas.h, config/mmix/mmix.h,
+ config/pa/pa64-hpux.h (CONST_SECTION_FUNCTION): Remove.
+
+ * config/lynx.h, config/svr3.h, config/alpha/elf.h, config/alpha/vms.h,
+ config/c4x/c4x.h, config/dsp16xx/dsp16xx.h, config/i386/sco5.h,
+ config/i386/svr3gas.h, config/i860/sysv3.h, config/i860/sysv4.h,
+ config/ia64/sysv4.h, config/m32r/m32r.h, config/m88k/m88k.h,
+ config/mcore/mcore-elf.h, config/mcore/mcore-pe.h, config/mips/elf.h,
+ config/mips/elf64.h, config/mips/iris6.h, config/mips/linux.h,
+ config/mips/mips.h, config/mips/rtems64.h, config/mips/vxworks.h,
+ config/rs6000/sysv4.h, config/v850/v850.h
+ (EXTRA_SECTIONS): Remove in_const/in_rdata.
+ (EXTRA_SECTION_FUNCTIONS): Remove accompanying function.
+
+ * config/svr3.h, config/c4x/c4x.h, config/i386/dgux.h,
+ config/i386/sco5.h, config/i386/svr3gas.h, config/ia64/aix.h,
+ config/m88k/dgux.h, config/mcore/mcore-pe.h, config/mmix/mmix.h,
+ config/sparc/sysv4.h (SELECT_RTX_SECTION): Use readonly_data_section.
+ * config/alpha/alpha.c (alpha_start_function): Likewise.
+ (alpha_write_linkage): Likewise.
+ * config/m32r/m32r.c (m32r_select_section): Likewise.
+ * config/m88k/m88k.c (m88k_select_section): Likewise.
+ * config/mips/mips.c (mips_select_rtx_section): Likewise.
+ * config/rs6000/rs6000.c (rs6000_select_rtx_section): Likewise.
+ (rs6000_elf_select_section): Likewise.
+ * config/v850/v850.c (v850_select_section): Likewise.
+
+ * config/1750a/1750a.h, config/i860/sysv3.h
+ (READONLY_DATA_SECTION_ASM_OP): New.
+ READONLY_DATA_SECTION_ASM_OP.
+ * config/i386/interix.c, config/i386/winnt.c
+ (i386_pe_unique_section): Always use .rdata prefix.
+ * config/pa/som.h (readonly_data): Always switch to read-only section.
+ (READONLY_DATA_SECTION): Predicate on flag_pic.
+ * config/we32k/we32k.h (READONLY_DATA_SECTION): Remove parenthesis.
+ * doc/tm.texi (READONLY_DATA_SECTION_ASM_OP): New.
+ (READONLY_DATA_SECTION): Update.
+
+2002-05-18 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * c-common.c (c_common_post_options): Warn if -Wformat-zero-length
+ is used without -Wformat.
+ * c-common.h (warn_format_zero_length): Declare extern.
+ * c-decl.c (warn_options): Add "format-zero-length".
+ * c-format.c (warn_format_zero_length): Declare.
+ (set_Wformat): Set warn_format_zero_length for -Wformat.
+ (check_format_info): Only warn about zero-length formats if
+ warn_format_zero_length is true. Include the format type
+ name in the warning message.
+ * doc/invoke.texi: Document -Wformat-zero-length.
+ * testsuite/gcc.dg/format/zero-length-1.c: New test.
+
+2002-05-18 Kazu Hirata <kazu@cs.umass.edu>
+
+ * timevar.c: Fix formatting.
+ * tlink.c: Likewise.
+ * toplev.c: Likewise.
+ * tree-dump.c: Likewise.
+ * tree-inline.c: Likewise.
+
+2002-05-18 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppinit.c (cpp_post_options): If preprocessed, turn off
+ traditional. If traditional, turn off column numbers.
+ * cpplib.c (cpp_push_buffer): Lex from stage 3 if traditional.
+ * cpptrad.c (handle_newline): Update line_base.
+ (skip_comment): Handle -Wcomment.
+
+2002-05-17 Zack Weinberg <zack@codesourcery.com>
+
+ * cppinit.c (struct builtin): Remove unused fields.
+ (CPLUS, BUILTIN, OPERATOR, O, builtin_array_end): Kill.
+ (operator_array): New - was second half of builtin_array.
+ (init_builtins): Simplify loop over builtin_array/operator_array.
+
+2002-05-18 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * defaults.h (UNIQUE_SECTION): Remove.
+ * system.h (UNIQUE_SECTION, SELECT_SECTION): Poison.
+
+2002-05-17 Richard Henderson <rth@redhat.com>
+
+ * expr.c (init_expr_once): Don't use start/end_sequence.
+ Use rtx_alloc instead of emit_insn.
+ * toplev.c (lang_dependent_init): Run init_expr_once here ...
+ (lang_independent_init): ... not here.
+
+2002-05-17 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/sh/lib1funcs.asm (GLOBAL): Use __USER_LABEL_PREFIX__.
+
+2002-05-17 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (avr_regs_to_save): New function. Also check
+ for fixed registers, possibly used for global register variables.
+ (initial_elimination_offset, avr_output_function_prologue,
+ avr_output_function_epilogue): Move common code to avr_regs_to_save.
+
+2002-05-17 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in: Update for cpptrad.c.
+ * cpphash.h (struct cpp_buffer): New members for buffer
+ overlays.
+ (struct cpp_reader): New members for traditional output.
+ (_cpp_read_logical_line, _cpp_overlay_buffer): New.
+ * cppinit.c (cpp_create_reader): Set trad_line.
+ (cpp_destroy): Free trad_out_base if used.
+ (cpp_read_main_file): Overlay an empty buffer if traditional.
+ (cpp_finish_options): Don't do builtins.
+ (COMMAND_LINE_OPTIONS): Add -traditional-cpp.
+ (cpp_handle_option): Handle it.
+ * cpplex.c (continue_after_nul): New.
+ (_cpp_lex_direct): Use handle_nul.
+ * cpplib.h (struct cpp_options): New traditional option.
+ * cpptrad.c: New file.
+
+2002-05-17 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (c_common_init_options): Use C89 for Objective-C,
+ and set the options flag.
+ * cppinit.c (lang_flags): Remove objc.
+ (lang_defaults): Remove OBJC and OBJCXX.
+ (set_lang): Update.
+ (COMMAND_LINE_OPTIONS): Remove -+ and -lang-objc++.
+ (cpp_handle_option): Remove -+ and -lang-objc++.
+ For ObjC, just set a flag.
+ (print_help): Update.
+ * cpplib.h (enum c_lang): Remove CLK_OBJC and CLK_OBJCXX.
+
+2002-05-17 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * doc/install.texi (Specific, mips-sgi-irix6): Document need to
+ bootstrap with -mips3.
+
+2002-05-17 Kazu Hirata <kazu@cs.umass.edu>
+
+ * final.c: Fix formatting.
+ * fix-header.c: Likewise.
+ * flow.c: Likewise.
+ * fold-const.c: Likewise.
+ * function.c: Likewise.
+
+2002-05-17 David S. Miller <davem@redhat.com>
+
+ PR c/6689, PR optimization/6615
+ * local-alloc.c (struct equivalence): Rename 'src' to 'src_p'
+ and make it a pointer to rtx. Update comments.
+ (update_equiv_regs): When scanning for equivalences, record
+ address of SET_SRC (set) in reg_equiv[].src_p. Dereference
+ it while making the equiv replacements.
+
+2002-05-17 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * config/sparc/sparc.c (sparc_aout_select_section): Fixed typo.
+
+2002-05-17 kaz Kojima <kkojima@rr.iij4u.or.jp>
+
+ * config/sh/sh.h (ENCODE_SECTION_INFO): Consider MODULE_LOCAL_P
+ when encoding visibility into SYMBOL_REF_FLAG.
+
+2002-05-17 Richard Sandiford <rsandifo@redhat.com>
+
+ * expr.c (force_operand): Fix reversed move.
+
+2002-05-17 Kurt Wall <kwall@kurtwerks.com>
+
+ * doc/install.texi (Testing): Mention two common DejaGnu warnings
+ that can be ignored.
+
+2002-05-16 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/install.texi (Final install): Recommend to install into a
+ "clean" target directory.
+
+2002-05-17 Richard Henderson <rth@redhat.com>
+
+ * config/ia64/ia64.md: Use braced strings instead of quoted strings
+ for code blocks. Tidy whitespace.
+
+2002-05-17 Richard Henderson <rth@redhat.com>
+
+ * hooks.c (hook_tree_bool_false): New.
+ * hooks.h: Declare it.
+ * target-def.h (TARGET_ASM_SELECT_SECTION): New.
+ (TARGET_ASM_UNIQUE_SECTION, TARGET_IN_SMALL_DATA_P): New.
+ * target.h (select_section, unique_section): New.
+ (in_small_data_p): New.
+ * varasm.c (resolve_unique_section): Use hooks instead of macros.
+ (variable_section, output_constant_def_contents): Likewise.
+ (default_select_section, default_unique_section): New.
+ (categorize_decl_for_section, default_elf_select_section): New.
+ * output.h: Declare them.
+
+ * config/darwin.h (ALIAS_SECTION, try_section_alias): Remove.
+ (TARGET_ASM_SELECT_SECTION): New.
+ (SELECT_SECTION): Move ...
+ * config/darwin.c (machopic_select_section): ... here.
+ * config/darwin-protos.h: Update.
+
+ * config/nextstep.h (TARGET_ASM_SELECT_SECTION): New.
+ (SELECT_SECTION): Move ...
+ * config/nextstep.c (nextstep_select_section): ... here.
+ * config/nextstep-protos.h: Update.
+
+ * config/elfos.h (UNIQUE_SECTION, SELECT_SECTION): Remove.
+ (TARGET_ASM_SELECT_SECTION): New.
+ * config/svr3.h (SELECT_SECTION): Remove.
+
+ * config/alpha/alpha.c (unicosmk_unique_section): Make static.
+ (TARGET_ASM_UNIQUE_SECTION) [UNICOS]: New.
+ (TARGET_IN_SMALL_DATA_P, alpha_in_small_data_p): New.
+ (alpha_encode_section_info): Use it.
+ * config/alpha/alpha-protos.h: Update.
+ * config/alpha/elf.h (DO_SELECT_SECTION): Remove.
+ (SELECT_SECTION, UNIQUE_SECTION): Remove.
+ (TARGET_ASM_SELECT_SECTION): New.
+ * config/alpha/unicosmk.h (UNIQUE_SECTION): Remove.
+
+ * config/arm/pe.h (UNIQUE_SECTION): Remove.
+ (TARGET_ASM_UNIQUE_SECTION): New.
+
+ * config/avr/avr.c (TARGET_ASM_UNIQUE_SECTION): New.
+ (avr_unique_section): Rename from unique_section; make static.
+ * config/avr/avr-protos.h: Update.
+ * config/avr/avr.h (UNIQUE_SECTION): Remove.
+
+ * config/c4x/c4x.h (SELECT_SECTION): Remove.
+
+ * config/i386/cygwin.h (UNIQUE_SECTION): Remove.
+ (TARGET_ASM_UNIQUE_SECTION): New.
+ * config/i386/i386-interix.h: Likewise.
+ * config/i386/win32.h: Likewise.
+ * config/i386/djgpp.h (UNIQUE_SECTION): Remove.
+ * config/i386/i386.c (ix86_asm_file_end): Use target hook not macro.
+ * config/i386/sco5.h (SELECT_SECTION): Remove.
+ (TARGET_ASM_SELECT_SECTION): New.
+ * config/i386/svr3gas.h (SELECT_SECTION): Remove.
+
+ * config/i860/paragon.h: Undef TARGET_ASM_SELECT_SECTION
+ instead of SELECT_SECTION.
+ * config/m68k/dpx2.h: Likewise.
+ * config/rs6000/lynx.h: Likewise.
+
+ * config/ia64/aix.h (SELECT_SECTION, UNIQUE_SECTION): Remove.
+ (TARGET_ASM_SELECT_SECTION, TARGET_ASM_UNIQUE_SECTION): New.
+ * config/ia64/ia64.c (TARGET_IN_SMALL_DATA_P): New.
+ (ia64_in_small_data_p): New.
+ (ia64_encode_section_info): Use it. Reorganize overlarge conditional.
+ (ia64_aix_select_section, ia64_aix_unique_section): New.
+ * config/ia64/sysv4.h (DO_SELECT_SECTION): Remove.
+ (SELECT_SECTION, UNIQUE_SECTION): Remove.
+
+ * config/m32r/m32r.h (SELECT_SECTION): Remove.
+ (TARGET_ASM_SELECT_SECTION): New.
+ * config/m32r/m32r.c (m32r_select_section): Take align argument.
+ * config/m32r/m32r-protos.h: Update.
+
+ * config/m88k/m88k.h (TARGET_ASM_SELECT_SECTION): New.
+ (SELECT_SECTION): Move ...
+ * config/m88k/m88k.c (m88k_select_section): ... here.
+
+ * config/mcore/mcore-pe.h (SELECT_SECTION): Remove.
+ * config/mcore/mcore.h (UNIQUE_SECTION): Remove.
+ * config/mcore/mcore.c (TARGET_ASM_UNIQUE_SECTION): New.
+ (mcore_unique_section): Make static.
+ * config/mcore/mcore-protos.h: Update.
+
+ * config/mips/elf.h (UNIQUE_SECTION): Remove.
+ (TARGET_ASM_UNIQUE_SECTION): New.
+ * config/mips/elf64.h: Likewise.
+ * config/mips/iris6gld.h: Likewise.
+ * config/mips/linux.h: Likewise.
+ * config/mips/mips-protos.h: Update.
+ * config/mips/mips.c (mips_select_section): Add align argument.
+ * config/mips/mips.h (SELECT_SECTION): Remove.
+ (TARGET_ASM_SELECT_SECTION): New.
+
+ * config/mmix/mmix.h (SELECT_SECTION, UNIQUE_SECTION): Remove.
+ * config/mmix/mmix.c (mmix_select_section): Remove.
+ (mmix_unique_section): Remove.
+ * config/mmix/mmix-protos.h: Update.
+
+ * config/pa/pa.h (TARGET_ASM_SELECT_SECTION): New.
+ (SELECT_SECTION): Move ...
+ * config/pa/pa.c (pa_select_section): ... here.
+ * config/pa/pa64-hpux.h (UNIQUE_SECTION): Remove.
+
+ * config/rs6000/rs6000.c (rs6000_elf_select_section): Rename
+ from rs6000_select_section and make static.
+ (rs6000_elf_unique_section): Similarly.
+ (rs6000_xcoff_select_section): From xcoff.h.
+ (rs6000_xcoff_unique_section): Likewise.
+ * config/rs6000/rs6000-protos.h: Update.
+ * config/rs6000/sysv4.h (SELECT_SECTION, UNIQUE_SECTION): Remove.
+ (TARGET_ASM_SELECT_SECTION, TARGET_ASM_UNIQUE_SECTION): New.
+ * config/rs6000/xcoff.h: Likewise.
+
+ * config/sparc/aout.h (TARGET_ASM_SELECT_SECTION): New.
+ (SELECT_SECTION): Move ...
+ * config/sparc/sparc.c (sparc_aout_select_section): ... here.
+
+ * config/v850/v850.h (SELECT_SECTION): Move ...
+ * config/v850/v850.c (v850_select_section): ... here.
+ (TARGET_ASM_SELECT_SECTION): New.
+
+ * config/vax/vms.h (SELECT_SECTION): Move ...
+ * config/vax/vax.c (vms_select_section): ... here.
+ (TARGET_ASM_SELECT_SECTION): New.
+
+ * doc/tm.texi: Update SELECT_SECTION and UNIQUE_SECTION docs
+ for the target hooks.
+
+2002-05-17 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/arm/arm.c (emit_multi_reg_push): Do not set
+ RTX_FRAME_RELATED_P on the SEQUENCE.
+
+2002-05-16 Richard Henderson <rth@redhat.com>
+
+ * config/ia64/ia64.c (ia64_reorg): Rebuild bb_for_insn before
+ splitting. Use split_all_insns; update_life_info_in_dirty_blocks.
+
+2002-05-16 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/unicosmk.h (TARGET_OS_CPP_BUILTINS): Fix typo.
+
+ * config/ia64/ia64.c (saveable_obstack): Do not declare.
+
+2002-05-16 Richard Henderson <rth@redhat.com>
+
+ * basic-block.h, bb-reorder.c, cfg.c, cfganal.c, cfgbuild.c,
+ cfgcleanup.c, cfglayout.c, cfgloop.c, cfgrtl.c, combine.c,
+ conflict.c, df.c, df.h, dominance.c, final.c, flow.c, function.c,
+ gcse.c, global.c, graph.c, haifa-sched.c, ifcvt.c, lcm.c,
+ local-alloc.c, loop.c, predict.c, print-rtl.c, profile.c,
+ recog.c, reg-stack.c, regclass.c, regmove.c, regrename.c,
+ reload1.c, reorg.c, resource.c, sbitmap.c, sched-deps.c,
+ sched-ebb.c, sched-rgn.c, sibcall.c, ssa-ccp.c, ssa-dce.c, ssa.c:
+ Revert "Basic block renumbering removal", and two followup patches.
+
+2002-05-16 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * lcm.c (optimize_mode_switching): Revert previous change.
+
+2002-05-16 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * sched-rgn.c (schedule_insns): Initialize large_region_blocks
+ with only extant block numbers.
+
+2002-05-16 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * lcm.c (optimize_mode_switching): Fix typo.
+
+2002-05-16 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * flow.c (calculate_global_regs_live): Queue blocks in program order.
+
+2002-05-16 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * doc/install.texi (Configuration): Document PWDCMD.
+
+2002-05-16 Dale Johannesen <dalej@apple.com>
+
+ * combine.c (cant_combine_insn_p): Reenable combinations
+ involving hard regs unless CLASS_LIKELY_SPILLED_P.
+
+2002-05-16 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (cb_register_builtins): Handle more built-ins
+ here rather than in gcc.c specs.
+ * gcc.c (cpp_unique_options): Move many built-ins to c-common.c.
+ (cpp_options): Pass -O flags even when only preprocessing.
+ * toplev.c (set_fast_math_flags): New prototype.
+ (fast_math_flags_set_p): New.
+ (set_no_fast_math_flags): Remove.
+ (decode_f_option): Update.
+ * toplev.h (set_fast_math_flags): Update.
+ (fast_math_flags_set_p): New.
+ (set_no_fast_math_flags): Remove.
+config:
+ * c4x/c4x.c (c4x_override_options): Update.
+
+2002-05-16 Zack Weinberg <zack@codesourcery.com>
+
+ * c-common.c (STDC_0_IN_SYSTEM_HEADERS, REGISTER_PREFIX):
+ Default-define here.
+ (builtin_define_with_value): Can now wrap the expansion in
+ quotation marks if such is wanted.
+ (cb_register_builtins): Update calls to builtin_define_with_value.
+ Define __REGISTER_PREFIX__, __USER_LABEL_PREFIX__, and __VERSION__
+ here.
+ (c_common_init): Set options->stdc_0_in_system_headers.
+ * c-lex.h: Update prototype of builtin_define_with_value.
+ * cppdefault.h: Remove default definitions of USER_LABEL_PREFIX
+ and REGISTER_PREFIX.
+
+ * cppinit.c (VERS, ULP, C, X): Kill.
+ (builtin_array): Remove entries for __VERSION__,
+ __USER_LABEL_PREFIX__, __REGISTER_PREFIX__, and
+ __HAVE_BUILTIN_SETJMP__. Make __STDC__ always a builtin, not
+ a constant.
+ (init_builtins): Kill off a bunch of now-dead code.
+ (COMMAND_LINE_OPTIONS): Remove -fleading-underscore and
+ -fno-leading-underscore.
+ (cpp_handle_option): Remove code to set user_label_prefix.
+ (cpp_post_options): Likewise.
+
+ * cpplib.h (struct cpp_options): Remove user_label_prefix.
+ (stdc_0_in_system_headers): New.
+ * cppmacro.c (builtin_macro): Check CPP_OPTION (pfile,
+ stdc_0_in_system_headers) too to decide the value of __STDC__.
+
+ * tradcpp.c (user_label_prefix): Kill.
+ (main): Remove code handling -f(no-)leading-underscore.
+ (initialize_builtins): Don't define __REGISTER_PREFIX__
+ or __USER_LABEL_PREFIX__.
+ (install_value): Wrap compound statement in dummy loop so the
+ macro works properly in an if statement.
+
+
+2002-05-16 Janis Johnson <janis187@us.ibm.com>
+
+ * loop.h (struct loop_info): Add member has_prefetch.
+ * loop.c (PREFETCH_CONDITIONAL): Change default to 1.
+ (prescan_loop): Initialize has_prefetch.
+ (struct prefetch_info): Change prefetch_in_loop and
+ prefetch_before_loop from bit fields to ints.
+ (emit_prefetch_instructions): Several small fixes.
+ (check_dbra_loop): Don't reverse loop that uses prefetch.
+
+2002-05-16 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * Makefile.in: Allow for PWDCMD to override hardcoded pwd.
+ * configure.in: Likewise.
+ * fixinc/check.tpl: Likewise.
+ * fixinc/fixinc.dgux: Likewise.
+ * fixinc/fixinc.svr4: Likewise.
+ * fixinc/fixinc.winnt: Likewise.
+ * fixinc/fixincl.sh: Likewise.
+ * fixproto: Likewise.
+ * configure: Regenerate.
+
+2002-05-16 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ Basic block renumbering removal:
+ * basic_block.h (struct basic_block_def): Renamed index to sindex,
+ added prev_bb and next_bb fields.
+ (n_basic_blocks): Renamed to num_basic_blocks.
+ (last_basic_block): New, index of last basic block.
+ (FOR_BB_BETWEEN, FOR_ALL_BB, FOR_ALL_BB_REVERSE): New macros for
+ traversing basic block chain.
+ (BLOCK_NUM): index -> sindex.
+ (create_basic_block_structure, create_basic_block): Declaration changed.
+ (debug_num2bb): Declare.
+ (expunge_block_nocompact): Declaration removed.
+ (link_block, unlink_block, compact_blocks): Declare.
+ * bb-reorder.c (make_reorder_chain, make_reorder_chain_1): Modified.
+ * cfg.c (entry_exit_blocks): Initialize new fields.
+ (clear_edges, alloc_block, expunge_block, cached_make_edge,
+ redirect_edge_pred, dump_flow_info, dump_edge_info,
+ alloc_aux_for_blocks, clear_aux_for_blocks, alloc_aux_for_edges,
+ free_aux_for_edges): Modified.
+ (link_block, unlink_block, compact_blocks, debug_num2bb): New.
+ (expunge_block_nocompact): Removed.
+ * cfganal.c (can_fallthru, mark_dfs_back_edges, flow_call_edges_add,
+ find_unreachable_blocks, create_edge_list, print_edge_list,
+ verify_edge_list, flow_edge_list_print, remove_fake_successors,
+ remove_fake_edges, flow_reverse_top_sort_order_compute,
+ flow_depth_first_order_compute, flow_preorder_transversal_compute,
+ flow_dfs_compute_reverse_init, flow_dfs_compute_reverse_add_bb,
+ flow_dfs_compute_reverse_execute): Modified.
+ * cfgbuild.c (make_edges, make_eh_edge, find_basic_blocks_1,
+ find_basic_blocks, find_many_sub_basic_blocks, find_sub_basic_blocks):
+ Modified.
+ * cfgcleanup.c (try_simplify_condjump, try_forward_edges,
+ merge_blocks_move_predecessor_nojumps,
+ merge_blocks_move_successor_nojumps, merge_blocks,
+ outgoing_edges_match, try_crossjump_to_edge, try_crossjump_bb,
+ try_optimize_cfg, delete_unreachable_blocks, cleanup_cfg): Modified.
+ * cfglayout.c (skip_insns_after_block, label_for_bb,
+ record_effective_endpoints, scope_to_insns_finalize,
+ fixup_reorder_chain, verify_insn_chain, cleanup_unconditional_jumps,
+ fixup_fallthru_exit_predecessor, cfg_layout_redirect_edge,
+ cfg_layout_duplicate_bb): Modified.
+ * cfgloop.c (flow_loops_cfg_dump, flow_loop_dump, flow_loops_dump,
+ flow_loop_entry_edges_find, flow_loop_exit_edges_find,
+ flow_loop_nodes_find, flow_loop_pre_header_find, flow_loop_scan,
+ flow_loops_find, flow_loop_outside_edge_p): Modified.
+ * cfgrtl.c (create_basic_block_structure, create_basic_block,
+ flow_delete_block, compute_bb_for_insn, split_block,
+ try_redirect_by_replacing_jump, redirect_edge_and_branch,
+ force_nonfallthru_and_redirect, tidy_fallthru_edge,
+ back_edge_of_syntactic_loop_p, split_edge, commit_one_edge_insertion,
+ commit_edge_insertions, commit_edge_insertions_watch_calls,
+ dump_bb, print_rtl_with_bb, verify_flow_info, purge_dead_edges,
+ purge_all_dead_edges): Modified.
+ * combine.c (combine_instructions, set_nonzero_bits_and_sign_copies,
+ try_combine, nonzero_bits, num_sign_bit_copies, get_last_value_validate,
+ get_last_value, reg_dead_at_p, distribute_notes, distribute_links):
+ Modified.
+ * conflict.c (conflict_graph_compute): Modified.
+ * df.c (FOR_ALL_BBS): Removed.
+ (df_bitmaps_alloc, df_bitmaps_free, df_alloc, df_analyse_1,
+ df_modified_p, df_analyse, df_refs_unlink, df_insn_modify,
+ df_dump, hybrid_search_bitmap, iterative_dataflow_sbitmap): Modified.
+ * df.h (DF_BB_INFO, DF_REF_BBNO): Modified.
+ * dominance.c (init_dom_info, calc_dfs_tree_nonrec, calc_dfs_tree,
+ calc_idoms, idoms_to_doms, calculate_dominance_info): Modified.
+ * final.c (compute_alignments, final_scan_insn): Modified.
+ * flow.c (verify_local_live_at_start, update_life_info,
+ update_life_info_in_dirty_blocks, free_basic_block_vars,
+ delete_noop_moves, calculate_global_regs_live,
+ initialize_uninitialized_subregs, allocate_bb_life_data,
+ regno_uninitialized, regno_clobbered_at_setjmp, mark_set_1,
+ mark_used_reg, count_or_remove_death_notes): Modified.
+ * function.c (thread_prologue_and_epilogue_insns): Modified.
+ * gcse.c (struct null_pointer_info): Change typo of current_block
+ to basic_block.
+ (gcse_main, alloc_gcse_mem, compute_local_properties, compute_sets,
+ oprs_unchanged_p, load_killed_in_block_p, record_last_reg_set_info,
+ compute_hash_table, alloc_rd_mem, handle_rd_kill_set, compute_kill_rd,
+ alloc_avail_expr_mem, expr_killed_p, compute_ae_kill,
+ expr_reaches_here_p_work, expr_reaches_here_p, handle_avail_expr,
+ classic_gcse, one_classic_gcse_pass, compute_transp, cprop,
+ one_cprop_pass, compute_pre_data, pre_expr_reaches_here_p_work,
+ pre_expr_reaches_here_p, insert_insn_end_bb, pre_edge_insert,
+ pre_delete, one_pre_gcse_pass, compute_transpout,
+ invalidate_nonnull_info, delete_null_pointer_checks_1,
+ free_code_hoist_mem, compute_code_hoist_vbeinout,
+ hoist_expr_reaches_here_p, hoist_code, one_code_hoisting_pass,
+ compute_ld_motion_mems, store_ops_ok, find_moveable_store,
+ compute_store_table, build_store_vectors, insert_insn_start_bb,
+ insert_store, replace_store_insn, free_store_memory, store_motion):
+ Modified.
+ * global.c (global_alloc, global_conflicts, mark_elimination,
+ build_insn_chain): Modified.
+ * graph.c (print_rtl_graph_with_bb): Modified.
+ * haifa-sched.c (sched_init): Modified.
+ * ifcvt.c (SET_ORIG_INDEX, ORIG_INDEX): Removed.
+ (find_if_block, find_cond_trap, find_if_case_1, find_if_case_2,
+ if_convert): Modified.
+ * lcm.c (compute_antinout_edge, compute_earliest, compute_laterin,
+ compute_insert_delete, pre_edge_lcm, compute_available,
+ compute_farthest, compute_nearerout, compute_rev_insert_delete,
+ pre_edge_rev_lcm, make_preds_opaque, optimize_mode_switching):
+ Modified.
+ * local-alloc.c (alloc_qty, local_alloc, update_equiv_regs): Modified.
+ * loop.c (loop_dump_aux): Modified.
+ * predict.c (combine_predictions_for_insn, estimate_probability,
+ last_basic_block_p, process_note_prediction, process_note_predictions,
+ note_prediction_to_br_prob, propagate_freq, counts_to_freqs,
+ expensive_function_p, estimate_bb_frequencies,
+ compute_function_frequency): Modified.
+ * print-rtl.c (print_rtx): Modified.
+ * profile.c (GCOV_INDEX_TO_BB, BB_TO_GCOV_INDEX, instrument_edges,
+ get_exec_counts, compute_branch_probabilities, compute_checksum,
+ branch_prob, find_spanning_tree): Modified.
+ * recog.c (split_all_insns, peephole2_optimize): Modified.
+ * reg-stack.c (reg_to_stack, convert_regs_entry, compensate_edge,
+ convert_regs_1, convert_regs_2, convert_regs): Modified.
+ * regclass.c (scan_one_insn, regclass): Modified.
+ * regmove.c (mark_flags_life_zones, regmove_optimize,
+ combine_stack_adjustments): Modified.
+ * regrename.c (regrename_optimize, copyprop_hardreg_forward): Modified.
+ * reload1.c (reload, reload_combine, copy_eh_notes): Modified.
+ * reorg.c (dbr_schedule): Modified.
+ * resource.c (find_basic_block, init_resource_info): Modified.
+ * sbitmap.c (sbitmap_intersection_of_succs,
+ sbitmap_intersection_of_preds, sbitmap_union_of_succs,
+ sbitmap_union_of_preds): Modified.
+ * sched-deps.c (init_dependency_caches): Modified.
+ * sched-ebb.c (schedule_ebbs): Modified.
+ * sched-rgn.c (is_cfg_nonregular, build_control_flow, debug_regions,
+ find_rgns, compute_trg_info, init_regions, schedule_insns): Modified.
+ * sibcall.c (optimize_sibling_and_tail_recursive_call): Modified.
+ * ssa-ccp.c (examine_flow_edges, optimize_unexecutable_edges,
+ ssa_ccp_substitute_constants, ssa_ccp_df_delete_unreachable_insns,
+ ssa_const_prop): Modified.
+ * ssa-dce.c (set_control_dependent_block_to_edge_map_,
+ find_control_dependence, find_pdom, ssa_eliminate_dead_code): Modified.
+ * ssa.c (remove_phi_alternative, find_evaluations,
+ compute_dominance_frontiers_1, compute_iterated_dominance_frontiers,
+ insert_phi_node, rename_block, convert_to_ssa, eliminate_phi,
+ make_regs_equivalent_over_bad_edges,
+ make_equivalent_phi_alternatives_equival,
+ compute_conservative_reg_partition,
+ coalesce_regs_in_successor_phi_nodes, compute_coalesced_reg_partition,
+ rename_equivalent_regs, convert_from_ssa, for_each_successor_phi):
+ Modified.
+
+2002-05-16 Mark Mitchell <mark@codesourcery.com>
+
+ * cfgrtl.c (purge_dead_edges): Correct handling of EDGE_EH.
+
+2002-05-16 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/arm/arm.c (arm_rtx_costs): Check for RTX being a
+ SYMBOL_REF before calling CONSTANT_POOL_ADDRESS_P.
+ (arm_adjust_cost): Check for RTX being a SYMBOL_REF before
+ calling CONSTANT_POOL_ADDRESS_P.
+ * config/arm/arm.h (TARGET_CPU_CPP_BUILTINS): Fix typo in code
+ to decide whether to define __arm__ or __thumb.
+ (THUMB_GO_IF_LEGITIMATE_ADDRESS): Check for RTX being a
+ SYMBOL_REF before calling CONSTANT_POOL_ADDRESS_P.
+
+2002-05-16 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * config/arc/arc.h (CPP_PREDEFINES): Remove.
+ (CPP_SPEC): Update.
+ (TARGET_CPU_CPP_BUILTINS): New.
+
+2002-05-16 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpphash.h (cpp_macro): Move here, and make expansion a union.
+ * cppmacro.c (cpp_macro): Remove.
+ (enter_macro_context, replace_args, warn_of_redefinition,
+ _cpp_create_definition, cpp_macro_definition): Update.
+
+2002-05-16 Jason Merrill <jason@redhat.com>
+
+ * config/mips/mips.c (mips_output_external): Don't do sdata
+ optimization for a variable with DECL_COMDAT set.
+
+2002-05-15 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/altivec.h: Cleanups for tighter typechecking.
+ Cleanups for accepting modifiers on pointers.
+ Fix predicate typos.
+ Allow long pointers as well as int pointers.
+
+2002-05-15 Richard Henderson <rth@redhat.com>
+
+ * varasm.c (merge_weak): Remove special case for extern and common.
+
+2002-05-15 Matt Hiller <hiller@redhat.com>
+
+ * testsuite/gcc.c-torture/compile/20000804-1.x: Don't return 1 if
+ XFAILing.
+ * testsuite/gcc.c-torture/compile/20001226-1.x: Ditto.
+ * testsuite/gcc.c-torture/compile/920520-1.x: Ditto.
+ * testsuite/gcc.c-torture/compile/mipscop-1.x: XFAIL for now.
+ * testsuite/gcc.c-torture/compile/mipscop-2.x: Ditto.
+ * testsuite/gcc.c-torture/compile/mipscop-3.x: Ditto.
+ * testsuite/gcc.c-torture/compile/mipscop-4.x: Ditto.
+
+2002-05-15 Aldy Hernandez <aldyh@redhat.com>
+
+ * reload1.c (forget_old_reloads_1): Do not use subreg offset.
+
+2002-05-15 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.md ("altivec_mtvscr"): Set VSCR register.
+ ("altivec_mfvscr"): Read from VSCR.
+
+ Add vscr sets for the following insns: altivec_vctuxs,
+ altivec_vaddubs, altivec_vaddsbs, altivec_vadduhs,
+ altivec_vaddshs, altivec_vadduws, altivec_vaddsws, altivec_vctsxs,
+ altivec_vmhaddshs, altivec_vmhraddshs, altivec_vmsumuhs,
+ altivec_vmsumshs, altivec_vpkuhss, altivec_vpkshss,
+ altivec_vpkuwss, altivec_vpkswss, altivec_vpkuhus,
+ altivec_vpkshus, altivec_vpkuwus, altivec_vpkswus,
+ altivec_vsububs, altivec_vsubsbs, altivec_vsubuhs,
+ altivec_vsubshs, altivec_vsubuws, altivec_vsubsws,
+ altivec_vsum4ubs, altivec_vsum4sbs, altivec_vsum4shs,
+ altivec_vsum2sws, altivec_vsumsws.
+
+ * config/rs6000/rs6000.h: Add VSCR fixed register.
+ (CALL_REALLY_USED_REGISTERS): Add vscr.
+ (CALL_USED_REGISTERS): Same.
+ (FIXED_REGISTERS): Same.
+ (REG_ALLOC_ORDER): Same.
+ (reg_class): Add VSCR_REGS.
+ (REG_CLASS_NAMES): Same.
+ (REG_CLASS_CONTENTS): Same.
+ (VSCR_REGNO): New.
+ (REGISTER_NAMES): Add vscr.
+ (DEBUG_REGISTER_NAMES): Same.
+ (ADDITIONAL_REGISTER_NAMES): Same.
+ (FIRST_PSEUDO_REGISTER): Increment.
+ (CONDITIONAL_REGISTER_USAGE): Set VSCR as a global register.
+
+2002-05-15 Jakub Jelinek <jakub@redhat.com>
+
+ * fold-const.c (fold): Fix a typo.
+
+2002-05-15 Eric Botcazou <ebotcazou@multimania.com>
+
+ * fold-const.c (fold) [LT_EXPR]: Move the transformation of a
+ comparison against the highest or lowest integer value before
+ the 'X >= CST to X > (CST - 1)' and 'X < CST to X <= (CST - 1)'
+ transformation and that of an unsigned comparison against 0
+ right after.
+
+2002-05-15 Richard Henderson <rth@redhat.com>
+
+ * varasm.c (merge_weak): Error for any weakening after definition.
+ Adjust weakening after use warning to catch more cases.
+ (assemble_alias): Set TREE_USED and TREE_ASM_WRITTEN consistently.
+ * config/alpha/alpha.c (alpha_encode_section_info): Do not abort.
+
+Wed May 15 10:38:27 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * invoke.texi (-malign-double): Re-add lost warning.
+
+ * i386-protos.h (x86_output_mi_thunk): Declare.
+ * unix.h (ASM_OUTPUT_MI_THUNK): Move offline to ...
+ * i386.c (x86_output_mi_thunk): ... here; handle 64bits.
+
+ * dwarf2out.c (output_call_frame_info): Do not skip unwind info
+ when flag_asynchronous_unwind_tables is set.
+
+ * flags.h (flag_reorder_functions): Declare.
+ * function.c (prepare_function_start): Initialize frequnecy.
+ * params.def (HOT_BB_COUNT_FRACTION, HOT_BB_FREQUENCY_FRACTION): New.
+ * Makefile.in (predict.o): Add dependency on target.h and params.h
+ * defaults.h (HOT_TEXT_SECTION_NAME,
+ UNLIKELY_EXECUTED_TEXT_SECTION_NAME): New macros.
+ * predict.c (choose_function_section): New function.
+ (estimate_bb_frequencies): Use it.
+ * toplev.c (flag_reorder_functions): New global variable.
+ (lang_independent_options): New.
+ (parse_options_and_default_flags): Set.
+ * varasm.c (assemble_start_function): Bypass functdion alignment
+ for never executed functions.
+ * invoke.texi (-freorder-blocks, -freorder-functions): Document.
+ (param hot-bb-count-fraction, hot-bb-frequency-fraction): New.
+ * tm.texi (HOT_TEXT_SECTION_NAME, UNLIKELY_EXECUTED_TEXT_SECTION_NAME):
+ Document.
+
+ Thu Jan 3 21:52:09 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * predict.c: Inlude profile.h
+ (MIN_COUNT): Rename to MIN_COUNT_FRACTION
+ (maybe_hot_bb_p, probably_cold_bb_p, probably_never_executed_bb_p):
+ Use the information about maximal counter in the program.
+
+ Thu Dec 20 22:14:00 CET 2001 Jan Hubicka <jh@suse.cz>
+
+ * basic-block.h (maybe_hot_bb_p, probably_cold_bb_p,
+ probably_never_executed_bb_p): New functions.
+ * cfgcleanup.c (outgoing_edges_match): Use them.
+ * predict.c (MIN_COUNT, MIN_FREQUENCY): New macros.
+ (maybe_hot_bb_p, probably_cold_bb_p,
+ probably_never_executed_bb_p): New functions.
+
+ * function.h (function): Add new field function_frequency.
+ * predict.c (compute_function_frequency): New function.
+ (estimate_probability): Call it.
+
+2002-03-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR optimization/5172, optimization/5200
+ * gcse.c (gcse_main): Disable store_motion.
+
+2002-05-14 Zack Weinberg <zack@codesourcery.com>
+
+ * c-parse.in (MODIFIED_WCHAR_TYPE): New macro.
+ (c_common_nodes_and_builtins): Use it.
+ (builtin_define_with_value): New function.
+ (cb_register_builtins): Define __SIZE_TYPE__,
+ __PTRDIFF_TYPE__, __WCHAR_TYPE__, and __WINT_TYPE__ here,
+ using builtin_define_with_value. Use consistent notation when
+ defining __GXX_WEAK__.
+ (WCHAR_TYPE_SIZE): Don't redefine.
+ (combine_strings): Don't use WCHAR_TYPE_SIZE.
+
+ * cppdefault.h: Don't provide defaults for SIZE_TYPE,
+ PTRDIFF_TYPE, WCHAR_TYPE, or WINT_TYPE.
+ * cppinit.c (builtin_array): Remove entries for __SIZE_TYPE__ etc.
+ * tradcpp.c (initialize_builtins): Likewise.
+ * gcc.c (cpp_unique_options): Don't muck with __WCHAR_TYPE__.
+
+ * c-lex.h (builtin_define_with_value): Prototype.
+ * system.h: Poison NO_BUILTIN_SIZE_TYPE, NO_BUILTIN_WCHAR_TYPE,
+ NO_BUILTIN_PTRDIFF_TYPE, and NO_BUILTIN_WINT_TYPE.
+ * doc/tm.texi: Remove mention of NO_BUILTIN_SIZE_TYPE etc.
+
+ * config/avr/avr.h, config/h8300/h8300.h, config/i386/i386.h,
+ config/ia64/ia64.h, config/mips/dec-osf1.h, config/mips/iris6.h,
+ config/mips/linux.h, config/mips/mips.h, config/mips/netbsd.h,
+ config/mips/osfrose.h, config/mips/sni-svr4.h, config/rs6000/aix51.h,
+ config/s390/linux.h, config/sh/sh.h, config/sh/sh64.h,
+ config/sparc/linux64.h, config/sparc/netbsd-elf.h,
+ config/sparc/sol2-bi.h, config/sparc/sparc.h:
+ Do not define NO_BUILTIN_SIZE_TYPE etc. Remove all references
+ to __SIZE_TYPE__ etc from all spec strings. When this makes
+ extra specs empty, delete them.
+
+2002-05-14 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.c (override_options): Override TARGET_JUMP_IN_DELAY when scheduling
+ for PA8000 or generating dwarf2 call frame information.
+ (output_call): Remove DO_FRAME_NOTES check from return pointer
+ optimization.
+ (following_call): Return 0 when scheduling for PA8000 or generating
+ dwarf2 call frame information. Revise comment.
+
+2002-05-14 Neil Booth <neil@daikokuya.demon.co.uk>
+
+config/alpha:
+ * alpha.h (TARGET_CPU_CPP_BUILTINS): Define __IEEE_FP
+ and __IEEE_FP_INEXACT as appropriate.
+ (CPLUSPLUS_CPP_SPEC): Don't define __cplusplus.
+ (CPP_SPEC): Remove ieee defines.
+ * freebsd.h, netbsd.h: Remove ieee defines and cpp_cpu.
+
+2002-05-14 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (ix86_save_reg): Make regno unsigned.
+ (ix86_safe_length, ix86_safe_length_prefix, ix86_safe_memory): Kill.
+
+2002-05-14 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * arm/arm.h (TARGET_CPU_CPP_BUILTINS): Define.
+ (CPP_SPEC): Update.
+ (CPP_APCS_PC_SPEC, CPP_APCS_PC_DEFAULT_SPEC,
+ CPP_FLOAT_SPEC, CPP_FLOAT_DEFAULT_SPEC, CPP_ENDIAN_SPEC,
+ CPP_ENDIAN_DEFAULT_SPEC, CPP_INTERWORK_DEFAULT_SPEC,
+ CPP_INTERWORK_SPEC, CPP_PREDEFINES): Remove.
+ (EXTRA_SPECS): Update.
+ * arm/conix-elf.h, arm/linux-elf.h, arm/netbsd.h, arm/riscix.h,
+ arm/riscix1-1.h, arm/rtems-elf.h, arm/semiaof.h, arm/unknown-elf.h,
+ arm/unknown-elf-oabi.h, arm/vxarm.h: Remove CPP_PREDEFINES and
+ define TARGET_OS_CPP_BUILTINS if necessary.
+
+2002-05-14 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * gcc.c (cpp_options): Must pass -m* and -f* options
+ to the front end even when only preprocessing.
+ (cc1_options): Remove redundant -lang-c.
+ * tradcpp.c (main): Ignore -m options.
+objc:
+ * lang-specs.h: Similarly.
+
+2002-05-14 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (transform_3): Add code for transformation
+ `(A,B,...)+C -> A+C,B,...'.
+
+Tue May 14 12:48:22 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * final.c (end_final): Do not output profile_arcs constructor, when
+ no functions are instrumented.
+
+Tue May 14 12:38:30 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (testsi to testqi_zext_1 splitter): Fix typo.
+
+2002-05-14 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/install.texi: Remove special markup originally required for
+ HTML generation with texi2html.
+
+2002-05-14 Andreas Schwab <schwab@suse.de>
+
+ * config/ia64/sysv4.h (DO_SELECT_SECTION): Factored out of
+ SELECT_SECTION.
+ (UNIQUE_SECTION): Define to get small data correctly.
+
+ * varasm.c (resolve_unique_section): Add third parameter
+ flag_function_or_data_sections and use it instead of
+ flag_function_sections.
+ (assemble_start_function): Pass flag_function_sections.
+ (asm_emit_uninitialised): Pass flag_data_sections.
+ (assemble_variable): Likewise.
+
+2002-05-14 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.md: Use define_constants for unspec numbers.
+ * config/i386/i386.c: Likewise.
+
+2002-05-13 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * doc/contrib.texi: Update my entry.
+
+2002-05-13 Mark Mitchell <mark@codesourcery.com>
+
+ * fixinc/inclhack.def (winidss_valist): Limit applicability.
+ * fixinc/fixincl.x: Regenerated.
+ * fixinc/tests/base/math.h: Update.
+ * fixinc/tests/base/testing.h: Likewise.
+
+2002-05-13 Zack Weinberg <zack@codesourcery.com>
+
+ * genattr.c (gen_attr): Don't emit a comma after the last
+ enumerator.
+
+2002-05-13 Richard Henderson <rth@redhat.com>
+
+ * cfgrtl.c (purge_dead_edges): Handle abnormal call edges created
+ by non-local gotos.
+ * recog.c (peephole2_optimize): Likewise.
+
+2002-05-13 Andris Pavenis <pavenis@lanet.lv>
+
+ * cppfiles.c (open_file): Change mode (DJGPP only) of redirected
+ input to O_BINARY.
+
+2002-05-13 Jeffrey A Law (law@redhat.com)
+
+ * flow.c (invalidate_mems_from_autoinc): Rewrite to use for_each_rtx.
+ Update prototype and callers.
+ (propagate_one_insn): Stack pointer adjustments kill MEMs on
+ the mem_set_list which reference the stack pointer, as do
+ calls to constant functions as they may clobber outgoing
+ argument space.
+
+ * i386.c (ia32_multipass_dfa_lookahead): Prototype.
+
+ * i386.c (TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD): Define.
+ (ia32_multipass_dfa_lookahead): New function.
+
+2002-05-13 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * gcc.c (SWITCH_TAKES_ARG): Remove 'V'.
+ (translate_options): Remove 'V'.
+ (process_command): Similarly.
+doc:
+ * invoke.texi: Remove documentation of 'V'.
+
+2002-05-13 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/linux.h: Revert 2002-04-22 changes.
+
+2002-05-13 Scott Marks <SMarks@mobile-mind.com>
+
+ * config/fr30/fr30.md: Only allow splits of immediate loads
+ if the destination is a register.
+
+2002-05-13 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in (c-common.o, cppinit.o): Update.
+ * c-common.c: Include except.h.
+ (cb_register_builtins): Handle __USING_SJLJ_EXCEPTIONS__.
+ Call TARGET_CPU_CPP_BUILTINS and TARGET_OS_CPP_BUILTINS.
+ * cppinit.c (__USING_SJLJ_EXCEPTIONS): Not here.
+ * defaults.h (TARGET_OS_CPP_BUILTINS, TARGET_CPU_CPP_BUILTINS,
+ CPP_PREDEFINES): Handle here.
+config:
+ * alpha/alpha-interix.h, alpha/gnu.h, alpha/linux.h,
+ alpha/netbsd.h, alpha/openbsd.h, alpha/osf.h, alpha/unicosmk.h,
+ alpha/vms.h, alpha/vxworks.h: Remove CPP_PREDEFINES, define
+ TARGET_OS_CPP_BUILTINS.
+ * alpha/alpha.h (TARGET_CPU_CPP_BUILTINS): Define.
+ (CPP_SPEC, EXTRA_SPECS): Update.
+ (CPP_AM_BWX_SPEC, CPP_AM_MAX_SPEC, CPP_AM_FIX_SPEC,
+ CPP_AM_CIX_SPEC, CPP_IM_EV4_SPEC, CPP_IM_EV5_SPEC,
+ CPP_IM_EV6_SPEC, CPP_CPU_EV4_SPEC, CPP_CPU_EV5_SPEC,
+ CPP_CPU_EV56_SPEC, CPP_CPU_PCA56_SPEC, CPP_CPU_EV6_SPEC,
+ CPP_CPU_EV67_SPEC, CPP_CPU_DEFAULT_SPEC, CPP_CPU_SPEC): Remove.
+doc:
+ * tm.texi (TARGET_REGISTER_CPP_BUILTINS): Remove.
+ (TARGET_OS_CPP_BUILTINS, TARGET_CPU_CPP_BUILTINS): Define.
+
+2002-05-12 Zack Weinberg <zack@codesourcery.com>
+
+ * emit-rtl.c (global_rtl): Update comment.
+ (const_double_htab, const_double_htab_hash,
+ const_double_htab_hash, lookup_const_double): New.
+ (const_int_htab_hash, const_int_htab_eq): Remove const
+ qualifiers, which cause tons of warnings with RTL checking on.
+ (gen_rtx_CONST_DOUBLE): Deleted.
+ (const_double_from_real_value): New function - bears some
+ resemblance to the former immed_real_const_1.
+ (immed_double_const): Moved here from varasm.c and
+ simplified.
+ (gen_rtx_REG): Make REGNO unsigned to squelch warnings.
+ (gen_rtx_SUBREG): Use gen_rtx_raw_SUBREG.
+ (gen_rtx): Use immed_double_const.
+ (init_emit_once): Initialize the const_double_htab. Use
+ REAL_VALUE_FROM_INT where possible. Can now use
+ CONST_DOUBLE_FROM_REAL_VALUE when setting up const_tiny_rtx.
+ * varasm.c (struct varasm_status): Remove x_const_double_chain.
+ (const_double_chain, immed_real_const, clear_const_double_mem): Delete.
+ (immed_double_const, immed_real_const_1): Moved to emit-rtl.c.
+ (init_varasm_status, mark_varasm_status): Don't touch
+ x_const_double_chain.
+
+ * output.h: Delete prototype for clear_const_double_mem.
+ * real.h: Make REAL_VALUE_TYPE a macro again. Remove leading
+ '0' slot from all CONST_DOUBLE_FORMAT definitions. Prototype
+ const_double_from_real_value, not immed_real_const_1, and use
+ it to define CONST_DOUBLE_FROM_REAL_VALUE. Define new macro
+ CONST_DOUBLE_ATOF.
+ * rtl.h (CONST_DOUBLE_CHAIN): Kill.
+ (CONST_DOUBLE_LOW, CONST_DOUBLE_HIGH): Adjust.
+ (gen_rtx_CONST_DOUBLE, immed_real_const): Delete prototypes.
+ (gen_rtx_REG): Second arg is unsigned.
+
+ * gengenrtl.c (special_rtx): Take out CONST_DOUBLE.
+ (excluded_rtx): New, return true for CONST_DOUBLE.
+ (genmacro): Write nothing for excluded codes.
+ * combine.c (combine_simplify_rtx): Use CONST_DOUBLE_FROM_REAL_VALUE.
+ * expr.c (expand_expr): Likewise.
+ * ggc-common.c (ggc_mark_rtx_children_1): Don't mark the
+ CONST_DOUBLE_CHAIN.
+ * toplev.c (rest_of_compilation): Don't call
+ clear_const_double_mem.
+
+ * config/rs6000/rs6000.c (rs6000_float_const): Delete.
+ (rs6000_hash_constant): Remove CONST_DOUBLE special case.
+ (toc_hash_eq): Remove CONST_DOUBLE and LABEL_REF special cases.
+ * config/rs6000/rs6000-protos.h: Don't prototype rs6000_float_const.
+ * config/c4x/c4x.md, config/rs6000/rs6000.md: Use CONST_DOUBLE_ATOF.
+ * config/dsp16xx/dsp16xx.md, config/mips/mips.md,
+ config/pa/pa.md: Use CONST_DOUBLE_FROM_REAL_VALUE.
+ * config/sparc/sparc.md, config/sparc/sparc.c: Use immed_double_const.
+
+2002-05-12 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * mips/iris6.h (CPLUSPLUS_CPP_SPEC): Define.
+
+2002-05-12 Tom Tromey <tromey@redhat.com>
+
+ * tree.h (copy_node): Don't mention TREE_PERMANENT.
+
+2002-05-12 Zack Weinberg <zack@codesourcery.com>
+
+ * gensupport.c (n_comma_elts): Moved here from genattrtab.c.
+ (scan_comma_elt): New function. Accepts whitespace in comma lists.
+ * gensupport.h: Prototype new routines.
+ * genattr.c (gen_attr): Use scan_comma_elt. Avoid unnecessary
+ use of printf.
+ * genattrtab.c (n_comma_elts): Moved to gensupport.c.
+ (next_comma_elt): Use scan_comma_elt.
+
+ * config/i386/i386.md: Use new attribute notation to break up
+ long lines in define_attr forms.
+
+2002-05-12 Richard Henderson <rth@redhat.com>
+
+ * expr.c (compress_float_constant): New.
+ (emit_move_insn): Use it.
+ (float_extend_from_mem): New.
+ (init_expr_once): Initialize it.
+ * real.c (exact_real_truncate): New.
+
+ * config/i386/i386.h (CONST_COSTS): Assume CONST_DOUBLE gets
+ dropped into memory; penalize for size.
+ (RTX_COSTS): FLOAT_EXTEND is free.
+ * config/i386/i386.md (extendsfdf2, extendsfxf2, extendsftf2,
+ extenddfxf2, extenddftf2): Accept constants and drop them to memory.
+
+2002-05-12 Richard Henderson <rth@redhat.com>
+
+ * profile.h (profile_info): Add missing extern to declaration.
+ * profile.c (profile_info): Define it.
+
+2002-05-11 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa/pa32-regs.h (HARD_REGNO_MODE_OK): Revise sets of general registers
+ used for DImode and TImode.
+
+2002-05-11 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpplex.c (_cpp_lex_direct): When in a directive at EOF
+ fake a newline.
+
+2002-05-11 Zack Weinberg <zack@codesourcery.com>
+
+ * config/rs6000/rs6000.c (rs6000_default_long_calls,
+ rs6000_longcall_switch, rs6000_set_default_type_attributes): New.
+ (TARGET_SET_DEFAULT_TYPE_ATTRIBUTES): Set it.
+ (rs6000_override_options): Handle -m(no-)longcall.
+ (init_cumulative_args, output_mi_thunk): Check for both
+ longcall and shortcall attributes on the function.
+ (rs6000_attribute_table): Add "shortcall".
+ (rs6000_handle_longcall_attribute): Update comment.
+ (altivec_expand_unop_builtin, altivec_expand_binop_builtin,
+ altivec_expand_ternop_builtin): Add default clauses to switches
+ to silence warnings.
+
+ * config/rs6000/rs6000.h: Declare rs6000_longcall_switch and
+ rs6000_default_long_calls. Define REGISTER_TARGET_PRAGMAS.
+ (TARGET_OPTIONS): Add longcall and no-longcall.
+
+ * config/rs6000/rs6000.md (call_nonlocal_sysv,
+ call_value_nonlocal_sysv): Split by alternatives. One pair
+ accepts only SYMBOL_REFs and rejects if CALL_LONG is set in
+ the call cookie. The other pair accepts only LR/CTR and has
+ no restriction.
+
+ * config.gcc (rs6000-*-* | powerpc*-*-* trailer stanza):
+ Set c_target_objs, cxx_target_objs; add t-rs6000-c-rule to
+ tmake_file.
+ * config/rs6000/rs6000-c.c: New file.
+ * config/rs6000/t-rs6000-c-rule: New file.
+ * config/rs6000/rs6000-protos.c: Add multiple-include guard.
+ Prototype rs6000_pragma_longcall.
+
+ * doc/extend.texi: Document shortcall attribute.
+ * doc/invoke.texi: Document -mlongcall, -mno-longcall.
+
+2002-05-11 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * reorg.c (dbr_schedule): Remove unnecessary test.
+
+Sat May 11 14:34:35 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (testsi to testqi spliters): New.
+
+ 2002-01-14 Josef Zlomek <zlomek@matfyz.cz>
+
+ cfg.c (dump_edge_info): added dumping of EDGE_CAN_FALLTHRU.
+
+ Wed Jan 9 2002 Josef Zlomek <zlomj9am@artax.karlin.mff.cuni.cz>
+
+ * basic-block.h: New flag EDGE_CAN_FALLTHRU
+ * cfganal.c (set_edge_can_fallthru_flag): New function; marks the edges
+ that can be made fallthru.
+
+ Mon Nov 12 16:25:53 CET 2001 Jan Hubicka <jh@suse.cz>
+
+ * cfglayout.c (cleanup_unconditional_jumps): New static function.
+ (cfg_layout_initialize): Use it.
+
+2002-05-11 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (avr_mcu_types): Update supported devices.
+ * config/avr/avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS): Likewise.
+ * config/avr/t-avr (MULTILIB_MATCHES): Likewise.
+
+2002-05-11 Kazu Hirata <kazu@cs.umass.edu>
+
+ * dbxout.c: Fix formatting.
+ * dependence.c: Likewise.
+ * df.c: Likewise.
+ * diagnostic.c: Likewise.
+ * doloop.c: Likewise.
+ * dominance.c: Likewise.
+ * doschk.c: Likewise.
+ * dwarf2asm.c: Likewise.
+ * dwarf2out.c: Likewise.
+ * dwarfout.c: Likewise.
+
+2002-05-10 Richard Henderson <rth@redhat.com>
+
+ * final.c (end_final): Tidy whitespace. Don't honor flag_pack_struct.
+ Convert integers constants as needed. Replace "nwords" field with
+ "sizeof_bb".
+ (final): Save profile data if cfun->arc_profile, not profile_arc_flag.
+ * function.h: Fix typo in comment.
+ * libgcc2.c (struct bb): Replace "nwords" with "sizeof_bb".
+
+2002-05-10 Roger Sayle <roger@eyesopen.com>
+
+ * fold-const.c (build_range_check): Optimize (c>=1) && (c<=127)
+ into the equivalent (signed char)c > 0.
+
+2002-05-10 Janis Johnson <janis187@us.ibm.com>
+
+ * loop.c: (PREFETCH_EXTREME_DIFFERENCE, PREFETCH_BEFORE_LOOP): New.
+ (PREFETCH_CONDITIONAL): Renamed from PREFETCH_NOT_ALWAYS.
+ (struct prefetch_info): Fix spelling of member bytes_accessed.
+ (emit_prefetch_instructions): Make dump messages more regular;
+ restructure code to add more dump messages; use new macros for
+ heuristics. (There are no code generation changes in any of this).
+
+2002-05-10 David S. Miller <davem@redhat.com>
+
+ * rtl.h (INSN_ANNULLED_BRANCH_P): Accept INSN too, update comment.
+ (struct rtx_def): Update unchanging flag comment.
+ * doc/rtl.texi (INSN_ANNULLED_BRANCH_P): Update description.
+ * reorg.c (delete_from_delay_list): INSN_ANNULLED_BRANCH_P needs
+ to be handled to INSN too.
+ (dbr_schedule): Likewise.
+ * resource.c (next_insn_no_annul): Likewise.
+
+ * cse.c (rtx_cost): Remove multiplication by power of 2 special
+ casing.
+
+2002-05-14 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/install.texi (Specific, *-*-solaris2*): Update passus on
+ setting CONFIG_SHELL to /bin/ksh and remove alternate trick to
+ (possibly) work around broken /bin/sh.
+
+2002-05-10 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * config/mips/t-iris6 (SHLIB_SLIBDIR_SUFFIXES): Use mabi=64 and
+ . as N64/N32 libgcc_s.so subdirs.
+
+2002-05-10 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.md: Use define_constants for unspec numbers.
+
+ * rtl.h (struct rtx_def): Document unchanging and in_struct flags
+ more accurately.
+ (INSN_ANNULLED_BRANCH_P): Only valid for JUMP_INSN and CALL_INSN, fix
+ comment.
+ (INSN_FROM_TARGET_P): Valid also for CALL_INSN.
+ * doc/rtl.texi: Document these macros more accurately.
+ * recog.c (whole file): Only mess with INSN_ANNULLED_BRANCH_P for
+ JUMP_INSNs and CALL_INSNs.
+ * resource.c (whole file): Only mess with INSN_ANNULLED_BRANCH_P
+ or INSN_FROM_TARGET_P if the code is appropriate.
+
+2002-05-10 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (print_operand): Check that addr is a SYMBOL_REF
+ before using SYMBOL_REF_FLAG (addr).
+
+ * config/avr/avr-protos.h (avr_io_address_p): Declare.
+ * config/avr/avr.c (io_address_p): Rename to avr_io_address_p.
+ Make non-static. Update all callers.
+ * config/avr/avr.md (*cbi, *sbi, *sbix_branch, *sbix_branch_bit7):
+ New insns to clear/set/test a single bit in I/O address space.
+
+2002-05-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * rtl.h (ENABLE_RTL_FLAG_CHECKING): Also check for gcc >= 2.7.
+
+2002-05-09 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in: Update.
+ * c-common.c (flag_iso, flag_undef, cb_register_builtins,
+ builtin_define_std): New.
+ (c_common_init): Register CPP builtins callback.
+ * c-common.h (flag_iso, flag_undef): New.
+ * c-decl.c (c_decode_option): Set flag_iso and flag_undef.
+ * c-lex.c: Don't include target.h.
+ (cb_register_builtins): Move to c-common.c.
+ (init_c_lex): Don't register hook here.
+ * c-lex.h (builtin_define, builtin_assert, builtin_define_std): New.
+ (cpp_define, cpp_assert): Remove.
+ * gcc.c (cc1_options): Pass -undef to front end.
+ * target-def.h (TARGET_REGISTER_CPP_BUILTINS): Remove.
+ (TARGET_INITIALIZER): Update.
+ * target.h (struct cpp_reader): Don't predeclare.
+ (struct gcc_target): Remove cpp builtin hook.
+ * tree.c (default_register_cpp_builtins): Remove.
+doc:
+ * tm.texi: Update.
+
+2002-05-09 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppexp.c (_cpp_expand_op_stack): Set op_limit.
+
+2002-05-09 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * config/mips/t-iris6 (SHLIB_SLIBDIR_SUFFIXES): Define.
+ (SHLIB_LINK, SHLIB_INSTALL): Adjust.
+
+2002-05-09 Jakub Jelinek <jakub@redhat.com>
+
+ * config/sparc/t-linux64 (SHLIB_MAPFILES): Set.
+ * config/sparc/libgcc-sparc-glibc.ver: New file.
+ * config/cris/t-linux (SHLIB_MAPFILES): Remove.
+ * mklibgcc.in: Preprocess SHLIB_MAPFILES with ml flags.
+
+2002-05-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/6429
+ * Makefile.in (libgcc.mk): Pass SHLIB_SLIBDIR_SUFFIXES to mklibgcc.
+ * mklibgcc.in: If SHLIB_SLIBDIR_SUFFIXES is defined, put libgcc_s
+ shared libraries into multilib dirs, with SONAME libgcc_s.so.1 for
+ base multilibs.
+ * config/t-slibgcc-elf-ver (SHLIB_LINK): Adjust for the above.
+ * config/t-slibgcc-sld (SHLIB_LINK): Likewise.
+ * config/sparc/t-linux64 (SHLIB_SLIBDIR_SUFFIXES): Define.
+ * config/sparc/t-sol2-64 (SHLIB_SLIBDIR_SUFFIXES): Define.
+
+2002-05-09 Richard Henderson <rth@redhat.com>
+
+ * config/ia64/ia64.md: Use define_constants for unspec numbers.
+ * config/ia64/ia64.c: Likewise.
+
+2002-05-09 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips.c (mips_add_large_offset_to_sp): Remove FILE arg.
+ (save_restore_insns): Likewise.
+ (mips_expand_prologue, mips_expand_epilogue): Update callers.
+ (highpart_shift_operator): Attach ATTRIBUTE_UNUSED to mode argument.
+
+Thu May 9 11:50:09 2002 Jeffrey A Law (law@redhat.com)
+
+ * athlon.md, k6.md, pentium.md, ppro.md): New files.
+ * i386.md: Move scheduling information into new files.
+
+ * i386.md (type attribute): Add "rotate" for rotate insns.
+ (rotate insns): Set type to "rotate".
+ (various attributes and function units): Treat rotate like shift.
+ (pent_pair attribute): Only rotates by one bit position are
+ pairable.
+ (sbb insns): Explicitly set pent_pair attribute on a couple
+ that were missing it.
+
+Thu May 9 18:29:24 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.c (sh_builtin_saveregs): If starting with an odd fp register,
+ make sure that buffer starts on odd word address.
+ (sh_va_arg): Skip odd fp registers when reading a double precision
+ value.
+
+2002-05-09 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * tree.h (preserve_data, object_permanent_p, type_precision):
+ Remove.
+
+2002-05-09 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpplib.c (cpp_init_internal_pragmas): Remove #pragma poison.
+ * cppmacro.c (paste_all_tokens): Bad pastes are a hard error.
+doc:
+ * cpp.texi: Update for removal of obsolete features.
+
+Thu May 9 07:46:18 2002 Jan Hubicka <jh@suse.cz>
+ Jeffrey A Law (law@redhat.com)
+
+ * i386.c (ia32_use_dfa_pipeline_interface): New function. Use
+ the DFA interface for Pentium processors.
+ (TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE): DEFINE.
+ (attr_pent_pair, ix86_pent_find_pair): Remove.
+ (ix86_sched_reorder_pentium): Remove.
+ (ix86_sched_reorder): Remove reordering for Pentium.
+ * i386.md (Pentium scheduling): Rewrite using DFA description.
+
+Thu May 9 14:55:39 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfganal.c (can_fallthru): Fix fast path.
+ * cfgrtl.c (verify_flow_info): Avoid crash on conditionals
+ with edges to the next block.
+
+Thu May 9 14:52:45 CEST 2002 Jan Hubicka <jh@suse.cz>
+ Pavel Nejedly <bim@atrey.karlin.mff.cuni.cz>
+
+ * final.c (end_final): Use C trees to output data structures for profiling.
+
+ * Makefile.in (LIBGCC_DEPS): Added missing dependency on gcov-io.h
+ (profile.o): New dependency profile.h
+ (final.o): New dependency profile.h
+ * profile.h: New file. New global structure profile_info.
+ * final.h (count_edges_instrumented_now): Declare.
+ (current_function_cfg_checksum): Declare.
+ (function_list): New structure.
+ (functions_head, functions_tail): New static variables.
+ (end_final): Emits more data, removed some -ax stuff.
+ (final): Stores function names and chcksums.
+ * gcov-io.h (__write_gcov_string): New function.
+ (__read_gcov_string): New function.
+ * gcov.c (read_profile): New function.
+ (create_program_flow_graph): Uses read_profile instead of reading
+ da_file.
+ (read_files): Removed da_file checking, it's done by read_profile now.
+ * libgcc2.c (bb_function_info): New structure.
+ (bb): New field in structure, removed some -ax stuff.
+ (__bb_exit_func): Changed structure of da_file.
+ * profile.c (count_edges_instrumented_now): New global variable.
+ (current_function_cfg_checksum): New global variable.
+ (max_counter_in_program): New global variable.
+ (get_exec_counts): New function.
+ (compute_checksum): New function.
+ (instrument_edges): Sets count_edges_instrumented_now.
+ (compute_branch_probabilities): Uses get_exec_counts instead of
+ reading da_file.
+ (branch_prob): Calls compute_checksum and writes extra data to bbg_file.
+ (init_branch_prob): Removed da_file checking, done in get_exec_counts
+ now.
+ (end_branch_prob): Removed da_file checking, done in get_exec_counts
+ now.
+ * gcov.texi: Updated information about gcov file format.
+
+2002-05-09 Kazu Hirata <kazu@cs.umass.edu>
+
+ * sbitmap.c: Fix formatting.
+ * scan.c: Likewise.
+ * scan-decls.c: Likewise.
+ * sched-deps.c: Likewise.
+ * sched-ebb.c: Likewise.
+ * sched-rgn.c: Likewise.
+ * sched-vis.c: Likewise.
+ * sdbout.c: Likewise.
+ * sibcall.c: Likewise.
+ * simplify-rtx.c: Likewise.
+ * ssa.c: Likewise.
+ * ssa-ccp.c: Likewise.
+ * ssa-dce.c: Likewise.
+ * stmt.c: Likewise.
+ * stor-layout.c: Likewise.
+ * stringpool.c: Likewise.
+
+2002-05-09 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sol2.h (ASM_CPU_SPEC): Handle -mcpu=v9.
+
+2002-05-07 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.h (TARGET_BUGGY_QP_LIB): Define to zero.
+ * config/sparc/sol2.h (TARGET_BUGGY_QP_LIB): Override to one.
+ * config/sparc/sparc.c (emit_soft_tfmode_libcall): If the Qp
+ library implementation clobbers the output before the inputs
+ are fully consumed, use stack temporary for the output.
+
+2002-05-09 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/netbsd.h (CPP_SPEC): Remove.
+ * config/i386/netbsd-elf.h (CPP_SPEC): Define.
+ * config/i386/netbsd.h (CPP_SPEC): Define.
+ * config/ns32k/netbsd.h (CPP_SPEC): Define.
+ * config/sparc/netbsd-elf.h (CPP_SPEC): Remove.
+ * config/sparc/netbsd.h (CPP_SPEC): Define.
+ * config/vax/netbsd.h (CPP_SPEC): Define.
+
+2002-05-08 Kazu Hirata <kazu@cs.umass.edu>
+
+ * read-rtl.c: Fix formatting.
+ * real.c: Likewise.
+ * recog.c: Likewise.
+ * regclass.c: Likewise.
+ * regmove.c: Likewise.
+ * reg-stack.c: Likewise.
+ * reload1.c: Likewise.
+ * reload.c: Likewise.
+ * resource.c: Likewise.
+ * rtlanal.c: Likewise.
+ * rtl.c: Likewise.
+ * rtl-error.c: Likewise.
+
+2002-05-08 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa/pa-64.h (MAX_WCHAR_TYPE_SIZE): Delete.
+ * pa/pa.h (MAX_WCHAR_TYPE_SIZE): Delete.
+
+2002-05-08 Bernd Schmidt <bernds@redhat.com>
+
+ * config/i386/i386.h (CPP_CPUCOMMON_SPEC): Tweak previous change to
+ use __SSE2__ macro instead.
+ * config/i386/xmmintrin.h: Likewise.
+
+2002-05-08 Janis Johnson <janis187@us.ibm.com>
+
+ * rtl.h (RTL_FLAG_CHECK*): Add an argument for the macro name,
+ and use it in all invocations of these macros. Clean up comments.
+ * rtl.c (rtl_check_failed_flag): Add an argument for the name
+ of the flag access macro whose check failed.
+ * doc/rtl.texi (Flags): Document additional flag uses.
+
+2002-05-08 Robert Spier <rspier@pobox.com>
+ Neil Booth <neil@daikokuya.demon.co.uk>
+
+ PR preprocessor/6521
+ * cppfiles.c (handle_missing_header): Don't do anything
+ different for <> includes.
+doc:
+ * cppopts.texi: Update documentation for -MG.
+
+2002-05-08 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpplex.c (cpp_interpret_charconst): Truncate as well as
+ sign-extend.
+doc:
+ * cpp.texi: Clarify multichar charconst valuation.
+
+2002-05-08 Mark Mitchell <mark@codesourcery.com>
+
+ * doc/invoke.texi: Document -mwindiss option.
+
+2002-05-08 Jason Merrill <jason@redhat.com>
+
+ * dwarf2out.c (output_call_frame_info): Don't emit a CIE with no FDEs.
+
+ * dwarf2out.c (gen_type_die): Abort on broken recursion.
+
+ PR c++/6381
+ * dwarf2out.c (rtl_for_decl_location): Only expand INTEGER_CST and
+ REAL_CST.
+
+2002-05-08 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/arm/t-arm-elf (MULTILIB): Do not allow big-endian/
+ little-endian multilibs to override arm/thumb multilibs.
+ Do not build hardware floating point multilibs, nor apcs-26
+ multilibs for the Thumb.
+
+2002-05-08 Mark Mitchell <mark@codesourcery.com>
+
+ PR c/6569.
+ * varasm.c (mark_weak): New function.
+ (merge_weak): Use it. Do not call declare_weak.
+ (declare_weak): Use merge_weak.
+
+Wed May 8 13:12:11 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * cse.c (dead_libcall_p): Update counts.
+ (delete_trivially_dead_insns): Update call of dead_libcall_p.
+
+Wed May 8 11:08:50 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfglayout.c (function_tail_eff_head): Rename to ...
+ (function_footer): ... this one.
+ (unlink_insn_chain): New functions.
+ (label_for_bb): Only call block_label and emit debug message.
+ (record_effective_endpoints): Actually unlink the headers and footers.
+ (fixup_reorder_cahin): Re-insert the unlinked sequences.
+ (cfg_layout_duplicate_bb): Use duplicate_insn_chain.
+ * cfglayout.h (struct reorder_block_def): New fields footer/header;
+ remove eff_head/eff_end.
+ * rtl.h (set_first_insn): Declare.
+ * emit-rtl.c (set_first_insn): New function.
+
+ * cfglayout.c (fixup_reorder_chain): Dump duplicated
+ (cfg_layout_can_duplicate_bb_p, cfg_layout_rerirect_edge,
+ cfg_layout_duplicate_bb): New global function.
+ (duplicate_insn_chain): New static function.
+ * cfglayout.h (cfg_layout_can_duplicate_bb_p, cfg_layout_rerirect_edge,
+ cfg_layout_duplicate_bb): Declare.
+ (struct reorder_block_def): Add "original" field.
+ * emit-rtl.c (emit_copy_of_insn_after): New function.
+ * rtl.h (emit_copy_of_insn_after): Declare.
+
+ * cfglayout.c (fixup_fallthru_exit_predecessor): Kill.
+ (fixup_reorder_chain): properly handle edges to exit block.
+
+Wed May 8 11:10:31 CEST 2002 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+ Jan Hubicka <jh@suse.cz>
+
+ * basic-block.h (note_prediction_to_br_prob): declare.
+ * c-semantics.c: Inlucde predit.h
+ (expand_stmt): predict GOTO_STMT as not taken.
+ * cfgcleanup.c: (delete_unreachable_blocks): Make global.
+ (cleanup_cfg): Do not free tail_recursion_list.
+ * cfgrtl.c (can_delete_note_p): Delete NOTE_INSN_PREDICTION.
+ (flow_delete_block): Kill predictions past end of basic block.
+ * output.h (delete_unreachable_blocks): Declare.
+ * predict.c (predicted_by_p, process_note_predictions,
+ process_note_prediction, last_block_p): New function.
+ (estimate_probability): Bypass loop on PRED_CONTINUE;
+ do not handle noreturn heuristics; kill PRED_RETURN; add
+ PRED_EARLY_RETURN.
+ * predict.def (PRED_CONTINUE, PRED_EARLY_RETURN, PRED_GOTO,
+ PRED_CONST_RETURN, PRED_NEGATIVE_RETURN, PRED_NULL_RETURN): New.
+ * predict.h (IS_TAKEN): New constant.
+ * print-rtl.c (print_rtx): Pretty print NOTE_INSN_PREDICTION.
+ * rtl.c (NOTE_INSN_PREDICTION): New.
+ * rtl.h (NOTE_PREDICTION, NOTE_PREDICTION_ALG, NOTE_PREDICTION_FLAGS):
+ New macro.
+ (insn_note): add NOTE_INSN_PREDICTION.
+ * sibcall.c (optimize_sibling_and_tail_recursive_call): Do not build
+ CFG; free tail_recursion_label_list.
+ * stmt.c: Include predict.h;
+ (return_prediction): New.
+ (expand_value_return): Use it.
+ * toplev.c: Lower NOTE_INSN_PREDICTION before sibcall.
+
+2002-05-08 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips.md: Name the unspecs with define_constant.
+ (*HILO_delay): Rename to 'hilo_delay' (no star).
+ (reload_indi): Replace gen_rtx_UNSPEC with gen_hilo_delay.
+ (reload_outdi, reload_outsi): Likewise.
+
+2002-05-07 Kazu Hirata <kazu@cs.umass.edu>
+
+ * toplev.c: Fix formatting.
+
+2002-05-07 Janis Johnson <janis187@us.ibm.com>
+
+ * config.in (ENABLE_RTL_FLAG_CHECKING): New.
+ * configure.in (ac_rtlflag_checking): New.
+ * doc/install.texi (--enable-checking): Document RTL flag checking.
+
+2002-05-07 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (c_common_init): Set options->unsigned_wchar.
+ * cppinit.c (cpp_create_reader): Default unsigned_wchar,
+ group target dependencies.
+ (init_builtins, cpp_handle_option): Update.
+ * cpplex.c (cpp_interpret_charconst): Update.
+ * cpplib.h (struct cpp_options): Add unsigned_wchar, rename
+ signed_char to unsigned_char, group target dependencies.
+ * defaults.h (WCHAR_UNSIGNED): Remove.
+ * system.h (WCHAR_UNSIGNED, MAX_CHAR_TYPE_SIZE): Poison.
+config:
+ * freebsd.h, interix.h, alpha/freebsd.h, arm/freebsd.h,
+ i386/386bsd.h, i386/beos-elf.h, i386/bsd386.h, i386/cygwin.h,
+ i386/djgpp.h, i386/freebsd-aout.h, i386/i386-interix.h,
+ i386/win32.h, ia64/freebsd.h, mips/netbsd.h, rs6000/freebsd.h,
+ sh/elf.h, sh/sh.h, sparc/freebsd.h: Remove WCHAR_UNSIGNED.
+doc:
+ * tm.texi: Remove MAX_CHAR_TYPE_SIZE.
+
+2002-05-07 Mark Mitchell <mark@codesourcery.com>
+
+ * fixinc/inclhack.def (windiss_math1): New fix.
+ (windiss_math2): Likewise.
+ (windiss_valist): Likewise.
+ * fixinc/fixincl.x: Regenerated.
+
+2002-05-07 Andreas Jaeger <aj@suse.de>
+
+ * genautomata.c (output_internal_min_issue_delay_func): Add
+ ATTRIBUTE_UNUSED to avoid warning with empty dfa.
+ (output_internal_trans_func): Likewise.
+
+Tue May 7 10:06:22 2002 Jeffrey A Law (law@redhat.com)
+
+ * pa.c (hppa_profile_hook): Use force_reg to get the address
+ of the profile hook into an appropriate pseudo register.
+
+2002-05-07 Mark Mitchell <mark@codesourcery.com>
+
+ * config/rs6000/sysv4.h (SUBTARGET_SWITCHES): Add -mwindiss.
+ (LINK_START_SPEC): Handle it.
+ (LINK_OS_SPEC): Likewise.
+ (CPP_SPEC): Likewise.
+ (STARTFILE_SPEC): Likewise.
+ (LIB_SPEC): Likewise.
+ (ENDFILE_SPEC): Likewise. Do not assume crtsavres.o is used on
+ all platforms.
+ (CRTSAVRES_DEFAULT_SPEC): New macro.
+ (LIB_WINDISS_SPEC): New macro.
+ (CPP_OS_WINDISS_SPEC): Likewise.
+ (STARTFILE_WINDISS_SPEC): Likewise.
+ (ENDFILE_WINDISS_SPEC): Likewise.
+ (LINK_START_WINDISS_SPEC): Likewise.
+ (LINK_OS_WINDISS_SPEC): Likewise.
+ * config/rs6000/windiss.h: New file.
+
+2002-05-07 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c (bdesc_2arg): Fix vmax typos.
+
+2002-05-06 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.md (shift insns): Do not mask off
+ second operand, 'I' constraint and SHIFT_COUNT_TRUNCATED
+ take care of it.
+
+2002-05-06 Richard Henderson <rth@redhat.com>
+
+ PR c++/6212
+ * expr.c (highest_pow2_factor_for_type): New.
+ (expand_assignment): Use it.
+
+2002-05-06 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.md ("altivec_mtvscr"): Change to
+ unspec_volatile.
+ ("altivec_mfvscr"): Same.
+
+2002-05-06 Janis Johnson <janis187@us.ibm.com>
+
+ * rtl.h (struct rtx_def): Update comments.
+ (RTL_FLAG_CHECK[12345678]): New. (rtl_check_failed_flag): Declare.
+ (RTL_FLAG): New. (CLEAR_RTX_FLAGS): New. (flag access macros): Use
+ RTL_FLAG_CHECK macros with list of expected RTL codes.
+ * rtl.c (copy_rtx, shallow_copy_rtx): Use RTX_FLAG macro.
+ (rtl_check_failed_flag): New.
+ * reload1.c (reload): Use REG macro before changing rtx to MEM.
+ (reload_cse_noop_set_p): Check rtx code before using access macro.
+ * config/ia64/ia64.c (process_for_unwind_directive): Check rtx code
+ before using access macro.
+
+2002-05-06 Janis Johnson <janis187@us.ibm.com>
+
+ * doc/rtl.texi (Flags): Update to reflect current usage.
+
+2002-05-06 Roger Sayle <roger@eyesopen.com>
+
+ PR opt/3995
+ * fold-const.c (sign_bit_p): New function.
+ (fold) [EQ_EXPR]: Use this to convert (A & C) == 0 into A >= 0 and
+ (A & C) != 0 into A < 0, when constant C is the sign bit of A's type.
+ Reapply fold when converting (A & C) == C into (A & C) != 0.
+ (fold_binary_op_with_conditional_arg): Fix typo in comment.
+
+2002-05-07 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (warn_multichar): New.
+ (c_common_init): Set CPP's warn_multichar.
+ * c-common.h (warn_multichar): New.
+ * c-decl.c (warn_multichar): Remove.
+ * c-lex.c (lex_charconst): Update.
+ * c-tree.h (warn_multichar): Remove.
+ * cppexp.c (eval_token): Sign-extend charconst value.
+ * cppinit.c (cpp_create_reader): Set warn_multichar.
+ * cpplex.c (cpp_interpret_charconst): Don't sign-extend
+ each character. Update prototype. Sign-extend the result.
+ * cpplib.h: Fix conditions.
+ (struct cpp_options): Add new warning flag.
+ (cpp_interpret_charconst): Update prototype.
+doc:
+ * cpp.texi: Update documentation.
+
+2002-05-06 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (form_the_same_automaton_unit_lists_from_regexp):
+ Fix typo in usage of allof instead of unit.
+
+2002-05-06 Richard Henderson <rth@redhat.com>
+
+ * recog.c (if_test_bypass_p): Accept multiple set insns for OUT,
+ and any jump or call for IN.
+
+2002-05-06 Bernd Schmidt <bernds@redhat.com>
+
+ * config/i386/i386.h (CPP_CPUCOMMON_SPEC): Define __SSE2_BUILTINS__ if
+ -msse2.
+ * config/i386/xmmintrin.h: Use it to conditionalize SSE2 support.
+
+2002-05-06 Roger Sayle <roger@eyesopen.com>
+
+ * fold-const.c (lshift-double): Cast the high word to an unsigned
+ HOST_WIDE_INT when extracting sign bit to avoid compiler warning.
+ (div_and_round_double): Cast carry to a signed HOST_WIDE_INT to
+ avoid compiler warning. (fold): Remove redundant code from
+ BIT_AND_EXPR as integer operands are canonicalized to be arg1.
+
+2002-05-06 Jeff Law <law@redhat.com>
+
+ * pa-protos.h (hppa_fpstore_bypass_p): Declare.
+ * pa.c (pa_adjust_cost): Remove all true dependency cost
+ adjustments. Also remove support for non-DFA scheduling.
+ * pa.md (700, 7100, 7100lc, 7200, 7300): Use bypass mechanism
+ to adjust true dependency costs. Update various comments.
+ (7100lc, 7200, 7300 scheduling): Simplify by combining the
+ FP ALU & MPY units into a single unit.
+
+2002-05-06 Catherine Moore <clm@redhat.com>
+
+ * config/v850/v850.c (compute_register_save_size): Make sure
+ to count all of the registers that will be saved.
+
+Mon May 6 18:03:11 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (q_regs_operand): Use ANY_QI_REGS_P.
+
+2002-05-06 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.c (emit_soft_tfmode_libcall): Do not
+ allow result to overlap input operands in memory.
+
+2002-05-06 Neil Booth <neil@daikokuya.demon.co.uk>
+
+doc:
+ * cpp.texi: Update multichar charconst docs.
+
+2002-05-06 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpplex.c (cpp_interpret_charconst): Sign-extend each
+ character. Don't ignore excess characters. Treat
+ multicharacter character constants as signed.
+ (cpp_parse_escape): Clarify diagnostic.
+
+2002-05-05 Jakub Jelinek <jakub@redhat.com>
+
+ * config/sparc/sparc.md (ashlsi3): If shift count is const1_rtx,
+ use add instead of shift.
+ (ashldi3_sp64): Likewise.
+ (ashlsi3_const1, ashldi3_const1): Remove.
+ * config/sparc/sparc.h (PREDICATE_CODES): Add const1_operand.
+ * config/sparc/sparc.c (const1_operand): New.
+
+2002-05-05 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config.gcc (alpha*-*-netbsd*): Don't use crtstuff.
+
+2002-05-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/6561
+ * config/sparc/sparc.md (muldi3_v8plus): Handle %1 equal to %2.
+
+2002-05-05 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (alpha_adjust_cost): Remove everything but
+ memory latency adjustments.
+ (alpha_variable_issue): Remove.
+ (alpha_use_dfa_pipeline_interface): New.
+ (alpha_multipass_dfa_lookahead): New.
+ * config/alpha/alpha.md: Remove define_function_unit scheduling;
+ include new dfa scheduling.
+ (attr type): Add none.
+ (blockage): Use it.
+ * config/alpha/ev4.md: New.
+ * config/alpha/ev5.md: New.
+ * config/alpha/ev6.md: New.
+
+2002-05-05 David S. Miller <davem@redhat.com>
+
+ * recog.c (store_data_bypass_p): Handle CLOBBER inside PARALLEL.
+
+2002-05-05 Kazu Hirata <kazu@cs.umass.edu>
+
+ * cse.c: Fix formatting.
+ * emit-rtl.c: Likewise.
+
+2002-05-05 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (initiate_states): Add additional guard to
+ initialize `units_array'.
+
+2002-05-05 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (form_the_same_automaton_unit_lists_from_regexp,
+ process_unit_to_form_the_same_automaton_unit_lists,
+ form_the_same_automaton_unit_lists
+ check_unit_distributions_to_automata): New prototypes and
+ functions.
+ (check_automata): Rename it into `check_automata_insn_issues'.
+ (unit_decl): New fields `the_same_automaton_unit' and
+ `the_same_automaton_message_reported_p'.
+ (unit_decl_t): New typedef.
+ (the_same_automaton_lists): New gloval variable.
+ (unit_regexp, unit_set_el, units_array, units_cmp,
+ output_get_cpu_unit_code_func): Use the typedef.
+ (evaluate_max_reserv_cycles): Increment
+ `description->max_insn_reserv_cycles'.
+ (initiate_states): Don't increment `max_cycles_num'.
+ (transform_insn_regexps): Move code around transformation of
+ regexps from `generate'.
+ (generate): Remove call of `transform_insn_regexps'.
+ (expand_automata): Call `transform_insn_regexps' and
+ `check_unit_distributions_to_automata'. Check errors before
+ `generate'.
+
+ * config/sparc/ultra3.md (us3_a0, us3_a1): Move the units into
+ automaton `ultrasparc3_1'.
+
+2002-05-05 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (c_common_init): Set up CPP arithmetic.
+ * cppinit.c (cpp_create_reader): Default CPP arithmetic to
+ something reasonable for the host.
+ (sanity_checks): Add checks.
+ (cpp_read_main_file): Call sanity_checks() from here...
+ (cpp_post_options): ... not here.
+ * cpplex.c (cpp_interpret_charconst): Get max_chars right.
+ * cpplib.h (struct cpp_options): New member int_precision.
+
+2002-05-05 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ * doc/install.texi (powerpc-*-linux-gnu*): Update build requirements.
+
+2002-05-04 David S. Miller <davem@redhat.com>
+
+ * config/sparc/linux.h, config/sparc/linux64.h
+ (HANDLE_PRAGMA_PACK_PUSH_POP): Don't define twice.
+
+ * config/sparc/sparc.c (sparc_rtx_costs): Describe costs of
+ more RTX codes.
+ * config/sparc/sparc.h (RTX_COSTS_CASES): List those new codes.
+
+ * recog.c (store_data_bypass_p): Handle out_insn being a PARALLEL
+ of SETs.
+
+2002-05-05 Tim Josling <tej@melbpc.org.au>
+
+ * treelang; New directory for new sample language treelang.
+
+2002-05-04 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in (c-lex.o): Update.
+ * c-lex.c: Include target.h.
+ (cb_register_builtins): New.
+ (init_c_lex): Set builtins callback.
+ * c-lex.h (cpp_define, cpp_assert): New prototypes.
+ * cppinit.c (init_builtins): Use callback, including for
+ GXX_WEAK.
+ * cpplib.h (struct cpp_callbacks): New member.
+ * target-def.h (TARGET_REGISTER_CPP_BUILTINS): New.
+ (TARGET_INITIALIZER): Update.
+ * target.h (struct gcc_target): New hook.
+ * tree.c (default_register_cpp_builtins): New.
+ * tree.h (default_register_cpp_builtins): New.
+doc:
+ * tm.texi (TARGET_REGISTER_CPP_BUILTINS): Document.
+
+2002-05-04 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppinit.c (MAX_WCHAR_TYPE_SIZE): Move to cpplib.h
+ (cpp_post_options): Move sanity checks to...
+ (sanity_checks): New.
+ * cpplex.c (maybe_read_ucs): Fix prototype.
+ (parse_string, cpp_parse_escape): Cast for %c format specifier.
+ * cpplib.h (cppchar_t): Use unsigned long or unsigned long long
+ if necessary.
+
+2002-05-04 Bernd Schmidt <bernds@redhat.com>
+
+ * config/i386/i386.c (bdesc_2arg): Add a couple of missing SSE2
+ builtins. Use V2DI patterns instead of TI for logical operations.
+ (ix86_init_mmx_sse_builtins): Add a couple of missing SSE2 builtins.
+ Correct definitions of psadbw, pmovmskb128, movntdq, cvtdq2ps.
+ (ix86_expand_builtins): Change the pattern used for movntdq.
+ * config/i386/i386.md (sse2_andv2di3, sse2_iorv2di3, sse2_xorv2di3,
+ sse2_nandv2di3): New patterns.
+ (sse2_anddf3, sse2_nanddf3, sse2_iordf3, sse2_xordf3): Correct modes
+ on operands.
+ (sse2_movntv2di): Renamed from sse2_movntti and modes adjusted.
+ (cvtdq2pd): Correct mode on operand 1.
+ (sse2_umulsidi3): Describe without unspec.
+ (sse2_psadbw, mmx_psadbw): Describe with unspec; use more appropriate
+ machine modes.
+ (lshrv2di3): Renamed from sse2_lshrv2di3 and removed unspec.
+ (ashlv2di3): Likewise, from sse2_ashlv2di3.
+ (ashrv8hi3, ashrv4si3, lshrv8hi3, lshrv4si3, lshrv2di3, ashlv8hi3,
+ ashlv4si3, ashlv2di3): Use SImode for shift count.
+ (ashrv8hi3_ti, ashrv4si3_ti, lshrv8hi3_ti, lshrv4si3_ti, lshrv2di3_ti,
+ lshrv4si3_ti, lshrv2di3_ti, ashlv8hi3_ti, ashlv4si3_ti, ashlv2di3_ti):
+ New patterns.
+ * config/i386/xmmintrin.h (__v2df, __v2di, __v4si, __v8hi, __v16qi):
+ New typedefs.
+ (__m128i, __m128d): New macros.
+ (_mm_add_pd, _mm_add_sd, _mm_sub_pd, _mm_sub_sd, _mm_mul_pd,
+ _mm_mul_sd, _mm_div_pd, _mm_div_sd, _mm_sqrt_pd, _mm_sqrt_sd,
+ _mm_min_pd, _mm_min_sd, _mm_max_sd, _mm_max_pd, _mm_and_pd,
+ _mm_andnot_pd, _mm_xor_pd, _mm_or_pd, _mm_cmpeq_pd, _mm_cmplt_pd,
+ _mm_cmple_pd, _mm_cmpgt_pd, _mm_cmpge_pd, _mm_cmpneq_pd,
+ _mm_cmpnlt_pd, _mm_cmpnle_pd, _mm_cmpngt_pd, _mm_cmpnge_pd,
+ _mm_cmpord_pd, _mm_cmpunord_pd, _mm_cmpeq_sd, _mm_cmplt_sd,
+ _mm_cmple_sd, _mm_cmpgt_sd, _mm_cmpge_sd, _mm_cmpneq_sd,
+ _mm_cmpnlt_sd, _mm_cmpnle_sd, _mm_cmpngt_sd, _mm_cmpnge_sd,
+ _mm_cmpord_sd, _mm_cmpunord_sd, _mm_comieq_sd, _mm_comilt_sd,
+ _mm_comile_sd, _mm_comigt_sd, _mm_comige_sd, _mm_comineq_sd,
+ _mm_ucomieq_sd, _mm_ucomieq_sd, _mm_ucomilt_sd, _mm_ucomile_sd,
+ _mm_ucomigt_sd, _mm_ucomige_sd, _mm_ucomineq_sd, _mm_cvtepi32_pd,
+ _mm_cvtepi32_ps, _mm_cvtpd_epi32, _mm_cvtpd_pi32, _mm_cvtpd_ps,
+ _mm_cvttpd_epi32, _mm_cvttpd_pi32, _mm_cvtpi32_pd, _mm_cvtps_epi32,
+ _mm_cvttps_epi32, _mm_cvtps_pd, _mm_cvtsd_si32, _mm_cvttsd_si32,
+ _mm_cvtsd_ss, _mm_cvtsi32_sd, _mm_cvtss_sd, _mm_unpackhi_pd,
+ _mm_unpacklo_pd, _mm_loadh_pd, _mm_storeh_pd, _mm_storel_pd,
+ _mm_movemask_pd, _mm_packs_epi16, _mm_packs_epi32, _mm_packus_epi16,
+ _mm_unpackhi_epi8, _mm_unpackhi_epi16, _mm_unpackhi_epi32,
+ _mm_unpacklo_epi8, _mm_unpacklo_epi16, _mm_unpacklo_epi32,
+ _mm_add_epi8, _mm_add_epi16, _mm_add_epi32, _mm_add_epi64,
+ _mm_adds_epi8, _mm_adds_epi16, _mm_adds_epu8, _mm_adds_epu16,
+ _mm_sub_epi8, _mm_sub_epi16, _mm_sub_epi32, _mm_sub_epi64,
+ _mm_subs_epi8, _mm_subs_epi16, _mm_subs_epu8, _mm_subs_epu16,
+ _mm_madd_epi16, _mm_mulhi_epi16, _mm_mullo_epi16, _mm_mul_pu16,
+ _mm_mul_epu16, _mm_sll_epi16, _mm_sll_epi32, _mm_sll_epi64,
+ _mm_sra_epi16, _mm_sra_epi32, _mm_srl_epi16, _mm_srl_epi32,
+ _mm_srl_epi64, _mm_slli_epi16, _mm_slli_epi32, _mm_slli_epi64,
+ _mm_srai_epi16, _mm_srai_epi32, _mm_srli_epi16, _mm_srli_epi32,
+ _mm_srli_epi64, _mm_and_si128, _mm_andnot_si128, _mm_or_si128,
+ _mm_xor_si128, _mm_cmpeq_epi8, _mm_cmpeq_epi16, _mm_cmpeq_epi32,
+ _mm_cmpgt_epi8, _mm_cmpgt_epi16, _mm_cmpgt_epi32, _mm_max_epi16,
+ _mm_max_epu8, _mm_min_epi16, _mm_min_epu8, _mm_movemask_epi8,
+ _mm_mulhi_epu16, _mm_maskmoveu_si128, _mm_avg_epu8, _mm_avg_epu16,
+ _mm_sad_epu8, _mm_stream_si32, _mm_stream_si128, _mm_stream_pd,
+ _mm_movpi64_epi64, _mm_clflush, _mm_lfence, _mm_mfence): New
+ functions.
+ (_mm_shufflehi_epi16, _mm_shufflelo_epi16, _mm_shuffle_epi32,
+ _mm_extract_epi16, _mm_insert_epi16, _mm_shuffle_pd): New macros.
+
+2002-05-04 Kazu Hirata <kazu@cs.umass.edu>
+
+ * dwarf2out.c: Fix formatting.
+ * varasm.c: Likewise.
+
+2002-05-04 David Edelsohn <edelsohn@gnu.org>
+
+ PR c/6543
+ * config/rs6000/rs6000.md (sCC pattern and splitter): Remove
+ clobber and use result as temporary value.
+
+Sat May 4 13:20:54 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * expr.c (force_operand): Use expand_simple_* to handle more
+ cases.
+
+2002-05-04 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-lex.c (lex_string): Let cpp_parse_escape handles truncation
+ and sign-extension.
+ (lex_charconst): Update for change in prototype of
+ cpp_interpret_charconst. Extend from cppchar_t to HOST_WIDE_INT
+ appropriately.
+ * cpphash.h (BITS_PER_CPPCHAR_T): New.
+ * cppinit.c (cpp_create_reader): Initialize them for no
+ change in semantics.
+ (cpp_post_options): Add sanity checks.
+ * cpplex.c (cpp_parse_escape): Handle precision, sign-extension
+ and truncation issues. Calculate in type cppchar_t.
+ (MAX_CHAR_TYPE_SIZE, MAX_WCHAR_TYPE_SIZE): Remove.
+ (cpp_interpret_charconst): Calculate in type cppchar_t. Handle
+ run-time dependent precision correctly. Return whether the
+ result is signed or not.
+ * cpplib.c (dequote_string): Use cppchar_t; update.
+ * cpplib.h (cppchar_signed_t): New.
+ struct cpp_options): New precision members.
+ (cpp_interpret_charconst, cpp_parse_escape): Update prototypes.
+ * cppexp.c (eval_token): Update.
+
+2002-05-03 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc-protos.h (sparc_rtx_costs): New.
+ * config/sparc/sparc.c (sparc_rtx_costs): New function
+ implementing RTX_COSTS and CONST_COSTS.
+ * config/sparc/sparc.h (CONST_COSTS): Delete.
+ (RTX_COSTS_CASES): Define.
+ (RTX_COSTS): Expand RTX_COSTS_CASES and use sparc_rtx_costs to do
+ the work.
+
+ * config/sparc/sparc.md (DFA schedulers): Split out...
+ * config/sparc/cypress.md, config/sparc/hypersparc.md,
+ config/sparc/sparclet.md, config/sparc/supersparc.md,
+ config/sparc/ultra1_2.md, config/sparc/ultra3.md: ... into here.
+
+ * config/sparc/sparc.c (LEAF_REGISTERS): Do not do ifdef
+ checks on it, always defined for SPARC.
+
+ * config/sparc/sparc.h (REG_ALLOC_ORDER, REG_LEAF_ALLOC_ORDER):
+ Tweak, and add more detailed comments.
+
+2002-05-03 Zack Weinberg <zack@codesourcery.com>
+
+ * Re-apply patch accidentally reverted with
+ DFA scheduler merge: remove all rules and variables to slurp
+ source files out of libiberty and rebuild them with HOST_CC.
+ ($(HOST_PREFIX_1)varray.o): New rule.
+ (genattrtab rule): Word wrap.
+
+2002-05-03 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/i386/netbsd64.h (CPP_LP64_SPEC): Define.
+ (CPP_SUBTARGET_SPEC): Define.
+ (SUBTARGET_EXTRA_SPECS): Redefine, adding cpp_lp64 and
+ cpp_subtarget specs.
+ (CPP_SPEC): Redefine to include %(cpp_subtarget).
+
+2002-05-03 David S. Miller <davem@redhat.com>
+
+ * target-defs.h (TARGET_SCHED_CYCLE_DISPLAY): Delete.
+ * target.h (struct gcc_target): Delete cycle_display member.
+
+ * config/ia64/ia64.c (ia64_emit_insn_before): Put it back.
+ (rtx_needs_barrier): Delete reference to cycle_display unspec.
+ (ia64_sched_reorder2): Mention need for cycle display handling
+ once such notes exist.
+
+2002-05-03 Richard Henderson <rth@redhat.com>
+
+ * real.c (etoasc): Strip most trailing zeros for clarity.
+ * sched-vis.c: Include real.h.
+ (print_value): Use REAL_VALUE_TO_DECIMAL as needed.
+ * Makefile.in (sched-vis.o): Add real.h.
+
+2002-05-03 David S. Miller <davem@redhat.com>
+
+ * haifa-sched.c (rank_for_schedule): Revert 2002-05-02 change,
+ no longer needed.
+
+2002-05-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c (altivec_expand_binop_builtin): Error out
+ when we get an out of range literal.
+ (altivec_expand_ternop_builtin): Same.
+ (altivec_expand_unop_builtin): Same.
+ (altivec_expand_builtin): Same, for dss.
+ (altivec_expand_builtin): Use trees instead of rtl when
+ determining literal argument validity.
+
+2002-05-03 David S. Miller <davem@redhat.com>
+
+ Delete cycle display scheduling hook.
+ * config/ia64/ia64.c (ia64_cycle_display,
+ TARGET_SCHED_CYCLE_DISPLAY, ia64_emit_insn_before): Delete.
+ (ia64_sched_reorder2): Don't check for CODE_FOR_cycle_display
+ and use emit_insn_before instead of ia64_emit_insn_before.
+ * config/ia64/ia64.md (unspec usage): Delete cycle display.
+ (cycle_display): Delete insn pattern.
+ * config/sparc/sparc.md (unspec usage): Delete cycle display.
+ (cycle_display): Delete insn pattern.
+ * config/sparc/sparc.c (sparc_cycle_display,
+ TARGET_SCHED_CYCLE_DISPLAY): Delete.
+ * doc/md.texi (cycle_display): Don't mention.
+ * doc/tm.texi (TARGET_SCHED_CYCLE_DISPLAY): Likewise.
+
+2002-05-03 Richard Henderson <rth@redhat.com>
+
+ * recog.c (store_data_bypass_p, if_test_bypass_p): New.
+ * recog.h: Declare them.
+
+ * config/sparc/sparc.c (ultrasparc_store_bypass_p): Remove.
+ * config/sparc/sparc.md: Use store_data_bypass_p instead.
+ * config/sparc/sparc-protos.h: Update.
+
+2002-05-03 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/sparc/netbsd-elf.c (CPP_SUBTARGET_SPEC64): Remove
+ -D__arch64__. Add -D_LP64.
+ (CPP_ARCH32_SPEC): Redefine to match the non-bi-arch version
+ from sparc.h.
+ (CPP_ARCH64_SPEC): Likewise.
+ (NO_BUILTIN_PTRDIFF_TYPE): Undef.
+ (NO_BUILTIN_SIZE_TYPE): Undef.
+
+2002-05-03 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (min_issue_delay_pass_states): Change return type
+ in the prototype.
+ (min_issue_delay_pass_states): Change the algorithm.
+ (min_issue_delay): Set up min_insn_issue_delay for the state.
+ (output_min_issue_delay_table): Interchange the nested loops and
+ and initiate min_insn_issue_delay for states.
+
+Fri May 3 22:59:15 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgcleanup.c (try_optimize_cfg): Call merge_block only when
+ jump is simplejump.
+
+Fri May 3 22:53:37 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (expand_movstr, expand_clrstr): Fix inline-all-stringops
+ sequence.
+
+2002-05-03 Richard Henderson <rth@redhat.com>
+
+ PR opt/6534
+ * ifcvt.c (noce_try_store_flag, noce_try_store_flag_constants,
+ noce_try_store_flag_inc, noce_try_store_flag_mask, noce_try_cmove,
+ noce_try_cmove_arith, noce_try_minmax, noce_try_abs): Insert new
+ code before JUMP, not EARLIEST.
+
+2002-05-03 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * c-format.c (check_format_info_main): Don't check for presence of
+ parameter for * width until after operand number has been read,
+ and only check for it if format parameters are available.
+ Fixes PR c/6547.
+
+2002-05-03 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/alpha/netbsd.h (CPP_PREDEFINES): Add -D_LP64.
+ (LINK_SPEC): Undef before defining.
+
+2002-05-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR preprocessor/6489
+ * tradcpp.c (fixup_newlines): New.
+ (main, finclude): Use it.
+
+2002-05-03 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/elf64.h (UNIQUE_SECTION): Use mips_unique_section.
+ * config/mips/mips.c (mips_unique_section): Strip encoding from
+ decl name.
+
+2002-05-03 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (ix86_expand_int_movcc): Truncate to proper
+ mode.
+
+2002-05-03 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * doc/install.texi (Installing): Mention GCC 3.1 buildstats.
+ (Specific): Removed buildstats references.
+ (Specific, hppa*-hp-hpux11): Adjust for GCC versions > 3.0.
+ (Specific, sparc-sun-solaris2*): Update 64-bit hints for GCC 3.1.
+ Accomodate Solaris versions beyond 8.
+ (Specific, sparc-sun-solaris2.7): Update as path for GCC 3.1.
+ (Specific, *-*-solaris2.8): Removed, obsolete.
+
+2002-05-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/6542
+ * config/sparc/sparc.h (leaf_reg_remap): Remove const.
+ (CONDITIONAL_REGISTER_USAGE): For TARGET_FLAT make
+ fill leaf_reg_remap with identity.
+ * config/sparc/sparc.c (leaf_reg_remap): Remove const.
+
+2002-05-03 Kazu Hirata <kazu@cs.umass.edu>
+
+ * config/h8300/crti.asm: Remove trailing spaces.
+ * config/h8300/h8300.c: Likewise.
+ * config/h8300/lib1funcs.asm: Likewise.
+
+2002-05-02 Jason Merrill <jason@redhat.com>
+
+ * defaults.h (BOOL_TYPE_SIZE): Move default here from cp/decl.c.
+ * c-decl.c (c_init_decl_processing): Use it.
+ * config/rs6000/darwin.h (BOOL_TYPE_SIZE): Define to INT_TYPE_SIZE.
+ * config/i960/i960.h (BOOL_TYPE_SIZE): Don't define.
+ * config/mcore/mcore.h (BOOL_TYPE_SIZE): Don't define.
+
+2002-05-03 Kazu Hirata <kazu@cs.umass.edu>
+
+ * regrename.c: Fix formatting.
+ * tree.c: Likewise.
+
+Fri May 3 13:34:43 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (attribute memory): Handle compares properly.
+
+Fri May 3 10:51:38 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (sse_clrsf, sse_clrsi): Set memory attribute
+ to none.
+
+2002-05-02 Kazu Hirata <kazu@cs.umass.edu>
+
+ * function.c: Fix formatting.
+
+2002-05-02 Jan Hubicka <jh@suse.cz>
+
+ * haifa-sched.c (schedule_insn): Print table of instructions and
+ reservations.
+ (sched_block): Do not print ready list at verbosity level 1.
+ * sched-vis.c (print_insn): Make global.
+ * sched-ebb.c (ebb_print_insn): Rename from...
+ (print_insn): ... this one.
+ * sched-int.h (print_insn): Declare
+
+2002-05-02 Richard Henderson <rth@redhat.com>
+
+ * haifa-sched.c (rank_for_schedule): Skip past last_scheduled_insn
+ emitted by cycle_display.
+
+2002-05-02 Loren J. Rittle <ljrittle@acm.org>
+
+ * doc/install.texi (*-*-freebsd*): Update to latest status.
+
+2002-05-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/6540
+ * config.gcc (sparc*-*-solaris2*): Set float_format to i128.
+ * config/float-sparc.h: Assume 128-bit long double if
+ __LONG_DOUBLE_128__ is defined.
+
+2002-05-02 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genattrtab.c (write_function_unit_info): Add a dummy element
+ when num_units == 0.
+
+2002-05-02 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+
+ * predict.c: (propagate_freq, estimate_bb_frequencies): Use
+ TYPE_MODE (double_type_node) instead of DFmode.
+
+Thu May 2 19:50:04 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgrtl.c (try_redirect_by_replacing_jump): Do not kill computed
+ jumps post reload.
+ * toplev.c (rest_of_compilation): Revert Richard's patch.
+
+2001-05-02 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa/x-ada (ADA_CFLAGS): Rename to X_ADA_CFLAGS.
+
+2002-05-02 Catherine Moore <clm@redhat.com>
+
+ * config/v850/v850.h (TRAMPOLINE_TEMPLATE): Change r5 to r20.
+
+2002-05-02 Kazu Hirata <kazu@hxi.com>
+
+ * combine.c: Fix comment typos.
+ * expr.c: Likewise.
+ * genautomata.c: Likewise.
+ * stmt.c: Likewise.
+ * tree.h: Likewise.
+
+2002-05-02 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/install.texi: State GNAT version requirements.
+
+2002-05-02 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/fr30/fr30.h (GO_IF_LEGITIMATE_ADDRESS): Accept any form
+ of the frame pointer or arg pointer register which strict register
+ checking is not enabled.
+
+2002-05-02 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/altivec-8.c: New.
+
+ * config/rs6000/rs6000.c (rs6000_legitimate_address): Disallow
+ PRE_INC and PRE_DEC for altivec modes.
+
+2002-05-01 Bruce Korb <bkorb@gnu.org>
+
+ * fixinc/check.tpl(set-writable): make sure the function exists first
+ * fixinc/inclhack.def(alpha_assert): fix test_text
+ * fixinc/tests/base/assert.h: add in missing result
+
+2002-05-01 Jeff Law <law@redhat.com>
+
+ * pa.h (EXTRA_CONSTRAINT): Don't accept PIC addresses for the
+ 'T' constraint.
+
+2002-05-01 Joel Brobecker <brobecker@gnat.com>
+
+ * dbxout.c (dbxout_type): Emit size information for range types,
+ as well, but only when using GDB extensions.
+
+2002-05-01 Richard Henderson <rth@redhat.com>
+
+ * configure.in (HAVE_GAS_HIDDEN): Replace SPARC feature test with
+ target-independent gnu binutils date test.
+
+2002-05-01 Richard Henderson <rth@redhat.com>
+
+ * cfgcleanup.c (merge_blocks_move_successor_nojumps): Emit dump
+ info before expunging the block.
+
+2002-05-01 Jakub Jelinek <jakub@redhat.com>
+
+ * cppinit.c (cpp_handle_option) [-dM]: Don't set no_output here...
+ (cpp_post_options): ...but here. Disable -dD, -dN and -dI when
+ -M -or -MM is in effect.
+
+2002-05-01 Zack Weinberg <zack@codesourcery.com>
+
+ * config.gcc: Correct test of --enable-obsolete. Obsolete all
+ A29k configurations.
+ * doc/install.texi: Update to match.
+
+2002-05-01 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ PR bootstrap/6514
+ * varasm.c (globalize_decl): Compare DECL_ASSEMBLER_NAME to check
+ for duplicates. Always loop over whole list.
+
+Wed May 1 10:32:37 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * reload.c (find_reloads, case 'p'): Set BADOP to 0.
+
+2002-05-01 Joel Sherrill <joel@OARcorp.com>
+
+ * config/sparc/t-elf (sparc-rtems, sparc-elf): Build assembly
+ support routines.
+
+2002-05-01 Joel Sherrill <joel@OARcorp.com>
+
+ * config/arm/rtems-elf.h: Add #undef TARGET_VERSION to prevent warning.
+
+2002-05-01 David Edelsohn <edelsohn@gnu.org>
+
+ * rs6000.md (abssi2_nopower): Convert to define_insn_and_split.
+ (nabs_nopower): Same.
+ (floatdisf2): New pattern.
+ (absdi2): Convert to define_insn_and_split.
+ (nabsdi2): Same.
+ (trunctfsf2): Same.
+ (floatditf2): Same.
+ (floatsitf2): Same.
+ (fix_trunctfdi2): Same.
+ (fix_trunctfsi2): Same.
+
+2002-05-01 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/install.texi: Update Texinfo version requirement
+ documentation.
+
+2002-05-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/6512, PR target/5628
+ * config/sparc/sparc.md (movdf_insn_v9only_novis): Don't allow >= %f32
+ when memory is not aligned.
+ (movdf_insn_v9only_vis): Likewise.
+ * config/sparc/sparc.h (SECONDARY_INPUT_RELOAD_CLASS): Request a FP_REGS
+ temporary for EXTRA_FP_REGS DFmode load from unaligned memory.
+ (SECONDARY_OUTPUT_RELOAD_CLASS): Similarly.
+
+2002-05-01 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/altivec-7.c: New.
+
+ * config/rs6000/altivec.h: Cleanup.
+
+2002-04-30 Aldy Hernandez <aldyh@redhat.com>
+
+ * doc/invoke.texi (Option Summary): Add -mvrsave=.
+ (RS/6000 and PowerPC Options): Document -mvrsave=.
+
+ * config/rs6000/rs6000.c (rs6000_altivec_vrsave): New global.
+ (rs6000_altivec_vrsave_string): Same.
+ (rs6000_override_options): Call rs6000_parse_vrsave_option.
+ (rs6000_parse_vrsave_option): New.
+ (rs6000_stack_info): Only generate vrsave instructions when
+ TARGET_ALTIVEC_VRSAVE.
+
+ * config/rs6000/rs6000.h (TARGET_OPTIONS): Add -mvrsave= option.
+ (rs6000_altivec_vrsave_string): Define extern.
+ (rs6000_altivec_vrsave): Same.
+ (TARGET_ALTIVEC_VRSAVE): New.
+
+2002-04-30 Richard Henderson <rth@redhat.com>
+
+ PR opt/6516
+ * toplev.c (rest_of_compilation): Don't run cross-jump before
+ bb-reorder.
+
+2002-04-30 Tom Rix <trix@redhat.com>
+
+ * regrename.c (build_def_use, copyprop_hardreg_forward_1): Sanity
+ check which_alternative.
+
+2002-04-30 Kazu Hirata <kazu@hxi.com>
+
+ * cpplex.c: Fix comment formatting.
+ * function.c: Likewise.
+ * integrate.c: Likewise.
+ * regrename.c: Likewise.
+ * sibcall.c: Likewise.
+ * simplify-rtx.c: Likewise.
+ * tree-inline.c: Likewise.
+
+2002-04-30 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * config.gcc (hppa1.1-*-pro*, hppa1.1-*-osf*, hppa1.1-*-rtems*,
+ hppa1.0-*-osf*, hppa1.1-*-bsd*, hppa1.1-*-hpux10*, hppa2*-*-hpux10*,
+ hppa1.0-*-hpux10*, hppa*64*-*-hpux11*, hppa1.1-*-hpux11*,
+ hppa2*-*-hpux11*, hppa1.0-*-hpux11*, hppa*-*-lites*): Define xmake_file.
+ * pa/t-linux, pa/t-pa, pa/t-pa64, t-pro (T_ADAFLAGS): Delete.
+ * pa/x-ada: New file. Define ADA_CFLAGS.
+
+2002-04-30 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.h (MMIX_LAST_STACK_REGISTER_REGNUM): Renamed
+ from MMIX_LAST_REGISTER_FILE_REGNUM.
+ (NO_IMPLICIT_EXTERN_C): Remove cryptic obsolete comment.
+ (struct machine_function): New member highest_saved_stack_register
+ previously static variable in mmix.c.
+ (MACHINE_DEPENDENT_REORG): Define.
+ * config/mmix/mmix.c (highest_saved_stack_register): Deleted.
+ (MMIX_OUTPUT_REGNO): New.
+ (mmix_target_asm_function_prologue): Move calculation of last used
+ saved-stack-register into...
+ (mmix_machine_dependent_reorg): New function. Update to also handle
+ !TARGET_ABI_GNU.
+ (mmix_print_operand): Apply MMIX_OUTPUT_REGNO when emitting
+ register names, simplify somewhat by new variable regno.
+ <case 'p'>: Remove fixed FIXME. Always emit highest used saved
+ register.
+ (mmix_print_operand_address): Apply MMIX_OUTPUT_REGNO when
+ emitting register names.
+ (mmix_asm_output_reg_push, mmix_asm_output_reg_pop): Ditto.
+ (mmix_dbx_register_number): Apply MMIX_OUTPUT_REGNO here too.
+ Remove fixed FIXME.
+ * config/mmix/mmix-protos.h (mmix_machine_dependent_reorg):
+ Declare.
+
+ * config/mmix/mmix.md ("divmoddi4"): Update head comment.
+
+2002-04-30 Richard Henderson <rth@redhat.com>
+
+ * config/sparc/sparc.c (emit_soft_tfmode_libcall,
+ emit_soft_tfmode_binop, emit_soft_tfmode_unop, emit_soft_tfmode_cvt,
+ emit_hard_tfmode_operation, emit_tfmode_binop, emit_tfmode_unop,
+ emit_tfmode_cvt): New.
+ * config/sparc/sparc.md (extendsftf2, extenddftf2, trunctfsf2,
+ trunctfdf2, floatsitf2, floatunssitf2, floatditf2, floatunsditf2,
+ fix_trunctfsi2, fixuns_trunctfsi2, fix_trunctfdi2, fixuns_trunctfdi2,
+ addtf3, subtf3, multf3, divtf3, sqrttf2): Use them.
+ * config/sparc/sparc-protos.h: Update.
+
+2002-04-30 Janis Johnson <janis187@us.ibm.com>
+
+ * install.texi (Final install): Add to the list of info to include
+ in a report of a successful bootstrap, and add link to 3.1 list.
+
+Tue Apr 30 19:15:36 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (type): Add new SSE/MMX subtypes, remove usused fop1.
+ (mode): Add vector modes
+ (i387): Kill attribute.
+ (unit): New attribute.
+ (length_immediate): Grok new types.
+ (prefix_data16, prefix_rep, prefix_0f): Fix for SSE/MMX.
+ (modrm): Use "unit".
+ (memory): Handle MMX/SSE properly.
+ (scheduling descriptions): Kill uses of fop1.
+ (sse, mmx, fp patterns): Set type and mode properly.
+
+Tue Apr 30 09:31:59 2002 Jeffrey A Law (law@redhat.com)
+
+ * pa.c (override_options): Default to PA8000 scheduling.
+ * doc/invoke.texi (HP-PA options): Mention newly added 7300
+ scheduling parameter.
+
+ * pa.md (7100lc, 7200, 7300 scheduling): Slightly refine
+ handling of double precision multiplies.
+
+ * pa.md (7100lc, 7200, 7300 scheduling): Refine handling of
+ fpdiv and fpsqrt instructions.
+ (7200 & 7300 scheduling): Fix typo in handling of
+ store-load and store-store penalties.
+
+2002-04-30 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/contrib.texi (Contributors): Use MIPS instead of Mips and
+ mips. Add two missing commas.
+
+2002-04-30 Paolo Carlini <pcarlini@unitus.it>
+
+ * doc/contrib.texi (Contributors): Update Paolo Carlini's
+ and Benjamin Kosnik's entries.
+
+2002-04-29 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.h (BRANCH_COST, PREFETCH_BLOCK,
+ SIMULTANEOUS_PREFETCHES): Tune for UltraSPARC-III.
+ * config/sparc/sparc.md (call + jmp 32-bit peepholes): Likewise.
+ * config/sparc/sparc.c (sparc_initialize_trampoline): Likewise.
+
+2002-04-29 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ * combine.c (find_split_point): Use gen_int_mode.
+
+2002-04-29 Vladimir Makarov <vmakarov@redhat.com>
+
+ Merging code from dfa-branch:
+
+ 2002-04-24 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (output_reserv_sets): Fix typo.
+
+ 2002-04-23 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (output_reserv_sets): Remove
+ next_cycle_output_flag.
+
+ Thu Apr 18 08:57:06 2002 Jeffrey A Law (law@redhat.com)
+
+ * sched-rgn.c (init_ready_list): Make the DFA code handle
+ USE/CLOBBER insns in the same way as the traditional
+ scheduler.
+ (new_ready): Similarly..
+
+ 2002-04-17 Vladimir Makarov <vmakarov@redhat.com>
+
+ * haifa-sched.c (schedule_block): Change the DFA state only after
+ issuing insn.
+
+ Wed Apr 17 15:38:36 2002 Jeffrey A Law (law@redhat.com)
+
+ * pa.c (hppa_use_dfa_pipeline_interface): New function.
+ (TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE): Define.
+ (override_options): Add PA7300 scheduling support.
+ (pa_adjust_cost): Update various comments. Properly
+ handle anti and output dependencies when using the
+ DFA scheduler.
+ (pa_issue_rate): Add PA7300 scheduling support.
+ (pa_can_combine_p): Call extract_insn before calling
+ constrain_operands (taken from mainline tree).
+ * pa.h (enum processor_type): Add PROCESSOR_PA7300.
+ * pa.md (cpu attr): Add 7300. Rewrite pipeline
+ descriptions using DFA descriptions. Add PA7300
+ scheduling support.
+
+ 2002-03-30 David S. Miller <davem@redhat.com>
+
+ Add UltraSPARC-III DFA scheduling support.
+ * config/sparc/sparc.md (define_attr type): Add fpcrmove.
+ Update FP conditional move on register insn patterns to use it, as
+ appropriate.
+ (define_attr cpu): Add ultrasparc3.
+ (define_attr us3load_type): New, update integer load patterns to
+ set it, as appropriate.
+ (define_automaton): Add ultrasparc3_0 and ultrasparc3_1.
+ (rest): Add UltraSPARC3 scheduling description.
+ * config/sparc/sparc.h (TARGET_CPU_ultrasparc3): New.
+ (PROCESSOR_ULTRASPARC3): New.
+ ({ASM,CPP}_CPU64_DEFAULT_SPEC): Handle ultrasparc3.
+ ({ASM,CPP}_CPU_SPEC): Likewise.
+ (REGISTER_MOVE_COST): Likewise.
+ (RTX_COSTS): Likewise.
+ * config/sparc/sparc.c (sparc_override_options,
+ sparc_initialize_trampoline, sparc64_initialize_trampoline,
+ sparc_use_dfa_pipeline_interface, sparc_use_sched_lookahead,
+ sparc_issue_rate): Likewise.
+ * config/sparc/sol2.h: Likewise.
+ * config/sparc/sol2-sld-64.h: Likewise.
+ * config/sparc/linux64.h: Likewise.
+
+ 2002-03-22 Vladimir Makarov <vmakarov@redhat.com>
+
+ * doc/md.texi: Add comments about usage the latency time for the
+ different dependencies and about case when two or more conditions
+ in different define_insn_reservations returns TRUE for an insn.
+
+ * doc/md.texi: Add reference for automaton based pipeline
+ description.
+
+ 2002-03-04 Vladimir Makarov <vmakarov@redhat.com>
+
+ * doc/passes.texi: Add missed information about genattrtab.
+
+ 2002-03-01 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (output_automata_list_transition_code): Check
+ automata_list on NULL.
+
+ 2002-02-28 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (output_insn_code_cases,
+ output_automata_list_min_issue_delay_code,
+ output_automata_list_transition_code,
+ output_automata_list_state_alts_code): Comment the functions.
+
+ 2002-02-22 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (automata_list_el_t): New typedef.
+ (get_free_automata_list_el,free_automata_list_el,
+ free_automata_list, automata_list_hash, automata_list_eq_p,
+ initiate_automata_lists, automata_list_start, automata_list_add,
+ automata_list_finish, finish_automata_lists,
+ output_insn_code_cases, output_automata_list_min_issue_delay_code,
+ output_automata_list_transition_code,
+ output_automata_list_state_alts_code, add_automaton_state,
+ form_important_insn_automata_lists): New functions and prototypes.
+ (insn_reserv_decl): Add members important_automata_list and
+ processed_p.
+ (ainsn): Add members important_p.
+ (automata_list_el): New structure.
+ (first_free_automata_list_el, current_automata_list,
+ automata_list_table): New global variables.
+ (create_ainsns): Initiate member important_p.
+ (output_internal_min_issue_delay_func): Generate the switch and
+ call output_insn_code_cases.
+ (output_internal_trans_func, output_internal_state_alts_func):
+ Ditto.
+ (generate): Call initiate_automata_lists.
+ (automaton_states): New global variable.
+ (expand_automata): Call form_important_insn_automata_lists.
+ (write_automata): Call finish_automata_lists.
+
+ 2002-02-21 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (add_excls, add_presence_absence): Check that
+ cpu units in the sets belong the same automaton.
+
+ * rtl.def (EXCLUSION_SET, PRESENCE_SET, ABSENCE_SET): Add comment
+ about that cpu units in the sets belong the same automaton.
+
+ * doc/md.texi: Ditto.
+
+ 2001-12-20 Naveen Sharma <naveens@noida.hcltech.com>
+ Nitin Gupta <niting@noida.hcltech.com>
+
+ * config/sh/sh.c (sh_use_dfa_interface): New function.
+
+ (sh_issue_rate): New Function.
+ TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE: define.
+ TARGET_SCHED_ISSUE_RATE: define.
+
+ * config/sh/sh.md: Add DFA based pipeline description for SH4.
+
+ (define_attr insn_class): New attribute used for DFA
+ scheduling.
+ (define_insn cmpgtsi_t): Set attribute insn_class mt_group.
+ (cmpgesi_t,cmpgtusi_t,cmpgeusi_t,cmpeqsi_t,
+ cmpeqdi_t): Likewise.
+
+ (add,addc1,addsi3,subc,subc1,*subsi3_internal,
+ negc,negsi2,ashldi3_k,lshrdi3_k,ashrdi3_k): Set insn_class
+ ex_group.
+ (iorsi3,rotlsi3_1,rotlsi3_31,rotlsi3_16): Likewise.
+
+ 2001-10-03 Vladimir Makarov <vmakarov@toke.toronto.redhat.com>
+
+ * haifa-sched.c (queue_to_ready): Remove unnecessary condition for
+ break.
+
+ 2001-10-03 Vladimir Makarov <vmakarov@toke.toronto.redhat.com>
+
+ * genautomata.c (DFA_INSN_CODES_LENGTH_VARIABLE_NAME): New macro.
+ (output_dfa_insn_code_func): Expand dfa_insn_codes if it is
+ necessary.
+ (output_dfa_start_func): Initiate new variable insn_codes_length,
+ (write_automata): Output definition of the new variable.
+
+ 2001-10-02 David S. Miller <davem@redhat.com>
+
+ * haifa-sched.c (advance_one_cycle): New function.
+ (schedule_block): Use it.
+ (queue_to_ready): Use it, and also make sure to advance the DFA
+ state on all stall cycles, not just those where insn_queue links
+ are found.
+
+ 2001-10-02 Richard Sandiford <rsandifo@redhat.com>
+
+ * haifa-sched.c (max_issue): Remove last_p argument. Only return
+ nonzero if the highest-priority instruction could be scheduled.
+ (choose_ready): Remove last argument from max_issue call.
+
+ 2001-09-28 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.c (sparc_use_sched_lookahead): Use 4 for
+ ultrasparc and 3 for other multi-issue sparcs.
+
+ 2001-09-27 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.md (cycle_display): New pattern.
+ * config/sparc/sparc.c (sparc_cycle_display): New.
+ (TARGET_SCHED_CYCLE_DISPLAY): Set it.
+
+ 2001-09-25 David S. Miller <davem@redhat.com>
+
+ Convert all of SPARC scheduling to DFA
+ * config/sparc/sparc.md: Kill all define_function_unit
+ directives and replace with DFA equivalent.
+ * config/sparc/sparc.c (ultrasparc_adjust_cost,
+ mark_ultrasparc_pipeline_state, ultra_cmove_results_ready_p,
+ ultra_fpmode_conflict_exists, ultra_find_type,
+ ultra_build_types_avail, ultra_flush_pipeline,
+ ultra_rescan_pipeline_state, ultrasparc_sched_reorder,
+ ultrasparc_variable_issue, ultrasparc_sched_init,
+ sparc_variable_issue, sparc_sched_reorder, ultra_code_from_mask,
+ ultra_schedule_insn, ultra_code_names, ultra_pipe_hist,
+ ultra_cur_hist, ultra_cycles_elapsed): Kill.
+ (sparc_use_dfa_pipeline_interface, sparc_use_sched_lookahead,
+ ultrasparc_store_bypass_p): New.
+ * config/sparc/sparc-protos.h (ultrasparc_store_bypass_p):
+ Declare.
+
+ 2001-09-24 David S. Miller <davem@redhat.com>
+
+ * haifa-sched.c (ready_remove): Fix thinko, we want to copy around
+ ready->vec[foo] not ready[foo].
+
+ 2001-09-07 Vladimir Makarov <vmakarov@redhat.com>
+
+ * doc/md.texi: Correct examples for define_insn_reservations
+ `mult' and `div'.
+
+ 2001-09-07 Vladimir Makarov <vmakarov@redhat.com>
+
+ * genautomata.c (create_automata): Print message about creation of
+ each automaton.
+ (generate): Remove printing meease about creation of
+ automata.
+
+ 2001-09-05 David S. Miller <davem@redhat.com>
+
+ * config/sparc/linux.h: Set CPLUSPLUS_CPP_SPEC.
+ * config/sparc/linux64.h: Likewise.
+
+ 2001-08-31 Vladimir Makarov <vmakarov@redhat.com>
+
+ * haifa-sched.c (insn_cost, schedule_insn, queue_to_ready,
+ schedule_block, sched_init, sched_finish): Add missed calls of
+ use_dfa_pipeline_interface.
+
+ * sched-rgn.c (init_ready_list, new_ready, debug_dependencies):
+ Ditto.
+
+ * sched-vis.c (get_visual_tbl_length): Ditto.
+
+ 2001-08-27 Richard Henderson <rth@redhat.com>
+
+ * genattr.c (main): Emit state_t even when not doing scheduling.
+
+ 2001-08-27 Richard Henderson <rth@redhat.com>
+
+ * genautomata.c (expand_automata): Always create a description.
+
+ 2001-08-27 Vladimir Makarov <vmakarov@touchme.toronto.redhat.com>
+
+ * rtl.def (DEFINE_CPU_UNIT, DEFINE_QUERY_CPU_UNIT, EXCLUSION_SET,
+ PRESENCE_SET, ABSENCE_SET, DEFINE_BYPASS, DEFINE_AUTOMATON,
+ AUTOMATA_OPTION, DEFINE_RESERVATION, DEFINE_INSN_RESERVATION): New
+ RTL constructions.
+
+ * genattr.c (main): New variable num_insn_reservations. Increase
+ it if there is DEFINE_INSN_RESERVATION. Output automaton based
+ pipeline hazard recognizer interface.
+
+ * genattrtab.h: New file.
+
+ * genattrtab.c: Include genattrtab.h.
+ (attr_printf, check_attr_test, make_internal_attr,
+ make_numeric_value): Move protypes into genattrtab.h. Define them
+ as external.
+ (num_dfa_decls): New global variable.
+ (main): Process DEFINE_CPU_UNIT, DEFINE_QUERY_CPU_UNIT,
+ DEFINE_BYPASS, EXCLUSION_SET, PRESENCE_SET, ABSENCE_SET,
+ DEFINE_AUTOMATON, AUTOMATA_OPTION, DEFINE_RESERVATION,
+ DEFINE_INSN_RESERVATION. Call expand_automata and write_automata.
+
+ * genautomata.c: New file.
+
+ * rtl.h (LINK_COST_ZERO, LINK_COST_FREE): Remove them.
+
+ * sched-int.h: (curr_state): Add the external definition for
+ automaton pipeline interface.
+ (haifa_insn_data): Add comments for members blockage and units.
+
+ * target-def.h (TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE,
+ TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN,
+ TARGET_SCHED_DFA_PRE_CYCLE_INSN,
+ TARGET_SCHED_INIT_DFA_POST_CYCLE_INSN,
+ TARGET_SCHED_DFA_POST_CYCLE_INSN,
+ TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD,
+ TARGET_SCHED_INIT_DFA_BUBBLES, TARGET_SCHED_DFA_BUBBLE): New
+ macros.
+ (TARGET_SCHED): Use the new macros.
+
+ * target.h (use_dfa_pipeline_interface, init_dfa_pre_cycle_insn,
+ dfa_pre_cycle_insn, init_dfa_post_cycle_insn, dfa_post_cycle_insn,
+ first_cycle_multipass_dfa_lookahead, init_dfa_bubbles,
+ dfa_bubble): New members in gcc_target.sched.
+
+ * haifa-sched.c (insert_schedule_bubbles_p): New variable.
+ (MAX_INSN_QUEUE_INDEX): New macro for automaton interface.
+ (insn_queue): Redefine it as pointer to array.
+ (NEXT_Q, NEXT_Q_AFTER): Use MAX_INSN_QUEUE_INDEX instead of
+ INSN_QUEUE_SIZE.
+ (max_insn_queue_index_macro_value): New variable.
+ (curr_state, dfa_state_size, ready_try): New varaibles for
+ automaton interface.
+ (ready_element, ready_remove, max_issue): New function prototypes
+ for automaton interface.
+ (choose_ready): New function prototype.
+ (insn_unit, blockage_range): Add comments.
+ (unit_last_insn, unit_tick, unit_n_insns): Define them for case
+ FUNCTION_UNITS_SIZE == 0.
+ (insn_issue_delay, actual_hazard_this_instance, schedule_unit,
+ actual_hazard, potential_hazard): Add comments.
+ (insn_cost): Use cost -1 as undefined value. Remove
+ LINK_COST_ZERO and LINK_COST_FREE. Add new code for automaton
+ pipeline interface.
+ (ready_element, ready_remove): New functions for automaton
+ interface.
+ (schedule_insn): Add new code for automaton pipeline interface.
+ (queue_to_ready): Add new code for automaton pipeline interface.
+ Use MAX_INSN_QUEUE_INDEX instead of INSN_QUEUE_SIZE.
+ (debug_ready_list): Print newline when the queue is empty.
+ (max_issue): New function for automaton pipeline interface.
+ (choose_ready): New function.
+ (schedule_block): Add new code for automaton pipeline interface.
+ Print ready list before scheduling each insn.
+ (sched_init): Add new code for automaton pipeline interface.
+ Initiate insn cost by -1.
+ (sched_finish): Free the current automaton state and finalize
+ automaton pipeline interface.
+
+ * sched-rgn.c: Include target.h.
+ (init_ready_list, new_ready, debug_dependencies): Add new code for
+ automaton pipeline interface.
+
+ * sched-vis.c: Include target.h.
+ (get_visual_tbl_length): Add code for automaton interface.
+ (target_units, print_block_visualization): Add comments.
+
+ * Makefile.in (GETRUNTIME, HASHTAB, HOST_GETRUNTIME, HOST_HASHTAB,
+ USE_HOST_GETRUNTIME, USE_HOST_HASHTAB, HOST_VARRAY): New variables.
+ (sched-rgn.o, sched-vis.o): Add new dependency file target.h.
+ (getruntime.o, genautomata.o): New entries.
+ (genattrtab.o): Add new dependency file genattrtab.h.
+ (genattrtab): Add new dependencies. Link it with `libm.a'.
+ (getruntime.o, hashtab.o): New entries for canadian cross.
+
+ * doc/md.texi: Description of automaton based model.
+
+ * doc/tm.texi (TARGET_SCHED_ISSUE_RATE, TARGET_SCHED_ADJUST_COST):
+ Add comments.
+ (TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE,
+ TARGET_SCHED_DFA_PRE_CYCLE_INSN,
+ TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN,
+ TARGET_SCHED_DFA_POST_CYCLE_INSN,
+ TARGET_SCHED_INIT_DFA_POST_CYCLE_INSN,
+ TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD,
+ TARGET_SCHED_INIT_DFA_BUBBLES, TARGET_SCHED_DFA_BUBBLE): The new
+ hook descriptions.
+ (TRADITIONAL_PIPELINE_INTERFACE, DFA_PIPELINE_INTERFACE,
+ MAX_DFA_ISSUE_RATE): New macro descriptions.
+
+ * doc/contrib.texi: Add dfa based scheduler contribution.
+
+ * doc/gcc.texi: Add more information about genattrtab.
+
+Mon Apr 29 17:19:10 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * reload1.c (eliminate_regs, case SUBREG): Fix typo in
+ adjust_address_nv call.
+
+2002-04-29 Janis Johnson <janis187@us.ibm.com>
+
+ * doc/install.texi (Testing): Provide additional information, and
+ a stronger encouragement, for running the testsuites.
+
+2002-04-29 DJ Delorie <dj@redhat.com>
+
+ * config/mips/mips.c (mips_parse_cpu): Warn if the CPU name is
+ given in upper case.
+
+2002-04-29 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * fixinc/inclhack.def (solaris_widec): Include <wchar.h> in
+ Solaris 2 <widec.h> if missing.
+ * fixinc/fixincl.x: Regenerate.
+ * fixinc/tests/base/widec.h: New file.
+
+2002-04-29 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * toplev.c (f_options): Add "profile" switch so that
+ -fno-profile can be used to disable -p.
+
+2002-04-29 Bernd Schmidt <bernds@redhat.com>
+
+ * c-common.c (type_for_mode): Add support for V2DFmode, V2DImode,
+ UV2DImode.
+ * tree.c (build_common_tree_nodes_2): Likewise.
+ * tree.h (enum tree_index): Likewise.
+ (V2DF_type_node, V2DI_type_node, unsigned_V2DI_type_node): Define.
+
+ * config/i386/i386.c (bdesc_comi, bdesc_2arg, bdesc_1arg): Add SSE2
+ entries.
+ (init_mmx_sse_builtins): Initialize SSE2 builtins.
+ (ix86_expand_builtin): Add support for SSE2 builtins.
+ * config/i386/i386.h (VALID_SSE2_REG_MODE): New macro.
+ (VALID_SSE_REG_MODE): Use it.
+ (VECTOR_MODE_SUPPORTED_P): Allow SSE2 modes here as well.
+ (enum ix86_builtins): Add SSE2 builtins.
+ * config/i386/i386.md (movv2df_internal, movv2df, movv8hi_internal,
+ movv8hi, movv16qi_internal, movv16qi, pushv2df, pushv8hi, pushv16qi,
+ addv2df3, vmaddv2df3, subv2df3, vmsubv2df3, mulv2df3, vmmulv2df3,
+ divv2df3, vmdivv2df3, smaxv2df3, vmsmaxv2df3, sminv2df3, vmsminv2df3,
+ sse2_anddf3, sse2_nanddf3, sse2_iordf3, sse2_xordf3, sqrtv2df2,
+ vmsqrtv2df2, maskcmpv2df3, maskncmpv2df3, vmmaskcmpv2df3,
+ vmmaskncmpv2df3, sse2_comi, sse2_ucomi, sse2_movmskpd, sse2_pmovmskb,
+ sse2_maskmovdqu, sse2_movntv2df, sse2_movntti, sse2_movntsi, cvtdq2ps,
+ cvtps2dq, cvttps2dq, cvtdq2pd, cvtpd2dq, cvttpd2dq, cvtpd2pi,
+ cvttpd2pi, cvtpi2pd, cvtsd2si, cvttsd2si, cvtsi2sd, cvtsd2ss,
+ cvtss2sd, cvtpd2ps, cvtps2pd, addv16qi3, addv8hi3, addv4si3, addv2di3,
+ ssaddv16qi3, ssaddv8hi3, usaddv16qi3, usaddv8hi3, subv16qi3, subv8hi3,
+ subv4si3, subv2di3, sssubv16qi3, sssubv8hi3, ussubv16qi3, ussubv8hi3,
+ mulv8hi3, smulv8hi3_highpart, umulv8hi3_highpart, sse2_umulsidi3,
+ sse2_umulv2siv2di3, sse2_pmaddwd, sse2_clrti, sse2_uavgv16qi3,
+ sse2_uavgv8hi3, sse2_psadbw, sse2_pinsrw, sse2_pextrw, sse2_pshufd,
+ sse2_pshuflw, sse2_pshufhw, eqv16qi3, eqv8hi3, eqv4si3, gtv16qi3,
+ gtv8hi3, gtv4si3, umaxv16qi3, smaxv8hi3, uminv16qi3, sminv8hi3,
+ ashrv8hi3, ashrv4si3, lshrv8hi3, lshrv4si3, sse2_lshrv2di3,
+ ashlv8hi3, ashlv4si3, sse2_ashlv2di3, sse2_ashlti3, sse2_lshrti3,
+ sse2_unpckhpd, sse2_unpcklpd, sse2_packsswb, sse2_packssdw,
+ sse2_packuswb, sse2_punpckhbw, sse2_punpckhwd, sse2_punpckhdq,
+ sse2_punpcklbw, sse2_punpcklwd, sse2_punpckldq, sse2_movapd,
+ sse2_movupd, sse2_movdqa, sse2_movdqu, sse2_movdq2q, sse2_movq2dq,
+ sse2_movhpd, sse2_movlpd, sse2_loadsd, sse2_movsd, sse2_storesd,
+ sse2_shufpd, sse2_clflush, sse2_mfence, mfence_insn, sse2_lfence,
+ lfence_insn): New patterns.
+ (sse2_andti3, sse2_nandti3, sse2_iorti3, sse2_xorti3): Renamed from
+ sse_andti3_sse2, sse_nandti3_sse2, sse_iorti3_sse2, sse_xorti3_sse2.
+
+Mon Apr 29 17:03:24 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (sse_mov?fcc*): Revert patch of Mar 14th.
+
+2002-04-29 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/contrib.texi (Contributors): Add Paolo Carlini and
+ Janis Johnson.
+ Update Richard Henderson, Jakub Jelinek, and Mark Mitchell.
+ Refer to Objective-C instead of ObjC, SPARC instead of sparc,
+ and CPU instead of cpu.
+
+Mon Apr 29 13:36:41 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * toplev.c (flag_if_conversion, flag_if_conversion2): New static
+ variables.
+ (lang_independent_options): Add -fif-conversion, -fif-conversion2
+ (rest_of_compilation): Do if conversion only when asked for.
+ (parse_options_and_default_flags): Set new variables to 1 for -O1
+ * invoke.texi (-fif-conversion, -fif-conversion2): Document.
+
+Mon Apr 29 13:02:50 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (dbx64_register_map): Fix typo.
+
+Mon Apr 29 12:18:35 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * predict.c (real_zero, real_one, real_almost_one, real_br_prob_base,
+ real_one_half, real_bb_freq_max): New static variables.
+ (debug_profile_bbauxs): Kill.
+ (process_note_predictions): Kill unused variable.
+ (block_info_def, edge_info_def): Use REAL_VALUE_TYPE instead of
+ volatile double.
+ (propagate_freq): Use REAL_ARITHMETICS.
+ (estimate_bb_frequencies): Likevise; init new static variables.
+ * Makefile.in (predict.o): Add dependency on real.h
+
+2002-04-28 David S. Miller <davem@redhat.com>
+
+ PR target/6500
+ * config/sparc/sparc.md (prefetch): Emit properly for 32-bit vs.
+ 64-bit TARGET_V9. Do not use prefetch page, use prefetch for
+ several {reads,writes} instead.
+ * config/sparc/sparc.h (PREFETCH_BLOCK, SIMULTANEOUS_PREFETCHES):
+ Define.
+
+2002-04-27 David S. Miller <davem@redhat.com>
+
+ PR target/6494
+ * config/sparc/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Be mindful
+ of the stack bias.
+
+ * config/sparc/linux.h, config/sparc/linux64.h: Don't bother
+ including signal.h and sys/ucontext.h, not needed.
+
+2002-04-29 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * varasm.c (output_constant_def): Correct test for not calling
+ ENCODE_SECTION_INFO for INTEGER_CST.
+
+2002-04-29 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppexp.c (lex): Move some code to _cpp_parse_expr, but
+ keep most cases as function eval_token.
+ (eval_token): New function.
+ (_cpp_parse_expr): Read token here for improved diagnostics.
+ Don't use op_as_text. Detect bad ':' here.
+ (reduce): Don't detect bad ':' here.
+ (op_as_text): Remove.
+ * cpphash.h (_cpp_test_assertion): Change prototype.
+ * cpplib.c (_cpp_test_assertion): Change prototype.
+
+2002-04-28 Richard Henderson <rth@redhat.com>
+
+ PR c/5154
+ * ggc-common.c (ggc_mark_rtx_children_1): Rename from...
+ (ggc_mark_rtx_children): New.
+
+2002-04-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/6496
+ * config/sparc/sparc.md (call + jump 32-bit peepholes): Disable jump
+ after call peepholes for UltraSPARC.
+ (call + jump 64-bit peepholes): Remove.
+
+2002-04-28 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ PR c/6497
+ * config/rs6000/rs6000.md (sCC patterns): Remove clobber and use
+ result as temporary value.
+
+2002-04-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/6396
+ * toplev.c (rest_of_compilation): Only run regrename and copy
+ propagation if optimizing.
+
+2002-04-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR optimization/6475
+ * reload1.c (alter_reg): Only call set_mem_expr if I is home pseudo
+ register of REGNO_DECL (i).
+ * Makefile.in (reload1.o): Add $(TREE_H).
+
+2002-04-28 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppexp.c (lex): Update to use state.skip_eval.
+ (struct op): Remove prio and flags members.
+ (FLAG_BITS, FLAG_MASK, PRIO_SHIFT, EXTRACT_PRIO, EXTRACT_FLAGS,
+ SHORT_CIRCUIT, RIGHT_ASSOC, ..._PRIO, op_to_prio): Remove.
+ (LEFT_ASSOC): New macro.
+ (optab): New table of operator priorities and flags.
+ (SHIFT): Update.
+ (_cpp_parse_expr): Clean up logic. Return bool. Use a
+ malloc-ed parser stack.
+ (reduce): New; reduce the operator stack.
+ (_cpp_expand_op_stack): Expand the operator stack as necessary.
+ * cpphash.h (struct op): Predeclare.
+ (struct cpp_reader): New members op_stack, op_limit.
+ (struct lexer_state): New member skip_eval.
+ (_cpp_parse_expr): Update.
+ (_cpp_expand_op_stack): New.
+ * cpplib.c (do_if): Update.
+ * cppinit.c (cpp_create_reader): Create op stack.
+ (cpp_destroy): And destroy it.
+ * cpplib.h (CPP_LAST_CPP_OP): Correct.
+ (TTYPE_TABLE): Correct.
+
+2002-04-28 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ PR c/6343
+ * c-decl.c (duplicate_decls): Call merge_weak.
+ * c-pragma.c (apply_pragma_weak): Warn about misuse.
+ * output.h (merge_weak): Prototype merge_weak.
+ * varasm.c (merge_weak): New function.
+ (declare_weak): Make sure we don't give an error on VAR_DECLs.
+ Mark RTL with SYMBOL_REF_WEAK.
+
+2002-04-27 Kurt Garloff <garloff@suse.de>
+
+ * tree-inline.c (inlinable_function_p): Improve heuristics
+ by using a smoother function to cut down allowable inlinable size.
+ * param.def: Add parameters max-inline-insns-single,
+ max-inline-slope, min-inline-insns that determine the exact
+ shape of the above function.
+ * param.h: Likewise.
+
+2002-04-26 Richard Henderson <rth@redhat.com>
+
+ * c-parse.in (malloced_yyss, malloced_yyvs): New.
+ (yyoverflow): Re-add. Set them.
+ (free_parser_stacks): New.
+ * c-common.h: Declare it.
+ * c-lex.c (c_common_parse_file): Call it.
+
+2002-04-26 Richard Henderson <rth@redhat.com>
+
+ * cfgrtl.c (tidy_fallthru_edge): Don't use next_real_insn
+ for fallthru search.
+
+2002-04-26 Eric Christopher <echristo@redhat.com>
+
+ PR optimization/3700
+ * config/mips/mips.c (mips_issue_rate): Define. New function.
+ (TARGET_SCHED_ISSUE_RATE): Use.
+
+2002-04-25 David S. Miller <davem@redhat.com>
+
+ PR target/6422
+ * reorg.c (optimize_skip): Do not allow exception causing
+ instructions to be considered for delay slots.
+ (fill_simply_delay_slots, fill_slots_from_thread): Likewise.
+ (relax_delay_slots): Do not try to consider exception causing
+ instructions as redundant.
+
+2002-04-26 Richard Henderson <rth@redhat.com>
+
+ PR c/5225
+ * c-typeck.c (build_unary_op) [CONVERT_EXPR]: Invoke non_lvalue.
+
+2002-04-26 Mark Mitchell <mark@codesourcery.com>
+
+ PR bootstrap/6445
+ * config/i386/i386.md (untyped_call): Return the value in a float
+ register if TARGET_FLOAT_RETURNS_IN_80387, not just if
+ TARGET_80387.
+
+2002-04-26 Alexandre Oliva <aoliva@redhat.com>
+
+ * tree.c (tree_int_cst_lt): Compare constants whose types differ
+ in unsigned-ness correctly.
+
+2002-04-26 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.h (FUNCTION_OK_FOR_SIBCALL): Don't do sibcalls when using the
+ portable runtime model.
+
+2002-04-26 Richard Henderson <rth@redhat.com>
+
+ * c-parse.in (yyoverflow): Revert.
+
+2002-04-26 David Edelsohn <edelsohn@gnu.org>
+ Richard Henderson <rth@redhat.com>
+
+ * config/rs6000/rs6000.md (sCC pattern): Remove clobber and use
+ result as temporary value.
+
+2002-04-26 Richard Henderson <rth@redhat.com>
+
+ PR c/3581
+ * c-common.c (fix_string_type): Split out of ...
+ (combine_strings): ... here. Take a varray, not a tree list.
+ (c_expand_builtin_printf): Use fix_string_type.
+ * c-common.h: Update decls.
+ * c-parse.in (string): Remove. Update all uses to use STRING
+ instead, and not call combine_strings.
+ (yylexstring): New.
+ (_yylex): Use it.
+ * c-typeck.c (simple_asm_stmt): Don't call combine_strings.
+ (build_asm_stmt): Likewise.
+ * objc/objc-act.c (my_build_string): Use fix_string_type.
+ (build_objc_string_object): Build varray for combine_strings.
+
+2002-04-26 Bo Thorsen <bo@suse.co.uk>
+
+ * config/i386/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Define for
+ x86-64.
+
+2002-04-26 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppexp.c (CPP_UMINUS, CPP_UPLUS): New.
+ (HAVE_NO_R_OPERAND): Remove.
+ (HAVE_VALUE): Remove.
+ (op_to_prio): Update.
+ (UNARY): Don't alter flags.
+ (_cpp_parse_expr): want_value used to indicate whether
+ a number or unary operator is expected next. Distinguish
+ unary and binary +/-.
+ (op_as_text): Update for unary operators.
+
+2002-04-25 Richard Henderson <rth@redhat.com>
+
+ PR c/2161
+ * c-parse.in (yyoverflow): New.
+
+2002-04-25 Richard Henderson <rth@redhat.com>
+
+ PR c/2098
+ * c-common.c (shorten_compare): Simplfy conditions leading to
+ the generation of a warning.
+
+2002-04-25 Richard Henderson <rth@redhat.com>
+
+ PR c/2035
+ * expmed.c (extract_bit_field): Fall through to generic code rather
+ than aborting on subreg special case.
+
+2002-04-25 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.h (FUNCTION_OK_FOR_SIBCALL): Add back check
+ for DECL being NULL.
+
+2002-04-25 Steve Christiansen <smc@us.ibm.com>
+
+ * doc/md.texi (Machine Constraints): Add IA-64 constraints.
+
+2002-04-25 Eric Botcazou <ebotcazou@multimania.com>
+
+ * c-decl.c (grokdeclarator): Remove outdated ??? note
+ on invalid declaration of flexible array members.
+
+2002-04-25 Richard Henderson <rth@redhat.com>
+
+ * doc/invoke.texi: Document -gdwarf{,-2} vs debug level.
+
+2002-04-25 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.c (s390_emit_epilogue): Always restore registers
+ needed by the compiler, even if they are used as global regs.
+
+2002-04-25 Matt Hiller <hiller@redhat.com>
+
+ * mips.c (mips_class_max_nregs, mips_register_move_cost): New
+ functions.
+ * mips.h (CLASS_MAX_NREGS, REGISTER_MOVE_COST): Redefine as calls
+ of the corresponding functions.
+ * mips-protos.h (mips_class_max_nregs, mips_register_move_cost):
+ New prototypes.
+
+2002-04-25 Matt Hiller <hiller@redhat.com>
+
+ * config/mips/mips.h (mips_sw_reg_names): Declare as extern.
+
+ (ALL_COP_ADDITIONAL_REGISTER_NAMES): New macro.
+ (FIRST_PSEUDO_REGISTER): Redefine considering coprocessor
+ registers, adjust comment accordingly.
+ (FIXED_REGISTERS, CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS,
+ reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS, REGISTER_NAMES,
+ DEBUG_REGISTER_NAMES, REG_ALLOC_ORDER): Adjust to include entries
+ for coprocessor registers.
+ (ADDITIONAL_REGISTER_NAMES): Include
+ ALL_COP_ADDITIONAL_REGISTER_NAMES.
+
+ (COP0_REG_FIRST, COP0_REG_LAST, COP0_REG_NUM,
+ COP2_REG_FIRST, COP2_REG_LAST, COP2_REG_NUM,
+ COP3_REG_FIRST, COP3_REG_LAST, COP3_REG_NUM,
+ COP0_REG_P, COP2_REG_P, COP3_REG_P, ALL_COP_REG_P,
+ COPNUM_AS_CHAR_FROM_REGNUM, COP_REG_CLASS_P): New macros.
+
+ (mips_char_to_class): Adjust comment to include coprocessor
+ constraint letters.
+
+ * config/mips/mips.c (coprocessor_operand, coprocessor2_operand):
+ New functions.
+ (mips_reg_names, mips_regno_to_class): Include coprocessor
+ information.
+ (mips_sw_reg_names): Ditto, make non-static.
+ (mips_move_1word): Handle moves to and from coprocessor registers.
+ (mips_move_2words): Handle moves to and from coprocessor
+ registers.
+ (mips_class_max_nregs, mips_register_move_cost): Handle
+ coprocessor register classes.
+ (override_options): Initialize mips_char_to_class and
+ mips_hard_regno_mode_ok properly for coprocessor registers.
+
+ * config/mips/mips.md (movdi_internal, movdi_internal2,
+ movsi_internal1, movsi_internal2): Add constraint-sets for
+ coprocessor registers.
+ * testsuite/gcc.c-torture/mipscop-1.c: New testcase.
+ * testsuite/gcc.c-torture/mipscop-1.x: Disable above if target
+ isn't mips.
+ * testsuite/gcc.c-torture/mipscop-2.c: New testcase.
+ * testsuite/gcc.c-torture/mipscop-2.x: Disable above if target
+ isn't mips.
+ * testsuite/gcc.c-torture/mipscop-3.c: New testcase.
+ * testsuite/gcc.c-torture/mipscop-3.x: Disable above if target
+ isn't mips.
+ * testsuite/gcc.c-torture/mipscop-4.c: New testcase.
+ * testsuite/gcc.c-torture/mipscop-4.x: Disable above if target
+ isn't mips.
+
+ * doc/tm.texi: Document feature.
+
+2002-04-25 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * integrate.c (function_attribute_inlinable_p): Simplify.
+ Check the table pointer is not NULL.
+
+2002-04-25 Steven Bosscher <S.Bosscher@student.tudelft.nl>
+
+ * doc/c-tree.texi: Fix typo in introduction.
+
+2002-04-25 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.h (c_common_parse_file): Update.
+ * c-lang.c (LANG_HOOKS_SET_YYDEBUG): Remove.
+ * c-lex.c (YYDEBUG): Get from c-lex.h.
+ (c_common_parse_file): Update.
+ * c-lex.h (YYDEBUG, yydebug): New.
+ * c-parse.in (YYDEBUG): Get from c-lex.h.
+ (c_set_yydebug): Remove.
+ * c-tree.h (c_set_yydebug): Remove.
+ * langhooks-def.h (lhd_do_nothing_i): New.
+ (lhd_set_yydebug, LANG_HOOKS_SET_YYDEBUG): Remove.
+ (LANG_HOOKS_PARSE_FILE, LANG_HOOKS_INITIALIZER): Update.
+ * langhooks.c (lhd_do_nothing_i): New.
+ (lhd_set_yydebug): Remove.
+ * langhooks.h (struct lang_hooks): Update.
+ * toplev.c (set_yydebug): New.
+ (compile_file): Update call to parse_file hook.
+ (decode_d_option): Update.
+objc:
+ * objc-lang.c (LANG_HOOKS_SET_YYDEBUG): Remove.
+
+Wed Apr 24 23:45:37 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * loop.c (load_mems): Don't change the interface of called functions.
+
+ * calls.c (expand_call): Take current_function_pretend_args_size
+ into account when setting argblock for sibcalls.
+
+2002-04-24 Matt Hiller <hiller@redhat.com>
+
+ * cpplex.c: Remove conditional #undef of MULTIBYTE_CHARS.
+ * c-lex.c: Ditto.
+
+ * cpplex.c (skip_line_comment): Process comment one multibyte
+ character at a time rather than one char at a time, if
+ appropriate.
+ (parse_string): Process string one multibyte character at a time
+ rather than one char at a time, if appropriate.
+ * c-lex.c (lex_string): Lex and copy multibyte strings
+ appropriately.
+ * cpplib.h (cppchar_t): Change to unsigned.
+
+2002-04-24 Richard Henderson <rth@redhat.com>
+
+ PR c/3467
+ * c-decl.c (grokdeclarator): Don't pedwarn variable sized arrays
+ for c99.
+
+Wed Apr 24 21:51:54 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.c (sh_va_arg): If argument was passed by reference,
+ dereference the pointer.
+
+ * sh.h (PIC_OFFSET_TABLE_REGNUM): Conditionalize on flag_pic.
+
+ * sh.md (divsi3_i4_media): Use match_operand for input values
+ rather than hard registers.
+ (divsi3 - TARGET_SHMEDIA_FPU case): Don't ferry values
+ unnecessarily through hard registers. Keep copies of pseudo
+ registers outside of the libcall sequence.
+
+ * sh.md (casesi_shift_media): Add modes.
+
+ * sh.h (RETURN_IN_MEMORY): Return variable size BLKmode
+ values in memory.
+
+2002-04-24 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * attribs.c (c_common_attribute_table): Move table and handlers
+ to c-common.c.
+ (format_attribute_table, lang_attribute_table,
+ lang_attribute_common): Remove.
+ (init_attributes): Replace NULL pointers with pointers to the
+ empty table.
+ (handle_packed_attribute, handle_nocommon_attribute,
+ handle_common_attribute, handle_noreturn_attribute,
+ handle_noinline_attribute, handle_always_inline_attribute,
+ handle_used_attribute, handle_unused_attribute,
+ handle_const_attribute, handle_transparent_union_attribute,
+ handle_constructor_attribute, handle_destructor_attribute,
+ handle_mode_attribute, handle_section_attribute,
+ handle_aligned_attribute, handle_weak_attribute,
+ handle_alias_attribute, handle_visibility_attribute,
+ handle_no_instrument_function_attribute, handle_malloc_attribute,
+ handle_no_limit_stack_attribute, handle_pure_attribute,
+ handle_deprecated_attribute, handle_vector_size_attribute,
+ vector_size_helper): Move to c-common.c.
+ * c-common.c (c_common_attribute_table,
+ handle_packed_attribute, handle_nocommon_attribute,
+ handle_common_attribute, handle_noreturn_attribute,
+ handle_noinline_attribute, handle_always_inline_attribute,
+ handle_used_attribute, handle_unused_attribute,
+ handle_const_attribute, handle_transparent_union_attribute,
+ handle_constructor_attribute, handle_destructor_attribute,
+ handle_mode_attribute, handle_section_attribute,
+ handle_aligned_attribute, handle_weak_attribute,
+ handle_alias_attribute, handle_visibility_attribute,
+ handle_no_instrument_function_attribute, handle_malloc_attribute,
+ handle_no_limit_stack_attribute, handle_pure_attribute,
+ handle_deprecated_attribute, handle_vector_size_attribute,
+ vector_size_helper): Move from attribs.c.
+ * c-common.h (c_common_attribute_table,
+ c_common_format_attribute_table): New.
+ * c-lang.c (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE,
+ LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE): Redefine.
+ * langhooks-def.h (LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE,
+ LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, LANG_HOOKS_ATTRIBUTE_TABLE): New.
+ (LANG_HOOKS_INITIALIZER): Update.
+ * langhooks.h (struct lang_hooks): 3 new attribute hooks.
+ * target-def.h (TARGET_ATTRIBUTE_TABLE): Default to NULL.
+ * target.h: Update comment.
+ * tree.c (default_target_attribute_table): Remove.
+ * tree.h (default_target_attribute_table, format_attribute_table,
+ lang_attribute_table, lang_attribute_common): Remove.
+objc:
+ * objc-lang.c (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE,
+ LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE): Redefine.
+
+2002-04-24 Jason Merrill <jason@redhat.com>
+
+ * dwarf2.h (enum dwarf_attribute): Add DW_AT_GNU_vector.
+ * dwarf2out.c (dwarf_attr_name): Support it.
+ (gen_array_type_die): Emit it.
+ (lookup_type_die): No special handling for VECTOR_TYPE.
+ (gen_type_die): Hand VECTOR_TYPE off to gen_array_type_die.
+
+2002-04-24 Richard Henderson <rth@redhat.com>
+
+ * config/mips/mips.md (movdi_usd): Renumber.
+
+2002-04-24 David S. Miller <davem@redhat.com>
+
+ PR target/6420
+ * config/sparc/sparc.h (FUNCTION_OK_FOR_SIBCALL): Return false if
+ 32-bit SPARC and current_function_returns_struct is true.
+
+Wed Apr 24 13:48:25 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * loop.c (canonicalize_condition): Use gen_int_mode.
+
+2002-04-24 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/altivec.h: Cleanup file. Add non individual
+ variants.
+ (vec_vaddubm): New.
+ (vec_vadduhm): New.
+ (vec_vadduwm): New.
+ (vec_vaddfp): New.
+ (vec_vaddcuw): New.
+ (vec_vaddubs): New.
+ (vec_vaddsbs): New.
+ (vec_vadduhs): New.
+ (vec_vadduws): New.
+ (vec_vaddsws): New.
+ (vec_vand): New.
+ (vec_vandc): New.
+ (vec_vavgub): New.
+ (vec_vavgsb): New.
+ (vec_vavguh): New.
+ (vec_vavgsh): New.
+ (vec_vavguw): New.
+ (vec_vavgsw): New.
+ (vec_vrfip): New.
+ (vec_vcmpbfp): New.
+ (vec_vcmpequb): New.
+ (vec_vcmpequh): New.
+ (vec_vcmpequw): New.
+ (vec_vcmpeqfp): New.
+ (vec_vcmpgefp): New.
+ (vec_vcmpgtub): New.
+ (vec_vcmpgtsb): New.
+ (vec_vcmpgtuh): New.
+ (vec_vcmpgtsh): New.
+ (vec_vcmpgtuw): New.
+ (vec_vcmpgtsw): New.
+ (vec_vcmpgtfp): New.
+ (vec_vcmpgefp): New.
+ (vec_vcfux): New.
+ (vec_vcfsx): New.
+ (vec_vctsxs): New.
+ (vec_vctuxs): New.
+ (vec_vexptefp): New.
+ (vec_vrfim): New.
+ (vec_lvx): New.
+ (vec_lvebx): New.
+ (vec_lvehx): New.
+ (vec_lde): Add vector float variant.
+ (vec_lvewx): New.
+ (vec_lvxl): New.
+ (vec_vlogefp): New.
+ (vec_vmaddfp): New.
+ (vec_vmhaddshs): New.
+ (vec_vmaxub): New.
+ (vec_vmaxsb): New.
+ (vec_vmaxuh): New.
+ (vec_vmaxsh): New.
+ (vec_vmaxuw): New.
+ (vec_vmaxsw): New.
+ (vec_vmaxsw): New.
+ (vec_vmaxfp): New.
+ (vec_vmrghb): New.
+ (vec_vmrghh): New.
+ (vec_vmrghw): New.
+ (vec_vmrglb): New.
+ (vec_vmrglh): New.
+ (vec_vmrglw): New.
+ (vec_vminub): New.
+ (vec_vminsb): New.
+ (vec_vminuh): New.
+ (vec_vminsh): New.
+ (vec_vminuw): New.
+ (vec_vminsw): New.
+ (vec_vminfp): New.
+ (vec_vmladduhm): New.
+ (vec_vmhraddshs): New.
+ (vec_msumubm): New.
+ (vec_vmsummbm): New.
+ (vec_vmsumuhm): New.
+ (vec_vmsumshm): New.
+ (vec_vmsumuhs): New.
+ (vec_vmsumshs): New.
+ (vec_vmuleub): New.
+ (vec_vmulesb): New.
+ (vec_vmuleuh): New.
+ (vec_vmulesh): New.
+ (vec_vmuloub): New.
+ (vec_mulosb): New.
+ (vec_vmulouh): New.
+ (vec_vmulosh): New.
+ (vec_vnmsubfp): New.
+ (vec_vnor): New.
+ (vec_vor): New.
+ (vec_vpkuhum): New.
+ (vec_vpkuwum): New.
+ (vec_vpkpx): New.
+ (vec_vpkuhus): New.
+ (vec_vpkshss): New.
+ (vec_vpkuwus): New.
+ (vec_vpkswss): New.
+ (vec_vpkshus): New.
+ (vec_vpkswus): New.
+ (vec_vperm): New.
+ (vec_vrefp): New.
+ (vec_vrlb): New.
+ (vec_vrlh): New.
+ (vec_vrlw): New.
+ (vec_vrfin): New.
+ (vec_vrsqrtefp): New.
+ (vec_vsel): New.
+ (vec_vslb): New.
+ (vec_vslh): New.
+ (vec_vslw): New.
+ (vec_vsldoi): New.
+ (vec_vsl): New.
+ (vec_vslo): New.
+ (vec_vspltb): New.
+ (vec_vsplth): New.
+ (vec_vspltw): New.
+ (vec_vspltisb): New.
+ (vec_vspltish): New.
+ (vec_vspltisw): New.
+ (vec_vsrb): New.
+ (vec_vsrh): New.
+ (vec_vsrw): New.
+ (vec_vsrab): New.
+ (vec_vsrah): New.
+ (vec_vsraw): New.
+ (vec_vsr): New.
+ (vec_vsro): New.
+ (vec_stvx): New.
+ (vec_stvebx): New.
+ (vec_stvehx): New.
+ (vec_stvewx): New.
+ (vec_stvxl): New.
+ (vec_vsububm): New.
+ (vec_vsubuhm): New.
+ (vec_vsubuwm): New.
+ (vec_vsubfp): New.
+ (vec_vsubcuw): New.
+ (vec_vsububs): New.
+ (vec_vsubsbs): New.
+ (vec_vsubuhs): New.
+ (vec_vsubshs): New.
+ (vec_vsubuws): New.
+ (vec_vsubsws): New.
+ (vec_vsum4ubs): New.
+ (vec_vsum4sbs): New.
+ (vec_vsum4shs): New.
+ (vec_vsum2sws): New.
+ (vec_vsumsws): New.
+ (vec_vrfiz): New.
+ (vec_vupkhsb): New.
+ (vec_vupkhpx): New.
+ (vec_vupkhsh): New.
+ (vec_vupklsb): New.
+ (vec_vupklpx): New.
+ (vec_vupklsh): New.
+ (vec_vxor): New.
+
+2002-04-23 Eric Botcazou <ebotcazou@multimania.com>
+
+ PR c/5430
+ * fold-const.c (split_tree): Add MINUS_LITP parameter; separate
+ added literals from substracted literals.
+ (associate_trees): Don't convert MINUS_EXPR into PLUS_EXPR.
+ (fold) [associate]: Preserve MINUS_EXPR if needed.
+
+2002-04-23 Zack Weinberg <zack@codesourcery.com>
+
+ * doc/install.texi: Clarify which versions of alpha*-dec-osf*
+ are obsoleted.
+
+2002-04-23 Tom Tromey <tromey@redhat.com>
+
+ * gcc.c: Added --resource. For PR java/6314.
+
+2002-04-23 David O'Brien <obrien@FreeBSD.org>
+
+ * cp/g++spec.c: Use profiled libstdc++ and libm with -p/-pg.
+ * config/freebsd.h (MATH_LIBRARY_PROFILE): Use the _p verions of
+ these libraries.
+
+2002-04-23 David O'Brien <obrien@FreeBSD.org>
+
+ * config/freebsd.h(OBJECT_FORMAT_ELF): Define.
+
+Tue Apr 23 14:24:25 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (ix86_output_addr_diff_elt): Avoid x86_64 binutils bug
+ workaround.
+ (ix86_expand_int_movcc): Avoid x86_64 compilation chrash.
+ (ix86_expand_clrstr): Fix typo.
+ * loop.c (gen_load_of_final_value): New.
+ (loop_givs_rescan, strength_reduce, check_dbra_loop):
+ Use it.
+
+2002-04-23 Roger Sayle <roger@eyesopen.com>
+
+ * builtins.c (builtin_memset_gen_str): New function.
+ (expand_builtin_memset): Optimize the case of constant length, but
+ unknown value.
+
+2002-04-23 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/altivec.h (vec_step): Remove extraneous
+ parentheses.
+ (vec_ctu): Cast return.
+
+2002-04-23 Alan Modra <amodra@bigpond.net.au>
+
+ PR target/6413
+ * function.h: (struct function): Add profile_label_no field.
+ (current_function_profile_label_no): Define.
+ * function.c: (profile_label_no): New static var.
+ (expand_function_start): Increment it, and copy to
+ current_function_profile_label_no.
+ * output.h (profile_label_no): Delete.
+ * final.c (profile_label_no): Delete.
+ (profile_function): Use current_function_profile_label_no.
+ (final_end_function): Don't increment profile_label_no here.
+ * config/i386/i386.c (ix86_osf_output_function_prologue): Replace
+ profile_label_no with current_function_profile_label_no.
+ * config/pa/pa.c (current_function_number): Delete.
+ (pa_output_function_prologue): Don't output profile label here.
+ (hppa_profile_hook): Use label_no param rather than
+ current_function_number.
+ (FUNC_BEGIN_PROLOG_LABEL): Move to ..
+ * config/pa/pa.h: .. here.
+ (FUNCTION_PROFILER): Output profile label here.
+
+2002-04-22 Eric Christopher <echristo@redhat.com>
+
+ * config/mips/mips.h (ASM_OUTPUT_ALIGNED_DECL_COMMON): Revert
+ patch of 2002-04-09 due to binutils issues.
+ (FUNCTION_ARG_REGNO_P): Ensure even numbered float register.
+
+2002-04-22 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.md ("*movv4si_internal"): Change 'm'
+ constraint to 'o' for m=r and r=m alternatives.
+ ("*movv8hi_internal1"): Same.
+ ("*movv16qi_internal1"): Same.
+ ("*movv4sf_internal1"): Same.
+
+2002-04-22 Janis Johnson <janis187@us.ibm.com>
+
+ * rtl.h (RTX_FLAG): New macro.
+ * emit-rtl.c (copy_most_rtx): Use macros to access rtx flags.
+ * final.c (alter_subreg): Use macro to access rtx flag.
+ * integrate.c (copy_rtx_and_substitute): Use new access macro.
+ * print-rtl.c (print_rtx): Use new access macro.
+
+ * cse.c (insert): Check rtx code before accessing flag.
+
+ * genattrtab.c (ATTR_IND_SIMPLIFIED_P, ATTR_CURR_SIMPLIFIED_P,
+ ATTR_PERMANENT_P, ATTR_EQ_ATTR_P): New.
+ (attr_hash_add_string, attr_rtx_1, attr_copy_rtx, check_attr_test,
+ convert_const_symbol_ref, make_canonical, make_alternative_compare,
+ evaluate_eq_attr, attr_rtx_cost, simplify_test_exp_in_temp,
+ simplify_test_exp, optimize_attrs, simplify_by_exploding,
+ find_and_mark_used_attributes, unmark_used_attributes,
+ add_values_to_cover, simplify_with_current_value,
+ simplify_with_current_value_aux, clear_struct_flag, walk_attr_value,
+ copy_rtx_unchanging, main): Use new access macros.
+
+2002-04-22 Tom Rix <trix@redhat.com>
+
+ * expmed.c (init_expmed): Generate shifted constant once.
+
+2002-04-22 Zack Weinberg <zack@codesourcery.com>
+
+ * c-lex.c (lex_charconst): Call convert to get constant in
+ proper type; don't just smash the type field.
+ Fixes PR c/6300.
+
+ * config.gcc: Add list of obsolete configurations. Disallow
+ building these without --enable-obsolete.
+ * doc/install.texi: Document --enable-obsolete and obsoletion
+ policy. Mention obsoletion of individual targets in
+ appropriate places.
+
+2002-04-22 Richard Henderson <rth@redhat.com>
+
+ * config/sparc/sol2-bi.h (ASM_DEBUG_SPEC): New.
+
+2002-04-22 Mark Mitchell <mark@codesourcery.com>
+
+ PR f/6138.
+ * function.c (fixup_memory_subreg): Add promoted_mode parameter.
+ (walk_fixup_memory_subreg): Likewise.
+ (fixup_var_refs_insn): Adjust accordingly.
+ (fixup_var_refs_1): Likewise.
+
+2002-04-22 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/linux.h: (LIBPATH_SPEC, LIBPATH_ARCH31_SPEC,
+ LIBPATH_ARCH64_SPEC): Define.
+ (EXTRA_SPECS): Add libpath, libpath_arch31, libpath_arch64.
+ (STARTFILE_SPEC, ENDFILE_SPEC): Define; use libpath.
+ (LINK_ARCH31_SPEC): Add libpath_arch31 to search path.
+ (LINK_ARCH64_SPEC): Add libpath_arch64 to search path.
+
+2002-04-22 Joel Sherrill <joel@OARcorp.com>
+
+ * gthr-rtems.h: Correct prototypes to remove warnings.
+
+2002-04-22 Richard Henderson <rth@redhat.com>
+
+ PR c/6344
+ * alias.c (canon_true_dependence): Special case (mem:blk (scratch)).
+
+ * gcse.c (free_insn_expr_list_list): New.
+ (clear_modify_mem_tables): Use it. Fix bit set usage.
+ (canon_list_insert): Use EXPR_LISTs for expressions.
+ (record_last_mem_set_info): Factor BLOCK_NUM (insn).
+
+2002-04-22 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppfiles.c (_cpp_pop_file_buffer): Return void. Move
+ file change and include code to _cpp_pop_buffer.
+ * cpphash.h (struct pending_option): Predeclare.
+ (struct cpp_reader): New member next_include_file.
+ (_cpp_pop_file_buffer): Update.
+ (_cpp_push_next_buffer): Update, rename.
+ * cppinit.c (cpp_destroy): Free include chain and pending here.
+ (cpp_finish_options): Simplify.
+ (_cpp_push_next_buffer): Rename and clean up.
+ * cpplib.c (cpp_pop_buffer): Move code from _cpp_pop_file_buffer.
+ Clarify.
+ * cppmacro.c (cpp_scan_nooutput): Set return_at_eof here.
+
+2002-04-22 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/altivec.h (vec_xor): Add variant for both args
+ being vector signed int.
+ (vec_andc): Same.
+ (vec_xor): Add variant for both args being vector signed char.
+ Remove redundant variant.
+ (vec_andc): Same.
+
+2002-04-21 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.md (set then compare DI mode peephole2): Fix
+ compare mode in output RTL.
+
+2002-04-22 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.c (rs6000_override_options): Correct
+ style and formatting of previous patch.
+
+2002-04-22 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.c (rs6000_override_options): Always clear
+ flag_pic for ABI_AIX.
+
+2002-04-21 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppexp.c (struct op, parse_number): Replace U_CHAR with uchar.
+ * cppfiles.c (read_include_file): Similarly.
+ * cpphash.h (DSC, U_CHAR, ustrcmp, ustrncmp, ustrlen,
+ uxstrdup ustrchr, ufputs): Similarly.
+ * cppinit.c (TRIGRAPH_MAP, cpp_destroy): Similarly.
+ * cpplex.c (parse_slow, unescaped_terminator_p, save_comment,
+ cpp_ideq, parse_identifier, parse_number): Similarly.
+ * cpplib.c (struct directive, dequote_string, D, run_directive,
+ cpp_push_buffer): Similarly.
+ * cppmacro.c (new_string_token, builtin_macro, cpp_quote_string,
+ _cpp_create_definition, check_trad_stringification,
+ cpp_macro_definition): Similarly.
+
+2002-04-21 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppmacro.c (funlike_invocation_p): Don't step back
+ over CPP_EOF.
+
+2002-04-21 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.c (output_profile_hook): Do not increment
+ labelno.
+
+2002-04-20 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/invoke.texi: Remove Chill references.
+ * doc/gcc.texi: Update last modified date.
+
+2002-04-20 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/lib1funcs.asm (___mulsi3): Remove unnecessary
+ push and pop. Replace add.l with add.w.
+
+2002-04-20 Toshiyasu Morita <toshiyasu.morita@hsa.hitachi.com>
+
+ * config/h8300/lib1funcs.asm (___mulsi3): Use hardware
+ multiply instructions for H8/300H case.
+
+2002-04-20 Toshiyasu Morita <toshiyasu.morita@hsa.hitachi.com>
+
+ * config/h8300/lib1funcs.asm (___cmpsi2, ___ucmpsi2):
+ Bum three instructions from each routine.
+
+2002-04-20 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in: Update.
+ * decl.c (push_c_function_context, pop_c_function_context,
+ mark_c_function_context): Rename for consistency.
+ * c-objc-common.c (c_objc_common_init): Langhooks set elsewhere.
+ * c-tree.h (push_c_function_context, pop_c_function_context,
+ mark_c_function_context): Rename for consistency.
+ * c-lang.c (LANG_HOOKS_FUNCTION_ENTER_NESTED,
+ LANG_HOOKS_FUNCTION_LEAVE_NESTED, LANG_HOOKS_FUNCTION_MARK): Redefine.
+ * function.c (init_lang_status, save_lang_status,
+ restore_lang_status, mark_lang_status, free_lang_status):
+ Move to langhooks.h.
+ (push_function_context_to, pop_function_context_from,
+ free_after_parsing, prepare_function_start, ggc_mark_struct_function):
+ Update.
+ * function.h (init_lang_status, save_lang_status,
+ restore_lang_status, mark_lang_status, free_lang_status):
+ Move to langhooks.h.
+ * langhooks-def.h (LANG_HOOKS_FUNCTION_INIT,
+ LANG_HOOKS_FUNCTION_FREE, LANG_HOOKS_FUNCTION_ENTER_NESTED,
+ LANG_HOOKS_FUNCTION_LEAVE_NESTED, LANG_HOOKS_FUNCTION_MARK,
+ LANG_HOOKS_FUNCTION_INITIALIZER): New.
+ (LANG_HOOKS_INITIALIZER): Update.
+ (lhd_do_nothing_f): New.
+ * langhooks.h (struct lang_hooks_for_functions): New.
+ (struct lang_hooks): New hooks.
+ * langhooks.c (lhd_do_nothing_f): New.
+objc:
+ * objc-lang.c (LANG_HOOKS_FUNCTION_ENTER_NESTED,
+ LANG_HOOKS_FUNCTION_LEAVE_NESTED, LANG_HOOKS_FUNCTION_MARK): Redefine.
+
+2002-04-19 David S. Miller <davem@redhat.com>
+
+ * config/sparc/linux.h (MD_FALLBACK_FRAME_STATE_FOR): Define.
+ * config/sparc/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Likewise.
+
+2002-04-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR optimization/3756
+ * config/i386/i386.c (ix86_expand_int_movcc): Optimize
+ x = ((int) y < 0) ? cst1 : cst2.
+
+2002-04-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/6358
+ * function.c: Reapply patch for c/6358.
+ (expand_function_end): Copy decl_rtl's mode, not
+ current_function_return_rtx mode.
+
+2002-04-19 Joel Sherrill <joel@OARcorp.com>
+
+ * config/rtems.h (STARTFILE_SPEC, ENDFILE_SPEC): Fix for non-ELF
+ targets.
+
+2002-04-19 Tom Tromey <tromey@redhat.com>
+
+ * doc/install.texi (Specific): Update status of Solaris 2.8.
+ For PR libgcj/6158.
+
+2002-04-19 Andreas Schwab <schwab@suse.de>
+
+ * real.c: Allow sizeof (REAL_VALUE_TYPE) > 2*NE.
+ (PUT_REAL): Restore old definition.
+
+2002-04-19 Dan Nicolaescu <dann@godzilla.ics.uci.edu>
+ Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/install.texi (Specific, sparc-sun-solaris2*): Mention that
+ binutils 2.11.2 and higher generate smaller binaries than Sun's
+ native tools.
+
+2002-04-19 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/6352
+ * toplev.c (rest_of_compilation): Do not defer functions for which
+ TREE_SYMBOL_REFERENCED has already been set.
+
+Fri Apr 19 15:53:03 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (movsi_1, movhi_1): Force reload to use more flexible
+ alternative.
+
+2002-04-19 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * builtins.c: Include langhooks.h.
+ (lang_type_promotes_to): Remove.
+ (expand_builtin_va_arg): Use new hook.
+ * c-common.c (c_common_nodes_and_builtins): Don't set hook.
+ (simple_type_promotes_to): Move to c-typeck.c.
+ * c-common.h (simple_type_promotes_to): Remove.
+ * c-decl.c (duplicate_decls, grokdeclarator): Update.
+ * c-format.c: Include langhooks.h.
+ (check_format_types): Update.
+ * c-tree.h (c_type_promotes_to): New.
+ * c-typeck.c (c_type_promotes_to): Move from c-common.c.
+ (type_lists_compatible_p): Update.
+ * langhooks-def.h (lhd_type_promotes_to): New.
+ (LANG_HOOKS_TYPE_PROMOTES_TO): New.
+ (LANG_HOOKS_FOR_TYPES_INITIALIZER): Update.
+ * langhooks.c (lhd_type_promotes_to): New.
+ * langhooks.h (struct lang_hooks_for_types): New hook.
+ * tree.h (lang_type_promotes_to): Remove.
+objc:
+ * objc-lang.c (LANG_HOOKS_TYPE_PROMOTES_TO): Redefine.
+
+2002-04-18 Richard Henderson <rth@redhat.com>
+
+ * function.c: Revert patch for c/6358.
+
+2002-04-18 Richard Henderson <rth@redhat.com>
+
+ * ifcvt.c (find_cond_trap): Handle cases with no proper THEN or JOIN
+ blocks. Handle multiple references to the TRAP block. Handle
+ non-adjacent THEN and OTHER blocks.
+
+2002-04-18 Richard Henderson <rth@redhat.com>
+
+ * config/ia64/ia64.c (ia64_function_arg_pass_by_reference): Don't
+ crash with no type for by-mode libcalls.
+
+ * config/ia64/ia64.md (conditional_trap): Fix predicate polarity.
+
+2002-04-18 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/lib2funcs.S (__xtensa_libgcc_window_spill,
+ __xtensa_nonlocal_goto): Use a syscall instructions to flush
+ the register windows.
+
+2002-04-18 Zack Weinberg <zack@codesourcery.com>
+
+ * real.h: Define REAL_VALUE_TYPE_SIZE as 96 or 160, as
+ appropriate. Document need for extended precision even when
+ MAX_LONG_DOUBLE_TYPE_SIZE is smaller. Define REAL_WIDTH here,
+ based on REAL_VALUE_TYPE_SIZE. Use REAL_WIDTH to size
+ REAL_VALUE_TYPE. Define CONST_DOUBLE_FORMAT here. Use #error
+ instead of relying on later syntax error when REAL_WIDTH > 5.
+ * real.c: Define NE based only on whether or not we have a
+ full 128-bit extended type (not INTEL_EXTENDED_IEEE_FORMAT).
+ Require sizeof(REAL_VALUE_TYPE) == 2*NE. Unconditionally
+ define GET_REAL and PUT_REAL as simple memcpy operations; no
+ need to byteswap or round.
+ Use #error instead of #ifdef-ing out the entire file, for
+ prompt error detection.
+
+ * rtl.c, gengenrtl.c: No need to calculate CONST_DOUBLE_FORMAT here.
+
+2002-04-18 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.h (BRANCH_COST): Define.
+
+ * fold-const.c (BRANCH_COST): Don't provide default here, expr.h
+ does it.
+
+2002-04-18 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * flow.c (update_life_info): Ignore return value of cleanup_cfg.
+ Mask out PROP_SCAN_DEAD_CODE | PROP_KILL_DEAD_CODE in
+ propagate_block calls after relaxation loop using new variable
+ stabilized_prop_flags.
+
+2002-04-18 Richard Henderson <rth@redhat.com>
+
+ * config/ia64/ia64.c (ia64_function_arg_pass_by_reference): New.
+ (ia64_va_arg): Expect variable sized types by reference.
+ * config/ia64/ia64-protos.h: Update.
+ * config/ia64/ia64.h (FUNCTION_ARG_PASS_BY_REFERENCE): Use
+ ia64_function_arg_pass_by_reference.
+
+2002-04-18 Richard Henderson <rth@redhat.com>
+
+ * ifcvt.c: Include except.h.
+ (block_has_only_trap): Break out from find_cond_trap.
+ (find_cond_trap): Use it. Always delete the trap block.
+ (merge_if_block): Allow then block null. Be less simplistic about
+ what insns can end a block.
+ * Makefile.in (ifcvt.o): Depend on except.h.
+
+ * config/ia64/ia64.md (trap, conditional_trap): New.
+
+2002-04-18 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/6358
+ * function.c (assign_parms): Assign hard current_function_return_rtx
+ register here...
+ (expand_function_end): ...not here.
+
+2002-04-18 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-lang.c (LANG_HOOKS_INCOMPLETE_TYPE_ERROR): Redefine.
+ * c-tree.h (c_incomplete_type_error): New.
+ * c-typeck.c (require_complete_type, build_component_ref): Update.
+ (incomplete_type_error): Rename.
+ * langhooks-def.h (lhd_incomplete_type_error): New.
+ (LANG_HOOKS_INCOMPLETE_TYPE_ERROR): New.
+ (LANG_HOOKS_FOR_TYPES_INITIALIZER): Update.
+ * langhooks.c (lhd_incomplete_type_error): New.
+ * langhooks.h (struct lang_hooks_for_types): New hook.
+ * tree.c (size_in_bytes): Use new hook.
+ * tree.h (incomplete_type_error): Remove.
+objc:
+ * objc-lang.c (LANG_HOOKS_INCOMPLETE_TYPE_ERROR): Redefine.
+
+2002-04-18 Zack Weinberg <zack@codesourcery.com>
+
+ * config/arc/arc.md: Remove #if HOST_FLOAT_FORMAT !=
+ TARGET_FLOAT_FORMAT blocks.
+
+2002-04-18 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/install.texi (Downloading the source): Do not mention Chill
+ any longer, but mention Ada.
+ (Configuration): Do not mention Chill any longer.
+
+2002-04-18 Hans-Peter Nilsson <hp@axis.com>
+
+ * config/cris/cris.h (TARGET_VERSION): Remove local version number.
+
+Thu Apr 18 17:14:08 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.h (SSE_FLOAT_MODE_P): Fix bogus conflict resolution
+ in last patch.
+
+2002-04-18 Jakub Jelinek <jakub@redhat.com>
+
+ * fold-const.c (fold): Use (*lang_hooks.types.unsigned_type)
+ instead of unsigned_type.
+
+Thu Apr 18 15:49:12 CEST 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.h (SSE_FLOAT_MODE_P): Kill bogus TARGET_SSE_MATH check.
+ * i386.md (sse_mov?fcc*): Swap operands for cases they will be swapped
+ later.
+
+2002-04-18 Bernd Schmidt <bernds@redhat.com>
+
+ * attribs.c (vector_type_node_list): New static variable.
+ (handle_vector_size_attribute): Use it to avoid generating a
+ new type node each time we are called.
+
+ * combine.c (subst): Avoid trying to make a vector mode subreg of
+ an integer constant.
+ (gen_lowpart_for_combine): Likewise.
+
+2002-04-18 Roger Sayle <roger@eyesopen.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ * fold-const.c (fold) [NOP_EXPR]: Convert (T)(x&c) into ((T)x&(T)c)
+ for integer constant c (if x has unsigned type or sign bit is not
+ set in c). This folds the zero/sign extension into the bit-wise and
+ operation.
+
+2002-04-18 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/6205
+ * config/i386/i386.md (movsf_1): Use pxor only if TARGET_SSE2,
+ otherwise xorps.
+
+2002-04-17 NIIBE Yutaka <gniibe@m17n.org>
+
+ * config/sh/elf.h: Undefine ASM_OUTPUT_CASE_LABEL.
+
+2002-04-17 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * gcc.c (read_specs): Detect and fail if an attempt is made to
+ rename a spec string to an already existing string.
+
+2002-04-17 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.c (legitimize_pic_address): Do not generate
+ illegal address constant without CONST.
+
+2002-04-17 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * sparc/linux64.h (CC1_SPEC): Error for -m32 and -m64.
+ * sparc/netbsd-elf.h (CC1_SPEC32, CC1_SPEC64): Likewise.
+
+2002-04-17 Ulrich Weigand <uweigand@de.ibm.com>
+
+ PR optimization/6305
+ * config/s390/s390.c (s390_expand_plus_operand): Use find_replacement
+ to make sure previous reloads are taken into account. Generate
+ better code if one operand is an in-range immediate constant.
+
+2002-04-16 Andrew Haley <aph@cambridge.redhat.com>
+
+ * doc/install.texi (Building): libgcj requires GNU make.
+
+2002-04-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR bootstrap/6315
+ * config/sparc/sparc.md (movtf reg<-reg split): Allow spliting
+ even if hard quad and register is not floating.
+ (movtf reg<-mem split): Disallow splitting if hard quad and
+ register is floating.
+ (movtf mem<-reg split): Likewise.
+ * config/sparc/sparc.c (fp_register_operand): New predicate.
+ * config/sparc/sparc.h (PREDICATE_CODES): Add fp_register_operand.
+
+2002-04-17 Zack Weinberg <zack@codesourcery.com>
+
+ * Makefile.in (PROTO_OBJS): Add cppdefault.o.
+ (protoize.o): Take $(PREPROCESSOR_DEFINES) off command line.
+ (unprotoize.o): Ditto. Build from protoize.c. Define
+ UNPROTOIZE on command line.
+ * protoize.c: Include cppdefault.h. Delete include_defaults.
+ (in_system_include_dir): Use cpp_include_defaults (defined in
+ cppdefault.o).
+ * unprotoize.c: Delete file.
+
+2002-04-17 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/altivec.h (vec_ld): Add array variants.
+ (vec_lde): Same.
+ (vec_ldl): Same.
+
+2002-04-17 Alan Matsuoka <alanm@redhat.com>
+ Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/altivec.h: Define __ALTIVEC__.
+ (bool): New.
+ (__pixel): New.
+ (pixel): New.
+ (vec_cfux): New.
+ (vec_vmaddfp): New.
+ (vec_vsldoi): New.
+ Add parentheses to all macro arguments.
+
+2002-04-16 Richard Henderson <rth@redhat.com>
+
+ PR c++/6320
+ * except.c (remove_eh_handler): Insert inner regions at beginning
+ of sibling chain. Refactor expressions.
+
+2002-04-16 Richard Henderson <rth@redhat.com>
+
+ * config/sparc/sol2-bi.h (AS_SPARC64_FLAG): New.
+ * config/sparc/sol2-gas-bi.h: New file.
+ * config.gcc (sparc*-solaris): Add it as needed.
+ * configure.in (AS_SPARC64_FLAG): Remove check.
+ * config.in, configure: Regenerate.
+
+ * config/sparc/sol2-bi.h (CC1_SPEC): Error for -m32 and -m64.
+
+2002-04-16 Richard Henderson <rth@redhat.com>
+
+ * config/mips/mips.c (override_options): Don't override N32 for
+ a 64-bit ISA.
+
+ PR 6202
+ * config/mips/mips.md (can_delay): Split out of existing define_delays.
+ (HILO_delay): Set can_delay false.
+
+2002-04-16 Dale Johannesen <dalej@apple.com>
+
+ * config/rs6000/rs6000.c (rs6000_output_function_prologue): Compute
+ instruction addresses.
+ (rs6000_output_function_epilogue): Likewise.
+
+2002-04-16 Paolo Carlini <pcarlini@unitus.it>
+
+ * c-parse.in (poplevel, compstmt_start,
+ compstmt_primary_start): Add ending ';', in accordance
+ with POSIX.
+
+2002-04-16 Richard Henderson <rth@redhat.com>
+
+ * config.gcc (sparcv9-solaris): Configure for 64-bit default.
+ Adjust tm_file order to get TARGET_DEFAULT set properly.
+ (sparc-solaris): Configure 2.[78] for 64-bit multilibs.
+ * doc/install.texi (sparc-solaris): Update.
+
+2002-04-16 Dale Johannesen <dalej@apple.com>
+
+ * config/rs6000/rs6000.c (rs6000_emit_cmove): Fail if modes of
+ comparison operands do not match each other or if modes of
+ conditions do not match result.
+
+2002-04-16 Hartmut Penner <hpenner@de.ibm.com>
+
+ PR target/6305
+ * config/s390/s390.md (mulsidi3): Set both subregs of the
+ multiword register.
+
+2002-04-16 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/altivec.h (vec_addc): Type check.
+
+2002-04-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/6279
+ * expr.c (store_expr): Don't copy if DECL_RTL (exp) == target.
+
+ * expr.c (safe_from_p): Cleanup: use DECL_RTL_IF_SET.
+
+2002-04-15 Richard Henderson <rth@redhat.com>
+
+ * config/mips/abi64.h (SUBTARGET_CONDITIONAL_REGISTER_USAGE): Set
+ call_really_used_regs too.
+
+2002-04-15 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/gnu.h (CPP_PREDEFINES): Underscores for gnu_hurd.
+
+2002-04-15 David S. Miller <davem@redhat.com>
+
+ * rtlanal.c (note_stores): Don't present PARALLEL SET_DESTs
+ as being CLOBBERed.
+
+2002-04-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/6290
+ * config/rs6000/rs6000.c (easy_vector_constant): Return 1 if the
+ CONST_VECTOR is { 0, ... 0 }.
+
+2002-04-15 Loren J. Rittle <ljrittle@acm.org>
+
+ * doc/install.texi (Installing GCC: Configuration): Clarify
+ the only supported ways to configure gcc.
+
+2002-04-15 Roland McGrath <roland@frob.com>
+
+ * config.gcc (alpha*-*-gnu*): New target configuration.
+ * config/alpha/gnu.h: New file for it.
+ * config/gnu.h (TARGET_MEM_FUNCTIONS): #undef before #define.
+
+2002-04-16 Mark Mitchell <mark@codesourcery.com>
+
+ * c-common.h (STMT_EXPR_NO_SCOPE): New macro.
+ * c-common.c (c_expand_expr): Respect STMT_EXPR_NO_SCOPE.
+ * tree.h (expand_start_stmt_expr): Update prototype.
+ * stmt.c (expand_start_stmt_expr): Add has_scope parameter.
+ * tree-inline.c (expand_call_inline): Set STMT_EXPR_NO_SCOPE
+ on the STMT_EXPR created for the inline function.
+
+2002-04-15 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/linux.h, config/arm/linux-elf.h, config/i370/linux.h,
+ config/i386/linux-aout.h, config/i386/linux-oldld.h,
+ config/i386/linux.h, config/i386/linux64.h, config/ia64/linux.h,
+ config/m68k/linux-aout.h, config/m68k/linux.h, config/mips/linux.h,
+ config/pa/pa-linux.h, config/pj/linux.h, config/s390/linux.h,
+ config/sh/linux.h, config/sparc/linux-aout.h, config/sparc/linux.h,
+ config/sparc/linux64.h, config/xtensa/linux.h (CPP_PREDEFINES):
+ Define __gnu_linux__, not gnu_linux.
+ * config/rs6000/sysv4.h (CPP_OS_GNU_SPEC): Likewise for gnu_hurd.
+
+2002-04-15 Mark Mitchell <mark@codesourcery.com>
+
+ Remove Chill front end.
+ * gcc.c (default_compilers): Remove Chill entries.
+ * ch: Remove directory.
+ * doc/frontends.texi: Remove information about Chill.
+ * doc/sourcebuild.texi: Likewise.
+ * doc/standards.texi: Likewise.
+
+2002-04-15 Douglas B Rupp <rupp@gnat.com>
+
+ * config/alpha/vms.h (INCLUDE_DEFAULTS): Add /gnu/lib/gcc-lib/include.
+ (LONGLONG_STANDALONE): Define.
+
+2002-04-15 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.c (sparc_emit_float_lib_cmp):
+ Call emit_library_call with LCT_NORMAL.
+ (sparc_initialize_trampoline): Use LCT_foo instead of
+ magic constant in emit_library_call invocations.
+ (sparc64_initialize_trampoline): Likewise.
+ (sparc_profile_hook): Likewise.
+ * config/sparc/sparc.md: Likewise.
+
+ * config/sparc/sparc.c (sparc_extra_constraint_check):
+ Fix type of argument 'c'.
+ * config/sparc/sparc-protos.h (sparc_extra_constraint_check):
+ Likewise.
+
+2002-04-15 Gabriel Dos Reis <gdr@merlin.codesourcery.com>
+
+ * diagnostic.h (output_buffer_state): Redefine.
+ (output_format_decoder): New macro.
+ (output_prefixing_rule): Likewise.
+ (output_line_cutoff): Likewise.
+ (diagnostic_format_decoder): Adjust.
+ (diagnostic_prefixing_rule): Likewise.
+ (diagnostic_line_cutoff): Likewise.
+ (diagnostic_state): Likewise.
+ (diagnostic_kind_count): Likewise.
+ (diagnostic_buffer): Now a macro.
+
+ * diagnostic.c (diagnostic_buffer): Remove definition.
+ (output_is_line_wrapping): Adjust.
+ (set_real_maximum_length): Likewise.
+ (output_set_maximum_length): Likewise.
+ (init_output_buffer): Likewise.
+ (lhd_print_error_function): Likewise.
+ (output_do_verbatim): Likewise.
+
+2002-04-14 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpperror.c (print_location): Don't print include chain
+ if line == 0.
+ (cpp_begin_message): Update to use DL_ macros.
+ (cpp_ice, cpp_fatal, cpp_error_from_errno, cpp_warning,
+ cpp_warning_with_line, cpp_pedwarn, cpp_pedwarn_with_line,
+ cpp_notice, cpp_notice_from_errno): Remove.
+ (cpp_error, cpp_error_with_line): Update to take a diagnostic
+ level.
+ (cpp_errno): New.
+ * cppexp.c (CPP_ICE): Remove.
+ (SYNTAX_ERROR, SYNTAX_ERROR2, parse_number, parse_defined,
+ lex, integer_overflow, _cpp_parse_expr): Update.
+ * cppfiles.c (read_include_file, find_include_file,
+ handle_missing_header, _cpp_read_file, remap_filename): Update.
+ * cpphash.h (enum error_type): Remove.
+ (_cpp_begin_message): Update.
+ * cppinit.c (append_include_chain, remove_dup_dirs, output_deps,
+ cpp_handle_option, cpp_post_options): Update.
+ * cpplex.c (trigraph_p, skip_escaped_newlines, skip_block_comment,
+ skip_whitespace, parse_identifier, parse_slow, parse_string,
+ _cpp_lex_direct, cpp_spell_token, maybe_read_ucs, cpp_parse_escape,
+ cpp_interpret_charconst): Update.
+ * cpplib.c (check_eol, directive_diagnostics, _cpp_handle_directive,
+ lex_macro_node, do_undef, glue_header_name, parse_include,
+ do_include_common, read_flag, do_line, do_linemarker, do_ident,
+ cpp_register_pragma, do_pragma_once, do_pragma_system_header,
+ do_pragma_poison, do_pragma_dependency, _cpp_do__Pragma, do_else,
+ do_elif, do_endif, parse_answer, parse_assertion, do_assert,
+ _cpp_pop_buffer, do_diagnostic): Update.
+ * cpplib.h (DL_WARNING, DL_WARNING_SYSHDR, DL_PEDWARN, DL_ERROR,
+ DL_FATAL, DL_ICE, DL_EXTRACT, DL_WARNING_P): New.
+ (cpp_ice, cpp_fatal, cpp_error_from_errno, cpp_warning,
+ cpp_warning_with_line, cpp_pedwarn, cpp_pedwarn_with_line,
+ cpp_notice, cpp_notice_from_errno): Remove.
+ (cpp_error, cpp_error_with_line): Update to take a diagnostic
+ level.
+ (cpp_errno): New.
+ * cppmacro.c (builtin_macro, stringify_arg, paste_all_tokens,
+ collect_args, enter_macro_context, save_parameter, parse_params,
+ _cpp_create_definition, check_trad_stringification,
+ cpp_macro_definition): Update.
+ * cppmain.c (cpp_preprocess_file): Update.
+ * fix-header.c (read_scan_file): Update.
+
+2002-04-14 Andreas Schwab <schwab@suse.de>
+
+ * config/ia64/linux.h (CPP_PREDEFINES): Fix missing backslash.
+
+2002-04-14 Jeroen Dobbelaere <jeroen.dobbelaere@acunia.com>
+
+ * config/arm/linux-elf.h (CPLUSPLUS_CPP_SPEC): Define.
+
+2002-04-13 Mark Mitchell <mark@codesourcery.com>
+
+ * config/i386/gnu.h (CPP_PREDEFINES): Define __gnu_hurd__,
+ not gnu_hurd.
+
+2002-04-13 Hans-Peter Nilsson <hp@axis.com>
+
+ * config/cris/linux.h (CRIS_CPP_SUBTARGET_SPEC): Fix typo.
+
+2002-04-13 Joel Sherrill <joel@OARcorp.com>
+
+ * config/sparc/t-elf: Enable v8 multilibs. Impacts
+ sparc-elf and sparc-rtems targets.
+
+2002-04-13 Mark Mitchell <mark@codesourcery.com>
+
+ * alpha/linux.h: Define __gnu_linux__ wherever __linux__ is
+ defined, and __gnu_hurd__ wherever __GNU__ is defined.
+ * arm/linux-elf.h: Likewise.
+ * cris/aout.h: Likewise.
+ * cris/linux.h: Likewise.
+ * i370/linux.h: Likewise.
+ * i386/gnu.h: Likewise.
+ * i386/linux-aout.h: Likewise.
+ * i386/linux-oldld.h: Likewise.
+ * i386/linux.h: Likewise.
+ * i386/linux64.h: Likewise.
+ * ia64/linux.h: Likewise.
+ * m68k/linux-aout.h: Likewise.
+ * m68k/linux.h: Likewise.
+ * mips/linux.h: Likewise.
+ * pa/pa-linux.h: Likewise.
+ * pj/linux.h: Likewise.
+ * rs6000/sysv4.h: Likewise.
+ * s390/linux.h: Likewise.
+ * sh/linux.h: Likewise.
+ * sparc/linux-aout.h: Likewise.
+ * sparc/linux.h: Likewise.
+ * sparc/linux64.h: Likewise.
+ * xtensa/linux.h: Likewise.
+
+2002-04-13 Richard Sandiford <rsandifo@redhat.com>
+
+ * stmt.c (check_unique_operand_names): Expect operand names to
+ be strings rather than identifiers. Use simple_cst_equal to
+ compare them.
+ (resolve_operand_name_1): Make same identifier to string change here.
+ * c-parse.in (asm_operand): Convert a named operand into a string.
+ * cp/parse.y (asm_operand): Likewise.
+
+2002-04-13 Andreas Schwab <schwab@suse.de>
+
+ * config/ia64/ia64.h (CPP_SPEC): Include %(cpp_cpu).
+
+2002-04-12 Mark Mitchell <mark@codesourcery.com>
+
+ Revert these changes:
+
+ 2002-04-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/5571
+ * stor-layout.c (layout_decl): Reset the RTL for the decl.
+
+2002-04-12 Richard Henderson <rth@redhat.com>
+
+ * config.gcc (sparcv9-*-solaris2): Default to 32-bit code.
+ (sparc*-*-solaris): Clean up header files.
+ * configure.in (AS_SPARC64_FLAG): Error out if can't find it
+ and plan on generating 64-bit code.
+ * toplev.c (decode_g_option): Remove LINKER_DOES_NOT_WORK_WITH_DWARF2.
+ * config/sparc/sol2-64.h: Delete and reuse for default 64-bit code.
+ * config/sparc/sol2-sld-64.h: Rename ...
+ * config/sparc/sol2-bi.h: ... here. Remove the bits that checked
+ for AS_SPARC64_FLAG not defined.
+ * config/sparc/sol2-gld-bi.h: New.
+ * config/sparc/sol2-sld.h: Remove.
+ * config/sparc/sol26-sld.h: New.
+ * config/sparc/sol2.h: Tidy comments.
+ * doc/install.texi: Document sparc-solaris configury changes.
+
+2002-04-12 Richard Henderson <rth@redhat.com>
+
+ * recog.c (offsettable_address_p): Match the logic in adjust_address.
+
+ * config/sparc/sparc.h (LEGITIMIZE_RELOAD_ADDRESS): Handle TFmode
+ in 64-bit mode only. Use only for 32-bit or MEDLOW.
+
+2002-04-12 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * config/alpha/osf.h (LINK_SPEC): Pass -S to silence ld warnings.
+
+Fri Apr 12 15:42:59 2002 Jeffrey A Law (law@redhat.com)
+
+ * pa.c (pa_can_combine_p): Call extract_insn before calling
+ constrain_operands.
+
+2002-04-12 Douglas B Rupp <rupp@gnat.com>
+
+ * config/i386/i386-interix.h (EH_FRAME_IN_DATA_SECTION): Define.
+ (TARGET_ASM_NAMED_SECTION, RETURN_IN_MEMORY) Define.
+ (DEFAULT_PCC_STRUCT_RETURN): Define as 0.
+ (CPP_PREDEFINES): Handle __declspec.
+ * config/i386/t-interix (USER_H): Remove.
+
+2002-04-12 DJ Delorie <dj@redhat.com>
+
+ * integrate.c (compare_blocks): Make comparisons safe for when
+ sizeof(int) < sizeof(char *).
+ (find_block): Likewise.
+
+2002-04-12 Jan Hubicka <jh@suse.cz>
+ David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.c (call_operand): Allow LINK and COUNT
+ registers.
+ (symbol_ref_operand): New.
+ * config/rs6000/rs6000.h (PREDICATE_CODES): Add symbol_ref_operand.
+ * config/rs6000/rs6000.md (call_nonlocal_aix): Use symbol_ref_operand.
+
+2002-04-12 Andreas Schwab <schwab@suse.de>
+
+ * config/ia64/ia64.h (ASM_SPEC): Moved from here ...
+ * config/ia64/sysv4.h (ASM_SPEC): ... to here, so that it
+ overrides the definition in config/svr4.h.
+
+2002-04-12 Eric Norum <eric.norum@usask.ca>
+
+ * config/rtems.h, config/a29k/rtems.h, config/arm/rtems-elf.h,
+ config/c4x/rtems.h, config/h8300/rtems.h, config/i386/rtems.h,
+ config/i386/rtemself.h, config/i960/rtems.h, config/m68k/rtems.h,
+ config/m68k/rtemself.h, config/mips/rtems.h, config/mips/rtems64.h,
+ config/pa/rtems.h, config/rs6000/rtems.h, config/sh/rtems.h,
+ config/sh/rtemself.h, config/sparc/rtems.h, config/sparc/rtemself.h,
+ config/v850/rtems.h (*-rtems*): Cleanup pass to move common
+ definitions to config/rtems.h and make the targets more similar.
+
+Fri Apr 12 08:06:54 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * expr.c (expand_assigment): Remove duplicate conversions #ifdef
+ POINTERS_EXTEND_UNSIGNED.
+ (store_constructor, expand_expr, case COMPONENT_REF): Likewise.
+ (store_expr): Use TYPE_MODE (sizetype), not ptr_mode.
+
+ * emit-rtl.c (widen_memory_access): Don't do anything if MEMOFFSET
+ not specified.
+
+Fri Apr 12 12:11:26 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.c (calc_live_regs, sh_pr_n_sets): Use of PR_MEDIA_REG / PR_REG
+ depends on TARGET_SHMEDIA, not TARGET_SH5.
+
+2002-04-12 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * function.c (fixup_var_refs_1) <SET, handling VAR in SET_SRC>:
+ For paradoxical (subreg VAR), replace VAR, don't try the subreg.
+
+Fri Apr 12 10:51:38 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.c (broken_move): Constant 0. / 1. load is OK if there is
+ no r0 clobber.
+
+2002-04-12 Andreas Schwab <schwab@suse.de>
+
+ * config/ia64/ia64.h (EXTRA_SPECS): Fix missing backslash.
+
+2002-04-12 Richard Henderson <rth@redhat.com>
+
+ PR bootstrap/4191
+ * config/d30v/d30v.h (INIT_SECTION_ASM_OP): Don't undef.
+
+ * flow.c (mark_used_reg): Manage reg_cond_dead properly for
+ modes spanning multiple hard regs.
+
+ * recog.c (peephole2_optimize): Rebuild jump labels as needed.
+
+2002-04-11 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.c (pa_output_function_prologue): Don't accumulate the total
+ number of code bytes when using TARGET_64BIT, or gas, SOM and not
+ the portable runtime.
+ (output_deferred_plabels): Handle 64bit plabels.
+ (output_cbranch): Use $PIC_pcrel$0 for pc relative relocations when
+ generating pic code using the GAS assembler for object formats that
+ are not SOM (ie., ELF32 and ELF64).
+ (output_millicode_call): Check attribute type if attribute length is 28.
+ Likewise use $PIC_pcrel$0. Only call get_attr_length and
+ dbr_sequence_length once.
+ (output_call): Likewise use $PIC_pcrel$0, and call get_attr_length and
+ dbr_sequence_length once.
+ * pa.h (TARGET_SOM): Define if not defined.
+ * pa.md (pattern to load address of label): Likewise use $PIC_pcrel$0
+ with GAS and not SOM.
+ (jump, call_internal_reg, call_value_internal_reg): Likewise.
+ * som.h (OBJ_SOM): Rename to TARGET_SOM. Undefine before defining.
+
+2002-04-11 David O'Brien <obrien@FreeBSD.org>
+
+ * config/freebsd.h (NO_IMPLICIT_EXTERN_C, SCCS_DIRECTIVE): Give value.
+ (DEFAULT_PCC_STRUCT_RETURN) Do not redefine.
+ (USER_LABEL_PREFIX, HANDLE_SYSV_PRAGMA, IDENT_ASM_OP,
+ DWARF2_DEBUGGING_INFO, DBX_DEBUGGING_INFO, PREFERRED_DEBUGGING_TYPE):
+ elfos.h and dbxelf.h values are fine now.
+ * config/i386/freebsd.h, config/alpha/freebsd.h
+ (DEFAULT_PCC_STRUCT_RETURN): Define to 0.
+
+2002-04-11 David O'Brien <obrien@FreeBSD.org>
+
+ * config/ia64/aix.h (CPP_PREDEFINES): Do not define _LP64/__LP64__
+ or set Acpu or Amachine. Reformat.
+ (ASM_SPEC, DONT_USE_BUILTIN_SETJMP, PROFILE_BEFORE_PROLOGUE): Do not
+ define.
+ (LINK_SPEC): Do not need to undef.
+ * config/ia64/elf.h (ASM_EXTRA_SPEC): Define.
+ * config/ia64/freebsd.h (LINK_SPEC): Do not need to undef.
+ (ASM_SPEC, DONT_USE_BUILTIN_SETJMP, PROFILE_BEFORE_PROLOGUE): Do not
+ define.
+ * config/ia64/hpux.h (ASM_EXTRA_SPEC): Define.
+ (ASM_SPEC): Do not define, use ASM_EXTRA_SPEC instead.
+ (LINK_SPEC): Do not need to undef.
+ (DONT_USE_BUILTIN_SETJMP): Do not define.
+ * config/ia64/ia64.h (ASM_SPEC, ASM_EXTRA_SPEC): Add.
+ (CPP_CPU_SPEC): Define _LP64, set Acpu and Amachine. Remove -Dia64.
+ (DONT_USE_BUILTIN_SETJMP, PROFILE_BEFORE_PROLOGUE): Define.
+ Remove trailing spaces.
+ * config/ia64/linux.h (CPP_PREDEFINES): Do not define _LP64/__LP64__,
+ __ELF__, or set Acpu or Amachine. Reformat.
+ (ASM_SPEC, DONT_USE_BUILTIN_SETJMP, PROFILE_BEFORE_PROLOGUE): Do not
+ define.
+
+2002-04-11 David O'Brien <obrien@FreeBSD.org>
+
+ * config.gcc (ia64-*-freebsd*): Fix ordering of tm_files to match
+ all other *-*-freebsd* targets.
+
+2002-04-11 Richard Henderson <rth@redhat.com>
+
+ * config.gcc (alpha*-*-linux*ecoff): Detect and reject.
+
+2002-04-11 David O'Brien <obrien@FreeBSD.org>
+
+ * config.gcc (alpha*-*-openbsd, alpha64-dec-*vms,alpha*-dec-*vms):
+ Include {cpu}/{cpu}.h thru tm_file.
+ (alpha*-*-linux*ecoff): Remove target.
+ * config/alpha/elf.h (CPP_SUBTARGET_SPEC): Define __ELF__.
+ (LINK_SPEC): Remove, is not OS independent.
+ * config/alpha/freebsd.h (CPP_SPEC): Do not define __ELF__.
+ (LINK_SPEC): Do not need to #undef any longer.
+ * config/alpha/linux-ecoff.h (LINK_SPEC): Do not need to #undef
+ any longer.
+ * config/alpha/linux-elf.h (SUB_CPP_PREDEFINES): Do not define
+ __ELF__.
+ (LINK_SPEC): Moved here from alpha/elf.h.
+ * config/alpha/linux.h (CPP_PREDEFINES): No longer consumer of
+ SUB_CPP_PREDEFINES.
+ * config/alpha/linux-ecoff.h: Remove.
+ * config/alpha/netbsd.h (CPP_PREDEFINES): Do not define __ELF__.
+ (CPP_SPEC): Define _POSIX_SOURCE as needed.
+ (CPP_SUBTARGET_SPEC): Do not define.
+ (LINK_SPEC): Do not need to #undef any longer.
+ * config/alpha/openbsd.h: Do not directly include alpha/alpha.h.
+ * config/alpha/vms.h: Likewise.
+
+2002-04-11 Richard Sandiford <rsandifo@redhat.com>
+
+ * doc/extend.texi: Remove old claim that typedefs cannot have
+ an alignment attribute.
+
+2002-04-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR optimization/6177
+ * expr.c (expand_expr) [COMPONENT_REF]: Handle op0 CONCAT if
+ bitpos is 0 and bitsize CONCAT size.
+
+2002-04-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/6223
+ * combine.c (if_then_else_cond): Use trunc_int_for_mode on nz.
+
+2002-04-10 David O'Brien <obrien@FreeBSD.org>
+
+ * config/alpha/freebsd.h: Minor reformatting.
+ (CPP_SPEC): Define ELF and add cpp_subtarget.
+ (ASM_SPEC): No longer needed.
+
+2002-04-11 Richard Henderson <rth@redhat.com>
+
+ * config/sparc/sparc.md (movdi_insn_sp32): Add o/J alternative.
+ (movdi_insn_sp32_v9): Likewise. Only allow stx with aligned memory.
+ (dimode mem/zero splitter): New.
+
+2002-04-11 Hans-Peter Nilsson <hp@axis.com>
+
+ * config/cris/cris.c (cris_override_options): Tweak error message
+ for PIC not implemented.
+
+ * config/cris/cris.h: Tweak comments related to parameter-passing.
+
+ * t-cris (TARGET_LIBGCC2_CFLAGS): Don't -Dinhibit_libc here.
+
+2002-04-10 Richard Henderson <rth@redhat.com>
+
+ * except.c (add_ehl_entry): Allow duplicates after landing pad
+ creation.
+
+2002-04-10 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/t-aix43 (SHLIB_NM_FLAGS): Add -X32_64.
+
+2002-04-10 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ * c-decl.c (c_init_decl_processing): Move generation of
+ decls for g77_integer_type_node and friends from here ...
+ * c-common.c (c_common_nodes_and_builtins): ... to here.
+
+2002-04-10 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * reload1.c (choose_reload_regs): HARD_FRAME_POINTER_REGNUM
+ is only used as frame pointer when frame_pointer_needed is true.
+
+2002-04-10 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/817
+ * arm.md (arm_movdi): Adjust neg_pool_range attribute to allow
+ for the fact that the pool entry uses two words.
+ (movdf_hard_insn): Similarly. Also, ADR instruction can span
+ 1k bytes.
+ (movdf_soft_insn): Similarly.
+ (movxf_hard_insn): Adjust neg_pool_range attribute to allow
+ for the fact that the pool entry uses three words.
+
+2002-04-10 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips.c (mips_va_arg): When using the struct version
+ of the EABI va_list, allow arguments in the register save area to
+ take up less room than a stack argument.
+
+2002-04-10 Richard Henderson <rth@redhat.com>
+
+ * expr.c (expand_expr) [INTEGER_CST]: Don't force into registers
+ if EXPAND_INITIALIZER.
+
+2002-04-09 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.md (movdi_er_maybe_g): New.
+ * config/alpha/alpha.c (alpha_expand_mov): Use it.
+
+2002-04-10 Alan Modra <amodra@bigpond.net.au>
+
+ PR optimization/6233
+ * rtlanal.c (pure_call_p): New function.
+ * rtl.h (pure_call_p): Declare.
+ * loop.c (prescan_loop): Use it to set has_nonconst_call.
+ * gcse.c (store_killed_in_insn): Use pure_call_p here too.
+
+2002-04-09 Eric Christopher <echristo@redhat.com>
+
+ * config/mips/mips.h (ASM_OUTPUT_ALIGNED_DECL_COMMON): Add additional
+ information to .comm directive.
+
+2002-04-09 Richard Henderson <rth@redhat.com>
+
+ PR c/5078
+ * expr.c (expand_expr) [INTEGER_CST]: Force overflows into registers.
+
+2002-04-09 Richard Henderson <rth@redhat.com>
+
+ * basic-block.h (flow_delete_block_noexpunge): Declare.
+ (expunge_block_nocompact): Declare.
+ * cfg.c (expunge_block_nocompact): Split out from ...
+ (expunge_block): ... here.
+ * cfgrtl.c (can_delete_label_p): Don't use exception_handler_labels.
+ (flow_delete_block_noexpunge): Split out from ...
+ (flow_delete_block): ... here.
+ * cfgcleanup.c (delete_unreachable_blocks): Compact while
+ removing dead blocks.
+ * except.c (exception_handler_labels): Remove.
+ (exception_handler_label_map): New.
+ (struct eh_region): Add aka member.
+ (mark_ehl_map_entry, mark_ehl_map, free_region): New.
+ (ehl_hash, ehl_eq, ehl_free, add_ehl_entry): New.
+ (for_each_eh_label, for_each_eh_label_1): New.
+ (init_eh): Register exception_handler_label_map.
+ (free_eh_status): Use free_region.
+ (find_exception_handler_labels): Use the map, not the list.
+ (remove_exception_handler_label): Likewise.
+ (maybe_remove_eh_handler): Likewise.
+ (remove_eh_handler): Use the region aka bitmap.
+ * except.h (exception_handler_labels): Remove.
+ (for_each_eh_label): Declare.
+ * jump.c (rebuild_jump_labels): Don't check exception_handler_labels.
+ * loop.c (invalidate_loops_containing_label): New.
+ (find_and_verify_loops): Use it. Use for_each_eh_label.
+ * sched-rgn.c (is_cfg_nonregular): Use
+ current_function_has_exception_handlers.
+
+2002-04-09 Richard Henderson <rth@redhat.com>
+
+ * sbitmap.c (sbitmap_union_of_diff, sbitmap_a_and_b, sbitmap_a_xor_b,
+ sbitmap_a_or_b, sbitmap_a_or_b_and_c, sbitmap_a_and_b_or_c):
+ Do not return changed status.
+ (sbitmap_union_of_diff_cg, sbitmap_a_and_b_cg, sbitmap_a_xor_b_cg,
+ sbitmap_a_or_b_cg, sbitmap_a_or_b_and_c_cg, sbitmap_a_and_b_or_c_cg):
+ New functions that do return changed status.
+ * sbitmap.h: Update decls.
+ * gcse.c, lcm.c: Use _cg functions as needed.
+
+Tue Apr 9 19:15:57 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * config.gcc (sh-*-elf*): Use sh/embed-elf.h instead of sh/elf.h.
+ (sh64-*-elf*, sh-*-rtemself*): Likewise.
+ * config/sh/embed_bb.c: New file.
+ * config/sh/embed-elf.h: New file.
+ * sh.h (CPP_SPEC): Supply __SIZE_TYPE__ and __PTRDIFF_TYPE__
+ if -m[12345]* option is given. Don't use subtarget_cpp_ptr_spec.
+ (CPP_DEFAULT_CPU_SPEC): Add settings for __SIZE_TYPE__ and
+ __PTRDIFF_TYPE__ .
+ (SUBTARGET_CPP_PTR_SPEC): Don't define.
+ (EXTRA_SPECS): Remove subtarget_cpp_ptr_spec.
+ Add subtarget_asm_endian_spec.
+ (ASM_SPEC): Use subtarget_asm_endian_spec.
+ (SUBTARGET_ASM_ENDIAN_SPEC): Define.
+ (RETURN_ADDR_RTX): Use PR_MEDIA_REG for TARGET_SH5.
+ (WCHAR_UNSIGNED): Define.
+ (SH_ELF_WCHAR_TYPE, SH_DBX_REGISTER_NUMBER): Define.
+ (DBX_REGISTER_NUMBER): Use SH_DBX_REGISTER_NUMBER.
+ (ALLOCATE_INITIAL_VALUE): Use PR_MEDIA_REG for TARGET_SH5.
+ Fix value.
+ * sh.c (calc_live_regs): Use PR_MEDIA_REG for TARGET_SH5.
+ (sh_adjust_cost): Likewise.
+ sh64.h (CPP_DEFAULT_CPU_SPEC): Add settings for __SIZE_TYPE__ and
+ __PTRDIFF_TYPE__ .
+ (SUBTARGET_CPP_PTR_SPEC, WCHAR_TYPE): Don't #undef/ #define.
+ (WCHAR_TYPE_SIZE): Likewise.
+ (ASM_SPEC): Use subtarget_asm_endian_spec.
+ (SH_ELF_WCHAR_TYPE): #undef/ #define.
+ (MAX_WCHAR_TYPE_SIZE): Don't #undef.
+ * config/sh/elf.h (WCHAR_UNSIGNED): #undef .
+ (MAX_WCHAR_TYPE_SIZE): Don't #define .
+ (WCHAR_TYPE, WCHAR_TYPE_SIZE): #undef / #define .
+ (USER_LABEL_PREFIX): Don't #undef /#define .
+ (DBX_REGISTER_NUMBER): Use SH_DBX_REGISTER_NUMBER.
+ * config/elf/linux.h (USER_LABEL_PREFIX): Don't #undef /#define .
+ (SIZE_TYPE, PTRDIFF_TYPE, WCHAR_TYPE, WCHAR_TYPE_SIZE): Likewise.
+ (ASM_SPEC): Likewise.
+ (SUBTARGET_ASM_ENDIAN_SPEC): #undef / #define .
+ (CC1_SPEC): don't supply -m3 for -m4*, -m5*.
+ * t-sh: (LIB1ASMFUNCS): Use LIB1ASMFUNCS_CACHE.
+ (LIB2FUNCS_EXTRA): Define.
+ * t-sh64 (LIB2FUNCS_EXTRA): Define.
+ * config/sh/t-linux (LIB1ASMFUNCS): Don't redefine.
+ (LIB1ASMFUNCS_CACHE): Define.
+ (LIB2FUNCS_EXTRA): Redefine empty.
+
+2002-04-08 Richard Henderson <rth@redhat.com>
+
+ * reorg.c (get_branch_condition): Use reversed_comparison_code.
+
+2002-04-09 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/larith.asm (__map_data_section): Fix condition
+ and optimize for size.
+ (__do_global_ctors): Fix pointer comparison.
+ (__do_global_dtors): Likewise.
+
+2002-04-09 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.c (sparc_extra_constraint_check): New
+ function, implementing EXTRA_CONSTRAINTS. For memory constraints,
+ allow reloading pseudos.
+ * config/sparc/sparc.h (EXTRA_CONSTRAINTS): Use it.
+ * config/sparc/sparc-protos.h: Declare it.
+
+ * config/sparc/sparc.c (const64_is_2insns): Kill signed vs.
+ unsigned comparison warning.
+ (output_restore_regs): Mark leaf_function as unused.
+
+Tue Apr 9 09:35:45 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * expr.c (is_aligning_offset): New function.
+ (expand_expr, case COMPONENT_EXPR): Call it.
+
+2002-04-08 David S. Miller <davem@redhat.com>
+
+ PR target/6082
+ * config/sparc/freebsd.h (SPARC_DEFAULT_CMODEL): Set to CM_MEDLOW
+
+ Make init_priority work on SPARC when using GNU ld.
+ * config/sparc/linux.h, config/sparc/linux64.h,
+ config/sparc/netbsd-elf.h, config/sparc/freebsd.h
+ (CTORS_SECTION_ASM_OP, DTORS_SECTION_ASM_OP): Undefine.
+ * config/sparc/sol2-gld.h: New file to do the same.
+ * config.gcc (sparc*-*-solaris2*): If gnu_ld=yes add
+ sparc/sol2-gld.h to tm_file.
+
+ PR optimization/4328
+ * config/sparc/sparc.h (EXTRA_CONSTRAINT): Add new constraint 'W'.
+ * doc/md.texi: Document it.
+ * config/sparc/sparc.md (movdi_insn_sp64_novis,
+ movdi_insn_sp64_vis, movdf_insn_sp32, movdf_insn_v9only_novis,
+ movdf_insn_v9only_vis, movdf_insn_sp64_novis,
+ movdf_insn_sp64_vis): Use it as MEM constraing with 'e' registers.
+ * config/sparc/sparc.c (mem_min_alignment): Fix comment.
+
+2002-04-08 Andreas Jaeger <aj@suse.de>
+
+ * stmt.c (expand_asm_operands): Revert last patch from Richard
+ Henderson.
+
+2002-04-08 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/contrib.texi (Contributors): Add John David Anglin and Loren
+ J. Rittle (the latter also to Testers). Update David O'Brien's entry.
+
+2002-04-08 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/contrib.texi (Contributors): Add David O'Brien.
+
+2002-04-08 Alan Modra <amodra@bigpond.net.au>
+
+ * configure.in (auto-build.h): Use target_alias and build_alias
+ when running configure.
+ (gcc_cv_as, gcc_cv_ld): Search install paths when build != host too.
+ (gcc_cv_nm, gcc_cv_objdump): Set for build != host too.
+ * configure: Regenerate.
+
+2002-04-07 David S. Miller <davem@redhat.com>
+
+ * config.gcc (sparc64-*-linux*): Add t-crtfm to tmake_file.
+
+2002-04-07 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ PR 5933
+ * pa.h (ASM_OUTPUT_MI_THUNK): Use indirect jump to target function when
+ generating 32-bit pic code.
+
+2002-04-06 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * cppinit.c (cpp_create_reader): Initialize
+ discard_comments_in_macro_exp.
+ (COMMAND_LINE_OPTIONS): Add "-CC" option.
+ (cpp_handle_option): Handle "-CC" option.
+ * cpplex.c (save_comment): If saving a C++ comment in
+ a directive, convert it to a C comment.
+ (_cpp_lex_direct): Pass second comment start character to
+ save_comment to indicate comment type.
+ * cpplib.c (_cpp_handle_directive): If processing
+ a "#define" directive and discard_comments_in_macro_exp
+ is false, re-enable saving of comments.
+ (lex_macro_node): If discard_comments_in_macro_exp is false,
+ discard any comments before the macro identifier.
+ * cpplib.h (struct cpp_options): Add discard_comments_in_macro_exp
+ member.
+ * cppmacro.c (cpp_get_token): If expanding a macro while
+ processing a directive, discard any comments we might encounter.
+ (parse_params): If discard_comments_in_macro_exp is false,
+ ignore comments in the macro parameter list.
+ * gcc.c (cpp_unique_options): Add "-CC" option.
+ (option_map): Map "--comments-in-macros" to "-CC".
+ * doc/cppopts.texi: Document "-CC" option.
+ * f/lang-specs.h: Add "-CC" option.
+ * testsuite/gcc.dg/cpp/maccom1.c: New test.
+ * testsuite/gcc.dg/cpp/maccom2.c: New test.
+ * testsuite/gcc.dg/cpp/maccom3.c: New test.
+ * testsuite/gcc.dg/cpp/maccom4.c: New test.
+ * testsuite/gcc.dg/cpp/maccom5.c: New test.
+ * testsuite/gcc.dg/cpp/maccom6.c: New test.
+
+2002-04-06 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ PR middle-end/6180
+ * reorg.c (dbr_schedule): Don't reposition prologue and epilogue notes.
+
+2002-04-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/5571
+ * stor-layout.c (layout_decl): Reset the RTL for the decl.
+
+ PR opt/5120
+ * sibcall.c (optimize_sibling_and_tail_recursive_call): Clear
+ RTX_UNCHANGING_P for the functions arguments when a tail call
+ is made.
+
+2002-04-06 Jason Merrill <jason@redhat.com>
+
+ * toplev.c (flag_no_inline, flag_really_no_inline): Default to 2.
+ (parse_options_and_default_flags): Set them appropriately.
+ * c-common.c (c_common_post_options): Don't set flag_really_no_inline.
+
+2002-04-06 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/t-mmix (TARGET_LIBGCC2_CFLAGS): Don't -Dinhibit_libc
+ here.
+
+ * config/mmix/mmix.h (INITIAL_ELIMINATION_OFFSET): Remove spurious
+ semicolon.
+
+ * config/mmix/mmix.c (mmix_expand_builtin_va_arg): Variable-size
+ types come in by-reference. Fix typo in comment.
+
+2002-04-05 David S. Miller <davem@redhat.com>
+
+ * config/sparc/freebsd.h (ENDFILE_SPEC): Add crtfastmath bits.
+ * config.gcc (sparc64-wrs-vxworks, sparc-*-chorusos,
+ sparc-*-rtems*, sparclite-*-elf* sparc86x-*-elf*, sparc64-*-elf*,
+ {sparc64,ultrasparc}-*-freebsd*): Add sparc/t-crtfm to tmake_file.
+
+2002-04-05 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.c (sparc_nonflat_function_epilogue): If we
+ are not going to emit return instructions, emit at least a nop
+ for the sake of sane backtraces.
+
+2002-04-05 Richard Henderson <rth@redhat.com>
+
+ * doc/rtl.texi (Regs and Memory): Document (mem:BLK (scratch)).
+
+2002-04-05 Jakub Jeilnek <jakub@redhat.com>
+
+ * mklibgcc.in: Use $tmpmapfile, not tmp-$@.
+
+2002-04-05 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/mips/mips.h (ISA_HAS_BRANCHLIKELY, ISA_HAS_CONDMOVE,
+ ISA_HAS_FP4, ISA_HAS_MADD_MSUB, ISA_HAS_NMADD_NMSUB,
+ ISA_HAS_CLZ_CLO, ISA_HAS_DCLZ_DCLO): Disable if TARGET_MIPS16.
+
+2002-04-05 Andreas Schwab <schwab@suse.de>
+
+ * c-convert.c: Include c-common.h.
+ * Makefile.in (c-convert.o): Updated.
+
+2002-04-05 Jakub Jelinek <jakub@redhat.com>
+
+ * mklibgcc.in: Use separate libgcc.map for each multilib.
+ * Makefile.in (distclean): Don't remove libgcc.map here.
+
+2002-04-05 Jakub Jelinek <jakub@redhat.com>
+
+ * Makefile.in (s-mlib): Handle --disable-multilib by separate
+ genmultilib invocation.
+
+2002-04-04 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips.h (CUMULATIVE_ARGS): Rename fp_regs to num_fprs
+ to avoid clash with Irix header file sys/ucontext.h. Rename gp_regs
+ to num_gprs for symmetry.
+ * config/mips/mips.c: Adjust accordingly.
+
+2002-04-04 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (truthvalue_conversion): Rename, update.
+ * c-common.h (c_common_truthvalue_conversion): New.
+ * c-convert.c (convert): Update.
+ * c-lang.c (LANG_HOOKS_TRUTHVALUE_CONVERSION): Redefine.
+ * c-parse.in (expr_no_commas, if_prefix, select_or_iter_stmt): Update.
+ * c-typeck.c (build_binary_op, build_unary_op,
+ build_conditional_expr): Update.
+ * fold-const.c (constant_boolean_node, fold): Use langhook.
+ * langhooks-def.h (LANGHOOK_INITIALIZER): Update.
+ * langhooks.h (struct lang_hooks): New hook.
+ * stmt.c (expand_decl_cleanup): Use langhook.
+ * tree.h (truthvalue_conversion): Remove.
+objc:
+ * objc-lang.c (LANG_HOOKS_TRUTHVALUE_CONVERSION): Redefine.
+
+2002-04-05 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/t-linux64 (EXTRA_MULTILIB_PARTS): Add crtsavres.o
+ Add rules to make null object file.
+
+2002-04-04 Jim Blandy <jimb@redhat.com>
+
+ * cppmacro.c (cpp_macro_definition): Do not emit spaces after
+ macro formal parameter names.
+
+2002-04-04 David S. Miller <davem@redhat.com>
+
+ * calls.c (store_one_arg): If ECF_SIBCALL, use tail_call_reg.
+
+2002-04-04 Richard Henderson <rth@redhat.com>
+
+ PR middle-end/5099
+ * stmt.c (expand_asm_operands): Validate outputs vs asm_operand_ok.
+ Support copies into and out of memory. Don't accept allows_reg
+ and allows_mem as gospel.
+
+2002-04-04 Richard Henderson <rth@redhat.com>
+
+ PR opt/6165
+ * alias.c (true_dependence): Force (mem:blk (scratch)) to conflict.
+ (write_dependence_p): Likewise.
+
+2002-04-04 Richard Henderson <rth@redhat.com>
+
+ * predict.c (estimate_bb_frequencies): Do frequency calculation
+ with a volatile temporary.
+
+2002-04-04 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/linux.h (LOCAL_LABEL_PREFIX): Define.
+
+2002-04-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/6119
+ * final.c (final_start_function): Don't bump profile_label_no here...
+ (final_end_function): ...but here.
+
+2002-04-04 Jakub Jelinek <jakub@redhat.com>
+
+ * config/sparc/sparc.md (pic): New attribute.
+ (do_builtin_setjmp_setup): Save %fp, %i7 and %l7 for TARGET_V9
+ into stack slots.
+ (split after do_builtin_setjmp_setup): New.
+
+2002-04-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR fortran/6106
+ * config/sparc/sparc.h (MIN_UNITS_PER_WORD): Backout 2001-01-01
+ change.
+
+2002-04-04 Jakub Jelinek <jakub@redhat.com>
+
+ * config/sparc/sparc.c (sparc_va_arg): Adjust va_list by
+ UNITS_PER_WORD for zero sized aggregates.
+
+2002-04-03 David S. Miller <davem@redhat.com>
+
+ * gcc.c (LINK_GCC_C_SEQUENCE_SPEC): No need for a new
+ one-character spec for this, just use %(link_gcc_c_sequence).
+
+2002-04-03 David S. Miller <davem@redhat.com>
+
+ * config/sparc/crtfastmath.c (FPRS_NS): Delete bogus little-endian
+ handling.
+
+2002-04-03 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa-linux.h (INCOMING_RETURN_ADDR_RTX): Move.
+ (DWARF_FRAME_RETURN_COLUMN): Move.
+ (ASM_PREFERRED_EH_DATA_FORMAT): Define.
+ (ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX): Define.
+ * pa.c (except.h, predict.h): Include.
+ (FRP): Delete.
+ (store_reg_modify, set_reg_plus_d): Revise prototypes.
+ (output_ascii): Add cast.
+ (store_reg_modify): Revise to add frame notes.
+ (set_reg_plus_d): Likewise.
+ (compute_frame_size): Include space for eh data registers in frame if
+ the current function calls eh_return.
+ (hppa_expand_prologue): Ensure register %r2 is saved if the current
+ function calls eh_return. Save eh data registers if the current
+ function calls eh_return. Fix code to add frame notes. Emit
+ blockage to prevent insns with frame notes being scheduled in the
+ delay slot of calls.
+ (hppa_expand_epilogue): Restore eh data registers and do final stack
+ adjustment if the current function calls eh_return. Don't add frame
+ notes.
+ (output_call): Revise for change in length of call insn. Don't do
+ return pointer adjustment for an unconditional jump in the delay slot
+ of a call when using frame notes.
+ * pa.h (EH_RETURN_DATA_REGNO): Revise for TARGET_64BIT compatibility.
+ (EH_RETURN_HANDLER_RTX): Use saved value on stack.
+ (ARG_POINTER_CFA_OFFSET): Define.
+ * pa.md (return_external_pic): New pattern.
+ (prologue): Correct formatting. Use return_external_pic if current
+ function calls eh_return.
+ (call_internal_symref, call_value_internal_symref,
+ sibcall_internal_symref, sibcall_value_internal_symref): Change default
+ lengths of short, long non-pic, and long pic calls to 8, 68, and 84,
+ respectively.
+ (exception_receiver): Use hppa_pic_save_rtx () to restore pic register.
+
+ * configure.in ("assembler dwarf2 debug_line support"): Add hppa*-*-* to
+ list of targets to check using "nop" insn.
+ * configure: Rebuilt.
+
+2002-04-04 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/t-linux64 (EXTRA_MULTILIB_PARTS): Define.
+
+2002-04-03 David S. Miller <davem@redhat.com>
+
+ * gcc.c (LINK_GCC_C_SEQUENCE_SPEC): New spec to override the gcc/c
+ library sequence passed to the linker.
+ (LINK_COMMAND_SPEC): Use it.
+ * doc/tm.texi: Document it, and mention from LINK_COMMAND_SPEC as
+ a macro a target can use to avoid overriding LINK_COMMAND_SPEC.
+ * config/sparc/sparc.h (LINK_GCC_C_SEQUENCE_SPEC): Define.
+
+2002-04-03 Jason Merrill <jason@redhat.com>
+
+ * except.c (struct eh_status): Remove protect_list.
+ (begin_protect_partials, end_protect_partials): Remove.
+ (add_partial_entry): Remove.
+ * except.h: Remove prototypes.
+
+ * expr.c (expand_expr) [WITH_CLEANUP_EXPR, TARGET_EXPR]: Use
+ expand_decl_cleanup_eh.
+
+ PR c++/5636
+ * tree.h (CLEANUP_EH_ONLY): New macro.
+ * stmt.c (expand_decl_cleanup_eh): New fn.
+ (expand_cleanups): Check CLEANUP_EH_ONLY.
+ * c-semantics.c (genrtl_decl_cleanup): Just take the CLEANUP_STMT.
+ Use expand_decl_cleanup_eh.
+ (expand_stmt): Adjust.
+ * c-common.h: Adjust prototype.
+
+2002-04-04 Hans-Peter Nilsson <hp@axis.com>
+
+ * config/cris/cris.c (cris_target_asm_function_prologue): Cast
+ uses of PIC_OFFSET_TABLE_REGNUM to int to silence warnings.
+ (cris_target_asm_function_epilogue): Ditto.
+ (cris_initial_frame_pointer_offset): Ditto.
+ (cris_simple_epilogue): Ditto.
+ (cris_expand_builtin_va_arg): Variable-size types come in
+ by-reference.
+
+2002-04-03 David S. Miller <davem@redhat.com>
+
+ * config/sparc/crtfastmath.c (FPRS_NS): Get it right for
+ little-endian.
+ (set_fast_math): Correct 'fsr' type.
+
+2002-04-03 Richard Henderson <rth@redhat.com>
+
+ PR opt/3569
+ * langhooks.h (lang_hooks.decls.warn_unused_global): New.
+ * toplev.c (check_global_declarations): Use it.
+ * langhooks-def.h (lhd_warn_unused_global_decl): Declare.
+ (LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL): New.
+ (LANG_HOOKS_DECLS): Add it.
+ * langhooks.c (lhd_warn_unused_global_decl): New.
+ * c-decl.c (LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL): New.
+ * c-objc-common.c (c_warn_unused_global_decl): New.
+ * c-tree.h (c_warn_unused_global_decl): Declare.
+ * objc/objc-lang.c (LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL): New.
+
+2002-04-03 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * langhooks-def.h (lhd_set_decl_assembler_name,
+ LANG_HOOKS_SET_DECL_ASSEMBLER_NAME): New.
+ (LANG_HOOKS_INITIALIZER): Update.
+ * langhooks.c (lhd_set_decl_assembler_name): New, from tree.c
+ * langhooks.h (struct lang_hooks): New hook.
+ * tree.c (set_decl_assembler_name): Move to langhooks.c.
+ (lang_set_decl_assembler_name): Remove.
+ (init_obstacks): Don't set hook.
+ (decl_assembler_name): New function.
+ * tree.h (DECL_ASSEMBLER_NAME): Turn into a function call.
+ (decl_assembler_name): New.
+ (lang_set_decl_assembler_name): Remove.
+
+2002-04-03 Jakub Jelinek <jakub@redhat.com>
+
+ * configure.in (HAVE_SPARC_UA_PCREL_HIDDEN): Test whether %r_disp32()
+ works properly with .hidden symbols.
+ * configure: Rebuilt.
+ * config.in: Rebuilt.
+ * config/sparc/sparc.h (ASM_PREFERRED_EH_DATA_FORMAT): Use
+ DW_EH_PE_absptr for flag_pic && GLOBAL if %r_disp32() doesn't work
+ properly with .hidden symbols.
+
+2002-04-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/6102
+ * df.c (df_insn_refs_record): Use XEXP not SET_DEST to access
+ USE argument.
+
+2002-04-03 Richard Henderson <rth@redhat.com>
+
+ PR opt/4120
+ * sched-rgn.c (sets_likely_spilled): New.
+ (sets_likely_spilled_1): New.
+ (add_branch_dependences): Use it.
+
+2002-04-02 Richard Henderson <rth@redhat.com>
+
+ PR opt/4311
+ * loop.h (LOOP_FIRST_PASS): New.
+ * loop.c (strength_reduce): Mind it when deciding to unroll.
+ * toplev.c (rest_of_compilation): Set it.
+
+2002-04-02 David S. Miller <davem@redhat.com>
+
+ * config/sparc/sparc.md (ldd peephole2s): Fix final arg to
+ mems_ok_for_ldd_peep when the order of the loads being examined
+ is reversed.
+ * config/sparc/sparc.c (mems_ok_for_ldd_peep): Expand upon
+ existing comment to increase comprehension of this situation.
+
+2002-04-02 Zack Weinberg <zack@codesourcery.com>
+
+ * config/sh/sh.md: Don't use union real_extract.
+
+2002-04-02 Richard Henderson <rth@redhat.com>
+
+ * libgcc2.c (__bb_exit_func): Revert 03-31 change.
+
+2002-04-02 David O'Brien <obrien@FreeBSD.org>
+
+ * config.gcc (i386-dg-dgux, i386-go32-msdos , i386-go32-rtems,
+ i386-ibm-aix, i386-moss-msdos, i386-ncr-sysv4, i386-next-,
+ i386-pc-msdosdjgpp, i386-sequent-bsd, i386-sequent-ptx1,
+ i386-sequent-ptx2, i386-sequent-ptx4, i386-sun-sunos,
+ i386-wrs-vxworks, i386-*-aout, i386-*-beoself, i386-*-bsd,
+ i386-*-bsdi, i386-*-chorusos, i386-*-coff, i386-*-elf,
+ i386-*-freebsd5, i386-*-freebsd-aout, i386-*-gnu, i386-*-interix,
+ i386-*-interix3, i386-*-isc, i386-*-linux, i386-*-linuxaout,
+ i386-*-linuxoldld, i386-*-lynxos, i386-*-mach, i386-*-mingw32,
+ i386-*-netbsd, i386-*-netbsdelf, i386-*-netware, i386-*-openbsd,
+ i386-*-osf1, i386-*-osfrose, i386-*-pe , i386-*-rtems,
+ i386-*-rtemscoff, i386-*-sco3.2v5, i386-*-solaris2, i386-*-sysv,
+ i386-*-sysv4, i386-*-sysv5, i386-*-udk, i386-*-uwin, i386-*-vsta,
+ i386-*-win32, x86_64-*-freebsd5, x86_64-*-linux, x86_64-*-netbsd):
+ Include as many configury headers via tm_file as possible. This
+ includes among others i386/unix.h, i386/bsd.h, i386/gas.h.
+ * config/openbsd-oldgas.h: New file.
+ * config/i386/386bsd.h, config/i386/aix386ng.h, config/i386/att.h,
+ config/i386/bsd.h, config/i386/djgpp.h, config/i386/freebsd-aout.h,
+ config/i386/gas.h, config/i386/gstabs.h, config/i386/i386-aout.h,
+ config/i386/i386-coff.h, config/i386/i386-interix.h,
+ config/i386/iscdbx.h, config/i386/linux-aout.h,
+ config/i386/linux-oldld.h, config/i386/lynx-ng.h, config/i386/lynx.h,
+ config/i386/mach.h, config/i386/netbsd.h, config/i386/next.h,
+ config/i386/openbsd.h, config/i386/osfelf.h, config/i386/osfrose.h,
+ config/i386/sco5.h, config/i386/seq-gas.h, config/i386/seq-sysv3.h,
+ config/i386/seq2-sysv3.h, config/i386/sequent.h, config/i386/sun.h,
+ config/i386/sun386.h, config/i386/svr3dbx.h, config/i386/svr3gas.h,
+ config/i386/sysv3.h, config/i386/uwin.h, config/i386/vsta.h,
+ config/i386/vxi386.h: Do not directly include configury headers.
+ * config/i386/cygwin.h, config/i386/djgpp.h, config/i386/win32.h:
+ Directly include configury headers that are no longer automatically
+ included by the above headers.
+ * config/i386/att.h, config/i386/bsd.h (TARGET_VERSION): Do not define.
+ * config/i386/386bsd.h, config/i386/aix386ng.h, config/i386/cygwin.h,
+ config/i386/djgpp.h, config/i386/i386-aout.h, config/i386/i386-coff.h,
+ config/i386/lynx-ng.h, config/i386/lynx.h, config/i386/mach.h,
+ config/i386/netbsd.h, config/i386/openbsd.h, config/i386/rtems.h,
+ config/i386/seq-sysv3.h, config/i386/sequent.h, config/i386/svr3gas.h,
+ config/i386/sysv3.h, config/i386/vsta.h, config/i386/vxi386.h
+ (TARGET_VERSION): Define.
+ * config/i386/beos-elf.h, config/i386/freebsd.h,
+ config/i386/i386-interix.h, config/i386/i386elf.h, config/i386/linux.h,
+ config/i386/linux64.h, config/i386/netbsd-elf.h, config/i386/netbsd64.h,
+ config/i386/osfelf.h, config/i386/osfrose.h, config/i386/ptx4-i.h,
+ config/i386/sco5.h, config/i386/sysv4.h
+ (TARGET_VERSION): Do not need to protect.
+ * config/i386/freebsd64.h (TARGET_VERSION): Fix style.
+ * config/i386/386bsd.h, config/i386/cygwin.h, config/i386/djgpp.h,
+ config/i386/freebsd-aout.h, config/i386/i386-aout.h,
+ config/i386/i386-interix.h, config/i386/linux-aout.h,
+ config/i386/linux-oldld.h, config/i386/mach.h, config/i386/netbsd.h,
+ config/i386/openbsd.h, config/i386/vsta.h, config/i386/win32.h
+ (YES_UNDERSCORES): Do not define - not needed.
+ * config/i386/bsd.h, config/i386/gas.h (LPREFIX,
+ ASM_GENERATE_INTERNAL_LABEL, ASM_OUTPUT_INTERNAL_LABEL,
+ USER_LABEL_PREFIX): Do not handle the "NO_UNDERSCORES" case.
+ * config/i386/i386-coff.h, config/i386/lynx.h, config/i386/lynx-ng.h
+ (LPREFIX, ASM_GENERATE_INTERNAL_LABEL, ASM_OUTPUT_INTERNAL_LABEL,
+ USER_LABEL_PREFIX): Define. (handles the "NO_UNDERSCORES" case)
+ * config/i386/isc.h: Preserve comment from config/i386/isccoff.h.
+ * config/i386/isccoff.h, config/i386/v3gas.h: Remove.
+
+2002-04-02 Eric Botcazou <ebotcazou@multimania.com>
+ Richard Henderson <rth@redhat.com>
+
+ PR c/5484
+ * function.c (assign_temp): Accept either type or decl argument.
+ Detect variables whose size is too large to fit into an integer.
+ * stmt.c (expand_decl): Pass the decl, not the type.
+
+2002-04-02 David O'Brien <obrien@FreeBSD.org>
+
+ * protoize.c: Match include directory usage with cppdefault.c.
+
+2002-04-03 Jeffrey A Law (law@redhat.com)
+ Hans-Peter Nilsson <hp@bitrange.com>
+
+ * combine.c (simplify_comparison): Avoid narrowing a comparison
+ with a paradoxical subreg when doing so would drop signficant bits.
+
+2002-04-02 Steve Ellcey <sje@cup.hp.com>
+
+ * builtins.c (expand_builtin_prefetch): Force op0 pointer to Pmode
+ if POINTERS_EXTEND_UNSIGNED is defined.
+
+2002-04-02 Richard Henderson <rth@redhat.com>
+
+ PR opt/3967
+ * local-alloc.c (contains_replace_regs): LO_SUM may contain
+ replace regs.
+
+2002-04-02 Richard Henderson <rth@redhat.com>
+
+ * doc/standards.texi: Document required freestanding libc entry points.
+
+2002-04-02 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.md (ctrdi*): Add FPR constraint and
+ associated splitter. Remove MQ constraint.
+ (ctrdi_internal4): Correct CCmode clobber.
+
+2002-04-02 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * milli64.S ($$dyncall): New function.
+ * t-linux (LIB1ASMFUNCS): Revise module list.
+ (LIB1ASMSRC): Use pa/milli64.S.
+
+2002-04-02 Richard Henderson <rth@redhat.com>
+
+ * fixinc/inclhack.def (AAB_solaris_sys_varargs_h): Move and
+ rename solaris_sys_varargs_h.
+
+Tue Apr 2 06:47:40 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * stor-layout.c (layout_type, case ARRAY_TYPE): Give one-element array
+ the same mode as its component.
+
+2002-04-02 Richard Henderson <rth@redhat.com>
+
+ PR opt/190
+ * final.c (this_is_asm_operands): Export.
+ * output.h (this_is_asm_operands): Declare.
+ * config/i386/i386.c (print_operand): Error odd asm operands.
+
+2002-04-02 Richard Henderson <rth@redhat.com>
+
+ PR opt/420
+ * config/m68k/m68k.md (dbcc peepholes): Match four forms of dbra.
+
+2002-04-01 Richard Henderson <rth@redhat.com>
+
+ PR target/1538
+ * fixinc/inclhack.def (solaris_sys_varargs_h): New.
+ * fixinc/fixincl.x: Rebuild.
+
+2002-04-01 Richard Henderson <rth@redhat.com>
+
+ * config/ia64/unwind-ia64.c: Include ia64intrin.h.
+ (atomic_alloc, atomic_free): New.
+ (SIZE, MASK_FOR, PTR_IN): New.
+ (emergency_reg_state, emergency_reg_state_free): New.
+ (emergency_labeled_state, emergency_labeled_state_free): New.
+ (reg_state_alloced, labeled_state_alloced): New.
+ (alloc_reg_state, free_reg_state): New.
+ (alloc_label_state, free_label_state, free_label_states): New.
+ (push, pop, dup_state_stack, free_state_stack): Use them.
+ (desc_label_state): Likewise.
+ (uw_frame_state_for): Free label states and state stack.
+ (uw_update_reg_address): Eliminate warnings.
+
+2002-04-01 Vladimir Makarov <vmakarov@redhat.com>
+
+ * config/pa/pa-pro-end.h (ASM_OUTPUT_ALIGNED_COMMON,
+ ASM_OUTPUT_ALIGNED_LOCAL): Redefine them.
+
+2002-04-01 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-decl.c (grokdeclarator): Update.
+ * c-lang.c (LANG_HOOKS_MARK_ADDRESSABLE): Redefine.
+ * c-tree.h (c_mark_addressable): New.
+ * c-typeck.c (default_function_array_conversion, build_unary_op,
+ build_array_ref, convert_for_assignment): Update.
+ (mark_addressable): Rename.
+ * calls.c (try_to_integrate, expand_call): Use langhook.
+ * expr.c (expand_expr): Use langhook.
+ * langhooks-def.h (LANG_HOOKS_INITIALIZER): Update.
+ * langhooks.h (struct lang_hooks): New hook.
+ * stmt.c (expand_asm_operands): Use langhook.
+ * tree.h (mark_addressable): Remove.
+objc:
+ * objc-lang.c (LANG_HOOKS_MARK_ADDRESSABLE): Redefine.
+
+2002-04-01 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.c (xtensa_va_arg): Fix compiler warning
+ in previous change.
+
+2002-04-01 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.c (xtensa_va_arg): Fix to handle arguments
+ for which MUST_PASS_IN_STACK is true (e.g., variable-sized types).
+
+2002-04-01 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (unsigned_conversion_warning, convert_and_check,
+ unsigned_type, signed_type, shorten_compare,
+ c_common_get_alias_set, c_common_nodes_and_builtins): Use new hooks.
+ (unsigned_type, signed_type, signed_or_unsigned_type): Rename.
+ * c-common.h (unsigned_type, signed_type, signed_or_unsigned_type):
+ New.
+ * c-decl.c (grokdeclarator): Update.
+ * c-format.c (check_format_types): Update.
+ * c-lang.c (LANG_HOOKS_SIGNED_TYPE, LANG_HOOKS_UNSIGNED_TYPE,
+ LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE): New.
+ * c-typeck.c (build_binary_op, convert_for_assignment): Update.
+ * convert.c (convert_to_integer): Use new hooks.
+ * expmed.c (make_tree): Use new hooks.
+ * expr.c (store_expr): Use new hooks.
+ * fold-const.c (operand_equal_for_comparison_p, build_range_check,
+ all_ones_mask_p, unextend, fold): Use new hooks.
+ * langhooks.h (struct lang_hooks_for_types): New hooks.
+ * tree.h (signed_or_unsigned_type, signed_type,
+ unsigned_type): Remove.
+objc:
+ * objc-lang.c (LANG_HOOKS_SIGNED_TYPE, LANG_HOOKS_UNSIGNED_TYPE,
+ LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE): New.
+
+2002-03-31 Richard Henderson <rth@redhat.com>
+
+ * config/ia64/unwind-ia64.c (alloc_spill_area): Fix offset.
+ (desc_frgr_mem): Fix reference to f16-f31.
+
+2002-03-31 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * rtl.h (RTL_CHECK1, RTL_CHECK2, RTL_CHECKC1, RTL_CHECKC2,
+ RTVEC_ELT): Const-ify.
+ * varray.h (VARRAY_CHECK): Const-ify.
+ * ggc.h (ggc_mark_rtx, ggc_mark_tree, ggc_mark_nonnull_tree,
+ ggc_mark_rtvec, ggc_mark): Const-ify.
+
+2002-04-01 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * diagnostic.c: Include langhooks-def.h.
+ * Makefile.in (diagnostic.o): Update.
+
+2002-03-31 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (c_unsafe_for_reeval): Rename.
+ * c-common.h (c_unsafe_for_reeval): Rename.
+ * c-decl.c (finish_incomplete_decl): Rename.
+ (c_init_decl_processing): Don't set langhook.
+ * c-lang.c (LANG_HOOKS_FINISH_INCOMPLETE_DECL,
+ LANG_HOOKS_UNSAFE_FOR_REEVAL): Redefine.
+ * c-objc-common.c (c_objc_common_init): Don't set langhook.
+ * c-tree.h (finish_incomplete_decl): Rename.
+ * langhooks-def.h (lhd_unsafe_for_reeval): New.
+ (LANG_HOOKS_FINISH_INCOMPLETE_DECL, LANG_HOOKS_UNSAFE_FOR_REEVAL): New.
+ (LANG_HOOKS_INITIALIZER): Update.
+ * langhooks.c (lhd_unsafe_For_reeval): New.
+ * langhooks.h (struct langhooks): New hooks.
+ * toplev.c (incomplete_decl_finalize_hook): Remove.
+ (wrapup_global_declarations): Update.
+ * tree.c (lang_unsafe_for_reeval): Remove.
+ (unsafe_for_reeval): Update.
+ * tree.h (lang_unsafe_for_reeval, incomplete_decl_finalize_hook):
+ Remove.
+objc:
+ * objc-lang.c (LANG_HOOKS_FINISH_INCOMPLETE_DECL,
+ LANG_HOOKS_UNSAFE_FOR_REEVAL): Redefine.
+
+2002-03-31 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * diagnostic.c (print_error_function): Remove.
+ (default_print_error_function): Rename.
+ (report_error_function): Update.
+ * diagnostic.h (print_error_function): Remove.
+ (default_print_error_function): Remove.
+ * langhooks-def.h (struct diagnostic_context): Predeclare.
+ (lhd_print_error_function, LANG_HOOKS_PRINT_ERROR_FUNCTION): New.
+ (LANG_HOOKS_INITIALIZER): Update.
+ * langhooks.h (struct diagnostic context): Predeclare.
+ (struct lang_hooks): New hook.
+
+2002-03-31 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ * config/rs6000/rs6000.h (RS6000_PIC_OFFSET_TABLE_REGNUM): New.
+ (PIC_OFFSET_TABLE_REGNUM): Use it and return INVALID_REGNUM if
+ !flag_pic.
+ (CONDITIONAL_REGISTER_USAGE): Adjust accordingly.
+ * config/rs6000/rs6000.h: Use RS6000_PIC_OFFSET_TABLE_REGNUM instead
+ of PIC_OFFSET_TABLE_REGNUM thruout.
+ * config/rs6000/rs6000.md: Likewise.
+ * config/rs6000/darwin.h: Likewise.
+
+Sun Mar 31 14:43:24 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * emit-rtl.c (adjust_address_1, offset_address): Cast value to
+ unsigned HOST_WIDE_INT, not unsigned int.
+
+2002-03-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/6096, middle-end/6098, middle-end/6099
+ * reorg.c (emit_delay_sequence): Only increment LABEL_NUSES for
+ CODE_LABELs.
+ (fill_slots_from_thread): Likewise.
+
+2002-03-31 Jakub Jelinek <jakub@redhat.com>
+
+ * config/sparc/sparc.c (function_arg_record_value_1): Pass complex
+ floating fields in float regs.
+ (function_arg_record_value_2): Likewise.
+
+2002-03-31 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.md (define_constants): Remove misleading
+ FIXME. Add MMIX_fp_rO_OFFSET.
+ ("nonlocal_goto_receiver"): Don't have stack-frame address of
+ saved rO as part of the pattern. Remove FIXME.
+ ("*nonlocal_goto_receiver_expanded"): Similar. Generate address
+ here, at output-time.
+
+2002-03-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/6100
+ * config/sparc/sparc.c (output_cbranch): Use REG_BR_PROB, not
+ REG_BR_PRED.
+ (output_v9branch): Likewise.
+
+2002-03-31 Alexandre Oliva <aoliva@redhat.com>
+
+ * gcc.c: Revert previous patch for now.
+ * config/i386/djgpp.h: Likewise.
+
+2002-03-31 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/crti.asm (_init): Register _fini with atexit.
+ * config/mmix/crtn.asm (_fini): Add omitted "POP 0,0".
+
+2002-03-31 Richard Henderson <rth@redhat.com>
+
+ PR target/3997
+ * config/alpha/elf.h (ASM_OUTPUT_DEF): Tidy.
+ (ASM_OUTPUT_DEF_FROM_DECLS): New.
+
+2002-03-31 Richard Henderson <rth@redhat.com>
+
+ * libgcc2.c (__bb_exit_func): Make static.
+
+ * config/alpha/alpha.md (trap): New.
+
+2002-03-31 Richard Henderson <rth@redhat.com>
+
+ * builtins.c (expand_builtin_va_arg): Give warnings not errors for
+ promoted argument types; build trap.
+ (expand_builtin_trap): New.
+ (expand_builtin): Use it.
+ * stmt.c (expand_nl_goto_receivers): Likewise.
+ * expr.h (expand_builtin_trap): Declare.
+ * libfuncs.h (LTI_abort, abort_libfunc): New.
+ * optabs.c (init_optabs): Init abort_libfunc.
+
+2002-03-31 Alexandre Oliva <aoliva@redhat.com>
+
+ * gcc.c (LIBGCC_SPEC): Folded %L and duplicate %G here...
+ (LINK_COMMAND_SPEC): ... from here.
+ (init_gcc_specs): Duplicate it here too, omitting
+ shared_name in the second copy.
+ (init_spec): Test for duplicate
+ * config/i386/djgpp.h (LINK_COMMAND_SPEC): Remove `%L %G'.
+
+2002-03-30 David S. Miller <davem@redhat.com>
+
+ * config/sparc/linux.h (HANDLE_PRAGMA_PACK_PUSH_POP): Define.
+ * config/sparc/linux64.h (HANDLE_PRAGMA_PACK_PUSH_POP): Likewise.
+
+2002-03-30 Roger Sayle <roger@eyesopen.com>
+ Richard Henderson <rth@redhat.com>
+
+ * regmove.c (combine_stack_adjustments_for_block): Avoid
+ emitting a stack adjustment of zero bytes. Let delete_insn
+ update bb->head.
+
+2002-03-30 Richard Henderson <rth@redhat.com>
+
+ * config/sparc/sparc.c: Remove all references to TARGET_EPILOGUE.
+ (sparc_emitting_epilogue): New.
+ (leaf_label, output_return, sparc_return_peephole_ok): Remove.
+ * config/sparc/sparc-protos.h: Update.
+ * config/sparc/sparc.h (MASK_EPILOGUE, TARGET_EPILOGUE): Remove.
+ (TARGET_SWITCHES): Update.
+ * config/sparc/sparc.md (return): Remove.
+ (return_*): Use sparc_emitting_epilogue, not !TARGET_EPILOGUE.
+ * config/sparc/freebsd.h, config/sparc/linux64.h, config/sparc/lite.h,
+ config/sparc/liteelf.h, config/sparc/netbsd-elf.h,
+ config/sparc/sol2-sld-64.h, config/sparc/sol2.h,
+ config/sparc/sp64-aout.h, config/sparc/sp64-elf.h,
+ config/sparc/sp86x-aout.h, config/sparc/sp86x-elf.h,
+ config/sparc/splet.h, config/sparc/vxsparc64.h (TARGET_DEFAULT):
+ Remove MASK_EPILOGUE.
+ * doc/invoke.texi: Update.
+
+2002-03-30 Daniel Berlin <dan@dberlin.org>
+
+ * dwarf2out.c (dwarf2out_define): Remove start_source_file call,
+ CPP will start the file for us.
+
+2002-03-30 Richard Henderson <rth@redhat.com>
+
+ PR target/5446
+ * config/ia64/ia64.c (group_barrier_needed_p): Special case
+ prologue_allocate_stack.
+ (ia64_single_set): Use insn codes for recognition of special
+ cases, not rtl matching.
+ * config/ia64/ia64.md (prologue_allocate_stack): Op 3 is in-out.
+
+Sat Mar 30 23:48:41 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgbuild.c (find_basic_blocks_1): Clear aux for blocks.
+
+2002-03-30 Richard Henderson <rth@redhat.com>
+
+ PR target/6032
+ * config/sparc/sparc.h (OVERRIDE_OPTIONS): Don't override -fpic
+ or -fomit-frame-pointer with profiling.
+ (SUBTARGET_OVERRIDE_OPTIONS): Remove.
+ (FUNCTION_PROFILER): Do nothing.
+ (PROFILE_HOOK): New.
+ * config/sparc/sparc.c (sparc_override_options): Don't check
+ code models for profiling.
+ (sparc_function_profiler): Remove.
+ (sparc_profile_hook): New.
+ * config/sparc/sparc-protos.h: Update.
+
+2002-03-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR optimization/6086
+ * combine.c (combine_simplify_rtx): If simplify_rtx failed because
+ of SUBREG of volatile MEM or because the MEM was mode dependent,
+ return CLOBBER instead of unmodified SUBREG.
+
+Sat Mar 30 14:08:55 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * local-alloc.c (local_alloc): Avoid call of update_equiv_regs
+ when not optimizing.
+
+ * toplev.c (rest_of_compilation): Cann mark_constant_function
+ only when optimizing.
+
+ * flow.c (calculate_global_regs_live): Ensure that all AUX fields
+ are NULL.
+
+ * cfgcleanup.c (bb_flags): Add BB_NONTHREADABLE_BLOCK.
+ (thread_jump): Set BB_NONTHREADABLE_BLOCK, check it.
+ (try_optimize_cfg): clear all AUX fields.
+
+ * i386.c (aligned_operand): Be prepared for SUBREGed registers.
+ (ix86_decompose_address): Use REG_P instead of GET_CODE (...) == REG.
+ (ix86_address_cost): Be prepared for SUBREGed registers.
+ (legitimate_address_p): Accept SUBREGed registers.
+
+2002-03-29 Richard Henderson <rth@redhat.com>
+
+ PR target/5672
+ * expr.c (expand_expr): Pass along EXPAND_INITIALIZER one more place.
+
+2002-03-29 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ * config/rs6000/rs6000.c (rs6000_va_arg): Correctly set register count
+ for aggregate and TFmode types.
+
+2002-03-29 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * cfg.c (dump_flow_info): Guard against NULL regno_reg_rtx[i].
+
+2002-03-29 Richard Henderson <rth@redhat.com>
+
+ PR target/5886
+ * config/ia64/aix.h (CPP_PREDEFINES): Add -D_LP64.
+ * config/ia64/hpux.h, config/ia64/linux.h: Likewise.
+
+2002-03-29 Richard Henderson <rth@redhat.com>
+
+ PR target/6041
+ * config/i386/i386.c (x86_arch_always_fancy_math_387): New.
+ (override_options): Disable NO_FANCY_MATH_387 if the arch allows.
+ * config/i386/i386.h (x86_arch_always_fancy_math_387): New.
+ * config/i386/i386.md (sqrtxf2, sqrtextendsfxf2, sinxf2): Fix
+ conditional.
+ * docs/invoke.texi: Update -mno-fancy-math-387 docs.
+
+2002-03-29 Dale Johannesen <dalej@apple.com>
+
+ * loop.c (combine_movables): Do allow combination of pseudos.
+
+2002-03-29 Loren J. Rittle <ljrittle@acm.org>
+
+ * config.gcc (*-*-freebsd*): Enable creation of libgcc_s.so.
+ * config/t-slibgcc-elf-ver (SHLIB_LC): Add macro and use it.
+ No functional change except ...
+ * config/t-slibgcc-nolc-override (SHLIB_LC): Override it. New file.
+ * doc/install.texi (*-*-freebsd*): Document port configuration.
+
+2002-03-29 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in (convert.o, calls.o, expmed.o): Update.
+ * attribs.c (handle_mode_attribute, handle_vector_size_attribute):
+ Use new hooks.
+ * builtin-types.def (BT_PTRMODE): Update.
+ * c-common.c (type_for_size): Rename c_common_type_for_size.
+ (type_for_mode): Similarly.
+ (shorten_compare, pointer_int_sum, c_common_nodes_and_builtins):
+ Use new hook.
+ * c-bommon.h (c_common_type_for_size, c_common_type_for_mode): New.
+ * c-decl.c (finish_enum, build_enumerator): Use new hooks.
+ * c-lang.c (LANG_HOOKS_TYPE_FOR_MODE, LANG_HOOKS_TYPE_FOR_SIZE):
+ Redefine.
+ * c-typeck.c (common_type, comptypes, default_conversion):
+ Use new hooks.
+ * calls.c: Include langhooks.h.
+ (emit_library_call_value_1): Use new hooks. Avoid redundant
+ calls.
+ * convert.c: Include langhooks.h
+ (convert_to_pointer, convert_to_integer): Use new hooks.
+ * except.c (init_eh): Similarly.
+ * expmed.c: Include langhooks.h.
+ (expand_mult_add): Use new hooks.
+ * expr.c (store_expr, store_constructor, expand_expr, do_jump,
+ try_casesi): Similarly.
+ * fold-const.c (optimize_bit_field_compare, make_range,
+ decode_field_reference, fold_truthop, fold): Similarly.
+ * function.c (assign_stack_local_1, assign_stack_temp_for_type,
+ put_var_into_stack): Similarly.
+ * langhooks-def.h (LANG_HOOKS_TYPE_FOR_MODE,
+ LANG_HOOKS_TYPE_FOR_SIZE): New.
+ (LANG_HOOKS_TYPES_INITIALIZER): Update.
+ * langhooks.h (lang_hooks_for_types): New hooks.
+ * stmt.c (expand_decl_cleanup, emit_case_nodes): Use new hooks.
+ * tree.c (get_unwidened, get_narrower): Similarly.
+ * tree.h (type_for_mode, type_for_size): Remove.
+ * varasm.c (force_const_mem): Use new hooks.
+ * utils2.c (nonbinary_modular_operation): Update.
+objc:
+ * objc-act.c (handle_impent): Update.
+ * objc-lang.c (LANG_HOOKS_TYPE_FOR_MODE, LANG_HOOKS_TYPE_FOR_SIaZE):
+ Redefine.
+
+2002-03-29 Steve Ellcey <sje@cup.hp.com>
+
+ * config/ia64/ia64.md (*ptr_extend_plus_1, *ptr_extend_plus_2): New.
+ * config/ia64/ia64.c (basereg_operand): New.
+ * config/ia64/ia64-protos.h (basereg_operand): Declare.
+ * config/ia64/ia64.h (PREDICATE_CODES): Add basereg_operand.
+
+2002-03-29 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.c (mmix_target_asm_function_prologue): Correct
+ unwind information when frame_pointer_needed.
+ (mmix_assemble_integer): Tweak wording in comment.
+
+2002-03-29 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in (except.o): Update.
+ * except.c: Include langhooks.h.
+ (init_eh): Use langhook.
+ * langhooks-def.h (LANG_HOOKS_MAKE_TYPE,
+ LANG_HOOKS_FOR_TYPES_INITIALIZER): New.
+ (LANG_HOOKS_INITIALIZER): Update.
+ * langhooks.h (lang_hooks_for_types): New.
+ (struct lang_hooks): Add it.
+ * tree.c (make_lang_type_fn, make_lang_type): Remove.
+ * tree.h (make_lang_type_fn, make_lang_type): Remove.
+config:
+ * alpha/alpha.c: Include langhooks.h.
+ (alpha_build_va_list): Use langhook.
+ * d30v/d30v.c: Include langhooks.h.
+ (d30v_build_va_list): Use langhook.
+ * i386/i386.c: Include langhooks.h.
+ (ix86_build_va_list): Use langhook.
+ * rs6000/rs6000.c (rs6000_build_va_list): Use langhook.
+ * s390/s390.c: Include langhooks.h.
+ (s390_build_va_list): Use langhook.
+ * stormy16/stormy16.c: Include langhooks.h.
+ (stormy16_build_va_list): Use langhook.
+
+2002-03-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/5964
+ * config/sparc/sparc.md (empty_delay_slot, branch_type): New
+ attributes.
+ (length): Compute variable length for branches/calls/jumps here.
+ (branch, inverted_branch, normal_fp_branch, inverted_fp_branch,
+ normal_fpe_branch, inverted_fpe_branch): Remove length attribute,
+ define branch_type attribute.
+ (divsi3_sp32): Maximum length is 6 not 7.
+ (call_address_struct_value_sp32, call_symbolic_struct_value_sp32,
+ call_address_untyped_struct_value_sp32,
+ call_symbolic_untyped_struct_value_sp32): Set length to 3 not 2.
+ * config/sparc/sparc.c (empty_delay_slot): New function.
+ * config/sparc/sparc.h (ADJUST_INSN_LENGTH): Remove.
+ * config/sparc/sparc-protos.h (empty_delay_slot): Add prototype.
+
+2002-03-29 Jakub Jelinek <jakub@redhat.com>
+
+ * combine.c (set_nonzero_bits_and_sign_copies): Don't call
+ nonzero_bits if not needed.
+ (nonzero_bits) [XOR]: Likewise.
+ (nonzero_bits) [REG]: Use reg_last_set_nonzero_bits even if
+ reg_last_set_mode and mode are both MODE_INT, but not equal.
+ (record_value_for_reg): Compute reg_last_set_nonzero_bits
+ in nonzero_bits_mode for MODE_INT modes.
+
+2002-03-28 Richard Henderson <rth@redhat.com>
+
+ PR target/5715
+ * config/alpha/osf.h (ASM_SPEC): Don't pass any special options
+ to GAS. Correct drift between alternatives.
+
+2002-03-28 Richard Henderson <rth@redhat.com>
+
+ PR target/6087
+ * reload1.c (fixup_abnormal_edges): Move insn to edge via sequence.
+
+2002-03-28 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/i386/freebsd.h (LINK_SPEC): Don't pass default
+ emulation to the linker.
+
+2002-03-28 Loren J. Rittle <ljrittle@acm.org>
+
+ * config/alpha/freebsd.h (LINK_SPEC): Likewise.
+ * config/sparc/freebsd.h (LINK_SPEC): Likewise.
+
+Thu Mar 28 16:35:31 2002 Jeffrey A Law (law@redhat.com)
+
+ * combine.c (simplify_and_const_int): Make sure to apply mask
+ when force_to_mode returns a constant integer. PR3311.
+
+2002-03-28 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa-linux.h (LOCAL_LABEL_PREFIX): Define.
+
+2002-03-28 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/invoke.texi (Warning Options): Refer to C++ Dialect Options
+ and Objective-C Dialect Options.
+
+2002-03-28 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (alpha_emit_conditional_branch): TFmode NE
+ comparison should be done vs !=0 not >0 return code. Tidy cases.
+
+2002-03-28 Richard Henderson <rth@redhat.com>
+
+ * c-decl.c (finish_function): New arg can_defer_p. Pass it
+ on to c_expand_body.
+ * c-tree.h (finish_function): Update decl.
+ * c-objc-common.c, c-parse.in, objc/objc-act.c: Update calls.
+
+Thu Mar 28 19:13:36 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * ifcvt.c (if_convert): Clear aux_for_blocks early enought.
+
+Thu Mar 28 13:21:53 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * rtlanal.c: Include flags.h
+ (may_trap_p): Do not mark FP operations if trapping
+ if !flag_trapping_math
+ * Makefile.in (rtlanal.o): Add dependency on flag.h
+ * ifcvt.c (noce_operand_ok): Avoid the lameness.
+
+2002-03-27 Zack Weinberg <zack@codesourcery.com>
+
+ * mips.md: Use dconst1, not 1.0, as first argument of
+ REAL_VALUE_LDEXP. Don't use union real_extract.
+
+2002-03-28 Alan Modra <amodra@bigpond.net.au>
+
+ * configure.in (gcc_cv_as): Use $target_alias in directory searchs
+ rather than $target. Heed program_prefix and
+ program_transform_name. Search for gas in cross-compiler case too.
+ "test -x" rather than "test -f".
+ (gcc_cv_ld): Likewise.
+ (gcc_cv_nm): Heed program_prefix and program_transform_name.
+ (gcc_cv_objdump): Likewise.
+ * configure: Regenerate.
+
+2002-03-27 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in (attribs.o): Update.
+ * attribs.c: Include langhooks.h.
+ (decl_attributes): Use langhook.
+ * c-decl.c (insert_default_attributes): Rename.
+ * c-tree.h (c_insert_default_attributes): New.
+ * langhooks-def.h (LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES):New.
+ (LANG_HOOKS_INITIALIZER): Update.
+ * langhooks.h (struct lang_hooks): New hook.
+ * tree.h (insert_default_attributes): Remove.
+objc:
+ * objc-lang.c (LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES): Redefine.
+
+2002-03-27 Andreas Schwab <schwab@suse.de>
+
+ * config/i386/i386.c (classify_argument): Also check for
+ QUAL_UNION_TYPE.
+
+2002-03-27 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * doc/install.texi (alpha*-dec-osf*): Don't need --enable-libgcj
+ any more.
+
+Wed Mar 27 23:19:30 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * i960.md (ret): Set PC.
+ (nonlocal_goto): Fix expander.
+ * builtins.c (epxand_builin_longjmp): Check that we've emitted
+ some jump or call.
+
+Wed Mar 27 23:11:35 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * optabs.c (emit_no_conflict_block, emit_libcall_block): Avoid nesting
+ of libcall regions.
+
+Wed Mar 27 22:54:14 CET 2002 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * cfgrtl.c (merge_blocks_nomove): Use set_block_for_insn instead of
+ assigning to BLOCK_FOR_INSN directly.
+
+Wed Mar 27 22:33:05 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (ix86_output_addr_diff_elt): Remove binutils bug workaround.
+
+2002-03-27 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (c_expand_expr): Fix prototype.
+ * c-common.h (c_expand_expr): Always declare, update.
+ * c-lang.c (LANG_HOOKS_EXPAND_EXPR): Redefine.
+ * c-objc-common.c (c_objc_common_init): No global hook.
+ * expr.c (expand_expr): Use langhook.
+ * expr.h (enum expand_modifier): Conditionally declare.
+ * langhooks-def.h (lhd_expand_expr, LANG_HOOKS_EXPAND_EXPR): New.
+ (LANG_HOOKS_INITIALIZER): Update.
+ * langhooks.c (lhd_expand_expr): New.
+ * langhooks.h (struct lang_hooks): New hook.
+ * toplev.c (lang_expand_expr_t, lang_expand_expr): Delete.
+ (lang_independent_init): Don't default hook.
+objc:
+ * objc-lang.c (LANG_HOOKS_EXPAND_EXPR): Redefine.
+
+2002-03-27 Richard Henderson <rth@redhat.com>
+
+ PR target/6054
+ * config/ia64/ia64.c (ia64_expand_call): Use pic patterns for
+ TARGET_CONST_GP. Simplify conditions.
+
+2002-03-27 Richard Henderson <rth@redhat.com>
+
+ * config/sparc/freebsd.h, config/sparc/linux.h, config/sparc/linux64.h,
+ config/sparc/netbsd-elf.h, config/sparc/pbd.h, config/sparc/sol2.h,
+ config/sparc/vxsim.h (LOCAL_LABEL_PREFIX): Define.
+
+2002-03-27 Danny Smith <dannysmith@users.sourceforge.net>
+
+ * config/i386/cygwin.h (TARGET_DLL, TARGET_WIN32,
+ TARGET_CYGWIN, TARGET_WINDOWS): Remove unused switches.
+ (MASK_DLL, MASK_WIN32, MASK_CYGWIN, MASK_WINDOWS):
+ Remove unnecessary masks.
+ (MASK_NOP_FUN_DLLIMPORT): Use an unused an bit.
+ (SUBTARGET_SWITCHES): Use empty masks for -mwin32, -mcygwin,
+ -mwindows, -mdll switches and their negations.
+
+2002-03-27 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * gcc-common.c (lang_mark_false_label_stack): Remove.
+ * ggc.h (lang_mark_false_label_stack): Similarly.
+
+2002-03-26 Vladimir Makarov <vmakarov@redhat.com>
+
+ * pa/pa-pro-end.h (CPP_PREDEFINES): Add -D__pro__.
+
+ * pa/lib2funcs.asm: Don't use .SPACE and .SUBSPACE if __pro__
+ or __rtems_ is defined.
+
+2002-03-26 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (alpha_emit_set_const): Add a REG_EQUAL note
+ if a non-trivial load was emitted.
+ (alpha_emit_set_const_1): Remove obsolete extension. Fix thinko
+ in high+extra+low case.
+
+2002-03-26 Richard Henderson <rth@redhat.com>
+
+ * config.gcc (sparc*-solaris): Use float_format=sparc.
+
+2002-03-26 Richard Henderson <rth@redhat.com>
+
+ * config/sparc/sparc.h (MAX_WCHAR_TYPE_SIZE): Don't define.
+ * config/sparc/linux-aout.h (MAX_WCHAR_TYPE_SIZE): Don't undef.
+ * config/sparc/linux.h, config/sparc/linux64.h: Likewise.
+ * config/sparc/sol2.h (WCHAR_TYPE, WCHAR_TYPE_SIZE): Redefine.
+ (WINT_TYPE_SIZE): Fix at 32.
+
+2002-03-26 Richard Henderson <rth@redhat.com>
+
+ * toplev.c (rest_of_compilation): Delay emit_initial_value_sets
+ until after eh landing pad generation.
+ * config/alpha/alpha.c (alpha_gp_save_rtx): Use gen_mem_addressof.
+ * config/alpha/alpha.md (exception_receiver_2): Only accept MEMs.
+
+2002-03-26 Richard Henderson <rth@redhat.com>
+
+ * expr.h (ADD_PARM_SIZE): One more convert for INC.
+
+2002-03-26 Phil Edwards <pme@gcc.gnu.org>
+
+ * gcc.c (cpp_options): Preserve relative ordering of -pedantic
+ and warning switches.
+ (cc1_options): Likewise.
+
+2002-03-26 Hans Boehm <Hans_Boehm@hp.com>
+
+ * config/ia64/linux.h (MD_FALLBACK_FRAME_STATE_FOR):
+ Restore more of the signal context. Set no_reg_stack_frame.
+ * config/ia64/unwind-ia64.c (unw_state_record):
+ Add no_reg_stack_frame, comments.
+ (uw_frame_state_for): Initialize when field to UNW_WHEN_NEVER.
+ (uw_update_context): Adjust bsp when unwinding from leaf,
+ but not signal frame.
+
+2002-03-26 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/aix51.h (WCHAR_TYPE): Define.
+
+2002-03-26 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.c (xtensa_va_arg): Handle variable-sized types.
+
+2002-03-26 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/5621
+ * arm.md (define_asm_attributes): Reapply patch of Thu Sep 9, 1999:
+ "Add a pool_range attribute", which was lost during the ARM/Thumb
+ merge.
+
+2002-03-26 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.c (xtensa_valid_move): Allow move from
+ a register into the MAC16 accumulator.
+
+2002-03-26 Andrew Cagney <ac131313@redhat.com>
+
+ * doc/invoke.texi (Option Summary): Mention -Wswitch-enum.
+ (Warning Options): Document -Wswitch-enum.
+ * toplev.c (W_options): Add -Wswitch-enum. Update comment on
+ -Wswitch.
+ (warn_switch_enum): Define variables.
+ * flags.h (warn_switch_enum): Declare variables.
+ * stmt.c (expand_end_case_type): When warn_switch_enum /
+ -Wswitch-enum, perform switch checks.
+ Fix PR c/5044.
+
+2002-03-26 Richard Earnshaw <rearnsha@arm.com>
+
+ * arm.md (reload_mulsi3, reload_mulsi_compare0, reload_muladdsi)
+ (reload_mulsi_compare0_scratch, reload_muladdsi_compare0)
+ (reload_muladdsi_compare0_scratch): Delete.
+
+2002-03-26 Loren J. Rittle <ljrittle@acm.org>
+
+ * doc/install.texi (*-*-freebsd*): Update.
+
+2002-03-26 Richard Henderson <rth@redhat.com>
+
+ * expr.h (ADD_PARM_SIZE): Cast INC to ssizetype.
+ (SUB_PARM_SIZE): Cast DEC to ssizetype.
+
+ * config/alpha/alpha.c (alpha_va_arg): Read MUST_PASS_IN_STACK
+ types from the normal argument frame.
+
+ * config/sparc/sparc.c (function_arg_pass_by_reference): Pass
+ variable sized objects by reference.
+ (sparc_va_arg): Receive them by reference too.
+
+2002-03-26 Hartmut Penner <hpenner@de.ibm.com>
+
+ * config/s390/s390.c (s390_emit_epilogue): Change epilogue
+ code to not restoring global registers.
+
+2002-03-26 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in (ggc-common.o): Update.
+ * c-decl.c (lang_mark_tree): Rename c_mark_tree.
+ * c-lang.c (LANG_HOOKS_MARK_TREE): Redefine.
+ * c-tree.h (c_mark_tree): New.
+ * ggc-common.c: Include langhooks.h.
+ (gcc_mark_trees): Use new langhook.
+ * ggc-callbacks.c: Delete file.
+ * ggc.h (lang_mark_tree): Remove.
+ * langhooks-def.h (LANG_HOOKS_MARK_TREE): New.
+ (LANG_HOOKS_INITIALIZER): Update.
+ * langhooks.h (struct lang_hooks): New hook.
+objc:
+ * objc-lang.c (LANG_HOOKS_MARK_TREE): Redefine.
+
+2002-03-25 Zack Weinberg <zack@codesourcery.com>
+
+ * doc/cpp.texi: Exclude entire Top node from printed manual.
+ Move option index after directive index. Insert page breaks
+ before GFDL and concept index. Index environment variables
+ with command line options.
+ * doc/cppenv.texi: Use @vtable for environment variable list.
+ Add paragraph explaining semantics of empty elements in path
+ variables. Exclude a cross-reference to Fishkill from the
+ manpage. Remove an unnecessary cross-reference of the entry
+ right above the referer. Don't use @anchor in text that goes
+ into manpage.
+ * doc/cppopts.texi: Cross-reference the environment variables
+ section, not the specific environment variable, for consistency.
+
+2002-03-25 Richard Henderson <rth@redhat.com>
+
+ * recog.c (peephole2_optimize): Distribute EH_REGION -1 notes
+ anywhere in the block. Don't refer to insns that have been
+ removed from the chain. Iterate backward through the new insns.
+ Don't refer to edges that have been removed.
+
+2002-03-26 Alan Modra <amodra@bigpond.net.au>
+
+ * combine.c (simplify_comparison <ASHIFTRT, LSHIFTRT>): Correct
+ test for overflow of constant.
+
+2002-03-25 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/2623
+ * arm.md (loadhi_preinc, loadhi_predec, loadhi_shiftpreinc)
+ (loadhi_shiftpredec, loadhi-with-writeback peephole): Don't use
+ these patterns on arm_archv4.
+
+2002-03-25 Danny Smith <dannysmith@sourceforge.users.net>
+
+ * config/i386/mingw32.h (WINT_TYPE): Define as "short unsigned
+ int".
+
+2002-03-25 Zack Weinberg <zack@codesourcery.com>
+
+ * toplev.c: Don't include setjmp.h. Kill float_handler_set,
+ float_handled, float_handler, float_signal, set_float_handler,
+ and do_float_handler. Set handler for SIGFPE to crash_signal.
+ * toplev.h: Don't prototype do_float_handler.
+
+ * c-lex.c: Fold parse_float into lex_number. Make warning
+ about portability of hex float constants more informative, and
+ don't issue it on top of a syntax error.
+ * fold-const.c: Fold const_binop_1 and fold_convert_1 into
+ their callers.
+ * real.h: Define REAL_VALUE_ABS here...
+ * simplify-rtx.c: ... not here. Fold check_fold_consts,
+ simplify_unary_real, simplify_binary_real, and
+ simplify_binary_is2orm1 into their callers.
+ * tree.c: Fold build_real_from_int_cst_1 into caller.
+
+ * doc/tm.texi: Document REAL_VALUE_ABS and REAL_VALUE_NEGATIVE.
+
+ * tsystem.h: Include float.h here...
+ * libgcc2.c: ... not here.
+
+2002-03-25 Nick Clifton <nickc@cambridge.redhat.com>
+
+ Fixes for: PR bootstrap/3591, target/5676
+ * config/mcore/mcore.h (CC1_SPEC): Define only if not already
+ defined. Do not disable exceptions or rtti.
+ * config/mcore/mcore-pe.h (CC1_SPEC): Define before including
+ mcore.h. Disable exceptions and rtti, since they are not
+ supported by EPOC.
+
+2002-03-25 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-decl.c (maybe_build_cleanup): Remove.
+ * expr.c (expand_expr): Use langhook.
+ * langhooks-def.h (lhd_return_null_tree,
+ LANG_HOOKS_MAYBE_BUILD_CLEANUP): New.
+ (LANGHOOKS_INITIALIZER): Update.
+ * langhooks.c (lhd_return_null_tree): New.
+ * langhooks.h (struct lang_hooks): New hook.
+ * tree-inline.c (initialize_inlined_parameters): Use langhook.
+ * tree.h (maybe_build_cleanup): Remove.
+
+2002-03-25 Jakub Jelinek <jakub@redhat.com>
+
+ * regrename.c (build_def_use): Move recog_memoized
+ before extract_insn.
+
+2002-03-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/6043
+ * expr.c (emit_group_store): Handle storing into CONCAT.
+
+2002-03-25 Jakub Jelinek <jakub@redhat.com>
+
+ * regrename.c (build_def_use): Share RTL between MATCH_OPERATOR and
+ corresponding MATCH_DUP.
+
+2002-03-24 Richard Henderson <rth@redhat.com>
+
+ * unroll.c (unroll_loop): Zero label_map.
+
+ * gcse.c: Include except.h.
+ * Makefile.in (gcse.o): Update.
+
+2002-03-24 Richard Henderson <rth@redhat.com>
+
+ * varasm.c (asm_emit_uninitialised): Revert 2002-03-14 change.
+ Do resolve_unique_section before shared data clause.
+
+2002-03-24 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/elf.h (STARTFILE_SPEC): Use crtbeginT with -static.
+
+2002-03-24 Richard Henderson <rth@redhat.com>
+
+ * recog.c (peephole2_optimize): Split blocks when EH insns are
+ generated in the middle of a block. Do global life update if
+ zapped EH edges.
+
+2002-03-24 Richard Henderson <rth@redhat.com>
+
+ * mips.c (mips_function_value): Only promote_mode for non-libcalls.
+
+2002-03-24 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ preprocessor/3951
+ * gcc.c (cpp_options): Pass -MD through as -MD not -M -MF.
+ * cppinit.c (cpp_handle_option): Set no_ouput if -MD or -MMD.
+ (init_dependency_output): Don't make no_output decision here.
+
+2002-03-24 Andrew Cagney <ac131313@redhat.com>
+
+ * stmt.c (check_for_full_enumeration_handling): Remove tests of
+ warn_switch. Update description.
+ (expand_end_case_type): Call check_for_full_enumeration_handling
+ when warn_switch.
+
+2002-03-24 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/m68hc11.c (m68hc11_autoinc_compatible_p): New function.
+ (m68hc11_split_move): Call it to see if the source and destination
+ operands use the same direction auto inc/dec mode, otherwise make the
+ source an offsetable memory operand and generate an add.
+
+2002-03-24 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/m68hc11.md ("*subsi3_zero_extendhi"): Allow address
+ register for operand 2.
+ ("*subsi3_zero_extendqi"): Likewise.
+ ("*iorhi3_gen"): Do the operation on the upper bits and then lower
+ bits so that it is compatible with a pop.
+ ("*andhi3_gen"): Likewise.
+ ("xorhi3"): Likewise.
+
+2002-03-24 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppinit.c (cpp_handle_option): Set warn_endif_labels if
+ -pedantic here...
+ (cpp_post_options): ... not here.
+
+2002-03-24 Neil Booth <neil@daikokuya.demon.co.uk>
+ Aldy Hernandez <aldyh@redhat.com>
+
+ Removal of separate preprocessor cpp0.
+
+ * Makefile.in (GCC_PASSES, STAGESTUFF, LIBCPP_OBJS,
+ cpp0, install-common): Update.
+ * c-common.c (flag_preprocess_only): New.
+ (c_common_init): Preprocess for -E.
+ * c-common.h (flag_preprocess_only): New.
+ * c-decl.c (c_decode_option): Handle -E and -std=c++98.
+ * c-objc-common.c (c_init_decl_processing): Exit quickly
+ for NULL return from c_common_init.
+ * cpplib.h (cpp_preprocess_file): New.
+ * cppmain.c (main, general_init, pfile, progname): Remove.
+ (do_preprocessing): Rename cpp_preprocess_file, don't call
+ cpp_finish. Don't close stdout here.
+ (setup_callbacks): Update prototype.
+ * gcc.c (trad_capable_cpp, cpp_unique_options, default_compilers):
+ Update.
+ * tradcpp.c (main): Ignore -quiet.
+objc:
+ * lang-specs.h (default_compilers): Preprocess with cc1obj.
+
+2002-03-24 Richard Henderson <rth@redhat.com>
+
+ PR optimization/5742
+ * machmode.def: Add inner mode field to complex modes.
+ * config/mips/mips.c (mips_function_value): Always define. Add
+ new argument to handle libcalls.
+ * config/mips/mips.h (LIBCALL_VALUE): Use mips_function_value.
+ (FUNCTION_VALUE): Likewise.
+ * config/mips/abi64.h (FUNCTION_VALUE): Remove.
+ * config/mips/mips-protos.h: Update.
+
+2002-03-23 Richard Henderson <rth@redhat.com>
+
+ * config/sparc/sparc.c (sparc_emit_floatunsdi): New.
+ * config/sparc/sparc-protos.h: Update.
+ * config/sparc/sparc.md (floatunsdisf2, floatunsdidf2): New.
+
+2002-03-23 Richard Henderson <rth@redhat.com>
+
+ * config/sparc/gmon-sol2.c (internal_mcount): Assume either
+ _start or _init begins the text segment.
+
+2002-03-23 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.h (RETURN_IN_MEMORY): Cast to HOST_WIDE_INT
+ not HOST_WIDEST_INT.
+ (RS6000_ARG_SIZE): Remove unsigned cast of int_size_in_bytes.
+
+2002-03-23 Richard Earnshaw <rearnsha@arm.com>
+
+ PR java/5489
+ * arm.md (return, sibcall_epilogue): Pass const_true_rtx as the
+ operand argument to output_return_instruction.
+ * arm.c (arm_print_operand, case 'd'): If the operand is
+ const_true_rtx then just return.
+ (arm_print_operand, case 'D'): If the operand is const_true_rtx
+ then abort.
+
+2002-03-23 Andrew Cagney <ac131313@redhat.com>
+
+ * doc/invoke.texi (Option Summary): Mention -Wswitch-default.
+ (Warning Options): Document -Wswitch-default.
+ * toplev.c (W_options): Add -Wswitch-default. Update comment on
+ -Wswitch.
+ (warn_switch_default): Define variable.
+ (warn_switch): Update comment.
+ * flags.h (warn_switch_default): Declare variable.
+ (warn_switch): Update comment.
+ * stmt.c (expand_end_case): Check for and, when
+ warn_switch_no_default, warn of a missing default case.
+
+2002-03-23 Alan Modra <amodra@bigpond.net.au>
+
+ * real.h (N): Special case 128 bit doubles.
+
+ * combine.c (simplify_comparison): When widening modes, ignore
+ sign extension on CONST_INTs.
+
+2002-03-22 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.c (print_operand): Fix incorrect mode
+ passed to adjust_address. Fix comment formatting.
+
+
+2002-03-22 Zack Weinberg <zack@codesourcery.com>
+
+ * real.h: Don't define REAL_INFINITY or REAL_IS_NOT_DOUBLE.
+ Always make REAL_VALUE_TYPE a struct containing an array of
+ HOST_WIDE_INT, not a double. Tidy up the code deciding how
+ big it is. Don't declare or use union real_extract.
+
+ * emit-rtl.c (init_emit_once), varasm.c (immed_real_const_1,
+ decode_rtx_const, output_constant_pool), config/a29k/a29k.c
+ (print_operand), config/arm/arm.c (output_move_double),
+ config/arm/arm.md (consttable_4, consttable_8),
+ config/romp/romp.c (output_fpops), config/s390/s390.h
+ (ASM_OUTPUT_SPECIAL_POOL_ENTRY), config/xtensa/xtensa.c
+ (xtensa_output_literal): Don't use union real_extract.
+
+ * config/dsp16xx/dsp16xx.c (print_operand), config/i860/i860.c
+ (sfmode_constant_to_ulong), config/ns32k/merlin.h
+ (PRINT_OPERAND), config/ns32k/ns32k.c (print_operand),
+ config/pdp11/pdp11.h (PRINT_OPERAND), config/we32k/we32k.h
+ (PRINT_OPERAND): Don't use local version of union
+ real_extract.
+
+ * config/convex/convex.c (check_float_value), config/vax/vax.c
+ (vax_float_literal), config/m88k/m88k.md (divdf3),
+ config/dsp16xx/dsp16xx.md (fixuns_trunchfhi2),
+ config/pdp11/pdp11.c (output_move_quad): Don't do host
+ arithmetic on target floating point quantities.
+
+ * config/a29k/a29k.md, config/dsp16xx/dsp16xx.c
+ (output_dsp16xx_float_const): Don't test HOST_FLOAT_FORMAT.
+
+ * fold-const.c (fold), simplify-rtx.c (simplify_binary_real):
+ Use MODE_HAS_INFINITIES rather than #ifdef REAL_INFINITY.
+
+ * real.c (earith): Test INFINITY rather than REAL_INFINITY;
+ NANS implies INFINITY, so can drop #ifdef NANS inside #ifndef
+ INFINITY.
+ * print-rtl.c (print_rtx): Disable code which needs
+ floating-point emulator.
+ * libgcc2.c: Include float.h and use DBL_MANT_DIG,
+ FLT_MANT_DIG, to define DF_SIZE and SF_SIZE, rather than
+ depending on HOST_FLOAT_FORMAT to be defined properly.
+
+ * config/1750a/1750a.c (get_double, float_label): Delete.
+ (print_operand): Delete huge commented-out chunk. Use
+ REAL_VALUE_TO_DECIMAL.
+ * config/1750a/1750a-protos.h: Delete prototypes of deleted
+ functions.
+ * config/convex/convex.h: Always set TARGET_FLOAT_FORMAT to
+ IEEE_FLOAT_FORMAT.
+ * config/i370/i370.h (PRINT_OPERAND [TARGET_HLASM version]):
+ Use REAL_VALUE_TO_DECIMAL as ELF version does.
+ * config/m88k/m88k.c (real_power_of_2_operand,
+ legitimize_operand): Take the REAL_VALUE_TYPE and/or union
+ real_extract out of the union; run the input through
+ REAL_VALUE_TO_TARGET_DOUBLE, then plug the pair of longwords
+ from that into the union.
+ * config/pdp11/pdp11.c (output_move_double): Rearrange
+ parentheses to make automatic indenter happy.
+
+ * doc/tm.texi (Cross-compilation): Rename node to "Floating
+ Point" and rewrite to describe current situation. Also adjust
+ documentation of REAL_VALUE_TO_TARGET_SINGLE and friends to
+ match code.
+ * doc/rtl.texi: Adjust cross reference.
+
+2002-03-22 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa-protos.h (non_acc_reg_operand): Remove.
+ (xtensa_valid_move, xtensa_preferred_reload_class): Define.
+ * config/xtensa/xtensa.c (non_acc_reg_operand): Remove.
+ (xtensa_valid_move, xtensa_preferred_reload_class): Define to
+ prevent use of sp as a reload register.
+ (xtensa_emit_move_sequence): Use xtensa_valid_move instead of
+ non_acc_reg_operand.
+ * config/xtensa/xtensa.h (PREDICATE_CODES): Remove non_acc_reg_operand.
+ (PREFERRED_RELOAD_CLASS): Move code to xtensa_preferred_reload_class.
+ * config/xtensa/xtensa.md (movsi_internal, movhi_internal,
+ movqi_internal): Use xtensa_valid_move instead of non_acc_reg_operand.
+
+2002-03-22 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpphash.h (struct cpp_reader): Remove mls_line and mls_col.
+ * cpplex.c (unterminated): Delete.
+ (parse_string): No string literal may extend over multiple
+ lines. Suppress the error when preprocessing assembly.
+ * cppmain.c (scan_translation_unit): Strings are single-line.
+
+ * doc/cpp.texi: Update to match.
+
+2002-03-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR optimization/5854
+ * config/m68hc11/m68hc11.h (CONST_OK_FOR_LETTER_VALUE_P): Use K for 0.
+ Shut up warnings.
+ (CONST_DOUBLE_OK_FOR_LETTER_P): Use G for 0.0.
+ (EXTRA_CONSTRAINT): Use S for non-push memory operand.
+ * config/m68hc11/m68hc11.c (m68hc11_split_move): Handle setting from
+ const0 if scratch register was not allocated.
+ (m68hc11_reload_operands, m68hc11_gen_lowpart, m68hc11_gen_highpart,
+ m68hc11_z_replacement): Replace gen_rtx (CONST_INT, VOIDmode, ...)
+ with GEN_INT (...).
+ (m68hc11_reorg): Compute BLOCK_FOR_INSN before reload_cse_regs.
+ * config/m68hc11/m68hc11.md: Replace gen_rtx (CONST_INT, VOIDmode, ...)
+ with GEN_INT (...) everywhere. Remove constraints in define_split
+ patterns.
+ (movdi_internal, movdf_internal, movsi_internal, movsf_internal): Don't
+ require scratch register for setting 0 into regs/non-pushable memory.
+
+2002-03-22 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/mips/mips.h (MASK_RETURN_ADDR): Define.
+ (TARGET_PTRMEMFUNC_VBIT_LOCATION): Define.
+
+2002-03-22 Phil Edwards <pme@gcc.gnu.org>
+
+ * cpplib.h (struct cpp_options): New member, warn_endif_labels.
+ * cppinit.c (cpp_create_reader): On by default.
+ (cpp_handle_option): Handle -W[no-]endif-labels.
+ (cpp_post_options): Also enable if -pedantic.
+ * cpplib.c (do_else): Use it.
+ (do_endif): Likewise.
+ * doc/cppopts.texi: Document new option.
+ * doc/invoke.texi: Document new option.
+
+2002-03-22 Lars Brinkhoff <lars@nocrew.org>
+
+ * config/i386/i386.c, config/i386/i386.md: Change all occurences
+ of GEN_INT (trunc_int_for_mode (...)) to gen_int_mode (...).
+
+2002-03-22 Alexandre Oliva <aoliva@redhat.com>
+
+ * flow.c (calculate_global_regs_live): Clear aux fields of
+ ENTRY and EXIT.
+
+2002-03-22 Jakub Jelinek <jakub@redhat.com>
+
+ * config/v850/v850.c (v850_reorg): Only call alter_subreg on
+ REG or MEM subregs, pass rtx * instead of rtx to it.
+ * config/i860/i860.c (output_delayed_branch, output_delay_insn): Pass
+ rtx * instead of rtx to alter_subreg.
+ * config/m32r/m32r.c (gen_split_move_double): Likewise.
+ * config/pj/pj.c (pj_output_rval): Likewise.
+
+2002-03-22 Richard Henderson <rth@redhat.com>
+
+ PR target/3177
+ * config/ia64/ia64.h (CUMULATIVE_ARGS): Add int_regs.
+ (INIT_CUMULATIVE_ARGS, INIT_CUMULATIVE_INCOMING_ARGS): Update.
+ * config/ia64/ia64.c (ia64_function_arg_advance): Set int_regs.
+ (ia64_expand_prologue): Look at int_regs, not words, for number
+ of incomming int regs.
+
+2002-03-22 Andrew MacLeod <amacleod@redhat.com>
+
+ * expr.c (expand_expr): A RESULT_DECL is part of a call.
+
+Fri Mar 22 16:30:42 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * toplev.c (flag_loop_optimize, flag_crossjumping):
+ New static variables.
+ (rest_of_compilation): Conditionalize crossjumping and
+ loop optimizer.
+ (parse_options_and_default_flags): Default loop_optimize and
+ crossjumping.
+ (lang_independent_options): Add -fcrossjumping and -floop-optimize
+ * invoke.texi (crossjumping, loop-optimize): Document.
+
+2002-03-22 Richard Sandiford <rsandifo@redhat.com>
+
+ * real.c (eiisneg): Move outside #ifdef NANS.
+
+Fri Mar 22 12:08:36 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgcleanup.c (outgoing_edges_math): Fix condition; relax
+ frequencies match; avoid match on different loop depths.
+ (try_crossjump_to_bb): Kill tests that no longer brings time
+ savings.
+ * cfgrtl.c (force_nonfallthru_and_redirect): Fix loop_depth
+ updating code.
+ (split_edge): Likewise.
+
+ * flow.c (update_life_info_in_dirty_blocks): Fix uninitialized
+ variable.
+
+ * Makefile.in (cfgrtl): Add insn-config.h depenendency.
+ * cfgrtl.c: Include insn-config.h
+ (split_block) Dirtify block in presence of conditional execution
+
+2002-03-22 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/abi64.h (SETUP_INCOMING_VARARGS): Undefine.
+ * config/mips/mips-protos.h (mips_setup_incoming_varargs): Declare.
+ (function_arg): Constify CUMULATIVE_ARGS.
+ (function_arg_partial_nregs, function_arg_pass_by_reference): Likewise.
+ * config/mips/mips.h (UNITS_PER_FPVALUE): Zero when TARGET_SOFT_FLOAT.
+ (UNITS_PER_DOUBLE): New macro.
+ (SETUP_INCOMING_VARARGS): Define. Use mips_setup_incoming_varargs.
+ (CUMULATIVE_ARGS): Reformat. Remove num_adjusts workaround and
+ last_arg_fp field. Replace arg_words and fp_arg_words with gp_regs,
+ fp_regs and stack_words.
+ (EABI_FLOAT_VARARGS_P): New macro.
+ * config/mips/mips.c (struct mips_arg_info): New.
+ (mips_arg_info): New function.
+ (function_arg_advance): Use it. Add adjustment instructions here
+ rather than in function_arg.
+ (function_arg): Constify CUMULATIVE_ARGS. Use mips_arg_info. Check
+ for VOIDmode at the beginning of the function.
+ (function_partial_nregs): Constify CUMULATIVE_ARGS. Use mips_arg_info.
+ (function_arg_pass_by_reference): Likewise.
+ (mips_setup_incoming_varags): New, largely based on old abi64.h code.
+ (mips_build_va_list): Test EABI_FLOAT_VARARGS_P.
+ (mips_va_start): Likewise. Use the new stack_words field of
+ CUMULATIVE_ARGS to set up overflow area. Reformat.
+ (mips_va_arg): Test EABI_FLOAT_VARARGS_P. Unify EABI handling of
+ doubles and other types, aligning the overflow pointer for non-doubles
+ too. Remove some code duplication. Replace hard-coded constants.
+
+2002-03-22 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips.h (FUNCTION_ARG_REGNO_P): Simplify.
+ (CLASS_UNITS): Undefine.
+ (CLASS_MAX_NREGS): Use FP_INC.
+ * config/mips/mips.c (compute_frame_size): Likewise.
+ (override_options): Use FP_INC and UNITS_PER_FPVALUE.
+
+2002-03-22 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpplex.c (parse_identifier_slow): Rename parse_slow, adjust
+ prototype, and handle lexing numbers and identifiers.
+ (parse_identifier): Update to new form of parse_slow.
+ (parse_number): Fast path only, use parse_slow otherwise.
+ (_cpp_lex_direct): Update calls to parse_number.
+
+2002-03-21 DJ Delorie <dj@redhat.com>
+
+ * bb-reorder.c (make_reorder_chain_1): Protect against
+ when redundant edges are omitted.
+ * predict.c (dump_prediction): Likewise.
+
+2002-03-21 Richard Henderson <rth@redhat.com>
+
+ PR target/5996
+ * fixinc/inclhack.def (solaris_stdio_tag): New.
+ * fixinc/fixincl.x: Regenerate.
+
+2002-03-21 Eric Botcazou <ebotcazou@multimania.com>
+
+ PR c/5597
+ * c-typeck.c (process_init_element): Flag non-static
+ initialization of a flexible array member as illegal.
+
+2002-03-22 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/t-linux64: New.
+ * config.gcc (powerpc64-*-linux* <tmake_file>): Drop t-ppcos and
+ t-ppccomm. Use t-rs6000 and t-linux64.
+ (powerpc64-*-gnu* <tmake_file>): Likewise.
+ * mklibgcc.in (SHLIB_MKMAP_OPTS): New variable.
+ * mkmap-symver.awk (dotsyms): If set, output .foo as well as foo.
+ * Makefile.in (SHLIB_MKMAP_OPTS): Pass to mklibgcc.
+
+2002-03-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * langhooks.c (lhd_tree_inlining_cannot_inline_tree_fn): Check
+ flag_really_no_inline instead of optimize == 0.
+
+ * c-objc-common.c (c_cannot_inline_tree_fn): Same.
+
+ * cp/tree.c (cp_cannot_inline_tree_fn): Same.
+
+ * flags.h (flag_really_no_inline): New.
+
+ * c-common.c (c_common_post_options): Initialize
+ flag_really_no_inline.
+
+ * toplev.c (flag_really_no_inline): New.
+
+2002-03-21 Jakub Jelinek <jakub@redhat.com>
+
+ * config/avr/avr.md (length): Fix length computation for
+ conditional branches.
+
+2002-03-21 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in (fold-const.o, stor-layout.o, stmt.o,
+ sdbout.o, profile.o): Update.
+ * c-common.c (c_common_nodes_and_builtins): Use pushdecl
+ langhook.
+ * c-common.h (gettags): Move here from tree.h.
+ * c-tree.h (pushdecl, pushlevel, poplevel, set_block,
+ insert_block, getdecls, kept_level_p, global_bindings_p): New.
+ * dbxout.c (dbxout_init): Use getdecls langhook.
+ * expr.c (expand_expr): Use insert_block langhook.
+ * fold-const.c: Include langhooks.h.
+ (fold_range_test, fold_binary_op_with_conditional_arg,
+ fold): Use global_bindings_p langhook.
+ * integrate.c (expand_inline_function): Use insert_block langhook.
+ * langhooks-def.h (LANG_HOOKS_DECLS, LANG_HOOKS_PUSHLEVEL,
+ LANG_HOOKS_POPLEVEL, LANG_HOOKS_GLOBAL_BINDINGS_P,
+ LANG_HOOKS_INSERT_BLOCK, LANG_HOOKS_SET_BLOCK, LANG_HOOKS_PUSHDECL,
+ LANG_HOOKS_GETDECLS): New.
+ (LANG_HOOKS_INITIALIZER): Update.
+ * langhooks.c (lhd_clear_binding_stack): Use global_bindings_p
+ langhook.
+ * langhooks.h (struct lang_hooks_for_decls): New.
+ (struct lang_hooks): Update.
+ * profile.c: Include langhooks.h.
+ (output_func_start_profiler): Use new langhooks.
+ * sdbout.c: Include langhooks.h.
+ (sdbout_init, sdbout_finish): Use getdecls langhook.
+ * stmt.c: Include langhooks.h.
+ (expand_fixup, fixup_gotos): Use new langhooks.
+ * stor-layout.c: Include langhooks.h.
+ (variable_size): Use global_bindings_p langhook.
+ * toplev.c (compile_file): Use getdecls langhook.
+ * tree-inline.c (remap_block): Use insert_block langhook.
+ * tree.h (pushdecl, pushlevel, poplevel, set_block, gettags,
+ insert_block, getdecls, kept_level_p, global_bindings_p): Remove.
+
+2002-03-21 Richard Henderson <rth@redhat.com>
+
+ * config/rs6000/rs6000.c (rs6000_select_rtx_section): Put symbolic
+ constants in .data when -fpic.
+
+2002-03-21 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/contrib.texi (Contributors): Use GNU/Linux instead of Linux
+ where appropriate.
+
+2002-03-21 Tom Tromey <tromey@redhat.com>
+
+ * config/i386/sol2.h (ASM_QUAD): Undef. Fixes PR bootstrap/5948.
+
+Thu Mar 21 09:50:48 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * config/ia64/ia64.c (hfa_element_mode, case ARRAY_TYPE): Recurse.
+
+ * expr.c (emit_group_store): Don't copy const0_rtx to a CONCAT.
+
+2002-03-21 Eric Botcazou <ebotcazou@multimania.com>
+ Richard Henderson <rth@redhat.com>
+
+ PR c/5354
+ * c-common.c (c_expand_expr): Preserve result of a statement
+ expression if needed.
+
+2002-03-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR bootstrap/4195
+ * genrecog.c (maybe_both_true_mode): Remove.
+ (maybe_both_true_2, write_switch): Revert 2001-07-17 changes.
+ * machmode.def (Pmode): Likewise.
+
+Thu Mar 21 01:55:06 EST 2002 John Wehle (john@feith.com)
+
+ * alias.c: (nonlocal_mentioned_p): Use for_each_rtx.
+ (nonlocal_mentioned_p_1): New function.
+ (nonlocal_referenced_p, nonlocal_referenced_p_1): Likewise.
+ (nonlocal_set_p, nonlocal_set_p_1): Likewise.
+ (mark_constant_function): Recognize pure functions.
+ * rtl.h (global_reg_mentioned_p): New prototype.
+ * rtlanal.c (global_reg_mentioned_p,
+ global_reg_mentioned_p_1): New function.
+
+2002-03-21 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * fixinc/inclhack.def (alpha_assert): Fix assert macro in Tru64
+ UNIX assert.h.
+ * fixinc/fixincl.x: Regenerate.
+
+2002-03-20 Jason Merrill <jason@redhat.com>
+
+ * config/i386/cygwin.h (DWARF2_UNWIND_INFO): Define to 0.
+
+2002-03-20 Michael Meissner <meissner@redhat.com>
+
+ * doc/invoke.texi (Optimize Options): Document that -O2 sets
+ -fstrict-aliasing.
+
+2002-03-20 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.h (ASM_OUTPUT_POOL_PROLOGUE): Emit a
+ ".literal_position" directive before the constant pool.
+
+2002-03-20 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/contrib.texi (Contributors): Update Geoffrey Keating.
+ Add Craig Rodrigues.
+ Add Brad Lucier to testers.
+
+2002-03-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/4792
+ * config/arc/arc.md (movsicc, movdicc, movsfcc, movdfcc): Add mode
+ to if_then_else.
+ (movsicc_insn, movdicc_insn, movsfcc_insn, movdfcc_insn): Likewise.
+ * config/arc/arc.c (arc_final_prescan_insn): Use extract_insn_cached
+ instead of insn_extract.
+
+2002-03-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR bootstrap/4192
+ * config/fr30/fr30.md (jump): Remove clobber of fixed register.
+
+ * genemit.c (output_added_clobbers_hard_reg_p): Only output return
+ stmt if some case has been output.
+
+2002-03-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/5972
+ * config/i386/i386.md (movdicc_c_rex64, movsicc_noc, movhicc_noc,
+ movsfcc_1, movdfcc_1): Add %O2.
+ * config/i386/i386.c (print_operand): Handle %ON.
+ Print . before float condition codes in Sun as cmov syntax.
+ * config/i386/sol2.h (CMOV_SUN_AS_SYNTAX): Define for Sun as.
+ * config.gcc (i[34567]86-*-solaris2*): Remove comment which is
+ no longer true.
+
+2002-03-20 Philip Blundell <pb@nexus.co.uk>
+
+ * config/arm/arm.c (arm_output_epilogue): Don't generate separate
+ return instruction if PC was popped.
+
+2002-03-20 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.md: Remove unused type attributes.
+ (adddi_carry, subddi_carry): Change type attribute to "multi".
+
+2002-03-19 Dale Johannesen <dalej@apple.com>
+
+ PR optimization/5999, middle-end/5731
+ * expr.c (expand_expr) [RDIV_EXPR]: Only convert real divisions into
+ multiplications by reciprocals.
+
+2002-03-20 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in: Update.
+ * c-common.c: Include langhooks.h.
+ (inline_forbidden_p): Use new hook.
+ * diagnostic.c: Include langhooks.h.
+ (format_with_decl, announce_function,
+ default_print_error_function): Use new hook.
+ * dwarf2out.c (dwarf2_name): Use new hook.
+ * function.c: Include langhooks.h.
+ (init_function_start): Use new hook.
+ * langhooks-def.h (lhd_decl_printable_name): New.
+ (LANGHOOKS_DECL_PRINTABLE_NAME): New.
+ (LANGHOOKS_INITIALIZER): Update.
+ * langhooks.c (lhd_decl_printable_name): New.
+ * langhooks.h (struct lang_hooks): New hook.
+ * toplev.c (decl_name, decl_printable_name): Remove.
+ (open_dump_file): Use new hook.
+ (process_options): Remove old hook.
+ * tree.h (decl_printable_name): Remove.
+objc:
+ * objc-act.c (objc_init): Remove old hook.
+ (objc_printable_name): Export.
+ * objc-act.h (objc_printable_name): New.
+ * objc-lang.c (LANG_HOOKS_DECL_PRINTABLE_NAME): Redefine.
+
+2002-03-19 Jim Blandy <jimb@redhat.com>
+
+ * c-lex.c (cb_file_change): Pass the #inclusion's line number to
+ the start_source_file debug hook, not the current line number.
+
+2002-03-19 Richard Henderson <rth@redhat.com>
+
+ * flow.c (EH_USES): Provide default.
+ (calculate_global_regs_live): Use it for EH edges and noreturn calls.
+ * doc/tm.texi (EH_USES): New.
+
+ * config/ia64/ia64.c (ia64_eh_uses): New.
+ * config/ia64/ia64-protos.h: Update.
+ * config/ia64/ia64.h (EH_USES): New.
+
+2002-03-19 Richard Henderson <rth@redhat.com>
+
+ * varasm.c (output_constant_def): Fix stupid typo.
+
+2002-03-19 Richard Henderson <rth@redhat.com>
+
+ PR 5879
+ * except.c (current_function_has_exception_handlers): New.
+ * except.h: Declare it.
+ * sibcall.c (optimize_sibling_and_tail_recursive_call): Use it.
+ Combine tests that disable all sibcalls for the function.
+
+2002-03-19 Olivier Hainque <hainque@act-europe.fr>
+
+ * varasm.c (output_constant_def): Don't call ENCODE_SECTION_INFO
+ for INTEGER_CST.
+
+2002-03-19 Richard Henderson <rth@redhat.com>
+
+ PR 5977, 5991
+ * config/ia64/ia64.c: Revert 2002-03-01 patch.
+ * config/ia64/ia64.h (INIT_EXPANDERS): New.
+
+2002-03-19 Jim Blandy <jimb@redhat.com>
+
+ * cppmacro.c (cpp_macro_definition): Emit a space after the macro
+ name, even if the replacement list contains no tokens, as required
+ by Dwarf.
+
+2002-03-19 Jason Merrill <jason@redhat.com>
+
+ * varasm.c (globalize_decl): Get the name from the RTL, not
+ DECL_ASSEMBLER_NAME.
+
+ * Makefile.in (LIBGCC2_DEBUG_CFLAGS): Set to -g.
+
+2002-03-19 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.md (adddi3, adddi_carry, subdi3,
+ subdi_carry): Define.
+
+2002-03-19 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.c (rs6000_override_options): Only warn
+ about -fpic/-fPIC if extra_warnings set.
+
+2002-03-19 David Edelsohn <edelsohn@gnu.org>
+
+ * expr.c (expand_expr): Sign-extend CONST_INT generated from
+ TREE_STRING_POINTER.
+ * fold-const.c (fold): Delete #if 0 ARRAY_REF case.
+
+Tue Mar 19 14:12:32 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * config/sparc/sparc.h (CAN_ELMINIATE): Can only eliminate FP
+ in favor of SP if FRAME_POINTER_REQUIRED is false.
+
+2002-03-19 Lars Brinkhoff <lars@nocrew.org>
+
+ * emit-rtl.c (gen_int_mode): New function.
+ * rtl.h: Prototype for it.
+ * combine.c (make_extraction, simplify_comparison), expmed.c
+ (store_bit_field, expand_mult_highpart, expand_divmod), expr.c
+ (convert_modes, store_field), optabs.c (expand_fix),
+ simplify-rtx.c (neg_const_int, simplify_unary_real),
+
+ * config/rs6000/rs6000.c, config/rs6000/rs6000.md:
+ Use it instead of GEN_INT (trunc_int_for_mode (...)).
+
+2002-03-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/5656
+ * langhooks.h (struct lang_hooks_for_tree_inlining): Add
+ convert_parm_for_inlining.
+ * c-lang.c (LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING):
+ Define.
+ * langhooks-def.h: Likewise.
+ * objc/objc-lang.c: Likewise.
+ * langhooks.c (lhd_tree_inlining_convert_parm_for_inlining): New
+ function.
+ * tree-inline.c (initialize_inlined_parameters):
+ Call convert_parm_for_inlining lang hook if needed.
+ * c-typeck.c (c_convert_parm_for_inlining): New function.
+ * c-tree.h (c_convert_parm_for_inlining): Add prototype.
+
+2002-03-18 Mark Mitchell <mark@codesourcery.com>
+
+ * calls.c (precompute_arguments): Do not assume that temporaries
+ can be destroyed after expanding the argument.
+ (expand_call): Likewise.
+
+2002-03-15 Eric Christopher <echristo@redhat.com>
+
+ * config/mips/mips.md (movdf_internal2): Add two new move constraints.
+ Fix register preference on last change.
+ * config/mips/mips.c (mips_return_in_memory): New function.
+ * config/mips/mips.h (RETURN_IN_MEMORY): Use.
+ * config/mips/mips-protos.h: Declare.
+ * config/mips/abi64.h (RETURN_IN_MEMORY): Remove. Add to above.
+ * config/mips/elf64.h: Add #ifndef/#endif brackets around defaults.
+
+2002-03-18 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/mips/mips.md (andsi3) [TARGET_MIPS16]: Force operand 1 to
+ a register too.
+ (anddi3, iorsi3): Likewise.
+
+ * config/mips/mips.h (ENCODE_SECTION_INFO) [TARGET_MIPS16]: Don't
+ use %gprel for symbols that are going to be placed in linkonce
+ sections.
+
+ * config/mips/mips.h (ELIMINABLE_REGS): Can't eliminate
+ RETURN_ADDRESS_POINTER_REGNUM to $ra.
+ (CAN_ELIMINATE): Only eliminate it to $sp if a frame pointer is
+ not needed. Disregard leaf_function_p().
+ (INITIAL_ELIMINATION_OFFSET): Adjust for elimination of rap to
+ mips16 frame pointer.
+ * config/mips/mips.md (store ra): Only to small SP offsets.
+ 2001-08-22 Graham Stott <grahams@redhat.com>
+ * config/mips/mips.h (RETURN_ADDR_RTX): For a leaf function
+ return a REG rtx for the return address register.
+
+2002-03-18 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.h (GO_IF_MODE_DEPENDENT_ADDRESS): Treat
+ constant-pool addresses as "mode-dependent".
+ (GO_IF_LEGITIMATE_ADDRESS): Rename macro arguments.
+
+2002-03-18 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/5740
+ * expr.c (emit_group_load): Use extract_bit_field if
+ needed for CONCAT arguments.
+
+2002-03-18 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/4863
+ * arm.md (tablejump): Make this a define_expand. For PIC add the
+ offset to the base of the table.
+ (thumb_tablejump): Matcher for Thumb tablejump insn.
+ * config/arm/aout.h (ASM_OUTPUT_ADDR_DIFF_ELT): Output thumb entries
+ as the difference of two labels.
+ * config/arm/aof.h (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
+ * config/arm/elf.h (JUMP_TABLES_IN_TEXT_SECTION): Only put ARM jump
+ tables in the code.
+ * config/arm/coff.h (JUMP_TABLES_IN_TEXT_SECTION): Likewise.
+ * arm.c (get_jump_table_size): If the table is not in the text
+ section, return zero.
+
+2002-03-18 Bernd Schmidt <bernds@redhat.com>
+
+ * config/arm/arm.c (arm_gen_movstrqi): Use gen_lowpart instead
+ of gen_rtx_SUBREG.
+ (arm_reload_out_hi): Use gen_lowpart instead of
+ gen_rtx_SUBREG to access QImode components.
+ * config/arm/arm.md: Disable zero_extend split for QImode
+ subregs in BIG_ENDIAN mode.
+ (storehi_bigend): Match use of least significant byte.
+ (storeinthi): Remove extraneous SUBREG.
+ Add missing construction of operands[2].
+ (movhi): Use gen_lowpart in place of gen_rtx_SUBREG.
+ (movqi): Use gen_lowpart in place of gen_rtx_SUBREG.
+ Replace gen_rtx (SUBREG) with gen_rtx_SUBREG.
+
+2002-03-18 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.h (PREDICATE_CODES): Add PARALLEL to
+ any_operand.
+
+2002-03-17 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (alpha_emit_set_const_1): Build add insns
+ explicitly.
+
+2002-03-17 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.md ("fixuns_truncdfdi2"): Use (unsigned_fix:DI
+ (unsigned_fix:DF op1)), not (unsigned_fix:DI (fix:DF op1)).
+
+2002-03-17 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * ifcvt.c (dead_or_predicable): Fix uninitialized variable.
+
+ * predict.c (estimate_bb_frequencies): Delete unused variables.
+
+2002-03-17 Richard Henderson <rth@redhat.com>
+
+ * config/ia64/ia64.c (ia64_attribute_table): Move before
+ targetm definition. Make static.
+
+2002-03-17 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.h (yyparse, c_common_parse_file): New.
+ * c-lang.c: Include c-common.h.
+ (LANG_HOOKS_PARSE_FILE): Redefine.
+ * c-lex.c: Include c-common.h.
+ (yyparse): Rename c_common_parse_file. Call yyparse.
+ * c-parse.in (yyparse): Remove macro.
+ * c-tree.h (yyparse_1): Remove.
+ * langhooks-def.h (LANG_HOOKS_PARSE_FILE): New.
+ (LANG_HOOKS_INITIALIZER): Update.
+ * langhooks.h (struct lang_hoooks): New hook parse_file.
+ * toplev.c (compile_file): Use parse_file hook.
+ * tree.h (yyparse): Remove.
+ * objc/objc-lang.c (LANG_HOOKS_PARSE_FILE): Redefine.
+
+2002-03-17 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.md ("truncdfsf2"): Correct operator is
+ float_truncate, not fix.
+ ("*truncdfsf2_real"): Ditto.
+ ("*nonlocal_goto_receiver_expanded"): Fix output template formatting.
+
+ * config/mmix/mmix.h (WCHAR_TYPE, WCHAR_TYPE_SIZE): Don't define.
+
+2002-03-16 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/mips/mips.h (CAN_ELIMINATE): Don't eliminate rap to $fp
+ (s8), but rather HARD_FRAME_POINTER_REGNUM. Add parentheses
+ where appropriate. Make the second reference to
+ leaf_function_p a function call, as intended. Reindented.
+
+ * config/mips/mips.h (ISA_HAS_COND_TRAP): Not available on MIPS16.
+ * config/mips/mips.md (trap) [TARGET_MIPS16]: Emit `break 0'.
+
+ * config/mips/mips.md (addsi3, adddi3): Use scratch register to
+ add register to non-constant into sp.
+
+ * config/mips/mips-protos.h (embedded_pic_fnaddr_reg): New.
+ * config/mips/mips.h (embedded_pic_fnaddr_rtx): Lose.
+ (mips16_gp_pseudo_rtx): Lose.
+ (INIT_EXPANDERS): Deleted.
+ * config/mips/mips.c (mips_init_machine_status): New.
+ (mips_free_machine_status): New.
+ (mips_mark_machine_status): New.
+ (override_options): Set them.
+ (embedded_pic_fnaddr_rtx, mips16_gp_pseudo_rtx): Moved to...
+ (struct machine_function): ... new. Replaced all references.
+ (mips_add_gc_roots): Don't mark them.
+ (embedded_pic_fnaddr_reg): New, extracted from...
+ (embedded_pic_offset): ... here.
+ * config/mips/mips.md (movdi): Call embedded_pic_fnaddr_reg.
+ (movsi): Likewise.
+
+2002-03-16 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppinit.c: Revert -MD removal.
+
+2002-03-16 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/m68hc11.c (m68hc11_override_options): Don't use
+ soft registers by default for 68HC12.
+ (m68hc11_conditional_register_usage): Don't use Z register for 68HC12
+ when compiling with -fomit-frame-pointer.
+ (expand_prologue): Use push/pop to allocate 4-bytes of locals on 68HC12.
+ (expand_epilogue): Likewise.
+ (m68hc11_gen_rotate): Use exg when rotating by 8.
+
+2002-03-16 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/m68hc11-protos.h (ix_reg): Declare.
+ * config/m68hc11/m68hc11.md ("addsi3"): Use general_operand for sources.
+ (splits): Remove unused add splits.
+ ("*addhi3_68hc12"): Tune constraints.
+ ("addhi_sp"): Try to use X instead of Y in all cases and if the
+ constant fits in 8-bits and D is dead use abx/aby instructions.
+ ("*addhi3"): Remove extern declaration of ix_reg.
+ ("*subsi3"): Optimize and provide new split.
+ ("subhi3"): Cleanup.
+ ("*subhi3_sp"): Avoid saving X if we know it is dead.
+ (arith splits): For 68hc12 save the address register on the stack
+ and do the arithmetic operation with a pop.
+
+2002-03-16 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/m68hc11.md ("*movqi_68hc12"): Fix constraints, avoid
+ allocating QImode in address registers.
+ ("*movqi_m68hc11"): Likewise.
+
+Sat Mar 16 12:57:28 CET 2002 Jan HUbicka <jh@suse.cz>
+
+ * cfgcleanup.c (cleanup_cfg): Fix updating of liveness.
+
+2002-03-16 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppinit.c (print_help): Display -MD and -MMD.
+ Don't display usage string. Update assertion syntax and
+ typo.
+ (COMMAND_LINE_OPTIONS): Remove OPT_MD, OPT_MMD.
+ (cpp_handle_option): Update.
+
+2002-03-15 Chris Demetriou <cgd@broadcom.com>
+
+ * config/mips/mips.h (SUBTARGET_CPP_SIZE_SPEC): Provide an
+ MEABI case for each definition of SUBTARGET_CPP_SIZE_SPEC,
+ and define it so that regardless of target CPU size,
+ __SIZE_TYPE__ and __PTRDIFF_TYPE__ are defined in terms
+ of "int" rather than "long."
+
+2002-03-15 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (alpha_va_arg): Manipulate the type
+ size as a tree.
+
+2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/m68hc11.md ("tstqi_1"): Try to use ldab instead of tst.
+ ("tstqi" split): Avoid using memory for tstqi on address register.
+ (splits): Remove constraints.
+ ("cmphi_1_hc12"): New from "cmphi_1" and tuned for 68HC12.
+ ("cmpdf", "cmpsf"): Remove since not used.
+ ("*tbeq", "*tbne", "*tbeq8", "*tbne8"): Also look in cc_status.value2.
+ (peephole2): New peepholes to optimize tstqi and pre inc/dec addressing.
+
+2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/m68hc11.md ("negsi2"): Optimize inline case.
+ ("neghi2"): Tighten constraints.
+ ("one_cmplsi2"): Optimize and simplify split.
+ * config/m68hc11/larith.asm (__negsi2): Likewise for library.
+
+2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/m68hc11.md ("logicalsi3_zexthi"): Fix constraints
+ and split of AND operation to clear the upper bits.
+ ("*logicalsi3_zextqi"): Likewise.
+ ("*logicallhi3_zexthi_ashift8"): Likewise.
+ ("*logicalsi3_silshr16"): Likewise.
+ ("logicalsi3_silshl16"): Likewise.
+ ("anddi3", "iordi3", "xordi3" splits): Remove constraints.
+
+2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/m68hc11.c (m68hc11_symbolic_p): New function.
+ (m68hc11_indirect_p): New function.
+ (m68hc11_override_options): Must set MASK_NO_DIRECT_MODE for 68HC12.
+ (m68hc11_gen_highpart): Use TARGET_NO_DIRECT_MODE instead of
+ TARGET_M6812.
+ (asm_print_register): Likewise.
+ * config/m68hc11/m68hc11-protos.h (m68hc11_symbolic_p): Declare.
+ (m68hc11_indirect_p): Declare.
+ * config/m68hc11/m68hc11.h (EXTRA_CONSTRAINT): New constraint 'R', 'Q'.
+ (TARGET_NO_DIRECT_MODE, TARGET_RELAX): New.
+ (TARGET_SWITCHES): New option -mrelax.
+ * config/m68hc11/m68hc11.md ("andsi3"): Allow soft register for
+ destination.
+ ("iorsi3", "xorsi3"): Likewise.
+ ("andhi3", "andqi3", "iorhi3", "iorqi3"): Use a define_expand.
+ ("*andhi3_mem"): New to handle destination in memory with bclr
+ and a scratch register.
+ ("*andqi3_mem", "*iorhi3_mem", "*iorqi3_mem"): Likewise.
+ ("*andhi3_const"): New when operand2 is constant.
+ ("*andqi3_const", "*iorhi3_const", "*iorqi3_const"): Likewise.
+ ("*andhi3_gen"): Cleanup of the old "andhi3".
+ ("*andqi3_gen", "*iorhi3_gen", "*iorqi3_gen"): Likewise.
+ ("xorqi3"): Update constraints.
+
+2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/m68hc11.c (m68hc11_small_indexed_indirect_p): Look
+ for reg_equiv_memory_loc when the operand is a register that does
+ not get a hard register (stack location).
+ (tst_operand): After reload, accept all memory operand.
+ (symbolic_memory_operand): Fix detection of symbolic references.
+ * config/m68hc11/m68hc11.h (VALID_CONSTANT_OFFSET_P): For 68HC12
+ accept symbols and any constant.
+
+2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/m68hc11.c (emit_move_after_reload): Add a REG_INC
+ note on the insn that sets the soft frame register.
+ (must_parenthesize): ix and iy are also reserved names.
+ (print_operand_address): One more place where parenthesis are required
+ to avoid confusion with register names.
+ (m68hc11_gen_movhi): Allow push of stack pointer.
+ (m68hc11_check_z_replacement): Fix handling of parallel with a
+ clobber.
+ (m68hc11_z_replacement): Must update the REG_INC notes to tell what
+ the replacement register is.
+ * config/m68hc11/m68hc11.h (REG_CLASS_CONTENTS): Switch Z_REGS
+ and D8_REGS classes.
+ (MODES_TIEABLE_P): All modes are tieable except QImode.
+
+2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/larith.asm (___adddi3): Optimize saving of result.
+ (___subdi3): Likewise.
+ (__mulsi3, __mulhi32): Avoid using _.tmp scratch location.
+ (__map_data_section): Optimize 68hc11 case.
+
+2002-03-15 Stephane Carrez <Stephane.Carrez@worldnet.fr>
+
+ * config/m68hc11/m68hc11.c (m6812_cost): Make cost of add higher
+ than a shift to avoid adding a register with itself.
+ (m68hc11_memory_move_cost): Take into account NO_REGS.
+ (m68hc11_register_move_cost): Update and use memory move cost
+ for soft registers.
+ (m68hc11_address_cost): Make cost of valid offset not 0 so that
+ it gives more opportunities to cse to optimize.
+ * config/m68hc11/m68hc11.h (REGISTER_MOVE_COST): Pass the mode.
+ * config/m68hc11/m68hc11-protos.h (m68hc11_register_move_cost): Update.
+
+2002-03-15 Mark Mitchell <mark@codesourcery.com>
+
+ * c-common.c (statement_code_p): Handle CLEANUP_STMT.
+ * c-common.def (CLEANUP_STMT): New tree node.
+ * c-common.h (CLEANUP_DECL): New macro.
+ (CLEANUP_EXPR): Likewise.
+ * c-semantics.c (expand_stmt): Handle CLEANUP_STMT.
+ * expr.c (expand_expr): Tidy.
+ * tree-dump.c (dequeue_and_dump): Handle CLEANUP_STMT.
+ * tree-inline.c (initialize_inlined_parameters): Clean up
+ new local variables.
+
+2002-03-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR bootstrap/4128
+ * config/sparc/sparc.c (gen_v9_scc): Move early clobber test
+ before movrXX only, use reg_overlap_mentioned_p.
+ Only special case NE if just one insn can be generated.
+
+2002-03-15 Jason Merrill <jason@redhat.com>
+
+ * varasm.c (assemble_variable): Call resolve_unique_section before
+ checking DECL_SECTION_NAME. Use zeros for a decl with DECL_INITIAL
+ of error_mark_node.
+
+2002-03-15 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/5170
+ * arm.md (split pattern for thumb shiftable immediates): Add comment
+ explaining non-obvious test.
+
+2002-03-15 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/5712
+ * arm.md (movaddr, movaddr_insn): Delete.
+
+2002-03-15 Jason Merrill <jason@redhat.com>
+
+ * toplev.c (wrapup_global_declarations): Clarify variable handling.
+ -fkeep-static-consts doesn't apply to comdats.
+
+2002-03-14 Richard Henderson <rth@redhat.com>
+
+ * c-decl.c: Include c-pragma.h.
+ (start_decl, start_function): Invoke maybe_apply_pragma_weak.
+ (finish_function): Tidy.
+ * c-pragma.c: Include c-common.h.
+ (pending_weaks, apply_pragma_weak, maybe_apply_pragma_weak): New.
+ (handle_pragma_weak): Use them.
+ (init_pragma): Register pending_weaks.
+ * c-pragma.h (maybe_apply_pragma_weak): Declare.
+ * print-tree.c (print_node): Print DECL_WEAK.
+ * varasm.c (mark_weak_decls): Remove.
+ (remove_from_pending_weak_list): Remove.
+ (add_weak): Remove.
+ (asm_emit_uninitialised): Call globalize_decl for weak commons.
+ (weak_decls): Make a tree_list.
+ (declare_weak): Cons weak_decls directly.
+ (globalize_decl): Remove weak_decls elements directly.
+ (weak_finish): Simplify weak_decls walk. Don't weaken unused
+ symbols. Don't pretend to handle aliases.
+ (init_varasm_once): Update weak_decls registry.
+ * Makefile.in: Update dependencies.
+
+2002-03-14 Richard Henderson <rth@redhat.com>
+
+ PR target/5312
+ * config/ia64/ia64.c: Include tm_p.h last.
+ (gen_nop_type): Remove duplicate definition.
+ (cycle_end_fill_slots): Set sched_data for second L slot.
+ (maybe_rotate): Call cycle_end_fill_slots to fill in nop slots.
+ (nop_cycles_until): Fix typos.
+
+2002-03-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR optimization/5891
+ * unroll.c (copy_loop_body) [CALL_INSN]: Copy SIBLING_CALL_P flag.
+
+2002-03-14 David Mosberger <davidm@hpl.hp.com>, Hans Boehm <Hans_Boehm@hp.com>
+
+ * config/ia64/unwind-ia64.c: Handle copy_state and label_state
+ descriptors correctly.
+
+2002-03-14 Michael Meissner <meissner@redhat.com>
+
+ * params.def (PARAM_MAX_UNROLLED_INSNS): New macro, default to
+ 100, allowing MAX_UNROLLED_INSNS to be overridden.
+
+ * params.h (MAX_UNROLLED_INSNS): Define so it can be overridden by
+ --param.
+
+ * unroll.c (params.h): Include.
+ (MAX_UNROLLED_INSNS): Delete, now in params.h.
+
+ * doc/invoke.texi (--param max-unroll-insns): Document.
+
+ * Makefile.in (unroll.o): Add $(PARAMS_H) dependency.
+
+2002-03-14 Richard Earnshaw <rearnsha@arm.com>
+
+ * arm.md: Fix warnings about constraints in peepholes and splits.
+
+2002-03-14 Zack Weinberg <zack@codesourcery.com>
+
+ * cpphash.h (struct lexer_state): Remove line_extension member.
+ * cpplib.c (dequote_string, do_linemarker): New functions.
+ (linemarker_dir): New data object.
+ (DIRECTIVE_TABLE): No longer need to interpret #line in
+ preprocessed source. Delete obsolete comment about return
+ values of handlers.
+ (end_directive, directive_diagnostics, _cpp_handle_directive):
+ Don't muck with line_extension.
+ (directive_diagnostics): No need to issue warnings for
+ linemarkers here.
+ (_cpp_handle_directive): Issue warnings for linemarkers here,
+ when appropriate. Dispatch linemarkers to do_linemarker, not
+ do_line.
+ (do_line): Code to handle linemarkers split out to do_linemarker.
+ Convert escape sequences in filename argument, both places.
+
+ * cppmacro.c (quote_string): Rename cpp_quote_string and
+ export. All callers changed.
+ * cpplib.h (cpp_quote_string): Prototype.
+ * cppmain.c (print_line): Call cpp_quote_string on to_file
+ before printing it.
+
+ * doc/cpp.texi: Document that escapes are now interpreted in
+ #line and in linemarkers, and that non-printing characters are
+ converted to octal escapes when linemarkers are generated.
+
+Thu Mar 14 19:04:29 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * emit-rtl.c (try_split): Use delete_insns.
+ * recog.c (split_all_insns): Fix terminating condition.
+
+2002-03-14 Richard Earnshaw <rearnsha@arm.com>
+ Jeroen Dobbelaere <jeroen.dobbelaere@acunia.com>
+
+ PR target/5828
+ * arm.c (arm_output_epilogue): Fix floating-point register save
+ adjustment when using a frame pointer.
+
+2002-03-14 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/mips/mips.h (FP_INC, UNITS_PER_FPVALUE): New macros.
+ * config/mips/mips.c (compute_frame_size): Retrofit them here.
+ (save_restore_insns, mips_expand_epilogue): And here.
+ (build_mips16_call_stub): And here.
+ (mips_function_value): Use the new macros to decide whether a single
+ or complex float can be returned in floating-point registers. Return
+ a parallel rtx in the complex case.
+
+Thu Mar 14 11:03:12 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * toplev.c (rest_of_compilation): Add CLEANUP_UPDATE_LIFE to cfg_cleanup
+ call after liveness analysis.
+
+ * recog.c (split_insn): Use delete_insn_and_edges.
+
+ * cfgrtl.c (verify_flow_info): Be permisive about non-any_condjump
+ instructions to have branch prediction notes.
+ * ia64reorg.c (ia64_reorg): Do not rebuild CFG.
+
+2002-03-14 Geoffrey Keating <geoffk@redhat.com>
+
+ * configure.in: Don't pass -Wno-long-long to a ADA compiler
+ that doesn't support it.
+ * configure: Regenerate.
+
+2002-03-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/5626
+ * config/sparc/sparc.md (normal_branch, inverted_branch,
+ normal_fp_branch, inverted_fp_branch, normal_fpe_branch,
+ inverted_fp_branch): Adjust calls to output_cbranch.
+ Set length attribute.
+ (normal_int_branch_sp64, inverted_int_branch_sp64): Adjust calls to
+ output_v9branch. Set length attribute.
+ * config/sparc/sparc.c (fcc0_reg_operand, noov_compare64_op): New
+ predicates.
+ (noov_compare_op): Handle CCX_NOOVmode the same way as CC_NOOVmode.
+ (output_cbranch): Likewise. Handle far branches.
+ (output_v9branch): Handle far branches.
+ * config/sparc/sparc-protos.h (output_cbranch, output_v9branch):
+ Adjust prototypes.
+ * config/sparc/sparc.h (PREDICATE_CODES): Add fcc0_reg_operand and
+ noov_compare64_op predicates.
+
+2002-03-13 Jason Merrill <jason@redhat.com>
+
+ * gthr-posix.h (__gthread_active_p): Move __gthread_active_ptr
+ into the function and constify it.
+ * gthr-dce.h, gthr-solaris.h: Likewise.
+
+2002-03-13 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.h (PAD_VARARGS_DOWN): Define.
+ * config/rs6000/rs6000.c (rs6000_va_arg): Use
+ std_expand_builtin_va_arg if not ABI_V4.
+
+2002-03-13 Jason Merrill <jason@redhat.com>
+
+ * varasm.c (globalize_decl): New fn.
+ (assemble_start_function): Use it.
+ (asm_emit_uninitialized): Use it.
+ (assemble_alias): Use it.
+ (assemble_variable): Use it.
+
+2002-03-13 Hans-Peter Nilsson <hp@axis.com>
+
+ * config/cris/cris.c (cris_target_asm_function_prologue): Revert
+ 2002-03-12 internal visibility change.
+ (cris_encode_section_info): Consider MODULE_LOCAL_P when encoding
+ visibility into SYMBOL_REF_FLAG.
+
+2002-03-13 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * expr.c (expand_expr, case NE_EXPR): Do not call copy_to_reg with
+ VOIDmode operand. Add compile-time optimization for constant results.
+
+2002-03-12 Jason Merrill <jason@redhat.com>
+
+ * c-typeck.c (convert_for_assignment): Don't allow conversions
+ between pointers and references. Only allow lvalues to convert to
+ reference.
+
+2002-03-13 Hartmut Penner <hpenner@de.ibm.com>
+
+ * config/s390/s390.h (PROFILE_BEFORE_PROLOGUE): Emit profile code
+ before prologue, to avoid scheduling problems.
+
+2002-03-13 Jakub Jelinek <jakub@redhat.com>
+
+ * config/sparc/sparc.h (INITIAL_FRAME_POINTER_OFFSET): Remove.
+ (ELIMINABLE_REGS): Add sfp->sp.
+ (INITIAL_ELIMINATION_OFFSET): Compute sfp->sp offset too.
+
+2002-03-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR optimization/5892
+ * config/ia64/ia64.c (rotate_one_bundle): Update current packet.
+
+2002-03-13 Jakub Jelinek <jakub@redhat.com>
+
+ * loop.c (basic_induction_var): Don't call convert_modes if mode
+ classes are different.
+
+2002-03-12 Richard Henderson <rth@redhat.com>
+
+ PR optimization/5901
+ * function.c (reposition_prologue_and_epilogue_notes): Position
+ the markers after/before the last/first insn not deleted.
+
+2002-03-12 Richard Henderson <rth@redhat.com>
+
+ PR optimization/5878
+ * config/arc/arc.h, config/cris/cris.h, config/i386/i386.h,
+ config/m68k/m68k.h, config/s390/s390.h, config/sparc/sparc.h
+ (PIC_OFFSET_TABLE_REGNUM): Conditionalize on flag_pic.
+
+ * config/arm/arm.h config/i386/i386.h, config/m68k/m68k.h,
+ config/sparc/sparc.h (CONDITIONAL_REGISTER_USAGE): Set
+ PIC_OFFSET_TABLE_REGNUM based on INVALID_REGNUM not flag_pic.
+
+ * config/arc/arc.h (CONDITIONAL_REGISTER_USAGE): New.
+ * config/arm/arm.c (arm_pic_register): Init to INVALID_REGNUM.
+ (arm_override_options): Set arm_pic_register if TARGET_APCS_STACK
+ also. Don't set it if not flag_pic.
+ * config/i386/i386.c (ix86_save_reg): Trust PIC_OFFSET_TABLE_REGNUM
+ to be INVALID_REGNUM when not used.
+
+2002-03-13 Aldy Hernandez <aldyh@redhat.com>
+
+ * expmed.c (store_bit_field): Reset alias set for memory.
+ (extract_bit_field): Same.
+
+2002-03-12 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * c-common.c (c_tree_code_type, c_tree_code_length,
+ c_tree_code_name, add_c_tree_codes): Delete.
+ * c-common.h (add_c_tree_codes): Delete.
+ * c-lang.c (tree_code_type, tree_code_length, tree_code_name):
+ Define.
+ * c-objc-common.c (c_objc_common_init): Don't call
+ add_c_tree_codes, instead set lang_unsafe_for_reeval.
+ * objc/objc-act.c (objc_tree_code_type, objc_tree_code_length,
+ objc_tree_code_name, add_objc_tree_codes): Delete.
+ (objc_init): Don't call add_objc_tree_codes.
+ * objc/objc-lang.c (tree_code_type, tree_code_length,
+ tree_code_name): Define.
+ * toplev.c (lang_independent_init): Don't set
+ tree_code_length[IDENTIFIER_NODE].
+ * tree.c (tree_code_type, tree_code_length, tree_code_name):
+ Delete definitions, moved to language front-ends.
+ * tree.def (IDENTIFIER_NODE): Hardwire the length.
+ * tree.h (tree_code_type, tree_code_length, tree_code_name):
+ Const-ify.
+ (tree_code_length): Change type to unsigned char.
+
+2002-03-12 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (ix86_expand_prologue): Revert 2002-03-03
+ internal visibility change.
+
+2002-03-12 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.c (xtensa_expand_block_move): Use
+ validize_mem() instead of change_address to avoid clobbering
+ memory attributes.
+
+2002-03-12 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-lex.h (position_after_whitespace): Remove.
+
+2002-03-12 Jakub Jelinek <jakub@redhat.com>
+
+ * c-lex.c (cb_ident, c_lex): Remove unnecessary cast.
+ (lex_string): Use unsigned char pointers.
+
+2002-03-12 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * reload1.c (reload): Ignore MEM REG_EQUIV notes if the equivalent
+ is not a valid memory_operand.
+
+2002-03-12 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa-config.h: Define XCHAL_HAVE_LOOPS.
+ * config/xtensa/lib1funcs.asm: Fix copyright to include
+ special case for libgcc files.
+ (__udivsi3): Avoid loop instructions when XCHAL_HAVE_LOOPS is 0.
+ (__divsi3): Likewise.
+ (__umodsi3): Likewise.
+ (__modsi3): Likewise.
+ * config/xtensa/lib2funcs.S: Fix copyright to include
+ special case for libgcc files.
+
+2002-03-12 Tom Rix <trix@redhat.com>
+
+ * collect2.c (resolve_lib_name): Move outside of
+ OBJECT_FORMAT_COFF ifdef.
+ (ignore_library): Same.
+
+2002-03-12 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/t-xtensa (CRTSTUFF_T_CFLAGS_S): Define.
+
+2002-03-12 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/xtensa.h (ASM_OUTPUT_POOL_PROLOGUE): Switch
+ to function_section before writing out the constant pool.
+
+2002-03-12 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.h (PREDICATE_CODES): Add any_operand and
+ zero_constant.
+ * config/rs6000/rs6000.c (easy_fp_constant): Fix formatting.
+
+2002-03-12 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.md (addsi3): Optimize sign extension.
+ (adddi3): Likewise.
+ (movdf): Likewise.
+ (movdi): Likewise.
+ (cmpsi splitter): Likewise.
+ (modsi3): Fail if <= 0.
+ * config/rs6000/rs6000.c (reg_or_add_cint64_operand): Remove
+ redundant test when HOST_BITS_PER_WIDE_INT != 32.
+ (reg_or_sub_cint64_operand): Likewise.
+ (num_insns_constant_wide): Optimize sign extension.
+ (rs6000_legitimize_address): Likewise.
+
+2002-03-12 Andrew MacLeod <amacleod@redhat.com>
+
+ * config/sparc/linux.h (HANDLE_PRAGMA_PACK_PUSH_POP): Define.
+ * config/sparc/linux64.h (HANDLE_PRAGMA_PACK_PUSH_POP): Define.
+
+2002-03-12 Andrew MacLeod <amacleod@redhat.com>
+
+ * config/sparc/sparc.h (RETURN_ADDR_RTX): Include v9 stack bias in
+ address calculation.
+
+2002-03-12 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.md (reload_insi, reload_indi): Change mode of
+ scratch register to DImode / TImode.
+ config/s390/s390.c (s390_expand_plus_operand): Make sure scratch
+ register used does not overlap the target.
+
+2002-03-12 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Makefile.in (debug.o): Depend on debug.h.
+ * dbxout.c (dbx_debug_hooks, xcoff_debug_hooks): Const-ify.
+ * debug.c (do_nothing_debug_hooks): Likewise.
+ * debug.h (debug_hooks, do_nothing_debug_hooks, dbx_debug_hooks,
+ sdb_debug_hooks, xcoff_debug_hooks, dwarf_debug_hooks,
+ dwarf2_debug_hooks, vmsdbg_debug_hooks): Likewise.
+ * dwarf2out.c (dwarf2_debug_hooks): Likewise.
+ * dwarfout.c (dwarf_debug_hooks): Likewise.
+ * integrate.c (output_inline_function): Likewise.
+ * objc/objc-act.c (synth_module_prologue): Likewise.
+ * sdbout.c (sdb_debug_hooks): Likewise.
+ * toplev.c (debug_hooks): Likewise.
+ * vmsdbgout.c (vmsdbg_debug_hooks): Likewise.
+
+2002-03-12 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * 1750a.h, a29k.h, arc.h, arm.h, c4x.h, clipper.h, cris.h, d30v.h,
+ dsp16xx.h, fr30.h, h8300.h, i370.h, i386.h, i860.h, i960.h,
+ m32r.h, m68hc11.h, m68k.h, m88k.h, mcore.h, mmix.h, mn10300.h,
+ ns32k.h, pa.h, pdp11.h, pj.h, romp.h, s390.h, stormy16.h,
+ v850.h, vax.h, we32k.h, xtensa.h (POINTER_SIZE): Delete.
+ * defaults.h (POINTER_SIZE): Define.
+ * doc/tm.texi (POINTER_SIZE): Document default.
+
+2002-03-12 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * mn10200.h (PTRDIFF_TYPE): Change it to a signed type.
+
+2002-03-11 Richard Henderson <rth@redhat.com>
+
+ * toplev.c (rest_of_compilation): Call purge_all_dead_edges
+ if rebuild_label_notes_after_reload.
+
+2002-03-12 Hans-Peter Nilsson <hp@axis.com>
+
+ * config/cris/cris.c (cris_target_asm_function_prologue): Do not
+ emit pic register load if "internal" visibility.
+ (cris_print_operand): Avoid traditional-warning for 0xffffffff.
+ (cris_expand_builtin_va_arg): Do all computations on trees.
+
+2002-03-11 Richard Henderson <rth@redhat.com>
+
+ * rtlanal.c: Include recog.h.
+ (keep_with_call_p): Fix thinko.
+ * Makefile.in (rtlanal.o): Update dependencies.
+
+2002-03-11 Chris Meyer <cmeyer@gatan.com>
+
+ * genflags.c (gen_insn): Use IS_VSPACE.
+ * genoutput.c (output_insn_data): Likewise.
+ (process_template): Likewise.
+
+2002-03-11 Richard Henderson <rth@redhat.com>
+
+ * toplev.c (rest_of_compilation): Don't compile if we've had errors.
+
+2002-03-11 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in: Update.
+ * doc/cppenv.texi, cppopts.texi: Split out of cpp.texi and gcc.texi.
+ Update documentation.
+ * doc/gcc.texi: Include cppopts.texi and cppenv.texi.
+ * doc/cpp.texi: Include cppopts.texi and cppenv.texi.
+
+2002-03-11 Zack Weinberg <zack@codesourcery.com>
+
+ * Makefile.in: Give texi2pod its input file as a command line
+ argument, not on stdin.
+
+2002-03-11 Dan Nicolaescu <dann@ics.uci.edu>
+ Daniel Berlin <dan@dberlin.org>
+
+ C++ alias analysis improvement.
+ * alias.c (record_component_aliases): Record aliases for base
+ classes too.
+
+2002-03-11 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.h (REG_ALLOC_ORDER): Add missing register.
+
+2002-03-11 Douglas B Rupp <rupp@gnat.com>
+
+ * toplev.c (vms_fopen): Remove, not needed.
+
+ * vmsdbgout.c (lookup_filename): Adjust creation date for GMT.
+
+ * config/alpha/xm-vms.h (__UNIX_FWRITE): Define.
+
+ * config/alpha/alpha.c (alpha_sa_size, VMS): Don't reserve space
+ for FP, already done later.
+
+ * toplev.c (debug_args): Add entry for VMS_DEBUG.
+ * vmsdbgout.c (vmsdbgout_init): Fix typo in call to xmalloc.
+
+2002-03-11 Richard Sandiford <rsandifo@redhat.com>
+
+ * defaults.h (LARGEST_EXPONENT_IS_NORMAL, ROUND_TOWARDS_ZERO): New.
+ (MODE_HAS_NANS, MODE_HAS_INFINITIES): Evaluate to false if
+ LARGEST_EXPONENT_IS_NORMAL for the given mode.
+ (MODE_HAS_SIGN_DEPENDENT_ROUNDING): False when ROUND_TOWARDS_ZERO.
+ * real.c (eadd1): Make rounding dependent on !ROUND_TOWARDS_ZERO.
+ (ediv, emul, eldexp, esqrt): Likewise.
+ (etoe113, etoe64, etoe53, etoe24, etodec, etoibm, etoc4x): Likewise.
+ (e24toe): Only check NaNs & infinities if !LARGEST_EXPONENT_IS_NORMAL.
+ (saturate): New function.
+ (toe53, toe24): Saturate on overflow if LARGEST_EXPONENT_IS_NORMAL.
+ (make_nan): Use a saturation value instead of a NaN if
+ LARGEST_EXPONENT_IS_NORMAL. Warn when this happens.
+ * fp-bit.c (pack_d): Saturate on NaN, infinite or overflowing
+ inputs if LARGEST_EXPONENT_IS_NORMAL. Represent subnormals as
+ zero if NO_DENORMALS. Only round to nearest if !ROUND_TOWARDS_ZERO.
+ (unpack_d): No NaNs or infinities if LARGEST_EXPONENT_IS_NORMAL.
+ (_fpmul_parts, _fpdiv_parts): Only round to nearest if
+ !ROUND_TOWARDS_ZERO.
+ * doc/tm.texi (LARGEST_EXPONENT_IS_NORMAL): Document.
+ (ROUND_TOWARDS_ZERO): Document.
+
+2002-03-11 Andreas Jaeger <aj@suse.de>
+
+ * cfg.c (dump_flow_info): Remove unused variable.
+
+2002-03-11 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.c (mmix_expand_builtin_va_arg): Do all
+ computations on trees.
+
+2002-03-10 Richard Henderson <rth@redhat.com>
+
+ PR 5693:
+ * reload.c (copy_replacements_1): New.
+ (copy_replacements): Use it to recurse through the rtx.
+
+2002-03-10 Richard Henderson <rth@redhat.com>
+
+ * loop.c (strength_reduce): Compute number of iterations as
+ unsigned HOST_WIDE_INT.
+
+2002-03-10 Richard Henderson <rth@redhat.com>
+
+ * sched-rgn.c (add_branch_dependences): Don't allow insns that throw
+ to move away from the end of the block.
+
+2002-03-10 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ PR preprocessor/5899
+ * cppinit.c (init_dependency_output): Don't ignore -dM etc.
+
+2002-03-10 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * mbchar.c (JIS_state_table, JIS_action_table): Const-ify.
+
+ * attribs.c (decl_attributes): Fix signed/unsigned warning.
+
+2002-03-10 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.c: Improve comments.
+ (mmix_target_asm_function_prologue): Drop variable
+ empty_stack_frame. Don't allocate unused slot above fp.
+ (mmix_target_asm_function_epilogue): Mirror prologue changes.
+ * config/mmix/mmix.h (MMIX_GNU_ABI_REG_ALLOC_ORDER): Don't have
+ brace in first column.
+ (enum reg_class): Ditto.
+ (FIRST_PARM_OFFSET): Now 0.
+ (USER_LABEL_PREFIX): Remove #if 0:d definition.
+
+2002-03-10 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * combine.c (make_extraction): Fix error in last change.
+
+2002-03-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * c4x.c (c4x_fp_reglist): Const-ify.
+ * cris.c (cris_print_operand): Likewise.
+ * i386.c (ix86_va_arg): Likewise.
+ * ia64/unwind-ia64.c (unw_decode_table): Likewise.
+ * m32r.c (m32r_hard_regno_mode_ok): Likewise.
+ * m32r.h (m32r_hard_regno_mode_ok): Likewise.
+ * mcore.c (regno_reg_class, mcore_unique_section): Likewise.
+ * mcore.h (regno_reg_class): Likewise.
+ * mips.c (gen_int_relational): Likewise.
+ * ns32k.c (ns32k_reg_class_contents, regclass_map): Likewise.
+ * ns32k.h (ns32k_reg_class_contents, regclass_map): Likewise.
+ * pdp11.c (move_costs): Likewise.
+ * pj.h (INITIALIZE_TRAMPOLINE): Likewise.
+ * s390.c (s390_branch_condition_mnemonic, regclass_map):
+ Likewise.
+ * s390.h (regclass_map): Likewise.
+ * sh.c (shift_amounts): Likewise.
+ * sh.md (rotlsi3): Likewise.
+
+2002-03-09 Geoffrey Keating <geoffk@redhat.com>
+
+ * config/rs6000/rs6000.md (ne0+4): Add extra CLOBBER.
+ (ne0+5): Use new clobber to generate proper shift pattern.
+ Patch by Michael Matz <matz@kde.org>.
+
+2002-03-09 Andreas Schwab <schwab@suse.de>
+
+ * gcc.c (validate_all_switches): Also handle `%W{...}'.
+
+2002-03-09 Geoffrey Keating <geoffk@redhat.com>
+
+ * config/rs6000/sysv4.h (BIGGEST_ALIGNMENT): Don't define.
+
+2002-03-09 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/5877
+ * expr.c (highest_pow2_factor): Check TREE_INT_CST_LOW
+ even for non-representable constants.
+
+Sat Mar 9 07:20:01 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * emit-rtl.c (copy_most_rtx): Accept EXPR_LIST for may_share.
+ * function.c (fixup_var_refs): Add MAY_SHARE parameter.
+ (fixup_var_refs_insns, fixup_var_refs_insns_with_has): Likewise.
+ (fixup_var_refs_insn, fixup_var_refs_1): Likewise.
+ (pop_function_context): Compute MAY_SHARE parameter for
+ fixup_var_refs.
+ (fixup_var_refs_1, case MEM): Pass MAY_SHARE to copy_most_rtx, not VAR.
+ (gen_mem_addressof): Call fixup_var_refs with new parm.
+
+ * combine.c (make_extraction): Don't make extension of CONST_INT.
+
+2002-03-09 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/mips/mips.c (function_arg_pass_by_reference): Force to 0
+ in o32 and o64 ABIs.
+ * config/mips/abi64.h (MUST_PASS_IN_STACK): Define as in expr.h,
+ but getting fixed-size structs passed in registers regardless of
+ padding in o32 and o64 ABIs.
+
+ * config/mips/mips.c (mips_va_arg): Apply big-endianness address
+ offset before loading address of argument passed by transparent
+ reference.
+
+2002-03-08 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * t-pa64 (LIB1ASMFUNCS, LIB1ASMSRC): Delete.
+
+2002-03-09 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/mips/mips.c (mips_expand_prologue): Set regno of vararg
+ marker such that registers after it are saved.
+
+2002-03-08 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * sparc.c (arith_4096_operand): Fix error in last change.
+
+2002-03-08 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/mips/mips.h (SUBTARGET_CPP_SIZE_SPEC): Remove duplicate
+ defaults for MEABI.
+
+2002-03-08 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c (rs6000_va_arg): Fix alignment for
+ vectors.
+
+2002-03-08 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/sysv4.h (BIGGEST_ALIGNMENT): Change for altivec.
+
+Fri Mar 8 21:27:49 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgrtl.c (purge_dead_edges): Set BB_DRITY flags if edge has been
+ removed; fix return value.
+ * combine.c (combine_instructions): Dirtify blocks where we failed to
+ update liveness; purge dead edges; use update_life_info_in_dirty_blocks.
+ * toplev.c (rest_of_compilation): Do not purge_dead_edges after combine.
+
+2002-03-08 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * gcse.c (insert_insn_end_bb): Fix typo in last change.
+
+Fri Mar 8 21:08:52 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * recog.c (peephole2_optimize): Re-distribute EH edges.
+
+2002-03-08 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * expr.c (expand_expr): Use unsave lang hook.
+ * langhooks-def.h (LANG_HOOKS_UNSAVE): New.
+ (LANG_HOOKS_INITIALIZER): Update.
+ * langhooks.h (struct lang_hooks): New hook unsave.
+ * tree.c (lang_unsave, lang_unsave_expr_now): Remove.
+ (unsave_expr_1): Remove unused lang_unsave_expr_now.
+ (unsave_expr_now_r): Rename lhd_unsave. Update. Return input.
+ (unsave_expr_now): Remove.
+ * tree.h (unsave_expr_now, lang_unsave,
+ lang_unsave_expr_now): Remove.
+ (lhd_unsave): New.
+
+2002-03-08 Andreas Jaeger <aj@suse.de>
+
+ * flow.c (propagate_block_delete_insn): Remove unused variable.
+
+2002-03-08 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (h8300_adjust_insn_length): Tighten
+ insn length for memory load/store.
+
+2002-03-08 Craig Rodrigues <rodrigc@gcc.gnu.org>
+
+ * doc/install.texi (--with-libiconv-prefix): Document.
+
+2002-03-08 Michael Y. Brukman <myb2@cornell.edu>
+
+ * doc/sourcebuild.texi: Fix typo.
+
+2002-03-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/3711
+ * builtins.c (std_expand_builtin_va_arg): Do all computations on
+ trees.
+
+Fri Mar 8 06:48:45 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * rtl.c (copy_most_rtx): Move from here ...
+ * emit-rtl.c (copy_most_rtx): ... to here.
+
+2002-03-08 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/mips/mips.h (LONG_MAX_SPEC): Rewrite, along with
+ SUBTARGET_CPP_SIZE_SPEC.
+ * config/mips/abi64.h (LONG_MAX_SPEC): Delete.
+
+ * config/mips/mips.h (SUBTARGET_CPP_SIZE_SPEC): Simplify.
+
+2002-03-07 Matt Hiller <hiller@redhat.com>
+
+ * gensupport.c (first_dir_md_include): Renamed from include;
+ change all references.
+ (last_dir_md_include): Renamed from last_include; change all
+ references.
+ (init_md_reader): Unconditionally initialize base_dir whether or
+ not filename is a relative path.
+
+2002-03-07 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/fp-bit.c (_unord_f2): Compile it in even if
+ US_SOFTWARE_GOFAST is enabled.
+
+ * config/gofast.h (GOFAST_RENAME_LIBCALLS): Set gt and ge as
+ NULL_RTX. Set all HFmode operations as NULL_RTX.
+ * optabs.c (prepare_float_lib_cmp) <GT, GE, LT, LE>: If libfunc is
+ NULL_RTX, try reversing the comparison and the operands.
+
+2002-03-06 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * genextract.c (walk_rtx): Recurse into MATCH_PAR_DUP.
+ genoutput.c (scan_operands): Recurse into MATCH_PAR_DUP
+ and MATCH_OP_DUP.
+
+Thu Mar 7 16:54:10 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * reload1.c (reload_cse_delete_noop_set): Purge dead edges.
+
+Thu Mar 7 16:33:54 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * basic-block.h (fixup_abnormal_edges): Declare.
+ * reload1.c (fixup_abnormal_edges): New function.
+ * reg-stack.c (convert_regs): Use it.
+
+ * gcse.c (insert_insn_end_bb): Handle trapping insns.
+
+ * gcse.c (hash_scan_set): Refuse instructions with EH edges.
+
+2002-03-07 Richard Sandiford <rsandifo@redhat.com>
+
+ * defaults.h (MODE_HAS_NANS, MODE_HAS_INFINITIES): New.
+ (MODE_HAS_SIGNED_ZEROS, MODE_HAS_SIGN_DEPENDENT_ROUNDING): New.
+ * flags.h (HONOR_NANS, HONOR_INFINITIES, HONOR_SIGNED_ZEROS): New.
+ (HONOR_SIGN_DEPENDENT_ROUNDING): New.
+ * builtins.c (expand_builtin_mathfn): Use HONOR_NANS.
+ * c-common.c (truthvalue_conversion): Reduce x - y != 0 to x != y
+ unless x and y could be infinite.
+ (expand_unordered_cmp): New, mostly split from expand_tree_builtin.
+ Check that the common type of both arguments is a real, even for
+ targets without unordered comparisons. Allow an integer argument
+ to be compared against a real.
+ (expand_tree_builtin): Use expand_unordered_cmp.
+ * combine.c (combine_simplify_rtx): Use the new HONOR_... macros.
+ * cse.c (fold_rtx): Likewise. Fix indentation.
+ * fold-const.c (fold_real_zero_addition_p): New.
+ (fold): Use it, and the new HONOR_... macros.
+ * ifcvt.c (noce_try_minmax): Use the new HONOR_... macros.
+ * jump.c (reversed_comparison_code_parts): After searching for
+ the true comparison mode, use HONOR_NANS to decide whether it
+ can be safely reversed.
+ (reverse_condition_maybe_unordered): Remove IEEE check.
+ * simplify-rtx.c (simplify_binary_operation): Use the new macros
+ to decide which simplifications are valid. Allow the following
+ simplifications for IEEE: (-a + b) to (b - a), (a + -b) to (a - b),
+ and (a - -b) to (a + b).
+ (simplify_relational_operation): Use HONOR_NANS.
+ * doc/tm.texi: Document the MODE_HAS_... macros.
+
+2002-03-07 Richard Earnshaw <rearnsha@arm.com>
+
+ * combine.c (simplify_comparison): If simplifying a logical shift
+ right and compare with constant, force the comparison to unsigned.
+
+2002-03-07 Aldy Hernandez <aldyh@redhat.com>
+
+ * doc/invoke.texi: Add documentation for -mabi=no-altivec.
+
+ * config/rs6000/rs6000.c (rs6000_parse_abi_options): Add
+ -mabi=no-altivec
+ (alt_reg_names): Remove % for vrsave.
+
+2002-03-06 Richard Henderson <rth@redhat.com>
+
+ PR optimization/5844
+ * genemit.c (gen_exp): New argument used. Invoke copy_rtx
+ if used indicates we've already emitted one copy of an operand.
+ (gen_insn, gen_expand, output_add_clobbers): Supply a null used.
+ (gen_split): Supply a non-null used.
+
+2002-03-06 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * reload1.c (reload): Unshare all rtl after reload is done.
+
+ * simplify-rtx.c (simplify_plus_minus): Do not abort,
+ but simply fail if the expression is too complex to simplify.
+ (simplify_gen_binary): Handle simplify_plus_minus failures.
+
+Wed Mar 6 20:32:09 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * toplev.c (rest_of_compilation): Do jump threading before SSA path;
+ consistently call delete_trivially_dead_insns after CSE and GCSE;
+ fix DFI_life dumping; do jump threading after liveness; do crossjumping
+ after liveness2; update comment in last crossjumping.
+ * cfgcleanup.c (try_crossjump_to_edge): Dirtify block.
+
+Wed Mar 6 12:27:10 2002 Jeffrey A Law (law@redhat.com)
+
+ * ssa-ccp.c (ssa_fast_dce): Update the DF def-use chains
+ after completing fast dead code elimination.
+
+ * m68k.h (CONST_COSTS): Lower cost of 0.0 when used inside a
+ COMPARE operator.
+
+2002-03-06 Phil Edwards <pme@gcc.gnu.org>
+
+ * version.c: Fix misplaced leading blanks on first line.
+
+Wed Mar 6 19:08:03 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgrtl.c (verify_flow_info): Accept RESX as EH edge source.
+
+Wed Mar 6 18:14:43 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgcleanup.c (mentions_nonequal_regs): New function.
+ (thread_jump): Use it.
+ * toplev.c (rest_of_compilation): Run jump threading after
+ liveness.
+
+2002-03-06 Jakub Jelinek <jakub@redhat.com>
+
+ * ssa-ccp.c (ssa_ccp_substitute_constants): Backout 2002-03-05
+ patch.
+
+Wed Mar 6 11:28:19 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * predict.c (estimate_bb_frequencies): Do not reload the
+ frequencies from notes.
+
+Wed Mar 6 10:59:39 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgrtl.c (delete_insn_and_edges, delete_insn_chain_and_edges): New.
+ * rtl.h (delete_insn_and_edges, delete_insn_chain_and_edges): Declare
+
+ * basic-block.h (update_life_info, update_life_info_in_dirty_blocks,
+ delete_noop_moves): Return indeger.
+ * flow.c (ndead): New variable.
+ (propagate_block_delete_insn): Use delete_insn_and_edges; remove
+ BB argument; update callers.
+ (propagate_block_delete_libcall): Use delete_insn_chain_and_edges.
+ (life_analysis): Do not call purge_all_dead_edges.
+ (update_life_info): Return number of deleted insns; print statistics.
+ (update_life_info_in_dirty_blocks): likewise.
+ (delete_noop_moves): Use delete_insn_and_edges; print statistics;
+ return number of insns deleted.
+
+ * cse.c: Include timevar.h
+ (delete_trivially_dead_insns): Kill preserve_basic_blocks argument;
+ iterate until stabilizes; print statistics; return number of killed
+ insns.
+ * Makefile.in: (cse.o): Add timevar.h dependency
+ * rtl.h (delete_trivially_dead_insns): New.
+ * timever.def: Add TV_DELETE_TRIVIALLY_DEAD timer.
+ * toplev.c (rest_of_compilation): Update callers.
+
+ * cfgcleanup.c (try_optimize_cfg): Kill blocks.
+ (try_optimize_cfg): Do not update liveness.
+ (cleanup-cfg): Loop until try_optimize_cfg and dead code
+ removal stabilizes; use delete_trivially_dead_insns.
+
+ * cfgrtl.c (verify_flow_info): Sanity check outgoing edges.
+
+2002-03-05 Zack Weinberg <zack@codesourcery.com>
+
+ * cppmain.c (setup_callbacks): Disable #pragma and #ident
+ callbacks when processing assembly language.
+
+2002-03-05 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.h (ASM_FILE_END): Define.
+ * som.h (ASM_FILE_END): Delete.
+
+ * pa.c (function_arg): Don't pass floats in general registers in
+ indirect calls if TARGET_ELF32.
+
+2002-03-05 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.md (floatsidf2): Conditionalize on hard-float.
+
+2002-03-05 Danny Smith <dannysmith@users.sourceforge.net>
+
+ * gthr-win32.h (__GTHREAD_MUTEX_INIT_DEFAULT): Define.
+
+2002-03-05 Jakub Jelinek <jakub@redhat.com>
+
+ * mklibgcc.in: Prepend a tab before .hidden, add $flags to gcc
+ -r command line. Don't hide any symbols if not building
+ shared libgcc.
+
+Tue Mar 5 18:31:27 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfg.c (dump_flow_info): Warn about profile mismatches.
+ * cfgrtl.c (verify_flow_info): Few aditional sanity checks.
+ (purge_dead_edges): Remove REG_BR_PROB notes on simplejumps.
+
+2002-03-05 Jakub Jelinek <jakub@redhat.com>
+
+ * expmed.c (emit_store_flag): Don't test BITS_PER_WORD * 2
+ wide volatile memory by parts.
+
+2002-03-05 Jakub Jelinek <jakub@redhat.com>
+
+ * ssa-ccp.c (ssa_ccp_substitute_constants): Don't crash if def
+ is NULL.
+
+2002-03-05 Richard Henderson <rth@redhat.com>
+
+ * rs6000.h (TOTAL_ALTIVEC_REGS): Fix off-by-one error.
+
+2002-03-04 Geoffrey Keating <geoffk@redhat.com>
+
+ * toplev.c (documented_lang_options): Document more
+ language-specific options.
+ * doc/invoke.texi (Warning Options): Correct documentation for
+ -Wno-multichar, -Wno-div-by-zero, and -Wsystem-headers.
+ * c-decl.c (c_decode_option): Use a table to handle warning options.
+
+2002-03-05 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.h (ENCODE_SECTION_INFO): Pass on new second
+ parameter to mmix_encode_section_info.
+ (LINK_SPEC): Don't defsym __.MMIX.start..text if linking
+ relocatably. Always produce ELF, not mmo if linking relocatably.
+ * config/mmix/mmix.c (mmix_encode_section_info): If new parameter
+ first is nonzero, don't add symbol prefix.
+ * config/mmix/mmix-protos.h (mmix_encode_section_info): Tweak
+ prototype accordingly.
+
+2002-03-04 Krister Walfridsson <cato@df.lth.se>
+
+ * config.gcc (*-*-netbsd*): Add t-slibgcc-elf-ver to tmake_file.
+
+2002-03-05 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * configure.in: Increase required makeinfo version to 4.1.
+ * configure: Regenerate.
+
+2002-03-04 Geoffrey Keating <geoffk@redhat.com>
+
+ * .cvsignore: Remove *.info* and genrtl*; these files are generated
+ elsewhere now.
+
+2002-03-04 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/include/texinfo.tex: Update to version 2002-03-01.06.
+ * doc/invoke.texi: Fix @math uses.
+
+Mon Mar 4 15:33:54 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * toplev.c (rest_of_compilation): Cleanup CFG after dead jumptables
+ removal
+
+2002-03-03 Aldy Hernandez <aldyh@redhat.com>
+
+ * config.gcc (powerpc-*-eabialtivec*): Use t-ppcendian.
+ (powerpc-*-eabisimaltivec*): Same.
+
+ * config/rs6000/t-ppcendian: New.
+
+2002-03-04 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+
+ * c4x-protos.h, c4x.h, c4x.c, c4x.md: Add new functions
+ nonimmediate_src_operand and nonimmediate_lsrc_operand to
+ disallow ZERO_EXTEND with CONST_INT or CONST_DOUBLE.
+
+2002-03-03 Richard Henderson <rth@redhat.com>
+
+ * toplev.c (rest_of_decl_compilation): Revert last two changes.
+
+2002-03-03 Zack Weinberg <zack@codesourcery.com>
+
+ * emit-rtl.c, final.c, fold-const.c, gengenrtl.c, optabs.c,
+ print-tree.c, real.c, real.h, recog.c, rtl.c, simplify-rtx.c,
+ tree.c, config/m68k/m68k.c:
+ Remove all #ifndef REAL_ARITHMETIC blocks, make all #ifdef
+ REAL_ARITHMETIC blocks unconditional. Delete some further
+ #ifdef blocks predicated on REAL_ARITHMETIC.
+ * flags.h, toplev.c: Delete remaining references to
+ flag_pretend_float.
+
+ * doc/invoke.texi: Remove documentation of -fpretend-float.
+ * doc/tm.texi: Describe the various REAL_* macros as provided by
+ real.h, not by the target configuration files.
+
+ * config/alpha/alpha.h, config/alpha/unicosmk.h, config/arm/arm.h,
+ config/avr/avr.h, config/c4x/c4x.h, config/convex/convex.h,
+ config/cris/cris.h, config/d30v/d30v.h, config/dsp16xx/dsp16xx.h,
+ config/h8300/h8300.h, config/i370/i370.h, config/i386/i386.h,
+ config/i386/osf1elf.h, config/i960/i960.h, config/ia64/ia64.h,
+ config/m32r/m32r.h, config/m68hc11/m68hc11.h, config/m68k/dpx2.h,
+ config/m68k/linux-aout.h, config/m68k/linux.h, config/m68k/m68k.h,
+ config/m68k/sun3.h, config/m68k/vxm68k.h, config/mcore/mcore.h,
+ config/mips/mips.h, config/mmix/mmix.h, config/mn10200/mn10200.h,
+ config/mn10300/mn10300.h, config/pa/pa.h, config/pj/pj.h,
+ config/rs6000/rs6000.h, config/s390/s390.h, config/sh/sh.h,
+ config/sparc/freebsd.h, config/sparc/linux.h, config/sparc/linux64.h,
+ config/sparc/sol2.h, config/sparc/sparc.h, config/sparc/vxsim.h,
+ config/stormy16/stormy16.h, config/v850/v850.h, config/vax/vax.h,
+ config/xtensa/xtensa.h:
+ Do not define, undefine, or mention in comments any of
+ REAL_ARITHMETIC, REAL_VALUE_ATOF, REAL_VALUE_HTOF,
+ REAL_VALUE_ISNAN, REAL_VALUE_ISINF,
+ REAL_VALUE_TO_TARGET_SINGLE, REAL_VALUE_TO_TARGET_DOUBLE,
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE, REAL_VALUE_TO_DECIMAL,
+ REAL_VALUE_TYPE, REAL_VALUES_EQUAL, REAL_VALUES_LESS,
+ REAL_VALUE_LDEXP, REAL_VALUE_FIX, REAL_VALUE_UNSIGNED_FIX,
+ REAL_VALUE_RNDZINT, REAL_VALUE_UNSIGNED_RNDZINT,
+ REAL_INFINITY, REAL_VALUE_NEGATE, REAL_VALUE_TRUNCATE,
+ REAL_VALUE_TO_INT, or REAL_VALUE_FROM_INT.
+
+2002-03-03 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * 1750a.h, a29k.h, alpha.h, arc.h, arm.h, avr.h, c4x.h, clipper.h,
+ convex.h, cris.h, d30v.h, dsp16xx.h, elxsi.h, fr30.h, h8300.h,
+ i370.h, i386.h, i860.h, i960.h, ia64.h, m32r.h, m68hc11.h, m68k.h,
+ m88k.h, mcore.h, mips.h, mmix.h, mn10200.h, mn10300.h, ns32k.h,
+ pa.h, pdp11.h, pj.h, romp.h, rs6000.h, s390.h, sh.h, sparc.h,
+ stormy16.h, v850.h, vax.h, we32k.h, xtensa.h (BITS_PER_WORD):
+ Delete.
+ * defaults.h (BITS_PER_WORD): Define.
+ * doc/tm.texi (BITS_PER_WORD): Document default value.
+
+ * 1750a.h, avr.h, convex.h, d30v.h, dsp16xx.h, fr30.h, ia64.h,
+ m68hc11.h, m88k.h, mips.h, pdp11.h, rs6000.h, sparc.c,
+ stormy16.h, xtensa.h, vmsdbgout.c (CHAR_TYPE_SIZE): Delete.
+
+2002-03-03 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * attribs.c (init_attributes, decl_attributes): Use ARRAY_SIZE in
+ lieu of explicit sizeof/sizeof.
+ * i386.c (override_options, ix86_init_mmx_sse_builtins,
+ ix86_expand_builtin): Likewise.
+ * mips.c (mips_add_gc_roots): Likewise.
+ * mmix.c (mmix_output_condition): Likewise.
+ * rs6000.c (rs6000_override_options, altivec_expand_builtin,
+ altivec_init_builtins): Likewise.
+ * sparc.c (mark_ultrasparc_pipeline_state): Likewise.
+ * cppexp.c (Nsuff, parse_number): Likewise.
+ * cppinit.c (builtin_array_end): Likewise.
+ * gcc.c (n_default_compilers, process_command): Likewise.
+ * genpreds.c (output_predicate_decls): Likewise.
+ * ggc-page.c (NUM_EXTRA_ORDERS): Likewise.
+ * lcm.c (N_ENTITIES): Likewise.
+ * stor-layout.c (set_sizetype): Likewise.
+
+2002-03-03 Richard Henderson <rth@redhat.com>
+
+ * toplev.c (rest_of_decl_compilation): Do not invoke make_decl_rtl
+ for types or labels.
+
+2002-03-03 Richard Henderson <rth@redhat.com>
+
+ * c-decl.c (start_decl): Initialized variables are not common.
+
+2002-03-02 Per Bothner <per@bothner.com>
+
+ * gcc.c (option_map): Suport new --bootclasspath option.
+ --CLASSPATH is now just an alias for --classpath.
+
+2002-03-02 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.h (ix86_expand_prologue): Do not emit pic register
+ load if "internal" visibility.
+ * doc/extend.texi: Document visibility meanings.
+
+2002-03-02 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.h (ENCODE_SECTION_INFO): MODULE_LOCAL_P applies
+ to functions as well.
+
+2002-03-02 Richard Henderson <rth@redhat.com>
+
+ * attribs.c (handle_alias_attribute): Don't call assemble_alias.
+ (handle_visibility_attribute): Don't call assemble_visibility.
+ * toplev.c (rest_of_decl_compilation): Invoke make_decl_rtl even
+ without asmspec. Invoke assemble_alias when needed.
+ * varasm.c (maybe_assemble_visibility): New.
+ (assemble_start_function, assemble_variable, assemble_alias): Use it.
+
+2002-03-02 Richard Henderson <rth@redhat.com>
+
+ * varasm.c (make_decl_rtl): Remove call to REDO_SECTION_INFO_P;
+ invoke ENCODE_SECTION_INFO with first call flag.
+
+ * config/darwin-protos.h, config/darwin.c, config/darwin.h,
+ config/a29k/a29k.h, config/alpha/alpha-protos.h, config/alpha/alpha.c,
+ config/alpha/alpha.h, config/arc/arc.h, config/arm/arm-protos.h,
+ config/arm/arm.h, config/arm/pe.c, config/arm/pe.h,
+ config/avr/avr-protos.h, config/avr/avr.c, config/avr/avr.h,
+ config/c4x/c4x-protos.h, config/c4x/c4x.c, config/c4x/c4x.h,
+ config/cris/cris-protos.h, config/cris/cris.c, config/cris/cris.h,
+ config/d30v/d30v.h, config/h8300/h8300.h, config/i370/i370.h,
+ config/i386/cygwin.h, config/i386/i386-interix.h, config/i386/i386.h,
+ config/i386/osfrose.h, config/i386/win32.h, config/i386/winnt.c,
+ config/ia64/ia64-protos.h, config/ia64/ia64.c, config/ia64/ia64.h,
+ config/m32r/m32r-protos.h, config/m32r/m32r.c, config/m32r/m32r.h,
+ config/m68hc11/m68hc11-protos.h, config/m68hc11/m68hc11.c,
+ config/m68hc11/m68hc11.h, config/m88k/m88k.h,
+ config/mcore/mcore-protos.h, config/mcore/mcore.c,
+ config/mcore/mcore.h, config/mips/mips.h, config/ns32k/ns32k.h,
+ config/pa/pa.h, config/romp/romp.h, config/rs6000/linux64.h,
+ config/rs6000/rs6000-protos.h, config/rs6000/rs6000.c,
+ config/rs6000/sysv4.h, config/rs6000/xcoff.h, config/s390/s390.h,
+ config/sh/sh.h, config/sparc/sparc.h,
+ config/stormy16/stormy16-protos.h, config/stormy16/stormy16.c,
+ config/stormy16/stormy16.h, config/v850/v850.h, config/vax/vms.h,
+ config/xtensa/xtensa.h, doc/tm.texi: ENCODE_SECTION_INFO now takes
+ FIRST argument. As needed, examine it and do nothing.
+
+ * config/darwin.h, config/alpha/alpha.h, config/arm/pe.h,
+ config/i386/cygwin.h, config/ia64/ia64.h, config/m68hc11/m68hc11.h,
+ config/mcore/mcore.h: Remove REDO_SECTION_INFO_P.
+
+ * config/arm/t-pe (pe.o): Add dependencies.
+
+2002-03-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * a29k.h, alpha.h, arc.h, arm.h, avr.h, clipper.h, convex.h,
+ cris.h, d30v.h, elxsi.h, fr30.h, h8300.h, i370.h, i386.h, i860.h,
+ i960.h, ia64.h, m32r.h, m68hc11.h, m68k.h, m88k.h, mcore.h,
+ mips.h, mmix.h, mn10200.h, mn10300.h, ns32k.h, pa.h, pdp11.h,
+ pj.h, romp.h, rs6000.h, s390.h, sh.h, sparc.h, stormy16.h, v850.h,
+ vax.h, we32k.h, xtensa.h: (BITS_PER_UNIT): Delete.
+ * defaults.h (BITS_PER_UNIT): Define.
+ * doc/tm.texi (BITS_PER_UNIT): Document default value.
+
+2002-03-02 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300-protos.h: Add a prototype for
+ compute_a_shift_length.
+ * config/h8300/h8300.c (h8300_asm_insn_count): New.
+ (compute_a_shift_length): Likewise.
+ (h8300_adjust_insn_length): Do not adjust insn length of shift
+ insns.
+ * config/h8300/h8300.md (anonymous shift patterns): Use
+ compute_a_shift_length.
+
+Sat Mar 2 06:30:14 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * config/sparc/sparc.c (sparc_initialize_trampoline): Use
+ trunc_int_for_mode.
+
+ * emit-rtl.c (offset_address): Call update_temp_slot_address.
+
+2002-03-01 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * Makefile.in (CRTSTUFF_CFLAGS): Add -fno-zero-initialized-in-bss.
+ * doc/invoke.texi (-fno-zero-initialized-in-bss): Document.
+ * flags.h (flag_zero_initialized_in_bss): Declare.
+ * toplev.c (flag_zero_initialized_in_bss): New flag.
+ (lang_independent_options): Add flag_zero_initialized_in_bss.
+ * tree.c (initializer_zerop): New function.
+ * tree.h (initializer_zerop): Declare.
+ * varasm.c (assemble_variable): If we can emit bss, put zero
+ initializers in the bss section.
+
+2002-03-02 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.h (ASM_WEAKEN_DECL): AIX assembler doesn't
+ like more than one symbol per .weak directive.
+
+2002-03-01 Richard Henderson <rth@redhat.com>
+
+ * config/ia64/ia64.c (ia64_initial_elimination_offset): Do not
+ adjust argument_pointer by pretend_args_size.
+ (ia64_va_start): Adjust va_start address by -pretend_args_size.
+
+2002-03-01 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (h8300_adjust_insn_length): Clean up.
+
+Fri Mar 1 20:59:14 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * toplev.c (rest_of_compilation): Delete dead jumptables before
+ loop.
+ * flow.c (delete_dead_jumptables): Make global.
+ * rtl.h (delete_dead_jumptables): Declare.
+
+2002-03-01 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.h (HANDLE_PRAGMA_PACK): Delete.
+ * config/rs6000/darwin.h (HANDLE_SYSV_PRAGMA): Define.
+ * config/rs6000/xcoff.h (COLLECT_EXPORT_LIST): Delete.
+
+2002-03-01 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300-protos.h: Fix formatting.
+ * config/h8300/h8300.c: Likewise.
+ * config/h8300/h8300.h: Likewise.
+
+2002-03-01 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (print_operand): Support 16-bit
+ constant addresses.
+ * config/h8300/h8300.h (TINY_CONSTANT_ADDRESS_P): New.
+
+2002-02-28 Richard Henderson <rth@redhat.com>
+
+ * expmed.c (store_bit_field): Prevent generation of CONCATs;
+ pun complex values as integers; use gen_lowpart instead of
+ gen_rtx_SUBREG.
+ (extract_bit_field): Likewise.
+
+2002-03-01 Alan Modra <amodra@bigpond.net.au>
+ David Edelsohn <edelsohn@gnu.org>
+
+ * doc/tm.texi (ASM_WEAKEN_DECL): Document.
+ (ASM_WEAKEN_LABEL): Mention ASM_WEAKEN_DECL.
+ (SUPPORTS_WEAK): Likewise.
+ * output.h (add_weak): Add tree param.
+ * varasm.c (add_weak): Likewise. Save decl.
+ (struct weak_syms): Add decl field.
+ (mark_weak_decls): New function.
+ (init_varasm_once): ggc_add_root mark_weak_decls.
+ (assemble_start_function): Use ASM_WEAKEN_DECL.
+ (assemble_variable): Likewise.
+ (assemble_alias): Likewise.
+ (declare_weak): Pass decl to add_weak.
+ (weak_finish): Use ASM_WEAKEN_DECL. Try to find decl.
+ (remove_from_pending_weak_list): Declare and define for
+ ASM_WEAKEN_DECL.
+ * c-pragma.c (handle_pragma_weak): Adjust add_weak call.
+ * c-pragma.h (HANDLE_PRAGMA_WEAK): Define if ASM_WEAKEN_DECL too.
+ * defaults.h (SUPPORTS_WEAK): Likewise.
+ * config/rs6000/linux64.h (ASM_DECLARE_FUNCTION_NAME): Don't emit
+ .weak for code sym. Do emit .size for descriptor sym.
+ (ASM_DECLARE_FUNCTION_SIZE): Define.
+ * config/rs6000/rs6000.h (ASM_WEAKEN_DECL): Define.
+ (ASM_OUTPUT_DEF_FROM_DECLS): Don't emit .weak here. Don't output
+ .lglobl unless TARGET_XCOFF. Formatting fixes.
+ * config/rs6000/xcoff.h (ASM_DECLARE_FUNCTION_NAME): Don't emit
+ .weak for code sym.
+ (HANDLE_PRAGMA_WEAK): Remove.
+ (ASM_WEAKEN_LABEL): Remove.
+ * config/rs6000/aix.h (HANDLE_SYSV_PRAGMA): Define.
+
+2002-03-01 Jason Merrill <jason@redhat.com>
+
+ * tree.h (TARGET_EXPR_SLOT, TARGET_EXPR_INITIAL): New macros.
+ (TARGET_EXPR_CLEANUP): New macro.
+
+2002-02-28 Steve Ellcey <sje@cup.hp.com>
+
+ * doc/rtl.texi (SUBREG_PROMOTED_UNSIGNED_P): Change definition
+ to take ptr_extend into account as third type of extension.
+ (SUBREG_PROMOTED_UNSIGNED_SET): Definition of new macro to set bit
+ fields used by SUBREG_PROMOTED_UNSIGNED_P.
+ * rtl.h (SUBREG_PROMOTED_UNSIGNED_SET): New macro.
+ (SUBREG_PROMOTED_UNSIGNED_P): Change to return -1 as well as 0 or 1.
+ * calls.c (precompute_arguments): Use new macro.
+ (expand_call): Ditto.
+ * combine.c (nonzero_bits): Ditto.
+ (record_promoted_value): Ditto.
+ * expr.c (store_expr): Ditto.
+ (expand_expr): Ditto.
+ * function.c (assign_parms): Ditto.
+
+2002-02-28 Alexandre Oliva <aoliva@redhat.com>
+
+ * gcc.c (init_gcc_specs): Get -static and -static-libgcc to
+ override -shared and -shared-libgcc.
+
+2002-02-28 David O'Brien <obrien@FreeBSD.org>
+
+ * config.gcc (sparc64-*-freebsd): Explicitly accept a cpu specification
+ of "ultrasparc".
+ * config/sparc/freebsd.h: Do not use MASK_FASTER_STRUCTS. It appears
+ to be broken.
+
+2002-02-28 Richard Henderson <rth@redhat.com>
+
+ * config/ia64/ia64.c (ia64_adjust_cost): All non-MM consumers have
+ 4 cycle latency from MM producers.
+ (ia64_internal_sched_reorder): Likewise with pipeline flush.
+
+2002-02-28 Jakub Jelinek <jakub@redhat.com>
+
+ * mklibgcc.in: Don't use GNU make extension.
+
+2002-02-28 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-parse.in (STATIC): New terminal.
+ (scspec): New non-terminal. Update productions accordingly.
+ (program): Remove bogus ifc / end ifc.
+ (array_declarator): Simplify production using STATIC.
+
+2002-02-28 Jim Meyering <meyering@lucent.com>
+
+ * cpplex.c (cpp_parse_escape): Restore mistakenly-removed code:
+ \a still means TARGET_BELL.
+
+2002-02-28 Richard Henderson <rth@redhat.com>
+
+ * haifa-sched.c (sched_emit_insn): New.
+ (schedule_block): Use last_scheduled_insn to track last insn.
+ * sched-int.h (sched_emit_insn): Prototype.
+ * config/ia64/ia64.c (last_issued): Remove.
+ (ia64_variable_issue): Don't set it.
+ (nop_cycles_until): Use sched_emit_insn.
+
+2002-02-28 Andrew MacLeod <amacleod@redhat.com>
+
+ * config/sparc/sparc.c (sparc64_initialize_trampoline): Generate sign
+ extended constants.
+
+2002-02-28 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c: Fix formatting.
+ * config/h8300/h8300.h: Likewise.
+
+2002-02-28 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (avr_hard_regno_mode_ok): Do not allow r29
+ which may overwrite the high byte of the frame pointer.
+
+2002-02-28 Bo Thorsen <bo@suse.de>
+
+ * config/i386/linux64.h (LINK_SPEC): Fix 32/64 bit compilation.
+ (STARTFILE_SPEC): Add 64 bit files.
+ (ENDFILE_SPEC): Likewise.
+
+2002-02-28 Jason Merrill <jason@redhat.com>
+
+ * c-decl.c (finish_function): Only warn about missing return
+ statement with -Wreturn-type.
+
+Don Feb 28 11:24:30 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgrtl.c (purge_dead_edges): Fix handling of EH edges.
+
+ * i386.h (CONDITIONAL_REGISTER_USAGE): Do not write to
+ PIC_OFFSET_TABLE_REGNUM when it is INVALID_REGNUM
+
+Don Feb 28 11:07:36 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * basic-block.h (BB_REACHABLE): Renumber.
+ (BB_DIRTY, BB_NEW): New flags.
+ (clear_bb_flags): Declare.
+ (update_life_info_in_dirty_blocks): Declare.
+ * cfg.c (clear_bb_flags): New function.
+ * cfgrtl.c (create_basic_block_structure): Set flags to BB_NEW.
+ * emit-rtl.c (add_insn_after, add_insn_before, remove_insn,
+ reorder_insns, emit_insn_after): Mark block as dirty.
+ * flow.c (update_life_info): Fix clearing of PROP_LOG_LINKS.
+ (update_life_info_in_dirty_blocks): New function.
+ * recog.c (apply_change_group): Dirtify block.
+
+ * cse.c (cse_insn): Reorder emitting of jump insn to keep
+ cfg consistent.
+ * gcse.c (delete_null_pointer_checks): Likewise.
+
+ * toplev.c (dump_file_index): Move cse2 after bp,
+ add DFI_null
+ (dump_file_info): Similary.
+ (rest_of_compilation): Avoid most of CFG rebuilds;
+ do first if converision after null pointer checks, do cse2
+ after branch prediction; avoid full liveness rebuild after
+ initializing subregs.
+ * invoke.texi (-d options): Document -du, renumber.
+
+ * cfgcleanup.c (bb_flags): Remove BB_UPDATE_LIFE.
+ (notice_new_block): Do not set BB_UPDATE_LIFE.
+ (try_forward_edges, merge_blocks_move_predecessor_nojumps,
+ merge_blocks_move_successor_nojumps, merge_blocks,
+ try_crossjump_to_edge): Likewise.
+ (try_optimize_cfg): Likewise; use update_life_info_in_dirty_blocks.
+ * cfgrtl.c (merge_blocks_nomove): Copy b's flags to a.
+ * ifcvt.c (SET_UPDATE_LIFE, UPDATE_LIFE): Kill.
+ (merge_of_block): Do not use life_data_ok.
+ (find_if_case_1): Do not use SET_UPDATE_LIFE.
+ (if_convert): Use BB_DIRTY mechanizm to update life.
+ * lcm.c (optimize_mode_switching): Update
+ update_life_info_in_dirty_blocks
+
+2002-02-28 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Makefile.in (integrate.o): Update.
+ * c-decl.c (copy_lang_decl): Rename.
+ * c-lang.c (LANG_HOOKS_DUP_LANG_SPECIFIC_DECL): Redefine.
+ * integrate.c: Include langhooks.h.
+ (copy_decl_for_inlining): Update to use langhook.
+ * langhooks-def.h (lhd_do_nothing_t,
+ LANG_HOOKS_DUP_LANG_SPECIFIC_DECL): New.
+ (LANG_HOOKS_INITIALIZER): Update.
+ * langhooks.c (lhd_do_nothing_t): New.
+ * langhooks.h (struct lang_hooks): Add dup_lang_specific_decl.
+ * tree.h (copy_lang_decl): Remove.
+objc:
+ * objc-lang.c (LANG_HOOKS_DUP_LANG_SPECIFIC_DECL): Redefine.
+
+2002-02-27 Andrew MacLeod <amacleod@redhat.com>
+
+ * dwarf2out.c (stack_adjust_offset): Add support for POST_INC,
+ POST_DEC, and POST_MODIFY.
+
+2002-02-27 Zack Weinberg <zack@codesourcery.com>
+
+ * c-typeck.c (digest_init): Remove unused parameter; all
+ callers changed.
+
+2002-02-27 Geoffrey Keating <geoffk@redhat.com>
+
+ * expmed.c (expand_shift): Correctly test for low part of a
+ subreg.
+
+2002-02-27 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.c (s390_chunkify_pool): Do not confuse
+ insn UIDs with insn addresses.
+
+2002-02-27 Zack Weinberg <zack@codesourcery.com>
+
+ * c-common.c, c-common.h, c-decl.c, c-lex.c, c-parse.in,
+ c-tree.h, c-typeck.c, cppexp.c, cpplex.c, cpplib.c, cpplib.h,
+ cppmacro.c, objc/lang-specs.h, objc/objc-act.c,
+ builtin-types.def, builtins.def, dwarf2out.c, dwarfout.c,
+ gcc.c, toplev.c: Delete code implementing -traditional mode.
+
+ * doc/bugreport.texi, doc/cpp.texi, doc/extend.texi,
+ doc/invoke.texi, doc/standards.texi, doc/trouble.texi:
+ Document removal of -traditional mode for compilation, and
+ remove documentation only relevant to that mode.
+
+ * config/nextstep.h, config/ptx4.h, config/svr4.h,
+ config/convex/convex.h, config/d30v/d30v.h,
+ config/i386/dgux.h, config/i386/osf1elf.h,
+ config/i386/osfelf.h, config/i386/osfrose.h,
+ config/i386/sco5.h, config/i386/sol2.h, config/m68k/a-ux.h,
+ config/m68k/hp310.h, config/m88k/dgux.h,
+ config/m88k/dguxbcs.h, config/m88k/luna.h, config/m88k/m88k.c,
+ config/m88k/m88k.h, config/m88k/openbsd.h,
+ config/mips/abi64.h, config/mips/osfrose.h,
+ config/mips/svr4-5.h, config/mips/svr4-t.h,
+ config/sparc/sol2-sld-64.h, config/sparc/sol2.h,
+ config/stormy16/stormy16.h: Remove all references to
+ -traditional from target specs. Delete all mention of the
+ no-longer-necessary TRADITIONAL_RETURN_FLOAT macro. Also
+ delete a couple of commented-out definitions of
+ DOLLARS_IN_IDENTIFIERS, with (incorrect) commentary referring
+ to -traditional.
+
+ * system.h: Poison TRADITIONAL_RETURN_FLOAT.
+ * doc/tm.texi: Remove mention of TRADITIONAL_RETURN_FLOAT macro.
+
+2002-02-27 Zack Weinberg <zack@codesourcery.com>
+
+ * mklibgcc.in: Don't use \n in a line subject to
+ interpretation by echo.
+
+2002-02-27 Graham Stott <grahams@redhat.com>
+
+ * config/rs6000/rs6000.h (ASM_OUTPUT_DEF_FROM_DELC):
+ Constify NAME.
+
+ * loop.c (prescan_loop): Handle PARALLEL.
+
+ * unroll.c (loop_iterations): Return 0 if the add_val for
+ a BIV is REG.
+
+ * final.c (output_operand_lossage): Constify PFX_STR.
+
+ * df.c (df_insn_refs_record): Use XEXP (x, 0) for USE.
+
+Wed Feb 27 10:45:19 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * linux64.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Remove.
+ * x86-64.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Allways define.
+
+Wed Feb 27 10:39:20 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * linux64.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Define.
+
+2002-02-27 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpplex.c (_cpp_lex_token): Handle directives in macro
+ arguments.
+ * cpplib.c (_cpp_handle_directive): Save and restore state
+ if parsing macro args when entering a directive.
+ * cppmacro.c (collect_args): No need to handle directives
+ in macro arguments.
+ (enter_macro_context, replace_args): Use the original macro
+ definition in case it was redefined whilst collecting arguments.
+doc:
+ * cpp.texi: Update.
+
+2002-02-26 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/aix43.h (THREAD_MODEL_SPEC): Delete.
+ * config/rs6000/aix51.h (THREAD_MODEL_SPEC): Delete.
+ * config/rs6000/rs6000.c (rs6000_return_addr): Use efficient
+ method on AIX.
+ * config/rs6000/rs6000.md (movsi_low): Use gpc_reg_operand.
+ (movsi_low_st, movdf_low, movdf_low_st, movsf_low, movsf_low_st): Same.
+ (load_toc_v4_PIC_2): Same.
+
+2002-02-26 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.md (load_toc_aix_di): Handle TARGET_RELOCATABLE.
+
+2002-02-26 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.md (ashldi_se): Re-enable.
+
+2002-02-26 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (alpha_encode_section_info): Examine
+ MODULE_LOCAL_P; improve commentary.
+
+2002-02-26 Zack Weinberg <zack@codesourcery.com>
+
+ * doc/cpp.texi: Clarify documentation of relationship between
+ #line and #include.
+
+2002-02-26 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300-protos.h: Update the prototype for
+ compute_logical_op_length. Add the prototype for
+ compute_logical_op_cc.
+ * config/h8300/h8300.c (compute_logical_op_length): Figure out
+ code from operands.
+ (compute_logical_op_cc): New.
+ * config/h8300/h8300.md: Combine all the logical op patterns
+ in HImode and SImode. Use compute_logical_op_cc.
+
+2002-02-26 Kelley Cook <kelleycook@comcast.net>
+
+ * config/i386/i386.c (print_operand): Don't append ATT-style
+ length suffixs to x87 opcodes when in Intel mode.
+
+2002-02-26 Ryan T. Sammartino <ryants@shaw.ca>
+
+ * emit-rtl.c (gen_const_vector_0): Remove TYPE argument.
+ (init_emit_once): Update calls.
+ * fixinc/gnu-regex.c (_GNU_SOURCE): Remove.
+ (init_syntax_once): Prototype.
+
+2002-02-26 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa-linux.h (LIB_SPEC): Update definition.
+ * pa32-linux.h (LINK_COMMAND_SPEC): Delete.
+
+2002-02-26 Richard Henderson <rth@redhat.com>
+
+ * config/ia64/ia64.c (nop_cycles_until): Do init_insn_group_barriers
+ if we emitted a stop bit.
+
+2002-02-26 Jakub Jelinek <jakub@redhat.com>
+
+ * configure.in (libgcc_visibility): Substitute.
+ * configure: Rebuilt.
+ * mklibgcc.in: If libgcc_visibility = yes, make libgcc.a global
+ defined symbols .hidden.
+
+2002-02-26 Jakub Jelinek <jakub@redhat.com>
+
+ * attribs.c (c_common_attribute_table): Add visibility.
+ (handle_visibility_attribute): New function.
+ * varasm.c (assemble_visibility): New function.
+ * output.h (assemble_visibility): Add prototype.
+ * tree.h (MODULE_LOCAL_P): Define.
+ * crtstuff.c (__dso_handle): Use visibility attribute.
+ * config/i386/i386.h (ENCODE_SECTION_INFO): Set SYMBOL_REF_FLAG
+ for MODULE_LOCAL_P symbols too.
+ * config/ia64/ia64.c (ia64_encode_section_info): Handle
+ MODULE_LOCAL_P symbols the same way as local symbols.
+ Add SDATA_NAME_FLAG_CHAR even if decl was explicitely forced
+ into .sdata/.sbss by the user.
+ * doc/extend.texi (Function Attributes): Document visibility
+ attribute.
+
+2002-02-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/5770
+ * dwarf2out.c (rtl_for_decl_location): Return CONST_STRING for
+ STRING_CST initializer spanning the whole variable without
+ embedded zeros.
+ If expand_expr returned MEM, don't use it.
+
+2002-02-26 Alexandre Oliva <aoliva@redhat.com>
+
+ * dwarf2out.c (gen_inlined_subroutine_die): If block is abstract,
+ generate a die for the lexical block.
+
+2002-02-26 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300-protos.h: Add a prototype for
+ compute_logical_op_length.
+ * config/h8300/h8300.c (compute_logical_op_length): New.
+ * config/h8300/h8300.md (anonymous logical patterns): Use
+ compute_logical_op_length for length.
+
+2002-02-26 Aldy Hernandez <aldyh@redhat.com>
+
+ * dwarf2out.c (modified_type_die): Do not call type_main_variant
+ for vectors.
+ (gen_type_die): Same.
+
+ * attribs.c (handle_vector_size_attribute): Set debug information.
+
+2002-02-26 Daniel Egger <degger@fhm.edu>
+
+ * config/rs6000/rs6000.md: Swap define_insn attributes to
+ fix incorrect generation of merge high instructions instead
+ of merge low.
+
+2002-02-26 Aldy Hernandez <aldyh@redhat.com>
+
+ * c-typeck.c (really_start_incremental_init): Use
+ bitsize_zero_node for vectors.
+
+2002-02-26 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.md (get_vrsave_internal): Fix typo.
+ ("*set_vrsave_internal"): Same.
+
+2002-02-25 Richard Henderson <rth@redhat.com>
+
+ * expr.c (expand_expr) [MULT_EXPR]: Do not apply distributive law
+ in EXPAND_SUM case. Use host_integerp/tree_low_cst.
+
+2002-02-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/5755
+ * config/i386/i386.c (ix86_return_pops_args): Only pop
+ fake structure return argument if it was passed on the stack.
+
+2002-02-25 Jason Merrill <jason@redhat.com>
+
+ * attribs.c (decl_attributes): Also re-layout PARM_DECL and
+ RESULT_DECL.
+
+2002-02-25 Alexandre Oliva <aoliva@redhat.com>
+
+ * gcc.c (init_gcc_specs): Get -shared-libgcc along with -shared to
+ link with shared_name only.
+ * doc/invoke.texi (Link Options): Document new behavior.
+
+2002-02-25 Aldy Hernandez <aldyh@redhat.com>
+
+ * c-typeck.c (push_init_level): Handle vectors.
+
+2002-02-25 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/sparc/sparc.c (const64_high_operand): Zero-extend
+ operands of SPARC_SETHI_P.
+ (input_operand): Likewise.
+ (sparc_emit_set_const32): Likewise.
+ * config/sparc/sparc.h (SPARC_SETHI_P): Disregard TARGET_ARCH64.
+ (SPARC_SETHI32_P): Zero-extend operand from 32 bits.
+ (CONST_OK_FOR_LETTER_P): Use SETHI32 for `K'. Add `N' as SETHI.
+ * config/sparc/sparc.md (movdi_insn_sp64_novis): Use `N'.
+ (movdi_insn_sp64_vis): Likewise.
+ (movdi split, movdf split): Use SETHI32.
+ * doc/md.texi: Document SPARC constraints L, M and N.
+
+2002-02-25 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.md ("get_vrsave_internal"): New.
+ ("*set_vrsave_internal"): use mfspr for Darwin.
+
+ * config/rs6000/rs6000.c (rs6000_emit_prologue): Call
+ gen_get_vrsave_internal.
+
+Sun Feb 24 16:38:56 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * optabs.c (widen_operand): Properly handle CONST_INT for NO_EXTEND.
+
+2002-02-24 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpplex.c (cpp_interpret_charconst): Get signedness or
+ otherwise of wide character constants correct.
+ * cppexp.c (lex): Get signedness of wide charconsts correct.
+
+Sun Feb 24 07:41:31 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * optabs.c (widen_operand): Only call convert_modes for
+ promoted SUBREG if signedness matches.
+ * config/alpha/alpha.md (*addsi_se2, *subsi_se2): New patterns.
+
+2002-02-23 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpplib.c (glue_header_name): Use local buffer to build up
+ header name.
+
+2002-02-23 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * doc/cpp.texi, doc/invoke.texi: Update documentation for -MM.
+
+2002-02-23 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (output_simode_bld): Handle H8/300 and
+ H8/300[HS] separately.
+ * config/h8300/h8300.md: Remove the early clobber constraint
+ from bit field patterns.
+
+2002-02-23 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md (mulqihi3): Tighten predicates to
+ register_operand.
+ (mulhisi3): Likewise.
+ (umulqisi3): Likewise.
+ (umulhisi3): Likewise.
+
+2002-02-23 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppinit.c (output_deps): Correct test for stdout output.
+ (init_dependency_output): Cure warning.
+
+Sat Feb 23 08:42:47 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * expr.c (store_expr): When converting expression to promoted
+ equivalent type, allow using SUBREG_REG of TARGET as the target
+ of the expansion of EXP.
+ * loop.c (basic_induction_var, case SUBREG): Always look inside.
+ * config/alpha/alpha.c (rtx_equiv_function_matters): Delete decl.
+ (alpha_emit_set_const): Handle SImode when can't make new pseudos.
+ (alpha_emit_set_const_1, alpha_sa_mask): Use no_new_pseudos.
+ * config/alpha/alpha.md (addsi3, subsi3): Don't use if optimizing.
+
+2002-02-23 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/contribute.texi, doc/extend.texi, doc/install.texi,
+ doc/invoke.texi, doc/md.texi, doc/passes.texi, doc/rtl.texi,
+ doc/standards.texi, doc/tm.texi: Remove trailing whitespace.
+
+2002-02-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR optimization/5747
+ * loop.c (scan_loop): Update reg info if move_movables created new
+ pseudos.
+
+2002-02-23 David Edelsohn <edelsohn@gnu.org>
+
+ * gcc.c (init_gcc_spec): Revert last change.
+
+2002-02-23 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.md (load_toc_aix_{si,di}): Use
+ gpc_reg_operand constraint.
+
+2002-02-23 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.c (num_insns_constant): Fix formatting.
+ Simplify comparison of `low'.
+ (add_operand): Fix formatting.
+ (non_add_cint_operand): Use CONST_OK_FOR_LETTER_P.
+ (mask_operand): Disallow mask to wrap in 64-bit mode.
+ (rs6000_stack_info): Remove redundant test setting push_p.
+ (output_toc): Fix formatting.
+ * config/rs6000/rs6000.md (boolsi3, boolcsi3 splitters): Use
+ cc_reg_not_cr0_operand constraint.
+ (booldi3, boolcdi3 splitters): Same.
+
+2002-02-23 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/altivec.h: Add extra level of parentheses on casts.
+
+2002-02-22 David Edelsohn <edelsohn@gnu.org>
+
+ * gcc.c (init_gcc_spec): Do not link with static libgcc.a if
+ gcc invoked with -shared-libgcc.
+
+2002-02-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/5748
+ * stmt.c (expand_anon_union_decl): Set TREE_USED on the anon union
+ decl if any of elements was TREE_USED.
+
+2002-02-22 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/sparc/sol2.h: Don't include sys/mman.h.
+ * config/sparc/sparc.c (arith_operand): Use SMALL_INT32.
+ (arith_4096_operand): Don't throw high bits away.
+ (const64_operand): Take sign extension of CONST_INTs into account.
+ (const64_high_operand, sparc_emit_set_const32): Likewise.
+ (GEN_HIGHINT64): Likewise.
+ (sparc_emit_set_const64_quick1): Likewise.
+ (const64_is_2insns): Likewise.
+ (print_operand): Use trunc_int_for_mode for sign extension.
+ * config/sparc/sparc.h (SMALL_INT32): Likewise.
+ * config/sparc/sparc.md (movqi): Sign-extend CONST_DOUBLE
+ chars. Assume CONST_INT is already properly sign-extended.
+ (movdi split): Sign-extend each SImode part.
+ (andsi3 split): Don't mask high bits off, so that result
+ remains properly sign-extend.
+ (iorsi3 split): Likewise.
+ (xorsi3 split): Likewise.
+
+2002-02-22 Richard Sandiford <rsandifo@redhat.com>
+
+ * fold-const.c (fold): Fix typo in comments.
+
+2002-02-21 Diego Novillo <dnovillo@redhat.com>
+
+ * Makefile.in (langhooks.o): Update dependencies.
+
+2002-02-21 Diego Novillo <dnovillo@redhat.com>
+
+ * langhooks.c: Include flags.h.
+
+2002-02-21 Aldy Hernandez <aldyh@redhat.com>
+
+ * testsuite/gcc.dg/attr-alwaysinline.c: New.
+
+ * c-common.c (c_common_post_options): Set inline trees by
+ default.
+
+ * doc/extend.texi (Function Attributes): Document always_inline
+ attribute.
+ Update documentation about inlining when not optimizing.
+
+ * cp/decl.c (duplicate_decls): Merge always_inline attribute.
+
+ * cp/tree.c (cp_cannot_inline_tree_fn): Do not inline at -O0
+ unless DECL_ALWAYS_INLINE.
+
+ * c-objc-common.c (c_cannot_inline_tree_fn): Do not inline at -O0
+ unless DECL_ALWAYS_INLINE.
+ (c_disregard_inline_limits): Disregard if always_inline set.
+
+ * langhooks.c (lhd_tree_inlining_disregard_inline_limits):
+ Disregard if always_inline set.
+ (lhd_tree_inlining_cannot_inline_tree_fn): Do not inline at -O0
+ unless DECL_ALWAYS_INLINE.
+
+ * attribs.c (handle_always_inline_attribute): New.
+ (c_common_attribute_table): Add always_inline.
+
+ * config/rs6000/altivec.h: Add prototypes for builtins
+ requiring the always_inline attribute.
+
+2002-02-21 Eric Christopher <echristo@redhat.com>
+
+ * expmed.c (store_bit_field): Try to simplify the subreg
+ before generating a new one when when the mode size of
+ value is less than maxmode.
+
+2002-02-21 Richard Henderson <rth@redhat.com>
+
+ * emit-rtl.c (offset_address): Use simplify_gen_binary rather
+ than gen_rtx_PLUS to form the sum.
+ * explow.c (force_reg): Rearrange to not allocate new pseudo
+ when force_operand returns a register.
+ * expr.c (expand_assignment): Allow offset_rtx expansion to
+ return a sum. Do not force addresses into registers.
+ (expand_expr): Likewise.
+ * simplify-rtx.c (simplify_gen_binary): Use simplify_plus_minus
+ to canonicalize arithmetic that didn't simpify.
+ (simplify_plus_minus): New argument force; update
+ all callers. Don't split CONST unless we can do something with it,
+ and wouldn't lose the constness of the operands.
+
+ * config/i386/i386.c (legitimize_pic_address): Recognize UNSPECs
+ that we generated earlier.
+
+2002-02-21 Tom Tromey <tromey@redhat.com>
+
+ * dwarf2out.c (DWARF_LINE_MIN_INSTR_LENGTH): Removed.
+ (output_line_info): Use constant `1', with a long explanatory
+ comment.
+ * system.h (DWARF_LINE_MIN_INSTR_LENGTH): Poison.
+
+Thu Feb 21 22:43:44 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * jump.c (redirect_jump): If old label has no UID, don't try to
+ delete it.
+
+Thu Feb 21 21:17:21 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.md (insv): Provide byte offsets for gen_rtx_SUBREG.
+ If input is constant, do shifts at compile time.
+
+2002-02-21 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/extend.texi: Fix some more overfull hboxes.
+
+2002-02-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR optimization/4994
+ * config/i386/i386.md (movsi_1, movsf_1): Support MMX -> MMX
+ register moves.
+
+2002-02-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/4574
+ * expr.h (expand_and): Add mode argument.
+ * expmed.c (expand_and): Add mode argument.
+ (expand_mult_highpart_adjust, emit_store_flag): Adjust callers.
+ * expr.c (store_field, expand_expr, do_store_flag): Likewise.
+ * except.c (expand_builtin_extract_return_addr): Likewise.
+ * config/alpha/alpha.c (alpha_initialize_trampoline): Likewise.
+ * config/sparc/sparc.c (sparc_initialize_trampoline): Likewise.
+ * config/c4x/c4x.h (INITIALIZE_TRAMPOLINE): Likewise.
+ Use GEN_INT (x) instead of gen_rtx (CONST_INT, VOIDmode, x).
+ * config/c4x/c4x.md: Use GEN_INT (x) instead of
+ gen_rtx (CONST_INT, VOIDmode, x).
+
+2002-02-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/4697:
+ * stmt.c (warn_if_unused_value): Move side effects test once more.
+
+2002-02-20 Torbjorn Granlund <tege@swox.com>
+
+ * config/avr/avr.md: Add more patterns for mized-mode add and subtract
+ (addsi3_zero_extend, subhi3_zero_extend1, subsi3_zero_extend).
+
+Thu Feb 21 16:20:46 2002 Alexandre Oliva <aoliva@redhat.com>
+
+ * rtlanal.c (replace_rtx): Don't make a CONST_INT the operand of
+ SUBREG or ZERO_EXTEND.
+
+Thu Feb 21 15:35:46 2002 J"orn Rennecke <joern.rennecke@superh.com>
+
+ * sh.h (current_function_anonymous_args): Remove.
+ (SETUP_INCOMING_VARARGS): Don't set it - just check that one
+ of current_function_varargs and current_function_stdarg is set.
+ * sh.c (sh_expand_prologue): Check current_function_varargs /
+ current_function_stdarg / TARGET_SH5 instead of
+ current_function_anonymous_args.
+
+ * sh64.h (TARGET_VERSION): Define.
+
+2002-02-20 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.h (EPILOGUE_USES): Conditionalize
+ VRSAVE_REGNO on TARGET_ALTIVEC.
+
+2002-02-20 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.c (includes_lshift_p): Mask irrelevant
+ bits of SImode const_int.
+ (includes_rshift_p): Likewise.
+ (print_operand): Call mask_operand and mask64_operand with correct
+ mode.
+ (rs6000_output_function_epilogue): Pad traceback table to word.
+ * config/rs6000/rs6000.h (MASK_64BIT): Correct comment.
+ (EXTRA_CONSTRAINT, 'S' and 'T'): Call mask_operand and
+ mask64_operand with correct mode.
+ (FUNCTION_ARG_REGNO_P): Correct parentheses.
+
+2002-02-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/4461
+ * varasm.c (get_pool_constant_mark): New.
+ * rtl.h (get_pool_constant_mark): Add prototype.
+ * dwarf2out.c (mem_loc_descriptor): A pool constant cannot
+ be represented if it has not been output.
+
+2002-02-20 Alexandre Oliva <aoliva@redhat.com>
+
+ * combine.c (do_SUBST): Sanity check substitutions of
+ CONST_INTs, and reject them in SUBREGs and ZERO_EXTENDs.
+ (subst): Simplify SUBREG or ZERO_EXTEND instead of SUBSTing a
+ CONST_INT into its operand.
+ (known_cond): Likewise, for ZERO_EXTEND.
+ * simplify-rtx.c (simplify_unary_operation): Fix condition to
+ allow for simplification of wide modes. Reject CONST_INTs in
+ ZERO_EXTEND when their actual mode is not given.
+
+2002-02-20 Alexandre Oliva <aoliva@redhat.com>
+
+ * c-decl.c (pushdecl): If no global declaration is found for an
+ extern declaration in block scope, try a limbo one.
+
+2002-02-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/4401
+ * c-common.c (pointer_int_sum): Moved from...
+ * c-typeck.c (pointer_int_sum): ...here.
+ * c-common.h (pointer_int_sum): Add prototype.
+
+2002-02-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/5713
+ * c-decl.c (duplicate_decls): Return 0 if issued error about
+ redeclaration.
+
+2002-02-20 Roger Sayle <roger@eyesopen.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR c/4389
+ * tree.c (host_integerp): Ensure that the constant integer is
+ representable in a HOST_WIDE_INT or an unsigned HOST_WIDE_INT
+ when pos is zero or nonzero respectively. Clarify comment.
+ * c-format.c (check_format_info_recurse): Fix host_integerp
+ usage; the pos argument should be zero when assigning to a
+ signed HOST_WIDE_INT.
+
+2002-02-20 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (ix86_expand_vector_move): Use the mode
+ of the operand, rather than assuming TImode.
+ (ix86_expand_binop_builtin): Cope with commutative patterns
+ using nonimmediate_operand for both operands.
+ (ix86_expand_timode_binop_builtin): Likewise.
+ (ix86_expand_store_builtin): Validate operand 1.
+ (ix86_expand_unop1_builtin): Likewise.
+
+2002-02-20 Philip Blundell <philb@gnu.org>
+
+ PR 5705
+ * config/arm/arm.h (HARD_REGNO_RENAME_OK): New macro.
+
+2002-02-20 Richard Henderson <rth@redhat.com>
+
+ PR c/5615
+ * expr.h (ARGS_SIZE_TREE): Convert size.var to ssizetype.
+
+2002-02-20 Tom Tromey <tromey@redhat.com>
+
+ * config/fr30/fr30.h (DWARF_LINE_MIN_INSTR_LENGTH): Removed.
+ * config/sh/sh.h (DWARF_LINE_MIN_INSTR_LENGTH): Removed.
+ * config/pj/pj.h (DWARF_LINE_MIN_INSTR_LENGTH): Removed.
+ * config/cris/cris.h (DWARF_LINE_MIN_INSTR_LENGTH): Removed.
+ * dwarf2out.c (DWARF_LINE_MIN_INSTR_LENGTH): Define
+ unconditionally.
+
+Wed Feb 20 00:03:25 EST 2002 Alan Matsuoka <alanm@redhat.com>
+
+ * config/rs6000/rs6000.h (LEGITIMATE_OFFSET_ADDRESS_P): Look
+ for (const_int 0) in X not just INTVAL.
+
+2002-02-20 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/extend.texi: Avoid or reduce overfull hboxes.
+
+2002-02-20 Diego Novillo <dnovillo@redhat.com>
+
+ * expmed.c (store_bit_field): Do not store bit fields using SUBREG
+ operations if the field does not start at a mode boundary.
+
+2001-02-20 Joel Sherrill <joel@OARcorp.com>
+
+ * config/a29k/rtems.h, config/arm/rtems-elf.h, config/h8300/rtems.h,
+ config/mips/rtems.h: Use new style of -Asystem= rather than -Asystem().
+ Also done for -Acpu and -Amachine.
+
+2002-02-20 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppinit.c (init_dependency_output): Take deps output file
+ from -o if none given with -MF. Suppress normal output.
+ * gcc.c (cpp_unique_options): Have -M and -MM imply -E.
+ * doc/cpp.texi, doc/invoke.texi: Update.
+
+2002-02-19 Zack Weinberg <zack@codesourcery.com>
+
+ * toplev.c (output_quoted_string): Write unprintable
+ characters with octal escapes.
+
+2002-02-19 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.h (CONDITIONAL_REGISTER_USAGE): Set
+ really_call_used[VRSAVE_REGNO] if not Altivec.
+
+2002-02-19 Alan Modra <amodra@bigpond.net.au>
+
+ * config/rs6000/rs6000.c (u_short_cint_operand): Mask op with
+ MODE_MASK.
+ (constant_pool_expr_1): Fix formatting.
+ (rs6000_legitimize_reload_address): Likewise.
+
+Tue Feb 19 20:13:57 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * config/sparc/sparc.md (nonlocal_goto): Use hard_frame_pointer_rtx
+ now that we have one.
+
+2002-02-19 Zack Weinberg <zack@codesourcery.com>
+
+ * tree.h (struct tree_common): Remove aux. Add unused_0 at
+ end of first block of bitfields (which was only seven bits);
+ rename dummy to unused_1; remove comment which is no longer true.
+
+2002-02-19 Gaute B Strokkenes <gs234@cam.ac.uk>
+
+ * doc/c-tree.texi (Classes, TYPE_BINFO): Fix typo.
+
+2002-02-19 Philip Blundell <pb@nexus.co.uk>
+
+ PR 5399
+ * config/arm/arm.h (THUMB_LEGITIMATE_CONSTANT_P): Accept anything
+ if generating PIC.
+
+ PR 5054
+ * config/arm/arm.md (call_insn) [TARGET_THUMB]: Use
+ arm_is_longcall_p rather than inspecting call-type cookie
+ directly.
+ (call_value_insn) [TARGET_THUMB]: Likewise.
+
+2002-02-19 Graham Stott <grahams@redhat.com>
+
+ * config/i386/i386.c (ix86_expand_builtin): Fix typo.
+
+2002-02-19 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/linux64.h (LINK_OS_LINUX_SPEC): Look in /lib64.
+ ({STARTFILE,ENDFILE}_LINUX_SPEC): Define.
+ (FP_SAVE_INLINE): Delete.
+
+ * config/rs6000/sysv4.h (ENDFILE_SPEC): Add crtsaveres.o.
+ * config/rs6000/eabi.asm: Remove ABI save restore routines.
+ * config/rs6000/t-ppccomm: Build crtsavres.o.
+ * config/rs6000/crtsavres.asm: New file.
+
+2002-02-19 Philip Blundell <philb@gnu.org>
+
+ * config/arm/arm.c (use_return_insn): Don't reject interrupt
+ functions.
+ (arm_compute_save_reg_mask): Save LR for interrupt functions too.
+ (output_return_instruction): Allow interrupt functions to return with
+ ldmfd sp!, {... pc}^. Use LDR to restore any single register.
+ (arm_expand_prologue): Subtract 4 before stacking LR in an
+ interrupt function.
+
+2002-02-19 Philip Blundell <pb@nexus.co.uk>
+
+ * config/arm/arm.c (arm_encode_call_attribute): Operate on any
+ decl, not just FUNCTION_DECL.
+ (legitimize_pic_address): Handle local SYMBOL_REF like LABEL_REF.
+ (arm_assemble_integer): Likewise.
+ * config/arm/arm.h (ARM_ENCODE_CALL_TYPE): Allow any decl to be
+ marked local.
+
+2002-02-19 matthew green <mrg@eterna.com.au>
+
+ * config.gcc (sparc-*-netbsdelf*): Enable target.
+ (sparc64-*-netbsd*): New target.
+ * config/sparc/netbsd-elf.h: New file.
+ * config/sparc/t-netbsd64: New file.
+
+2002-02-19 Gaute B Strokkenes <gs234@cam.ac.uk>
+
+ * doc/rtl.texi (Flags, MEM_SCALAR_P): Fix typo.
+
+2002-02-19 Ryan T. Sammartino <ryants@shaw.ca>
+
+ * doc/invoke.texi: explicitly list the style guidelines that
+ -Weffc++ checks for.
+
+Tue Feb 19 12:37:23 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * regmove.c (regmove_optimize): Avoid increasing of register pressure.
+
+2002-02-19 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ PR other/5718
+ * gcc.c (cpp_unique_options): Treat -o as indicating object file
+ only if not -E. If -E, pass -o through to the preprocessor.
+
+2002-02-19 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.h (REGNO_REG_CLASS): Replace a literal
+ register number with an appropriate macro.
+
+2002-02-19 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
+
+ * doc/rtl.texi (Constants): Close @code tag.
+
+2002-02-19 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/i386/i386.md ("mmx_uavgv8qi3"): Use const_vector.
+ ("mmx_uavgv4hi3"): Same.
+ ("pmulhrwv4hi3"): Same.
+
+ * tree-inline.c (walk_tree): Handle vectors.
+
+ * c-common.c (constant_expression_warning): Handle vectors.
+ (overflow_warning): Same.
+
+ * sched-deps.c (sched_analyze_2): Handle vectors.
+
+ * rtlanal.c (rtx_unstable_p): Handle vectors.
+ (rtx_varies_p): Same.
+ (count_occurrences): Same.
+ (regs_set_between_p): Same.
+ (modified_between_p): Same.
+ (modified_in_p): Same.
+ (volatile_insn_p): Same.
+ (volatile_refs_p): Same.
+ (side_effects_p): Same.
+ (may_trap_p): Same.
+ (inequality_comparisons_p): Same.
+ (replace_regs): Same.
+ (computed_jump_p_1): Same.
+
+ * rtl.c (DEF_MACHMODE): Change all definitions to accept 8th
+ argument.
+ (inner_mode_array): New.
+ (copy_rtx): Handle vectors.
+ (copy_most_rtx): Same.
+ (rtx_equal_p): Same.
+ (get_mode_alignment): Adjust for vectors.
+
+ * resource.c (mark_referenced_resources): Handle vectors.
+ (mark_set_resources): Same.
+
+ * reload1.c (eliminate_regs): Handle vectors.
+ (elimination_effects): Same.
+ (scan_paradoxical_subregs): Same.
+
+ * reload.c (subst_reg_equivs): Handle vectors.
+
+ * regrename.c (scan_rtx): Handle vectors.
+
+ * regclass.c (reg_scan_mark_refs): Handle vectors.
+
+ * recog.c (find_single_use_1): Handle vectors.
+
+ * local-alloc.c (equiv_init_varies_p): Handle vectors.
+ (contains_replace_regs): Same.
+ (memref_referenced_p): Same.
+
+ * integrate.c (copy_rtx_and_substitute): Handle vectors.
+ (subst_constants): Same.
+
+ * genattrtab.c (attr_copy_rtx): Handle vectors.
+ (encode_units_mask): Same.
+ (clear_struct_flag): Same.
+ (count_sub_rtxs): Same.
+
+ * gcse.c (want_to_gcse_p): Handle vectors.
+ (oprs_unchanged_p): Same.
+ (hash_expr_1): Same.
+ (oprs_not_set_p): Same.
+ (expr_killed_p): Same.
+ (compute_transp): Same.
+ (store_ops_ok): Same.
+
+ * function.c (purge_addressof_1): Do not allow paradoxical subregs
+ of vectors.
+ (fixup_var_refs_1): Same.
+ (instantiate_virtual_regs_1): Same.
+
+ * fold-const.c (operand_equal_p): Handle vectors.
+ (fold): Same.
+ (rtl_expr_nonnegative_p): Same.
+
+ * flow.c (mark_used_regs): Handle vectors.
+
+ * df.c (df_uses_record): Handle vectors.
+
+ * cselib.c (cselib_subst_to_values): Handle vectors.
+ (cselib_mem_conflict_p): Same.
+ (hash_rtx): Same.
+
+ * cse.c (canon_reg): Handle vectors.
+ (fold_rt): Same.
+ (cse_process_notes): Same.
+ (count_reg_usage): Same.
+ (canon_hash): Same.
+
+ * alias.c (nonlocal_mentioned_p): Add case for CONST_VECTOR.
+
+ * combine.c (mark_used_regs_combine): Add case for CONST_VECTOR.
+
+ * emit-rtl.c (init_emit_once): Generate const0_rtx for vectors.
+ (gen_rtx): Handle CONST_VECTOR.
+ (gen_const_vector_0): New.
+ (copy_rtx_if_shared): CONST_VECTORs can be shared.
+ (reset_used_flags): Same.
+ (copy_insn_1): Same.
+ (initializer_constant_valid_p): Handle VECTOR_CST.
+
+ * doc/c-tree.texi (Expression trees): Document VECTOR_CST.
+
+ * doc/rtl.texi (Constants): Document const_vector.
+ (CONST0_RTX): Update for vectors.
+ (RTL sharing): Same.
+
+ * print-tree.c (print_node): Add case for VECTOR_CST.
+
+ * tree.h (TREE_VECTOR_CST_ELTS): New.
+ (struct tree_vector): New.
+ (union tree_node): Add vector node.
+ (build_vector): Add prototype.
+
+ * tree.def (VECTOR_CST): New.
+
+ * tree.c (build_vector): New.
+
+ * expmed.c (make_tree): Handle CONST_VECTOR.
+
+ * rtl.h (CONSTANT_P): CONST_VECTORs are constants too.
+ (CONST_VECTOR_ELT): New.
+ (CONST_VECTOR_NUNITS): New.
+
+ * machmode.h (GET_MODE_INNER): New.
+ (DEF_MACHMODE): Accept 8th arg.
+
+ * machmode.def: Add 8th argument for vector inner mode.
+ Add inner vector modes for vectors.
+
+ * rtl.def (VEC_CONST): Remove.
+ (CONST_VECTOR): New.
+
+ * expr.c (clear_storage): Allow vectors.
+ (is_zeros_p): Handle VECTOR_CST.
+
+ * varasm.c (output_constant_pool): Handle vectors.
+ (rtx_const): Add veclo and vechi fields.
+ (kind): Add RTX_VECTOR.
+ (decode_rtx_const): Add case for vector.
+
+ * config/rs6000/rs6000-protos.h: Add zero_constant.
+
+ * config/rs6000/rs6000.c (rs6000_emit_move): Handle vector
+ constants. Force easy vector constants into memory.
+ (easy_vector_constant): New.
+ (emit_easy_vector_constant): New.
+ (rs6000_legitimize_reload_address): Do not generate bad reloads on
+ darwin.
+
+ * config/rs6000/rs6000.md ("altivec_lvx"): Reflect what
+ instruction does.
+ ("altivec_lvxl"): Same.
+ (altivec_lvebx): Same.
+ (altivec_lvehx): Same.
+ (altivec_lvewx): Same.
+ ("*movv4si_const0"): New.
+ ("*movv4sf_const0"): New.
+ ("*movv8hi_const0"): New.
+ ("*movv16qi_const0"): New.
+
+2002-02-18 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (notice_update_cc): Use
+ cc_status.value2.
+
+2002-02-18 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md (divmod patterns): Change the
+ constraints for operands[1] to register_operand.
+
+2002-02-18 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300-protos.h: Remove the prototype for
+ p_operand.
+ * config/h8300/h8300.c (p_operand): Remove.
+ * config/h8300/h8300.md: Replace p_operand with
+ const_int_operand.
+
+2002-02-18 Philip Blundell <pb@nexus.co.uk>
+
+ * config/arm/arm.c (arm_compute_save_reg_mask): Fix typo in
+ comment.
+ (output_return_instruction): Allow use of LDR to unstack
+ return addresss even for interrupt handlers or when
+ interworking. If compiling for ARMv5, use interworking-safe
+ return instructions by default. Remove duplicated code and
+ lengthy "strcat" sequences.
+
+2002-02-18 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ * config/rs6000/sysv4.h (STARTFILE_SPEC): Use crtbeginT.o for -static.
+ (LINK_EH_SPEC): Define.
+ * config/rs6000/t-ppccomm (EXTRA_MULTILIB_PARTS): Add crtbeginT.o.
+
+2002-02-18 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.c (s390_emit_prologue): Do not set the
+ frame_related flag for call-clobbered registers.
+
+Mon Feb 18 15:07:35 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.c (classify_argument): Properly classify SSE/MMX modes and VOIDmode.
+ (construct_container): Fix handling of SSE operands.
+ (ix86_expand_builtin): Fix handling of 64bit pointers.
+ (mmx_maskmovq_rex): New pattern.
+
+Mon Feb 18 11:55:55 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * regrename.c (kill_set_value): Handle subregs properly.
+
+2002-02-18 David Billinghurst <David.Billinghurst@riotinto.com>
+
+ * objc/objc-act.c (handle_impent): Remove leading '*'
+ from objc_class_name.
+
+2002-02-17 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (some_small_symbolic_operand,
+ some_small_symbolic_operand_1, split_small_symbolic_operand,
+ split_small_symbolic_operand_1): Rename from *symbolic_mem_op*.
+ Handle small SYMBOL_REFs anywhere, not just inside memories.
+ * config/alpha/alpha-protos.h: Update.
+ * config/alpha/alpha.h (PREDICATE_CODES): Update.
+ * config/alpha/alpha.md (small symbolic operand splitter): Update.
+
+2002-02-17 Roland McGrath <roland@frob.com>
+
+ * config.gcc (powerpc-*-gnu-gnualtivec*,
+ powerpc-*-gnu*, powerpc64-*-gnu*): New configurations.
+ * config/rs6000/gnu.h: New file.
+ * config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS):
+ Grok "gnu" in rs6000_abi_name.
+ (ASM_SPEC, CC1_SPEC, LINK_START_SPEC, LINK_OS_SPEC,
+ CPP_ENDIAN_SPEC, CPP_SPEC, STARTFILE_SPEC, LIB_SPEC, ENDFILE_SPEC):
+ Grok -mcall-gnu analogous to -mcall-linux et al.
+ (LIB_GNU_SPEC, STARTFILE_GNU_SPEC, ENDFILE_GNU_SPEC,
+ LINK_START_GNU_SPEC, LINK_OS_GNU_SPEC, CPP_OS_GNU_SPEC): New macros.
+ (SUBTARGET_EXTRA_SPECS): Add *_os_gnu specs using them.
+
+2002-02-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/3444:
+ * c-typeck.c (build_binary_op) [BIT_XOR_EXPR]: Remove explicit
+ shortening.
+
+2002-02-17 Philipp Thomas <pthomas@suse.de>
+
+ * config/cris/cris.h: Undefine STARTFILE_SPEC and
+ ENDFILE_SPEC before (re)defining them.
+
+2002-02-17 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c: Fix formatting.
+ * config/h8300/h8300.h: Likewise.
+
+2002-02-17 Philipp Thomas <pthomas@suse.de>
+
+ * doc/tm.texi: Explain why empty strings should not be
+ marked for translation.
+
+2002-02-17 Philipp Thomas <pthomas@suse.de>
+
+ * final.c (output_operand_lossage): Changed to accept
+ printf style arguments. Change calls where necessary.
+ * output.h (output_operand_lossage): Change declaration
+ accordingly. Update copyright.
+ * config/arc/arc.c config/fr30/fr30.c config/m32r/m32r.c
+ config/m88k/m88k.c : Adapt all calls to output_operand_lossage.
+ Update copyright date where necessary.
+
+ * config/i386/i386.c (print_operand): Likewise. Remove use of
+ sprintf.
+
+ * config/cris/cris.c (cris_operand_lossage): Likewise.
+ Rename parameter so that exgettext recognizes it as
+ translatable message.
+ (LOSE_AND_RETURN): Rename parameter to msgid.
+
+2002-02-17 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.h (CONDITIONAL_REGISTER_USAGE): Replace a
+ hard coded register number with an appropriate macro.
+ (HARD_REGNO_MODE_OK): Likewise.
+ (ARG_POINTER_REGNUM): Likewise.
+ (STATIC_CHAIN_REGNUM): Likewise.
+ (RETURN_ADDRESS_POINTER_REGNUM): Likewise.
+ * config/h8300/h8300.md (define_constants): Define more
+ register numbers.
+
+2002-02-17 Philipp Thomas <pthomas@suse.de>
+
+ * config/i386/i386.h: Don't mark empty strings for translation.
+
+2002-02-16 H.J. Lu <hjl@gnu.org>
+
+ * config/mips/linux.h (ASM_PREFERRED_EH_DATA_FORMAT): New.
+
+2002-02-16 Zack Weinberg <zack@codesourcery.com>
+
+ * cppinit.c (merge_include_chains): Check for brack being
+ NULL before attempting to merge it with qtail.
+
+2002-02-16 Andrew Cagney <ac131313@redhat.com>
+
+ * config/rs6000/netbsd.h (PREFERRED_DEBUGGING_TYPE): Set to
+ DBX_DEBUG.
+
+2002-02-16 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa/t-pa, pa/t-pro, som.h: Revert last patch.
+
+2002-02-16 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa/t-pa (LIB2FUNCS_EXTRA): Don't build lib2funcs.asm.
+ * pa/t-pro (LIB2FUNCS_EXTRA): Likewise.
+ * som.h (DO_GLOBAL_DTORS_BODY): Delete define.
+
+Sat Feb 16 13:48:50 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * config/alpha/alpha.md (*movsi_nt_vms_nofix): Was *movsi_nt_vms;
+ now only if !TARGET_FIX.
+ (*movsi_nt_vms_fix): New pattern.
+
+2002-02-16 Douglas B Rupp <rupp@gnat.com>
+
+ * config/alpha/alpha.c: Implement null frame procedure types on VMS.
+ (alpha_procedure_type): Replaces alpha_is_stack_procedure.
+ (alpha_sa_mask, alpha_sa_size): Reflect above change.
+ (alpha_pv_save_size, alpha_expand_prologue): Likewise.
+ (alpha_start_function, alpha_expand_epilogue): Likewise.
+ (unicosmk_gen_dsib): Likewise.
+
+Sat Feb 16 13:39:09 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * expr.c (store_constructor): Handle target REG case for ARRAY_TYPE.
+
+2002-02-16 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.c (pool_stop_uid, other_chunk, far_away,
+ check_and_change_labels, s390_final_chunkify): Delete.
+ (s390_split_branches, s390_chunkify_pool): New functions.
+ (s390_function_prologue): Call them.
+
+ * config/s390/s390.h (S390_REL_MAX): Delete.
+ (S390_CHUNK_MAX, S390_CHUNK_OV): Adjust values.
+
+ * config/s390/s390.md (cjump, icjump, jump): Fix length
+ attribute calculation.
+
+
+2002-02-15 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/linux64.h (STRIP_NAME_ENCODING): Delete.
+ * config/rs6000/ppc-asm.h (JUMP_TARGET): Define for powerpc64.
+
+2002-02-15 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * gcc.c (init_gcc_specs): Revert patch from 2002-02-15.
+ * config/pa/pa-linux.h (LIB_SPEC): Likewise.
+ * config/pa/pa32-linux.h (LINK_COMMAND_SPEC): Likewise.
+
+2002-02-15 Richard Sandiford <rsandifo@redhat.com>
+
+ * c-decl.c (grokdeclarator): Prevent a segfault on unnamed decls.
+
+2002-02-15 Richard Sandiford <rsandifo@redhat.com>
+
+ * reload.c (find_dummy_reload): Check that an output register
+ is valid for its mode.
+
+2002-02-14 Alexandre Oliva <aoliva@redhat.com>
+
+ * combine.c (known_cond): After replacing the REG of a SUBREG, try
+ to simplify it.
+
+ * function.c (assign_parms): Demote promoted argument passed by
+ transparent reference.
+
+2001-02-14 Joel Sherrill <joel@OARcorp.com>
+
+ * config/arm/rtems-elf.h, config/h8300/rtems.h: Removed redundant
+ -Acpu() and -Amachine() to eliminate warnings.
+
+2002-02-14 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/linux.h (ASM_OUTPUT_ALIGNED_BSS): New.
+
+2002-02-14 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300-protos.h: Update the prototype for
+ const_costs.
+ * config/h8300/h8300.c (const_costs): Treat SET as a little
+ more expensive operation.
+ * config/h8300/h8300.h (DEFAULT_RTX_COSTS): Update the
+ reference to const_costs.
+
+2002-02-14 Hans-Peter Nilsson <hp@axis.com>
+
+ * config.gcc (c4x-*-rtems*): Fix typo in tm_file setting.
+
+2002-02-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/5503:
+ * c-decl.c (duplicate_decls): If builtin type has TYPE_ARG_TYPES NULL,
+ use arguments from newtype.
+
+2002-02-13 Eric Christopher <echristo@redhat.com>
+
+ * config/mips/mips.c (override_options): Add check for march/mipsX
+ on the same command line. Fix error message in cpu processing.
+ Remove architecture and ISA checks.
+
+2002-02-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/darwin.h (ROUND_TYPE_ALIGN): Adjust for vectors.
+
+ * config/rs6000/sysv4.h (ROUND_TYPE_ALIGN): Add MAX.
+
+2002-02-14 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.md ("*movv4si_internal"): Add m<-r and r<-r
+ alternatives.
+ ("*movv8hi_internal1"): Same.
+ ("*movv16qi_internal1"): Same.
+ ("*movv4sf_internal1"): Same.
+
+ * config/rs6000/rs6000.c (rs6000_legitimize_reload_address): Do
+ not push_reload for altivec modes.
+
+2002-02-13 Joel Sherrill <joel@OARcorp.com>
+
+ * config.gcc (a29k-*-rtems), config/a29k/rtems.h: General cleanup across
+ all RTEMS targets including removal of #includes from config/*/rtems*.h
+ file and adding them to tm_file setting. Added xm_defines=POSIX to
+ many targets.
+ * config.gcc (c4x-*-rtems), config/c4x/rtems.h: Ditto.
+ * config.gcc (h8300-*-rtems), config/h8300/rtems.h: Ditto.
+ * config.gcc (hppa1.1-*-rtems), config/pa/rtems.h: Ditto.
+ * config.gcc (i960-*-rtems), config/i960/rtems.h: Ditto.
+ * config.gcc (m68k-*-rtems*), config/m68k/rtems.h,
+ config/m68k/rtemself.h: Ditto.
+ * config.gcc (mips*-*-rtems*), config/mips/rtems.h,
+ config/mips/rtems64.h: Ditto.
+ * config.gcc (powerpc-*-rtems*), config/rs6000/rtems.h: Ditto.
+ * config.gcc (sh-*-rtems*), config/sh/rtems.h, config/sh/rtemself.h:
+ Ditto.
+ * config.gcc (sparc-*-rtems*), config/sparc/rtems.h,
+ config/sparc/rtemself.h: Ditto.
+ * config.gcc (v850-*-rtems*), config/v850/rtems.h: Ditto.
+ * config.gcc (arm-rtems), config/arm/rtems-elf.h: Ditto plus moved
+ arm-rtems stanza closer to other arm-elf targets and made arm-rtems
+ more like arm-elf.
+ * config.gcc (i[34567]86-*-rtems*), config/i386/djgpp-rtems.h,
+ config/i386/rtems.h, config/i386/rtemself.h: Ditto plus i386-rtemself
+ target made more similar to i386-elf.
+ * config/i386/t-rtems-i386: Added soft float support and multilibs.
+ * config/m68k/t-m68kbare: Add 68040 and 68060 as multilib alternatives to
+ be similar to config/m68k/t-m68kelf.
+ * gthr-rtems.h: Encapsulate with extern "C" for C++.
+
+Wed Feb 13 23:41:15 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * regmove.c (kill_value): Handle subregs.
+
+Wed Feb 13 23:34:30 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (mul patterns): Allow memory operand to be first;
+ add expanders where needed; fix constraints.
+ (min?f_nonieee, max?f_nonieee, SSE TImode patterns):
+ Allow memory operand to be the first.
+
+ * i386.c (ix86_prepare_fp_compare_args): Fix condition for swapping
+ operands.
+
+2002-02-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/5681:
+ * expr.c (safe_from_p): Pass VOIDmode to true_dependence instead of
+ GET_MODE (x).
+
+2002-02-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR optimization/5547:
+ * config/i386/i386.c (i386_simplify_dwarf_addr): Simplify
+ all valid IA-32 address modes involving non-scaled %ebx and
+ GOT/GOTOFF as displacement.
+
+2002-02-13 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.c (s390_final_chunkify): Re-run shorten_branches
+ after emitting ltorg insns.
+
+ * config/s390/s390.md (*cmpdf_ccs_0, *cmpdf_ccs, *cmpsf_ccs_0,
+ *cmpsf_ccs, truncdfsf2_ieee, *adddf3, *addsf3, *subdf3, *subsf3,
+ *muldf3, *mulsf3, *divdf3, *divsf3, *negdf2, *negsf2, *absdf2,
+ *abssf2): Fix "op_type" attribute.
+
+2002-02-13 Douglas B Rupp <rupp@gnat.com>
+
+ * mkconfig.sh: Avoid using a subshell redirect.
+ ($output.T): Change to $(output)T.
+ (ENABLE_NLS): Remove unneeded undef.
+
+ * config/alpha/vms.h (MD_EXEC_PREFIX, MD_STARTFILE_PREFIX): Define.
+ * config/alpha/x-vms (libsubdir): Define.
+
+ * config/alpha/vms.h (MD_FALLBACK_FRAME_STATE_FOR): Handle
+ register frame procedures. Optimize retrieving context.
+
+ * config/alpha/t-vms (MULTILIB_OPTIONS): Define.
+ (MULTILIB_DIRNAME, LIBGCC, INSTALL_LIBGCC): Likewise.
+ * config/alpha/vms.h (ASM_FILE_START): Write .arch directive.
+
+Wed Feb 13 09:45:08 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * alias.c (find_base_term, case ZERO_EXTEND, case SIGN_EXTEND):
+ Make same change as for find_base_value.
+
+2002-02-13 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.h (MODES_TIEABLE_P): Accept a combination
+ of QImode and SImode.
+
+2002-02-13 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (h8300_adjust_insn_length): Correct the
+ length computation of movsi.
+ * config/h8300/h8300.md (movsi_h8300hs): Correct the length.
+
+2002-02-13 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md (subqi3): Tighten the predicate for
+ operands[2] to register_operand.
+
+Wed Feb 13 10:35:56 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (fop_*_comm_*): allow nonimmediate in the first operand.
+
+2002-02-12 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.md: Use predicate altivec_register_operand
+ for altivec_lvx* and altivec_stvx*.
+ ("*movv4si_internal"): Add constraint for loading from GPRs.
+ ("*movv8hi_internal1"): Same.
+ ("*movv16qi_internal1"): Same.
+ ("*movv4sf_internal1"): Same.
+
+ * config/rs6000/rs6000.c (altivec_register_operand): New.
+
+ * config/rs6000/rs6000.h (PREDICATE_CODES): Add
+ altivec_register_operand.
+
+2002-02-13 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.c (mmix_assemble_integer) <case 4>: Don't
+ handle SYMBOL_REF.
+
+2002-02-13 Stan Shebs <shebs@apple.com>
+
+ * c-typeck.c (digest_init): Handle vectors.
+ (really_start_incremental_init): Same.
+ (pop_init_level): Same.
+ (process_init_element): Same.
+
+ * varasm.c (output_constant): Same.
+
+ * expr.c (clear_storage): Same.
+ (store_constructor): Same.
+
+2002-02-12 Eric Christopher <echristo@redhat.com>
+
+ * explow.c (hard_function_value): Add comment explaining
+ signed/unsigned comparison.
+
+2002-02-12 Jakub Jelinek <jakub@redhat.com>
+
+ * jump.c (never_reached_warning): Add finish argument.
+ If finish is NULL, stop on CODE_LABEL, otherwise stop before first
+ real insn after end.
+ * rtl.h (never_reached_warning): Adjust prototype.
+ * cse.c (cse_insn): Pass NULL as finish to never_reached_warning.
+ * cfgrtl.c (flow_delete_block): Pass b->end as finish to
+ never_reached_warning.
+
+2002-02-12 Graham Stott <grahams@redhat.com>
+
+ * config/hp/pa.h (GO_IF_LEGITIMATE_ADDRESS): Fix typos.
+
+2002-02-12 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (shift_alg_hi): Improve the 15-bit
+ logical shifts on H8/300.
+ (shift_alg_si): Improve several shifts on H8/300.
+ (get_shift_alg): Likewise.
+
+2002-02-12 Graham Stott <grahams@redhat.com>
+
+ * config/pa/pa.c (compute_movstrsi_length): Fix typos.
+
+Tue Feb 12 10:12:56 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * alias.c (find_base_value, case ZERO_EXTEND, case SIGN_EXTEND):
+ Handle #ifdef POINTERS_EXTEND_UNSIGNED.
+
+2002-02-11 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.c (mmix_assemble_integer) <case 1, 2>: Handle
+ non-CONST_INT through default_assemble_integer.
+ <case 4>: Likewise, for non-CONST_INT, non-SYMBOL_REF.
+ <case 8>: Abort for CONST_DOUBLE.
+
+2002-02-11 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * gcc.c (init_gcc_specs): Add static libgcc to link when "-shared"
+ is specified.
+ * config/pa/pa-linux.h (LIB_SPEC): Delete.
+ * config/pa/pa32-linux.h (LINK_COMMAND_SPEC): Delete.
+
+2002-02-11 Andrew Haley <aph@cambridge.redhat.com>
+
+ * config/stormy16/stormy16.md (zero_extendqihi2): New.
+
+2002-02-11 Alexandre Oliva <aoliva@redhat.com>
+
+ * regrename.c (regrename_optimize): Don't accept a
+ part-clobbered register if the replaced register is not part
+ clobbered.
+
+ * calls.c (store_one_arg): In the non-BLKmode non-partial case,
+ take padding into account when computing the argument value.
+
+ * config/sh/sh.h (FUNCTION_ARG_REGNO_P): Fix parenthesizing error.
+
+ * combine.c (try_combine): Apply substitutions in
+ CALL_INSN_FUNCTION_USAGE too.
+
+2002-02-11 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c (altivec_init_builtins): Handle
+ __builtin_altivec_abs*.
+ (bdesc_abs): New.
+
+ * config/rs6000/rs6000.h (rs6000_builtins): Add
+ ALTIVEC_BUILTIN_ABS*.
+
+ * config/rs6000/altivec.h: Use const char for builtins expecting
+ literals.
+ (vec_abs): New versions for C and C++.
+ (vec_abss): Same.
+
+2002-02-10 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.h (INITIALIZE_TRAMPOLINE): Simplify by
+ using Pmode.
+
+2002-02-10 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.h (STACK_POINTER_REGNUM): Use the
+ constant definition from h8300.md.
+ (FRAME_POINTER_REGNUM): Likewise.
+ * config/h8300/h8300.md (define_constants): Add FP_REG.
+
+2002-02-10 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (print_operand): Remove redundant code.
+
+2002-02-10 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300-protos.h: Remove the prototype for byte_reg.
+ * config/h8300/h8300.c (byte_reg): Make it static.
+
+2002-02-10 Richard Henderson <rth@redhat.com>
+
+ PR c/5623
+ * c-typeck.c (incomplete_type_error): Handle flexible array members.
+
+2002-02-10 Richard Henderson <rth@redhat.com>
+
+ PR c++/5624
+ * tree.c (append_random_chars): Don't abort if main_input_filename
+ does not exist.
+
+2002-02-10 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/t-mmix (MULTILIB_EXTRA_OPTS): Disable.
+
+2002-02-10 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md (pushhi1_h8300): Correct the mode used.
+ (pushhi1): Likewise.
+
+2002-02-10 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.c (reg_before_reload_operand): Don't accept a SUBREG operand.
+ * pa.h (PREDICATE_CODES): Adjust codes for reg_before_reload_operand.
+
+2002-02-09 David O'Brien <obrien@FreeBSD.org>
+
+ * config/sparc/freebsd.h(TARGET_DEFAULT): Add MASK_EPILOGUE setting and
+ remove MASK_VIS.
+ (ASM_CPU_DEFAULT_SPEC): Remove. Default setting is fine.
+
+2002-02-09 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (output_logical_op): Use sub.w to clear
+ a half of an SImode register on H8/300.
+
+Sat Feb 9 18:28:02 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (movdi_2): Add missing '!'.
+
+2002-02-09 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.h: Fix formatting. Remove commented-out
+ definitions.
+
+2002-02-09 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md (length): Correct the distance valid
+ for the short branch.
+
+2002-02-09 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md (iorhi3): Tighten the predicates.
+
+2002-02-09 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/sh/sh.h (REGISTER_NATURAL_MODE): Save part-clobbered
+ registers in SImode.
+ (HARD_REGNO_CALL_PART_CLOBBERED) [TARGET_SHMEDIA32]: Set r18 as
+ part-clobbered.
+
+ * config/sh/sh.c (expand_prologue): Fix mis-applied 2001-11-09's
+ patch.
+
+ Contribute sh64-elf.
+ 2002-02-09 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.c (TARGET_CANNOT_MODIFY_JUMPS_P): Define to...
+ (sh_cannot_modify_jumps_p): New function.
+ 2002-02-05 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.c (TARGET_MS_BITFIELD_LAYOUT_P): Define to...
+ (sh_ms_bitfield_layout_p): New function.
+ 2002-02-04 Alexandre Oliva <aoliva@redhat.com>
+ Zack Weinberg <zack@codesourcery.com>
+ * config/sh/sh.h (TRAMPOLINE_ADJUST_ADDRESS): Use
+ expand_simple_binop instead of expand_binop.
+ 2002-02-03 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (OVERRIDE_OPTIONS) [! TARGET_SH5]: Disable
+ use of .quad and .uaquad.
+ * config/sh/sh.c (TARGET_ASM_UNALIGNED_DI_OP,
+ TARGET_ASM_ALIGNED_DI_OP): Add comment pointing to the above.
+ 2002-01-24 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (movdi_const, movdi_const_32bit,
+ movdi_const_16bit): Make sure all CONSTs have modes.
+ (sym2PIC): Ditto, but by adjusting all callers.
+ * config/sh/sh.c (calc_live_regs) [TARGET_SHCOMPACT]: Set pr_live
+ if the prologue calls the SHmedia argument decoder or register
+ saver.
+ 2002-01-24 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.c (TARGET_ASM_UNALIGNED_DI_OP): Define.
+ (TARGET_ASM_ALIGNED_DI_OP): Likewise.
+ (sh_expand_epilogue): Don't emit USE of return target register.
+ (prepare_move_operands): Legitimize DImode PIC addresses.
+ (sh_media_register_for_return): Skip tr0, used to initialize the
+ PIC register.
+ (sh_expand_prologue): Remove explicit USE of return register.
+ (nonpic_symbol_mentioned_p): PC is non-PIC. Don't recurse in
+ CONST_DOUBLEs. UNSPEC_GOTPLT is PIC.
+ * config/sh/sh.h (ASM_OUTPUT_DOUBLE_INT): Removed, obsolete.
+ (OVERRIDE_OPTIONS): Don't disable PIC on SH5.
+ (EXTRA_CONSTRAINT_S): Use MOVI_SHORI_BASE_OPERAND_P instead of
+ EXTRA_CONSTRAINT_T.
+ (GOT_ENTRY_P, GOTPLT_ENTRY_P, GOTOFF_P, PIC_ADDR_P): New.
+ (MOVI_SHORI_BASE_OPERAND_P): New.
+ (NON_PIC_REFERENCE_P, PIC_REFERENCE_P): New.
+ (EXTRA_CONSTRAINT_T): Define in terms of them.
+ (OUTPUT_ADDR_CONST_EXTRA): Handle UNSPEC_GOTPLT.
+ * config/sh/sh.md (movsi_media, movsi_media_nofpu,
+ movdi_media, movdi_media_nofpu): Add SIBCALL_REGS class to
+ alternatives supporting TARGET_REGS.
+ (UNSPEC_GOTPLT): New constant.
+ (movdi split): Move incrementing of LABEL_NUSES...
+ (movdi_const, movdi_const_32bit): Here. Use
+ MOVI_SHORI_BASE_OPERAND_P instead of EXTRA_CONSTRAINT_T.
+ (movdi_const_16bit): New.
+ (call, call_value) [flag_pic]: Use GOTPLT.
+ (call_pop, call_value_pop): New expands.
+ (call_pop_compact, call_pop_rettramp): New insns.
+ (call_value_pop_compact, call_value_pop_rettramp): New insns.
+ (sibcall) [flag_pic]: Use GOT.
+ (builtint_setjmp_receiver): Remove bogus, unused expand.
+ (GOTaddr2picreg): Implement for SHcompact and SHmedia.
+ (*pt, *ptb, ptrel): New insns.
+ (sym2GOT): Handle DImode GOT.
+ (sym2GOTPLT, symGOTPLT2reg): New expands.
+ (sym2PIC): New expand.
+ (shcompact_return_tramp): Use GOTPLT to return trampoline.
+ (shcompact_return_tramp_i): Use return register explicitly.
+ * config/sh/sh.h (OVERRIDE_OPTIONS) [TARGET_SHMEDIA]: Don't
+ disable flag_reorder_blocks.
+ 2002-01-19 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (sibcall_compact): Reorder return, uses and
+ clobbers, for clarity.
+ (sibcall_epilogue) [TARGET_SHCOMPACT]: Mark saving and
+ restoring of r0 in macl as MAYBE_DEAD.
+ 2002-01-18 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (LONG_DOUBLE_TYPE_SIZE): Define.
+ * config/sh/sh.md (movv4sf_i, movv16sf_i): Fix uses of
+ alter_subreg all over.
+ (jump) [TARGET_SHMEDIA]: FAIL to create new jumps after
+ reload, instead of emitting instructions that would require
+ reloading.
+ (casesi_load_media): Add missing modes.
+ 2001-11-09 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.c (sh_expand_prologue): Mark the PIC register
+ as used if the argument decoder is called.
+ 2001-08-28 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (udivsi3, divsi3): Load libcall symbol name in
+ Pmode, then extend it to DImode if necessary.
+ 2001-08-28 Stephen Clarke <Stephen.Clarke@st.com>
+ * config/sh/sh.h (LEGITIMATE_CONSTANT_P): Don't accept DFmode
+ constants in FPU-enabled SHmedia, let them be loaded from memory.
+ 2001-08-28 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (cmpeqdi_media, cmpgtdi_media, cmpgtudi_media):
+ Adjust whitespace in assembly output templates.
+ 2001-08-28 Stephen Clarke <Stephen.Clarke@st.com>
+ * config/sh/sh.md (movdicc_false, movdicc_true, movdicc): Adjust
+ mode of if_then_else.
+ 2001-08-04 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh64.h (CPP_DEFAULT_CPU_SPEC): Override definition in
+ sh.h.
+ 2001-07-26 Andrew Haley <aph@cambridge.redhat.com>
+ Joern Rennecke <amylaar@redhat.com>
+ * config/sh/sh64.h (CPP_DEFAULT_CPU_SPEC): New.
+ (SUBTARGET_CPP_PTR_SPEC): New.
+ (SUBTARGET_CPP_SPEC): Remove.
+ 2001-07-06 Chandrakala Chavva <cchavva@redhat.com>
+ * config/sh/sh.md (movsf_media_nofpu+1, movdf_media_nofpu+1):
+ Fix typo in previous checkin.
+ 2001-07-11 Chandrakala Chavva <cchavva@redhat.com>
+ * config/sh/sh.h (MODES_TIEABLE_P): Fix redact indentations.
+ 2001-07-10 Chandrakala Chavva <cchavva@cygnus.com>
+ Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (MODES_TIEABLE_P): Don't tie modes wider than
+ what single FP register can hold for SHmedia target.
+ 2001-07-06 Chandrakala Chavva <cchavva@redhat.com>
+ Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (movsf_media_nofpu+1, movdf_media_nofpu+1):
+ Do not split into SUBREG.
+ 2001-06-14 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/ushmedia.h, config/sh/sshmedia.h: Updated signatures
+ and added new functions as specified in SH5 ABI r9.
+ 2001-06-04 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/lib1funcs.asm (GCC_nested_trampoline): Align to an
+ 8-byte boundary.
+ 2001-06-03 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.c (dump_table): Add const0_rtx in calls of
+ gen_consttable_4 and gen_consttable_8. Emit multiple labels
+ and consttable_window_ends.
+ 2001-06-03 Graham Stott <grahams@redhat,com>
+ * config/sh/sh.md (movdi split): Remove unused variable last_insn.
+ 2001-05-16 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.c (print_operand): Handle floating-point pair,
+ vector and matrix registers.
+ * config/sh/sh.h (REGISTER_MOVE_COST): Take floating-pointer
+ vector modes into account.
+ * config/sh/sh.md (movv2sf): Split move between registers into
+ movdf.
+ (movv4sf, movv16sf): Introduce insns that get split only after
+ reload.
+ * config/sh/shmedia.h: Fix Copyright dates.
+ * config/sh/ushmedia.h: Likewise. Move loop counter
+ declarations into conditionals that uses them.
+ (sh_media_FVADD_S, sh_media_FVSUB_S): Fix off-by-one error in
+ loop boundary.
+ * config/sh/sshmedia.h: Fix Copyright dates.
+ (sh_media_PUTCFG): Fix constraints.
+ 2001-05-12 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (TARGET_PTRMEMFUNC_VBIT_LOCATION): Define to
+ ptrmemfunc_vbit_in_delta for SH5.
+ 2001-05-08 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (TARGET_SWITCHES): Document -m5-*.
+ * invoke.texi: Likewise.
+ 2001-04-14 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/lib1funcs.asm (GCC_push_shmedia_regs,
+ GCC_push_shmedia_regs_nofpu, GCC_pop_shmedia_regs,
+ GCC_pop_shmedia_regs_nofpu): New global symbols.
+ * config/sh/t-sh64 (LIB1ASMFUNCS): Add them.
+ * config/sh/sh.h (SHMEDIA_REGS_STACK_ADJUST): New macro.
+ * config/sh/sh.c (calc_live_regs): Account for PR's saving in
+ compact function with nonlocal labels.
+ (sh_expand_prologue) [SHcompact]: Push SHmedia regs if needed.
+ (sh_expand_epilogue) [SHcompact]: Pop them when appropriate.
+ (initial_elimination_offset): Account for their stack space.
+ * config/sh/sh.md (shmedia_save_restore_regs_compact): New insn.
+ * config/sh/sh.md (movsi_media, movsi_media_nofpu, movqi_media,
+ movhi_media, movdi_media, movdi_media_nofpu, movdf_media,
+ movdf_media_nofpu, movsf_media, movsf_media_nofpu): Require at
+ least one of the operands to be a register.
+ (movv2sf): Likewise. Renamed to movv2sf_i.
+ (movdi, movdf, movv2sf, movv4sf, movv16sf, movsf):
+ prepare_move_operands() before emitting SHmedia insns.
+ 2001-04-03 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/crti.asm (init, fini) [__SH5__ && ! __SHMEDIA__]:
+ Don't save nor initialize r12. Don't mis-align the stack.
+ Pad the code with a nop.
+ * config/sh/crti.asm: Don't restore r12. Don't mis-align the
+ stack.
+ 2001-03-13 Alexandre Oliva <aoliva@redhat.com>
+ * gcc/longlong.h (__umulsidi3, count_leading_zeros)
+ [__SHMEDIA__]: Implement.
+ 2001-03-11 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md: Set latency of `pt' closer to reality.
+ (movsi_media, movsi_media_nofpu, movdi_media, movdi_media_nofpu,
+ movdf_media, movdf_media_nofpu, movsf_media, movsf_media_nofpu):
+ Set move, load and store type attributes.
+ * config/sh/sh.c (sh_loop_align) [TARGET_SH5]: Set to 3.
+ * config/sh/sh.h (OVERRIDE_OPTIONS) [TARGET_SH5]: Disable
+ profiling.
+ * config/sh/sh.h (PROMOTE_MODE): Sign-extend SImode to DImode.
+ * config/sh/sh-protos.h (sh_media_register_for_return): Declare.
+ * config/sh/sh.c (sh_media_register_for_return): New function.
+ (sh_expand_prologue) [TARGET_SHMEDIA]: Copy r18 to an available
+ branch-target register.
+ (sh_expand_epilogue) [TARGET_SHMEDIA]: Explicitly USE it.
+ * config/sh/sh.md (return_media_i): Use any call-clobbered
+ branch-target register.
+ (return_media): If r18 wasn't copied in the prologue, copy it
+ here.
+ * config/sh/sh.h (CONDITIONAL_REGISTER_USAGE) [TARGET_SHMEDIA]:
+ Clear class FP0_REGS.
+ * config/sh/sh64.h (LINK_SPEC): Removed incorrect default copied
+ from elf.h.
+ 2001-03-08 DJ Delorie <dj@redhat.com>
+ * config/sh/sh.h (OVERRIDE_OPTIONS): Disable relaxing for SHMEDIA.
+ 2001-02-09 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (sibcall_compact): Set fp_mode to single.
+ 2001-02-07 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (INT_ASM_OP) [SHMEDIA64]: Use `.quad'.
+ 2001-02-03 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (INIT_CUMULATIVE_ARGS): Compute size of BLKmode
+ return value correctly for call_cookie.
+ 2001-02-01 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/crt1.asm (start): Modified so as to call
+ ___setup_argv_and_call_main.
+ 2001-01-26 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Don't count stack_regs in
+ SHmedia mode.
+ 2001-01-20 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (STRIP_DATALABEL_ENCODING): New macro.
+ (STRIP_NAME_ENCODING): Use it.
+ (ASM_OUTPUT_LABELREF): Likewise. Don't call assemble_name().
+ 2001-01-19 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (sgeu) [! SHMEDIA]: Fix invocation of
+ prepare_scc_operands().
+ * config/sh/sh.h (SH_DATALABEL_ENCODING): Change to "#"...
+ (DATALABEL_SYMNAME_P): ... so that we don't need memcmp here.
+ 2001-01-17 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (STRIP_NAME_ENCODING): Strip leading `*'.
+ 2001-01-13 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (shcompact_incoming_args): Use R0_REG.
+ * config/sh/sh.md (R7_REG, R8_REG, R9_REG): Define as constants,
+ used in shcompact_incoming_args.
+ * config/sh/sh.c (sh_expand_epilogue): Fix thinko in previous
+ change.
+ * config/sh/crt1.asm (start) [SH5]: Switch to single-precision
+ mode.
+ * config/sh/lib1funcs.asm (sdivsi3_i4, udivsi3_i4, set_fpscr):
+ Adjust accordingly.
+ * config/sh/sh.c (sh_expand_prologue, sh_expand_epilogue):
+ Simplify. Adjust. Add sanity check.
+ * config/sh/sh.h (TARGET_SWITCHES) [5-compact]: Set
+ FPU_SINGLE_BIT.
+ * config/sh/sh.md (udivsi3_i4_single, divsi3_i4_single): Match
+ TARGET_SHCOMPACT.
+ (udivsi3, divsi3): Use them.
+ (force_mode_for_call): New insn.
+ (call, call_value, sibcall_value): Emit it before SHcompact
+ calls.
+ 2001-01-11 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (call, call_value, sibcall): Make sure the
+ call cookie is non-NULL before taking its value.
+ 2001-01-10 Alexandre Oliva <aoliva@redhat.com>
+ * config.gcc (sh64): Set target_requires_64bit_host_wide_int.
+ 2001-01-09 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (shcompact_incoming_args): Set argument memory
+ block.
+ * config/sh/sh.h (STATIC_CHAIN_REGNUM) [SH5]: Use r1.
+ * config/sh/sh.c (sh_expand_prologue) [SH5]: Use r0 as
+ temporary for stack adjusts. Use MACL and MACH to pass
+ arguments to shcompact_incoming_args.
+ * config/sh/sh.md (shcompact_incoming_args): Adjust. Don't
+ clobber r1.
+ * config/sh/lib1funcs.asm (shcompact_incoming_args): Likewise.
+ (nested_trampoline): Load static chain address into r1.
+ * config/sh/sh.md (movdi_media splits): Fix sign-extension.
+ 2001-01-07 Alexandre Oliva <aoliva@redhat.com
+ * config/sh/sh.c (fpul_operand) [SHMEDIA]: Just call
+ fp_arith_reg_operand().
+ 2001-01-06 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (casesi): Sign-extend the first two operands,
+ and use signed compares for them.
+ * config/sh/sh.c (dump_table): Don't emit 8-byte constants after
+ 4-byte ones. Instead, inter-leave them, maintaining the 8-byte
+ ones properly aligned.
+ (find_barrier): Account for extra alignment needed for 8-byte wide
+ constants.
+ (machine_dependent_reorg): Require a label for the second 4-byte
+ constant after an 8-byte one.
+ * config/sh/lib1funcs.asm (sdivsi3): Fix typo in yesterday's
+ change.
+ 2001-01-05 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.c (machine_dependent_reorg) [SHCOMPACT]: Reset
+ last_float when switching float modes.
+ * config/sh/sh.md (movdf) [SH5]: Don't use stack-pointer
+ auto-increment for general-purpose registers.
+ * config/sh/lib1funcs.asm (sdivsi3) [SHMEDIA]: Sign-extend the
+ result.
+ * config/sh/sh.c (sh_expand_prologue) [SH5]: Use r1 as temporary
+ for stack adjust.
+ * config/sh/sh.c (sh_builtin_saveregs): Support using all
+ registers for varargs.
+ 2001-01-01 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Simplify.
+ * config/sh/sh.h (CALL_COOKIE_STACKSEQ,
+ CALL_COOKIE_STACKSEQ_SHIFT, CALL_COOKIE_STACKSEQ_GET): New macros.
+ (CALL_COOKIE_INT_REG_SHIFT): Adjust.
+ (FUNCTION_ARG_ADVANCE): Use SHCOMPACT_FORCE_ON_STACK. Adjust
+ call_cookie accordingly.
+ (FUNCTION_ARG): Test SHCOMPACT_FORCE_ON_STACK.
+ (SHCOMPACT_BYREF): Likewise.
+ (SHCOMPACT_FORCE_ON_STACK): New macro.
+ * config/sh/sh.c (sh_expand_prologue): Use new call_cookie format.
+ (sh_builtin_saveregs): Likewise.
+ * config/sh/lib1funcs.asm (shcompact_call_trampoline,
+ shcompact_incoming_args): Use new shift values. Support
+ sequences of consecutive and non-consecutive pushes/pops.
+ * config/sh/sh.md (return): Don't explicitly use PR_REG.
+ 2001-01-05 Hans-Peter Nilsson <hpn@cygnus.com>
+ * config/sh/sh.h (TEXT_SECTION): Define.
+ * config/sh/elf.h (ASM_FILE_START): Output TEXT_SECTION_ASM_OP.
+ 2001-01-05 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (INIT_CUMULATIVE_LIBCALL_ARGS): New macro.
+ * config/sh/sh.h (BASE_RETURN_VALUE_REG): Use FP regs for
+ return values on FPU-enabled SHmedia.
+ (FUNCTION_VALUE_REGNO_P): Mark FIRST_FP_RET_REG as used on
+ FPU-enabled SHmedia.
+ (INIT_CUMULATIVE_ARGS): Set up return trampoline only if
+ value is returned in a non-FP reg and is not returned by
+ reference.
+ * config/sh/sh.md (shcompact_return_tramp_i): Change type to
+ jump_ind.
+ 2000-01-04 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (SH_MIN_ALIGN_FOR_CALLEE_COPY): New.
+ (FUNCTION_ARG_CALLEE_COPIES): Require argument to be
+ quad-aligned to be passed by callee-copy reference.
+ 2001-01-03 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/elf.h (MAX_WCHAR_TYPE_SIZE): Define.
+ * config/sh/sh64.h (MAX_WCHAR_TYPE_SIZE): Undefine.
+ 2001-01-02 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/lib1funcs.asm (shcompact_call_trampoline): Fix error in
+ copying low-numbered FP regs to r7 and r8.
+ * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Don't request copying of
+ FP regs to general-purpose regs only if the copy was passed on the
+ stack.
+ * config/sh/lib1funcs.asm (shcompact_call_trampoline): Fix typo in
+ copying FP reg to r9.
+ * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Use trampoline to
+ copy FP regs to general-purpose regs only in outgoing calls.
+ * config/sh/sh.md (movdf_media, movsf_media): Revert incorrect
+ change from 2000-10-30. Adjust for 64-bit (or 32-bit)
+ HOST_WIDE_INT.
+ * config/sh/sh.h (struct sh_args): Document all fields.
+ (FUNCTION_OK_FOR_SIBCALL): Functions that receive arguments
+ passed partially on the stack should not consider making
+ sibcalls.
+ * config/sh/sh.h (FUNCTION_ARG_ADVANCE): Add byref regs to
+ stack_regs only for incoming calls. When passing FP args,
+ make sure there are FP regs available before modifying
+ call_cookie.
+ (SHCOMPACT_BYREF): Pass double args in general-purpose
+ registers by reference.
+ 2000-12-30 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (FUNCTION_OK_FOR_SIBCALL) [SHCOMPACT]: Don't
+ attempt to generate sibcalls if the caller got any arguments
+ by reference.
+ * config/sh/lib1funcs.asm (set_fpscr) [SH5]: Default to double.
+ * config/sh/sh.c (dump_table) [SHCOMPACT]: Align DImode and DFmode
+ to 8-byte boundaries.
+ * config/sh/sh.md (shcompact_preserve_incoming_args): New insn.
+ * config/sh/sh.h (CALL_COOKIE_INT_REG_GET): New macro.
+ * config/sh/sh.c (sh_expand_prologue): Preserve args that will be
+ stored in the stack.
+ * config/sh/lib1funcs.asm (ct_main_table, ia_main_table): Arrange
+ for the offsets to have the ISA bit set.
+ (shcompact_call_trampoline): Document. Swap r0 and r1, to match
+ invocation. Use beq instead of bgt to mark end of sequence of
+ loads.
+ (shcompact_incoming_args): Fix store of r2. Use beq instead of
+ bgt to mark end of sequence of stores.
+ * config/sh/sh.c (arith_operand): Don't check whether
+ CONST_OK_FOR_J for now.
+ * config/sh/sh.md (movdf_media, movsf_media): Use HOST_WIDE_INT
+ instead of long for conversion.
+ 2000-12-29 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.c (print_operand_address): Convert INTVAL to int
+ before passing it to fprintf.
+ 2000-12-28 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/crt1.asm (start): Reset SR.FD, to enable the FP unit.
+ Call set_fpscr before reading/writing SR.
+ * config/sh/crt1.asm (start): Set SR.SZ and SR.PR, but not SR.FR.
+ Call set_fpscr.
+ * config/sh/lib1funcs.asm: Add `.align 2' directives before
+ SHmedia code.
+ (FMOVD_WORKS): Define on SH5 with FPU.
+ (set_fpscr): Define on SH5. Remove separate _fpscr_values
+ setting.
+ * config/sh/t-sh64 (LIB1ASMFUNCS): Add _set_fpscr instead of
+ _fpscr_values.
+ 2000-12-28 Hans-Peter Nilsson <hpn@cygnus.com>
+ * config/sh/lib1funcs.asm (ct_main_table): Align contents to even
+ address.
+ (ia_main_table): Ditto.
+ 2000-12-27 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (MAX_WCHAR_TYPE_SIZE): Don't define.
+ * config/sh/sh64.h (WCHAR_TYPE, WCHAR_TYPE_SIZE): Reinstate
+ the definitions from sh.h.
+ * config/sh/sh.h (PTRDIFF_TYPE): Define as conditional on
+ TARGET_SH5.
+ (SUBTARGET_CPP_SPEC): Arrange for __PTRDIFF_TYPE__ to be defined.
+ * config/sh/elf.h (PTRDIFF_TYPE): Likewise.
+ * config/sh/sh64.h (SUBTARGET_CPP_SPEC): Likewise.
+ 2000-12-26 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (movdi_media split): Don't add REG_LABEL notes.
+ Increment LABEL_NUSES.
+
+ * config/sh/sh.h (SIZE_TYPE): Define as conditional on
+ TARGET_SH5.
+ (SUBTARGET_CPP_SPEC): Arrange for __SIZE_TYPE__ to be always
+ defined.
+ * config/sh/elf.h (SIZE_TYPE): Likewise.
+ * config/sh/sh64.h (SUBTARGET_CPP_SPEC): Likewise.
+ * config/sh/lib1funcs.asm (shcompact_call_trampoline,
+ shcompact_incoming_args): Load switch table addresses using
+ datalabel.
+ * config/sh/sh.h (SUBTARGET_CPP_SPEC): Define __SIZE_TYPE__.
+ (NO_BUILTIN_SIZE_TYPE): Define.
+ (SIZE_TYPE): Don't define.
+ * config/sh/sh64.h (SUBTARGET_CPP_SPEC): Define __SIZE_TYPE__.
+ * config/sh/sh.h (CPP_SPEC): Fixed typo that prevented the
+ definition of __SH5__=32 for -m5-compact-nofpu.
+ * config/sh/sh.c (barrier_align): Ensure 32-bit alignment after
+ ADDR_DIFF_VEC.
+ 2000-12-24 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (FUNCTION_ARG_PADDING): Removed.
+ 2000-12-23 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (TARGET_CACHE32): Enable on SH5.
+ (FUNCTION_BOUNDARY): Ensure 32-bit alignment for SHmedia.
+ (INSN_LENGTH_ALIGNMENT): Likewise.
+ 2000-12-22 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (call, call_value, sibcall): Simplify
+ copying of non-branch-target register.
+ 2000-12-22 Alexandre Oliva <aoliva@redhat.com>
+ * glimits.h (__LONG_MAX__): Revert 2000-12-13's patch.
+ * config/sh/sh.h (CPP_SPEC): Define it here for 64-bit SHmedia.
+ 2000-12-22 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (GET_SH_ARG_CLASS): Handle complex
+ floating-point values as structs.
+ (FUNCTION_ARG): Use SH5_PROTOTYPED_FLOAT_ARG.
+ (SH5_PROTOTYPELESS_FLOAT_ARG): List FP registers before
+ general-purpose register.
+ (SH5_PROTOTYPED_FLOAT_ARG): New macro.
+ 2000-12-20 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (addsi3): Force operand1 to reg for SHmedia.
+ * config/sh/sh.md (movsi_media): Split CONST_DOUBLE loads too.
+ * config/sh/sh.h (DATALABEL_REF_P): Don't require the CONST.
+ (ENCODE_SECTION_INFO): Enclose variables and constants in
+ DATALABEL unspecs.
+ (SH_DATALABEL_ENCODING, DATALABEL_SYMNAME_P): Define.
+ (STRIP_NAME_ENCODING): Strip SH_DATALABEL_ENCODING off.
+ (ASM_OUTPUT_LABELREF, AMS_OUTPUT_SYMBOL_REF): Define.
+ * config/sh/sh.c (gen_datalabel_ref): Use UNSPEC_DATALABEL
+ only for LABEL_REFs. For SYMBOL_REFs, prepend
+ SH_DATALABEL_ENCODING to the symbol name.
+ * config/sh/sh.md (indirect_jump): Use SUBREG instead of
+ convert_mode().
+ 2000-12-20 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (casesi): Enclose ADDR_DIFF_VEC address in
+ UNSPEC_DATALABEL.
+ * config/sh/sh.c (gen_datalabel_ref): Accept LABEL_REFs.
+ * config/sh/sh.h (DATALABEL_REF_NO_CONST_P): Likewise.
+ (DATALABEL_REF_P): Don't require CONST.
+ (ASM_OUTPUT_ADDR_DIFF_ELT): On SH5, output datalabel before
+ REL label.
+ 2000-12-19 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (extendhidi2, extendqidi2): Use arithmetic shift
+ right.
+ 2000-12-18 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (movsi_media, call, call_value, sibcall):
+ Use shallow_copy_rtx and PUT_MODE to change the mode of
+ SYMBOL_REFs, LABEL_REFs, CONSTs, etc.
+ * config/sh/sh.h (PREFERRED_RELOAD_CLASS): Reload SYMBOL_REFs
+ on SHmedia using GENERAL_REGs.
+ * config/sh/sh.md (ble_media_i, blt_media_i, bleu_media_i,
+ bltu_media_i): Fix reversion of conditions.
+ 2000-12-18 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.md (zero_extendhidi2): Use logical shift right.
+ * config/sh/sh.c (output_far_jump): Save r13 in macl.
+ 2000-12-17 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.c (gen_datalabel_ref): Fix mode of the UNSPEC.
+ 2000-12-16 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/lib1funcs.asm (ic_invalidate): Define for SH5.
+ (GCC_nested_trampoline): Likewise.
+ * config/sh/sh-protos.h (gen_datalabel_ref): Declare.
+ * config/sh/sh.c (gen_datalabel_ref): Define.
+ * config/sh/sh.h (TRAMPOLINE_SIZE): Adjust for SH5.
+ (INITIALIZE_TRAMPOLINE): Likewise.
+ (TRAMPOLINE_ADJUST_ADDRESS): Define.
+ (DATALABEL_REF_NO_CONST_P, DATALABEL_REF_P): Define.
+ (EXTRA_CONSTRAINT_T): Match DATALABEL unspecs.
+ (OUTPUT_ADDR_CONST_EXTRA): Handle DATALABEL unspecs.
+ * config/sh/sh.md (UNSPEC_DATALABEL): New constant.
+ (ic_invalidate): Adjust for SH5.
+ (ic_invalidate_line_media, ic_invalidate_line_compact): New insns.
+ * config/sh/t-sh64 (LIB1ASMFUNCS): Added _ic_invalidate and
+ _nested_trampoline.
+ 2000-12-15 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (MOVE_MAX): Set to 8 for SHmedia, 4 elsewhere.
+ (MOVE_MAX_PIECES): Set to 8 on SHmedia too.
+ 2000-12-14 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (DBX_REGISTER_NUMBER): Adjust for sh64-elf-gdb.
+ * config/sh/elf.h (DBX_REGISTER_NUMBER): Likewise.
+ 2000-12-14 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.c (target_reg_operand): Match only target-branch
+ registers and pseudos that aren't virtual registers.
+ * config/sh/sh.md (call, call_value, sibcall) [TARGET_SHMEDIA]:
+ Copy operands that don't match target_reg_operand to pseudos.
+ (call_media, call_value_media, sibcall_media): Use
+ target_reg_operand instead of target_operand.
+ 2000-12-13 Alexandre Oliva <aoliva@redhat.com>
+ * glimits.h (__LONG_MAX__) [SH5 == 64]: Adjust for 64 bits.
+ * config/sh/sh.c (target_reg_operand): Match hardware registers
+ other than branch-target registers.
+ * config/sh/sh.md (zero_extendqidi2): Input operand is %1.
+ * config/sh/lib1funcs.asm (sdivsi3) [SH5]: Make it global.
+ (fpscr_values) [SH5 == 32]: Define.
+ * config/sh/t-sh64 (LIB1ASMFUNCS): Add fpscr_values.
+ * config/sh/sh.md (call, call_value, sibcall) [TARGET_SHMEDIA]:
+ Handle function addresses coming in SUBREGs.
+ 2000-12-12 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/lib1funcs.asm (shcompact_call_trampoline,
+ shcompact_return_trampoline): Use datalabel where appropriate.
+ 2000-12-09 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (SECONDARY_OUTPUT_RELOAD_CLASS): Use a
+ general-purpose register to copy one branch-target register to
+ another.
+ 2000-12-06 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.c (target_operand): Accept LABEL_REFs and
+ SYMBOL_REFs with VOIDmode.
+ * config/sh/sh.md (ble_media_i, blt_media_i, bleu_media_i,
+ bltu_media_i): New insns.
+ 2000-12-06 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (RETURN_IN_MEMORY): Adjust for SH5 ABI.
+ (INIT_CUMULATIVE_ARGS): Likewise.
+ 2000-12-01 Alexandre Oliva <aoliva@redhat.com>
+ * machmode.def (V16SFmode): New mode.
+ * c-common.c (type_for_mode): Support V2SF and V16SF.
+ * tree.c (build_common_tree_nodes_2): Likewise.
+ * tree.h (tree_index): Likewise.
+ * calls.c (emit_call_1): Take args_so_far. Adjust all
+ callers. Introduce CALL_POPS_ARGS.
+ * tm.texi (CALL_POPS_ARGS): Document.
+ * config/sh/crt1.asm: Implement in SHmedia mode.
+ * config/sh/crti.asm, config/sh/crtn.asm: Likewise
+ * config/sh/elf.h (ASM_SPEC, LINK_SPEC): Support SH5 flags.
+ (DBX_REGISTER_NUMBER): Renumber registers for SH5.
+ * config/sh/lib1funcs.asm: Disable functions unused in SH5.
+ Implement divsi and udivsi in SHmedia mode. Introduce
+ SHcompact trampolines.
+ * config/sh/sh.c (GEN_MOV, GEN_ADD3, GEN_SUB3): Use DImode
+ only in SHmedia64.
+ (regno_reg_class): Rewrite.
+ (fp_reg_names): Remove.
+ (sh_register_names, sh_additional_register_names): New.
+ (print_operand): Added `u'. Support SUBREGs in addresses.
+ Add parentheses around shifted CONSTs.
+ (output_file_start): Output .mode and .abi directives.
+ (shiftcosts, addsubcosts, multcosts): Adjust.
+ (output_stack_adjust): Compute alignment. Sanity-check SIZE.
+ (push_regs): Take array of HOST_WIDE_INTs. Adjust callers.
+ (calc_live_regs): Output to array of HOST_WIDE_INTs. Count
+ bytes, not registers. Take into account the need for the
+ SHcompact incoming args trampoline. Adjust all callers.
+ (sh_expand_prologue): Take stack_regs into account. Call
+ incoming args trampoline. Keep stack aligned as per SH5 ABI.
+ (sh_expand_epilogue): Take stack_regs into accoutn. Keep
+ stack aligned as per SH5 ABI.
+ (sh_builtin_saveregs): Support SH5 ABI.
+ (sh_build_va_list, sh_va_start): Likewise.
+ (initial_elimination_offset): Take alignment into account.
+ Compute location of PR according to the SH5 stack frame.
+ (arith_reg_operand): Reject branch-target registers.
+ (shmedia_6bit_operand): New.
+ (logical_operand): Use CONST_OK_FOR_P on SHmedia.
+ (target_reg_operand): Match DImode only. Accept SUBREGs.
+ (target_operand): New.
+ * config/sh/sh.h (CPP_SPEC, SUBTARGET_CPP_SPEC): Support SH5 flags.
+ (CONDITIONAL_REGISTER_USAGE): Implement SH5 ABI. Initialize
+ SIBCALL_REGS for SHmedia.
+ (TARGET_SH3E, TARGET_SH4): Only if SH1_BIT is set too.
+ (TARGET_FPU_DOUBLE, TARGET_FPU_ANY): New.
+ (TARGET_SHMEDIA32, TARGET_SHMEDIA64): New.
+ (TARGET_SWITCHES): New SH5 flags.
+ (OVERRIDE_OPTIONS): Set SH5-specific options. Use
+ VALID_REGISTER_P to disable unsupported registers.
+ (LONG_TYPE_SIZE, LONG_LONG_TYPE_SIZE): Set.
+ (POINTER_SIZE, PARM_BOUNDARY): Adjust.
+ (FUNCTION_ARG_PADDING): Define.
+ (FASTEST_ALIGNMENT): Adjust.
+ (SH_REGISTER_NAMES_INITIALIZER): New.
+ (sh_register_names): Declare.
+ (DEBUG_REGISTER_NAMES): Define.
+ (REGISTER_NAMES): Define based on sh_register_names.
+ (SH_ADDITIONAL_REGISTER_NAMES_INITIALIZER): New.
+ (sh_additional_register_names): Declare.
+ (LAST_GENERAL_REG, LAST_FP_REG, LAST_XD_REG): Adjust for SHmedia.
+ (FIRST_TARGET_REG, LAST_TARGET_REG): Define.
+ (TARGET_REGISTER_P, SHMEDIA_REGISTER_P, VALID_REGISTER_P): Define.
+ (REGISTER_NATURAL_MODE): Define.
+ (FIRST_PSEUDO_REGISTER): Adjust.
+ (FIXED_REGISTERS, CALL_USED_REGISTERS): Adjust.
+ (HARD_REGNO_CALL_PART_CLOBBERED): Define.
+ (HARD_REGNO_NREGS, HARD_REGNO_MODE_OK): Adjust.
+ (VECTOR_MODE_SUPPORTED_P): Define.
+ (REG_CLASS_CONTENTS): Adjust.
+ (SMALL_REGISTER_CLASSES): Adjust.
+ (REG_ALLOC_ORDER): Adjust.
+ (INDEX_REG_CLASS): Adjust.
+ (CONST_OK_FOR_O, CONST_OK_FOR_P): New.
+ (CONST_OK_FOR_LETTER_P): Adjust.
+ (PREFERRED_RELOAD_CLASS): Adjust.
+ (SECONDARY_OUTPUT_RELOAD_CLASS): Adjust.
+ (SECONDARY_INPUT_RELOAD_CLASS): Adjust.
+ (NPARM_REGS, FIRST_PARM_REG, FIRST_RET_REG): Adjust.
+ (FIRST_FP_PARM_REG): Adjust.
+ (CALL_POPS_ARGS): Define.
+ (FUNCTION_ARG_REGNO_P): Adjust.
+ (struct sh_args): New fields.
+ (GET_SH_ARG_CLASS): Adjust.
+ (INIT_CUMULATIVE_ARGS): Adjust.
+ (INIT_CUMULATIVE_INCOMING_ARGS): Define.
+ (FUNCTION_ARG_ADVANCE): Adjust.
+ (FUNCTION_ARG): Adjust.
+ (FUNCTION_ARG_PASS_BY_REFERENCE, SHCOMPACT_BYREF): Define.
+ (FUNCTION_ARG_CALLEE_COPIES): Define.
+ (SH5_PROTOTYPELESS_FLOAT_ARG): Define.
+ (STRICT_ARGUMENT_NAMING): Define.
+ (PRETEND_OUTGOING_VARARGS_NAMED): Adjust.
+ (FUNCTION_ARG_PARTIAL_NREGS): Adjust.
+ (SH5_WOULD_BE_PARTIAL_NREGS): Define.
+ (SETUP_INCOMING_VARARGS): Adjust.
+ (HAVE_POST_INCREMENT, HAVE_PRE_DECREMENT): Adjust.
+ (USE_LOAD_POST_INCREMENT, USE_STORE_PRE_DECREMENT): Adjust.
+ (REGNO_OK_FOR_INDEX_P, REG_OK_FOR_INDEX_P): Adjust.
+ (SUBREG_OK_FOR_INDEX_P): Adjust.
+ (EXTRA_CONSTRAINT_S): Update.
+ (EXTRA_CONSTRAINT_T): New.
+ (EXTRA_CONSTRAINT): Adjust.
+ (GO_IF_LEGITIMATE_INDEX): Adjust.
+ (GO_IF_LEGITIMATE_ADDRESS): Adjust.
+ (LEGITIMIZE_ADDRESS, LEGITIMIZE_RELOAD_ADDRESS): Adjust.
+ (MOVE_MAX): Adjust.
+ (MAX_MOVE_MAX): Define.
+ (Pmode): Adjust.
+ (CONST_COSTS): Adjust.
+ (REGISTER_MOVE_COST): Adjust.
+ (BRANCH_COST): Adjust.
+ (TEXT_SECTION_ASM_OP): Adjust.
+ (DBX_REGISTER_NUMBER): Adjust.
+ (ASM_OUTPUT_DOUBLE_INT): New.
+ (UNALIGNED_DOUBLE_INT_ASM_OP): New.
+ (PREDICATE_CODES): Adjust.
+ (PROMOTE_MODE): Adjust.
+ (CRT_CALL_STATIC_FUNCTION): Do not define for SHmedia.
+ * config/sh/sh.md (AP_REG, PR_REG, T_REG, GBR_REG): Renumber.
+ (MACH_REG, MACL_REG, FPUL_REG, RAP_REG, FPSCR_REG): Renumber.
+ (PR_MEDIA_REG, T_MEDIA_REG, R10_REG): New.
+ (DR0_REG, DR2_REG, DR4_REG): Renumber.
+ (TR0_REG, TR1_REG, TR2_REG): New.
+ (XD0_REG): Renumber.
+ (UNSPEC_COMPACT_ARGS): New.
+ (type): Added pt and ptabs.
+ (length): Default to 4 on SHmedia. Default pt length to 12
+ and 20 on SHmedia32 and SHmedia64, respectively.
+ (pt): New function unit.
+ (movdi, movsi): Add types pt and ptabs. Don't increment LABEL_NUSES.
+ Add whitespace between operands of SHmedia instructions.
+ (movdicc): Fix.
+ (adddi3_media, addsi3_media): Adjust constraints.
+ (subsi3) [SHmedia]: Force operand 1 into a register.
+ (udivsi3_i1_media, udivsi3_i4_media): New.
+ (udivsi3): Support SHmedia.
+ (divsi3_i1_media, divsi3_i4_media): New.
+ (divsi3): Support SHmedia.
+ (anddi3, iordi3, xordi3): Adjust constraints.
+ (zero_extendhidi2, zero_extendqidi2): New.
+ (extendsidi2, extendhidi2, extendqidi2): New.
+ (push, pop, push_e, push_fpul, push_4): Disable on SH5.
+ (pop_e, pop_fpul, pop_4): Likewise.
+ (movsi_media): Support FP and BT registers.
+ (movsi_media_nofpu): New. Adjust splits to DImode.
+ (lduw, ldub): Renamed to zero_extend* above.
+ (movqi_media): Fix typo.
+ (movdi_media): Support FP and BT registers.
+ (movdi_media_nofpu): New. Adjust splits for SHmedia32.
+ (movdi_const_32bit): New.
+ (shori_media): Require immediate operand. Use `u' for output.
+ (movdf_media, movsf_media): Simplified.
+ (movdf_media_nofpu, movsf_media_nofpu): New.
+ (movdf, movsf): Adjust
+ (movv2sf, movv2sf, movv16sf): New.
+ (beq_media, beq_media_i): Adjust constraints. Don't use
+ scratch BT register.
+ (bne_media, bne_media_i): Likewise.
+ (bgt_media, bgt_media_i): Likewise.
+ (bge_media, bge_media_i): Likewise.
+ (bgtu_media, bgtu_media_i): Likewise.
+ (bgeu_media, bgeu_media_i): Likewise.
+ (beq, bne, bgt, blt, ble, bge, bgtu, bltu, bgeu, bleu,
+ bunordered): Emit jump insn. Force operands to registers when
+ needed.
+ (jump_media, jump): Simplify.
+ (call_compact, call_compact_rettramp): New.
+ (call_value_compact, call_value_compact_rettramp): New.
+ (call_media, call_value_media): Simplify.
+ (sibcall_compact, sibcall_media): New.
+ (call, call_value): Adjust for SHmedia and SHcompact.
+ (sibcall, sibcall_value, untyped_call): Likewise.
+ (sibcall_epilogue): Preserve r0 across epilogue for SHcompact.
+ (indirect_jump): Adjust for SHmedia.
+ (casesi_jump_media): New.
+ (nop): Re-enable for SHmedia.
+ (call_site): Restrict to SH1.
+ (casesi): Adjust for SHmedia.
+ (casesi_shift_media, casesi_load_media): New.
+ (return): Explicitly use PR register. Call return trampoline
+ on SHcompact.
+ (return_i): Explicitly use PR register.
+ (shcompact_return_tramp, shcompact_return_tramp_i): New.
+ (return_media): Adjust.
+ (shcompact_incoming_args): New.
+ (epilogue): Adjust.
+ (seq, slt, sle, sgt, sge, sgtu, sltu, sleu, sgeu, sne): Adjust.
+ (movstrsi): Disable on SH5.
+ (fpu_switch0, fpu_switch1, movpsi): Enable on SH4.
+ (addsf3, addsf3_media): Test TARGET_SHMEDIA_FPU.
+ (subsf3, subsf3_media): Likewise.
+ (mulsf3, mulsf3_media, mac_media): Likewise.
+ (divsf3, divsf3_media): Likewise.
+ (floatdisf2, floatsisf2_media): Likewise. Adjust constraints.
+ (floatsisf2, fux_truncsfsi2): Likewise.
+ (fix_truncsfdi2, fix_truncsfsi2_media): Likewise. Adjust
+ constraints.
+ (cmpeqsf_media, cmpgtsf_media, cmpgesf_media): Likewise.
+ (cmpunsf_media, cmpsf): Likewise.
+ (negsf2, negsf2_media, sqrtsf2, sqrtsf2_media): Likewise.
+ (abssf2, abssf2_media): Likewise.
+ (adddf3, adddf3_media, subdf3, subdf3_media): Likewise.
+ (muldf3, muldf3_media, divdf3, divdf3_media): Likewise.
+ (floatdidf2, floatsidf2_media): Likewise. Adjust constraints.
+ (floatsidf2, fix_truncdfsi2): Likewise.
+ (fix_truncdfdi2, fix_truncdfsi2_media): Likewise. Adjust
+ constraints.
+ (cmpeqdf_media, cmpgtdf_media): Likewise.
+ (cmpgedf_media, cmpundf_media, cmpdf): Likewise.
+ (negdf2, negdf2_media, sqrtdf2, sqrtdf2_media): Likewise.
+ (absdf2, absdf2_media): Likewise.
+ (extendsfdf2, extendsfdf2_media): Likewise.
+ (truncsfdf2, truncsfdf2_media): Likewise.
+ * config/sh/sh64.h: New file.
+ * config/sh/t-sh64: New file.
+ * config/sh/shmedia.h: New file.
+ * config/sh/ushmedia.h: New file.
+ * config/sh/sshmedia.h: New file.
+ * configure.in: Added sh64-*-elf.
+ * configure: Rebuilt.
+ 2000-10-10 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.c (GEN_MOV, GEN_ADD3, GEN_SUB3): New macros.
+ (reg_class_from_letter): Use `b' for TARGET_REGS.
+ (print_operand): Support `%M', `%m', `AND' and
+ `ASHIFTRT'. Do not precede constants with `#' on SHmedia.
+ (andcosts): Adjust for SHmedia.
+ (output_stack_adjust, sh_expand_prologue, sh_expand_epilogue):
+ Likewise.
+ (target_reg_operand): New function.
+ * config/sh/sh-protos.h (target_reg_operand): Declare.
+ * config/sh/sh.h (CONDITIONAL_REGISTER_USAGE): Don't disable
+ FP registers on SH5.
+ (HARD_REGNO_MODE_OK): Accept them whenever they're acceptable
+ on SH4.
+ (TARGET_REGISTER_P): New macro.
+ (reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS): Added TARGET_REGS.
+ (FUNCTION_VALUE): Use DImode for promoted types on SHmedia.
+ (EXTRA_CONSTRAINT_S): New macro.
+ (EXTRA_CONSTRAINT): Adjust.
+ (FLOAT_TYPE_SIZE): Define to 32.
+ (Pmode): DImode on SHmedia.
+ (CONST_COSTS): Adjust for SHmedia literals.
+ (PREDICATE_CODES): Added target_reg_operand.
+ (PROMOTE_MODE): Promote signed types to DImode on SHmedia.
+ * config/sh/sh.md: Remove all attrs from SHmedia insns.
+ (cmpeqdi_media, cmpgtdi_media, cmpgtudi_media): New insns.
+ (cmpdi): Accept SHmedia.
+ (movdicc_false, movdicc_true): New insns.
+ (movdicc): New expand.
+ (adddi3): Accept arith_operand for op2, but FAIL on SH1 if
+ no_new_pseudos.
+ (addsi3_media): Match `S' constraint.
+ (anddi3, andcdi3, iordi3, xordi3, negdi_media): New insns.
+ (negdi2): Expand for SHmedia.
+ (one_cmpldi2): New expand.
+ (zero_extendsidi2): Change from expand to insn.
+ (extendsidi2): Add constraints.
+ (movdi_media, movsi_media): Change `%x' to `%M'. Use `%m' for
+ LD/ST address. Fix SI immediate loading split.
+ (movhi_media, movqi_media, lduw, ldub): New insns.
+ (movhi, movqi): Accept SHmedia.
+ (shori_media, movdi_media): Relax input constraints. Split
+ symbolic constants.
+ (movdf_media, movsf_media): New insn. New split to movdi.
+ (movdf, movsf): Match on SHmedia.
+ (beq_media, bne_media, bgt_media, bge_media, bgtu_media,
+ bgeu_media): New insns and splits. New insns with `_i' suffix.
+ (beq, bne, bgt, blt, ble, bge, bgtu, bltu, bgeu, bleu): Adjust.
+ (bunordered): New expand.
+ (jump_compact): Renamed from `jump'.
+ (jump_media): New insn.
+ (jump): New expand.
+ (call_media, call_value_media): New insns.
+ (call, call_value): Adjust.
+ (indirect_jump_compact): Renamed from `indirect_jump'.
+ (indirect_jump_media): New insn.
+ (indirect_jump): New expand.
+ (untyped_call, return): Accept SHmedia.
+ (return_media): New insn.
+ (prologue, epilogue, blockage): Accept SHmedia.
+ (seq, slt, sle, sgt, sge, sgtu, sltu, sleu, sgeu, sne): Adjust.
+ (sunordered): New expand.
+ (addsf3, subsf3, mulsf3, divsf3, floatsisf2, fix_truncsfsi2,
+ cmpsf, negsf2, sqrtsf2, abssf2): Adjust for SHmedia.
+ (addsf3_media, subsf3_media, mulsf3_media, mac_media,
+ divsf3_media, floatdisf2, floatsisf2_media, fix_truncsfdi2,
+ fix_truncsfsi2_media, cmpeqsf_media, cmpgtsf_media,
+ cmpgesf_media, cmpunsf_media, negsf2_media, sqrtsf2_media,
+ abssf2_media): New insns.
+ (adddf3, subdf3, muldf3, divdf3, floatsidf2, fix_truncdfsi2,
+ cmpdf, negdf2, sqrtdf2, absdf2): Adjust for SHmedia.
+ (adddf3_media, subdf3_media, muldf3_media, divdf3_media,
+ floatdidf2, floatsidf2_media, fix_truncdfdi2,
+ fix_truncdfsi2_media, cmpeqdf_media, cmpgtdf_media,
+ cmpgedf_media, cmpundf_media, negdf2_media, sqrtdf2_media,
+ absdf2_media): New insns.
+ (extendsfdf2, truncdfsf2): Adjust for SHmedia.
+ (extendsfdf2_media, truncdfsf2_media): New insns.
+ 2000-09-14 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.c (machine_dependent_reorg): On shmedia, skip for now.
+ * config/sh/sh.h (CONST_OK_FOR_J): Document.
+ (LEGITIMATE_CONSTANT_P): Accept CONST_DOUBLEs on shmedia.
+ * config/sh/sh.md (adddi3): New expand.
+ (adddi3_media, adddi3z_media): New insns.
+ (adddi3_compact): Renamed from adddi3.
+ (addsi3_media): Use add.l r63 to add constant zero.
+ (subdi3): New expand.
+ (subdi3_media): New insn.
+ (subdi3_compact): Renamed from subdi3.
+ (mulsidi3): New expand.
+ (mulsidi3_media): New insn.
+ (mulsidi3_compact): Renamed from mulsidi3.
+ (umulsidi3): New expand.
+ (umulsidi3_media): New insn.
+ (umulsidi3_compact): Renamed from umulsidi3.
+ (ashlsi3_media, ashrsi3_media, lshrsi3_media): New insns.
+ (ashlsi3, ashrsi3, lshrsi3): Use them.
+ (ashldi3_media, ashrdi3_media, lshrdi3_media): New insns.
+ (ashldi3, ashrdi3, lshrdi3): Use them.
+ (zero_extendsidi2): New expand.
+ (extendsidi2): New insn.
+ (movsi_media): New insn. Split to movdi to load constants.
+ (movsi): Enable for shmedia.
+ (movdi_media): New insn. Use shori_media to load wide constants.
+ (short_media): New insn.
+ (movdi): Enable for shmedia.
+ 2000-09-08 Alexandre Oliva <aoliva@redhat.com>
+ * config/sh/sh.h (CPP_SPEC): Added `m5'.
+ (SUBTARGET_CPP_SPEC): Added `!m5'.
+ (SH5_BIT, TARGET_SH5, TARGET_SHMEDIA, TARGET_SHCOMPACT): New macros.
+ (TARGET_SWITCHES): Added `5' and `5-compact'. Added SH1_BIT
+ to all other SH variants.
+ (TARGET_DEFAULT): Set to SH1_BIT.
+ (OVERRIDE_OPTIONS): Recognize sh5 CPU.
+ (BITS_PER_WORD): Raise to 64 on shmedia.
+ (MAX_BITS_PER_WORD): Change to 64.
+ (MAX_LONG_TYPE_SIZE, MAX_WCHAR_TYPE_SIZE): Set to MAX_BITS_PER_WORD.
+ (INT_TYPE_SIZE): Keep as 32.
+ (UNITS_PER_WORD): Raise to 8 on shmedia.
+ (MIN_UNITS_PER_WORD): Keep as 4.
+ (POINTER_SIZE): Raise to 64 on shmedia.
+ (CONST_OK_FOR_J): New macro.
+ (CONST_OK_FOR_LETTER_P): Use it.
+ (processor_type): Add PROCESSOR_SH5.
+ * config/sh/sh.md: Conditionalize all expands, insns and
+ splits to TARGET_SH1.
+ (cpu): Added sh5.
+ (addsi3_compact): Renamed from...
+ (addsi3): Now an expand.
+ (addsi3_media, subsi3_media): New insns.
+ (subsi3): Don't negate constants with SHmedia.
+
+ * hooks.c: New file.
+ * hooks.h: New file.
+ * Makefile.in (HOOKS_H): New.
+ (TARGET_DEF_H): Added $(HOOKS_H).
+ (OBJS): Added hooks.o.
+ (cfgcleanup.o, bb-reorder.o): Added target.h.
+ (hooks.o): Added dependencies.
+ * target-def.h (TARGET_CANNOT_MODIFY_JUMPS_P): New, added to...
+ (TARGET_INITIALIZER): this.
+ * doc/tm.texi (TARGET_CANNOT_MODIFY_JUMPS_P): Document.
+ * target.h (struct gcc_target): Added cannot_modify_jumps_p.
+ * bb-reorder.c: Include target.h.
+ (reorder_basic_blocks): Skip if cannot modify jumps.
+ * cfgcleanup.c: Include target.h.
+ (try_optimize_cfg): Skip merge blocking if cannot modify jumps.
+
+2002-02-08 Chris Demetriou <cgd@broadcom.com>
+
+ * config/mips/mips.md (casesi_internal, casesi_internal_di):
+ Protect jump delay slot instructions with .set noreorder and
+ .set nomacro.
+
+2002-02-08 Chris Demetriou <cgd@broadcom.com>
+
+ * config/mips/mips.md (casesi_internal_di): Calculate
+ the index into the target offset table correctly.
+
+2002-02-08 Richard Henderson <rth@redhat.com>
+
+ * expr.c (expand_expr): Mind EXPAND_INITIALIZER for truncation also.
+ * final.c (output_addr_const): Accept and discard SUBREG.
+ * varasm.c (decode_addr_const): Don't abort on unknown expressions --
+ mark them unknown instead.
+ (simplify_subtraction): Handle RTX_UNKNOWN.
+ (initializer_constant_valid_p): Strip NOP_EXPRs that narrow the mode.
+
+2002-02-08 David Edelsohn <edelsohn@gnu.org>
+
+ * doc/invoke.texi (RS/6000 and PowerPC Options): Fix typo.
+
+2002-02-08 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/elf.h (ASM_OUTPUT_ALIGNED_BSS): New.
+
+2002-02-08 Andreas Jaeger <aj@suse.de>
+
+ * config.gcc (x86_64-*-linux): Add t-linux64 makefile fragment.
+ * config/i386/t-linux64: New file.
+
+2002-02-08 Jakub Jelinek <jakub@redhat.com>
+
+ * c-common.c (c_expand_expr): Revert 2002-02-06 patch.
+ * c-parse.in (compstmt): Clear last_expr_type.
+
+2002-02-07 Richard Henderson <rth@redhat.com>
+
+ * loop.c (strength_reduce): Sink final_value when not
+ eliminating a biv.
+
+2002-02-07 David O'Brien <obrien@FreeBSD.org>
+
+ * config/sparc/freebsd.h: Fix mismatched spec {.
+
+2002-02-07 Richard Henderson <rth@redhat.com>
+
+ * cfgrtl.c: Include recog.h and insn-config.h.
+ (keep_with_call_p): Fix general_operand invocation.
+ * Makefile.in (cfgrtl.o): Update dependencies.
+
+2002-02-07 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (two_insn_adds_subs_operand): Revise a
+ comment. Accept HImode only if TARGET_H8300.
+
+2002-02-07 Eric Christopher <echristo@redhat.com>
+
+ * config/mips/crtn.asm: Cleanup #ifdefs.
+
+2002-02-07 Eric Christopher <echristo@redhat.com>
+
+ * config/mips/crti.asm: Add changes for mips16. mips16 uses
+ register 7 as RA instead of $31.
+ * config/mips/crtn.asm: Ditto.
+ * config/mips/mips.c (mips_move_2words): Add case for
+ TARGET_MIPS16 when HOST_BITS_PER_WIDE_INT >= 64.
+ (compute_frame_size): Fix typo.
+ (save_restore_insns): Ditto. Make documentation about using
+ register $7 as return register more precise.
+ (mips_expand_epilogue): Fix comment. Add code to work around not
+ being able to add to the stack pointer directly.
+ * config/mips/mips.h (EH_RETURN_DATA_REGNO): Change register number
+ to 2 for TARGET_MIPS16 as we need 6 and 7 as clobbers in the
+ epilogue.
+
+2002-02-07 Tom Rix <trix@redhat.com>
+
+ * config/rs6000/rs6000.c (reg_or_aligned_short_operand): New. For
+ immediates in ldu and stdu DS opcode field.
+ * config/rs6000/rs6000.md (movdi_update, movdi_update1): Use.
+ * config/rs6000/rs6000-protos.h: Add reg_or_aligned_short_operand.
+ * config/rs6000/rs6000.h (PREDICATE_CODES): Same.
+
+2002-02-07 Jeff Sturm <jsturm@one-point.com>
+
+ * config/sparc/sparc.c (compute_frame_size): Don't correct frame
+ offset for stack bias.
+
+2002-02-07 H.J. Lu <hjl@gnu.org>
+
+ * config/mips/linux.h (SUBTARGET_ASM_DEBUGGING_SPEC): Defined.
+
+2002-02-07 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * testsuite/gcc.dg/cpp/charconst-2.c: Add -fsigned-char option.
+
+Thu Feb 7 12:14:17 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386-protos.h (x86_order_regs_for_local_alloc): Declare
+ * i386.c (x86_order_regs_for_local_alloc): New global function.
+ * i386.h (REG_ALLOC_ORDER): CLeanup.
+ (ORDER_REGS_FOR_LOCAL_ALLOC): New.
+
+2002-02-07 Richard Henderson <rth@redhat.com>
+
+ PR optimization/2463
+ * alias.c (find_base_value): Recall base values for fixed hard regs.
+ * loop.c (loop_regs_update): Don't use single_set on non-insns.
+
+2002-02-07 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/mips/mips.md (define_delay) [mips16]: Adjust required
+ length.
+
+2002-02-06 Richard Henderson <rth@redhat.com>
+
+ PR c/5609
+ * stmt.c (resolve_operand_name_1): Take more care with mixed
+ named and unnamed operands.
+
+2002-02-06 Janis Johnson <janis187@us.ibm.com>
+ Jan Hubicka <jh@suse.cz>
+
+ * loop.c (remove_constant_addition): Avoid clobbering a shared
+ CONST expression.
+
+2002-02-06 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config.gcc (s390x-*-linux*): Add t-linux64 makefile fragment.
+ * config/s390/t-linux64: New file.
+ * config/s390/libgcc-glibc.ver: New file.
+
+2002-02-06 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/linux64.h: Delete file.
+ * config/s390/s390x.h: New file.
+ * config.gcc (s390x-*-linux*): Use s390x.h instead of linux64.h
+ as target header file.
+ * config/s390/linux.h (TARGET_VERSION): Define depending on
+ DEFAULT_TARGET_64BIT.
+ (CPP_SPEC, ASM_SPEC, LINK_SPEC): Likewise.
+ (SIZE_TYPE, PTRDIFF_TYPE): Likewise.
+ (NO_BUILTIN_SIZE_TYPE, NO_BUILTIN_PTRDIFF_TYPE): Define.
+ (CPP_ARCH31_SPEC, CPP_ARCH64_SPEC): New defines.
+ (LINK_ARCH31_SPEC, LINK_ARCH64_SPEC): New defines.
+ (EXTRA_SPEC): New define.
+ * config/s390/s390.h (TARGET_VERSION): Define depending on
+ DEFAULT_TARGET_64BIT.
+ (MASK_RETURN_ADDR): Add run-time check for TARGET_64BIT.
+
+2002-02-06 Jason Merrill <jason@redhat.com>
+
+ * c-decl.c (finish_function): Warn about a non-void function with
+ no return statement and no abnormal exit.
+ (current_function_returns_abnormally): New variable.
+ (start_function): Clear it.
+ (struct c_language_function): Add returns_abnormally.
+ (push_c_function_context): Save it.
+ (pop_c_function_context): Restore it.
+ (builtin_function): Set TREE_THIS_VOLATILE on return fns.
+ (grokdeclarator): Set C_FUNCTION_IMPLICIT_INT on functions without
+ an explicit return type.
+ * c-tree.h: Declare current_function_returns_abnormally.
+ (C_FUNCTION_IMPLICIT_INT): New macro.
+ * c-typeck.c (build_function_call): Set it.
+ (c_expand_return): Set current_function_returns_value even if the
+ value is erroneous.
+
+2002-02-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/5420:
+ * c-common.c (c_unsafe_for_reeval): Make COMPOUND_LITERAL_EXPR
+ unsafe for reevaluation.
+
+2002-02-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/5482:
+ * c-common.c (c_expand_expr) [STMT_EXPR]: If last expression is not
+ EXPR_STMT, but COMPOUND_STMT, recurse into it.
+
+2002-02-06 Richard Henderson <rth@redhat.com>
+
+ * cfganal.c (keep_with_call_p): Source for fixed_reg dest must
+ be a general_operand. Dest for function value must be a pseudo.
+
+2002-02-06 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * dbxout.c (dbxout_symbol_location): Accept LABEL_REFs as well
+ as SYMBOL_REFs from the constant pool.
+
+2002-02-06 Alexandre Oliva <aoliva@redhat.com>
+
+ * dbxout.c (dbxout_parms): Apply DEBUGGER_ARG_OFFSET to parameters
+ passed by invisible reference.
+
+2002-02-05 Richard Henderson <rth@redhat.com>
+
+ * config/sparc/sparc.h (ARG_POINTER_CFA_OFFSET): No stack bias.
+
+2002-02-06 Hans-Peter Nilsson <hp@bitrange.com>
+
+ Implement using "base addresses" in insn operands as default.
+ * config/mmix/mmix.c (mmix_conditional_register_usage): if
+ -mabi=gnu, modify fixed_regs to fit the GNU ABI.
+ (mmix_extra_constraint): Use 'R' to indicate that GETA should be
+ used to read the rtx value.
+ (mmix_target_asm_function_epilogue): Fix spacing.
+ (mmix_constant_address_p): Handle TARGET_BASE_ADDRESSES.
+ (mmix_legitimate_address): Ditto.
+ (mmix_encode_section_info): Set SYMBOL_REF_FLAG on rtx:es that
+ should be loaded with a GETA insn. Don't allocate needless extra
+ char for nul termination and fix misleading comment.
+ (mmix_print_operand_address): Handle constants if
+ TARGET_BASE_ADDRESSES.
+ (mmix_output_register_setting): Use base addressing if
+ TARGET_BASE_ADDRESSES and the number of insns is 3.
+ * config/mmix/t-mmix (MULTILIB_EXTRA_OPTS): New.
+ * config/mmix/mmix.md ("movdi"): Change the alternative with GETA
+ to use R as constraint, add LDA to match s.
+ * config/mmix/mmix.h (TARGET_BASE_ADDRESSES): New.
+ (TARGET_DEFAULT): Add TARGET_MASK_BASE_ADDRESSES.
+ (TARGET_SWITCHES): Add -mbase-addresses, -mno-base-addresses.
+ (FIXED_REGISTERS): Make registers $231..$246 fixed by default.
+ (MMIX_MMIXWARE_ABI_REG_ALLOC_ORDER): Move $231..$246 last, in
+ order with other fixed registers.
+ (MMIX_GNU_ABI_REG_ALLOC_ORDER): Put forward $231, in order with
+ other parameter/call-clobbered registers.
+ * doc/invoke.texi (Option Summary) <MMIX Options>: Add
+ -mbase-addresses, -mno-base-addresses.
+ (MMIX Options): Ditto.
+
+2002-02-05 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.h (PREDICATE_CODES): Add reg_before_reload_operand.
+
+2002-02-06 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/altivec.h: Change elem to _S_elem.
+
+2002-02-05 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/netbsd.h (WCHAR_TYPE): Define.
+ (WCHAR_TYPE_SIZE): Ditto.
+ (WINT_TYPE): Ditto.
+ * config/alpha/netbsd.h (WCHAR_TYPE): Remove.
+ (WCHAR_UNSIGNED): Ditto.
+ (WCHAR_TYPE_SIZE): Ditto.
+ (WINT_TYPE): Ditto.
+ * config/arm/netbsd.h: Likewise.
+ * config/i386/netbsd-elf.h: Likewise.
+ * config/i386/netbsd.h: Likewise.
+ * config/m68k/netbsd-elf.h: Likewise.
+ * config/m68k/netbsd.h: Likewise.
+ * config/ns32k/netbsd.h: Likewise.
+ * config/sparc/netbsd.h: Likewise.
+ * config/vax/netbsd.: Likewise.
+
+2002-02-05 Alexandre Oliva <aoliva@redhat.com>
+
+ * target.h (struct gcc_target): Added ms_bitfield_layout_p.
+ * target-def.h (TARGET_MS_BITFIELD_LAYOUT_P): New. Added to...
+ (TARGET_INITIALIZER): this.
+ * doc/tm.texi (TARGET_MS_BITFIELD_LAYOUT_P): Document.
+ (BITFIELD_NBYTES_LIMITED): Markup fix.
+ * tree.h (default_ms_bitfield_layout_p): Declare.
+ (record_layout_info): Added prev_field.
+ * tree.c (default_ms_bitfield_layout_p): New fn.
+ * c-decl.c (finish_struct): Disregard EMPTY_FIELD_BOUNDARY and
+ PCC_BITFIELD_TYPE_MATTERS for MS bit-field layout.
+ * stor-layout.c: Include target.h.
+ (start_record_layout): Initialize prev_field.
+ (place_field): Handle MS bit-field layout, and disregard
+ EMPTY_FIELD_BOUNDARY, BITFIELD_NBYTES_LIMITED and
+ PCC_BITFIELD_TYPE_MATTERS in this case. Update prev_field.
+ * Makefile.in (stor-layout.o): Adjust dependencies.
+
+2002-02-05 Jason Merrill <jason@redhat.com>
+
+ * collect2.c (dump_file): Pass DMGL_VERBOSE to cplus_demangle.
+
+2002-02-05 Andreas Jaeger <aj@suse.de>
+
+ * crtstuff.c: Fix comments.
+
+2002-02-05 Richard Henderson <rth@redhat.com>
+
+ PR fortran/3393
+ * loop.c (loop_iv_add_mult_emit_before): Copy multiplier as well.
+ (loop_iv_add_mult_sink, loop_iv_add_mult_hoist): Likewise.
+
+ PR fortran/3392
+ * config/mips/mips.c (function_arg): Handle TImode.
+ (function_arg_advance): Likewise.
+
+2002-02-05 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/altivec.h (vec_step_help): Rename to
+ __vec_step_help.
+
+2002-02-05 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/altivec.h: Fix typos.
+
+2002-02-05 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/arm/netbsd.h: Correct a comment.
+
+2002-02-05 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c (altivec_init_builtins): Fix typo
+ building void typed builtins.
+
+ * config/rs6000/altivec.h (vec_ld*): Fix typos.
+ (vec_step): Implement for C++.
+
+Mon Feb 4 19:23:19 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * final.c (final_scan_insn): Add case for NOTE_INSN_LOOP_END_TOP_COND.
+
+2002-02-04 Richard Henderson <rth@redhat.com>
+
+ * combine.c (nonzero_bits): Re-introduce special case for
+ sp/fp/ap wrt REGNO_POINTER_ALIGN.
+
+2002-02-05 Aldy Hernandez <aldyh@redhat.com>
+
+ * doc/extend.texi: Warn about unsupported usage of altivec
+ builtins.
+
+ * config/rs6000/rs6000.md (altivec_vcmp*_p): Remove.
+ (altivec_predicate_*): New.
+
+ * config/rs6000/altivec.h: Rewrite predicates to use new builtins.
+ Add C++ version of vec_*() functions.
+
+ * config/rs6000/rs6000.c (bdesc_altivec_preds): New.
+ (bdesc_2arg): Remove altivec predicates.
+ (altivec_expand_builtin): Handle predicates.
+ (altivec_init_builtins): Handle predicates.
+ (altivec_expand_predicate_builtin): New.
+
+2002-02-04 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.c (DO_FRAME_NOTES): Move forward.
+ (store_reg): Revise handling of frame notes.
+ (load_reg): Likewise.
+ (set_reg_plus_d): Likewise.
+ (hppa_expand_prologue): Likewise.
+ (hppa_expand_epilogue): Likewise.
+
+2002-02-04 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * unwind-dw2-fde-glibc.c: Define _GNU_SOURCE if not defined.
+
+2002-02-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/4475, c++/3780:
+ * c-common.def (SWITCH_STMT): Add SWITCH_TYPE operand.
+ * c-common.h (SWITCH_TYPE): Define.
+ * c-typeck.c (c_start_case): Set SWITCH_TYPE.
+ * stmt.c (all_cases_count): Set lastval to thisval at end of loop.
+ Rename spareness variable to sparseness.
+ (expand_end_case_type): Renamed from expand_end_case, use orig_type
+ if non-NULL instead of TREE_TYPE (orig_index).
+ * tree.h (expand_end_case_type): Renamed from expand_end_case.
+ (expand_end_case): Define using expand_end_case_type.
+ * c-semantics.c (genrtl_switch_stmt): Pass SWITCH_TYPE
+ to expand_end_case_type.
+ * doc/c-tree.texi (SWITCH_STMT): Document SWITCH_TYPE.
+
+2002-02-04 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.h (PREFERRED_STACK_BOUNDARY): Define to match standard rounding.
+ (BIGGEST_ALIGNMENT): Change to 128.
+
+2002-02-04 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa32-linux.h (LINK_COMMAND_SPEC): Define.
+
+2002-02-04 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.md (call_internal_reg_64bit): Remove unused variable.
+
+2002-02-04 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/arm/arm.h (machine_function): Add uses_anonymous_args
+ field.
+ (SETUP_INCOMING_VARARGS): Set uses_anonymous_args.
+ * config/arm/arm.c (current_function_anonymous_args): Delete,
+ replace uses with cfun->machine->uses_anonymous_args.
+ (arm_reorg): Do not reset uses_anonymous_args.
+
+ * config/arm/arm.c (arm_hard_regno_mode_ok): Allow any value in
+ any geenral register.
+
+2001-02-04 Bernd Schmidt <bernds@redhat.com>s
+
+ * cfgrtl.c (force_nonfallthru_and_redirect): Don't try to redirect
+ the entry block.
+
+2002-02-04 Richard Henderson <rth@redhat.com>
+
+ * combine.c (force_to_mode): Remove STACK_BIAS code.
+ (nonzero_bits): Likewise. Replace sp/fp special case with
+ REGNO_POINTER_ALIGN.
+
+ * config/sparc/sparc.h (FRAME_POINTER_REGNUM): Change to SFP.
+ (HARD_FRAME_POINTER_REGNUM): New.
+ (FIRST_PSEUDO_REGISTER, REG_CLASS_CONTENTS): Update.
+ (FIXED_REGS, CALL_USED_REGS): Update.
+ (REG_ALLOC_ORDER, REGISTER_NAMES): Update.
+ (CONDITIONAL_REGISTER_USAGE): Update for HFP.
+ (HARD_REGNO_NREGS): Update for SFP.
+ (STACK_POINTER_OFFSET): Include bias here ...
+ (FIRST_PARM_OFFSET): ... not here.
+ (STACK_BIAS): Remove.
+ (INIT_EXPANDERS): New.
+ (STARTING_FRAME_OFFSET): Do not include bias.
+ (ELIMINABLE_REGS, CAN_ELIMINATE, INITIAL_ELIMINATION_OFFSET): New.
+ (REGNO_OK_FOR_INDEX_P, REGNO_OK_FOR_BASE_P): Update for SFP.
+ (REG_OK_FOR_INDEX_P, REG_OK_FOR_BASE_P): Likewise.
+ * config/sparc/aout.h (DBX_REGISTER_NUMBER): Update for HFP.
+ * config/sparc/litecoff.h, config/sparc/sol2.h: Likewise.
+ * config/sparc/sparc.c (mem_min_alignment): Update for HFP.
+ (sparc_nonflat_function_prologue, epilogue_renumber): Likewise.
+ (MUST_SAVE_REGISTER): Likewise.
+ (sparc_flat_function_prologue): Likewise.
+ (sparc_flat_function_epilogue): Likewise.
+ (HARD_FRAME_POINTER_MASK): Rename from FRAME_POINTER_MASK.
+ (sparc_init_modes): SFP is GENERAL_REGS.
+ (sparc_builtin_saveregs): SFP does not have bias applied.
+
+2002-02-04 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (current_function_is_thunk): Don't check
+ current_function_is_thunk.
+ (alpha_sa_mask): Distinguish between current_function_is_thunk
+ called from ASM_OUTPUT_MI_THUNK and not.
+ (alpha_does_function_need_gp): Thunks always need gp.
+ (alpha_start_function, alpha_output_function_end_prologue): Likewise.
+ (alpha_output_mi_thunk_osf): New.
+ * config/alpha/alpha-protos.h: Update.
+ * config/alpha/alpha.h (ASM_OUTPUT_MI_THUNK): New.
+
+2002-02-04 Richard Sandiford <rsandifo@redhat.com>
+
+ * c-typeck.c (build_c_cast): Warn when qualifiers are added to
+ function types, not when they're taken away.
+
+Mon Feb 4 09:05:58 2002 Jeffrey A Law (law@redhat.com)
+
+ * cfgrtl.c (try_redirect_by_replacing_jump): Remove associated
+ CODE_LABEL and jump table when replacing a table jump with a
+ simple jump.
+
+2002-02-04 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390-protos.h (legitimize_la_operand,
+ s390_secondary_input_reload_class, s390_plus_operand,
+ s390_expand_plus_operand): Add prototypes.
+
+ config/s390/s390.c (s390_secondary_input_reload_class,
+ s390_plus_operand, s390_expand_plus_operand): New functions.
+
+ (struct s390_address): New member 'pointer'.
+ (s390_decompose_address): Compute it.
+ (legitimate_la_operand_p): Use it.
+ (legitimize_la_operand): New function.
+ (movti, movdi, movdf splitters): Call it.
+
+ config/s390/s390.h (SECONDARY_INPUT_RELOAD_CLASS): Define.
+ (PREDICATE_CODES): Add s390_plus_operand.
+
+ config/s390/s390.md (adddi3_inv_64, addaddr_ccclobber): Delete.
+ (la_ccclobber): Allow GENERAL_REGS as output operand.
+
+ (reload_load_address, *reload_load_address_reg_0, *la, *do_la_reg_0,
+ *reload_la_64, *reload_la_31 and splitters): Delete, replace by ...
+ (*la_64, *la_31, reload_indi, reload_insi): ... these.
+
+2002-02-04 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * gcc/config/s390/s390.h (CRT_CALL_STATIC_FUNCTION): Fixed
+ register names for regular asm () construct.
+
+2002-02-04 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.md (movsf_1): Allow moving SF values in MMX
+ registers.
+
+2002-02-04 Jakub Jelinek <jakub@redhat.com>
+
+ * combine.c (recog_for_combine): Create a dummy insn with PATTERN
+ pat for recog.
+
+2002-02-04 Hartmut Penner <hpenner@de.ibm.com>
+
+ * varasm.c (decode_rtx_const): Allow unspec (symbol_ref) in
+ constant pool to be identical by string address and index.
+
+2002-02-04 Anthony Green <green@redhat.com>
+
+ * output.h (SECTION_OVERRIDE): Define.
+ * varasm.c (named_section): Obey SECTION_OVERRIDE.
+
+2002-02-03 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config.gcc (arm*-*-netbsdelf*): Placeholder to prevent match
+ by existing arm*-*-netbsd* (a.out) target.
+ (ns32k-*-netbsdelf*): Likewise.
+ (sparc-*-netbsdelf*): Likewise.
+ (vax-*-netbsdelf*): Likewise.
+
+2002-02-03 Danny Smith <dannysmith@users.sourceforge.net>
+
+ * gthr-win32.h: Protect against conflicting typedef for BOOL in windows
+ headers and libobjc headers.
+
+2002-02-03 Mumit Khan <khan@nanotech.wisc.edu>
+
+ * gthr-win32.h (__mingwthr_key_dtor): Use extern "C" linkage for C++.
+ (_mingw.h): Remove duplicate include.
+
+2002-02-03 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config.gcc: Set cpu_type to m68k for 68010, as well.
+ (m68010-*-netbsdelf*): New...
+ (m68k*-*-netbsdelf*): ...targets.
+ * config/m68k/netbsd-elf.h: New file.
+
+2002-02-02 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (hand_list): Move inside function_arg.
+
+2002-02-02 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (h8_push_ops): Move inside
+ h8300_init_once.
+ (h8_pop_ops): Likewise.
+ (h8_move_ops): Likewise.
+
+2002-02-02 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (os_task): Make it static.
+ (monitor): Likewise.
+ (pragma_saveall): Likewise.
+
+2002-02-02 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/sh/sh.md (ic_invalidate_line): Make sure the immediate
+ constant is a valid sign-extension for Pmode.
+
+2002-02-02 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c: Fix formatting.
+
+2002-02-02 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md: Fix formatting.
+
+2002-02-02 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md (one_cmpl patterns): Tighten the
+ predicates of operands[1]. Split the patterns for each
+ processor variant.
+
+2002-02-02 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md (xor patterns): Tighten the predicates
+ of operands[1] to register_operand.
+
+2002-02-02 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpphash.h (struct spec_nodes): Remove n__CHAR_UNSIGNED__.
+ * cpphash.c (_cpp_init_hashtable): Similarly.
+ * cppinit.c (cpp_create_reader): Default the signed_char flag.
+ (init_builtins): Define __CHAR_UNSIGNED__ appropriately.
+ (COMMAND_LINE_OPTIONS): Recognize -f{un,}signed-char.
+ (cpp_handle_option): Handle the new options.
+ * cpplex.c (cpp_interpret_charconst): Use new flag.
+ * cpplib.h (struct cpp_options): New member signed_char.
+ * gcc.c (cpp_unique_options): Remove %c spec and documentation.
+ (cpp_options): Handle -fsigned-char and -funsigned-char.
+ (static_specs): Remove signed_char_spec.
+ (do_spec1): Don't handle %c.
+ * system.h: Poison SIGNED_CHAR_SPEC.
+ * tradcif.y (yylex): Use flag_signed_char.
+ * tradcpp.h (flag_signed_char): New.
+ * tradcpp.c (flag_signed_char): New.
+ (main): Handle new command-line options.
+ (initialize_builtins): Define __CHAR_UNSIGNED__ if appropriate.
+config:
+ * alpha/alpha.h (SIGNED_CHAR_SPEC): Remove.
+ * avr/avr.h: Remove old comments.
+ * i960/i960.h (CPP_SPEC): Pass -fsigned-char if -mic*.
+ (CC1_SPEC): Pass -fsigned-char if -mic*.
+ (SIGNED_CHAR_SPEC): Remove.
+doc:
+ * tm.texi (SIGNED_CHAR_SPEC): Remove documentation.
+
+2002-02-01 Eric Christopher <echristo@redhat.com>
+
+ From Daniel Jacobowitz <dmj+@andrew.cmu.edu>
+ * config/mips/mips.h (FUNCTION_PROFILER): Fix function profiling.
+ * config/mips/linux.h (ASM_OUTPUT_REG_PUSH): Undefine.
+ (ASM_OUTPUT_REG_POP): Ditto.
+
+2002-02-02 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-decl.c, tree.c, tree.h, objc/objc-act.c: Revert bitfield
+ patch.
+
+2002-02-02 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.h (CPP_CPUCOMMON_SPEC): Add missing | separators.
+
+2002-02-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/5304:
+ * expmed.c (expand_mult_highpart): Use immed_double_const for wide_op1
+ unconditionally.
+
+2002-02-01 Janis Johnson <janis187@us.ibm.com>
+
+ * cfganal.c: Include tm_p.h.
+ (keep_with_call_p): Fix the test that determines if a register holds
+ the return value of a call.
+
+2002-02-01 DJ Delorie <dj@redhat.com>
+
+ * config/sparc/sparc.c (sparc_emit_set_symbolic_const64): If
+ we are given conflicting registers, switch to the other one we
+ had allocated for us.
+ * config/sparc/sparc.md (reload_indi, reload_outdi): Pass op[2]
+ as TImode so we know when the "other" register is available.
+
+2002-02-01 David O'Brien <obrien@FreeBSD.org>
+
+ * config/sparc/sol2-sld-64.h: Include sparc/biarch64.h rather than
+ sparc/sparc_bi.h.
+
+2002-02-01 Janis Johnson <janis187@us.ibm.com>
+
+ * cfganal.c (keep_with_call_p): New function.
+ (flow_call_edges_add): Prevent splitting a block between a call and
+ a single-set instruction that should be kept in the same block.
+
+2002-02-01 Craig Rodrigues <rodrigc@gcc.gnu.org>
+
+ * doc/install.texi (avr): Update outdated URL.
+
+2002-01-30 Andrew Haley <aph@cambridge.redhat.com>
+
+ * config/stormy16/stormy16.md (pushqi): New.
+ (popqi): New.
+ (pushhi): New.
+ (pophi): New.
+ (movhi): Remove stack operands.
+ (movqi): Likewise.
+ * config/stormy16/stormy16.h (PREDICATE_CODES): Add
+ nonimmediate_nonstack_operand.
+ * config/stormy16/stormy16.c (nonimmediate_nonstack_operand):
+ New.
+ * config/stormy16/stormy16-protos.h (nonimmediate_nonstack_operand)
+ New.
+
+2002-01-31 Jason Merrill <jason@redhat.com>
+
+ * Makefile.in (c-parse.c): Handle .output file.
+ * objc/Make-lang.in (objc-parse.c): Likewise.
+
+2002-02-01 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/mips/mips.h (ENDIAN_SPEC): Output the endianness flag if
+ the -me[lb] option is given. Don't output the default flag
+ twice.
+
+2002-01-31 Zack Weinberg <zack@codesourcery.com>
+
+ * c-lex.c (yyparse): Call debug_hooks->start_source_file for
+ the primary source file; this has not been done yet.
+ * c-decl.c (c_expand_body): Reset input_filename from
+ DECL_SOURCE_FILE (fndecl) before calling init_function_start.
+
+2002-01-31 Kazu Hirata <kazu@hxi.com>
+
+ * rtlanal.c (subreg_regno_offset): Do not use
+ SUBREG_REGNO_OFFSET.
+ * system.h: Add SUBREG_REGNO_OFFSET to the GCC poison list.
+ * doc/tm.texi (SUBREG_REGNO_OFFSET): Remove.
+
+2002-01-31 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * gccbug.in: Follow GNU Coding Standards for --version. Use GCC
+ version rather than GNATS version in --version output.
+
+2002-01-31 Richard Sandiford <rsandifo@redhat.com>
+
+ * ifcvt.c (noce_process_if_block): Make a copy of the destination
+ when copying back from a temporary.
+
+2002-01-30 Richard Henderson <rth@redhat.com>
+
+ * ifcvt.c (dead_or_predicable): Handling merging when other_bb
+ and new_dest are the same.
+
+2002-01-30 Richard Henderson <rth@redhat.com>
+
+ PR opt/5076
+ * rtl.h (NOTE_INSN_LOOP_END_TOP_COND): New.
+ * rtl.c (note_insn_name): Update.
+ * emit-rtl.c (remove_unnecessary_notes): Kill it.
+ * stmt.c (expand_end_loop): Kill jump opt code. Use LOOP_END_TOP_COND
+ to perform loop rotation.
+ (expand_exit_loop_top_cond): New.
+ * tree.h (expand_exit_loop_top_cond): Declare it.
+ * c-semantics.c (genrtl_while_stmt): Use it.
+ (genrtl_for_stmt): Likewise.
+
+2002-01-30 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/mips/mips.h (PARM_BOUNDARY): Guarantee alignment of
+ arguments to 64-bit boundaries on 64-bit ABIs.
+
+2002-01-30 Steve Ellcey <sje@cup.hp.com>
+
+ * loop.c (loop_invariant_p): Special case pic_offset_table_rtx.
+
+2002-01-31 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * c-decl.c (grokdeclarator): Handle type being a typedef for an
+ invalid type.
+
+2002-01-30 David O'Brien <obrien@FreeBSD.org>
+
+ * config.gcc: Include sparc/biarch64.h rather than sparc/sparc_bi.h.
+ * config/sparc/sparc_bi.h: Remove file.
+ * config/sparc/biarch64.h: New file (rename of sparc_bi.h).
+
+2002-01-30 Richard Henderson <rth@redhat.com>
+
+ * sched-deps.c (sched_analyze): Make a call read the frame pointer.
+
+2002-01-30 Zack Weinberg <zack@codesourcery.com>
+
+ * expmed.c (emit_store_flag): Call protect_from_queue on op0 and op1.
+
+2002-01-30 Jason Merrill <jason@redhat.com>
+
+ * dwarf2out.c (dwarf_cfi_name): Add other DWARF 3 codes.
+ (output_cfi): Likewise. Disable DW_CFA_GNU_negative_offset_extended.
+ (reg_save): Use DW_CFA_offset_extended_sf instead.
+
+ * dwarf2out.c (dwarf2out_finish): Don't abort if there were errors.
+
+2002-01-29 Jakub Jelinek <jakub@redhat.com>
+
+ * cselib.c (cselib_record_sets): Use IF_THEN_ELSE result
+ in cselib_lookup.
+
+2002-01-29 Aldy Hernandez <aldyh@redhat.com>
+
+ * rs6000.md ("*call_value_local32"): Remove constraints.
+ ("*call_value_local64"): Same.
+ ("*call_value_indirect_nonlocal_aix32"): Same.
+ ("*call_value_nonlocal_aix32"): Same.
+ ("*call_value_indirect_nonlocal_aix64"): Same.
+ ("*call_value_nonlocal_aix64"): Same.
+ ("*call_value_nonlocal_sysv"): Same.
+
+2002-01-29 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/elf.h (SDB_DEBUGGING_INFO): Undef.
+
+2002-01-29 Richard Henderson <rth@redhat.com>
+
+ * expr.c (force_operand): Ignore flag_pic for detecting pic
+ address loads.
+ * regclass.c (init_reg_sets_1): Test fixed_regs not flag_pic
+ for determining if PIC_OFFSET_TABLE_REGNUM is call-clobbered.
+ * resource.c (mark_target_live_regs): Use regs_invalidated_by_call
+ instead of open-coded loop.
+ * doc/tm.texi (PIC_OFFSET_TABLE_REGNUM): Clarify that it must
+ be fixed when in use.
+
+2002-01-29 Richard Henderson <rth@redhat.com>
+
+ * sched-int.h (struct deps_reg): Add uses_length, clobbers_length.
+ * sched-rgn.c (propagate_deps): Update them.
+ * sched-deps.c (sched_analyze_insn): Update them. Flush the
+ clobbers list when either gets too long.
+
+2002-01-29 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.h (LIMIT_RELOAD_CLASS): Handle LEGACY_REGS
+ and INDEX_REGS the same as GENERAL_REGS.
+ (SECONDARY_OUTPUT_RELOAD_CLASS): Likewise.
+
+2002-01-29 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * tree.c (build_nonstandard_integer_type): Correct prototype.
+
+2002-01-29 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.md (movstrsico, movstrdix_64,
+ movstrsix_31): Remove, replace by ...
+ (movstrdi_short, movstrsi_short, movstrdi_long,
+ movstrsi_long): ... these. New.
+ (movstrdi, movstrsi): Adapt.
+
+ (rotldi3, rotlsi3, ashldi3, *ashldi3_31, *ashldi3_64,
+ ashlsi3, lshrdi3, *lshrdi3_31, *lshrdi3_64, lshrsi3):
+ Remove unnecessary CC clobber.
+ (*ashrdi3_cc_31, *ashrdi3_cconly_31, *ashrdi3_cc_64,
+ *ashrdi3_cconly_64, *ashrsi3_cc, *ashrsi3_cconly): New.
+
+ (divmoddi4): Don't partially initialize TImode register.
+
+2002-01-29 Geoffrey Keating <geoffk@redhat.com>
+
+ * doc/sourcebuild.texi (C Tests): Document gcc.dg/debug directory.
+
+2002-01-29 Richard Henderson <rth@redhat.com>
+
+ * flow.c (print_rtl_and_abort): Remove.
+ (print_rtl_and_abort_fcn): Remove.
+ (verify_local_live_at_start): Use dump_bb instead.
+ (verify_wide_reg): Likewise. Take a basic_block, not rtl endpoints.
+ (verify_wide_reg_1): Return 2 on mode test failure.
+
+2002-01-29 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ PR c/3325, c/3326, c/2511, c/3347
+ * c-decl.c (enum_decl_context): Remove BITFIELD.
+ (grokdeclarator): Take bitfield width as an input.
+ Ensure bitfields are given the correct type. Perform
+ bitfield width validation with build_bitfield_integer_type
+ rather than waiting for finish_struct.
+ (grok_typename, grok_typename_in_parm_context, start_decl,
+ push_parmdecl, grokfield, start_function): Update calls to
+ grokdeclarator.
+ (build_bitfield_integer_type): New function.
+ (finish_struct): Move bitfield validation to grokdeclarator
+ and build_bitfield_integer_type.
+ * tree.c (build_nonstandard_integer_type): New function.
+ * tree.h (build_nonstandard_integer_type): New prototype.
+objc:
+ * objc-act.c (objc_copy_list): Remove DECL_INITIAL kludge.
+
+2002-01-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/1502:
+ * cppinit.c (cpp_handle_option): Add ignore argument, if it is zero,
+ don't ignore unrecognized -W* options.
+ (cpp_handle_options): Pass 1 as last argument to cpp_handle_option.
+ * cpplib.h (cpp_handle_option): Adjust prototype.
+ * c-decl.c (c_decode_options): Pass 0 as last argument to
+ cpp_handle_option.
+
+ PR c/2896:
+ * gcc.c (cpp_unique_options): Split from cpp_options.
+ (cpp_options): Source cpp_unique_options.
+ (default_compilers): Use cpp_unique_options instead of cpp_options
+ when used together with cc1_options.
+ (static_specs): Add cpp_unique_options.
+ * objc/lang-specs.h: Use cpp_unique_options instead of cpp_options
+ when used together with cc1_options.
+
+2002-01-29 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300-protos.h: Update the prototype of
+ output_a_shift.
+ * config/h8300/h8300.c (output_a_shift): Remove an unused
+ argument 'insn'. Remove redundant code.
+ * config/h8300/h8300.md: Adust to the new prototype of
+ output_a_shift.
+
+2002-01-29 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300-protos.h: Update the prototypes of
+ emit_a_rotate and expand_a_rotate.
+ * config/h8300/h8300.c (emit_a_rotate): Change the type of the
+ first argument to 'enum rtx_code'.
+ (expand_a_rotate): Likewise.
+
+2002-01-28 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300-protos.h: Update the prototype of
+ output_simode_bld.
+ * config/h8300/h8300.c (output_simode_bld): Remove an argumen
+ 'log2'.
+ * config/h8300/h8300.md: Adjust to the new prototype.
+
+2002-01-28 Kazu Hirata <kazu@hxi.com>
+
+ * conifg/h8300/h8300.c (h8300_adjust_insn_length): Remove
+ redundant code.
+
+2002-01-28 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * emit-rtl.c (gen_rtx_REG): Check that the PIC_OFFSET_TABLE_REGNUM
+ is a fixed register before returning pic_offset_table_rtx.
+ * loop.c (scan_loop): Don't hoist insns that set pic_offset_table_rtx
+ when PIC_OFFSET_TABLE_REG_CALL_CLOBBERED is defined.
+
+2002-01-28 Jason Merrill <jason@redhat.com>
+
+ * dwarf2.h: Sync with src version.
+
+2002-01-28 Paul Koning <pkoning@equallogic.com>
+
+ * builtin-types.def (BT_FN_VOID_CONST_PTR_VAR): Replace
+ BT_FN_VOID_PTR_VAR.
+ * builtins.def (BUILT_IN_PREFETCH): Change first argument to be const.
+ * doc/extend.texi (__builtin_prefetch): Update documentation:
+ first argument is now const void ptr.
+
+2002-01-28 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300-protos.h: Remove an unused prototype.
+
+2002-01-28 Roman Zippel <zippel@linux-m68k.org>
+
+ * toplev.c (lang_independent_init): Round up identifier size.
+
+2002-01-28 Richard Earnshaw <rearnsha@arm.com>
+
+ * config.gcc: Revert previous change.
+
+2002-01-28 Andris Pavenis <pavenis@latnet.lv>
+
+ * config/i386/djgpp.h: Use STRIP_NAME_ENCODING in macro UNIQUE_SECTION
+
+2002-01-28 Richard Earnshaw <rearnsha@arm.com>
+
+ * config.gcc (*-*-netbsdelf*): Set up generic parameters.
+ (*-*-netbsd*): Always use collect2. Remove collect2 settings from
+ other non-elf netbsd config frags.
+ * config/netbsd-aout.h (STARTFILE_SPEC): Don't pull in c++rt0 since
+ collect2 will does that.
+ * config/netbsd.h (LIBGCC_SPEC): Add white space before -lgcc, so that
+ shared-lib frobbing will work.
+
+2002-01-28 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.h: Fix formatting.
+ * config/h8300/h8300.md: Likewise.
+
+2002-01-28 Loren J. Rittle <ljrittle@acm.org>
+
+ * fixinc/inclhack.def (strict_ansi_not): Add a bypass based on
+ the old, removed AAA_standards fix.
+ * fixinc/fixincl.x: Rebuilt.
+
+2002-01-28 Hans-Peter Nilsson <hp@axis.com>
+
+ * config/cris/cris.h (CRT_CALL_STATIC_FUNCTION): Change to emit
+ atexit call in crtbegin, hooked in after call to frame_dummy;
+ register EH before registering __fini__start.
+
+2002-01-28 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/altivec.h: Remove spurious semicolons.
+
+2002-01-27 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md: Replace dead bit extraction patterns
+ with ones that work.
+
+Sun Jan 27 13:23:40 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * emit-rtl.c (get_mem_attrs): Don't default alignment for non-BLKmode
+ if not STRICT_ALIGNMENT.
+ * rtl.h (MEM_ALIGN): Likewise.
+
+2002-01-27 Craig Rodrigues <rodrigc@gcc.gnu.org>
+
+ * doc/invoke.texi (-fdump-translation-unit): Revert this
+ patch: 2001-10-21 Craig Rodrigues <rodrigc@gcc.gnu.org>
+
+2002-01-27 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md (define_constants): New.
+ (anonymous patterns) Use defined constants appropriately.
+
+2002-01-27 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (function_arg): Remove redundant code.
+
+2002-01-26 Richard Henderson <rth@redhat.com>
+
+ * sched-deps.c (reg_pending_uses_head): New.
+ (reg_pending_barrier): Rename from reg_pending_sets_all.
+ (find_insn_list): Don't mark inline.
+ (find_insn_mem_list): Remove.
+ (add_dependence_list, add_dependence_list_and_free): New.
+ (flush_pending_lists): Replace only_write param with separate
+ for_read and for_write parameters. Update all callers. Use
+ add_dependence_list_and_free.
+ (sched_analyze_1): Do not add reg dependencies here; just set
+ the pending bits. Use add_dependence_list.
+ (sched_analyze_2): Likewise.
+ (sched_analyze_insn): Replace schedule_barrier_found with
+ reg_pending_barrier. Add all dependencies for pending reg
+ uses, sets, and clobbers.
+ (sched_analyze): Don't add reg dependencies for calls, just
+ set pending bits. Use regs_invalidated_by_call. Treat
+ sched_before_next_call as a normal list, not a fake insn.
+ (init_deps): No funny init for sched_before_next_call.
+ (free_deps): Free pending mems lists. Don't zero reg_last.
+ (init_deps_global): Init reg_pending_uses.
+ (finish_deps_global): Free it.
+ * sched-int.h (deps): Make in_post_call_group_p boolean. Update docs.
+ (find_insn_mem_list): Remove.
+ * sched-rgn.c (concat_INSN_LIST, concat_insn_mem_list): New.
+ (propagate_deps): Use them. Zero temp mem lists.
+
+2002-01-26 Richard Henderson <rth@redhat.com>
+
+ * Makefile.in (CRTSTUFF_CFLAGS): New.
+ (crtbegin.o, crtend.o, crtbeginS.o, crtendS.o, crtbeginT.o): Use it.
+ * config.gcc (alpha-linux, alpha-freebsd, alpha-netbsd): Use plain
+ crtstuff.c instead of alpha assembly version.
+ * crtstuff.c (CRT_CALL_STATIC_FUNCTION): Rewrite to assume the
+ entire dummy function sequence. Use FORCE_CODE_SECTION_ALIGN
+ not FORCE_{INIT,FINI}_SECTION_ALIGN.
+ (__do_global_dtors_aux): Mark used.
+ (frame_dummy, __do_global_ctors_aux): Mark used.
+ (fini_dummy, init_dummy): Remove.
+
+ * config/alpha/crtbegin.asm: Remove file.
+ * config/alpha/crtend.asm: Remove file.
+ * config/alpha/t-crtbe: Remove file.
+ * config/alpha/elf.h (CRT_CALL_STATIC_FUNCTION): New.
+ (LINK_EH_SPEC): New.
+
+ * config/cris/cris.h (CRT_CALL_STATIC_FUNCTION): Rewrite old
+ FORCE_INIT_SECTION_ALIGN hack. Register __fini_start before
+ calling constructors.
+ * config/cris/linux.h (CRT_CALL_STATIC_FUNCTION): Undef.
+
+ * config/i386/i386.h (CRT_CALL_STATIC_FUNCTION): New.
+ * config/i386/linux.h (CRT_CALL_STATIC_FUNCTION): Replace old
+ CRT_END_INIT_DUMMY hack.
+ * config/i386/sol2.h (FORCE_CODE_SECTION_ALIGN): Replace
+ FORCE_{INIT,FINI}_SECTION_ALIGN.
+
+ * config/mcore/mcore-elf.h (FORCE_CODE_SECTION_ALIGN): Replace
+ FORCE_{INIT,FINI}_SECTION_ALIGN.
+
+ * config/s390/s390.h (CRT_CALL_STATIC_FUNCTION): Update for new
+ invocation sequence.
+ * config/sh/sh.h (CRT_CALL_STATIC_FUNCTION): Likewise.
+
+ * doc/tm.texi (CRT_CALL_STATIC_FUNCTION): Update.
+ (FORCE_CODE_SECTION_ALIGN): New.
+
+2002-01-26 Richard Henderson <rth@redhat.com>
+
+ * config/cris/cris.c (cris_print_operand): Handle 64-bit CONST_INT.
+
+2002-01-26 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (alpha_sa_mask): Mark RA for unicos here too.
+ (alpha_sa_size): Use alpha_sa_mask to compute size of saved regs.
+
+2002-01-26 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md: Remove bit extraction patterns that
+ cannot be triggered.
+ Restrict each bit extraction pattern to a variant on which the
+ pattern is tested.
+
+2002-01-26 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/include/texinfo.tex: Update to version 2002-01-04.07.
+
+2002-01-26 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md: Remove bit test patterns that cannot
+ be triggered.
+ Restrict each bit test pattern to a variant on which the
+ pattern is tested.
+
+2002-01-26 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * builtins.c (expand_builtin_strncat): Remove redundant check for
+ INTEGER_CST.
+
+2002-01-25 David O'Brien <obrien@FreeBSD.org>
+
+ * config/i386/x86-64.h (DEFAULT_PCC_STRUCT_RETURN): Do not overide
+ default setting.
+ * config/i386/freebsd64.h (DEFAULT_PCC_STRUCT_RETURN): Do not override
+ existing setting.
+
+2002-01-25 Geoffrey Keating <geoffk@redhat.com>
+
+ * dbxout.c (dbxout_init): Use assemble_name rather than just
+ stripping off the first character.
+ (dbxout_source_file): Likewise.
+
+2002-01-25 DJ Delorie <dj@redhat.com>
+
+ * config/sparc/sparc.c (sparc_emit_set_symbolic_const64): Compare
+ using rtx_equal_p, not by comparing pointers.
+
+2002-01-25 Steve Ellcey <sje@cup.hp.com>
+
+ * emit-rtl.c (gen_rtx_REG): Always return the same rtx
+ for PIC_OFFSET_TABLE_REGNUM.
+ (init_emit_once): Use gen_raw_REG to initialize pic_offset_table_rtx.
+
+2002-01-25 David O'Brien <obrien@FreeBSD.org>
+
+ * config.gcc (x86_64-*-freebsd*): New target.
+ (x86_64-*-netbsd*,x86_64-*-linux*): Use ${tm_file} rather than its
+ value.
+ (i[34567]86-*-freebsd*): Don't include svr4.h.
+ * config/i386/freebsd64.h: New file.
+
+2002-01-25 Douglas B Rupp <rupp@gnat.com>
+
+ * config/alpha/x-vms (version): Make static.
+
+ * config/alpha/vms.h (MD_FALLBACK_FRAME_STATE_FOR): Fix error
+ in previous checkin.
+
+ * Makefile.in (install-headers-cp): New target.
+ * config.gcc (alpha-dec-*vms*): Install headers with
+ install-headers-cp
+
+Fri Jan 25 22:42:49 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * unroll.c (unroll_loop): Lower final_value to nonmemory operand;
+ avoid it's copies.
+
+Fri Jan 25 08:26:19 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * builtins.c (expand_builtin_strncpy): Use integer_zerop instead
+ of compare_tree_int.
+ (expand_builtin_strncat): Likewise.
+ * c-decl.c (finish_struct): Use tree_low_cst.
+ * tree.h (compare_tree_int): Arg is unsigned HOST_WIDE_INT.
+ * tree.c (compare_tree_int): Likewise.
+
+2002-01-25 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * reload1.c (eliminate_regs_in_insn): Recognize frame pointer
+ adjustments even if they are implemented by more than two insns.
+
+Fri Jan 25 20:43:56 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * df.c (df_ref_create, df_ref_record_1, df_ref_record): Kill BB arg.
+ * df.h (struct ref): Kill B.
+ (DF_REF_BB, DF_REF_BBNO): Use BLOCK_FOR_INSN.
+
+ * basic-block.h (PROP_EQUAL_NOTES): New flag.
+ * flow.c (propagate_one_insn): Use it.
+ (mark_used_regs): Handle NIL.
+
+2002-01-25 Geoffrey Keating <geoffk@redhat.com>
+
+ * config/stormy16/stormy16.md (tablejump_pcrel): Use a MEM
+ to help folding.
+
+2002-01-25 David Edelsohn <edelsohn@gnu.org>
+
+ * rs6000.md (prefetch): Make address V4SI mode so that the address
+ is restricted to legitimate form for instruction.
+
+2002-01-25 Bob Wilson <bob.wilson@acm.org>
+
+ * doc/install.texi (xtensa-*-elf): New target.
+ (xtensa-*-linux*): New target.
+ * doc/contrib.texi: Add myself.
+
+2002-01-25 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/arm/arm.c (arm_hard_regno_mode_ok): Allow any general
+ purpose register to hold an SImode (or smaller) value.
+
+2002-01-25 Jakub Jelinek <jakub@redhat.com>
+
+ * unwind-dw2-fde-glibc.c: If inhibit_libc, use __register_frame*
+ registry only.
+ * crtstuff.c: Likewise.
+
+2002-01-25 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md (negation patterns): Tighten
+ predicates to register_operand.
+
+2002-01-24 Aldy Hernandez <aldyh@redhat.com>
+
+ * loop.c (emit_prefetch_instructions): Use the prefetch insn's
+ mode, not Pmode.
+
+ * builtins.c (expand_builtin_prefetch): Same.
+
+2002-01-24 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/sh/sh.md (sym_label2reg): Make sure all CONSTs have
+ modes.
+
+2002-01-24 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (print_operand): Remove support for
+ operand character 'A'.
+ * config/h8300/h8300.md (three anonymous patterns): Replace
+ operand character 'A' with either 'T' or 'S'.
+
+2002-01-24 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (print_operand): Remove support for
+ operand character 'U'.
+
+2002-01-24 Andris Pavenis <pavenis@latnet.lv>
+
+ * config/i386/t-djgpp: Use NATIVE_SYSTEM_HEADER_DIR.
+
+2002-01-24 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/arm/arm.c (arm_hard_regno_mode_ok): Allow SImode
+ values to be assigned to the stack pointer.
+
+2002-01-14 Hartmut Penner <hpenner@de.ibm.com>
+
+ * emit_rtl.c (gen_lowpart_common): Conversion from const_int
+ to const_double needs to be done right for big-endian systems.
+
+2002-01-24 Jason Merrill <jason@redhat.com>
+
+ PR c++/2432
+ * config/sparc/sparc.md (call-jump peepholes): Pass the right insn
+ to can_throw_internal.
+
+2002-01-23 Richard Henderson <rth@redhat.com>
+
+ * fold-const.c (fold): Change UINT_MAX test to check vs precision
+ rather than TYPE_MAX_VALUE. Fix indentation and a bogus negation.
+
+2002-01-24 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/sh/sh.md (symGOT_load, sym2GOT, sym2GOTOFF): New expands.
+ (symGOT2reg): Use them, then set as GOT value as unchanging.
+ (symGOTOFF2reg): Set REG_EQUAL note. Use a different pseudo
+ as a temporary, if possible.
+ (symPLT_label2reg): Enclose (pc) in UNSPEC_PIC. Emit
+ sym@PLT-(.LPCS#+2-.) instead of sym@PLT+.-(.LPCS#+2).
+
+2002-01-23 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md: Fix xorqi and xorqi so that they will
+ accept to accept 0x80 as operands[2].
+
+2002-01-24 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/sparc/sparc.md (fix_trunctfdi2): Correct typo in mode.
+
+2002-01-23 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.md (call_value_osf_1_er peepholes): Fix typo.
+
+2002-01-23 Aldy Hernandez <aldyh@redhat.com>
+
+ * c-parse.in (parmlist_or_identifiers): Add maybe_attribute.
+ (parmlist_or_identifiers_1): Verify that only a parmlist follows
+ an attribute.
+
+2002-01-23 Richard Henderson <rth@redhat.com>
+
+ * expr.c (move_by_pieces_1): Extend size before negation.
+
+ * config/m68k/t-m68kbare (MULTILIB_OPTIONS): Add 68040 and 68060.
+ (MULTILIB_MATCHES): Remove 68040 and 68060 aliases.
+ (MULTILIB_EXCEPTIONS): Ignore 68881 and soft-float for 68040 and 68060.
+ * config/m68k/t-m68kelf: Likewise.
+
+2002-01-23 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa/elf.h: New file.
+ * config/xtensa/lib1funcs.asm: New file.
+ * config/xtensa/lib2funcs.S: New file.
+ * config/xtensa/linux.h: New file.
+ * config/xtensa/t-xtensa: New file.
+ * config/xtensa/xtensa-config.h: New file.
+ * config/xtensa/xtensa-protos.h: New file.
+ * config/xtensa/xtensa.c: New file.
+ * config/xtensa/xtensa.h: New file.
+ * config/xtensa/xtensa.md: New file.
+ * config.gcc (xtensa-*-elf*): New target.
+ (xtensa-*-linux*): New target.
+ * cse.c (canon_hash): Compare rtx pointers instead of register
+ numbers. This is required for the Xtensa port.
+ * integrate.c (copy_insn_list): Handle case where the static
+ chain is in memory and the memory address has to be copied to
+ a register.
+ * doc/invoke.texi (Option Summary): Add Xtensa options.
+ (Xtensa Options): New node.
+ * doc/md.texi (Machine Constraints): Add Xtensa machine constraints.
+
+2002-01-23 Zack Weinberg <zack@codesourcery.com>
+
+ * diagnostic.c (internal_error): Do ICE suppression only
+ when ENABLE_CHECKING is not defined.
+
+ * c-typeck.c (require_complete_type): Return error_mark_node
+ if type is error_mark_node.
+
+2002-01-23 Janis Johnson <janis187@us.ibm.com>
+
+ * toplev.c (process_options): Disable -fprefetch-loop-arrays with
+ -Os and issue a warning.
+
+2002-01-23 Zack Weinberg <zack@codesourcery.com>
+
+ * doc/fragments.texi, doc/hostconfig.texi: Update to reflect
+ current (lack of) need for host configuration by hand.
+
+ * doc/gccint.texi, doc/rtl.texi, doc/tm.texi: Adjust cross
+ references. Documentation of some target macros moved from
+ hostconfig.texi to tm.texi.
+
+2002-01-23 Will Cohen <wcohen@redhat.com>
+
+ * config/arm/arm.h (THUMB_FUNCTION_PROFILER): Define if not currently
+ defined.
+
+2002-01-23 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md (*andorhi3): Accept 0x8000 as an
+ operand[3].
+
+2002-01-23 Jason Merrill <jason@redhat.com>
+
+ * tree.c (build1): Don't set TREE_READONLY on INDIRECT_REF.
+
+ * function.c (assign_parms): Don't put args of inline functions
+ into registers when not optimizing.
+
+2002-01-23 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/arm/arm.md (UNSPEC_PROLOGUE_USE): New unspec constant.
+ (prologue_use): New pattern.
+ * config/arm/arm.c (expand_prologue): Use gen_prologue_use in
+ preference to gen_rtx_USE.
+ (thumb_expand_prologue): Use gen_prologue_use in preference to
+ gen_rtx_USE.
+ (thumb_expand_epilogue): Use gen_prologue_use in preference to
+ gen_rtx_USE.
+
+2002-01-23 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * loop.c [!HAVE_prefetch] (CODE_FOR_prefetch): Define to 0.
+
+2002-01-23 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ PR c/3504
+ * doc/extend.texi: Correct documentation of __alignof__.
+
+2002-01-22 Zack Weinberg <zack@codesourcery.com>
+
+ * params.h: Rename arguments of DEFPARAM so that it will be
+ recognized as a translation keyword.
+
+2002-01-22 Aldy Hernandez <aldyh@redhat.com>
+
+ * extend.texi: Document altivec functions.
+ Fix N-bit adjectives in X86 builtin documentation.
+
+2002-01-22 Alexandre Oliva <aoliva@redhat.com>
+
+ * reload.c (reg_overlap_mentioned_for_reload_p): Handle PLUS and
+ auto_inc_dec values.
+
+2002-01-22 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/netbsd-aout.h (SWITCH_TAKES_ARG): Remove bogus white space
+ after backslash.
+ (ASM_DECLARE_OBJECT_NAME): Add missing backslash before final line.
+
+2002-01-22 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/i386/freebsd-aout.h (ASM_QUAD): Undefine.
+
+2002-01-22 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (split_small_symbolic_mem_operand): Use
+ copy_insn not copy_rtx.
+
+2002-01-23 Alan Modra <amodra@bigpond.net.au>
+
+ * combine.c (simplify_and_const_int): Don't trunc_int_for_mode
+ "nonzero" as that might add "1" bits. Ensure "constop" is
+ properly sign extened.
+ (force_to_mode): Tweak for sign extended constop.
+
+2002-01-22 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (some_small_symbolic_mem_operand) Use
+ for_each_rtx instead of assuming we're already looking at the MEM.
+ (split_small_symbolic_mem_operand): Likewise.
+ * config/alpha/alpha.h (PREDICATE_CODES): Update.
+ * config/alpha/alpha.md (small symbolic memory splitters): Update.
+
+2002-01-22 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.md (divmodsi_internal_er): Generate lituse
+ sequence number for the literal.
+ (divmoddi_internal_er): Likewise.
+
+2002-01-22 Craig Rodrigues <rodrigc@gcc.gnu.org>
+
+ PR java/4972
+ * aclocal.m4 (AM_ICONV): Put linking flags for libiconv
+ in LIBICONV variable.
+ * configure: Regenerated.
+
+2002-01-22 Krister Walfridsson <cato@df.lth.se>
+
+ * dependence.c (build_def_use): Remove array_idx.
+
+ * dwarfout.c (last_filename): Remove.
+ (output_compile_unit_die): Remove last_filename.
+
+2002-01-22 Roger Sayle <roger@eyesopen.com>
+ Richard Henderson <rth@redhat.com>
+
+ PR opt/3640
+ * fold-const.c (fold): Optimize unsigned comparisons against
+ UINT_MAX (and similar unsigned constants).
+
+2002-01-22 Janis Johnson <janis187@us.ibm.com>
+
+ * Makefile.in (loop.o): Depend on OPTABS_H.
+ * loop.c (emit_prefetch_instructions): Check the prefetch operand
+ against the predicate.
+
+ PR target/5379
+ * config/i386/i386.md (prefetch_sse): Specify "p" as a constraint
+ for the address operand.
+
+2002-01-22 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/freebsd.h (FUNCTION_PROFILER): Remove.
+
+2002-01-22 Craig Rodrigues <rodrigc@gcc.gnu.org>
+
+ PR other/5450
+ * config/i386/sysv4.h (CPP_SPEC): Define, and add CPU
+ preprocessor flags.
+
+2002-01-22 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config.gcc (x86_64-*-netbsd*): New target.
+ * config/i386/netbsd64.h: New file.
+
+2002-01-22 Aldy Hernandez <aldyh@redhat.com>
+
+ * regrename.c (kill_value): Fix typo.
+
+2002-01-22 Aldy Hernandez <aldyh@redhat.com>
+
+ * doc/tm.texi: Remove STARTING_FRAME_PHASE.
+
+ * config/rs6000/rs6000.h: Same.
+
+ * function.c (instantiate_virtual_regs): Remove
+ STARTING_FRAME_PHASE.
+ (assign_stack_local_1): Same.
+ Calculate frame phase.
+
+2002-01-22 Nick Clifton <nickc@redhat.com>
+
+ * config/arm/arm.h (CONDITIONAL_REGISTER_USAGE): Move 'regno'
+ variable declaration to outer scope in order to simplify
+ future extensions.
+ (HARD_REGNO_MODE_OK): Replace macro body with a with a call to
+ arm_hard_regno_mode_ok.
+ * config/arm/arm-protos.h: Add a prototype for
+ arm_hard_regno_mode_ok.
+ * config/arm/arm.c (soft_df_operand): Remove now redundant
+ check for DImode values using IP_REGNUM.
+ (nonimmediate_soft_df_operand): Remove now redundant check for
+ DImode values using IP_REGNUM.
+ (arm_hard_regno_mode_ok): New function. New check: make sure
+ that DImode values are not stored in IP_REGNUM.
+
+ * config/arm/arm.c (arm_expand_prologue): Replace REG_MAYBE_DEAD
+ note with a USE.
+ (thumb_expand_prologue): Replace REG_MAYBE_DEAD note with a USE.
+
+2002-01-22 Jason Merrill <jason@redhat.com>
+
+ * c-semantics.c (genrtl_compound_stmt): Only check nesting
+ consistency if this COMPOUND_STMT is scoped.
+
+2002-01-22 Kazu Hirata <kazu@hxi.com>
+
+ * predict.c: Fix formatting.
+ * print-tree.c: Likewise.
+ * protoize.c: Likewise.
+ * real.h: Likewise.
+ * rtl.h: Likewise.
+ * sbitmap.h: Likewise.
+ * scan.c: Likewise.
+ * sched-deps.c: Likewise.
+ * sched-vis.c: Likewise.
+ * sdbout.c: Likewise.
+ * sibcall.c: Likewise.
+ * ssa.c: Likewise.
+ * ssa-ccp.c: Likewise.
+ * ssa-dce.c: Likewise.
+ * stmt.c: Likewise.
+ * stor-layout.c: Likewise.
+ * system.h: Likewise.
+
+Tue Jan 22 06:26:33 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * tree.c (int_fits_type_p): If bounds of a subtype are variable, see
+ if fits in bounds of base type.
+
+ * dwarf2out.c (equate_decl_number_to_die): Add "int" to decls.
+ (loc_descriptor_from_tree, case CALL_EXPR, case ADDR_EXPR): New.
+ (add_bound_info, default): If can't find a context, make a
+ SAVE_EXPR.
+ (dwarf2out_finish): Check for SAVE_EXPR in node->created_for.
+
+2002-01-22 Hans-Peter Nilsson <hp@axis.com>
+
+ * c-typeck.c (parser_build_binary_op): If result from
+ build_binary_op is ERROR_MARK just return error_mark_node without
+ further processing.
+
+2002-01-21 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * config/netbsd.h (TARGET_HAS_F_SETLKW): define.
+ Split a.out-specific bits into...
+ * config/netbsd-aout.h: ...this.
+ * config/netbsd-elf.h: New file.
+ * config/alpha/netbsd-elf.h: Remove.
+ * config/alpha/netbsd.h: Rewrite for a NetBSD/alpha ELF target.
+ * config/i386/netbsd-elf.h (LIB_SPEC): Remove.
+ (STARTFILE_SPEC): Remove redundant definition.
+ (ENDFILE_SPEC): Likewise.
+ (LINK_SPEC): Likewise.
+ (CPP_SPEC): Likewise.
+ (ASM_SPEC): Likewise.
+ (LIB_SPEC): Likewise.
+ (SWITCH_TAKES_ARG): Likewise.
+ (TARGET_MEM_FUNCTIONS): Likewise.
+ (CPP_PREDEFINES): Redefine.
+ (ASM_FINAL_SPEC): Remove redefinition.
+ (ASM_COMMENT_START): Redefine.
+ (FUNCTION_PROFILER): Define.
+ (TARGET_VERSION): Redefine.
+ Comment and formatting cleanup.
+ * config/i386/netbsd.h: Include <netbsd-aout.h>.
+ * config/m68k/netbsd.h: Include <netbsd-aout.h>.
+ * config/mips/netbsd.h: Rewrite for NetBSD/mips ELF target,
+ big- or little-endian.
+ * config/ns32k/netbsd.h: Include <netbsd-aout.h>.
+ * config.gcc (*-*-netbsd*): Add definitions common to all
+ NetBSD configs.
+ (alpha*-*-netbsd*): Remove redundant xm_defines, gas, and
+ gnu_ld definitions. Add netbsd-elf.h to and remove
+ alpha/netbsd-elf.h from tm_file. Remove alpha/t-crtfm from
+ tmake_file, and don't lose previous tmake_file contents.
+ (arm*-*-netbsd*): Add netbsd-aout.h to tm_file.
+ (i[34567]86-*-netbsdelf*): Remove redundant xm_defines, gas, and
+ gnu_ld definitions. Add netbsd-elf.h to tm_file.
+ (mips-dec-netbsd*): Remove as alias for mipsel-*-netbsd*.
+ (mipsel-*-netbsd*): Rename this to...
+ (mips*-*-netbsd*): ...this. Add elfos.h to tm_file. Add
+ mips/little.h to tm_file for mips*el-*.
+ (powerpc-*-netbsd*): Remove redundant xm_defines definition.
+ (sparc-*-netbsd*): Add netbsd-aout.h to tm_file.
+ (vax-*-netbsd*): Add netbsd-aout.h to tm_file.
+
+2002-01-21 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa-protos.h (reg_before_reload_operand): New function prototype.
+ * pa.c (reg_before_reload_operand): New function implementation.
+ * pa.md (decrement_and_branch_until_zero, movb): Use it. Change "!*m"
+ contraints to "*m".
+
+2002-01-21 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ * combine.c (simplify_and_const_int): Properly sign-extend CONSTOP.
+
+2002-01-21 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa64-hpux.h (MD_EXEC_PREFIX): Set to "/usr/ccs/bin".
+ (MD_STARTFILE_PREFIX): Set to "/usr/ccs/lib/pa20_64/".
+ (MD_STARTFILE_PREFIX_1): Set to "/opt/langtools/lib/pa20_64/".
+ (EH_FRAME_IN_DATA_SECTION): Define and update comment on init sections.
+ (ENDFILE_SPEC): Undefine.
+ (STARTFILE_SPEC): Redefine for PA.
+
+2002-01-21 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
+
+ * config/rs6000/t-ppccomm (CRTSTUFF_T_CFLAGS_S): Re-add -fPIC.
+
+2002-01-21 Daniel Jacobowitz <drow@mvista.com>
+
+ * config.gcc: Add entries to supported PowerPC --with-cpu
+ types.
+
+2002-01-21 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (ix86_function_arg_regno_p): Never return
+ true for 64-bit mode only SSE registers in 32-bit mode.
+
+2002-01-21 Kazu Hirata <kazu@hxi.com>
+
+ * unwind-dw2.c: Fix formatting.
+ * unwind-dw2-fde.c: Likewise.
+ * unwind-dw2-fde.h: Likewise.
+ * unwind-pe.h: Likewise.
+ * varasm.c: Likewise.
+ * varray.h: Likewise.
+
+2002-01-21 Hans-Peter Nilsson <hp@bitrange.com>
+
+ Remove workaround for register stack overwrite bug in mmix.
+ * config/mmix/mmix.c (mmix_target_asm_function_prologue): Remove
+ support for TARGET_REG_STACK_FILL_BUG.
+ * config/mmix/mmix.h: Remove member has_call_without_parameters.
+ (TARGET_MASK_REG_STACK_FILL_BUG, TARGET_REG_STACK_FILL_BUG):
+ Delete.
+ (TARGET_DEFAULT): Remove TARGET_MASK_REG_STACK_FILL_BUG.
+ (TARGET_SWITCHES): Remove -mreg-stack-fill-bug-workaround and
+ -mno-reg-stack-fill-bug-workaround.
+ * config/mmix/mmix.md ("call", "call_value"): Don't set struct
+ machine member has_call_without_parameters.
+ * doc/invoke.texi (Option Summary) <MMIX Options>: Remove
+ -mreg-stack-fill-bug-workaround and
+ -mno-reg-stack-fill-bug-workaround.
+ (MMIX Options): Ditto.
+
+2002-01-21 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (function_arg): Replace 0 with NULL_RTX
+ as appropriate.
+ Remove redundant code.
+
+2002-01-21 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * config/alpha/alpha.h, config/arc/arc.h, config/avr/avr.h,
+ config/c4x/c4x.h, config/d30v/d30v.h, config/dsp16xx/dsp16xx.h,
+ config/fr30/fr30.h, config/ia64/ia64.h, config/m68hc11/m68hc11.h,
+ config/mips/mips.h, config/rs6000/rs6000.h, config/sparc/sparc.h,
+ config/stormy16/stormy16.h, config/v850/v850.h: Remove commented
+ out target macro definitions and non-target-specific comments
+ mostly taken from old versions of the manual.
+
+2002-01-20 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.h: Fix comment formatting.
+ * config/ia64/aix.h: Likewise.
+ * config/ia64/ia64-protos.h: Likewise.
+ * config/ia64/ia64.c: Likewise.
+ * config/ia64/ia64.h: Likewise.
+ * config/ia64/ia64intrin.h: Likewise.
+ * config/ia64/linux.h: Likewise.
+ * config/ia64/unwind-aix.c: Likewise.
+ * config/ia64/unwind-ia64.c: Likewise.
+
+2002-01-20 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c: Revise comments about shift code.
+
+2002-01-20 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (function_arg): Update a comment.
+
+2002-01-20 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md: Update the comments at the beginning
+ of the file.
+
+2002-01-20 Kazu Hirata <kazu@hxi.com>
+
+ * config/i370/i370.c: Fix comment formatting.
+ * config/i370/i370.h: Likewise.
+ * config/i370/i370.md: Likewise.
+ * config/i370/linux.h: Likewise.
+
+Sun Jan 20 18:40:14 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * reg-stack.c (subst_stack_regs): Properly check for deleted insn.
+
+ * dwarf2out.c (loc_descriptor_from_tree): Add TRUTH_*_EXPR cases.
+ (gen_struct_or_union_type_die): Don't SIGSEGV if no TYPE_STUB_DECL
+ in incomplete case.
+
+2002-01-20 Graham Stott <grahams@redhat.com>
+
+ * cfgloop.c (flow_loop_preheader_scan): Fix typo.
+
+2002-01-19 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * config.gcc (hppa*64*-*-hpux11*): Fix tmake_file.
+
+2002-01-19 Tom Rix <trix@redhat.com>
+
+ * config/rs6000/rs6000.md: Fix DF split for 64 bit hosts.
+
+2002-01-18 Aldy Hernandez <aldyh@redhat.com>
+
+ * doc/tm.texi (STARTING_FRAME_PHASE): Document.
+
+ * function.c (assign_stack_local_1): Adjust x_frame_offset with
+ STARTING_FRAME_PHASE.
+ (STARTING_FRAME_PHASE): New.
+ (instantiate_virtual_regs): Check saneness of
+ STARTING_FRAME_PHASE.
+
+ * config/rs6000/rs6000.h (STARTING_FRAME_PHASE): New.
+
+2002-01-19 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/sh/sh.md (movdf_i4 split): Fix alter_subreg calls.
+
+2002-01-18 Craig Rodrigues <rodrigc@gcc.gnu.org>
+
+ * doc/install.texi (hppa*-hp-hpux11): Clarify that GCC 2.95.x cannot
+ be used for bootstrapping GCC 3.0.
+
+2002-01-18 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md: Fix an insn length.
+
+2002-01-18 Kazu Hirata <kazu@hxi.com>
+
+ * bitmap.h: Fix comment formatting.
+ * combine.c: Likewise.
+ * cppfiles.c: Likewise.
+ * c-pragma.h: Likewise.
+ * c-typeck.c: Likewise.
+ * df.c: Likewise.
+ * dwarf2out.c: Likewise.
+ * function.c: Likewise.
+ * gcc.c: Likewise.
+ * genattrtab.c: Likewise.
+ * gthr-win32.h: Likewise.
+ * haifa-sched.c: Likewise.
+ * predict.c: Likewise.
+ * rtlanal.c: Likewise.
+ * rtl.h: Likewise.
+ * unwind-dw2-fde.h: Likewise.
+ * unwind-pe.h: Likewise.
+ * vmsdbgout.c: Likewise.
+
+Thu Jan 17 15:28:26 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * attribs.c (decl_attributes): Clear ATTR_FLAG_TYPE_IN_PLACE
+ if type_required and passed decl.
+
+2002-01-17 Aldy Hernandez <aldyh@redhat.com>
+
+ * config.gcc (cpu_type): Include altivec.h in powerpc
+ extra_headers.
+ Same for darwin.
+
+ * config/rs6000/altivec.h: New.
+
+2002-01-17 David Edelsohn <edelsohn@gnu.org>
+
+ * doc/install.texi (*-ibm-aix*): Update assembler and exception
+ handling information.
+ * doc/trouble.texi (Interoperation): Add libstdc++ information
+ for AIX.
+ (Misunderstandings): Add template instantiation and static template
+ member information for AIX.
+
+2002-01-17 Jason Merrill <jason@redhat.com>
+
+ * dbxout.c (dbxout_type): Support const and volatile.
+
+ * except.c (add_partial_entry): Remove backwards compatibility code.
+ (end_protect_partials): Likewise.
+
+2002-01-17 Jakub Jelinek <jakub@redhat.com>
+
+ * config/ia64/ia64.md (prologue_use): New.
+ * config/ia64/ia64.c (ia64_expand_prologue): Use
+ gen_prologue_use instead of gen_rtx_USE.
+ (group_barrier_needed_p): Handle CODE_FOR_prologue_use the same way
+ as CODE_FOR_pred_rel_mutex.
+ (ia64_sched_reorder2): Likewise.
+
+2002-01-16 Eric Christopher <echristo@redhat.com>
+
+ * config/mips/r3900.h: Reformat.
+ (SUBTARGET_CPP_SIZE_SPEC): Remove.
+ * config/mips/isa3264.h (SUBTARGET_CPP_SIZE_SPEC): Ditto.
+ * config/mips/mips.h (ABI_GAS_ASM_SPEC): Default to "".
+ (SUBTARGET_CPP_SIZE_SPEC): Rewrite.
+ * config/mips/t-elf: Remove mips3 multilib.
+
+2002-01-16 H.J. Lu <hjl@gnu.org>
+
+ * config/mips/linux.h: Include "mips/abi64.h".
+
+2002-01-16 H.J. Lu <hjl@gnu.org>
+
+ * config/mips/t-linux: New.
+
+ * config.gcc: Add mips/t-linux to tmake_file for mips*-*-linux*.
+
+ * config/mips/linux.h: Don't include "gofast.h".
+ (INIT_SUBTARGET_OPTABS): Removed.
+
+2002-01-16 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300-protos.h: Replace emit_a_shift with
+ output_a_shift.
+ * config/h8300/h8300.c: Likewise.
+ * config/h8300/h8300.md: Likewise.
+
+2002-01-16 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md (pushqi1_h8300): Use a tab instead of
+ spaces after an opcode name.
+ (pushqi1_h8300hs): Likewise.
+ (pushhi1_h8300hs): Likewise.
+
+2002-01-16 Kazu Hirata <kazu@hxi.com>
+
+ * doc/extend.texi: Replace "option" with "attribute"
+ appropriately.
+
+2002-01-16 Jakub Jelinek <jakub@redhat.com>
+
+ * config/alpha/alpha.c (some_small_symbolic_mem_operand): Look into
+ (and:DI () (const_int -8)).
+ (split_small_symbolic_mem_operand): Split
+ (mem (and:DI () (const_int -8)).
+
+2002-01-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/5309:
+ * config/sparc/sparc.c (ultrasparc_adjust_cost): Handle TYPE_IDIV the
+ same way as TYPE_IMUL.
+ (ultrasparc_sched_reorder): Likewise.
+ * config/sparc/sparc.md (type): Add comment to update
+ ultrasparc_sched_reorder when making changes.
+
+2002-01-16 Kazu Hirata <kazu@hxi.com>
+
+ * doc/invoke.texi: Change the dump file name of block
+ reordering pass from 28.bbro to 29.bbro.
+ Mention -dk option.
+
+Wed Jan 16 17:54:22 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (minsf splitter): Fix pasto.
+
+2002-01-16 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/arm/arm.c (arm_expand_prologue): Add REG_MAYBE_DEAD note
+ to frame pointer initialisation instruction.
+ (thumb_expand_prologue): Add REG_MAYBE_DEAD note to frame pointer
+ initialisation instruction.
+ (soft_df_operand): Do not accept the IP register.
+ (nonimmediate_soft_df_operand): Do not accept the IP register.
+
+2002-01-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/5357:
+ * config/sparc/sparc.c (sparc_override_options): Avoid MASK_V9 and
+ MASK_V8 being both set.
+
+2002-01-16 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.c (s390_emit_prologue): Do not emit USE
+ insn for GOT register; add REG_MAYBE_DEAD notes instead.
+ config/s390/s390.md (call, call_value): Add GOT register to
+ CALL_INSN_FUNCTION_USAGE where needed.
+ (call_exp, call_value_exp): New.
+
+2002-01-16 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/arm/arm.c: General formatting tidy up.
+
+2002-01-16 Graham Stott <grahams@redhat.com>
+
+ * calls.c (try_to_integrate): Use "(size_t)" intermediate
+ cast and when casting an integer literal to "rtx" pointer.
+ (expand_call): Likewise.
+ * flow.c (try_pre_increment): Likewise.
+ (find_use_as_address): Likewise.
+ * integrate.c (expand_iline_function): Likewise.
+ * regmove.c (try_auto_increment): Likewise.
+
+2002-01-16 Graham Stott <grahams@redhat.com>
+
+ * sched-rgn.c (passed): Use sbitmap_free.
+ (header): Likewise.
+ (inner): Likewise.
+ (in_queue): Likewise.
+ (in_stack): Likewise.
+
+2002-01-15 Eric Christopher <echristo@redhat.com>
+
+ * flow.c (propagate_one_insn): Change to use fatal_insn.
+
+2002-01-15 Kazu Hirata <kazu@hxi.com>
+
+ * expmed.c (extract_fixed_bit_field): Remove unused code.
+ * system.h: Poison SLOW_ZERO_EXTEND.
+ * doc/tm.texi: Remove.
+ * config/1750a/1750a.h (SLOW_ZERO_EXTEND): Remove.
+ * config/arm/arm.h: Likewise.
+ * config/avr/avr.h: Likewise.
+ * config/clipper/clipper.h: Likewise.
+ * config/convex/convex.h: Likewise.
+ * config/d30v/d30v.h: Likewise.
+ * config/dsp16xx/dsp16xx.h: Likewise.
+ * config/elxsi/elxsi.h: Likewise.
+ * config/fr30/fr30.h: Likewise.
+ * config/h8300/h8300.h: Likewise.
+ * config/i370/i370.h: Likewise.
+ * config/i386/i386.h: Likewise.
+ * config/m68k/m68k.h: Likewise.
+ * config/mips/mips.h: Likewise.
+ * config/ns32k/ns32k.h: Likewise.
+ * config/pdp11/pdp11.h: Likewise.
+ * config/pj/pj.h: Likewise.
+ * config/s390/s390.h: Likewise.
+ * config/sh/sh.h: Likewise.
+ * config/stormy16/stormy16.h: Likewise.
+ * config/v850/v850.h: Likewise.
+ * config/vax/vax.h: Likewise.
+ * config/we32k/we32k.h: Likewise.
+
+2002-01-15 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.md (altivec_stvx): Add parallels to stvx.
+ (altivec_lvsl): Change constraint to b.
+ (altivec_lvsr): Same.
+ (altivec_lvebx): Same.
+ (altivec_lvehx): Same.
+ (altivec_lvewx): Same.
+ (altivec_lvxl): Same.
+ (altivec_lvx): Same.
+ (altivec_stvx): Add parallel.
+ (altivec_stvxl): Same.
+ (altivec_stvehx): Same.
+ (altivec_stvebx): Same.
+ (altivec_stvebx): Same.
+
+2002-01-15 Aldy Hernandez <aldyh@redhat.com>
+
+ * config.gcc: Change altivec.h to altivec-defs.h.
+
+ * config/rs6000/altivec.h: Delete.
+
+ * config/rs6000/altivec-defs.h: Add.
+
+2002-01-15 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * vax.c (vax_rtx_cost): Return MAX_COST for unsupported MULT, UDIV
+ and UMOD modes.
+
+ * vax.h (INDEX_TERM_P): Restrict indexing to modes which have a size
+ less than or equal to eight bytes.
+
+ * vax.md (andsi3): Remove constraints and change SET destination
+ operand type to nonimmediate_operand.
+ (andhi3, andqi3): Likewise. Don't clear high order bits of operand 1
+ when it is a CONST_INT.
+
+2002-01-15 Jason Merrill <jason@redhat.com>
+
+ * c-common.def (FILE_STMT): New code.
+ * c-common.c (statement_code_p): It's a statement.
+ * c-common.h (stmt_tree_s): Add x_last_filename.
+ (FILE_STMT_FILENAME_NODE, FILE_STMT_FILENAME): New macros.
+ (last_expr_filename): New macro.
+ * c-semantics.c (begin_stmt_tree): Initialize it.
+ (add_stmt): If the filename changed, also insert a
+ FILE_STMT.
+ (expand_stmt): Handle seeing one.
+
+2002-01-15 Eric Christopher <echristo@redhat.com>
+
+ * flow.c (propagate_one_insn): Add error message and print out
+ insn for debugging.
+
+2002-01-15 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * system.h (ASM_IDENTIFY_GCC, STDC_VALUE, TRAMPOLINE_ALIGN,
+ ASM_IDENTIFY_GCC_AFTER_SOURCE): Poison.
+ * config/pdp11/pdp11.h (TRAMPOLINE_ALIGN): Rename to
+ TRAMPOLINE_ALIGNMENT.
+ * config/arm/arm.h, config/mcore/mcore.h: Likewise. Change value
+ to be in bits.
+ * config/i386/cygwin.h (PCC_BITFIELDS_TYPE_MATTERS): Rename to
+ PCC_BITFIELD_TYPE_MATTERS.
+ * config/interix.h (STDC_VALUE): Remove. Use
+ STDC_0_IN_SYSTEM_HEADERS.
+ * config/darwin.h (ASM_IDENTIFY_GCC), config/dsp16xx/dsp16xx.h
+ (ASM_IDENTIFY_GCC), config/stormy16/stormy16.h (ASM_IDENTIFY_GCC,
+ ASM_IDENTIFY_GCC_AFTER_SOURCE): Remove.
+
+2002-01-15 Craig Rodrigues <rodrigc@gcc.gnu.org>
+
+ * doc/install.texi (hppa*-hp-hpux11): --enable-threads does
+ not work on this platform currently.
+
+2002-01-15 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * c-typeck.c (build_unary_op): Don't wrap msgid argument of
+ readonly_warning in _().
+
+2002-01-15 Douglas B Rupp <rupp@gnat.com>
+
+ * gcc.c (delete_if_ordinary): Backout previous change.
+
+2002-01-15 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (print_operand): Remove support for
+ unused operand characters.
+
+ * read-rtl.c: Fix formatting.
+ * real.c: Likewise.
+ * recog.c: Likewise.
+ * regclass.c: Likewise.
+ * regmove.c: Likewise.
+ * reg-stack.c: Likewise.
+ * reload1.c: Likewise.
+ * rtlanal.c: Likewise.
+
+2002-01-15 Kazu Hirata <kazu@hxi.com>
+
+ * config/i386/i386.c: Fix formatting.
+
+2002-01-15 Jakub Jelinek <jakub@redhat.com>
+
+ * c-typeck.c (process_init_element): Don't save_expr
+ COMPOUND_LITERAL_EXPR if just its initializer will be used.
+
+2002-01-15 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.c (rs6000_output_function_epilogue): Do not
+ emit optional traceback table if optimize_size or TARGET_ELF.
+ * config/rs6000/rs6000.md (prefetch): New.
+
+2002-01-15 Andreas Jaeger <aj@suse.de>
+
+ * config.gcc (x86_64-*-*): Install mmintrin.h and xmmintrin.h.
+
+2002-01-15 Kazu Hirata <kazu@hxi.com>
+
+ * mips-tfile.c: Fix formatting.
+
+Tue Jan 15 00:56:11 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * unroll.c (final_reg_note_copy): Fix previous commit.
+
+2002-01-14 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300-protos.h: Remove the prototype for
+ eq_operator.
+ * config/h8300/h8300.c (eq_operator): Remove.
+
+2002-01-14 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.md (prefetch): Tidy.
+ (prefetch_3dnow): Fix locality operand.
+
+2002-01-14 Richard Henderson <rth@redhat.com>
+
+ * config/mips/mips.h (HI_AND_FP_REGS): New register class.
+ (CLASS_CANNOT_CHANGE_MODE): Disallow HI in little-endian mode.
+
+2002-01-14 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * reload1.c (reload_combine): Pass reg_sum replacement through
+ copy_rtx in loop performing multiple changes.
+
+2002-01-14 Jakub Jelinek <jakub@redhat.com>
+
+ * except.c (remove_unreachable_regions): New.
+ (free_eh_status): Clear exception_handler_labels.
+ (convert_from_eh_region_ranges): Call remove_unreachable_regions.
+ (find_exception_handler_labels): Don't add the same label more than
+ once.
+ (remove_exception_handler_label): Don't die if
+ find_exception_handler_labels hasn't been called for the current
+ function yet.
+
+Mon Jan 14 21:26:13 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * toplev.c (rest_of_compilation): Rebuild jump labels after
+ gcse.
+
+2002-01-14 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/extend.texi: Move documentation of X86 built-in functions
+ here.
+ * doc/invoke.texi: From here.
+ * doc/sourcebuild.texi: Document location of documentation for
+ machine built-in functions.
+
+2002-01-13 Christopher Faylor <cgf@redhat.com>
+
+ * cppfiles.c (TEST_THRESHOLD): New macro.
+ (SHOULD_MMAP): Ditto.
+ (read_include_file): Use SHOULD_MMAP macro to decide when mmap should
+ be used.
+
+Mon Jan 14 20:23:34 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * unroll.c (final_reg_note_copy): Properly handle
+ REG_LABEL
+ (unroll_loops): Fix LOOP_CONDITION heuristics.
+
+2002-01-14 Geoffrey Keating <geoffk@redhat.com>
+
+ * doc/invoke.texi (Xstormy16 Options): Add xstormy16 option.
+ * doc/md.texi (Machine Constraints): Use @minus{} where appropriate.
+
+Mon Jan 14 20:18:19 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgcleanup.c (try_forward_edges): Avoid infinite loop at infinite
+ threaded loop.
+
+2002-01-14 Tom Rix <trix@redhat.com>
+
+ * config/rs6000/rs6000.md: Fix typo with sradi.
+
+2002-01-14 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.md (movstrdix_64, movstrsix_31, movstrdi_64,
+ movstrsi_31, clrstrsi_64, clrstrsi_31): Improve RTL templates.
+ (clrstrdi, clrstrsi): Adapt callers.
+
+ (extendsidi2, zero_extendsidi2): Remove no-conflict blocks.
+
+ (movti splitter): Never use register 0 as base register.
+
+2002-01-14 Hartmut Penner <hpenner@de.ibm.com>
+
+ * combine.c (simplify_shift_const): Always generate new rtx
+ for shift expression instead of reusing given expression.
+
+Mon Jan 14 07:08:55 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * config/alpha/alpha.c (alpha_expand_mov): Don't call
+ alpha_legitimize_address unless mode is Pmode.
+
+2002-01-13 Geoffrey Keating <geoffk@redhat.com>
+
+ * doc/md.texi (Modifiers): Document the '*' constraint for the
+ user.
+
+ * doc/md.texi (Machine Constraints): Add constraints for xstormy16.
+ * doc/extend.texi (Function Attributes): 'interrupt' is valid
+ for xstormy16 too.
+
+2002-01-13 Richard Henderson <rth@redhat.com>
+
+ * reload.c (find_reloads): Use a hard reg destination as reload reg
+ for an input reload of the source.
+
+2002-01-13 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/install.texi (Binaries): Make link to ftp.writtenword.com
+ more generic.
+
+Sun Jan 13 07:23:01 2002 Douglas B Rupp <rupp@gnat.com>
+
+ * Makefile.in (LIB2FUNCS): Split into LIB2FUNCS_1 and LIB2FUNCS_2.
+ * mklibgcc.in (LIB2FUNCS): Split into LIB2FUNCS_1 and LIB2FUNCS_2.
+
+ * config/alpha/x-vms (USE_COLLECT2): Set to empty.
+
+Sun Jan 13 06:55:31 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * dwarf2out.c (mem_loc_descriptor, case ADDRESSOF): New case.
+
+2002-01-12 Tom Rix <trix@redhat.com>
+
+ * config/rs6000/rs6000.c (rs6000_emit_set_long_const): Use ior for
+ TARGET_POWERPC64.
+
+2002-01-12 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (bdesc_2arg): Mark psadbw MASK_3DNOW_A.
+
+ * doc/invoke.texi: Update Alpha options.
+
+ * doc/invoke.texi: Update i386 built-in function lists.
+
+Sat Jan 12 17:38:11 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * unroll.c (final_reg_note_copy): Avoid crash on REG_LABEL note
+ referencing outside.
+
+Sat Jan 12 08:54:51 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * diagnostic.c (warn_deprecated_use): Rework to lower indentation.
+ * expr.c (emit_move_insn_1): Remove warning, use HOST_WIDE_INT for
+ offsets, and change line folding.
+ * optabs.c (expand_binop): Remove warnings.
+ * sdbout.c (sdbout_record_type_name): Constify NAME to avoid warning.
+
+2002-01-12 Graham Stott <grahams@redhat.com>
+
+ * attribs.c (handle_deprecated_attribute): constify WHAT.
+ * diagnostic.c (warn_deprecated_use): Add braces, fixes
+ dangling else warning and constify WHAT.
+ * except.h (struct function, struct inline_remap): Move
+ struct tag forward defs before all prototypes.
+ (duplicate_eh_regions): Whitespace.
+
+2002-01-12 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/arm/arm.h (ARM_LEGITIMIZE_RELOAD_ADDRESS): Use
+ MODE_BASE_REG_CLASS.
+ (THUMB_LEGITIMIZE_RELOAD_ADDRESS): Use MODE_BASE_REG_CLASS.
+
+2002-01-12 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386.c (override_options): If SSE, enable sse prefetch.
+ (ix86_expand_vector_move): New.
+ (bdesc_2arg): Remove andps, andnps, orps, xorps.
+ (ix86_init_mmx_sse_builtins): Make static. Remove composite builtins.
+ Remove old prefetch builtins. Special case the logicals removed above.
+ (ix86_expand_builtin): Likewise.
+ (safe_vector_operand): Use V4SFmode, not TImode.
+ (ix86_expand_store_builtin): Remove shuffle arg. Update callers.
+ (ix86_expand_timode_binop_builtin): New.
+ * config/i386/i386-protos.h: Update.
+ * config/i386/i386.h (enum ix86_builtins): Update.
+ * config/i386/i386.md: Correct predicates on MMX/SSE patterns.
+ Use ix86_expand_vector_move in vector move expanders.
+ (movti_internal, movti_rex64): Add xorps alternative.
+ (sse_clrv4sf): Rename and adjust from sse_clrti.
+ (prefetch): Don't work so hard.
+ (prefetch_sse, prefetch_3dnow): Use PREFETCH rtx, not UNSPEC.
+ * config/i386/xmmintrin.h (__m128): Use V4SFmode.
+ (_mm_getcsr, _mm_setcsr): Fix typo in builtin name.
+
+2002-01-11 Richard Henderson <rth@redhat.com>
+
+ * config/i386/mmintrin.h: New file.
+ * config/i386/xmmintrin.h: New file.
+ * config.gcc (i?86-*-*): Add extra_headers.
+ * simplify-rtx.c (simplify_unary_operation): Handle saturating
+ truncation codes.
+ (simplify_binary_operation): Handle saturating arithmetic codes.
+ * config/i386/i386.c (ix86_expand_sse_comi): Return the full result,
+ not the lowpart subreg.
+ (ix86_expand_builtin): Return a TImode dummy register instead of 0
+ on error.
+ * config/i386/i386.md (mmx_clrdi): Override memory attribute.
+
+2002-01-12 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * conflict.c (conflict_graph_compute): Free regsets when finished.
+ * ssa.c (compute_coalesced_reg_partition): Likewise.
+
+2002-01-12 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+
+ * global.c (find_reg): Check for HARD_REGNO_CALL_PART_CLOBBERED
+ every where we allocate a register.
+
+2002-01-12 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * gcse.c (compute_pre_data, pre_gcse): Use sbitmap_free.
+ * lcm.c (compute_earliest, compute_farthest): Likewise.
+
+2002-01-11 Janis Johnson <janis187@us.ibm.com>
+
+ * expr.c (expand_assignment): Fix misuse of MEM_KEEP_ALIAS_SET.
+
+2002-01-11 Janis Johnson <janis187@us.ibm.com>
+
+ * doc/rtl.texi (Insns): Fix 2 typos.
+
+2002-01-11 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/invoke.texi: Avoid overfull hboxes. Add summary of D30V
+ options. Use @table @gcctabopt for MMIX options. Add index
+ entries for MMIX options. Start new paragraph with first
+ heading of the machine-dependent options.
+
+2002-01-11 Craig Rodrigues <rodrigc@gcc.gnu.org>
+
+ PR other/5299
+ * config/ns32k/ns32k.md: Fix spelling mistake of "than" in comments.
+ * combine.c (force_to_mode): Same.
+ * reload1.c (clear_reload_reg_in_use): Same.
+
+2002-01-11 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * config/arm/arm.c (arm_gen_constant): Correct test of 'remainder'
+ and 'subtargets'.
+
+2002-01-11 Andreas Jaeger <aj@suse.de>,
+ Brad Lucier <lucier@math.purdue.edu>
+
+ * config/i386/i386.h (CPP_CPUCOMMON_SPEC): Remove wrong
+ mcpu.
+
+Fri Jan 11 07:35:12 2002 Douglas B Rupp <rupp@gnat.com>
+
+ * config/alpha/vms.h: (MD_FALLBACK_FRAME_STATE_FOR): Fix errors.
+ Protect with IN_LIBGCC.
+ (LINK_EH_SPEC): Add required trailing space.
+
+Fri Jan 11 09:25:05 2002 Nicola Pero <n.pero@mi.flashnet.it>
+
+ * c-tree.h: Move function declarations so that they are listed
+ under the filename which contains them.
+ (check_identifier, finish_decl_top_level,
+ lookup_name_current_level_global, shadow_record_fields): Remove.
+
+2002-01-11 Andreas Jaeger <aj@suse.de>
+
+ * config/i386/i386.h (CPP_CPUCOMMON_SPEC): Remove duplicated
+ march.
+
+2002-01-10 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (print_operand): Add 'J'.
+ * config/alpha/alpha.md (call_osf_1_er, call_value_osf_1_er): Take a
+ new operand with the sequence number for the lituse. When splitting
+ the insns, use gen_movdi_er_high_g and generate a sequence number.
+ (gen_movdi_er_high_g): Print the sequence number if nonzero.
+
+2002-01-10 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c (altivec_init_builtins): Add support for
+ lvebx, lvehx, lvewx, lvxl, lvx, stvx, stvebx, stvehx, stvewx,
+ stvxl.
+ (altivec_expand_builtin): Same.
+ (altivec_expand_stv_builtin): New.
+
+ * config/rs6000/rs6000.h (rs6000_builtins): Same.
+
+ * config/rs6000/rs6000.md ("altivec_lvebx"): New.
+ ("altivec_lvehx"): New.
+ ("altivec_lvewx"): New.
+ ("altivec_lvxl"): New.
+ ("altivec_lvx"): New.
+ ("altivec_stvx"): New.
+ ("altivec_stvebx"): New.
+ ("altivec_stvehx"): New.
+ ("altivec_stvewx"): New.
+ ("altivec_stvxl"): New.
+
+2002-01-10 Richard Henderson <rth@redhat.com>
+
+ * cfgrtl.c (delete_insn): Assert insn hasn't been deleted yet.
+ * reload1.c (delete_output_reload): Zap spill_reg_store. Take
+ care not to delete instructions twice.
+
+2002-01-10 Zack Weinberg <zack@codesourcery.com>
+
+ * toplev.c: Don't declare environ (it's not used anywhere).
+ * configure.in: Don't check for declaration of environ.
+ * config/i386/xm-mingw32.h: Don't #define environ.
+ * config.in, configure: Regenerate.
+
+2002-01-10 Zack Weinberg <zack@codesourcery.com>
+
+ * configure.in: Set stage1_cflags for powerpc-*-darwin*.
+ * configure: Regenerate.
+
+ * config/interix.h: Set DO_GLOBAL_CTORS_BODY and
+ DO_GLOBAL_DTORS_BODY here, not in xm-interix.h.
+ * config/alpha/vms.h: Set INCLUDE_DEFAULTS here, not in
+ alpha/xm-vms.h.
+ * config/m68k/t-next: Set OTHER_FIXINCLUDES_DIRS and
+ LIMITS_H_TEST here, not in m68k/x-next.
+ * config/rs6000/beos.h: Set STANDARD_INCLUDE_DIR and
+ SYSTEM_INCLUDE_DIR here, not in rs6000/xm-beos.h.
+
+ * config/x-interix: Don't set RANLIB, RANLIB_TEST, SHELL,
+ LIBGCC2_INCLUDES, or SYSTEM_HEADER_DIR.
+ * config/alpha/x-vms: Don't set USE_COLLECT2. Add comments.
+
+ * config/i386/x-djgpp: Renamed i386/t-djgpp.
+ * config/m88k/x-dolph: Renamed m88k/t-dolph.
+ * config/m88k/x-texXD88: Renamed m88k/t-texXD88.
+ * config/pa/x-pa-mpeix: Renamed pa/t-mpeix. Update for
+ replacement of quadlib.asm with quadlib.c.
+
+ * config/x-interix3, config/xm-interix.h, config/i386/x-beos,
+ config/i386/xm-osf1elf.h, config/rs6000/x-darwin,
+ config/rs6000/xm-beos.h: Delete file.
+
+ * config.gcc: Update to match above changes.
+
+2002-01-10 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.h: Fix comment typos.
+ * config/h8300/h8300.md: Likewise.
+ * config/h8300/lib1funcs.asm: Likewise.
+
+2002-01-10 Dale Johannesen <dalej@apple.com>
+
+ PR optimization/5269
+ * unroll.c (precondition_loop_p): Make *increment be the correct
+ sign when n_iterations known, to avoid confusing caller.
+
+2002-01-10 Kazu Hirata <kazu@hxi.com>
+
+ * doc/extend.texi (deprecated): Fix a typo.
+
+Thu Jan 10 22:35:54 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * basic-block.h (update_br_prob_note): Declare.
+ * cfgcleanup.c (try_simplify_condjump): Call update_br_prob_note.
+ (try_forward_edges): Care negative frequencies and update note.
+ (outgoing_edges_match): Tweek conditional merging heuristics.
+ (try_crossjump_to_edge): use update_br_prob_note.
+ * cfglayout.c (fixup_reorder_chain): Likewise.
+ * cfrtl.c (update_br_prob_note): New.
+ * ifcvt.c (dead_or_predicable): Call update_br_prob_note.
+
+ * i386.c (ix86_decompose_address): Return -1 if address contains
+ shift.
+ (legitimate_address_p): Require ix86_decompose_address to return 1.
+
+ * gcse.c (hash_scan_set): Use CONSTANT_INSN_P.
+ (cprop_insn): Likewise.
+
+2002-01-10 Kazu Hirata <kazu@hxi.com>
+
+ * toplev.c: Fix formatting.
+ * tree.c: Likewise.
+ * tree-dump.c: Likewise.
+ * unroll.c: Likewise.
+ * unwind-dw2.c: Likewise.
+ * unwind-dw2-fde.c: Likewise.
+ * unwind-dw2-fde-glibc.c: Likewise.
+ * unwind-sjlj.c: Likewise.
+
+2002-01-10 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/invoke.texi: Document PDP-11 options.
+
+2002-01-10 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.h: Fix formatting.
+
+2002-01-10 Ira Ruben <ira@apple.com>
+
+ Add __attribute__ ((deprecated)).
+ * extend.texi: Document __attribute__ ((deprecated)).
+ * invoke.texi: Document -Wno-deprecated-declarations.
+ * testsuite/g++.dg/other/deprecated.C: New C++ test.
+ * testsuite/gcc.dg/deprecated.c: New C test.
+ * attribs.c (enum attrs): Declare handle_deprecated_attribute().
+ (c_common_attribute_table): Add "deprecated" entry.
+ (handle_deprecated_attribute): New function.
+ * c-decl.c (deprecated_states): New enum.
+ deprecated_state: State of "deprecated" handling.
+ (start_decl): Set deprecated_state based on attributes.
+ (grokdeclarator): Test for deprecated uses, propagate attribute.
+ * c-typeck.c (build_component_ref): Test for deprecated fields.
+ (build_external_ref): Test for deprecated primaries.
+ * diagnostic.c (warn_deprecated_use) New function to issue
+ warnings about __attribute__ ((depricated)) references.
+ * flags.h (warn_deprecated_decl): Extern declared for
+ -W[no-]deprecated-declarations option.
+ * print-tree.c (print_node): Show deprecated flag status.
+ * toplev.c (warn_deprecated_decl): Defined.
+ (W_options): Added "deprecated-declaration".
+ * toplev.h (warn_deprecated_use): Extern declared.
+ * tree.h (struct tree_common): Define deprecated_flag.
+ (TREE_DEPRECATED): New macro to access flag.
+ * cp/call.c (build_call): Test for deprecated calls.
+ * cp/class.c (add_implicitly_declared_members): Set global
+ flag to tell grokdeclarator to not issue deprecated warnings.
+ * cp/cp-tree.h: Add extern for adding_implicit_members.
+ * cp/decl.c (deprecated_states): New enum.
+ (start_decl): Set deprecated_state based on attributes.
+ (grokdeclarator): Test for deprecated uses, propagate attribute.
+ * cp/lex.c (do_identifier): Test for deprecated primaries.
+ * cp/typeck.c (build_component_ref): Test for deprecated fields.
+
+2002-01-10 Ira Ruben <ira@apple.com>
+
+ Fix to assign attributes to inline member functions.
+ * cp/decl.c (start_method): Handle attrlist.
+
+2002-01-10 Kazu Hirata <kazu@hxi.com>
+
+ * combine.c (expand_field_assignment): Use subreg_lsb().
+
+2002-01-10 David Edelsohn <edelsohn@gnu.org>
+
+ * alias.c (find_base_value): Add cases for HIGH, PRE_INC, PRE_DEC,
+ POST_INC, POST_DEC, PRE_MODIFY, and POST_MODIFY.
+ (find_base_term): Add cases for TRUNCATE, PRE_MODIFY, and POST_MODIFY.
+ Recurse for any operand of AND as long as constant is nonzero.
+
+2002-01-10 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md: Remove constraints from expanders.
+
+2002-01-10 Kazu Hirata <kazu@hxi.com>
+
+ * varasm.c: Fix formatting.
+ * varray.c: Likewise.
+ * vmsdbgout.c: Likewise.
+ * xcoffout.c: Likewise.
+
+Thu Jan 10 17:19:12 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgcleanup.c (try_forward_edges): Properly initialize nthreaded_edges;
+ update edge probabilities to match.
+
+2002-01-10 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * Makefile.in ($(docdir)/gccint.info, gccint.dvi): Add additional
+ dependencies.
+ * doc/languages.texi, doc/sourcebuild.texi: New files.
+ * doc/configfiles.texi: Make a subsubsection. Update.
+ * doc/configterms.texi: Add @node. Remove warning that this isn't
+ instructions for building GCC.
+ * doc/makefile.texi: Make a subsection.
+ * doc/gccint.texi: Update.
+
+Thu Jan 10 16:39:58 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * i386.md (sse_mov?fcc_const0_?): Fix constraints.
+
+Thu Jan 10 12:45:50 2002 Nicola Pero <n.pero@mi.flashnet.it>
+
+ * doc/cpp.texi: Document the __OBJC__ preprocessor macro.
+
+Thu Jan 10 11:19:18 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * optabs.c (expand_fix): Look for wider integer modes first.
+
+ * i386.md (mov?f): Avoid the fake const double trick for medium
+ memory model.
+ (min?f*/max?f*): Prohibit memory operands for i387 variant.
+ (fop_df_4): Disable for SSE compilation.
+
+2002-01-10 Graham Stott <grahams@redhat.com>
+
+ * dwarf2out.c (indirect_string_alloc, output_indirect_string):
+ Move prototype into DWARF2_DEBUGGING_INFO conditional block.
+
+2002-01-10 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.md (extendsidi2_fix): Penalize f/f alternative.
+
+2002-01-10 Richard Henderson <rth@redhat.com>
+
+ * regrename.c (find_oldest_value_reg): Fix typo in mode change check.
+ (copyprop_hardreg_forward_1): Likewise. Use mode_change_ok.
+
+2002-01-10 Kazu Hirata <kazu@hxi.com>
+
+ * combine.c (can_combine_p): Fix a comment typo.
+
+2002-01-09 Zack Weinberg <zack@codesourcery.com>
+
+ * Makefile.in (s-gencheck, s-options, s-specs): Handle an
+ empty list correctly. Change loop index $t to $f for
+ consistency with rest of Makefile.
+
+2002-01-08 Aldy Hernandez <aldyh@redhat.com>
+
+ * testuite/gcc.dg/altivec-4.c: Add test for mtvscr, dssall,
+ mfvscr, dss, lvsl, lvsr, dstt, dstst, dststt, dst.
+
+ * config/rs6000/rs6000.c (altivec_expand_builtin): Add support for
+ mtvscr, dssall, mfvscr, dss, lvsl, lvsr, dstt, dst, dstst, dststt.
+ (altivec_init_builtins): Same.
+ (altivec_expand_unop_builtin): Return NULL_RTX on error.
+ (altivec_expand_binop_builtin): Same.
+ (altivec_expand_ternop_builtin): Same.
+ (bdesc_dst): New.
+
+ * config/rs6000/rs6000.md ("altivec_mtvscr"): New.
+ ("altivec_vctuxs"): Fix typo.
+ ("altivec_vnmsubfp"): Same.
+ ("altivec_dssall"): New.
+ ("altivec_mfvscr"): New.
+ ("altivec_dss"): New.
+ ("altivec_lvsl"): New.
+ ("altivec_lvsr"): New.
+ ("altivec_dstt"): New.
+ ("altivec_dstst"): New.
+ ("altivec_dststt"): New.
+ ("altivec_dst"): New.
+
+ * config/rs6000/rs6000.h (rs6000_builtins): Add mtvscr, dssall,
+ mfvscr, dss, lvsl, lvsr, dstt, dstst, dststt, dst.
+
+2002-01-09 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.md (prologue_mcount): Remove lituse_jsr reloc.
+
+2002-01-10 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.c (mmix_asm_identify_gcc): Remove unused
+ function.
+ * config/mmix/mmix-protos.h (mmix_asm_identify_gcc): Don't
+ prototype.
+ * config/mmix/mmix.h (ASM_IDENTIFY_GCC): Remove unused macro.
+
+2002-01-09 Kazu Hirata <kazu@hxi.com>
+
+ * read-rtl.c: Fix formatting.
+ * real.c: Likewise.
+ * regclass.c: Likewise.
+ * regrename.c: Likewise.
+ * reg-stack.c: Likewise.
+ * reload1.c: Likewise.
+ * reload.c: Likewise.
+ * rtl.c: Likewise.
+
+2002-01-09 Kazu Hirata <kazu@hxi.com>
+
+ * rtlanal.c (find_reg_fusage): Use XEXP instead of SET_DEST
+ to extract items in the expr_list chain.
+
+2002-01-09 Richard Henderson <rth@redhat.com>
+
+ * config/vax/vax.c (vax_rtx_cost): Never abort.
+
+ * config/vax/vax.h (REAL_ARITHMETIC): Define.
+
+2002-01-09 Jan Hubicka <jh@suse.cz>
+
+ * gcse.c (cprop_jump): Delete insn if simplified jump is no-op.
+
+2002-01-09 Richard Henderson <rth@redhat.com>
+
+ * config/arm/arm.c (arm_gen_constant): Use trunc_int_for_mode.
+ Unify code from various alternatives.
+
+2002-01-09 Richard Henderson <rth@redhat.com>
+
+ * regrename.c (copy_value): Ignore the copy if the source register
+ is present in the value chain with a narrower mode.
+
+2002-01-09 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+
+ * real.c (c4xtoe, toc4x): Do some special conversion on long doubles
+ for the c4x target. Also improve layout.
+
+2002-01-09 Richard Henderson <rth@redhat.com>
+
+ * config/m32r/m32r.c (move_src_operand): Fix 32-bit int test.
+ * config/m32r/m32r.md (and ior xor splitters): Swap operands
+ to match insn patterns.
+
+2002-01-09 Richard Henderson <rth@redhat.com>
+
+ * regrename.c (find_oldest_value_reg): Use gen_rtx_raw_REG.
+ (copyprop_hardreg_forward_1): Likewise.
+
+2002-01-09 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.md (decrement_and_branch_until_zero): Change predicate for
+ operand 0 from register_operand to reg_or_nonsymb_mem_operand.
+
+2002-01-09 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
+
+ * ginclude/stddef.h: Define _BSD_WCHAR_T_DEFINED_ if _BSD_WCHAR_T_
+ gets undefined. For Darwin.
+
+2002-01-09 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
+
+ * config/c4x/c4x.h: Use PUSH_ARGS and PUSH_ROUNDING for stack passing.
+
+2002-01-09 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x/md: Remove extraneous constraints from define_splits.
+
+2002-01-08 Richard Henderson <rth@redhat.com>
+
+ * regrename.c (copy_value): Ignore overlapping copies.
+
+2002-01-08 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (alpha_split_conditional_move): Call copy_rtx
+ as needed to avoid shared structure.
+
+2002-01-08 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (get_shift_alg): Fix 15-bit LSHIFTRT on
+ H8/300H and H8S.
+
+2002-01-08 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/tm.texi (EASY_DIV_EXPR, IMPLICIT_FIX_EXPR,
+ LONGJMP_RESTORE_FROM_STACK, MAX_INT_TYPE_SIZE): Remove
+ documentation of obsolete macros.
+ * system.h: Poison these macros.
+ * config/1750a/1750a.h, config/a29k/a29k.h, config/alpha/alpha.h,
+ config/arc/arc.h, config/arm/arm.h, config/avr/avr.h,
+ config/c4x/c4x.h, config/clipper/clipper.h,
+ config/convex/convex.h, config/cris/cris.h, config/d30v/d30v.h,
+ config/dsp16xx/dsp16xx.h, config/elxsi/elxsi.h,
+ config/fr30/fr30.h, config/h8300/h8300.h, config/i370/i370.h,
+ config/i386/i386.h, config/i860/i860.h, config/i960/i960.h,
+ config/ia64/ia64.h, config/m32r/m32r.h, config/m68hc11/m68hc11.h,
+ config/m68k/m68k.h, config/m88k/m88k.h, config/mcore/mcore.h,
+ config/mips/mips.h, config/mmix/mmix.h, config/mn10200/mn10200.h,
+ config/mn10300/mn10300.h, config/ns32k/ns32k.h, config/pa/pa.h,
+ config/pdp11/pdp11.h, config/pj/pj.h, config/romp/romp.h,
+ config/rs6000/rs6000.h, config/s390/s390.h, config/sh/sh.h,
+ config/sparc/sparc.h, config/stormy16/stormy16.h,
+ config/v850/v850.h, config/vax/vax.h, config/we32k/we32k.h: Remove
+ definitions and commented out definitions of obsolete macros.
+ * config/mips/iris5.h (MAX_WCHAR_TYPE_SIZE): Don't define in terms
+ of MAX_INT_TYPE_SIZE.
+
+2002-01-08 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/s390.c (s390_preferred_reload_class): Never
+ return ADDR_REGS if it isn't a subset of the given class.
+ * config/s390/s390.h (REGISTER_MOVE_COST): Penalize not just
+ FP_REGS, but all superclasses as well.
+
+ * config/s390/s390.c (s390_function_profiler): Fix thinko.
+
+ * config/s390/s390.md (cmpdi_ccu_mem, cmpsi_ccu_mem,
+ cmphi_ccu_mem, cmpqi_ccu_mem): First operand of compare
+ must not be a const_int.
+
+2002-01-08 Richard Henderson <rth@redhat.com>
+
+ * Makefile.in (toplev.o): Depend on options.h.
+ (gcc.o): Depend on specs.h.
+
+2002-01-08 Jakub Jelinek <jakub@redhat.com>
+
+ * expr.c (store_expr): Convert VOIDmode constants back to target's
+ mode.
+
+2002-01-08 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * doc/invoke.texi: Markup gcc as @command. Refer to
+ http://gcc.gnu.org/onlinedocs/gcc/Contributors.html instead
+ of http://gcc.gnu.org/thanks.html.
+
+2002-01-08 Dale Johannesen <dalej@apple.com>
+
+ * config/rs6000/rs6000.md: Add missing int register
+ target case to movdf_low.
+
+2002-01-08 Zack Weinberg <zack@codesourcery.com>
+
+ * Makefile.in (cs-tconfig.h): Don't depend on $(CONFIG_H) or
+ except.h. Remove commands to define USING_SJLJ_EXCEPTIONS.
+ (cppinit.o): Depend on except.h.
+ (gencheck.h, options.h, specs.h, s-gencheck, s-options,
+ s-specs): New rules.
+
+ * configure.in: Don't AC_DEFINE_UNQUOTED PACKAGE or VERSION.
+ Don't create specs.h/options.h/gencheck.h here. Remove
+ unnecessary variable settings from last argument of AC_OUTPUT.
+ * config.in, configure: Regenerate.
+ * intl.c: Hardcode package name as "gcc".
+
+ * cppinit.c: Include except.h.
+ (builtin_array): Define __USING_SJLJ_EXCEPTIONS__ when
+ appropriate.
+ * unwind-dw2.c, unwind-sjlj.c, config/ia64/unwind-ia64.c:
+ Use #if(n)def __USING_SJLJ_EXCEPTIONS, not #if
+ (!)USING_SJLJ_EXCEPTIONS.
+ * doc/cpp.texi: Document __USING_SJLJ_EXCEPTIONS__.
+
+2002-01-08 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/tm.texi (ASM_OUTPUT_EH_REGION_BEG, ASM_OUTPUT_EH_REGION_END,
+ ASM_OUTPUT_LABELREF_AS_INT, DOESNT_NEED_UNWINDER, EH_TABLE_LOOKUP,
+ OBJC_SELECTORS_WITHOUT_LABELS, OMIT_EH_TABLE): Remove
+ documentation of obsolete macros.
+ * system.h: Poison these macros.
+ * config/d30v/d30v.h, config/ns32k/encore.h,
+ config/stormy16/stormy16.h: Remove definitions and commented out
+ definitions of obsolete macros.
+
+Tue Jan 8 15:56:41 2002 Nicola Pero <nicola@brainstorm.co.uk>
+
+ * objc/objc-act.c (handle_class_ref): Mark the declaration of
+ %sobjc_class_ref_%s as used - to prevent unwanted compiler
+ warnings.
+
+2002-01-08 Ulrich Weigand <uweigand@de.ibm.com>
+
+ * config/s390/linux.h (ASM_OUTPUT_LABELREF): Remove.
+ * config/s390/s390.c (s390_emit_epilog): Add REG_FRAME_RELATED_EXPR
+ to insn adjusting stack/frame pointer.
+ * config/s390/s390.md (reload_la_64, reload_la_31): Do not
+ accept operands that cause the insn to be non-splittable.
+
+2002-01-08 Graham Stott <grahams@redhat.com>
+
+ * c-tree.h (C_TYPE_FIELDS_READONLY): Uppercase macro parameter.
+ (C_TYPE_FIELDS_VOLATILE): Likewise.
+ (C_TYPE_BEING_DEFINED): Likewise.
+ (C_IS_RESERVED_WORD): Likewise.
+ (C_TYPE_VARIABLE_SIZE): Likewise.
+ (C_DECL_VARIABLE_SIZE): Likewise.
+ (C_MISSING_PROTOTYPE_WARNED): Likewise.
+ (C_SET_EXP_ORIGINAL_CODE): Likewise.
+ (C_TYPEDEF_EXPLICITLY_SIGNED): Uppercase macro parameter and remove
+ parenthesis.
+ (C_DECL_ANTICIPATED): Likewise.
+ (c_build_type_variant): Add parenthesis.
+
+2002-01-08 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * gcc.c (option_map): Remove --version.
+ (process_command): Handle -fversion following the GNU Coding
+ Standards. Partially addresses PR other/704.
+
+2002-01-08 Graham Stott <grahams@redhat.com>
+
+ * combine.c (combine_instructions): Fix typo.
+
+2002-01-08 Graham Stott <grahams@redhat.com>
+
+ * debug.h: Use "tree" and "rtx" throughout.
+
+ * debug.c: Likewise.
+
+2002-01-08 Nick Clifton <nickc@cambridge.redhat.com>
+
+ * dbxout.c (dbxout_symbol_location): If a symbol ref is in the
+ constant pool, use the pool's version of the symbol instead.
+
+2002-01-07 Richard Henderson <rth@redhat.com>
+
+ * regrename.c (find_oldest_value_reg): Ignore the value chain if
+ the original register was copied in a mode with a fewer number of
+ hard registers than the desired mode.
+ (copyprop_hardreg_forward_1): Likewise.
+ (debug_value_data): Fix loop test.
+ * toplev.c (parse_options_and_default_flags): Reenable
+ -fcprop-registers at -O1.
+
+2002-01-07 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c (bdesc_2arg): Add altivec predicates.
+ (altivec_init_builtins): New node v4si_ftype_v16qi_v16qi.
+
+ * config/rs6000/rs6000.h (rs6000_builtins): Add enums for altivec
+ predicates.
+
+ * config/rs6000/rs6000.md: Add altivec predicate patterns.
+
+2002-01-07 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * pa.c (FUNC_BEGIN_PROLOG_LABEL, current_function_number): Define.
+ (pa_output_function_prologue): Output local label at the beginning of
+ the prologue when profiling.
+ (hppa_profile_hook): Use the local label rather than the function label.
+ * pa.h (PROFILE_BEFORE_PROLOGUE): Define.
+
+2002-01-07 Aldy Hernandez <aldyh@redhat.com>
+
+ * config/rs6000/rs6000.c (print_operand): Remove extra space.
+ (altivec_expand_unop_builtin): Fix thinko.
+ (altivec_expand_binop_builtin): Same.
+ (altivec_expand_ternop_builtin): Same.
+ (altivec_expand_builtin): Same.
+
+2002-01-07 Richard Henderson <rth@redhat.com>
+
+ * config/rs6000/xcoff.h (ASM_FILE_START): Reverted to profile_flag.
+
+2002-01-07 Jason Merrill <jason@redhat.com>
+
+ * unwind-dw2.c (execute_cfa_program): Use < again.
+
+2002-01-07 Jakub Jelinek <jakub@redhat.com>
+
+ * predict.c (combine_predictions_for_insn): Avoid division by zero.
+
+2002-01-07 Jakub Jelinek <jakub@redhat.com>
+
+ * simplify-rtx.c (simplify_plus_minus): Bump n_ops for NOT.
+ Don't allow -1 - x -> ~x simplifications in the first pass.
+
+2002-01-07 Aldy Hernandez <aldyh@redhat.com>
+
+ * rs6000.c (altivec_expand_ternop_builtin): Don't die on invalid
+ arguments.
+ (altivec_expand_binop_builtin): Same.
+ (altivec_expand_unop_builtin): Same.
+ (print_operand): Fix typo.
+ (bdesc_1arg): Add vupk* variants.
+
+ * rs6000.h (rs6000_builtins): Add vupk* enums.
+
+ * rs6000.md: Add altivec_vupk* variants.
+
+2002-01-07 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * doc/gcc.texi, doc/gccint.texi, doc/cppinternals.texi,
+ doc/install.texi, doc/invoke.texi, doc/rtl.texi: Update copyright
+ and last update dates.
+
+2002-01-07 Janis Johnson <janis187@us.ibm.com>
+
+ * doc/rtl.texi (Flags): Clean up documentation of RTL flags
+
+2002-01-07 Marek Michalkiewicz <marekm@amelek.gda.pl>
+
+ * config/avr/avr.c (avr_mcu_types): Add new MCU types.
+ * config/avr/avr.h (CPP_SPEC): Likewise.
+ (LINK_SPEC): Likewise.
+ (CRT_BINUTILS_SPECS): Likewise.
+ * config/avr/t-avr (MULTILIB_MATCHES): Likewise.
+ * doc/invoke.texi (AVR Options): Document them.
+
+Mon Jan 7 11:59:34 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * unroll.c (copy_loop_body): Always properly update JUMP_LABEL and
+ LABEL_NUSES.
+
+2002-01-07 Graham Stott <grahams@redhat.com>
+
+ * config/i386/i386.h: Update copyright date.
+ (HALF_PIC_PTR): Add parenthesis.
+ (OPTIMIZATION_OPTIONS): Whitespace, add parenthesis and wrap.
+ (CONSTANT_ALIGNMENT): Add parenthesis.
+ (DATA_ALIGNMENT): Likewise.
+ (LOCAL_ALIGNMENT): Likewise.
+ (FUNCTION_ARG_BOUNDARY): Whitespace, add parenthesis and wrap.
+ (IS_STACK_MODE): Uppercase macro parameter, add parenthesis and wrap.
+ (CONDITIONAL_REGISTER_USAGE): Wrap in do {...} while (0).
+ (HARD_REGNO_NREGS): Add paranethesis.
+ (VALID_SSE_REG_MODE): Whitespace.
+ (VALID_MMX_REG_MODE): Whitespace.
+ (VALID_FP_MODE_P): Uppercase macros parameter and whitespace.
+ (ix86_hard_regno_mode_ok): Add parenthesis.
+ (HARD_REGNO_CALLER_SAVE_MODE): Whitespace.
+ (RETURN_IN_MEMORY): Whitespace.
+ (N_REG_CLASSES): Add parenthesis.
+ (INTEGER_CLASS_P): Add parenthesis and wrap.
+ (FLOAT_CLASS_P): Likewise.
+ (SSE_CLASS_P): Likewise.
+ (MMX_CLASS_P): Likewise.
+ (MAYBE_INTEGER_CLASS_P): Likewise.
+ (MAYBE_FLOAT_CLASS_P): Likewise.
+ (MAYBE_SSE_CLASS_P): Likewise.
+ (MAYBE_MMX_CLASS_P): Likewise.
+ (Q_CLASS_P): Likewise.
+ (GENERAL_REGNO_P): Uppercase macro parameter.
+ (REX_INT_REGNO_P): Uppercase macro parameter and wrap.
+ (FP_REGNO_P): Likewise.
+ (ANY_FP_REGNO_P): Uppercase macro parameter.
+ (SSE_REGNO_P): Likewise.
+ (SSE_REGNO): Likewise.
+ (SSE_REG_P): Likewise.
+ (SSE_FLOAT_MODE_P): Likewise.
+ (MMX_REGNO_P): Likewise.
+ (MMX_REG_P):Likewise.
+ (STACK_REG_P): Likewise.
+ (NON_STACK_REG_P): Likewise.
+ (STACK_TOP_P): Likewise.
+ (CONVERT_HARD_REGISTER_TO_SSA_P): Add parenthesis.
+ (PREFERRED_RELOAD_CLASS): Add parenthesis and whitespace.
+ (SECONDARY_MEMORY_NEEDED): Likewise.
+ (SECONDARY_OUTPUT_RELOAD_CLASS): Whitespace.
+ (MD_ASM_CLOBBERS): Whitespace and wrap.
+ (MUST_PASS_IN_STACK): Whitespace and wrap.
+ (RETURN_POPS_ARGS): Add parenthesis.
+ (INIT_CUMULATIVE_ARGS): Likewise.
+ (FUNCTION_ARG): Likewise.
+ (FUNCTION_OK_FOR_SIBCALL): Add parenthesis and whitespace.
+ (SETUP_INCOMING_VARARGS): Likewise.
+ (BUILD_VA_LIST_TYPE): Add parenthesis.
+ (EXPAND_BUILTIN_VA_START): Uppercase macro paremeters and add
+ parenthsis.
+ (EXPAND_BUILTIN_VA_ARG): Likewise.
+ (FUNCTION_PROFILER): Wrap in do { ... } while (0) and add parenthesis.
+ (INITIALIZE_TRAMPOLINE): Add parenthesis.
+ (INITIAL_ELIMINATION_OFFSET): Likewise.
+ (REGNO_OK_FOR_INDEX_P): Add parenthesis.
+ (REGNO_OK_FOR_BASE_P): Likewise.
+ (REGNO_OK_FOR_SIREG_P): Add parenthesis and wrap.
+ (REGNO_OK_FOR_DIREG_P): Likewise.
+ (REG_OK_FOR_INDEX_P): Whitespace.
+ (REG_OK_FOR_BASE_P): Whitespace.
+ (GO_IF_LEGITIMATE_ADDRESS): Wrap in do { ... } while (0) and add
+ parenthesis.
+ (FIND_BASE_TERM): Fix typo.
+ (LEGITIMIZE_ADDRESS): Wrap in { .. } while (0) and add parenthesis.
+ (REWRITE_ADDRESS): Uppercase macro parameter and whitespace.
+ (SYMBOLIC_CONST; Whitespace.
+ (GO_IF_MODE_DEPENDENT_ADDRESS):Wrap in { .. } while (0) and wrap.
+ (ENCODE_SECTION_INFO): Whitespace.
+ (FINALIZE_PIC): Remove do { ... } while (0).
+ (PROMOTE_MODE): Wrap in do { ... } while (0).
+ (CONST_COSTS): Whitespace.
+ (RTX_COSTS): Add paramethesis, whitespace and wrap.
+ (REGISTER_MOVE_COST): Add parenthesis.
+ (MEMORY_MOVE_COST): Likewise.
+ (EXTRA_CC_MODES): Whitespace.
+ (SELECT_CC_MODE): Add parenthesis and whitespace.
+ (DBX_REGISTER_NUMBER): Uppercase macro parameter and add parenthsis.
+ (ASM_PREFERRED_EH_DATA_FORMAT): Add parenthesis and whitespace.
+ (ASM_OUTPUT_LABEL): Add paramethesis.
+ (ASM_OUTPUT_REG_PUSH): Add parenthesis and whitespace.
+ (ASM_OUTPUT_REG_POP): Likewise.
+ (ASM_OUTPUT_ADDR_VEC_ELT): Add parenthesis.
+ (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
+
+ * config/i386/i386.c: Update copyright.
+ (CHECK_STACK_LIMIT): Add parenthesis.
+ (AT_BP): Uppercase macro parameter.
+ (x86_64_int_parameter_registers): Constify.
+ (x86_64_int_return_registers): Likewise.
+ (ix86_compare_op0): Use rtx.
+ (construct_container): Constify INTREG parameter.
+ (function_arg): Use rtx.
+
+ * diagnostic.h: Update copyright date.
+ (output_buffer_state): Add parenthesis.
+ (output_buffer_format_args): Likewise.
+
+ * combine.c (combine_instructions): Replace XEXP (links, 0)
+ with link.
+
+2002-01-06 H.J. Lu <hjl@gnu.org>
+
+ * cfgcleanup.c (thread_jump): Fix 2 typos.
+
+2002-01-06 Aldy Hernandez <aldyh@redhat.com>
+
+ * config.gcc: Add support for --enable-altivec.
+
+2002-01-06 Craig Rodrigues <rodrigc@gcc.gnu.org>
+
+ * emit-rtl.c (gen_highpart): Add check for NULL_RTX.
+
+2002-01-06 Jakub Jelinek <jakub@redhat.com>
+
+ * objc/objc-act.c (handle_impent): Use assemble_variable to emit
+ __objc_class_name_*.
+
+2002-01-06 Craig Rodrigues <rodrigc@gcc.gnu.org>
+
+ * doc/install.texi (sparcv9-*-solaris2*): Add documentation.
+
+2002-01-06 Richard Henderson <rth@redhat.com>
+
+ * reorg.c (emit_delay_sequence): Remove death notes, not merely
+ nop them out. Increment label reference count for REG_LABEL.
+ (fill_slots_from_thread): Frob label reference count around
+ delete_related_insns.
+
+2002-01-05 Richard Henderson <rth@redhat.com>
+
+ * cfgcleanup.c (try_forward_edges): Detect infinite loops while
+ jump threading.
+
+2002-01-05 Richard Henderson <rth@redhat.com>
+
+ * c-decl.c (c_expand_body): Don't call outlining_inline_function.
+ * integrate.c (output_inline_function): Likewise.
+ * toplev.c (rest_of_compilation): Do it here instead. Move call
+ to remove_unnecessary_notes after emitting abstract instance.
+ Force an emitted nested function to have its parent emited as well.
+ * dwarf2out.c (loc_descriptor_from_tree): Read mode after checking
+ for null.
+ (rtl_for_decl_location): Do not look at reload data structures
+ before reload has run.
+
+2002-01-05 Kazu Hirata <kazu@hxi.com>
+
+ * cse.c: Fix formatting.
+ * dwarf2asm.c: Likewise.
+ * dwarf2out.c: Likewise.
+ * explow.c: Likewise.
+ * expmed.c: Likewise.
+ * function.c: Likewise.
+ * gcov.c: Likewise.
+ * gencheck.c: Likewise.
+ * genrecog.c: Likewise.
+ * ggc-common.c: Likewise.
+ * ggc-page.c: Likewise.
+ * global.c: Likewise.
+
+2002-01-05 Kazu Hirata <kazu@hxi.com>
+
+ * combine.c: Fix formatting.
+
+2002-01-05 Craig Rodrigues <crodrigu@bbn.com>
+
+ PR middle-end/1557
+ * config/ia64/ia64.h (RENAME_EXTENDED_BLOCKS): Remove.
+
+2002-01-05 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.h (TARGET_POWERPC): For IN_LIBGCC2, define
+ as 1 for __powerpc64__ as well.
+
+ * config/rs6000/t-aix43 (T_ADAFLAGS): Define.
+
+ * alias.c (find_base_value, PLUS/MINUS): If we found a base,
+ return it.
+
+2002-01-05 Daniel Berlin <dan@dberlin.org>
+
+ * lcm.c: Revert change, due to performance regression it causes on
+ SPEC because it's slightly more conservative (sigh, I hate
+ edge-based LCM).
+
+Sat Jan 5 11:52:05 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgcleanup.c (try_forward_edges): Allow multiple jump threading.
+
+2002-01-05 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * doc/cppinternals.texi: Update.
+
+2002-01-05 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * doc/invoke.texi (Option Summary) <MMIX Options>: Document
+ -mbranch-predict, -mreg-stack-fill-bug-workaround and their
+ negatives.
+ (MMIX Options): Ditto. Fix item/itemx typo for -mno-zero-extend.
+ * config/mmix/mmix.c (mmix_target_asm_function_prologue): Rework
+ kludge for pre-october-14th mmix versions to handle new-found bug
+ with PUSHJ/PUSHGO and the register stack.
+ * config/mmix/mmix.h (struct machine_function): Rename member
+ has_call_value_without_parameters to has_call_without_parameters.
+ All referers changed.
+ (TARGET_MASK_REG_STACK_FILL_BUG, TARGET_DEFAULT
+ TARGET_MASK_BRANCH_PREDICT): New macros.
+ (TARGET_SWITCHES): New options -mreg-stack-fill-bug-workaround,
+ -mno-reg-stack-fill-bug-workaround.
+ * config/mmix/mmix.md ("call"): Set struct machine member
+ has_call_without_parameters.
+
+Sat Jan 5 02:20:22 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgcleanup.c (thread_jump): Fix handling of reversed branches.
+
+Sat Jan 5 01:35:29 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * cfgcleanup.c: Include tm_p.h
+ (mark_effect): Fix handling of hard register; fix handling of SET
+
+2002-01-04 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.md (anonymous patterns): Check that
+ operands are registers before using REGNO on them.
+
+2002-01-03 Roland McGrath <roland@frob.com>
+
+ * doc/invoke.texi (RS/6000 and PowerPC Options): Add -mcall-gnu.
+
+2002-01-04 Jakub Jelinek <jakub@redhat.com>
+
+ * tree.h (expand_expr_stmt_value): Add maybe_last argument.
+ * c-common.h (genrtl_expr_stmt_value): Likewise.
+ * stmt.c (expand_expr_stmt): Pass 1 as maybe_last.
+ (expand_expr_stmt_value): Add maybe_last argument.
+ Don't warn about statement with no effect if it is the last statement
+ in expression statement.
+ * c-semantics.c (genrtl_expr_stmt): Pass 1 as maybe_last.
+ (genrtl_expr_stmt_value): Add maybe_last argument, pass it down to
+ expand_expr_stmt_value.
+ (expand_stmt) [EXPR_STMT]: Pass 1 as maybe_last to
+ genrtl_expr_stmt_value if t is the last EXPR_STMT in its scope.
+ * expr.c (expand_expr) [LABELED_BLOCK_EXPR, LOOP_EXPR]: Pass 1
+ as maybe_last to expand_expr_stmt_value.
+
+Fri Jan 4 11:45:05 2002 Jeffrey A Law (law@redhat.com)
+
+ * c-common.c (c_expand_start_cond): Expect the IF_STMT node to
+ be passed in, do not build it.
+ (c_begin_if_stmt): New function.
+ (c_begin_while_stmt, c_finish_while_stmt_cond): Likewise.
+ * c-common.h (c_expand_start_cond): Update prototype.
+ (c_begin_if_stmt): Prototype new function.
+ (c_begin_while_stmt, c_finish_while_stmt_cond): Likewise.
+ * c-parse.in (if_prefix): Use c_begin_if_stmt,
+ c_begin_while_stmt and c_finish_while_stmt_cond.
+
+2002-01-04 William Cohen <wcohen@redhat.com>
+
+ * config/pa/elf.h (ASM_FILE_START): Reverted to profile_flag.
+ * config/pa/pa-linux.h (ASM_FILE_START): Likewise.
+ * config/pa/pa64-hpux.h (ASM_FILE_START): Likewise.
+ * config/pa/som.h (ASM_FILE_START): Likewise.
+
+2002-01-04 Daniel Berlin <dan@cgsoftware.com>
+
+ * lcm.c: Include df.h.
+ Add available_transfer_function prototype.
+ (compute_available): Rework to use iterative dataflow framework.
+ (struct bb_info): s/bb_info/lcm_bb_info/g to avoid conflict
+ with bb_info in df.h
+ (available_transfer_function): New function.
+
+ * Makefile.in (lcm.o): add df.h to dependencies.
+
+2002-01-04 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (some_operand): Accept HIGH.
+ (input_operand): Likewise; accept simple references to globals.
+ (alpha_const_ok_for_letter_p): New, outlined from alpha.h.
+ (alpha_const_double_ok_for_letter_p): Likewise.
+ (alpha_extra_constraint): Likewise.
+ (alpha_preferred_reload_class): Likewise. Do not force
+ symbolic constants to memory.
+ (alpha_legitimate_address_p): Accept simple references
+ to small_symbolic_operand.
+ (alpha_legitimize_address): New arg scratch. Be prepared to be
+ called when no_new_pseudos. Emit simple symbolic references.
+ Split integers into low, high, and rest.
+ (alpha_expand_mov): Use alpha_legitimize_address.
+ (some_small_symbolic_mem_operand): New.
+ (split_small_symbolic_mem_operand): New.
+ * config/alpha/alpha-protos.h: Update.
+ * config/alpha/alpha.h (CONST_OK_FOR_LETTER_P): Out-line.
+ (CONST_DOUBLE_OK_FOR_LETTER_P): Likewise.
+ (EXTRA_CONSTRAINT): Likewise.
+ (PREFERRED_RELOAD_CLASS): Likewise.
+ (LEGITIMIZE_ADDRESS): Update for alpha_legitimize_address change.
+ (PREDICATE_CODES): Update.
+ * config/alpha/alpha.md: New post-reload splitters to convert
+ simplfied symbolic operands to the form that references $29.
+ (divide expanders): Use emit_move_insn, not gen_movdi_er_high_g.
+ (movdi_er_nofix, movdi_er_fix): Accept any symbolic operand.
+
+2002-01-03 Richard Henderson <rth@redhat.com>
+
+ * local-alloc.c (function_invariant_p): Update commentary.
+
+2002-01-04 H.J. Lu <hjl@gnu.org>
+
+ * toplev.c (rest_of_compilation): Fix a typo when calling
+ cleanup_cfg.
+
+2002-01-03 Kazu Hirata <kazu@hxi.com>
+
+ * c-common.c: Fix formatting.
+ * diagnostic.c: Likewise.
+ * doloop.c: Likewise.
+ * dwarf2out.c: Likewise.
+
+2002-01-03 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/h8300.c (output_logical_op): Use 'not.w' instead
+ of 'neg.w' when xoring with 0x0000ffff or 0xffff0000.
+
+2002-01-03 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cpperror.c: Update comments and copyright.
+ * cppexp.c, cppfiles.c, cpphash.c, cpphash.h, cppinit.c,
+ cpplex.c, cpplib.c, cpplib.h, cppmacro.c, cppmain.c: Similarly.
+
+2002-01-03 John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+ * collect2.c (main): Use strcmp when testing for "-shared".
+
+2002-01-03 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cppmacro.c: Don't include intl.h. Update comments.
+ (new_number_token): Allocate enough buffer for 64-bit unsigned
+ integers; update prototype.
+ * cppmain.c: Update comments.
+
+2002-01-03 William Cohen <wcohen@redhat.com>
+
+ * function.h (struct function): Add profile.
+ (current_function_profile): New.
+ doc/extend.texi: Update documentation.
+ * final.c (final_start_function): Use current_function_profile
+ instead of profile_flag.
+ (profile_after_prologue): Likewise.
+ * function.c (expand_function_start): Likewise.
+ (expand_function_start): Likewise.
+ * config/alpha/alpha.c (direct_call_operand):
+ (alpha_does_function_need_gp): Likewise.
+ (alpha_expand_prologue): Likewise.
+ * config/arm/arm.c (arm_expand_prologue): Likewise.
+ thumb_expand_prologue: Likewise.
+ * config/d30v/d30v.c (d30v_stack_info): Likewise.
+ * config/fr30/fr30.c (MUST_SAVE_RETURN_POINTER): Likewise.
+ (fr30_expand_prologue): Likewise.
+ * config/i386/cygwin.h (SUBTARGET_PROLOGUE): Likewise.
+ * config/i386/i386.c (ix86_osf_output_function_prologue): Likewise.
+ * config/i386/i386.h (FINALIZE_PIC): Likewise.
+ * config/i386/win32.h (SUBTARGET_PROLOGUE): Likewise.
+ * config/i960/i960.c (i960_output_function_prologue): Likewise.
+ * config/ia64/ia64.c (ia64_compute_frame_size): Likewise.
+ * config/m32r/m32r.c (MUST_SAVE_RETURN_ADDR): Likewise.
+ (m32r_expand_prologue): Likewise.
+ * config/m88k/m88k.c (m88k_layout_frame): Likewise.
+ (m88k_expand_prologue): Likewise.
+ * config/m88k/m88k.h (ADJUST_INSN_LENGTH): Likewise.
+ * config/mips/mips.c (compute_frame_size): Likewise.
+ (mips_expand_prologue): Likewise.
+ (mips_can_use_return_insn): Likewise.
+ * config/pa/elf.h (ASM_FILE_START): Likewise.
+ * config/pa/pa-linux.h (ASM_FILE_START): Likewise.
+ * config/pa/pa64-hpux.h (ASM_FILE_START): Likewise.
+ * config/pa/som.h (ASM_FILE_START): Likewise.
+ * config/romp/romp.c (romp_using_r14): Likewise.
+ * config/rs6000/rs6000.c (first_reg_to_save): Likewise.
+ (rs6000_stack_info): Likewise.
+ * config/rs6000/sysv4.h (ASM_DECLARE_FUNCTION_NAME): Likewise.
+ * config/rs6000/xcoff.h (ASM_FILE_START): Likewise.
+ * config/v850/v850.c (compute_register_save_size): Likewise.
+
+2002-01-03 Jakub Jelinek <jakub@redhat.com>
+
+ * simplify-rtx.c (simplify_binary_operation) [DIV]: If
+ gen_lowpart_common fails, use gen_lowpart_SUBREG.
+
+2002-01-03 Turly O'Connor <turly@apple.com>
+
+ * darwin.c (machopic_output_possible_stub_label): Don't generate
+ stub routines for pseudo-stubs which we've just defined.
+
+2002-01-03 Kazu Hirata <kazu@hxi.com>
+
+ * builtins.c: Fix formatting.
+ * c-typeck.c: Likewise.
+ * combine.c: Likewise.
+ * expr.c: Likewise.
+ * loop.c: Likewise.
+
+2002-01-03 Andreas Schwab <schwab@suse.de>
+
+ * cppfiles.c (_cpp_pop_file_buffer): Change return type to bool
+ and return true if _cpp_push_next_buffer pushed a new include
+ file.
+ * cpplib.c (_cpp_pop_buffer): Only call obstack_free if
+ _cpp_pop_file_buffer did not push a new file.
+ * cpphash.h (_cpp_pop_file_buffer): Update declaration.
+
+2002-01-02 Eric Christopher <echristo@redhat.com>
+
+ * final.c (final_scan_insn): Change 0 -> NULL_RTX in
+ FIND_REG_INC_NOTE call. Update copyright.
+ * loop.c (canonicalize_condition): Ditto.
+ * reorg.c (delete_scheduled_jump): Ditto.
+
+2002-01-03 Kazu Hirata <kazu@hxi.com>
+
+ * gcse.c: Fix formatting.
+
+2002-01-03 Graham Stott <grahams@redhat.com>
+
+ * mkconfig.sh: Output to config.h, hconfig.h and tconfig.h
+ forward defs for struct tags rtx_def, union_tree, rtvec_def
+ also output corresponding typedefs for rtx, tree, and rtvec.
+
+ * system.h: Move forward defs for struct tags rtx_def, union_tree,
+ rtvec_def along with corresponding typedefs for rtx, tree, and
+ rtvec to config.h, hconfig.h, tconfig.h.
+
+2002-01-03 Graham Stott <grahams@redhat.com>
+
+ * tree.h: Update copyright date.
+ (IS_EXPR_CODE_CLASS): Add parenthesis.
+ (TREE_SET_CODE): Add whitespace.
+ (TREE_CHECK): Add parenthesis.
+ (TREE_CLASS_CODE): Add parenthesis and wrap long line.
+ (CST_OR_CONSTRUCTOR_CHECK):
+ (EXPR_CHECK): Add parenthis, whitespace and wrap line.
+ (TREE_SYMBOL_REFERENCED): Whitespace.
+ (INT_CST_LT): Likewise.
+ (INT_CST_LT_UNSIGNED): Likewise.
+ (tree_real_cst): Unwrap comment.
+ (tree_string): Likewise.
+ (tree_complex): Likewise.
+ (IDENTIFIER_POINTER): correct cast.
+ (SAVE_EXPR_CONTEXT): Whitespace.
+ (EXPR_WFL_FILENAME_NODE): Likewise.
+ (EXPR_WFL_FILENAME): Remove parenthesis.
+ (DECL_ORIGIN): Add parenthesis.
+ (DECL_FROM_INLINE): Use NULL_TREE.
+ (build_int_2): Whitespace.
+ (build_type_variant): Add parenthesis.
+
+ * gcc/jcf-parse.c: Update copyright date.
+ (yyparse): Constify resource_filename.
+
+2002-01-03 Graham Stott <grahams@redhat.com>
+
+ * rtl.h: Update copyright date.
+ (RTL_CHECK1): Wrap long line.
+ (RTL_CHECK2): Likewise.
+ (RTL_CHECKC1): Wrap long line and whitespace.
+ (RTL_CHECKC2): Likewise.
+ (XWINT): Whitespace.
+ (XINT): Likewise.
+ (XSTR): Likewise.
+ (XEXP): Likewise.
+ (XVEC): Likewise.
+ (XMODE): Likewise.
+ (XBITMAP): Likewise.
+ (XTREE): Likewise.
+ (XBBDEF): Likewise.
+ (XTMPL): Likewise.
+ (X0WINT): Likewise.
+ (X0INT):Likewise.
+ (X0UINT): Likewise.
+ (X0STR): Likewise.
+ (X0EXP): Likewise.
+ (X0VEC): Likewise.
+ (X0MODE): Likewise.
+ (X0BITMAP): Likewise.
+ (X0TREE): Likewise.
+ (X0BBDEF): Likewise.
+ (X0ADVFLAGS): Likewise.
+ (X0CSELIB): Likewise.
+ (X0MEMATTR): Likewise.
+ (XCWINT): Likewise.
+ (XCINT): Likewise.
+ (XCUINT): Likewise.
+ (XCSTR): Likewise.
+ (XCEXP): Likewise.
+ (XCVEC): Likewise.
+ (XCMODE): Likewise.
+ (XCBITMAP): Likewise.
+ (XCTREE): Likewise.
+ (XCBBDEF): Likewise.
+ (XCADVFLAGS): Likewise.
+ (XCCSELIB): Likewise.
+ (XC2EXP): Likewise.
+ (INSN_UID): Likewise.
+ (PREV_INSN): Likewise.
+ (PATTERN): Likewise.
+ (INSN_CODE): Likewise.
+ (PUT_REG_NOTE_KIND): Likewise.
+ (CODE_LABEL_NUMBER): Likewise.
+ (NOTE_SOURCE_FILE): Likewise.
+ (NOTE_BLOCK): Likewise.
+ (NOTE_EH_HANDLER): Likewise.
+ (NOTE_RANGE_INFO): Likewise.
+ (NOTE_LIVE_INFO): Likewise.
+ (NOTE_BASIC_BLOCK): Likewise.
+ (NOTE_EXPECTED_VALUE): Likewise.
+ (NOTE_LINE_NUMBER): Likewise.
+ (LABEL_NAME): Likewise.
+ (LABEL_NUSES): Likewise.
+ (LABEL_ALTERNATE_NAME): Likewise.
+ (ADDRESSOF_DECL): Likewise.
+ (JUMP_LABEL): Likewise.
+ (LABEL_NEXTREF): Likewise.
+ (REGNO): Likewise.
+ (ORIGINAL_REGNO: Likewise.
+ (HARD_REGISTER_NUM_P): Add parenthesis.
+ (SUBREG_REG): Whitespace.
+ (SUBREG_BYTE): Likewise.
+ (ASM_OPERANDS_TEMPLATE): Remove parenthesis.
+ (ASM_OPERANDS_OUTPUT_CONSTRAINT): Likewise.
+ (ASM_OPERANDS_OUTPUT_IDX): Likewise.
+ (ASM_OPERANDS_INPUT_VEC): Likewise.
+ (ASM_OPERANDS_INPUT_CONSTRAINT_VEC): Likewise.
+ (ASM_OPERANDS_INPUT): Likewise.
+ (ASM_OPERANDS_INPUT_LENGTH): Likewise.
+ (ASM_OPERANDS_INPUT_CONSTRAINT_EXP): Likewise.
+ (ASM_OPERANDS_INPUT_CONSTRAINT): Likewise.
+ (ASM_OPERANDS_INPUT_MODE): Likewise.
+ (ASM_OPERANDS_SOURCE_FILE): Likewise.
+ (ASM_OPERANDS_SOURCE_LINE): Likewise.
+ (MEM_SET_IN_STRUCT_P): Minor reformat.
+ (TRAP_CONDITION): Whitespace.
+ (TRAP_CODE): Likewise.
+ (COND_EXEC_TEST): Likewise.
+ (COND_EXEC_CODE): Likewise.
+ (FIND_REG_INC_NOTE): Uppercase macro args and add parenthesis.
+ (PHI_NODE_P): Add parenthesis.
+ (plus_constant): Whitespace and add parenthesis.
+
+2002-01-03 Kazu Hirata <kazu@hxi.com>
+
+ * config/avr/avr.c: Fix comment typos.
+ * config/c4x/c4x.md: Likewise.
+ * config/dsp16xx/dsp16xx.h: Likewise.
+ * config/dsp16xx/dsp16xx.md: Likewise.
+ * config/i386/i386.md: Likewise.
+ * config/ia64/ia64.c: Likewise.
+ * config/m32r/m32r.h: Likewise.
+ * config/m68hc11/m68hc11.md: Likewise.
+ * config/mmix/mmix.c: Likewise.
+ * config/mn10200/mn10200.c: Likewise.
+ * config/romp/romp.c: Likewise.
+ * config/sh/sh.c: Likewise.
+ * config/stormy16/stormy16.c: Likewise.
+ * config/stormy16/stormy16.h: Likewise.
+ * config/stormy16/stormy16.md: Likewise.
+
+2002-01-03 Graham Stott <grahams@redhat.com>
+
+ * loop.h: Update copyright date.
+ (LOOP_MOVABLES): Fix typo.
+ (LOOP_REGS): Likewise.
+ (LOOP_IVS): Likewise.
+
+2002-01-03 Graham Stott <grahams@redhat.com>
+
+ * cppinit.c: Update copyright date.
+ Don't include output.h
+ * Makefile.in: Update copyright date.
+ Update dependency.
+
+2002-01-02 Craig Rodrigues <rodrigc@gcc.gnu.org>
+
+ PR c/5226
+ * invoke.texi (-mthreads): Remove from documented RS/6000 options.
+ (-pthread) Add to RS/6000 options.
+
+2002-01-02 Kazu Hirata <kazu@hxi.com>
+
+ * except.c: Fix comment typos.
+ * loop.c: Likewise.
+ * varasm.c: Likewise.
+ * doc/tm.texi: Fix a typo.
+
+2002-01-02 Jakub Jelinek <jakub@redhat.com>
+
+ * c-typeck.c (output_init_element): Allow initializing static storage
+ duration objects with compound literals.
+
+2002-01-02 Richard Henderson <rth@redhat.com>
+
+ * objc/objc-act.c (hack_method_prototype): Clear current_function_decl
+ after abusing it.
+
+2002-01-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * gcc.c (default_compilers): Const-ify.
+ * mips-tdump.c (stab_names): Likewise.
+ * mips-tfile.c (map_coff_types, map_coff_storage,
+ map_coff_sym_type, map_coff_derived_type, stabs_symbol,
+ pseudo_ops_t, pseudo_ops): Likewise.
+ * protoize.c (default_include): Likewise
+
+ * real.c (GET_REAL, PUT_REAL): Don't cast away const-ness.
+ (ezero, ehalf, eone, etwo, e32, elog2, esqrt2, epi): Const-ify.
+ Add array size in declaration.
+ (endian, emov, eisneg, eisinf, eisnan, eiisnan, eiisneg, emovi,
+ emovo, emovz, eiisinf, ecmpm, eaddm, esubm, m16m, edivm, emulm,
+ esub, eadd, eadd1, ediv, emul, e53toe, e64toe, e113toe, e24toe,
+ etoe113, etoe64, etoe53, etoe24, ecmp, eround, ltoe, ultoe,
+ eifrac, euifrac, e24toasc, e53toasc, e64toasc, e113toasc, etoasc,
+ efloor, efrexp, eldexp, eremain, dectoe, etodec, ibmtoe, etoibm,
+ c4xtoe, etoc4x, uditoe, ditoe, etoudi, etodi, esqrt, etens,
+ emtens, make_nan): Const-ify.
+ (TFbignan, TFlittlenan, XFbignan, XFlittlenan, DFbignan,
+ DFlittlenan, SFbignan, SFlittlenan): Make static and const-ify.
+
+2002-01-02 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * config.gcc (ia64-*-*): Set extra_headers.
+ (alpha*-dec-osf*): Likewise. Don't use alpha/t-osf.
+ * config/alpha/t-osf: Remove.
+ * config/ia64/t-ia64 (EXTRA_HEADERS): Remove.
+
+2002-01-02 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/t-aix43: Revert previous change.
+
+2002-01-02 Jason Merrill <jason@redhat.com>
+
+ * c-decl.c (c_expand_body): Call outlining_inline_function when
+ emitting an inline function out of line.
+
+2002-01-02 Richard Henderson <rth@redhat.com>
+
+ * dwarf2out.c (limbo_die_node): Add created_for member.
+ (new_die): New argument created_for. Update all callers.
+ (mark_limbo_die_list): New.
+ (dwarf2out_init): Register limbo_die_list as a root.
+ (dwarf2out_finish): Force insert limbo dies into their function
+ context.
+
+2002-01-02 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/5089
+ * doc/invoke.texi (-Wold-style-cast): Only warn about non-void casts.
+
+2002-01-02 Kazu Hirata <kazu@hxi.com>
+
+ * config/h8300/fixunssfsi.c: Update copyright.
+ Fix comment typos.
+ Fix formatting.
+ * config/h8300/h8300.c: Update copyright.
+ Eliminate warnings.
+
+2002-01-02 Kazu Hirata <kazu@hxi.com>
+
+ * config/romp/romp.c: Fix comment formatting.
+ * config/romp/romp.h: Likewise.
+ * config/romp/romp.md: Likewise.
+ * config/s390/s390.c: Likewise.
+ * config/stormy16/stormy16.c: Likewise.
+ * config/stormy16/stormy16.h: Likewise.
+
+2002-01-02 Alexandre Oliva <aoliva@redhat.com>
+
+ * c-common.h (genrtl_expr_stmt_value): Declare.
+ * c-semantics.c (genrtl_goto_stmt): Redirect to...
+ (genrtl_goto_stmt_value): ... this new function. Pass new
+ argument down to expand_expr_stmt_value, taking
+ TREE_ADDRESSABLE into account.
+ * c-common.c (c_expand_expr): Mark the last EXPR_STMT of a
+ STMT_EXPR as addressable, i.e., one whose result we want.
+ * expr.c (expand_expr): Don't save expression statement value
+ of labeled_blocks or loop_exprs.
+ * stmt.c (expand_expr_stmt): Redirect to...
+ (expand_expr_stmt_value): ... this new function. Use new
+ argument to tell whether to save expression value.
+ (expand_end_stmt_expr): Reset last_expr_type and
+ last_expr_value if we don't have either.
+ * tree-inline.c (declare_return_variable): Mark its use
+ statement as addressable.
+ * tree.h: Document new use of TREE_ADDRESSABLE.
+ (expand_expr_stmt_value): Declare.
+
+2002-01-01 Tom Rix <trix@redhat.com>
+
+ * config/rs6000/rs6000.c (rs6000_emit_set_long_const): Fix for use by
+ rs6000_emit_allocate_stack.
+
+2002-01-01 Joseph S. Myers <jsm28@cam.ac.uk>
+
+ * configure.in: Prepend ${srcdir}/config/${cpu_type}/ instead of
+ ${srcdir}/ginclude/ to every entry in extra_headers.
+ * configure: Regenerate.
+ * ginclude/math-3300.h: Rename to config/m68k/math-3300.h.
+ * ginclude/math-68881.h: Rename to config/m68k/math-68881.h.
+ * ginclude/ppc-asm.h: Rename to config/rs6000/ppc-asm.h.
+ * ginclude/proto.h: Rename to config/convex/proto.h.
+
+Tue Jan 1 17:12:56 2002 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * attribs.c (handle_vector_size_attribute): Use host_integerp
+ and tree_int_cst; remove warnings.
+ * caller-save.c (insert_restore): Add cast to get rid of warning.
+ (insert_save): Likewise.
+ * emit-rtl.c (adjust_address_1, offset_address): Likewise.
+ * regmove.c (find_matches): Add temporary var to kill a warning.
+
+2002-01-01 Douglas B Rupp <rupp@gnat.com>
+
+ * config/alpha/vms.h (DWARF2_UNWIND_INFO, EH_RETURN_HANDLER_RTX,
+ LINK_EH_SPEC, MD_FALLBACK_FRAME_STATE_FOR): Define.
+ * config/alpha/t-vms (EXTRA_PARTS): Add vms-dwarf2eh.o
+ (vms-dwarf2eh.o): Add Makefile rule.
+ * config/alpha/vms-ld.c (main): Handle vms-dwarf2eh.o.
+ * config/alpha/vms-dwarf2eh.asm: New file.
+
+ * gcc.c (delete_if_ordinary): Delete all versions.
+
+2002-01-01 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * config/mmix/mmix.md: Update FIXME to not mention
+ define_constants.
+ (MMIX_rJ_REGNUM): New define_constants constant.
+ ("movqi", "movsi", "movdi", "*movdicc_real_foldable",
+ "*movdicc_real"): Adjust contraints formatting.
+ ("*bCC_foldable"): Add %+ for P in output format and delete FIXME
+ for branch prediction.
+ ("*bCC", "*bCC_inverted_foldable", "*bCC_inverted"): Add %+ in
+ output template.
+ ("*call_real", "*call_value_real", "nonlocal_goto_receiver",
+ "*nonlocal_goto_receiver_expanded"): Use MMIX_rJ_REGNUM instead of
+ number. Delete related FIXMEs.
+ * config/mmix/mmix.h (MMIX_INCOMING_RETURN_ADDRESS_REGNUM): Change
+ from number to MMIX_rJ_REGNUM.
+ (TARGET_MASK_BRANCH_PREDICT): New.
+ (TARGET_DEFAULT): Change to TARGET_MASK_BRANCH_PREDICT.
+ (TARGET_SWITCHES): Update comment. Correct -mno-toplevel-symbols
+ value. Add -mbranch-predict and -mno-branch-predict.
+ (TARGET_VERSION): Drop date.
+ (ADDITIONAL_REGISTER_NAMES): Use MMIX_rJ_REGNUM, not number.
+ * config/mmix/mmix.c (mmix_encode_section_info): Correct condition
+ for finding out global symbols.
+ (mmix_asm_output_labelref): Revert condition for global symbol.
+ (mmix_print_operand): <case '+'>: Emit P for a likely branch.
+ (mmix_print_operand_punct_valid_p): A '+' is valid.
+
+See ChangeLog.6 for earlier changes.
diff --git a/contrib/gcc/FSFChangeLog.10 b/contrib/gcc/FSFChangeLog.10
index 0fea553..e7ae6c5 100644
--- a/contrib/gcc/FSFChangeLog.10
+++ b/contrib/gcc/FSFChangeLog.10
@@ -5704,7 +5704,7 @@ Sun Aug 13 14:50:58 1995 Jim Wilson <wilson@chestnut.cygnus.com>
* Makefile.in (gfloat.h): Add a - before the rm command.
* loop.c (find_and_verify_loops): Set dest_loop only if
- JUMP_LABEL (insn) is non-zero.
+ JUMP_LABEL (insn) is nonzero.
Mon Jul 31 14:31:53 1995 Ian Lance Taylor <ian@cygnus.com>
@@ -6057,7 +6057,7 @@ Mon Jul 17 06:41:19 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
* xm-alpha.h (sbrk): Add declaration.
- * convert.c (convert_to_integer): If TYPE is a enumeral type or
+ * convert.c (convert_to_integer): If TYPE is an enumeral type or
if its precision is not the same as the size of its mode,
convert in two steps.
@@ -8538,7 +8538,7 @@ Tue Apr 25 18:52:43 1995 Stephen R. van den Berg (berg@pool.informatik.rwth-aa
(mark_regs_pat, straighten_stack): New functions.
(reg_to_stack): Amend initialisation of FP_mode_reg.
Mark FP registers mentioned in USE insns before NOTE_INSN_FUNCTION_BEG.
- (get_true_reg): Eliminate FP subreg accesses in favour of the
+ (get_true_reg): Eliminate FP subreg accesses in favor of the
actual FP register in use.
(record_reg_life_pat): Make it work on SUBREGs as well. Make use of
the new mark_regs_pat function. Handle USE insns if called unnested.
@@ -8552,7 +8552,7 @@ Tue Apr 25 18:52:43 1995 Stephen R. van den Berg (berg@pool.informatik.rwth-aa
Delete the no_live_regs shortcut to save space.
Use stackentry state to determine filled registers.
(replace_reg): Accept COMPLEX_FLOAT as well.
- (move_for_stack_reg): Optimise away some pointer dereferencing.
+ (move_for_stack_reg): Optimize away some pointer dereferencing.
(subst_stack_regs): Make sure the stack is in the right order
and of the right size for register passing.
(goto_block_pat): Make sure the stack is in the right order
@@ -8841,7 +8841,7 @@ Sat Apr 15 13:26:34 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
Sat Apr 15 12:11:46 1995 Brendan Kehoe <brendan@cygnus.com>
* alpha/alpha.c (output_epilog): Initialize fp_offset to 0, and
- make sure it's non-zero before we try to use it to restore the
+ make sure it's nonzero before we try to use it to restore the
frame pointer.
Fri Apr 14 19:45:05 1995 Jason Merrill <jason@phydeaux.cygnus.com>
diff --git a/contrib/gcc/FSFChangeLog.11 b/contrib/gcc/FSFChangeLog.11
index 38de90c..1e80eab 100644
--- a/contrib/gcc/FSFChangeLog.11
+++ b/contrib/gcc/FSFChangeLog.11
@@ -2636,7 +2636,7 @@ Wed Sep 10 11:49:20 1997 Jason Merrill <jason@yorick.cygnus.com>
EXCEPTION_SECTION, mark the start of the frame info with a
collectable tag.
* collect2.c (frame_tables): New list.
- (is_ctor_dtor): Recognise frame entries.
+ (is_ctor_dtor): Recognize frame entries.
(scan_prog_file): Likewise.
(main): Pass -fno-exceptions to sub-compile. Also do collection
if there are any frame entries.
@@ -3114,7 +3114,7 @@ Wed Aug 27 20:15:53 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
(braf_branch_p, align_length, fixup_addr_diff_vecs): Likewise.
(addr_diff_vec_adjust, get_dest_uid, gen_far_branch): Likewise.
(split_branches, regs_used, gen_block_redirect): Likewise.
- (from_compare): Can't compare non-zero DImode constant directly.
+ (from_compare): Can't compare nonzero DImode constant directly.
Emit special code for TARGET_SH3E floating point with code == GE.
Force 0.0 into a register for SH3E.
(print_operand): Add ','.
@@ -3935,7 +3935,7 @@ Mon Aug 4 08:06:48 1997 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
integer argument of push_reload.
* rtlanal.c (may_trap_p): Fix unintended fall-through so divisions by
- non-zero constants are handled properly. Return 1 for FP divisions.
+ nonzero constants are handled properly. Return 1 for FP divisions.
Mon Aug 4 06:52:20 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
@@ -3948,7 +3948,7 @@ Sun Aug 3 21:57:31 1997 Jim Meyering <meyering@eng.ascend.com>
Sun Aug 3 21:54:51 1997 Nick Burrett <n.a.burrett@btinternet.com>
- * cpplib.c (cpp_start_read): Recognise suffixes 'cp' and 'c++'.
+ * cpplib.c (cpp_start_read): Recognize suffixes 'cp' and 'c++'.
Sun Aug 3 19:18:27 1997 Ralf Baechle <ralf@uni-koblenz.de>
@@ -5105,7 +5105,7 @@ Thu Jun 19 21:18:20 1997 Jim Wilson <wilson@cygnus.com>
Thu Jun 19 14:55:49 1997 Brendan Kehoe <brendan@cygnus.com>
- * toplev.c (xmalloc): Only give the fatal msg if SIZE is non-zero.
+ * toplev.c (xmalloc): Only give the fatal msg if SIZE is nonzero.
Sun Apr 27 23:19:13 1997 Ulrich Drepper <drepper@cygnus.com>
@@ -9711,7 +9711,7 @@ Sun Oct 20 20:01:09 1996 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
Fri Oct 18 13:32:13 1996 Michael Meissner <meissner@tiktok.cygnus.com>
* rs6000.md (float conversion insns): Generate correct code
- if the bit 15 of rs6000_fpmem_offset is non-zero.
+ if the bit 15 of rs6000_fpmem_offset is nonzero.
Thu Oct 17 23:22:03 1996 Jason Merrill <jason@yorick.cygnus.com>
@@ -9814,7 +9814,7 @@ Tue Oct 15 16:52:33 1996 Ian Lance Taylor <ian@cygnus.com>
Tue Oct 15 11:19:17 1996 Lee Iverson <leei@Canada.AI.SRI.COM>
- * mips.h (CPP_SPEC): Restore -D_LANGUAGE_C for Objective C.
+ * mips.h (CPP_SPEC): Restore -D_LANGUAGE_C for Objective-C.
Mon Oct 14 18:03:35 1996 Jason Merrill <jason@yorick.cygnus.com>
@@ -9864,7 +9864,7 @@ Fri Oct 11 12:19:21 1996 Ian Lance Taylor <ian@cygnus.com>
(ASM_SPEC): Rewrite to use above specs.
(SUBTARGET_CPP{,_SIZE}_SPEC): Define.
(CPP_SPEC): Use above specs. Don't define _LANGUAGE_C if C++ or
- Objective C.
+ Objective-C.
({,SUBTARGET_}EXTRA_SPECS): Define.
* mips/dec-bsd.h ({CPP,ASM}_SPEC): Don't define.
* mips/dec-osf1.h (CPP_SPEC): Don't define.
@@ -11676,7 +11676,7 @@ Thu Jul 11 17:29:33 1996 Michael Meissner <meissner@tiktok.cygnus.com>
Thu Jul 11 10:12:50 1996 Jeffrey A Law (law@cygnus.com)
- * h8300.h (OK_FOR_U): If generating H8/S code, accept
+ * h8300.h (OK_FOR_U): If generating H8S code, accept
SYMBOL_REF and SYMBOL_REF + CONST_INT.
* h8300.c ({shift,rotate}_one): Emit tabs between opcode and
@@ -11684,7 +11684,7 @@ Thu Jul 11 10:12:50 1996 Jeffrey A Law (law@cygnus.com)
(shift_two, rotate_two): Define.
(get_shift_alg): Accept new argument "assembler2_p" for
rotate/shift by two insns. All callers changed. Rework
- to generate more efficient code on the H8/300, H8/300H, and H8/S.
+ to generate more efficient code on the H8/300, H8/300H, and H8S.
Try to simplify somewhat.
(emit_a_shift): Use shift-by-two insns when they're available.
Emit tabs between opcode and operands to be consistent with
@@ -11755,31 +11755,31 @@ Mon Jul 8 18:00:33 1996 Jim Wilson <wilson@cygnus.com>
Mon Jul 8 16:27:33 1996 Jeffrey A. Law <law@cygnus.com>
- * First cut at support for the H8/S.
- * h8300.c (h8300_init_once): Handle the H8/S (treat it
+ * First cut at support for the H8S.
+ * h8300.c (h8300_init_once): Handle the H8S (treat it
like the H8/300H).
(dosize, adds_subs_operand, one_insn_adds_subs_operand): Likewise.
(output_adds_subs, const_costs, print_operand): Likewise.
(output_simode_bld, h8300_adjust_insn_length): Likewise.
(push_order, pop_order): Reverse.
(function_prologue): Try to use ldm.l and stm.l insns
- on the H8/S. Minor cleanups.
+ on the H8S. Minor cleanups.
(function_epilogue): Likewise.
- (asm_file_start): Emit ".h8300s" when compiling for the H8/S.
- * h8300/h8300.h (CPP_SPEC): Handle the H8/S.
+ (asm_file_start): Emit ".h8300s" when compiling for the H8S.
+ * h8300/h8300.h (CPP_SPEC): Handle the H8S.
(TARGET_H8300S): New target.
(TARGET_SWITCHES): Add "-ms" and "-mno-s".
- (BITS_PER_WORD): Handle the H8/S (treat it like the H8/300H).
+ (BITS_PER_WORD): Handle the H8S (treat it like the H8/300H).
(UNITS_PER_WORD, POINTER_SIZE, PARM_BOUNDARY): Likewise.
(BIGGEST_ALIGNMENT, BIGGEST_FIELD_ALIGNMENT): Likewise.
(INITIALIZE_TRAMPOLINE, MOVE_MAX, Pmode): Likewise.
- * h8300.md: Handle H8/S just like H8/300H
+ * h8300.md: Handle H8S just like H8/300H
throughout the entire file.
* t-h8300 (MULTILIB_OPTIONS): Build "-ms" libraries too.
- (MULTILIB_DIRNAMES): Put H8/S libraries in "h8300s" directory.
+ (MULTILIB_DIRNAMES): Put H8S libraries in "h8300s" directory.
* h8300/lib1funcs.asm: Emit ".h8300s" pseudo-op when generating
- h8300s object files. Otherwise treat the H8/S just like the H8/300H.
- * ginclude/stdarg.h: Handle the H8/S.
+ h8300s object files. Otherwise treat the H8S just like the H8/300H.
+ * ginclude/stdarg.h: Handle the H8S.
* ginclude/varargs.h: Likewise.
Mon Jul 8 14:50:58 1996 Doug Evans <dje@cygnus.com>
@@ -14430,7 +14430,7 @@ Thu Apr 4 11:40:55 1996 Michael Meissner <meissner@tiktok.cygnus.com>
Wed Apr 3 14:10:16 1996 Jim Wilson <wilson@chestnut.cygnus.com>
- * expr.c (emit_push_insn): Clobber register only if it is non-zero.
+ * expr.c (emit_push_insn): Clobber register only if it is nonzero.
Wed Apr 3 11:31:55 1996 Jeffrey A. Law <law@cygnus.com>
diff --git a/contrib/gcc/LANGUAGES b/contrib/gcc/LANGUAGES
index 8bc5156..d1e0719 100644
--- a/contrib/gcc/LANGUAGES
+++ b/contrib/gcc/LANGUAGES
@@ -18,7 +18,7 @@ Aug 31, 1998:
from the input stream, and to push them back into the input stream respectively.
The third argument is a pointer to a null terminate string which is the first
word after #pragma. The expression supplied by HANDLE_PRAGMA should return
- non-zero if it parsed and implemented the pragma. Otherwise it should return
+ nonzero if it parsed and implemented the pragma. Otherwise it should return
zero, and leave the input stream as it was before the expression was evaluated.
A new back-end definable macro has been added: INSERT_ATTRIBUTES. This macro
diff --git a/contrib/gcc/Makefile.in b/contrib/gcc/Makefile.in
index e7c29b9e..75e4d03 100644
--- a/contrib/gcc/Makefile.in
+++ b/contrib/gcc/Makefile.in
@@ -69,6 +69,13 @@ CFLAGS = -g
STAGE1_CFLAGS = -g @stage1_cflags@
BOOT_CFLAGS = -g -O2
+# Flags to determine code coverage. When coverage is disabled, this will
+# contain the optimization flags, as you normally want code coverage
+# without optimization. The -dumpbase $@ makes sure that the auxilary
+# files end up near the object files.
+COVERAGE_FLAGS = @coverage_flags@
+coverageexts = .{da,bb,bbg}
+
# The warning flags are separate from BOOT_CFLAGS because people tend to
# override optimization flags and we'd like them to still have warnings
# turned on. These flags are also used to pass other stage dependent
@@ -85,9 +92,17 @@ LOOSE_WARN = -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes
STRICT_WARN = -Wtraditional @strict1_warn@
STRICT2_WARN = -Wtraditional -pedantic -Wno-long-long
+# This is set by --enable-checking. The idea is to catch forgotten
+# "extern" tags in header files.
+NOCOMMON_FLAG = @nocommon_flag@
+
+# These are set by --enable-checking=valgrind.
+RUN_GEN = @valgrind_command@
+VALGRIND_DRIVER_DEFINES = @valgrind_path_defines@
+
# This is how we control whether or not the additional warnings are applied.
.-warn = $(STRICT_WARN)
-GCC_WARN_CFLAGS = $(LOOSE_WARN) $($(@D)-warn)
+GCC_WARN_CFLAGS = $(LOOSE_WARN) $($(@D)-warn) $(NOCOMMON_FLAG)
# All warnings have to be shut off in stage1 if the compiler used then
# isn't gcc; configure determines that. WARN_CFLAGS will be either
@@ -101,6 +116,7 @@ T_CFLAGS =
X_CPPFLAGS =
T_CPPFLAGS =
+ADAC = @ADAC@
AWK = @AWK@
CC = @CC@
BISON = @BISON@
@@ -111,7 +127,14 @@ AR = ar
AR_FLAGS = rc
DLLTOOL = dlltool
RANLIB = @RANLIB@
-SHELL = /bin/sh
+SHELL = @SHELL@
+# pwd command to use. Allow user to override default by setting PWDCMD in
+# the environment to account for automounters. The make variable must not
+# be called PWDCMD, otherwise the value set here is passed to make
+# subprocesses and overrides the setting from the user's environment.
+# Don't use PWD since it is a common shell environment variable and we
+# don't want to corrupt it.
+PWD_COMMAND = $${PWDCMD-pwd}
# on sysV, define this as cp.
INSTALL = @INSTALL@
# Some systems may be missing symbolic links, regular links, or both.
@@ -154,15 +177,19 @@ INSTALL_HEADERS_DIR = @build_install_headers_dir@
# Header files that are made available under the same name
# to programs compiled with GCC.
-USER_H = $(srcdir)/ginclude/stdarg.h $(srcdir)/ginclude/stddef.h \
- $(srcdir)/ginclude/varargs.h \
- $(srcdir)/ginclude/stdbool.h $(srcdir)/ginclude/iso646.h \
- $(EXTRA_HEADERS)
-
-# The GCC to use for compiling libgcc.a, enquire, and crt*.o.
+USER_H = $(srcdir)/ginclude/float.h \
+ $(srcdir)/ginclude/iso646.h \
+ $(srcdir)/ginclude/stdarg.h \
+ $(srcdir)/ginclude/stdbool.h \
+ $(srcdir)/ginclude/stddef.h \
+ $(srcdir)/ginclude/varargs.h \
+ $(srcdir)/unwind.h \
+ $(EXTRA_HEADERS)
+
+# The GCC to use for compiling libgcc.a and crt*.o.
# Usually the one we just built.
# Don't use this as a dependency--use $(GCC_PASSES) or $(GCC_PARTS).
-GCC_FOR_TARGET = ./xgcc -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include -isystem $(build_tooldir)/sys-include
+GCC_FOR_TARGET = $(STAGE_CC_WRAPPER) ./xgcc -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include -isystem $(build_tooldir)/sys-include
# This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET.
# It omits XCFLAGS, and specifies -B./.
@@ -230,6 +257,7 @@ HASHTAB_H = $(srcdir)/../include/hashtab.h
OBSTACK_H = $(srcdir)/../include/obstack.h
SPLAY_TREE_H= $(srcdir)/../include/splay-tree.h
FIBHEAP_H = $(srcdir)/../include/fibheap.h
+PARTITION_H = $(srcdir)/../include/partition.h
# Default native SYSTEM_HEADER_DIR, to be overridden by targets.
NATIVE_SYSTEM_HEADER_DIR = /usr/include
@@ -253,6 +281,7 @@ tmake_file=@dep_tmake_file@
out_file=$(srcdir)/config/@out_file@
out_object_file=@out_object_file@
md_file=$(srcdir)/config/@md_file@
+tm_defines=@tm_defines@
tm_p_file_list=@tm_p_file_list@
tm_p_file=@tm_p_file@
build_xm_file_list=@build_xm_file_list@
@@ -369,11 +398,12 @@ TARGET_LIBGCC2_CFLAGS =
# Options to use when compiling crtbegin/end.
CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
- -finhibit-size-directive -fno-inline-functions -fno-exceptions
+ -finhibit-size-directive -fno-inline-functions -fno-exceptions \
+ -fno-zero-initialized-in-bss
# Additional sources to handle exceptions; overridden on ia64.
LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
- $(srcdir)/unwind-sjlj.c
+ $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h
# nm flags to list global symbols in libgcc object files.
@@ -415,19 +445,11 @@ LIB2FUNCS_EXTRA =
# Assembler files should have names ending in `.asm'.
LIB2FUNCS_STATIC_EXTRA =
-# Handle cpp installation.
-INSTALL_CPP=
-UNINSTALL_CPP=
-
-# We do not try to build float.h anymore. Let configure select the
-# appropriate pre-built float.h file for the target.
-FLOAT_H=@float_h_file@
-
# Program to convert libraries.
LIBCONVERT =
# Control whether header files are installed.
-INSTALL_HEADERS=install-headers
+INSTALL_HEADERS=install-headers install-mkheaders
# Control whether Info documentation is built and installed.
BUILD_INFO = @BUILD_INFO@
@@ -449,7 +471,7 @@ COMPILERS = cc1$(exeext) @all_compilers@
# List of things which should already be built whenever we try to use xgcc
# to compile anything (without linking).
-GCC_PASSES=xgcc$(exeext) cc1$(exeext) cpp0$(exeext) specs $(EXTRA_PASSES)
+GCC_PASSES=xgcc$(exeext) cc1$(exeext) specs $(EXTRA_PASSES)
# List of things which should already be built whenever we try to use xgcc
# to link anything.
@@ -461,12 +483,12 @@ DIR = ../gcc
# Flags to use when cross-building GCC.
# Prefix to apply to names of object files when using them
# to run on the machine we are compiling on.
-HOST_PREFIX = @HOST_PREFIX@
+BUILD_PREFIX = @BUILD_PREFIX@
# Prefix to apply to names of object files when compiling them
# to run on the machine we are compiling on.
# The default for this variable is chosen to keep these rules
# out of the way of the other rules for compiling the same source files.
-HOST_PREFIX_1 = @HOST_PREFIX_1@
+BUILD_PREFIX_1 = @BUILD_PREFIX_1@
# Native compiler for the build machine and its switches.
HOST_CC = @HOST_CC@
HOST_CFLAGS= @HOST_CFLAGS@ -DGENERATOR_FILE
@@ -533,7 +555,7 @@ all: all.indirect
.NOEXPORT:
# GCONFIG_H lists the config files that the generator files depend on, while
-# CONFIG_H lists the the ones ordinary gcc files depend on, which includes
+# CONFIG_H lists the ones ordinary gcc files depend on, which includes
# several files generated by those generators.
GCONFIG_H = config.h $(host_xm_file_list)
HCONFIG_H = hconfig.h $(build_xm_file_list)
@@ -541,16 +563,18 @@ CONFIG_H = $(GCONFIG_H) insn-constants.h insn-flags.h
TCONFIG_H = tconfig.h $(xm_file_list)
TARGET_H = target.h
HOOKS_H = hooks.h
-LANGHOOKS_DEF_H = langhooks.h $(HOOKS_H)
+LANGHOOKS_DEF_H = langhooks-def.h $(HOOKS_H)
TARGET_DEF_H = target-def.h $(HOOKS_H)
TM_P_H = tm_p.h $(tm_p_file_list) tm-preds.h
-MACHMODE_H = machmode.h machmode.def
+MACHMODE_H = machmode.h machmode.def @extra_modes_file@
RTL_BASE_H = rtl.h rtl.def $(MACHMODE_H)
RTL_H = $(RTL_BASE_H) genrtl.h
PARAMS_H = params.h params.def
-TREE_H = tree.h real.h tree.def $(MACHMODE_H) tree-check.h version.h builtins.def
-BASIC_BLOCK_H = basic-block.h bitmap.h sbitmap.h varray.h
+TREE_H = tree.h tree.def $(MACHMODE_H) tree-check.h version.h builtins.def \
+ location.h
+BASIC_BLOCK_H = basic-block.h bitmap.h sbitmap.h varray.h $(PARTITION_H) \
+ hard-reg-set.h
DEMANGLE_H = $(srcdir)/../include/demangle.h
RECOG_H = recog.h
EXPR_H = expr.h
@@ -559,10 +583,10 @@ REGS_H = regs.h varray.h $(MACHMODE_H)
INTEGRATE_H = integrate.h varray.h
LOOP_H = loop.h varray.h bitmap.h
GCC_H = gcc.h version.h
-GGC_H = ggc.h varray.h
+GGC_H = ggc.h varray.h gtype-desc.h
TIMEVAR_H = timevar.h timevar.def
INSN_ATTR_H = insn-attr.h $(srcdir)/insn-addr.h $(srcdir)/varray.h
-C_COMMON_H = c-common.h $(SPLAY_TREE_H)
+C_COMMON_H = c-common.h $(SPLAY_TREE_H) $(CPPLIB_H)
C_TREE_H = c-tree.h $(C_COMMON_H)
SYSTEM_H = system.h hwint.h $(srcdir)/../include/libiberty.h
PREDICT_H = predict.h predict.def
@@ -587,8 +611,8 @@ INTERNAL_CFLAGS = -DIN_GCC @CROSS@
# This is the variable actually used when we compile.
# If you change this line, you probably also need to change the definition
# of HOST_CFLAGS in build-make to match.
-ALL_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) \
- $(CFLAGS) $(WARN_CFLAGS) $(XCFLAGS) @DEFS@
+ALL_CFLAGS = $(X_CFLAGS) $(T_CFLAGS) \
+ $(CFLAGS) $(INTERNAL_CFLAGS) $(COVERAGE_FLAGS) $(WARN_CFLAGS) $(XCFLAGS) @DEFS@
# Likewise.
ALL_CPPFLAGS = $(CPPFLAGS) $(X_CPPFLAGS) $(T_CPPFLAGS)
@@ -609,15 +633,24 @@ HOST_LIBDEPS= $(BUILD_LIBIBERTY)
# and the system's installed libraries.
LIBS = $(INTLLIBS) @LIBS@ $(LIBIBERTY)
+# Any system libraries needed just for GNAT.
+SYSLIBS = @GNAT_LIBEXC@
+
+# Libs needed (at present) just for jcf-dump.
+LDEXP_LIB = @LDEXP_LIB@
+
# Likewise, for use in the tools that must run on this machine
# even if we are cross-building GCC.
HOST_LIBS = $(BUILD_LIBIBERTY)
-HOST_RTL = $(HOST_PREFIX)rtl.o read-rtl.o $(HOST_PREFIX)bitmap.o \
- $(HOST_PREFIX)ggc-none.o gensupport.o
+HOST_RTL = $(BUILD_PREFIX)rtl.o read-rtl.o $(BUILD_PREFIX)bitmap.o \
+ $(BUILD_PREFIX)ggc-none.o
+HOST_SUPPORT = gensupport.o insn-conditions.o
+HOST_EARLY_SUPPORT = gensupport.o dummy-conditions.o
-HOST_PRINT = $(HOST_PREFIX)print-rtl.o
-HOST_ERRORS = $(HOST_PREFIX)errors.o
+HOST_PRINT = print-rtl1.o
+HOST_ERRORS = $(BUILD_PREFIX)errors.o
+HOST_VARRAY = $(BUILD_PREFIX)varray.o
# Specify the directories to be searched for header files.
# Both . and srcdir are used, in that order,
@@ -704,60 +737,55 @@ CXX_TARGET_OBJS=@cxx_target_objs@
# Language-specific object files for C and Objective C.
C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \
- c-convert.o c-aux-info.o c-common.o c-format.o c-semantics.o \
- c-objc-common.o libcpp.a $(C_TARGET_OBJS)
+ c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \
+ c-objc-common.o c-dump.o libcpp.a $(C_TARGET_OBJS)
# Language-specific object files for C.
-C_OBJS = c-parse.o c-lang.o $(C_AND_OBJC_OBJS)
+C_OBJS = c-parse.o c-lang.o c-pretty-print.o $(C_AND_OBJC_OBJS)
# Language-independent object files.
-OBJS = alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
- cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o cfgrtl.o \
- combine.o conflict.o convert.o cse.o cselib.o dbxout.o debug.o dependence.o \
- df.o diagnostic.o doloop.o dominance.o dwarf2asm.o dwarf2out.o dwarfout.o \
- emit-rtl.o except.o explow.o expmed.o expr.o final.o flow.o \
- fold-const.o function.o gcse.o genrtl.o ggc-common.o global.o graph.o \
- haifa-sched.o hash.o hashtable.o hooks.o ifcvt.o insn-attrtab.o insn-emit.o \
- insn-extract.o insn-opinit.o insn-output.o insn-peep.o insn-recog.o \
- integrate.o intl.o jump.o langhooks.o lcm.o lists.o local-alloc.o \
- loop.o mbchar.o optabs.o params.o predict.o print-rtl.o print-tree.o \
- profile.o real.o recog.o reg-stack.o regclass.o regmove.o regrename.o \
- reload.o reload1.o reorg.o resource.o rtl.o rtlanal.o rtl-error.o \
- sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o \
- sibcall.o simplify-rtx.o ssa.o ssa-ccp.o ssa-dce.o stmt.o \
- stor-layout.o stringpool.o timevar.o toplev.o tree.o tree-dump.o \
+OBJS = alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
+ cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o \
+ cfgrtl.o combine.o conflict.o convert.o cse.o cselib.o dbxout.o \
+ debug.o df.o diagnostic.o doloop.o dominance.o \
+ dwarf2asm.o dwarf2out.o dwarfout.o emit-rtl.o except.o explow.o \
+ expmed.o expr.o final.o flow.o fold-const.o function.o gcse.o \
+ genrtl.o ggc-common.o global.o graph.o gtype-desc.o \
+ haifa-sched.o hashtable.o hooks.o ifcvt.o insn-attrtab.o insn-emit.o \
+ insn-extract.o insn-opinit.o insn-output.o insn-peep.o insn-recog.o \
+ integrate.o intl.o jump.o langhooks.o lcm.o lists.o local-alloc.o \
+ loop.o mbchar.o optabs.o params.o predict.o print-rtl.o print-tree.o \
+ profile.o ra.o ra-build.o ra-colorize.o ra-debug.o ra-rewrite.o \
+ real.o recog.o reg-stack.o regclass.o regmove.o regrename.o \
+ reload.o reload1.o reorg.o resource.o rtl.o rtlanal.o rtl-error.o \
+ sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o \
+ sibcall.o simplify-rtx.o ssa.o ssa-ccp.o ssa-dce.o stmt.o \
+ stor-layout.o stringpool.o timevar.o toplev.o tracer.o tree.o tree-dump.o \
tree-inline.o unroll.o varasm.o varray.o version.o vmsdbgout.o xcoffout.o \
- $(GGC) $(out_object_file) $(EXTRA_OBJS)
+ et-forest.o $(GGC) $(out_object_file) $(EXTRA_OBJS)
BACKEND = main.o libbackend.a
-# GEN files are listed separately, so they can be built before doing parallel
-# makes for cc1 or cc1plus. Otherwise sequent parallel make attempts to load
-# them before rtl.o is compiled.
-GEN= genemit$(build_exeext) genoutput$(build_exeext) genrecog$(build_exeext) \
- genextract$(build_exeext) genflags$(build_exeext) gencodes$(build_exeext) \
- genconfig$(build_exeext) genpeep$(build_exeext) gengenrtl$(build_exeext) \
- gencheck$(build_exeext) genpreds$(build_exeext) genconstants$(build_exeext)
-
# Files to be copied away after each stage in building.
STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \
insn-output.c insn-recog.c insn-emit.c insn-extract.c insn-peep.c \
insn-attr.h insn-attrtab.c insn-opinit.c insn-constants.h tm-preds.h \
- tree-check.h \
- s-flags s-config s-codes s-mlib s-under s-genrtl \
- s-output s-recog s-emit s-extract s-peep s-check \
+ tree-check.h insn-conditions.c \
+ s-flags s-config s-codes s-mlib s-genrtl s-gtype gtyp-gen.h \
+ s-output s-recog s-emit s-extract s-peep s-check s-conditions \
s-attr s-attrtab s-opinit s-preds s-constants s-crt0 \
genemit$(build_exeext) genoutput$(build_exeext) genrecog$(build_exeext) \
genextract$(build_exeext) genflags$(build_exeext) gencodes$(build_exeext) \
genconfig$(build_exeext) genpeep$(build_exeext) genattrtab$(build_exeext) \
genattr$(build_exeext) genopinit$(build_exeext) gengenrtl$(build_exeext) \
gencheck$(build_exeext) genpreds$(build_exeext) genconstants$(build_exeext) \
- genrtl.c genrtl.h \
- xgcc$(exeext) cpp$(exeext) cc1$(exeext) cpp0$(exeext) $(EXTRA_PASSES) \
+ gengtype$(build_exeext) genconditions$(build_exeext) \
+ genrtl.c genrtl.h gt-*.h gtype-*.h gtype-desc.c \
+ xgcc$(exeext) cpp$(exeext) cc1$(exeext) $(EXTRA_PASSES) \
$(EXTRA_PARTS) $(EXTRA_PROGRAMS) gcc-cross$(exeext) cc1obj$(exeext) \
- enquire$(exeext) protoize$(exeext) unprotoize$(exeext) \
- specs collect2$(exeext) $(USE_COLLECT2) underscore.c tradcpp0$(exeext) \
+ protoize$(exeext) unprotoize$(exeext) \
+ specs collect2$(exeext) $(USE_COLLECT2) \
gcov$(exeext) *.[0-9][0-9].* *.[si] libcpp.a libbackend.a libgcc.mk \
$(LANG_STAGESTUFF)
@@ -777,17 +805,30 @@ LIB2FUNCS_ST = _eprintf _bb __gcc_bcmp
FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \
_fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \
_lt_sf _le_sf _unord_sf _si_to_sf _sf_to_si _negate_sf _make_sf \
- _sf_to_df _thenan_sf _sf_to_usi _usi_to_sf
+ _sf_to_df _sf_to_tf _thenan_sf _sf_to_usi _usi_to_sf
DPBIT_FUNCS = _pack_df _unpack_df _addsub_df _mul_df _div_df \
_fpcmp_parts_df _compare_df _eq_df _ne_df _gt_df _ge_df \
_lt_df _le_df _unord_df _si_to_df _df_to_si _negate_df _make_df \
- _df_to_sf _thenan_df _df_to_usi _usi_to_df
+ _df_to_sf _df_to_tf _thenan_df _df_to_usi _usi_to_df
+
+TPBIT_FUNCS = _pack_tf _unpack_tf _addsub_tf _mul_tf _div_tf \
+ _fpcmp_parts_tf _compare_tf _eq_tf _ne_tf _gt_tf _ge_tf \
+ _lt_tf _le_tf _unord_tf _si_to_tf _tf_to_si _negate_tf _make_tf \
+ _tf_to_df _tf_to_sf _thenan_tf _tf_to_usi _usi_to_tf
# These might cause a divide overflow trap and so are compiled with
# unwinder info.
LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _udivdi3 _umoddi3 _udiv_w_sdiv _udivmoddi4
+# The only suffixes we want for implicit rules are .c and .o, so clear
+# the list and add them. This speeds up GNU Make, and allows -r to work.
+# For i18n support, we also need .gmo, .po, .pox.
+# This must come before the language makefile fragments to allow them to
+# add suffixes and rules of their own.
+.SUFFIXES:
+.SUFFIXES: .c .o .po .pox .gmo
+
#
# Language makefile fragments.
@@ -813,11 +854,6 @@ LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _udivdi3 _umoddi3 _udiv_w_sdiv _udivmoddi4
# End of language makefile fragments.
#
-# The only suffixes we want for implicit rules are .c and .o, so clear
-# the list and add them. This speeds up GNU Make, and allows -r to work.
-# For i18n support, we also need .gmo, .po, .pox.
-.SUFFIXES:
-.SUFFIXES: .c .o .po .pox .gmo
Makefile: $(srcdir)/Makefile.in config.status $(srcdir)/version.c \
$(xmake_file) $(tmake_file) $(LANG_MAKEFILES)
@@ -833,22 +869,26 @@ tconfig.h: cs-tconfig.h ; @true
tm_p.h: cs-tm_p.h ; @true
cs-config.h: Makefile
- HEADERS="$(host_xm_file)" DEFINES="$(host_xm_defines)" \
+ TM_DEFINES="$(tm_defines)" \
+ HEADERS="$(host_xm_file)" XM_DEFINES="$(host_xm_defines)" \
TARGET_CPU_DEFAULT="$(target_cpu_default)" \
$(SHELL) $(srcdir)/mkconfig.sh config.h
cs-hconfig.h: Makefile
- HEADERS="$(build_xm_file)" DEFINES="$(build_xm_defines)" \
+ TM_DEFINES="$(tm_defines)" \
+ HEADERS="$(build_xm_file)" XM_DEFINES="$(build_xm_defines)" \
TARGET_CPU_DEFAULT="$(target_cpu_default)" \
$(SHELL) $(srcdir)/mkconfig.sh hconfig.h
cs-tconfig.h: Makefile
- HEADERS="$(xm_file)" DEFINES="$(xm_defines)" \
+ TM_DEFINES="$(tm_defines)" \
+ HEADERS="$(xm_file)" XM_DEFINES="$(xm_defines)" \
TARGET_CPU_DEFAULT="" \
$(SHELL) $(srcdir)/mkconfig.sh tconfig.h
cs-tm_p.h: Makefile
- HEADERS="$(tm_p_file)" DEFINES="" TARGET_CPU_DEFAULT="" \
+ TM_DEFINES="" \
+ HEADERS="$(tm_p_file)" XM_DEFINES="" TARGET_CPU_DEFAULT="" \
$(SHELL) $(srcdir)/mkconfig.sh tm_p.h
# Don't automatically run autoconf, since configure.in might be accidentally
@@ -865,6 +905,9 @@ gccbug: $(srcdir)/gccbug.in
mklibgcc: $(srcdir)/mklibgcc.in
CONFIG_FILES=mklibgcc CONFIG_HEADERS= ./config.status
+mkheaders: $(srcdir)/mkheaders.in
+ CONFIG_FILES=mkheaders CONFIG_HEADERS= ./config.status
+
# cstamp-h.in controls rebuilding of config.in.
# It is named cstamp-h.in and not stamp-h.in so the mostlyclean rule doesn't
# delete it. A stamp file is needed as autoheader won't update the file if
@@ -899,8 +942,6 @@ config.status: $(srcdir)/configure $(srcdir)/config.gcc version.c
all.internal: start.encap rest.encap doc
# This is what to compile if making a cross-compiler.
-# Note that we can compile enquire using the cross-compiler just built,
-# although we can't run it on this machine.
all.cross: native gcc-cross cpp$(exeext) specs \
$(LIBGCC) $(EXTRA_PARTS) lang.all.cross doc
# This is what must be made before installing GCC and converting libraries.
@@ -914,7 +955,7 @@ native: config.status auto-host.h intl.all build-@POSUB@ $(LANGUAGES) \
$(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(USE_COLLECT2)
# Define the names for selecting languages in LANGUAGES.
-C c: cc1$(exeext) tradcpp0$(exeext)
+C c: cc1$(exeext)
PROTO: proto
# Tell GNU make these are phony targets.
@@ -979,7 +1020,7 @@ xlimits.h: glimits.h limitx.h limity.h
LIB2ADD = $(LIB2FUNCS_EXTRA)
LIB2ADD_ST = $(LIB2FUNCS_STATIC_EXTRA)
-libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) xgcc$(exeext)
+libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) xgcc$(exeext) specs
objext='$(objext)' \
LIB1ASMFUNCS='$(LIB1ASMFUNCS)' \
LIB2FUNCS_1='$(LIB2FUNCS_1)' \
@@ -994,6 +1035,8 @@ libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) xgcc$(exeext
LIB2_DIVMOD_FUNCS='$(LIB2_DIVMOD_FUNCS)' \
DPBIT='$(DPBIT)' \
DPBIT_FUNCS='$(DPBIT_FUNCS)' \
+ TPBIT='$(TPBIT)' \
+ TPBIT_FUNCS='$(TPBIT_FUNCS)' \
MULTILIBS=`$(GCC_FOR_TARGET) --print-multi-lib` \
EXTRA_MULTILIB_PARTS='$(EXTRA_MULTILIB_PARTS)' \
SHLIB_LINK='$(SHLIB_LINK)' \
@@ -1013,12 +1056,13 @@ libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) xgcc$(exeext
LIBGCC_DEPS = $(GCC_PASSES) $(LANGUAGES) stmp-int-hdrs $(STMP_FIXPROTO) \
libgcc.mk $(srcdir)/libgcc2.c $(TCONFIG_H) \
$(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs \
- tsystem.h $(FPBIT) $(DPBIT) $(LIB2ADD) $(LIB2ADD_ST) $(LIB2ADDEH) \
- $(LIB2ADDEHDEP) $(EXTRA_PARTS) $(srcdir)/config/$(LIB1ASMSRC)
+ tsystem.h $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \
+ $(LIB2ADD_ST) $(LIB2ADDEH) $(LIB2ADDEHDEP) $(EXTRA_PARTS) \
+ $(srcdir)/config/$(LIB1ASMSRC)
libgcc.a: $(LIBGCC_DEPS)
$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
- HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \
+ BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
AR_FOR_TARGET="$(AR_FOR_TARGET)" \
AR_CREATE_FOR_TARGET="$(AR_CREATE_FOR_TARGET)" \
AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \
@@ -1060,7 +1104,7 @@ s-mlib: $(srcdir)/genmultilib Makefile
# Build multiple copies of libgcc.a, one for each target switch.
stmp-multilib: $(LIBGCC_DEPS)
$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
- HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \
+ BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
AR_FOR_TARGET="$(AR_FOR_TARGET)" \
AR_CREATE_FOR_TARGET="$(AR_CREATE_FOR_TARGET)" \
AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \
@@ -1132,8 +1176,9 @@ s-crt0: $(CRT0_S) $(MCRT0_S) $(GCC_PASSES) $(CONFIG_H)
c-errors.o: c-errors.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) flags.h \
diagnostic.h $(TM_P_H)
-c-parse.o : $(srcdir)/c-parse.c $(CONFIG_H) $(TREE_H) c-lex.h $(GGC_H) intl.h \
- $(C_TREE_H) input.h flags.h $(SYSTEM_H) toplev.h output.h $(CPPLIB_H)
+c-parse.o : $(srcdir)/c-parse.c $(CONFIG_H) $(TREE_H) $(GGC_H) intl.h \
+ $(C_TREE_H) input.h flags.h $(SYSTEM_H) toplev.h output.h $(CPPLIB_H) \
+ gt-c-parse.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-c $(srcdir)/c-parse.c $(OUTPUT_OPTION)
@@ -1155,32 +1200,34 @@ $(srcdir)/c-parse.y: c-parse.in
$(SHELL) $(srcdir)/move-if-change tmp-c-parse.y $(srcdir)/c-parse.y
c-decl.o : c-decl.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) $(C_TREE_H) \
- $(GGC_H) $(TARGET_H) c-lex.h flags.h function.h output.h $(EXPR_H) \
- debug.h toplev.h intl.h $(TM_P_H) tree-inline.h $(TIMEVAR_H) c-pragma.h
+ $(GGC_H) $(TARGET_H) flags.h function.h output.h $(EXPR_H) \
+ debug.h toplev.h intl.h $(TM_P_H) tree-inline.h $(TIMEVAR_H) c-pragma.h \
+ gt-c-decl.h libfuncs.h except.h
c-typeck.o : c-typeck.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
$(TARGET_H) flags.h intl.h output.h $(EXPR_H) $(RTL_H) toplev.h $(TM_P_H)
c-lang.o : c-lang.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
- langhooks.h langhooks-def.h
-c-lex.o : c-lex.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) c-lex.h \
- debug.h $(C_TREE_H) \
+ $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) c-common.h gtype-c.h
+c-lex.o : c-lex.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) \
+ debug.h $(C_TREE_H) c-common.h real.h \
c-pragma.h input.h intl.h flags.h toplev.h output.h \
mbchar.h $(CPPLIB_H) $(EXPR_H) $(TM_P_H)
c-objc-common.o : c-objc-common.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
$(C_TREE_H) $(RTL_H) insn-config.h integrate.h $(EXPR_H) $(C_TREE_H) \
flags.h toplev.h tree-inline.h diagnostic.h integrate.h $(VARRAY_H) \
- $(GGC_H)
+ langhooks.h $(GGC_H) gt-c-objc-common.h $(TARGET_H)
c-aux-info.o : c-aux-info.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
flags.h toplev.h
-c-convert.o : c-convert.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h toplev.h
+c-convert.o : c-convert.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h toplev.h \
+ $(C_COMMON_H)
c-pragma.o: c-pragma.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) function.h \
- c-pragma.h toplev.h output.h $(GGC_H) $(TM_P_H) $(C_COMMON_H)
+ c-pragma.h toplev.h output.h $(GGC_H) $(TM_P_H) $(C_COMMON_H) gt-c-pragma.h
mbchar.o: mbchar.c $(CONFIG_H) $(SYSTEM_H) mbchar.h
graph.o: graph.c $(CONFIG_H) $(SYSTEM_H) toplev.h flags.h output.h $(RTL_H) \
function.h hard-reg-set.h $(BASIC_BLOCK_H) graph.h
sbitmap.o: sbitmap.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h hard-reg-set.h \
$(BASIC_BLOCK_H)
-COLLECT2_OBJS = collect2.o tlink.o hash.o intl.o underscore.o version.o
+COLLECT2_OBJS = collect2.o tlink.o intl.o version.o
COLLECT2_LIBS = @COLLECT2_LIBS@
collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
# Don't try modifying collect2 (aka ld) in place--it might be linking this.
@@ -1194,44 +1241,36 @@ collect2.o : collect2.c $(CONFIG_H) $(SYSTEM_H) gstab.h intl.h \
-DTARGET_MACHINE=\"$(target_alias)\" \
-c $(srcdir)/collect2.c $(OUTPUT_OPTION)
-tlink.o: tlink.c $(DEMANGLE_H) hash.h $(CONFIG_H) $(SYSTEM_H) collect2.h intl.h
-hash.o: hash.c hash.h $(SYSTEM_H) toplev.h $(GCONFIG_H)
- $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-
-underscore.c: s-under ; @true
-
-s-under: $(GCC_PASSES)
- echo "int xxy_us_dummy;" >tmp-dum.c
- $(GCC_FOR_TARGET) -S tmp-dum.c
- echo '/*WARNING: This file is automatically generated!*/' >tmp-under.c
- if grep _xxy_us_dummy tmp-dum.s > /dev/null ; then \
- echo "int prepends_underscore = 1;" >>tmp-under.c; \
- else \
- echo "int prepends_underscore = 0;" >>tmp-under.c; \
- fi
- $(SHELL) $(srcdir)/move-if-change tmp-under.c underscore.c
- -rm -f tmp-dum.c tmp-dum.s
- $(STAMP) s-under
+tlink.o: tlink.c $(DEMANGLE_H) $(HASHTAB_H) $(CONFIG_H) $(SYSTEM_H) \
+ $(OBSTACK_H) collect2.h intl.h
# A file used by all variants of C.
c-common.o : c-common.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(OBSTACK_H) \
$(C_COMMON_H) flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
$(EXPR_H) $(TM_P_H) builtin-types.def builtin-attrs.def $(TARGET_H) \
- diagnostic.h tree-inline.h $(LANGHOOKS_DEF_H)
+ diagnostic.h except.h gt-c-common.h real.h langhooks.h c-tree.h
+c-pretty-print.o : c-pretty-print.c c-pretty-print.h pretty-print.h \
+ $(C_COMMON_H) $(CONFIG_H) $(SYSTEM_H) real.h
+
+c-opts.o : c-opts.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_COMMON_H) \
+ c-pragma.h flags.h toplev.h langhooks.h tree-inline.h diagnostic.h \
+ intl.h
# A file used by all variants of C and some other languages.
-attribs.o : attribs.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(OBSTACK_H) flags.h \
+attribs.o : attribs.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h \
toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) $(EXPR_H) $(TM_P_H) \
- builtin-types.def $(TARGET_H)
+ builtin-types.def $(TARGET_H) langhooks.h
-c-format.o : c-format.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
+c-format.o : c-format.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) langhooks.h \
$(C_COMMON_H) flags.h toplev.h intl.h diagnostic.h
c-semantics.o : c-semantics.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
- c-lex.h flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
- $(EXPR_H)
+ flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
+ $(EXPR_H) $(PREDICT_H)
+
+c-dump.o : c-dump.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) tree-dump.h
# Language-independent files.
@@ -1242,6 +1281,7 @@ DRIVER_DEFINES = \
-DDEFAULT_TARGET_MACHINE=\"$(target_alias)\" \
-DSTANDARD_BINDIR_PREFIX=\"$(bindir)/\" \
-DTOOLDIR_BASE_PREFIX=\"$(unlibsubdir)/../\" \
+ $(VALGRIND_DRIVER_DEFINES) \
`test "X$${SHLIB_LINK}" = "X" || test "@enable_shared@" != "yes" || echo "-DENABLE_SHARED_LIBGCC"` \
`test "X$${SHLIB_MULTILIB}" = "X" || echo "-DNO_SHARED_LIBGCC_MULTILIB"`
@@ -1264,7 +1304,7 @@ cppspec.o: cppspec.c $(CONFIG_H) $(SYSTEM_H) $(GCC_H)
tree-check.h: s-check ; @true
s-check : gencheck$(build_exeext) $(srcdir)/move-if-change
- ./gencheck$(build_exeext) > tmp-check.h
+ $(RUN_GEN) ./gencheck$(build_exeext) > tmp-check.h
$(SHELL) $(srcdir)/move-if-change tmp-check.h tree-check.h
$(STAMP) s-check
@@ -1305,17 +1345,23 @@ dumpvers: dumpvers.c
version.o: version.c version.h
+gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_H) varray.h $(HASHTAB_H) \
+ $(TREE_H) $(RTL_H) function.h insn-config.h $(EXPR_H) $(OPTABS_H) \
+ libfuncs.h debug.h $(GGC_H) bitmap.h $(BASIC_BLOCK_H) hard-reg-set.h \
+ ssa.h cselib.h insn-addr.h
+
ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
- flags.h $(GGC_H) varray.h hash.h $(HASHTAB_H) $(TM_P_H)
+ flags.h $(GGC_H) varray.h $(HASHTAB_H) $(TM_P_H) langhooks.h \
+ $(PARAMS_H)
ggc-simple.o: ggc-simple.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
- $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H)
+ $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H)
ggc-page.o: ggc-page.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
- toplev.h $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H)
+ toplev.h $(GGC_H) $(TIMEVAR_H) $(TM_P_H)
stringpool.o: stringpool.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(OBSTACK_H) \
- flags.h toplev.h
+ flags.h toplev.h $(GGC_H)
hashtable.o: hashtable.c hashtable.h $(CONFIG_H) $(SYSTEM_H) $(OBSTACK_H)
@@ -1329,13 +1375,15 @@ prefix.o: prefix.c $(CONFIG_H) $(SYSTEM_H) Makefile prefix.h
-DPREFIX=\"$(prefix)\" \
-c $(srcdir)/prefix.c $(OUTPUT_OPTION)
-convert.o: convert.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h convert.h toplev.h
+convert.o: convert.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h convert.h \
+ toplev.h langhooks.h
langhooks.o : langhooks.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) toplev.h \
tree-inline.h $(RTL_H) insn-config.h integrate.h langhooks.h \
$(LANGHOOKS_DEF_H) flags.h
tree.o : tree.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h function.h toplev.h \
- $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H) langhooks.h
+ $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H) langhooks.h \
+ real.h gt-tree.h
tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
flags.h langhooks.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
$(EXPR_H) $(SPLAY_TREE_H) tree-dump.h
@@ -1344,21 +1392,22 @@ tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) \
$(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h langhooks.h \
$(C_COMMON_H) tree-inline.h
print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(GGC_H) \
- langhooks.h
+ langhooks.h real.h
stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h \
- function.h $(EXPR_H) $(RTL_H) toplev.h $(GGC_H) $(TM_P_H) $(TARGET_H)
-fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h \
- toplev.h $(HASHTAB_H) $(EXPR_H) $(RTL_H) $(GGC_H) $(TM_P_H)
+ function.h $(EXPR_H) $(RTL_H) toplev.h $(GGC_H) $(TM_P_H) $(TARGET_H) \
+ langhooks.h
+fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h real.h \
+ toplev.h $(HASHTAB_H) $(EXPR_H) $(RTL_H) $(GGC_H) $(TM_P_H) langhooks.h
diagnostic.o : diagnostic.c diagnostic.h real.h diagnostic.def \
$(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_P_H) flags.h $(GGC_H) \
- input.h toplev.h intl.h
+ input.h toplev.h intl.h langhooks.h $(LANGHOOKS_DEF_H)
toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) function.h \
flags.h xcoffout.h input.h $(INSN_ATTR_H) output.h diagnostic.h \
debug.h insn-config.h intl.h $(RECOG_H) Makefile toplev.h \
dwarf2out.h sdbout.h dbxout.h $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) \
graph.h $(LOOP_H) except.h $(REGS_H) $(TIMEVAR_H) $(lang_options_files) \
- ssa.h $(PARAMS_H) $(TM_P_H) reload.h dwarf2asm.h $(TARGET_H) halfpic.h \
- langhooks.h insn-flags.h options.h
+ ssa.h $(PARAMS_H) $(TM_P_H) reload.h dwarf2asm.h $(TARGET_H) \
+ langhooks.h insn-flags.h options.h cfglayout.h real.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DTARGET_NAME=\"$(target_alias)\" \
-c $(srcdir)/toplev.c $(OUTPUT_OPTION)
@@ -1370,69 +1419,73 @@ rtl-error.o: rtl-error.c system.h $(RTL_H) $(INSN_ATTR_H) insn-config.h \
rtl.o : rtl.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) real.h $(GGC_H) errors.h
$(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-print-rtl.o : print-rtl.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
- hard-reg-set.h $(BASIC_BLOCK_H)
- $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+print-rtl.o : print-rtl.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
+ hard-reg-set.h $(BASIC_BLOCK_H) real.h
+rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) toplev.h $(RTL_H) \
+ hard-reg-set.h $(TM_P_H) insn-config.h $(RECOG_H) real.h flags.h
-rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) toplev.h $(RTL_H) hard-reg-set.h $(TM_P_H)
errors.o : errors.c $(GCONFIG_H) $(SYSTEM_H) errors.h
$(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) flags.h \
- function.h $(EXPR_H) hard-reg-set.h $(REGS_H) $(OBSTACK_H) \
+ function.h $(EXPR_H) hard-reg-set.h $(REGS_H) \
output.h c-pragma.h toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
- $(HASHTAB_H) $(TARGET_H) langhooks.h
+ $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h real.h
function.o : function.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
function.h $(EXPR_H) libfuncs.h $(REGS_H) hard-reg-set.h \
- insn-config.h $(RECOG_H) output.h toplev.h except.h hash.h $(GGC_H) \
- $(TM_P_H) langhooks.h
+ insn-config.h $(RECOG_H) output.h toplev.h except.h $(HASHTAB_H) $(GGC_H) \
+ $(TM_P_H) langhooks.h gt-function.h
stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h function.h \
insn-config.h hard-reg-set.h $(EXPR_H) libfuncs.h except.h \
- $(LOOP_H) $(RECOG_H) toplev.h output.h varray.h $(GGC_H) $(TM_P_H)
+ $(LOOP_H) $(RECOG_H) toplev.h output.h varray.h $(GGC_H) $(TM_P_H) \
+ langhooks.h $(PREDICT_H) gt-stmt.h
except.o : except.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
- except.h function.h $(EXPR_H) libfuncs.h integrate.h \
+ except.h function.h $(EXPR_H) libfuncs.h integrate.h langhooks.h \
insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \
- dwarf2asm.h dwarf2out.h toplev.h $(HASHTAB_H) intl.h $(GGC_H)
+ dwarf2asm.h dwarf2out.h toplev.h $(HASHTAB_H) intl.h $(GGC_H) \
+ gt-except.h
expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h function.h \
$(REGS_H) $(EXPR_H) $(OPTABS_H) libfuncs.h insn-attr.h insn-config.h \
$(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
- except.h reload.h $(GGC_H) langhooks.h intl.h $(TM_P_H)
+ except.h reload.h $(GGC_H) langhooks.h intl.h $(TM_P_H) real.h
builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
$(TARGET_H) function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) insn-config.h \
$(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
- except.h $(TM_P_H) $(PREDICT_H) libfuncs.h
-calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h $(EXPR_H) \
- libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H)
+ except.h $(TM_P_H) $(PREDICT_H) libfuncs.h real.h langhooks.h
+calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
+ $(EXPR_H) langhooks.h $(TARGET_H) \
+ libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H) \
+ except.h
expmed.o : expmed.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
insn-config.h $(EXPR_H) $(OPTABS_H) $(RECOG_H) real.h \
- toplev.h $(TM_P_H)
+ toplev.h $(TM_P_H) langhooks.h
explow.o : explow.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
hard-reg-set.h insn-config.h $(EXPR_H) $(OPTABS_H) $(RECOG_H) \
- toplev.h function.h ggc.h $(TM_P_H)
+ toplev.h function.h ggc.h $(TM_P_H) gt-explow.h
optabs.o : optabs.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
insn-config.h $(EXPR_H) $(OPTABS_H) libfuncs.h $(RECOG_H) reload.h \
- toplev.h $(GGC_H) real.h $(TM_P_H) except.h hard-reg-set.h $(BASIC_BLOCK_H)
+ toplev.h $(GGC_H) real.h $(TM_P_H) except.h gt-optabs.h $(BASIC_BLOCK_H)
dbxout.o : dbxout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) flags.h \
$(REGS_H) debug.h $(TM_P_H) $(TARGET_H) function.h langhooks.h \
insn-config.h reload.h gstab.h xcoffout.h output.h dbxout.h toplev.h
-debug.o : debug.c $(CONFIG_H) $(SYSTEM_H)
+debug.o : debug.c debug.h $(CONFIG_H) $(SYSTEM_H)
sdbout.o : sdbout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) flags.h \
function.h $(EXPR_H) output.h hard-reg-set.h $(REGS_H) real.h \
- insn-config.h $(OBSTACK_H) xcoffout.h c-pragma.h ggc.h \
- sdbout.h toplev.h $(TM_P_H) except.h debug.h
+ insn-config.h xcoffout.h c-pragma.h ggc.h \
+ sdbout.h toplev.h $(TM_P_H) except.h debug.h langhooks.h gt-sdbout.h
dwarfout.o : dwarfout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) dwarf.h \
flags.h insn-config.h reload.h output.h toplev.h $(TM_P_H) \
debug.h langhooks.h
dwarf2out.o : dwarf2out.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) dwarf2.h \
- debug.h flags.h insn-config.h reload.h output.h diagnostic.h \
+ debug.h flags.h insn-config.h reload.h output.h diagnostic.h real.h \
hard-reg-set.h $(REGS_H) $(EXPR_H) libfuncs.h toplev.h dwarf2out.h varray.h \
- $(GGC_H) except.h dwarf2asm.h $(TM_P_H) langhooks.h
+ $(GGC_H) except.h dwarf2asm.h $(TM_P_H) langhooks.h $(HASHTAB_H) gt-dwarf2out.h
dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) flags.h $(RTL_H) $(TREE_H) \
- output.h dwarf2asm.h $(TM_P_H)
+ output.h dwarf2asm.h $(TM_P_H) $(GGC_H)
vmsdbgout.o : vmsdbgout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) flags.h \
- output.h vmsdbg.h debug.h langhooks.h
+ output.h vmsdbg.h debug.h langhooks.h function.h
xcoffout.o : xcoffout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) xcoffout.h \
- flags.h toplev.h output.h dbxout.h $(GGC_H)
+ flags.h toplev.h output.h dbxout.h $(GGC_H) $(TARGET_H)
emit-rtl.o : emit-rtl.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
function.h $(REGS_H) insn-config.h $(RECOG_H) real.h $(GGC_H) \
$(EXPR_H) $(srcdir)/../include/obstack.h hard-reg-set.h bitmap.h toplev.h \
@@ -1441,23 +1494,23 @@ real.o : real.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) toplev.h $(TM_P_H)
integrate.o : integrate.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
debug.h $(INTEGRATE_H) insn-config.h $(EXPR_H) real.h $(REGS_H) \
intl.h function.h output.h $(RECOG_H) except.h toplev.h $(LOOP_H) \
- $(PARAMS_H) $(TM_P_H) $(TARGET_H)
+ $(PARAMS_H) $(TM_P_H) $(TARGET_H) langhooks.h gt-integrate.h
jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h hard-reg-set.h $(REGS_H) \
insn-config.h $(RECOG_H) $(EXPR_H) real.h except.h function.h \
toplev.h $(INSN_ATTR_H) $(TM_P_H) reload.h $(PREDICT_H)
simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) \
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
- output.h function.h $(GGC_H) $(OBSTACK_H) $(TM_P_H)
+ output.h function.h $(GGC_H) $(OBSTACK_H) $(TM_P_H) $(TREE_H)
cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) \
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
- output.h function.h cselib.h $(GGC_H) $(OBSTACK_H) $(TM_P_H)
+ output.h function.h cselib.h $(GGC_H) $(TM_P_H) gt-cselib.h
cse.o : cse.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h function.h \
- $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H)
+ $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H) $(TIMEVAR_H)
gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) hard-reg-set.h \
flags.h real.h insn-config.h ggc.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) \
- function.h output.h toplev.h $(TM_P_H) $(PARAMS_H) except.h
+ function.h output.h toplev.h $(TM_P_H) $(PARAMS_H) except.h gt-gcse.h
sibcall.o : sibcall.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) function.h \
hard-reg-set.h flags.h insn-config.h $(RECOG_H) $(BASIC_BLOCK_H)
resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h $(SYSTEM_H) \
@@ -1466,7 +1519,7 @@ resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h $(SYSTEM_H) \
lcm.o : lcm.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
real.h insn-config.h $(INSN_ATTR_H) $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) \
$(TM_P_H) df.h
-ssa.o : ssa.c $(CONFIG_H) $(SYSTEM_H) $(REGS_H) varray.h $(EXPR_H) \
+ssa.o : ssa.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) varray.h $(EXPR_H) \
hard-reg-set.h flags.h function.h real.h insn-config.h $(RECOG_H) \
$(BASIC_BLOCK_H) output.h ssa.h
ssa-dce.o : ssa-dce.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) hard-reg-set.h \
@@ -1481,7 +1534,8 @@ conflict.o : conflict.c $(CONFIG_H) $(SYSTEM_H) $(OBSTACK_H) $(HASHTAB_H) \
$(RTL_H) hard-reg-set.h $(BASIC_BLOCK_H)
profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
insn-config.h output.h $(REGS_H) $(EXPR_H) function.h \
- gcov-io.h toplev.h $(GGC_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TARGET_H)
+ gcov-io.h toplev.h $(GGC_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TARGET_H) \
+ langhooks.h profile.h libfuncs.h gt-profile.h
loop.o : loop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h $(LOOP_H) \
insn-config.h $(REGS_H) hard-reg-set.h $(RECOG_H) $(EXPR_H) \
real.h $(PREDICT_H) $(BASIC_BLOCK_H) function.h \
@@ -1490,7 +1544,7 @@ doloop.o : doloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h $(LOOP_H) \
$(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TM_P_H) toplev.h
unroll.o : unroll.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) insn-config.h function.h \
$(INTEGRATE_H) $(REGS_H) $(RECOG_H) flags.h $(EXPR_H) $(LOOP_H) toplev.h \
- hard-reg-set.h varray.h $(BASIC_BLOCK_H) $(TM_P_H) $(PREDICT_H)
+ hard-reg-set.h varray.h $(BASIC_BLOCK_H) $(TM_P_H) $(PREDICT_H) $(PARAMS_H)
flow.o : flow.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h insn-config.h \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
function.h except.h $(EXPR_H) ssa.h $(GGC_H) $(TM_P_H)
@@ -1499,19 +1553,20 @@ cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h insn-config.h \
function.h except.h $(GGC_H) $(TM_P_H)
cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h insn-config.h \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
- function.h except.h $(GGC_H) $(TM_P_H)
+ function.h except.h $(GGC_H) $(TM_P_H) insn-config.h
cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(BASIC_BLOCK_H) \
hard-reg-set.h insn-config.h $(RECOG_H) $(GGC_H) $(TM_P_H)
cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h insn-config.h \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
- function.h except.h $(GGC_H)
+ function.h except.h $(GGC_H)
cfgcleanup.o : cfgcleanup.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TIMEVAR_H)\
$(BASIC_BLOCK_H) hard-reg-set.h output.h flags.h $(RECOG_H) toplev.h \
- $(GGC_H) insn-config.h cselib.h $(TARGET_H) $(TM_P_H)
+ $(GGC_H) insn-config.h cselib.h $(TARGET_H) $(TM_P_H) $(PARAMS_H)
cfgloop.o : cfgloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
$(BASIC_BLOCK_H) hard-reg-set.h
dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) hard-reg-set.h \
- $(BASIC_BLOCK_H)
+ $(BASIC_BLOCK_H) et-forest.h
+et-forest.o : et-forest.c $(CONFIG_H) $(SYSTEM_H) et-forest.h
combine.o : combine.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h function.h \
insn-config.h $(INSN_ATTR_H) $(REGS_H) $(EXPR_H) \
$(BASIC_BLOCK_H) $(RECOG_H) real.h hard-reg-set.h toplev.h $(TM_P_H)
@@ -1521,14 +1576,27 @@ regclass.o : regclass.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) hard-reg-set.h flags.h
local-alloc.o : local-alloc.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \
output.h function.h $(INSN_ATTR_H) toplev.h except.h $(TM_P_H)
-bitmap.o : bitmap.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h $(BASIC_BLOCK_H) \
- $(REGS_H)
+bitmap.o : bitmap.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h \
+ $(BASIC_BLOCK_H) $(REGS_H) $(GGC_H)
$(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
global.o : global.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h reload.h function.h \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h output.h toplev.h \
$(TM_P_H)
-varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) varray.h $(RTL_H) $(TREE_H) bitmap.h \
- errors.h
+varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) varray.h $(GGC_H) errors.h
+ra.o : ra.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_P_H) insn-config.h \
+ $(RECOG_H) integrate.h function.h $(REGS_H) $(OBSTACK_H) hard-reg-set.h \
+ $(BASIC_BLOCK_H) df.h expr.h output.h toplev.h flags.h reload.h ra.h
+ra-build.o : ra-build.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_P_H) \
+ insn-config.h $(RECOG_H) function.h $(REGS_H) hard-reg-set.h \
+ $(BASIC_BLOCK_H) df.h output.h ggc.h ra.h gt-ra-build.h reload.h
+ra-colorize.o : ra-colorize.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_P_H) \
+ function.h $(REGS_H) hard-reg-set.h $(BASIC_BLOCK_H) df.h output.h ra.h
+ra-debug.o : ra-debug.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) insn-config.h \
+ $(RECOG_H) function.h hard-reg-set.h $(BASIC_BLOCK_H) df.h output.h ra.h \
+ $(TM_P_H)
+ra-rewrite.o : ra-rewrite.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_P_H) \
+ function.h $(REGS_H) hard-reg-set.h $(BASIC_BLOCK_H) df.h expr.h \
+ output.h except.h ra.h reload.h insn-config.h
reload.o : reload.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h output.h \
$(EXPR_H) $(OPTABS_H) reload.h $(RECOG_H) hard-reg-set.h insn-config.h \
$(REGS_H) function.h real.h toplev.h $(TM_P_H)
@@ -1544,7 +1612,8 @@ reorg.o : reorg.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) conditions.h hard-reg-set.h \
$(RECOG_H) function.h flags.h output.h $(EXPR_H) toplev.h $(PARAMS_H) $(TM_P_H)
alias.o : alias.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h hard-reg-set.h \
$(BASIC_BLOCK_H) $(REGS_H) toplev.h output.h $(EXPR_H) \
- $(GGC_H) function.h cselib.h $(TREE_H) $(TM_P_H) langhooks.h
+ $(GGC_H) function.h cselib.h $(TREE_H) $(TM_P_H) langhooks.h $(TARGET_H) \
+ gt-alias.h
regmove.o : regmove.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) insn-config.h \
$(RECOG_H) output.h $(REGS_H) hard-reg-set.h flags.h function.h \
$(EXPR_H) $(BASIC_BLOCK_H) toplev.h $(TM_P_H) except.h reload.h
@@ -1556,28 +1625,33 @@ sched-deps.o : sched-deps.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) sched-int.h \
$(INSN_ATTR_H) toplev.h $(RECOG_H) except.h cselib.h $(PARAMS_H) $(TM_P_H)
sched-rgn.o : sched-rgn.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) sched-int.h \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h function.h \
- $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H)
+ $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H) $(TARGET_H)
sched-ebb.o : sched-ebb.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) sched-int.h \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h function.h \
$(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H)
sched-vis.o : sched-vis.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) sched-int.h \
- hard-reg-set.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(REGS_H) $(TM_P_H)
+ hard-reg-set.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(REGS_H) $(TM_P_H) \
+ $(TARGET_H) real.h
final.o : final.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h intl.h \
$(REGS_H) $(RECOG_H) conditions.h insn-config.h $(INSN_ATTR_H) function.h \
- real.h output.h hard-reg-set.h except.h debug.h xcoffout.h \
+ real.h output.h hard-reg-set.h except.h debug.h xcoffout.h profile.h \
toplev.h reload.h dwarf2out.h $(BASIC_BLOCK_H) $(TM_P_H) $(TARGET_H) $(EXPR_H)
recog.o : recog.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) function.h $(BASIC_BLOCK_H) \
$(REGS_H) $(RECOG_H) $(EXPR_H) hard-reg-set.h flags.h insn-config.h \
$(INSN_ATTR_H) real.h toplev.h output.h reload.h $(TM_P_H)
reg-stack.o : reg-stack.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) $(RECOG_H) \
$(REGS_H) hard-reg-set.h flags.h insn-config.h toplev.h reload.h \
- varray.h function.h $(TM_P_H)
+ varray.h function.h $(TM_P_H) $(GGC_H) gt-reg-stack.h
predict.o: predict.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h \
- $(RECOG_H) function.h except.h $(EXPR_H) $(TM_P_H) $(PREDICT_H)
+ $(RECOG_H) function.h except.h $(EXPR_H) $(TM_P_H) $(PREDICT_H) real.h \
+ $(PARAMS_H) $(TARGET_H)
lists.o: lists.c $(CONFIG_H) $(SYSTEM_H) toplev.h $(RTL_H) $(GGC_H)
bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
flags.h $(BASIC_BLOCK_H) hard-reg-set.h output.h cfglayout.h $(TARGET_H)
+tracer.o : tracer.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
+ $(BASIC_BLOCK_H) hard-reg-set.h output.h cfglayout.h flags.h \
+ $(PARAMS_H) profile.h
cfglayout.o : cfglayout.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
insn-config.h $(BASIC_BLOCK_H) hard-reg-set.h output.h function.h \
cfglayout.h
@@ -1587,9 +1661,7 @@ regrename.o : regrename.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) insn-config.h \
resource.h $(OBSTACK_H) flags.h $(TM_P_H)
ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) toplev.h \
flags.h insn-config.h function.h $(RECOG_H) $(BASIC_BLOCK_H) $(EXPR_H) \
- output.h except.h $(TM_P_H)
-dependence.o : dependence.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
- $(C_COMMON_H) flags.h varray.h $(EXPR_H)
+ output.h except.h $(TM_P_H) real.h
params.o : params.c $(CONFIG_H) $(SYSTEM_H) $(PARAMS_H) toplev.h
hooks.o: hooks.c $(CONFIG_H) $(SYSTEM_H) $(HOOKS_H)
@@ -1612,9 +1684,6 @@ mips-tdump: mips-tdump.o version.o $(LIBDEPS)
mips-tdump.o : mips-tdump.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H)
-# Build file to support OSF/rose half-pic format.
-halfpic.o: halfpic.c $(CONFIG_H) $(RTL_H) $(TREE_H) $(SYSTEM_H) halfpic.h
-
#
# Generate header and source files from the machine description,
# and compile them.
@@ -1644,25 +1713,40 @@ halfpic.o: halfpic.c $(CONFIG_H) $(RTL_H) $(TREE_H) $(SYSTEM_H) halfpic.h
insn-config.h: s-config ; @true
s-config : $(md_file) genconfig$(build_exeext) $(srcdir)/move-if-change
- ./genconfig$(build_exeext) $(md_file) > tmp-config.h
+ $(RUN_GEN) ./genconfig$(build_exeext) $(md_file) > tmp-config.h
$(SHELL) $(srcdir)/move-if-change tmp-config.h insn-config.h
$(STAMP) s-config
+insn-conditions.c: s-conditions ; @true
+s-conditions : $(md_file) genconditions$(build_exeext) $(srcdir)/move-if-change
+ $(RUN_GEN) ./genconditions$(build_exeext) $(md_file) > tmp-conditions.c
+ $(SHELL) $(srcdir)/move-if-change tmp-conditions.c insn-conditions.c
+ $(STAMP) s-conditions
+
+insn-conditions.o : insn-conditions.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) \
+ $(TM_P_H) $(REGS_H) function.h $(RECOG_H) real.h output.h flags.h \
+ hard-reg-set.h resource.h toplev.h reload.h gensupport.h insn-constants.h
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) insn-conditions.c
+
+dummy-conditions.o : dummy-conditions.c $(HCONFIG_H) $(SYSTEM_H) gensupport.h
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/dummy-conditions.c $(OUTPUT_OPTION)
+
insn-flags.h: s-flags ; @true
s-flags : $(md_file) genflags$(build_exeext) $(srcdir)/move-if-change
- ./genflags$(build_exeext) $(md_file) > tmp-flags.h
+ $(RUN_GEN) ./genflags$(build_exeext) $(md_file) > tmp-flags.h
$(SHELL) $(srcdir)/move-if-change tmp-flags.h insn-flags.h
$(STAMP) s-flags
insn-codes.h: s-codes ; @true
s-codes : $(md_file) gencodes$(build_exeext) $(srcdir)/move-if-change
- ./gencodes$(build_exeext) $(md_file) > tmp-codes.h
+ $(RUN_GEN) ./gencodes$(build_exeext) $(md_file) > tmp-codes.h
$(SHELL) $(srcdir)/move-if-change tmp-codes.h insn-codes.h
$(STAMP) s-codes
insn-constants.h: s-constants ; @true
s-constants : $(md_file) genconstants$(build_exeext) $(srcdir)/move-if-change
- ./genconstants$(build_exeext) $(md_file) > tmp-constants.h
+ $(RUN_GEN) ./genconstants$(build_exeext) $(md_file) > tmp-constants.h
$(SHELL) $(srcdir)/move-if-change tmp-constants.h insn-constants.h
$(STAMP) s-constants
@@ -1674,7 +1758,7 @@ insn-emit.o : insn-emit.c $(CONFIG_H) $(RTL_H) $(EXPR_H) real.h output.h \
insn-emit.c: s-emit ; @true
s-emit : $(md_file) genemit$(build_exeext) $(srcdir)/move-if-change
- ./genemit$(build_exeext) $(md_file) > tmp-emit.c
+ $(RUN_GEN) ./genemit$(build_exeext) $(md_file) > tmp-emit.c
$(SHELL) $(srcdir)/move-if-change tmp-emit.c insn-emit.c
$(STAMP) s-emit
@@ -1686,7 +1770,7 @@ insn-recog.o : insn-recog.c $(CONFIG_H) $(RTL_H) insn-config.h $(RECOG_H) \
insn-recog.c: s-recog ; @true
s-recog : $(md_file) genrecog$(build_exeext) $(srcdir)/move-if-change
- ./genrecog$(build_exeext) $(md_file) > tmp-recog.c
+ $(RUN_GEN) ./genrecog$(build_exeext) $(md_file) > tmp-recog.c
$(SHELL) $(srcdir)/move-if-change tmp-recog.c insn-recog.c
$(STAMP) s-recog
@@ -1697,7 +1781,7 @@ insn-opinit.o : insn-opinit.c $(CONFIG_H) $(RTL_H) \
insn-opinit.c: s-opinit ; @true
s-opinit : $(md_file) genopinit$(build_exeext) $(srcdir)/move-if-change
- ./genopinit$(build_exeext) $(md_file) > tmp-opinit.c
+ $(RUN_GEN) ./genopinit$(build_exeext) $(md_file) > tmp-opinit.c
$(SHELL) $(srcdir)/move-if-change tmp-opinit.c insn-opinit.c
$(STAMP) s-opinit
@@ -1708,7 +1792,7 @@ insn-extract.o : insn-extract.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) toplev.h \
insn-extract.c: s-extract ; @true
s-extract : $(md_file) genextract$(build_exeext) $(srcdir)/move-if-change
- ./genextract$(build_exeext) $(md_file) > tmp-extract.c
+ $(RUN_GEN) ./genextract$(build_exeext) $(md_file) > tmp-extract.c
$(SHELL) $(srcdir)/move-if-change tmp-extract.c insn-extract.c
$(STAMP) s-extract
@@ -1719,7 +1803,7 @@ insn-peep.o : insn-peep.c $(CONFIG_H) $(RTL_H) $(REGS_H) output.h real.h \
insn-peep.c: s-peep ; @true
s-peep : $(md_file) genpeep$(build_exeext) $(srcdir)/move-if-change
- ./genpeep$(build_exeext) $(md_file) > tmp-peep.c
+ $(RUN_GEN) ./genpeep$(build_exeext) $(md_file) > tmp-peep.c
$(SHELL) $(srcdir)/move-if-change tmp-peep.c insn-peep.c
$(STAMP) s-peep
@@ -1731,13 +1815,13 @@ insn-attrtab.o : insn-attrtab.c $(CONFIG_H) $(RTL_H) $(REGS_H) real.h \
insn-attr.h: s-attr ; @true
s-attr : $(md_file) genattr$(build_exeext) $(srcdir)/move-if-change
- ./genattr$(build_exeext) $(md_file) > tmp-attr.h
+ $(RUN_GEN) ./genattr$(build_exeext) $(md_file) > tmp-attr.h
$(SHELL) $(srcdir)/move-if-change tmp-attr.h insn-attr.h
$(STAMP) s-attr
insn-attrtab.c: s-attrtab ; @true
s-attrtab : $(md_file) genattrtab$(build_exeext) $(srcdir)/move-if-change
- ./genattrtab$(build_exeext) $(md_file) > tmp-attrtab.c
+ $(RUN_GEN) ./genattrtab$(build_exeext) $(md_file) > tmp-attrtab.c
$(SHELL) $(srcdir)/move-if-change tmp-attrtab.c insn-attrtab.c
$(STAMP) s-attrtab
@@ -1750,7 +1834,7 @@ insn-output.o : insn-output.c $(CONFIG_H) $(RTL_H) $(GGC_H) $(REGS_H) real.h \
insn-output.c: s-output ; @true
s-output : $(md_file) genoutput$(build_exeext) $(srcdir)/move-if-change
- ./genoutput$(build_exeext) $(md_file) > tmp-output.c
+ $(RUN_GEN) ./genoutput$(build_exeext) $(md_file) > tmp-output.c
$(SHELL) $(srcdir)/move-if-change tmp-output.c insn-output.c
$(STAMP) s-output
@@ -1759,19 +1843,83 @@ genrtl.c genrtl.h : s-genrtl
@true # force gnu make to recheck modification times.
s-genrtl: gengenrtl$(build_exeext) $(srcdir)/move-if-change $(RTL_BASE_H)
- ./gengenrtl$(build_exeext) -h > tmp-genrtl.h
+ $(RUN_GEN) ./gengenrtl$(build_exeext) -h > tmp-genrtl.h
$(SHELL) $(srcdir)/move-if-change tmp-genrtl.h genrtl.h
- ./gengenrtl$(build_exeext) > tmp-genrtl.c
+ $(RUN_GEN) ./gengenrtl$(build_exeext) > tmp-genrtl.c
$(SHELL) $(srcdir)/move-if-change tmp-genrtl.c genrtl.c
$(STAMP) s-genrtl
tm-preds.h: s-preds; @true
s-preds: genpreds$(build_exeext) $(srcdir)/move-if-change
- ./genpreds$(build_exeext) > tmp-preds.h
+ $(RUN_GEN) ./genpreds$(build_exeext) > tmp-preds.h
$(SHELL) $(srcdir)/move-if-change tmp-preds.h tm-preds.h
$(STAMP) s-preds
+GTFILES = $(GCONFIG_H) $(srcdir)/location.h \
+ $(HASHTAB_H) \
+ $(srcdir)/bitmap.h $(srcdir)/function.h $(srcdir)/rtl.h $(srcdir)/optabs.h \
+ $(srcdir)/tree.h $(srcdir)/libfuncs.h $(srcdir)/hashtable.h $(srcdir)/real.h \
+ $(srcdir)/varray.h $(srcdir)/ssa.h $(srcdir)/insn-addr.h $(srcdir)/cselib.h \
+ $(srcdir)/c-common.h $(srcdir)/c-tree.h \
+ $(srcdir)/basic-block.h \
+ $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c \
+ $(srcdir)/dwarf2out.c $(srcdir)/emit-rtl.c \
+ $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \
+ $(srcdir)/fold-const.c $(srcdir)/function.c \
+ $(srcdir)/gcse.c $(srcdir)/integrate.c $(srcdir)/lists.c $(srcdir)/optabs.c \
+ $(srcdir)/profile.c $(srcdir)/ra-build.c $(srcdir)/regclass.c \
+ $(srcdir)/reg-stack.c \
+ $(srcdir)/sdbout.c $(srcdir)/stmt.c $(srcdir)/stor-layout.c \
+ $(srcdir)/tree.c $(srcdir)/varasm.c \
+ $(out_file) \
+ @all_gtfiles@
+
+GTFILES_FILES_LANGS = @all_gtfiles_files_langs@
+GTFILES_FILES_FILES = @all_gtfiles_files_files@
+GTFILES_LANG_DIR_NAMES = @subdirs@
+GTFILES_SRCDIR = @srcdir@
+
+gtype-desc.h gtype-desc.c gt-except.h gt-function.h : s-gtype; @true
+gt-integrate.h gt-stmt.h gt-tree.h gt-varasm.h gt-emit-rtl.h : s-gtype; @true
+gt-explow.h gt-stor-layout.h gt-regclass.h gt-lists.h : s-gtype; @true
+gt-alias.h gt-cselib.h gt-fold-const.h gt-gcse.h gt-profile.h : s-gtype; @true
+gt-expr.h gt-sdbout.h gt-optabs.h gt-bitmap.h gt-dwarf2out.h : s-gtype ; @true
+gt-ra-build.h gt-reg-stack.h : s-gtype ; @true
+gt-c-common.h gt-c-decl.h gt-c-parse.h gt-c-pragma.h : s-gtype; @true
+gt-c-objc-common.h gtype-c.h gt-location.h : s-gtype ; @true
+
+gtyp-gen.h: Makefile
+ echo "/* This file is machine generated. Do not edit. */" > tmp-gtyp.h
+ echo "static const char *srcdir = " >> tmp-gtyp.h
+ echo "\"$(GTFILES_SRCDIR)\"" >> tmp-gtyp.h
+ echo ";" >> tmp-gtyp.h
+ echo "static const char *lang_files[] = {" >> tmp-gtyp.h
+ ll="$(GTFILES_FILES_FILES)"; \
+ for f in $$ll; do \
+ echo "\"$$f\", "; done >> tmp-gtyp.h
+ echo "NULL};" >> tmp-gtyp.h
+ echo "static const char *langs_for_lang_files[] = {" >> tmp-gtyp.h
+ ff="$(GTFILES_FILES_LANGS)"; \
+ for f in $$ff; do \
+ echo "\"$$f\", " ; done >> tmp-gtyp.h
+ echo "NULL};" >> tmp-gtyp.h
+ echo "static const char *all_files[] = {" >> tmp-gtyp.h
+ gf="$(GTFILES)"; \
+ for f in $$gf; do \
+ echo "\"$$f\", "; done >> tmp-gtyp.h
+ echo " NULL};" >> tmp-gtyp.h
+ echo "static const char *lang_dir_names[] = { \"c\", " >> tmp-gtyp.h
+ gf="$(GTFILES_LANG_DIR_NAMES)"; \
+ for l in $$gf; do \
+ echo "\"$$l\", "; done >> tmp-gtyp.h
+ echo "NULL};" >> tmp-gtyp.h
+ $(SHELL) $(srcdir)/move-if-change tmp-gtyp.h gtyp-gen.h
+
+s-gtype: gengtype$(build_exeext) $(GTFILES)
+ $(RUN_GEN) ./gengtype
+ $(STAMP) s-gtype
+
#
# Compile the programs that generate insn-* from the machine description.
# They are compiled with $(HOST_CC), and associated libraries,
@@ -1790,93 +1938,123 @@ read-rtl.o: read-rtl.c $(HCONFIG_H) $(SYSTEM_H) $(RTL_H) \
gensupport.o: gensupport.c $(RTL_H) $(OBSTACK_H) $(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gensupport.c $(OUTPUT_OPTION)
-genconfig$(build_exeext) : genconfig.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genconfig$(build_exeext) : genconfig.o $(HOST_RTL) $(HOST_SUPPORT) \
+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genconfig.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genconfig.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
+ $(HOST_ERRORS) $(HOST_LIBS)
genconfig.o : genconfig.c $(RTL_H) $(HCONFIG_H) \
$(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genconfig.c $(OUTPUT_OPTION)
-genflags$(build_exeext) : genflags.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genflags$(build_exeext) : genflags.o $(HOST_RTL) $(HOST_SUPPORT) \
+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genflags.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genflags.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
+ $(HOST_ERRORS) $(HOST_LIBS)
genflags.o : genflags.c $(RTL_H) $(OBSTACK_H) $(HCONFIG_H) \
$(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genflags.c $(OUTPUT_OPTION)
-gencodes$(build_exeext) : gencodes.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+gencodes$(build_exeext) : gencodes.o $(HOST_RTL) $(HOST_SUPPORT) \
+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- gencodes.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ gencodes.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
+ $(HOST_ERRORS) $(HOST_LIBS)
gencodes.o : gencodes.c $(RTL_H) $(HCONFIG_H) \
$(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gencodes.c $(OUTPUT_OPTION)
-genconstants$(build_exeext) : genconstants.o $(HOST_RTL) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genconstants$(build_exeext) : genconstants.o $(HOST_RTL) $(HOST_EARLY_SUPPORT) \
+ $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genconstants.o $(HOST_RTL) $(HOST_ERRORS) $(HOST_LIBS)
+ genconstants.o $(HOST_EARLY_SUPPORT) $(HOST_RTL) \
+ $(HOST_ERRORS) $(HOST_LIBS)
genconstants.o : genconstants.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genconstants.c $(OUTPUT_OPTION)
-genemit$(build_exeext) : genemit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genemit$(build_exeext) : genemit.o $(HOST_RTL) $(HOST_SUPPORT) \
+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genemit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genemit.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
+ $(HOST_ERRORS) $(HOST_LIBS)
genemit.o : genemit.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genemit.c $(OUTPUT_OPTION)
-genopinit$(build_exeext) : genopinit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genopinit$(build_exeext) : genopinit.o $(HOST_RTL) $(HOST_SUPPORT) \
+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genopinit.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genopinit.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
+ $(HOST_ERRORS) $(HOST_LIBS)
genopinit.o : genopinit.c $(RTL_H) $(HCONFIG_H) \
$(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genopinit.c $(OUTPUT_OPTION)
-genrecog$(build_exeext) : genrecog.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genrecog$(build_exeext) : genrecog.o $(HOST_RTL) $(HOST_SUPPORT) \
+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genrecog.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genrecog.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
+ $(HOST_ERRORS) $(HOST_LIBS)
genrecog.o : genrecog.c $(RTL_H) $(HCONFIG_H) \
$(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genrecog.c $(OUTPUT_OPTION)
-genextract$(build_exeext) : genextract.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genextract$(build_exeext) : genextract.o $(HOST_RTL) $(HOST_SUPPORT) \
+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genextract.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genextract.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
+ $(HOST_ERRORS) $(HOST_LIBS)
genextract.o : genextract.c $(RTL_H) $(HCONFIG_H) \
$(SYSTEM_H) insn-config.h errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genextract.c $(OUTPUT_OPTION)
-genpeep$(build_exeext) : genpeep.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genpeep$(build_exeext) : genpeep.o $(HOST_RTL) $(HOST_SUPPORT) \
+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genpeep.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genpeep.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
+ $(HOST_ERRORS) $(HOST_LIBS)
genpeep.o : genpeep.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genpeep.c $(OUTPUT_OPTION)
-genattr$(build_exeext) : genattr.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genattr$(build_exeext) : genattr.o $(HOST_RTL) $(HOST_SUPPORT) \
+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genattr.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genattr.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
+ $(HOST_ERRORS) $(HOST_LIBS)
genattr.o : genattr.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h gensupport.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattr.c $(OUTPUT_OPTION)
-genattrtab$(build_exeext) : genattrtab.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genattrtab$(build_exeext) : genattrtab.o genautomata.o \
+ $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_VARRAY) \
+ $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genattrtab.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genattrtab.o genautomata.o \
+ $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) \
+ $(HOST_VARRAY) $(HOST_LIBS) -lm
genattrtab.o : genattrtab.c $(RTL_H) $(OBSTACK_H) $(HCONFIG_H) \
- $(SYSTEM_H) errors.h $(GGC_H) gensupport.h
+ $(SYSTEM_H) errors.h $(GGC_H) gensupport.h genattrtab.h
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattrtab.c $(OUTPUT_OPTION)
-genoutput$(build_exeext) : genoutput.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
+genautomata.o : genautomata.c $(RTL_H) $(OBSTACK_H) $(HCONFIG_H) \
+ $(SYSTEM_H) errors.h varray.h genattrtab.h $(HASHTAB_H)
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genautomata.c $(OUTPUT_OPTION)
+
+genoutput$(build_exeext) : genoutput.o $(HOST_RTL) $(HOST_SUPPORT) \
+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
- genoutput.o $(HOST_RTL) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBS)
+ genoutput.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
+ $(HOST_ERRORS) $(HOST_LIBS)
genoutput.o : genoutput.c $(RTL_H) $(HCONFIG_H) \
$(SYSTEM_H) errors.h gensupport.h
@@ -1896,38 +2074,92 @@ genpreds$(build_exeext) : genpreds.o $(HOST_LIBDEPS)
genpreds.o : genpreds.c $(RTL_BASE_H) $(HCONFIG_H) $(SYSTEM_H)
$(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genpreds.c $(OUTPUT_OPTION)
+gengtype$(build_exeext) : gengtype.o gengtype-lex.o gengtype-yacc.o \
+ $(HOST_LIBDEPS)
+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
+ gengtype.o gengtype-lex.o gengtype-yacc.o $(HOST_LIBS)
+
+gengtype.o : gengtype.c gengtype.h $(HCONFIG_H) $(SYSTEM_H) real.h rtl.def \
+ gtyp-gen.h
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/gengtype.c $(OUTPUT_OPTION)
+
+gengtype-lex.o : $(srcdir)/gengtype-lex.c gengtype.h $(srcdir)/gengtype-yacc.c \
+ $(HCONFIG_H) $(SYSTEM_H)
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/gengtype-lex.c $(OUTPUT_OPTION)
+
+gengtype-yacc.o : $(srcdir)/gengtype-yacc.c gengtype.h $(HCONFIG_H) $(SYSTEM_H)
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/gengtype-yacc.c $(OUTPUT_OPTION)
+
+# The sed command works around a bug in flex-2.5.4.
+$(srcdir)/gengtype-lex.c : $(srcdir)/gengtype-lex.l
+ cd $(srcdir) && \
+ $(FLEX) $(FLEXFLAGS) -t -o$@ gengtype-lex.l | \
+ sed 's/^\(char msg\[\];\)/yyconst \1/' > g-$$$$ ; \
+ if test $$? -eq 0 ; then \
+ mv -f g-$$$$ gengtype-lex.c ; \
+ else \
+ rm -f g-$$$$.* ; \
+ false ; \
+ fi
+
+$(srcdir)/gengtype-yacc.c: $(srcdir)/gengtype-yacc.y
+ (cd $(srcdir) && \
+ $(BISON) $(BISONFLAGS) -d -o gengtype-yacc.c gengtype-yacc.y || \
+ ( rm -f $@ && false ) )
+
+genconditions$(build_exeext) : genconditions.o $(HOST_EARLY_SUPPORT) \
+ $(HOST_RTL) $(HOST_ERRORS) $(HOST_LIBDEPS)
+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
+ genconditions.o $(HOST_EARLY_SUPPORT) $(HOST_RTL) \
+ $(HOST_ERRORS) $(HOST_LIBS)
+
+genconditions.o : genconditions.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/genconditions.c $(OUTPUT_OPTION)
+
#
# Compile the libraries to be used by gen*.
# If we are not cross-building, gen* use the same .o's that cc1 will use,
-# and HOST_PREFIX_1 is `loser-', just to ensure these rules don't conflict
+# and BUILD_PREFIX_1 is `loser-', just to ensure these rules don't conflict
# with the rules for rtl.o, etc.
-$(HOST_PREFIX_1)rtl.o: $(srcdir)/rtl.c $(HCONFIG_H) $(SYSTEM_H) $(RTL_H) \
+$(BUILD_PREFIX_1)rtl.o: $(srcdir)/rtl.c $(HCONFIG_H) $(SYSTEM_H) $(RTL_H) \
real.h $(GGC_H) errors.h
- rm -f $(HOST_PREFIX)rtl.c
- sed -e 's/config[.]h/hconfig.h/' $(srcdir)/rtl.c > $(HOST_PREFIX)rtl.c
- $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)rtl.c $(OUTPUT_OPTION)
+ rm -f $(BUILD_PREFIX)rtl.c
+ sed -e 's/config[.]h/hconfig.h/' $(srcdir)/rtl.c > $(BUILD_PREFIX)rtl.c
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)rtl.c $(OUTPUT_OPTION)
-$(HOST_PREFIX_1)print-rtl.o: $(srcdir)/print-rtl.c $(HCONFIG_H) \
+print-rtl1.o: $(srcdir)/print-rtl.c $(HCONFIG_H) \
$(RTL_H) $(TREE_H) hard-reg-set.h $(BASIC_BLOCK_H)
- rm -f $(HOST_PREFIX)print-rtl.c
- sed -e 's/config[.]h/hconfig.h/' $(srcdir)/print-rtl.c > $(HOST_PREFIX)print-rtl.c
- $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)print-rtl.c $(OUTPUT_OPTION)
-
-$(HOST_PREFIX_1)bitmap.o: $(srcdir)/bitmap.c $(HCONFIG_H) $(SYSTEM_H) $(RTL_H) \
- flags.h $(BASIC_BLOCK_H) $(REGS_H)
- rm -f $(HOST_PREFIX)bitmap.c
- sed -e 's/config[.]h/hconfig.h/' $(srcdir)/bitmap.c > $(HOST_PREFIX)bitmap.c
- $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)bitmap.c $(OUTPUT_OPTION)
-
-$(HOST_PREFIX_1)errors.o: errors.c $(HCONFIG_H) $(SYSTEM_H) errors.h
- rm -f $(HOST_PREFIX)errors.c
- sed -e 's/config[.]h/hconfig.h/' $(srcdir)/errors.c > $(HOST_PREFIX)errors.c
- $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)errors.c $(OUTPUT_OPTION)
-
-$(HOST_PREFIX_1)ggc-none.o: ggc-none.c $(HCONFIG_H) $(SYSTEM_H) $(GCC_H)
- rm -f $(HOST_PREFIX)ggc-none.c
- sed -e 's/config[.]h/hconfig.h/' $(srcdir)/ggc-none.c > $(HOST_PREFIX)ggc-none.c
- $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)ggc-none.c $(OUTPUT_OPTION)
+ rm -f print-rtl1.c
+ sed -e 's/config[.]h/hconfig.h/' $(srcdir)/print-rtl.c > print-rtl1.c
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) print-rtl1.c $(OUTPUT_OPTION)
+
+$(BUILD_PREFIX_1)bitmap.o: $(srcdir)/bitmap.c $(HCONFIG_H) $(SYSTEM_H) \
+ $(RTL_H) flags.h $(BASIC_BLOCK_H) $(REGS_H) $(GGC_H)
+ rm -f $(BUILD_PREFIX)bitmap.c
+ sed -e 's/config[.]h/hconfig.h/' $(srcdir)/bitmap.c > $(BUILD_PREFIX)bitmap.c
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)bitmap.c $(OUTPUT_OPTION)
+
+$(BUILD_PREFIX_1)errors.o: errors.c $(HCONFIG_H) $(SYSTEM_H) errors.h
+ rm -f $(BUILD_PREFIX)errors.c
+ sed -e 's/config[.]h/hconfig.h/' $(srcdir)/errors.c > $(BUILD_PREFIX)errors.c
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)errors.c $(OUTPUT_OPTION)
+
+$(BUILD_PREFIX_1)varray.o: varray.c $(HCONFIG_H) $(SYSTEM_H) varray.h \
+ $(RTL_H) $(GGC_H) $(TREE_H) bitmap.h errors.h
+ rm -f $(BUILD_PREFIX)varray.c
+ sed -e 's/config[.]h/hconfig.h/' $(srcdir)/varray.c > \
+ $(BUILD_PREFIX)varray.c
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
+ $(BUILD_PREFIX)varray.c $(OUTPUT_OPTION)
+
+$(BUILD_PREFIX_1)ggc-none.o: ggc-none.c $(HCONFIG_H) $(SYSTEM_H) $(GGC_H)
+ rm -f $(BUILD_PREFIX)ggc-none.c
+ sed -e 's/config[.]h/hconfig.h/' $(srcdir)/ggc-none.c > $(BUILD_PREFIX)ggc-none.c
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)ggc-none.c $(OUTPUT_OPTION)
#
# Remake internationalization support.
@@ -1953,7 +2185,7 @@ intl.all intl.install: config.h insn-flags.h insn-constants.h
# Make-lang.in should add dependencies of po-generated on any generated
# files which need to be scanned by gettext (usually Yacc-generated parsers).
-po-generated: c-parse.c tradcif.c
+po-generated: c-parse.c
#
# Remake cpp and protoize.
@@ -1967,9 +2199,9 @@ PREPROCESSOR_DEFINES = \
-DCROSS_INCLUDE_DIR=\"$(gcc_tooldir)/sys-include\" \
-DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\"
-LIBCPP_OBJS = cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o \
- cpphash.o cpperror.o cppinit.o cppdefault.o \
- hashtable.o line-map.o mkdeps.o prefix.o version.o mbchar.o
+LIBCPP_OBJS = cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o cpptrad.o \
+ cpphash.o cpperror.o cppinit.o cppdefault.o cppmain.o \
+ hashtable.o line-map.o mkdeps.o prefix.o mbchar.o
LIBCPP_DEPS = $(CPPLIB_H) cpphash.h line-map.h hashtable.h intl.h \
$(OBSTACK_H) $(SYSTEM_H)
@@ -1981,11 +2213,7 @@ libcpp.a: $(LIBCPP_OBJS)
$(AR) $(AR_FLAGS) libcpp.a $(LIBCPP_OBJS)
-$(RANLIB) libcpp.a
-cpp0$(exeext): cppmain.o intl.o libcpp.a $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o cpp0$(exeext) cppmain.o \
- intl.o libcpp.a $(LIBS)
-
-cppmain.o: cppmain.c $(CONFIG_H) $(CPPLIB_H) intl.h $(SYSTEM_H)
+cppmain.o: cppmain.c $(CONFIG_H) $(LIBCPP_DEPS)
cpperror.o: cpperror.c $(CONFIG_H) $(LIBCPP_DEPS)
cppexp.o: cppexp.c $(CONFIG_H) $(LIBCPP_DEPS)
@@ -1993,9 +2221,10 @@ cpplex.o: cpplex.c $(CONFIG_H) $(LIBCPP_DEPS) mbchar.h
cppmacro.o: cppmacro.c $(CONFIG_H) $(LIBCPP_DEPS)
cpplib.o: cpplib.c $(CONFIG_H) $(LIBCPP_DEPS)
cpphash.o: cpphash.c $(CONFIG_H) $(LIBCPP_DEPS)
+cpptrad.o: cpptrad.c $(CONFIG_H) $(LIBCPP_DEPS)
cppfiles.o: cppfiles.c $(CONFIG_H) $(LIBCPP_DEPS) $(SPLAY_TREE_H) mkdeps.h
cppinit.o: cppinit.c $(CONFIG_H) $(LIBCPP_DEPS) cppdefault.h \
- mkdeps.h prefix.h version.h except.h
+ mkdeps.h prefix.h
cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) cppdefault.h Makefile
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
@@ -2004,20 +2233,6 @@ cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) cppdefault.h Makefile
mkdeps.o: mkdeps.c $(CONFIG_H) $(SYSTEM_H) mkdeps.h
-# The traditional mode preprocessor, a separate program for ease of
-# maintenance. Some code is shared with the ISO-C cpp.
-tradcpp0$(exeext): tradcpp.o tradcif.o cppdefault.o version.o intl.o \
- mkdeps.o $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o tradcpp0$(exeext) \
- tradcpp.o tradcif.o mkdeps.o cppdefault.o version.o intl.o $(LIBS)
-
-tradcpp.o: tradcpp.c $(CONFIG_H) $(SYSTEM_H) version.h cppdefault.h tradcpp.h
-tradcif.o: $(srcdir)/tradcif.c $(CONFIG_H) $(SYSTEM_H) tradcpp.h
-
-$(srcdir)/tradcif.c: $(srcdir)/tradcif.y
- (cd $(srcdir) && $(BISON) $(BISONFLAGS) -o tr$$$$.c tradcif.y && \
- mv -f tr$$$$.c tradcif.c)
-
# Note for the stamp targets, we run the program `true' instead of
# having an empty command (nothing following the semicolon).
@@ -2099,8 +2314,7 @@ gcov$(exeext): $(GCOV_OBJS) $(LIBDEPS)
# s-* so that mostlyclean does not force the include directory to
# be rebuilt.
-# Build the include directory including float.h (which no longer depends upon
-# enquire).
+# Build the include directory
stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) xlimits.h
# Copy in the headers provided with gcc.
# The sed command gets just the last file name component;
@@ -2120,11 +2334,6 @@ stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) xlimits.h
rm -f include/limits.h
cp xlimits.h include/limits.h
chmod a+r include/limits.h
- rm -f include/float.h
- if [ x$(FLOAT_H) != xMakefile.in ]; then \
- cp $(srcdir)/config/$(FLOAT_H) include/float.h && \
- chmod a+r include/float.h; \
- else :; fi
# Install the README
rm -f include/README
cp $(srcdir)/README-fixinc include/README
@@ -2146,7 +2355,7 @@ fixinc.sh: $(FIXINCSRCDIR)/mkfixinc.sh $(FIXINCSRCDIR)/fixincl.c \
$(FIXINCSRCDIR)/procopen.c $(FIXINCSRCDIR)/gnu-regex.c \
$(FIXINCSRCDIR)/server.c $(FIXINCSRCDIR)/gnu-regex.h \
$(FIXINCSRCDIR)/server.h $(FIXINCSRCDIR)/inclhack.def specs.ready
- (MAKE="$(MAKE)"; srcdir=`cd $(srcdir)/fixinc && pwd` ; \
+ (MAKE="$(MAKE)"; srcdir=`cd $(srcdir)/fixinc && ${PWD_COMMAND}` ; \
CC="$(HOST_CC)"; CFLAGS="$(HOST_CFLAGS)"; LDFLAGS="$(HOST_LDFLAGS)"; \
WARN_CFLAGS="$(WARN_CFLAGS)"; \
export MAKE srcdir CC CFLAGS LDFLAGS WARN_CFLAGS; cd ./fixinc && \
@@ -2156,10 +2365,10 @@ fixinc.sh: $(FIXINCSRCDIR)/mkfixinc.sh $(FIXINCSRCDIR)/fixincl.c \
stmp-fixinc: fixinc.sh gsyslimits.h
rm -rf include; mkdir include
-chmod a+rx include
- (TARGET_MACHINE='$(target)'; srcdir=`cd $(srcdir); pwd`; \
+ (TARGET_MACHINE='$(target)'; srcdir=`cd $(srcdir); ${PWD_COMMAND}`; \
SHELL='$(SHELL)' ;\
export TARGET_MACHINE srcdir SHELL ; \
- $(SHELL) ./fixinc.sh `pwd`/include $(SYSTEM_HEADER_DIR) $(OTHER_FIXINCLUDES_DIRS); \
+ $(SHELL) ./fixinc.sh `${PWD_COMMAND}`/include $(SYSTEM_HEADER_DIR) $(OTHER_FIXINCLUDES_DIRS); \
rm -f include/syslimits.h; \
if [ -f include/limits.h ]; then \
mv include/limits.h include/syslimits.h; \
@@ -2216,7 +2425,7 @@ xsys-protos.h: $(GCC_PASSES) $(srcdir)/sys-protos.h deduced.h gen-protos$(build_
mv tmp-fixtmp.c fixtmp.c
$(GCC_FOR_TARGET) fixtmp.c -w -U__SIZE_TYPE__ -U__PTRDIFF_TYPE__ -U__WCHAR_TYPE__ -E \
| sed -e 's/ / /g' -e 's/ *(/ (/g' -e 's/ [ ]*/ /g' -e 's/( )/()/' \
- | ./gen-protos >xsys-protos.hT
+ | $(RUN_GEN) ./gen-protos >xsys-protos.hT
mv xsys-protos.hT xsys-protos.h
rm -rf fixtmp.c
@@ -2268,24 +2477,22 @@ stmp-fixproto: fixhdr.ready fixproto stmp-int-hdrs
docdir = $(srcdir)/doc
doc: $(BUILD_INFO) $(GENERATED_MANPAGES) gccbug
-info: $(docdir)/cpp.info $(docdir)/gcc.info $(docdir)/gccint.info lang.info $(docdir)/cppinternals.info
+info: $(docdir)/cpp.info $(docdir)/gcc.info $(docdir)/gccint.info $(docdir)/gccinstall.info lang.info $(docdir)/cppinternals.info
-$(docdir)/cpp.info: $(docdir)/cpp.texi $(docdir)/include/fdl.texi \
+TEXI_CPP_FILES = $(docdir)/cpp.texi $(docdir)/include/fdl.texi \
$(docdir)/cppenv.texi $(docdir)/cppopts.texi
- cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/cpp.info doc/cpp.texi
-$(docdir)/gcc.info: $(docdir)/gcc.texi $(docdir)/include/gcc-common.texi \
+TEXI_GCC_FILES = $(docdir)/gcc.texi $(docdir)/include/gcc-common.texi \
$(docdir)/frontends.texi $(docdir)/standards.texi \
$(docdir)/invoke.texi $(docdir)/extend.texi $(docdir)/md.texi \
$(docdir)/objc.texi $(docdir)/gcov.texi $(docdir)/trouble.texi \
$(docdir)/bugreport.texi $(docdir)/service.texi \
- $(docdir)/contribute.texi $(docdir)/vms.texi $(docdir)/compat.texi \
+ $(docdir)/contribute.texi $(docdir)/compat.texi \
$(docdir)/include/funding.texi $(docdir)/gnu.texi \
$(docdir)/include/gpl.texi $(docdir)/include/fdl.texi \
$(docdir)/contrib.texi $(docdir)/cppenv.texi $(docdir)/cppopts.texi
- cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/gcc.info doc/gcc.texi
-$(docdir)/gccint.info: $(docdir)/gccint.texi \
+TEXI_GCCINT_FILES = $(docdir)/gccint.texi \
$(docdir)/include/gcc-common.texi $(docdir)/contribute.texi \
$(docdir)/makefile.texi $(docdir)/configterms.texi \
$(docdir)/portability.texi $(docdir)/interface.texi \
@@ -2296,46 +2503,47 @@ $(docdir)/gccint.info: $(docdir)/gccint.texi \
$(docdir)/headerdirs.texi $(docdir)/include/funding.texi \
$(docdir)/gnu.texi $(docdir)/include/gpl.texi \
$(docdir)/include/fdl.texi $(docdir)/contrib.texi \
- $(docdir)/languages.texi $(docdir)/sourcebuild.texi
+ $(docdir)/languages.texi $(docdir)/sourcebuild.texi \
+ $(docdir)/gty.texi
+
+TEXI_GCCINSTALL_FILES = $(docdir)/install.texi $(docdir)/install-old.texi \
+ $(docdir)/include/fdl.texi
+
+TEXI_CPPINT_FILES = $(docdir)/cppinternals.texi
+
+$(docdir)/cpp.info: $(TEXI_CPP_FILES)
+ cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/cpp.info doc/cpp.texi
+
+$(docdir)/gcc.info: $(TEXI_GCC_FILES)
+ cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/gcc.info doc/gcc.texi
+
+$(docdir)/gccint.info: $(TEXI_GCCINT_FILES)
cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/gccint.info doc/gccint.texi
-$(docdir)/cppinternals.info: $(docdir)/cppinternals.texi
+$(docdir)/gccinstall.info: $(TEXI_GCCINSTALL_FILES)
+ cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/gccinstall.info doc/install.texi
+
+$(docdir)/cppinternals.info: $(TEXI_CPPINT_FILES)
cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/cppinternals.info \
doc/cppinternals.texi
-dvi: gcc.dvi gccint.dvi cpp.dvi lang.dvi cppinternals.dvi
+dvi: gcc.dvi gccint.dvi gccinstall.dvi cpp.dvi lang.dvi cppinternals.dvi
# This works with GNU Make's default rule.
-cpp.dvi: $(docdir)/cpp.texi $(docdir)/include/fdl.texi \
- $(docdir)/cppenv.texi $(docdir)/cppopts.texi
+cpp.dvi: $(TEXI_CPP_FILES)
$(TEXI2DVI) -I $(docdir) -I $(docdir)/include $(docdir)/cpp.texi
-gcc.dvi: $(docdir)/gcc.texi $(docdir)/include/gcc-common.texi \
- $(docdir)/frontends.texi $(docdir)/standards.texi \
- $(docdir)/invoke.texi $(docdir)/extend.texi $(docdir)/md.texi \
- $(docdir)/objc.texi $(docdir)/gcov.texi $(docdir)/trouble.texi \
- $(docdir)/bugreport.texi $(docdir)/service.texi \
- $(docdir)/contribute.texi $(docdir)/vms.texi \
- $(docdir)/include/funding.texi $(docdir)/gnu.texi \
- $(docdir)/include/gpl.texi $(docdir)/include/fdl.texi \
- $(docdir)/contrib.texi $(docdir)/cppenv.texi $(docdir)/cppopts.texi
+gcc.dvi: $(TEXI_GCC_FILES)
$(TEXI2DVI) -I $(docdir) -I $(docdir)/include $(docdir)/gcc.texi
-gccint.dvi: $(docdir)/gccint.texi \
- $(docdir)/include/gcc-common.texi $(docdir)/contribute.texi \
- $(docdir)/makefile.texi $(docdir)/configterms.texi \
- $(docdir)/portability.texi $(docdir)/interface.texi \
- $(docdir)/passes.texi $(docdir)/c-tree.texi \
- $(docdir)/rtl.texi $(docdir)/md.texi $(docdir)/tm.texi \
- $(docdir)/hostconfig.texi $(docdir)/fragments.texi \
- $(docdir)/configfiles.texi $(docdir)/collect2.texi \
- $(docdir)/headerdirs.texi $(docdir)/include/funding.texi \
- $(docdir)/gnu.texi $(docdir)/include/gpl.texi \
- $(docdir)/include/fdl.texi $(docdir)/contrib.texi \
- $(docdir)/languages.texi $(docdir)/sourcebuild.texi
+gccint.dvi: $(TEXI_GCCINT_FILES)
$(TEXI2DVI) -I $(docdir) -I $(docdir)/include $(docdir)/gccint.texi
-cppinternals.dvi: $(docdir)/cppinternals.texi
+gccinstall.dvi: $(TEXI_GCCINSTALL_FILES)
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(TEXI2DVI) -I $$s/doc -I $$s/doc/include -o $@ $$s/doc/install.texi
+
+cppinternals.dvi: $(TEXI_CPPINT_FILES)
$(TEXI2DVI) -I $(docdir) -I $(docdir)/include $(docdir)/cppinternals.texi
generated-manpages: $(docdir)/gcov.1 $(docdir)/cpp.1 $(docdir)/gcc.1 \
@@ -2410,22 +2618,24 @@ $(docdir)/fsf-funding.7: $(docdir)/include/funding.texi
INTL_MOSTLYCLEAN = intl.mostlyclean
mostlyclean: $(INTL_MOSTLYCLEAN) lang.mostlyclean
-rm -f $(STAGESTUFF)
+ -rm -f *$(coverageexts)
-rm -rf libgcc
# Delete the temporary source copies for cross compilation.
- -rm -f $(HOST_PREFIX_1)rtl.c $(HOST_PREFIX_1)print-rtl.c
- -rm -f $(HOST_PREFIX_1)bitmap.c $(HOST_PREFIX_1)errors.c
- -rm -f $(HOST_PREFIX_1)ggc-none.c
+ -rm -f $(BUILD_PREFIX_1)rtl.c $(BUILD_PREFIX_1)print-rtl.c
+ -rm -f $(BUILD_PREFIX_1)bitmap.c $(BUILD_PREFIX_1)errors.c
+ -rm -f $(BUILD_PREFIX_1)ggc-none.c
# Delete the temp files made in the course of building libgcc.a.
-rm -f xlimits.h
# Delete other built files.
- -rm -f t-float.h-cross xsys-protos.hT
+ -rm -f xsys-protos.hT
+ -rm -f specs.h options.h gencheck.h
# Delete the stamp and temporary files.
-rm -f s-* tmp-* stamp-* stmp-*
-rm -f */stamp-* */tmp-*
# Delete debugging dump files.
-rm -f *.[0-9][0-9].* */*.[0-9][0-9].*
# Delete some files made during installation.
- -rm -f specs float.h-* enquire SYSCALLS.c.X SYSCALLS.c
+ -rm -f specs SYSCALLS.c.X SYSCALLS.c
-rm -f collect collect2 mips-tfile mips-tdump
# Delete files generated for fixproto
-rm -rf fix-header$(build_exeext) xsys-protos.h deduced.h tmp-deduced.h \
@@ -2440,6 +2650,11 @@ mostlyclean: $(INTL_MOSTLYCLEAN) lang.mostlyclean
-rm -f gcc.vrs gcc.kys gcc.tps gcc.pgs gcc.fns
# Delete core dumps.
-rm -f core */core
+# Delete file generated for gengtype.c
+ -rm -f gtyp-gen.h
+# Delete files generated by gengtype.c
+ -rm -f gtype-*
+ -rm -f gt-*
# Delete all files made by compilation
# that don't exist in the distribution.
@@ -2474,20 +2689,24 @@ distclean: clean $(INTL_DISTCLEAN) lang.distclean
-rm -f cstamp-h
-rm -f config.status config.run config.cache config.bak
-rm -f Make-lang Make-hooks Make-host Make-target
- -rm -f Makefile specs.h options.h gencheck.h *.oaux
+ -rm -f Makefile *.oaux
-rm -f gthr-default.h
-rm -f */stage1 */stage2 */stage3 */stage4 */include
-rm -f c-parse.output
-rm -f *.asm
- -rm -f float.h
-rm -f site.exp site.bak testsuite/site.exp testsuite/site.bak
- -rm -f testsuite/{gcc,g++}.{log,sum}
+ -rm -f testsuite/*.log testsuite/*.sum
+ -cd testsuite && rm -f x *.x *.x? *.exe *.rpo *.o *.s *.S *.c
+ -cd testsuite && rm -f *.out *.gcov *.bb *.bbg
+ -rm -rf ${QMTEST_DIR} stamp-qmtest
-rm -f intl/libintl.h libintl.h
-rm -f cxxmain.c
- -rm -f mklibgcc gccbug .gdbinit configargs.h
+ -rm -f mklibgcc mkheaders gccbug .gdbinit configargs.h
-rm -f gcov.pod
-rm -f fixinc/Makefile
- -rmdir ada cp f java objc fixinc intl po 2>/dev/null
+# Delete po/*.gmo only if we are not building in the source directory.
+ -if [ ! -f po/exgettext ]; then rm -f po/*.gmo; fi
+ -rmdir ada cp f java objc fixinc intl po testsuite 2>/dev/null
# Delete anything likely to be found in the source directory
# that shouldn't be in the distribution.
@@ -2532,7 +2751,7 @@ maintainer-clean:
# Install the driver last so that the window when things are
# broken is small.
install: install-common $(INSTALL_HEADERS) $(INSTALL_LIBGCC) \
- $(INSTALL_CPP) install-man install-info intl.install install-@POSUB@ \
+ install-cpp install-man install-info intl.install install-@POSUB@ \
lang.install-normal install-driver
# Handle cpp installation.
@@ -2553,14 +2772,6 @@ install-cpp: cpp$(exeext)
else true; fi; \
fi
-uninstall-cpp:
- -rm -f $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext)
- -rm -f $(DESTDIR)$(bindir)/$(CPP_CROSS_NAME)$(exeext)
- -if [ x$(cpp_install_dir) != x ]; then \
- rm -f $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_INSTALL_NAME)$(exeext); \
- rm -f $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_CROSS_NAME)$(exeext); \
- else true; fi
-
# Create the installation directories.
# $(libdir)/gcc-lib/include isn't currently searched by cpp.
installdirs:
@@ -2618,10 +2829,6 @@ install-common: native $(EXTRA_PARTS) lang.install-common
$(INSTALL_DATA) SYSCALLS.c.X $(DESTDIR)$(libsubdir)/SYSCALLS.c.X; \
chmod a-x $(DESTDIR)$(libsubdir)/SYSCALLS.c.X; \
fi
- -rm -f $(DESTDIR)$(libsubdir)/cpp0$(exeext)
- $(INSTALL_PROGRAM) cpp0$(exeext) $(DESTDIR)$(libsubdir)/cpp0$(exeext)
- -rm -f $(DESTDIR)$(libsubdir)/tradcpp0$(exeext)
- $(INSTALL_PROGRAM) tradcpp0$(exeext) $(DESTDIR)$(libsubdir)/tradcpp0$(exeext)
# Install gcov if it was compiled.
-if [ -f gcov$(exeext) ]; \
then \
@@ -2630,12 +2837,16 @@ install-common: native $(EXTRA_PARTS) lang.install-common
fi
$(INSTALL_SCRIPT) gccbug $(DESTDIR)$(bindir)/$(GCCBUG_INSTALL_NAME)
-# Install the driver program as $(target_alias)-gcc
+# Install the driver program as $(target_alias)-gcc,
+# $(target-alias)-gcc-$(version)
# and also as either gcc (if native) or $(gcc_tooldir)/bin/gcc.
install-driver: installdirs xgcc$(exeext)
-if [ -f gcc-cross$(exeext) ] ; then \
rm -f $(DESTDIR)$(bindir)/$(GCC_CROSS_NAME)$(exeext); \
$(INSTALL_PROGRAM) gcc-cross$(exeext) $(DESTDIR)$(bindir)/$(GCC_CROSS_NAME)$(exeext); \
+ rm -f $(DESTDIR)$(bindir)/$(target_alias)-gcc-$(version); \
+ ( cd $(DESTDIR)$(bindir) && \
+ $(LN) $(GCC_CROSS_NAME)$(exeext) $(target_alias)-gcc-$(version) ); \
if [ -d $(DESTDIR)$(gcc_tooldir)/bin/. ] ; then \
rm -f $(DESTDIR)$(gcc_tooldir)/bin/gcc$(exeext); \
$(INSTALL_PROGRAM) gcc-cross$(exeext) $(DESTDIR)$(gcc_tooldir)/bin/gcc$(exeext); \
@@ -2643,10 +2854,13 @@ install-driver: installdirs xgcc$(exeext)
else \
rm -f $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext); \
$(INSTALL_PROGRAM) xgcc$(exeext) $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext); \
- rm -f $(DESTDIR)$(bindir)/$(target_alias)-gcc-1$(exeext); \
+ rm -f $(DESTDIR)$(bindir)/$(target_alias)-gcc-$(version); \
( cd $(DESTDIR)$(bindir) && \
- $(LN) $(GCC_INSTALL_NAME)$(exeext) $(target_alias)-gcc-1$(exeext) && \
- mv -f $(target_alias)-gcc-1$(exeext) $(GCC_TARGET_INSTALL_NAME)$(exeext) ); \
+ $(LN) $(GCC_INSTALL_NAME)$(exeext) $(target_alias)-gcc-$(version) ); \
+ rm -f $(DESTDIR)$(bindir)/$(target_alias)-gcc-tmp$(exeext); \
+ ( cd $(DESTDIR)$(bindir) && \
+ $(LN) $(GCC_INSTALL_NAME)$(exeext) $(target_alias)-gcc-tmp$(exeext) && \
+ mv -f $(target_alias)-gcc-tmp$(exeext) $(GCC_TARGET_INSTALL_NAME)$(exeext) ); \
fi
# Install the info files.
@@ -2709,7 +2923,7 @@ install-libgcc: libgcc.mk libgcc.a installdirs
r_f_t=: ; \
fi; \
$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
- HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \
+ BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
AR_FOR_TARGET="$(AR_FOR_TARGET)" \
AR_CREATE_FOR_TARGET="$(AR_CREATE_FOR_TARGET)" \
AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \
@@ -2736,7 +2950,7 @@ install-multilib: stmp-multilib installdirs
r_f_t=: ; \
fi; \
$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
- HOST_PREFIX="$(HOST_PREFIX)" HOST_PREFIX_1="$(HOST_PREFIX_1)" \
+ BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
AR_FOR_TARGET="$(AR_FOR_TARGET)" \
AR_CREATE_FOR_TARGET="$(AR_CREATE_FOR_TARGET)" \
AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \
@@ -2762,7 +2976,7 @@ install-headers: $(INSTALL_HEADERS_DIR)
# Don't need to use LN_S here since we really do need ln -s and no substitutes.
-files=`cd $(DESTDIR)$(libsubdir)/include; find . -type l -print 2>/dev/null`; \
if [ $$? -eq 0 ]; then \
- dir=`cd include; pwd`; \
+ dir=`cd include; ${PWD_COMMAND}`; \
for i in $$files; do \
dest=`ls -ld $(DESTDIR)$(libsubdir)/include/$$i | sed -n 's/.*-> //p'`; \
if expr "$$dest" : "$$dir.*" > /dev/null; then \
@@ -2784,7 +2998,7 @@ install-headers-tar: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir
# Unless a full pathname is provided, some shells would print the new CWD,
# found in CDPATH, corrupting the output. We could just redirect the
# output of `cd', but some shells lose on redirection within `()'s
- (cd `pwd`/include ; \
+ (cd `${PWD_COMMAND}`/include ; \
tar -cf - .; exit 0) | (cd $(DESTDIR)$(libsubdir)/include; tar xpf - )
# /bin/sh on some systems returns the status of the first tar,
# and that can lose with GNU tar which always writes a full block.
@@ -2793,13 +3007,50 @@ install-headers-tar: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir
# Install the include directory using cpio.
install-headers-cpio: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir
# See discussion about the use of `pwd` above
- cd `pwd`/include ; \
+ cd `${PWD_COMMAND}`/include ; \
find . -print | cpio -pdum $(DESTDIR)$(libsubdir)/include
# Install the include directory using cp.
install-headers-cp: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir
cp -p -r include $(DESTDIR)$(libsubdir)
+itoolsdir = $(libsubdir)/install-tools
+# Don't install the headers. Instead, install appropriate scripts
+# and supporting files for fixincludes to be run later.
+install-mkheaders: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir \
+ mkheaders xlimits.h
+ -rm -rf $(DESTDIR)$(itoolsdir)
+ $(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$(itoolsdir)/include
+ for file in $(USER_H); do \
+ realfile=`echo $$file | sed -e 's|.*/\([^/]*\)$$|\1|'`; \
+ $(INSTALL_DATA) $$file \
+ $(DESTDIR)$(itoolsdir)/include/$$realfile ; \
+ done
+ $(INSTALL_DATA) xlimits.h $(DESTDIR)$(itoolsdir)/include/limits.h
+ if [ x$(STMP_FIXINC) != x ] ; then \
+ $(INSTALL_DATA) $(srcdir)/README-fixinc \
+ $(DESTDIR)$(itoolsdir)/include/README ; \
+ $(INSTALL_PROGRAM) fixinc.sh $(DESTDIR)$(itoolsdir)/fixinc.sh ; \
+ $(INSTALL_PROGRAM) fixinc/fixincl $(DESTDIR)$(itoolsdir)/fixincl ; \
+ $(INSTALL_DATA) $(srcdir)/gsyslimits.h $(DESTDIR)$(itoolsdir)/gsyslimits.h ; \
+ else :; fi
+ if [ x$(STMP_FIXPROTO) != x ] ; then \
+ $(INSTALL_PROGRAM) $(srcdir)/mkinstalldirs \
+ $(DESTDIR)$(itoolsdir)/mkinstalldirs ; \
+ $(INSTALL_PROGRAM) $(srcdir)/fixproto $(DESTDIR)$(itoolsdir)/fixproto ; \
+ $(INSTALL_PROGRAM) fix-header$(build_exeext) \
+ $(DESTDIR)$(itoolsdir)/fix-header$(build_exeext) ; \
+ else :; fi
+ $(INSTALL_PROGRAM) mkheaders $(DESTDIR)$(itoolsdir)/mkheaders
+ echo 'SYSTEM_HEADER_DIR="$(SYSTEM_HEADER_DIR)"' \
+ > $(DESTDIR)$(itoolsdir)/mkheaders.conf
+ echo 'OTHER_FIXINCLUDES_DIRS="$(OTHER_FIXINCLUDES_DIRS)"' \
+ >> $(DESTDIR)$(itoolsdir)/mkheaders.conf
+ echo 'FIXPROTO_DEFINES="$(FIXPROTO_DEFINES)"' \
+ >> $(DESTDIR)$(itoolsdir)/mkheaders.conf
+ echo 'STMP_FIXPROTO="$(STMP_FIXPROTO)"' >> $(DESTDIR)$(itoolsdir)/mkheaders.conf
+ echo 'STMP_FIXINC="$(STMP_FIXINC)"' >> $(DESTDIR)$(itoolsdir)/mkheaders.conf
+
# Use this target to install the program `collect2' under the name `collect2'.
install-collect2: collect2 installdirs
$(INSTALL_PROGRAM) collect2$(exeext) $(DESTDIR)$(libsubdir)/collect2$(exeext)
@@ -2807,10 +3058,16 @@ install-collect2: collect2 installdirs
$(INSTALL_PROGRAM) xgcc$(exeext) $(DESTDIR)$(libsubdir)/gcc$(exeext)
# Cancel installation by deleting the installed files.
-uninstall: intl.uninstall lang.uninstall $(UNINSTALL_CPP)
+uninstall: intl.uninstall lang.uninstall
-rm -rf $(DESTDIR)$(libsubdir)
-rm -rf $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext)
-rm -rf $(DESTDIR)$(bindir)/$(GCC_CROSS_NAME)$(exeext)
+ -rm -f $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext)
+ -rm -f $(DESTDIR)$(bindir)/$(CPP_CROSS_NAME)$(exeext)
+ -if [ x$(cpp_install_dir) != x ]; then \
+ rm -f $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_INSTALL_NAME)$(exeext); \
+ rm -f $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_CROSS_NAME)$(exeext); \
+ else true; fi
-rm -rf $(DESTDIR)$(bindir)/$(PROTOIZE_INSTALL_NAME)$(exeext)
-rm -rf $(DESTDIR)$(bindir)/$(PROTOIZE_CROSS_NAME)$(exeext)
-rm -rf $(DESTDIR)$(bindir)/$(UNPROTOIZE_INSTALL_NAME)$(exeext)
@@ -2838,8 +3095,8 @@ site.exp: ./config.status Makefile
@echo "## these variables are automatically generated by make ##" > ./tmp0
@echo "# Do not edit here. If you wish to override these values" >> ./tmp0
@echo "# add them to the last section" >> ./tmp0
- @echo "set rootme \"`pwd`\"" >> ./tmp0
- @echo "set srcdir \"`cd ${srcdir}; pwd`\"" >> ./tmp0
+ @echo "set rootme \"`${PWD_COMMAND}`\"" >> ./tmp0
+ @echo "set srcdir \"`cd ${srcdir}; ${PWD_COMMAND}`\"" >> ./tmp0
@echo "set host_triplet $(host_canonical)" >> ./tmp0
@echo "set build_triplet $(build_canonical)" >> ./tmp0
@echo "set target_triplet $(target)" >> ./tmp0
@@ -2872,23 +3129,26 @@ site.exp: ./config.status Makefile
fi
echo "set tmpdir $(objdir)/testsuite" >> ./tmp0
@echo "set srcdir \"\$${srcdir}/testsuite\"" >> ./tmp0
+ @if [ "X$(ALT_CXX_UNDER_TEST)" != "X" ] ; then \
+ echo "set ALT_CXX_UNDER_TEST $(ALT_CXX_UNDER_TEST)" >> ./tmp0; \
+ else true; \
+ fi
+ @if [ "X$(COMPAT_OPTIONS)" != "X" ] ; then \
+ echo "set COMPAT_OPTIONS $(COMPAT_OPTIONS)" >> ./tmp0; \
+ else true; \
+ fi
@echo "## All variables above are generated by configure. Do Not Edit ##" >> ./tmp0
@cat ./tmp0 > site.exp
@cat site.bak | sed \
-e '1,/^## All variables above are.*##/ d' >> site.exp
-@rm -f ./tmp?
-CHECK_TARGETS = check-gcc check-fixinc @check_languages@
+CHECK_TARGETS = check-gcc @check_languages@
check-c++ : check-g++
check-f77 : check-g77
check-java :
-check-fixinc :
- if (autogen --ver=v) > /dev/null 2>&1 ; \
- then cd fixinc && $(MAKE) check ; \
- else true ; fi
-
check: $(CHECK_TARGETS)
# The idea is to parallelize testing of multilibs, for example:
@@ -2912,55 +3172,132 @@ $(TESTSUITEDIR)/site.exp: site.exp
sed '/set tmpdir/ s|testsuite|$(TESTSUITEDIR)|' < site.exp > $@
check-g++: $(TESTSUITEDIR)/site.exp
- -(rootme=`pwd`; export rootme; \
- srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \
+ -(rootme=`${PWD_COMMAND}`; export rootme; \
+ srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \
cd $(TESTSUITEDIR); \
EXPECT=${EXPECT} ; export EXPECT ; \
if [ -f $${rootme}/../expect/expect ] ; then \
- TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \
+ TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
export TCL_LIBRARY ; fi ; \
$(RUNTEST) --tool g++ $(RUNTESTFLAGS))
check-gcc: $(TESTSUITEDIR)/site.exp
- -(rootme=`pwd`; export rootme; \
- srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \
+ -(rootme=`${PWD_COMMAND}`; export rootme; \
+ srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \
cd $(TESTSUITEDIR); \
EXPECT=${EXPECT} ; export EXPECT ; \
if [ -f $${rootme}/../expect/expect ] ; then \
- TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \
+ TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
export TCL_LIBRARY ; fi ; \
$(RUNTEST) --tool gcc $(RUNTESTFLAGS))
check-g77: $(TESTSUITEDIR)/site.exp
- -(rootme=`pwd`; export rootme; \
- srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \
+ -(rootme=`${PWD_COMMAND}`; export rootme; \
+ srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \
cd $(TESTSUITEDIR); \
EXPECT=${EXPECT} ; export EXPECT ; \
if [ -f $${rootme}/../expect/expect ] ; then \
- TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \
+ TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
export TCL_LIBRARY ; fi ; \
$(RUNTEST) --tool g77 $(RUNTESTFLAGS))
check-objc: $(TESTSUITEDIR)/site.exp
- -(rootme=`pwd`; export rootme; \
- srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \
+ -(rootme=`${PWD_COMMAND}`; export rootme; \
+ srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \
cd $(TESTSUITEDIR); \
EXPECT=${EXPECT} ; export EXPECT ; \
if [ -f $${rootme}/../expect/expect ] ; then \
- TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \
+ TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
export TCL_LIBRARY ; fi ; \
$(RUNTEST) --tool objc $(RUNTESTFLAGS))
check-consistency: testsuite/site.exp
- -rootme=`pwd`; export rootme; \
- srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \
+ -rootme=`${PWD_COMMAND}`; export rootme; \
+ srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \
cd testsuite; \
EXPECT=${EXPECT} ; export EXPECT ; \
if [ -f $${rootme}/../expect/expect ] ; then \
- TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; pwd` ; \
+ TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
export TCL_LIBRARY ; fi ; \
$(RUNTEST) --tool consistency $(RUNTESTFLAGS)
+# QMTest targets
+
+# The path to qmtest.
+QMTEST_PATH=qmtest
+
+# The flags to pass to qmtest.
+QMTESTFLAGS=
+
+# The flags to pass to "qmtest run".
+QMTESTRUNFLAGS=
+
+# The command to use to invoke qmtest.
+QMTEST=${QMTEST_PATH} ${QMTESTFLAGS}
+
+# The tests (or suites) to run.
+QMTEST_GPP_TESTS=gpp
+
+# The subdirectory of the OBJDIR that will be used to store the QMTest
+# test database configuration and that will be used for temporary
+# scratch space during QMTest's execution.
+QMTEST_DIR=qmtestsuite
+
+# Create the QMTest database configuration.
+${QMTEST_DIR} stamp-qmtest:
+ debug_options=""; \
+ ${STAMP} empty.C; \
+ for option in \
+ -gdwarf-2 -gstabs -gstabs+ -gxcoff -gxcoff+ -gcoff; do \
+ (./cc1plus -q $${option} empty.C 2>&1 | \
+ grep "unknown or unsupported -g option" > /dev/null) || \
+ debug_options="$${debug_options}$${option} "; done; \
+ ${QMTEST} -D ${QMTEST_DIR} create-tdb \
+ -c gcc_database.GCCDatabase \
+ -a GCCDatabase.testsuite_root=`cd ${srcdir}/testsuite && pwd` \
+ -a GCCDatabase.debug_options="$${debug_options}"
+ rm -f empty.C empty.s
+ $(STAMP) stamp-qmtest
+
+# Create the QMTest context file.
+${QMTEST_DIR}/context: stamp-qmtest
+ echo "GCCTest.flags=-B${objdir}" >> $@
+ echo "GCCTest.objdir=${objdir}/.." >> $@
+ echo "GCCTest.host=${host_canonical}" >> $@
+ echo "GCCTest.target=${target}" >> $@
+ echo "GCCTest.gcov=${objdir}/gcov" >> $@
+ echo "GPPTest.gpp=${objdir}/g++" >> $@
+ echo "DGTest.demangler=${objdir}/c++filt" >> $@
+
+# Run the G++ testsuite using QMTest.
+qmtest-g++: ${QMTEST_DIR}/context ${QMTEST_DIR}/gpp-expected.qmr
+ cd ${QMTEST_DIR} && ${QMTEST} run ${QMTESTRUNFLAGS} -C context \
+ -o gpp.qmr -O gpp-expected.qmr \
+ ${QMTEST_GPP_TESTS}
+
+# Use the QMTest GUI.
+qmtest-gui: ${QMTEST_DIR}/context
+ cd ${QMTEST_DIR} && ${QMTEST} gui -C context
+
+# Build the set of expected G++ failures.
+${QMTEST_DIR}/gpp-expected.qmr: ${QMTEST_DIR}/context
+ echo "Determining expected results..."
+ cd ${QMTEST_DIR} && ${QMTEST} run ${QMTESTRUNFLAGS} -C context \
+ -c "GCCTest.generate_xfails=1" -o gpp-expected.qmr \
+ ${QMTEST_GPP_TESTS} \
+ > /dev/null
+
+.PHONY: qmtest-g++
+
+# Run Paranoia on real.c.
+
+paranoia.o: $(srcdir)/../contrib/paranoia.cc $(CONFIG_H) $(SYSTEM_H) \
+ real.h $(TREE_H)
+ g++ -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+
+paranoia: paranoia.o real.o $(LIBIBERTY)
+ g++ -o $@ paranoia.o real.o $(LIBIBERTY)
+
# These exist for maintenance purposes.
# Update the tags table.
@@ -2979,6 +3316,7 @@ VOL_FILES=`echo $(BACKEND) $(OBJS) $(C_OBJS) $(LIBCPP_OBJS) *.c *.h gen*`
# WARN_CFLAGS setting can't be to the expansion of GCC_WARN_CFLAGS in
# the context of the stage_x rule.
STAGE2_FLAGS_TO_PASS = \
+ ADAC="\$$(CC)" \
CFLAGS="$(BOOT_CFLAGS)" \
LDFLAGS="$(BOOT_LDFLAGS)" \
WARN_CFLAGS="\$$(GCC_WARN_CFLAGS)" \
@@ -2996,7 +3334,7 @@ STAGE2_FLAGS_TO_PASS = \
stage1_build:
$(MAKE) CC="$(CC)" libdir=$(libdir) LANGUAGES="$(BOOT_LANGUAGES)" \
CFLAGS="$(STAGE1_CFLAGS)" MAKEINFO="$(MAKEINFO)" \
- MAKEINFOFLAGS="$(MAKEINFOFLAGS)"
+ MAKEINFOFLAGS="$(MAKEINFOFLAGS)" COVERAGE_FLAGS=
$(STAMP) stage1_build
echo stage1_build > stage_last
@@ -3006,7 +3344,7 @@ stage1_copy: stage1_build
echo stage2_build > stage_last
stage2_build: stage1_copy
- $(MAKE) CC="stage1/xgcc$(exeext) -Bstage1/ -B$(build_tooldir)/bin/" \
+ $(MAKE) CC="$(STAGE_CC_WRAPPER) stage1/xgcc$(exeext) -Bstage1/ -B$(build_tooldir)/bin/" \
STAGE_PREFIX=stage1/ \
$(STAGE2_FLAGS_TO_PASS)
$(STAMP) stage2_build
@@ -3018,7 +3356,7 @@ stage2_copy: stage2_build
echo stage3_build > stage_last
stage3_build: stage2_copy
- $(MAKE) CC="stage2/xgcc$(exeext) -Bstage2/ -B$(build_tooldir)/bin/" \
+ $(MAKE) CC="$(STAGE_CC_WRAPPER) stage2/xgcc$(exeext) -Bstage2/ -B$(build_tooldir)/bin/" \
STAGE_PREFIX=stage2/ \
$(STAGE2_FLAGS_TO_PASS)
$(STAMP) stage3_build
@@ -3031,7 +3369,7 @@ stage3_copy: stage3_build
echo stage4_build > stage_last
stage4_build: stage3_copy
- $(MAKE) CC="stage3/xgcc$(exeext) -Bstage3/ -B$(build_tooldir)/bin/" \
+ $(MAKE) CC="$(STAGE_CC_WRAPPER) stage3/xgcc$(exeext) -Bstage3/ -B$(build_tooldir)/bin/" \
STAGE_PREFIX=stage3/ \
$(STAGE2_FLAGS_TO_PASS)
$(STAMP) stage4_build
@@ -3052,7 +3390,8 @@ bootstrap: stage3_build
@echo
@echo Bootstrap complete - make \"quickstrap\" to redo last build,
@echo \"restage1\" through \"restage3\" to rebuild specific stages,
- @echo or \"cleanstrap\" to redo the bootstrap from scratch.
+ @echo \"restrap\" to redo the bootstrap from stage1, or
+ @echo \"cleanstrap\" to redo the bootstrap from scratch.
bootstrap-lean : clean_s1 clean_s2 stage3_build
@echo
@@ -3121,6 +3460,16 @@ cleanstrap:
-$(MAKE) clean
$(MAKE) LANGUAGES="$(LANGUAGES)" bootstrap
+unstrap:
+ -rm -rf stage[234]*
+ $(MAKE) unstage1
+
+# Differs from cleanstrap in that it starts from the earlier stage1 build,
+# not from scratch.
+restrap:
+ $(MAKE) unstrap
+ $(MAKE) LANGUAGES="$(LANGUAGES)" bootstrap
+
# Compare the object files in the current directory with those in the
# stage2 directory.
@@ -3159,18 +3508,21 @@ compare compare3 compare4 compare-lean compare3-lean compare4-lean: force
# Compare the object files in the current directory with those in the
# stage2 directory. Use gnu cmp (diffutils v2.4 or later) to avoid
# running tail and the overhead of twice copying each object file.
-
+# An exit status of 1 is precisely the result we're looking for (other
+# values mean other problems).
gnucompare gnucompare3 gnucompare4 gnucompare-lean gnucompare3-lean gnucompare4-lean: force
-rm -f .bad_compare
case "$@" in gnucompare | gnucompare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^gnucompare\([0-9][0-9]*\).*,\1,'` ;; esac; \
for file in *$(objext); do \
- (cmp --ignore-initial=16 $$file stage$$stage/$$file > /dev/null 2>&1 || echo $$file differs >> .bad_compare) || true; \
+ cmp --ignore-initial=16 $$file stage$$stage/$$file > /dev/null 2>&1; \
+ test $$? -eq 1 && echo $$file differs >> .bad_compare || true; \
done
case "$@" in gnucompare | gnucompare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^gnucompare\([0-9][0-9]*\).*,\1,'` ;; esac; \
for dir in tmp-foo intl $(SUBDIRS); do \
if [ "`echo $$dir/*$(objext)`" != "$$dir/*$(objext)" ] ; then \
for file in $$dir/*$(objext); do \
- (cmp --ignore-initial=16 $$file stage$$stage/$$file > /dev/null 2>&1 || echo $$file differs >> .bad_compare) || true; \
+ cmp --ignore-initial=16 $$file stage$$stage/$$file > /dev/null 2>&1; \
+ test $$? -eq 1 && echo $$file differs >> .bad_compare || true; \
done; \
else true; fi; \
done
@@ -3323,59 +3675,6 @@ risky-stage4: stage4
force:
-# ---
-# The enquire rules are still useful for building new float-anything.h.
-# Special flags for compiling enquire.
-# We disable optimization to make floating point more reliable.
-ENQUIRE_CFLAGS = -DNO_MEM -DNO_LONG_DOUBLE_IO -O0
-ENQUIRE_LDFLAGS = $(LDFLAGS)
-
-# Enquire target (This is a variable so that a target can choose not to
-# build it.)
-ENQUIRE = enquire
-
-# Test to see whether <float.h> exists in the system header files,
-# and is not derived from GCC.
-FLOAT_H_TEST = \
- [ -f $(SYSTEM_HEADER_DIR)/float.h ] && \
- if grep 'ifndef _FLOAT_H___' $(SYSTEM_HEADER_DIR)/float.h >/dev/null; \
- then false; \
- else :; fi
-# We pretend to not having a usable <float.h>, hence disable the FLOAT_H_TEST
-# to ensure, we're emitting a full blown <float.h> ourselves.
-FLOAT_H_TEST = false
-
-# Used to compile enquire with standard cc, but have forgotten why.
-# Let's try with GCC.
-enquire: enquire.o $(GCC_PARTS)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ENQUIRE_LDFLAGS) enquire.o -o $@
-enquire.o: $(srcdir)/enquire.c $(GCC_PASSES) stmp-int-hdrs
- if $(FLOAT_H_TEST); then \
- rm -f include/float.h; \
- SYS_FLOAT_H_WRAP=1; \
- else :; \
- SYS_FLOAT_H_WRAP=0; \
- fi; \
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ALL_CPPFLAGS) $(ENQUIRE_CFLAGS) \
- -DSYS_FLOAT_H_WRAP=$$SYS_FLOAT_H_WRAP \
- -I. -c $(srcdir)/enquire.c $(OUTPUT_OPTION)
-
-# Create float.h source for the native machine.
-# Make it empty if we can use the system float.h without changes.
-float.h-nat: enquire
- -./enquire -f > tmp-float.h
- grep '#define [^_]' tmp-float.h >/dev/null || true > tmp-float.h
- mv tmp-float.h float.h-nat
-
-# Create a dummy float.h source for a cross-compiler.
-# ??? This isn't used anymore. Should we create config/float-unkn.h
-# and make that the default float_format in configure?
-float.h-cross:
- echo "#ifndef __GCC_FLOAT_NOT_NEEDED" > t-float.h-cross
- echo "#error float.h values not known for cross-compiler" >> t-float.h-cross
- echo "#endif" >> t-float.h-cross
- mv t-float.h-cross float.h-cross
-
# Rules for generating translated message descriptions.
# Disabled by autoconf if the tools are not available.
@@ -3386,7 +3685,7 @@ MSGMERGE = msgmerge
PACKAGE = @PACKAGE@
CATALOGS = @CATALOGS@
-.PHONY: build- install- build-po install-po update-po
+.PHONY: build- install- build-po install-po update-po
# Dummy rules to deal with dependencies produced by use of
# "build-@POSUB@" and "install-@POSUB@" above, when NLS is disabled.
diff --git a/contrib/gcc/ONEWS b/contrib/gcc/ONEWS
index 4d4b54b..f4b3581 100644
--- a/contrib/gcc/ONEWS
+++ b/contrib/gcc/ONEWS
@@ -1,112 +1,28 @@
This file contains information about GCC releases up to GCC 2.8.1, and
-some information about EGCS releases. For more details of changes in
-EGCS releases, and details of changes in GCC 2.95 and more recent
-releases, see the release notes on the GCC web site and the file NEWS
-which contains the most relevant parts of those release notes in text
-form.
+a tiny bit of information on EGCS.
-Noteworthy changes in GCC for EGCS 1.1.
----------------------------------------
-
-The compiler now implements global common subexpression elimination (gcse) as
-well as global constant/copy propagation. (link to gcse page).
-
-More major improvements have been made to the alias analysis code. A new
-option to allow front-ends to provide alias information to the optimizers
-has also been added (-fstrict-aliasing). -fstrict-aliasing is off by default
-now, but will be enabled by default in the future. (link to alias page)
-
-Major changes continue in the exception handling support. This release
-includes some changes to reduce static overhead for exception handling. It
-also includes some major changes to the setjmp/longjmp based EH mechanism to
-make it less pessimistic. And finally, major infrastructure improvements
-to the dwarf2 EH mechanism have been made to make our EH support extensible.
-
-We have fixed the infamous security problems with temporary files.
-
-The "regmove" optimization pass has been nearly completely rewritten. It now
-uses much more information about the target to determine profitability of
-transformations.
+For details of changes in EGCS releases and GCC 2.95 and later releases,
+see the release notes on the GCC web site or the file NEWS which contains
+the most relevant parts of those release notes in text form.
-The compiler now recomputes register usage information immediately before
-register allocation. Previously such information was only not kept up to
-date after instruction combination which led to poor register allocation
-choices by our priority based register allocator.
-
-The register reloading phase of the compiler has been improved to better
-optimize spill code. This primarily helps targets which generate lots of
-spills (like the x86 ports and many register poor embedded ports).
-
-A few changes in the heuristics used by the register allocator and scheduler
-have been made which can significantly improve performance for certain
-applications.
-
-The compiler's branch shortening algorithms have been significantly improved
-to work better on targets which align jump targets.
+Changes in GCC for EGCS (that are not listed in the web release notes)
+---------------------------------------------------------------------
The compiler now supports the "ADDRESSOF" optimization which can significantly
reduce the overhead for certain inline calls (and inline calls in general).
-The compiler now supports a code size optimization switch (-Os). When enabled
-the compiler will prefer optimizations which improve code size over those
-which improve code speed.
-
-The compiler has been improved to completely eliminate library calls which
-compute constant values. This is particularly useful on machines which
-do not have integer mul/div or floating point support on-chip.
-
-GCC now supports a "--help" option to print detailed help information.
-
-cpplib has been greatly improved. It is probably usable for some sites now
-(major missing feature is trigraphs).
-
-Memory footprint for the compiler has been significantly reduced for certain
-pathalogical cases.
-
-Build time improvements for targets which support lots of sched parameters
-(alpha and mips primarily).
-
Compile time for certain programs using large constant initializers has been
improved (affects glibc significantly).
-Plus an incredible number of infrastructure changes, warning fixes, bugfixes
-and local optimizations.
-
Various improvements have been made to better support cross compilations. They
are still not easy, but they are improving.
-Target specific NEWS
-
- Sparc: Now includes V8 plus and V9 support, lots of tuning for Ultrasparcs
- and uses the Haifa scheduler by default.
-
- Alpha: EV6 tuned, optimized expansion of memcpy/bzero.
-
- x86: Data in the static store is aligned per Intel recommendations. Jump
- targets are aligned per Intel recommendations. Improved epilogue
- sequences for Pentium chips. Backend improvements which should help
- register allocation on all x86 variants. Support for PPro conditional
- move instructions has been fixed and enabled. Random changes
- throughout the port to make generated code more Pentium friendly.
- Improved support for 64bit integer operations.
- Unixware 7, a System V Release 5 target is now supported.
- SCO OpenServer targets can support GAS. See gcc/INSTALL for details.
-
- RS6000/PowerPC: Includes AIX4.3 support as well as PowerPC64 support.
- Haifa instruction scheduling is enabled by default now.
-
- MIPS: Multiply/Multiply-Add support has been largely rewritten to generate
- more efficient code. Includes mips16 support.
-
- M68K: Various micro-optimizations and Coldfire fixes.
+Target-specific changes:
M32r: Major improvements to this port.
Arm: Includes Thumb and super interworking support.
-EGCS includes all gcc2 changes up to and including the June 9, 1998 snapshot.
-
-
Noteworthy changes in GCC version 2.8.1
---------------------------------------
diff --git a/contrib/gcc/README.Portability b/contrib/gcc/README.Portability
index d69c386..04638b2 100644
--- a/contrib/gcc/README.Portability
+++ b/contrib/gcc/README.Portability
@@ -123,8 +123,19 @@ int myfunc PARAMS ((double, int *));
int
myfunc (var1, var2)
- double var1;
- int *var2;
+ double var1;
+ int *var2;
+{
+ ...
+}
+
+This implies that if the function takes no arguments, it should be
+declared and defined as follows:
+
+int myfunc PARAMS ((void));
+
+int
+myfunc ()
{
...
}
@@ -139,32 +150,16 @@ void cpp_ice PARAMS ((cpp_reader *, const char *msgid, ...));
void
cpp_ice VPARAMS ((cpp_reader *pfile, const char *msgid, ...))
-{
-#ifndef ANSI_PROTOTYPES
- cpp_reader *pfile;
- const char *msgid;
-#endif
- va_list ap;
-
- VA_START (ap, msgid);
-
-#ifndef ANSI_PROTOTYPES
- pfile = va_arg (ap, cpp_reader *);
- msgid = va_arg (ap, const char *);
-#endif
+{
+ VA_OPEN (ap, msgid);
+ VA_FIXEDARG (ap, cpp_reader *, pfile);
+ VA_FIXEDARG (ap, const char *, msgid);
...
- va_end (ap);
+ VA_CLOSE (ap);
}
-For the curious, here are the definitions of the above macros. See
-ansidecl.h for the definitions of the above macros and more.
-
-#define PARAMS(paramlist) paramlist /* ISO C. */
-#define VPARAMS(args) args
-
-#define PARAMS(paramlist) () /* K+R C. */
-#define VPARAMS(args) (va_alist) va_dcl
+See ansidecl.h for the definitions of the above macros and more.
One aspect of using K+R style function declarations, is you cannot
have arguments whose types are char, short, or float, since without
@@ -305,8 +300,8 @@ long and int are not the same size.
Second, if you write a function definition with no return type at
all:
- operate(a, b)
- int a, b;
+ operate (a, b)
+ int a, b;
{
...
}
@@ -319,8 +314,8 @@ Implicit function declarations always have return type int. So if you
correct the above definition to
void
- operate(a, b)
- int a, b;
+ operate (a, b)
+ int a, b;
...
but operate() is called above its definition, you will get an error
diff --git a/contrib/gcc/aclocal.m4 b/contrib/gcc/aclocal.m4
index 0c4b5c6..b634e06 100644
--- a/contrib/gcc/aclocal.m4
+++ b/contrib/gcc/aclocal.m4
@@ -306,10 +306,7 @@ procedure conftest is begin null; end conftest;
EOF
gcc_cv_prog_adac=no
# Have to do ac_tool_prefix and user overrides by hand.
-user_adac=$ADAC
-user_cc=$CC
-for cand in ${ac_tool_prefix}$user_adac $user_adac \
- ${ac_tool_prefix}$user_cc $user_cc \
+for cand in ${ADAC+"$ADAC"} ${CC+"$CC"} \
${ac_tool_prefix}gcc gcc \
${ac_tool_prefix}cc cc \
${ac_tool_prefix}gnatgcc gnatgcc \
@@ -399,352 +396,93 @@ fi
AC_SUBST($1)dnl
])
-# Check whether mmap can map an arbitrary page from /dev/zero or with
-# MAP_ANONYMOUS, without MAP_FIXED.
-AC_DEFUN([AC_FUNC_MMAP_ANYWHERE],
-[AC_CHECK_FUNCS(getpagesize)
-# The test program for the next two tests is the same except for one
-# set of ifdefs.
-changequote({{{,}}})dnl
-{{{cat >ct-mmap.inc <<'EOF'
-#include <sys/types.h>
+# mmap(2) blacklisting. Some platforms provide the mmap library routine
+# but don't support all of the features we need from it.
+AC_DEFUN([gcc_AC_FUNC_MMAP_BLACKLIST],
+[if test $ac_cv_header_sys_mman_h != yes \
+ || test $ac_cv_func_mmap != yes; then
+ gcc_cv_func_mmap_file=no
+ gcc_cv_func_mmap_dev_zero=no
+ gcc_cv_func_mmap_anon=no
+else
+ AC_CACHE_CHECK([whether read-only mmap of a plain file works],
+ gcc_cv_func_mmap_file,
+ [# Add a system to this blacklist if
+ # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
+ # memory area containing the same data that you'd get if you applied
+ # read() to the same fd. The only system known to have a problem here
+ # is VMS, where text files have record structure.
+ case "$host_os" in
+ vms*)
+ gcc_cv_func_mmap_file=no ;;
+ *)
+ gcc_cv_func_mmap_file=yes;;
+ esac])
+ AC_CACHE_CHECK([whether mmap from /dev/zero works],
+ gcc_cv_func_mmap_dev_zero,
+ [# Add a system to this blacklist if it has mmap() but /dev/zero
+ # does not exist, or if mmapping /dev/zero does not give anonymous
+ # zeroed pages with both the following properties:
+ # 1. If you map N consecutive pages in with one call, and then
+ # unmap any subset of those pages, the pages that were not
+ # explicitly unmapped remain accessible.
+ # 2. If you map two adjacent blocks of memory and then unmap them
+ # both at once, they must both go away.
+ # Systems known to be in this category are Windows (all variants),
+ # VMS, and Darwin.
+ case "$host_os" in
+ vms* | cygwin* | pe | mingw* | darwin*)
+ gcc_cv_func_mmap_dev_zero=no ;;
+ *)
+ gcc_cv_func_mmap_dev_zero=yes;;
+ esac])
+
+ # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
+ AC_CACHE_CHECK([for MAP_ANON(YMOUS)], gcc_cv_decl_map_anon,
+ [AC_TRY_COMPILE(
+[#include <sys/types.h>
#include <sys/mman.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <setjmp.h>
-#include <stdio.h>
-
-#if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
-# define MAP_ANONYMOUS MAP_ANON
-#endif
-
-/* This mess was copied from the GNU getpagesize.h. */
-#ifndef HAVE_GETPAGESIZE
-# ifdef HAVE_UNISTD_H
-# include <unistd.h>
-# endif
-
-/* Assume that all systems that can run configure have sys/param.h. */
-# ifndef HAVE_SYS_PARAM_H
-# define HAVE_SYS_PARAM_H 1
-# endif
-
-# ifdef _SC_PAGESIZE
-# define getpagesize() sysconf(_SC_PAGESIZE)
-# else /* no _SC_PAGESIZE */
-# ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-# ifdef EXEC_PAGESIZE
-# define getpagesize() EXEC_PAGESIZE
-# else /* no EXEC_PAGESIZE */
-# ifdef NBPG
-# define getpagesize() NBPG * CLSIZE
-# ifndef CLSIZE
-# define CLSIZE 1
-# endif /* no CLSIZE */
-# else /* no NBPG */
-# ifdef NBPC
-# define getpagesize() NBPC
-# else /* no NBPC */
-# ifdef PAGESIZE
-# define getpagesize() PAGESIZE
-# endif /* PAGESIZE */
-# endif /* no NBPC */
-# endif /* no NBPG */
-# endif /* no EXEC_PAGESIZE */
-# else /* no HAVE_SYS_PARAM_H */
-# define getpagesize() 8192 /* punt totally */
-# endif /* no HAVE_SYS_PARAM_H */
-# endif /* no _SC_PAGESIZE */
-
-#endif /* no HAVE_GETPAGESIZE */
-
-#ifndef MAP_FAILED
-# define MAP_FAILED -1
-#endif
-
-#undef perror_exit
-#define perror_exit(str, val) \
- do { perror(str); exit(val); } while (0)
-
-/* Some versions of cygwin mmap require that munmap is called with the
- same parameters as mmap. GCC expects that this is not the case.
- Test for various forms of this problem. Warning - icky signal games. */
-
-static sigset_t unblock_sigsegv;
-static jmp_buf r;
-static size_t pg;
-static int devzero;
+#include <unistd.h>
-static char *
-anonmap (size)
- size_t size;
-{
-#ifdef USE_MAP_ANON
- return (char *) mmap (0, size, PROT_READ|PROT_WRITE,
- MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
-#else
- return (char *) mmap (0, size, PROT_READ|PROT_WRITE,
- MAP_PRIVATE, devzero, 0);
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
#endif
-}
-
-static void
-sigsegv (unused)
- int unused;
-{
- sigprocmask (SIG_UNBLOCK, &unblock_sigsegv, 0);
- longjmp (r, 1);
-}
-
-/* Basic functionality test. */
-void
-test_0 ()
-{
- char *x = anonmap (pg);
- if (x == (char *) MAP_FAILED)
- perror_exit("test 0 mmap", 2);
-
- *(int *)x += 1;
-
- if (munmap(x, pg) < 0)
- perror_exit("test 0 munmap", 3);
-}
-
-/* 1. If we map a 2-page region and unmap its second page, the first page
- must remain. */
-static void
-test_1 ()
-{
- char *x = anonmap (pg * 2);
- if (x == (char *)MAP_FAILED)
- perror_exit ("test 1 mmap", 4);
-
- signal (SIGSEGV, sigsegv);
- if (setjmp (r))
- perror_exit ("test 1 fault", 5);
-
- x[0] = 1;
- x[pg] = 1;
-
- if (munmap (x + pg, pg) < 0)
- perror_exit ("test 1 munmap 1", 6);
- x[0] = 2;
-
- if (setjmp (r) == 0)
- {
- x[pg] = 1;
- perror_exit ("test 1 no fault", 7);
- }
- if (munmap (x, pg) < 0)
- perror_exit ("test 1 munmap 2", 8);
-}
-
-/* 2. If we map a 2-page region and unmap its first page, the second
- page must remain. */
-static void
-test_2 ()
-{
- char *x = anonmap (pg * 2);
- if (x == (char *)MAP_FAILED)
- perror_exit ("test 2 mmap", 9);
-
- signal (SIGSEGV, sigsegv);
- if (setjmp (r))
- perror_exit ("test 2 fault", 10);
-
- x[0] = 1;
- x[pg] = 1;
-
- if (munmap (x, pg) < 0)
- perror_exit ("test 2 munmap 1", 11);
-
- x[pg] = 2;
-
- if (setjmp (r) == 0)
- {
- x[0] = 1;
- perror_exit ("test 2 no fault", 12);
- }
-
- if (munmap (x+pg, pg) < 0)
- perror_exit ("test 2 munmap 2", 13);
-}
-
-/* 3. If we map two adjacent 1-page regions and unmap them both with
- one munmap, both must go away.
-
- Getting two adjacent 1-page regions with two mmap calls is slightly
- tricky. All OS's tested skip over already-allocated blocks; therefore
- we have been careful to unmap all allocated regions in previous tests.
- HP/UX allocates pages backward in memory. No OS has yet been observed
- to be so perverse as to leave unmapped space between consecutive calls
- to mmap. */
-
-static void
-test_3 ()
-{
- char *x, *y, *z;
-
- x = anonmap (pg);
- if (x == (char *)MAP_FAILED)
- perror_exit ("test 3 mmap 1", 14);
- y = anonmap (pg);
- if (y == (char *)MAP_FAILED)
- perror_exit ("test 3 mmap 2", 15);
-
- if (y != x + pg)
- {
- if (y == x - pg)
- z = y, y = x, x = z;
- else
- {
- fprintf (stderr, "test 3 nonconsecutive pages - %lx, %lx\n",
- (unsigned long)x, (unsigned long)y);
- exit (16);
- }
- }
-
- signal (SIGSEGV, sigsegv);
- if (setjmp (r))
- perror_exit ("test 3 fault", 17);
-
- x[0] = 1;
- y[0] = 1;
-
- if (munmap (x, pg*2) < 0)
- perror_exit ("test 3 munmap", 18);
-
- if (setjmp (r) == 0)
- {
- x[0] = 1;
- perror_exit ("test 3 no fault 1", 19);
- }
-
- signal (SIGSEGV, sigsegv);
- if (setjmp (r) == 0)
- {
- y[0] = 1;
- perror_exit ("test 3 no fault 2", 20);
- }
-}
-
-int
-main ()
-{
- sigemptyset (&unblock_sigsegv);
- sigaddset (&unblock_sigsegv, SIGSEGV);
- pg = getpagesize ();
-#ifndef USE_MAP_ANON
- devzero = open ("/dev/zero", O_RDWR);
- if (devzero < 0)
- perror_exit ("open /dev/zero", 1);
-#endif
-
- test_0();
- test_1();
- test_2();
- test_3();
-
- exit(0);
-}
-EOF}}}
-changequote([,])dnl
-
-AC_CACHE_CHECK(for working mmap from /dev/zero,
- ac_cv_func_mmap_dev_zero,
-[AC_TRY_RUN(
- [#include "ct-mmap.inc"],
- ac_cv_func_mmap_dev_zero=yes,
- [if test $? -lt 4
- then ac_cv_func_mmap_dev_zero=no
- else ac_cv_func_mmap_dev_zero=buggy
- fi],
- # If this is not cygwin, and /dev/zero is a character device, it's probably
- # safe to assume it works.
- [case "$host_os" in
- cygwin* | win32 | pe | mingw* ) ac_cv_func_mmap_dev_zero=buggy ;;
- * ) if test -c /dev/zero
- then ac_cv_func_mmap_dev_zero=yes
- else ac_cv_func_mmap_dev_zero=no
- fi ;;
- esac])
-])
-if test $ac_cv_func_mmap_dev_zero = yes; then
- AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1,
- [Define if mmap can get us zeroed pages from /dev/zero.])
-fi
-
-AC_CACHE_CHECK([for working mmap with MAP_ANON(YMOUS)],
- ac_cv_func_mmap_anon,
-[AC_TRY_RUN(
- [#define USE_MAP_ANON
-#include "ct-mmap.inc"],
- ac_cv_func_mmap_anon=yes,
- [if test $? -lt 4
- then ac_cv_func_mmap_anon=no
- else ac_cv_func_mmap_anon=buggy
- fi],
- # Unlike /dev/zero, it is not safe to assume MAP_ANON(YMOUS) works
- # just because it's there. Some SCO Un*xen define it but don't implement it.
- ac_cv_func_mmap_anon=no)
-])
-if test $ac_cv_func_mmap_anon = yes; then
- AC_DEFINE(HAVE_MMAP_ANON, 1,
- [Define if mmap can get us zeroed pages using MAP_ANON(YMOUS).])
+],
+[int n = MAP_ANONYMOUS;],
+ gcc_cv_decl_map_anon=yes,
+ gcc_cv_decl_map_anon=no)])
+
+ if test $gcc_cv_decl_map_anon = no; then
+ gcc_cv_func_mmap_anon=no
+ else
+ AC_CACHE_CHECK([whether mmap with MAP_ANON(YMOUS) works],
+ gcc_cv_func_mmap_anon,
+ [# Add a system to this blacklist if it has mmap() and MAP_ANON or
+ # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
+ # doesn't give anonymous zeroed pages with the same properties listed
+ # above for use of /dev/zero.
+ # Systems known to be in this category are Windows, VMS, and SCO Unix.
+ case "$host_os" in
+ vms* | cygwin* | pe | mingw* | sco* | udk* )
+ gcc_cv_func_mmap_anon=no ;;
+ *)
+ gcc_cv_func_mmap_anon=yes;;
+ esac])
+ fi
fi
-rm -f ct-mmap.inc
-])
-
-# Check whether mmap can map a plain file, without MAP_FIXED.
-AC_DEFUN([AC_FUNC_MMAP_FILE],
-[AC_CACHE_CHECK(for working mmap of a file, ac_cv_func_mmap_file,
-[# Create a file one thousand bytes long.
-for i in 1 2 3 4 5 6 7 8 9 0
-do for j in 1 2 3 4 5 6 7 8 9 0
-do echo $i $j xxxxx
-done
-done > conftestdata$$
-
-AC_TRY_RUN([
-/* Test by Zack Weinberg. Modified from MMAP_ANYWHERE test by
- Richard Henderson and Alexandre Oliva.
- Check whether read-only mmap of a plain file works. */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-
-int main()
-{
- char *x;
- int fd;
- struct stat st;
- fd = open("conftestdata$$", O_RDONLY);
- if (fd < 0)
- exit(1);
-
- if (fstat (fd, &st))
- exit(2);
-
- x = (char*)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (x == (char *) -1)
- exit(3);
-
- if (x[0] != '1' || x[1] != ' ' || x[2] != '1' || x[3] != ' ')
- exit(4);
-
- if (munmap(x, st.st_size) < 0)
- exit(5);
-
- exit(0);
-}], ac_cv_func_mmap_file=yes, ac_cv_func_mmap_file=no,
-ac_cv_func_mmap_file=no)])
-if test $ac_cv_func_mmap_file = yes; then
+if test $gcc_cv_func_mmap_file = yes; then
AC_DEFINE(HAVE_MMAP_FILE, 1,
[Define if read-only mmap of a plain file works.])
fi
+if test $gcc_cv_func_mmap_dev_zero = yes; then
+ AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1,
+ [Define if mmap of /dev/zero works.])
+fi
+if test $gcc_cv_func_mmap_anon = yes; then
+ AC_DEFINE(HAVE_MMAP_ANON, 1,
+ [Define if mmap with MAP_ANON(YMOUS) works.])
+fi
])
dnl Locate a program and check that its version is acceptable.
@@ -1690,3 +1428,29 @@ strdup strtoul tsearch __argz_count __argz_stringify __argz_next])
INTL_LIBTOOL_SUFFIX_PREFIX=ifelse([$1], use-libtool, [l], [])
AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX)
])
+
+AC_DEFUN(gcc_AC_INITFINI_ARRAY,
+[AC_CACHE_CHECK(for .preinit_array/.init_array/.fini_array support,
+ gcc_cv_initfinit_array, [dnl
+ cat > conftest.c <<EOF
+static int x = -1;
+int main (void) { return x; }
+int foo (void) { x = 0; }
+int (*fp) (void) __attribute__ ((section (".init_array"))) = foo;
+EOF
+ if AC_TRY_COMMAND([${CC-cc} -o conftest conftest.c 1>&AS_MESSAGE_LOG_FD])
+ then
+ if ./conftest; then
+ gcc_cv_initfinit_array=yes
+ else
+ gcc_cv_initfinit_array=no
+ fi
+ else
+ gcc_cv_initfinit_array=no
+ fi
+ rm -f conftest*])
+ AC_SUBST(gcc_cv_initfinit_array)
+ if test $gcc_cv_initfinit_array = yes; then
+ AC_DEFINE(HAVE_INITFINI_ARRAY, 1,
+ [Define .init_array/.fini_array sections are available and working.])
+ fi])
diff --git a/contrib/gcc/alias.c b/contrib/gcc/alias.c
index db9dc07..4fa4f5c 100644
--- a/contrib/gcc/alias.c
+++ b/contrib/gcc/alias.c
@@ -1,5 +1,6 @@
/* Alias analysis for GNU C
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ Free Software Foundation, Inc.
Contributed by John Carr (jfc@mit.edu).
This file is part of GCC.
@@ -36,6 +37,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "splay-tree.h"
#include "ggc.h"
#include "langhooks.h"
+#include "target.h"
/* The alias sets assigned to MEMs assist the back-end in determining
which MEMs can alias which other MEMs. In general, two MEMs in
@@ -75,7 +77,7 @@ typedef struct alias_set_entry
/* The children of the alias set. These are not just the immediate
children, but, in fact, all descendents. So, if we have:
- struct T { struct S s; float f; }
+ struct T { struct S s; float f; }
continuing our example above, the children here will be all of
`int', `double', `float', and `struct S'. */
@@ -108,7 +110,13 @@ static tree decl_for_component_ref PARAMS ((tree));
static rtx adjust_offset_for_component_ref PARAMS ((tree, rtx));
static int nonoverlapping_memrefs_p PARAMS ((rtx, rtx));
static int write_dependence_p PARAMS ((rtx, rtx, int));
+
+static int nonlocal_mentioned_p_1 PARAMS ((rtx *, void *));
static int nonlocal_mentioned_p PARAMS ((rtx));
+static int nonlocal_referenced_p_1 PARAMS ((rtx *, void *));
+static int nonlocal_referenced_p PARAMS ((rtx));
+static int nonlocal_set_p_1 PARAMS ((rtx *, void *));
+static int nonlocal_set_p PARAMS ((rtx));
/* Set up all info needed to perform alias analysis on memory references. */
@@ -125,7 +133,7 @@ static int nonlocal_mentioned_p PARAMS ((rtx));
/* Cap the number of passes we make over the insns propagating alias
information through set chains. 10 is a completely arbitrary choice. */
#define MAX_ALIAS_LOOP_PASSES 10
-
+
/* reg_base_value[N] gives an address to which register N is related.
If all sets after the first add or subtract to the current value
or otherwise modify it so it does not point to a different top level
@@ -134,7 +142,7 @@ static int nonlocal_mentioned_p PARAMS ((rtx));
A base address can be an ADDRESS, SYMBOL_REF, or LABEL_REF. ADDRESS
expressions represent certain special values: function arguments and
- the stack, frame, and argument pointers.
+ the stack, frame, and argument pointers.
The contents of an ADDRESS is not normally used, the mode of the
ADDRESS determines whether the ADDRESS is a function argument or some
@@ -145,10 +153,14 @@ static int nonlocal_mentioned_p PARAMS ((rtx));
current function performs nonlocal memory memory references for the
purposes of marking the function as a constant function. */
-static rtx *reg_base_value;
+static GTY((length ("reg_base_value_size"))) rtx *reg_base_value;
static rtx *new_reg_base_value;
static unsigned int reg_base_value_size; /* size of reg_base_value array */
+/* Static hunks of RTL used by the aliasing code; these are initialized
+ once per function to avoid unnecessary RTL allocations. */
+static GTY (()) rtx static_reg_base_value[FIRST_PSEUDO_REGISTER];
+
#define REG_BASE_VALUE(X) \
(REGNO (X) < reg_base_value_size \
? reg_base_value[REGNO (X)] : 0)
@@ -188,7 +200,7 @@ char *reg_known_equiv_p;
/* True when scanning insns from the start of the rtl to the
NOTE_INSN_FUNCTION_BEG note. */
-static int copying_arguments;
+static bool copying_arguments;
/* The splay-tree used to store the various alias set entries. */
static splay_tree alias_sets;
@@ -209,12 +221,12 @@ get_alias_set_entry (alias_set)
/* Returns nonzero if the alias sets for MEM1 and MEM2 are such that
the two MEMs cannot alias each other. */
-static int
+static int
mems_in_disjoint_alias_sets_p (mem1, mem2)
rtx mem1;
rtx mem2;
{
-#ifdef ENABLE_CHECKING
+#ifdef ENABLE_CHECKING
/* Perform a basic sanity check. Namely, that there are no alias sets
if we're not using strict aliasing. This helps to catch bugs
whereby someone uses PUT_CODE, but doesn't clear MEM_ALIAS_SET, or
@@ -311,6 +323,8 @@ int
objects_must_conflict_p (t1, t2)
tree t1, t2;
{
+ HOST_WIDE_INT set1, set2;
+
/* If neither has a type specified, we don't know if they'll conflict
because we may be using them to store objects of various types, for
example the argument and local variables areas of inlined functions. */
@@ -331,15 +345,15 @@ objects_must_conflict_p (t1, t2)
|| (t1 != 0 && TYPE_VOLATILE (t1) && t2 != 0 && TYPE_VOLATILE (t2)))
return 1;
- /* If one is aggregate and the other is scalar then they may not
- conflict. */
- if ((t1 != 0 && AGGREGATE_TYPE_P (t1))
- != (t2 != 0 && AGGREGATE_TYPE_P (t2)))
- return 0;
+ set1 = t1 ? get_alias_set (t1) : 0;
+ set2 = t2 ? get_alias_set (t2) : 0;
- /* Otherwise they conflict only if the alias sets conflict. */
- return alias_sets_conflict_p (t1 ? get_alias_set (t1) : 0,
- t2 ? get_alias_set (t2) : 0);
+ /* Otherwise they conflict if they have no alias set or the same. We
+ can't simply use alias_sets_conflict_p here, because we must make
+ sure that every subtype of t1 will conflict with every subtype of
+ t2 for which a pair of subobjects of these respective subtypes
+ overlaps on the stack. */
+ return set1 == 0 || set2 == 0 || set1 == set2;
}
/* T is an expression with pointer type. Find the DECL on which this
@@ -508,8 +522,8 @@ get_alias_set (t)
else
{
DECL_POINTER_ALIAS_SET (decl) = new_alias_set ();
- record_alias_subset (pointed_to_alias_set,
- DECL_POINTER_ALIAS_SET (decl));
+ record_alias_subset (pointed_to_alias_set,
+ DECL_POINTER_ALIAS_SET (decl));
}
}
@@ -603,7 +617,7 @@ new_alias_set ()
not vice versa. For example, in C, a store to an `int' can alias a
structure containing an `int', but not vice versa. Here, the
structure would be the SUPERSET and `int' the SUBSET. This
- function should be called only once per SUPERSET/SUBSET pair.
+ function should be called only once per SUPERSET/SUBSET pair.
It is illegal for SUPERSET to be zero; everything is implicitly a
subset of alias set zero. */
@@ -625,14 +639,14 @@ record_alias_subset (superset, subset)
abort ();
superset_entry = get_alias_set_entry (superset);
- if (superset_entry == 0)
+ if (superset_entry == 0)
{
/* Create an entry for the SUPERSET, so that we have a place to
attach the SUBSET. */
superset_entry
= (alias_set_entry) xmalloc (sizeof (struct alias_set_entry));
superset_entry->alias_set = superset;
- superset_entry->children
+ superset_entry->children
= splay_tree_new (splay_tree_compare_ints, 0, 0);
superset_entry->has_zero_child = 0;
splay_tree_insert (alias_sets, (splay_tree_key) superset,
@@ -646,7 +660,7 @@ record_alias_subset (superset, subset)
subset_entry = get_alias_set_entry (subset);
/* If there is an entry for the subset, enter all of its children
(if they are not already present) as children of the SUPERSET. */
- if (subset_entry)
+ if (subset_entry)
{
if (subset_entry->has_zero_child)
superset_entry->has_zero_child = 1;
@@ -656,7 +670,7 @@ record_alias_subset (superset, subset)
}
/* Enter the SUBSET itself as a child of the SUPERSET. */
- splay_tree_insert (superset_entry->children,
+ splay_tree_insert (superset_entry->children,
(splay_tree_key) subset, 0);
}
}
@@ -687,6 +701,17 @@ record_component_aliases (type)
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
+ /* Recursively record aliases for the base classes, if there are any */
+ if (TYPE_BINFO (type) != NULL && TYPE_BINFO_BASETYPES (type) != NULL)
+ {
+ int i;
+ for (i = 0; i < TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)); i++)
+ {
+ tree binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), i);
+ record_alias_subset (superset,
+ get_alias_set (BINFO_TYPE (binfo)));
+ }
+ }
for (field = TYPE_FIELDS (type); field != 0; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL && ! DECL_NONADDRESSABLE_P (field))
record_alias_subset (superset, get_alias_set (TREE_TYPE (field)));
@@ -759,9 +784,17 @@ find_base_value (src)
The test above is not sufficient because the scheduler may move
a copy out of an arg reg past the NOTE_INSN_FUNCTION_BEGIN. */
if ((regno >= FIRST_PSEUDO_REGISTER || fixed_regs[regno])
- && regno < reg_base_value_size
- && reg_base_value[regno])
- return reg_base_value[regno];
+ && regno < reg_base_value_size)
+ {
+ /* If we're inside init_alias_analysis, use new_reg_base_value
+ to reduce the number of relaxation iterations. */
+ if (new_reg_base_value && new_reg_base_value[regno]
+ && REG_N_SETS (regno) == 1)
+ return new_reg_base_value[regno];
+
+ if (reg_base_value[regno])
+ return reg_base_value[regno];
+ }
return src;
@@ -1111,7 +1144,7 @@ rtx_equal_for_memref_p (x, y)
case LABEL_REF:
return XEXP (x, 0) == XEXP (y, 0);
-
+
case SYMBOL_REF:
return XSTR (x, 0) == XSTR (y, 0);
@@ -1248,7 +1281,7 @@ find_base_term (x)
case TRUNCATE:
if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (Pmode))
- return 0;
+ return 0;
/* Fall through. */
case HIGH:
case PRE_INC:
@@ -1302,7 +1335,7 @@ find_base_term (x)
tests can certainly be added. For example, if one of the operands
is a shift or multiply, then it must be the index register and the
other operand is the base register. */
-
+
if (tmp1 == pic_offset_table_rtx && CONSTANT_P (tmp2))
return find_base_term (tmp2);
@@ -1400,7 +1433,7 @@ base_alias_check (x, y, x_mode, y_mode)
if (rtx_equal_p (x_base, y_base))
return 1;
- /* The base addresses of the read and write are different expressions.
+ /* The base addresses of the read and write are different expressions.
If they are both symbols and they are not accessed via AND, there is
no conflict. We can bring knowledge of object alignment into play
here. For example, on alpha, "char a, b;" can alias one another,
@@ -1475,7 +1508,7 @@ addr_side_effect_eval (addr, size, n_refs)
int n_refs;
{
int offset = 0;
-
+
switch (GET_CODE (addr))
{
case PRE_INC:
@@ -1494,7 +1527,7 @@ addr_side_effect_eval (addr, size, n_refs)
default:
return addr;
}
-
+
if (offset)
addr = gen_rtx_PLUS (GET_MODE (addr), XEXP (addr, 0), GEN_INT (offset));
else
@@ -1657,7 +1690,7 @@ memrefs_conflict_p (xsize, x, ysize, y, c)
}
/* Treat an access through an AND (e.g. a subword access on an Alpha)
- as an access with indeterminate size. Assume that references
+ as an access with indeterminate size. Assume that references
besides AND are aligned, so if the size of the other reference is
at least as large as the alignment, assume no other overlap. */
if (GET_CODE (x) == AND && GET_CODE (XEXP (x, 1)) == CONST_INT)
@@ -1669,7 +1702,7 @@ memrefs_conflict_p (xsize, x, ysize, y, c)
if (GET_CODE (y) == AND && GET_CODE (XEXP (y, 1)) == CONST_INT)
{
/* ??? If we are indexing far enough into the array/structure, we
- may yet be able to determine that we can not overlap. But we
+ may yet be able to determine that we can not overlap. But we
also need to that we are far enough from the end not to overlap
a following reference, so we do nothing with that for now. */
if (GET_CODE (x) == AND || xsize < -INTVAL (XEXP (y, 1)))
@@ -1731,7 +1764,7 @@ memrefs_conflict_p (xsize, x, ysize, y, c)
If both memory references are volatile, then there must always be a
dependence between the two references, since their order can not be
changed. A volatile and non-volatile reference can be interchanged
- though.
+ though.
A MEM_IN_STRUCT reference at a non-AND varying address can never
conflict with a non-MEM_IN_STRUCT reference at a fixed address. We
@@ -1758,23 +1791,23 @@ read_dependence (mem, x)
to decide whether or not an address may vary; it should return
nonzero whenever variation is possible.
MEM1_ADDR and MEM2_ADDR are the addresses of MEM1 and MEM2. */
-
+
static rtx
fixed_scalar_and_varying_struct_p (mem1, mem2, mem1_addr, mem2_addr, varies_p)
rtx mem1, mem2;
rtx mem1_addr, mem2_addr;
int (*varies_p) PARAMS ((rtx, int));
-{
+{
if (! flag_strict_aliasing)
return NULL_RTX;
- if (MEM_SCALAR_P (mem1) && MEM_IN_STRUCT_P (mem2)
+ if (MEM_SCALAR_P (mem1) && MEM_IN_STRUCT_P (mem2)
&& !varies_p (mem1_addr, 1) && varies_p (mem2_addr, 1))
/* MEM1 is a scalar at a fixed address; MEM2 is a struct at a
varying address. */
return mem1;
- if (MEM_IN_STRUCT_P (mem1) && MEM_SCALAR_P (mem2)
+ if (MEM_IN_STRUCT_P (mem1) && MEM_SCALAR_P (mem2)
&& varies_p (mem1_addr, 1) && !varies_p (mem2_addr, 1))
/* MEM2 is a scalar at a fixed address; MEM1 is a struct at a
varying address. */
@@ -1794,7 +1827,7 @@ aliases_everything_p (mem)
/* If the address is an AND, its very hard to know at what it is
actually pointing. */
return 1;
-
+
return 0;
}
@@ -1852,7 +1885,7 @@ nonoverlapping_component_refs_p (x, y)
while (x && y
&& TREE_CODE (x) == COMPONENT_REF
&& TREE_CODE (y) == COMPONENT_REF);
-
+
return false;
}
@@ -1885,7 +1918,7 @@ adjust_offset_for_component_ref (x, offset)
return NULL_RTX;
ioffset = INTVAL (offset);
- do
+ do
{
tree field = TREE_OPERAND (x, 1);
@@ -1986,15 +2019,15 @@ nonoverlapping_memrefs_p (x, y)
offsety = INTVAL (XEXP (basey, 1)), basey = XEXP (basey, 0);
/* If the bases are different, we know they do not overlap if both
- are constants or if one is a constant and the other a pointer into the
+ are constants or if one is a constant and the other a pointer into the
stack frame. Otherwise a different base means we can't tell if they
overlap or not. */
if (! rtx_equal_p (basex, basey))
- return ((CONSTANT_P (basex) && CONSTANT_P (basey))
- || (CONSTANT_P (basex) && REG_P (basey)
- && REGNO_PTR_FRAME_P (REGNO (basey)))
- || (CONSTANT_P (basey) && REG_P (basex)
- && REGNO_PTR_FRAME_P (REGNO (basex))));
+ return ((CONSTANT_P (basex) && CONSTANT_P (basey))
+ || (CONSTANT_P (basex) && REG_P (basey)
+ && REGNO_PTR_FRAME_P (REGNO (basey)))
+ || (CONSTANT_P (basey) && REG_P (basex)
+ && REGNO_PTR_FRAME_P (REGNO (basex))));
sizex = (GET_CODE (rtlx) != MEM ? (int) GET_MODE_SIZE (GET_MODE (rtlx))
: MEM_SIZE (rtlx) ? INTVAL (MEM_SIZE (rtlx))
@@ -2111,9 +2144,9 @@ true_dependence (mem, mem_mode, x, varies)
}
/* Canonical true dependence: X is read after store in MEM takes place.
- Variant of true_dependence which assumes MEM has already been
- canonicalized (hence we no longer do that here).
- The mem_addr argument has been added, since true_dependence computed
+ Variant of true_dependence which assumes MEM has already been
+ canonicalized (hence we no longer do that here).
+ The mem_addr argument has been added, since true_dependence computed
this value prior to canonicalizing. */
int
@@ -2177,8 +2210,8 @@ canon_true_dependence (mem, mem_mode, mem_addr, x, varies)
varies);
}
-/* Returns non-zero if a write to X might alias a previous read from
- (or, if WRITEP is non-zero, a write to) MEM. */
+/* Returns nonzero if a write to X might alias a previous read from
+ (or, if WRITEP is nonzero, a write to) MEM. */
static int
write_dependence_p (mem, x, writep)
@@ -2239,7 +2272,7 @@ write_dependence_p (mem, x, writep)
SIZE_FOR_MODE (x), x_addr, 0))
return 0;
- fixed_scalar
+ fixed_scalar
= fixed_scalar_and_varying_struct_p (mem, x, mem_addr, x_addr,
rtx_addr_varies_p);
@@ -2266,36 +2299,23 @@ output_dependence (mem, x)
{
return write_dependence_p (mem, x, /*writep=*/1);
}
-
-/* Returns non-zero if X mentions something which is not
- local to the function and is not constant. */
+
+/* A subroutine of nonlocal_mentioned_p, returns 1 if *LOC mentions
+ something which is not local to the function and is not constant. */
static int
-nonlocal_mentioned_p (x)
- rtx x;
+nonlocal_mentioned_p_1 (loc, data)
+ rtx *loc;
+ void *data ATTRIBUTE_UNUSED;
{
+ rtx x = *loc;
rtx base;
- RTX_CODE code;
int regno;
- code = GET_CODE (x);
-
- if (GET_RTX_CLASS (code) == 'i')
- {
- /* Constant functions can be constant if they don't use
- scratch memory used to mark function w/o side effects. */
- if (code == CALL_INSN && CONST_OR_PURE_CALL_P (x))
- {
- x = CALL_INSN_FUNCTION_USAGE (x);
- if (x == 0)
- return 0;
- }
- else
- x = PATTERN (x);
- code = GET_CODE (x);
- }
+ if (! x)
+ return 0;
- switch (code)
+ switch (GET_CODE (x))
{
case SUBREG:
if (GET_CODE (SUBREG_REG (x)) == REG)
@@ -2377,74 +2397,263 @@ nonlocal_mentioned_p (x)
break;
}
- /* Recursively scan the operands of this expression. */
+ return 0;
+}
- {
- const char *fmt = GET_RTX_FORMAT (code);
- int i;
-
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e' && XEXP (x, i))
- {
- if (nonlocal_mentioned_p (XEXP (x, i)))
- return 1;
- }
- else if (fmt[i] == 'E')
- {
- int j;
- for (j = 0; j < XVECLEN (x, i); j++)
- if (nonlocal_mentioned_p (XVECEXP (x, i, j)))
- return 1;
- }
- }
- }
+/* Returns nonzero if X might mention something which is not
+ local to the function and is not constant. */
+
+static int
+nonlocal_mentioned_p (x)
+ rtx x;
+{
+
+ if (INSN_P (x))
+ {
+ if (GET_CODE (x) == CALL_INSN)
+ {
+ if (! CONST_OR_PURE_CALL_P (x))
+ return 1;
+ x = CALL_INSN_FUNCTION_USAGE (x);
+ if (x == 0)
+ return 0;
+ }
+ else
+ x = PATTERN (x);
+ }
+
+ return for_each_rtx (&x, nonlocal_mentioned_p_1, NULL);
+}
+
+/* A subroutine of nonlocal_referenced_p, returns 1 if *LOC references
+ something which is not local to the function and is not constant. */
+
+static int
+nonlocal_referenced_p_1 (loc, data)
+ rtx *loc;
+ void *data ATTRIBUTE_UNUSED;
+{
+ rtx x = *loc;
+
+ if (! x)
+ return 0;
+
+ switch (GET_CODE (x))
+ {
+ case MEM:
+ case REG:
+ case SYMBOL_REF:
+ case SUBREG:
+ return nonlocal_mentioned_p (x);
+
+ case CALL:
+ /* Non-constant calls and recursion are not local. */
+ return 1;
+
+ case SET:
+ if (nonlocal_mentioned_p (SET_SRC (x)))
+ return 1;
+
+ if (GET_CODE (SET_DEST (x)) == MEM)
+ return nonlocal_mentioned_p (XEXP (SET_DEST (x), 0));
+
+ /* If the destination is anything other than a CC0, PC,
+ MEM, REG, or a SUBREG of a REG that occupies all of
+ the REG, then X references nonlocal memory if it is
+ mentioned in the destination. */
+ if (GET_CODE (SET_DEST (x)) != CC0
+ && GET_CODE (SET_DEST (x)) != PC
+ && GET_CODE (SET_DEST (x)) != REG
+ && ! (GET_CODE (SET_DEST (x)) == SUBREG
+ && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG
+ && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))
+ + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
+ == ((GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
+ + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))))
+ return nonlocal_mentioned_p (SET_DEST (x));
+ return 0;
+
+ case CLOBBER:
+ if (GET_CODE (XEXP (x, 0)) == MEM)
+ return nonlocal_mentioned_p (XEXP (XEXP (x, 0), 0));
+ return 0;
+
+ case USE:
+ return nonlocal_mentioned_p (XEXP (x, 0));
+
+ case ASM_INPUT:
+ case UNSPEC_VOLATILE:
+ return 1;
+
+ case ASM_OPERANDS:
+ if (MEM_VOLATILE_P (x))
+ return 1;
+
+ /* FALLTHROUGH */
+
+ default:
+ break;
+ }
return 0;
}
+/* Returns nonzero if X might reference something which is not
+ local to the function and is not constant. */
+
+static int
+nonlocal_referenced_p (x)
+ rtx x;
+{
+
+ if (INSN_P (x))
+ {
+ if (GET_CODE (x) == CALL_INSN)
+ {
+ if (! CONST_OR_PURE_CALL_P (x))
+ return 1;
+ x = CALL_INSN_FUNCTION_USAGE (x);
+ if (x == 0)
+ return 0;
+ }
+ else
+ x = PATTERN (x);
+ }
+
+ return for_each_rtx (&x, nonlocal_referenced_p_1, NULL);
+}
+
+/* A subroutine of nonlocal_set_p, returns 1 if *LOC sets
+ something which is not local to the function and is not constant. */
+
+static int
+nonlocal_set_p_1 (loc, data)
+ rtx *loc;
+ void *data ATTRIBUTE_UNUSED;
+{
+ rtx x = *loc;
+
+ if (! x)
+ return 0;
+
+ switch (GET_CODE (x))
+ {
+ case CALL:
+ /* Non-constant calls and recursion are not local. */
+ return 1;
+
+ case PRE_INC:
+ case PRE_DEC:
+ case POST_INC:
+ case POST_DEC:
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ return nonlocal_mentioned_p (XEXP (x, 0));
+
+ case SET:
+ if (nonlocal_mentioned_p (SET_DEST (x)))
+ return 1;
+ return nonlocal_set_p (SET_SRC (x));
+
+ case CLOBBER:
+ return nonlocal_mentioned_p (XEXP (x, 0));
+
+ case USE:
+ return 0;
+
+ case ASM_INPUT:
+ case UNSPEC_VOLATILE:
+ return 1;
+
+ case ASM_OPERANDS:
+ if (MEM_VOLATILE_P (x))
+ return 1;
+
+ /* FALLTHROUGH */
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* Returns nonzero if X might set something which is not
+ local to the function and is not constant. */
+
+static int
+nonlocal_set_p (x)
+ rtx x;
+{
+
+ if (INSN_P (x))
+ {
+ if (GET_CODE (x) == CALL_INSN)
+ {
+ if (! CONST_OR_PURE_CALL_P (x))
+ return 1;
+ x = CALL_INSN_FUNCTION_USAGE (x);
+ if (x == 0)
+ return 0;
+ }
+ else
+ x = PATTERN (x);
+ }
+
+ return for_each_rtx (&x, nonlocal_set_p_1, NULL);
+}
+
/* Mark the function if it is constant. */
void
mark_constant_function ()
{
rtx insn;
- int nonlocal_mentioned;
+ int nonlocal_memory_referenced;
- if (TREE_PUBLIC (current_function_decl)
- || TREE_READONLY (current_function_decl)
+ if (TREE_READONLY (current_function_decl)
|| DECL_IS_PURE (current_function_decl)
|| TREE_THIS_VOLATILE (current_function_decl)
- || TYPE_MODE (TREE_TYPE (current_function_decl)) == VOIDmode)
+ || TYPE_MODE (TREE_TYPE (current_function_decl)) == VOIDmode
+ || current_function_has_nonlocal_goto
+ || !(*targetm.binds_local_p) (current_function_decl))
return;
/* A loop might not return which counts as a side effect. */
if (mark_dfs_back_edges ())
return;
- nonlocal_mentioned = 0;
+ nonlocal_memory_referenced = 0;
init_alias_analysis ();
- /* Determine if this is a constant function. */
+ /* Determine if this is a constant or pure function. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (INSN_P (insn) && nonlocal_mentioned_p (insn))
- {
- nonlocal_mentioned = 1;
+ {
+ if (! INSN_P (insn))
+ continue;
+
+ if (nonlocal_set_p (insn) || global_reg_mentioned_p (insn)
+ || volatile_refs_p (PATTERN (insn)))
break;
- }
+
+ if (! nonlocal_memory_referenced)
+ nonlocal_memory_referenced = nonlocal_referenced_p (insn);
+ }
end_alias_analysis ();
/* Mark the function. */
- if (! nonlocal_mentioned)
+ if (insn)
+ ;
+ else if (nonlocal_memory_referenced)
+ DECL_IS_PURE (current_function_decl) = 1;
+ else
TREE_READONLY (current_function_decl) = 1;
}
-
-
-static HARD_REG_SET argument_registers;
+
void
init_alias_once ()
@@ -2460,7 +2669,19 @@ init_alias_once ()
numbers, so translate if necessary due to register windows. */
if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (i))
&& HARD_REGNO_MODE_OK (i, Pmode))
- SET_HARD_REG_BIT (argument_registers, i);
+ static_reg_base_value[i]
+ = gen_rtx_ADDRESS (VOIDmode, gen_rtx_REG (Pmode, i));
+
+ static_reg_base_value[STACK_POINTER_REGNUM]
+ = gen_rtx_ADDRESS (Pmode, stack_pointer_rtx);
+ static_reg_base_value[ARG_POINTER_REGNUM]
+ = gen_rtx_ADDRESS (Pmode, arg_pointer_rtx);
+ static_reg_base_value[FRAME_POINTER_REGNUM]
+ = gen_rtx_ADDRESS (Pmode, frame_pointer_rtx);
+#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+ static_reg_base_value[HARD_FRAME_POINTER_REGNUM]
+ = gen_rtx_ADDRESS (Pmode, hard_frame_pointer_rtx);
+#endif
alias_sets = splay_tree_new (splay_tree_compare_ints, 0, 0);
}
@@ -2479,10 +2700,10 @@ init_alias_analysis ()
reg_known_value_size = maxreg;
- reg_known_value
+ reg_known_value
= (rtx *) xcalloc ((maxreg - FIRST_PSEUDO_REGISTER), sizeof (rtx))
- FIRST_PSEUDO_REGISTER;
- reg_known_equiv_p
+ reg_known_equiv_p
= (char*) xcalloc ((maxreg - FIRST_PSEUDO_REGISTER), sizeof (char))
- FIRST_PSEUDO_REGISTER;
@@ -2490,8 +2711,8 @@ init_alias_analysis ()
optimization. Loop unrolling can create a large number of
registers. */
reg_base_value_size = maxreg * 2;
- reg_base_value = (rtx *) xcalloc (reg_base_value_size, sizeof (rtx));
- ggc_add_rtx_root (reg_base_value, reg_base_value_size);
+ reg_base_value = (rtx *) ggc_alloc_cleared (reg_base_value_size
+ * sizeof (rtx));
new_reg_base_value = (rtx *) xmalloc (reg_base_value_size * sizeof (rtx));
reg_seen = (char *) xmalloc (reg_base_value_size);
@@ -2534,7 +2755,7 @@ init_alias_analysis ()
/* We're at the start of the function each iteration through the
loop, so we're copying arguments. */
- copying_arguments = 1;
+ copying_arguments = true;
/* Wipe the potential alias information clean for this pass. */
memset ((char *) new_reg_base_value, 0, reg_base_value_size * sizeof (rtx));
@@ -2550,21 +2771,8 @@ init_alias_analysis ()
The address expression is VOIDmode for an argument and
Pmode for other registers. */
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (TEST_HARD_REG_BIT (argument_registers, i))
- new_reg_base_value[i] = gen_rtx_ADDRESS (VOIDmode,
- gen_rtx_REG (Pmode, i));
-
- new_reg_base_value[STACK_POINTER_REGNUM]
- = gen_rtx_ADDRESS (Pmode, stack_pointer_rtx);
- new_reg_base_value[ARG_POINTER_REGNUM]
- = gen_rtx_ADDRESS (Pmode, arg_pointer_rtx);
- new_reg_base_value[FRAME_POINTER_REGNUM]
- = gen_rtx_ADDRESS (Pmode, frame_pointer_rtx);
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
- new_reg_base_value[HARD_FRAME_POINTER_REGNUM]
- = gen_rtx_ADDRESS (Pmode, hard_frame_pointer_rtx);
-#endif
+ memcpy (new_reg_base_value, static_reg_base_value,
+ FIRST_PSEUDO_REGISTER * sizeof (rtx));
/* Walk the insns adding values to the new_reg_base_value array. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
@@ -2637,7 +2845,7 @@ init_alias_analysis ()
}
else if (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
- copying_arguments = 0;
+ copying_arguments = false;
}
/* Now propagate values from new_reg_base_value to reg_base_value. */
@@ -2705,12 +2913,7 @@ end_alias_analysis ()
reg_known_value_size = 0;
free (reg_known_equiv_p + FIRST_PSEUDO_REGISTER);
reg_known_equiv_p = 0;
- if (reg_base_value)
- {
- ggc_del_root (reg_base_value);
- free (reg_base_value);
- reg_base_value = 0;
- }
+ reg_base_value = 0;
reg_base_value_size = 0;
if (alias_invariant)
{
@@ -2718,3 +2921,5 @@ end_alias_analysis ()
alias_invariant = 0;
}
}
+
+#include "gt-alias.h"
diff --git a/contrib/gcc/ansidecl.h b/contrib/gcc/ansidecl.h
index 9a7c577..f8f2d73 100644
--- a/contrib/gcc/ansidecl.h
+++ b/contrib/gcc/ansidecl.h
@@ -136,10 +136,13 @@ So instead we use the macro below and test it against specific values. */
#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
#endif /* GCC_VERSION */
-#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32)
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32) || (defined(__alpha) && defined(__cplusplus))
/* All known AIX compilers implement these things (but don't always
define __STDC__). The RISC/OS MIPS compiler defines these things
in SVR4 mode, but does not define __STDC__. */
+/* eraxxon@alumni.rice.edu: The Compaq C++ compiler, unlike many other
+ C++ compilers, does not define __STDC__, though it acts as if this
+ was so. (Verified versions: 5.7, 6.2, 6.3, 6.5) */
#define ANSI_PROTOTYPES 1
#define PTR void *
@@ -265,8 +268,21 @@ So instead we use the macro below and test it against specific values. */
#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
#endif /* ATTRIBUTE_NORETURN */
+/* Attribute `nonnull' was valid as of gcc 3.3. */
+#ifndef ATTRIBUTE_NONNULL
+# if (GCC_VERSION >= 3003)
+# define ATTRIBUTE_NONNULL(m) __attribute__ ((__nonnull__ (m)))
+# else
+# define ATTRIBUTE_NONNULL(m)
+# endif /* GNUC >= 3.3 */
+#endif /* ATTRIBUTE_NONNULL */
+
+/* Use ATTRIBUTE_PRINTF when the format specifier must not be NULL.
+ This was the case for the `printf' format attribute by itself
+ before GCC 3.3, but as of 3.3 we need to add the `nonnull'
+ attribute to retain this behavior. */
#ifndef ATTRIBUTE_PRINTF
-#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
+#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) ATTRIBUTE_NONNULL(m)
#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)
#define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3)
#define ATTRIBUTE_PRINTF_3 ATTRIBUTE_PRINTF(3, 4)
@@ -274,6 +290,21 @@ So instead we use the macro below and test it against specific values. */
#define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6)
#endif /* ATTRIBUTE_PRINTF */
+/* Use ATTRIBUTE_NULL_PRINTF when the format specifier may be NULL. A
+ NULL format specifier was allowed as of gcc 3.3. */
+#ifndef ATTRIBUTE_NULL_PRINTF
+# if (GCC_VERSION >= 3003)
+# define ATTRIBUTE_NULL_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
+# else
+# define ATTRIBUTE_NULL_PRINTF(m, n)
+# endif /* GNUC >= 3.3 */
+# define ATTRIBUTE_NULL_PRINTF_1 ATTRIBUTE_NULL_PRINTF(1, 2)
+# define ATTRIBUTE_NULL_PRINTF_2 ATTRIBUTE_NULL_PRINTF(2, 3)
+# define ATTRIBUTE_NULL_PRINTF_3 ATTRIBUTE_NULL_PRINTF(3, 4)
+# define ATTRIBUTE_NULL_PRINTF_4 ATTRIBUTE_NULL_PRINTF(4, 5)
+# define ATTRIBUTE_NULL_PRINTF_5 ATTRIBUTE_NULL_PRINTF(5, 6)
+#endif /* ATTRIBUTE_NULL_PRINTF */
+
/* We use __extension__ in some places to suppress -pedantic warnings
about GCC extensions. This feature didn't work properly before
gcc 2.8. */
diff --git a/contrib/gcc/attribs.c b/contrib/gcc/attribs.c
index 47b7cf2..c5a8a73 100644
--- a/contrib/gcc/attribs.c
+++ b/contrib/gcc/attribs.c
@@ -29,164 +29,45 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ggc.h"
#include "expr.h"
#include "tm_p.h"
-#include "obstack.h"
#include "cpplib.h"
#include "target.h"
+#include "langhooks.h"
static void init_attributes PARAMS ((void));
-/* Table of the tables of attributes (common, format, language, machine)
+/* Table of the tables of attributes (common, language, format, machine)
searched. */
static const struct attribute_spec *attribute_tables[4];
static bool attributes_initialized = false;
-static tree handle_packed_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_nocommon_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_common_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_noreturn_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_noinline_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_always_inline_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_used_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_unused_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_const_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_transparent_union_attribute PARAMS ((tree *, tree, tree,
- int, bool *));
-static tree handle_constructor_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_destructor_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_mode_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_section_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_aligned_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_weak_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_alias_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_no_instrument_function_attribute PARAMS ((tree *, tree,
- tree, int,
- bool *));
-static tree handle_malloc_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_no_limit_stack_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_pure_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_deprecated_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree handle_vector_size_attribute PARAMS ((tree *, tree, tree, int,
- bool *));
-static tree vector_size_helper PARAMS ((tree, tree));
-
-/* Table of machine-independent attributes common to all C-like languages. */
-static const struct attribute_spec c_common_attribute_table[] =
-{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
- { "packed", 0, 0, false, false, false,
- handle_packed_attribute },
- { "nocommon", 0, 0, true, false, false,
- handle_nocommon_attribute },
- { "common", 0, 0, true, false, false,
- handle_common_attribute },
- /* FIXME: logically, noreturn attributes should be listed as
- "false, true, true" and apply to function types. But implementing this
- would require all the places in the compiler that use TREE_THIS_VOLATILE
- on a decl to identify non-returning functions to be located and fixed
- to check the function type instead. */
- { "noreturn", 0, 0, true, false, false,
- handle_noreturn_attribute },
- { "volatile", 0, 0, true, false, false,
- handle_noreturn_attribute },
- { "noinline", 0, 0, true, false, false,
- handle_noinline_attribute },
- { "always_inline", 0, 0, true, false, false,
- handle_always_inline_attribute },
- { "used", 0, 0, true, false, false,
- handle_used_attribute },
- { "unused", 0, 0, false, false, false,
- handle_unused_attribute },
- /* The same comments as for noreturn attributes apply to const ones. */
- { "const", 0, 0, true, false, false,
- handle_const_attribute },
- { "transparent_union", 0, 0, false, false, false,
- handle_transparent_union_attribute },
- { "constructor", 0, 0, true, false, false,
- handle_constructor_attribute },
- { "destructor", 0, 0, true, false, false,
- handle_destructor_attribute },
- { "mode", 1, 1, false, true, false,
- handle_mode_attribute },
- { "section", 1, 1, true, false, false,
- handle_section_attribute },
- { "aligned", 0, 1, false, false, false,
- handle_aligned_attribute },
- { "weak", 0, 0, true, false, false,
- handle_weak_attribute },
- { "alias", 1, 1, true, false, false,
- handle_alias_attribute },
- { "no_instrument_function", 0, 0, true, false, false,
- handle_no_instrument_function_attribute },
- { "malloc", 0, 0, true, false, false,
- handle_malloc_attribute },
- { "no_stack_limit", 0, 0, true, false, false,
- handle_no_limit_stack_attribute },
- { "pure", 0, 0, true, false, false,
- handle_pure_attribute },
- { "deprecated", 0, 0, false, false, false,
- handle_deprecated_attribute },
- { "vector_size", 1, 1, false, true, false,
- handle_vector_size_attribute },
- { NULL, 0, 0, false, false, false, NULL }
-};
-
/* Default empty table of attributes. */
static const struct attribute_spec empty_attribute_table[] =
{
{ NULL, 0, 0, false, false, false, NULL }
};
-/* Table of machine-independent attributes for checking formats, if used. */
-const struct attribute_spec *format_attribute_table = empty_attribute_table;
-
-/* Table of machine-independent attributes for a particular language. */
-const struct attribute_spec *lang_attribute_table = empty_attribute_table;
-
-/* Flag saying whether common language attributes are to be supported. */
-int lang_attribute_common = 1;
-
/* Initialize attribute tables, and make some sanity checks
if --enable-checking. */
static void
init_attributes ()
{
-#ifdef ENABLE_CHECKING
- int i;
-#endif
+ size_t i;
- attribute_tables[0]
- = lang_attribute_common ? c_common_attribute_table : empty_attribute_table;
- attribute_tables[1] = lang_attribute_table;
- attribute_tables[2] = format_attribute_table;
+ attribute_tables[0] = lang_hooks.common_attribute_table;
+ attribute_tables[1] = lang_hooks.attribute_table;
+ attribute_tables[2] = lang_hooks.format_attribute_table;
attribute_tables[3] = targetm.attribute_table;
+ /* Translate NULL pointers to pointers to the empty table. */
+ for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
+ if (attribute_tables[i] == NULL)
+ attribute_tables[i] = empty_attribute_table;
+
#ifdef ENABLE_CHECKING
/* Make some sanity checks on the attribute tables. */
- for (i = 0;
- i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
- i++)
+ for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
{
int j;
@@ -218,9 +99,7 @@ init_attributes ()
}
/* Check that each name occurs just once in each table. */
- for (i = 0;
- i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
- i++)
+ for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
{
int j, k;
for (j = 0; attribute_tables[i][j].name != NULL; j++)
@@ -230,16 +109,11 @@ init_attributes ()
abort ();
}
/* Check that no name occurs in more than one table. */
- for (i = 0;
- i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
- i++)
+ for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
{
- int j, k, l;
+ size_t j, k, l;
- for (j = i + 1;
- j < ((int) (sizeof (attribute_tables)
- / sizeof (attribute_tables[0])));
- j++)
+ for (j = i + 1; j < ARRAY_SIZE (attribute_tables); j++)
for (k = 0; attribute_tables[i][k].name != NULL; k++)
for (l = 0; attribute_tables[j][l].name != NULL; l++)
if (!strcmp (attribute_tables[i][k].name,
@@ -279,7 +153,7 @@ decl_attributes (node, attributes, flags)
if (DECL_P (*node) && TREE_CODE (*node) == FUNCTION_DECL
&& !(flags & (int) ATTR_FLAG_BUILT_IN))
- insert_default_attributes (*node);
+ (*lang_hooks.insert_default_attributes) (*node);
for (a = attributes; a; a = TREE_CHAIN (a))
{
@@ -288,12 +162,9 @@ decl_attributes (node, attributes, flags)
tree *anode = node;
const struct attribute_spec *spec = NULL;
bool no_add_attrs = 0;
- int i;
+ size_t i;
- for (i = 0;
- i < ((int) (sizeof (attribute_tables)
- / sizeof (attribute_tables[0])));
- i++)
+ for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
{
int j;
@@ -433,930 +304,6 @@ decl_attributes (node, attributes, flags)
return returned_attrs;
}
-/* Handle a "packed" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_packed_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags;
- bool *no_add_attrs;
-{
- tree *type = NULL;
- if (DECL_P (*node))
- {
- if (TREE_CODE (*node) == TYPE_DECL)
- type = &TREE_TYPE (*node);
- }
- else
- type = node;
-
- if (type)
- {
- if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *type = build_type_copy (*type);
- TYPE_PACKED (*type) = 1;
- }
- else if (TREE_CODE (*node) == FIELD_DECL)
- DECL_PACKED (*node) = 1;
- /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
- used for DECL_REGISTER. It wouldn't mean anything anyway. */
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "nocommon" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_nocommon_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- if (TREE_CODE (*node) == VAR_DECL)
- DECL_COMMON (*node) = 0;
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "common" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_common_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- if (TREE_CODE (*node) == VAR_DECL)
- DECL_COMMON (*node) = 1;
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "noreturn" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_noreturn_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree type = TREE_TYPE (*node);
-
- /* See FIXME comment in c_common_attribute_table. */
- if (TREE_CODE (*node) == FUNCTION_DECL)
- TREE_THIS_VOLATILE (*node) = 1;
- else if (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
- TREE_TYPE (*node)
- = build_pointer_type
- (build_type_variant (TREE_TYPE (type),
- TREE_READONLY (TREE_TYPE (type)), 1));
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "noinline" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_noinline_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- DECL_UNINLINABLE (*node) = 1;
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "always_inline" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_always_inline_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- {
- /* Do nothing else, just set the attribute. We'll get at
- it later with lookup_attribute. */
- }
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "used" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_used_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (*node))
- = TREE_USED (*node) = 1;
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "unused" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_unused_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags;
- bool *no_add_attrs;
-{
- if (DECL_P (*node))
- {
- tree decl = *node;
-
- if (TREE_CODE (decl) == PARM_DECL
- || TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == LABEL_DECL
- || TREE_CODE (decl) == TYPE_DECL)
- TREE_USED (decl) = 1;
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- }
- else
- {
- if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *node = build_type_copy (*node);
- TREE_USED (*node) = 1;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "const" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_const_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree type = TREE_TYPE (*node);
-
- /* See FIXME comment on noreturn in c_common_attribute_table. */
- if (TREE_CODE (*node) == FUNCTION_DECL)
- TREE_READONLY (*node) = 1;
- else if (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
- TREE_TYPE (*node)
- = build_pointer_type
- (build_type_variant (TREE_TYPE (type), 1,
- TREE_THIS_VOLATILE (TREE_TYPE (type))));
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "transparent_union" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_transparent_union_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags;
- bool *no_add_attrs;
-{
- tree decl = NULL_TREE;
- tree *type = NULL;
- int is_type = 0;
-
- if (DECL_P (*node))
- {
- decl = *node;
- type = &TREE_TYPE (decl);
- is_type = TREE_CODE (*node) == TYPE_DECL;
- }
- else if (TYPE_P (*node))
- type = node, is_type = 1;
-
- if (is_type
- && TREE_CODE (*type) == UNION_TYPE
- && (decl == 0
- || (TYPE_FIELDS (*type) != 0
- && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))))
- {
- if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *type = build_type_copy (*type);
- TYPE_TRANSPARENT_UNION (*type) = 1;
- }
- else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
- && TREE_CODE (*type) == UNION_TYPE
- && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))
- DECL_TRANSPARENT_UNION (decl) = 1;
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "constructor" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_constructor_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree decl = *node;
- tree type = TREE_TYPE (decl);
-
- if (TREE_CODE (decl) == FUNCTION_DECL
- && TREE_CODE (type) == FUNCTION_TYPE
- && decl_function_context (decl) == 0)
- {
- DECL_STATIC_CONSTRUCTOR (decl) = 1;
- TREE_USED (decl) = 1;
- }
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "destructor" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_destructor_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree decl = *node;
- tree type = TREE_TYPE (decl);
-
- if (TREE_CODE (decl) == FUNCTION_DECL
- && TREE_CODE (type) == FUNCTION_TYPE
- && decl_function_context (decl) == 0)
- {
- DECL_STATIC_DESTRUCTOR (decl) = 1;
- TREE_USED (decl) = 1;
- }
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "mode" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_mode_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree type = *node;
-
- *no_add_attrs = true;
-
- if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- else
- {
- int j;
- const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
- int len = strlen (p);
- enum machine_mode mode = VOIDmode;
- tree typefm;
-
- if (len > 4 && p[0] == '_' && p[1] == '_'
- && p[len - 1] == '_' && p[len - 2] == '_')
- {
- char *newp = (char *) alloca (len - 1);
-
- strcpy (newp, &p[2]);
- newp[len - 4] = '\0';
- p = newp;
- }
-
- /* Change this type to have a type with the specified mode.
- First check for the special modes. */
- if (! strcmp (p, "byte"))
- mode = byte_mode;
- else if (!strcmp (p, "word"))
- mode = word_mode;
- else if (! strcmp (p, "pointer"))
- mode = ptr_mode;
- else
- for (j = 0; j < NUM_MACHINE_MODES; j++)
- if (!strcmp (p, GET_MODE_NAME (j)))
- mode = (enum machine_mode) j;
-
- if (mode == VOIDmode)
- error ("unknown machine mode `%s'", p);
- else if (0 == (typefm = type_for_mode (mode,
- TREE_UNSIGNED (type))))
- error ("no data type for mode `%s'", p);
- else
- *node = typefm;
- /* No need to layout the type here. The caller should do this. */
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "section" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_section_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name ATTRIBUTE_UNUSED;
- tree args;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree decl = *node;
-
- if (targetm.have_named_sections)
- {
- if ((TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL)
- && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
- {
- if (TREE_CODE (decl) == VAR_DECL
- && current_function_decl != NULL_TREE
- && ! TREE_STATIC (decl))
- {
- error_with_decl (decl,
- "section attribute cannot be specified for local variables");
- *no_add_attrs = true;
- }
-
- /* The decl may have already been given a section attribute
- from a previous declaration. Ensure they match. */
- else if (DECL_SECTION_NAME (decl) != NULL_TREE
- && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
- TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
- {
- error_with_decl (*node,
- "section of `%s' conflicts with previous declaration");
- *no_add_attrs = true;
- }
- else
- DECL_SECTION_NAME (decl) = TREE_VALUE (args);
- }
- else
- {
- error_with_decl (*node,
- "section attribute not allowed for `%s'");
- *no_add_attrs = true;
- }
- }
- else
- {
- error_with_decl (*node,
- "section attributes are not supported for this target");
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "aligned" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_aligned_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name ATTRIBUTE_UNUSED;
- tree args;
- int flags;
- bool *no_add_attrs;
-{
- tree decl = NULL_TREE;
- tree *type = NULL;
- int is_type = 0;
- tree align_expr = (args ? TREE_VALUE (args)
- : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
- int i;
-
- if (DECL_P (*node))
- {
- decl = *node;
- type = &TREE_TYPE (decl);
- is_type = TREE_CODE (*node) == TYPE_DECL;
- }
- else if (TYPE_P (*node))
- type = node, is_type = 1;
-
- /* Strip any NOPs of any kind. */
- while (TREE_CODE (align_expr) == NOP_EXPR
- || TREE_CODE (align_expr) == CONVERT_EXPR
- || TREE_CODE (align_expr) == NON_LVALUE_EXPR)
- align_expr = TREE_OPERAND (align_expr, 0);
-
- if (TREE_CODE (align_expr) != INTEGER_CST)
- {
- error ("requested alignment is not a constant");
- *no_add_attrs = true;
- }
- else if ((i = tree_log2 (align_expr)) == -1)
- {
- error ("requested alignment is not a power of 2");
- *no_add_attrs = true;
- }
- else if (i > HOST_BITS_PER_INT - 2)
- {
- error ("requested alignment is too large");
- *no_add_attrs = true;
- }
- else if (is_type)
- {
- /* If we have a TYPE_DECL, then copy the type, so that we
- don't accidentally modify a builtin type. See pushdecl. */
- if (decl && TREE_TYPE (decl) != error_mark_node
- && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
- {
- tree tt = TREE_TYPE (decl);
- *type = build_type_copy (*type);
- DECL_ORIGINAL_TYPE (decl) = tt;
- TYPE_NAME (*type) = decl;
- TREE_USED (*type) = TREE_USED (decl);
- TREE_TYPE (decl) = *type;
- }
- else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *type = build_type_copy (*type);
-
- TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT;
- TYPE_USER_ALIGN (*type) = 1;
- }
- else if (TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FIELD_DECL)
- {
- error_with_decl (decl,
- "alignment may not be specified for `%s'");
- *no_add_attrs = true;
- }
- else
- {
- DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
- DECL_USER_ALIGN (decl) = 1;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "weak" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_weak_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name ATTRIBUTE_UNUSED;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs ATTRIBUTE_UNUSED;
-{
- declare_weak (*node);
-
- return NULL_TREE;
-}
-
-/* Handle an "alias" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_alias_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree decl = *node;
-
- if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
- || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))
- {
- error_with_decl (decl,
- "`%s' defined both normally and as an alias");
- *no_add_attrs = true;
- }
- else if (decl_function_context (decl) == 0)
- {
- tree id;
-
- id = TREE_VALUE (args);
- if (TREE_CODE (id) != STRING_CST)
- {
- error ("alias arg not a string");
- *no_add_attrs = true;
- return NULL_TREE;
- }
- id = get_identifier (TREE_STRING_POINTER (id));
- /* This counts as a use of the object pointed to. */
- TREE_USED (id) = 1;
-
- if (TREE_CODE (decl) == FUNCTION_DECL)
- DECL_INITIAL (decl) = error_mark_node;
- else
- DECL_EXTERNAL (decl) = 0;
- }
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "no_instrument_function" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_no_instrument_function_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree decl = *node;
-
- if (TREE_CODE (decl) != FUNCTION_DECL)
- {
- error_with_decl (decl,
- "`%s' attribute applies only to functions",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- else if (DECL_INITIAL (decl))
- {
- error_with_decl (decl,
- "can't set `%s' attribute after definition",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- else
- DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
-
- return NULL_TREE;
-}
-
-/* Handle a "malloc" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_malloc_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- DECL_IS_MALLOC (*node) = 1;
- /* ??? TODO: Support types. */
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "no_limit_stack" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_no_limit_stack_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- tree decl = *node;
-
- if (TREE_CODE (decl) != FUNCTION_DECL)
- {
- error_with_decl (decl,
- "`%s' attribute applies only to functions",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- else if (DECL_INITIAL (decl))
- {
- error_with_decl (decl,
- "can't set `%s' attribute after definition",
- IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
- else
- DECL_NO_LIMIT_STACK (decl) = 1;
-
- return NULL_TREE;
-}
-
-/* Handle a "pure" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_pure_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- DECL_IS_PURE (*node) = 1;
- /* ??? TODO: Support types. */
- else
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "deprecated" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_deprecated_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args ATTRIBUTE_UNUSED;
- int flags;
- bool *no_add_attrs;
-{
- tree type = NULL_TREE;
- int warn = 0;
- const char *what = NULL;
-
- if (DECL_P (*node))
- {
- tree decl = *node;
- type = TREE_TYPE (decl);
-
- if (TREE_CODE (decl) == TYPE_DECL
- || TREE_CODE (decl) == PARM_DECL
- || TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == FIELD_DECL)
- TREE_DEPRECATED (decl) = 1;
- else
- warn = 1;
- }
- else if (TYPE_P (*node))
- {
- if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *node = build_type_copy (*node);
- TREE_DEPRECATED (*node) = 1;
- type = *node;
- }
- else
- warn = 1;
-
- if (warn)
- {
- *no_add_attrs = true;
- if (type && TYPE_NAME (type))
- {
- if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
- what = IDENTIFIER_POINTER (TYPE_NAME (*node));
- else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- && DECL_NAME (TYPE_NAME (type)))
- what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
- }
- if (what)
- warning ("`%s' attribute ignored for `%s'",
- IDENTIFIER_POINTER (name), what);
- else
- warning ("`%s' attribute ignored",
- IDENTIFIER_POINTER (name));
- }
-
- return NULL_TREE;
-}
-
-/* Handle a "vector_size" attribute; arguments as in
- struct attribute_spec.handler. */
-
-static tree
-handle_vector_size_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
- tree name;
- tree args;
- int flags ATTRIBUTE_UNUSED;
- bool *no_add_attrs;
-{
- unsigned HOST_WIDE_INT vecsize, nunits;
- enum machine_mode mode, orig_mode, new_mode;
- tree type = *node, new_type;
-
- *no_add_attrs = true;
-
- if (! host_integerp (TREE_VALUE (args), 1))
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- return NULL_TREE;
- }
-
- /* Get the vector size (in bytes). */
- vecsize = tree_low_cst (TREE_VALUE (args), 1);
-
- /* We need to provide for vector pointers, vector arrays, and
- functions returning vectors. For example:
-
- __attribute__((vector_size(16))) short *foo;
-
- In this case, the mode is SI, but the type being modified is
- HI, so we need to look further. */
-
- while (POINTER_TYPE_P (type)
- || TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
-
- /* Get the mode of the type being modified. */
- orig_mode = TYPE_MODE (type);
-
- if (TREE_CODE (type) == RECORD_TYPE
- || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT
- && GET_MODE_CLASS (orig_mode) != MODE_INT)
- || ! host_integerp (TYPE_SIZE_UNIT (type), 1))
- {
- error ("invalid vector type for attribute `%s'",
- IDENTIFIER_POINTER (name));
- return NULL_TREE;
- }
-
- /* Calculate how many units fit in the vector. */
- nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
-
- /* Find a suitably sized vector. */
- new_mode = VOIDmode;
- for (mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_mode) == MODE_INT
- ? MODE_VECTOR_INT
- : MODE_VECTOR_FLOAT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if (vecsize == GET_MODE_SIZE (mode)
- && nunits == (unsigned HOST_WIDE_INT) GET_MODE_NUNITS (mode))
- {
- new_mode = mode;
- break;
- }
-
- if (new_mode == VOIDmode)
- error ("no vector mode with the size and type specified could be found");
- else
- {
- new_type = type_for_mode (new_mode, TREE_UNSIGNED (type));
- if (!new_type)
- error ("no vector mode with the size and type specified could be found");
- else
- /* Build back pointers if needed. */
- *node = vector_size_helper (*node, new_type);
- }
-
- return NULL_TREE;
-}
-
-/* HACK. GROSS. This is absolutely disgusting. I wish there was a
- better way.
-
- If we requested a pointer to a vector, build up the pointers that
- we stripped off while looking for the inner type. Similarly for
- return values from functions.
-
- The argument "type" is the top of the chain, and "bottom" is the
- new type which we will point to. */
-
-static tree
-vector_size_helper (type, bottom)
- tree type, bottom;
-{
- tree inner, outer;
-
- if (POINTER_TYPE_P (type))
- {
- inner = vector_size_helper (TREE_TYPE (type), bottom);
- outer = build_pointer_type (inner);
- }
- else if (TREE_CODE (type) == ARRAY_TYPE)
- {
- inner = vector_size_helper (TREE_TYPE (type), bottom);
- outer = build_array_type (inner, TYPE_VALUES (type));
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- inner = vector_size_helper (TREE_TYPE (type), bottom);
- outer = build_function_type (inner, TYPE_VALUES (type));
- }
- else
- return bottom;
-
- TREE_READONLY (outer) = TREE_READONLY (type);
- TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type);
-
- return outer;
-}
-
/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two
lists. SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE).
@@ -1375,7 +322,7 @@ split_specs_attrs (specs_attrs, declspecs, prefix_attributes)
tree t, s, a, next, specs, attrs;
/* This can happen after an __extension__ in pedantic mode. */
- if (specs_attrs != NULL_TREE
+ if (specs_attrs != NULL_TREE
&& TREE_CODE (specs_attrs) == INTEGER_CST)
{
*declspecs = NULL_TREE;
diff --git a/contrib/gcc/basic-block.h b/contrib/gcc/basic-block.h
index aa78b45..1829fde 100644
--- a/contrib/gcc/basic-block.h
+++ b/contrib/gcc/basic-block.h
@@ -26,6 +26,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "sbitmap.h"
#include "varray.h"
#include "partition.h"
+#include "hard-reg-set.h"
/* Head of register set linked list. */
typedef bitmap_head regset_head;
@@ -33,7 +34,7 @@ typedef bitmap_head regset_head;
typedef bitmap regset;
/* Initialize a new regset. */
-#define INIT_REG_SET(HEAD) bitmap_initialize (HEAD)
+#define INIT_REG_SET(HEAD) bitmap_initialize (HEAD, 1)
/* Clear a register set by freeing up the linked list. */
#define CLEAR_REG_SET(HEAD) bitmap_clear (HEAD)
@@ -99,7 +100,7 @@ do { \
#define OBSTACK_ALLOC_REG_SET(OBSTACK) BITMAP_OBSTACK_ALLOC (OBSTACK)
/* Initialize a register set. Returns the new register set. */
-#define INITIALIZE_REG_SET(HEAD) bitmap_initialize (&HEAD)
+#define INITIALIZE_REG_SET(HEAD) bitmap_initialize (&HEAD, 1)
/* Do any cleanup needed on a regset when it is no longer used. */
#define FREE_REG_SET(REGSET) BITMAP_FREE(REGSET)
@@ -135,12 +136,16 @@ typedef struct edge_def {
in profile.c */
} *edge;
-#define EDGE_FALLTHRU 1
-#define EDGE_ABNORMAL 2
-#define EDGE_ABNORMAL_CALL 4
-#define EDGE_EH 8
-#define EDGE_FAKE 16
-#define EDGE_DFS_BACK 32
+#define EDGE_FALLTHRU 1 /* 'Straight line' flow */
+#define EDGE_ABNORMAL 2 /* Strange flow, like computed
+ label, or eh */
+#define EDGE_ABNORMAL_CALL 4 /* Call with abnormal exit
+ like an exception, or sibcall */
+#define EDGE_EH 8 /* Exception throw */
+#define EDGE_FAKE 16 /* Not a real edge (profile.c) */
+#define EDGE_DFS_BACK 32 /* A backwards edge */
+#define EDGE_CAN_FALLTHRU 64 /* Candidate for straight line
+ flow. */
#define EDGE_COMPLEX (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH)
@@ -205,9 +210,15 @@ typedef struct basic_block_def {
/* The index of this block. */
int index;
+ /* Previous and next blocks in the chain. */
+ struct basic_block_def *prev_bb, *next_bb;
+
/* The loop depth of this block. */
int loop_depth;
+ /* Outermost loop containing the block. */
+ struct loop *loop_father;
+
/* Expected number of executions: calculated in profile.c. */
gcov_type count;
@@ -221,12 +232,19 @@ typedef struct basic_block_def {
#define BB_FREQ_MAX 10000
/* Masks for basic_block.flags. */
-#define BB_REACHABLE 1
+#define BB_DIRTY 1
+#define BB_NEW 2
+#define BB_REACHABLE 4
+#define BB_VISITED 8
/* Number of basic blocks in the current function. */
extern int n_basic_blocks;
+/* First free basic block number. */
+
+extern int last_basic_block;
+
/* Number of edges in the current function. */
extern int n_edges;
@@ -237,13 +255,30 @@ extern varray_type basic_block_info;
#define BASIC_BLOCK(N) (VARRAY_BB (basic_block_info, (N)))
+/* For iterating over basic blocks. */
+#define FOR_BB_BETWEEN(BB, FROM, TO, DIR) \
+ for (BB = FROM; BB != TO; BB = BB->DIR)
+
+#define FOR_EACH_BB(BB) \
+ FOR_BB_BETWEEN (BB, ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR, next_bb)
+
+#define FOR_EACH_BB_REVERSE(BB) \
+ FOR_BB_BETWEEN (BB, EXIT_BLOCK_PTR->prev_bb, ENTRY_BLOCK_PTR, prev_bb)
+
+/* Cycles through _all_ basic blocks, even the fake ones (entry and
+ exit block). */
+
+#define FOR_ALL_BB(BB) \
+ for (BB = ENTRY_BLOCK_PTR; BB; BB = BB->next_bb)
+
/* What registers are live at the setjmp call. */
extern regset regs_live_at_setjmp;
/* Special labels found during CFG build. */
-extern rtx label_value_list, tail_recursion_label_list;
+extern GTY(()) rtx label_value_list;
+extern GTY(()) rtx tail_recursion_label_list;
extern struct obstack flow_obstack;
@@ -279,27 +314,30 @@ extern struct basic_block_def entry_exit_blocks[2];
#define ENTRY_BLOCK_PTR (&entry_exit_blocks[0])
#define EXIT_BLOCK_PTR (&entry_exit_blocks[1])
-extern varray_type basic_block_for_insn;
-#define BLOCK_FOR_INSN(INSN) VARRAY_BB (basic_block_for_insn, INSN_UID (INSN))
#define BLOCK_NUM(INSN) (BLOCK_FOR_INSN (INSN)->index + 0)
+#define set_block_for_insn(INSN, BB) (BLOCK_FOR_INSN (INSN) = BB)
-extern void compute_bb_for_insn PARAMS ((int));
+extern void compute_bb_for_insn PARAMS ((void));
extern void free_bb_for_insn PARAMS ((void));
extern void update_bb_for_insn PARAMS ((basic_block));
-extern void set_block_for_insn PARAMS ((rtx, basic_block));
extern void free_basic_block_vars PARAMS ((int));
extern edge split_block PARAMS ((basic_block, rtx));
extern basic_block split_edge PARAMS ((edge));
extern void insert_insn_on_edge PARAMS ((rtx, edge));
+
extern void commit_edge_insertions PARAMS ((void));
+extern void commit_edge_insertions_watch_calls PARAMS ((void));
+
extern void remove_fake_edges PARAMS ((void));
extern void add_noreturn_fake_exit_edges PARAMS ((void));
extern void connect_infinite_loops_to_exit PARAMS ((void));
extern int flow_call_edges_add PARAMS ((sbitmap));
extern edge cached_make_edge PARAMS ((sbitmap *, basic_block,
basic_block, int));
+extern edge unchecked_make_edge PARAMS ((basic_block,
+ basic_block, int));
extern edge make_edge PARAMS ((basic_block,
basic_block, int));
extern edge make_single_succ_edge PARAMS ((basic_block,
@@ -308,10 +346,11 @@ extern void remove_edge PARAMS ((edge));
extern void redirect_edge_succ PARAMS ((edge, basic_block));
extern edge redirect_edge_succ_nodup PARAMS ((edge, basic_block));
extern void redirect_edge_pred PARAMS ((edge, basic_block));
-extern basic_block create_basic_block_structure PARAMS ((int, rtx, rtx, rtx));
-extern basic_block create_basic_block PARAMS ((int, rtx, rtx));
+extern basic_block create_basic_block_structure PARAMS ((rtx, rtx, rtx, basic_block));
+extern basic_block create_basic_block PARAMS ((rtx, rtx, basic_block));
extern int flow_delete_block PARAMS ((basic_block));
extern int flow_delete_block_noexpunge PARAMS ((basic_block));
+extern void clear_bb_flags PARAMS ((void));
extern void merge_blocks_nomove PARAMS ((basic_block, basic_block));
extern void tidy_fallthru_edge PARAMS ((edge, basic_block,
basic_block));
@@ -324,6 +363,10 @@ extern void clear_edges PARAMS ((void));
extern void mark_critical_edges PARAMS ((void));
extern rtx first_insn_after_basic_block_note PARAMS ((basic_block));
+/* Dominator information for basic blocks. */
+
+typedef struct dominance_info *dominance_info;
+
/* Structure to hold information for each natural loop. */
struct loop
{
@@ -379,6 +422,9 @@ struct loop
/* The loop nesting depth. */
int depth;
+ /* Superloops of the loop. */
+ struct loop **pred;
+
/* The height of the loop (enclosed loop levels) within the loop
hierarchy tree. */
int level;
@@ -392,10 +438,7 @@ struct loop
/* Link to the next (sibling) loop. */
struct loop *next;
- /* Non-zero if the loop shares a header with another loop. */
- int shared;
-
- /* Non-zero if the loop is invalid (e.g., contains setjmp.). */
+ /* Nonzero if the loop is invalid (e.g., contains setjmp.). */
int invalid;
/* Auxiliary info specific to a pass. */
@@ -404,16 +447,13 @@ struct loop
/* The following are currently used by loop.c but they are likely to
disappear as loop.c is converted to use the CFG. */
- /* Non-zero if the loop has a NOTE_INSN_LOOP_VTOP. */
+ /* Nonzero if the loop has a NOTE_INSN_LOOP_VTOP. */
rtx vtop;
- /* Non-zero if the loop has a NOTE_INSN_LOOP_CONT.
+ /* Nonzero if the loop has a NOTE_INSN_LOOP_CONT.
A continue statement will generate a branch to NEXT_INSN (cont). */
rtx cont;
- /* The dominator of cont. */
- rtx cont_dominator;
-
/* The NOTE_INSN_LOOP_BEG. */
rtx start;
@@ -460,6 +500,11 @@ struct loops
will find the inner loops before their enclosing outer loops). */
struct loop *array;
+ /* The above array is unused in new loop infrastructure and is kept only for
+ purposes of the old loop optimizer. Instead we store just pointers to
+ loops here. */
+ struct loop **parray;
+
/* Pointer to root of loop heirachy tree. */
struct loop *tree_root;
@@ -467,7 +512,7 @@ struct loops
struct cfg
{
/* The bitmap vector of dominators or NULL if not computed. */
- sbitmap *dom;
+ dominance_info dom;
/* The ordering of the basic blocks in a depth first search. */
int *dfs_order;
@@ -481,6 +526,33 @@ struct loops
sbitmap shared_headers;
};
+/* Structure to group all of the information to process IF-THEN and
+ IF-THEN-ELSE blocks for the conditional execution support. This
+ needs to be in a public file in case the IFCVT macros call
+ functions passing the ce_if_block data structure. */
+
+typedef struct ce_if_block
+{
+ basic_block test_bb; /* First test block. */
+ basic_block then_bb; /* THEN block. */
+ basic_block else_bb; /* ELSE block or NULL. */
+ basic_block join_bb; /* Join THEN/ELSE blocks. */
+ basic_block last_test_bb; /* Last bb to hold && or || tests. */
+ int num_multiple_test_blocks; /* # of && and || basic blocks. */
+ int num_and_and_blocks; /* # of && blocks. */
+ int num_or_or_blocks; /* # of || blocks. */
+ int num_multiple_test_insns; /* # of insns in && and || blocks. */
+ int and_and_p; /* Complex test is &&. */
+ int num_then_insns; /* # of insns in THEN block. */
+ int num_else_insns; /* # of insns in ELSE block. */
+ int pass; /* Pass number. */
+
+#ifdef IFCVT_EXTRA_FIELDS
+ IFCVT_EXTRA_FIELDS /* Any machine dependent fields. */
+#endif
+
+} ce_if_block_t;
+
extern int flow_loops_find PARAMS ((struct loops *, int flags));
extern int flow_loops_update PARAMS ((struct loops *, int flags));
extern void flow_loops_free PARAMS ((struct loops *));
@@ -491,6 +563,8 @@ extern void flow_loop_dump PARAMS ((const struct loop *, FILE *,
void (*)(const struct loop *,
FILE *, int), int));
extern int flow_loop_scan PARAMS ((struct loops *, struct loop *, int));
+extern void flow_loop_tree_node_add PARAMS ((struct loop *, struct loop *));
+extern void flow_loop_tree_node_remove PARAMS ((struct loop *));
/* This structure maintains an edge list vector. */
struct edge_list
@@ -562,7 +636,12 @@ enum update_life_extent
by dead code removal. */
#define PROP_AUTOINC 64 /* Create autoinc mem references. */
#define PROP_EQUAL_NOTES 128 /* Take into account REG_EQUAL notes. */
-#define PROP_FINAL 127 /* All of the above. */
+#define PROP_SCAN_DEAD_STORES 256 /* Scan for dead code. */
+#define PROP_FINAL (PROP_DEATH_NOTES | PROP_LOG_LINKS \
+ | PROP_REG_INFO | PROP_KILL_DEAD_CODE \
+ | PROP_SCAN_DEAD_CODE | PROP_AUTOINC \
+ | PROP_ALLOW_CFG_CHANGES \
+ | PROP_SCAN_DEAD_STORES)
#define CLEANUP_EXPENSIVE 1 /* Do relativly expensive optimizations
except for edge forwarding */
@@ -575,6 +654,8 @@ enum update_life_extent
notes. */
#define CLEANUP_UPDATE_LIFE 32 /* Keep life information up to date. */
#define CLEANUP_THREADING 64 /* Do jump threading. */
+#define CLEANUP_NO_INSN_DEL 128 /* Do not try to delete trivially dead
+ insns. */
/* Flags for loop discovery. */
#define LOOP_TREE 1 /* Build loop hierarchy tree. */
@@ -582,12 +663,13 @@ enum update_life_extent
#define LOOP_ENTRY_EDGES 4 /* Find entry edges. */
#define LOOP_EXIT_EDGES 8 /* Find exit edges. */
#define LOOP_EDGES (LOOP_ENTRY_EDGES | LOOP_EXIT_EDGES)
-#define LOOP_EXITS_DOMS 16 /* Find nodes that dom. all exits. */
-#define LOOP_ALL 31 /* All of the above */
+#define LOOP_ALL 15 /* All of the above */
extern void life_analysis PARAMS ((rtx, FILE *, int));
-extern void update_life_info PARAMS ((sbitmap, enum update_life_extent,
+extern int update_life_info PARAMS ((sbitmap, enum update_life_extent,
int));
+extern int update_life_info_in_dirty_blocks PARAMS ((enum update_life_extent,
+ int));
extern int count_or_remove_death_notes PARAMS ((sbitmap, int));
extern int propagate_block PARAMS ((basic_block, regset, regset, regset,
int));
@@ -617,7 +699,12 @@ extern rtx emit_block_insn_before PARAMS ((rtx, rtx, basic_block));
/* In predict.c */
extern void estimate_probability PARAMS ((struct loops *));
+extern void note_prediction_to_br_prob PARAMS ((void));
extern void expected_value_to_br_prob PARAMS ((void));
+extern void note_prediction_to_br_prob PARAMS ((void));
+extern bool maybe_hot_bb_p PARAMS ((basic_block));
+extern bool probably_cold_bb_p PARAMS ((basic_block));
+extern bool probably_never_executed_bb_p PARAMS ((basic_block));
/* In flow.c */
extern void init_flow PARAMS ((void));
@@ -630,10 +717,12 @@ extern void debug_regset PARAMS ((regset));
extern void allocate_reg_life_data PARAMS ((void));
extern void allocate_bb_life_data PARAMS ((void));
extern void expunge_block PARAMS ((basic_block));
-extern void expunge_block_nocompact PARAMS ((basic_block));
+extern void link_block PARAMS ((basic_block, basic_block));
+extern void unlink_block PARAMS ((basic_block));
+extern void compact_blocks PARAMS ((void));
extern basic_block alloc_block PARAMS ((void));
extern void find_unreachable_blocks PARAMS ((void));
-extern void delete_noop_moves PARAMS ((rtx));
+extern int delete_noop_moves PARAMS ((rtx));
extern basic_block redirect_edge_and_branch_force PARAMS ((edge, basic_block));
extern basic_block force_nonfallthru PARAMS ((edge));
extern bool redirect_edge_and_branch PARAMS ((edge, basic_block));
@@ -661,13 +750,32 @@ extern void free_aux_for_edges PARAMS ((void));
debugger, and it is declared extern so we don't get warnings about
it being unused. */
extern void verify_flow_info PARAMS ((void));
-extern int flow_loop_outside_edge_p PARAMS ((const struct loop *, edge));
+extern bool flow_loop_outside_edge_p PARAMS ((const struct loop *, edge));
+extern bool flow_loop_nested_p PARAMS ((const struct loop *,
+ const struct loop *));
+extern bool flow_bb_inside_loop_p PARAMS ((const struct loop *,
+ const basic_block));
+extern basic_block *get_loop_body PARAMS ((const struct loop *));
+extern int dfs_enumerate_from PARAMS ((basic_block, int,
+ bool (*)(basic_block, void *),
+ basic_block *, int, void *));
+
+extern edge loop_preheader_edge PARAMS ((struct loop *));
+extern edge loop_latch_edge PARAMS ((struct loop *));
+
+extern void add_bb_to_loop PARAMS ((basic_block, struct loop *));
+extern void remove_bb_from_loops PARAMS ((basic_block));
+extern struct loop * find_common_loop PARAMS ((struct loop *, struct loop *));
+
+extern void verify_loop_structure PARAMS ((struct loops *, int));
+#define VLS_EXPECT_PREHEADERS 1
+#define VLS_EXPECT_SIMPLE_LATCHES 2
typedef struct conflict_graph_def *conflict_graph;
/* Callback function when enumerating conflicts. The arguments are
the smaller and larger regno in the conflict. Returns zero if
- enumeration is to continue, non-zero to halt enumeration. */
+ enumeration is to continue, nonzero to halt enumeration. */
typedef int (*conflict_graph_enum_fn) PARAMS ((int, int, void *));
@@ -690,8 +798,12 @@ extern conflict_graph conflict_graph_compute
PARAMS ((regset,
partition));
extern bool mark_dfs_back_edges PARAMS ((void));
+extern void set_edge_can_fallthru_flag PARAMS ((void));
extern void update_br_prob_note PARAMS ((basic_block));
extern void fixup_abnormal_edges PARAMS ((void));
+extern bool can_hoist_insn_p PARAMS ((rtx, rtx, regset));
+extern rtx hoist_insn_after PARAMS ((rtx, rtx, rtx, rtx));
+extern rtx hoist_insn_to_edge PARAMS ((rtx, edge, rtx, rtx));
extern bool control_flow_insn_p PARAMS ((rtx));
/* In dominance.c */
@@ -702,7 +814,21 @@ enum cdi_direction
CDI_POST_DOMINATORS
};
-extern void calculate_dominance_info PARAMS ((int *, sbitmap *,
- enum cdi_direction));
-
+extern dominance_info calculate_dominance_info PARAMS ((enum cdi_direction));
+extern void free_dominance_info PARAMS ((dominance_info));
+extern basic_block nearest_common_dominator PARAMS ((dominance_info,
+ basic_block, basic_block));
+extern void set_immediate_dominator PARAMS ((dominance_info,
+ basic_block, basic_block));
+extern basic_block get_immediate_dominator PARAMS ((dominance_info,
+ basic_block));
+extern bool dominated_by_p PARAMS ((dominance_info, basic_block, basic_block));
+extern int get_dominated_by PARAMS ((dominance_info, basic_block, basic_block **));
+extern void add_to_dominance_info PARAMS ((dominance_info, basic_block));
+extern void delete_from_dominance_info PARAMS ((dominance_info, basic_block));
+basic_block recount_dominator PARAMS ((dominance_info, basic_block));
+extern void redirect_immediate_dominators PARAMS ((dominance_info, basic_block,
+ basic_block));
+void iterate_fix_dominators PARAMS ((dominance_info, basic_block *, int));
+extern void verify_dominators PARAMS ((dominance_info));
#endif /* GCC_BASIC_BLOCK_H */
diff --git a/contrib/gcc/bb-reorder.c b/contrib/gcc/bb-reorder.c
index b0cc462..857e0fb 100644
--- a/contrib/gcc/bb-reorder.c
+++ b/contrib/gcc/bb-reorder.c
@@ -89,11 +89,13 @@
#include "flags.h"
#include "output.h"
#include "cfglayout.h"
+#include "function.h"
#include "target.h"
/* Local function prototypes. */
static void make_reorder_chain PARAMS ((void));
static basic_block make_reorder_chain_1 PARAMS ((basic_block, basic_block));
+static basic_block maybe_duplicate_computed_goto_succ PARAMS ((basic_block));
/* Compute an ordering for a subgraph beginning with block BB. Record the
ordering in RBI()->index and chained through RBI()->next. */
@@ -102,14 +104,11 @@ static void
make_reorder_chain ()
{
basic_block prev = NULL;
- int nbb_m1 = n_basic_blocks - 1;
- basic_block next;
+ basic_block next, bb;
/* Loop until we've placed every block. */
do
{
- int i;
-
next = NULL;
/* Find the next unplaced block. */
@@ -119,19 +118,59 @@ make_reorder_chain ()
remove from the list as we place. The head of that list is
what we're looking for here. */
- for (i = 0; i <= nbb_m1 && !next; ++i)
- {
- basic_block bb = BASIC_BLOCK (i);
- if (! RBI (bb)->visited)
+ FOR_EACH_BB (bb)
+ if (! RBI (bb)->visited)
+ {
next = bb;
- }
+ break;
+ }
+
if (next)
- prev = make_reorder_chain_1 (next, prev);
+ prev = make_reorder_chain_1 (next, prev);
}
while (next);
RBI (prev)->next = NULL;
}
+/* If the successor is our artificial computed_jump block, duplicate it. */
+
+static inline basic_block
+maybe_duplicate_computed_goto_succ (bb)
+ basic_block bb;
+{
+ edge e;
+ basic_block next;
+
+ /* Note that we can't rely on computed_goto_common_label still being in
+ the instruction stream -- cfgloop.c likes to munge things about. But
+ we can still use it's non-null-ness to avoid a fruitless search. */
+ if (!cfun->computed_goto_common_label)
+ return NULL;
+
+ /* Only want to duplicate when coming from a simple branch. */
+ e = bb->succ;
+ if (!e || e->succ_next)
+ return NULL;
+
+ /* Only duplicate if we've already layed out this block once. */
+ next = e->dest;
+ if (!RBI (next)->visited)
+ return NULL;
+
+ /* See if the block contains only a computed branch. */
+ if ((next->head == next->end
+ || next_active_insn (next->head) == next->end)
+ && computed_jump_p (next->end))
+ {
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Duplicating block %d after %d\n",
+ next->index, bb->index);
+ return cfg_layout_duplicate_bb (next, e);
+ }
+
+ return NULL;
+}
+
/* A helper function for make_reorder_chain.
We do not follow EH edges, or non-fallthru edges to noreturn blocks.
@@ -158,13 +197,13 @@ make_reorder_chain_1 (bb, prev)
restart:
RBI (prev)->next = bb;
- if (rtl_dump_file && prev->index + 1 != bb->index)
+ if (rtl_dump_file && prev->next_bb != bb)
fprintf (rtl_dump_file, "Reordering block %d after %d\n",
bb->index, prev->index);
}
else
{
- if (bb->index != 0)
+ if (bb->prev_bb != ENTRY_BLOCK_PTR)
abort ();
}
RBI (bb)->visited = 1;
@@ -205,9 +244,13 @@ make_reorder_chain_1 (bb, prev)
e_taken = e;
}
- next = (taken ? e_taken : e_fall)->dest;
+ next = ((taken && e_taken) ? e_taken : e_fall)->dest;
}
+ /* If the successor is our artificial computed_jump block, duplicate it. */
+ else
+ next = maybe_duplicate_computed_goto_succ (bb);
+
/* In the absence of a prediction, disturb things as little as possible
by selecting the old "next" block from the list of successors. If
there had been a fallthru edge, that will be the one. */
@@ -221,7 +264,7 @@ make_reorder_chain_1 (bb, prev)
next = e->dest;
break;
}
- else if (e->dest->index == bb->index + 1)
+ else if (e->dest == bb->next_bb)
{
if (! (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH)))
next = e->dest;
diff --git a/contrib/gcc/bitmap.c b/contrib/gcc/bitmap.c
index 786689b..917e87b 100644
--- a/contrib/gcc/bitmap.c
+++ b/contrib/gcc/bitmap.c
@@ -1,5 +1,6 @@
/* Functions to support general ended bitmaps.
- Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -23,6 +24,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "rtl.h"
#include "flags.h"
#include "obstack.h"
+#include "ggc.h"
#include "bitmap.h"
/* Obstack to allocate bitmap elements from. */
@@ -40,13 +42,33 @@ static int bitmap_obstack_init = FALSE;
/* Global data */
bitmap_element bitmap_zero_bits; /* An element of all zero bits. */
static bitmap_element *bitmap_free; /* Freelist of bitmap elements. */
+static GTY((deletable (""))) bitmap_element *bitmap_ggc_free;
+static void bitmap_elem_to_freelist PARAMS ((bitmap, bitmap_element *));
static void bitmap_element_free PARAMS ((bitmap, bitmap_element *));
-static bitmap_element *bitmap_element_allocate PARAMS ((void));
+static bitmap_element *bitmap_element_allocate PARAMS ((bitmap));
static int bitmap_element_zerop PARAMS ((bitmap_element *));
static void bitmap_element_link PARAMS ((bitmap, bitmap_element *));
static bitmap_element *bitmap_find_bit PARAMS ((bitmap, unsigned int));
+/* Add ELEM to the appropriate freelist. */
+static INLINE void
+bitmap_elem_to_freelist (head, elt)
+ bitmap head;
+ bitmap_element *elt;
+{
+ if (head->using_obstack)
+ {
+ elt->next = bitmap_free;
+ bitmap_free = elt;
+ }
+ else
+ {
+ elt->next = bitmap_ggc_free;
+ bitmap_ggc_free = elt;
+ }
+}
+
/* Free a bitmap element. Since these are allocated off the
bitmap_obstack, "free" actually means "put onto the freelist". */
@@ -75,56 +97,68 @@ bitmap_element_free (head, elt)
if (head->current)
head->indx = head->current->indx;
}
-
- elt->next = bitmap_free;
- bitmap_free = elt;
+ bitmap_elem_to_freelist (head, elt);
}
/* Allocate a bitmap element. The bits are cleared, but nothing else is. */
static INLINE bitmap_element *
-bitmap_element_allocate ()
+bitmap_element_allocate (head)
+ bitmap head;
{
bitmap_element *element;
- if (bitmap_free != 0)
- {
- element = bitmap_free;
- bitmap_free = element->next;
- }
- else
+ if (head->using_obstack)
{
- /* We can't use gcc_obstack_init to initialize the obstack since
- print-rtl.c now calls bitmap functions, and bitmap is linked
- into the gen* functions. */
- if (!bitmap_obstack_init)
+ if (bitmap_free != 0)
{
- bitmap_obstack_init = TRUE;
-
- /* Let particular systems override the size of a chunk. */
+ element = bitmap_free;
+ bitmap_free = element->next;
+ }
+ else
+ {
+ /* We can't use gcc_obstack_init to initialize the obstack since
+ print-rtl.c now calls bitmap functions, and bitmap is linked
+ into the gen* functions. */
+ if (!bitmap_obstack_init)
+ {
+ bitmap_obstack_init = TRUE;
+
+ /* Let particular systems override the size of a chunk. */
#ifndef OBSTACK_CHUNK_SIZE
#define OBSTACK_CHUNK_SIZE 0
#endif
- /* Let them override the alloc and free routines too. */
+ /* Let them override the alloc and free routines too. */
#ifndef OBSTACK_CHUNK_ALLOC
#define OBSTACK_CHUNK_ALLOC xmalloc
#endif
#ifndef OBSTACK_CHUNK_FREE
#define OBSTACK_CHUNK_FREE free
#endif
-
+
#if !defined(__GNUC__) || (__GNUC__ < 2)
#define __alignof__(type) 0
#endif
-
- obstack_specify_allocation (&bitmap_obstack, OBSTACK_CHUNK_SIZE,
- __alignof__ (bitmap_element),
- (void *(*) PARAMS ((long))) OBSTACK_CHUNK_ALLOC,
- (void (*) PARAMS ((void *))) OBSTACK_CHUNK_FREE);
+
+ obstack_specify_allocation (&bitmap_obstack, OBSTACK_CHUNK_SIZE,
+ __alignof__ (bitmap_element),
+ (void *(*) PARAMS ((long))) OBSTACK_CHUNK_ALLOC,
+ (void (*) PARAMS ((void *))) OBSTACK_CHUNK_FREE);
+ }
+
+ element = (bitmap_element *) obstack_alloc (&bitmap_obstack,
+ sizeof (bitmap_element));
}
-
- element = (bitmap_element *) obstack_alloc (&bitmap_obstack,
- sizeof (bitmap_element));
+ }
+ else
+ {
+ if (bitmap_ggc_free != NULL)
+ {
+ element = bitmap_ggc_free;
+ bitmap_ggc_free = element->next;
+ }
+ else
+ element = ggc_alloc (sizeof (bitmap_element));
}
memset (element->bits, 0, sizeof (element->bits));
@@ -232,11 +266,10 @@ bitmap_clear (head)
for (element = head->first; element != 0; element = next)
{
next = element->next;
- element->next = bitmap_free;
- bitmap_free = element;
+ bitmap_elem_to_freelist (head, element);
}
- head->first = head->current = 0;
+ head->first = head->current = 0;
}
/* Copy a bitmap to another bitmap. */
@@ -256,7 +289,7 @@ bitmap_copy (to, from)
/* Copy elements in forward direction one at a time */
for (from_ptr = from->first; from_ptr; from_ptr = from_ptr->next)
{
- bitmap_element *to_elt = bitmap_element_allocate ();
+ bitmap_element *to_elt = bitmap_element_allocate (to);
to_elt->indx = from_ptr->indx;
@@ -298,7 +331,7 @@ bitmap_find_bit (head, bit)
unsigned int bit;
{
bitmap_element *element;
- unsigned HOST_WIDE_INT indx = bit / BITMAP_ELEMENT_ALL_BITS;
+ unsigned int indx = bit / BITMAP_ELEMENT_ALL_BITS;
if (head->current == 0
|| head->indx == indx)
@@ -337,10 +370,9 @@ bitmap_clear_bit (head, bit)
if (ptr != 0)
{
- unsigned bit_num = bit % (unsigned) HOST_BITS_PER_WIDE_INT;
- unsigned word_num = ((bit / (unsigned) HOST_BITS_PER_WIDE_INT)
- % BITMAP_ELEMENT_WORDS);
- ptr->bits[word_num] &= ~ (((unsigned HOST_WIDE_INT) 1) << bit_num);
+ unsigned bit_num = bit % BITMAP_WORD_BITS;
+ unsigned word_num = bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS;
+ ptr->bits[word_num] &= ~ (((BITMAP_WORD) 1) << bit_num);
/* If we cleared the entire word, free up the element */
if (bitmap_element_zerop (ptr))
@@ -356,14 +388,13 @@ bitmap_set_bit (head, bit)
int bit;
{
bitmap_element *ptr = bitmap_find_bit (head, bit);
- unsigned word_num
- = ((bit / (unsigned) HOST_BITS_PER_WIDE_INT) % BITMAP_ELEMENT_WORDS);
- unsigned bit_num = bit % (unsigned) HOST_BITS_PER_WIDE_INT;
- unsigned HOST_WIDE_INT bit_val = ((unsigned HOST_WIDE_INT) 1) << bit_num;
+ unsigned word_num = bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS;
+ unsigned bit_num = bit % BITMAP_WORD_BITS;
+ BITMAP_WORD bit_val = ((BITMAP_WORD) 1) << bit_num;
if (ptr == 0)
{
- ptr = bitmap_element_allocate ();
+ ptr = bitmap_element_allocate (head);
ptr->indx = bit / BITMAP_ELEMENT_ALL_BITS;
ptr->bits[word_num] = bit_val;
bitmap_element_link (head, ptr);
@@ -387,9 +418,8 @@ bitmap_bit_p (head, bit)
if (ptr == 0)
return 0;
- bit_num = bit % (unsigned) HOST_BITS_PER_WIDE_INT;
- word_num
- = ((bit / (unsigned) HOST_BITS_PER_WIDE_INT) % BITMAP_ELEMENT_WORDS);
+ bit_num = bit % BITMAP_WORD_BITS;
+ word_num = bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS;
return (ptr->bits[word_num] >> bit_num) & 1;
}
@@ -397,12 +427,12 @@ bitmap_bit_p (head, bit)
/* Return the bit number of the first set bit in the bitmap, or -1
if the bitmap is empty. */
-int
+int
bitmap_first_set_bit (a)
bitmap a;
{
bitmap_element *ptr = a->first;
- unsigned HOST_WIDE_INT word;
+ BITMAP_WORD word;
unsigned word_num, bit_num;
if (ptr == NULL)
@@ -424,10 +454,10 @@ bitmap_first_set_bit (a)
bit_num = 0;
word = word & -word;
-#if HOST_BITS_PER_WIDE_INT > 64
+#if nBITMAP_WORD_BITS > 64
#error "Fill out the table."
#endif
-#if HOST_BITS_PER_WIDE_INT > 32
+#if nBITMAP_WORD_BITS > 32
if ((word & 0xffffffff) == 0)
word >>= 32, bit_num += 32;
#endif
@@ -443,19 +473,19 @@ bitmap_first_set_bit (a)
bit_num += 1;
return (ptr->indx * BITMAP_ELEMENT_ALL_BITS
- + word_num * HOST_BITS_PER_WIDE_INT
+ + word_num * BITMAP_WORD_BITS
+ bit_num);
}
/* Return the bit number of the last set bit in the bitmap, or -1
if the bitmap is empty. */
-int
+int
bitmap_last_set_bit (a)
bitmap a;
{
bitmap_element *ptr = a->first;
- unsigned HOST_WIDE_INT word;
+ BITMAP_WORD word;
unsigned word_num, bit_num;
if (ptr == NULL)
@@ -477,11 +507,11 @@ bitmap_last_set_bit (a)
/* Binary search for the last set bit. */
bit_num = 0;
-#if HOST_BITS_PER_WIDE_INT > 64
+#if nBITMAP_WORD_BITS > 64
#error "Fill out the table."
#endif
-#if HOST_BITS_PER_WIDE_INT > 32
- if (word & ~ (unsigned HOST_WIDE_INT) 0xffffffff)
+#if nBITMAP_WORD_BITS > 32
+ if (word & ~(BITMAP_WORD)0xffffffff)
word >>= 32, bit_num += 32;
#endif
if (word & 0xffff0000)
@@ -496,7 +526,7 @@ bitmap_last_set_bit (a)
bit_num += 1;
return (ptr->indx * BITMAP_ELEMENT_ALL_BITS
- + word_num * HOST_BITS_PER_WIDE_INT
+ + word_num * BITMAP_WORD_BITS
+ bit_num);
}
@@ -526,7 +556,7 @@ bitmap_operation (to, from1, from2, operation)
#if BITMAP_ELEMENT_WORDS == 2
#define DOIT(OP) \
do { \
- unsigned HOST_WIDE_INT t0, t1, f10, f11, f20, f21; \
+ BITMAP_WORD t0, t1, f10, f11, f20, f21; \
f10 = from1_tmp->bits[0]; \
f20 = from2_tmp->bits[0]; \
t0 = f10 OP f20; \
@@ -541,7 +571,7 @@ bitmap_operation (to, from1, from2, operation)
#else
#define DOIT(OP) \
do { \
- unsigned HOST_WIDE_INT t, f1, f2; \
+ BITMAP_WORD t, f1, f2; \
int i; \
for (i = 0; i < BITMAP_ELEMENT_WORDS; ++i) \
{ \
@@ -594,8 +624,7 @@ bitmap_operation (to, from1, from2, operation)
changed = 1;
to_tmp = to_ptr;
to_ptr = to_ptr->next;
- to_tmp->next = bitmap_free;
- bitmap_free = to_tmp;
+ bitmap_elem_to_freelist (to, to_tmp);
}
if (to_ptr && to_ptr->indx == indx)
{
@@ -603,7 +632,7 @@ bitmap_operation (to, from1, from2, operation)
to_ptr = to_ptr->next;
}
else
- to_tmp = bitmap_element_allocate ();
+ to_tmp = bitmap_element_allocate (to);
/* Do the operation, and if any bits are set, link it into the
linked list. */
@@ -638,8 +667,7 @@ bitmap_operation (to, from1, from2, operation)
}
else
{
- to_tmp->next = bitmap_free;
- bitmap_free = to_tmp;
+ bitmap_elem_to_freelist (to, to_tmp);
}
}
@@ -649,8 +677,16 @@ bitmap_operation (to, from1, from2, operation)
changed = 1;
for (to_tmp = to_ptr; to_tmp->next ; to_tmp = to_tmp->next)
continue;
- to_tmp->next = bitmap_free;
- bitmap_free = to_ptr;
+ if (to->using_obstack)
+ {
+ to_tmp->next = bitmap_free;
+ bitmap_free = to_ptr;
+ }
+ else
+ {
+ to_tmp->next = bitmap_ggc_free;
+ bitmap_ggc_free = to_ptr;
+ }
}
#undef DOIT
@@ -668,7 +704,7 @@ bitmap_equal_p (a, b)
bitmap_head c;
int ret;
- c.first = c.current = 0;
+ memset (&c, 0, sizeof (c));
ret = ! bitmap_operation (&c, a, b, BITMAP_XOR);
bitmap_clear (&c);
@@ -687,6 +723,7 @@ bitmap_ior_and_compl (to, from1, from2)
bitmap_head tmp;
tmp.first = tmp.current = 0;
+ tmp.using_obstack = 0;
bitmap_operation (&tmp, from1, from2, BITMAP_AND_COMPL);
bitmap_operation (to, to, &tmp, BITMAP_IOR);
@@ -704,6 +741,7 @@ bitmap_union_of_diff (dst, a, b, c)
int changed;
tmp.first = tmp.current = 0;
+ tmp.using_obstack = 0;
bitmap_operation (&tmp, b, c, BITMAP_AND_COMPL);
changed = bitmap_operation (dst, &tmp, a, BITMAP_IOR);
@@ -715,10 +753,15 @@ bitmap_union_of_diff (dst, a, b, c)
/* Initialize a bitmap header. */
bitmap
-bitmap_initialize (head)
+bitmap_initialize (head, using_obstack)
bitmap head;
+ int using_obstack;
{
+ if (head == NULL && ! using_obstack)
+ head = ggc_alloc (sizeof (*head));
+
head->first = head->current = 0;
+ head->using_obstack = using_obstack;
return head;
}
@@ -740,7 +783,7 @@ debug_bitmap_file (file, head)
for (ptr = head->first; ptr; ptr = ptr->next)
{
- int i, j, col = 26;
+ unsigned int i, j, col = 26;
fprintf (file, "\t");
fprintf (file, HOST_PTR_PRINTF, (PTR) ptr);
@@ -751,7 +794,7 @@ debug_bitmap_file (file, head)
fprintf (file, " indx = %u\n\t\tbits = {", ptr->indx);
for (i = 0; i < BITMAP_ELEMENT_WORDS; i++)
- for (j = 0; j < HOST_BITS_PER_WIDE_INT; j++)
+ for (j = 0; j < BITMAP_WORD_BITS; j++)
if ((ptr->bits[i] >> j) & 1)
{
if (col > 70)
@@ -761,7 +804,7 @@ debug_bitmap_file (file, head)
}
fprintf (file, " %u", (ptr->indx * BITMAP_ELEMENT_ALL_BITS
- + i * HOST_BITS_PER_WIDE_INT + j));
+ + i * BITMAP_WORD_BITS + j));
col += 4;
}
@@ -800,3 +843,5 @@ bitmap_print (file, head, prefix, suffix)
});
fputs (suffix, file);
}
+
+#include "gt-bitmap.h"
diff --git a/contrib/gcc/bitmap.h b/contrib/gcc/bitmap.h
index 8925d86..85f8239 100644
--- a/contrib/gcc/bitmap.h
+++ b/contrib/gcc/bitmap.h
@@ -1,5 +1,5 @@
/* Functions to support general ended bitmaps.
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
This file is part of GCC.
@@ -20,12 +20,20 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
#ifndef GCC_BITMAP_H
-#define GCC_BITMAP_H
+#define GCC_BITMAP_H
+
+/* Fundamental storage type for bitmap. */
+
+/* typedef unsigned HOST_WIDE_INT BITMAP_WORD; */
+/* #define nBITMAP_WORD_BITS HOST_BITS_PER_WIDE_INT */
+typedef unsigned long BITMAP_WORD;
+#define nBITMAP_WORD_BITS (CHAR_BIT * SIZEOF_LONG)
+#define BITMAP_WORD_BITS (unsigned) nBITMAP_WORD_BITS
/* Number of words to use for each element in the linked list. */
#ifndef BITMAP_ELEMENT_WORDS
-#define BITMAP_ELEMENT_WORDS 2
+#define BITMAP_ELEMENT_WORDS ((128 + nBITMAP_WORD_BITS - 1) / nBITMAP_WORD_BITS)
#endif
/* Number of bits in each actual element of a bitmap. We get slightly better
@@ -33,28 +41,30 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
bits is unsigned, assuming it is a power of 2. */
#define BITMAP_ELEMENT_ALL_BITS \
- ((unsigned) (BITMAP_ELEMENT_WORDS * HOST_BITS_PER_WIDE_INT))
+ ((unsigned) (BITMAP_ELEMENT_WORDS * BITMAP_WORD_BITS))
/* Bitmap set element. We use a linked list to hold only the bits that
are set. This allows for use to grow the bitset dynamically without
having to realloc and copy a giant bit array. The `prev' field is
undefined for an element on the free list. */
-typedef struct bitmap_element_def
+typedef struct bitmap_element_def GTY(())
{
struct bitmap_element_def *next; /* Next element. */
struct bitmap_element_def *prev; /* Previous element. */
unsigned int indx; /* regno/BITMAP_ELEMENT_ALL_BITS. */
- unsigned HOST_WIDE_INT bits[BITMAP_ELEMENT_WORDS]; /* Bits that are set. */
+ BITMAP_WORD bits[BITMAP_ELEMENT_WORDS]; /* Bits that are set. */
} bitmap_element;
/* Head of bitmap linked list. */
-typedef struct bitmap_head_def {
+typedef struct bitmap_head_def GTY(()) {
bitmap_element *first; /* First element in linked list. */
bitmap_element *current; /* Last element looked at. */
unsigned int indx; /* Index of last element looked at. */
-
-} bitmap_head, *bitmap;
+ int using_obstack; /* Are we using an obstack or ggc for
+ allocation? */
+} bitmap_head;
+typedef struct bitmap_head_def *bitmap;
/* Enumeration giving the various operations we support. */
enum bitmap_bits {
@@ -100,10 +110,12 @@ extern void debug_bitmap_file PARAMS ((FILE *, bitmap));
/* Print a bitmap */
extern void bitmap_print PARAMS ((FILE *, bitmap, const char *, const char *));
-/* Initialize a bitmap header. */
-extern bitmap bitmap_initialize PARAMS ((bitmap));
+/* Initialize a bitmap header. If HEAD is NULL, a new header will be
+ allocated. USING_OBSTACK indicates how elements should be allocated. */
+extern bitmap bitmap_initialize PARAMS ((bitmap head,
+ int using_obstack));
-/* Release all memory held by bitmaps. */
+/* Release all memory used by the bitmap obstack. */
extern void bitmap_release_memory PARAMS ((void));
/* A few compatibility/functions macros for compatibility with sbitmaps */
@@ -117,22 +129,15 @@ extern int bitmap_last_set_bit PARAMS((bitmap));
/* Allocate a bitmap with oballoc. */
#define BITMAP_OBSTACK_ALLOC(OBSTACK) \
- bitmap_initialize ((bitmap) obstack_alloc (OBSTACK, sizeof (bitmap_head)))
-
-/* Allocate a bitmap with alloca. Note alloca cannot be passed as an
- argument to a function, so we set a temporary variable to the value
- returned by alloca and pass that variable to bitmap_initialize().
- PTR is then set to the value returned from bitmap_initialize() to
- avoid having it appear more than once in case it has side effects. */
-#define BITMAP_ALLOCA(PTR) \
-do { \
- bitmap temp_bitmap_ = (bitmap) alloca (sizeof (bitmap_head)); \
- (PTR) = bitmap_initialize (temp_bitmap_); \
-} while (0)
-
+ bitmap_initialize ((bitmap) obstack_alloc (OBSTACK, sizeof (bitmap_head)), 1)
+
+/* Allocate a bitmap with ggc_alloc. */
+#define BITMAP_GGC_ALLOC() \
+ bitmap_initialize (NULL, 0)
+
/* Allocate a bitmap with xmalloc. */
#define BITMAP_XMALLOC() \
- bitmap_initialize ((bitmap) xmalloc (sizeof (bitmap_head)))
+ bitmap_initialize ((bitmap) xmalloc (sizeof (bitmap_head)), 1)
/* Do any cleanup needed on a bitmap when it is no longer used. */
#define BITMAP_FREE(BITMAP) \
@@ -165,9 +170,8 @@ do { \
do { \
bitmap_element *ptr_ = (BITMAP)->first; \
unsigned int indx_ = (MIN) / BITMAP_ELEMENT_ALL_BITS; \
- unsigned bit_num_ = (MIN) % ((unsigned) HOST_BITS_PER_WIDE_INT); \
- unsigned word_num_ = (((MIN) / ((unsigned) HOST_BITS_PER_WIDE_INT)) \
- % BITMAP_ELEMENT_WORDS); \
+ unsigned bit_num_ = (MIN) % BITMAP_WORD_BITS; \
+ unsigned word_num_ = (MIN) / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS; \
\
\
/* Find the block the minimum bit is in. */ \
@@ -184,20 +188,19 @@ do { \
{ \
for (; word_num_ < BITMAP_ELEMENT_WORDS; word_num_++) \
{ \
- unsigned HOST_WIDE_INT word_ = ptr_->bits[word_num_]; \
+ BITMAP_WORD word_ = ptr_->bits[word_num_]; \
\
if (word_ != 0) \
{ \
- for (; bit_num_ < HOST_BITS_PER_WIDE_INT; bit_num_++) \
+ for (; bit_num_ < BITMAP_WORD_BITS; bit_num_++) \
{ \
- unsigned HOST_WIDE_INT mask_ \
- = ((unsigned HOST_WIDE_INT) 1) << bit_num_; \
+ BITMAP_WORD mask_ = ((BITMAP_WORD) 1) << bit_num_; \
\
if ((word_ & mask_) != 0) \
{ \
word_ &= ~ mask_; \
(BITNUM) = (ptr_->indx * BITMAP_ELEMENT_ALL_BITS \
- + word_num_ * HOST_BITS_PER_WIDE_INT \
+ + word_num_ * BITMAP_WORD_BITS \
+ bit_num_); \
CODE; \
\
@@ -223,9 +226,8 @@ do { \
bitmap_element *ptr1_ = (BITMAP1)->first; \
bitmap_element *ptr2_ = (BITMAP2)->first; \
unsigned int indx_ = (MIN) / BITMAP_ELEMENT_ALL_BITS; \
- unsigned bit_num_ = (MIN) % ((unsigned) HOST_BITS_PER_WIDE_INT); \
- unsigned word_num_ = (((MIN) / ((unsigned) HOST_BITS_PER_WIDE_INT)) \
- % BITMAP_ELEMENT_WORDS); \
+ unsigned bit_num_ = (MIN) % BITMAP_WORD_BITS; \
+ unsigned word_num_ = (MIN) / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS; \
\
/* Find the block the minimum bit is in in the first bitmap. */ \
while (ptr1_ != 0 && ptr1_->indx < indx_) \
@@ -251,20 +253,19 @@ do { \
\
for (; word_num_ < BITMAP_ELEMENT_WORDS; word_num_++) \
{ \
- unsigned HOST_WIDE_INT word_ = (ptr1_->bits[word_num_] \
- & ~ tmp2_->bits[word_num_]); \
+ BITMAP_WORD word_ = (ptr1_->bits[word_num_] \
+ & ~ tmp2_->bits[word_num_]); \
if (word_ != 0) \
{ \
- for (; bit_num_ < HOST_BITS_PER_WIDE_INT; bit_num_++) \
+ for (; bit_num_ < BITMAP_WORD_BITS; bit_num_++) \
{ \
- unsigned HOST_WIDE_INT mask_ \
- = ((unsigned HOST_WIDE_INT)1) << bit_num_; \
+ BITMAP_WORD mask_ = ((BITMAP_WORD) 1) << bit_num_; \
\
if ((word_ & mask_) != 0) \
{ \
word_ &= ~ mask_; \
(BITNUM) = (ptr1_->indx * BITMAP_ELEMENT_ALL_BITS \
- + word_num_ * HOST_BITS_PER_WIDE_INT \
+ + word_num_ * BITMAP_WORD_BITS \
+ bit_num_); \
\
CODE; \
@@ -290,9 +291,8 @@ do { \
bitmap_element *ptr1_ = (BITMAP1)->first; \
bitmap_element *ptr2_ = (BITMAP2)->first; \
unsigned int indx_ = (MIN) / BITMAP_ELEMENT_ALL_BITS; \
- unsigned bit_num_ = (MIN) % ((unsigned) HOST_BITS_PER_WIDE_INT); \
- unsigned word_num_ = (((MIN) / ((unsigned) HOST_BITS_PER_WIDE_INT)) \
- % BITMAP_ELEMENT_WORDS); \
+ unsigned bit_num_ = (MIN) % BITMAP_WORD_BITS; \
+ unsigned word_num_ = (MIN) / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS; \
\
/* Find the block the minimum bit is in in the first bitmap. */ \
while (ptr1_ != 0 && ptr1_->indx < indx_) \
@@ -324,20 +324,19 @@ do { \
\
for (; word_num_ < BITMAP_ELEMENT_WORDS; word_num_++) \
{ \
- unsigned HOST_WIDE_INT word_ = (ptr1_->bits[word_num_] \
- & ptr2_->bits[word_num_]); \
+ BITMAP_WORD word_ = (ptr1_->bits[word_num_] \
+ & ptr2_->bits[word_num_]); \
if (word_ != 0) \
{ \
- for (; bit_num_ < HOST_BITS_PER_WIDE_INT; bit_num_++) \
+ for (; bit_num_ < BITMAP_WORD_BITS; bit_num_++) \
{ \
- unsigned HOST_WIDE_INT mask_ \
- = ((unsigned HOST_WIDE_INT)1) << bit_num_; \
+ BITMAP_WORD mask_ = ((BITMAP_WORD) 1) << bit_num_; \
\
if ((word_ & mask_) != 0) \
{ \
word_ &= ~ mask_; \
(BITNUM) = (ptr1_->indx * BITMAP_ELEMENT_ALL_BITS \
- + word_num_ * HOST_BITS_PER_WIDE_INT \
+ + word_num_ * BITMAP_WORD_BITS \
+ bit_num_); \
\
CODE; \
diff --git a/contrib/gcc/builtin-attrs.def b/contrib/gcc/builtin-attrs.def
index 10b3708..7bdbd62 100644
--- a/contrib/gcc/builtin-attrs.def
+++ b/contrib/gcc/builtin-attrs.def
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
Contributed by Joseph Myers <jsm28@cam.ac.uk>.
This file is part of GCC.
@@ -77,36 +77,65 @@ DEF_LIST_INT_INT (3,0)
DEF_LIST_INT_INT (3,4)
#undef DEF_LIST_INT_INT
+/* Construct tress for identifiers. */
+DEF_ATTR_IDENT (ATTR_CONST, "const")
+DEF_ATTR_IDENT (ATTR_FORMAT, "format")
+DEF_ATTR_IDENT (ATTR_FORMAT_ARG, "format_arg")
+DEF_ATTR_IDENT (ATTR_MALLOC, "malloc")
+DEF_ATTR_IDENT (ATTR_NONNULL, "nonnull")
+DEF_ATTR_IDENT (ATTR_NORETURN, "noreturn")
+DEF_ATTR_IDENT (ATTR_NOTHROW, "nothrow")
DEF_ATTR_IDENT (ATTR_PRINTF, "printf")
+DEF_ATTR_IDENT (ATTR_PURE, "pure")
DEF_ATTR_IDENT (ATTR_SCANF, "scanf")
-DEF_ATTR_IDENT (ATTR_STRFTIME, "strftime")
DEF_ATTR_IDENT (ATTR_STRFMON, "strfmon")
+DEF_ATTR_IDENT (ATTR_STRFTIME, "strftime")
-DEF_ATTR_IDENT (ATTR_FORMAT, "format")
-DEF_ATTR_IDENT (ATTR_FORMAT_ARG, "format_arg")
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_LIST, ATTR_NOTHROW, ATTR_NULL, ATTR_NULL)
+
+DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_LIST, ATTR_CONST, \
+ ATTR_NULL, ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_LIST, ATTR_PURE, \
+ ATTR_NULL, ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_NORETURN_NOTHROW_LIST, ATTR_NORETURN, \
+ ATTR_NULL, ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_NOTHROW_LIST, ATTR_MALLOC, \
+ ATTR_NULL, ATTR_NOTHROW_LIST)
+
+DEF_ATTR_TREE_LIST (ATTR_NONNULL_1, ATTR_NONNULL, ATTR_LIST_1, \
+ ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_NONNULL_2, ATTR_NONNULL, ATTR_LIST_2, \
+ ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_NONNULL_3, ATTR_NONNULL, ATTR_LIST_3, \
+ ATTR_NOTHROW_LIST)
/* Construct a tree for a format attribute. */
-#define DEF_FORMAT_ATTRIBUTE(TYPE, VALUES) \
+#define DEF_FORMAT_ATTRIBUTE(TYPE, FA, VALUES) \
DEF_ATTR_TREE_LIST (CONCAT4 (ATTR_,TYPE,_,VALUES), ATTR_NULL, \
CONCAT2 (ATTR_,TYPE), CONCAT2 (ATTR_LIST_,VALUES)) \
DEF_ATTR_TREE_LIST (CONCAT4 (ATTR_FORMAT_,TYPE,_,VALUES), ATTR_FORMAT, \
- CONCAT4 (ATTR_,TYPE,_,VALUES), ATTR_NULL)
-DEF_FORMAT_ATTRIBUTE(PRINTF,1_0)
-DEF_FORMAT_ATTRIBUTE(PRINTF,1_2)
-DEF_FORMAT_ATTRIBUTE(PRINTF,2_0)
-DEF_FORMAT_ATTRIBUTE(PRINTF,2_3)
-DEF_FORMAT_ATTRIBUTE(PRINTF,3_0)
-DEF_FORMAT_ATTRIBUTE(PRINTF,3_4)
-DEF_FORMAT_ATTRIBUTE(SCANF,1_0)
-DEF_FORMAT_ATTRIBUTE(SCANF,1_2)
-DEF_FORMAT_ATTRIBUTE(SCANF,2_0)
-DEF_FORMAT_ATTRIBUTE(SCANF,2_3)
-DEF_FORMAT_ATTRIBUTE(STRFTIME,3_0)
-DEF_FORMAT_ATTRIBUTE(STRFMON,3_4)
+ CONCAT4 (ATTR_,TYPE,_,VALUES), CONCAT2 (ATTR_NONNULL_,FA))
+DEF_FORMAT_ATTRIBUTE(PRINTF,1,1_0)
+DEF_FORMAT_ATTRIBUTE(PRINTF,1,1_2)
+DEF_FORMAT_ATTRIBUTE(PRINTF,2,2_0)
+DEF_FORMAT_ATTRIBUTE(PRINTF,2,2_3)
+DEF_FORMAT_ATTRIBUTE(PRINTF,3,3_0)
+DEF_FORMAT_ATTRIBUTE(PRINTF,3,3_4)
+DEF_FORMAT_ATTRIBUTE(SCANF,1,1_0)
+DEF_FORMAT_ATTRIBUTE(SCANF,1,1_2)
+DEF_FORMAT_ATTRIBUTE(SCANF,2,2_0)
+DEF_FORMAT_ATTRIBUTE(SCANF,2,2_3)
+DEF_FORMAT_ATTRIBUTE(STRFTIME,3,3_0)
+DEF_FORMAT_ATTRIBUTE(STRFMON,3,3_4)
#undef DEF_FORMAT_ATTRIBUTE
-DEF_ATTR_TREE_LIST (ATTR_FORMAT_ARG_1, ATTR_FORMAT_ARG, ATTR_LIST_1, ATTR_NULL)
-DEF_ATTR_TREE_LIST (ATTR_FORMAT_ARG_2, ATTR_FORMAT_ARG, ATTR_LIST_2, ATTR_NULL)
+/* Construct a tree for a format_arg attribute. */
+#define DEF_FORMAT_ARG_ATTRIBUTE(FA) \
+ DEF_ATTR_TREE_LIST (CONCAT2 (ATTR_FORMAT_ARG_,FA), ATTR_FORMAT_ARG, \
+ CONCAT2 (ATTR_LIST_,FA), CONCAT2 (ATTR_NONNULL_,FA))
+DEF_FORMAT_ARG_ATTRIBUTE(1)
+DEF_FORMAT_ARG_ATTRIBUTE(2)
+#undef DEF_FORMAT_ARG_ATTRIBUTE
/* Define an attribute for a function, along with the IDENTIFIER_NODE. */
#define DEF_FN_ATTR_IDENT(NAME, ATTRS, PREDICATE) \
@@ -121,24 +150,10 @@ DEF_ATTR_TREE_LIST (ATTR_FORMAT_ARG_2, ATTR_FORMAT_ARG, ATTR_LIST_2, ATTR_NULL)
-ffreestanding, these default attributes are disabled, and must be
specified manually if desired. */
-/* __builtin functions should be checked unconditionally, even with
- -ffreestanding. */
-DEF_FN_ATTR_IDENT (__builtin_printf, ATTR_FORMAT_PRINTF_1_2, true)
-DEF_FN_ATTR_IDENT (__builtin_fprintf, ATTR_FORMAT_PRINTF_2_3, true)
-DEF_FN_ATTR_IDENT (__builtin_printf_unlocked, ATTR_FORMAT_PRINTF_1_2, true)
-DEF_FN_ATTR_IDENT (__builtin_fprintf_unlocked, ATTR_FORMAT_PRINTF_2_3, true)
-
/* Functions from ISO/IEC 9899:1990. */
#define DEF_C89_ATTR(NAME, ATTRS) DEF_FN_ATTR_IDENT (NAME, ATTRS, flag_hosted)
-DEF_C89_ATTR (printf, ATTR_FORMAT_PRINTF_1_2)
-DEF_C89_ATTR (fprintf, ATTR_FORMAT_PRINTF_2_3)
-DEF_C89_ATTR (sprintf, ATTR_FORMAT_PRINTF_2_3)
-DEF_C89_ATTR (scanf, ATTR_FORMAT_SCANF_1_2)
DEF_C89_ATTR (fscanf, ATTR_FORMAT_SCANF_2_3)
-DEF_C89_ATTR (sscanf, ATTR_FORMAT_SCANF_2_3)
-DEF_C89_ATTR (vprintf, ATTR_FORMAT_PRINTF_1_0)
DEF_C89_ATTR (vfprintf, ATTR_FORMAT_PRINTF_2_0)
-DEF_C89_ATTR (vsprintf, ATTR_FORMAT_PRINTF_2_0)
DEF_C89_ATTR (strftime, ATTR_FORMAT_STRFTIME_3_0)
#undef DEF_C89_ATTR
@@ -147,11 +162,7 @@ DEF_C89_ATTR (strftime, ATTR_FORMAT_STRFTIME_3_0)
DEF_FN_ATTR_IDENT (NAME, ATTRS, \
(flag_hosted \
&& (flag_isoc99 || flag_noniso_default_format_attributes)))
-DEF_C99_ATTR (snprintf, ATTR_FORMAT_PRINTF_3_4)
-DEF_C99_ATTR (vsnprintf, ATTR_FORMAT_PRINTF_3_0)
-DEF_C99_ATTR (vscanf, ATTR_FORMAT_SCANF_1_0)
DEF_C99_ATTR (vfscanf, ATTR_FORMAT_SCANF_2_0)
-DEF_C99_ATTR (vsscanf, ATTR_FORMAT_SCANF_2_0)
#undef DEF_C99_ATTR
/* Functions not in any version of ISO C. */
@@ -164,8 +175,5 @@ DEF_EXT_ATTR (dgettext, ATTR_FORMAT_ARG_2)
DEF_EXT_ATTR (dcgettext, ATTR_FORMAT_ARG_2)
/* X/Open strfmon function. */
DEF_EXT_ATTR (strfmon, ATTR_FORMAT_STRFMON_3_4)
-/* Glibc thread-unsafe stdio functions. */
-DEF_EXT_ATTR (printf_unlocked, ATTR_FORMAT_PRINTF_1_2)
-DEF_EXT_ATTR (fprintf_unlocked, ATTR_FORMAT_PRINTF_2_3)
#undef DEF_EXT_ATTR
#undef DEF_FN_ATTR_IDENT
diff --git a/contrib/gcc/builtin-types.def b/contrib/gcc/builtin-types.def
index c594bd2..d5c39b4 100644
--- a/contrib/gcc/builtin-types.def
+++ b/contrib/gcc/builtin-types.def
@@ -40,6 +40,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
DEF_FUNCTION_TYPE_VAR_0 (ENUM, RETURN)
DEF_FUNCTION_TYPE_VAR_1 (ENUM, RETURN, ARG1)
DEF_FUNCTION_TYPE_VAR_2 (ENUM, RETURN, ARG1, ARG2)
+ DEF_FUNCTION_TYPE_VAR_3 (ENUM, RETURN, ARG1, ARG2, ARG3)
Similar, but for function types that take variable arguments.
For example:
@@ -73,13 +74,10 @@ DEF_PRIMITIVE_TYPE (BT_COMPLEX_LONG_DOUBLE, complex_long_double_type_node)
DEF_PRIMITIVE_TYPE (BT_PTR, ptr_type_node)
DEF_PRIMITIVE_TYPE (BT_CONST_PTR, const_ptr_type_node)
-DEF_PRIMITIVE_TYPE (BT_TRAD_PTR, traditional_ptr_type_node)
-DEF_PRIMITIVE_TYPE (BT_TRAD_CONST_PTR, traditional_cptr_type_node)
-DEF_PRIMITIVE_TYPE (BT_PTRMODE, type_for_mode (ptr_mode, 0))
+DEF_PRIMITIVE_TYPE (BT_PTRMODE, (*lang_hooks.types.type_for_mode)(ptr_mode, 0))
DEF_PRIMITIVE_TYPE (BT_SIZE, size_type_node)
DEF_PRIMITIVE_TYPE (BT_STRING, string_type_node)
DEF_PRIMITIVE_TYPE (BT_CONST_STRING, const_string_type_node)
-DEF_PRIMITIVE_TYPE (BT_LEN, traditional_len_type_node)
DEF_PRIMITIVE_TYPE (BT_VALIST_REF, va_list_ref_type_node)
DEF_PRIMITIVE_TYPE (BT_VALIST_ARG, va_list_arg_type_node)
@@ -87,6 +85,9 @@ DEF_PRIMITIVE_TYPE (BT_VALIST_ARG, va_list_arg_type_node)
DEF_FUNCTION_TYPE_0 (BT_FN_VOID, BT_VOID)
DEF_FUNCTION_TYPE_0 (BT_FN_PTR, BT_PTR)
DEF_FUNCTION_TYPE_0 (BT_FN_UNSIGNED, BT_UNSIGNED)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT, BT_FLOAT)
+DEF_FUNCTION_TYPE_0 (BT_FN_DOUBLE, BT_DOUBLE)
+DEF_FUNCTION_TYPE_0 (BT_FN_LONG_DOUBLE, BT_LONG_DOUBLE)
DEF_FUNCTION_TYPE_1 (BT_FN_LONG_LONG, BT_LONG, BT_LONG)
DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_LONGLONG, BT_LONGLONG, BT_LONGLONG)
@@ -112,11 +113,15 @@ DEF_FUNCTION_TYPE_1 (BT_FN_PTR_SIZE, BT_PTR, BT_SIZE)
DEF_FUNCTION_TYPE_1 (BT_FN_INT_INT, BT_INT, BT_INT)
DEF_FUNCTION_TYPE_1 (BT_FN_INT_PTR, BT_INT, BT_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTR, BT_VOID, BT_PTR)
-DEF_FUNCTION_TYPE_1 (BT_FN_LEN_CONST_STRING, BT_LEN, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_SIZE_CONST_STRING, BT_SIZE, BT_CONST_STRING)
DEF_FUNCTION_TYPE_1 (BT_FN_INT_CONST_STRING, BT_INT, BT_CONST_STRING)
DEF_FUNCTION_TYPE_1 (BT_FN_PTR_PTR, BT_PTR, BT_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VALIST_REF, BT_VOID, BT_VALIST_REF)
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_INT, BT_VOID, BT_INT)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_CONST_STRING, BT_FLOAT, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_CONST_STRING, BT_DOUBLE, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_LONG_DOUBLE_CONST_STRING,
+ BT_LONG_DOUBLE, BT_CONST_STRING)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_INT, BT_VOID, BT_PTR, BT_INT)
DEF_FUNCTION_TYPE_2 (BT_FN_STRING_STRING_CONST_STRING,
@@ -141,25 +146,32 @@ DEF_FUNCTION_TYPE_2 (BT_FN_LONG_LONG_LONG,
BT_LONG, BT_LONG, BT_LONG)
DEF_FUNCTION_TYPE_2 (BT_FN_INT_PTR_CONST_STRING,
BT_INT, BT_PTR, BT_CONST_STRING)
-DEF_FUNCTION_TYPE_2 (BT_FN_VOID_TRAD_PTR_LEN,
- BT_VOID, BT_TRAD_PTR, BT_LEN)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_SIZE,
+ BT_VOID, BT_PTR, BT_SIZE)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_CONST_STRING, BT_VALIST_ARG)
DEF_FUNCTION_TYPE_3 (BT_FN_STRING_STRING_CONST_STRING_SIZE,
BT_STRING, BT_STRING, BT_CONST_STRING, BT_SIZE)
DEF_FUNCTION_TYPE_3 (BT_FN_INT_CONST_STRING_CONST_STRING_SIZE,
BT_INT, BT_CONST_STRING, BT_CONST_STRING, BT_SIZE)
-DEF_FUNCTION_TYPE_3 (BT_FN_TRAD_PTR_PTR_CONST_PTR_SIZE,
- BT_TRAD_PTR, BT_PTR, BT_CONST_PTR, BT_SIZE)
+DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_CONST_PTR_SIZE,
+ BT_PTR, BT_PTR, BT_CONST_PTR, BT_SIZE)
DEF_FUNCTION_TYPE_3 (BT_FN_INT_CONST_PTR_CONST_PTR_SIZE,
BT_INT, BT_CONST_PTR, BT_CONST_PTR, BT_SIZE)
-DEF_FUNCTION_TYPE_3 (BT_FN_TRAD_PTR_PTR_INT_SIZE,
- BT_TRAD_PTR, BT_PTR, BT_INT, BT_SIZE)
-DEF_FUNCTION_TYPE_3 (BT_FN_INT_TRAD_CONST_PTR_TRAD_CONST_PTR_LEN,
- BT_INT, BT_TRAD_CONST_PTR, BT_TRAD_CONST_PTR, BT_LEN)
-DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_INT, BT_VOID, BT_PTR, BT_INT, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_INT_SIZE,
+ BT_PTR, BT_PTR, BT_INT, BT_SIZE)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_INT,
+ BT_VOID, BT_PTR, BT_INT, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_INT_STRING_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_STRING, BT_CONST_STRING, BT_VALIST_ARG)
+DEF_FUNCTION_TYPE_3 (BT_FN_INT_CONST_STRING_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_CONST_STRING, BT_CONST_STRING, BT_VALIST_ARG)
DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_PTR,
BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_PTR)
+DEF_FUNCTION_TYPE_4 (BT_FN_INT_STRING_SIZE_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_STRING, BT_SIZE, BT_CONST_STRING, BT_VALIST_ARG)
DEF_FUNCTION_TYPE_VAR_0 (BT_FN_VOID_VAR, BT_VOID)
DEF_FUNCTION_TYPE_VAR_0 (BT_FN_INT_VAR, BT_INT)
@@ -174,6 +186,13 @@ DEF_FUNCTION_TYPE_VAR_1 (BT_FN_INT_CONST_STRING_VAR,
DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_PTR_CONST_STRING_VAR,
BT_INT, BT_PTR, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_STRING_CONST_STRING_VAR,
+ BT_INT, BT_STRING, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_CONST_STRING_CONST_STRING_VAR,
+ BT_INT, BT_CONST_STRING, BT_CONST_STRING)
+
+DEF_FUNCTION_TYPE_VAR_3 (BT_FN_INT_STRING_SIZE_CONST_STRING_VAR,
+ BT_INT, BT_STRING, BT_SIZE, BT_CONST_STRING)
DEF_POINTER_TYPE (BT_PTR_FN_VOID_VAR, BT_FN_VOID_VAR)
DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE,
diff --git a/contrib/gcc/builtins.c b/contrib/gcc/builtins.c
index d8874d6..4c5650a 100644
--- a/contrib/gcc/builtins.c
+++ b/contrib/gcc/builtins.c
@@ -22,9 +22,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
#include "machmode.h"
+#include "real.h"
#include "rtl.h"
#include "tree.h"
-#include "obstack.h"
#include "flags.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -41,6 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "predict.h"
#include "tm_p.h"
#include "target.h"
+#include "langhooks.h"
#define CALLED_AS_BUILT_IN(NODE) \
(!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
@@ -61,7 +62,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
const char *const built_in_class_names[4]
= {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"};
-#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA) STRINGX(X),
+#define DEF_BUILTIN(X, N, C, T, LT, B, F, NA, AT) STRINGX(X),
const char *const built_in_names[(int) END_BUILTINS] =
{
#include "builtins.def"
@@ -72,8 +73,6 @@ const char *const built_in_names[(int) END_BUILTINS] =
initialized to NULL_TREE. */
tree built_in_decls[(int) END_BUILTINS];
-tree (*lang_type_promotes_to) PARAMS ((tree));
-
static int get_pointer_alignment PARAMS ((tree, unsigned int));
static tree c_strlen PARAMS ((tree));
static const char *c_getstr PARAMS ((tree));
@@ -98,11 +97,11 @@ static rtx expand_builtin_mathfn PARAMS ((tree, rtx, rtx));
static rtx expand_builtin_constant_p PARAMS ((tree));
static rtx expand_builtin_args_info PARAMS ((tree));
static rtx expand_builtin_next_arg PARAMS ((tree));
-static rtx expand_builtin_va_start PARAMS ((int, tree));
+static rtx expand_builtin_va_start PARAMS ((tree));
static rtx expand_builtin_va_end PARAMS ((tree));
static rtx expand_builtin_va_copy PARAMS ((tree));
static rtx expand_builtin_memcmp PARAMS ((tree, tree, rtx,
- enum machine_mode));
+ enum machine_mode));
static rtx expand_builtin_strcmp PARAMS ((tree, rtx,
enum machine_mode));
static rtx expand_builtin_strncmp PARAMS ((tree, rtx,
@@ -118,17 +117,19 @@ static rtx expand_builtin_strspn PARAMS ((tree, rtx,
static rtx expand_builtin_strcspn PARAMS ((tree, rtx,
enum machine_mode));
static rtx expand_builtin_memcpy PARAMS ((tree, rtx,
- enum machine_mode));
+ enum machine_mode));
static rtx expand_builtin_strcpy PARAMS ((tree, rtx,
- enum machine_mode));
+ enum machine_mode));
static rtx builtin_strncpy_read_str PARAMS ((PTR, HOST_WIDE_INT,
enum machine_mode));
static rtx expand_builtin_strncpy PARAMS ((tree, rtx,
enum machine_mode));
static rtx builtin_memset_read_str PARAMS ((PTR, HOST_WIDE_INT,
enum machine_mode));
+static rtx builtin_memset_gen_str PARAMS ((PTR, HOST_WIDE_INT,
+ enum machine_mode));
static rtx expand_builtin_memset PARAMS ((tree, rtx,
- enum machine_mode));
+ enum machine_mode));
static rtx expand_builtin_bzero PARAMS ((tree));
static rtx expand_builtin_strlen PARAMS ((tree, rtx));
static rtx expand_builtin_strstr PARAMS ((tree, rtx,
@@ -147,6 +148,8 @@ static tree stabilize_va_list PARAMS ((tree, int));
static rtx expand_builtin_expect PARAMS ((tree, rtx));
static tree fold_builtin_constant_p PARAMS ((tree));
static tree fold_builtin_classify_type PARAMS ((tree));
+static tree fold_builtin_inf PARAMS ((tree, int));
+static tree fold_builtin_nan PARAMS ((tree, tree, int));
static tree build_function_call_expr PARAMS ((tree, tree));
static int validate_arglist PARAMS ((tree, ...));
@@ -511,7 +514,7 @@ expand_builtin_setjmp_setup (buf_addr, receiver_label)
void
expand_builtin_setjmp_receiver (receiver_label)
- rtx receiver_label ATTRIBUTE_UNUSED;
+ rtx receiver_label ATTRIBUTE_UNUSED;
{
/* Clobber the FP when we get here, so we have to make sure it's
marked as used by this function. */
@@ -639,7 +642,7 @@ void
expand_builtin_longjmp (buf_addr, value)
rtx buf_addr, value;
{
- rtx fp, lab, stack, insn;
+ rtx fp, lab, stack, insn, last;
enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
if (setjmp_alias_set == -1)
@@ -662,6 +665,7 @@ expand_builtin_longjmp (buf_addr, value)
current_function_calls_longjmp = 1;
+ last = get_last_insn ();
#ifdef HAVE_builtin_longjmp
if (HAVE_builtin_longjmp)
emit_insn (gen_builtin_longjmp (buf_addr));
@@ -707,6 +711,8 @@ expand_builtin_longjmp (buf_addr, value)
internal exception handling use only. */
for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
{
+ if (insn == last)
+ abort ();
if (GET_CODE (insn) == JUMP_INSN)
{
REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx,
@@ -714,7 +720,7 @@ expand_builtin_longjmp (buf_addr, value)
break;
}
else if (GET_CODE (insn) == CALL_INSN)
- break;
+ break;
}
}
@@ -740,7 +746,7 @@ expand_builtin_prefetch (arglist)
{
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
if (TREE_CHAIN (TREE_CHAIN (arglist)))
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
else
arg2 = build_int_2 (3, 0);
}
@@ -756,8 +762,8 @@ expand_builtin_prefetch (arglist)
/* Argument 1 (read/write flag) must be a compile-time constant int. */
if (TREE_CODE (arg1) != INTEGER_CST)
{
- error ("second arg to `__builtin_prefetch' must be a constant");
- arg1 = integer_zero_node;
+ error ("second arg to `__builtin_prefetch' must be a constant");
+ arg1 = integer_zero_node;
}
op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
/* Argument 1 must be either zero or one. */
@@ -784,19 +790,26 @@ expand_builtin_prefetch (arglist)
#ifdef HAVE_prefetch
if (HAVE_prefetch)
{
- if (! (*insn_data[(int)CODE_FOR_prefetch].operand[0].predicate)
- (op0,
- insn_data[(int)CODE_FOR_prefetch].operand[0].mode))
- op0 = force_reg (Pmode, op0);
+ if ((! (*insn_data[(int) CODE_FOR_prefetch].operand[0].predicate)
+ (op0,
+ insn_data[(int) CODE_FOR_prefetch].operand[0].mode))
+ || (GET_MODE(op0) != Pmode))
+ {
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE(op0) != Pmode)
+ op0 = convert_memory_address (Pmode, op0);
+#endif
+ op0 = force_reg (Pmode, op0);
+ }
emit_insn (gen_prefetch (op0, op1, op2));
}
else
#endif
op0 = protect_from_queue (op0, 0);
- /* Don't do anything with direct references to volatile memory, but
- generate code to handle other side effects. */
- if (GET_CODE (op0) != MEM && side_effects_p (op0))
- emit_insn (op0);
+ /* Don't do anything with direct references to volatile memory, but
+ generate code to handle other side effects. */
+ if (GET_CODE (op0) != MEM && side_effects_p (op0))
+ emit_insn (op0);
}
/* Get a MEM rtx for expression EXP which is the address of an operand
@@ -820,7 +833,7 @@ get_memory_rtx (exp)
If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
we can. First remove any nops. */
while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
- || TREE_CODE (exp) == NON_LVALUE_EXPR)
+ || TREE_CODE (exp) == NON_LVALUE_EXPR)
&& POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
exp = TREE_OPERAND (exp, 0);
@@ -874,7 +887,7 @@ apply_args_register_offset (regno)
/* Arguments are always put in outgoing registers (in the argument
block) if such make sense. */
#ifdef OUTGOING_REGNO
- regno = OUTGOING_REGNO(regno);
+ regno = OUTGOING_REGNO (regno);
#endif
return apply_args_reg_offset[regno];
}
@@ -1001,7 +1014,7 @@ apply_result_size ()
mode = GET_MODE_WIDER_MODE (mode))
if (HARD_REGNO_MODE_OK (regno, mode)
&& have_insn_for (SET, mode))
- best_mode = mode;
+ best_mode = mode;
if (best_mode == VOIDmode)
for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
@@ -1147,12 +1160,12 @@ expand_builtin_apply_args ()
apply_args_value = temp;
- /* Put the sequence after the NOTE that starts the function.
- If this is inside a SEQUENCE, make the outer-level insn
+ /* Put the insns after the NOTE that starts the function.
+ If this is inside a start_sequence, make the outer-level insn
chain current, so the code is placed at the start of the
function. */
push_topmost_sequence ();
- emit_insns_before (seq, NEXT_INSN (get_insns ()));
+ emit_insn_before (seq, NEXT_INSN (get_insns ()));
pop_topmost_sequence ();
return temp;
}
@@ -1214,7 +1227,7 @@ expand_builtin_apply (function, arguments, argsize)
set_mem_align (dest, PARM_BOUNDARY);
src = gen_rtx_MEM (BLKmode, incoming_args);
set_mem_align (src, PARM_BOUNDARY);
- emit_block_move (dest, src, argsize);
+ emit_block_move (dest, src, argsize, BLOCK_OP_NORMAL);
/* Refer to the argument block. */
apply_args_size ();
@@ -1249,7 +1262,7 @@ expand_builtin_apply (function, arguments, argsize)
emit_move_insn (value, adjust_address (arguments, Pmode, size));
emit_move_insn (struct_value_rtx, value);
if (GET_CODE (struct_value_rtx) == REG)
- use_reg (&call_fusage, struct_value_rtx);
+ use_reg (&call_fusage, struct_value_rtx);
size += GET_MODE_SIZE (Pmode);
}
@@ -1381,7 +1394,7 @@ expand_builtin_return (result)
}
/* Put the USE insns before the return. */
- emit_insns (call_fusage);
+ emit_insn (call_fusage);
/* Return whatever values was restored by jumping directly to the end
of the function. */
@@ -1470,6 +1483,7 @@ expand_builtin_mathfn (exp, target, subtarget)
rtx op0, insns;
tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
tree arglist = TREE_OPERAND (exp, 1);
+ enum machine_mode argmode;
if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
return 0;
@@ -1512,14 +1526,22 @@ expand_builtin_mathfn (exp, target, subtarget)
case BUILT_IN_SQRTF:
case BUILT_IN_SQRTL:
builtin_optab = sqrt_optab; break;
- default:
+ case BUILT_IN_EXP:
+ case BUILT_IN_EXPF:
+ case BUILT_IN_EXPL:
+ builtin_optab = exp_optab; break;
+ case BUILT_IN_LOG:
+ case BUILT_IN_LOGF:
+ case BUILT_IN_LOGL:
+ builtin_optab = log_optab; break;
+ default:
abort ();
}
/* Compute into TARGET.
Set TARGET to wherever the result comes back. */
- target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
- builtin_optab, op0, target, 0);
+ argmode = TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist)));
+ target = expand_unop (argmode, builtin_optab, op0, target, 0);
/* If we were unable to expand via the builtin, stop the
sequence (without outputting the insns) and return 0, causing
@@ -1530,18 +1552,12 @@ expand_builtin_mathfn (exp, target, subtarget)
return 0;
}
- /* If errno must be maintained and if we are not allowing unsafe
- math optimizations, check the result. */
+ /* If errno must be maintained, we must set it to EDOM for NaN results. */
- if (flag_errno_math && ! flag_unsafe_math_optimizations)
+ if (flag_errno_math && HONOR_NANS (argmode))
{
rtx lab1;
- /* Don't define the builtin FP instructions
- if your machine is not IEEE. */
- if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
- abort ();
-
lab1 = gen_label_rtx ();
/* Test the result; if it is NaN, set errno=EDOM because
@@ -1550,16 +1566,16 @@ expand_builtin_mathfn (exp, target, subtarget)
0, lab1);
#ifdef TARGET_EDOM
- {
+ {
#ifdef GEN_ERRNO_RTX
- rtx errno_rtx = GEN_ERRNO_RTX;
+ rtx errno_rtx = GEN_ERRNO_RTX;
#else
- rtx errno_rtx
- = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
+ rtx errno_rtx
+ = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
#endif
- emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
- }
+ emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
+ }
#else
/* We can't set errno=EDOM directly; let the library call do it.
Pop the arguments right away in case the call gets deleted. */
@@ -1574,7 +1590,7 @@ expand_builtin_mathfn (exp, target, subtarget)
/* Output the entire sequence. */
insns = get_insns ();
end_sequence ();
- emit_insns (insns);
+ emit_insn (insns);
return target;
}
@@ -1636,7 +1652,7 @@ expand_builtin_strlen (exp, target)
/* Mark the beginning of the strlen sequence so we can emit the
source operand later. */
- before_strlen = get_last_insn();
+ before_strlen = get_last_insn ();
char_rtx = const0_rtx;
char_mode = insn_data[(int) icode].operand[2].mode;
@@ -1656,7 +1672,7 @@ expand_builtin_strlen (exp, target)
expand_expr (src, src_reg, ptr_mode, EXPAND_SUM));
if (pat != src_reg)
emit_move_insn (src_reg, pat);
- pat = gen_sequence ();
+ pat = get_insns ();
end_sequence ();
if (before_strlen)
@@ -1942,20 +1958,20 @@ expand_builtin_memcpy (arglist, target, mode)
/* If DEST is not a pointer type, call the normal function. */
if (dest_align == 0)
- return 0;
+ return 0;
/* If the LEN parameter is zero, return DEST. */
if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
- {
- /* Evaluate and ignore SRC in case it has side-effects. */
- expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return expand_expr (dest, target, mode, EXPAND_NORMAL);
- }
+ {
+ /* Evaluate and ignore SRC in case it has side-effects. */
+ expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ return expand_expr (dest, target, mode, EXPAND_NORMAL);
+ }
/* If either SRC is not a pointer type, don't do this
operation in-line. */
if (src_align == 0)
- return 0;
+ return 0;
dest_mem = get_memory_rtx (dest);
set_mem_align (dest_mem, dest_align);
@@ -1974,17 +1990,29 @@ expand_builtin_memcpy (arglist, target, mode)
store_by_pieces (dest_mem, INTVAL (len_rtx),
builtin_memcpy_read_str,
(PTR) src_str, dest_align);
- return force_operand (XEXP (dest_mem, 0), NULL_RTX);
+ dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE (dest_mem) != ptr_mode)
+ dest_mem = convert_memory_address (ptr_mode, dest_mem);
+#endif
+ return dest_mem;
}
src_mem = get_memory_rtx (src);
set_mem_align (src_mem, src_align);
/* Copy word part most expediently. */
- dest_addr = emit_block_move (dest_mem, src_mem, len_rtx);
+ dest_addr = emit_block_move (dest_mem, src_mem, len_rtx,
+ BLOCK_OP_NORMAL);
if (dest_addr == 0)
- dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
+ {
+ dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE (dest_addr) != ptr_mode)
+ dest_addr = convert_memory_address (ptr_mode, dest_addr);
+#endif
+ }
return dest_addr;
}
@@ -2002,7 +2030,7 @@ expand_builtin_strcpy (exp, target, mode)
enum machine_mode mode;
{
tree arglist = TREE_OPERAND (exp, 1);
- tree fn, len;
+ tree fn, len, src, dst;
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
@@ -2011,14 +2039,18 @@ expand_builtin_strcpy (exp, target, mode)
if (!fn)
return 0;
- len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
- if (len == 0)
+ src = TREE_VALUE (TREE_CHAIN (arglist));
+ len = c_strlen (src);
+ if (len == 0 || TREE_SIDE_EFFECTS (len))
return 0;
+ dst = TREE_VALUE (arglist);
len = size_binop (PLUS_EXPR, len, ssize_int (1));
- chainon (arglist, build_tree_list (NULL_TREE, len));
+ arglist = build_tree_list (NULL_TREE, len);
+ arglist = tree_cons (NULL_TREE, src, arglist);
+ arglist = tree_cons (NULL_TREE, dst, arglist);
return expand_expr (build_function_call_expr (fn, arglist),
- target, mode, EXPAND_NORMAL);
+ target, mode, EXPAND_NORMAL);
}
/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
@@ -2063,9 +2095,9 @@ expand_builtin_strncpy (arglist, target, mode)
/* If the len parameter is zero, return the dst parameter. */
if (integer_zerop (len))
- {
- /* Evaluate and ignore the src argument in case it has
- side-effects. */
+ {
+ /* Evaluate and ignore the src argument in case it has
+ side-effects. */
expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
VOIDmode, EXPAND_NORMAL);
/* Return the dst parameter. */
@@ -2100,15 +2132,20 @@ expand_builtin_strncpy (arglist, target, mode)
store_by_pieces (dest_mem, tree_low_cst (len, 1),
builtin_strncpy_read_str,
(PTR) p, dest_align);
- return force_operand (XEXP (dest_mem, 0), NULL_RTX);
+ dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE (dest_mem) != ptr_mode)
+ dest_mem = convert_memory_address (ptr_mode, dest_mem);
+#endif
+ return dest_mem;
}
/* OK transform into builtin memcpy. */
fn = built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
- return 0;
+ return 0;
return expand_expr (build_function_call_expr (fn, arglist),
- target, mode, EXPAND_NORMAL);
+ target, mode, EXPAND_NORMAL);
}
}
@@ -2130,6 +2167,34 @@ builtin_memset_read_str (data, offset, mode)
return c_readstr (p, mode);
}
+/* Callback routine for store_by_pieces. Return the RTL of a register
+ containing GET_MODE_SIZE (MODE) consecutive copies of the unsigned
+ char value given in the RTL register data. For example, if mode is
+ 4 bytes wide, return the RTL for 0x01010101*data. */
+
+static rtx
+builtin_memset_gen_str (data, offset, mode)
+ PTR data;
+ HOST_WIDE_INT offset ATTRIBUTE_UNUSED;
+ enum machine_mode mode;
+{
+ rtx target, coeff;
+ size_t size;
+ char *p;
+
+ size = GET_MODE_SIZE (mode);
+ if (size == 1)
+ return (rtx) data;
+
+ p = alloca (size);
+ memset (p, 1, size);
+ coeff = c_readstr (p, mode);
+
+ target = convert_to_mode (mode, (rtx) data, 1);
+ target = expand_mult (mode, target, coeff, NULL_RTX, 1);
+ return force_reg (mode, target);
+}
+
/* Expand expression EXP, which is a call to the memset builtin. Return 0
if we failed the caller should emit a normal call, otherwise try to get
the result in TARGET, if convenient (and in mode MODE if that's
@@ -2164,14 +2229,46 @@ expand_builtin_memset (exp, target, mode)
/* If the LEN parameter is zero, return DEST. */
if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
- {
- /* Evaluate and ignore VAL in case it has side-effects. */
- expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return expand_expr (dest, target, mode, EXPAND_NORMAL);
- }
+ {
+ /* Evaluate and ignore VAL in case it has side-effects. */
+ expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ return expand_expr (dest, target, mode, EXPAND_NORMAL);
+ }
if (TREE_CODE (val) != INTEGER_CST)
- return 0;
+ {
+ rtx val_rtx;
+
+ if (!host_integerp (len, 1))
+ return 0;
+
+ if (optimize_size && tree_low_cst (len, 1) > 1)
+ return 0;
+
+ /* Assume that we can memset by pieces if we can store the
+ * the coefficients by pieces (in the required modes).
+ * We can't pass builtin_memset_gen_str as that emits RTL. */
+ c = 1;
+ if (!can_store_by_pieces (tree_low_cst (len, 1),
+ builtin_memset_read_str,
+ (PTR) &c, dest_align))
+ return 0;
+
+ val = fold (build1 (CONVERT_EXPR, unsigned_char_type_node, val));
+ val_rtx = expand_expr (val, NULL_RTX, VOIDmode, 0);
+ val_rtx = force_reg (TYPE_MODE (unsigned_char_type_node),
+ val_rtx);
+ dest_mem = get_memory_rtx (dest);
+ store_by_pieces (dest_mem, tree_low_cst (len, 1),
+ builtin_memset_gen_str,
+ (PTR) val_rtx, dest_align);
+ dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE (dest_mem) != ptr_mode)
+ dest_mem = convert_memory_address (ptr_mode, dest_mem);
+#endif
+ return dest_mem;
+ }
if (target_char_cast (val, &c))
return 0;
@@ -2189,7 +2286,12 @@ expand_builtin_memset (exp, target, mode)
store_by_pieces (dest_mem, tree_low_cst (len, 1),
builtin_memset_read_str,
(PTR) &c, dest_align);
- return force_operand (XEXP (dest_mem, 0), NULL_RTX);
+ dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE (dest_mem) != ptr_mode)
+ dest_mem = convert_memory_address (ptr_mode, dest_mem);
+#endif
+ return dest_mem;
}
len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
@@ -2199,7 +2301,13 @@ expand_builtin_memset (exp, target, mode)
dest_addr = clear_storage (dest_mem, len_rtx);
if (dest_addr == 0)
- dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
+ {
+ dest_addr = force_operand (XEXP (dest_mem, 0), NULL_RTX);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE (dest_addr) != ptr_mode)
+ dest_addr = convert_memory_address (ptr_mode, dest_addr);
+#endif
+ }
return dest_addr;
}
@@ -2256,7 +2364,7 @@ expand_builtin_memcmp (exp, arglist, target, mode)
const char *p1, *p2;
if (!validate_arglist (arglist,
- POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
arg1 = TREE_VALUE (arglist);
@@ -2295,12 +2403,12 @@ expand_builtin_memcmp (exp, arglist, target, mode)
tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
tree ind1 =
fold (build1 (CONVERT_EXPR, integer_type_node,
- build1 (INDIRECT_REF, cst_uchar_node,
- build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
+ build1 (INDIRECT_REF, cst_uchar_node,
+ build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
tree ind2 =
fold (build1 (CONVERT_EXPR, integer_type_node,
- build1 (INDIRECT_REF, cst_uchar_node,
- build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
+ build1 (INDIRECT_REF, cst_uchar_node,
+ build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
@@ -2437,12 +2545,12 @@ expand_builtin_strcmp (exp, target, mode)
if (!len || TREE_CODE (len) != INTEGER_CST)
{
if (len2 && !TREE_SIDE_EFFECTS (len2))
- len = len2;
+ len = len2;
else if (len == 0)
- return 0;
+ return 0;
}
else if (len2 && TREE_CODE (len2) == INTEGER_CST
- && tree_int_cst_lt (len2, len))
+ && tree_int_cst_lt (len2, len))
len = len2;
/* If both arguments have side effects, we cannot optimize. */
@@ -2453,9 +2561,11 @@ expand_builtin_strcmp (exp, target, mode)
if (!fn)
return 0;
- chainon (arglist, build_tree_list (NULL_TREE, len));
+ arglist = build_tree_list (NULL_TREE, len);
+ arglist = tree_cons (NULL_TREE, arg2, arglist);
+ arglist = tree_cons (NULL_TREE, arg1, arglist);
return expand_expr (build_function_call_expr (fn, arglist),
- target, mode, EXPAND_NORMAL);
+ target, mode, EXPAND_NORMAL);
}
/* Expand expression EXP, which is a call to the strncmp builtin. Return 0
@@ -2483,23 +2593,23 @@ expand_builtin_strncmp (exp, target, mode)
/* If the len parameter is zero, return zero. */
if (host_integerp (arg3, 1) && tree_low_cst (arg3, 1) == 0)
- {
- /* Evaluate and ignore arg1 and arg2 in case they have
- side-effects. */
- expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
- expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return const0_rtx;
- }
+ {
+ /* Evaluate and ignore arg1 and arg2 in case they have
+ side-effects. */
+ expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ return const0_rtx;
+ }
p1 = c_getstr (arg1);
p2 = c_getstr (arg2);
/* If all arguments are constant, evaluate at compile-time. */
if (host_integerp (arg3, 1) && p1 && p2)
- {
- const int r = strncmp (p1, p2, tree_low_cst (arg3, 1));
- return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
- }
+ {
+ const int r = strncmp (p1, p2, tree_low_cst (arg3, 1));
+ return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
+ }
/* If len == 1 or (either string parameter is "" and (len >= 1)),
return (*(const u_char*)arg1 - *(const u_char*)arg2). */
@@ -2557,7 +2667,7 @@ expand_builtin_strncmp (exp, target, mode)
newarglist = tree_cons (NULL_TREE, arg2, newarglist);
newarglist = tree_cons (NULL_TREE, arg1, newarglist);
return expand_expr (build_function_call_expr (fn, newarglist),
- target, mode, EXPAND_NORMAL);
+ target, mode, EXPAND_NORMAL);
}
/* Expand expression EXP, which is a call to the strcat builtin.
@@ -2609,7 +2719,7 @@ expand_builtin_strncat (arglist, target, mode)
/* If the requested length is zero, or the src parameter string
length is zero, return the dst parameter. */
if (integer_zerop (len) || (p && *p == '\0'))
- {
+ {
/* Evaluate and ignore the src and len parameters in case
they have side-effects. */
expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
@@ -2621,7 +2731,7 @@ expand_builtin_strncat (arglist, target, mode)
length, call strcat. */
if (TREE_CODE (len) == INTEGER_CST && p
&& compare_tree_int (len, strlen (p)) >= 0)
- {
+ {
tree newarglist
= tree_cons (NULL_TREE, dst, build_tree_list (NULL_TREE, src));
tree fn = built_in_decls[BUILT_IN_STRCAT];
@@ -2657,14 +2767,14 @@ expand_builtin_strspn (arglist, target, mode)
/* If both arguments are constants, evaluate at compile-time. */
if (p1 && p2)
- {
+ {
const size_t r = strspn (p1, p2);
return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
}
/* If either argument is "", return 0. */
if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
- {
+ {
/* Evaluate and ignore both arguments in case either one has
side-effects. */
expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
@@ -2694,14 +2804,14 @@ expand_builtin_strcspn (arglist, target, mode)
/* If both arguments are constants, evaluate at compile-time. */
if (p1 && p2)
- {
+ {
const size_t r = strcspn (p1, p2);
return expand_expr (size_int (r), target, mode, EXPAND_NORMAL);
}
/* If the first argument is "", return 0. */
if (p1 && *p1 == '\0')
- {
+ {
/* Evaluate and ignore argument s2 in case it has
side-effects. */
expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
@@ -2710,7 +2820,7 @@ expand_builtin_strcspn (arglist, target, mode)
/* If the second argument is "", return __builtin_strlen(s1). */
if (p2 && *p2 == '\0')
- {
+ {
tree newarglist = build_tree_list (NULL_TREE, s1),
fn = built_in_decls[BUILT_IN_STRLEN];
@@ -2766,11 +2876,11 @@ expand_builtin_saveregs ()
saveregs_value = val;
- /* Put the sequence after the NOTE that starts the function. If this
- is inside a SEQUENCE, make the outer-level insn chain current, so
+ /* Put the insns after the NOTE that starts the function. If this
+ is inside a start_sequence, make the outer-level insn chain current, so
the code is placed at the start of the function. */
push_topmost_sequence ();
- emit_insns_after (seq, get_insns ());
+ emit_insn_after (seq, get_insns ());
pop_topmost_sequence ();
return val;
@@ -2838,10 +2948,9 @@ expand_builtin_next_arg (arglist)
{
tree fntype = TREE_TYPE (current_function_decl);
- if ((TYPE_ARG_TYPES (fntype) == 0
- || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
- == void_type_node))
- && ! current_function_varargs)
+ if (TYPE_ARG_TYPES (fntype) == 0
+ || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
+ == void_type_node))
{
error ("`va_start' used in function with fixed args");
return const0_rtx;
@@ -2864,7 +2973,7 @@ expand_builtin_next_arg (arglist)
if (arg != last_parm)
warning ("second parameter of `va_start' not last named argument");
}
- else if (! current_function_varargs)
+ else
/* Evidently an out of date version of <stdarg.h>; can't validate
va_start's second argument, but can still work as intended. */
warning ("`__builtin_next_arg' called without an argument");
@@ -2928,25 +3037,12 @@ stabilize_va_list (valist, needs_lvalue)
the variable. */
void
-std_expand_builtin_va_start (stdarg_p, valist, nextarg)
- int stdarg_p;
+std_expand_builtin_va_start (valist, nextarg)
tree valist;
rtx nextarg;
{
tree t;
- if (! stdarg_p)
- {
- /* The dummy named parameter is declared as a 'word' sized
- object, but if a 'word' is smaller than an 'int', it would
- have been promoted to int when it was added to the arglist. */
- int align = PARM_BOUNDARY / BITS_PER_UNIT;
- int size = MAX (UNITS_PER_WORD,
- GET_MODE_SIZE (TYPE_MODE (integer_type_node)));
- int offset = ((size + align - 1) / align) * align;
- nextarg = plus_constant (nextarg, -offset);
- }
-
t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
make_tree (ptr_type_node, nextarg));
TREE_SIDE_EFFECTS (t) = 1;
@@ -2954,31 +3050,27 @@ std_expand_builtin_va_start (stdarg_p, valist, nextarg)
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
-/* Expand ARGLIST, which from a call to __builtin_stdarg_va_start or
- __builtin_varargs_va_start, depending on STDARG_P. */
+/* Expand ARGLIST, from a call to __builtin_va_start. */
static rtx
-expand_builtin_va_start (stdarg_p, arglist)
- int stdarg_p;
+expand_builtin_va_start (arglist)
tree arglist;
{
rtx nextarg;
- tree chain = arglist, valist;
+ tree chain, valist;
- if (stdarg_p)
- nextarg = expand_builtin_next_arg (chain = TREE_CHAIN (arglist));
- else
- nextarg = expand_builtin_next_arg (NULL_TREE);
+ chain = TREE_CHAIN (arglist);
if (TREE_CHAIN (chain))
error ("too many arguments to function `va_start'");
+ nextarg = expand_builtin_next_arg (chain);
valist = stabilize_va_list (TREE_VALUE (arglist), 1);
#ifdef EXPAND_BUILTIN_VA_START
- EXPAND_BUILTIN_VA_START (stdarg_p, valist, nextarg);
+ EXPAND_BUILTIN_VA_START (valist, nextarg);
#else
- std_expand_builtin_va_start (stdarg_p, valist, nextarg);
+ std_expand_builtin_va_start (valist, nextarg);
#endif
return const0_rtx;
@@ -3078,7 +3170,8 @@ expand_builtin_va_arg (valist, type)
/* Generate a diagnostic for requesting data of a type that cannot
be passed through `...' due to type promotion at the call site. */
- else if ((promoted_type = (*lang_type_promotes_to) (type)) != NULL_TREE)
+ else if ((promoted_type = (*lang_hooks.types.type_promotes_to) (type))
+ != type)
{
const char *name = "<anonymous type>", *pname = 0;
static bool gave_help;
@@ -3154,7 +3247,7 @@ expand_builtin_va_end (arglist)
#ifdef EXPAND_BUILTIN_VA_END
valist = stabilize_va_list (valist, 0);
- EXPAND_BUILTIN_VA_END(arglist);
+ EXPAND_BUILTIN_VA_END (arglist);
#else
/* Evaluate for side effects, if needed. I hate macros that don't
do that. */
@@ -3214,7 +3307,7 @@ expand_builtin_va_copy (arglist)
set_mem_align (srcb, TYPE_ALIGN (va_list_type_node));
/* Copy. */
- emit_block_move (dstb, srcb, size);
+ emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL);
}
return const0_rtx;
@@ -3385,8 +3478,12 @@ expand_builtin_fputs (arglist, ignore, unlocked)
/* FALLTHROUGH */
case 1: /* length is greater than 1, call fwrite. */
{
- tree string_arg = TREE_VALUE (arglist);
+ tree string_arg;
+ /* If optimizing for size keep fputs. */
+ if (optimize_size)
+ return 0;
+ string_arg = TREE_VALUE (arglist);
/* New argument list transforming fputs(string, stream) to
fwrite(string, 1, len, stream). */
arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
@@ -3432,7 +3529,7 @@ expand_builtin_expect (arglist, target)
target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
/* Don't bother with expected value notes for integral constants. */
- if (GET_CODE (target) != CONST_INT)
+ if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
{
/* We do need to force this into a register so that we can be
moderately sure to be able to correctly interpret the branch
@@ -3450,7 +3547,7 @@ expand_builtin_expect (arglist, target)
/* Like expand_builtin_expect, except do this in a jump context. This is
called from do_jump if the conditional is a __builtin_expect. Return either
- a SEQUENCE of insns to emit the jump or NULL if we cannot optimize
+ a list of insns to emit the jump or NULL if we cannot optimize
__builtin_expect. We need to optimize this at jump time so that machines
like the PowerPC don't turn the test into a SCC operation, and then jump
based on the test being 0/1. */
@@ -3471,8 +3568,8 @@ expand_builtin_expect_jump (exp, if_false_label, if_true_label)
if (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
&& (integer_zerop (arg1) || integer_onep (arg1)))
{
- int j;
int num_jumps = 0;
+ rtx insn;
/* If we fail to locate an appropriate conditional jump, we'll
fall back to normal evaluation. Ensure that the expression
@@ -3493,16 +3590,17 @@ expand_builtin_expect_jump (exp, if_false_label, if_true_label)
/* Expand the jump insns. */
start_sequence ();
do_jump (arg0, if_false_label, if_true_label);
- ret = gen_sequence ();
+ ret = get_insns ();
end_sequence ();
/* Now that the __builtin_expect has been validated, go through and add
the expect's to each of the conditional jumps. If we run into an
error, just give up and generate the 'safe' code of doing a SCC
operation and then doing a branch on that. */
- for (j = 0; j < XVECLEN (ret, 0); j++)
+ insn = ret;
+ while (insn != NULL_RTX)
{
- rtx insn = XVECEXP (ret, 0, j);
+ rtx next = NEXT_INSN (insn);
rtx pattern;
if (GET_CODE (insn) == JUMP_INSN && any_condjump_p (insn)
@@ -3513,7 +3611,7 @@ expand_builtin_expect_jump (exp, if_false_label, if_true_label)
int taken;
if (GET_CODE (ifelse) != IF_THEN_ELSE)
- continue;
+ goto do_next_insn;
if (GET_CODE (XEXP (ifelse, 1)) == LABEL_REF)
{
@@ -3540,7 +3638,7 @@ expand_builtin_expect_jump (exp, if_false_label, if_true_label)
label = NULL_RTX;
}
else
- continue;
+ goto do_next_insn;
/* If the test is expected to fail, reverse the
probabilities. */
@@ -3554,11 +3652,14 @@ expand_builtin_expect_jump (exp, if_false_label, if_true_label)
else if (label == if_false_label)
taken = 1 - taken;
else if (label != if_true_label)
- continue;
+ goto do_next_insn;
num_jumps++;
predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
}
+
+ do_next_insn:
+ insn = next;
}
/* If no jumps were modified, fail and do __builtin_expect the normal
@@ -3600,6 +3701,9 @@ expand_builtin (exp, target, subtarget, mode, ignore)
tree arglist = TREE_OPERAND (exp, 1);
enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+ /* Perform postincrements before expanding builtin functions.  */
+ emit_queue ();
+
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
return (*targetm.expand_builtin) (exp, target, subtarget, mode, ignore);
@@ -3608,11 +3712,18 @@ expand_builtin (exp, target, subtarget, mode, ignore)
if (!optimize && !CALLED_AS_BUILT_IN (fndecl))
switch (fcode)
{
- case BUILT_IN_SIN:
- case BUILT_IN_COS:
case BUILT_IN_SQRT:
case BUILT_IN_SQRTF:
case BUILT_IN_SQRTL:
+ case BUILT_IN_SIN:
+ case BUILT_IN_SINF:
+ case BUILT_IN_SINL:
+ case BUILT_IN_COS:
+ case BUILT_IN_COSF:
+ case BUILT_IN_COSL:
+ case BUILT_IN_EXP:
+ case BUILT_IN_EXPF:
+ case BUILT_IN_EXPL:
case BUILT_IN_MEMSET:
case BUILT_IN_MEMCPY:
case BUILT_IN_MEMCMP:
@@ -3646,11 +3757,11 @@ expand_builtin (exp, target, subtarget, mode, ignore)
case BUILT_IN_FPUTC_UNLOCKED:
case BUILT_IN_FPUTS_UNLOCKED:
case BUILT_IN_FWRITE_UNLOCKED:
- return expand_call (exp, target, ignore);
+ return expand_call (exp, target, ignore);
default:
- break;
- }
+ break;
+ }
switch (fcode)
{
@@ -3683,6 +3794,12 @@ expand_builtin (exp, target, subtarget, mode, ignore)
case BUILT_IN_COS:
case BUILT_IN_COSF:
case BUILT_IN_COSL:
+ case BUILT_IN_EXP:
+ case BUILT_IN_EXPF:
+ case BUILT_IN_EXPL:
+ case BUILT_IN_LOG:
+ case BUILT_IN_LOGF:
+ case BUILT_IN_LOGL:
/* Treat these like sqrt only if unsafe math optimizations are allowed,
because of possible accuracy problems. */
if (! flag_unsafe_math_optimizations)
@@ -3695,9 +3812,6 @@ expand_builtin (exp, target, subtarget, mode, ignore)
return target;
break;
- case BUILT_IN_FMOD:
- break;
-
case BUILT_IN_APPLY_ARGS:
return expand_builtin_apply_args ();
@@ -3762,11 +3876,11 @@ expand_builtin (exp, target, subtarget, mode, ignore)
0 otherwise. */
case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
if (arglist != 0
- || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
- || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
- return const0_rtx;
+ || ! AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
+ || GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) != MEM)
+ return const0_rtx;
else
- return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
+ return XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
case BUILT_IN_ALLOCA:
target = expand_builtin_alloca (arglist, target);
@@ -3918,15 +4032,6 @@ expand_builtin (exp, target, subtarget, mode, ignore)
expand_builtin_trap ();
return const0_rtx;
- case BUILT_IN_PUTCHAR:
- case BUILT_IN_PUTS:
- case BUILT_IN_FPUTC:
- case BUILT_IN_FWRITE:
- case BUILT_IN_PUTCHAR_UNLOCKED:
- case BUILT_IN_PUTS_UNLOCKED:
- case BUILT_IN_FPUTC_UNLOCKED:
- case BUILT_IN_FWRITE_UNLOCKED:
- break;
case BUILT_IN_FPUTS:
target = expand_builtin_fputs (arglist, ignore,/*unlocked=*/ 0);
if (target)
@@ -3945,8 +4050,8 @@ expand_builtin (exp, target, subtarget, mode, ignore)
case BUILT_IN_DWARF_CFA:
return virtual_cfa_rtx;
#ifdef DWARF2_UNWIND_INFO
- case BUILT_IN_DWARF_FP_REGNUM:
- return expand_builtin_dwarf_fp_regnum ();
+ case BUILT_IN_DWARF_SP_COLUMN:
+ return expand_builtin_dwarf_sp_column ();
case BUILT_IN_INIT_DWARF_REG_SIZES:
expand_builtin_init_dwarf_reg_sizes (TREE_VALUE (arglist));
return const0_rtx;
@@ -3963,10 +4068,9 @@ expand_builtin (exp, target, subtarget, mode, ignore)
case BUILT_IN_EH_RETURN_DATA_REGNO:
return expand_builtin_eh_return_data_regno (arglist);
#endif
- case BUILT_IN_VARARGS_START:
- return expand_builtin_va_start (0, arglist);
+ case BUILT_IN_VA_START:
case BUILT_IN_STDARG_START:
- return expand_builtin_va_start (1, arglist);
+ return expand_builtin_va_start (arglist);
case BUILT_IN_VA_END:
return expand_builtin_va_end (arglist);
case BUILT_IN_VA_COPY:
@@ -3978,9 +4082,10 @@ expand_builtin (exp, target, subtarget, mode, ignore)
return const0_rtx;
- default: /* just do library call, if unknown builtin */
- error ("built-in function `%s' not currently supported",
- IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+ default: /* just do library call, if unknown builtin */
+ if (!DECL_ASSEMBLER_NAME_SET_P (fndecl))
+ error ("built-in function `%s' not currently supported",
+ IDENTIFIER_POINTER (DECL_NAME (fndecl)));
}
/* The switch statement above can drop through to cause the function
@@ -4042,6 +4147,44 @@ fold_builtin_classify_type (arglist)
return build_int_2 (type_to_class (TREE_TYPE (TREE_VALUE (arglist))), 0);
}
+/* Fold a call to __builtin_inf or __builtin_huge_val. */
+
+static tree
+fold_builtin_inf (type, warn)
+ tree type;
+ int warn;
+{
+ REAL_VALUE_TYPE real;
+
+ if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
+ warning ("target format does not support infinity");
+
+ real_inf (&real);
+ return build_real (type, real);
+}
+
+/* Fold a call to __builtin_nan or __builtin_nans. */
+
+static tree
+fold_builtin_nan (arglist, type, quiet)
+ tree arglist, type;
+ int quiet;
+{
+ REAL_VALUE_TYPE real;
+ const char *str;
+
+ if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
+ return 0;
+ str = c_getstr (TREE_VALUE (arglist));
+ if (!str)
+ return 0;
+
+ if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
+ return 0;
+
+ return build_real (type, real);
+}
+
/* Used by constant folding to eliminate some builtin calls early. EXP is
the CALL_EXPR of a call to a builtin function. */
@@ -4078,6 +4221,26 @@ fold_builtin (exp)
}
break;
+ case BUILT_IN_INF:
+ case BUILT_IN_INFF:
+ case BUILT_IN_INFL:
+ return fold_builtin_inf (TREE_TYPE (TREE_TYPE (fndecl)), true);
+
+ case BUILT_IN_HUGE_VAL:
+ case BUILT_IN_HUGE_VALF:
+ case BUILT_IN_HUGE_VALL:
+ return fold_builtin_inf (TREE_TYPE (TREE_TYPE (fndecl)), false);
+
+ case BUILT_IN_NAN:
+ case BUILT_IN_NANF:
+ case BUILT_IN_NANL:
+ return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), true);
+
+ case BUILT_IN_NANS:
+ case BUILT_IN_NANSF:
+ case BUILT_IN_NANSL:
+ return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), false);
+
default:
break;
}
@@ -4112,29 +4275,32 @@ validate_arglist VPARAMS ((tree arglist, ...))
VA_OPEN (ap, arglist);
VA_FIXEDARG (ap, tree, arglist);
- do {
- code = va_arg (ap, enum tree_code);
- switch (code)
+ do
{
- case 0:
- /* This signifies an ellipses, any further arguments are all ok. */
- res = 1;
- goto end;
- case VOID_TYPE:
- /* This signifies an endlink, if no arguments remain, return
- true, otherwise return false. */
- res = arglist == 0;
- goto end;
- default:
- /* If no parameters remain or the parameter's code does not
- match the specified code, return false. Otherwise continue
- checking any remaining arguments. */
- if (arglist == 0 || code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
- goto end;
- break;
+ code = va_arg (ap, enum tree_code);
+ switch (code)
+ {
+ case 0:
+ /* This signifies an ellipses, any further arguments are all ok. */
+ res = 1;
+ goto end;
+ case VOID_TYPE:
+ /* This signifies an endlink, if no arguments remain, return
+ true, otherwise return false. */
+ res = arglist == 0;
+ goto end;
+ default:
+ /* If no parameters remain or the parameter's code does not
+ match the specified code, return false. Otherwise continue
+ checking any remaining arguments. */
+ if (arglist == 0
+ || code != TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))))
+ goto end;
+ break;
+ }
+ arglist = TREE_CHAIN (arglist);
}
- arglist = TREE_CHAIN (arglist);
- } while (1);
+ while (1);
/* We need gotos here since we can only have one VA_CLOSE in a
function. */
diff --git a/contrib/gcc/builtins.def b/contrib/gcc/builtins.def
index c6f6dc4..c208b75 100644
--- a/contrib/gcc/builtins.def
+++ b/contrib/gcc/builtins.def
@@ -22,7 +22,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* Before including this file, you should define a macro:
DEF_BUILTIN (ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P,
- FALLBACK_P, NONANSI_P)
+ FALLBACK_P, NONANSI_P, ATTRS)
This macro will be called once for each builtin function. The
ENUM will be of type `enum built_in_function', and will indicate
@@ -50,15 +50,18 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
If NONANSI_P is true, then the non-`__builtin_' variant is not an
ANSI/ISO library function, and so we should pretend it does not
- exist when compiling in ANSI conformant mode. */
+ exist when compiling in ANSI conformant mode.
+
+ ATTRs is an attribute list as defined in builtin-attrs.def that
+ describes the attributes of this builtin function. */
/* A GCC builtin (like __builtin_saveregs) is provided by the
compiler, but does not correspond to a function in the standard
library. */
#undef DEF_GCC_BUILTIN
-#define DEF_GCC_BUILTIN(ENUM, NAME, TYPE) \
+#define DEF_GCC_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, BT_LAST, \
- false, false, false)
+ false, false, false, ATTRS)
/* A fallback builtin is a builtin (like __builtin_puts) that falls
@@ -66,9 +69,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
for which we should not introduce the non-`__builtin' variant of
the name. */
#undef DEF_FALLBACK_BUILTIN
-#define DEF_FALLBACK_BUILTIN(ENUM, NAME, TYPE) \
+#define DEF_FALLBACK_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
- false, true, false)
+ false, true, false, ATTRS)
/* Like DEF_FALLBACK_BUILTIN, except that the function is not one that
is specified by ANSI/ISO C. So, when we're being fully conformant
@@ -77,74 +80,76 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#undef DEF_EXT_FALLBACK_BUILTIN
#define DEF_EXT_FALLBACK_BUILTIN(ENUM, NAME, TYPE) \
DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
- false, true, true)
+ false, true, true, ATTR_NOTHROW_LIST)
/* A library builtin (like __builtin_strchr) is a builtin equivalent
of an ANSI/ISO standard library function. In addition to the
`__builtin' version, we will create an ordinary version (e.g,
`strchr') as well. If we cannot compute the answer using the
builtin function, we will fall back to the standard library
- version. */
+ version. */
#undef DEF_LIB_BUILTIN
-#define DEF_LIB_BUILTIN(ENUM, NAME, TYPE) \
+#define DEF_LIB_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
- true, true, false)
+ true, true, false, ATTRS)
/* Like DEF_LIB_BUILTIN, except that a call to the builtin should
never fall back to the library version. */
#undef DEF_LIB_ALWAYS_BUILTIN
#define DEF_LIB_ALWAYS_BUILTIN(ENUM, NAME, TYPE) \
DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
- true, false, true)
+ true, false, true, ATTR_CONST_NOTHROW_LIST)
/* Like DEF_LIB_BUILTIN, except that the function is not one that is
specified by ANSI/ISO C. So, when we're being fully conformant we
ignore the version of these builtins that does not begin with
__builtin. */
#undef DEF_EXT_LIB_BUILTIN
-#define DEF_EXT_LIB_BUILTIN(ENUM, NAME, TYPE) \
+#define DEF_EXT_LIB_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
- true, true, true)
+ true, true, true, ATTRS)
/* Like DEF_LIB_BUILTIN, except that the function is only a part of
the standard in C99 or above. */
#undef DEF_C99_BUILTIN
-#define DEF_C99_BUILTIN(ENUM, NAME, TYPE) \
+#define DEF_C99_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
- true, !flag_isoc99, true)
+ true, true, !flag_isoc99, ATTRS)
/* Like DEF_LIB_BUILTIN, except that the function is expanded in the
front-end. */
#undef DEF_FRONT_END_LIB_BUILTIN
-#define DEF_FRONT_END_LIB_BUILTIN(ENUM, NAME, TYPE) \
+#define DEF_FRONT_END_LIB_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
DEF_BUILTIN (ENUM, NAME, BUILT_IN_FRONTEND, TYPE, TYPE, \
- true, true, false)
+ true, true, false, ATTRS)
/* Like DEF_FRONT_END_LIB_BUILTIN, except that the function is not one
that is specified by ANSI/ISO C. So, when we're being fully
conformant we ignore the version of these builtins that does not
begin with __builtin. */
#undef DEF_EXT_FRONT_END_LIB_BUILTIN
-#define DEF_EXT_FRONT_END_LIB_BUILTIN(ENUM, NAME, TYPE) \
+#define DEF_EXT_FRONT_END_LIB_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
DEF_BUILTIN (ENUM, NAME, BUILT_IN_FRONTEND, TYPE, TYPE, \
- true, true, true)
+ true, true, true, ATTRS)
/* A built-in that is not currently used. */
#undef DEF_UNUSED_BUILTIN
#define DEF_UNUSED_BUILTIN(X) \
DEF_BUILTIN (X, (const char *) NULL, NOT_BUILT_IN, BT_LAST, \
- BT_LAST, false, false, false)
+ BT_LAST, false, false, false, ATTR_NOTHROW_LIST)
/* If SMALL_STACK is defined, then `alloca' is only defined in its
`__builtin' form. */
#if SMALL_STACK
DEF_FALLBACK_BUILTIN(BUILT_IN_ALLOCA,
"__builtin_alloca",
- BT_FN_PTR_SIZE)
+ BT_FN_PTR_SIZE,
+ ATTR_MALLOC_NOTHROW_LIST)
#else
DEF_EXT_LIB_BUILTIN(BUILT_IN_ALLOCA,
"__builtin_alloca",
- BT_FN_PTR_SIZE)
+ BT_FN_PTR_SIZE,
+ ATTR_MALLOC_NOTHROW_LIST)
#endif
DEF_LIB_ALWAYS_BUILTIN(BUILT_IN_ABS,
@@ -166,37 +171,48 @@ DEF_LIB_ALWAYS_BUILTIN(BUILT_IN_FABSL,
DEF_C99_BUILTIN(BUILT_IN_LLABS,
"__builtin_llabs",
- BT_FN_LONGLONG_LONGLONG)
+ BT_FN_LONGLONG_LONGLONG,
+ ATTR_NOTHROW_LIST)
DEF_C99_BUILTIN(BUILT_IN_IMAXABS,
"__builtin_imaxabs",
- BT_FN_INTMAX_INTMAX)
+ BT_FN_INTMAX_INTMAX,
+ ATTR_NOTHROW_LIST)
DEF_C99_BUILTIN(BUILT_IN_CONJ,
"__builtin_conj",
- BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE)
+ BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE,
+ ATTR_NOTHROW_LIST)
DEF_C99_BUILTIN(BUILT_IN_CONJF,
"__builtin_conjf",
- BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT)
+ BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT,
+ ATTR_NOTHROW_LIST)
DEF_C99_BUILTIN(BUILT_IN_CONJL,
"__builtin_conjl",
- BT_FN_COMPLEX_LONG_DOUBLE_COMPLEX_LONG_DOUBLE)
+ BT_FN_COMPLEX_LONG_DOUBLE_COMPLEX_LONG_DOUBLE,
+ ATTR_NOTHROW_LIST)
DEF_C99_BUILTIN(BUILT_IN_CREAL,
"__builtin_creal",
- BT_FN_DOUBLE_COMPLEX_DOUBLE)
+ BT_FN_DOUBLE_COMPLEX_DOUBLE,
+ ATTR_NOTHROW_LIST)
DEF_C99_BUILTIN(BUILT_IN_CREALF,
"__builtin_crealf",
- BT_FN_FLOAT_COMPLEX_FLOAT)
+ BT_FN_FLOAT_COMPLEX_FLOAT,
+ ATTR_NOTHROW_LIST)
DEF_C99_BUILTIN(BUILT_IN_CREALL,
"__builtin_creall",
- BT_FN_LONG_DOUBLE_COMPLEX_LONG_DOUBLE)
+ BT_FN_LONG_DOUBLE_COMPLEX_LONG_DOUBLE,
+ ATTR_NOTHROW_LIST)
DEF_C99_BUILTIN(BUILT_IN_CIMAG,
"__builtin_cimag",
- BT_FN_DOUBLE_COMPLEX_DOUBLE)
+ BT_FN_DOUBLE_COMPLEX_DOUBLE,
+ ATTR_NOTHROW_LIST)
DEF_C99_BUILTIN(BUILT_IN_CIMAGF,
"__builtin_cimagf",
- BT_FN_FLOAT_COMPLEX_FLOAT)
+ BT_FN_FLOAT_COMPLEX_FLOAT,
+ ATTR_NOTHROW_LIST)
DEF_C99_BUILTIN(BUILT_IN_CIMAGL,
"__builtin_cimagl",
- BT_FN_LONG_DOUBLE_COMPLEX_LONG_DOUBLE)
+ BT_FN_LONG_DOUBLE_COMPLEX_LONG_DOUBLE,
+ ATTR_NOTHROW_LIST)
DEF_UNUSED_BUILTIN(BUILT_IN_DIV)
DEF_UNUSED_BUILTIN(BUILT_IN_LDIV)
@@ -211,184 +227,383 @@ DEF_UNUSED_BUILTIN(BUILT_IN_FREM)
DEF_BUILTIN (BUILT_IN_BZERO,
"__builtin_bzero",
BUILT_IN_NORMAL,
- BT_FN_VOID_TRAD_PTR_LEN,
+ BT_FN_VOID_PTR_SIZE,
BT_FN_VOID_VAR,
- true, true, true)
+ true, true, true,
+ ATTR_NOTHROW_LIST)
DEF_BUILTIN (BUILT_IN_BCMP,
"__builtin_bcmp",
BUILT_IN_NORMAL,
- BT_FN_INT_TRAD_CONST_PTR_TRAD_CONST_PTR_LEN,
+ BT_FN_INT_CONST_PTR_CONST_PTR_SIZE,
BT_FN_INT_VAR,
- true, true, true)
+ true, true, true,
+ ATTR_PURE_NOTHROW_LIST)
DEF_EXT_LIB_BUILTIN(BUILT_IN_FFS,
"__builtin_ffs",
- BT_FN_INT_INT)
+ BT_FN_INT_INT,
+ ATTR_CONST_NOTHROW_LIST)
DEF_EXT_LIB_BUILTIN(BUILT_IN_INDEX,
"__builtin_index",
- BT_FN_STRING_CONST_STRING_INT)
+ BT_FN_STRING_CONST_STRING_INT,
+ ATTR_PURE_NOTHROW_LIST)
DEF_EXT_LIB_BUILTIN(BUILT_IN_RINDEX,
"__builtin_rindex",
- BT_FN_STRING_CONST_STRING_INT)
+ BT_FN_STRING_CONST_STRING_INT,
+ ATTR_PURE_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_MEMCPY,
"__builtin_memcpy",
- BT_FN_TRAD_PTR_PTR_CONST_PTR_SIZE)
+ BT_FN_PTR_PTR_CONST_PTR_SIZE,
+ ATTR_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_MEMCMP,
"__builtin_memcmp",
- BT_FN_INT_CONST_PTR_CONST_PTR_SIZE)
+ BT_FN_INT_CONST_PTR_CONST_PTR_SIZE,
+ ATTR_PURE_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_MEMSET,
"__builtin_memset",
- BT_FN_TRAD_PTR_PTR_INT_SIZE)
+ BT_FN_PTR_PTR_INT_SIZE,
+ ATTR_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRCAT,
"__builtin_strcat",
- BT_FN_STRING_STRING_CONST_STRING)
+ BT_FN_STRING_STRING_CONST_STRING,
+ ATTR_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRNCAT,
"__builtin_strncat",
- BT_FN_STRING_STRING_CONST_STRING_SIZE)
+ BT_FN_STRING_STRING_CONST_STRING_SIZE,
+ ATTR_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRCPY,
"__builtin_strcpy",
- BT_FN_STRING_STRING_CONST_STRING)
+ BT_FN_STRING_STRING_CONST_STRING,
+ ATTR_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRNCPY,
"__builtin_strncpy",
- BT_FN_STRING_STRING_CONST_STRING_SIZE)
+ BT_FN_STRING_STRING_CONST_STRING_SIZE,
+ ATTR_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRCMP,
"__builtin_strcmp",
- BT_FN_INT_CONST_STRING_CONST_STRING)
+ BT_FN_INT_CONST_STRING_CONST_STRING,
+ ATTR_PURE_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRNCMP,
"__builtin_strncmp",
- BT_FN_INT_CONST_STRING_CONST_STRING_SIZE)
+ BT_FN_INT_CONST_STRING_CONST_STRING_SIZE,
+ ATTR_PURE_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRLEN,
"__builtin_strlen",
- BT_FN_LEN_CONST_STRING)
+ BT_FN_SIZE_CONST_STRING,
+ ATTR_PURE_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRSTR,
"__builtin_strstr",
- BT_FN_STRING_CONST_STRING_CONST_STRING)
+ BT_FN_STRING_CONST_STRING_CONST_STRING,
+ ATTR_PURE_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRPBRK,
"__builtin_strpbrk",
- BT_FN_STRING_CONST_STRING_CONST_STRING)
+ BT_FN_STRING_CONST_STRING_CONST_STRING,
+ ATTR_PURE_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRSPN,
"__builtin_strspn",
- BT_FN_SIZE_CONST_STRING_CONST_STRING)
+ BT_FN_SIZE_CONST_STRING_CONST_STRING,
+ ATTR_PURE_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRCSPN,
"__builtin_strcspn",
- BT_FN_SIZE_CONST_STRING_CONST_STRING)
+ BT_FN_SIZE_CONST_STRING_CONST_STRING,
+ ATTR_PURE_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRCHR,
"__builtin_strchr",
- BT_FN_STRING_CONST_STRING_INT)
+ BT_FN_STRING_CONST_STRING_INT,
+ ATTR_PURE_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_STRRCHR,
"__builtin_strrchr",
- BT_FN_STRING_CONST_STRING_INT)
+ BT_FN_STRING_CONST_STRING_INT,
+ ATTR_PURE_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_SQRT,
"__builtin_sqrt",
- BT_FN_DOUBLE_DOUBLE)
+ BT_FN_DOUBLE_DOUBLE,
+ flag_errno_math ? ATTR_NOTHROW_LIST
+ : (flag_unsafe_math_optimizations
+ ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST))
DEF_LIB_BUILTIN(BUILT_IN_SIN,
"__builtin_sin",
- BT_FN_DOUBLE_DOUBLE)
+ BT_FN_DOUBLE_DOUBLE,
+ flag_unsafe_math_optimizations ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_COS,
"__builtin_cos",
- BT_FN_DOUBLE_DOUBLE)
+ BT_FN_DOUBLE_DOUBLE,
+ flag_unsafe_math_optimizations ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST)
+DEF_LIB_BUILTIN(BUILT_IN_EXP,
+ "__builtin_exp",
+ BT_FN_DOUBLE_DOUBLE,
+ flag_errno_math ? ATTR_NOTHROW_LIST
+ : (flag_unsafe_math_optimizations
+ ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST))
+DEF_LIB_BUILTIN(BUILT_IN_LOG,
+ "__builtin_log",
+ BT_FN_DOUBLE_DOUBLE,
+ flag_errno_math ? ATTR_NOTHROW_LIST
+ : (flag_unsafe_math_optimizations
+ ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST))
DEF_LIB_BUILTIN(BUILT_IN_SQRTF,
"__builtin_sqrtf",
- BT_FN_FLOAT_FLOAT)
+ BT_FN_FLOAT_FLOAT,
+ flag_errno_math ? ATTR_NOTHROW_LIST
+ : (flag_unsafe_math_optimizations
+ ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST))
DEF_LIB_BUILTIN(BUILT_IN_SINF,
"__builtin_sinf",
- BT_FN_FLOAT_FLOAT)
+ BT_FN_FLOAT_FLOAT,
+ flag_unsafe_math_optimizations ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_COSF,
"__builtin_cosf",
- BT_FN_FLOAT_FLOAT)
+ BT_FN_FLOAT_FLOAT,
+ flag_unsafe_math_optimizations ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST)
+DEF_LIB_BUILTIN(BUILT_IN_EXPF,
+ "__builtin_expf",
+ BT_FN_FLOAT_FLOAT,
+ flag_errno_math ? ATTR_NOTHROW_LIST
+ : (flag_unsafe_math_optimizations
+ ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST))
+DEF_LIB_BUILTIN(BUILT_IN_LOGF,
+ "__builtin_logf",
+ BT_FN_FLOAT_FLOAT,
+ flag_errno_math ? ATTR_NOTHROW_LIST
+ : (flag_unsafe_math_optimizations
+ ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST))
DEF_LIB_BUILTIN(BUILT_IN_SQRTL,
"__builtin_sqrtl",
- BT_FN_LONG_DOUBLE_LONG_DOUBLE)
+ BT_FN_LONG_DOUBLE_LONG_DOUBLE,
+ flag_errno_math ? ATTR_NOTHROW_LIST
+ : (flag_unsafe_math_optimizations
+ ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST))
DEF_LIB_BUILTIN(BUILT_IN_SINL,
"__builtin_sinl",
- BT_FN_LONG_DOUBLE_LONG_DOUBLE)
+ BT_FN_LONG_DOUBLE_LONG_DOUBLE,
+ flag_unsafe_math_optimizations ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST)
DEF_LIB_BUILTIN(BUILT_IN_COSL,
"__builtin_cosl",
- BT_FN_LONG_DOUBLE_LONG_DOUBLE)
-
-DEF_UNUSED_BUILTIN(BUILT_IN_GETEXP)
-DEF_UNUSED_BUILTIN(BUILT_IN_GETMAN)
+ BT_FN_LONG_DOUBLE_LONG_DOUBLE,
+ flag_unsafe_math_optimizations ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST)
+DEF_LIB_BUILTIN(BUILT_IN_EXPL,
+ "__builtin_expl",
+ BT_FN_LONG_DOUBLE_LONG_DOUBLE,
+ flag_errno_math ? ATTR_NOTHROW_LIST
+ : (flag_unsafe_math_optimizations
+ ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST))
+DEF_LIB_BUILTIN(BUILT_IN_LOGL,
+ "__builtin_logl",
+ BT_FN_LONG_DOUBLE_LONG_DOUBLE,
+ flag_errno_math ? ATTR_NOTHROW_LIST
+ : (flag_unsafe_math_optimizations
+ ? ATTR_CONST_NOTHROW_LIST
+ : ATTR_PURE_NOTHROW_LIST))
+
+DEF_GCC_BUILTIN(BUILT_IN_INF,
+ "__builtin_inf",
+ BT_FN_DOUBLE,
+ ATTR_CONST_NOTHROW_LIST)
+DEF_GCC_BUILTIN(BUILT_IN_INFF,
+ "__builtin_inff",
+ BT_FN_FLOAT,
+ ATTR_CONST_NOTHROW_LIST)
+DEF_GCC_BUILTIN(BUILT_IN_INFL,
+ "__builtin_infl",
+ BT_FN_LONG_DOUBLE,
+ ATTR_CONST_NOTHROW_LIST)
+
+DEF_GCC_BUILTIN(BUILT_IN_HUGE_VAL,
+ "__builtin_huge_val",
+ BT_FN_DOUBLE,
+ ATTR_CONST_NOTHROW_LIST)
+DEF_GCC_BUILTIN(BUILT_IN_HUGE_VALF,
+ "__builtin_huge_valf",
+ BT_FN_FLOAT,
+ ATTR_CONST_NOTHROW_LIST)
+DEF_GCC_BUILTIN(BUILT_IN_HUGE_VALL,
+ "__builtin_huge_vall",
+ BT_FN_LONG_DOUBLE,
+ ATTR_CONST_NOTHROW_LIST)
+
+DEF_LIB_BUILTIN(BUILT_IN_NAN,
+ "__builtin_nan",
+ BT_FN_DOUBLE_CONST_STRING,
+ ATTR_CONST_NOTHROW_LIST)
+DEF_LIB_BUILTIN(BUILT_IN_NANF,
+ "__builtin_nanf",
+ BT_FN_FLOAT_CONST_STRING,
+ ATTR_CONST_NOTHROW_LIST)
+DEF_LIB_BUILTIN(BUILT_IN_NANL,
+ "__builtin_nanl",
+ BT_FN_LONG_DOUBLE_CONST_STRING,
+ ATTR_CONST_NOTHROW_LIST)
+
+DEF_LIB_BUILTIN(BUILT_IN_NANS,
+ "__builtin_nans",
+ BT_FN_DOUBLE_CONST_STRING,
+ ATTR_CONST_NOTHROW_LIST)
+DEF_LIB_BUILTIN(BUILT_IN_NANSF,
+ "__builtin_nansf",
+ BT_FN_FLOAT_CONST_STRING,
+ ATTR_CONST_NOTHROW_LIST)
+DEF_LIB_BUILTIN(BUILT_IN_NANSL,
+ "__builtin_nansl",
+ BT_FN_LONG_DOUBLE_CONST_STRING,
+ ATTR_CONST_NOTHROW_LIST)
DEF_GCC_BUILTIN(BUILT_IN_SAVEREGS,
"__builtin_saveregs",
- BT_FN_PTR_VAR)
+ BT_FN_PTR_VAR,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_CLASSIFY_TYPE,
"__builtin_classify_type",
- BT_FN_INT_VAR)
+ BT_FN_INT_VAR,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_NEXT_ARG,
"__builtin_next_arg",
- BT_FN_PTR_VAR)
+ BT_FN_PTR_VAR,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_ARGS_INFO,
"__builtin_args_info",
- BT_FN_INT_INT)
+ BT_FN_INT_INT,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_CONSTANT_P,
"__builtin_constant_p",
- BT_FN_INT_VAR)
+ BT_FN_INT_VAR,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_FRAME_ADDRESS,
"__builtin_frame_address",
- BT_FN_PTR_UNSIGNED)
+ BT_FN_PTR_UNSIGNED,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_RETURN_ADDRESS,
"__builtin_return_address",
- BT_FN_PTR_UNSIGNED)
+ BT_FN_PTR_UNSIGNED,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_AGGREGATE_INCOMING_ADDRESS,
"__builtin_aggregate_incoming_address",
- BT_FN_PTR_VAR)
+ BT_FN_PTR_VAR,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_APPLY_ARGS,
"__builtin_apply_args",
- BT_FN_PTR_VAR)
+ BT_FN_PTR_VAR,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_APPLY,
"__builtin_apply",
- BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE)
+ BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_RETURN,
"__builtin_return",
- BT_FN_VOID_PTR)
+ BT_FN_VOID_PTR,
+ ATTR_NORETURN_NOTHROW_LIST)
DEF_GCC_BUILTIN(BUILT_IN_SETJMP,
"__builtin_setjmp",
- BT_FN_INT_PTR)
+ BT_FN_INT_PTR,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_LONGJMP,
"__builtin_longjmp",
- BT_FN_VOID_PTR_INT)
+ BT_FN_VOID_PTR_INT,
+ ATTR_NORETURN_NOTHROW_LIST)
DEF_GCC_BUILTIN(BUILT_IN_TRAP,
"__builtin_trap",
- BT_FN_VOID)
+ BT_FN_VOID,
+ ATTR_NORETURN_NOTHROW_LIST)
DEF_GCC_BUILTIN(BUILT_IN_PREFETCH,
"__builtin_prefetch",
- BT_FN_VOID_CONST_PTR_VAR)
-
-/* Stdio builtins. */
-DEF_FALLBACK_BUILTIN(BUILT_IN_PUTCHAR,
- "__builtin_putchar",
- BT_FN_INT_INT)
-DEF_FALLBACK_BUILTIN(BUILT_IN_PUTS,
- "__builtin_puts",
- BT_FN_INT_CONST_STRING)
+ BT_FN_VOID_CONST_PTR_VAR,
+ ATTR_NULL)
+
+/* stdio.h builtins (without FILE *). */
+
DEF_FRONT_END_LIB_BUILTIN(BUILT_IN_PRINTF,
"__builtin_printf",
- BT_FN_INT_CONST_STRING_VAR)
-DEF_FALLBACK_BUILTIN(BUILT_IN_FPUTC,
- "__builtin_fputc",
- BT_FN_INT_INT_PTR)
+ BT_FN_INT_CONST_STRING_VAR,
+ ATTR_FORMAT_PRINTF_1_2)
+DEF_LIB_BUILTIN(BUILT_IN_PUTCHAR,
+ "__builtin_putchar",
+ BT_FN_INT_INT,
+ ATTR_NOTHROW_LIST)
+DEF_LIB_BUILTIN(BUILT_IN_PUTS,
+ "__builtin_puts",
+ BT_FN_INT_CONST_STRING,
+ ATTR_NOTHROW_LIST)
+DEF_C99_BUILTIN(BUILT_IN_SNPRINTF,
+ "__builtin_snprintf",
+ BT_FN_INT_STRING_SIZE_CONST_STRING_VAR,
+ ATTR_FORMAT_PRINTF_3_4)
+DEF_LIB_BUILTIN(BUILT_IN_SPRINTF,
+ "__builtin_sprintf",
+ BT_FN_INT_STRING_CONST_STRING_VAR,
+ ATTR_FORMAT_PRINTF_2_3)
+DEF_LIB_BUILTIN(BUILT_IN_SCANF,
+ "__builtin_scanf",
+ BT_FN_INT_CONST_STRING_VAR,
+ ATTR_FORMAT_SCANF_1_2)
+DEF_LIB_BUILTIN(BUILT_IN_SSCANF,
+ "__builtin_sscanf",
+ BT_FN_INT_CONST_STRING_CONST_STRING_VAR,
+ ATTR_FORMAT_SCANF_2_3)
+DEF_LIB_BUILTIN(BUILT_IN_VPRINTF,
+ "__builtin_vprintf",
+ BT_FN_INT_CONST_STRING_VALIST_ARG,
+ ATTR_FORMAT_PRINTF_1_0)
+DEF_C99_BUILTIN(BUILT_IN_VSCANF,
+ "__builtin_vscanf",
+ BT_FN_INT_CONST_STRING_VALIST_ARG,
+ ATTR_FORMAT_SCANF_1_0)
+DEF_C99_BUILTIN(BUILT_IN_VSSCANF,
+ "__builtin_vsscanf",
+ BT_FN_INT_CONST_STRING_CONST_STRING_VALIST_ARG,
+ ATTR_FORMAT_SCANF_2_0)
+DEF_C99_BUILTIN(BUILT_IN_VSNPRINTF,
+ "__builtin_vsnprintf",
+ BT_FN_INT_STRING_SIZE_CONST_STRING_VALIST_ARG,
+ ATTR_FORMAT_PRINTF_3_0)
+DEF_LIB_BUILTIN(BUILT_IN_VSPRINTF,
+ "__builtin_vsprintf",
+ BT_FN_INT_STRING_CONST_STRING_VALIST_ARG,
+ ATTR_FORMAT_PRINTF_2_0)
+
+
+/* stdio.h builtins (with FILE *). */
+
/* Declare the __builtin_ style with arguments and the regular style
without them. We rely on stdio.h to supply the arguments for the
regular style declaration since we had to use void* instead of
FILE* in the __builtin_ prototype supplied here. */
+
+DEF_FALLBACK_BUILTIN(BUILT_IN_FPUTC,
+ "__builtin_fputc",
+ BT_FN_INT_INT_PTR,
+ ATTR_NOTHROW_LIST)
DEF_BUILTIN (BUILT_IN_FPUTS,
"__builtin_fputs",
BUILT_IN_NORMAL,
BT_FN_INT_CONST_STRING_PTR,
BT_FN_INT_VAR,
- true, true, false)
+ true, true, false, ATTR_NOTHROW_LIST)
DEF_FALLBACK_BUILTIN(BUILT_IN_FWRITE,
"__builtin_fwrite",
- BT_FN_SIZE_CONST_PTR_SIZE_SIZE_PTR)
+ BT_FN_SIZE_CONST_PTR_SIZE_SIZE_PTR,
+ ATTR_NOTHROW_LIST)
DEF_FRONT_END_LIB_BUILTIN(BUILT_IN_FPRINTF,
"__builtin_fprintf",
- BT_FN_INT_PTR_CONST_STRING_VAR)
+ BT_FN_INT_PTR_CONST_STRING_VAR,
+ ATTR_FORMAT_PRINTF_2_3)
-/* Stdio unlocked builtins. */
+/* stdio unlocked builtins (without FILE *). */
DEF_EXT_FALLBACK_BUILTIN(BUILT_IN_PUTCHAR_UNLOCKED,
"__builtin_putchar_unlocked",
@@ -398,91 +613,152 @@ DEF_EXT_FALLBACK_BUILTIN(BUILT_IN_PUTS_UNLOCKED,
BT_FN_INT_CONST_STRING)
DEF_EXT_FRONT_END_LIB_BUILTIN(BUILT_IN_PRINTF_UNLOCKED,
"__builtin_printf_unlocked",
- BT_FN_INT_CONST_STRING_VAR)
-DEF_EXT_FALLBACK_BUILTIN(BUILT_IN_FPUTC_UNLOCKED,
- "__builtin_fputc_unlocked",
- BT_FN_INT_INT_PTR)
+ BT_FN_INT_CONST_STRING_VAR,
+ ATTR_FORMAT_PRINTF_1_2)
+
+/* stdio unlocked builtins (with FILE *). */
+
/* Declare the __builtin_ style with arguments and the regular style
without them. We rely on stdio.h to supply the arguments for the
regular style declaration since we had to use void* instead of
FILE* in the __builtin_ prototype supplied here. */
+
+DEF_EXT_FALLBACK_BUILTIN(BUILT_IN_FPUTC_UNLOCKED,
+ "__builtin_fputc_unlocked",
+ BT_FN_INT_INT_PTR)
DEF_BUILTIN (BUILT_IN_FPUTS_UNLOCKED,
"__builtin_fputs_unlocked",
BUILT_IN_NORMAL,
BT_FN_INT_CONST_STRING_PTR,
BT_FN_INT_VAR,
- true, true, true)
+ true, true, true, ATTR_NOTHROW_LIST)
DEF_EXT_FALLBACK_BUILTIN(BUILT_IN_FWRITE_UNLOCKED,
"__builtin_fwrite_unlocked",
BT_FN_SIZE_CONST_PTR_SIZE_SIZE_PTR)
DEF_EXT_FRONT_END_LIB_BUILTIN(BUILT_IN_FPRINTF_UNLOCKED,
"__builtin_fprintf_unlocked",
- BT_FN_INT_PTR_CONST_STRING_VAR)
+ BT_FN_INT_PTR_CONST_STRING_VAR,
+ ATTR_FORMAT_PRINTF_2_3)
/* ISO C99 floating point unordered comparisons. */
DEF_GCC_BUILTIN(BUILT_IN_ISGREATER,
"__builtin_isgreater",
- BT_FN_INT_VAR)
+ BT_FN_INT_VAR,
+ ATTR_CONST_NOTHROW_LIST)
DEF_GCC_BUILTIN(BUILT_IN_ISGREATEREQUAL,
"__builtin_isgreaterequal",
- BT_FN_INT_VAR)
+ BT_FN_INT_VAR,
+ ATTR_CONST_NOTHROW_LIST)
DEF_GCC_BUILTIN(BUILT_IN_ISLESS,
"__builtin_isless",
- BT_FN_INT_VAR)
+ BT_FN_INT_VAR,
+ ATTR_CONST_NOTHROW_LIST)
DEF_GCC_BUILTIN(BUILT_IN_ISLESSEQUAL,
"__builtin_islessequal",
- BT_FN_INT_VAR)
+ BT_FN_INT_VAR,
+ ATTR_CONST_NOTHROW_LIST)
DEF_GCC_BUILTIN(BUILT_IN_ISLESSGREATER,
"__builtin_islessgreater",
- BT_FN_INT_VAR)
+ BT_FN_INT_VAR,
+ ATTR_CONST_NOTHROW_LIST)
DEF_GCC_BUILTIN(BUILT_IN_ISUNORDERED,
"__builtin_isunordered",
- BT_FN_INT_VAR)
+ BT_FN_INT_VAR,
+ ATTR_CONST_NOTHROW_LIST)
/* Various hooks for the DWARF 2 __throw routine. */
DEF_GCC_BUILTIN(BUILT_IN_UNWIND_INIT,
"__builtin_unwind_init",
- BT_FN_VOID)
+ BT_FN_VOID,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_DWARF_CFA,
"__builtin_dwarf_cfa",
- BT_FN_PTR)
-DEF_GCC_BUILTIN(BUILT_IN_DWARF_FP_REGNUM,
- "__builtin_dwarf_fp_regnum",
- BT_FN_UNSIGNED)
+ BT_FN_PTR,
+ ATTR_NULL)
+DEF_GCC_BUILTIN(BUILT_IN_DWARF_SP_COLUMN,
+ "__builtin_dwarf_sp_column",
+ BT_FN_UNSIGNED,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_INIT_DWARF_REG_SIZES,
"__builtin_init_dwarf_reg_size_table",
- BT_FN_VOID_PTR)
+ BT_FN_VOID_PTR,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_FROB_RETURN_ADDR,
"__builtin_frob_return_addr",
- BT_FN_PTR_PTR)
+ BT_FN_PTR_PTR,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_EXTRACT_RETURN_ADDR,
"__builtin_extract_return_addr",
- BT_FN_PTR_PTR)
+ BT_FN_PTR_PTR,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_EH_RETURN,
"__builtin_eh_return",
- BT_FN_VOID_PTRMODE_PTR)
+ BT_FN_VOID_PTRMODE_PTR,
+ ATTR_NORETURN_NOTHROW_LIST)
DEF_GCC_BUILTIN(BUILT_IN_EH_RETURN_DATA_REGNO,
"__builtin_eh_return_data_regno",
- BT_FN_INT_INT)
-
-DEF_GCC_BUILTIN(BUILT_IN_VARARGS_START,
- "__builtin_varargs_start",
- BT_FN_VOID_VALIST_REF)
-DEF_GCC_BUILTIN(BUILT_IN_STDARG_START,
+ BT_FN_INT_INT,
+ ATTR_NULL)
+
+/* Variable argument list (stdarg.h) support */
+DEF_GCC_BUILTIN(BUILT_IN_VA_START,
+ "__builtin_va_start",
+ BT_FN_VOID_VALIST_REF_VAR,
+ ATTR_NULL)
+DEF_GCC_BUILTIN(BUILT_IN_STDARG_START, /* backward compat */
"__builtin_stdarg_start",
- BT_FN_VOID_VALIST_REF_VAR)
+ BT_FN_VOID_VALIST_REF_VAR,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_VA_END,
"__builtin_va_end",
- BT_FN_VOID_VALIST_REF)
+ BT_FN_VOID_VALIST_REF,
+ ATTR_NULL)
DEF_GCC_BUILTIN(BUILT_IN_VA_COPY,
"__builtin_va_copy",
- BT_FN_VOID_VALIST_REF_VALIST_ARG)
+ BT_FN_VOID_VALIST_REF_VALIST_ARG,
+ ATTR_NULL)
+
DEF_GCC_BUILTIN(BUILT_IN_EXPECT,
"__builtin_expect",
- BT_FN_LONG_LONG_LONG)
+ BT_FN_LONG_LONG_LONG,
+ ATTR_NULL)
/* C++ extensions */
DEF_UNUSED_BUILTIN(BUILT_IN_NEW)
DEF_UNUSED_BUILTIN(BUILT_IN_VEC_NEW)
DEF_UNUSED_BUILTIN(BUILT_IN_DELETE)
DEF_UNUSED_BUILTIN(BUILT_IN_VEC_DELETE)
+
+/* Declare abort, exit, _exit and _Exit */
+DEF_BUILTIN (BUILT_IN_ABORT,
+ "__builtin_abort",
+ NOT_BUILT_IN,
+ BT_FN_VOID,
+ BT_FN_VOID,
+ 1, 0, 0,
+ ATTR_NORETURN_NOTHROW_LIST)
+
+DEF_BUILTIN (BUILT_IN_EXIT,
+ "__builtin_exit",
+ NOT_BUILT_IN,
+ BT_FN_VOID_INT,
+ BT_FN_VOID_INT,
+ 1, 0, 0,
+ ATTR_NORETURN_NOTHROW_LIST)
+
+DEF_BUILTIN (BUILT_IN__EXIT,
+ "__builtin__exit",
+ NOT_BUILT_IN,
+ BT_FN_VOID_INT,
+ BT_FN_VOID_INT,
+ 1, 0, 1,
+ ATTR_NORETURN_NOTHROW_LIST)
+
+DEF_BUILTIN (BUILT_IN__EXIT2,
+ "__builtin__Exit",
+ NOT_BUILT_IN,
+ BT_FN_VOID_INT,
+ BT_FN_VOID_INT,
+ 1, 0, !flag_isoc99,
+ ATTR_NORETURN_NOTHROW_LIST)
+
diff --git a/contrib/gcc/c-aux-info.c b/contrib/gcc/c-aux-info.c
index 67ecae6..761fa84 100644
--- a/contrib/gcc/c-aux-info.c
+++ b/contrib/gcc/c-aux-info.c
@@ -188,7 +188,7 @@ gen_formal_list_for_type (fntype, style)
/* For the generation of an ANSI prototype for a function definition, we have
to look at the formal parameter list of the function's own "type" to
determine if the function's formal parameter list should end with an
- ellipsis. Given a tree node, the following function will return non-zero
+ ellipsis. Given a tree node, the following function will return nonzero
if the "function type" parameter list should end with an ellipsis. */
static int
@@ -471,7 +471,7 @@ gen_type (ret_val, t, style)
The given entity may be either a variable or a function.
- If the "is_func_definition" parameter is non-zero, assume that the thing
+ If the "is_func_definition" parameter is nonzero, assume that the thing
we are generating a declaration for is a FUNCTION_DECL node which is
associated with a function definition. In this case, we can assume that
an attached list of DECL nodes for function formal arguments is present. */
diff --git a/contrib/gcc/c-common.c b/contrib/gcc/c-common.c
index 3511f15..b40a35a 100644
--- a/contrib/gcc/c-common.c
+++ b/contrib/gcc/c-common.c
@@ -22,6 +22,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
#include "tree.h"
+#include "real.h"
#include "flags.h"
#include "toplev.h"
#include "output.h"
@@ -30,17 +31,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ggc.h"
#include "expr.h"
#include "c-common.h"
-#include "tree-inline.h"
#include "diagnostic.h"
#include "tm_p.h"
#include "obstack.h"
-#include "c-lex.h"
#include "cpplib.h"
#include "target.h"
-cpp_reader *parse_in; /* Declared in c-lex.h. */
+#include "langhooks.h"
+#include "except.h" /* For USING_SJLJ_EXCEPTIONS. */
+#include "tree-inline.h"
+#include "c-tree.h"
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE TYPE_PRECISION (wchar_type_node)
+cpp_reader *parse_in; /* Declared in c-pragma.h. */
/* We let tm.h override the types used here, to handle trivial differences
such as the choice of unsigned int or long unsigned int for size_t.
@@ -56,6 +57,10 @@ cpp_reader *parse_in; /* Declared in c-lex.h. */
#define WCHAR_TYPE "int"
#endif
+/* WCHAR_TYPE gets overridden by -fshort-wchar. */
+#define MODIFIED_WCHAR_TYPE \
+ (flag_short_wchar ? "short unsigned int" : WCHAR_TYPE)
+
#ifndef PTRDIFF_TYPE
#define PTRDIFF_TYPE "long int"
#endif
@@ -80,6 +85,10 @@ cpp_reader *parse_in; /* Declared in c-lex.h. */
: "long long unsigned int"))
#endif
+#ifndef REGISTER_PREFIX
+#define REGISTER_PREFIX ""
+#endif
+
/* The variant of the C language being processed. */
enum c_language_kind c_language;
@@ -180,6 +189,22 @@ enum c_language_kind c_language;
tree c_global_trees[CTI_MAX];
+/* Switches common to the C front ends. */
+
+/* Nonzero if prepreprocessing only. */
+int flag_preprocess_only;
+
+/* Nonzero if an ISO standard was selected. It rejects macros in the
+ user's namespace. */
+int flag_iso;
+
+/* Nonzero whenever Objective-C functionality is being used. */
+int flag_objc;
+
+/* Nonzero if -undef was given. It suppresses target built-in macros
+ and assertions. */
+int flag_undef;
+
/* Nonzero means don't recognize the non-ANSI builtin functions. */
int flag_no_builtin;
@@ -197,6 +222,180 @@ int flag_short_double;
int flag_short_wchar;
+/* Nonzero means allow Microsoft extensions without warnings or errors. */
+int flag_ms_extensions;
+
+/* Nonzero means don't recognize the keyword `asm'. */
+
+int flag_no_asm;
+
+/* Nonzero means give string constants the type `const char *', as mandated
+ by the standard. */
+
+int flag_const_strings;
+
+/* Nonzero means `$' can be in an identifier. */
+
+#ifndef DOLLARS_IN_IDENTIFIERS
+#define DOLLARS_IN_IDENTIFIERS 1
+#endif
+int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
+
+/* Nonzero means to treat bitfields as signed unless they say `unsigned'. */
+
+int flag_signed_bitfields = 1;
+int explicit_flag_signed_bitfields;
+
+/* Nonzero means warn about pointer casts that can drop a type qualifier
+ from the pointer target type. */
+
+int warn_cast_qual;
+
+/* Warn about functions which might be candidates for format attributes. */
+
+int warn_missing_format_attribute;
+
+/* Nonzero means warn about sizeof(function) or addition/subtraction
+ of function pointers. */
+
+int warn_pointer_arith;
+
+/* Nonzero means warn for any global function def
+ without separate previous prototype decl. */
+
+int warn_missing_prototypes;
+
+/* Warn if adding () is suggested. */
+
+int warn_parentheses;
+
+/* Warn if initializer is not completely bracketed. */
+
+int warn_missing_braces;
+
+/* Warn about comparison of signed and unsigned values.
+ If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified. */
+
+int warn_sign_compare;
+
+/* Nonzero means warn about usage of long long when `-pedantic'. */
+
+int warn_long_long = 1;
+
+/* Nonzero means warn about deprecated conversion from string constant to
+ `char *'. */
+
+int warn_write_strings;
+
+/* Nonzero means warn about multiple (redundant) decls for the same single
+ variable or function. */
+
+int warn_redundant_decls;
+
+/* Warn about testing equality of floating point numbers. */
+
+int warn_float_equal;
+
+/* Warn about a subscript that has type char. */
+
+int warn_char_subscripts;
+
+/* Warn if a type conversion is done that might have confusing results. */
+
+int warn_conversion;
+
+/* Warn about #pragma directives that are not recognized. */
+
+int warn_unknown_pragmas; /* Tri state variable. */
+
+/* Warn about format/argument anomalies in calls to formatted I/O functions
+ (*printf, *scanf, strftime, strfmon, etc.). */
+
+int warn_format;
+
+/* Warn about Y2K problems with strftime formats. */
+
+int warn_format_y2k;
+
+/* Warn about excess arguments to formats. */
+
+int warn_format_extra_args;
+
+/* Warn about zero-length formats. */
+
+int warn_format_zero_length;
+
+/* Warn about non-literal format arguments. */
+
+int warn_format_nonliteral;
+
+/* Warn about possible security problems with calls to format functions. */
+
+int warn_format_security;
+
+
+/* C/ObjC language option variables. */
+
+
+/* Nonzero means message about use of implicit function declarations;
+ 1 means warning; 2 means error. */
+
+int mesg_implicit_function_declaration = -1;
+
+/* Nonzero means allow type mismatches in conditional expressions;
+ just make their values `void'. */
+
+int flag_cond_mismatch;
+
+/* Nonzero means enable C89 Amendment 1 features. */
+
+int flag_isoc94;
+
+/* Nonzero means use the ISO C99 dialect of C. */
+
+int flag_isoc99;
+
+/* Nonzero means that we have builtin functions, and main is an int */
+
+int flag_hosted = 1;
+
+/* Nonzero means add default format_arg attributes for functions not
+ in ISO C. */
+
+int flag_noniso_default_format_attributes = 1;
+
+/* Nonzero means warn when casting a function call to a type that does
+ not match the return type (e.g. (float)sqrt() or (anything*)malloc()
+ when there is no previous declaration of sqrt or malloc. */
+
+int warn_bad_function_cast;
+
+/* Warn about traditional constructs whose meanings changed in ANSI C. */
+
+int warn_traditional;
+
+/* Nonzero means warn for non-prototype function decls
+ or non-prototyped defs without previous prototype. */
+
+int warn_strict_prototypes;
+
+/* Nonzero means warn for any global function def
+ without separate previous decl. */
+
+int warn_missing_declarations;
+
+/* Nonzero means warn about declarations of objects not at
+ file-scope level and about *all* declarations of functions (whether
+ or static) not at file-scope level. Note that we exclude
+ implicit function declarations. To get warnings about those, use
+ -Wimplicit. */
+
+int warn_nested_externs;
+
+/* Warn if main is suspicious. */
+
+int warn_main;
+
/* Nonzero means warn about possible violations of sequence point rules. */
int warn_sequence_point;
@@ -204,6 +403,254 @@ int warn_sequence_point;
/* Nonzero means to warn about compile-time division by zero. */
int warn_div_by_zero = 1;
+/* Nonzero means warn about use of implicit int. */
+
+int warn_implicit_int;
+
+/* Warn about NULL being passed to argument slots marked as requiring
+ non-NULL. */
+
+int warn_nonnull;
+
+
+/* ObjC language option variables. */
+
+
+/* Open and close the file for outputting class declarations, if
+ requested (ObjC). */
+
+int flag_gen_declaration;
+
+/* Generate code for GNU or NeXT runtime environment. */
+
+#ifdef NEXT_OBJC_RUNTIME
+int flag_next_runtime = 1;
+#else
+int flag_next_runtime = 0;
+#endif
+
+/* Tells the compiler that this is a special run. Do not perform any
+ compiling, instead we are to test some platform dependent features
+ and output a C header file with appropriate definitions. */
+
+int print_struct_values;
+
+/* ???. Undocumented. */
+
+const char *constant_string_class_name;
+
+/* Warn if multiple methods are seen for the same selector, but with
+ different argument types. Performs the check on the whole selector
+ table at the end of compilation. */
+
+int warn_selector;
+
+/* Warn if a @selector() is found, and no method with that selector
+ has been previously declared. The check is done on each
+ @selector() as soon as it is found - so it warns about forward
+ declarations. */
+
+int warn_undeclared_selector;
+
+/* Warn if methods required by a protocol are not implemented in the
+ class adopting it. When turned off, methods inherited to that
+ class are also considered implemented. */
+
+int warn_protocol = 1;
+
+
+/* C++ language option variables. */
+
+
+/* Nonzero means don't recognize any extension keywords. */
+
+int flag_no_gnu_keywords;
+
+/* Nonzero means do emit exported implementations of functions even if
+ they can be inlined. */
+
+int flag_implement_inlines = 1;
+
+/* Nonzero means do emit exported implementations of templates, instead of
+ multiple static copies in each file that needs a definition. */
+
+int flag_external_templates;
+
+/* Nonzero means that the decision to emit or not emit the implementation of a
+ template depends on where the template is instantiated, rather than where
+ it is defined. */
+
+int flag_alt_external_templates;
+
+/* Nonzero means that implicit instantiations will be emitted if needed. */
+
+int flag_implicit_templates = 1;
+
+/* Nonzero means that implicit instantiations of inline templates will be
+ emitted if needed, even if instantiations of non-inline templates
+ aren't. */
+
+int flag_implicit_inline_templates = 1;
+
+/* Nonzero means generate separate instantiation control files and
+ juggle them at link time. */
+
+int flag_use_repository;
+
+/* Nonzero if we want to issue diagnostics that the standard says are not
+ required. */
+
+int flag_optional_diags = 1;
+
+/* Nonzero means we should attempt to elide constructors when possible. */
+
+int flag_elide_constructors = 1;
+
+/* Nonzero means that member functions defined in class scope are
+ inline by default. */
+
+int flag_default_inline = 1;
+
+/* Controls whether compiler generates 'type descriptor' that give
+ run-time type information. */
+
+int flag_rtti = 1;
+
+/* Nonzero if we want to conserve space in the .o files. We do this
+ by putting uninitialized data and runtime initialized data into
+ .common instead of .data at the expense of not flagging multiple
+ definitions. */
+
+int flag_conserve_space;
+
+/* Nonzero if we want to obey access control semantics. */
+
+int flag_access_control = 1;
+
+/* Nonzero if we want to check the return value of new and avoid calling
+ constructors if it is a null pointer. */
+
+int flag_check_new;
+
+/* Nonzero if we want the new ISO rules for pushing a new scope for `for'
+ initialization variables.
+ 0: Old rules, set by -fno-for-scope.
+ 2: New ISO rules, set by -ffor-scope.
+ 1: Try to implement new ISO rules, but with backup compatibility
+ (and warnings). This is the default, for now. */
+
+int flag_new_for_scope = 1;
+
+/* Nonzero if we want to emit defined symbols with common-like linkage as
+ weak symbols where possible, in order to conform to C++ semantics.
+ Otherwise, emit them as local symbols. */
+
+int flag_weak = 1;
+
+/* Nonzero to use __cxa_atexit, rather than atexit, to register
+ destructors for local statics and global objects. */
+
+int flag_use_cxa_atexit = DEFAULT_USE_CXA_ATEXIT;
+
+/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */
+
+int flag_vtable_gc;
+
+/* Nonzero means make the default pedwarns warnings instead of errors.
+ The value of this flag is ignored if -pedantic is specified. */
+
+int flag_permissive;
+
+/* Nonzero means to implement standard semantics for exception
+ specifications, calling unexpected if an exception is thrown that
+ doesn't match the specification. Zero means to treat them as
+ assertions and optimize accordingly, but not check them. */
+
+int flag_enforce_eh_specs = 1;
+
+/* The version of the C++ ABI in use. The following values are
+ allowed:
+
+ 0: The version of the ABI believed most conformant with the
+ C++ ABI specification. This ABI may change as bugs are
+ discovered and fixed. Therefore, 0 will not necessarily
+ indicate the same ABI in different versions of G++.
+
+ 1: The version of the ABI first used in G++ 3.2.
+
+ Additional positive integers will be assigned as new versions of
+ the ABI become the default version of the ABI. */
+
+int flag_abi_version = 1;
+
+/* Nonzero means warn about things that will change when compiling
+ with an ABI-compliant compiler. */
+
+int warn_abi = 0;
+
+/* Nonzero means warn about implicit declarations. */
+
+int warn_implicit = 1;
+
+/* Nonzero means warn when all ctors or dtors are private, and the class
+ has no friends. */
+
+int warn_ctor_dtor_privacy = 1;
+
+/* Nonzero means warn in function declared in derived class has the
+ same name as a virtual in the base class, but fails to match the
+ type signature of any virtual function in the base class. */
+
+int warn_overloaded_virtual;
+
+/* Nonzero means warn when declaring a class that has a non virtual
+ destructor, when it really ought to have a virtual one. */
+
+int warn_nonvdtor;
+
+/* Nonzero means warn when the compiler will reorder code. */
+
+int warn_reorder;
+
+/* Nonzero means warn when synthesis behavior differs from Cfront's. */
+
+int warn_synth;
+
+/* Nonzero means warn when we convert a pointer to member function
+ into a pointer to (void or function). */
+
+int warn_pmf2ptr = 1;
+
+/* Nonzero means warn about violation of some Effective C++ style rules. */
+
+int warn_ecpp;
+
+/* Nonzero means warn where overload resolution chooses a promotion from
+ unsigned to signed over a conversion to an unsigned of the same size. */
+
+int warn_sign_promo;
+
+/* Nonzero means warn when an old-style cast is used. */
+
+int warn_old_style_cast;
+
+/* Nonzero means warn when non-templatized friend functions are
+ declared within a template */
+
+int warn_nontemplate_friend = 1;
+
+/* Nonzero means complain about deprecated features. */
+
+int warn_deprecated = 1;
+
+/* Maximum template instantiation depth. This limit is rather
+ arbitrary, but it exists to limit the time it takes to notice
+ infinite template instantiations. */
+
+int max_tinst_depth = 500;
+
+
+
/* The elements of `ridpointers' are identifier nodes for the reserved
type names and storage classes. It is indexed by a RID_... value. */
tree *ridpointers;
@@ -267,6 +714,169 @@ static int if_stack_space = 0;
/* Stack pointer. */
static int if_stack_pointer = 0;
+static tree handle_packed_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_nocommon_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_common_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_noreturn_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_noinline_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_always_inline_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_used_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_unused_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_const_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_transparent_union_attribute PARAMS ((tree *, tree, tree,
+ int, bool *));
+static tree handle_constructor_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_destructor_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_mode_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_section_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_aligned_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_weak_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_alias_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_visibility_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_tls_model_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_no_instrument_function_attribute PARAMS ((tree *, tree,
+ tree, int,
+ bool *));
+static tree handle_malloc_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_no_limit_stack_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_pure_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_deprecated_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_vector_size_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_nonnull_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_nothrow_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree handle_cleanup_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree vector_size_helper PARAMS ((tree, tree));
+
+static void check_function_nonnull PARAMS ((tree, tree));
+static void check_nonnull_arg PARAMS ((void *, tree,
+ unsigned HOST_WIDE_INT));
+static bool nonnull_check_p PARAMS ((tree, unsigned HOST_WIDE_INT));
+static bool get_nonnull_operand PARAMS ((tree,
+ unsigned HOST_WIDE_INT *));
+void builtin_define_std PARAMS ((const char *));
+static void builtin_define_with_value PARAMS ((const char *, const char *,
+ int));
+static void builtin_define_with_int_value PARAMS ((const char *,
+ HOST_WIDE_INT));
+static void builtin_define_with_hex_fp_value PARAMS ((const char *, tree,
+ int, const char *,
+ const char *));
+static void builtin_define_type_max PARAMS ((const char *, tree, int));
+static void builtin_define_type_precision PARAMS ((const char *, tree));
+static void builtin_define_float_constants PARAMS ((const char *,
+ const char *, tree));
+
+/* Table of machine-independent attributes common to all C-like languages. */
+const struct attribute_spec c_common_attribute_table[] =
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+ { "packed", 0, 0, false, false, false,
+ handle_packed_attribute },
+ { "nocommon", 0, 0, true, false, false,
+ handle_nocommon_attribute },
+ { "common", 0, 0, true, false, false,
+ handle_common_attribute },
+ /* FIXME: logically, noreturn attributes should be listed as
+ "false, true, true" and apply to function types. But implementing this
+ would require all the places in the compiler that use TREE_THIS_VOLATILE
+ on a decl to identify non-returning functions to be located and fixed
+ to check the function type instead. */
+ { "noreturn", 0, 0, true, false, false,
+ handle_noreturn_attribute },
+ { "volatile", 0, 0, true, false, false,
+ handle_noreturn_attribute },
+ { "noinline", 0, 0, true, false, false,
+ handle_noinline_attribute },
+ { "always_inline", 0, 0, true, false, false,
+ handle_always_inline_attribute },
+ { "used", 0, 0, true, false, false,
+ handle_used_attribute },
+ { "unused", 0, 0, false, false, false,
+ handle_unused_attribute },
+ /* The same comments as for noreturn attributes apply to const ones. */
+ { "const", 0, 0, true, false, false,
+ handle_const_attribute },
+ { "transparent_union", 0, 0, false, false, false,
+ handle_transparent_union_attribute },
+ { "constructor", 0, 0, true, false, false,
+ handle_constructor_attribute },
+ { "destructor", 0, 0, true, false, false,
+ handle_destructor_attribute },
+ { "mode", 1, 1, false, true, false,
+ handle_mode_attribute },
+ { "section", 1, 1, true, false, false,
+ handle_section_attribute },
+ { "aligned", 0, 1, false, false, false,
+ handle_aligned_attribute },
+ { "weak", 0, 0, true, false, false,
+ handle_weak_attribute },
+ { "alias", 1, 1, true, false, false,
+ handle_alias_attribute },
+ { "no_instrument_function", 0, 0, true, false, false,
+ handle_no_instrument_function_attribute },
+ { "malloc", 0, 0, true, false, false,
+ handle_malloc_attribute },
+ { "no_stack_limit", 0, 0, true, false, false,
+ handle_no_limit_stack_attribute },
+ { "pure", 0, 0, true, false, false,
+ handle_pure_attribute },
+ { "deprecated", 0, 0, false, false, false,
+ handle_deprecated_attribute },
+ { "vector_size", 1, 1, false, true, false,
+ handle_vector_size_attribute },
+ { "visibility", 1, 1, true, false, false,
+ handle_visibility_attribute },
+ { "tls_model", 1, 1, true, false, false,
+ handle_tls_model_attribute },
+ { "nonnull", 0, -1, false, true, true,
+ handle_nonnull_attribute },
+ { "nothrow", 0, 0, true, false, false,
+ handle_nothrow_attribute },
+ { "may_alias", 0, 0, false, true, false, NULL },
+ { "cleanup", 1, 1, true, false, false,
+ handle_cleanup_attribute },
+ { NULL, 0, 0, false, false, false, NULL }
+};
+
+/* Give the specifications for the format attributes, used by C and all
+ descendents. */
+
+const struct attribute_spec c_common_format_attribute_table[] =
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+ { "format", 3, 3, false, true, true,
+ handle_format_attribute },
+ { "format_arg", 1, 1, false, true, true,
+ handle_format_arg_attribute },
+ { NULL, 0, 0, false, false, false, NULL }
+};
+
/* Record the start of an if-then, and record the start of it
for ambiguous else detection.
@@ -483,7 +1093,7 @@ fname_as_string (pretty_p)
if (pretty_p)
name = (current_function_decl
- ? (*decl_printable_name) (current_function_decl, 2)
+ ? (*lang_hooks.decl_printable_name) (current_function_decl, 2)
: "top level");
else if (current_function_decl && DECL_NAME (current_function_decl))
name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
@@ -530,6 +1140,13 @@ fname_decl (rid, id)
if (!decl)
{
tree saved_last_tree = last_tree;
+ /* If a tree is built here, it would normally have the lineno of
+ the current statement. Later this tree will be moved to the
+ beginning of the function and this line number will be wrong.
+ To avoid this problem set the lineno to 0 here; that prevents
+ it from appearing in the RTL. */
+ int saved_lineno = lineno;
+ lineno = 0;
decl = (*make_fname_decl) (id, fname_vars[ix].pretty);
if (last_tree != saved_last_tree)
@@ -545,6 +1162,7 @@ fname_decl (rid, id)
saved_function_name_decls);
}
*fname_vars[ix].decl = decl;
+ lineno = saved_lineno;
}
if (!ix && !current_function_decl)
pedwarn_with_decl (decl, "`%s' is not defined outside of function scope");
@@ -552,136 +1170,152 @@ fname_decl (rid, id)
return decl;
}
-/* Given a chain of STRING_CST nodes,
- concatenate them into one STRING_CST
- and give it a suitable array-of-chars data type. */
+/* Given a STRING_CST, give it a suitable array-of-chars data type. */
+
+tree
+fix_string_type (value)
+ tree value;
+{
+ const int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
+ const int wide_flag = TREE_TYPE (value) == wchar_array_type_node;
+ const int nchars_max = flag_isoc99 ? 4095 : 509;
+ int length = TREE_STRING_LENGTH (value);
+ int nchars;
+
+ /* Compute the number of elements, for the array type. */
+ nchars = wide_flag ? length / wchar_bytes : length;
+
+ if (pedantic && nchars - 1 > nchars_max && c_language == clk_c)
+ pedwarn ("string length `%d' is greater than the length `%d' ISO C%d compilers are required to support",
+ nchars - 1, nchars_max, flag_isoc99 ? 99 : 89);
+
+ /* Create the array type for the string constant.
+ -Wwrite-strings says make the string constant an array of const char
+ so that copying it to a non-const pointer will get a warning.
+ For C++, this is the standard behavior. */
+ if (flag_const_strings && ! flag_writable_strings)
+ {
+ tree elements
+ = build_type_variant (wide_flag ? wchar_type_node : char_type_node,
+ 1, 0);
+ TREE_TYPE (value)
+ = build_array_type (elements,
+ build_index_type (build_int_2 (nchars - 1, 0)));
+ }
+ else
+ TREE_TYPE (value)
+ = build_array_type (wide_flag ? wchar_type_node : char_type_node,
+ build_index_type (build_int_2 (nchars - 1, 0)));
+
+ TREE_CONSTANT (value) = 1;
+ TREE_READONLY (value) = ! flag_writable_strings;
+ TREE_STATIC (value) = 1;
+ return value;
+}
+
+/* Given a VARRAY of STRING_CST nodes, concatenate them into one
+ STRING_CST. */
tree
combine_strings (strings)
- tree strings;
+ varray_type strings;
{
+ const int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
+ const int nstrings = VARRAY_ACTIVE_SIZE (strings);
tree value, t;
int length = 1;
int wide_length = 0;
int wide_flag = 0;
- int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
- int nchars;
- const int nchars_max = flag_isoc99 ? 4095 : 509;
+ int i;
+ char *p, *q;
- if (TREE_CHAIN (strings))
+ /* Don't include the \0 at the end of each substring. Count wide
+ strings and ordinary strings separately. */
+ for (i = 0; i < nstrings; ++i)
{
- /* More than one in the chain, so concatenate. */
- char *p, *q;
+ t = VARRAY_TREE (strings, i);
- /* Don't include the \0 at the end of each substring,
- except for the last one.
- Count wide strings and ordinary strings separately. */
- for (t = strings; t; t = TREE_CHAIN (t))
+ if (TREE_TYPE (t) == wchar_array_type_node)
{
- if (TREE_TYPE (t) == wchar_array_type_node)
- {
- wide_length += (TREE_STRING_LENGTH (t) - wchar_bytes);
- wide_flag = 1;
- }
- else
- {
- length += (TREE_STRING_LENGTH (t) - 1);
- if (C_ARTIFICIAL_STRING_P (t) && !in_system_header)
- warning ("concatenation of string literals with __FUNCTION__ is deprecated");
- }
+ wide_length += TREE_STRING_LENGTH (t) - wchar_bytes;
+ wide_flag = 1;
+ }
+ else
+ {
+ length += (TREE_STRING_LENGTH (t) - 1);
+ if (C_ARTIFICIAL_STRING_P (t) && !in_system_header)
+ warning ("concatenation of string literals with __FUNCTION__ is deprecated");
}
+ }
+
+ /* If anything is wide, the non-wides will be converted,
+ which makes them take more space. */
+ if (wide_flag)
+ length = length * wchar_bytes + wide_length;
- /* If anything is wide, the non-wides will be converted,
- which makes them take more space. */
- if (wide_flag)
- length = length * wchar_bytes + wide_length;
+ p = xmalloc (length);
- p = xmalloc (length);
+ /* Copy the individual strings into the new combined string.
+ If the combined string is wide, convert the chars to ints
+ for any individual strings that are not wide. */
- /* Copy the individual strings into the new combined string.
- If the combined string is wide, convert the chars to ints
- for any individual strings that are not wide. */
+ q = p;
+ for (i = 0; i < nstrings; ++i)
+ {
+ int len, this_wide;
- q = p;
- for (t = strings; t; t = TREE_CHAIN (t))
+ t = VARRAY_TREE (strings, i);
+ this_wide = TREE_TYPE (t) == wchar_array_type_node;
+ len = TREE_STRING_LENGTH (t) - (this_wide ? wchar_bytes : 1);
+ if (this_wide == wide_flag)
{
- int len = (TREE_STRING_LENGTH (t)
- - ((TREE_TYPE (t) == wchar_array_type_node)
- ? wchar_bytes : 1));
- if ((TREE_TYPE (t) == wchar_array_type_node) == wide_flag)
+ memcpy (q, TREE_STRING_POINTER (t), len);
+ q += len;
+ }
+ else
+ {
+ const int nzeros = (TYPE_PRECISION (wchar_type_node)
+ / BITS_PER_UNIT) - 1;
+ int j, k;
+
+ if (BYTES_BIG_ENDIAN)
{
- memcpy (q, TREE_STRING_POINTER (t), len);
- q += len;
+ for (k = 0; k < len; k++)
+ {
+ for (j = 0; j < nzeros; j++)
+ *q++ = 0;
+ *q++ = TREE_STRING_POINTER (t)[k];
+ }
}
else
{
- int i, j;
- for (i = 0; i < len; i++)
+ for (k = 0; k < len; k++)
{
- if (BYTES_BIG_ENDIAN)
- {
- for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++)
- *q++ = 0;
- *q++ = TREE_STRING_POINTER (t)[i];
- }
- else
- {
- *q++ = TREE_STRING_POINTER (t)[i];
- for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++)
- *q++ = 0;
- }
+ *q++ = TREE_STRING_POINTER (t)[k];
+ for (j = 0; j < nzeros; j++)
+ *q++ = 0;
}
}
}
- if (wide_flag)
- {
- int i;
- for (i = 0; i < wchar_bytes; i++)
- *q++ = 0;
- }
- else
- *q = 0;
-
- value = build_string (length, p);
- free (p);
}
- else
+
+ /* Nul terminate the string. */
+ if (wide_flag)
{
- value = strings;
- length = TREE_STRING_LENGTH (value);
- if (TREE_TYPE (value) == wchar_array_type_node)
- wide_flag = 1;
+ for (i = 0; i < wchar_bytes; i++)
+ *q++ = 0;
}
+ else
+ *q = 0;
- /* Compute the number of elements, for the array type. */
- nchars = wide_flag ? length / wchar_bytes : length;
-
- if (pedantic && nchars - 1 > nchars_max && c_language == clk_c)
- pedwarn ("string length `%d' is greater than the length `%d' ISO C%d compilers are required to support",
- nchars - 1, nchars_max, flag_isoc99 ? 99 : 89);
+ value = build_string (length, p);
+ free (p);
- /* Create the array type for the string constant.
- -Wwrite-strings says make the string constant an array of const char
- so that copying it to a non-const pointer will get a warning.
- For C++, this is the standard behavior. */
- if (flag_const_strings
- && (! flag_traditional && ! flag_writable_strings))
- {
- tree elements
- = build_type_variant (wide_flag ? wchar_type_node : char_type_node,
- 1, 0);
- TREE_TYPE (value)
- = build_array_type (elements,
- build_index_type (build_int_2 (nchars - 1, 0)));
- }
+ if (wide_flag)
+ TREE_TYPE (value) = wchar_array_type_node;
else
- TREE_TYPE (value)
- = build_array_type (wide_flag ? wchar_type_node : char_type_node,
- build_index_type (build_int_2 (nchars - 1, 0)));
+ TREE_TYPE (value) = char_array_type_node;
- TREE_CONSTANT (value) = 1;
- TREE_READONLY (value) = ! flag_writable_strings;
- TREE_STATIC (value) = 1;
return value;
}
@@ -755,13 +1389,15 @@ void
unsigned_conversion_warning (result, operand)
tree result, operand;
{
+ tree type = TREE_TYPE (result);
+
if (TREE_CODE (operand) == INTEGER_CST
- && TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE
- && TREE_UNSIGNED (TREE_TYPE (result))
+ && TREE_CODE (type) == INTEGER_TYPE
+ && TREE_UNSIGNED (type)
&& skip_evaluation == 0
- && !int_fits_type_p (operand, TREE_TYPE (result)))
+ && !int_fits_type_p (operand, type))
{
- if (!int_fits_type_p (operand, signed_type (TREE_TYPE (result))))
+ if (!int_fits_type_p (operand, c_common_signed_type (type)))
/* This detects cases like converting -129 or 256 to unsigned char. */
warning ("large integer implicitly truncated to unsigned type");
else if (warn_conversion)
@@ -810,7 +1446,8 @@ convert_and_check (type, expr)
don't warn unless pedantic. */
if ((pedantic
|| TREE_UNSIGNED (type)
- || ! constant_fits_type_p (expr, unsigned_type (type)))
+ || ! constant_fits_type_p (expr,
+ c_common_unsigned_type (type)))
&& skip_evaluation == 0)
warning ("overflow in implicit constant conversion");
}
@@ -1212,7 +1849,7 @@ verify_tree (x, pbefore_sp, pno_sp, writer)
}
}
-/* Try to warn for undefined behaviour in EXPR due to missing sequence
+/* Try to warn for undefined behavior in EXPR due to missing sequence
points. */
static void
@@ -1300,7 +1937,7 @@ check_case_value (value)
that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */
tree
-type_for_size (bits, unsignedp)
+c_common_type_for_size (bits, unsignedp)
unsigned bits;
int unsignedp;
{
@@ -1344,7 +1981,7 @@ type_for_size (bits, unsignedp)
then UNSIGNEDP selects between signed and unsigned types. */
tree
-type_for_mode (mode, unsignedp)
+c_common_type_for_mode (mode, unsignedp)
enum machine_mode mode;
int unsignedp;
{
@@ -1399,41 +2036,44 @@ type_for_mode (mode, unsignedp)
if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
return build_pointer_type (integer_type_node);
-#ifdef VECTOR_MODE_SUPPORTED_P
- if (VECTOR_MODE_SUPPORTED_P (mode))
+ switch (mode)
{
- switch (mode)
- {
- case V16QImode:
- return unsignedp ? unsigned_V16QI_type_node : V16QI_type_node;
- case V8HImode:
- return unsignedp ? unsigned_V8HI_type_node : V8HI_type_node;
- case V4SImode:
- return unsignedp ? unsigned_V4SI_type_node : V4SI_type_node;
- case V2SImode:
- return unsignedp ? unsigned_V2SI_type_node : V2SI_type_node;
- case V4HImode:
- return unsignedp ? unsigned_V4HI_type_node : V4HI_type_node;
- case V8QImode:
- return unsignedp ? unsigned_V8QI_type_node : V8QI_type_node;
- case V16SFmode:
- return V16SF_type_node;
- case V4SFmode:
- return V4SF_type_node;
- case V2SFmode:
- return V2SF_type_node;
- default:
- break;
- }
+ case V16QImode:
+ return unsignedp ? unsigned_V16QI_type_node : V16QI_type_node;
+ case V8HImode:
+ return unsignedp ? unsigned_V8HI_type_node : V8HI_type_node;
+ case V4SImode:
+ return unsignedp ? unsigned_V4SI_type_node : V4SI_type_node;
+ case V2DImode:
+ return unsignedp ? unsigned_V2DI_type_node : V2DI_type_node;
+ case V2SImode:
+ return unsignedp ? unsigned_V2SI_type_node : V2SI_type_node;
+ case V2HImode:
+ return unsignedp ? unsigned_V2HI_type_node : V2HI_type_node;
+ case V4HImode:
+ return unsignedp ? unsigned_V4HI_type_node : V4HI_type_node;
+ case V8QImode:
+ return unsignedp ? unsigned_V8QI_type_node : V8QI_type_node;
+ case V1DImode:
+ return unsignedp ? unsigned_V1DI_type_node : V1DI_type_node;
+ case V16SFmode:
+ return V16SF_type_node;
+ case V4SFmode:
+ return V4SF_type_node;
+ case V2SFmode:
+ return V2SF_type_node;
+ case V2DFmode:
+ return V2DF_type_node;
+ default:
+ break;
}
-#endif
return 0;
}
/* Return an unsigned type the same as TYPE in other respects. */
tree
-unsigned_type (type)
+c_common_unsigned_type (type)
tree type;
{
tree type1 = TYPE_MAIN_VARIANT (type);
@@ -1462,13 +2102,13 @@ unsigned_type (type)
if (type1 == intQI_type_node)
return unsigned_intQI_type_node;
- return signed_or_unsigned_type (1, type);
+ return c_common_signed_or_unsigned_type (1, type);
}
/* Return a signed type the same as TYPE in other respects. */
tree
-signed_type (type)
+c_common_signed_type (type)
tree type;
{
tree type1 = TYPE_MAIN_VARIANT (type);
@@ -1497,14 +2137,14 @@ signed_type (type)
if (type1 == unsigned_intQI_type_node)
return intQI_type_node;
- return signed_or_unsigned_type (0, type);
+ return c_common_signed_or_unsigned_type (0, type);
}
/* Return a type the same as TYPE except unsigned or
signed according to UNSIGNEDP. */
tree
-signed_or_unsigned_type (unsignedp, type)
+c_common_signed_or_unsigned_type (unsignedp, type)
int unsignedp;
tree type;
{
@@ -1572,8 +2212,9 @@ min_precision (value, unsignedp)
return log + 1 + ! unsignedp;
}
-/* Print an error message for invalid operands to arith operation CODE.
- NOP_EXPR is used as a special case (see truthvalue_conversion). */
+/* Print an error message for invalid operands to arith operation
+ CODE. NOP_EXPR is used as a special case (see
+ c_common_truthvalue_conversion). */
void
binary_op_error (code)
@@ -1753,19 +2394,20 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
int unsignedp = TREE_UNSIGNED (*restype_ptr);
tree val;
- type = signed_or_unsigned_type (unsignedp0, TREE_TYPE (primop0));
+ type = c_common_signed_or_unsigned_type (unsignedp0,
+ TREE_TYPE (primop0));
/* If TYPE is an enumeration, then we need to get its min/max
values from it's underlying integral type, not the enumerated
type itself. */
if (TREE_CODE (type) == ENUMERAL_TYPE)
- type = type_for_size (TYPE_PRECISION (type), unsignedp0);
+ type = c_common_type_for_size (TYPE_PRECISION (type), unsignedp0);
maxval = TYPE_MAX_VALUE (type);
minval = TYPE_MIN_VALUE (type);
if (unsignedp && !unsignedp0)
- *restype_ptr = signed_type (*restype_ptr);
+ *restype_ptr = c_common_signed_type (*restype_ptr);
if (TREE_TYPE (primop1) != *restype_ptr)
primop1 = convert (*restype_ptr, primop1);
@@ -1862,22 +2504,11 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
default:
break;
}
- type = unsigned_type (type);
- }
-
- if (!max_gt && !unsignedp0 && TREE_CODE (primop0) != INTEGER_CST)
- {
- /* This is the case of (char)x >?< 0x80, which people used to use
- expecting old C compilers to change the 0x80 into -0x80. */
- if (val == boolean_false_node)
- warning ("comparison is always false due to limited range of data type");
- if (val == boolean_true_node)
- warning ("comparison is always true due to limited range of data type");
+ type = c_common_unsigned_type (type);
}
- if (!min_lt && unsignedp0 && TREE_CODE (primop0) != INTEGER_CST)
+ if (TREE_CODE (primop0) != INTEGER_CST)
{
- /* This is the case of (unsigned char)x >?< -1 or < 0. */
if (val == boolean_false_node)
warning ("comparison is always false due to limited range of data type");
if (val == boolean_true_node)
@@ -1914,15 +2545,19 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
&& TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (*restype_ptr))
{
type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));
- type = signed_or_unsigned_type (unsignedp0
- || TREE_UNSIGNED (*restype_ptr),
- type);
+ type = c_common_signed_or_unsigned_type (unsignedp0
+ || TREE_UNSIGNED (*restype_ptr),
+ type);
/* Make sure shorter operand is extended the right way
to match the longer operand. */
- primop0 = convert (signed_or_unsigned_type (unsignedp0, TREE_TYPE (primop0)),
- primop0);
- primop1 = convert (signed_or_unsigned_type (unsignedp1, TREE_TYPE (primop1)),
- primop1);
+ primop0
+ = convert (c_common_signed_or_unsigned_type (unsignedp0,
+ TREE_TYPE (primop0)),
+ primop0);
+ primop1
+ = convert (c_common_signed_or_unsigned_type (unsignedp1,
+ TREE_TYPE (primop1)),
+ primop1);
}
else
{
@@ -1945,7 +2580,7 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
so suppress the warning. */
if (extra_warnings && !in_system_header
&& ! (TREE_CODE (primop0) == INTEGER_CST
- && ! TREE_OVERFLOW (convert (signed_type (type),
+ && ! TREE_OVERFLOW (convert (c_common_signed_type (type),
primop0))))
warning ("comparison of unsigned expression >= 0 is always true");
value = boolean_true_node;
@@ -1954,7 +2589,7 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
case LT_EXPR:
if (extra_warnings && !in_system_header
&& ! (TREE_CODE (primop0) == INTEGER_CST
- && ! TREE_OVERFLOW (convert (signed_type (type),
+ && ! TREE_OVERFLOW (convert (c_common_signed_type (type),
primop0))))
warning ("comparison of unsigned expression < 0 is always false");
value = boolean_false_node;
@@ -2063,8 +2698,8 @@ pointer_int_sum (resultcode, ptrop, intop)
if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
|| TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype))
- intop = convert (type_for_size (TYPE_PRECISION (sizetype),
- TREE_UNSIGNED (sizetype)), intop);
+ intop = convert (c_common_type_for_size (TYPE_PRECISION (sizetype),
+ TREE_UNSIGNED (sizetype)), intop);
/* Replace the integer argument with a suitable product by the object size.
Do this multiplication as signed, then convert to the appropriate
@@ -2096,7 +2731,7 @@ pointer_int_sum (resultcode, ptrop, intop)
The resulting type should always be `boolean_type_node'. */
tree
-truthvalue_conversion (expr)
+c_common_truthvalue_conversion (expr)
tree expr;
{
if (TREE_CODE (expr) == ERROR_MARK)
@@ -2162,32 +2797,32 @@ truthvalue_conversion (expr)
case COMPLEX_EXPR:
return build_binary_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
- truthvalue_conversion (TREE_OPERAND (expr, 0)),
- truthvalue_conversion (TREE_OPERAND (expr, 1)),
+ c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
+ c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
0);
case NEGATE_EXPR:
case ABS_EXPR:
case FLOAT_EXPR:
case FFS_EXPR:
- /* These don't change whether an object is non-zero or zero. */
- return truthvalue_conversion (TREE_OPERAND (expr, 0));
+ /* These don't change whether an object is nonzero or zero. */
+ return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
case LROTATE_EXPR:
case RROTATE_EXPR:
- /* These don't change whether an object is zero or non-zero, but
+ /* These don't change whether an object is zero or nonzero, but
we can't ignore them if their second arg has side-effects. */
if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
return build (COMPOUND_EXPR, boolean_type_node, TREE_OPERAND (expr, 1),
- truthvalue_conversion (TREE_OPERAND (expr, 0)));
+ c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
else
- return truthvalue_conversion (TREE_OPERAND (expr, 0));
+ return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
case COND_EXPR:
/* Distribute the conversion into the arms of a COND_EXPR. */
return fold (build (COND_EXPR, boolean_type_node, TREE_OPERAND (expr, 0),
- truthvalue_conversion (TREE_OPERAND (expr, 1)),
- truthvalue_conversion (TREE_OPERAND (expr, 2))));
+ c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
+ c_common_truthvalue_conversion (TREE_OPERAND (expr, 2))));
case CONVERT_EXPR:
/* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
@@ -2200,14 +2835,19 @@ truthvalue_conversion (expr)
/* If this is widening the argument, we can ignore it. */
if (TYPE_PRECISION (TREE_TYPE (expr))
>= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
- return truthvalue_conversion (TREE_OPERAND (expr, 0));
+ return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
break;
case MINUS_EXPR:
- /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
- this case. */
- if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
- && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
+ /* Perhaps reduce (x - y) != 0 to (x != y). The expressions
+ aren't guaranteed to the be same for modes that can represent
+ infinity, since if x and y are both +infinity, or both
+ -infinity, then x - y is not a number.
+
+ Note that this transformation is safe when x or y is NaN.
+ (x - y) is then NaN, and both (x - y) != 0 and x != y will
+ be false. */
+ if (HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (TREE_OPERAND (expr, 0)))))
break;
/* fall through... */
case BIT_XOR_EXPR:
@@ -2240,12 +2880,12 @@ truthvalue_conversion (expr)
if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
{
- tree tem = save_expr (expr);
+ tree t = save_expr (expr);
return (build_binary_op
((TREE_SIDE_EFFECTS (expr)
? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
- truthvalue_conversion (build_unary_op (REALPART_EXPR, tem, 0)),
- truthvalue_conversion (build_unary_op (IMAGPART_EXPR, tem, 0)),
+ c_common_truthvalue_conversion (build_unary_op (REALPART_EXPR, t, 0)),
+ c_common_truthvalue_conversion (build_unary_op (IMAGPART_EXPR, t, 0)),
0));
}
@@ -2254,7 +2894,7 @@ truthvalue_conversion (expr)
static tree builtin_function_2 PARAMS ((const char *, const char *, tree, tree,
int, enum built_in_class, int, int,
- int));
+ tree));
/* Make a variant type in the proper way for C/C++, propagating qualifiers
down to the element type of an array. */
@@ -2316,7 +2956,6 @@ c_apply_type_quals_to_decl (type_quals, decl)
}
}
-
/* Return the typed-based alias set for T, which may be an expression
or a type. Return -1 if we don't do anything special. */
@@ -2349,13 +2988,17 @@ c_common_get_alias_set (t)
|| t == signed_char_type_node
|| t == unsigned_char_type_node)
return 0;
-
+
+ /* If it has the may_alias attribute, it can alias anything. */
+ if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (t)))
+ return 0;
+
/* The C standard specifically allows aliasing between signed and
unsigned variants of the same type. We treat the signed
variant as canonical. */
if (TREE_CODE (t) == INTEGER_TYPE && TREE_UNSIGNED (t))
{
- tree t1 = signed_type (t);
+ tree t1 = c_common_signed_type (t);
/* t1 == t can happen for boolean nodes which are always unsigned. */
if (t1 != t)
@@ -2396,36 +3039,66 @@ c_common_get_alias_set (t)
return -1;
}
-/* Implement the __alignof keyword: Return the minimum required
- alignment of TYPE, measured in bytes. */
-
+/* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where the
+ second parameter indicates which OPERATOR is being applied. The COMPLAIN
+ flag controls whether we should diagnose possibly ill-formed
+ constructs or not. */
tree
-c_alignof (type)
+c_sizeof_or_alignof_type (type, op, complain)
tree type;
+ enum tree_code op;
+ int complain;
{
- enum tree_code code = TREE_CODE (type);
- tree t;
-
- /* In C++, sizeof applies to the referent. Handle alignof the same way. */
- if (code == REFERENCE_TYPE)
+ const char *op_name;
+ tree value = NULL;
+ enum tree_code type_code = TREE_CODE (type);
+
+ my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
+ op_name = op == SIZEOF_EXPR ? "sizeof" : "__alignof__";
+
+ if (type_code == FUNCTION_TYPE)
{
- type = TREE_TYPE (type);
- code = TREE_CODE (type);
+ if (op == SIZEOF_EXPR)
+ {
+ if (complain && (pedantic || warn_pointer_arith))
+ pedwarn ("invalid application of `sizeof' to a function type");
+ value = size_one_node;
+ }
+ else
+ value = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
+ }
+ else if (type_code == VOID_TYPE || type_code == ERROR_MARK)
+ {
+ if (type_code == VOID_TYPE
+ && complain && (pedantic || warn_pointer_arith))
+ pedwarn ("invalid application of `%s' to a void type", op_name);
+ value = size_one_node;
}
-
- if (code == FUNCTION_TYPE)
- t = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
- else if (code == VOID_TYPE || code == ERROR_MARK)
- t = size_one_node;
else if (!COMPLETE_TYPE_P (type))
{
- error ("__alignof__ applied to an incomplete type");
- t = size_zero_node;
+ if (complain)
+ error ("invalid application of `%s' to an incomplete type", op_name);
+ value = size_zero_node;
}
else
- t = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
+ {
+ if (op == SIZEOF_EXPR)
+ /* Convert in case a char is more than one unit. */
+ value = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+ size_int (TYPE_PRECISION (char_type_node)
+ / BITS_PER_UNIT));
+ else
+ value = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
+ }
- return fold (build1 (NOP_EXPR, size_type_node, t));
+ /* VALUE will have an integer type with TYPE_IS_SIZETYPE set.
+ TYPE_IS_SIZETYPE means that certain things (like overflow) will
+ never happen. However, this node should really have type
+ `size_t', which is just a typedef for an ordinary integer type. */
+ value = fold (build1 (NOP_EXPR, size_type_node, value));
+ my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)), 20001021);
+
+ return value;
}
/* Implement the __alignof keyword: Return the minimum required
@@ -2476,19 +3149,30 @@ c_alignof_expr (expr)
return fold (build1 (NOP_EXPR, size_type_node, t));
}
-/* Give the specifications for the format attributes, used by C and all
- descendents. */
+/* Handle C and C++ default attributes. */
-static const struct attribute_spec c_format_attribute_table[] =
+enum built_in_attribute
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
- { "format", 3, 3, false, true, true,
- handle_format_attribute },
- { "format_arg", 1, 1, false, true, true,
- handle_format_arg_attribute },
- { NULL, 0, 0, false, false, false, NULL }
+#define DEF_ATTR_NULL_TREE(ENUM) ENUM,
+#define DEF_ATTR_INT(ENUM, VALUE) ENUM,
+#define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
+#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
+#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No entry needed in enum. */
+#include "builtin-attrs.def"
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
+#undef DEF_FN_ATTR
+ ATTR_LAST
};
+static GTY(()) tree built_in_attributes[(int) ATTR_LAST];
+
+static bool c_attrs_initialized = false;
+
+static void c_init_attributes PARAMS ((void));
+
/* Build tree nodes and builtin functions common to both C and C++ language
frontends. */
@@ -2506,6 +3190,7 @@ c_common_nodes_and_builtins ()
#define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
#define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
#define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
+#define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
#include "builtin-types.def"
#undef DEF_PRIMITIVE_TYPE
@@ -2517,6 +3202,7 @@ c_common_nodes_and_builtins ()
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
#undef DEF_POINTER_TYPE
BT_LAST
};
@@ -2526,18 +3212,9 @@ c_common_nodes_and_builtins ()
tree builtin_types[(int) BT_LAST];
int wchar_type_size;
tree array_domain_type;
- /* Either char* or void*. */
- tree traditional_ptr_type_node;
- /* Either const char* or const void*. */
- tree traditional_cptr_type_node;
- tree traditional_len_type_node;
tree va_list_ref_type_node;
tree va_list_arg_type_node;
- /* We must initialize this before any builtin functions (which might have
- attributes) are declared. (c_common_init is too late.) */
- format_attribute_table = c_format_attribute_table;
-
/* Define `int' and `char' first so that dbx will output them first. */
record_builtin_type (RID_INT, NULL, integer_type_node);
record_builtin_type (RID_CHAR, "char", char_type_node);
@@ -2571,41 +3248,52 @@ c_common_nodes_and_builtins ()
record_builtin_type (RID_MAX, "signed char", signed_char_type_node);
record_builtin_type (RID_MAX, "unsigned char", unsigned_char_type_node);
- /* These are types that type_for_size and type_for_mode use. */
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intHI_type_node));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
+ /* These are types that c_common_type_for_size and
+ c_common_type_for_mode use. */
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
+ intQI_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
+ intHI_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
+ intSI_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
+ intDI_type_node));
#if HOST_BITS_PER_WIDE_INT >= 64
- pushdecl (build_decl (TYPE_DECL, get_identifier ("__int128_t"), intTI_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
+ get_identifier ("__int128_t"),
+ intTI_type_node));
#endif
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intHI_type_node));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node));
- pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
+ unsigned_intQI_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
+ unsigned_intHI_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
+ unsigned_intSI_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
+ unsigned_intDI_type_node));
#if HOST_BITS_PER_WIDE_INT >= 64
- pushdecl (build_decl (TYPE_DECL, get_identifier ("__uint128_t"), unsigned_intTI_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
+ get_identifier ("__uint128_t"),
+ unsigned_intTI_type_node));
#endif
/* Create the widest literal types. */
widest_integer_literal_type_node
= make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
- pushdecl (build_decl (TYPE_DECL, NULL_TREE,
- widest_integer_literal_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
+ widest_integer_literal_type_node));
widest_unsigned_literal_type_node
= make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
- pushdecl (build_decl (TYPE_DECL, NULL_TREE,
- widest_unsigned_literal_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
+ widest_unsigned_literal_type_node));
/* `unsigned long' is the standard type for sizeof.
Note that stddef.h uses `unsigned long',
and this must agree, even if long and int are the same size. */
size_type_node =
TREE_TYPE (identifier_global_value (get_identifier (SIZE_TYPE)));
- signed_size_type_node = signed_type (size_type_node);
- if (flag_traditional)
- size_type_node = signed_size_type_node;
+ signed_size_type_node = c_common_signed_type (size_type_node);
set_sizetype (size_type_node);
build_common_tree_nodes_2 (flag_short_double);
@@ -2614,14 +3302,18 @@ c_common_nodes_and_builtins ()
record_builtin_type (RID_DOUBLE, NULL, double_type_node);
record_builtin_type (RID_MAX, "long double", long_double_type_node);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
- complex_integer_type_node));
- pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
- complex_float_type_node));
- pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
- complex_double_type_node));
- pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
- complex_long_double_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
+ get_identifier ("complex int"),
+ complex_integer_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
+ get_identifier ("complex float"),
+ complex_float_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
+ get_identifier ("complex double"),
+ complex_double_type_node));
+ (*lang_hooks.decls.pushdecl)
+ (build_decl (TYPE_DECL, get_identifier ("complex long double"),
+ complex_long_double_type_node));
/* Types which are common to the fortran compiler and libf2c. When
changing these, you also need to be concerned with f/com.h. */
@@ -2643,12 +3335,12 @@ c_common_nodes_and_builtins ()
if (g77_integer_type_node != NULL_TREE)
{
- pushdecl (build_decl (TYPE_DECL,
- get_identifier ("__g77_integer"),
- g77_integer_type_node));
- pushdecl (build_decl (TYPE_DECL,
- get_identifier ("__g77_uinteger"),
- g77_uinteger_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
+ get_identifier ("__g77_integer"),
+ g77_integer_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
+ get_identifier ("__g77_uinteger"),
+ g77_uinteger_type_node));
}
if (TYPE_PRECISION (float_type_node) * 2
@@ -2668,12 +3360,12 @@ c_common_nodes_and_builtins ()
if (g77_longint_type_node != NULL_TREE)
{
- pushdecl (build_decl (TYPE_DECL,
- get_identifier ("__g77_longint"),
- g77_longint_type_node));
- pushdecl (build_decl (TYPE_DECL,
- get_identifier ("__g77_ulongint"),
- g77_ulongint_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
+ get_identifier ("__g77_longint"),
+ g77_longint_type_node));
+ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
+ get_identifier ("__g77_ulongint"),
+ g77_ulongint_type_node));
}
record_builtin_type (RID_VOID, NULL, void_type_node);
@@ -2705,19 +3397,8 @@ c_common_nodes_and_builtins ()
= build_pointer_type (build_qualified_type
(char_type_node, TYPE_QUAL_CONST));
- traditional_ptr_type_node = ((flag_traditional &&
- c_language != clk_cplusplus)
- ? string_type_node : ptr_type_node);
- traditional_cptr_type_node = ((flag_traditional &&
- c_language != clk_cplusplus)
- ? const_string_type_node : const_ptr_type_node);
-
- (*targetm.init_builtins) ();
-
/* This is special for C++ so functions can be overloaded. */
- wchar_type_node = get_identifier (flag_short_wchar
- ? "short unsigned int"
- : WCHAR_TYPE);
+ wchar_type_node = get_identifier (MODIFIED_WCHAR_TYPE);
wchar_type_node = TREE_TYPE (identifier_global_value (wchar_type_node));
wchar_type_size = TYPE_PRECISION (wchar_type_node);
if (c_language == clk_cplusplus)
@@ -2730,8 +3411,8 @@ c_common_nodes_and_builtins ()
}
else
{
- signed_wchar_type_node = signed_type (wchar_type_node);
- unsigned_wchar_type_node = unsigned_type (wchar_type_node);
+ signed_wchar_type_node = c_common_signed_type (wchar_type_node);
+ unsigned_wchar_type_node = c_common_unsigned_type (wchar_type_node);
}
/* This is for wide string constants. */
@@ -2749,16 +3430,19 @@ c_common_nodes_and_builtins ()
default_function_type = build_function_type (integer_type_node, NULL_TREE);
ptrdiff_type_node
= TREE_TYPE (identifier_global_value (get_identifier (PTRDIFF_TYPE)));
- unsigned_ptrdiff_type_node = unsigned_type (ptrdiff_type_node);
+ unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node);
- pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),
- va_list_type_node));
+ (*lang_hooks.decls.pushdecl)
+ (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),
+ va_list_type_node));
- pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_ptrdiff_t"),
- ptrdiff_type_node));
+ (*lang_hooks.decls.pushdecl)
+ (build_decl (TYPE_DECL, get_identifier ("__builtin_ptrdiff_t"),
+ ptrdiff_type_node));
- pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_size_t"),
- sizetype));
+ (*lang_hooks.decls.pushdecl)
+ (build_decl (TYPE_DECL, get_identifier ("__builtin_size_t"),
+ sizetype));
if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
{
@@ -2771,10 +3455,6 @@ c_common_nodes_and_builtins ()
va_list_ref_type_node = build_reference_type (va_list_type_node);
}
- traditional_len_type_node = ((flag_traditional &&
- c_language != clk_cplusplus)
- ? integer_type_node : sizetype);
-
#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
builtin_types[(int) ENUM] = VALUE;
#define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
@@ -2840,6 +3520,19 @@ c_common_nodes_and_builtins ()
tree_cons (NULL_TREE, \
builtin_types[(int) ARG2], \
NULL_TREE)));
+
+#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
+ builtin_types[(int) ENUM] \
+ = build_function_type \
+ (builtin_types[(int) RETURN], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG1], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG2], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG3], \
+ NULL_TREE))));
+
#define DEF_POINTER_TYPE(ENUM, TYPE) \
builtin_types[(int) ENUM] \
= build_pointer_type (builtin_types[(int) TYPE]);
@@ -2851,10 +3544,15 @@ c_common_nodes_and_builtins ()
#undef DEF_FUNCTION_TYPE_4
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
+#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
#undef DEF_POINTER_TYPE
-#define DEF_BUILTIN(ENUM, NAME, CLASS, \
- TYPE, LIBTYPE, BOTH_P, FALLBACK_P, NONANSI_P) \
+ if (!c_attrs_initialized)
+ c_init_attributes ();
+
+#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, \
+ BOTH_P, FALLBACK_P, NONANSI_P, ATTRS) \
if (NAME) \
{ \
tree decl; \
@@ -2867,7 +3565,8 @@ c_common_nodes_and_builtins ()
CLASS, \
(FALLBACK_P \
? (NAME + strlen ("__builtin_")) \
- : NULL)); \
+ : NULL), \
+ built_in_attributes[(int) ATTRS]); \
else \
decl = builtin_function_2 (NAME, \
NAME + strlen ("__builtin_"), \
@@ -2877,40 +3576,16 @@ c_common_nodes_and_builtins ()
CLASS, \
FALLBACK_P, \
NONANSI_P, \
- /*noreturn_p=*/0); \
+ built_in_attributes[(int) ATTRS]); \
\
built_in_decls[(int) ENUM] = decl; \
}
#include "builtins.def"
#undef DEF_BUILTIN
- /* Declare _exit and _Exit just to mark them as non-returning. */
- builtin_function_2 (NULL, "_exit", NULL_TREE,
- builtin_types[BT_FN_VOID_INT],
- 0, NOT_BUILT_IN, 0, 1, 1);
- builtin_function_2 (NULL, "_Exit", NULL_TREE,
- builtin_types[BT_FN_VOID_INT],
- 0, NOT_BUILT_IN, 0, !flag_isoc99, 1);
-
- /* Declare these functions non-returning
- to avoid spurious "control drops through" warnings. */
- builtin_function_2 (NULL, "abort",
- NULL_TREE, ((c_language == clk_cplusplus)
- ? builtin_types[BT_FN_VOID]
- : builtin_types[BT_FN_VOID_VAR]),
- 0, NOT_BUILT_IN, 0, 0, 1);
-
- builtin_function_2 (NULL, "exit",
- NULL_TREE, ((c_language == clk_cplusplus)
- ? builtin_types[BT_FN_VOID_INT]
- : builtin_types[BT_FN_VOID_VAR]),
- 0, NOT_BUILT_IN, 0, 0, 1);
+ (*targetm.init_builtins) ();
main_identifier_node = get_identifier ("main");
-
- /* ??? Perhaps there's a better place to do this. But it is related
- to __builtin_va_arg, so it isn't that off-the-wall. */
- lang_type_promotes_to = simple_type_promotes_to;
}
tree
@@ -2977,15 +3652,15 @@ builtin_function_disabled_p (name)
conflicts with headers. FUNCTION_CODE and CLASS are as for
builtin_function. If LIBRARY_NAME_P is nonzero, NAME is passed as
the LIBRARY_NAME parameter to builtin_function when declaring BUILTIN_NAME.
- If NONANSI_P is nonzero, the name NAME is treated as a non-ANSI name; if
- NORETURN_P is nonzero, the function is marked as non-returning.
+ If NONANSI_P is nonzero, the name NAME is treated as a non-ANSI name;
+ ATTRS is the tree list representing the builtin's function attributes.
Returns the declaration of BUILTIN_NAME, if any, otherwise
the declaration of NAME. Does not declare NAME if flag_no_builtin,
or if NONANSI_P and flag_no_nonansi_builtin. */
static tree
builtin_function_2 (builtin_name, name, builtin_type, type, function_code,
- class, library_name_p, nonansi_p, noreturn_p)
+ class, library_name_p, nonansi_p, attrs)
const char *builtin_name;
const char *name;
tree builtin_type;
@@ -2994,31 +3669,23 @@ builtin_function_2 (builtin_name, name, builtin_type, type, function_code,
enum built_in_class class;
int library_name_p;
int nonansi_p;
- int noreturn_p;
+ tree attrs;
{
tree bdecl = NULL_TREE;
tree decl = NULL_TREE;
if (builtin_name != 0)
{
bdecl = builtin_function (builtin_name, builtin_type, function_code,
- class, library_name_p ? name : NULL);
- if (noreturn_p)
- {
- TREE_THIS_VOLATILE (bdecl) = 1;
- TREE_SIDE_EFFECTS (bdecl) = 1;
- }
+ class, library_name_p ? name : NULL,
+ attrs);
}
if (name != 0 && !flag_no_builtin && !builtin_function_disabled_p (name)
&& !(nonansi_p && flag_no_nonansi_builtin))
{
- decl = builtin_function (name, type, function_code, class, NULL);
+ decl = builtin_function (name, type, function_code, class, NULL,
+ attrs);
if (nonansi_p)
DECL_BUILT_IN_NONANSI (decl) = 1;
- if (noreturn_p)
- {
- TREE_THIS_VOLATILE (decl) = 1;
- TREE_SIDE_EFFECTS (decl) = 1;
- }
}
return (bdecl != 0 ? bdecl : decl);
}
@@ -3054,34 +3721,6 @@ c_promoting_integer_type_p (t)
}
}
-/* Given a type, apply default promotions wrt unnamed function arguments
- and return the new type. Return NULL_TREE if no change. */
-/* ??? There is a function of the same name in the C++ front end that
- does something similar, but is more thorough and does not return NULL
- if no change. We could perhaps share code, but it would make the
- self_promoting_type property harder to identify. */
-
-tree
-simple_type_promotes_to (type)
- tree type;
-{
- if (TYPE_MAIN_VARIANT (type) == float_type_node)
- return double_type_node;
-
- if (c_promoting_integer_type_p (type))
- {
- /* Traditionally, unsignedness is preserved in default promotions.
- Also preserve unsignedness if not really getting any wider. */
- if (TREE_UNSIGNED (type)
- && (flag_traditional
- || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
- return unsigned_type_node;
- return integer_type_node;
- }
-
- return NULL_TREE;
-}
-
/* Return 1 if PARMS specifies a fixed number of parameters
and none of their types is affected by default promotions. */
@@ -3122,6 +3761,81 @@ strip_array_types (type)
return type;
}
+static tree expand_unordered_cmp PARAMS ((tree, tree, enum tree_code,
+ enum tree_code));
+
+/* Expand a call to an unordered comparison function such as
+ __builtin_isgreater(). FUNCTION is the function's declaration and
+ PARAMS a list of the values passed. For __builtin_isunordered(),
+ UNORDERED_CODE is UNORDERED_EXPR and ORDERED_CODE is NOP_EXPR. In
+ other cases, UNORDERED_CODE and ORDERED_CODE are comparison codes
+ that give the opposite of the desired result. UNORDERED_CODE is
+ used for modes that can hold NaNs and ORDERED_CODE is used for the
+ rest. */
+
+static tree
+expand_unordered_cmp (function, params, unordered_code, ordered_code)
+ tree function, params;
+ enum tree_code unordered_code, ordered_code;
+{
+ tree arg0, arg1, type;
+ enum tree_code code0, code1;
+
+ /* Check that we have exactly two arguments. */
+ if (params == 0 || TREE_CHAIN (params) == 0)
+ {
+ error ("too few arguments to function `%s'",
+ IDENTIFIER_POINTER (DECL_NAME (function)));
+ return error_mark_node;
+ }
+ else if (TREE_CHAIN (TREE_CHAIN (params)) != 0)
+ {
+ error ("too many arguments to function `%s'",
+ IDENTIFIER_POINTER (DECL_NAME (function)));
+ return error_mark_node;
+ }
+
+ arg0 = TREE_VALUE (params);
+ arg1 = TREE_VALUE (TREE_CHAIN (params));
+
+ code0 = TREE_CODE (TREE_TYPE (arg0));
+ code1 = TREE_CODE (TREE_TYPE (arg1));
+
+ /* Make sure that the arguments have a common type of REAL. */
+ type = 0;
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ type = common_type (TREE_TYPE (arg0), TREE_TYPE (arg1));
+
+ if (type == 0 || TREE_CODE (type) != REAL_TYPE)
+ {
+ error ("non-floating-point argument to function `%s'",
+ IDENTIFIER_POINTER (DECL_NAME (function)));
+ return error_mark_node;
+ }
+
+ if (unordered_code == UNORDERED_EXPR)
+ {
+ if (MODE_HAS_NANS (TYPE_MODE (type)))
+ return build_binary_op (unordered_code,
+ convert (type, arg0),
+ convert (type, arg1),
+ 0);
+ else
+ return integer_zero_node;
+ }
+
+ return build_unary_op (TRUTH_NOT_EXPR,
+ build_binary_op (MODE_HAS_NANS (TYPE_MODE (type))
+ ? unordered_code
+ : ordered_code,
+ convert (type, arg0),
+ convert (type, arg1),
+ 0),
+ 0);
+}
+
+
/* Recognize certain built-in functions so we can make tree-codes
other than CALL_EXPR. We do this when it enables fold-const.c
to do something useful. */
@@ -3134,8 +3848,6 @@ tree
expand_tree_builtin (function, params, coerced_params)
tree function, params, coerced_params;
{
- enum tree_code code;
-
if (DECL_BUILT_IN_CLASS (function) != BUILT_IN_NORMAL)
return NULL_TREE;
@@ -3174,72 +3886,22 @@ expand_tree_builtin (function, params, coerced_params)
return build_unary_op (IMAGPART_EXPR, TREE_VALUE (coerced_params), 0);
case BUILT_IN_ISGREATER:
- if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
- code = UNLE_EXPR;
- else
- code = LE_EXPR;
- goto unordered_cmp;
+ return expand_unordered_cmp (function, params, UNLE_EXPR, LE_EXPR);
case BUILT_IN_ISGREATEREQUAL:
- if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
- code = UNLT_EXPR;
- else
- code = LT_EXPR;
- goto unordered_cmp;
+ return expand_unordered_cmp (function, params, UNLT_EXPR, LT_EXPR);
case BUILT_IN_ISLESS:
- if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
- code = UNGE_EXPR;
- else
- code = GE_EXPR;
- goto unordered_cmp;
+ return expand_unordered_cmp (function, params, UNGE_EXPR, GE_EXPR);
case BUILT_IN_ISLESSEQUAL:
- if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
- code = UNGT_EXPR;
- else
- code = GT_EXPR;
- goto unordered_cmp;
+ return expand_unordered_cmp (function, params, UNGT_EXPR, GT_EXPR);
case BUILT_IN_ISLESSGREATER:
- if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
- code = UNEQ_EXPR;
- else
- code = EQ_EXPR;
- goto unordered_cmp;
+ return expand_unordered_cmp (function, params, UNEQ_EXPR, EQ_EXPR);
case BUILT_IN_ISUNORDERED:
- if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
- return integer_zero_node;
- code = UNORDERED_EXPR;
- goto unordered_cmp;
-
- unordered_cmp:
- {
- tree arg0, arg1;
-
- if (params == 0
- || TREE_CHAIN (params) == 0)
- {
- error ("too few arguments to function `%s'",
- IDENTIFIER_POINTER (DECL_NAME (function)));
- return error_mark_node;
- }
- else if (TREE_CHAIN (TREE_CHAIN (params)) != 0)
- {
- error ("too many arguments to function `%s'",
- IDENTIFIER_POINTER (DECL_NAME (function)));
- return error_mark_node;
- }
-
- arg0 = TREE_VALUE (params);
- arg1 = TREE_VALUE (TREE_CHAIN (params));
- arg0 = build_binary_op (code, arg0, arg1, 0);
- if (code != UNORDERED_EXPR)
- arg0 = build_unary_op (TRUTH_NOT_EXPR, arg0, 0);
- return arg0;
- }
- break;
+ return expand_unordered_cmp (function, params, UNORDERED_EXPR, NOP_EXPR);
default:
break;
@@ -3248,7 +3910,7 @@ expand_tree_builtin (function, params, coerced_params)
return NULL_TREE;
}
-/* Returns non-zero if CODE is the code for a statement. */
+/* Returns nonzero if CODE is the code for a statement. */
int
statement_code_p (code)
@@ -3566,41 +4228,6 @@ finish_label_address_expr (label)
return result;
}
-/* Mark P (a stmt_tree) for GC. The use of a `void *' for the
- parameter allows this function to be used as a GC-marking
- function. */
-
-void
-mark_stmt_tree (p)
- void *p;
-{
- stmt_tree st = (stmt_tree) p;
-
- ggc_mark_tree (st->x_last_stmt);
- ggc_mark_tree (st->x_last_expr_type);
-}
-
-/* Mark LD for GC. */
-
-void
-c_mark_lang_decl (c)
- struct c_lang_decl *c ATTRIBUTE_UNUSED;
-{
-}
-
-/* Mark F for GC. */
-
-void
-mark_c_language_function (f)
- struct language_function *f;
-{
- if (!f)
- return;
-
- mark_stmt_tree (&f->x_stmt_tree);
- ggc_mark_tree (f->x_scope_stmt_stack);
-}
-
/* Hook used by expand_expr to expand language-specific tree codes. */
rtx
@@ -3608,7 +4235,7 @@ c_expand_expr (exp, target, tmode, modifier)
tree exp;
rtx target;
enum machine_mode tmode;
- enum expand_modifier modifier;
+ int modifier; /* Actually enum_modifier. */
{
switch (TREE_CODE (exp))
{
@@ -3749,7 +4376,7 @@ c_safe_from_p (target, exp)
/* Hook used by unsafe_for_reeval to handle language-specific tree codes. */
int
-c_unsafe_for_reeval (exp)
+c_common_unsafe_for_reeval (exp)
tree exp;
{
/* Statement expressions may not be reevaluated, likewise compound
@@ -3774,56 +4401,6 @@ c_staticp (exp)
return 0;
}
-/* Tree code classes. */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
-
-static const char c_tree_code_type[] = {
- 'x',
-#include "c-common.def"
-};
-#undef DEFTREECODE
-
-/* Table indexed by tree code giving number of expression
- operands beyond the fixed part of the node structure.
- Not used for types or decls. */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
-
-static const int c_tree_code_length[] = {
- 0,
-#include "c-common.def"
-};
-#undef DEFTREECODE
-
-/* Names of tree components.
- Used for printing out the tree and error messages. */
-#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
-
-static const char *const c_tree_code_name[] = {
- "@@dummy",
-#include "c-common.def"
-};
-#undef DEFTREECODE
-
-/* Adds the tree codes specific to the C front end to the list of all
- tree codes. */
-
-void
-add_c_tree_codes ()
-{
- memcpy (tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE,
- c_tree_code_type,
- (int) LAST_C_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE);
- memcpy (tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE,
- c_tree_code_length,
- (LAST_C_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE) * sizeof (int));
- memcpy (tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE,
- c_tree_code_name,
- (LAST_C_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
- lang_unsafe_for_reeval = c_unsafe_for_reeval;
-}
-
#define CALLED_AS_BUILT_IN(NODE) \
(!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
@@ -4012,7 +4589,7 @@ c_expand_builtin_printf (arglist, target, tmode, modifier, ignore, unlocked)
memcpy (newstr, TREE_STRING_POINTER (stripped_string), newlen - 1);
newstr[newlen - 1] = 0;
- arglist = combine_strings (build_string (newlen, newstr));
+ arglist = fix_string_type (build_string (newlen, newstr));
arglist = build_tree_list (NULL_TREE, arglist);
fn = fn_puts;
}
@@ -4151,112 +4728,449 @@ boolean_increment (code, arg)
return val;
}
-/* Handle C and C++ default attributes. */
+/* Define NAME with value TYPE precision. */
+static void
+builtin_define_type_precision (name, type)
+ const char *name;
+ tree type;
+{
+ builtin_define_with_int_value (name, TYPE_PRECISION (type));
+}
-enum built_in_attribute
+/* Define the float.h constants for TYPE using NAME_PREFIX and FP_SUFFIX. */
+static void
+builtin_define_float_constants (name_prefix, fp_suffix, type)
+ const char *name_prefix;
+ const char *fp_suffix;
+ tree type;
{
-#define DEF_ATTR_NULL_TREE(ENUM) ENUM,
-#define DEF_ATTR_INT(ENUM, VALUE) ENUM,
-#define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
-#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
-#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No entry needed in enum. */
-#include "builtin-attrs.def"
-#undef DEF_ATTR_NULL_TREE
-#undef DEF_ATTR_INT
-#undef DEF_ATTR_IDENT
-#undef DEF_ATTR_TREE_LIST
-#undef DEF_FN_ATTR
- ATTR_LAST
-};
+ /* Used to convert radix-based values to base 10 values in several cases.
+
+ In the max_exp -> max_10_exp conversion for 128-bit IEEE, we need at
+ least 6 significant digits for correct results. Using the fraction
+ formed by (log(2)*1e6)/(log(10)*1e6) overflows a 32-bit integer as an
+ intermediate; perhaps someone can find a better approximation, in the
+ mean time, I suspect using doubles won't harm the bootstrap here. */
+
+ const double log10_2 = .30102999566398119521;
+ double log10_b;
+ const struct real_format *fmt;
+
+ char name[64], buf[128];
+ int dig, min_10_exp, max_10_exp;
+ int decimal_dig;
+
+ fmt = real_format_for_mode[TYPE_MODE (type) - QFmode];
+
+ /* The radix of the exponent representation. */
+ if (type == float_type_node)
+ builtin_define_with_int_value ("__FLT_RADIX__", fmt->b);
+ log10_b = log10_2 * fmt->log2_b;
+
+ /* The number of radix digits, p, in the floating-point significand. */
+ sprintf (name, "__%s_MANT_DIG__", name_prefix);
+ builtin_define_with_int_value (name, fmt->p);
+
+ /* The number of decimal digits, q, such that any floating-point number
+ with q decimal digits can be rounded into a floating-point number with
+ p radix b digits and back again without change to the q decimal digits,
+
+ p log10 b if b is a power of 10
+ floor((p - 1) log10 b) otherwise
+ */
+ dig = (fmt->p - 1) * log10_b;
+ sprintf (name, "__%s_DIG__", name_prefix);
+ builtin_define_with_int_value (name, dig);
+
+ /* The minimum negative int x such that b**(x-1) is a normalized float. */
+ sprintf (name, "__%s_MIN_EXP__", name_prefix);
+ sprintf (buf, "(%d)", fmt->emin);
+ builtin_define_with_value (name, buf, 0);
+
+ /* The minimum negative int x such that 10**x is a normalized float,
+
+ ceil (log10 (b ** (emin - 1)))
+ = ceil (log10 (b) * (emin - 1))
+
+ Recall that emin is negative, so the integer truncation calculates
+ the ceiling, not the floor, in this case. */
+ min_10_exp = (fmt->emin - 1) * log10_b;
+ sprintf (name, "__%s_MIN_10_EXP__", name_prefix);
+ sprintf (buf, "(%d)", min_10_exp);
+ builtin_define_with_value (name, buf, 0);
+
+ /* The maximum int x such that b**(x-1) is a representable float. */
+ sprintf (name, "__%s_MAX_EXP__", name_prefix);
+ builtin_define_with_int_value (name, fmt->emax);
+
+ /* The maximum int x such that 10**x is in the range of representable
+ finite floating-point numbers,
+
+ floor (log10((1 - b**-p) * b**emax))
+ = floor (log10(1 - b**-p) + log10(b**emax))
+ = floor (log10(1 - b**-p) + log10(b)*emax)
+
+ The safest thing to do here is to just compute this number. But since
+ we don't link cc1 with libm, we cannot. We could implement log10 here
+ a series expansion, but that seems too much effort because:
+
+ Note that the first term, for all extant p, is a number exceedingly close
+ to zero, but slightly negative. Note that the second term is an integer
+ scaling an irrational number, and that because of the floor we are only
+ interested in its integral portion.
+
+ In order for the first term to have any effect on the integral portion
+ of the second term, the second term has to be exceedingly close to an
+ integer itself (e.g. 123.000000000001 or something). Getting a result
+ that close to an integer requires that the irrational multiplicand have
+ a long series of zeros in its expansion, which doesn't occur in the
+ first 20 digits or so of log10(b).
+
+ Hand-waving aside, crunching all of the sets of constants above by hand
+ does not yield a case for which the first term is significant, which
+ in the end is all that matters. */
+ max_10_exp = fmt->emax * log10_b;
+ sprintf (name, "__%s_MAX_10_EXP__", name_prefix);
+ builtin_define_with_int_value (name, max_10_exp);
+
+ /* The number of decimal digits, n, such that any floating-point number
+ can be rounded to n decimal digits and back again without change to
+ the value.
+
+ p * log10(b) if b is a power of 10
+ ceil(1 + p * log10(b)) otherwise
+
+ The only macro we care about is this number for the widest supported
+ floating type, but we want this value for rendering constants below. */
+ {
+ double d_decimal_dig = 1 + fmt->p * log10_b;
+ decimal_dig = d_decimal_dig;
+ if (decimal_dig < d_decimal_dig)
+ decimal_dig++;
+ }
+ if (type == long_double_type_node)
+ builtin_define_with_int_value ("__DECIMAL_DIG__", decimal_dig);
+
+ /* Since, for the supported formats, B is always a power of 2, we
+ construct the following numbers directly as a hexadecimal
+ constants. */
+
+ /* The maximum representable finite floating-point number,
+ (1 - b**-p) * b**emax */
+ {
+ int i, n;
+ char *p;
+
+ strcpy (buf, "0x0.");
+ n = fmt->p * fmt->log2_b;
+ for (i = 0, p = buf + 4; i + 3 < n; i += 4)
+ *p++ = 'f';
+ if (i < n)
+ *p++ = "08ce"[n - i];
+ sprintf (p, "p%d", fmt->emax * fmt->log2_b);
+ }
+ sprintf (name, "__%s_MAX__", name_prefix);
+ builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
+
+ /* The minimum normalized positive floating-point number,
+ b**(emin-1). */
+ sprintf (name, "__%s_MIN__", name_prefix);
+ sprintf (buf, "0x1p%d", (fmt->emin - 1) * fmt->log2_b);
+ builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
+
+ /* The difference between 1 and the least value greater than 1 that is
+ representable in the given floating point type, b**(1-p). */
+ sprintf (name, "__%s_EPSILON__", name_prefix);
+ sprintf (buf, "0x1p%d", (1 - fmt->p) * fmt->log2_b);
+ builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
+
+ /* For C++ std::numeric_limits<T>::denorm_min. The minimum denormalized
+ positive floating-point number, b**(emin-p). Zero for formats that
+ don't support denormals. */
+ sprintf (name, "__%s_DENORM_MIN__", name_prefix);
+ if (fmt->has_denorm)
+ {
+ sprintf (buf, "0x1p%d", (fmt->emin - fmt->p) * fmt->log2_b);
+ builtin_define_with_hex_fp_value (name, type, decimal_dig,
+ buf, fp_suffix);
+ }
+ else
+ {
+ sprintf (buf, "0.0%s", fp_suffix);
+ builtin_define_with_value (name, buf, 0);
+ }
+}
-static tree built_in_attributes[(int) ATTR_LAST];
+/* Hook that registers front end and target-specific built-ins. */
+void
+cb_register_builtins (pfile)
+ cpp_reader *pfile;
+{
+ /* -undef turns off target-specific built-ins. */
+ if (flag_undef)
+ return;
-static bool c_attrs_initialized = false;
+ if (c_language == clk_cplusplus)
+ {
+ if (SUPPORTS_ONE_ONLY)
+ cpp_define (pfile, "__GXX_WEAK__=1");
+ else
+ cpp_define (pfile, "__GXX_WEAK__=0");
+ if (warn_deprecated)
+ cpp_define (pfile, "__DEPRECATED");
+ }
+ if (flag_exceptions)
+ cpp_define (pfile, "__EXCEPTIONS");
+
+ /* represents the C++ ABI version, always defined so it can be used while
+ preprocessing C and assembler. */
+ cpp_define (pfile, "__GXX_ABI_VERSION=102");
+
+ /* libgcc needs to know this. */
+ if (USING_SJLJ_EXCEPTIONS)
+ cpp_define (pfile, "__USING_SJLJ_EXCEPTIONS__");
+
+ /* stddef.h needs to know these. */
+ builtin_define_with_value ("__SIZE_TYPE__", SIZE_TYPE, 0);
+ builtin_define_with_value ("__PTRDIFF_TYPE__", PTRDIFF_TYPE, 0);
+ builtin_define_with_value ("__WCHAR_TYPE__", MODIFIED_WCHAR_TYPE, 0);
+ builtin_define_with_value ("__WINT_TYPE__", WINT_TYPE, 0);
+
+ /* limits.h needs to know these. */
+ builtin_define_type_max ("__SCHAR_MAX__", signed_char_type_node, 0);
+ builtin_define_type_max ("__SHRT_MAX__", short_integer_type_node, 0);
+ builtin_define_type_max ("__INT_MAX__", integer_type_node, 0);
+ builtin_define_type_max ("__LONG_MAX__", long_integer_type_node, 1);
+ builtin_define_type_max ("__LONG_LONG_MAX__", long_long_integer_type_node, 2);
+ builtin_define_type_max ("__WCHAR_MAX__", wchar_type_node, 0);
+
+ builtin_define_type_precision ("__CHAR_BIT__", char_type_node);
+
+ /* float.h needs to know these. */
+
+ builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
+ TARGET_FLT_EVAL_METHOD);
+
+ builtin_define_float_constants ("FLT", "F", float_type_node);
+ builtin_define_float_constants ("DBL", "", double_type_node);
+ builtin_define_float_constants ("LDBL", "L", long_double_type_node);
+
+ /* For use in assembly language. */
+ builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0);
+ builtin_define_with_value ("__USER_LABEL_PREFIX__", user_label_prefix, 0);
+
+ /* Misc. */
+ builtin_define_with_value ("__VERSION__", version_string, 1);
+
+ /* Other target-independent built-ins determined by command-line
+ options. */
+ if (optimize_size)
+ cpp_define (pfile, "__OPTIMIZE_SIZE__");
+ if (optimize)
+ cpp_define (pfile, "__OPTIMIZE__");
+
+ if (flag_hosted)
+ cpp_define (pfile, "__STDC_HOSTED__=1");
+ else
+ cpp_define (pfile, "__STDC_HOSTED__=0");
+
+ if (fast_math_flags_set_p ())
+ cpp_define (pfile, "__FAST_MATH__");
+ if (flag_really_no_inline)
+ cpp_define (pfile, "__NO_INLINE__");
+ if (flag_signaling_nans)
+ cpp_define (pfile, "__SUPPORT_SNAN__");
+ if (flag_finite_math_only)
+ cpp_define (pfile, "__FINITE_MATH_ONLY__=1");
+ else
+ cpp_define (pfile, "__FINITE_MATH_ONLY__=0");
-static void c_init_attributes PARAMS ((void));
+ if (flag_iso)
+ cpp_define (pfile, "__STRICT_ANSI__");
-/* Common initialization before parsing options. */
-void
-c_common_init_options (lang)
- enum c_language_kind lang;
-{
- c_language = lang;
- parse_in = cpp_create_reader (lang == clk_c ? CLK_GNUC89:
- lang == clk_cplusplus ? CLK_GNUCXX: CLK_OBJC);
+ if (!flag_signed_char)
+ cpp_define (pfile, "__CHAR_UNSIGNED__");
- /* Mark as "unspecified" (see c_common_post_options). */
- flag_bounds_check = -1;
+ if (c_language == clk_cplusplus && TREE_UNSIGNED (wchar_type_node))
+ cpp_define (pfile, "__WCHAR_UNSIGNED__");
+
+ /* Make the choice of ObjC runtime visible to source code. */
+ if (flag_objc && flag_next_runtime)
+ cpp_define (pfile, "__NEXT_RUNTIME__");
+
+ /* A straightforward target hook doesn't work, because of problems
+ linking that hook's body when part of non-C front ends. */
+# define preprocessing_asm_p() (cpp_get_options (pfile)->lang == CLK_ASM)
+# define preprocessing_trad_p() (cpp_get_options (pfile)->traditional)
+# define builtin_define(TXT) cpp_define (pfile, TXT)
+# define builtin_assert(TXT) cpp_assert (pfile, TXT)
+ TARGET_CPU_CPP_BUILTINS ();
+ TARGET_OS_CPP_BUILTINS ();
}
-/* Post-switch processing. */
+/* Pass an object-like macro. If it doesn't lie in the user's
+ namespace, defines it unconditionally. Otherwise define a version
+ with two leading underscores, and another version with two leading
+ and trailing underscores, and define the original only if an ISO
+ standard was not nominated.
+
+ e.g. passing "unix" defines "__unix", "__unix__" and possibly
+ "unix". Passing "_mips" defines "__mips", "__mips__" and possibly
+ "_mips". */
void
-c_common_post_options ()
+builtin_define_std (macro)
+ const char *macro;
{
- cpp_post_options (parse_in);
-
- flag_inline_trees = 1;
+ size_t len = strlen (macro);
+ char *buff = alloca (len + 5);
+ char *p = buff + 2;
+ char *q = p + len;
+
+ /* prepend __ (or maybe just _) if in user's namespace. */
+ memcpy (p, macro, len + 1);
+ if (!( *p == '_' && (p[1] == '_' || ISUPPER (p[1]))))
+ {
+ if (*p != '_')
+ *--p = '_';
+ if (p[1] != '_')
+ *--p = '_';
+ }
+ cpp_define (parse_in, p);
- /* Use tree inlining if possible. Function instrumentation is only
- done in the RTL level, so we disable tree inlining. */
- if (! flag_instrument_function_entry_exit)
+ /* If it was in user's namespace... */
+ if (p != buff + 2)
{
- if (!flag_no_inline)
- flag_no_inline = 1;
- if (flag_inline_functions)
- {
- flag_inline_trees = 2;
- flag_inline_functions = 0;
- }
+ /* Define the macro with leading and following __. */
+ if (q[-1] != '_')
+ *q++ = '_';
+ if (q[-2] != '_')
+ *q++ = '_';
+ *q = '\0';
+ cpp_define (parse_in, p);
+
+ /* Finally, define the original macro if permitted. */
+ if (!flag_iso)
+ cpp_define (parse_in, macro);
}
+}
+
+/* Pass an object-like macro and a value to define it to. The third
+ parameter says whether or not to turn the value into a string
+ constant. */
+static void
+builtin_define_with_value (macro, expansion, is_str)
+ const char *macro;
+ const char *expansion;
+ int is_str;
+{
+ char *buf;
+ size_t mlen = strlen (macro);
+ size_t elen = strlen (expansion);
+ size_t extra = 2; /* space for an = and a NUL */
- /* If still "unspecified", make it match -fbounded-pointers. */
- if (flag_bounds_check == -1)
- flag_bounds_check = flag_bounded_pointers;
-
- /* Special format checking options don't work without -Wformat; warn if
- they are used. */
- if (warn_format_y2k && !warn_format)
- warning ("-Wformat-y2k ignored without -Wformat");
- if (warn_format_extra_args && !warn_format)
- warning ("-Wformat-extra-args ignored without -Wformat");
- if (warn_format_nonliteral && !warn_format)
- warning ("-Wformat-nonliteral ignored without -Wformat");
- if (warn_format_security && !warn_format)
- warning ("-Wformat-security ignored without -Wformat");
- if (warn_missing_format_attribute && !warn_format)
- warning ("-Wmissing-format-attribute ignored without -Wformat");
-
- /* If an error has occurred in cpplib, note it so we fail
- immediately. */
- errorcount += cpp_errors (parse_in);
+ if (is_str)
+ extra += 2; /* space for two quote marks */
+
+ buf = alloca (mlen + elen + extra);
+ if (is_str)
+ sprintf (buf, "%s=\"%s\"", macro, expansion);
+ else
+ sprintf (buf, "%s=%s", macro, expansion);
+
+ cpp_define (parse_in, buf);
}
-/* Front end initialization common to C, ObjC and C++. */
-const char *
-c_common_init (filename)
- const char *filename;
+/* Pass an object-like macro and an integer value to define it to. */
+static void
+builtin_define_with_int_value (macro, value)
+ const char *macro;
+ HOST_WIDE_INT value;
{
- /* Do this before initializing pragmas, as then cpplib's hash table
- has been set up. */
- filename = init_c_lex (filename);
+ char *buf;
+ size_t mlen = strlen (macro);
+ size_t vlen = 18;
+ size_t extra = 2; /* space for = and NUL. */
- init_pragma ();
+ buf = alloca (mlen + vlen + extra);
+ memcpy (buf, macro, mlen);
+ buf[mlen] = '=';
+ sprintf (buf + mlen + 1, HOST_WIDE_INT_PRINT_DEC, value);
- if (!c_attrs_initialized)
- c_init_attributes ();
+ cpp_define (parse_in, buf);
+}
- return filename;
+/* Pass an object-like macro a hexadecimal floating-point value. */
+static void
+builtin_define_with_hex_fp_value (macro, type, digits, hex_str, fp_suffix)
+ const char *macro;
+ tree type ATTRIBUTE_UNUSED;
+ int digits;
+ const char *hex_str;
+ const char *fp_suffix;
+{
+ REAL_VALUE_TYPE real;
+ char dec_str[64], buf[256];
+
+ /* Hex values are really cool and convenient, except that they're
+ not supported in strict ISO C90 mode. First, the "p-" sequence
+ is not valid as part of a preprocessor number. Second, we get a
+ pedwarn from the preprocessor, which has no context, so we can't
+ suppress the warning with __extension__.
+
+ So instead what we do is construct the number in hex (because
+ it's easy to get the exact correct value), parse it as a real,
+ then print it back out as decimal. */
+
+ real_from_string (&real, hex_str);
+ real_to_decimal (dec_str, &real, sizeof (dec_str), digits, 0);
+
+ sprintf (buf, "%s=%s%s", macro, dec_str, fp_suffix);
+ cpp_define (parse_in, buf);
}
-/* Common finish hook for the C, ObjC and C++ front ends. */
-void
-c_common_finish ()
+/* Define MAX for TYPE based on the precision of the type. IS_LONG is
+ 1 for type "long" and 2 for "long long". We have to handle
+ unsigned types, since wchar_t might be unsigned. */
+
+static void
+builtin_define_type_max (macro, type, is_long)
+ const char *macro;
+ tree type;
+ int is_long;
{
- cpp_finish (parse_in);
+ static const char *const values[]
+ = { "127", "255",
+ "32767", "65535",
+ "2147483647", "4294967295",
+ "9223372036854775807", "18446744073709551615",
+ "170141183460469231731687303715884105727",
+ "340282366920938463463374607431768211455" };
+ static const char *const suffixes[] = { "", "U", "L", "UL", "LL", "ULL" };
+
+ const char *value, *suffix;
+ char *buf;
+ size_t idx;
+
+ /* Pre-rendering the values mean we don't have to futz with printing a
+ multi-word decimal value. There are also a very limited number of
+ precisions that we support, so it's really a waste of time. */
+ switch (TYPE_PRECISION (type))
+ {
+ case 8: idx = 0; break;
+ case 16: idx = 2; break;
+ case 32: idx = 4; break;
+ case 64: idx = 6; break;
+ case 128: idx = 8; break;
+ default: abort ();
+ }
+
+ value = values[idx + TREE_UNSIGNED (type)];
+ suffix = suffixes[is_long * 2 + TREE_UNSIGNED (type)];
- /* For performance, avoid tearing down cpplib's internal structures.
- Call cpp_errors () instead of cpp_destroy (). */
- errorcount += cpp_errors (parse_in);
+ buf = alloca (strlen (macro) + 1 + strlen (value) + strlen (suffix) + 1);
+ sprintf (buf, "%s=%s%s", macro, value, suffix);
+
+ cpp_define (parse_in, buf);
}
static void
@@ -4281,7 +5195,6 @@ c_init_attributes ()
#undef DEF_ATTR_IDENT
#undef DEF_ATTR_TREE_LIST
#undef DEF_FN_ATTR
- ggc_add_tree_root (built_in_attributes, (int) ATTR_LAST);
c_attrs_initialized = true;
}
@@ -4325,3 +5238,1447 @@ shadow_warning (msgid, name, decl)
"shadowed declaration is here");
}
+/* Attribute handlers common to C front ends. */
+
+/* Handle a "packed" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_packed_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags;
+ bool *no_add_attrs;
+{
+ tree *type = NULL;
+ if (DECL_P (*node))
+ {
+ if (TREE_CODE (*node) == TYPE_DECL)
+ type = &TREE_TYPE (*node);
+ }
+ else
+ type = node;
+
+ if (type)
+ {
+ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ *type = build_type_copy (*type);
+ TYPE_PACKED (*type) = 1;
+ }
+ else if (TREE_CODE (*node) == FIELD_DECL)
+ DECL_PACKED (*node) = 1;
+ /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
+ used for DECL_REGISTER. It wouldn't mean anything anyway. */
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "nocommon" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_nocommon_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ if (TREE_CODE (*node) == VAR_DECL)
+ DECL_COMMON (*node) = 0;
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "common" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_common_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ if (TREE_CODE (*node) == VAR_DECL)
+ DECL_COMMON (*node) = 1;
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "noreturn" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_noreturn_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree type = TREE_TYPE (*node);
+
+ /* See FIXME comment in c_common_attribute_table. */
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ TREE_THIS_VOLATILE (*node) = 1;
+ else if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+ TREE_TYPE (*node)
+ = build_pointer_type
+ (build_type_variant (TREE_TYPE (type),
+ TREE_READONLY (TREE_TYPE (type)), 1));
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "noinline" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_noinline_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ DECL_UNINLINABLE (*node) = 1;
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "always_inline" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_always_inline_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ {
+ /* Do nothing else, just set the attribute. We'll get at
+ it later with lookup_attribute. */
+ }
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "used" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_used_attribute (pnode, name, args, flags, no_add_attrs)
+ tree *pnode;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree node = *pnode;
+
+ if (TREE_CODE (node) == FUNCTION_DECL
+ || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node)))
+ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (node))
+ = TREE_USED (node) = 1;
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "unused" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_unused_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags;
+ bool *no_add_attrs;
+{
+ if (DECL_P (*node))
+ {
+ tree decl = *node;
+
+ if (TREE_CODE (decl) == PARM_DECL
+ || TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == LABEL_DECL
+ || TREE_CODE (decl) == TYPE_DECL)
+ TREE_USED (decl) = 1;
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ }
+ else
+ {
+ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ *node = build_type_copy (*node);
+ TREE_USED (*node) = 1;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "const" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_const_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree type = TREE_TYPE (*node);
+
+ /* See FIXME comment on noreturn in c_common_attribute_table. */
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ TREE_READONLY (*node) = 1;
+ else if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+ TREE_TYPE (*node)
+ = build_pointer_type
+ (build_type_variant (TREE_TYPE (type), 1,
+ TREE_THIS_VOLATILE (TREE_TYPE (type))));
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "transparent_union" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_transparent_union_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags;
+ bool *no_add_attrs;
+{
+ tree decl = NULL_TREE;
+ tree *type = NULL;
+ int is_type = 0;
+
+ if (DECL_P (*node))
+ {
+ decl = *node;
+ type = &TREE_TYPE (decl);
+ is_type = TREE_CODE (*node) == TYPE_DECL;
+ }
+ else if (TYPE_P (*node))
+ type = node, is_type = 1;
+
+ if (is_type
+ && TREE_CODE (*type) == UNION_TYPE
+ && (decl == 0
+ || (TYPE_FIELDS (*type) != 0
+ && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))))
+ {
+ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ *type = build_type_copy (*type);
+ TYPE_TRANSPARENT_UNION (*type) = 1;
+ }
+ else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
+ && TREE_CODE (*type) == UNION_TYPE
+ && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))
+ DECL_TRANSPARENT_UNION (decl) = 1;
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "constructor" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_constructor_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree decl = *node;
+ tree type = TREE_TYPE (decl);
+
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && TREE_CODE (type) == FUNCTION_TYPE
+ && decl_function_context (decl) == 0)
+ {
+ DECL_STATIC_CONSTRUCTOR (decl) = 1;
+ TREE_USED (decl) = 1;
+ }
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "destructor" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_destructor_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree decl = *node;
+ tree type = TREE_TYPE (decl);
+
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && TREE_CODE (type) == FUNCTION_TYPE
+ && decl_function_context (decl) == 0)
+ {
+ DECL_STATIC_DESTRUCTOR (decl) = 1;
+ TREE_USED (decl) = 1;
+ }
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "mode" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_mode_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree type = *node;
+
+ *no_add_attrs = true;
+
+ if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ else
+ {
+ int j;
+ const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
+ int len = strlen (p);
+ enum machine_mode mode = VOIDmode;
+ tree typefm;
+
+ if (len > 4 && p[0] == '_' && p[1] == '_'
+ && p[len - 1] == '_' && p[len - 2] == '_')
+ {
+ char *newp = (char *) alloca (len - 1);
+
+ strcpy (newp, &p[2]);
+ newp[len - 4] = '\0';
+ p = newp;
+ }
+
+ /* Change this type to have a type with the specified mode.
+ First check for the special modes. */
+ if (! strcmp (p, "byte"))
+ mode = byte_mode;
+ else if (!strcmp (p, "word"))
+ mode = word_mode;
+ else if (! strcmp (p, "pointer"))
+ mode = ptr_mode;
+ else
+ for (j = 0; j < NUM_MACHINE_MODES; j++)
+ if (!strcmp (p, GET_MODE_NAME (j)))
+ mode = (enum machine_mode) j;
+
+ if (mode == VOIDmode)
+ error ("unknown machine mode `%s'", p);
+ else if (0 == (typefm = (*lang_hooks.types.type_for_mode)
+ (mode, TREE_UNSIGNED (type))))
+ error ("no data type for mode `%s'", p);
+ else
+ {
+ /* If this is a vector, make sure we either have hardware
+ support, or we can emulate it. */
+ if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+ && !vector_mode_valid_p (mode))
+ {
+ error ("unable to emulate '%s'", GET_MODE_NAME (mode));
+ return NULL_TREE;
+ }
+
+ *node = typefm;
+ /* No need to layout the type here. The caller should do this. */
+ }
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "section" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_section_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name ATTRIBUTE_UNUSED;
+ tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree decl = *node;
+
+ if (targetm.have_named_sections)
+ {
+ if ((TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == VAR_DECL)
+ && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
+ {
+ if (TREE_CODE (decl) == VAR_DECL
+ && current_function_decl != NULL_TREE
+ && ! TREE_STATIC (decl))
+ {
+ error_with_decl (decl,
+ "section attribute cannot be specified for local variables");
+ *no_add_attrs = true;
+ }
+
+ /* The decl may have already been given a section attribute
+ from a previous declaration. Ensure they match. */
+ else if (DECL_SECTION_NAME (decl) != NULL_TREE
+ && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
+ TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
+ {
+ error_with_decl (*node,
+ "section of `%s' conflicts with previous declaration");
+ *no_add_attrs = true;
+ }
+ else
+ DECL_SECTION_NAME (decl) = TREE_VALUE (args);
+ }
+ else
+ {
+ error_with_decl (*node,
+ "section attribute not allowed for `%s'");
+ *no_add_attrs = true;
+ }
+ }
+ else
+ {
+ error_with_decl (*node,
+ "section attributes are not supported for this target");
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "aligned" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_aligned_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name ATTRIBUTE_UNUSED;
+ tree args;
+ int flags;
+ bool *no_add_attrs;
+{
+ tree decl = NULL_TREE;
+ tree *type = NULL;
+ int is_type = 0;
+ tree align_expr = (args ? TREE_VALUE (args)
+ : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
+ int i;
+
+ if (DECL_P (*node))
+ {
+ decl = *node;
+ type = &TREE_TYPE (decl);
+ is_type = TREE_CODE (*node) == TYPE_DECL;
+ }
+ else if (TYPE_P (*node))
+ type = node, is_type = 1;
+
+ /* Strip any NOPs of any kind. */
+ while (TREE_CODE (align_expr) == NOP_EXPR
+ || TREE_CODE (align_expr) == CONVERT_EXPR
+ || TREE_CODE (align_expr) == NON_LVALUE_EXPR)
+ align_expr = TREE_OPERAND (align_expr, 0);
+
+ if (TREE_CODE (align_expr) != INTEGER_CST)
+ {
+ error ("requested alignment is not a constant");
+ *no_add_attrs = true;
+ }
+ else if ((i = tree_log2 (align_expr)) == -1)
+ {
+ error ("requested alignment is not a power of 2");
+ *no_add_attrs = true;
+ }
+ else if (i > HOST_BITS_PER_INT - 2)
+ {
+ error ("requested alignment is too large");
+ *no_add_attrs = true;
+ }
+ else if (is_type)
+ {
+ /* If we have a TYPE_DECL, then copy the type, so that we
+ don't accidentally modify a builtin type. See pushdecl. */
+ if (decl && TREE_TYPE (decl) != error_mark_node
+ && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
+ {
+ tree tt = TREE_TYPE (decl);
+ *type = build_type_copy (*type);
+ DECL_ORIGINAL_TYPE (decl) = tt;
+ TYPE_NAME (*type) = decl;
+ TREE_USED (*type) = TREE_USED (decl);
+ TREE_TYPE (decl) = *type;
+ }
+ else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ *type = build_type_copy (*type);
+
+ TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT;
+ TYPE_USER_ALIGN (*type) = 1;
+ }
+ else if (TREE_CODE (decl) != VAR_DECL
+ && TREE_CODE (decl) != FIELD_DECL)
+ {
+ error_with_decl (decl,
+ "alignment may not be specified for `%s'");
+ *no_add_attrs = true;
+ }
+ else
+ {
+ DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
+ DECL_USER_ALIGN (decl) = 1;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "weak" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_weak_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name ATTRIBUTE_UNUSED;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs ATTRIBUTE_UNUSED;
+{
+ declare_weak (*node);
+
+ return NULL_TREE;
+}
+
+/* Handle an "alias" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_alias_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree decl = *node;
+
+ if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
+ || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))
+ {
+ error_with_decl (decl,
+ "`%s' defined both normally and as an alias");
+ *no_add_attrs = true;
+ }
+ else if (decl_function_context (decl) == 0)
+ {
+ tree id;
+
+ id = TREE_VALUE (args);
+ if (TREE_CODE (id) != STRING_CST)
+ {
+ error ("alias arg not a string");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ id = get_identifier (TREE_STRING_POINTER (id));
+ /* This counts as a use of the object pointed to. */
+ TREE_USED (id) = 1;
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ DECL_INITIAL (decl) = error_mark_node;
+ else
+ DECL_EXTERNAL (decl) = 0;
+ }
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle an "visibility" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_visibility_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree decl = *node;
+
+ if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl))
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else
+ {
+ tree id;
+
+ id = TREE_VALUE (args);
+ if (TREE_CODE (id) != STRING_CST)
+ {
+ error ("visibility arg not a string");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ if (strcmp (TREE_STRING_POINTER (id), "hidden")
+ && strcmp (TREE_STRING_POINTER (id), "protected")
+ && strcmp (TREE_STRING_POINTER (id), "internal")
+ && strcmp (TREE_STRING_POINTER (id), "default"))
+ {
+ error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle an "tls_model" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_tls_model_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree decl = *node;
+
+ if (! DECL_THREAD_LOCAL (decl))
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else
+ {
+ tree id;
+
+ id = TREE_VALUE (args);
+ if (TREE_CODE (id) != STRING_CST)
+ {
+ error ("tls_model arg not a string");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ if (strcmp (TREE_STRING_POINTER (id), "local-exec")
+ && strcmp (TREE_STRING_POINTER (id), "initial-exec")
+ && strcmp (TREE_STRING_POINTER (id), "local-dynamic")
+ && strcmp (TREE_STRING_POINTER (id), "global-dynamic"))
+ {
+ error ("tls_model arg must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\"");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "no_instrument_function" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_no_instrument_function_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree decl = *node;
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ error_with_decl (decl,
+ "`%s' attribute applies only to functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else if (DECL_INITIAL (decl))
+ {
+ error_with_decl (decl,
+ "can't set `%s' attribute after definition",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else
+ DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
+
+ return NULL_TREE;
+}
+
+/* Handle a "malloc" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_malloc_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ DECL_IS_MALLOC (*node) = 1;
+ /* ??? TODO: Support types. */
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "no_limit_stack" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_no_limit_stack_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree decl = *node;
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ error_with_decl (decl,
+ "`%s' attribute applies only to functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else if (DECL_INITIAL (decl))
+ {
+ error_with_decl (decl,
+ "can't set `%s' attribute after definition",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else
+ DECL_NO_LIMIT_STACK (decl) = 1;
+
+ return NULL_TREE;
+}
+
+/* Handle a "pure" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_pure_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ DECL_IS_PURE (*node) = 1;
+ /* ??? TODO: Support types. */
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "cleanup" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_cleanup_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree decl = *node;
+ tree cleanup_id, cleanup_decl;
+
+ /* ??? Could perhaps support cleanups on TREE_STATIC, much like we do
+ for global destructors in C++. This requires infrastructure that
+ we don't have generically at the moment. It's also not a feature
+ we'd be missing too much, since we do have attribute constructor. */
+ if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ /* Verify that the argument is a function in scope. */
+ /* ??? We could support pointers to functions here as well, if
+ that was considered desirable. */
+ cleanup_id = TREE_VALUE (args);
+ if (TREE_CODE (cleanup_id) != IDENTIFIER_NODE)
+ {
+ error ("cleanup arg not an identifier");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ cleanup_decl = lookup_name (cleanup_id);
+ if (!cleanup_decl || TREE_CODE (cleanup_decl) != FUNCTION_DECL)
+ {
+ error ("cleanup arg not a function");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ /* That the function has proper type is checked with the
+ eventual call to build_function_call. */
+
+ return NULL_TREE;
+}
+
+/* Handle a "deprecated" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_deprecated_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags;
+ bool *no_add_attrs;
+{
+ tree type = NULL_TREE;
+ int warn = 0;
+ const char *what = NULL;
+
+ if (DECL_P (*node))
+ {
+ tree decl = *node;
+ type = TREE_TYPE (decl);
+
+ if (TREE_CODE (decl) == TYPE_DECL
+ || TREE_CODE (decl) == PARM_DECL
+ || TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == FIELD_DECL)
+ TREE_DEPRECATED (decl) = 1;
+ else
+ warn = 1;
+ }
+ else if (TYPE_P (*node))
+ {
+ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ *node = build_type_copy (*node);
+ TREE_DEPRECATED (*node) = 1;
+ type = *node;
+ }
+ else
+ warn = 1;
+
+ if (warn)
+ {
+ *no_add_attrs = true;
+ if (type && TYPE_NAME (type))
+ {
+ if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
+ what = IDENTIFIER_POINTER (TYPE_NAME (*node));
+ else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ && DECL_NAME (TYPE_NAME (type)))
+ what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+ }
+ if (what)
+ warning ("`%s' attribute ignored for `%s'",
+ IDENTIFIER_POINTER (name), what);
+ else
+ warning ("`%s' attribute ignored",
+ IDENTIFIER_POINTER (name));
+ }
+
+ return NULL_TREE;
+}
+
+/* Keep a list of vector type nodes we created in handle_vector_size_attribute,
+ to prevent us from duplicating type nodes unnecessarily.
+ The normal mechanism to prevent duplicates is to use type_hash_canon, but
+ since we want to distinguish types that are essentially identical (except
+ for their debug representation), we use a local list here. */
+static GTY(()) tree vector_type_node_list = 0;
+
+/* Handle a "vector_size" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_vector_size_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ unsigned HOST_WIDE_INT vecsize, nunits;
+ enum machine_mode mode, orig_mode, new_mode;
+ tree type = *node, new_type = NULL_TREE;
+ tree type_list_node;
+
+ *no_add_attrs = true;
+
+ if (! host_integerp (TREE_VALUE (args), 1))
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ return NULL_TREE;
+ }
+
+ /* Get the vector size (in bytes). */
+ vecsize = tree_low_cst (TREE_VALUE (args), 1);
+
+ /* We need to provide for vector pointers, vector arrays, and
+ functions returning vectors. For example:
+
+ __attribute__((vector_size(16))) short *foo;
+
+ In this case, the mode is SI, but the type being modified is
+ HI, so we need to look further. */
+
+ while (POINTER_TYPE_P (type)
+ || TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+
+ /* Get the mode of the type being modified. */
+ orig_mode = TYPE_MODE (type);
+
+ if (TREE_CODE (type) == RECORD_TYPE
+ || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT
+ && GET_MODE_CLASS (orig_mode) != MODE_INT)
+ || ! host_integerp (TYPE_SIZE_UNIT (type), 1))
+ {
+ error ("invalid vector type for attribute `%s'",
+ IDENTIFIER_POINTER (name));
+ return NULL_TREE;
+ }
+
+ /* Calculate how many units fit in the vector. */
+ nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+
+ /* Find a suitably sized vector. */
+ new_mode = VOIDmode;
+ for (mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_mode) == MODE_INT
+ ? MODE_VECTOR_INT
+ : MODE_VECTOR_FLOAT);
+ mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ if (vecsize == GET_MODE_SIZE (mode)
+ && nunits == (unsigned HOST_WIDE_INT) GET_MODE_NUNITS (mode))
+ {
+ new_mode = mode;
+ break;
+ }
+
+ if (new_mode == VOIDmode)
+ {
+ error ("no vector mode with the size and type specified could be found");
+ return NULL_TREE;
+ }
+
+ for (type_list_node = vector_type_node_list; type_list_node;
+ type_list_node = TREE_CHAIN (type_list_node))
+ {
+ tree other_type = TREE_VALUE (type_list_node);
+ tree record = TYPE_DEBUG_REPRESENTATION_TYPE (other_type);
+ tree fields = TYPE_FIELDS (record);
+ tree field_type = TREE_TYPE (fields);
+ tree array_type = TREE_TYPE (field_type);
+ if (TREE_CODE (fields) != FIELD_DECL
+ || TREE_CODE (field_type) != ARRAY_TYPE)
+ abort ();
+
+ if (TYPE_MODE (other_type) == mode && type == array_type)
+ {
+ new_type = other_type;
+ break;
+ }
+ }
+
+ if (new_type == NULL_TREE)
+ {
+ tree index, array, rt, list_node;
+
+ new_type = (*lang_hooks.types.type_for_mode) (new_mode,
+ TREE_UNSIGNED (type));
+
+ if (!new_type)
+ {
+ error ("no vector mode with the size and type specified could be found");
+ return NULL_TREE;
+ }
+
+ new_type = build_type_copy (new_type);
+
+ /* If this is a vector, make sure we either have hardware
+ support, or we can emulate it. */
+ if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+ && !vector_mode_valid_p (mode))
+ {
+ error ("unable to emulate '%s'", GET_MODE_NAME (mode));
+ return NULL_TREE;
+ }
+
+ /* Set the debug information here, because this is the only
+ place where we know the underlying type for a vector made
+ with vector_size. For debugging purposes we pretend a vector
+ is an array within a structure. */
+ index = build_int_2 (TYPE_VECTOR_SUBPARTS (new_type) - 1, 0);
+ array = build_array_type (type, build_index_type (index));
+ rt = make_node (RECORD_TYPE);
+
+ TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);
+ DECL_CONTEXT (TYPE_FIELDS (rt)) = rt;
+ layout_type (rt);
+ TYPE_DEBUG_REPRESENTATION_TYPE (new_type) = rt;
+
+ list_node = build_tree_list (NULL, new_type);
+ TREE_CHAIN (list_node) = vector_type_node_list;
+ vector_type_node_list = list_node;
+ }
+
+ /* Build back pointers if needed. */
+ *node = vector_size_helper (*node, new_type);
+
+ return NULL_TREE;
+}
+
+/* HACK. GROSS. This is absolutely disgusting. I wish there was a
+ better way.
+
+ If we requested a pointer to a vector, build up the pointers that
+ we stripped off while looking for the inner type. Similarly for
+ return values from functions.
+
+ The argument "type" is the top of the chain, and "bottom" is the
+ new type which we will point to. */
+
+static tree
+vector_size_helper (type, bottom)
+ tree type, bottom;
+{
+ tree inner, outer;
+
+ if (POINTER_TYPE_P (type))
+ {
+ inner = vector_size_helper (TREE_TYPE (type), bottom);
+ outer = build_pointer_type (inner);
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ inner = vector_size_helper (TREE_TYPE (type), bottom);
+ outer = build_array_type (inner, TYPE_VALUES (type));
+ }
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ inner = vector_size_helper (TREE_TYPE (type), bottom);
+ outer = build_function_type (inner, TYPE_VALUES (type));
+ }
+ else
+ return bottom;
+
+ TREE_READONLY (outer) = TREE_READONLY (type);
+ TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type);
+
+ return outer;
+}
+
+/* Handle the "nonnull" attribute. */
+static tree
+handle_nonnull_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name ATTRIBUTE_UNUSED;
+ tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ tree type = *node;
+ unsigned HOST_WIDE_INT attr_arg_num;
+
+ /* If no arguments are specified, all pointer arguments should be
+ non-null. Veryify a full prototype is given so that the arguments
+ will have the correct types when we actually check them later. */
+ if (! args)
+ {
+ if (! TYPE_ARG_TYPES (type))
+ {
+ error ("nonnull attribute without arguments on a non-prototype");
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+ }
+
+ /* Argument list specified. Verify that each argument number references
+ a pointer argument. */
+ for (attr_arg_num = 1; args; args = TREE_CHAIN (args))
+ {
+ tree argument;
+ unsigned HOST_WIDE_INT arg_num, ck_num;
+
+ if (! get_nonnull_operand (TREE_VALUE (args), &arg_num))
+ {
+ error ("nonnull argument has invalid operand number (arg %lu)",
+ (unsigned long) attr_arg_num);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ argument = TYPE_ARG_TYPES (type);
+ if (argument)
+ {
+ for (ck_num = 1; ; ck_num++)
+ {
+ if (! argument || ck_num == arg_num)
+ break;
+ argument = TREE_CHAIN (argument);
+ }
+
+ if (! argument
+ || TREE_CODE (TREE_VALUE (argument)) == VOID_TYPE)
+ {
+ error ("nonnull argument with out-of-range operand number (arg %lu, operand %lu)",
+ (unsigned long) attr_arg_num, (unsigned long) arg_num);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE)
+ {
+ error ("nonnull argument references non-pointer operand (arg %lu, operand %lu)",
+ (unsigned long) attr_arg_num, (unsigned long) arg_num);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ }
+ }
+
+ return NULL_TREE;
+}
+
+/* Check the argument list of a function call for null in argument slots
+ that are marked as requiring a non-null pointer argument. */
+
+static void
+check_function_nonnull (attrs, params)
+ tree attrs;
+ tree params;
+{
+ tree a, args, param;
+ int param_num;
+
+ for (a = attrs; a; a = TREE_CHAIN (a))
+ {
+ if (is_attribute_p ("nonnull", TREE_PURPOSE (a)))
+ {
+ args = TREE_VALUE (a);
+
+ /* Walk the argument list. If we encounter an argument number we
+ should check for non-null, do it. If the attribute has no args,
+ then every pointer argument is checked (in which case the check
+ for pointer type is done in check_nonnull_arg). */
+ for (param = params, param_num = 1; ;
+ param_num++, param = TREE_CHAIN (param))
+ {
+ if (! param)
+ break;
+ if (! args || nonnull_check_p (args, param_num))
+ check_function_arguments_recurse (check_nonnull_arg, NULL,
+ TREE_VALUE (param),
+ param_num);
+ }
+ }
+ }
+}
+
+/* Helper for check_function_nonnull; given a list of operands which
+ must be non-null in ARGS, determine if operand PARAM_NUM should be
+ checked. */
+
+static bool
+nonnull_check_p (args, param_num)
+ tree args;
+ unsigned HOST_WIDE_INT param_num;
+{
+ unsigned HOST_WIDE_INT arg_num;
+
+ for (; args; args = TREE_CHAIN (args))
+ {
+ if (! get_nonnull_operand (TREE_VALUE (args), &arg_num))
+ abort ();
+
+ if (arg_num == param_num)
+ return true;
+ }
+ return false;
+}
+
+/* Check that the function argument PARAM (which is operand number
+ PARAM_NUM) is non-null. This is called by check_function_nonnull
+ via check_function_arguments_recurse. */
+
+static void
+check_nonnull_arg (ctx, param, param_num)
+ void *ctx ATTRIBUTE_UNUSED;
+ tree param;
+ unsigned HOST_WIDE_INT param_num;
+{
+ /* Just skip checking the argument if it's not a pointer. This can
+ happen if the "nonnull" attribute was given without an operand
+ list (which means to check every pointer argument). */
+
+ if (TREE_CODE (TREE_TYPE (param)) != POINTER_TYPE)
+ return;
+
+ if (integer_zerop (param))
+ warning ("null argument where non-null required (arg %lu)",
+ (unsigned long) param_num);
+}
+
+/* Helper for nonnull attribute handling; fetch the operand number
+ from the attribute argument list. */
+
+static bool
+get_nonnull_operand (arg_num_expr, valp)
+ tree arg_num_expr;
+ unsigned HOST_WIDE_INT *valp;
+{
+ /* Strip any conversions from the arg number and verify they
+ are constants. */
+ while (TREE_CODE (arg_num_expr) == NOP_EXPR
+ || TREE_CODE (arg_num_expr) == CONVERT_EXPR
+ || TREE_CODE (arg_num_expr) == NON_LVALUE_EXPR)
+ arg_num_expr = TREE_OPERAND (arg_num_expr, 0);
+
+ if (TREE_CODE (arg_num_expr) != INTEGER_CST
+ || TREE_INT_CST_HIGH (arg_num_expr) != 0)
+ return false;
+
+ *valp = TREE_INT_CST_LOW (arg_num_expr);
+ return true;
+}
+
+/* Handle a "nothrow" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_nothrow_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ TREE_NOTHROW (*node) = 1;
+ /* ??? TODO: Support types. */
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Check for valid arguments being passed to a function. */
+void
+check_function_arguments (attrs, params)
+ tree attrs;
+ tree params;
+{
+ /* Check for null being passed in a pointer argument that must be
+ non-null. We also need to do this if format checking is enabled. */
+
+ if (warn_nonnull)
+ check_function_nonnull (attrs, params);
+
+ /* Check for errors in format strings. */
+
+ if (warn_format)
+ check_function_format (NULL, attrs, params);
+}
+
+/* Generic argument checking recursion routine. PARAM is the argument to
+ be checked. PARAM_NUM is the number of the argument. CALLBACK is invoked
+ once the argument is resolved. CTX is context for the callback. */
+void
+check_function_arguments_recurse (callback, ctx, param, param_num)
+ void (*callback) PARAMS ((void *, tree, unsigned HOST_WIDE_INT));
+ void *ctx;
+ tree param;
+ unsigned HOST_WIDE_INT param_num;
+{
+ if (TREE_CODE (param) == NOP_EXPR)
+ {
+ /* Strip coercion. */
+ check_function_arguments_recurse (callback, ctx,
+ TREE_OPERAND (param, 0), param_num);
+ return;
+ }
+
+ if (TREE_CODE (param) == CALL_EXPR)
+ {
+ tree type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (param, 0)));
+ tree attrs;
+ bool found_format_arg = false;
+
+ /* See if this is a call to a known internationalization function
+ that modifies a format arg. Such a function may have multiple
+ format_arg attributes (for example, ngettext). */
+
+ for (attrs = TYPE_ATTRIBUTES (type);
+ attrs;
+ attrs = TREE_CHAIN (attrs))
+ if (is_attribute_p ("format_arg", TREE_PURPOSE (attrs)))
+ {
+ tree inner_args;
+ tree format_num_expr;
+ int format_num;
+ int i;
+
+ /* Extract the argument number, which was previously checked
+ to be valid. */
+ format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
+ 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
+ || TREE_INT_CST_HIGH (format_num_expr) != 0)
+ abort ();
+
+ format_num = TREE_INT_CST_LOW (format_num_expr);
+
+ for (inner_args = TREE_OPERAND (param, 1), i = 1;
+ inner_args != 0;
+ inner_args = TREE_CHAIN (inner_args), i++)
+ if (i == format_num)
+ {
+ check_function_arguments_recurse (callback, ctx,
+ TREE_VALUE (inner_args),
+ param_num);
+ found_format_arg = true;
+ break;
+ }
+ }
+
+ /* If we found a format_arg attribute and did a recursive check,
+ we are done with checking this argument. Otherwise, we continue
+ and this will be considered a non-literal. */
+ if (found_format_arg)
+ return;
+ }
+
+ if (TREE_CODE (param) == COND_EXPR)
+ {
+ /* Check both halves of the conditional expression. */
+ check_function_arguments_recurse (callback, ctx,
+ TREE_OPERAND (param, 1), param_num);
+ check_function_arguments_recurse (callback, ctx,
+ TREE_OPERAND (param, 2), param_num);
+ return;
+ }
+
+ (*callback) (ctx, param, param_num);
+}
+
+#include "gt-c-common.h"
diff --git a/contrib/gcc/c-common.def b/contrib/gcc/c-common.def
index 7ad9e38..802238a 100644
--- a/contrib/gcc/c-common.def
+++ b/contrib/gcc/c-common.def
@@ -23,7 +23,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
/* Tree nodes relevant to both C and C++. These were originally in
-cp-tree.def in the cp subdir. */
+cp-tree.def in the cp subdir. */
/* A node to remember a source position. */
DEFTREECODE (SRCLOC, "srcloc", 'x', 2)
@@ -33,55 +33,55 @@ DEFTREECODE (ARROW_EXPR, "arrow_expr", 'e', 1)
DEFTREECODE (ALIGNOF_EXPR, "alignof_expr", '1', 1)
/* Used to represent an expression statement. Use `EXPR_STMT_EXPR' to
- obtain the expression. */
+ obtain the expression. */
DEFTREECODE (EXPR_STMT, "expr_stmt", 'e', 1)
/* Used to represent a brace-enclosed block. The operand is
- COMPOUND_BODY. */
+ COMPOUND_BODY. */
DEFTREECODE (COMPOUND_STMT, "compound_stmt", 'e', 1)
/* Used to represent a local declaration. The operand is
- DECL_STMT_DECL. */
+ DECL_STMT_DECL. */
DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 1)
/* Represents an 'if' statement. The operands are IF_COND,
- THEN_CLAUSE, and ELSE_CLAUSE, respectively. */
+ THEN_CLAUSE, and ELSE_CLAUSE, respectively. */
DEFTREECODE (IF_STMT, "if_stmt", 'e', 3)
/* Used to represent a `for' statement. The operands are
- FOR_INIT_STMT, FOR_COND, FOR_EXPR, and FOR_BODY, respectively. */
+ FOR_INIT_STMT, FOR_COND, FOR_EXPR, and FOR_BODY, respectively. */
DEFTREECODE (FOR_STMT, "for_stmt", 'e', 4)
/* Used to represent a 'while' statement. The operands are WHILE_COND
- and WHILE_BODY, respectively. */
+ and WHILE_BODY, respectively. */
DEFTREECODE (WHILE_STMT, "while_stmt", 'e', 2)
/* Used to represent a 'do' statement. The operands are DO_BODY and
- DO_COND, respectively. */
+ DO_COND, respectively. */
DEFTREECODE (DO_STMT, "do_stmt", 'e', 2)
/* Used to represent a 'return' statement. The operand is
- RETURN_EXPR. */
+ RETURN_STMT_EXPR. */
DEFTREECODE (RETURN_STMT, "return_stmt", 'e', 1)
-/* Used to represent a 'break' statement. */
+/* Used to represent a 'break' statement. */
DEFTREECODE (BREAK_STMT, "break_stmt", 'e', 0)
-/* Used to represent a 'continue' statement. */
+/* Used to represent a 'continue' statement. */
DEFTREECODE (CONTINUE_STMT, "continue_stmt", 'e', 0)
/* Used to represent a 'switch' statement. The operands are
- SWITCH_COND, SWITCH_BODY and SWITCH_TYPE, respectively. */
+ SWITCH_COND, SWITCH_BODY and SWITCH_TYPE, respectively. */
DEFTREECODE (SWITCH_STMT, "switch_stmt", 'e', 3)
-/* Used to represent a 'goto' statement. The operand is GOTO_DESTINATION. */
+/* Used to represent a 'goto' statement. The operand is GOTO_DESTINATION. */
DEFTREECODE (GOTO_STMT, "goto_stmt", 'e', 1)
/* Used to represent a 'label' statement. The operand is a LABEL_DECL
- and can be obtained through the macro LABEL_STMT_LABEL. */
+ and can be obtained through the macro LABEL_STMT_LABEL. */
DEFTREECODE (LABEL_STMT, "label_stmt", 'e', 1)
-/* Used to represent an inline assembly statement. */
+/* Used to represent an inline assembly statement. */
DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5)
/* A SCOPE_STMT marks the beginning or end of a scope. If
diff --git a/contrib/gcc/c-common.h b/contrib/gcc/c-common.h
index f5e4659..1f59ebd 100644
--- a/contrib/gcc/c-common.h
+++ b/contrib/gcc/c-common.h
@@ -43,7 +43,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
*/
/* Reserved identifiers. This is the union of all the keywords for C,
- C++, and Objective C. All the type modifiers have to be in one
+ C++, and Objective-C. All the type modifiers have to be in one
block at the beginning, because they are used as mask bits. There
are 27 type modifiers; if we add many more we will have to redesign
the mask mechanism. */
@@ -58,7 +58,7 @@ enum rid
RID_VOLATILE, RID_SIGNED, RID_AUTO, RID_RESTRICT,
/* C extensions */
- RID_BOUNDED, RID_UNBOUNDED, RID_COMPLEX,
+ RID_BOUNDED, RID_UNBOUNDED, RID_COMPLEX, RID_THREAD,
/* C++ */
RID_FRIEND, RID_VIRTUAL, RID_EXPLICIT, RID_EXPORT, RID_MUTABLE,
@@ -93,12 +93,7 @@ enum rid
/* casts */
RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
- /* alternate spellings */
- RID_AND, RID_AND_EQ, RID_NOT, RID_NOT_EQ,
- RID_OR, RID_OR_EQ, RID_XOR, RID_XOR_EQ,
- RID_BITAND, RID_BITOR, RID_COMPL,
-
- /* Objective C */
+ /* Objective-C */
RID_ID, RID_AT_ENCODE, RID_AT_END,
RID_AT_CLASS, RID_AT_ALIAS, RID_AT_DEFS,
RID_AT_PRIVATE, RID_AT_PROTECTED, RID_AT_PUBLIC,
@@ -179,10 +174,10 @@ enum c_tree_index
/* Identifier part common to the C front ends. Inherits from
tree_identifier, despite appearances. */
-struct c_common_identifier
+struct c_common_identifier GTY(())
{
struct tree_common common;
- struct cpp_hashnode node;
+ struct cpp_hashnode GTY ((skip (""))) node;
};
#define wchar_type_node c_global_trees[CTI_WCHAR_TYPE]
@@ -226,7 +221,7 @@ struct c_common_identifier
/* A node for `((void) 0)'. */
#define void_zero_node c_global_trees[CTI_VOID_ZERO]
-extern tree c_global_trees[CTI_MAX];
+extern GTY(()) tree c_global_trees[CTI_MAX];
/* Mark which labels are explicitly declared.
These may be shadowed, and may be referenced from nested functions. */
@@ -238,16 +233,14 @@ extern tree c_global_trees[CTI_MAX];
typedef enum c_language_kind
{
- clk_c, /* A dialect of C: K&R C, ANSI/ISO C89, C2000,
- etc. */
- clk_cplusplus, /* ANSI/ISO C++ */
- clk_objective_c /* Objective C */
+ clk_c = 0, /* A dialect of C: K&R C, ANSI/ISO C89, C2000, etc. */
+ clk_cplusplus /* ANSI/ISO C++ */
}
c_language_kind;
/* Information about a statement tree. */
-struct stmt_tree_s {
+struct stmt_tree_s GTY(()) {
/* The last statement added to the tree. */
tree x_last_stmt;
/* The type of the last expression statement. (This information is
@@ -255,12 +248,12 @@ struct stmt_tree_s {
tree x_last_expr_type;
/* The last filename we recorded. */
const char *x_last_expr_filename;
- /* In C++, Non-zero if we should treat statements as full
+ /* In C++, Nonzero if we should treat statements as full
expressions. In particular, this variable is no-zero if at the
end of a statement we should destroy any temporaries created
during that statement. Similarly, if, at the end of a block, we
should destroy any local variables in this block. Normally, this
- variable is non-zero, since those are the normal semantics of
+ variable is nonzero, since those are the normal semantics of
C++.
However, in order to represent aggregate initialization code as
@@ -277,7 +270,7 @@ typedef struct stmt_tree_s *stmt_tree;
/* Global state pertinent to the current function. Some C dialects
extend this structure with additional fields. */
-struct language_function {
+struct c_language_function GTY(()) {
/* While we are parsing the function, this contains information
about the statement-tree that we are building. */
struct stmt_tree_s x_stmt_tree;
@@ -316,11 +309,14 @@ extern int (*lang_statement_code_p) PARAMS ((enum tree_code));
extern void (*lang_expand_stmt) PARAMS ((tree));
extern void (*lang_expand_decl_stmt) PARAMS ((tree));
extern void (*lang_expand_function_end) PARAMS ((void));
+extern tree gettags PARAMS ((void));
/* Callback that determines if it's ok for a function to have no
noreturn attribute. */
extern int (*lang_missing_noreturn_ok_p) PARAMS ((tree));
+extern int yyparse PARAMS ((void));
+extern void free_parser_stacks PARAMS ((void));
extern stmt_tree current_stmt_tree PARAMS ((void));
extern tree *current_scope_stmt_stack PARAMS ((void));
@@ -336,7 +332,6 @@ extern tree walk_stmt_tree PARAMS ((tree *,
void *));
extern void prep_stmt PARAMS ((tree));
extern void expand_stmt PARAMS ((tree));
-extern void mark_stmt_tree PARAMS ((void *));
extern void shadow_warning PARAMS ((const char *,
tree, tree));
extern tree c_begin_if_stmt PARAMS ((void));
@@ -349,7 +344,7 @@ extern void c_finish_while_stmt_cond PARAMS ((tree, tree));
structure for FUNCTION_DECLs; all other DECLs have a NULL
DECL_LANG_SPECIFIC field. */
-struct c_lang_decl {
+struct c_lang_decl GTY(()) {
unsigned declared_inline : 1;
};
@@ -360,17 +355,35 @@ struct c_lang_decl {
#define DECL_NUM_STMTS(NODE) \
(FUNCTION_DECL_CHECK (NODE)->decl.u1.i)
-extern void c_mark_lang_decl PARAMS ((struct c_lang_decl *));
-
/* The variant of the C language being processed. Each C language
front-end defines this variable. */
extern c_language_kind c_language;
-/* Nonzero means give string constants the type `const char *', rather
- than `char *'. */
+/* Switches common to the C front ends. */
-extern int flag_const_strings;
+/* Nonzero if prepreprocessing only. */
+extern int flag_preprocess_only;
+
+/* Nonzero if an ISO standard was selected. It rejects macros in the
+ user's namespace. */
+extern int flag_iso;
+
+/* Nonzero whenever Objective-C functionality is being used. */
+extern int flag_objc;
+
+/* Nonzero if -undef was given. It suppresses target built-in macros
+ and assertions. */
+extern int flag_undef;
+
+/* Nonzero means don't recognize the non-ANSI builtin functions. */
+
+extern int flag_no_builtin;
+
+/* Nonzero means don't recognize the non-ANSI builtin functions.
+ -ansi sets this. */
+
+extern int flag_no_nonansi_builtin;
/* Nonzero means give `double' the same size as `float'. */
@@ -380,7 +393,91 @@ extern int flag_short_double;
extern int flag_short_wchar;
-/* Warn about *printf or *scanf format/argument anomalies. */
+/* Nonzero means allow Microsoft extensions without warnings or errors. */
+extern int flag_ms_extensions;
+
+/* Nonzero means don't recognize the keyword `asm'. */
+
+extern int flag_no_asm;
+
+/* Nonzero means give string constants the type `const char *', as mandated
+ by the standard. */
+
+extern int flag_const_strings;
+
+/* Nonzero means `$' can be in an identifier. */
+
+extern int dollars_in_ident;
+
+/* Nonzero means to treat bitfields as signed unless they say `unsigned'. */
+
+extern int flag_signed_bitfields;
+extern int explicit_flag_signed_bitfields;
+
+/* Nonzero means warn about pointer casts that can drop a type qualifier
+ from the pointer target type. */
+
+extern int warn_cast_qual;
+
+/* Warn about functions which might be candidates for format attributes. */
+
+extern int warn_missing_format_attribute;
+
+/* Nonzero means warn about sizeof(function) or addition/subtraction
+ of function pointers. */
+
+extern int warn_pointer_arith;
+
+/* Nonzero means warn for any global function def
+ without separate previous prototype decl. */
+
+extern int warn_missing_prototypes;
+
+/* Warn if adding () is suggested. */
+
+extern int warn_parentheses;
+
+/* Warn if initializer is not completely bracketed. */
+
+extern int warn_missing_braces;
+
+/* Warn about comparison of signed and unsigned values.
+ If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified. */
+
+extern int warn_sign_compare;
+
+/* Nonzero means warn about usage of long long when `-pedantic'. */
+
+extern int warn_long_long;
+
+/* Nonzero means warn about deprecated conversion from string constant to
+ `char *'. */
+
+extern int warn_write_strings;
+
+/* Nonzero means warn about multiple (redundant) decls for the same single
+ variable or function. */
+
+extern int warn_redundant_decls;
+
+/* Warn about testing equality of floating point numbers. */
+
+extern int warn_float_equal;
+
+/* Warn about a subscript that has type char. */
+
+extern int warn_char_subscripts;
+
+/* Warn if a type conversion is done that might have confusing results. */
+
+extern int warn_conversion;
+
+/* Warn about #pragma directives that are not recognized. */
+
+extern int warn_unknown_pragmas; /* Tri state variable. */
+
+/* Warn about format/argument anomalies in calls to formatted I/O functions
+ (*printf, *scanf, strftime, strfmon, etc.). */
extern int warn_format;
@@ -392,6 +489,10 @@ extern int warn_format_y2k;
extern int warn_format_extra_args;
+/* Warn about zero-length formats. */
+
+extern int warn_format_zero_length;
+
/* Warn about non-literal format arguments. */
extern int warn_format_nonliteral;
@@ -400,25 +501,19 @@ extern int warn_format_nonliteral;
extern int warn_format_security;
-/* Warn about possible violations of sequence point rules. */
-
-extern int warn_sequence_point;
-
-/* Warn about functions which might be candidates for format attributes. */
-extern int warn_missing_format_attribute;
+/* C/ObjC language option variables. */
-/* Nonzero means warn about sizeof (function) or addition/subtraction
- of function pointers. */
-extern int warn_pointer_arith;
+/* Nonzero means message about use of implicit function declarations;
+ 1 means warning; 2 means error. */
-/* Nonzero means to warn about compile-time division by zero. */
-extern int warn_div_by_zero;
+extern int mesg_implicit_function_declaration;
-/* Nonzero means do some things the same way PCC does. */
+/* Nonzero means allow type mismatches in conditional expressions;
+ just make their values `void'. */
-extern int flag_traditional;
+extern int flag_cond_mismatch;
/* Nonzero means enable C89 Amendment 1 features. */
@@ -428,7 +523,7 @@ extern int flag_isoc94;
extern int flag_isoc99;
-/* Nonzero means environment is hosted (i.e., not freestanding) */
+/* Nonzero means that we have builtin functions, and main is an int */
extern int flag_hosted;
@@ -437,27 +532,286 @@ extern int flag_hosted;
extern int flag_noniso_default_format_attributes;
-/* Nonzero means don't recognize any builtin functions. */
+/* Nonzero means warn when casting a function call to a type that does
+ not match the return type (e.g. (float)sqrt() or (anything*)malloc()
+ when there is no previous declaration of sqrt or malloc. */
-extern int flag_no_builtin;
+extern int warn_bad_function_cast;
-/* Nonzero means don't recognize the non-ANSI builtin functions.
- -ansi sets this. */
+/* Warn about traditional constructs whose meanings changed in ANSI C. */
-extern int flag_no_nonansi_builtin;
+extern int warn_traditional;
-/* Nonzero means warn about suggesting putting in ()'s. */
+/* Nonzero means warn for non-prototype function decls
+ or non-prototyped defs without previous prototype. */
-extern int warn_parentheses;
+extern int warn_strict_prototypes;
-/* Warn if a type conversion is done that might have confusing results. */
+/* Nonzero means warn for any global function def
+ without separate previous decl. */
-extern int warn_conversion;
+extern int warn_missing_declarations;
-/* Nonzero means warn about usage of long long,
- when `-pedantic' and not C99. */
+/* Nonzero means warn about extern declarations of objects not at
+ file-scope level and about *all* declarations of functions (whether
+ extern or static) not at file-scope level. Note that we exclude
+ implicit function declarations. To get warnings about those, use
+ -Wimplicit. */
-extern int warn_long_long;
+extern int warn_nested_externs;
+
+/* Warn if main is suspicious. */
+
+extern int warn_main;
+
+/* Nonzero means warn about possible violations of sequence point rules. */
+
+extern int warn_sequence_point;
+
+/* Nonzero means to warn about compile-time division by zero. */
+extern int warn_div_by_zero;
+
+/* Nonzero means warn about use of implicit int. */
+
+extern int warn_implicit_int;
+
+/* Warn about NULL being passed to argument slots marked as requiring
+ non-NULL. */
+
+extern int warn_nonnull;
+
+
+/* ObjC language option variables. */
+
+
+/* Open and close the file for outputting class declarations, if
+ requested (ObjC). */
+
+extern int flag_gen_declaration;
+
+/* Generate code for GNU or NeXT runtime environment. */
+
+extern int flag_next_runtime;
+
+/* Tells the compiler that this is a special run. Do not perform any
+ compiling, instead we are to test some platform dependent features
+ and output a C header file with appropriate definitions. */
+
+extern int print_struct_values;
+
+/* ???. Undocumented. */
+
+extern const char *constant_string_class_name;
+
+/* Warn if multiple methods are seen for the same selector, but with
+ different argument types. Performs the check on the whole selector
+ table at the end of compilation. */
+
+extern int warn_selector;
+
+/* Warn if a @selector() is found, and no method with that selector
+ has been previously declared. The check is done on each
+ @selector() as soon as it is found - so it warns about forward
+ declarations. */
+
+extern int warn_undeclared_selector;
+
+/* Warn if methods required by a protocol are not implemented in the
+ class adopting it. When turned off, methods inherited to that
+ class are also considered implemented. */
+
+extern int warn_protocol;
+
+
+/* C++ language option variables. */
+
+
+/* Nonzero means don't recognize any extension keywords. */
+
+extern int flag_no_gnu_keywords;
+
+/* Nonzero means do emit exported implementations of functions even if
+ they can be inlined. */
+
+extern int flag_implement_inlines;
+
+/* Nonzero means do emit exported implementations of templates, instead of
+ multiple static copies in each file that needs a definition. */
+
+extern int flag_external_templates;
+
+/* Nonzero means that the decision to emit or not emit the implementation of a
+ template depends on where the template is instantiated, rather than where
+ it is defined. */
+
+extern int flag_alt_external_templates;
+
+/* Nonzero means that implicit instantiations will be emitted if needed. */
+
+extern int flag_implicit_templates;
+
+/* Nonzero means that implicit instantiations of inline templates will be
+ emitted if needed, even if instantiations of non-inline templates
+ aren't. */
+
+extern int flag_implicit_inline_templates;
+
+/* Nonzero means generate separate instantiation control files and
+ juggle them at link time. */
+
+extern int flag_use_repository;
+
+/* Nonzero if we want to issue diagnostics that the standard says are not
+ required. */
+
+extern int flag_optional_diags;
+
+/* Nonzero means we should attempt to elide constructors when possible. */
+
+extern int flag_elide_constructors;
+
+/* Nonzero means that member functions defined in class scope are
+ inline by default. */
+
+extern int flag_default_inline;
+
+/* Controls whether compiler generates 'type descriptor' that give
+ run-time type information. */
+
+extern int flag_rtti;
+
+/* Nonzero if we want to conserve space in the .o files. We do this
+ by putting uninitialized data and runtime initialized data into
+ .common instead of .data at the expense of not flagging multiple
+ definitions. */
+
+extern int flag_conserve_space;
+
+/* Nonzero if we want to obey access control semantics. */
+
+extern int flag_access_control;
+
+/* Nonzero if we want to check the return value of new and avoid calling
+ constructors if it is a null pointer. */
+
+extern int flag_check_new;
+
+/* Nonzero if we want the new ISO rules for pushing a new scope for `for'
+ initialization variables.
+ 0: Old rules, set by -fno-for-scope.
+ 2: New ISO rules, set by -ffor-scope.
+ 1: Try to implement new ISO rules, but with backup compatibility
+ (and warnings). This is the default, for now. */
+
+extern int flag_new_for_scope;
+
+/* 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 flag_weak;
+
+/* Nonzero to use __cxa_atexit, rather than atexit, to register
+ destructors for local statics and global objects. */
+
+extern int flag_use_cxa_atexit;
+
+/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */
+
+extern int flag_vtable_gc;
+
+/* Nonzero means make the default pedwarns warnings instead of errors.
+ The value of this flag is ignored if -pedantic is specified. */
+
+extern int flag_permissive;
+
+/* Nonzero means to implement standard semantics for exception
+ specifications, calling unexpected if an exception is thrown that
+ doesn't match the specification. Zero means to treat them as
+ assertions and optimize accordingly, but not check them. */
+
+extern int flag_enforce_eh_specs;
+
+/* The version of the C++ ABI in use. The following values are
+ allowed:
+
+ 0: The version of the ABI believed most conformant with the
+ C++ ABI specification. This ABI may change as bugs are
+ discovered and fixed. Therefore, 0 will not necessarily
+ indicate the same ABI in different versions of G++.
+
+ 1: The version of the ABI first used in G++ 3.2.
+
+ Additional positive integers will be assigned as new versions of
+ the ABI become the default version of the ABI. */
+
+extern int flag_abi_version;
+
+/* Nonzero means warn about things that will change when compiling
+ with an ABI-compliant compiler. */
+
+extern int warn_abi;
+
+/* Nonzero means warn about implicit declarations. */
+
+extern int warn_implicit;
+
+/* Nonzero means warn when all ctors or dtors are private, and the class
+ has no friends. */
+
+extern int warn_ctor_dtor_privacy;
+
+/* Nonzero means warn in function declared in derived class has the
+ same name as a virtual in the base class, but fails to match the
+ type signature of any virtual function in the base class. */
+
+extern int warn_overloaded_virtual;
+
+/* Nonzero means warn when declaring a class that has a non virtual
+ destructor, when it really ought to have a virtual one. */
+
+extern int warn_nonvdtor;
+
+/* Nonzero means warn when the compiler will reorder code. */
+
+extern int warn_reorder;
+
+/* Nonzero means warn when synthesis behavior differs from Cfront's. */
+
+extern int warn_synth;
+
+/* Nonzero 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;
+
+/* Nonzero means warn when an old-style cast is used. */
+
+extern int warn_old_style_cast;
+
+/* Nonzero means warn when non-templatized friend functions are
+ declared within a template */
+
+extern int warn_nontemplate_friend;
+
+/* Nonzero means complain about deprecated features. */
+
+extern int warn_deprecated;
+
+/* Maximum template instantiation depth. This limit is rather
+ arbitrary, but it exists to limit the time it takes to notice
+ infinite template instantiations. */
+
+extern int max_tinst_depth;
/* Nonzero means the expression being parsed will never be evaluated.
This is a count, since unevaluated expressions can nest. */
@@ -484,6 +838,10 @@ extern int skip_evaluation;
what operator was specified for it. */
#define C_EXP_ORIGINAL_CODE(exp) ((enum tree_code) TREE_COMPLEXITY (exp))
+/* Attribute table common to the C front ends. */
+extern const struct attribute_spec c_common_attribute_table[];
+extern const struct attribute_spec c_common_format_attribute_table[];
+
/* Pointer to function to lazily generate the VAR_DECL for __FUNCTION__ etc.
ID is the identifier to use, NAME is the string.
TYPE_DEP indicates whether it depends on type of the function or not
@@ -501,6 +859,12 @@ extern const char *fname_as_string PARAMS ((int));
extern tree fname_decl PARAMS ((unsigned, tree));
extern const char *fname_string PARAMS ((unsigned));
+extern void check_function_arguments PARAMS ((tree, tree));
+extern void check_function_arguments_recurse PARAMS ((void (*) (void *,
+ tree,
+ unsigned HOST_WIDE_INT),
+ void *, tree,
+ unsigned HOST_WIDE_INT));
extern void check_function_format PARAMS ((int *, tree, tree));
extern void set_Wformat PARAMS ((int));
extern tree handle_format_attribute PARAMS ((tree *, tree, tree,
@@ -508,23 +872,34 @@ extern tree handle_format_attribute PARAMS ((tree *, tree, tree,
extern tree handle_format_arg_attribute PARAMS ((tree *, tree, tree,
int, bool *));
extern void c_common_insert_default_attributes PARAMS ((tree));
+extern int c_common_decode_option PARAMS ((int, char **));
+extern tree c_common_type_for_mode PARAMS ((enum machine_mode,
+ int));
+extern tree c_common_type_for_size PARAMS ((unsigned int, int));
+extern tree c_common_unsigned_type PARAMS ((tree));
+extern tree c_common_signed_type PARAMS ((tree));
+extern tree c_common_signed_or_unsigned_type PARAMS ((int, tree));
+extern tree c_common_truthvalue_conversion PARAMS ((tree));
extern void c_apply_type_quals_to_decl PARAMS ((int, tree));
-extern tree c_sizeof PARAMS ((tree));
-extern tree c_alignof PARAMS ((tree));
+extern tree c_sizeof_or_alignof_type PARAMS ((tree, enum tree_code, int));
extern tree c_alignof_expr PARAMS ((tree));
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PARAMS ((enum tree_code));
+#define my_friendly_assert(EXP, N) (void) \
+ (((EXP) == 0) ? (fancy_abort (__FILE__, __LINE__, __FUNCTION__), 0) : 0)
+
extern tree c_expand_expr_stmt PARAMS ((tree));
extern void c_expand_start_cond PARAMS ((tree, int, tree));
extern void c_finish_then PARAMS ((void));
extern void c_expand_start_else PARAMS ((void));
-extern void c_finish_else PARAMS ((void));
+extern void c_finish_else PARAMS ((void));
extern void c_expand_end_cond PARAMS ((void));
/* Validate the expression after `case' and apply default promotions. */
extern tree check_case_value PARAMS ((tree));
-/* Concatenate a list of STRING_CST nodes into one STRING_CST. */
-extern tree combine_strings PARAMS ((tree));
+extern tree fix_string_type PARAMS ((tree));
+struct varray_head_tag;
+extern tree combine_strings PARAMS ((struct varray_head_tag *));
extern void constant_expression_warning PARAMS ((tree));
extern tree convert_and_check PARAMS ((tree, tree));
extern void overflow_warning PARAMS ((tree));
@@ -533,6 +908,8 @@ extern void unsigned_conversion_warning PARAMS ((tree, tree));
/* Read the rest of the current #-directive line. */
extern char *get_directive_line PARAMS ((void));
#define GET_DIRECTIVE_LINE() get_directive_line ()
+#define c_sizeof(T) c_sizeof_or_alignof_type (T, SIZEOF_EXPR, 1)
+#define c_alignof(T) c_sizeof_or_alignof_type (T, ALIGNOF_EXPR, 1)
/* Subroutine of build_binary_op, used for comparison operations.
See if the operands have both been converted from subword integer types
@@ -554,13 +931,13 @@ extern void disable_builtin_function PARAMS ((const char *));
extern tree build_va_arg PARAMS ((tree, tree));
extern void c_common_init_options PARAMS ((enum c_language_kind));
-extern void c_common_post_options PARAMS ((void));
+extern bool c_common_post_options PARAMS ((void));
extern const char *c_common_init PARAMS ((const char *));
extern void c_common_finish PARAMS ((void));
+extern void c_common_parse_file PARAMS ((int));
extern HOST_WIDE_INT c_common_get_alias_set PARAMS ((tree));
extern bool c_promoting_integer_type_p PARAMS ((tree));
extern int self_promoting_args_p PARAMS ((tree));
-extern tree simple_type_promotes_to PARAMS ((tree));
extern tree strip_array_types PARAMS ((tree));
/* These macros provide convenient access to the various _STMT nodes. */
@@ -591,7 +968,7 @@ extern tree strip_array_types PARAMS ((tree));
/* RETURN_STMT accessors. These give the expression associated with a
return statement, and whether it should be ignored when expanding
(as opposed to inlining). */
-#define RETURN_EXPR(NODE) TREE_OPERAND (RETURN_STMT_CHECK (NODE), 0)
+#define RETURN_STMT_EXPR(NODE) TREE_OPERAND (RETURN_STMT_CHECK (NODE), 0)
/* EXPR_STMT accessor. This gives the expression associated with an
expression statement. */
@@ -721,7 +1098,7 @@ extern tree strip_array_types PARAMS ((tree));
#define STMT_LINENO(NODE) \
(TREE_COMPLEXITY ((NODE)))
-/* If non-zero, the STMT_LINENO for NODE is the line at which the
+/* If nonzero, the STMT_LINENO for NODE is the line at which the
function ended. */
#define STMT_LINENO_FOR_FN_P(NODE) \
(TREE_LANG_FLAG_2 ((NODE)))
@@ -744,7 +1121,6 @@ enum c_tree_code {
#undef DEFTREECODE
-extern void add_c_tree_codes PARAMS ((void));
extern void genrtl_do_pushlevel PARAMS ((void));
extern void genrtl_goto_stmt PARAMS ((tree));
extern void genrtl_expr_stmt PARAMS ((tree));
@@ -830,8 +1206,6 @@ extern tree boolean_increment PARAMS ((enum tree_code,
after entering or leaving a header file. */
extern void extract_interface_info PARAMS ((void));
-extern void mark_c_language_function PARAMS ((struct language_function *));
-
extern int case_compare PARAMS ((splay_tree_key,
splay_tree_key));
@@ -847,18 +1221,19 @@ extern tree finish_label_address_expr PARAMS ((tree));
different implementations. Used in c-common.c. */
extern tree lookup_label PARAMS ((tree));
-/* enum expand_modified is in expr.h, as is the macro below. */
-
-#ifdef QUEUED_VAR
-extern rtx c_expand_expr PARAMS ((tree, rtx, enum machine_mode,
- enum expand_modifier));
-#endif
+extern rtx c_expand_expr PARAMS ((tree, rtx,
+ enum machine_mode,
+ int));
extern int c_safe_from_p PARAMS ((rtx, tree));
extern int c_staticp PARAMS ((tree));
-extern int c_unsafe_for_reeval PARAMS ((tree));
+extern int c_common_unsafe_for_reeval PARAMS ((tree));
+
+extern const char *init_c_lex PARAMS ((const char *));
+
+extern void cb_register_builtins PARAMS ((cpp_reader *));
/* Information recorded about each file examined during compilation. */
@@ -872,4 +1247,6 @@ struct c_fileinfo
struct c_fileinfo *get_fileinfo PARAMS ((const char *));
extern void dump_time_statistics PARAMS ((void));
+extern int c_dump_tree PARAMS ((void *, tree));
+
#endif /* ! GCC_C_COMMON_H */
diff --git a/contrib/gcc/c-config-lang.in b/contrib/gcc/c-config-lang.in
new file mode 100644
index 0000000..c0a786f
--- /dev/null
+++ b/contrib/gcc/c-config-lang.in
@@ -0,0 +1,26 @@
+# Top level configure fragment for GNU C - C language.
+# Copyright (C) 1994, 1995, 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+#This file is part of GCC.
+
+#GCC is free software; you can redistribute it and/or modify
+#it under the terms of the GNU General Public License as published by
+#the Free Software Foundation; either version 2, or (at your option)
+#any later version.
+
+#GCC is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with GCC; see the file COPYING. If not, write to
+#the Free Software Foundation, 59 Temple Place - Suite 330,
+#Boston, MA 02111-1307, USA.
+
+# This file c-config-lang.c is a special pseudo config-lang.in file
+# for the language C. It has limited use, specifically to record the
+# files used by C that have garbage collection GTY macros in them
+# which therefore need to be scanned by gengtype.c.
+
+gtfiles="\$(srcdir)/c-lang.c \$(srcdir)/c-parse.in \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c \$(srcdir)/c-objc-common.c"
diff --git a/contrib/gcc/c-convert.c b/contrib/gcc/c-convert.c
index 947c79b..3634bbe 100644
--- a/contrib/gcc/c-convert.c
+++ b/contrib/gcc/c-convert.c
@@ -1,5 +1,5 @@
/* Language-level data type conversion for GNU C.
- Copyright (C) 1987, 1988, 1991, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991, 1998, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -29,6 +29,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tree.h"
#include "flags.h"
#include "convert.h"
+#include "c-common.h"
#include "toplev.h"
/* Change of width--truncation and extension of integers or reals--
@@ -42,7 +43,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
Here is a list of all the functions that assume that widening and
narrowing is always done with a NOP_EXPR:
In convert.c, convert_to_integer.
- In c-typeck.c, build_binary_op (boolean ops), and truthvalue_conversion.
+ In c-typeck.c, build_binary_op (boolean ops), and
+ c_common_truthvalue_conversion.
In expr.c: expand_expr, for operands of a MULT_EXPR.
In fold-const.c: fold.
In tree.c: get_narrower and get_unwidened. */
@@ -90,9 +92,9 @@ convert (type, expr)
return fold (convert_to_integer (type, e));
if (code == BOOLEAN_TYPE)
{
- tree t = truthvalue_conversion (expr);
- /* If truthvalue_conversion returns a NOP_EXPR, we must fold it here
- to avoid infinite recursion between fold () and convert (). */
+ tree t = c_common_truthvalue_conversion (expr);
+ /* If it returns a NOP_EXPR, we must fold it here to avoid
+ infinite recursion between fold () and convert (). */
if (TREE_CODE (t) == NOP_EXPR)
return fold (build1 (NOP_EXPR, type, TREE_OPERAND (t, 0)));
else
diff --git a/contrib/gcc/c-decl.c b/contrib/gcc/c-decl.c
index 2c8857f..37b22a7 100644
--- a/contrib/gcc/c-decl.c
+++ b/contrib/gcc/c-decl.c
@@ -37,7 +37,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "output.h"
#include "expr.h"
#include "c-tree.h"
-#include "c-lex.h"
#include "toplev.h"
#include "ggc.h"
#include "tm_p.h"
@@ -47,6 +46,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "timevar.h"
#include "c-common.h"
#include "c-pragma.h"
+#include "libfuncs.h"
+#include "except.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@@ -104,26 +105,21 @@ static int current_function_prototype_line;
/* The current statement tree. */
-static struct stmt_tree_s c_stmt_tree;
+static GTY(()) struct stmt_tree_s c_stmt_tree;
/* The current scope statement stack. */
-static tree c_scope_stmt_stack;
+static GTY(()) tree c_scope_stmt_stack;
/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
that have names. Here so we can clear out their names' definitions
at the end of the function. */
-static tree named_labels;
+static GTY(()) tree named_labels;
/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
-static tree shadowed_labels;
-
-/* Nonzero when store_parm_decls is called indicates a varargs function.
- Value not meaningful after store_parm_decls. */
-
-static int c_function_varargs;
+static GTY(()) tree shadowed_labels;
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
@@ -165,7 +161,7 @@ static int current_extern_inline;
/* Note that the information in the `names' component of the global contour
is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
-struct binding_level
+struct binding_level GTY(())
{
/* A chain of _DECL nodes for all variables, constants, functions,
and typedef types. These are in the reverse of the order supplied.
@@ -216,9 +212,9 @@ struct binding_level
/* Nonzero means make a BLOCK if this level has any subblocks. */
char keep_if_subblocks;
- /* Number of decls in `names' that have incomplete
- structure or union types. */
- int n_incomplete;
+ /* List of decls in `names' that have incomplete structure or
+ union types. */
+ tree incomplete_list;
/* A list of decls giving the (reversed) specified order of parms,
not including any forward-decls in the parmlist.
@@ -230,22 +226,22 @@ struct binding_level
/* The binding level currently in effect. */
-static struct binding_level *current_binding_level;
+static GTY(()) struct binding_level *current_binding_level;
/* A chain of binding_level structures awaiting reuse. */
-static struct binding_level *free_binding_level;
+static GTY((deletable (""))) struct binding_level *free_binding_level;
/* The outermost binding level, for names of file scope.
This is created when the compiler is started and exists
through the entire run. */
-static struct binding_level *global_binding_level;
+static GTY(()) struct binding_level *global_binding_level;
/* Binding level structures are initialized by copying this one. */
static struct binding_level clear_binding_level
- = {NULL, NULL, NULL, NULL, NULL, NULL_BINDING_LEVEL, 0, 0, 0, 0, 0, 0,
+ = {NULL, NULL, NULL, NULL, NULL, NULL_BINDING_LEVEL, 0, 0, 0, 0, 0, NULL,
NULL};
/* Nonzero means unconditionally make a BLOCK for the next level pushed. */
@@ -263,7 +259,7 @@ static int keep_next_if_subblocks;
saved values of named_labels and shadowed_labels for
a label binding level outside the current one. */
-static struct binding_level *label_level_chain;
+static GTY(()) struct binding_level *label_level_chain;
/* Functions called automatically at the beginning and end of execution. */
@@ -272,7 +268,7 @@ tree static_ctors, static_dtors;
/* Forward declarations. */
static struct binding_level * make_binding_level PARAMS ((void));
-static void mark_binding_level PARAMS ((void *));
+static void pop_binding_level PARAMS ((struct binding_level **));
static void clear_limbo_values PARAMS ((tree));
static int duplicate_decls PARAMS ((tree, tree, int));
static int redeclaration_error_message PARAMS ((tree, tree));
@@ -288,163 +284,9 @@ static void layout_array_type PARAMS ((tree));
static tree c_make_fname_decl PARAMS ((tree, int));
static void c_expand_body PARAMS ((tree, int, int));
static void warn_if_shadowing PARAMS ((tree, tree));
+static bool flexible_array_type_p PARAMS ((tree));
+static tree set_save_expr_context PARAMS ((tree *, int *, void *));
-/* C-specific option variables. */
-
-/* Nonzero means allow type mismatches in conditional expressions;
- just make their values `void'. */
-
-int flag_cond_mismatch;
-
-/* Nonzero means don't recognize the keyword `asm'. */
-
-int flag_no_asm;
-
-/* Nonzero means do some things the same way PCC does. */
-
-int flag_traditional;
-
-/* Nonzero means enable C89 Amendment 1 features. */
-
-int flag_isoc94 = 0;
-
-/* Nonzero means use the ISO C99 dialect of C. */
-
-int flag_isoc99 = 0;
-
-/* Nonzero means that we have builtin functions, and main is an int */
-
-int flag_hosted = 1;
-
-/* Nonzero means add default format_arg attributes for functions not
- in ISO C. */
-
-int flag_noniso_default_format_attributes = 1;
-
-/* Nonzero means to allow single precision math even if we're generally
- being traditional. */
-int flag_allow_single_precision = 0;
-
-/* Nonzero means to treat bitfields as signed unless they say `unsigned'. */
-
-int flag_signed_bitfields = 1;
-int explicit_flag_signed_bitfields = 0;
-
-/* Nonzero means warn about use of implicit int. */
-
-int warn_implicit_int;
-
-/* Nonzero means warn about usage of long long when `-pedantic'. */
-
-int warn_long_long = 1;
-
-/* Nonzero means message about use of implicit function declarations;
- 1 means warning; 2 means error. */
-
-int mesg_implicit_function_declaration = -1;
-
-/* Nonzero means give string constants the type `const char *'
- to get extra warnings from them. These warnings will be too numerous
- to be useful, except in thoroughly ANSIfied programs. */
-
-int flag_const_strings;
-
-/* Nonzero means warn about pointer casts that can drop a type qualifier
- from the pointer target type. */
-
-int warn_cast_qual;
-
-/* Nonzero means warn when casting a function call to a type that does
- not match the return type (e.g. (float)sqrt() or (anything*)malloc()
- when there is no previous declaration of sqrt or malloc. */
-
-int warn_bad_function_cast;
-
-/* Warn about functions which might be candidates for format attributes. */
-
-int warn_missing_format_attribute;
-
-/* Warn about traditional constructs whose meanings changed in ANSI C. */
-
-int warn_traditional;
-
-/* Nonzero means warn about sizeof(function) or addition/subtraction
- of function pointers. */
-
-int warn_pointer_arith;
-
-/* Nonzero means warn for non-prototype function decls
- or non-prototyped defs without previous prototype. */
-
-int warn_strict_prototypes;
-
-/* Nonzero means warn for any global function def
- without separate previous prototype decl. */
-
-int warn_missing_prototypes;
-
-/* Nonzero means warn for any global function def
- without separate previous decl. */
-
-int warn_missing_declarations;
-
-/* Nonzero means warn about multiple (redundant) decls for the same single
- variable or function. */
-
-int warn_redundant_decls = 0;
-
-/* Nonzero means warn about extern declarations of objects not at
- file-scope level and about *all* declarations of functions (whether
- extern or static) not at file-scope level. Note that we exclude
- implicit function declarations. To get warnings about those, use
- -Wimplicit. */
-
-int warn_nested_externs = 0;
-
-/* Warn about a subscript that has type char. */
-
-int warn_char_subscripts = 0;
-
-/* Warn if a type conversion is done that might have confusing results. */
-
-int warn_conversion;
-
-/* Warn if adding () is suggested. */
-
-int warn_parentheses;
-
-/* Warn if initializer is not completely bracketed. */
-
-int warn_missing_braces;
-
-/* Warn if main is suspicious. */
-
-int warn_main;
-
-/* Warn about #pragma directives that are not recognised. */
-
-int warn_unknown_pragmas = 0; /* Tri state variable. */
-
-/* Warn about comparison of signed and unsigned values.
- If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified. */
-
-int warn_sign_compare = -1;
-
-/* Warn about testing equality of floating point numbers. */
-
-int warn_float_equal = 0;
-
-/* Nonzero means warn about use of multicharacter literals. */
-
-int warn_multichar = 1;
-
-/* Nonzero means `$' can be in an identifier. */
-
-#ifndef DOLLARS_IN_IDENTIFIERS
-#define DOLLARS_IN_IDENTIFIERS 1
-#endif
-int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
-
/* States indicating how grokdeclarator() should handle declspecs marked
with __attribute__((deprecated)). An object declared as
__attribute__((deprecated)) suppresses warnings of uses of other
@@ -457,357 +299,6 @@ enum deprecated_states {
static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
-/* Decode the string P as a language-specific option for C.
- Return the number of strings consumed. Should not complain
- if it does not recognise the option. */
-
-int
-c_decode_option (argc, argv)
- int argc ATTRIBUTE_UNUSED;
- char **argv;
-{
- int strings_processed;
- char *p = argv[0];
-
- strings_processed = cpp_handle_option (parse_in, argc, argv, 0);
-
- if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
- {
- warning ("-traditional is deprecated and may be removed");
- flag_traditional = 1;
- flag_writable_strings = 1;
- }
- 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;
- }
- else if (!strncmp (p, "-std=", 5))
- {
- /* Select the appropriate language standard. We currently
- recognize:
- -std=iso9899:1990 same as -ansi
- -std=iso9899:199409 ISO C as modified in amend. 1
- -std=iso9899:1999 ISO C 99
- -std=c89 same as -std=iso9899:1990
- -std=c99 same as -std=iso9899:1999
- -std=gnu89 default, iso9899:1990 + gnu extensions
- -std=gnu99 iso9899:1999 + gnu extensions
- */
- const char *const argstart = &p[5];
-
- if (!strcmp (argstart, "iso9899:1990")
- || !strcmp (argstart, "c89"))
- {
- iso_1990:
- flag_isoc94 = 0;
- iso_1994:
- flag_traditional = 0;
- flag_writable_strings = 0;
- flag_no_asm = 1;
- flag_no_nonansi_builtin = 1;
- flag_noniso_default_format_attributes = 0;
- flag_isoc99 = 0;
- }
- else if (!strcmp (argstart, "iso9899:199409"))
- {
- flag_isoc94 = 1;
- goto iso_1994;
- }
- else if (!strcmp (argstart, "iso9899:199x")
- || !strcmp (argstart, "iso9899:1999")
- || !strcmp (argstart, "c9x")
- || !strcmp (argstart, "c99"))
- {
- flag_traditional = 0;
- flag_writable_strings = 0;
- flag_no_asm = 1;
- flag_no_nonansi_builtin = 1;
- flag_noniso_default_format_attributes = 0;
- flag_isoc99 = 1;
- flag_isoc94 = 1;
- }
- else if (!strcmp (argstart, "gnu89"))
- {
- flag_traditional = 0;
- flag_writable_strings = 0;
- flag_no_asm = 0;
- flag_no_nonansi_builtin = 0;
- flag_noniso_default_format_attributes = 1;
- flag_isoc99 = 0;
- flag_isoc94 = 0;
- }
- else if (!strcmp (argstart, "gnu9x") || !strcmp (argstart, "gnu99"))
- {
- flag_traditional = 0;
- flag_writable_strings = 0;
- flag_no_asm = 0;
- flag_no_nonansi_builtin = 0;
- flag_noniso_default_format_attributes = 1;
- flag_isoc99 = 1;
- flag_isoc94 = 1;
- }
- else
- error ("unknown C standard `%s'", argstart);
- }
- else if (!strcmp (p, "-fdollars-in-identifiers"))
- dollars_in_ident = 1;
- else if (!strcmp (p, "-fno-dollars-in-identifiers"))
- dollars_in_ident = 0;
- else if (!strcmp (p, "-fsigned-char"))
- flag_signed_char = 1;
- else if (!strcmp (p, "-funsigned-char"))
- flag_signed_char = 0;
- else if (!strcmp (p, "-fno-signed-char"))
- flag_signed_char = 0;
- else if (!strcmp (p, "-fno-unsigned-char"))
- flag_signed_char = 1;
- else if (!strcmp (p, "-fsigned-bitfields")
- || !strcmp (p, "-fno-unsigned-bitfields"))
- {
- flag_signed_bitfields = 1;
- explicit_flag_signed_bitfields = 1;
- }
- else if (!strcmp (p, "-funsigned-bitfields")
- || !strcmp (p, "-fno-signed-bitfields"))
- {
- flag_signed_bitfields = 0;
- explicit_flag_signed_bitfields = 1;
- }
- else if (!strcmp (p, "-fshort-enums"))
- flag_short_enums = 1;
- else if (!strcmp (p, "-fno-short-enums"))
- flag_short_enums = 0;
- else if (!strcmp (p, "-fshort-wchar"))
- flag_short_wchar = 1;
- else if (!strcmp (p, "-fno-short-wchar"))
- flag_short_wchar = 0;
- else if (!strcmp (p, "-fcond-mismatch"))
- flag_cond_mismatch = 1;
- else if (!strcmp (p, "-fno-cond-mismatch"))
- flag_cond_mismatch = 0;
- else if (!strcmp (p, "-fshort-double"))
- flag_short_double = 1;
- else if (!strcmp (p, "-fno-short-double"))
- flag_short_double = 0;
- else if (!strcmp (p, "-fasm"))
- flag_no_asm = 0;
- else if (!strcmp (p, "-fno-asm"))
- flag_no_asm = 1;
- else if (!strcmp (p, "-fbuiltin"))
- flag_no_builtin = 0;
- else if (!strcmp (p, "-fno-builtin"))
- flag_no_builtin = 1;
- else if (!strncmp (p, "-fno-builtin-", strlen ("-fno-builtin-")))
- disable_builtin_function (p + strlen ("-fno-builtin-"));
- else if (p[0] == '-' && p[1] == 'f' && dump_switch_p (p + 2))
- ;
- else if (!strcmp (p, "-ansi"))
- goto iso_1990;
- 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_int = 1;
- if (mesg_implicit_function_declaration != 2)
- mesg_implicit_function_declaration = 1;
- }
- else if (!strcmp (p, "-Wno-implicit"))
- warn_implicit_int = 0, mesg_implicit_function_declaration = 0;
- else if (!strcmp (p, "-Wlong-long"))
- warn_long_long = 1;
- else if (!strcmp (p, "-Wno-long-long"))
- warn_long_long = 0;
- else if (!strcmp (p, "-Wwrite-strings"))
- flag_const_strings = 1;
- else if (!strcmp (p, "-Wno-write-strings"))
- flag_const_strings = 0;
- else if (!strcmp (p, "-Wcast-qual"))
- warn_cast_qual = 1;
- else if (!strcmp (p, "-Wno-cast-qual"))
- warn_cast_qual = 0;
- else if (!strcmp (p, "-Wbad-function-cast"))
- warn_bad_function_cast = 1;
- else if (!strcmp (p, "-Wno-bad-function-cast"))
- warn_bad_function_cast = 0;
- else if (!strcmp (p, "-Wno-missing-noreturn"))
- warn_missing_noreturn = 0;
- else if (!strcmp (p, "-Wmissing-format-attribute"))
- warn_missing_format_attribute = 1;
- else if (!strcmp (p, "-Wno-missing-format-attribute"))
- warn_missing_format_attribute = 0;
- else if (!strcmp (p, "-Wpointer-arith"))
- warn_pointer_arith = 1;
- else if (!strcmp (p, "-Wno-pointer-arith"))
- warn_pointer_arith = 0;
- else if (!strcmp (p, "-Wstrict-prototypes"))
- warn_strict_prototypes = 1;
- else if (!strcmp (p, "-Wno-strict-prototypes"))
- warn_strict_prototypes = 0;
- else if (!strcmp (p, "-Wmissing-prototypes"))
- warn_missing_prototypes = 1;
- else if (!strcmp (p, "-Wno-missing-prototypes"))
- warn_missing_prototypes = 0;
- else if (!strcmp (p, "-Wmissing-declarations"))
- warn_missing_declarations = 1;
- else if (!strcmp (p, "-Wno-missing-declarations"))
- warn_missing_declarations = 0;
- else if (!strcmp (p, "-Wredundant-decls"))
- warn_redundant_decls = 1;
- else if (!strcmp (p, "-Wno-redundant-decls"))
- warn_redundant_decls = 0;
- else if (!strcmp (p, "-Wnested-externs"))
- warn_nested_externs = 1;
- else if (!strcmp (p, "-Wno-nested-externs"))
- warn_nested_externs = 0;
- else if (!strcmp (p, "-Wtraditional"))
- warn_traditional = 1;
- else if (!strcmp (p, "-Wno-traditional"))
- warn_traditional = 0;
- else if (!strncmp (p, "-Wformat=", 9))
- set_Wformat (atoi (p + 9));
- else if (!strcmp (p, "-Wformat"))
- set_Wformat (1);
- else if (!strcmp (p, "-Wno-format"))
- set_Wformat (0);
- else if (!strcmp (p, "-Wformat-y2k"))
- warn_format_y2k = 1;
- else if (!strcmp (p, "-Wno-format-y2k"))
- warn_format_y2k = 0;
- else if (!strcmp (p, "-Wformat-extra-args"))
- warn_format_extra_args = 1;
- else if (!strcmp (p, "-Wno-format-extra-args"))
- warn_format_extra_args = 0;
- else if (!strcmp (p, "-Wformat-nonliteral"))
- warn_format_nonliteral = 1;
- else if (!strcmp (p, "-Wno-format-nonliteral"))
- warn_format_nonliteral = 0;
- else if (!strcmp (p, "-Wformat-security"))
- warn_format_security = 1;
- else if (!strcmp (p, "-Wno-format-security"))
- warn_format_security = 0;
- else if (!strcmp (p, "-Wchar-subscripts"))
- warn_char_subscripts = 1;
- else if (!strcmp (p, "-Wno-char-subscripts"))
- warn_char_subscripts = 0;
- else if (!strcmp (p, "-Wconversion"))
- warn_conversion = 1;
- else if (!strcmp (p, "-Wno-conversion"))
- warn_conversion = 0;
- else if (!strcmp (p, "-Wparentheses"))
- warn_parentheses = 1;
- else if (!strcmp (p, "-Wno-parentheses"))
- warn_parentheses = 0;
- else if (!strcmp (p, "-Wreturn-type"))
- warn_return_type = 1;
- else if (!strcmp (p, "-Wno-return-type"))
- warn_return_type = 0;
- else if (!strcmp (p, "-Wsequence-point"))
- warn_sequence_point = 1;
- else if (!strcmp (p, "-Wno-sequence-point"))
- warn_sequence_point = 0;
- else if (!strcmp (p, "-Wcomment"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wno-comment"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wcomments"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wno-comments"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wtrigraphs"))
- ; /* 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"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "-Wmissing-braces"))
- 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 = -1;
- 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, "-Wfloat-equal"))
- warn_float_equal = 1;
- else if (!strcmp (p, "-Wno-float-equal"))
- warn_float_equal = 0;
- else if (!strcmp (p, "-Wmultichar"))
- warn_multichar = 1;
- else if (!strcmp (p, "-Wno-multichar"))
- warn_multichar = 0;
- else if (!strcmp (p, "-Wdiv-by-zero"))
- warn_div_by_zero = 1;
- else if (!strcmp (p, "-Wno-div-by-zero"))
- warn_div_by_zero = 0;
- else if (!strcmp (p, "-Wunknown-pragmas"))
- /* Set to greater than 1, so that even unknown pragmas in system
- headers will be warned about. */
- warn_unknown_pragmas = 2;
- else if (!strcmp (p, "-Wno-unknown-pragmas"))
- warn_unknown_pragmas = 0;
- else if (!strcmp (p, "-Wall"))
- {
- /* We save the value of warn_uninitialized, since if they put
- -Wuninitialized on the command line, we need to generate a
- warning about not using it without also specifying -O. */
- if (warn_uninitialized != 1)
- warn_uninitialized = 2;
- warn_implicit_int = 1;
- mesg_implicit_function_declaration = 1;
- warn_return_type = 1;
- set_Wunused (1);
- warn_switch = 1;
- set_Wformat (1);
- warn_char_subscripts = 1;
- warn_parentheses = 1;
- warn_sequence_point = 1;
- warn_missing_braces = 1;
- /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding can turn
- it off only if it's not explicit. */
- warn_main = 2;
- /* Only warn about unknown pragmas that are not in system headers. */
- warn_unknown_pragmas = 1;
- }
- else
- return strings_processed;
-
- return 1;
-}
-
void
c_print_identifier (file, node, indent)
FILE *file;
@@ -834,7 +325,7 @@ c_print_identifier (file, node, indent)
for a top-level tentative array defn that wasn't complete before. */
void
-finish_incomplete_decl (decl)
+c_finish_incomplete_decl (decl)
tree decl;
{
if (TREE_CODE (decl) == VAR_DECL)
@@ -854,13 +345,33 @@ finish_incomplete_decl (decl)
}
}
-/* Create a new `struct binding_level'. */
+/* Reuse or create a struct for this binding level. */
static struct binding_level *
make_binding_level ()
{
- /* NOSTRICT */
- return (struct binding_level *) xmalloc (sizeof (struct binding_level));
+ if (free_binding_level)
+ {
+ struct binding_level *result = free_binding_level;
+ free_binding_level = result->level_chain;
+ return result;
+ }
+ else
+ return (struct binding_level *) ggc_alloc (sizeof (struct binding_level));
+}
+
+/* Remove a binding level from a list and add it to the level chain. */
+
+static void
+pop_binding_level (lp)
+ struct binding_level **lp;
+{
+ struct binding_level *l = *lp;
+ *lp = l->level_chain;
+
+ memset (l, 0, sizeof (struct binding_level));
+ l->level_chain = free_binding_level;
+ free_binding_level = l;
}
/* Nonzero if we are currently in the global binding level. */
@@ -928,17 +439,7 @@ pushlevel (tag_transparent)
named_labels = 0;
}
- /* Reuse or create a struct for this binding level. */
-
- if (free_binding_level)
- {
- newlevel = free_binding_level;
- free_binding_level = free_binding_level->level_chain;
- }
- else
- {
- newlevel = make_binding_level ();
- }
+ newlevel = make_binding_level ();
/* Add this level to the front of the chain (stack) of levels that
are active. */
@@ -1159,13 +660,7 @@ poplevel (keep, reverse, functionbody)
/* Pop the current level, and free the structure for reuse. */
- {
- struct binding_level *level = current_binding_level;
- current_binding_level = current_binding_level->level_chain;
-
- level->level_chain = free_binding_level;
- free_binding_level = level;
- }
+ pop_binding_level (&current_binding_level);
/* Dispose of the block that we just made inside some higher level. */
if (functionbody)
@@ -1244,17 +739,7 @@ push_label_level ()
{
struct binding_level *newlevel;
- /* Reuse or create a struct for this binding level. */
-
- if (free_binding_level)
- {
- newlevel = free_binding_level;
- free_binding_level = free_binding_level->level_chain;
- }
- else
- {
- newlevel = make_binding_level ();
- }
+ newlevel = make_binding_level ();
/* Add this level to the front of the chain (stack) of label levels. */
@@ -1316,9 +801,7 @@ pop_label_level ()
shadowed_labels = level->shadowed;
/* Pop the current level, and free the structure for reuse. */
- label_level_chain = label_level_chain->level_chain;
- level->level_chain = free_binding_level;
- free_binding_level = level;
+ pop_binding_level (&label_level_chain);
}
/* Push a definition or a declaration of struct, union or enum tag "name".
@@ -1483,14 +966,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
match enough. Ultimately, copy most of the information from the new
decl to the old one, and keep using the old one. */
- if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL
- && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (newdecl)) == olddecl
- && DECL_INITIAL (olddecl) == 0)
- /* If -traditional, avoid error for redeclaring fcn
- after implicit decl. */
- ;
- else if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_BUILT_IN (olddecl))
+ if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_BUILT_IN (olddecl))
{
/* A function declaration for a built-in function. */
if (!TREE_PUBLIC (newdecl))
@@ -1657,7 +1133,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
break;
}
- if (simple_type_promotes_to (type) != NULL_TREE)
+ if (c_type_promotes_to (type) != type)
{
error ("an argument type that has a default promotion can't match an empty parameter name list declaration");
break;
@@ -1665,6 +1141,27 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
}
}
error_with_decl (olddecl, "previous declaration of `%s'");
+
+ /* This is safer because the initializer might contain references
+ to variables that were declared between olddecl and newdecl. This
+ will make the initializer invalid for olddecl in case it gets
+ assigned to olddecl below. */
+ if (TREE_CODE (newdecl) == VAR_DECL)
+ DECL_INITIAL (newdecl) = 0;
+ }
+ /* TLS cannot follow non-TLS declaration. */
+ else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
+ && !DECL_THREAD_LOCAL (olddecl) && DECL_THREAD_LOCAL (newdecl))
+ {
+ error_with_decl (newdecl, "thread-local declaration of `%s' follows non thread-local declaration");
+ error_with_decl (olddecl, "previous declaration of `%s'");
+ }
+ /* non-TLS declaration cannot follow TLS declaration. */
+ else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
+ && DECL_THREAD_LOCAL (olddecl) && !DECL_THREAD_LOCAL (newdecl))
+ {
+ error_with_decl (newdecl, "non thread-local declaration of `%s' follows thread-local declaration");
+ error_with_decl (olddecl, "previous declaration of `%s'");
}
else
{
@@ -1739,12 +1236,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
}
/* Type for passing arg must be consistent
with that declared for the arg. */
- if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type))
- /* If -traditional, allow `unsigned int' instead of `int'
- in the prototype. */
- && (! (flag_traditional
- && TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == integer_type_node
- && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node)))
+ if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type)))
{
error_with_decl (newdecl,
"prototype for `%s' follows and argument %d doesn't match",
@@ -1879,11 +1371,6 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
COPY_DECL_RTL (olddecl, newdecl);
/* Merge the type qualifiers. */
- if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
- && ! TREE_THIS_VOLATILE (newdecl))
- TREE_THIS_VOLATILE (write_olddecl) = 0;
-
if (TREE_READONLY (newdecl))
TREE_READONLY (write_olddecl) = 1;
@@ -2197,10 +1684,7 @@ pushdecl (x)
IDENTIFIER_POINTER (name));
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 (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional)
+ if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x))
{
t = IDENTIFIER_GLOBAL_VALUE (name);
/* Type decls at global scope don't conflict with externs declared
@@ -2219,9 +1703,8 @@ pushdecl (x)
}
/* 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)
+ warn. */
+ if (TREE_PUBLIC (name)
/* Don't test for DECL_EXTERNAL, because grokdeclarator
sets this for all functions. */
&& ! TREE_PUBLIC (x)
@@ -2253,7 +1736,7 @@ pushdecl (x)
}
/* If we are processing a typedef statement, generate a whole new
- ..._TYPE node (which will be just an variant of the existing
+ ..._TYPE node (which will be just a variant of the existing
..._TYPE node with identical properties) and then install the
TYPE_DECL node generated to represent the typedef name as the
TYPE_NAME of this brand new (duplicate) ..._TYPE node.
@@ -2315,9 +1798,6 @@ pushdecl (x)
}
/* Multiple external decls of the same identifier ought to match.
- Check against both global declarations (when traditional) and out of
- scope (limbo) block level declarations.
-
We get warnings about inline functions where they are defined.
Avoid duplicate warnings where they are used. */
if (TREE_PUBLIC (x)
@@ -2325,11 +1805,7 @@ pushdecl (x)
{
tree decl;
- if (flag_traditional && IDENTIFIER_GLOBAL_VALUE (name) != 0
- && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name))
- || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name))))
- decl = IDENTIFIER_GLOBAL_VALUE (name);
- else if (IDENTIFIER_LIMBO_VALUE (name) != 0)
+ if (IDENTIFIER_LIMBO_VALUE (name) != 0)
/* Decls in limbo are always extern, so no need to check that. */
decl = IDENTIFIER_LIMBO_VALUE (name);
else
@@ -2359,39 +1835,6 @@ pushdecl (x)
"previous implicit declaration of `%s'");
}
- /* 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)
- {
- tree type = TREE_TYPE (x);
-
- /* But don't do this if the type contains temporary nodes. */
- while (type)
- {
- if (type == error_mark_node)
- break;
- if (TYPE_CONTEXT (type))
- {
- warning_with_decl (x, "type of external `%s' is not global");
- /* By exiting the loop early, we leave TYPE nonzero,
- and thus prevent globalization of the decl. */
- break;
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE
- && TYPE_ARG_TYPES (type) != 0)
- /* The types might not be truly local,
- but the list of arg types certainly is temporary.
- Since prototypes are nontraditional,
- ok not to do the traditional thing. */
- break;
- type = TREE_TYPE (type);
- }
-
- if (type == 0)
- b = global_binding_level;
- }
-
/* This name is new in its binding level.
Install the new declaration and return it. */
if (b == global_binding_level)
@@ -2548,7 +1991,7 @@ pushdecl (x)
b->shadowed = tree_cons (name, oldlocal, b->shadowed);
}
- /* Keep count of variables in this level with incomplete type.
+ /* Keep list of variables in this level with incomplete type.
If the input is erroneous, we can have error_mark in the type
slot (e.g. "f(void a, ...)") - that doesn't count as an
incomplete type. */
@@ -2561,7 +2004,7 @@ pushdecl (x)
element = TREE_TYPE (element);
if (TREE_CODE (element) == RECORD_TYPE
|| TREE_CODE (element) == UNION_TYPE)
- ++b->n_incomplete;
+ b->incomplete_list = tree_cons (NULL_TREE, x, b->incomplete_list);
}
}
@@ -2625,12 +2068,12 @@ implicitly_declare (functionid)
IDENTIFIER_IMPLICIT_DECL (functionid) = decl;
/* 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);
- /* This is a no-op in c-lang.c or something real in objc-actions.c. */
- maybe_objc_check_decl (decl);
+ /* This is a no-op in c-lang.c or something real in objc-act.c. */
+ if (flag_objc)
+ objc_check_decl (decl);
rest_of_decl_compilation (decl, NULL, 0, 0);
@@ -2674,17 +2117,8 @@ redeclaration_error_message (newdecl, olddecl)
{
if (TREE_CODE (newdecl) == TYPE_DECL)
{
- if (flag_traditional && TREE_TYPE (newdecl) == TREE_TYPE (olddecl))
- return 0;
- /* pushdecl creates distinct types for TYPE_DECLs by calling
- build_type_copy, so the above comparison generally fails. We do
- another test against the TYPE_MAIN_VARIANT of the olddecl, which
- is equivalent to what this code used to do before the build_type_copy
- call. The variant type distinction should not matter for traditional
- code, because it doesn't have type qualifiers. */
- if (flag_traditional
- && TYPE_MAIN_VARIANT (TREE_TYPE (olddecl)) == TREE_TYPE (newdecl))
- return 0;
+ /* Do not complain about type redeclarations where at least one
+ declaration was in a system header. */
if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl))
return 0;
return 1;
@@ -3030,25 +2464,6 @@ lookup_name_current_level (name)
return t;
}
-/* Mark ARG for GC. */
-
-static void
-mark_binding_level (arg)
- void *arg;
-{
- struct binding_level *level = *(struct binding_level **) arg;
-
- for (; level != 0; level = level->level_chain)
- {
- ggc_mark_tree (level->names);
- ggc_mark_tree (level->tags);
- ggc_mark_tree (level->shadowed);
- ggc_mark_tree (level->blocks);
- ggc_mark_tree (level->this_block);
- ggc_mark_tree (level->parm_order);
- }
-}
-
/* Create the predefined scalar types of C,
and some nodes representing standard constants (0, 1, (void *) 0).
Initialize the global binding level.
@@ -3102,22 +2517,6 @@ c_init_decl_processing ()
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
-
- incomplete_decl_finalize_hook = finish_incomplete_decl;
-
- /* Record our roots. */
-
- ggc_add_tree_root (c_global_trees, CTI_MAX);
- ggc_add_root (&c_stmt_tree, 1, sizeof c_stmt_tree, mark_stmt_tree);
- ggc_add_tree_root (&c_scope_stmt_stack, 1);
- ggc_add_tree_root (&named_labels, 1);
- ggc_add_tree_root (&shadowed_labels, 1);
- ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
- mark_binding_level);
- ggc_add_root (&label_level_chain, 1, sizeof label_level_chain,
- mark_binding_level);
- ggc_add_tree_root (&static_ctors, 1);
- ggc_add_tree_root (&static_dtors, 1);
}
/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
@@ -3166,24 +2565,21 @@ c_make_fname_decl (id, type_dep)
See tree.h for its possible values.
If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
- the name to be called if we can't opencode the function. */
+ the name to be called if we can't opencode the function. If
+ ATTRS is nonzero, use that for the function's attribute list. */
tree
-builtin_function (name, type, function_code, class, library_name)
+builtin_function (name, type, function_code, class, library_name, attrs)
const char *name;
tree type;
int function_code;
enum built_in_class class;
const char *library_name;
+ tree attrs;
{
tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
- /* If -traditional, permit redefining a builtin function any way you like.
- (Though really, if the program redefines these functions,
- it probably won't work right unless compiled with -fno-builtin.) */
- if (flag_traditional && name[0] != '_')
- DECL_BUILT_IN_NONANSI (decl) = 1;
if (library_name)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
make_decl_rtl (decl, NULL);
@@ -3191,17 +2587,16 @@ builtin_function (name, type, function_code, class, library_name)
DECL_BUILT_IN_CLASS (decl) = class;
DECL_FUNCTION_CODE (decl) = function_code;
- /* The return builtins leave the current function. */
- if (function_code == BUILT_IN_RETURN || function_code == BUILT_IN_EH_RETURN)
- TREE_THIS_VOLATILE (decl) = 1;
-
/* Warn if a function in the namespace for users
is used without an occasion to consider it declared. */
if (name[0] != '_' || name[1] != '_')
C_DECL_ANTICIPATED (decl) = 1;
/* Possibly apply some default attributes to this built-in function. */
- decl_attributes (&decl, NULL_TREE, 0);
+ if (attrs)
+ decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
+ else
+ decl_attributes (&decl, NULL_TREE, 0);
return decl;
}
@@ -3210,7 +2605,7 @@ builtin_function (name, type, function_code, class, library_name)
attributes. */
void
-insert_default_attributes (decl)
+c_insert_default_attributes (decl)
tree decl;
{
if (!TREE_PUBLIC (decl))
@@ -3307,8 +2702,8 @@ shadow_tag_warned (declspecs, warned)
/* Construct an array declarator. EXPR is the expression inside [], or
NULL_TREE. QUALS are the type qualifiers inside the [] (to be applied
to the pointer to which a parameter array is converted). STATIC_P is
- non-zero if "static" is inside the [], zero otherwise. VLA_UNSPEC_P
- is non-zero is the array is [*], a VLA of unspecified length which is
+ nonzero if "static" is inside the [], zero otherwise. VLA_UNSPEC_P
+ is nonzero is the array is [*], a VLA of unspecified length which is
nevertheless a complete type (not currently implemented by GCC),
zero otherwise. The declarator is constructed as an ARRAY_REF
(to be decoded by grokdeclarator), whose operand 0 is what's on the
@@ -3330,9 +2725,9 @@ build_array_declarator (expr, quals, static_p, vla_unspec_p)
if (pedantic && !flag_isoc99)
{
if (static_p || quals != NULL_TREE)
- pedwarn ("ISO C89 does not support `static' or type qualifiers in parameter array declarators");
+ pedwarn ("ISO C90 does not support `static' or type qualifiers in parameter array declarators");
if (vla_unspec_p)
- pedwarn ("ISO C89 does not support `[*]' array declarators");
+ pedwarn ("ISO C90 does not support `[*]' array declarators");
}
if (vla_unspec_p)
warning ("GCC does not yet properly implement `[*]' array declarators");
@@ -3341,7 +2736,7 @@ build_array_declarator (expr, quals, static_p, vla_unspec_p)
/* Set the type of an array declarator. DECL is the declarator, as
constructed by build_array_declarator; TYPE is what appears on the left
- of the [] and goes in operand 0. ABSTRACT_P is non-zero if it is an
+ of the [] and goes in operand 0. ABSTRACT_P is nonzero if it is an
abstract declarator, zero otherwise; this is used to reject static and
type qualifiers in abstract declarators, where they are not in the
C99 grammar. */
@@ -3517,9 +2912,19 @@ start_decl (declarator, declspecs, initialized, attributes)
/* 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))
+
+ -fno-common gives strict ANSI behavior, though this tends to break
+ a large body of code that grew up without this rule.
+
+ Thread-local variables are never common, since there's no entrenched
+ body of code to break, and it allows more efficient variable references
+ in the presense of dynamic linking. */
+
+ if (TREE_CODE (decl) == VAR_DECL
+ && !initialized
+ && TREE_PUBLIC (decl)
+ && !DECL_THREAD_LOCAL (decl)
+ && !flag_no_common)
DECL_COMMON (decl) = 1;
/* Set attributes here so if duplicate decl, will have proper attributes. */
@@ -3690,8 +3095,9 @@ finish_decl (decl, init, asmspec_tree)
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
{
- /* This is a no-op in c-lang.c or something real in objc-actions.c. */
- maybe_objc_check_decl (decl);
+ /* This is a no-op in c-lang.c or something real in objc-act.c. */
+ if (flag_objc)
+ objc_check_decl (decl);
if (!DECL_CONTEXT (decl))
{
@@ -3753,8 +3159,9 @@ finish_decl (decl, init, asmspec_tree)
if (TREE_CODE (decl) == TYPE_DECL)
{
- /* This is a no-op in c-lang.c or something real in objc-actions.c. */
- maybe_objc_check_decl (decl);
+ /* This is a no-op in c-lang.c or something real in objc-act.c. */
+ if (flag_objc)
+ objc_check_decl (decl);
rest_of_decl_compilation (decl, NULL, DECL_CONTEXT (decl) == 0, 0);
}
@@ -3763,17 +3170,41 @@ finish_decl (decl, init, asmspec_tree)
computing them in the following function definition. */
if (current_binding_level == global_binding_level)
get_pending_sizes ();
-}
-/* If DECL has a cleanup, build and return that cleanup here.
- This is a callback called by expand_expr. */
+ /* Install a cleanup (aka destructor) if one was given. */
+ if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
+ {
+ tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
+ if (attr)
+ {
+ static bool eh_initialized_p;
-tree
-maybe_build_cleanup (decl)
- tree decl ATTRIBUTE_UNUSED;
-{
- /* There are no cleanups in C. */
- return NULL_TREE;
+ tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
+ tree cleanup_decl = lookup_name (cleanup_id);
+ tree cleanup;
+
+ /* Build "cleanup(&decl)" for the destructor. */
+ cleanup = build_unary_op (ADDR_EXPR, decl, 0);
+ cleanup = build_tree_list (NULL_TREE, cleanup);
+ cleanup = build_function_call (cleanup_decl, cleanup);
+
+ /* Don't warn about decl unused; the cleanup uses it. */
+ TREE_USED (decl) = 1;
+
+ /* Initialize EH, if we've been told to do so. */
+ if (flag_exceptions && !eh_initialized_p)
+ {
+ eh_initialized_p = true;
+ eh_personality_libfunc
+ = init_one_libfunc (USING_SJLJ_EXCEPTIONS
+ ? "__gcc_personality_sj0"
+ : "__gcc_personality_v0");
+ using_eh_for_cleanups ();
+ }
+
+ add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
+ }
+ }
}
/* Given a parsed parameter declaration,
@@ -3958,6 +3389,40 @@ complete_array_type (type, initial_value, do_default)
return value;
}
+/* Determine whether TYPE is a structure with a flexible array member,
+ or a union containing such a structure (possibly recursively). */
+
+static bool
+flexible_array_type_p (type)
+ tree type;
+{
+ tree x;
+ switch (TREE_CODE (type))
+ {
+ case RECORD_TYPE:
+ x = TYPE_FIELDS (type);
+ if (x == NULL_TREE)
+ return false;
+ while (TREE_CHAIN (x) != NULL_TREE)
+ x = TREE_CHAIN (x);
+ if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
+ && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
+ && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
+ return true;
+ return false;
+ case UNION_TYPE:
+ for (x = TYPE_FIELDS (type); x != NULL_TREE; x = TREE_CHAIN (x))
+ {
+ if (flexible_array_type_p (TREE_TYPE (x)))
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
/* Given declspecs and a declarator,
determine the name and type of the object declared
and construct a ..._DECL node for it.
@@ -4109,7 +3574,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
enum rid i = C_RID_CODE (id);
if ((int) i <= (int) RID_LAST_MODIFIER)
{
- if (i == RID_LONG && (specbits & (1 << (int) i)))
+ if (i == RID_LONG && (specbits & (1 << (int) RID_LONG)))
{
if (longlong)
error ("`long long long' is too long for GCC");
@@ -4117,12 +3582,33 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
{
if (pedantic && !flag_isoc99 && ! in_system_header
&& warn_long_long)
- pedwarn ("ISO C89 does not support `long long'");
+ pedwarn ("ISO C90 does not support `long long'");
longlong = 1;
}
}
else if (specbits & (1 << (int) i))
- pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
+ {
+ if (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT)
+ {
+ if (!flag_isoc99)
+ pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
+ }
+ else
+ error ("duplicate `%s'", IDENTIFIER_POINTER (id));
+ }
+
+ /* Diagnose "__thread extern". Recall that this list
+ is in the reverse order seen in the text. */
+ if (i == RID_THREAD
+ && (specbits & (1 << (int) RID_EXTERN
+ | 1 << (int) RID_STATIC)))
+ {
+ if (specbits & 1 << (int) RID_EXTERN)
+ error ("`__thread' before `extern'");
+ else
+ error ("`__thread' before `static'");
+ }
+
specbits |= 1 << (int) i;
goto found;
}
@@ -4242,12 +3728,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
else
{
ok = 1;
- if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
+ if (!explicit_int && !defaulted_int && !explicit_char)
{
- pedwarn ("long, short, signed or unsigned used invalidly for `%s'",
- name);
- if (flag_pedantic_errors)
- ok = 0;
+ error ("long, short, signed or unsigned used invalidly for `%s'",
+ name);
+ ok = 0;
}
}
@@ -4270,9 +3755,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
/* Decide whether an integer type is signed or not.
Optionally treat bitfields as signed by default. */
if (specbits & 1 << (int) RID_UNSIGNED
- /* Traditionally, all bitfields are unsigned. */
- || (bitfield && flag_traditional
- && (! explicit_flag_signed_bitfields || !flag_signed_bitfields))
|| (bitfield && ! flag_signed_bitfields
&& (explicit_int || defaulted_int || explicit_char
/* A typedef for plain `int' without `signed'
@@ -4291,7 +3773,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
else if (type == char_type_node)
type = unsigned_char_type_node;
else if (typedef_decl)
- type = unsigned_type (type);
+ type = c_common_unsigned_type (type);
else
type = unsigned_type_node;
}
@@ -4308,7 +3790,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
if (specbits & 1 << (int) RID_COMPLEX)
{
if (pedantic && !flag_isoc99)
- pedwarn ("ISO C89 does not support complex types");
+ pedwarn ("ISO C90 does not support complex types");
/* 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
@@ -4375,6 +3857,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
if (specbits & 1 << (int) RID_REGISTER) nclasses++;
if (specbits & 1 << (int) RID_TYPEDEF) nclasses++;
+ /* "static __thread" and "extern __thread" are allowed. */
+ if ((specbits & (1 << (int) RID_THREAD
+ | 1 << (int) RID_STATIC
+ | 1 << (int) RID_EXTERN)) == (1 << (int) RID_THREAD))
+ nclasses++;
+
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
@@ -4384,7 +3872,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
&& (specbits
& ((1 << (int) RID_REGISTER)
| (1 << (int) RID_AUTO)
- | (1 << (int) RID_TYPEDEF))))
+ | (1 << (int) RID_TYPEDEF)
+ | (1 << (int) RID_THREAD))))
{
if (specbits & 1 << (int) RID_AUTO
&& (pedantic || current_binding_level == global_binding_level))
@@ -4393,8 +3882,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
error ("function definition declared `register'");
if (specbits & 1 << (int) RID_TYPEDEF)
error ("function definition declared `typedef'");
+ if (specbits & 1 << (int) RID_THREAD)
+ error ("function definition declared `__thread'");
specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
- | (1 << (int) RID_AUTO));
+ | (1 << (int) RID_AUTO) | (1 << (int) RID_THREAD));
}
else if (decl_context != NORMAL && nclasses > 0)
{
@@ -4417,7 +3908,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
}
specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
| (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
- | (1 << (int) RID_EXTERN));
+ | (1 << (int) RID_EXTERN) | (1 << (int) RID_THREAD));
}
}
else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
@@ -4428,12 +3919,25 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
else
error ("`%s' has both `extern' and initializer", name);
}
- else if (specbits & 1 << (int) RID_EXTERN && funcdef_flag
- && current_binding_level != global_binding_level)
- error ("nested function `%s' declared `extern'", name);
- else if (current_binding_level == global_binding_level
- && specbits & (1 << (int) RID_AUTO))
- error ("top-level declaration of `%s' specifies `auto'", name);
+ else if (current_binding_level == global_binding_level)
+ {
+ if (specbits & 1 << (int) RID_AUTO)
+ error ("top-level declaration of `%s' specifies `auto'", name);
+ }
+ else
+ {
+ if (specbits & 1 << (int) RID_EXTERN && funcdef_flag)
+ error ("nested function `%s' declared `extern'", name);
+ else if ((specbits & (1 << (int) RID_THREAD
+ | 1 << (int) RID_EXTERN
+ | 1 << (int) RID_STATIC))
+ == (1 << (int) RID_THREAD))
+ {
+ error ("function-scope `%s' implicitly auto and declared `__thread'",
+ name);
+ specbits &= ~(1 << (int) RID_THREAD);
+ }
+ }
}
/* Now figure out the structure of the declarator proper.
@@ -4501,7 +4005,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
tree itype = NULL_TREE;
tree size = TREE_OPERAND (declarator, 1);
/* The index is a signed object `sizetype' bits wide. */
- tree index_type = signed_type (sizetype);
+ tree index_type = c_common_signed_type (sizetype);
array_ptr_quals = TREE_TYPE (declarator);
array_parm_static = TREE_STATIC (declarator);
@@ -4522,6 +4026,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
type = error_mark_node;
}
+ if (pedantic && flexible_array_type_p (type))
+ pedwarn ("invalid use of structure with flexible array member");
+
if (size == error_mark_node)
type = error_mark_node;
@@ -4564,10 +4071,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
if (!flag_isoc99 && pedantic)
{
if (TREE_CONSTANT (size))
- pedwarn ("ISO C89 forbids array `%s' whose size can't be evaluated",
+ pedwarn ("ISO C90 forbids array `%s' whose size can't be evaluated",
name);
else
- pedwarn ("ISO C89 forbids variable-size array `%s'",
+ pedwarn ("ISO C90 forbids variable-size array `%s'",
name);
}
}
@@ -4603,14 +4110,27 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
}
if (size_varies)
- itype = variable_size (itype);
+ {
+ /* We must be able to distinguish the
+ SAVE_EXPR_CONTEXT for the variably-sized type
+ so that we can set it correctly in
+ set_save_expr_context. The convention is
+ that all SAVE_EXPRs that need to be reset
+ have NULL_TREE for their SAVE_EXPR_CONTEXT. */
+ tree cfd = current_function_decl;
+ if (decl_context == PARM)
+ current_function_decl = NULL_TREE;
+ itype = variable_size (itype);
+ if (decl_context == PARM)
+ current_function_decl = cfd;
+ }
itype = build_index_type (itype);
}
}
else if (decl_context == FIELD)
{
if (pedantic && !flag_isoc99 && !in_system_header)
- pedwarn ("ISO C89 does not support flexible array members");
+ pedwarn ("ISO C90 does not support flexible array members");
/* ISO C99 Flexible array members are effectively identical
to GCC's zero-length array extension. */
@@ -4682,13 +4202,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
type = integer_type_node;
}
-#ifndef TRADITIONAL_RETURN_FLOAT
- /* Traditionally, declaring return type float means double. */
-
- if (flag_traditional && TYPE_MAIN_VARIANT (type) == float_type_node)
- type = double_type_node;
-#endif /* TRADITIONAL_RETURN_FLOAT */
-
/* Construct the function type and go to the next
inner layer of declarator. */
@@ -4976,11 +4489,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
if (type == error_mark_node)
promoted_type = type;
else
- {
- promoted_type = simple_type_promotes_to (type);
- if (! promoted_type)
- promoted_type = type;
- }
+ promoted_type = c_type_promotes_to (type);
DECL_ARG_TYPE (decl) = promoted_type;
DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written;
@@ -5032,6 +4541,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
pedwarn ("invalid storage class for function `%s'", name);
if (specbits & (1 << (int) RID_REGISTER))
error ("invalid storage class for function `%s'", name);
+ if (specbits & (1 << (int) RID_THREAD))
+ error ("invalid storage class for function `%s'", name);
/* Function declaration not at top level.
Storage classes other than `extern' are not allowed
and `extern' makes no difference. */
@@ -5091,6 +4602,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
needed, and let dwarf2 know that the function is inlinable. */
else if (flag_inline_trees == 2 && initialized)
{
+ if (!DECL_INLINE (decl))
+ DID_INLINE_FUNC (decl) = 1;
DECL_INLINE (decl) = 1;
DECL_DECLARED_INLINE_P (decl) = 0;
}
@@ -5124,22 +4637,32 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
pedwarn_with_decl (decl, "variable `%s' declared `inline'");
DECL_EXTERNAL (decl) = extern_ref;
+
/* At top level, the presence of a `static' or `register' storage
class specifier, or the absence of all storage class specifiers
makes this declaration a definition (perhaps tentative). Also,
the absence of both `static' and `register' makes it public. */
if (current_binding_level == global_binding_level)
{
- TREE_PUBLIC (decl)
- = !(specbits
- & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)));
- TREE_STATIC (decl) = ! DECL_EXTERNAL (decl);
+ TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC)
+ | (1 << (int) RID_REGISTER)));
+ TREE_STATIC (decl) = !extern_ref;
}
/* Not at top level, only `static' makes a static definition. */
else
{
TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
- TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
+ TREE_PUBLIC (decl) = extern_ref;
+ }
+
+ if (specbits & 1 << (int) RID_THREAD)
+ {
+ if (targetm.have_tls)
+ DECL_THREAD_LOCAL (decl) = 1;
+ else
+ /* A mere warning is sure to result in improper semantics
+ at runtime. Don't bother to allow this to compile. */
+ error ("thread-local storage not supported for this target");
}
}
@@ -5156,7 +4679,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
Otherwise, the fact that those components are volatile
will be ignored, and would even crash the compiler. */
if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
- mark_addressable (decl);
+ c_mark_addressable (decl);
decl_attributes (&decl, returned_attrs, 0);
@@ -5491,25 +5014,22 @@ start_struct (code, name)
ref = lookup_tag (code, name, current_binding_level, 1);
if (ref && TREE_CODE (ref) == code)
{
- C_TYPE_BEING_DEFINED (ref) = 1;
- TYPE_PACKED (ref) = flag_pack_struct;
if (TYPE_FIELDS (ref))
{
if (code == UNION_TYPE)
- error ("redefinition of `union %s'",
- IDENTIFIER_POINTER (name));
+ error ("redefinition of `union %s'", IDENTIFIER_POINTER (name));
else
- error ("redefinition of `struct %s'",
- IDENTIFIER_POINTER (name));
+ error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name));
}
-
- return ref;
}
+ else
+ {
+ /* Otherwise create a forward-reference just so the tag is in scope. */
- /* Otherwise create a forward-reference just so the tag is in scope. */
-
- ref = make_node (code);
- pushtag (name, ref);
+ ref = make_node (code);
+ pushtag (name, ref);
+ }
+
C_TYPE_BEING_DEFINED (ref) = 1;
TYPE_PACKED (ref) = flag_pack_struct;
return ref;
@@ -5533,15 +5053,44 @@ grokfield (filename, line, declarator, declspecs, width)
if (declarator == NULL_TREE && width == NULL_TREE)
{
- /* This is an unnamed decl. We only support unnamed
- structs/unions, so check for other things and refuse them. */
+ /* This is an unnamed decl.
+
+ If we have something of the form "union { list } ;" then this
+ is the anonymous union extension. Similarly for struct.
+
+ If this is something of the form "struct foo;", then
+ If MS extensions are enabled, this is handled as an
+ anonymous struct.
+ Otherwise this is a forward declaration of a structure tag.
+
+ If this is something of the form "foo;" and foo is a TYPE_DECL, then
+ If MS extensions are enabled and foo names a structure, then
+ again this is an anonymous struct.
+ Otherwise this is an error.
+
+ Oh what a horrid tangled web we weave. I wonder if MS consiously
+ took this from Plan 9 or if it was an accident of implementation
+ that took root before someone noticed the bug... */
+
tree type = TREE_VALUE (declspecs);
- if (TREE_CODE (type) == TYPE_DECL)
+ if (flag_ms_extensions && TREE_CODE (type) == TYPE_DECL)
type = TREE_TYPE (type);
- if (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE)
+ if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)
+ {
+ if (flag_ms_extensions)
+ ; /* ok */
+ else if (flag_iso)
+ goto warn_unnamed_field;
+ else if (TYPE_NAME (type) == NULL)
+ ; /* ok */
+ else
+ goto warn_unnamed_field;
+ }
+ else
{
- error ("unnamed fields of type other than struct or union are not allowed");
+ warn_unnamed_field:
+ warning ("declaration does not declare anything");
return NULL_TREE;
}
}
@@ -5551,7 +5100,8 @@ grokfield (filename, line, declarator, declspecs, width)
finish_decl (value, NULL_TREE, NULL_TREE);
DECL_INITIAL (value) = width;
- maybe_objc_check_decl (value);
+ if (flag_objc)
+ objc_check_decl (value);
return value;
}
@@ -5584,7 +5134,7 @@ finish_struct (t, fieldlist, attributes)
if (pedantic)
pedwarn ("%s defined inside parms",
TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
- else if (! flag_traditional)
+ else
warning ("%s defined inside parms",
TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
}
@@ -5727,18 +5277,6 @@ finish_struct (t, fieldlist, attributes)
}
}
- else if (TREE_TYPE (x) != error_mark_node)
- {
- unsigned int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT
- : TYPE_ALIGN (TREE_TYPE (x)));
-
- /* Non-bit-fields are aligned for their type, except packed
- fields which require only BITS_PER_UNIT alignment. */
- DECL_ALIGN (x) = MAX (DECL_ALIGN (x), min_align);
- if (! DECL_PACKED (x))
- DECL_USER_ALIGN (x) |= TYPE_USER_ALIGN (TREE_TYPE (x));
- }
-
DECL_INITIAL (x) = 0;
/* Detect flexible array member in an invalid context. */
@@ -5754,6 +5292,11 @@ finish_struct (t, fieldlist, attributes)
else if (! saw_named_field)
error_with_decl (x, "flexible array member in otherwise empty struct");
}
+
+ if (pedantic && TREE_CODE (t) == RECORD_TYPE
+ && flexible_array_type_p (TREE_TYPE (x)))
+ pedwarn_with_decl (x, "invalid use of structure with flexible array member");
+
if (DECL_NAME (x))
saw_named_field = 1;
}
@@ -5827,22 +5370,29 @@ finish_struct (t, fieldlist, attributes)
/* If this structure or union completes the type of any previous
variable declaration, lay it out and output its rtl. */
- if (current_binding_level->n_incomplete != 0)
+ if (current_binding_level->incomplete_list != NULL_TREE)
{
- tree decl;
- for (decl = current_binding_level->names; decl; decl = TREE_CHAIN (decl))
- {
+ tree prev = NULL_TREE;
+
+ for (x = current_binding_level->incomplete_list; x; x = TREE_CHAIN (x))
+ {
+ tree decl = TREE_VALUE (x);
+
if (TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TYPE_MAIN_VARIANT (t)
&& TREE_CODE (decl) != TYPE_DECL)
{
layout_decl (decl, 0);
- /* This is a no-op in c-lang.c or something real in objc-actions.c. */
- maybe_objc_check_decl (decl);
+ /* This is a no-op in c-lang.c or something real in objc-act.c. */
+ if (flag_objc)
+ objc_check_decl (decl);
rest_of_decl_compilation (decl, NULL, toplevel, 0);
if (! toplevel)
expand_decl (decl);
- if (--current_binding_level->n_incomplete == 0)
- break;
+ /* Unlink X from the incomplete list. */
+ if (prev)
+ TREE_CHAIN (prev) = TREE_CHAIN (x);
+ else
+ current_binding_level->incomplete_list = TREE_CHAIN (x);
}
else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
@@ -5856,13 +5406,17 @@ finish_struct (t, fieldlist, attributes)
if (TREE_CODE (decl) != TYPE_DECL)
{
layout_decl (decl, 0);
- maybe_objc_check_decl (decl);
+ if (flag_objc)
+ objc_check_decl (decl);
rest_of_decl_compilation (decl, NULL, toplevel, 0);
if (! toplevel)
expand_decl (decl);
}
- if (--current_binding_level->n_incomplete == 0)
- break;
+ /* Unlink X from the incomplete list. */
+ if (prev)
+ TREE_CHAIN (prev) = TREE_CHAIN (x);
+ else
+ current_binding_level->incomplete_list = TREE_CHAIN (x);
}
}
}
@@ -5979,7 +5533,7 @@ finish_enum (enumtype, values, attributes)
min_precision (maxnode, unsign));
if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
{
- tree narrowest = type_for_size (precision, unsign);
+ tree narrowest = c_common_type_for_size (precision, unsign);
if (narrowest == 0)
{
warning ("enumeration values exceed range of largest integer");
@@ -5992,7 +5546,7 @@ finish_enum (enumtype, values, attributes)
precision = TYPE_PRECISION (integer_type_node);
if (precision == TYPE_PRECISION (integer_type_node))
- enum_value_type = type_for_size (precision, 0);
+ enum_value_type = c_common_type_for_size (precision, 0);
else
enum_value_type = enumtype;
@@ -6120,11 +5674,11 @@ build_enumerator (name, value)
/* Now create a declaration for the enum value name. */
type = TREE_TYPE (value);
- type = type_for_size (MAX (TYPE_PRECISION (type),
- TYPE_PRECISION (integer_type_node)),
- ((flag_traditional
- || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))
- && TREE_UNSIGNED (type)));
+ type = c_common_type_for_size (MAX (TYPE_PRECISION (type),
+ TYPE_PRECISION (integer_type_node)),
+ (TYPE_PRECISION (type)
+ >= TYPE_PRECISION (integer_type_node)
+ && TREE_UNSIGNED (type)));
decl = build_decl (CONST_DECL, name, type);
DECL_INITIAL (decl) = convert (type, value);
@@ -6159,7 +5713,6 @@ start_function (declspecs, declarator, attributes)
current_function_returns_abnormally = 0;
warn_about_return_type = 0;
current_extern_inline = 0;
- c_function_varargs = 0;
named_labels = 0;
shadowed_labels = 0;
@@ -6356,12 +5909,10 @@ start_function (declspecs, declarator, attributes)
/* Promote the value to int before returning it. */
if (c_promoting_integer_type_p (restype))
{
- /* It retains unsignedness if traditional
- or if not really getting wider. */
+ /* It retains unsignedness if not really getting wider. */
if (TREE_UNSIGNED (restype)
- && (flag_traditional
- || (TYPE_PRECISION (restype)
- == TYPE_PRECISION (integer_type_node))))
+ && (TYPE_PRECISION (restype)
+ == TYPE_PRECISION (integer_type_node)))
restype = unsigned_type_node;
else
restype = integer_type_node;
@@ -6380,16 +5931,6 @@ start_function (declspecs, declarator, attributes)
return 1;
}
-
-/* Record that this function is going to be a varargs function.
- This is called before store_parm_decls, which is too early
- to call mark_varargs directly. */
-
-void
-c_mark_varargs ()
-{
- c_function_varargs = 1;
-}
/* Store the parameter declarations into the current function declaration.
This is called after parsing the parameter declarations, before
@@ -6580,15 +6121,6 @@ store_parm_decls ()
layout_decl (found, 0);
}
- /* Traditionally, a parm declared float is actually a double. */
- if (found && flag_traditional
- && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == float_type_node)
- {
- TREE_TYPE (found) = double_type_node;
- DECL_ARG_TYPE (found) = double_type_node;
- layout_decl (found, 0);
- }
-
/* If no declaration found, default to int. */
if (!found)
{
@@ -6722,11 +6254,7 @@ store_parm_decls ()
"prototype declaration");
}
}
- /* If -traditional, allow `int' argument to match
- `unsigned' prototype. */
- else if (! (flag_traditional
- && TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == integer_type_node
- && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node))
+ else
{
error ("argument `%s' doesn't match prototype",
IDENTIFIER_POINTER (DECL_NAME (parm)));
@@ -6861,13 +6389,6 @@ finish_function (nested, can_defer_p)
DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
- /* Obey `register' declarations if `setjmp' is called in this fn. */
- if (flag_traditional && current_function_calls_setjmp)
- {
- setjmp_protect (DECL_INITIAL (fndecl));
- setjmp_protect_args ();
- }
-
if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted)
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
@@ -6924,7 +6445,7 @@ finish_function (nested, can_defer_p)
/* Let the error reporting routines know that we're outside a
function. For a nested function, this value is used in
- pop_c_function_context and then reset via pop_function_context. */
+ c_pop_function_context and then reset via pop_function_context. */
current_function_decl = NULL;
}
}
@@ -6944,7 +6465,27 @@ c_expand_deferred_function (fndecl)
}
}
-/* Generate the RTL for the body of FNDECL. If NESTED_P is non-zero,
+/* Called to move the SAVE_EXPRs for parameter declarations in a
+ nested function into the nested function. DATA is really the
+ nested FUNCTION_DECL. */
+
+static tree
+set_save_expr_context (tp, walk_subtrees, data)
+ tree *tp;
+ int *walk_subtrees;
+ void *data;
+{
+ if (TREE_CODE (*tp) == SAVE_EXPR && !SAVE_EXPR_CONTEXT (*tp))
+ SAVE_EXPR_CONTEXT (*tp) = (tree) data;
+ /* Do not walk back into the SAVE_EXPR_CONTEXT; that will cause
+ circularity. */
+ else if (DECL_P (*tp))
+ *walk_subtrees = 0;
+
+ return NULL_TREE;
+}
+
+/* Generate the RTL for the body of FNDECL. If NESTED_P is nonzero,
then we are already in the process of generating RTL for another
function. If can_defer_p is zero, we won't attempt to defer the
generation of RTL. */
@@ -6955,12 +6496,19 @@ c_expand_body (fndecl, nested_p, can_defer_p)
int nested_p, can_defer_p;
{
int uninlinable = 1;
+ int saved_lineno;
+ const char *saved_input_filename;
/* There's no reason to do any of the work here if we're only doing
semantic analysis; this code just generates RTL. */
if (flag_syntax_only)
return;
+ saved_lineno = lineno;
+ saved_input_filename = input_filename;
+ lineno = DECL_SOURCE_LINE (fndecl);
+ input_filename = DECL_SOURCE_FILE (fndecl);
+
if (flag_inline_trees)
{
/* First, cache whether the current function is inlinable. Some
@@ -6978,6 +6526,8 @@ c_expand_body (fndecl, nested_p, can_defer_p)
/* Let the back-end know that this function exists. */
(*debug_hooks->deferred_inline_function) (fndecl);
timevar_pop (TV_INTEGRATION);
+ lineno = saved_lineno;
+ input_filename = saved_input_filename;
return;
}
@@ -6999,7 +6549,6 @@ c_expand_body (fndecl, nested_p, can_defer_p)
/* Initialize the RTL code for the function. */
current_function_decl = fndecl;
- input_filename = DECL_SOURCE_FILE (fndecl);
init_function_start (fndecl, input_filename, DECL_SOURCE_LINE (fndecl));
/* This function is being processed in whole-function mode. */
@@ -7012,13 +6561,18 @@ c_expand_body (fndecl, nested_p, can_defer_p)
immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1;
- /* If this is a varargs function, inform function.c. */
- if (c_function_varargs)
- mark_varargs ();
-
/* Set up parameters and prepare for return, for the function. */
expand_function_start (fndecl, 0);
+ /* If the function has a variably modified type, there may be
+ SAVE_EXPRs in the parameter types. Their context must be set to
+ refer to this function; they cannot be expanded in the containing
+ function. */
+ if (decl_function_context (fndecl)
+ && variably_modified_type_p (TREE_TYPE (fndecl)))
+ walk_tree (&TREE_TYPE (fndecl), set_save_expr_context, fndecl,
+ NULL);
+
/* If this function is `main', emit a call to `__main'
to run global initializers, etc. */
if (DECL_NAME (fndecl)
@@ -7028,7 +6582,9 @@ c_expand_body (fndecl, nested_p, can_defer_p)
/* Generate the RTL for this function. */
expand_stmt (DECL_SAVED_TREE (fndecl));
- if (uninlinable)
+
+ /* Keep the function body if it's needed for inlining or dumping. */
+ if (uninlinable && !dump_enabled_p (TDI_all))
{
/* Allow the body of the function to be garbage collected. */
DECL_SAVED_TREE (fndecl) = NULL_TREE;
@@ -7099,7 +6655,7 @@ c_expand_body (fndecl, nested_p, can_defer_p)
/* 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.
- For a nested function, this is done in pop_c_function_context.
+ For a nested function, this is done in c_pop_function_context.
If rest_of_compilation set this to 0, leave it 0. */
if (DECL_INITIAL (fndecl) != 0)
DECL_INITIAL (fndecl) = error_mark_node;
@@ -7129,6 +6685,9 @@ c_expand_body (fndecl, nested_p, can_defer_p)
/* Return to the enclosing function. */
pop_function_context ();
timevar_pop (TV_EXPAND);
+
+ lineno = saved_lineno;
+ input_filename = saved_input_filename;
}
/* Check the declarations given in a for-loop for satisfying the C99
@@ -7193,9 +6752,9 @@ check_for_loop_decls ()
that keep track of the progress of compilation of the current function.
Used for nested functions. */
-struct c_language_function
+struct language_function GTY(())
{
- struct language_function base;
+ struct c_language_function base;
tree named_labels;
tree shadowed_labels;
int returns_value;
@@ -7210,13 +6769,13 @@ struct c_language_function
used during compilation of a C function. */
void
-push_c_function_context (f)
+c_push_function_context (f)
struct function *f;
{
- struct c_language_function *p;
- p = ((struct c_language_function *)
- xmalloc (sizeof (struct c_language_function)));
- f->language = (struct language_function *) p;
+ struct language_function *p;
+ p = ((struct language_function *)
+ ggc_alloc (sizeof (struct language_function)));
+ f->language = p;
p->base.x_stmt_tree = c_stmt_tree;
p->base.x_scope_stmt_stack = c_scope_stmt_stack;
@@ -7233,11 +6792,10 @@ push_c_function_context (f)
/* Restore the variables used during compilation of a C function. */
void
-pop_c_function_context (f)
+c_pop_function_context (f)
struct function *f;
{
- struct c_language_function *p
- = (struct c_language_function *) f->language;
+ struct language_function *p = f->language;
tree link;
/* Bring back all the labels that were shadowed. */
@@ -7267,32 +6825,13 @@ pop_c_function_context (f)
current_extern_inline = p->extern_inline;
current_binding_level = p->binding_level;
- free (p);
- f->language = 0;
+ f->language = NULL;
}
-/* Mark the language specific parts of F for GC. */
+/* Copy the DECL_LANG_SPECIFIC data associated with DECL. */
void
-mark_c_function_context (f)
- struct function *f;
-{
- struct c_language_function *p
- = (struct c_language_function *) f->language;
-
- if (p == 0)
- return;
-
- mark_c_language_function (&p->base);
- ggc_mark_tree (p->shadowed_labels);
- ggc_mark_tree (p->named_labels);
- mark_binding_level (&p->binding_level);
-}
-
-/* Copy the DECL_LANG_SPECIFIC data associated with NODE. */
-
-void
-copy_lang_decl (decl)
+c_dup_lang_specific_decl (decl)
tree decl;
{
struct lang_decl *ld;
@@ -7306,38 +6845,12 @@ copy_lang_decl (decl)
DECL_LANG_SPECIFIC (decl) = ld;
}
-/* Mark the language specific bits in T for GC. */
-
-void
-lang_mark_tree (t)
- tree t;
-{
- if (TREE_CODE (t) == IDENTIFIER_NODE)
- {
- struct lang_identifier *i = (struct lang_identifier *) t;
- ggc_mark_tree (i->global_value);
- ggc_mark_tree (i->local_value);
- ggc_mark_tree (i->label_value);
- ggc_mark_tree (i->implicit_decl);
- ggc_mark_tree (i->error_locus);
- ggc_mark_tree (i->limbo_value);
- }
- else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
- ggc_mark (TYPE_LANG_SPECIFIC (t));
- else if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
- {
- ggc_mark (DECL_LANG_SPECIFIC (t));
- c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base);
- ggc_mark_tree (DECL_LANG_SPECIFIC (t)->pending_sizes);
- }
-}
-
/* The functions below are required for functionality of doing
function at once processing in the C front end. Currently these
functions are not called from anywhere in the C front end, but as
these changes continue, that will change. */
-/* Returns non-zero if the current statement is a full expression,
+/* Returns nonzero if the current statement is a full expression,
i.e. temporaries created during that statement should be destroyed
at the end of the statement. */
@@ -7446,3 +6959,26 @@ build_void_list_node ()
tree t = build_tree_list (NULL_TREE, void_type_node);
return t;
}
+
+/* Return something to represent absolute declarators containing a *.
+ TARGET is the absolute declarator that the * contains.
+ TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
+ to apply to the pointer type, represented as identifiers, possible mixed
+ with attributes.
+
+ We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST,
+ if attributes are present) and whose type is the modifier list. */
+
+tree
+make_pointer_declarator (type_quals_attrs, target)
+ tree type_quals_attrs, target;
+{
+ tree quals, attrs;
+ tree itarget = target;
+ split_specs_attrs (type_quals_attrs, &quals, &attrs);
+ if (attrs != NULL_TREE)
+ itarget = tree_cons (attrs, target, NULL_TREE);
+ return build1 (INDIRECT_REF, quals, itarget);
+}
+
+#include "gt-c-decl.h"
diff --git a/contrib/gcc/c-dump.c b/contrib/gcc/c-dump.c
new file mode 100644
index 0000000..65407a5
--- /dev/null
+++ b/contrib/gcc/c-dump.c
@@ -0,0 +1,196 @@
+/* Tree-dumping functionality for C-family languages.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Written by Mark Mitchell <mark@codesourcery.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "tree.h"
+#include "c-tree.h"
+#include "tree-dump.h"
+
+/* Dump information common to statements from STMT. */
+
+void
+dump_stmt (di, t)
+ dump_info_p di;
+ tree t;
+{
+ dump_int (di, "line", STMT_LINENO (t));
+}
+
+/* Dump the next statement after STMT. */
+
+void
+dump_next_stmt (di, t)
+ dump_info_p di;
+ tree t;
+{
+ dump_child ("next", TREE_CHAIN (t));
+}
+
+/* Dump any C-specific tree codes and attributes of common codes. */
+
+int
+c_dump_tree (dump_info, t)
+ void *dump_info;
+ tree t;
+{
+ enum tree_code code;
+ dump_info_p di = (dump_info_p) dump_info;
+
+ /* Figure out what kind of node this is. */
+ code = TREE_CODE (t);
+
+ switch (code)
+ {
+ case FIELD_DECL:
+ if (DECL_C_BIT_FIELD (t))
+ dump_string (di, "bitfield");
+ break;
+
+ case ASM_STMT:
+ dump_stmt (di, t);
+ if (ASM_VOLATILE_P (t))
+ dump_string (di, "volatile");
+ dump_child ("strg", ASM_STRING (t));
+ dump_child ("outs", ASM_OUTPUTS (t));
+ dump_child ("ins", ASM_INPUTS (t));
+ dump_child ("clbr", ASM_CLOBBERS (t));
+ dump_next_stmt (di, t);
+ break;
+
+ case BREAK_STMT:
+ case CONTINUE_STMT:
+ dump_stmt (di, t);
+ dump_next_stmt (di, t);
+ break;
+
+ case CASE_LABEL:
+ /* Note that a case label is not like other statements; there is
+ no way to get the line-number of a case label. */
+ dump_child ("low", CASE_LOW (t));
+ dump_child ("high", CASE_HIGH (t));
+ dump_next_stmt (di, t);
+ break;
+
+ case CLEANUP_STMT:
+ dump_stmt (di, t);
+ dump_child ("decl", CLEANUP_DECL (t));
+ dump_child ("expr", CLEANUP_EXPR (t));
+ dump_next_stmt (di, t);
+ break;
+
+ case COMPOUND_STMT:
+ dump_stmt (di, t);
+ dump_child ("body", COMPOUND_BODY (t));
+ dump_next_stmt (di, t);
+ break;
+
+ case DECL_STMT:
+ dump_stmt (di, t);
+ dump_child ("decl", DECL_STMT_DECL (t));
+ dump_next_stmt (di, t);
+ break;
+
+ case DO_STMT:
+ dump_stmt (di, t);
+ dump_child ("body", DO_BODY (t));
+ dump_child ("cond", DO_COND (t));
+ dump_next_stmt (di, t);
+ break;
+
+ case EXPR_STMT:
+ dump_stmt (di, t);
+ dump_child ("expr", EXPR_STMT_EXPR (t));
+ dump_next_stmt (di, t);
+ break;
+
+ case FOR_STMT:
+ dump_stmt (di, t);
+ dump_child ("init", FOR_INIT_STMT (t));
+ dump_child ("cond", FOR_COND (t));
+ dump_child ("expr", FOR_EXPR (t));
+ dump_child ("body", FOR_BODY (t));
+ dump_next_stmt (di, t);
+ break;
+
+ case GOTO_STMT:
+ dump_stmt (di, t);
+ dump_child ("dest", GOTO_DESTINATION (t));
+ dump_next_stmt (di, t);
+ break;
+
+ case IF_STMT:
+ dump_stmt (di, t);
+ dump_child ("cond", IF_COND (t));
+ dump_child ("then", THEN_CLAUSE (t));
+ dump_child ("else", ELSE_CLAUSE (t));
+ dump_next_stmt (di, t);
+ break;
+
+ case LABEL_STMT:
+ dump_stmt (di, t);
+ dump_child ("labl", LABEL_STMT_LABEL (t));
+ dump_next_stmt (di, t);
+ break;
+
+ case RETURN_STMT:
+ dump_stmt (di, t);
+ dump_child ("expr", RETURN_STMT_EXPR (t));
+ dump_next_stmt (di, t);
+ break;
+
+ case SWITCH_STMT:
+ dump_stmt (di, t);
+ dump_child ("cond", SWITCH_COND (t));
+ dump_child ("body", SWITCH_BODY (t));
+ dump_next_stmt (di, t);
+ break;
+
+ case WHILE_STMT:
+ dump_stmt (di, t);
+ dump_child ("cond", WHILE_COND (t));
+ dump_child ("body", WHILE_BODY (t));
+ dump_next_stmt (di, t);
+ break;
+
+ case SCOPE_STMT:
+ dump_stmt (di, t);
+ if (SCOPE_BEGIN_P (t))
+ dump_string (di, "begn");
+ else
+ dump_string (di, "end");
+ if (SCOPE_NULLIFIED_P (t))
+ dump_string (di, "null");
+ if (!SCOPE_NO_CLEANUPS_P (t))
+ dump_string (di, "clnp");
+ dump_next_stmt (di, t);
+ break;
+
+ case STMT_EXPR:
+ dump_child ("stmt", STMT_EXPR_STMT (t));
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
diff --git a/contrib/gcc/c-errors.c b/contrib/gcc/c-errors.c
index 3f030f9..1bd52a8 100644
--- a/contrib/gcc/c-errors.c
+++ b/contrib/gcc/c-errors.c
@@ -32,13 +32,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
void
pedwarn_c99 VPARAMS ((const char *msgid, ...))
{
- diagnostic_context dc;
-
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
- set_diagnostic_context (&dc, msgid, &ap, input_filename, lineno,
- !flag_isoc99 || !flag_pedantic_errors);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, msgid, &ap, input_filename, lineno,
+ flag_isoc99 ? pedantic_error_kind () : DK_WARNING);
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
}
diff --git a/contrib/gcc/c-format.c b/contrib/gcc/c-format.c
index 658ca30..083e912 100644
--- a/contrib/gcc/c-format.c
+++ b/contrib/gcc/c-format.c
@@ -27,31 +27,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "c-common.h"
#include "intl.h"
#include "diagnostic.h"
-
+#include "langhooks.h"
-/* Command line options and their associated flags. */
-
-/* Warn about format/argument anomalies in calls to formatted I/O functions
- (*printf, *scanf, strftime, strfmon, etc.). */
-
-int warn_format;
-
-/* Warn about Y2K problems with strftime formats. */
-
-int warn_format_y2k;
-
-/* Warn about excess arguments to formats. */
-
-int warn_format_extra_args;
-
-/* Warn about non-literal format arguments. */
-
-int warn_format_nonliteral;
-
-/* Warn about possible security problems with calls to format functions. */
-
-int warn_format_security;
-
/* Set format warning options according to a -Wformat=n option. */
void
@@ -61,11 +38,15 @@ set_Wformat (setting)
warn_format = setting;
warn_format_y2k = setting;
warn_format_extra_args = setting;
+ warn_format_zero_length = setting;
if (setting != 1)
{
warn_format_nonliteral = setting;
warn_format_security = setting;
}
+ /* Make sure not to disable -Wnonnull if -Wformat=0 is specified. */
+ if (setting)
+ warn_nonnull = setting;
}
@@ -305,7 +286,7 @@ decode_format_attr (args, info, validated_p)
/* Check a call to a format function against a parameter list. */
-/* The meaningfully distinct length modifiers for format checking recognised
+/* The meaningfully distinct length modifiers for format checking recognized
by GCC. */
enum format_lengths
{
@@ -348,7 +329,7 @@ enum format_std_version
? "ISO C++" \
: ((FEATURE_VER) == STD_EXT \
? "ISO C" \
- : "ISO C89"))
+ : "ISO C90"))
/* Adjust a C standard version, which may be STD_C9L, to account for
-Wno-long-long. Returns other standard versions unchanged. */
#define ADJ_STD(VER) ((int)((VER) == STD_C9L \
@@ -458,7 +439,7 @@ typedef struct
/* The flag character in question (0 for end of array). */
const int flag_char;
/* Zero if this entry describes the flag character in general, or a
- non-zero character that may be found in flags2 if it describes the
+ nonzero character that may be found in flags2 if it describes the
flag when used with certain formats only. If the latter, only
the first such entry found that applies to the current conversion
specifier is used; the values of `name' and `long_name' it supplies
@@ -488,11 +469,11 @@ typedef struct
const int flag_char1;
/* The second flag character. */
const int flag_char2;
- /* Non-zero if the message should say that the first flag is ignored with
+ /* Nonzero if the message should say that the first flag is ignored with
the second, zero if the combination should simply be objected to. */
const int ignored;
/* Zero if this entry applies whenever this flag combination occurs,
- a non-zero character from flags2 if it only applies in some
+ a nonzero character from flags2 if it only applies in some
circumstances (e.g. 'i' for printf formats ignoring 0 with precision). */
const int predicate;
} format_flag_pair;
@@ -709,7 +690,6 @@ static const format_flag_pair strfmon_flag_pairs[] =
#define T_I &integer_type_node
#define T89_I { STD_C89, NULL, T_I }
-#define T99_I { STD_C99, NULL, T_I }
#define T_L &long_integer_type_node
#define T89_L { STD_C89, NULL, T_L }
#define T_LL &long_long_integer_type_node
@@ -719,7 +699,6 @@ static const format_flag_pair strfmon_flag_pairs[] =
#define T89_S { STD_C89, NULL, T_S }
#define T_UI &unsigned_type_node
#define T89_UI { STD_C89, NULL, T_UI }
-#define T99_UI { STD_C99, NULL, T_UI }
#define T_UL &long_unsigned_type_node
#define T89_UL { STD_C89, NULL, T_UL }
#define T_ULL &long_long_unsigned_type_node
@@ -895,10 +874,16 @@ typedef struct
int number_other;
} format_check_results;
+typedef struct
+{
+ format_check_results *res;
+ function_format_info *info;
+ tree params;
+ int *status;
+} format_check_context;
+
static void check_format_info PARAMS ((int *, function_format_info *, tree));
-static void check_format_info_recurse PARAMS ((int *, format_check_results *,
- function_format_info *, tree,
- tree, unsigned HOST_WIDE_INT));
+static void check_format_arg PARAMS ((void *, tree, unsigned HOST_WIDE_INT));
static void check_format_info_main PARAMS ((int *, format_check_results *,
function_format_info *,
const char *, int, tree,
@@ -1011,7 +996,7 @@ check_function_format (status, attrs, params)
static void
status_warning VPARAMS ((int *status, const char *msgid, ...))
{
- diagnostic_context dc;
+ diagnostic_info diagnostic ;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, int *, status);
@@ -1022,9 +1007,9 @@ status_warning VPARAMS ((int *status, const char *msgid, ...))
else
{
/* This duplicates the warning function behavior. */
- set_diagnostic_context
- (&dc, msgid, &ap, input_filename, lineno, /* warn = */ 1);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, _(msgid), &ap, input_filename, lineno,
+ DK_WARNING);
+ report_diagnostic (&diagnostic);
}
VA_CLOSE (ap);
@@ -1289,6 +1274,7 @@ check_format_info (status, info, params)
function_format_info *info;
tree params;
{
+ format_check_context format_ctx;
unsigned HOST_WIDE_INT arg_num;
tree format_tree;
format_check_results res;
@@ -1315,7 +1301,13 @@ check_format_info (status, info, params)
res.number_unterminated = 0;
res.number_other = 0;
- check_format_info_recurse (status, &res, info, format_tree, params, arg_num);
+ format_ctx.res = &res;
+ format_ctx.info = info;
+ format_ctx.params = params;
+ format_ctx.status = status;
+
+ check_function_arguments_recurse (check_format_arg, &format_ctx,
+ format_tree, arg_num);
if (res.number_non_literal > 0)
{
@@ -1361,8 +1353,9 @@ check_format_info (status, info, params)
&& res.number_other == 0 && warn_format_extra_args)
status_warning (status, "unused arguments in $-style format");
if (res.number_empty > 0 && res.number_non_literal == 0
- && res.number_other == 0)
- status_warning (status, "zero-length format string");
+ && res.number_other == 0 && warn_format_zero_length)
+ status_warning (status, "zero-length %s format string",
+ format_types[info->format_type].name);
if (res.number_wide > 0)
status_warning (status, "format is a wide character string");
@@ -1371,112 +1364,31 @@ check_format_info (status, info, params)
status_warning (status, "unterminated format string");
}
-
-/* Recursively check a call to a format function. FORMAT_TREE is the
- format parameter, which may be a conditional expression in which
- both halves should be checked. ARG_NUM is the number of the
- format argument; PARAMS points just after it in the argument list. */
+/* Callback from check_function_arguments_recurse to check a
+ format string. FORMAT_TREE is the format parameter. ARG_NUM
+ is the number of the format argument. CTX points to a
+ format_check_context. */
static void
-check_format_info_recurse (status, res, info, format_tree, params, arg_num)
- int *status;
- format_check_results *res;
- function_format_info *info;
+check_format_arg (ctx, format_tree, arg_num)
+ void *ctx;
tree format_tree;
- tree params;
unsigned HOST_WIDE_INT arg_num;
{
+ format_check_context *format_ctx = ctx;
+ format_check_results *res = format_ctx->res;
+ function_format_info *info = format_ctx->info;
+ tree params = format_ctx->params;
+ int *status = format_ctx->status;
+
int format_length;
HOST_WIDE_INT offset;
const char *format_chars;
tree array_size = 0;
tree array_init;
- if (TREE_CODE (format_tree) == NOP_EXPR)
- {
- /* Strip coercion. */
- check_format_info_recurse (status, res, info,
- TREE_OPERAND (format_tree, 0), params,
- arg_num);
- return;
- }
-
- if (TREE_CODE (format_tree) == CALL_EXPR)
- {
- tree type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (format_tree, 0)));
- tree attrs;
- bool found_format_arg = false;
-
- /* See if this is a call to a known internationalization function
- that modifies the format arg. Such a function may have multiple
- format_arg attributes (for example, ngettext). */
-
- for (attrs = TYPE_ATTRIBUTES (type);
- attrs;
- attrs = TREE_CHAIN (attrs))
- if (is_attribute_p ("format_arg", TREE_PURPOSE (attrs)))
- {
- tree inner_args;
- tree format_num_expr;
- int format_num;
- int i;
-
- /* Extract the argument number, which was previously checked
- to be valid. */
- format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
- 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
- || TREE_INT_CST_HIGH (format_num_expr) != 0)
- abort ();
-
- format_num = TREE_INT_CST_LOW (format_num_expr);
-
- for (inner_args = TREE_OPERAND (format_tree, 1), i = 1;
- inner_args != 0;
- inner_args = TREE_CHAIN (inner_args), i++)
- if (i == format_num)
- {
- check_format_info_recurse (status, res, info,
- TREE_VALUE (inner_args), params,
- arg_num);
- found_format_arg = true;
- break;
- }
- }
-
- /* If we found a format_arg attribute and did a recursive check,
- we are done with checking this format string. Otherwise, we
- continue and this will count as a non-literal format string. */
- if (found_format_arg)
- return;
- }
-
- if (TREE_CODE (format_tree) == COND_EXPR)
- {
- /* Check both halves of the conditional expression. */
- check_format_info_recurse (status, res, info,
- TREE_OPERAND (format_tree, 1), params,
- arg_num);
- check_format_info_recurse (status, res, info,
- TREE_OPERAND (format_tree, 2), params,
- arg_num);
- return;
- }
-
if (integer_zerop (format_tree))
{
- /* FIXME: this warning should go away once Marc Espie's
- __attribute__((nonnull)) patch is in. Instead, checking for
- nonnull attributes should probably change this function to act
- specially if info == NULL and add a res->number_null entry for
- that case, or maybe add a function pointer to be called at
- the end instead of hardcoding check_format_info_main. */
- status_warning (status, "null format string");
-
/* Skip to first argument to check, so we can see if this format
has any arguments (it shouldn't). */
while (arg_num + 1 < info->first_arg_num)
@@ -1751,11 +1663,6 @@ check_format_info_main (status, res, info, format_chars, format_length,
/* "...a field width...may be indicated by an asterisk.
In this case, an int argument supplies the field width..." */
++format_chars;
- if (params == 0)
- {
- status_warning (status, "too few arguments for format");
- return;
- }
if (has_operand_number != 0)
{
int opnum;
@@ -1775,6 +1682,11 @@ check_format_info_main (status, res, info, format_chars, format_length,
}
if (info->first_arg_num != 0)
{
+ if (params == 0)
+ {
+ status_warning (status, "too few arguments for format");
+ return;
+ }
cur_param = TREE_VALUE (params);
if (has_operand_number <= 0)
{
@@ -2258,7 +2170,6 @@ check_format_types (status, types)
tree cur_type;
tree orig_cur_type;
tree wanted_type;
- tree promoted_type;
int arg_num;
int i;
int char_type_flag;
@@ -2277,11 +2188,7 @@ check_format_types (status, types)
abort ();
if (types->pointer_count == 0)
- {
- promoted_type = simple_type_promotes_to (wanted_type);
- if (promoted_type != NULL_TREE)
- wanted_type = promoted_type;
- }
+ wanted_type = (*lang_hooks.types.type_promotes_to) (wanted_type);
STRIP_NOPS (cur_param);
@@ -2386,8 +2293,8 @@ check_format_types (status, types)
&& TREE_CODE (cur_type) == INTEGER_TYPE
&& (! pedantic || i == 0 || (i == 1 && char_type_flag))
&& (TREE_UNSIGNED (wanted_type)
- ? wanted_type == unsigned_type (cur_type)
- : wanted_type == signed_type (cur_type)))
+ ? wanted_type == c_common_unsigned_type (cur_type)
+ : wanted_type == c_common_signed_type (cur_type)))
continue;
/* Likewise, "signed char", "unsigned char" and "char" are
equivalent but the above test won't consider them equivalent. */
diff --git a/contrib/gcc/c-lang.c b/contrib/gcc/c-lang.c
index 2b7d473..8614e25 100644
--- a/contrib/gcc/c-lang.c
+++ b/contrib/gcc/c-lang.c
@@ -24,10 +24,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "system.h"
#include "tree.h"
#include "c-tree.h"
+#include "c-common.h"
+#include "ggc.h"
#include "langhooks.h"
#include "langhooks-def.h"
-static const char *c_init PARAMS ((const char *));
static void c_init_options PARAMS ((void));
/* ### When changing hooks, consider if ObjC needs changing too!! ### */
@@ -35,25 +36,51 @@ static void c_init_options PARAMS ((void));
#undef LANG_HOOKS_NAME
#define LANG_HOOKS_NAME "GNU C"
#undef LANG_HOOKS_INIT
-#define LANG_HOOKS_INIT c_init
+#define LANG_HOOKS_INIT c_objc_common_init
#undef LANG_HOOKS_FINISH
#define LANG_HOOKS_FINISH c_common_finish
#undef LANG_HOOKS_INIT_OPTIONS
#define LANG_HOOKS_INIT_OPTIONS c_init_options
#undef LANG_HOOKS_DECODE_OPTION
-#define LANG_HOOKS_DECODE_OPTION c_decode_option
+#define LANG_HOOKS_DECODE_OPTION c_common_decode_option
#undef LANG_HOOKS_POST_OPTIONS
#define LANG_HOOKS_POST_OPTIONS c_common_post_options
#undef LANG_HOOKS_GET_ALIAS_SET
#define LANG_HOOKS_GET_ALIAS_SET c_common_get_alias_set
#undef LANG_HOOKS_SAFE_FROM_P
#define LANG_HOOKS_SAFE_FROM_P c_safe_from_p
+#undef LANG_HOOKS_EXPAND_EXPR
+#define LANG_HOOKS_EXPAND_EXPR c_expand_expr
+#undef LANG_HOOKS_MARK_ADDRESSABLE
+#define LANG_HOOKS_MARK_ADDRESSABLE c_mark_addressable
+#undef LANG_HOOKS_PARSE_FILE
+#define LANG_HOOKS_PARSE_FILE c_common_parse_file
+#undef LANG_HOOKS_TRUTHVALUE_CONVERSION
+#define LANG_HOOKS_TRUTHVALUE_CONVERSION c_common_truthvalue_conversion
+#undef LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES
+#define LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES c_insert_default_attributes
+#undef LANG_HOOKS_FINISH_INCOMPLETE_DECL
+#define LANG_HOOKS_FINISH_INCOMPLETE_DECL c_finish_incomplete_decl
+#undef LANG_HOOKS_UNSAFE_FOR_REEVAL
+#define LANG_HOOKS_UNSAFE_FOR_REEVAL c_common_unsafe_for_reeval
#undef LANG_HOOKS_STATICP
#define LANG_HOOKS_STATICP c_staticp
+#undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL
+#define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL c_warn_unused_global_decl
#undef LANG_HOOKS_PRINT_IDENTIFIER
#define LANG_HOOKS_PRINT_IDENTIFIER c_print_identifier
-#undef LANG_HOOKS_SET_YYDEBUG
-#define LANG_HOOKS_SET_YYDEBUG c_set_yydebug
+#undef LANG_HOOKS_FUNCTION_ENTER_NESTED
+#define LANG_HOOKS_FUNCTION_ENTER_NESTED c_push_function_context
+#undef LANG_HOOKS_FUNCTION_LEAVE_NESTED
+#define LANG_HOOKS_FUNCTION_LEAVE_NESTED c_pop_function_context
+#undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL
+#define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL c_dup_lang_specific_decl
+
+/* Attribute hooks. */
+#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
+#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
+#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table
#undef LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN
#define LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN \
@@ -67,25 +94,70 @@ static void c_init_options PARAMS ((void));
#undef LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING
#define LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
c_convert_parm_for_inlining
+#undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
+#define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN c_dump_tree
+
+#undef LANG_HOOKS_TYPE_FOR_MODE
+#define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode
+#undef LANG_HOOKS_TYPE_FOR_SIZE
+#define LANG_HOOKS_TYPE_FOR_SIZE c_common_type_for_size
+#undef LANG_HOOKS_SIGNED_TYPE
+#define LANG_HOOKS_SIGNED_TYPE c_common_signed_type
+#undef LANG_HOOKS_UNSIGNED_TYPE
+#define LANG_HOOKS_UNSIGNED_TYPE c_common_unsigned_type
+#undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
+#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE c_common_signed_or_unsigned_type
+#undef LANG_HOOKS_INCOMPLETE_TYPE_ERROR
+#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR c_incomplete_type_error
+#undef LANG_HOOKS_TYPE_PROMOTES_TO
+#define LANG_HOOKS_TYPE_PROMOTES_TO c_type_promotes_to
/* ### When changing hooks, consider if ObjC needs changing too!! ### */
/* Each front end provides its own. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+/* Tree code classes. */
+
+#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
+
+const char tree_code_type[] = {
+#include "tree.def"
+ 'x',
+#include "c-common.def"
+};
+#undef DEFTREECODE
+
+/* Table indexed by tree code giving number of expression
+ operands beyond the fixed part of the node structure.
+ Not used for types or decls. */
+
+#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
+
+const unsigned char tree_code_length[] = {
+#include "tree.def"
+ 0,
+#include "c-common.def"
+};
+#undef DEFTREECODE
+
+/* Names of tree components.
+ Used for printing out the tree and error messages. */
+#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
+
+const char *const tree_code_name[] = {
+#include "tree.def"
+ "@@dummy",
+#include "c-common.def"
+};
+#undef DEFTREECODE
+
static void
c_init_options ()
{
c_common_init_options (clk_c);
}
-static const char *
-c_init (filename)
- const char *filename;
-{
- return c_objc_common_init (filename);
-}
-
/* Used by c-lex.c, but only for objc. */
tree
@@ -102,14 +174,21 @@ is_class_name (arg)
return 0;
}
+tree
+objc_is_id (arg)
+ tree arg ATTRIBUTE_UNUSED;
+{
+ return 0;
+}
+
void
-maybe_objc_check_decl (decl)
+objc_check_decl (decl)
tree decl ATTRIBUTE_UNUSED;
{
}
int
-maybe_objc_comptypes (lhs, rhs, reflexive)
+objc_comptypes (lhs, rhs, reflexive)
tree lhs ATTRIBUTE_UNUSED;
tree rhs ATTRIBUTE_UNUSED;
int reflexive ATTRIBUTE_UNUSED;
@@ -118,13 +197,7 @@ maybe_objc_comptypes (lhs, rhs, reflexive)
}
tree
-maybe_building_objc_message_expr ()
-{
- return 0;
-}
-
-int
-recognize_objc_keyword ()
+objc_message_selector ()
{
return 0;
}
@@ -143,3 +216,5 @@ finish_file ()
{
c_objc_common_finish_file ();
}
+
+#include "gtype-c.h"
diff --git a/contrib/gcc/c-lex.c b/contrib/gcc/c-lex.c
index 48b087e..a60fbb0 100644
--- a/contrib/gcc/c-lex.c
+++ b/contrib/gcc/c-lex.c
@@ -1,6 +1,6 @@
-/* Lexical analyzer for C and Objective C.
+/* Mainly the interface between cpplib and the C front ends.
Copyright (C) 1987, 1988, 1989, 1992, 1994, 1995, 1996, 1997
- 1998, 1999, 2000 Free Software Foundation, Inc.
+ 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -22,13 +22,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
+#include "real.h"
#include "rtl.h"
#include "tree.h"
#include "expr.h"
#include "input.h"
#include "output.h"
-#include "c-lex.h"
#include "c-tree.h"
+#include "c-common.h"
#include "flags.h"
#include "timevar.h"
#include "cpplib.h"
@@ -39,20 +40,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "splay-tree.h"
#include "debug.h"
-/* MULTIBYTE_CHARS support only works for native compilers.
- ??? Ideally what we want is to model widechar support after
- the current floating point support. */
-#ifdef CROSS_COMPILE
-#undef MULTIBYTE_CHARS
-#endif
-
#ifdef MULTIBYTE_CHARS
#include "mbchar.h"
#include <locale.h>
#endif /* MULTIBYTE_CHARS */
-#ifndef GET_ENVIRONMENT
-#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ((ENV_VALUE) = getenv (ENV_NAME))
-#endif
/* The current line map. */
static const struct line_map *map;
@@ -64,9 +55,6 @@ static unsigned int src_lineno;
static int header_time, body_time;
static splay_tree file_info_tree;
-/* Cause the `yydebug' variable to be defined. */
-#define YYDEBUG 1
-
/* File used for outputting assembler code. */
extern FILE *asm_out_file;
@@ -76,15 +64,18 @@ extern FILE *asm_out_file;
/* Number of bytes in a wide character. */
#define WCHAR_BYTES (WCHAR_TYPE_SIZE / BITS_PER_UNIT)
-int indent_level; /* Number of { minus number of }. */
int pending_lang_change; /* If we need to switch languages - C++ only */
int c_header_level; /* depth in C headers - C++ only */
/* Nonzero tells yylex to ignore \ in string constants. */
static int ignore_escape_flag;
-static void parse_float PARAMS ((PTR));
-static tree lex_number PARAMS ((const char *, unsigned int));
+static tree interpret_integer PARAMS ((const cpp_token *, unsigned int));
+static tree interpret_float PARAMS ((const cpp_token *, unsigned int));
+static enum integer_type_kind
+ narrowest_unsigned_type PARAMS ((tree, unsigned int));
+static enum integer_type_kind
+ narrowest_signed_type PARAMS ((tree, unsigned int));
static tree lex_string PARAMS ((const unsigned char *, unsigned int,
int));
static tree lex_charconst PARAMS ((const cpp_token *));
@@ -144,9 +135,6 @@ init_c_lex (filename)
/* Start it at 0. */
lineno = 0;
- if (filename == NULL || !strcmp (filename, "-"))
- filename = "";
-
return cpp_read_main_file (parse_in, filename, ident_hash);
}
@@ -155,13 +143,21 @@ init_c_lex (filename)
Also, make sure the start_source_file debug hook gets called for
the primary source file. */
-int
-yyparse()
+void
+c_common_parse_file (set_yydebug)
+ int set_yydebug ATTRIBUTE_UNUSED;
{
+#if YYDEBUG != 0
+ yydebug = set_yydebug;
+#else
+ warning ("YYDEBUG not defined");
+#endif
+
(*debug_hooks->start_source_file) (lineno, input_filename);
cpp_finish_options (parse_in);
- return yyparse_1();
+ yyparse ();
+ free_parser_stacks ();
}
struct c_fileinfo *
@@ -227,9 +223,6 @@ dump_time_statistics ()
splay_tree_foreach (file_info_tree, dump_one_header, 0);
}
-/* Not yet handled: #pragma, #define, #undef.
- No need to deal with linemarkers under normal conditions. */
-
static void
cb_ident (pfile, line, str)
cpp_reader *pfile ATTRIBUTE_UNUSED;
@@ -276,7 +269,6 @@ cb_file_change (pfile, new_map)
lineno = included_at;
push_srcloc (new_map->to_file, 1);
- input_file_stack->indent_level = indent_level;
(*debug_hooks->start_source_file) (included_at, new_map->to_file);
#ifndef NO_IMPLICIT_EXTERN_C
if (c_header_level)
@@ -299,16 +291,6 @@ cb_file_change (pfile, new_map)
--pending_lang_change;
}
#endif
-#if 0
- if (indent_level != input_file_stack->indent_level)
- {
- warning_with_file_and_line
- (input_filename, lineno,
- "this file contains more '%c's than '%c's",
- indent_level > input_file_stack->indent_level ? '{' : '}',
- indent_level > input_file_stack->indent_level ? '}' : '{');
- }
-#endif
pop_srcloc ();
(*debug_hooks->end_source_file) (to_line);
@@ -682,88 +664,7 @@ utf8_extend_token (c)
while (shift);
}
#endif
-
-#if 0
-struct try_type
-{
- tree *const node_var;
- const char unsigned_flag;
- const char long_flag;
- const char long_long_flag;
-};
-
-struct try_type type_sequence[] =
-{
- { &integer_type_node, 0, 0, 0},
- { &unsigned_type_node, 1, 0, 0},
- { &long_integer_type_node, 0, 1, 0},
- { &long_unsigned_type_node, 1, 1, 0},
- { &long_long_integer_type_node, 0, 1, 1},
- { &long_long_unsigned_type_node, 1, 1, 1}
-};
-#endif /* 0 */
-struct pf_args
-{
- /* Input */
- const char *str;
- int fflag;
- int lflag;
- int base;
- /* Output */
- int conversion_errno;
- REAL_VALUE_TYPE value;
- tree type;
-};
-
-static void
-parse_float (data)
- PTR data;
-{
- struct pf_args * args = (struct pf_args *) data;
- const char *typename;
-
- args->conversion_errno = 0;
- args->type = double_type_node;
- typename = "double";
-
- /* The second argument, machine_mode, of REAL_VALUE_ATOF
- tells the desired precision of the binary result
- of decimal-to-binary conversion. */
-
- if (args->fflag)
- {
- if (args->lflag)
- error ("both 'f' and 'l' suffixes on floating constant");
-
- args->type = float_type_node;
- typename = "float";
- }
- else if (args->lflag)
- {
- args->type = long_double_type_node;
- typename = "long double";
- }
- else if (flag_single_precision_constant)
- {
- args->type = float_type_node;
- typename = "float";
- }
-
- errno = 0;
- if (args->base == 16)
- args->value = REAL_VALUE_HTOF (args->str, TYPE_MODE (args->type));
- else
- args->value = REAL_VALUE_ATOF (args->str, TYPE_MODE (args->type));
-
- args->conversion_errno = errno;
- /* A diagnostic is required here by some ISO C testsuites.
- This is not pedwarn, because some people don't want
- an error for this. */
- if (REAL_VALUE_ISINF (args->value) && pedantic)
- warning ("floating point number exceeds range of '%s'", typename);
-}
-
int
c_lex (value)
tree *value;
@@ -785,9 +686,6 @@ c_lex (value)
*value = NULL_TREE;
switch (tok->type)
{
- case CPP_OPEN_BRACE: indent_level++; break;
- case CPP_CLOSE_BRACE: indent_level--; break;
-
/* Issue this error here, where we can get at tok->val.c. */
case CPP_OTHER:
if (ISGRAPH (tok->val.c))
@@ -801,7 +699,28 @@ c_lex (value)
break;
case CPP_NUMBER:
- *value = lex_number ((const char *)tok->val.str.text, tok->val.str.len);
+ {
+ unsigned int flags = cpp_classify_number (parse_in, tok);
+
+ switch (flags & CPP_N_CATEGORY)
+ {
+ case CPP_N_INVALID:
+ /* cpplib has issued an error. */
+ *value = error_mark_node;
+ break;
+
+ case CPP_N_INTEGER:
+ *value = interpret_integer (tok, flags);
+ break;
+
+ case CPP_N_FLOATING:
+ *value = interpret_float (tok, flags);
+ break;
+
+ default:
+ abort ();
+ }
+ }
break;
case CPP_CHAR:
@@ -827,476 +746,203 @@ c_lex (value)
return tok->type;
}
-#define ERROR(msgid) do { error(msgid); goto syntax_error; } while(0)
-
-static tree
-lex_number (str, len)
- const char *str;
- unsigned int len;
+/* Returns the narrowest C-visible unsigned type, starting with the
+ minimum specified by FLAGS, that can fit VALUE, or itk_none if
+ there isn't one. */
+static enum integer_type_kind
+narrowest_unsigned_type (value, flags)
+ tree value;
+ unsigned int flags;
{
- int base = 10;
- int count = 0;
- int largest_digit = 0;
- int numdigits = 0;
- int overflow = 0;
- int c;
- tree value;
- const char *p;
- enum anon1 { NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON } floatflag = NOT_FLOAT;
-
- /* We actually store only HOST_BITS_PER_CHAR bits in each part.
- The code below which fills the parts array assumes that a host
- int is at least twice as wide as a host char, and that
- HOST_BITS_PER_WIDE_INT is an even multiple of HOST_BITS_PER_CHAR.
- Two HOST_WIDE_INTs is the largest int literal we can store.
- In order to detect overflow below, the number of parts (TOTAL_PARTS)
- must be exactly the number of parts needed to hold the bits
- of two HOST_WIDE_INTs. */
-#define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2)
- unsigned int parts[TOTAL_PARTS];
-
- /* Optimize for most frequent case. */
- if (len == 1)
- {
- if (*str == '0')
- return integer_zero_node;
- else if (*str == '1')
- return integer_one_node;
- else
- return build_int_2 (*str - '0', 0);
- }
+ enum integer_type_kind itk;
- for (count = 0; count < TOTAL_PARTS; count++)
- parts[count] = 0;
-
- /* len is known to be >1 at this point. */
- p = str;
-
- if (len > 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
- {
- base = 16;
- p = str + 2;
- }
- /* The ISDIGIT check is so we are not confused by a suffix on 0. */
- else if (str[0] == '0' && ISDIGIT (str[1]))
- {
- base = 8;
- p = str + 1;
- }
-
- do
- {
- c = *p++;
-
- if (c == '.')
- {
- if (floatflag == AFTER_POINT)
- ERROR ("too many decimal points in floating constant");
- else if (floatflag == AFTER_EXPON)
- ERROR ("decimal point in exponent - impossible!");
- else
- floatflag = AFTER_POINT;
-
- if (base == 8)
- base = 10;
- }
- else if (c == '_')
- /* Possible future extension: silently ignore _ in numbers,
- permitting cosmetic grouping - e.g. 0x8000_0000 == 0x80000000
- but somewhat easier to read. Ada has this? */
- ERROR ("underscore in number");
- else
- {
- int n;
- /* It is not a decimal point.
- It should be a digit (perhaps a hex digit). */
-
- if (ISDIGIT (c)
- || (base == 16 && ISXDIGIT (c)))
- {
- n = hex_value (c);
- }
- else if (base <= 10 && (c == 'e' || c == 'E'))
- {
- base = 10;
- floatflag = AFTER_EXPON;
- break;
- }
- else if (base == 16 && (c == 'p' || c == 'P'))
- {
- floatflag = AFTER_EXPON;
- break; /* start of exponent */
- }
- else
- {
- p--;
- break; /* start of suffix */
- }
-
- if (n >= largest_digit)
- largest_digit = n;
- numdigits++;
-
- for (count = 0; count < TOTAL_PARTS; count++)
- {
- parts[count] *= base;
- if (count)
- {
- parts[count]
- += (parts[count-1] >> HOST_BITS_PER_CHAR);
- parts[count-1]
- &= (1 << HOST_BITS_PER_CHAR) - 1;
- }
- else
- parts[0] += n;
- }
-
- /* If the highest-order part overflows (gets larger than
- a host char will hold) then the whole number has
- overflowed. Record this and truncate the highest-order
- part. */
- if (parts[TOTAL_PARTS - 1] >> HOST_BITS_PER_CHAR)
- {
- overflow = 1;
- parts[TOTAL_PARTS - 1] &= (1 << HOST_BITS_PER_CHAR) - 1;
- }
- }
- }
- while (p < str + len);
-
- /* This can happen on input like `int i = 0x;' */
- if (numdigits == 0)
- ERROR ("numeric constant with no digits");
-
- if (largest_digit >= base)
- ERROR ("numeric constant contains digits beyond the radix");
-
- if (floatflag != NOT_FLOAT)
- {
- tree type;
- int imag, fflag, lflag, conversion_errno;
- REAL_VALUE_TYPE real;
- struct pf_args args;
- char *copy;
-
- if (base == 16 && pedantic && !flag_isoc99)
- pedwarn ("floating constant may not be in radix 16");
-
- if (base == 16 && floatflag != AFTER_EXPON)
- ERROR ("hexadecimal floating constant has no exponent");
-
- /* Read explicit exponent if any, and put it in tokenbuf. */
- if ((base == 10 && ((c == 'e') || (c == 'E')))
- || (base == 16 && (c == 'p' || c == 'P')))
- {
- if (p < str + len)
- c = *p++;
- if (p < str + len && (c == '+' || c == '-'))
- c = *p++;
- /* Exponent is decimal, even if string is a hex float. */
- if (! ISDIGIT (c))
- ERROR ("floating constant exponent has no digits");
- while (p < str + len && ISDIGIT (c))
- c = *p++;
- if (! ISDIGIT (c))
- p--;
- }
+ if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+ itk = itk_unsigned_int;
+ else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+ itk = itk_unsigned_long;
+ else
+ itk = itk_unsigned_long_long;
- /* Copy the float constant now; we don't want any suffixes in the
- string passed to parse_float. */
- copy = alloca (p - str + 1);
- memcpy (copy, str, p - str);
- copy[p - str] = '\0';
+ /* int_fits_type_p must think the type of its first argument is
+ wider than its second argument, or it won't do the proper check. */
+ TREE_TYPE (value) = widest_unsigned_literal_type_node;
- /* Now parse suffixes. */
- fflag = lflag = imag = 0;
- while (p < str + len)
- switch (*p++)
- {
- case 'f': case 'F':
- if (fflag)
- ERROR ("more than one 'f' suffix on floating constant");
- else if (warn_traditional && !in_system_header
- && ! cpp_sys_macro_p (parse_in))
- warning ("traditional C rejects the 'f' suffix");
-
- fflag = 1;
- break;
+ for (; itk < itk_none; itk += 2 /* skip unsigned types */)
+ if (int_fits_type_p (value, integer_types[itk]))
+ return itk;
- case 'l': case 'L':
- if (lflag)
- ERROR ("more than one 'l' suffix on floating constant");
- else if (warn_traditional && !in_system_header
- && ! cpp_sys_macro_p (parse_in))
- warning ("traditional C rejects the 'l' suffix");
+ return itk_none;
+}
- lflag = 1;
- break;
+/* Ditto, but narrowest signed type. */
+static enum integer_type_kind
+narrowest_signed_type (value, flags)
+ tree value;
+ unsigned int flags;
+{
+ enum integer_type_kind itk;
- case 'i': case 'I':
- case 'j': case 'J':
- if (imag)
- ERROR ("more than one 'i' or 'j' suffix on floating constant");
- else if (pedantic)
- pedwarn ("ISO C forbids imaginary numeric constants");
- imag = 1;
- break;
+ if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+ itk = itk_int;
+ else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+ itk = itk_long;
+ else
+ itk = itk_long_long;
- default:
- ERROR ("invalid suffix on floating constant");
- }
+ /* int_fits_type_p must think the type of its first argument is
+ wider than its second argument, or it won't do the proper check. */
+ TREE_TYPE (value) = widest_unsigned_literal_type_node;
- /* Setup input for parse_float() */
- args.str = copy;
- args.fflag = fflag;
- args.lflag = lflag;
- args.base = base;
+ for (; itk < itk_none; itk += 2 /* skip signed types */)
+ if (int_fits_type_p (value, integer_types[itk]))
+ return itk;
- /* Convert string to a double, checking for overflow. */
- if (do_float_handler (parse_float, (PTR) &args))
- {
- /* Receive output from parse_float() */
- real = args.value;
- }
- else
- /* We got an exception from parse_float() */
- ERROR ("floating constant out of range");
-
- /* Receive output from parse_float() */
- conversion_errno = args.conversion_errno;
- type = args.type;
-
-#ifdef ERANGE
- /* ERANGE is also reported for underflow,
- so test the value to distinguish overflow from that. */
- if (conversion_errno == ERANGE && !flag_traditional && pedantic
- && (REAL_VALUES_LESS (dconst1, real)
- || REAL_VALUES_LESS (real, dconstm1)))
- warning ("floating point number exceeds range of 'double'");
-#endif
+ return itk_none;
+}
- /* Create a node with determined type and value. */
- if (imag)
- value = build_complex (NULL_TREE, convert (type, integer_zero_node),
- build_real (type, real));
- else
- value = build_real (type, real);
- }
+/* Interpret TOKEN, an integer with FLAGS as classified by cpplib. */
+static tree
+interpret_integer (token, flags)
+ const cpp_token *token;
+ unsigned int flags;
+{
+ tree value, type;
+ enum integer_type_kind itk;
+ cpp_num integer;
+ cpp_options *options = cpp_get_options (parse_in);
+
+ integer = cpp_interpret_integer (parse_in, token, flags);
+ integer = cpp_num_sign_extend (integer, options->precision);
+ value = build_int_2_wide (integer.low, integer.high);
+
+ /* The type of a constant with a U suffix is straightforward. */
+ if (flags & CPP_N_UNSIGNED)
+ itk = narrowest_unsigned_type (value, flags);
else
{
- tree trad_type, ansi_type, type;
- HOST_WIDE_INT high, low;
- int spec_unsigned = 0;
- int spec_long = 0;
- int spec_long_long = 0;
- int spec_imag = 0;
- int suffix_lu = 0;
- int warn = 0, i;
-
- trad_type = ansi_type = type = NULL_TREE;
- while (p < str + len)
+ /* The type of a potentially-signed integer constant varies
+ depending on the base it's in, the standard in use, and the
+ length suffixes. */
+ enum integer_type_kind itk_u = narrowest_unsigned_type (value, flags);
+ enum integer_type_kind itk_s = narrowest_signed_type (value, flags);
+
+ /* In both C89 and C99, octal and hex constants may be signed or
+ unsigned, whichever fits tighter. We do not warn about this
+ choice differing from the traditional choice, as the constant
+ is probably a bit pattern and either way will work. */
+ if ((flags & CPP_N_RADIX) != CPP_N_DECIMAL)
+ itk = MIN (itk_u, itk_s);
+ else
{
- c = *p++;
- switch (c)
+ /* In C99, decimal constants are always signed.
+ In C89, decimal constants that don't fit in long have
+ undefined behavior; we try to make them unsigned long.
+ In GCC's extended C89, that last is true of decimal
+ constants that don't fit in long long, too. */
+
+ itk = itk_s;
+ if (itk_s > itk_u && itk_s > itk_long)
{
- case 'u': case 'U':
- if (spec_unsigned)
- error ("two 'u' suffixes on integer constant");
- else if (warn_traditional && !in_system_header
- && ! cpp_sys_macro_p (parse_in))
- warning ("traditional C rejects the 'u' suffix");
-
- spec_unsigned = 1;
- if (spec_long)
- suffix_lu = 1;
- break;
-
- case 'l': case 'L':
- if (spec_long)
+ if (!flag_isoc99)
{
- if (spec_long_long)
- error ("three 'l' suffixes on integer constant");
- else if (suffix_lu)
- error ("'lul' is not a valid integer suffix");
- else if (c != spec_long)
- error ("'Ll' and 'lL' are not valid integer suffixes");
- else if (pedantic && ! flag_isoc99
- && ! in_system_header && warn_long_long)
- pedwarn ("ISO C89 forbids long long integer constants");
- spec_long_long = 1;
+ if (itk_u < itk_unsigned_long)
+ itk_u = itk_unsigned_long;
+ itk = itk_u;
+ warning ("this decimal constant is unsigned only in ISO C90");
}
- spec_long = c;
- break;
-
- case 'i': case 'I': case 'j': case 'J':
- if (spec_imag)
- error ("more than one 'i' or 'j' suffix on integer constant");
- else if (pedantic)
- pedwarn ("ISO C forbids imaginary numeric constants");
- spec_imag = 1;
- break;
-
- default:
- ERROR ("invalid suffix on integer constant");
+ else if (warn_traditional)
+ warning ("this decimal constant would be unsigned in ISO C90");
}
}
+ }
- /* If the literal overflowed, pedwarn about it now. */
- if (overflow)
- {
- warn = 1;
- pedwarn ("integer constant is too large for this configuration of the compiler - truncated to %d bits", HOST_BITS_PER_WIDE_INT * 2);
- }
-
- /* This is simplified by the fact that our constant
- is always positive. */
-
- high = low = 0;
-
- for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++)
- {
- high |= ((HOST_WIDE_INT) parts[i + (HOST_BITS_PER_WIDE_INT
- / HOST_BITS_PER_CHAR)]
- << (i * HOST_BITS_PER_CHAR));
- low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR);
- }
-
- value = build_int_2 (low, high);
- TREE_TYPE (value) = long_long_unsigned_type_node;
-
- /* If warn_traditional, calculate both the ISO type and the
- traditional type, then see if they disagree.
- Otherwise, calculate only the type for the dialect in use. */
- if (warn_traditional || flag_traditional)
- {
- /* Calculate the traditional type. */
- /* Traditionally, any constant is signed; but if unsigned is
- specified explicitly, obey that. Use the smallest size
- with the right number of bits, except for one special
- case with decimal constants. */
- if (! spec_long && base != 10
- && int_fits_type_p (value, unsigned_type_node))
- trad_type = spec_unsigned ? unsigned_type_node : integer_type_node;
- /* A decimal constant must be long if it does not fit in
- type int. I think this is independent of whether the
- constant is signed. */
- else if (! spec_long && base == 10
- && int_fits_type_p (value, integer_type_node))
- trad_type = spec_unsigned ? unsigned_type_node : integer_type_node;
- else if (! spec_long_long)
- trad_type = (spec_unsigned
- ? long_unsigned_type_node
- : long_integer_type_node);
- else if (int_fits_type_p (value,
- spec_unsigned
- ? long_long_unsigned_type_node
- : long_long_integer_type_node))
- trad_type = (spec_unsigned
- ? long_long_unsigned_type_node
- : long_long_integer_type_node);
- else
- trad_type = (spec_unsigned
- ? widest_unsigned_literal_type_node
- : widest_integer_literal_type_node);
- }
- if (warn_traditional || ! flag_traditional)
- {
- /* Calculate the ISO type. */
- if (! spec_long && ! spec_unsigned
- && int_fits_type_p (value, integer_type_node))
- ansi_type = integer_type_node;
- else if (! spec_long && (base != 10 || spec_unsigned)
- && int_fits_type_p (value, unsigned_type_node))
- ansi_type = unsigned_type_node;
- else if (! spec_unsigned && !spec_long_long
- && int_fits_type_p (value, long_integer_type_node))
- ansi_type = long_integer_type_node;
- else if (! spec_long_long
- && int_fits_type_p (value, long_unsigned_type_node))
- ansi_type = long_unsigned_type_node;
- else if (! spec_unsigned
- && int_fits_type_p (value, long_long_integer_type_node))
- ansi_type = long_long_integer_type_node;
- else if (int_fits_type_p (value, long_long_unsigned_type_node))
- ansi_type = long_long_unsigned_type_node;
- else if (! spec_unsigned
- && int_fits_type_p (value, widest_integer_literal_type_node))
- ansi_type = widest_integer_literal_type_node;
- else
- ansi_type = widest_unsigned_literal_type_node;
- }
-
- type = flag_traditional ? trad_type : ansi_type;
+ if (itk == itk_none)
+ /* cpplib has already issued a warning for overflow. */
+ type = ((flags & CPP_N_UNSIGNED)
+ ? widest_unsigned_literal_type_node
+ : widest_integer_literal_type_node);
+ else
+ type = integer_types[itk];
- /* We assume that constants specified in a non-decimal
- base are bit patterns, and that the programmer really
- meant what they wrote. */
- if (warn_traditional && !in_system_header
- && base == 10 && trad_type != ansi_type)
- {
- if (TYPE_PRECISION (trad_type) != TYPE_PRECISION (ansi_type))
- warning ("width of integer constant changes with -traditional");
- else if (TREE_UNSIGNED (trad_type) != TREE_UNSIGNED (ansi_type))
- warning ("integer constant is unsigned in ISO C, signed with -traditional");
- else
- warning ("width of integer constant may change on other systems with -traditional");
- }
+ if (itk > itk_unsigned_long
+ && (flags & CPP_N_WIDTH) != CPP_N_LARGE
+ && ! in_system_header && ! flag_isoc99)
+ pedwarn ("integer constant is too large for \"%s\" type",
+ (flags & CPP_N_UNSIGNED) ? "unsigned long" : "long");
- if (pedantic && !flag_traditional && (flag_isoc99 || !spec_long_long)
- && !warn
- && ((flag_isoc99
- ? TYPE_PRECISION (long_long_integer_type_node)
- : TYPE_PRECISION (long_integer_type_node)) < TYPE_PRECISION (type)))
- {
- warn = 1;
- pedwarn ("integer constant larger than the maximum value of %s",
- (flag_isoc99
- ? (TREE_UNSIGNED (type)
- ? _("an unsigned long long int")
- : _("a long long int"))
- : _("an unsigned long int")));
- }
+ TREE_TYPE (value) = type;
- if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
- warning ("decimal constant is so large that it is unsigned");
+ /* Convert imaginary to a complex type. */
+ if (flags & CPP_N_IMAGINARY)
+ value = build_complex (NULL_TREE, convert (type, integer_zero_node), value);
- if (spec_imag)
- {
- if (TYPE_PRECISION (type)
- <= TYPE_PRECISION (integer_type_node))
- value = build_complex (NULL_TREE, integer_zero_node,
- convert (integer_type_node, value));
- else
- ERROR ("complex integer constant is too wide for 'complex int'");
- }
- else if (flag_traditional && !int_fits_type_p (value, type))
- /* The traditional constant 0x80000000 is signed
- but doesn't fit in the range of int.
- This will change it to -0x80000000, which does fit. */
- {
- TREE_TYPE (value) = unsigned_type (type);
- value = convert (type, value);
- TREE_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (value) = 0;
- }
- else
- TREE_TYPE (value) = type;
+ return value;
+}
- /* If it's still an integer (not a complex), and it doesn't
- fit in the type we choose for it, then pedwarn. */
+/* Interpret TOKEN, a floating point number with FLAGS as classified
+ by cpplib. */
+static tree
+interpret_float (token, flags)
+ const cpp_token *token;
+ unsigned int flags;
+{
+ tree type;
+ tree value;
+ REAL_VALUE_TYPE real;
+ char *copy;
+ size_t copylen;
+ const char *typename;
- if (! warn
- && TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE
- && ! int_fits_type_p (value, TREE_TYPE (value)))
- pedwarn ("integer constant is larger than the maximum value for its type");
+ /* FIXME: make %T work in error/warning, then we don't need typename. */
+ if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+ {
+ type = long_double_type_node;
+ typename = "long double";
+ }
+ else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL
+ || flag_single_precision_constant)
+ {
+ type = float_type_node;
+ typename = "float";
+ }
+ else
+ {
+ type = double_type_node;
+ typename = "double";
}
- if (p < str + len)
- error ("missing white space after number '%.*s'", (int) (p - str), str);
+ /* Copy the constant to a nul-terminated buffer. If the constant
+ has any suffixes, cut them off; REAL_VALUE_ATOF/ REAL_VALUE_HTOF
+ can't handle them. */
+ copylen = token->val.str.len;
+ if ((flags & CPP_N_WIDTH) != CPP_N_MEDIUM)
+ /* Must be an F or L suffix. */
+ copylen--;
+ if (flags & CPP_N_IMAGINARY)
+ /* I or J suffix. */
+ copylen--;
+
+ copy = alloca (copylen + 1);
+ memcpy (copy, token->val.str.text, copylen);
+ copy[copylen] = '\0';
+
+ real_from_string (&real, copy);
+ real_convert (&real, TYPE_MODE (type), &real);
+
+ /* A diagnostic is required for "soft" overflow by some ISO C
+ testsuites. This is not pedwarn, because some people don't want
+ an error for this.
+ ??? That's a dubious reason... is this a mandatory diagnostic or
+ isn't it? -- zw, 2001-08-21. */
+ if (REAL_VALUE_ISINF (real) && pedantic)
+ warning ("floating constant exceeds range of \"%s\"", typename);
+
+ /* Create a node with determined type and value. */
+ value = build_real (type, real);
+ if (flags & CPP_N_IMAGINARY)
+ value = build_complex (NULL_TREE, convert (type, integer_zero_node), value);
return value;
-
- syntax_error:
- return integer_zero_node;
}
static tree
@@ -1309,9 +955,7 @@ lex_string (str, len, wide)
char *buf = alloca ((len + 1) * (wide ? WCHAR_BYTES : 1));
char *q = buf;
const unsigned char *p = str, *limit = str + len;
- unsigned int c;
- unsigned width = wide ? WCHAR_TYPE_SIZE
- : TYPE_PRECISION (char_type_node);
+ cppchar_t c;
#ifdef MULTIBYTE_CHARS
/* Reset multibyte conversion state. */
@@ -1341,19 +985,10 @@ lex_string (str, len, wide)
#endif
if (c == '\\' && !ignore_escape_flag)
- {
- unsigned int mask;
-
- if (width < HOST_BITS_PER_INT)
- mask = ((unsigned int) 1 << width) - 1;
- else
- mask = ~0;
- c = cpp_parse_escape (parse_in, &p, limit,
- mask, flag_traditional);
- }
+ c = cpp_parse_escape (parse_in, &p, limit, wide);
- /* Add this single character into the buffer either as a wchar_t
- or as a single byte. */
+ /* Add this single character into the buffer either as a wchar_t,
+ a multibyte sequence, or as a single byte. */
if (wide)
{
unsigned charwidth = TYPE_PRECISION (char_type_node);
@@ -1374,6 +1009,16 @@ lex_string (str, len, wide)
}
q += WCHAR_BYTES;
}
+#ifdef MULTIBYTE_CHARS
+ else if (char_len > 1)
+ {
+ /* We're dealing with a multibyte character. */
+ for ( ; char_len >0; --char_len)
+ {
+ *q++ = *(p - char_len);
+ }
+ }
+#endif
else
{
*q++ = c;
@@ -1407,45 +1052,30 @@ static tree
lex_charconst (token)
const cpp_token *token;
{
- HOST_WIDE_INT result;
+ cppchar_t result;
tree type, value;
unsigned int chars_seen;
-
- result = cpp_interpret_charconst (parse_in, token, warn_multichar,
- flag_traditional, &chars_seen);
- if (token->type == CPP_WCHAR)
- {
- value = build_int_2 (result, 0);
- type = wchar_type_node;
- }
- else
- {
- if (result < 0)
- value = build_int_2 (result, -1);
- else
- value = build_int_2 (result, 0);
-
- /* In C, a character constant has type 'int'.
- In C++ 'char', but multi-char charconsts have type 'int'. */
- if (c_language == clk_cplusplus && chars_seen <= 1)
- type = char_type_node;
- else
- type = integer_type_node;
- }
+ int unsignedp;
- /* cpp_interpret_charconst issues a warning if the constant
- overflows, but if the number fits in HOST_WIDE_INT anyway, it
- will return it un-truncated, which may cause problems down the
- line. So set the type to widest_integer_literal_type, call
- convert to truncate it to the proper type, then clear
- TREE_OVERFLOW so we don't get a second warning.
+ result = cpp_interpret_charconst (parse_in, token,
+ &chars_seen, &unsignedp);
- FIXME: cpplib's assessment of overflow may not be accurate on a
- platform where the final type can change at (compiler's) runtime. */
+ /* Cast to cppchar_signed_t to get correct sign-extension of RESULT
+ before possibly widening to HOST_WIDE_INT for build_int_2. */
+ if (unsignedp || (cppchar_signed_t) result >= 0)
+ value = build_int_2 (result, 0);
+ else
+ value = build_int_2 ((cppchar_signed_t) result, -1);
- TREE_TYPE (value) = widest_integer_literal_type_node;
- value = convert (type, value);
- TREE_OVERFLOW (value) = 0;
+ if (token->type == CPP_WCHAR)
+ type = wchar_type_node;
+ /* In C, a character constant has type 'int'.
+ In C++ 'char', but multi-char charconsts have type 'int'. */
+ else if ((c_language == clk_c) || chars_seen > 1)
+ type = integer_type_node;
+ else
+ type = char_type_node;
+ TREE_TYPE (value) = type;
return value;
}
diff --git a/contrib/gcc/c-objc-common.c b/contrib/gcc/c-objc-common.c
index d2bc5c1..9f3847c 100644
--- a/contrib/gcc/c-objc-common.c
+++ b/contrib/gcc/c-objc-common.c
@@ -33,14 +33,16 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tree-inline.h"
#include "varray.h"
#include "ggc.h"
+#include "langhooks.h"
+#include "target.h"
-static int c_tree_printer PARAMS ((output_buffer *));
+static bool c_tree_printer PARAMS ((output_buffer *, text_info *));
static tree inline_forbidden_p PARAMS ((tree *, int *, void *));
static void expand_deferred_fns PARAMS ((void));
static tree start_cdtor PARAMS ((int));
static void finish_cdtor PARAMS ((tree));
-static varray_type deferred_fns;
+static GTY(()) varray_type deferred_fns;
int
c_missing_noreturn_ok_p (decl)
@@ -90,7 +92,7 @@ inline_forbidden_p (nodep, walk_subtrees, fn)
{
/* We cannot inline functions that take a variable number of
arguments. */
- case BUILT_IN_VARARGS_START:
+ case BUILT_IN_VA_START:
case BUILT_IN_STDARG_START:
#if 0
/* Functions that need information about the address of the
@@ -119,7 +121,7 @@ inline_forbidden_p (nodep, walk_subtrees, fn)
/* We will not inline a function which uses computed goto. The
addresses of its local labels, which may be tucked into
global storage, are of course not constant across
- instantiations, which causes unexpected behaviour. */
+ instantiations, which causes unexpected behavior. */
if (TREE_CODE (t) != LABEL_DECL)
return node;
@@ -167,17 +169,11 @@ c_cannot_inline_tree_fn (fnp)
/* Don't auto-inline anything that might not be bound within
this unit of translation. */
- if (!DECL_DECLARED_INLINE_P (fn) && flag_pic && TREE_PUBLIC (fn))
- {
- DECL_UNINLINABLE (fn) = 1;
- return 1;
- }
+ if (!DECL_DECLARED_INLINE_P (fn) && !(*targetm.binds_local_p) (fn))
+ goto cannot_inline;
if (! function_attribute_inlinable_p (fn))
- {
- DECL_UNINLINABLE (fn) = 1;
- return 1;
- }
+ goto cannot_inline;
/* If a function has pending sizes, we must not defer its
compilation, and we can't inline it as a tree. */
@@ -187,10 +183,7 @@ c_cannot_inline_tree_fn (fnp)
put_pending_sizes (t);
if (t)
- {
- DECL_UNINLINABLE (fn) = 1;
- return 1;
- }
+ goto cannot_inline;
}
if (DECL_CONTEXT (fn))
@@ -198,10 +191,7 @@ c_cannot_inline_tree_fn (fnp)
/* If a nested function has pending sizes, we may have already
saved them. */
if (DECL_LANG_SPECIFIC (fn)->pending_sizes)
- {
- DECL_UNINLINABLE (fn) = 1;
- return 1;
- }
+ goto cannot_inline;
}
else
{
@@ -223,13 +213,29 @@ c_cannot_inline_tree_fn (fnp)
return 0;
}
- if (walk_tree (&DECL_SAVED_TREE (fn), inline_forbidden_p, fn, NULL))
- {
- DECL_UNINLINABLE (fn) = 1;
- return 1;
- }
+ if (walk_tree_without_duplicates
+ (&DECL_SAVED_TREE (fn), inline_forbidden_p, fn))
+ goto cannot_inline;
return 0;
+
+ cannot_inline:
+ DECL_UNINLINABLE (fn) = 1;
+ return 1;
+}
+
+/* Called from check_global_declarations. */
+
+bool
+c_warn_unused_global_decl (decl)
+ tree decl;
+{
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
+ return false;
+ if (DECL_IN_SYSTEM_HEADER (decl))
+ return false;
+
+ return true;
}
/* Initialization common to C and Objective-C front ends. */
@@ -240,13 +246,9 @@ c_objc_common_init (filename)
c_init_decl_processing ();
filename = c_common_init (filename);
+ if (filename == NULL)
+ return NULL;
- add_c_tree_codes ();
-
- save_lang_status = &push_c_function_context;
- restore_lang_status = &pop_c_function_context;
- mark_lang_status = &mark_c_function_context;
- lang_expand_expr = c_expand_expr;
lang_expand_decl_stmt = c_expand_decl_stmt;
/* These were not defined in the Objective-C front end, but I'm
@@ -266,7 +268,6 @@ c_objc_common_init (filename)
}
VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
- ggc_add_tree_varray_root (&deferred_fns, 1);
return filename;
}
@@ -304,7 +305,7 @@ expand_deferred_fns ()
}
}
- VARRAY_FREE (deferred_fns);
+ deferred_fns = 0;
}
static tree
@@ -403,26 +404,29 @@ c_objc_common_finish_file ()
by the C++ front-end.
Please notice when called, the `%' part was already skipped by the
diagnostic machinery. */
-static int
-c_tree_printer (buffer)
+static bool
+c_tree_printer (buffer, text)
output_buffer *buffer;
+ text_info *text;
{
- tree t = va_arg (output_buffer_format_args (buffer), tree);
+ tree t = va_arg (*text->args_ptr, tree);
- switch (*output_buffer_text_cursor (buffer))
+ switch (*text->format_spec)
{
case 'D':
case 'F':
case 'T':
{
const char *n = DECL_NAME (t)
- ? (*decl_printable_name) (t, 2)
+ ? (*lang_hooks.decl_printable_name) (t, 2)
: "({anonymous})";
output_add_string (buffer, n);
}
- return 1;
+ return true;
default:
- return 0;
+ return false;
}
}
+
+#include "gt-c-objc-common.h"
diff --git a/contrib/gcc/c-opts.c b/contrib/gcc/c-opts.c
new file mode 100644
index 0000000..77a468a
--- /dev/null
+++ b/contrib/gcc/c-opts.c
@@ -0,0 +1,1799 @@
+/* C/ObjC/C++ command line option handling.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Neil Booth.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "tree.h"
+#include "c-common.h"
+#include "c-pragma.h"
+#include "flags.h"
+#include "toplev.h"
+#include "langhooks.h"
+#include "tree-inline.h"
+#include "diagnostic.h"
+#include "intl.h"
+
+/* CPP's options. */
+static cpp_options *cpp_opts;
+
+/* Input filename. */
+static const char *in_fname;
+
+/* Filename and stream for preprocessed output. */
+static const char *out_fname;
+static FILE *out_stream;
+
+/* Append dependencies to deps_file. */
+static bool deps_append;
+
+/* If dependency switches (-MF etc.) have been given. */
+static bool deps_seen;
+
+/* Dependency output file. */
+static const char *deps_file;
+
+/* Number of deferred options, deferred options array size. */
+static size_t deferred_count, deferred_size;
+
+static void missing_arg PARAMS ((size_t));
+static size_t find_opt PARAMS ((const char *, int));
+static void set_Wimplicit PARAMS ((int));
+static void complain_wrong_lang PARAMS ((size_t, int));
+static void write_langs PARAMS ((char *, int));
+static void print_help PARAMS ((void));
+static void handle_OPT_d PARAMS ((const char *));
+static void set_std_cxx98 PARAMS ((int));
+static void set_std_c89 PARAMS ((int, int));
+static void set_std_c99 PARAMS ((int));
+static void check_deps_environment_vars PARAMS ((void));
+static void preprocess_file PARAMS ((void));
+static void handle_deferred_opts PARAMS ((void));
+static void sanitize_cpp_opts PARAMS ((void));
+
+#ifndef STDC_0_IN_SYSTEM_HEADERS
+#define STDC_0_IN_SYSTEM_HEADERS 0
+#endif
+
+#define CL_C_ONLY (1 << 0) /* Only C. */
+#define CL_OBJC_ONLY (1 << 1) /* Only ObjC. */
+#define CL_CXX_ONLY (1 << 2) /* Only C++. */
+#define CL_OBJCXX_ONLY (1 << 3) /* Only ObjC++. */
+#define CL_JOINED (1 << 4) /* If takes joined argument. */
+#define CL_SEPARATE (1 << 5) /* If takes a separate argument. */
+
+#define CL_ARG (CL_JOINED | CL_SEPARATE)
+#define CL_C (CL_C_ONLY | CL_OBJC_ONLY)
+#define CL_OBJC (CL_OBJC_ONLY | CL_OBJCXX_ONLY)
+#define CL_CXX (CL_CXX_ONLY | CL_OBJCXX_ONLY)
+#define CL_ALL (CL_C | CL_CXX)
+
+/* This is the list of all command line options, with the leading "-"
+ removed. It must be sorted in ASCII collating order. All options
+ beginning with "f" or "W" are implicitly assumed to take a "no-"
+ form; this form should not be listed. The variable "on" is true if
+ the positive form is given, otherwise it is false. If you don't
+ want to allow a "no-" form, your handler should reject "on" being
+ false by returning zero. See, for example, the handling of
+ -ftabstop=.
+
+ If the user gives an option to a front end that doesn't support it,
+ an error is output, mentioning which front ends the option is valid
+ for. If you don't want this, you must accept it for all front
+ ends, and test for the front end in the option handler. See, for
+ example, the handling of -Wno-strict-prototypes for C++.
+
+ If you request an argument with CL_JOINED, CL_SEPARATE or their
+ combination CL_ARG, it is stored in the variable "arg", which is
+ guaranteed to be non-NULL and to not be an empty string. It points
+ to the argument either within the argv[] vector or within one of
+ that vector's strings, and so the text is permanent and copies need
+ not be made. Be sure to add an error message in missing_arg() if
+ the default is not appropriate. */
+
+#define COMMAND_LINE_OPTIONS \
+ OPT("-help", CL_ALL, OPT__help) \
+ OPT("C", CL_ALL, OPT_C) \
+ OPT("CC", CL_ALL, OPT_CC) \
+ OPT("E", CL_ALL, OPT_E) \
+ OPT("H", CL_ALL, OPT_H) \
+ OPT("M", CL_ALL, OPT_M) \
+ OPT("MD", CL_ALL | CL_SEPARATE, OPT_MD) \
+ OPT("MF", CL_ALL | CL_ARG, OPT_MF) \
+ OPT("MG", CL_ALL, OPT_MG) \
+ OPT("MM", CL_ALL, OPT_MM) \
+ OPT("MMD", CL_ALL | CL_SEPARATE, OPT_MMD) \
+ OPT("MP", CL_ALL, OPT_MP) \
+ OPT("MQ", CL_ALL | CL_ARG, OPT_MQ) \
+ OPT("MT", CL_ALL | CL_ARG, OPT_MT) \
+ OPT("P", CL_ALL, OPT_P) \
+ OPT("Wabi", CL_CXX, OPT_Wabi) \
+ OPT("Wall", CL_ALL, OPT_Wall) \
+ OPT("Wbad-function-cast", CL_C, OPT_Wbad_function_cast) \
+ OPT("Wcast-qual", CL_ALL, OPT_Wcast_qual) \
+ OPT("Wchar-subscripts", CL_ALL, OPT_Wchar_subscripts) \
+ OPT("Wcomment", CL_ALL, OPT_Wcomment) \
+ OPT("Wcomments", CL_ALL, OPT_Wcomments) \
+ OPT("Wconversion", CL_ALL, OPT_Wconversion) \
+ OPT("Wctor-dtor-privacy", CL_CXX, OPT_Wctor_dtor_privacy) \
+ OPT("Wdeprecated", CL_CXX, OPT_Wdeprecated) \
+ OPT("Wdiv-by-zero", CL_C, OPT_Wdiv_by_zero) \
+ OPT("Weffc++", CL_CXX, OPT_Weffcxx) \
+ OPT("Wendif-labels", CL_ALL, OPT_Wendif_labels) \
+ OPT("Werror", CL_ALL, OPT_Werror) \
+ OPT("Werror-implicit-function-declaration", \
+ CL_C, OPT_Werror_implicit_function_decl) \
+ OPT("Wfloat-equal", CL_ALL, OPT_Wfloat_equal) \
+ OPT("Wformat", CL_ALL, OPT_Wformat) \
+ OPT("Wformat-extra-args", CL_ALL, OPT_Wformat_extra_args) \
+ OPT("Wformat-nonliteral", CL_ALL, OPT_Wformat_nonliteral) \
+ OPT("Wformat-security", CL_ALL, OPT_Wformat_security) \
+ OPT("Wformat-y2k", CL_ALL, OPT_Wformat_y2k) \
+ OPT("Wformat-zero-length", CL_C, OPT_Wformat_zero_length) \
+ OPT("Wformat=", CL_ALL | CL_JOINED, OPT_Wformat_eq) \
+ OPT("Wimplicit", CL_ALL, OPT_Wimplicit) \
+ OPT("Wimplicit-function-declaration", CL_C, OPT_Wimplicit_function_decl) \
+ OPT("Wimplicit-int", CL_C, OPT_Wimplicit_int) \
+ OPT("Wimport", CL_ALL, OPT_Wimport) \
+ OPT("Wlong-long", CL_ALL, OPT_Wlong_long) \
+ OPT("Wmain", CL_C, OPT_Wmain) \
+ OPT("Wmissing-braces", CL_ALL, OPT_Wmissing_braces) \
+ OPT("Wmissing-declarations", CL_C, OPT_Wmissing_declarations) \
+ OPT("Wmissing-format-attribute",CL_ALL, OPT_Wmissing_format_attribute) \
+ OPT("Wmissing-prototypes", CL_ALL, OPT_Wmissing_prototypes) \
+ OPT("Wmultichar", CL_ALL, OPT_Wmultichar) \
+ OPT("Wnested-externs", CL_C, OPT_Wnested_externs) \
+ OPT("Wnon-template-friend", CL_CXX, OPT_Wnon_template_friend) \
+ OPT("Wnon-virtual-dtor", CL_CXX, OPT_Wnon_virtual_dtor) \
+ OPT("Wnonnull", CL_C, OPT_Wnonnull) \
+ OPT("Wold-style-cast", CL_CXX, OPT_Wold_style_cast) \
+ OPT("Woverloaded-virtual", CL_CXX, OPT_Woverloaded_virtual) \
+ OPT("Wparentheses", CL_ALL, OPT_Wparentheses) \
+ OPT("Wpmf-conversions", CL_CXX, OPT_Wpmf_conversions) \
+ OPT("Wpointer-arith", CL_ALL, OPT_Wpointer_arith) \
+ OPT("Wprotocol", CL_OBJC, OPT_Wprotocol) \
+ OPT("Wredundant-decls", CL_ALL, OPT_Wredundant_decls) \
+ OPT("Wreorder", CL_CXX, OPT_Wreorder) \
+ OPT("Wreturn-type", CL_ALL, OPT_Wreturn_type) \
+ OPT("Wselector", CL_OBJC, OPT_Wselector) \
+ OPT("Wsequence-point", CL_C, OPT_Wsequence_point) \
+ OPT("Wsign-compare", CL_ALL, OPT_Wsign_compare) \
+ OPT("Wsign-promo", CL_CXX, OPT_Wsign_promo) \
+ OPT("Wstrict-prototypes", CL_ALL, OPT_Wstrict_prototypes) \
+ OPT("Wsynth", CL_CXX, OPT_Wsynth) \
+ OPT("Wsystem-headers", CL_ALL, OPT_Wsystem_headers) \
+ OPT("Wtraditional", CL_C, OPT_Wtraditional) \
+ OPT("Wtrigraphs", CL_ALL, OPT_Wtrigraphs) \
+ OPT("Wundeclared-selector", CL_OBJC, OPT_Wundeclared_selector) \
+ OPT("Wundef", CL_ALL, OPT_Wundef) \
+ OPT("Wunknown-pragmas", CL_ALL, OPT_Wunknown_pragmas) \
+ OPT("Wunused-macros", CL_ALL, OPT_Wunused_macros) \
+ OPT("Wwrite-strings", CL_ALL, OPT_Wwrite_strings) \
+ OPT("ansi", CL_ALL, OPT_ansi) \
+ OPT("d", CL_ALL | CL_JOINED, OPT_d) \
+ OPT("fabi-version=", CL_CXX | CL_JOINED, OPT_fabi_version) \
+ OPT("faccess-control", CL_CXX, OPT_faccess_control) \
+ OPT("fall-virtual", CL_CXX, OPT_fall_virtual) \
+ OPT("falt-external-templates",CL_CXX, OPT_falt_external_templates) \
+ OPT("fasm", CL_ALL, OPT_fasm) \
+ OPT("fbuiltin", CL_ALL, OPT_fbuiltin) \
+ OPT("fbuiltin-", CL_ALL | CL_JOINED, OPT_fbuiltin_) \
+ OPT("fcheck-new", CL_CXX, OPT_fcheck_new) \
+ OPT("fcond-mismatch", CL_ALL, OPT_fcond_mismatch) \
+ OPT("fconserve-space", CL_CXX, OPT_fconserve_space) \
+ OPT("fconst-strings", CL_CXX, OPT_fconst_strings) \
+ OPT("fconstant-string-class=", CL_OBJC | CL_JOINED, \
+ OPT_fconstant_string_class) \
+ OPT("fdefault-inline", CL_CXX, OPT_fdefault_inline) \
+ OPT("fdollars-in-identifiers",CL_ALL, OPT_fdollars_in_identifiers) \
+ OPT("fdump-", CL_ALL | CL_JOINED, OPT_fdump) \
+ OPT("felide-constructors", CL_CXX, OPT_felide_constructors) \
+ OPT("fenforce-eh-specs", CL_CXX, OPT_fenforce_eh_specs) \
+ OPT("fenum-int-equiv", CL_CXX, OPT_fenum_int_equiv) \
+ OPT("fexternal-templates", CL_CXX, OPT_fexternal_templates) \
+ OPT("ffixed-form", CL_C, OPT_ffixed_form) \
+ OPT("ffixed-line-length-", CL_C | CL_JOINED, OPT_ffixed_line_length) \
+ OPT("ffor-scope", CL_CXX, OPT_ffor_scope) \
+ OPT("ffreestanding", CL_C, OPT_ffreestanding) \
+ OPT("fgnu-keywords", CL_CXX, OPT_fgnu_keywords) \
+ OPT("fgnu-runtime", CL_OBJC, OPT_fgnu_runtime) \
+ OPT("fguiding-decls", CL_CXX, OPT_fguiding_decls) \
+ OPT("fhandle-exceptions", CL_CXX, OPT_fhandle_exceptions) \
+ OPT("fhonor-std", CL_CXX, OPT_fhonor_std) \
+ OPT("fhosted", CL_C, OPT_fhosted) \
+ OPT("fhuge-objects", CL_CXX, OPT_fhuge_objects) \
+ OPT("fimplement-inlines", CL_CXX, OPT_fimplement_inlines) \
+ OPT("fimplicit-inline-templates", CL_CXX, OPT_fimplicit_inline_templates) \
+ OPT("fimplicit-templates", CL_CXX, OPT_fimplicit_templates) \
+ OPT("flabels-ok", CL_CXX, OPT_flabels_ok) \
+ OPT("fms-extensions", CL_ALL, OPT_fms_extensions) \
+ OPT("fname-mangling-version-",CL_CXX | CL_JOINED, OPT_fname_mangling) \
+ OPT("fnew-abi", CL_CXX, OPT_fnew_abi) \
+ OPT("fnext-runtime", CL_OBJC, OPT_fnext_runtime) \
+ OPT("fnonansi-builtins", CL_CXX, OPT_fnonansi_builtins) \
+ OPT("fnonnull-objects", CL_CXX, OPT_fnonnull_objects) \
+ OPT("foperator-names", CL_CXX, OPT_foperator_names) \
+ OPT("foptional-diags", CL_CXX, OPT_foptional_diags) \
+ OPT("fpermissive", CL_CXX, OPT_fpermissive) \
+ OPT("fpreprocessed", CL_ALL, OPT_fpreprocessed) \
+ OPT("frepo", CL_CXX, OPT_frepo) \
+ OPT("frtti", CL_CXX, OPT_frtti) \
+ OPT("fshort-double", CL_ALL, OPT_fshort_double) \
+ OPT("fshort-enums", CL_ALL, OPT_fshort_enums) \
+ OPT("fshort-wchar", CL_ALL, OPT_fshort_wchar) \
+ OPT("fshow-column", CL_ALL, OPT_fshow_column) \
+ OPT("fsigned-bitfields", CL_ALL, OPT_fsigned_bitfields) \
+ OPT("fsigned-char", CL_ALL, OPT_fsigned_char) \
+ OPT("fsquangle", CL_CXX, OPT_fsquangle) \
+ OPT("fstats", CL_CXX, OPT_fstats) \
+ OPT("fstrict-prototype", CL_CXX, OPT_fstrict_prototype) \
+ OPT("ftabstop=", CL_ALL | CL_JOINED, OPT_ftabstop) \
+ OPT("ftemplate-depth-", CL_CXX | CL_JOINED, OPT_ftemplate_depth) \
+ OPT("fthis-is-variable", CL_CXX, OPT_fthis_is_variable) \
+ OPT("funsigned-bitfields", CL_ALL, OPT_funsigned_bitfields) \
+ OPT("funsigned-char", CL_ALL, OPT_funsigned_char) \
+ OPT("fuse-cxa-atexit", CL_CXX, OPT_fuse_cxa_atexit) \
+ OPT("fvtable-gc", CL_CXX, OPT_fvtable_gc) \
+ OPT("fvtable-thunks", CL_CXX, OPT_fvtable_thunks) \
+ OPT("fweak", CL_CXX, OPT_fweak) \
+ OPT("fxref", CL_CXX, OPT_fxref) \
+ OPT("gen-decls", CL_OBJC, OPT_gen_decls) \
+ OPT("lang-asm", CL_C_ONLY, OPT_lang_asm) \
+ OPT("lang-objc", CL_ALL, OPT_lang_objc) \
+ OPT("nostdinc", CL_ALL, OPT_nostdinc) \
+ OPT("nostdinc++", CL_ALL, OPT_nostdincplusplus) \
+ OPT("o", CL_ALL | CL_ARG, OPT_o) \
+ OPT("pedantic", CL_ALL, OPT_pedantic) \
+ OPT("pedantic-errors", CL_ALL, OPT_pedantic_errors) \
+ OPT("print-objc-runtime-info", CL_OBJC, OPT_print_objc_runtime_info) \
+ OPT("remap", CL_ALL, OPT_remap) \
+ OPT("std=c++98", CL_CXX, OPT_std_cplusplus98) \
+ OPT("std=c89", CL_C, OPT_std_c89) \
+ OPT("std=c99", CL_C, OPT_std_c99) \
+ OPT("std=c9x", CL_C, OPT_std_c9x) \
+ OPT("std=gnu++98", CL_CXX, OPT_std_gnuplusplus98) \
+ OPT("std=gnu89", CL_C, OPT_std_gnu89) \
+ OPT("std=gnu99", CL_C, OPT_std_gnu99) \
+ OPT("std=gnu9x", CL_C, OPT_std_gnu9x) \
+ OPT("std=iso9899:1990", CL_C, OPT_std_iso9899_1990) \
+ OPT("std=iso9899:199409", CL_C, OPT_std_iso9899_199409) \
+ OPT("std=iso9899:1999", CL_C, OPT_std_iso9899_1999) \
+ OPT("std=iso9899:199x", CL_C, OPT_std_iso9899_199x) \
+ OPT("traditional-cpp", CL_ALL, OPT_traditional_cpp) \
+ OPT("trigraphs", CL_ALL, OPT_trigraphs) \
+ OPT("undef", CL_ALL, OPT_undef) \
+ OPT("v", CL_ALL, OPT_v) \
+ OPT("w", CL_ALL, OPT_w)
+
+#define OPT(text, flags, code) code,
+enum opt_code
+{
+ COMMAND_LINE_OPTIONS
+ N_OPTS
+};
+#undef OPT
+
+struct cl_option
+{
+ const char *opt_text;
+ unsigned char opt_len;
+ unsigned char flags;
+ ENUM_BITFIELD (opt_code) opt_code : 2 * CHAR_BIT;
+};
+
+#define OPT(text, flags, code) { text, sizeof(text) - 1, flags, code },
+#ifdef HOST_EBCDIC
+static struct cl_option cl_options[] =
+#else
+static const struct cl_option cl_options[] =
+#endif
+{
+ COMMAND_LINE_OPTIONS
+};
+#undef OPT
+#undef COMMAND_LINE_OPTIONS
+
+/* Holds switches parsed by c_common_decode_option (), but whose
+ handling is deffered to c_common_post_options (). */
+static void defer_opt PARAMS ((enum opt_code, const char *));
+static struct deferred_opt
+{
+ enum opt_code code;
+ const char *arg;
+} *deferred_opts;
+
+
+#ifdef HOST_EBCDIC
+static int opt_comp PARAMS ((const void *, const void *));
+
+/* Run-time sorting of options array. */
+static int
+opt_comp (p1, p2)
+ const void *p1, *p2;
+{
+ return strcmp (((struct cl_option *) p1)->opt_text,
+ ((struct cl_option *) p2)->opt_text);
+}
+#endif
+
+/* Complain that switch OPT_INDEX expects an argument but none was
+ provided. */
+static void
+missing_arg (opt_index)
+ size_t opt_index;
+{
+ const char *opt_text = cl_options[opt_index].opt_text;
+
+ switch (cl_options[opt_index].opt_code)
+ {
+ case OPT_Wformat_eq:
+ case OPT_d:
+ case OPT_fabi_version:
+ case OPT_fbuiltin_:
+ case OPT_fdump:
+ case OPT_fname_mangling:
+ case OPT_ftabstop:
+ case OPT_ftemplate_depth:
+ default:
+ error ("missing argument to \"-%s\"", opt_text);
+ break;
+
+ case OPT_fconstant_string_class:
+ error ("no class name specified with \"-%s\"", opt_text);
+ break;
+
+ case OPT_MF:
+ case OPT_MD:
+ case OPT_MMD:
+ case OPT_o:
+ error ("missing filename after \"-%s\"", opt_text);
+ break;
+
+ case OPT_MQ:
+ case OPT_MT:
+ error ("missing target after \"-%s\"", opt_text);
+ break;
+ }
+}
+
+/* Perform a binary search to find which option the command-line INPUT
+ matches. Returns its index in the option array, and N_OPTS on
+ failure.
+
+ Complications arise since some options can be suffixed with an
+ argument, and multiple complete matches can occur, e.g. -pedantic
+ and -pedantic-errors. Also, some options are only accepted by some
+ languages. If a switch matches for a different language and
+ doesn't match any alternatives for the true front end, the index of
+ the matched switch is returned anyway. The caller should check for
+ this case. */
+static size_t
+find_opt (input, lang_flag)
+ const char *input;
+ int lang_flag;
+{
+ size_t md, mn, mx;
+ size_t opt_len;
+ size_t result = N_OPTS;
+ int comp;
+
+ mn = 0;
+ mx = N_OPTS;
+
+ while (mx > mn)
+ {
+ md = (mn + mx) / 2;
+
+ opt_len = cl_options[md].opt_len;
+ comp = strncmp (input, cl_options[md].opt_text, opt_len);
+
+ if (comp < 0)
+ mx = md;
+ else if (comp > 0)
+ mn = md + 1;
+ else
+ {
+ /* The switch matches. It it an exact match? */
+ if (input[opt_len] == '\0')
+ return md;
+ else
+ {
+ mn = md + 1;
+
+ /* If the switch takes no arguments this is not a proper
+ match, so we continue the search (e.g. input="stdc++"
+ match was "stdc"). */
+ if (!(cl_options[md].flags & CL_JOINED))
+ continue;
+
+ /* Is this switch valid for this front end? */
+ if (!(cl_options[md].flags & lang_flag))
+ {
+ /* If subsequently we don't find a better match,
+ return this and let the caller report it as a bad
+ match. */
+ result = md;
+ continue;
+ }
+
+ /* Two scenarios remain: we have the switch's argument,
+ or we match a longer option. This can happen with
+ -iwithprefix and -withprefixbefore. The longest
+ possible option match succeeds.
+
+ Scan forwards, and return an exact match. Otherwise
+ return the longest valid option-accepting match (mx).
+ This loops at most twice with current options. */
+ mx = md;
+ for (md = md + 1; md < (size_t) N_OPTS; md++)
+ {
+ opt_len = cl_options[md].opt_len;
+ if (strncmp (input, cl_options[md].opt_text, opt_len))
+ break;
+ if (input[opt_len] == '\0')
+ return md;
+ if (cl_options[md].flags & lang_flag
+ && cl_options[md].flags & CL_JOINED)
+ mx = md;
+ }
+
+ return mx;
+ }
+ }
+ }
+
+ return result;
+}
+
+/* Defer option CODE with argument ARG. */
+static void
+defer_opt (code, arg)
+ enum opt_code code;
+ const char *arg;
+{
+ /* FIXME: this should be in c_common_init_options, which should take
+ argc and argv. */
+ if (!deferred_opts)
+ {
+ extern int save_argc;
+ deferred_size = save_argc;
+ deferred_opts = (struct deferred_opt *)
+ xmalloc (deferred_size * sizeof (struct deferred_opt));
+ }
+
+ if (deferred_count == deferred_size)
+ abort ();
+
+ deferred_opts[deferred_count].code = code;
+ deferred_opts[deferred_count].arg = arg;
+ deferred_count++;
+}
+
+/* Common initialization before parsing options. */
+void
+c_common_init_options (lang)
+ enum c_language_kind lang;
+{
+#ifdef HOST_EBCDIC
+ /* For non-ASCII hosts, the cl_options array needs to be sorted at
+ runtime. */
+ qsort (cl_options, N_OPTS, sizeof (struct cl_option), opt_comp);
+#endif
+#if ENABLE_CHECKING
+ {
+ size_t i;
+
+ for (i = 1; i < N_OPTS; i++)
+ if (strcmp (cl_options[i - 1].opt_text, cl_options[i].opt_text) >= 0)
+ error ("options array incorrectly sorted: %s is before %s",
+ cl_options[i - 1].opt_text, cl_options[i].opt_text);
+ }
+#endif
+
+ c_language = lang;
+ parse_in = cpp_create_reader (lang == clk_c ? CLK_GNUC89 : CLK_GNUCXX);
+ cpp_opts = cpp_get_options (parse_in);
+ if (flag_objc)
+ cpp_opts->objc = 1;
+
+ flag_const_strings = (lang == clk_cplusplus);
+ warn_pointer_arith = (lang == clk_cplusplus);
+ if (lang == clk_c)
+ warn_sign_compare = -1;
+}
+
+/* Handle one command-line option in (argc, argv).
+ Can be called multiple times, to handle multiple sets of options.
+ Returns number of strings consumed. */
+int
+c_common_decode_option (argc, argv)
+ int argc;
+ char **argv;
+{
+ static const int lang_flags[] = {CL_C_ONLY, CL_C, CL_CXX_ONLY, CL_CXX};
+ size_t opt_index;
+ const char *opt, *arg = 0;
+ char *dup = 0;
+ bool on = true;
+ int result, lang_flag;
+ const struct cl_option *option;
+ enum opt_code code;
+
+ opt = argv[0];
+
+ /* Interpret "-" or a non-switch as a file name. */
+ if (opt[0] != '-' || opt[1] == '\0')
+ {
+ if (!in_fname)
+ in_fname = opt;
+ else if (!out_fname)
+ out_fname = opt;
+ else
+ {
+ error ("too many filenames given. Type %s --help for usage",
+ progname);
+ return argc;
+ }
+
+ return 1;
+ }
+
+ /* Drop the "no-" from negative switches. */
+ if ((opt[1] == 'W' || opt[1] == 'f')
+ && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
+ {
+ size_t len = strlen (opt) - 3;
+
+ dup = xmalloc (len + 1);
+ dup[0] = '-';
+ dup[1] = opt[1];
+ memcpy (dup + 2, opt + 5, len - 2 + 1);
+ opt = dup;
+ on = false;
+ }
+
+ result = cpp_handle_option (parse_in, argc, argv);
+
+ /* Skip over '-'. */
+ lang_flag = lang_flags[(c_language << 1) + flag_objc];
+ opt_index = find_opt (opt + 1, lang_flag);
+ if (opt_index == N_OPTS)
+ goto done;
+
+ result = 1;
+ option = &cl_options[opt_index];
+
+ /* Sort out any argument the switch takes. */
+ if (option->flags & CL_ARG)
+ {
+ if (option->flags & CL_JOINED)
+ {
+ /* Have arg point to the original switch. This is because
+ some code, such as disable_builtin_function, expects its
+ argument to be persistent until the program exits. */
+ arg = argv[0] + cl_options[opt_index].opt_len + 1;
+ if (!on)
+ arg += strlen ("no-");
+ }
+
+ /* If we don't have an argument, and CL_SEPARATE, try the next
+ argument in the vector. */
+ if (!arg || (*arg == '\0' && option->flags & CL_SEPARATE))
+ {
+ arg = argv[1];
+ result = 2;
+ }
+
+ if (!arg || *arg == '\0')
+ {
+ missing_arg (opt_index);
+ result = argc;
+ goto done;
+ }
+ }
+
+ /* Complain about the wrong language after we've swallowed any
+ necessary extra argument. Eventually make this a hard error
+ after the call to find_opt, and return argc. */
+ if (!(cl_options[opt_index].flags & lang_flag))
+ {
+ complain_wrong_lang (opt_index, on);
+ goto done;
+ }
+
+ switch (code = option->opt_code)
+ {
+ case N_OPTS: /* Shut GCC up. */
+ break;
+
+ case OPT__help:
+ print_help ();
+ break;
+
+ case OPT_C:
+ cpp_opts->discard_comments = 0;
+ break;
+
+ case OPT_CC:
+ cpp_opts->discard_comments = 0;
+ cpp_opts->discard_comments_in_macro_exp = 0;
+ break;
+
+ case OPT_E:
+ flag_preprocess_only = 1;
+ break;
+
+ case OPT_H:
+ cpp_opts->print_include_names = 1;
+ break;
+
+ case OPT_M:
+ case OPT_MM:
+ /* When doing dependencies with -M or -MM, suppress normal
+ preprocessed output, but still do -dM etc. as software
+ depends on this. Preprocessed output does occur if -MD, -MMD
+ or environment var dependency generation is used. */
+ cpp_opts->deps.style = (code == OPT_M ? DEPS_SYSTEM: DEPS_USER);
+ cpp_opts->no_output = 1;
+ cpp_opts->inhibit_warnings = 1;
+ break;
+
+ case OPT_MD:
+ case OPT_MMD:
+ cpp_opts->deps.style = (code == OPT_MD ? DEPS_SYSTEM: DEPS_USER);
+ deps_file = arg;
+ break;
+
+ case OPT_MF:
+ deps_seen = true;
+ deps_file = arg;
+ break;
+
+ case OPT_MG:
+ deps_seen = true;
+ cpp_opts->deps.missing_files = true;
+ break;
+
+ case OPT_MP:
+ deps_seen = true;
+ cpp_opts->deps.phony_targets = true;
+ break;
+
+ case OPT_MQ:
+ case OPT_MT:
+ deps_seen = true;
+ defer_opt (code, arg);
+ break;
+
+ case OPT_P:
+ cpp_opts->no_line_commands = 1;
+ break;
+
+ case OPT_Wabi:
+ warn_abi = on;
+ break;
+
+ case OPT_Wall:
+ set_Wunused (on);
+ set_Wformat (on);
+ set_Wimplicit (on);
+ warn_char_subscripts = on;
+ warn_missing_braces = on;
+ warn_parentheses = on;
+ warn_return_type = on;
+ warn_sequence_point = on; /* Was C only. */
+ if (c_language == clk_cplusplus)
+ warn_sign_compare = on;
+ warn_switch = on;
+ warn_strict_aliasing = on;
+
+ /* Only warn about unknown pragmas that are not in system
+ headers. */
+ warn_unknown_pragmas = on;
+
+ /* We save the value of warn_uninitialized, since if they put
+ -Wuninitialized on the command line, we need to generate a
+ warning about not using it without also specifying -O. */
+ if (warn_uninitialized != 1)
+ warn_uninitialized = (on ? 2 : 0);
+
+ if (c_language == clk_c)
+ /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding
+ can turn it off only if it's not explicit. */
+ warn_main = on * 2;
+ else
+ {
+ /* C++-specific warnings. */
+ warn_ctor_dtor_privacy = on;
+ warn_nonvdtor = on;
+ warn_reorder = on;
+ warn_nontemplate_friend = on;
+ }
+
+ cpp_opts->warn_trigraphs = on;
+ cpp_opts->warn_comments = on;
+ cpp_opts->warn_num_sign_change = on;
+ cpp_opts->warn_multichar = on; /* Was C++ only. */
+ break;
+
+ case OPT_Wbad_function_cast:
+ warn_bad_function_cast = on;
+ break;
+
+ case OPT_Wcast_qual:
+ warn_cast_qual = on;
+ break;
+
+ case OPT_Wchar_subscripts:
+ warn_char_subscripts = on;
+ break;
+
+ case OPT_Wcomment:
+ case OPT_Wcomments:
+ cpp_opts->warn_comments = on;
+ break;
+
+ case OPT_Wconversion:
+ warn_conversion = on;
+ break;
+
+ case OPT_Wctor_dtor_privacy:
+ warn_ctor_dtor_privacy = on;
+ break;
+
+ case OPT_Wdeprecated:
+ warn_deprecated = on;
+ break;
+
+ case OPT_Wdiv_by_zero:
+ warn_div_by_zero = on;
+ break;
+
+ case OPT_Weffcxx:
+ warn_ecpp = on;
+ break;
+
+ case OPT_Wendif_labels:
+ cpp_opts->warn_endif_labels = on;
+ break;
+
+ case OPT_Werror:
+ cpp_opts->warnings_are_errors = on;
+ break;
+
+ case OPT_Werror_implicit_function_decl:
+ if (!on)
+ result = 0;
+ else
+ mesg_implicit_function_declaration = 2;
+ break;
+
+ case OPT_Wfloat_equal:
+ warn_float_equal = on;
+ break;
+
+ case OPT_Wformat:
+ set_Wformat (on);
+ break;
+
+ case OPT_Wformat_eq:
+ set_Wformat (atoi (arg));
+ break;
+
+ case OPT_Wformat_extra_args:
+ warn_format_extra_args = on;
+ break;
+
+ case OPT_Wformat_nonliteral:
+ warn_format_nonliteral = on;
+ break;
+
+ case OPT_Wformat_security:
+ warn_format_security = on;
+ break;
+
+ case OPT_Wformat_y2k:
+ warn_format_y2k = on;
+ break;
+
+ case OPT_Wformat_zero_length:
+ warn_format_zero_length = on;
+ break;
+
+ case OPT_Wimplicit:
+ set_Wimplicit (on);
+ break;
+
+ case OPT_Wimplicit_function_decl:
+ mesg_implicit_function_declaration = on;
+ break;
+
+ case OPT_Wimplicit_int:
+ warn_implicit_int = on;
+ break;
+
+ case OPT_Wimport:
+ cpp_opts->warn_import = on;
+ break;
+
+ case OPT_Wlong_long:
+ warn_long_long = on;
+ break;
+
+ case OPT_Wmain:
+ if (on)
+ warn_main = 1;
+ else
+ warn_main = -1;
+ break;
+
+ case OPT_Wmissing_braces:
+ warn_missing_braces = on;
+ break;
+
+ case OPT_Wmissing_declarations:
+ warn_missing_declarations = on;
+ break;
+
+ case OPT_Wmissing_format_attribute:
+ warn_missing_format_attribute = on;
+ break;
+
+ case OPT_Wmissing_prototypes:
+ warn_missing_prototypes = on;
+ break;
+
+ case OPT_Wmultichar:
+ cpp_opts->warn_multichar = on;
+ break;
+
+ case OPT_Wnested_externs:
+ warn_nested_externs = on;
+ break;
+
+ case OPT_Wnon_template_friend:
+ warn_nontemplate_friend = on;
+ break;
+
+ case OPT_Wnon_virtual_dtor:
+ warn_nonvdtor = on;
+ break;
+
+ case OPT_Wnonnull:
+ warn_nonnull = on;
+ break;
+
+ case OPT_Wold_style_cast:
+ warn_old_style_cast = on;
+ break;
+
+ case OPT_Woverloaded_virtual:
+ warn_overloaded_virtual = on;
+ break;
+
+ case OPT_Wparentheses:
+ warn_parentheses = on;
+ break;
+
+ case OPT_Wpmf_conversions:
+ warn_pmf2ptr = on;
+ break;
+
+ case OPT_Wpointer_arith:
+ warn_pointer_arith = on;
+ break;
+
+ case OPT_Wprotocol:
+ warn_protocol = on;
+ break;
+
+ case OPT_Wselector:
+ warn_selector = on;
+ break;
+
+ case OPT_Wredundant_decls:
+ warn_redundant_decls = on;
+ break;
+
+ case OPT_Wreorder:
+ warn_reorder = on;
+ break;
+
+ case OPT_Wreturn_type:
+ warn_return_type = on;
+ break;
+
+ case OPT_Wsequence_point:
+ warn_sequence_point = on;
+ break;
+
+ case OPT_Wsign_compare:
+ warn_sign_compare = on;
+ break;
+
+ case OPT_Wsign_promo:
+ warn_sign_promo = on;
+ break;
+
+ case OPT_Wstrict_prototypes:
+ if (!on && c_language == clk_cplusplus)
+ warning ("-Wno-strict-prototypes is not supported in C++");
+ else
+ warn_strict_prototypes = on;
+ break;
+
+ case OPT_Wsynth:
+ warn_synth = on;
+ break;
+
+ case OPT_Wsystem_headers:
+ cpp_opts->warn_system_headers = on;
+ break;
+
+ case OPT_Wtraditional:
+ warn_traditional = on;
+ cpp_opts->warn_traditional = on;
+ break;
+
+ case OPT_Wtrigraphs:
+ cpp_opts->warn_trigraphs = on;
+ break;
+
+ case OPT_Wundeclared_selector:
+ warn_undeclared_selector = on;
+ break;
+
+ case OPT_Wundef:
+ cpp_opts->warn_undef = on;
+ break;
+
+ case OPT_Wunknown_pragmas:
+ /* Set to greater than 1, so that even unknown pragmas in
+ system headers will be warned about. */
+ warn_unknown_pragmas = on * 2;
+ break;
+
+ case OPT_Wunused_macros:
+ cpp_opts->warn_unused_macros = on;
+ break;
+
+ case OPT_Wwrite_strings:
+ if (c_language == clk_c)
+ flag_const_strings = on;
+ else
+ warn_write_strings = on;
+ break;
+
+ case OPT_ansi:
+ if (c_language == clk_c)
+ set_std_c89 (false, true);
+ else
+ set_std_cxx98 (true);
+ break;
+
+ case OPT_d:
+ handle_OPT_d (arg);
+ break;
+
+ case OPT_fcond_mismatch:
+ if (c_language == clk_c)
+ {
+ flag_cond_mismatch = on;
+ break;
+ }
+ /* Fall through. */
+
+ case OPT_fall_virtual:
+ case OPT_fenum_int_equiv:
+ case OPT_fguiding_decls:
+ case OPT_fhonor_std:
+ case OPT_fhuge_objects:
+ case OPT_flabels_ok:
+ case OPT_fname_mangling:
+ case OPT_fnew_abi:
+ case OPT_fnonnull_objects:
+ case OPT_fsquangle:
+ case OPT_fstrict_prototype:
+ case OPT_fthis_is_variable:
+ case OPT_fvtable_thunks:
+ case OPT_fxref:
+ warning ("switch \"%s\" is no longer supported", argv[0]);
+ break;
+
+ case OPT_fabi_version:
+ flag_abi_version = read_integral_parameter (arg, argv[0], 1);
+ break;
+
+ case OPT_faccess_control:
+ flag_access_control = on;
+ break;
+
+ case OPT_falt_external_templates:
+ flag_alt_external_templates = on;
+ if (on)
+ flag_external_templates = true;
+ cp_deprecated:
+ warning ("switch \"%s\" is deprecated, please see documentation for details", argv[0]);
+ break;
+
+ case OPT_fasm:
+ flag_no_asm = !on;
+ break;
+
+ case OPT_fbuiltin:
+ flag_no_builtin = !on;
+ break;
+
+ case OPT_fbuiltin_:
+ if (on)
+ result = 0;
+ else
+ disable_builtin_function (arg);
+ break;
+
+ case OPT_fdollars_in_identifiers:
+ dollars_in_ident = on;
+ break;
+
+ case OPT_fdump:
+ if (!on || !dump_switch_p (argv[0] + strlen ("-f")))
+ result = 0;
+ break;
+
+ case OPT_ffreestanding:
+ on = !on;
+ /* Fall through... */
+ case OPT_fhosted:
+ flag_hosted = on;
+ flag_no_builtin = !on;
+ /* warn_main will be 2 if set by -Wall, 1 if set by -Wmain */
+ if (!on && warn_main == 2)
+ warn_main = 0;
+ break;
+
+ case OPT_fshort_double:
+ flag_short_double = on;
+ break;
+
+ case OPT_fshort_enums:
+ flag_short_enums = on;
+ break;
+
+ case OPT_fshort_wchar:
+ flag_short_wchar = on;
+ break;
+
+ case OPT_fsigned_bitfields:
+ flag_signed_bitfields = on;
+ explicit_flag_signed_bitfields = 1;
+ break;
+
+ case OPT_fsigned_char:
+ flag_signed_char = on;
+ break;
+
+ case OPT_funsigned_bitfields:
+ flag_signed_bitfields = !on;
+ explicit_flag_signed_bitfields = 1;
+ break;
+
+ case OPT_funsigned_char:
+ flag_signed_char = !on;
+ break;
+
+ case OPT_fcheck_new:
+ flag_check_new = on;
+ break;
+
+ case OPT_fconserve_space:
+ flag_conserve_space = on;
+ break;
+
+ case OPT_fconst_strings:
+ flag_const_strings = on;
+ break;
+
+ case OPT_fconstant_string_class:
+ constant_string_class_name = arg;
+ break;
+
+ case OPT_fdefault_inline:
+ flag_default_inline = on;
+ break;
+
+ case OPT_felide_constructors:
+ flag_elide_constructors = on;
+ break;
+
+ case OPT_fenforce_eh_specs:
+ flag_enforce_eh_specs = on;
+ break;
+
+ case OPT_fexternal_templates:
+ flag_external_templates = on;
+ goto cp_deprecated;
+
+ case OPT_ffixed_form:
+ case OPT_ffixed_line_length:
+ /* Fortran front end options ignored when preprocessing only. */
+ if (flag_preprocess_only)
+ result = -1;
+ break;
+
+ case OPT_ffor_scope:
+ flag_new_for_scope = on;
+ break;
+
+ case OPT_fgnu_keywords:
+ flag_no_gnu_keywords = !on;
+ break;
+
+ case OPT_fgnu_runtime:
+ flag_next_runtime = !on;
+ break;
+
+ case OPT_fhandle_exceptions:
+ warning ("-fhandle-exceptions has been renamed to -fexceptions (and is now on by default)");
+ flag_exceptions = on;
+ break;
+
+ case OPT_fimplement_inlines:
+ flag_implement_inlines = on;
+ break;
+
+ case OPT_fimplicit_inline_templates:
+ flag_implicit_inline_templates = on;
+ break;
+
+ case OPT_fimplicit_templates:
+ flag_implicit_templates = on;
+ break;
+
+ case OPT_fms_extensions:
+ flag_ms_extensions = on;
+ break;
+
+ case OPT_fnext_runtime:
+ flag_next_runtime = on;
+ break;
+
+ case OPT_fnonansi_builtins:
+ flag_no_nonansi_builtin = !on;
+ break;
+
+ case OPT_foperator_names:
+ cpp_opts->operator_names = on;
+ break;
+
+ case OPT_foptional_diags:
+ flag_optional_diags = on;
+ break;
+
+ case OPT_fpermissive:
+ flag_permissive = on;
+ break;
+
+ case OPT_fpreprocessed:
+ cpp_opts->preprocessed = on;
+ break;
+
+ case OPT_frepo:
+ flag_use_repository = on;
+ if (on)
+ flag_implicit_templates = 0;
+ break;
+
+ case OPT_frtti:
+ flag_rtti = on;
+ break;
+
+ case OPT_fshow_column:
+ cpp_opts->show_column = on;
+ break;
+
+ case OPT_fstats:
+ flag_detailed_statistics = on;
+ break;
+
+ case OPT_ftabstop:
+ /* Don't recognize -fno-tabstop=. */
+ if (!on)
+ return 0;
+
+ /* It is documented that we silently ignore silly values. */
+ {
+ char *endptr;
+ long tabstop = strtol (arg, &endptr, 10);
+ if (*endptr == '\0' && tabstop >= 1 && tabstop <= 100)
+ cpp_opts->tabstop = tabstop;
+ }
+ break;
+
+ case OPT_ftemplate_depth:
+ max_tinst_depth = read_integral_parameter (arg, argv[0], 0);
+ break;
+
+ case OPT_fvtable_gc:
+ flag_vtable_gc = on;
+ break;
+
+ case OPT_fuse_cxa_atexit:
+ flag_use_cxa_atexit = on;
+ break;
+
+ case OPT_fweak:
+ flag_weak = on;
+ break;
+
+ case OPT_gen_decls:
+ flag_gen_declaration = 1;
+ break;
+
+ case OPT_lang_asm:
+ cpp_set_lang (parse_in, CLK_ASM);
+ break;
+
+ case OPT_lang_objc:
+ cpp_opts->objc = 1;
+ break;
+
+ case OPT_nostdinc:
+ /* No default include directories. You must specify all
+ include-file directories with -I. */
+ cpp_opts->no_standard_includes = 1;
+ break;
+
+ case OPT_nostdincplusplus:
+ /* No default C++-specific include directories. */
+ cpp_opts->no_standard_cplusplus_includes = 1;
+ break;
+
+ case OPT_o:
+ if (!out_fname)
+ out_fname = arg;
+ else
+ {
+ error ("output filename specified twice");
+ result = argc;
+ }
+ break;
+
+ /* We need to handle the -pedantic switches here, rather than in
+ c_common_post_options, so that a subsequent -Wno-endif-labels
+ is not overridden. */
+ case OPT_pedantic_errors:
+ cpp_opts->pedantic_errors = 1;
+ /* fall through */
+ case OPT_pedantic:
+ cpp_opts->pedantic = 1;
+ cpp_opts->warn_endif_labels = 1;
+ break;
+
+ case OPT_print_objc_runtime_info:
+ print_struct_values = 1;
+ break;
+
+ case OPT_remap:
+ cpp_opts->remap = 1;
+ break;
+
+ case OPT_std_cplusplus98:
+ case OPT_std_gnuplusplus98:
+ set_std_cxx98 (code == OPT_std_cplusplus98 /* ISO */);
+ break;
+
+ case OPT_std_c89:
+ case OPT_std_iso9899_1990:
+ case OPT_std_iso9899_199409:
+ set_std_c89 (code == OPT_std_iso9899_199409 /* c94 */, true /* ISO */);
+ break;
+
+ case OPT_std_gnu89:
+ set_std_c89 (false /* c94 */, false /* ISO */);
+ break;
+
+ case OPT_std_c99:
+ case OPT_std_c9x:
+ case OPT_std_iso9899_1999:
+ case OPT_std_iso9899_199x:
+ set_std_c99 (true /* ISO */);
+ break;
+
+ case OPT_std_gnu99:
+ case OPT_std_gnu9x:
+ set_std_c99 (false /* ISO */);
+ break;
+
+ case OPT_trigraphs:
+ cpp_opts->trigraphs = 1;
+ break;
+
+ case OPT_traditional_cpp:
+ cpp_opts->traditional = 1;
+ break;
+
+ case OPT_undef:
+ flag_undef = 1;
+ break;
+
+ case OPT_w:
+ cpp_opts->inhibit_warnings = 1;
+ break;
+
+ case OPT_v:
+ cpp_opts->verbose = 1;
+ break;
+ }
+
+ done:
+ if (dup)
+ free (dup);
+ return result;
+}
+
+/* Post-switch processing. */
+bool
+c_common_post_options ()
+{
+ /* Canonicalize the input and output filenames. */
+ if (in_fname == NULL || !strcmp (in_fname, "-"))
+ in_fname = "";
+
+ if (out_fname == NULL || !strcmp (out_fname, "-"))
+ out_fname = "";
+
+ if (cpp_opts->deps.style == DEPS_NONE)
+ check_deps_environment_vars ();
+
+ handle_deferred_opts ();
+
+ sanitize_cpp_opts ();
+
+ flag_inline_trees = 1;
+
+ /* Use tree inlining if possible. Function instrumentation is only
+ done in the RTL level, so we disable tree inlining. */
+ if (! flag_instrument_function_entry_exit)
+ {
+ if (!flag_no_inline)
+ flag_no_inline = 1;
+ if (flag_inline_functions)
+ {
+ flag_inline_trees = 2;
+ flag_inline_functions = 0;
+ }
+ }
+
+ /* Special format checking options don't work without -Wformat; warn if
+ they are used. */
+ if (warn_format_y2k && !warn_format)
+ warning ("-Wformat-y2k ignored without -Wformat");
+ if (warn_format_extra_args && !warn_format)
+ warning ("-Wformat-extra-args ignored without -Wformat");
+ if (warn_format_zero_length && !warn_format)
+ warning ("-Wformat-zero-length ignored without -Wformat");
+ if (warn_format_nonliteral && !warn_format)
+ warning ("-Wformat-nonliteral ignored without -Wformat");
+ if (warn_format_security && !warn_format)
+ warning ("-Wformat-security ignored without -Wformat");
+ if (warn_missing_format_attribute && !warn_format)
+ warning ("-Wmissing-format-attribute ignored without -Wformat");
+
+ /* If an error has occurred in cpplib, note it so we fail
+ immediately. */
+ errorcount += cpp_errors (parse_in);
+
+ return flag_preprocess_only;
+}
+
+/* Preprocess the input file to out_stream. */
+static void
+preprocess_file ()
+{
+ /* Open the output now. We must do so even if no_output is on,
+ because there may be other output than from the actual
+ preprocessing (e.g. from -dM). */
+ if (out_fname[0] == '\0')
+ out_stream = stdout;
+ else
+ out_stream = fopen (out_fname, "w");
+
+ if (out_stream == NULL)
+ fatal_io_error ("opening output file %s", out_fname);
+ else
+ cpp_preprocess_file (parse_in, in_fname, out_stream);
+}
+
+/* Front end initialization common to C, ObjC and C++. */
+const char *
+c_common_init (filename)
+ const char *filename;
+{
+ /* Set up preprocessor arithmetic. Must be done after call to
+ c_common_nodes_and_builtins for type nodes to be good. */
+ cpp_opts->precision = TYPE_PRECISION (intmax_type_node);
+ cpp_opts->char_precision = TYPE_PRECISION (char_type_node);
+ cpp_opts->int_precision = TYPE_PRECISION (integer_type_node);
+ cpp_opts->wchar_precision = TYPE_PRECISION (wchar_type_node);
+ cpp_opts->unsigned_wchar = TREE_UNSIGNED (wchar_type_node);
+
+ /* Register preprocessor built-ins before calls to
+ cpp_main_file. */
+ cpp_get_callbacks (parse_in)->register_builtins = cb_register_builtins;
+
+ /* NULL is passed up to toplev.c and we exit quickly. */
+ if (flag_preprocess_only)
+ {
+ preprocess_file ();
+ return NULL;
+ }
+
+ /* Do this before initializing pragmas, as then cpplib's hash table
+ has been set up. NOTE: we are using our own file name here, not
+ the one supplied. */
+ filename = init_c_lex (in_fname);
+
+ init_pragma ();
+
+ return filename;
+}
+
+/* Common finish hook for the C, ObjC and C++ front ends. */
+void
+c_common_finish ()
+{
+ FILE *deps_stream = NULL;
+
+ if (cpp_opts->deps.style != DEPS_NONE)
+ {
+ /* If -M or -MM was seen without -MF, default output to the
+ output stream. */
+ if (!deps_file)
+ deps_stream = out_stream;
+ else
+ {
+ deps_stream = fopen (deps_file, deps_append ? "a": "w");
+ if (!deps_stream)
+ fatal_io_error ("opening dependency file %s", deps_file);
+ }
+ }
+
+ /* For performance, avoid tearing down cpplib's internal structures
+ with cpp_destroy (). */
+ errorcount += cpp_finish (parse_in, deps_stream);
+
+ if (deps_stream && deps_stream != out_stream
+ && (ferror (deps_stream) || fclose (deps_stream)))
+ fatal_io_error ("closing dependency file %s", deps_file);
+
+ if (out_stream && (ferror (out_stream) || fclose (out_stream)))
+ fatal_io_error ("when writing output to %s", out_fname);
+}
+
+/* Either of two environment variables can specify output of
+ dependencies. Their value is either "OUTPUT_FILE" or "OUTPUT_FILE
+ DEPS_TARGET", where OUTPUT_FILE is the file to write deps info to
+ and DEPS_TARGET is the target to mention in the deps. They also
+ result in dependency information being appended to the output file
+ rather than overwriting it, and like Sun's compiler
+ SUNPRO_DEPENDENCIES suppresses the dependency on the main file. */
+static void
+check_deps_environment_vars ()
+{
+ char *spec;
+
+ GET_ENVIRONMENT (spec, "DEPENDENCIES_OUTPUT");
+ if (spec)
+ cpp_opts->deps.style = DEPS_USER;
+ else
+ {
+ GET_ENVIRONMENT (spec, "SUNPRO_DEPENDENCIES");
+ if (spec)
+ {
+ cpp_opts->deps.style = DEPS_SYSTEM;
+ cpp_opts->deps.ignore_main_file = true;
+ }
+ }
+
+ if (spec)
+ {
+ /* Find the space before the DEPS_TARGET, if there is one. */
+ char *s = strchr (spec, ' ');
+ if (s)
+ {
+ /* Let the caller perform MAKE quoting. */
+ defer_opt (OPT_MT, s + 1);
+ *s = '\0';
+ }
+
+ /* Command line -MF overrides environment variables and default. */
+ if (!deps_file)
+ deps_file = spec;
+
+ deps_append = 1;
+ }
+}
+
+/* Handle deferred command line switches. */
+static void
+handle_deferred_opts ()
+{
+ size_t i;
+
+ for (i = 0; i < deferred_count; i++)
+ {
+ struct deferred_opt *opt = &deferred_opts[i];
+
+ switch (opt->code)
+ {
+ case OPT_MT:
+ case OPT_MQ:
+ cpp_add_dependency_target (parse_in, opt->arg, opt->code == OPT_MQ);
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ free (deferred_opts);
+}
+
+/* These settings are appropriate for GCC, but not necessarily so for
+ cpplib as a library. */
+static void
+sanitize_cpp_opts ()
+{
+ /* If we don't know what style of dependencies to output, complain
+ if any other dependency switches have been given. */
+ if (deps_seen && cpp_opts->deps.style == DEPS_NONE)
+ error ("to generate dependencies you must specify either -M or -MM");
+
+ /* -dM and dependencies suppress normal output; do it here so that
+ the last -d[MDN] switch overrides earlier ones. */
+ if (cpp_opts->dump_macros == dump_only)
+ cpp_opts->no_output = 1;
+
+ /* Disable -dD, -dN and -dI if normal output is suppressed. Allow
+ -dM since at least glibc relies on -M -dM to work. */
+ if (cpp_opts->no_output)
+ {
+ if (cpp_opts->dump_macros != dump_only)
+ cpp_opts->dump_macros = dump_none;
+ cpp_opts->dump_includes = 0;
+ }
+
+ cpp_opts->unsigned_char = !flag_signed_char;
+ cpp_opts->stdc_0_in_system_headers = STDC_0_IN_SYSTEM_HEADERS;
+
+ /* We want -Wno-long-long to override -pedantic -std=non-c99
+ and/or -Wtraditional, whatever the ordering. */
+ cpp_opts->warn_long_long
+ = warn_long_long && ((!flag_isoc99 && pedantic) || warn_traditional);
+}
+
+/* Set the C 89 standard (with 1994 amendments if C94, without GNU
+ extensions if ISO). There is no concept of gnu94. */
+static void
+set_std_c89 (c94, iso)
+ int c94, iso;
+{
+ cpp_set_lang (parse_in, c94 ? CLK_STDC94: iso ? CLK_STDC89: CLK_GNUC89);
+ flag_iso = iso;
+ flag_no_asm = iso;
+ flag_no_gnu_keywords = iso;
+ flag_no_nonansi_builtin = iso;
+ flag_noniso_default_format_attributes = !iso;
+ flag_isoc94 = c94;
+ flag_isoc99 = 0;
+ flag_writable_strings = 0;
+}
+
+/* Set the C 99 standard (without GNU extensions if ISO). */
+static void
+set_std_c99 (iso)
+ int iso;
+{
+ cpp_set_lang (parse_in, iso ? CLK_STDC99: CLK_GNUC99);
+ flag_no_asm = iso;
+ flag_no_nonansi_builtin = iso;
+ flag_noniso_default_format_attributes = !iso;
+ flag_iso = iso;
+ flag_isoc99 = 1;
+ flag_isoc94 = 1;
+ flag_writable_strings = 0;
+}
+
+/* Set the C++ 98 standard (without GNU extensions if ISO). */
+static void
+set_std_cxx98 (iso)
+ int iso;
+{
+ cpp_set_lang (parse_in, iso ? CLK_CXX98: CLK_GNUCXX);
+ flag_no_gnu_keywords = iso;
+ flag_no_nonansi_builtin = iso;
+ flag_noniso_default_format_attributes = !iso;
+ flag_iso = iso;
+}
+
+/* Handle setting implicit to ON. */
+static void
+set_Wimplicit (on)
+ int on;
+{
+ warn_implicit = on;
+ warn_implicit_int = on;
+ if (on)
+ {
+ if (mesg_implicit_function_declaration != 2)
+ mesg_implicit_function_declaration = 1;
+ }
+ else
+ mesg_implicit_function_declaration = 0;
+}
+
+/* Args to -d specify what to dump. Silently ignore
+ unrecognized options; they may be aimed at toplev.c. */
+static void
+handle_OPT_d (arg)
+ const char *arg;
+{
+ char c;
+
+ while ((c = *arg++) != '\0')
+ switch (c)
+ {
+ case 'M':
+ cpp_opts->dump_macros = dump_only;
+ break;
+
+ case 'N':
+ cpp_opts->dump_macros = dump_names;
+ break;
+
+ case 'D':
+ cpp_opts->dump_macros = dump_definitions;
+ break;
+
+ case 'I':
+ cpp_opts->dump_includes = 1;
+ break;
+ }
+}
+
+/* Write a slash-separated list of languages in FLAGS to BUF. */
+static void
+write_langs (buf, flags)
+ char *buf;
+ int flags;
+{
+ *buf = '\0';
+ if (flags & CL_C_ONLY)
+ strcat (buf, "C");
+ if (flags & CL_OBJC_ONLY)
+ {
+ if (*buf)
+ strcat (buf, "/");
+ strcat (buf, "ObjC");
+ }
+ if (flags & CL_CXX_ONLY)
+ {
+ if (*buf)
+ strcat (buf, "/");
+ strcat (buf, "C++");
+ }
+}
+
+/* Complain that switch OPT_INDEX does not apply to this front end. */
+static void
+complain_wrong_lang (opt_index, on)
+ size_t opt_index;
+ int on;
+{
+ char ok_langs[60], bad_langs[60];
+ int ok_flags = cl_options[opt_index].flags;
+
+ write_langs (ok_langs, ok_flags);
+ write_langs (bad_langs, ~ok_flags);
+ warning ("\"-%c%s%s\" is valid for %s but not for %s",
+ cl_options[opt_index].opt_text[0], on ? "" : "no-",
+ cl_options[opt_index].opt_text + 1, ok_langs, bad_langs);
+}
+
+/* Handle --help output. */
+static void
+print_help ()
+{
+ /* To keep the lines from getting too long for some compilers, limit
+ to about 500 characters (6 lines) per chunk. */
+ fputs (_("\
+Switches:\n\
+ -include <file> Include the contents of <file> before other files\n\
+ -imacros <file> Accept definition of macros in <file>\n\
+ -iprefix <path> Specify <path> as a prefix for next two options\n\
+ -iwithprefix <dir> Add <dir> to the end of the system include path\n\
+ -iwithprefixbefore <dir> Add <dir> to the end of the main include path\n\
+ -isystem <dir> Add <dir> to the start of the system include path\n\
+"), stdout);
+ fputs (_("\
+ -idirafter <dir> Add <dir> to the end of the system include path\n\
+ -I <dir> Add <dir> to the end of the main include path\n\
+ -I- Fine-grained include path control; see info docs\n\
+ -nostdinc Do not search system include directories\n\
+ (dirs specified with -isystem will still be used)\n\
+ -nostdinc++ Do not search system include directories for C++\n\
+ -o <file> Put output into <file>\n\
+"), stdout);
+ fputs (_("\
+ -trigraphs Support ISO C trigraphs\n\
+ -std=<std name> Specify the conformance standard; one of:\n\
+ gnu89, gnu99, c89, c99, iso9899:1990,\n\
+ iso9899:199409, iso9899:1999, c++98\n\
+ -w Inhibit warning messages\n\
+ -W[no-]trigraphs Warn if trigraphs are encountered\n\
+ -W[no-]comment{s} Warn if one comment starts inside another\n\
+"), stdout);
+ fputs (_("\
+ -W[no-]traditional Warn about features not present in traditional C\n\
+ -W[no-]undef Warn if an undefined macro is used by #if\n\
+ -W[no-]import Warn about the use of the #import directive\n\
+"), stdout);
+ fputs (_("\
+ -W[no-]error Treat all warnings as errors\n\
+ -W[no-]system-headers Do not suppress warnings from system headers\n\
+ -W[no-]all Enable most preprocessor warnings\n\
+"), stdout);
+ fputs (_("\
+ -M Generate make dependencies\n\
+ -MM As -M, but ignore system header files\n\
+ -MD Generate make dependencies and compile\n\
+ -MMD As -MD, but ignore system header files\n\
+ -MF <file> Write dependency output to the given file\n\
+ -MG Treat missing header file as generated files\n\
+"), stdout);
+ fputs (_("\
+ -MP Generate phony targets for all headers\n\
+ -MQ <target> Add a MAKE-quoted target\n\
+ -MT <target> Add an unquoted target\n\
+"), stdout);
+ fputs (_("\
+ -D<macro> Define a <macro> with string '1' as its value\n\
+ -D<macro>=<val> Define a <macro> with <val> as its value\n\
+ -A<question>=<answer> Assert the <answer> to <question>\n\
+ -A-<question>=<answer> Disable the <answer> to <question>\n\
+ -U<macro> Undefine <macro> \n\
+ -v Display the version number\n\
+"), stdout);
+ fputs (_("\
+ -H Print the name of header files as they are used\n\
+ -C Do not discard comments\n\
+ -dM Display a list of macro definitions active at end\n\
+ -dD Preserve macro definitions in output\n\
+ -dN As -dD except that only the names are preserved\n\
+ -dI Include #include directives in the output\n\
+"), stdout);
+ fputs (_("\
+ -f[no-]preprocessed Treat the input file as already preprocessed\n\
+ -ftabstop=<number> Distance between tab stops for column reporting\n\
+ -P Do not generate #line directives\n\
+ -remap Remap file names when including files\n\
+ --help Display this information\n\
+"), stdout);
+}
diff --git a/contrib/gcc/c-parse.in b/contrib/gcc/c-parse.in
index 0b4bde3..59e399b 100644
--- a/contrib/gcc/c-parse.in
+++ b/contrib/gcc/c-parse.in
@@ -1,6 +1,6 @@
/* YACC parser for C syntax and for Objective C. -*-c-*-
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996,
- 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -40,14 +40,13 @@ end ifc
#include "cpplib.h"
#include "intl.h"
#include "timevar.h"
-#include "c-lex.h"
+#include "c-pragma.h" /* For YYDEBUG definition, and parse_in. */
#include "c-tree.h"
-#include "c-pragma.h"
#include "flags.h"
#include "output.h"
#include "toplev.h"
#include "ggc.h"
-
+
#ifdef MULTIBYTE_CHARS
#include <locale.h>
#endif
@@ -59,11 +58,48 @@ end ifobjc
/* Like YYERROR but do call yyerror. */
#define YYERROR1 { yyerror ("syntax error"); YYERROR; }
-/* Cause the "yydebug" variable to be defined. */
-#define YYDEBUG 1
-
-/* Rename the "yyparse" function so that we can override it elsewhere. */
-#define yyparse yyparse_1
+/* Like the default stack expander, except (1) use realloc when possible,
+ (2) impose no hard maxiumum on stack size, (3) REALLY do not use alloca.
+
+ Irritatingly, YYSTYPE is defined after this %{ %} block, so we cannot
+ give malloced_yyvs its proper type. This is ok since all we need from
+ it is to be able to free it. */
+
+static short *malloced_yyss;
+static void *malloced_yyvs;
+
+#define yyoverflow(MSG, SS, SSSIZE, VS, VSSIZE, YYSSZ) \
+do { \
+ size_t newsize; \
+ short *newss; \
+ YYSTYPE *newvs; \
+ newsize = *(YYSSZ) *= 2; \
+ if (malloced_yyss) \
+ { \
+ newss = (short *) \
+ really_call_realloc (*(SS), newsize * sizeof (short)); \
+ newvs = (YYSTYPE *) \
+ really_call_realloc (*(VS), newsize * sizeof (YYSTYPE)); \
+ } \
+ else \
+ { \
+ newss = (short *) really_call_malloc (newsize * sizeof (short)); \
+ newvs = (YYSTYPE *) really_call_malloc (newsize * sizeof (YYSTYPE)); \
+ if (newss) \
+ memcpy (newss, *(SS), (SSSIZE)); \
+ if (newvs) \
+ memcpy (newvs, *(VS), (VSSIZE)); \
+ } \
+ if (!newss || !newvs) \
+ { \
+ yyerror (MSG); \
+ return 2; \
+ } \
+ *(SS) = newss; \
+ *(VS) = newvs; \
+ malloced_yyss = newss; \
+ malloced_yyvs = (void *) newvs; \
+} while (0)
%}
%start program
@@ -82,7 +118,8 @@ end ifobjc
/* Reserved words that specify storage class.
yylval contains an IDENTIFIER_NODE which indicates which one. */
-%token SCSPEC
+%token SCSPEC /* Storage class other than static. */
+%token STATIC /* Static storage class. */
/* Reserved words that specify type.
yylval contains an IDENTIFIER_NODE which indicates which one. */
@@ -148,7 +185,7 @@ end ifobjc
%type <ttype> BREAK CONTINUE RETURN GOTO ASM_KEYWORD SIZEOF TYPEOF ALIGNOF
%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist
-%type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
+%type <ttype> expr_no_commas cast_expr unary_expr primary STRING
%type <ttype> declspecs_nosc_nots_nosa_noea declspecs_nosc_nots_nosa_ea
%type <ttype> declspecs_nosc_nots_sa_noea declspecs_nosc_nots_sa_ea
%type <ttype> declspecs_nosc_ts_nosa_noea declspecs_nosc_ts_nosa_ea
@@ -164,7 +201,7 @@ end ifobjc
%type <ttype> typespec_reserved_nonattr typespec_reserved_attr
%type <ttype> typespec_nonreserved_nonattr
-%type <ttype> SCSPEC TYPESPEC TYPE_QUAL maybe_type_qual
+%type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_type_qual
%type <ttype> initdecls notype_initdecls initdcl notype_initdcl
%type <ttype> init maybeasm
%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
@@ -215,28 +252,28 @@ ifobjc
end ifobjc
%{
-/* Number of statements (loosely speaking) and compound statements
+/* Number of statements (loosely speaking) and compound statements
seen so far. */
static int stmt_count;
static int compstmt_count;
-
+
/* Input file and line number of the end of the body of last simple_if;
used by the stmt-rule immediately after simple_if returns. */
static const char *if_stmt_file;
static int if_stmt_line;
/* List of types and structure classes of the current declaration. */
-static tree current_declspecs = NULL_TREE;
-static tree prefix_attributes = NULL_TREE;
+static GTY(()) tree current_declspecs;
+static GTY(()) tree prefix_attributes;
/* List of all the attributes applying to the identifier currently being
declared; includes prefix_attributes and possibly some more attributes
just after a comma. */
-static tree all_prefix_attributes = NULL_TREE;
+static GTY(()) tree all_prefix_attributes;
/* Stack of saved values of current_declspecs, prefix_attributes and
all_prefix_attributes. */
-static tree declspec_stack;
+static GTY(()) tree declspec_stack;
/* PUSH_DECLSPEC_STACK is called from setspecs; POP_DECLSPEC_STACK
should be called from the productions making use of setspecs. */
@@ -258,17 +295,19 @@ static tree declspec_stack;
/* For __extension__, save/restore the warning flags which are
controlled by __extension__. */
-#define SAVE_WARN_FLAGS() \
+#define SAVE_EXT_FLAGS() \
size_int (pedantic \
| (warn_pointer_arith << 1) \
- | (warn_traditional << 2))
+ | (warn_traditional << 2) \
+ | (flag_iso << 3))
-#define RESTORE_WARN_FLAGS(tval) \
+#define RESTORE_EXT_FLAGS(tval) \
do { \
int val = tree_low_cst (tval, 0); \
pedantic = val & 1; \
warn_pointer_arith = (val >> 1) & 1; \
warn_traditional = (val >> 2) & 1; \
+ flag_iso = (val >> 3) & 1; \
} while (0)
ifobjc
@@ -278,8 +317,8 @@ static enum tree_code objc_inherit_code;
static int objc_pq_context = 0, objc_public_flag = 0;
/* The following flag is needed to contextualize ObjC lexical analysis.
- In some cases (e.g., 'int NSObject;'), it is undesirable to bind
- an identifier to an ObjC class, even if a class with that name
+ In some cases (e.g., 'int NSObject;'), it is undesirable to bind
+ an identifier to an ObjC class, even if a class with that name
exists. */
static int objc_need_raw_identifier;
#define OBJC_NEED_RAW_IDENTIFIER(VAL) objc_need_raw_identifier = VAL
@@ -289,6 +328,8 @@ ifc
#define OBJC_NEED_RAW_IDENTIFIER(VAL) /* nothing */
end ifc
+static bool parsing_iso_function_signature;
+
/* Tell yyparse how to print a token's value, if yydebug is set. */
#define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
@@ -296,20 +337,16 @@ end ifc
static void yyprint PARAMS ((FILE *, int, YYSTYPE));
static void yyerror PARAMS ((const char *));
static int yylexname PARAMS ((void));
+static int yylexstring PARAMS ((void));
static inline int _yylex PARAMS ((void));
static int yylex PARAMS ((void));
static void init_reswords PARAMS ((void));
-/* Add GC roots for variables local to this file. */
+ /* Initialisation routine for this file. */
void
c_parse_init ()
{
init_reswords ();
-
- ggc_add_tree_root (&declspec_stack, 1);
- ggc_add_tree_root (&current_declspecs, 1);
- ggc_add_tree_root (&prefix_attributes, 1);
- ggc_add_tree_root (&all_prefix_attributes, 1);
}
%}
@@ -326,9 +363,10 @@ program: /* empty */
get us back to the global binding level. */
while (! global_bindings_p ())
poplevel (0, 0, 0);
-ifc
+ /* __FUNCTION__ is defined at file scope (""). This
+ call may not be necessary as my tests indicate it
+ still works without it. */
finish_fname_decls ();
-end ifc
finish_file ();
}
;
@@ -343,6 +381,11 @@ extdefs:
;
extdef:
+ extdef_1
+ { parsing_iso_function_signature = false; } /* Reset after any external definition. */
+ ;
+
+extdef_1:
fndef
| datadef
ifobjc
@@ -357,15 +400,15 @@ end ifobjc
else
error ("argument of `asm' is not a constant string"); }
| extension extdef
- { RESTORE_WARN_FLAGS ($1); }
+ { RESTORE_EXT_FLAGS ($1); }
;
datadef:
setspecs notype_initdecls ';'
{ if (pedantic)
error ("ISO C forbids data definition with no type or storage class");
- else if (!flag_traditional)
- warning ("data definition has no type or storage class");
+ else
+ warning ("data definition has no type or storage class");
POP_DECLSPEC_STACK; }
| declspecs_nots setspecs notype_initdecls ';'
@@ -392,7 +435,7 @@ fndef:
save_filename save_lineno compstmt_or_error
{ DECL_SOURCE_FILE (current_function_decl) = $7;
DECL_SOURCE_LINE (current_function_decl) = $8;
- finish_function (0, 1);
+ finish_function (0, 1);
POP_DECLSPEC_STACK; }
| declspecs_ts setspecs declarator error
{ POP_DECLSPEC_STACK; }
@@ -406,7 +449,7 @@ fndef:
save_filename save_lineno compstmt_or_error
{ DECL_SOURCE_FILE (current_function_decl) = $7;
DECL_SOURCE_LINE (current_function_decl) = $8;
- finish_function (0, 1);
+ finish_function (0, 1);
POP_DECLSPEC_STACK; }
| declspecs_nots setspecs notype_declarator error
{ POP_DECLSPEC_STACK; }
@@ -420,7 +463,7 @@ fndef:
save_filename save_lineno compstmt_or_error
{ DECL_SOURCE_FILE (current_function_decl) = $6;
DECL_SOURCE_LINE (current_function_decl) = $7;
- finish_function (0, 1);
+ finish_function (0, 1);
POP_DECLSPEC_STACK; }
| setspecs notype_declarator error
{ POP_DECLSPEC_STACK; }
@@ -480,28 +523,13 @@ unary_expr:
/* __extension__ turns off -pedantic for following primary. */
| extension cast_expr %prec UNARY
{ $$ = $2;
- RESTORE_WARN_FLAGS ($1); }
+ RESTORE_EXT_FLAGS ($1); }
| unop cast_expr %prec UNARY
{ $$ = build_unary_op ($1, $2, 0);
overflow_warning ($$); }
/* Refer to the address of a label as a pointer. */
| ANDAND identifier
{ $$ = finish_label_address_expr ($2); }
-/* This seems to be impossible on some machines, so let's turn it off.
- You can use __builtin_next_arg to find the anonymous stack args.
- | '&' ELLIPSIS
- { tree types = TYPE_ARG_TYPES (TREE_TYPE (current_function_decl));
- $$ = error_mark_node;
- if (TREE_VALUE (tree_last (types)) == void_type_node)
- error ("`&...' used in function with fixed number of arguments");
- else
- {
- if (pedantic)
- pedwarn ("ISO C forbids `&...'");
- $$ = tree_last (DECL_ARGUMENTS (current_function_decl));
- $$ = build_unary_op (ADDR_EXPR, $$, 0);
- } }
-*/
| sizeof unary_expr %prec UNARY
{ skip_evaluation--;
if (TREE_CODE ($2) == COMPONENT_REF
@@ -568,19 +596,22 @@ expr_no_commas:
| expr_no_commas '^' expr_no_commas
{ $$ = parser_build_binary_op ($2, $1, $3); }
| expr_no_commas ANDAND
- { $1 = truthvalue_conversion (default_conversion ($1));
+ { $1 = c_common_truthvalue_conversion
+ (default_conversion ($1));
skip_evaluation += $1 == boolean_false_node; }
expr_no_commas
{ skip_evaluation -= $1 == boolean_false_node;
$$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); }
| expr_no_commas OROR
- { $1 = truthvalue_conversion (default_conversion ($1));
+ { $1 = c_common_truthvalue_conversion
+ (default_conversion ($1));
skip_evaluation += $1 == boolean_true_node; }
expr_no_commas
{ skip_evaluation -= $1 == boolean_true_node;
$$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); }
| expr_no_commas '?'
- { $1 = truthvalue_conversion (default_conversion ($1));
+ { $1 = c_common_truthvalue_conversion
+ (default_conversion ($1));
skip_evaluation += $1 == boolean_false_node; }
expr ':'
{ skip_evaluation += (($1 == boolean_true_node)
@@ -593,7 +624,8 @@ expr_no_commas:
pedwarn ("ISO C forbids omitting the middle term of a ?: expression");
/* Make sure first operand is calculated only once. */
$<ttype>2 = save_expr ($1);
- $1 = truthvalue_conversion (default_conversion ($<ttype>2));
+ $1 = c_common_truthvalue_conversion
+ (default_conversion ($<ttype>2));
skip_evaluation += $1 == boolean_true_node; }
':' expr_no_commas
{ skip_evaluation -= $1 == boolean_true_node;
@@ -608,7 +640,8 @@ expr_no_commas:
| expr_no_commas ASSIGN expr_no_commas
{ char class;
$$ = build_modify_expr ($1, $2, $3);
- /* This inhibits warnings in truthvalue_conversion. */
+ /* This inhibits warnings in
+ c_common_truthvalue_conversion. */
class = TREE_CODE_CLASS (TREE_CODE ($$));
if (IS_EXPR_CODE_CLASS (class))
C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK);
@@ -623,11 +656,11 @@ primary:
$$ = build_external_ref ($1, yychar == '(');
}
| CONSTANT
- | string
- { $$ = combine_strings ($1); }
+ | STRING
+ { $$ = fix_string_type ($$); }
| VAR_FUNC_NAME
{ $$ = fname_decl (C_RID_CODE ($$), $$); }
- | '(' typename ')' '{'
+ | '(' typename ')' '{'
{ start_init (NULL_TREE, NULL, 0);
$2 = groktypename ($2);
really_start_incremental_init ($2); }
@@ -735,29 +768,6 @@ ifobjc
end ifobjc
;
-/* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */
-string:
- STRING
- | string STRING
- {
-ifc
- static int last_lineno = 0;
- static const char *last_input_filename = 0;
-end ifc
- $$ = chainon ($1, $2);
-ifc
- if (warn_traditional && !in_system_header
- && (lineno != last_lineno || !last_input_filename ||
- strcmp (last_input_filename, input_filename)))
- {
- warning ("traditional C rejects string concatenation");
- last_lineno = lineno;
- last_input_filename = input_filename;
- }
-end ifc
- }
- ;
-
ifobjc
/* Produces an STRING_CST with perhaps more STRING_CSTs chained
onto it, which is to be read as an ObjC string object. */
@@ -770,13 +780,21 @@ objc_string:
end ifobjc
old_style_parm_decls:
+ old_style_parm_decls_1
+ {
+ parsing_iso_function_signature = false; /* Reset after decls. */
+ }
+ ;
+
+old_style_parm_decls_1:
/* empty */
+ {
+ if (warn_traditional && !in_system_header
+ && parsing_iso_function_signature)
+ warning ("traditional C rejects ISO C style function definitions");
+ parsing_iso_function_signature = false; /* Reset after warning. */
+ }
| datadecls
- | datadecls ELLIPSIS
- /* ... is used here to indicate a varargs function. */
- { c_mark_varargs ();
- if (pedantic)
- pedwarn ("ISO C does not permit use of `varargs.h'"); }
;
/* The following are analogous to lineno_decl, decls and decl
@@ -850,12 +868,12 @@ decl:
| declspecs ';'
{ shadow_tag ($1); }
| extension decl
- { RESTORE_WARN_FLAGS ($1); }
+ { RESTORE_EXT_FLAGS ($1); }
;
/* A list of declaration specifiers. These are:
- - Storage class specifiers (SCSPEC), which for GCC currently include
+ - Storage class specifiers (scspec), which for GCC currently includes
function specifiers ("inline").
- Type specifiers (typespec_*).
@@ -1026,7 +1044,7 @@ declspecs_nosc_ts_sa_ea:
;
declspecs_sc_nots_nosa_noea:
- SCSPEC
+ scspec
{ $$ = tree_cons (NULL_TREE, $1, NULL_TREE);
TREE_STATIC ($$) = 0; }
| declspecs_sc_nots_nosa_noea TYPE_QUAL
@@ -1035,25 +1053,25 @@ declspecs_sc_nots_nosa_noea:
| declspecs_sc_nots_nosa_ea TYPE_QUAL
{ $$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = 1; }
- | declspecs_nosc_nots_nosa_noea SCSPEC
+ | declspecs_nosc_nots_nosa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_nosc_nots_nosa_ea SCSPEC
+ | declspecs_nosc_nots_nosa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_nots_nosa_noea SCSPEC
+ | declspecs_sc_nots_nosa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_nots_nosa_ea SCSPEC
+ | declspecs_sc_nots_nosa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
@@ -1074,25 +1092,25 @@ declspecs_sc_nots_sa_noea:
| declspecs_sc_nots_sa_ea TYPE_QUAL
{ $$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = 1; }
- | declspecs_nosc_nots_sa_noea SCSPEC
+ | declspecs_nosc_nots_sa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_nosc_nots_sa_ea SCSPEC
+ | declspecs_nosc_nots_sa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_nots_sa_noea SCSPEC
+ | declspecs_sc_nots_sa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_nots_sa_ea SCSPEC
+ | declspecs_sc_nots_sa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
@@ -1125,25 +1143,25 @@ declspecs_sc_ts_nosa_noea:
| declspecs_sc_nots_nosa_ea typespec_nonattr
{ $$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = 1; }
- | declspecs_nosc_ts_nosa_noea SCSPEC
+ | declspecs_nosc_ts_nosa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_nosc_ts_nosa_ea SCSPEC
+ | declspecs_nosc_ts_nosa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_ts_nosa_noea SCSPEC
+ | declspecs_sc_ts_nosa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_ts_nosa_ea SCSPEC
+ | declspecs_sc_ts_nosa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
@@ -1188,25 +1206,25 @@ declspecs_sc_ts_sa_noea:
| declspecs_sc_nots_sa_ea typespec_nonattr
{ $$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = 1; }
- | declspecs_nosc_ts_sa_noea SCSPEC
+ | declspecs_nosc_ts_sa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_nosc_ts_sa_ea SCSPEC
+ | declspecs_nosc_ts_sa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_ts_sa_noea SCSPEC
+ | declspecs_sc_ts_sa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_ts_sa_ea SCSPEC
+ | declspecs_sc_ts_sa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
@@ -1398,10 +1416,8 @@ notype_initdecls:
maybeasm:
/* empty */
{ $$ = NULL_TREE; }
- | ASM_KEYWORD '(' string ')'
- { if (TREE_CHAIN ($3)) $3 = combine_strings ($3);
- $$ = $3;
- }
+ | ASM_KEYWORD '(' STRING ')'
+ { $$ = $3; }
;
initdcl:
@@ -1416,7 +1432,7 @@ initdcl:
| declarator maybeasm maybe_attribute
{ tree d = start_decl ($1, current_declspecs, 0,
chainon ($3, all_prefix_attributes));
- finish_decl (d, NULL_TREE, $2);
+ finish_decl (d, NULL_TREE, $2);
}
;
@@ -1442,7 +1458,7 @@ maybe_attribute:
| attributes
{ $$ = $1; }
;
-
+
attributes:
attribute
{ $$ = $1; }
@@ -1461,7 +1477,7 @@ attribute_list:
| attribute_list ',' attrib
{ $$ = chainon ($1, $3); }
;
-
+
attrib:
/* empty */
{ $$ = NULL_TREE; }
@@ -1480,10 +1496,15 @@ attrib:
any_word:
identifier
- | SCSPEC
+ | scspec
| TYPESPEC
| TYPE_QUAL
;
+
+scspec:
+ STATIC
+ | SCSPEC
+ ;
/* Initializers. `init' is the entry point. */
@@ -1546,17 +1567,12 @@ designator_list:
designator:
'.' identifier
{ set_init_label ($2); }
- /* These are for labeled elements. The syntax for an array element
- initializer conflicts with the syntax for an Objective-C message,
- so don't include these productions in the Objective-C grammar. */
-ifc
| '[' expr_no_commas ELLIPSIS expr_no_commas ']'
{ set_init_index ($2, $4);
if (pedantic)
pedwarn ("ISO C forbids specifying range of elements to initialize"); }
| '[' expr_no_commas ']'
{ set_init_index ($2, NULL_TREE); }
-end ifc
;
nested_function:
@@ -1571,6 +1587,7 @@ nested_function:
pop_function_context ();
YYERROR1;
}
+ parsing_iso_function_signature = false; /* Don't warn about nested functions. */
}
old_style_parm_decls
{ store_parm_decls (); }
@@ -1585,7 +1602,7 @@ nested_function:
DECL_SOURCE_FILE (decl) = $5;
DECL_SOURCE_LINE (decl) = $6;
finish_function (1, 1);
- pop_function_context ();
+ pop_function_context ();
add_decl_stmt (decl); }
;
@@ -1601,6 +1618,7 @@ notype_nested_function:
pop_function_context ();
YYERROR1;
}
+ parsing_iso_function_signature = false; /* Don't warn about nested functions. */
}
old_style_parm_decls
{ store_parm_decls (); }
@@ -1615,7 +1633,7 @@ notype_nested_function:
DECL_SOURCE_FILE (decl) = $5;
DECL_SOURCE_LINE (decl) = $6;
finish_function (1, 1);
- pop_function_context ();
+ pop_function_context ();
add_decl_stmt (decl); }
;
@@ -1736,7 +1754,7 @@ structsp_attr:
{ $$ = start_struct (RECORD_TYPE, $2);
/* Start scope of tag before parsing components. */
}
- component_decl_list '}' maybe_attribute
+ component_decl_list '}' maybe_attribute
{ $$ = finish_struct ($<ttype>4, $5, chainon ($1, $7)); }
| struct_head '{' component_decl_list '}' maybe_attribute
{ $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE),
@@ -1826,8 +1844,8 @@ component_decl:
POP_DECLSPEC_STACK; }
| declspecs_nosc_ts setspecs save_filename save_lineno
{
- /* Support for unnamed structs or unions as members of
- structs or unions (which is [a] useful and [b] supports
+ /* Support for unnamed structs or unions as members of
+ structs or unions (which is [a] useful and [b] supports
MS P-SDK). */
if (pedantic)
pedwarn ("ISO C doesn't support unnamed structs/unions");
@@ -1846,7 +1864,7 @@ component_decl:
{ $$ = NULL_TREE; }
| extension component_decl
{ $$ = $2;
- RESTORE_WARN_FLAGS ($1); }
+ RESTORE_EXT_FLAGS ($1); }
;
components:
@@ -1974,30 +1992,17 @@ direct_absdcl1:
/* The [...] part of a declarator for an array type. */
array_declarator:
- '[' expr ']'
- { $$ = build_array_declarator ($2, NULL_TREE, 0, 0); }
- | '[' declspecs_nosc expr ']'
+ '[' maybe_type_quals_attrs expr ']'
{ $$ = build_array_declarator ($3, $2, 0, 0); }
- | '[' ']'
- { $$ = build_array_declarator (NULL_TREE, NULL_TREE, 0, 0); }
- | '[' declspecs_nosc ']'
+ | '[' maybe_type_quals_attrs ']'
{ $$ = build_array_declarator (NULL_TREE, $2, 0, 0); }
- | '[' '*' ']'
- { $$ = build_array_declarator (NULL_TREE, NULL_TREE, 0, 1); }
- | '[' declspecs_nosc '*' ']'
+ | '[' maybe_type_quals_attrs '*' ']'
{ $$ = build_array_declarator (NULL_TREE, $2, 0, 1); }
- | '[' SCSPEC expr ']'
- { if (C_RID_CODE ($2) != RID_STATIC)
- error ("storage class specifier in array declarator");
- $$ = build_array_declarator ($3, NULL_TREE, 1, 0); }
- | '[' SCSPEC declspecs_nosc expr ']'
- { if (C_RID_CODE ($2) != RID_STATIC)
- error ("storage class specifier in array declarator");
- $$ = build_array_declarator ($4, $3, 1, 0); }
- | '[' declspecs_nosc SCSPEC expr ']'
- { if (C_RID_CODE ($3) != RID_STATIC)
- error ("storage class specifier in array declarator");
- $$ = build_array_declarator ($4, $2, 1, 0); }
+ | '[' STATIC maybe_type_quals_attrs expr ']'
+ { $$ = build_array_declarator ($4, $3, 1, 0); }
+ /* declspecs_nosc_nots is a synonym for type_quals_attrs. */
+ | '[' declspecs_nosc_nots STATIC expr ']'
+ { $$ = build_array_declarator ($4, $2, 1, 0); }
;
/* A nonempty series of declarations and statements (possibly followed by
@@ -2096,8 +2101,8 @@ c99_block_end: /* empty */
{ if (flag_isoc99)
{
tree scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
- $$ = poplevel (kept_level_p (), 0, 0);
- SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
+ $$ = poplevel (kept_level_p (), 0, 0);
+ SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
= SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
= $$;
}
@@ -2146,8 +2151,8 @@ compstmt_start: '{' { compstmt_count++;
compstmt_nostart: '}'
{ $$ = convert (void_type_node, integer_zero_node); }
| pushlevel maybe_label_decls compstmt_contents_nonempty '}' poplevel
- { $$ = poplevel (kept_level_p (), 1, 0);
- SCOPE_STMT_BLOCK (TREE_PURPOSE ($5))
+ { $$ = poplevel (kept_level_p (), 1, 0);
+ SCOPE_STMT_BLOCK (TREE_PURPOSE ($5))
= SCOPE_STMT_BLOCK (TREE_VALUE ($5))
= $$; }
;
@@ -2176,7 +2181,7 @@ compstmt_primary_start:
;
compstmt: compstmt_start compstmt_nostart
- { RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
+ { RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
last_expr_type = NULL_TREE;
$$ = $1; }
;
@@ -2203,7 +2208,7 @@ if_prefix:
IF
{ $<ttype>$ = c_begin_if_stmt (); }
'(' expr ')'
- { c_expand_start_cond (truthvalue_conversion ($4),
+ { c_expand_start_cond (c_common_truthvalue_conversion ($4),
compstmt_count,$<ttype>2);
$<itype>$ = stmt_count;
if_stmt_file = $<filename>-2;
@@ -2217,7 +2222,7 @@ do_stmt_start:
DO
{ stmt_count++;
compstmt_count++;
- $<ttype>$
+ $<ttype>$
= add_stmt (build_stmt (DO_STMT, NULL_TREE,
NULL_TREE));
/* In the event that a parse error prevents
@@ -2312,30 +2317,31 @@ select_or_iter_stmt:
we later pass to c_finish_while_stmt_cond to fill
in the condition and other tidbits. */
| WHILE
- { stmt_count++;
+ { stmt_count++;
$<ttype>$ = c_begin_while_stmt (); }
'(' expr ')'
- { $4 = truthvalue_conversion ($4);
- c_finish_while_stmt_cond (truthvalue_conversion ($4),
- $<ttype>2);
+ { $4 = c_common_truthvalue_conversion ($4);
+ c_finish_while_stmt_cond
+ (c_common_truthvalue_conversion ($4), $<ttype>2);
$<ttype>$ = add_stmt ($<ttype>2); }
c99_block_lineno_labeled_stmt
{ RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
| do_stmt_start
'(' expr ')' ';'
- { DO_COND ($1) = truthvalue_conversion ($3); }
+ { DO_COND ($1) = c_common_truthvalue_conversion ($3); }
| do_stmt_start error
{ }
| FOR
{ $<ttype>$ = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
- add_stmt ($<ttype>$); }
+ add_stmt ($<ttype>$); }
'(' for_init_stmt
{ stmt_count++;
RECHAIN_STMTS ($<ttype>2, FOR_INIT_STMT ($<ttype>2)); }
xexpr ';'
- { if ($6)
- FOR_COND ($<ttype>2) = truthvalue_conversion ($6); }
+ { if ($6)
+ FOR_COND ($<ttype>2)
+ = c_common_truthvalue_conversion ($6); }
xexpr ')'
{ FOR_EXPR ($<ttype>2) = $9; }
c99_block_lineno_labeled_stmt
@@ -2349,7 +2355,7 @@ select_or_iter_stmt:
for_init_stmt:
xexpr ';'
- { add_stmt (build_stmt (EXPR_STMT, $1)); }
+ { add_stmt (build_stmt (EXPR_STMT, $1)); }
| decl
{ check_for_loop_decls (); }
;
@@ -2475,14 +2481,16 @@ asm_operand:
STRING '(' expr ')'
{ $$ = build_tree_list (build_tree_list (NULL_TREE, $1), $3); }
| '[' identifier ']' STRING '(' expr ')'
- { $$ = build_tree_list (build_tree_list ($2, $4), $6); }
+ { $2 = build_string (IDENTIFIER_LENGTH ($2),
+ IDENTIFIER_POINTER ($2));
+ $$ = build_tree_list (build_tree_list ($2, $4), $6); }
;
asm_clobbers:
- string
- { $$ = tree_cons (NULL_TREE, combine_strings ($1), NULL_TREE); }
- | asm_clobbers ',' string
- { $$ = tree_cons (NULL_TREE, combine_strings ($3), $1); }
+ STRING
+ { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
+ | asm_clobbers ',' STRING
+ { $$ = tree_cons (NULL_TREE, $3, $1); }
;
/* This is what appears inside the parens in a function declarator.
@@ -2535,7 +2543,9 @@ parmlist_2: /* empty */
error ("ISO C requires a named argument before `...'");
}
| parms
- { $$ = get_parm_info (1); }
+ { $$ = get_parm_info (1);
+ parsing_iso_function_signature = true;
+ }
| parms ',' ELLIPSIS
{ $$ = get_parm_info (0); }
;
@@ -2558,7 +2568,7 @@ parm:
| declspecs_ts setspecs notype_declarator maybe_attribute
{ $$ = build_tree_list (build_tree_list (current_declspecs,
$3),
- chainon ($4, all_prefix_attributes));
+ chainon ($4, all_prefix_attributes));
POP_DECLSPEC_STACK; }
| declspecs_ts setspecs absdcl_maybe_attribute
{ $$ = $3;
@@ -2585,7 +2595,7 @@ firstparm:
| declspecs_ts_nosa setspecs_fp notype_declarator maybe_attribute
{ $$ = build_tree_list (build_tree_list (current_declspecs,
$3),
- chainon ($4, all_prefix_attributes));
+ chainon ($4, all_prefix_attributes));
POP_DECLSPEC_STACK; }
| declspecs_ts_nosa setspecs_fp absdcl_maybe_attribute
{ $$ = $3;
@@ -2657,10 +2667,11 @@ identifiers_or_typenames:
extension:
EXTENSION
- { $$ = SAVE_WARN_FLAGS();
+ { $$ = SAVE_EXT_FLAGS();
pedantic = 0;
warn_pointer_arith = 0;
- warn_traditional = 0; }
+ warn_traditional = 0;
+ flag_iso = 0; }
;
ifobjc
@@ -3212,14 +3223,8 @@ receiver:
;
objcmessageexpr:
- '['
- { objc_receiver_context = 1; }
- receiver
- { objc_receiver_context = 0; }
- messageargs ']'
- {
- $$ = build_tree_list ($3, $5);
- }
+ '[' receiver messageargs ']'
+ { $$ = build_tree_list ($2, $3); }
;
selectorarg:
@@ -3287,11 +3292,10 @@ struct resword
/* Disable mask. Keywords are disabled if (reswords[i].disable & mask) is
_true_. */
-#define D_TRAD 0x01 /* not in traditional C */
-#define D_C89 0x02 /* not in C89 */
-#define D_EXT 0x04 /* GCC extension */
-#define D_EXT89 0x08 /* GCC extension incorporated in C99 */
-#define D_OBJC 0x10 /* Objective C only */
+#define D_C89 0x01 /* not in C89 */
+#define D_EXT 0x02 /* GCC extension */
+#define D_EXT89 0x04 /* GCC extension incorporated in C99 */
+#define D_OBJC 0x08 /* Objective C only */
static const struct resword reswords[] =
{
@@ -3333,6 +3337,7 @@ static const struct resword reswords[] =
{ "__restrict__", RID_RESTRICT, 0 },
{ "__signed", RID_SIGNED, 0 },
{ "__signed__", RID_SIGNED, 0 },
+ { "__thread", RID_THREAD, 0 },
{ "__typeof", RID_TYPEOF, 0 },
{ "__typeof__", RID_TYPEOF, 0 },
{ "__unbounded", RID_UNBOUNDED, 0 },
@@ -3344,7 +3349,7 @@ static const struct resword reswords[] =
{ "break", RID_BREAK, 0 },
{ "case", RID_CASE, 0 },
{ "char", RID_CHAR, 0 },
- { "const", RID_CONST, D_TRAD },
+ { "const", RID_CONST, 0 },
{ "continue", RID_CONTINUE, 0 },
{ "default", RID_DEFAULT, 0 },
{ "do", RID_DO, 0 },
@@ -3356,24 +3361,24 @@ static const struct resword reswords[] =
{ "for", RID_FOR, 0 },
{ "goto", RID_GOTO, 0 },
{ "if", RID_IF, 0 },
- { "inline", RID_INLINE, D_TRAD|D_EXT89 },
+ { "inline", RID_INLINE, D_EXT89 },
{ "int", RID_INT, 0 },
{ "long", RID_LONG, 0 },
{ "register", RID_REGISTER, 0 },
- { "restrict", RID_RESTRICT, D_TRAD|D_C89 },
+ { "restrict", RID_RESTRICT, D_C89 },
{ "return", RID_RETURN, 0 },
{ "short", RID_SHORT, 0 },
- { "signed", RID_SIGNED, D_TRAD },
+ { "signed", RID_SIGNED, 0 },
{ "sizeof", RID_SIZEOF, 0 },
{ "static", RID_STATIC, 0 },
{ "struct", RID_STRUCT, 0 },
{ "switch", RID_SWITCH, 0 },
{ "typedef", RID_TYPEDEF, 0 },
- { "typeof", RID_TYPEOF, D_TRAD|D_EXT },
+ { "typeof", RID_TYPEOF, D_EXT },
{ "union", RID_UNION, 0 },
{ "unsigned", RID_UNSIGNED, 0 },
{ "void", RID_VOID, 0 },
- { "volatile", RID_VOLATILE, D_TRAD },
+ { "volatile", RID_VOLATILE, 0 },
{ "while", RID_WHILE, 0 },
ifobjc
{ "id", RID_ID, D_OBJC },
@@ -3410,7 +3415,7 @@ end ifobjc
three languages. */
static const short rid_to_yy[RID_MAX] =
{
- /* RID_STATIC */ SCSPEC,
+ /* RID_STATIC */ STATIC,
/* RID_UNSIGNED */ TYPESPEC,
/* RID_LONG */ TYPESPEC,
/* RID_CONST */ TYPE_QUAL,
@@ -3428,6 +3433,7 @@ static const short rid_to_yy[RID_MAX] =
/* RID_BOUNDED */ TYPE_QUAL,
/* RID_UNBOUNDED */ TYPE_QUAL,
/* RID_COMPLEX */ TYPESPEC,
+ /* RID_THREAD */ SCSPEC,
/* C++ */
/* RID_FRIEND */ 0,
@@ -3443,7 +3449,7 @@ static const short rid_to_yy[RID_MAX] =
/* RID_BYCOPY */ TYPE_QUAL,
/* RID_BYREF */ TYPE_QUAL,
/* RID_ONEWAY */ TYPE_QUAL,
-
+
/* C */
/* RID_INT */ TYPESPEC,
/* RID_CHAR */ TYPESPEC,
@@ -3517,19 +3523,6 @@ static const short rid_to_yy[RID_MAX] =
/* RID_REINTCAST */ 0,
/* RID_STATCAST */ 0,
- /* alternate spellings */
- /* RID_AND */ 0,
- /* RID_AND_EQ */ 0,
- /* RID_NOT */ 0,
- /* RID_NOT_EQ */ 0,
- /* RID_OR */ 0,
- /* RID_OR_EQ */ 0,
- /* RID_XOR */ 0,
- /* RID_XOR_EQ */ 0,
- /* RID_BITAND */ 0,
- /* RID_BITOR */ 0,
- /* RID_COMPL */ 0,
-
/* Objective C */
/* RID_ID */ OBJECTNAME,
/* RID_AT_ENCODE */ ENCODE,
@@ -3552,10 +3545,9 @@ init_reswords ()
unsigned int i;
tree id;
int mask = (flag_isoc99 ? 0 : D_C89)
- | (flag_traditional ? D_TRAD : 0)
| (flag_no_asm ? (flag_isoc99 ? D_EXT : D_EXT|D_EXT89) : 0);
- if (c_language != clk_objective_c)
+ if (!flag_objc)
mask |= D_OBJC;
/* It is not necessary to register ridpointers as a GC root, because
@@ -3610,12 +3602,12 @@ static int
yylexname ()
{
tree decl;
-
+
ifobjc
int objc_force_identifier = objc_need_raw_identifier;
OBJC_NEED_RAW_IDENTIFIER (0);
end ifobjc
-
+
if (C_IS_RESERVED_WORD (yylval.ttype))
{
enum rid rid_code = C_RID_CODE (yylval.ttype);
@@ -3640,13 +3632,13 @@ end ifobjc
/* __FUNCTION__ and __PRETTY_FUNCTION__ get converted
to string constants. */
const char *name = fname_string (rid_code);
-
+
yylval.ttype = build_string (strlen (name) + 1, name);
C_ARTIFICIAL_STRING_P (yylval.ttype) = 1;
last_token = CPP_STRING; /* so yyerror won't choke */
return STRING;
}
-
+
/* Return the canonical spelling for this keyword. */
yylval.ttype = ridpointers[(int) rid_code];
return yycode;
@@ -3665,8 +3657,8 @@ ifobjc
tree objc_interface_decl = is_class_name (yylval.ttype);
/* ObjC class names are in the same namespace as variables and
typedefs, and hence are shadowed by local declarations. */
- if (objc_interface_decl
- && (global_bindings_p ()
+ if (objc_interface_decl
+ && (global_bindings_p ()
|| (!objc_force_identifier && !decl)))
{
yylval.ttype = objc_interface_decl;
@@ -3678,6 +3670,57 @@ end ifobjc
return IDENTIFIER;
}
+/* Concatenate strings before returning them to the parser. This isn't quite
+ as good as having it done in the lexer, but it's better than nothing. */
+
+static int
+yylexstring ()
+{
+ enum cpp_ttype next_type;
+ tree orig = yylval.ttype;
+
+ next_type = c_lex (&yylval.ttype);
+ if (next_type == CPP_STRING
+ || next_type == CPP_WSTRING
+ || (next_type == CPP_NAME && yylexname () == STRING))
+ {
+ varray_type strings;
+
+ifc
+ static int last_lineno = 0;
+ static const char *last_input_filename = 0;
+ if (warn_traditional && !in_system_header
+ && (lineno != last_lineno || !last_input_filename ||
+ strcmp (last_input_filename, input_filename)))
+ {
+ warning ("traditional C rejects string concatenation");
+ last_lineno = lineno;
+ last_input_filename = input_filename;
+ }
+end ifc
+
+ VARRAY_TREE_INIT (strings, 32, "strings");
+ VARRAY_PUSH_TREE (strings, orig);
+
+ do
+ {
+ VARRAY_PUSH_TREE (strings, yylval.ttype);
+ next_type = c_lex (&yylval.ttype);
+ }
+ while (next_type == CPP_STRING
+ || next_type == CPP_WSTRING
+ || (next_type == CPP_NAME && yylexname () == STRING));
+
+ yylval.ttype = combine_strings (strings);
+ }
+ else
+ yylval.ttype = orig;
+
+ /* We will have always read one token too many. */
+ _cpp_backup_tokens (parse_in, 1);
+
+ return STRING;
+}
static inline int
_yylex ()
@@ -3744,7 +3787,13 @@ _yylex ()
return 0;
case CPP_NAME:
- return yylexname ();
+ {
+ int ret = yylexname ();
+ if (ret == STRING)
+ return yylexstring ();
+ else
+ return ret;
+ }
case CPP_NUMBER:
case CPP_CHAR:
@@ -3753,8 +3802,8 @@ _yylex ()
case CPP_STRING:
case CPP_WSTRING:
- return STRING;
-
+ return yylexstring ();
+
/* This token is Objective-C specific. It gives the next token
special significance. */
case CPP_ATSIGN:
@@ -3809,21 +3858,6 @@ yylex()
return r;
}
-/* Sets the value of the 'yydebug' variable to VALUE.
- This is a function so we don't have to have YYDEBUG defined
- in order to build the compiler. */
-
-void
-c_set_yydebug (value)
- int value;
-{
-#if YYDEBUG != 0
- yydebug = value;
-#else
- warning ("YYDEBUG not defined");
-#endif
-}
-
/* Function used when yydebug is set, to print a token in more detail. */
static void
@@ -3835,7 +3869,7 @@ yyprint (file, yychar, yyl)
tree t = yyl.ttype;
fprintf (file, " [%s]", NAME(last_token));
-
+
switch (yychar)
{
case IDENTIFIER:
@@ -3844,6 +3878,7 @@ yyprint (file, yychar, yyl)
case TYPESPEC:
case TYPE_QUAL:
case SCSPEC:
+ case STATIC:
if (IDENTIFIER_POINTER (t))
fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
break;
@@ -3877,23 +3912,16 @@ yyprint (file, yychar, yyl)
/* This is not the ideal place to put these, but we have to get them out
of c-lex.c because cp/lex.c has its own versions. */
-/* Return something to represent absolute declarators containing a *.
- TARGET is the absolute declarator that the * contains.
- TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
- to apply to the pointer type, represented as identifiers, possible mixed
- with attributes.
+/* Free malloced parser stacks if necessary. */
- We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST,
- if attributes are present) and whose type is the modifier list. */
-
-tree
-make_pointer_declarator (type_quals_attrs, target)
- tree type_quals_attrs, target;
+void
+free_parser_stacks ()
{
- tree quals, attrs;
- tree itarget = target;
- split_specs_attrs (type_quals_attrs, &quals, &attrs);
- if (attrs != NULL_TREE)
- itarget = tree_cons (attrs, target, NULL_TREE);
- return build1 (INDIRECT_REF, quals, itarget);
+ if (malloced_yyss)
+ {
+ free (malloced_yyss);
+ free (malloced_yyvs);
+ }
}
+
+#include "gt-c-parse.h"
diff --git a/contrib/gcc/c-pragma.c b/contrib/gcc/c-pragma.c
index a0a99fd..73c7d5f 100644
--- a/contrib/gcc/c-pragma.c
+++ b/contrib/gcc/c-pragma.c
@@ -29,7 +29,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "flags.h"
#include "toplev.h"
#include "ggc.h"
-#include "c-lex.h"
#include "c-common.h"
#include "output.h"
#include "tm_p.h"
@@ -37,11 +36,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define GCC_BAD(msgid) do { warning (msgid); return; } while (0)
#define GCC_BAD2(msgid, arg) do { warning (msgid, arg); return; } while (0)
-#ifdef HANDLE_PRAGMA_PACK
-static void handle_pragma_pack PARAMS ((cpp_reader *));
-
-#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
-typedef struct align_stack
+typedef struct align_stack GTY(())
{
int alignment;
unsigned int num_pushes;
@@ -49,8 +44,12 @@ typedef struct align_stack
struct align_stack * prev;
} align_stack;
-static struct align_stack * alignment_stack = NULL;
+static GTY(()) struct align_stack * alignment_stack;
+#ifdef HANDLE_PRAGMA_PACK
+static void handle_pragma_pack PARAMS ((cpp_reader *));
+
+#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
/* If we have a "global" #pragma pack(<n>) in effect when the first
#pragma pack(push,<n>) is encountered, this stores the value of
maximum_field_alignment in effect. When the final pop_alignment()
@@ -62,7 +61,6 @@ static int default_alignment;
static void push_alignment PARAMS ((int, tree));
static void pop_alignment PARAMS ((tree));
-static void mark_align_stack PARAMS ((void *));
/* Push an alignment value onto the stack. */
static void
@@ -76,7 +74,7 @@ push_alignment (alignment, id)
{
align_stack * entry;
- entry = (align_stack *) xmalloc (sizeof (* entry));
+ entry = (align_stack *) ggc_alloc (sizeof (* entry));
entry->alignment = alignment;
entry->num_pushes = 1;
@@ -138,24 +136,9 @@ pop_alignment (id)
else
maximum_field_alignment = entry->alignment;
- free (alignment_stack);
-
alignment_stack = entry;
}
}
-
-static void
-mark_align_stack (p)
- void *p;
-{
- align_stack *a = *(align_stack **) p;
-
- while (a)
- {
- ggc_mark_tree (a->id);
- a = a->prev;
- }
-}
#else /* not HANDLE_PRAGMA_PACK_PUSH_POP */
#define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = (ALIGN))
#define push_alignment(ID, N) \
@@ -273,12 +256,12 @@ handle_pragma_pack (dummy)
}
#endif /* HANDLE_PRAGMA_PACK */
+static GTY(()) tree pending_weaks;
+
#ifdef HANDLE_PRAGMA_WEAK
static void apply_pragma_weak PARAMS ((tree, tree));
static void handle_pragma_weak PARAMS ((cpp_reader *));
-static tree pending_weaks;
-
static void
apply_pragma_weak (decl, value)
tree decl, value;
@@ -364,11 +347,11 @@ maybe_apply_pragma_weak (decl)
}
#endif /* HANDLE_PRAGMA_WEAK */
+static GTY(()) tree pending_redefine_extname;
+
#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
static void handle_pragma_redefine_extname PARAMS ((cpp_reader *));
-static tree pending_redefine_extname;
-
/* #pragma redefined_extname oldname newname */
static void
handle_pragma_redefine_extname (dummy)
@@ -400,16 +383,23 @@ handle_pragma_redefine_extname (dummy)
SET_DECL_ASSEMBLER_NAME (decl, newname);
}
else
- pending_redefine_extname
- = tree_cons (oldname, newname, pending_redefine_extname);
+ add_to_renaming_pragma_list(oldname, newname);
}
#endif
+void
+add_to_renaming_pragma_list (oldname, newname)
+ tree oldname, newname;
+{
+ pending_redefine_extname
+ = tree_cons (oldname, newname, pending_redefine_extname);
+}
+
+static GTY(()) tree pragma_extern_prefix;
+
#ifdef HANDLE_PRAGMA_EXTERN_PREFIX
static void handle_pragma_extern_prefix PARAMS ((cpp_reader *));
-static tree pragma_extern_prefix;
-
/* #pragma extern_prefix "prefix" */
static void
handle_pragma_extern_prefix (dummy)
@@ -457,11 +447,10 @@ maybe_apply_renaming_pragma (decl, asmname)
{
const char *oldasmname = IDENTIFIER_POINTER (oldname) + 1;
if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldasmname) != 0)
- warning ("asm declaration conficts with previous rename");
+ warning ("asm declaration conflicts with previous rename");
asmname = build_string (strlen (oldasmname), oldasmname);
}
-#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
{
tree *p, t;
@@ -477,7 +466,6 @@ maybe_apply_renaming_pragma (decl, asmname)
return build_string (strlen (newname), newname);
}
}
-#endif
#ifdef HANDLE_PRAGMA_EXTERN_PREFIX
if (pragma_extern_prefix && !asmname)
@@ -501,25 +489,19 @@ init_pragma ()
#endif
#ifdef HANDLE_PRAGMA_WEAK
cpp_register_pragma (parse_in, 0, "weak", handle_pragma_weak);
- ggc_add_tree_root (&pending_weaks, 1);
#endif
#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
cpp_register_pragma (parse_in, 0, "redefine_extname",
handle_pragma_redefine_extname);
- ggc_add_tree_root (&pending_redefine_extname, 1);
#endif
#ifdef HANDLE_PRAGMA_EXTERN_PREFIX
cpp_register_pragma (parse_in, 0, "extern_prefix",
handle_pragma_extern_prefix);
- ggc_add_tree_root (&pragma_extern_prefix, 1);
#endif
#ifdef REGISTER_TARGET_PRAGMAS
REGISTER_TARGET_PRAGMAS (parse_in);
#endif
-
-#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
- ggc_add_root (&alignment_stack, 1, sizeof(alignment_stack),
- mark_align_stack);
-#endif
}
+
+#include "gt-c-pragma.h"
diff --git a/contrib/gcc/c-pragma.h b/contrib/gcc/c-pragma.h
index 22e4f7a..7911c5a 100644
--- a/contrib/gcc/c-pragma.h
+++ b/contrib/gcc/c-pragma.h
@@ -22,6 +22,13 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#ifndef GCC_C_PRAGMA_H
#define GCC_C_PRAGMA_H
+/* Cause the `yydebug' variable to be defined. */
+#define YYDEBUG 1
+extern int yydebug;
+
+struct cpp_reader;
+extern struct cpp_reader* parse_in;
+
#ifdef HANDLE_SYSV_PRAGMA
#if ((defined (ASM_WEAKEN_LABEL) && defined (ASM_OUTPUT_WEAK_ALIAS)) \
|| defined (ASM_WEAKEN_DECL))
@@ -55,5 +62,8 @@ extern void cpp_register_pragma PARAMS ((cpp_reader *,
extern void maybe_apply_pragma_weak PARAMS ((tree));
extern tree maybe_apply_renaming_pragma PARAMS ((tree, tree));
+extern void add_to_renaming_pragma_list PARAMS ((tree, tree));
+
+extern int c_lex PARAMS ((tree *));
#endif /* GCC_C_PRAGMA_H */
diff --git a/contrib/gcc/c-pretty-print.c b/contrib/gcc/c-pretty-print.c
new file mode 100644
index 0000000..377018e
--- /dev/null
+++ b/contrib/gcc/c-pretty-print.c
@@ -0,0 +1,1493 @@
+/* Subroutines common to both C and C++ pretty-printers.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "real.h"
+#include "c-pretty-print.h"
+#include "c-tree.h"
+
+/* literal */
+static void pp_c_char PARAMS ((c_pretty_printer, int));
+static void pp_c_character_literal PARAMS ((c_pretty_printer, tree));
+static void pp_c_bool_literal PARAMS ((c_pretty_printer, tree));
+static bool pp_c_enumerator PARAMS ((c_pretty_printer, tree));
+static void pp_c_integer_literal PARAMS ((c_pretty_printer, tree));
+static void pp_c_real_literal PARAMS ((c_pretty_printer, tree));
+static void pp_c_string_literal PARAMS ((c_pretty_printer, tree));
+
+static void pp_c_primary_expression PARAMS ((c_pretty_printer, tree));
+
+/* postfix-expression */
+static void pp_c_initializer_list PARAMS ((c_pretty_printer, tree));
+
+static void pp_c_unary_expression PARAMS ((c_pretty_printer, tree));
+static void pp_c_multiplicative_expression PARAMS ((c_pretty_printer, tree));
+static void pp_c_additive_expression PARAMS ((c_pretty_printer, tree));
+static void pp_c_shift_expression PARAMS ((c_pretty_printer, tree));
+static void pp_c_relational_expression PARAMS ((c_pretty_printer, tree));
+static void pp_c_equality_expression PARAMS ((c_pretty_printer, tree));
+static void pp_c_and_expression PARAMS ((c_pretty_printer, tree));
+static void pp_c_exclusive_or_expression PARAMS ((c_pretty_printer,
+ tree));
+static void pp_c_inclusive_or_expression PARAMS ((c_pretty_printer,
+ tree));
+static void pp_c_logical_and_expression PARAMS ((c_pretty_printer, tree));
+static void pp_c_conditional_expression PARAMS ((c_pretty_printer, tree));
+static void pp_c_assignment_expression PARAMS ((c_pretty_printer, tree));
+
+/* declarations. */
+static void pp_c_declaration_specifiers PARAMS ((c_pretty_printer, tree));
+static void pp_c_init_declarator PARAMS ((c_pretty_printer, tree));
+static void pp_c_declarator PARAMS ((c_pretty_printer, tree));
+static void pp_c_direct_declarator PARAMS ((c_pretty_printer, tree));
+static void pp_c_abstract_declarator PARAMS ((c_pretty_printer, tree));
+static void pp_c_specifier_qualifier_list PARAMS ((c_pretty_printer, tree));
+static void pp_c_simple_type_specifier PARAMS ((c_pretty_printer, tree));
+static void pp_c_parameter_declaration PARAMS ((c_pretty_printer, tree));
+static void pp_c_type_id PARAMS ((c_pretty_printer, tree));
+static void pp_c_storage_class_specifier PARAMS ((c_pretty_printer, tree));
+static void pp_c_function_specifier PARAMS ((c_pretty_printer, tree));
+
+
+/* Declarations. */
+
+/* Print out CV-qualifiers. Take care of possible extensions. */
+void
+pp_c_cv_qualifier (ppi, cv)
+ c_pretty_printer ppi;
+ int cv;
+{
+ if (cv & TYPE_QUAL_CONST)
+ pp_c_identifier (ppi, "const");
+ if (cv & TYPE_QUAL_VOLATILE)
+ pp_c_identifier (ppi, "volatile");
+ if (cv & TYPE_QUAL_RESTRICT)
+ pp_c_identifier (ppi, flag_isoc99 ? "restrict" : "__restrict__");
+}
+
+static void
+pp_c_simple_type_specifier (ppi, t)
+ c_pretty_printer ppi;
+ tree t;
+{
+ const enum tree_code code = TREE_CODE (t);
+ switch (code)
+ {
+ case ERROR_MARK:
+ pp_c_identifier (ppi, "<type-error>");
+ break;
+
+#if 0
+ case UNKNOWN_TYPE:
+ pp_c_identifier (ppi, "<unkown-type>");
+ break;
+#endif
+
+ case IDENTIFIER_NODE:
+ pp_c_tree_identifier (ppi, t);
+ break;
+
+ case VOID_TYPE:
+ case BOOLEAN_TYPE:
+ case CHAR_TYPE:
+ case INTEGER_TYPE:
+ case REAL_TYPE:
+ pp_c_tree_identifier (ppi, DECL_NAME (t));
+ break;
+
+ case COMPLEX_TYPE:
+ case VECTOR_TYPE:
+ pp_c_simple_type_specifier (ppi, TYPE_MAIN_VARIANT (TREE_TYPE (t)));
+ if (code == COMPLEX_TYPE)
+ pp_c_identifier (ppi, flag_isoc99 ? "_Complex" : "__complex__");
+ else if (code == VECTOR_TYPE)
+ pp_c_identifier (ppi, "__vector__");
+ break;
+
+ case TYPE_DECL:
+ if (DECL_NAME (t))
+ pp_c_tree_identifier (ppi, DECL_NAME (t));
+ else
+ pp_c_identifier (ppi, "<typedef-error>");
+ break;
+
+ case UNION_TYPE:
+ case RECORD_TYPE:
+ case ENUMERAL_TYPE:
+ if (code == UNION_TYPE)
+ pp_c_identifier (ppi, "union");
+ else if (code == RECORD_TYPE)
+ pp_c_identifier (ppi, "struct");
+ else if (code == ENUMERAL_TYPE)
+ pp_c_identifier (ppi, "enum");
+ else
+ pp_c_identifier (ppi, "<tag-error>");
+
+ if (TYPE_NAME (t))
+ pp_c_tree_identifier (ppi, TYPE_NAME (t));
+ else
+ pp_c_identifier (ppi, "<anonymous>");
+ break;
+
+ default:
+ pp_unsupported_tree (ppi, t);
+ }
+}
+
+static inline void
+pp_c_specifier_qualifier_list (ppi, t)
+ c_pretty_printer ppi;
+ tree t;
+{
+ pp_c_simple_type_specifier (ppi, TYPE_MAIN_VARIANT (TREE_TYPE (t)));
+ pp_c_cv_qualifier (ppi, TYPE_QUALS (t));
+}
+
+static void
+pp_c_abstract_declarator (ppi, t)
+ c_pretty_printer ppi;
+ tree t;
+{
+ pp_unsupported_tree (ppi, t);
+}
+
+
+static inline void
+pp_c_type_id (ppi, t)
+ c_pretty_printer ppi;
+ tree t;
+{
+ pp_c_specifier_qualifier_list (ppi, t);
+ pp_c_abstract_declarator (ppi, t);
+}
+
+static inline void
+pp_c_storage_class_specifier (pp, t)
+ c_pretty_printer pp;
+ tree t;
+{
+ if (TREE_CODE (t) == TYPE_DECL)
+ pp_c_identifier (pp, "typedef");
+ else if (DECL_REGISTER (t))
+ pp_c_identifier (pp, "register");
+}
+
+static inline void
+pp_c_function_specifier (pp, t)
+ c_pretty_printer pp;
+ tree t;
+{
+ if (TREE_CODE (t) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (t))
+ pp_c_identifier (pp, "inline");
+}
+
+static inline void
+pp_c_declaration_specifiers (pp, t)
+ c_pretty_printer pp;
+ tree t;
+{
+ pp_c_storage_class_specifier (pp, t);
+ pp_c_function_specifier (pp, t);
+ pp_type_specifier (pp, TYPE_MAIN_VARIANT (TREE_TYPE (t)));
+ pp_c_cv_qualifier (pp, TYPE_QUALS (TREE_TYPE (t)));
+}
+
+static inline void
+pp_c_direct_declarator (pp, t)
+ c_pretty_printer pp;
+ tree t;
+{
+ pp_unsupported_tree (pp, t);
+}
+
+static inline void
+pp_c_declarator (pp, t)
+ c_pretty_printer pp;
+ tree t;
+{
+ pp_unsupported_tree (pp, t);
+}
+
+static inline void
+pp_c_init_declarator (pp, t)
+ c_pretty_printer pp;
+ tree t;
+{
+ pp_declarator (pp, t);
+ if (DECL_INITIAL (t))
+ {
+ pp_whitespace (pp);
+ pp_equal (pp);
+ pp_whitespace (pp);
+ pp_c_initializer (pp, DECL_INITIAL (t));
+ }
+}
+
+void
+pp_c_declaration (pp, t)
+ c_pretty_printer pp;
+ tree t;
+{
+ pp_declaration_specifiers (pp, t);
+ pp_c_init_declarator (pp, t);
+}
+
+static void
+pp_c_parameter_declaration (pp, t)
+ c_pretty_printer pp;
+ tree t;
+{
+ pp_unsupported_tree (pp, t);
+}
+
+/* Pretty-print ATTRIBUTES using GNU C extension syntax. */
+void
+pp_c_attributes (pp, attributes)
+ c_pretty_printer pp;
+ tree attributes;
+{
+ if (attributes == NULL_TREE)
+ return;
+
+ pp_c_identifier (pp, "__attribute__");
+ pp_c_left_paren (pp);
+ pp_c_left_paren (pp);
+ for (; attributes != NULL_TREE; attributes = TREE_CHAIN (attributes))
+ {
+ pp_tree_identifier (pp, TREE_PURPOSE (attributes));
+ if (TREE_VALUE (attributes))
+ {
+ pp_c_left_paren (pp);
+ pp_c_expression_list (pp, TREE_VALUE (attributes));
+ pp_c_right_paren (pp);
+ }
+
+ if (TREE_CHAIN (attributes))
+ pp_separate_with (pp, ',');
+ }
+ pp_c_right_paren (pp);
+ pp_c_right_paren (pp);
+}
+
+
+/* Expressions. */
+
+/* Print out a c-char. */
+static void
+pp_c_char (ppi, c)
+ c_pretty_printer ppi;
+ int c;
+{
+ switch (c)
+ {
+ case TARGET_NEWLINE:
+ pp_identifier (ppi, "\\n");
+ break;
+ case TARGET_TAB:
+ pp_identifier (ppi, "\\t");
+ break;
+ case TARGET_VT:
+ pp_identifier (ppi, "\\v");
+ break;
+ case TARGET_BS:
+ pp_identifier (ppi, "\\b");
+ break;
+ case TARGET_CR:
+ pp_identifier (ppi, "\\r");
+ break;
+ case TARGET_FF:
+ pp_identifier (ppi, "\\f");
+ break;
+ case TARGET_BELL:
+ pp_identifier (ppi, "\\a");
+ break;
+ case '\\':
+ pp_identifier (ppi, "\\\\");
+ break;
+ case '\'':
+ pp_identifier (ppi, "\\'");
+ break;
+ case '\"':
+ pp_identifier (ppi, "\\\"");
+ break;
+ default:
+ if (ISPRINT (c))
+ pp_character (ppi, c);
+ else
+ pp_format_scalar (ppi, "\\%03o", (unsigned) c);
+ break;
+ }
+}
+
+/* Print out a STRING literal. */
+static inline void
+pp_c_string_literal (ppi, s)
+ c_pretty_printer ppi;
+ tree s;
+{
+ const char *p = TREE_STRING_POINTER (s);
+ int n = TREE_STRING_LENGTH (s) - 1;
+ int i;
+ pp_doublequote (ppi);
+ for (i = 0; i < n; ++i)
+ pp_c_char (ppi, p[i]);
+ pp_doublequote (ppi);
+}
+
+/* Print out a CHARACTER literal. */
+static inline void
+pp_c_character_literal (ppi, c)
+ c_pretty_printer ppi;
+ tree c;
+{
+ pp_quote (ppi);
+ pp_c_char (ppi, tree_low_cst (c, 0));
+ pp_quote (ppi);
+}
+
+/* Print out a BOOLEAN literal. */
+static inline void
+pp_c_bool_literal (ppi, b)
+ c_pretty_printer ppi;
+ tree b;
+{
+ if (b == boolean_false_node || integer_zerop (b))
+ {
+ if (c_language == clk_cplusplus)
+ pp_c_identifier (ppi, "false");
+ else if (c_language == clk_c && flag_isoc99)
+ pp_c_identifier (ppi, "_False");
+ else
+ pp_unsupported_tree (ppi, b);
+ }
+ else if (b == boolean_true_node)
+ {
+ if (c_language == clk_cplusplus)
+ pp_c_identifier (ppi, "true");
+ else if (c_language == clk_c && flag_isoc99)
+ pp_c_identifier (ppi, "_True");
+ else
+ pp_unsupported_tree (ppi, b);
+ }
+ else
+ pp_unsupported_tree (ppi, b);
+}
+
+/* Attempt to print out an ENUMERATOR. Return true on success. Else return
+ false; that means the value was obtained by a cast, in which case
+ print out the type-id part of the cast-expression -- the casted value
+ is then printed by pp_c_integer_literal. */
+static bool
+pp_c_enumerator (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ tree type = TREE_TYPE (e);
+ tree value;
+
+ /* Find the name of this constant. */
+ for (value = TYPE_VALUES (type);
+ value != NULL_TREE && !tree_int_cst_equal (TREE_VALUE (value), e);
+ value = TREE_CHAIN (value))
+ ;
+
+ if (value != NULL_TREE)
+ pp_c_tree_identifier (ppi, TREE_PURPOSE (value));
+ else
+ {
+ /* Value must have been cast. */
+ pp_c_left_paren (ppi);
+ pp_type_id (ppi, type);
+ pp_c_right_paren (ppi);
+ return false;
+ }
+
+ return true;
+}
+
+/* Print out an INTEGER constant value. */
+static void
+pp_c_integer_literal (ppi, i)
+ c_pretty_printer ppi;
+ tree i;
+{
+ tree type = TREE_TYPE (i);
+
+ if (type == boolean_type_node)
+ pp_c_bool_literal (ppi, i);
+ else if (type == char_type_node)
+ pp_c_character_literal (ppi, i);
+ else if (TREE_CODE (type) == ENUMERAL_TYPE
+ && pp_c_enumerator (ppi, i))
+ ;
+ else
+ {
+ if (host_integerp (i, 0))
+ pp_wide_integer (ppi, TREE_INT_CST_LOW (i));
+ else
+ {
+ if (tree_int_cst_sgn (i) < 0)
+ {
+ static char format[10]; /* "%x%09999x\0" */
+ if (!format[0])
+ sprintf (format, "%%x%%0%dx", HOST_BITS_PER_INT / 4);
+
+ pp_c_char (ppi, '-');
+ i = build_int_2 (-TREE_INT_CST_LOW (i),
+ ~TREE_INT_CST_HIGH (i) + !TREE_INT_CST_LOW (i));
+ sprintf (pp_buffer (ppi)->digit_buffer, format,
+ TREE_INT_CST_HIGH (i), TREE_INT_CST_LOW (i));
+ pp_identifier (ppi, pp_buffer (ppi)->digit_buffer);
+
+ }
+ }
+ }
+}
+
+/* Print out a REAL value. */
+static inline void
+pp_c_real_literal (ppi, r)
+ c_pretty_printer ppi;
+ tree r;
+{
+ real_to_decimal (pp_buffer (ppi)->digit_buffer, &TREE_REAL_CST (r),
+ sizeof (pp_buffer (ppi)->digit_buffer), 0, 1);
+ pp_identifier (ppi, pp_buffer(ppi)->digit_buffer);
+}
+
+
+void
+pp_c_literal (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ switch (TREE_CODE (e))
+ {
+ case INTEGER_CST:
+ pp_c_integer_literal (ppi, e);
+ break;
+
+ case REAL_CST:
+ pp_c_real_literal (ppi, e);
+ break;
+
+ case STRING_CST:
+ pp_c_string_literal (ppi, e);
+ break;
+
+ default:
+ pp_unsupported_tree (ppi, e);
+ break;
+ }
+}
+
+/* Pretty-print a C primary-expression. */
+static void
+pp_c_primary_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ switch (TREE_CODE (e))
+ {
+ case VAR_DECL:
+ case PARM_DECL:
+ case FIELD_DECL:
+ case CONST_DECL:
+ case FUNCTION_DECL:
+ case LABEL_DECL:
+ e = DECL_NAME (e);
+ /* Fall through. */
+ case IDENTIFIER_NODE:
+ pp_c_tree_identifier (ppi, e);
+ break;
+
+ case ERROR_MARK:
+ pp_c_identifier (ppi, "<erroneous-expression>");
+ break;
+
+ case RESULT_DECL:
+ pp_c_identifier (ppi, "<return-value>");
+ break;
+
+ case INTEGER_CST:
+ case REAL_CST:
+ case STRING_CST:
+ pp_c_literal (ppi, e);
+ break;
+
+ case TARGET_EXPR:
+ pp_c_left_paren (ppi);
+ pp_c_identifier (ppi, "__builtin_memcpy");
+ pp_c_left_paren (ppi);
+ pp_ampersand (ppi);
+ pp_c_primary_expression (ppi, TREE_OPERAND (e, 0));
+ pp_separate_with (ppi, ',');
+ pp_ampersand (ppi);
+ pp_initializer (ppi, TREE_OPERAND (e, 1));
+ if (TREE_OPERAND (e, 2))
+ {
+ pp_separate_with (ppi, ',');
+ pp_c_expression (ppi, TREE_OPERAND (e, 2));
+ }
+ pp_c_right_paren (ppi);
+
+ case STMT_EXPR:
+ pp_c_left_paren (ppi);
+ pp_statement (ppi, STMT_EXPR_STMT (e));
+ pp_c_right_paren (ppi);
+ break;
+
+ default:
+ /* Make sure this call won't cause any infinite loop. */
+ pp_c_left_paren (ppi);
+ pp_c_expression (ppi, e);
+ pp_c_right_paren (ppi);
+ break;
+ }
+}
+
+/* Print out a C initializer -- also support C compound-literals. */
+void
+pp_c_initializer (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ if (TREE_CODE (e) == CONSTRUCTOR)
+ {
+ enum tree_code code = TREE_CODE (TREE_TYPE (e));
+ if (code == RECORD_TYPE || code == UNION_TYPE || code == ARRAY_TYPE)
+ {
+ pp_left_brace (ppi);
+ pp_c_initializer_list (ppi, e);
+ pp_right_brace (ppi);
+ }
+ else
+ pp_unsupported_tree (ppi, TREE_OPERAND (e, 1));
+ }
+ else
+ pp_assignment_expression (ppi, e);
+}
+
+static void
+pp_c_initializer_list (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ tree type = TREE_TYPE (e);
+ const enum tree_code code = TREE_CODE (type);
+
+ if (code == RECORD_TYPE || code == UNION_TYPE || code == ARRAY_TYPE)
+ {
+ tree init = TREE_OPERAND (e, 1);
+ for (; init != NULL_TREE; init = TREE_CHAIN (init))
+ {
+ if (code == RECORD_TYPE || code == UNION_TYPE)
+ {
+ pp_dot (ppi);
+ pp_c_primary_expression (ppi, TREE_PURPOSE (init));
+ }
+ else
+ {
+ pp_c_left_bracket (ppi);
+ if (TREE_PURPOSE (init))
+ pp_c_literal (ppi, TREE_PURPOSE (init));
+ pp_c_right_bracket (ppi);
+ }
+ pp_c_whitespace (ppi);
+ pp_equal (ppi);
+ pp_c_whitespace (ppi);
+ pp_initializer (ppi, TREE_VALUE (init));
+ if (TREE_CHAIN (init))
+ pp_separate_with (ppi, ',');
+ }
+ }
+ else
+ pp_unsupported_tree (ppi, type);
+}
+
+void
+pp_c_postfix_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ enum tree_code code = TREE_CODE (e);
+ switch (code)
+ {
+ case POSTINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ pp_postfix_expression (ppi, TREE_OPERAND (e, 0));
+ pp_identifier (ppi, code == POSTINCREMENT_EXPR ? "++" : "--");
+ break;
+
+ case ARROW_EXPR:
+ pp_postfix_expression (ppi, TREE_OPERAND (e, 0));
+ pp_arrow (ppi);
+ break;
+
+ case ARRAY_REF:
+ pp_postfix_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_left_bracket (ppi);
+ pp_c_expression (ppi, TREE_OPERAND (e, 1));
+ pp_c_right_bracket (ppi);
+ break;
+
+ case CALL_EXPR:
+ pp_postfix_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_left_paren (ppi);
+ pp_c_expression_list (ppi, TREE_OPERAND (e, 1));
+ pp_c_right_paren (ppi);
+ break;
+
+ case ABS_EXPR:
+ case FFS_EXPR:
+ pp_c_identifier (ppi,
+ code == ABS_EXPR ? "__builtin_abs" : "__builtin_ffs");
+ pp_c_left_paren (ppi);
+ pp_c_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_right_paren (ppi);
+ break;
+
+ case COMPONENT_REF:
+ {
+ tree object = TREE_OPERAND (e, 0);
+ if (TREE_CODE (object) == INDIRECT_REF)
+ {
+ pp_postfix_expression (ppi, TREE_OPERAND (object, 0));
+ pp_arrow (ppi);
+ }
+ else
+ {
+ pp_postfix_expression (ppi, object);
+ pp_dot (ppi);
+ }
+ pp_c_expression (ppi, TREE_OPERAND (e, 1));
+ }
+ break;
+
+ case COMPLEX_CST:
+ case VECTOR_CST:
+ case COMPLEX_EXPR:
+ pp_c_left_paren (ppi);
+ pp_type_id (ppi, TREE_TYPE (e));
+ pp_c_right_paren (ppi);
+ pp_left_brace (ppi);
+
+ if (code == COMPLEX_CST)
+ {
+ pp_c_expression (ppi, TREE_REALPART (e));
+ pp_separate_with (ppi, ',');
+ pp_c_expression (ppi, TREE_IMAGPART (e));
+ }
+ else if (code == VECTOR_CST)
+ pp_c_expression_list (ppi, TREE_VECTOR_CST_ELTS (e));
+ else if (code == COMPLEX_EXPR)
+ {
+ pp_c_expression (ppi, TREE_OPERAND (e, 0));
+ pp_separate_with (ppi, ',');
+ pp_c_expression (ppi, TREE_OPERAND (e, 1));
+ }
+
+ pp_right_brace (ppi);
+ break;
+
+ case COMPOUND_LITERAL_EXPR:
+ e = DECL_INITIAL (e);
+ /* Fall through. */
+ case CONSTRUCTOR:
+ pp_initializer (ppi, e);
+ break;
+
+#if 0
+ case SRCLOC:
+ pp_left_paren (ppi);
+ pp_identifier (ppi, "__location__");
+ pp_right_paren (ppi);
+ pp_whitespace (ppi);
+ pp_left_brace (ppi);
+ pp_dot (ppi);
+ pp_identifier (ppi, "file");
+ pp_whitespace (ppi);
+ pp_equal (ppi);
+ pp_c_whitespace (ppi);
+ pp_c_expression (ppi, SRCLOC_FILE (e));
+ pp_separate_with (ppi, ',');
+ pp_dot (ppi);
+ pp_identifier (ppi, "line");
+ pp_whitespace (ppi);
+ pp_equal (ppi);
+ pp_c_whitespace (ppi);
+ pp_c_expression (ppi, SRCLOC_LINE (e));
+ pp_right_brace (ppi);
+ break;
+#endif
+
+ case VA_ARG_EXPR:
+ pp_c_identifier (ppi, "__builtin_va_arg");
+ pp_c_left_paren (ppi);
+ pp_assignment_expression (ppi, TREE_OPERAND (e, 0));
+ pp_separate_with (ppi, ',');
+ pp_type_id (ppi, TREE_TYPE (e));
+ pp_c_right_paren (ppi);
+ break;
+
+ default:
+ pp_primary_expression (ppi, e);
+ break;
+ }
+}
+
+/* Print out an expression-list; E is expected to be a TREE_LIST */
+void
+pp_c_expression_list (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ for (; e != NULL_TREE; e = TREE_CHAIN (e))
+ {
+ pp_c_assignment_expression (ppi, TREE_VALUE (e));
+ if (TREE_CHAIN (e))
+ pp_separate_with (ppi, ',');
+ }
+}
+
+static void
+pp_c_unary_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ enum tree_code code = TREE_CODE (e);
+ switch (code)
+ {
+ case PREINCREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ pp_identifier (ppi, code == PREINCREMENT_EXPR ? "++" : "--");
+ pp_c_unary_expression (ppi, TREE_OPERAND (e, 0));
+ break;
+
+ case ADDR_EXPR:
+ case INDIRECT_REF:
+ case CONVERT_EXPR:
+ case NEGATE_EXPR:
+ case BIT_NOT_EXPR:
+ case TRUTH_NOT_EXPR:
+ case CONJ_EXPR:
+ if (code == ADDR_EXPR)
+ pp_ampersand (ppi);
+ else if (code == INDIRECT_REF)
+ pp_star (ppi);
+ else if (code == NEGATE_EXPR)
+ pp_minus (ppi);
+ else if (code == BIT_NOT_EXPR || code == CONJ_EXPR)
+ pp_complement (ppi);
+ else if (code == TRUTH_NOT_EXPR)
+ pp_exclamation (ppi);
+ pp_c_cast_expression (ppi, TREE_OPERAND (e, 0));
+ break;
+
+ case SIZEOF_EXPR:
+ case ALIGNOF_EXPR:
+ pp_c_identifier (ppi, code == SIZEOF_EXPR ? "sizeof" : "__alignof__");
+ pp_c_whitespace (ppi);
+ if (TYPE_P (TREE_OPERAND (e, 0)))
+ {
+ pp_c_left_paren (ppi);
+ pp_type_id (ppi, TREE_OPERAND (e, 0));
+ pp_c_right_paren (ppi);
+ }
+ else
+ pp_c_unary_expression (ppi, TREE_OPERAND (e, 0));
+ break;
+
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ pp_c_identifier (ppi, code == REALPART_EXPR ? "__real__" : "__imag__");
+ pp_c_whitespace (ppi);
+ pp_unary_expression (ppi, TREE_OPERAND (e, 0));
+ break;
+
+ default:
+ pp_postfix_expression (ppi, e);
+ break;
+ }
+}
+
+void
+pp_c_cast_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ if (TREE_CODE (e) == CONVERT_EXPR || TREE_CODE (e) == FLOAT_EXPR)
+ {
+ pp_c_left_paren (ppi);
+ pp_type_id (ppi, TREE_TYPE (e));
+ pp_c_right_paren (ppi);
+ pp_c_cast_expression (ppi, TREE_OPERAND (e, 0));
+ }
+ else
+ pp_unary_expression (ppi, e);
+}
+
+static void
+pp_c_multiplicative_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ enum tree_code code = TREE_CODE (e);
+ switch (code)
+ {
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case TRUNC_MOD_EXPR:
+ pp_c_multiplicative_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_whitespace (ppi);
+ if (code == MULT_EXPR)
+ pp_star (ppi);
+ else if (code == TRUNC_DIV_EXPR)
+ pp_slash (ppi);
+ else
+ pp_modulo (ppi);
+ pp_c_whitespace (ppi);
+ pp_c_cast_expression (ppi, TREE_OPERAND (e, 1));
+ break;
+
+ default:
+ pp_c_cast_expression (ppi, e);
+ break;
+ }
+}
+
+static inline void
+pp_c_additive_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ enum tree_code code = TREE_CODE (e);
+ switch (code)
+ {
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ pp_c_additive_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_whitespace (ppi);
+ if (code == PLUS_EXPR)
+ pp_plus (ppi);
+ else
+ pp_minus (ppi);
+ pp_c_whitespace (ppi);
+ pp_multiplicative_expression (ppi, TREE_OPERAND (e, 1));
+ break;
+
+ default:
+ pp_multiplicative_expression (ppi, e);
+ break;
+ }
+}
+
+static inline void
+pp_c_shift_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ enum tree_code code = TREE_CODE (e);
+ switch (code)
+ {
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ pp_c_shift_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_whitespace (ppi);
+ pp_identifier (ppi, code == LSHIFT_EXPR ? "<<" : ">>");
+ pp_c_whitespace (ppi);
+ pp_c_additive_expression (ppi, TREE_OPERAND (e, 1));
+ break;
+
+ default:
+ pp_c_additive_expression (ppi, e);
+ }
+}
+
+static void
+pp_c_relational_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ enum tree_code code = TREE_CODE (e);
+ switch (code)
+ {
+ case LT_EXPR:
+ case GT_EXPR:
+ case LE_EXPR:
+ case GE_EXPR:
+ pp_c_relational_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_whitespace (ppi);
+ if (code == LT_EXPR)
+ pp_less (ppi);
+ else if (code == GT_EXPR)
+ pp_greater (ppi);
+ else if (code == LE_EXPR)
+ pp_identifier (ppi, "<=");
+ else if (code == GE_EXPR)
+ pp_identifier (ppi, ">=");
+ pp_c_whitespace (ppi);
+ pp_c_shift_expression (ppi, TREE_OPERAND (e, 1));
+ break;
+
+ default:
+ pp_c_shift_expression (ppi, e);
+ break;
+ }
+}
+
+static inline void
+pp_c_equality_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ enum tree_code code = TREE_CODE (e);
+ switch (code)
+ {
+ case EQ_EXPR:
+ case NE_EXPR:
+ pp_c_equality_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_maybe_whitespace (ppi);
+ pp_identifier (ppi, code == EQ_EXPR ? "==" : "!=");
+ pp_c_whitespace (ppi);
+ pp_c_relational_expression (ppi, TREE_OPERAND (e, 1));
+ break;
+
+ default:
+ pp_c_relational_expression (ppi, e);
+ break;
+ }
+}
+
+static inline void
+pp_c_and_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ if (TREE_CODE (e) == BIT_AND_EXPR)
+ {
+ pp_c_and_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_maybe_whitespace (ppi);
+ pp_ampersand (ppi);
+ pp_c_whitespace (ppi);
+ pp_c_equality_expression (ppi, TREE_OPERAND (e, 1));
+ }
+ else
+ pp_c_equality_expression (ppi, e);
+}
+
+static inline void
+pp_c_exclusive_or_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ if (TREE_CODE (e) == BIT_XOR_EXPR)
+ {
+ pp_c_exclusive_or_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_maybe_whitespace (ppi);
+ pp_carret (ppi);
+ pp_c_whitespace (ppi);
+ pp_c_and_expression (ppi, TREE_OPERAND (e, 1));
+ }
+ else
+ pp_c_and_expression (ppi, e);
+}
+
+static inline void
+pp_c_inclusive_or_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ if (TREE_CODE (e) == BIT_IOR_EXPR)
+ {
+ pp_c_exclusive_or_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_maybe_whitespace (ppi);
+ pp_bar (ppi);
+ pp_c_whitespace (ppi);
+ pp_c_exclusive_or_expression (ppi, TREE_OPERAND (e, 1));
+ }
+ else
+ pp_c_exclusive_or_expression (ppi, e);
+}
+
+static inline void
+pp_c_logical_and_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ if (TREE_CODE (e) == TRUTH_ANDIF_EXPR)
+ {
+ pp_c_logical_and_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_maybe_whitespace (ppi);
+ pp_identifier (ppi, "&&");
+ pp_c_whitespace (ppi);
+ pp_c_inclusive_or_expression (ppi, TREE_OPERAND (e, 1));
+ }
+ else
+ pp_c_inclusive_or_expression (ppi, e);
+}
+
+void
+pp_c_logical_or_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ if (TREE_CODE (e) == TRUTH_ORIF_EXPR)
+ {
+ pp_c_logical_or_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_maybe_whitespace (ppi);
+ pp_identifier (ppi, "||");
+ pp_c_whitespace (ppi);
+ pp_c_logical_and_expression (ppi, TREE_OPERAND (e, 1));
+ }
+ else
+ pp_c_logical_and_expression (ppi, e);
+}
+
+static void
+pp_c_conditional_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ if (TREE_CODE (e) == COND_EXPR)
+ {
+ pp_c_logical_or_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_maybe_whitespace (ppi);
+ pp_question (ppi);
+ pp_c_whitespace (ppi);
+ pp_c_expression (ppi, TREE_OPERAND (e, 1));
+ pp_c_maybe_whitespace (ppi);
+ pp_colon (ppi);
+ pp_c_whitespace (ppi);
+ pp_c_conditional_expression (ppi, TREE_OPERAND (e, 2));
+ }
+ else
+ pp_c_logical_or_expression (ppi, e);
+}
+
+
+/* Pretty-print a C assignment-expression. */
+static void
+pp_c_assignment_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ if (TREE_CODE (e) == MODIFY_EXPR || TREE_CODE (e) == INIT_EXPR)
+ {
+ pp_c_unary_expression (ppi, TREE_OPERAND (e, 0));
+ pp_c_maybe_whitespace (ppi);
+ pp_equal (ppi);
+ pp_whitespace (ppi);
+ pp_c_assignment_expression (ppi, TREE_OPERAND (e, 1));
+ }
+ else
+ pp_c_conditional_expression (ppi, e);
+}
+
+/* Pretty-print an expression. */
+void
+pp_c_expression (ppi, e)
+ c_pretty_printer ppi;
+ tree e;
+{
+ switch (TREE_CODE (e))
+ {
+ case INTEGER_CST:
+ pp_c_integer_literal (ppi, e);
+ break;
+
+ case REAL_CST:
+ pp_c_real_literal (ppi, e);
+ break;
+
+ case STRING_CST:
+ pp_c_string_literal (ppi, e);
+ break;
+
+ case FUNCTION_DECL:
+ case VAR_DECL:
+ case CONST_DECL:
+ case PARM_DECL:
+ case RESULT_DECL:
+ case FIELD_DECL:
+ case LABEL_DECL:
+ case ERROR_MARK:
+ case TARGET_EXPR:
+ case STMT_EXPR:
+ pp_c_primary_expression (ppi, e);
+ break;
+
+ case POSTINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case ARROW_EXPR:
+ case ARRAY_REF:
+ case CALL_EXPR:
+ case COMPONENT_REF:
+ case COMPLEX_CST:
+ case VECTOR_CST:
+ case ABS_EXPR:
+ case FFS_EXPR:
+ case CONSTRUCTOR:
+ case COMPOUND_LITERAL_EXPR:
+ case COMPLEX_EXPR:
+ case VA_ARG_EXPR:
+ pp_c_postfix_expression (ppi, e);
+ break;
+
+ case CONJ_EXPR:
+ case ADDR_EXPR:
+ case INDIRECT_REF:
+ case NEGATE_EXPR:
+ case BIT_NOT_EXPR:
+ case TRUTH_NOT_EXPR:
+ case PREINCREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ case SIZEOF_EXPR:
+ case ALIGNOF_EXPR:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ pp_c_unary_expression (ppi, e);
+ break;
+
+ case CONVERT_EXPR:
+ case FLOAT_EXPR:
+ pp_c_cast_expression (ppi, e);
+ break;
+
+ case MULT_EXPR:
+ case TRUNC_MOD_EXPR:
+ case TRUNC_DIV_EXPR:
+ pp_c_multiplicative_expression (ppi, e);
+ break;
+
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ pp_c_shift_expression (ppi, e);
+ break;
+
+ case LT_EXPR:
+ case GT_EXPR:
+ case LE_EXPR:
+ case GE_EXPR:
+ pp_c_relational_expression (ppi, e);
+ break;
+
+ case BIT_AND_EXPR:
+ pp_c_and_expression (ppi, e);
+ break;
+
+ case BIT_XOR_EXPR:
+ pp_c_exclusive_or_expression (ppi, e);
+ break;
+
+ case BIT_IOR_EXPR:
+ pp_c_inclusive_or_expression (ppi, e);
+ break;
+
+ case TRUTH_ANDIF_EXPR:
+ pp_c_logical_and_expression (ppi, e);
+ break;
+
+ case TRUTH_ORIF_EXPR:
+ pp_c_logical_or_expression (ppi, e);
+ break;
+
+ case COND_EXPR:
+ pp_c_conditional_expression (ppi, e);
+ break;
+
+ case MODIFY_EXPR:
+ case INIT_EXPR:
+ pp_c_assignment_expression (ppi, e);
+ break;
+
+ case NOP_EXPR:
+ pp_c_expression (ppi, TREE_OPERAND (e, 0));
+ break;
+
+ case COMPOUND_EXPR:
+ pp_c_left_paren (ppi);
+ pp_c_expression (ppi, TREE_OPERAND (e, 0));
+ pp_separate_with (ppi, ',');
+ pp_assignment_expression (ppi, TREE_OPERAND (e, 1));
+ pp_c_right_paren (ppi);
+ break;
+
+
+ default:
+ pp_unsupported_tree (ppi, e);
+ break;
+ }
+}
+
+
+/* Statements. */
+void
+pp_c_statement (ppi, stmt)
+ c_pretty_printer ppi;
+ tree stmt;
+{
+ const enum tree_code code = TREE_CODE (stmt);
+ switch (code)
+ {
+ case LABEL_STMT:
+ case CASE_LABEL:
+ pp_newline (ppi);
+ if (code == LABEL_STMT)
+ pp_tree_identifier (ppi, DECL_NAME (LABEL_STMT_LABEL (stmt)));
+ else if (code == LABEL_STMT)
+ {
+ if (CASE_LOW (stmt) == NULL_TREE)
+ pp_identifier (ppi, "default");
+ else
+ {
+ pp_c_identifier (ppi, "case");
+ pp_c_whitespace (ppi);
+ pp_conditional_expression (ppi, CASE_LOW (stmt));
+ if (CASE_HIGH (stmt))
+ {
+ pp_identifier (ppi, "...");
+ pp_conditional_expression (ppi, CASE_HIGH (stmt));
+ }
+ }
+ }
+ pp_colon (ppi);
+ pp_newline_and_indent (ppi, 3);
+ break;
+
+ case COMPOUND_STMT:
+ pp_left_brace (ppi);
+ pp_newline_and_indent (ppi, 3);
+ for (stmt = COMPOUND_BODY (stmt); stmt; stmt = TREE_CHAIN (stmt))
+ pp_c_statement (ppi, stmt);
+ pp_newline_and_indent (ppi, -3);
+ pp_right_brace (ppi);
+ pp_newline (ppi);
+ break;
+
+ case EXPR_STMT:
+ case CLEANUP_STMT:
+ pp_newline (ppi);
+ pp_c_expression (ppi, code == EXPR_STMT
+ ? EXPR_STMT_EXPR (stmt)
+ : CLEANUP_EXPR (stmt));
+ pp_semicolon (ppi);
+ pp_newline (ppi);
+ break;
+
+ case IF_STMT:
+ pp_c_identifier (ppi, "if");
+ pp_whitespace (ppi);
+ pp_c_left_paren (ppi);
+ pp_c_expression (ppi, IF_COND (stmt));
+ pp_right_paren (ppi);
+ pp_newline_and_indent (ppi, 3);
+ pp_statement (ppi, THEN_CLAUSE (stmt));
+ pp_newline_and_indent (ppi, -3);
+ if (ELSE_CLAUSE (stmt))
+ {
+ tree else_clause = ELSE_CLAUSE (stmt);
+ pp_c_identifier (ppi, "else");
+ if (TREE_CODE (else_clause) == IF_STMT)
+ pp_c_whitespace (ppi);
+ else
+ pp_newline_and_indent (ppi, 3);
+ pp_statement (ppi, else_clause);
+ if (TREE_CODE (else_clause) != IF_STMT)
+ pp_newline_and_indent (ppi, -3);
+ }
+ break;
+
+ case SWITCH_STMT:
+ pp_newline (ppi);
+ pp_c_identifier (ppi, "switch");
+ pp_whitespace (ppi);
+ pp_c_left_paren (ppi);
+ pp_c_expression (ppi, SWITCH_COND (stmt));
+ pp_right_paren (ppi);
+ pp_newline_and_indent (ppi, 3);
+ pp_statement (ppi, SWITCH_BODY (stmt));
+ pp_newline_and_indent (ppi, -3);
+ break;
+
+ case WHILE_STMT:
+ pp_c_identifier (ppi, "while");
+ pp_whitespace (ppi);
+ pp_c_left_paren (ppi);
+ pp_c_expression (ppi, WHILE_COND (stmt));
+ pp_right_paren (ppi);
+ pp_newline_and_indent (ppi, 3);
+ pp_statement (ppi, WHILE_BODY (stmt));
+ pp_newline_and_indent (ppi, -3);
+ break;
+
+ case DO_STMT:
+ pp_c_identifier (ppi, "do");
+ pp_newline_and_indent (ppi, 3);
+ pp_statement (ppi, DO_BODY (stmt));
+ pp_newline_and_indent (ppi, -3);
+ pp_c_identifier (ppi, "while");
+ pp_whitespace (ppi);
+ pp_c_left_paren (ppi);
+ pp_c_expression (ppi, DO_COND (stmt));
+ pp_c_right_paren (ppi);
+ pp_semicolon (ppi);
+ pp_newline (ppi);
+ break;
+
+ case FOR_STMT:
+ pp_c_identifier (ppi, "for");
+ pp_whitespace (ppi);
+ pp_c_left_paren (ppi);
+ pp_statement (ppi, FOR_INIT_STMT (stmt));
+ pp_c_whitespace (ppi);
+ if (FOR_COND (stmt))
+ pp_c_expression (ppi, FOR_COND (stmt));
+ pp_semicolon (ppi);
+ pp_c_whitespace (ppi);
+ if (FOR_EXPR (stmt))
+ pp_c_expression (ppi, FOR_EXPR (stmt));
+ pp_right_paren (ppi);
+ pp_newline_and_indent (ppi, 3);
+ pp_statement (ppi, FOR_BODY (stmt));
+ pp_newline_and_indent (ppi, -3);
+ break;
+
+ case BREAK_STMT:
+ case CONTINUE_STMT:
+ pp_newline (ppi);
+ pp_identifier (ppi, code == BREAK_STMT ? "break" : "continue");
+ pp_semicolon (ppi);
+ pp_newline (ppi);
+ break;
+
+ case RETURN_STMT:
+ case GOTO_STMT:
+ {
+ tree e = code == RETURN_STMT
+ ? RETURN_STMT_EXPR (stmt)
+ : GOTO_DESTINATION (stmt);
+
+ pp_newline (ppi);
+ pp_c_identifier (ppi, code == RETURN_STMT ? "return" : "goto");
+ if (e)
+ pp_c_expression (ppi, e);
+ pp_semicolon (ppi);
+ pp_newline (ppi);
+ }
+ break;
+
+ case SCOPE_STMT:
+ if (!SCOPE_NULLIFIED_P (stmt) && SCOPE_NO_CLEANUPS_P (stmt))
+ {
+ if (SCOPE_BEGIN_P (stmt))
+ {
+ pp_left_brace (ppi);
+ pp_newline_and_indent (ppi, 3);
+ }
+ else if (SCOPE_END_P (stmt))
+ {
+ pp_right_brace (ppi);
+ pp_newline_and_indent (ppi, -3);
+ }
+ }
+ break;
+
+ case DECL_STMT:
+ pp_declaration (ppi, DECL_STMT_DECL (stmt));
+ pp_semicolon (ppi);
+ pp_newline (ppi);
+ break;
+
+ case ASM_STMT:
+ {
+ bool has_volatile_p = ASM_VOLATILE_P (stmt);
+ bool is_extended = has_volatile_p || ASM_INPUTS (stmt)
+ || ASM_OUTPUTS (stmt) || ASM_CLOBBERS (stmt);
+ pp_c_identifier (ppi, is_extended ? "__asm__" : "asm");
+ if (has_volatile_p)
+ pp_c_identifier (ppi, "__volatile__");
+ pp_whitespace (ppi);
+ pp_c_left_paren (ppi);
+ pp_c_string_literal (ppi, ASM_STRING (stmt));
+ if (is_extended)
+ {
+ pp_whitespace (ppi);
+ pp_separate_with (ppi, ':');
+ if (ASM_OUTPUTS (stmt))
+ pp_c_expression (ppi, ASM_OUTPUTS (stmt));
+ pp_whitespace (ppi);
+ pp_separate_with (ppi, ':');
+ if (ASM_INPUTS (stmt))
+ pp_c_expression (ppi, ASM_INPUTS (stmt));
+ pp_whitespace (ppi);
+ pp_separate_with (ppi, ':');
+ if (ASM_CLOBBERS (stmt))
+ pp_c_expression (ppi, ASM_CLOBBERS (stmt));
+ }
+ pp_right_paren (ppi);
+ pp_newline (ppi);
+ }
+ break;
+
+ case FILE_STMT:
+ pp_c_identifier (ppi, "__FILE__");
+ pp_whitespace (ppi);
+ pp_equal (ppi);
+ pp_c_whitespace (ppi);
+ pp_c_identifier (ppi, FILE_STMT_FILENAME (stmt));
+ pp_semicolon (ppi);
+ pp_newline (ppi);
+ break;
+
+ default:
+ pp_unsupported_tree (ppi, stmt);
+ }
+
+}
+
+
+/* Initialize the PRETTY-PRINTER for handling C codes. */
+void
+pp_c_pretty_printer_init (pp)
+ c_pretty_printer pp;
+{
+ pp->offset_list = 0;
+
+ pp->declaration = pp_c_declaration;
+ pp->declaration_specifiers = pp_c_declaration_specifiers;
+ pp->type_specifier = pp_c_simple_type_specifier;
+ pp->declarator = pp_c_declarator;
+ pp->direct_declarator = pp_c_direct_declarator;
+ pp->parameter_declaration = pp_c_parameter_declaration;
+ pp->type_id = pp_c_type_id;
+
+ pp->statement = pp_c_statement;
+
+ pp->primary_expression = pp_c_primary_expression;
+ pp->postfix_expression = pp_c_postfix_expression;
+ pp->unary_expression = pp_c_unary_expression;
+ pp->initializer = pp_c_initializer;
+ pp->multiplicative_expression = pp_c_multiplicative_expression;
+ pp->conditional_expression = pp_c_conditional_expression;
+ pp->assignment_expression = pp_c_assignment_expression;
+}
diff --git a/contrib/gcc/c-pretty-print.h b/contrib/gcc/c-pretty-print.h
new file mode 100644
index 0000000..0ab702e
--- /dev/null
+++ b/contrib/gcc/c-pretty-print.h
@@ -0,0 +1,165 @@
+/* Various declarations for the C and C++ pretty-printers.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#ifndef GCC_C_PRETTY_PRINTER
+#define GCC_C_PRETTY_PRINTER
+
+#include "tree.h"
+#include "c-common.h"
+#include "pretty-print.h"
+
+
+/* The data type used to bundle information necessary for pretty-printing
+ a C or C++ entity. */
+typedef struct c_pretty_print_info *c_pretty_printer;
+
+/* The type of a C pretty-printer 'member' function. */
+typedef void (*c_pretty_print_fn) PARAMS ((c_pretty_printer, tree));
+
+struct c_pretty_print_info
+{
+ struct pretty_print_info base;
+ /* Points to the first element of an array of offset-list.
+ Not used yet. */
+ int *offset_list;
+
+ /* These must be overriden by each of the C and C++ front-end to
+ reflect their understanding of syntatic productions when they differ. */
+ c_pretty_print_fn declaration;
+ c_pretty_print_fn declaration_specifiers;
+ c_pretty_print_fn type_specifier;
+ c_pretty_print_fn declarator;
+ c_pretty_print_fn direct_declarator;
+ c_pretty_print_fn parameter_declaration;
+ c_pretty_print_fn type_id;
+
+ c_pretty_print_fn statement;
+
+ c_pretty_print_fn primary_expression;
+ c_pretty_print_fn postfix_expression;
+ c_pretty_print_fn unary_expression;
+ c_pretty_print_fn initializer;
+ c_pretty_print_fn multiplicative_expression;
+ c_pretty_print_fn conditional_expression;
+ c_pretty_print_fn assignment_expression;
+};
+
+#define pp_c_left_paren(PPI) \
+ do { \
+ pp_left_paren (PPI); \
+ pp_c_base (PPI)->base.padding = pp_none; \
+ } while (0)
+#define pp_c_right_paren(PPI) \
+ do { \
+ pp_right_paren (PPI); \
+ pp_c_base (PPI)->base.padding = pp_none; \
+ } while (0)
+#define pp_c_left_bracket(PPI) \
+ do { \
+ pp_left_bracket (PPI); \
+ pp_c_base (PPI)->base.padding = pp_none; \
+ } while (0)
+#define pp_c_right_bracket(PPI) \
+ do { \
+ pp_right_bracket (PPI); \
+ pp_c_base (PPI)->base.padding = pp_none; \
+ } while (0)
+#define pp_c_whitespace(PPI) \
+ do { \
+ pp_whitespace (PPI); \
+ pp_c_base (PPI)->base.padding = pp_none; \
+ } while (0)
+#define pp_c_maybe_whitespace(PPI) \
+ do { \
+ if (pp_c_base (PPI)->base.padding != pp_none) \
+ pp_c_whitespace (PPI); \
+ } while (0)
+#define pp_c_identifier(PPI, ID) \
+ do { \
+ pp_c_maybe_whitespace (PPI); \
+ pp_identifier (PPI, ID); \
+ pp_c_base (PPI)->base.padding = pp_before; \
+ } while (0)
+
+#define pp_c_tree_identifier(PPI, ID) \
+ pp_c_identifier (PPI, IDENTIFIER_POINTER (ID))
+
+/* Returns the 'output_buffer *' associated with a PRETTY-PRINTER, the latter
+ being something digestible by pp_c_base. */
+#define pp_buffer(PPI) pp_c_base (PPI)->base.buffer
+
+#define pp_declaration(PPI, T) \
+ (*pp_c_base (PPI)->declaration) (pp_c_base (PPI), T)
+#define pp_declaration_specifiers(PPI, D) \
+ (*pp_c_base (PPI)->declaration_specifiers) (pp_c_base (PPI), D)
+#define pp_type_specifier(PPI, D) \
+ (*pp_c_base (PPI)->type_specifier) (pp_c_base (PPI), D)
+#define pp_declarator(PPI, D) \
+ (*pp_c_base (PPI)->declarator) (pp_c_base (PPI), D)
+#define pp_direct_declarator(PPI, D) \
+ (*pp_c_base (PPI)->direct_declarator) (pp_c_base (PPI), D)
+#define pp_parameter_declaration(PPI, T) \
+ (*pp_c_base (PPI)->parameter_declaration) (pp_c_base (PPI), T)
+#define pp_type_id(PPI, D) \
+ (*pp_c_base (PPI)->type_id) (pp_c_base (PPI), D)
+
+#define pp_statement(PPI, S) \
+ (*pp_c_base (PPI)->statement) (pp_c_base (PPI), S)
+
+#define pp_primary_expression(PPI, E) \
+ (*pp_c_base (PPI)->primary_expression) (pp_c_base (PPI), E)
+#define pp_postfix_expression(PPI, E) \
+ (*pp_c_base (PPI)->postfix_expression) (pp_c_base (PPI), E)
+#define pp_unary_expression(PPI, E) \
+ (*pp_c_base (PPI)->unary_expression) (pp_c_base (PPI), E)
+#define pp_initializer(PPI, E) \
+ (*pp_c_base (PPI)->initializer) (pp_c_base (PPI), E)
+#define pp_multiplicative_expression(PPI, E) \
+ (*pp_c_base (PPI)->multiplicative_expression) (pp_c_base (PPI), E)
+#define pp_conditional_expression(PPI, E) \
+ (*pp_c_base (PPI)->conditional_expression) (pp_c_base (PPI), E)
+#define pp_assignment_expression(PPI, E) \
+ (*pp_c_base (PPI)->assignment_expression) (pp_c_base (PPI), E)
+
+
+/* Returns the c_pretty_printer base object of PRETTY-PRINTER. This
+ macro must be overriden by any subclass of c_pretty_print_info. */
+#define pp_c_base(PP) (PP)
+
+extern void pp_c_pretty_printer_init PARAMS ((c_pretty_printer));
+
+/* Declarations. */
+void pp_c_attributes PARAMS ((c_pretty_printer, tree));
+void pp_c_cv_qualifier PARAMS ((c_pretty_printer, int));
+void pp_c_parameter_declaration_clause PARAMS ((c_pretty_printer, tree));
+void pp_c_declaration PARAMS ((c_pretty_printer, tree));
+/* Statements. */
+void pp_c_statement PARAMS ((c_pretty_printer, tree));
+/* Expressions. */
+void pp_c_expression PARAMS ((c_pretty_printer, tree));
+void pp_c_logical_or_expression PARAMS ((c_pretty_printer, tree));
+void pp_c_expression_list PARAMS ((c_pretty_printer, tree));
+void pp_c_cast_expression PARAMS ((c_pretty_printer, tree));
+void pp_c_postfix_expression PARAMS ((c_pretty_printer, tree));
+void pp_c_initializer PARAMS ((c_pretty_printer, tree));
+void pp_c_literal PARAMS ((c_pretty_printer, tree));
+
+#endif /* GCC_C_PRETTY_PRINTER */
diff --git a/contrib/gcc/c-semantics.c b/contrib/gcc/c-semantics.c
index eaa4452..8559fa1 100644
--- a/contrib/gcc/c-semantics.c
+++ b/contrib/gcc/c-semantics.c
@@ -36,6 +36,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "expr.h"
#include "output.h"
#include "timevar.h"
+#include "predict.h"
/* If non-NULL, the address of a language-specific function for
expanding statements. */
@@ -334,7 +335,7 @@ genrtl_expr_stmt (expr)
whether to (1) save the value of the expression, (0) discard it or
(-1) use expr_stmts_for_value to tell. The use of -1 is
deprecated, and retained only for backward compatibility.
- MAYBE_LAST is non-zero if this EXPR_STMT might be the last statement
+ MAYBE_LAST is nonzero if this EXPR_STMT might be the last statement
in expression statement. */
void
@@ -446,8 +447,9 @@ genrtl_do_stmt (t)
/* Recognize the common special-case of do { ... } while (0) and do
not emit the loop widgetry in this case. In particular this
avoids cluttering the rtl with dummy loop notes, which can affect
- alignment of adjacent labels. */
- if (integer_zerop (cond))
+ alignment of adjacent labels. COND can be NULL due to parse
+ errors. */
+ if (!cond || integer_zerop (cond))
{
expand_start_null_loop ();
expand_stmt (DO_BODY (t));
@@ -486,7 +488,7 @@ genrtl_return_stmt (stmt)
{
tree expr;
- expr = RETURN_EXPR (stmt);
+ expr = RETURN_STMT_EXPR (stmt);
emit_line_note (input_filename, lineno);
if (!expr)
@@ -673,8 +675,7 @@ genrtl_case_label (case_label)
if (cleanup)
{
static int explained = 0;
- warning_with_decl (TREE_PURPOSE (cleanup),
- "destructor needed for `%#D'");
+ warning ("destructor needed for `%#D'", (TREE_PURPOSE (cleanup)));
warning ("where case label appears here");
if (!explained)
{
@@ -835,6 +836,15 @@ expand_stmt (t)
break;
case GOTO_STMT:
+ /* Emit information for branch prediction. */
+ if (!GOTO_FAKE_P (t)
+ && TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL
+ && flag_guess_branch_prob)
+ {
+ rtx note = emit_note (NULL, NOTE_INSN_PREDICTION);
+
+ NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_GOTO, NOT_TAKEN);
+ }
genrtl_goto_stmt (GOTO_DESTINATION (t));
break;
diff --git a/contrib/gcc/c-tree.h b/contrib/gcc/c-tree.h
index 54208db..159c235 100644
--- a/contrib/gcc/c-tree.h
+++ b/contrib/gcc/c-tree.h
@@ -34,16 +34,32 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
lang_identifier nodes, because some keywords are only special in a
particular context. */
-struct lang_identifier
+struct lang_identifier GTY(())
{
- struct c_common_identifier ignore;
- tree global_value, local_value, label_value, implicit_decl;
- tree error_locus, limbo_value;
+ struct c_common_identifier common_id;
+ tree global_value;
+ tree local_value;
+ tree label_value;
+ tree implicit_decl;
+ tree error_locus;
+ tree limbo_value;
+};
+
+/* The resulting tree type. */
+
+union lang_tree_node
+ GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
+ chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
+{
+ union tree_node GTY ((tag ("0"),
+ desc ("tree_node_structure (&%h)")))
+ generic;
+ struct lang_identifier GTY ((tag ("1"))) identifier;
};
/* Language-specific declaration information. */
-struct lang_decl
+struct lang_decl GTY(())
{
struct c_lang_decl base;
/* The return types and parameter types may have variable size.
@@ -107,10 +123,10 @@ struct lang_decl
(DECL_LANG_SPECIFIC (NODE)->base.declared_inline)
/* In a RECORD_TYPE, a sorted array of the fields of the type. */
-struct lang_type
+struct lang_type GTY(())
{
int len;
- tree elts[1];
+ tree GTY((length ("%h.len"))) elts[1];
};
/* Record whether a type or decl was written with nonconstant size.
@@ -150,29 +166,36 @@ struct lang_type
/* in c-lang.c and objc-act.c */
extern tree lookup_interface PARAMS ((tree));
extern tree is_class_name PARAMS ((tree));
-extern void maybe_objc_check_decl PARAMS ((tree));
+extern tree objc_is_id PARAMS ((tree));
+extern void objc_check_decl PARAMS ((tree));
extern void finish_file PARAMS ((void));
-extern int maybe_objc_comptypes PARAMS ((tree, tree, int));
-extern tree maybe_building_objc_message_expr PARAMS ((void));
-extern int recognize_objc_keyword PARAMS ((void));
+extern int objc_comptypes PARAMS ((tree, tree, int));
+extern tree objc_message_selector PARAMS ((void));
extern tree lookup_objc_ivar PARAMS ((tree));
/* in c-parse.in */
extern void c_parse_init PARAMS ((void));
-extern void c_set_yydebug PARAMS ((int));
-extern int yyparse_1 PARAMS ((void));
/* in c-aux-info.c */
extern void gen_aux_info_record PARAMS ((tree, int, int, int));
/* in c-decl.c */
+extern int global_bindings_p PARAMS ((void));
+extern int kept_level_p PARAMS ((void));
+extern tree getdecls PARAMS ((void));
+extern void pushlevel PARAMS ((int));
+extern tree poplevel PARAMS ((int,int, int));
+extern void insert_block PARAMS ((tree));
+extern void set_block PARAMS ((tree));
+extern tree pushdecl PARAMS ((tree));
+
+extern void c_insert_default_attributes PARAMS ((tree));
extern void c_init_decl_processing PARAMS ((void));
+extern void c_dup_lang_specific_decl PARAMS ((tree));
extern void c_print_identifier PARAMS ((FILE *, tree, int));
extern tree build_array_declarator PARAMS ((tree, tree, int, int));
extern tree build_enumerator PARAMS ((tree, tree));
-extern int c_decode_option PARAMS ((int, char **));
-extern void c_mark_varargs PARAMS ((void));
extern void check_for_loop_decls PARAMS ((void));
extern void clear_parm_order PARAMS ((void));
extern int complete_array_type PARAMS ((tree, tree, int));
@@ -191,14 +214,12 @@ extern tree implicitly_declare PARAMS ((tree));
extern void implicit_decl_warning PARAMS ((tree));
extern int in_parm_level_p PARAMS ((void));
extern void keep_next_level PARAMS ((void));
-extern int kept_level_p PARAMS ((void));
extern tree lookup_name PARAMS ((tree));
extern tree lookup_name_current_level PARAMS ((tree));
extern void parmlist_tags_warning PARAMS ((void));
extern void pending_xref_error PARAMS ((void));
-extern void mark_c_function_context PARAMS ((struct function *));
-extern void push_c_function_context PARAMS ((struct function *));
-extern void pop_c_function_context PARAMS ((struct function *));
+extern void c_push_function_context PARAMS ((struct function *));
+extern void c_pop_function_context PARAMS ((struct function *));
extern void pop_label_level PARAMS ((void));
extern void push_label_level PARAMS ((void));
extern void push_parm_decl PARAMS ((tree));
@@ -218,7 +239,7 @@ extern tree xref_tag PARAMS ((enum tree_code, tree));
extern tree c_begin_compound_stmt PARAMS ((void));
extern void c_expand_deferred_function PARAMS ((tree));
extern void c_expand_decl_stmt PARAMS ((tree));
-
+extern tree make_pointer_declarator PARAMS ((tree, tree));
/* in c-objc-common.c */
extern int c_disregard_inline_limits PARAMS ((tree));
@@ -227,23 +248,28 @@ extern const char *c_objc_common_init PARAMS ((const char *));
extern int c_missing_noreturn_ok_p PARAMS ((tree));
extern void c_objc_common_finish_file PARAMS ((void));
extern int defer_fn PARAMS ((tree));
+extern bool c_warn_unused_global_decl PARAMS ((tree));
#define c_build_type_variant(TYPE, CONST_P, VOLATILE_P) \
c_build_qualified_type ((TYPE), \
((CONST_P) ? TYPE_QUAL_CONST : 0) | \
((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))
+#define c_sizeof_nowarn(T) c_sizeof_or_alignof_type (T, SIZEOF_EXPR, 0)
/* in c-typeck.c */
extern tree require_complete_type PARAMS ((tree));
extern int comptypes PARAMS ((tree, tree));
-extern tree c_sizeof_nowarn PARAMS ((tree));
extern tree c_size_in_bytes PARAMS ((tree));
+extern bool c_mark_addressable PARAMS ((tree));
+extern void c_incomplete_type_error PARAMS ((tree, tree));
+extern tree c_type_promotes_to PARAMS ((tree));
extern tree build_component_ref PARAMS ((tree, tree));
extern tree build_indirect_ref PARAMS ((tree, const char *));
extern tree build_array_ref PARAMS ((tree, tree));
extern tree build_external_ref PARAMS ((tree, int));
extern tree parser_build_binary_op PARAMS ((enum tree_code,
tree, tree));
+extern int c_tree_expr_nonnegative_p PARAMS ((tree));
extern void readonly_warning PARAMS ((tree, const char *));
extern tree build_conditional_expr PARAMS ((tree, tree, tree));
extern tree build_compound_expr PARAMS ((tree));
@@ -287,94 +313,14 @@ extern int current_function_returns_null;
extern int current_function_returns_abnormally;
-/* Nonzero means `$' can be in an identifier. */
-
-extern int dollars_in_ident;
-
-/* Nonzero means allow type mismatches in conditional expressions;
- just make their values `void'. */
-
-extern int flag_cond_mismatch;
-
-/* Nonzero means don't recognize the keyword `asm'. */
-
-extern int flag_no_asm;
-
-/* Nonzero means warn about implicit declarations. */
-
-extern int warn_implicit;
-
-/* Nonzero means warn for all old-style non-prototype function decls. */
-
-extern int warn_strict_prototypes;
-
-/* Nonzero means warn about multiple (redundant) decls for the same single
- variable or function. */
-
-extern int warn_redundant_decls;
-
-/* Nonzero means warn about extern declarations of objects not at
- file-scope level and about *all* declarations of functions (whether
- extern or static) not at file-scope level. Note that we exclude
- implicit function declarations. To get warnings about those, use
- -Wimplicit. */
-
-extern int warn_nested_externs;
-
-/* Nonzero means warn about pointer casts that can drop a type qualifier
- from the pointer target type. */
-
-extern int warn_cast_qual;
-
-/* Nonzero means warn when casting a function call to a type that does
- not match the return type (e.g. (float)sqrt() or (anything*)malloc()
- when there is no previous declaration of sqrt or malloc. */
-
-extern int warn_bad_function_cast;
-
-/* Warn about traditional constructs whose meanings changed in ANSI C. */
-
-extern int warn_traditional;
-
-/* Warn about a subscript that has type char. */
-
-extern int warn_char_subscripts;
-
-/* Warn if main is suspicious. */
-
-extern int warn_main;
-
-/* Nonzero means to allow single precision math even if we're generally
- being traditional. */
-extern int flag_allow_single_precision;
-
-/* Warn if initializer is not completely bracketed. */
-
-extern int warn_missing_braces;
-
-/* Warn about comparison of signed and unsigned values. */
-
-extern int warn_sign_compare;
-
-/* Warn about testing equality of floating point numbers. */
-
-extern int warn_float_equal;
-
-/* Warn about multicharacter constants. */
-
-extern int warn_multichar;
-
/* Nonzero means we are reading code that came from a system header file. */
extern int system_header_p;
-/* Warn about implicit declarations. 1 = warning, 2 = error. */
-extern int mesg_implicit_function_declaration;
-
/* In c-decl.c */
-extern void finish_incomplete_decl PARAMS ((tree));
+extern void c_finish_incomplete_decl PARAMS ((tree));
-extern tree static_ctors;
-extern tree static_dtors;
+extern GTY(()) tree static_ctors;
+extern GTY(()) tree static_dtors;
#endif /* ! GCC_C_TREE_H */
diff --git a/contrib/gcc/c-typeck.c b/contrib/gcc/c-typeck.c
index 17e3144..21cc510 100644
--- a/contrib/gcc/c-typeck.c
+++ b/contrib/gcc/c-typeck.c
@@ -51,7 +51,7 @@ static int missing_braces_mentioned;
static int undeclared_variable_notice;
static tree qualify_type PARAMS ((tree, tree));
-static int comp_target_types PARAMS ((tree, tree));
+static int comp_target_types PARAMS ((tree, tree, int));
static int function_types_compatible_p PARAMS ((tree, tree));
static int type_lists_compatible_p PARAMS ((tree, tree));
static tree decl_constant_value_for_broken_optimization PARAMS ((tree));
@@ -73,7 +73,7 @@ static void push_array_bounds PARAMS ((int));
static int spelling_length PARAMS ((void));
static char *print_spelling PARAMS ((char *));
static void warning_init PARAMS ((const char *));
-static tree digest_init PARAMS ((tree, tree, int, int));
+static tree digest_init PARAMS ((tree, tree, int));
static void output_init_element PARAMS ((tree, tree, tree, int));
static void output_pending_init_elements PARAMS ((int));
static int set_designator PARAMS ((int));
@@ -99,7 +99,7 @@ require_complete_type (value)
if (COMPLETE_TYPE_P (type))
return value;
- incomplete_type_error (value, type);
+ c_incomplete_type_error (value, type);
return error_mark_node;
}
@@ -108,7 +108,7 @@ require_complete_type (value)
and TYPE is the type that was invalid. */
void
-incomplete_type_error (value, type)
+c_incomplete_type_error (value, type)
tree value;
tree type;
{
@@ -173,6 +173,28 @@ incomplete_type_error (value, type)
}
}
+/* Given a type, apply default promotions wrt unnamed function
+ arguments and return the new type. */
+
+tree
+c_type_promotes_to (type)
+ tree type;
+{
+ if (TYPE_MAIN_VARIANT (type) == float_type_node)
+ return double_type_node;
+
+ if (c_promoting_integer_type_p (type))
+ {
+ /* Preserve unsignedness if not really getting any wider. */
+ if (TREE_UNSIGNED (type)
+ && (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
+ return unsigned_type_node;
+ return integer_type_node;
+ }
+
+ return type;
+}
+
/* Return a variant of TYPE which has all the type qualifiers of LIKE
as well as those of TYPE. */
@@ -216,9 +238,9 @@ common_type (t1, t2)
/* Treat an enum type as the unsigned integer type of the same width. */
if (TREE_CODE (t1) == ENUMERAL_TYPE)
- t1 = type_for_size (TYPE_PRECISION (t1), 1);
+ t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1);
if (TREE_CODE (t2) == ENUMERAL_TYPE)
- t2 = type_for_size (TYPE_PRECISION (t2), 1);
+ t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1);
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
@@ -465,9 +487,9 @@ comptypes (type1, type2)
signedness. */
if (TREE_CODE (t1) == ENUMERAL_TYPE)
- t1 = type_for_size (TYPE_PRECISION (t1), TREE_UNSIGNED (t1));
+ t1 = c_common_type_for_size (TYPE_PRECISION (t1), TREE_UNSIGNED (t1));
if (TREE_CODE (t2) == ENUMERAL_TYPE)
- t2 = type_for_size (TYPE_PRECISION (t2), TREE_UNSIGNED (t2));
+ t2 = c_common_type_for_size (TYPE_PRECISION (t2), TREE_UNSIGNED (t2));
if (t1 == t2)
return 1;
@@ -546,7 +568,7 @@ comptypes (type1, type2)
}
case RECORD_TYPE:
- if (maybe_objc_comptypes (t1, t2, 0) == 1)
+ if (flag_objc && objc_comptypes (t1, t2, 0) == 1)
val = 1;
break;
@@ -557,16 +579,21 @@ comptypes (type1, type2)
}
/* Return 1 if TTL and TTR are pointers to types that are equivalent,
- ignoring their qualifiers. */
+ ignoring their qualifiers. REFLEXIVE is only used by ObjC - set it
+ to 1 or 0 depending if the check of the pointer types is meant to
+ be reflexive or not (typically, assignments are not reflexive,
+ while comparisons are reflexive).
+*/
static int
-comp_target_types (ttl, ttr)
+comp_target_types (ttl, ttr, reflexive)
tree ttl, ttr;
+ int reflexive;
{
int val;
- /* Give maybe_objc_comptypes a crack at letting these types through. */
- if ((val = maybe_objc_comptypes (ttl, ttr, 1)) >= 0)
+ /* Give objc_comptypes a crack at letting these types through. */
+ if ((val = objc_comptypes (ttl, ttr, reflexive)) >= 0)
return val;
val = comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ttl)),
@@ -658,12 +685,12 @@ type_lists_compatible_p (args1, args2)
So match anything that self-promotes. */
if (TREE_VALUE (args1) == 0)
{
- if (simple_type_promotes_to (TREE_VALUE (args2)) != NULL_TREE)
+ if (c_type_promotes_to (TREE_VALUE (args2)) != TREE_VALUE (args2))
return 0;
}
else if (TREE_VALUE (args2) == 0)
{
- if (simple_type_promotes_to (TREE_VALUE (args1)) != NULL_TREE)
+ if (c_type_promotes_to (TREE_VALUE (args1)) != TREE_VALUE (args1))
return 0;
}
else if (! (newval = comptypes (TYPE_MAIN_VARIANT (TREE_VALUE (args1)),
@@ -714,71 +741,6 @@ type_lists_compatible_p (args1, args2)
}
}
-/* Compute the value of the `sizeof' operator. */
-
-tree
-c_sizeof (type)
- tree type;
-{
- enum tree_code code = TREE_CODE (type);
- tree size;
-
- if (code == FUNCTION_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("sizeof applied to a function type");
- size = size_one_node;
- }
- else if (code == VOID_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("sizeof applied to a void type");
- size = size_one_node;
- }
- else if (code == ERROR_MARK)
- size = size_one_node;
- else if (!COMPLETE_TYPE_P (type))
- {
- error ("sizeof applied to an incomplete type");
- size = size_zero_node;
- }
- else
- /* Convert in case a char is more than one unit. */
- size = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
- size_int (TYPE_PRECISION (char_type_node)
- / BITS_PER_UNIT));
-
- /* SIZE will have an integer type with TYPE_IS_SIZETYPE set.
- TYPE_IS_SIZETYPE means that certain things (like overflow) will
- never happen. However, this node should really have type
- `size_t', which is just a typedef for an ordinary integer type. */
- return fold (build1 (NOP_EXPR, size_type_node, size));
-}
-
-tree
-c_sizeof_nowarn (type)
- tree type;
-{
- enum tree_code code = TREE_CODE (type);
- tree size;
-
- if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK)
- size = size_one_node;
- else if (!COMPLETE_TYPE_P (type))
- size = size_zero_node;
- else
- /* Convert in case a char is more than one unit. */
- size = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
- size_int (TYPE_PRECISION (char_type_node)
- / BITS_PER_UNIT));
-
- /* SIZE will have an integer type with TYPE_IS_SIZETYPE set.
- TYPE_IS_SIZETYPE means that certain things (like overflow) will
- never happen. However, this node should really have type
- `size_t', which is just a typedef for an ordinary integer type. */
- return fold (build1 (NOP_EXPR, size_type_node, size));
-}
-
/* Compute the size to increment a pointer by. */
tree
@@ -932,7 +894,7 @@ default_function_array_conversion (exp)
is not the target type of the type of the ADDR_EXPR itself.
Question is, can this lossage be avoided? */
adr = build1 (ADDR_EXPR, ptrtype, exp);
- if (mark_addressable (exp) == 0)
+ if (!c_mark_addressable (exp))
return error_mark_node;
TREE_CONSTANT (adr) = staticp (exp);
TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */
@@ -994,12 +956,11 @@ default_conversion (exp)
but convert wide enums to something wider. */
if (code == ENUMERAL_TYPE)
{
- type = type_for_size (MAX (TYPE_PRECISION (type),
- TYPE_PRECISION (integer_type_node)),
- ((flag_traditional
- || (TYPE_PRECISION (type)
- >= TYPE_PRECISION (integer_type_node)))
- && TREE_UNSIGNED (type)));
+ type = c_common_type_for_size (MAX (TYPE_PRECISION (type),
+ TYPE_PRECISION (integer_type_node)),
+ ((TYPE_PRECISION (type)
+ >= TYPE_PRECISION (integer_type_node))
+ && TREE_UNSIGNED (type)));
return convert (type, exp);
}
@@ -1010,26 +971,18 @@ default_conversion (exp)
c_promoting_integer_type_p, otherwise leave it alone. */
&& 0 > compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)),
TYPE_PRECISION (integer_type_node)))
- return convert (flag_traditional && TREE_UNSIGNED (type)
- ? unsigned_type_node : integer_type_node,
- exp);
+ return convert (integer_type_node, exp);
if (c_promoting_integer_type_p (type))
{
- /* Traditionally, unsignedness is preserved in default promotions.
- Also preserve unsignedness if not really getting any wider. */
+ /* Preserve unsignedness if not really getting any wider. */
if (TREE_UNSIGNED (type)
- && (flag_traditional
- || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
+ && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
return convert (unsigned_type_node, exp);
return convert (integer_type_node, exp);
}
- if (flag_traditional && !flag_allow_single_precision
- && TYPE_MAIN_VARIANT (type) == float_type_node)
- return convert (double_type_node, exp);
-
if (code == VOID_TYPE)
{
error ("void value not ignored as it ought to be");
@@ -1172,7 +1125,7 @@ build_component_ref (datum, component)
{
if (!COMPLETE_TYPE_P (type))
{
- incomplete_type_error (NULL_TREE, type);
+ c_incomplete_type_error (NULL_TREE, type);
return error_mark_node;
}
@@ -1191,7 +1144,7 @@ build_component_ref (datum, component)
end does it - by giving the anonymous entities each a
separate name and type, and then have build_component_ref
recursively call itself. We can't do that here. */
- for (; field; field = TREE_CHAIN (field))
+ do
{
tree subdatum = TREE_VALUE (field);
@@ -1208,7 +1161,10 @@ build_component_ref (datum, component)
warn_deprecated_use (subdatum);
datum = ref;
+
+ field = TREE_CHAIN (field);
}
+ while (field);
return ref;
}
@@ -1326,7 +1282,7 @@ build_array_ref (array, index)
|| (COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (array)))
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))) != INTEGER_CST))
{
- if (mark_addressable (array) == 0)
+ if (!c_mark_addressable (array))
return error_mark_node;
}
/* An array that is indexed by a constant value which is not within
@@ -1337,7 +1293,7 @@ build_array_ref (array, index)
&& TYPE_VALUES (TREE_TYPE (array))
&& ! int_fits_type_p (index, TYPE_VALUES (TREE_TYPE (array))))
{
- if (mark_addressable (array) == 0)
+ if (!c_mark_addressable (array))
return error_mark_node;
}
@@ -1349,7 +1305,7 @@ build_array_ref (array, index)
if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo))
pedwarn ("ISO C forbids subscripting `register' array");
else if (! flag_isoc99 && ! lvalue_p (foo))
- pedwarn ("ISO C89 forbids subscripting non-lvalue array");
+ pedwarn ("ISO C90 forbids subscripting non-lvalue array");
}
type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
@@ -1502,6 +1458,17 @@ build_external_ref (id, fun)
ref = DECL_INITIAL (ref);
TREE_CONSTANT (ref) = 1;
}
+ else if (current_function_decl != 0
+ && DECL_CONTEXT (current_function_decl) != 0
+ && (TREE_CODE (ref) == VAR_DECL
+ || TREE_CODE (ref) == PARM_DECL
+ || TREE_CODE (ref) == FUNCTION_DECL))
+ {
+ tree context = decl_function_context (ref);
+
+ if (context != 0 && context != current_function_decl)
+ DECL_NONLOCAL (ref) = 1;
+ }
return ref;
}
@@ -1564,10 +1531,9 @@ build_function_call (function, params)
coerced_params
= convert_arguments (TYPE_ARG_TYPES (fntype), params, name, fundecl);
- /* Check for errors in format strings. */
+ /* Check that the arguments to the function are valid. */
- if (warn_format)
- check_function_format (NULL, TYPE_ATTRIBUTES (fntype), coerced_params);
+ check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params);
/* Recognize certain built-in functions so we can make tree-codes
other than CALL_EXPR. We do this when it enables fold-const.c
@@ -2011,7 +1977,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
/* Subtraction of two similar pointers.
We must subtract them as integers, then divide by object size. */
if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
- && comp_target_types (type0, type1))
+ && comp_target_types (type0, type1, 1))
return pointer_diff (op0, op1);
/* Handle pointer minus int. Just like pointer plus int. */
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
@@ -2035,9 +2001,9 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
warning ("division by zero");
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
- || code0 == COMPLEX_TYPE)
+ || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == COMPLEX_TYPE))
+ || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
{
if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
resultcode = RDIV_EXPR;
@@ -2060,6 +2026,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
case BIT_XOR_EXPR:
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
shorten = -1;
+ else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+ common = 1;
break;
case TRUNC_MOD_EXPR:
@@ -2094,8 +2062,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
but that does not mean the operands should be
converted to ints! */
result_type = integer_type_node;
- op0 = truthvalue_conversion (op0);
- op1 = truthvalue_conversion (op1);
+ op0 = c_common_truthvalue_conversion (op0);
+ op1 = c_common_truthvalue_conversion (op1);
converted = 1;
}
break;
@@ -2121,18 +2089,14 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
}
}
- /* Use the type of the value to be shifted.
- This is what most traditional C compilers do. */
+ /* Use the type of the value to be shifted. */
result_type = type0;
- /* Unless traditional, convert the shift-count to an integer,
- regardless of size of value being shifted. */
- if (! flag_traditional)
- {
- if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
- /* Avoid converting op1 to result_type later. */
- converted = 1;
- }
+ /* 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);
+ /* Avoid converting op1 to result_type later. */
+ converted = 1;
}
break;
@@ -2148,18 +2112,14 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
warning ("left shift count >= width of type");
}
- /* Use the type of the value to be shifted.
- This is what most traditional C compilers do. */
+ /* Use the type of the value to be shifted. */
result_type = type0;
- /* Unless traditional, convert the shift-count to an integer,
- regardless of size of value being shifted. */
- if (! flag_traditional)
- {
- if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
- /* Avoid converting op1 to result_type later. */
- converted = 1;
- }
+ /* 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);
+ /* Avoid converting op1 to result_type later. */
+ converted = 1;
}
break;
@@ -2175,18 +2135,14 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
warning ("shift count >= width of type");
}
- /* Use the type of the value to be shifted.
- This is what most traditional C compilers do. */
+ /* Use the type of the value to be shifted. */
result_type = type0;
- /* Unless traditional, convert the shift-count to an integer,
- regardless of size of value being shifted. */
- if (! flag_traditional)
- {
- if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
- /* Avoid converting op1 to result_type later. */
- converted = 1;
- }
+ /* 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);
+ /* Avoid converting op1 to result_type later. */
+ converted = 1;
}
break;
@@ -2198,9 +2154,11 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
but don't convert the args to int! */
build_type = integer_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
- || code0 == COMPLEX_TYPE)
+ || code0 == COMPLEX_TYPE
+ || code0 == VECTOR_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == COMPLEX_TYPE))
+ || code1 == COMPLEX_TYPE
+ || code1 == VECTOR_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
@@ -2209,7 +2167,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
/* Anything compares with void *. void * compares with anything.
Otherwise, the targets must be compatible
and both must be object or both incomplete. */
- if (comp_target_types (type0, type1))
+ if (comp_target_types (type0, type1, 1))
result_type = common_type (type0, type1);
else if (VOID_TYPE_P (tt0))
{
@@ -2240,14 +2198,12 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
- if (! flag_traditional)
- pedwarn ("comparison between pointer and integer");
+ pedwarn ("comparison between pointer and integer");
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
- if (! flag_traditional)
- pedwarn ("comparison between pointer and integer");
+ pedwarn ("comparison between pointer and integer");
}
break;
@@ -2258,7 +2214,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
shorten = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
- if (comp_target_types (type0, type1))
+ if (comp_target_types (type0, type1, 1))
{
result_type = common_type (type0, type1);
if (pedantic
@@ -2283,7 +2239,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
- if (comp_target_types (type0, type1))
+ if (comp_target_types (type0, type1, 1))
{
result_type = common_type (type0, type1);
if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
@@ -2316,14 +2272,12 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
- if (! flag_traditional)
- pedwarn ("comparison between pointer and integer");
+ pedwarn ("comparison between pointer and integer");
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
- if (! flag_traditional)
- pedwarn ("comparison between pointer and integer");
+ pedwarn ("comparison between pointer and integer");
}
break;
@@ -2347,9 +2301,11 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
break;
}
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
+ || code0 == VECTOR_TYPE)
&&
- (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
+ (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
+ || code1 == VECTOR_TYPE))
{
int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
@@ -2411,22 +2367,24 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
&& unsigned0 == unsigned1
&& (unsigned0 || !uns))
result_type
- = signed_or_unsigned_type (unsigned0,
- common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
+ = c_common_signed_or_unsigned_type
+ (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
else if (TREE_CODE (arg0) == INTEGER_CST
&& (unsigned1 || !uns)
&& (TYPE_PRECISION (TREE_TYPE (arg1))
< TYPE_PRECISION (result_type))
- && (type = signed_or_unsigned_type (unsigned1,
- TREE_TYPE (arg1)),
+ && (type
+ = c_common_signed_or_unsigned_type (unsigned1,
+ TREE_TYPE (arg1)),
int_fits_type_p (arg0, type)))
result_type = type;
else if (TREE_CODE (arg1) == INTEGER_CST
&& (unsigned0 || !uns)
&& (TYPE_PRECISION (TREE_TYPE (arg0))
< TYPE_PRECISION (result_type))
- && (type = signed_or_unsigned_type (unsigned0,
- TREE_TYPE (arg0)),
+ && (type
+ = c_common_signed_or_unsigned_type (unsigned0,
+ TREE_TYPE (arg0)),
int_fits_type_p (arg1, type)))
result_type = type;
}
@@ -2452,7 +2410,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
{
/* Do an unsigned shift if the operand was zero-extended. */
result_type
- = signed_or_unsigned_type (unsigned_arg, TREE_TYPE (arg0));
+ = c_common_signed_or_unsigned_type (unsigned_arg,
+ TREE_TYPE (arg0));
/* Convert value-to-be-shifted to that type. */
if (TREE_TYPE (op0) != result_type)
op0 = convert (result_type, op0);
@@ -2523,22 +2482,24 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
constant expression involving such literals or a
conditional expression involving such literals)
and it is non-negative. */
- if (tree_expr_nonnegative_p (sop))
+ if (c_tree_expr_nonnegative_p (sop))
/* OK */;
/* Do not warn if the comparison is an equality operation,
the unsigned quantity is an integral constant, and it
would fit in the result if the result were signed. */
else if (TREE_CODE (uop) == INTEGER_CST
&& (resultcode == EQ_EXPR || resultcode == NE_EXPR)
- && int_fits_type_p (uop, signed_type (result_type)))
+ && int_fits_type_p
+ (uop, c_common_signed_type (result_type)))
/* OK */;
/* Do not warn if the unsigned quantity is an enumeration
constant and its maximum value would fit in the result
if the result were signed. */
else if (TREE_CODE (uop) == INTEGER_CST
&& TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE
- && int_fits_type_p (TYPE_MAX_VALUE (TREE_TYPE(uop)),
- signed_type (result_type)))
+ && int_fits_type_p
+ (TYPE_MAX_VALUE (TREE_TYPE(uop)),
+ c_common_signed_type (result_type)))
/* OK */;
else
warning ("comparison between signed and unsigned");
@@ -2637,6 +2598,27 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
}
}
+
+/* Return true if `t' is known to be non-negative. */
+
+int
+c_tree_expr_nonnegative_p (t)
+ tree t;
+{
+ if (TREE_CODE (t) == STMT_EXPR)
+ {
+ t=COMPOUND_BODY (STMT_EXPR_STMT (t));
+
+ /* Find the last statement in the chain, ignoring the final
+ * scope statement */
+ while (TREE_CHAIN (t) != NULL_TREE
+ && TREE_CODE (TREE_CHAIN (t)) != SCOPE_STMT)
+ t=TREE_CHAIN (t);
+ return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
+ }
+ return tree_expr_nonnegative_p (t);
+}
+
/* Return a tree for the difference of pointers OP0 and OP1.
The resulting tree has type int. */
@@ -2758,11 +2740,13 @@ build_unary_op (code, xarg, flag)
}
else if (!noconvert)
arg = default_conversion (arg);
+ arg = non_lvalue (arg);
break;
case NEGATE_EXPR:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
- || typecode == COMPLEX_TYPE))
+ || typecode == COMPLEX_TYPE
+ || typecode == VECTOR_TYPE))
{
error ("wrong type argument to unary minus");
return error_mark_node;
@@ -2772,7 +2756,12 @@ build_unary_op (code, xarg, flag)
break;
case BIT_NOT_EXPR:
- if (typecode == COMPLEX_TYPE)
+ if (typecode == INTEGER_TYPE || typecode == VECTOR_TYPE)
+ {
+ if (!noconvert)
+ arg = default_conversion (arg);
+ }
+ else if (typecode == COMPLEX_TYPE)
{
code = CONJ_EXPR;
if (pedantic)
@@ -2780,13 +2769,11 @@ build_unary_op (code, xarg, flag)
if (!noconvert)
arg = default_conversion (arg);
}
- else if (typecode != INTEGER_TYPE)
+ else
{
error ("wrong type argument to bit-complement");
return error_mark_node;
}
- else if (!noconvert)
- arg = default_conversion (arg);
break;
case ABS_EXPR:
@@ -2822,7 +2809,7 @@ build_unary_op (code, xarg, flag)
error ("wrong type argument to unary exclamation mark");
return error_mark_node;
}
- arg = truthvalue_conversion (arg);
+ arg = c_common_truthvalue_conversion (arg);
return invert_truthvalue (arg);
case NOP_EXPR:
@@ -2888,6 +2875,9 @@ build_unary_op (code, xarg, flag)
tree inc;
tree result_type = TREE_TYPE (arg);
+ arg = get_unwidened (arg, 0);
+ argtype = TREE_TYPE (arg);
+
/* Compute the increment. */
if (typecode == POINTER_TYPE)
@@ -2916,9 +2906,6 @@ build_unary_op (code, xarg, flag)
else
inc = integer_one_node;
- arg = get_unwidened (arg, 0);
- argtype = TREE_TYPE (arg);
-
inc = convert (argtype, inc);
/* Handle incrementing a cast-expression. */
@@ -3012,7 +2999,7 @@ build_unary_op (code, xarg, flag)
/* For &x[y], return x+y */
if (TREE_CODE (arg) == ARRAY_REF)
{
- if (mark_addressable (TREE_OPERAND (arg, 0)) == 0)
+ if (!c_mark_addressable (TREE_OPERAND (arg, 0)))
return error_mark_node;
return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1), 1);
@@ -3067,7 +3054,7 @@ build_unary_op (code, xarg, flag)
argtype = build_pointer_type (argtype);
- if (mark_addressable (arg) == 0)
+ if (!c_mark_addressable (arg))
return error_mark_node;
{
@@ -3286,13 +3273,14 @@ readonly_warning (arg, msgid)
/* Mark EXP saying that we need to be able to take the
address of it; it should not be allocated in a register.
- Value is 1 if successful. */
+ Returns true if successful. */
-int
-mark_addressable (exp)
+bool
+c_mark_addressable (exp)
tree exp;
{
tree x = exp;
+
while (1)
switch (TREE_CODE (x))
{
@@ -3301,7 +3289,7 @@ mark_addressable (exp)
{
error ("cannot take address of bit-field `%s'",
IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (x, 1))));
- return 0;
+ return false;
}
/* ... fall through ... */
@@ -3316,7 +3304,7 @@ mark_addressable (exp)
case COMPOUND_LITERAL_EXPR:
case CONSTRUCTOR:
TREE_ADDRESSABLE (x) = 1;
- return 1;
+ return true;
case VAR_DECL:
case CONST_DECL:
@@ -3329,7 +3317,7 @@ mark_addressable (exp)
{
error ("global register variable `%s' used in nested function",
IDENTIFIER_POINTER (DECL_NAME (x)));
- return 0;
+ return false;
}
pedwarn ("register variable `%s' used in nested function",
IDENTIFIER_POINTER (DECL_NAME (x)));
@@ -3340,7 +3328,7 @@ mark_addressable (exp)
{
error ("address of global register variable `%s' requested",
IDENTIFIER_POINTER (DECL_NAME (x)));
- return 0;
+ return false;
}
/* If we are making this addressable due to its having
@@ -3351,13 +3339,13 @@ mark_addressable (exp)
else if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (x)))
{
error ("cannot put object with volatile field into register");
- return 0;
+ return false;
}
pedwarn ("address of register variable `%s' requested",
IDENTIFIER_POINTER (DECL_NAME (x)));
}
- put_var_into_stack (x);
+ put_var_into_stack (x, /*rescan=*/true);
/* drops in */
case FUNCTION_DECL:
@@ -3368,7 +3356,7 @@ mark_addressable (exp)
#endif
default:
- return 1;
+ return true;
}
}
@@ -3385,7 +3373,7 @@ build_conditional_expr (ifexp, op1, op2)
tree result_type = NULL;
tree orig_op1 = op1, orig_op2 = op2;
- ifexp = truthvalue_conversion (default_conversion (ifexp));
+ ifexp = c_common_truthvalue_conversion (default_conversion (ifexp));
#if 0 /* Produces wrong result if within sizeof. */
/* Don't promote the operands separately if they promote
@@ -3458,8 +3446,8 @@ build_conditional_expr (ifexp, op1, op2)
/* Do not warn if the signed quantity is an unsuffixed
integer literal (or some static constant expression
involving such literals) and it is non-negative. */
- else if ((unsigned_op2 && tree_expr_nonnegative_p (op1))
- || (unsigned_op1 && tree_expr_nonnegative_p (op2)))
+ else if ((unsigned_op2 && c_tree_expr_nonnegative_p (op1))
+ || (unsigned_op1 && c_tree_expr_nonnegative_p (op2)))
/* OK */;
else
warning ("signed and unsigned type in conditional expression");
@@ -3474,7 +3462,7 @@ build_conditional_expr (ifexp, op1, op2)
}
else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
{
- if (comp_target_types (type1, type2))
+ 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)
@@ -3629,7 +3617,12 @@ build_c_cast (type, expr)
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
- type = TYPE_MAIN_VARIANT (type);
+
+ /* The ObjC front-end uses TYPE_MAIN_VARIANT to tie together types differing
+ only in <protocol> qualifications. But when constructing cast expressions,
+ the protocols do matter and must be kept around. */
+ if (!flag_objc || !objc_is_id (type))
+ type = TYPE_MAIN_VARIANT (type);
#if 0
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
@@ -3685,8 +3678,7 @@ build_c_cast (type, expr)
else
name = "";
t = digest_init (type, build (CONSTRUCTOR, type, NULL_TREE,
- build_tree_list (field, value)),
- 0, 0);
+ build_tree_list (field, value)), 0);
TREE_CONSTANT (t) = TREE_CONSTANT (value);
return t;
}
@@ -3781,6 +3773,23 @@ build_c_cast (type, expr)
&& !TREE_CONSTANT (value))
warning ("cast to pointer from integer of different size");
+ if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (otype) == POINTER_TYPE
+ && TREE_CODE (expr) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (expr, 0))
+ && flag_strict_aliasing && warn_strict_aliasing
+ && !VOID_TYPE_P (TREE_TYPE (type)))
+ {
+ /* Casting the address of a decl to non void pointer. Warn
+ if the cast breaks type based aliasing. */
+ if (!COMPLETE_TYPE_P (TREE_TYPE (type)))
+ warning ("type-punning to incomplete type might break strict-aliasing rules");
+ else if (!alias_sets_conflict_p
+ (get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0))),
+ get_alias_set (TREE_TYPE (type))))
+ warning ("dereferencing type-punned pointer will break strict-aliasing rules");
+ }
+
ovalue = value;
value = convert (type, value);
@@ -4037,9 +4046,11 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
{
overflow_warning (rhs);
- /* Check for Objective-C protocols. This will issue a warning if
- there are protocol violations. No need to use the return value. */
- maybe_objc_comptypes (type, rhstype, 0);
+ /* Check for Objective-C protocols. This will automatically
+ issue a warning if there are protocol violations. No need to
+ use the return value. */
+ if (flag_objc)
+ objc_comptypes (type, rhstype, 0);
return rhs;
}
@@ -4054,7 +4065,12 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
if (codel == REFERENCE_TYPE
&& comptypes (TREE_TYPE (type), TREE_TYPE (rhs)) == 1)
{
- if (mark_addressable (rhs) == 0)
+ if (!lvalue_p (rhs))
+ {
+ error ("cannot pass rvalue to reference parameter");
+ return error_mark_node;
+ }
+ if (!c_mark_addressable (rhs))
return error_mark_node;
rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs);
@@ -4073,7 +4089,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
|| codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
|| codel == BOOLEAN_TYPE)
- && (coder == INTEGER_TYPE || coder == REAL_TYPE
+ && (coder == INTEGER_TYPE || coder == REAL_TYPE
|| coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
|| coder == BOOLEAN_TYPE))
return convert_and_check (type, rhs);
@@ -4107,7 +4123,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
Meanwhile, the lhs target must have all the qualifiers of
the rhs. */
if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
- || comp_target_types (memb_type, rhstype))
+ || comp_target_types (memb_type, rhstype, 0))
{
/* If this type won't generate any warnings, use it. */
if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
@@ -4173,7 +4189,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
/* Conversions among pointers */
else if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE)
- && (coder == POINTER_TYPE || coder == REFERENCE_TYPE))
+ && (coder == codel))
{
tree ttl = TREE_TYPE (type);
tree ttr = TREE_TYPE (rhstype);
@@ -4182,9 +4198,9 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
and vice versa; otherwise, targets must be the same.
Meanwhile, the lhs target must have all the qualifiers of the rhs. */
if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
- || comp_target_types (type, rhstype)
- || (unsigned_type (TYPE_MAIN_VARIANT (ttl))
- == unsigned_type (TYPE_MAIN_VARIANT (ttr))))
+ || comp_target_types (type, rhstype, 0)
+ || (c_common_unsigned_type (TYPE_MAIN_VARIANT (ttl))
+ == c_common_unsigned_type (TYPE_MAIN_VARIANT (ttr))))
{
if (pedantic
&& ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
@@ -4207,7 +4223,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
/* If this is not a case of ignoring a mismatch in signedness,
no warning. */
else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
- || comp_target_types (type, rhstype))
+ || comp_target_types (type, rhstype, 0))
;
/* If there is a mismatch, do warn. */
else if (pedantic)
@@ -4262,7 +4278,7 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
{
if (funname)
{
- tree selector = maybe_building_objc_message_expr ();
+ tree selector = objc_message_selector ();
if (selector && parmnum > 2)
error ("incompatible type for argument %d of `%s'",
@@ -4307,7 +4323,8 @@ c_convert_parm_for_inlining (parm, value, fn)
/* Print a warning using MSGID.
It gets OPNAME as its one parameter.
- If OPNAME is null, it is replaced by "passing arg ARGNUM of `FUNCTION'".
+ if OPNAME is null and ARGNUM is 0, it is replaced by "passing arg of `FUNCTION'".
+ Otherwise if OPNAME is null, it is replaced by "passing arg ARGNUM of `FUNCTION'".
FUNCTION and ARGNUM are handled specially if we are building an
Objective-C selector. */
@@ -4320,7 +4337,7 @@ warn_for_assignment (msgid, opname, function, argnum)
{
if (opname == 0)
{
- tree selector = maybe_building_objc_message_expr ();
+ tree selector = objc_message_selector ();
char * new_opname;
if (selector && argnum > 2)
@@ -4328,7 +4345,27 @@ warn_for_assignment (msgid, opname, function, argnum)
function = selector;
argnum -= 2;
}
- if (function)
+ if (argnum == 0)
+ {
+ if (function)
+ {
+ /* Function name is known; supply it. */
+ const char *const argstring = _("passing arg of `%s'");
+ new_opname = (char *) alloca (IDENTIFIER_LENGTH (function)
+ + strlen (argstring) + 1
+ + 1);
+ sprintf (new_opname, argstring,
+ IDENTIFIER_POINTER (function));
+ }
+ else
+ {
+ /* Function name unknown (call through ptr). */
+ const char *const argnofun = _("passing arg of pointer to function");
+ new_opname = (char *) alloca (strlen (argnofun) + 1 + 1);
+ sprintf (new_opname, argnofun);
+ }
+ }
+ else if (function)
{
/* Function name is known; supply it. */
const char *const argstring = _("passing arg %d of `%s'");
@@ -4395,8 +4432,7 @@ store_init_value (decl, init)
/* Digest the specified initializer into an expression. */
- value = digest_init (type, init, TREE_STATIC (decl),
- TREE_STATIC (decl) || (pedantic && !flag_isoc99));
+ value = digest_init (type, init, TREE_STATIC (decl));
/* Store the expression if valid; else report error. */
@@ -4496,15 +4532,6 @@ static int spelling_size; /* Size of the spelling stack. */
#define SPELLING_DEPTH() (spelling - spelling_base)
#define RESTORE_SPELLING_DEPTH(DEPTH) (spelling = spelling_base + (DEPTH))
-/* Save and restore the spelling stack around arbitrary C code. */
-
-#define SAVE_SPELLING_DEPTH(code) \
-{ \
- int __depth = SPELLING_DEPTH (); \
- code; \
- RESTORE_SPELLING_DEPTH (__depth); \
-}
-
/* Push an element on the spelling stack with type KIND and assign VALUE
to MEMBER. */
@@ -4657,14 +4684,13 @@ warning_init (msgid)
/* Digest the parser output INIT as an initializer for type TYPE.
Return a C expression of type TYPE to represent the initial value.
- The arguments REQUIRE_CONSTANT and CONSTRUCTOR_CONSTANT request errors
- if non-constant initializers or elements are seen. CONSTRUCTOR_CONSTANT
- applies only to elements of constructors. */
+ REQUIRE_CONSTANT requests an error if non-constant initializers or
+ elements are seen. */
static tree
-digest_init (type, init, require_constant, constructor_constant)
+digest_init (type, init, require_constant)
tree type, init;
- int require_constant, constructor_constant;
+ int require_constant;
{
enum tree_code code = TREE_CODE (type);
tree inside_init = init;
@@ -4843,44 +4869,6 @@ digest_init (type, init, require_constant, constructor_constant)
return error_mark_node;
}
- /* Traditionally, you can write struct foo x = 0;
- and it initializes the first element of x to 0. */
- if (flag_traditional)
- {
- tree top = 0, prev = 0, otype = type;
- while (TREE_CODE (type) == RECORD_TYPE
- || TREE_CODE (type) == ARRAY_TYPE
- || TREE_CODE (type) == QUAL_UNION_TYPE
- || TREE_CODE (type) == UNION_TYPE)
- {
- tree temp = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
- if (prev == 0)
- top = temp;
- else
- TREE_OPERAND (prev, 1) = build_tree_list (NULL_TREE, temp);
- prev = temp;
- if (TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
- else if (TYPE_FIELDS (type))
- type = TREE_TYPE (TYPE_FIELDS (type));
- else
- {
- error_init ("invalid initializer");
- return error_mark_node;
- }
- }
-
- if (otype != type)
- {
- TREE_OPERAND (prev, 1)
- = build_tree_list (NULL_TREE,
- digest_init (type, init, require_constant,
- constructor_constant));
- return top;
- }
- else
- return error_mark_node;
- }
error_init ("invalid initializer");
return error_mark_node;
}
@@ -5240,7 +5228,7 @@ really_start_incremental_init (type)
constructor_max_index = build_int_2 (-1, -1);
/* constructor_max_index needs to be an INTEGER_CST. Attempts
- to initialize VLAs will cause an proper error; avoid tree
+ to initialize VLAs will cause a proper error; avoid tree
checking errors as well by setting a safe value. */
if (constructor_max_index
&& TREE_CODE (constructor_max_index) != INTEGER_CST)
@@ -5260,7 +5248,7 @@ really_start_incremental_init (type)
/* Vectors are like simple fixed-size arrays. */
constructor_max_index =
build_int_2 (TYPE_VECTOR_SUBPARTS (constructor_type) - 1, 0);
- constructor_index = convert (bitsizetype, integer_zero_node);
+ constructor_index = convert (bitsizetype, bitsize_zero_node);
constructor_unfilled_index = constructor_index;
}
else
@@ -5292,6 +5280,7 @@ push_init_level (implicit)
&& constructor_fields == 0)
process_init_element (pop_init_level (1));
else if (TREE_CODE (constructor_type) == ARRAY_TYPE
+ && constructor_max_index
&& tree_int_cst_lt (constructor_max_index, constructor_index))
process_init_element (pop_init_level (1));
else
@@ -5430,7 +5419,7 @@ push_init_level (implicit)
constructor_max_index = build_int_2 (-1, -1);
/* constructor_max_index needs to be an INTEGER_CST. Attempts
- to initialize VLAs will cause an proper error; avoid tree
+ to initialize VLAs will cause a proper error; avoid tree
checking errors as well by setting a safe value. */
if (constructor_max_index
&& TREE_CODE (constructor_max_index) != INTEGER_CST)
@@ -5619,7 +5608,7 @@ pop_init_level (implicit)
}
/* Common handling for both array range and field name designators.
- ARRAY argument is non-zero for array ranges. Returns zero for success. */
+ ARRAY argument is nonzero for array ranges. Returns zero for success. */
static int
set_designator (array)
@@ -6277,8 +6266,7 @@ output_init_element (value, type, field, pending)
|| TREE_CHAIN (field)))))
return;
- value = digest_init (type, value, require_constant_value,
- require_constant_elements);
+ value = digest_init (type, value, require_constant_value);
if (value == error_mark_node)
{
constructor_erroneous = 1;
@@ -6889,12 +6877,9 @@ simple_asm_stmt (expr)
{
tree stmt;
- if (TREE_CHAIN (expr))
- expr = combine_strings (expr);
-
/* Simple asm statements are treated as volatile. */
stmt = add_stmt (build_stmt (ASM_STMT, ridpointers[(int) RID_VOLATILE],
- expr, NULL_TREE, NULL_TREE, NULL_TREE));
+ expr, NULL_TREE, NULL_TREE, NULL_TREE));
ASM_INPUT_P (stmt) = 1;
return stmt;
}
@@ -6916,8 +6901,6 @@ build_asm_stmt (cv_qualifier, string, outputs, inputs, clobbers)
{
tree tail;
- if (TREE_CHAIN (string))
- string = combine_strings (string);
if (TREE_CODE (string) != STRING_CST)
{
error ("asm template is not a string constant");
@@ -6994,7 +6977,11 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
/* Record the contents of OUTPUTS before it is modified. */
for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
- o[i] = TREE_VALUE (tail);
+ {
+ o[i] = TREE_VALUE (tail);
+ if (o[i] == error_mark_node)
+ return;
+ }
/* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of
OUTPUTS some trees for where the values were actually stored. */
diff --git a/contrib/gcc/caller-save.c b/contrib/gcc/caller-save.c
index 87a13dc..b7e3cea 100644
--- a/contrib/gcc/caller-save.c
+++ b/contrib/gcc/caller-save.c
@@ -115,6 +115,9 @@ init_caller_save ()
rtx address;
int i, j;
enum machine_mode mode;
+ rtx savepat, restpat;
+ rtx test_reg, test_mem;
+ rtx saveinsn, restinsn;
/* First find all the registers that we need to deal with and all
the modes that they can have. If we can't find a mode to use,
@@ -179,22 +182,35 @@ init_caller_save ()
address = addr_reg;
/* Next we try to form an insn to save and restore the register. We
- see if such an insn is recognized and meets its constraints. */
+ see if such an insn is recognized and meets its constraints.
- start_sequence ();
+ To avoid lots of unnecessary RTL allocation, we construct all the RTL
+ once, then modify the memory and register operands in-place. */
+
+ test_reg = gen_rtx_REG (VOIDmode, 0);
+ test_mem = gen_rtx_MEM (VOIDmode, address);
+ savepat = gen_rtx_SET (VOIDmode, test_mem, test_reg);
+ restpat = gen_rtx_SET (VOIDmode, test_reg, test_mem);
+
+ saveinsn = gen_rtx_INSN (VOIDmode, 0, 0, 0, 0, 0, savepat, -1, 0, 0);
+ restinsn = gen_rtx_INSN (VOIDmode, 0, 0, 0, 0, 0, restpat, -1, 0, 0);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
for (mode = 0 ; mode < MAX_MACHINE_MODE; mode++)
if (HARD_REGNO_MODE_OK (i, mode))
{
- rtx mem = gen_rtx_MEM (mode, address);
- rtx reg = gen_rtx_REG (mode, i);
- rtx savepat = gen_rtx_SET (VOIDmode, mem, reg);
- rtx restpat = gen_rtx_SET (VOIDmode, reg, mem);
- rtx saveinsn = emit_insn (savepat);
- rtx restinsn = emit_insn (restpat);
int ok;
+ /* Update the register number and modes of the register
+ and memory operand. */
+ REGNO (test_reg) = i;
+ PUT_MODE (test_reg, mode);
+ PUT_MODE (test_mem, mode);
+
+ /* Force re-recognition of the modified insns. */
+ INSN_CODE (saveinsn) = -1;
+ INSN_CODE (restinsn) = -1;
+
reg_save_code[i][mode] = recog_memoized (saveinsn);
reg_restore_code[i][mode] = recog_memoized (restinsn);
@@ -221,6 +237,7 @@ init_caller_save ()
reg_save_code[i][mode] = -1;
reg_restore_code[i][mode] = -1;
}
+
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
for (j = 1; j <= MOVE_MAX_WORDS; j++)
if (reg_save_code [i][regno_save_mode[i][j]] == -1)
@@ -232,8 +249,6 @@ init_caller_save ()
SET_HARD_REG_BIT (call_fixed_reg_set, i);
}
}
-
- end_sequence ();
}
/* Initialize save areas by showing that we haven't allocated any yet. */
diff --git a/contrib/gcc/calls.c b/contrib/gcc/calls.c
index 9a059a0..b5a5123 100644
--- a/contrib/gcc/calls.c
+++ b/contrib/gcc/calls.c
@@ -1,6 +1,6 @@
/* Convert function calls to rtl insns, for GNU C compiler.
Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -33,6 +33,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tm_p.h"
#include "timevar.h"
#include "sbitmap.h"
+#include "langhooks.h"
+#include "target.h"
+#include "except.h"
#if !defined FUNCTION_OK_FOR_SIBCALL
#define FUNCTION_OK_FOR_SIBCALL(DECL) 1
@@ -91,7 +94,7 @@ struct arg_data
/* Number of registers to use. 0 means put the whole arg in registers.
Also 0 if not passed in registers. */
int partial;
- /* Non-zero if argument must be passed on stack.
+ /* Nonzero if argument must be passed on stack.
Note that some arguments may be passed on the stack
even though pass_on_stack is zero, just because FUNCTION_ARG says so.
pass_on_stack identifies arguments that *cannot* go in registers. */
@@ -126,7 +129,7 @@ struct arg_data
struct args_size alignment_pad;
};
-/* A vector of one char per byte of stack space. A byte if non-zero if
+/* A vector of one char per byte of stack space. A byte if nonzero if
the corresponding stack location has been used.
This vector is used to prevent a function call within an argument from
clobbering any stack already set up. */
@@ -225,6 +228,7 @@ static int check_sibcall_argument_overlap PARAMS ((rtx, struct arg_data *));
static int combine_pending_stack_adjustment_and_call
PARAMS ((int, struct args_size *, int));
+static tree fix_unsafe_tree PARAMS ((tree));
#ifdef REG_PARM_STACK_SPACE
static rtx save_fixed_argument_area PARAMS ((int, rtx, int *, int *));
@@ -614,6 +618,8 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
if (ecf_flags & ECF_NOTHROW)
REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, const0_rtx,
REG_NOTES (call_insn));
+ else
+ note_eh_region_may_contain_throw ();
if (ecf_flags & ECF_NORETURN)
REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_NORETURN, const0_rtx,
@@ -799,6 +805,21 @@ setjmp_call_p (fndecl)
return special_function_p (fndecl, 0) & ECF_RETURNS_TWICE;
}
+/* Return true when exp contains alloca call. */
+bool
+alloca_call_p (exp)
+ tree exp;
+{
+ if (TREE_CODE (exp) == CALL_EXPR
+ && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
+ && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
+ == FUNCTION_DECL)
+ && (special_function_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
+ 0) & ECF_MAY_BE_ALLOCA))
+ return true;
+ return false;
+}
+
/* Detect flags (function attributes) from the function decl or type node. */
static int
@@ -876,6 +897,12 @@ precompute_register_parameters (num_actuals, args, reg_parm_seen)
emit_queue ();
}
+ /* If the value is a non-legitimate constant, force it into a
+ pseudo now. TLS symbols sometimes need a call to resolve. */
+ if (CONSTANT_P (args[i].value)
+ && !LEGITIMATE_CONSTANT_P (args[i].value))
+ args[i].value = force_reg (args[i].mode, args[i].value);
+
/* If we are to promote the function arg to a wider mode,
do it now. */
@@ -967,11 +994,8 @@ save_fixed_argument_area (reg_parm_stack_space, argblock,
if (save_mode == BLKmode)
{
save_area = assign_stack_temp (BLKmode, num_to_save, 0);
- /* Cannot use emit_block_move here because it can be done by a
- library call which in turn gets into this place again and deadly
- infinite recursion happens. */
- move_by_pieces (validize_mem (save_area), stack_area, num_to_save,
- PARM_BOUNDARY);
+ emit_block_move (validize_mem (save_area), stack_area,
+ GEN_INT (num_to_save), BLOCK_OP_CALL_PARM);
}
else
{
@@ -1008,11 +1032,9 @@ restore_fixed_argument_area (save_area, argblock, high_to_save, low_to_save)
if (save_mode != BLKmode)
emit_move_insn (stack_area, save_area);
else
- /* Cannot use emit_block_move here because it can be done by a library
- call which in turn gets into this place again and deadly infinite
- recursion happens. */
- move_by_pieces (stack_area, validize_mem (save_area),
- high_to_save - low_to_save + 1, PARM_BOUNDARY);
+ emit_block_move (stack_area, validize_mem (save_area),
+ GEN_INT (high_to_save - low_to_save + 1),
+ BLOCK_OP_CALL_PARM);
}
#endif /* REG_PARM_STACK_SPACE */
@@ -1053,7 +1075,6 @@ store_unaligned_arguments_into_pseudos (args, num_actuals)
this means we must skip the empty high order bytes when
calculating the bit offset. */
if (BYTES_BIG_ENDIAN
- && !FUNCTION_ARG_REG_LITTLE_ENDIAN
&& bytes < UNITS_PER_WORD)
big_endian_correction = (BITS_PER_WORD - (bytes * BITS_PER_UNIT));
@@ -1539,8 +1560,8 @@ precompute_arguments (flags, num_actuals, args)
args[i].initial_value
= gen_lowpart_SUBREG (mode, args[i].value);
SUBREG_PROMOTED_VAR_P (args[i].initial_value) = 1;
- SUBREG_PROMOTED_UNSIGNED_P (args[i].initial_value)
- = args[i].unsignedp;
+ SUBREG_PROMOTED_UNSIGNED_SET (args[i].initial_value,
+ args[i].unsignedp);
}
#endif
}
@@ -1645,6 +1666,7 @@ compute_argument_addresses (args, argblock, num_actuals)
addr = plus_constant (addr, arg_offset);
args[i].stack = gen_rtx_MEM (args[i].mode, addr);
+ set_mem_align (args[i].stack, PARM_BOUNDARY);
set_mem_attributes (args[i].stack,
TREE_TYPE (args[i].tree_value), 1);
@@ -1655,6 +1677,7 @@ compute_argument_addresses (args, argblock, num_actuals)
addr = plus_constant (addr, arg_offset);
args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr);
+ set_mem_align (args[i].stack_slot, PARM_BOUNDARY);
set_mem_attributes (args[i].stack_slot,
TREE_TYPE (args[i].tree_value), 1);
@@ -1674,12 +1697,12 @@ compute_argument_addresses (args, argblock, num_actuals)
FNDECL is the tree node for the target function. For an indirect call
FNDECL will be NULL_TREE.
- EXP is the CALL_EXPR for this call. */
+ ADDR is the operand 0 of CALL_EXPR for this call. */
static rtx
-rtx_for_function_call (fndecl, exp)
+rtx_for_function_call (fndecl, addr)
tree fndecl;
- tree exp;
+ tree addr;
{
rtx funexp;
@@ -1703,7 +1726,7 @@ rtx_for_function_call (fndecl, exp)
rtx funaddr;
push_temp_slots ();
funaddr = funexp
- = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
+ = expand_expr (addr, NULL_RTX, VOIDmode, 0);
pop_temp_slots (); /* FUNEXP can't be BLKmode. */
emit_queue ();
}
@@ -1881,7 +1904,7 @@ try_to_integrate (fndecl, actparms, target, ignore, type, structure_value_addr)
NULL_RTX, BITS_PER_UNIT);
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, first_insn);
+ emit_insn_before (seq, first_insn);
emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
}
}
@@ -1904,7 +1927,7 @@ try_to_integrate (fndecl, actparms, target, ignore, type, structure_value_addr)
warning_with_decl (fndecl, "inlining failed in call to `%s'");
warning ("called from here");
}
- mark_addressable (fndecl);
+ (*lang_hooks.mark_addressable) (fndecl);
return (rtx) (size_t) - 1;
}
@@ -1970,7 +1993,7 @@ combine_pending_stack_adjustment_and_call (unadjusted_args_size,
/* Scan X expression if it does not dereference any argument slots
we already clobbered by tail call arguments (as noted in stored_args_map
bitmap).
- Return non-zero if X expression dereferences such argument slots,
+ Return nonzero if X expression dereferences such argument slots,
zero otherwise. */
static int
@@ -2033,7 +2056,7 @@ check_sibcall_argument_overlap_1 (x)
/* Scan sequence after INSN if it does not dereference any argument slots
we already clobbered by tail call arguments (as noted in stored_args_map
bitmap). Add stack slots for ARG to stored_args_map bitmap afterwards.
- Return non-zero if sequence after INSN dereferences such argument slots,
+ Return nonzero if sequence after INSN dereferences such argument slots,
zero otherwise. */
static int
@@ -2204,6 +2227,7 @@ expand_call (exp, target, ignore)
int old_stack_allocated;
rtx call_fusage;
tree p = TREE_OPERAND (exp, 0);
+ tree addr = TREE_OPERAND (exp, 0);
int i;
/* The alignment of the stack, in bits. */
HOST_WIDE_INT preferred_stack_boundary;
@@ -2239,7 +2263,7 @@ expand_call (exp, target, ignore)
warning_with_decl (fndecl, "can't inline call to `%s'");
warning ("called from here");
}
- mark_addressable (fndecl);
+ (*lang_hooks.mark_addressable) (fndecl);
}
flags |= flags_from_decl_or_type (fndecl);
@@ -2285,7 +2309,7 @@ expand_call (exp, target, ignore)
/* In case this is a static function, note that it has been
used. */
if (! TREE_ADDRESSABLE (fndecl))
- mark_addressable (fndecl);
+ (*lang_hooks.mark_addressable) (fndecl);
is_integrable = 0;
}
}
@@ -2325,7 +2349,7 @@ expand_call (exp, target, ignore)
preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
/* Operand 0 is a pointer-to-function; get the type of the function. */
- funtype = TREE_TYPE (TREE_OPERAND (exp, 0));
+ funtype = TREE_TYPE (addr);
if (! POINTER_TYPE_P (funtype))
abort ();
funtype = TREE_TYPE (funtype);
@@ -2462,8 +2486,8 @@ expand_call (exp, target, ignore)
/* Tail recursion fails, when we are not dealing with recursive calls. */
if (!try_tail_recursion
- || TREE_CODE (TREE_OPERAND (exp, 0)) != ADDR_EXPR
- || TREE_OPERAND (TREE_OPERAND (exp, 0), 0) != current_function_decl)
+ || TREE_CODE (addr) != ADDR_EXPR
+ || TREE_OPERAND (addr, 0) != current_function_decl)
try_tail_recursion = 0;
/* Rest of purposes for tail call optimizations to fail. */
@@ -2487,19 +2511,19 @@ expand_call (exp, target, ignore)
reload insns generated to fix things up would appear
before the sibcall_epilogue. */
|| fndecl == NULL_TREE
- || (flags & (ECF_RETURNS_TWICE | ECF_LONGJMP))
- || TREE_THIS_VOLATILE (fndecl)
+ || (flags & (ECF_RETURNS_TWICE | ECF_LONGJMP | ECF_NORETURN))
|| !FUNCTION_OK_FOR_SIBCALL (fndecl)
/* If this function requires more stack slots than the current
function, we cannot change it into a sibling call. */
|| args_size.constant > current_function_args_size
/* If the callee pops its own arguments, then it must pop exactly
the same number of arguments as the current function. */
- || RETURN_POPS_ARGS (fndecl, funtype, args_size.constant)
- != RETURN_POPS_ARGS (current_function_decl,
- TREE_TYPE (current_function_decl),
- current_function_args_size))
- try_tail_call = 0;
+ || (RETURN_POPS_ARGS (fndecl, funtype, args_size.constant)
+ != RETURN_POPS_ARGS (current_function_decl,
+ TREE_TYPE (current_function_decl),
+ current_function_args_size))
+ || !(*lang_hooks.decls.ok_for_sibcall) (fndecl))
+ try_tail_call = 0;
if (try_tail_call || try_tail_recursion)
{
@@ -2544,7 +2568,7 @@ expand_call (exp, target, ignore)
}
/* Do the same for the function address if it is an expression. */
if (!fndecl)
- TREE_OPERAND (exp, 0) = fix_unsafe_tree (TREE_OPERAND (exp, 0));
+ addr = fix_unsafe_tree (addr);
/* Expanding one of those dangerous arguments could have added
cleanups, but otherwise give it a whirl. */
if (any_pending_cleanups (1))
@@ -2938,7 +2962,7 @@ expand_call (exp, target, ignore)
be deferred during the evaluation of the arguments. */
NO_DEFER_POP;
- funexp = rtx_for_function_call (fndecl, exp);
+ funexp = rtx_for_function_call (fndecl, addr);
/* Figure out the register where the value, if any, will come back. */
valreg = 0;
@@ -3089,7 +3113,7 @@ expand_call (exp, target, ignore)
{
insns = get_insns ();
end_sequence ();
- emit_insns (insns);
+ emit_insn (insns);
}
else
{
@@ -3143,7 +3167,7 @@ expand_call (exp, target, ignore)
/* Write out the sequence. */
insns = get_insns ();
end_sequence ();
- emit_insns (insns);
+ emit_insn (insns);
valreg = temp;
}
@@ -3288,7 +3312,7 @@ expand_call (exp, target, ignore)
}
target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
SUBREG_PROMOTED_VAR_P (target) = 1;
- SUBREG_PROMOTED_UNSIGNED_P (target) = unsignedp;
+ SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp);
}
#endif
@@ -3327,9 +3351,9 @@ expand_call (exp, target, ignore)
if (save_mode != BLKmode)
emit_move_insn (stack_area, args[i].save_area);
else
- emit_block_move (stack_area,
- validize_mem (args[i].save_area),
- GEN_INT (args[i].size.constant));
+ emit_block_move (stack_area, args[i].save_area,
+ GEN_INT (args[i].size.constant),
+ BLOCK_OP_CALL_PARM);
}
highest_outgoing_arg_in_use = initial_highest_arg_in_use;
@@ -3430,7 +3454,7 @@ expand_call (exp, target, ignore)
tail_recursion_label));
}
else
- emit_insns (normal_call_insns);
+ emit_insn (normal_call_insns);
currently_expanding_call--;
@@ -3494,6 +3518,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
int reg_parm_stack_space = 0;
int needed;
rtx before_call;
+ tree tfom; /* type_for_mode (outmode, 0) */
#ifdef REG_PARM_STACK_SPACE
/* Define the boundary of the register parm stack space that needs to be
@@ -3555,27 +3580,31 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
/* If this kind of value comes back in memory,
decide where in memory it should come back. */
- if (outmode != VOIDmode && aggregate_value_p (type_for_mode (outmode, 0)))
+ if (outmode != VOIDmode)
{
+ tfom = (*lang_hooks.types.type_for_mode) (outmode, 0);
+ if (aggregate_value_p (tfom))
+ {
#ifdef PCC_STATIC_STRUCT_RETURN
- rtx pointer_reg
- = hard_function_value (build_pointer_type (type_for_mode (outmode, 0)),
- 0, 0);
- mem_value = gen_rtx_MEM (outmode, pointer_reg);
- pcc_struct_value = 1;
- if (value == 0)
- value = gen_reg_rtx (outmode);
+ rtx pointer_reg
+ = hard_function_value (build_pointer_type (tfom), 0, 0);
+ mem_value = gen_rtx_MEM (outmode, pointer_reg);
+ pcc_struct_value = 1;
+ if (value == 0)
+ value = gen_reg_rtx (outmode);
#else /* not PCC_STATIC_STRUCT_RETURN */
- struct_value_size = GET_MODE_SIZE (outmode);
- if (value != 0 && GET_CODE (value) == MEM)
- mem_value = value;
- else
- mem_value = assign_temp (type_for_mode (outmode, 0), 0, 1, 1);
+ struct_value_size = GET_MODE_SIZE (outmode);
+ if (value != 0 && GET_CODE (value) == MEM)
+ mem_value = value;
+ else
+ mem_value = assign_temp (tfom, 0, 1, 1);
#endif
-
- /* This call returns a big structure. */
- flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
+ /* This call returns a big structure. */
+ flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
+ }
}
+ else
+ tfom = void_type_node;
/* ??? Unfinished: must pass the memory address as an argument. */
@@ -3684,6 +3713,16 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
#endif
;
+ /* loop.c won't look at CALL_INSN_FUNCTION_USAGE of const/pure
+ functions, so we have to pretend this isn't such a function. */
+ if (flags & ECF_LIBCALL_BLOCK)
+ {
+ rtx insns = get_insns ();
+ end_sequence ();
+ emit_insn (insns);
+ }
+ flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
+
/* If this was a CONST function, it is now PURE since
it now reads memory. */
if (flags & ECF_CONST)
@@ -3696,12 +3735,13 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
slot = val;
else if (must_copy)
{
- slot = assign_temp (type_for_mode (mode, 0), 0, 1, 1);
+ slot = assign_temp ((*lang_hooks.types.type_for_mode) (mode, 0),
+ 0, 1, 1);
emit_move_insn (slot, val);
}
else
{
- tree type = type_for_mode (mode, 0);
+ tree type = (*lang_hooks.types.type_for_mode) (mode, 0);
slot = gen_rtx_MEM (mode,
expand_expr (build1 (ADDR_EXPR,
@@ -3911,8 +3951,8 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
{
save_area = assign_stack_temp (BLKmode, num_to_save, 0);
set_mem_align (save_area, PARM_BOUNDARY);
- emit_block_move (validize_mem (save_area), stack_area,
- GEN_INT (num_to_save));
+ emit_block_move (save_area, stack_area, GEN_INT (num_to_save),
+ BLOCK_OP_CALL_PARM);
}
else
{
@@ -3980,8 +4020,9 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
}
}
- emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0,
- argblock, GEN_INT (argvec[argnum].offset.constant),
+ emit_push_insn (val, mode, NULL_TREE, NULL_RTX, PARM_BOUNDARY,
+ partial, reg, 0, argblock,
+ GEN_INT (argvec[argnum].offset.constant),
reg_parm_stack_space, ARGS_SIZE_RTX (alignment_pad));
/* Now mark the segment we just used. */
@@ -4068,8 +4109,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
emit_call_1 (fun,
get_identifier (XSTR (orgfun, 0)),
- build_function_type (outmode == VOIDmode ? void_type_node
- : type_for_mode (outmode, 0), NULL_TREE),
+ build_function_type (tfom, NULL_TREE),
original_args_size.constant, args_size.constant,
struct_value_size,
FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
@@ -4109,18 +4149,27 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
{
rtx insns;
- if (valreg == 0 || GET_CODE (valreg) == PARALLEL)
+ if (valreg == 0)
{
insns = get_insns ();
end_sequence ();
- emit_insns (insns);
+ emit_insn (insns);
}
else
{
rtx note = 0;
- rtx temp = gen_reg_rtx (GET_MODE (valreg));
+ rtx temp;
int i;
+ if (GET_CODE (valreg) == PARALLEL)
+ {
+ temp = gen_reg_rtx (outmode);
+ emit_group_store (temp, valreg, outmode);
+ valreg = temp;
+ }
+
+ temp = gen_reg_rtx (GET_MODE (valreg));
+
/* Construct an "equal form" for the value which mentions all the
arguments in order as well as the function name. */
for (i = 0; i < nargs; i++)
@@ -4154,10 +4203,16 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
if (value != mem_value)
emit_move_insn (value, mem_value);
}
+ else if (GET_CODE (valreg) == PARALLEL)
+ {
+ if (value == 0)
+ value = gen_reg_rtx (outmode);
+ emit_group_store (value, valreg, outmode);
+ }
else if (value != 0)
- emit_move_insn (value, hard_libcall_value (outmode));
+ emit_move_insn (value, valreg);
else
- value = hard_libcall_value (outmode);
+ value = valreg;
}
if (ACCUMULATE_OUTGOING_ARGS)
@@ -4183,8 +4238,9 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
if (save_mode != BLKmode)
emit_move_insn (stack_area, save_area);
else
- emit_block_move (stack_area, validize_mem (save_area),
- GEN_INT (high_to_save - low_to_save + 1));
+ emit_block_move (stack_area, save_area,
+ GEN_INT (high_to_save - low_to_save + 1),
+ BLOCK_OP_CALL_PARM);
}
#endif
@@ -4286,7 +4342,7 @@ emit_library_call_value VPARAMS((rtx orgfun, rtx value,
FNDECL is the declaration of the function we are calling.
- Return non-zero if this arg should cause sibcall failure,
+ Return nonzero if this arg should cause sibcall failure,
zero otherwise. */
static int
@@ -4294,7 +4350,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
struct arg_data *arg;
rtx argblock;
int flags;
- int variable_size;
+ int variable_size ATTRIBUTE_UNUSED;
int reg_parm_stack_space;
{
tree pval = arg->tree_value;
@@ -4361,7 +4417,8 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
arg->save_area = assign_temp (nt, 0, 1, 1);
preserve_temp_slots (arg->save_area);
emit_block_move (validize_mem (arg->save_area), stack_area,
- expr_size (arg->tree_value));
+ expr_size (arg->tree_value),
+ BLOCK_OP_CALL_PARM);
}
else
{
@@ -4369,21 +4426,6 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
emit_move_insn (arg->save_area, stack_area);
}
}
-
- /* Now that we have saved any slots that will be overwritten
- by this store, mark all slots this store will use. We
- must do this before we actually expand the argument since
- the expansion itself may trigger library calls which might
- need to use the same stack slot. We only do it if we can't
- pass all arguments to a library call in registers. */
- if (arg->partial)
- {
- for (i = lower_bound; i < upper_bound; i++)
- stack_usage_map[i] = 1;
-
- /* Set it so that we don't do it again. */
- variable_size = 1;
- }
}
}
@@ -4437,7 +4479,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
(partial
|| TYPE_MODE (TREE_TYPE (pval)) != arg->mode)
? NULL_RTX : arg->stack,
- VOIDmode, 0);
+ VOIDmode, EXPAND_STACK_PARM);
/* If we are promoting object (or for any other reason) the mode
doesn't agree, convert the mode. */
@@ -4490,8 +4532,8 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
/* This isn't already where we want it on the stack, so put it there.
This can either be done with push or copy insns. */
- emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX, 0,
- partial, reg, used - size, argblock,
+ emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX,
+ PARM_BOUNDARY, partial, reg, used - size, argblock,
ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
ARGS_SIZE_RTX (arg->alignment_pad));
@@ -4504,6 +4546,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
{
/* BLKmode, at least partly to be pushed. */
+ unsigned int parm_align;
int excess;
rtx size_rtx;
@@ -4529,6 +4572,23 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
NULL_RTX, TYPE_MODE (sizetype), 0);
}
+ /* Some types will require stricter alignment, which will be
+ provided for elsewhere in argument layout. */
+ parm_align = MAX (PARM_BOUNDARY, TYPE_ALIGN (TREE_TYPE (pval)));
+
+ /* When an argument is padded down, the block is aligned to
+ PARM_BOUNDARY, but the actual argument isn't. */
+ if (FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)) == downward)
+ {
+ if (arg->size.var)
+ parm_align = BITS_PER_UNIT;
+ else if (excess)
+ {
+ unsigned int excess_align = (excess & -excess) * BITS_PER_UNIT;
+ parm_align = MIN (parm_align, excess_align);
+ }
+ }
+
if ((flags & ECF_SIBCALL) && GET_CODE (arg->value) == MEM)
{
/* emit_push_insn might not work properly if arg->value and
@@ -4562,42 +4622,9 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
}
}
- /* Special handling is required if part of the parameter lies in the
- register parameter area. The argument may be copied into the stack
- slot using memcpy(), but the original contents of the register
- parameter area will be restored after the memcpy() call.
-
- To ensure that the part that lies in the register parameter area
- is copied correctly, we emit a separate push for that part. This
- push should be small enough to avoid a call to memcpy(). */
-#ifndef STACK_PARMS_IN_REG_PARM_AREA
- if (arg->reg && arg->pass_on_stack)
-#else
- if (1)
-#endif
- {
- if (arg->offset.constant < reg_parm_stack_space && arg->offset.var)
- error ("variable offset is passed partially in stack and in reg");
- else if (arg->offset.constant < reg_parm_stack_space && arg->size.var)
- error ("variable size is passed partially in stack and in reg");
- else if (arg->offset.constant < reg_parm_stack_space
- && ((arg->offset.constant + arg->size.constant)
- > reg_parm_stack_space))
- {
- rtx size_rtx1 = GEN_INT (reg_parm_stack_space - arg->offset.constant);
- emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx1,
- TYPE_ALIGN (TREE_TYPE (pval)), partial, reg,
- excess, argblock, ARGS_SIZE_RTX (arg->offset),
- reg_parm_stack_space,
- ARGS_SIZE_RTX (arg->alignment_pad));
- }
- }
-
-
emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
- TYPE_ALIGN (TREE_TYPE (pval)), partial, reg, excess,
- argblock, ARGS_SIZE_RTX (arg->offset),
- reg_parm_stack_space,
+ parm_align, partial, reg, excess, argblock,
+ ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
ARGS_SIZE_RTX (arg->alignment_pad));
/* Unless this is a partially-in-register argument, the argument is now
@@ -4612,6 +4639,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
arg->value = arg->stack_slot;
}
+ /* Mark all slots this store used. */
if (ACCUMULATE_OUTGOING_ARGS && !(flags & ECF_SIBCALL)
&& argblock && ! variable_size && arg->stack)
for (i = lower_bound; i < upper_bound; i++)
diff --git a/contrib/gcc/cfg.c b/contrib/gcc/cfg.c
index 73689c3..2d11580 100644
--- a/contrib/gcc/cfg.c
+++ b/contrib/gcc/cfg.c
@@ -38,6 +38,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
dump_flow_info, debug_flow_info, dump_edge_info
- Allocation of AUX fields for basic blocks
alloc_aux_for_blocks, free_aux_for_blocks, alloc_aux_for_block
+ - clear_bb_flags
*/
#include "config.h"
@@ -64,6 +65,10 @@ static char *flow_firstobj;
int n_basic_blocks;
+/* First free basic block number. */
+
+int last_basic_block;
+
/* Number of edges in the current function. */
int n_edges;
@@ -92,7 +97,10 @@ struct basic_block_def entry_exit_blocks[2]
NULL, /* global_live_at_end */
NULL, /* aux */
ENTRY_BLOCK, /* index */
+ NULL, /* prev_bb */
+ EXIT_BLOCK_PTR, /* next_bb */
0, /* loop_depth */
+ NULL, /* loop_father */
0, /* count */
0, /* frequency */
0 /* flags */
@@ -110,7 +118,10 @@ struct basic_block_def entry_exit_blocks[2]
NULL, /* global_live_at_end */
NULL, /* aux */
EXIT_BLOCK, /* index */
+ ENTRY_BLOCK_PTR, /* prev_bb */
+ NULL, /* next_bb */
0, /* loop_depth */
+ NULL, /* loop_father */
0, /* count */
0, /* frequency */
0 /* flags */
@@ -162,12 +173,11 @@ free_edge (e)
void
clear_edges ()
{
- int i;
+ basic_block bb;
edge e;
- for (i = 0; i < n_basic_blocks; ++i)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
edge e = bb->succ;
while (e)
@@ -219,38 +229,99 @@ alloc_block ()
return bb;
}
-/* Remove block B from the basic block array and compact behind it. */
+/* Link block B to chain after AFTER. */
+void
+link_block (b, after)
+ basic_block b, after;
+{
+ b->next_bb = after->next_bb;
+ b->prev_bb = after;
+ after->next_bb = b;
+ b->next_bb->prev_bb = b;
+}
+
+/* Unlink block B from chain. */
+void
+unlink_block (b)
+ basic_block b;
+{
+ b->next_bb->prev_bb = b->prev_bb;
+ b->prev_bb->next_bb = b->next_bb;
+}
+
+/* Sequentially order blocks and compact the arrays. */
+void
+compact_blocks ()
+{
+ int i;
+ basic_block bb;
+
+ i = 0;
+ FOR_EACH_BB (bb)
+ {
+ BASIC_BLOCK (i) = bb;
+ bb->index = i;
+ i++;
+ }
+
+ if (i != n_basic_blocks)
+ abort ();
+
+ last_basic_block = n_basic_blocks;
+}
+
+
+/* Remove block B from the basic block array. */
void
-expunge_block_nocompact (b)
+expunge_block (b)
basic_block b;
{
+ unlink_block (b);
+ BASIC_BLOCK (b->index) = NULL;
+ n_basic_blocks--;
+
/* Invalidate data to make bughunting easier. */
memset (b, 0, sizeof *b);
b->index = -3;
b->succ = (edge) first_deleted_block;
first_deleted_block = (basic_block) b;
}
+
+/* Create an edge connecting SRC and DEST with flags FLAGS. Return newly
+ created edge. Use this only if you are sure that this edge can't
+ possibly already exist. */
-void
-expunge_block (b)
- basic_block b;
+edge
+unchecked_make_edge (src, dst, flags)
+ basic_block src, dst;
+ int flags;
{
- int i, n = n_basic_blocks;
+ edge e;
- for (i = b->index; i + 1 < n; ++i)
+ if (first_deleted_edge)
+ {
+ e = first_deleted_edge;
+ first_deleted_edge = e->succ_next;
+ }
+ else
{
- basic_block x = BASIC_BLOCK (i + 1);
- BASIC_BLOCK (i) = x;
- x->index = i;
+ e = (edge) obstack_alloc (&flow_obstack, sizeof *e);
+ memset (e, 0, sizeof *e);
}
+ n_edges++;
- n_basic_blocks--;
- basic_block_info->num_elements--;
+ e->succ_next = src->succ;
+ e->pred_next = dst->pred;
+ e->src = src;
+ e->dest = dst;
+ e->flags = flags;
- expunge_block_nocompact (b);
+ src->succ = e;
+ dst->pred = e;
+
+ return e;
}
-
/* Create an edge connecting SRC and DST with FLAGS optionally using
edge cache CACHE. Return the new edge, NULL if already exist. */
@@ -291,26 +362,7 @@ cached_make_edge (edge_cache, src, dst, flags)
break;
}
- if (first_deleted_edge)
- {
- e = first_deleted_edge;
- first_deleted_edge = e->succ_next;
- }
- else
- {
- e = (edge) obstack_alloc (&flow_obstack, sizeof *e);
- memset (e, 0, sizeof *e);
- }
- n_edges++;
-
- e->succ_next = src->succ;
- e->pred_next = dst->pred;
- e->src = src;
- e->dest = dst;
- e->flags = flags;
-
- src->succ = e;
- dst->pred = e;
+ e = unchecked_make_edge (src, dst, flags);
if (use_edge_cache)
SET_BIT (edge_cache[src->index], dst->index);
@@ -418,6 +470,8 @@ redirect_edge_succ_nodup (e, new_succ)
{
s->flags |= e->flags;
s->probability += e->probability;
+ if (s->probability > REG_BR_PROB_BASE)
+ s->probability = REG_BR_PROB_BASE;
s->count += e->count;
remove_edge (e);
e = s;
@@ -448,12 +502,23 @@ redirect_edge_pred (e, new_pred)
new_pred->succ = e;
e->src = new_pred;
}
+
+void
+clear_bb_flags ()
+{
+ basic_block bb;
+
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ bb->flags = 0;
+}
void
dump_flow_info (file)
FILE *file;
{
int i;
+ int max_regno = max_reg_num ();
+ basic_block bb;
static const char * const reg_class_names[] = REG_CLASS_NAMES;
fprintf (file, "%d registers.\n", max_regno);
@@ -469,7 +534,7 @@ dump_flow_info (file)
if (REG_N_SETS (i))
fprintf (file, "; set %d time%s", REG_N_SETS (i),
(REG_N_SETS (i) == 1) ? "" : "s");
- if (REG_USERVAR_P (regno_reg_rtx[i]))
+ if (regno_reg_rtx[i] != NULL && REG_USERVAR_P (regno_reg_rtx[i]))
fprintf (file, "; user var");
if (REG_N_DEATHS (i) != 1)
fprintf (file, "; dies in %d places", REG_N_DEATHS (i));
@@ -477,7 +542,8 @@ dump_flow_info (file)
fprintf (file, "; crosses 1 call");
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)
+ if (regno_reg_rtx[i] != NULL
+ && PSEUDO_REGNO_BYTES (i) != UNITS_PER_WORD)
fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i));
class = reg_preferred_class (i);
@@ -494,22 +560,30 @@ dump_flow_info (file)
reg_class_names[(int) altclass]);
}
- if (REG_POINTER (regno_reg_rtx[i]))
+ if (regno_reg_rtx[i] != NULL && REG_POINTER (regno_reg_rtx[i]))
fprintf (file, "; pointer");
fprintf (file, ".\n");
}
fprintf (file, "\n%d basic blocks, %d edges.\n", n_basic_blocks, n_edges);
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
edge e;
+ int sum;
+ gcov_type lsum;
fprintf (file, "\nBasic block %d: first insn %d, last %d, ",
- i, INSN_UID (bb->head), INSN_UID (bb->end));
+ bb->index, INSN_UID (bb->head), INSN_UID (bb->end));
+ fprintf (file, "prev %d, next %d, ",
+ bb->prev_bb->index, bb->next_bb->index);
fprintf (file, "loop_depth %d, count ", bb->loop_depth);
fprintf (file, HOST_WIDEST_INT_PRINT_DEC, bb->count);
- fprintf (file, ", freq %i.\n", bb->frequency);
+ fprintf (file, ", freq %i", bb->frequency);
+ if (maybe_hot_bb_p (bb))
+ fprintf (file, ", maybe hot");
+ if (probably_never_executed_bb_p (bb))
+ fprintf (file, ", probably never executed");
+ fprintf (file, ".\n");
fprintf (file, "Predecessors: ");
for (e = bb->pred; e; e = e->pred_next)
@@ -526,6 +600,37 @@ dump_flow_info (file)
dump_regset (bb->global_live_at_end, file);
putc ('\n', file);
+
+ /* Check the consistency of profile information. We can't do that
+ in verify_flow_info, as the counts may get invalid for incompletely
+ solved graphs, later elliminating of conditionals or roundoff errors.
+ It is still practical to have them reported for debugging of simple
+ testcases. */
+ sum = 0;
+ for (e = bb->succ; e; e = e->succ_next)
+ sum += e->probability;
+ if (bb->succ && abs (sum - REG_BR_PROB_BASE) > 100)
+ fprintf (file, "Invalid sum of outgoing probabilities %.1f%%\n",
+ sum * 100.0 / REG_BR_PROB_BASE);
+ sum = 0;
+ for (e = bb->pred; e; e = e->pred_next)
+ sum += EDGE_FREQUENCY (e);
+ if (abs (sum - bb->frequency) > 100)
+ fprintf (file,
+ "Invalid sum of incomming frequencies %i, should be %i\n",
+ sum, bb->frequency);
+ lsum = 0;
+ for (e = bb->pred; e; e = e->pred_next)
+ lsum += e->count;
+ if (lsum - bb->count > 100 || lsum - bb->count < -100)
+ fprintf (file, "Invalid sum of incomming counts %i, should be %i\n",
+ (int)lsum, (int)bb->count);
+ lsum = 0;
+ for (e = bb->succ; e; e = e->succ_next)
+ lsum += e->count;
+ if (bb->succ && (lsum - bb->count > 100 || lsum - bb->count < -100))
+ fprintf (file, "Invalid sum of incomming counts %i, should be %i\n",
+ (int)lsum, (int)bb->count);
}
putc ('\n', file);
@@ -564,7 +669,7 @@ dump_edge_info (file, e, do_succ)
if (e->flags)
{
static const char * const bitnames[]
- = {"fallthru", "ab", "abcall", "eh", "fake", "dfs_back"};
+ = {"fallthru", "ab", "abcall", "eh", "fake", "dfs_back", "can_fallthru"};
int comma = 0;
int i, flags = e->flags;
@@ -594,7 +699,7 @@ static void *first_block_aux_obj = 0;
static struct obstack edge_aux_obstack;
static void *first_edge_aux_obj = 0;
-/* Allocate an memory block of SIZE as BB->aux. The obstack must
+/* Allocate a memory block of SIZE as BB->aux. The obstack must
be first initialized by alloc_aux_for_blocks. */
inline void
@@ -630,13 +735,10 @@ alloc_aux_for_blocks (size)
first_block_aux_obj = (char *) obstack_alloc (&block_aux_obstack, 0);
if (size)
{
- int i;
-
- for (i = 0; i < n_basic_blocks; i++)
- alloc_aux_for_block (BASIC_BLOCK (i), size);
+ basic_block bb;
- alloc_aux_for_block (ENTRY_BLOCK_PTR, size);
- alloc_aux_for_block (EXIT_BLOCK_PTR, size);
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ alloc_aux_for_block (bb, size);
}
}
@@ -645,13 +747,10 @@ alloc_aux_for_blocks (size)
void
clear_aux_for_blocks ()
{
- int i;
-
- for (i = 0; i < n_basic_blocks; i++)
- BASIC_BLOCK (i)->aux = NULL;
+ basic_block bb;
- ENTRY_BLOCK_PTR->aux = NULL;
- EXIT_BLOCK_PTR->aux = NULL;
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ bb->aux = NULL;
}
/* Free data allocated in block_aux_obstack and clear AUX pointers
@@ -668,7 +767,7 @@ free_aux_for_blocks ()
clear_aux_for_blocks ();
}
-/* Allocate an memory edge of SIZE as BB->aux. The obstack must
+/* Allocate a memory edge of SIZE as BB->aux. The obstack must
be first initialized by alloc_aux_for_edges. */
inline void
@@ -705,17 +804,12 @@ alloc_aux_for_edges (size)
first_edge_aux_obj = (char *) obstack_alloc (&edge_aux_obstack, 0);
if (size)
{
- int i;
- for (i = -1; i < n_basic_blocks; i++)
+ basic_block bb;
+
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
{
- basic_block bb;
edge e;
- if (i >= 0)
- bb = BASIC_BLOCK (i);
- else
- bb = ENTRY_BLOCK_PTR;
-
for (e = bb->succ; e; e = e->succ_next)
alloc_aux_for_edge (e, size);
}
@@ -727,18 +821,11 @@ alloc_aux_for_edges (size)
void
clear_aux_for_edges ()
{
- int i;
+ basic_block bb;
+ edge e;
- for (i = -1; i < n_basic_blocks; i++)
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
{
- basic_block bb;
- edge e;
-
- if (i >= 0)
- bb = BASIC_BLOCK (i);
- else
- bb = ENTRY_BLOCK_PTR;
-
for (e = bb->succ; e; e = e->succ_next)
e->aux = NULL;
}
diff --git a/contrib/gcc/cfganal.c b/contrib/gcc/cfganal.c
index f0ca224..3831c5f 100644
--- a/contrib/gcc/cfganal.c
+++ b/contrib/gcc/cfganal.c
@@ -28,7 +28,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "insn-config.h"
#include "recog.h"
#include "toplev.h"
-#include "obstack.h"
#include "tm_p.h"
/* Store the data structures necessary for depth-first search. */
@@ -55,7 +54,6 @@ static void flow_dfs_compute_reverse_finish
PARAMS ((depth_first_search_ds));
static void remove_fake_successors PARAMS ((basic_block));
static bool need_fake_edge_p PARAMS ((rtx));
-static bool keep_with_call_p PARAMS ((rtx));
static bool flow_active_insn_p PARAMS ((rtx));
/* Like active_insn_p, except keep the return value clobber around
@@ -69,7 +67,7 @@ flow_active_insn_p (insn)
return true;
/* A clobber of the function return value exists for buggy
- programs that fail to return a value. It's effect is to
+ programs that fail to return a value. Its effect is to
keep the return value from being live across the entire
function. If we allow it to be skipped, we introduce the
possibility for register livetime aborts. */
@@ -112,7 +110,10 @@ can_fallthru (src, target)
rtx insn = src->end;
rtx insn2 = target->head;
- if (src->index + 1 == target->index && !active_insn_p (insn2))
+ if (src->next_bb != target)
+ return 0;
+
+ if (!active_insn_p (insn2))
insn2 = next_active_insn (insn2);
/* ??? Later we may add code to move jump tables offline. */
@@ -120,7 +121,7 @@ can_fallthru (src, target)
}
/* Mark the back edges in DFS traversal.
- Return non-zero if a loop (natural or otherwise) is present.
+ Return nonzero if a loop (natural or otherwise) is present.
Inspired by Depth_First_Search_PP described in:
Advanced Compiler Design and Implementation
@@ -142,15 +143,15 @@ mark_dfs_back_edges ()
bool found = false;
/* Allocate the preorder and postorder number arrays. */
- pre = (int *) xcalloc (n_basic_blocks, sizeof (int));
- post = (int *) xcalloc (n_basic_blocks, sizeof (int));
+ pre = (int *) xcalloc (last_basic_block, sizeof (int));
+ post = (int *) xcalloc (last_basic_block, sizeof (int));
/* Allocate stack for back-tracking up CFG. */
stack = (edge *) xmalloc ((n_basic_blocks + 1) * sizeof (edge));
sp = 0;
/* Allocate bitmap to track nodes that have been visited. */
- visited = sbitmap_alloc (n_basic_blocks);
+ visited = sbitmap_alloc (last_basic_block);
/* None of the nodes in the CFG have been visited yet. */
sbitmap_zero (visited);
@@ -211,6 +212,40 @@ mark_dfs_back_edges ()
return found;
}
+/* Set the flag EDGE_CAN_FALLTHRU for edges that can be fallthru. */
+
+void
+set_edge_can_fallthru_flag ()
+{
+ basic_block bb;
+
+ FOR_EACH_BB (bb)
+ {
+ edge e;
+
+ for (e = bb->succ; e; e = e->succ_next)
+ {
+ e->flags &= ~EDGE_CAN_FALLTHRU;
+
+ /* The FALLTHRU edge is also CAN_FALLTHRU edge. */
+ if (e->flags & EDGE_FALLTHRU)
+ e->flags |= EDGE_CAN_FALLTHRU;
+ }
+
+ /* If the BB ends with an invertable condjump all (2) edges are
+ CAN_FALLTHRU edges. */
+ if (!bb->succ || !bb->succ->succ_next || bb->succ->succ_next->succ_next)
+ continue;
+ if (!any_condjump_p (bb->end))
+ continue;
+ if (!invert_jump (bb->end, JUMP_LABEL (bb->end), 0))
+ continue;
+ invert_jump (bb->end, JUMP_LABEL (bb->end), 0);
+ bb->succ->flags |= EDGE_CAN_FALLTHRU;
+ bb->succ->succ_next->flags |= EDGE_CAN_FALLTHRU;
+ }
+}
+
/* Return true if we need to add fake edge to exit.
Helper function for the flow_call_edges_add. */
@@ -236,32 +271,6 @@ need_fake_edge_p (insn)
|| GET_CODE (PATTERN (insn)) == ASM_INPUT);
}
-/* Return true if INSN should be kept in the same block as a preceding call.
- This is done for a single-set whose destination is a fixed register or
- whose source is the function return value. This is a helper function for
- flow_call_edges_add. */
-
-static bool
-keep_with_call_p (insn)
- rtx insn;
-{
- rtx set;
-
- if (INSN_P (insn) && (set = single_set (insn)) != NULL)
- {
- if (GET_CODE (SET_DEST (set)) == REG
- && fixed_regs[REGNO (SET_DEST (set))]
- && general_operand (SET_SRC (set), VOIDmode))
- return true;
- if (GET_CODE (SET_SRC (set)) == REG
- && FUNCTION_VALUE_REGNO_P (REGNO (SET_SRC (set)))
- && GET_CODE (SET_DEST (set)) == REG
- && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
- return true;
- }
- return false;
-}
-
/* Add fake edges to the function exit for any non constant and non noreturn
calls, volatile inline assembly in the bitmap of blocks specified by
BLOCKS or to the whole CFG if BLOCKS is zero. Return the number of blocks
@@ -276,29 +285,16 @@ flow_call_edges_add (blocks)
{
int i;
int blocks_split = 0;
- int bb_num = 0;
- basic_block *bbs;
+ int last_bb = last_basic_block;
bool check_last_block = false;
- /* Map bb indices into basic block pointers since split_block
- will renumber the basic blocks. */
-
- bbs = xmalloc (n_basic_blocks * sizeof (*bbs));
+ if (n_basic_blocks == 0)
+ return 0;
if (! blocks)
- {
- for (i = 0; i < n_basic_blocks; i++)
- bbs[bb_num++] = BASIC_BLOCK (i);
-
- check_last_block = true;
- }
+ check_last_block = true;
else
- EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
- {
- bbs[bb_num++] = BASIC_BLOCK (i);
- if (i == n_basic_blocks - 1)
- check_last_block = true;
- });
+ check_last_block = TEST_BIT (blocks, EXIT_BLOCK_PTR->prev_bb->index);
/* In the last basic block, before epilogue generation, there will be
a fallthru edge to EXIT. Special care is required if the last insn
@@ -314,7 +310,7 @@ flow_call_edges_add (blocks)
Handle this by adding a dummy instruction in a new last basic block. */
if (check_last_block)
{
- basic_block bb = BASIC_BLOCK (n_basic_blocks - 1);
+ basic_block bb = EXIT_BLOCK_PTR->prev_bb;
rtx insn = bb->end;
/* Back up past insns that must be kept in the same block as a call. */
@@ -340,12 +336,18 @@ flow_call_edges_add (blocks)
calls since there is no way that we can determine if they will
return or not... */
- for (i = 0; i < bb_num; i++)
+ for (i = 0; i < last_bb; i++)
{
- basic_block bb = bbs[i];
+ basic_block bb = BASIC_BLOCK (i);
rtx insn;
rtx prev_insn;
+ if (!bb)
+ continue;
+
+ if (blocks && !TEST_BIT (blocks, i))
+ continue;
+
for (insn = bb->end; ; insn = prev_insn)
{
prev_insn = PREV_INSN (insn);
@@ -375,9 +377,12 @@ flow_call_edges_add (blocks)
/* Note that the following may create a new basic block
and renumber the existing basic blocks. */
- e = split_block (bb, split_at_insn);
- if (e)
- blocks_split++;
+ if (split_at_insn != bb->end)
+ {
+ e = split_block (bb, split_at_insn);
+ if (e)
+ blocks_split++;
+ }
make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
}
@@ -390,28 +395,26 @@ flow_call_edges_add (blocks)
if (blocks_split)
verify_flow_info ();
- free (bbs);
return blocks_split;
}
/* Find unreachable blocks. An unreachable block will have 0 in
- the reachable bit in block->flags. A non-zero value indicates the
+ the reachable bit in block->flags. A nonzero value indicates the
block is reachable. */
void
find_unreachable_blocks ()
{
edge e;
- int i, n;
- basic_block *tos, *worklist;
+ basic_block *tos, *worklist, bb;
- n = n_basic_blocks;
- tos = worklist = (basic_block *) xmalloc (sizeof (basic_block) * n);
+ tos = worklist =
+ (basic_block *) xmalloc (sizeof (basic_block) * n_basic_blocks);
/* Clear all the reachability flags. */
- for (i = 0; i < n; ++i)
- BASIC_BLOCK (i)->flags &= ~BB_REACHABLE;
+ FOR_EACH_BB (bb)
+ bb->flags &= ~BB_REACHABLE;
/* Add our starting points to the worklist. Almost always there will
be only one. It isn't inconceivable that we might one day directly
@@ -461,8 +464,8 @@ create_edge_list ()
struct edge_list *elist;
edge e;
int num_edges;
- int x;
int block_count;
+ basic_block bb;
block_count = n_basic_blocks + 2; /* Include the entry and exit blocks. */
@@ -470,18 +473,12 @@ create_edge_list ()
/* Determine the number of edges in the flow graph by counting successor
edges on each basic block. */
- for (x = 0; x < n_basic_blocks; x++)
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
{
- basic_block bb = BASIC_BLOCK (x);
-
for (e = bb->succ; e; e = e->succ_next)
num_edges++;
}
- /* Don't forget successors of the entry block. */
- for (e = ENTRY_BLOCK_PTR->succ; e; e = e->succ_next)
- num_edges++;
-
elist = (struct edge_list *) xmalloc (sizeof (struct edge_list));
elist->num_blocks = block_count;
elist->num_edges = num_edges;
@@ -489,18 +486,10 @@ create_edge_list ()
num_edges = 0;
- /* Follow successors of the entry block, and register these edges. */
- for (e = ENTRY_BLOCK_PTR->succ; e; e = e->succ_next)
- elist->index_to_edge[num_edges++] = e;
-
- for (x = 0; x < n_basic_blocks; x++)
- {
- basic_block bb = BASIC_BLOCK (x);
-
- /* Follow all successors of blocks, and register these edges. */
- for (e = bb->succ; e; e = e->succ_next)
- elist->index_to_edge[num_edges++] = e;
- }
+ /* Follow successors of blocks, and register these edges. */
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
+ for (e = bb->succ; e; e = e->succ_next)
+ elist->index_to_edge[num_edges++] = e;
return elist;
}
@@ -554,13 +543,12 @@ verify_edge_list (f, elist)
FILE *f;
struct edge_list *elist;
{
- int x, pred, succ, index;
+ int pred, succ, index;
edge e;
+ basic_block bb, p, s;
- for (x = 0; x < n_basic_blocks; x++)
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
{
- basic_block bb = BASIC_BLOCK (x);
-
for (e = bb->succ; e; e = e->succ_next)
{
pred = e->src->index;
@@ -581,33 +569,12 @@ verify_edge_list (f, elist)
}
}
- for (e = ENTRY_BLOCK_PTR->succ; e; e = e->succ_next)
- {
- pred = e->src->index;
- succ = e->dest->index;
- index = EDGE_INDEX (elist, e->src, e->dest);
- if (index == EDGE_INDEX_NO_EDGE)
- {
- fprintf (f, "*p* No index for edge from %d to %d\n", pred, succ);
- continue;
- }
-
- if (INDEX_EDGE_PRED_BB (elist, index)->index != pred)
- fprintf (f, "*p* Pred for index %d should be %d not %d\n",
- index, pred, INDEX_EDGE_PRED_BB (elist, index)->index);
- if (INDEX_EDGE_SUCC_BB (elist, index)->index != succ)
- fprintf (f, "*p* Succ for index %d should be %d not %d\n",
- index, succ, INDEX_EDGE_SUCC_BB (elist, index)->index);
- }
-
- /* We've verified that all the edges are in the list, no lets make sure
+ /* We've verified that all the edges are in the list, now lets make sure
there are no spurious edges in the list. */
- for (pred = 0; pred < n_basic_blocks; pred++)
- for (succ = 0; succ < n_basic_blocks; succ++)
+ FOR_BB_BETWEEN (p, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
+ FOR_BB_BETWEEN (s, ENTRY_BLOCK_PTR->next_bb, NULL, next_bb)
{
- basic_block p = BASIC_BLOCK (pred);
- basic_block s = BASIC_BLOCK (succ);
int found_edge = 0;
for (e = p->succ; e; e = e->succ_next)
@@ -624,78 +591,15 @@ verify_edge_list (f, elist)
break;
}
- if (EDGE_INDEX (elist, BASIC_BLOCK (pred), BASIC_BLOCK (succ))
+ if (EDGE_INDEX (elist, p, s)
== EDGE_INDEX_NO_EDGE && found_edge != 0)
fprintf (f, "*** Edge (%d, %d) appears to not have an index\n",
- pred, succ);
- if (EDGE_INDEX (elist, BASIC_BLOCK (pred), BASIC_BLOCK (succ))
+ p->index, s->index);
+ if (EDGE_INDEX (elist, p, s)
!= EDGE_INDEX_NO_EDGE && found_edge == 0)
fprintf (f, "*** Edge (%d, %d) has index %d, but there is no edge\n",
- pred, succ, EDGE_INDEX (elist, BASIC_BLOCK (pred),
- BASIC_BLOCK (succ)));
+ p->index, s->index, EDGE_INDEX (elist, p, s));
}
-
- for (succ = 0; succ < n_basic_blocks; succ++)
- {
- basic_block p = ENTRY_BLOCK_PTR;
- basic_block s = BASIC_BLOCK (succ);
- int found_edge = 0;
-
- for (e = p->succ; e; e = e->succ_next)
- if (e->dest == s)
- {
- found_edge = 1;
- break;
- }
-
- for (e = s->pred; e; e = e->pred_next)
- if (e->src == p)
- {
- found_edge = 1;
- break;
- }
-
- if (EDGE_INDEX (elist, ENTRY_BLOCK_PTR, BASIC_BLOCK (succ))
- == EDGE_INDEX_NO_EDGE && found_edge != 0)
- fprintf (f, "*** Edge (entry, %d) appears to not have an index\n",
- succ);
- if (EDGE_INDEX (elist, ENTRY_BLOCK_PTR, BASIC_BLOCK (succ))
- != EDGE_INDEX_NO_EDGE && found_edge == 0)
- fprintf (f, "*** Edge (entry, %d) has index %d, but no edge exists\n",
- succ, EDGE_INDEX (elist, ENTRY_BLOCK_PTR,
- BASIC_BLOCK (succ)));
- }
-
- for (pred = 0; pred < n_basic_blocks; pred++)
- {
- basic_block p = BASIC_BLOCK (pred);
- basic_block s = EXIT_BLOCK_PTR;
- int found_edge = 0;
-
- for (e = p->succ; e; e = e->succ_next)
- if (e->dest == s)
- {
- found_edge = 1;
- break;
- }
-
- for (e = s->pred; e; e = e->pred_next)
- if (e->src == p)
- {
- found_edge = 1;
- break;
- }
-
- if (EDGE_INDEX (elist, BASIC_BLOCK (pred), EXIT_BLOCK_PTR)
- == EDGE_INDEX_NO_EDGE && found_edge != 0)
- fprintf (f, "*** Edge (%d, exit) appears to not have an index\n",
- pred);
- if (EDGE_INDEX (elist, BASIC_BLOCK (pred), EXIT_BLOCK_PTR)
- != EDGE_INDEX_NO_EDGE && found_edge == 0)
- fprintf (f, "*** Edge (%d, exit) has index %d, but no edge exists\n",
- pred, EDGE_INDEX (elist, BASIC_BLOCK (pred),
- EXIT_BLOCK_PTR));
- }
}
/* This routine will determine what, if any, edge there is between
@@ -784,13 +688,10 @@ remove_fake_successors (bb)
void
remove_fake_edges ()
{
- int x;
-
- for (x = 0; x < n_basic_blocks; x++)
- remove_fake_successors (BASIC_BLOCK (x));
+ basic_block bb;
- /* We've handled all successors except the entry block's. */
- remove_fake_successors (ENTRY_BLOCK_PTR);
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
+ remove_fake_successors (bb);
}
/* This function will add a fake edge between any block which has no
@@ -800,11 +701,11 @@ remove_fake_edges ()
void
add_noreturn_fake_exit_edges ()
{
- int x;
+ basic_block bb;
- for (x = 0; x < n_basic_blocks; x++)
- if (BASIC_BLOCK (x)->succ == NULL)
- make_single_succ_edge (BASIC_BLOCK (x), EXIT_BLOCK_PTR, EDGE_FAKE);
+ FOR_EACH_BB (bb)
+ if (bb->succ == NULL)
+ make_single_succ_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
}
/* This function adds a fake edge between any infinite loops to the
@@ -860,7 +761,7 @@ flow_reverse_top_sort_order_compute (rts_order)
sp = 0;
/* Allocate bitmap to track nodes that have been visited. */
- visited = sbitmap_alloc (n_basic_blocks);
+ visited = sbitmap_alloc (last_basic_block);
/* None of the nodes in the CFG have been visited yet. */
sbitmap_zero (visited);
@@ -909,8 +810,8 @@ flow_reverse_top_sort_order_compute (rts_order)
}
/* Compute the depth first search order and store in the array
- DFS_ORDER if non-zero, marking the nodes visited in VISITED. If
- RC_ORDER is non-zero, return the reverse completion number for each
+ DFS_ORDER if nonzero, marking the nodes visited in VISITED. If
+ RC_ORDER is nonzero, return the reverse completion number for each
node. Returns the number of nodes visited. A depth first search
tries to get as far away from the starting point as quickly as
possible. */
@@ -931,7 +832,7 @@ flow_depth_first_order_compute (dfs_order, rc_order)
sp = 0;
/* Allocate bitmap to track nodes that have been visited. */
- visited = sbitmap_alloc (n_basic_blocks);
+ visited = sbitmap_alloc (last_basic_block);
/* None of the nodes in the CFG have been visited yet. */
sbitmap_zero (visited);
@@ -1030,22 +931,23 @@ flow_preorder_transversal_compute (pot_order)
sbitmap visited;
struct dfst_node *node;
struct dfst_node *dfst;
+ basic_block bb;
/* Allocate stack for back-tracking up CFG. */
stack = (edge *) xmalloc ((n_basic_blocks + 1) * sizeof (edge));
sp = 0;
/* Allocate the tree. */
- dfst = (struct dfst_node *) xcalloc (n_basic_blocks,
+ dfst = (struct dfst_node *) xcalloc (last_basic_block,
sizeof (struct dfst_node));
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
max_successors = 0;
- for (e = BASIC_BLOCK (i)->succ; e; e = e->succ_next)
+ for (e = bb->succ; e; e = e->succ_next)
max_successors++;
- dfst[i].node
+ dfst[bb->index].node
= (max_successors
? (struct dfst_node **) xcalloc (max_successors,
sizeof (struct dfst_node *))
@@ -1053,7 +955,7 @@ flow_preorder_transversal_compute (pot_order)
}
/* Allocate bitmap to track nodes that have been visited. */
- visited = sbitmap_alloc (n_basic_blocks);
+ visited = sbitmap_alloc (last_basic_block);
/* None of the nodes in the CFG have been visited yet. */
sbitmap_zero (visited);
@@ -1104,7 +1006,7 @@ flow_preorder_transversal_compute (pot_order)
walking the tree from right to left. */
i = 0;
- node = &dfst[0];
+ node = &dfst[ENTRY_BLOCK_PTR->next_bb->index];
pot_order[i++] = 0;
while (node)
@@ -1120,7 +1022,7 @@ flow_preorder_transversal_compute (pot_order)
/* Free the tree. */
- for (i = 0; i < n_basic_blocks; i++)
+ for (i = 0; i < last_basic_block; i++)
if (dfst[i].node)
free (dfst[i].node);
@@ -1154,7 +1056,7 @@ flow_preorder_transversal_compute (pot_order)
/* Initialize the data structures used for depth-first search on the
reverse graph. If INITIALIZE_STACK is nonzero, the exit block is
added to the basic block stack. DATA is the current depth-first
- search context. If INITIALIZE_STACK is non-zero, there is an
+ search context. If INITIALIZE_STACK is nonzero, there is an
element on the stack. */
static void
@@ -1167,7 +1069,7 @@ flow_dfs_compute_reverse_init (data)
data->sp = 0;
/* Allocate bitmap to track nodes that have been visited. */
- data->visited_blocks = sbitmap_alloc (n_basic_blocks - (INVALID_BLOCK + 1));
+ data->visited_blocks = sbitmap_alloc (last_basic_block - (INVALID_BLOCK + 1));
/* None of the nodes in the CFG have been visited yet. */
sbitmap_zero (data->visited_blocks);
@@ -1199,7 +1101,6 @@ flow_dfs_compute_reverse_execute (data)
{
basic_block bb;
edge e;
- int i;
while (data->sp > 0)
{
@@ -1213,9 +1114,9 @@ flow_dfs_compute_reverse_execute (data)
}
/* Determine if there are unvisited basic blocks. */
- for (i = n_basic_blocks - (INVALID_BLOCK + 1); --i >= 0; )
- if (!TEST_BIT (data->visited_blocks, i))
- return BASIC_BLOCK (i + (INVALID_BLOCK + 1));
+ FOR_BB_BETWEEN (bb, EXIT_BLOCK_PTR, NULL, prev_bb)
+ if (!TEST_BIT (data->visited_blocks, bb->index - (INVALID_BLOCK + 1)))
+ return bb;
return NULL;
}
@@ -1230,3 +1131,54 @@ flow_dfs_compute_reverse_finish (data)
free (data->stack);
sbitmap_free (data->visited_blocks);
}
+
+/* Performs dfs search from BB over vertices satisfying PREDICATE;
+ if REVERSE, go against direction of edges. Returns number of blocks
+ found and their list in RSLT. RSLT can contain at most RSLT_MAX items. */
+int
+dfs_enumerate_from (bb, reverse, predicate, rslt, rslt_max, data)
+ basic_block bb;
+ int reverse;
+ bool (*predicate) PARAMS ((basic_block, void *));
+ basic_block *rslt;
+ int rslt_max;
+ void *data;
+{
+ basic_block *st, lbb;
+ int sp = 0, tv = 0;
+
+ st = xcalloc (rslt_max, sizeof (basic_block));
+ rslt[tv++] = st[sp++] = bb;
+ bb->flags |= BB_VISITED;
+ while (sp)
+ {
+ edge e;
+ lbb = st[--sp];
+ if (reverse)
+ {
+ for (e = lbb->pred; e; e = e->pred_next)
+ if (!(e->src->flags & BB_VISITED) && predicate (e->src, data))
+ {
+ if (tv == rslt_max)
+ abort ();
+ rslt[tv++] = st[sp++] = e->src;
+ e->src->flags |= BB_VISITED;
+ }
+ }
+ else
+ {
+ for (e = lbb->succ; e; e = e->succ_next)
+ if (!(e->dest->flags & BB_VISITED) && predicate (e->dest, data))
+ {
+ if (tv == rslt_max)
+ abort ();
+ rslt[tv++] = st[sp++] = e->dest;
+ e->dest->flags |= BB_VISITED;
+ }
+ }
+ }
+ free (st);
+ for (sp = 0; sp < tv; sp++)
+ rslt[sp]->flags &= ~BB_VISITED;
+ return tv;
+}
diff --git a/contrib/gcc/cfgbuild.c b/contrib/gcc/cfgbuild.c
index 3a5af2d..795ae17 100644
--- a/contrib/gcc/cfgbuild.c
+++ b/contrib/gcc/cfgbuild.c
@@ -1,6 +1,6 @@
/* Control flow graph building code for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -45,12 +45,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "except.h"
#include "toplev.h"
#include "timevar.h"
-#include "obstack.h"
static int count_basic_blocks PARAMS ((rtx));
static void find_basic_blocks_1 PARAMS ((rtx));
static rtx find_label_refs PARAMS ((rtx, rtx));
-static void make_edges PARAMS ((rtx, int, int, int));
+static void make_edges PARAMS ((rtx, basic_block,
+ basic_block, int));
static void make_label_edge PARAMS ((sbitmap *, basic_block,
rtx, int));
static void make_eh_edge PARAMS ((sbitmap *, basic_block, rtx));
@@ -102,35 +102,35 @@ control_flow_insn_p (insn)
switch (GET_CODE (insn))
{
- case NOTE:
- case CODE_LABEL:
- return false;
-
- case JUMP_INSN:
- /* Jump insn always causes control transfer except for tablejumps. */
- return (GET_CODE (PATTERN (insn)) != ADDR_VEC
- && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC);
-
- case CALL_INSN:
- /* Call insn may return to the nonlocal goto handler. */
- return ((nonlocal_goto_handler_labels
- && (0 == (note = find_reg_note (insn, REG_EH_REGION,
- NULL_RTX))
- || INTVAL (XEXP (note, 0)) >= 0))
- /* Or may trap. */
- || can_throw_internal (insn));
-
- case INSN:
- return (flag_non_call_exceptions && can_throw_internal (insn));
-
- case BARRIER:
- /* It is nonsence to reach barrier when looking for the
- end of basic block, but before dead code is eliminated
- this may happen. */
- return false;
-
- default:
- abort ();
+ case NOTE:
+ case CODE_LABEL:
+ return false;
+
+ case JUMP_INSN:
+ /* Jump insn always causes control transfer except for tablejumps. */
+ return (GET_CODE (PATTERN (insn)) != ADDR_VEC
+ && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC);
+
+ case CALL_INSN:
+ /* Call insn may return to the nonlocal goto handler. */
+ return ((nonlocal_goto_handler_labels
+ && (0 == (note = find_reg_note (insn, REG_EH_REGION,
+ NULL_RTX))
+ || INTVAL (XEXP (note, 0)) >= 0))
+ /* Or may trap. */
+ || can_throw_internal (insn));
+
+ case INSN:
+ return (flag_non_call_exceptions && can_throw_internal (insn));
+
+ case BARRIER:
+ /* It is nonsence to reach barrier when looking for the
+ end of basic block, but before dead code is eliminated
+ this may happen. */
+ return false;
+
+ default:
+ abort ();
}
}
@@ -205,9 +205,9 @@ find_label_refs (f, lvl)
rtx lab = XEXP (note, 0), next;
if ((next = next_nonnote_insn (lab)) != NULL
- && GET_CODE (next) == JUMP_INSN
- && (GET_CODE (PATTERN (next)) == ADDR_VEC
- || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
+ && GET_CODE (next) == JUMP_INSN
+ && (GET_CODE (PATTERN (next)) == ADDR_VEC
+ || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
;
else if (GET_CODE (lab) == NOTE)
;
@@ -279,9 +279,10 @@ make_eh_edge (edge_cache, src, insn)
static void
make_edges (label_value_list, min, max, update_p)
rtx label_value_list;
- int min, max, update_p;
+ basic_block min, max;
+ int update_p;
{
- int i;
+ basic_block bb;
sbitmap *edge_cache = NULL;
/* Assume no computed jump; revise as we create edges. */
@@ -290,35 +291,35 @@ make_edges (label_value_list, min, max, update_p)
/* Heavy use of computed goto in machine-generated code can lead to
nearly fully-connected CFGs. In that case we spend a significant
amount of time searching the edge lists for duplicates. */
- if (forced_labels || label_value_list)
+ if (forced_labels || label_value_list || cfun->max_jumptable_ents > 100)
{
- edge_cache = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
- sbitmap_vector_zero (edge_cache, n_basic_blocks);
+ edge_cache = sbitmap_vector_alloc (last_basic_block, last_basic_block);
+ sbitmap_vector_zero (edge_cache, last_basic_block);
if (update_p)
- for (i = min; i <= max; ++i)
+ FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
{
edge e;
- for (e = BASIC_BLOCK (i)->succ; e ; e = e->succ_next)
+ for (e = bb->succ; e ; e = e->succ_next)
if (e->dest != EXIT_BLOCK_PTR)
- SET_BIT (edge_cache[i], e->dest->index);
+ SET_BIT (edge_cache[bb->index], e->dest->index);
}
}
- /* By nature of the way these get numbered, block 0 is always the entry. */
- if (min == 0)
- cached_make_edge (edge_cache, ENTRY_BLOCK_PTR, BASIC_BLOCK (0),
+ /* By nature of the way these get numbered, ENTRY_BLOCK_PTR->next_bb block
+ is always the entry. */
+ if (min == ENTRY_BLOCK_PTR->next_bb)
+ cached_make_edge (edge_cache, ENTRY_BLOCK_PTR, min,
EDGE_FALLTHRU);
- for (i = min; i <= max; ++i)
+ FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
{
- basic_block bb = BASIC_BLOCK (i);
rtx insn, x;
enum rtx_code code;
int force_fallthru = 0;
- if (GET_CODE (bb->head) == CODE_LABEL && LABEL_ALTERNATE_NAME (bb->head))
+ if (GET_CODE (bb->head) == CODE_LABEL && LABEL_ALT_ENTRY_P (bb->head))
cached_make_edge (NULL, ENTRY_BLOCK_PTR, bb, 0);
/* Examine the last instruction of the block, and discover the
@@ -442,16 +443,15 @@ make_edges (label_value_list, min, max, update_p)
/* Find out if we can drop through to the next block. */
insn = next_nonnote_insn (insn);
- if (!insn || (i + 1 == n_basic_blocks && force_fallthru))
+ if (!insn || (bb->next_bb == EXIT_BLOCK_PTR && force_fallthru))
cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
- else if (i + 1 < n_basic_blocks)
+ else if (bb->next_bb != EXIT_BLOCK_PTR)
{
- rtx tmp = BLOCK_HEAD (i + 1);
+ rtx tmp = bb->next_bb->head;
if (GET_CODE (tmp) == NOTE)
tmp = next_nonnote_insn (tmp);
if (force_fallthru || insn == tmp)
- cached_make_edge (edge_cache, bb, BASIC_BLOCK (i + 1),
- EDGE_FALLTHRU);
+ cached_make_edge (edge_cache, bb, bb->next_bb, EDGE_FALLTHRU);
}
}
@@ -469,12 +469,12 @@ find_basic_blocks_1 (f)
rtx f;
{
rtx insn, next;
- int i = 0;
rtx bb_note = NULL_RTX;
rtx lvl = NULL_RTX;
rtx trll = NULL_RTX;
rtx head = NULL_RTX;
rtx end = NULL_RTX;
+ basic_block prev = ENTRY_BLOCK_PTR;
/* We process the instructions in a slightly different way than we did
previously. This is so that we see a NOTE_BASIC_BLOCK after we have
@@ -491,7 +491,7 @@ find_basic_blocks_1 (f)
if ((GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == BARRIER)
&& head)
{
- create_basic_block_structure (i++, head, end, bb_note);
+ prev = create_basic_block_structure (head, end, bb_note, prev);
head = end = NULL_RTX;
bb_note = NULL_RTX;
}
@@ -505,7 +505,7 @@ find_basic_blocks_1 (f)
if (head && control_flow_insn_p (insn))
{
- create_basic_block_structure (i++, head, end, bb_note);
+ prev = create_basic_block_structure (head, end, bb_note, prev);
head = end = NULL_RTX;
bb_note = NULL_RTX;
}
@@ -587,15 +587,16 @@ find_basic_blocks_1 (f)
}
if (head != NULL_RTX)
- create_basic_block_structure (i++, head, end, bb_note);
+ create_basic_block_structure (head, end, bb_note, prev);
else if (bb_note)
delete_insn (bb_note);
- if (i != n_basic_blocks)
+ if (last_basic_block != n_basic_blocks)
abort ();
label_value_list = lvl;
tail_recursion_label_list = trll;
+ clear_aux_for_blocks ();
}
@@ -609,28 +610,28 @@ find_basic_blocks (f, nregs, file)
int nregs ATTRIBUTE_UNUSED;
FILE *file ATTRIBUTE_UNUSED;
{
- int max_uid;
- timevar_push (TV_CFG);
+ basic_block bb;
- basic_block_for_insn = 0;
+ timevar_push (TV_CFG);
/* Flush out existing data. */
if (basic_block_info != NULL)
{
- int i;
-
clear_edges ();
/* Clear bb->aux on all extant basic blocks. We'll use this as a
tag for reuse during create_basic_block, just in case some pass
copies around basic block notes improperly. */
- for (i = 0; i < n_basic_blocks; ++i)
- BASIC_BLOCK (i)->aux = NULL;
+ FOR_EACH_BB (bb)
+ bb->aux = NULL;
VARRAY_FREE (basic_block_info);
}
n_basic_blocks = count_basic_blocks (f);
+ last_basic_block = 0;
+ ENTRY_BLOCK_PTR->next_bb = EXIT_BLOCK_PTR;
+ EXIT_BLOCK_PTR->prev_bb = ENTRY_BLOCK_PTR;
/* Size the basic block table. The actual structures will be allocated
by find_basic_blocks_1, since we want to keep the structure pointers
@@ -644,22 +645,8 @@ find_basic_blocks (f, nregs, file)
find_basic_blocks_1 (f);
- /* Record the block to which an insn belongs. */
- /* ??? This should be done another way, by which (perhaps) a label is
- tagged directly with the basic block that it starts. It is used for
- more than that currently, but IMO that is the only valid use. */
-
- max_uid = get_max_uid ();
-#ifdef AUTO_INC_DEC
- /* Leave space for insns life_analysis makes in some cases for auto-inc.
- These cases are rare, so we don't need too much space. */
- max_uid += max_uid / 10;
-#endif
-
- compute_bb_for_insn (max_uid);
-
/* Discover the edges of our cfg. */
- make_edges (label_value_list, 0, n_basic_blocks - 1, 0);
+ make_edges (label_value_list, ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR->prev_bb, 0);
/* Do very simple cleanup now, for the benefit of code that runs between
here and cleanup_cfg, e.g. thread_prologue_and_epilogue_insns. */
@@ -710,7 +697,7 @@ find_bb_boundaries (bb)
bb = fallthru->dest;
remove_edge (fallthru);
flow_transfer_insn = NULL_RTX;
- if (LABEL_ALTERNATE_NAME (insn))
+ if (LABEL_ALT_ENTRY_P (insn))
make_edge (ENTRY_BLOCK_PTR, bb, 0);
}
@@ -788,25 +775,24 @@ void
find_many_sub_basic_blocks (blocks)
sbitmap blocks;
{
- int i;
- int min, max;
+ basic_block bb, min, max;
- for (i = 0; i < n_basic_blocks; i++)
- SET_STATE (BASIC_BLOCK (i),
- TEST_BIT (blocks, i) ? BLOCK_TO_SPLIT : BLOCK_ORIGINAL);
+ FOR_EACH_BB (bb)
+ SET_STATE (bb,
+ TEST_BIT (blocks, bb->index) ? BLOCK_TO_SPLIT : BLOCK_ORIGINAL);
- for (i = 0; i < n_basic_blocks; i++)
- if (STATE (BASIC_BLOCK (i)) == BLOCK_TO_SPLIT)
- find_bb_boundaries (BASIC_BLOCK (i));
+ FOR_EACH_BB (bb)
+ if (STATE (bb) == BLOCK_TO_SPLIT)
+ find_bb_boundaries (bb);
- for (i = 0; i < n_basic_blocks; i++)
- if (STATE (BASIC_BLOCK (i)) != BLOCK_ORIGINAL)
+ FOR_EACH_BB (bb)
+ if (STATE (bb) != BLOCK_ORIGINAL)
break;
- min = max = i;
- for (; i < n_basic_blocks; i++)
- if (STATE (BASIC_BLOCK (i)) != BLOCK_ORIGINAL)
- max = i;
+ min = max = bb;
+ for (; bb != EXIT_BLOCK_PTR; bb = bb->next_bb)
+ if (STATE (bb) != BLOCK_ORIGINAL)
+ max = bb;
/* Now re-scan and wire in all edges. This expect simple (conditional)
jumps at the end of each new basic blocks. */
@@ -814,45 +800,42 @@ find_many_sub_basic_blocks (blocks)
/* Update branch probabilities. Expect only (un)conditional jumps
to be created with only the forward edges. */
- for (i = min; i <= max; i++)
+ FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
{
edge e;
- basic_block b = BASIC_BLOCK (i);
- if (STATE (b) == BLOCK_ORIGINAL)
+ if (STATE (bb) == BLOCK_ORIGINAL)
continue;
- if (STATE (b) == BLOCK_NEW)
+ if (STATE (bb) == BLOCK_NEW)
{
- b->count = 0;
- b->frequency = 0;
- for (e = b->pred; e; e=e->pred_next)
+ bb->count = 0;
+ bb->frequency = 0;
+ for (e = bb->pred; e; e=e->pred_next)
{
- b->count += e->count;
- b->frequency += EDGE_FREQUENCY (e);
+ bb->count += e->count;
+ bb->frequency += EDGE_FREQUENCY (e);
}
}
- compute_outgoing_frequencies (b);
+ compute_outgoing_frequencies (bb);
}
- for (i = 0; i < n_basic_blocks; i++)
- SET_STATE (BASIC_BLOCK (i), 0);
+ FOR_EACH_BB (bb)
+ SET_STATE (bb, 0);
}
/* Like above but for single basic block only. */
void
find_sub_basic_blocks (bb)
- basic_block bb;
+ basic_block bb;
{
- int i;
- int min, max;
- basic_block next = (bb->index == n_basic_blocks - 1
- ? NULL : BASIC_BLOCK (bb->index + 1));
+ basic_block min, max, b;
+ basic_block next = bb->next_bb;
- min = bb->index;
+ min = bb;
find_bb_boundaries (bb);
- max = (next ? next->index : n_basic_blocks) - 1;
+ max = next->prev_bb;
/* Now re-scan and wire in all edges. This expect simple (conditional)
jumps at the end of each new basic blocks. */
@@ -860,12 +843,11 @@ find_sub_basic_blocks (bb)
/* Update branch probabilities. Expect only (un)conditional jumps
to be created with only the forward edges. */
- for (i = min; i <= max; i++)
+ FOR_BB_BETWEEN (b, min, max->next_bb, next_bb)
{
edge e;
- basic_block b = BASIC_BLOCK (i);
- if (i != min)
+ if (b != min)
{
b->count = 0;
b->frequency = 0;
diff --git a/contrib/gcc/cfgcleanup.c b/contrib/gcc/cfgcleanup.c
index 9589d1f..008c8da 100644
--- a/contrib/gcc/cfgcleanup.c
+++ b/contrib/gcc/cfgcleanup.c
@@ -43,20 +43,18 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "recog.h"
#include "toplev.h"
#include "cselib.h"
+#include "params.h"
#include "tm_p.h"
#include "target.h"
-#include "obstack.h"
-
/* cleanup_cfg maintains following flags for each basic block. */
enum bb_flags
{
- /* Set if life info needs to be recomputed for given BB. */
- BB_UPDATE_LIFE = 1,
/* Set if BB is the forwarder block to avoid too many
forwarder_block_p calls. */
- BB_FORWARDER_BLOCK = 2
+ BB_FORWARDER_BLOCK = 1,
+ BB_NONTHREADABLE_BLOCK = 2
};
#define BB_FLAGS(BB) (enum bb_flags) (BB)->aux
@@ -75,7 +73,6 @@ static int flow_find_cross_jump PARAMS ((int, basic_block, basic_block,
rtx *, rtx *));
static bool insns_match_p PARAMS ((int, rtx, rtx));
-static bool delete_unreachable_blocks PARAMS ((void));
static bool label_is_jump_target_p PARAMS ((rtx, rtx));
static bool tail_recursion_label_p PARAMS ((rtx));
static void merge_blocks_move_predecessor_nojumps PARAMS ((basic_block,
@@ -91,6 +88,7 @@ static edge thread_jump PARAMS ((int, edge, basic_block));
static bool mark_effect PARAMS ((rtx, bitmap));
static void notice_new_block PARAMS ((basic_block));
static void update_forwarder_flag PARAMS ((basic_block));
+static int mentions_nonequal_regs PARAMS ((rtx *, void *));
/* Set flags for newly created block. */
@@ -101,7 +99,6 @@ notice_new_block (bb)
if (!bb)
return;
- BB_SET_FLAG (bb, BB_UPDATE_LIFE);
if (forwarder_block_p (bb))
BB_SET_FLAG (bb, BB_FORWARDER_BLOCK);
}
@@ -149,7 +146,7 @@ try_simplify_condjump (cbranch_block)
unconditional jump. */
jump_block = cbranch_fallthru_edge->dest;
if (jump_block->pred->pred_next
- || jump_block->index == n_basic_blocks - 1
+ || jump_block->next_bb == EXIT_BLOCK_PTR
|| !FORWARDER_BLOCK_P (jump_block))
return false;
jump_dest_block = jump_block->succ->dest;
@@ -192,8 +189,8 @@ try_simplify_condjump (cbranch_block)
static bool
mark_effect (exp, nonequal)
- rtx exp;
- regset nonequal;
+ rtx exp;
+ regset nonequal;
{
int regno;
rtx dest;
@@ -201,43 +198,69 @@ mark_effect (exp, nonequal)
{
/* In case we do clobber the register, mark it as equal, as we know the
value is dead so it don't have to match. */
- case CLOBBER:
- if (REG_P (XEXP (exp, 0)))
- {
- dest = XEXP (exp, 0);
- regno = REGNO (dest);
- CLEAR_REGNO_REG_SET (nonequal, regno);
- if (regno < FIRST_PSEUDO_REGISTER)
- {
- int n = HARD_REGNO_NREGS (regno, GET_MODE (dest));
- while (--n > 0)
- CLEAR_REGNO_REG_SET (nonequal, regno + n);
- }
- }
- return false;
+ case CLOBBER:
+ if (REG_P (XEXP (exp, 0)))
+ {
+ dest = XEXP (exp, 0);
+ regno = REGNO (dest);
+ CLEAR_REGNO_REG_SET (nonequal, regno);
+ if (regno < FIRST_PSEUDO_REGISTER)
+ {
+ int n = HARD_REGNO_NREGS (regno, GET_MODE (dest));
+ while (--n > 0)
+ CLEAR_REGNO_REG_SET (nonequal, regno + n);
+ }
+ }
+ return false;
- case SET:
- if (rtx_equal_for_cselib_p (SET_DEST (exp), SET_SRC (exp)))
- return false;
- dest = SET_DEST (exp);
- if (dest == pc_rtx)
- return false;
- if (!REG_P (dest))
- return true;
- regno = REGNO (dest);
- SET_REGNO_REG_SET (nonequal, regno);
- if (regno < FIRST_PSEUDO_REGISTER)
- {
- int n = HARD_REGNO_NREGS (regno, GET_MODE (dest));
- while (--n > 0)
- SET_REGNO_REG_SET (nonequal, regno + n);
- }
+ case SET:
+ if (rtx_equal_for_cselib_p (SET_DEST (exp), SET_SRC (exp)))
return false;
-
- default:
+ dest = SET_DEST (exp);
+ if (dest == pc_rtx)
return false;
+ if (!REG_P (dest))
+ return true;
+ regno = REGNO (dest);
+ SET_REGNO_REG_SET (nonequal, regno);
+ if (regno < FIRST_PSEUDO_REGISTER)
+ {
+ int n = HARD_REGNO_NREGS (regno, GET_MODE (dest));
+ while (--n > 0)
+ SET_REGNO_REG_SET (nonequal, regno + n);
+ }
+ return false;
+
+ default:
+ return false;
}
}
+
+/* Return nonzero if X is an register set in regset DATA.
+ Called via for_each_rtx. */
+static int
+mentions_nonequal_regs (x, data)
+ rtx *x;
+ void *data;
+{
+ regset nonequal = (regset) data;
+ if (REG_P (*x))
+ {
+ int regno;
+
+ regno = REGNO (*x);
+ if (REGNO_REG_SET_P (nonequal, regno))
+ return 1;
+ if (regno < FIRST_PSEUDO_REGISTER)
+ {
+ int n = HARD_REGNO_NREGS (regno, GET_MODE (*x));
+ while (--n > 0)
+ if (REGNO_REG_SET_P (nonequal, regno + n))
+ return 1;
+ }
+ }
+ return 0;
+}
/* Attempt to prove that the basic block B will have no side effects and
allways continues in the same edge if reached via E. Return the edge
if exist, NULL otherwise. */
@@ -255,18 +278,29 @@ thread_jump (mode, e, b)
regset nonequal;
bool failed = false;
+ if (BB_FLAGS (b) & BB_NONTHREADABLE_BLOCK)
+ return NULL;
+
/* At the moment, we do handle only conditional jumps, but later we may
want to extend this code to tablejumps and others. */
if (!e->src->succ->succ_next || e->src->succ->succ_next->succ_next)
return NULL;
if (!b->succ || !b->succ->succ_next || b->succ->succ_next->succ_next)
- return NULL;
+ {
+ BB_SET_FLAG (b, BB_NONTHREADABLE_BLOCK);
+ return NULL;
+ }
/* Second branch must end with onlyjump, as we will eliminate the jump. */
- if (!any_condjump_p (e->src->end) || !any_condjump_p (b->end)
- || !onlyjump_p (b->end))
+ if (!any_condjump_p (e->src->end))
return NULL;
+ if (!any_condjump_p (b->end) || !onlyjump_p (b->end))
+ {
+ BB_SET_FLAG (b, BB_NONTHREADABLE_BLOCK);
+ return NULL;
+ }
+
set1 = pc_set (e->src->end);
set2 = pc_set (b->end);
if (((e->flags & EDGE_FALLTHRU) != 0)
@@ -300,7 +334,10 @@ thread_jump (mode, e, b)
for (insn = NEXT_INSN (b->head); insn != NEXT_INSN (b->end);
insn = NEXT_INSN (insn))
if (INSN_P (insn) && side_effects_p (PATTERN (insn)))
- return NULL;
+ {
+ BB_SET_FLAG (b, BB_NONTHREADABLE_BLOCK);
+ return NULL;
+ }
cselib_init ();
@@ -319,26 +356,34 @@ thread_jump (mode, e, b)
for (insn = NEXT_INSN (b->head); insn != NEXT_INSN (b->end) && !failed;
insn = NEXT_INSN (insn))
- {
- if (INSN_P (insn))
- {
- rtx pat = PATTERN (insn);
-
- if (GET_CODE (pat) == PARALLEL)
- {
- for (i = 0; i < XVECLEN (pat, 0); i++)
- failed |= mark_effect (XVECEXP (pat, 0, i), nonequal);
- }
- else
- failed |= mark_effect (pat, nonequal);
- }
+ {
+ if (INSN_P (insn))
+ {
+ rtx pat = PATTERN (insn);
+
+ if (GET_CODE (pat) == PARALLEL)
+ {
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ failed |= mark_effect (XVECEXP (pat, 0, i), nonequal);
+ }
+ else
+ failed |= mark_effect (pat, nonequal);
+ }
- cselib_process_insn (insn);
- }
+ cselib_process_insn (insn);
+ }
/* Later we should clear nonequal of dead registers. So far we don't
have life information in cfg_cleanup. */
if (failed)
+ {
+ BB_SET_FLAG (b, BB_NONTHREADABLE_BLOCK);
+ goto failed_exit;
+ }
+
+ /* cond2 must not mention any register that is not equal to the
+ former block. */
+ if (for_each_rtx (&cond2, mentions_nonequal_regs, nonequal))
goto failed_exit;
/* In case liveness information is available, we need to prove equivalence
@@ -455,10 +500,10 @@ try_forward_edges (mode, b)
For fallthru forwarders, the LOOP_BEG note must appear between
the header of block and CODE_LABEL of the loop, for non forwarders
it must appear before the JUMP_INSN. */
- if (mode & CLEANUP_PRE_LOOP)
+ if ((mode & CLEANUP_PRE_LOOP) && optimize)
{
rtx insn = (target->succ->flags & EDGE_FALLTHRU
- ? target->head : prev_nonnote_insn (target->end));
+ ? target->head : prev_nonnote_insn (target->end));
if (GET_CODE (insn) != NOTE)
insn = NEXT_INSN (insn);
@@ -469,14 +514,23 @@ try_forward_edges (mode, b)
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
break;
- if (insn && GET_CODE (insn) == NOTE)
+ if (GET_CODE (insn) == NOTE)
+ break;
+
+ /* Do not clean up branches to just past the end of a loop
+ at this time; it can mess up the loop optimizer's
+ recognition of some patterns. */
+
+ insn = PREV_INSN (target->head);
+ if (insn && GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
break;
}
counter++;
target = new_target;
threaded |= new_target_threaded;
- }
+ }
if (counter >= n_basic_blocks)
{
@@ -499,7 +553,7 @@ try_forward_edges (mode, b)
{
notice_new_block (redirect_edge_and_branch_force (e, target));
if (rtl_dump_file)
- fprintf (rtl_dump_file, "Conditionals threaded.\n");
+ fprintf (rtl_dump_file, "Conditionals threaded.\n");
}
else if (!redirect_edge_and_branch (e, target))
{
@@ -519,7 +573,6 @@ try_forward_edges (mode, b)
if (!FORWARDER_BLOCK_P (b) && forwarder_block_p (b))
BB_SET_FLAG (b, BB_FORWARDER_BLOCK);
- BB_SET_FLAG (b, BB_UPDATE_LIFE);
do
{
@@ -569,7 +622,7 @@ try_forward_edges (mode, b)
&& first == threaded_edges [n]->src)
n++;
t = first->succ;
- }
+ }
t->count -= edge_count;
if (t->count < 0)
@@ -643,7 +696,6 @@ merge_blocks_move_predecessor_nojumps (a, b)
basic_block a, b;
{
rtx barrier;
- int index;
barrier = next_nonnote_insn (a->end);
if (GET_CODE (barrier) != BARRIER)
@@ -663,20 +715,16 @@ merge_blocks_move_predecessor_nojumps (a, b)
/* Scramble the insn chain. */
if (a->end != PREV_INSN (b->head))
reorder_insns_nobb (a->head, a->end, PREV_INSN (b->head));
- BB_SET_FLAG (a, BB_UPDATE_LIFE);
+ a->flags |= BB_DIRTY;
if (rtl_dump_file)
fprintf (rtl_dump_file, "Moved block %d before %d and merged.\n",
a->index, b->index);
- /* Swap the records for the two blocks around. Although we are deleting B,
- A is now where B was and we want to compact the BB array from where
- A used to be. */
- BASIC_BLOCK (a->index) = b;
- BASIC_BLOCK (b->index) = a;
- index = a->index;
- a->index = b->index;
- b->index = index;
+ /* Swap the records for the two blocks around. */
+
+ unlink_block (a);
+ link_block (a, b->prev_bb);
/* Now blocks A and B are contiguous. Merge them. */
merge_blocks_nomove (a, b);
@@ -729,13 +777,12 @@ merge_blocks_move_successor_nojumps (a, b)
/* Restore the real end of b. */
b->end = real_b_end;
- /* Now blocks A and B are contiguous. Merge them. */
- merge_blocks_nomove (a, b);
- BB_SET_FLAG (a, BB_UPDATE_LIFE);
-
if (rtl_dump_file)
fprintf (rtl_dump_file, "Moved block %d after %d and merged.\n",
b->index, a->index);
+
+ /* Now blocks A and B are contiguous. Merge them. */
+ merge_blocks_nomove (a, b);
}
/* Attempt to merge basic blocks that are potentially non-adjacent.
@@ -760,18 +807,12 @@ merge_blocks (e, b, c, mode)
if (e->flags & EDGE_FALLTHRU)
{
int b_index = b->index, c_index = c->index;
- /* We need to update liveness in case C already has broken liveness
- or B ends by conditional jump to next instructions that will be
- removed. */
- if ((BB_FLAGS (c) & BB_UPDATE_LIFE)
- || GET_CODE (b->end) == JUMP_INSN)
- BB_SET_FLAG (b, BB_UPDATE_LIFE);
merge_blocks_nomove (b, c);
update_forwarder_flag (b);
if (rtl_dump_file)
fprintf (rtl_dump_file, "Merged %d and %d without moving.\n",
- b_index, c_index);
+ b_index, c_index);
return true;
}
@@ -831,8 +872,6 @@ merge_blocks (e, b, c, mode)
bb = force_nonfallthru (b_fallthru_edge);
if (bb)
notice_new_block (bb);
- else
- BB_SET_FLAG (b_fallthru_edge->src, BB_UPDATE_LIFE);
}
merge_blocks_move_predecessor_nojumps (b, c);
@@ -847,8 +886,8 @@ merge_blocks (e, b, c, mode)
static bool
insns_match_p (mode, i1, i2)
- int mode ATTRIBUTE_UNUSED;
- rtx i1, i2;
+ int mode ATTRIBUTE_UNUSED;
+ rtx i1, i2;
{
rtx p1, p2;
@@ -873,8 +912,9 @@ insns_match_p (mode, i1, i2)
equal, they were constructed identically. */
if (GET_CODE (i1) == CALL_INSN
- && !rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1),
- CALL_INSN_FUNCTION_USAGE (i2)))
+ && (!rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1),
+ CALL_INSN_FUNCTION_USAGE (i2))
+ || SIBLING_CALL_P (i1) != SIBLING_CALL_P (i2)))
return false;
#ifdef STACK_REGS
@@ -988,10 +1028,10 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2)
while (true)
{
/* Ignore notes. */
- while (!active_insn_p (i1) && i1 != bb1->head)
+ while (!INSN_P (i1) && i1 != bb1->head)
i1 = PREV_INSN (i1);
- while (!active_insn_p (i2) && i2 != bb2->head)
+ while (!INSN_P (i2) && i2 != bb2->head)
i2 = PREV_INSN (i2);
if (i1 == bb1->head || i2 == bb2->head)
@@ -1000,8 +1040,8 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2)
if (!insns_match_p (mode, i1, i2))
break;
- /* Don't begin a cross-jump with a USE or CLOBBER insn. */
- if (active_insn_p (i1))
+ /* Don't begin a cross-jump with a NOTE insn. */
+ if (INSN_P (i1))
{
/* If the merged insns have different REG_EQUAL notes, then
remove them. */
@@ -1018,10 +1058,10 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2)
remove_note (i1, equiv1);
remove_note (i2, equiv2);
}
-
+
afterlast1 = last1, afterlast2 = last2;
last1 = i1, last2 = i2;
- ninsns++;
+ ninsns++;
}
i1 = PREV_INSN (i1);
@@ -1040,13 +1080,13 @@ flow_find_cross_jump (mode, bb1, bb2, f1, f2)
Two, it keeps line number notes as matched as may be. */
if (ninsns)
{
- while (last1 != bb1->head && !active_insn_p (PREV_INSN (last1)))
+ while (last1 != bb1->head && !INSN_P (PREV_INSN (last1)))
last1 = PREV_INSN (last1);
if (last1 != bb1->head && GET_CODE (PREV_INSN (last1)) == CODE_LABEL)
last1 = PREV_INSN (last1);
- while (last2 != bb2->head && !active_insn_p (PREV_INSN (last2)))
+ while (last2 != bb2->head && !INSN_P (PREV_INSN (last2)))
last2 = PREV_INSN (last2);
if (last2 != bb2->head && GET_CODE (PREV_INSN (last2)) == CODE_LABEL)
@@ -1078,9 +1118,11 @@ outgoing_edges_match (mode, bb1, bb2)
/* If BB1 has only one successor, we may be looking at either an
unconditional jump, or a fake edge to exit. */
if (bb1->succ && !bb1->succ->succ_next
- && !(bb1->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)))
+ && (bb1->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0
+ && (GET_CODE (bb1->end) != JUMP_INSN || simplejump_p (bb1->end)))
return (bb2->succ && !bb2->succ->succ_next
- && (bb2->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0);
+ && (bb2->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0
+ && (GET_CODE (bb2->end) != JUMP_INSN || simplejump_p (bb2->end)));
/* Match conditional jumps - this may get tricky when fallthru and branch
edges are crossed. */
@@ -1096,7 +1138,7 @@ outgoing_edges_match (mode, bb1, bb2)
enum rtx_code code1, code2;
if (!bb2->succ
- || !bb2->succ->succ_next
+ || !bb2->succ->succ_next
|| bb2->succ->succ_next->succ_next
|| !any_condjump_p (bb2->end)
|| !onlyjump_p (bb2->end))
@@ -1175,8 +1217,8 @@ outgoing_edges_match (mode, bb1, bb2)
roughly similar. */
if (match
&& !optimize_size
- && bb1->frequency > BB_FREQ_MAX / 1000
- && bb2->frequency > BB_FREQ_MAX / 1000)
+ && maybe_hot_bb_p (bb1)
+ && maybe_hot_bb_p (bb2))
{
int prob2;
@@ -1207,7 +1249,7 @@ outgoing_edges_match (mode, bb1, bb2)
return match;
}
- /* Generic case - we are seeing an computed jump, table jump or trapping
+ /* Generic case - we are seeing a computed jump, table jump or trapping
instruction. */
/* First ensure that the instructions match. There may be many outgoing
@@ -1245,9 +1287,9 @@ outgoing_edges_match (mode, bb1, bb2)
if (fallthru1)
{
basic_block d1 = (forwarder_block_p (fallthru1->dest)
- ? fallthru1->dest->succ->dest: fallthru1->dest);
+ ? fallthru1->dest->succ->dest: fallthru1->dest);
basic_block d2 = (forwarder_block_p (fallthru2->dest)
- ? fallthru2->dest->succ->dest: fallthru2->dest);
+ ? fallthru2->dest->succ->dest: fallthru2->dest);
if (d1 != d2)
return false;
@@ -1279,21 +1321,21 @@ try_crossjump_to_edge (mode, e1, e2)
{
int nmatch;
basic_block src1 = e1->src, src2 = e2->src;
- basic_block redirect_to;
+ basic_block redirect_to, redirect_from, to_remove;
rtx newpos1, newpos2;
edge s;
- rtx last;
- rtx label;
/* Search backward through forwarder blocks. We don't need to worry
about multiple entry or chained forwarders, as they will be optimized
away. We do this to look past the unconditional jump following a
conditional jump that is required due to the current CFG shape. */
if (src1->pred
+ && !src1->pred->pred_next
&& FORWARDER_BLOCK_P (src1))
e1 = src1->pred, src1 = e1->src;
if (src2->pred
+ && !src2->pred->pred_next
&& FORWARDER_BLOCK_P (src2))
e2 = src2->pred, src2 = e2->src;
@@ -1344,6 +1386,8 @@ try_crossjump_to_edge (mode, e1, e2)
redirect_to->count += src1->count;
redirect_to->frequency += src1->frequency;
+ /* We may have some registers visible trought the block. */
+ redirect_to->flags |= BB_DIRTY;
/* Recompute the frequencies and counts of outgoing edges. */
for (s = redirect_to->succ; s; s = s->succ_next)
@@ -1407,29 +1451,14 @@ try_crossjump_to_edge (mode, e1, e2)
if (GET_CODE (newpos1) == NOTE)
newpos1 = NEXT_INSN (newpos1);
- last = src1->end;
- /* Emit the jump insn. */
- label = block_label (redirect_to);
- emit_jump_insn_after (gen_jump (label), src1->end);
- JUMP_LABEL (src1->end) = label;
- LABEL_NUSES (label)++;
+ redirect_from = split_block (src1, PREV_INSN (newpos1))->src;
+ to_remove = redirect_from->succ->dest;
- /* Delete the now unreachable instructions. */
- delete_insn_chain (newpos1, last);
+ redirect_edge_and_branch_force (redirect_from->succ, redirect_to);
+ flow_delete_block (to_remove);
- /* Make sure there is a barrier after the new jump. */
- last = next_nonnote_insn (src1->end);
- if (!last || GET_CODE (last) != BARRIER)
- emit_barrier_after (src1->end);
-
- /* Update CFG. */
- while (src1->succ)
- remove_edge (src1->succ);
- make_single_succ_edge (src1, redirect_to, 0);
-
- BB_SET_FLAG (src1, BB_UPDATE_LIFE);
- update_forwarder_flag (src1);
+ update_forwarder_flag (redirect_from);
return true;
}
@@ -1445,6 +1474,7 @@ try_crossjump_bb (mode, bb)
{
edge e, e2, nexte2, nexte, fallthru;
bool changed;
+ int n = 0, max;
/* Nothing to do if there is not at least two incoming edges. */
if (!bb->pred || !bb->pred->pred_next)
@@ -1453,9 +1483,15 @@ try_crossjump_bb (mode, bb)
/* It is always cheapest to redirect a block that ends in a branch to
a block that falls through into BB, as that adds no branches to the
program. We'll try that combination first. */
- for (fallthru = bb->pred; fallthru; fallthru = fallthru->pred_next)
- if (fallthru->flags & EDGE_FALLTHRU)
- break;
+ fallthru = NULL;
+ max = PARAM_VALUE (PARAM_MAX_CROSSJUMP_EDGES);
+ for (e = bb->pred; e ; e = e->pred_next, n++)
+ {
+ if (e->flags & EDGE_FALLTHRU)
+ fallthru = e;
+ if (n > max)
+ return false;
+ }
changed = false;
for (e = bb->pred; e; e = nexte)
@@ -1530,17 +1566,19 @@ static bool
try_optimize_cfg (mode)
int mode;
{
- int i;
bool changed_overall = false;
bool changed;
int iterations = 0;
- sbitmap blocks;
+ basic_block bb, b;
if (mode & CLEANUP_CROSSJUMP)
add_noreturn_fake_exit_edges ();
- for (i = 0; i < n_basic_blocks; i++)
- update_forwarder_flag (BASIC_BLOCK (i));
+ FOR_EACH_BB (bb)
+ update_forwarder_flag (bb);
+
+ if (mode & CLEANUP_UPDATE_LIFE)
+ clear_bb_flags ();
if (! (* targetm.cannot_modify_jumps_p) ())
{
@@ -1557,16 +1595,16 @@ try_optimize_cfg (mode)
"\n\ntry_optimize_cfg iteration %i\n\n",
iterations);
- for (i = 0; i < n_basic_blocks;)
+ for (b = ENTRY_BLOCK_PTR->next_bb; b != EXIT_BLOCK_PTR;)
{
- basic_block c, b = BASIC_BLOCK (i);
+ basic_block c;
edge s;
bool changed_here = false;
/* Delete trivially dead basic blocks. */
while (b->pred == NULL)
{
- c = BASIC_BLOCK (b->index - 1);
+ c = b->prev_bb;
if (rtl_dump_file)
fprintf (rtl_dump_file, "Deleting block %i.\n",
b->index);
@@ -1620,7 +1658,7 @@ try_optimize_cfg (mode)
"Deleting fallthru block %i.\n",
b->index);
- c = BASIC_BLOCK (b->index ? b->index - 1 : 1);
+ c = b->prev_bb == ENTRY_BLOCK_PTR ? b->next_bb : b->prev_bb;
redirect_edge_succ_nodup (b->pred, b->succ->dest);
flow_delete_block (b);
changed = true;
@@ -1638,17 +1676,15 @@ try_optimize_cfg (mode)
/* If the jump insn has side effects,
we can't kill the edge. */
&& (GET_CODE (b->end) != JUMP_INSN
- || (onlyjump_p (b->end)
- && !tablejump_p (b->end)))
+ || (flow2_completed
+ ? simplejump_p (b->end)
+ : onlyjump_p (b->end)))
&& merge_blocks (s, b, c, mode))
changed_here = true;
/* Simplify branch over branch. */
if ((mode & CLEANUP_EXPENSIVE) && try_simplify_condjump (b))
- {
- BB_SET_FLAG (b, BB_UPDATE_LIFE);
- changed_here = true;
- }
+ changed_here = true;
/* If B has a single outgoing edge, but uses a
non-trivial jump instruction without side-effects, we
@@ -1661,7 +1697,6 @@ try_optimize_cfg (mode)
&& onlyjump_p (b->end)
&& redirect_edge_and_branch (b->succ, b->succ->dest))
{
- BB_SET_FLAG (b, BB_UPDATE_LIFE);
update_forwarder_flag (b);
changed_here = true;
}
@@ -1678,7 +1713,7 @@ try_optimize_cfg (mode)
/* Don't get confused by the index shift caused by
deleting blocks. */
if (!changed_here)
- i = b->index + 1;
+ b = b->next_bb;
else
changed = true;
}
@@ -1700,64 +1735,33 @@ try_optimize_cfg (mode)
if (mode & CLEANUP_CROSSJUMP)
remove_fake_edges ();
- if ((mode & CLEANUP_UPDATE_LIFE) && changed_overall)
- {
- bool found = 0;
-
- blocks = sbitmap_alloc (n_basic_blocks);
- sbitmap_zero (blocks);
- for (i = 0; i < n_basic_blocks; i++)
- if (BB_FLAGS (BASIC_BLOCK (i)) & BB_UPDATE_LIFE)
- {
- found = 1;
- SET_BIT (blocks, i);
- }
-
- if (found)
- update_life_info (blocks, UPDATE_LIFE_GLOBAL,
- PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
- | PROP_KILL_DEAD_CODE);
- sbitmap_free (blocks);
- }
-
- for (i = 0; i < n_basic_blocks; i++)
- BASIC_BLOCK (i)->aux = NULL;
+ clear_aux_for_blocks ();
return changed_overall;
}
/* Delete all unreachable basic blocks. */
-static bool
+bool
delete_unreachable_blocks ()
{
- int i, j;
bool changed = false;
+ basic_block b, next_bb;
find_unreachable_blocks ();
- /* Delete all unreachable basic blocks. Do compaction concurrently,
- as otherwise we can wind up with O(N^2) behaviour here when we
- have oodles of dead code. */
+ /* Delete all unreachable basic blocks. */
- for (i = j = 0; i < n_basic_blocks; ++i)
+ for (b = ENTRY_BLOCK_PTR->next_bb; b != EXIT_BLOCK_PTR; b = next_bb)
{
- basic_block b = BASIC_BLOCK (i);
+ next_bb = b->next_bb;
if (!(b->flags & BB_REACHABLE))
{
- flow_delete_block_noexpunge (b);
- expunge_block_nocompact (b);
+ flow_delete_block (b);
changed = true;
}
- else
- {
- BASIC_BLOCK (j) = b;
- b->index = j++;
- }
}
- n_basic_blocks = j;
- basic_block_info->num_elements = j;
if (changed)
tidy_fallthru_edges ();
@@ -1773,13 +1777,48 @@ cleanup_cfg (mode)
bool changed = false;
timevar_push (TV_CLEANUP_CFG);
- changed = delete_unreachable_blocks ();
- if (try_optimize_cfg (mode))
- delete_unreachable_blocks (), changed = true;
+ if (delete_unreachable_blocks ())
+ {
+ changed = true;
+ /* We've possibly created trivially dead code. Cleanup it right
+ now to introduce more oppurtunities for try_optimize_cfg. */
+ if (!(mode & (CLEANUP_NO_INSN_DEL
+ | CLEANUP_UPDATE_LIFE | CLEANUP_PRE_SIBCALL))
+ && !reload_completed)
+ delete_trivially_dead_insns (get_insns(), max_reg_num ());
+ }
+
+ compact_blocks ();
+
+ while (try_optimize_cfg (mode))
+ {
+ delete_unreachable_blocks (), changed = true;
+ if (mode & CLEANUP_UPDATE_LIFE)
+ {
+ /* Cleaning up CFG introduces more oppurtunities for dead code
+ removal that in turn may introduce more oppurtunities for
+ cleaning up the CFG. */
+ if (!update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
+ PROP_DEATH_NOTES
+ | PROP_SCAN_DEAD_CODE
+ | PROP_KILL_DEAD_CODE
+ | PROP_LOG_LINKS))
+ break;
+ }
+ else if (!(mode & (CLEANUP_NO_INSN_DEL | CLEANUP_PRE_SIBCALL))
+ && (mode & CLEANUP_EXPENSIVE)
+ && !reload_completed)
+ {
+ if (!delete_trivially_dead_insns (get_insns(), max_reg_num ()))
+ break;
+ }
+ else
+ break;
+ delete_dead_jumptables ();
+ }
/* Kill the data we won't maintain. */
free_EXPR_LIST_list (&label_value_list);
- free_EXPR_LIST_list (&tail_recursion_label_list);
timevar_pop (TV_CLEANUP_CFG);
return changed;
diff --git a/contrib/gcc/cfglayout.c b/contrib/gcc/cfglayout.c
index 329e9f8..ca5f475 100644
--- a/contrib/gcc/cfglayout.c
+++ b/contrib/gcc/cfglayout.c
@@ -35,7 +35,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
extern struct obstack flow_obstack;
/* Holds the interesting trailing notes for the function. */
-static rtx function_tail_eff_head;
+static rtx function_footer;
static rtx skip_insns_after_block PARAMS ((basic_block));
static void record_effective_endpoints PARAMS ((void));
@@ -46,10 +46,31 @@ static void set_block_levels PARAMS ((tree, int));
static void change_scope PARAMS ((rtx, tree, tree));
void verify_insn_chain PARAMS ((void));
+static void cleanup_unconditional_jumps PARAMS ((void));
static void fixup_fallthru_exit_predecessor PARAMS ((void));
-
-/* Map insn uid to lexical block. */
-static varray_type insn_scopes;
+static rtx unlink_insn_chain PARAMS ((rtx, rtx));
+static rtx duplicate_insn_chain PARAMS ((rtx, rtx));
+
+static rtx
+unlink_insn_chain (first, last)
+ rtx first;
+ rtx last;
+{
+ rtx prevfirst = PREV_INSN (first);
+ rtx nextlast = NEXT_INSN (last);
+
+ PREV_INSN (first) = NULL;
+ NEXT_INSN (last) = NULL;
+ if (prevfirst)
+ NEXT_INSN (prevfirst) = nextlast;
+ if (nextlast)
+ PREV_INSN (nextlast) = prevfirst;
+ else
+ set_last_insn (prevfirst);
+ if (!prevfirst)
+ set_first_insn (nextlast);
+ return first;
+}
/* Skip over inter-block insns occurring after BB which are typically
associated with BB (e.g., barriers). If there are any such insns,
@@ -62,8 +83,8 @@ skip_insns_after_block (bb)
rtx insn, last_insn, next_head, prev;
next_head = NULL_RTX;
- if (bb->index + 1 != n_basic_blocks)
- next_head = BASIC_BLOCK (bb->index + 1)->head;
+ if (bb->next_bb != EXIT_BLOCK_PTR)
+ next_head = bb->next_bb->head;
for (last_insn = insn = bb->end; (insn = NEXT_INSN (insn)) != 0; )
{
@@ -103,7 +124,7 @@ skip_insns_after_block (bb)
last_insn = insn;
continue;
}
- break;
+ break;
default:
break;
@@ -113,7 +134,7 @@ skip_insns_after_block (bb)
}
/* It is possible to hit contradictory sequence. For instance:
-
+
jump_insn
NOTE_INSN_LOOP_BEG
barrier
@@ -128,14 +149,14 @@ skip_insns_after_block (bb)
if (GET_CODE (insn) == NOTE)
switch (NOTE_LINE_NUMBER (insn))
{
- case NOTE_INSN_LOOP_END:
- case NOTE_INSN_BLOCK_END:
- case NOTE_INSN_DELETED:
- case NOTE_INSN_DELETED_LABEL:
+ case NOTE_INSN_LOOP_END:
+ case NOTE_INSN_BLOCK_END:
+ case NOTE_INSN_DELETED:
+ case NOTE_INSN_DELETED_LABEL:
continue;
- default:
+ default:
reorder_insns (insn, insn, last_insn);
- }
+ }
}
return last_insn;
@@ -155,8 +176,6 @@ label_for_bb (bb)
fprintf (rtl_dump_file, "Emitting label for block %d\n", bb->index);
label = block_label (bb);
- if (bb->head == PREV_INSN (RBI (bb)->eff_head))
- RBI (bb)->eff_head = label;
}
return label;
@@ -169,20 +188,24 @@ static void
record_effective_endpoints ()
{
rtx next_insn = get_insns ();
- int i;
-
- for (i = 0; i < n_basic_blocks; i++)
+ basic_block bb;
+
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
rtx end;
- RBI (bb)->eff_head = next_insn;
+ if (PREV_INSN (bb->head) && next_insn != bb->head)
+ RBI (bb)->header = unlink_insn_chain (next_insn,
+ PREV_INSN (bb->head));
end = skip_insns_after_block (bb);
- RBI (bb)->eff_end = end;
- next_insn = NEXT_INSN (end);
+ if (NEXT_INSN (bb->end) && bb->end != end)
+ RBI (bb)->footer = unlink_insn_chain (NEXT_INSN (bb->end), end);
+ next_insn = NEXT_INSN (bb->end);
}
- function_tail_eff_head = next_insn;
+ function_footer = next_insn;
+ if (function_footer)
+ function_footer = unlink_insn_chain (function_footer, get_last_insn ());
}
/* Build a varray mapping INSN_UID to lexical block. Return it. */
@@ -193,8 +216,6 @@ scope_to_insns_initialize ()
tree block = NULL;
rtx insn, next;
- VARRAY_TREE_INIT (insn_scopes, get_max_uid (), "insn scopes");
-
for (insn = get_insns (); insn; insn = next)
{
next = NEXT_INSN (insn);
@@ -202,7 +223,7 @@ scope_to_insns_initialize ()
if (active_insn_p (insn)
&& GET_CODE (PATTERN (insn)) != ADDR_VEC
&& GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
- VARRAY_TREE (insn_scopes, INSN_UID (insn)) = block;
+ INSN_SCOPE (insn) = block;
else if (GET_CODE (insn) == NOTE)
{
switch (NOTE_LINE_NUMBER (insn))
@@ -220,6 +241,10 @@ scope_to_insns_initialize ()
}
}
}
+
+ /* Tag the blocks with a depth number so that change_scope can find
+ the common parent easily. */
+ set_block_levels (DECL_INITIAL (cfun->decl), 0);
}
/* For each lexical block, set BLOCK_NUMBER to the depth at which it is
@@ -237,7 +262,21 @@ set_block_levels (block, level)
block = BLOCK_CHAIN (block);
}
}
-
+
+/* Return sope resulting from combination of S1 and S2. */
+tree
+choose_inner_scope (s1, s2)
+ tree s1, s2;
+{
+ if (!s1)
+ return s2;
+ if (!s2)
+ return s1;
+ if (BLOCK_NUMBER (s1) > BLOCK_NUMBER (s2))
+ return s1;
+ return s2;
+}
+
/* Emit lexical block notes needed to change scope from S1 to S2. */
static void
@@ -294,17 +333,26 @@ scope_to_insns_finalize ()
tree cur_block = DECL_INITIAL (cfun->decl);
rtx insn, note;
- /* Tag the blocks with a depth number so that change_scope can find
- the common parent easily. */
- set_block_levels (cur_block, 0);
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ insn = get_insns ();
+ if (!active_insn_p (insn))
+ insn = next_active_insn (insn);
+ for (; insn; insn = next_active_insn (insn))
{
tree this_block;
- if ((size_t) INSN_UID (insn) >= insn_scopes->num_elements)
- continue;
- this_block = VARRAY_TREE (insn_scopes, INSN_UID (insn));
+ this_block = INSN_SCOPE (insn);
+ /* For sequences compute scope resulting from merging all scopes
+ of instructions nested inside. */
+ if (GET_CODE (PATTERN (insn)) == SEQUENCE)
+ {
+ int i;
+ rtx body = PATTERN (insn);
+
+ this_block = NULL;
+ for (i = 0; i < XVECLEN (body, 0); i++)
+ this_block = choose_inner_scope (this_block,
+ INSN_SCOPE (XVECEXP (body, 0, i)));
+ }
if (! this_block)
continue;
@@ -315,8 +363,6 @@ scope_to_insns_finalize ()
}
}
- VARRAY_FREE (insn_scopes);
-
/* change_scope emits before the insn, not after. */
note = emit_note (NULL, NOTE_INSN_DELETED);
change_scope (note, cur_block, DECL_INITIAL (cfun->decl));
@@ -330,32 +376,49 @@ scope_to_insns_finalize ()
static void
fixup_reorder_chain ()
{
- basic_block bb, last_bb;
+ basic_block bb, prev_bb;
int index;
- rtx insn;
- int old_n_basic_blocks = n_basic_blocks;
+ rtx insn = NULL;
/* First do the bulk reordering -- rechain the blocks without regard to
the needed changes to jumps and labels. */
- for (last_bb = BASIC_BLOCK (0), bb = RBI (last_bb)->next, index = 1;
+ for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
bb != 0;
- last_bb = bb, bb = RBI (bb)->next, index++)
+ bb = RBI (bb)->next, index++)
{
- rtx last_e = RBI (last_bb)->eff_end;
- rtx curr_h = RBI (bb)->eff_head;
-
- NEXT_INSN (last_e) = curr_h;
- PREV_INSN (curr_h) = last_e;
+ if (RBI (bb)->header)
+ {
+ if (insn)
+ NEXT_INSN (insn) = RBI (bb)->header;
+ else
+ set_first_insn (RBI (bb)->header);
+ PREV_INSN (RBI (bb)->header) = insn;
+ insn = RBI (bb)->header;
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ }
+ if (insn)
+ NEXT_INSN (insn) = bb->head;
+ else
+ set_first_insn (bb->head);
+ PREV_INSN (bb->head) = insn;
+ insn = bb->end;
+ if (RBI (bb)->footer)
+ {
+ NEXT_INSN (insn) = RBI (bb)->footer;
+ PREV_INSN (RBI (bb)->footer) = insn;
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ }
}
if (index != n_basic_blocks)
abort ();
- insn = RBI (last_bb)->eff_end;
- NEXT_INSN (insn) = function_tail_eff_head;
- if (function_tail_eff_head)
- PREV_INSN (function_tail_eff_head) = insn;
+ NEXT_INSN (insn) = function_footer;
+ if (function_footer)
+ PREV_INSN (function_footer) = insn;
while (NEXT_INSN (insn))
insn = NEXT_INSN (insn);
@@ -368,7 +431,7 @@ fixup_reorder_chain ()
/* Now add jumps and labels as needed to match the blocks new
outgoing edges. */
- for (bb = BASIC_BLOCK (0); bb ; bb = RBI (bb)->next)
+ for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = RBI (bb)->next)
{
edge e_fall, e_taken, e;
rtx bb_end_insn;
@@ -397,11 +460,44 @@ fixup_reorder_chain ()
&& e_fall->dest == EXIT_BLOCK_PTR))
continue;
+ if (!e_taken)
+ e_taken = e_fall;
+
+ /* The degenerated case of conditional jump jumping to the next
+ instruction can happen on target having jumps with side
+ effects.
+
+ Create temporarily the duplicated edge representing branch.
+ It will get unidentified by force_nonfallthru_and_redirect
+ that would otherwise get confused by fallthru edge not pointing
+ to the next basic block. */
+ if (!e_taken)
+ {
+ rtx note;
+ edge e_fake;
+
+ e_fake = unchecked_make_edge (bb, e_fall->dest, 0);
+
+ note = find_reg_note (bb->end, REG_BR_PROB, NULL_RTX);
+ if (note)
+ {
+ int prob = INTVAL (XEXP (note, 0));
+
+ e_fake->probability = prob;
+ e_fake->count = e_fall->count * prob / REG_BR_PROB_BASE;
+ e_fall->probability -= e_fall->probability;
+ e_fall->count -= e_fake->count;
+ if (e_fall->probability < 0)
+ e_fall->probability = 0;
+ if (e_fall->count < 0)
+ e_fall->count = 0;
+ }
+ }
/* There is one special case: if *neither* block is next,
such as happens at the very end of a function, then we'll
need to add a new unconditional jump. Choose the taken
edge based on known or assumed probability. */
- if (RBI (bb)->next != e_taken->dest)
+ else if (RBI (bb)->next != e_taken->dest)
{
rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);
@@ -417,7 +513,7 @@ fixup_reorder_chain ()
}
}
- /* Otherwise we can try to invert the jump. This will
+ /* Otherwise we can try to invert the jump. This will
basically never fail, however, keep up the pretense. */
else if (invert_jump (bb_end_insn,
label_for_bb (e_fall->dest), 0))
@@ -470,8 +566,6 @@ fixup_reorder_chain ()
if (nb)
{
alloc_aux_for_block (nb, sizeof (struct reorder_block_def));
- RBI (nb)->eff_head = nb->head;
- RBI (nb)->eff_end = NEXT_INSN (nb->end);
RBI (nb)->visited = 1;
RBI (nb)->next = RBI (bb)->next;
RBI (bb)->next = nb;
@@ -481,23 +575,38 @@ fixup_reorder_chain ()
}
/* Put basic_block_info in the new order. */
- bb = BASIC_BLOCK (0);
- index = 0;
if (rtl_dump_file)
- fprintf (rtl_dump_file, "Reordered sequence:\n");
-
- for (; bb; bb = RBI (bb)->next, index++)
{
- if (rtl_dump_file)
- fprintf (rtl_dump_file, " %i %sbb %i freq %i\n", index,
- bb->index >= old_n_basic_blocks ? "compensation " : "",
- bb->index,
- bb->frequency);
+ fprintf (rtl_dump_file, "Reordered sequence:\n");
+ for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0; bb; bb = RBI (bb)->next, index ++)
+ {
+ fprintf (rtl_dump_file, " %i ", index);
+ if (RBI (bb)->original)
+ fprintf (rtl_dump_file, "duplicate of %i ",
+ RBI (bb)->original->index);
+ else if (forwarder_block_p (bb) && GET_CODE (bb->head) != CODE_LABEL)
+ fprintf (rtl_dump_file, "compensation ");
+ else
+ fprintf (rtl_dump_file, "bb %i ", bb->index);
+ fprintf (rtl_dump_file, " [%i]\n", bb->frequency);
+ }
+ }
+ prev_bb = ENTRY_BLOCK_PTR;
+ bb = ENTRY_BLOCK_PTR->next_bb;
+ index = 0;
+
+ for (; bb; prev_bb = bb, bb = RBI (bb)->next, index ++)
+ {
bb->index = index;
BASIC_BLOCK (index) = bb;
+
+ bb->prev_bb = prev_bb;
+ prev_bb->next_bb = bb;
}
+ prev_bb->next_bb = EXIT_BLOCK_PTR;
+ EXIT_BLOCK_PTR->prev_bb = prev_bb;
}
/* Perform sanity checks on the insn chain.
@@ -530,10 +639,70 @@ verify_insn_chain ()
if (insn_cnt1 != insn_cnt2)
abort ();
}
+
+/* Remove any unconditional jumps and forwarder block creating fallthru
+ edges instead. During BB reordering, fallthru edges are not required
+ to target next basic block in the linear CFG layout, so the unconditional
+ jumps are not needed. */
+
+static void
+cleanup_unconditional_jumps ()
+{
+ basic_block bb;
+
+ FOR_EACH_BB (bb)
+ {
+ if (!bb->succ)
+ continue;
+ if (bb->succ->flags & EDGE_FALLTHRU)
+ continue;
+ if (!bb->succ->succ_next)
+ {
+ rtx insn;
+ if (GET_CODE (bb->head) != CODE_LABEL && forwarder_block_p (bb)
+ && bb->prev_bb != ENTRY_BLOCK_PTR)
+ {
+ basic_block prev = bb->prev_bb;
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Removing forwarder BB %i\n",
+ bb->index);
-/* The block falling through to exit must be the last one in the reordered
- chain. Ensure it is. */
+ redirect_edge_succ_nodup (bb->pred, bb->succ->dest);
+ flow_delete_block (bb);
+ bb = prev;
+ }
+ else if (simplejump_p (bb->end))
+ {
+ rtx jump = bb->end;
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Removing jump %i in BB %i\n",
+ INSN_UID (jump), bb->index);
+ delete_insn (jump);
+ bb->succ->flags |= EDGE_FALLTHRU;
+ }
+ else
+ continue;
+ insn = NEXT_INSN (bb->end);
+ while (insn
+ && (GET_CODE (insn) != NOTE
+ || NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK))
+ {
+ rtx next = NEXT_INSN (insn);
+
+ if (GET_CODE (insn) == BARRIER)
+ delete_barrier (insn);
+
+ insn = next;
+ }
+ }
+ }
+}
+
+/* The block falling through to exit must be the last one in the
+ reordered chain. Ensure that this condition is met. */
static void
fixup_fallthru_exit_predecessor ()
{
@@ -546,7 +715,7 @@ fixup_fallthru_exit_predecessor ()
if (bb && RBI (bb)->next)
{
- basic_block c = BASIC_BLOCK (0);
+ basic_block c = ENTRY_BLOCK_PTR->next_bb;
while (RBI (c)->next != bb)
c = RBI (c)->next;
@@ -560,15 +729,279 @@ fixup_fallthru_exit_predecessor ()
}
}
-/* Main entry point to this module: initialize the datastructures for CFG
- layout changes. */
+/* Return true in case it is possible to duplicate the basic block BB. */
+
+bool
+cfg_layout_can_duplicate_bb_p (bb)
+ basic_block bb;
+{
+ rtx next;
+ edge s;
+
+ if (bb == EXIT_BLOCK_PTR || bb == ENTRY_BLOCK_PTR)
+ return false;
+
+ /* Duplicating fallthru block to exit would require adding a jump
+ and splitting the real last BB. */
+ for (s = bb->succ; s; s = s->succ_next)
+ if (s->dest == EXIT_BLOCK_PTR && s->flags & EDGE_FALLTHRU)
+ return false;
+
+ /* Do not attempt to duplicate tablejumps, as we need to unshare
+ the dispatch table. This is dificult to do, as the instructions
+ computing jump destination may be hoisted outside the basic block. */
+ if (GET_CODE (bb->end) == JUMP_INSN && JUMP_LABEL (bb->end)
+ && (next = next_nonnote_insn (JUMP_LABEL (bb->end)))
+ && GET_CODE (next) == JUMP_INSN
+ && (GET_CODE (PATTERN (next)) == ADDR_VEC
+ || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
+ return false;
+ return true;
+}
+
+static rtx
+duplicate_insn_chain (from, to)
+ rtx from, to;
+{
+ rtx insn, last;
+
+ /* Avoid updating of boundaries of previous basic block. The
+ note will get removed from insn stream in fixup. */
+ last = emit_note (NULL, NOTE_INSN_DELETED);
+
+ /* Create copy at the end of INSN chain. The chain will
+ be reordered later. */
+ for (insn = from; insn != NEXT_INSN (to); insn = NEXT_INSN (insn))
+ {
+ rtx new;
+ switch (GET_CODE (insn))
+ {
+ case INSN:
+ case CALL_INSN:
+ case JUMP_INSN:
+ /* Avoid copying of dispatch tables. We never duplicate
+ tablejumps, so this can hit only in case the table got
+ moved far from original jump. */
+ if (GET_CODE (PATTERN (insn)) == ADDR_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
+ break;
+ new = emit_copy_of_insn_after (insn, get_last_insn ());
+ break;
+
+ case CODE_LABEL:
+ break;
+
+ case BARRIER:
+ emit_barrier ();
+ break;
+
+ case NOTE:
+ switch (NOTE_LINE_NUMBER (insn))
+ {
+ /* In case prologue is empty and function contain label
+ in first BB, we may want to copy the block. */
+ case NOTE_INSN_PROLOGUE_END:
+
+ case NOTE_INSN_LOOP_VTOP:
+ case NOTE_INSN_LOOP_CONT:
+ case NOTE_INSN_LOOP_BEG:
+ case NOTE_INSN_LOOP_END:
+ /* Strip down the loop notes - we don't really want to keep
+ them consistent in loop copies. */
+ case NOTE_INSN_DELETED:
+ case NOTE_INSN_DELETED_LABEL:
+ /* No problem to strip these. */
+ case NOTE_INSN_EPILOGUE_BEG:
+ case NOTE_INSN_FUNCTION_END:
+ /* Debug code expect these notes to exist just once.
+ Keep them in the master copy.
+ ??? It probably makes more sense to duplicate them for each
+ epilogue copy. */
+ case NOTE_INSN_FUNCTION_BEG:
+ /* There is always just single entry to function. */
+ case NOTE_INSN_BASIC_BLOCK:
+ break;
+
+ /* There is no purpose to duplicate prologue. */
+ case NOTE_INSN_BLOCK_BEG:
+ case NOTE_INSN_BLOCK_END:
+ /* The BLOCK_BEG/BLOCK_END notes should be eliminated when BB
+ reordering is in the progress. */
+ case NOTE_INSN_EH_REGION_BEG:
+ case NOTE_INSN_EH_REGION_END:
+ /* Should never exist at BB duplication time. */
+ abort ();
+ break;
+ case NOTE_INSN_REPEATED_LINE_NUMBER:
+ emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
+ break;
+
+ default:
+ if (NOTE_LINE_NUMBER (insn) < 0)
+ abort ();
+ /* It is possible that no_line_number is set and the note
+ won't be emitted. */
+ emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
+ }
+ break;
+ default:
+ abort ();
+ }
+ }
+ insn = NEXT_INSN (last);
+ delete_insn (last);
+ return insn;
+}
+
+/* Redirect Edge to DEST. */
+void
+cfg_layout_redirect_edge (e, dest)
+ edge e;
+ basic_block dest;
+{
+ basic_block src = e->src;
+ basic_block old_next_bb = src->next_bb;
+
+ /* Redirect_edge_and_branch may decide to turn branch into fallthru edge
+ in the case the basic block appears to be in sequence. Avoid this
+ transformation. */
+
+ src->next_bb = NULL;
+ if (e->flags & EDGE_FALLTHRU)
+ {
+ /* Redirect any branch edges unified with the fallthru one. */
+ if (GET_CODE (src->end) == JUMP_INSN
+ && JUMP_LABEL (src->end) == e->dest->head)
+ {
+ if (!redirect_jump (src->end, block_label (dest), 0))
+ abort ();
+ }
+ /* In case we are redirecting fallthru edge to the branch edge
+ of conditional jump, remove it. */
+ if (src->succ->succ_next
+ && !src->succ->succ_next->succ_next)
+ {
+ edge s = e->succ_next ? e->succ_next : src->succ;
+ if (s->dest == dest
+ && any_condjump_p (src->end)
+ && onlyjump_p (src->end))
+ delete_insn (src->end);
+ }
+ redirect_edge_succ_nodup (e, dest);
+ }
+ else
+ redirect_edge_and_branch (e, dest);
+
+ /* We don't want simplejumps in the insn stream during cfglayout. */
+ if (simplejump_p (src->end))
+ {
+ delete_insn (src->end);
+ delete_barrier (NEXT_INSN (src->end));
+ src->succ->flags |= EDGE_FALLTHRU;
+ }
+ src->next_bb = old_next_bb;
+}
+
+/* Create a duplicate of the basic block BB and redirect edge E into it. */
+
+basic_block
+cfg_layout_duplicate_bb (bb, e)
+ basic_block bb;
+ edge e;
+{
+ rtx insn;
+ edge s, n;
+ basic_block new_bb;
+ gcov_type new_count = e ? e->count : 0;
+
+ if (bb->count < new_count)
+ new_count = bb->count;
+ if (!bb->pred)
+ abort ();
+#ifdef ENABLE_CHECKING
+ if (!cfg_layout_can_duplicate_bb_p (bb))
+ abort ();
+#endif
+
+ insn = duplicate_insn_chain (bb->head, bb->end);
+ new_bb = create_basic_block (insn,
+ insn ? get_last_insn () : NULL,
+ EXIT_BLOCK_PTR->prev_bb);
+ alloc_aux_for_block (new_bb, sizeof (struct reorder_block_def));
+
+ if (RBI (bb)->header)
+ {
+ insn = RBI (bb)->header;
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ insn = duplicate_insn_chain (RBI (bb)->header, insn);
+ if (insn)
+ RBI (new_bb)->header = unlink_insn_chain (insn, get_last_insn ());
+ }
+
+ if (RBI (bb)->footer)
+ {
+ insn = RBI (bb)->footer;
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ insn = duplicate_insn_chain (RBI (bb)->footer, insn);
+ if (insn)
+ RBI (new_bb)->footer = unlink_insn_chain (insn, get_last_insn ());
+ }
+
+ if (bb->global_live_at_start)
+ {
+ new_bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
+ new_bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
+ COPY_REG_SET (new_bb->global_live_at_start, bb->global_live_at_start);
+ COPY_REG_SET (new_bb->global_live_at_end, bb->global_live_at_end);
+ }
+
+ new_bb->loop_depth = bb->loop_depth;
+ new_bb->flags = bb->flags;
+ for (s = bb->succ; s; s = s->succ_next)
+ {
+ n = make_edge (new_bb, s->dest, s->flags);
+ n->probability = s->probability;
+ if (new_count)
+ /* Take care for overflows! */
+ n->count = s->count * (new_count * 10000 / bb->count) / 10000;
+ else
+ n->count = 0;
+ s->count -= n->count;
+ }
+
+ new_bb->count = new_count;
+ bb->count -= new_count;
+
+ if (e)
+ {
+ new_bb->frequency = EDGE_FREQUENCY (e);
+ bb->frequency -= EDGE_FREQUENCY (e);
+
+ cfg_layout_redirect_edge (e, new_bb);
+ }
+
+ if (bb->count < 0)
+ bb->count = 0;
+ if (bb->frequency < 0)
+ bb->frequency = 0;
+
+ RBI (new_bb)->original = bb;
+ return new_bb;
+}
+
+/* Main entry point to this module - initialize the datastructures for
+ CFG layout changes. It keeps LOOPS up-to-date if not null. */
void
cfg_layout_initialize ()
{
+ /* Our algorithm depends on fact that there are now dead jumptables
+ around the code. */
alloc_aux_for_blocks (sizeof (struct reorder_block_def));
- scope_to_insns_initialize ();
+ cleanup_unconditional_jumps ();
record_effective_endpoints ();
}
@@ -586,8 +1019,6 @@ cfg_layout_finalize ()
verify_insn_chain ();
#endif
- scope_to_insns_finalize ();
-
free_aux_for_blocks ();
#ifdef ENABLE_CHECKING
diff --git a/contrib/gcc/cfglayout.h b/contrib/gcc/cfglayout.h
index 3b12e50..e4e27d0 100644
--- a/contrib/gcc/cfglayout.h
+++ b/contrib/gcc/cfglayout.h
@@ -21,9 +21,12 @@
/* Structure to hold information about the blocks during reordering. */
typedef struct reorder_block_def
{
- rtx eff_head;
- rtx eff_end;
+ rtx header;
+ rtx footer;
basic_block next;
+ basic_block original;
+
+ /* These fields are used by bb-reorder pass. */
int visited;
} *reorder_block_def;
@@ -31,6 +34,8 @@ typedef struct reorder_block_def
extern void cfg_layout_initialize PARAMS ((void));
extern void cfg_layout_finalize PARAMS ((void));
-
+extern bool cfg_layout_can_duplicate_bb_p PARAMS ((basic_block));
+extern basic_block cfg_layout_duplicate_bb PARAMS ((basic_block, edge));
extern void scope_to_insns_initialize PARAMS ((void));
extern void scope_to_insns_finalize PARAMS ((void));
+extern void cfg_layout_redirect_edge PARAMS ((edge, basic_block));
diff --git a/contrib/gcc/cfgloop.c b/contrib/gcc/cfgloop.c
index 2bd0d4c..0a2829f 100644
--- a/contrib/gcc/cfgloop.c
+++ b/contrib/gcc/cfgloop.c
@@ -23,24 +23,28 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "rtl.h"
#include "hard-reg-set.h"
#include "basic-block.h"
+#include "toplev.h"
+
+/* Ratio of frequencies of edges so that one of more latch edges is
+ considered to belong to inner loop with same header. */
+#define HEAVY_EDGE_RATIO 8
static void flow_loops_cfg_dump PARAMS ((const struct loops *,
FILE *));
-static int flow_loop_nested_p PARAMS ((struct loop *,
- struct loop *));
-static int flow_loop_entry_edges_find PARAMS ((basic_block, const sbitmap,
- edge **));
-static int flow_loop_exit_edges_find PARAMS ((const sbitmap, edge **));
-static int flow_loop_nodes_find PARAMS ((basic_block, basic_block,
- sbitmap));
+static void flow_loop_entry_edges_find PARAMS ((struct loop *));
+static void flow_loop_exit_edges_find PARAMS ((struct loop *));
+static int flow_loop_nodes_find PARAMS ((basic_block, struct loop *));
static void flow_loop_pre_header_scan PARAMS ((struct loop *));
static basic_block flow_loop_pre_header_find PARAMS ((basic_block,
- const sbitmap *));
-static void flow_loop_tree_node_add PARAMS ((struct loop *,
- struct loop *));
-static void flow_loops_tree_build PARAMS ((struct loops *));
-static int flow_loop_level_compute PARAMS ((struct loop *, int));
+ dominance_info));
+static int flow_loop_level_compute PARAMS ((struct loop *));
static int flow_loops_level_compute PARAMS ((struct loops *));
+static basic_block make_forwarder_block PARAMS ((basic_block, int, int,
+ edge, int));
+static void canonicalize_loop_headers PARAMS ((void));
+static bool glb_enum_p PARAMS ((basic_block, void *));
+static void redirect_edge_with_latch_update PARAMS ((edge, basic_block));
+static void flow_loop_free PARAMS ((struct loop *));
/* Dump loop related CFG information. */
@@ -50,18 +54,19 @@ flow_loops_cfg_dump (loops, file)
FILE *file;
{
int i;
+ basic_block bb;
if (! loops->num || ! file || ! loops->cfg.dom)
return;
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
edge succ;
- fprintf (file, ";; %d succs { ", i);
- for (succ = BASIC_BLOCK (i)->succ; succ; succ = succ->succ_next)
+ fprintf (file, ";; %d succs { ", bb->index);
+ for (succ = bb->succ; succ; succ = succ->succ_next)
fprintf (file, "%d ", succ->dest->index);
- flow_nodes_print ("} dom", loops->cfg.dom[i], file);
+ fprintf (file, "}\n");
}
/* Dump the DFS node order. */
@@ -85,14 +90,15 @@ flow_loops_cfg_dump (loops, file)
}
}
-/* Return non-zero if the nodes of LOOP are a subset of OUTER. */
+/* Return nonzero if the nodes of LOOP are a subset of OUTER. */
-static int
+bool
flow_loop_nested_p (outer, loop)
- struct loop *outer;
- struct loop *loop;
+ const struct loop *outer;
+ const struct loop *loop;
{
- return sbitmap_a_subset_b_p (loop->nodes, outer->nodes);
+ return loop->depth > outer->depth
+ && loop->pred[outer->depth] == outer;
}
/* Dump the loop information specified by LOOP to the stream FILE
@@ -105,22 +111,18 @@ flow_loop_dump (loop, file, loop_dump_aux, verbose)
void (*loop_dump_aux) PARAMS((const struct loop *, FILE *, int));
int verbose;
{
+ basic_block *bbs;
+ int i;
+
if (! loop || ! loop->header)
return;
- if (loop->first->head && loop->last->end)
- fprintf (file, ";;\n;; Loop %d (%d to %d):%s%s\n",
- loop->num, INSN_UID (loop->first->head),
- INSN_UID (loop->last->end),
- loop->shared ? " shared" : "", loop->invalid ? " invalid" : "");
- else
- fprintf (file, ";;\n;; Loop %d:%s%s\n", loop->num,
- loop->shared ? " shared" : "", loop->invalid ? " invalid" : "");
+ fprintf (file, ";;\n;; Loop %d:%s\n", loop->num,
+ loop->invalid ? " invalid" : "");
- fprintf (file, ";; header %d, latch %d, pre-header %d, first %d, last %d\n",
+ fprintf (file, ";; header %d, latch %d, pre-header %d\n",
loop->header->index, loop->latch->index,
- loop->pre_header ? loop->pre_header->index : -1,
- loop->first->index, loop->last->index);
+ loop->pre_header ? loop->pre_header->index : -1);
fprintf (file, ";; depth %d, level %d, outer %ld\n",
loop->depth, loop->level,
(long) (loop->outer ? loop->outer->num : -1));
@@ -131,14 +133,15 @@ flow_loop_dump (loop, file, loop_dump_aux, verbose)
flow_edge_list_print (";; entry edges", loop->entry_edges,
loop->num_entries, file);
- fprintf (file, ";; %d", loop->num_nodes);
- flow_nodes_print (" nodes", loop->nodes, file);
+ fprintf (file, ";; nodes:");
+ bbs = get_loop_body (loop);
+ for (i = 0; i < loop->num_nodes; i++)
+ fprintf (file, " %d", bbs[i]->index);
+ free (bbs);
+ fprintf (file, "\n");
flow_edge_list_print (";; exit edges", loop->exit_edges,
loop->num_exits, file);
- if (loop->exits_doms)
- flow_nodes_print (";; exit doms", loop->exits_doms, file);
-
if (loop_dump_aux)
loop_dump_aux (loop, file, verbose);
}
@@ -153,55 +156,53 @@ flow_loops_dump (loops, file, loop_dump_aux, verbose)
void (*loop_dump_aux) PARAMS((const struct loop *, FILE *, int));
int verbose;
{
- int i, j;
+ int i;
int num_loops;
num_loops = loops->num;
if (! num_loops || ! file)
return;
- fprintf (file, ";; %d loops found, %d levels\n", num_loops, loops->levels);
+ fprintf (file, ";; %d loops found, %d levels\n",
+ num_loops, loops->levels);
+
for (i = 0; i < num_loops; i++)
{
- struct loop *loop = &loops->array[i];
+ struct loop *loop = loops->parray[i];
- flow_loop_dump (loop, file, loop_dump_aux, verbose);
- if (loop->shared)
- for (j = 0; j < i; j++)
- {
- struct loop *oloop = &loops->array[j];
+ if (!loop)
+ continue;
- if (loop->header == oloop->header)
- {
- int disjoint;
- int smaller;
-
- smaller = loop->num_nodes < oloop->num_nodes;
-
- /* If the union of LOOP and OLOOP is different than
- the larger of LOOP and OLOOP then LOOP and OLOOP
- must be disjoint. */
- disjoint = ! flow_loop_nested_p (smaller ? loop : oloop,
- smaller ? oloop : loop);
- fprintf (file,
- ";; loop header %d shared by loops %d, %d %s\n",
- loop->header->index, i, j,
- disjoint ? "disjoint" : "nested");
- }
- }
+ flow_loop_dump (loop, file, loop_dump_aux, verbose);
}
if (verbose)
flow_loops_cfg_dump (loops, file);
}
+/* Free data allocated for LOOP. */
+static void
+flow_loop_free (loop)
+ struct loop *loop;
+{
+ if (loop->pre_header_edges)
+ free (loop->pre_header_edges);
+ if (loop->entry_edges)
+ free (loop->entry_edges);
+ if (loop->exit_edges)
+ free (loop->exit_edges);
+ if (loop->pred)
+ free (loop->pred);
+ free (loop);
+}
+
/* Free all the memory allocated for LOOPS. */
void
flow_loops_free (loops)
struct loops *loops;
{
- if (loops->array)
+ if (loops->parray)
{
int i;
@@ -211,180 +212,163 @@ flow_loops_free (loops)
/* Free the loop descriptors. */
for (i = 0; i < loops->num; i++)
{
- struct loop *loop = &loops->array[i];
-
- if (loop->pre_header_edges)
- free (loop->pre_header_edges);
- if (loop->nodes)
- sbitmap_free (loop->nodes);
- if (loop->entry_edges)
- free (loop->entry_edges);
- if (loop->exit_edges)
- free (loop->exit_edges);
- if (loop->exits_doms)
- sbitmap_free (loop->exits_doms);
+ struct loop *loop = loops->parray[i];
+
+ if (!loop)
+ continue;
+
+ flow_loop_free (loop);
}
- free (loops->array);
- loops->array = NULL;
+ free (loops->parray);
+ loops->parray = NULL;
if (loops->cfg.dom)
- sbitmap_vector_free (loops->cfg.dom);
+ free_dominance_info (loops->cfg.dom);
if (loops->cfg.dfs_order)
free (loops->cfg.dfs_order);
+ if (loops->cfg.rc_order)
+ free (loops->cfg.rc_order);
- if (loops->shared_headers)
- sbitmap_free (loops->shared_headers);
}
}
-/* Find the entry edges into the loop with header HEADER and nodes
- NODES and store in ENTRY_EDGES array. Return the number of entry
- edges from the loop. */
+/* Find the entry edges into the LOOP. */
-static int
-flow_loop_entry_edges_find (header, nodes, entry_edges)
- basic_block header;
- const sbitmap nodes;
- edge **entry_edges;
+static void
+flow_loop_entry_edges_find (loop)
+ struct loop *loop;
{
edge e;
int num_entries;
- *entry_edges = NULL;
-
num_entries = 0;
- for (e = header->pred; e; e = e->pred_next)
+ for (e = loop->header->pred; e; e = e->pred_next)
{
- basic_block src = e->src;
-
- if (src == ENTRY_BLOCK_PTR || ! TEST_BIT (nodes, src->index))
+ if (flow_loop_outside_edge_p (loop, e))
num_entries++;
}
if (! num_entries)
abort ();
- *entry_edges = (edge *) xmalloc (num_entries * sizeof (edge));
+ loop->entry_edges = (edge *) xmalloc (num_entries * sizeof (edge *));
num_entries = 0;
- for (e = header->pred; e; e = e->pred_next)
+ for (e = loop->header->pred; e; e = e->pred_next)
{
- basic_block src = e->src;
-
- if (src == ENTRY_BLOCK_PTR || ! TEST_BIT (nodes, src->index))
- (*entry_edges)[num_entries++] = e;
+ if (flow_loop_outside_edge_p (loop, e))
+ loop->entry_edges[num_entries++] = e;
}
- return num_entries;
+ loop->num_entries = num_entries;
}
-/* Find the exit edges from the loop using the bitmap of loop nodes
- NODES and store in EXIT_EDGES array. Return the number of
- exit edges from the loop. */
+/* Find the exit edges from the LOOP. */
-static int
-flow_loop_exit_edges_find (nodes, exit_edges)
- const sbitmap nodes;
- edge **exit_edges;
+static void
+flow_loop_exit_edges_find (loop)
+ struct loop *loop;
{
edge e;
- int node;
- int num_exits;
+ basic_block node, *bbs;
+ int num_exits, i;
- *exit_edges = NULL;
+ loop->exit_edges = NULL;
+ loop->num_exits = 0;
/* Check all nodes within the loop to see if there are any
successors not in the loop. Note that a node may have multiple
- exiting edges ????? A node can have one jumping edge and one fallthru
- edge so only one of these can exit the loop. */
+ exiting edges. */
num_exits = 0;
- EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, node, {
- for (e = BASIC_BLOCK (node)->succ; e; e = e->succ_next)
- {
- basic_block dest = e->dest;
+ bbs = get_loop_body (loop);
+ for (i = 0; i < loop->num_nodes; i++)
+ {
+ node = bbs[i];
+ for (e = node->succ; e; e = e->succ_next)
+ {
+ basic_block dest = e->dest;
- if (dest == EXIT_BLOCK_PTR || ! TEST_BIT (nodes, dest->index))
+ if (!flow_bb_inside_loop_p (loop, dest))
num_exits++;
- }
- });
+ }
+ }
if (! num_exits)
- return 0;
+ {
+ free (bbs);
+ return;
+ }
- *exit_edges = (edge *) xmalloc (num_exits * sizeof (edge));
+ loop->exit_edges = (edge *) xmalloc (num_exits * sizeof (edge *));
/* Store all exiting edges into an array. */
num_exits = 0;
- EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, node, {
- for (e = BASIC_BLOCK (node)->succ; e; e = e->succ_next)
- {
- basic_block dest = e->dest;
+ for (i = 0; i < loop->num_nodes; i++)
+ {
+ node = bbs[i];
+ for (e = node->succ; e; e = e->succ_next)
+ {
+ basic_block dest = e->dest;
- if (dest == EXIT_BLOCK_PTR || ! TEST_BIT (nodes, dest->index))
- (*exit_edges)[num_exits++] = e;
+ if (!flow_bb_inside_loop_p (loop, dest))
+ loop->exit_edges[num_exits++] = e;
}
- });
-
- return num_exits;
+ }
+ free (bbs);
+ loop->num_exits = num_exits;
}
-/* Find the nodes contained within the loop with header HEADER and
- latch LATCH and store in NODES. Return the number of nodes within
- the loop. */
+/* Find the nodes contained within the LOOP with header HEADER.
+ Return the number of nodes within the loop. */
static int
-flow_loop_nodes_find (header, latch, nodes)
+flow_loop_nodes_find (header, loop)
basic_block header;
- basic_block latch;
- sbitmap nodes;
+ struct loop *loop;
{
basic_block *stack;
int sp;
- int num_nodes = 0;
+ int num_nodes = 1;
+ int findex, lindex;
- stack = (basic_block *) xmalloc (n_basic_blocks * sizeof (basic_block));
- sp = 0;
+ header->loop_father = loop;
+ header->loop_depth = loop->depth;
+ findex = lindex = header->index;
- /* Start with only the loop header in the set of loop nodes. */
- sbitmap_zero (nodes);
- SET_BIT (nodes, header->index);
- num_nodes++;
- header->loop_depth++;
-
- /* Push the loop latch on to the stack. */
- if (! TEST_BIT (nodes, latch->index))
+ if (loop->latch->loop_father != loop)
{
- SET_BIT (nodes, latch->index);
- latch->loop_depth++;
+ stack = (basic_block *) xmalloc (n_basic_blocks * sizeof (basic_block));
+ sp = 0;
num_nodes++;
- stack[sp++] = latch;
- }
-
- while (sp)
- {
- basic_block node;
- edge e;
-
- node = stack[--sp];
- for (e = node->pred; e; e = e->pred_next)
+ stack[sp++] = loop->latch;
+ loop->latch->loop_father = loop;
+ loop->latch->loop_depth = loop->depth;
+
+ while (sp)
{
- basic_block ancestor = e->src;
+ basic_block node;
+ edge e;
- /* If each ancestor not marked as part of loop, add to set of
- loop nodes and push on to stack. */
- if (ancestor != ENTRY_BLOCK_PTR
- && ! TEST_BIT (nodes, ancestor->index))
+ node = stack[--sp];
+
+ for (e = node->pred; e; e = e->pred_next)
{
- SET_BIT (nodes, ancestor->index);
- ancestor->loop_depth++;
- num_nodes++;
- stack[sp++] = ancestor;
+ basic_block ancestor = e->src;
+
+ if (ancestor != ENTRY_BLOCK_PTR
+ && ancestor->loop_father != loop)
+ {
+ ancestor->loop_father = loop;
+ ancestor->loop_depth = loop->depth;
+ num_nodes++;
+ stack[sp++] = ancestor;
+ }
}
}
+ free (stack);
}
- free (stack);
return num_nodes;
}
@@ -431,7 +415,7 @@ flow_loop_pre_header_scan (loop)
static basic_block
flow_loop_pre_header_find (header, dom)
basic_block header;
- const sbitmap *dom;
+ dominance_info dom;
{
basic_block pre_header;
edge e;
@@ -444,7 +428,7 @@ flow_loop_pre_header_find (header, dom)
basic_block node = e->src;
if (node != ENTRY_BLOCK_PTR
- && ! TEST_BIT (dom[node->index], header->index))
+ && ! dominated_by_p (dom, node, header))
{
if (pre_header == NULL)
pre_header = node;
@@ -461,68 +445,55 @@ flow_loop_pre_header_find (header, dom)
return pre_header;
}
-/* Add LOOP to the loop hierarchy tree where PREVLOOP was the loop
- previously added. The insertion algorithm assumes that the loops
- are added in the order found by a depth first search of the CFG. */
+/* Add LOOP to the loop hierarchy tree where FATHER is father of the
+ added loop. */
-static void
-flow_loop_tree_node_add (prevloop, loop)
- struct loop *prevloop;
+void
+flow_loop_tree_node_add (father, loop)
+ struct loop *father;
struct loop *loop;
{
-
- if (flow_loop_nested_p (prevloop, loop))
- {
- prevloop->inner = loop;
- loop->outer = prevloop;
- return;
- }
-
- for (; prevloop->outer; prevloop = prevloop->outer)
- if (flow_loop_nested_p (prevloop->outer, loop))
- {
- prevloop->next = loop;
- loop->outer = prevloop->outer;
- return;
- }
-
- prevloop->next = loop;
- loop->outer = NULL;
+ loop->next = father->inner;
+ father->inner = loop;
+ loop->outer = father;
+
+ loop->depth = father->depth + 1;
+ loop->pred = xmalloc (sizeof (struct loop *) * loop->depth);
+ memcpy (loop->pred, father->pred, sizeof (struct loop *) * father->depth);
+ loop->pred[father->depth] = father;
}
-/* Build the loop hierarchy tree for LOOPS. */
+/* Remove LOOP from the loop hierarchy tree. */
-static void
-flow_loops_tree_build (loops)
- struct loops *loops;
+void
+flow_loop_tree_node_remove (loop)
+ struct loop *loop;
{
- int i;
- int num_loops;
+ struct loop *prev, *father;
- num_loops = loops->num;
- if (! num_loops)
- return;
+ father = loop->outer;
+ loop->outer = NULL;
- /* Root the loop hierarchy tree with the first loop found.
- Since we used a depth first search this should be the
- outermost loop. */
- loops->tree_root = &loops->array[0];
- loops->tree_root->outer = loops->tree_root->inner
- = loops->tree_root->next = NULL;
+ /* Remove loop from the list of sons. */
+ if (father->inner == loop)
+ father->inner = loop->next;
+ else
+ {
+ for (prev = father->inner; prev->next != loop; prev = prev->next);
+ prev->next = loop->next;
+ }
- /* Add the remaining loops to the tree. */
- for (i = 1; i < num_loops; i++)
- flow_loop_tree_node_add (&loops->array[i - 1], &loops->array[i]);
+ loop->depth = -1;
+ free (loop->pred);
+ loop->pred = NULL;
}
/* Helper function to compute loop nesting depth and enclosed loop level
- for the natural loop specified by LOOP at the loop depth DEPTH.
- Returns the loop level. */
+ for the natural loop specified by LOOP. Returns the loop level. */
static int
-flow_loop_level_compute (loop, depth)
+flow_loop_level_compute (loop)
struct loop *loop;
- int depth;
{
struct loop *inner;
int level = 1;
@@ -537,13 +508,13 @@ flow_loop_level_compute (loop, depth)
itself). */
for (inner = loop->inner; inner; inner = inner->next)
{
- int ilevel = flow_loop_level_compute (inner, depth + 1) + 1;
+ int ilevel = flow_loop_level_compute (inner) + 1;
- level = MAX (ilevel, level);
+ if (ilevel > level)
+ level = ilevel;
}
loop->level = level;
- loop->depth = depth;
return level;
}
@@ -555,18 +526,7 @@ static int
flow_loops_level_compute (loops)
struct loops *loops;
{
- int levels = 0;
- struct loop *loop;
- int level;
-
- /* Traverse all the outer level loops. */
- for (loop = loops->tree_root; loop; loop = loop->next)
- {
- level = flow_loop_level_compute (loop, 1);
- levels = MAX (levels, level);
- }
-
- return levels;
+ return flow_loop_level_compute (loops->tree_root);
}
/* Scan a single natural loop specified by LOOP collecting information
@@ -578,37 +538,18 @@ flow_loop_scan (loops, loop, flags)
struct loop *loop;
int flags;
{
- /* Determine prerequisites. */
- if ((flags & LOOP_EXITS_DOMS) && ! loop->exit_edges)
- flags |= LOOP_EXIT_EDGES;
-
if (flags & LOOP_ENTRY_EDGES)
- /* Find edges which enter the loop header. Note that the entry edges
- should only enter the header of a natural loop. */
- loop->num_entries = flow_loop_entry_edges_find (loop->header, loop->nodes,
- &loop->entry_edges);
+ {
+ /* Find edges which enter the loop header.
+ Note that the entry edges should only
+ enter the header of a natural loop. */
+ flow_loop_entry_edges_find (loop);
+ }
if (flags & LOOP_EXIT_EDGES)
- /* Find edges which exit the loop. */
- loop->num_exits
- = flow_loop_exit_edges_find (loop->nodes, &loop->exit_edges);
-
- if (flags & LOOP_EXITS_DOMS)
{
- int j;
-
- /* Determine which loop nodes dominate all the exits
- of the loop. */
- loop->exits_doms = sbitmap_alloc (n_basic_blocks);
- sbitmap_copy (loop->exits_doms, loop->nodes);
- for (j = 0; j < loop->num_exits; j++)
- sbitmap_a_and_b (loop->exits_doms, loop->exits_doms,
- loops->cfg.dom[loop->exit_edges[j]->src->index]);
-
- /* The header of a natural loop must dominate
- all exits. */
- if (! TEST_BIT (loop->exits_doms, loop->header->index))
- abort ();
+ /* Find edges which exit the loop. */
+ flow_loop_exit_edges_find (loop);
}
if (flags & LOOP_PRE_HEADER)
@@ -625,6 +566,189 @@ flow_loop_scan (loops, loop, flags)
return 1;
}
+#define HEADER_BLOCK(B) (* (int *) (B)->aux)
+#define LATCH_EDGE(E) (*(int *) (E)->aux)
+
+/* Redirect edge and update latch and header info. */
+static void
+redirect_edge_with_latch_update (e, to)
+ edge e;
+ basic_block to;
+{
+ basic_block jump;
+
+ jump = redirect_edge_and_branch_force (e, to);
+ if (jump)
+ {
+ alloc_aux_for_block (jump, sizeof (int));
+ HEADER_BLOCK (jump) = 0;
+ alloc_aux_for_edge (jump->pred, sizeof (int));
+ LATCH_EDGE (jump->succ) = LATCH_EDGE (e);
+ LATCH_EDGE (jump->pred) = 0;
+ }
+}
+
+/* Split BB into entry part and rest; if REDIRECT_LATCH, redirect edges
+ marked as latch into entry part, analogically for REDIRECT_NONLATCH.
+ In both of these cases, ignore edge EXCEPT. If CONN_LATCH, set edge
+ between created entry part and BB as latch one. Return created entry
+ part. */
+
+static basic_block
+make_forwarder_block (bb, redirect_latch, redirect_nonlatch, except,
+ conn_latch)
+ basic_block bb;
+ int redirect_latch;
+ int redirect_nonlatch;
+ edge except;
+ int conn_latch;
+{
+ edge e, next_e, fallthru;
+ basic_block dummy;
+ rtx insn;
+
+ insn = PREV_INSN (first_insn_after_basic_block_note (bb));
+
+ fallthru = split_block (bb, insn);
+ dummy = fallthru->src;
+ bb = fallthru->dest;
+
+ bb->aux = xmalloc (sizeof (int));
+ HEADER_BLOCK (dummy) = 0;
+ HEADER_BLOCK (bb) = 1;
+
+ /* Redirect back edges we want to keep. */
+ for (e = dummy->pred; e; e = next_e)
+ {
+ next_e = e->pred_next;
+ if (e == except
+ || !((redirect_latch && LATCH_EDGE (e))
+ || (redirect_nonlatch && !LATCH_EDGE (e))))
+ {
+ dummy->frequency -= EDGE_FREQUENCY (e);
+ dummy->count -= e->count;
+ if (dummy->frequency < 0)
+ dummy->frequency = 0;
+ if (dummy->count < 0)
+ dummy->count = 0;
+ redirect_edge_with_latch_update (e, bb);
+ }
+ }
+
+ alloc_aux_for_edge (fallthru, sizeof (int));
+ LATCH_EDGE (fallthru) = conn_latch;
+
+ return dummy;
+}
+
+/* Takes care of merging natural loops with shared headers. */
+static void
+canonicalize_loop_headers ()
+{
+ dominance_info dom;
+ basic_block header;
+ edge e;
+
+ /* Compute the dominators. */
+ dom = calculate_dominance_info (CDI_DOMINATORS);
+
+ alloc_aux_for_blocks (sizeof (int));
+ alloc_aux_for_edges (sizeof (int));
+
+ /* Split blocks so that each loop has only single latch. */
+ FOR_EACH_BB (header)
+ {
+ int num_latches = 0;
+ int have_abnormal_edge = 0;
+
+ for (e = header->pred; e; e = e->pred_next)
+ {
+ basic_block latch = e->src;
+
+ if (e->flags & EDGE_ABNORMAL)
+ have_abnormal_edge = 1;
+
+ if (latch != ENTRY_BLOCK_PTR
+ && dominated_by_p (dom, latch, header))
+ {
+ num_latches++;
+ LATCH_EDGE (e) = 1;
+ }
+ }
+ if (have_abnormal_edge)
+ HEADER_BLOCK (header) = 0;
+ else
+ HEADER_BLOCK (header) = num_latches;
+ }
+
+ if (HEADER_BLOCK (ENTRY_BLOCK_PTR->succ->dest))
+ {
+ basic_block bb;
+
+ /* We could not redirect edges freely here. On the other hand,
+ we can simply split the edge from entry block. */
+ bb = split_edge (ENTRY_BLOCK_PTR->succ);
+
+ alloc_aux_for_edge (bb->succ, sizeof (int));
+ LATCH_EDGE (bb->succ) = 0;
+ alloc_aux_for_block (bb, sizeof (int));
+ HEADER_BLOCK (bb) = 0;
+ }
+
+ FOR_EACH_BB (header)
+ {
+ int num_latch;
+ int want_join_latch;
+ int max_freq, is_heavy;
+ edge heavy;
+
+ if (!HEADER_BLOCK (header))
+ continue;
+
+ num_latch = HEADER_BLOCK (header);
+
+ want_join_latch = (num_latch > 1);
+
+ if (!want_join_latch)
+ continue;
+
+ /* Find a heavy edge. */
+ is_heavy = 1;
+ heavy = NULL;
+ max_freq = 0;
+ for (e = header->pred; e; e = e->pred_next)
+ if (LATCH_EDGE (e) &&
+ EDGE_FREQUENCY (e) > max_freq)
+ max_freq = EDGE_FREQUENCY (e);
+ for (e = header->pred; e; e = e->pred_next)
+ if (LATCH_EDGE (e) &&
+ EDGE_FREQUENCY (e) >= max_freq / HEAVY_EDGE_RATIO)
+ {
+ if (heavy)
+ {
+ is_heavy = 0;
+ break;
+ }
+ else
+ heavy = e;
+ }
+
+ if (is_heavy)
+ {
+ basic_block new_header =
+ make_forwarder_block (header, true, true, heavy, 0);
+ if (num_latch > 2)
+ make_forwarder_block (new_header, true, false, NULL, 1);
+ }
+ else
+ make_forwarder_block (header, true, false, NULL, 1);
+ }
+
+ free_aux_for_blocks ();
+ free_aux_for_edges ();
+ free_dominance_info (dom);
+}
+
/* Find all the natural loops in the function and save in LOOPS structure and
recalculate loop_depth information in basic block structures. FLAGS
controls which loop information is collected. Return the number of natural
@@ -640,9 +764,11 @@ flow_loops_find (loops, flags)
int num_loops;
edge e;
sbitmap headers;
- sbitmap *dom;
+ dominance_info dom;
int *dfs_order;
int *rc_order;
+ basic_block header;
+ basic_block bb;
/* This function cannot be repeatedly called with different
flags to build up the loop information. The loop tree
@@ -660,38 +786,79 @@ flow_loops_find (loops, flags)
dfs_order = NULL;
rc_order = NULL;
+ /* Join loops with shared headers. */
+ canonicalize_loop_headers ();
+
/* Compute the dominators. */
- dom = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
- calculate_dominance_info (NULL, dom, CDI_DOMINATORS);
+ dom = loops->cfg.dom = calculate_dominance_info (CDI_DOMINATORS);
- /* Count the number of loop edges (back edges). This should be the
+ /* Count the number of loop headers. This should be the
same as the number of natural loops. */
+ headers = sbitmap_alloc (last_basic_block);
+ sbitmap_zero (headers);
+
num_loops = 0;
- for (b = 0; b < n_basic_blocks; b++)
+ FOR_EACH_BB (header)
{
- basic_block header;
-
- header = BASIC_BLOCK (b);
+ int more_latches = 0;
+
header->loop_depth = 0;
for (e = header->pred; e; e = e->pred_next)
{
basic_block latch = e->src;
+ if (e->flags & EDGE_ABNORMAL)
+ {
+ if (more_latches)
+ {
+ RESET_BIT (headers, header->index);
+ num_loops--;
+ }
+ break;
+ }
+
/* Look for back edges where a predecessor is dominated
by this block. A natural loop has a single entry
node (header) that dominates all the nodes in the
loop. It also has single back edge to the header
- from a latch node. Note that multiple natural loops
- may share the same header. */
- if (b != header->index)
- abort ();
-
- if (latch != ENTRY_BLOCK_PTR && TEST_BIT (dom[latch->index], b))
- num_loops++;
+ from a latch node. */
+ if (latch != ENTRY_BLOCK_PTR && dominated_by_p (dom, latch, header))
+ {
+ /* Shared headers should be eliminated by now. */
+ if (more_latches)
+ abort ();
+ more_latches = 1;
+ SET_BIT (headers, header->index);
+ num_loops++;
+ }
}
}
+ /* Allocate loop structures. */
+ loops->parray = (struct loop **) xcalloc (num_loops + 1, sizeof (struct loop *));
+
+ /* Dummy loop containing whole function. */
+ loops->parray[0] = xcalloc (1, sizeof (struct loop));
+ loops->parray[0]->next = NULL;
+ loops->parray[0]->inner = NULL;
+ loops->parray[0]->outer = NULL;
+ loops->parray[0]->depth = 0;
+ loops->parray[0]->pred = NULL;
+ loops->parray[0]->num_nodes = n_basic_blocks + 2;
+ loops->parray[0]->latch = EXIT_BLOCK_PTR;
+ loops->parray[0]->header = ENTRY_BLOCK_PTR;
+ ENTRY_BLOCK_PTR->loop_father = loops->parray[0];
+ EXIT_BLOCK_PTR->loop_father = loops->parray[0];
+
+ loops->tree_root = loops->parray[0];
+
+ /* Find and record information about all the natural loops
+ in the CFG. */
+ loops->num = 1;
+ FOR_EACH_BB (bb)
+ bb->loop_father = loops->tree_root;
+
if (num_loops)
{
/* Compute depth first search order of the CFG so that outer
@@ -705,104 +872,65 @@ flow_loops_find (loops, flags)
loops->cfg.dfs_order = dfs_order;
loops->cfg.rc_order = rc_order;
- /* Allocate loop structures. */
- loops->array
- = (struct loop *) xcalloc (num_loops, sizeof (struct loop));
+ num_loops = 1;
- headers = sbitmap_alloc (n_basic_blocks);
- sbitmap_zero (headers);
-
- loops->shared_headers = sbitmap_alloc (n_basic_blocks);
- sbitmap_zero (loops->shared_headers);
-
- /* Find and record information about all the natural loops
- in the CFG. */
- num_loops = 0;
- for (b = n_basic_blocks - 1; b >= 0; b--)
+ for (b = 0; b < n_basic_blocks; b++)
{
- basic_block latch;
+ struct loop *loop;
/* Search the nodes of the CFG in reverse completion order
so that we can find outer loops first. */
- latch = BASIC_BLOCK (rc_order[b]);
+ if (!TEST_BIT (headers, rc_order[b]))
+ continue;
- /* Look for all the possible headers for this latch block. */
- for (e = latch->succ; e; e = e->succ_next)
- {
- basic_block header = e->dest;
-
- /* Look for forward edges where this block is dominated by
- a successor of this block. A natural loop has a single
- entry node (header) that dominates all the nodes in the
- loop. It also has single back edge to the header from a
- latch node. Note that multiple natural loops may share
- the same header. */
- if (header != EXIT_BLOCK_PTR
- && TEST_BIT (dom[latch->index], header->index))
- {
- struct loop *loop;
+ header = BASIC_BLOCK (rc_order[b]);
+
+ loop = loops->parray[num_loops] = xcalloc (1, sizeof (struct loop));
- loop = loops->array + num_loops;
+ loop->header = header;
+ loop->num = num_loops;
+ num_loops++;
- loop->header = header;
- loop->latch = latch;
- loop->num = num_loops;
+ /* Look for the latch for this header block. */
+ for (e = header->pred; e; e = e->pred_next)
+ {
+ basic_block latch = e->src;
- num_loops++;
+ if (latch != ENTRY_BLOCK_PTR
+ && dominated_by_p (dom, latch, header))
+ {
+ loop->latch = latch;
+ break;
}
}
- }
- for (i = 0; i < num_loops; i++)
- {
- struct loop *loop = &loops->array[i];
-
- /* Keep track of blocks that are loop headers so
- that we can tell which loops should be merged. */
- if (TEST_BIT (headers, loop->header->index))
- SET_BIT (loops->shared_headers, loop->header->index);
- SET_BIT (headers, loop->header->index);
-
- /* Find nodes contained within the loop. */
- loop->nodes = sbitmap_alloc (n_basic_blocks);
- loop->num_nodes
- = flow_loop_nodes_find (loop->header, loop->latch, loop->nodes);
-
- /* Compute first and last blocks within the loop.
- These are often the same as the loop header and
- loop latch respectively, but this is not always
- the case. */
- loop->first
- = BASIC_BLOCK (sbitmap_first_set_bit (loop->nodes));
- loop->last
- = BASIC_BLOCK (sbitmap_last_set_bit (loop->nodes));
-
- flow_loop_scan (loops, loop, flags);
+ flow_loop_tree_node_add (header->loop_father, loop);
+ loop->num_nodes = flow_loop_nodes_find (loop->header, loop);
}
- /* Natural loops with shared headers may either be disjoint or
- nested. Disjoint loops with shared headers cannot be inner
- loops and should be merged. For now just mark loops that share
- headers. */
- for (i = 0; i < num_loops; i++)
- if (TEST_BIT (loops->shared_headers, loops->array[i].header->index))
- loops->array[i].shared = 1;
-
sbitmap_free (headers);
- }
- else
- sbitmap_vector_free (dom);
- loops->num = num_loops;
+ /* Assign the loop nesting depth and enclosed loop level for each
+ loop. */
+ loops->levels = flow_loops_level_compute (loops);
- /* Build the loop hierarchy tree. */
- flow_loops_tree_build (loops);
+ /* Scan the loops. */
+ for (i = 1; i < num_loops; i++)
+ flow_loop_scan (loops, loops->parray[i], flags);
- /* Assign the loop nesting depth and enclosed loop level for each
- loop. */
- loops->levels = flow_loops_level_compute (loops);
+ loops->num = num_loops;
+ }
+ else
+ {
+ loops->cfg.dom = NULL;
+ free_dominance_info (dom);
+ }
+#ifdef ENABLE_CHECKING
+ verify_flow_info ();
+ verify_loop_structure (loops, 0);
+#endif
- return num_loops;
+ return loops->num;
}
/* Update the information regarding the loops in the CFG
@@ -815,22 +943,259 @@ flow_loops_update (loops, flags)
{
/* One day we may want to update the current loop data. For now
throw away the old stuff and rebuild what we need. */
- if (loops->array)
+ if (loops->parray)
flow_loops_free (loops);
return flow_loops_find (loops, flags);
}
-/* Return non-zero if edge E enters header of LOOP from outside of LOOP. */
+/* Return nonzero if basic block BB belongs to LOOP. */
+bool
+flow_bb_inside_loop_p (loop, bb)
+ const struct loop *loop;
+ const basic_block bb;
+{
+ struct loop *source_loop;
-int
+ if (bb == ENTRY_BLOCK_PTR || bb == EXIT_BLOCK_PTR)
+ return 0;
+
+ source_loop = bb->loop_father;
+ return loop == source_loop || flow_loop_nested_p (loop, source_loop);
+}
+
+/* Return nonzero if edge E enters header of LOOP from outside of LOOP. */
+
+bool
flow_loop_outside_edge_p (loop, e)
const struct loop *loop;
edge e;
{
if (e->dest != loop->header)
abort ();
+ return !flow_bb_inside_loop_p (loop, e->src);
+}
- return (e->src == ENTRY_BLOCK_PTR)
- || ! TEST_BIT (loop->nodes, e->src->index);
+/* Enumeration predicate for get_loop_body. */
+static bool
+glb_enum_p (bb, glb_header)
+ basic_block bb;
+ void *glb_header;
+{
+ return bb != (basic_block) glb_header;
}
+
+/* Gets basic blocks of a loop. */
+basic_block *
+get_loop_body (loop)
+ const struct loop *loop;
+{
+ basic_block *tovisit, bb;
+ int tv = 0;
+
+ if (!loop->num_nodes)
+ abort ();
+
+ tovisit = xcalloc (loop->num_nodes, sizeof (basic_block));
+ tovisit[tv++] = loop->header;
+
+ if (loop->latch == EXIT_BLOCK_PTR)
+ {
+ /* There may be blocks unreachable from EXIT_BLOCK. */
+ if (loop->num_nodes != n_basic_blocks + 2)
+ abort ();
+ FOR_EACH_BB (bb)
+ tovisit[tv++] = bb;
+ tovisit[tv++] = EXIT_BLOCK_PTR;
+ }
+ else if (loop->latch != loop->header)
+ {
+ tv = dfs_enumerate_from (loop->latch, 1, glb_enum_p,
+ tovisit + 1, loop->num_nodes - 1,
+ loop->header) + 1;
+ }
+
+ if (tv != loop->num_nodes)
+ abort ();
+ return tovisit;
+}
+
+/* Adds basic block BB to LOOP. */
+void
+add_bb_to_loop (bb, loop)
+ basic_block bb;
+ struct loop *loop;
+ {
+ int i;
+
+ bb->loop_father = loop;
+ bb->loop_depth = loop->depth;
+ loop->num_nodes++;
+ for (i = 0; i < loop->depth; i++)
+ loop->pred[i]->num_nodes++;
+ }
+
+/* Remove basic block BB from loops. */
+void
+remove_bb_from_loops (bb)
+ basic_block bb;
+ {
+ int i;
+ struct loop *loop = bb->loop_father;
+
+ loop->num_nodes--;
+ for (i = 0; i < loop->depth; i++)
+ loop->pred[i]->num_nodes--;
+ bb->loop_father = NULL;
+ bb->loop_depth = 0;
+ }
+
+/* Finds nearest common ancestor in loop tree for given loops. */
+struct loop *
+find_common_loop (loop_s, loop_d)
+ struct loop *loop_s;
+ struct loop *loop_d;
+{
+ if (!loop_s) return loop_d;
+ if (!loop_d) return loop_s;
+
+ if (loop_s->depth < loop_d->depth)
+ loop_d = loop_d->pred[loop_s->depth];
+ else if (loop_s->depth > loop_d->depth)
+ loop_s = loop_s->pred[loop_d->depth];
+
+ while (loop_s != loop_d)
+ {
+ loop_s = loop_s->outer;
+ loop_d = loop_d->outer;
+ }
+ return loop_s;
+}
+
+/* Checks that LOOPS are allright:
+ -- sizes of loops are allright
+ -- results of get_loop_body really belong to the loop
+ -- loop header have just single entry edge and single latch edge
+ -- loop latches have only single successor that is header of their loop
+ */
+void
+verify_loop_structure (loops, flags)
+ struct loops *loops;
+ int flags;
+{
+ int *sizes, i, j;
+ basic_block *bbs, bb;
+ struct loop *loop;
+ int err = 0;
+
+ /* Check sizes. */
+ sizes = xcalloc (loops->num, sizeof (int));
+ sizes[0] = 2;
+
+ FOR_EACH_BB (bb)
+ for (loop = bb->loop_father; loop; loop = loop->outer)
+ sizes[loop->num]++;
+
+ for (i = 0; i < loops->num; i++)
+ {
+ if (!loops->parray[i])
+ continue;
+
+ if (loops->parray[i]->num_nodes != sizes[i])
+ {
+ error ("Size of loop %d should be %d, not %d.",
+ i, sizes[i], loops->parray[i]->num_nodes);
+ err = 1;
+ }
+ }
+
+ free (sizes);
+
+ /* Check get_loop_body. */
+ for (i = 1; i < loops->num; i++)
+ {
+ loop = loops->parray[i];
+ if (!loop)
+ continue;
+ bbs = get_loop_body (loop);
+
+ for (j = 0; j < loop->num_nodes; j++)
+ if (!flow_bb_inside_loop_p (loop, bbs[j]))
+ {
+ error ("Bb %d do not belong to loop %d.",
+ bbs[j]->index, i);
+ err = 1;
+ }
+ free (bbs);
+ }
+
+ /* Check headers and latches. */
+ for (i = 1; i < loops->num; i++)
+ {
+ loop = loops->parray[i];
+ if (!loop)
+ continue;
+
+ if ((flags & VLS_EXPECT_PREHEADERS)
+ && (!loop->header->pred->pred_next
+ || loop->header->pred->pred_next->pred_next))
+ {
+ error ("Loop %d's header does not have exactly 2 entries.", i);
+ err = 1;
+ }
+ if (flags & VLS_EXPECT_SIMPLE_LATCHES)
+ {
+ if (!loop->latch->succ
+ || loop->latch->succ->succ_next)
+ {
+ error ("Loop %d's latch does not have exactly 1 successor.", i);
+ err = 1;
+ }
+ if (loop->latch->succ->dest != loop->header)
+ {
+ error ("Loop %d's latch does not have header as successor.", i);
+ err = 1;
+ }
+ if (loop->latch->loop_father != loop)
+ {
+ error ("Loop %d's latch does not belong directly to it.", i);
+ err = 1;
+ }
+ }
+ if (loop->header->loop_father != loop)
+ {
+ error ("Loop %d's header does not belong directly to it.", i);
+ err = 1;
+ }
+ }
+
+ if (err)
+ abort ();
+}
+
+/* Returns latch edge of LOOP. */
+edge
+loop_latch_edge (loop)
+ struct loop *loop;
+{
+ edge e;
+
+ for (e = loop->header->pred; e->src != loop->latch; e = e->pred_next)
+ continue;
+
+ return e;
+}
+
+/* Returns preheader edge of LOOP. */
+edge
+loop_preheader_edge (loop)
+ struct loop *loop;
+{
+ edge e;
+
+ for (e = loop->header->pred; e->src == loop->latch; e = e->pred_next)
+ continue;
+
+ return e;
+}
+
diff --git a/contrib/gcc/cfgrtl.c b/contrib/gcc/cfgrtl.c
index e2cb773..7780ca5 100644
--- a/contrib/gcc/cfgrtl.c
+++ b/contrib/gcc/cfgrtl.c
@@ -56,6 +56,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "toplev.h"
#include "tm_p.h"
#include "obstack.h"
+#include "insn-config.h"
/* Stubs in case we don't have a return insn. */
#ifndef HAVE_return
@@ -63,9 +64,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define gen_return() NULL_RTX
#endif
-/* The basic block structure for every insn, indexed by uid. */
-varray_type basic_block_for_insn;
-
/* The labels mentioned in non-jump rtl. Valid during find_basic_blocks. */
/* ??? Should probably be using LABEL_NUSES instead. It would take a
bit of surgery to be able to use or co-opt the routines in jump. */
@@ -74,7 +72,7 @@ rtx tail_recursion_label_list;
static int can_delete_note_p PARAMS ((rtx));
static int can_delete_label_p PARAMS ((rtx));
-static void commit_one_edge_insertion PARAMS ((edge));
+static void commit_one_edge_insertion PARAMS ((edge, int));
static bool try_redirect_by_replacing_jump PARAMS ((edge, basic_block));
static rtx last_loop_beg_note PARAMS ((rtx));
static bool back_edge_of_syntactic_loop_p PARAMS ((basic_block, basic_block));
@@ -88,7 +86,8 @@ can_delete_note_p (note)
rtx note;
{
return (NOTE_LINE_NUMBER (note) == NOTE_INSN_DELETED
- || NOTE_LINE_NUMBER (note) == NOTE_INSN_BASIC_BLOCK);
+ || NOTE_LINE_NUMBER (note) == NOTE_INSN_BASIC_BLOCK
+ || NOTE_LINE_NUMBER (note) == NOTE_INSN_PREDICTION);
}
/* True if a given label can be deleted. */
@@ -117,7 +116,7 @@ delete_insn (insn)
if (GET_CODE (insn) == CODE_LABEL)
{
/* Some labels can't be directly removed from the INSN chain, as they
- might be references via variables, constant pool etc.
+ might be references via variables, constant pool etc.
Convert them to the special NOTE_INSN_DELETED_LABEL note. */
if (! can_delete_label_p (insn))
{
@@ -177,6 +176,24 @@ delete_insn (insn)
return next;
}
+/* Like delete_insn but also purge dead edges from BB. */
+rtx
+delete_insn_and_edges (insn)
+ rtx insn;
+{
+ rtx x;
+ bool purge = false;
+
+ if (INSN_P (insn)
+ && BLOCK_FOR_INSN (insn)
+ && BLOCK_FOR_INSN (insn)->end == insn)
+ purge = true;
+ x = delete_insn (insn);
+ if (purge)
+ purge_dead_edges (BLOCK_FOR_INSN (insn));
+ return x;
+}
+
/* Unlink a chain of insns between START and FINISH, leaving notes
that must be paired. */
@@ -202,18 +219,35 @@ delete_insn_chain (start, finish)
start = next;
}
}
+
+/* Like delete_insn but also purge dead edges from BB. */
+void
+delete_insn_chain_and_edges (first, last)
+ rtx first, last;
+{
+ bool purge = false;
+
+ if (INSN_P (last)
+ && BLOCK_FOR_INSN (last)
+ && BLOCK_FOR_INSN (last)->end == last)
+ purge = true;
+ delete_insn_chain (first, last);
+ if (purge)
+ purge_dead_edges (BLOCK_FOR_INSN (last));
+}
/* Create a new basic block consisting of the instructions between HEAD and END
inclusive. This function is designed to allow fast BB construction - reuses
the note and basic block struct in BB_NOTE, if any and do not grow
BASIC_BLOCK chain and should be used directly only by CFG construction code.
END can be NULL in to create new empty basic block before HEAD. Both END
- and HEAD can be NULL to create basic block at the end of INSN chain. */
+ and HEAD can be NULL to create basic block at the end of INSN chain.
+ AFTER is the basic block we should be put after. */
basic_block
-create_basic_block_structure (index, head, end, bb_note)
- int index;
+create_basic_block_structure (head, end, bb_note, after)
rtx head, end, bb_note;
+ basic_block after;
{
basic_block bb;
@@ -235,7 +269,7 @@ create_basic_block_structure (index, head, end, bb_note)
}
if (after != bb_note && NEXT_INSN (after) != bb_note)
- reorder_insns (bb_note, bb_note, after);
+ reorder_insns_nobb (bb_note, bb_note, after);
}
else
{
@@ -269,10 +303,11 @@ create_basic_block_structure (index, head, end, bb_note)
bb->head = head;
bb->end = end;
- bb->index = index;
- BASIC_BLOCK (index) = bb;
- if (basic_block_for_insn)
- update_bb_for_insn (bb);
+ bb->index = last_basic_block++;
+ bb->flags = BB_NEW;
+ link_block (bb, after);
+ BASIC_BLOCK (bb->index) = bb;
+ update_bb_for_insn (bb);
/* Tag the block so that we know it has been used when considering
other basic block notes. */
@@ -282,33 +317,23 @@ create_basic_block_structure (index, head, end, bb_note)
}
/* Create new basic block consisting of instructions in between HEAD and END
- and place it to the BB chain at position INDEX. END can be NULL in to
+ and place it to the BB chain after block AFTER. END can be NULL in to
create new empty basic block before HEAD. Both END and HEAD can be NULL to
create basic block at the end of INSN chain. */
basic_block
-create_basic_block (index, head, end)
- int index;
+create_basic_block (head, end, after)
rtx head, end;
+ basic_block after;
{
basic_block bb;
- int i;
- /* Place the new block just after the block being split. */
- VARRAY_GROW (basic_block_info, ++n_basic_blocks);
+ /* Place the new block just after the end. */
+ VARRAY_GROW (basic_block_info, last_basic_block+1);
- /* Some parts of the compiler expect blocks to be number in
- sequential order so insert the new block immediately after the
- block being split.. */
- for (i = n_basic_blocks - 1; i > index; --i)
- {
- basic_block tmp = BASIC_BLOCK (i - 1);
-
- BASIC_BLOCK (i) = tmp;
- tmp->index = i;
- }
+ n_basic_blocks++;
- bb = create_basic_block_structure (index, head, end, NULL);
+ bb = create_basic_block_structure (head, end, NULL, after);
bb->aux = NULL;
return bb;
}
@@ -335,6 +360,18 @@ flow_delete_block_noexpunge (b)
and remove the associated NOTE_INSN_EH_REGION_BEG and
NOTE_INSN_EH_REGION_END notes. */
+ /* Get rid of all NOTE_INSN_PREDICTIONs and NOTE_INSN_LOOP_CONTs
+ hanging before the block. */
+
+ for (insn = PREV_INSN (b->head); insn; insn = PREV_INSN (insn))
+ {
+ if (GET_CODE (insn) != NOTE)
+ break;
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PREDICTION
+ || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT)
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ }
+
insn = b->head;
never_reached_warning (insn, b->end);
@@ -379,38 +416,28 @@ flow_delete_block (b)
basic_block b;
{
int deleted_handler = flow_delete_block_noexpunge (b);
-
- /* Remove the basic block from the array, and compact behind it. */
+
+ /* Remove the basic block from the array. */
expunge_block (b);
return deleted_handler;
}
-/* Records the basic block struct in BB_FOR_INSN, for every instruction
- indexed by INSN_UID. MAX is the size of the array. */
+/* Records the basic block struct in BLOCK_FOR_INSN for every insn. */
void
-compute_bb_for_insn (max)
- int max;
+compute_bb_for_insn ()
{
- int i;
-
- if (basic_block_for_insn)
- VARRAY_FREE (basic_block_for_insn);
-
- VARRAY_BB_INIT (basic_block_for_insn, max, "basic_block_for_insn");
+ basic_block bb;
- for (i = 0; i < n_basic_blocks; ++i)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
rtx end = bb->end;
rtx insn;
for (insn = bb->head; ; insn = NEXT_INSN (insn))
{
- if (INSN_UID (insn) < max)
- VARRAY_BB (basic_block_for_insn, INSN_UID (insn)) = bb;
-
+ BLOCK_FOR_INSN (insn) = bb;
if (insn == end)
break;
}
@@ -422,10 +449,10 @@ compute_bb_for_insn (max)
void
free_bb_for_insn ()
{
- if (basic_block_for_insn)
- VARRAY_FREE (basic_block_for_insn);
-
- basic_block_for_insn = 0;
+ rtx insn;
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) != BARRIER)
+ BLOCK_FOR_INSN (insn) = NULL;
}
/* Update insns block within BB. */
@@ -436,9 +463,6 @@ update_bb_for_insn (bb)
{
rtx insn;
- if (! basic_block_for_insn)
- return;
-
for (insn = bb->head; ; insn = NEXT_INSN (insn))
{
set_block_for_insn (insn, bb);
@@ -446,26 +470,6 @@ update_bb_for_insn (bb)
break;
}
}
-
-/* Record INSN's block as BB. */
-
-void
-set_block_for_insn (insn, bb)
- rtx insn;
- basic_block bb;
-{
- size_t uid = INSN_UID (insn);
-
- if (uid >= basic_block_for_insn->num_elements)
- {
- /* Add one-eighth the size so we don't keep calling xrealloc. */
- size_t new_size = uid + (uid + 7) / 8;
-
- VARRAY_GROW (basic_block_for_insn, new_size);
- }
-
- VARRAY_BB (basic_block_for_insn, uid) = bb;
-}
/* Split a block BB after insn INSN creating a new fallthru edge.
Return the new edge. Note that to keep other parts of the compiler happy,
@@ -486,7 +490,7 @@ split_block (bb, insn)
return 0;
/* Create the new basic block. */
- new_bb = create_basic_block (bb->index + 1, NEXT_INSN (insn), bb->end);
+ new_bb = create_basic_block (NEXT_INSN (insn), bb->end, bb);
new_bb->count = bb->count;
new_bb->frequency = bb->frequency;
new_bb->loop_depth = bb->loop_depth;
@@ -515,6 +519,15 @@ split_block (bb, insn)
propagate_block (new_bb, new_bb->global_live_at_start, NULL, NULL, 0);
COPY_REG_SET (bb->global_live_at_end,
new_bb->global_live_at_start);
+#ifdef HAVE_conditional_execution
+ /* In the presence of conditional execution we are not able to update
+ liveness precisely. */
+ if (reload_completed)
+ {
+ bb->flags |= BB_DIRTY;
+ new_bb->flags |= BB_DIRTY;
+ }
+#endif
}
return new_edge;
@@ -600,6 +613,7 @@ merge_blocks_nomove (a, b)
for (e = b->succ; e; e = e->succ_next)
e->src = a;
a->succ = b->succ;
+ a->flags |= b->flags;
/* B hasn't quite yet ceased to exist. Attempt to prevent mishap. */
b->pred = b->succ = NULL;
@@ -614,15 +628,12 @@ merge_blocks_nomove (a, b)
/* Reassociate the insns of B with A. */
if (!b_empty)
{
- if (basic_block_for_insn)
- {
- rtx x;
+ rtx x;
- for (x = a_end; x != b_end; x = NEXT_INSN (x))
- set_block_for_insn (x, a);
+ for (x = a_end; x != b_end; x = NEXT_INSN (x))
+ set_block_for_insn (x, a);
- set_block_for_insn (b_end, a);
- }
+ set_block_for_insn (b_end, a);
a_end = b_end;
}
@@ -643,8 +654,6 @@ block_label (block)
if (GET_CODE (block->head) != CODE_LABEL)
{
block->head = emit_label_before (gen_label_rtx (), block->head);
- if (basic_block_for_insn)
- set_block_for_insn (block->head, block);
}
return block->head;
@@ -663,9 +672,8 @@ try_redirect_by_replacing_jump (e, target)
basic_block src = e->src;
rtx insn = src->end, kill_from;
edge tmp;
- rtx set;
+ rtx set, table;
int fallthru = 0;
- rtx table;
/* Verify that all targets will be TARGET. */
for (tmp = src->succ; tmp; tmp = tmp->succ_next)
@@ -674,8 +682,7 @@ try_redirect_by_replacing_jump (e, target)
if (tmp || !onlyjump_p (insn))
return false;
-
- if (reload_completed && JUMP_LABEL (insn)
+ if (flow2_completed && JUMP_LABEL (insn)
&& (table = NEXT_INSN (JUMP_LABEL (insn))) != NULL_RTX
&& GET_CODE (table) == JUMP_INSN
&& (GET_CODE (PATTERN (table)) == ADDR_VEC
@@ -786,7 +793,7 @@ try_redirect_by_replacing_jump (e, target)
/* Return last loop_beg note appearing after INSN, before start of next
basic block. Return INSN if there are no such notes.
- When emitting jump to redirect an fallthru edge, it should always appear
+ When emitting jump to redirect a fallthru edge, it should always appear
after the LOOP_BEG notes, as loop optimizer expect loop to either start by
fallthru edge or jump following the LOOP_BEG note jumping to the loop exit
test. */
@@ -926,12 +933,54 @@ force_nonfallthru_and_redirect (e, target)
edge e;
basic_block target;
{
- basic_block jump_block, new_bb = NULL;
+ basic_block jump_block, new_bb = NULL, src = e->src;
rtx note;
edge new_edge;
+ int abnormal_edge_flags = 0;
+
+ /* In the case the last instruction is conditional jump to the next
+ instruction, first redirect the jump itself and then continue
+ by creating an basic block afterwards to redirect fallthru edge. */
+ if (e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR
+ && any_condjump_p (e->src->end)
+ /* When called from cfglayout, fallthru edges do not
+ neccessarily go to the next block. */
+ && e->src->next_bb == e->dest
+ && JUMP_LABEL (e->src->end) == e->dest->head)
+ {
+ rtx note;
+ edge b = unchecked_make_edge (e->src, target, 0);
+
+ if (!redirect_jump (e->src->end, block_label (target), 0))
+ abort ();
+ note = find_reg_note (e->src->end, REG_BR_PROB, NULL_RTX);
+ if (note)
+ {
+ int prob = INTVAL (XEXP (note, 0));
+
+ b->probability = prob;
+ b->count = e->count * prob / REG_BR_PROB_BASE;
+ e->probability -= e->probability;
+ e->count -= b->count;
+ if (e->probability < 0)
+ e->probability = 0;
+ if (e->count < 0)
+ e->count = 0;
+ }
+ }
if (e->flags & EDGE_ABNORMAL)
- abort ();
+ {
+ /* Irritating special case - fallthru edge to the same block as abnormal
+ edge.
+ We can't redirect abnormal edge, but we still can split the fallthru
+ one and create separate abnormal edge to original destination.
+ This allows bb-reorder to make such edge non-fallthru. */
+ if (e->dest != target)
+ abort ();
+ abnormal_edge_flags = e->flags & ~(EDGE_FALLTHRU | EDGE_CAN_FALLTHRU);
+ e->flags &= EDGE_FALLTHRU | EDGE_CAN_FALLTHRU;
+ }
else if (!(e->flags & EDGE_FALLTHRU))
abort ();
else if (e->src == ENTRY_BLOCK_PTR)
@@ -939,14 +988,11 @@ force_nonfallthru_and_redirect (e, target)
/* We can't redirect the entry block. Create an empty block at the
start of the function which we use to add the new jump. */
edge *pe1;
- basic_block bb = create_basic_block (0, e->dest->head, NULL);
+ basic_block bb = create_basic_block (e->dest->head, NULL, ENTRY_BLOCK_PTR);
/* Change the existing edge's source to be the new block, and add
a new edge from the entry block to the new block. */
e->src = bb;
- bb->count = e->count;
- bb->frequency = EDGE_FREQUENCY (e);
- bb->loop_depth = 0;
for (pe1 = &ENTRY_BLOCK_PTR->succ; *pe1; pe1 = &(*pe1)->succ_next)
if (*pe1 == e)
{
@@ -958,7 +1004,7 @@ force_nonfallthru_and_redirect (e, target)
make_single_succ_edge (ENTRY_BLOCK_PTR, bb, EDGE_FALLTHRU);
}
- if (e->src->succ->succ_next)
+ if (e->src->succ->succ_next || abnormal_edge_flags)
{
/* Create the new structures. */
@@ -975,7 +1021,7 @@ force_nonfallthru_and_redirect (e, target)
|| GET_CODE (PATTERN (NEXT_INSN (note))) == ADDR_VEC))
note = NEXT_INSN (NEXT_INSN (note));
- jump_block = create_basic_block (e->src->index + 1, note, NULL);
+ jump_block = create_basic_block (note, NULL, e->src);
jump_block->count = e->count;
jump_block->frequency = EDGE_FREQUENCY (e);
jump_block->loop_depth = target->loop_depth;
@@ -1025,6 +1071,9 @@ force_nonfallthru_and_redirect (e, target)
emit_barrier_after (jump_block->end);
redirect_edge_succ_nodup (e, target);
+ if (abnormal_edge_flags)
+ make_edge (src, target, abnormal_edge_flags);
+
return new_bb;
}
@@ -1077,8 +1126,9 @@ tidy_fallthru_edge (e, b, c)
So search through a sequence of barriers, labels, and notes for
the head of block C and assert that we really do fall through. */
- if (next_real_insn (b->end) != next_real_insn (PREV_INSN (c->head)))
- return;
+ for (q = NEXT_INSN (b->end); q != c->head; q = NEXT_INSN (q))
+ if (INSN_P (q))
+ return;
/* Remove what will soon cease being the jump insn from the source block.
If block B consisted only of this single jump, turn it into a deleted
@@ -1119,14 +1169,17 @@ tidy_fallthru_edge (e, b, c)
void
tidy_fallthru_edges ()
{
- int i;
+ basic_block b, c;
- for (i = 1; i < n_basic_blocks; i++)
+ if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
+ return;
+
+ FOR_BB_BETWEEN (b, ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR->prev_bb, next_bb)
{
- basic_block b = BASIC_BLOCK (i - 1);
- basic_block c = BASIC_BLOCK (i);
edge s;
+ c = b->next_bb;
+
/* We care about simple conditional or unconditional jumps with
a single successor.
@@ -1159,12 +1212,19 @@ back_edge_of_syntactic_loop_p (bb1, bb2)
{
rtx insn;
int count = 0;
+ basic_block bb;
- if (bb1->index > bb2->index)
- return false;
- else if (bb1->index == bb2->index)
+ if (bb1 == bb2)
return true;
+ /* ??? Could we guarantee that bb indices are monotone, so that we could
+ just compare them? */
+ for (bb = bb1; bb && bb != bb2; bb = bb->next_bb)
+ continue;
+
+ if (!bb)
+ return false;
+
for (insn = bb1->end; insn != bb2->head && count >= 0;
insn = NEXT_INSN (insn))
if (GET_CODE (insn) == NOTE)
@@ -1241,11 +1301,9 @@ split_edge (edge_in)
else
before = NULL_RTX;
- bb = create_basic_block (edge_in->dest == EXIT_BLOCK_PTR ? n_basic_blocks
- : edge_in->dest->index, before, NULL);
+ bb = create_basic_block (before, NULL, edge_in->dest->prev_bb);
bb->count = edge_in->count;
bb->frequency = EDGE_FREQUENCY (edge_in);
- bb->loop_depth = edge_in->dest->loop_depth;
/* ??? This info is likely going to be out of date very soon. */
if (edge_in->dest->global_live_at_start)
@@ -1301,94 +1359,115 @@ insert_insn_on_edge (pattern, e)
/* Update the CFG for the instructions queued on edge E. */
static void
-commit_one_edge_insertion (e)
+commit_one_edge_insertion (e, watch_calls)
edge e;
+ int watch_calls;
{
rtx before = NULL_RTX, after = NULL_RTX, insns, tmp, last;
- basic_block bb;
+ basic_block bb = NULL;
/* Pull the insns off the edge now since the edge might go away. */
insns = e->insns;
e->insns = NULL_RTX;
- /* Figure out where to put these things. If the destination has
- one predecessor, insert there. Except for the exit block. */
- if (e->dest->pred->pred_next == NULL
- && e->dest != EXIT_BLOCK_PTR)
+ /* Special case -- avoid inserting code between call and storing
+ its return value. */
+ if (watch_calls && (e->flags & EDGE_FALLTHRU) && !e->dest->pred->pred_next
+ && e->src != ENTRY_BLOCK_PTR
+ && GET_CODE (e->src->end) == CALL_INSN)
{
- bb = e->dest;
+ rtx next = next_nonnote_insn (e->src->end);
- /* Get the location correct wrt a code label, and "nice" wrt
- a basic block note, and before everything else. */
- tmp = bb->head;
- if (GET_CODE (tmp) == CODE_LABEL)
- tmp = NEXT_INSN (tmp);
- if (NOTE_INSN_BASIC_BLOCK_P (tmp))
- tmp = NEXT_INSN (tmp);
- if (tmp == bb->head)
- before = tmp;
- else
- after = PREV_INSN (tmp);
+ after = e->dest->head;
+ /* The first insn after the call may be a stack pop, skip it. */
+ while (next
+ && keep_with_call_p (next))
+ {
+ after = next;
+ next = next_nonnote_insn (next);
+ }
+ bb = e->dest;
}
-
- /* If the source has one successor and the edge is not abnormal,
- insert there. Except for the entry block. */
- else if ((e->flags & EDGE_ABNORMAL) == 0
- && e->src->succ->succ_next == NULL
- && e->src != ENTRY_BLOCK_PTR)
+ if (!before && !after)
{
- bb = e->src;
-
- /* It is possible to have a non-simple jump here. Consider a target
- where some forms of unconditional jumps clobber a register. This
- happens on the fr30 for example.
-
- We know this block has a single successor, so we can just emit
- the queued insns before the jump. */
- if (GET_CODE (bb->end) == JUMP_INSN)
- for (before = bb->end;
- GET_CODE (PREV_INSN (before)) == NOTE
- && NOTE_LINE_NUMBER (PREV_INSN (before)) == NOTE_INSN_LOOP_BEG;
- before = PREV_INSN (before))
- ;
- else
+ /* Figure out where to put these things. If the destination has
+ one predecessor, insert there. Except for the exit block. */
+ if (e->dest->pred->pred_next == NULL && e->dest != EXIT_BLOCK_PTR)
+ {
+ bb = e->dest;
+
+ /* Get the location correct wrt a code label, and "nice" wrt
+ a basic block note, and before everything else. */
+ tmp = bb->head;
+ if (GET_CODE (tmp) == CODE_LABEL)
+ tmp = NEXT_INSN (tmp);
+ if (NOTE_INSN_BASIC_BLOCK_P (tmp))
+ tmp = NEXT_INSN (tmp);
+ if (tmp == bb->head)
+ before = tmp;
+ else if (tmp)
+ after = PREV_INSN (tmp);
+ else
+ after = get_last_insn ();
+ }
+
+ /* If the source has one successor and the edge is not abnormal,
+ insert there. Except for the entry block. */
+ else if ((e->flags & EDGE_ABNORMAL) == 0
+ && e->src->succ->succ_next == NULL
+ && e->src != ENTRY_BLOCK_PTR)
{
- /* We'd better be fallthru, or we've lost track of what's what. */
- if ((e->flags & EDGE_FALLTHRU) == 0)
- abort ();
+ bb = e->src;
+
+ /* It is possible to have a non-simple jump here. Consider a target
+ where some forms of unconditional jumps clobber a register. This
+ happens on the fr30 for example.
+
+ We know this block has a single successor, so we can just emit
+ the queued insns before the jump. */
+ if (GET_CODE (bb->end) == JUMP_INSN)
+ for (before = bb->end;
+ GET_CODE (PREV_INSN (before)) == NOTE
+ && NOTE_LINE_NUMBER (PREV_INSN (before)) ==
+ NOTE_INSN_LOOP_BEG; before = PREV_INSN (before))
+ ;
+ else
+ {
+ /* We'd better be fallthru, or we've lost track of what's what. */
+ if ((e->flags & EDGE_FALLTHRU) == 0)
+ abort ();
+ after = bb->end;
+ }
+ }
+ /* Otherwise we must split the edge. */
+ else
+ {
+ bb = split_edge (e);
after = bb->end;
}
}
- /* Otherwise we must split the edge. */
- else
- {
- bb = split_edge (e);
- after = bb->end;
- }
-
/* Now that we've found the spot, do the insertion. */
if (before)
{
- emit_insns_before (insns, before);
+ emit_insn_before (insns, before);
last = prev_nonnote_insn (before);
}
else
- last = emit_insns_after (insns, after);
+ last = emit_insn_after (insns, after);
if (returnjump_p (last))
{
/* ??? Remove all outgoing edges from BB and add one for EXIT.
This is not currently a problem because this only happens
- for the (single) epilogue, which already has a fallthru edge
- to EXIT. */
+ for the (single) epilogue, which already has a fallthru edge
+ to EXIT. */
e = bb->succ;
if (e->dest != EXIT_BLOCK_PTR
- || e->succ_next != NULL
- || (e->flags & EDGE_FALLTHRU) == 0)
+ || e->succ_next != NULL || (e->flags & EDGE_FALLTHRU) == 0)
abort ();
e->flags &= ~EDGE_FALLTHRU;
@@ -1400,7 +1479,8 @@ commit_one_edge_insertion (e)
else if (GET_CODE (last) == JUMP_INSN)
abort ();
- find_sub_basic_blocks (bb);
+ /* Mark the basic block for find_sub_basic_blocks. */
+ bb->aux = &bb->aux;
}
/* Update the CFG for all queued instructions. */
@@ -1408,16 +1488,15 @@ commit_one_edge_insertion (e)
void
commit_edge_insertions ()
{
- int i;
basic_block bb;
+ sbitmap blocks;
+ bool changed = false;
#ifdef ENABLE_CHECKING
verify_flow_info ();
#endif
- i = -1;
- bb = ENTRY_BLOCK_PTR;
- while (1)
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
{
edge e, next;
@@ -1425,13 +1504,70 @@ commit_edge_insertions ()
{
next = e->succ_next;
if (e->insns)
- commit_one_edge_insertion (e);
+ {
+ changed = true;
+ commit_one_edge_insertion (e, false);
+ }
}
+ }
- if (++i >= n_basic_blocks)
- break;
- bb = BASIC_BLOCK (i);
+ if (!changed)
+ return;
+
+ blocks = sbitmap_alloc (last_basic_block);
+ sbitmap_zero (blocks);
+ FOR_EACH_BB (bb)
+ if (bb->aux)
+ {
+ SET_BIT (blocks, bb->index);
+ bb->aux = NULL;
+ }
+ find_many_sub_basic_blocks (blocks);
+ sbitmap_free (blocks);
+}
+
+/* Update the CFG for all queued instructions, taking special care of inserting
+ code on edges between call and storing its return value. */
+
+void
+commit_edge_insertions_watch_calls ()
+{
+ basic_block bb;
+ sbitmap blocks;
+ bool changed = false;
+
+#ifdef ENABLE_CHECKING
+ verify_flow_info ();
+#endif
+
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
+ {
+ edge e, next;
+
+ for (e = bb->succ; e; e = next)
+ {
+ next = e->succ_next;
+ if (e->insns)
+ {
+ changed = true;
+ commit_one_edge_insertion (e, true);
+ }
+ }
}
+
+ if (!changed)
+ return;
+
+ blocks = sbitmap_alloc (last_basic_block);
+ sbitmap_zero (blocks);
+ FOR_EACH_BB (bb)
+ if (bb->aux)
+ {
+ SET_BIT (blocks, bb->index);
+ bb->aux = NULL;
+ }
+ find_many_sub_basic_blocks (blocks);
+ sbitmap_free (blocks);
}
/* Print out one basic block with live information at start and end. */
@@ -1501,7 +1637,6 @@ print_rtl_with_bb (outf, rtx_first)
fprintf (outf, "(nil)\n");
else
{
- int i;
enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
int max_uid = get_max_uid ();
basic_block *start
@@ -1511,9 +1646,10 @@ print_rtl_with_bb (outf, rtx_first)
enum bb_state *in_bb_p
= (enum bb_state *) xcalloc (max_uid, sizeof (enum bb_state));
- for (i = n_basic_blocks - 1; i >= 0; i--)
+ basic_block bb;
+
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block bb = BASIC_BLOCK (i);
rtx x;
start[INSN_UID (bb->head)] = bb;
@@ -1534,7 +1670,6 @@ print_rtl_with_bb (outf, rtx_first)
for (tmp_rtx = rtx_first; NULL != tmp_rtx; tmp_rtx = NEXT_INSN (tmp_rtx))
{
int did_output;
- basic_block bb;
if ((bb = start[INSN_UID (tmp_rtx)]) != NULL)
{
@@ -1621,16 +1756,37 @@ verify_flow_info ()
basic_block *bb_info, *last_visited;
size_t *edge_checksum;
rtx x;
- int i, last_bb_num_seen, num_bb_notes, err = 0;
+ int num_bb_notes, err = 0;
+ basic_block bb, last_bb_seen;
bb_info = (basic_block *) xcalloc (max_uid, sizeof (basic_block));
- last_visited = (basic_block *) xcalloc (n_basic_blocks + 2,
+ last_visited = (basic_block *) xcalloc (last_basic_block + 2,
sizeof (basic_block));
- edge_checksum = (size_t *) xcalloc (n_basic_blocks + 2, sizeof (size_t));
+ edge_checksum = (size_t *) xcalloc (last_basic_block + 2, sizeof (size_t));
- for (i = n_basic_blocks - 1; i >= 0; i--)
+ /* Check bb chain & numbers. */
+ last_bb_seen = ENTRY_BLOCK_PTR;
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb, NULL, next_bb)
+ {
+ if (bb != EXIT_BLOCK_PTR
+ && bb != BASIC_BLOCK (bb->index))
+ {
+ error ("bb %d on wrong place", bb->index);
+ err = 1;
+ }
+
+ if (bb->prev_bb != last_bb_seen)
+ {
+ error ("prev_bb of %d should be %d, not %d",
+ bb->index, last_bb_seen->index, bb->prev_bb->index);
+ err = 1;
+ }
+
+ last_bb_seen = bb;
+ }
+
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block bb = BASIC_BLOCK (i);
rtx head = bb->head;
rtx end = bb->end;
@@ -1676,12 +1832,36 @@ verify_flow_info ()
}
/* Now check the basic blocks (boundaries etc.) */
- for (i = n_basic_blocks - 1; i >= 0; i--)
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block bb = BASIC_BLOCK (i);
- int has_fallthru = 0;
+ int n_fallthru = 0, n_eh = 0, n_call = 0, n_abnormal = 0, n_branch = 0;
edge e;
+ rtx note;
+ if (INSN_P (bb->end)
+ && (note = find_reg_note (bb->end, REG_BR_PROB, NULL_RTX))
+ && bb->succ && bb->succ->succ_next
+ && any_condjump_p (bb->end))
+ {
+ if (INTVAL (XEXP (note, 0)) != BRANCH_EDGE (bb)->probability)
+ {
+ error ("verify_flow_info: REG_BR_PROB does not match cfg %i %i",
+ INTVAL (XEXP (note, 0)), BRANCH_EDGE (bb)->probability);
+ err = 1;
+ }
+ }
+ if (bb->count < 0)
+ {
+ error ("verify_flow_info: Wrong count of block %i %i",
+ bb->index, (int)bb->count);
+ err = 1;
+ }
+ if (bb->frequency < 0)
+ {
+ error ("verify_flow_info: Wrong frequency of block %i %i",
+ bb->index, bb->frequency);
+ err = 1;
+ }
for (e = bb->succ; e; e = e->succ_next)
{
if (last_visited [e->dest->index + 2] == bb)
@@ -1690,11 +1870,34 @@ verify_flow_info ()
e->src->index, e->dest->index);
err = 1;
}
+ if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
+ {
+ error ("verify_flow_info: Wrong probability of edge %i->%i %i",
+ e->src->index, e->dest->index, e->probability);
+ err = 1;
+ }
+ if (e->count < 0)
+ {
+ error ("verify_flow_info: Wrong count of edge %i->%i %i",
+ e->src->index, e->dest->index, (int)e->count);
+ err = 1;
+ }
last_visited [e->dest->index + 2] = bb;
if (e->flags & EDGE_FALLTHRU)
- has_fallthru = 1;
+ n_fallthru++;
+
+ if ((e->flags & ~EDGE_DFS_BACK) == 0)
+ n_branch++;
+
+ if (e->flags & EDGE_ABNORMAL_CALL)
+ n_call++;
+
+ if (e->flags & EDGE_EH)
+ n_eh++;
+ else if (e->flags & EDGE_ABNORMAL)
+ n_abnormal++;
if ((e->flags & EDGE_FALLTHRU)
&& e->src != ENTRY_BLOCK_PTR
@@ -1702,7 +1905,7 @@ verify_flow_info ()
{
rtx insn;
- if (e->src->index + 1 != e->dest->index)
+ if (e->src->next_bb != e->dest)
{
error
("verify_flow_info: Incorrect blocks for fallthru %i->%i",
@@ -1742,7 +1945,52 @@ verify_flow_info ()
edge_checksum[e->dest->index + 2] += (size_t) e;
}
- if (!has_fallthru)
+ if (n_eh && GET_CODE (PATTERN (bb->end)) != RESX
+ && !find_reg_note (bb->end, REG_EH_REGION, NULL_RTX))
+ {
+ error ("Missing REG_EH_REGION note in the end of bb %i", bb->index);
+ err = 1;
+ }
+ if (n_branch
+ && (GET_CODE (bb->end) != JUMP_INSN
+ || (n_branch > 1 && (any_uncondjump_p (bb->end)
+ || any_condjump_p (bb->end)))))
+ {
+ error ("Too many outgoing branch edges from bb %i", bb->index);
+ err = 1;
+ }
+ if (n_fallthru && any_uncondjump_p (bb->end))
+ {
+ error ("Fallthru edge after unconditional jump %i", bb->index);
+ err = 1;
+ }
+ if (n_branch != 1 && any_uncondjump_p (bb->end))
+ {
+ error ("Wrong amount of branch edges after unconditional jump %i", bb->index);
+ err = 1;
+ }
+ if (n_branch != 1 && any_condjump_p (bb->end)
+ && JUMP_LABEL (bb->end) != bb->next_bb->head)
+ {
+ error ("Wrong amount of branch edges after conditional jump %i", bb->index);
+ err = 1;
+ }
+ if (n_call && GET_CODE (bb->end) != CALL_INSN)
+ {
+ error ("Call edges for non-call insn in bb %i", bb->index);
+ err = 1;
+ }
+ if (n_abnormal
+ && (GET_CODE (bb->end) != CALL_INSN && n_call != n_abnormal)
+ && (GET_CODE (bb->end) != JUMP_INSN
+ || any_condjump_p (bb->end)
+ || any_uncondjump_p (bb->end)))
+ {
+ error ("Abnormal edges for no purpose in bb %i", bb->index);
+ err = 1;
+ }
+
+ if (!n_fallthru)
{
rtx insn;
@@ -1775,7 +2023,7 @@ verify_flow_info ()
}
for (x = bb->head; x != NEXT_INSN (bb->end); x = NEXT_INSN (x))
- if (basic_block_for_insn && BLOCK_FOR_INSN (x) != bb)
+ if (BLOCK_FOR_INSN (x) != bb)
{
debug_rtx (x);
if (! BLOCK_FOR_INSN (x))
@@ -1850,26 +2098,27 @@ verify_flow_info ()
edge_checksum[e->dest->index + 2] -= (size_t) e;
}
- for (i = -2; i < n_basic_blocks; ++i)
- if (edge_checksum[i + 2])
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ if (edge_checksum[bb->index + 2])
{
- error ("basic block %i edge lists are corrupted", i);
+ error ("basic block %i edge lists are corrupted", bb->index);
err = 1;
}
- last_bb_num_seen = -1;
num_bb_notes = 0;
+ last_bb_seen = ENTRY_BLOCK_PTR;
+
for (x = rtx_first; x; x = NEXT_INSN (x))
{
if (NOTE_INSN_BASIC_BLOCK_P (x))
{
- basic_block bb = NOTE_BASIC_BLOCK (x);
+ bb = NOTE_BASIC_BLOCK (x);
num_bb_notes++;
- if (bb->index != last_bb_num_seen + 1)
+ if (bb != last_bb_seen->next_bb)
internal_error ("basic blocks not numbered consecutively");
- last_bb_num_seen = bb->index;
+ last_bb_seen = bb;
}
if (!bb_info[INSN_UID (x)])
@@ -1941,18 +2190,29 @@ purge_dead_edges (bb)
remove_note (insn, note);
}
- /* Cleanup abnormal edges caused by throwing insns that have been
- eliminated. */
- if (! can_throw_internal (bb->end))
- for (e = bb->succ; e; e = next)
- {
- next = e->succ_next;
- if (e->flags & EDGE_EH)
- {
- remove_edge (e);
- purged = true;
- }
- }
+ /* Cleanup abnormal edges caused by exceptions or non-local gotos. */
+ for (e = bb->succ; e; e = next)
+ {
+ next = e->succ_next;
+ if (e->flags & EDGE_EH)
+ {
+ if (can_throw_internal (bb->end))
+ continue;
+ }
+ else if (e->flags & EDGE_ABNORMAL_CALL)
+ {
+ if (GET_CODE (bb->end) == CALL_INSN
+ && (! (note = find_reg_note (insn, REG_EH_REGION, NULL))
+ || INTVAL (XEXP (note, 0)) >= 0))
+ continue;
+ }
+ else
+ continue;
+
+ remove_edge (e);
+ bb->flags |= BB_DIRTY;
+ purged = true;
+ }
if (GET_CODE (insn) == JUMP_INSN)
{
@@ -1963,7 +2223,18 @@ purge_dead_edges (bb)
if (!any_condjump_p (insn)
&& !returnjump_p (insn)
&& !simplejump_p (insn))
- return false;
+ return purged;
+
+ /* Branch probability/prediction notes are defined only for
+ condjumps. We've possibly turned condjump into simplejump. */
+ if (simplejump_p (insn))
+ {
+ note = find_reg_note (insn, REG_BR_PROB, NULL);
+ if (note)
+ remove_note (insn, note);
+ while ((note = find_reg_note (insn, REG_BR_PRED, NULL)))
+ remove_note (insn, note);
+ }
for (e = bb->succ; e; e = next)
{
@@ -1971,7 +2242,7 @@ purge_dead_edges (bb)
/* Avoid abnormal flags to leak from computed jumps turned
into simplejumps. */
-
+
e->flags &= ~EDGE_ABNORMAL;
/* See if this edge is one we should keep. */
@@ -1994,12 +2265,13 @@ purge_dead_edges (bb)
continue;
/* We do not need this edge. */
+ bb->flags |= BB_DIRTY;
purged = true;
remove_edge (e);
}
if (!bb->succ || !purged)
- return false;
+ return purged;
if (rtl_dump_file)
fprintf (rtl_dump_file, "Purged edges from bb %i\n", bb->index);
@@ -2012,7 +2284,7 @@ purge_dead_edges (bb)
{
bb->succ->probability = REG_BR_PROB_BASE;
bb->succ->count = bb->count;
- }
+ }
else
{
note = find_reg_note (insn, REG_BR_PROB, NULL);
@@ -2046,7 +2318,11 @@ purge_dead_edges (bb)
{
next = e->succ_next;
if (!(e->flags & EDGE_FALLTHRU))
- remove_edge (e), purged = true;
+ {
+ bb->flags |= BB_DIRTY;
+ remove_edge (e);
+ purged = true;
+ }
}
if (!bb->succ || bb->succ->succ_next)
@@ -2068,22 +2344,23 @@ bool
purge_all_dead_edges (update_life_p)
int update_life_p;
{
- int i, purged = false;
+ int purged = false;
sbitmap blocks = 0;
+ basic_block bb;
if (update_life_p)
{
- blocks = sbitmap_alloc (n_basic_blocks);
+ blocks = sbitmap_alloc (last_basic_block);
sbitmap_zero (blocks);
}
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- bool purged_here = purge_dead_edges (BASIC_BLOCK (i));
+ bool purged_here = purge_dead_edges (bb);
purged |= purged_here;
if (purged_here && update_life_p)
- SET_BIT (blocks, i);
+ SET_BIT (blocks, bb->index);
}
if (update_life_p && purged)
diff --git a/contrib/gcc/collect2.c b/contrib/gcc/collect2.c
index 933a277..81a2bf3 100644
--- a/contrib/gcc/collect2.c
+++ b/contrib/gcc/collect2.c
@@ -57,10 +57,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "obstack.h"
#include "intl.h"
#include "version.h"
-
-/* Obstack allocation and deallocation routines. */
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
/* On certain systems, we have code that works by scanning the object file
directly. But this code uses system-specific header files and library
@@ -144,11 +140,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* 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. */
+ give the same symbol without quotes for an alternative entry point. */
#ifndef NAME__MAIN
#define NAME__MAIN "__main"
-#define SYMBOL__MAIN __main
#endif
/* This must match tree.h. */
@@ -237,19 +231,11 @@ static struct head exports; /* list of exported symbols */
static struct head frame_tables; /* list of frame unwind info tables */
struct obstack temporary_obstack;
-struct obstack permanent_obstack;
char * temporary_firstobj;
/* Holds the return value of pexecute. */
int pexecute_pid;
-/* Defined in the automatically-generated underscore.c. */
-extern int prepends_underscore;
-
-#ifndef GET_ENV_PATH_LIST
-#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
-#endif
-
/* Structure to hold all the directories in which to search for files to
execute. */
@@ -526,8 +512,8 @@ dump_file (name)
if (*word == '.')
++word, putc ('.', stderr);
p = word;
- if (*p == '_' && prepends_underscore)
- ++p;
+ if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
+ p += strlen (USER_LABEL_PREFIX);
if (no_demangle)
result = 0;
@@ -762,7 +748,7 @@ prefix_from_env (env, pprefix)
struct path_prefix *pprefix;
{
const char *p;
- GET_ENV_PATH_LIST (p, env);
+ GET_ENVIRONMENT (p, env);
if (p)
prefix_from_string (p, pprefix);
@@ -926,7 +912,6 @@ main (argc, argv)
#endif
obstack_begin (&temporary_obstack, 0);
- obstack_begin (&permanent_obstack, 0);
temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0);
current_demangling_style = auto_demangling;
@@ -1086,18 +1071,18 @@ main (argc, argv)
{
const char *q = extract_string (&p);
if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
- *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
+ *c_ptr++ = xstrdup (q);
if (strcmp (q, "-EL") == 0 || strcmp (q, "-EB") == 0)
- *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
+ *c_ptr++ = xstrdup (q);
if (strcmp (q, "-shared") == 0)
shared_obj = 1;
if (*q == '-' && q[1] == 'B')
{
- *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
+ *c_ptr++ = xstrdup (q);
if (q[2] == 0)
{
q = extract_string (&p);
- *c_ptr++ = obstack_copy0 (&permanent_obstack, q, strlen (q));
+ *c_ptr++ = xstrdup (q);
}
}
}
@@ -1506,7 +1491,7 @@ main (argc, argv)
}
-/* Wait for a process to finish, and exit if a non-zero status is found. */
+/* Wait for a process to finish, and exit if a nonzero status is found. */
int
collect_wait (prog)
@@ -1522,7 +1507,7 @@ collect_wait (prog)
int sig = WTERMSIG (status);
error ("%s terminated with signal %d [%s]%s",
prog, sig, strsignal(sig),
- status & 0200 ? "" : ", core dumped");
+ WCOREDUMP(status) ? ", core dumped" : "");
collect_exit (FATAL_EXIT_CODE);
}
@@ -2144,7 +2129,7 @@ scan_prog_file (prog_name, which_pass)
fatal_perror ("close %d", pipe_fd[1]);
execv (nm_file_name, real_nm_argv);
- fatal_perror ("execvp %s", nm_file_name);
+ fatal_perror ("execv %s", nm_file_name);
}
/* Parent context from here on. */
@@ -2870,7 +2855,7 @@ scan_prog_file (prog_name, which_pass)
(void) ldclose(ldptr);
#endif
}
-
+#endif /* OBJECT_FORMAT_COFF */
#ifdef COLLECT_EXPORT_LIST
/* Given a library name without "lib" prefix, this function
@@ -2950,9 +2935,7 @@ ignore_library (name)
if (! strcmp (name, *p)) return 1;
return 0;
}
-#endif
-
-#endif /* OBJECT_FORMAT_COFF */
+#endif /* COLLECT_EXPORT_LIST */
/*
diff --git a/contrib/gcc/collect2.h b/contrib/gcc/collect2.h
index 2a65836..f678820 100644
--- a/contrib/gcc/collect2.h
+++ b/contrib/gcc/collect2.h
@@ -36,7 +36,6 @@ extern int file_exists PARAMS ((const char *));
extern const char *ldout;
extern const char *c_file_name;
extern struct obstack temporary_obstack;
-extern struct obstack permanent_obstack;
extern char *temporary_firstobj;
extern int vflag, debug;
diff --git a/contrib/gcc/combine.c b/contrib/gcc/combine.c
index 5e8ad1a..03d0dff 100644
--- a/contrib/gcc/combine.c
+++ b/contrib/gcc/combine.c
@@ -1,6 +1,6 @@
/* Optimize by combining instructions for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -137,6 +137,12 @@ static int max_uid_cuid;
#define UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD(val) \
(((unsigned HOST_WIDE_INT) (val) << (BITS_PER_WORD - 1)) << 1)
+#define nonzero_bits(X, M) \
+ cached_nonzero_bits (X, M, NULL_RTX, VOIDmode, 0)
+
+#define num_sign_bit_copies(X, M) \
+ cached_num_sign_bit_copies (X, M, NULL_RTX, VOIDmode, 0)
+
/* Maximum register number, which is the size of the tables below. */
static unsigned int combine_max_regno;
@@ -192,8 +198,8 @@ static HARD_REG_SET newpat_used_regs;
static rtx added_links_insn;
-/* Basic block number of the block in which we are performing combines. */
-static int this_basic_block;
+/* Basic block in which we are performing combines. */
+static basic_block this_basic_block;
/* A bitmap indicating which blocks had registers go dead at entry.
After combine, we'll need to re-do global life analysis with
@@ -202,7 +208,7 @@ static sbitmap refresh_blocks;
static int need_refresh;
/* The next group of arrays allows the recording of the last value assigned
- to (hard or pseudo) register n. We use this information to see if a
+ to (hard or pseudo) register n. We use this information to see if an
operation being processed is redundant given a prior operation performed
on the register. For example, an `and' with a constant is redundant if
all the zero bits are already known to be turned off.
@@ -221,7 +227,7 @@ static int need_refresh;
register was assigned
reg_last_set_table_tick records the value of label_tick when a
value using the register is assigned
- reg_last_set_invalid set to non-zero when it is not valid
+ reg_last_set_invalid set to nonzero when it is not valid
to use the value of this register in some
register's value
@@ -230,7 +236,7 @@ static int need_refresh;
and the register being validly contained in some other expression in the
table.
- Entry I in reg_last_set_value is valid if it is non-zero, and either
+ Entry I in reg_last_set_value is valid if it is nonzero, and either
reg_n_sets[i] is 1 or reg_last_set_label[i] == label_tick.
Register I may validly appear in any expression returned for the value
@@ -242,7 +248,7 @@ static int need_refresh;
not validly appear in an expression, the register is replaced by
something that won't match, (clobber (const_int 0)).
- reg_last_set_invalid[i] is set non-zero when register I is being assigned
+ reg_last_set_invalid[i] is set nonzero when register I is being assigned
to and reg_last_set_table_tick[i] == label_tick. */
/* Record last value assigned to (hard or pseudo) register n. */
@@ -259,7 +265,7 @@ static int *reg_last_set_label;
static int *reg_last_set_table_tick;
-/* Set non-zero if references to register n in expressions should not be
+/* Set nonzero if references to register n in expressions should not be
used. */
static char *reg_last_set_invalid;
@@ -314,8 +320,8 @@ struct undo
{
struct undo *next;
int is_int;
- union {rtx r; unsigned int i;} old_contents;
- union {rtx *r; unsigned int *i;} where;
+ union {rtx r; int i;} old_contents;
+ union {rtx *r; int *i;} where;
};
/* Record a bunch of changes to be undone, up to MAX_UNDO of them.
@@ -339,8 +345,7 @@ static struct undobuf undobuf;
static int n_occurrences;
static void do_SUBST PARAMS ((rtx *, rtx));
-static void do_SUBST_INT PARAMS ((unsigned int *,
- unsigned int));
+static void do_SUBST_INT PARAMS ((int *, int));
static void init_reg_last_arrays PARAMS ((void));
static void setup_incoming_promotions PARAMS ((void));
static void set_nonzero_bits_and_sign_copies PARAMS ((rtx, rtx, void *));
@@ -376,8 +381,20 @@ static rtx make_field_assignment PARAMS ((rtx));
static rtx apply_distributive_law PARAMS ((rtx));
static rtx simplify_and_const_int PARAMS ((rtx, enum machine_mode, rtx,
unsigned HOST_WIDE_INT));
-static unsigned HOST_WIDE_INT nonzero_bits PARAMS ((rtx, enum machine_mode));
-static unsigned int num_sign_bit_copies PARAMS ((rtx, enum machine_mode));
+static unsigned HOST_WIDE_INT cached_nonzero_bits
+ PARAMS ((rtx, enum machine_mode, rtx,
+ enum machine_mode,
+ unsigned HOST_WIDE_INT));
+static unsigned HOST_WIDE_INT nonzero_bits1
+ PARAMS ((rtx, enum machine_mode, rtx,
+ enum machine_mode,
+ unsigned HOST_WIDE_INT));
+static unsigned int cached_num_sign_bit_copies
+ PARAMS ((rtx, enum machine_mode, rtx,
+ enum machine_mode, unsigned int));
+static unsigned int num_sign_bit_copies1
+ PARAMS ((rtx, enum machine_mode, rtx,
+ enum machine_mode, unsigned int));
static int merge_outer_ops PARAMS ((enum rtx_code *, HOST_WIDE_INT *,
enum rtx_code, HOST_WIDE_INT,
enum machine_mode, int *));
@@ -472,10 +489,10 @@ do_SUBST (into, newval)
static void
do_SUBST_INT (into, newval)
- unsigned int *into, newval;
+ int *into, newval;
{
struct undo *buf;
- unsigned int oldval = *into;
+ int oldval = *into;
if (oldval == newval)
return;
@@ -498,7 +515,7 @@ do_SUBST_INT (into, newval)
/* Main entry point for combiner. F is the first insn of the function.
NREGS is the first unused pseudo-reg number.
- Return non-zero if the combiner has turned an indirect jump
+ Return nonzero if the combiner has turned an indirect jump
instruction into a direct jump. */
int
combine_instructions (f, nregs)
@@ -578,7 +595,7 @@ combine_instructions (f, nregs)
setup_incoming_promotions ();
- refresh_blocks = sbitmap_alloc (n_basic_blocks);
+ refresh_blocks = sbitmap_alloc (last_basic_block);
sbitmap_zero (refresh_blocks);
need_refresh = 0;
@@ -610,143 +627,144 @@ combine_instructions (f, nregs)
/* Now scan all the insns in forward order. */
- this_basic_block = -1;
label_tick = 1;
last_call_cuid = 0;
mem_last_set = 0;
init_reg_last_arrays ();
setup_incoming_promotions ();
- for (insn = f; insn; insn = next ? next : NEXT_INSN (insn))
+ FOR_EACH_BB (this_basic_block)
{
- next = 0;
-
- /* If INSN starts a new basic block, update our basic block number. */
- if (this_basic_block + 1 < n_basic_blocks
- && BLOCK_HEAD (this_basic_block + 1) == insn)
- this_basic_block++;
-
- if (GET_CODE (insn) == CODE_LABEL)
- label_tick++;
-
- else if (INSN_P (insn))
+ for (insn = this_basic_block->head;
+ insn != NEXT_INSN (this_basic_block->end);
+ insn = next ? next : NEXT_INSN (insn))
{
- /* See if we know about function return values before this
- insn based upon SUBREG flags. */
- check_promoted_subreg (insn, PATTERN (insn));
-
- /* Try this insn with each insn it links back to. */
+ next = 0;
- for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
- if ((next = try_combine (insn, XEXP (links, 0),
- NULL_RTX, &new_direct_jump_p)) != 0)
- goto retry;
+ if (GET_CODE (insn) == CODE_LABEL)
+ label_tick++;
- /* Try each sequence of three linked insns ending with this one. */
-
- for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+ else if (INSN_P (insn))
{
- rtx link = XEXP (links, 0);
+ /* See if we know about function return values before this
+ insn based upon SUBREG flags. */
+ check_promoted_subreg (insn, PATTERN (insn));
- /* If the linked insn has been replaced by a note, then there
- is no point in pursuing this chain any further. */
- if (GET_CODE (link) == NOTE)
- continue;
+ /* Try this insn with each insn it links back to. */
- for (nextlinks = LOG_LINKS (link);
- nextlinks;
- nextlinks = XEXP (nextlinks, 1))
- if ((next = try_combine (insn, link,
- XEXP (nextlinks, 0),
- &new_direct_jump_p)) != 0)
+ for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+ if ((next = try_combine (insn, XEXP (links, 0),
+ NULL_RTX, &new_direct_jump_p)) != 0)
goto retry;
- }
+
+ /* Try each sequence of three linked insns ending with this one. */
+
+ for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+ {
+ rtx link = XEXP (links, 0);
+
+ /* If the linked insn has been replaced by a note, then there
+ is no point in pursuing this chain any further. */
+ if (GET_CODE (link) == NOTE)
+ continue;
+
+ for (nextlinks = LOG_LINKS (link);
+ nextlinks;
+ nextlinks = XEXP (nextlinks, 1))
+ if ((next = try_combine (insn, link,
+ XEXP (nextlinks, 0),
+ &new_direct_jump_p)) != 0)
+ goto retry;
+ }
#ifdef HAVE_cc0
- /* Try to combine a jump insn that uses CC0
- with a preceding insn that sets CC0, and maybe with its
- logical predecessor as well.
- This is how we make decrement-and-branch insns.
- We need this special code because data flow connections
- via CC0 do not get entered in LOG_LINKS. */
-
- if (GET_CODE (insn) == JUMP_INSN
- && (prev = prev_nonnote_insn (insn)) != 0
- && GET_CODE (prev) == INSN
- && sets_cc0_p (PATTERN (prev)))
- {
- if ((next = try_combine (insn, prev,
- NULL_RTX, &new_direct_jump_p)) != 0)
- goto retry;
-
- for (nextlinks = LOG_LINKS (prev); nextlinks;
- nextlinks = XEXP (nextlinks, 1))
- if ((next = try_combine (insn, prev,
- XEXP (nextlinks, 0),
- &new_direct_jump_p)) != 0)
- goto retry;
- }
+ /* Try to combine a jump insn that uses CC0
+ with a preceding insn that sets CC0, and maybe with its
+ logical predecessor as well.
+ This is how we make decrement-and-branch insns.
+ We need this special code because data flow connections
+ via CC0 do not get entered in LOG_LINKS. */
+
+ if (GET_CODE (insn) == JUMP_INSN
+ && (prev = prev_nonnote_insn (insn)) != 0
+ && GET_CODE (prev) == INSN
+ && sets_cc0_p (PATTERN (prev)))
+ {
+ if ((next = try_combine (insn, prev,
+ NULL_RTX, &new_direct_jump_p)) != 0)
+ goto retry;
+
+ for (nextlinks = LOG_LINKS (prev); nextlinks;
+ nextlinks = XEXP (nextlinks, 1))
+ if ((next = try_combine (insn, prev,
+ XEXP (nextlinks, 0),
+ &new_direct_jump_p)) != 0)
+ goto retry;
+ }
- /* Do the same for an insn that explicitly references CC0. */
- if (GET_CODE (insn) == INSN
- && (prev = prev_nonnote_insn (insn)) != 0
- && GET_CODE (prev) == INSN
- && sets_cc0_p (PATTERN (prev))
- && GET_CODE (PATTERN (insn)) == SET
- && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (insn))))
- {
- if ((next = try_combine (insn, prev,
- NULL_RTX, &new_direct_jump_p)) != 0)
- goto retry;
+ /* Do the same for an insn that explicitly references CC0. */
+ if (GET_CODE (insn) == INSN
+ && (prev = prev_nonnote_insn (insn)) != 0
+ && GET_CODE (prev) == INSN
+ && sets_cc0_p (PATTERN (prev))
+ && GET_CODE (PATTERN (insn)) == SET
+ && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (insn))))
+ {
+ if ((next = try_combine (insn, prev,
+ NULL_RTX, &new_direct_jump_p)) != 0)
+ goto retry;
+
+ for (nextlinks = LOG_LINKS (prev); nextlinks;
+ nextlinks = XEXP (nextlinks, 1))
+ if ((next = try_combine (insn, prev,
+ XEXP (nextlinks, 0),
+ &new_direct_jump_p)) != 0)
+ goto retry;
+ }
- for (nextlinks = LOG_LINKS (prev); nextlinks;
- nextlinks = XEXP (nextlinks, 1))
- if ((next = try_combine (insn, prev,
- XEXP (nextlinks, 0),
- &new_direct_jump_p)) != 0)
+ /* Finally, see if any of the insns that this insn links to
+ explicitly references CC0. If so, try this insn, that insn,
+ and its predecessor if it sets CC0. */
+ for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+ if (GET_CODE (XEXP (links, 0)) == INSN
+ && GET_CODE (PATTERN (XEXP (links, 0))) == SET
+ && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (XEXP (links, 0))))
+ && (prev = prev_nonnote_insn (XEXP (links, 0))) != 0
+ && GET_CODE (prev) == INSN
+ && sets_cc0_p (PATTERN (prev))
+ && (next = try_combine (insn, XEXP (links, 0),
+ prev, &new_direct_jump_p)) != 0)
goto retry;
- }
-
- /* Finally, see if any of the insns that this insn links to
- explicitly references CC0. If so, try this insn, that insn,
- and its predecessor if it sets CC0. */
- for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
- if (GET_CODE (XEXP (links, 0)) == INSN
- && GET_CODE (PATTERN (XEXP (links, 0))) == SET
- && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (XEXP (links, 0))))
- && (prev = prev_nonnote_insn (XEXP (links, 0))) != 0
- && GET_CODE (prev) == INSN
- && sets_cc0_p (PATTERN (prev))
- && (next = try_combine (insn, XEXP (links, 0),
- prev, &new_direct_jump_p)) != 0)
- goto retry;
#endif
- /* Try combining an insn with two different insns whose results it
- uses. */
- for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
- for (nextlinks = XEXP (links, 1); nextlinks;
- nextlinks = XEXP (nextlinks, 1))
- if ((next = try_combine (insn, XEXP (links, 0),
- XEXP (nextlinks, 0),
- &new_direct_jump_p)) != 0)
- goto retry;
+ /* Try combining an insn with two different insns whose results it
+ uses. */
+ for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+ for (nextlinks = XEXP (links, 1); nextlinks;
+ nextlinks = XEXP (nextlinks, 1))
+ if ((next = try_combine (insn, XEXP (links, 0),
+ XEXP (nextlinks, 0),
+ &new_direct_jump_p)) != 0)
+ goto retry;
- if (GET_CODE (insn) != NOTE)
- record_dead_and_set_regs (insn);
+ if (GET_CODE (insn) != NOTE)
+ record_dead_and_set_regs (insn);
- retry:
- ;
+ retry:
+ ;
+ }
}
}
+ clear_bb_flags ();
+ EXECUTE_IF_SET_IN_SBITMAP (refresh_blocks, 0, i,
+ BASIC_BLOCK (i)->flags |= BB_DIRTY);
+ new_direct_jump_p |= purge_all_dead_edges (0);
delete_noop_moves (f);
- if (need_refresh)
- {
- update_life_info (refresh_blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
- PROP_DEATH_NOTES);
- }
+ update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
+ PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
+ | PROP_KILL_DEAD_CODE);
/* Clean up. */
sbitmap_free (refresh_blocks);
@@ -858,7 +876,7 @@ set_nonzero_bits_and_sign_copies (x, set, data)
&& REGNO (x) >= FIRST_PSEUDO_REGISTER
/* If this register is undefined at the start of the file, we can't
say what its contents were. */
- && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, REGNO (x))
+ && ! REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, REGNO (x))
&& GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT)
{
if (set == 0 || GET_CODE (set) == CLOBBER)
@@ -1285,13 +1303,13 @@ sets_function_arg_p (pat)
case, we would be getting the wrong value of I2DEST into I3, so we
must reject the combination. This case occurs when I2 and I1 both
feed into I3, rather than when I1 feeds into I2, which feeds into I3.
- If I1_NOT_IN_SRC is non-zero, it means that finding I1 in the source
+ If I1_NOT_IN_SRC is nonzero, it means that finding I1 in the source
of a SET must prevent combination from occurring.
Before doing the above check, we first try to expand a field assignment
into a set of logical operations.
- If PI3_DEST_KILLED is non-zero, it is a pointer to a location in which
+ If PI3_DEST_KILLED is nonzero, it is a pointer to a location in which
we place a register that is both set and used within I3. If more than one
such register is detected, we fail.
@@ -1497,7 +1515,7 @@ cant_combine_insn_p (insn)
If we did the combination, return the insn at which combine should
resume scanning.
- Set NEW_DIRECT_JUMP_P to a non-zero value if try_combine creates a
+ Set NEW_DIRECT_JUMP_P to a nonzero value if try_combine creates a
new direct jump instruction. */
static rtx
@@ -1754,6 +1772,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
subst_prev_insn = i1
= gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2,
+ BLOCK_FOR_INSN (i2), INSN_SCOPE (i2),
XVECEXP (PATTERN (i2), 0, 1), -1, NULL_RTX,
NULL_RTX);
@@ -2165,30 +2184,23 @@ try_combine (i3, i2, i1, new_direct_jump_p)
}
}
- /* If we've split a jump pattern, we'll wind up with a sequence even
- with one instruction. We can handle that below, so extract it. */
- if (m_split && GET_CODE (m_split) == SEQUENCE
- && XVECLEN (m_split, 0) == 1)
- m_split = PATTERN (XVECEXP (m_split, 0, 0));
-
- if (m_split && GET_CODE (m_split) != SEQUENCE)
+ if (m_split && NEXT_INSN (m_split) == NULL_RTX)
{
+ m_split = PATTERN (m_split);
insn_code_number = recog_for_combine (&m_split, i3, &new_i3_notes);
if (insn_code_number >= 0)
newpat = m_split;
}
- else if (m_split && GET_CODE (m_split) == SEQUENCE
- && XVECLEN (m_split, 0) == 2
+ else if (m_split && NEXT_INSN (NEXT_INSN (m_split)) == NULL_RTX
&& (next_real_insn (i2) == i3
- || ! use_crosses_set_p (PATTERN (XVECEXP (m_split, 0, 0)),
- INSN_CUID (i2))))
+ || ! use_crosses_set_p (PATTERN (m_split), INSN_CUID (i2))))
{
rtx i2set, i3set;
- rtx newi3pat = PATTERN (XVECEXP (m_split, 0, 1));
- newi2pat = PATTERN (XVECEXP (m_split, 0, 0));
+ rtx newi3pat = PATTERN (NEXT_INSN (m_split));
+ newi2pat = PATTERN (m_split);
- i3set = single_set (XVECEXP (m_split, 0, 1));
- i2set = single_set (XVECEXP (m_split, 0, 0));
+ i3set = single_set (NEXT_INSN (m_split));
+ i2set = single_set (m_split);
/* In case we changed the mode of I2DEST, replace it in the
pseudo-register table here. We can't do it above in case this
@@ -2289,8 +2301,19 @@ try_combine (i3, i2, i1, new_direct_jump_p)
/* If *SPLIT is a paradoxical SUBREG, when we split it, it should
be written as a ZERO_EXTEND. */
if (split_code == SUBREG && GET_CODE (SUBREG_REG (*split)) == MEM)
- SUBST (*split, gen_rtx_ZERO_EXTEND (split_mode,
- SUBREG_REG (*split)));
+ {
+#ifdef LOAD_EXTEND_OP
+ /* Or as a SIGN_EXTEND if LOAD_EXTEND_OP says that that's
+ what it really is. */
+ if (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (*split)))
+ == SIGN_EXTEND)
+ SUBST (*split, gen_rtx_SIGN_EXTEND (split_mode,
+ SUBREG_REG (*split)));
+ else
+#endif
+ SUBST (*split, gen_rtx_ZERO_EXTEND (split_mode,
+ SUBREG_REG (*split)));
+ }
#endif
newi2pat = gen_rtx_SET (VOIDmode, newdest, *split);
@@ -2311,6 +2334,10 @@ try_combine (i3, i2, i1, new_direct_jump_p)
copy. This saves at least one insn, more if register allocation can
eliminate the copy.
+ We cannot do this if the destination of the first assignment is a
+ condition code register or cc0. We eliminate this case by making sure
+ the SET_DEST and SET_SRC have the same mode.
+
We cannot do this if the destination of the second assignment is
a register that we have already assumed is zero-extended. Similarly
for a SUBREG of such a register. */
@@ -2320,6 +2347,8 @@ try_combine (i3, i2, i1, new_direct_jump_p)
&& XVECLEN (newpat, 0) == 2
&& GET_CODE (XVECEXP (newpat, 0, 0)) == SET
&& GET_CODE (SET_SRC (XVECEXP (newpat, 0, 0))) == SIGN_EXTEND
+ && (GET_MODE (SET_DEST (XVECEXP (newpat, 0, 0)))
+ == GET_MODE (SET_SRC (XVECEXP (newpat, 0, 0))))
&& GET_CODE (XVECEXP (newpat, 0, 1)) == SET
&& rtx_equal_p (SET_SRC (XVECEXP (newpat, 0, 1)),
XEXP (SET_SRC (XVECEXP (newpat, 0, 0)), 0))
@@ -2386,8 +2415,8 @@ try_combine (i3, i2, i1, new_direct_jump_p)
which we know will be a NOTE. */
for (insn = NEXT_INSN (i3);
- insn && (this_basic_block == n_basic_blocks - 1
- || insn != BLOCK_HEAD (this_basic_block + 1));
+ insn && (this_basic_block->next_bb == EXIT_BLOCK_PTR
+ || insn != this_basic_block->next_bb->head);
insn = NEXT_INSN (insn))
{
if (INSN_P (insn) && reg_referenced_p (ni2dest, PATTERN (insn)))
@@ -2604,8 +2633,8 @@ try_combine (i3, i2, i1, new_direct_jump_p)
&& ! find_reg_note (i2, REG_UNUSED,
SET_DEST (XVECEXP (PATTERN (i2), 0, i))))
for (temp = NEXT_INSN (i2);
- temp && (this_basic_block == n_basic_blocks - 1
- || BLOCK_HEAD (this_basic_block) != temp);
+ temp && (this_basic_block->next_bb == EXIT_BLOCK_PTR
+ || this_basic_block->head != temp);
temp = NEXT_INSN (temp))
if (temp != i3 && INSN_P (temp))
for (link = LOG_LINKS (temp); link; link = XEXP (link, 1))
@@ -2818,7 +2847,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
BARRIER following it since it may have initially been a
conditional jump. It may also be the last nonnote insn. */
- if (GET_CODE (newpat) == RETURN || any_uncondjump_p (i3))
+ if (returnjump_p (i3) || any_uncondjump_p (i3))
{
*new_direct_jump_p = 1;
@@ -2826,6 +2855,18 @@ try_combine (i3, i2, i1, new_direct_jump_p)
|| GET_CODE (temp) != BARRIER)
emit_barrier_after (i3);
}
+
+ if (undobuf.other_insn != NULL_RTX
+ && (returnjump_p (undobuf.other_insn)
+ || any_uncondjump_p (undobuf.other_insn)))
+ {
+ *new_direct_jump_p = 1;
+
+ if ((temp = next_nonnote_insn (undobuf.other_insn)) == NULL_RTX
+ || GET_CODE (temp) != BARRIER)
+ emit_barrier_after (undobuf.other_insn);
+ }
+
/* An NOOP jump does not need barrier, but it does need cleaning up
of CFG. */
if (GET_CODE (newpat) == SET
@@ -2958,20 +2999,22 @@ find_split_point (loc, insn)
we can make put both sources together and make a split point
in the middle. */
- if (seq && XVECLEN (seq, 0) == 2
- && GET_CODE (XVECEXP (seq, 0, 0)) == INSN
- && GET_CODE (PATTERN (XVECEXP (seq, 0, 0))) == SET
- && SET_DEST (PATTERN (XVECEXP (seq, 0, 0))) == reg
+ if (seq
+ && NEXT_INSN (seq) != NULL_RTX
+ && NEXT_INSN (NEXT_INSN (seq)) == NULL_RTX
+ && GET_CODE (seq) == INSN
+ && GET_CODE (PATTERN (seq)) == SET
+ && SET_DEST (PATTERN (seq)) == reg
&& ! reg_mentioned_p (reg,
- SET_SRC (PATTERN (XVECEXP (seq, 0, 0))))
- && GET_CODE (XVECEXP (seq, 0, 1)) == INSN
- && GET_CODE (PATTERN (XVECEXP (seq, 0, 1))) == SET
- && SET_DEST (PATTERN (XVECEXP (seq, 0, 1))) == reg
+ SET_SRC (PATTERN (seq)))
+ && GET_CODE (NEXT_INSN (seq)) == INSN
+ && GET_CODE (PATTERN (NEXT_INSN (seq))) == SET
+ && SET_DEST (PATTERN (NEXT_INSN (seq))) == reg
&& memory_address_p (GET_MODE (x),
- SET_SRC (PATTERN (XVECEXP (seq, 0, 1)))))
+ SET_SRC (PATTERN (NEXT_INSN (seq)))))
{
- rtx src1 = SET_SRC (PATTERN (XVECEXP (seq, 0, 0)));
- rtx src2 = SET_SRC (PATTERN (XVECEXP (seq, 0, 1)));
+ rtx src1 = SET_SRC (PATTERN (seq));
+ rtx src2 = SET_SRC (PATTERN (NEXT_INSN (seq)));
/* Replace the placeholder in SRC2 with SRC1. If we can
find where in SRC2 it was placed, that can become our
@@ -3062,11 +3105,8 @@ find_split_point (loc, insn)
SUBST (SET_SRC (x),
gen_binary (IOR, mode,
gen_binary (AND, mode, dest,
- GEN_INT
- (
- trunc_int_for_mode
- (~(mask << pos)
- & GET_MODE_MASK (mode), mode))),
+ gen_int_mode (~(mask << pos),
+ mode)),
GEN_INT (src << pos)));
SUBST (SET_DEST (x), dest);
@@ -3085,7 +3125,7 @@ find_split_point (loc, insn)
case AND:
/* If we are AND'ing with a large constant that is only a single
bit and the result is only being used in a context where we
- need to know if it is zero or non-zero, replace it with a bit
+ need to know if it is zero or nonzero, replace it with a bit
extraction. This will avoid the large constant, which might
have taken more than one insn to make. If the constant were
not a valid argument to the AND but took only one insn to make,
@@ -3313,10 +3353,10 @@ find_split_point (loc, insn)
`n_occurrences' is incremented each time FROM is replaced.
- IN_DEST is non-zero if we are processing the SET_DEST of a SET.
+ IN_DEST is nonzero if we are processing the SET_DEST of a SET.
- UNIQUE_COPY is non-zero if each substitution must be unique. We do this
- by copying if `n_occurrences' is non-zero. */
+ UNIQUE_COPY is nonzero if each substitution must be unique. We do this
+ by copying if `n_occurrences' is nonzero. */
static rtx
subst (x, from, to, in_dest, unique_copy)
@@ -3497,15 +3537,13 @@ subst (x, from, to, in_dest, unique_copy)
)
return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
if (code == SUBREG
&& GET_CODE (to) == REG
&& REGNO (to) < FIRST_PSEUDO_REGISTER
- && (TEST_HARD_REG_BIT
- (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
- REGNO (to)))
- && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (to),
- GET_MODE (x)))
+ && REG_CANNOT_CHANGE_MODE_P (REGNO (to),
+ GET_MODE (to),
+ GET_MODE (x)))
return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
#endif
@@ -3540,7 +3578,8 @@ subst (x, from, to, in_dest, unique_copy)
if (GET_CODE (new) == CONST_INT && GET_CODE (x) == SUBREG)
{
enum machine_mode mode = GET_MODE (x);
- x = simplify_subreg (mode, new,
+
+ x = simplify_subreg (GET_MODE (x), new,
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x));
if (! x)
@@ -3772,7 +3811,8 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
if (temp == const0_rtx)
temp = CONST0_RTX (mode);
else
- temp = immed_real_const_1 (FLOAT_STORE_FLAG_VALUE (mode), mode);
+ temp = CONST_DOUBLE_FROM_REAL_VALUE (FLOAT_STORE_FLAG_VALUE (mode),
+ mode);
}
#endif
break;
@@ -3864,7 +3904,12 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
/* simplify_subreg can't use gen_lowpart_for_combine. */
if (CONSTANT_P (SUBREG_REG (x))
- && subreg_lowpart_offset (mode, op0_mode) == SUBREG_BYTE (x))
+ && subreg_lowpart_offset (mode, op0_mode) == SUBREG_BYTE (x)
+ /* Don't call gen_lowpart_for_combine if the inner mode
+ is VOIDmode and we cannot simplify it, as SUBREG without
+ inner mode is invalid. */
+ && (GET_MODE (SUBREG_REG (x)) != VOIDmode
+ || gen_lowpart_common (mode, SUBREG_REG (x))))
return gen_lowpart_for_combine (mode, SUBREG_REG (x));
if (GET_MODE_CLASS (GET_MODE (SUBREG_REG (x))) == MODE_CC)
@@ -3991,15 +4036,35 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
if (GET_CODE (XEXP (x, 0)) == NOT)
return plus_constant (XEXP (XEXP (x, 0), 0), 1);
- /* (neg (minus X Y)) can become (minus Y X). */
+ /* (neg (minus X Y)) can become (minus Y X). This transformation
+ isn't safe for modes with signed zeros, since if X and Y are
+ both +0, (minus Y X) is the same as (minus X Y). If the rounding
+ mode is towards +infinity (or -infinity) then the two expressions
+ will be rounded differently. */
if (GET_CODE (XEXP (x, 0)) == MINUS
- && (! FLOAT_MODE_P (mode)
- /* x-y != -(y-x) with IEEE floating point. */
- || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || flag_unsafe_math_optimizations))
+ && !HONOR_SIGNED_ZEROS (mode)
+ && !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
return gen_binary (MINUS, mode, XEXP (XEXP (x, 0), 1),
XEXP (XEXP (x, 0), 0));
+ /* (neg (plus A B)) is canonicalized to (minus (neg A) B). */
+ if (GET_CODE (XEXP (x, 0)) == PLUS
+ && !HONOR_SIGNED_ZEROS (mode)
+ && !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
+ {
+ temp = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 0), 0), mode);
+ temp = combine_simplify_rtx (temp, mode, last, in_dest);
+ return gen_binary (MINUS, mode, temp, XEXP (XEXP (x, 0), 1));
+ }
+
+ /* (neg (mult A B)) becomes (mult (neg A) B).
+ This works even for floating-point values. */
+ if (GET_CODE (XEXP (x, 0)) == MULT)
+ {
+ temp = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 0), 0), mode);
+ return gen_binary (MULT, mode, temp, XEXP (XEXP (x, 0), 1));
+ }
+
/* (neg (xor A 1)) is (plus A -1) if A is known to be either 0 or 1. */
if (GET_CODE (XEXP (x, 0)) == XOR && XEXP (XEXP (x, 0), 1) == const1_rtx
&& nonzero_bits (XEXP (XEXP (x, 0), 0), mode) == 1)
@@ -4102,7 +4167,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
if (TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))
&& num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
- >= GET_MODE_BITSIZE (mode) + 1
+ >= (unsigned int) (GET_MODE_BITSIZE (mode) + 1)
&& ! (GET_CODE (XEXP (x, 0)) == LSHIFTRT
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT))
return gen_lowpart_for_combine (mode, XEXP (x, 0));
@@ -4158,10 +4223,11 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
if (XEXP (x, 1) == const0_rtx)
return XEXP (x, 0);
- /* In IEEE floating point, x-0 is not the same as x. */
- if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0)))
- || flag_unsafe_math_optimizations)
+ /* x - 0 is the same as x unless x's mode has signed zeros and
+ allows rounding towards -infinity. Under those conditions,
+ 0 - 0 is -0. */
+ if (!(HONOR_SIGNED_ZEROS (GET_MODE (XEXP (x, 0)))
+ && HONOR_SIGN_DEPENDENT_ROUNDING (GET_MODE (XEXP (x, 0))))
&& XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0))))
return XEXP (x, 0);
break;
@@ -4187,6 +4253,19 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
#endif
case PLUS:
+ /* Canonicalize (plus (mult (neg B) C) A) to (minus A (mult B C)).
+ */
+ if (GET_CODE (XEXP (x, 0)) == MULT
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == NEG)
+ {
+ rtx in1, in2;
+
+ in1 = XEXP (XEXP (XEXP (x, 0), 0), 0);
+ in2 = XEXP (XEXP (x, 0), 1);
+ return gen_binary (MINUS, mode, XEXP (x, 1),
+ gen_binary (MULT, mode, in1, in2));
+ }
+
/* If we have (plus (plus (A const) B)), associate it so that CONST is
outermost. That's because that's the way indexed addresses are
supposed to appear. This code used to check many more cases, but
@@ -4293,6 +4372,32 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
return simplify_and_const_int (NULL_RTX, mode, XEXP (x, 0),
-INTVAL (XEXP (XEXP (x, 1), 1)) - 1);
+ /* Canonicalize (minus A (mult (neg B) C)) to (plus (mult B C) A).
+ */
+ if (GET_CODE (XEXP (x, 1)) == MULT
+ && GET_CODE (XEXP (XEXP (x, 1), 0)) == NEG)
+ {
+ rtx in1, in2;
+
+ in1 = XEXP (XEXP (XEXP (x, 1), 0), 0);
+ in2 = XEXP (XEXP (x, 1), 1);
+ return gen_binary (PLUS, mode, gen_binary (MULT, mode, in1, in2),
+ XEXP (x, 0));
+ }
+
+ /* Canonicalize (minus (neg A) (mult B C)) to
+ (minus (mult (neg B) C) A). */
+ if (GET_CODE (XEXP (x, 1)) == MULT
+ && GET_CODE (XEXP (x, 0)) == NEG)
+ {
+ rtx in1, in2;
+
+ in1 = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 1), 0), mode);
+ in2 = XEXP (XEXP (x, 1), 1);
+ return gen_binary (MINUS, mode, gen_binary (MULT, mode, in1, in2),
+ XEXP (XEXP (x, 0), 0));
+ }
+
/* Canonicalize (minus A (plus B C)) to (minus (minus A B) C) for
integers. */
if (GET_CODE (XEXP (x, 1)) == PLUS && INTEGRAL_MODE_P (mode))
@@ -4579,7 +4684,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
#ifdef SHIFT_COUNT_TRUNCATED
else if (SHIFT_COUNT_TRUNCATED && GET_CODE (XEXP (x, 1)) != REG)
SUBST (XEXP (x, 1),
- force_to_mode (XEXP (x, 1), GET_MODE (x),
+ force_to_mode (XEXP (x, 1), GET_MODE (XEXP (x, 1)),
((HOST_WIDE_INT) 1
<< exact_log2 (GET_MODE_BITSIZE (GET_MODE (x))))
- 1,
@@ -4761,12 +4866,12 @@ simplify_if_then_else (x)
/* Convert a == b ? b : a to "a". */
if (true_code == EQ && ! side_effects_p (cond)
- && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
+ && !HONOR_NANS (mode)
&& rtx_equal_p (XEXP (cond, 0), false_rtx)
&& rtx_equal_p (XEXP (cond, 1), true_rtx))
return false_rtx;
else if (true_code == NE && ! side_effects_p (cond)
- && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
+ && !HONOR_NANS (mode)
&& rtx_equal_p (XEXP (cond, 0), true_rtx)
&& rtx_equal_p (XEXP (cond, 1), false_rtx))
return true_rtx;
@@ -4827,7 +4932,9 @@ simplify_if_then_else (x)
neither 1 or -1, but it isn't worth checking for. */
if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
- && comparison_p && mode != VOIDmode && ! side_effects_p (x))
+ && comparison_p
+ && GET_MODE_CLASS (mode) == MODE_INT
+ && ! side_effects_p (x))
{
rtx t = make_compound_operation (true_rtx, SET);
rtx f = make_compound_operation (false_rtx, SET);
@@ -4862,7 +4969,8 @@ simplify_if_then_else (x)
&& subreg_lowpart_p (XEXP (XEXP (t, 0), 0))
&& rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 0)), f)
&& (num_sign_bit_copies (f, GET_MODE (f))
- > (GET_MODE_BITSIZE (mode)
+ > (unsigned int)
+ (GET_MODE_BITSIZE (mode)
- GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (t, 0), 0))))))
{
c1 = XEXP (XEXP (t, 0), 1); z = f; op = GET_CODE (XEXP (t, 0));
@@ -4877,7 +4985,8 @@ simplify_if_then_else (x)
&& subreg_lowpart_p (XEXP (XEXP (t, 0), 1))
&& rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 1)), f)
&& (num_sign_bit_copies (f, GET_MODE (f))
- > (GET_MODE_BITSIZE (mode)
+ > (unsigned int)
+ (GET_MODE_BITSIZE (mode)
- GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (t, 0), 1))))))
{
c1 = XEXP (XEXP (t, 0), 0); z = f; op = GET_CODE (XEXP (t, 0));
@@ -4977,7 +5086,8 @@ simplify_set (x)
simplify the expression for the object knowing that we only need the
low-order bits. */
- if (GET_MODE_CLASS (mode) == MODE_INT)
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
{
src = force_to_mode (src, mode, ~(HOST_WIDE_INT) 0, NULL_RTX, 0);
SUBST (SET_SRC (x), src);
@@ -4986,11 +5096,9 @@ simplify_set (x)
/* If we are setting CC0 or if the source is a COMPARE, look for the use of
the comparison result and try to simplify it unless we already have used
undobuf.other_insn. */
- if ((GET_CODE (src) == COMPARE
-#ifdef HAVE_cc0
- || dest == cc0_rtx
-#endif
- )
+ if ((GET_MODE_CLASS (mode) == MODE_CC
+ || GET_CODE (src) == COMPARE
+ || CC0_P (dest))
&& (cc_use = find_single_use (dest, subst_insn, &other_insn)) != 0
&& (undobuf.other_insn == 0 || other_insn == undobuf.other_insn)
&& GET_RTX_CLASS (GET_CODE (*cc_use)) == '<'
@@ -4998,15 +5106,44 @@ simplify_set (x)
{
enum rtx_code old_code = GET_CODE (*cc_use);
enum rtx_code new_code;
- rtx op0, op1;
+ rtx op0, op1, tmp;
int other_changed = 0;
enum machine_mode compare_mode = GET_MODE (dest);
+ enum machine_mode tmp_mode;
if (GET_CODE (src) == COMPARE)
op0 = XEXP (src, 0), op1 = XEXP (src, 1);
else
op0 = src, op1 = const0_rtx;
+ /* Check whether the comparison is known at compile time. */
+ if (GET_MODE (op0) != VOIDmode)
+ tmp_mode = GET_MODE (op0);
+ else if (GET_MODE (op1) != VOIDmode)
+ tmp_mode = GET_MODE (op1);
+ else
+ tmp_mode = compare_mode;
+ tmp = simplify_relational_operation (old_code, tmp_mode, op0, op1);
+ if (tmp != NULL_RTX)
+ {
+ rtx pat = PATTERN (other_insn);
+ undobuf.other_insn = other_insn;
+ SUBST (*cc_use, tmp);
+
+ /* Attempt to simplify CC user. */
+ if (GET_CODE (pat) == SET)
+ {
+ rtx new = simplify_rtx (SET_SRC (pat));
+ if (new != NULL_RTX)
+ SUBST (SET_SRC (pat), new);
+ }
+
+ /* Convert X into a no-op move. */
+ SUBST (SET_DEST (x), pc_rtx);
+ SUBST (SET_SRC (x), pc_rtx);
+ return x;
+ }
+
/* Simplify our comparison, if possible. */
new_code = simplify_comparison (old_code, &op0, &op1);
@@ -5136,13 +5273,11 @@ simplify_set (x)
&& (GET_MODE_SIZE (GET_MODE (src))
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
#endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
&& ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER
- && (TEST_HARD_REG_BIT
- (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
- REGNO (dest)))
- && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (src),
- GET_MODE (SUBREG_REG (src))))
+ && REG_CANNOT_CHANGE_MODE_P (REGNO (dest),
+ GET_MODE (SUBREG_REG (src)),
+ GET_MODE (src)))
#endif
&& (GET_CODE (dest) == REG
|| (GET_CODE (dest) == SUBREG
@@ -5156,6 +5291,30 @@ simplify_set (x)
src = SET_SRC (x), dest = SET_DEST (x);
}
+#ifdef HAVE_cc0
+ /* If we have (set (cc0) (subreg ...)), we try to remove the subreg
+ in SRC. */
+ if (dest == cc0_rtx
+ && GET_CODE (src) == SUBREG
+ && subreg_lowpart_p (src)
+ && (GET_MODE_BITSIZE (GET_MODE (src))
+ < GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (src)))))
+ {
+ rtx inner = SUBREG_REG (src);
+ enum machine_mode inner_mode = GET_MODE (inner);
+
+ /* Here we make sure that we don't have a sign bit on. */
+ if (GET_MODE_BITSIZE (inner_mode) <= HOST_BITS_PER_WIDE_INT
+ && (nonzero_bits (inner, inner_mode)
+ < ((unsigned HOST_WIDE_INT) 1
+ << (GET_MODE_BITSIZE (GET_MODE (src)) - 1))))
+ {
+ SUBST (SET_SRC (x), inner);
+ src = SET_SRC (x);
+ }
+ }
+#endif
+
#ifdef LOAD_EXTEND_OP
/* If we have (set FOO (subreg:M (mem:N BAR) 0)) with M wider than N, this
would require a paradoxical subreg. Replace the subreg with a
@@ -5594,9 +5753,15 @@ expand_compound_operation (x)
if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) > UNITS_PER_WORD)
return x;
+ /* Reject MODEs that aren't scalar integers because turning vector
+ or complex modes into shifts causes problems. */
+
+ if (! SCALAR_INT_MODE_P (GET_MODE (XEXP (x, 0))))
+ return x;
+
len = GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)));
/* If the inner object has VOIDmode (the only way this can happen
- is if it is a ASM_OPERANDS), we can't do anything since we don't
+ is if it is an ASM_OPERANDS), we can't do anything since we don't
know how much masking to do. */
if (len == 0)
return x;
@@ -5615,6 +5780,12 @@ expand_compound_operation (x)
|| GET_MODE (XEXP (x, 0)) == VOIDmode)
return x;
+ /* Reject MODEs that aren't scalar integers because turning vector
+ or complex modes into shifts causes problems. */
+
+ if (! SCALAR_INT_MODE_P (GET_MODE (XEXP (x, 0))))
+ return x;
+
len = INTVAL (XEXP (x, 1));
pos = INTVAL (XEXP (x, 2));
@@ -5822,12 +5993,12 @@ expand_field_assignment (x)
compute_mode = GET_MODE (inner);
- /* Don't attempt bitwise arithmetic on non-integral modes. */
- if (! INTEGRAL_MODE_P (compute_mode))
+ /* Don't attempt bitwise arithmetic on non scalar integer modes. */
+ if (! SCALAR_INT_MODE_P (compute_mode))
{
enum machine_mode imode;
- /* Something is probably seriously wrong if this matches. */
+ /* Don't do anything for vector or complex integral types. */
if (! FLOAT_MODE_P (compute_mode))
break;
@@ -5881,15 +6052,15 @@ expand_field_assignment (x)
code that understands the USE is this routine. If it is not removed,
it will cause the resulting insn not to match.
- UNSIGNEDP is non-zero for an unsigned reference and zero for a
+ UNSIGNEDP is nonzero for an unsigned reference and zero for a
signed reference.
- IN_DEST is non-zero if this is a reference in the destination of a
- SET. This is used when a ZERO_ or SIGN_EXTRACT isn't needed. If non-zero,
+ IN_DEST is nonzero if this is a reference in the destination of a
+ SET. This is used when a ZERO_ or SIGN_EXTRACT isn't needed. If nonzero,
a STRICT_LOW_PART will be used, if zero, ZERO_EXTEND or SIGN_EXTEND will
be used.
- IN_COMPARE is non-zero if we are in a COMPARE. This means that a
+ IN_COMPARE is nonzero if we are in a COMPARE. This means that a
ZERO_EXTRACT should be built even for bits starting at bit 0.
MODE is the desired mode of the result (if IN_DEST == 0).
@@ -5940,6 +6111,21 @@ make_extraction (mode, inner, pos, pos_rtx, len,
is_mode = GET_MODE (SUBREG_REG (inner));
inner = SUBREG_REG (inner);
}
+ else if (GET_CODE (inner) == ASHIFT
+ && GET_CODE (XEXP (inner, 1)) == CONST_INT
+ && pos_rtx == 0 && pos == 0
+ && len > (unsigned HOST_WIDE_INT) INTVAL (XEXP (inner, 1)))
+ {
+ /* We're extracting the least significant bits of an rtx
+ (ashift X (const_int C)), where LEN > C. Extract the
+ least significant (LEN - C) bits of X, giving an rtx
+ whose mode is MODE, then shift it left C times. */
+ new = make_extraction (mode, XEXP (inner, 0),
+ 0, 0, len - INTVAL (XEXP (inner, 1)),
+ unsignedp, in_dest, in_compare);
+ if (new != 0)
+ return gen_rtx_ASHIFT (mode, new, XEXP (inner, 1));
+ }
inner_mode = GET_MODE (inner);
@@ -6017,7 +6203,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
- GET_MODE_SIZE (tmode)) % UNITS_PER_WORD;
/* Avoid creating invalid subregs, for example when
- simplifying (x>>32)&255. */
+ simplifying (x>>32)&255. */
if (final_word >= GET_MODE_SIZE (inner_mode))
return NULL_RTX;
@@ -6046,7 +6232,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
return new;
if (GET_CODE (new) == CONST_INT)
- return GEN_INT (trunc_int_for_mode (INTVAL (new), mode));
+ return gen_int_mode (INTVAL (new), mode);
/* If we know that no extraneous bits are set, and that the high
bit is not set, convert the extraction to the cheaper of
@@ -6362,7 +6548,7 @@ make_compound_operation (x, in_code)
: in_code == COMPARE ? SET : in_code);
/* Process depending on the code of this operation. If NEW is set
- non-zero, it will be returned. */
+ nonzero, it will be returned. */
switch (code)
{
@@ -6567,7 +6753,11 @@ make_compound_operation (x, in_code)
if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (tem))
|| (GET_MODE_SIZE (mode) >
GET_MODE_SIZE (GET_MODE (XEXP (tem, 0)))))
- tem = gen_rtx_fmt_e (GET_CODE (tem), mode, XEXP (tem, 0));
+ {
+ if (! SCALAR_INT_MODE_P (mode))
+ break;
+ tem = gen_rtx_fmt_e (GET_CODE (tem), mode, XEXP (tem, 0));
+ }
else
tem = gen_lowpart_for_combine (mode, XEXP (tem, 0));
return tem;
@@ -6635,7 +6825,7 @@ get_pos_from_mask (m, plen)
Return a possibly simplified expression, but always convert X to
MODE. If X is a CONST_INT, AND the CONST_INT with MASK.
- Also, if REG is non-zero and X is a register equal in value to REG,
+ Also, if REG is nonzero and X is a register equal in value to REG,
replace X with REG.
If JUST_SELECT is nonzero, don't optimize by noticing that bits in MASK
@@ -6698,12 +6888,20 @@ force_to_mode (x, mode, mask, reg, just_select)
/* If none of the bits in X are needed, return a zero. */
if (! just_select && (nonzero & mask) == 0)
- return const0_rtx;
+ x = const0_rtx;
/* If X is a CONST_INT, return a new one. Do this here since the
test below will fail. */
if (GET_CODE (x) == CONST_INT)
- return gen_int_mode (INTVAL (x) & mask, mode);
+ {
+ if (SCALAR_INT_MODE_P (mode))
+ return gen_int_mode (INTVAL (x) & mask, mode);
+ else
+ {
+ x = GEN_INT (INTVAL (x) & mask);
+ return gen_lowpart_common (mode, x);
+ }
+ }
/* If X is narrower than MODE and we want all the bits in X's mode, just
get X in the proper mode. */
@@ -6776,7 +6974,7 @@ force_to_mode (x, mode, mask, reg, just_select)
if (GET_CODE (x) == AND && GET_CODE (XEXP (x, 1)) == CONST_INT
&& ((INTVAL (XEXP (x, 1)) & GET_MODE_MASK (GET_MODE (x)))
- == (HOST_WIDE_INT) mask))
+ == mask))
x = XEXP (x, 0);
/* If it remains an AND, try making another AND with the bits
@@ -7058,7 +7256,7 @@ force_to_mode (x, mode, mask, reg, just_select)
}
}
- /* If MASK is 1, convert this to a LSHIFTRT. This can be done
+ /* If MASK is 1, convert this to an LSHIFTRT. This can be done
even if the shift count isn't a constant. */
if (mask == 1)
x = gen_binary (LSHIFTRT, GET_MODE (x), XEXP (x, 0), XEXP (x, 1));
@@ -7125,7 +7323,8 @@ force_to_mode (x, mode, mask, reg, just_select)
< GET_MODE_BITSIZE (GET_MODE (x)))
&& INTVAL (XEXP (XEXP (x, 0), 1)) < HOST_BITS_PER_WIDE_INT)
{
- temp = GEN_INT (mask << INTVAL (XEXP (XEXP (x, 0), 1)));
+ temp = gen_int_mode (mask << INTVAL (XEXP (XEXP (x, 0), 1)),
+ GET_MODE (x));
temp = gen_binary (XOR, GET_MODE (x), XEXP (XEXP (x, 0), 0), temp);
x = gen_binary (LSHIFTRT, GET_MODE (x), temp, XEXP (XEXP (x, 0), 1));
@@ -7245,7 +7444,7 @@ if_then_else_cond (x, ptrue, pfalse)
}
/* See if we have PLUS, IOR, XOR, MINUS or UMAX, where one of the
- operands is zero when the other is non-zero, and vice-versa,
+ operands is zero when the other is nonzero, and vice-versa,
and STORE_FLAG_VALUE is 1 or -1. */
if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
@@ -7367,7 +7566,7 @@ if_then_else_cond (x, ptrue, pfalse)
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& exact_log2 (nz = nonzero_bits (x, mode)) >= 0)
{
- *ptrue = GEN_INT (trunc_int_for_mode (nz, mode)), *pfalse = const0_rtx;
+ *ptrue = gen_int_mode (nz, mode), *pfalse = const0_rtx;
return x;
}
@@ -7866,7 +8065,7 @@ simplify_and_const_int (x, mode, varop, constop)
return const0_rtx;
/* If VAROP is a NEG of something known to be zero or 1 and CONSTOP is
- a power of two, we can replace this with a ASHIFT. */
+ a power of two, we can replace this with an ASHIFT. */
if (GET_CODE (varop) == NEG && nonzero_bits (XEXP (varop, 0), mode) == 1
&& (i = exact_log2 (constop)) >= 0)
return simplify_shift_const (NULL_RTX, ASHIFT, mode, XEXP (varop, 0), i);
@@ -7942,23 +8141,76 @@ simplify_and_const_int (x, mode, varop, constop)
return x;
}
+#define nonzero_bits_with_known(X, MODE) \
+ cached_nonzero_bits (X, MODE, known_x, known_mode, known_ret)
+
+/* The function cached_nonzero_bits is a wrapper around nonzero_bits1.
+ It avoids exponential behavior in nonzero_bits1 when X has
+ identical subexpressions on the first or the second level. */
+
+static unsigned HOST_WIDE_INT
+cached_nonzero_bits (x, mode, known_x, known_mode, known_ret)
+ rtx x;
+ enum machine_mode mode;
+ rtx known_x;
+ enum machine_mode known_mode;
+ unsigned HOST_WIDE_INT known_ret;
+{
+ if (x == known_x && mode == known_mode)
+ return known_ret;
+
+ /* Try to find identical subexpressions. If found call
+ nonzero_bits1 on X with the subexpressions as KNOWN_X and the
+ precomputed value for the subexpression as KNOWN_RET. */
+
+ if (GET_RTX_CLASS (GET_CODE (x)) == '2'
+ || GET_RTX_CLASS (GET_CODE (x)) == 'c')
+ {
+ rtx x0 = XEXP (x, 0);
+ rtx x1 = XEXP (x, 1);
+
+ /* Check the first level. */
+ if (x0 == x1)
+ return nonzero_bits1 (x, mode, x0, mode,
+ nonzero_bits_with_known (x0, mode));
+
+ /* Check the second level. */
+ if ((GET_RTX_CLASS (GET_CODE (x0)) == '2'
+ || GET_RTX_CLASS (GET_CODE (x0)) == 'c')
+ && (x1 == XEXP (x0, 0) || x1 == XEXP (x0, 1)))
+ return nonzero_bits1 (x, mode, x1, mode,
+ nonzero_bits_with_known (x1, mode));
+
+ if ((GET_RTX_CLASS (GET_CODE (x1)) == '2'
+ || GET_RTX_CLASS (GET_CODE (x1)) == 'c')
+ && (x0 == XEXP (x1, 0) || x0 == XEXP (x1, 1)))
+ return nonzero_bits1 (x, mode, x0, mode,
+ nonzero_bits_with_known (x0, mode));
+ }
+
+ return nonzero_bits1 (x, mode, known_x, known_mode, known_ret);
+}
+
/* We let num_sign_bit_copies recur into nonzero_bits as that is useful.
We don't let nonzero_bits recur into num_sign_bit_copies, because that
is less useful. We can't allow both, because that results in exponential
run time recursion. There is a nullstone testcase that triggered
this. This macro avoids accidental uses of num_sign_bit_copies. */
-#define num_sign_bit_copies()
+#define cached_num_sign_bit_copies()
-/* Given an expression, X, compute which bits in X can be non-zero.
+/* Given an expression, X, compute which bits in X can be nonzero.
We don't care about bits outside of those defined in MODE.
For most X this is simply GET_MODE_MASK (GET_MODE (MODE)), but if X is
a shift, AND, or zero_extract, we can do better. */
static unsigned HOST_WIDE_INT
-nonzero_bits (x, mode)
+nonzero_bits1 (x, mode, known_x, known_mode, known_ret)
rtx x;
enum machine_mode mode;
+ rtx known_x;
+ enum machine_mode known_mode;
+ unsigned HOST_WIDE_INT known_ret;
{
unsigned HOST_WIDE_INT nonzero = GET_MODE_MASK (mode);
unsigned HOST_WIDE_INT inner_nz;
@@ -7996,7 +8248,7 @@ nonzero_bits (x, mode)
&& GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
&& GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (GET_MODE (x)))
{
- nonzero &= nonzero_bits (x, GET_MODE (x));
+ nonzero &= nonzero_bits_with_known (x, GET_MODE (x));
nonzero |= GET_MODE_MASK (mode) & ~GET_MODE_MASK (GET_MODE (x));
return nonzero;
}
@@ -8049,7 +8301,7 @@ nonzero_bits (x, mode)
&& (reg_last_set_label[REGNO (x)] == label_tick
|| (REGNO (x) >= FIRST_PSEUDO_REGISTER
&& REG_N_SETS (REGNO (x)) == 1
- && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start,
+ && ! REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start,
REGNO (x))))
&& INSN_CUID (reg_last_set[REGNO (x)]) < subst_low_cuid)
return reg_last_set_nonzero_bits[REGNO (x)] & nonzero;
@@ -8078,7 +8330,7 @@ nonzero_bits (x, mode)
| ((HOST_WIDE_INT) (-1)
<< GET_MODE_BITSIZE (GET_MODE (x))));
#endif
- return nonzero_bits (tem, mode) & nonzero;
+ return nonzero_bits_with_known (tem, mode) & nonzero;
}
else if (nonzero_sign_valid && reg_nonzero_bits[REGNO (x)])
{
@@ -8153,11 +8405,12 @@ nonzero_bits (x, mode)
break;
case TRUNCATE:
- nonzero &= (nonzero_bits (XEXP (x, 0), mode) & GET_MODE_MASK (mode));
+ nonzero &= (nonzero_bits_with_known (XEXP (x, 0), mode)
+ & GET_MODE_MASK (mode));
break;
case ZERO_EXTEND:
- nonzero &= nonzero_bits (XEXP (x, 0), mode);
+ nonzero &= nonzero_bits_with_known (XEXP (x, 0), mode);
if (GET_MODE (XEXP (x, 0)) != VOIDmode)
nonzero &= GET_MODE_MASK (GET_MODE (XEXP (x, 0)));
break;
@@ -8165,8 +8418,8 @@ nonzero_bits (x, mode)
case SIGN_EXTEND:
/* If the sign bit is known clear, this is the same as ZERO_EXTEND.
Otherwise, show all the bits in the outer mode but not the inner
- may be non-zero. */
- inner_nz = nonzero_bits (XEXP (x, 0), mode);
+ may be nonzero. */
+ inner_nz = nonzero_bits_with_known (XEXP (x, 0), mode);
if (GET_MODE (XEXP (x, 0)) != VOIDmode)
{
inner_nz &= GET_MODE_MASK (GET_MODE (XEXP (x, 0)));
@@ -8181,19 +8434,21 @@ nonzero_bits (x, mode)
break;
case AND:
- nonzero &= (nonzero_bits (XEXP (x, 0), mode)
- & nonzero_bits (XEXP (x, 1), mode));
+ nonzero &= (nonzero_bits_with_known (XEXP (x, 0), mode)
+ & nonzero_bits_with_known (XEXP (x, 1), mode));
break;
case XOR: case IOR:
case UMIN: case UMAX: case SMIN: case SMAX:
{
- unsigned HOST_WIDE_INT nonzero0 = nonzero_bits (XEXP (x, 0), mode);
+ unsigned HOST_WIDE_INT nonzero0 =
+ nonzero_bits_with_known (XEXP (x, 0), mode);
/* Don't call nonzero_bits for the second time if it cannot change
anything. */
if ((nonzero & nonzero0) != nonzero)
- nonzero &= (nonzero0 | nonzero_bits (XEXP (x, 1), mode));
+ nonzero &= (nonzero0
+ | nonzero_bits_with_known (XEXP (x, 1), mode));
}
break;
@@ -8203,11 +8458,13 @@ nonzero_bits (x, mode)
case MOD: case UMOD:
/* We can apply the rules of arithmetic to compute the number of
high- and low-order zero bits of these operations. We start by
- computing the width (position of the highest-order non-zero bit)
+ computing the width (position of the highest-order nonzero bit)
and the number of low-order zero bits for each value. */
{
- unsigned HOST_WIDE_INT nz0 = nonzero_bits (XEXP (x, 0), mode);
- unsigned HOST_WIDE_INT nz1 = nonzero_bits (XEXP (x, 1), mode);
+ unsigned HOST_WIDE_INT nz0 =
+ nonzero_bits_with_known (XEXP (x, 0), mode);
+ unsigned HOST_WIDE_INT nz1 =
+ nonzero_bits_with_known (XEXP (x, 1), mode);
int width0 = floor_log2 (nz0) + 1;
int width1 = floor_log2 (nz1) + 1;
int low0 = floor_log2 (nz0 & -nz0);
@@ -8289,9 +8546,9 @@ nonzero_bits (x, mode)
been zero-extended, we know that at least the high-order bits
are zero, though others might be too. */
- if (SUBREG_PROMOTED_VAR_P (x) && SUBREG_PROMOTED_UNSIGNED_P (x))
+ if (SUBREG_PROMOTED_VAR_P (x) && SUBREG_PROMOTED_UNSIGNED_P (x) > 0)
nonzero = (GET_MODE_MASK (GET_MODE (x))
- & nonzero_bits (SUBREG_REG (x), GET_MODE (x)));
+ & nonzero_bits_with_known (SUBREG_REG (x), GET_MODE (x)));
/* If the inner mode is a single word for both the host and target
machines, we can compute this from which bits of the inner
@@ -8300,17 +8557,18 @@ nonzero_bits (x, mode)
&& (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
<= HOST_BITS_PER_WIDE_INT))
{
- nonzero &= nonzero_bits (SUBREG_REG (x), mode);
+ nonzero &= nonzero_bits_with_known (SUBREG_REG (x), mode);
#if defined (WORD_REGISTER_OPERATIONS) && defined (LOAD_EXTEND_OP)
/* If this is a typical RISC machine, we only have to worry
about the way loads are extended. */
- if (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND
- ? (((nonzero
- & (((unsigned HOST_WIDE_INT) 1
- << (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) - 1))))
- != 0))
- : LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) != ZERO_EXTEND)
+ if ((LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND
+ ? (((nonzero
+ & (((unsigned HOST_WIDE_INT) 1
+ << (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) - 1))))
+ != 0))
+ : LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) != ZERO_EXTEND)
+ || GET_CODE (SUBREG_REG (x)) != MEM)
#endif
{
/* On many CISC machines, accessing an object in a wider mode
@@ -8342,7 +8600,8 @@ nonzero_bits (x, mode)
unsigned int width = GET_MODE_BITSIZE (inner_mode);
int count = INTVAL (XEXP (x, 1));
unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (inner_mode);
- unsigned HOST_WIDE_INT op_nonzero = nonzero_bits (XEXP (x, 0), mode);
+ unsigned HOST_WIDE_INT op_nonzero =
+ nonzero_bits_with_known (XEXP (x, 0), mode);
unsigned HOST_WIDE_INT inner = op_nonzero & mode_mask;
unsigned HOST_WIDE_INT outer = 0;
@@ -8377,8 +8636,8 @@ nonzero_bits (x, mode)
break;
case IF_THEN_ELSE:
- nonzero &= (nonzero_bits (XEXP (x, 1), mode)
- | nonzero_bits (XEXP (x, 2), mode));
+ nonzero &= (nonzero_bits_with_known (XEXP (x, 1), mode)
+ | nonzero_bits_with_known (XEXP (x, 2), mode));
break;
default:
@@ -8389,17 +8648,74 @@ nonzero_bits (x, mode)
}
/* See the macro definition above. */
-#undef num_sign_bit_copies
+#undef cached_num_sign_bit_copies
+#define num_sign_bit_copies_with_known(X, M) \
+ cached_num_sign_bit_copies (X, M, known_x, known_mode, known_ret)
+
+/* The function cached_num_sign_bit_copies is a wrapper around
+ num_sign_bit_copies1. It avoids exponential behavior in
+ num_sign_bit_copies1 when X has identical subexpressions on the
+ first or the second level. */
+
+static unsigned int
+cached_num_sign_bit_copies (x, mode, known_x, known_mode, known_ret)
+ rtx x;
+ enum machine_mode mode;
+ rtx known_x;
+ enum machine_mode known_mode;
+ unsigned int known_ret;
+{
+ if (x == known_x && mode == known_mode)
+ return known_ret;
+
+ /* Try to find identical subexpressions. If found call
+ num_sign_bit_copies1 on X with the subexpressions as KNOWN_X and
+ the precomputed value for the subexpression as KNOWN_RET. */
+
+ if (GET_RTX_CLASS (GET_CODE (x)) == '2'
+ || GET_RTX_CLASS (GET_CODE (x)) == 'c')
+ {
+ rtx x0 = XEXP (x, 0);
+ rtx x1 = XEXP (x, 1);
+
+ /* Check the first level. */
+ if (x0 == x1)
+ return
+ num_sign_bit_copies1 (x, mode, x0, mode,
+ num_sign_bit_copies_with_known (x0, mode));
+
+ /* Check the second level. */
+ if ((GET_RTX_CLASS (GET_CODE (x0)) == '2'
+ || GET_RTX_CLASS (GET_CODE (x0)) == 'c')
+ && (x1 == XEXP (x0, 0) || x1 == XEXP (x0, 1)))
+ return
+ num_sign_bit_copies1 (x, mode, x1, mode,
+ num_sign_bit_copies_with_known (x1, mode));
+
+ if ((GET_RTX_CLASS (GET_CODE (x1)) == '2'
+ || GET_RTX_CLASS (GET_CODE (x1)) == 'c')
+ && (x0 == XEXP (x1, 0) || x0 == XEXP (x1, 1)))
+ return
+ num_sign_bit_copies1 (x, mode, x0, mode,
+ num_sign_bit_copies_with_known (x0, mode));
+ }
+
+ return num_sign_bit_copies1 (x, mode, known_x, known_mode, known_ret);
+}
+
/* Return the number of bits at the high-order end of X that are known to
be equal to the sign bit. X will be used in mode MODE; if MODE is
VOIDmode, X will be used in its own mode. The returned value will always
be between 1 and the number of bits in MODE. */
static unsigned int
-num_sign_bit_copies (x, mode)
+num_sign_bit_copies1 (x, mode, known_x, known_mode, known_ret)
rtx x;
enum machine_mode mode;
+ rtx known_x;
+ enum machine_mode known_mode;
+ unsigned int known_ret;
{
enum rtx_code code = GET_CODE (x);
unsigned int bitwidth;
@@ -8422,7 +8738,7 @@ num_sign_bit_copies (x, mode)
/* For a smaller object, just ignore the high bits. */
if (bitwidth < GET_MODE_BITSIZE (GET_MODE (x)))
{
- num0 = num_sign_bit_copies (x, GET_MODE (x));
+ num0 = num_sign_bit_copies_with_known (x, GET_MODE (x));
return MAX (1,
num0 - (int) (GET_MODE_BITSIZE (GET_MODE (x)) - bitwidth));
}
@@ -8464,14 +8780,14 @@ num_sign_bit_copies (x, mode)
&& (reg_last_set_label[REGNO (x)] == label_tick
|| (REGNO (x) >= FIRST_PSEUDO_REGISTER
&& REG_N_SETS (REGNO (x)) == 1
- && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start,
+ && ! REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start,
REGNO (x))))
&& INSN_CUID (reg_last_set[REGNO (x)]) < subst_low_cuid)
return reg_last_set_sign_bit_copies[REGNO (x)];
tem = get_last_value (x);
if (tem != 0)
- return num_sign_bit_copies (tem, mode);
+ return num_sign_bit_copies_with_known (tem, mode);
if (nonzero_sign_valid && reg_sign_bit_copies[REGNO (x)] != 0
&& GET_MODE_BITSIZE (GET_MODE (x)) == bitwidth)
@@ -8504,7 +8820,7 @@ num_sign_bit_copies (x, mode)
if (SUBREG_PROMOTED_VAR_P (x) && ! SUBREG_PROMOTED_UNSIGNED_P (x))
{
- num0 = num_sign_bit_copies (SUBREG_REG (x), mode);
+ num0 = num_sign_bit_copies_with_known (SUBREG_REG (x), mode);
return MAX ((int) bitwidth
- (int) GET_MODE_BITSIZE (GET_MODE (x)) + 1,
num0);
@@ -8513,7 +8829,7 @@ num_sign_bit_copies (x, mode)
/* For a smaller object, just ignore the high bits. */
if (bitwidth <= GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))))
{
- num0 = num_sign_bit_copies (SUBREG_REG (x), VOIDmode);
+ num0 = num_sign_bit_copies_with_known (SUBREG_REG (x), VOIDmode);
return MAX (1, (num0
- (int) (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
- bitwidth)));
@@ -8533,8 +8849,9 @@ num_sign_bit_copies (x, mode)
if ((GET_MODE_SIZE (GET_MODE (x))
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
- && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND)
- return num_sign_bit_copies (SUBREG_REG (x), mode);
+ && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND
+ && GET_CODE (SUBREG_REG (x)) == MEM)
+ return num_sign_bit_copies_with_known (SUBREG_REG (x), mode);
#endif
#endif
break;
@@ -8546,16 +8863,16 @@ num_sign_bit_copies (x, mode)
case SIGN_EXTEND:
return (bitwidth - GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
- + num_sign_bit_copies (XEXP (x, 0), VOIDmode));
+ + num_sign_bit_copies_with_known (XEXP (x, 0), VOIDmode));
case TRUNCATE:
/* For a smaller object, just ignore the high bits. */
- num0 = num_sign_bit_copies (XEXP (x, 0), VOIDmode);
+ num0 = num_sign_bit_copies_with_known (XEXP (x, 0), VOIDmode);
return MAX (1, (num0 - (int) (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
- bitwidth)));
case NOT:
- return num_sign_bit_copies (XEXP (x, 0), mode);
+ return num_sign_bit_copies_with_known (XEXP (x, 0), mode);
case ROTATE: case ROTATERT:
/* If we are rotating left by a number of bits less than the number
@@ -8565,7 +8882,7 @@ num_sign_bit_copies (x, mode)
&& INTVAL (XEXP (x, 1)) >= 0
&& INTVAL (XEXP (x, 1)) < (int) bitwidth)
{
- num0 = num_sign_bit_copies (XEXP (x, 0), mode);
+ num0 = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
return MAX (1, num0 - (code == ROTATE ? INTVAL (XEXP (x, 1))
: (int) bitwidth - INTVAL (XEXP (x, 1))));
}
@@ -8576,7 +8893,7 @@ num_sign_bit_copies (x, mode)
is known to be positive, the number of sign bit copies is the
same as that of the input. Finally, if the input has just one bit
that might be nonzero, all the bits are copies of the sign bit. */
- num0 = num_sign_bit_copies (XEXP (x, 0), mode);
+ num0 = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
if (bitwidth > HOST_BITS_PER_WIDE_INT)
return num0 > 1 ? num0 - 1 : 1;
@@ -8594,8 +8911,8 @@ num_sign_bit_copies (x, mode)
case SMIN: case SMAX: case UMIN: case UMAX:
/* Logical operations will preserve the number of sign-bit copies.
MIN and MAX operations always return one of the operands. */
- num0 = num_sign_bit_copies (XEXP (x, 0), mode);
- num1 = num_sign_bit_copies (XEXP (x, 1), mode);
+ num0 = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
+ num1 = num_sign_bit_copies_with_known (XEXP (x, 1), mode);
return MIN (num0, num1);
case PLUS: case MINUS:
@@ -8613,8 +8930,8 @@ num_sign_bit_copies (x, mode)
: bitwidth - floor_log2 (nonzero) - 1);
}
- num0 = num_sign_bit_copies (XEXP (x, 0), mode);
- num1 = num_sign_bit_copies (XEXP (x, 1), mode);
+ num0 = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
+ num1 = num_sign_bit_copies_with_known (XEXP (x, 1), mode);
result = MAX (1, MIN (num0, num1) - 1);
#ifdef POINTERS_EXTEND_UNSIGNED
@@ -8636,8 +8953,8 @@ num_sign_bit_copies (x, mode)
to be positive, we must allow for an additional bit since negating
a negative number can remove one sign bit copy. */
- num0 = num_sign_bit_copies (XEXP (x, 0), mode);
- num1 = num_sign_bit_copies (XEXP (x, 1), mode);
+ num0 = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
+ num1 = num_sign_bit_copies_with_known (XEXP (x, 1), mode);
result = bitwidth - (bitwidth - num0) - (bitwidth - num1);
if (result > 0
@@ -8660,17 +8977,17 @@ num_sign_bit_copies (x, mode)
& ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0)
return 1;
else
- return num_sign_bit_copies (XEXP (x, 0), mode);
+ return num_sign_bit_copies_with_known (XEXP (x, 0), mode);
case UMOD:
/* The result must be <= the second operand. */
- return num_sign_bit_copies (XEXP (x, 1), mode);
+ return num_sign_bit_copies_with_known (XEXP (x, 1), mode);
case DIV:
/* Similar to unsigned division, except that we have to worry about
the case where the divisor is negative, in which case we have
to add 1. */
- result = num_sign_bit_copies (XEXP (x, 0), mode);
+ result = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
if (result > 1
&& (bitwidth > HOST_BITS_PER_WIDE_INT
|| (nonzero_bits (XEXP (x, 1), mode)
@@ -8680,7 +8997,7 @@ num_sign_bit_copies (x, mode)
return result;
case MOD:
- result = num_sign_bit_copies (XEXP (x, 1), mode);
+ result = num_sign_bit_copies_with_known (XEXP (x, 1), mode);
if (result > 1
&& (bitwidth > HOST_BITS_PER_WIDE_INT
|| (nonzero_bits (XEXP (x, 1), mode)
@@ -8692,7 +9009,7 @@ num_sign_bit_copies (x, mode)
case ASHIFTRT:
/* Shifts by a constant add to the number of bits equal to the
sign bit. */
- num0 = num_sign_bit_copies (XEXP (x, 0), mode);
+ num0 = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
if (GET_CODE (XEXP (x, 1)) == CONST_INT
&& INTVAL (XEXP (x, 1)) > 0)
num0 = MIN ((int) bitwidth, num0 + INTVAL (XEXP (x, 1)));
@@ -8706,12 +9023,12 @@ num_sign_bit_copies (x, mode)
|| INTVAL (XEXP (x, 1)) >= (int) bitwidth)
return 1;
- num0 = num_sign_bit_copies (XEXP (x, 0), mode);
+ num0 = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
return MAX (1, num0 - INTVAL (XEXP (x, 1)));
case IF_THEN_ELSE:
- num0 = num_sign_bit_copies (XEXP (x, 1), mode);
- num1 = num_sign_bit_copies (XEXP (x, 2), mode);
+ num0 = num_sign_bit_copies_with_known (XEXP (x, 1), mode);
+ num1 = num_sign_bit_copies_with_known (XEXP (x, 2), mode);
return MIN (num0, num1);
case EQ: case NE: case GE: case GT: case LE: case LT:
@@ -8767,8 +9084,8 @@ extended_count (x, mode, unsignedp)
return (unsignedp
? (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
- ? (GET_MODE_BITSIZE (mode) - 1
- - floor_log2 (nonzero_bits (x, mode)))
+ ? (unsigned int) (GET_MODE_BITSIZE (mode) - 1
+ - floor_log2 (nonzero_bits (x, mode)))
: 0)
: num_sign_bit_copies (x, mode) - 1);
}
@@ -8911,7 +9228,7 @@ merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p)
}
/* Simplify a shift of VAROP by COUNT bits. CODE says what kind of shift.
- The result of the shift is RESULT_MODE. X, if non-zero, is an expression
+ The result of the shift is RESULT_MODE. X, if nonzero, is an expression
that we started with.
The shift is normally computed in the widest mode we find in VAROP, as
@@ -8978,7 +9295,14 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
/* Convert ROTATERT to ROTATE. */
if (code == ROTATERT)
- code = ROTATE, count = GET_MODE_BITSIZE (result_mode) - count;
+ {
+ unsigned int bitsize = GET_MODE_BITSIZE (result_mode);;
+ code = ROTATE;
+ if (VECTOR_MODE_P (result_mode))
+ count = bitsize / GET_MODE_NUNITS (result_mode) - count;
+ else
+ count = bitsize - count;
+ }
/* We need to determine what mode we will do the shift in. If the
shift is a right shift or a ROTATE, we must always do it in the mode
@@ -8998,7 +9322,7 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
multiple operations, each of which are defined, we know what the
result is supposed to be. */
- if (count > GET_MODE_BITSIZE (shift_mode) - 1)
+ if (count > (unsigned int) (GET_MODE_BITSIZE (shift_mode) - 1))
{
if (code == ASHIFTRT)
count = GET_MODE_BITSIZE (shift_mode) - 1;
@@ -9036,8 +9360,8 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
/* We simplify the tests below and elsewhere by converting
ASHIFTRT to LSHIFTRT if we know the sign bit is clear.
- `make_compound_operation' will convert it to a ASHIFTRT for
- those machines (such as VAX) that don't have a LSHIFTRT. */
+ `make_compound_operation' will convert it to an ASHIFTRT for
+ those machines (such as VAX) that don't have an LSHIFTRT. */
if (GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
&& code == ASHIFTRT
&& ((nonzero_bits (varop, shift_mode)
@@ -9114,9 +9438,9 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
if (subreg_lowpart_p (varop)
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (varop)))
> GET_MODE_SIZE (GET_MODE (varop)))
- && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (varop)))
- + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
- == mode_words))
+ && (unsigned int) ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (varop)))
+ + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
+ == mode_words)
{
varop = SUBREG_REG (varop);
if (GET_MODE_SIZE (GET_MODE (varop)) > GET_MODE_SIZE (mode))
@@ -9157,7 +9481,8 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
bit of a wider mode may be different from what would be
interpreted as the sign bit in a narrower mode, so, if
the result is narrower, don't discard the shift. */
- if (code == LSHIFTRT && count == GET_MODE_BITSIZE (result_mode) - 1
+ if (code == LSHIFTRT
+ && count == (unsigned int) (GET_MODE_BITSIZE (result_mode) - 1)
&& (GET_MODE_BITSIZE (result_mode)
>= GET_MODE_BITSIZE (GET_MODE (varop))))
{
@@ -9191,8 +9516,9 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
(ashiftrt:M1 (ashift:M1 (and:M1 (subreg:M1 FOO 0 C2) C3) C1).
This simplifies certain SIGN_EXTEND operations. */
if (code == ASHIFT && first_code == ASHIFTRT
- && (GET_MODE_BITSIZE (result_mode)
- - GET_MODE_BITSIZE (GET_MODE (varop))) == count)
+ && count == (unsigned int)
+ (GET_MODE_BITSIZE (result_mode)
+ - GET_MODE_BITSIZE (GET_MODE (varop))))
{
/* C3 has the low-order C1 bits zero. */
@@ -9210,7 +9536,7 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
/* If this was (ashiftrt (ashift foo C1) C2) and FOO has more
than C1 high-order bits equal to the sign bit, we can convert
- this to either an ASHIFT or a ASHIFTRT depending on the
+ this to either an ASHIFT or an ASHIFTRT depending on the
two counts.
We cannot do this if VAROP's mode is not SHIFT_MODE. */
@@ -9348,7 +9674,8 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
&& XEXP (XEXP (varop, 0), 1) == constm1_rtx
&& (STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
&& (code == LSHIFTRT || code == ASHIFTRT)
- && count == GET_MODE_BITSIZE (GET_MODE (varop)) - 1
+ && count == (unsigned int)
+ (GET_MODE_BITSIZE (GET_MODE (varop)) - 1)
&& rtx_equal_p (XEXP (XEXP (varop, 0), 0), XEXP (varop, 1)))
{
count = 0;
@@ -9403,7 +9730,7 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
if (code == LSHIFTRT
&& XEXP (varop, 1) == const0_rtx
&& GET_MODE (XEXP (varop, 0)) == result_mode
- && count == GET_MODE_BITSIZE (result_mode) - 1
+ && count == (unsigned int) (GET_MODE_BITSIZE (result_mode) - 1)
&& GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_WIDE_INT
&& ((STORE_FLAG_VALUE
& ((HOST_WIDE_INT) 1
@@ -9422,7 +9749,8 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
case NEG:
/* (lshiftrt (neg A) C) where A is either 0 or 1 and C is one less
than the number of bits in the mode is equivalent to A. */
- if (code == LSHIFTRT && count == GET_MODE_BITSIZE (result_mode) - 1
+ if (code == LSHIFTRT
+ && count == (unsigned int) (GET_MODE_BITSIZE (result_mode) - 1)
&& nonzero_bits (XEXP (varop, 0), result_mode) == 1)
{
varop = XEXP (varop, 0);
@@ -9446,7 +9774,8 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
/* (lshiftrt (plus A -1) C) where A is either 0 or 1 and C
is one less than the number of bits in the mode is
equivalent to (xor A 1). */
- if (code == LSHIFTRT && count == GET_MODE_BITSIZE (result_mode) - 1
+ if (code == LSHIFTRT
+ && count == (unsigned int) (GET_MODE_BITSIZE (result_mode) - 1)
&& XEXP (varop, 1) == constm1_rtx
&& nonzero_bits (XEXP (varop, 0), result_mode) == 1
&& merge_outer_ops (&outer_op, &outer_const, XOR,
@@ -9511,10 +9840,12 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
&& GET_CODE (XEXP (varop, 0)) == ASHIFTRT
- && count == GET_MODE_BITSIZE (GET_MODE (varop)) - 1
+ && count == (unsigned int)
+ (GET_MODE_BITSIZE (GET_MODE (varop)) - 1)
&& (code == LSHIFTRT || code == ASHIFTRT)
&& GET_CODE (XEXP (XEXP (varop, 0), 1)) == CONST_INT
- && INTVAL (XEXP (XEXP (varop, 0), 1)) == count
+ && (unsigned HOST_WIDE_INT) INTVAL (XEXP (XEXP (varop, 0), 1))
+ == count
&& rtx_equal_p (XEXP (XEXP (varop, 0), 0), XEXP (varop, 1)))
{
count = 0;
@@ -9578,7 +9909,7 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
if (x && GET_RTX_CLASS (GET_CODE (x)) == '2'
&& GET_CODE (XEXP (x, 1)) == CONST_INT
- && INTVAL (XEXP (x, 1)) == count)
+ && (unsigned HOST_WIDE_INT) INTVAL (XEXP (x, 1)) == count)
const_rtx = XEXP (x, 1);
else
const_rtx = GEN_INT (count);
@@ -9610,7 +9941,7 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
x = simplify_shift_const (x, code, shift_mode, XEXP (x, 0),
INTVAL (XEXP (x, 1)));
- /* If we were doing a LSHIFTRT in a wider mode than it was originally,
+ /* If we were doing an LSHIFTRT in a wider mode than it was originally,
turn off all the bits that the shift would have turned off. */
if (orig_code == LSHIFTRT && result_mode != shift_mode)
x = simplify_and_const_int (NULL_RTX, shift_mode, x,
@@ -9796,14 +10127,14 @@ gen_lowpart_for_combine (mode, x)
}
result = gen_lowpart_common (mode, x);
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
if (result != 0
&& GET_CODE (result) == SUBREG
&& GET_CODE (SUBREG_REG (result)) == REG
- && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER
- && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (result),
- GET_MODE (SUBREG_REG (result))))
- REG_CHANGES_MODE (REGNO (SUBREG_REG (result))) = 1;
+ && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER)
+ bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (result))
+ * MAX_MACHINE_MODE
+ + GET_MODE (result));
#endif
if (result)
@@ -9851,15 +10182,15 @@ gen_lowpart_for_combine (mode, x)
{
int offset = 0;
rtx res;
+ enum machine_mode sub_mode = GET_MODE (x);
- /* We can't handle VOIDmodes. We can get here when generating vector
- modes since these, unlike integral and floating point modes are not
- handled earlier. */
- if (GET_MODE (x) == VOIDmode)
- return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
-
- offset = subreg_lowpart_offset (mode, GET_MODE (x));
- res = simplify_gen_subreg (mode, x, GET_MODE (x), offset);
+ offset = subreg_lowpart_offset (mode, sub_mode);
+ if (sub_mode == VOIDmode)
+ {
+ sub_mode = int_mode_for_mode (mode);
+ x = gen_lowpart_common (sub_mode, x);
+ }
+ res = simplify_gen_subreg (mode, x, sub_mode, offset);
if (res)
return res;
return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
@@ -10118,7 +10449,9 @@ simplify_comparison (code, pop0, pop1)
/* Get the constant we are comparing against and turn off all bits
not on in our mode. */
- const_op = trunc_int_for_mode (INTVAL (op1), mode);
+ const_op = INTVAL (op1);
+ if (mode != VOIDmode)
+ const_op = trunc_int_for_mode (const_op, mode);
op1 = GEN_INT (const_op);
/* If we are comparing against a constant power of two and the value
@@ -10490,7 +10823,8 @@ simplify_comparison (code, pop0, pop1)
& ~GET_MODE_MASK (mode))
|| (num_sign_bit_copies (XEXP (SUBREG_REG (op0), 0),
GET_MODE (SUBREG_REG (op0)))
- > (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
+ > (unsigned int)
+ (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
- GET_MODE_BITSIZE (mode)))))
{
op0 = SUBREG_REG (op0);
@@ -10574,7 +10908,8 @@ simplify_comparison (code, pop0, pop1)
of bits in X minus 1, is one iff X > 0. */
if (sign_bit_comparison_p && GET_CODE (XEXP (op0, 0)) == ASHIFTRT
&& GET_CODE (XEXP (XEXP (op0, 0), 1)) == CONST_INT
- && INTVAL (XEXP (XEXP (op0, 0), 1)) == mode_width - 1
+ && (unsigned HOST_WIDE_INT) INTVAL (XEXP (XEXP (op0, 0), 1))
+ == mode_width - 1
&& rtx_equal_p (XEXP (XEXP (op0, 0), 0), XEXP (op0, 1)))
{
op0 = XEXP (op0, 1);
@@ -10643,7 +10978,7 @@ simplify_comparison (code, pop0, pop1)
break;
case IOR:
- /* The sign bit of (ior (plus X (const_int -1)) X) is non-zero
+ /* The sign bit of (ior (plus X (const_int -1)) X) is nonzero
iff X <= 0. */
if (sign_bit_comparison_p && GET_CODE (XEXP (op0, 0)) == PLUS
&& XEXP (XEXP (op0, 0), 1) == constm1_rtx
@@ -10729,6 +11064,9 @@ simplify_comparison (code, pop0, pop1)
represents the low part, permute the SUBREG and the AND and
try again. */
if (GET_CODE (XEXP (op0, 0)) == SUBREG
+ /* Require an integral mode, to avoid creating something like
+ (AND:SF ...). */
+ && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
&& (0
#ifdef WORD_REGISTER_OPERATIONS
|| ((mode_width
@@ -10809,7 +11147,7 @@ simplify_comparison (code, pop0, pop1)
unsigned HOST_WIDE_INT temp = const_op & GET_MODE_MASK (mode);
temp >>= INTVAL (XEXP (op0, 1));
- op1 = GEN_INT (trunc_int_for_mode (temp, mode));
+ op1 = gen_int_mode (temp, mode);
op0 = XEXP (op0, 0);
continue;
}
@@ -10832,7 +11170,8 @@ simplify_comparison (code, pop0, pop1)
low-order bit. */
if (const_op == 0 && equality_comparison_p
&& GET_CODE (XEXP (op0, 1)) == CONST_INT
- && INTVAL (XEXP (op0, 1)) == mode_width - 1)
+ && (unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1))
+ == mode_width - 1)
{
op0 = simplify_and_const_int (NULL_RTX, mode, XEXP (op0, 0),
(HOST_WIDE_INT) 1);
@@ -10929,7 +11268,8 @@ simplify_comparison (code, pop0, pop1)
if (const_op == 0
&& (equality_comparison_p || sign_bit_comparison_p)
&& GET_CODE (XEXP (op0, 1)) == CONST_INT
- && INTVAL (XEXP (op0, 1)) == mode_width - 1)
+ && (unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1))
+ == mode_width - 1)
{
op0 = XEXP (op0, 0);
code = (code == NE || code == GT ? LT : GE);
@@ -11030,9 +11370,11 @@ simplify_comparison (code, pop0, pop1)
if (zero_extended
|| ((num_sign_bit_copies (op0, tmode)
- > GET_MODE_BITSIZE (tmode) - GET_MODE_BITSIZE (mode))
+ > (unsigned int) (GET_MODE_BITSIZE (tmode)
+ - GET_MODE_BITSIZE (mode)))
&& (num_sign_bit_copies (op1, tmode)
- > GET_MODE_BITSIZE (tmode) - GET_MODE_BITSIZE (mode))))
+ > (unsigned int) (GET_MODE_BITSIZE (tmode)
+ - GET_MODE_BITSIZE (mode)))))
{
/* If OP0 is an AND and we don't have an AND in MODE either,
make a new AND in the proper mode. */
@@ -11142,7 +11484,45 @@ update_table_tick (x)
/* Note that we can't have an "E" in values stored; see
get_last_value_validate. */
if (fmt[i] == 'e')
- update_table_tick (XEXP (x, i));
+ {
+ /* Check for identical subexpressions. If x contains
+ identical subexpression we only have to traverse one of
+ them. */
+ if (i == 0
+ && (GET_RTX_CLASS (code) == '2'
+ || GET_RTX_CLASS (code) == 'c'))
+ {
+ /* Note that at this point x1 has already been
+ processed. */
+ rtx x0 = XEXP (x, 0);
+ rtx x1 = XEXP (x, 1);
+
+ /* If x0 and x1 are identical then there is no need to
+ process x0. */
+ if (x0 == x1)
+ break;
+
+ /* If x0 is identical to a subexpression of x1 then while
+ processing x1, x0 has already been processed. Thus we
+ are done with x. */
+ if ((GET_RTX_CLASS (GET_CODE (x1)) == '2'
+ || GET_RTX_CLASS (GET_CODE (x1)) == 'c')
+ && (x0 == XEXP (x1, 0) || x0 == XEXP (x1, 1)))
+ break;
+
+ /* If x1 is identical to a subexpression of x0 then we
+ still have to process the rest of x0. */
+ if ((GET_RTX_CLASS (GET_CODE (x0)) == '2'
+ || GET_RTX_CLASS (GET_CODE (x0)) == 'c')
+ && (x1 == XEXP (x0, 0) || x1 == XEXP (x0, 1)))
+ {
+ update_table_tick (XEXP (x0, x1 == XEXP (x0, 0) ? 1 : 0));
+ break;
+ }
+ }
+
+ update_table_tick (XEXP (x, i));
+ }
}
/* Record that REG is set to VALUE in insn INSN. If VALUE is zero, we
@@ -11390,7 +11770,7 @@ record_promoted_value (insn, subreg)
if (reg_last_set[regno] == insn)
{
- if (SUBREG_PROMOTED_UNSIGNED_P (subreg))
+ if (SUBREG_PROMOTED_UNSIGNED_P (subreg) > 0)
reg_last_set_nonzero_bits[regno] &= GET_MODE_MASK (mode);
}
@@ -11440,7 +11820,7 @@ check_promoted_subreg (insn, x)
mentioned in *LOC are valid when *LOC was part of a value set when
label_tick == TICK. Return 0 if some are not.
- If REPLACE is non-zero, replace the invalid reference with
+ If REPLACE is nonzero, replace the invalid reference with
(clobber (const_int 0)) and return 1. This replacement is useful because
we often can get useful information about the form of a value (e.g., if
it was produced by a shift that always produces -1 or 0) even though
@@ -11473,7 +11853,7 @@ get_last_value_validate (loc, insn, tick, replace)
|| (! (regno >= FIRST_PSEUDO_REGISTER
&& REG_N_SETS (regno) == 1
&& (! REGNO_REG_SET_P
- (BASIC_BLOCK (0)->global_live_at_start, regno)))
+ (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno)))
&& reg_last_set_label[j] > tick))
{
if (replace)
@@ -11495,11 +11875,52 @@ get_last_value_validate (loc, insn, tick, replace)
}
for (i = 0; i < len; i++)
- if ((fmt[i] == 'e'
- && get_last_value_validate (&XEXP (x, i), insn, tick, replace) == 0)
- /* Don't bother with these. They shouldn't occur anyway. */
- || fmt[i] == 'E')
- return 0;
+ {
+ if (fmt[i] == 'e')
+ {
+ /* Check for identical subexpressions. If x contains
+ identical subexpression we only have to traverse one of
+ them. */
+ if (i == 1
+ && (GET_RTX_CLASS (GET_CODE (x)) == '2'
+ || GET_RTX_CLASS (GET_CODE (x)) == 'c'))
+ {
+ /* Note that at this point x0 has already been checked
+ and found valid. */
+ rtx x0 = XEXP (x, 0);
+ rtx x1 = XEXP (x, 1);
+
+ /* If x0 and x1 are identical then x is also valid. */
+ if (x0 == x1)
+ return 1;
+
+ /* If x1 is identical to a subexpression of x0 then
+ while checking x0, x1 has already been checked. Thus
+ it is valid and so as x. */
+ if ((GET_RTX_CLASS (GET_CODE (x0)) == '2'
+ || GET_RTX_CLASS (GET_CODE (x0)) == 'c')
+ && (x1 == XEXP (x0, 0) || x1 == XEXP (x0, 1)))
+ return 1;
+
+ /* If x0 is identical to a subexpression of x1 then x is
+ valid iff the rest of x1 is valid. */
+ if ((GET_RTX_CLASS (GET_CODE (x1)) == '2'
+ || GET_RTX_CLASS (GET_CODE (x1)) == 'c')
+ && (x0 == XEXP (x1, 0) || x0 == XEXP (x1, 1)))
+ return
+ get_last_value_validate (&XEXP (x1,
+ x0 == XEXP (x1, 0) ? 1 : 0),
+ insn, tick, replace);
+ }
+
+ if (get_last_value_validate (&XEXP (x, i), insn, tick,
+ replace) == 0)
+ return 0;
+ }
+ /* Don't bother with these. They shouldn't occur anyway. */
+ else if (fmt[i] == 'E')
+ return 0;
+ }
/* If we haven't found a reason for it to be invalid, it is valid. */
return 1;
@@ -11547,7 +11968,7 @@ get_last_value (x)
&& (regno < FIRST_PSEUDO_REGISTER
|| REG_N_SETS (regno) != 1
|| (REGNO_REG_SET_P
- (BASIC_BLOCK (0)->global_live_at_start, regno)))))
+ (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno)))))
return 0;
/* If the value was set in a later insn than the ones we are processing,
@@ -11653,7 +12074,7 @@ reg_dead_at_p_1 (dest, x, data)
reg_dead_flag = (GET_CODE (x) == CLOBBER) ? 1 : -1;
}
-/* Return non-zero if REG is known to be dead at INSN.
+/* Return nonzero if REG is known to be dead at INSN.
We scan backwards from INSN. If we hit a REG_DEAD note or a CLOBBER
referencing REG, it is dead. If we hit a SET referencing REG, it is
@@ -11666,7 +12087,7 @@ reg_dead_at_p (reg, insn)
rtx reg;
rtx insn;
{
- int block;
+ basic_block block;
unsigned int i;
/* Set variables for reg_dead_at_p_1. */
@@ -11699,21 +12120,21 @@ reg_dead_at_p (reg, insn)
return 1;
}
- /* Get the basic block number that we were in. */
+ /* Get the basic block that we were in. */
if (insn == 0)
- block = 0;
+ block = ENTRY_BLOCK_PTR->next_bb;
else
{
- for (block = 0; block < n_basic_blocks; block++)
- if (insn == BLOCK_HEAD (block))
+ FOR_EACH_BB (block)
+ if (insn == block->head)
break;
- if (block == n_basic_blocks)
+ if (block == EXIT_BLOCK_PTR)
return 0;
}
for (i = reg_dead_regno; i < reg_dead_endregno; i++)
- if (REGNO_REG_SET_P (BASIC_BLOCK (block)->global_live_at_start, i))
+ if (REGNO_REG_SET_P (block->global_live_at_start, i))
return 0;
return 1;
@@ -11764,7 +12185,7 @@ mark_used_regs_combine (x)
{
unsigned int endregno, r;
- /* None of this applies to the stack, frame or arg pointers */
+ /* None of this applies to the stack, frame or arg pointers. */
if (regno == STACK_POINTER_REGNUM
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
|| regno == HARD_FRAME_POINTER_REGNUM
@@ -11872,7 +12293,7 @@ move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
rtx where_dead = reg_last_death[regno];
rtx before_dead, after_dead;
- /* Don't move the register if it gets killed in between from and to */
+ /* Don't move the register if it gets killed in between from and to. */
if (maybe_kill_insn && reg_set_p (x, maybe_kill_insn)
&& ! reg_referenced_p (x, maybe_kill_insn))
return;
@@ -11920,7 +12341,7 @@ move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
if (i < regno || i >= ourend)
REG_NOTES (where_dead)
= gen_rtx_EXPR_LIST (REG_DEAD,
- gen_rtx_REG (reg_raw_mode[i], i),
+ regno_reg_rtx[i],
REG_NOTES (where_dead));
}
@@ -11947,7 +12368,7 @@ move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
offset = 1;
for (i = regno + offset; i < ourend; i++)
- move_deaths (gen_rtx_REG (reg_raw_mode[i], i),
+ move_deaths (regno_reg_rtx[i],
maybe_kill_insn, from_cuid, to_insn, &oldnotes);
}
@@ -12107,7 +12528,6 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
{
case REG_BR_PROB:
case REG_BR_PRED:
- case REG_EXEC_COUNT:
/* Doesn't matter much where we put this, as long as it's somewhere.
It is preferable to keep these notes on branches, which is most
likely to be i3. */
@@ -12327,7 +12747,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
case REG_DEAD:
/* If the register is used as an input in I3, it dies there.
- Similarly for I2, if it is non-zero and adjacent to I3.
+ Similarly for I2, if it is nonzero and adjacent to I3.
If the register is not used as an input in either I3 or I2
and it is not one of the registers we were supposed to eliminate,
@@ -12356,7 +12776,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
if (place == 0)
{
- basic_block bb = BASIC_BLOCK (this_basic_block);
+ basic_block bb = this_basic_block;
for (tem = PREV_INSN (i3); place == 0; tem = PREV_INSN (tem))
{
@@ -12500,7 +12920,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
&& REGNO_REG_SET_P (bb->global_live_at_start,
REGNO (XEXP (note, 0))))
{
- SET_BIT (refresh_blocks, this_basic_block);
+ SET_BIT (refresh_blocks, this_basic_block->index);
need_refresh = 1;
}
}
@@ -12520,7 +12940,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
after we remove them in delete_noop_moves. */
if (noop_move_p (place))
{
- SET_BIT (refresh_blocks, this_basic_block);
+ SET_BIT (refresh_blocks, this_basic_block->index);
need_refresh = 1;
}
@@ -12569,8 +12989,8 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
for (i = regno; i < endregno;
i += HARD_REGNO_NREGS (i, reg_raw_mode[i]))
{
- rtx piece = gen_rtx_REG (reg_raw_mode[i], i);
- basic_block bb = BASIC_BLOCK (this_basic_block);
+ rtx piece = regno_reg_rtx[i];
+ basic_block bb = this_basic_block;
if (! dead_or_set_p (place, piece)
&& ! reg_bitfield_target_p (piece,
@@ -12593,7 +13013,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
if (tem == bb->head)
{
SET_BIT (refresh_blocks,
- this_basic_block);
+ this_basic_block->index);
need_refresh = 1;
break;
}
@@ -12698,8 +13118,8 @@ distribute_links (links)
since most links don't point very far away. */
for (insn = NEXT_INSN (XEXP (link, 0));
- (insn && (this_basic_block == n_basic_blocks - 1
- || BLOCK_HEAD (this_basic_block + 1) != insn));
+ (insn && (this_basic_block->next_bb == EXIT_BLOCK_PTR
+ || this_basic_block->next_bb->head != insn));
insn = NEXT_INSN (insn))
if (INSN_P (insn) && reg_overlap_mentioned_p (reg, PATTERN (insn)))
{
diff --git a/contrib/gcc/config.gcc b/contrib/gcc/config.gcc
index bb71f51..6493ccf 100644
--- a/contrib/gcc/config.gcc
+++ b/contrib/gcc/config.gcc
@@ -45,6 +45,8 @@
#
# cpu_type The name of the cpu, if different from machine.
#
+# tm_defines List of target macros to define for all compilations.
+#
# tm_file A list of target macro files, if different from
# "$cpu_type/$cpu_type.h". Usually it's constructed
# per target in a way like this:
@@ -69,11 +71,9 @@
# makefile-fragments, if different from
# "$cpu_type/t-$cpu_type".
#
-# float_format Set to the symbolic name for the floating-point
-# formats used for this machine, if different from
-# "i64". Used to derive a header file name to
-# include, like "vax" for "float-vax.h". If no such
-# file is wanted, set to "none".
+# extra_modes The name of the file containing a list of extra
+# machine modes, if necessary and different from
+# "$cpu_type/$cpu_type-modes.def".
#
# extra_objs List of extra objects that should be linked into
# the compiler proper (cc1, cc1obj, cc1plus)
@@ -104,6 +104,8 @@
# cxx_target_objs List of extra target-dependent objects that be
# linked into the C++ compiler only.
#
+# target_gtfiles List of extra source files with type information.
+#
# build_xm_defines List of macros to define when compiling for the
# build machine.
#
@@ -184,8 +186,8 @@ extra_host_objs=
extra_gcc_objs=
c_target_objs=
cxx_target_objs=
+tm_defines=
xm_defines=
-float_format=
# Set this to force installation and use of collect2.
use_collect2=
# Set this to override the default target model.
@@ -206,71 +208,67 @@ thread_file=
gas="$gas_flag"
gnu_ld="$gnu_ld_flag"
enable_threads=$enable_threads_flag
+target_gtfiles=
# Obsolete configurations.
-# To avoid some tedious lists, we have a blacklist with a whitelist
-# embedded within it.
case $machine in
- 1750a-* \
- | a29k-* \
- | alpha*-*-osf[123]* \
- | arm-*-riscix* \
- | c*-convex-* \
- | clipper-* \
- | elxsi-* \
- | i860-* \
- | i?86-*-aix* \
- | i?86-*-bsd* \
- | i?86-*-chorusos* \
- | i?86-*-dgux* \
- | i?86-*-freebsd1.* \
- | i?86-*-isc* \
- | i?86-*-linux*oldld* \
- | i?86-*-osf1* \
- | i?86-*-osfrose* \
- | i?86-*-rtemscoff* \
- | i?86-*-sunos* \
- | i?86-go32-rtems* \
- | i?86-next-* \
- | i?86-sequent-bsd* \
- | i?86-sequent-ptx[12]* \
- | i?86-sequent-sysv3* \
- | m68[k0]*-*-lynxos* \
- | m68[k0]*-*-rtemscoff* \
- | m68[k0]*-*-sysv3* \
- | m68[k0]*-altos-* \
- | m68[k0]*-apollo-* \
- | m68[k0]*-apple-* \
- | m68[k0]*-bull-* \
- | m68[k0]*-convergent-* \
- | m68[k0]*-isi-* \
- | m68[k0]*-next-* \
- | m68[k0]*-sony-* \
- | m88k-* \
- | mips-*-bsd* \
- | mips-*-riscos* \
- | mips-*-sysv* \
- | mips-*-ultrix* \
- | mips-dec-* \
- | mips-sgi-irix[1234]* \
- | mips-sony-* \
- | mips-tandem-* \
- | ns32k-* \
- | pj-* \
- | pjl-* \
- | romp-* \
- | sparc-*-rtemsaout* \
- | we32k-* \
-)
- case $machine in
- mips-sni-sysv4 \
- | m88k-*-aout* | m88k-*-openbsd* | m88k-*-sysv4* \
- | ns32k-*-netbsd* | ns32k-*-openbsd* \
- | romp-*-openbsd* \
- )
- # Whitelisted.
- ;;
- *)
+ m88k-*-* \
+ | mn10200-*-* \
+ | romp-*-* \
+ | alpha*-*-interix* \
+ | alpha*-*-linux*libc1* \
+ | alpha*-*-linux*ecoff* \
+ | arm*-*-aout* \
+ | arm*-*-conix* \
+ | arm*-*-oabi \
+ | strongarm-*-coff* \
+ | hppa1.0-*-osf* \
+ | hppa1.0-*-bsd* \
+ | hppa1.[01]-*-hpux[789]* \
+ | hppa*-*-hiux* \
+ | hppa*-*-lites* \
+ | i?86-*-win32 \
+ | m68000-hp-bsd* \
+ | m68000-sun-sunos* \
+ | m68000-att-sysv* \
+ | m68k-atari-sysv* \
+ | m68k-motorola-sysv* \
+ | m68k-ncr-sysv* \
+ | m68k-plexus-sysv* \
+ | m68k-tti-* \
+ | m68k-crds-unos* \
+ | m68k-cbm-sysv* \
+ | m68k-ccur-rtu* \
+ | m68k-hp-bsd* \
+ | m68k-sun-mach* \
+ | m68k-sun-sunos* \
+ | m68k-*-linux*aout* \
+ | m68k-*-linux*libc1* \
+ | m68k-*-psos* \
+ | mips*-*-ecoff* \
+ | mips-sni-sysv4 \
+ | mips64orion-*-rtems* \
+ | ns32k-*-openbsd* \
+ | powerpc*-*-sysv* \
+ | powerpc*-*-linux*libc1* \
+ | rs6000-ibm-aix[123]* \
+ | rs6000-bull-bosx \
+ | rs6000-*-mach* \
+ | sparc-*-aout* \
+ | sparc-*-netbsd*aout* \
+ | sparc-*-bsd* \
+ | sparc-*-chorusos* \
+ | sparc-*-linux*aout* \
+ | sparc-*-linux*libc1* \
+ | sparc-*-lynxos* \
+ | sparc-hal-solaris2* \
+ | sparc-*-sunos[34]* \
+ | sparclet-*-aout* \
+ | sparclite-*-aout* \
+ | sparc86x-*-aout* \
+ | v850-*-rtems* \
+ | vax-*-vms* \
+ )
if test "x$enable_obsolete" != xyes; then
echo "*** Configuration $machine is obsolete." >&2
echo "*** Specify --enable-obsolete to build it anyway." >&2
@@ -278,7 +276,6 @@ case $machine in
echo "*** unless a maintainer comes forward." >&2
exit 1
fi;;
- esac
esac
# Set default cpu_type, tm_file, tm_p_file and xm_file so it can be
@@ -299,10 +296,6 @@ arm*-*-*)
xscale-*-*)
cpu_type=arm
;;
-c*-convex-*)
- cpu_type=convex
- extra_headers=proto.h
- ;;
i[34567]86-*-*)
cpu_type=i386
extra_headers="mmintrin.h xmmintrin.h"
@@ -327,19 +320,20 @@ m68k-*-*)
mips*-*-*)
cpu_type=mips
;;
-pj*-*-*)
- cpu_type=pj
- ;;
powerpc*-*-*)
cpu_type=rs6000
- extra_headers="ppc-asm.h altivec.h"
+ extra_headers="ppc-asm.h altivec.h spe.h"
;;
sparc*-*-*)
cpu_type=sparc
;;
-sh64-*-*)
+# Note the 'l'; we need to be able to match e.g. "shle" or "shl".
+sh[123456789l]*-*-*)
cpu_type=sh
;;
+tic4x-*-*)
+ cpu_type=c4x
+ ;;
esac
tm_file=${cpu_type}/${cpu_type}.h
@@ -347,6 +341,11 @@ if test -f ${srcdir}/config/${cpu_type}/${cpu_type}-protos.h
then
tm_p_file=${cpu_type}/${cpu_type}-protos.h
fi
+extra_modes=
+if test -f ${srcdir}/config/${cpu_type}/${cpu_type}-modes.def
+then
+ extra_modes=${cpu_type}/${cpu_type}-modes.def
+fi
case $machine in
x86_64-*-*)
@@ -369,6 +368,8 @@ case $machine in
*-*-linux*ecoff* | *-*-linux*libc1* | *-*-linux*oldld* | *-*-linux*aout*)
;;
*)
+ extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
+ gas=yes gnu_ld=yes
case x${enable_threads} in
x | xyes | xposix) thread_file='posix'
;;
@@ -392,8 +393,11 @@ case $machine in
# But here we need a little extra magic.
tmake_file="t-slibgcc-elf-ver t-linux t-gnu"
case $machine in
+ alpha*)
+ tm_file="${cpu_type}/${cpu_type}.h alpha/elf.h alpha/linux.h alpha/linux-elf.h gnu.h ${tm_file}"
+ ;;
i[34567]86-*-*)
- tm_file="${cpu_type}/${cpu_type}.h i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h gnu.h ${tm_file}"
+ tm_file="${cpu_type}/${cpu_type}.h i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h gnu.h ${tm_file}"
;;
esac
;;
@@ -411,6 +415,32 @@ case $machine in
xm_defines=POSIX
gas=yes
gnu_ld=yes
+
+ # NetBSD 2.0 and later get POSIX threads enabled by default.
+ # Allow them to be explicitly enabled on any other version.
+ case x${enable_threads} in
+ x)
+ case $machine in
+ *-*-netbsd[2-9]* | *-*-netbsdelf[2-9]*)
+ thread_file='posix'
+ tm_defines="${tm_defines} NETBSD_ENABLE_PTHREADS"
+ ;;
+ esac
+ ;;
+ xyes | xposix)
+ thread_file='posix'
+ tm_defines="${tm_defines} NETBSD_ENABLE_PTHREADS"
+ ;;
+ esac
+
+ # NetBSD 1.7 and later are set up to use GCC's crtstuff for
+ # ELF configurations. We will clear extra_parts in the
+ # a.out configurations.
+ case $machine in
+ *-*-netbsd*1.[7-9]* | *-*-netbsd[2-9]* | *-*-netbsdelf[2-9]*)
+ extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o"
+ ;;
+ esac
;;
*-*-freebsd[12] | *-*-freebsd[12].* | *-*-freebsd*aout*)
# This is the place-holder for the generic a.out configuration
@@ -483,39 +513,6 @@ case $machine in
then tmake_file=${cpu_type}/t-$rest
fi
;;
-1750a-*-*)
- # 1750a is only supported as a target.
- case "$build,$host" in 1750a*,* | *,1750a* )
- echo "*** $machine is only supported as a target" >&2
- exit 1
- esac
- ;;
-a29k-*-bsd* | a29k-*-sym1*)
- tm_file="${tm_file} a29k/unix.h"
- xm_defines=POSIX
- use_collect2=yes
- ;;
-a29k-*-udi | a29k-*-coff)
- tm_file="${tm_file} dbxcoff.h"
- tmake_file=a29k/t-a29kbare
- ;;
-a29k*-*-rtems*)
- xm_defines=POSIX
- tm_file="a29k/a29k.h a29k/rtems.h rtems.h"
- tmake_file="a29k/t-a29kbare t-rtems"
- if test x$enable_threads = xyes; then
- thread_file='rtems'
- fi
- ;;
-a29k-wrs-vxworks*)
- tm_file="${tm_file} dbxcoff.h a29k/vx29k.h"
- tmake_file=a29k/t-vx29k
- extra_parts="crtbegin.o crtend.o"
- thread_file='vxworks'
- ;;
-a29k-*-*) # Default a29k environment.
- use_collect2=yes
- ;;
alpha*-*-unicosmk*)
use_collect2=yes
tm_file="${tm_file} alpha/unicosmk.h"
@@ -546,11 +543,8 @@ alpha-*-interix)
#local_prefix='$$INTERIX_ROOT'/usr/contrib
;;
alpha*-*-linux*ecoff*)
- tm_file="${tm_file} alpha/linux-ecoff.h alpha/linux.h"
- target_cpu_default="MASK_GAS"
- tmake_file="alpha/t-alpha alpha/t-ieee"
- gas=no
- gas=yes gnu_ld=yes
+ echo "Configuration $machine no longer supported" 1>&2
+ exit 1
;;
alpha*-*-linux*libc1*)
tm_file="${tm_file} alpha/elf.h alpha/linux.h alpha/linux-elf.h"
@@ -566,8 +560,10 @@ alpha*-*-linux*)
tm_file="${tm_file} alpha/elf.h alpha/linux.h alpha/linux-elf.h"
target_cpu_default="MASK_GAS"
tmake_file="t-slibgcc-elf-ver t-linux alpha/t-crtfm alpha/t-alpha alpha/t-ieee"
- extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o"
- gas=yes gnu_ld=yes
+ ;;
+alpha*-*-gnu*)
+ target_cpu_default="MASK_GAS"
+ tmake_file="${tmake_file} alpha/t-crtfm alpha/t-alpha alpha/t-ieee"
;;
alpha*-*-freebsd*)
tm_file="${tm_file} ${fbsd_tm_file} alpha/elf.h alpha/freebsd.h"
@@ -582,12 +578,13 @@ alpha*-*-netbsd*)
;;
alpha*-*-openbsd*)
+ tm_file="${cpu_type}/${cpu_type}.h ${tm_file}"
# default x-alpha is only appropriate for dec-osf.
target_cpu_default="MASK_GAS"
tmake_file="alpha/t-alpha alpha/t-ieee"
;;
-alpha*-dec-osf*)
+alpha*-dec-osf[45]*)
xm_defines=POSIX
if test x$stabs = xyes
then
@@ -598,30 +595,22 @@ alpha*-dec-osf*)
extra_passes="mips-tfile mips-tdump"
fi
use_collect2=yes
- tmake_file="alpha/t-alpha alpha/t-ieee alpha/t-crtfm"
+ tmake_file="alpha/t-alpha alpha/t-ieee alpha/t-crtfm alpha/t-osf4"
+ tm_file="${tm_file} alpha/osf.h"
extra_headers=va_list.h
case $machine in
- *-*-osf1*)
- tm_file="${tm_file} alpha/osf.h alpha/osf12.h alpha/osf2or3.h"
- ;;
- *-*-osf[23]*)
- tm_file="${tm_file} alpha/osf.h alpha/osf2or3.h"
- ;;
*-*-osf4*)
- tm_file="${tm_file} alpha/osf.h"
- tmake_file="$tmake_file alpha/t-osf4"
# Some versions of OSF4 (specifically X4.0-9 296.7) have
# a broken tar, so we use cpio instead.
install_headers_dir=install-headers-cpio
+ # Set target_cpu_default except on 4.0a.
+ case $machine in
+ *-*-osf4.0a) ;;
+ *) target_cpu_default=MASK_SUPPORT_ARCH
+ esac
;;
*-*-osf5*)
- tm_file="${tm_file} alpha/osf.h alpha/osf5.h"
- tmake_file="$tmake_file alpha/t-osf4"
- float_format=i128
- ;;
- esac
- case $machine in
- *-*-osf4.0[b-z] | *-*-osf4.[1-9]* | *-*-osf5*)
+ tm_file="${tm_file} alpha/osf5.h"
target_cpu_default=MASK_SUPPORT_ARCH
;;
esac
@@ -639,7 +628,7 @@ alpha*-*-vxworks*)
;;
alpha64-dec-*vms*)
xm_defines=POSIX
- tm_file="alpha/vms.h alpha/vms64.h"
+ tm_file="${tm_file} alpha/vms.h alpha/vms64.h"
xm_file="alpha/xm-vms.h alpha/xm-vms64.h"
tmake_file="alpha/t-alpha alpha/t-vms alpha/t-vms64 alpha/t-ieee"
xmake_file=alpha/x-vms
@@ -657,7 +646,7 @@ alpha64-dec-*vms*)
;;
alpha*-dec-*vms*)
xm_defines=POSIX
- tm_file=alpha/vms.h
+ tm_file="${tm_file} alpha/vms.h"
xm_file=alpha/xm-vms.h
tmake_file="alpha/t-alpha alpha/t-vms alpha/t-ieee"
xmake_file=alpha/x-vms
@@ -686,20 +675,6 @@ arm-*-vxworks*)
tmake_file=arm/t-arm-coff
thread_file='vxworks'
;;
-arm-*-riscix1.[01]*) # Acorn RISC machine (early versions)
- tm_file="arm/riscix1-1.h arm/arm.h"
- use_collect2=yes
- ;;
-arm-*-riscix*) # Acorn RISC machine
- if test x$gas = xyes
- then
- tm_file="arm/riscix.h arm/rix-gas.h arm/arm.h"
- else
- tm_file="arm/riscix.h arm/arm.h"
- fi
- tmake_file=arm/t-riscix
- use_collect2=yes
- ;;
arm-semi-aout | armel-semi-aout)
tm_file="arm/semi.h arm/aout.h arm/arm.h"
tmake_file=arm/t-semi
@@ -713,11 +688,13 @@ arm*-*-freebsd*|strongarm*-*-freebsd*)
tmake_file="${tmake_file} arm/t-strongarm-elf"
;;
arm*-*-netbsdelf*)
- echo "GCC does not yet support the ${machine} target"; exit 1
+ tm_file="dbxelf.h elfos.h netbsd.h netbsd-elf.h arm/elf.h arm/aout.h arm/arm.h arm/netbsd-elf.h"
+ tmake_file="${tmake_file} arm/t-netbsd"
;;
arm*-*-netbsd*)
tm_file="arm/aout.h arm/arm.h netbsd.h netbsd-aout.h arm/netbsd.h"
tmake_file="t-netbsd arm/t-netbsd"
+ extra_parts=""
use_collect2=yes
;;
arm*-*-linux*) # ARM GNU/Linux with ELF
@@ -770,27 +747,7 @@ arm-*-pe*)
;;
avr-*-*)
;;
-c1-convex-*) # Convex C1
- target_cpu_default=1
- use_collect2=yes
- ;;
-c2-convex-*) # Convex C2
- target_cpu_default=2
- use_collect2=yes
- ;;
-c32-convex-*)
- target_cpu_default=4
- use_collect2=yes
- ;;
-c34-convex-*)
- target_cpu_default=8
- use_collect2=yes
- ;;
-c38-convex-*)
- target_cpu_default=16
- use_collect2=yes
- ;;
-c4x-*-rtems*)
+c4x-*-rtems* | tic4x-*-rtems*)
xm_defines=POSIX
tmake_file="c4x/t-c4x t-rtems"
tm_file="c4x/c4x.h c4x/rtems.h rtems.h"
@@ -800,18 +757,11 @@ c4x-*-rtems*)
c_target_objs="c4x-c.o"
cxx_target_objs="c4x-c.o"
;;
-c4x-*)
- float_format=c4x
+c4x-* | tic4x-*)
tmake_file=c4x/t-c4x
c_target_objs="c4x-c.o"
cxx_target_objs="c4x-c.o"
;;
-clipper-intergraph-clix*)
- tm_file="${tm_file} svr3.h clipper/clix.h"
- xm_defines=POSIX
- extra_parts="crtbegin.o crtend.o"
- install_headers_dir=install-headers-cpio
- ;;
cris-*-aout)
tm_file="dbxelf.h ${tm_file} cris/aout.h"
gas=yes
@@ -825,28 +775,21 @@ cris-*-elf | cris-*-none)
cris-*-linux*)
tm_file="dbxelf.h elfos.h svr4.h ${tm_file} linux.h cris/linux.h"
tmake_file="cris/t-cris t-slibgcc-elf-ver cris/t-linux"
- extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
- case x${enable_threads} in
- x | xyes | xpthreads | xposix)
- thread_file=posix
- ;;
- esac
- gas=yes
;;
d30v-*)
tm_file="dbxelf.h elfos.h svr4.h ${tm_file}"
- float_format=i64
;;
dsp16xx-*)
;;
-elxsi-elxsi-*)
- use_collect2=yes
- ;;
fr30-*-elf)
tm_file="dbxelf.h elfos.h svr4.h ${tm_file}"
tmake_file=fr30/t-fr30
extra_parts="crti.o crtn.o crtbegin.o crtend.o"
;;
+frv-*-elf)
+ tm_file="dbxelf.h elfos.h svr4.h ${tm_file} frv/frv-abi.h"
+ tmake_file=frv/t-frv
+ ;;
h8300-*-rtems*)
xm_defines=POSIX
tmake_file="h8300/t-h8300 t-rtems"
@@ -854,30 +797,25 @@ h8300-*-rtems*)
if test x$enable_threads = xyes; then
thread_file='rtems'
fi
- float_format=i32
;;
h8300-*-elf*)
tmake_file="h8300/t-h8300 h8300/t-elf"
tm_file="h8300/h8300.h h8300/elf.h"
- float_format=i32
;;
h8300-*-*)
- float_format=i32
;;
hppa*64*-*-linux* | parisc*64*-*-linux*)
target_cpu_default="(MASK_PA_11 | MASK_PA_20)"
- tm_file="pa/pa64-start.h ${tm_file} dbxelf.h elfos.h svr4.h linux.h pa/pa-linux.h \
- pa/pa64-regs.h pa/pa-64.h pa/pa64-linux.h"
+ tm_file="pa/pa64-start.h ${tm_file} dbxelf.h elfos.h svr4.h linux.h \
+ pa/pa-linux.h pa/pa64-regs.h pa/pa-64.h pa/pa64-linux.h"
tmake_file=pa/t-linux64
gas=yes gnu_ld=yes
;;
hppa*-*-linux* | parisc*-*-linux*)
- target_cpu_default="MASK_PA_11"
+ target_cpu_default="MASK_PA_11 | MASK_NO_SPACE_REGS"
tm_file="${tm_file} dbxelf.h elfos.h svr4.h linux.h pa/pa-linux.h \
pa/pa32-regs.h pa/pa32-linux.h"
tmake_file="t-slibgcc-elf-ver t-linux pa/t-linux"
- extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
- gas=yes gnu_ld=yes
;;
hppa*-*-openbsd*)
target_cpu_default="MASK_PA_11"
@@ -973,7 +911,6 @@ hppa1.0-*-hpux8*)
hppa1.1-*-hpux10* | hppa2*-*-hpux10*)
target_cpu_default="MASK_PA_11"
tm_file="${tm_file} pa/pa32-regs.h pa/long_double.h pa/som.h pa/pa-hpux.h pa/pa-hpux10.h"
- float_format=i128
xm_defines=POSIX
tmake_file="pa/t-pa pa/t-pa-hpux pa/t-hpux-shlib"
xmake_file="pa/x-ada"
@@ -990,7 +927,6 @@ hppa1.1-*-hpux10* | hppa2*-*-hpux10*)
;;
hppa1.0-*-hpux10*)
tm_file="${tm_file} pa/pa32-regs.h pa/long_double.h pa/som.h pa/pa-hpux.h pa/pa-hpux10.h"
- float_format=i128
xm_defines=POSIX
tmake_file="pa/t-pa pa/t-pa-hpux pa/t-hpux-shlib"
xmake_file="pa/x-ada"
@@ -1007,12 +943,24 @@ hppa1.0-*-hpux10*)
;;
hppa*64*-*-hpux11*)
xm_defines=POSIX
- tm_file="pa/pa64-start.h ${tm_file} pa/pa64-regs.h pa/long_double.h pa/elf.h pa/pa-hpux.h pa/pa-hpux11.h pa/pa-64.h pa/pa64-hpux.h"
- float_format=i128
+ if test x$gas = xyes
+ then
+ tm_file="pa/pa64-start.h ${tm_file} dbxelf.h elfos.h \
+ pa/pa64-regs.h pa/long_double.h pa/pa-hpux.h \
+ pa/pa-hpux11.h pa/pa-64.h pa/pa64-hpux.h"
+ else
+ tm_file="pa/pa64-start.h ${tm_file} dbxelf.h pa/elf.h \
+ pa/pa64-regs.h pa/long_double.h pa/pa-hpux.h \
+ pa/pa-hpux11.h pa/pa-64.h pa/pa64-hpux.h"
+ fi
tmake_file="pa/t-pa64 pa/t-pa-hpux"
xmake_file="pa/x-ada"
target_cpu_default="(MASK_PA_11|MASK_PA_20|MASK_GAS)"
-
+ extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o"
+ if test x$gnu_ld = xyes
+ then
+ target_cpu_default="${target_cpu_default}|MASK_GNU_LD"
+ fi
# if [ x$enable_threads = x ]; then
# enable_threads=$have_pthread_h
# fi
@@ -1021,12 +969,10 @@ hppa*64*-*-hpux11*)
# tmake_file="${tmake_file} pa/t-dce-thr"
# fi
install_headers_dir=install-headers-cpio
- use_collect2=yes
;;
hppa1.1-*-hpux11* | hppa2*-*-hpux11*)
target_cpu_default="MASK_PA_11"
tm_file="${tm_file} pa/pa32-regs.h pa/long_double.h pa/som.h pa/pa-hpux.h pa/pa-hpux11.h"
- float_format=i128
xm_defines=POSIX
tmake_file="pa/t-pa pa/t-pa-hpux pa/t-hpux-shlib"
xmake_file="pa/x-ada"
@@ -1042,7 +988,6 @@ hppa1.1-*-hpux11* | hppa2*-*-hpux11*)
;;
hppa1.0-*-hpux11*)
tm_file="${tm_file} pa/pa32-regs.h pa/long_double.h pa/som.h pa/pa-hpux.h pa/pa-hpux11.h"
- float_format=i128
xm_defines=POSIX
tmake_file="pa/t-pa pa/t-pa-hpux pa/t-hpux-shlib"
xmake_file="pa/x-ada"
@@ -1119,195 +1064,117 @@ i370-*-linux*)
tm_file="dbxelf.h elfos.h svr4.h linux.h i370/linux.h ${tm_file}"
tmake_file="t-slibgcc-elf-ver t-linux"
# broken_install=yes
- extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
- # extra_parts="crtbegin.o crtend.o"
- gnu_ld=yes
- gas=yes
elf=yes
;;
-i[34567]86-*-chorusos*)
- xm_defines=POSIX
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h i386/i386elf.h chorus.h"
- tmake_file="i386/t-i386elf t-svr4"
- case x${enable_threads} in
- xyes | xpthreads | xposix)
- thread_file='posix'
- ;;
- esac
+i[34567]86-*-darwin*)
+ tm_file="${tm_file} darwin.h i386/darwin.h"
+ tm_p_file="${tm_p_file} darwin-protos.h"
+ tmake_file="t-darwin"
+ extra_objs="darwin.o"
+ target_gtfiles="\$(srcdir)/config/darwin.c"
+ c_target_objs="darwin-c.o"
+ cxx_target_objs="darwin-c.o"
+ extra_parts="crt2.o"
+ # Darwin linker does collect2 functionality
+ use_collect2=no
;;
i[34567]86-*-elf*)
xm_defines=POSIX
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h i386/i386elf.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/i386elf.h"
tmake_file="i386/t-i386elf t-svr4"
;;
-i[34567]86-ibm-aix*) # IBM PS/2 running AIX
- if test x$gas = xyes
- then
- tm_file=i386/aix386.h
- extra_parts="crtbegin.o crtend.o"
- tmake_file=i386/t-crtstuff
- else
- tm_file=i386/aix386ng.h
- use_collect2=yes
- fi
- xm_defines=POSIX
- ;;
i[34567]86-ncr-sysv4*) # NCR 3000 - ix86 running system V.4
xm_defines="POSIX SMALL_ARG_MAX"
if test x$stabs = xyes -a x$gas = xyes
then
tm_file=i386/sysv4gdb.h
else
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h i386/sysv4-cpp.h"
fi
extra_parts="crtbegin.o crtend.o"
tmake_file=i386/t-crtpic
;;
-i[34567]86-next-*)
- tm_p_file="${tm_p_file} nextstep-protos.h"
- tm_file=i386/next.h
- tmake_file=i386/t-next
- extra_objs=nextstep.o
- extra_parts="crtbegin.o crtend.o"
- if test x$enable_threads = xyes; then
- thread_file='mach'
- fi
- ;;
i[34567]86-*-netware) # Intel 80386's running netware
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h netware.h i386/netware.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h netware.h i386/netware.h"
tmake_file=i386/t-netware
;;
-i[34567]86-sequent-bsd*) # 80386 from Sequent
- use_collect2=yes
- if test x$gas = xyes
- then
- tm_file=i386/seq-gas.h
- else
- tm_file=i386/sequent.h
- fi
- ;;
-i[34567]86-sequent-ptx1*)
- xm_defines=POSIX
- tm_file=i386/seq-sysv3.h
- tmake_file=i386/t-crtstuff
- extra_parts="crtbegin.o crtend.o"
- install_headers_dir=install-headers-cpio
- ;;
-i[34567]86-sequent-ptx2* | i[34567]86-sequent-sysv3*)
- xm_defines=POSIX
- tm_file=i386/seq2-sysv3.h
- tmake_file=i386/t-crtstuff
- extra_parts="crtbegin.o crtend.o"
- install_headers_dir=install-headers-cpio
- ;;
i[34567]86-sequent-ptx4* | i[34567]86-sequent-sysv4*)
if test x$gas = xyes
then
tm_file="${tm_file} usegas.h"
fi
xm_defines="POSIX SMALL_ARG_MAX"
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h ptx4.h i386/ptx4-i.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ptx4.h i386/ptx4-i.h"
tmake_file=t-svr4
extra_parts="crtbegin.o crtend.o"
install_headers_dir=install-headers-cpio
;;
-i386-sun-sunos*) # Sun i386 roadrunner
- xm_defines=POSIX
- tm_file=i386/sun.h
- use_collect2=yes
+i[34567]86-sequent-sysv*) # would otherwise be caught by i?86-*-sysv*
+ echo "*** Configuration $machine not supported" 1>&2
+ exit 1
;;
i[34567]86-wrs-vxworks*)
- tm_file=i386/vxi386.h
+ tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h i386/vxi386.h"
thread_file='vxworks'
;;
i[34567]86-*-aout*)
- tm_file=i386/i386-aout.h
+ tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h i386/i386-aout.h"
;;
i[34567]86-*-beoself* | i[34567]86-*-beos*)
xm_defines=POSIX
tmake_file='i386/t-beos i386/t-crtpic'
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h i386/beos-elf.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h i386/beos-elf.h"
extra_parts='crtbegin.o crtend.o'
;;
-i[34567]86-*-bsdi* | i[34567]86-*-bsd386*)
- tm_file="i386/386bsd.h i386/bsd386.h"
-# tmake_file=t-libc-ok
- ;;
-i[34567]86-*-bsd*)
- tm_file=i386/386bsd.h
-# tmake_file=t-libc-ok
-# Next line turned off because both 386BSD and BSD/386 use GNU ld.
-# use_collect2=yes
- ;;
-i[34567]86-*-freebsd[12] | i[34567]86-*-freebsd[12].* | i[34567]86-*-freebsd*aout*)
- tm_file=i386/freebsd-aout.h
+i[34567]86-*-freebsd2 | i[34567]86-*-freebsd2.* | i[34567]86-*-freebsd*aout*)
+ tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h i386/freebsd-aout.h"
tmake_file=t-freebsd
;;
i[34567]86-*-freebsd*)
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h ${fbsd_tm_file} i386/freebsd.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ${fbsd_tm_file} i386/freebsd.h"
;;
x86_64-*-freebsd*)
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h ${fbsd_tm_file} i386/x86-64.h i386/freebsd.h i386/freebsd64.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ${fbsd_tm_file} i386/x86-64.h i386/freebsd.h i386/freebsd64.h"
;;
i[34567]86-*-netbsdelf*)
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h netbsd.h netbsd-elf.h i386/netbsd-elf.h"
- float_format=i386
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h netbsd.h netbsd-elf.h i386/netbsd-elf.h"
;;
i[34567]86-*-netbsd*)
- tm_file=i386/netbsd.h
+ tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h netbsd.h netbsd-aout.h i386/netbsd.h"
tmake_file=t-netbsd
+ extra_parts=""
use_collect2=yes
;;
x86_64-*-netbsd*)
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h netbsd.h netbsd-elf.h i386/x86-64.h i386/netbsd64.h"
- float_format=i386
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h netbsd.h netbsd-elf.h i386/x86-64.h i386/netbsd64.h"
;;
i[34567]86-*-openbsd*)
+ tm_file="${cpu_type}/${cpu_type}.h i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h openbsd-oldgas.h openbsd.h ${tm_file}"
# needed to unconfuse gdb
tmake_file="t-libc-ok t-openbsd i386/t-openbsd"
# we need collect2 until our bug is fixed...
use_collect2=yes
;;
i[34567]86-*-coff*)
- tm_file=i386/i386-coff.h
- ;;
-i[34567]86-*-isc*) # 80386 running ISC system
- xm_defines=POSIX
- if test x$gas = xyes -a x$stabs = xyes
- then
- tm_file=i386/iscdbx.h
- tmake_file=i386/t-svr3dbx
- extra_parts="svr3.ifile svr3z.ifile"
- else
- tm_file=i386/isccoff.h
- tmake_file=i386/t-crtstuff
- extra_parts="crtbegin.o crtend.o"
- fi
- install_headers_dir=install-headers-cpio
+ tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/i386-coff.h"
;;
-i[34567]86-*-linux*oldld*) # Intel 80386's running GNU/Linux
- # with a.out format using
- # pre BFD linkers
- tmake_file="t-linux-aout i386/t-crtstuff"
- tm_file=i386/linux-oldld.h
- gnu_ld=yes
- float_format=i386
+i[34567]86-*-linux*oldld*) # would otherwise be caught by i?86-*-linux*
+ echo "*** Configuration $machine not supported" 1>&2
+ exit 1
;;
i[34567]86-*-linux*aout*) # Intel 80386's running GNU/Linux
# with a.out format
tmake_file="t-linux-aout i386/t-crtstuff"
- tm_file=i386/linux-aout.h
+ tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h linux-aout.h i386/linux-aout.h"
gnu_ld=yes
- float_format=i386
;;
i[34567]86-*-linux*libc1) # Intel 80386's running GNU/Linux
# with ELF format using the
# GNU/Linux C library 5
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h"
tmake_file="t-slibgcc-elf-ver t-linux t-linux-gnulibc1 i386/t-crtstuff"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
gnu_ld=yes
- float_format=i386
if test x$enable_threads = xyes; then
thread_file='single'
fi
@@ -1315,22 +1182,15 @@ i[34567]86-*-linux*libc1) # Intel 80386's running GNU/Linux
i[34567]86-*-linux*) # Intel 80386's running GNU/Linux
# with ELF format using glibc 2
# aka GNU/Linux C library 6
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h"
tmake_file="t-slibgcc-elf-ver t-linux i386/t-crtstuff"
- extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
- gnu_ld=yes
- float_format=i386
;;
x86_64-*-linux*)
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h linux.h \
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h \
i386/x86-64.h i386/linux64.h"
- tmake_file="t-slibgcc-elf-ver t-linux i386/t-crtstuff i386/t-linux64"
- extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
- gnu_ld=yes
- float_format=i386
+ tmake_file="t-slibgcc-elf-ver t-linux i386/t-linux64"
;;
i[34567]86-*-gnu*)
- float_format=i386
;;
i[34567]86-go32-msdos | i[34567]86-*-go32*)
echo "GO32/DJGPP V1.X is no longer supported. Use *-pc-msdosdjgpp for DJGPP V2.X instead."
@@ -1338,19 +1198,18 @@ i[34567]86-go32-msdos | i[34567]86-*-go32*)
;;
i[34567]86-pc-msdosdjgpp*)
xm_file=i386/xm-djgpp.h
- tm_file=i386/djgpp.h
+ tm_file="dbxcoff.h ${tm_file} i386/djgpp.h"
tmake_file=i386/t-djgpp
gnu_ld=yes
gas=yes
exeext=.exe
- float_format=none
case $host in *pc-msdosdjgpp*)
target_alias=djgpp
;;
esac
;;
i[34567]86-moss-msdos* | i[34567]86-*-moss*)
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h i386/moss.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h i386/moss.h"
tmake_file=t-libc-ok
gnu_ld=yes
gas=yes
@@ -1358,47 +1217,24 @@ i[34567]86-moss-msdos* | i[34567]86-*-moss*)
i[34567]86-*-lynxos*)
if test x$gas = xyes
then
- tm_file=i386/lynx.h
+ tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h lynx.h i386/lynx.h"
else
- tm_file=i386/lynx-ng.h
+ tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h lynx-ng.h i386/lynx-ng.h"
fi
;;
i[34567]86-*-mach*)
- tm_file=i386/mach.h
+ tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h i386/mach.h"
# tmake_file=t-libc-ok
use_collect2=yes
;;
-i[34567]86-*-osfrose*) # 386 using OSF/rose
- if test x$elf = xyes
- then
- tm_file=i386/osfelf.h
- use_collect2=
- else
- tm_file=i386/osfrose.h
- use_collect2=yes
- fi
- tmake_file=i386/t-osf
- extra_objs=halfpic.o
- ;;
-i[34567]86-go32-rtems*)
- xm_defines=POSIX
- tm_file="i386/djgpp.h i386/djgpp-rtems.h rtems.h"
- tmake_file=t-rtems
- if test x$enable_threads = xyes; then
- thread_file='rtems'
- fi
- ;;
-i[34567]86-*-rtemscoff*)
- xm_defines=POSIX
- tm_file="i386/i386-coff.h i386/rtems.h rtems.h"
- tmake_file=t-rtems
- if test x$enable_threads = xyes; then
- thread_file='rtems'
- fi
+i[34567]86-go32-rtems* | i[34567]86-*-rtemscoff*)
+ # would otherwise be caught by i?86-*-rtems*
+ echo "*** Configuration $machine not supported" 1>&2
+ exit 1
;;
-i[34567]86-*-rtems*|i[34567]86-*-rtemself*)
+i[34567]86-*-rtems*)
xm_defines=POSIX
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h i386/i386elf.h i386/rtemself.h rtems.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/i386elf.h i386/rtemself.h rtems.h"
extra_parts="crtbegin.o crtend.o crti.o crtn.o"
tmake_file="i386/t-rtems-i386 i386/t-crtstuff t-rtems"
if test x$enable_threads = xyes; then
@@ -1408,7 +1244,7 @@ i[34567]86-*-rtems*|i[34567]86-*-rtemself*)
i[34567]86-*-sco3.2v5*) # 80386 running SCO Open Server 5
xm_defines=POSIX
install_headers_dir=install-headers-cpio
- tm_file="${tm_file} i386/att.h i386/sco5.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h i386/sco5.h"
if test x$gas = xyes
then
tm_file="usegas.h ${tm_file}"
@@ -1420,10 +1256,7 @@ i[34567]86-*-sco3.2v5*) # 80386 running SCO Open Server 5
;;
i[34567]86-*-solaris2*)
xm_defines="POSIX SMALL_ARG_MAX"
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h i386/sol2.h"
- if test x$gas = xyes; then
- tm_file="i386/sol2gas.h ${tm_file}"
- fi
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h sol2.h i386/sol2.h"
tmake_file="i386/t-sol2 t-svr4"
if test x$gnu_ld = xyes; then
tmake_file="$tmake_file t-slibgcc-elf-ver"
@@ -1447,7 +1280,7 @@ i[34567]86-*-solaris2*)
;;
i[34567]86-*-sysv5*) # Intel x86 on System V Release 5
xm_defines=POSIX
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h i386/sysv5.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h i386/sysv5.h"
if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
@@ -1460,7 +1293,7 @@ i[34567]86-*-sysv5*) # Intel x86 on System V Release 5
;;
i[34567]86-*-sysv4*) # Intel 80386's running system V.4
xm_defines="POSIX SMALL_ARG_MAX"
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h i386/sysv4-cpp.h"
if test x$stabs = xyes
then
tm_file="${tm_file} dbx.h"
@@ -1470,53 +1303,41 @@ i[34567]86-*-sysv4*) # Intel 80386's running system V.4
;;
i[34567]86-*-udk*) # Intel x86 on SCO UW/OSR5 Dev Kit
xm_defines=POSIX
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h i386/sysv5.h i386/udk.h"
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h i386/sysv5.h i386/udk.h"
tmake_file="i386/t-crtpic i386/t-udk t-svr4"
extra_parts="crtbegin.o crtend.o"
install_headers_dir=install-headers-cpio
;;
-i[34567]86-*-osf1*) # Intel 80386's running OSF/1 1.3+
- xm_defines='POSIX USE_C_ALLOCA SMALL_ARG_MAX'
- if test x$stabs = xyes
- then
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h i386/osf1elf.h i386/osf1elfgdb.h"
- else
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h i386/osf1elf.h"
- fi
- tmake_file=i386/t-osf1elf
- extra_parts="crti.o crtn.o crtbegin.o crtend.o"
- ;;
i[34567]86-*-sysv*) # Intel 80386's running system V
xm_defines=POSIX
if test x$gas = xyes
then
if test x$stabs = xyes
then
- tm_file=i386/svr3dbx.h
+ tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/svr3gas.h i386/svr3dbx.h"
tmake_file=i386/t-svr3dbx
- extra_parts="svr3.ifile svr3z.rfile"
+ extra_parts="svr3.ifile svr3z.ifile"
else
- tm_file=i386/svr3gas.h
+ tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/svr3gas.h"
extra_parts="crtbegin.o crtend.o"
tmake_file=i386/t-crtstuff
fi
else
- tm_file=i386/sysv3.h
+ tm_file="${tm_file} svr3.h i386/unix.h i386/att.h i386/sysv3.h"
extra_parts="crtbegin.o crtend.o"
tmake_file=i386/t-crtstuff
fi
tmake_file="$tmake_file i386/t-crtpic"
;;
i386-*-vsta) # Intel 80386's running VSTa kernel
- xm_file=i386/xm-vsta.h
- tm_file=i386/vsta.h
+ xm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/xm-vsta.h"
+ tm_file="${tm_file} i386/vsta.h"
;;
i[34567]86-*-win32)
xm_defines=POSIX
xm_file=i386/xm-cygwin.h
- float_format=i386
tmake_file=i386/t-cygwin
- tm_file=i386/win32.h
+ tm_file="${tm_file} i386/win32.h"
extra_objs=winnt.o
if test x$enable_threads = xyes; then
thread_file='win32'
@@ -1526,7 +1347,6 @@ i[34567]86-*-win32)
i[34567]86-*-pe | i[34567]86-*-cygwin*)
xm_defines=POSIX
xm_file=i386/xm-cygwin.h
- float_format=i386
tmake_file=i386/t-cygwin
tm_file=i386/cygwin.h
extra_objs=winnt.o
@@ -1537,7 +1357,6 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*)
;;
i[34567]86-*-mingw32*)
tm_file=i386/mingw32.h
- float_format=i386
xm_defines=POSIX
xm_file=i386/xm-mingw32.h
tmake_file="i386/t-cygwin i386/t-mingw32"
@@ -1555,7 +1374,7 @@ i[34567]86-*-mingw32*)
esac
;;
i[34567]86-*-uwin*)
- tm_file=i386/uwin.h
+ tm_file="i386/cygwin.h i386/uwin.h"
tmake_file="i386/t-cygwin i386/t-uwin"
extra_objs=winnt.o
if test x$enable_threads = xyes; then
@@ -1564,11 +1383,11 @@ i[34567]86-*-uwin*)
exeext=.exe
;;
i[34567]86-*-interix3*)
- tm_file="i386/i386-interix.h i386/i386-interix3.h interix.h interix3.h"
+ tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/i386-interix.h i386/i386-interix3.h interix.h interix3.h"
xm_file="i386/xm-i386-interix.h"
xm_defines=POSIX
tmake_file="t-interix i386/t-interix"
- extra_objs=interix.o
+ extra_objs=winnt.o
xmake_file="x-interix"
if test x$enable_threads = xyes ; then
thread_file='posix'
@@ -1578,11 +1397,11 @@ i[34567]86-*-interix3*)
fi
;;
i[34567]86-*-interix*)
- tm_file="i386/i386-interix.h interix.h"
+ tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/i386-interix.h interix.h"
xm_file="i386/xm-i386-interix.h"
xm_defines=POSIX
tmake_file="t-interix i386/t-interix"
- extra_objs=interix.o
+ extra_objs=winnt.o
if test x$enable_threads = xyes ; then
thread_file='posix'
fi
@@ -1590,44 +1409,6 @@ i[34567]86-*-interix*)
tm_file="${tm_file} dbxcoff.h"
fi
;;
-i[34567]86-dg-dgux*)
- xm_defines=POSIX
- tm_file="${tm_file} i386/att.h dbxelf.h elfos.h svr4.h i386/sysv4.h i386/dgux.h"
- tmake_file=i386/t-dgux
- install_headers_dir=install-headers-cpio
- ;;
-i860-alliant-*) # Alliant FX/2800
- tm_file="${tm_file} dbxelf.h elfos.h svr4.h i860/sysv4.h i860/fx2800.h"
- tmake_file=i860/t-fx2800
- extra_parts="crtbegin.o crtend.o"
- ;;
-i860-*-bsd*)
- tm_file="${tm_file} i860/bsd.h"
- if test x$gas = xyes
- then
- tm_file="${tm_file} i860/bsd-gas.h"
- fi
- use_collect2=yes
- ;;
-i860-*-mach*)
- tm_file="${tm_file} i860/mach.h"
- tmake_file=t-libc-ok
- ;;
-i860-*-osf*) # Intel Paragon XP/S, OSF/1AD
- tm_file="${tm_file} svr3.h i860/paragon.h"
- xm_defines=POSIX
- ;;
-i860-*-sysv3*)
- tm_file="${tm_file} svr3.h i860/sysv3.h"
- xm_defines=POSIX
- extra_parts="crtbegin.o crtend.o"
- ;;
-i860-*-sysv4*)
- tm_file="${tm_file} dbxelf.h elfos.h svr4.h i860/sysv4.h"
- xm_defines=POSIX
- tmake_file=t-svr4
- extra_parts="crtbegin.o crtend.o"
- ;;
i960-wrs-vxworks5 | i960-wrs-vxworks5.0*)
tm_file="${tm_file} i960/vx960.h"
tmake_file=i960/t-vxworks960
@@ -1678,6 +1459,7 @@ ia64*-*-aix*)
tm_file="${tm_file} dbxelf.h elfos.h svr4.h ia64/sysv4.h ia64/aix.h"
tmake_file="ia64/t-ia64 ia64/t-aix"
target_cpu_default="MASK_GNU_AS|MASK_GNU_LD"
+ extra_parts="crti.o crtn.o crtbegin.o crtend.o crtbeginS.o crtendS.o"
;;
ia64*-*-elf*)
tm_file="${tm_file} dbxelf.h elfos.h ia64/sysv4.h ia64/elf.h"
@@ -1691,19 +1473,19 @@ ia64*-*-elf*)
then
target_cpu_default="${target_cpu_default}|MASK_GNU_LD"
fi
- float_format=i386
+ extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
;;
ia64*-*-freebsd*)
tm_file="${tm_file} dbxelf.h elfos.h ${fbsd_tm_file} ia64/sysv4.h ia64/freebsd.h"
target_cpu_default="MASK_GNU_AS|MASK_GNU_LD"
tmake_file="${tmake_file} ia64/t-ia64"
- float_format=i386
+ extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
;;
ia64*-*-linux*)
tm_file="${tm_file} dbxelf.h elfos.h svr4.h linux.h ia64/sysv4.h ia64/linux.h"
tmake_file="t-slibgcc-elf-ver t-linux ia64/t-ia64 ia64/t-glibc"
target_cpu_default="MASK_GNU_AS|MASK_GNU_LD"
- float_format=i386
+ extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
;;
ia64*-*-hpux*)
tm_file="${tm_file} dbxelf.h elfos.h svr4.h ia64/sysv4.h ia64/hpux.h ia64/hpux_longdouble.h"
@@ -1712,11 +1494,15 @@ ia64*-*-hpux*)
if test x$enable_threads = xyes; then
thread_file='posix'
fi
- float_format=i386
+ use_collect2=no
+ c_target_objs="ia64-c.o"
+ cxx_target_objs="ia64-c.o"
+ ;;
+ip2k-*-elf)
;;
m32r-*-elf*)
tm_file="dbxelf.h elfos.h svr4.h ${tm_file}"
- extra_parts="crtinit.o crtfini.o"
+ extra_parts="crtinit.o crtfini.o m32rx/crtinit.o m32rx/crtfini.o"
;;
# m68hc11 and m68hc12 share the same machine description.
m68hc11-*-*|m6811-*-*)
@@ -1733,11 +1519,6 @@ m68hc12-*-*|m6812-*-*)
out_file="m68hc11/m68hc11.c"
tmake_file="m68hc11/t-m68hc11-gas"
;;
-m68000-convergent-sysv*)
- tm_file=m68k/ctix.h
- xm_defines=POSIX
- use_collect2=yes
- ;;
m68000-hp-bsd*) # HP 9000/200 running BSD
tm_file=m68k/hp2bsd.h
use_collect2=yes
@@ -1772,63 +1553,16 @@ m68000-att-sysv*)
fi
use_collect2=yes
;;
-m68k-apple-aux*) # Apple Macintosh running A/UX
- xm_defines=POSIX
- tmake_file=m68k/t-aux
- install_headers_dir=install-headers-cpio
- extra_parts="crt1.o mcrt1.o maccrt1.o crt2.o crtn.o"
- tm_file=
- if test "$gnu_ld" = yes
- then
- tm_file="${tm_file} m68k/auxgld.h"
- else
- tm_file="${tm_file} m68k/auxld.h"
- fi
- if test "$gas" = yes
- then
- tm_file="${tm_file} m68k/auxgas.h"
- else
- tm_file="${tm_file} m68k/auxas.h"
- fi
- tm_file="${tm_file} m68k/a-ux.h"
- float_format=m68k
- ;;
-m68k-apollo-*)
- tm_file=m68k/apollo68.h
- use_collect2=yes
- float_format=m68k
- ;;
-m68k-altos-sysv*) # Altos 3068
- if test x$gas = xyes
- then
- tm_file=m68k/altos3068.h
- xm_defines=POSIX
- else
- echo "The Altos is supported only with the GNU assembler" 1>&2
- exit 1
- fi
- ;;
-m68k-bull-sysv*) # Bull DPX/2
- if test x$gas = xyes
- then
- if test x$stabs = xyes
- then
- tm_file=m68k/dpx2cdbx.h
- else
- tm_file=m68k/dpx2g.h
- fi
- else
- tm_file=m68k/dpx2.h
- fi
- xm_defines=POSIX
- use_collect2=yes
- ;;
m68k-atari-sysv4*) # Atari variant of V.4.
tm_file=m68k/atari.h
xm_defines=POSIX
tmake_file=t-svr4
extra_parts="crtbegin.o crtend.o"
- float_format=m68k
+ ;;
+m68k-apollo-sysv* | m68k-bull-sysv*)
+ # can otherwise be caught by m68k-*-sysv4*
+ echo "*** Configuration $machine not supported" 1>&2
+ exit 1
;;
m68k-motorola-sysv*)
tm_file=m68k/mot3300.h
@@ -1853,7 +1587,6 @@ m68k-motorola-sysv*)
fi
gdb_needs_out_file_path=yes
extra_parts="crt0.o mcrt0.o"
- float_format=m68k
;;
m68k-ncr-sysv*) # NCR Tower 32 SVR3
tm_file=m68k/tower-as.h
@@ -1879,32 +1612,18 @@ m68k-cbm-sysv4*) # Commodore variant of V.4.
xm_defines=POSIX
tmake_file=t-svr4
extra_parts="crtbegin.o crtend.o"
- float_format=m68k
;;
m68k-ccur-rtu)
tm_file=m68k/ccur-GAS.h
use_collect2=yes
- float_format=m68k
;;
m68k-hp-bsd4.4*) # HP 9000/3xx running 4.4bsd
tm_file=m68k/hp3bsd44.h
use_collect2=yes
- float_format=m68k
;;
m68k-hp-bsd*) # HP 9000/3xx running Berkeley Unix
tm_file=m68k/hp3bsd.h
use_collect2=yes
- float_format=m68k
- ;;
-m68k-isi-bsd*)
- if test x$with_fp = xno
- then
- tm_file=m68k/isi-nfp.h
- else
- tm_file=m68k/isi.h
- float_format=m68k
- fi
- use_collect2=yes
;;
m68k-hp-hpux7*) # HP 9000 series 300 running HPUX version 7.
xm_defines=POSIX
@@ -1918,7 +1637,6 @@ m68k-hp-hpux7*) # HP 9000 series 300 running HPUX version 7.
fi
install_headers_dir=install-headers-cpio
use_collect2=yes
- float_format=m68k
;;
m68k-hp-hpux*) # HP 9000 series 300
xm_defines=POSIX
@@ -1932,53 +1650,10 @@ m68k-hp-hpux*) # HP 9000 series 300
fi
install_headers_dir=install-headers-cpio
use_collect2=yes
- float_format=m68k
;;
m68k-sun-mach*)
tm_file=m68k/sun3mach.h
use_collect2=yes
- float_format=m68k
- ;;
-m68k-sony-newsos3*)
- if test x$gas = xyes
- then
- tm_file=m68k/news3gas.h
- else
- tm_file=m68k/news3.h
- fi
- use_collect2=yes
- float_format=m68k
- ;;
-m68k-sony-bsd* | m68k-sony-newsos*)
- if test x$gas = xyes
- then
- tm_file=m68k/newsgas.h
- else
- tm_file=m68k/news.h
- fi
- use_collect2=yes
- float_format=m68k
- ;;
-m68k-next-nextstep2*)
- tm_p_file="${tm_p_file} nextstep-protos.h"
- tm_file=m68k/next21.h
- tmake_file=m68k/t-next
- xmake_file=m68k/x-next
- extra_objs=nextstep.o
- use_collect2=yes
- float_format=m68k
- ;;
-m68k-next-nextstep[34]*)
- tm_p_file="${tm_p_file} nextstep-protos.h"
- tm_file=m68k/next.h
- tmake_file=m68k/t-next
- xmake_file=m68k/x-next
- extra_objs=nextstep.o
- extra_parts="crtbegin.o crtend.o"
- float_format=m68k
- if test x$enable_threads = xyes; then
- thread_file='mach'
- fi
;;
m68k-sun-sunos3*)
if test x$with_fp = xno
@@ -1986,7 +1661,6 @@ m68k-sun-sunos3*)
tm_file=m68k/sun3n3.h
else
tm_file=m68k/sun3o3.h
- float_format=m68k
fi
use_collect2=yes
;;
@@ -1996,7 +1670,6 @@ m68k-sun-sunos*) # For SunOS 4 (the default).
tm_file=m68k/sun3n.h
else
tm_file=m68k/sun3.h
- float_format=m68k
fi
use_collect2=yes
;;
@@ -2004,17 +1677,14 @@ m68k-wrs-vxworks*)
tm_file=m68k/vxm68k.h
tmake_file=m68k/t-vxworks68
thread_file='vxworks'
- float_format=m68k
;;
m68k-*-aout*)
tmake_file=m68k/t-m68kbare
tm_file="m68k/m68k-aout.h libgloss.h"
- float_format=m68k
;;
m68k-*-coff*)
tmake_file=m68k/t-m68kbare
tm_file="m68k/m68k-coff.h dbx.h"
- float_format=m68k
;;
m68020-*-elf* | m68k-*-elf*)
tm_file="m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h m68k/m68kemb.h m68k/m68020-elf.h"
@@ -2022,16 +1692,6 @@ m68020-*-elf* | m68k-*-elf*)
tmake_file=m68k/t-m68kelf
extra_parts="crtbegin.o crtend.o"
;;
-m68k-*-lynxos*)
- if test x$gas = xyes
- then
- tm_file=m68k/lynx.h
- else
- tm_file=m68k/lynx-ng.h
- fi
- tmake_file=m68k/t-lynx
- float_format=m68k
- ;;
m68010-*-netbsdelf* | m68k*-*-netbsdelf*)
tm_file="${tm_file} dbxelf.h elfos.h netbsd.h netbsd-elf.h m68k/netbsd-elf.h"
case $machine in
@@ -2042,38 +1702,29 @@ m68010-*-netbsdelf* | m68k*-*-netbsdelf*)
target_cpu_default="MASK_68020|MASK_68881|MASK_BITFIELD"
;;
esac
- float_format=m68k
;;
m68k*-*-netbsd*)
tm_file=m68k/netbsd.h
tmake_file=t-netbsd
- float_format=m68k
+ extra_parts=""
use_collect2=yes
;;
m68k*-*-openbsd*)
# needed to unconfuse gdb
tmake_file="t-libc-ok t-openbsd m68k/t-openbsd"
- float_format=m68k
# we need collect2 until our bug is fixed...
use_collect2=yes
;;
-m68k-*-sysv3*) # Motorola m68k's running system V.3
- xm_defines=POSIX
- extra_parts="crtbegin.o crtend.o"
- float_format=m68k
- ;;
m68k-*-sysv4*) # Motorola m68k's running system V.4
tm_file=m68k/m68kv4.h
xm_defines=POSIX
tmake_file=t-svr4
extra_parts="crtbegin.o crtend.o"
- float_format=m68k
;;
m68k-*-linux*aout*) # Motorola m68k's running GNU/Linux
# with a.out format
tm_file=m68k/linux-aout.h
tmake_file="t-linux-aout m68k/t-linux-aout"
- float_format=m68k
gnu_ld=yes
;;
m68k-*-linux*libc1) # Motorola m68k's running GNU/Linux
@@ -2082,7 +1733,6 @@ m68k-*-linux*libc1) # Motorola m68k's running GNU/Linux
tm_file=m68k/linux.h
tmake_file="t-slibgcc-elf-ver t-linux t-linux-gnulibc1 m68k/t-linux"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- float_format=m68k
gnu_ld=yes
;;
m68k-*-linux*) # Motorola m68k's running GNU/Linux
@@ -2090,104 +1740,32 @@ m68k-*-linux*) # Motorola m68k's running GNU/Linux
# aka the GNU/Linux C library 6.
tm_file=m68k/linux.h
tmake_file="t-slibgcc-elf-ver t-linux m68k/t-linux"
- extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- float_format=m68k
- gnu_ld=yes
;;
m68k-*-psos*)
tmake_file=m68k/t-m68kbare
tm_file=m68k/m68k-psos.h
- float_format=m68k
;;
-m68k-*-rtemscoff*)
- xm_defines=POSIX
- tmake_file="m68k/t-m68kbare t-rtems"
- tm_file="m68k/m68k-coff.h m68k/rtems.h rtems.h"
- float_format=m68k
- if test x$enable_threads = xyes; then
- thread_file='rtems'
- fi
+m68k-*-rtemscoff*) # would otherwise be caught by m68k-*-rtems*
+ echo "*** Configuration $machine not supported" 1>&2
+ exit 1
;;
-m68k-*-rtemself*|m68k-*-rtems*)
+m68k-*-rtems*)
xm_defines=POSIX
tmake_file="m68k/t-m68kbare t-rtems m68k/t-crtstuff"
tm_file="m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h m68k/m68kemb.h m68k/m68020-elf.h m68k/rtemself.h rtems.h"
- float_format=m68k
extra_parts="crtbegin.o crtend.o"
if test x$enable_threads = xyes; then
thread_file='rtems'
fi
;;
-m88k-dg-dgux*)
- xm_defines=POSIX
- case $machine in
- m88k-dg-dguxbcs*)
- tm_file="dbxelf.h elfos.h svr4.h m88k/dgux.h m88k/dguxbcs.h"
- tmake_file="m88k/t-dgux m88k/t-dguxbcs"
- ;;
- *)
- tm_file="dbxelf.h elfos.h svr4.h m88k/dgux.h"
- tmake_file=m88k/t-dgux
- ;;
- esac
- extra_parts="crtbegin.o bcscrtbegin.o crtend.o m88kdgux.ld"
- if test x$gas = xyes
- then
- tmake_file=m88k/t-dgux-gas
- fi
- ;;
-m88k-dolphin-sysv3*)
- xm_defines=POSIX
- tm_file=m88k/dolph.h
- extra_parts="crtbegin.o crtend.o"
- tmake_file=m88k/t-dolph
- if test x$gas = xyes
- then
- tmake_file=m88k/t-m88k-gas
- fi
- ;;
-m88k-tektronix-sysv3)
- xm_defines=POSIX
- tm_file=m88k/tekXD88.h
- extra_parts="crtbegin.o crtend.o"
- tmake_file=m88k/t-tekXD88
- if test x$gas = xyes
- then
- tmake_file=m88k/t-m88k-gas
- fi
- ;;
m88k-*-aout*)
xm_defines=POSIX
tm_file=m88k/m88k-aout.h
;;
-m88k-*-coff*)
- xm_defines=POSIX
- tm_file=m88k/m88k-coff.h
- tmake_file=m88k/t-bug
- ;;
-m88k-*-luna*)
- tm_file=m88k/luna.h
- extra_parts="crtbegin.o crtend.o"
- if test x$gas = xyes
- then
- tmake_file=m88k/t-luna-gas
- else
- tmake_file=m88k/t-luna
- fi
- ;;
m88k-*-openbsd*)
tmake_file="${tmake_file} m88k/t-luna-gas"
tm_file="m88k/aout-dbx.h aoutos.h m88k/m88k.h openbsd.h ${tm_file}"
;;
-m88k-*-sysv3*)
- xm_defines=POSIX
- tm_file=m88k/sysv3.h
- extra_parts="crtbegin.o crtend.o"
- if test x$gas = xyes
- then
- tmake_file=m88k/t-m88k-gas
- fi
- ;;
m88k-*-sysv4*)
xm_defines=POSIX
tm_file="dbxelf.h elfos.h svr4.h m88k/sysv4.h"
@@ -2202,6 +1780,30 @@ mcore-*-pe*)
tm_file=mcore/mcore-pe.h
tmake_file=mcore/t-mcore-pe
;;
+mips-sgi-irix6*o32) # SGI System V.4., IRIX 6, O32 ABI
+ if test x$gas = xyes
+ then
+ tm_file="mips/iris5.h mips/iris5gas.h mips/iris6-o32-gas.h"
+ if test x$stabs = xyes
+ then
+ tm_file="${tm_file} dbx.h mips/dbxmdebug.h"
+ fi
+ tmake_file=mips/t-iris5-gas
+ else
+ tm_file="mips/iris5.h mips/iris6-o32-as.h"
+ tmake_file=mips/t-iris5-as
+ fi
+ tm_file="${tm_file} mips/iris6-o32.h"
+ tmake_file="${tmake_file} mips/t-iris mips/t-iris5-6"
+ xm_defines=POSIX
+ xm_file=mips/xm-iris5.h
+ # mips-tfile doesn't work yet
+ # See comment in mips/iris5.h file.
+ use_collect2=yes
+# if test x$enable_threads = xyes; then
+# thread_file='irix'
+# fi
+ ;;
mips-sgi-irix6*) # SGI System V.4., IRIX 6
if test "x$gnu_ld" = xyes
then
@@ -2209,14 +1811,14 @@ mips-sgi-irix6*) # SGI System V.4., IRIX 6
else
tm_file=mips/iris6.h
fi
- tmake_file="mips/t-iris mips/t-iris6"
+ tmake_file="mips/t-iris mips/t-iris5-6 mips/t-iris6"
xm_defines=POSIX
# if test x$enable_threads = xyes; then
# thread_file='irix'
# fi
;;
mips-wrs-vxworks)
- tm_file="mips/elf.h mips/vxworks.h"
+ tm_file="${tm_file} mips/elf.h mips/vxworks.h"
tmake_file=mips/t-ecoff
gas=yes
gnu_ld=yes
@@ -2258,12 +1860,14 @@ mips-sgi-irix5*) # SGI System V.4., IRIX 5
tm_file="mips/iris5.h mips/iris5gas.h"
if test x$stabs = xyes
then
- tm_file="${tm_file} dbx.h"
+ tm_file="${tm_file} dbx.h mips/dbxmdebug.h"
fi
+ tmake_file=mips/t-iris5-gas
else
tm_file=mips/iris5.h
+ tmake_file=mips/t-iris5-as
fi
- tmake_file=mips/t-iris
+ tmake_file="${tmake_file} mips/t-iris mips/t-iris5-6"
xm_defines=POSIX
xm_file=mips/xm-iris5.h
# mips-tfile doesn't work yet
@@ -2273,122 +1877,24 @@ mips-sgi-irix5*) # SGI System V.4., IRIX 5
# thread_file='irix'
# fi
;;
-mips-sgi-irix4loser*) # Mostly like a MIPS.
- tm_file="mips/iris4loser.h mips/iris3.h ${tm_file} mips/iris4.h"
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- tmake_file=mips/t-iris
- xm_defines=POSIX
- if test x$gas = xyes
- then :
- else
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
-# if test x$enable_threads = xyes; then
-# thread_file='irix'
-# fi
- ;;
-mips-sgi-irix4*) # Mostly like a MIPS.
- tm_file="mips/iris3.h ${tm_file} mips/iris4.h"
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- tmake_file=mips/t-iris
- xm_defines=POSIX
- if test x$gas = xyes
- then :
- else
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
-# if test x$enable_threads = xyes; then
-# thread_file='irix'
-# fi
- ;;
-mips-sgi-*) # Mostly like a MIPS.
- tm_file="mips/iris3.h ${tm_file}"
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- xm_defines=POSIX
- if test x$gas = xyes
- then :
- else
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
- ;;
-mips-dec-osfrose*) # Decstation running OSF/1 reference port with OSF/rose.
- tm_file="mips/osfrose.h ${tm_file}"
- extra_objs=halfpic.o
- use_collect2=yes
- ;;
-mips-dec-osf*) # Decstation running OSF/1 as shipped by DIGITAL
- tm_file=mips/dec-osf1.h
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- if test x$gas = xyes
- then :
- else
- tmake_file=mips/t-ultrix
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
+mips-sgi-*) # would otherwise be caught by mips-*-elf*
+ echo "*** Configuration $machine not supported" 1>&2
+ exit 1
;;
-mips-dec-bsd*) # Decstation running 4.4 BSD
- tm_file=mips/dec-bsd.h
- if test x$gas = xyes
- then :
- else
- tmake_file=mips/t-ultrix
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
- ;;
mips*-*-netbsd*) # NetBSD/mips, either endian.
- tm_file="elfos.h mips/netbsd.h"
- case $machine in
- mips*el-*)
- tm_file="mips/little.h $tm_file"
- ;;
- esac
+ target_cpu_default="MASK_GAS|MASK_ABICALLS"
+ tm_file="elfos.h ${tm_file} mips/netbsd.h"
tmake_file="${tmake_file} mips/t-netbsd"
;;
mips*-*-linux*) # Linux MIPS, either endian.
- tm_file="dbxelf.h elfos.h svr4.h linux.h mips/linux.h"
+ tm_file="dbxelf.h elfos.h svr4.h linux.h ${tm_file} mips/linux.h"
case $machine in
mipsisa32*-*)
- tm_file="$tm_file mips/isa32-linux.h"
target_cpu_default="MASK_SOFT_FLOAT"
+ tm_defines="MIPS_ISA_DEFAULT=32"
;;
esac
- case $machine in
- mips*el-*)
- tm_file="mips/little.h $tm_file"
- ;;
- esac
tmake_file="t-slibgcc-elf-ver t-linux mips/t-linux"
- extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
- gnu_ld=yes
- gas=yes
;;
mips*el-*-openbsd*) # mips little endian
target_cpu_default="MASK_GAS|MASK_ABICALLS"
@@ -2397,278 +1903,83 @@ mips*-*-openbsd*) # mips big endian
target_cpu_default="MASK_GAS|MASK_ABICALLS"
tm_file="mips/openbsd-be.h ${tm_file}"
;;
-mips-sony-bsd* | mips-sony-newsos*) # Sony NEWS 3600 or risc/news.
- tm_file="mips/news4.h ${tm_file}"
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- if test x$gas = xyes
- then :
- else
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
- ;;
-mips-sony-sysv*) # Sony NEWS 3800 with NEWSOS5.0.
- # That is based on svr4.
- # t-svr4 is not right because this system doesn't use ELF.
- tm_file="mips/news5.h ${tm_file}"
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- xm_defines=POSIX
- if test x$gas = xyes
- then :
- else
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
- ;;
-mips-tandem-sysv4*) # Tandem S2 running NonStop UX
- tm_file="mips/svr4-5.h mips/svr4-t.h"
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- xm_defines=POSIX
- if test x$gas = xyes
- then
- extra_parts="crtbegin.o crtend.o"
- else
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
- ;;
-mips-*-ultrix* | mips-dec-mach3) # Decstation.
- tm_file="mips/ultrix.h ${tm_file}"
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- if test x$gas = xyes
- then :
- else
- tmake_file=mips/t-ultrix
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
- ;;
-mips-*-riscos[56789]bsd*)
- tm_file=mips/bsd-5.h # MIPS BSD 4.3, RISC-OS 5.0
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- if test x$gas = xyes
- then
- tmake_file=mips/t-bsd-gas
- else
- tmake_file=mips/t-bsd
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
- ;;
-mips-*-bsd* | mips-*-riscosbsd* | mips-*-riscos[1234]bsd*)
- tm_file="mips/bsd-4.h ${tm_file}" # MIPS BSD 4.3, RISC-OS 4.0
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- if test x$gas = xyes
- then
- tmake_file=mips/t-bsd-gas
- else
- tmake_file=mips/t-bsd
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
- ;;
-mips-*-riscos[56789]sysv4*)
- tm_file=mips/svr4-5.h # MIPS System V.4., RISC-OS 5.0
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- if test x$gas = xyes
- then
- tmake_file=mips/t-svr4-gas
- else
- tmake_file=mips/t-svr4
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
- ;;
-mips-*-sysv4* | mips-*-riscos[1234]sysv4* | mips-*-riscossysv4*)
- tm_file="mips/svr4-4.h ${tm_file}"
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- xm_defines=POSIX
- if test x$gas = xyes
- then
- tmake_file=mips/t-svr4-gas
- else
- tmake_file=mips/t-svr4
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
- ;;
-mips-*-riscos[56789]sysv*)
- tm_file=mips/svr3-5.h # MIPS System V.3, RISC-OS 5.0
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- xm_defines=POSIX
- if test x$gas = xyes
- then
- tmake_file=mips/t-svr3-gas
- else
- tmake_file=mips/t-svr3
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
- ;;
-mips-*-sysv* | mips-*-riscos*sysv*)
- tm_file="mips/svr3-4.h ${tm_file}"
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- xm_defines=POSIX
- if test x$gas = xyes
- then
- tmake_file=mips/t-svr3-gas
- else
- tmake_file=mips/t-svr3
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
- ;;
-mips-*-riscos[56789]*) # Default MIPS RISC-OS 5.0.
- tm_file=mips/mips-5.h
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- if test x$gas = xyes
- then :
- else
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
- ;;
-mipsel-*-ecoff*)
- tm_file=mips/ecoffl.h
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- tmake_file=mips/t-ecoff
- ;;
-mips-*-ecoff*)
- tm_file="gofast.h mips/ecoff.h"
+mips-*-ecoff* | mipsel-*-ecoff*)
if test x$stabs = xyes; then
tm_file="${tm_file} dbx.h"
fi
tmake_file=mips/t-ecoff
;;
-mipsisa32-*-elf*)
- tm_file="mips/isa3264.h mips/abi64.h"
+mipsisa32-*-elf* | mipsisa32el-*-elf*)
+ tm_file="${tm_file} mips/elf.h"
tmake_file=mips/t-isa3264
- target_cpu_default="MASK_SOFT_FLOAT"
+ tm_defines="MIPS_ISA_DEFAULT=32 MIPS_ABI_DEFAULT=ABI_MEABI"
;;
-mipsel-*-elf*)
- tm_file="mips/elfl.h"
+mipsisa64-*-elf* | mipsisa64el-*-elf*)
+ tm_file="${tm_file} mips/elf.h"
+ tmake_file=mips/t-isa3264
+ target_cpu_default="MASK_64BIT|MASK_FLOAT64|MASK_GAS"
+ tm_defines="MIPS_ISA_DEFAULT=64 MIPS_ABI_DEFAULT=ABI_MEABI"
+ ;;
+mipsisa64sr71k-*-elf*)
+ tm_file="${tm_file} mips/elf.h"
+ tmake_file=mips/t-sr71k
+ target_cpu_default="MASK_64BIT|MASK_FLOAT64|MASK_GAS"
+ tm_defines="MIPS_ISA_DEFAULT=64 MIPS_CPU_STRING_DEFAULT=\\\"sr71000\\\" MIPS_ABI_DEFAULT=ABI_MEABI"
+ ;;
+mipsisa64sb1-*-elf* | mipsisa64sb1el-*-elf*)
+ tm_file="${tm_file} mips/elf.h"
tmake_file=mips/t-elf
+ target_cpu_default="MASK_64BIT|MASK_FLOAT64|MASK_GAS"
+ tm_defines="MIPS_ISA_DEFAULT=64 MIPS_CPU_STRING_DEFAULT=\\\"sb1\\\" MIPS_ABI_DEFAULT=ABI_O64"
;;
-mips-*-elf*)
- tm_file="mips/elf.h"
+mips-*-elf* | mipsel-*-elf*)
+ tm_file="${tm_file} mips/elf.h"
tmake_file=mips/t-elf
;;
-mips64el-*-elf*)
- tm_file="mips/elfl64.h"
+mips64-*-elf* | mips64el-*-elf*)
+ tm_file="${tm_file} mips/elf64.h"
tmake_file=mips/t-elf
+ target_cpu_default="MASK_64BIT|MASK_FLOAT64|MASK_GAS"
+ tm_defines="MIPS_ISA_DEFAULT=3 MIPS_ABI_DEFAULT=ABI_O64"
;;
-mips64orionel-*-elf*)
- tm_file="mips/elforion.h mips/elfl64.h"
+mips64vr-*-elf* | mips64vrel-*-elf*)
+ tm_file="mips/vr.h ${tm_file} mips/elf64.h"
+ tm_defines="MIPS_ABI_DEFAULT=ABI_O64 MIPS_MARCH_CONTROLS_SOFT_FLOAT=1"
+ tmake_file=mips/t-vr
+ ;;
+mips64orion-*-elf* | mips64orionel-*-elf*)
+ tm_file="${tm_file} mips/elforion.h mips/elf64.h"
tmake_file=mips/t-elf
- ;;
-mips64-*-elf*)
- tm_file="mips/elf64.h"
- tmake_file=mips/t-elf
- ;;
-mips64orion-*-elf*)
- tm_file="mips/elforion.h mips/elf64.h"
tmake_file=mips/t-elf
+ target_cpu_default="MASK_64BIT|MASK_FLOAT64|MASK_GAS"
+ tm_defines="MIPS_ISA_DEFAULT=3 MIPS_ABI_DEFAULT=ABI_O64"
;;
mips64orion-*-rtems*)
xm_defines=POSIX
- tm_file="mips/elforion.h mips/elf64.h mips/rtems64.h rtems.h"
+ tm_file="${tm_file} mips/elforion.h mips/elf64.h mips/rtems64.h rtems.h"
tmake_file="mips/t-elf t-rtems"
+ tmake_file=mips/t-elf
+ target_cpu_default="MASK_64BIT|MASK_FLOAT64|MASK_GAS"
+ tm_defines="MIPS_ISA_DEFAULT=3 MIPS_ABI_DEFAULT=ABI_O64"
if test x$enable_threads = xyes; then
thread_file='rtems'
fi
;;
mips*-*-rtems*)
xm_defines=POSIX
- tm_file="mips/elf.h mips/rtems.h rtems.h"
+ tm_file="${tm_file} mips/elf.h mips/rtems.h rtems.h"
tmake_file="mips/t-elf t-rtems"
if test x$enable_threads = xyes; then
thread_file='rtems'
fi
;;
-mipstx39el-*-elf*)
- tm_file="mips/r3900.h mips/elfl.h mips/abi64.h"
+mipstx39-*-elf* | mipstx39el-*-elf*)
+ tm_file="${tm_file} mips/r3900.h mips/elf.h"
tmake_file=mips/t-r3900
- target_cpu_default="MASK_SOFT_FLOAT"
- ;;
-mipstx39-*-elf*)
- tm_file="mips/r3900.h mips/elf.h mips/abi64.h"
- tmake_file=mips/t-r3900
- ;;
-mips-*-*) # Default MIPS RISC-OS 4.0.
- if test x$stabs = xyes; then
- tm_file="${tm_file} dbx.h"
- fi
- if test x$gas = xyes
- then :
- else
- extra_passes="mips-tfile mips-tdump"
- fi
- if test x$gnu_ld != xyes
- then
- use_collect2=yes
- fi
;;
mmix-knuth-mmixware)
;;
mn10200-*-*)
- float_format=i32
tm_file="dbxelf.h elfos.h svr4.h ${tm_file}"
if test x$stabs = xyes
then
@@ -2684,42 +1995,14 @@ mn10300-*-*)
fi
use_collect2=no
;;
-ns32k-encore-bsd*)
- tm_file=ns32k/encore.h
- use_collect2=yes
- ;;
-ns32k-sequent-bsd*)
- tm_file=ns32k/sequent.h
- use_collect2=yes
- ;;
-ns32k-tek6100-bsd*)
- tm_file=ns32k/tek6100.h
- use_collect2=yes
- ;;
-ns32k-tek6200-bsd*)
- tm_file=ns32k/tek6200.h
- use_collect2=yes
- ;;
-ns32k-merlin-*)
- tm_file=ns32k/merlin.h
- use_collect2=yes
- ;;
-ns32k-pc532-mach*)
- tm_file=ns32k/pc532-mach.h
- use_collect2=yes
- ;;
-ns32k-pc532-minix*)
- tm_file=ns32k/pc532-min.h
- xm_defines='POSIX HZ=60'
- use_collect2=yes
- ;;
ns32k-*-netbsdelf*)
echo "GCC does not yet support the ${machine} target"; exit 1
;;
ns32k-*-netbsd*)
- tm_file=ns32k/netbsd.h
+ tm_file="${tm_file} netbsd.h netbsd-aout.h ns32k/netbsd.h"
# On NetBSD, the headers are already okay, except for math.h.
- tmake_file=t-netbsd
+ tmake_file="t-netbsd ns32k/t-ns32k"
+ extra_parts=""
use_collect2=yes
;;
pdp11-*-bsd)
@@ -2732,21 +2015,6 @@ avr-*-*)
ns32k-*-openbsd*)
# Nothing special
;;
-pj*-linux*)
- tm_file="dbxelf.h elfos.h svr4.h pj/linux.h ${tm_file}"
- ;;
-pj-*)
- ;;
-pjl-*)
- tm_file="dbxelf.h elfos.h svr4.h pj/pjl.h ${tm_file}"
- ;;
-
-romp-*-aos*)
- use_collect2=yes
- ;;
-romp-*-mach*)
- use_collect2=yes
- ;;
romp-*-openbsd*)
# Nothing special
;;
@@ -2762,7 +2030,7 @@ powerpc64-*-linux*)
powerpc64-*-gnu*)
tm_file="${cpu_type}/${cpu_type}.h elfos.h svr4.h freebsd-spec.h gnu.h rs6000/sysv4.h rs6000/linux64.h rs6000/gnu.h"
out_file=rs6000/rs6000.c
- tmake_file="rs6000/t-ppcos t-slibgcc-elf-ver t-gnu rs6000/t-ppccomm"
+ tmake_file="rs6000/t-rs6000 t-slibgcc-elf-ver t-gnu rs6000/t-linux64"
;;
powerpc-*-beos*)
tm_file="${tm_file} rs6000/aix.h rs6000/beos.h rs6000/xcoff.h"
@@ -2773,10 +2041,12 @@ powerpc-*-beos*)
powerpc-*-darwin*)
tm_file="${tm_file} darwin.h rs6000/darwin.h"
tm_p_file="${tm_p_file} darwin-protos.h"
- tmake_file=rs6000/t-darwin
+ tmake_file="rs6000/t-rs6000 t-darwin rs6000/t-darwin"
extra_objs="darwin.o"
+ target_gtfiles="\$(srcdir)/config/darwin.c"
c_target_objs="darwin-c.o"
cxx_target_objs="darwin-c.o"
+ extra_parts="crt2.o"
# Darwin linker does collect2 functionality
use_collect2=no
extra_headers=altivec.h
@@ -2793,8 +2063,8 @@ powerpc-*-sysv*)
tmake_file="rs6000/t-ppcos rs6000/t-ppccomm"
;;
powerpc-*-netbsd*)
- tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/netbsd.h"
- tmake_file="rs6000/t-ppcos rs6000/t-ppccomm"
+ tm_file="${tm_file} dbxelf.h elfos.h netbsd.h netbsd-elf.h freebsd-spec.h rs6000/sysv4.h rs6000/netbsd.h"
+ tmake_file="${tmake_file} rs6000/t-netbsd"
;;
powerpc-*-chorusos*)
xm_defines=POSIX
@@ -2811,10 +2081,15 @@ powerpc-*-eabiaix*)
tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabiaix.h"
tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
;;
+powerpc-*-eabispe*)
+ xm_defines=POSIX
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabispe.h"
+ tmake_file="rs6000/t-ppcendian rs6000/t-ppccomm"
+ ;;
powerpc-*-eabisimaltivec*)
xm_defines=POSIX
tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabisim.h rs6000/eabialtivec.h"
- tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
+ tmake_file="rs6000/t-ppcendian rs6000/t-ppccomm"
;;
powerpc-*-eabisim*)
xm_defines=POSIX
@@ -2829,7 +2104,7 @@ powerpc-*-elf*)
powerpc-*-eabialtivec*)
xm_defines=POSIX
tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/eabi.h rs6000/eabialtivec.h"
- tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
+ tmake_file="rs6000/t-ppcendian rs6000/t-ppccomm"
;;
powerpc-*-eabi*)
xm_defines=POSIX
@@ -2884,6 +2159,12 @@ powerpc-wrs-vxworks*)
tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
thread_file='vxworks'
;;
+powerpc-wrs-windiss*)
+ xm_defines=POSIX
+ tm_file="${tm_file} elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/windiss.h"
+ tmake_file="rs6000/t-ppcgas rs6000/t-ppccomm"
+ thread_file=""
+ ;;
powerpcle-wrs-vxworks*)
xm_defines=POSIX
tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/sysv4le.h rs6000/vxppc.h"
@@ -2913,14 +2194,12 @@ powerpcle-*-eabi*)
rs6000-ibm-aix3.[01]*)
xm_defines=POSIX
tm_file="${tm_file} rs6000/aix.h rs6000/aix31.h rs6000/xcoff.h"
- float_format=none
use_collect2=yes
;;
rs6000-ibm-aix3.2.[456789]* | powerpc-ibm-aix3.2.[456789]*)
xm_defines=POSIX
tm_file="${tm_file} rs6000/aix.h rs6000/aix3newas.h rs6000/xcoff.h"
tmake_file=rs6000/t-newas
- float_format=none
use_collect2=yes
extra_headers=
;;
@@ -2928,7 +2207,6 @@ rs6000-ibm-aix4.[12]* | powerpc-ibm-aix4.[12]*)
xm_defines=POSIX
tm_file="${tm_file} rs6000/aix.h rs6000/aix41.h rs6000/xcoff.h"
tmake_file=rs6000/t-newas
- float_format=none
use_collect2=yes
extra_headers=
;;
@@ -2936,16 +2214,22 @@ rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
xm_defines=POSIX
tm_file="${tm_file} rs6000/aix.h rs6000/aix43.h rs6000/xcoff.h"
tmake_file=rs6000/t-aix43
- float_format=none
use_collect2=yes
thread_file='aix'
extra_headers=
;;
-rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*)
+rs6000-ibm-aix5.1.* | powerpc-ibm-aix5.1.*)
xm_defines=POSIX
tm_file="${tm_file} rs6000/aix.h rs6000/aix51.h rs6000/xcoff.h"
tmake_file=rs6000/t-aix43
- float_format=none
+ use_collect2=yes
+ thread_file='aix'
+ extra_headers=
+ ;;
+rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*)
+ xm_defines=POSIX
+ tm_file="${tm_file} rs6000/aix.h rs6000/aix52.h rs6000/xcoff.h"
+ tmake_file=rs6000/t-aix52
use_collect2=yes
thread_file='aix'
extra_headers=
@@ -2953,13 +2237,11 @@ rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*)
rs6000-ibm-aix*)
xm_defines=POSIX
tm_file="${tm_file} rs6000/aix.h rs6000/xcoff.h"
- float_format=none
use_collect2=yes
;;
rs6000-bull-bosx)
xm_defines=POSIX
tm_file="${tm_file} rs6000/aix.h rs6000/xcoff.h"
- float_format=none
use_collect2=yes
;;
rs6000-*-mach*)
@@ -2974,37 +2256,45 @@ rs6000-*-lynxos*)
;;
s390-*-linux*)
tm_file="s390/s390.h dbxelf.h elfos.h svr4.h linux.h s390/linux.h"
- tmake_file="t-slibgcc-elf-ver t-linux s390/t-linux"
- extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o"
+ tmake_file="t-slibgcc-elf-ver t-linux s390/t-crtstuff"
;;
s390x-*-linux*)
tm_file="s390/s390x.h s390/s390.h dbxelf.h elfos.h svr4.h linux.h s390/linux.h"
tm_p_file=s390/s390-protos.h
md_file=s390/s390.md
+ extra_modes=s390/s390-modes.def
out_file=s390/s390.c
- tmake_file="t-slibgcc-elf-ver t-linux s390/t-linux s390/t-linux64"
- extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o"
+ tmake_file="t-slibgcc-elf-ver t-linux s390/t-crtstuff s390/t-linux64"
;;
-sh-*-elf*)
+sh-*-elf* | sh[2346l]*-*-elf*)
tmake_file="sh/t-sh sh/t-elf"
- tm_file="${tm_file} sh/elf.h"
- float_format=sh
- ;;
-sh64-*-elf*)
- tmake_file="sh/t-sh sh/t-elf sh/t-sh64"
- tm_file="${tm_file} sh/sh.h sh/elf.h sh/sh64.h"
- float_format=sh
- extra_headers="../../config/sh/shmedia.h ../../config/sh/ushmedia.h ../../config/sh/sshmedia.h"
- # Not strictly necessary to check this, but a good idea anyway.
- if test $machine = $target; then
- target_requires_64bit_host_wide_int=yes
- fi
+ case $machine in
+ shl* | sh64l*)
+ tm_file="sh/little.h ${tm_file}"
+ tmake_file="${tmake_file} sh/t-le"
+ ;;
+ esac
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sh/embed-elf.h"
+ case $machine in
+ sh64*)
+ tmake_file="${tmake_file} sh/t-sh64"
+ tm_file="${tm_file} sh/sh64.h"
+ extra_headers="shmedia.h ushmedia.h sshmedia.h"
+ ;;
+ sh4_single*) target_cpu_default="SELECT_SH4_SINGLE" ;;
+ sh4*) target_cpu_default="SELECT_SH4" ;;
+ sh3e*) target_cpu_default="SELECT_SH3E" ;;
+ sh3*) target_cpu_default="SELECT_SH3" ;;
+ sh2*) target_cpu_default="SELECT_SH2" ;;
+ esac
+ case $machine in
+ sh[234]*) tmake_file="${tmake_file} sh/t-monolib" ;;
+ esac
;;
sh-*-rtemself*)
xm_defines=POSIX
tmake_file="sh/t-sh sh/t-elf t-rtems"
- tm_file="${tm_file} sh/elf.h sh/rtemself.h rtems.h"
- float_format=sh
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sh/embed-elf.h sh/rtemself.h rtems.h"
if test x$enable_threads = xyes; then
thread_file='rtems'
fi
@@ -3012,27 +2302,80 @@ sh-*-rtemself*)
sh-*-rtems*)
xm_defines=POSIX
tmake_file="sh/t-sh t-rtems"
- tm_file="${tm_file} sh/rtems.h rtems.h"
- float_format=sh
+ tm_file="${tm_file} sh/coff.h sh/rtems.h rtems.h"
if test x$enable_threads = xyes; then
thread_file='rtems'
fi
;;
-sh-*-linux*)
- tm_file="${tm_file} sh/elf.h sh/linux.h"
+sh-*-linux* | sh[2346lbe]*-*-linux*)
tmake_file="sh/t-sh sh/t-elf sh/t-linux"
+ case $machine in
+ sh*be-*-* | sh*eb-*-*) ;;
+ *)
+ tm_file="sh/little.h ${tm_file}"
+ tmake_file="${tmake_file} sh/t-le"
+ ;;
+ esac
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sh/elf.h sh/linux.h"
gas=yes gnu_ld=yes
- float_format=sh
+ case $machine in
+ sh64*)
+ tmake_file="${tmake_file} sh/t-sh64"
+ tm_file="${tm_file} sh/sh64.h"
+ extra_headers="shmedia.h ushmedia.h sshmedia.h"
+ ;;
+ sh4_single*) target_cpu_default="SELECT_SH4_SINGLE" ;;
+ sh4*) target_cpu_default="SELECT_SH4" ;;
+ sh3e[lb]e*) target_cpu_default="SELECT_SH3E" ;;
+ sh3e[lb]*) target_cpu_default="SELECT_SH3" ;;
+ sh3e*) target_cpu_default="SELECT_SH3E" ;;
+ sh3*) target_cpu_default="SELECT_SH3" ;;
+ sh2*) target_cpu_default="SELECT_SH2" ;;
+ esac
+ case $machine in
+ sh[234]*) tmake_file="${tmake_file} sh/t-monolib" ;;
+ esac
+ ;;
+sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
+ sh64-*-netbsd* | sh64l*-*-netbsd*)
+ tm_file="${tm_file} dbxelf.h elfos.h sh/elf.h netbsd.h netbsd-elf.h sh/netbsd-elf.h"
+ tmake_file="${tmake_file} sh/t-sh sh/t-elf"
+ case $machine in
+ sh*l*-*)
+ tm_file="sh/little.h ${tm_file}"
+ tmake_file="${tmake_file} sh/t-le"
+ ;;
+ *)
+ tmake_file="${tmake_file} sh/t-be"
+ ;;
+ esac
+ case $machine in
+ sh5*-*)
+ # SHmedia, 32-bit ABI
+ target_cpu_default="SH5_BIT|SH4_BIT|SH3E_BIT"
+ tmake_file="${tmake_file} sh/t-sh64 sh/t-netbsd-sh5"
+ ;;
+ sh64*-*)
+ # SHmedia, 64-bit ABI
+ target_cpu_default="SH5_BIT|SH4_BIT"
+ tmake_file="${tmake_file} sh/t-sh64 sh/t-netbsd-sh5 sh/t-netbsd-sh5-64"
+ ;;
+ *)
+ # SH3, software floating point
+ target_cpu_default="SH1_BIT|SH2_BIT|SH3_BIT"
+ tmake_file="${tmake_file} sh/t-netbsd"
+ ;;
+ esac
;;
sh-*-*)
- float_format=sh
+ tm_file="${tm_file} sh/coff.h"
;;
sparc-tti-*)
tm_file="${tm_file} sparc/pbd.h"
xm_defines=POSIX
;;
sparc64-wrs-vxworks*)
- tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/sol2.h sparc/elf.h sparc/biarch64.h gofast.h sparc/vxsparc64.h"
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sol2.h sparc/sol2.h sparc/elf.h sparc/biarch64.h gofast.h sparc/vxsparc64.h"
tmake_file="sparc/t-vxsparc64 sparc/t-crtfm"
use_collect2=yes
;;
@@ -3052,6 +2395,7 @@ sparc-*-netbsdelf*)
sparc-*-netbsd*)
tm_file="${tm_file} sparc/aout.h netbsd.h netbsd-aout.h sparc/netbsd.h"
tmake_file=t-netbsd
+ extra_parts=""
use_collect2=yes
;;
sparc-*-openbsd*)
@@ -3066,16 +2410,14 @@ sparc64-*-openbsd*)
xm_file=sparc/xm-sp64.h
gas=yes gnu_ld=yes
with_cpu=ultrasparc
- float_format=i128
;;
sparc-*-bsd*)
tm_file="${tm_file} sparc/bsd.h"
;;
sparc-*-chorusos*)
- tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/sol2.h sparc/elf.h chorus.h"
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sol2.h sparc/sol2.h sparc/elf.h chorus.h"
tmake_file="sparc/t-chorus-elf sparc/t-crtfm"
extra_parts="crti.o crtn.o crtbegin.o crtend.o"
- float_format=i64
case x${enable_threads} in
xyes | xpthreads | xposix)
thread_file='posix'
@@ -3083,29 +2425,23 @@ sparc-*-chorusos*)
esac
;;
sparc-*-elf*)
- tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/sol2.h sparc/elf.h"
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sol2.h sparc/sol2.h sparc/elf.h"
tmake_file="sparc/t-elf sparc/t-crtfm"
extra_parts="crti.o crtn.o crtbegin.o crtend.o"
- #float_format=i128
- float_format=i64
;;
-sparc-*-linux*aout*) # Sparc's running GNU/Linux, a.out
+sparc-*-linux*aout*) # SPARC's running GNU/Linux, a.out
tm_file="aoutos.h sparc/sparc.h sparc/aout.h sparc/linux-aout.h"
gnu_ld=yes
;;
-sparc-*-linux*libc1*) # Sparc's running GNU/Linux, libc5
+sparc-*-linux*libc1*) # SPARC's running GNU/Linux, libc5
tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/linux.h"
tmake_file="t-slibgcc-elf-ver t-linux t-linux-gnulibc1 sparc/t-crtfm"
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
gnu_ld=yes
- float_format=sparc
;;
-sparc-*-linux*) # Sparc's running GNU/Linux, libc6
+sparc-*-linux*) # SPARC's running GNU/Linux, libc6
tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/linux.h"
tmake_file="t-slibgcc-elf-ver t-linux sparc/t-crtfm"
- extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
- gnu_ld=yes
- float_format=sparc
;;
sparc-*-lynxos*)
if test x$gas = xyes
@@ -3116,27 +2452,21 @@ sparc-*-lynxos*)
fi
tmake_file=sparc/t-sunos41
;;
-sparc-*-rtemsaout*)
- xm_defines=POSIX
- tmake_file="sparc/t-sparcbare t-rtems"
- tm_file="${tm_file} aoutos.h sparc/aout.h sparc/rtems.h rtems.h"
- if test x$enable_threads = xyes; then
- thread_file='rtems'
- fi
+sparc-*-rtemsaout*) # would otherwise be caught by sparc-*-rtems*
+ echo "*** Configuration $machine not supported" 1>&2
+ exit 1
;;
-sparc-*-rtems*|sparc-*-rtemself*)
+sparc-*-rtems*)
xm_defines=POSIX
- tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/sol2.h sparc/elf.h sparc/rtemself.h rtems.h"
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sol2.h sparc/sol2.h sparc/elf.h sparc/rtemself.h rtems.h"
tmake_file="sparc/t-elf sparc/t-crtfm t-rtems"
extra_parts="crti.o crtn.o crtbegin.o crtend.o"
- #float_format=i128
- float_format=i64
if test x$enable_threads = xyes; then
thread_file='rtems'
fi
;;
sparc64-*-solaris2* | sparcv9-*-solaris2*)
- tm_file="sparc/biarch64.h ${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/sol2.h sparc/sol2-64.h sparc/sol2-bi.h"
+ tm_file="sparc/biarch64.h ${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sol2.h sparc/sol2.h sparc/sol2-64.h sparc/sol2-bi.h"
if test x$gnu_ld = xyes; then
tm_file="${tm_file} sparc/sol2-gld.h sparc/sol2-gld-bi.h"
fi
@@ -3151,7 +2481,6 @@ sparc64-*-solaris2* | sparcv9-*-solaris2*)
tmake_file="$tmake_file t-slibgcc-sld"
fi
extra_parts="crt1.o crti.o crtn.o gcrt1.o crtbegin.o crtend.o"
- float_format=i128
if test x${enable_threads} = x ; then
enable_threads=$have_pthread_h
if test x${enable_threads} = x ; then
@@ -3168,7 +2497,7 @@ sparc64-*-solaris2* | sparcv9-*-solaris2*)
;;
sparc-hal-solaris2*)
xm_defines=POSIX
- tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/sol2.h sparc/hal.h"
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sol2.h sparc/sol2.h sparc/hal.h"
tmake_file="sparc/t-halos sparc/t-sol2 sparc/t-crtfm"
if test x$gnu_ld = xyes; then
tm_file="${tm_file} sparc/sol2-gld.h"
@@ -3177,11 +2506,10 @@ sparc-hal-solaris2*)
tmake_file="$tmake_file t-slibgcc-sld"
fi
extra_parts="crt1.o crti.o crtn.o gmon.o crtbegin.o crtend.o"
- float_format=i128
thread_file='solaris'
;;
sparc-*-solaris2*)
- tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/sol2.h"
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sol2.h sparc/sol2.h"
if test x$gnu_ld = xyes; then
tm_file="${tm_file} sparc/sol2-gld.h"
fi
@@ -3192,6 +2520,11 @@ sparc-*-solaris2*)
tmake_file="$tmake_file t-slibgcc-sld"
fi
case $machine in
+ *-*-solaris2.[0-6] | *-*-solaris2.[0-6].*)
+ if test x$gnu_ld = xno; then
+ tm_file="${tm_file} sparc/sol26-sld.h"
+ fi
+ ;;
*-*-solaris2.[789])
tm_file="sparc/biarch64.h ${tm_file} sparc/sol2-bi.h"
if test x$gnu_ld = xyes; then
@@ -3203,16 +2536,8 @@ sparc-*-solaris2*)
tmake_file="$tmake_file sparc/t-sol2-64"
;;
esac
- case $machine in
- *-*-solaris2.[0-7] | *-*-solaris2.[0-7].*)
- if test x$gnu_ld = xno; then
- tm_file="${tm_file} sparc/sol27-sld.h"
- fi
- ;;
- esac
xm_defines=POSIX
extra_parts="crt1.o crti.o crtn.o gcrt1.o gmon.o crtbegin.o crtend.o"
- float_format=i128
if test x${enable_threads} = x; then
enable_threads=$have_pthread_h
if test x${enable_threads} = x; then
@@ -3267,7 +2592,7 @@ sparclite-*-aout*)
tmake_file=sparc/t-sparclite
;;
sparclite-*-elf*)
- tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/sol2.h sparc/elf.h gofast.h sparc/liteelf.h"
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sol2.h sparc/sol2.h sparc/elf.h gofast.h sparc/liteelf.h"
tmake_file="sparc/t-sparclite sparc/t-crtfm"
extra_parts="crtbegin.o crtend.o"
;;
@@ -3276,7 +2601,7 @@ sparc86x-*-aout*)
tmake_file=sparc/t-sp86x
;;
sparc86x-*-elf*)
- tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/sol2.h sparc/elf.h gofast.h sparc/sp86x-elf.h"
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sol2.h sparc/sol2.h sparc/elf.h gofast.h sparc/sp86x-elf.h"
tmake_file="sparc/t-sp86x sparc/t-crtfm"
extra_parts="crtbegin.o crtend.o"
;;
@@ -3284,7 +2609,7 @@ sparc64-*-aout*)
tm_file="sparc/sparc.h aoutos.h sparc/aout.h sparc/sp64-aout.h"
;;
sparc64-*-elf*)
- tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/sol2.h sparc/sp64-elf.h"
+ tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sol2.h sparc/sol2.h sparc/sp64-elf.h"
tmake_file="${tmake_file} sparc/t-crtfm"
extra_parts="crtbegin.o crtend.o"
;;
@@ -3298,36 +2623,35 @@ sparc64-*-freebsd*|ultrasparc-*-freebsd*)
*) echo "$with_cpu not supported for freebsd target"; exit 1 ;;
esac
;;
-sparc64-*-linux*) # 64-bit Sparc's running GNU/Linux
+sparc64-*-linux*) # 64-bit SPARC's running GNU/Linux
tmake_file="t-slibgcc-elf-ver t-linux sparc/t-linux64 sparc/t-crtfm"
tm_file="sparc/biarch64.h ${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/linux64.h"
- extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
- gnu_ld=yes
- float_format=sparc
;;
sparc64-*-netbsd*)
tmake_file="${tmake_file} sparc/t-netbsd64"
tm_file="sparc/biarch64.h ${tm_file}"
tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h netbsd.h netbsd-elf.h sparc/netbsd-elf.h"
- float_format=sparc
;;
strongarm-*-elf*)
tm_file="arm/strongarm-elf.h dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/aout.h arm/arm.h"
tmake_file=arm/t-strongarm-elf
out_file=arm/arm.c
md_file=arm/arm.md
+ extra_modes=arm/arm-modes.def
;;
strongarm-*-coff*)
tm_file="arm/semi.h arm/aout.h arm/coff.h arm/strongarm-coff.h arm/arm.h"
tmake_file=arm/t-strongarm-coff
out_file=arm/arm.c
md_file=arm/arm.md
+ extra_modes=arm/arm-modes.def
;;
strongarm-*-pe)
tm_file="arm/semi.h arm/aout.h arm/coff.h arm/strongarm-coff.h arm/arm.h arm/pe.h arm/strongarm-pe.h"
tmake_file=arm/t-strongarm-pe
out_file=arm/arm.c
md_file=arm/arm.md
+ extra_modes=arm/arm-modes.def
extra_objs=pe.o
;;
thumb*-*-*)
@@ -3348,6 +2672,21 @@ v850-*-rtems*)
c_target_objs="v850-c.o"
cxx_target_objs="v850-c.o"
;;
+v850e-*-*)
+ target_cpu_default="TARGET_CPU_v850e"
+ tm_file="dbxelf.h elfos.h svr4.h v850/v850.h"
+ tm_p_file=v850/v850-protos.h
+ tmake_file=v850/t-v850
+ md_file=v850/v850.md
+ out_file=v850/v850.c
+ if test x$stabs = xyes
+ then
+ tm_file="${tm_file} dbx.h"
+ fi
+ use_collect2=no
+ c_target_objs="v850-c.o"
+ cxx_target_objs="v850-c.o"
+ ;;
v850-*-*)
target_cpu_default="TARGET_CPU_generic"
tm_file="dbxelf.h elfos.h svr4.h ${tm_file}"
@@ -3361,55 +2700,49 @@ v850-*-*)
cxx_target_objs="v850-c.o"
;;
vax-*-bsd*) # VAXen running BSD
+ tm_file="${tm_file} vax/bsd.h"
use_collect2=yes
- float_format=vax
;;
vax-*-sysv*) # VAXen running system V
tm_file="${tm_file} vax/vaxv.h"
xm_defines=POSIX
- float_format=vax
;;
vax-*-netbsdelf*)
- echo "GCC does not yet support the ${machine} target"; exit 1
+ tm_file="${tm_file} elfos.h netbsd.h netbsd-elf.h vax/elf.h vax/netbsd-elf.h"
+ float_format=vax
;;
vax-*-netbsd*)
tm_file="${tm_file} netbsd.h netbsd-aout.h vax/netbsd.h"
tmake_file=t-netbsd
- float_format=vax
+ extra_parts=""
use_collect2=yes
;;
vax-*-openbsd*)
tm_file="vax/vax.h vax/openbsd1.h openbsd.h ${tm_file}"
- float_format=vax
use_collect2=yes
;;
vax-*-ultrix*) # VAXen running ultrix
tm_file="${tm_file} vax/ultrix.h"
- float_format=vax
;;
vax-*-vms*) # VAXen running VMS
xm_file=vax/xm-vms.h
tm_file=vax/vms.h
- float_format=vax
;;
vax-*-*) # VAX default entry
- float_format=vax
- ;;
-we32k-att-sysv*)
- xm_defines=POSIX
- use_collect2=yes
;;
xscale-*-elf)
tm_file="arm/xscale-elf.h dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/aout.h arm/arm.h"
tmake_file=arm/t-xscale-elf
out_file=arm/arm.c
md_file=arm/arm.md
+ extra_modes=arm/arm-modes.def
;;
xscale-*-coff)
tm_file="arm/semi.h arm/aout.h arm/coff.h arm/xscale-coff.h arm/arm.h"
tmake_file=arm/t-xscale-coff
out_file=arm/arm.c
md_file=arm/arm.md
+ extra_modes=arm/arm-modes.def
;;
xstormy16-*-elf)
# For historical reasons, the target files omit the 'x'.
@@ -3429,12 +2762,10 @@ xtensa-*-elf*)
;;
xtensa-*-linux*)
tm_file="${tm_file} dbxelf.h elfos.h svr4.h linux.h xtensa/linux.h"
- tmake_file="t-linux xtensa/t-xtensa"
- extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
- gas=yes gnu_ld=yes
+ tmake_file="t-slibgcc-elf-ver t-linux xtensa/t-xtensa"
;;
*)
- echo "Configuration $machine not supported" 1>&2
+ echo "*** Configuration $machine not supported" 1>&2
exit 1
;;
esac
@@ -3464,7 +2795,7 @@ i586-*-*)
k6-*)
target_cpu_default2=TARGET_CPU_DEFAULT_k6
;;
- pentium_mmx-*)
+ pentium_mmx-*|winchip_c6-*|winchip2-*|c3-*)
target_cpu_default2=TARGET_CPU_DEFAULT_pentium_mmx
;;
*)
@@ -3566,23 +2897,49 @@ hppa*-*-* | parisc*-*-*)
then
target_cpu_default2="MASK_GAS|MASK_JUMP_IN_DELAY"
fi
+ case $machine in
+ hppa1* | parisc1*)
+ tm_defines="TARGET_SCHED_DEFAULT=\\\"7100LC\\\""
+ ;;
+ esac
;;
-
-mips*-*-ecoff* | mips*-*-elf*)
- if test x$gas = xyes
- then
- if test x$gnu_ld = xyes
+mips*-*-*)
+ case $machine in
+ mips*-*-ecoff* | mips*-*-elf*)
+ if test x$gas = xyes
+ then
+ if test x$gnu_ld = xyes
+ then
+ target_cpu_default2="MASK_GAS|MASK_SPLIT_ADDR"
+ else
+ target_cpu_default2="MASK_GAS"
+ fi
+ fi
+ ;;
+ mips*-*-*)
+ if test x$gas = xyes
then
- target_cpu_default2="MASK_GAS|MASK_SPLIT_ADDR"
- else
target_cpu_default2="MASK_GAS"
fi
- fi
- ;;
-mips*-*-*)
- if test x$gas = xyes
+ ;;
+ esac
+ case $machine in
+ mips*el-*-*)
+ tm_defines="TARGET_ENDIAN_DEFAULT=0 $tm_defines"
+ ;;
+ esac
+ case $tm_file in
+ *mips/elf.h* | *mips/elf64.h*)
+ tm_defines="OBJECT_FORMAT_ELF $tm_defines"
+ ;;
+ esac
+ if test "x$enable_gofast" = xyes
then
- target_cpu_default2="MASK_GAS"
+ tm_defines="INIT_SUBTARGET_OPTABS=INIT_GOFAST_OPTABS $tm_defines"
+ tm_file="gofast.h $tm_file"
+ tmake_file="mips/t-gofast $tmake_file"
+ else
+ tmake_file="mips/t-mips $tmake_file"
fi
;;
powerpc*-*-* | rs6000-*-*)
@@ -3603,7 +2960,6 @@ powerpc*-*-* | rs6000-*-*)
x401 | x403 | x405 | xec603e | x801 | x821 | x823 | x860)
target_cpu_default2="\\\"$with_cpu\\\""
- tm_file="$tm_file rs6000/softfloat.h"
;;
xyes | xno)
@@ -3619,6 +2975,9 @@ powerpc*-*-* | rs6000-*-*)
fi
;;
esac
+ c_target_objs="${c_target_objs} rs6000-c.o"
+ cxx_target_objs="${cxx_target_objs} rs6000-c.o"
+ tmake_file="${tmake_file} rs6000/t-rs6000-c-rule"
;;
sparc*-*-*)
case ".$with_cpu" in
@@ -3637,6 +2996,22 @@ sparc*-*-*)
;;
esac
;;
+v850*-*-*)
+ case "x$with_cpu" in
+ x)
+ ;;
+ xv850e)
+ target_cpu_default2="TARGET_CPU_$with_cpu"
+ ;;
+ *)
+ if test x$pass2done = xyes
+ then
+ echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2
+ exit 1
+ fi
+ ;;
+ esac
+ ;;
esac
if test "$target_cpu_default2" != ""
diff --git a/contrib/gcc/config.in b/contrib/gcc/config.in
index ec5be95..bc52d36 100644
--- a/contrib/gcc/config.in
+++ b/contrib/gcc/config.in
@@ -1,4 +1,4 @@
-/* config.in. Generated automatically from configure.in by autoheader. */
+/* config.in. Generated automatically from configure.in by autoheader 2.13. */
/* Define if using alloca.c. */
#undef C_ALLOCA
@@ -93,6 +93,9 @@
/* Define if you have the __argz_stringify function. */
#undef HAVE___ARGZ_STRINGIFY
+/* Define if you have the alphasort function. */
+#undef HAVE_ALPHASORT
+
/* Define if you have the atoll function. */
#undef HAVE_ATOLL
@@ -138,15 +141,15 @@
/* Define if you have the getgid function. */
#undef HAVE_GETGID
-/* Define if you have the getpagesize function. */
-#undef HAVE_GETPAGESIZE
-
/* Define if you have the getrlimit function. */
#undef HAVE_GETRLIMIT
/* Define if you have the getrusage function. */
#undef HAVE_GETRUSAGE
+/* Define if you have the gettimeofday function. */
+#undef HAVE_GETTIMEOFDAY
+
/* Define if you have the getuid function. */
#undef HAVE_GETUID
@@ -159,6 +162,9 @@
/* Define if you have the mempcpy function. */
#undef HAVE_MEMPCPY
+/* Define if you have the mmap function. */
+#undef HAVE_MMAP
+
/* Define if you have the munmap function. */
#undef HAVE_MUNMAP
@@ -171,6 +177,9 @@
/* Define if you have the putenv function. */
#undef HAVE_PUTENV
+/* Define if you have the scandir function. */
+#undef HAVE_SCANDIR
+
/* Define if you have the setenv function. */
#undef HAVE_SETENV
@@ -246,6 +255,9 @@
/* Define if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H
+/* Define if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
/* Define if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
@@ -273,39 +285,6 @@
/* Define to enable the use of a default assembler. */
#undef DEFAULT_ASSEMBLER
-/* Define if you want more run-time sanity checks. This one gets a grab
- bag of miscellaneous but relatively cheap checks. */
-#undef ENABLE_CHECKING
-
-/* Define if you want all operations on trees (the basic data
- structure of the front ends) to be checked for dynamic type safety
- at runtime. This is moderately expensive. */
-#undef ENABLE_TREE_CHECKING
-
-/* Define if you want all operations on RTL (the basic data structure
- of the optimizer and back end) to be checked for dynamic type safety
- at runtime. This is quite expensive. */
-#undef ENABLE_RTL_CHECKING
-
-/* Define if you want the garbage collector to do object poisoning and
- other memory allocation checks. This is quite expensive. */
-#undef ENABLE_GC_CHECKING
-
-/* Define if you want the garbage collector to operate in maximally
- paranoid mode, validating the entire heap and collecting garbage at
- every opportunity. This is extremely expensive. */
-#undef ENABLE_GC_ALWAYS_COLLECT
-
-/* Define if you want to use __cxa_atexit, rather than atexit, to
- register C++ destructors for local statics and global objects.
- This is essential for fully standards-compliant handling of
- destructors, but requires __cxa_atexit in libc. */
-#undef DEFAULT_USE_CXA_ATEXIT
-
-/* Define if you want the C and C++ compilers to support multibyte
- character sets for source code. */
-#undef MULTIBYTE_CHARS
-
/* Define if your compiler understands volatile. */
#undef HAVE_VOLATILE
@@ -339,6 +318,48 @@
/* Define if the host execution character set is EBCDIC. */
#undef HOST_EBCDIC
+/* Define if you want more run-time sanity checks. This one gets a grab
+ bag of miscellaneous but relatively cheap checks. */
+#undef ENABLE_CHECKING
+
+/* Define if you want all operations on trees (the basic data
+ structure of the front ends) to be checked for dynamic type safety
+ at runtime. This is moderately expensive. */
+#undef ENABLE_TREE_CHECKING
+
+/* Define if you want all operations on RTL (the basic data structure
+ of the optimizer and back end) to be checked for dynamic type safety
+ at runtime. This is quite expensive. */
+#undef ENABLE_RTL_CHECKING
+
+/* Define if you want RTL flag accesses to be checked against the RTL
+ codes that are supported for each access macro. This is relatively
+ cheap. */
+#undef ENABLE_RTL_FLAG_CHECKING
+
+/* Define if you want the garbage collector to do object poisoning and
+ other memory allocation checks. This is quite expensive. */
+#undef ENABLE_GC_CHECKING
+
+/* Define if you want the garbage collector to operate in maximally
+ paranoid mode, validating the entire heap and collecting garbage at
+ every opportunity. This is extremely expensive. */
+#undef ENABLE_GC_ALWAYS_COLLECT
+
+/* Define if you want to run subprograms and generated programs
+ through valgrind (a memory checker). This is extremely expensive. */
+#undef ENABLE_VALGRIND_CHECKING
+
+/* Define if you want to use __cxa_atexit, rather than atexit, to
+ register C++ destructors for local statics and global objects.
+ This is essential for fully standards-compliant handling of
+ destructors, but requires __cxa_atexit in libc. */
+#undef DEFAULT_USE_CXA_ATEXIT
+
+/* Define if you want the C and C++ compilers to support multibyte
+ character sets for source code. */
+#undef MULTIBYTE_CHARS
+
/* Always define this when using the GNU C Library */
#undef _GNU_SOURCE
@@ -372,15 +393,15 @@
/* Define if printf supports %p. */
#undef HAVE_PRINTF_PTR
-/* Define if mmap can get us zeroed pages from /dev/zero. */
+/* Define if read-only mmap of a plain file works. */
+#undef HAVE_MMAP_FILE
+
+/* Define if mmap of /dev/zero works. */
#undef HAVE_MMAP_DEV_ZERO
-/* Define if mmap can get us zeroed pages using MAP_ANON(YMOUS). */
+/* Define if mmap with MAP_ANON(YMOUS) works. */
#undef HAVE_MMAP_ANON
-/* Define if read-only mmap of a plain file works. */
-#undef HAVE_MMAP_FILE
-
/* Define if you have the iconv() function. */
#undef HAVE_ICONV
@@ -430,6 +451,9 @@
#undef HAVE_DECL_ERRNO
/* Define to 1 if we found this declaration otherwise define to 0. */
+#undef HAVE_DECL_VASPRINTF
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
#undef HAVE_DECL_MALLOC
/* Define to 1 if we found this declaration otherwise define to 0. */
@@ -459,6 +483,9 @@
/* Define to 1 if we found this declaration otherwise define to 0. */
#undef HAVE_DECL_GETRUSAGE
+/* Define to `long' if <sys/resource.h> doesn't define. */
+#undef rlim_t
+
/* Define to 1 if we found this declaration otherwise define to 0. */
#undef HAVE_DECL_TIMES
@@ -468,9 +495,20 @@
/* Define if <time.h> defines clock_t. */
#undef HAVE_CLOCK_T
+/* Define .init_array/.fini_array sections are available and working. */
+#undef HAVE_INITFINI_ARRAY
+
/* Define if host mkdir takes a single argument. */
#undef MKDIR_TAKES_ONE_ARG
+/* Define to the name of a file containing a list of extra machine modes
+ for this architecture. */
+#undef EXTRA_MODES_FILE
+
+/* Define if the target architecture needs extra machine modes to represent
+ the results of comparisons. */
+#undef EXTRA_CC_MODES
+
/* Define if you have the iconv() function. */
#undef HAVE_ICONV
@@ -523,6 +561,9 @@
/* Define if your assembler supports marking sections with SHF_MERGE flag. */
#undef HAVE_GAS_SHF_MERGE
+/* Define if your assembler supports thread-local storage. */
+#undef HAVE_AS_TLS
+
/* Define if your assembler supports explicit relocations. */
#undef HAVE_AS_EXPLICIT_RELOCS
@@ -544,6 +585,9 @@
/* Define true if the assembler supports '.long foo@GOTOFF'. */
#undef HAVE_AS_GOTOFF_IN_DATA
+/* Define if your assembler supports ltoffx and ldxmov relocations. */
+#undef HAVE_AS_LTOFFX_LDXMOV_RELOCS
+
/* Define if your assembler supports dwarf2 .file/.loc directives,
and preserves file table indices exactly as given. */
#undef HAVE_AS_DWARF2_DEBUG_LINE
@@ -554,12 +598,22 @@
/* Define if your assembler supports the --gstabs option. */
#undef HAVE_AS_GSTABS_DEBUG_FLAG
+/* Define if your linker links a mix of read-only
+ and read-write sections into a read-write section. */
+#undef HAVE_LD_RO_RW_SECTION_MIXING
+
/* Define if your linker supports --eh-frame-hdr option. */
#undef HAVE_LD_EH_FRAME_HDR
+/* Define if your MIPS libgloss linker scripts consistently include STARTUP directives. */
+#undef HAVE_MIPS_LIBGLOSS_STARTUP_DIRECTIVES
+
/* Define 0/1 to force the choice for exception handling model. */
#undef CONFIG_SJLJ_EXCEPTIONS
+/* Define if gcc should use -lunwind. */
+#undef USE_LIBUNWIND_EXCEPTIONS
+
/* Bison unconditionally undefines `const' if neither `__STDC__' nor
__cplusplus are defined. That's a problem since we use `const' in
diff --git a/contrib/gcc/config/alpha/alpha-interix.h b/contrib/gcc/config/alpha/alpha-interix.h
index 4dc2186..3f1580d 100644
--- a/contrib/gcc/config/alpha/alpha-interix.h
+++ b/contrib/gcc/config/alpha/alpha-interix.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler, for DEC Alpha
running Windows/NT.
- Copyright (C) 1995, 1996, 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1999, 2000, 2002 Free Software Foundation, Inc.
Donn Terry, Softway Systems, Inc.
From code
@@ -25,15 +25,18 @@ Boston, MA 02111-1307, USA. */
/* cpp handles __STDC__ */
/* The three "Alpha" defines on the first such line are from the CLAXP spec */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES " \
- -D__INTERIX \
- -D__OPENNT \
- -D__Alpha_AXP -D_M_ALPHA -D_ALPHA_ \
- -D__alpha -D__alpha__\
- -D__stdcall= \
- -D__cdecl= \
- -Asystem=unix -Asystem=interix -Acpu=alpha -Amachine=alpha"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__INTERIX"); \
+ builtin_define ("__OPENNT"); \
+ builtin_define ("__Alpha_AXP"); \
+ builtin_define ("_M_ALPHA"); \
+ builtin_define ("_ALPHA_"); \
+ builtin_define ("__stdcall="); \
+ builtin_define ("__cdecl="); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=interix"); \
+ } while (0)
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC "\
@@ -64,17 +67,9 @@ Boston, MA 02111-1307, USA. */
/* The following are needed for C++, but also needed for profiling */
-/* Support const sections and the ctors and dtors sections for g++.
- Note that there appears to be two different ways to support const
- sections at the moment. You can either #define the symbol
- READONLY_DATA_SECTION (giving it some code which switches to the
- readonly data section) or else you can #define the symbols
- EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
- SELECT_RTX_SECTION. We do both here just to be on the safe side. */
+/* Support const sections and the ctors and dtors sections for g++. */
-#define USE_CONST_SECTION 1
-
-#define CONST_SECTION_ASM_OP "\t.rdata"
+#define READONLY_DATA_SECTION_ASM_OP "\t.rdata"
/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
@@ -94,38 +89,6 @@ Boston, MA 02111-1307, USA. */
#define CTORS_SECTION_ASM_OP "\t.ctors"
#define DTORS_SECTION_ASM_OP "\t.dtors"
-/* A default list of other sections which we might be "in" at any given
- time. For targets that use additional sections (e.g. .tdesc) you
- should override this definition in the target-specific file which
- includes this file. */
-
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const
-
-/* A default list of extra section function definitions. For targets
- that use additional sections (e.g. .tdesc) you should override this
- definition in the target-specific file which includes this file. */
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- CONST_SECTION_FUNCTION
-
-#undef READONLY_DATA_SECTION
-#define READONLY_DATA_SECTION() const_section ()
-
-#define CONST_SECTION_FUNCTION \
-void \
-const_section () \
-{ \
- if (!USE_CONST_SECTION) \
- text_section(); \
- else if (in_section != in_const) \
- { \
- fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
- in_section = in_const; \
- } \
-}
-
/* The linker will take care of this, and having them causes problems with
ld -r (specifically -rU). */
#define CTOR_LISTS_DEFINED_EXTERNALLY 1
@@ -185,15 +148,3 @@ while (0)
fprintf (FILE, "\t.globl\t__fltused\n"); \
ASM_OUTPUT_SOURCE_FILENAME (FILE, main_input_filename); \
}
-
-/* The current Interix assembler (consistent with the DEC documentation)
- uses a=b NOT .set a,b; .set is for assembler options. */
-#undef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
-#define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO) \
- do { \
- assemble_name (FILE, SY); \
- fputc ('=', FILE); \
- assemble_name (FILE, HI); \
- fputc ('-', FILE); \
- assemble_name (FILE, LO); \
- } while (0)
diff --git a/contrib/gcc/config/alpha/alpha-protos.h b/contrib/gcc/config/alpha/alpha-protos.h
index c6fdd04..fe4943b 100644
--- a/contrib/gcc/config/alpha/alpha-protos.h
+++ b/contrib/gcc/config/alpha/alpha-protos.h
@@ -1,5 +1,5 @@
/* Prototypes for alpha.c functions used in the md file & elsewhere.
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -34,10 +34,10 @@ extern void alpha_expand_epilogue PARAMS ((void));
extern void alpha_output_filename PARAMS ((FILE *, const char *));
extern void alpha_output_lineno PARAMS ((FILE *, int));
-#ifdef RTX_CODE
extern int reg_or_0_operand PARAMS ((rtx, enum machine_mode));
extern int reg_or_6bit_operand PARAMS ((rtx, enum machine_mode));
extern int reg_or_8bit_operand PARAMS ((rtx, enum machine_mode));
+extern int reg_or_const_int_operand PARAMS ((rtx, enum machine_mode));
extern int cint8_operand PARAMS ((rtx, enum machine_mode));
extern int add_operand PARAMS ((rtx, enum machine_mode));
extern int sext_add_operand PARAMS ((rtx, enum machine_mode));
@@ -47,8 +47,7 @@ extern int or_operand PARAMS ((rtx, enum machine_mode));
extern int mode_width_operand PARAMS ((rtx, enum machine_mode));
extern int mode_mask_operand PARAMS ((rtx, enum machine_mode));
extern int mul8_operand PARAMS ((rtx, enum machine_mode));
-extern int fp0_operand PARAMS ((rtx, enum machine_mode));
-extern int reg_or_fp0_operand PARAMS ((rtx, enum machine_mode));
+extern int const0_operand PARAMS ((rtx, enum machine_mode));
extern int hard_fp_register_operand PARAMS ((rtx, enum machine_mode));
extern int hard_int_register_operand PARAMS ((rtx, enum machine_mode));
extern int reg_or_cint_operand PARAMS ((rtx, enum machine_mode));
@@ -61,6 +60,12 @@ extern int local_symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int small_symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int some_small_symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int global_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int dtp16_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int dtp32_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int gotdtp_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int tp16_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int tp32_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int gottp_symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int call_operand PARAMS ((rtx, enum machine_mode));
extern int symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int alpha_comparison_operator PARAMS ((rtx, enum machine_mode));
@@ -108,13 +113,7 @@ extern rtx alpha_emit_set_long_const PARAMS ((rtx, HOST_WIDE_INT,
extern bool alpha_expand_mov PARAMS ((enum machine_mode, rtx *));
extern bool alpha_expand_mov_nobwx PARAMS ((enum machine_mode, rtx *));
extern void alpha_emit_floatuns PARAMS ((rtx[]));
-extern rtx alpha_emit_conditional_branch PARAMS ((enum rtx_code));
-extern rtx alpha_emit_setcc PARAMS ((enum rtx_code));
extern rtx alpha_emit_conditional_move PARAMS ((rtx, enum machine_mode));
-extern int alpha_split_conditional_move PARAMS ((enum rtx_code, rtx, rtx,
- rtx, rtx));
-extern void alpha_emit_xfloating_arith PARAMS ((enum rtx_code, rtx[]));
-extern void alpha_emit_xfloating_cvt PARAMS ((enum rtx_code, rtx[]));
extern void alpha_split_tfmode_pair PARAMS ((rtx[]));
extern void alpha_split_tfmode_frobsign PARAMS ((rtx[],
rtx (*)(rtx, rtx, rtx)));
@@ -124,61 +123,55 @@ extern void alpha_expand_unaligned_store PARAMS ((rtx, rtx, HOST_WIDE_INT,
HOST_WIDE_INT));
extern int alpha_expand_block_move PARAMS ((rtx []));
extern int alpha_expand_block_clear PARAMS ((rtx []));
+extern rtx alpha_expand_zap_mask PARAMS ((HOST_WIDE_INT));
+extern void alpha_expand_builtin_vector_binop PARAMS ((rtx (*)(rtx, rtx, rtx),
+ enum machine_mode,
+ rtx, rtx, rtx));
extern rtx alpha_return_addr PARAMS ((int, rtx));
extern rtx alpha_gp_save_rtx PARAMS ((void));
extern void print_operand PARAMS ((FILE *, rtx, int));
extern void print_operand_address PARAMS ((FILE *, rtx));
extern void alpha_initialize_trampoline PARAMS ((rtx, rtx, rtx, int, int, int));
extern void alpha_reorg PARAMS ((rtx));
-#endif /* RTX_CODE */
+
+extern tree alpha_build_va_list PARAMS ((void));
+extern void alpha_va_start PARAMS ((tree, rtx));
+extern rtx alpha_va_arg PARAMS ((tree, tree));
+extern rtx function_arg PARAMS ((CUMULATIVE_ARGS, enum machine_mode,
+ tree, int));
+extern void alpha_start_function PARAMS ((FILE *, const char *, tree));
+extern void alpha_end_function PARAMS ((FILE *, const char *, tree));
+
+extern int alpha_find_lo_sum_using_gp PARAMS ((rtx));
#ifdef REAL_VALUE_TYPE
extern int check_float_value PARAMS ((enum machine_mode,
- REAL_VALUE_TYPE *, int));
+ REAL_VALUE_TYPE *, int));
#endif
-#if TARGET_ABI_OPEN_VMS
-#ifdef HAVE_MACHINE_MODES
-extern enum avms_arg_type alpha_arg_type PARAMS ((enum machine_mode));
-#endif
#ifdef RTX_CODE
-extern rtx alpha_arg_info_reg_val PARAMS ((CUMULATIVE_ARGS));
-#endif
-#ifdef BUFSIZ
-extern void alpha_write_linkage PARAMS ((FILE *));
+extern rtx alpha_emit_conditional_branch PARAMS ((enum rtx_code));
+extern rtx alpha_emit_setcc PARAMS ((enum rtx_code));
+extern int alpha_split_conditional_move PARAMS ((enum rtx_code, rtx, rtx,
+ rtx, rtx));
+extern void alpha_emit_xfloating_arith PARAMS ((enum rtx_code, rtx[]));
+extern void alpha_emit_xfloating_cvt PARAMS ((enum rtx_code, rtx[]));
#endif
-#endif /* TARGET_ABI_OPEN_VMS */
-#ifdef RTX_CODE
extern rtx alpha_need_linkage PARAMS ((const char *, int));
-#endif
+extern rtx alpha_use_linkage PARAMS ((rtx, tree, int, int));
-#ifdef TREE_CODE
-extern tree alpha_build_va_list PARAMS ((void));
-#ifdef RTX_CODE
-extern void alpha_va_start PARAMS ((int, tree, rtx));
-extern rtx alpha_va_arg PARAMS ((tree, tree));
-extern rtx function_arg PARAMS ((CUMULATIVE_ARGS, enum machine_mode,
- tree, int));
+#if TARGET_ABI_OPEN_VMS
+#ifdef HAVE_MACHINE_MODES
+extern enum avms_arg_type alpha_arg_type PARAMS ((enum machine_mode));
#endif
-extern void alpha_start_function PARAMS ((FILE *, const char *, tree));
-extern void alpha_end_function PARAMS ((FILE *, const char *, tree));
-extern void alpha_output_mi_thunk_osf PARAMS ((FILE *, tree,
- HOST_WIDE_INT, tree));
-extern void alpha_encode_section_info PARAMS ((tree));
-#endif /* TREE CODE */
+extern rtx alpha_arg_info_reg_val PARAMS ((CUMULATIVE_ARGS));
+#endif /* TARGET_ABI_OPEN_VMS */
-#ifdef RTX_CODE
extern rtx unicosmk_add_call_info_word PARAMS ((rtx));
-#endif
#if TARGET_ABI_UNICOSMK
-#ifdef RTX_CODE
extern void unicosmk_defer_case_vector PARAMS ((rtx, rtx));
-#endif
-#ifdef TREE_CODE
-extern void unicosmk_unique_section PARAMS ((tree, int));
-#endif
extern void unicosmk_add_extern PARAMS ((const char *));
extern void unicosmk_output_align PARAMS ((FILE *, int));
extern char * unicosmk_text_section PARAMS ((void));
diff --git a/contrib/gcc/config/alpha/alpha.c b/contrib/gcc/config/alpha/alpha.c
index 3bc8e4d..9657e56 100644
--- a/contrib/gcc/config/alpha/alpha.c
+++ b/contrib/gcc/config/alpha/alpha.c
@@ -1,6 +1,6 @@
/* Subroutines used for code generation on the DEC Alpha.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GNU CC.
@@ -47,6 +47,7 @@ Boston, MA 02111-1307, USA. */
#include "target.h"
#include "target-def.h"
#include "debug.h"
+#include "langhooks.h"
/* Specify which cpu to schedule for. */
@@ -68,6 +69,10 @@ enum alpha_fp_rounding_mode alpha_fprm;
enum alpha_fp_trap_mode alpha_fptm;
+/* Specify bit size of immediate TLS offsets. */
+
+int alpha_tls_size = 32;
+
/* Strings decoded into the above options. */
const char *alpha_cpu_string; /* -mcpu= */
@@ -76,13 +81,14 @@ const char *alpha_tp_string; /* -mtrap-precision=[p|s|i] */
const char *alpha_fprm_string; /* -mfp-rounding-mode=[n|m|c|d] */
const char *alpha_fptm_string; /* -mfp-trap-mode=[n|u|su|sui] */
const char *alpha_mlat_string; /* -mmemory-latency= */
+const char *alpha_tls_size_string; /* -mtls-size=[16|32|64] */
/* Save information from a "cmpxx" operation until the branch or scc is
emitted. */
struct alpha_compare alpha_compare;
-/* Non-zero if inside of a function, because the Alpha asm can't
+/* Nonzero if inside of a function, because the Alpha asm can't
handle .files inside of functions. */
static int inside_function = FALSE;
@@ -112,14 +118,22 @@ int alpha_this_literal_sequence_number;
int alpha_this_gpdisp_sequence_number;
/* Declarations of static functions. */
+static int tls_symbolic_operand_1
+ PARAMS ((rtx, enum machine_mode, int, int));
+static enum tls_model tls_symbolic_operand_type
+ PARAMS ((rtx));
static bool decl_in_text_section
PARAMS ((tree));
+static bool alpha_in_small_data_p
+ PARAMS ((tree));
+static void alpha_encode_section_info
+ PARAMS ((tree, int));
+static const char *alpha_strip_name_encoding
+ PARAMS ((const char *));
static int some_small_symbolic_operand_1
PARAMS ((rtx *, void *));
static int split_small_symbolic_operand_1
PARAMS ((rtx *, void *));
-static bool local_symbol_p
- PARAMS ((rtx));
static void alpha_set_memflags_1
PARAMS ((rtx, int, int, int));
static rtx alpha_emit_set_const_1
@@ -128,9 +142,13 @@ static void alpha_expand_unaligned_load_words
PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
static void alpha_expand_unaligned_store_words
PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
+static void alpha_init_builtins
+ PARAMS ((void));
+static rtx alpha_expand_builtin
+ PARAMS ((tree, rtx, rtx, enum machine_mode, int));
static void alpha_sa_mask
PARAMS ((unsigned long *imaskP, unsigned long *fmaskP));
-static int find_lo_sum
+static int find_lo_sum_using_gp
PARAMS ((rtx *, void *));
static int alpha_does_function_need_gp
PARAMS ((void));
@@ -140,6 +158,10 @@ static const char *get_trap_mode_suffix
PARAMS ((void));
static const char *get_round_mode_suffix
PARAMS ((void));
+static const char *get_some_local_dynamic_name
+ PARAMS ((void));
+static int get_some_local_dynamic_name_1
+ PARAMS ((rtx *, void *));
static rtx set_frame_related_p
PARAMS ((void));
static const char *alpha_lookup_xfloating_lib_func
@@ -156,18 +178,31 @@ static int alpha_adjust_cost
PARAMS ((rtx, rtx, rtx, int));
static int alpha_issue_rate
PARAMS ((void));
-static int alpha_variable_issue
- PARAMS ((FILE *, int, rtx, int));
+static int alpha_use_dfa_pipeline_interface
+ PARAMS ((void));
+static int alpha_multipass_dfa_lookahead
+ PARAMS ((void));
-#if TARGET_ABI_UNICOSMK
-static void alpha_init_machine_status
- PARAMS ((struct function *p));
-static void alpha_mark_machine_status
- PARAMS ((struct function *p));
-static void alpha_free_machine_status
- PARAMS ((struct function *p));
+#ifdef OBJECT_FORMAT_ELF
+static void alpha_elf_select_rtx_section
+ PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT));
+#endif
+
+#if TARGET_ABI_OPEN_VMS
+static bool alpha_linkage_symbol_p
+ PARAMS ((const char *symname));
+static void alpha_write_linkage
+ PARAMS ((FILE *, const char *, tree));
+#endif
+
+#if TARGET_ABI_OSF
+static void alpha_output_mi_thunk_osf
+ PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
#endif
+static struct machine_function * alpha_init_machine_status
+ PARAMS ((void));
+
static void unicosmk_output_deferred_case_vectors PARAMS ((FILE *));
static void unicosmk_gen_dsib PARAMS ((unsigned long *imaskP));
static void unicosmk_output_ssib PARAMS ((FILE *, const char *));
@@ -196,15 +231,27 @@ static void vms_asm_out_destructor PARAMS ((rtx, int));
# define TARGET_SECTION_TYPE_FLAGS vms_section_type_flags
#endif
+#undef TARGET_IN_SMALL_DATA_P
+#define TARGET_IN_SMALL_DATA_P alpha_in_small_data_p
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO alpha_encode_section_info
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING alpha_strip_name_encoding
+
#if TARGET_ABI_UNICOSMK
static void unicosmk_asm_named_section PARAMS ((const char *, unsigned int));
static void unicosmk_insert_attributes PARAMS ((tree, tree *));
static unsigned int unicosmk_section_type_flags PARAMS ((tree, const char *,
int));
+static void unicosmk_unique_section PARAMS ((tree, int));
# undef TARGET_INSERT_ATTRIBUTES
# define TARGET_INSERT_ATTRIBUTES unicosmk_insert_attributes
# undef TARGET_SECTION_TYPE_FLAGS
# define TARGET_SECTION_TYPE_FLAGS unicosmk_section_type_flags
+# undef TARGET_ASM_UNIQUE_SECTION
+# define TARGET_ASM_UNIQUE_SECTION unicosmk_unique_section
+# undef TARGET_ASM_GLOBALIZE_LABEL
+# define TARGET_ASM_GLOBALIZE_LABEL hook_FILEptr_constcharptr_void
#endif
#undef TARGET_ASM_ALIGNED_HI_OP
@@ -223,6 +270,11 @@ static unsigned int unicosmk_section_type_flags PARAMS ((tree, const char *,
#define TARGET_ASM_UNALIGNED_DI_OP "\t.align 0\n\t.quad\t"
#endif
+#ifdef OBJECT_FORMAT_ELF
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION alpha_elf_select_rtx_section
+#endif
+
#undef TARGET_ASM_FUNCTION_END_PROLOGUE
#define TARGET_ASM_FUNCTION_END_PROLOGUE alpha_output_function_end_prologue
@@ -230,8 +282,27 @@ static unsigned int unicosmk_section_type_flags PARAMS ((tree, const char *,
#define TARGET_SCHED_ADJUST_COST alpha_adjust_cost
#undef TARGET_SCHED_ISSUE_RATE
#define TARGET_SCHED_ISSUE_RATE alpha_issue_rate
-#undef TARGET_SCHED_VARIABLE_ISSUE
-#define TARGET_SCHED_VARIABLE_ISSUE alpha_variable_issue
+#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
+#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE \
+ alpha_use_dfa_pipeline_interface
+#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
+#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
+ alpha_multipass_dfa_lookahead
+
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS HAVE_AS_TLS
+
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS alpha_init_builtins
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN alpha_expand_builtin
+
+#if TARGET_ABI_OSF
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK alpha_output_mi_thunk_osf
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
+#endif
struct gcc_target targetm = TARGET_INITIALIZER;
@@ -352,6 +423,18 @@ override_options ()
error ("bad value `%s' for -mfp-trap-mode switch", alpha_fptm_string);
}
+ if (alpha_tls_size_string)
+ {
+ if (strcmp (alpha_tls_size_string, "16") == 0)
+ alpha_tls_size = 16;
+ else if (strcmp (alpha_tls_size_string, "32") == 0)
+ alpha_tls_size = 32;
+ else if (strcmp (alpha_tls_size_string, "64") == 0)
+ alpha_tls_size = 64;
+ else
+ error ("bad value `%s' for -mtls-size switch", alpha_tls_size_string);
+ }
+
alpha_cpu
= TARGET_CPU_DEFAULT & MASK_CPU_EV6 ? PROCESSOR_EV6
: (TARGET_CPU_DEFAULT & MASK_CPU_EV5 ? PROCESSOR_EV5 : PROCESSOR_EV4);
@@ -494,12 +577,16 @@ override_options ()
/* Register variables and functions with the garbage collector. */
-#if TARGET_ABI_UNICOSMK
/* Set up function hooks. */
init_machine_status = alpha_init_machine_status;
- mark_machine_status = alpha_mark_machine_status;
- free_machine_status = alpha_free_machine_status;
-#endif
+
+ /* Tell the compiler when we're using VAX floating point. */
+ if (TARGET_FLOAT_VAX)
+ {
+ real_format_for_mode[SFmode - QFmode] = &vax_f_format;
+ real_format_for_mode[DFmode - QFmode] = &vax_g_format;
+ real_format_for_mode[TFmode - QFmode] = NULL;
+ }
}
/* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */
@@ -526,7 +613,7 @@ reg_or_0_operand (op, mode)
register rtx op;
enum machine_mode mode;
{
- return op == const0_rtx || register_operand (op, mode);
+ return op == CONST0_RTX (mode) || register_operand (op, mode);
}
/* Return 1 if OP is a constant in the range of 0-63 (for a shift) or
@@ -555,6 +642,16 @@ reg_or_8bit_operand (op, mode)
|| register_operand (op, mode));
}
+/* Return 1 if OP is a constant or any register. */
+
+int
+reg_or_const_int_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ return GET_CODE (op) == CONST_INT || register_operand (op, mode);
+}
+
/* Return 1 if OP is an 8-bit constant. */
int
@@ -661,24 +758,26 @@ mode_mask_operand (op, mode)
register rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
-#if HOST_BITS_PER_WIDE_INT == 32
- if (GET_CODE (op) == CONST_DOUBLE)
- return (CONST_DOUBLE_LOW (op) == -1
- && (CONST_DOUBLE_HIGH (op) == -1
- || CONST_DOUBLE_HIGH (op) == 0));
-#else
- if (GET_CODE (op) == CONST_DOUBLE)
- return (CONST_DOUBLE_LOW (op) == -1 && CONST_DOUBLE_HIGH (op) == 0);
-#endif
+ if (GET_CODE (op) == CONST_INT)
+ {
+ HOST_WIDE_INT value = INTVAL (op);
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) == 0xff
- || INTVAL (op) == 0xffff
- || INTVAL (op) == (HOST_WIDE_INT)0xffffffff
-#if HOST_BITS_PER_WIDE_INT == 64
- || INTVAL (op) == -1
-#endif
- ));
+ if (value == 0xff)
+ return 1;
+ if (value == 0xffff)
+ return 1;
+ if (value == 0xffffffff)
+ return 1;
+ if (value == -1)
+ return 1;
+ }
+ else if (HOST_BITS_PER_WIDE_INT == 32 && GET_CODE (op) == CONST_DOUBLE)
+ {
+ if (CONST_DOUBLE_LOW (op) == 0xffffffff && CONST_DOUBLE_HIGH (op) == 0)
+ return 1;
+ }
+
+ return 0;
}
/* Return 1 if OP is a multiple of 8 less than 64. */
@@ -693,25 +792,14 @@ mul8_operand (op, mode)
&& (INTVAL (op) & 7) == 0);
}
-/* Return 1 if OP is the constant zero in floating-point. */
-
-int
-fp0_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- return (GET_MODE (op) == mode
- && GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode));
-}
-
-/* Return 1 if OP is the floating-point constant zero or a register. */
+/* Return 1 if OP is the zero constant for MODE. */
int
-reg_or_fp0_operand (op, mode)
+const0_operand (op, mode)
register rtx op;
enum machine_mode mode;
{
- return fp0_operand (op, mode) || register_operand (op, mode);
+ return op == CONST0_RTX (mode);
}
/* Return 1 if OP is a hard floating-point register. */
@@ -769,8 +857,15 @@ some_operand (op, mode)
switch (GET_CODE (op))
{
- case REG: case MEM: case CONST_DOUBLE: case CONST_INT: case LABEL_REF:
- case SYMBOL_REF: case CONST: case HIGH:
+ case REG:
+ case MEM:
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case CONST_VECTOR:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ case CONST:
+ case HIGH:
return 1;
case SUBREG:
@@ -824,7 +919,9 @@ input_operand (op, mode)
symbolic operands to be reconstructed from their high/lo_sum
form. */
return (small_symbolic_operand (op, mode)
- || global_symbolic_operand (op, mode));
+ || global_symbolic_operand (op, mode)
+ || gotdtp_symbolic_operand (op, mode)
+ || gottp_symbolic_operand (op, mode));
}
/* This handles both the Windows/NT and OSF cases. */
@@ -847,7 +944,8 @@ input_operand (op, mode)
&& general_operand (op, mode));
case CONST_DOUBLE:
- return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
+ case CONST_VECTOR:
+ return op == CONST0_RTX (mode);
case CONST_INT:
return mode == QImode || mode == HImode || add_operand (op, mode);
@@ -911,31 +1009,15 @@ direct_call_operand (op, mode)
}
/* Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing
- a variable known to be defined in this file. */
-
-static bool
-local_symbol_p (op)
- rtx op;
-{
- const char *str = XSTR (op, 0);
-
- /* ??? SYMBOL_REF_FLAG is set for local function symbols, but we
- run into problems with the rtl inliner in that the symbol was
- once external, but is local after inlining, which results in
- unrecognizable insns. */
-
- return (CONSTANT_POOL_ADDRESS_P (op)
- /* If @, then ENCODE_SECTION_INFO sez it's local. */
- || str[0] == '@'
- /* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local. */
- || (str[0] == '*' && str[1] == '$'));
-}
+ a (non-tls) variable known to be defined in this file. */
int
local_symbolic_operand (op, mode)
rtx op;
enum machine_mode mode;
{
+ const char *str;
+
if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
return 0;
@@ -950,7 +1032,26 @@ local_symbolic_operand (op, mode)
if (GET_CODE (op) != SYMBOL_REF)
return 0;
- return local_symbol_p (op);
+ /* Easy pickings. */
+ if (CONSTANT_POOL_ADDRESS_P (op) || STRING_POOL_ADDRESS_P (op))
+ return 1;
+
+ /* ??? SYMBOL_REF_FLAG is set for local function symbols, but we
+ run into problems with the rtl inliner in that the symbol was
+ once external, but is local after inlining, which results in
+ unrecognizable insns. */
+
+ str = XSTR (op, 0);
+
+ /* If @[LS], then alpha_encode_section_info sez it's local. */
+ if (str[0] == '@' && (str[1] == 'L' || str[1] == 'S'))
+ return 1;
+
+ /* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local. */
+ if (str[0] == '*' && str[1] == '$')
+ return 1;
+
+ return 0;
}
/* Return true if OP is a SYMBOL_REF or CONST referencing a variable
@@ -982,7 +1083,7 @@ small_symbolic_operand (op, mode)
else
{
str = XSTR (op, 0);
- return str[0] == '@' && str[1] == 's';
+ return str[0] == '@' && str[1] == 'S';
}
}
@@ -994,6 +1095,8 @@ global_symbolic_operand (op, mode)
rtx op;
enum machine_mode mode;
{
+ const char *str;
+
if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
return 0;
@@ -1005,7 +1108,12 @@ global_symbolic_operand (op, mode)
if (GET_CODE (op) != SYMBOL_REF)
return 0;
- return ! local_symbol_p (op);
+ if (local_symbolic_operand (op, mode))
+ return 0;
+
+ /* Also verify that it's not a TLS symbol. */
+ str = XSTR (op, 0);
+ return str[0] != '%' && str[0] != '@';
}
/* Return 1 if OP is a valid operand for the MEM of a CALL insn. */
@@ -1058,6 +1166,110 @@ symbolic_operand (op, mode)
return 0;
}
+/* Return true if OP is valid for a particular TLS relocation. */
+
+static int
+tls_symbolic_operand_1 (op, mode, size, unspec)
+ rtx op;
+ enum machine_mode mode;
+ int size, unspec;
+{
+ const char *str;
+ int letter;
+
+ if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
+ return 0;
+
+ if (GET_CODE (op) != CONST)
+ return 0;
+ op = XEXP (op, 0);
+
+ if (GET_CODE (op) != UNSPEC || XINT (op, 1) != unspec)
+ return 0;
+ op = XVECEXP (op, 0, 0);
+
+ if (GET_CODE (op) != SYMBOL_REF)
+ return 0;
+ str = XSTR (op, 0);
+
+ if (str[0] == '%')
+ {
+ if (size != 64)
+ return 0;
+ }
+ else if (str[0] == '@')
+ {
+ if (alpha_tls_size > size)
+ return 0;
+ }
+ else
+ return 0;
+
+ letter = (unspec == UNSPEC_DTPREL ? 'D' : 'T');
+
+ return str[1] == letter;
+}
+
+/* Return true if OP is valid for 16-bit DTP relative relocations. */
+
+int
+dtp16_symbolic_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return tls_symbolic_operand_1 (op, mode, 16, UNSPEC_DTPREL);
+}
+
+/* Return true if OP is valid for 32-bit DTP relative relocations. */
+
+int
+dtp32_symbolic_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return tls_symbolic_operand_1 (op, mode, 32, UNSPEC_DTPREL);
+}
+
+/* Return true if OP is valid for 64-bit DTP relative relocations. */
+
+int
+gotdtp_symbolic_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return tls_symbolic_operand_1 (op, mode, 64, UNSPEC_DTPREL);
+}
+
+/* Return true if OP is valid for 16-bit TP relative relocations. */
+
+int
+tp16_symbolic_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return tls_symbolic_operand_1 (op, mode, 16, UNSPEC_TPREL);
+}
+
+/* Return true if OP is valid for 32-bit TP relative relocations. */
+
+int
+tp32_symbolic_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return tls_symbolic_operand_1 (op, mode, 32, UNSPEC_TPREL);
+}
+
+/* Return true if OP is valid for 64-bit TP relative relocations. */
+
+int
+gottp_symbolic_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return tls_symbolic_operand_1 (op, mode, 64, UNSPEC_TPREL);
+}
+
/* Return 1 if OP is a valid Alpha comparison operator. Here we know which
comparisons are valid in which insn. */
@@ -1455,7 +1667,9 @@ alpha_extra_constraint (value, c)
return GET_CODE (value) == HIGH;
case 'U':
return TARGET_ABI_UNICOSMK && symbolic_operand (value, VOIDmode);
-
+ case 'W':
+ return (GET_CODE (value) == CONST_VECTOR
+ && value == CONST0_RTX (GET_MODE (value)));
default:
return false;
}
@@ -1528,6 +1742,54 @@ alpha_tablejump_best_label (insn)
return best_label ? best_label : const0_rtx;
}
+
+/* Return the TLS model to use for SYMBOL. */
+
+static enum tls_model
+tls_symbolic_operand_type (symbol)
+ rtx symbol;
+{
+ const char *str;
+
+ if (GET_CODE (symbol) != SYMBOL_REF)
+ return 0;
+ str = XSTR (symbol, 0);
+
+ if (str[0] == '%')
+ {
+ /* ??? Be prepared for -ftls-model=local-dynamic. Perhaps we shouldn't
+ have separately encoded local-ness. On well, maybe the user will use
+ attribute visibility next time. At least we don't crash... */
+ if (str[1] == 'G' || str[1] == 'D')
+ return TLS_MODEL_GLOBAL_DYNAMIC;
+ if (str[1] == 'T')
+ return TLS_MODEL_INITIAL_EXEC;
+ }
+ else if (str[0] == '@')
+ {
+ if (str[1] == 'D')
+ {
+ /* Local dynamic is a waste if we're not going to combine
+ the __tls_get_addr calls. So avoid it if not optimizing. */
+ if (optimize)
+ return TLS_MODEL_LOCAL_DYNAMIC;
+ else
+ return TLS_MODEL_GLOBAL_DYNAMIC;
+ }
+ if (str[1] == 'T')
+ {
+ /* 64-bit local exec is the same as initial exec except without
+ the dynamic relocation. In either case we use a got entry. */
+ if (alpha_tls_size == 64)
+ return TLS_MODEL_INITIAL_EXEC;
+ else
+ return TLS_MODEL_LOCAL_EXEC;
+ }
+ }
+
+ return 0;
+}
+
/* Return true if the function DECL will be placed in the default text
section. */
@@ -1545,6 +1807,36 @@ decl_in_text_section (decl)
&& DECL_ONE_ONLY (decl))));
}
+/* Return true if EXP should be placed in the small data section. */
+
+static bool
+alpha_in_small_data_p (exp)
+ tree exp;
+{
+ /* We want to merge strings, so we never consider them small data. */
+ if (TREE_CODE (exp) == STRING_CST)
+ return false;
+
+ if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
+ {
+ const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
+ if (strcmp (section, ".sdata") == 0
+ || strcmp (section, ".sbss") == 0)
+ return true;
+ }
+ else
+ {
+ HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
+
+ /* If this is an incomplete type with size 0, then we can't put it
+ in sdata because it might be too big when completed. */
+ if (size > 0 && size <= g_switch_value)
+ return true;
+ }
+
+ return false;
+}
+
/* If we are referencing a function that is static, make the SYMBOL_REF
special. We use this to see indicate we can branch to this function
without setting PV or restoring GP.
@@ -1553,25 +1845,38 @@ decl_in_text_section (decl)
to the name. If in addition the variable is to go in .sdata/.sbss,
then add "@s" instead. */
-void
-alpha_encode_section_info (decl)
+static void
+alpha_encode_section_info (decl, first)
tree decl;
+ int first ATTRIBUTE_UNUSED;
{
const char *symbol_str;
- bool is_local, is_small;
+ bool is_local;
+ char encoding = 0;
+ rtx rtl, symbol;
+
+ rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl);
+ /* Careful not to prod global register variables. */
+ if (GET_CODE (rtl) != MEM)
+ return;
+ symbol = XEXP (rtl, 0);
+ if (GET_CODE (symbol) != SYMBOL_REF)
+ return;
+
if (TREE_CODE (decl) == FUNCTION_DECL)
{
/* We mark public functions once they are emitted; otherwise we
don't know that they exist in this unit of translation. */
if (TREE_PUBLIC (decl))
return;
+
/* Do not mark functions that are not in .text; otherwise we
don't know that they are near enough for a direct branch. */
if (! decl_in_text_section (decl))
return;
- SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
+ SYMBOL_REF_FLAG (symbol) = 1;
return;
}
@@ -1579,98 +1884,100 @@ alpha_encode_section_info (decl)
if (! TARGET_EXPLICIT_RELOCS)
return;
- /* Careful not to prod global register variables. */
- if (TREE_CODE (decl) != VAR_DECL
- || GET_CODE (DECL_RTL (decl)) != MEM
- || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
- return;
-
- symbol_str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+ symbol_str = XSTR (symbol, 0);
/* A variable is considered "local" if it is defined in this module. */
+ is_local = (*targetm.binds_local_p) (decl);
- if (DECL_EXTERNAL (decl))
- is_local = false;
- /* Linkonce and weak data is never local. */
- else if (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))
- is_local = false;
- else if (! TREE_PUBLIC (decl))
- is_local = true;
- /* If PIC, then assume that any global name can be overridden by
- symbols resolved from other modules. */
- else if (flag_pic)
- is_local = false;
- /* Uninitialized COMMON variable may be unified with symbols
- resolved from other modules. */
- else if (DECL_COMMON (decl)
- && (DECL_INITIAL (decl) == NULL
- || DECL_INITIAL (decl) == error_mark_node))
- is_local = false;
- /* Otherwise we're left with initialized (or non-common) global data
- which is of necessity defined locally. */
- else
- is_local = true;
-
- /* Determine if DECL will wind up in .sdata/.sbss. */
-
- is_small = false;
- if (DECL_SECTION_NAME (decl))
+ /* Care for TLS variables. */
+ if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
{
- const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
- if (strcmp (section, ".sdata") == 0
- || strcmp (section, ".sbss") == 0)
- is_small = true;
+ switch (decl_tls_model (decl))
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ encoding = 'G';
+ break;
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ encoding = 'D';
+ break;
+ case TLS_MODEL_INITIAL_EXEC:
+ case TLS_MODEL_LOCAL_EXEC:
+ encoding = 'T';
+ break;
+ }
}
- else
+ else if (is_local)
{
- HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
-
- /* If the variable has already been defined in the output file, then it
- is too late to put it in sdata if it wasn't put there in the first
- place. The test is here rather than above, because if it is already
- in sdata, then it can stay there. */
-
- if (TREE_ASM_WRITTEN (decl))
- ;
-
- /* If this is an incomplete type with size 0, then we can't put it in
- sdata because it might be too big when completed. */
- else if (size > 0 && size <= g_switch_value)
- is_small = true;
+ /* Determine if DECL will wind up in .sdata/.sbss. */
+ if (alpha_in_small_data_p (decl))
+ encoding = 'S';
+ else
+ encoding = 'L';
}
/* Finally, encode this into the symbol string. */
- if (is_local)
+ if (encoding)
{
- const char *string;
char *newstr;
size_t len;
+ char want_prefix = (is_local ? '@' : '%');
+ char other_prefix = (is_local ? '%' : '@');
- if (symbol_str[0] == '@')
+ if (symbol_str[0] == want_prefix)
{
- if (symbol_str[1] == (is_small ? 's' : 'v'))
+ if (symbol_str[1] == encoding)
return;
symbol_str += 2;
}
+ else if (symbol_str[0] == other_prefix)
+ symbol_str += 2;
len = strlen (symbol_str) + 1;
newstr = alloca (len + 2);
- newstr[0] = '@';
- newstr[1] = (is_small ? 's' : 'v');
+ newstr[0] = want_prefix;
+ newstr[1] = encoding;
memcpy (newstr + 2, symbol_str, len);
- string = ggc_alloc_string (newstr, len + 2 - 1);
- XSTR (XEXP (DECL_RTL (decl), 0), 0) = string;
- }
- else if (symbol_str[0] == '@')
- {
- /* We're hosed. This can happen when the user adds a weak
- attribute after rtl generation. They should have gotten
- a warning about unspecified behaviour from varasm.c. */
+ XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1);
}
}
+/* Undo the effects of the above. */
+
+static const char *
+alpha_strip_name_encoding (str)
+ const char *str;
+{
+ if (str[0] == '@' || str[0] == '%')
+ str += 2;
+ if (str[0] == '*')
+ str++;
+ return str;
+}
+
+#if TARGET_ABI_OPEN_VMS
+static bool
+alpha_linkage_symbol_p (symname)
+ const char *symname;
+{
+ int symlen = strlen (symname);
+
+ if (symlen > 4)
+ return strcmp (&symname [symlen - 4], "..lk") == 0;
+
+ return false;
+}
+
+#define LINKAGE_SYMBOL_REF_P(X) \
+ ((GET_CODE (X) == SYMBOL_REF \
+ && alpha_linkage_symbol_p (XSTR (X, 0))) \
+ || (GET_CODE (X) == CONST \
+ && GET_CODE (XEXP (X, 0)) == PLUS \
+ && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF \
+ && alpha_linkage_symbol_p (XSTR (XEXP (XEXP (X, 0), 0), 0))))
+#endif
+
/* legitimate_address_p recognizes an RTL expression that is a valid
memory address for an instruction. The MODE argument is the
machine mode for the MEM expression that wants to use this address.
@@ -1710,6 +2017,11 @@ alpha_legitimate_address_p (mode, x, strict)
if (CONSTANT_ADDRESS_P (x))
return true;
+#if TARGET_ABI_OPEN_VMS
+ if (LINKAGE_SYMBOL_REF_P (x))
+ return true;
+#endif
+
/* Register plus a small constant offset is valid. */
if (GET_CODE (x) == PLUS)
{
@@ -1765,7 +2077,9 @@ alpha_legitimate_address_p (mode, x, strict)
return false;
/* The symbol must be local. */
- if (local_symbolic_operand (ofs, Pmode))
+ if (local_symbolic_operand (ofs, Pmode)
+ || dtp32_symbolic_operand (ofs, Pmode)
+ || tp32_symbolic_operand (ofs, Pmode))
return true;
}
}
@@ -1831,6 +2145,100 @@ alpha_legitimize_address (x, scratch, mode)
/* If this is a local symbol, split the address into HIGH/LO_SUM parts. */
if (TARGET_EXPLICIT_RELOCS && symbolic_operand (x, Pmode))
{
+ rtx r0, r16, eqv, tga, tp, insn, dest, seq;
+
+ switch (tls_symbolic_operand_type (x))
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ start_sequence ();
+
+ r0 = gen_rtx_REG (Pmode, 0);
+ r16 = gen_rtx_REG (Pmode, 16);
+ tga = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr");
+ dest = gen_reg_rtx (Pmode);
+ seq = GEN_INT (alpha_next_sequence_number++);
+
+ emit_insn (gen_movdi_er_tlsgd (r16, pic_offset_table_rtx, x, seq));
+ insn = gen_call_value_osf_tlsgd (r0, tga, seq);
+ insn = emit_call_insn (insn);
+ CONST_OR_PURE_CALL_P (insn) = 1;
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
+
+ insn = get_insns ();
+ end_sequence ();
+
+ emit_libcall_block (insn, dest, r0, x);
+ return dest;
+
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ start_sequence ();
+
+ r0 = gen_rtx_REG (Pmode, 0);
+ r16 = gen_rtx_REG (Pmode, 16);
+ tga = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr");
+ scratch = gen_reg_rtx (Pmode);
+ seq = GEN_INT (alpha_next_sequence_number++);
+
+ emit_insn (gen_movdi_er_tlsldm (r16, pic_offset_table_rtx, seq));
+ insn = gen_call_value_osf_tlsldm (r0, tga, seq);
+ insn = emit_call_insn (insn);
+ CONST_OR_PURE_CALL_P (insn) = 1;
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
+
+ insn = get_insns ();
+ end_sequence ();
+
+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+ UNSPEC_TLSLDM_CALL);
+ emit_libcall_block (insn, scratch, r0, eqv);
+
+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPREL);
+ eqv = gen_rtx_CONST (Pmode, eqv);
+
+ if (alpha_tls_size == 64)
+ {
+ dest = gen_reg_rtx (Pmode);
+ emit_insn (gen_rtx_SET (VOIDmode, dest, eqv));
+ emit_insn (gen_adddi3 (dest, dest, scratch));
+ return dest;
+ }
+ if (alpha_tls_size == 32)
+ {
+ insn = gen_rtx_HIGH (Pmode, eqv);
+ insn = gen_rtx_PLUS (Pmode, scratch, insn);
+ scratch = gen_reg_rtx (Pmode);
+ emit_insn (gen_rtx_SET (VOIDmode, scratch, insn));
+ }
+ return gen_rtx_LO_SUM (Pmode, scratch, eqv);
+
+ case TLS_MODEL_INITIAL_EXEC:
+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_TPREL);
+ eqv = gen_rtx_CONST (Pmode, eqv);
+ tp = gen_reg_rtx (Pmode);
+ scratch = gen_reg_rtx (Pmode);
+ dest = gen_reg_rtx (Pmode);
+
+ emit_insn (gen_load_tp (tp));
+ emit_insn (gen_rtx_SET (VOIDmode, scratch, eqv));
+ emit_insn (gen_adddi3 (dest, tp, scratch));
+ return dest;
+
+ case TLS_MODEL_LOCAL_EXEC:
+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_TPREL);
+ eqv = gen_rtx_CONST (Pmode, eqv);
+ tp = gen_reg_rtx (Pmode);
+
+ emit_insn (gen_load_tp (tp));
+ if (alpha_tls_size == 32)
+ {
+ insn = gen_rtx_HIGH (Pmode, eqv);
+ insn = gen_rtx_PLUS (Pmode, tp, insn);
+ tp = gen_reg_rtx (Pmode);
+ emit_insn (gen_rtx_SET (VOIDmode, tp, insn));
+ }
+ return gen_rtx_LO_SUM (Pmode, tp, eqv);
+ }
+
if (local_symbolic_operand (x, Pmode))
{
if (small_symbolic_operand (x, Pmode))
@@ -2156,6 +2564,8 @@ alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
switch (GET_CODE (x))
{
case SEQUENCE:
+ abort ();
+
case PARALLEL:
for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
alpha_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p,
@@ -2190,11 +2600,11 @@ alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p)
}
}
-/* Given INSN, which is either an INSN or a SEQUENCE generated to
- perform a memory operation, look for any MEMs in either a SET_DEST or
- a SET_SRC and copy the in-struct, unchanging, and volatile flags from
- REF into each of the MEMs found. If REF is not a MEM, don't do
- anything. */
+/* Given INSN, which is an INSN list or the PATTERN of a single insn
+ generated to perform a memory operation, look for any MEMs in either
+ a SET_DEST or a SET_SRC and copy the in-struct, unchanging, and
+ volatile flags from REF into each of the MEMs found. If REF is not
+ a MEM, don't do anything. */
void
alpha_set_memflags (insn, ref)
@@ -2555,6 +2965,8 @@ alpha_expand_mov (mode, operands)
tmp = alpha_legitimize_address (operands[1], operands[0], mode);
if (tmp)
{
+ if (tmp == operands[0])
+ return true;
operands[1] = tmp;
return false;
}
@@ -2603,7 +3015,7 @@ alpha_expand_mov (mode, operands)
}
/* Otherwise we've nothing left but to drop the thing to memory. */
- operands[1] = force_const_mem (DImode, operands[1]);
+ operands[1] = force_const_mem (mode, operands[1]);
if (reload_in_progress)
{
emit_move_insn (operands[0], XEXP (operands[1], 0));
@@ -2907,7 +3319,7 @@ alpha_emit_conditional_branch (code)
}
else
{
- /* ??? We mark the the branch mode to be CCmode to prevent the
+ /* ??? We mark the branch mode to be CCmode to prevent the
compare and branch from being combined, since the compare
insn follows IEEE rules that the branch does not. */
branch_mode = CCmode;
@@ -3075,7 +3487,7 @@ alpha_emit_setcc (code)
/* Rewrite a comparison against zero CMP of the form
(CODE (cc0) (const_int 0)) so it can be written validly in
a conditional move (if_then_else CMP ...).
- If both of the operands that set cc0 are non-zero we must emit
+ If both of the operands that set cc0 are nonzero we must emit
an insn to perform the compare (it can't be done within
the conditional move). */
rtx
@@ -3107,7 +3519,7 @@ alpha_emit_conditional_move (cmp, mode)
/* If we have fp<->int register move instructions, do a cmov by
performing the comparison in fp registers, and move the
- zero/non-zero value to integer registers, where we can then
+ zero/nonzero value to integer registers, where we can then
use a normal cmov, or vice-versa. */
switch (code)
@@ -3639,7 +4051,7 @@ alpha_split_tfmode_frobsign (operands, operation)
alpha_split_tfmode_pair (operands);
- /* Detect three flavours of operand overlap. */
+ /* Detect three flavors of operand overlap. */
move = 1;
if (rtx_equal_p (operands[0], operands[2]))
move = 0;
@@ -3885,17 +4297,13 @@ alpha_expand_unaligned_store (dst, src, size, ofs)
emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffff), addr));
break;
case 4:
- emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffffffff), addr));
- break;
- case 8:
{
-#if HOST_BITS_PER_WIDE_INT == 32
- rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode);
-#else
- rtx msk = constm1_rtx;
-#endif
+ rtx msk = immed_double_const (0xffffffff, 0, DImode);
emit_insn (gen_mskxl_be (dsth, dsth, msk, addr));
+ break;
}
+ case 8:
+ emit_insn (gen_mskxl_be (dsth, dsth, constm1_rtx, addr));
break;
}
@@ -3932,17 +4340,13 @@ alpha_expand_unaligned_store (dst, src, size, ofs)
emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffff), addr));
break;
case 4:
- emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffffffff), addr));
- break;
- case 8:
{
-#if HOST_BITS_PER_WIDE_INT == 32
- rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode);
-#else
- rtx msk = constm1_rtx;
-#endif
+ rtx msk = immed_double_const (0xffffffff, 0, DImode);
emit_insn (gen_mskxl_le (dstl, dstl, msk, addr));
+ break;
}
+ case 8:
+ emit_insn (gen_mskxl_le (dstl, dstl, constm1_rtx, addr));
break;
}
}
@@ -4068,11 +4472,6 @@ alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs)
{
rtx const im8 = GEN_INT (-8);
rtx const i64 = GEN_INT (64);
-#if HOST_BITS_PER_WIDE_INT == 32
- rtx const im1 = immed_double_const (0xffffffff, 0xffffffff, DImode);
-#else
- rtx const im1 = constm1_rtx;
-#endif
rtx ins_tmps[MAX_MOVE_WORDS];
rtx st_tmp_1, st_tmp_2, dreg;
rtx st_addr_1, st_addr_2, dmema;
@@ -4136,13 +4535,13 @@ alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs)
/* Split and merge the ends with the destination data. */
if (WORDS_BIG_ENDIAN)
{
- emit_insn (gen_mskxl_be (st_tmp_2, st_tmp_2, im1, dreg));
+ emit_insn (gen_mskxl_be (st_tmp_2, st_tmp_2, constm1_rtx, dreg));
emit_insn (gen_mskxh (st_tmp_1, st_tmp_1, i64, dreg));
}
else
{
emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dreg));
- emit_insn (gen_mskxl_le (st_tmp_1, st_tmp_1, im1, dreg));
+ emit_insn (gen_mskxl_le (st_tmp_1, st_tmp_1, constm1_rtx, dreg));
}
if (data_regs != NULL)
@@ -4807,6 +5206,75 @@ alpha_expand_block_clear (operands)
return 1;
}
+
+/* Returns a mask so that zap(x, value) == x & mask. */
+
+rtx
+alpha_expand_zap_mask (value)
+ HOST_WIDE_INT value;
+{
+ rtx result;
+ int i;
+
+ if (HOST_BITS_PER_WIDE_INT >= 64)
+ {
+ HOST_WIDE_INT mask = 0;
+
+ for (i = 7; i >= 0; --i)
+ {
+ mask <<= 8;
+ if (!((value >> i) & 1))
+ mask |= 0xff;
+ }
+
+ result = gen_int_mode (mask, DImode);
+ }
+ else if (HOST_BITS_PER_WIDE_INT == 32)
+ {
+ HOST_WIDE_INT mask_lo = 0, mask_hi = 0;
+
+ for (i = 7; i >= 4; --i)
+ {
+ mask_hi <<= 8;
+ if (!((value >> i) & 1))
+ mask_hi |= 0xff;
+ }
+
+ for (i = 3; i >= 0; --i)
+ {
+ mask_lo <<= 8;
+ if (!((value >> i) & 1))
+ mask_lo |= 0xff;
+ }
+
+ result = immed_double_const (mask_lo, mask_hi, DImode);
+ }
+ else
+ abort ();
+
+ return result;
+}
+
+void
+alpha_expand_builtin_vector_binop (gen, mode, op0, op1, op2)
+ rtx (*gen) PARAMS ((rtx, rtx, rtx));
+ enum machine_mode mode;
+ rtx op0, op1, op2;
+{
+ op0 = gen_lowpart (mode, op0);
+
+ if (op1 == const0_rtx)
+ op1 = CONST0_RTX (mode);
+ else
+ op1 = gen_lowpart (mode, op1);
+
+ if (op2 == const0_rtx)
+ op2 = CONST0_RTX (mode);
+ else
+ op2 = gen_lowpart (mode, op2);
+
+ emit_insn ((*gen) (op0, op1, op2));
+}
/* Adjust the cost of a scheduling dependency. Return the new cost of
a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
@@ -4818,15 +5286,13 @@ alpha_adjust_cost (insn, link, dep_insn, cost)
rtx dep_insn;
int cost;
{
- rtx set, set_src;
enum attr_type insn_type, dep_insn_type;
/* If the dependence is an anti-dependence, there is no cost. For an
output dependence, there is sometimes a cost, but it doesn't seem
worth handling those few cases. */
-
if (REG_NOTE_KIND (link) != 0)
- return 0;
+ return cost;
/* If we can't recognize the insns, we can't really do anything. */
if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
@@ -4841,122 +5307,13 @@ alpha_adjust_cost (insn, link, dep_insn, cost)
|| dep_insn_type == TYPE_LDSYM)
cost += alpha_memory_latency-1;
- switch (alpha_cpu)
- {
- case PROCESSOR_EV4:
- /* On EV4, if INSN is a store insn and DEP_INSN is setting the data
- being stored, we can sometimes lower the cost. */
-
- if ((insn_type == TYPE_IST || insn_type == TYPE_FST)
- && (set = single_set (dep_insn)) != 0
- && GET_CODE (PATTERN (insn)) == SET
- && rtx_equal_p (SET_DEST (set), SET_SRC (PATTERN (insn))))
- {
- switch (dep_insn_type)
- {
- case TYPE_ILD:
- case TYPE_FLD:
- /* No savings here. */
- return cost;
-
- case TYPE_IMUL:
- /* In these cases, we save one cycle. */
- return cost - 1;
-
- default:
- /* In all other cases, we save two cycles. */
- return MAX (0, cost - 2);
- }
- }
-
- /* Another case that needs adjustment is an arithmetic or logical
- operation. It's cost is usually one cycle, but we default it to
- two in the MD file. The only case that it is actually two is
- for the address in loads, stores, and jumps. */
-
- if (dep_insn_type == TYPE_IADD || dep_insn_type == TYPE_ILOG)
- {
- switch (insn_type)
- {
- case TYPE_ILD:
- case TYPE_IST:
- case TYPE_FLD:
- case TYPE_FST:
- case TYPE_JSR:
- return cost;
- default:
- return 1;
- }
- }
-
- /* The final case is when a compare feeds into an integer branch;
- the cost is only one cycle in that case. */
-
- if (dep_insn_type == TYPE_ICMP && insn_type == TYPE_IBR)
- return 1;
- break;
-
- case PROCESSOR_EV5:
- /* And the lord DEC saith: "A special bypass provides an effective
- latency of 0 cycles for an ICMP or ILOG insn producing the test
- operand of an IBR or ICMOV insn." */
-
- if ((dep_insn_type == TYPE_ICMP || dep_insn_type == TYPE_ILOG)
- && (set = single_set (dep_insn)) != 0)
- {
- /* A branch only has one input. This must be it. */
- if (insn_type == TYPE_IBR)
- return 0;
- /* A conditional move has three, make sure it is the test. */
- if (insn_type == TYPE_ICMOV
- && GET_CODE (set_src = PATTERN (insn)) == SET
- && GET_CODE (set_src = SET_SRC (set_src)) == IF_THEN_ELSE
- && rtx_equal_p (SET_DEST (set), XEXP (set_src, 0)))
- return 0;
- }
-
- /* "The multiplier is unable to receive data from IEU bypass paths.
- The instruction issues at the expected time, but its latency is
- increased by the time it takes for the input data to become
- available to the multiplier" -- which happens in pipeline stage
- six, when results are comitted to the register file. */
-
- if (insn_type == TYPE_IMUL)
- {
- switch (dep_insn_type)
- {
- /* These insns produce their results in pipeline stage five. */
- case TYPE_ILD:
- case TYPE_ICMOV:
- case TYPE_IMUL:
- case TYPE_MVI:
- return cost + 1;
-
- /* Other integer insns produce results in pipeline stage four. */
- default:
- return cost + 2;
- }
- }
- break;
-
- case PROCESSOR_EV6:
- /* There is additional latency to move the result of (most) FP
- operations anywhere but the FP register file. */
+ /* Everything else handled in DFA bypasses now. */
- if ((insn_type == TYPE_FST || insn_type == TYPE_FTOI)
- && (dep_insn_type == TYPE_FADD ||
- dep_insn_type == TYPE_FMUL ||
- dep_insn_type == TYPE_FCMOV))
- return cost + 2;
-
- break;
- }
-
- /* Otherwise, return the default cost. */
return cost;
}
-/* Function to initialize the issue rate used by the scheduler. */
+/* The number of instructions that can be issued per cycle. */
+
static int
alpha_issue_rate ()
{
@@ -4964,57 +5321,50 @@ alpha_issue_rate ()
}
static int
-alpha_variable_issue (dump, verbose, insn, cim)
- FILE *dump ATTRIBUTE_UNUSED;
- int verbose ATTRIBUTE_UNUSED;
- rtx insn;
- int cim;
+alpha_use_dfa_pipeline_interface ()
{
- if (recog_memoized (insn) < 0 || get_attr_type (insn) == TYPE_MULTI)
- return 0;
-
- return cim - 1;
+ return true;
}
-
-/* Register global variables and machine-specific functions with the
- garbage collector. */
+/* How many alternative schedules to try. This should be as wide as the
+ scheduling freedom in the DFA, but no wider. Making this value too
+ large results extra work for the scheduler.
-#if TARGET_ABI_UNICOSMK
-static void
-alpha_init_machine_status (p)
- struct function *p;
-{
- p->machine =
- (struct machine_function *) xcalloc (1, sizeof (struct machine_function));
+ For EV4, loads can be issued to either IB0 or IB1, thus we have 2
+ alternative schedules. For EV5, we can choose between E0/E1 and
+ FA/FM. For EV6, an arithmatic insn can be issued to U0/U1/L0/L1. */
- p->machine->first_ciw = NULL_RTX;
- p->machine->last_ciw = NULL_RTX;
- p->machine->ciw_count = 0;
- p->machine->addr_list = NULL_RTX;
+static int
+alpha_multipass_dfa_lookahead ()
+{
+ return (alpha_cpu == PROCESSOR_EV6 ? 4 : 2);
}
+
+/* Machine-specific function data. */
-static void
-alpha_mark_machine_status (p)
- struct function *p;
+struct machine_function GTY(())
{
- struct machine_function *machine = p->machine;
+ /* For unicosmk. */
+ /* List of call information words for calls from this function. */
+ struct rtx_def *first_ciw;
+ struct rtx_def *last_ciw;
+ int ciw_count;
- if (machine)
- {
- ggc_mark_rtx (machine->first_ciw);
- ggc_mark_rtx (machine->addr_list);
- }
-}
+ /* List of deferred case vectors. */
+ struct rtx_def *addr_list;
-static void
-alpha_free_machine_status (p)
- struct function *p;
+ /* For OSF. */
+ const char *some_ld_name;
+};
+
+/* How to allocate a 'struct machine_function'. */
+
+static struct machine_function *
+alpha_init_machine_status ()
{
- free (p->machine);
- p->machine = NULL;
+ return ((struct machine_function *)
+ ggc_alloc_cleared (sizeof (struct machine_function)));
}
-#endif /* TARGET_ABI_UNICOSMK */
/* Functions to save and restore alpha_return_addr_rtx. */
@@ -5039,7 +5389,7 @@ alpha_gp_save_rtx ()
{
rtx r = get_hard_reg_initial_val (DImode, 29);
if (GET_CODE (r) != MEM)
- r = gen_mem_addressof (r, NULL_TREE);
+ r = gen_mem_addressof (r, NULL_TREE, /*rescan=*/true);
return r;
}
@@ -5158,6 +5508,45 @@ get_round_mode_suffix ()
abort ();
}
+/* Locate some local-dynamic symbol still in use by this function
+ so that we can print its name in some movdi_er_tlsldm pattern. */
+
+static const char *
+get_some_local_dynamic_name ()
+{
+ rtx insn;
+
+ if (cfun->machine->some_ld_name)
+ return cfun->machine->some_ld_name;
+
+ for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
+ if (INSN_P (insn)
+ && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
+ return cfun->machine->some_ld_name;
+
+ abort ();
+}
+
+static int
+get_some_local_dynamic_name_1 (px, data)
+ rtx *px;
+ void *data ATTRIBUTE_UNUSED;
+{
+ rtx x = *px;
+
+ if (GET_CODE (x) == SYMBOL_REF)
+ {
+ const char *str = XSTR (x, 0);
+ if (str[0] == '@' && str[1] == 'D')
+ {
+ cfun->machine->some_ld_name = str;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/* Print an operand. Recognize special options, documented below. */
void
@@ -5175,6 +5564,10 @@ print_operand (file, x, code)
assemble_name (file, alpha_fnname);
break;
+ case '&':
+ assemble_name (file, get_some_local_dynamic_name ());
+ break;
+
case '/':
{
const char *trap = get_trap_mode_suffix ();
@@ -5216,13 +5609,30 @@ print_operand (file, x, code)
break;
case 'J':
- if (GET_CODE (x) == CONST_INT)
- {
- if (INTVAL (x) != 0)
- fprintf (file, "\t\t!lituse_jsr!%d", (int) INTVAL (x));
- }
- else
- output_operand_lossage ("invalid %%J value");
+ {
+ const char *lituse;
+
+ if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSGD_CALL)
+ {
+ x = XVECEXP (x, 0, 0);
+ lituse = "lituse_tlsgd";
+ }
+ else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSLDM_CALL)
+ {
+ x = XVECEXP (x, 0, 0);
+ lituse = "lituse_tlsldm";
+ }
+ else if (GET_CODE (x) == CONST_INT)
+ lituse = "lituse_jsr";
+ else
+ {
+ output_operand_lossage ("invalid %%J value");
+ break;
+ }
+
+ if (x != const0_rtx)
+ fprintf (file, "\t\t!%s!%d", lituse, (int) INTVAL (x));
+ }
break;
case 'r':
@@ -5330,31 +5740,40 @@ print_operand (file, x, code)
case 'U':
/* Similar, except do it from the mask. */
- if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xff)
- fprintf (file, "b");
- else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffff)
- fprintf (file, "w");
- else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff)
- fprintf (file, "l");
-#if HOST_BITS_PER_WIDE_INT == 32
- else if (GET_CODE (x) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (x) == 0
- && CONST_DOUBLE_LOW (x) == -1)
- fprintf (file, "l");
- else if (GET_CODE (x) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (x) == -1
- && CONST_DOUBLE_LOW (x) == -1)
- fprintf (file, "q");
-#else
- else if (GET_CODE (x) == CONST_INT && INTVAL (x) == -1)
- fprintf (file, "q");
- else if (GET_CODE (x) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (x) == 0
- && CONST_DOUBLE_LOW (x) == -1)
- fprintf (file, "q");
-#endif
- else
- output_operand_lossage ("invalid %%U value");
+ if (GET_CODE (x) == CONST_INT)
+ {
+ HOST_WIDE_INT value = INTVAL (x);
+
+ if (value == 0xff)
+ {
+ fputc ('b', file);
+ break;
+ }
+ if (value == 0xffff)
+ {
+ fputc ('w', file);
+ break;
+ }
+ if (value == 0xffffffff)
+ {
+ fputc ('l', file);
+ break;
+ }
+ if (value == -1)
+ {
+ fputc ('q', file);
+ break;
+ }
+ }
+ else if (HOST_BITS_PER_WIDE_INT == 32
+ && GET_CODE (x) == CONST_DOUBLE
+ && CONST_DOUBLE_LOW (x) == 0xffffffff
+ && CONST_DOUBLE_HIGH (x) == 0)
+ {
+ fputc ('l', file);
+ break;
+ }
+ output_operand_lossage ("invalid %%U value");
break;
case 's':
@@ -5456,6 +5875,19 @@ print_operand (file, x, code)
fprintf (file, "%s", reg_names[REGNO (x)]);
else if (GET_CODE (x) == MEM)
output_address (XEXP (x, 0));
+ else if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC)
+ {
+ switch (XINT (XEXP (x, 0), 1))
+ {
+ case UNSPEC_DTPREL:
+ case UNSPEC_TPREL:
+ output_addr_const (file, XVECEXP (XEXP (x, 0), 0, 0));
+ break;
+ default:
+ output_operand_lossage ("unknown relocation unspec");
+ break;
+ }
+ }
else
output_addr_const (file, x);
break;
@@ -5485,7 +5917,36 @@ print_operand_address (file, addr)
if (GET_CODE (addr) == LO_SUM)
{
- output_addr_const (file, XEXP (addr, 1));
+ const char *reloc16, *reloclo;
+ rtx op1 = XEXP (addr, 1);
+
+ if (GET_CODE (op1) == CONST && GET_CODE (XEXP (op1, 0)) == UNSPEC)
+ {
+ op1 = XEXP (op1, 0);
+ switch (XINT (op1, 1))
+ {
+ case UNSPEC_DTPREL:
+ reloc16 = NULL;
+ reloclo = (alpha_tls_size == 16 ? "dtprel" : "dtprello");
+ break;
+ case UNSPEC_TPREL:
+ reloc16 = NULL;
+ reloclo = (alpha_tls_size == 16 ? "tprel" : "tprello");
+ break;
+ default:
+ output_operand_lossage ("unknown relocation unspec");
+ return;
+ }
+
+ output_addr_const (file, XVECEXP (op1, 0, 0));
+ }
+ else
+ {
+ reloc16 = "gprel";
+ reloclo = "gprellow";
+ output_addr_const (file, op1);
+ }
+
if (offset)
{
fputc ('+', file);
@@ -5502,7 +5963,7 @@ print_operand_address (file, addr)
abort ();
fprintf (file, "($%d)\t\t!%s", basereg,
- (basereg == 29 ? "gprel" : "gprellow"));
+ (basereg == 29 ? reloc16 : reloclo));
return;
}
@@ -5513,6 +5974,24 @@ print_operand_address (file, addr)
basereg = subreg_regno (addr);
else if (GET_CODE (addr) == CONST_INT)
offset = INTVAL (addr);
+
+#if TARGET_ABI_OPEN_VMS
+ else if (GET_CODE (addr) == SYMBOL_REF)
+ {
+ fprintf (file, "%s", XSTR (addr, 0));
+ return;
+ }
+ else if (GET_CODE (addr) == CONST
+ && GET_CODE (XEXP (addr, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF)
+ {
+ fprintf (file, "%s+%d",
+ XSTR (XEXP (XEXP (addr, 0), 0), 0),
+ INTVAL (XEXP (XEXP (addr, 0), 1)));
+ return;
+ }
+#endif
+
else
abort ();
@@ -5577,7 +6056,7 @@ alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs)
#ifdef TRANSFER_FROM_TRAMPOLINE
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
- 0, VOIDmode, 1, addr, Pmode);
+ 0, VOIDmode, 1, tramp, Pmode);
#endif
if (jmpofs >= 0)
@@ -5723,7 +6202,7 @@ alpha_build_va_list ()
if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
return ptr_type_node;
- record = make_lang_type (RECORD_TYPE);
+ record = (*lang_hooks.types.make_type) (RECORD_TYPE);
type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
TREE_CHAIN (record) = type_decl;
TYPE_NAME (record) = type_decl;
@@ -5746,8 +6225,7 @@ alpha_build_va_list ()
}
void
-alpha_va_start (stdarg_p, valist, nextarg)
- int stdarg_p;
+alpha_va_start (valist, nextarg)
tree valist;
rtx nextarg ATTRIBUTE_UNUSED;
{
@@ -5758,7 +6236,7 @@ alpha_va_start (stdarg_p, valist, nextarg)
return;
if (TARGET_ABI_UNICOSMK)
- std_expand_builtin_va_start (stdarg_p, valist, nextarg);
+ std_expand_builtin_va_start (valist, nextarg);
/* For Unix, SETUP_INCOMING_VARARGS moves the starting address base
up by 48, storing fp arg registers in the first 48 bytes, and the
@@ -5767,12 +6245,15 @@ alpha_va_start (stdarg_p, valist, nextarg)
If no integer registers need be stored, then we must subtract 48
in order to account for the integer arg registers which are counted
- in argsize above, but which are not actually stored on the stack. */
+ in argsize above, but which are not actually stored on the stack.
+ Must further be careful here about structures straddling the last
+ integer argument register; that futzes with pretend_args_size,
+ which changes the meaning of AP. */
- if (NUM_ARGS <= 5 + stdarg_p)
+ if (NUM_ARGS <= 6)
offset = TARGET_ABI_OPEN_VMS ? UNITS_PER_WORD : 6 * UNITS_PER_WORD;
else
- offset = -6 * UNITS_PER_WORD;
+ offset = -6 * UNITS_PER_WORD + current_function_pretend_args_size;
if (TARGET_ABI_OPEN_VMS)
{
@@ -5897,6 +6378,310 @@ alpha_va_arg (valist, type)
return addr;
}
+/* Builtins. */
+
+enum alpha_builtin
+{
+ ALPHA_BUILTIN_CMPBGE,
+ ALPHA_BUILTIN_EXTBL,
+ ALPHA_BUILTIN_EXTWL,
+ ALPHA_BUILTIN_EXTLL,
+ ALPHA_BUILTIN_EXTQL,
+ ALPHA_BUILTIN_EXTWH,
+ ALPHA_BUILTIN_EXTLH,
+ ALPHA_BUILTIN_EXTQH,
+ ALPHA_BUILTIN_INSBL,
+ ALPHA_BUILTIN_INSWL,
+ ALPHA_BUILTIN_INSLL,
+ ALPHA_BUILTIN_INSQL,
+ ALPHA_BUILTIN_INSWH,
+ ALPHA_BUILTIN_INSLH,
+ ALPHA_BUILTIN_INSQH,
+ ALPHA_BUILTIN_MSKBL,
+ ALPHA_BUILTIN_MSKWL,
+ ALPHA_BUILTIN_MSKLL,
+ ALPHA_BUILTIN_MSKQL,
+ ALPHA_BUILTIN_MSKWH,
+ ALPHA_BUILTIN_MSKLH,
+ ALPHA_BUILTIN_MSKQH,
+ ALPHA_BUILTIN_UMULH,
+ ALPHA_BUILTIN_ZAP,
+ ALPHA_BUILTIN_ZAPNOT,
+ ALPHA_BUILTIN_AMASK,
+ ALPHA_BUILTIN_IMPLVER,
+ ALPHA_BUILTIN_RPCC,
+ ALPHA_BUILTIN_THREAD_POINTER,
+ ALPHA_BUILTIN_SET_THREAD_POINTER,
+
+ /* TARGET_MAX */
+ ALPHA_BUILTIN_MINUB8,
+ ALPHA_BUILTIN_MINSB8,
+ ALPHA_BUILTIN_MINUW4,
+ ALPHA_BUILTIN_MINSW4,
+ ALPHA_BUILTIN_MAXUB8,
+ ALPHA_BUILTIN_MAXSB8,
+ ALPHA_BUILTIN_MAXUW4,
+ ALPHA_BUILTIN_MAXSW4,
+ ALPHA_BUILTIN_PERR,
+ ALPHA_BUILTIN_PKLB,
+ ALPHA_BUILTIN_PKWB,
+ ALPHA_BUILTIN_UNPKBL,
+ ALPHA_BUILTIN_UNPKBW,
+
+ /* TARGET_CIX */
+ ALPHA_BUILTIN_CTTZ,
+ ALPHA_BUILTIN_CTLZ,
+ ALPHA_BUILTIN_CTPOP,
+
+ ALPHA_BUILTIN_max
+};
+
+static unsigned int const code_for_builtin[ALPHA_BUILTIN_max] = {
+ CODE_FOR_builtin_cmpbge,
+ CODE_FOR_builtin_extbl,
+ CODE_FOR_builtin_extwl,
+ CODE_FOR_builtin_extll,
+ CODE_FOR_builtin_extql,
+ CODE_FOR_builtin_extwh,
+ CODE_FOR_builtin_extlh,
+ CODE_FOR_builtin_extqh,
+ CODE_FOR_builtin_insbl,
+ CODE_FOR_builtin_inswl,
+ CODE_FOR_builtin_insll,
+ CODE_FOR_builtin_insql,
+ CODE_FOR_builtin_inswh,
+ CODE_FOR_builtin_inslh,
+ CODE_FOR_builtin_insqh,
+ CODE_FOR_builtin_mskbl,
+ CODE_FOR_builtin_mskwl,
+ CODE_FOR_builtin_mskll,
+ CODE_FOR_builtin_mskql,
+ CODE_FOR_builtin_mskwh,
+ CODE_FOR_builtin_msklh,
+ CODE_FOR_builtin_mskqh,
+ CODE_FOR_umuldi3_highpart,
+ CODE_FOR_builtin_zap,
+ CODE_FOR_builtin_zapnot,
+ CODE_FOR_builtin_amask,
+ CODE_FOR_builtin_implver,
+ CODE_FOR_builtin_rpcc,
+ CODE_FOR_load_tp,
+ CODE_FOR_set_tp,
+
+ /* TARGET_MAX */
+ CODE_FOR_builtin_minub8,
+ CODE_FOR_builtin_minsb8,
+ CODE_FOR_builtin_minuw4,
+ CODE_FOR_builtin_minsw4,
+ CODE_FOR_builtin_maxub8,
+ CODE_FOR_builtin_maxsb8,
+ CODE_FOR_builtin_maxuw4,
+ CODE_FOR_builtin_maxsw4,
+ CODE_FOR_builtin_perr,
+ CODE_FOR_builtin_pklb,
+ CODE_FOR_builtin_pkwb,
+ CODE_FOR_builtin_unpkbl,
+ CODE_FOR_builtin_unpkbw,
+
+ /* TARGET_CIX */
+ CODE_FOR_builtin_cttz,
+ CODE_FOR_builtin_ctlz,
+ CODE_FOR_builtin_ctpop
+};
+
+struct alpha_builtin_def
+{
+ const char *name;
+ enum alpha_builtin code;
+ unsigned int target_mask;
+};
+
+static struct alpha_builtin_def const zero_arg_builtins[] = {
+ { "__builtin_alpha_implver", ALPHA_BUILTIN_IMPLVER, 0 },
+ { "__builtin_alpha_rpcc", ALPHA_BUILTIN_RPCC, 0 }
+};
+
+static struct alpha_builtin_def const one_arg_builtins[] = {
+ { "__builtin_alpha_amask", ALPHA_BUILTIN_AMASK, 0 },
+ { "__builtin_alpha_pklb", ALPHA_BUILTIN_PKLB, MASK_MAX },
+ { "__builtin_alpha_pkwb", ALPHA_BUILTIN_PKWB, MASK_MAX },
+ { "__builtin_alpha_unpkbl", ALPHA_BUILTIN_UNPKBL, MASK_MAX },
+ { "__builtin_alpha_unpkbw", ALPHA_BUILTIN_UNPKBW, MASK_MAX },
+ { "__builtin_alpha_cttz", ALPHA_BUILTIN_CTTZ, MASK_CIX },
+ { "__builtin_alpha_ctlz", ALPHA_BUILTIN_CTLZ, MASK_CIX },
+ { "__builtin_alpha_ctpop", ALPHA_BUILTIN_CTPOP, MASK_CIX }
+};
+
+static struct alpha_builtin_def const two_arg_builtins[] = {
+ { "__builtin_alpha_cmpbge", ALPHA_BUILTIN_CMPBGE, 0 },
+ { "__builtin_alpha_extbl", ALPHA_BUILTIN_EXTBL, 0 },
+ { "__builtin_alpha_extwl", ALPHA_BUILTIN_EXTWL, 0 },
+ { "__builtin_alpha_extll", ALPHA_BUILTIN_EXTLL, 0 },
+ { "__builtin_alpha_extql", ALPHA_BUILTIN_EXTQL, 0 },
+ { "__builtin_alpha_extwh", ALPHA_BUILTIN_EXTWH, 0 },
+ { "__builtin_alpha_extlh", ALPHA_BUILTIN_EXTLH, 0 },
+ { "__builtin_alpha_extqh", ALPHA_BUILTIN_EXTQH, 0 },
+ { "__builtin_alpha_insbl", ALPHA_BUILTIN_INSBL, 0 },
+ { "__builtin_alpha_inswl", ALPHA_BUILTIN_INSWL, 0 },
+ { "__builtin_alpha_insll", ALPHA_BUILTIN_INSLL, 0 },
+ { "__builtin_alpha_insql", ALPHA_BUILTIN_INSQL, 0 },
+ { "__builtin_alpha_inswh", ALPHA_BUILTIN_INSWH, 0 },
+ { "__builtin_alpha_inslh", ALPHA_BUILTIN_INSLH, 0 },
+ { "__builtin_alpha_insqh", ALPHA_BUILTIN_INSQH, 0 },
+ { "__builtin_alpha_mskbl", ALPHA_BUILTIN_MSKBL, 0 },
+ { "__builtin_alpha_mskwl", ALPHA_BUILTIN_MSKWL, 0 },
+ { "__builtin_alpha_mskll", ALPHA_BUILTIN_MSKLL, 0 },
+ { "__builtin_alpha_mskql", ALPHA_BUILTIN_MSKQL, 0 },
+ { "__builtin_alpha_mskwh", ALPHA_BUILTIN_MSKWH, 0 },
+ { "__builtin_alpha_msklh", ALPHA_BUILTIN_MSKLH, 0 },
+ { "__builtin_alpha_mskqh", ALPHA_BUILTIN_MSKQH, 0 },
+ { "__builtin_alpha_umulh", ALPHA_BUILTIN_UMULH, 0 },
+ { "__builtin_alpha_zap", ALPHA_BUILTIN_ZAP, 0 },
+ { "__builtin_alpha_zapnot", ALPHA_BUILTIN_ZAPNOT, 0 },
+ { "__builtin_alpha_minub8", ALPHA_BUILTIN_MINUB8, MASK_MAX },
+ { "__builtin_alpha_minsb8", ALPHA_BUILTIN_MINSB8, MASK_MAX },
+ { "__builtin_alpha_minuw4", ALPHA_BUILTIN_MINUW4, MASK_MAX },
+ { "__builtin_alpha_minsw4", ALPHA_BUILTIN_MINSW4, MASK_MAX },
+ { "__builtin_alpha_maxub8", ALPHA_BUILTIN_MAXUB8, MASK_MAX },
+ { "__builtin_alpha_maxsb8", ALPHA_BUILTIN_MAXSB8, MASK_MAX },
+ { "__builtin_alpha_maxuw4", ALPHA_BUILTIN_MAXUW4, MASK_MAX },
+ { "__builtin_alpha_maxsw4", ALPHA_BUILTIN_MAXSW4, MASK_MAX },
+ { "__builtin_alpha_perr", ALPHA_BUILTIN_PERR, MASK_MAX }
+};
+
+static void
+alpha_init_builtins ()
+{
+ const struct alpha_builtin_def *p;
+ tree ftype;
+ size_t i;
+
+ ftype = build_function_type (long_integer_type_node, void_list_node);
+
+ p = zero_arg_builtins;
+ for (i = 0; i < ARRAY_SIZE (zero_arg_builtins); ++i, ++p)
+ if ((target_flags & p->target_mask) == p->target_mask)
+ builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
+ NULL, NULL_TREE);
+
+ ftype = build_function_type_list (long_integer_type_node,
+ long_integer_type_node, NULL_TREE);
+
+ p = one_arg_builtins;
+ for (i = 0; i < ARRAY_SIZE (one_arg_builtins); ++i, ++p)
+ if ((target_flags & p->target_mask) == p->target_mask)
+ builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
+ NULL, NULL_TREE);
+
+ ftype = build_function_type_list (long_integer_type_node,
+ long_integer_type_node,
+ long_integer_type_node, NULL_TREE);
+
+ p = two_arg_builtins;
+ for (i = 0; i < ARRAY_SIZE (two_arg_builtins); ++i, ++p)
+ if ((target_flags & p->target_mask) == p->target_mask)
+ builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
+ NULL, NULL_TREE);
+
+ ftype = build_function_type (ptr_type_node, void_list_node);
+ builtin_function ("__builtin_thread_pointer", ftype,
+ ALPHA_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
+ NULL, NULL_TREE);
+
+ ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
+ builtin_function ("__builtin_set_thread_pointer", ftype,
+ ALPHA_BUILTIN_SET_THREAD_POINTER, BUILT_IN_MD,
+ NULL, NULL_TREE);
+}
+
+/* Expand an expression EXP that calls a built-in function,
+ with result going to TARGET if that's convenient
+ (and in mode MODE if that's convenient).
+ SUBTARGET may be used as the target for computing one of EXP's operands.
+ IGNORE is nonzero if the value is to be ignored. */
+
+static rtx
+alpha_expand_builtin (exp, target, subtarget, mode, ignore)
+ tree exp;
+ rtx target;
+ rtx subtarget ATTRIBUTE_UNUSED;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ int ignore ATTRIBUTE_UNUSED;
+{
+#define MAX_ARGS 2
+
+ tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+ tree arglist = TREE_OPERAND (exp, 1);
+ enum insn_code icode;
+ rtx op[MAX_ARGS], pat;
+ int arity;
+ bool nonvoid;
+
+ if (fcode >= ALPHA_BUILTIN_max)
+ internal_error ("bad builtin fcode");
+ icode = code_for_builtin[fcode];
+ if (icode == 0)
+ internal_error ("bad builtin fcode");
+
+ nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
+
+ for (arglist = TREE_OPERAND (exp, 1), arity = 0;
+ arglist;
+ arglist = TREE_CHAIN (arglist), arity++)
+ {
+ const struct insn_operand_data *insn_op;
+
+ tree arg = TREE_VALUE (arglist);
+ if (arg == error_mark_node)
+ return NULL_RTX;
+ if (arity > MAX_ARGS)
+ return NULL_RTX;
+
+ insn_op = &insn_data[icode].operand[arity + nonvoid];
+
+ op[arity] = expand_expr (arg, NULL_RTX, insn_op->mode, 0);
+
+ if (!(*insn_op->predicate) (op[arity], insn_op->mode))
+ op[arity] = copy_to_mode_reg (insn_op->mode, op[arity]);
+ }
+
+ if (nonvoid)
+ {
+ enum machine_mode tmode = insn_data[icode].operand[0].mode;
+ if (!target
+ || GET_MODE (target) != tmode
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
+ target = gen_reg_rtx (tmode);
+ }
+
+ switch (arity)
+ {
+ case 0:
+ pat = GEN_FCN (icode) (target);
+ break;
+ case 1:
+ if (nonvoid)
+ pat = GEN_FCN (icode) (target, op[0]);
+ else
+ pat = GEN_FCN (icode) (op[0]);
+ break;
+ case 2:
+ pat = GEN_FCN (icode) (target, op[0], op[1]);
+ break;
+ default:
+ abort ();
+ }
+ if (!pat)
+ return NULL_RTX;
+ emit_insn (pat);
+
+ if (nonvoid)
+ return target;
+ else
+ return const0_rtx;
+}
+
/* This page contains routines that are used to determine what the function
prologue and epilogue code will do and write them out. */
@@ -5934,10 +6719,11 @@ alpha_sa_mask (imaskP, fmaskP)
unsigned int i;
/* Irritatingly, there are two kinds of thunks -- those created with
- ASM_OUTPUT_MI_THUNK and those with DECL_THUNK_P that go through
- the regular part of the compiler. In the ASM_OUTPUT_MI_THUNK case
- we don't have valid register life info, but assemble_start_function
- wants to output .frame and .mask directives. */
+ TARGET_ASM_OUTPUT_MI_THUNK and those with DECL_THUNK_P that go
+ through the regular part of the compiler. In the
+ TARGET_ASM_OUTPUT_MI_THUNK case we don't have valid register life
+ info, but assemble_start_function wants to output .frame and
+ .mask directives. */
if (current_function_is_thunk && !no_new_pseudos)
{
*imaskP = 0;
@@ -6012,7 +6798,7 @@ alpha_sa_size ()
alpha_procedure_type
= (sa_size || get_frame_size() != 0
- || current_function_outgoing_args_size || current_function_varargs
+ || current_function_outgoing_args_size
|| current_function_stdarg || current_function_calls_alloca
|| frame_pointer_needed)
? PT_STACK : PT_REGISTER;
@@ -6111,11 +6897,18 @@ const struct attribute_spec vms_attribute_table[] =
#endif
static int
-find_lo_sum (px, data)
+find_lo_sum_using_gp (px, data)
rtx *px;
void *data ATTRIBUTE_UNUSED;
{
- return GET_CODE (*px) == LO_SUM;
+ return GET_CODE (*px) == LO_SUM && XEXP (*px, 0) == pic_offset_table_rtx;
+}
+
+int
+alpha_find_lo_sum_using_gp (insn)
+ rtx insn;
+{
+ return for_each_rtx (&PATTERN (insn), find_lo_sum_using_gp, NULL) > 0;
}
static int
@@ -6144,15 +6937,9 @@ alpha_does_function_need_gp ()
for (; insn; insn = NEXT_INSN (insn))
if (INSN_P (insn)
&& GET_CODE (PATTERN (insn)) != USE
- && GET_CODE (PATTERN (insn)) != CLOBBER)
- {
- enum attr_type type = get_attr_type (insn);
- if (type == TYPE_LDSYM || type == TYPE_JSR)
- return 1;
- if (TARGET_EXPLICIT_RELOCS
- && for_each_rtx (&PATTERN (insn), find_lo_sum, NULL) > 0)
- return 1;
- }
+ && GET_CODE (PATTERN (insn)) != CLOBBER
+ && get_attr_usegp (insn))
+ return 1;
return 0;
}
@@ -6179,22 +6966,30 @@ alpha_write_verstamp (file)
static rtx
set_frame_related_p ()
{
- rtx seq = gen_sequence ();
+ rtx seq = get_insns ();
+ rtx insn;
+
end_sequence ();
- if (GET_CODE (seq) == SEQUENCE)
+ if (!seq)
+ return NULL_RTX;
+
+ if (INSN_P (seq))
{
- int i = XVECLEN (seq, 0);
- while (--i >= 0)
- RTX_FRAME_RELATED_P (XVECEXP (seq, 0, i)) = 1;
- return emit_insn (seq);
+ insn = seq;
+ while (insn != NULL_RTX)
+ {
+ RTX_FRAME_RELATED_P (insn) = 1;
+ insn = NEXT_INSN (insn);
+ }
+ seq = emit_insn (seq);
}
else
{
seq = emit_insn (seq);
RTX_FRAME_RELATED_P (seq) = 1;
- return seq;
}
+ return seq;
}
#define FRP(exp) (start_sequence (), exp, set_frame_related_p ())
@@ -6698,26 +7493,13 @@ alpha_start_function (file, fnname, decl)
}
#if TARGET_ABI_OPEN_VMS
- /* Ifdef'ed cause readonly_section and link_section are only
- available then. */
- readonly_section ();
+ /* Ifdef'ed cause link_section are only available then. */
+ readonly_data_section ();
fprintf (file, "\t.align 3\n");
assemble_name (file, fnname); fputs ("..na:\n", file);
fputs ("\t.ascii \"", file);
assemble_name (file, fnname);
fputs ("\\0\"\n", file);
-
- link_section ();
- fprintf (file, "\t.align 3\n");
- fputs ("\t.name ", file);
- assemble_name (file, fnname);
- fputs ("..na\n", file);
- ASM_OUTPUT_LABEL (file, fnname);
- fprintf (file, "\t.pdesc ");
- assemble_name (file, fnname);
- fprintf (file, "..en,%s\n",
- alpha_procedure_type == PT_STACK ? "stack"
- : alpha_procedure_type == PT_REGISTER ? "reg" : "null");
alpha_need_linkage (fnname, 1);
text_section ();
#endif
@@ -7003,6 +7785,39 @@ alpha_expand_epilogue ()
}
}
}
+
+#if TARGET_ABI_OPEN_VMS
+#include <splay-tree.h>
+
+/* Structure to collect function names for final output
+ in link section. */
+
+enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN};
+enum reloc_kind {KIND_LINKAGE, KIND_CODEADDR};
+
+struct alpha_funcs
+{
+ int num;
+ splay_tree links;
+};
+
+struct alpha_links
+{
+ int num;
+ rtx linkage;
+ enum links_kind lkind;
+ enum reloc_kind rkind;
+};
+
+static splay_tree alpha_funcs_tree;
+static splay_tree alpha_links_tree;
+
+static int mark_alpha_links_node PARAMS ((splay_tree_node, void *));
+static void mark_alpha_links PARAMS ((void *));
+static int alpha_write_one_linkage PARAMS ((splay_tree_node, void *));
+
+static int alpha_funcs_num;
+#endif
/* Output the rest of the textual info surrounding the epilogue. */
@@ -7010,7 +7825,7 @@ void
alpha_end_function (file, fnname, decl)
FILE *file;
const char *fnname;
- tree decl ATTRIBUTE_UNUSED;
+ tree decl;
{
/* End the function. */
if (!TARGET_ABI_UNICOSMK && !flag_inhibit_size_directive)
@@ -7021,20 +7836,20 @@ alpha_end_function (file, fnname, decl)
}
inside_function = FALSE;
- /* Show that we know this function if it is called again.
+#if TARGET_ABI_OPEN_VMS
+ alpha_write_linkage (file, fnname, decl);
+#endif
+
+ /* Show that we know this function if it is called again.
- Don't do this for global functions in object files destined for a
- shared library because the function may be overridden by the application
- or other libraries. Similarly, don't do this for weak functions.
+ Do this only for functions whose symbols bind locally.
Don't do this for functions not defined in the .text section, as
otherwise it's not unlikely that the destination is out of range
for a direct branch. */
- if (!DECL_WEAK (current_function_decl)
- && (!flag_pic || !TREE_PUBLIC (current_function_decl))
- && decl_in_text_section (current_function_decl))
- SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl), 0)) = 1;
+ if ((*targetm.binds_local_p) (decl) && decl_in_text_section (decl))
+ SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
/* Output jump tables and the static subroutine information block. */
if (TARGET_ABI_UNICOSMK)
@@ -7044,7 +7859,8 @@ alpha_end_function (file, fnname, decl)
}
}
-/* Emit a tail call to FUNCTION after adjusting THIS by DELTA.
+#if TARGET_ABI_OSF
+/* Emit a tail call to FUNCTION after adjusting THIS by DELTA.
In order to avoid the hordes of differences between generated code
with and without TARGET_EXPLICIT_RELOCS, and to avoid duplicating
@@ -7053,11 +7869,12 @@ alpha_end_function (file, fnname, decl)
Not sure why this idea hasn't been explored before... */
-void
-alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, function)
+static void
+alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, vcall_offset, function)
FILE *file;
tree thunk_fndecl ATTRIBUTE_UNUSED;
HOST_WIDE_INT delta;
+ HOST_WIDE_INT vcall_offset;
tree function;
{
HOST_WIDE_INT hi, lo;
@@ -7092,6 +7909,37 @@ alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, function)
emit_insn (gen_adddi3 (this, this, tmp));
}
+ /* Add a delta stored in the vtable at VCALL_OFFSET. */
+ if (vcall_offset)
+ {
+ rtx tmp, tmp2;
+
+ tmp = gen_rtx_REG (Pmode, 0);
+ emit_move_insn (tmp, gen_rtx_MEM (Pmode, this));
+
+ lo = ((vcall_offset & 0xffff) ^ 0x8000) - 0x8000;
+ hi = (((vcall_offset - lo) & 0xffffffff) ^ 0x80000000) - 0x80000000;
+ if (hi + lo == vcall_offset)
+ {
+ if (hi)
+ emit_insn (gen_adddi3 (tmp, tmp, GEN_INT (hi)));
+ }
+ else
+ {
+ tmp2 = alpha_emit_set_long_const (gen_rtx_REG (Pmode, 1),
+ vcall_offset, -(vcall_offset < 0));
+ emit_insn (gen_adddi3 (tmp, tmp, tmp2));
+ lo = 0;
+ }
+ if (lo)
+ tmp2 = gen_rtx_PLUS (Pmode, tmp, GEN_INT (lo));
+ else
+ tmp2 = tmp;
+ emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp2));
+
+ emit_insn (gen_adddi3 (this, this, tmp));
+ }
+
/* Generate a tail call to the target function. */
if (! TREE_USED (function))
{
@@ -7113,6 +7961,7 @@ alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, function)
final (insn, file, 1, 0);
final_end_function ();
}
+#endif /* TARGET_ABI_OSF */
/* Debugging support. */
@@ -7575,6 +8424,7 @@ alphaev4_insn_pipe (insn)
case TYPE_MISC:
case TYPE_IBR:
case TYPE_JSR:
+ case TYPE_CALLPAL:
case TYPE_FCPYS:
case TYPE_FCMOV:
case TYPE_FADD:
@@ -7617,6 +8467,7 @@ alphaev5_insn_pipe (insn)
case TYPE_IBR:
case TYPE_JSR:
+ case TYPE_CALLPAL:
return EV5_E1;
case TYPE_FCPYS:
@@ -8077,82 +8928,25 @@ alpha_reorg (insns)
}
}
-/* Check a floating-point value for validity for a particular machine mode. */
-
-static const char * const float_strings[] =
-{
- /* These are for FLOAT_VAX. */
- "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
- "-1.70141173319264430e+38",
- "2.93873587705571877e-39", /* 2^-128 */
- "-2.93873587705571877e-39",
- /* These are for the default broken IEEE mode, which traps
- on infinity or denormal numbers. */
- "3.402823466385288598117e+38", /* 2^128 (1 - 2^-24) */
- "-3.402823466385288598117e+38",
- "1.1754943508222875079687e-38", /* 2^-126 */
- "-1.1754943508222875079687e-38",
-};
+#ifdef OBJECT_FORMAT_ELF
-static REAL_VALUE_TYPE float_values[8];
-static int inited_float_values = 0;
+/* Switch to the section to which we should output X. The only thing
+ special we do here is to honor small data. */
-int
-check_float_value (mode, d, overflow)
+static void
+alpha_elf_select_rtx_section (mode, x, align)
enum machine_mode mode;
- REAL_VALUE_TYPE *d;
- int overflow ATTRIBUTE_UNUSED;
+ rtx x;
+ unsigned HOST_WIDE_INT align;
{
-
- if (TARGET_IEEE || TARGET_IEEE_CONFORMANT || TARGET_IEEE_WITH_INEXACT)
- return 0;
-
- if (inited_float_values == 0)
- {
- int i;
- for (i = 0; i < 8; i++)
- float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode);
-
- inited_float_values = 1;
- }
-
- if (mode == SFmode)
- {
- REAL_VALUE_TYPE r;
- REAL_VALUE_TYPE *fvptr;
-
- if (TARGET_FLOAT_VAX)
- fvptr = &float_values[0];
- else
- fvptr = &float_values[4];
-
- memcpy (&r, d, sizeof (REAL_VALUE_TYPE));
- if (REAL_VALUES_LESS (fvptr[0], r))
- {
- memcpy (d, &fvptr[0], sizeof (REAL_VALUE_TYPE));
- return 1;
- }
- else if (REAL_VALUES_LESS (r, fvptr[1]))
- {
- memcpy (d, &fvptr[1], sizeof (REAL_VALUE_TYPE));
- return 1;
- }
- else if (REAL_VALUES_LESS (dconst0, r)
- && REAL_VALUES_LESS (r, fvptr[2]))
- {
- memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
- return 1;
- }
- else if (REAL_VALUES_LESS (r, dconst0)
- && REAL_VALUES_LESS (fvptr[3], r))
- {
- memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
- return 1;
- }
- }
-
- return 0;
+ if (TARGET_SMALL_DATA && GET_MODE_SIZE (mode) <= g_switch_value)
+ /* ??? Consider using mergable sdata sections. */
+ sdata_section ();
+ else
+ default_elf_select_rtx_section (mode, x, align);
}
+
+#endif /* OBJECT_FORMAT_ELF */
#if TARGET_ABI_OPEN_VMS
@@ -8189,25 +8983,6 @@ alpha_arg_info_reg_val (cum)
return GEN_INT (regval);
}
-#include <splay-tree.h>
-
-/* Structure to collect function names for final output
- in link section. */
-
-enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN};
-
-struct alpha_links
-{
- rtx linkage;
- enum links_kind kind;
-};
-
-static splay_tree alpha_links;
-
-static int mark_alpha_links_node PARAMS ((splay_tree_node, void *));
-static void mark_alpha_links PARAMS ((void *));
-static int alpha_write_one_linkage PARAMS ((splay_tree_node, void *));
-
/* Protect alpha_links from garbage collection. */
static int
@@ -8241,46 +9016,67 @@ alpha_need_linkage (name, is_local)
{
splay_tree_node node;
struct alpha_links *al;
+ struct alpha_funcs *cfaf;
if (name[0] == '*')
name++;
- if (alpha_links)
+ if (is_local)
+ {
+ alpha_funcs_tree = splay_tree_new
+ ((splay_tree_compare_fn) splay_tree_compare_pointers,
+ (splay_tree_delete_key_fn) free,
+ (splay_tree_delete_key_fn) free);
+
+ cfaf = (struct alpha_funcs *) xmalloc (sizeof (struct alpha_funcs));
+
+ cfaf->links = 0;
+ cfaf->num = ++alpha_funcs_num;
+
+ splay_tree_insert (alpha_funcs_tree,
+ (splay_tree_key) current_function_decl,
+ (splay_tree_value) cfaf);
+
+ }
+
+ if (alpha_links_tree)
{
/* Is this name already defined? */
- node = splay_tree_lookup (alpha_links, (splay_tree_key) name);
+ node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name);
if (node)
{
al = (struct alpha_links *) node->value;
if (is_local)
{
/* Defined here but external assumed. */
- if (al->kind == KIND_EXTERN)
- al->kind = KIND_LOCAL;
+ if (al->lkind == KIND_EXTERN)
+ al->lkind = KIND_LOCAL;
}
else
{
/* Used here but unused assumed. */
- if (al->kind == KIND_UNUSED)
- al->kind = KIND_LOCAL;
+ if (al->lkind == KIND_UNUSED)
+ al->lkind = KIND_LOCAL;
}
return al->linkage;
}
}
else
{
- alpha_links = splay_tree_new ((splay_tree_compare_fn) strcmp,
- (splay_tree_delete_key_fn) free,
- (splay_tree_delete_key_fn) free);
- ggc_add_root (&alpha_links, 1, 1, mark_alpha_links);
+ alpha_links_tree = splay_tree_new
+ ((splay_tree_compare_fn) strcmp,
+ (splay_tree_delete_key_fn) free,
+ (splay_tree_delete_key_fn) free);
+
+ ggc_add_root (&alpha_links_tree, 1, 1, mark_alpha_links);
}
al = (struct alpha_links *) xmalloc (sizeof (struct alpha_links));
name = xstrdup (name);
/* Assume external if no definition. */
- al->kind = (is_local ? KIND_UNUSED : KIND_EXTERN);
+ al->lkind = (is_local ? KIND_UNUSED : KIND_EXTERN);
/* Ensure we have an IDENTIFIER so assemble_name can mark it used. */
get_identifier (name);
@@ -8296,50 +9092,165 @@ alpha_need_linkage (name, is_local)
ggc_alloc_string (linksym, name_len + 5));
}
- splay_tree_insert (alpha_links, (splay_tree_key) name,
+ splay_tree_insert (alpha_links_tree, (splay_tree_key) name,
(splay_tree_value) al);
return al->linkage;
}
+rtx
+alpha_use_linkage (linkage, cfundecl, lflag, rflag)
+ rtx linkage;
+ tree cfundecl;
+ int lflag;
+ int rflag;
+{
+ splay_tree_node cfunnode;
+ struct alpha_funcs *cfaf;
+ struct alpha_links *al;
+ const char *name = XSTR (linkage, 0);
+
+ cfaf = (struct alpha_funcs *) 0;
+ al = (struct alpha_links *) 0;
+
+ cfunnode = splay_tree_lookup (alpha_funcs_tree, (splay_tree_key) cfundecl);
+ cfaf = (struct alpha_funcs *) cfunnode->value;
+
+ if (cfaf->links)
+ {
+ splay_tree_node lnode;
+
+ /* Is this name already defined? */
+
+ lnode = splay_tree_lookup (cfaf->links, (splay_tree_key) name);
+ if (lnode)
+ al = (struct alpha_links *) lnode->value;
+ }
+ else
+ {
+ cfaf->links = splay_tree_new
+ ((splay_tree_compare_fn) strcmp,
+ (splay_tree_delete_key_fn) free,
+ (splay_tree_delete_key_fn) free);
+ ggc_add_root (&cfaf->links, 1, 1, mark_alpha_links);
+ }
+
+ if (!al)
+ {
+ size_t name_len;
+ size_t buflen;
+ char buf [512];
+ char *linksym;
+ splay_tree_node node = 0;
+ struct alpha_links *anl;
+
+ if (name[0] == '*')
+ name++;
+
+ name_len = strlen (name);
+
+ al = (struct alpha_links *) xmalloc (sizeof (struct alpha_links));
+ al->num = cfaf->num;
+
+ node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name);
+ if (node)
+ {
+ anl = (struct alpha_links *) node->value;
+ al->lkind = anl->lkind;
+ }
+
+ sprintf (buf, "$%d..%s..lk", cfaf->num, name);
+ buflen = strlen (buf);
+ linksym = alloca (buflen + 1);
+ memcpy (linksym, buf, buflen + 1);
+
+ al->linkage = gen_rtx_SYMBOL_REF
+ (Pmode, ggc_alloc_string (linksym, buflen + 1));
+
+ splay_tree_insert (cfaf->links, (splay_tree_key) name,
+ (splay_tree_value) al);
+ }
+
+ if (rflag)
+ al->rkind = KIND_CODEADDR;
+ else
+ al->rkind = KIND_LINKAGE;
+
+ if (lflag)
+ return gen_rtx_MEM (Pmode, plus_constant (al->linkage, 8));
+ else
+ return al->linkage;
+}
+
static int
alpha_write_one_linkage (node, data)
splay_tree_node node;
void *data;
{
const char *const name = (const char *) node->key;
- struct alpha_links *links = (struct alpha_links *) node->value;
+ struct alpha_links *link = (struct alpha_links *) node->value;
FILE *stream = (FILE *) data;
- if (links->kind == KIND_UNUSED
- || ! TREE_SYMBOL_REFERENCED (get_identifier (name)))
- return 0;
-
- fprintf (stream, "$%s..lk:\n", name);
- if (links->kind == KIND_LOCAL)
+ fprintf (stream, "$%d..%s..lk:\n", link->num, name);
+ if (link->rkind == KIND_CODEADDR)
{
- /* Local and used, build linkage pair. */
- fprintf (stream, "\t.quad %s..en\n", name);
- fprintf (stream, "\t.quad %s\n", name);
+ if (link->lkind == KIND_LOCAL)
+ {
+ /* Local and used */
+ fprintf (stream, "\t.quad %s..en\n", name);
+ }
+ else
+ {
+ /* External and used, request code address. */
+ fprintf (stream, "\t.code_address %s\n", name);
+ }
}
else
{
- /* External and used, request linkage pair. */
- fprintf (stream, "\t.linkage %s\n", name);
+ if (link->lkind == KIND_LOCAL)
+ {
+ /* Local and used, build linkage pair. */
+ fprintf (stream, "\t.quad %s..en\n", name);
+ fprintf (stream, "\t.quad %s\n", name);
+ }
+ else
+ {
+ /* External and used, request linkage pair. */
+ fprintf (stream, "\t.linkage %s\n", name);
+ }
}
return 0;
}
-void
-alpha_write_linkage (stream)
- FILE *stream;
+static void
+alpha_write_linkage (stream, funname, fundecl)
+ FILE *stream;
+ const char *funname;
+ tree fundecl;
{
- if (alpha_links)
+ splay_tree_node node;
+ struct alpha_funcs *func;
+
+ link_section ();
+ fprintf (stream, "\t.align 3\n");
+ node = splay_tree_lookup (alpha_funcs_tree, (splay_tree_key) fundecl);
+ func = (struct alpha_funcs *) node->value;
+
+ fputs ("\t.name ", stream);
+ assemble_name (stream, funname);
+ fputs ("..na\n", stream);
+ ASM_OUTPUT_LABEL (stream, funname);
+ fprintf (stream, "\t.pdesc ");
+ assemble_name (stream, funname);
+ fprintf (stream, "..en,%s\n",
+ alpha_procedure_type == PT_STACK ? "stack"
+ : alpha_procedure_type == PT_REGISTER ? "reg" : "null");
+
+ if (func->links)
{
- readonly_section ();
- fprintf (stream, "\t.align 3\n");
- splay_tree_foreach (alpha_links, alpha_write_one_linkage, stream);
+ splay_tree_foreach (func->links, alpha_write_one_linkage, stream);
+ /* splay_tree_delete (func->links); */
}
}
@@ -8432,6 +9343,16 @@ alpha_need_linkage (name, is_local)
return NULL_RTX;
}
+rtx
+alpha_use_linkage (linkage, cfundecl, lflag, rflag)
+ rtx linkage ATTRIBUTE_UNUSED;
+ tree cfundecl ATTRIBUTE_UNUSED;
+ int lflag ATTRIBUTE_UNUSED;
+ int rflag ATTRIBUTE_UNUSED;
+{
+ return NULL_RTX;
+}
+
#endif /* TARGET_ABI_OPEN_VMS */
#if TARGET_ABI_UNICOSMK
@@ -8495,9 +9416,8 @@ unicosmk_output_module_name (file)
prefix the module name with a '$' if necessary. */
if (!ISALPHA (*name))
- fprintf (file, "$%s", name);
- else
- fputs (name, file);
+ putc ('$', file);
+ output_clean_symbol_name (file, name);
}
/* Output text that to appear at the beginning of an assembler file. */
@@ -8636,7 +9556,7 @@ unicosmk_section_type_flags (decl, name, reloc)
/* Generate a section name for decl and associate it with the
declaration. */
-void
+static void
unicosmk_unique_section (decl, reloc)
tree decl;
int reloc ATTRIBUTE_UNUSED;
@@ -8648,7 +9568,7 @@ unicosmk_unique_section (decl, reloc)
abort ();
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- STRIP_NAME_ENCODING (name, name);
+ name = alpha_strip_name_encoding (name);
len = strlen (name);
if (TREE_CODE (decl) == FUNCTION_DECL)
@@ -8716,7 +9636,7 @@ unicosmk_insert_attributes (decl, attr_ptr)
{
if (DECL_P (decl)
&& (TREE_PUBLIC (decl) || TREE_CODE (decl) == FUNCTION_DECL))
- UNIQUE_SECTION (decl, 0);
+ unicosmk_unique_section (decl, 0);
}
/* Output an alignment directive. We have to use the macro 'gcc@code@align'
@@ -8879,8 +9799,7 @@ unicosmk_ssib_name ()
x = XEXP (x, 0);
if (GET_CODE (x) != SYMBOL_REF)
abort ();
- fnname = XSTR (x, 0);
- STRIP_NAME_ENCODING (fnname, fnname);
+ fnname = alpha_strip_name_encoding (XSTR (x, 0));
len = strlen (fnname);
if (len + SSIB_PREFIX_LEN > 255)
@@ -9055,7 +9974,7 @@ unicosmk_output_externs (file)
/* We have to strip the encoding and possibly remove user_label_prefix
from the identifier in order to handle -fleading-underscore and
explicit asm names correctly (cf. gcc.dg/asm-names-1.c). */
- STRIP_NAME_ENCODING (real_name, p->name);
+ real_name = alpha_strip_name_encoding (p->name);
if (len && p->name[0] == '*'
&& !memcmp (real_name, user_label_prefix, len))
real_name += len;
@@ -9080,7 +9999,7 @@ unicosmk_add_extern (name)
struct unicosmk_extern_list *p;
p = (struct unicosmk_extern_list *)
- permalloc (sizeof (struct unicosmk_extern_list));
+ xmalloc (sizeof (struct unicosmk_extern_list));
p->next = unicosmk_extern_head;
p->name = name;
unicosmk_extern_head = p;
@@ -9162,7 +10081,7 @@ unicosmk_need_dex (x)
--i;
}
- dex = (struct unicosmk_dex *) permalloc (sizeof (struct unicosmk_dex));
+ dex = (struct unicosmk_dex *) xmalloc (sizeof (struct unicosmk_dex));
dex->name = name;
dex->next = unicosmk_dex_list;
unicosmk_dex_list = dex;
@@ -9230,3 +10149,6 @@ unicosmk_need_dex (x)
}
#endif /* TARGET_ABI_UNICOSMK */
+
+#include "gt-alpha.h"
+
diff --git a/contrib/gcc/config/alpha/alpha.h b/contrib/gcc/config/alpha/alpha.h
index 4410a86..b933ea3 100644
--- a/contrib/gcc/config/alpha/alpha.h
+++ b/contrib/gcc/config/alpha/alpha.h
@@ -20,24 +20,81 @@ 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. */
+/* Target CPU builtins. */
+#define TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__alpha"); \
+ builtin_define ("__alpha__"); \
+ builtin_assert ("cpu=alpha"); \
+ builtin_assert ("machine=alpha"); \
+ if (TARGET_CIX) \
+ { \
+ builtin_define ("__alpha_cix__"); \
+ builtin_assert ("cpu=cix"); \
+ } \
+ if (TARGET_FIX) \
+ { \
+ builtin_define ("__alpha_fix__"); \
+ builtin_assert ("cpu=fix"); \
+ } \
+ if (TARGET_BWX) \
+ { \
+ builtin_define ("__alpha_bwx__"); \
+ builtin_assert ("cpu=bwx"); \
+ } \
+ if (TARGET_MAX) \
+ { \
+ builtin_define ("__alpha_max__"); \
+ builtin_assert ("cpu=max"); \
+ } \
+ if (TARGET_CPU_EV6) \
+ { \
+ builtin_define ("__alpha_ev6__"); \
+ builtin_assert ("cpu=ev6"); \
+ } \
+ else if (TARGET_CPU_EV5) \
+ { \
+ builtin_define ("__alpha_ev5__"); \
+ builtin_assert ("cpu=ev5"); \
+ } \
+ else /* Presumably ev4. */ \
+ { \
+ builtin_define ("__alpha_ev4__"); \
+ builtin_assert ("cpu=ev4"); \
+ } \
+ if (TARGET_IEEE || TARGET_IEEE_WITH_INEXACT) \
+ builtin_define ("_IEEE_FP"); \
+ if (TARGET_IEEE_WITH_INEXACT) \
+ builtin_define ("_IEEE_FP_INEXACT"); \
+ \
+ /* Macros dependent on the C dialect. */ \
+ SUBTARGET_LANGUAGE_CPP_BUILTINS(); \
+} while (0)
+
+#ifndef SUBTARGET_LANGUAGE_CPP_BUILTINS
+#define SUBTARGET_LANGUAGE_CPP_BUILTINS() \
+ do \
+ { \
+ if (preprocessing_asm_p ()) \
+ builtin_define_std ("LANGUAGE_ASSEMBLY"); \
+ else if (c_language == clk_c) \
+ builtin_define_std ("LANGUAGE_C"); \
+ else if (c_language == clk_cplusplus) \
+ { \
+ builtin_define ("__LANGUAGE_C_PLUS_PLUS"); \
+ builtin_define ("__LANGUAGE_C_PLUS_PLUS__"); \
+ } \
+ if (flag_objc) \
+ { \
+ builtin_define ("__LANGUAGE_OBJECTIVE_C"); \
+ builtin_define ("__LANGUAGE_OBJECTIVE_C__"); \
+ } \
+ } \
+ while (0)
+#endif
-/* For C++ we need to ensure that __LANGUAGE_C_PLUS_PLUS is defined independent
- of the source file extension. */
-#define CPLUSPLUS_CPP_SPEC "\
--D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus \
-%(cpp) \
-"
-
-/* Write out the correct language type definition for the header files.
- Unless we have assembler language, write out the symbols for C. */
-#define CPP_SPEC "\
-%{!undef:\
-%{.S:-D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY }}\
-%{.m:-D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C }\
-%{!.S:%{!.cc:%{!.cxx:%{!.cpp:%{!.cp:%{!.c++:%{!.C:%{!.m:-D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C }}}}}}}}}\
-%{mieee:-D_IEEE_FP }\
-%{mieee-with-inexact:-D_IEEE_FP -D_IEEE_FP_INEXACT }}\
-%(cpp_cpu) %(cpp_subtarget)"
+#define CPP_SPEC "%(cpp_subtarget)"
#ifndef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC ""
@@ -89,6 +146,7 @@ extern int target_flags;
extern enum alpha_trap_precision alpha_tp;
extern enum alpha_fp_rounding_mode alpha_fprm;
extern enum alpha_fp_trap_mode alpha_fptm;
+extern int alpha_tls_size;
/* This means that floating-point support exists in the target implementation
of the Alpha architecture. This is usually the default. */
@@ -160,6 +218,10 @@ extern enum alpha_fp_trap_mode alpha_fptm;
#define MASK_SMALL_DATA (1 << 13)
#define TARGET_SMALL_DATA (target_flags & MASK_SMALL_DATA)
+/* This means emit thread pointer loads for kernel not user. */
+#define MASK_TLS_KERNEL (1 << 14)
+#define TARGET_TLS_KERNEL (target_flags & MASK_TLS_KERNEL)
+
/* This means that the processor is an EV5, EV56, or PCA56.
Unlike alpha_cpu this is not affected by -mtune= setting. */
#define MASK_CPU_EV5 (1 << 28)
@@ -203,6 +265,9 @@ extern enum alpha_fp_trap_mode alpha_fptm;
#ifndef TARGET_FIXUP_EV5_PREFETCH
#define TARGET_FIXUP_EV5_PREFETCH 0
#endif
+#ifndef HAVE_AS_TLS
+#define HAVE_AS_TLS 0
+#endif
/* Macro to define tables used to set the flags.
This is a list in braces of pairs in braces,
@@ -245,6 +310,8 @@ extern enum alpha_fp_trap_mode alpha_fptm;
N_("Emit 16-bit relocations to the small data areas")}, \
{"large-data", -MASK_SMALL_DATA, \
N_("Emit 32-bit relocations to the small data areas")}, \
+ {"tls-kernel", MASK_TLS_KERNEL, \
+ N_("Emit rdval instead of rduniq for thread pointer")}, \
{"", TARGET_DEFAULT | TARGET_CPU_DEFAULT \
| TARGET_DEFAULT_EXPLICIT_RELOCS, ""} }
@@ -268,6 +335,7 @@ extern const char *alpha_fprm_string; /* For -mfp-rounding-mode=[n|m|c|d] */
extern const char *alpha_fptm_string; /* For -mfp-trap-mode=[n|u|su|sui] */
extern const char *alpha_tp_string; /* For -mtrap-precision=[p|f|i] */
extern const char *alpha_mlat_string; /* For -mmemory-latency= */
+extern const char *alpha_tls_size_string; /* For -mtls-size= */
#define TARGET_OPTIONS \
{ \
@@ -283,67 +351,10 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */
N_("Control the precision given to fp exceptions")}, \
{"memory-latency=", &alpha_mlat_string, \
N_("Tune expected memory latency")}, \
+ {"tls-size=", &alpha_tls_size_string, \
+ N_("Specify bit size of immediate TLS offsets")}, \
}
-/* Attempt to describe CPU characteristics to the preprocessor. */
-
-/* Corresponding to amask... */
-#define CPP_AM_BWX_SPEC "-D__alpha_bwx__ -Acpu=bwx"
-#define CPP_AM_MAX_SPEC "-D__alpha_max__ -Acpu=max"
-#define CPP_AM_FIX_SPEC "-D__alpha_fix__ -Acpu=fix"
-#define CPP_AM_CIX_SPEC "-D__alpha_cix__ -Acpu=cix"
-
-/* Corresponding to implver... */
-#define CPP_IM_EV4_SPEC "-D__alpha_ev4__ -Acpu=ev4"
-#define CPP_IM_EV5_SPEC "-D__alpha_ev5__ -Acpu=ev5"
-#define CPP_IM_EV6_SPEC "-D__alpha_ev6__ -Acpu=ev6"
-
-/* Common combinations. */
-#define CPP_CPU_EV4_SPEC "%(cpp_im_ev4)"
-#define CPP_CPU_EV5_SPEC "%(cpp_im_ev5)"
-#define CPP_CPU_EV56_SPEC "%(cpp_im_ev5) %(cpp_am_bwx)"
-#define CPP_CPU_PCA56_SPEC "%(cpp_im_ev5) %(cpp_am_bwx) %(cpp_am_max)"
-#define CPP_CPU_EV6_SPEC \
- "%(cpp_im_ev6) %(cpp_am_bwx) %(cpp_am_max) %(cpp_am_fix)"
-#define CPP_CPU_EV67_SPEC \
- "%(cpp_im_ev6) %(cpp_am_bwx) %(cpp_am_max) %(cpp_am_fix) %(cpp_am_cix)"
-
-#ifndef CPP_CPU_DEFAULT_SPEC
-# if TARGET_CPU_DEFAULT & MASK_CPU_EV6
-# if TARGET_CPU_DEFAULT & MASK_CIX
-# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV67_SPEC
-# else
-# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV6_SPEC
-# endif
-# else
-# if TARGET_CPU_DEFAULT & MASK_CPU_EV5
-# if TARGET_CPU_DEFAULT & MASK_MAX
-# define CPP_CPU_DEFAULT_SPEC CPP_CPU_PCA56_SPEC
-# else
-# if TARGET_CPU_DEFAULT & MASK_BWX
-# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV56_SPEC
-# else
-# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV5_SPEC
-# endif
-# endif
-# else
-# define CPP_CPU_DEFAULT_SPEC CPP_CPU_EV4_SPEC
-# endif
-# endif
-#endif /* CPP_CPU_DEFAULT_SPEC */
-
-#ifndef CPP_CPU_SPEC
-#define CPP_CPU_SPEC "\
-%{!undef:-Acpu=alpha -Amachine=alpha -D__alpha -D__alpha__ \
-%{mcpu=ev4|mcpu=21064:%(cpp_cpu_ev4) }\
-%{mcpu=ev5|mcpu=21164:%(cpp_cpu_ev5) }\
-%{mcpu=ev56|mcpu=21164a:%(cpp_cpu_ev56) }\
-%{mcpu=pca56|mcpu=21164pc|mcpu=21164PC:%(cpp_cpu_pca56) }\
-%{mcpu=ev6|mcpu=21264:%(cpp_cpu_ev6) }\
-%{mcpu=ev67|mcpu=21264a:%(cpp_cpu_ev67) }\
-%{!mcpu*:%(cpp_cpu_default) }}"
-#endif
-
/* This macro defines names of additional specifications to put in the
specs that can be used in various specifications like CC1_SPEC. Its
definition is an initializer with a subgrouping for each command option.
@@ -359,21 +370,6 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */
#endif
#define EXTRA_SPECS \
- { "cpp_am_bwx", CPP_AM_BWX_SPEC }, \
- { "cpp_am_max", CPP_AM_MAX_SPEC }, \
- { "cpp_am_fix", CPP_AM_FIX_SPEC }, \
- { "cpp_am_cix", CPP_AM_CIX_SPEC }, \
- { "cpp_im_ev4", CPP_IM_EV4_SPEC }, \
- { "cpp_im_ev5", CPP_IM_EV5_SPEC }, \
- { "cpp_im_ev6", CPP_IM_EV6_SPEC }, \
- { "cpp_cpu_ev4", CPP_CPU_EV4_SPEC }, \
- { "cpp_cpu_ev5", CPP_CPU_EV5_SPEC }, \
- { "cpp_cpu_ev56", CPP_CPU_EV56_SPEC }, \
- { "cpp_cpu_pca56", CPP_CPU_PCA56_SPEC }, \
- { "cpp_cpu_ev6", CPP_CPU_EV6_SPEC }, \
- { "cpp_cpu_ev67", CPP_CPU_EV67_SPEC }, \
- { "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \
- { "cpp_cpu", CPP_CPU_SPEC }, \
{ "cpp_subtarget", CPP_SUBTARGET_SPEC }, \
SUBTARGET_EXTRA_SPECS
@@ -409,15 +405,16 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */
/* target machine storage layout */
-/* Define to enable software floating point emulation. */
-#define REAL_ARITHMETIC
-
/* Define the size of `int'. The default is the same as the word size. */
#define INT_TYPE_SIZE 32
/* Define the size of `long long'. The default is the twice the word size. */
#define LONG_LONG_TYPE_SIZE 64
+/* We're IEEE unless someone says to use VAX. */
+#define TARGET_FLOAT_FORMAT \
+ (TARGET_FLOAT_VAX ? VAX_FLOAT_FORMAT : IEEE_FLOAT_FORMAT)
+
/* The two floating-point formats we support are S-floating, which is
4 bytes, and T-floating, which is 8 bytes. `float' is S and `double'
and `long double' are T. */
@@ -474,15 +471,6 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */
for them. Might as well be consistent with bytes. */
#define WORDS_BIG_ENDIAN 0
-/* number of bits in an addressable storage unit */
-#define BITS_PER_UNIT 8
-
-/* Width in bits of a "word", which is the contents of a machine register.
- Note that this is not necessarily the width of data type `int';
- if using 16-bit ints on a 68000, this would still be 32.
- But on a machine with 16-bit registers, this would be 16. */
-#define BITS_PER_WORD 64
-
/* Width of a word, in units (bytes). */
#define UNITS_PER_WORD 8
@@ -505,7 +493,7 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */
/* Every structure's size must be a multiple of this. */
#define STRUCTURE_SIZE_BOUNDARY 8
-/* A bitfield declared as `int' forces `int' alignment for the struct. */
+/* A bit-field declared as `int' forces `int' alignment for the struct. */
#define PCC_BITFIELD_TYPE_MATTERS 1
/* No data type wants to be aligned rounder than this. */
@@ -524,14 +512,14 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */
#define DATA_ALIGNMENT(EXP, ALIGN) MAX ((ALIGN), BITS_PER_WORD)
#endif
-/* Set this non-zero if move instructions will actually fail to work
+/* Set this nonzero if move instructions will actually fail to work
when given unaligned data.
Since we get an error message when we do one, call them invalid. */
#define STRICT_ALIGNMENT 1
-/* Set this non-zero if unaligned move instructions are extremely slow.
+/* Set this nonzero if unaligned move instructions are extremely slow.
On the Alpha, they trap. */
@@ -640,6 +628,12 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */
? GET_MODE_UNIT_SIZE (MODE) == 8 || GET_MODE_UNIT_SIZE (MODE) == 4 \
: 1)
+/* Value is 1 if MODE is a supported vector mode. */
+
+#define VECTOR_MODE_SUPPORTED_P(MODE) \
+ (TARGET_MAX \
+ && ((MODE) == V8QImode || (MODE) == V4HImode || (MODE) == V2SImode))
+
/* A C expression that is nonzero if a value of mode
MODE1 is accessible in mode MODE2 without copying.
@@ -719,7 +713,7 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */
class that represents their union. */
enum reg_class {
- NO_REGS, R24_REG, R25_REG, R27_REG,
+ NO_REGS, R0_REG, R24_REG, R25_REG, R27_REG,
GENERAL_REGS, FLOAT_REGS, ALL_REGS,
LIM_REG_CLASSES
};
@@ -728,8 +722,8 @@ enum reg_class {
/* Give names of register classes as strings for dump file. */
-#define REG_CLASS_NAMES \
- {"NO_REGS", "R24_REG", "R25_REG", "R27_REG", \
+#define REG_CLASS_NAMES \
+ {"NO_REGS", "R0_REG", "R24_REG", "R25_REG", "R27_REG", \
"GENERAL_REGS", "FLOAT_REGS", "ALL_REGS" }
/* Define which registers fit in which classes.
@@ -738,6 +732,7 @@ enum reg_class {
#define REG_CLASS_CONTENTS \
{ {0x00000000, 0x00000000}, /* NO_REGS */ \
+ {0x00000001, 0x00000000}, /* R0_REG */ \
{0x01000000, 0x00000000}, /* R24_REG */ \
{0x02000000, 0x00000000}, /* R25_REG */ \
{0x08000000, 0x00000000}, /* R27_REG */ \
@@ -751,7 +746,8 @@ enum reg_class {
or could index an array. */
#define REGNO_REG_CLASS(REGNO) \
- ((REGNO) == 24 ? R24_REG \
+ ((REGNO) == 0 ? R0_REG \
+ : (REGNO) == 24 ? R24_REG \
: (REGNO) == 25 ? R25_REG \
: (REGNO) == 27 ? R27_REG \
: (REGNO) >= 32 && (REGNO) <= 62 ? FLOAT_REGS \
@@ -768,6 +764,7 @@ enum reg_class {
: (C) == 'b' ? R25_REG \
: (C) == 'c' ? R27_REG \
: (C) == 'f' ? FLOAT_REGS \
+ : (C) == 'v' ? R0_REG \
: NO_REGS)
/* Define this macro to change register usage conditional on target flags. */
@@ -811,7 +808,9 @@ enum reg_class {
'T' is a HIGH.
- 'U' is a symbolic operand. */
+ 'U' is a symbolic operand.
+
+ 'W' is a vector zero. */
#define EXTRA_CONSTRAINT alpha_extra_constraint
@@ -858,15 +857,11 @@ enum reg_class {
#define CLASS_MAX_NREGS(CLASS, MODE) \
((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 mode of the object illegally. */
-
-#define CLASS_CANNOT_CHANGE_MODE FLOAT_REGS
+/* Return the class of registers that cannot change mode from FROM to TO. */
-/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE. */
-
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? reg_classes_intersect_p (FLOAT_REGS, CLASS) : 0)
/* Define the cost of moving between registers of various classes. Moving
between FLOAT_REGS and anything else except float regs is expensive.
@@ -1172,12 +1167,11 @@ extern int alpha_memory_latency;
/* We do not allow indirect calls to be optimized into sibling calls, nor
can we allow a call to a function in a different compilation unit to
- be optimized into a sibcall. Except if the function is known not to
- return, in which case our caller doesn't care what the gp is. */
+ be optimized into a sibcall. */
#define FUNCTION_OK_FOR_SIBCALL(DECL) \
(DECL \
- && ((TREE_ASM_WRITTEN (DECL) && !flag_pic) \
- || ! TREE_PUBLIC (DECL)))
+ && (! TREE_PUBLIC (DECL) \
+ || (TREE_ASM_WRITTEN (DECL) && (*targetm.binds_local_p) (DECL))))
/* Try to output insns to set TARGET equal to the constant C if it can be
done in less than N insns. Do all computations in MODE. Returns the place
@@ -1474,7 +1468,7 @@ do { \
#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TImode)
/* Nonzero if access to memory by bytes is no faster than for words.
- Also non-zero if doing byte operations (specifically shifts) in registers
+ Also nonzero if doing byte operations (specifically shifts) in registers
is undesirable.
On the Alpha, we want to not use the byte operation and instead use
@@ -1730,60 +1724,6 @@ do { \
#define DATA_SECTION_ASM_OP "\t.data"
-/* Define an extra section for read-only data, a routine to enter it, and
- indicate that it is for read-only data.
-
- The first time we enter the readonly data section for a file, we write
- eight bytes of zero. This works around a bug in DEC's assembler in
- some versions of OSF/1 V3.x. */
-
-#define EXTRA_SECTIONS readonly_data
-
-#define EXTRA_SECTION_FUNCTIONS \
-void \
-literal_section () \
-{ \
- if (in_section != readonly_data) \
- { \
- static int firsttime = 1; \
- \
- fprintf (asm_out_file, "%s\n", READONLY_DATA_SECTION_ASM_OP); \
- if (firsttime) \
- { \
- firsttime = 0; \
- assemble_aligned_integer (8, const0_rtx); \
- } \
- \
- in_section = readonly_data; \
- } \
-} \
-
-#define READONLY_DATA_SECTION literal_section
-
-/* Define this macro if references to a symbol must be treated differently
- depending on something about the variable or function named by the symbol
- (such as what section it is in). */
-
-#define ENCODE_SECTION_INFO(DECL) alpha_encode_section_info (DECL)
-
-/* If a variable is weakened, made one only or moved into a different
- section, it may be necessary to redo the section info to move the
- variable out of sdata. */
-
-#define REDO_SECTION_INFO_P(DECL) \
- ((TREE_CODE (DECL) == VAR_DECL) \
- && (DECL_ONE_ONLY (DECL) || DECL_WEAK (DECL) || DECL_COMMON (DECL) \
- || DECL_SECTION_NAME (DECL) != 0))
-
-#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
-do { \
- (VAR) = (SYMBOL_NAME); \
- if ((VAR)[0] == '@') \
- (VAR) += 2; \
- if ((VAR)[0] == '*') \
- (VAR)++; \
-} while (0)
-
/* How to refer to registers in assembler output.
This sequence is indexed by compiler's hard-register-number (see above). */
@@ -1802,7 +1742,7 @@ do { \
#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
do { \
const char *name_ = NAME; \
- if (*name_ == '@') \
+ if (*name_ == '@' || *name_ == '%') \
name_ += 2; \
if (*name_ == '*') \
name_++; \
@@ -1811,17 +1751,8 @@ do { \
fputs (name_, STREAM); \
} while (0)
-/* This is how to output the definition of a user-level label named NAME,
- such as the label on a static function or variable NAME. */
-
-#define ASM_OUTPUT_LABEL(FILE,NAME) \
- do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
-
-/* This is how to output a command to make the user-level label named NAME
- defined for reference from other files. */
-
-#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
- do { fputs ("\t.globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.globl "
/* The prefix to add to user-visible assembler symbols. */
@@ -1848,11 +1779,6 @@ do { \
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
sprintf ((LABEL), "*$%s%ld", (PREFIX), (long)(NUM))
-/* Check a floating-point value for validity for a particular machine mode. */
-
-#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \
- ((OVERFLOW) = check_float_value (MODE, &D, OVERFLOW))
-
/* We use the default ASCII-output routine, except that we don't write more
than 50 characters since the assembler doesn't support very long lines. */
@@ -1985,7 +1911,7 @@ do { \
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
((CODE) == '/' || (CODE) == ',' || (CODE) == '-' || (CODE) == '~' \
- || (CODE) == '#' || (CODE) == '*')
+ || (CODE) == '#' || (CODE) == '*' || (CODE) == '&')
/* Print a memory address as an operand to reference that memory location. */
@@ -1995,9 +1921,11 @@ do { \
/* Define the codes that are matched by predicates in alpha.c. */
#define PREDICATE_CODES \
- {"reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \
+ {"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, \
+ CONST_VECTOR}}, \
{"reg_or_6bit_operand", {SUBREG, REG, CONST_INT}}, \
{"reg_or_8bit_operand", {SUBREG, REG, CONST_INT}}, \
+ {"reg_or_const_int_operand", {SUBREG, REG, CONST_INT}}, \
{"cint8_operand", {CONST_INT}}, \
{"reg_or_cint_operand", {SUBREG, REG, CONST_INT}}, \
{"add_operand", {SUBREG, REG, CONST_INT}}, \
@@ -2008,24 +1936,29 @@ do { \
{"mode_mask_operand", {CONST_INT}}, \
{"mul8_operand", {CONST_INT}}, \
{"mode_width_operand", {CONST_INT}}, \
- {"reg_or_fp0_operand", {SUBREG, REG, CONST_DOUBLE}}, \
{"alpha_comparison_operator", {EQ, LE, LT, LEU, LTU}}, \
{"alpha_zero_comparison_operator", {EQ, NE, LE, LT, LEU, LTU}}, \
{"alpha_swapped_comparison_operator", {EQ, GE, GT, GEU, GTU}}, \
{"signed_comparison_operator", {EQ, NE, LE, LT, GE, GT}}, \
{"alpha_fp_comparison_operator", {EQ, LE, LT, UNORDERED}}, \
{"divmod_operator", {DIV, MOD, UDIV, UMOD}}, \
- {"fp0_operand", {CONST_DOUBLE}}, \
+ {"const0_operand", {CONST_INT, CONST_DOUBLE, CONST_VECTOR}}, \
{"current_file_function_operand", {SYMBOL_REF}}, \
{"direct_call_operand", {SYMBOL_REF}}, \
{"local_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
{"small_symbolic_operand", {SYMBOL_REF, CONST}}, \
{"global_symbolic_operand", {SYMBOL_REF, CONST}}, \
+ {"dtp16_symbolic_operand", {CONST}}, \
+ {"dtp32_symbolic_operand", {CONST}}, \
+ {"gotdtp_symbolic_operand", {CONST}}, \
+ {"tp16_symbolic_operand", {CONST}}, \
+ {"tp32_symbolic_operand", {CONST}}, \
+ {"gottp_symbolic_operand", {CONST}}, \
{"call_operand", {REG, SYMBOL_REF}}, \
{"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \
- SYMBOL_REF, CONST, LABEL_REF, HIGH}}, \
+ CONST_VECTOR, SYMBOL_REF, CONST, LABEL_REF, HIGH}},\
{"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \
- SYMBOL_REF, CONST, LABEL_REF, HIGH}}, \
+ CONST_VECTOR, SYMBOL_REF, CONST, LABEL_REF, HIGH}}, \
{"some_ni_operand", {SUBREG, REG, MEM}}, \
{"aligned_memory_operand", {MEM}}, \
{"unaligned_memory_operand", {MEM}}, \
@@ -2045,8 +1978,8 @@ do { \
(VALIST) = alpha_build_va_list ()
/* Implement `va_start' for varargs and stdarg. */
-#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
- alpha_va_start (stdarg, valist, nextarg)
+#define EXPAND_BUILTIN_VA_START(valist, nextarg) \
+ alpha_va_start (valist, nextarg)
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
@@ -2061,9 +1994,9 @@ do { \
/* Definitions for debugging. */
-#define SDB_DEBUGGING_INFO /* generate info for mips-tfile */
-#define DBX_DEBUGGING_INFO /* generate embedded stabs */
-#define MIPS_DEBUGGING_INFO /* MIPS specific debugging info */
+#define SDB_DEBUGGING_INFO 1 /* generate info for mips-tfile */
+#define DBX_DEBUGGING_INFO 1 /* generate embedded stabs */
+#define MIPS_DEBUGGING_INFO 1 /* MIPS specific debugging info */
#ifndef PREFERRED_DEBUGGING_TYPE /* assume SDB_DEBUGGING_INFO */
#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG
@@ -2201,8 +2134,3 @@ do { \
/* Generate calls to memcpy, etc., not bcopy, etc. */
#define TARGET_MEM_FUNCTIONS 1
-
-/* 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) \
- alpha_output_mi_thunk_osf (FILE, THUNK_FNDECL, DELTA, FUNCTION)
diff --git a/contrib/gcc/config/alpha/alpha.md b/contrib/gcc/config/alpha/alpha.md
index 1875b80..a4c0ae6 100644
--- a/contrib/gcc/config/alpha/alpha.md
+++ b/contrib/gcc/config/alpha/alpha.md
@@ -1,6 +1,6 @@
;; Machine description for DEC Alpha for GNU C compiler
;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-;; 2000, 2001 Free Software Foundation, Inc.
+;; 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
;;
;; This file is part of GNU CC.
@@ -40,6 +40,24 @@
(UNSPEC_LITUSE 12)
(UNSPEC_SIBCALL 13)
(UNSPEC_SYMBOL 14)
+
+ ;; TLS Support
+ (UNSPEC_TLSGD_CALL 15)
+ (UNSPEC_TLSLDM_CALL 16)
+ (UNSPEC_TLSGD 17)
+ (UNSPEC_TLSLDM 18)
+ (UNSPEC_DTPREL 19)
+ (UNSPEC_TPREL 20)
+ (UNSPEC_TP 21)
+
+ ;; Builtins
+ (UNSPEC_CMPBGE 22)
+ (UNSPEC_ZAP 23)
+ (UNSPEC_AMASK 24)
+ (UNSPEC_IMPLVER 25)
+ (UNSPEC_PERR 26)
+ (UNSPEC_CTLZ 27)
+ (UNSPEC_CTPOP 28)
])
;; UNSPEC_VOLATILE:
@@ -57,6 +75,8 @@
(UNSPECV_FORCE_MOV 9)
(UNSPECV_LDGP1 10)
(UNSPECV_PLDGP2 11) ; prologue ldgp
+ (UNSPECV_SET_TP 12)
+ (UNSPECV_RPCC 13)
])
;; Where necessary, the suffixes _le and _be are used to distinguish between
@@ -77,8 +97,8 @@
;; separately.
(define_attr "type"
- "ild,fld,ldsym,ist,fst,ibr,fbr,jsr,iadd,ilog,shift,icmov,fcmov,icmp,imul,\
-fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
+ "ild,fld,ldsym,ist,fst,ibr,callpal,fbr,jsr,iadd,ilog,shift,icmov,fcmov,icmp,imul,\
+fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none"
(const_string "iadd"))
;; Describe a user's asm statement.
@@ -122,314 +142,24 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_attr "length" ""
(const_int 4))
-
-;; On EV4 there are two classes of resources to consider: resources needed
-;; to issue, and resources needed to execute. IBUS[01] are in the first
-;; category. ABOX, BBOX, EBOX, FBOX, IMUL & FDIV make up the second.
-;; (There are a few other register-like resources, but ...)
-
-; First, describe all of the issue constraints with single cycle delays.
-; All insns need a bus, but all except loads require one or the other.
-(define_function_unit "ev4_ibus0" 1 0
- (and (eq_attr "cpu" "ev4")
- (eq_attr "type" "fst,fbr,iadd,imul,ilog,shift,icmov,icmp"))
- 1 1)
-
-(define_function_unit "ev4_ibus1" 1 0
- (and (eq_attr "cpu" "ev4")
- (eq_attr "type" "ist,ibr,jsr,fadd,fcmov,fcpys,fmul,fdiv,misc"))
- 1 1)
-
-; Memory delivers its result in three cycles. Actually return one and
-; take care of this in adjust_cost, since we want to handle user-defined
-; memory latencies.
-(define_function_unit "ev4_abox" 1 0
- (and (eq_attr "cpu" "ev4")
- (eq_attr "type" "ild,fld,ldsym,ist,fst"))
- 1 1)
-
-; Branches have no delay cost, but do tie up the unit for two cycles.
-(define_function_unit "ev4_bbox" 1 1
- (and (eq_attr "cpu" "ev4")
- (eq_attr "type" "ibr,fbr,jsr"))
- 2 2)
-
-; Arithmetic insns are normally have their results available after
-; two cycles. There are a number of exceptions. They are encoded in
-; ADJUST_COST. Some of the other insns have similar exceptions.
-(define_function_unit "ev4_ebox" 1 0
- (and (eq_attr "cpu" "ev4")
- (eq_attr "type" "iadd,ilog,shift,icmov,icmp,misc"))
- 2 1)
-
-(define_function_unit "imul" 1 0
- (and (eq_attr "cpu" "ev4")
- (and (eq_attr "type" "imul")
- (eq_attr "opsize" "si")))
- 21 19)
-
-(define_function_unit "imul" 1 0
- (and (eq_attr "cpu" "ev4")
- (and (eq_attr "type" "imul")
- (eq_attr "opsize" "!si")))
- 23 21)
-
-(define_function_unit "ev4_fbox" 1 0
- (and (eq_attr "cpu" "ev4")
- (eq_attr "type" "fadd,fmul,fcpys,fcmov"))
- 6 1)
-
-(define_function_unit "fdiv" 1 0
- (and (eq_attr "cpu" "ev4")
- (and (eq_attr "type" "fdiv")
- (eq_attr "opsize" "si")))
- 34 30)
-
-(define_function_unit "fdiv" 1 0
- (and (eq_attr "cpu" "ev4")
- (and (eq_attr "type" "fdiv")
- (eq_attr "opsize" "di")))
- 63 59)
-
-;; EV5 scheduling. EV5 can issue 4 insns per clock.
-;;
-;; EV5 has two asymetric integer units. Model this with E0 & E1 along
-;; with the combined resource EBOX.
-
-(define_function_unit "ev5_ebox" 2 0
- (and (eq_attr "cpu" "ev5")
- (eq_attr "type" "!fbr,fcmov,fadd,fmul,fcpys,fdiv"))
- 1 1)
-
-; Memory takes at least 2 clocks. Return one from here and fix up with
-; user-defined latencies in adjust_cost.
-(define_function_unit "ev5_ebox" 2 0
- (and (eq_attr "cpu" "ev5")
- (eq_attr "type" "ild,fld,ldsym"))
- 1 1)
-
-; Loads can dual issue with one another, but loads and stores do not mix.
-(define_function_unit "ev5_e0" 1 0
- (and (eq_attr "cpu" "ev5")
- (eq_attr "type" "ild,fld,ldsym"))
- 1 1
- [(eq_attr "type" "ist,fst")])
-
-; Stores, shifts, multiplies can only issue to E0
-(define_function_unit "ev5_e0" 1 0
- (and (eq_attr "cpu" "ev5")
- (eq_attr "type" "ist,fst,shift,imul"))
- 1 1)
-
-; Motion video insns also issue only to E0, and take two ticks.
-(define_function_unit "ev5_e0" 1 0
- (and (eq_attr "cpu" "ev5")
- (eq_attr "type" "mvi"))
- 2 1)
-
-; Conditional moves always take 2 ticks.
-(define_function_unit "ev5_ebox" 2 0
- (and (eq_attr "cpu" "ev5")
- (eq_attr "type" "icmov"))
- 2 1)
-
-; Branches can only issue to E1
-(define_function_unit "ev5_e1" 1 0
- (and (eq_attr "cpu" "ev5")
- (eq_attr "type" "ibr,jsr"))
- 1 1)
-
-; Multiplies also use the integer multiplier.
-; ??? How to: "No instruction can be issued to pipe E0 exactly two
-; cycles before an integer multiplication completes."
-(define_function_unit "imul" 1 0
- (and (eq_attr "cpu" "ev5")
- (and (eq_attr "type" "imul")
- (eq_attr "opsize" "si")))
- 8 4)
-
-(define_function_unit "imul" 1 0
- (and (eq_attr "cpu" "ev5")
- (and (eq_attr "type" "imul")
- (eq_attr "opsize" "di")))
- 12 8)
-
-(define_function_unit "imul" 1 0
- (and (eq_attr "cpu" "ev5")
- (and (eq_attr "type" "imul")
- (eq_attr "opsize" "udi")))
- 14 8)
-
-;; Similarly for the FPU we have two asymetric units. But fcpys can issue
-;; on either so we have to play the game again.
-
-(define_function_unit "ev5_fbox" 2 0
- (and (eq_attr "cpu" "ev5")
- (eq_attr "type" "fadd,fcmov,fmul,fcpys,fbr,fdiv"))
- 4 1)
-
-(define_function_unit "ev5_fm" 1 0
- (and (eq_attr "cpu" "ev5")
- (eq_attr "type" "fmul"))
- 4 1)
-
-; Add and cmov as you would expect; fbr never produces a result;
-; fdiv issues through fa to the divider,
-(define_function_unit "ev5_fa" 1 0
- (and (eq_attr "cpu" "ev5")
- (eq_attr "type" "fadd,fcmov,fbr,fdiv"))
- 4 1)
-
-; ??? How to: "No instruction can be issued to pipe FA exactly five
-; cycles before a floating point divide completes."
-(define_function_unit "fdiv" 1 0
- (and (eq_attr "cpu" "ev5")
- (and (eq_attr "type" "fdiv")
- (eq_attr "opsize" "si")))
- 15 15) ; 15 to 31 data dependent
-
-(define_function_unit "fdiv" 1 0
- (and (eq_attr "cpu" "ev5")
- (and (eq_attr "type" "fdiv")
- (eq_attr "opsize" "di")))
- 22 22) ; 22 to 60 data dependent
-
-;; EV6 scheduling. EV6 can issue 4 insns per clock.
-;;
-;; EV6 has two symmetric pairs ("clusters") of two asymetric integer units
-;; ("upper" and "lower"), yielding pipe names U0, U1, L0, L1.
-
-;; Conditional moves decompose into two independent primitives, each
-;; taking one cycle. Since ev6 is out-of-order, we can't see anything
-;; but two cycles.
-(define_function_unit "ev6_ebox" 4 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "icmov"))
- 2 1)
-
-(define_function_unit "ev6_ebox" 4 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "!fbr,fcmov,fadd,fmul,fcpys,fdiv,fsqrt"))
- 1 1)
-
-;; Integer loads take at least 3 clocks, and only issue to lower units.
-;; Return one from here and fix up with user-defined latencies in adjust_cost.
-(define_function_unit "ev6_l" 2 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "ild,ldsym,ist,fst"))
- 1 1)
-
-;; FP loads take at least 4 clocks. Return two from here...
-(define_function_unit "ev6_l" 2 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "fld"))
- 2 1)
-
-;; Motion video insns also issue only to U0, and take three ticks.
-(define_function_unit "ev6_u0" 1 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "mvi"))
- 3 1)
-
-(define_function_unit "ev6_u" 2 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "mvi"))
- 3 1)
-
-;; Shifts issue to either upper pipe.
-(define_function_unit "ev6_u" 2 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "shift"))
- 1 1)
-
-;; Multiplies issue only to U1, and all take 7 ticks.
-;; Rather than create a new function unit just for U1, reuse IMUL
-(define_function_unit "imul" 1 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "imul"))
- 7 1)
-
-(define_function_unit "ev6_u" 2 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "imul"))
- 7 1)
-
-;; Branches issue to either upper pipe
-(define_function_unit "ev6_u" 2 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "ibr"))
- 3 1)
-
-;; Calls only issue to L0.
-(define_function_unit "ev6_l0" 1 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "jsr"))
- 1 1)
-
-(define_function_unit "ev6_l" 2 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "jsr"))
- 1 1)
-
-;; Ftoi/itof only issue to lower pipes
-(define_function_unit "ev6_l" 2 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "ftoi"))
- 3 1)
-
-(define_function_unit "ev6_l" 2 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "itof"))
- 4 1)
-
-;; For the FPU we are very similar to EV5, except there's no insn that
-;; can issue to fm & fa, so we get to leave that out.
-
-(define_function_unit "ev6_fm" 1 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "fmul"))
- 4 1)
-
-(define_function_unit "ev6_fa" 1 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "fadd,fcpys,fbr,fdiv,fsqrt"))
- 4 1)
-
-(define_function_unit "ev6_fa" 1 0
- (and (eq_attr "cpu" "ev6")
- (eq_attr "type" "fcmov"))
- 8 1)
-
-(define_function_unit "fdiv" 1 0
- (and (eq_attr "cpu" "ev6")
- (and (eq_attr "type" "fdiv")
- (eq_attr "opsize" "si")))
- 12 10)
-
-(define_function_unit "fdiv" 1 0
- (and (eq_attr "cpu" "ev6")
- (and (eq_attr "type" "fdiv")
- (eq_attr "opsize" "di")))
- 15 13)
-
-(define_function_unit "fsqrt" 1 0
- (and (eq_attr "cpu" "ev6")
- (and (eq_attr "type" "fsqrt")
- (eq_attr "opsize" "si")))
- 16 14)
-
-(define_function_unit "fsqrt" 1 0
- (and (eq_attr "cpu" "ev6")
- (and (eq_attr "type" "fsqrt")
- (eq_attr "opsize" "di")))
- 32 30)
-
-; ??? The FPU communicates with memory and the integer register file
-; via two fp store units. We need a slot in the fst immediately, and
-; a slot in LOW after the operand data is ready. At which point the
-; data may be moved either to the store queue or the integer register
-; file and the insn retired.
+;; The USEGP attribute marks instructions that have relocations that use
+;; the GP.
+
+(define_attr "usegp" "no,yes"
+ (cond [(eq_attr "type" "ldsym,jsr")
+ (const_string "yes")
+ (eq_attr "type" "ild,fld,ist,fst")
+ (symbol_ref "alpha_find_lo_sum_using_gp(insn)")
+ ]
+ (const_string "no")))
+
+
+;; Include scheduling descriptions.
+
+(include "ev4.md")
+(include "ev5.md")
+(include "ev6.md")
;; First define the arithmetic insns. Note that the 32-bit forms also
;; sign-extend.
@@ -453,7 +183,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:SI 1 "nonimmediate_operand" "r,m,*f,m")))]
"! TARGET_FIX"
"@
- addl %1,$31,%0
+ addl $31,%1,%0
ldl %0,%1
cvtlq %1,%0
lds %0,%1\;cvtlq %0,%0"
@@ -466,7 +196,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:SI 1 "nonimmediate_operand" "r,m,*f,*f,m")))]
"TARGET_FIX"
"@
- addl %1,$31,%0
+ addl $31,%1,%0
ldl %0,%1
ftois %1,%0
cvtlq %1,%0
@@ -637,12 +367,55 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
""
"")
+(define_insn "*adddi_er_lo16_dtp"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "dtp16_symbolic_operand" "")))]
+ "HAVE_AS_TLS"
+ "lda %0,%2(%1)\t\t!dtprel")
+
+(define_insn "*adddi_er_hi32_dtp"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (high:DI (match_operand:DI 2 "dtp32_symbolic_operand" ""))))]
+ "HAVE_AS_TLS"
+ "ldah %0,%2(%1)\t\t!dtprelhi")
+
+(define_insn "*adddi_er_lo32_dtp"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "dtp32_symbolic_operand" "")))]
+ "HAVE_AS_TLS"
+ "lda %0,%2(%1)\t\t!dtprello")
+
+(define_insn "*adddi_er_lo16_tp"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "tp16_symbolic_operand" "")))]
+ "HAVE_AS_TLS"
+ "lda %0,%2(%1)\t\t!tprel")
+
+(define_insn "*adddi_er_hi32_tp"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (high:DI (match_operand:DI 2 "tp32_symbolic_operand" ""))))]
+ "HAVE_AS_TLS"
+ "ldah %0,%2(%1)\t\t!tprelhi")
+
+(define_insn "*adddi_er_lo32_tp"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "tp32_symbolic_operand" "")))]
+ "HAVE_AS_TLS"
+ "lda %0,%2(%1)\t\t!tprello")
+
(define_insn "*adddi_er_high_l"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "register_operand" "r")
(high:DI (match_operand:DI 2 "local_symbolic_operand" ""))))]
"TARGET_EXPLICIT_RELOCS"
- "ldah %0,%2(%1)\t\t!gprelhigh")
+ "ldah %0,%2(%1)\t\t!gprelhigh"
+ [(set_attr "usegp" "yes")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -977,17 +750,31 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
"mulqv %r1,%2,%0"
[(set_attr "type" "imul")])
-(define_insn "umuldi3_highpart"
+(define_expand "umuldi3_highpart"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "register_operand" ""))
+ (match_operand:DI 2 "reg_or_8bit_operand" ""))
+ (const_int 64))))]
+ ""
+{
+ if (REG_P (operands[2]))
+ operands[2] = gen_rtx_ZERO_EXTEND (TImode, operands[2]);
+})
+
+(define_insn "*umuldi3_highpart_reg"
[(set (match_operand:DI 0 "register_operand" "=r")
(truncate:DI
(lshiftrt:TI
(mult:TI (zero_extend:TI
- (match_operand:DI 1 "reg_or_0_operand" "%rJ"))
+ (match_operand:DI 1 "register_operand" "r"))
(zero_extend:TI
- (match_operand:DI 2 "reg_or_8bit_operand" "rI")))
+ (match_operand:DI 2 "register_operand" "r")))
(const_int 64))))]
""
- "umulh %r1,%2,%0"
+ "umulh %1,%2,%0"
[(set_attr "type" "imul")
(set_attr "opsize" "udi")])
@@ -1973,7 +1760,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
"ext%M2l %r1,%3,%0"
[(set_attr "type" "shift")])
-;; Combine has some strange notion of preserving existing undefined behaviour
+;; Combine has some strange notion of preserving existing undefined behavior
;; in shifts larger than a word size. So capture these patterns that it
;; should have turned into zero_extracts.
@@ -2346,35 +2133,35 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "abssf2"
[(set (match_operand:SF 0 "register_operand" "=f")
- (abs:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))]
+ (abs:SF (match_operand:SF 1 "reg_or_0_operand" "fG")))]
"TARGET_FP"
"cpys $f31,%R1,%0"
[(set_attr "type" "fcpys")])
(define_insn "*nabssf2"
[(set (match_operand:SF 0 "register_operand" "=f")
- (neg:SF (abs:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))]
+ (neg:SF (abs:SF (match_operand:SF 1 "reg_or_0_operand" "fG"))))]
"TARGET_FP"
"cpysn $f31,%R1,%0"
[(set_attr "type" "fadd")])
(define_insn "absdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
- (abs:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+ (abs:DF (match_operand:DF 1 "reg_or_0_operand" "fG")))]
"TARGET_FP"
"cpys $f31,%R1,%0"
[(set_attr "type" "fcpys")])
(define_insn "*nabsdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
- (neg:DF (abs:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG"))))]
+ (neg:DF (abs:DF (match_operand:DF 1 "reg_or_0_operand" "fG"))))]
"TARGET_FP"
"cpysn $f31,%R1,%0"
[(set_attr "type" "fadd")])
(define_expand "abstf2"
[(parallel [(set (match_operand:TF 0 "register_operand" "")
- (abs:TF (match_operand:TF 1 "reg_or_fp0_operand" "")))
+ (abs:TF (match_operand:TF 1 "reg_or_0_operand" "")))
(use (match_dup 2))])]
"TARGET_HAS_XFLOATING_LIBS"
{
@@ -2387,7 +2174,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn_and_split "*abstf_internal"
[(set (match_operand:TF 0 "register_operand" "=r")
- (abs:TF (match_operand:TF 1 "reg_or_fp0_operand" "rG")))
+ (abs:TF (match_operand:TF 1 "reg_or_0_operand" "rG")))
(use (match_operand:DI 2 "register_operand" "r"))]
"TARGET_HAS_XFLOATING_LIBS"
"#"
@@ -2397,21 +2184,21 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "negsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
- (neg:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))]
+ (neg:SF (match_operand:SF 1 "reg_or_0_operand" "fG")))]
"TARGET_FP"
"cpysn %R1,%R1,%0"
[(set_attr "type" "fadd")])
(define_insn "negdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
- (neg:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+ (neg:DF (match_operand:DF 1 "reg_or_0_operand" "fG")))]
"TARGET_FP"
"cpysn %R1,%R1,%0"
[(set_attr "type" "fadd")])
(define_expand "negtf2"
[(parallel [(set (match_operand:TF 0 "register_operand" "")
- (neg:TF (match_operand:TF 1 "reg_or_fp0_operand" "")))
+ (neg:TF (match_operand:TF 1 "reg_or_0_operand" "")))
(use (match_dup 2))])]
"TARGET_HAS_XFLOATING_LIBS"
{
@@ -2424,7 +2211,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn_and_split "*negtf_internal"
[(set (match_operand:TF 0 "register_operand" "=r")
- (neg:TF (match_operand:TF 1 "reg_or_fp0_operand" "rG")))
+ (neg:TF (match_operand:TF 1 "reg_or_0_operand" "rG")))
(use (match_operand:DI 2 "register_operand" "r"))]
"TARGET_HAS_XFLOATING_LIBS"
"#"
@@ -2434,8 +2221,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*addsf_ieee"
[(set (match_operand:SF 0 "register_operand" "=&f")
- (plus:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG")
- (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
+ (plus:SF (match_operand:SF 1 "reg_or_0_operand" "%fG")
+ (match_operand:SF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"add%,%/ %R1,%R2,%0"
[(set_attr "type" "fadd")
@@ -2445,8 +2232,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "addsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
- (plus:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG")
- (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
+ (plus:SF (match_operand:SF 1 "reg_or_0_operand" "%fG")
+ (match_operand:SF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP"
"add%,%/ %R1,%R2,%0"
[(set_attr "type" "fadd")
@@ -2456,8 +2243,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*adddf_ieee"
[(set (match_operand:DF 0 "register_operand" "=&f")
- (plus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG")
- (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+ (plus:DF (match_operand:DF 1 "reg_or_0_operand" "%fG")
+ (match_operand:DF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"add%-%/ %R1,%R2,%0"
[(set_attr "type" "fadd")
@@ -2467,8 +2254,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "adddf3"
[(set (match_operand:DF 0 "register_operand" "=f")
- (plus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG")
- (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+ (plus:DF (match_operand:DF 1 "reg_or_0_operand" "%fG")
+ (match_operand:DF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP"
"add%-%/ %R1,%R2,%0"
[(set_attr "type" "fadd")
@@ -2479,8 +2266,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*adddf_ext1"
[(set (match_operand:DF 0 "register_operand" "=f")
(plus:DF (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" "fG"))
- (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+ (match_operand:SF 1 "reg_or_0_operand" "fG"))
+ (match_operand:DF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"add%-%/ %R1,%R2,%0"
[(set_attr "type" "fadd")
@@ -2491,9 +2278,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*adddf_ext2"
[(set (match_operand:DF 0 "register_operand" "=f")
(plus:DF (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" "%fG"))
+ (match_operand:SF 1 "reg_or_0_operand" "%fG"))
(float_extend:DF
- (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))]
+ (match_operand:SF 2 "reg_or_0_operand" "fG"))))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"add%-%/ %R1,%R2,%0"
[(set_attr "type" "fadd")
@@ -2519,7 +2306,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*cvtql"
[(set (match_operand:SI 0 "register_operand" "=f")
- (unspec:SI [(match_operand:DI 1 "reg_or_fp0_operand" "fG")]
+ (unspec:SI [(match_operand:DI 1 "reg_or_0_operand" "fG")]
UNSPEC_CVTQL))]
"TARGET_FP"
"cvtql%/ %R1,%0"
@@ -2529,7 +2316,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn_and_split "*fix_truncdfsi_ieee"
[(set (match_operand:SI 0 "memory_operand" "=m")
- (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")) 0))
+ (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_0_operand" "fG")) 0))
(clobber (match_scratch:DI 2 "=&f"))
(clobber (match_scratch:SI 3 "=&f"))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
@@ -2544,7 +2331,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn_and_split "*fix_truncdfsi_internal"
[(set (match_operand:SI 0 "memory_operand" "=m")
- (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")) 0))
+ (subreg:SI (fix:DI (match_operand:DF 1 "reg_or_0_operand" "fG")) 0))
(clobber (match_scratch:DI 2 "=f"))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"#"
@@ -2559,7 +2346,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*fix_truncdfdi_ieee"
[(set (match_operand:DI 0 "reg_no_subreg_operand" "=&f")
- (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+ (fix:DI (match_operand:DF 1 "reg_or_0_operand" "fG")))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"cvt%-q%/ %R1,%0"
[(set_attr "type" "fadd")
@@ -2569,7 +2356,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "fix_truncdfdi2"
[(set (match_operand:DI 0 "reg_no_subreg_operand" "=f")
- (fix:DI (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+ (fix:DI (match_operand:DF 1 "reg_or_0_operand" "fG")))]
"TARGET_FP"
"cvt%-q%/ %R1,%0"
[(set_attr "type" "fadd")
@@ -2582,7 +2369,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn_and_split "*fix_truncsfsi_ieee"
[(set (match_operand:SI 0 "memory_operand" "=m")
(subreg:SI (fix:DI (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" "fG"))) 0))
+ (match_operand:SF 1 "reg_or_0_operand" "fG"))) 0))
(clobber (match_scratch:DI 2 "=&f"))
(clobber (match_scratch:SI 3 "=&f"))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
@@ -2598,7 +2385,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn_and_split "*fix_truncsfsi_internal"
[(set (match_operand:SI 0 "memory_operand" "=m")
(subreg:SI (fix:DI (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" "fG"))) 0))
+ (match_operand:SF 1 "reg_or_0_operand" "fG"))) 0))
(clobber (match_scratch:DI 2 "=f"))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"#"
@@ -2614,7 +2401,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*fix_truncsfdi_ieee"
[(set (match_operand:DI 0 "reg_no_subreg_operand" "=&f")
(fix:DI (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))]
+ (match_operand:SF 1 "reg_or_0_operand" "fG"))))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"cvt%-q%/ %R1,%0"
[(set_attr "type" "fadd")
@@ -2625,7 +2412,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "fix_truncsfdi2"
[(set (match_operand:DI 0 "reg_no_subreg_operand" "=f")
(fix:DI (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" "fG"))))]
+ (match_operand:SF 1 "reg_or_0_operand" "fG"))))]
"TARGET_FP"
"cvt%-q%/ %R1,%0"
[(set_attr "type" "fadd")
@@ -2752,7 +2539,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*truncdfsf2_ieee"
[(set (match_operand:SF 0 "register_operand" "=&f")
- (float_truncate:SF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+ (float_truncate:SF (match_operand:DF 1 "reg_or_0_operand" "fG")))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"cvt%-%,%/ %R1,%0"
[(set_attr "type" "fadd")
@@ -2762,7 +2549,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "truncdfsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
- (float_truncate:SF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+ (float_truncate:SF (match_operand:DF 1 "reg_or_0_operand" "fG")))]
"TARGET_FP"
"cvt%-%,%/ %R1,%0"
[(set_attr "type" "fadd")
@@ -2804,8 +2591,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*divsf3_ieee"
[(set (match_operand:SF 0 "register_operand" "=&f")
- (div:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")
- (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
+ (div:SF (match_operand:SF 1 "reg_or_0_operand" "fG")
+ (match_operand:SF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"div%,%/ %R1,%R2,%0"
[(set_attr "type" "fdiv")
@@ -2816,8 +2603,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "divsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
- (div:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")
- (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
+ (div:SF (match_operand:SF 1 "reg_or_0_operand" "fG")
+ (match_operand:SF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP"
"div%,%/ %R1,%R2,%0"
[(set_attr "type" "fdiv")
@@ -2828,8 +2615,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*divdf3_ieee"
[(set (match_operand:DF 0 "register_operand" "=&f")
- (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")
- (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+ (div:DF (match_operand:DF 1 "reg_or_0_operand" "fG")
+ (match_operand:DF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"div%-%/ %R1,%R2,%0"
[(set_attr "type" "fdiv")
@@ -2839,8 +2626,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "divdf3"
[(set (match_operand:DF 0 "register_operand" "=f")
- (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")
- (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+ (div:DF (match_operand:DF 1 "reg_or_0_operand" "fG")
+ (match_operand:DF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP"
"div%-%/ %R1,%R2,%0"
[(set_attr "type" "fdiv")
@@ -2850,8 +2637,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*divdf_ext1"
[(set (match_operand:DF 0 "register_operand" "=f")
- (div:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG"))
- (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+ (div:DF (float_extend:DF (match_operand:SF 1 "reg_or_0_operand" "fG"))
+ (match_operand:DF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"div%-%/ %R1,%R2,%0"
[(set_attr "type" "fdiv")
@@ -2861,9 +2648,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*divdf_ext2"
[(set (match_operand:DF 0 "register_operand" "=f")
- (div:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")
+ (div:DF (match_operand:DF 1 "reg_or_0_operand" "fG")
(float_extend:DF
- (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))]
+ (match_operand:SF 2 "reg_or_0_operand" "fG"))))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"div%-%/ %R1,%R2,%0"
[(set_attr "type" "fdiv")
@@ -2873,8 +2660,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*divdf_ext3"
[(set (match_operand:DF 0 "register_operand" "=f")
- (div:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG"))
- (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))]
+ (div:DF (float_extend:DF (match_operand:SF 1 "reg_or_0_operand" "fG"))
+ (float_extend:DF (match_operand:SF 2 "reg_or_0_operand" "fG"))))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"div%-%/ %R1,%R2,%0"
[(set_attr "type" "fdiv")
@@ -2891,8 +2678,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*mulsf3_ieee"
[(set (match_operand:SF 0 "register_operand" "=&f")
- (mult:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG")
- (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
+ (mult:SF (match_operand:SF 1 "reg_or_0_operand" "%fG")
+ (match_operand:SF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"mul%,%/ %R1,%R2,%0"
[(set_attr "type" "fmul")
@@ -2902,8 +2689,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "mulsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
- (mult:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG")
- (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
+ (mult:SF (match_operand:SF 1 "reg_or_0_operand" "%fG")
+ (match_operand:SF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP"
"mul%,%/ %R1,%R2,%0"
[(set_attr "type" "fmul")
@@ -2913,8 +2700,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*muldf3_ieee"
[(set (match_operand:DF 0 "register_operand" "=&f")
- (mult:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG")
- (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+ (mult:DF (match_operand:DF 1 "reg_or_0_operand" "%fG")
+ (match_operand:DF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"mul%-%/ %R1,%R2,%0"
[(set_attr "type" "fmul")
@@ -2924,8 +2711,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "muldf3"
[(set (match_operand:DF 0 "register_operand" "=f")
- (mult:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG")
- (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+ (mult:DF (match_operand:DF 1 "reg_or_0_operand" "%fG")
+ (match_operand:DF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP"
"mul%-%/ %R1,%R2,%0"
[(set_attr "type" "fmul")
@@ -2936,8 +2723,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*muldf_ext1"
[(set (match_operand:DF 0 "register_operand" "=f")
(mult:DF (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" "fG"))
- (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+ (match_operand:SF 1 "reg_or_0_operand" "fG"))
+ (match_operand:DF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"mul%-%/ %R1,%R2,%0"
[(set_attr "type" "fmul")
@@ -2948,9 +2735,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*muldf_ext2"
[(set (match_operand:DF 0 "register_operand" "=f")
(mult:DF (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" "%fG"))
+ (match_operand:SF 1 "reg_or_0_operand" "%fG"))
(float_extend:DF
- (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))]
+ (match_operand:SF 2 "reg_or_0_operand" "fG"))))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"mul%-%/ %R1,%R2,%0"
[(set_attr "type" "fmul")
@@ -2967,8 +2754,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*subsf3_ieee"
[(set (match_operand:SF 0 "register_operand" "=&f")
- (minus:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")
- (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
+ (minus:SF (match_operand:SF 1 "reg_or_0_operand" "fG")
+ (match_operand:SF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"sub%,%/ %R1,%R2,%0"
[(set_attr "type" "fadd")
@@ -2978,8 +2765,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "subsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
- (minus:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")
- (match_operand:SF 2 "reg_or_fp0_operand" "fG")))]
+ (minus:SF (match_operand:SF 1 "reg_or_0_operand" "fG")
+ (match_operand:SF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP"
"sub%,%/ %R1,%R2,%0"
[(set_attr "type" "fadd")
@@ -2989,8 +2776,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*subdf3_ieee"
[(set (match_operand:DF 0 "register_operand" "=&f")
- (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")
- (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+ (minus:DF (match_operand:DF 1 "reg_or_0_operand" "fG")
+ (match_operand:DF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"sub%-%/ %R1,%R2,%0"
[(set_attr "type" "fadd")
@@ -3000,8 +2787,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "subdf3"
[(set (match_operand:DF 0 "register_operand" "=f")
- (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")
- (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+ (minus:DF (match_operand:DF 1 "reg_or_0_operand" "fG")
+ (match_operand:DF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP"
"sub%-%/ %R1,%R2,%0"
[(set_attr "type" "fadd")
@@ -3012,8 +2799,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*subdf_ext1"
[(set (match_operand:DF 0 "register_operand" "=f")
(minus:DF (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" "fG"))
- (match_operand:DF 2 "reg_or_fp0_operand" "fG")))]
+ (match_operand:SF 1 "reg_or_0_operand" "fG"))
+ (match_operand:DF 2 "reg_or_0_operand" "fG")))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"sub%-%/ %R1,%R2,%0"
[(set_attr "type" "fadd")
@@ -3023,9 +2810,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*subdf_ext2"
[(set (match_operand:DF 0 "register_operand" "=f")
- (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")
+ (minus:DF (match_operand:DF 1 "reg_or_0_operand" "fG")
(float_extend:DF
- (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))]
+ (match_operand:SF 2 "reg_or_0_operand" "fG"))))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"sub%-%/ %R1,%R2,%0"
[(set_attr "type" "fadd")
@@ -3036,9 +2823,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*subdf_ext3"
[(set (match_operand:DF 0 "register_operand" "=f")
(minus:DF (float_extend:DF
- (match_operand:SF 1 "reg_or_fp0_operand" "fG"))
+ (match_operand:SF 1 "reg_or_0_operand" "fG"))
(float_extend:DF
- (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))]
+ (match_operand:SF 2 "reg_or_0_operand" "fG"))))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"sub%-%/ %R1,%R2,%0"
[(set_attr "type" "fadd")
@@ -3055,7 +2842,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*sqrtsf2_ieee"
[(set (match_operand:SF 0 "register_operand" "=&f")
- (sqrt:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))]
+ (sqrt:SF (match_operand:SF 1 "reg_or_0_operand" "fG")))]
"TARGET_FP && TARGET_FIX && alpha_fptm >= ALPHA_FPTM_SU"
"sqrt%,%/ %R1,%0"
[(set_attr "type" "fsqrt")
@@ -3066,7 +2853,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "sqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
- (sqrt:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))]
+ (sqrt:SF (match_operand:SF 1 "reg_or_0_operand" "fG")))]
"TARGET_FP && TARGET_FIX"
"sqrt%,%/ %R1,%0"
[(set_attr "type" "fsqrt")
@@ -3077,7 +2864,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*sqrtdf2_ieee"
[(set (match_operand:DF 0 "register_operand" "=&f")
- (sqrt:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+ (sqrt:DF (match_operand:DF 1 "reg_or_0_operand" "fG")))]
"TARGET_FP && TARGET_FIX && alpha_fptm >= ALPHA_FPTM_SU"
"sqrt%-%/ %R1,%0"
[(set_attr "type" "fsqrt")
@@ -3087,9 +2874,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "sqrtdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
- (sqrt:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
+ (sqrt:DF (match_operand:DF 1 "reg_or_0_operand" "fG")))]
"TARGET_FP && TARGET_FIX"
- "sqrt%-%/ %1,%0"
+ "sqrt%-%/ %R1,%0"
[(set_attr "type" "fsqrt")
(set_attr "trap" "yes")
(set_attr "round_suffix" "normal")
@@ -3462,7 +3249,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:HI 2 "reg_or_8bit_operand" "rI")))]
"TARGET_MAX"
"maxuw4 %r1,%2,%0"
- [(set_attr "type" "shift")])
+ [(set_attr "type" "mvi")])
(define_expand "smaxdi3"
[(set (match_dup 3)
@@ -3647,8 +3434,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*cmpdf_ieee"
[(set (match_operand:DF 0 "register_operand" "=&f")
(match_operator:DF 1 "alpha_fp_comparison_operator"
- [(match_operand:DF 2 "reg_or_fp0_operand" "fG")
- (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
+ [(match_operand:DF 2 "reg_or_0_operand" "fG")
+ (match_operand:DF 3 "reg_or_0_operand" "fG")]))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"cmp%-%C1%/ %R2,%R3,%0"
[(set_attr "type" "fadd")
@@ -3658,8 +3445,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*cmpdf_internal"
[(set (match_operand:DF 0 "register_operand" "=f")
(match_operator:DF 1 "alpha_fp_comparison_operator"
- [(match_operand:DF 2 "reg_or_fp0_operand" "fG")
- (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
+ [(match_operand:DF 2 "reg_or_0_operand" "fG")
+ (match_operand:DF 3 "reg_or_0_operand" "fG")]))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"cmp%-%C1%/ %R2,%R3,%0"
[(set_attr "type" "fadd")
@@ -3670,8 +3457,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set (match_operand:DF 0 "register_operand" "=&f")
(match_operator:DF 1 "alpha_fp_comparison_operator"
[(float_extend:DF
- (match_operand:SF 2 "reg_or_fp0_operand" "fG"))
- (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
+ (match_operand:SF 2 "reg_or_0_operand" "fG"))
+ (match_operand:DF 3 "reg_or_0_operand" "fG")]))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"cmp%-%C1%/ %R2,%R3,%0"
[(set_attr "type" "fadd")
@@ -3682,8 +3469,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set (match_operand:DF 0 "register_operand" "=f")
(match_operator:DF 1 "alpha_fp_comparison_operator"
[(float_extend:DF
- (match_operand:SF 2 "reg_or_fp0_operand" "fG"))
- (match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
+ (match_operand:SF 2 "reg_or_0_operand" "fG"))
+ (match_operand:DF 3 "reg_or_0_operand" "fG")]))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"cmp%-%C1%/ %R2,%R3,%0"
[(set_attr "type" "fadd")
@@ -3693,9 +3480,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*cmpdf_ieee_ext2"
[(set (match_operand:DF 0 "register_operand" "=&f")
(match_operator:DF 1 "alpha_fp_comparison_operator"
- [(match_operand:DF 2 "reg_or_fp0_operand" "fG")
+ [(match_operand:DF 2 "reg_or_0_operand" "fG")
(float_extend:DF
- (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))]
+ (match_operand:SF 3 "reg_or_0_operand" "fG"))]))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"cmp%-%C1%/ %R2,%R3,%0"
[(set_attr "type" "fadd")
@@ -3705,9 +3492,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*cmpdf_ext2"
[(set (match_operand:DF 0 "register_operand" "=f")
(match_operator:DF 1 "alpha_fp_comparison_operator"
- [(match_operand:DF 2 "reg_or_fp0_operand" "fG")
+ [(match_operand:DF 2 "reg_or_0_operand" "fG")
(float_extend:DF
- (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))]
+ (match_operand:SF 3 "reg_or_0_operand" "fG"))]))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"cmp%-%C1%/ %R2,%R3,%0"
[(set_attr "type" "fadd")
@@ -3718,9 +3505,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set (match_operand:DF 0 "register_operand" "=&f")
(match_operator:DF 1 "alpha_fp_comparison_operator"
[(float_extend:DF
- (match_operand:SF 2 "reg_or_fp0_operand" "fG"))
+ (match_operand:SF 2 "reg_or_0_operand" "fG"))
(float_extend:DF
- (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))]
+ (match_operand:SF 3 "reg_or_0_operand" "fG"))]))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
"cmp%-%C1%/ %R2,%R3,%0"
[(set_attr "type" "fadd")
@@ -3731,9 +3518,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set (match_operand:DF 0 "register_operand" "=f")
(match_operator:DF 1 "alpha_fp_comparison_operator"
[(float_extend:DF
- (match_operand:SF 2 "reg_or_fp0_operand" "fG"))
+ (match_operand:SF 2 "reg_or_0_operand" "fG"))
(float_extend:DF
- (match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))]
+ (match_operand:SF 3 "reg_or_0_operand" "fG"))]))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"cmp%-%C1%/ %R2,%R3,%0"
[(set_attr "type" "fadd")
@@ -3744,10 +3531,10 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(if_then_else:DF
(match_operator 3 "signed_comparison_operator"
- [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG")
- (match_operand:DF 2 "fp0_operand" "G,G")])
- (match_operand:DF 1 "reg_or_fp0_operand" "fG,0")
- (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))]
+ [(match_operand:DF 4 "reg_or_0_operand" "fG,fG")
+ (match_operand:DF 2 "const0_operand" "G,G")])
+ (match_operand:DF 1 "reg_or_0_operand" "fG,0")
+ (match_operand:DF 5 "reg_or_0_operand" "0,fG")))]
"TARGET_FP"
"@
fcmov%C3 %R4,%R1,%0
@@ -3758,10 +3545,10 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(if_then_else:SF
(match_operator 3 "signed_comparison_operator"
- [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG")
- (match_operand:DF 2 "fp0_operand" "G,G")])
- (match_operand:SF 1 "reg_or_fp0_operand" "fG,0")
- (match_operand:SF 5 "reg_or_fp0_operand" "0,fG")))]
+ [(match_operand:DF 4 "reg_or_0_operand" "fG,fG")
+ (match_operand:DF 2 "const0_operand" "G,G")])
+ (match_operand:SF 1 "reg_or_0_operand" "fG,0")
+ (match_operand:SF 5 "reg_or_0_operand" "0,fG")))]
"TARGET_FP"
"@
fcmov%C3 %R4,%R1,%0
@@ -3772,10 +3559,10 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(if_then_else:DF
(match_operator 3 "signed_comparison_operator"
- [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG")
- (match_operand:DF 2 "fp0_operand" "G,G")])
- (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG,0"))
- (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))]
+ [(match_operand:DF 4 "reg_or_0_operand" "fG,fG")
+ (match_operand:DF 2 "const0_operand" "G,G")])
+ (float_extend:DF (match_operand:SF 1 "reg_or_0_operand" "fG,0"))
+ (match_operand:DF 5 "reg_or_0_operand" "0,fG")))]
"TARGET_FP"
"@
fcmov%C3 %R4,%R1,%0
@@ -3787,10 +3574,10 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(if_then_else:DF
(match_operator 3 "signed_comparison_operator"
[(float_extend:DF
- (match_operand:SF 4 "reg_or_fp0_operand" "fG,fG"))
- (match_operand:DF 2 "fp0_operand" "G,G")])
- (match_operand:DF 1 "reg_or_fp0_operand" "fG,0")
- (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))]
+ (match_operand:SF 4 "reg_or_0_operand" "fG,fG"))
+ (match_operand:DF 2 "const0_operand" "G,G")])
+ (match_operand:DF 1 "reg_or_0_operand" "fG,0")
+ (match_operand:DF 5 "reg_or_0_operand" "0,fG")))]
"TARGET_FP"
"@
fcmov%C3 %R4,%R1,%0
@@ -3802,10 +3589,10 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(if_then_else:SF
(match_operator 3 "signed_comparison_operator"
[(float_extend:DF
- (match_operand:SF 4 "reg_or_fp0_operand" "fG,fG"))
- (match_operand:DF 2 "fp0_operand" "G,G")])
- (match_operand:SF 1 "reg_or_fp0_operand" "fG,0")
- (match_operand:SF 5 "reg_or_fp0_operand" "0,fG")))]
+ (match_operand:SF 4 "reg_or_0_operand" "fG,fG"))
+ (match_operand:DF 2 "const0_operand" "G,G")])
+ (match_operand:SF 1 "reg_or_0_operand" "fG,0")
+ (match_operand:SF 5 "reg_or_0_operand" "0,fG")))]
"TARGET_FP"
"@
fcmov%C3 %R4,%R1,%0
@@ -3817,10 +3604,10 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(if_then_else:DF
(match_operator 3 "signed_comparison_operator"
[(float_extend:DF
- (match_operand:SF 4 "reg_or_fp0_operand" "fG,fG"))
- (match_operand:DF 2 "fp0_operand" "G,G")])
- (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG,0"))
- (match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))]
+ (match_operand:SF 4 "reg_or_0_operand" "fG,fG"))
+ (match_operand:DF 2 "const0_operand" "G,G")])
+ (float_extend:DF (match_operand:SF 1 "reg_or_0_operand" "fG,0"))
+ (match_operand:DF 5 "reg_or_0_operand" "0,fG")))]
"TARGET_FP"
"@
fcmov%C3 %R4,%R1,%0
@@ -3829,8 +3616,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_expand "maxdf3"
[(set (match_dup 3)
- (le:DF (match_operand:DF 1 "reg_or_fp0_operand" "")
- (match_operand:DF 2 "reg_or_fp0_operand" "")))
+ (le:DF (match_operand:DF 1 "reg_or_0_operand" "")
+ (match_operand:DF 2 "reg_or_0_operand" "")))
(set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF (eq (match_dup 3) (match_dup 4))
(match_dup 1) (match_dup 2)))]
@@ -3842,8 +3629,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_expand "mindf3"
[(set (match_dup 3)
- (lt:DF (match_operand:DF 1 "reg_or_fp0_operand" "")
- (match_operand:DF 2 "reg_or_fp0_operand" "")))
+ (lt:DF (match_operand:DF 1 "reg_or_0_operand" "")
+ (match_operand:DF 2 "reg_or_0_operand" "")))
(set (match_operand:DF 0 "register_operand" "")
(if_then_else:DF (ne (match_dup 3) (match_dup 4))
(match_dup 1) (match_dup 2)))]
@@ -3855,8 +3642,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_expand "maxsf3"
[(set (match_dup 3)
- (le:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" ""))
- (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" ""))))
+ (le:DF (float_extend:DF (match_operand:SF 1 "reg_or_0_operand" ""))
+ (float_extend:DF (match_operand:SF 2 "reg_or_0_operand" ""))))
(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (eq (match_dup 3) (match_dup 4))
(match_dup 1) (match_dup 2)))]
@@ -3868,8 +3655,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_expand "minsf3"
[(set (match_dup 3)
- (lt:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" ""))
- (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" ""))))
+ (lt:DF (float_extend:DF (match_operand:SF 1 "reg_or_0_operand" ""))
+ (float_extend:DF (match_operand:SF 2 "reg_or_0_operand" ""))))
(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (ne (match_dup 3) (match_dup 4))
(match_dup 1) (match_dup 2)))]
@@ -3883,8 +3670,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set (pc)
(if_then_else
(match_operator 1 "signed_comparison_operator"
- [(match_operand:DF 2 "reg_or_fp0_operand" "fG")
- (match_operand:DF 3 "fp0_operand" "G")])
+ [(match_operand:DF 2 "reg_or_0_operand" "fG")
+ (match_operand:DF 3 "const0_operand" "G")])
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_FP"
@@ -3896,8 +3683,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(if_then_else
(match_operator 1 "signed_comparison_operator"
[(float_extend:DF
- (match_operand:SF 2 "reg_or_fp0_operand" "fG"))
- (match_operand:DF 3 "fp0_operand" "G")])
+ (match_operand:SF 2 "reg_or_0_operand" "fG"))
+ (match_operand:DF 3 "const0_operand" "G")])
(label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_FP"
@@ -3908,8 +3695,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
;; and compares.
(define_expand "cmpdf"
- [(set (cc0) (compare (match_operand:DF 0 "reg_or_fp0_operand" "")
- (match_operand:DF 1 "reg_or_fp0_operand" "")))]
+ [(set (cc0) (compare (match_operand:DF 0 "reg_or_0_operand" "")
+ (match_operand:DF 1 "reg_or_0_operand" "")))]
"TARGET_FP"
{
alpha_compare.op0 = operands[0];
@@ -4669,11 +4456,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
emit_move_insn (gen_rtx_REG (DImode, 25), operands[1]);
if (GET_CODE (operands[0]) == SYMBOL_REF)
{
- rtx linkage = alpha_need_linkage (XSTR (operands[0], 0), 0);
+ alpha_need_linkage (XSTR (operands[0], 0), 0);
- emit_move_insn (gen_rtx_REG (Pmode, 26), gen_rtx_MEM (Pmode, linkage));
- operands[2]
- = validize_mem (gen_rtx_MEM (Pmode, plus_constant (linkage, 8)));
+ operands[2] = const0_rtx;
}
else
{
@@ -4771,11 +4556,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
emit_move_insn (gen_rtx_REG (DImode, 25), operands[2]);
if (GET_CODE (operands[1]) == SYMBOL_REF)
{
- rtx linkage = alpha_need_linkage (XSTR (operands[1], 0), 0);
+ alpha_need_linkage (XSTR (operands[1], 0), 0);
- emit_move_insn (gen_rtx_REG (Pmode, 26), gen_rtx_MEM (Pmode, linkage));
- operands[3]
- = validize_mem (gen_rtx_MEM (Pmode, plus_constant (linkage, 8)));
+ operands[3] = const0_rtx;
}
else
{
@@ -4960,17 +4743,31 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set_attr "type" "jsr")
(set_attr "length" "*,*,12")])
+; GAS relies on the order and position of instructions output below in order
+; to generate relocs for VMS link to potentially optimize the call.
+; Please do not molest.
(define_insn "*call_vms_1"
[(call (mem:DI (match_operand:DI 0 "call_operand" "r,s"))
(match_operand 1 "" ""))
- (use (match_operand:DI 2 "nonimmediate_operand" "r,m"))
+ (use (match_operand:DI 2 "nonmemory_operand" "r,n"))
(use (reg:DI 25))
(use (reg:DI 26))
(clobber (reg:DI 27))]
"TARGET_ABI_OPEN_VMS"
- "@
- mov %2,$27\;jsr $26,0\;ldq $27,0($29)
- ldq $27,%2\;jsr $26,%0\;ldq $27,0($29)"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return \"mov %2,$27\;jsr $26,0\;ldq $27,0($29)\";
+ case 1:
+ operands [2] = alpha_use_linkage (operands [0], cfun->decl, 1, 0);
+ operands [3] = alpha_use_linkage (operands [0], cfun->decl, 0, 0);
+ return \"ldq $26,%3\;ldq $27,%2\;jsr $26,%0\;ldq $27,0($29)\";
+ default:
+ abort();
+ }
+}"
[(set_attr "type" "jsr")
(set_attr "length" "12,16")])
@@ -5018,7 +4815,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
""
""
- [(set_attr "length" "0")])
+ [(set_attr "length" "0")
+ (set_attr "type" "none")])
(define_insn "jump"
[(set (pc)
@@ -5095,7 +4893,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(unspec_volatile [(const_int 0)] UNSPECV_IMB)]
""
"call_pal 0x86"
- [(set_attr "type" "ibr")])
+ [(set_attr "type" "callpal")])
;; BUGCHK is documented common to OSF/1 and VMS PALcode.
;; NT does not document anything at 0x81 -- presumably it would generate
@@ -5105,7 +4903,44 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(trap_if (const_int 1) (const_int 0))]
"!TARGET_ABI_WINDOWS_NT"
"call_pal 0x81"
- [(set_attr "type" "ibr")])
+ [(set_attr "type" "callpal")])
+
+;; For userland, we load the thread pointer from the TCB.
+;; For the kernel, we load the per-cpu private value.
+
+(define_insn "load_tp"
+ [(set (match_operand:DI 0 "register_operand" "=v")
+ (unspec:DI [(const_int 0)] UNSPEC_TP))]
+ "TARGET_ABI_OSF"
+{
+ if (TARGET_TLS_KERNEL)
+ return "call_pal 0x32";
+ else
+ return "call_pal 0x9e";
+}
+ [(set_attr "type" "callpal")])
+
+;; For completeness, and possibly a __builtin function, here's how to
+;; set the thread pointer. Since we don't describe enough of this
+;; quantity for CSE, we have to use a volatile unspec, and then there's
+;; not much point in creating an R16_REG register class.
+
+(define_expand "set_tp"
+ [(set (reg:DI 16) (match_operand:DI 0 "input_operand" ""))
+ (unspec_volatile [(reg:DI 16)] UNSPECV_SET_TP)]
+ "TARGET_ABI_OSF"
+ "")
+
+(define_insn "*set_tp"
+ [(unspec_volatile [(reg:DI 16)] UNSPECV_SET_TP)]
+ "TARGET_ABI_OSF"
+{
+ if (TARGET_TLS_KERNEL)
+ return "call_pal 0x31";
+ else
+ return "call_pal 0x9f";
+}
+ [(set_attr "type" "callpal")])
;; Finally, we have the basic data motion insns. The byte and word insns
;; are done via define_expand. Start with the floating-point insns, since
@@ -5116,7 +4951,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:SF 1 "input_operand" "fG,m,*rG,m,fG,*r"))]
"TARGET_FPREGS && ! TARGET_FIX
&& (register_operand (operands[0], SFmode)
- || reg_or_fp0_operand (operands[1], SFmode))"
+ || reg_or_0_operand (operands[1], SFmode))"
"@
cpys %R1,%R1,%0
ld%, %0,%1
@@ -5131,7 +4966,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:SF 1 "input_operand" "fG,m,*rG,m,fG,*r,*r,f"))]
"TARGET_FPREGS && TARGET_FIX
&& (register_operand (operands[0], SFmode)
- || reg_or_fp0_operand (operands[1], SFmode))"
+ || reg_or_0_operand (operands[1], SFmode))"
"@
cpys %R1,%R1,%0
ld%, %0,%1
@@ -5148,7 +4983,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:SF 1 "input_operand" "rG,m,r"))]
"! TARGET_FPREGS
&& (register_operand (operands[0], SFmode)
- || reg_or_fp0_operand (operands[1], SFmode))"
+ || reg_or_0_operand (operands[1], SFmode))"
"@
bis $31,%r1,%0
ldl %0,%1
@@ -5160,7 +4995,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:DF 1 "input_operand" "fG,m,*rG,m,fG,*r"))]
"TARGET_FPREGS && ! TARGET_FIX
&& (register_operand (operands[0], DFmode)
- || reg_or_fp0_operand (operands[1], DFmode))"
+ || reg_or_0_operand (operands[1], DFmode))"
"@
cpys %R1,%R1,%0
ld%- %0,%1
@@ -5175,7 +5010,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:DF 1 "input_operand" "fG,m,*rG,m,fG,*r,*r,f"))]
"TARGET_FPREGS && TARGET_FIX
&& (register_operand (operands[0], DFmode)
- || reg_or_fp0_operand (operands[1], DFmode))"
+ || reg_or_0_operand (operands[1], DFmode))"
"@
cpys %R1,%R1,%0
ld%- %0,%1
@@ -5192,7 +5027,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:DF 1 "input_operand" "rG,m,r"))]
"! TARGET_FPREGS
&& (register_operand (operands[0], DFmode)
- || reg_or_fp0_operand (operands[1], DFmode))"
+ || reg_or_0_operand (operands[1], DFmode))"
"@
bis $31,%r1,%0
ldq %0,%1
@@ -5206,7 +5041,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set (match_operand:TF 0 "nonimmediate_operand" "=r,o")
(match_operand:TF 1 "input_operand" "roG,rG"))]
"register_operand (operands[0], TFmode)
- || reg_or_fp0_operand (operands[1], TFmode)"
+ || reg_or_0_operand (operands[1], TFmode)"
"#"
"reload_completed"
[(set (match_dup 0) (match_dup 2))
@@ -5227,7 +5062,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
""
{
if (GET_CODE (operands[0]) == MEM
- && ! reg_or_fp0_operand (operands[1], SFmode))
+ && ! reg_or_0_operand (operands[1], SFmode))
operands[1] = force_reg (SFmode, operands[1]);
})
@@ -5237,7 +5072,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
""
{
if (GET_CODE (operands[0]) == MEM
- && ! reg_or_fp0_operand (operands[1], DFmode))
+ && ! reg_or_0_operand (operands[1], DFmode))
operands[1] = force_reg (DFmode, operands[1]);
})
@@ -5247,7 +5082,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
""
{
if (GET_CODE (operands[0]) == MEM
- && ! reg_or_fp0_operand (operands[1], TFmode))
+ && ! reg_or_0_operand (operands[1], TFmode))
operands[1] = force_reg (TFmode, operands[1]);
})
@@ -5497,7 +5332,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
return "lda %0,%2(%1)\t\t!gprel";
else
return "lda %0,%2(%1)\t\t!gprellow";
-})
+}
+ [(set_attr "usegp" "yes")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -5523,10 +5359,12 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(match_dup 0)]
"operands[0] = split_small_symbolic_operand (operands[0]);")
+;; Accepts any symbolic, not just global, since function calls that
+;; don't go via bsr still use !literal in hopes of linker relaxation.
(define_insn "movdi_er_high_g"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "global_symbolic_operand" "")
+ (match_operand:DI 2 "symbolic_operand" "")
(match_operand 3 "const_int_operand" "")]
UNSPEC_LITERAL))]
"TARGET_EXPLICIT_RELOCS"
@@ -5583,6 +5421,77 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
}
})
+(define_insn "movdi_er_tlsgd"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "symbolic_operand" "")
+ (match_operand 3 "const_int_operand" "")]
+ UNSPEC_TLSGD))]
+ "HAVE_AS_TLS"
+{
+ if (INTVAL (operands[3]) == 0)
+ return "lda %0,%2(%1)\t\t!tlsgd";
+ else
+ return "lda %0,%2(%1)\t\t!tlsgd!%3";
+})
+
+(define_insn "movdi_er_tlsldm"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")
+ (match_operand 2 "const_int_operand" "")]
+ UNSPEC_TLSLDM))]
+ "HAVE_AS_TLS"
+{
+ if (INTVAL (operands[2]) == 0)
+ return "lda %0,%&(%1)\t\t!tlsldm";
+ else
+ return "lda %0,%&(%1)\t\t!tlsldm!%2";
+})
+
+(define_insn "*movdi_er_gotdtp"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_DTPREL))]
+ "HAVE_AS_TLS"
+ "ldq %0,%2(%1)\t\t!gotdtprel"
+ [(set_attr "type" "ild")
+ (set_attr "usegp" "yes")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "gotdtp_symbolic_operand" ""))]
+ "HAVE_AS_TLS && reload_completed"
+ [(set (match_dup 0)
+ (unspec:DI [(match_dup 2)
+ (match_dup 1)] UNSPEC_DTPREL))]
+{
+ operands[1] = XVECEXP (XEXP (operands[1], 0), 0, 0);
+ operands[2] = pic_offset_table_rtx;
+})
+
+(define_insn "*movdi_er_gottp"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_TPREL))]
+ "HAVE_AS_TLS"
+ "ldq %0,%2(%1)\t\t!gottprel"
+ [(set_attr "type" "ild")
+ (set_attr "usegp" "yes")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "gottp_symbolic_operand" ""))]
+ "HAVE_AS_TLS && reload_completed"
+ [(set (match_dup 0)
+ (unspec:DI [(match_dup 2)
+ (match_dup 1)] UNSPEC_TPREL))]
+{
+ operands[1] = XVECEXP (XEXP (operands[1], 0), 0, 0);
+ operands[2] = pic_offset_table_rtx;
+})
+
(define_insn "*movdi_er_nofix"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q")
(match_operand:DI 1 "input_operand" "rJ,K,L,T,s,m,rJ,*fJ,Q,*f"))]
@@ -5600,7 +5509,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
fmov %R1,%0
ldt %0,%1
stt %R1,%0"
- [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")])
+ [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")
+ (set_attr "usegp" "*,*,*,yes,*,*,*,*,*,*")])
;; The 'U' constraint matches symbolic operands on Unicos/Mk. Those should
;; have been split up by the rules above but we shouldn't reject the
@@ -5647,7 +5557,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
stt %R1,%0
ftoit %1,%0
itoft %1,%0"
- [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst,ftoi,itof")])
+ [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst,ftoi,itof")
+ (set_attr "usegp" "*,*,*,yes,*,*,*,*,*,*,*,*")])
(define_insn "*movdi_fix"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q,r,*f")
@@ -6254,6 +6165,195 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
DONE;
})
+;; Vector operations
+
+(define_expand "movv8qi"
+ [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
+ (match_operand:V8QI 1 "general_operand" ""))]
+ ""
+{
+ if (alpha_expand_mov (V8QImode, operands))
+ DONE;
+})
+
+(define_insn "*movv8qi_fix"
+ [(set (match_operand:V8QI 0 "nonimmediate_operand" "=r,r,m,*f,*f,m,r,*f")
+ (match_operand:V8QI 1 "input_operand" "rW,m,rW,*fW,m,*f,*f,r"))]
+ "TARGET_FIX
+ && (register_operand (operands[0], V8QImode)
+ || reg_or_0_operand (operands[1], V8QImode))"
+ "@
+ bis $31,%r1,%0
+ ldq %0,%1
+ stq %r1,%0
+ cpys %R1,%R1,%0
+ ldt %0,%1
+ stt %R1,%0
+ ftoit %1,%0
+ itoft %1,%0"
+ [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst,ftoi,itof")])
+
+(define_insn "*movv8qi_nofix"
+ [(set (match_operand:V8QI 0 "nonimmediate_operand" "=r,r,m,*f,*f,m")
+ (match_operand:V8QI 1 "input_operand" "rW,m,rW,*fW,m,*f"))]
+ "! TARGET_FIX
+ && (register_operand (operands[0], V8QImode)
+ || reg_or_0_operand (operands[1], V8QImode))"
+ "@
+ bis $31,%r1,%0
+ ldq %0,%1
+ stq %r1,%0
+ cpys %R1,%R1,%0
+ ldt %0,%1
+ stt %R1,%0"
+ [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst")])
+
+(define_expand "movv4hi"
+ [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
+ (match_operand:V4HI 1 "general_operand" ""))]
+ ""
+{
+ if (alpha_expand_mov (V4HImode, operands))
+ DONE;
+})
+
+(define_insn "*movv4hi_fix"
+ [(set (match_operand:V4HI 0 "nonimmediate_operand" "=r,r,m,*f,*f,m,r,*f")
+ (match_operand:V4HI 1 "input_operand" "rW,m,rW,*fW,m,*f,*f,r"))]
+ "TARGET_FIX
+ && (register_operand (operands[0], V4HImode)
+ || reg_or_0_operand (operands[1], V4HImode))"
+ "@
+ bis $31,%r1,%0
+ ldq %0,%1
+ stq %r1,%0
+ cpys %R1,%R1,%0
+ ldt %0,%1
+ stt %R1,%0
+ ftoit %1,%0
+ itoft %1,%0"
+ [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst,ftoi,itof")])
+
+(define_insn "*movv4hi_nofix"
+ [(set (match_operand:V4HI 0 "nonimmediate_operand" "=r,r,m,*f,*f,m")
+ (match_operand:V4HI 1 "input_operand" "rW,m,rW,*fW,m,*f"))]
+ "! TARGET_FIX
+ && (register_operand (operands[0], V4HImode)
+ || reg_or_0_operand (operands[1], V4HImode))"
+ "@
+ bis $31,%r1,%0
+ ldq %0,%1
+ stq %r1,%0
+ cpys %R1,%R1,%0
+ ldt %0,%1
+ stt %R1,%0"
+ [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst")])
+
+(define_expand "movv2si"
+ [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
+ (match_operand:V2SI 1 "general_operand" ""))]
+ ""
+{
+ if (alpha_expand_mov (V2SImode, operands))
+ DONE;
+})
+
+(define_insn "*movv2si_fix"
+ [(set (match_operand:V2SI 0 "nonimmediate_operand" "=r,r,m,*f,*f,m,r,*f")
+ (match_operand:V2SI 1 "input_operand" "rW,m,rW,*fW,m,*f,*f,r"))]
+ "TARGET_FIX
+ && (register_operand (operands[0], V2SImode)
+ || reg_or_0_operand (operands[1], V2SImode))"
+ "@
+ bis $31,%r1,%0
+ ldq %0,%1
+ stq %r1,%0
+ cpys %R1,%R1,%0
+ ldt %0,%1
+ stt %R1,%0
+ ftoit %1,%0
+ itoft %1,%0"
+ [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst,ftoi,itof")])
+
+(define_insn "*movv2si_nofix"
+ [(set (match_operand:V2SI 0 "nonimmediate_operand" "=r,r,m,*f,*f,m")
+ (match_operand:V2SI 1 "input_operand" "rW,m,rW,*fW,m,*f"))]
+ "! TARGET_FIX
+ && (register_operand (operands[0], V2SImode)
+ || reg_or_0_operand (operands[1], V2SImode))"
+ "@
+ bis $31,%r1,%0
+ ldq %0,%1
+ stq %r1,%0
+ cpys %R1,%R1,%0
+ ldt %0,%1
+ stt %R1,%0"
+ [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst")])
+
+(define_insn "uminv8qi3"
+ [(set (match_operand:V8QI 0 "register_operand" "=r")
+ (umin:V8QI (match_operand:V8QI 1 "reg_or_0_operand" "rW")
+ (match_operand:V8QI 2 "reg_or_0_operand" "rW")))]
+ "TARGET_MAX"
+ "minub8 %r1,%r2,%0"
+ [(set_attr "type" "mvi")])
+
+(define_insn "sminv8qi3"
+ [(set (match_operand:V8QI 0 "register_operand" "=r")
+ (smin:V8QI (match_operand:V8QI 1 "reg_or_0_operand" "rW")
+ (match_operand:V8QI 2 "reg_or_0_operand" "rW")))]
+ "TARGET_MAX"
+ "minsb8 %r1,%r2,%0"
+ [(set_attr "type" "mvi")])
+
+(define_insn "uminv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand" "=r")
+ (umin:V4HI (match_operand:V4HI 1 "reg_or_0_operand" "rW")
+ (match_operand:V4HI 2 "reg_or_0_operand" "rW")))]
+ "TARGET_MAX"
+ "minuw4 %r1,%r2,%0"
+ [(set_attr "type" "mvi")])
+
+(define_insn "sminv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand" "=r")
+ (smin:V4HI (match_operand:V4HI 1 "reg_or_0_operand" "rW")
+ (match_operand:V4HI 2 "reg_or_0_operand" "rW")))]
+ "TARGET_MAX"
+ "minsw4 %r1,%r2,%0"
+ [(set_attr "type" "mvi")])
+
+(define_insn "umaxv8qi3"
+ [(set (match_operand:V8QI 0 "register_operand" "=r")
+ (umax:V8QI (match_operand:V8QI 1 "reg_or_0_operand" "rW")
+ (match_operand:V8QI 2 "reg_or_0_operand" "rW")))]
+ "TARGET_MAX"
+ "maxub8 %r1,%r2,%0"
+ [(set_attr "type" "mvi")])
+
+(define_insn "smaxv8qi3"
+ [(set (match_operand:V8QI 0 "register_operand" "=r")
+ (smax:V8QI (match_operand:V8QI 1 "reg_or_0_operand" "rW")
+ (match_operand:V8QI 2 "reg_or_0_operand" "rW")))]
+ "TARGET_MAX"
+ "maxsb8 %r1,%r2,%0"
+ [(set_attr "type" "mvi")])
+
+(define_insn "umaxv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand" "=r")
+ (umax:V4HI (match_operand:V4HI 1 "reg_or_0_operand" "rW")
+ (match_operand:V4HI 2 "reg_or_0_operand" "rW")))]
+ "TARGET_MAX"
+ "maxuw4 %r1,%r2,%0"
+ [(set_attr "type" "mvi")])
+
+(define_insn "smaxv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand" "=r")
+ (smax:V4HI (match_operand:V4HI 1 "reg_or_0_operand" "rW")
+ (match_operand:V4HI 2 "reg_or_0_operand" "rW")))]
+ "TARGET_MAX"
+ "maxsw4 %r1,%r2,%0"
+ [(set_attr "type" "mvi")])
+
;; Bit field extract patterns which use ext[wlq][lh]
(define_expand "extv"
@@ -6684,7 +6784,11 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
"TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF
&& prev_nonnote_insn (insn) == operands[0]"
[(const_int 0)]
- "DONE;")
+ "
+{
+ emit_note (NULL, NOTE_INSN_DELETED);
+ DONE;
+}")
(define_insn "*builtin_setjmp_receiver_1"
[(unspec_volatile [(label_ref (match_operand 0 "" ""))] UNSPECV_SETJMPR)]
@@ -6864,12 +6968,12 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
and leave the LRU eviction counter pointing to that block. */
static const char * const alt[2][2] = {
{
- "lds $f31,%a0", /* read, evict next */
+ "ldq $31,%a0", /* read, evict next */
"ldl $31,%a0", /* read, evict last */
},
{
"ldt $f31,%a0", /* write, evict next */
- "ldq $31,%a0", /* write, evict last */
+ "lds $f31,%a0", /* write, evict last */
}
};
@@ -6922,7 +7026,687 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
else
return ".align %0 #realign";
})
+
+;; Instructions to be emitted from __builtins.
+
+(define_insn "builtin_cmpbge"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "reg_or_0_operand" "rJ")
+ (match_operand:DI 2 "reg_or_8bit_operand" "rI")]
+ UNSPEC_CMPBGE))]
+ ""
+ "cmpbge %r1,%2,%0"
+ ;; The EV6 data sheets list this as ILOG. OTOH, EV6 doesn't
+ ;; actually differentiate between ILOG and ICMP in the schedule.
+ [(set_attr "type" "icmp")])
+
+(define_expand "builtin_extbl"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx, rtx));
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_extxl_be;
+ else
+ gen = gen_extxl_le;
+ emit_insn ((*gen) (operands[0], operands[1], GEN_INT (8), operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_extwl"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx, rtx));
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_extxl_be;
+ else
+ gen = gen_extxl_le;
+ emit_insn ((*gen) (operands[0], operands[1], GEN_INT (16), operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_extll"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx, rtx));
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_extxl_be;
+ else
+ gen = gen_extxl_le;
+ emit_insn ((*gen) (operands[0], operands[1], GEN_INT (32), operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_extql"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx, rtx));
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_extxl_be;
+ else
+ gen = gen_extxl_le;
+ emit_insn ((*gen) (operands[0], operands[1], GEN_INT (64), operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_extwh"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx));
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_extwh_be;
+ else
+ gen = gen_extwh_le;
+ emit_insn ((*gen) (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_extlh"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx));
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_extlh_be;
+ else
+ gen = gen_extlh_le;
+ emit_insn ((*gen) (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_extqh"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx));
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_extqh_be;
+ else
+ gen = gen_extqh_le;
+ emit_insn ((*gen) (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_insbl"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx));
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_insbl_be;
+ else
+ gen = gen_insbl_le;
+ operands[1] = gen_lowpart (QImode, operands[1]);
+ emit_insn ((*gen) (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_inswl"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx));
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_inswl_be;
+ else
+ gen = gen_inswl_le;
+ operands[1] = gen_lowpart (HImode, operands[1]);
+ emit_insn ((*gen) (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_insll"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx));
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_insll_be;
+ else
+ gen = gen_insll_le;
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ emit_insn ((*gen) (operands[0], operands[1], operands[2]));
+ emit_insn ((*gen) (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_insql"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx));
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_insql_be;
+ else
+ gen = gen_insql_le;
+ emit_insn ((*gen) (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_inswh"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ emit_insn (gen_insxh (operands[0], operands[1], GEN_INT (16), operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_inslh"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ emit_insn (gen_insxh (operands[0], operands[1], GEN_INT (32), operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_insqh"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ emit_insn (gen_insxh (operands[0], operands[1], GEN_INT (64), operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_mskbl"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx, rtx));
+ rtx mask;
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_mskxl_be;
+ else
+ gen = gen_mskxl_le;
+ mask = GEN_INT (0xff);
+ emit_insn ((*gen) (operands[0], operands[1], mask, operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_mskwl"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx, rtx));
+ rtx mask;
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_mskxl_be;
+ else
+ gen = gen_mskxl_le;
+ mask = GEN_INT (0xffff);
+ emit_insn ((*gen) (operands[0], operands[1], mask, operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_mskll"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx, rtx));
+ rtx mask;
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_mskxl_be;
+ else
+ gen = gen_mskxl_le;
+ mask = immed_double_const (0xffffffff, 0, DImode);
+ emit_insn ((*gen) (operands[0], operands[1], mask, operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_mskql"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ rtx (*gen) PARAMS ((rtx, rtx, rtx, rtx));
+ rtx mask;
+ if (WORDS_BIG_ENDIAN)
+ gen = gen_mskxl_be;
+ else
+ gen = gen_mskxl_le;
+ mask = constm1_rtx;
+ emit_insn ((*gen) (operands[0], operands[1], mask, operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_mskwh"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ emit_insn (gen_mskxh (operands[0], operands[1], GEN_INT (16), operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_msklh"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ emit_insn (gen_mskxh (operands[0], operands[1], GEN_INT (32), operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_mskqh"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "reg_or_8bit_operand" "")]
+ ""
+{
+ emit_insn (gen_mskxh (operands[0], operands[1], GEN_INT (64), operands[2]));
+ DONE;
+})
+
+(define_expand "builtin_zap"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (and:DI (unspec:DI
+ [(match_operand:DI 2 "reg_or_const_int_operand" "")]
+ UNSPEC_ZAP)
+ (match_operand:DI 1 "reg_or_const_int_operand" "")))]
+ ""
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ rtx mask = alpha_expand_zap_mask (INTVAL (operands[2]));
+
+ if (mask == const0_rtx)
+ {
+ emit_move_insn (operands[0], const0_rtx);
+ DONE;
+ }
+ if (mask == constm1_rtx)
+ {
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+ }
+
+ operands[1] = force_reg (DImode, operands[1]);
+ emit_insn (gen_anddi3 (operands[0], operands[1], mask));
+ DONE;
+ }
+
+ operands[1] = force_reg (DImode, operands[1]);
+ operands[2] = gen_lowpart (QImode, operands[2]);
+})
+
+(define_insn "*builtin_zap_1"
+ [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
+ (and:DI (unspec:DI
+ [(match_operand:QI 2 "reg_or_const_int_operand" "n,n,r,r")]
+ UNSPEC_ZAP)
+ (match_operand:DI 1 "reg_or_const_int_operand" "n,r,J,r")))]
+ ""
+ "@
+ #
+ #
+ bis $31,$31,%0
+ zap %r1,%2,%0"
+ [(set_attr "type" "shift,shift,ilog,shift")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (and:DI (unspec:DI
+ [(match_operand:QI 2 "const_int_operand" "")]
+ UNSPEC_ZAP)
+ (match_operand:DI 1 "const_int_operand" "")))]
+ ""
+ [(const_int 0)]
+{
+ rtx mask = alpha_expand_zap_mask (INTVAL (operands[2]));
+ if (HOST_BITS_PER_WIDE_INT >= 64 || GET_CODE (mask) == CONST_INT)
+ operands[1] = gen_int_mode (INTVAL (operands[1]) & INTVAL (mask), DImode);
+ else
+ {
+ HOST_WIDE_INT c_lo = INTVAL (operands[1]);
+ HOST_WIDE_INT c_hi = (c_lo < 0 ? -1 : 0);
+ operands[1] = immed_double_const (c_lo & CONST_DOUBLE_LOW (mask),
+ c_hi & CONST_DOUBLE_HIGH (mask),
+ DImode);
+ }
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+})
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (and:DI (unspec:DI
+ [(match_operand:QI 2 "const_int_operand" "")]
+ UNSPEC_ZAP)
+ (match_operand:DI 1 "register_operand" "")))]
+ ""
+ [(set (match_dup 0)
+ (and:DI (match_dup 1) (match_dup 2)))]
+{
+ operands[2] = alpha_expand_zap_mask (INTVAL (operands[2]));
+ if (operands[2] == const0_rtx)
+ {
+ emit_move_insn (operands[0], const0_rtx);
+ DONE;
+ }
+ if (operands[2] == constm1_rtx)
+ {
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+ }
+})
+
+(define_expand "builtin_zapnot"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (and:DI (unspec:DI
+ [(not:QI (match_operand:DI 2 "reg_or_const_int_operand" ""))]
+ UNSPEC_ZAP)
+ (match_operand:DI 1 "reg_or_const_int_operand" "")))]
+ ""
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ rtx mask = alpha_expand_zap_mask (~ INTVAL (operands[2]));
+
+ if (mask == const0_rtx)
+ {
+ emit_move_insn (operands[0], const0_rtx);
+ DONE;
+ }
+ if (mask == constm1_rtx)
+ {
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+ }
+ operands[1] = force_reg (DImode, operands[1]);
+ emit_insn (gen_anddi3 (operands[0], operands[1], mask));
+ DONE;
+ }
+
+ operands[1] = force_reg (DImode, operands[1]);
+ operands[2] = gen_lowpart (QImode, operands[2]);
+})
+
+(define_insn "*builtin_zapnot_1"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI (unspec:DI
+ [(not:QI (match_operand:QI 2 "register_operand" "r"))]
+ UNSPEC_ZAP)
+ (match_operand:DI 1 "reg_or_0_operand" "rJ")))]
+ ""
+ "zapnot %r1,%2,%0"
+ [(set_attr "type" "shift")])
+
+(define_insn "builtin_amask"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "reg_or_8bit_operand" "rI")]
+ UNSPEC_AMASK))]
+ ""
+ "amask %1,%0"
+ [(set_attr "type" "ilog")])
+
+(define_insn "builtin_implver"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(const_int 0)] UNSPEC_IMPLVER))]
+ ""
+ "implver %0"
+ [(set_attr "type" "ilog")])
+
+(define_insn "builtin_rpcc"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec_volatile:DI [(const_int 0)] UNSPECV_RPCC))]
+ ""
+ "rpcc %0"
+ [(set_attr "type" "ilog")])
+
+(define_expand "builtin_minub8"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_0_operand" "")]
+ "TARGET_MAX"
+{
+ alpha_expand_builtin_vector_binop (gen_uminv8qi3, V8QImode, operands[0],
+ operands[1], operands[2]);
+ DONE;
+})
+
+(define_expand "builtin_minsb8"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_0_operand" "")]
+ "TARGET_MAX"
+{
+ alpha_expand_builtin_vector_binop (gen_sminv8qi3, V8QImode, operands[0],
+ operands[1], operands[2]);
+ DONE;
+})
+
+(define_expand "builtin_minuw4"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_0_operand" "")]
+ "TARGET_MAX"
+{
+ alpha_expand_builtin_vector_binop (gen_uminv4hi3, V4HImode, operands[0],
+ operands[1], operands[2]);
+ DONE;
+})
+
+(define_expand "builtin_minsw4"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_0_operand" "")]
+ "TARGET_MAX"
+{
+ alpha_expand_builtin_vector_binop (gen_sminv4hi3, V4HImode, operands[0],
+ operands[1], operands[2]);
+ DONE;
+})
+
+(define_expand "builtin_maxub8"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_0_operand" "")]
+ "TARGET_MAX"
+{
+ alpha_expand_builtin_vector_binop (gen_umaxv8qi3, V8QImode, operands[0],
+ operands[1], operands[2]);
+ DONE;
+})
+
+(define_expand "builtin_maxsb8"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_0_operand" "")]
+ "TARGET_MAX"
+{
+ alpha_expand_builtin_vector_binop (gen_smaxv8qi3, V8QImode, operands[0],
+ operands[1], operands[2]);
+ DONE;
+})
+
+(define_expand "builtin_maxuw4"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_0_operand" "")]
+ "TARGET_MAX"
+{
+ alpha_expand_builtin_vector_binop (gen_umaxv4hi3, V4HImode, operands[0],
+ operands[1], operands[2]);
+ DONE;
+})
+
+(define_expand "builtin_maxsw4"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" "")
+ (match_operand:DI 2 "reg_or_0_operand" "")]
+ "TARGET_MAX"
+{
+ alpha_expand_builtin_vector_binop (gen_smaxv4hi3, V4HImode, operands[0],
+ operands[1], operands[2]);
+ DONE;
+})
+
+(define_insn "builtin_perr"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "reg_or_0_operand" "%rJ")
+ (match_operand:DI 2 "reg_or_8bit_operand" "rJ")]
+ UNSPEC_PERR))]
+ "TARGET_MAX"
+ "perr %r1,%r2,%0"
+ [(set_attr "type" "mvi")])
+
+(define_expand "builtin_pklb"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (vec_concat:V8QI
+ (vec_concat:V4QI
+ (truncate:V2QI (match_operand:DI 1 "register_operand" ""))
+ (match_dup 2))
+ (match_dup 3)))]
+ "TARGET_MAX"
+{
+ operands[0] = gen_lowpart (V8QImode, operands[0]);
+ operands[1] = gen_lowpart (V2SImode, operands[1]);
+ operands[2] = CONST0_RTX (V2QImode);
+ operands[3] = CONST0_RTX (V4QImode);
+})
+
+(define_insn "*pklb"
+ [(set (match_operand:V8QI 0 "register_operand" "=r")
+ (vec_concat:V8QI
+ (vec_concat:V4QI
+ (truncate:V2QI (match_operand:V2SI 1 "register_operand" "r"))
+ (match_operand:V2QI 2 "const0_operand" ""))
+ (match_operand:V4QI 3 "const0_operand" "")))]
+ "TARGET_MAX"
+ "pklb %r1,%0"
+ [(set_attr "type" "mvi")])
+
+(define_expand "builtin_pkwb"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (vec_concat:V8QI
+ (truncate:V4QI (match_operand:DI 1 "register_operand" ""))
+ (match_dup 2)))]
+ "TARGET_MAX"
+{
+ operands[0] = gen_lowpart (V8QImode, operands[0]);
+ operands[1] = gen_lowpart (V4HImode, operands[1]);
+ operands[2] = CONST0_RTX (V4QImode);
+})
+
+(define_insn "*pkwb"
+ [(set (match_operand:V8QI 0 "register_operand" "=r")
+ (vec_concat:V8QI
+ (truncate:V4QI (match_operand:V4HI 1 "register_operand" "r"))
+ (match_operand:V4QI 2 "const0_operand" "")))]
+ "TARGET_MAX"
+ "pkwb %r1,%0"
+ [(set_attr "type" "mvi")])
+
+(define_expand "builtin_unpkbl"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extend:V2SI
+ (vec_select:V2QI (match_operand:DI 1 "register_operand" "")
+ (parallel [(const_int 0) (const_int 1)]))))]
+ "TARGET_MAX"
+{
+ operands[0] = gen_lowpart (V2SImode, operands[0]);
+ operands[1] = gen_lowpart (V8QImode, operands[1]);
+})
+
+(define_insn "*unpkbl"
+ [(set (match_operand:V2SI 0 "register_operand" "=r")
+ (zero_extend:V2SI
+ (vec_select:V2QI (match_operand:V8QI 1 "reg_or_0_operand" "rW")
+ (parallel [(const_int 0) (const_int 1)]))))]
+ "TARGET_MAX"
+ "unpkbl %r1,%0"
+ [(set_attr "type" "mvi")])
+
+(define_expand "builtin_unpkbw"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extend:V4HI
+ (vec_select:V4QI (match_operand:DI 1 "register_operand" "")
+ (parallel [(const_int 0)
+ (const_int 1)
+ (const_int 2)
+ (const_int 3)]))))]
+ "TARGET_MAX"
+{
+ operands[0] = gen_lowpart (V4HImode, operands[0]);
+ operands[1] = gen_lowpart (V8QImode, operands[1]);
+})
+
+(define_insn "*unpkbw"
+ [(set (match_operand:V4HI 0 "register_operand" "=r")
+ (zero_extend:V4HI
+ (vec_select:V4QI (match_operand:V8QI 1 "reg_or_0_operand" "rW")
+ (parallel [(const_int 0)
+ (const_int 1)
+ (const_int 2)
+ (const_int 3)]))))]
+ "TARGET_MAX"
+ "unpkbw %r1,%0"
+ [(set_attr "type" "mvi")])
+
+(define_expand "builtin_cttz"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "")]
+ UNSPEC_CTTZ))]
+ "TARGET_CIX"
+ "")
+
+(define_insn "builtin_ctlz"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")]
+ UNSPEC_CTLZ))]
+ "TARGET_CIX"
+ "ctlz %1,%0"
+ [(set_attr "type" "mvi")])
+
+(define_insn "builtin_ctpop"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")]
+ UNSPEC_CTPOP))]
+ "TARGET_CIX"
+ "ctpop %1,%0"
+ [(set_attr "type" "mvi")])
+
;; The call patterns are at the end of the file because their
;; wildcard operand0 interferes with nice recognition.
@@ -7021,7 +7805,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(plus:DI (pc) (const_int 4)))
(unspec_volatile [(reg:DI 29)] UNSPECV_BLOCKAGE)
(use (match_operand 3 "" ""))
- (use (match_operand 4 "const_int_operand" ""))]
+ (use (match_operand 4 "" ""))]
"TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
"jsr $26,(%1),%3%J4"
[(set_attr "type" "jsr")])
@@ -7041,6 +7825,70 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set_attr "type" "jsr")
(set_attr "length" "*,*,8")])
+(define_insn_and_split "call_value_osf_tlsgd"
+ [(set (match_operand 0 "" "")
+ (call (mem:DI (match_operand:DI 1 "symbolic_operand" ""))
+ (const_int 0)))
+ (unspec [(match_operand:DI 2 "const_int_operand" "")] UNSPEC_TLSGD_CALL)
+ (use (reg:DI 29))
+ (clobber (reg:DI 26))]
+ "HAVE_AS_TLS"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 3)
+ (unspec:DI [(match_dup 5)
+ (match_dup 1)
+ (match_dup 2)] UNSPEC_LITERAL))
+ (parallel [(set (match_dup 0)
+ (call (mem:DI (match_dup 3))
+ (const_int 0)))
+ (set (reg:DI 26) (plus:DI (pc) (const_int 4)))
+ (unspec_volatile [(match_dup 5)] UNSPECV_BLOCKAGE)
+ (use (match_dup 1))
+ (use (unspec [(match_dup 2)] UNSPEC_TLSGD_CALL))])
+ (set (match_dup 5)
+ (unspec_volatile:DI [(reg:DI 26) (match_dup 4)] UNSPECV_LDGP1))
+ (set (match_dup 5)
+ (unspec:DI [(match_dup 5) (match_dup 4)] UNSPEC_LDGP2))]
+{
+ operands[3] = gen_rtx_REG (Pmode, 27);
+ operands[4] = GEN_INT (alpha_next_sequence_number++);
+ operands[5] = pic_offset_table_rtx;
+}
+ [(set_attr "type" "multi")])
+
+(define_insn_and_split "call_value_osf_tlsldm"
+ [(set (match_operand 0 "" "")
+ (call (mem:DI (match_operand:DI 1 "symbolic_operand" ""))
+ (const_int 0)))
+ (unspec [(match_operand:DI 2 "const_int_operand" "")] UNSPEC_TLSLDM_CALL)
+ (use (reg:DI 29))
+ (clobber (reg:DI 26))]
+ "HAVE_AS_TLS"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 3)
+ (unspec:DI [(match_dup 5)
+ (match_dup 1)
+ (match_dup 2)] UNSPEC_LITERAL))
+ (parallel [(set (match_dup 0)
+ (call (mem:DI (match_dup 3))
+ (const_int 0)))
+ (set (reg:DI 26) (plus:DI (pc) (const_int 4)))
+ (unspec_volatile [(match_dup 5)] UNSPECV_BLOCKAGE)
+ (use (match_dup 1))
+ (use (unspec [(match_dup 2)] UNSPEC_TLSLDM_CALL))])
+ (set (reg:DI 29)
+ (unspec_volatile:DI [(reg:DI 26) (match_dup 4)] UNSPECV_LDGP1))
+ (set (reg:DI 29)
+ (unspec:DI [(reg:DI 29) (match_dup 4)] UNSPEC_LDGP2))]
+{
+ operands[3] = gen_rtx_REG (Pmode, 27);
+ operands[4] = GEN_INT (alpha_next_sequence_number++);
+ operands[5] = pic_offset_table_rtx;
+}
+ [(set_attr "type" "multi")])
+
(define_insn "*call_value_osf_1"
[(set (match_operand 0 "" "")
(call (mem:DI (match_operand:DI 1 "call_operand" "c,R,s"))
@@ -7092,18 +7940,32 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set_attr "type" "jsr")
(set_attr "length" "*,*,12")])
+; GAS relies on the order and position of instructions output below in order
+; to generate relocs for VMS link to potentially optimize the call.
+; Please do not molest.
(define_insn "*call_value_vms_1"
[(set (match_operand 0 "" "")
(call (mem:DI (match_operand:DI 1 "call_operand" "r,s"))
(match_operand 2 "" "")))
- (use (match_operand:DI 3 "nonimmediate_operand" "r,m"))
+ (use (match_operand:DI 3 "nonmemory_operand" "r,n"))
(use (reg:DI 25))
(use (reg:DI 26))
(clobber (reg:DI 27))]
"TARGET_ABI_OPEN_VMS"
- "@
- mov %3,$27\;jsr $26,0\;ldq $27,0($29)
- ldq $27,%3\;jsr $26,%1\;ldq $27,0($29)"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return \"mov %3,$27\;jsr $26,0\;ldq $27,0($29)\";
+ case 1:
+ operands [3] = alpha_use_linkage (operands [1], cfun->decl, 1, 0);
+ operands [4] = alpha_use_linkage (operands [1], cfun->decl, 0, 0);
+ return \"ldq $26,%4\;ldq $27,%3\;jsr $26,%1\;ldq $27,0($29)\";
+ default:
+ abort();
+ }
+}"
[(set_attr "type" "jsr")
(set_attr "length" "12,16")])
@@ -7116,4 +7978,3 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
"TARGET_ABI_UNICOSMK"
"jsr $26,(%1)"
[(set_attr "type" "jsr")])
-
diff --git a/contrib/gcc/config/alpha/elf.h b/contrib/gcc/config/alpha/elf.h
index 9f8d808..dbe9263 100644
--- a/contrib/gcc/config/alpha/elf.h
+++ b/contrib/gcc/config/alpha/elf.h
@@ -27,30 +27,23 @@ Boston, MA 02111-1307, USA. */
/* ??? Move all SDB stuff from alpha.h to osf.h. */
#undef SDB_DEBUGGING_INFO
-#define DBX_DEBUGGING_INFO
-#define DWARF2_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
+#define DWARF2_DEBUGGING_INFO 1
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
#undef ASM_FINAL_SPEC
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC "-D__ELF__"
+
#undef CC1_SPEC
#define CC1_SPEC "%{G*}"
#undef ASM_SPEC
#define ASM_SPEC "%{G*} %{relax:-relax} %{!gstabs*:-no-mdebug}%{gstabs*:-mdebug}"
-#undef LINK_SPEC
-#define LINK_SPEC "-m elf64alpha %{G*} %{relax:-relax} \
- %{O*:-O3} %{!O*:-O1} \
- %{shared:-shared} \
- %{!shared: \
- %{!static: \
- %{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker %(elf_dynamic_linker)}} \
- %{static:-static}}"
-
/* Output at beginning of assembler file. */
#undef ASM_FILE_START
#define ASM_FILE_START(FILE) \
@@ -75,9 +68,6 @@ do { \
#undef IDENT_ASM_OP
#define IDENT_ASM_OP "\t.ident\t"
-/* Allow #sccs in preprocessor. */
-#define SCCS_DIRECTIVE
-
/* Output #ident as a .ident. */
#undef ASM_OUTPUT_IDENT
#define ASM_OUTPUT_IDENT(FILE, NAME) \
@@ -122,7 +112,7 @@ do { \
#undef ASM_OUTPUT_EXTERNAL_LIBCALL
#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
- ASM_GLOBALIZE_LABEL (FILE, XSTR (FUN, 0))
+ (*targetm.asm_out.globalize_label) (FILE, XSTR (FUN, 0))
/* This says how to output assembler code to declare an
uninitialized external linkage data object. Under SVR4,
@@ -152,17 +142,9 @@ do { \
sbss_section(); \
else \
bss_section(); \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
- putc ('\n', FILE); \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
if (!flag_inhibit_size_directive) \
- { \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, ",%d\n", (SIZE)); \
- } \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE); \
ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT)); \
ASM_OUTPUT_LABEL(FILE, NAME); \
ASM_OUTPUT_SKIP((FILE), (SIZE) ? (SIZE) : 1); \
@@ -174,7 +156,7 @@ do { \
#undef ASM_OUTPUT_ALIGNED_BSS
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
do { \
- ASM_GLOBALIZE_LABEL (FILE, NAME); \
+ (*targetm.asm_out.globalize_label) (FILE, NAME); \
ASM_OUTPUT_ALIGNED_LOCAL (FILE, NAME, SIZE, ALIGN); \
} while (0)
@@ -198,20 +180,8 @@ do { \
#undef ASCII_DATA_ASM_OP
#define ASCII_DATA_ASM_OP "\t.ascii\t"
-/* Support const sections and the ctors and dtors sections for g++.
- Note that there appears to be two different ways to support const
- sections at the moment. You can either #define the symbol
- READONLY_DATA_SECTION (giving it some code which switches to the
- readonly data section) or else you can #define the symbols
- EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
- SELECT_RTX_SECTION. We do both here just to be on the safe side. */
-
-#undef USE_CONST_SECTION
-#define USE_CONST_SECTION 1
-
-#undef CONST_SECTION_ASM_OP
-#define CONST_SECTION_ASM_OP "\t.section\t.rodata"
-
+#undef READONLY_DATA_SECTION_ASM_OP
+#define READONLY_DATA_SECTION_ASM_OP "\t.section\t.rodata"
#undef BSS_SECTION_ASM_OP
#define BSS_SECTION_ASM_OP "\t.section\t.bss"
#undef SBSS_SECTION_ASM_OP
@@ -246,7 +216,7 @@ do { \
includes this file. */
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const, in_sbss, in_sdata
+#define EXTRA_SECTIONS in_sbss, in_sdata
/* A default list of extra section function definitions. For targets
that use additional sections (e.g. .tdesc) you should override this
@@ -254,30 +224,12 @@ do { \
#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
- CONST_SECTION_FUNCTION \
SECTION_FUNCTION_TEMPLATE(sbss_section, in_sbss, SBSS_SECTION_ASM_OP) \
SECTION_FUNCTION_TEMPLATE(sdata_section, in_sdata, SDATA_SECTION_ASM_OP)
extern void sbss_section PARAMS ((void));
extern void sdata_section PARAMS ((void));
-#undef READONLY_DATA_SECTION
-#define READONLY_DATA_SECTION() const_section ()
-
-#undef CONST_SECTION_FUNCTION
-#define CONST_SECTION_FUNCTION \
-void \
-const_section () \
-{ \
- if (!USE_CONST_SECTION) \
- text_section(); \
- else if (in_section != in_const) \
- { \
- fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
- in_section = in_const; \
- } \
-}
-
#undef SECTION_FUNCTION_TEMPLATE
#define SECTION_FUNCTION_TEMPLATE(FN, ENUM, OP) \
void FN () \
@@ -291,177 +243,10 @@ void FN () \
/* Switch into a generic section. */
#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
-
-/* 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.
-
- Set SECNUM to:
- 0 .text
- 1 .rodata
- 2 .data
- 3 .sdata
- 4 .bss
- 5 .sbss
-*/
-
-#define DO_SELECT_SECTION(SECNUM, DECL, RELOC) \
- do \
- { \
- HOST_WIDE_INT size; \
- SECNUM = 1; \
- if (TREE_CODE (DECL) == FUNCTION_DECL) \
- { \
- SECNUM = 0; \
- break; \
- } \
- else if (TREE_CODE (DECL) == STRING_CST) \
- { \
- if (flag_writable_strings) \
- SECNUM = 2; \
- else \
- SECNUM = 0x101; \
- break; \
- } \
- else if (TREE_CODE (DECL) == VAR_DECL) \
- { \
- if (DECL_INITIAL (DECL) == NULL \
- || DECL_INITIAL (DECL) == error_mark_node) \
- SECNUM = 4; \
- else if ((flag_pic && RELOC) \
- || ! TREE_READONLY (DECL) \
- || TREE_SIDE_EFFECTS (DECL) \
- || ! TREE_CONSTANT (DECL_INITIAL (DECL))) \
- SECNUM = 2; \
- else if (flag_merge_constants >= 2) \
- { \
- /* C and C++ don't allow different variables to \
- share the same location. -fmerge-all-constants\
- allows even that (at the expense of not \
- conforming). */ \
- if (TREE_CODE (DECL_INITIAL (DECL)) == STRING_CST)\
- SECNUM = 0x201; \
- else \
- SECNUM = 0x301; \
- } \
- } \
- else if (TREE_CODE (DECL) == CONSTRUCTOR) \
- { \
- if ((flag_pic && RELOC) \
- || TREE_SIDE_EFFECTS (DECL) \
- || ! TREE_CONSTANT (DECL)) \
- SECNUM = 2; \
- } \
- \
- /* Select small data sections based on size. */ \
- size = int_size_in_bytes (TREE_TYPE (DECL)); \
- if (size >= 0 && size <= g_switch_value) \
- { \
- if ((SECNUM & 0xff) >= 2) \
- SECNUM += 1; \
- /* Move readonly data to .sdata only if -msmall-data. */ \
- /* ??? Consider .sdata.{lit4,lit8} as \
- SHF_MERGE|SHF_ALPHA_GPREL. */ \
- else if (TARGET_SMALL_DATA) \
- SECNUM = 3; \
- } \
- } \
- while (0)
-
-#undef SELECT_SECTION
-#define SELECT_SECTION(DECL, RELOC, ALIGN) \
- do \
- { \
- typedef void (*sec_fn) PARAMS ((void)); \
- static sec_fn const sec_functions[6] = \
- { \
- text_section, \
- const_section, \
- data_section, \
- sdata_section, \
- bss_section, \
- sbss_section \
- }; \
- \
- int sec; \
- \
- DO_SELECT_SECTION (sec, DECL, RELOC); \
- \
- switch (sec) \
- { \
- case 0x101: \
- mergeable_string_section (DECL, ALIGN, 0); \
- break; \
- case 0x201: \
- mergeable_string_section (DECL_INITIAL (DECL),\
- ALIGN, 0); \
- break; \
- case 0x301: \
- mergeable_constant_section (DECL_MODE (DECL), \
- ALIGN, 0); \
- break; \
- default: \
- (*sec_functions[sec]) (); \
- break; \
- } \
- } \
- while (0)
+#define TARGET_ASM_SELECT_SECTION default_elf_select_section
#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
-#undef UNIQUE_SECTION
-#define UNIQUE_SECTION(DECL, RELOC) \
- do \
- { \
- static const char * const prefixes[6][2] = \
- { \
- { ".text.", ".gnu.linkonce.t." }, \
- { ".rodata.", ".gnu.linkonce.r." }, \
- { ".data.", ".gnu.linkonce.d." }, \
- { ".sdata.", ".gnu.linkonce.s." }, \
- { ".bss.", ".gnu.linkonce.b." }, \
- { ".sbss.", ".gnu.linkonce.sb." } \
- }; \
- \
- int nlen, plen, sec; \
- const char *name, *prefix; \
- char *string; \
- \
- DO_SELECT_SECTION (sec, DECL, RELOC); \
- \
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
- STRIP_NAME_ENCODING (name, name); \
- nlen = strlen (name); \
- \
- prefix = prefixes[sec & 0xff][DECL_ONE_ONLY(DECL)]; \
- plen = strlen (prefix); \
- \
- string = alloca (nlen + plen + 1); \
- \
- memcpy (string, prefix, plen); \
- memcpy (string + plen, name, nlen + 1); \
- \
- DECL_SECTION_NAME (DECL) = build_string (nlen + plen, string); \
- } \
- while (0)
-
-/* A C statement or statements to switch to the appropriate
- section for output of RTX in mode MODE. RTX is some kind
- of constant in RTL. The argument MODE is redundant except
- in the case of a `const_int' rtx. Currently, these always
- go into the const section. */
-
-#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE, RTX, ALIGN) \
-do { \
- if (TARGET_SMALL_DATA && GET_MODE_SIZE (MODE) <= g_switch_value) \
- /* ??? Consider .sdata.{lit4,lit8} as SHF_MERGE|SHF_ALPHA_GPREL. */ \
- sdata_section (); \
- else \
- mergeable_constant_section((MODE), (ALIGN), 0); \
-} while (0)
-
/* Define the strings used for the special svr4 .type and .size directives.
These strings generally do not vary from one system running svr4 to
another, but if a given system (e.g. m88k running svr) needs to use
@@ -538,22 +323,14 @@ do { \
#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
do { \
HOST_WIDE_INT size; \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
- putc ('\n', FILE); \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
size_directive_output = 0; \
if (!flag_inhibit_size_directive \
&& DECL_SIZE (DECL) \
&& (size = int_size_in_bytes (TREE_TYPE (DECL))) > 0) \
{ \
size_directive_output = 1; \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, NAME); \
- fputc (',', FILE); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, size); \
- fputc ('\n', FILE); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \
} \
ASM_OUTPUT_LABEL(FILE, NAME); \
} while (0)
@@ -577,11 +354,7 @@ do { \
&& (size = int_size_in_bytes (TREE_TYPE (DECL))) > 0) \
{ \
size_directive_output = 1; \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, name); \
- fputc (',', FILE); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, size); \
- fputc ('\n', FILE); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, name, size); \
} \
} while (0)
@@ -653,7 +426,7 @@ do { \
%{shared:crtendS.o%s}%{!shared:crtend.o%s} crtn.o%s"
/* We support #pragma. */
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
/* Select a format to encode pointers in exception handling data. CODE
is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
diff --git a/contrib/gcc/config/alpha/ev4.md b/contrib/gcc/config/alpha/ev4.md
new file mode 100644
index 0000000..41e1efd
--- /dev/null
+++ b/contrib/gcc/config/alpha/ev4.md
@@ -0,0 +1,147 @@
+;; Scheduling description for Alpha EV4.
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU CC.
+;;
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+; On EV4 there are two classes of resources to consider: resources needed
+; to issue, and resources needed to execute. IBUS[01] are in the first
+; category. ABOX, BBOX, EBOX, FBOX, IMUL & FDIV make up the second.
+; (There are a few other register-like resources, but ...)
+
+(define_automaton "ev4_0,ev4_1,ev4_2")
+(define_cpu_unit "ev4_ib0,ev4_ib1,ev4_abox,ev4_bbox" "ev4_0")
+(define_cpu_unit "ev4_ebox,ev4_imul" "ev4_1")
+(define_cpu_unit "ev4_fbox,ev4_fdiv" "ev4_2")
+(define_reservation "ev4_ib01" "ev4_ib0|ev4_ib1")
+
+; Assume type "multi" single issues.
+(define_insn_reservation "ev4_multi" 1
+ (and (eq_attr "cpu" "ev4")
+ (eq_attr "type" "multi"))
+ "ev4_ib0+ev4_ib1")
+
+; Loads from L0 completes in three cycles. adjust_cost still factors
+; in user-specified memory latency, so return 1 here.
+(define_insn_reservation "ev4_ld" 1
+ (and (eq_attr "cpu" "ev4")
+ (eq_attr "type" "ild,fld,ldsym"))
+ "ev4_ib01+ev4_abox")
+
+; Stores can issue before the data (but not address) is ready.
+(define_insn_reservation "ev4_ist" 1
+ (and (eq_attr "cpu" "ev4")
+ (eq_attr "type" "ist"))
+ "ev4_ib1+ev4_abox")
+
+(define_insn_reservation "ev4_fst" 1
+ (and (eq_attr "cpu" "ev4")
+ (eq_attr "type" "fst"))
+ "ev4_ib0+ev4_abox")
+
+; Branches have no delay cost, but do tie up the unit for two cycles.
+(define_insn_reservation "ev4_ibr" 2
+ (and (eq_attr "cpu" "ev4")
+ (eq_attr "type" "ibr,jsr"))
+ "ev4_ib1+ev4_bbox,ev4_bbox")
+
+(define_insn_reservation "ev4_callpal" 2
+ (and (eq_attr "cpu" "ev4")
+ (eq_attr "type" "callpal"))
+ "ev4_ib1+ev4_bbox,ev4_bbox")
+
+(define_insn_reservation "ev4_fbr" 2
+ (and (eq_attr "cpu" "ev4")
+ (eq_attr "type" "fbr"))
+ "ev4_ib0+ev4_bbox,ev4_bbox")
+
+; Arithmetic insns are normally have their results available after
+; two cycles. There are a number of exceptions.
+
+(define_insn_reservation "ev4_iaddlog" 2
+ (and (eq_attr "cpu" "ev4")
+ (eq_attr "type" "iadd,ilog"))
+ "ev4_ib0+ev4_ebox")
+
+(define_bypass 1
+ "ev4_iaddlog"
+ "ev4_ibr,ev4_iaddlog,ev4_shiftcm,ev4_icmp,ev4_imulsi,ev4_imuldi")
+
+(define_insn_reservation "ev4_shiftcm" 2
+ (and (eq_attr "cpu" "ev4")
+ (eq_attr "type" "shift,icmov"))
+ "ev4_ib0+ev4_ebox")
+
+(define_insn_reservation "ev4_icmp" 2
+ (and (eq_attr "cpu" "ev4")
+ (eq_attr "type" "icmp"))
+ "ev4_ib0+ev4_ebox")
+
+(define_bypass 1 "ev4_icmp" "ev4_ibr")
+
+(define_bypass 0
+ "ev4_iaddlog,ev4_shiftcm,ev4_icmp"
+ "ev4_ist"
+ "store_data_bypass_p")
+
+; Multiplies use a non-piplined imul unit. Also, "no [ebox] insn can
+; be issued exactly three cycles before an integer multiply completes".
+
+(define_insn_reservation "ev4_imulsi" 21
+ (and (eq_attr "cpu" "ev4")
+ (and (eq_attr "type" "imul")
+ (eq_attr "opsize" "si")))
+ "ev4_ib0+ev4_imul,ev4_imul*18,ev4_ebox")
+
+(define_bypass 20 "ev4_imulsi" "ev4_ist" "store_data_bypass_p")
+
+(define_insn_reservation "ev4_imuldi" 23
+ (and (eq_attr "cpu" "ev4")
+ (and (eq_attr "type" "imul")
+ (eq_attr "opsize" "!si")))
+ "ev4_ib0+ev4_imul,ev4_imul*20,ev4_ebox")
+
+(define_bypass 22 "ev4_imuldi" "ev4_ist" "store_data_bypass_p")
+
+; Most FP insns have a 6 cycle latency, but with a 4 cycle bypass back in.
+(define_insn_reservation "ev4_fpop" 6
+ (and (eq_attr "cpu" "ev4")
+ (eq_attr "type" "fadd,fmul,fcpys,fcmov"))
+ "ev4_ib1+ev4_fbox")
+
+(define_bypass 4 "ev4_fpop" "ev4_fpop")
+
+; The floating point divider is not pipelined. Also, "no FPOP insn can be
+; issued exactly five or exactly six cycles before an fdiv insn completes".
+
+(define_insn_reservation "ev4_fdivsf" 34
+ (and (eq_attr "cpu" "ev4")
+ (and (eq_attr "type" "fdiv")
+ (eq_attr "opsize" "si")))
+ "ev4_ib1+ev4_fdiv,ev4_fdiv*28,ev4_fdiv+ev4_fbox,ev4_fbox")
+
+(define_insn_reservation "ev4_fdivdf" 63
+ (and (eq_attr "cpu" "ev4")
+ (and (eq_attr "type" "fdiv")
+ (eq_attr "opsize" "di")))
+ "ev4_ib1+ev4_fdiv,ev4_fdiv*57,ev4_fdiv+ev4_fbox,ev4_fbox")
+
+; Traps don't consume or produce data.
+(define_insn_reservation "ev4_misc" 1
+ (and (eq_attr "cpu" "ev4")
+ (eq_attr "type" "misc"))
+ "ev4_ib1")
diff --git a/contrib/gcc/config/alpha/ev5.md b/contrib/gcc/config/alpha/ev5.md
new file mode 100644
index 0000000..832cf6b
--- /dev/null
+++ b/contrib/gcc/config/alpha/ev5.md
@@ -0,0 +1,190 @@
+;; Scheduling description for Alpha EV5.
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU CC.
+;;
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; EV5 has two asymetric integer units, E0 and E1, plus separate
+;; FP add and multiply units.
+
+(define_automaton "ev5_0,ev5_1")
+(define_cpu_unit "ev5_e0,ev5_e1,ev5_fa,ev5_fm" "ev5_0")
+(define_reservation "ev5_e01" "ev5_e0|ev5_e1")
+(define_reservation "ev5_fam" "ev5_fa|ev5_fm")
+(define_cpu_unit "ev5_imul" "ev5_0")
+(define_cpu_unit "ev5_fdiv" "ev5_1")
+
+; Assume type "multi" single issues.
+(define_insn_reservation "ev5_multi" 1
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "multi"))
+ "ev5_e0+ev5_e1+ev5_fa+ev5_fm")
+
+; Stores can only issue to E0, and may not issue with loads.
+; Model this with some fake units.
+
+(define_cpu_unit "ev5_l0,ev5_l1,ev5_st" "ev5_0")
+(define_reservation "ev5_ld" "ev5_l0|ev5_l1")
+(exclusion_set "ev5_l0,ev5_l1" "ev5_st")
+
+(define_insn_reservation "ev5_st" 1
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "ist,fst"))
+ "ev5_e0+ev5_st")
+
+; Loads from L0 complete in two cycles. adjust_cost still factors
+; in user-specified memory latency, so return 1 here.
+(define_insn_reservation "ev5_ld" 1
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "ild,fld,ldsym"))
+ "ev5_e01+ev5_ld")
+
+; Integer branches slot only to E1.
+(define_insn_reservation "ev5_ibr" 1
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "ibr"))
+ "ev5_e1")
+
+(define_insn_reservation "ev5_callpal" 1
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "callpal"))
+ "ev5_e1")
+
+(define_insn_reservation "ev5_jsr" 1
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "jsr"))
+ "ev5_e1")
+
+(define_insn_reservation "ev5_shift" 1
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "shift"))
+ "ev5_e0")
+
+(define_insn_reservation "ev5_mvi" 2
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "mvi"))
+ "ev5_e0")
+
+(define_insn_reservation "ev5_cmov" 2
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "icmov"))
+ "ev5_e01")
+
+(define_insn_reservation "ev5_iadd" 1
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "iadd"))
+ "ev5_e01")
+
+(define_insn_reservation "ev5_ilogcmp" 1
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "ilog,icmp"))
+ "ev5_e01")
+
+; Conditional move and branch can issue the same cycle as the test.
+(define_bypass 0 "ev5_ilogcmp" "ev5_ibr,ev5_cmov" "if_test_bypass_p")
+
+; Multiplies use a non-piplined imul unit. Also, "no insn can be issued
+; to E0 exactly two cycles before an integer multiply completes".
+
+(define_insn_reservation "ev5_imull" 8
+ (and (eq_attr "cpu" "ev5")
+ (and (eq_attr "type" "imul")
+ (eq_attr "opsize" "si")))
+ "ev5_e0+ev5_imul,ev5_imul*3,nothing,ev5_e0")
+
+(define_insn_reservation "ev5_imulq" 12
+ (and (eq_attr "cpu" "ev5")
+ (and (eq_attr "type" "imul")
+ (eq_attr "opsize" "di")))
+ "ev5_e0+ev5_imul,ev5_imul*7,nothing,ev5_e0")
+
+(define_insn_reservation "ev5_imulh" 14
+ (and (eq_attr "cpu" "ev5")
+ (and (eq_attr "type" "imul")
+ (eq_attr "opsize" "udi")))
+ "ev5_e0+ev5_imul,ev5_imul*7,nothing*3,ev5_e0")
+
+; The multiplier is unable to receive data from Ebox bypass paths. The
+; instruction issues at the expected time, but its latency is increased
+; by the time it takes for the input data to become available to the
+; multiplier. For example, an IMULL instruction issued one cycle later
+; than an ADDL instruction, which produced one of its operands, has a
+; latency of 10 (8 + 2). If the IMULL instruction is issued two cycles
+; later than the ADDL instruction, the latency is 9 (8 + 1).
+;
+; Model this instead with increased latency on the input instruction.
+
+(define_bypass 3
+ "ev5_ld,ev5_shift,ev5_mvi,ev5_cmov,ev5_iadd,ev5_ilogcmp"
+ "ev5_imull,ev5_imulq,ev5_imulh")
+
+(define_bypass 9 "ev5_imull" "ev5_imull,ev5_imulq,ev5_imulh")
+(define_bypass 13 "ev5_imulq" "ev5_imull,ev5_imulq,ev5_imulh")
+(define_bypass 15 "ev5_imulh" "ev5_imull,ev5_imulq,ev5_imulh")
+
+; Similarly for the FPU we have two asymetric units.
+
+(define_insn_reservation "ev5_fadd" 4
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "fadd,fcmov"))
+ "ev5_fa")
+
+(define_insn_reservation "ev5_fbr" 1
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "fbr"))
+ "ev5_fa")
+
+(define_insn_reservation "ev5_fcpys" 4
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "fcpys"))
+ "ev5_fam")
+
+(define_insn_reservation "ev5_fmul" 4
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "fmul"))
+ "ev5_fm")
+
+; The floating point divider is not pipelined. Also, "no insn can be issued
+; to FA exactly five before an fdiv insn completes".
+;
+; ??? Do not model this late reservation due to the enormously increased
+; size of the resulting DFA.
+;
+; ??? Putting ev5_fa and ev5_fdiv alone into the same automata produces
+; a DFA of acceptable size, but putting ev5_fm and ev5_fa into separate
+; automata produces incorrect results for insns that can choose one or
+; the other, i.e. ev5_fcpys.
+
+(define_insn_reservation "ev5_fdivsf" 15
+ (and (eq_attr "cpu" "ev5")
+ (and (eq_attr "type" "fdiv")
+ (eq_attr "opsize" "si")))
+ ; "ev5_fa+ev5_fdiv,ev5_fdiv*9,ev5_fa+ev5_fdiv,ev5_fdiv*4"
+ "ev5_fa+ev5_fdiv,ev5_fdiv*14")
+
+(define_insn_reservation "ev5_fdivdf" 22
+ (and (eq_attr "cpu" "ev5")
+ (and (eq_attr "type" "fdiv")
+ (eq_attr "opsize" "di")))
+ ; "ev5_fa+ev5_fdiv,ev5_fdiv*17,ev5_fa+ev5_fdiv,ev5_fdiv*4"
+ "ev5_fa+ev5_fdiv,ev5_fdiv*21")
+
+; Traps don't consume or produce data; rpcc is latency 2 if we ever add it.
+(define_insn_reservation "ev5_misc" 2
+ (and (eq_attr "cpu" "ev5")
+ (eq_attr "type" "misc"))
+ "ev5_e0")
diff --git a/contrib/gcc/config/alpha/ev6.md b/contrib/gcc/config/alpha/ev6.md
new file mode 100644
index 0000000..12204b6
--- /dev/null
+++ b/contrib/gcc/config/alpha/ev6.md
@@ -0,0 +1,173 @@
+;; Scheduling description for Alpha EV6.
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU CC.
+;;
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+; EV6 can issue 4 insns per clock. It's out-of-order, so this isn't
+; expected to help over-much, but a precise description can be important
+; for software pipelining.
+;
+; EV6 has two symmetric pairs ("clusters") of two asymetric integer
+; units ("upper" and "lower"), yielding pipe names U0, U1, L0, L1.
+;
+; ??? The clusters have independent register files that are re-synced
+; every cycle. Thus there is one additional cycle of latency between
+; insns issued on different clusters. Possibly model that by duplicating
+; all EBOX insn_reservations that can issue to either cluster, increasing
+; all latencies by one, and adding bypasses within the cluster.
+;
+; ??? In addition, instruction order affects cluster issue.
+
+(define_automaton "ev6_0,ev6_1")
+(define_cpu_unit "ev6_u0,ev6_u1,ev6_l0,ev6_l1" "ev6_0")
+(define_reservation "ev6_u" "ev6_u0|ev6_u1")
+(define_reservation "ev6_l" "ev6_l0|ev6_l1")
+(define_reservation "ev6_ebox" "ev6_u|ev6_l")
+
+(define_cpu_unit "ev6_fa" "ev6_1")
+(define_cpu_unit "ev6_fm,ev6_fst0,ev6_fst1" "ev6_0")
+(define_reservation "ev6_fst" "ev6_fst0|ev6_fst1")
+
+; Assume type "multi" single issues.
+(define_insn_reservation "ev6_multi" 1
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "multi"))
+ "ev6_u0+ev6_u1+ev6_l0+ev6_l1+ev6_fa+ev6_fm+ev6_fst0+ev6_fst1")
+
+; Integer loads take at least 3 clocks, and only issue to lower units.
+; adjust_cost still factors in user-specified memory latency, so return 1 here.
+(define_insn_reservation "ev6_ild" 1
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "ild,ldsym"))
+ "ev6_l")
+
+(define_insn_reservation "ev6_ist" 1
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "ist"))
+ "ev6_l")
+
+; FP loads take at least 4 clocks. adjust_cost still factors
+; in user-specified memory latency, so return 2 here.
+(define_insn_reservation "ev6_fld" 2
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "fld"))
+ "ev6_l")
+
+; The FPU communicates with memory and the integer register file
+; via two fp store units. We need a slot in the fst immediately, and
+; a slot in LOW after the operand data is ready. At which point the
+; data may be moved either to the store queue or the integer register
+; file and the insn retired.
+
+(define_insn_reservation "ev6_fst" 3
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "fst"))
+ "ev6_fst,nothing,ev6_l")
+
+; Arithmetic goes anywhere.
+(define_insn_reservation "ev6_arith" 1
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "iadd,ilog,icmp"))
+ "ev6_ebox")
+
+; Motion video insns also issue only to U0, and take three ticks.
+(define_insn_reservation "ev6_mvi" 3
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "mvi"))
+ "ev6_u0")
+
+; Shifts issue to upper units.
+(define_insn_reservation "ev6_shift" 1
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "shift"))
+ "ev6_u")
+
+; Multiplies issue only to U1, and all take 7 ticks.
+(define_insn_reservation "ev6_imul" 7
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "imul"))
+ "ev6_u1")
+
+; Conditional moves decompose into two independent primitives, each taking
+; one cycle. Since ev6 is out-of-order, we can't see anything but two cycles.
+(define_insn_reservation "ev6_icmov" 2
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "icmov"))
+ "ev6_ebox,ev6_ebox")
+
+; Integer branches issue to upper units
+(define_insn_reservation "ev6_ibr" 1
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "ibr,callpal"))
+ "ev6_u")
+
+; Calls only issue to L0.
+(define_insn_reservation "ev6_jsr" 1
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "jsr"))
+ "ev6_l0")
+
+; Ftoi/itof only issue to lower pipes.
+(define_insn_reservation "ev6_itof" 3
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "itof"))
+ "ev6_l")
+
+(define_insn_reservation "ev6_ftoi" 3
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "ftoi"))
+ "ev6_fst,nothing,ev6_l")
+
+(define_insn_reservation "ev6_fmul" 4
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "fmul"))
+ "ev6_fm")
+
+(define_insn_reservation "ev6_fadd" 4
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "fadd,fcpys,fbr"))
+ "ev6_fa")
+
+(define_insn_reservation "ev6_fcmov" 8
+ (and (eq_attr "cpu" "ev6")
+ (eq_attr "type" "fcmov"))
+ "ev6_fa,nothing*3,ev6_fa")
+
+(define_insn_reservation "ev6_fdivsf" 12
+ (and (eq_attr "cpu" "ev6")
+ (and (eq_attr "type" "fdiv")
+ (eq_attr "opsize" "si")))
+ "ev6_fa*9")
+
+(define_insn_reservation "ev6_fdivdf" 15
+ (and (eq_attr "cpu" "ev6")
+ (and (eq_attr "type" "fdiv")
+ (eq_attr "opsize" "di")))
+ "ev6_fa*12")
+
+(define_insn_reservation "ev6_sqrtsf" 18
+ (and (eq_attr "cpu" "ev6")
+ (and (eq_attr "type" "fsqrt")
+ (eq_attr "opsize" "si")))
+ "ev6_fa*15")
+
+(define_insn_reservation "ev6_sqrtdf" 33
+ (and (eq_attr "cpu" "ev6")
+ (and (eq_attr "type" "fsqrt")
+ (eq_attr "opsize" "di")))
+ "ev6_fa*30")
diff --git a/contrib/gcc/config/alpha/freebsd.h b/contrib/gcc/config/alpha/freebsd.h
index 35a9e65..f809c62 100644
--- a/contrib/gcc/config/alpha/freebsd.h
+++ b/contrib/gcc/config/alpha/freebsd.h
@@ -20,18 +20,26 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Provide a CPP_SPEC appropriate for FreeBSD/alpha. Besides the dealing with
+/* Provide a FBSD_TARGET_CPU_CPP_BUILTINS and CPP_SPEC appropriate for
+ FreeBSD/alpha. Besides the dealing with
the GCC option `-posix', and PIC issues as on all FreeBSD platforms, we must
deal with the Alpha's FP issues. */
+#undef FBSD_TARGET_CPU_CPP_BUILTINS
+#define FBSD_TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ if (flag_pic) \
+ { \
+ builtin_define ("__PIC__"); \
+ builtin_define ("__pic__"); \
+ } \
+ } \
+ while (0)
+
#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu) %(cpp_subtarget) -D__ELF__ \
- %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} \
- %{posix:-D_POSIX_SOURCE} \
- %{mieee:-D_IEEE_FP} \
- %{mieee-with-inexact:-D_IEEE_FP -D_IEEE_FP_INEXACT}"
+#define CPP_SPEC "%(cpp_subtarget) %{posix:-D_POSIX_SOURCE}"
-#undef LINK_SPEC
#define LINK_SPEC "%{G*} %{relax:-relax} \
%{p:%e`-p' not supported; use `-pg' and gprof(1)} \
%{Wl,*:%*} \
@@ -54,9 +62,6 @@ Boston, MA 02111-1307, USA. */
/* alpha.h gets this wrong for FreeBSD. We use the GCC defaults instead. */
#undef WCHAR_TYPE
-#undef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
-
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
diff --git a/contrib/gcc/config/alpha/gnu.h b/contrib/gcc/config/alpha/gnu.h
new file mode 100644
index 0000000..9b25daf
--- /dev/null
+++ b/contrib/gcc/config/alpha/gnu.h
@@ -0,0 +1,30 @@
+/* Configuration for an Alpha running GNU with ELF as the target machine. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (Alpha GNU)");
+
+#undef TARGET_OS_CPP_BUILTINS /* config.gcc includes alpha/linux.h. */
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__GNU__"); \
+ builtin_define ("__ELF__"); \
+ builtin_define ("__gnu_hurd__"); \
+ builtin_define ("_LONGLONG"); \
+ builtin_define_std ("unix"); \
+ builtin_assert ("system=gnu"); \
+ } while (0)
+
+#undef ELF_DYNAMIC_LINKER
+#define ELF_DYNAMIC_LINKER "/lib/ld.so"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shared: \
+ %{!static: \
+ %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}} \
+ %{static:crt0.o%s}} \
+ crti.o%s \
+ %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
+
+/* FIXME: Is a Hurd-specific fallback mechanism necessary? */
+#undef MD_FALLBACK_FRAME_STATE_FOR
diff --git a/contrib/gcc/config/alpha/linux-elf.h b/contrib/gcc/config/alpha/linux-elf.h
index 6430059..49f5181 100644
--- a/contrib/gcc/config/alpha/linux-elf.h
+++ b/contrib/gcc/config/alpha/linux-elf.h
@@ -27,17 +27,23 @@ Boston, MA 02111-1307, USA. */
#define SUBTARGET_EXTRA_SPECS \
{ "elf_dynamic_linker", ELF_DYNAMIC_LINKER },
-#undef SUB_CPP_PREDEFINES
-#define SUB_CPP_PREDEFINES "-D__ELF__"
-
#ifdef USE_GNULIBC_1
#define ELF_DYNAMIC_LINKER "/lib/ld.so.1"
#else
#define ELF_DYNAMIC_LINKER "/lib/ld-linux.so.2"
#endif
+#define LINK_SPEC "-m elf64alpha %{G*} %{relax:-relax} \
+ %{O*:-O3} %{!O*:-O1} \
+ %{shared:-shared} \
+ %{!shared: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker %(elf_dynamic_linker)}} \
+ %{static:-static}}"
+
#ifndef USE_GNULIBC_1
#undef LIB_SPEC
#define LIB_SPEC \
-"%{shared:-lc}%{!shared:%{pthread:-lpthread }%{profile:-lc_p}%{!profile:-lc}} "
+"%{pthread:-lpthread }%{shared:-lc}%{!shared:%{profile:-lc_p}%{!profile:-lc}} "
#endif
diff --git a/contrib/gcc/config/alpha/linux.h b/contrib/gcc/config/alpha/linux.h
index 912d7b26..0c53344 100644
--- a/contrib/gcc/config/alpha/linux.h
+++ b/contrib/gcc/config/alpha/linux.h
@@ -23,20 +23,23 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_FP | MASK_FPREGS | MASK_GAS)
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
-"-D__gnu_linux__ -Dlinux -Dunix -Asystem=linux -D_LONGLONG -D__alpha__ " \
-SUB_CPP_PREDEFINES
-
-/* The GNU C++ standard library requires that these macros be defined. */
-#undef CPLUSPLUS_CPP_SPEC
-#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__gnu_linux__"); \
+ builtin_define ("_LONGLONG"); \
+ builtin_define_std ("linux"); \
+ builtin_define_std ("unix"); \
+ builtin_assert ("system=linux"); \
+ /* The GNU C++ standard library requires this. */ \
+ if (c_language == clk_cplusplus) \
+ builtin_define ("_GNU_SOURCE"); \
+ } while (0)
#undef LIB_SPEC
#define LIB_SPEC \
- "%{shared: -lc} \
- %{!shared: %{pthread:-lpthread} \
- %{profile:-lc_p} %{!profile: -lc}}"
+ "%{pthread:-lpthread} \
+ %{shared:-lc} \
+ %{!shared: %{profile:-lc_p}%{!profile:-lc}}"
/* Show that we need a GP when profiling. */
#undef TARGET_PROFILING_NEEDS_GP
@@ -56,6 +59,8 @@ SUB_CPP_PREDEFINES
/* Define this so that all GNU/Linux targets handle the same pragmas. */
#define HANDLE_PRAGMA_PACK_PUSH_POP
+#define TARGET_HAS_F_SETLKW
+
/* Do code reading to identify a signal frame, and set the frame
state data appropriately. See unwind-dw2.c for the structs. */
diff --git a/contrib/gcc/config/alpha/netbsd.h b/contrib/gcc/config/alpha/netbsd.h
index 9a54c3a..e1da9cf 100644
--- a/contrib/gcc/config/alpha/netbsd.h
+++ b/contrib/gcc/config/alpha/netbsd.h
@@ -22,9 +22,16 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_FP | MASK_FPREGS | MASK_GAS)
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
- "-D__NetBSD__ -D__ELF__ -D_LP64 -Asystem=unix -Asystem=NetBSD"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ NETBSD_OS_CPP_BUILTINS_ELF(); \
+ NETBSD_OS_CPP_BUILTINS_LP64(); \
+ } while (0)
+
+
+/* NetBSD doesn't use the LANGUAGE* built-ins. */
+#undef SUBTARGET_LANGUAGE_CPP_BUILTINS
+#define SUBTARGET_LANGUAGE_CPP_BUILTINS() /* nothing */
/* Show that we need a GP when profiling. */
@@ -32,39 +39,28 @@ Boston, MA 02111-1307, USA. */
#define TARGET_PROFILING_NEEDS_GP 1
-/* Provide a CPP_SPEC appropriate for NetBSD/alpha. In addition to
- the standard NetBSD specs, we also handle Alpha FP mode indications. */
-
-#undef CPP_SPEC
-#define CPP_SPEC \
- "%{mieee:-D_IEEE_FP} \
- %{mieee-with-inexact:-D_IEEE_FP -D_IEEE_FP_INEXACT} \
- %(cpp_cpu) %(cpp_subtarget)"
+/* Provide a CPP_SUBTARGET_SPEC appropriate for NetBSD/alpha. We use
+ this to pull in CPP specs that all NetBSD configurations need. */
#undef CPP_SUBTARGET_SPEC
-#define CPP_SUBTARGET_SPEC \
- "%{posix:-D_POSIX_SOURCE}"
+#define CPP_SUBTARGET_SPEC NETBSD_CPP_SPEC
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "netbsd_link_spec", NETBSD_LINK_SPEC_ELF }, \
+ { "netbsd_entry_point", NETBSD_ENTRY_POINT }, \
+ { "netbsd_endfile_spec", NETBSD_ENDFILE_SPEC },
-/* Provide a LINK_SPEC appropriate for a NetBSD/alpha ELF target.
- This is a copy of LINK_SPEC from <netbsd-elf.h> tweaked for
- the alpha target. */
+/* Provide a LINK_SPEC appropriate for a NetBSD/alpha ELF target. */
#undef LINK_SPEC
-#define LINK_SPEC \
- "%{G*} %{relax:-relax} \
- %{O*:-O3} %{!O*:-O1} \
- %{assert*} %{R*} \
- %{shared:-shared} \
- %{!shared: \
- -dc -dp \
- %{!nostdlib: \
- %{!r*: \
- %{!e*:-e __start}}} \
- %{!static: \
- %{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /usr/libexec/ld.elf_so}} \
- %{static:-static}}"
+#define LINK_SPEC \
+ "%{G*} %{relax:-relax} \
+ %{O*:-O3} %{!O*:-O1} \
+ %(netbsd_link_spec)"
+
+#define NETBSD_ENTRY_POINT "__start"
/* Provide an ENDFILE_SPEC appropriate for NetBSD/alpha ELF. Here we
@@ -76,7 +72,12 @@ Boston, MA 02111-1307, USA. */
#undef ENDFILE_SPEC
#define ENDFILE_SPEC \
"%{ffast-math|funsafe-math-optimizations:crtfm%O%s} \
- %{!shared:crtend%O%s} %{shared:crtendS%O%s}"
+ %(netbsd_endfile_spec)"
+
+
+/* Attempt to enable execute permissions on the stack. */
+
+#define TRANSFER_FROM_TRAMPOLINE NETBSD_ENABLE_EXECUTE_STACK
#undef TARGET_VERSION
diff --git a/contrib/gcc/config/alpha/openbsd.h b/contrib/gcc/config/alpha/openbsd.h
index 3424112..b82b66d 100644
--- a/contrib/gcc/config/alpha/openbsd.h
+++ b/contrib/gcc/config/alpha/openbsd.h
@@ -21,8 +21,6 @@ Boston, MA 02111-1307, USA. */
/* We settle for little endian for now. */
#define TARGET_ENDIAN_DEFAULT 0
-#include <alpha/alpha.h>
-
#define OBSD_NO_DYNAMIC_LIBRARIES
#define OBSD_HAS_DECLARE_FUNCTION_NAME
#define OBSD_HAS_DECLARE_FUNCTION_SIZE
@@ -41,8 +39,13 @@ Boston, MA 02111-1307, USA. */
"%{!nostdlib:%{!r*:%{!e*:-e __start}}} -dc -dp %{assert*}"
/* run-time target specifications */
-#define CPP_PREDEFINES "-D__unix__ -D__ANSI_COMPAT -Asystem=unix \
--D__OpenBSD__ -D__alpha__ -D__alpha"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__OpenBSD__"); \
+ builtin_define ("__ANSI_COMPAT"); \
+ builtin_define ("__unix__"); \
+ builtin_assert ("system=unix"); \
+ } while (0)
/* Layout of source language data types. */
diff --git a/contrib/gcc/config/alpha/osf.h b/contrib/gcc/config/alpha/osf.h
index efb0a16..2be2a42 100644
--- a/contrib/gcc/config/alpha/osf.h
+++ b/contrib/gcc/config/alpha/osf.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for DEC Alpha on OSF/1.
- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2001
+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2001, 2002, 2003
Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
@@ -32,14 +32,24 @@ Boston, MA 02111-1307, USA. */
/* Names to predefine in the preprocessor for this target machine. */
-#define CPP_PREDEFINES "\
--Dunix -D__osf__ -D_LONGLONG -DSYSTYPE_BSD \
--D_SYSTYPE_BSD -Asystem=unix -Asystem=xpg4"
-
-/* Tru64 UNIX V5 requires additional definitions for 16 byte long double
- support. Empty by default. */
-
-#define CPP_XFLOAT_SPEC ""
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("SYSTYPE_BSD"); \
+ builtin_define ("_SYSTYPE_BSD"); \
+ builtin_define ("__osf__"); \
+ builtin_define ("__digital__"); \
+ builtin_define ("__arch64__"); \
+ builtin_define ("_LONGLONG"); \
+ builtin_define ("__PRAGMA_EXTERN_PREFIX"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=xpg4"); \
+ /* Tru64 UNIX V5 has a 16 byte long \
+ double type and requires __X_FLOAT \
+ to be defined for <math.h>. */ \
+ if (LONG_DOUBLE_TYPE_SIZE == 128) \
+ builtin_define ("__X_FLOAT"); \
+ } while (0)
/* Accept DEC C flags for multithreaded programs. We use _PTHREAD_USE_D4
instead of PTHREAD_USE_D4 since both have the same effect and the former
@@ -47,8 +57,7 @@ Boston, MA 02111-1307, USA. */
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC \
-"%{pthread|threads:-D_REENTRANT} %{threads:-D_PTHREAD_USE_D4} %(cpp_xfloat) \
--D__EXTERN_PREFIX"
+"%{pthread|threads:-D_REENTRANT} %{threads:-D_PTHREAD_USE_D4}"
/* Under OSF4, -p and -pg require -lprof1, and -lprof1 requires -lpdf. */
@@ -136,9 +145,7 @@ Boston, MA 02111-1307, USA. */
#endif
#undef SUBTARGET_EXTRA_SPECS
-#define SUBTARGET_EXTRA_SPECS \
- { "cpp_xfloat", CPP_XFLOAT_SPEC }, \
- { "asm_oldas", ASM_OLDAS_SPEC }
+#define SUBTARGET_EXTRA_SPECS { "asm_oldas", ASM_OLDAS_SPEC }
/* Indicate that we have a stamp.h to use. */
#ifndef CROSS_COMPILE
@@ -193,7 +200,7 @@ __enable_execute_stack (addr) \
#define ASM_OUTPUT_WEAK_ALIAS(FILE, NAME, VALUE) \
do \
{ \
- ASM_GLOBALIZE_LABEL (FILE, NAME); \
+ (*targetm.asm_out.globalize_label) (FILE, NAME); \
fputs ("\t.weakext\t", FILE); \
assemble_name (FILE, NAME); \
if (VALUE) \
@@ -208,7 +215,6 @@ __enable_execute_stack (addr) \
#define ASM_WEAKEN_LABEL(FILE, NAME) ASM_OUTPUT_WEAK_ALIAS(FILE, NAME, 0)
/* Handle #pragma weak and #pragma pack. */
-#undef HANDLE_SYSV_PRAGMA
#define HANDLE_SYSV_PRAGMA 1
/* Handle #pragma extern_prefix. Technically only needed for Tru64 5.x,
diff --git a/contrib/gcc/config/alpha/osf5.h b/contrib/gcc/config/alpha/osf5.h
index c832c57..e483124 100644
--- a/contrib/gcc/config/alpha/osf5.h
+++ b/contrib/gcc/config/alpha/osf5.h
@@ -18,15 +18,12 @@
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+/* Tru64 5.1 uses IEEE QUAD format. */
+/* ??? However, since there is no support for VAX H_floating, we must
+ drop back to a 64-bit long double to avoid a crash looking for the
+ format associated with TFmode. */
#undef LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE 128
-
-/* Tru64 UNIX V5 has a 16 byte long double type and requires __X_FLOAT to be
- defined to get the appropriate prototypes for the long double functions
- in <math.h>. */
-
-#undef CPP_XFLOAT_SPEC
-#define CPP_XFLOAT_SPEC "-D__X_FLOAT"
+#define LONG_DOUBLE_TYPE_SIZE (TARGET_FLOAT_VAX ? 64 : 128)
/* In Tru64 UNIX V5.1, Compaq introduced a new assembler
(/usr/lib/cmplrs/cc/adu) which currently (versions between 3.04.29 and
diff --git a/contrib/gcc/config/alpha/t-crtfm b/contrib/gcc/config/alpha/t-crtfm
index 7076b51..5ca8c3f 100644
--- a/contrib/gcc/config/alpha/t-crtfm
+++ b/contrib/gcc/config/alpha/t-crtfm
@@ -1,4 +1,5 @@
EXTRA_PARTS += crtfastmath.o
crtfastmath.o: $(srcdir)/config/alpha/crtfastmath.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -c -o crtfastmath.o $(srcdir)/config/alpha/crtfastmath.c
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -frandom-seed=gcc-crtfastmath -c \
+ -o crtfastmath.o $(srcdir)/config/alpha/crtfastmath.c
diff --git a/contrib/gcc/config/alpha/unicosmk.h b/contrib/gcc/config/alpha/unicosmk.h
index 6dbe1a3..8f7b53d 100644
--- a/contrib/gcc/config/alpha/unicosmk.h
+++ b/contrib/gcc/config/alpha/unicosmk.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler, for DEC Alpha on Cray
T3E running Unicos/Mk.
- Copyright (C) 2001
+ Copyright (C) 2001, 2002
Free Software Foundation, Inc.
Contributed by Roman Lechtchinsky (rl@cs.tu-berlin.de)
@@ -32,15 +32,18 @@ Boston, MA 02111-1307, USA. */
/* The following defines are necessary for the standard headers to work
correctly. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__unix=1 -D_UNICOS=205 -D_CRAY=1 -D_CRAYT3E=1 -D_CRAYMPP=1 -D_CRAYIEEE=1 -D_ADDR64=1 -D_LD64=1 -D__UNICOSMK__ -D__INT_MAX__=9223372036854775807 -D__SHRT_MAX__=2147483647"
-
-/* Disable software floating point emulation because it requires a 16-bit
- type which we do not have. */
-
-#ifndef __GNUC__
-#undef REAL_ARITHMETIC
-#endif
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__unix"); \
+ builtin_define ("_UNICOS=205"); \
+ builtin_define ("_CRAY"); \
+ builtin_define ("_CRAYT3E"); \
+ builtin_define ("_CRAYMPP"); \
+ builtin_define ("_CRAYIEEE"); \
+ builtin_define ("_ADDR64"); \
+ builtin_define ("_LD64"); \
+ builtin_define ("__UNICOSMK__"); \
+ } while (0)
#define SHORT_TYPE_SIZE 32
@@ -234,10 +237,7 @@ do { \
On Unicos/Mk, the standard subroutine __T3E_MISMATCH stores all register
arguments on the stack. Unfortunately, it doesn't always store the first
one (i.e. the one that arrives in $16 or $f16). This is not a problem
- with stdargs as we always have at least one named argument there. This is
- not always the case when varargs.h is used, however. In such cases, we
- have to store the first argument ourselves. We use the information from
- the CIW to determine whether the first argument arrives in $16 or $f16. */
+ with stdargs as we always have at least one named argument there. */
#undef SETUP_INCOMING_VARARGS
#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
@@ -245,36 +245,9 @@ do { \
{ \
if (! (NO_RTL)) \
{ \
- int start; \
- \
- start = (CUM).num_reg_words; \
- if (!current_function_varargs || start == 0) \
- ++start; \
+ int start = (CUM).num_reg_words + 1; \
\
emit_insn (gen_umk_mismatch_args (GEN_INT (start))); \
- if (current_function_varargs && (CUM).num_reg_words == 0) \
- { \
- rtx tmp; \
- rtx int_label, end_label; \
- \
- tmp = gen_reg_rtx (DImode); \
- emit_move_insn (tmp, \
- gen_rtx_ZERO_EXTRACT (DImode, \
- gen_rtx_REG (DImode, 2),\
- (GEN_INT (1)), \
- (GEN_INT (7)))); \
- int_label = gen_label_rtx (); \
- end_label = gen_label_rtx (); \
- emit_insn (gen_cmpdi (tmp, GEN_INT (0))); \
- emit_jump_insn (gen_beq (int_label)); \
- emit_move_insn (gen_rtx_MEM (DFmode, virtual_incoming_args_rtx),\
- gen_rtx_REG (DFmode, 48)); \
- emit_jump (end_label); \
- emit_label (int_label); \
- emit_move_insn (gen_rtx_MEM (DImode, virtual_incoming_args_rtx),\
- gen_rtx_REG (DImode, 16)); \
- emit_label (end_label); \
- } \
emit_insn (gen_arg_home_umk ()); \
} \
\
@@ -288,19 +261,6 @@ do { \
#undef EPILOGUE_USES
#define EPILOGUE_USES(REGNO) ((REGNO) == 26 || (REGNO) == 15)
-/* Machine-specific function data. */
-
-struct machine_function
-{
- /* List of call information words for calls from this function. */
- struct rtx_def *first_ciw;
- struct rtx_def *last_ciw;
- int ciw_count;
-
- /* List of deferred case vectors. */
- struct rtx_def *addr_list;
-};
-
/* Would have worked, only the stack doesn't seem to be executable
#undef TRAMPOLINE_TEMPLATE
#define TRAMPOLINE_TEMPLATE(FILE) \
@@ -342,9 +302,9 @@ do { fprintf (FILE, "\tbr $1,0\n"); \
#undef DATA_SECTION_ASM_OP
#define DATA_SECTION_ASM_OP unicosmk_data_section ()
-/* There are ni read-only sections on Unicos/Mk. */
+/* There are no read-only sections on Unicos/Mk. */
-#undef READONLY_DATA_SECTION
+#undef READONLY_DATA_SECTION_ASM_OP
#define READONLY_DATA_SECTION data_section
/* Define extra sections for common data and SSIBs (static subroutine
@@ -375,16 +335,6 @@ ssib_section () \
in_section = in_ssib; \
}
-/* A C expression which evaluates to true if declshould be placed into a
- unique section for some target-specific reason. On Unicos/Mk, functions
- and public variables are always placed in unique sections. */
-
-/*
-#define UNIQUE_SECTION_P(DECL) (TREE_PUBLIC (DECL) \
- || TREE_CODE (DECL) == FUNCTION_DECL)
-*/
-#define UNIQUE_SECTION(DECL, RELOC) unicosmk_unique_section (DECL, RELOC)
-
/* This outputs text to go at the start of an assembler file. */
#undef ASM_FILE_START
@@ -399,12 +349,6 @@ ssib_section () \
#undef ASM_OUTPUT_SOURCE_FILENAME
-/* There is no directive for declaring a label as global. Instead, an
- additional colon must be appended when the label is defined. */
-
-#undef ASM_GLOBALIZE_LABEL
-#define ASM_GLOBALIZE_LABEL(FILE,NAME)
-
/* This is how to output a label for a jump table. Arguments are the same as
for ASM_OUTPUT_INTERNAL_LABEL, except the insn for the jump table is
passed. */
@@ -568,38 +512,6 @@ ssib_section () \
#undef ASM_OUTPUT_MAX_SKIP_ALIGN
#define ASM_OUTPUT_MAX_SKIP_ALIGN(STREAM,POWER,MAXSKIP)
-/* We have to define these because we do not use the floating-point
- emulation. Unfortunately, atof does not accept hex literals. */
-
-#ifndef REAL_ARITHMETIC
-#define REAL_VALUE_ATOF(x,s) atof(x)
-#define REAL_VALUE_HTOF(x,s) atof(x)
-
-#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) \
-do { \
- union { \
- float f; \
- HOST_WIDE_INT l; \
- } u; \
- \
- u.f = (IN); \
- (OUT) = (u.l >> 32) & 0xFFFFFFFF; \
-} while (0)
-
-#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \
-do { \
- union { \
- REAL_VALUE_TYPE f; \
- HOST_WIDE_INT l; \
- } u; \
- \
- u.f = (IN); \
- (OUT)[0] = (u.l >> 32) & 0xFFFFFFFF; \
- (OUT)[1] = (u.l & 0xFFFFFFFF); \
-} while (0)
-
-#endif
-
#undef NM_FLAGS
#undef OBJECT_FORMAT_COFF
diff --git a/contrib/gcc/config/alpha/vms-cc.c b/contrib/gcc/config/alpha/vms-cc.c
index a171b1c..26c3ae3 100644
--- a/contrib/gcc/config/alpha/vms-cc.c
+++ b/contrib/gcc/config/alpha/vms-cc.c
@@ -109,16 +109,11 @@ preprocess_args (p_argc, argv)
if (strcmp (argv[i], "-o") == 0)
{
char *buff, *ptr;
- int out_len;
i++;
ptr = to_host_file_spec (argv[i]);
objfilename = xstrdup (ptr);
- out_len = strlen (ptr);
- buff = xmalloc (out_len + 6);
-
- strcpy (buff, "/obj=");
- strcat (buff, ptr);
+ buff = concat ("/obj=", ptr, NULL);
addarg (buff);
}
}
@@ -202,11 +197,8 @@ main (argc, argv)
strncpy (cwdev, cwd, devlen);
cwdev [devlen] = '\0';
- search_dirs = xmalloc (strlen (system_search_dirs) + 1);
- strcpy (search_dirs, system_search_dirs);
-
- defines = xmalloc (strlen (default_defines) + 1);
- strcpy (defines, default_defines);
+ search_dirs = xstrdup (system_search_dirs);
+ defines = xstrdup (default_defines);
addarg ("cc");
preprocess_args (&argc , argv);
@@ -251,7 +243,6 @@ main (argc, argv)
{
/* Assume filename arg */
char buff [256], *ptr;
- int buff_len;
ptr = to_host_file_spec (argv[i]);
arg_len = strlen (ptr);
@@ -263,10 +254,7 @@ main (argc, argv)
else
sprintf (buff, "%s%s", cwd, ptr);
- buff_len = strlen (buff);
- ptr = xmalloc (buff_len + 1);
-
- strcpy (ptr, buff);
+ ptr = xstrdup (buff);
addarg (ptr);
}
}
diff --git a/contrib/gcc/config/alpha/vms-crt0-64.c b/contrib/gcc/config/alpha/vms-crt0-64.c
index 4120a6b..82ba322 100644
--- a/contrib/gcc/config/alpha/vms-crt0-64.c
+++ b/contrib/gcc/config/alpha/vms-crt0-64.c
@@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */
You Lose! This file can only be compiled with DEC C.
#else
-/* This file can only be compiled with DEC C, due the the call to
+/* This file can only be compiled with DEC C, due to the call to
lib$establish and the pragmas pointer_size. */
#pragma __pointer_size short
diff --git a/contrib/gcc/config/alpha/vms-crt0.c b/contrib/gcc/config/alpha/vms-crt0.c
index e75bc02..b7665f9 100644
--- a/contrib/gcc/config/alpha/vms-crt0.c
+++ b/contrib/gcc/config/alpha/vms-crt0.c
@@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */
You Lose! This file can only be compiled with DEC C.
#else
-/* This file can only be compiled with DEC C, due the the call to
+/* This file can only be compiled with DEC C, due to the call to
lib$establish. */
#include <stdlib.h>
diff --git a/contrib/gcc/config/alpha/vms-ld.c b/contrib/gcc/config/alpha/vms-ld.c
index 83ceaf9..e5688d8 100644
--- a/contrib/gcc/config/alpha/vms-ld.c
+++ b/contrib/gcc/config/alpha/vms-ld.c
@@ -396,8 +396,7 @@ main (argc, argv)
strncpy (cwdev, cwd, devlen);
cwdev [devlen] = '\0';
- search_dirs = xmalloc (strlen (system_search_dirs) + 1);
- strcpy (search_dirs, system_search_dirs);
+ search_dirs = xstrdup (system_search_dirs);
addarg ("link");
diff --git a/contrib/gcc/config/alpha/vms-psxcrt0-64.c b/contrib/gcc/config/alpha/vms-psxcrt0-64.c
index be3e70d..b16e8b4 100644
--- a/contrib/gcc/config/alpha/vms-psxcrt0-64.c
+++ b/contrib/gcc/config/alpha/vms-psxcrt0-64.c
@@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */
You Lose! This file can only be compiled with DEC C.
#else
-/* This file can only be compiled with DEC C, due the the call to
+/* This file can only be compiled with DEC C, due to the call to
lib$establish and the pragmas pointer_size. */
#pragma __pointer_size short
diff --git a/contrib/gcc/config/alpha/vms-psxcrt0.c b/contrib/gcc/config/alpha/vms-psxcrt0.c
index cdf5ced..c4140b4 100644
--- a/contrib/gcc/config/alpha/vms-psxcrt0.c
+++ b/contrib/gcc/config/alpha/vms-psxcrt0.c
@@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */
You Lose! This file can only be compiled with DEC C.
#else
-/* This file can only be compiled with DEC C, due the the call to
+/* This file can only be compiled with DEC C, due to the call to
lib$establish. */
#include <stdlib.h>
diff --git a/contrib/gcc/config/alpha/vms.h b/contrib/gcc/config/alpha/vms.h
index ffc3275..8df6156 100644
--- a/contrib/gcc/config/alpha/vms.h
+++ b/contrib/gcc/config/alpha/vms.h
@@ -29,17 +29,17 @@ Boston, MA 02111-1307, USA. */
#define NO_EXTERNAL_INDIRECT_ADDRESS
-#include "alpha/alpha.h"
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
-"-D__ALPHA -Dvms -DVMS -D__vms__ -D__VMS__ -Asystem=vms"
-
-#undef CPP_SUBTARGET_SPEC
-#define CPP_SUBTARGET_SPEC "\
-%{mfloat-ieee:-D__IEEE_FLOAT} \
-%{mfloat-vax:-D__G_FLOAT} \
-%{!mfloat-vax:-D__IEEE_FLOAT}"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define_std ("vms"); \
+ builtin_define_std ("VMS"); \
+ builtin_define ("__ALPHA"); \
+ builtin_assert ("system=vms"); \
+ if (TARGET_FLOAT_VAX) \
+ builtin_define ("__G_FLOAT"); \
+ else \
+ builtin_define ("__IEEE_FLOAT"); \
+ } while (0)
/* By default, allow $ to be part of an identifier. */
#define DOLLARS_IN_IDENTIFIERS 2
@@ -261,26 +261,17 @@ typedef struct {int num_args; enum avms_arg_type atypes[6];} avms_arg_info;
}
#define LINK_SECTION_ASM_OP "\t.link"
-#define READONLY_SECTION_ASM_OP "\t.rdata"
+#define READONLY_DATA_SECTION_ASM_OP "\t.rdata"
#define LITERALS_SECTION_ASM_OP "\t.literals"
#define CTORS_SECTION_ASM_OP "\t.ctors"
#define DTORS_SECTION_ASM_OP "\t.dtors"
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_link, in_rdata, in_literals
+#define EXTRA_SECTIONS in_link, in_literals
#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
void \
-readonly_section () \
-{ \
- if (in_section != in_rdata) \
- { \
- fprintf (asm_out_file, "%s\n", READONLY_SECTION_ASM_OP); \
- in_section = in_rdata; \
- } \
-} \
-void \
link_section () \
{ \
if (in_section != in_link) \
@@ -299,7 +290,6 @@ literals_section () \
} \
}
-extern void readonly_section PARAMS ((void));
extern void link_section PARAMS ((void));
extern void literals_section PARAMS ((void));
@@ -310,11 +300,6 @@ extern void literals_section PARAMS ((void));
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
fprintf (FILE, "\t.quad $L%d\n", (VALUE))
-#undef READONLY_DATA_SECTION
-#define READONLY_DATA_SECTION readonly_section
-
-#define ASM_FILE_END(FILE) alpha_write_linkage (FILE);
-
#undef CASE_VECTOR_MODE
#define CASE_VECTOR_MODE DImode
#undef CASE_VECTOR_PC_RELATIVE
@@ -379,8 +364,8 @@ do { \
#undef MIPS_DEBUGGING_INFO
#undef DBX_DEBUGGING_INFO
-#define DWARF2_DEBUGGING_INFO
-#define VMS_DEBUGGING_INFO
+#define DWARF2_DEBUGGING_INFO 1
+#define VMS_DEBUGGING_INFO 1
#define DWARF2_UNWIND_INFO 1
@@ -469,7 +454,7 @@ do { \
sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO)))
/* ??? VMS uses different linkage. */
-#undef ASM_OUTPUT_MI_THUNK
+#undef TARGET_ASM_OUTPUT_MI_THUNK
#undef ASM_SPEC
#undef ASM_FINAL_SPEC
diff --git a/contrib/gcc/config/alpha/vxworks.h b/contrib/gcc/config/alpha/vxworks.h
index 2f711ce..a27c645 100644
--- a/contrib/gcc/config/alpha/vxworks.h
+++ b/contrib/gcc/config/alpha/vxworks.h
@@ -26,10 +26,14 @@ Boston, MA 02111-1307, USA. */
%{!mvxsim: %{!mcpu*|mcpu=21064:-DCPU=21064} %{mcpu=21164:-DCPU=21164}} \
%{posix: -D_POSIX_SOURCE}"
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "\
--D__vxworks -D__alpha_vxworks -Asystem=vxworks \
--Asystem=embedded -D_LONGLONG"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__vxworks"); \
+ builtin_define ("__alpha_vxworks"); \
+ builtin_define ("_LONGLONG"); \
+ builtin_assert ("system=vxworks"); \
+ builtin_assert ("system=embedded"); \
+ } while (0)
/* VxWorks does all the library stuff itself. */
diff --git a/contrib/gcc/config/arm/README-interworking b/contrib/gcc/config/arm/README-interworking
index 46b76c9..de8b278 100644
--- a/contrib/gcc/config/arm/README-interworking
+++ b/contrib/gcc/config/arm/README-interworking
@@ -235,7 +235,7 @@ processing is enabled.
When the -mthumb-interwork command line switch is specified, gcc
arranges for all functions to return to their caller by using the BX
instruction. Thus provided that the return address has the bottom bit
-correctly initialised to indicate the instruction set of the caller,
+correctly initialized to indicate the instruction set of the caller,
correct operation will ensue.
When a function is called explicitly (rather than via a function
diff --git a/contrib/gcc/config/arm/aof.h b/contrib/gcc/config/arm/aof.h
index f110ea2..965337c 100644
--- a/contrib/gcc/config/arm/aof.h
+++ b/contrib/gcc/config/arm/aof.h
@@ -54,8 +54,6 @@ Boston, MA 02111-1307, USA. */
addressing across such boundaries. */
#define TEXT_SECTION_ASM_OP aof_text_section ()
-#define SELECT_RTX_SECTION(MODE,RTX,ALIGN) text_section ();
-
#define DATA_SECTION_ASM_OP aof_data_section ()
#define EXTRA_SECTIONS in_zero_init, in_common
@@ -222,14 +220,8 @@ do \
extern int arm_main_function;
-#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
-do { \
- fprintf ((STREAM), "\tEXPORT\t"); \
- assemble_name ((STREAM), (NAME)); \
- fputc ('\n', (STREAM)); \
- if ((NAME)[0] == 'm' && ! strcmp ((NAME), "main")) \
- arm_main_function = 1; \
-} while (0)
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\tEXPORT\t"
#define ASM_OUTPUT_LABEL(STREAM,NAME) \
do { \
diff --git a/contrib/gcc/config/arm/aout.h b/contrib/gcc/config/arm/aout.h
index 868eee0..8f4a605 100644
--- a/contrib/gcc/config/arm/aout.h
+++ b/contrib/gcc/config/arm/aout.h
@@ -111,9 +111,7 @@ Boston, MA 02111-1307, USA. */
/* Generate DBX debugging information. riscix.h will undefine this because
the native assembler does not support stabs. */
-#ifndef DBX_DEBUGGING_INFO
-#define DBX_DEBUGGING_INFO 1
-#endif
+#define DBX_DEBUGGING_INFO 1
/* Acorn dbx moans about continuation chars, so don't use any. */
#ifndef DBX_CONTIN_LENGTH
@@ -144,27 +142,8 @@ Boston, MA 02111-1307, USA. */
while (0)
#endif
-#ifndef ASM_OUTPUT_LABEL
-#define ASM_OUTPUT_LABEL(STREAM, NAME) \
- do \
- { \
- assemble_name (STREAM,NAME); \
- fputs (":\n", STREAM); \
- } \
- while (0)
-#endif
-
-/* Output a globalising directive for a label. */
-#ifndef ASM_GLOBALIZE_LABEL
-#define ASM_GLOBALIZE_LABEL(STREAM, NAME) \
- do \
- { \
- fprintf (STREAM, "\t.global\t"); \
- assemble_name (STREAM, NAME); \
- fputc ('\n',STREAM); \
- } \
- while (0)
-#endif
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.global\t"
/* Make an internal label into a string. */
#ifndef ASM_GENERATE_INTERNAL_LABEL
diff --git a/contrib/gcc/config/arm/arm-modes.def b/contrib/gcc/config/arm/arm-modes.def
new file mode 100644
index 0000000..48f9ddf
--- /dev/null
+++ b/contrib/gcc/config/arm/arm-modes.def
@@ -0,0 +1,46 @@
+/* Definitions of target machine for GNU compiler, for ARM.
+ Copyright (C) 2002 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 (rearnsha@arm.com)
+ Minor hacks by Nick Clifton (nickc@cygnus.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* 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. */
+
+CC (CC_NOOV)
+CC (CC_Z)
+CC (CC_SWP)
+CC (CCFP)
+CC (CCFPE)
+CC (CC_DNE)
+CC (CC_DEQ)
+CC (CC_DLE)
+CC (CC_DLT)
+CC (CC_DGE)
+CC (CC_DGT)
+CC (CC_DLEU)
+CC (CC_DLTU)
+CC (CC_DGEU)
+CC (CC_DGTU)
+CC (CC_C)
diff --git a/contrib/gcc/config/arm/arm-protos.h b/contrib/gcc/config/arm/arm-protos.h
index b42da82..cae9bea 100644
--- a/contrib/gcc/config/arm/arm-protos.h
+++ b/contrib/gcc/config/arm/arm-protos.h
@@ -1,5 +1,5 @@
/* Prototypes for exported functions defined in arm.c and pe.c
- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rearnsha@arm.com)
Minor hacks by Nick Clifton (nickc@cygnus.com)
@@ -31,9 +31,11 @@ extern void arm_finalize_pic PARAMS ((int));
extern int arm_volatile_func PARAMS ((void));
extern const char * arm_output_epilogue PARAMS ((int));
extern void arm_expand_prologue PARAMS ((void));
+extern HOST_WIDE_INT arm_get_frame_size PARAMS ((void));
/* Used in arm.md, but defined in output.c. */
extern void assemble_align PARAMS ((int));
extern const char * arm_strip_name_encoding PARAMS ((const char *));
+extern void arm_asm_output_labelref PARAMS ((FILE *, const char *));
extern unsigned long arm_current_func_type PARAMS ((void));
extern unsigned int arm_compute_initial_elimination_offset PARAMS ((unsigned int, unsigned int));
@@ -43,7 +45,8 @@ extern void arm_encode_call_attribute PARAMS ((tree, int));
extern int arm_function_ok_for_sibcall PARAMS ((tree));
#endif
#ifdef RTX_CODE
-extern int arm_hard_regno_mode_ok PARAMS ((unsigned int, enum machine_mode));
+extern int arm_hard_regno_mode_ok PARAMS ((unsigned int,
+ enum machine_mode));
extern int const_ok_for_arm PARAMS ((HOST_WIDE_INT));
extern int arm_split_constant PARAMS ((RTX_CODE, enum machine_mode,
HOST_WIDE_INT, rtx, rtx, int));
@@ -106,6 +109,7 @@ extern int arm_gen_movstrqi PARAMS ((rtx *));
extern rtx arm_gen_rotated_half_load PARAMS ((rtx));
extern enum machine_mode arm_select_cc_mode PARAMS ((RTX_CODE, rtx, rtx));
extern rtx arm_gen_compare_reg PARAMS ((RTX_CODE, rtx, rtx));
+extern rtx arm_gen_return_addr_mask PARAMS ((void));
extern void arm_reload_in_hi PARAMS ((rtx *));
extern void arm_reload_out_hi PARAMS ((rtx *));
extern void arm_reorg PARAMS ((rtx));
@@ -121,7 +125,8 @@ extern const char * output_move_double PARAMS ((rtx *));
extern const char * output_mov_immediate PARAMS ((rtx *));
extern const char * output_add_immediate PARAMS ((rtx *));
extern const char * arithmetic_instr PARAMS ((rtx, int));
-extern void output_ascii_pseudo_op PARAMS ((FILE *, const unsigned char *, int));
+extern void output_ascii_pseudo_op PARAMS ((FILE *, const unsigned char *,
+ int));
extern const char * output_return_instruction PARAMS ((rtx, int, int));
extern void arm_poke_function_name PARAMS ((FILE *, const char *));
extern void arm_print_operand PARAMS ((FILE *, rtx, int));
@@ -136,6 +141,11 @@ extern rtx arm_function_arg PARAMS ((CUMULATIVE_ARGS *,
enum machine_mode, tree, int));
extern void arm_init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx,
int));
+extern rtx arm_va_arg PARAMS ((tree, tree));
+extern int arm_function_arg_pass_by_reference PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode,
+ tree, int));
+
#endif
#if defined AOF_ASSEMBLER
@@ -152,10 +162,13 @@ extern void common_section PARAMS ((void));
#endif /* RTX_CODE */
+extern int arm_float_words_big_endian PARAMS ((void));
+
/* Thumb functions. */
extern void arm_init_expanders PARAMS ((void));
extern int thumb_far_jump_used_p PARAMS ((int));
extern const char * thumb_unexpanded_epilogue PARAMS ((void));
+extern HOST_WIDE_INT thumb_get_frame_size PARAMS ((void));
extern void thumb_expand_prologue PARAMS ((void));
extern void thumb_expand_epilogue PARAMS ((void));
#ifdef TREE_CODE
@@ -185,7 +198,7 @@ extern int arm_dllimport_name_p PARAMS ((const char *));
#ifdef TREE_CODE
extern void arm_pe_unique_section PARAMS ((tree, int));
-extern void arm_pe_encode_section_info PARAMS ((tree));
+extern void arm_pe_encode_section_info PARAMS ((tree, int));
extern int arm_dllexport_p PARAMS ((tree));
extern int arm_dllimport_p PARAMS ((tree));
extern void arm_mark_dllexport PARAMS ((tree));
diff --git a/contrib/gcc/config/arm/arm.c b/contrib/gcc/config/arm/arm.c
index 8c696c6..7422f1d 100644
--- a/contrib/gcc/config/arm/arm.c
+++ b/contrib/gcc/config/arm/arm.c
@@ -65,9 +65,8 @@ const struct attribute_spec arm_attribute_table[];
/* Forward function declarations. */
static void arm_add_gc_roots PARAMS ((void));
static int arm_gen_constant PARAMS ((enum rtx_code, Mmode, Hint, rtx, rtx, int, int));
-static Ulong bit_count PARAMS ((signed int));
+static unsigned bit_count PARAMS ((Ulong));
static int const_ok_for_op PARAMS ((Hint, enum rtx_code));
-static int eliminate_lr2ip PARAMS ((rtx *));
static rtx emit_multi_reg_push PARAMS ((int));
static rtx emit_sfm PARAMS ((int, int));
#ifndef AOF_ASSEMBLER
@@ -82,9 +81,7 @@ static Ccstar output_multi_immediate PARAMS ((rtx *, Ccstar, Ccstar, int, Hi
static void print_multi_reg PARAMS ((FILE *, Ccstar, int, int));
static Mmode select_dominance_cc_mode PARAMS ((rtx, rtx, Hint));
static Ccstar shift_op PARAMS ((rtx, Hint *));
-static void arm_init_machine_status PARAMS ((struct function *));
-static void arm_mark_machine_status PARAMS ((struct function *));
-static void arm_free_machine_status PARAMS ((struct function *));
+static struct machine_function * arm_init_machine_status PARAMS ((void));
static int number_of_first_bit_set PARAMS ((int));
static void replace_symbols_in_block PARAMS ((tree, rtx, rtx));
static void thumb_exit PARAMS ((FILE *, int, rtx));
@@ -117,9 +114,20 @@ static void thumb_output_function_prologue PARAMS ((FILE *, Hint));
static int arm_comp_type_attributes PARAMS ((tree, tree));
static void arm_set_default_type_attributes PARAMS ((tree));
static int arm_adjust_cost PARAMS ((rtx, rtx, rtx, int));
+static int count_insns_for_constant PARAMS ((HOST_WIDE_INT, int));
+static int arm_get_strip_length PARAMS ((int));
#ifdef OBJECT_FORMAT_ELF
static void arm_elf_asm_named_section PARAMS ((const char *, unsigned int));
#endif
+#ifndef ARM_PE
+static void arm_encode_section_info PARAMS ((tree, int));
+#endif
+#ifdef AOF_ASSEMBLER
+static void aof_globalize_label PARAMS ((FILE *, const char *));
+#endif
+static void arm_output_mi_thunk PARAMS ((FILE *, tree,
+ HOST_WIDE_INT,
+ HOST_WIDE_INT, tree));
#undef Hint
#undef Mmode
@@ -142,6 +150,8 @@ static void arm_elf_asm_named_section PARAMS ((const char *, unsigned int));
#define TARGET_ASM_ALIGNED_HI_OP "\tDCW\t"
#undef TARGET_ASM_ALIGNED_SI_OP
#define TARGET_ASM_ALIGNED_SI_OP "\tDCD\t"
+#undef TARGET_ASM_GLOBALIZE_LABEL
+#define TARGET_ASM_GLOBALIZE_LABEL aof_globalize_label
#else
#undef TARGET_ASM_ALIGNED_SI_OP
#define TARGET_ASM_ALIGNED_SI_OP NULL
@@ -170,15 +180,27 @@ static void arm_elf_asm_named_section PARAMS ((const char *, unsigned int));
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST arm_adjust_cost
+#undef TARGET_ENCODE_SECTION_INFO
+#ifdef ARM_PE
+#define TARGET_ENCODE_SECTION_INFO arm_pe_encode_section_info
+#else
+#define TARGET_ENCODE_SECTION_INFO arm_encode_section_info
+#endif
+
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING arm_strip_name_encoding
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK arm_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Obstack for minipool constant handling. */
static struct obstack minipool_obstack;
static char * minipool_startobj;
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
/* The maximum number of insns skipped which
will be conditionalised if possible. */
static int max_insns_skipped = 5;
@@ -223,13 +245,13 @@ int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
/* The bits in this mask specify which
instructions we are allowed to generate. */
-static int insn_flags = 0;
+static unsigned long insn_flags = 0;
/* The bits in this mask specify which instruction scheduling options should
be used. Note - there is an overlap with the FL_FAST_MULT. For some
hardware we want to be able to generate the multiply instructions, but to
tune as if they were not present in the architecture. */
-static int tune_flags = 0;
+static unsigned long tune_flags = 0;
/* The following are used in the arm.md file as equivalents to bits
in the above two flag variables. */
@@ -301,7 +323,7 @@ static const char * const arm_condition_codes[] =
struct processors
{
const char *const name;
- const unsigned int flags;
+ const unsigned long flags;
};
/* Not all of these give usefully different compilation alternatives,
@@ -355,7 +377,7 @@ static const struct processors all_cores[] =
{"arm10tdmi", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_ARCH5 },
{"arm1020t", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_ARCH5 },
{"xscale", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_STRONG | FL_ARCH5 | FL_ARCH5E | FL_XSCALE },
-
+
{NULL, 0}
};
@@ -389,17 +411,17 @@ struct arm_cpu_select arm_select[] =
{ NULL, "-mtune=", all_cores }
};
-/* Return the number of bits set in value' */
-static unsigned long
+/* Return the number of bits set in VALUE. */
+static unsigned
bit_count (value)
- signed int value;
+ unsigned long value;
{
unsigned long count = 0;
while (value)
{
- value &= ~(value & -value);
- ++count;
+ count++;
+ value &= value - 1; /* Clear the least-significant set bit. */
}
return count;
@@ -526,7 +548,7 @@ arm_override_options ()
if (sel->name == NULL)
{
- unsigned int current_bit_count = 0;
+ unsigned current_bit_count = 0;
const struct processors * best_fit = NULL;
/* Ideally we would like to issue an error message here
@@ -545,7 +567,7 @@ arm_override_options ()
for (sel = all_cores; sel->name != NULL; sel++)
if ((sel->flags & sought) == sought)
{
- unsigned int count;
+ unsigned count;
count = bit_count (sel->flags & insn_flags);
@@ -570,7 +592,7 @@ arm_override_options ()
architecture has been selected. */
if (tune_flags == 0)
tune_flags = insn_flags;
-
+
/* Make sure that the processor choice does not conflict with any of the
other command line choices. */
if (TARGET_APCS_32 && !(insn_flags & FL_MODE32))
@@ -657,7 +679,7 @@ arm_override_options ()
if (TARGET_APCS_FLOAT)
warning ("passing floating point arguments in fp regs not yet supported");
- /* Initialise boolean versions of the flags, for use in the arm.md file. */
+ /* Initialize boolean versions of the flags, for use in the arm.md file. */
arm_fast_multiply = (insn_flags & FL_FAST_MULT) != 0;
arm_arch4 = (insn_flags & FL_ARCH4) != 0;
arm_arch5 = (insn_flags & FL_ARCH5) != 0;
@@ -714,7 +736,7 @@ arm_override_options ()
if (arm_pic_register_string != NULL)
{
int pic_register = decode_reg_name (arm_pic_register_string);
-
+
if (!flag_pic)
warning ("-mpic-register= is useless without -fpic");
@@ -759,10 +781,6 @@ arm_override_options ()
static void
arm_add_gc_roots ()
{
- ggc_add_rtx_root (&arm_compare_op0, 1);
- ggc_add_rtx_root (&arm_compare_op1, 1);
- ggc_add_rtx_root (&arm_target_insn, 1); /* Not sure this is really a root. */
-
gcc_obstack_init(&minipool_obstack);
minipool_startobj = (char *) obstack_alloc (&minipool_obstack, 0);
}
@@ -820,7 +838,7 @@ arm_isr_value (argument)
if (streq (arg, ptr->arg))
return ptr->return_value;
- /* An unrecognised interrupt type. */
+ /* An unrecognized interrupt type. */
return ARM_FT_UNKNOWN;
}
@@ -902,6 +920,10 @@ use_return_insn (iscond)
consideration. */
if (func_type & (ARM_FT_VOLATILE | ARM_FT_NAKED))
return 0;
+
+ /* So do interrupt functions that use the frame pointer. */
+ if (IS_INTERRUPT (func_type) && frame_pointer_needed)
+ return 0;
/* As do variadic functions. */
if (current_function_pretend_args_size
@@ -909,7 +931,7 @@ use_return_insn (iscond)
/* Of if the function calls __builtin_eh_return () */
|| ARM_FUNC_TYPE (func_type) == ARM_FT_EXCEPTION_HANDLER
/* Or if there is no frame pointer and there is a stack adjustment. */
- || ((get_frame_size () + current_function_outgoing_args_size != 0)
+ || ((arm_get_frame_size () + current_function_outgoing_args_size != 0)
&& !frame_pointer_needed))
return 0;
@@ -1032,7 +1054,7 @@ arm_split_constant (code, mode, val, target, source, subtargets)
&& REGNO (target) != REGNO (source)))
{
/* After arm_reorg has been called, we can't fix up expensive
- constants by pushing them into memory so we must synthesise
+ constants by pushing them into memory so we must synthesize
them in-line, regardless of the cost. This is only likely to
be more costly on chips that have load delay slots and we are
compiling without running the scheduler (so no splitting
@@ -1073,7 +1095,9 @@ arm_split_constant (code, mode, val, target, source, subtargets)
}
static int
-count_insns_for_constant (HOST_WIDE_INT remainder, int i)
+count_insns_for_constant (remainder, i)
+ HOST_WIDE_INT remainder;
+ int i;
{
HOST_WIDE_INT temp1;
int num_insns = 0;
@@ -1752,9 +1776,20 @@ int
arm_return_in_memory (type)
tree type;
{
+ HOST_WIDE_INT size;
+
if (!AGGREGATE_TYPE_P (type))
/* All simple types are returned in registers. */
return 0;
+
+ size = int_size_in_bytes (type);
+
+ if (TARGET_ATPCS)
+ {
+ /* ATPCS returns aggregate types in memory only if they are
+ larger than a word (or are variable size). */
+ return (size < 0 || size > UNITS_PER_WORD);
+ }
/* For the arm-wince targets we choose to be compitable with Microsoft's
ARM and Thumb compilers, which always return aggregates in memory. */
@@ -1763,7 +1798,7 @@ arm_return_in_memory (type)
Also catch the case where int_size_in_bytes returns -1. In this case
the aggregate is either huge or of varaible size, and in either case
we will want to return it via memory and not in a register. */
- if (((unsigned int) int_size_in_bytes (type)) > UNITS_PER_WORD)
+ if (size < 0 || size > UNITS_PER_WORD)
return 1;
if (TREE_CODE (type) == RECORD_TYPE)
@@ -1841,6 +1876,27 @@ arm_return_in_memory (type)
return 1;
}
+/* Indicate whether or not words of a double are in big-endian order. */
+
+int
+arm_float_words_big_endian ()
+{
+
+ /* For FPA, float words are always big-endian. For VFP, floats words
+ follow the memory system mode. */
+
+ if (TARGET_HARD_FLOAT)
+ {
+ /* FIXME: TARGET_HARD_FLOAT currently implies FPA. */
+ return 1;
+ }
+
+ if (TARGET_VFP)
+ return (TARGET_BIG_END ? 1 : 0);
+
+ return 1;
+}
+
/* 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 NULL. */
@@ -1899,6 +1955,35 @@ arm_function_arg (pcum, mode, type, named)
return gen_rtx_REG (mode, pcum->nregs);
}
+
+/* Variable sized types are passed by reference. This is a GCC
+ extension to the ARM ABI. */
+
+int
+arm_function_arg_pass_by_reference (cum, mode, type, named)
+ CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ tree type;
+ int named ATTRIBUTE_UNUSED;
+{
+ return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
+}
+
+/* Implement va_arg. */
+
+rtx
+arm_va_arg (valist, type)
+ tree valist, type;
+{
+ /* Variable sized types are passed by reference. */
+ if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+ {
+ rtx addr = std_expand_builtin_va_arg (valist, build_pointer_type (type));
+ return gen_rtx_MEM (ptr_mode, force_reg (Pmode, addr));
+ }
+
+ return std_expand_builtin_va_arg (valist, type);
+}
/* Encode the current state of the #pragma [no_]long_calls. */
typedef enum
@@ -2171,7 +2256,7 @@ current_file_function_operand (sym_ref)
return 0;
}
-/* Return non-zero if a 32 bit "long_call" should be generated for
+/* Return nonzero if a 32 bit "long_call" should be generated for
this call. We generate a long_call if the function:
a. has an __attribute__((long call))
@@ -2224,7 +2309,7 @@ arm_is_longcall_p (sym_ref, call_cookie, call_symbol)
|| TARGET_LONG_CALLS;
}
-/* Return non-zero if it is ok to make a tail-call to DECL. */
+/* Return nonzero if it is ok to make a tail-call to DECL. */
int
arm_function_ok_for_sibcall (decl)
@@ -2442,7 +2527,7 @@ arm_finalize_pic (prologue)
emit_insn (gen_pic_add_dot_plus_four (pic_offset_table_rtx, l1));
}
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
if (prologue)
emit_insn_after (seq, get_insns ());
@@ -2558,7 +2643,8 @@ arm_rtx_costs (x, code, outer)
/* Memory costs quite a lot for the first word, but subsequent words
load at the equivalent of a single insn each. */
return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD)
- + (CONSTANT_POOL_ADDRESS_P (x) ? 4 : 0));
+ + ((GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
+ ? 4 : 0));
case IF_THEN_ELSE:
/* XXX a guess. */
@@ -2606,7 +2692,8 @@ arm_rtx_costs (x, code, outer)
/* Memory costs quite a lot for the first word, but subsequent words
load at the equivalent of a single insn each. */
return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD)
- + (CONSTANT_POOL_ADDRESS_P (x) ? 4 : 0));
+ + (GET_CODE (x) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (x) ? 4 : 0));
case DIV:
case MOD:
@@ -2914,16 +3001,16 @@ arm_adjust_cost (insn, link, dep, cost)
&& (d_pat = single_set (dep)) != NULL
&& GET_CODE (SET_DEST (d_pat)) == MEM)
{
+ rtx src_mem = XEXP (SET_SRC (i_pat), 0);
/* 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. */
- 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)))
+ if ((GET_CODE (src_mem) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (src_mem))
+ || reg_mentioned_p (stack_pointer_rtx, src_mem)
+ || reg_mentioned_p (frame_pointer_rtx, src_mem)
+ || reg_mentioned_p (hard_frame_pointer_rtx, src_mem))
return 1;
}
@@ -4319,7 +4406,7 @@ arm_gen_load_multiple (base_regno, count, from, up, write_back, unchanging_p,
if (write_back)
emit_move_insn (from, plus_constant (from, count * 4 * sign));
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
return seq;
@@ -4386,7 +4473,7 @@ arm_gen_store_multiple (base_regno, count, to, up, write_back, unchanging_p,
if (write_back)
emit_move_insn (to, plus_constant (to, count * 4 * sign));
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
return seq;
@@ -4449,7 +4536,7 @@ arm_gen_movstrqi (operands)
fin_dst = dst = copy_to_mode_reg (SImode, st_dst);
fin_src = src = copy_to_mode_reg (SImode, st_src);
- in_words_to_go = NUM_INTS (INTVAL (operands[2]));
+ in_words_to_go = ARM_NUM_INTS (INTVAL (operands[2]));
out_words_to_go = INTVAL (operands[2]) / 4;
last_bytes = INTVAL (operands[2]) & 3;
@@ -4876,6 +4963,19 @@ arm_gen_compare_reg (code, x, y)
return cc_reg;
}
+/* Generate a sequence of insns that will generate the correct return
+ address mask depending on the physical architecture that the program
+ is running on. */
+
+rtx
+arm_gen_return_addr_mask ()
+{
+ rtx reg = gen_reg_rtx (Pmode);
+
+ emit_insn (gen_return_addr_mask (reg));
+ return reg;
+}
+
void
arm_reload_in_hi (operands)
rtx * operands;
@@ -4956,7 +5056,14 @@ arm_reload_in_hi (operands)
}
}
- scratch = gen_rtx_REG (SImode, REGNO (operands[2]));
+ /* Operands[2] may overlap operands[0] (though it won't overlap
+ operands[1]), that's why we asked for a DImode reg -- so we can
+ use the bit that does not overlap. */
+ if (REGNO (operands[2]) == REGNO (operands[0]))
+ scratch = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
+ else
+ scratch = gen_rtx_REG (SImode, REGNO (operands[2]));
+
emit_insn (gen_zero_extendqisi2 (scratch,
gen_rtx_MEM (QImode,
plus_constant (base,
@@ -5349,7 +5456,7 @@ get_jump_table_size (insn)
/* ADDR_VECs only take room if read-only data does into the text
section. */
if (JUMP_TABLES_IN_TEXT_SECTION
-#if !defined(READONLY_DATA_SECTION)
+#if !defined(READONLY_DATA_SECTION) && !defined(READONLY_DATA_SECTION_ASM_OP)
|| 1
#endif
)
@@ -6322,57 +6429,27 @@ output_call (operands)
return "";
}
-static int
-eliminate_lr2ip (x)
- rtx * x;
-{
- int something_changed = 0;
- rtx x0 = * x;
- int code = GET_CODE (x0);
- int i, j;
- const char * fmt;
-
- switch (code)
- {
- case REG:
- if (REGNO (x0) == LR_REGNUM)
- {
- *x = gen_rtx_REG (SImode, IP_REGNUM);
- return 1;
- }
- return 0;
- default:
- /* Scan through the sub-elements and change any references there. */
- fmt = GET_RTX_FORMAT (code);
-
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- if (fmt[i] == 'e')
- something_changed |= eliminate_lr2ip (&XEXP (x0, i));
- else if (fmt[i] == 'E')
- for (j = 0; j < XVECLEN (x0, i); j++)
- something_changed |= eliminate_lr2ip (&XVECEXP (x0, i, j));
-
- return something_changed;
- }
-}
-
/* Output a 'call' insn that is a reference in memory. */
const char *
output_call_mem (operands)
rtx * operands;
{
- operands[0] = copy_rtx (operands[0]); /* Be ultra careful. */
- /* Handle calls using lr by using ip (which may be clobbered in subr anyway). */
- if (eliminate_lr2ip (&operands[0]))
- output_asm_insn ("mov%?\t%|ip, %|lr", operands);
-
if (TARGET_INTERWORK)
{
output_asm_insn ("ldr%?\t%|ip, %0", operands);
output_asm_insn ("mov%?\t%|lr, %|pc", operands);
output_asm_insn ("bx%?\t%|ip", operands);
}
+ else if (regno_use_in (LR_REGNUM, operands[0]))
+ {
+ /* LR is used in the memory address. We load the address in the
+ first instruction. It's safe to use IP as the target of the
+ load since the call will kill it anyway. */
+ output_asm_insn ("ldr%?\t%|ip, %0", operands);
+ output_asm_insn ("mov%?\t%|lr, %|pc", operands);
+ output_asm_insn ("mov%?\t%|pc, %|ip", operands);
+ }
else
{
output_asm_insn ("mov%?\t%|lr, %|pc", operands);
@@ -6543,11 +6620,11 @@ output_move_double (operands)
{
if (GET_MODE (operands[1]) == DFmode)
{
+ REAL_VALUE_TYPE r;
long l[2];
- union real_extract u;
- memcpy (&u, &CONST_DOUBLE_LOW (operands[1]), sizeof (u));
- REAL_VALUE_TO_TARGET_DOUBLE (u.d, l);
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+ REAL_VALUE_TO_TARGET_DOUBLE (r, l);
otherops[1] = GEN_INT (l[1]);
operands[1] = GEN_INT (l[0]);
}
@@ -6666,7 +6743,7 @@ output_move_double (operands)
}
else
{
- otherops[1] = adjust_address (operands[1], VOIDmode, 4);
+ otherops[1] = adjust_address (operands[1], SImode, 4);
/* Take care of overlapping base/data reg. */
if (reg_mentioned_p (operands[0], operands[1]))
{
@@ -6732,7 +6809,7 @@ output_move_double (operands)
/* Fall through */
default:
- otherops[0] = adjust_address (operands[0], VOIDmode, 4);
+ otherops[0] = adjust_address (operands[0], SImode, 4);
otherops[1] = gen_rtx_REG (SImode, 1 + REGNO (operands[1]));
output_asm_insn ("str%?\t%1, %0", operands);
output_asm_insn ("str%?\t%1, %0", otherops);
@@ -7190,7 +7267,7 @@ output_return_instruction (operand, really_return, reverse)
int reg;
unsigned long live_regs_mask;
unsigned long func_type;
-
+
func_type = arm_current_func_type ();
if (IS_NAKED (func_type))
@@ -7218,7 +7295,6 @@ output_return_instruction (operand, really_return, reverse)
if (current_function_calls_alloca && !really_return)
abort ();
- /* Construct the conditional part of the instruction(s) to be emitted. */
sprintf (conditional, "%%?%%%c0", reverse ? 'D' : 'd');
return_used_this_function = 1;
@@ -7275,6 +7351,8 @@ output_return_instruction (operand, really_return, reverse)
/* Generate the load multiple instruction to restore the registers. */
if (frame_pointer_needed)
sprintf (instr, "ldm%sea\t%%|fp, {", conditional);
+ else if (live_regs_mask & (1 << SP_REGNUM))
+ sprintf (instr, "ldm%sfd\t%%|sp, {", conditional);
else
sprintf (instr, "ldm%sfd\t%%|sp!, {", conditional);
@@ -7332,7 +7410,7 @@ output_return_instruction (operand, really_return, reverse)
really_return = 0;
}
}
-
+
if (really_return)
{
switch ((int) ARM_FUNC_TYPE (func_type))
@@ -7495,7 +7573,7 @@ arm_output_epilogue (really_return)
frame that is $fp + 4 for a non-variadic function. */
int floats_offset = 0;
rtx operands[3];
- int frame_size = get_frame_size ();
+ int frame_size = arm_get_frame_size ();
FILE * f = asm_out_file;
rtx eh_ofs = cfun->machine->eh_epilogue_sp_ofs;
@@ -7612,7 +7690,7 @@ arm_output_epilogue (really_return)
if (IS_INTERRUPT (func_type))
/* Interrupt handlers will have pushed the
IP onto the stack, so restore it now. */
- print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, 1 << IP_REGNUM);
+ print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, 1 << IP_REGNUM);
}
else
{
@@ -7686,7 +7764,16 @@ arm_output_epilogue (really_return)
asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
}
else if (saved_regs_mask)
- print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
+ {
+ if (saved_regs_mask & (1 << SP_REGNUM))
+ /* Note - write back to the stack register is not enabled
+ (ie "ldmfd sp!..."). We know that the stack pointer is
+ in the list of registers and if we add writeback the
+ instruction becomes UNPREDICTABLE. */
+ print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
+ else
+ print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
+ }
if (current_function_pretend_args_size)
{
@@ -7734,7 +7821,7 @@ arm_output_epilogue (really_return)
default:
if (frame_pointer_needed)
- /* If we used the frame pointer then the return adddress
+ /* If we used the frame pointer then the return address
will have been loaded off the stack directly into the
PC, so there is no need to issue a MOV instruction
here. */
@@ -7768,6 +7855,9 @@ arm_output_function_epilogue (file, frame_size)
}
else
{
+ /* We need to take into account any stack-frame rounding. */
+ frame_size = arm_get_frame_size ();
+
if (use_return_insn (FALSE)
&& return_used_this_function
&& (frame_size + current_function_outgoing_args_size) != 0
@@ -7809,7 +7899,7 @@ emit_multi_reg_push (mask)
num_dwarf_regs--;
/* For the body of the insn we are going to generate an UNSPEC in
- parallel with several USEs. This allows the insn to be recognised
+ parallel with several USEs. This allows the insn to be recognized
by the push_multi pattern in the arm.md file. The insn looks
something like this:
@@ -7842,7 +7932,6 @@ emit_multi_reg_push (mask)
par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs));
dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_dwarf_regs + 1));
- RTX_FRAME_RELATED_P (dwarf) = 1;
dwarf_par_index = 1;
for (i = 0; i <= LAST_ARM_REGNUM; i++)
@@ -7924,7 +8013,6 @@ emit_sfm (base_reg, count)
par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
dwarf = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
- RTX_FRAME_RELATED_P (dwarf) = 1;
reg = gen_rtx_REG (XFmode, base_reg++);
@@ -7996,11 +8084,11 @@ emit_sfm (base_reg, count)
current stack pointer -> | | /
--
- For a given funciton some or all of these stack compomnents
+ For a given function some or all of these stack components
may not be needed, giving rise to the possibility of
eliminating some of the registers.
- The values returned by this function must reflect the behaviour
+ The values returned by this function must reflect the behavior
of arm_expand_prologue() and arm_compute_save_reg_mask().
The sign of the number returned reflects the direction of stack
@@ -8012,7 +8100,7 @@ arm_compute_initial_elimination_offset (from, to)
unsigned int from;
unsigned int to;
{
- unsigned int local_vars = (get_frame_size () + 3) & ~3;
+ unsigned int local_vars = arm_get_frame_size ();
unsigned int outgoing_args = current_function_outgoing_args_size;
unsigned int stack_frame;
unsigned int call_saved_registers;
@@ -8041,10 +8129,14 @@ arm_compute_initial_elimination_offset (from, to)
reg_mask = reg_mask & ~ (reg_mask & - reg_mask);
}
- if (regs_ever_live[LR_REGNUM]
- /* If a stack frame is going to be created, the LR will
- be saved as part of that, so we do not need to allow
- for it here. */
+ if ((regs_ever_live[LR_REGNUM]
+ /* If optimizing for size, then we save the link register if
+ any other integer register is saved. This gives a smaller
+ return sequence. */
+ || (optimize_size && call_saved_registers > 0))
+ /* But if a stack frame is going to be created, the LR will
+ be saved as part of that, so we do not need to allow for
+ it here. */
&& ! frame_pointer_needed)
call_saved_registers += 4;
@@ -8133,6 +8225,79 @@ arm_compute_initial_elimination_offset (from, to)
}
}
+/* Calculate the size of the stack frame, taking into account any
+ padding that is required to ensure stack-alignment. */
+
+HOST_WIDE_INT
+arm_get_frame_size ()
+{
+ int regno;
+
+ int base_size = ROUND_UP (get_frame_size ());
+ int entry_size = 0;
+ unsigned long func_type = arm_current_func_type ();
+ int leaf;
+
+ if (! TARGET_ARM)
+ abort();
+
+ if (! TARGET_ATPCS)
+ return base_size;
+
+ /* We need to know if we are a leaf function. Unfortunately, it
+ is possible to be called after start_sequence has been called,
+ which causes get_insns to return the insns for the sequence,
+ not the function, which will cause leaf_function_p to return
+ the incorrect result.
+
+ To work around this, we cache the computed frame size. This
+ works because we will only be calling RTL expanders that need
+ to know about leaf functions once reload has completed, and the
+ frame size cannot be changed after that time, so we can safely
+ use the cached value. */
+
+ if (reload_completed)
+ return cfun->machine->frame_size;
+
+ leaf = leaf_function_p ();
+
+ /* A leaf function does not need any stack alignment if it has nothing
+ on the stack. */
+ if (leaf && base_size == 0)
+ {
+ cfun->machine->frame_size = 0;
+ return 0;
+ }
+
+ /* We know that SP will be word aligned on entry, and we must
+ preserve that condition at any subroutine call. But those are
+ the only constraints. */
+
+ /* Space for variadic functions. */
+ if (current_function_pretend_args_size)
+ entry_size += current_function_pretend_args_size;
+
+ /* Space for saved registers. */
+ entry_size += bit_count (arm_compute_save_reg_mask ()) * 4;
+
+ /* Space for saved FPA registers. */
+ if (! IS_VOLATILE (func_type))
+ {
+ for (regno = FIRST_ARM_FP_REGNUM; regno <= LAST_ARM_FP_REGNUM; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ entry_size += 12;
+ }
+
+ if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
+ base_size += 4;
+ if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
+ abort ();
+
+ cfun->machine->frame_size = base_size;
+
+ return base_size;
+}
+
/* Generate the prologue instructions for entry into an ARM function. */
void
@@ -8275,18 +8440,19 @@ arm_expand_prologue ()
RTX_FRAME_RELATED_P (insn) = 1;
}
- /* If this is an interrupt service routine, and the link register is
- going to be pushed, subtracting four now will mean that the
- function return can be done with a single instruction. */
+ /* If this is an interrupt service routine, and the link register
+ is going to be pushed, and we are not creating a stack frame,
+ (which would involve an extra push of IP and a pop in the epilogue)
+ subtracting four from LR now will mean that the function return
+ can be done with a single instruction. */
if ((func_type == ARM_FT_ISR || func_type == ARM_FT_FIQ)
- && (live_regs_mask & (1 << LR_REGNUM)) != 0)
- {
- emit_insn (gen_rtx_SET (SImode,
- gen_rtx_REG (SImode, LR_REGNUM),
- gen_rtx_PLUS (SImode,
- gen_rtx_REG (SImode, LR_REGNUM),
- GEN_INT (-4))));
- }
+ && (live_regs_mask & (1 << LR_REGNUM)) != 0
+ && ! frame_pointer_needed)
+ emit_insn (gen_rtx_SET (SImode,
+ gen_rtx_REG (SImode, LR_REGNUM),
+ gen_rtx_PLUS (SImode,
+ gen_rtx_REG (SImode, LR_REGNUM),
+ GEN_INT (-4))));
if (live_regs_mask)
{
@@ -8368,7 +8534,7 @@ arm_expand_prologue ()
}
}
- amount = GEN_INT (-(get_frame_size ()
+ amount = GEN_INT (-(arm_get_frame_size ()
+ current_function_outgoing_args_size));
if (amount != const0_rtx)
@@ -8389,15 +8555,8 @@ arm_expand_prologue ()
will prevent the scheduler from moving stores to the frame
before the stack adjustment. */
if (frame_pointer_needed)
- {
- rtx unspec = gen_rtx_UNSPEC (SImode,
- gen_rtvec (2, stack_pointer_rtx,
- hard_frame_pointer_rtx),
- UNSPEC_PRLG_STK);
-
- insn = emit_insn (gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_MEM (BLKmode, unspec)));
- }
+ insn = emit_insn (gen_stack_tie (stack_pointer_rtx,
+ hard_frame_pointer_rtx));
}
/* If we are profiling, make sure no instructions are scheduled before
@@ -8573,11 +8732,12 @@ arm_print_operand (stream, x, code)
case 'M':
asm_fprintf (stream, "{%r-%r}",
REGNO (x),
- REGNO (x) + NUM_REGS (GET_MODE (x)) - 1);
+ REGNO (x) + ARM_NUM_REGS (GET_MODE (x)) - 1);
return;
case 'd':
- if (!x)
+ /* CONST_TRUE_RTX means always -- that's the default. */
+ if (x == const_true_rtx)
return;
if (TARGET_ARM)
@@ -8588,8 +8748,10 @@ arm_print_operand (stream, x, code)
return;
case 'D':
- if (!x)
- return;
+ /* CONST_TRUE_RTX means not always -- ie never. We shouldn't ever
+ want to do that. */
+ if (x == const_true_rtx)
+ abort ();
if (TARGET_ARM)
fputs (arm_condition_codes[ARM_INVERSE_CONDITION_CODE
@@ -8642,7 +8804,7 @@ arm_assemble_integer (x, size, aligned_p)
if (NEED_GOT_RELOC && flag_pic && making_const_table &&
(GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF))
{
- if (GET_CODE (x) == SYMBOL_REF
+ if (GET_CODE (x) == SYMBOL_REF
&& (CONSTANT_POOL_ADDRESS_P (x)
|| ENCODED_SHORT_CALL_ATTR_P (XSTR (x, 0))))
fputs ("(GOTOFF)", asm_out_file);
@@ -9171,7 +9333,7 @@ arm_hard_regno_mode_ok (regno, mode)
register available to hold the upper part of the value.
We probably we ought to ensure that the register is the
start of an even numbered register pair. */
- return (NUM_REGS (mode) < 2) || (regno < LAST_LO_REGNUM);
+ return (ARM_NUM_REGS (mode) < 2) || (regno < LAST_LO_REGNUM);
if (regno <= LAST_ARM_REGNUM)
/* We allow any value to be stored in the general regisetrs. */
@@ -9251,7 +9413,7 @@ arm_debugger_arg_offset (value, addr)
held in the register into an offset from the frame pointer.
We do this by searching through the insns for the function
looking to see where this register gets its value. If the
- register is initialised from the frame pointer plus an offset
+ register is initialized from the frame pointer plus an offset
then we are in luck and we can continue, otherwise we give up.
This code is exercised by producing debugging information
@@ -9302,7 +9464,7 @@ arm_debugger_arg_offset (value, addr)
}
#define def_builtin(NAME, TYPE, CODE) \
- builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL)
+ builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE)
void
arm_init_builtins ()
@@ -9313,10 +9475,9 @@ arm_init_builtins ()
tree int_ftype_int, void_ftype_pchar;
- /* void func (void *) */
+ /* void func (char *) */
void_ftype_pchar
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, pchar_type_node, endlink));
+ = build_function_type_list (void_type_node, pchar_type_node, NULL_TREE);
/* int func (int) */
int_ftype_int
@@ -9373,7 +9534,7 @@ arm_expand_builtin (exp, target, subtarget, mode, ignore)
emit_insn (pat);
return target;
}
-
+
/* @@@ Should really do something sensible here. */
return NULL_RTX;
}
@@ -9818,11 +9979,12 @@ thumb_shiftable_const (val)
return 0;
}
-/* Returns non-zero if the current function contains,
+/* Returns nonzero if the current function contains,
or might contain a far jump. */
int
-thumb_far_jump_used_p (int in_prologue)
+thumb_far_jump_used_p (in_prologue)
+ int in_prologue;
{
rtx insn;
@@ -9887,7 +10049,7 @@ thumb_far_jump_used_p (int in_prologue)
return 0;
}
-/* Return non-zero if FUNC must be entered in ARM mode. */
+/* Return nonzero if FUNC must be entered in ARM mode. */
int
is_called_in_ARM_mode (func)
@@ -9922,17 +10084,16 @@ thumb_unexpanded_epilogue ()
if (return_used_this_function)
return "";
+ if (IS_NAKED (arm_current_func_type ()))
+ return "";
+
for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
- if (regs_ever_live[regno] && !call_used_regs[regno]
- && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register)))
+ if (THUMB_REG_PUSHED_P (regno))
live_regs_mask |= 1 << regno;
for (regno = 8; regno < 13; regno++)
- {
- if (regs_ever_live[regno] && !call_used_regs[regno]
- && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register)))
- high_regs_pushed++;
- }
+ if (THUMB_REG_PUSHED_P (regno))
+ high_regs_pushed++;
/* The prolog may have pushed some high registers to use as
work registers. eg the testuite file:
@@ -9977,8 +10138,7 @@ thumb_unexpanded_epilogue ()
("no low registers available for popping high registers");
for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)
- if (regs_ever_live[next_hi_reg] && !call_used_regs[next_hi_reg]
- && !(TARGET_SINGLE_PIC_BASE && (next_hi_reg == arm_pic_register)))
+ if (THUMB_REG_PUSHED_P (next_hi_reg))
break;
while (high_regs_pushed)
@@ -10007,10 +10167,7 @@ thumb_unexpanded_epilogue ()
regno);
for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
- if (regs_ever_live[next_hi_reg]
- && !call_used_regs[next_hi_reg]
- && !(TARGET_SINGLE_PIC_BASE
- && (next_hi_reg == arm_pic_register)))
+ if (THUMB_REG_PUSHED_P (next_hi_reg))
break;
}
}
@@ -10084,37 +10241,16 @@ thumb_unexpanded_epilogue ()
/* Functions to save and restore machine-specific function data. */
-static void
-arm_mark_machine_status (p)
- struct function * p;
-{
- machine_function *machine = p->machine;
-
- if (machine)
- ggc_mark_rtx (machine->eh_epilogue_sp_ofs);
-}
-
-static void
-arm_init_machine_status (p)
- struct function * p;
+static struct machine_function *
+arm_init_machine_status ()
{
- p->machine =
- (machine_function *) xcalloc (1, sizeof (machine_function));
+ struct machine_function *machine;
+ machine = (machine_function *) ggc_alloc_cleared (sizeof (machine_function));
-#if ARM_FT_UNKNOWWN != 0
- ((machine_function *) p->machine)->func_type = ARM_FT_UNKNOWN;
+#if ARM_FT_UNKNOWN != 0
+ machine->func_type = ARM_FT_UNKNOWN;
#endif
-}
-
-static void
-arm_free_machine_status (p)
- struct function * p;
-{
- if (p->machine)
- {
- free (p->machine);
- p->machine = NULL;
- }
+ return machine;
}
/* Return an RTX indicating where the return address to the
@@ -10145,8 +10281,92 @@ arm_init_expanders ()
{
/* Arrange to initialize and mark the machine per-function status. */
init_machine_status = arm_init_machine_status;
- mark_machine_status = arm_mark_machine_status;
- free_machine_status = arm_free_machine_status;
+}
+
+HOST_WIDE_INT
+thumb_get_frame_size ()
+{
+ int regno;
+
+ int base_size = ROUND_UP (get_frame_size ());
+ int count_regs = 0;
+ int entry_size = 0;
+ int leaf;
+
+ if (! TARGET_THUMB)
+ abort ();
+
+ if (! TARGET_ATPCS)
+ return base_size;
+
+ /* We need to know if we are a leaf function. Unfortunately, it
+ is possible to be called after start_sequence has been called,
+ which causes get_insns to return the insns for the sequence,
+ not the function, which will cause leaf_function_p to return
+ the incorrect result.
+
+ To work around this, we cache the computed frame size. This
+ works because we will only be calling RTL expanders that need
+ to know about leaf functions once reload has completed, and the
+ frame size cannot be changed after that time, so we can safely
+ use the cached value. */
+
+ if (reload_completed)
+ return cfun->machine->frame_size;
+
+ leaf = leaf_function_p ();
+
+ /* A leaf function does not need any stack alignment if it has nothing
+ on the stack. */
+ if (leaf && base_size == 0)
+ {
+ cfun->machine->frame_size = 0;
+ return 0;
+ }
+
+ /* We know that SP will be word aligned on entry, and we must
+ preserve that condition at any subroutine call. But those are
+ the only constraints. */
+
+ /* Space for variadic functions. */
+ if (current_function_pretend_args_size)
+ entry_size += current_function_pretend_args_size;
+
+ /* Space for pushed lo registers. */
+ for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
+ if (THUMB_REG_PUSHED_P (regno))
+ count_regs++;
+
+ /* Space for backtrace structure. */
+ if (TARGET_BACKTRACE)
+ {
+ if (count_regs == 0 && regs_ever_live[LAST_ARG_REGNUM] != 0)
+ entry_size += 20;
+ else
+ entry_size += 16;
+ }
+
+ if (count_regs || !leaf || thumb_far_jump_used_p (1))
+ count_regs++; /* LR */
+
+ entry_size += count_regs * 4;
+ count_regs = 0;
+
+ /* Space for pushed hi regs. */
+ for (regno = 8; regno < 13; regno++)
+ if (THUMB_REG_PUSHED_P (regno))
+ count_regs++;
+
+ entry_size += count_regs * 4;
+
+ if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
+ base_size += 4;
+ if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
+ abort ();
+
+ cfun->machine->frame_size = base_size;
+
+ return base_size;
}
/* Generate the rest of a function's prologue. */
@@ -10154,7 +10374,7 @@ arm_init_expanders ()
void
thumb_expand_prologue ()
{
- HOST_WIDE_INT amount = (get_frame_size ()
+ HOST_WIDE_INT amount = (thumb_get_frame_size ()
+ current_function_outgoing_args_size);
unsigned long func_type;
@@ -10200,14 +10420,12 @@ thumb_expand_prologue ()
been pushed at the start of the prologue and so we can corrupt
it now. */
for (regno = LAST_ARG_REGNUM + 1; regno <= LAST_LO_REGNUM; regno++)
- if (regs_ever_live[regno]
- && !call_used_regs[regno] /* Paranoia */
- && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register))
+ if (THUMB_REG_PUSHED_P (regno)
&& !(frame_pointer_needed
&& (regno == THUMB_HARD_FRAME_POINTER_REGNUM)))
break;
- if (regno > LAST_LO_REGNUM) /* Very unlikely */
+ if (regno > LAST_LO_REGNUM) /* Very unlikely. */
{
rtx spare = gen_rtx (REG, SImode, IP_REGNUM);
@@ -10251,7 +10469,7 @@ thumb_expand_prologue ()
void
thumb_expand_epilogue ()
{
- HOST_WIDE_INT amount = (get_frame_size ()
+ HOST_WIDE_INT amount = (thumb_get_frame_size ()
+ current_function_outgoing_args_size);
/* Naked functions don't have prologues. */
@@ -10322,13 +10540,13 @@ thumb_output_function_prologue (f, size)
#define STUB_NAME ".real_start_of"
- asm_fprintf (f, "\t.code\t16\n");
+ fprintf (f, "\t.code\t16\n");
#ifdef ARM_PE
if (arm_dllexport_name_p (name))
name = arm_strip_name_encoding (name);
#endif
asm_fprintf (f, "\t.globl %s%U%s\n", STUB_NAME, name);
- asm_fprintf (f, "\t.thumb_func\n");
+ fprintf (f, "\t.thumb_func\n");
asm_fprintf (f, "%s%U%s:\n", STUB_NAME, name);
}
@@ -10338,9 +10556,9 @@ thumb_output_function_prologue (f, size)
{
int num_pushes;
- asm_fprintf (f, "\tpush\t{");
+ fprintf (f, "\tpush\t{");
- num_pushes = NUM_INTS (current_function_pretend_args_size);
+ num_pushes = ARM_NUM_INTS (current_function_pretend_args_size);
for (regno = LAST_ARG_REGNUM + 1 - num_pushes;
regno <= LAST_ARG_REGNUM;
@@ -10348,7 +10566,7 @@ thumb_output_function_prologue (f, size)
asm_fprintf (f, "%r%s", regno,
regno == LAST_ARG_REGNUM ? "" : ", ");
- asm_fprintf (f, "}\n");
+ fprintf (f, "}\n");
}
else
asm_fprintf (f, "\tsub\t%r, %r, #%d\n",
@@ -10357,8 +10575,7 @@ thumb_output_function_prologue (f, size)
}
for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
- if (regs_ever_live[regno] && !call_used_regs[regno]
- && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register)))
+ if (THUMB_REG_PUSHED_P (regno))
live_regs_mask |= 1 << regno;
if (live_regs_mask || !leaf_function_p () || thumb_far_jump_used_p (1))
@@ -10459,11 +10676,8 @@ thumb_output_function_prologue (f, size)
thumb_pushpop (f, live_regs_mask, 1);
for (regno = 8; regno < 13; regno++)
- {
- if (regs_ever_live[regno] && !call_used_regs[regno]
- && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register)))
- high_regs_pushed++;
- }
+ if (THUMB_REG_PUSHED_P (regno))
+ high_regs_pushed++;
if (high_regs_pushed)
{
@@ -10472,20 +10686,15 @@ thumb_output_function_prologue (f, size)
int next_hi_reg;
for (next_hi_reg = 12; next_hi_reg > LAST_LO_REGNUM; next_hi_reg--)
- {
- if (regs_ever_live[next_hi_reg] && !call_used_regs[next_hi_reg]
- && !(TARGET_SINGLE_PIC_BASE
- && (next_hi_reg == arm_pic_register)))
- break;
- }
+ if (THUMB_REG_PUSHED_P (next_hi_reg))
+ break;
pushable_regs = mask;
if (pushable_regs == 0)
{
/* Desperation time -- this probably will never happen. */
- if (regs_ever_live[LAST_ARG_REGNUM]
- || !call_used_regs[LAST_ARG_REGNUM])
+ if (THUMB_REG_PUSHED_P (LAST_ARG_REGNUM))
asm_fprintf (f, "\tmov\t%r, %r\n", IP_REGNUM, LAST_ARG_REGNUM);
mask = 1 << LAST_ARG_REGNUM;
}
@@ -10501,15 +10710,12 @@ thumb_output_function_prologue (f, size)
high_regs_pushed--;
if (high_regs_pushed)
- for (next_hi_reg--; next_hi_reg > LAST_LO_REGNUM;
- next_hi_reg--)
- {
- if (regs_ever_live[next_hi_reg]
- && !call_used_regs[next_hi_reg]
- && !(TARGET_SINGLE_PIC_BASE
- && (next_hi_reg == arm_pic_register)))
+ {
+ for (next_hi_reg--; next_hi_reg > LAST_LO_REGNUM;
+ next_hi_reg--)
+ if (THUMB_REG_PUSHED_P (next_hi_reg))
break;
- }
+ }
else
{
mask &= ~((1 << regno) - 1);
@@ -10522,8 +10728,7 @@ thumb_output_function_prologue (f, size)
}
if (pushable_regs == 0
- && (regs_ever_live[LAST_ARG_REGNUM]
- || !call_used_regs[LAST_ARG_REGNUM]))
+ && (THUMB_REG_PUSHED_P (LAST_ARG_REGNUM)))
asm_fprintf (f, "\tmov\t%r, %r\n", LAST_ARG_REGNUM, IP_REGNUM);
}
}
@@ -10821,7 +11026,8 @@ thumb_reload_in_hi (operands)
that starts with the character 'c'. */
static int
-arm_get_strip_length (char c)
+arm_get_strip_length (c)
+ int c;
{
switch (c)
{
@@ -10834,7 +11040,8 @@ arm_get_strip_length (char c)
and all prefix encodings stripped from it. */
const char *
-arm_strip_name_encoding (const char * name)
+arm_strip_name_encoding (name)
+ const char * name;
{
int skip;
@@ -10844,10 +11051,35 @@ arm_strip_name_encoding (const char * name)
return name;
}
+/* If there is a '*' anywhere in the name's prefix, then
+ emit the stripped name verbatim, otherwise prepend an
+ underscore if leading underscores are being used. */
+
+void
+arm_asm_output_labelref (stream, name)
+ FILE * stream;
+ const char * name;
+{
+ int skip;
+ int verbatim = 0;
+
+ while ((skip = arm_get_strip_length (* name)))
+ {
+ verbatim |= (*name == '*');
+ name += skip;
+ }
+
+ if (verbatim)
+ fputs (name, stream);
+ else
+ asm_fprintf (stream, "%U%s", name);
+}
+
+rtx aof_pic_label;
+
#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;
@@ -10865,10 +11097,6 @@ aof_pic_entry (x)
if (aof_pic_label == NULL_RTX)
{
- /* We mark this here and not in arm_add_gc_roots() to avoid
- polluting even more code with ifdefs, and because it never
- contains anything useful until we assign to it here. */
- ggc_add_rtx_root (&aof_pic_label, 1);
aof_pic_label = gen_rtx_SYMBOL_REF (Pmode, "x$adcons");
}
@@ -11003,6 +11231,16 @@ aof_dump_imports (f)
imports_list = imports_list->next;
}
}
+
+static void
+aof_globalize_label (stream, name)
+ FILE *stream;
+ const char *name;
+{
+ default_globalize_label (stream, name);
+ if (! strcmp (name, "main"))
+ arm_main_function = 1;
+}
#endif /* AOF_ASSEMBLER */
#ifdef OBJECT_FORMAT_ELF
@@ -11018,8 +11256,13 @@ arm_elf_asm_named_section (name, flags)
const char *name;
unsigned int flags;
{
- char flagchars[8], *f = flagchars;
- const char *type;
+ char flagchars[10], *f = flagchars;
+
+ if (! named_section_first_declaration (name))
+ {
+ fprintf (asm_out_file, "\t.section\t%s\n", name);
+ return;
+ }
if (!(flags & SECTION_DEBUG))
*f++ = 'a';
@@ -11033,18 +11276,103 @@ arm_elf_asm_named_section (name, flags)
*f++ = 'M';
if (flags & SECTION_STRINGS)
*f++ = 'S';
+ if (flags & SECTION_TLS)
+ *f++ = 'T';
*f = '\0';
- if (flags & SECTION_BSS)
- type = "nobits";
- else
- type = "progbits";
+ fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
- if (flags & SECTION_ENTSIZE)
- fprintf (asm_out_file, "\t.section\t%s,\"%s\",%%%s,%d\n",
- name, flagchars, type, flags & SECTION_ENTSIZE);
- else
- fprintf (asm_out_file, "\t.section\t%s,\"%s\",%%%s\n",
- name, flagchars, type);
+ if (!(flags & SECTION_NOTYPE))
+ {
+ const char *type;
+
+ if (flags & SECTION_BSS)
+ type = "nobits";
+ else
+ type = "progbits";
+
+ fprintf (asm_out_file, ",%%%s", type);
+
+ if (flags & SECTION_ENTSIZE)
+ fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
+ }
+
+ putc ('\n', asm_out_file);
}
#endif
+
+#ifndef ARM_PE
+/* 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. */
+
+static void
+arm_encode_section_info (decl, first)
+ tree decl;
+ int first;
+{
+ /* This doesn't work with AOF syntax, since the string table may be in
+ a different AREA. */
+#ifndef AOF_ASSEMBLER
+ if (optimize > 0 && TREE_CONSTANT (decl)
+ && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
+ {
+ rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
+ ? TREE_CST_RTL (decl) : DECL_RTL (decl));
+ SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
+ }
+#endif
+
+ /* If we are referencing a function that is weak then encode a long call
+ flag in the function name, otherwise if the function is static or
+ or known to be defined in this file then encode a short call flag. */
+ if (first && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
+ {
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_WEAK (decl))
+ arm_encode_call_attribute (decl, LONG_CALL_FLAG_CHAR);
+ else if (! TREE_PUBLIC (decl))
+ arm_encode_call_attribute (decl, SHORT_CALL_FLAG_CHAR);
+ }
+}
+#endif /* !ARM_PE */
+
+/* Output code to add DELTA to the first argument, and then jump
+ to FUNCTION. Used for C++ multiple inheritance. */
+
+static void
+arm_output_mi_thunk (file, thunk, delta, vcall_offset, function)
+ FILE *file;
+ tree thunk ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT delta;
+ HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
+ tree function;
+{
+ int mi_delta = delta;
+ const char *const 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
+ {
+ asm_fprintf (file, "\t%s\t%r, %r, #%d\n",
+ mi_op, this_regno, this_regno,
+ mi_delta & (0xff << shift));
+ mi_delta &= ~(0xff << shift);
+ shift += 8;
+ }
+ }
+ fputs ("\tb\t", file);
+ assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
+ if (NEED_PLT_RELOC)
+ fputs ("(PLT)", file);
+ fputc ('\n', file);
+}
+
diff --git a/contrib/gcc/config/arm/arm.h b/contrib/gcc/config/arm/arm.h
index c5431b5..eda2d47 100644
--- a/contrib/gcc/config/arm/arm.h
+++ b/contrib/gcc/config/arm/arm.h
@@ -26,6 +26,52 @@ Boston, MA 02111-1307, USA. */
#ifndef GCC_ARM_H
#define GCC_ARM_H
+/* Target CPU builtins. */
+#define TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ if (TARGET_ARM) \
+ builtin_define ("__arm__"); \
+ else \
+ builtin_define ("__thumb__"); \
+ \
+ if (TARGET_BIG_END) \
+ { \
+ builtin_define ("__ARMEB__"); \
+ if (TARGET_THUMB) \
+ builtin_define ("__THUMBEB__"); \
+ if (TARGET_LITTLE_WORDS) \
+ builtin_define ("__ARMWEL__"); \
+ } \
+ else \
+ { \
+ builtin_define ("__ARMEL__"); \
+ if (TARGET_THUMB) \
+ builtin_define ("__THUMBEL__"); \
+ } \
+ \
+ if (TARGET_APCS_32) \
+ builtin_define ("__APCS_32__"); \
+ else \
+ builtin_define ("__APCS_26__"); \
+ \
+ if (TARGET_SOFT_FLOAT) \
+ builtin_define ("__SOFTFP__"); \
+ \
+ /* FIXME: TARGET_HARD_FLOAT currently implies \
+ FPA. */ \
+ if (TARGET_VFP && !TARGET_HARD_FLOAT) \
+ builtin_define ("__VFP_FP__"); \
+ \
+ /* Add a define for interworking. \
+ Needed when building libgcc.a. */ \
+ if (TARGET_INTERWORK) \
+ builtin_define ("__THUMB_INTERWORK__"); \
+ \
+ builtin_assert ("cpu=arm"); \
+ builtin_assert ("machine=arm"); \
+ } while (0)
+
#define TARGET_CPU_arm2 0x0000
#define TARGET_CPU_arm250 0x0000
#define TARGET_CPU_arm3 0x0000
@@ -66,21 +112,22 @@ extern arm_cc arm_current_cc;
extern int arm_target_label;
extern int arm_ccfsm_state;
-extern struct rtx_def * arm_target_insn;
+extern GTY(()) rtx arm_target_insn;
/* Run-time compilation parameters selecting different hardware subsets. */
extern int target_flags;
/* The floating point instruction architecture, can be 2 or 3 */
extern const char * target_fp_name;
/* Define the information needed to generate branch insns. This is
- stored from the compare operation. Note that we can't use "rtx" here
- since it hasn't been defined! */
-extern struct rtx_def * arm_compare_op0;
-extern struct rtx_def * arm_compare_op1;
+ stored from the compare operation. */
+extern GTY(()) rtx arm_compare_op0;
+extern GTY(()) rtx arm_compare_op1;
/* The label of the current constant pool. */
-extern struct rtx_def * pool_vector_label;
+extern rtx pool_vector_label;
/* Set to 1 when a return insn is output, this means that the epilogue
is not needed. */
extern int return_used_this_function;
+/* Used to produce AOF syntax assembler. */
+extern GTY(()) rtx aof_pic_label;
/* Just in case configure has failed to define anything. */
#ifndef TARGET_CPU_DEFAULT
@@ -126,16 +173,17 @@ Unrecognized value in TARGET_CPU_DEFAULT.
#endif
#undef CPP_SPEC
-#define CPP_SPEC "\
-%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) \
-%(cpp_endian) %(subtarget_cpp_spec) %(cpp_isa) %(cpp_interwork)"
-
-#define CPP_ISA_SPEC "%{mthumb:-D__thumb__} %{!mthumb:-D__arm__}"
+#define CPP_SPEC "%(cpp_cpu_arch) %(subtarget_cpp_spec) \
+%{mapcs-32:%{mapcs-26: \
+ %e-mapcs-26 and -mapcs-32 may not be used together}} \
+%{msoft-float:%{mhard-float: \
+ %e-msoft-float and -mhard_float may not be used together}} \
+%{mbig-endian:%{mlittle-endian: \
+ %e-mbig-endian and -mlittle-endian may not be used together}}"
/* Set the architecture define -- if -march= is set, then it overrides
the -mcpu= setting. */
#define CPP_CPU_ARCH_SPEC "\
--Acpu=arm -Amachine=arm \
%{march=arm2:-D__ARM_ARCH_2__} \
%{march=arm250:-D__ARM_ARCH_2__} \
%{march=arm3:-D__ARM_ARCH_2__} \
@@ -206,58 +254,6 @@ Unrecognized value in TARGET_CPU_DEFAULT.
%{!mcpu*:%(cpp_cpu_arch_default)}} \
"
-/* Define __APCS_26__ if the PC also contains the PSR */
-#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:%(cpp_apcs_pc_default)}} \
-"
-
-#ifndef CPP_APCS_PC_DEFAULT_SPEC
-#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_26__"
-#endif
-
-#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__} %{mthumb:-D__THUMBEB__}}\
-%{mlittle-endian:-D__ARMEL__ %{mthumb:-D__THUMBEL__}} \
-%{!mlittle-endian:%{!mbig-endian:%(cpp_endian_default)}} \
-"
-
-/* Default is little endian. */
-#define CPP_ENDIAN_DEFAULT_SPEC "-D__ARMEL__ %{mthumb:-D__THUMBEL__}"
-
-/* Add a define for interworking. Needed when building libgcc.a.
- This must define __THUMB_INTERWORK__ to the pre-processor if
- interworking is enabled by default. */
-#ifndef CPP_INTERWORK_DEFAULT_SPEC
-#define CPP_INTERWORK_DEFAULT_SPEC ""
-#endif
-
-#define CPP_INTERWORK_SPEC " \
-%{mthumb-interwork: \
- %{mno-thumb-interwork: %eincompatible interworking options} \
- -D__THUMB_INTERWORK__} \
-%{!mthumb-interwork:%{!mno-thumb-interwork:%(cpp_interwork_default)}} \
-"
-
-#ifndef CPP_PREDEFINES
-#define CPP_PREDEFINES ""
-#endif
-
#ifndef CC1_SPEC
#define CC1_SPEC ""
#endif
@@ -274,15 +270,6 @@ Unrecognized value in TARGET_CPU_DEFAULT.
#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 }, \
- { "cpp_isa", CPP_ISA_SPEC }, \
- { "cpp_interwork", CPP_INTERWORK_SPEC }, \
- { "cpp_interwork_default", CPP_INTERWORK_DEFAULT_SPEC }, \
{ "subtarget_cpp_spec", SUBTARGET_CPP_SPEC }, \
SUBTARGET_EXTRA_SPECS
@@ -383,6 +370,12 @@ Unrecognized value in TARGET_CPU_DEFAULT.
destination is non-Thumb aware. */
#define THUMB_FLAG_CALLER_SUPER_INTERWORKING (1 << 20)
+/* Nonzero means target uses VFP FP. */
+#define ARM_FLAG_VFP (1 << 21)
+
+/* Nonzero means to use ARM/Thumb Procedure Call Standard conventions. */
+#define ARM_FLAG_ATPCS (1 << 22)
+
#define TARGET_APCS_FRAME (target_flags & ARM_FLAG_APCS_FRAME)
#define TARGET_POKE_FUNCTION_NAME (target_flags & ARM_FLAG_POKE)
#define TARGET_FPE (target_flags & ARM_FLAG_FPE)
@@ -390,9 +383,11 @@ Unrecognized value in TARGET_CPU_DEFAULT.
#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_ATPCS (target_flags & ARM_FLAG_ATPCS)
#define TARGET_MMU_TRAPS (target_flags & ARM_FLAG_MMU_TRAPS)
#define TARGET_SOFT_FLOAT (target_flags & ARM_FLAG_SOFT_FLOAT)
#define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT)
+#define TARGET_VFP (target_flags & ARM_FLAG_VFP)
#define TARGET_BIG_END (target_flags & ARM_FLAG_BIG_END)
#define TARGET_INTERWORK (target_flags & ARM_FLAG_INTERWORK)
#define TARGET_LITTLE_WORDS (target_flags & ARM_FLAG_LITTLE_WORDS)
@@ -409,8 +404,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
? (target_flags & THUMB_FLAG_LEAF_BACKTRACE) \
: (target_flags & THUMB_FLAG_BACKTRACE))
-/* SUBTARGET_SWITCHES is used to add flags on a per-config basis.
- Bit 31 is reserved. See riscix.h. */
+/* SUBTARGET_SWITCHES is used to add flags on a per-config basis. */
#ifndef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES
#endif
@@ -647,8 +641,6 @@ extern int arm_is_6_or_7;
/* 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:
I think I have added all the code to make this work. Unfortunately,
early releases of the floating point emulation code on RISCiX used a
@@ -663,12 +655,6 @@ extern int arm_is_6_or_7;
/* Disable XFmode patterns in md file */
#define ENABLE_XF_PATTERNS 0
-/* Define if you don't want extended real, but do want to use the
- software floating point emulator for REAL_ARITHMETIC and
- decimal <-> binary conversion. */
-/* See comment above */
-#define REAL_ARITHMETIC
-
/* Define this if most significant bit is lowest numbered
in instructions that operate on numbered bit-fields. */
#define BITS_BIG_ENDIAN 0
@@ -693,22 +679,18 @@ extern int arm_is_6_or_7;
#endif
/* 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 */
-#define BITS_PER_UNIT 8
-
-#define BITS_PER_WORD 32
+ The rules are different based on whether or not we use FPA-format or
+ VFP-format doubles. */
+#define FLOAT_WORDS_BIG_ENDIAN (arm_float_words_big_endian ())
#define UNITS_PER_WORD 4
-#define POINTER_SIZE 32
-
#define PARM_BOUNDARY 32
#define STACK_BOUNDARY 32
+#define PREFERRED_STACK_BOUNDARY (TARGET_ATPCS ? 64 : 32)
+
#define FUNCTION_BOUNDARY 32
/* The lowest bit is used to indicate Thumb-mode functions, so the
@@ -737,7 +719,7 @@ extern int arm_is_6_or_7;
#define STRUCTURE_SIZE_BOUNDARY arm_structure_size_boundary
extern int arm_structure_size_boundary;
-/* This is the value used to initialise arm_structure_size_boundary. If a
+/* This is the value used to initialize arm_structure_size_boundary. If a
particular arm target wants to change the default value it should change
the definition of this macro, not STRUCTRUE_SIZE_BOUNDARY. See netbsd.h
for an example of this. */
@@ -748,12 +730,9 @@ extern int arm_structure_size_boundary;
/* Used when parsing command line option -mstructure_size_boundary. */
extern const char * structure_size_string;
-/* Non-zero if move instructions will actually fail to work
+/* Nonzero if move instructions will actually fail to work
when given unaligned data. */
#define STRICT_ALIGNMENT 1
-
-#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-
/* Standard register usage. */
@@ -889,15 +868,15 @@ extern const char * structure_size_string;
#define ROUND_UP(X) (((X) + 3) & ~3)
/* Convert fron bytes to ints. */
-#define NUM_INTS(X) (((X) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+#define ARM_NUM_INTS(X) (((X) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* The number of (integer) registers required to hold a quantity of type MODE. */
-#define NUM_REGS(MODE) \
- NUM_INTS (GET_MODE_SIZE (MODE))
+#define ARM_NUM_REGS(MODE) \
+ ARM_NUM_INTS (GET_MODE_SIZE (MODE))
/* The number of (integer) registers required to hold a quantity of TYPE MODE. */
-#define NUM_REGS2(MODE, TYPE) \
- NUM_INTS ((MODE) == BLKmode ? \
+#define ARM_NUM_REGS2(MODE, TYPE) \
+ ARM_NUM_INTS ((MODE) == BLKmode ? \
int_size_in_bytes (TYPE) : GET_MODE_SIZE (MODE))
/* The number of (integer) argument register available. */
@@ -1001,7 +980,7 @@ extern const char * structure_size_string;
&& REGNO >= FIRST_ARM_FP_REGNUM \
&& REGNO != FRAME_POINTER_REGNUM \
&& REGNO != ARG_POINTER_REGNUM) \
- ? 1 : NUM_REGS (MODE))
+ ? 1 : ARM_NUM_REGS (MODE))
/* Return true if REGNO is suitable for holding a quantity of type MODE. */
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
@@ -1324,7 +1303,7 @@ enum reg_class
needed to represent mode MODE in a register of class CLASS.
ARM regs are UNITS_PER_WORD bits while FPU regs can hold any FP mode */
#define CLASS_MAX_NREGS(CLASS, MODE) \
- ((CLASS) == FPU_REGS ? 1 : NUM_REGS (MODE))
+ ((CLASS) == FPU_REGS ? 1 : ARM_NUM_REGS (MODE))
/* Moves between FPU_REGS and GENERAL_REGS are two memory insns. */
#define REGISTER_MOVE_COST(MODE, FROM, TO) \
@@ -1420,7 +1399,7 @@ enum reg_class
Note value 7 is currently unassigned. Also note that the interrupt
function types all have bit 2 set, so that they can be tested for easily.
Note that 0 is deliberately chosen for ARM_FT_UNKNOWN so that when the
- machine_function structure is initialised (to zero) func_type will
+ machine_function structure is initialized (to zero) func_type will
default to unknown. This will force the first use of arm_current_func_type
to call arm_compute_func_type. */
#define ARM_FT_UNKNOWN 0 /* Type has not yet been determined. */
@@ -1449,16 +1428,18 @@ enum reg_class
/* A C structure for machine-specific, per-function data.
This is added to the cfun structure. */
-typedef struct machine_function
+typedef struct machine_function GTY(())
{
/* Additionsl stack adjustment in __builtin_eh_throw. */
- struct rtx_def *eh_epilogue_sp_ofs;
+ rtx eh_epilogue_sp_ofs;
/* Records if LR has to be saved for far jumps. */
int far_jump_used;
/* Records if ARG_POINTER was ever live. */
int arg_pointer_live;
/* Records if the save of LR has been eliminated. */
int lr_save_eliminated;
+ /* The size of the stack frame. Only valid after reload. */
+ int frame_size;
/* Records the type of the current function. */
unsigned long func_type;
/* Record if the function has a variable argument list. */
@@ -1503,9 +1484,17 @@ typedef struct
For args passed entirely in registers or entirely in memory, zero. */
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
( NUM_ARG_REGS > (CUM).nregs \
- && (NUM_ARG_REGS < ((CUM).nregs + NUM_REGS2 (MODE, TYPE))) \
+ && (NUM_ARG_REGS < ((CUM).nregs + ARM_NUM_REGS2 (MODE, TYPE))) \
? NUM_ARG_REGS - (CUM).nregs : 0)
+/* 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) \
+ arm_function_arg_pass_by_reference (&CUM, MODE, TYPE, NAMED)
+
/* 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.
@@ -1517,12 +1506,16 @@ typedef struct
of mode MODE and data type TYPE.
(TYPE is null for libcalls where that information may not be available.) */
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- (CUM).nregs += NUM_REGS2 (MODE, TYPE)
+ (CUM).nregs += ARM_NUM_REGS2 (MODE, TYPE)
/* 1 if N is a possible register number for function argument passing.
On the ARM, r0-r3 are used to pass args. */
#define FUNCTION_ARG_REGNO_P(REGNO) (IN_RANGE ((REGNO), 0, 3))
+/* Implement `va_arg'. */
+#define EXPAND_BUILTIN_VA_ARG(valist, type) \
+ arm_va_arg (valist, type)
+
/* Tail calling. */
@@ -1572,7 +1565,10 @@ typedef struct
will output the .text section.
The ``mov ip,lr'' seems like a good idea to stick with cc convention.
- ``prof'' doesn't seem to mind about this! */
+ ``prof'' doesn't seem to mind about this!
+
+ Note - this version of the code is designed to work in both ARM and
+ Thumb modes. */
#ifndef ARM_FUNCTION_PROFILER
#define ARM_FUNCTION_PROFILER(STREAM, LABELNO) \
{ \
@@ -1589,20 +1585,16 @@ typedef struct
}
#endif
-#ifndef THUMB_FUNCTION_PROFILER
-#define THUMB_FUNCTION_PROFILER(STREAM, LABELNO) \
-{ \
- fprintf (STREAM, "\tmov\tip, lr\n"); \
- fprintf (STREAM, "\tbl\tmcount\n"); \
- fprintf (STREAM, "\t.word\tLP%d\n", LABELNO); \
-}
-#endif
-
+#ifdef THUMB_FUNCTION_PROFILER
#define FUNCTION_PROFILER(STREAM, LABELNO) \
if (TARGET_ARM) \
ARM_FUNCTION_PROFILER (STREAM, LABELNO) \
else \
THUMB_FUNCTION_PROFILER (STREAM, LABELNO)
+#else
+#define FUNCTION_PROFILER(STREAM, LABELNO) \
+ ARM_FUNCTION_PROFILER (STREAM, LABELNO)
+#endif
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
the stack pointer does not matter. The value is tested only in
@@ -1657,7 +1649,13 @@ typedef struct
((TO) == ARM_HARD_FRAME_POINTER_REGNUM && TARGET_THUMB) ? 0 : \
((TO) == THUMB_HARD_FRAME_POINTER_REGNUM && TARGET_ARM) ? 0 : \
1)
-
+
+#define THUMB_REG_PUSHED_P(reg) \
+ (regs_ever_live [reg] \
+ && (! call_used_regs [reg] \
+ || (flag_pic && (reg) == PIC_OFFSET_TABLE_REGNUM)) \
+ && !(TARGET_SINGLE_PIC_BASE && ((reg) == arm_pic_register)))
+
/* Define the offset between two registers, one to be eliminated, and the
other its replacement, at the start of a routine. */
#define ARM_INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
@@ -1676,13 +1674,13 @@ typedef struct
int count_regs = 0; \
int regno; \
for (regno = 8; regno < 13; regno ++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- count_regs ++; \
+ if (THUMB_REG_PUSHED_P (regno)) \
+ count_regs ++; \
if (count_regs) \
(OFFSET) += 4 * count_regs; \
count_regs = 0; \
for (regno = 0; regno <= LAST_LO_REGNUM; regno ++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ if (THUMB_REG_PUSHED_P (regno)) \
count_regs ++; \
if (count_regs || ! leaf_function_p () || thumb_far_jump_used_p (0))\
(OFFSET) += 4 * (count_regs + 1); \
@@ -1697,7 +1695,7 @@ typedef struct
if ((TO) == STACK_POINTER_REGNUM) \
{ \
(OFFSET) += current_function_outgoing_args_size; \
- (OFFSET) += ROUND_UP (get_frame_size ()); \
+ (OFFSET) += thumb_get_frame_size (); \
} \
}
@@ -1884,56 +1882,11 @@ typedef struct
case '*': return 1; \
SUBTARGET_NAME_ENCODING_LENGTHS
-/* This has to be handled by a function because more than part of the
- ARM backend uses function name prefixes to encode attributes. */
-#undef STRIP_NAME_ENCODING
-#define STRIP_NAME_ENCODING(VAR, SYMBOL_NAME) \
- (VAR) = arm_strip_name_encoding (SYMBOL_NAME)
-
/* This is how to output a reference to a user-level label named NAME.
`assemble_name' uses this. */
#undef ASM_OUTPUT_LABELREF
#define ASM_OUTPUT_LABELREF(FILE, NAME) \
- asm_fprintf (FILE, "%U%s", arm_strip_name_encoding (NAME))
-
-/* If we are referencing a function that is weak then encode a long call
- flag in the function name, otherwise if the function is static or
- or known to be defined in this file then encode a short call flag.
- This macro is used inside the ENCODE_SECTION macro. */
-#define ARM_ENCODE_CALL_TYPE(decl) \
- if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd') \
- { \
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_WEAK (decl)) \
- arm_encode_call_attribute (decl, LONG_CALL_FLAG_CHAR); \
- else if (! TREE_PUBLIC (decl)) \
- arm_encode_call_attribute (decl, SHORT_CALL_FLAG_CHAR); \
- }
-
-/* 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) \
- && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST)) \
- { \
- rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd' \
- ? TREE_CST_RTL (decl) : DECL_RTL (decl)); \
- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; \
- } \
- ARM_ENCODE_CALL_TYPE (decl) \
-}
-#else
-#define ENCODE_SECTION_INFO(decl) \
-{ \
- ARM_ENCODE_CALL_TYPE (decl) \
-}
-#endif
+ arm_asm_output_labelref (FILE, NAME)
#define ARM_DECLARE_FUNCTION_SIZE(STREAM, NAME, DECL) \
arm_encode_call_attribute (DECL, SHORT_CALL_FLAG_CHAR)
@@ -2168,7 +2121,8 @@ typedef struct
goto WIN; \
/* This is PC relative data before MACHINE_DEPENDENT_REORG runs. */ \
else if (GET_MODE_SIZE (MODE) >= 4 && CONSTANT_P (X) \
- && CONSTANT_POOL_ADDRESS_P (X) && ! flag_pic) \
+ && GET_CODE (X) == SYMBOL_REF \
+ && CONSTANT_POOL_ADDRESS_P (X) && ! flag_pic) \
goto WIN; \
/* This is PC relative data after MACHINE_DEPENDENT_REORG runs. */ \
else if (GET_MODE_SIZE (MODE) >= 4 && reload_completed \
@@ -2477,12 +2431,13 @@ extern const char * arm_pic_register_string;
/* We can't directly access anything that contains a symbol,
nor can we indirect via the constant pool. */
#define LEGITIMATE_PIC_OPERAND_P(X) \
- ( ! symbol_mentioned_p (X) \
- && ! label_mentioned_p (X) \
- && (! CONSTANT_POOL_ADDRESS_P (X) \
- || ( ! symbol_mentioned_p (get_pool_constant (X)) \
- && ! label_mentioned_p (get_pool_constant (X)))))
-
+ (!(symbol_mentioned_p (X) \
+ || label_mentioned_p (X) \
+ || (GET_CODE (X) == SYMBOL_REF \
+ && CONSTANT_POOL_ADDRESS_P (X) \
+ && (symbol_mentioned_p (get_pool_constant (X)) \
+ || label_mentioned_p (get_pool_constant (X))))))
+
/* We need to know when we are making a constant pool; this determines
whether data needs to be in the GOT or can be referenced via a GOT
offset. */
@@ -2497,30 +2452,7 @@ extern int making_const_table;
/* Condition code information. */
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
- return the mode to be used for the comparison.
- 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(CC_NOOVmode, "CC_NOOV") \
- CC(CC_Zmode, "CC_Z") \
- CC(CC_SWPmode, "CC_SWP") \
- CC(CCFPmode, "CCFP") \
- CC(CCFPEmode, "CCFPE") \
- CC(CC_DNEmode, "CC_DNE") \
- CC(CC_DEQmode, "CC_DEQ") \
- CC(CC_DLEmode, "CC_DLE") \
- CC(CC_DLTmode, "CC_DLT") \
- CC(CC_DGEmode, "CC_DGE") \
- CC(CC_DGTmode, "CC_DGT") \
- CC(CC_DLEUmode, "CC_DLEU") \
- CC(CC_DLTUmode, "CC_DLTU") \
- CC(CC_DGEUmode, "CC_DGEU") \
- CC(CC_DGTUmode, "CC_DGTU") \
- CC(CC_Cmode, "CC_C")
+ return the mode to be used for the comparison. */
#define SELECT_CC_MODE(OP, X, Y) arm_select_cc_mode (OP, X, Y)
@@ -2779,39 +2711,6 @@ extern int making_const_table;
else \
THUMB_PRINT_OPERAND_ADDRESS (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); \
- const char *const 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 \
- { \
- asm_fprintf (FILE, "\t%s\t%r, %r, #%d\n", \
- mi_op, this_regno, this_regno, \
- mi_delta & (0xff << shift)); \
- mi_delta &= ~(0xff << shift); \
- shift += 8; \
- } \
- } \
- fputs ("\tb\t", FILE); \
- assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
- if (NEED_PLT_RELOC) \
- fputs ("(PLT)", FILE); \
- 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. */
@@ -2835,8 +2734,10 @@ extern int making_const_table;
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 (RETURN_ADDR_MASK26)) \
- : (GEN_INT ((unsigned long)0xffffffff)))
+ ((!TARGET_APCS_32) ? (gen_int_mode (RETURN_ADDR_MASK26, Pmode)) \
+ : (arm_arch4 || TARGET_THUMB) ? \
+ (gen_int_mode ((unsigned long)0xffffffff, Pmode)) \
+ : arm_gen_return_addr_mask ())
/* Define the codes that are matched by predicates in arm.c */
diff --git a/contrib/gcc/config/arm/arm.md b/contrib/gcc/config/arm/arm.md
index 5180c75..0e60712 100644
--- a/contrib/gcc/config/arm/arm.md
+++ b/contrib/gcc/config/arm/arm.md
@@ -59,7 +59,11 @@
(UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
; usage, that is, we will add the pic_register
; value to it before trying to dereference it.
- (UNSPEC_PRLG_STK 4) ; A special barrier that prevents frame accesses
+ (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
+ ; GLOBAL_OFFSET_TABLE. The operation is fully
+ ; described by the RTL but must be wrapped to
+ ; prevent combine from trying to rip it apart.
+ (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
; being scheduled before the stack adjustment insn.
(UNSPEC_CLZ 5) ; `clz' instruction, count leading zeros (SImode):
; operand 0 is the result,
@@ -69,6 +73,7 @@
; instructions setting registers for EH handling
; and stack frame generation. Operand 0 is the
; register to "use".
+ (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
]
)
@@ -179,7 +184,7 @@
(const_string "normal"))
; Load scheduling, set from the arm_ld_sched variable
-; initialised by arm_override_options()
+; initialized by arm_override_options()
(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
; condition codes: this one is used by final_prescan_insn to speed up
@@ -600,10 +605,10 @@
;; Reloading and elimination of the frame pointer can
;; sometimes cause this optimization to be missed.
(define_peephole2
- [(set (match_operand:SI 0 "register_operand" "=l")
- (match_operand:SI 1 "const_int_operand" "M"))
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "const_int_operand" ""))
(set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
+ (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
"TARGET_THUMB
&& REGNO (operands[2]) == STACK_POINTER_REGNUM
&& (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
@@ -1857,9 +1862,9 @@
;;; ??? This pattern is bogus. If operand3 has bits outside the range
;;; represented by the bitfield, then this will produce incorrect results.
;;; Somewhere, the value needs to be truncated. On targets like the m68k,
-;;; which have a real bitfield insert instruction, the truncation happens
-;;; in the bitfield insert instruction itself. Since arm does not have a
-;;; bitfield insert instruction, we would have to emit code here to truncate
+;;; which have a real bit-field insert instruction, the truncation happens
+;;; in the bit-field insert instruction itself. Since arm does not have a
+;;; bit-field insert instruction, we would have to emit code here to truncate
;;; the value before we insert. This loses some of the advantage of having
;;; this insv pattern, so this pattern needs to be reevalutated.
@@ -1867,7 +1872,7 @@
[(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
(match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" ""))
- (match_operand:SI 3 "nonmemory_operand" ""))]
+ (match_operand:SI 3 "reg_or_int_operand" ""))]
"TARGET_ARM"
"
{
@@ -2035,7 +2040,7 @@
"TARGET_ARM
&& reload_completed
&& operands[0] != operands[1]"
- [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
+ [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
(set (match_dup 3) (match_dup 4))]
"
{
@@ -2052,11 +2057,11 @@
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(and:DI (not:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r")))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
+ (match_operand:DI 1 "s_register_operand" "0,r")))]
"TARGET_ARM"
"#"
"TARGET_ARM && reload_completed"
- [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
+ [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
(set (match_dup 3) (and:SI (not:SI
(ashiftrt:SI (match_dup 2) (const_int 31)))
(match_dup 4)))]
@@ -2339,11 +2344,11 @@
; insns.
(define_split
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
- (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
- (match_operand:SI 3 "arm_rhs_operand" "rI")))
- (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
+ (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
+ (match_operand:SI 3 "arm_rhs_operand" "")))
+ (clobber (match_operand:SI 4 "s_register_operand" ""))]
"TARGET_ARM"
[(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
(not:SI (match_dup 3))))
@@ -3913,7 +3918,7 @@
;; DONE;
;;}")
-;; Recognise garbage generated above.
+;; Recognize garbage generated above.
;;(define_insn ""
;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
@@ -4129,6 +4134,7 @@
if ((val & (mask << i)) == val)
break;
+ /* Shouldn't happen, but we don't want to split if the shift is zero. */
if (i == 0)
FAIL;
@@ -4200,7 +4206,9 @@
(define_insn "pic_add_dot_plus_four"
[(set (match_operand:SI 0 "register_operand" "+r")
- (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
+ (unspec:SI [(plus:SI (match_dup 0)
+ (const (plus:SI (pc) (const_int 4))))]
+ UNSPEC_PIC_BASE))
(use (label_ref (match_operand 1 "" "")))]
"TARGET_THUMB && flag_pic"
"*
@@ -4213,7 +4221,9 @@
(define_insn "pic_add_dot_plus_eight"
[(set (match_operand:SI 0 "register_operand" "+r")
- (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
+ (unspec:SI [(plus:SI (match_dup 0)
+ (const (plus:SI (pc) (const_int 8))))]
+ UNSPEC_PIC_BASE))
(use (label_ref (match_operand 1 "" "")))]
"TARGET_ARM && flag_pic"
"*
@@ -4417,6 +4427,14 @@
emit_insn (gen_movsi (reg, GEN_INT (val)));
operands[1] = gen_lowpart (HImode, reg);
}
+ else if (arm_arch4 && !no_new_pseudos && optimize > 0
+ && GET_CODE (operands[1]) == MEM)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
+ operands[1] = gen_lowpart (HImode, reg);
+ }
else if (!arm_arch4)
{
/* Note: We do not have to worry about TARGET_MMU_TRAPS
@@ -4673,7 +4691,7 @@
"
)
-;; Pattern to recognise insn generated default case above
+;; Pattern to recognize insn generated default case above
(define_insn "*movhi_insn_arch4"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
(match_operand:HI 1 "general_operand" "rI,K,r,m"))]
@@ -4814,9 +4832,16 @@
emit_insn (gen_movsi (reg, operands[1]));
operands[1] = gen_lowpart (QImode, reg);
}
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (QImode, operands[1]);
- }
+ if (GET_CODE (operands[1]) == MEM && optimize > 0)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
+ operands[1] = gen_lowpart (QImode, reg);
+ }
+ if (GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (QImode, operands[1]);
+ }
}
else /* TARGET_THUMB */
{
@@ -6014,7 +6039,7 @@
if (arm_ccfsm_state != 0)
abort ();
- return \"bvs\\t%l0;beq\\t%l0\";
+ return \"bvs\\t%l0\;beq\\t%l0\";
"
[(set_attr "conds" "jump_clob")
(set_attr "length" "8")]
@@ -6031,7 +6056,7 @@
if (arm_ccfsm_state != 0)
abort ();
- return \"bmi\\t%l0;bgt\\t%l0\";
+ return \"bmi\\t%l0\;bgt\\t%l0\";
"
[(set_attr "conds" "jump_clob")
(set_attr "length" "8")]
@@ -6066,7 +6091,7 @@
if (arm_ccfsm_state != 0)
abort ();
- return \"bmi\\t%l0;bgt\\t%l0\";
+ return \"bmi\\t%l0\;bgt\\t%l0\";
"
[(set_attr "conds" "jump_clob")
(set_attr "length" "8")]
@@ -6083,7 +6108,7 @@
if (arm_ccfsm_state != 0)
abort ();
- return \"bvs\\t%l0;beq\\t%l0\";
+ return \"bvs\\t%l0\;beq\\t%l0\";
"
[(set_attr "conds" "jump_clob")
(set_attr "length" "8")]
@@ -6288,8 +6313,12 @@
"
{
enum rtx_code code = GET_CODE (operands[1]);
- rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
+ rtx ccreg;
+
+ if (code == UNEQ || code == LTGT)
+ FAIL;
+ ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
}"
)
@@ -6305,6 +6334,9 @@
enum rtx_code code = GET_CODE (operands[1]);
rtx ccreg;
+ if (code == UNEQ || code == LTGT)
+ FAIL;
+
/* When compiling for SOFT_FLOAT, ensure both arms are in registers.
Otherwise, ensure it is a valid FP add operand */
if ((!TARGET_HARD_FLOAT)
@@ -6325,8 +6357,12 @@
"
{
enum rtx_code code = GET_CODE (operands[1]);
- rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
+ rtx ccreg;
+ if (code == UNEQ || code == LTGT)
+ FAIL;
+
+ ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
}"
)
@@ -6665,8 +6701,8 @@
(define_expand "sibcall"
[(parallel [(call (match_operand 0 "memory_operand" "")
(match_operand 1 "general_operand" ""))
- (use (match_operand 2 "" ""))
- (use (reg:SI LR_REGNUM))])]
+ (return)
+ (use (match_operand 2 "" ""))])]
"TARGET_ARM"
"
{
@@ -6679,8 +6715,8 @@
[(parallel [(set (match_operand 0 "register_operand" "")
(call (match_operand 1 "memory_operand" "")
(match_operand 2 "general_operand" "")))
- (use (match_operand 3 "" ""))
- (use (reg:SI LR_REGNUM))])]
+ (return)
+ (use (match_operand 3 "" ""))])]
"TARGET_ARM"
"
{
@@ -6692,8 +6728,8 @@
(define_insn "*sibcall_insn"
[(call (mem:SI (match_operand:SI 0 "" "X"))
(match_operand 1 "" ""))
- (use (match_operand 2 "" ""))
- (use (reg:SI LR_REGNUM))]
+ (return)
+ (use (match_operand 2 "" ""))]
"TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
"*
return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
@@ -6705,8 +6741,8 @@
[(set (match_operand 0 "s_register_operand" "=r,f")
(call (mem:SI (match_operand:SI 1 "" "X,X"))
(match_operand 2 "" "")))
- (use (match_operand 3 "" ""))
- (use (reg:SI LR_REGNUM))]
+ (return)
+ (use (match_operand 3 "" ""))]
"TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
"*
return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
@@ -6725,7 +6761,7 @@
arm_ccfsm_state += 2;
return \"\";
}
- return output_return_instruction (NULL, TRUE, FALSE);
+ return output_return_instruction (const_true_rtx, TRUE, FALSE);
}"
[(set_attr "type" "load")
(set_attr "predicable" "yes")]
@@ -6771,6 +6807,33 @@
(set_attr "type" "load")]
)
+;; Generate a sequence of instructions to determine if the processor is
+;; in 26-bit or 32-bit mode, and return the appropriate return address
+;; mask.
+
+(define_expand "return_addr_mask"
+ [(set (match_dup 1)
+ (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
+ (const_int 0)))
+ (set (match_operand:SI 0 "s_register_operand" "")
+ (if_then_else:SI (eq (match_dup 1) (const_int 0))
+ (const_int -1)
+ (const_int 67108860)))] ; 0x03fffffc
+ "TARGET_ARM"
+ "
+ operands[1] = gen_rtx_REG (CC_NOOVmode, 24);
+ ")
+
+(define_insn "*check_arch2"
+ [(set (match_operand:CC_NOOV 0 "cc_register" "")
+ (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
+ (const_int 0)))]
+ "TARGET_ARM"
+ "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
+ [(set_attr "length" "8")
+ (set_attr "conds" "set")]
+)
+
;; Call subroutine returning any type.
(define_expand "untyped_call"
@@ -7015,139 +7078,6 @@
]
)
-;; These variants of the above insns can occur if the first operand is the
-;; frame pointer and we eliminate that. This is a kludge, but there doesn't
-;; seem to be a way around it. Most of the predicates have to be null
-;; because the format can be generated part way through reload, so
-;; if we don't match it as soon as it becomes available, reload doesn't know
-;; how to reload pseudos that haven't got hard registers; the constraints will
-;; sort everything out.
-
-(define_insn "*reload_mulsi3"
- [(set (match_operand:SI 0 "" "=&r")
- (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
- [(match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "rM")])
- (match_operand:SI 2 "" "r"))
- (match_operand:SI 1 "const_int_operand" "n")))]
- "TARGET_ARM && reload_in_progress"
- "*
- output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
- operands[2] = operands[1];
- operands[1] = operands[0];
- return output_add_immediate (operands);
- "
- [
- ; we have no idea how long the add_immediate is, it could be up to 4.
- (set_attr "length" "20")]
-)
-
-(define_insn "*reload_mulsi_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (plus:SI
- (plus:SI
- (match_operator:SI 5 "shift_operator"
- [(match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "rM")])
- (match_operand:SI 1 "" "r"))
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))
- (set (match_operand:SI 0 "" "=&r")
- (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
- (match_dup 1))
- (match_dup 2)))]
- "TARGET_ARM && reload_in_progress && !arm_is_xscale"
- "*
- output_add_immediate (operands);
- return \"add%?s\\t%0, %0, %3%S5\";
- "
- [(set_attr "conds" "set")
- (set_attr "shift" "3")
- (set_attr "length" "20")]
-)
-
-(define_insn "*reload_mulsi_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (plus:SI
- (plus:SI
- (match_operator:SI 5 "shift_operator"
- [(match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "rM")])
- (match_operand:SI 1 "" "r"))
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=&r"))]
- "TARGET_ARM && reload_in_progress && !arm_is_xscale"
- "*
- output_add_immediate (operands);
- return \"add%?s\\t%0, %0, %3%S5\";
- "
- [(set_attr "conds" "set")
- (set_attr "shift" "3")
- (set_attr "length" "20")]
-)
-
-;; These are similar, but are needed when the mla pattern contains the
-;; eliminated register as operand 3.
-
-(define_insn "*reload_muladdsi"
- [(set (match_operand:SI 0 "" "=&r,&r")
- (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
- (match_operand:SI 2 "" "r,r"))
- (match_operand:SI 3 "" "r,r"))
- (match_operand:SI 4 "const_int_operand" "n,n")))]
- "TARGET_ARM && reload_in_progress"
- "*
- output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
- operands[2] = operands[4];
- operands[1] = operands[0];
- return output_add_immediate (operands);
- "
- [(set_attr "length" "20")
- (set_attr "type" "mult")]
-)
-
-(define_insn "*reload_muladdsi_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
- (match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "r"))
- (match_operand:SI 1 "" "r"))
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))
- (set (match_operand:SI 0 "" "=&r")
- (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
- (match_dup 2)))]
- "TARGET_ARM && reload_in_progress && !arm_is_xscale"
- "*
- output_add_immediate (operands);
- output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
- return \"\";
- "
- [(set_attr "length" "20")
- (set_attr "conds" "set")
- (set_attr "type" "mult")]
-)
-
-(define_insn "*reload_muladdsi_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
- (match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "r"))
- (match_operand:SI 1 "" "r"))
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=&r"))]
- "TARGET_ARM && reload_in_progress"
- "*
- output_add_immediate (operands);
- return \"mla%?s\\t%0, %3, %4, %0\";
- "
- [(set_attr "length" "20")
- (set_attr "conds" "set")
- (set_attr "type" "mult")]
-)
-
(define_insn "*and_scc"
@@ -8506,7 +8436,7 @@
; We must watch to see that the source/destination register isn't also the
; same as the base address register, and that if the index is a register,
; that it is not the same as the base address register. In such cases the
-; instruction that we would generate would have UNPREDICTABLE behaviour so
+; instruction that we would generate would have UNPREDICTABLE behavior so
; we cannot use it.
(define_peephole
@@ -8759,18 +8689,27 @@
"
)
+;; Note - although unspec_volatile's USE all hard registers,
+;; USEs are ignored after relaod has completed. Thus we need
+;; to add an unspec of the link register to ensure that flow
+;; does not think that it is unused by the sibcall branch that
+;; will replace the standard function epilogue.
(define_insn "sibcall_epilogue"
- [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
+ [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
+ (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
"TARGET_ARM"
"*
- output_asm_insn (\"%@ Sibcall epilogue\", operands);
if (USE_RETURN_INSN (FALSE))
- return output_return_instruction (NULL, FALSE, FALSE);
+ return output_return_instruction (const_true_rtx, FALSE, FALSE);
return arm_output_epilogue (FALSE);
"
;; Length is absolute worst case
[(set_attr "length" "44")
- (set_attr "type" "block")]
+ (set_attr "type" "block")
+ ;; We don't clobber the conditions, but the potential length of this
+ ;; operation is sufficient to make conditionalizing the sequence
+ ;; unlikely to be profitable.
+ (set_attr "conds" "clob")]
)
(define_insn "*epilogue_insns"
@@ -8784,7 +8723,11 @@
"
; Length is absolute worst case
[(set_attr "length" "44")
- (set_attr "type" "block")]
+ (set_attr "type" "block")
+ ;; We don't clobber the conditions, but the potential length of this
+ ;; operation is sufficient to make conditionalizing the sequence
+ ;; unlikely to be profitable.
+ (set_attr "conds" "clob")]
)
(define_expand "eh_epilogue"
@@ -9018,6 +8961,16 @@
[(set_attr "type" "store4")]
)
+(define_insn "stack_tie"
+ [(set (mem:BLK (scratch))
+ (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
+ (match_operand:SI 1 "s_register_operand" "r")]
+ UNSPEC_PRLG_STK))]
+ ""
+ ""
+ [(set_attr "length" "0")]
+)
+
;; Similarly for the floating point registers
(define_insn "*push_fp_multi"
[(match_parallel 2 "multi_register_push"
@@ -9090,9 +9043,9 @@
{
case MODE_FLOAT:
{
- union real_extract u;
- memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
+ REAL_VALUE_TYPE r;
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
+ assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
break;
}
default:
@@ -9114,9 +9067,9 @@
{
case MODE_FLOAT:
{
- union real_extract u;
- memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
+ REAL_VALUE_TYPE r;
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
+ assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
break;
}
default:
diff --git a/contrib/gcc/config/arm/coff.h b/contrib/gcc/config/arm/coff.h
index c9f0d92..0a78268 100644
--- a/contrib/gcc/config/arm/coff.h
+++ b/contrib/gcc/config/arm/coff.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
For ARM with COFF object format.
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000
+ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002
Free Software Foundation, Inc.
Contributed by Doug Evans (devans@cygnus.com).
@@ -40,7 +40,7 @@ Boston, MA 02111-1307, USA. */
#endif
/* This is COFF, but prefer stabs. */
-#define SDB_DEBUGGING_INFO
+#define SDB_DEBUGGING_INFO 1
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
@@ -76,42 +76,12 @@ Boston, MA 02111-1307, USA. */
more efficient, but for Thumb it's better to put them out of band. */
#define JUMP_TABLES_IN_TEXT_SECTION (TARGET_ARM)
-#undef READONLY_DATA_SECTION
-#define READONLY_DATA_SECTION rdata_section
-#undef RDATA_SECTION_ASM_OP
-#define RDATA_SECTION_ASM_OP "\t.section .rdata"
+#undef READONLY_DATA_SECTION_ASM_OP
+#define READONLY_DATA_SECTION_ASM_OP "\t.section .rdata"
#undef CTORS_SECTION_ASM_OP
#define CTORS_SECTION_ASM_OP "\t.section .ctors,\"x\""
#undef DTORS_SECTION_ASM_OP
#define DTORS_SECTION_ASM_OP "\t.section .dtors,\"x\""
-
-/* A list of other sections which the compiler might be "in" at any
- given time. */
-
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS SUBTARGET_EXTRA_SECTIONS in_rdata
-
-#define SUBTARGET_EXTRA_SECTIONS
-
-/* A list of extra section function definitions. */
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- RDATA_SECTION_FUNCTION \
- SUBTARGET_EXTRA_SECTION_FUNCTIONS
-
-#define SUBTARGET_EXTRA_SECTION_FUNCTIONS
-
-#define RDATA_SECTION_FUNCTION \
-void \
-rdata_section () \
-{ \
- if (in_section != in_rdata) \
- { \
- fprintf (asm_out_file, "%s\n", RDATA_SECTION_ASM_OP); \
- in_section = in_rdata; \
- } \
-}
/* Support the ctors/dtors sections for g++. */
diff --git a/contrib/gcc/config/arm/conix-elf.h b/contrib/gcc/config/arm/conix-elf.h
index b74afdf..4a137d6 100644
--- a/contrib/gcc/config/arm/conix-elf.h
+++ b/contrib/gcc/config/arm/conix-elf.h
@@ -39,6 +39,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm7tdmi
#endif
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
- "-D__arm__ -D__CONIX__ -D__ELF__"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__CONIX__"); \
+ builtin_define ("__ELF__"); \
+ } while (0)
diff --git a/contrib/gcc/config/arm/crti.asm b/contrib/gcc/config/arm/crti.asm
index f3741db..ac58e44 100644
--- a/contrib/gcc/config/arm/crti.asm
+++ b/contrib/gcc/config/arm/crti.asm
@@ -35,7 +35,7 @@
# .init sections. Users may put any desired instructions in those
# sections.
- # Note - this macro is complimented by the FUNC_END macro
+ # Note - this macro is complemented by the FUNC_END macro
# in crtn.asm. If you change this macro you must also change
# that macro match.
.macro FUNC_START
diff --git a/contrib/gcc/config/arm/crtn.asm b/contrib/gcc/config/arm/crtn.asm
index a7f0e9e..2f4b542 100644
--- a/contrib/gcc/config/arm/crtn.asm
+++ b/contrib/gcc/config/arm/crtn.asm
@@ -35,7 +35,7 @@
# fact return. Users may put any desired instructions in those sections.
# This file is the last thing linked into any executable.
- # Note - this macro is complimented by the FUNC_START macro
+ # Note - this macro is complemented by the FUNC_START macro
# in crti.asm. If you change this macro you must also change
# that macro match.
#
diff --git a/contrib/gcc/config/arm/elf.h b/contrib/gcc/config/arm/elf.h
index 1cab2c4..0ad23f8 100644
--- a/contrib/gcc/config/arm/elf.h
+++ b/contrib/gcc/config/arm/elf.h
@@ -36,21 +36,27 @@ Boston, MA 02111-1307, USA. */
#ifndef SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS \
- { "subtarget_extra_asm_spec", SUBTARGET_EXTRA_ASM_SPEC },
+ { "subtarget_extra_asm_spec", SUBTARGET_EXTRA_ASM_SPEC }, \
+ { "subtarget_asm_float_spec", SUBTARGET_ASM_FLOAT_SPEC },
#endif
#ifndef SUBTARGET_EXTRA_ASM_SPEC
#define SUBTARGET_EXTRA_ASM_SPEC ""
#endif
+#ifndef SUBTARGET_ASM_FLOAT_SPEC
+#define SUBTARGET_ASM_FLOAT_SPEC "\
+%{mapcs-float:-mfloat} %{msoft-float:-mno-fpu}"
+#endif
+
#ifndef ASM_SPEC
#define ASM_SPEC "\
%{mbig-endian:-EB} \
-%{mcpu=*:-m%*} \
-%{march=*:-m%*} \
+%{mlittle-endian:-EL} \
+%{mcpu=*:-mcpu=%*} \
+%{march=*:-march=%*} \
%{mapcs-*:-mapcs-%*} \
-%{mapcs-float:-mfloat} \
-%{msoft-float:-mno-fpu} \
+%(subtarget_asm_float_spec) \
%{mthumb-interwork:-mthumb-interwork} \
%(subtarget_extra_asm_spec)"
#endif
@@ -58,22 +64,18 @@ Boston, MA 02111-1307, USA. */
/* The ARM uses @ are a comment character so we need to redefine
TYPE_OPERAND_FMT. */
#undef TYPE_OPERAND_FMT
-#define TYPE_OPERAND_FMT "%s"
+#define TYPE_OPERAND_FMT "%%%s"
/* We might need a ARM specific header to function declarations. */
#undef ASM_DECLARE_FUNCTION_NAME
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
- do \
- { \
- ARM_DECLARE_FUNCTION_NAME (FILE, NAME, DECL); \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
- putc ('\n', FILE); \
- ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
- ASM_OUTPUT_LABEL(FILE, NAME); \
- } \
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ ARM_DECLARE_FUNCTION_NAME (FILE, NAME, DECL); \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
+ ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
+ ASM_OUTPUT_LABEL(FILE, NAME); \
+ } \
while (0)
/* We might need an ARM specific trailer for function declarations. */
@@ -83,20 +85,7 @@ Boston, MA 02111-1307, USA. */
{ \
ARM_DECLARE_FUNCTION_SIZE (FILE, FNAME, DECL); \
if (!flag_inhibit_size_directive) \
- { \
- char label[256]; \
- static int labelno; \
- labelno ++; \
- ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \
- ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, (FNAME)); \
- fprintf (FILE, ","); \
- assemble_name (FILE, label); \
- fprintf (FILE, "-"); \
- assemble_name (FILE, (FNAME)); \
- putc ('\n', FILE); \
- } \
+ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
} \
while (0)
@@ -108,7 +97,7 @@ Boston, MA 02111-1307, USA. */
#define JUMP_TABLES_IN_TEXT_SECTION (TARGET_ARM)
#ifndef LINK_SPEC
-#define LINK_SPEC "%{mbig-endian:-EB} -X"
+#define LINK_SPEC "%{mbig-endian:-EB} %{mlittle-endian:-EL} -X"
#endif
/* Run-time Target Specification. */
diff --git a/contrib/gcc/config/arm/freebsd.h b/contrib/gcc/config/arm/freebsd.h
index a9b268c..0d417a2 100644
--- a/contrib/gcc/config/arm/freebsd.h
+++ b/contrib/gcc/config/arm/freebsd.h
@@ -41,9 +41,6 @@ Boston, MA 02111-1307, USA. */
/* We use the GCC defaults here. */
#undef WCHAR_TYPE
-#undef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
-
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
diff --git a/contrib/gcc/config/arm/linux-elf.h b/contrib/gcc/config/arm/linux-elf.h
index f1c86d2..c6d14e7 100644
--- a/contrib/gcc/config/arm/linux-elf.h
+++ b/contrib/gcc/config/arm/linux-elf.h
@@ -48,9 +48,9 @@ Boston, MA 02111-1307, USA. */
/* Now we define the strings used to build the spec file. */
#define LIB_SPEC \
- "%{shared: -lc} \
- %{!shared: %{pthread:-lpthread} \
- %{profile:-lc_p} %{!profile: -lc}}"
+ "%{pthread:-lpthread} \
+ %{shared:-lc} \
+ %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
#define LIBGCC_SPEC "%{msoft-float:-lfloat} -lgcc"
@@ -89,13 +89,15 @@ Boston, MA 02111-1307, USA. */
%{mbig-endian:-EB}" \
SUBTARGET_EXTRA_LINK_SPEC
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
-"-Dunix -D__gnu_linux__ -Dlinux -D__ELF__ \
--Asystem=unix -Asystem=posix"
-
-/* Allow #sccs in preprocessor. */
-#define SCCS_DIRECTIVE
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("linux"); \
+ builtin_define ("__gnu_linux__"); \
+ builtin_define ("__ELF__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=posix"); \
+ } while (0)
/* This is how we tell the assembler that two symbols have the same value. */
#define ASM_OUTPUT_DEF(FILE, NAME1, NAME2) \
diff --git a/contrib/gcc/config/arm/linux-gas.h b/contrib/gcc/config/arm/linux-gas.h
index b4e346d..5e8ddf9 100644
--- a/contrib/gcc/config/arm/linux-gas.h
+++ b/contrib/gcc/config/arm/linux-gas.h
@@ -45,7 +45,7 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
-/* Emit code to set up a trampoline and synchronise the caches. */
+/* Emit code to set up a trampoline and synchronize the caches. */
#undef INITIALIZE_TRAMPOLINE
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
{ \
diff --git a/contrib/gcc/config/arm/netbsd-elf.h b/contrib/gcc/config/arm/netbsd-elf.h
new file mode 100644
index 0000000..0d5b798
--- /dev/null
+++ b/contrib/gcc/config/arm/netbsd-elf.h
@@ -0,0 +1,177 @@
+/* Definitions of target machine for GNU compiler, NetBSD/arm ELF version.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Wasabi Systems, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Run-time Target Specification. */
+#undef TARGET_VERSION
+#define TARGET_VERSION fputs (" (NetBSD/arm ELF)", stderr);
+
+/* This is used in ASM_FILE_START. */
+#undef ARM_OS_NAME
+#define ARM_OS_NAME "NetBSD"
+
+/* arm.h defaults to ARM6 CPU. */
+
+/* This defaults us to little-endian. */
+#ifndef TARGET_ENDIAN_DEFAULT
+#define TARGET_ENDIAN_DEFAULT 0
+#endif
+
+#undef MULTILIB_DEFAULTS
+
+/* Default it to use ATPCS with soft-VFP. */
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT \
+ (ARM_FLAG_APCS_32 \
+ | ARM_FLAG_SOFT_FLOAT \
+ | ARM_FLAG_APCS_FRAME \
+ | ARM_FLAG_ATPCS \
+ | ARM_FLAG_VFP \
+ | ARM_FLAG_MMU_TRAPS \
+ | TARGET_ENDIAN_DEFAULT)
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ NETBSD_OS_CPP_BUILTINS_ELF(); \
+ } \
+ while (0)
+
+#undef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC NETBSD_CPP_SPEC
+
+#undef SUBTARGET_EXTRA_ASM_SPEC
+#define SUBTARGET_EXTRA_ASM_SPEC \
+ "-matpcs %{fpic:-k} %{fPIC:-k}"
+
+/* Default floating point model is soft-VFP.
+ FIXME: -mhard-float currently implies FPA. */
+#undef SUBTARGET_ASM_FLOAT_SPEC
+#define SUBTARGET_ASM_FLOAT_SPEC \
+ "%{mhard-float:-mfpu=fpa} \
+ %{msoft-float:-mfpu=softvfp} \
+ %{!mhard-float: \
+ %{!msoft-float:-mfpu=softvfp}}"
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "subtarget_extra_asm_spec", SUBTARGET_EXTRA_ASM_SPEC }, \
+ { "subtarget_asm_float_spec", SUBTARGET_ASM_FLOAT_SPEC }, \
+ { "netbsd_link_spec", NETBSD_LINK_SPEC_ELF }, \
+ { "netbsd_entry_point", NETBSD_ENTRY_POINT },
+
+#define NETBSD_ENTRY_POINT "__start"
+
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "-X %{mbig-endian:-EB} %{mlittle-endian:-EL} \
+ %(netbsd_link_spec)"
+
+/* Make GCC agree with <machine/ansi.h>. */
+
+#undef SIZE_TYPE
+#define SIZE_TYPE "long unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
+
+/* We don't have any limit on the length as out debugger is GDB. */
+#undef DBX_CONTIN_LENGTH
+
+/* NetBSD does its profiling differently to the Acorn compiler. We
+ don't need a word following the mcount call; and to skip it
+ requires either an assembly stub or use of fomit-frame-pointer when
+ compiling the profiling functions. Since we break Acorn CC
+ compatibility below a little more won't hurt. */
+
+#undef ARM_FUNCTION_PROFILER
+#define ARM_FUNCTION_PROFILER(STREAM,LABELNO) \
+{ \
+ asm_fprintf (STREAM, "\tmov\t%Rip, %Rlr\n"); \
+ asm_fprintf (STREAM, "\tbl\t__mcount%s\n", \
+ NEED_PLT_RELOC ? "(PLT)" : ""); \
+}
+
+/* VERY BIG NOTE: Change of structure alignment for NetBSD/arm.
+ There are consequences you should be aware of...
+
+ Normally GCC/arm uses a structure alignment of 32 for compatibility
+ with armcc. This means that structures are padded to a word
+ boundary. However this causes problems with bugged NetBSD kernel
+ code (possibly userland code as well - I have not checked every
+ binary). The nature of this bugged code is to rely on sizeof()
+ returning the correct size of various structures rounded to the
+ nearest byte (SCSI and ether code are two examples, the vm system
+ is another). This code breaks when the structure alignment is 32
+ as sizeof() will report a word=rounded size. By changing the
+ structure alignment to 8. GCC will conform to what is expected by
+ NetBSD.
+
+ This has several side effects that should be considered.
+ 1. Structures will only be aligned to the size of the largest member.
+ i.e. structures containing only bytes will be byte aligned.
+ structures containing shorts will be half word alinged.
+ structures containing ints will be word aligned.
+
+ This means structures should be padded to a word boundary if
+ alignment of 32 is required for byte structures etc.
+
+ 2. A potential performance penalty may exist if strings are no longer
+ word aligned. GCC will not be able to use word load/stores to copy
+ short strings.
+
+ This modification is not encouraged but with the present state of the
+ NetBSD source tree it is currently the only solution that meets the
+ requirements. */
+
+#undef DEFAULT_STRUCTURE_SIZE_BOUNDARY
+#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
+
+/* Emit code to set up a trampoline and synchronize the caches. */
+#undef INITIALIZE_TRAMPOLINE
+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
+do \
+ { \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 8)), \
+ (CXT)); \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 12)), \
+ (FNADDR)); \
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"), \
+ 0, VOIDmode, 2, TRAMP, Pmode, \
+ plus_constant (TRAMP, TRAMPOLINE_SIZE), Pmode); \
+ } \
+while (0)
+
+/* Clear the instruction cache from `BEG' to `END'. This makes a
+ call to the ARM_SYNC_ICACHE architecture specific syscall. */
+#define CLEAR_INSN_CACHE(BEG, END) \
+do \
+ { \
+ extern int sysarch(int number, void *args); \
+ struct \
+ { \
+ unsigned int addr; \
+ int len; \
+ } s; \
+ s.addr = (unsigned int)(BEG); \
+ s.len = (END) - (BEG); \
+ (void) sysarch (0, &s); \
+ } \
+while (0)
diff --git a/contrib/gcc/config/arm/netbsd.h b/contrib/gcc/config/arm/netbsd.h
index 2be49d8..38ccc3f 100644
--- a/contrib/gcc/config/arm/netbsd.h
+++ b/contrib/gcc/config/arm/netbsd.h
@@ -44,16 +44,22 @@ Boston, MA 02111-1307, USA. */
/* Some defines for CPP.
arm32 is the NetBSD port name, so we always define arm32 and __arm32__. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "\
--Dunix -Driscbsd -Darm32 -D__arm32__ -D__arm__ -D__NetBSD__ \
--Asystem=unix -Asystem=NetBSD"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ NETBSD_OS_CPP_BUILTINS_AOUT(); \
+ builtin_define_std ("arm32"); \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("riscbsd"); \
+ } while (0)
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "netbsd_cpp_spec", NETBSD_CPP_SPEC }, \
+ { "netbsd_link_spec", NETBSD_LINK_SPEC_AOUT },
-/* Define _POSIX_SOURCE if necessary. */
#undef CPP_SPEC
#define CPP_SPEC "\
-%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) %(cpp_endian) \
-%{posix:-D_POSIX_SOURCE} \
+%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) %(cpp_endian) %(netbsd_cpp_spec) \
"
/* Because TARGET_DEFAULT sets ARM_FLAG_APCS_32 */
@@ -66,10 +72,7 @@ Boston, MA 02111-1307, USA. */
/* Pass -X to the linker so that it will strip symbols starting with 'L' */
#undef LINK_SPEC
-#define LINK_SPEC "\
--X %{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{R*} \
-%{static:-Bstatic}} %{shared} %{assert*} \
-"
+#define LINK_SPEC "-X %(netbsd_link_spec)"
#undef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
@@ -77,7 +80,7 @@ Boston, MA 02111-1307, USA. */
#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE "int"
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
/* We don't have any limit on the length as out debugger is GDB. */
#undef DBX_CONTIN_LENGTH
@@ -142,3 +145,30 @@ Boston, MA 02111-1307, USA. */
requirements. */
#undef DEFAULT_STRUCTURE_SIZE_BOUNDARY
#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
+
+/* Emit code to set up a trampoline and synchronize the caches. */
+#undef INITIALIZE_TRAMPOLINE
+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
+{ \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 8)), \
+ (CXT)); \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 12)), \
+ (FNADDR)); \
+ 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 a
+ call to the ARM32_SYNC_ICACHE architecture specific syscall. */
+#define CLEAR_INSN_CACHE(BEG, END) \
+{ \
+ extern int sysarch(int number, void *args); \
+ struct { \
+ unsigned int addr; \
+ int len; \
+ } s; \
+ s.addr = (unsigned int)(BEG); \
+ s.len = (END) - (BEG); \
+ (void)sysarch(0, &s); \
+}
diff --git a/contrib/gcc/config/arm/pe.c b/contrib/gcc/config/arm/pe.c
index 8360f85..ee3da8f 100644
--- a/contrib/gcc/config/arm/pe.c
+++ b/contrib/gcc/config/arm/pe.c
@@ -1,5 +1,5 @@
/* Routines for GCC for ARM/pe.
- Copyright (C) 1995, 1996, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Doug Evans (dje@cygnus.com).
This file is part of GNU CC.
@@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */
extern int current_function_anonymous_args;
-/* Return non-zero if DECL is a dllexport'd object. */
+/* Return nonzero if DECL is a dllexport'd object. */
tree current_class_type; /* FIXME */
@@ -52,7 +52,7 @@ arm_dllexport_p (decl)
return 0;
}
-/* Return non-zero if DECL is a dllimport'd object. */
+/* Return nonzero if DECL is a dllimport'd object. */
int
arm_dllimport_p (decl)
@@ -74,7 +74,7 @@ arm_dllimport_p (decl)
return 0;
}
-/* Return non-zero if SYMBOL is marked as being dllexport'd. */
+/* Return nonzero if SYMBOL is marked as being dllexport'd. */
int
arm_dllexport_name_p (symbol)
@@ -83,7 +83,7 @@ arm_dllexport_name_p (symbol)
return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'e' && symbol[2] == '.';
}
-/* Return non-zero if SYMBOL is marked as being dllimport'd. */
+/* Return nonzero if SYMBOL is marked as being dllimport'd. */
int
arm_dllimport_name_p (symbol)
@@ -204,13 +204,12 @@ arm_mark_dllimport (decl)
XEXP (DECL_RTL (decl), 0) = newrtl;
}
-/* Cover function to implement ENCODE_SECTION_INFO. */
-
void
-arm_pe_encode_section_info (decl)
+arm_pe_encode_section_info (decl, first)
tree decl;
+ int first ATTRIBUTE_UNUSED;
{
- /* This bit is copied from arm.h. */
+ /* This bit is copied from arm_encode_section_info. */
if (optimize > 0 && TREE_CONSTANT (decl)
&& (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
{
@@ -247,8 +246,6 @@ arm_pe_encode_section_info (decl)
}
}
-/* Cover function for UNIQUE_SECTION. */
-
void
arm_pe_unique_section (decl, reloc)
tree decl;
@@ -260,15 +257,14 @@ arm_pe_unique_section (decl, reloc)
const char * prefix;
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- /* Strip off any encoding in fnname. */
- STRIP_NAME_ENCODING (name, name);
+ name = arm_strip_name_encoding (name);
/* The object is put in, for example, section .text$foo.
The linker will then ultimately place them in .text
(everything from the $ on is stripped). */
if (TREE_CODE (decl) == FUNCTION_DECL)
prefix = ".text$";
- else if (DECL_READONLY_SECTION (decl, reloc))
+ else if (decl_readonly_section (decl, reloc))
prefix = ".rdata$";
else
prefix = ".data$";
diff --git a/contrib/gcc/config/arm/pe.h b/contrib/gcc/config/arm/pe.h
index 1182aac..38727da 100644
--- a/contrib/gcc/config/arm/pe.h
+++ b/contrib/gcc/config/arm/pe.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for ARM with PE obj format.
- Copyright (C) 1995, 1996, 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1999, 2000, 2002 Free Software Foundation, Inc.
Contributed by Doug Evans (dje@cygnus.com).
This file is part of GNU CC.
@@ -94,30 +94,13 @@ Boston, MA 02111-1307, USA. */
1,1,1 \
}
-/* In addition to the stuff done in arm.h, we must mark dll symbols specially.
- Definitions of dllexport'd objects install some info in the .drectve
- section. References to dllimport'd objects are fetched indirectly via
- __imp_. If both are declared, dllexport overrides.
- This is also needed to implement one-only vtables: they go into their own
- section and we need to set DECL_SECTION_NAME so we do that here.
- Note that we can be called twice on the same decl. */
-#undef ENCODE_SECTION_INFO
-#define ENCODE_SECTION_INFO(DECL) \
- arm_pe_encode_section_info (DECL)
-
-/* Used to implement dllexport overriding dllimport semantics. It's also used
- to handle vtables - the first pass won't do anything because
- DECL_CONTEXT (DECL) will be 0 so arm_dll{ex,im}port_p will return 0.
- It's also used to handle dllimport override semantics. */
-#define REDO_SECTION_INFO_P(DECL) 1
-
/* Define this macro if in some cases global symbols from one translation
unit may not be bound to undefined symbols in another translation unit
without user intervention. For instance, under Microsoft Windows
symbols must be explicitly imported from shared libraries (DLLs). */
#define MULTIPLE_SYMBOL_SPACES
-#define UNIQUE_SECTION(DECL, RELOC) arm_pe_unique_section (DECL, RELOC)
+#define TARGET_ASM_UNIQUE_SECTION arm_pe_unique_section
#define SUPPORTS_ONE_ONLY 1
@@ -206,13 +189,13 @@ Boston, MA 02111-1307, USA. */
/* A list of other sections which the compiler might be "in" at any
given time. */
-#undef SUBTARGET_EXTRA_SECTIONS
-#define SUBTARGET_EXTRA_SECTIONS in_drectve,
+#undef EXTRA_SECTIONS
+#define EXTRA_SECTIONS in_drectve
/* A list of extra section function definitions. */
-#undef SUBTARGET_EXTRA_SECTION_FUNCTIONS
-#define SUBTARGET_EXTRA_SECTION_FUNCTIONS \
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS \
DRECTVE_SECTION_FUNCTION \
SWITCH_TO_SECTION_FUNCTION
@@ -245,7 +228,7 @@ switch_to_section (section, decl) \
case in_text: text_section (); break; \
case in_data: data_section (); break; \
case in_named: named_section (decl, NULL, 0); break; \
- case in_rdata: rdata_section (); break; \
+ case in_readonly_data: readonly_data_section (); break; \
case in_ctors: ctors_section (); break; \
case in_dtors: dtors_section (); break; \
case in_drectve: drectve_section (); break; \
diff --git a/contrib/gcc/config/arm/rtems-elf.h b/contrib/gcc/config/arm/rtems-elf.h
index 312c96f..27928db 100644
--- a/contrib/gcc/config/arm/rtems-elf.h
+++ b/contrib/gcc/config/arm/rtems-elf.h
@@ -24,5 +24,9 @@ Boston, MA 02111-1307, USA. */
#define HAS_INIT_SECTION
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__rtems__ -D__ELF__ -Asystem=rtems"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__rtems__"); \
+ builtin_define ("__ELF__"); \
+ builtin_assert ("system=rtems"); \
+ } while (0)
diff --git a/contrib/gcc/config/arm/semi.h b/contrib/gcc/config/arm/semi.h
index 54ea0e8b..2e1abd4 100644
--- a/contrib/gcc/config/arm/semi.h
+++ b/contrib/gcc/config/arm/semi.h
@@ -61,8 +61,8 @@ Boston, MA 02111-1307, USA. */
#define ASM_SPEC "\
%{fpic: -k} %{fPIC: -k} \
%{mbig-endian:-EB} \
-%{mcpu=*:-m%*} \
-%{march=*:-m%*} \
+%{mcpu=*:-mcpu=%*} \
+%{march=*:-march=%*} \
%{mapcs-float:-mfloat} \
%{msoft-float:-mno-fpu} \
%{mthumb-interwork:-mthumb-interwork} \
diff --git a/contrib/gcc/config/arm/semiaof.h b/contrib/gcc/config/arm/semiaof.h
index 7ca68bc..6ee17ef 100644
--- a/contrib/gcc/config/arm/semiaof.h
+++ b/contrib/gcc/config/arm/semiaof.h
@@ -20,8 +20,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. */
-#define CPP_PREDEFINES \
- "-Darm -Dsemi"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define_std ("arm"); \
+ builtin_define_std ("semi"); \
+ } while (0)
#define ASM_SPEC "%{g -g} -arch 4 \
-apcs 3%{mapcs-32:/32bit}%{mapcs-26:/26bit}%{!mapcs-26:%{!macps-32:/32bit}}"
diff --git a/contrib/gcc/config/arm/t-arm-elf b/contrib/gcc/config/arm/t-arm-elf
index d94b5d2..0011b2a 100644
--- a/contrib/gcc/config/arm/t-arm-elf
+++ b/contrib/gcc/config/arm/t-arm-elf
@@ -25,16 +25,18 @@ MULTILIB_OPTIONS = marm/mthumb
MULTILIB_DIRNAMES = arm thumb
MULTILIB_EXCEPTIONS =
-# MULTILIB_OPTIONS = mlittle-endian/mbig-endian
-# MULTILIB_DIRNAMES = le be
+# MULTILIB_OPTIONS += mlittle-endian/mbig-endian
+# MULTILIB_DIRNAMES += le be
# MULTILIB_EXCEPTIONS =
# MULTILIB_MATCHES = mbig-endian=mbe mlittle-endian=mle
#
# MULTILIB_OPTIONS += mhard-float/msoft-float
# MULTILIB_DIRNAMES += fpu soft
+# MULTILIB_EXCEPTIONS += *mthumb/*mhard-float*
#
# MULTILIB_OPTIONS += mapcs-32/mapcs-26
# MULTILIB_DIRNAMES += 32bit 26bit
+# MULTILIB_EXCEPTIONS += *mthumb/*mapcs-26*
#
# MULTILIB_OPTIONS += mno-thumb-interwork/mthumb-interwork
# MULTILIB_DIRNAMES += normal interwork
diff --git a/contrib/gcc/config/arm/t-pe b/contrib/gcc/config/arm/t-pe
index 4de3665..f559bd2 100644
--- a/contrib/gcc/config/arm/t-pe
+++ b/contrib/gcc/config/arm/t-pe
@@ -20,7 +20,8 @@ dp-bit.c: $(srcdir)/config/fp-bit.c
echo '#endif' >> dp-bit.c
cat $(srcdir)/config/fp-bit.c >> dp-bit.c
-pe.o: $(srcdir)/config/arm/pe.c
+pe.o: $(srcdir)/config/arm/pe.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) output.h \
+ flags.h $(TREE_H) $(EXPR_H) toplev.h $(TM_P_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/arm/pe.c
MULTILIB_OPTIONS = mhard-float mthumb
diff --git a/contrib/gcc/config/arm/unknown-elf-oabi.h b/contrib/gcc/config/arm/unknown-elf-oabi.h
index cc58f3a..91f18c0 100644
--- a/contrib/gcc/config/arm/unknown-elf-oabi.h
+++ b/contrib/gcc/config/arm/unknown-elf-oabi.h
@@ -23,10 +23,7 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fputs (" (ARM/ELF non-Linux old abi)", stderr);
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Darm_oabi -Darm -Darm_elf -Acpu=arm -Amachine=arm -D__ELF__"
-
#undef ASM_SPEC
-#define ASM_SPEC "-moabi %{mbig-endian:-EB} %{mcpu=*:-m%*} %{march=*:-m%*} \
+#define ASM_SPEC "-moabi %{mbig-endian:-EB} %{mcpu=*:-mcpu=%*} %{march=*:-march=%*} \
%{mapcs-*:-mapcs-%*} %{mthumb-interwork:-mthumb-interwork}"
diff --git a/contrib/gcc/config/arm/unknown-elf.h b/contrib/gcc/config/arm/unknown-elf.h
index 0741884..7f9211b 100644
--- a/contrib/gcc/config/arm/unknown-elf.h
+++ b/contrib/gcc/config/arm/unknown-elf.h
@@ -47,7 +47,7 @@ Boston, MA 02111-1307, USA. */
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-/* Return a non-zero value if DECL has a section attribute. */
+/* Return a nonzero value if DECL has a section attribute. */
#define IN_NAMED_SECTION(DECL) \
((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \
&& DECL_SECTION_NAME (DECL) != NULL_TREE)
@@ -61,7 +61,7 @@ Boston, MA 02111-1307, USA. */
else \
bss_section (); \
\
- ASM_GLOBALIZE_LABEL (FILE, NAME); \
+ (*targetm.asm_out.globalize_label) (FILE, NAME); \
\
ASM_OUTPUT_ALIGN (FILE, floor_log2 (ALIGN / BITS_PER_UNIT)); \
\
@@ -82,14 +82,10 @@ Boston, MA 02111-1307, USA. */
\
ASM_OUTPUT_ALIGN (FILE, floor_log2 (ALIGN / BITS_PER_UNIT)); \
ASM_OUTPUT_LABEL (FILE, NAME); \
- fprintf (FILE, "\t.space\t%d\n", SIZE); \
+ fprintf (FILE, "\t.space\t%d\n", SIZE ? SIZE : 1); \
} \
while (0)
-#ifndef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__"
-#endif
-
#ifndef CPP_APCS_PC_DEFAULT_SPEC
#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
#endif
diff --git a/contrib/gcc/config/arm/vxarm.h b/contrib/gcc/config/arm/vxarm.h
index 7559364..473362e 100644
--- a/contrib/gcc/config/arm/vxarm.h
+++ b/contrib/gcc/config/arm/vxarm.h
@@ -37,8 +37,10 @@ Boston, MA 02111-1307, USA. */
%{!mcpu*:%{!march=*:-DCPU=ARM710A}} \
"
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__vxworks -Acpu=arm -Amachine=arm"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__vxworks"); \
+ } while (0)
/* VxWorks does all the library stuff itself. */
#undef LIB_SPEC
diff --git a/contrib/gcc/config/arm/xscale-coff.h b/contrib/gcc/config/arm/xscale-coff.h
index 51fe693..d8fee7d 100644
--- a/contrib/gcc/config/arm/xscale-coff.h
+++ b/contrib/gcc/config/arm/xscale-coff.h
@@ -24,7 +24,7 @@
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_xscale
#undef SUBTARGET_EXTRA_ASM_SPEC
-#define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mxscale}"
+#define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale}"
#undef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS \
diff --git a/contrib/gcc/config/arm/xscale-elf.h b/contrib/gcc/config/arm/xscale-elf.h
index b1ce04e..8ea3588 100644
--- a/contrib/gcc/config/arm/xscale-elf.h
+++ b/contrib/gcc/config/arm/xscale-elf.h
@@ -28,7 +28,7 @@ Boston, MA 02111-1307, USA. */
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_xscale
#endif
-#define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mxscale} %{!mhard-float:-mno-fpu}"
+#define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale} %{!mhard-float:-mno-fpu}"
#ifndef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS \
diff --git a/contrib/gcc/config/darwin-c.c b/contrib/gcc/config/darwin-c.c
index 10ffaf0..c04c2b5 100644
--- a/contrib/gcc/config/darwin-c.c
+++ b/contrib/gcc/config/darwin-c.c
@@ -25,7 +25,6 @@ Boston, MA 02111-1307, USA. */
#include "cpplib.h"
#include "tree.h"
#include "c-pragma.h"
-#include "c-lex.h"
#include "c-tree.h"
#include "toplev.h"
#include "tm_p.h"
@@ -91,7 +90,7 @@ void
darwin_pragma_options (pfile)
cpp_reader *pfile ATTRIBUTE_UNUSED;
{
- char *arg;
+ const char *arg;
tree t, x;
if (c_lex (&t) != CPP_NAME)
diff --git a/contrib/gcc/config/darwin-crt2.c b/contrib/gcc/config/darwin-crt2.c
new file mode 100644
index 0000000..1ea2413
--- /dev/null
+++ b/contrib/gcc/config/darwin-crt2.c
@@ -0,0 +1,151 @@
+/* KeyMgr backwards-compatibility support for Darwin.
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+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 into combinations with other programs,
+and to distribute those combinations 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 a combine
+executable.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+/* It is incorrect to include config.h here, because this file is being
+ compiled for the target, and hence definitions concerning only the host
+ do not apply. */
+
+#include "tconfig.h"
+#include "tsystem.h"
+
+/* Homemade decls substituting for getsect.h and dyld.h, so cross
+ compilation works. */
+struct mach_header;
+extern char *getsectdatafromheader (struct mach_header *, const char *,
+ const char *, unsigned long *);
+extern void _dyld_register_func_for_add_image
+ (void (*) (struct mach_header *, unsigned long));
+extern void _dyld_register_func_for_remove_image
+ (void (*) (struct mach_header *, unsigned long));
+
+extern void __darwin_gcc3_preregister_frame_info (void);
+
+/* These are from "keymgr.h". */
+extern void _init_keymgr (void);
+extern void *_keymgr_get_and_lock_processwide_ptr (unsigned key);
+extern void _keymgr_set_and_unlock_processwide_ptr (unsigned key, void *ptr);
+
+extern void *__keymgr_global[];
+typedef struct _Sinfo_Node {
+ unsigned int size ; /*size of this node*/
+ unsigned short major_version ; /*API major version.*/
+ unsigned short minor_version ; /*API minor version.*/
+ } _Tinfo_Node ;
+
+/* KeyMgr 3.x is the first one supporting GCC3 stuff natively. */
+#define KEYMGR_API_MAJOR_GCC3 3
+/* ... with these keys. */
+#define KEYMGR_GCC3_LIVE_IMAGE_LIST 301 /* loaded images */
+#define KEYMGR_GCC3_DW2_OBJ_LIST 302 /* Dwarf2 object list */
+
+/* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST. Info about each resident image. */
+struct live_images {
+ unsigned long this_size; /* sizeof (live_images) */
+ struct mach_header *mh; /* the image info */
+ unsigned long vm_slide;
+ void (*destructor)(struct live_images *); /* destructor for this */
+ struct live_images *next;
+ unsigned int examined_p;
+ void *fde;
+ void *object_info;
+ unsigned long info[2]; /* Future use. */
+};
+
+
+/* These routines are used only on Darwin versions before 10.2.
+ Later versions have equivalent code in the system.
+ Eventually, they might go away, although it might be a long time... */
+
+static void darwin_unwind_dyld_remove_image_hook
+ (struct mach_header *m, unsigned long s);
+static void darwin_unwind_dyld_remove_image_hook
+ (struct mach_header *m, unsigned long s);
+extern void __darwin_gcc3_preregister_frame_info (void);
+
+static void
+darwin_unwind_dyld_add_image_hook (struct mach_header *mh, unsigned long slide)
+{
+ struct live_images *l = (struct live_images *)calloc (1, sizeof (*l));
+ l->mh = mh;
+ l->vm_slide = slide;
+ l->this_size = sizeof (*l);
+ l->next = (struct live_images *)
+ _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
+ _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST, l);
+}
+
+static void
+darwin_unwind_dyld_remove_image_hook (struct mach_header *m, unsigned long s)
+{
+ struct live_images *top, **lip, *destroy = NULL;
+
+ /* Look for it in the list of live images and delete it. */
+
+ top = (struct live_images *)
+ _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
+ for (lip = &top; *lip != NULL; lip = &(*lip)->next)
+ {
+ if ((*lip)->mh == m && (*lip)->vm_slide == s)
+ {
+ destroy = *lip;
+ *lip = destroy->next; /* unlink DESTROY */
+
+ if (destroy->this_size != sizeof (*destroy)) /* sanity check */
+ abort ();
+
+ break;
+ }
+ }
+ _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST, top);
+
+ /* Now that we have unlinked this from the image list, toss it. */
+ if (destroy != NULL)
+ {
+ if (destroy->destructor != NULL)
+ (*destroy->destructor) (destroy);
+ free (destroy);
+ }
+}
+
+void
+__darwin_gcc3_preregister_frame_info (void)
+{
+ const _Tinfo_Node *info;
+ _init_keymgr ();
+ info = (_Tinfo_Node *)__keymgr_global[2];
+ if (info != NULL)
+ {
+ if (info->major_version >= KEYMGR_API_MAJOR_GCC3)
+ return;
+ /* Otherwise, use our own add_image_hooks. */
+ }
+
+ _dyld_register_func_for_add_image (darwin_unwind_dyld_add_image_hook);
+ _dyld_register_func_for_remove_image (darwin_unwind_dyld_remove_image_hook);
+}
diff --git a/contrib/gcc/config/darwin-protos.h b/contrib/gcc/config/darwin-protos.h
index 0bff130..5fea152 100644
--- a/contrib/gcc/config/darwin-protos.h
+++ b/contrib/gcc/config/darwin-protos.h
@@ -1,5 +1,5 @@
/* Prototypes.
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -22,11 +22,9 @@ extern int name_needs_quotes PARAMS ((const char *));
extern void machopic_validate_stub_or_non_lazy_ptr PARAMS ((const char *, int));
-extern char *machopic_function_base_name PARAMS ((void));
-extern char *machopic_non_lazy_ptr_name PARAMS ((const char*));
-extern char *machopic_stub_name PARAMS ((const char*));
-
-extern void machopic_add_gc_roots PARAMS ((void));
+extern const char *machopic_function_base_name PARAMS ((void));
+extern const char *machopic_non_lazy_ptr_name PARAMS ((const char*));
+extern const char *machopic_stub_name PARAMS ((const char*));
extern void machopic_picsymbol_stub_section PARAMS ((void));
extern void machopic_symbol_stub_section PARAMS ((void));
@@ -58,7 +56,8 @@ extern void machopic_define_ident PARAMS ((tree));
extern void machopic_define_name PARAMS ((const char*));
extern int machopic_name_defined_p PARAMS ((const char*));
extern int machopic_ident_defined_p PARAMS ((tree));
-extern void darwin_encode_section_info PARAMS ((tree));
+extern void darwin_encode_section_info PARAMS ((tree, int));
+extern const char *darwin_strip_name_encoding PARAMS ((const char *));
#endif /* TREE_CODE */
@@ -68,9 +67,53 @@ extern void machopic_output_possible_stub_label PARAMS ((FILE *, const char*));
extern void darwin_exception_section PARAMS ((void));
extern void darwin_eh_frame_section PARAMS ((void));
+extern void machopic_select_section PARAMS ((tree, int,
+ unsigned HOST_WIDE_INT));
+extern void machopic_select_rtx_section PARAMS ((enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT));
#ifdef GCC_C_PRAGMA_H
extern void darwin_pragma_ignore PARAMS ((cpp_reader *));
extern void darwin_pragma_options PARAMS ((cpp_reader *));
extern void darwin_pragma_unused PARAMS ((cpp_reader *));
#endif
+
+/* Expanded by EXTRA_SECTION_FUNCTIONS into varasm.o. */
+extern void const_section PARAMS ((void));
+extern void const_data_section PARAMS ((void));
+extern void cstring_section PARAMS ((void));
+extern void literal4_section PARAMS ((void));
+extern void literal8_section PARAMS ((void));
+extern void constructor_section PARAMS ((void));
+extern void mod_init_section PARAMS ((void));
+extern void mod_term_section PARAMS ((void));
+extern void destructor_section PARAMS ((void));
+extern void objc_class_section PARAMS ((void));
+extern void objc_meta_class_section PARAMS ((void));
+extern void objc_category_section PARAMS ((void));
+extern void objc_class_vars_section PARAMS ((void));
+extern void objc_instance_vars_section PARAMS ((void));
+extern void objc_cls_meth_section PARAMS ((void));
+extern void objc_inst_meth_section PARAMS ((void));
+extern void objc_cat_cls_meth_section PARAMS ((void));
+extern void objc_cat_inst_meth_section PARAMS ((void));
+extern void objc_selector_refs_section PARAMS ((void));
+extern void objc_selector_fixup_section PARAMS ((void));
+extern void objc_symbols_section PARAMS ((void));
+extern void objc_module_info_section PARAMS ((void));
+extern void objc_protocol_section PARAMS ((void));
+extern void objc_string_object_section PARAMS ((void));
+extern void objc_constant_string_object_section PARAMS ((void));
+extern void objc_class_names_section PARAMS ((void));
+extern void objc_meth_var_names_section PARAMS ((void));
+extern void objc_meth_var_types_section PARAMS ((void));
+extern void objc_cls_refs_section PARAMS ((void));
+extern void machopic_lazy_symbol_ptr_section PARAMS ((void));
+extern void machopic_nl_symbol_ptr_section PARAMS ((void));
+extern void machopic_symbol_stub_section PARAMS ((void));
+extern void machopic_picsymbol_stub_section PARAMS ((void));
+extern void machopic_output_stub PARAMS ((FILE *, const char *, const char *));
+extern void darwin_exception_section PARAMS ((void));
+extern void darwin_eh_frame_section PARAMS ((void));
+extern void darwin_globalize_label PARAMS ((FILE *, const char *));
+extern void darwin_asm_output_dwarf_delta PARAMS ((FILE *, int, const char *, const char *));
diff --git a/contrib/gcc/config/darwin.c b/contrib/gcc/config/darwin.c
index 6864f0c..3722950 100644
--- a/contrib/gcc/config/darwin.c
+++ b/contrib/gcc/config/darwin.c
@@ -1,5 +1,5 @@
/* Functions for generic Darwin as target machine for GNU C compiler.
- Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001
+ Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002
Free Software Foundation, Inc.
Contributed by Apple Computer Inc.
@@ -38,13 +38,9 @@ Boston, MA 02111-1307, USA. */
#include "function.h"
#include "ggc.h"
#include "langhooks.h"
-
-#include "darwin-protos.h"
-
-extern void machopic_output_stub PARAMS ((FILE *, const char *, const char *));
+#include "tm_p.h"
static int machopic_data_defined_p PARAMS ((const char *));
-static int func_name_maybe_scoped PARAMS ((const char *));
static void update_non_lazy_ptrs PARAMS ((const char *));
static void update_stubs PARAMS ((const char *));
@@ -67,7 +63,7 @@ name_needs_quotes (name)
/* This module assumes that (const (symbol_ref "foo")) is a legal pic
reference, which will not be changed. */
-static tree machopic_defined_list;
+static GTY(()) tree machopic_defined_list;
enum machopic_addr_class
machopic_classify_ident (ident)
@@ -221,13 +217,13 @@ machopic_define_name (name)
}
/* This is a static to make inline functions work. The rtx
- representing the PIC base symbol always points to here. */
+ representing the PIC base symbol always points to here. */
static char function_base[32];
static int current_pic_label_num;
-char *
+const char *
machopic_function_base_name ()
{
static const char *name = NULL;
@@ -257,17 +253,17 @@ machopic_function_base_name ()
return function_base;
}
-static tree machopic_non_lazy_pointers = NULL;
+static GTY(()) tree machopic_non_lazy_pointers;
/* Return a non-lazy pointer name corresponding to the given name,
either by finding it in our list of pointer names, or by generating
a new one. */
-char *
+const char *
machopic_non_lazy_ptr_name (name)
const char *name;
{
- char *temp_name;
+ const char *temp_name;
tree temp, ident = get_identifier (name);
for (temp = machopic_non_lazy_pointers;
@@ -278,7 +274,7 @@ machopic_non_lazy_ptr_name (name)
return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
}
- STRIP_NAME_ENCODING (name, name);
+ name = darwin_strip_name_encoding (name);
/* Try again, but comparing names this time. */
for (temp = machopic_non_lazy_pointers;
@@ -288,7 +284,7 @@ machopic_non_lazy_ptr_name (name)
if (TREE_VALUE (temp))
{
temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
- STRIP_NAME_ENCODING (temp_name, temp_name);
+ temp_name = darwin_strip_name_encoding (temp_name);
if (strcmp (name, temp_name) == 0)
return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
}
@@ -321,22 +317,12 @@ machopic_non_lazy_ptr_name (name)
}
}
-static tree machopic_stubs = 0;
-
-/* Make sure the GC knows about our homemade lists. */
-
-void
-machopic_add_gc_roots ()
-{
- ggc_add_tree_root (&machopic_defined_list, 1);
- ggc_add_tree_root (&machopic_non_lazy_pointers, 1);
- ggc_add_tree_root (&machopic_stubs, 1);
-}
+static GTY(()) tree machopic_stubs;
/* Return the name of the stub corresponding to the given name,
generating a new stub name if necessary. */
-char *
+const char *
machopic_stub_name (name)
const char *name;
{
@@ -360,7 +346,7 @@ machopic_stub_name (name)
return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
}
- STRIP_NAME_ENCODING (name, name);
+ name = darwin_strip_name_encoding (name);
{
char *buffer;
@@ -401,7 +387,7 @@ machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
const char *name;
int validate_stub;
{
- char *real_name;
+ const char *real_name;
tree temp, ident = get_identifier (name), id2;
for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
@@ -414,7 +400,8 @@ machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
TREE_USED (temp) = 1;
if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
- STRIP_NAME_ENCODING (real_name, IDENTIFIER_POINTER (TREE_VALUE (temp)));
+ real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
+ real_name = darwin_strip_name_encoding (real_name);
id2 = maybe_get_identifier (real_name);
if (id2)
TREE_SYMBOL_REFERENCED (id2) = 1;
@@ -439,10 +426,12 @@ machopic_indirect_data_reference (orig, reg)
if (machopic_data_defined_p (name))
{
+#if defined (TARGET_TOC) || defined (HAVE_lo_sum)
rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
machopic_function_base_name ());
rtx offset = gen_rtx (CONST, Pmode,
gen_rtx (MINUS, Pmode, orig, pic_base));
+#endif
#if defined (TARGET_TOC) /* i.e., PowerPC */
rtx hi_sum_reg = reg;
@@ -502,9 +491,6 @@ machopic_indirect_data_reference (orig, reg)
else
result = gen_rtx (PLUS, Pmode, base, orig);
- if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
- RTX_UNCHANGING_P (result) = 1;
-
if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
{
if (reg)
@@ -676,10 +662,10 @@ machopic_legitimize_pic_address (orig, mode, reg)
}
#if !defined (TARGET_TOC)
- RTX_UNCHANGING_P (pic_ref) = 1;
emit_move_insn (reg, pic_ref);
pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
#endif
+ RTX_UNCHANGING_P (pic_ref) = 1;
}
else
{
@@ -711,6 +697,7 @@ machopic_legitimize_pic_address (orig, mode, reg)
gen_rtx (LO_SUM, Pmode,
hi_sum_reg, offset)));
pic_ref = reg;
+ RTX_UNCHANGING_P (pic_ref) = 1;
#else
emit_insn (gen_rtx (SET, VOIDmode, reg,
gen_rtx (HIGH, Pmode, offset)));
@@ -718,6 +705,7 @@ machopic_legitimize_pic_address (orig, mode, reg)
gen_rtx (LO_SUM, Pmode, reg, offset)));
pic_ref = gen_rtx (PLUS, Pmode,
pic_offset_table_rtx, reg);
+ RTX_UNCHANGING_P (pic_ref) = 1;
#endif
}
else
@@ -748,8 +736,6 @@ machopic_legitimize_pic_address (orig, mode, reg)
}
}
- RTX_UNCHANGING_P (pic_ref) = 1;
-
if (GET_CODE (pic_ref) != REG)
{
if (reg != 0)
@@ -846,7 +832,7 @@ machopic_finish (asm_out_file)
if (sym_name[0] == '!' && sym_name[1] == 'T')
continue;
- STRIP_NAME_ENCODING (sym_name, sym_name);
+ sym_name = darwin_strip_name_encoding (sym_name);
sym = alloca (strlen (sym_name) + 2);
if (sym_name[0] == '*' || sym_name[0] == '&')
@@ -869,20 +855,13 @@ machopic_finish (asm_out_file)
temp != NULL_TREE;
temp = TREE_CHAIN (temp))
{
- char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
- char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
-#if 0
- tree decl = lookup_name_darwin (TREE_VALUE (temp));
-#endif
+ const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
+ const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
if (! TREE_USED (temp))
continue;
- if (machopic_ident_defined_p (TREE_VALUE (temp))
-#if 0 /* add back when we have private externs */
- || (decl && DECL_PRIVATE_EXTERN (decl))
-#endif
- )
+ if (machopic_ident_defined_p (TREE_VALUE (temp)))
{
data_section ();
assemble_align (GET_MODE_ALIGNMENT (Pmode));
@@ -932,18 +911,6 @@ machopic_operand_p (op)
&& machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
return 1;
-#if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */
- /* Without this statement, the compiler crashes while compiling enquire.c
- when targetting PowerPC. It is not known why this code is not needed
- when targetting other processors. */
- else if (GET_CODE (op) == SYMBOL_REF
- && (machopic_classify_name (XSTR (op, 0))
- == MACHOPIC_DEFINED_FUNCTION))
- {
- return 1;
- }
-#endif
-
return 0;
}
@@ -952,8 +919,9 @@ machopic_operand_p (op)
use later. */
void
-darwin_encode_section_info (decl)
+darwin_encode_section_info (decl, first)
tree decl;
+ int first ATTRIBUTE_UNUSED;
{
char code = '\0';
int defined = 0;
@@ -1014,6 +982,15 @@ darwin_encode_section_info (decl)
update_stubs (XSTR (sym_ref, 0));
}
+/* Undo the effects of the above. */
+
+const char *
+darwin_strip_name_encoding (str)
+ const char *str;
+{
+ return str[0] == '!' ? str + 4 : str;
+}
+
/* Scan the list of non-lazy pointers and update any recorded names whose
stripped name matches the argument. */
@@ -1024,17 +1001,17 @@ update_non_lazy_ptrs (name)
const char *name1, *name2;
tree temp;
- STRIP_NAME_ENCODING (name1, name);
+ name1 = darwin_strip_name_encoding (name);
for (temp = machopic_non_lazy_pointers;
temp != NULL_TREE;
temp = TREE_CHAIN (temp))
{
- char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
+ const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
if (*sym_name == '!')
{
- STRIP_NAME_ENCODING (name2, sym_name);
+ name2 = darwin_strip_name_encoding (sym_name);
if (strcmp (name1, name2) == 0)
{
IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
@@ -1046,7 +1023,7 @@ update_non_lazy_ptrs (name)
/* Function NAME is being defined, and its label has just been output.
If there's already a reference to a stub for this function, we can
- just emit the stub label now and we don't bother emitting the stub later. */
+ just emit the stub label now and we don't bother emitting the stub later. */
void
machopic_output_possible_stub_label (file, name)
@@ -1088,17 +1065,17 @@ update_stubs (name)
const char *name1, *name2;
tree temp;
- STRIP_NAME_ENCODING (name1, name);
+ name1 = darwin_strip_name_encoding (name);
for (temp = machopic_stubs;
temp != NULL_TREE;
temp = TREE_CHAIN (temp))
{
- char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
+ const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
if (*sym_name == '!')
{
- STRIP_NAME_ENCODING (name2, sym_name);
+ name2 = darwin_strip_name_encoding (sym_name);
if (strcmp (name1, name2) == 0)
{
IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
@@ -1109,6 +1086,153 @@ update_stubs (name)
}
void
+machopic_select_section (exp, reloc, align)
+ tree exp;
+ int reloc;
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+{
+ if (TREE_CODE (exp) == STRING_CST)
+ {
+ if (flag_writable_strings)
+ data_section ();
+ else if (TREE_STRING_LENGTH (exp) !=
+ strlen (TREE_STRING_POINTER (exp)) + 1)
+ readonly_data_section ();
+ else
+ cstring_section ();
+ }
+ else if (TREE_CODE (exp) == INTEGER_CST
+ || TREE_CODE (exp) == REAL_CST)
+ {
+ tree size = TYPE_SIZE (TREE_TYPE (exp));
+
+ if (TREE_CODE (size) == INTEGER_CST &&
+ TREE_INT_CST_LOW (size) == 4 &&
+ TREE_INT_CST_HIGH (size) == 0)
+ literal4_section ();
+ else if (TREE_CODE (size) == INTEGER_CST &&
+ TREE_INT_CST_LOW (size) == 8 &&
+ TREE_INT_CST_HIGH (size) == 0)
+ literal8_section ();
+ else
+ readonly_data_section ();
+ }
+ else if (TREE_CODE (exp) == CONSTRUCTOR
+ && TREE_TYPE (exp)
+ && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
+ && TYPE_NAME (TREE_TYPE (exp)))
+ {
+ tree name = TYPE_NAME (TREE_TYPE (exp));
+ if (TREE_CODE (name) == TYPE_DECL)
+ name = DECL_NAME (name);
+ if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
+ objc_constant_string_object_section ();
+ else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
+ objc_string_object_section ();
+ else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
+ {
+ if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc))
+ const_data_section ();
+ else
+ readonly_data_section ();
+ }
+ else
+ data_section ();
+ }
+ else if (TREE_CODE (exp) == VAR_DECL &&
+ DECL_NAME (exp) &&
+ TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
+ IDENTIFIER_POINTER (DECL_NAME (exp)) &&
+ !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
+ {
+ const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
+
+ if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
+ objc_cls_meth_section ();
+ else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
+ objc_inst_meth_section ();
+ else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
+ objc_cat_cls_meth_section ();
+ else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
+ objc_cat_inst_meth_section ();
+ else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
+ objc_class_vars_section ();
+ else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
+ objc_instance_vars_section ();
+ else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
+ objc_cat_cls_meth_section ();
+ else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
+ objc_class_names_section ();
+ else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
+ objc_meth_var_names_section ();
+ else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
+ objc_meth_var_types_section ();
+ else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
+ objc_cls_refs_section ();
+ else if (!strncmp (name, "_OBJC_CLASS_", 12))
+ objc_class_section ();
+ else if (!strncmp (name, "_OBJC_METACLASS_", 16))
+ objc_meta_class_section ();
+ else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
+ objc_category_section ();
+ else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
+ objc_selector_refs_section ();
+ else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
+ objc_selector_fixup_section ();
+ else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
+ objc_symbols_section ();
+ else if (!strncmp (name, "_OBJC_MODULES", 13))
+ objc_module_info_section ();
+ else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
+ objc_cat_inst_meth_section ();
+ else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
+ objc_cat_cls_meth_section ();
+ else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
+ objc_cat_cls_meth_section ();
+ else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
+ objc_protocol_section ();
+ else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp))
+ && !TREE_SIDE_EFFECTS (exp))
+ {
+ if (flag_pic && reloc)
+ const_data_section ();
+ else
+ readonly_data_section ();
+ }
+ else
+ data_section ();
+ }
+ else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
+ {
+ if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc))
+ const_data_section ();
+ else
+ readonly_data_section ();
+ }
+ else
+ data_section ();
+}
+
+/* This can be called with address expressions as "rtx".
+ They must go in "const". */
+
+void
+machopic_select_rtx_section (mode, x, align)
+ enum machine_mode mode;
+ rtx x;
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+{
+ if (GET_MODE_SIZE (mode) == 8)
+ literal8_section ();
+ else if (GET_MODE_SIZE (mode) == 4
+ && (GET_CODE (x) == CONST_INT
+ || GET_CODE (x) == CONST_DOUBLE))
+ literal4_section ();
+ else
+ const_section ();
+}
+
+void
machopic_asm_out_constructor (symbol, priority)
rtx symbol;
int priority ATTRIBUTE_UNUSED;
@@ -1139,3 +1263,44 @@ machopic_asm_out_destructor (symbol, priority)
if (!flag_pic)
fprintf (asm_out_file, ".reference .destructors_used\n");
}
+
+void
+darwin_globalize_label (stream, name)
+ FILE *stream;
+ const char *name;
+{
+ if (!!strncmp (name, "_OBJC_", 6))
+ default_globalize_label (stream, name);
+}
+
+/* Output a difference of two labels that will be an assembly time
+ constant if the two labels are local. (.long lab1-lab2 will be
+ very different if lab1 is at the boundary between two sections; it
+ will be relocated according to the second section, not the first,
+ so one ends up with a difference between labels in different
+ sections, which is bad in the dwarf2 eh context for instance.) */
+
+static int darwin_dwarf_label_counter;
+
+void
+darwin_asm_output_dwarf_delta (file, size, lab1, lab2)
+ FILE *file;
+ int size ATTRIBUTE_UNUSED;
+ const char *lab1, *lab2;
+{
+ const char *p = lab1 + (lab1[0] == '*');
+ int islocaldiff = (p[0] == 'L');
+
+ if (islocaldiff)
+ fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
+ else
+ fprintf (file, "\t%s\t", ".long");
+ assemble_name (file, lab1);
+ fprintf (file, "-");
+ assemble_name (file, lab2);
+ if (islocaldiff)
+ fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
+}
+
+#include "gt-darwin.h"
+
diff --git a/contrib/gcc/config/darwin.h b/contrib/gcc/config/darwin.h
index 05ca85b..90d959c 100644
--- a/contrib/gcc/config/darwin.h
+++ b/contrib/gcc/config/darwin.h
@@ -35,6 +35,12 @@ Boston, MA 02111-1307, USA. */
leave it undefined and expect system builders to set configure args
correctly. */
+/* One of Darwin's NeXT legacies is the Mach-O format, which is partly
+ like a.out and partly like COFF, with additional features like
+ multi-architecture binary support. */
+
+#define OBJECT_FORMAT_MACHO
+
/* Suppress g++ attempt to link in the math library automatically.
(Some Darwin versions have a libm, but they seem to cause problems
for C++ executables.) */
@@ -78,56 +84,214 @@ Boston, MA 02111-1307, USA. */
#undef DEFAULT_PCC_STRUCT_RETURN
#define DEFAULT_PCC_STRUCT_RETURN 0
-/* Don't warn about MacOS-style 'APPL' four-char-constants. */
-
-#undef WARN_FOUR_CHAR_CONSTANTS
-#define WARN_FOUR_CHAR_CONSTANTS 0
+/* This table intercepts weirdo options whose names would interfere
+ with normal driver conventions, and either translates them into
+ standardly-named options, or adds a 'Z' so that they can get to
+ specs processing without interference.
+
+ Do not expand a linker option to "-Xlinker -<option>", since that
+ forfeits the ability to control via spec strings later. However,
+ as a special exception, do this translation with -filelist, because
+ otherwise the driver will think there are no input files and quit.
+ (The alternative would be to hack the driver to recognize -filelist
+ specially, but it's simpler to use the translation table.)
+
+ Note that an option name with a prefix that matches another option
+ name, that also takes an argument, needs to be modified so the
+ prefix is different, otherwise a '*' after the shorter option will
+ match with the longer one. */
+#define TARGET_OPTION_TRANSLATE_TABLE \
+ { "-all_load", "-Zall_load" }, \
+ { "-allowable_client", "-Zallowable_client" }, \
+ { "-arch_errors_fatal", "-Zarch_errors_fatal" }, \
+ { "-bind_at_load", "-Zbind_at_load" }, \
+ { "-bundle", "-Zbundle" }, \
+ { "-bundle_loader", "-Zbundle_loader" }, \
+ { "-weak_reference_mismatches", "-Zweak_reference_mismatches" }, \
+ { "-dependency-file", "-MF" }, \
+ { "-dylib_file", "-Zdylib_file" }, \
+ { "-dynamic", "-Zdynamic" }, \
+ { "-dynamiclib", "-Zdynamiclib" }, \
+ { "-exported_symbols_list", "-Zexported_symbols_list" }, \
+ { "-seg_addr_table_filename", "-Zseg_addr_table_filename" }, \
+ { "-filelist", "-Xlinker -filelist -Xlinker" }, \
+ { "-flat_namespace", "-Zflat_namespace" }, \
+ { "-force_cpusubtype_ALL", "-Zforce_cpusubtype_ALL" }, \
+ { "-force_flat_namespace", "-Zforce_flat_namespace" }, \
+ { "-image_base", "-Zimage_base" }, \
+ { "-init", "-Zinit" }, \
+ { "-install_name", "-Zinstall_name" }, \
+ { "-multiply_defined_unused", "-Zmultiplydefinedunused" }, \
+ { "-multiply_defined", "-Zmultiply_defined" }, \
+ { "-multi_module", "-Zmulti_module" }, \
+ { "-static", "-static -Wa,-static" }, \
+ { "-single_module", "-Zsingle_module" }, \
+ { "-unexported_symbols_list", "-Zunexported_symbols_list" }
+
+/* These compiler options take n arguments. */
+
+#undef WORD_SWITCH_TAKES_ARG
+#define WORD_SWITCH_TAKES_ARG(STR) \
+ (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) ? 1 : \
+ !strcmp (STR, "Zallowable_client") ? 1 : \
+ !strcmp (STR, "arch") ? 1 : \
+ !strcmp (STR, "arch_only") ? 1 : \
+ !strcmp (STR, "Zbundle_loader") ? 1 : \
+ !strcmp (STR, "client_name") ? 1 : \
+ !strcmp (STR, "compatibility_version") ? 1 : \
+ !strcmp (STR, "current_version") ? 1 : \
+ !strcmp (STR, "Zdylib_file") ? 1 : \
+ !strcmp (STR, "Zexported_symbols_list") ? 1 : \
+ !strcmp (STR, "Zimage_base") ? 1 : \
+ !strcmp (STR, "Zinit") ? 1 : \
+ !strcmp (STR, "Zinstall_name") ? 1 : \
+ !strcmp (STR, "Zmultiplydefinedunused") ? 1 : \
+ !strcmp (STR, "Zmultiply_defined") ? 1 : \
+ !strcmp (STR, "precomp-trustfile") ? 1 : \
+ !strcmp (STR, "read_only_relocs") ? 1 : \
+ !strcmp (STR, "sectcreate") ? 3 : \
+ !strcmp (STR, "sectorder") ? 3 : \
+ !strcmp (STR, "Zseg_addr_table_filename") ?1 :\
+ !strcmp (STR, "seg1addr") ? 1 : \
+ !strcmp (STR, "segprot") ? 3 : \
+ !strcmp (STR, "seg_addr_table") ? 1 : \
+ !strcmp (STR, "sub_library") ? 1 : \
+ !strcmp (STR, "sub_umbrella") ? 1 : \
+ !strcmp (STR, "umbrella") ? 1 : \
+ !strcmp (STR, "undefined") ? 1 : \
+ !strcmp (STR, "Zunexported_symbols_list") ? 1 : \
+ !strcmp (STR, "Zweak_reference_mismatches") ? 1 : \
+ !strcmp (STR, "pagezero_size") ? 1 : \
+ !strcmp (STR, "segs_read_only_addr") ? 1 : \
+ !strcmp (STR, "segs_read_write_addr") ? 1 : \
+ !strcmp (STR, "sectalign") ? 3 : \
+ !strcmp (STR, "sectobjectsymbols") ? 2 : \
+ !strcmp (STR, "segcreate") ? 3 : \
+ !strcmp (STR, "dylinker_install_name") ? 1 : \
+ 0)
/* Machine dependent cpp options. */
-/* The sequence here allows us to get a more specific version number
- glued into __APPLE_CC__. Normally this number would be updated as
- part of submitting to a release engineering organization. */
-
-#ifndef APPLE_CC
-#define APPLE_CC 999
-#endif
-
-#define STRINGIFY_THIS(x) # x
-#define REALLY_STRINGIFY(x) STRINGIFY_THIS(x)
-
#undef CPP_SPEC
-#define CPP_SPEC "-D__APPLE_CC__=" REALLY_STRINGIFY(APPLE_CC) " \
- %{static:-D__STATIC__}%{!static:-D__DYNAMIC__}"
+#define CPP_SPEC "%{static:%{!dynamic:-D__STATIC__}}%{!static:-D__DYNAMIC__}"
+
+/* This is mostly a clone of the standard LINK_COMMAND_SPEC, plus
+ precomp, libtool, and fat build additions. Also we
+ don't specify a second %G after %L because libSystem is
+ self-contained and doesn't need to link against libgcc.a. */
+/* In general, random Darwin linker flags should go into LINK_SPEC
+ instead of LINK_COMMAND_SPEC. The command spec is better for
+ specifying the handling of options understood by generic Unix
+ linkers, and for positional arguments like libraries. */
+#define LINK_COMMAND_SPEC "\
+%{!fdump=*:%{!fsyntax-only:%{!precomp:%{!c:%{!M:%{!MM:%{!E:%{!S:\
+ %{!Zdynamiclib:%(linker)}%{Zdynamiclib:/usr/bin/libtool} \
+ %l %X %{d} %{s} %{t} %{Z} \
+ %{!Zdynamiclib:%{A} %{e*} %{m} %{N} %{n} %{r} %{u*} %{x} %{z}} \
+ %{@:-o %f%u.out}%{!@:%{o*}%{!o:-o a.out}} \
+ %{!Zdynamiclib:%{!A:%{!nostdlib:%{!nostartfiles:%S}}}} \
+ %{L*} %(link_libgcc) %o %{!nostdlib:%{!nodefaultlibs:%G %L}} \
+ %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} %{F*} \
+ %{!--help:%{!no-c++filt|c++filt:| c++filt3 }} }}}}}}}}"
+
+/* Please keep the random linker options in alphabetical order (modulo
+ 'Z' and 'no' prefixes). Options that can only go to one of libtool
+ or ld must be listed twice, under both !Zdynamiclib and
+ Zdynamiclib, with one of the cases reporting an error. */
+/* Note that options taking arguments may appear multiple times on a
+ command line with different arguments each time, so put a * after
+ their names so all of them get passed. */
+#define LINK_SPEC \
+ "%{static}%{!static:-dynamic} \
+ %{!Zdynamiclib: \
+ %{Zbundle:-bundle} \
+ %{Zbundle_loader*:-bundle_loader %*} \
+ %{client_name*} \
+ %{compatibility_version*:%e-compatibility_version only allowed with -dynamiclib\
+} \
+ %{current_version*:%e-current_version only allowed with -dynamiclib} \
+ %{Zforce_cpusubtype_ALL:-force_cpusubtype_ALL} \
+ %{Zforce_flat_namespace:-force_flat_namespace} \
+ %{Zinstall_name*:%e-install_name only allowed with -dynamiclib} \
+ %{keep_private_externs} \
+ %{private_bundle} \
+ } \
+ %{Zdynamiclib: \
+ %{Zbundle:%e-bundle not allowed with -dynamiclib} \
+ %{Zbundle_loader*:%e-bundle_loader not allowed with -dynamiclib} \
+ %{client_name*:%e-client_name not allowed with -dynamiclib} \
+ %{compatibility_version*} \
+ %{current_version*} \
+ %{Zforce_cpusubtype_ALL:%e-force_cpusubtype_ALL not allowed with -dynamiclib} \
+ %{Zforce_flat_namespace:%e-force_flat_namespace not allowed with -dynamiclib} \
+ %{Zinstall_name*:-install_name %*} \
+ %{keep_private_externs:%e-keep_private_externs not allowed with -dynamiclib} \
+ %{private_bundle:%e-private_bundle not allowed with -dynamiclib} \
+ } \
+ %{Zall_load:-all_load}%{Zdynamiclib:%{!Zall_load:-noall_load}} \
+ %{Zallowable_client*:-allowable_client %*} \
+ %{Zbind_at_load:-bind_at_load} \
+ %{Zarch_errors_fatal:-arch_errors_fatal} \
+ %{Zdylib_file*:-dylib_file %*} \
+ %{Zdynamic:-dynamic}\
+ %{Zexported_symbols_list*:-exported_symbols_list %*} \
+ %{Zflat_namespace:-flat_namespace} \
+ %{headerpad_max_install_names*} \
+ %{Zimage_base*:-image_base %*} \
+ %{Zinit*:-init %*} \
+ %{nomultidefs} \
+ %{Zmulti_module:-multi_module} %{Zsingle_module:-single_module} \
+ %{Zmultiply_defined*:-multiply_defined %*} \
+ %{Zmultiplydefinedunused*:-multiply_defined_unused %*} \
+ %{prebind} %{noprebind} %{prebind_all_twolevel_modules} \
+ %{read_only_relocs} \
+ %{sectcreate*} %{sectorder*} %{seg1addr*} %{segprot*} %{seg_addr_table*} \
+ %{Zseg_addr_table_filename*:-seg_addr_table_filename %*} \
+ %{sub_library*} %{sub_umbrella*} \
+ %{twolevel_namespace} %{twolevel_namespace_hints} \
+ %{umbrella*} \
+ %{undefined*} \
+ %{Zunexported_symbols_list*:-unexported_symbols_list %*} \
+ %{Zweak_reference_mismatches*:-weak_reference_mismatches %*} \
+ %{X} \
+ %{y*} \
+ %{w} \
+ %{pagezero_size*} %{segs_read_*} %{seglinkedit} %{noseglinkedit} \
+ %{sectalign*} %{sectobjectsymbols*} %{segcreate*} %{whyload} \
+ %{whatsloaded} %{dylinker_install_name*} \
+ %{dylinker} %{Mach} "
+
/* Machine dependent libraries. */
#undef LIB_SPEC
#define LIB_SPEC "%{!static:-lSystem}"
-/* We specify crt0.o as -lcrt0.o so that ld will search the library path. */
+/* We specify crt0.o as -lcrt0.o so that ld will search the library path. */
-#undef STARTFILE_SPEC
+#undef STARTFILE_SPEC
#define STARTFILE_SPEC \
- "%{pg:%{static:-lgcrt0.o}%{!static:-lgcrt1.o}} \
- %{!pg:%{static:-lcrt0.o}%{!static:-lcrt1.o}}"
+ "%{!Zdynamiclib:%{Zbundle:%{!static:-lbundle1.o}} \
+ %{!Zbundle:%{pg:%{static:-lgcrt0.o} \
+ %{!static:%{object:-lgcrt0.o} \
+ %{!object:%{preload:-lgcrt0.o} \
+ %{!preload:-lgcrt1.o -lcrt2.o}}}} \
+ %{!pg:%{static:-lcrt0.o} \
+ %{!static:%{object:-lcrt0.o} \
+ %{!object:%{preload:-lcrt0.o} \
+ %{!preload:-lcrt1.o -lcrt2.o}}}}}}"
+
+/* The native Darwin linker doesn't necessarily place files in the order
+ that they're specified on the link line. Thus, it is pointless
+ to put anything in ENDFILE_SPEC. */
+/* #define ENDFILE_SPEC "" */
#undef DOLLARS_IN_IDENTIFIERS
#define DOLLARS_IN_IDENTIFIERS 2
-/* Allow #sccs (but don't do anything). */
-
-#define SCCS_DIRECTIVE
-
/* We use Dbx symbol format. */
-#define DBX_DEBUGGING_INFO
-
-/* Also enable Dwarf 2 as an option. */
-
-#define DWARF2_DEBUGGING_INFO
-
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+#define DBX_DEBUGGING_INFO 1
/* When generating stabs debugging, use N_BINCL entries. */
@@ -137,7 +301,7 @@ Boston, MA 02111-1307, USA. */
#define DBX_CONTIN_LENGTH 0
-/* gdb needs a null N_SO at the end of each file for scattered loading. */
+/* gdb needs a null N_SO at the end of each file for scattered loading. */
#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
@@ -158,6 +322,9 @@ do { text_section (); \
#define TARGET_ASM_CONSTRUCTOR machopic_asm_out_constructor
#define TARGET_ASM_DESTRUCTOR machopic_asm_out_destructor
+/* Always prefix with an underscore. */
+
+#define USER_LABEL_PREFIX "_"
/* Don't output a .file directive. That is only used by the assembler for
error reporting. */
@@ -177,7 +344,10 @@ do { text_section (); \
} \
} while (0)
-/* Give ObjcC methods pretty symbol names. */
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.space %d\n", SIZE)
+
+/* Give ObjC methods pretty symbol names. */
#undef OBJC_GEN_METHOD_LABEL
#define OBJC_GEN_METHOD_LABEL(BUF,IS_INST,CLASS_NAME,CAT_NAME,SEL_NAME,NUM) \
@@ -208,7 +378,7 @@ do { text_section (); \
if ((TREE_STATIC (DECL) \
&& (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
|| DECL_INITIAL (DECL)) \
- ENCODE_SECTION_INFO (DECL); \
+ (* targetm.encode_section_info) (DECL, false); \
ASM_OUTPUT_LABEL (FILE, xname); \
} while (0)
@@ -224,7 +394,7 @@ do { text_section (); \
if ((TREE_STATIC (DECL) \
&& (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
|| DECL_INITIAL (DECL)) \
- ENCODE_SECTION_INFO (DECL); \
+ (* targetm.encode_section_info) (DECL, false); \
ASM_OUTPUT_LABEL (FILE, xname); \
/* Avoid generating stubs for functions we've just defined by \
outputting any required stub name label now. */ \
@@ -235,30 +405,39 @@ do { text_section (); \
Make Objective-C internal symbols local. */
#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(FILE,NAME) \
- do { \
- STRIP_NAME_ENCODING (NAME, NAME); \
- if (NAME[0] == '&' || NAME[0] == '*') \
- { \
- int len = strlen (NAME); \
- if (len > 6 && !strcmp ("$stub", NAME + len - 5)) \
- machopic_validate_stub_or_non_lazy_ptr (NAME, 1); \
- else if (len > 7 && !strcmp ("$stub\"", NAME + len - 6)) \
- machopic_validate_stub_or_non_lazy_ptr (NAME, 1); \
- else if (len > 14 && !strcmp ("$non_lazy_ptr", NAME + len - 13)) \
- machopic_validate_stub_or_non_lazy_ptr (NAME, 0); \
- fputs (&NAME[1], FILE); \
- } \
- else if (NAME[0] == '+' || NAME[0] == '-') \
- fprintf (FILE, "\"%s\"", NAME); \
- 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); \
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ do { \
+ const char *xname = darwin_strip_name_encoding (NAME); \
+ if (xname[0] == '&' || xname[0] == '*') \
+ { \
+ int len = strlen (xname); \
+ if (len > 6 && !strcmp ("$stub", xname + len - 5)) \
+ machopic_validate_stub_or_non_lazy_ptr (xname, 1); \
+ else if (len > 7 && !strcmp ("$stub\"", xname + len - 6)) \
+ machopic_validate_stub_or_non_lazy_ptr (xname, 1); \
+ else if (len > 14 && !strcmp ("$non_lazy_ptr", xname + len - 13)) \
+ machopic_validate_stub_or_non_lazy_ptr (xname, 0); \
+ fputs (&xname[1], FILE); \
+ } \
+ else if (xname[0] == '+' || xname[0] == '-') \
+ fprintf (FILE, "\"%s\"", xname); \
+ else if (!strncmp (xname, "_OBJC_", 6)) \
+ fprintf (FILE, "L%s", xname); \
+ else if (!strncmp (xname, ".objc_class_name_", 17)) \
+ fprintf (FILE, "%s", xname); \
+ else \
+ fprintf (FILE, "_%s", xname); \
} while (0)
+/* Output before executable code. */
+#undef TEXT_SECTION_ASM_OP
+#define TEXT_SECTION_ASM_OP ".text"
+
+/* Output before writable data. */
+
+#undef DATA_SECTION_ASM_OP
+#define DATA_SECTION_ASM_OP ".data"
+
#undef ALIGN_ASM_OP
#define ALIGN_ASM_OP ".align"
@@ -270,33 +449,29 @@ do { text_section (); \
/* Ensure correct alignment of bss data. */
#undef ASM_OUTPUT_ALIGNED_DECL_LOCAL
-#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
- do { \
- fputs (".lcomm ", (FILE)); \
- assemble_name ((FILE), (NAME)); \
- fprintf ((FILE), ",%u,%u\n", (SIZE), floor_log2 ((ALIGN) / BITS_PER_UNIT)); \
- if ((DECL) && ((TREE_STATIC (DECL) \
- && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
- || DECL_INITIAL (DECL))) \
- ENCODE_SECTION_INFO (DECL); \
- if ((DECL) && ((TREE_STATIC (DECL) \
- && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
- || DECL_INITIAL (DECL))) \
- machopic_define_name (NAME); \
+#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
+ do { \
+ fputs (".lcomm ", (FILE)); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), ",%u,%u\n", (SIZE), \
+ floor_log2 ((ALIGN) / BITS_PER_UNIT)); \
+ if ((DECL) && ((TREE_STATIC (DECL) \
+ && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
+ || DECL_INITIAL (DECL))) \
+ (* targetm.encode_section_info) (DECL, false); \
+ if ((DECL) && ((TREE_STATIC (DECL) \
+ && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
+ || DECL_INITIAL (DECL))) \
+ machopic_define_name (NAME); \
} while (0)
-/* Output nothing for #ident. */
-
-#undef ASM_OUTPUT_IDENT
-#define ASM_OUTPUT_IDENT(FILE, NAME)
-
/* The maximum alignment which the object file format can support.
For Mach-O, this is 2^15. */
#undef MAX_OFILE_ALIGNMENT
#define MAX_OFILE_ALIGNMENT 0x8000
-/* Create new Mach-O sections. */
+/* Create new Mach-O sections. */
#undef SECTION_FUNCTION
#define SECTION_FUNCTION(FUNCTION, SECTION, DIRECTIVE, OBJC) \
@@ -315,11 +490,6 @@ FUNCTION () \
} \
} \
-#define ALIAS_SECTION(enum_value, alias_name) \
-do { if (!strcmp (alias_name, name)) \
- section_alias[enum_value] = (alias ? get_identifier (alias) : 0); \
- } while (0)
-
/* Darwin uses many types of special sections. */
#undef EXTRA_SECTIONS
@@ -449,7 +619,7 @@ SECTION_FUNCTION (machopic_picsymbol_stub_section, \
".picsymbol_stub", 0) \
SECTION_FUNCTION (darwin_exception_section, \
in_darwin_exception, \
- ".section __TEXT,__gcc_except_tab", 0) \
+ ".section __DATA,__gcc_except_tab", 0) \
SECTION_FUNCTION (darwin_eh_frame_section, \
in_darwin_eh_frame, \
".section __TEXT,__eh_frame", 0) \
@@ -485,174 +655,14 @@ objc_section_init () \
objc_module_info_section (); \
objc_symbols_section (); \
} \
-} \
-static tree section_alias[(int) num_sections]; \
-static void try_section_alias PARAMS ((void)); \
-static void try_section_alias () \
-{ \
- if (section_alias[in_section] && asm_out_file) \
- fprintf (asm_out_file, "%s\n", \
- IDENTIFIER_POINTER (section_alias[in_section])); \
-} \
-
-#if 0
-static void alias_section PARAMS ((const char *, const char *)); \
-static void alias_section (name, alias) \
- const char *name, *alias; \
-{ \
- ALIAS_SECTION (in_data, "data"); \
- ALIAS_SECTION (in_text, "text"); \
- ALIAS_SECTION (in_const, "const"); \
- ALIAS_SECTION (in_const_data, "const_data"); \
- ALIAS_SECTION (in_cstring, "cstring"); \
- ALIAS_SECTION (in_literal4, "literal4"); \
- ALIAS_SECTION (in_literal8, "literal8"); \
}
-#endif
-#undef READONLY_DATA_SECTION
#define READONLY_DATA_SECTION const_section
-#undef SELECT_SECTION
-#define SELECT_SECTION(exp,reloc,align) \
- do \
- { \
- if (TREE_CODE (exp) == STRING_CST) \
- { \
- if (flag_writable_strings) \
- data_section (); \
- else if (TREE_STRING_LENGTH (exp) != \
- strlen (TREE_STRING_POINTER (exp)) + 1) \
- readonly_data_section (); \
- else \
- cstring_section (); \
- } \
- else if (TREE_CODE (exp) == INTEGER_CST \
- || TREE_CODE (exp) == REAL_CST) \
- { \
- tree size = TYPE_SIZE (TREE_TYPE (exp)); \
- \
- if (TREE_CODE (size) == INTEGER_CST && \
- TREE_INT_CST_LOW (size) == 4 && \
- TREE_INT_CST_HIGH (size) == 0) \
- literal4_section (); \
- else if (TREE_CODE (size) == INTEGER_CST && \
- TREE_INT_CST_LOW (size) == 8 && \
- TREE_INT_CST_HIGH (size) == 0) \
- literal8_section (); \
- else \
- readonly_data_section (); \
- } \
- else if (TREE_CODE (exp) == CONSTRUCTOR \
- && TREE_TYPE (exp) \
- && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE \
- && TYPE_NAME (TREE_TYPE (exp))) \
- { \
- tree name = TYPE_NAME (TREE_TYPE (exp)); \
- if (TREE_CODE (name) == TYPE_DECL) \
- name = DECL_NAME (name); \
- if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString")) \
- objc_constant_string_object_section (); \
- else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString")) \
- objc_string_object_section (); \
- else if (TREE_READONLY (exp) || TREE_CONSTANT (exp)) \
- { \
- if (TREE_SIDE_EFFECTS (exp) || flag_pic && reloc) \
- const_data_section (); \
- else \
- readonly_data_section (); \
- } \
- else \
- data_section (); \
- } \
- else if (TREE_CODE (exp) == VAR_DECL && \
- DECL_NAME (exp) && \
- TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE && \
- IDENTIFIER_POINTER (DECL_NAME (exp)) && \
- !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6)) \
- { \
- const char *name = IDENTIFIER_POINTER (DECL_NAME (exp)); \
- \
- if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20)) \
- objc_cls_meth_section (); \
- else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23)) \
- objc_inst_meth_section (); \
- else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20)) \
- objc_cat_cls_meth_section (); \
- else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23)) \
- objc_cat_inst_meth_section (); \
- else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22)) \
- objc_class_vars_section (); \
- else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25)) \
- objc_instance_vars_section (); \
- else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22)) \
- objc_cat_cls_meth_section (); \
- else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17)) \
- objc_class_names_section (); \
- else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20)) \
- objc_meth_var_names_section (); \
- else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20)) \
- objc_meth_var_types_section (); \
- else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22)) \
- objc_cls_refs_section (); \
- else if (!strncmp (name, "_OBJC_CLASS_", 12)) \
- objc_class_section (); \
- else if (!strncmp (name, "_OBJC_METACLASS_", 16)) \
- objc_meta_class_section (); \
- else if (!strncmp (name, "_OBJC_CATEGORY_", 15)) \
- objc_category_section (); \
- else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25)) \
- objc_selector_refs_section (); \
- else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20)) \
- objc_selector_fixup_section (); \
- else if (!strncmp (name, "_OBJC_SYMBOLS", 13)) \
- objc_symbols_section (); \
- else if (!strncmp (name, "_OBJC_MODULES", 13)) \
- objc_module_info_section (); \
- else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32)) \
- objc_cat_inst_meth_section (); \
- else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29)) \
- objc_cat_cls_meth_section (); \
- else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20)) \
- objc_cat_cls_meth_section (); \
- else if (!strncmp (name, "_OBJC_PROTOCOL_", 15)) \
- objc_protocol_section (); \
- else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp)) \
- && !TREE_SIDE_EFFECTS (exp)) \
- { if (flag_pic && reloc ) const_data_section (); \
- else readonly_data_section (); } \
- else \
- data_section (); \
- } \
- else if (TREE_READONLY (exp) || TREE_CONSTANT (exp)) \
- { \
- if (TREE_SIDE_EFFECTS (exp) || flag_pic && reloc) \
- const_data_section (); \
- else \
- readonly_data_section (); \
- } \
- else \
- data_section (); \
- try_section_alias (); \
- } \
- while (0)
-
-/* This can be called with address expressions as "rtx".
- They must go in "const". */
-#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(mode, rtx, align) \
- do \
- { \
- if (GET_MODE_SIZE (mode) == 8) \
- literal8_section (); \
- else if (GET_MODE_SIZE (mode) == 4 \
- && (GET_CODE (rtx) == CONST_INT \
- || GET_CODE (rtx) == CONST_DOUBLE)) \
- literal4_section (); \
- else \
- const_section (); \
- } \
- while (0)
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION machopic_select_section
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION machopic_select_rtx_section
#define ASM_DECLARE_UNRESOLVED_REFERENCE(FILE,NAME) \
do { \
@@ -672,15 +682,13 @@ static void alias_section (name, alias) \
fprintf (FILE, "\t"); \
assemble_name (FILE, NAME); \
fprintf (FILE, "=0\n"); \
- assemble_global (NAME); \
+ (*targetm.asm_out.globalize_label) (FILE, NAME); \
} \
} while (0)
-#undef ASM_GLOBALIZE_LABEL
-#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
- do { const char *const _x = (NAME); if (!!strncmp (_x, "_OBJC_", 6)) { \
- (fputs (".globl ", FILE), assemble_name (FILE, _x), fputs ("\n", FILE)); \
- }} while (0)
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP ".globl "
+#define TARGET_ASM_GLOBALIZE_LABEL darwin_globalize_label
#undef ASM_GENERATE_INTERNAL_LABEL
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
@@ -716,15 +724,10 @@ enum machopic_addr_class {
#define MACHOPIC_JUST_INDIRECT (flag_pic == 1)
#define MACHOPIC_PURE (flag_pic == 2)
-#define ENCODE_SECTION_INFO(DECL) \
- darwin_encode_section_info (DECL)
-
-/* Be conservative and always redo the encoding. */
-
-#define REDO_SECTION_INFO_P(DECL) (1)
-
-#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
- ((VAR) = ((SYMBOL_NAME[0] == '!') ? (SYMBOL_NAME) + 4 : (SYMBOL_NAME)))
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO darwin_encode_section_info
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING darwin_strip_name_encoding
#define GEN_BINDER_NAME_FOR_STUB(BUF,STUB,STUB_LENGTH) \
do { \
@@ -760,12 +763,11 @@ enum machopic_addr_class {
#define GEN_LAZY_PTR_NAME_FOR_SYMBOL(BUF,SYMBOL,SYMBOL_LENGTH) \
do { \
- const char *symbol_ = (SYMBOL); \
+ const char *symbol_ = darwin_strip_name_encoding (SYMBOL); \
char *buffer_ = (BUF); \
- STRIP_NAME_ENCODING (symbol_, symbol_); \
if (symbol_[0] == '"') \
{ \
- strcpy (buffer_, "\"L"); \
+ strcpy (buffer_, "\"L"); \
strcpy (buffer_ + 2, symbol_ + 1); \
strcpy (buffer_ + (SYMBOL_LENGTH), "$lazy_ptr\""); \
} \
@@ -787,13 +789,26 @@ enum machopic_addr_class {
#define TARGET_ASM_EH_FRAME_SECTION darwin_eh_frame_section
+#undef ASM_PREFERRED_EH_DATA_FORMAT
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
- (((CODE) == 1 || (GLOBAL) == 0) ? DW_EH_PE_pcrel : DW_EH_PE_absptr)
-
-#define REGISTER_TARGET_PRAGMAS(PFILE) \
- do { \
- cpp_register_pragma (PFILE, 0, "mark", darwin_pragma_ignore); \
- cpp_register_pragma (PFILE, 0, "options", darwin_pragma_options); \
- cpp_register_pragma (PFILE, 0, "segment", darwin_pragma_ignore); \
- cpp_register_pragma (PFILE, 0, "unused", darwin_pragma_unused); \
+ (((CODE) == 2 && (GLOBAL) == 1) \
+ ? (DW_EH_PE_pcrel | DW_EH_PE_indirect) : \
+ ((CODE) == 1 || (GLOBAL) == 0) ? DW_EH_PE_pcrel : DW_EH_PE_absptr)
+
+#define ASM_OUTPUT_DWARF_DELTA(FILE,SIZE,LABEL1,LABEL2) \
+ darwin_asm_output_dwarf_delta (FILE, SIZE, LABEL1, LABEL2)
+
+#define TARGET_TERMINATE_DW2_EH_FRAME_INFO false
+
+#define DARWIN_REGISTER_TARGET_PRAGMAS(PFILE) \
+ do { \
+ cpp_register_pragma (PFILE, 0, "mark", darwin_pragma_ignore); \
+ cpp_register_pragma (PFILE, 0, "options", darwin_pragma_options); \
+ cpp_register_pragma (PFILE, 0, "segment", darwin_pragma_ignore); \
+ cpp_register_pragma (PFILE, 0, "unused", darwin_pragma_unused); \
} while (0)
+
+#undef ASM_APP_ON
+#define ASM_APP_ON ""
+#undef ASM_APP_OFF
+#define ASM_APP_OFF ""
diff --git a/contrib/gcc/config/dbx.h b/contrib/gcc/config/dbx.h
index c5cd3b5..a9feded 100644
--- a/contrib/gcc/config/dbx.h
+++ b/contrib/gcc/config/dbx.h
@@ -22,9 +22,7 @@ Boston, MA 02111-1307, USA. */
information. The configure script will add a #include of this file
to tm.h when --with-stabs is used for certain targets. */
-#ifndef DBX_DEBUGGING_INFO
-#define DBX_DEBUGGING_INFO
-#endif
+#define DBX_DEBUGGING_INFO 1
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
diff --git a/contrib/gcc/config/dbxcoff.h b/contrib/gcc/config/dbxcoff.h
index 1d5b448..b955932 100644
--- a/contrib/gcc/config/dbxcoff.h
+++ b/contrib/gcc/config/dbxcoff.h
@@ -24,10 +24,9 @@ Boston, MA 02111-1307, USA. */
/* Output DBX (stabs) debugging information if doing -gstabs. */
-#undef DBX_DEBUGGING_INFO
-#define DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
-/* Generate SDB debugging information by default. */
+/* Generate SDB debugging information by default. */
#ifndef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG
diff --git a/contrib/gcc/config/dbxelf.h b/contrib/gcc/config/dbxelf.h
index c1490ae..9f8f56a 100644
--- a/contrib/gcc/config/dbxelf.h
+++ b/contrib/gcc/config/dbxelf.h
@@ -27,8 +27,7 @@ Boston, MA 02111-1307, USA. */
/* Output DBX (stabs) debugging information if doing -gstabs. */
-#undef DBX_DEBUGGING_INFO
-#define DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
/* Make LBRAC and RBRAC addresses relative to the start of the
function. The native Solaris stabs debugging format works this
diff --git a/contrib/gcc/config/elfos.h b/contrib/gcc/config/elfos.h
index 6b93253..25a44af 100644
--- a/contrib/gcc/config/elfos.h
+++ b/contrib/gcc/config/elfos.h
@@ -1,6 +1,6 @@
/* elfos.h -- operating system specific defines to be used when
targeting GCC for some generic ELF system
- Copyright (C) 1991, 1994, 1995, 1999, 2000, 2001
+ Copyright (C) 1991, 1994, 1995, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
Based on svr4.h contributed by Ron Guilmette (rfg@netcom.com).
@@ -46,9 +46,11 @@ Boston, MA 02111-1307, USA. */
#define NO_DOLLAR_IN_LABEL
-/* Writing `int' for a bitfield forces int alignment for the structure. */
+/* Writing `int' for a bit-field forces int alignment for the structure. */
+#ifndef PCC_BITFIELD_TYPE_MATTERS
#define PCC_BITFIELD_TYPE_MATTERS 1
+#endif
/* Implicit library calls should use memcpy, not bcopy, etc. */
@@ -56,19 +58,15 @@ Boston, MA 02111-1307, USA. */
/* Handle #pragma weak and #pragma pack. */
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
/* System V Release 4 uses DWARF debugging info. */
-#ifndef DWARF_DEBUGGING_INFO
#define DWARF_DEBUGGING_INFO 1
-#endif
/* All ELF targets can support DWARF-2. */
-#ifndef DWARF2_DEBUGGING_INFO
#define DWARF2_DEBUGGING_INFO 1
-#endif
/* The GNU tools operate better with dwarf2, and it is required by some
psABI's. Since we don't have any native tools to be compatible with,
@@ -172,7 +170,7 @@ Boston, MA 02111-1307, USA. */
in each assembly file where they are referenced. */
#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
- ASM_GLOBALIZE_LABEL (FILE, XSTR (FUN, 0))
+ (*targetm.asm_out.globalize_label) (FILE, XSTR (FUN, 0))
/* This says how to output assembler code to declare an
uninitialized external linkage data object. Under SVR4,
@@ -216,17 +214,8 @@ Boston, MA 02111-1307, USA. */
#undef ASCII_DATA_ASM_OP
#define ASCII_DATA_ASM_OP "\t.ascii\t"
-/* Support const sections and the ctors and dtors sections for g++.
- Note that there appears to be two different ways to support const
- sections at the moment. You can either #define the symbol
- READONLY_DATA_SECTION (giving it some code which switches to the
- readonly data section) or else you can #define the symbols
- EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
- SELECT_RTX_SECTION. We do both here just to be on the safe side. */
-
-#define USE_CONST_SECTION 1
-
-#define CONST_SECTION_ASM_OP "\t.section\t.rodata"
+/* Support a read-only data section. */
+#define READONLY_DATA_SECTION_ASM_OP "\t.section\t.rodata"
/* On svr4, we *do* have support for the .init and .fini sections, and we
can put stuff in there to be executed before and after `main'. We let
@@ -237,176 +226,22 @@ Boston, MA 02111-1307, USA. */
#define INIT_SECTION_ASM_OP "\t.section\t.init"
#define FINI_SECTION_ASM_OP "\t.section\t.fini"
-#ifdef HAVE_GAS_SUBSECTION_ORDERING
-
-#define ASM_SECTION_START_OP "\t.subsection\t-1"
-
/* Output assembly directive to move to the beginning of current section. */
-#define ASM_OUTPUT_SECTION_START(FILE) \
+#ifdef HAVE_GAS_SUBSECTION_ORDERING
+# define ASM_SECTION_START_OP "\t.subsection\t-1"
+# define ASM_OUTPUT_SECTION_START(FILE) \
fprintf ((FILE), "%s\n", ASM_SECTION_START_OP)
-
#endif
-/* A default list of other sections which we might be "in" at any given
- time. For targets that use additional sections (e.g. .tdesc) you
- should override this definition in the target-specific file which
- includes this file. */
-
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const
-
-/* A default list of extra section function definitions. For targets
- that use additional sections (e.g. .tdesc) you should override this
- definition in the target-specific file which includes this file. */
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- CONST_SECTION_FUNCTION
-
-#define READONLY_DATA_SECTION() const_section ()
-
-#define CONST_SECTION_FUNCTION \
-void \
-const_section () \
-{ \
- if (!USE_CONST_SECTION) \
- text_section (); \
- else if (in_section != in_const) \
- { \
- fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
- in_section = in_const; \
- } \
-}
-
#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
-
-#define UNIQUE_SECTION(DECL, RELOC) \
- do \
- { \
- int len; \
- int sec; \
- const char *name; \
- char *string; \
- const char *prefix; \
- static const char *const prefixes[4][2] = \
- { \
- { ".text.", ".gnu.linkonce.t." }, \
- { ".rodata.", ".gnu.linkonce.r." }, \
- { ".data.", ".gnu.linkonce.d." }, \
- { ".bss.", ".gnu.linkonce.b." } \
- }; \
- \
- if (TREE_CODE (DECL) == FUNCTION_DECL) \
- sec = 0; \
- else if (DECL_INITIAL (DECL) == 0 \
- || DECL_INITIAL (DECL) == error_mark_node) \
- sec = 3; \
- else if (DECL_READONLY_SECTION (DECL, RELOC)) \
- sec = 1; \
- else \
- sec = 2; \
- \
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
- /* Strip off any encoding in name. */ \
- STRIP_NAME_ENCODING (name, name); \
- prefix = prefixes[sec][DECL_ONE_ONLY(DECL)]; \
- len = strlen (name) + strlen (prefix); \
- string = alloca (len + 1); \
- \
- sprintf (string, "%s%s", prefix, name); \
- \
- DECL_SECTION_NAME (DECL) = build_string (len, string); \
- } \
- while (0)
/* Switch into a generic section. */
#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
-/* A C statement or statements to switch to the appropriate
- section for output of RTX in mode MODE. RTX is some kind
- of constant in RTL. The argument MODE is redundant except
- in the case of a `const_int' rtx.
- If assembler supports SHF_MERGE sections, put it into
- a .rodata.cstN section where N is size of the constant,
- otherwise into const section. */
-
-#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE, RTX, ALIGN) \
- mergeable_constant_section ((MODE), (ALIGN), 0)
-
-/* A C statement or statements to switch to the appropriate
- section for output of DECL. DECL is either a `VAR_DECL' node
- or a constant of some sort. RELOC indicates whether forming
- the initial value of DECL requires link-time relocations.
-
- To optimize loading of shared programs, define following subsections
- of data section by attaching:
-
- .rel
- Section with this string in name contains data that do have
- relocations, so they get grouped together and dynamic linker
- will visit fewer pages in memory.
- .ro
- Marks data read only otherwise. This is useful with prelinking
- as most of relocations won't be dynamically linked and thus
- stay read only.
- .local
- Marks data containing relocations only to local objects. These
- relocation will get fully resolved by prelinking.
- */
-
-#undef SELECT_SECTION
-#define SELECT_SECTION(DECL, RELOC, ALIGN) \
-{ \
- if (TREE_CODE (DECL) == STRING_CST) \
- { \
- if (! flag_writable_strings) \
- mergeable_string_section ((DECL), (ALIGN), 0); \
- else \
- data_section (); \
- } \
- else if (TREE_CODE (DECL) == VAR_DECL) \
- { \
- if (!TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
- || !DECL_INITIAL (DECL) \
- || (DECL_INITIAL (DECL) != error_mark_node \
- && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \
- { \
- if (flag_pic && ((RELOC) & 2)) \
- named_section (NULL_TREE, ".data.rel", RELOC); \
- else if (flag_pic && (RELOC)) \
- named_section (NULL_TREE, ".data.rel.local", RELOC);\
- else \
- data_section (); \
- } \
- else if (flag_pic && ((RELOC) & 2)) \
- named_section (NULL_TREE, ".data.rel.ro", RELOC); \
- else if (flag_pic && (RELOC)) \
- named_section (NULL_TREE, ".data.rel.ro.local", RELOC); \
- else if (flag_merge_constants < 2) \
- /* C and C++ don't allow different variables to share \
- the same location. -fmerge-all-constants allows \
- even that (at the expense of not conforming). */ \
- const_section (); \
- else if (TREE_CODE (DECL_INITIAL (DECL)) == STRING_CST) \
- mergeable_string_section (DECL_INITIAL (DECL), (ALIGN), \
- 0); \
- else \
- mergeable_constant_section (DECL_MODE (DECL), (ALIGN), \
- 0); \
- } \
- else if (TREE_CODE (DECL) == CONSTRUCTOR) \
- { \
- if ((flag_pic && RELOC) \
- || TREE_SIDE_EFFECTS (DECL) \
- || ! TREE_CONSTANT (DECL)) \
- data_section (); \
- else \
- const_section (); \
- } \
- else \
- const_section (); \
-}
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION default_elf_select_rtx_section
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION default_elf_select_section
/* Define the strings used for the special svr4 .type and .size directives.
These strings generally do not vary from one system running svr4 to
@@ -454,18 +289,13 @@ const_section () \
function's return value. We allow for that here. */
#ifndef ASM_DECLARE_FUNCTION_NAME
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
- do \
- { \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
- putc ('\n', FILE); \
- \
- ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
- ASM_OUTPUT_LABEL(FILE, NAME); \
- } \
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
+ ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+ } \
while (0)
#endif
@@ -474,26 +304,19 @@ const_section () \
#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
do \
{ \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
- putc ('\n', FILE); \
- \
+ HOST_WIDE_INT size; \
+ \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
+ \
size_directive_output = 0; \
- \
if (!flag_inhibit_size_directive \
&& (DECL) && DECL_SIZE (DECL)) \
{ \
size_directive_output = 1; \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \
- int_size_in_bytes (TREE_TYPE (DECL))); \
- fputc ('\n', FILE); \
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \
} \
- \
+ \
ASM_OUTPUT_LABEL (FILE, NAME); \
} \
while (0)
@@ -508,6 +331,7 @@ const_section () \
do \
{ \
const char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
+ HOST_WIDE_INT size; \
\
if (!flag_inhibit_size_directive \
&& DECL_SIZE (DECL) \
@@ -516,12 +340,8 @@ const_section () \
&& !size_directive_output) \
{ \
size_directive_output = 1; \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, name); \
- putc (',', FILE); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \
- int_size_in_bytes (TREE_TYPE (DECL))); \
- fputc ('\n', FILE); \
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, name, size); \
} \
} \
while (0)
@@ -532,23 +352,7 @@ const_section () \
do \
{ \
if (!flag_inhibit_size_directive) \
- { \
- char label[256]; \
- static int labelno; \
- \
- labelno++; \
- \
- ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \
- ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \
- \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, (FNAME)); \
- fprintf (FILE, ","); \
- assemble_name (FILE, label); \
- fprintf (FILE, "-"); \
- assemble_name (FILE, (FNAME)); \
- putc ('\n', FILE); \
- } \
+ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
} \
while (0)
#endif
@@ -598,7 +402,7 @@ const_section () \
generated assembly code more compact (and thus faster to assemble)
as well as more readable, especially for targets like the i386
(where the only alternative is to output character sequences as
- comma separated lists of numbers). */
+ comma separated lists of numbers). */
#define ASM_OUTPUT_LIMITED_STRING(FILE, STR) \
do \
diff --git a/contrib/gcc/config/fp-bit.c b/contrib/gcc/config/fp-bit.c
index 94e11e7..e609760 100644
--- a/contrib/gcc/config/fp-bit.c
+++ b/contrib/gcc/config/fp-bit.c
@@ -1,6 +1,6 @@
/* This is a software floating point library which can be used
for targets without hardware floating point.
- Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
This file is free software; you can redistribute it and/or modify it
@@ -46,7 +46,7 @@ Boston, MA 02111-1307, USA. */
#include "tconfig.h"
#include "fp-bit.h"
-/* The following macros can be defined to change the behaviour of this file:
+/* The following macros can be defined to change the behavior of this file:
FLOAT: Implement a `float', aka SFmode, fp library. If this is not
defined, then this file implements a `double', aka DFmode, fp library.
FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e.
@@ -74,39 +74,47 @@ Boston, MA 02111-1307, USA. */
are referenced from within libc, since libgcc goes before and after the
system library. */
+#ifdef DECLARE_LIBRARY_RENAMES
+ DECLARE_LIBRARY_RENAMES
+#endif
+
#ifdef EXTENDED_FLOAT_STUBS
-__truncxfsf2 (){ abort(); }
-__extendsfxf2 (){ abort(); }
-__addxf3 (){ abort(); }
-__divxf3 (){ abort(); }
-__eqxf2 (){ abort(); }
-__extenddfxf2 (){ abort(); }
-__gtxf2 (){ abort(); }
-__lexf2 (){ abort(); }
-__ltxf2 (){ abort(); }
-__mulxf3 (){ abort(); }
-__negxf2 (){ abort(); }
-__nexf2 (){ abort(); }
-__subxf3 (){ abort(); }
-__truncxfdf2 (){ abort(); }
-
-__trunctfsf2 (){ abort(); }
-__extendsftf2 (){ abort(); }
-__addtf3 (){ abort(); }
-__divtf3 (){ abort(); }
-__eqtf2 (){ abort(); }
-__extenddftf2 (){ abort(); }
-__gttf2 (){ abort(); }
-__letf2 (){ abort(); }
-__lttf2 (){ abort(); }
-__multf3 (){ abort(); }
-__negtf2 (){ abort(); }
-__netf2 (){ abort(); }
-__subtf3 (){ abort(); }
-__trunctfdf2 (){ abort(); }
-__gexf2 (){ abort(); }
-__fixxfsi (){ abort(); }
-__floatsixf (){ abort(); }
+extern void abort (void);
+void __extendsfxf2 (void) { abort(); }
+void __extenddfxf2 (void) { abort(); }
+void __truncxfdf2 (void) { abort(); }
+void __truncxfsf2 (void) { abort(); }
+void __fixxfsi (void) { abort(); }
+void __floatsixf (void) { abort(); }
+void __addxf3 (void) { abort(); }
+void __subxf3 (void) { abort(); }
+void __mulxf3 (void) { abort(); }
+void __divxf3 (void) { abort(); }
+void __negxf2 (void) { abort(); }
+void __eqxf2 (void) { abort(); }
+void __nexf2 (void) { abort(); }
+void __gtxf2 (void) { abort(); }
+void __gexf2 (void) { abort(); }
+void __lexf2 (void) { abort(); }
+void __ltxf2 (void) { abort(); }
+
+void __extendsftf2 (void) { abort(); }
+void __extenddftf2 (void) { abort(); }
+void __trunctfdf2 (void) { abort(); }
+void __trunctfsf2 (void) { abort(); }
+void __fixtfsi (void) { abort(); }
+void __floatsitf (void) { abort(); }
+void __addtf3 (void) { abort(); }
+void __subtf3 (void) { abort(); }
+void __multf3 (void) { abort(); }
+void __divtf3 (void) { abort(); }
+void __negtf2 (void) { abort(); }
+void __eqtf2 (void) { abort(); }
+void __netf2 (void) { abort(); }
+void __gttf2 (void) { abort(); }
+void __getf2 (void) { abort(); }
+void __letf2 (void) { abort(); }
+void __lttf2 (void) { abort(); }
#else /* !EXTENDED_FLOAT_STUBS, rest of file */
/* IEEE "special" number predicates */
@@ -122,6 +130,10 @@ __floatsixf (){ abort(); }
const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
#elif defined L_thenan_df
const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} };
+#elif defined L_thenan_tf
+const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
+#elif defined TFLOAT
+extern const fp_number_type __thenan_tf;
#elif defined FLOAT
extern const fp_number_type __thenan_sf;
#else
@@ -132,8 +144,10 @@ INLINE
static fp_number_type *
nan (void)
{
- /* Discard the const qualifier... */
-#ifdef FLOAT
+ /* Discard the const qualifier... */
+#ifdef TFLOAT
+ return (fp_number_type *) (& __thenan_tf);
+#elif defined FLOAT
return (fp_number_type *) (& __thenan_sf);
#else
return (fp_number_type *) (& __thenan_df);
@@ -172,7 +186,7 @@ flip_sign ( fp_number_type * x)
extern FLO_type pack_d ( fp_number_type * );
-#if defined(L_pack_df) || defined(L_pack_sf)
+#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
FLO_type
pack_d ( fp_number_type * src)
{
@@ -181,7 +195,15 @@ pack_d ( fp_number_type * src)
int sign = src->sign;
int exp = 0;
- if (isnan (src))
+ if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
+ {
+ /* We can't represent these values accurately. By using the
+ largest possible magnitude, we guarantee that the conversion
+ of infinity is at least as big as any finite number. */
+ exp = EXPMAX;
+ fraction = ((fractype) 1 << FRACBITS) - 1;
+ }
+ else if (isnan (src))
{
exp = EXPMAX;
if (src->class == CLASS_QNAN || 1)
@@ -207,6 +229,13 @@ pack_d ( fp_number_type * src)
{
if (src->normal_exp < NORMAL_EXPMIN)
{
+#ifdef NO_DENORMALS
+ /* Go straight to a zero representation if denormals are not
+ supported. The denormal handling would be harmless but
+ isn't unnecessary. */
+ exp = 0;
+ fraction = 0;
+#else /* NO_DENORMALS */
/* This number's exponent is too low to fit into the bits
available in the number, so we'll store 0 in the exponent and
shift the fraction to the right to make up for it. */
@@ -242,8 +271,10 @@ pack_d ( fp_number_type * src)
exp += 1;
}
fraction >>= NGARDS;
+#endif /* NO_DENORMALS */
}
- else if (src->normal_exp > EXPBIAS)
+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
+ && src->normal_exp > EXPBIAS)
{
exp = EXPMAX;
fraction = 0;
@@ -251,25 +282,35 @@ pack_d ( fp_number_type * src)
else
{
exp = src->normal_exp + EXPBIAS;
- /* IF the gard bits are the all zero, but the first, then we're
- half way between two numbers, choose the one which makes the
- lsb of the answer 0. */
- if ((fraction & GARDMASK) == GARDMSB)
- {
- if (fraction & (1 << NGARDS))
- fraction += GARDROUND + 1;
- }
- else
+ if (!ROUND_TOWARDS_ZERO)
{
- /* Add a one to the guards to round up */
- fraction += GARDROUND;
+ /* IF the gard bits are the all zero, but the first, then we're
+ half way between two numbers, choose the one which makes the
+ lsb of the answer 0. */
+ if ((fraction & GARDMASK) == GARDMSB)
+ {
+ if (fraction & (1 << NGARDS))
+ fraction += GARDROUND + 1;
+ }
+ else
+ {
+ /* Add a one to the guards to round up */
+ fraction += GARDROUND;
+ }
+ if (fraction >= IMPLICIT_2)
+ {
+ fraction >>= 1;
+ exp += 1;
+ }
}
- if (fraction >= IMPLICIT_2)
+ fraction >>= NGARDS;
+
+ if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
{
- fraction >>= 1;
- exp += 1;
+ /* Saturate on overflow. */
+ exp = EXPMAX;
+ fraction = ((fractype) 1 << FRACBITS) - 1;
}
- fraction >>= NGARDS;
}
}
@@ -281,24 +322,92 @@ pack_d ( fp_number_type * src)
dst.bits.exp = exp;
dst.bits.sign = sign;
#else
+# if defined TFLOAT && defined HALFFRACBITS
+ {
+ halffractype high, low;
+
+ high = (fraction >> (FRACBITS - HALFFRACBITS));
+ high &= (((fractype)1) << HALFFRACBITS) - 1;
+ high |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << HALFFRACBITS;
+ high |= ((fractype) (sign & 1)) << (HALFFRACBITS | EXPBITS);
+
+ low = (halffractype)fraction &
+ ((((halffractype)1) << (FRACBITS - HALFFRACBITS)) - 1);
+
+ if (exp == EXPMAX || exp == 0 || low == 0)
+ low = 0;
+ else
+ {
+ exp -= HALFFRACBITS + 1;
+
+ while (exp > 0
+ && low < ((halffractype)1 << HALFFRACBITS))
+ {
+ low <<= 1;
+ exp--;
+ }
+
+ if (exp <= 0)
+ {
+ halffractype roundmsb, round;
+
+ exp = -exp + 1;
+
+ roundmsb = (1 << (exp - 1));
+ round = low & ((roundmsb << 1) - 1);
+
+ low >>= exp;
+ exp = 0;
+
+ if (round > roundmsb || (round == roundmsb && (low & 1)))
+ {
+ low++;
+ if (low >= ((halffractype)1 << HALFFRACBITS))
+ /* We don't shift left, since it has just become the
+ smallest normal number, whose implicit 1 bit is
+ now indicated by the non-zero exponent. */
+ exp++;
+ }
+ }
+
+ low &= ((halffractype)1 << HALFFRACBITS) - 1;
+ low |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << HALFFRACBITS;
+ low |= ((fractype) (sign & 1)) << (HALFFRACBITS | EXPBITS);
+ }
+
+ dst.value_raw = (((fractype) high) << HALFSHIFT) | low;
+ }
+# else
dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS;
dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS);
+# endif
#endif
#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
+#ifdef TFLOAT
+ {
+ qrtrfractype tmp1 = dst.words[0];
+ qrtrfractype tmp2 = dst.words[1];
+ dst.words[0] = dst.words[3];
+ dst.words[1] = dst.words[2];
+ dst.words[2] = tmp2;
+ dst.words[3] = tmp1;
+ }
+#else
{
halffractype tmp = dst.words[0];
dst.words[0] = dst.words[1];
dst.words[1] = tmp;
}
#endif
+#endif
return dst.value;
}
#endif
-#if defined(L_unpack_df) || defined(L_unpack_sf)
+#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
void
unpack_d (FLO_union_type * src, fp_number_type * dst)
{
@@ -312,8 +421,15 @@ unpack_d (FLO_union_type * src, fp_number_type * dst)
#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
FLO_union_type swapped;
+#ifdef TFLOAT
+ swapped.words[0] = src->words[3];
+ swapped.words[1] = src->words[2];
+ swapped.words[2] = src->words[1];
+ swapped.words[3] = src->words[0];
+#else
swapped.words[0] = src->words[1];
swapped.words[1] = src->words[0];
+#endif
src = &swapped;
#endif
@@ -322,9 +438,46 @@ unpack_d (FLO_union_type * src, fp_number_type * dst)
exp = src->bits.exp;
sign = src->bits.sign;
#else
- fraction = src->value_raw & ((((fractype)1) << FRACBITS) - (fractype)1);
+# if defined TFLOAT && defined HALFFRACBITS
+ {
+ halffractype high, low;
+
+ high = src->value_raw >> HALFSHIFT;
+ low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1);
+
+ fraction = high & ((((fractype)1) << HALFFRACBITS) - 1);
+ fraction <<= FRACBITS - HALFFRACBITS;
+ exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
+ sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1;
+
+ if (exp != EXPMAX && exp != 0 && low != 0)
+ {
+ int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
+ int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1;
+ int shift;
+ fractype xlow;
+
+ xlow = low & ((((fractype)1) << HALFFRACBITS) - 1);
+ if (lowexp)
+ xlow |= (((halffractype)1) << HALFFRACBITS);
+ else
+ lowexp = 1;
+ shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp);
+ if (shift > 0)
+ xlow <<= shift;
+ else if (shift < 0)
+ xlow >>= -shift;
+ if (sign == lowsign)
+ fraction += xlow;
+ else
+ fraction -= xlow;
+ }
+ }
+# else
+ fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1);
exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1);
sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1;
+# endif
#endif
dst->sign = sign;
@@ -342,7 +495,7 @@ unpack_d (FLO_union_type * src, fp_number_type * dst)
}
else
{
- /* Zero exponent with non zero fraction - it's denormalized,
+ /* Zero exponent with nonzero fraction - it's denormalized,
so there isn't a leading implicit one - we'll shift it so
it gets one. */
dst->normal_exp = exp - EXPBIAS + 1;
@@ -359,7 +512,7 @@ unpack_d (FLO_union_type * src, fp_number_type * dst)
dst->fraction.ll = fraction;
}
}
- else if (exp == EXPMAX)
+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
{
/* Huge exponent*/
if (fraction == 0)
@@ -369,7 +522,7 @@ unpack_d (FLO_union_type * src, fp_number_type * dst)
}
else
{
- /* Non zero fraction, means nan */
+ /* Nonzero fraction, means nan */
if (fraction & QUIET_NAN)
{
dst->class = CLASS_QNAN;
@@ -392,7 +545,7 @@ unpack_d (FLO_union_type * src, fp_number_type * dst)
}
#endif /* L_unpack_df || L_unpack_sf */
-#if defined(L_addsub_sf) || defined(L_addsub_df)
+#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
static fp_number_type *
_fpadd_parts (fp_number_type * a,
fp_number_type * b,
@@ -576,8 +729,8 @@ sub (FLO_type arg_a, FLO_type arg_b)
}
#endif /* L_addsub_sf || L_addsub_df */
-#if defined(L_mul_sf) || defined(L_mul_df)
-static INLINE fp_number_type *
+#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
+static inline __attribute__ ((__always_inline__)) fp_number_type *
_fpmul_parts ( fp_number_type * a,
fp_number_type * b,
fp_number_type * tmp)
@@ -625,7 +778,7 @@ _fpmul_parts ( fp_number_type * a,
/* Calculate the mantissa by multiplying both numbers to get a
twice-as-wide number. */
{
-#if defined(NO_DI_MODE)
+#if defined(NO_DI_MODE) || defined(TFLOAT)
{
fractype x = a->fraction.ll;
fractype ylow = b->fraction.ll;
@@ -688,13 +841,9 @@ _fpmul_parts ( fp_number_type * a,
#endif
}
- tmp->normal_exp = a->normal_exp + b->normal_exp;
+ tmp->normal_exp = a->normal_exp + b->normal_exp
+ + FRAC_NBITS - (FRACBITS + NGARDS);
tmp->sign = a->sign != b->sign;
-#ifdef FLOAT
- tmp->normal_exp += 2; /* ??????????????? */
-#else
- tmp->normal_exp += 4; /* ??????????????? */
-#endif
while (high >= IMPLICIT_2)
{
tmp->normal_exp++;
@@ -714,14 +863,14 @@ _fpmul_parts ( fp_number_type * a,
high |= 1;
low <<= 1;
}
- /* rounding is tricky. if we only round if it won't make us round later. */
+ /* rounding is tricky. if we only round if it won't make us round later. */
#if 0
if (low & FRACHIGH2)
{
if (((high & GARDMASK) != GARDMSB)
&& (((high + 1) & GARDMASK) == GARDMSB))
{
- /* don't round, it gets done again later. */
+ /* don't round, it gets done again later. */
}
else
{
@@ -729,7 +878,7 @@ _fpmul_parts ( fp_number_type * a,
}
}
#endif
- if ((high & GARDMASK) == GARDMSB)
+ if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
{
if (high & (1 << NGARDS))
{
@@ -768,8 +917,8 @@ multiply (FLO_type arg_a, FLO_type arg_b)
}
#endif /* L_mul_sf || L_mul_df */
-#if defined(L_div_sf) || defined(L_div_df)
-static INLINE fp_number_type *
+#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
+static inline __attribute__ ((__always_inline__)) fp_number_type *
_fpdiv_parts (fp_number_type * a,
fp_number_type * b)
{
@@ -839,7 +988,7 @@ _fpdiv_parts (fp_number_type * a,
numerator *= 2;
}
- if ((quotient & GARDMASK) == GARDMSB)
+ if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
{
if (quotient & (1 << NGARDS))
{
@@ -878,7 +1027,8 @@ divide (FLO_type arg_a, FLO_type arg_b)
}
#endif /* L_div_sf || L_div_df */
-#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df)
+#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
+ || defined(L_fpcmp_parts_tf)
/* according to the demo, fpcmp returns a comparison with 0... thus
a<b -> -1
a==b -> 0
@@ -889,7 +1039,7 @@ int
__fpcmp_parts (fp_number_type * a, fp_number_type * b)
{
#if 0
- /* either nan -> unordered. Must be checked outside of this routine. */
+ /* either nan -> unordered. Must be checked outside of this routine. */
if (isnan (a) && isnan (b))
{
return 1; /* still unordered! */
@@ -909,11 +1059,11 @@ __fpcmp_parts (fp_number_type * a, fp_number_type * b)
-------+--------+--------
-inf(1)| a>b(1) | a==b(0)
-------+--------+--------
- So since unordered must be non zero, just line up the columns...
+ So since unordered must be nonzero, just line up the columns...
*/
return b->sign - a->sign;
}
- /* but not both... */
+ /* but not both... */
if (isinf (a))
{
return a->sign ? -1 : 1;
@@ -934,7 +1084,7 @@ __fpcmp_parts (fp_number_type * a, fp_number_type * b)
{
return a->sign ? -1 : 1;
}
- /* now both are "normal". */
+ /* now both are "normal". */
if (a->sign != b->sign)
{
/* opposite signs */
@@ -949,7 +1099,7 @@ __fpcmp_parts (fp_number_type * a, fp_number_type * b)
{
return a->sign ? 1 : -1;
}
- /* same exponents; check size. */
+ /* same exponents; check size. */
if (a->fraction.ll > b->fraction.ll)
{
return a->sign ? -1 : 1;
@@ -958,12 +1108,12 @@ __fpcmp_parts (fp_number_type * a, fp_number_type * b)
{
return a->sign ? 1 : -1;
}
- /* after all that, they're equal. */
+ /* after all that, they're equal. */
return 0;
}
#endif
-#if defined(L_compare_sf) || defined(L_compare_df)
+#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
CMPtype
compare (FLO_type arg_a, FLO_type arg_b)
{
@@ -985,7 +1135,7 @@ compare (FLO_type arg_a, FLO_type arg_b)
/* These should be optimized for their specific tasks someday. */
-#if defined(L_eq_sf) || defined(L_eq_df)
+#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
CMPtype
_eq_f2 (FLO_type arg_a, FLO_type arg_b)
{
@@ -1006,7 +1156,7 @@ _eq_f2 (FLO_type arg_a, FLO_type arg_b)
}
#endif /* L_eq_sf || L_eq_df */
-#if defined(L_ne_sf) || defined(L_ne_df)
+#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
CMPtype
_ne_f2 (FLO_type arg_a, FLO_type arg_b)
{
@@ -1027,7 +1177,7 @@ _ne_f2 (FLO_type arg_a, FLO_type arg_b)
}
#endif /* L_ne_sf || L_ne_df */
-#if defined(L_gt_sf) || defined(L_gt_df)
+#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
CMPtype
_gt_f2 (FLO_type arg_a, FLO_type arg_b)
{
@@ -1048,7 +1198,7 @@ _gt_f2 (FLO_type arg_a, FLO_type arg_b)
}
#endif /* L_gt_sf || L_gt_df */
-#if defined(L_ge_sf) || defined(L_ge_df)
+#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
CMPtype
_ge_f2 (FLO_type arg_a, FLO_type arg_b)
{
@@ -1068,7 +1218,7 @@ _ge_f2 (FLO_type arg_a, FLO_type arg_b)
}
#endif /* L_ge_sf || L_ge_df */
-#if defined(L_lt_sf) || defined(L_lt_df)
+#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
CMPtype
_lt_f2 (FLO_type arg_a, FLO_type arg_b)
{
@@ -1089,7 +1239,7 @@ _lt_f2 (FLO_type arg_a, FLO_type arg_b)
}
#endif /* L_lt_sf || L_lt_df */
-#if defined(L_le_sf) || defined(L_le_df)
+#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
CMPtype
_le_f2 (FLO_type arg_a, FLO_type arg_b)
{
@@ -1110,7 +1260,9 @@ _le_f2 (FLO_type arg_a, FLO_type arg_b)
}
#endif /* L_le_sf || L_le_df */
-#if defined(L_unord_sf) || defined(L_unord_df)
+#endif /* ! US_SOFTWARE_GOFAST */
+
+#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
CMPtype
_unord_f2 (FLO_type arg_a, FLO_type arg_b)
{
@@ -1128,9 +1280,7 @@ _unord_f2 (FLO_type arg_a, FLO_type arg_b)
}
#endif /* L_unord_sf || L_unord_df */
-#endif /* ! US_SOFTWARE_GOFAST */
-
-#if defined(L_si_to_sf) || defined(L_si_to_df)
+#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
FLO_type
si_to_float (SItype arg_a)
{
@@ -1158,7 +1308,7 @@ si_to_float (SItype arg_a)
else
in.fraction.ll = arg_a;
- while (in.fraction.ll < (1LL << (FRACBITS + NGARDS)))
+ while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
{
in.fraction.ll <<= 1;
in.normal_exp -= 1;
@@ -1168,7 +1318,7 @@ si_to_float (SItype arg_a)
}
#endif /* L_si_to_sf || L_si_to_df */
-#if defined(L_usi_to_sf) || defined(L_usi_to_df)
+#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
FLO_type
usi_to_float (USItype arg_a)
{
@@ -1185,12 +1335,12 @@ usi_to_float (USItype arg_a)
in.normal_exp = FRACBITS + NGARDS;
in.fraction.ll = arg_a;
- while (in.fraction.ll > (1LL << (FRACBITS + NGARDS)))
+ while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS)))
{
in.fraction.ll >>= 1;
in.normal_exp += 1;
}
- while (in.fraction.ll < (1LL << (FRACBITS + NGARDS)))
+ while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
{
in.fraction.ll <<= 1;
in.normal_exp -= 1;
@@ -1200,7 +1350,7 @@ usi_to_float (USItype arg_a)
}
#endif
-#if defined(L_sf_to_si) || defined(L_df_to_si)
+#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
SItype
float_to_si (FLO_type arg_a)
{
@@ -1215,7 +1365,7 @@ float_to_si (FLO_type arg_a)
return 0;
if (isnan (&a))
return 0;
- /* get reasonable MAX_SI_INT... */
+ /* get reasonable MAX_SI_INT... */
if (isinf (&a))
return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
/* it is a number, but a small one */
@@ -1228,8 +1378,8 @@ float_to_si (FLO_type arg_a)
}
#endif /* L_sf_to_si || L_df_to_si */
-#if defined(L_sf_to_usi) || defined(L_df_to_usi)
-#ifdef US_SOFTWARE_GOFAST
+#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
+#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi)
/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
we also define them for GOFAST because the ones in libgcc2.c have the
wrong names and I'd rather define these here and keep GOFAST CYG-LOC's
@@ -1252,7 +1402,7 @@ float_to_usi (FLO_type arg_a)
/* it is a negative number */
if (a.sign)
return 0;
- /* get reasonable MAX_USI_INT... */
+ /* get reasonable MAX_USI_INT... */
if (isinf (&a))
return MAX_USI_INT;
/* it is a number, but a small one */
@@ -1268,7 +1418,7 @@ float_to_usi (FLO_type arg_a)
#endif /* US_SOFTWARE_GOFAST */
#endif /* L_sf_to_usi || L_df_to_usi */
-#if defined(L_negate_sf) || defined(L_negate_df)
+#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
FLO_type
negate (FLO_type arg_a)
{
@@ -1324,6 +1474,21 @@ sf_to_df (SFtype arg_a)
}
#endif /* L_sf_to_df */
+#if defined(L_sf_to_tf) && defined(TMODES)
+TFtype
+sf_to_tf (SFtype arg_a)
+{
+ fp_number_type in;
+ FLO_union_type au;
+
+ au.value = arg_a;
+ unpack_d (&au, &in);
+
+ return __make_tp (in.class, in.sign, in.normal_exp,
+ ((UTItype) in.fraction.ll) << F_T_BITOFF);
+}
+#endif /* L_sf_to_df */
+
#endif /* ! FLOAT_ONLY */
#endif /* FLOAT */
@@ -1367,5 +1532,84 @@ df_to_sf (DFtype arg_a)
}
#endif /* L_df_to_sf */
+#if defined(L_df_to_tf) && defined(TMODES) \
+ && !defined(FLOAT) && !defined(TFLOAT)
+TFtype
+df_to_tf (DFtype arg_a)
+{
+ fp_number_type in;
+ FLO_union_type au;
+
+ au.value = arg_a;
+ unpack_d (&au, &in);
+
+ return __make_tp (in.class, in.sign, in.normal_exp,
+ ((UTItype) in.fraction.ll) << D_T_BITOFF);
+}
+#endif /* L_sf_to_df */
+
+#ifdef TFLOAT
+#if defined(L_make_tf)
+TFtype
+__make_tp(fp_class_type class,
+ unsigned int sign,
+ int exp,
+ UTItype frac)
+{
+ fp_number_type in;
+
+ in.class = class;
+ in.sign = sign;
+ in.normal_exp = exp;
+ in.fraction.ll = frac;
+ return pack_d (&in);
+}
+#endif /* L_make_tf */
+
+#if defined(L_tf_to_df)
+DFtype
+tf_to_df (TFtype arg_a)
+{
+ fp_number_type in;
+ UDItype sffrac;
+ FLO_union_type au;
+
+ au.value = arg_a;
+ unpack_d (&au, &in);
+
+ sffrac = in.fraction.ll >> D_T_BITOFF;
+
+ /* We set the lowest guard bit in SFFRAC if we discarded any non
+ zero bits. */
+ if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0)
+ sffrac |= 1;
+
+ return __make_dp (in.class, in.sign, in.normal_exp, sffrac);
+}
+#endif /* L_tf_to_df */
+
+#if defined(L_tf_to_sf)
+SFtype
+tf_to_sf (TFtype arg_a)
+{
+ fp_number_type in;
+ USItype sffrac;
+ FLO_union_type au;
+
+ au.value = arg_a;
+ unpack_d (&au, &in);
+
+ sffrac = in.fraction.ll >> F_T_BITOFF;
+
+ /* We set the lowest guard bit in SFFRAC if we discarded any non
+ zero bits. */
+ if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0)
+ sffrac |= 1;
+
+ return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
+}
+#endif /* L_tf_to_sf */
+#endif /* TFLOAT */
+
#endif /* ! FLOAT */
#endif /* !EXTENDED_FLOAT_STUBS */
diff --git a/contrib/gcc/config/fp-bit.h b/contrib/gcc/config/fp-bit.h
index ab1817a..0e8509e 100644
--- a/contrib/gcc/config/fp-bit.h
+++ b/contrib/gcc/config/fp-bit.h
@@ -1,5 +1,5 @@
/* Header file for fp-bit.c. */
-/* Copyright (C) 2000
+/* Copyright (C) 2000, 2002, 2003
Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -35,7 +35,7 @@ Boston, MA 02111-1307, USA. */
This avoids the need to pull in the entire fp emulation library
when only a small number of functions are needed.
- If FINE_GRAINED_LIBRARIES is not defined, then compile every
+ If FINE_GRAINED_LIBRARIES is not defined, then compile every
suitable routine. */
#ifndef FINE_GRAINED_LIBRARIES
#define L_pack_df
@@ -87,12 +87,22 @@ Boston, MA 02111-1307, USA. */
#endif
#endif /* ! FINE_GRAINED_LIBRARIES */
+#if __LDBL_MANT_DIG__ == 113 || __LDBL_MANT_DIG__ == 106
+# define TMODES
+#endif
+
typedef float SFtype __attribute__ ((mode (SF)));
typedef float DFtype __attribute__ ((mode (DF)));
+#ifdef TMODES
+typedef float TFtype __attribute__ ((mode (TF)));
+#endif
typedef int HItype __attribute__ ((mode (HI)));
typedef int SItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
+#ifdef TMODES
+typedef int TItype __attribute__ ((mode (TI)));
+#endif
/* The type of the result of a fp compare */
#ifndef CMPtype
@@ -102,16 +112,68 @@ typedef int DItype __attribute__ ((mode (DI)));
typedef unsigned int UHItype __attribute__ ((mode (HI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef unsigned int UDItype __attribute__ ((mode (DI)));
+#ifdef TMODES
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+#endif
#define MAX_USI_INT (~(USItype)0)
#define MAX_SI_INT ((SItype) (MAX_USI_INT >> 1))
#define BITS_PER_SI (4 * BITS_PER_UNIT)
+#ifdef TMODES
+#define MAX_UDI_INT (~(UDItype)0)
+#define MAX_DI_INT ((DItype) (MAX_UDI_INT >> 1))
+#define BITS_PER_DI (8 * BITS_PER_UNIT)
+#endif
#ifdef FLOAT_ONLY
#define NO_DI_MODE
#endif
-#ifdef FLOAT
+#ifdef TFLOAT
+# ifndef TMODES
+# error "TFLOAT requires long double to have 113 bits of mantissa"
+# endif
+
+# define PREFIXFPDP tp
+# define PREFIXSFDF tf
+# define NGARDS 10L /* Is this right? */
+# define GARDROUND 0x1ff
+# define GARDMASK 0x3ff
+# define GARDMSB 0x200
+# define FRAC_NBITS 128
+
+# if __LDBL_MANT_DIG__ == 113 /* IEEE quad */
+# define EXPBITS 15
+# define EXPBIAS 16383
+# define EXPMAX (0x7fff)
+# define QUIET_NAN ((TItype)0x8 << 108)
+# define FRACHIGH ((TItype)0x8 << 124)
+# define FRACHIGH2 ((TItype)0xc << 124)
+# define FRACBITS 112
+# endif
+
+# if __LDBL_MANT_DIG__ == 106 /* IBM extended (double+double) */
+# define EXPBITS 11
+# define EXPBIAS 1023
+# define EXPMAX (0x7ff)
+# define QUIET_NAN ((TItype)0x8 << (48 + 64))
+# define FRACHIGH ((TItype)0x8 << 124)
+# define FRACHIGH2 ((TItype)0xc << 124)
+# define FRACBITS 105
+# define HALFFRACBITS 52
+# define HALFSHIFT 64
+# endif
+
+# define pack_d __pack_t
+# define unpack_d __unpack_t
+# define __fpcmp_parts __fpcmp_parts_t
+ typedef UTItype fractype;
+ typedef UDItype halffractype;
+ typedef USItype qrtrfractype;
+#define qrtrfractype qrtrfractype
+ typedef TFtype FLO_type;
+ typedef TItype intfrac;
+#elif defined FLOAT
# define NGARDS 7L
# define GARDROUND 0x3f
# define GARDMASK 0x7f
@@ -157,34 +219,59 @@ typedef unsigned int UDItype __attribute__ ((mode (DI)));
#endif /* FLOAT */
#ifdef US_SOFTWARE_GOFAST
-# ifdef FLOAT
+# ifdef TFLOAT
+# error "GOFAST TFmode not supported"
+# elif defined FLOAT
# define add fpadd
# define sub fpsub
# define multiply fpmul
# define divide fpdiv
# define compare fpcmp
+# define _unord_f2 __unordsf2
# define usi_to_float __floatunsisf
# define si_to_float sitofp
# define float_to_si fptosi
# define float_to_usi fptoui
# define negate __negsf2
# define sf_to_df fptodp
-# define dptofp dptofp
-#else
+# define sf_to_tf __extendsftf2
+# else
# define add dpadd
# define sub dpsub
# define multiply dpmul
# define divide dpdiv
# define compare dpcmp
+# define _unord_f2 __unorddf2
# define usi_to_float __floatunsidf
# define si_to_float litodp
# define float_to_si dptoli
# define float_to_usi dptoul
# define negate __negdf2
# define df_to_sf dptofp
+# define df_to_tf __extenddftf2
# endif /* FLOAT */
#else
-# ifdef FLOAT
+# ifdef TFLOAT
+# define add __addtf3
+# define sub __subtf3
+# define multiply __multf3
+# define divide __divtf3
+# define compare __cmptf2
+# define _eq_f2 __eqtf2
+# define _ne_f2 __netf2
+# define _gt_f2 __gttf2
+# define _ge_f2 __getf2
+# define _lt_f2 __lttf2
+# define _le_f2 __letf2
+# define _unord_f2 __unordtf2
+# define usi_to_float __floatunsitf
+# define si_to_float __floatsitf
+# define float_to_si __fixtfsi
+# define float_to_usi __fixunstfsi
+# define negate __negtf2
+# define tf_to_sf __trunctfsf2
+# define tf_to_df __trunctfdf2
+# elif defined FLOAT
# define add __addsf3
# define sub __subsf3
# define multiply __mulsf3
@@ -203,7 +290,8 @@ typedef unsigned int UDItype __attribute__ ((mode (DI)));
# define float_to_usi __fixunssfsi
# define negate __negsf2
# define sf_to_df __extendsfdf2
-#else
+# define sf_to_tf __extendsftf2
+# else
# define add __adddf3
# define sub __subdf3
# define multiply __muldf3
@@ -222,6 +310,7 @@ typedef unsigned int UDItype __attribute__ ((mode (DI)));
# define float_to_usi __fixunsdfsi
# define negate __negdf2
# define df_to_sf __truncdfsf2
+# define df_to_tf __extenddftf2
# endif /* FLOAT */
#endif /* US_SOFTWARE_GOFAST */
@@ -239,10 +328,15 @@ typedef unsigned int UDItype __attribute__ ((mode (DI)));
*/
#define F_D_BITOFF (52+8-(23+7))
+#ifdef TMODES
+# define F_T_BITOFF (__LDBL_MANT_DIG__-1+10-(23+7))
+# define D_T_BITOFF (__LDBL_MANT_DIG__-1+10-(52+8))
+#endif
+
#define NORMAL_EXPMIN (-(EXPBIAS)+1)
-#define IMPLICIT_1 (1LL<<(FRACBITS+NGARDS))
-#define IMPLICIT_2 (1LL<<(FRACBITS+1+NGARDS))
+#define IMPLICIT_1 ((fractype)1<<(FRACBITS+NGARDS))
+#define IMPLICIT_2 ((fractype)1<<(FRACBITS+1+NGARDS))
/* common types */
@@ -280,7 +374,11 @@ typedef union
fractype value_raw;
#ifndef FLOAT
+# ifdef qrtrfractype
+ qrtrfractype qwords[4];
+# else
halffractype words[2];
+# endif
#endif
#ifdef FLOAT_BIT_ORDER_MISMATCH
@@ -315,82 +413,82 @@ FLO_union_type;
/* Prototypes */
-#if defined(L_pack_df) || defined(L_pack_sf)
+#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
extern FLO_type pack_d (fp_number_type *);
#endif
extern void unpack_d (FLO_union_type *, fp_number_type *);
-#if defined(L_addsub_sf) || defined(L_addsub_df)
+#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
extern FLO_type add (FLO_type, FLO_type);
extern FLO_type sub (FLO_type, FLO_type);
#endif
-#if defined(L_mul_sf) || defined(L_mul_df)
+#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
extern FLO_type multiply (FLO_type, FLO_type);
#endif
-#if defined(L_div_sf) || defined(L_div_df)
+#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
extern FLO_type divide (FLO_type, FLO_type);
#endif
extern int __fpcmp_parts (fp_number_type *, fp_number_type *);
-#if defined(L_compare_sf) || defined(L_compare_df)
+#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compare_tf)
extern CMPtype compare (FLO_type, FLO_type);
#endif
#ifndef US_SOFTWARE_GOFAST
-#if defined(L_eq_sf) || defined(L_eq_df)
+#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
extern CMPtype _eq_f2 (FLO_type, FLO_type);
#endif
-#if defined(L_ne_sf) || defined(L_ne_df)
+#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
extern CMPtype _ne_f2 (FLO_type, FLO_type);
#endif
-#if defined(L_gt_sf) || defined(L_gt_df)
+#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
extern CMPtype _gt_f2 (FLO_type, FLO_type);
#endif
-#if defined(L_ge_sf) || defined(L_ge_df)
+#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
extern CMPtype _ge_f2 (FLO_type, FLO_type);
#endif
-#if defined(L_lt_sf) || defined(L_lt_df)
+#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
extern CMPtype _lt_f2 (FLO_type, FLO_type);
#endif
-#if defined(L_le_sf) || defined(L_le_df)
+#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
extern CMPtype _le_f2 (FLO_type, FLO_type);
#endif
-#if defined(L_unord_sf) || defined(L_unord_df)
+#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
extern CMPtype _unord_f2 (FLO_type, FLO_type);
#endif
#endif /* ! US_SOFTWARE_GOFAST */
-#if defined(L_si_to_sf) || defined(L_si_to_df)
+#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
extern FLO_type si_to_float (SItype);
#endif
-#if defined(L_sf_to_si) || defined(L_df_to_si)
+#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
extern SItype float_to_si (FLO_type);
#endif
-#if defined(L_sf_to_usi) || defined(L_df_to_usi)
-#ifdef US_SOFTWARE_GOFAST
+#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
+#if defined(US_SOFTWARE_GOFAST) || defined(L_tf_to_usi)
extern USItype float_to_usi (FLO_type);
#endif
#endif
-#if defined(L_usi_to_sf) || defined(L_usi_to_df)
+#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
extern FLO_type usi_to_float (USItype);
#endif
-#if defined(L_negate_sf) || defined(L_negate_df)
+#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
extern FLO_type negate (FLO_type);
#endif
@@ -403,6 +501,9 @@ extern DFtype __make_dp (fp_class_type, unsigned int, int, UDItype);
#if defined(L_sf_to_df)
extern DFtype sf_to_df (SFtype);
#endif
+#if defined(L_sf_to_tf) && defined(TMODES)
+extern TFtype sf_to_tf (SFtype);
+#endif
#endif /* ! FLOAT_ONLY */
#endif /* FLOAT */
@@ -414,6 +515,25 @@ extern DFtype __make_dp (fp_class_type, unsigned int, int, UDItype);
#if defined(L_df_to_sf)
extern SFtype df_to_sf (DFtype);
#endif
+#if defined(L_df_to_tf) && defined(TMODES)
+extern TFtype df_to_tf (DFtype);
+#endif
#endif /* ! FLOAT */
+#ifdef TMODES
+extern DFtype __make_dp (fp_class_type, unsigned int, int, UDItype);
+extern TFtype __make_tp (fp_class_type, unsigned int, int, UTItype);
+#ifdef TFLOAT
+#if defined(L_tf_to_sf)
+extern SFtype tf_to_sf (TFtype);
+#endif
+#if defined(L_tf_to_df)
+extern DFtype tf_to_df (TFtype);
+#endif
+#if defined(L_di_to_tf)
+extern TFtype di_to_df (DItype);
+#endif
+#endif /* TFLOAT */
+#endif /* TMODES */
+
#endif /* ! GCC_FP_BIT_H */
diff --git a/contrib/gcc/config/freebsd-spec.h b/contrib/gcc/config/freebsd-spec.h
index 8b01536..4d81d80 100644
--- a/contrib/gcc/config/freebsd-spec.h
+++ b/contrib/gcc/config/freebsd-spec.h
@@ -48,30 +48,31 @@ Boston, MA 02111-1307, USA. */
|| !strcmp ((STR), "soname") || !strcmp ((STR), "defsym") \
|| !strcmp ((STR), "assert") || !strcmp ((STR), "dynamic-linker"))
-#if FBSD_MAJOR == 6
-#define FBSD_CPP_PREDEFINES \
- "-D__FreeBSD__=6 -Dunix -D__ELF__ -D__KPRINTF_ATTRIBUTE__ -Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
-#endif
-
-#if FBSD_MAJOR == 5
-#define FBSD_CPP_PREDEFINES \
- "-D__FreeBSD__=5 -Dunix -D__ELF__ -D__KPRINTF_ATTRIBUTE__ -Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
-#endif
-
-#if FBSD_MAJOR == 4
-#define FBSD_CPP_PREDEFINES \
- "-D__FreeBSD__=4 -Dunix -D__ELF__ -D__KPRINTF_ATTRIBUTE__ -Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
-#endif
-
-#if FBSD_MAJOR == 3
-#define FBSD_CPP_PREDEFINES \
- "-D__FreeBSD__=3 -Dunix -D__ELF__ -D__KPRINTF_ATTRIBUTE__ -Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
-#endif
-
-#ifndef FBSD_CPP_PREDEFINES
-#define FBSD_CPP_PREDEFINES \
- "-D__FreeBSD__ -Dunix -D__ELF__ -D__KPRINTF_ATTRIBUTE__ -Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
-#endif
+#define FBSD_TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ if (FBSD_MAJOR == 6) \
+ builtin_define ("__FreeBSD__=6"); \
+ else if (FBSD_MAJOR == 5) \
+ builtin_define ("__FreeBSD__=5"); \
+ else if (FBSD_MAJOR == 4) \
+ builtin_define ("__FreeBSD__=4"); \
+ else if (FBSD_MAJOR == 3) \
+ builtin_define ("__FreeBSD__=3"); \
+ else \
+ builtin_define ("__FreeBSD__"); \
+ builtin_define_std ("unix"); \
+ builtin_define ("__ELF__"); \
+ builtin_define ("__KPRINTF_ATTRIBUTE__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=bsd"); \
+ builtin_assert ("system=FreeBSD"); \
+ FBSD_TARGET_CPU_CPP_BUILTINS(); \
+ } \
+ while (0)
+
+/* Define the default FreeBSD-specific per-CPU hook code. */
+#define FBSD_TARGET_CPU_CPP_BUILTINS() do {} while (0)
/* Provide a CPP_SPEC appropriate for FreeBSD. We just deal with the GCC
option `-posix', and PIC issues. */
@@ -84,7 +85,7 @@ Boston, MA 02111-1307, USA. */
/* Provide a STARTFILE_SPEC appropriate for FreeBSD. Here we add
the magical crtbegin.o file (see crtstuff.c) which provides part
of the support for getting C++ file-scope static object constructed
- before entering `main'. */
+ before entering `main'. */
#define FBSD_STARTFILE_SPEC \
"%{!shared: \
diff --git a/contrib/gcc/config/freebsd.h b/contrib/gcc/config/freebsd.h
index e7647bb..f71bd8b 100644
--- a/contrib/gcc/config/freebsd.h
+++ b/contrib/gcc/config/freebsd.h
@@ -42,7 +42,10 @@ Boston, MA 02111-1307, USA. */
#define WORD_SWITCH_TAKES_ARG(STR) (FBSD_WORD_SWITCH_TAKES_ARG(STR))
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES FBSD_CPP_PREDEFINES
+/* Obsolete, do not define it. */
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() FBSD_TARGET_OS_CPP_BUILTINS()
#undef CPP_SPEC
#define CPP_SPEC FBSD_CPP_SPEC
@@ -67,17 +70,10 @@ Boston, MA 02111-1307, USA. */
#undef NO_IMPLICIT_EXTERN_C
#define NO_IMPLICIT_EXTERN_C 1
-/* Allow #sccs in preprocessor. */
-#undef SCCS_DIRECTIVE
-#define SCCS_DIRECTIVE 1
-
/* Make gcc agree with FreeBSD's standard headers (<machine/ansi.h>, etc...) */
#undef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-
-#undef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
+#define WCHAR_TYPE "int"
#define MATH_LIBRARY_PROFILE "-lm_p"
@@ -91,4 +87,4 @@ Boston, MA 02111-1307, USA. */
/* Used by libgcc2.c. We support file locking with fcntl / F_SETLKW.
This enables the test coverage code to use file locking when exiting a
program, which avoids race conditions if the program has forked. */
-#define TARGET_HAS_F_SETLKW 1
+#define TARGET_HAS_F_SETLKW
diff --git a/contrib/gcc/config/frv/cmovd.c b/contrib/gcc/config/frv/cmovd.c
new file mode 100644
index 0000000..11b50ba
--- /dev/null
+++ b/contrib/gcc/config/frv/cmovd.c
@@ -0,0 +1,47 @@
+/* Move double-word library function.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ Contributed by Red Hat, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software ; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation * either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY ; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+void
+__cmovd (long long *dest, const long long *src, unsigned len)
+{
+ unsigned i;
+ unsigned num = len >> 3;
+ unsigned xlen = len & ~7;
+ char *dest_byte = (char *)dest;
+ const char *src_byte = (const char *)src;
+
+ if (dest_byte < src_byte || dest_byte > src_byte+len)
+ {
+ for (i = 0; i < num; i++)
+ dest[i] = src[i];
+
+ while (len > xlen)
+ {
+ dest_byte[xlen] = src_byte[xlen];
+ xlen++;
+ }
+ }
+ else
+ {
+ while (len-- > 0)
+ dest_byte[len] = src_byte[len];
+ }
+}
diff --git a/contrib/gcc/config/frv/cmovh.c b/contrib/gcc/config/frv/cmovh.c
new file mode 100644
index 0000000..018a0b4
--- /dev/null
+++ b/contrib/gcc/config/frv/cmovh.c
@@ -0,0 +1,43 @@
+/* Move half-word library function.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ Contributed by Red Hat, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software ; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation * either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY ; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+void
+__cmovh (short *dest, const short *src, unsigned len)
+{
+ unsigned i;
+ unsigned num = len >> 1;
+ char *dest_byte = (char *)dest;
+ const char *src_byte = (const char *)src;
+
+ if (dest_byte < src_byte || dest_byte > src_byte+len)
+ {
+ for (i = 0; i < num; i++)
+ dest[i] = src[i];
+
+ if ((len & 1) != 0)
+ dest_byte[len-1] = src_byte[len-1];
+ }
+ else
+ {
+ while (len-- > 0)
+ dest_byte[len] = src_byte[len];
+ }
+}
diff --git a/contrib/gcc/config/frv/cmovw.c b/contrib/gcc/config/frv/cmovw.c
new file mode 100644
index 0000000..5509e06
--- /dev/null
+++ b/contrib/gcc/config/frv/cmovw.c
@@ -0,0 +1,47 @@
+/* Move word library function.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ Contributed by Red Hat, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software ; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation * either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY ; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+void
+__cmovw (int *dest, const int *src, unsigned len)
+{
+ unsigned i;
+ unsigned num = len >> 2;
+ unsigned xlen = len & ~3;
+ char *dest_byte = (char *)dest;
+ const char *src_byte = (const char *)src;
+
+ if (dest_byte < src_byte || dest_byte > src_byte+len)
+ {
+ for (i = 0; i < num; i++)
+ dest[i] = src[i];
+
+ while (len > xlen)
+ {
+ dest_byte[xlen] = src_byte[xlen];
+ xlen++;
+ }
+ }
+ else
+ {
+ while (len-- > 0)
+ dest_byte[len] = src_byte[len];
+ }
+}
diff --git a/contrib/gcc/config/frv/frv-abi.h b/contrib/gcc/config/frv/frv-abi.h
new file mode 100644
index 0000000..68fd32f
--- /dev/null
+++ b/contrib/gcc/config/frv/frv-abi.h
@@ -0,0 +1,181 @@
+/* Frv map GCC names to FR-V ABI.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ Contributed by Red Hat, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* For each of the functions in the library that has a corresponding name in
+ the ABI, add an equivalence between the GCC name and the ABI name. This is
+ in a separate file from frv.h so that fp-bit.c can be made to include it. */
+
+#ifdef __GNUC__
+#ifdef __FRV_UNDERSCORE__
+#define RENAME_LIBRARY(OLD,NEW) \
+__asm__ (".globl\t_" #NEW "\n" \
+ "_" #NEW "=_" #OLD "\n" \
+ "\t.type\t_" #NEW ",@function\n");
+
+#else
+#define RENAME_LIBRARY(OLD,NEW) \
+__asm__ (".globl\t" #NEW "\n" \
+ #NEW "=" #OLD "\n" \
+ "\t.type\t" #NEW ",@function\n");
+#endif
+
+#define CREATE_DOUBLE_SHIFT(OLD,NEW) \
+__asm__ (".text\n" \
+ "\t.globl\t" #NEW "\n" \
+ "\t.type\t" #NEW ",@function\n" \
+ #NEW ":\n" \
+ "\tor\tgr11, gr0, gr10\n" \
+ "\tbra\t" #OLD "\n");
+
+#ifdef L_sf_to_df
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__extendsfdf2,__ftod)
+#endif
+
+#ifdef L_sf_to_si
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixsfsi,__ftoi)
+#endif
+
+#ifdef L_sf_to_usi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunssfsi,__ftoui)
+#endif
+
+#ifdef L_df_to_si
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixdfsi,__dtoi)
+#endif
+
+#ifdef L_fixunssfsi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunssfsi,__ftoui)
+#endif
+
+#ifdef L_fixunsdfsi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunsdfsi,__dtoui)
+#endif
+
+#ifdef L_fixsfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixsfdi,__ftoll)
+#endif
+
+#ifdef L_fixdfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixdfdi,__dtoll)
+#endif
+
+#ifdef L_fixunssfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunssfdi,__ftoull)
+#endif
+
+#ifdef L_fixunsdfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__fixunsdfdi,__dtoull)
+#endif
+
+#ifdef L_si_to_sf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatsisf,__itof)
+#endif
+
+#ifdef L_di_to_sf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatdisf,__lltof)
+#endif
+
+#ifdef L_df_to_sf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__truncdfsf2,__dtof)
+#endif
+
+#ifdef L_si_to_df
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatsidf,__itod)
+#endif
+
+#ifdef L_floatdisf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatdisf,__lltof)
+#endif
+
+#ifdef L_floatdidf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__floatdidf,__lltod)
+#endif
+
+#ifdef L_addsub_df
+#define DECLARE_LIBRARY_RENAMES \
+ RENAME_LIBRARY(__adddf3,__addd)
+ RENAME_LIBRARY(__subdf3,__subd)
+#endif
+
+#ifdef L_mul_df
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__muldf3,__muld)
+#endif
+
+#ifdef L_div_df
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__divdf3,__divd)
+#endif
+
+#ifdef L_addsub_sf
+#define DECLARE_LIBRARY_RENAMES \
+ RENAME_LIBRARY(__addsf3,__addf) \
+ RENAME_LIBRARY(__subsf3,__subf)
+#endif
+
+#ifdef L_mul_sf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__mulsf3,__mulf)
+#endif
+
+#ifdef L_div_sf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__divsf3,__divf)
+#endif
+
+#ifdef L_ashldi3
+#define DECLARE_LIBRARY_RENAMES CREATE_DOUBLE_SHIFT (__ashldi3,__sllll)
+#endif
+
+#ifdef L_lshrdi3
+#define DECLARE_LIBRARY_RENAMES CREATE_DOUBLE_SHIFT (__lshrdi3,__srlll)
+#endif
+
+#ifdef L_ashrdi3
+#define DECLARE_LIBRARY_RENAMES CREATE_DOUBLE_SHIFT (__ashrdi3,__srall)
+#endif
+
+#ifdef L_adddi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__adddi3,__addll)
+#endif
+
+#ifdef L_subdi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__subdi3,__subll)
+#endif
+
+#ifdef L_muldi3
+#define DECLARE_LIBRARY_RENAMES \
+ RENAME_LIBRARY(__muldi3,__mulll)
+ RENAME_LIBRARY(__muldi3,__umulll)
+#endif
+
+#ifdef L_divdi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__divdi3,__divll)
+#endif
+
+#ifdef L_udivdi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__udivdi3,__udivll)
+#endif
+
+#ifdef L_moddi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__moddi3,__modll)
+#endif
+
+#ifdef L_umoddi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY(__umoddi3,__umodll)
+#endif
+#endif /* __GNUC__ */
diff --git a/contrib/gcc/config/frv/frv-asm.h b/contrib/gcc/config/frv/frv-asm.h
new file mode 100644
index 0000000..e8447a6
--- /dev/null
+++ b/contrib/gcc/config/frv/frv-asm.h
@@ -0,0 +1,49 @@
+/* Assembler Support.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ Contributed by Red Hat, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software ; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation * either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY ; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* P(INSN): Emit INSN.P for VLIW machines, otherwise emit plain INSN.
+ P2(INSN): Emit INSN.P on the FR500 and above, otherwise emit plain INSN. */
+#ifdef __FRV_VLIW__
+#ifdef __STDC__
+#define P(A) A##.p
+#else
+#define P(A) A/**/.p
+#endif
+#if __FRV_VLIW__ > 2
+#define P2(A) P(A)
+#else
+#define P2(A) A
+#endif
+#else
+#define P(A) A
+#define P2(A) A
+#endif
+
+/* Add underscore if necessary to external name. */
+#ifdef __FRV_UNDERSCORE__
+#ifdef __STDC__
+#define EXT(NAME) _##NAME
+#else
+#define EXT(NAME) _/**/NAME
+#endif
+#else
+#define EXT(NAME) NAME
+#endif
diff --git a/contrib/gcc/config/frv/frv-modes.def b/contrib/gcc/config/frv/frv-modes.def
new file mode 100644
index 0000000..ca7818c
--- /dev/null
+++ b/contrib/gcc/config/frv/frv-modes.def
@@ -0,0 +1,30 @@
+/* Definitions of target machine for GNU compiler for FRV.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* On the FRV, the CC modes used are:
+
+ CCmode set ICC's from comparing signed integers
+ CC_UNSmode set ICC's from comparing unsigned integers
+ CC_FPmode set FCC's from comparing floating point
+ CC_CCRmode set CCR's to do conditional execution */
+
+CC (CC_UNS)
+CC (CC_FP)
+CC (CC_CCR)
diff --git a/contrib/gcc/config/frv/frv-protos.h b/contrib/gcc/config/frv/frv-protos.h
new file mode 100644
index 0000000..4f5a422
--- /dev/null
+++ b/contrib/gcc/config/frv/frv-protos.h
@@ -0,0 +1,247 @@
+/* Frv prototypes.
+ Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ Contributed by Red Hat, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Define the information needed to generate branch and scc insns. This is
+ stored from the compare operation. Note that we can't use "rtx" here
+ since it hasn't been defined! */
+
+/* Define global data defined in frv.c */
+extern const char *frv_branch_cost_string; /* -mbranch-cost option */
+extern int frv_branch_cost_int; /* value of -mbranch_cost */
+
+extern const char *frv_cpu_string; /* -mcpu= option */
+
+extern const char *frv_condexec_insns_str; /* -mcond-exec-insns= option */
+extern int frv_condexec_insns; /* value of -mcond-exec-insns */
+
+extern const char *frv_condexec_temps_str; /* -mcond-exec-temps= option */
+extern int frv_condexec_temps; /* value of -mcond-exec-temps */
+
+extern const char *frv_sched_lookahead_str; /* -msched-lookahead= option */
+extern int frv_sched_lookahead; /* value -msched-lookahead= */
+
+/* CPU type. This must be identical to the cpu enumeration in frv.md. */
+typedef enum frv_cpu
+{
+ FRV_CPU_GENERIC,
+ FRV_CPU_FR500,
+ FRV_CPU_FR400,
+ FRV_CPU_FR300,
+ FRV_CPU_SIMPLE,
+ FRV_CPU_TOMCAT
+} frv_cpu_t;
+
+extern frv_cpu_t frv_cpu_type; /* value of -mcpu= */
+
+/* Define functions defined in frv.c */
+extern void frv_expand_prologue PARAMS ((void));
+extern void frv_expand_epilogue PARAMS ((int));
+extern void frv_override_options PARAMS ((void));
+extern void frv_optimization_options PARAMS ((int, int));
+extern void frv_conditional_register_usage PARAMS ((void));
+extern frv_stack_t *frv_stack_info PARAMS ((void));
+extern void frv_debug_stack PARAMS ((frv_stack_t *));
+extern int frv_frame_pointer_required PARAMS ((void));
+extern int frv_initial_elimination_offset PARAMS ((int, int));
+
+#ifdef RTX_CODE
+extern int frv_legitimate_address_p PARAMS ((enum machine_mode, rtx,
+ int, int));
+extern rtx frv_legitimize_address PARAMS ((rtx, rtx,
+ enum machine_mode));
+
+#ifdef TREE_CODE
+extern void frv_init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree,
+ rtx, int, int));
+
+extern int frv_function_arg_boundary PARAMS ((enum machine_mode, tree));
+extern rtx frv_function_arg PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode,
+ tree, int, int));
+
+extern void frv_function_arg_advance PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode,
+ tree, int));
+
+extern int frv_function_arg_partial_nregs PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode,
+ tree, int));
+
+extern int frv_function_arg_pass_by_reference PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode,
+ tree, int));
+
+extern int frv_function_arg_callee_copies PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode,
+ tree, int));
+
+extern int frv_function_arg_keep_as_reference PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode,
+ tree, int));
+
+extern rtx frv_expand_builtin_saveregs PARAMS ((void));
+extern void frv_setup_incoming_varargs PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode,
+ tree, int *, int));
+
+extern void frv_expand_builtin_va_start PARAMS ((tree, rtx));
+extern rtx frv_expand_builtin_va_arg PARAMS ((tree, tree));
+#endif /* TREE_CODE */
+
+extern int frv_expand_block_move PARAMS ((rtx *));
+extern int frv_expand_block_clear PARAMS ((rtx *));
+extern rtx frv_dynamic_chain_address PARAMS ((rtx));
+extern rtx frv_return_addr_rtx PARAMS ((int, rtx));
+extern rtx frv_index_memory PARAMS ((rtx,
+ enum machine_mode,
+ int));
+extern const char *frv_asm_output_opcode
+ PARAMS ((FILE *, const char *));
+extern void frv_final_prescan_insn PARAMS ((rtx, rtx *, int));
+extern void frv_print_operand PARAMS ((FILE *, rtx, int));
+extern void frv_print_operand_address PARAMS ((FILE *, rtx));
+extern int frv_emit_movsi PARAMS ((rtx, rtx));
+extern const char *output_move_single PARAMS ((rtx *, rtx));
+extern const char *output_move_double PARAMS ((rtx *, rtx));
+extern const char *output_condmove_single
+ PARAMS ((rtx *, rtx));
+extern int frv_emit_cond_branch PARAMS ((enum rtx_code, rtx));
+extern int frv_emit_scc PARAMS ((enum rtx_code, rtx));
+extern rtx frv_split_scc PARAMS ((rtx, rtx, rtx, rtx,
+ HOST_WIDE_INT));
+extern int frv_emit_cond_move PARAMS ((rtx, rtx, rtx, rtx));
+extern rtx frv_split_cond_move PARAMS ((rtx *));
+extern rtx frv_split_minmax PARAMS ((rtx *));
+extern rtx frv_split_abs PARAMS ((rtx *));
+extern void frv_split_double_load PARAMS ((rtx, rtx));
+extern void frv_split_double_store PARAMS ((rtx, rtx));
+#ifdef BLOCK_HEAD
+extern void frv_ifcvt_init_extra_fields PARAMS ((ce_if_block_t *));
+extern void frv_ifcvt_modify_tests PARAMS ((ce_if_block_t *,
+ rtx *, rtx *));
+extern void frv_ifcvt_modify_multiple_tests
+ PARAMS ((ce_if_block_t *,
+ basic_block,
+ rtx *, rtx *));
+extern rtx frv_ifcvt_modify_insn PARAMS ((ce_if_block_t *,
+ rtx, rtx));
+extern void frv_ifcvt_modify_final PARAMS ((ce_if_block_t *));
+extern void frv_ifcvt_modify_cancel PARAMS ((ce_if_block_t *));
+#endif
+extern int frv_trampoline_size PARAMS ((void));
+extern void frv_initialize_trampoline PARAMS ((rtx, rtx, rtx));
+extern enum reg_class frv_secondary_reload_class
+ PARAMS ((enum reg_class class,
+ enum machine_mode mode,
+ rtx x, int));
+extern int frv_class_likely_spilled_p PARAMS ((enum reg_class class));
+extern int frv_hard_regno_mode_ok PARAMS ((int, enum machine_mode));
+extern int frv_hard_regno_nregs PARAMS ((int, enum machine_mode));
+extern int frv_class_max_nregs PARAMS ((enum reg_class class,
+ enum machine_mode mode));
+extern int frv_legitimate_constant_p PARAMS ((rtx));
+#endif /* RTX_CODE */
+
+extern int direct_return_p PARAMS ((void));
+extern int frv_register_move_cost PARAMS ((enum reg_class, enum reg_class));
+
+#ifdef TREE_CODE
+extern int frv_adjust_field_align PARAMS ((tree, int));
+#endif
+
+extern void fixup_section PARAMS ((void));
+extern void sdata_section PARAMS ((void));
+extern void sbss_section PARAMS ((void));
+extern void const_section PARAMS ((void));
+extern void data_section PARAMS ((void));
+
+#ifdef RTX_CODE
+extern int integer_register_operand PARAMS ((rtx, enum machine_mode));
+extern int frv_load_operand PARAMS ((rtx, enum machine_mode));
+extern int gpr_or_fpr_operand PARAMS ((rtx, enum machine_mode));
+extern int gpr_no_subreg_operand PARAMS ((rtx, enum machine_mode));
+extern int gpr_or_int6_operand PARAMS ((rtx, enum machine_mode));
+extern int fpr_or_int6_operand PARAMS ((rtx, enum machine_mode));
+extern int gpr_or_int_operand PARAMS ((rtx, enum machine_mode));
+extern int gpr_or_int12_operand PARAMS ((rtx, enum machine_mode));
+extern int gpr_fpr_or_int12_operand PARAMS ((rtx, enum machine_mode));
+extern int gpr_or_int10_operand PARAMS ((rtx, enum machine_mode));
+extern int move_source_operand PARAMS ((rtx, enum machine_mode));
+extern int move_destination_operand PARAMS ((rtx, enum machine_mode));
+extern int condexec_source_operand PARAMS ((rtx, enum machine_mode));
+extern int condexec_dest_operand PARAMS ((rtx, enum machine_mode));
+extern int lr_operand PARAMS ((rtx, enum machine_mode));
+extern int gpr_or_memory_operand PARAMS ((rtx, enum machine_mode));
+extern int fpr_or_memory_operand PARAMS ((rtx, enum machine_mode));
+extern int reg_or_0_operand PARAMS ((rtx, enum machine_mode));
+extern int fcc_operand PARAMS ((rtx, enum machine_mode));
+extern int icc_operand PARAMS ((rtx, enum machine_mode));
+extern int cc_operand PARAMS ((rtx, enum machine_mode));
+extern int fcr_operand PARAMS ((rtx, enum machine_mode));
+extern int icr_operand PARAMS ((rtx, enum machine_mode));
+extern int cr_operand PARAMS ((rtx, enum machine_mode));
+extern int call_operand PARAMS ((rtx, enum machine_mode));
+extern int fpr_operand PARAMS ((rtx, enum machine_mode));
+extern int even_reg_operand PARAMS ((rtx, enum machine_mode));
+extern int odd_reg_operand PARAMS ((rtx, enum machine_mode));
+extern int even_gpr_operand PARAMS ((rtx, enum machine_mode));
+extern int odd_gpr_operand PARAMS ((rtx, enum machine_mode));
+extern int quad_fpr_operand PARAMS ((rtx, enum machine_mode));
+extern int even_fpr_operand PARAMS ((rtx, enum machine_mode));
+extern int odd_fpr_operand PARAMS ((rtx, enum machine_mode));
+extern int dbl_memory_one_insn_operand PARAMS ((rtx, enum machine_mode));
+extern int dbl_memory_two_insn_operand PARAMS ((rtx, enum machine_mode));
+extern int int12_operand PARAMS ((rtx, enum machine_mode));
+extern int int6_operand PARAMS ((rtx, enum machine_mode));
+extern int int5_operand PARAMS ((rtx, enum machine_mode));
+extern int uint5_operand PARAMS ((rtx, enum machine_mode));
+extern int uint4_operand PARAMS ((rtx, enum machine_mode));
+extern int uint1_operand PARAMS ((rtx, enum machine_mode));
+extern int int_2word_operand PARAMS ((rtx, enum machine_mode));
+extern int pic_register_operand PARAMS ((rtx, enum machine_mode));
+extern int pic_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int small_data_register_operand PARAMS ((rtx, enum machine_mode));
+extern int small_data_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int upper_int16_operand PARAMS ((rtx, enum machine_mode));
+extern int uint16_operand PARAMS ((rtx, enum machine_mode));
+extern int relational_operator PARAMS ((rtx, enum machine_mode));
+extern int signed_relational_operator PARAMS ((rtx, enum machine_mode));
+extern int unsigned_relational_operator PARAMS ((rtx, enum machine_mode));
+extern int float_relational_operator PARAMS ((rtx, enum machine_mode));
+extern int ccr_eqne_operator PARAMS ((rtx, enum machine_mode));
+extern int minmax_operator PARAMS ((rtx, enum machine_mode));
+extern int condexec_si_binary_operator PARAMS ((rtx, enum machine_mode));
+extern int condexec_si_media_operator PARAMS ((rtx, enum machine_mode));
+extern int condexec_si_divide_operator PARAMS ((rtx, enum machine_mode));
+extern int condexec_si_unary_operator PARAMS ((rtx, enum machine_mode));
+extern int condexec_sf_conv_operator PARAMS ((rtx, enum machine_mode));
+extern int condexec_sf_add_operator PARAMS ((rtx, enum machine_mode));
+extern int condexec_memory_operand PARAMS ((rtx, enum machine_mode));
+extern int intop_compare_operator PARAMS ((rtx, enum machine_mode));
+extern int condexec_intop_cmp_operator PARAMS ((rtx, enum machine_mode));
+extern int acc_operand PARAMS ((rtx, enum machine_mode));
+extern int even_acc_operand PARAMS ((rtx, enum machine_mode));
+extern int quad_acc_operand PARAMS ((rtx, enum machine_mode));
+extern int accg_operand PARAMS ((rtx, enum machine_mode));
+extern rtx frv_matching_accg_for_acc PARAMS ((rtx));
+extern void frv_machine_dependent_reorg PARAMS ((rtx));
+#endif
+
diff --git a/contrib/gcc/config/frv/frv.c b/contrib/gcc/config/frv/frv.c
new file mode 100644
index 0000000..d09533a
--- /dev/null
+++ b/contrib/gcc/config/frv/frv.c
@@ -0,0 +1,9788 @@
+/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Contributed by Red Hat, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "rtl.h"
+#include "tree.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-flags.h"
+#include "output.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "recog.h"
+#include "reload.h"
+#include "expr.h"
+#include "obstack.h"
+#include "except.h"
+#include "function.h"
+#include "optabs.h"
+#include "toplev.h"
+#include "basic-block.h"
+#include "tm_p.h"
+#include "ggc.h"
+#include <ctype.h>
+#include "target.h"
+#include "target-def.h"
+
+#ifndef FRV_INLINE
+#define FRV_INLINE inline
+#endif
+
+/* Temporary register allocation support structure. */
+typedef struct frv_tmp_reg_struct
+ {
+ HARD_REG_SET regs; /* possible registers to allocate */
+ int next_reg[N_REG_CLASSES]; /* next register to allocate per class */
+ }
+frv_tmp_reg_t;
+
+/* Register state information for VLIW re-packing phase. These values must fit
+ within an unsigned char. */
+#define REGSTATE_DEAD 0x00 /* register is currently dead */
+#define REGSTATE_CC_MASK 0x07 /* Mask to isolate CCn for cond exec */
+#define REGSTATE_LIVE 0x08 /* register is live */
+#define REGSTATE_MODIFIED 0x10 /* reg modified in current VLIW insn */
+#define REGSTATE_IF_TRUE 0x20 /* reg modified in cond exec true */
+#define REGSTATE_IF_FALSE 0x40 /* reg modified in cond exec false */
+#define REGSTATE_UNUSED 0x80 /* bit for hire */
+#define REGSTATE_MASK 0xff /* mask for the bits to set */
+
+ /* conditional expression used */
+#define REGSTATE_IF_EITHER (REGSTATE_IF_TRUE | REGSTATE_IF_FALSE)
+
+/* the following is not sure in the reg_state bytes, so can have a larger value
+ than 0xff. */
+#define REGSTATE_CONDJUMP 0x100 /* conditional jump done in VLIW insn */
+
+/* Used in frv_frame_accessor_t to indicate the direction of a register-to-
+ memory move. */
+enum frv_stack_op
+{
+ FRV_LOAD,
+ FRV_STORE
+};
+
+/* Information required by frv_frame_access. */
+typedef struct
+{
+ /* This field is FRV_LOAD if registers are to be loaded from the stack and
+ FRV_STORE if they should be stored onto the stack. FRV_STORE implies
+ the move is being done by the prologue code while FRV_LOAD implies it
+ is being done by the epilogue. */
+ enum frv_stack_op op;
+
+ /* The base register to use when accessing the stack. This may be the
+ frame pointer, stack pointer, or a temporary. The choice of register
+ depends on which part of the frame is being accessed and how big the
+ frame is. */
+ rtx base;
+
+ /* The offset of BASE from the bottom of the current frame, in bytes. */
+ int base_offset;
+} frv_frame_accessor_t;
+
+/* Define the information needed to generate branch and scc insns. This is
+ stored from the compare operation. */
+rtx frv_compare_op0;
+rtx frv_compare_op1;
+
+/* Conditional execution support gathered together in one structure */
+typedef struct
+ {
+ /* Linked list of insns to add if the conditional execution conversion was
+ successful. Each link points to an EXPR_LIST which points to the pattern
+ of the insn to add, and the insn to be inserted before. */
+ rtx added_insns_list;
+
+ /* Identify which registers are safe to allocate for if conversions to
+ conditional execution. We keep the last allocated register in the
+ register classes between COND_EXEC statements. This will mean we allocate
+ different registers for each different COND_EXEC group if we can. This
+ might allow the scheduler to intermix two different COND_EXEC sections. */
+ frv_tmp_reg_t tmp_reg;
+
+ /* For nested IFs, identify which CC registers are used outside of setting
+ via a compare isnsn, and using via a check insn. This will allow us to
+ know if we can rewrite the register to use a different register that will
+ be paired with the CR register controlling the nested IF-THEN blocks. */
+ HARD_REG_SET nested_cc_ok_rewrite;
+
+ /* Temporary registers allocated to hold constants during conditional
+ execution. */
+ rtx scratch_regs[FIRST_PSEUDO_REGISTER];
+
+ /* Current number of temp registers available. */
+ int cur_scratch_regs;
+
+ /* Number of nested conditional execution blocks */
+ int num_nested_cond_exec;
+
+ /* Map of insns that set up constants in scratch registers. */
+ bitmap scratch_insns_bitmap;
+
+ /* Conditional execution test register (CC0..CC7) */
+ rtx cr_reg;
+
+ /* Conditional execution compare register that is paired with cr_reg, so that
+ nested compares can be done. The csubcc and caddcc instructions don't
+ have enough bits to specify both a CC register to be set and a CR register
+ to do the test on, so the same bit number is used for both. Needless to
+ say, this is rather inconvient for GCC. */
+ rtx nested_cc_reg;
+
+ /* Extra CR registers used for &&, ||. */
+ rtx extra_int_cr;
+ rtx extra_fp_cr;
+
+ /* Previous CR used in nested if, to make sure we are dealing with the same
+ nested if as the previous statement. */
+ rtx last_nested_if_cr;
+ }
+frv_ifcvt_t;
+
+static /* GTY(()) */ frv_ifcvt_t frv_ifcvt;
+
+/* Map register number to smallest register class. */
+enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
+
+/* Map class letter into register class */
+enum reg_class reg_class_from_letter[256];
+
+/* Cached value of frv_stack_info */
+static frv_stack_t *frv_stack_cache = (frv_stack_t *)0;
+
+/* -mbranch-cost= support */
+const char *frv_branch_cost_string;
+int frv_branch_cost_int = DEFAULT_BRANCH_COST;
+
+/* -mcpu= support */
+const char *frv_cpu_string; /* -mcpu= option */
+frv_cpu_t frv_cpu_type = CPU_TYPE; /* value of -mcpu= */
+
+/* -mcond-exec-insns= support */
+const char *frv_condexec_insns_str; /* -mcond-exec-insns= option */
+int frv_condexec_insns = DEFAULT_CONDEXEC_INSNS; /* value of -mcond-exec-insns*/
+
+/* -mcond-exec-temps= support */
+const char *frv_condexec_temps_str; /* -mcond-exec-temps= option */
+int frv_condexec_temps = DEFAULT_CONDEXEC_TEMPS; /* value of -mcond-exec-temps*/
+
+/* -msched-lookahead=n */
+const char *frv_sched_lookahead_str; /* -msched-lookahead=n */
+int frv_sched_lookahead = 4; /* -msched-lookahead=n */
+
+/* Forward references */
+static int frv_default_flags_for_cpu PARAMS ((void));
+static int frv_string_begins_with PARAMS ((tree, const char *));
+static FRV_INLINE int symbol_ref_small_data_p PARAMS ((rtx));
+static FRV_INLINE int const_small_data_p PARAMS ((rtx));
+static FRV_INLINE int plus_small_data_p PARAMS ((rtx, rtx));
+static void frv_print_operand_memory_reference_reg
+ PARAMS ((FILE *, rtx));
+static void frv_print_operand_memory_reference PARAMS ((FILE *, rtx, int));
+static int frv_print_operand_jump_hint PARAMS ((rtx));
+static FRV_INLINE int frv_regno_ok_for_base_p PARAMS ((int, int));
+static rtx single_set_pattern PARAMS ((rtx));
+static int frv_function_contains_far_jump PARAMS ((void));
+static rtx frv_alloc_temp_reg PARAMS ((frv_tmp_reg_t *,
+ enum reg_class,
+ enum machine_mode,
+ int, int));
+static rtx frv_frame_offset_rtx PARAMS ((int));
+static rtx frv_frame_mem PARAMS ((enum machine_mode,
+ rtx, int));
+static rtx frv_dwarf_store PARAMS ((rtx, int));
+static void frv_frame_insn PARAMS ((rtx, rtx));
+static void frv_frame_access PARAMS ((frv_frame_accessor_t*,
+ rtx, int));
+static void frv_frame_access_multi PARAMS ((frv_frame_accessor_t*,
+ frv_stack_t *, int));
+static void frv_frame_access_standard_regs PARAMS ((enum frv_stack_op,
+ frv_stack_t *));
+static struct machine_function *frv_init_machine_status PARAMS ((void));
+static int frv_legitimate_memory_operand PARAMS ((rtx,
+ enum machine_mode,
+ int));
+static rtx frv_int_to_acc PARAMS ((enum insn_code,
+ int, rtx));
+static enum machine_mode frv_matching_accg_mode PARAMS ((enum machine_mode));
+static rtx frv_read_argument PARAMS ((tree *));
+static int frv_check_constant_argument PARAMS ((enum insn_code,
+ int, rtx));
+static rtx frv_legitimize_target PARAMS ((enum insn_code, rtx));
+static rtx frv_legitimize_argument PARAMS ((enum insn_code,
+ int, rtx));
+static rtx frv_expand_set_builtin PARAMS ((enum insn_code,
+ tree, rtx));
+static rtx frv_expand_unop_builtin PARAMS ((enum insn_code,
+ tree, rtx));
+static rtx frv_expand_binop_builtin PARAMS ((enum insn_code,
+ tree, rtx));
+static rtx frv_expand_cut_builtin PARAMS ((enum insn_code,
+ tree, rtx));
+static rtx frv_expand_binopimm_builtin PARAMS ((enum insn_code,
+ tree, rtx));
+static rtx frv_expand_voidbinop_builtin PARAMS ((enum insn_code,
+ tree));
+static rtx frv_expand_voidtriop_builtin PARAMS ((enum insn_code,
+ tree));
+static rtx frv_expand_voidaccop_builtin PARAMS ((enum insn_code,
+ tree));
+static rtx frv_expand_mclracc_builtin PARAMS ((tree));
+static rtx frv_expand_mrdacc_builtin PARAMS ((enum insn_code,
+ tree));
+static rtx frv_expand_mwtacc_builtin PARAMS ((enum insn_code,
+ tree));
+static rtx frv_expand_noargs_builtin PARAMS ((enum insn_code));
+static rtx frv_emit_comparison PARAMS ((enum rtx_code, rtx,
+ rtx));
+static int frv_clear_registers_used PARAMS ((rtx *, void *));
+static void frv_ifcvt_add_insn PARAMS ((rtx, rtx, int));
+static rtx frv_ifcvt_rewrite_mem PARAMS ((rtx,
+ enum machine_mode,
+ rtx));
+static rtx frv_ifcvt_load_value PARAMS ((rtx, rtx));
+static void frv_registers_update PARAMS ((rtx, unsigned char [],
+ int [], int *, int));
+static int frv_registers_used_p PARAMS ((rtx, unsigned char [],
+ int));
+static int frv_registers_set_p PARAMS ((rtx, unsigned char [],
+ int));
+static void frv_pack_insns PARAMS ((void));
+static void frv_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void frv_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+static bool frv_assemble_integer PARAMS ((rtx, unsigned, int));
+static const char * frv_strip_name_encoding PARAMS ((const char *));
+static void frv_encode_section_info PARAMS ((tree, int));
+static void frv_init_builtins PARAMS ((void));
+static rtx frv_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
+static bool frv_in_small_data_p PARAMS ((tree));
+static void frv_asm_output_mi_thunk
+ PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
+
+/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE frv_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE frv_function_epilogue
+#undef TARGET_ASM_INTEGER
+#define TARGET_ASM_INTEGER frv_assemble_integer
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING frv_strip_name_encoding
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO frv_encode_section_info
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS frv_init_builtins
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN frv_expand_builtin
+#undef TARGET_IN_SMALL_DATA_P
+#define TARGET_IN_SMALL_DATA_P frv_in_small_data_p
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK frv_asm_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+/* Given a SYMBOL_REF, return true if it points to small data. */
+
+static FRV_INLINE int
+symbol_ref_small_data_p (x)
+ rtx x;
+{
+ return SDATA_NAME_P (XSTR (x, 0));
+}
+
+/* Given a CONST, return true if the symbol_ref points to small data. */
+
+static FRV_INLINE int
+const_small_data_p (x)
+ rtx x;
+{
+ rtx x0, x1;
+
+ if (GET_CODE (XEXP (x, 0)) != PLUS)
+ return FALSE;
+
+ x0 = XEXP (XEXP (x, 0), 0);
+ if (GET_CODE (x0) != SYMBOL_REF || !SDATA_NAME_P (XSTR (x0, 0)))
+ return FALSE;
+
+ x1 = XEXP (XEXP (x, 0), 1);
+ if (GET_CODE (x1) != CONST_INT
+ || !IN_RANGE_P (INTVAL (x1), -2048, 2047))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Given a PLUS, return true if this is a small data reference. */
+
+static FRV_INLINE int
+plus_small_data_p (op0, op1)
+ rtx op0;
+ rtx op1;
+{
+ if (GET_MODE (op0) == SImode
+ && GET_CODE (op0) == REG
+ && REGNO (op0) == SDA_BASE_REG)
+ {
+ if (GET_CODE (op1) == SYMBOL_REF)
+ return symbol_ref_small_data_p (op1);
+
+ if (GET_CODE (op1) == CONST)
+ return const_small_data_p (op1);
+ }
+
+ return FALSE;
+}
+
+
+static int
+frv_default_flags_for_cpu ()
+{
+ switch (frv_cpu_type)
+ {
+ case FRV_CPU_GENERIC:
+ return MASK_DEFAULT_FRV;
+
+ case FRV_CPU_FR500:
+ case FRV_CPU_TOMCAT:
+ return MASK_DEFAULT_FR500;
+
+ case FRV_CPU_FR400:
+ return MASK_DEFAULT_FR400;
+
+ case FRV_CPU_FR300:
+ case FRV_CPU_SIMPLE:
+ return MASK_DEFAULT_SIMPLE;
+ }
+ abort ();
+}
+
+/* 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
+frv_override_options ()
+{
+ int regno, i;
+
+ /* Set the cpu type */
+ if (frv_cpu_string)
+ {
+ if (strcmp (frv_cpu_string, "simple") == 0)
+ frv_cpu_type = FRV_CPU_SIMPLE;
+
+ else if (strcmp (frv_cpu_string, "tomcat") == 0)
+ frv_cpu_type = FRV_CPU_TOMCAT;
+
+ else if (strncmp (frv_cpu_string, "fr", sizeof ("fr")-1) != 0)
+ error ("Unknown cpu: -mcpu=%s", frv_cpu_string);
+
+ else
+ {
+ const char *p = frv_cpu_string + sizeof ("fr") - 1;
+ if (strcmp (p, "500") == 0)
+ frv_cpu_type = FRV_CPU_FR500;
+
+ else if (strcmp (p, "400") == 0)
+ frv_cpu_type = FRV_CPU_FR400;
+
+ else if (strcmp (p, "300") == 0)
+ frv_cpu_type = FRV_CPU_FR300;
+
+ else if (strcmp (p, "v") == 0)
+ frv_cpu_type = FRV_CPU_GENERIC;
+
+ else
+ error ("Unknown cpu: -mcpu=%s", frv_cpu_string);
+ }
+ }
+
+ target_flags |= (frv_default_flags_for_cpu () & ~target_flags_explicit);
+
+ /* -mlibrary-pic sets -fPIC and -G0 and also suppresses warnings from the
+ linker about linking pic and non-pic code. */
+ if (TARGET_LIBPIC)
+ {
+ if (!flag_pic) /* -fPIC */
+ flag_pic = 2;
+
+ if (! g_switch_set) /* -G0 */
+ {
+ g_switch_set = 1;
+ g_switch_value = 0;
+ }
+ }
+
+ /* Both -fpic and -gdwarf want to use .previous and the assembler only keeps
+ one level. */
+ if (write_symbols == DWARF_DEBUG && flag_pic)
+ error ("-fpic and -gdwarf are incompatible (-fpic and -g/-gdwarf-2 are fine)");
+
+ /* Change the branch cost value */
+ if (frv_branch_cost_string)
+ frv_branch_cost_int = atoi (frv_branch_cost_string);
+
+ /* Change the # of insns to be converted to conditional execution */
+ if (frv_condexec_insns_str)
+ frv_condexec_insns = atoi (frv_condexec_insns_str);
+
+ /* Change # of temporary registers used to hold integer constants */
+ if (frv_condexec_temps_str)
+ frv_condexec_temps = atoi (frv_condexec_temps_str);
+
+ /* Change scheduling look ahead. */
+ if (frv_sched_lookahead_str)
+ frv_sched_lookahead = atoi (frv_sched_lookahead_str);
+
+ /* A C expression whose value is a register class containing hard
+ register REGNO. In general there is more than one such class;
+ choose a class which is "minimal", meaning that no smaller class
+ also contains the register. */
+
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ {
+ enum reg_class class;
+
+ if (GPR_P (regno))
+ {
+ int gpr_reg = regno - GPR_FIRST;
+ if ((gpr_reg & 3) == 0)
+ class = QUAD_REGS;
+
+ else if ((gpr_reg & 1) == 0)
+ class = EVEN_REGS;
+
+ else
+ class = GPR_REGS;
+ }
+
+ else if (FPR_P (regno))
+ {
+ int fpr_reg = regno - GPR_FIRST;
+ if ((fpr_reg & 3) == 0)
+ class = QUAD_FPR_REGS;
+
+ else if ((fpr_reg & 1) == 0)
+ class = FEVEN_REGS;
+
+ else
+ class = FPR_REGS;
+ }
+
+ else if (regno == LR_REGNO)
+ class = LR_REG;
+
+ else if (regno == LCR_REGNO)
+ class = LCR_REG;
+
+ else if (ICC_P (regno))
+ class = ICC_REGS;
+
+ else if (FCC_P (regno))
+ class = FCC_REGS;
+
+ else if (ICR_P (regno))
+ class = ICR_REGS;
+
+ else if (FCR_P (regno))
+ class = FCR_REGS;
+
+ else if (ACC_P (regno))
+ {
+ int r = regno - ACC_FIRST;
+ if ((r & 3) == 0)
+ class = QUAD_ACC_REGS;
+ else if ((r & 1) == 0)
+ class = EVEN_ACC_REGS;
+ else
+ class = ACC_REGS;
+ }
+
+ else if (ACCG_P (regno))
+ class = ACCG_REGS;
+
+ else
+ class = NO_REGS;
+
+ regno_reg_class[regno] = class;
+ }
+
+ /* Check for small data option */
+ if (!g_switch_set)
+ g_switch_value = SDATA_DEFAULT_SIZE;
+
+ /* A C expression which defines the machine-dependent operand
+ constraint letters for register classes. If CHAR is such a
+ letter, the value should be the register class corresponding to
+ it. Otherwise, the value should be `NO_REGS'. The register
+ letter `r', corresponding to class `GENERAL_REGS', will not be
+ passed to this macro; you do not need to handle it.
+
+ The following letters are unavailable, due to being used as
+ constraints:
+ '0'..'9'
+ '<', '>'
+ 'E', 'F', 'G', 'H'
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'
+ 'Q', 'R', 'S', 'T', 'U'
+ 'V', 'X'
+ 'g', 'i', 'm', 'n', 'o', 'p', 'r', 's' */
+
+ for (i = 0; i < 256; i++)
+ reg_class_from_letter[i] = NO_REGS;
+
+ reg_class_from_letter['a'] = ACC_REGS;
+ reg_class_from_letter['b'] = EVEN_ACC_REGS;
+ reg_class_from_letter['c'] = CC_REGS;
+ reg_class_from_letter['d'] = GPR_REGS;
+ reg_class_from_letter['e'] = EVEN_REGS;
+ reg_class_from_letter['f'] = FPR_REGS;
+ reg_class_from_letter['h'] = FEVEN_REGS;
+ reg_class_from_letter['l'] = LR_REG;
+ reg_class_from_letter['q'] = QUAD_REGS;
+ reg_class_from_letter['t'] = ICC_REGS;
+ reg_class_from_letter['u'] = FCC_REGS;
+ reg_class_from_letter['v'] = ICR_REGS;
+ reg_class_from_letter['w'] = FCR_REGS;
+ reg_class_from_letter['x'] = QUAD_FPR_REGS;
+ reg_class_from_letter['y'] = LCR_REG;
+ reg_class_from_letter['z'] = SPR_REGS;
+ reg_class_from_letter['A'] = QUAD_ACC_REGS;
+ reg_class_from_letter['B'] = ACCG_REGS;
+ reg_class_from_letter['C'] = CR_REGS;
+
+ /* There is no single unaligned SI op for PIC code. Sometimes we
+ need to use ".4byte" and sometimes we need to use ".picptr".
+ See frv_assemble_integer for details. */
+ if (flag_pic)
+ targetm.asm_out.unaligned_op.si = 0;
+
+ init_machine_status = frv_init_machine_status;
+}
+
+
+/* Some machines may desire to change what optimizations are performed for
+ various optimization levels. This macro, if defined, is executed once just
+ after the optimization level is determined and before the remainder of the
+ command options have been parsed. Values set in this macro are used as the
+ default values for the other command line options.
+
+ LEVEL is the optimization level specified; 2 if `-O2' is specified, 1 if
+ `-O' is specified, and 0 if neither is specified.
+
+ SIZE is nonzero if `-Os' is specified, 0 otherwise.
+
+ 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.
+
+ *Do not examine `write_symbols' in this macro!* The debugging options are
+ *not supposed to alter the generated code. */
+
+/* On the FRV, possibly disable VLIW packing which is done by the 2nd
+ scheduling pass at the current time. */
+void
+frv_optimization_options (level, size)
+ int level;
+ int size ATTRIBUTE_UNUSED;
+{
+ if (level >= 2)
+ {
+#ifdef DISABLE_SCHED2
+ flag_schedule_insns_after_reload = 0;
+#endif
+#ifdef ENABLE_RCSP
+ flag_rcsp = 1;
+#endif
+ }
+}
+
+
+/* Return true if NAME (a STRING_CST node) begins with PREFIX. */
+
+static int
+frv_string_begins_with (name, prefix)
+ tree name;
+ const char *prefix;
+{
+ int prefix_len = strlen (prefix);
+
+ /* Remember: NAME's length includes the null terminator. */
+ return (TREE_STRING_LENGTH (name) > prefix_len
+ && strncmp (TREE_STRING_POINTER (name), prefix, prefix_len) == 0);
+}
+
+/* Encode section information of DECL, which is either a VAR_DECL,
+ FUNCTION_DECL, STRING_CST, CONSTRUCTOR, or ???.
+
+ For the FRV we want to record:
+
+ - whether the object lives in .sdata/.sbss.
+ objects living in .sdata/.sbss are prefixed with SDATA_FLAG_CHAR
+
+*/
+
+static void
+frv_encode_section_info (decl, first)
+ tree decl;
+ int first;
+{
+ if (! first)
+ return;
+ if (TREE_CODE (decl) == VAR_DECL)
+ {
+ int size = int_size_in_bytes (TREE_TYPE (decl));
+ tree section_name = DECL_SECTION_NAME (decl);
+ int is_small = 0;
+
+ /* Don't apply the -G flag to internal compiler structures. We
+ should leave such structures in the main data section, partly
+ for efficiency and partly because the size of some of them
+ (such as C++ typeinfos) is not known until later. */
+ if (!DECL_ARTIFICIAL (decl) && size > 0 && size <= g_switch_value)
+ is_small = 1;
+
+ /* If we already know which section the decl should be in, see if
+ it's a small data section. */
+ if (section_name)
+ {
+ if (TREE_CODE (section_name) == STRING_CST)
+ {
+ if (frv_string_begins_with (section_name, ".sdata"))
+ is_small = 1;
+ if (frv_string_begins_with (section_name, ".sbss"))
+ is_small = 1;
+ }
+ else
+ abort ();
+ }
+
+ if (is_small)
+ {
+ rtx sym_ref = XEXP (DECL_RTL (decl), 0);
+ char * str = xmalloc (2 + strlen (XSTR (sym_ref, 0)));
+
+ str[0] = SDATA_FLAG_CHAR;
+ strcpy (&str[1], XSTR (sym_ref, 0));
+ XSTR (sym_ref, 0) = str;
+ }
+ }
+}
+
+
+/* Zero or more C statements that may conditionally modify two variables
+ `fixed_regs' and `call_used_regs' (both of type `char []') after they have
+ been initialized from the two preceding macros.
+
+ This is necessary in case the fixed or call-clobbered registers depend on
+ target flags.
+
+ You need not define this macro if it has no work to do.
+
+ 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 `fixed_regs' and
+ `call_used_regs' to 1 for each of the registers in the classes which should
+ not be used by GCC. Also define the macro `REG_CLASS_FROM_LETTER' to return
+ `NO_REGS' if it is called with a letter for a class that shouldn't be used.
+
+ (However, if this class is not included in `GENERAL_REGS' and all of the
+ insn patterns whose constraints permit this class are controlled by target
+ switches, then GCC will automatically avoid using these registers when the
+ target switches are opposed to them.) */
+
+void
+frv_conditional_register_usage ()
+{
+ int i;
+
+ for (i = GPR_FIRST + NUM_GPRS; i <= GPR_LAST; i++)
+ fixed_regs[i] = call_used_regs[i] = 1;
+
+ for (i = FPR_FIRST + NUM_FPRS; i <= FPR_LAST; i++)
+ fixed_regs[i] = call_used_regs[i] = 1;
+
+ for (i = ACC_FIRST + NUM_ACCS; i <= ACC_LAST; i++)
+ fixed_regs[i] = call_used_regs[i] = 1;
+
+ for (i = ACCG_FIRST + NUM_ACCS; i <= ACCG_LAST; i++)
+ fixed_regs[i] = call_used_regs[i] = 1;
+
+ /* Reserve the registers used for conditional execution. At present, we need
+ 1 ICC and 1 ICR register. */
+ fixed_regs[ICC_TEMP] = call_used_regs[ICC_TEMP] = 1;
+ fixed_regs[ICR_TEMP] = call_used_regs[ICR_TEMP] = 1;
+
+ if (TARGET_FIXED_CC)
+ {
+ fixed_regs[ICC_FIRST] = call_used_regs[ICC_FIRST] = 1;
+ fixed_regs[FCC_FIRST] = call_used_regs[FCC_FIRST] = 1;
+ fixed_regs[ICR_FIRST] = call_used_regs[ICR_FIRST] = 1;
+ fixed_regs[FCR_FIRST] = call_used_regs[FCR_FIRST] = 1;
+ }
+
+#if 0
+ /* If -fpic, SDA_BASE_REG is the PIC register. */
+ if (g_switch_value == 0 && !flag_pic)
+ fixed_regs[SDA_BASE_REG] = call_used_regs[SDA_BASE_REG] = 0;
+
+ if (!flag_pic)
+ fixed_regs[PIC_REGNO] = call_used_regs[PIC_REGNO] = 0;
+#endif
+}
+
+
+/*
+ * Compute the stack frame layout
+ *
+ * Register setup:
+ * +---------------+-----------------------+-----------------------+
+ * |Register |type |caller-save/callee-save|
+ * +---------------+-----------------------+-----------------------+
+ * |GR0 |Zero register | - |
+ * |GR1 |Stack pointer(SP) | - |
+ * |GR2 |Frame pointer(FP) | - |
+ * |GR3 |Hidden parameter | caller save |
+ * |GR4-GR7 | - | caller save |
+ * |GR8-GR13 |Argument register | caller save |
+ * |GR14-GR15 | - | caller save |
+ * |GR16-GR31 | - | callee save |
+ * |GR32-GR47 | - | caller save |
+ * |GR48-GR63 | - | callee save |
+ * |FR0-FR15 | - | caller save |
+ * |FR16-FR31 | - | callee save |
+ * |FR32-FR47 | - | caller save |
+ * |FR48-FR63 | - | callee save |
+ * +---------------+-----------------------+-----------------------+
+ *
+ * Stack frame setup:
+ * Low
+ * SP-> |-----------------------------------|
+ * | Argument area |
+ * |-----------------------------------|
+ * | Register save area |
+ * |-----------------------------------|
+ * | Local variable save area |
+ * FP-> |-----------------------------------|
+ * | Old FP |
+ * |-----------------------------------|
+ * | Hidden parameter save area |
+ * |-----------------------------------|
+ * | Return address(LR) storage area |
+ * |-----------------------------------|
+ * | Padding for alignment |
+ * |-----------------------------------|
+ * | Register argument area |
+ * OLD SP-> |-----------------------------------|
+ * | Parameter area |
+ * |-----------------------------------|
+ * High
+ *
+ * Argument area/Parameter area:
+ *
+ * When a function is called, this area is used for argument transfer. When
+ * the argument is set up by the caller function, this area is referred to as
+ * the argument area. When the argument is referenced by the callee function,
+ * this area is referred to as the parameter area. The area is allocated when
+ * all arguments cannot be placed on the argument register at the time of
+ * argument transfer.
+ *
+ * Register save area:
+ *
+ * This is a register save area that must be guaranteed for the caller
+ * function. This area is not secured when the register save operation is not
+ * needed.
+ *
+ * Local variable save area:
+ *
+ * This is the area for local variables and temporary variables.
+ *
+ * Old FP:
+ *
+ * This area stores the FP value of the caller function.
+ *
+ * Hidden parameter save area:
+ *
+ * This area stores the start address of the return value storage
+ * area for a struct/union return function.
+ * When a struct/union is used as the return value, the caller
+ * function stores the return value storage area start address in
+ * register GR3 and passes it to the caller function.
+ * The callee function interprets the address stored in the GR3
+ * as the return value storage area start address.
+ * When register GR3 needs to be saved into memory, the callee
+ * function saves it in the hidden parameter save area. This
+ * area is not secured when the save operation is not needed.
+ *
+ * Return address(LR) storage area:
+ *
+ * This area saves the LR. The LR stores the address of a return to the caller
+ * function for the purpose of function calling.
+ *
+ * Argument register area:
+ *
+ * This area saves the argument register. This area is not secured when the
+ * save operation is not needed.
+ *
+ * Argument:
+ *
+ * Arguments, the count of which equals the count of argument registers (6
+ * words), are positioned in registers GR8 to GR13 and delivered to the callee
+ * function. When a struct/union return function is called, the return value
+ * area address is stored in register GR3. Arguments not placed in the
+ * argument registers will be stored in the stack argument area for transfer
+ * purposes. When an 8-byte type argument is to be delivered using registers,
+ * it is divided into two and placed in two registers for transfer. When
+ * argument registers must be saved to memory, the callee function secures an
+ * argument register save area in the stack. In this case, a continuous
+ * argument register save area must be established in the parameter area. The
+ * argument register save area must be allocated as needed to cover the size of
+ * the argument register to be saved. If the function has a variable count of
+ * arguments, it saves all argument registers in the argument register save
+ * area.
+ *
+ * Argument Extension Format:
+ *
+ * When an argument is to be stored in the stack, its type is converted to an
+ * extended type in accordance with the individual argument type. The argument
+ * is freed by the caller function after the return from the callee function is
+ * made.
+ *
+ * +-----------------------+---------------+------------------------+
+ * | Argument Type |Extended Type |Stack Storage Size(byte)|
+ * +-----------------------+---------------+------------------------+
+ * |char |int | 4 |
+ * |signed char |int | 4 |
+ * |unsigned char |int | 4 |
+ * |[signed] short int |int | 4 |
+ * |unsigned short int |int | 4 |
+ * |[signed] int |No extension | 4 |
+ * |unsigned int |No extension | 4 |
+ * |[signed] long int |No extension | 4 |
+ * |unsigned long int |No extension | 4 |
+ * |[signed] long long int |No extension | 8 |
+ * |unsigned long long int |No extension | 8 |
+ * |float |double | 8 |
+ * |double |No extension | 8 |
+ * |long double |No extension | 8 |
+ * |pointer |No extension | 4 |
+ * |struct/union |- | 4 (*1) |
+ * +-----------------------+---------------+------------------------+
+ *
+ * When a struct/union is to be delivered as an argument, the caller copies it
+ * to the local variable area and delivers the address of that area.
+ *
+ * Return Value:
+ *
+ * +-------------------------------+----------------------+
+ * |Return Value Type |Return Value Interface|
+ * +-------------------------------+----------------------+
+ * |void |None |
+ * |[signed|unsigned] char |GR8 |
+ * |[signed|unsigned] short int |GR8 |
+ * |[signed|unsigned] int |GR8 |
+ * |[signed|unsigned] long int |GR8 |
+ * |pointer |GR8 |
+ * |[signed|unsigned] long long int|GR8 & GR9 |
+ * |float |GR8 |
+ * |double |GR8 & GR9 |
+ * |long double |GR8 & GR9 |
+ * |struct/union |(*1) |
+ * +-------------------------------+----------------------+
+ *
+ * When a struct/union is used as the return value, the caller function stores
+ * the start address of the return value storage area into GR3 and then passes
+ * it to the callee function. The callee function interprets GR3 as the start
+ * address of the return value storage area. When this address needs to be
+ * saved in memory, the callee function secures the hidden parameter save area
+ * and saves the address in that area.
+ */
+
+frv_stack_t *
+frv_stack_info ()
+{
+ static frv_stack_t info, zero_info;
+ frv_stack_t *info_ptr = &info;
+ tree fndecl = current_function_decl;
+ int varargs_p = 0;
+ tree cur_arg;
+ tree next_arg;
+ int range;
+ int alignment;
+ int offset;
+
+ /* If we've already calculated the values and reload is complete, just return now */
+ if (frv_stack_cache)
+ return frv_stack_cache;
+
+ /* Zero all fields */
+ info = zero_info;
+
+ /* Set up the register range information */
+ info_ptr->regs[STACK_REGS_GPR].name = "gpr";
+ info_ptr->regs[STACK_REGS_GPR].first = LAST_ARG_REGNUM + 1;
+ info_ptr->regs[STACK_REGS_GPR].last = GPR_LAST;
+ info_ptr->regs[STACK_REGS_GPR].dword_p = TRUE;
+
+ info_ptr->regs[STACK_REGS_FPR].name = "fpr";
+ info_ptr->regs[STACK_REGS_FPR].first = FPR_FIRST;
+ info_ptr->regs[STACK_REGS_FPR].last = FPR_LAST;
+ info_ptr->regs[STACK_REGS_FPR].dword_p = TRUE;
+
+ info_ptr->regs[STACK_REGS_LR].name = "lr";
+ info_ptr->regs[STACK_REGS_LR].first = LR_REGNO;
+ info_ptr->regs[STACK_REGS_LR].last = LR_REGNO;
+ info_ptr->regs[STACK_REGS_LR].special_p = 1;
+
+ info_ptr->regs[STACK_REGS_CC].name = "cc";
+ info_ptr->regs[STACK_REGS_CC].first = CC_FIRST;
+ info_ptr->regs[STACK_REGS_CC].last = CC_LAST;
+ info_ptr->regs[STACK_REGS_CC].field_p = TRUE;
+
+ info_ptr->regs[STACK_REGS_LCR].name = "lcr";
+ info_ptr->regs[STACK_REGS_LCR].first = LCR_REGNO;
+ info_ptr->regs[STACK_REGS_LCR].last = LCR_REGNO;
+
+ info_ptr->regs[STACK_REGS_STDARG].name = "stdarg";
+ info_ptr->regs[STACK_REGS_STDARG].first = FIRST_ARG_REGNUM;
+ info_ptr->regs[STACK_REGS_STDARG].last = LAST_ARG_REGNUM;
+ info_ptr->regs[STACK_REGS_STDARG].dword_p = 1;
+ info_ptr->regs[STACK_REGS_STDARG].special_p = 1;
+
+ info_ptr->regs[STACK_REGS_STRUCT].name = "struct";
+ info_ptr->regs[STACK_REGS_STRUCT].first = STRUCT_VALUE_REGNUM;
+ info_ptr->regs[STACK_REGS_STRUCT].last = STRUCT_VALUE_REGNUM;
+ info_ptr->regs[STACK_REGS_STRUCT].special_p = 1;
+
+ info_ptr->regs[STACK_REGS_FP].name = "fp";
+ info_ptr->regs[STACK_REGS_FP].first = FRAME_POINTER_REGNUM;
+ info_ptr->regs[STACK_REGS_FP].last = FRAME_POINTER_REGNUM;
+ info_ptr->regs[STACK_REGS_FP].special_p = 1;
+
+ /* Determine if this is a stdarg function. If so, allocate space to store
+ the 6 arguments. */
+ if (cfun->stdarg)
+ varargs_p = 1;
+
+ else
+ {
+ /* Find the last argument, and see if it is __builtin_va_alist. */
+ for (cur_arg = DECL_ARGUMENTS (fndecl); cur_arg != (tree)0; cur_arg = next_arg)
+ {
+ next_arg = TREE_CHAIN (cur_arg);
+ if (next_arg == (tree)0)
+ {
+ if (DECL_NAME (cur_arg)
+ && !strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)), "__builtin_va_alist"))
+ varargs_p = 1;
+
+ break;
+ }
+ }
+ }
+
+ /* Iterate over all of the register ranges */
+ for (range = 0; range < STACK_REGS_MAX; range++)
+ {
+ frv_stack_regs_t *reg_ptr = &(info_ptr->regs[range]);
+ int first = reg_ptr->first;
+ int last = reg_ptr->last;
+ int size_1word = 0;
+ int size_2words = 0;
+ int regno;
+
+ /* Calculate which registers need to be saved & save area size */
+ switch (range)
+ {
+ default:
+ for (regno = first; regno <= last; regno++)
+ {
+ if ((regs_ever_live[regno] && !call_used_regs[regno])
+ || (current_function_calls_eh_return
+ && (regno >= FIRST_EH_REGNUM && regno <= LAST_EH_REGNUM))
+ || (flag_pic && cfun->uses_pic_offset_table && regno == PIC_REGNO))
+ {
+ info_ptr->save_p[regno] = REG_SAVE_1WORD;
+ size_1word += UNITS_PER_WORD;
+ }
+ }
+ break;
+
+ /* Calculate whether we need to create a frame after everything else
+ has been processed. */
+ case STACK_REGS_FP:
+ break;
+
+ case STACK_REGS_LR:
+ if (regs_ever_live[LR_REGNO]
+ || profile_flag
+ || frame_pointer_needed
+ || (flag_pic && cfun->uses_pic_offset_table))
+ {
+ info_ptr->save_p[LR_REGNO] = REG_SAVE_1WORD;
+ size_1word += UNITS_PER_WORD;
+ }
+ break;
+
+ case STACK_REGS_STDARG:
+ if (varargs_p)
+ {
+ /* If this is a stdarg function with an non varardic argument split
+ between registers and the stack, adjust the saved registers
+ downward */
+ last -= (ADDR_ALIGN (cfun->pretend_args_size, UNITS_PER_WORD)
+ / UNITS_PER_WORD);
+
+ for (regno = first; regno <= last; regno++)
+ {
+ info_ptr->save_p[regno] = REG_SAVE_1WORD;
+ size_1word += UNITS_PER_WORD;
+ }
+
+ info_ptr->stdarg_size = size_1word;
+ }
+ break;
+
+ case STACK_REGS_STRUCT:
+ if (cfun->returns_struct)
+ {
+ info_ptr->save_p[STRUCT_VALUE_REGNUM] = REG_SAVE_1WORD;
+ size_1word += UNITS_PER_WORD;
+ }
+ break;
+ }
+
+
+ if (size_1word)
+ {
+ /* If this is a field, it only takes one word */
+ if (reg_ptr->field_p)
+ size_1word = UNITS_PER_WORD;
+
+ /* Determine which register pairs can be saved together */
+ else if (reg_ptr->dword_p && TARGET_DWORD)
+ {
+ for (regno = first; regno < last; regno += 2)
+ {
+ if (info_ptr->save_p[regno] && info_ptr->save_p[regno+1])
+ {
+ size_2words += 2 * UNITS_PER_WORD;
+ size_1word -= 2 * UNITS_PER_WORD;
+ info_ptr->save_p[regno] = REG_SAVE_2WORDS;
+ info_ptr->save_p[regno+1] = REG_SAVE_NO_SAVE;
+ }
+ }
+ }
+
+ reg_ptr->size_1word = size_1word;
+ reg_ptr->size_2words = size_2words;
+
+ if (! reg_ptr->special_p)
+ {
+ info_ptr->regs_size_1word += size_1word;
+ info_ptr->regs_size_2words += size_2words;
+ }
+ }
+ }
+
+ /* Set up the sizes of each each field in the frame body, making the sizes
+ of each be divisible by the size of a dword if dword operations might
+ be used, or the size of a word otherwise. */
+ alignment = (TARGET_DWORD? 2 * UNITS_PER_WORD : UNITS_PER_WORD);
+
+ info_ptr->parameter_size = ADDR_ALIGN (cfun->outgoing_args_size, alignment);
+ info_ptr->regs_size = ADDR_ALIGN (info_ptr->regs_size_2words
+ + info_ptr->regs_size_1word,
+ alignment);
+ info_ptr->vars_size = ADDR_ALIGN (get_frame_size (), alignment);
+
+ info_ptr->pretend_size = cfun->pretend_args_size;
+
+ /* Work out the size of the frame, excluding the header. Both the frame
+ body and register parameter area will be dword-aligned. */
+ info_ptr->total_size
+ = (ADDR_ALIGN (info_ptr->parameter_size
+ + info_ptr->regs_size
+ + info_ptr->vars_size,
+ 2 * UNITS_PER_WORD)
+ + ADDR_ALIGN (info_ptr->pretend_size
+ + info_ptr->stdarg_size,
+ 2 * UNITS_PER_WORD));
+
+ /* See if we need to create a frame at all, if so add header area. */
+ if (info_ptr->total_size > 0
+ || info_ptr->regs[STACK_REGS_LR].size_1word > 0
+ || info_ptr->regs[STACK_REGS_STRUCT].size_1word > 0)
+ {
+ offset = info_ptr->parameter_size;
+ info_ptr->header_size = 4 * UNITS_PER_WORD;
+ info_ptr->total_size += 4 * UNITS_PER_WORD;
+
+ /* Calculate the offsets to save normal register pairs */
+ for (range = 0; range < STACK_REGS_MAX; range++)
+ {
+ frv_stack_regs_t *reg_ptr = &(info_ptr->regs[range]);
+ if (! reg_ptr->special_p)
+ {
+ int first = reg_ptr->first;
+ int last = reg_ptr->last;
+ int regno;
+
+ for (regno = first; regno <= last; regno++)
+ if (info_ptr->save_p[regno] == REG_SAVE_2WORDS
+ && regno != FRAME_POINTER_REGNUM
+ && (regno < FIRST_ARG_REGNUM
+ || regno > LAST_ARG_REGNUM))
+ {
+ info_ptr->reg_offset[regno] = offset;
+ offset += 2 * UNITS_PER_WORD;
+ }
+ }
+ }
+
+ /* Calculate the offsets to save normal single registers */
+ for (range = 0; range < STACK_REGS_MAX; range++)
+ {
+ frv_stack_regs_t *reg_ptr = &(info_ptr->regs[range]);
+ if (! reg_ptr->special_p)
+ {
+ int first = reg_ptr->first;
+ int last = reg_ptr->last;
+ int regno;
+
+ for (regno = first; regno <= last; regno++)
+ if (info_ptr->save_p[regno] == REG_SAVE_1WORD
+ && regno != FRAME_POINTER_REGNUM
+ && (regno < FIRST_ARG_REGNUM
+ || regno > LAST_ARG_REGNUM))
+ {
+ info_ptr->reg_offset[regno] = offset;
+ offset += UNITS_PER_WORD;
+ }
+ }
+ }
+
+ /* Calculate the offset to save the local variables at. */
+ offset = ADDR_ALIGN (offset, alignment);
+ if (info_ptr->vars_size)
+ {
+ info_ptr->vars_offset = offset;
+ offset += info_ptr->vars_size;
+ }
+
+ /* Align header to a dword-boundary. */
+ offset = ADDR_ALIGN (offset, 2 * UNITS_PER_WORD);
+
+ /* Calculate the offsets in the fixed frame. */
+ info_ptr->save_p[FRAME_POINTER_REGNUM] = REG_SAVE_1WORD;
+ info_ptr->reg_offset[FRAME_POINTER_REGNUM] = offset;
+ info_ptr->regs[STACK_REGS_FP].size_1word = UNITS_PER_WORD;
+
+ info_ptr->save_p[LR_REGNO] = REG_SAVE_1WORD;
+ info_ptr->reg_offset[LR_REGNO] = offset + 2*UNITS_PER_WORD;
+ info_ptr->regs[STACK_REGS_LR].size_1word = UNITS_PER_WORD;
+
+ if (cfun->returns_struct)
+ {
+ info_ptr->save_p[STRUCT_VALUE_REGNUM] = REG_SAVE_1WORD;
+ info_ptr->reg_offset[STRUCT_VALUE_REGNUM] = offset + UNITS_PER_WORD;
+ info_ptr->regs[STACK_REGS_STRUCT].size_1word = UNITS_PER_WORD;
+ }
+
+ /* Calculate the offsets to store the arguments passed in registers
+ for stdarg functions. The register pairs are first and the single
+ register if any is last. The register save area starts on a
+ dword-boundary. */
+ if (info_ptr->stdarg_size)
+ {
+ int first = info_ptr->regs[STACK_REGS_STDARG].first;
+ int last = info_ptr->regs[STACK_REGS_STDARG].last;
+ int regno;
+
+ /* Skip the header. */
+ offset += 4 * UNITS_PER_WORD;
+ for (regno = first; regno <= last; regno++)
+ {
+ if (info_ptr->save_p[regno] == REG_SAVE_2WORDS)
+ {
+ info_ptr->reg_offset[regno] = offset;
+ offset += 2 * UNITS_PER_WORD;
+ }
+ else if (info_ptr->save_p[regno] == REG_SAVE_1WORD)
+ {
+ info_ptr->reg_offset[regno] = offset;
+ offset += UNITS_PER_WORD;
+ }
+ }
+ }
+ }
+
+ if (reload_completed)
+ frv_stack_cache = info_ptr;
+
+ return info_ptr;
+}
+
+
+/* Print the information about the frv stack offsets, etc. when debugging. */
+
+void
+frv_debug_stack (info)
+ frv_stack_t *info;
+{
+ int range;
+
+ if (!info)
+ info = frv_stack_info ();
+
+ fprintf (stderr, "\nStack information for function %s:\n",
+ ((current_function_decl && DECL_NAME (current_function_decl))
+ ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl))
+ : "<unknown>"));
+
+ fprintf (stderr, "\ttotal_size\t= %6d\n", info->total_size);
+ fprintf (stderr, "\tvars_size\t= %6d\n", info->vars_size);
+ fprintf (stderr, "\tparam_size\t= %6d\n", info->parameter_size);
+ fprintf (stderr, "\tregs_size\t= %6d, 1w = %3d, 2w = %3d\n",
+ info->regs_size, info->regs_size_1word, info->regs_size_2words);
+
+ fprintf (stderr, "\theader_size\t= %6d\n", info->header_size);
+ fprintf (stderr, "\tpretend_size\t= %6d\n", info->pretend_size);
+ fprintf (stderr, "\tvars_offset\t= %6d\n", info->vars_offset);
+ fprintf (stderr, "\tregs_offset\t= %6d\n", info->regs_offset);
+
+ for (range = 0; range < STACK_REGS_MAX; range++)
+ {
+ frv_stack_regs_t *regs = &(info->regs[range]);
+ if ((regs->size_1word + regs->size_2words) > 0)
+ {
+ int first = regs->first;
+ int last = regs->last;
+ int regno;
+
+ fprintf (stderr, "\t%s\tsize\t= %6d, 1w = %3d, 2w = %3d, save =",
+ regs->name, regs->size_1word + regs->size_2words,
+ regs->size_1word, regs->size_2words);
+
+ for (regno = first; regno <= last; regno++)
+ {
+ if (info->save_p[regno] == REG_SAVE_1WORD)
+ fprintf (stderr, " %s (%d)", reg_names[regno],
+ info->reg_offset[regno]);
+
+ else if (info->save_p[regno] == REG_SAVE_2WORDS)
+ fprintf (stderr, " %s-%s (%d)", reg_names[regno],
+ reg_names[regno+1], info->reg_offset[regno]);
+ }
+
+ fputc ('\n', stderr);
+ }
+ }
+
+ fflush (stderr);
+}
+
+
+
+
+/* The following variable value is TRUE if the next output insn should
+ finish cpu cycle. In order words the insn will have packing bit
+ (which means absence of asm code suffix `.p' on assembler. */
+
+static int frv_insn_packing_flag;
+
+/* True if the current function contains a far jump. */
+
+static int
+frv_function_contains_far_jump ()
+{
+ rtx insn = get_insns ();
+ while (insn != NULL
+ && !(GET_CODE (insn) == JUMP_INSN
+ /* Ignore tablejump patterns. */
+ && GET_CODE (PATTERN (insn)) != ADDR_VEC
+ && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
+ && get_attr_far_jump (insn) == FAR_JUMP_YES))
+ insn = NEXT_INSN (insn);
+ return (insn != NULL);
+}
+
+/* For the FRV, this function makes sure that a function with far jumps
+ will return correctly. It also does the VLIW packing. */
+
+static void
+frv_function_prologue (file, size)
+ FILE *file;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+{
+ /* If no frame was created, check whether the function uses a call
+ instruction to implement a far jump. If so, save the link in gr3 and
+ replace all returns to LR with returns to GR3. GR3 is used because it
+ is call-clobbered, because is not available to the register allocator,
+ and because all functions that take a hidden argument pointer will have
+ a stack frame. */
+ if (frv_stack_info ()->total_size == 0 && frv_function_contains_far_jump ())
+ {
+ rtx insn;
+
+ /* Just to check that the above comment is true. */
+ if (regs_ever_live[GPR_FIRST + 3])
+ abort ();
+
+ /* Generate the instruction that saves the link register. */
+ fprintf (file, "\tmovsg lr,gr3\n");
+
+ /* Replace the LR with GR3 in *return_internal patterns. The insn
+ will now return using jmpl @(gr3,0) rather than bralr. We cannot
+ simply emit a different assembly directive because bralr and jmpl
+ execute in different units. */
+ for (insn = get_insns(); insn != NULL; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == JUMP_INSN)
+ {
+ rtx pattern = PATTERN (insn);
+ if (GET_CODE (pattern) == PARALLEL
+ && XVECLEN (pattern, 0) >= 2
+ && GET_CODE (XVECEXP (pattern, 0, 0)) == RETURN
+ && GET_CODE (XVECEXP (pattern, 0, 1)) == USE)
+ {
+ rtx address = XEXP (XVECEXP (pattern, 0, 1), 0);
+ if (GET_CODE (address) == REG && REGNO (address) == LR_REGNO)
+ REGNO (address) = GPR_FIRST + 3;
+ }
+ }
+ }
+
+ frv_pack_insns ();
+ frv_insn_packing_flag = TRUE;
+}
+
+
+/* Return the next available temporary register in a given class. */
+
+static rtx
+frv_alloc_temp_reg (info, class, mode, mark_as_used, no_abort)
+ frv_tmp_reg_t *info; /* which registers are available */
+ enum reg_class class; /* register class desired */
+ enum machine_mode mode; /* mode to allocate register with */
+ int mark_as_used; /* register not available after allocation */
+ int no_abort; /* return NULL instead of aborting */
+{
+ int regno = info->next_reg[ (int)class ];
+ int orig_regno = regno;
+ HARD_REG_SET *reg_in_class = &reg_class_contents[ (int)class ];
+ int i, nr;
+
+ for (;;)
+ {
+ if (TEST_HARD_REG_BIT (*reg_in_class, regno)
+ && TEST_HARD_REG_BIT (info->regs, regno))
+ break;
+
+ if (++regno >= FIRST_PSEUDO_REGISTER)
+ regno = 0;
+ if (regno == orig_regno)
+ {
+ if (no_abort)
+ return NULL_RTX;
+ else
+ abort ();
+ }
+ }
+
+ nr = HARD_REGNO_NREGS (regno, mode);
+ info->next_reg[ (int)class ] = regno + nr;
+
+ if (mark_as_used)
+ for (i = 0; i < nr; i++)
+ CLEAR_HARD_REG_BIT (info->regs, regno+i);
+
+ return gen_rtx_REG (mode, regno);
+}
+
+
+/* Return an rtx with the value OFFSET, which will either be a register or a
+ signed 12-bit integer. It can be used as the second operand in an "add"
+ instruction, or as the index in a load or store.
+
+ The function returns a constant rtx if OFFSET is small enough, otherwise
+ it loads the constant into register OFFSET_REGNO and returns that. */
+static rtx
+frv_frame_offset_rtx (offset)
+ int offset;
+{
+ rtx offset_rtx = GEN_INT (offset);
+ if (IN_RANGE_P (offset, -2048, 2047))
+ return offset_rtx;
+ else
+ {
+ rtx reg_rtx = gen_rtx_REG (SImode, OFFSET_REGNO);
+ if (IN_RANGE_P (offset, -32768, 32767))
+ emit_insn (gen_movsi (reg_rtx, offset_rtx));
+ else
+ {
+ emit_insn (gen_movsi_high (reg_rtx, offset_rtx));
+ emit_insn (gen_movsi_lo_sum (reg_rtx, offset_rtx));
+ }
+ return reg_rtx;
+ }
+}
+
+/* Generate (mem:MODE (plus:Pmode BASE (frv_frame_offset OFFSET)))). The
+ prologue and epilogue uses such expressions to access the stack. */
+static rtx
+frv_frame_mem (mode, base, offset)
+ enum machine_mode mode;
+ rtx base;
+ int offset;
+{
+ return gen_rtx_MEM (mode, gen_rtx_PLUS (Pmode,
+ base,
+ frv_frame_offset_rtx (offset)));
+}
+
+/* Generate a frame-related expression:
+
+ (set REG (mem (plus (sp) (const_int OFFSET)))).
+
+ Such expressions are used in FRAME_RELATED_EXPR notes for more complex
+ instructions. Marking the expressions as frame-related is superfluous if
+ the note contains just a single set. But if the note contains a PARALLEL
+ or SEQUENCE that has several sets, each set must be individually marked
+ as frame-related. */
+static rtx
+frv_dwarf_store (reg, offset)
+ rtx reg;
+ int offset;
+{
+ rtx set = gen_rtx_SET (VOIDmode,
+ gen_rtx_MEM (GET_MODE (reg),
+ plus_constant (stack_pointer_rtx,
+ offset)),
+ reg);
+ RTX_FRAME_RELATED_P (set) = 1;
+ return set;
+}
+
+/* Emit a frame-related instruction whose pattern is PATTERN. The
+ instruction is the last in a sequence that cumulatively performs the
+ operation described by DWARF_PATTERN. The instruction is marked as
+ frame-related and has a REG_FRAME_RELATED_EXPR note containing
+ DWARF_PATTERN. */
+static void
+frv_frame_insn (pattern, dwarf_pattern)
+ rtx pattern;
+ rtx dwarf_pattern;
+{
+ rtx insn = emit_insn (pattern);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ dwarf_pattern,
+ REG_NOTES (insn));
+}
+
+/* Emit instructions that transfer REG to or from the memory location (sp +
+ STACK_OFFSET). The register is stored in memory if ACCESSOR->OP is
+ FRV_STORE and loaded if it is FRV_LOAD. Only the prologue uses this
+ function to store registers and only the epilogue uses it to load them.
+
+ The caller sets up ACCESSOR so that BASE is equal to (sp + BASE_OFFSET).
+ The generated instruction will use BASE as its base register. BASE may
+ simply be the stack pointer, but if several accesses are being made to a
+ region far away from the stack pointer, it may be more efficient to set
+ up a temporary instead.
+
+ Store instructions will be frame-related and will be annotated with the
+ overall effect of the store. Load instructions will be followed by a
+ (use) to prevent later optimizations from zapping them.
+
+ The function takes care of the moves to and from SPRs, using TEMP_REGNO
+ as a temporary in such cases. */
+static void
+frv_frame_access (accessor, reg, stack_offset)
+ frv_frame_accessor_t *accessor;
+ rtx reg;
+ int stack_offset;
+{
+ enum machine_mode mode = GET_MODE (reg);
+ rtx mem = frv_frame_mem (mode,
+ accessor->base,
+ stack_offset - accessor->base_offset);
+
+ if (accessor->op == FRV_LOAD)
+ {
+ if (SPR_P (REGNO (reg)))
+ {
+ rtx temp = gen_rtx_REG (mode, TEMP_REGNO);
+ emit_insn (gen_rtx_SET (VOIDmode, temp, mem));
+ emit_insn (gen_rtx_SET (VOIDmode, reg, temp));
+ }
+ else
+ emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
+ emit_insn (gen_rtx_USE (VOIDmode, reg));
+ }
+ else
+ {
+ if (SPR_P (REGNO (reg)))
+ {
+ rtx temp = gen_rtx_REG (mode, TEMP_REGNO);
+ emit_insn (gen_rtx_SET (VOIDmode, temp, reg));
+ frv_frame_insn (gen_rtx_SET (Pmode, mem, temp),
+ frv_dwarf_store (reg, stack_offset));
+ }
+ else if (GET_MODE (reg) == DImode)
+ {
+ /* For DImode saves, the dwarf2 version needs to be a SEQUENCE
+ with a separate save for each register. */
+ rtx reg1 = gen_rtx_REG (SImode, REGNO (reg));
+ rtx reg2 = gen_rtx_REG (SImode, REGNO (reg) + 1);
+ rtx set1 = frv_dwarf_store (reg1, stack_offset);
+ rtx set2 = frv_dwarf_store (reg2, stack_offset + 4);
+ frv_frame_insn (gen_rtx_SET (Pmode, mem, reg),
+ gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2, set1, set2)));
+ }
+ else
+ frv_frame_insn (gen_rtx_SET (Pmode, mem, reg),
+ frv_dwarf_store (reg, stack_offset));
+ }
+}
+
+/* A function that uses frv_frame_access to transfer a group of registers to
+ or from the stack. ACCESSOR is passed directly to frv_frame_access, INFO
+ is the stack information generated by frv_stack_info, and REG_SET is the
+ number of the register set to transfer. */
+static void
+frv_frame_access_multi (accessor, info, reg_set)
+ frv_frame_accessor_t *accessor;
+ frv_stack_t *info;
+ int reg_set;
+{
+ frv_stack_regs_t *regs_info;
+ int regno;
+
+ regs_info = &info->regs[reg_set];
+ for (regno = regs_info->first; regno <= regs_info->last; regno++)
+ if (info->save_p[regno])
+ frv_frame_access (accessor,
+ info->save_p[regno] == REG_SAVE_2WORDS
+ ? gen_rtx_REG (DImode, regno)
+ : gen_rtx_REG (SImode, regno),
+ info->reg_offset[regno]);
+}
+
+/* Save or restore callee-saved registers that are kept outside the frame
+ header. The function saves the registers if OP is FRV_STORE and restores
+ them if OP is FRV_LOAD. INFO is the stack information generated by
+ frv_stack_info. */
+static void
+frv_frame_access_standard_regs (op, info)
+ enum frv_stack_op op;
+ frv_stack_t *info;
+{
+ frv_frame_accessor_t accessor;
+
+ accessor.op = op;
+ accessor.base = stack_pointer_rtx;
+ accessor.base_offset = 0;
+ frv_frame_access_multi (&accessor, info, STACK_REGS_GPR);
+ frv_frame_access_multi (&accessor, info, STACK_REGS_FPR);
+ frv_frame_access_multi (&accessor, info, STACK_REGS_LCR);
+}
+
+
+/* Called after register allocation to add any instructions needed for the
+ prologue. Using a prologue insn is favored compared to putting all of the
+ instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler
+ to intermix instructions with the saves of the caller saved registers. In
+ some cases, it might be necessary to emit a barrier instruction as the last
+ insn to prevent such scheduling.
+
+ Also any insns generated here should have RTX_FRAME_RELATED_P(insn) = 1
+ so that the debug info generation code can handle them properly. */
+void
+frv_expand_prologue ()
+{
+ frv_stack_t *info = frv_stack_info ();
+ rtx sp = stack_pointer_rtx;
+ rtx fp = frame_pointer_rtx;
+ frv_frame_accessor_t accessor;
+
+ if (TARGET_DEBUG_STACK)
+ frv_debug_stack (info);
+
+ if (info->total_size == 0)
+ return;
+
+ /* We're interested in three areas of the frame here:
+
+ A: the register save area
+ B: the old FP
+ C: the header after B
+
+ If the frame pointer isn't used, we'll have to set up A, B and C
+ using the stack pointer. If the frame pointer is used, we'll access
+ them as follows:
+
+ A: set up using sp
+ B: set up using sp or a temporary (see below)
+ C: set up using fp
+
+ We set up B using the stack pointer if the frame is small enough.
+ Otherwise, it's more efficient to copy the old stack pointer into a
+ temporary and use that.
+
+ Note that it's important to make sure the prologue and epilogue use the
+ same registers to access A and C, since doing otherwise will confuse
+ the aliasing code. */
+
+ /* Set up ACCESSOR for accessing region B above. If the frame pointer
+ isn't used, the same method will serve for C. */
+ accessor.op = FRV_STORE;
+ if (frame_pointer_needed && info->total_size > 2048)
+ {
+ rtx insn;
+
+ accessor.base = gen_rtx_REG (Pmode, OLD_SP_REGNO);
+ accessor.base_offset = info->total_size;
+ insn = emit_insn (gen_movsi (accessor.base, sp));
+ }
+ else
+ {
+ accessor.base = stack_pointer_rtx;
+ accessor.base_offset = 0;
+ }
+
+ /* Allocate the stack space. */
+ {
+ rtx asm_offset = frv_frame_offset_rtx (-info->total_size);
+ rtx dwarf_offset = GEN_INT (-info->total_size);
+
+ frv_frame_insn (gen_stack_adjust (sp, sp, asm_offset),
+ gen_rtx_SET (Pmode,
+ sp,
+ gen_rtx_PLUS (Pmode, sp, dwarf_offset)));
+ }
+
+ /* If the frame pointer is needed, store the old one at (sp + FP_OFFSET)
+ and point the new one to that location. */
+ if (frame_pointer_needed)
+ {
+ int fp_offset = info->reg_offset[FRAME_POINTER_REGNUM];
+
+ /* ASM_SRC and DWARF_SRC both point to the frame header. ASM_SRC is
+ based on ACCESSOR.BASE but DWARF_SRC is always based on the stack
+ pointer. */
+ rtx asm_src = plus_constant (accessor.base,
+ fp_offset - accessor.base_offset);
+ rtx dwarf_src = plus_constant (sp, fp_offset);
+
+ /* Store the old frame pointer at (sp + FP_OFFSET). */
+ frv_frame_access (&accessor, fp, fp_offset);
+
+ /* Set up the new frame pointer. */
+ frv_frame_insn (gen_rtx_SET (VOIDmode, fp, asm_src),
+ gen_rtx_SET (VOIDmode, fp, dwarf_src));
+
+ /* Access region C from the frame pointer. */
+ accessor.base = fp;
+ accessor.base_offset = fp_offset;
+ }
+
+ /* Set up region C. */
+ frv_frame_access_multi (&accessor, info, STACK_REGS_STRUCT);
+ frv_frame_access_multi (&accessor, info, STACK_REGS_LR);
+ frv_frame_access_multi (&accessor, info, STACK_REGS_STDARG);
+
+ /* Set up region A. */
+ frv_frame_access_standard_regs (FRV_STORE, info);
+
+ /* If this is a varargs/stdarg function, issue a blockage to prevent the
+ scheduler from moving loads before the stores saving the registers. */
+ if (info->stdarg_size > 0)
+ emit_insn (gen_blockage ());
+
+ /* Set up pic register/small data register for this function. */
+ if (flag_pic && cfun->uses_pic_offset_table)
+ emit_insn (gen_pic_prologue (gen_rtx_REG (Pmode, PIC_REGNO),
+ gen_rtx_REG (Pmode, LR_REGNO),
+ gen_rtx_REG (SImode, OFFSET_REGNO)));
+}
+
+
+/* Under frv, all of the work is done via frv_expand_epilogue, but
+ this function provides a convient place to do cleanup. */
+
+static void
+frv_function_epilogue (file, size)
+ FILE *file ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+{
+ frv_stack_cache = (frv_stack_t *)0;
+
+ /* zap last used registers for conditional execution. */
+ memset ((PTR) &frv_ifcvt.tmp_reg, 0, sizeof (frv_ifcvt.tmp_reg));
+
+ /* release the bitmap of created insns. */
+ BITMAP_XFREE (frv_ifcvt.scratch_insns_bitmap);
+}
+
+
+/* Called after register allocation to add any instructions needed for the
+ epilogue. Using an epilogue insn is favored compared to putting all of the
+ instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler
+ to intermix instructions with the saves of the caller saved registers. In
+ some cases, it might be necessary to emit a barrier instruction as the last
+ insn to prevent such scheduling.
+
+ If SIBCALL_P is true, the final branch back to the calling function is
+ omitted, and is used for sibling call (aka tail call) sites. For sibcalls,
+ we must not clobber any arguments used for parameter passing or any stack
+ slots for arguments passed to the current function. */
+
+void
+frv_expand_epilogue (sibcall_p)
+ int sibcall_p;
+{
+ frv_stack_t *info = frv_stack_info ();
+ rtx fp = frame_pointer_rtx;
+ rtx sp = stack_pointer_rtx;
+ rtx return_addr;
+ int fp_offset;
+
+ fp_offset = info->reg_offset[FRAME_POINTER_REGNUM];
+
+ /* Restore the stack pointer to its original value if alloca or the like
+ is used. */
+ if (! current_function_sp_is_unchanging)
+ emit_insn (gen_addsi3 (sp, fp, frv_frame_offset_rtx (-fp_offset)));
+
+ /* Restore the callee-saved registers that were used in this function. */
+ frv_frame_access_standard_regs (FRV_LOAD, info);
+
+ /* Set RETURN_ADDR to the address we should return to. Set it to NULL if
+ no return instruction should be emitted. */
+ if (sibcall_p)
+ return_addr = 0;
+ else if (info->save_p[LR_REGNO])
+ {
+ int lr_offset;
+ rtx mem;
+
+ /* Use the same method to access the link register's slot as we did in
+ the prologue. In other words, use the frame pointer if available,
+ otherwise use the stack pointer.
+
+ LR_OFFSET is the offset of the link register's slot from the start
+ of the frame and MEM is a memory rtx for it. */
+ lr_offset = info->reg_offset[LR_REGNO];
+ if (frame_pointer_needed)
+ mem = frv_frame_mem (Pmode, fp, lr_offset - fp_offset);
+ else
+ mem = frv_frame_mem (Pmode, sp, lr_offset);
+
+ /* Load the old link register into a GPR. */
+ return_addr = gen_rtx_REG (Pmode, TEMP_REGNO);
+ emit_insn (gen_rtx_SET (VOIDmode, return_addr, mem));
+ }
+ else
+ return_addr = gen_rtx_REG (Pmode, LR_REGNO);
+
+ /* Restore the old frame pointer. Emit a USE afterwards to make sure
+ the load is preserved. */
+ if (frame_pointer_needed)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, fp, gen_rtx_MEM (Pmode, fp)));
+ emit_insn (gen_rtx_USE (VOIDmode, fp));
+ }
+
+ /* Deallocate the stack frame. */
+ if (info->total_size != 0)
+ {
+ rtx offset = frv_frame_offset_rtx (info->total_size);
+ emit_insn (gen_stack_adjust (sp, sp, offset));
+ }
+
+ /* If this function uses eh_return, add the final stack adjustment now. */
+ if (current_function_calls_eh_return)
+ emit_insn (gen_stack_adjust (sp, sp, EH_RETURN_STACKADJ_RTX));
+
+ if (return_addr)
+ emit_jump_insn (gen_epilogue_return (return_addr));
+}
+
+
+/* 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 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 `this' pointer in C++. This is the incoming
+ argument *before* the function prologue, e.g. `%o0' on a sparc. The
+ addition must preserve the values of all other incoming arguments.
+
+ After the addition, emit code to jump to FUNCTION, which is a
+ `FUNCTION_DECL'. This is a direct pure jump, not a call, and does not touch
+ the return address. Hence returning from FUNCTION will return to whoever
+ called the current `thunk'.
+
+ The effect must be as if FUNCTION had been called directly with the adjusted
+ first argument. This macro is responsible for emitting all of the code for
+ a thunk function; `FUNCTION_PROLOGUE' and `FUNCTION_EPILOGUE' are not
+ invoked.
+
+ The THUNK_FNDECL is redundant. (DELTA and 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
+ FUNCTION instead of jumping to it. The generic approach does not support
+ varargs. */
+
+static void
+frv_asm_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
+ FILE *file;
+ tree thunk_fndecl ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT delta;
+ HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
+ tree function;
+{
+ const char *name_func = XSTR (XEXP (DECL_RTL (function), 0), 0);
+ const char *name_arg0 = reg_names[FIRST_ARG_REGNUM];
+ const char *name_jmp = reg_names[JUMP_REGNO];
+ const char *parallel = ((PACKING_FLAG_USED_P ()) ? ".p" : "");
+
+ /* Do the add using an addi if possible */
+ if (IN_RANGE_P (delta, -2048, 2047))
+ fprintf (file, "\taddi %s,#%d,%s\n", name_arg0, (int) delta, name_arg0);
+ else
+ {
+ const char *name_add = reg_names[TEMP_REGNO];
+ fprintf (file, "\tsethi%s #hi(", parallel);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, delta);
+ fprintf (file, "),%s\n", name_add);
+ fprintf (file, "\tsetlo #lo(");
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, delta);
+ fprintf (file, "),%s\n", name_add);
+ fprintf (file, "\tadd %s,%s,%s\n", name_add, name_arg0, name_arg0);
+ }
+
+ if (!flag_pic)
+ {
+ fprintf (file, "\tsethi%s #hi(", parallel);
+ assemble_name (file, name_func);
+ fprintf (file, "),%s\n", name_jmp);
+
+ fprintf (file, "\tsetlo #lo(");
+ assemble_name (file, name_func);
+ fprintf (file, "),%s\n", name_jmp);
+ }
+ else
+ {
+ /* Use JUMP_REGNO as a temporary PIC register. */
+ const char *name_lr = reg_names[LR_REGNO];
+ const char *name_gppic = name_jmp;
+ const char *name_tmp = reg_names[TEMP_REGNO];
+
+ fprintf (file, "\tmovsg %s,%s\n", name_lr, name_tmp);
+ fprintf (file, "\tcall 1f\n");
+ fprintf (file, "1:\tmovsg %s,%s\n", name_lr, name_gppic);
+ fprintf (file, "\tmovgs %s,%s\n", name_tmp, name_lr);
+ fprintf (file, "\tsethi%s #gprelhi(1b),%s\n", parallel, name_tmp);
+ fprintf (file, "\tsetlo #gprello(1b),%s\n", name_tmp);
+ fprintf (file, "\tsub %s,%s,%s\n", name_gppic, name_tmp, name_gppic);
+
+ fprintf (file, "\tsethi%s #gprelhi(", parallel);
+ assemble_name (file, name_func);
+ fprintf (file, "),%s\n", name_tmp);
+
+ fprintf (file, "\tsetlo #gprello(");
+ assemble_name (file, name_func);
+ fprintf (file, "),%s\n", name_tmp);
+
+ fprintf (file, "\tadd %s,%s,%s\n", name_gppic, name_tmp, name_jmp);
+ }
+
+ /* Jump to the function address */
+ fprintf (file, "\tjmpl @(%s,%s)\n", name_jmp, reg_names[GPR_FIRST+0]);
+}
+
+
+/* A C expression which is nonzero if a function must have and use a frame
+ pointer. This expression is evaluated in the reload pass. If its value is
+ nonzero the function will have a frame pointer.
+
+ The expression can in principle examine the current function and decide
+ according to the facts, but on most machines the constant 0 or the constant
+ 1 suffices. Use 0 when the machine allows code to be generated with no
+ frame pointer, and doing so saves some time or space. Use 1 when there is
+ no possible advantage to avoiding a frame pointer.
+
+ In certain cases, the compiler does not know how to produce valid code
+ without a frame pointer. The compiler recognizes those cases and
+ automatically gives the function a frame pointer regardless of what
+ `FRAME_POINTER_REQUIRED' says. You don't need to worry about them.
+
+ In a function that does not require a frame pointer, the frame pointer
+ register can be allocated for ordinary usage, unless you mark it as a fixed
+ register. See `FIXED_REGISTERS' for more information. */
+
+/* On frv, create a frame whenever we need to create stack */
+
+int
+frv_frame_pointer_required ()
+{
+ if (! current_function_is_leaf)
+ return TRUE;
+
+ if (get_frame_size () != 0)
+ return TRUE;
+
+ if (cfun->stdarg)
+ return TRUE;
+
+ if (!current_function_sp_is_unchanging)
+ return TRUE;
+
+ if (flag_pic && cfun->uses_pic_offset_table)
+ return TRUE;
+
+ if (profile_flag)
+ return TRUE;
+
+ if (cfun->machine->frame_needed)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It specifies the
+ initial difference between the specified pair of registers. This macro must
+ be defined if `ELIMINABLE_REGS' is defined. */
+
+/* See frv_stack_info for more details on the frv stack frame. */
+
+int
+frv_initial_elimination_offset (from, to)
+ int from;
+ int to;
+{
+ frv_stack_t *info = frv_stack_info ();
+ int ret = 0;
+
+ if (to == STACK_POINTER_REGNUM && from == ARG_POINTER_REGNUM)
+ ret = info->total_size - info->pretend_size;
+
+ else if (to == STACK_POINTER_REGNUM && from == FRAME_POINTER_REGNUM)
+ ret = - info->reg_offset[FRAME_POINTER_REGNUM];
+
+ else if (to == FRAME_POINTER_REGNUM && from == ARG_POINTER_REGNUM)
+ ret = (info->total_size
+ - info->reg_offset[FRAME_POINTER_REGNUM]
+ - info->pretend_size);
+
+ else
+ abort ();
+
+ if (TARGET_DEBUG_STACK)
+ fprintf (stderr, "Eliminate %s to %s by adding %d\n",
+ reg_names [from], reg_names[to], ret);
+
+ return ret;
+}
+
+
+/* This macro offers an alternative to using `__builtin_saveregs' and defining
+ the macro `EXPAND_BUILTIN_SAVEREGS'. Use it to store the anonymous register
+ arguments into the stack so that all the arguments appear to have been
+ passed consecutively on the stack. Once this is done, you can use the
+ standard implementation of varargs that works for machines that pass all
+ their arguments on the stack.
+
+ The argument ARGS_SO_FAR is the `CUMULATIVE_ARGS' data structure, containing
+ the values that obtain after processing of the named arguments. The
+ arguments MODE and TYPE describe the last named argument--its machine mode
+ and its data type as a tree node.
+
+ The macro implementation should do two things: first, push onto the stack
+ all the argument registers *not* used for the named arguments, and second,
+ store the size of the data thus pushed into the `int'-valued variable whose
+ name is supplied as the argument PRETEND_ARGS_SIZE. The value that you
+ store here will serve as additional offset for setting up the stack frame.
+
+ Because you must generate code to push the anonymous arguments at compile
+ time without knowing their data types, `SETUP_INCOMING_VARARGS' is only
+ useful on machines that have just a single category of argument register and
+ use it uniformly for all data types.
+
+ If the argument SECOND_TIME is nonzero, it means that the arguments of the
+ function are being analyzed for the second time. This happens for an inline
+ function, which is not actually compiled until the end of the source file.
+ The macro `SETUP_INCOMING_VARARGS' should not generate any instructions in
+ this case. */
+
+void
+frv_setup_incoming_varargs (cum, mode, type, pretend_size, second_time)
+ CUMULATIVE_ARGS *cum;
+ enum machine_mode mode;
+ tree type ATTRIBUTE_UNUSED;
+ int *pretend_size;
+ int second_time;
+{
+ if (TARGET_DEBUG_ARG)
+ fprintf (stderr,
+ "setup_vararg: words = %2d, mode = %4s, pretend_size = %d, second_time = %d\n",
+ *cum, GET_MODE_NAME (mode), *pretend_size, second_time);
+}
+
+
+/* If defined, is a C expression that produces the machine-specific code for a
+ call to `__builtin_saveregs'. This code will be moved to the very beginning
+ of the function, before any parameter access are made. The return value of
+ this function should be an RTX that contains the value to use as the return
+ of `__builtin_saveregs'.
+
+ If this macro is not defined, the compiler will output an ordinary call to
+ the library function `__builtin_saveregs'. */
+
+rtx
+frv_expand_builtin_saveregs ()
+{
+ int offset = UNITS_PER_WORD * FRV_NUM_ARG_REGS;
+
+ if (TARGET_DEBUG_ARG)
+ fprintf (stderr, "expand_builtin_saveregs: offset from ap = %d\n",
+ offset);
+
+ return gen_rtx (PLUS, Pmode, virtual_incoming_args_rtx, GEN_INT (- offset));
+}
+
+
+/* Expand __builtin_va_start to do the va_start macro. */
+
+void
+frv_expand_builtin_va_start (valist, nextarg)
+ tree valist;
+ rtx nextarg;
+{
+ tree t;
+ int num = cfun->args_info - FIRST_ARG_REGNUM - FRV_NUM_ARG_REGS;
+
+ nextarg = gen_rtx_PLUS (Pmode, virtual_incoming_args_rtx,
+ GEN_INT (UNITS_PER_WORD * num));
+
+ if (TARGET_DEBUG_ARG)
+ {
+ fprintf (stderr, "va_start: args_info = %d, num = %d\n",
+ cfun->args_info, num);
+
+ debug_rtx (nextarg);
+ }
+
+ t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
+ make_tree (ptr_type_node, nextarg));
+ TREE_SIDE_EFFECTS (t) = 1;
+
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+}
+
+
+/* Expand __builtin_va_arg to do the va_arg macro. */
+
+rtx
+frv_expand_builtin_va_arg(valist, type)
+ tree valist;
+ tree type;
+{
+ rtx addr;
+ rtx mem;
+ rtx reg;
+
+ if (TARGET_DEBUG_ARG)
+ {
+ fprintf (stderr, "va_arg:\n");
+ debug_tree (type);
+ }
+
+ if (! AGGREGATE_TYPE_P (type))
+ return std_expand_builtin_va_arg (valist, type);
+
+ addr = std_expand_builtin_va_arg (valist, ptr_type_node);
+ mem = gen_rtx_MEM (Pmode, addr);
+ reg = gen_reg_rtx (Pmode);
+
+ set_mem_alias_set (mem, get_varargs_alias_set ());
+ emit_move_insn (reg, mem);
+
+ return reg;
+}
+
+
+/* Expand a block move operation, and return 1 if successful. Return 0
+ if we should let the compiler generate normal code.
+
+ operands[0] is the destination
+ operands[1] is the source
+ operands[2] is the length
+ operands[3] is the alignment */
+
+/* Maximum number of loads to do before doing the stores */
+#ifndef MAX_MOVE_REG
+#define MAX_MOVE_REG 4
+#endif
+
+/* Maximum number of total loads to do. */
+#ifndef TOTAL_MOVE_REG
+#define TOTAL_MOVE_REG 8
+#endif
+
+int
+frv_expand_block_move (operands)
+ rtx operands[];
+{
+ rtx orig_dest = operands[0];
+ rtx orig_src = operands[1];
+ rtx bytes_rtx = operands[2];
+ rtx align_rtx = operands[3];
+ int constp = (GET_CODE (bytes_rtx) == CONST_INT);
+ int align;
+ int bytes;
+ int offset;
+ int num_reg;
+ int i;
+ rtx src_reg;
+ rtx dest_reg;
+ rtx src_addr;
+ rtx dest_addr;
+ rtx src_mem;
+ rtx dest_mem;
+ rtx tmp_reg;
+ rtx stores[MAX_MOVE_REG];
+ int move_bytes;
+ enum machine_mode mode;
+
+ /* If this is not a fixed size move, just call memcpy */
+ if (! constp)
+ return FALSE;
+
+ /* If this is not a fixed size alignment, abort */
+ if (GET_CODE (align_rtx) != CONST_INT)
+ abort ();
+
+ align = INTVAL (align_rtx);
+
+ /* Anything to move? */
+ bytes = INTVAL (bytes_rtx);
+ if (bytes <= 0)
+ return TRUE;
+
+ /* Don't support real large moves. */
+ if (bytes > TOTAL_MOVE_REG*align)
+ return FALSE;
+
+ /* Move the address into scratch registers. */
+ dest_reg = copy_addr_to_reg (XEXP (orig_dest, 0));
+ src_reg = copy_addr_to_reg (XEXP (orig_src, 0));
+
+ num_reg = offset = 0;
+ for ( ; bytes > 0; (bytes -= move_bytes), (offset += move_bytes))
+ {
+ /* Calculate the correct offset for src/dest */
+ if (offset == 0)
+ {
+ src_addr = src_reg;
+ dest_addr = dest_reg;
+ }
+ else
+ {
+ src_addr = plus_constant (src_reg, offset);
+ dest_addr = plus_constant (dest_reg, offset);
+ }
+
+ /* Generate the appropriate load and store, saving the stores
+ for later. */
+ if (bytes >= 4 && align >= 4)
+ mode = SImode;
+ else if (bytes >= 2 && align >= 2)
+ mode = HImode;
+ else
+ mode = QImode;
+
+ move_bytes = GET_MODE_SIZE (mode);
+ tmp_reg = gen_reg_rtx (mode);
+ src_mem = change_address (orig_src, mode, src_addr);
+ dest_mem = change_address (orig_dest, mode, dest_addr);
+ emit_insn (gen_rtx_SET (VOIDmode, tmp_reg, src_mem));
+ stores[num_reg++] = gen_rtx_SET (VOIDmode, dest_mem, tmp_reg);
+
+ if (num_reg >= MAX_MOVE_REG)
+ {
+ for (i = 0; i < num_reg; i++)
+ emit_insn (stores[i]);
+ num_reg = 0;
+ }
+ }
+
+ for (i = 0; i < num_reg; i++)
+ emit_insn (stores[i]);
+
+ return TRUE;
+}
+
+
+/* Expand a block clear operation, and return 1 if successful. Return 0
+ if we should let the compiler generate normal code.
+
+ operands[0] is the destination
+ operands[1] is the length
+ operands[2] is the alignment */
+
+int
+frv_expand_block_clear (operands)
+ rtx operands[];
+{
+ rtx orig_dest = operands[0];
+ rtx bytes_rtx = operands[1];
+ rtx align_rtx = operands[2];
+ int constp = (GET_CODE (bytes_rtx) == CONST_INT);
+ int align;
+ int bytes;
+ int offset;
+ int num_reg;
+ rtx dest_reg;
+ rtx dest_addr;
+ rtx dest_mem;
+ int clear_bytes;
+ enum machine_mode mode;
+
+ /* If this is not a fixed size move, just call memcpy */
+ if (! constp)
+ return FALSE;
+
+ /* If this is not a fixed size alignment, abort */
+ if (GET_CODE (align_rtx) != CONST_INT)
+ abort ();
+
+ align = INTVAL (align_rtx);
+
+ /* Anything to move? */
+ bytes = INTVAL (bytes_rtx);
+ if (bytes <= 0)
+ return TRUE;
+
+ /* Don't support real large clears. */
+ if (bytes > TOTAL_MOVE_REG*align)
+ return FALSE;
+
+ /* Move the address into a scratch register. */
+ dest_reg = copy_addr_to_reg (XEXP (orig_dest, 0));
+
+ num_reg = offset = 0;
+ for ( ; bytes > 0; (bytes -= clear_bytes), (offset += clear_bytes))
+ {
+ /* Calculate the correct offset for src/dest */
+ dest_addr = ((offset == 0)
+ ? dest_reg
+ : plus_constant (dest_reg, offset));
+
+ /* Generate the appropriate store of gr0 */
+ if (bytes >= 4 && align >= 4)
+ mode = SImode;
+ else if (bytes >= 2 && align >= 2)
+ mode = HImode;
+ else
+ mode = QImode;
+
+ clear_bytes = GET_MODE_SIZE (mode);
+ dest_mem = change_address (orig_dest, mode, dest_addr);
+ emit_insn (gen_rtx_SET (VOIDmode, dest_mem, const0_rtx));
+ }
+
+ return TRUE;
+}
+
+
+/* The following variable is used to output modifiers of assembler
+ code of the current output insn.. */
+
+static rtx *frv_insn_operands;
+
+/* The following function is used to add assembler insn code suffix .p
+ if it is necessary. */
+
+const char *
+frv_asm_output_opcode (f, ptr)
+ FILE *f;
+ const char *ptr;
+{
+ int c;
+
+ if (! PACKING_FLAG_USED_P())
+ return ptr;
+
+ for (; *ptr && *ptr != ' ' && *ptr != '\t';)
+ {
+ c = *ptr++;
+ if (c == '%' && ((*ptr >= 'a' && *ptr <= 'z')
+ || (*ptr >= 'A' && *ptr <= 'Z')))
+ {
+ int letter = *ptr++;
+
+ c = atoi (ptr);
+ frv_print_operand (f, frv_insn_operands [c], letter);
+ while ((c = *ptr) >= '0' && c <= '9')
+ ptr++;
+ }
+ else
+ fputc (c, f);
+ }
+
+ if (!frv_insn_packing_flag)
+ fprintf (f, ".p");
+
+ return ptr;
+}
+
+/* The following function sets up the packing bit for the current
+ output insn. Remember that the function is not called for asm
+ insns. */
+
+void
+frv_final_prescan_insn (insn, opvec, noperands)
+ rtx insn;
+ rtx *opvec;
+ int noperands ATTRIBUTE_UNUSED;
+{
+ if (! PACKING_FLAG_USED_P())
+ return;
+
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ return;
+
+ frv_insn_operands = opvec;
+
+ /* Look for the next printable instruction. frv_pack_insns () has set
+ things up so that any printable instruction will have TImode if it
+ starts a new packet and VOIDmode if it should be packed with the
+ previous instruction.
+
+ Printable instructions will be asm_operands or match one of the .md
+ patterns. Since asm instructions cannot be packed -- and will
+ therefore have TImode -- this loop terminates on any recognisable
+ instruction, and on any unrecognisable instruction with TImode. */
+ for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
+ {
+ if (NOTE_P (insn))
+ continue;
+ else if (!INSN_P (insn))
+ break;
+ else if (GET_MODE (insn) == TImode || INSN_CODE (insn) != -1)
+ break;
+ }
+
+ /* Set frv_insn_packing_flag to FALSE if the next instruction should
+ be packed with this one. Set it to TRUE otherwise. If the next
+ instruction is an asm insntruction, this statement will set the
+ flag to TRUE, and that value will still hold when the asm operands
+ themselves are printed. */
+ frv_insn_packing_flag = ! (insn && INSN_P (insn)
+ && GET_MODE (insn) != TImode);
+}
+
+
+
+/* A C expression whose value is RTL representing the address in a stack frame
+ where the pointer to the caller's frame is stored. Assume that FRAMEADDR is
+ an RTL expression for the address of the stack frame itself.
+
+ If you don't define this macro, the default is to return the value of
+ FRAMEADDR--that is, the stack frame address is also the address of the stack
+ word that points to the previous frame. */
+
+/* The default is correct, but we need to make sure the frame gets created. */
+rtx
+frv_dynamic_chain_address (frame)
+ rtx frame;
+{
+ cfun->machine->frame_needed = 1;
+ return frame;
+}
+
+
+/* A C expression whose value is RTL representing the value of 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, or the frame
+ pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is
+ defined.
+
+ The value of the expression must always be the correct address when COUNT is
+ zero, but may be `NULL_RTX' if there is not way to determine the return
+ address of other frames. */
+
+rtx
+frv_return_addr_rtx (count, frame)
+ int count ATTRIBUTE_UNUSED;
+ rtx frame;
+{
+ cfun->machine->frame_needed = 1;
+ return gen_rtx_MEM (Pmode, plus_constant (frame, 8));
+}
+
+/* Given a memory reference MEMREF, interpret the referenced memory as
+ an array of MODE values, and return a reference to the element
+ specified by INDEX. Assume that any pre-modification implicit in
+ MEMREF has already happened.
+
+ MEMREF must be a legitimate operand for modes larger than SImode.
+ GO_IF_LEGITIMATE_ADDRESS forbids register+register addresses, which
+ this function cannot handle. */
+rtx
+frv_index_memory (memref, mode, index)
+ rtx memref;
+ enum machine_mode mode;
+ int index;
+{
+ rtx base = XEXP (memref, 0);
+ if (GET_CODE (base) == PRE_MODIFY)
+ base = XEXP (base, 0);
+ return change_address (memref, mode,
+ plus_constant (base, index * GET_MODE_SIZE (mode)));
+}
+
+
+/* Print a memory address as an operand to reference that memory location. */
+void
+frv_print_operand_address (stream, x)
+ FILE * stream;
+ rtx x;
+{
+ if (GET_CODE (x) == MEM)
+ x = XEXP (x, 0);
+
+ switch (GET_CODE (x))
+ {
+ case REG:
+ fputs (reg_names [ REGNO (x)], stream);
+ return;
+
+ case CONST_INT:
+ fprintf (stream, "%ld", (long) INTVAL (x));
+ return;
+
+ case SYMBOL_REF:
+ assemble_name (stream, XSTR (x, 0));
+ return;
+
+ case LABEL_REF:
+ case CONST:
+ output_addr_const (stream, x);
+ return;
+
+ default:
+ break;
+ }
+
+ fatal_insn ("Bad insn to frv_print_operand_address:", x);
+}
+
+
+static void
+frv_print_operand_memory_reference_reg (stream, x)
+ FILE *stream;
+ rtx x;
+{
+ int regno = true_regnum (x);
+ if (GPR_P (regno))
+ fputs (reg_names[regno], stream);
+ else
+ fatal_insn ("Bad register to frv_print_operand_memory_reference_reg:", x);
+}
+
+/* Print a memory reference suitable for the ld/st instructions. */
+
+static void
+frv_print_operand_memory_reference (stream, x, addr_offset)
+ FILE *stream;
+ rtx x;
+ int addr_offset;
+{
+ rtx x0 = NULL_RTX;
+ rtx x1 = NULL_RTX;
+
+ switch (GET_CODE (x))
+ {
+ case SUBREG:
+ case REG:
+ x0 = x;
+ break;
+
+ case PRE_MODIFY: /* (pre_modify (reg) (plus (reg) (reg))) */
+ x0 = XEXP (x, 0);
+ x1 = XEXP (XEXP (x, 1), 1);
+ break;
+
+ case CONST_INT:
+ x1 = x;
+ break;
+
+ case PLUS:
+ x0 = XEXP (x, 0);
+ x1 = XEXP (x, 1);
+ if (GET_CODE (x0) == CONST_INT)
+ {
+ x0 = XEXP (x, 1);
+ x1 = XEXP (x, 0);
+ }
+ break;
+
+ default:
+ fatal_insn ("Bad insn to frv_print_operand_memory_reference:", x);
+ break;
+
+ }
+
+ if (addr_offset)
+ {
+ if (!x1)
+ x1 = const0_rtx;
+ else if (GET_CODE (x1) != CONST_INT)
+ fatal_insn ("Bad insn to frv_print_operand_memory_reference:", x);
+ }
+
+ fputs ("@(", stream);
+ if (!x0)
+ fputs (reg_names[GPR_R0], stream);
+ else if (GET_CODE (x0) == REG || GET_CODE (x0) == SUBREG)
+ frv_print_operand_memory_reference_reg (stream, x0);
+ else
+ fatal_insn ("Bad insn to frv_print_operand_memory_reference:", x);
+
+ fputs (",", stream);
+ if (!x1)
+ fputs (reg_names [GPR_R0], stream);
+
+ else
+ {
+ switch (GET_CODE (x1))
+ {
+ case SUBREG:
+ case REG:
+ frv_print_operand_memory_reference_reg (stream, x1);
+ break;
+
+ case CONST_INT:
+ fprintf (stream, "%ld", (long) (INTVAL (x1) + addr_offset));
+ break;
+
+ case SYMBOL_REF:
+ if (x0 && GET_CODE (x0) == REG && REGNO (x0) == SDA_BASE_REG
+ && symbol_ref_small_data_p (x1))
+ {
+ fputs ("#gprel12(", stream);
+ assemble_name (stream, XSTR (x1, 0));
+ fputs (")", stream);
+ }
+ else
+ fatal_insn ("Bad insn to frv_print_operand_memory_reference:", x);
+ break;
+
+ case CONST:
+ if (x0 && GET_CODE (x0) == REG && REGNO (x0) == SDA_BASE_REG
+ && const_small_data_p (x1))
+ {
+ fputs ("#gprel12(", stream);
+ assemble_name (stream, XSTR (XEXP (XEXP (x1, 0), 0), 0));
+ fprintf (stream, "+%d)", INTVAL (XEXP (XEXP (x1, 0), 1)));
+ }
+ else
+ fatal_insn ("Bad insn to frv_print_operand_memory_reference:", x);
+ break;
+
+ default:
+ fatal_insn ("Bad insn to frv_print_operand_memory_reference:", x);
+ }
+ }
+
+ fputs (")", stream);
+}
+
+
+/* Return 2 for likely branches and 0 for non-likely branches */
+
+#define FRV_JUMP_LIKELY 2
+#define FRV_JUMP_NOT_LIKELY 0
+
+static int
+frv_print_operand_jump_hint (insn)
+ rtx insn;
+{
+ rtx note;
+ rtx labelref;
+ int ret;
+ HOST_WIDE_INT prob = -1;
+ enum { UNKNOWN, BACKWARD, FORWARD } jump_type = UNKNOWN;
+
+ if (GET_CODE (insn) != JUMP_INSN)
+ abort ();
+
+ /* Assume any non-conditional jump is likely. */
+ if (! any_condjump_p (insn))
+ ret = FRV_JUMP_LIKELY;
+
+ else
+ {
+ labelref = condjump_label (insn);
+ if (labelref)
+ {
+ rtx label = XEXP (labelref, 0);
+ jump_type = (insn_current_address > INSN_ADDRESSES (INSN_UID (label))
+ ? BACKWARD
+ : FORWARD);
+ }
+
+ note = find_reg_note (insn, REG_BR_PROB, 0);
+ if (!note)
+ ret = ((jump_type == BACKWARD) ? FRV_JUMP_LIKELY : FRV_JUMP_NOT_LIKELY);
+
+ else
+ {
+ prob = INTVAL (XEXP (note, 0));
+ ret = ((prob >= (REG_BR_PROB_BASE / 2))
+ ? FRV_JUMP_LIKELY
+ : FRV_JUMP_NOT_LIKELY);
+ }
+ }
+
+#if 0
+ if (TARGET_DEBUG)
+ {
+ char *direction;
+
+ switch (jump_type)
+ {
+ default:
+ case UNKNOWN: direction = "unknown jump direction"; break;
+ case BACKWARD: direction = "jump backward"; break;
+ case FORWARD: direction = "jump forward"; break;
+ }
+
+ fprintf (stderr,
+ "%s: uid %ld, %s, probability = %ld, max prob. = %ld, hint = %d\n",
+ IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
+ (long)INSN_UID (insn), direction, (long)prob,
+ (long)REG_BR_PROB_BASE, ret);
+ }
+#endif
+
+ return ret;
+}
+
+
+/* Print an operand to an assembler instruction.
+
+ `%' followed by a letter and a digit says to output an operand in an
+ alternate fashion. Four letters have standard, built-in meanings described
+ below. The machine description macro `PRINT_OPERAND' can define additional
+ letters with nonstandard meanings.
+
+ `%cDIGIT' can be used to substitute an operand that is a constant value
+ without the syntax that normally indicates an immediate operand.
+
+ `%nDIGIT' is like `%cDIGIT' except that the value of the constant is negated
+ before printing.
+
+ `%aDIGIT' can be used to substitute an operand as if it were a memory
+ reference, with the actual operand treated as the address. This may be
+ useful when outputting a "load address" instruction, because often the
+ assembler syntax for such an instruction requires you to write the operand
+ as if it were a memory reference.
+
+ `%lDIGIT' is used to substitute a `label_ref' into a jump instruction.
+
+ `%=' outputs a number which is unique to each instruction in the entire
+ compilation. This is useful for making local labels to be referred to more
+ than once in a single template that generates multiple assembler
+ instructions.
+
+ `%' followed by a punctuation character specifies a substitution that does
+ not use an operand. Only one case is standard: `%%' outputs a `%' into the
+ assembler code. Other nonstandard cases can be defined in the
+ `PRINT_OPERAND' macro. You must also define which punctuation characters
+ are valid with the `PRINT_OPERAND_PUNCT_VALID_P' macro. */
+
+void
+frv_print_operand (file, x, code)
+ FILE * file;
+ rtx x;
+ int code;
+{
+ HOST_WIDE_INT value;
+ int offset;
+
+ if (code != 0 && !isalpha (code))
+ value = 0;
+
+ else if (GET_CODE (x) == CONST_INT)
+ value = INTVAL (x);
+
+ else if (GET_CODE (x) == CONST_DOUBLE)
+ {
+ if (GET_MODE (x) == SFmode)
+ {
+ REAL_VALUE_TYPE rv;
+ long l;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
+ REAL_VALUE_TO_TARGET_SINGLE (rv, l);
+ value = l;
+ }
+
+ else if (GET_MODE (x) == VOIDmode)
+ value = CONST_DOUBLE_LOW (x);
+
+ else
+ fatal_insn ("Bad insn in frv_print_operand, bad const_double", x);
+ }
+
+ else
+ value = 0;
+
+ switch (code)
+ {
+
+ case '.':
+ /* Output r0 */
+ fputs (reg_names[GPR_R0], file);
+ break;
+
+ case '#':
+ fprintf (file, "%d", frv_print_operand_jump_hint (current_output_insn));
+ break;
+
+ case SDATA_FLAG_CHAR:
+ /* Output small data area base register (gr16). */
+ fputs (reg_names[SDA_BASE_REG], file);
+ break;
+
+ case '~':
+ /* Output pic register (gr17). */
+ fputs (reg_names[PIC_REGNO], file);
+ break;
+
+ case '*':
+ /* Output the temporary integer CCR register */
+ fputs (reg_names[ICR_TEMP], file);
+ break;
+
+ case '&':
+ /* Output the temporary integer CC register */
+ fputs (reg_names[ICC_TEMP], file);
+ break;
+
+ /* case 'a': print an address */
+
+ case 'C':
+ /* Print appropriate test for integer branch false operation */
+ switch (GET_CODE (x))
+ {
+ default:
+ fatal_insn ("Bad insn to frv_print_operand, 'C' modifier:", x);
+
+ case EQ: fputs ("ne", file); break;
+ case NE: fputs ("eq", file); break;
+ case LT: fputs ("ge", file); break;
+ case LE: fputs ("gt", file); break;
+ case GT: fputs ("le", file); break;
+ case GE: fputs ("lt", file); break;
+ case LTU: fputs ("nc", file); break;
+ case LEU: fputs ("hi", file); break;
+ case GTU: fputs ("ls", file); break;
+ case GEU: fputs ("c", file); break;
+ }
+ break;
+
+ /* case 'c': print a constant without the constant prefix. If
+ CONSTANT_ADDRESS_P(x) is not true, PRINT_OPERAND is called. */
+
+ case 'c':
+ /* Print appropriate test for integer branch true operation */
+ switch (GET_CODE (x))
+ {
+ default:
+ fatal_insn ("Bad insn to frv_print_operand, 'c' modifier:", x);
+
+ case EQ: fputs ("eq", file); break;
+ case NE: fputs ("ne", file); break;
+ case LT: fputs ("lt", file); break;
+ case LE: fputs ("le", file); break;
+ case GT: fputs ("gt", file); break;
+ case GE: fputs ("ge", file); break;
+ case LTU: fputs ("c", file); break;
+ case LEU: fputs ("ls", file); break;
+ case GTU: fputs ("hi", file); break;
+ case GEU: fputs ("nc", file); break;
+ }
+ break;
+
+ case 'e':
+ /* Print 1 for a NE and 0 for an EQ to give the final argument
+ for a conditional instruction. */
+ if (GET_CODE (x) == NE)
+ fputs ("1", file);
+
+ else if (GET_CODE (x) == EQ)
+ fputs ("0", file);
+
+ else
+ fatal_insn ("Bad insn to frv_print_operand, 'e' modifier:", x);
+ break;
+
+ case 'F':
+ /* Print appropriate test for floating point branch false operation */
+ switch (GET_CODE (x))
+ {
+ default:
+ fatal_insn ("Bad insn to frv_print_operand, 'F' modifier:", x);
+
+ case EQ: fputs ("ne", file); break;
+ case NE: fputs ("eq", file); break;
+ case LT: fputs ("uge", file); break;
+ case LE: fputs ("ug", file); break;
+ case GT: fputs ("ule", file); break;
+ case GE: fputs ("ul", file); break;
+ }
+ break;
+
+ case 'f':
+ /* Print appropriate test for floating point branch true operation */
+ switch (GET_CODE (x))
+ {
+ default:
+ fatal_insn ("Bad insn to frv_print_operand, 'f' modifier:", x);
+
+ case EQ: fputs ("eq", file); break;
+ case NE: fputs ("ne", file); break;
+ case LT: fputs ("lt", file); break;
+ case LE: fputs ("le", file); break;
+ case GT: fputs ("gt", file); break;
+ case GE: fputs ("ge", file); break;
+ }
+ break;
+
+ case 'I':
+ /* Print 'i' if the operand is a constant, or is a memory reference that
+ adds a constant */
+ if (GET_CODE (x) == MEM)
+ x = ((GET_CODE (XEXP (x, 0)) == PLUS)
+ ? XEXP (XEXP (x, 0), 1)
+ : XEXP (x, 0));
+
+ switch (GET_CODE (x))
+ {
+ default:
+ break;
+
+ case CONST_INT:
+ case SYMBOL_REF:
+ case CONST:
+ fputs ("i", file);
+ break;
+ }
+ break;
+
+ case 'i':
+ /* For jump instructions, print 'i' if the operand is a constant or
+ is an expression that adds a constant */
+ if (GET_CODE (x) == CONST_INT)
+ fputs ("i", file);
+
+ else
+ {
+ if (GET_CODE (x) == CONST_INT
+ || (GET_CODE (x) == PLUS
+ && (GET_CODE (XEXP (x, 1)) == CONST_INT
+ || GET_CODE (XEXP (x, 0)) == CONST_INT)))
+ fputs ("i", file);
+ }
+ break;
+
+ case 'L':
+ /* Print the lower register of a double word register pair */
+ if (GET_CODE (x) == REG)
+ fputs (reg_names[ REGNO (x)+1 ], file);
+ else
+ fatal_insn ("Bad insn to frv_print_operand, 'L' modifier:", x);
+ break;
+
+ /* case 'l': print a LABEL_REF */
+
+ case 'M':
+ case 'N':
+ /* Print a memory reference for ld/st/jmp, %N prints a memory reference
+ for the second word of double memory operations. */
+ offset = (code == 'M') ? 0 : UNITS_PER_WORD;
+ switch (GET_CODE (x))
+ {
+ default:
+ fatal_insn ("Bad insn to frv_print_operand, 'M/N' modifier:", x);
+
+ case MEM:
+ frv_print_operand_memory_reference (file, XEXP (x, 0), offset);
+ break;
+
+ case REG:
+ case SUBREG:
+ case CONST_INT:
+ case PLUS:
+ case SYMBOL_REF:
+ frv_print_operand_memory_reference (file, x, offset);
+ break;
+ }
+ break;
+
+ case 'O':
+ /* Print the opcode of a command. */
+ switch (GET_CODE (x))
+ {
+ default:
+ fatal_insn ("Bad insn to frv_print_operand, 'O' modifier:", x);
+
+ case PLUS: fputs ("add", file); break;
+ case MINUS: fputs ("sub", file); break;
+ case AND: fputs ("and", file); break;
+ case IOR: fputs ("or", file); break;
+ case XOR: fputs ("xor", file); break;
+ case ASHIFT: fputs ("sll", file); break;
+ case ASHIFTRT: fputs ("sra", file); break;
+ case LSHIFTRT: fputs ("srl", file); break;
+ }
+ break;
+
+ /* case 'n': negate and print a constant int */
+
+ case 'P':
+ /* Print PIC label using operand as the number. */
+ if (GET_CODE (x) != CONST_INT)
+ fatal_insn ("Bad insn to frv_print_operand, P modifier:", x);
+
+ fprintf (file, ".LCF%ld", (long)INTVAL (x));
+ break;
+
+ case 'U':
+ /* Print 'u' if the operand is a update load/store */
+ if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == PRE_MODIFY)
+ fputs ("u", file);
+ break;
+
+ case 'z':
+ /* If value is 0, print gr0, otherwise it must be a register */
+ if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0)
+ fputs (reg_names[GPR_R0], file);
+
+ else if (GET_CODE (x) == REG)
+ fputs (reg_names [REGNO (x)], file);
+
+ else
+ fatal_insn ("Bad insn in frv_print_operand, z case", x);
+ break;
+
+ case 'x':
+ /* Print constant in hex */
+ if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
+ {
+ fprintf (file, "%s0x%.4lx", IMMEDIATE_PREFIX, (long) value);
+ break;
+ }
+
+ /* fall through */
+
+ case '\0':
+ if (GET_CODE (x) == REG)
+ fputs (reg_names [REGNO (x)], file);
+
+ else if (GET_CODE (x) == CONST_INT
+ || GET_CODE (x) == CONST_DOUBLE)
+ fprintf (file, "%s%ld", IMMEDIATE_PREFIX, (long) value);
+
+ else if (GET_CODE (x) == MEM)
+ frv_print_operand_address (file, XEXP (x, 0));
+
+ else if (CONSTANT_ADDRESS_P (x))
+ frv_print_operand_address (file, x);
+
+ else
+ fatal_insn ("Bad insn in frv_print_operand, 0 case", x);
+
+ break;
+
+ default:
+ fatal_insn ("frv_print_operand: unknown code", x);
+ break;
+ }
+
+ return;
+}
+
+
+/* A C statement (sans semicolon) for initializing the variable CUM for the
+ state at the beginning of the argument list. The variable has type
+ `CUMULATIVE_ARGS'. The value of 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. The value of INDIRECT is nonzero when
+ processing an indirect call, for example a call through a function pointer.
+ The value of INDIRECT is zero for a call to an explicitly named function, a
+ library function call, or when `INIT_CUMULATIVE_ARGS' is used to find
+ arguments for the function being compiled.
+
+ When processing a call to a compiler support library function, LIBNAME
+ identifies which one. It is a `symbol_ref' rtx which contains the name of
+ the function, as a string. LIBNAME is 0 when an ordinary C function call is
+ being processed. Thus, each time this macro is called, either LIBNAME or
+ FNTYPE is nonzero, but never both of them at once. */
+
+void
+frv_init_cumulative_args (cum, fntype, libname, indirect, incoming)
+ CUMULATIVE_ARGS *cum;
+ tree fntype;
+ rtx libname;
+ int indirect;
+ int incoming;
+{
+ *cum = FIRST_ARG_REGNUM;
+
+ if (TARGET_DEBUG_ARG)
+ {
+ fprintf (stderr, "\ninit_cumulative_args:");
+ if (indirect)
+ fputs (" indirect", stderr);
+
+ if (incoming)
+ fputs (" incoming", stderr);
+
+ if (fntype)
+ {
+ tree ret_type = TREE_TYPE (fntype);
+ fprintf (stderr, " return=%s,",
+ tree_code_name[ (int)TREE_CODE (ret_type) ]);
+ }
+
+ if (libname && GET_CODE (libname) == SYMBOL_REF)
+ fprintf (stderr, " libname=%s", XSTR (libname, 0));
+
+ if (cfun->returns_struct)
+ fprintf (stderr, " return-struct");
+
+ putc ('\n', stderr);
+ }
+}
+
+
+/* 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. */
+
+int
+frv_function_arg_boundary (mode, type)
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ tree type ATTRIBUTE_UNUSED;
+{
+ return BITS_PER_WORD;
+}
+
+
+/* A C expression that controls whether a function argument is passed in a
+ register, and which register.
+
+ The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes (in a way
+ defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE) all of the previous
+ arguments so far passed in registers; MODE, the machine mode of the argument;
+ TYPE, the data type of the argument as a tree node or 0 if that is not known
+ (which happens for C support library functions); and NAMED, which is 1 for an
+ ordinary argument and 0 for nameless arguments that correspond to `...' in the
+ called function's prototype.
+
+ The value of the expression should either be a `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 usual way to make the ANSI library `stdarg.h' work on a machine where
+ some arguments are usually passed in registers, is to cause nameless
+ arguments to be passed on the stack instead. This is done by making
+ `FUNCTION_ARG' return 0 whenever NAMED is 0.
+
+ You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of
+ this macro to determine if this argument is of a type that must be passed in
+ the stack. If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG'
+ returns nonzero for such an argument, the compiler will abort. If
+ `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the
+ stack and then loaded into a register. */
+
+rtx
+frv_function_arg (cum, mode, type, named, incoming)
+ CUMULATIVE_ARGS *cum;
+ enum machine_mode mode;
+ tree type ATTRIBUTE_UNUSED;
+ int named;
+ int incoming ATTRIBUTE_UNUSED;
+{
+ enum machine_mode xmode = (mode == BLKmode) ? SImode : mode;
+ int arg_num = *cum;
+ rtx ret;
+ const char *debstr;
+
+ /* Return a marker for use in the call instruction. */
+ if (xmode == VOIDmode)
+ {
+ ret = const0_rtx;
+ debstr = "<0>";
+ }
+
+ else if (arg_num <= LAST_ARG_REGNUM)
+ {
+ ret = gen_rtx (REG, xmode, arg_num);
+ debstr = reg_names[arg_num];
+ }
+
+ else
+ {
+ ret = NULL_RTX;
+ debstr = "memory";
+ }
+
+ if (TARGET_DEBUG_ARG)
+ fprintf (stderr,
+ "function_arg: words = %2d, mode = %4s, named = %d, size = %3d, arg = %s\n",
+ arg_num, GET_MODE_NAME (mode), named, GET_MODE_SIZE (mode), debstr);
+
+ return ret;
+}
+
+
+/* A C statement (sans semicolon) to update the summarizer variable CUM to
+ advance past an argument in the argument list. The values MODE, TYPE and
+ NAMED describe that argument. Once this is done, the variable CUM is
+ suitable for analyzing the *following* argument with `FUNCTION_ARG', etc.
+
+ This macro need not do anything if the argument in question was passed on
+ the stack. The compiler knows how to track the amount of stack space used
+ for arguments without any special help. */
+
+void
+frv_function_arg_advance (cum, mode, type, named)
+ CUMULATIVE_ARGS *cum;
+ enum machine_mode mode;
+ tree type ATTRIBUTE_UNUSED;
+ int named;
+{
+ enum machine_mode xmode = (mode == BLKmode) ? SImode : mode;
+ int bytes = GET_MODE_SIZE (xmode);
+ int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+ int arg_num = *cum;
+
+ *cum = arg_num + words;
+
+ if (TARGET_DEBUG_ARG)
+ fprintf (stderr,
+ "function_adv: words = %2d, mode = %4s, named = %d, size = %3d\n",
+ arg_num, GET_MODE_NAME (mode), named, words * UNITS_PER_WORD);
+}
+
+
+/* A C expression for the number of words, at the beginning of an argument,
+ must be put in registers. The value must be zero for arguments that are
+ passed entirely in registers or that are entirely pushed on the stack.
+
+ On some machines, certain arguments must be passed partially in registers
+ and partially in memory. On these machines, typically the first N words of
+ arguments are passed in registers, and the rest on the stack. If a
+ multi-word argument (a `double' or a structure) crosses that boundary, its
+ first few words must be passed in registers and the rest must be pushed.
+ This macro tells the compiler when this occurs, and how many of the words
+ should go in registers.
+
+ `FUNCTION_ARG' for these arguments should return the first register to be
+ used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for
+ the called function. */
+
+int
+frv_function_arg_partial_nregs (cum, mode, type, named)
+ CUMULATIVE_ARGS *cum;
+ enum machine_mode mode;
+ tree type ATTRIBUTE_UNUSED;
+ int named ATTRIBUTE_UNUSED;
+{
+ enum machine_mode xmode = (mode == BLKmode) ? SImode : mode;
+ int bytes = GET_MODE_SIZE (xmode);
+ int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+ int arg_num = *cum;
+ int ret;
+
+ ret = ((arg_num <= LAST_ARG_REGNUM && arg_num + words > LAST_ARG_REGNUM+1)
+ ? LAST_ARG_REGNUM - arg_num + 1
+ : 0);
+
+ if (TARGET_DEBUG_ARG && ret)
+ fprintf (stderr, "function_arg_partial_nregs: %d\n", ret);
+
+ return ret;
+
+}
+
+
+
+/* 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.
+
+ On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable
+ definition of this macro might be
+ #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
+ MUST_PASS_IN_STACK (MODE, TYPE) */
+
+int
+frv_function_arg_pass_by_reference (cum, mode, type, named)
+ CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
+ enum machine_mode mode;
+ tree type;
+ int named ATTRIBUTE_UNUSED;
+{
+ return MUST_PASS_IN_STACK (mode, type);
+}
+
+/* If defined, 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. */
+
+int
+frv_function_arg_callee_copies (cum, mode, type, named)
+ CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ tree type ATTRIBUTE_UNUSED;
+ int named ATTRIBUTE_UNUSED;
+{
+ return 0;
+}
+
+/* If defined, a C expression that indicates when it is more desirable to keep
+ an argument passed by invisible reference as a reference, rather than
+ copying it to a pseudo register. */
+
+int
+frv_function_arg_keep_as_reference (cum, mode, type, named)
+ CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ tree type ATTRIBUTE_UNUSED;
+ int named ATTRIBUTE_UNUSED;
+{
+ return 0;
+}
+
+
+/* Return true if a register is ok to use as a base or index register. */
+
+static FRV_INLINE int
+frv_regno_ok_for_base_p (regno, strict_p)
+ int regno;
+ int strict_p;
+{
+ if (GPR_P (regno))
+ return TRUE;
+
+ if (strict_p)
+ return (reg_renumber[regno] >= 0 && GPR_P (reg_renumber[regno]));
+
+ if (regno == ARG_POINTER_REGNUM)
+ return TRUE;
+
+ return (regno >= FIRST_PSEUDO_REGISTER);
+}
+
+
+/* A C compound statement with a conditional `goto LABEL;' executed if X (an
+ RTX) is a legitimate memory address on the target machine for a memory
+ operand of mode MODE.
+
+ It usually pays to define several simpler macros to serve as subroutines for
+ this one. Otherwise it may be too complicated to understand.
+
+ This macro must exist in two variants: a strict variant and a non-strict
+ one. The strict variant is used in the reload pass. It must be defined so
+ that any pseudo-register that has not been allocated a hard register is
+ considered a memory reference. In contexts where some kind of register is
+ required, a pseudo-register with no hard register must be rejected.
+
+ The non-strict variant is used in other passes. It must be defined to
+ accept all pseudo-registers in every context where some kind of register is
+ required.
+
+ Compiler source files that want to use the strict variant of this macro
+ define the macro `REG_OK_STRICT'. You should use an `#ifdef REG_OK_STRICT'
+ conditional to define the strict variant in that case and the non-strict
+ variant otherwise.
+
+ Subroutines to check for acceptable registers for various purposes (one for
+ base registers, one for index registers, and so on) are typically among the
+ subroutines used to define `GO_IF_LEGITIMATE_ADDRESS'. Then only these
+ subroutine macros need have two variants; the higher levels of macros may be
+ the same whether strict or not.
+
+ Normally, constant addresses which are the sum of a `symbol_ref' and an
+ integer are stored inside a `const' RTX to mark them as constant.
+ Therefore, there is no need to recognize such sums specifically as
+ legitimate addresses. Normally you would simply recognize any `const' as
+ legitimate.
+
+ Usually `PRINT_OPERAND_ADDRESS' is not prepared to handle constant sums that
+ are not marked with `const'. It assumes that a naked `plus' indicates
+ indexing. If so, then you *must* reject such naked constant sums as
+ illegitimate addresses, so that none of them will be given to
+ `PRINT_OPERAND_ADDRESS'.
+
+ On some machines, whether a symbolic address is legitimate depends on the
+ section that the address refers to. On these machines, define the macro
+ `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and
+ then check for it here. When you see a `const', you will have to look
+ inside it to find the `symbol_ref' in order to determine the section.
+
+ The best way to modify the name string is by adding text to the beginning,
+ with suitable punctuation to prevent any ambiguity. Allocate the new name
+ in `saveable_obstack'. You will have to modify `ASM_OUTPUT_LABELREF' to
+ remove and decode the added text and output the name accordingly, and define
+ `(* targetm.strip_name_encoding)' to access the original name string.
+
+ You can check the information stored here into the `symbol_ref' in the
+ definitions of the macros `GO_IF_LEGITIMATE_ADDRESS' and
+ `PRINT_OPERAND_ADDRESS'. */
+
+int
+frv_legitimate_address_p (mode, x, strict_p, condexec_p)
+ enum machine_mode mode;
+ rtx x;
+ int strict_p;
+ int condexec_p;
+{
+ rtx x0, x1;
+ int ret = 0;
+ HOST_WIDE_INT value;
+ unsigned regno0;
+
+ switch (GET_CODE (x))
+ {
+ default:
+ break;
+
+ case SUBREG:
+ x = SUBREG_REG (x);
+ if (GET_CODE (x) != REG)
+ break;
+
+ /* fall through */
+
+ case REG:
+ ret = frv_regno_ok_for_base_p (REGNO (x), strict_p);
+ break;
+
+ case PRE_MODIFY:
+ x0 = XEXP (x, 0);
+ x1 = XEXP (x, 1);
+ if (GET_CODE (x0) != REG
+ || ! frv_regno_ok_for_base_p (REGNO (x0), strict_p)
+ || GET_CODE (x1) != PLUS
+ || ! rtx_equal_p (x0, XEXP (x1, 0))
+ || GET_CODE (XEXP (x1, 1)) != REG
+ || ! frv_regno_ok_for_base_p (REGNO (XEXP (x1, 1)), strict_p))
+ break;
+
+ ret = 1;
+ break;
+
+ case CONST_INT:
+ /* 12 bit immediate */
+ if (condexec_p)
+ ret = FALSE;
+ else
+ {
+ ret = IN_RANGE_P (INTVAL (x), -2048, 2047);
+
+ /* If we can't use load/store double operations, make sure we can
+ address the second word. */
+ if (ret && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+ ret = IN_RANGE_P (INTVAL (x) + GET_MODE_SIZE (mode) - 1,
+ -2048, 2047);
+ }
+ break;
+
+ case PLUS:
+ x0 = XEXP (x, 0);
+ x1 = XEXP (x, 1);
+
+ if (GET_CODE (x0) == SUBREG)
+ x0 = SUBREG_REG (x0);
+
+ if (GET_CODE (x0) != REG)
+ break;
+
+ regno0 = REGNO (x0);
+ if (!frv_regno_ok_for_base_p (regno0, strict_p))
+ break;
+
+ switch (GET_CODE (x1))
+ {
+ default:
+ break;
+
+ case SUBREG:
+ x1 = SUBREG_REG (x1);
+ if (GET_CODE (x1) != REG)
+ break;
+
+ /* fall through */
+
+ case REG:
+ /* Do not allow reg+reg addressing for modes > 1 word if we can't depend
+ on having move double instructions */
+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+ ret = FALSE;
+ else
+ ret = frv_regno_ok_for_base_p (REGNO (x1), strict_p);
+ break;
+
+ case CONST_INT:
+ /* 12 bit immediate */
+ if (condexec_p)
+ ret = FALSE;
+ else
+ {
+ value = INTVAL (x1);
+ ret = IN_RANGE_P (value, -2048, 2047);
+
+ /* If we can't use load/store double operations, make sure we can
+ address the second word. */
+ if (ret && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+ ret = IN_RANGE_P (value + GET_MODE_SIZE (mode) - 1, -2048, 2047);
+ }
+ break;
+
+ case SYMBOL_REF:
+ if (!condexec_p
+ && regno0 == SDA_BASE_REG
+ && symbol_ref_small_data_p (x1))
+ ret = TRUE;
+ break;
+
+ case CONST:
+ if (!condexec_p && regno0 == SDA_BASE_REG && const_small_data_p (x1))
+ ret = TRUE;
+ break;
+
+ }
+ break;
+ }
+
+ if (TARGET_DEBUG_ADDR)
+ {
+ fprintf (stderr, "\n========== GO_IF_LEGITIMATE_ADDRESS, mode = %s, result = %d, addresses are %sstrict%s\n",
+ GET_MODE_NAME (mode), ret, (strict_p) ? "" : "not ",
+ (condexec_p) ? ", inside conditional code" : "");
+ debug_rtx (x);
+ }
+
+ return ret;
+}
+
+
+/* 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 statement label
+ elsewhere in the code; the macro definition may use
+
+ GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN);
+
+ to avoid further processing if the address has become legitimate.
+
+ X will always be the result of a call to `break_out_memory_refs', and OLDX
+ will be the operand that was given to that function to produce X.
+
+ The code generated by this macro should not alter the substructure of X. If
+ it transforms X into a more legitimate form, it should assign X (which will
+ always be a C variable) a new value.
+
+ It is not necessary for this macro to come up with a legitimate address.
+ The compiler has standard ways of doing so in all cases. In fact, it is
+ safe for this macro to do nothing. But often a machine-dependent strategy
+ can generate better code. */
+
+rtx
+frv_legitimize_address (x, oldx, mode)
+ rtx x;
+ rtx oldx ATTRIBUTE_UNUSED;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ rtx ret = NULL_RTX;
+
+ /* Don't try to legitimize addresses if we are not optimizing, since the
+ address we generate is not a general operand, and will horribly mess
+ things up when force_reg is called to try and put it in a register because
+ we aren't optimizing. */
+ if (optimize
+ && ((GET_CODE (x) == SYMBOL_REF && symbol_ref_small_data_p (x))
+ || (GET_CODE (x) == CONST && const_small_data_p (x))))
+ {
+ ret = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, SDA_BASE_REG), x);
+ if (flag_pic)
+ cfun->uses_pic_offset_table = TRUE;
+ }
+
+ if (TARGET_DEBUG_ADDR && ret != NULL_RTX)
+ {
+ fprintf (stderr, "\n========== LEGITIMIZE_ADDRESS, mode = %s, modified address\n",
+ GET_MODE_NAME (mode));
+ debug_rtx (ret);
+ }
+
+ return ret;
+}
+
+/* Return 1 if operand is a valid FRV address. CONDEXEC_P is true if
+ the operand is used by a predicated instruction. */
+
+static int
+frv_legitimate_memory_operand (op, mode, condexec_p)
+ rtx op;
+ enum machine_mode mode;
+ int condexec_p;
+{
+ return ((GET_MODE (op) == mode || mode == VOIDmode)
+ && GET_CODE (op) == MEM
+ && frv_legitimate_address_p (mode, XEXP (op, 0),
+ reload_completed, condexec_p));
+}
+
+
+/* Return 1 is OP is a memory operand, or will be turned into one by
+ reload. */
+
+int frv_load_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (reload_in_progress)
+ {
+ rtx tmp = op;
+ if (GET_CODE (tmp) == SUBREG)
+ tmp = SUBREG_REG (tmp);
+ if (GET_CODE (tmp) == REG
+ && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
+ op = reg_equiv_memory_loc[REGNO (tmp)];
+ }
+
+ return op && memory_operand (op, mode);
+}
+
+
+/* Return 1 if operand is a GPR register or a FPR register. */
+
+int gpr_or_fpr_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ if (GPR_P (regno) || FPR_P (regno) || regno >= FIRST_PSEUDO_REGISTER)
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Return 1 if operand is a GPR register or 12 bit signed immediate. */
+
+int gpr_or_int12_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_CODE (op) == CONST_INT)
+ return IN_RANGE_P (INTVAL (op), -2048, 2047);
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ return GPR_OR_PSEUDO_P (REGNO (op));
+}
+
+/* Return 1 if operand is a GPR register, or a FPR register, or a 12 bit
+ signed immediate. */
+
+int gpr_fpr_or_int12_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_CODE (op) == CONST_INT)
+ return IN_RANGE_P (INTVAL (op), -2048, 2047);
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ if (GPR_P (regno) || FPR_P (regno) || regno >= FIRST_PSEUDO_REGISTER)
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Return 1 if operand is a register or 6 bit signed immediate. */
+
+int fpr_or_int6_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_CODE (op) == CONST_INT)
+ return IN_RANGE_P (INTVAL (op), -32, 31);
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ return FPR_OR_PSEUDO_P (REGNO (op));
+}
+
+/* Return 1 if operand is a register or 10 bit signed immediate. */
+
+int gpr_or_int10_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_CODE (op) == CONST_INT)
+ return IN_RANGE_P (INTVAL (op), -512, 511);
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ return GPR_OR_PSEUDO_P (REGNO (op));
+}
+
+/* Return 1 if operand is a register or an integer immediate. */
+
+int gpr_or_int_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_CODE (op) == CONST_INT)
+ return TRUE;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ return GPR_OR_PSEUDO_P (REGNO (op));
+}
+
+/* Return 1 if operand is a 12 bit signed immediate. */
+
+int int12_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ if (GET_CODE (op) != CONST_INT)
+ return FALSE;
+
+ return IN_RANGE_P (INTVAL (op), -2048, 2047);
+}
+
+/* Return 1 if operand is a 6 bit signed immediate. */
+
+int int6_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ if (GET_CODE (op) != CONST_INT)
+ return FALSE;
+
+ return IN_RANGE_P (INTVAL (op), -32, 31);
+}
+
+/* Return 1 if operand is a 5 bit signed immediate. */
+
+int int5_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return GET_CODE (op) == CONST_INT && IN_RANGE_P (INTVAL (op), -16, 15);
+}
+
+/* Return 1 if operand is a 5 bit unsigned immediate. */
+
+int uint5_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return GET_CODE (op) == CONST_INT && IN_RANGE_P (INTVAL (op), 0, 31);
+}
+
+/* Return 1 if operand is a 4 bit unsigned immediate. */
+
+int uint4_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return GET_CODE (op) == CONST_INT && IN_RANGE_P (INTVAL (op), 0, 15);
+}
+
+/* Return 1 if operand is a 1 bit unsigned immediate (0 or 1). */
+
+int uint1_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return GET_CODE (op) == CONST_INT && IN_RANGE_P (INTVAL (op), 0, 1);
+}
+
+/* Return 1 if operand is an integer constant that takes 2 instructions
+ to load up and can be split into sethi/setlo instructions.. */
+
+int int_2word_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ HOST_WIDE_INT value;
+ REAL_VALUE_TYPE rv;
+ long l;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ break;
+
+ case LABEL_REF:
+ return (flag_pic == 0);
+
+ case CONST:
+ /* small data references are already 1 word */
+ return (flag_pic == 0) && (! const_small_data_p (op));
+
+ case SYMBOL_REF:
+ /* small data references are already 1 word */
+ return (flag_pic == 0) && (! symbol_ref_small_data_p (op));
+
+ case CONST_INT:
+ return ! IN_RANGE_P (INTVAL (op), -32768, 32767);
+
+ case CONST_DOUBLE:
+ if (GET_MODE (op) == SFmode)
+ {
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
+ REAL_VALUE_TO_TARGET_SINGLE (rv, l);
+ value = l;
+ return ! IN_RANGE_P (value, -32768, 32767);
+ }
+ else if (GET_MODE (op) == VOIDmode)
+ {
+ value = CONST_DOUBLE_LOW (op);
+ return ! IN_RANGE_P (value, -32768, 32767);
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+/* Return 1 if operand is the pic address register. */
+int
+pic_register_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ if (! flag_pic)
+ return FALSE;
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ if (REGNO (op) != PIC_REGNO)
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Return 1 if operand is a symbolic reference when a PIC option is specified
+ that takes 3 seperate instructions to form. */
+
+int pic_symbolic_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ if (! flag_pic)
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ break;
+
+ case LABEL_REF:
+ return TRUE;
+
+ case SYMBOL_REF:
+ /* small data references are already 1 word */
+ return ! symbol_ref_small_data_p (op);
+
+ case CONST:
+ /* small data references are already 1 word */
+ return ! const_small_data_p (op);
+ }
+
+ return FALSE;
+}
+
+/* Return 1 if operand is the small data register. */
+int
+small_data_register_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ if (REGNO (op) != SDA_BASE_REG)
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Return 1 if operand is a symbolic reference to a small data area static or
+ global object. */
+
+int small_data_symbolic_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ switch (GET_CODE (op))
+ {
+ default:
+ break;
+
+ case CONST:
+ return const_small_data_p (op);
+
+ case SYMBOL_REF:
+ return symbol_ref_small_data_p (op);
+ }
+
+ return FALSE;
+}
+
+/* Return 1 if operand is a 16 bit unsigned immediate */
+
+int uint16_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ if (GET_CODE (op) != CONST_INT)
+ return FALSE;
+
+ return IN_RANGE_P (INTVAL (op), 0, 0xffff);
+}
+
+/* Return 1 if operand is an integer constant with the bottom 16 bits clear */
+
+int upper_int16_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ if (GET_CODE (op) != CONST_INT)
+ return FALSE;
+
+ return ((INTVAL (op) & 0xffff) == 0);
+}
+
+/* Return true if operand is a GPR register. */
+
+int
+integer_register_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ return GPR_OR_PSEUDO_P (REGNO (op));
+}
+
+/* Return true if operand is a GPR register. Do not allow SUBREG's
+ here, in order to prevent a combine bug. */
+
+int
+gpr_no_subreg_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ return GPR_OR_PSEUDO_P (REGNO (op));
+}
+
+/* Return true if operand is a FPR register. */
+
+int
+fpr_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ return FPR_OR_PSEUDO_P (REGNO (op));
+}
+
+/* Return true if operand is an even GPR or FPR register. */
+
+int
+even_reg_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return TRUE;
+
+ if (GPR_P (regno))
+ return (((regno - GPR_FIRST) & 1) == 0);
+
+ if (FPR_P (regno))
+ return (((regno - FPR_FIRST) & 1) == 0);
+
+ return FALSE;
+}
+
+/* Return true if operand is an odd GPR register. */
+
+int
+odd_reg_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ /* assume that reload will give us an even register */
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return FALSE;
+
+ if (GPR_P (regno))
+ return (((regno - GPR_FIRST) & 1) != 0);
+
+ if (FPR_P (regno))
+ return (((regno - FPR_FIRST) & 1) != 0);
+
+ return FALSE;
+}
+
+/* Return true if operand is an even GPR register. */
+
+int
+even_gpr_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return TRUE;
+
+ if (! GPR_P (regno))
+ return FALSE;
+
+ return (((regno - GPR_FIRST) & 1) == 0);
+}
+
+/* Return true if operand is an odd GPR register. */
+
+int
+odd_gpr_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ /* assume that reload will give us an even register */
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return FALSE;
+
+ if (! GPR_P (regno))
+ return FALSE;
+
+ return (((regno - GPR_FIRST) & 1) != 0);
+}
+
+/* Return true if operand is a quad aligned FPR register. */
+
+int
+quad_fpr_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return TRUE;
+
+ if (! FPR_P (regno))
+ return FALSE;
+
+ return (((regno - FPR_FIRST) & 3) == 0);
+}
+
+/* Return true if operand is an even FPR register. */
+
+int
+even_fpr_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return TRUE;
+
+ if (! FPR_P (regno))
+ return FALSE;
+
+ return (((regno - FPR_FIRST) & 1) == 0);
+}
+
+/* Return true if operand is an odd FPR register. */
+
+int
+odd_fpr_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ /* assume that reload will give us an even register */
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ return FALSE;
+
+ if (! FPR_P (regno))
+ return FALSE;
+
+ return (((regno - FPR_FIRST) & 1) != 0);
+}
+
+/* Return true if operand is a 2 word memory address that can be loaded in one
+ instruction to load or store. We assume the stack and frame pointers are
+ suitably aligned, and variables in the small data area. FIXME -- at some we
+ should recognize other globals and statics. We can't assume that any old
+ pointer is aligned, given that arguments could be passed on an odd word on
+ the stack and the address taken and passed through to another function. */
+
+int
+dbl_memory_one_insn_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ rtx addr;
+ rtx addr_reg;
+
+ if (! TARGET_DWORD)
+ return FALSE;
+
+ if (GET_CODE (op) != MEM)
+ return FALSE;
+
+ if (mode != VOIDmode && GET_MODE_SIZE (mode) != 2*UNITS_PER_WORD)
+ return FALSE;
+
+ addr = XEXP (op, 0);
+ if (GET_CODE (addr) == REG)
+ addr_reg = addr;
+
+ else if (GET_CODE (addr) == PLUS)
+ {
+ rtx addr0 = XEXP (addr, 0);
+ rtx addr1 = XEXP (addr, 1);
+
+ if (GET_CODE (addr0) != REG)
+ return FALSE;
+
+ if (plus_small_data_p (addr0, addr1))
+ return TRUE;
+
+ if (GET_CODE (addr1) != CONST_INT)
+ return FALSE;
+
+ if ((INTVAL (addr1) & 7) != 0)
+ return FALSE;
+
+ addr_reg = addr0;
+ }
+
+ else
+ return FALSE;
+
+ if (addr_reg == frame_pointer_rtx || addr_reg == stack_pointer_rtx)
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Return true if operand is a 2 word memory address that needs to
+ use two instructions to load or store. */
+
+int
+dbl_memory_two_insn_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_CODE (op) != MEM)
+ return FALSE;
+
+ if (mode != VOIDmode && GET_MODE_SIZE (mode) != 2*UNITS_PER_WORD)
+ return FALSE;
+
+ if (! TARGET_DWORD)
+ return TRUE;
+
+ return ! dbl_memory_one_insn_operand (op, mode);
+}
+
+/* Return true if operand is something that can be an output for a move
+ operation. */
+
+int
+move_destination_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ rtx subreg;
+ enum rtx_code code;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ break;
+
+ case SUBREG:
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ subreg = SUBREG_REG (op);
+ code = GET_CODE (subreg);
+ if (code == MEM)
+ return frv_legitimate_address_p (mode, XEXP (subreg, 0),
+ reload_completed, FALSE);
+
+ return (code == REG);
+
+ case REG:
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ return TRUE;
+
+ case MEM:
+ if (GET_CODE (XEXP (op, 0)) == ADDRESSOF)
+ return TRUE;
+
+ return frv_legitimate_memory_operand (op, mode, FALSE);
+ }
+
+ return FALSE;
+}
+
+/* Return true if operand is something that can be an input for a move
+ operation. */
+
+int
+move_source_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ rtx subreg;
+ enum rtx_code code;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ break;
+
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ case CONST:
+ return immediate_operand (op, mode);
+
+ case SUBREG:
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ subreg = SUBREG_REG (op);
+ code = GET_CODE (subreg);
+ if (code == MEM)
+ return frv_legitimate_address_p (mode, XEXP (subreg, 0),
+ reload_completed, FALSE);
+
+ return (code == REG);
+
+ case REG:
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ return TRUE;
+
+ case MEM:
+ if (GET_CODE (XEXP (op, 0)) == ADDRESSOF)
+ return TRUE;
+
+ return frv_legitimate_memory_operand (op, mode, FALSE);
+ }
+
+ return FALSE;
+}
+
+/* Return true if operand is something that can be an output for a conditional
+ move operation. */
+
+int
+condexec_dest_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ rtx subreg;
+ enum rtx_code code;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ break;
+
+ case SUBREG:
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ subreg = SUBREG_REG (op);
+ code = GET_CODE (subreg);
+ if (code == MEM)
+ return frv_legitimate_address_p (mode, XEXP (subreg, 0),
+ reload_completed, TRUE);
+
+ return (code == REG);
+
+ case REG:
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ return TRUE;
+
+ case MEM:
+ if (GET_CODE (XEXP (op, 0)) == ADDRESSOF)
+ return TRUE;
+
+ return frv_legitimate_memory_operand (op, mode, TRUE);
+ }
+
+ return FALSE;
+}
+
+/* Return true if operand is something that can be an input for a conditional
+ move operation. */
+
+int
+condexec_source_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ rtx subreg;
+ enum rtx_code code;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ break;
+
+ case CONST_INT:
+ case CONST_DOUBLE:
+ return ZERO_P (op);
+
+ case SUBREG:
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ subreg = SUBREG_REG (op);
+ code = GET_CODE (subreg);
+ if (code == MEM)
+ return frv_legitimate_address_p (mode, XEXP (subreg, 0),
+ reload_completed, TRUE);
+
+ return (code == REG);
+
+ case REG:
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ return TRUE;
+
+ case MEM:
+ if (GET_CODE (XEXP (op, 0)) == ADDRESSOF)
+ return TRUE;
+
+ return frv_legitimate_memory_operand (op, mode, TRUE);
+ }
+
+ return FALSE;
+}
+
+/* Return true if operand is a register of any flavor or a 0 of the
+ appropriate type. */
+
+int
+reg_or_0_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ switch (GET_CODE (op))
+ {
+ default:
+ break;
+
+ case REG:
+ case SUBREG:
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ return register_operand (op, mode);
+
+ case CONST_INT:
+ case CONST_DOUBLE:
+ return ZERO_P (op);
+ }
+
+ return FALSE;
+}
+
+/* Return true if operand is the link register */
+
+int
+lr_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (REGNO (op) != LR_REGNO && REGNO (op) < FIRST_PSEUDO_REGISTER)
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Return true if operand is a gpr register or a valid memory operation. */
+
+int
+gpr_or_memory_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (integer_register_operand (op, mode)
+ || frv_legitimate_memory_operand (op, mode, FALSE));
+}
+
+/* Return true if operand is a fpr register or a valid memory operation. */
+
+int
+fpr_or_memory_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (fpr_operand (op, mode)
+ || frv_legitimate_memory_operand (op, mode, FALSE));
+}
+
+/* Return true if operand is an icc register */
+
+int
+icc_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ return ICC_OR_PSEUDO_P (regno);
+}
+
+/* Return true if operand is an fcc register */
+
+int
+fcc_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ return FCC_OR_PSEUDO_P (regno);
+}
+
+/* Return true if operand is either an fcc or icc register */
+
+int
+cc_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ if (CC_OR_PSEUDO_P (regno))
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Return true if operand is an integer CCR register */
+
+int
+icr_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ return ICR_OR_PSEUDO_P (regno);
+}
+
+/* Return true if operand is an fcc register */
+
+int
+fcr_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ return FCR_OR_PSEUDO_P (regno);
+}
+
+/* Return true if operand is either an fcc or icc register */
+
+int
+cr_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ if (CR_OR_PSEUDO_P (regno))
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Return true if operand is a memory reference suitable for a call. */
+
+int
+call_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_MODE (op) != mode && mode != VOIDmode && GET_CODE (op) != CONST_INT)
+ return FALSE;
+
+ if (GET_CODE (op) == SYMBOL_REF)
+ return TRUE;
+
+ /* Note this doesn't allow reg+reg or reg+imm12 addressing (which should
+ never occur anyway), but prevents reload from not handling the case
+ properly of a call through a pointer on a function that calls
+ vfork/setjmp, etc. due to the need to flush all of the registers to stack. */
+ return gpr_or_int12_operand (op, mode);
+}
+
+/* Return true if operator is an kind of relational operator */
+
+int
+relational_operator (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ rtx op0;
+ rtx op1;
+ int regno;
+
+ if (mode != VOIDmode && mode != GET_MODE (op))
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ return FALSE;
+
+ case EQ:
+ case NE:
+ case LE:
+ case LT:
+ case GE:
+ case GT:
+ case LEU:
+ case LTU:
+ case GEU:
+ case GTU:
+ break;
+ }
+
+ op1 = XEXP (op, 1);
+ if (op1 != const0_rtx)
+ return FALSE;
+
+ op0 = XEXP (op, 0);
+ if (GET_CODE (op0) != REG)
+ return FALSE;
+
+ regno = REGNO (op0);
+ switch (GET_MODE (op0))
+ {
+ default:
+ break;
+
+ case CCmode:
+ case CC_UNSmode:
+ return ICC_OR_PSEUDO_P (regno);
+
+ case CC_FPmode:
+ return FCC_OR_PSEUDO_P (regno);
+
+ case CC_CCRmode:
+ return CR_OR_PSEUDO_P (regno);
+ }
+
+ return FALSE;
+}
+
+/* Return true if operator is a signed integer relational operator */
+
+int
+signed_relational_operator (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ rtx op0;
+ rtx op1;
+ int regno;
+
+ if (mode != VOIDmode && mode != GET_MODE (op))
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ return FALSE;
+
+ case EQ:
+ case NE:
+ case LE:
+ case LT:
+ case GE:
+ case GT:
+ break;
+ }
+
+ op1 = XEXP (op, 1);
+ if (op1 != const0_rtx)
+ return FALSE;
+
+ op0 = XEXP (op, 0);
+ if (GET_CODE (op0) != REG)
+ return FALSE;
+
+ regno = REGNO (op0);
+ if (GET_MODE (op0) == CCmode && ICC_OR_PSEUDO_P (regno))
+ return TRUE;
+
+ if (GET_MODE (op0) == CC_CCRmode && CR_OR_PSEUDO_P (regno))
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Return true if operator is a signed integer relational operator */
+
+int
+unsigned_relational_operator (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ rtx op0;
+ rtx op1;
+ int regno;
+
+ if (mode != VOIDmode && mode != GET_MODE (op))
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ return FALSE;
+
+ case LEU:
+ case LTU:
+ case GEU:
+ case GTU:
+ break;
+ }
+
+ op1 = XEXP (op, 1);
+ if (op1 != const0_rtx)
+ return FALSE;
+
+ op0 = XEXP (op, 0);
+ if (GET_CODE (op0) != REG)
+ return FALSE;
+
+ regno = REGNO (op0);
+ if (GET_MODE (op0) == CC_UNSmode && ICC_OR_PSEUDO_P (regno))
+ return TRUE;
+
+ if (GET_MODE (op0) == CC_CCRmode && CR_OR_PSEUDO_P (regno))
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Return true if operator is a floating point relational operator */
+
+int
+float_relational_operator (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ rtx op0;
+ rtx op1;
+ int regno;
+
+ if (mode != VOIDmode && mode != GET_MODE (op))
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ return FALSE;
+
+ case EQ: case NE:
+ case LE: case LT:
+ case GE: case GT:
+#if 0
+ case UEQ: case UNE:
+ case ULE: case ULT:
+ case UGE: case UGT:
+ case ORDERED:
+ case UNORDERED:
+#endif
+ break;
+ }
+
+ op1 = XEXP (op, 1);
+ if (op1 != const0_rtx)
+ return FALSE;
+
+ op0 = XEXP (op, 0);
+ if (GET_CODE (op0) != REG)
+ return FALSE;
+
+ regno = REGNO (op0);
+ if (GET_MODE (op0) == CC_FPmode && FCC_OR_PSEUDO_P (regno))
+ return TRUE;
+
+ if (GET_MODE (op0) == CC_CCRmode && CR_OR_PSEUDO_P (regno))
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Return true if operator is EQ/NE of a conditional execution register. */
+
+int
+ccr_eqne_operator (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ enum machine_mode op_mode = GET_MODE (op);
+ rtx op0;
+ rtx op1;
+ int regno;
+
+ if (mode != VOIDmode && op_mode != mode)
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ return FALSE;
+
+ case EQ:
+ case NE:
+ break;
+ }
+
+ op1 = XEXP (op, 1);
+ if (op1 != const0_rtx)
+ return FALSE;
+
+ op0 = XEXP (op, 0);
+ if (GET_CODE (op0) != REG)
+ return FALSE;
+
+ regno = REGNO (op0);
+ if (op_mode == CC_CCRmode && CR_OR_PSEUDO_P (regno))
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Return true if operator is a minimum or maximum operator (both signed and
+ unsigned). */
+
+int
+minmax_operator (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (mode != VOIDmode && mode != GET_MODE (op))
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ return FALSE;
+
+ case SMIN:
+ case SMAX:
+ case UMIN:
+ case UMAX:
+ break;
+ }
+
+ if (! integer_register_operand (XEXP (op, 0), mode))
+ return FALSE;
+
+ if (! gpr_or_int10_operand (XEXP (op, 1), mode))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Return true if operator is an integer binary operator that can executed
+ conditionally and takes 1 cycle. */
+
+int
+condexec_si_binary_operator (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ enum machine_mode op_mode = GET_MODE (op);
+
+ if (mode != VOIDmode && op_mode != mode)
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ return FALSE;
+
+ case PLUS:
+ case MINUS:
+ case AND:
+ case IOR:
+ case XOR:
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ return TRUE;
+ }
+}
+
+/* Return true if operator is an integer binary operator that can be
+ executed conditionally by a media instruction. */
+
+int
+condexec_si_media_operator (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ enum machine_mode op_mode = GET_MODE (op);
+
+ if (mode != VOIDmode && op_mode != mode)
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ return FALSE;
+
+ case AND:
+ case IOR:
+ case XOR:
+ return TRUE;
+ }
+}
+
+/* Return true if operator is an integer division operator that can executed
+ conditionally. */
+
+int
+condexec_si_divide_operator (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ enum machine_mode op_mode = GET_MODE (op);
+
+ if (mode != VOIDmode && op_mode != mode)
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ return FALSE;
+
+ case DIV:
+ case UDIV:
+ return TRUE;
+ }
+}
+
+/* Return true if operator is an integer unary operator that can executed
+ conditionally. */
+
+int
+condexec_si_unary_operator (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ enum machine_mode op_mode = GET_MODE (op);
+
+ if (mode != VOIDmode && op_mode != mode)
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ return FALSE;
+
+ case NEG:
+ case NOT:
+ return TRUE;
+ }
+}
+
+/* Return true if operator is a conversion-type expression that can be
+ evaluated conditionally by floating-point instructions. */
+
+int
+condexec_sf_conv_operator (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ enum machine_mode op_mode = GET_MODE (op);
+
+ if (mode != VOIDmode && op_mode != mode)
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ return FALSE;
+
+ case NEG:
+ case ABS:
+ return TRUE;
+ }
+}
+
+/* Return true if operator is an addition or subtraction expression.
+ Such expressions can be evaluated conditionally by floating-point
+ instructions. */
+
+int
+condexec_sf_add_operator (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ enum machine_mode op_mode = GET_MODE (op);
+
+ if (mode != VOIDmode && op_mode != mode)
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ return FALSE;
+
+ case PLUS:
+ case MINUS:
+ return TRUE;
+ }
+}
+
+/* Return true if the memory operand is one that can be conditionally
+ executed. */
+
+int
+condexec_memory_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ enum machine_mode op_mode = GET_MODE (op);
+ rtx addr;
+
+ if (mode != VOIDmode && op_mode != mode)
+ return FALSE;
+
+ switch (op_mode)
+ {
+ default:
+ return FALSE;
+
+ case QImode:
+ case HImode:
+ case SImode:
+ case SFmode:
+ break;
+ }
+
+ if (GET_CODE (op) != MEM)
+ return FALSE;
+
+ addr = XEXP (op, 0);
+ if (GET_CODE (addr) == ADDRESSOF)
+ return TRUE;
+
+ return frv_legitimate_address_p (mode, addr, reload_completed, TRUE);
+}
+
+/* Return true if operator is an integer binary operator that can be combined
+ with a setcc operation. Do not allow the arithmetic operations that could
+ potentially overflow since the FR-V sets the condition code based on the
+ "true" value of the result, not the result after truncating to a 32-bit
+ register. */
+
+int
+intop_compare_operator (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ enum machine_mode op_mode = GET_MODE (op);
+
+ if (mode != VOIDmode && op_mode != mode)
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ return FALSE;
+
+ case AND:
+ case IOR:
+ case XOR:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ break;
+ }
+
+ if (! integer_register_operand (XEXP (op, 0), SImode))
+ return FALSE;
+
+ if (! gpr_or_int10_operand (XEXP (op, 1), SImode))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Return true if operator is an integer binary operator that can be combined
+ with a setcc operation inside of a conditional execution. */
+
+int
+condexec_intop_cmp_operator (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ enum machine_mode op_mode = GET_MODE (op);
+
+ if (mode != VOIDmode && op_mode != mode)
+ return FALSE;
+
+ switch (GET_CODE (op))
+ {
+ default:
+ return FALSE;
+
+ case AND:
+ case IOR:
+ case XOR:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ break;
+ }
+
+ if (! integer_register_operand (XEXP (op, 0), SImode))
+ return FALSE;
+
+ if (! integer_register_operand (XEXP (op, 1), SImode))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Return 1 if operand is a valid ACC register number */
+
+int
+acc_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ return ACC_OR_PSEUDO_P (regno);
+}
+
+/* Return 1 if operand is a valid even ACC register number */
+
+int
+even_acc_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ return (ACC_OR_PSEUDO_P (regno) && ((regno - ACC_FIRST) & 1) == 0);
+}
+
+/* Return 1 if operand is zero or four */
+
+int
+quad_acc_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int regno;
+
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ regno = REGNO (op);
+ return (ACC_OR_PSEUDO_P (regno) && ((regno - ACC_FIRST) & 3) == 0);
+}
+
+/* Return 1 if operand is a valid ACCG register number */
+
+int
+accg_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return FALSE;
+
+ if (GET_CODE (op) == SUBREG)
+ {
+ if (GET_CODE (SUBREG_REG (op)) != REG)
+ return register_operand (op, mode);
+
+ op = SUBREG_REG (op);
+ }
+
+ if (GET_CODE (op) != REG)
+ return FALSE;
+
+ return ACCG_OR_PSEUDO_P (REGNO (op));
+}
+
+
+/* Return true if the bare return instruction can be used outside of the
+ epilog code. For frv, we only do it if there was no stack allocation. */
+
+int
+direct_return_p ()
+{
+ frv_stack_t *info;
+
+ if (!reload_completed)
+ return FALSE;
+
+ info = frv_stack_info ();
+ return (info->total_size == 0);
+}
+
+
+/* Emit code to handle a MOVSI, adding in the small data register or pic
+ register if needed to load up addresses. Return TRUE if the appropriate
+ instructions are emitted. */
+
+int
+frv_emit_movsi (dest, src)
+ rtx dest;
+ rtx src;
+{
+ int base_regno = -1;
+
+ if (!reload_in_progress
+ && !reload_completed
+ && !register_operand (dest, SImode)
+ && (!reg_or_0_operand (src, SImode)
+ /* Virtual registers will almost always be replaced by an
+ add instruction, so expose this to CSE by copying to
+ an intermediate register */
+ || (GET_CODE (src) == REG
+ && IN_RANGE_P (REGNO (src),
+ FIRST_VIRTUAL_REGISTER,
+ LAST_VIRTUAL_REGISTER))))
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, dest, copy_to_mode_reg (SImode, src)));
+ return TRUE;
+ }
+
+ /* Explicitly add in the PIC or small data register if needed. */
+ switch (GET_CODE (src))
+ {
+ default:
+ break;
+
+ case LABEL_REF:
+ if (flag_pic)
+ base_regno = PIC_REGNO;
+
+ break;
+
+ case CONST:
+ if (const_small_data_p (src))
+ base_regno = SDA_BASE_REG;
+
+ else if (flag_pic)
+ base_regno = PIC_REGNO;
+
+ break;
+
+ case SYMBOL_REF:
+ if (symbol_ref_small_data_p (src))
+ base_regno = SDA_BASE_REG;
+
+ else if (flag_pic)
+ base_regno = PIC_REGNO;
+
+ break;
+ }
+
+ if (base_regno >= 0)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, dest,
+ gen_rtx_PLUS (Pmode,
+ gen_rtx_REG (Pmode, base_regno),
+ src)));
+
+ if (base_regno == PIC_REGNO)
+ cfun->uses_pic_offset_table = TRUE;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/* Return a string to output a single word move. */
+
+const char *
+output_move_single (operands, insn)
+ rtx operands[];
+ rtx insn;
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+
+ if (GET_CODE (dest) == REG)
+ {
+ int dest_regno = REGNO (dest);
+ enum machine_mode mode = GET_MODE (dest);
+
+ if (GPR_P (dest_regno))
+ {
+ if (GET_CODE (src) == REG)
+ {
+ /* gpr <- some sort of register */
+ int src_regno = REGNO (src);
+
+ if (GPR_P (src_regno))
+ return "mov %1, %0";
+
+ else if (FPR_P (src_regno))
+ return "movfg %1, %0";
+
+ else if (SPR_P (src_regno))
+ return "movsg %1, %0";
+ }
+
+ else if (GET_CODE (src) == MEM)
+ {
+ /* gpr <- memory */
+ switch (mode)
+ {
+ default:
+ break;
+
+ case QImode:
+ return "ldsb%I1%U1 %M1,%0";
+
+ case HImode:
+ return "ldsh%I1%U1 %M1,%0";
+
+ case SImode:
+ case SFmode:
+ return "ld%I1%U1 %M1, %0";
+ }
+ }
+
+ else if (GET_CODE (src) == CONST_INT
+ || GET_CODE (src) == CONST_DOUBLE)
+ {
+ /* gpr <- integer/floating constant */
+ HOST_WIDE_INT value;
+
+ if (GET_CODE (src) == CONST_INT)
+ value = INTVAL (src);
+
+ else if (mode == SFmode)
+ {
+ REAL_VALUE_TYPE rv;
+ long l;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, src);
+ REAL_VALUE_TO_TARGET_SINGLE (rv, l);
+ value = l;
+ }
+
+ else
+ value = CONST_DOUBLE_LOW (src);
+
+ if (IN_RANGE_P (value, -32768, 32767))
+ return "setlos %1, %0";
+
+ return "#";
+ }
+
+ else if (GET_CODE (src) == SYMBOL_REF
+ || GET_CODE (src) == LABEL_REF
+ || GET_CODE (src) == CONST)
+ {
+ /* Silently fix up instances where the small data pointer is not
+ used in the address. */
+ if (small_data_symbolic_operand (src, GET_MODE (src)))
+ return "addi %@, #gprel12(%1), %0";
+
+ return "#";
+ }
+ }
+
+ else if (FPR_P (dest_regno))
+ {
+ if (GET_CODE (src) == REG)
+ {
+ /* fpr <- some sort of register */
+ int src_regno = REGNO (src);
+
+ if (GPR_P (src_regno))
+ return "movgf %1, %0";
+
+ else if (FPR_P (src_regno))
+ {
+ if (TARGET_HARD_FLOAT)
+ return "fmovs %1, %0";
+ else
+ return "mor %1, %1, %0";
+ }
+ }
+
+ else if (GET_CODE (src) == MEM)
+ {
+ /* fpr <- memory */
+ switch (mode)
+ {
+ default:
+ break;
+
+ case QImode:
+ return "ldbf%I1%U1 %M1,%0";
+
+ case HImode:
+ return "ldhf%I1%U1 %M1,%0";
+
+ case SImode:
+ case SFmode:
+ return "ldf%I1%U1 %M1, %0";
+ }
+ }
+
+ else if (ZERO_P (src))
+ return "movgf %., %0";
+ }
+
+ else if (SPR_P (dest_regno))
+ {
+ if (GET_CODE (src) == REG)
+ {
+ /* spr <- some sort of register */
+ int src_regno = REGNO (src);
+
+ if (GPR_P (src_regno))
+ return "movgs %1, %0";
+ }
+ }
+ }
+
+ else if (GET_CODE (dest) == MEM)
+ {
+ if (GET_CODE (src) == REG)
+ {
+ int src_regno = REGNO (src);
+ enum machine_mode mode = GET_MODE (dest);
+
+ if (GPR_P (src_regno))
+ {
+ switch (mode)
+ {
+ default:
+ break;
+
+ case QImode:
+ return "stb%I0%U0 %1, %M0";
+
+ case HImode:
+ return "sth%I0%U0 %1, %M0";
+
+ case SImode:
+ case SFmode:
+ return "st%I0%U0 %1, %M0";
+ }
+ }
+
+ else if (FPR_P (src_regno))
+ {
+ switch (mode)
+ {
+ default:
+ break;
+
+ case QImode:
+ return "stbf%I0%U0 %1, %M0";
+
+ case HImode:
+ return "sthf%I0%U0 %1, %M0";
+
+ case SImode:
+ case SFmode:
+ return "stf%I0%U0 %1, %M0";
+ }
+ }
+ }
+
+ else if (ZERO_P (src))
+ {
+ switch (GET_MODE (dest))
+ {
+ default:
+ break;
+
+ case QImode:
+ return "stb%I0%U0 %., %M0";
+
+ case HImode:
+ return "sth%I0%U0 %., %M0";
+
+ case SImode:
+ case SFmode:
+ return "st%I0%U0 %., %M0";
+ }
+ }
+ }
+
+ fatal_insn ("Bad output_move_single operand", insn);
+ return "";
+}
+
+
+/* Return a string to output a double word move. */
+
+const char *
+output_move_double (operands, insn)
+ rtx operands[];
+ rtx insn;
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ enum machine_mode mode = GET_MODE (dest);
+
+ if (GET_CODE (dest) == REG)
+ {
+ int dest_regno = REGNO (dest);
+
+ if (GPR_P (dest_regno))
+ {
+ if (GET_CODE (src) == REG)
+ {
+ /* gpr <- some sort of register */
+ int src_regno = REGNO (src);
+
+ if (GPR_P (src_regno))
+ return "#";
+
+ else if (FPR_P (src_regno))
+ {
+ if (((dest_regno - GPR_FIRST) & 1) == 0
+ && ((src_regno - FPR_FIRST) & 1) == 0)
+ return "movfgd %1, %0";
+
+ return "#";
+ }
+ }
+
+ else if (GET_CODE (src) == MEM)
+ {
+ /* gpr <- memory */
+ if (dbl_memory_one_insn_operand (src, mode))
+ return "ldd%I1%U1 %M1, %0";
+
+ return "#";
+ }
+
+ else if (GET_CODE (src) == CONST_INT
+ || GET_CODE (src) == CONST_DOUBLE)
+ return "#";
+ }
+
+ else if (FPR_P (dest_regno))
+ {
+ if (GET_CODE (src) == REG)
+ {
+ /* fpr <- some sort of register */
+ int src_regno = REGNO (src);
+
+ if (GPR_P (src_regno))
+ {
+ if (((dest_regno - FPR_FIRST) & 1) == 0
+ && ((src_regno - GPR_FIRST) & 1) == 0)
+ return "movgfd %1, %0";
+
+ return "#";
+ }
+
+ else if (FPR_P (src_regno))
+ {
+ if (TARGET_DOUBLE
+ && ((dest_regno - FPR_FIRST) & 1) == 0
+ && ((src_regno - FPR_FIRST) & 1) == 0)
+ return "fmovd %1, %0";
+
+ return "#";
+ }
+ }
+
+ else if (GET_CODE (src) == MEM)
+ {
+ /* fpr <- memory */
+ if (dbl_memory_one_insn_operand (src, mode))
+ return "lddf%I1%U1 %M1, %0";
+
+ return "#";
+ }
+
+ else if (ZERO_P (src))
+ return "#";
+ }
+ }
+
+ else if (GET_CODE (dest) == MEM)
+ {
+ if (GET_CODE (src) == REG)
+ {
+ int src_regno = REGNO (src);
+
+ if (GPR_P (src_regno))
+ {
+ if (((src_regno - GPR_FIRST) & 1) == 0
+ && dbl_memory_one_insn_operand (dest, mode))
+ return "std%I0%U0 %1, %M0";
+
+ return "#";
+ }
+
+ if (FPR_P (src_regno))
+ {
+ if (((src_regno - FPR_FIRST) & 1) == 0
+ && dbl_memory_one_insn_operand (dest, mode))
+ return "stdf%I0%U0 %1, %M0";
+
+ return "#";
+ }
+ }
+
+ else if (ZERO_P (src))
+ {
+ if (dbl_memory_one_insn_operand (dest, mode))
+ return "std%I0%U0 %., %M0";
+
+ return "#";
+ }
+ }
+
+ fatal_insn ("Bad output_move_double operand", insn);
+ return "";
+}
+
+
+/* Return a string to output a single word conditional move.
+ Operand0 -- EQ/NE of ccr register and 0
+ Operand1 -- CCR register
+ Operand2 -- destination
+ Operand3 -- source */
+
+const char *
+output_condmove_single (operands, insn)
+ rtx operands[];
+ rtx insn;
+{
+ rtx dest = operands[2];
+ rtx src = operands[3];
+
+ if (GET_CODE (dest) == REG)
+ {
+ int dest_regno = REGNO (dest);
+ enum machine_mode mode = GET_MODE (dest);
+
+ if (GPR_P (dest_regno))
+ {
+ if (GET_CODE (src) == REG)
+ {
+ /* gpr <- some sort of register */
+ int src_regno = REGNO (src);
+
+ if (GPR_P (src_regno))
+ return "cmov %z3, %2, %1, %e0";
+
+ else if (FPR_P (src_regno))
+ return "cmovfg %3, %2, %1, %e0";
+ }
+
+ else if (GET_CODE (src) == MEM)
+ {
+ /* gpr <- memory */
+ switch (mode)
+ {
+ default:
+ break;
+
+ case QImode:
+ return "cldsb%I3%U3 %M3, %2, %1, %e0";
+
+ case HImode:
+ return "cldsh%I3%U3 %M3, %2, %1, %e0";
+
+ case SImode:
+ case SFmode:
+ return "cld%I3%U3 %M3, %2, %1, %e0";
+ }
+ }
+
+ else if (ZERO_P (src))
+ return "cmov %., %2, %1, %e0";
+ }
+
+ else if (FPR_P (dest_regno))
+ {
+ if (GET_CODE (src) == REG)
+ {
+ /* fpr <- some sort of register */
+ int src_regno = REGNO (src);
+
+ if (GPR_P (src_regno))
+ return "cmovgf %3, %2, %1, %e0";
+
+ else if (FPR_P (src_regno))
+ {
+ if (TARGET_HARD_FLOAT)
+ return "cfmovs %3,%2,%1,%e0";
+ else
+ return "cmor %3, %3, %2, %1, %e0";
+ }
+ }
+
+ else if (GET_CODE (src) == MEM)
+ {
+ /* fpr <- memory */
+ if (mode == SImode || mode == SFmode)
+ return "cldf%I3%U3 %M3, %2, %1, %e0";
+ }
+
+ else if (ZERO_P (src))
+ return "cmovgf %., %2, %1, %e0";
+ }
+ }
+
+ else if (GET_CODE (dest) == MEM)
+ {
+ if (GET_CODE (src) == REG)
+ {
+ int src_regno = REGNO (src);
+ enum machine_mode mode = GET_MODE (dest);
+
+ if (GPR_P (src_regno))
+ {
+ switch (mode)
+ {
+ default:
+ break;
+
+ case QImode:
+ return "cstb%I2%U2 %3, %M2, %1, %e0";
+
+ case HImode:
+ return "csth%I2%U2 %3, %M2, %1, %e0";
+
+ case SImode:
+ case SFmode:
+ return "cst%I2%U2 %3, %M2, %1, %e0";
+ }
+ }
+
+ else if (FPR_P (src_regno) && (mode == SImode || mode == SFmode))
+ return "cstf%I2%U2 %3, %M2, %1, %e0";
+ }
+
+ else if (ZERO_P (src))
+ {
+ enum machine_mode mode = GET_MODE (dest);
+ switch (mode)
+ {
+ default:
+ break;
+
+ case QImode:
+ return "cstb%I2%U2 %., %M2, %1, %e0";
+
+ case HImode:
+ return "csth%I2%U2 %., %M2, %1, %e0";
+
+ case SImode:
+ case SFmode:
+ return "cst%I2%U2 %., %M2, %1, %e0";
+ }
+ }
+ }
+
+ fatal_insn ("Bad output_condmove_single operand", insn);
+ return "";
+}
+
+
+/* Emit the appropriate code to do a comparison, returning the register the
+ comparison was done it. */
+
+static rtx
+frv_emit_comparison (test, op0, op1)
+ enum rtx_code test;
+ rtx op0;
+ rtx op1;
+{
+ enum machine_mode cc_mode;
+ rtx cc_reg;
+
+ /* Floating point doesn't have comparison against a constant */
+ if (GET_MODE (op0) == CC_FPmode && GET_CODE (op1) != REG)
+ op1 = force_reg (GET_MODE (op0), op1);
+
+ /* Possibly disable using anything but a fixed register in order to work
+ around cse moving comparisons past function calls. */
+ cc_mode = SELECT_CC_MODE (test, op0, op1);
+ cc_reg = ((TARGET_ALLOC_CC)
+ ? gen_reg_rtx (cc_mode)
+ : gen_rtx_REG (cc_mode,
+ (cc_mode == CC_FPmode) ? FCC_FIRST : ICC_FIRST));
+
+ emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
+ gen_rtx_COMPARE (cc_mode, op0, op1)));
+
+ return cc_reg;
+}
+
+
+/* Emit code for a conditional branch. The comparison operands were previously
+ stored in frv_compare_op0 and frv_compare_op1.
+
+ XXX: I originally wanted to add a clobber of a CCR register to use in
+ conditional execution, but that confuses the rest of the compiler. */
+
+int
+frv_emit_cond_branch (test, label)
+ enum rtx_code test;
+ rtx label;
+{
+ rtx test_rtx;
+ rtx label_ref;
+ rtx if_else;
+ rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1);
+ enum machine_mode cc_mode = GET_MODE (cc_reg);
+
+ /* Branches generate:
+ (set (pc)
+ (if_then_else (<test>, <cc_reg>, (const_int 0))
+ (label_ref <branch_label>)
+ (pc))) */
+ label_ref = gen_rtx_LABEL_REF (VOIDmode, label);
+ test_rtx = gen_rtx (test, cc_mode, cc_reg, const0_rtx);
+ if_else = gen_rtx_IF_THEN_ELSE (cc_mode, test_rtx, label_ref, pc_rtx);
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_else));
+ return TRUE;
+}
+
+
+/* Emit code to set a gpr to 1/0 based on a comparison. The comparison
+ operands were previously stored in frv_compare_op0 and frv_compare_op1. */
+
+int
+frv_emit_scc (test, target)
+ enum rtx_code test;
+ rtx target;
+{
+ rtx set;
+ rtx test_rtx;
+ rtx clobber;
+ rtx cr_reg;
+ rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1);
+
+ /* SCC instructions generate:
+ (parallel [(set <target> (<test>, <cc_reg>, (const_int 0))
+ (clobber (<ccr_reg>))]) */
+ test_rtx = gen_rtx_fmt_ee (test, SImode, cc_reg, const0_rtx);
+ set = gen_rtx_SET (VOIDmode, target, test_rtx);
+
+ cr_reg = ((TARGET_ALLOC_CC)
+ ? gen_reg_rtx (CC_CCRmode)
+ : gen_rtx_REG (CC_CCRmode,
+ ((GET_MODE (cc_reg) == CC_FPmode)
+ ? FCR_FIRST
+ : ICR_FIRST)));
+
+ clobber = gen_rtx_CLOBBER (VOIDmode, cr_reg);
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber)));
+ return TRUE;
+}
+
+
+/* Split a SCC instruction into component parts, returning a SEQUENCE to hold
+ the seperate insns. */
+
+rtx
+frv_split_scc (dest, test, cc_reg, cr_reg, value)
+ rtx dest;
+ rtx test;
+ rtx cc_reg;
+ rtx cr_reg;
+ HOST_WIDE_INT value;
+{
+ rtx ret;
+
+ start_sequence ();
+
+ /* Set the appropriate CCR bit. */
+ emit_insn (gen_rtx_SET (VOIDmode,
+ cr_reg,
+ gen_rtx_fmt_ee (GET_CODE (test),
+ GET_MODE (cr_reg),
+ cc_reg,
+ const0_rtx)));
+
+ /* Move the value into the destination. */
+ emit_move_insn (dest, GEN_INT (value));
+
+ /* Move 0 into the destination if the test failed */
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_EQ (GET_MODE (cr_reg),
+ cr_reg,
+ const0_rtx),
+ gen_rtx_SET (VOIDmode, dest, const0_rtx)));
+
+ /* Finish up, return sequence. */
+ ret = get_insns ();
+ end_sequence ();
+ return ret;
+}
+
+
+/* Emit the code for a conditional move, return TRUE if we could do the
+ move. */
+
+int
+frv_emit_cond_move (dest, test_rtx, src1, src2)
+ rtx dest;
+ rtx test_rtx;
+ rtx src1;
+ rtx src2;
+{
+ rtx set;
+ rtx clobber_cc;
+ rtx test2;
+ rtx cr_reg;
+ rtx if_rtx;
+ enum rtx_code test = GET_CODE (test_rtx);
+ rtx cc_reg = frv_emit_comparison (test, frv_compare_op0, frv_compare_op1);
+ enum machine_mode cc_mode = GET_MODE (cc_reg);
+
+ /* Conditional move instructions generate:
+ (parallel [(set <target>
+ (if_then_else (<test> <cc_reg> (const_int 0))
+ <src1>
+ <src2>))
+ (clobber (<ccr_reg>))]) */
+
+ /* Handle various cases of conditional move involving two constants. */
+ if (GET_CODE (src1) == CONST_INT && GET_CODE (src2) == CONST_INT)
+ {
+ HOST_WIDE_INT value1 = INTVAL (src1);
+ HOST_WIDE_INT value2 = INTVAL (src2);
+
+ /* having 0 as one of the constants can be done by loading the other
+ constant, and optionally moving in gr0. */
+ if (value1 == 0 || value2 == 0)
+ ;
+
+ /* If the first value is within an addi range and also the difference
+ between the two fits in an addi's range, load up the difference, then
+ conditionally move in 0, and then unconditionally add the first
+ value. */
+ else if (IN_RANGE_P (value1, -2048, 2047)
+ && IN_RANGE_P (value2 - value1, -2048, 2047))
+ ;
+
+ /* If neither condition holds, just force the constant into a
+ register. */
+ else
+ {
+ src1 = force_reg (GET_MODE (dest), src1);
+ src2 = force_reg (GET_MODE (dest), src2);
+ }
+ }
+
+ /* If one value is a register, insure the other value is either 0 or a
+ register. */
+ else
+ {
+ if (GET_CODE (src1) == CONST_INT && INTVAL (src1) != 0)
+ src1 = force_reg (GET_MODE (dest), src1);
+
+ if (GET_CODE (src2) == CONST_INT && INTVAL (src2) != 0)
+ src2 = force_reg (GET_MODE (dest), src2);
+ }
+
+ test2 = gen_rtx_fmt_ee (test, cc_mode, cc_reg, const0_rtx);
+ if_rtx = gen_rtx_IF_THEN_ELSE (GET_MODE (dest), test2, src1, src2);
+
+ set = gen_rtx_SET (VOIDmode, dest, if_rtx);
+
+ cr_reg = ((TARGET_ALLOC_CC)
+ ? gen_reg_rtx (CC_CCRmode)
+ : gen_rtx_REG (CC_CCRmode,
+ (cc_mode == CC_FPmode) ? FCR_FIRST : ICR_FIRST));
+
+ clobber_cc = gen_rtx_CLOBBER (VOIDmode, cr_reg);
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber_cc)));
+ return TRUE;
+}
+
+
+/* Split a conditonal move into constituent parts, returning a SEQUENCE
+ containing all of the insns. */
+
+rtx
+frv_split_cond_move (operands)
+ rtx operands[];
+{
+ rtx dest = operands[0];
+ rtx test = operands[1];
+ rtx cc_reg = operands[2];
+ rtx src1 = operands[3];
+ rtx src2 = operands[4];
+ rtx cr_reg = operands[5];
+ rtx ret;
+ enum machine_mode cr_mode = GET_MODE (cr_reg);
+
+ start_sequence ();
+
+ /* Set the appropriate CCR bit. */
+ emit_insn (gen_rtx_SET (VOIDmode,
+ cr_reg,
+ gen_rtx_fmt_ee (GET_CODE (test),
+ GET_MODE (cr_reg),
+ cc_reg,
+ const0_rtx)));
+
+ /* Handle various cases of conditional move involving two constants. */
+ if (GET_CODE (src1) == CONST_INT && GET_CODE (src2) == CONST_INT)
+ {
+ HOST_WIDE_INT value1 = INTVAL (src1);
+ HOST_WIDE_INT value2 = INTVAL (src2);
+
+ /* having 0 as one of the constants can be done by loading the other
+ constant, and optionally moving in gr0. */
+ if (value1 == 0)
+ {
+ emit_move_insn (dest, src2);
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_NE (cr_mode, cr_reg,
+ const0_rtx),
+ gen_rtx_SET (VOIDmode, dest, src1)));
+ }
+
+ else if (value2 == 0)
+ {
+ emit_move_insn (dest, src1);
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_EQ (cr_mode, cr_reg,
+ const0_rtx),
+ gen_rtx_SET (VOIDmode, dest, src2)));
+ }
+
+ /* If the first value is within an addi range and also the difference
+ between the two fits in an addi's range, load up the difference, then
+ conditionally move in 0, and then unconditionally add the first
+ value. */
+ else if (IN_RANGE_P (value1, -2048, 2047)
+ && IN_RANGE_P (value2 - value1, -2048, 2047))
+ {
+ rtx dest_si = ((GET_MODE (dest) == SImode)
+ ? dest
+ : gen_rtx_SUBREG (SImode, dest, 0));
+
+ emit_move_insn (dest_si, GEN_INT (value2 - value1));
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_NE (cr_mode, cr_reg,
+ const0_rtx),
+ gen_rtx_SET (VOIDmode, dest_si,
+ const0_rtx)));
+ emit_insn (gen_addsi3 (dest_si, dest_si, src1));
+ }
+
+ else
+ abort ();
+ }
+ else
+ {
+ /* Emit the conditional move for the test being true if needed. */
+ if (! rtx_equal_p (dest, src1))
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_NE (cr_mode, cr_reg, const0_rtx),
+ gen_rtx_SET (VOIDmode, dest, src1)));
+
+ /* Emit the conditional move for the test being false if needed. */
+ if (! rtx_equal_p (dest, src2))
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_EQ (cr_mode, cr_reg, const0_rtx),
+ gen_rtx_SET (VOIDmode, dest, src2)));
+ }
+
+ /* Finish up, return sequence. */
+ ret = get_insns ();
+ end_sequence ();
+ return ret;
+}
+
+
+/* Split (set DEST SOURCE), where DEST is a double register and SOURCE is a
+ memory location that is not known to be dword-aligned. */
+void
+frv_split_double_load (dest, source)
+ rtx dest;
+ rtx source;
+{
+ int regno = REGNO (dest);
+ rtx dest1 = gen_highpart (SImode, dest);
+ rtx dest2 = gen_lowpart (SImode, dest);
+ rtx address = XEXP (source, 0);
+
+ /* If the address is pre-modified, load the lower-numbered register
+ first, then load the other register using an integer offset from
+ the modified base register. This order should always be safe,
+ since the pre-modification cannot affect the same registers as the
+ load does.
+
+ The situation for other loads is more complicated. Loading one
+ of the registers could affect the value of ADDRESS, so we must
+ be careful which order we do them in. */
+ if (GET_CODE (address) == PRE_MODIFY
+ || ! refers_to_regno_p (regno, regno + 1, address, NULL))
+ {
+ /* It is safe to load the lower-numbered register first. */
+ emit_move_insn (dest1, change_address (source, SImode, NULL));
+ emit_move_insn (dest2, frv_index_memory (source, SImode, 1));
+ }
+ else
+ {
+ /* ADDRESS is not pre-modified and the address depends on the
+ lower-numbered register. Load the higher-numbered register
+ first. */
+ emit_move_insn (dest2, frv_index_memory (source, SImode, 1));
+ emit_move_insn (dest1, change_address (source, SImode, NULL));
+ }
+}
+
+/* Split (set DEST SOURCE), where DEST refers to a dword memory location
+ and SOURCE is either a double register or the constant zero. */
+void
+frv_split_double_store (dest, source)
+ rtx dest;
+ rtx source;
+{
+ rtx dest1 = change_address (dest, SImode, NULL);
+ rtx dest2 = frv_index_memory (dest, SImode, 1);
+ if (ZERO_P (source))
+ {
+ emit_move_insn (dest1, CONST0_RTX (SImode));
+ emit_move_insn (dest2, CONST0_RTX (SImode));
+ }
+ else
+ {
+ emit_move_insn (dest1, gen_highpart (SImode, source));
+ emit_move_insn (dest2, gen_lowpart (SImode, source));
+ }
+}
+
+
+/* Split a min/max operation returning a SEQUENCE containing all of the
+ insns. */
+
+rtx
+frv_split_minmax (operands)
+ rtx operands[];
+{
+ rtx dest = operands[0];
+ rtx minmax = operands[1];
+ rtx src1 = operands[2];
+ rtx src2 = operands[3];
+ rtx cc_reg = operands[4];
+ rtx cr_reg = operands[5];
+ rtx ret;
+ enum rtx_code test_code;
+ enum machine_mode cr_mode = GET_MODE (cr_reg);
+
+ start_sequence ();
+
+ /* Figure out which test to use */
+ switch (GET_CODE (minmax))
+ {
+ default:
+ abort ();
+
+ case SMIN: test_code = LT; break;
+ case SMAX: test_code = GT; break;
+ case UMIN: test_code = LTU; break;
+ case UMAX: test_code = GTU; break;
+ }
+
+ /* Issue the compare instruction. */
+ emit_insn (gen_rtx_SET (VOIDmode,
+ cc_reg,
+ gen_rtx_COMPARE (GET_MODE (cc_reg),
+ src1, src2)));
+
+ /* Set the appropriate CCR bit. */
+ emit_insn (gen_rtx_SET (VOIDmode,
+ cr_reg,
+ gen_rtx_fmt_ee (test_code,
+ GET_MODE (cr_reg),
+ cc_reg,
+ const0_rtx)));
+
+ /* If are taking the min/max of a nonzero constant, load that first, and
+ then do a conditional move of the other value. */
+ if (GET_CODE (src2) == CONST_INT && INTVAL (src2) != 0)
+ {
+ if (rtx_equal_p (dest, src1))
+ abort ();
+
+ emit_move_insn (dest, src2);
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_NE (cr_mode, cr_reg, const0_rtx),
+ gen_rtx_SET (VOIDmode, dest, src1)));
+ }
+
+ /* Otherwise, do each half of the move. */
+ else
+ {
+ /* Emit the conditional move for the test being true if needed. */
+ if (! rtx_equal_p (dest, src1))
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_NE (cr_mode, cr_reg, const0_rtx),
+ gen_rtx_SET (VOIDmode, dest, src1)));
+
+ /* Emit the conditional move for the test being false if needed. */
+ if (! rtx_equal_p (dest, src2))
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_EQ (cr_mode, cr_reg, const0_rtx),
+ gen_rtx_SET (VOIDmode, dest, src2)));
+ }
+
+ /* Finish up, return sequence. */
+ ret = get_insns ();
+ end_sequence ();
+ return ret;
+}
+
+
+/* Split an integer abs operation returning a SEQUENCE containing all of the
+ insns. */
+
+rtx
+frv_split_abs (operands)
+ rtx operands[];
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx cc_reg = operands[2];
+ rtx cr_reg = operands[3];
+ rtx ret;
+
+ start_sequence ();
+
+ /* Issue the compare < 0 instruction. */
+ emit_insn (gen_rtx_SET (VOIDmode,
+ cc_reg,
+ gen_rtx_COMPARE (CCmode, src, const0_rtx)));
+
+ /* Set the appropriate CCR bit. */
+ emit_insn (gen_rtx_SET (VOIDmode,
+ cr_reg,
+ gen_rtx_fmt_ee (LT, CC_CCRmode, cc_reg, const0_rtx)));
+
+ /* Emit the conditional negate if the value is negative */
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_NE (CC_CCRmode, cr_reg, const0_rtx),
+ gen_negsi2 (dest, src)));
+
+ /* Emit the conditional move for the test being false if needed. */
+ if (! rtx_equal_p (dest, src))
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_EQ (CC_CCRmode, cr_reg, const0_rtx),
+ gen_rtx_SET (VOIDmode, dest, src)));
+
+ /* Finish up, return sequence. */
+ ret = get_insns ();
+ end_sequence ();
+ return ret;
+}
+
+
+/* An internal function called by for_each_rtx to clear in a hard_reg set each
+ register used in an insn. */
+
+static int
+frv_clear_registers_used (ptr, data)
+ rtx *ptr;
+ void *data;
+{
+ if (GET_CODE (*ptr) == REG)
+ {
+ int regno = REGNO (*ptr);
+ HARD_REG_SET *p_regs = (HARD_REG_SET *)data;
+
+ if (regno < FIRST_PSEUDO_REGISTER)
+ {
+ int reg_max = regno + HARD_REGNO_NREGS (regno, GET_MODE (*ptr));
+
+ while (regno < reg_max)
+ {
+ CLEAR_HARD_REG_BIT (*p_regs, regno);
+ regno++;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+/* Initialize the extra fields provided by IFCVT_EXTRA_FIELDS. */
+
+/* On the FR-V, we don't have any extra fields per se, but it is useful hook to
+ initialize the static storage. */
+void
+frv_ifcvt_init_extra_fields (ce_info)
+ ce_if_block_t *ce_info ATTRIBUTE_UNUSED;
+{
+ frv_ifcvt.added_insns_list = NULL_RTX;
+ frv_ifcvt.cur_scratch_regs = 0;
+ frv_ifcvt.num_nested_cond_exec = 0;
+ frv_ifcvt.cr_reg = NULL_RTX;
+ frv_ifcvt.nested_cc_reg = NULL_RTX;
+ frv_ifcvt.extra_int_cr = NULL_RTX;
+ frv_ifcvt.extra_fp_cr = NULL_RTX;
+ frv_ifcvt.last_nested_if_cr = NULL_RTX;
+}
+
+
+/* Internal function to add a potenial insn to the list of insns to be inserted
+ if the conditional execution conversion is successful. */
+
+static void
+frv_ifcvt_add_insn (pattern, insn, before_p)
+ rtx pattern;
+ rtx insn;
+ int before_p;
+{
+ rtx link = alloc_EXPR_LIST (VOIDmode, pattern, insn);
+
+ link->jump = before_p; /* mark to add this before or after insn */
+ frv_ifcvt.added_insns_list = alloc_EXPR_LIST (VOIDmode, link,
+ frv_ifcvt.added_insns_list);
+
+ if (TARGET_DEBUG_COND_EXEC)
+ {
+ fprintf (stderr,
+ "\n:::::::::: frv_ifcvt_add_insn: add the following %s insn %d:\n",
+ (before_p) ? "before" : "after",
+ (int)INSN_UID (insn));
+
+ debug_rtx (pattern);
+ }
+}
+
+
+/* A C expression to modify the code described by the conditional if
+ information CE_INFO, possibly updating the tests in TRUE_EXPR, and
+ FALSE_EXPR for converting if-then and if-then-else code to conditional
+ instructions. Set either TRUE_EXPR or FALSE_EXPR to a null pointer if the
+ tests cannot be converted. */
+
+void
+frv_ifcvt_modify_tests (ce_info, p_true, p_false)
+ ce_if_block_t *ce_info;
+ rtx *p_true;
+ rtx *p_false;
+{
+ basic_block test_bb = ce_info->test_bb; /* test basic block */
+ basic_block then_bb = ce_info->then_bb; /* THEN */
+ basic_block else_bb = ce_info->else_bb; /* ELSE or NULL */
+ basic_block join_bb = ce_info->join_bb; /* join block or NULL */
+ rtx true_expr = *p_true;
+ rtx cr;
+ rtx cc;
+ rtx nested_cc;
+ enum machine_mode mode = GET_MODE (true_expr);
+ int j;
+ basic_block *bb;
+ int num_bb;
+ frv_tmp_reg_t *tmp_reg = &frv_ifcvt.tmp_reg;
+ rtx check_insn;
+ rtx sub_cond_exec_reg;
+ enum rtx_code code;
+ enum rtx_code code_true;
+ enum rtx_code code_false;
+ enum reg_class cc_class;
+ enum reg_class cr_class;
+ int cc_first;
+ int cc_last;
+
+ /* Make sure we are only dealing with hard registers. Also honor the
+ -mno-cond-exec switch, and -mno-nested-cond-exec switches if
+ applicable. */
+ if (!reload_completed || TARGET_NO_COND_EXEC
+ || (TARGET_NO_NESTED_CE && ce_info->pass > 1))
+ goto fail;
+
+ /* Figure out which registers we can allocate for our own purposes. Only
+ consider registers that are not preserved across function calls and are
+ not fixed. However, allow the ICC/ICR temporary registers to be allocated
+ if we did not need to use them in reloading other registers. */
+ memset ((PTR) &tmp_reg->regs, 0, sizeof (tmp_reg->regs));
+ COPY_HARD_REG_SET (tmp_reg->regs, call_used_reg_set);
+ AND_COMPL_HARD_REG_SET (tmp_reg->regs, fixed_reg_set);
+ SET_HARD_REG_BIT (tmp_reg->regs, ICC_TEMP);
+ SET_HARD_REG_BIT (tmp_reg->regs, ICR_TEMP);
+
+ /* If this is a nested IF, we need to discover whether the CC registers that
+ are set/used inside of the block are used anywhere else. If not, we can
+ change them to be the CC register that is paired with the CR register that
+ controls the outermost IF block. */
+ if (ce_info->pass > 1)
+ {
+ CLEAR_HARD_REG_SET (frv_ifcvt.nested_cc_ok_rewrite);
+ for (j = CC_FIRST; j <= CC_LAST; j++)
+ if (TEST_HARD_REG_BIT (tmp_reg->regs, j))
+ {
+ if (REGNO_REG_SET_P (then_bb->global_live_at_start, j))
+ continue;
+
+ if (else_bb && REGNO_REG_SET_P (else_bb->global_live_at_start, j))
+ continue;
+
+ if (join_bb && REGNO_REG_SET_P (join_bb->global_live_at_start, j))
+ continue;
+
+ SET_HARD_REG_BIT (frv_ifcvt.nested_cc_ok_rewrite, j);
+ }
+ }
+
+ for (j = 0; j < frv_ifcvt.cur_scratch_regs; j++)
+ frv_ifcvt.scratch_regs[j] = NULL_RTX;
+
+ frv_ifcvt.added_insns_list = NULL_RTX;
+ frv_ifcvt.cur_scratch_regs = 0;
+
+ bb = (basic_block *) alloca ((2 + ce_info->num_multiple_test_blocks)
+ * sizeof (basic_block));
+
+ if (join_bb)
+ {
+ int regno;
+
+ /* Remove anything live at the beginning of the join block from being
+ available for allocation. */
+ EXECUTE_IF_SET_IN_REG_SET (join_bb->global_live_at_start, 0, regno,
+ {
+ if (regno < FIRST_PSEUDO_REGISTER)
+ CLEAR_HARD_REG_BIT (tmp_reg->regs, regno);
+ });
+ }
+
+ /* Add in all of the blocks in multiple &&/|| blocks to be scanned. */
+ num_bb = 0;
+ if (ce_info->num_multiple_test_blocks)
+ {
+ basic_block multiple_test_bb = ce_info->last_test_bb;
+
+ while (multiple_test_bb != test_bb)
+ {
+ bb[num_bb++] = multiple_test_bb;
+ multiple_test_bb = multiple_test_bb->pred->src;
+ }
+ }
+
+ /* Add in the THEN and ELSE blocks to be scanned. */
+ bb[num_bb++] = then_bb;
+ if (else_bb)
+ bb[num_bb++] = else_bb;
+
+ sub_cond_exec_reg = NULL_RTX;
+ frv_ifcvt.num_nested_cond_exec = 0;
+
+ /* Scan all of the blocks for registers that must not be allocated. */
+ for (j = 0; j < num_bb; j++)
+ {
+ rtx last_insn = bb[j]->end;
+ rtx insn = bb[j]->head;
+ int regno;
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Scanning %s block %d, start %d, end %d\n",
+ (bb[j] == else_bb) ? "else" : ((bb[j] == then_bb) ? "then" : "test"),
+ (int) bb[j]->index,
+ (int) INSN_UID (bb[j]->head),
+ (int) INSN_UID (bb[j]->end));
+
+ /* Anything live at the beginning of the block is obviously unavailable
+ for allocation. */
+ EXECUTE_IF_SET_IN_REG_SET (bb[j]->global_live_at_start, 0, regno,
+ {
+ if (regno < FIRST_PSEUDO_REGISTER)
+ CLEAR_HARD_REG_BIT (tmp_reg->regs, regno);
+ });
+
+ /* loop through the insns in the block. */
+ for (;;)
+ {
+ /* Mark any new registers that are created as being unavailable for
+ allocation. Also see if the CC register used in nested IFs can be
+ reallocated. */
+ if (INSN_P (insn))
+ {
+ rtx pattern;
+ rtx set;
+ int skip_nested_if = FALSE;
+
+ for_each_rtx (&PATTERN (insn), frv_clear_registers_used,
+ (void *)&tmp_reg->regs);
+
+ pattern = PATTERN (insn);
+ if (GET_CODE (pattern) == COND_EXEC)
+ {
+ rtx reg = XEXP (COND_EXEC_TEST (pattern), 0);
+
+ if (reg != sub_cond_exec_reg)
+ {
+ sub_cond_exec_reg = reg;
+ frv_ifcvt.num_nested_cond_exec++;
+ }
+ }
+
+ set = single_set_pattern (pattern);
+ if (set)
+ {
+ rtx dest = SET_DEST (set);
+ rtx src = SET_SRC (set);
+
+ if (GET_CODE (dest) == REG)
+ {
+ int regno = REGNO (dest);
+ enum rtx_code src_code = GET_CODE (src);
+
+ if (CC_P (regno) && src_code == COMPARE)
+ skip_nested_if = TRUE;
+
+ else if (CR_P (regno)
+ && (src_code == IF_THEN_ELSE
+ || GET_RTX_CLASS (src_code) == '<'))
+ skip_nested_if = TRUE;
+ }
+ }
+
+ if (! skip_nested_if)
+ for_each_rtx (&PATTERN (insn), frv_clear_registers_used,
+ (void *)&frv_ifcvt.nested_cc_ok_rewrite);
+ }
+
+ if (insn == last_insn)
+ break;
+
+ insn = NEXT_INSN (insn);
+ }
+ }
+
+ /* If this is a nested if, rewrite the CC registers that are available to
+ include the ones that can be rewritten, to increase the chance of being
+ able to allocate a paired CC/CR register combination. */
+ if (ce_info->pass > 1)
+ {
+ for (j = CC_FIRST; j <= CC_LAST; j++)
+ if (TEST_HARD_REG_BIT (frv_ifcvt.nested_cc_ok_rewrite, j))
+ SET_HARD_REG_BIT (tmp_reg->regs, j);
+ else
+ CLEAR_HARD_REG_BIT (tmp_reg->regs, j);
+ }
+
+ if (rtl_dump_file)
+ {
+ int num_gprs = 0;
+ fprintf (rtl_dump_file, "Available GPRs: ");
+
+ for (j = GPR_FIRST; j <= GPR_LAST; j++)
+ if (TEST_HARD_REG_BIT (tmp_reg->regs, j))
+ {
+ fprintf (rtl_dump_file, " %d [%s]", j, reg_names[j]);
+ if (++num_gprs > GPR_TEMP_NUM+2)
+ break;
+ }
+
+ fprintf (rtl_dump_file, "%s\nAvailable CRs: ",
+ (num_gprs > GPR_TEMP_NUM+2) ? " ..." : "");
+
+ for (j = CR_FIRST; j <= CR_LAST; j++)
+ if (TEST_HARD_REG_BIT (tmp_reg->regs, j))
+ fprintf (rtl_dump_file, " %d [%s]", j, reg_names[j]);
+
+ fputs ("\n", rtl_dump_file);
+
+ if (ce_info->pass > 1)
+ {
+ fprintf (rtl_dump_file, "Modifiable CCs: ");
+ for (j = CC_FIRST; j <= CC_LAST; j++)
+ if (TEST_HARD_REG_BIT (tmp_reg->regs, j))
+ fprintf (rtl_dump_file, " %d [%s]", j, reg_names[j]);
+
+ fprintf (rtl_dump_file, "\n%d nested COND_EXEC statements\n",
+ frv_ifcvt.num_nested_cond_exec);
+ }
+ }
+
+ /* Allocate the appropriate temporary condition code register. Try to
+ allocate the ICR/FCR register that corresponds to the ICC/FCC register so
+ that conditional cmp's can be done. */
+ if (mode == CCmode || mode == CC_UNSmode)
+ {
+ cr_class = ICR_REGS;
+ cc_class = ICC_REGS;
+ cc_first = ICC_FIRST;
+ cc_last = ICC_LAST;
+ }
+ else if (mode == CC_FPmode)
+ {
+ cr_class = FCR_REGS;
+ cc_class = FCC_REGS;
+ cc_first = FCC_FIRST;
+ cc_last = FCC_LAST;
+ }
+ else
+ {
+ cc_first = cc_last = 0;
+ cr_class = cc_class = NO_REGS;
+ }
+
+ cc = XEXP (true_expr, 0);
+ nested_cc = cr = NULL_RTX;
+ if (cc_class != NO_REGS)
+ {
+ /* For nested IFs and &&/||, see if we can find a CC and CR register pair
+ so we can execute a csubcc/caddcc/cfcmps instruction. */
+ int cc_regno;
+
+ for (cc_regno = cc_first; cc_regno <= cc_last; cc_regno++)
+ {
+ int cr_regno = cc_regno - CC_FIRST + CR_FIRST;
+
+ if (TEST_HARD_REG_BIT (frv_ifcvt.tmp_reg.regs, cc_regno)
+ && TEST_HARD_REG_BIT (frv_ifcvt.tmp_reg.regs, cr_regno))
+ {
+ frv_ifcvt.tmp_reg.next_reg[ (int)cr_class ] = cr_regno;
+ cr = frv_alloc_temp_reg (tmp_reg, cr_class, CC_CCRmode, TRUE,
+ TRUE);
+
+ frv_ifcvt.tmp_reg.next_reg[ (int)cc_class ] = cc_regno;
+ nested_cc = frv_alloc_temp_reg (tmp_reg, cc_class, CCmode,
+ TRUE, TRUE);
+ break;
+ }
+ }
+ }
+
+ if (! cr)
+ {
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Could not allocate a CR temporary register\n");
+
+ goto fail;
+ }
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file,
+ "Will use %s for conditional execution, %s for nested comparisons\n",
+ reg_names[ REGNO (cr)],
+ (nested_cc) ? reg_names[ REGNO (nested_cc) ] : "<none>");
+
+ /* Set the CCR bit. Note for integer tests, we reverse the condition so that
+ in an IF-THEN-ELSE sequence, we are testing the TRUE case against the CCR
+ bit being true. We don't do this for floating point, because of NaNs. */
+ code = GET_CODE (true_expr);
+ if (GET_MODE (cc) != CC_FPmode)
+ {
+ code = reverse_condition (code);
+ code_true = EQ;
+ code_false = NE;
+ }
+ else
+ {
+ code_true = NE;
+ code_false = EQ;
+ }
+
+ check_insn = gen_rtx_SET (VOIDmode, cr,
+ gen_rtx_fmt_ee (code, CC_CCRmode, cc, const0_rtx));
+
+ /* Record the check insn to be inserted later. */
+ frv_ifcvt_add_insn (check_insn, test_bb->end, TRUE);
+
+ /* Update the tests. */
+ frv_ifcvt.cr_reg = cr;
+ frv_ifcvt.nested_cc_reg = nested_cc;
+ *p_true = gen_rtx_fmt_ee (code_true, CC_CCRmode, cr, const0_rtx);
+ *p_false = gen_rtx_fmt_ee (code_false, CC_CCRmode, cr, const0_rtx);
+ return;
+
+ /* Fail, don't do this conditional execution. */
+ fail:
+ *p_true = NULL_RTX;
+ *p_false = NULL_RTX;
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Disabling this conditional execution.\n");
+
+ return;
+}
+
+
+/* A C expression to modify the code described by the conditional if
+ information CE_INFO, for the basic block BB, possibly updating the tests in
+ TRUE_EXPR, and FALSE_EXPR for converting the && and || parts of if-then or
+ if-then-else code to conditional instructions. Set either TRUE_EXPR or
+ FALSE_EXPR to a null pointer if the tests cannot be converted. */
+
+/* p_true and p_false are given expressions of the form:
+
+ (and (eq:CC_CCR (reg:CC_CCR)
+ (const_int 0))
+ (eq:CC (reg:CC)
+ (const_int 0))) */
+
+void
+frv_ifcvt_modify_multiple_tests (ce_info, bb, p_true, p_false)
+ ce_if_block_t *ce_info;
+ basic_block bb;
+ rtx *p_true;
+ rtx *p_false;
+{
+ rtx old_true = XEXP (*p_true, 0);
+ rtx old_false = XEXP (*p_false, 0);
+ rtx true_expr = XEXP (*p_true, 1);
+ rtx false_expr = XEXP (*p_false, 1);
+ rtx test_expr;
+ rtx old_test;
+ rtx cr = XEXP (old_true, 0);
+ rtx check_insn;
+ rtx new_cr = NULL_RTX;
+ rtx *p_new_cr = (rtx *)0;
+ rtx if_else;
+ rtx compare;
+ rtx cc;
+ enum reg_class cr_class;
+ enum machine_mode mode = GET_MODE (true_expr);
+ rtx (*logical_func)(rtx, rtx, rtx);
+
+ if (TARGET_DEBUG_COND_EXEC)
+ {
+ fprintf (stderr,
+ "\n:::::::::: frv_ifcvt_modify_multiple_tests, before modification for %s\ntrue insn:\n",
+ ce_info->and_and_p ? "&&" : "||");
+
+ debug_rtx (*p_true);
+
+ fputs ("\nfalse insn:\n", stderr);
+ debug_rtx (*p_false);
+ }
+
+ if (TARGET_NO_MULTI_CE)
+ goto fail;
+
+ if (GET_CODE (cr) != REG)
+ goto fail;
+
+ if (mode == CCmode || mode == CC_UNSmode)
+ {
+ cr_class = ICR_REGS;
+ p_new_cr = &frv_ifcvt.extra_int_cr;
+ }
+ else if (mode == CC_FPmode)
+ {
+ cr_class = FCR_REGS;
+ p_new_cr = &frv_ifcvt.extra_fp_cr;
+ }
+ else
+ goto fail;
+
+ /* Allocate a temp CR, reusing a previously allocated temp CR if we have 3 or
+ more &&/|| tests. */
+ new_cr = *p_new_cr;
+ if (! new_cr)
+ {
+ new_cr = *p_new_cr = frv_alloc_temp_reg (&frv_ifcvt.tmp_reg, cr_class,
+ CC_CCRmode, TRUE, TRUE);
+ if (! new_cr)
+ goto fail;
+ }
+
+ if (ce_info->and_and_p)
+ {
+ old_test = old_false;
+ test_expr = true_expr;
+ logical_func = (GET_CODE (old_true) == EQ) ? gen_andcr : gen_andncr;
+ *p_true = gen_rtx_NE (CC_CCRmode, cr, const0_rtx);
+ *p_false = gen_rtx_EQ (CC_CCRmode, cr, const0_rtx);
+ }
+ else
+ {
+ old_test = old_false;
+ test_expr = false_expr;
+ logical_func = (GET_CODE (old_false) == EQ) ? gen_orcr : gen_orncr;
+ *p_true = gen_rtx_EQ (CC_CCRmode, cr, const0_rtx);
+ *p_false = gen_rtx_NE (CC_CCRmode, cr, const0_rtx);
+ }
+
+ /* First add the andcr/andncr/orcr/orncr, which will be added after the
+ conditional check instruction, due to frv_ifcvt_add_insn being a LIFO
+ stack. */
+ frv_ifcvt_add_insn ((*logical_func) (cr, cr, new_cr), bb->end, TRUE);
+
+ /* Now add the conditional check insn. */
+ cc = XEXP (test_expr, 0);
+ compare = gen_rtx_fmt_ee (GET_CODE (test_expr), CC_CCRmode, cc, const0_rtx);
+ if_else = gen_rtx_IF_THEN_ELSE (CC_CCRmode, old_test, compare, const0_rtx);
+
+ check_insn = gen_rtx_SET (VOIDmode, new_cr, if_else);
+
+ /* add the new check insn to the list of check insns that need to be
+ inserted. */
+ frv_ifcvt_add_insn (check_insn, bb->end, TRUE);
+
+ if (TARGET_DEBUG_COND_EXEC)
+ {
+ fputs ("\n:::::::::: frv_ifcvt_modify_multiple_tests, after modification\ntrue insn:\n",
+ stderr);
+
+ debug_rtx (*p_true);
+
+ fputs ("\nfalse insn:\n", stderr);
+ debug_rtx (*p_false);
+ }
+
+ return;
+
+ fail:
+ *p_true = *p_false = NULL_RTX;
+
+ /* If we allocated a CR register, release it. */
+ if (new_cr)
+ {
+ CLEAR_HARD_REG_BIT (frv_ifcvt.tmp_reg.regs, REGNO (new_cr));
+ *p_new_cr = NULL_RTX;
+ }
+
+ if (TARGET_DEBUG_COND_EXEC)
+ fputs ("\n:::::::::: frv_ifcvt_modify_multiple_tests, failed.\n", stderr);
+
+ return;
+}
+
+
+/* Return a register which will be loaded with a value if an IF block is
+ converted to conditional execution. This is used to rewrite instructions
+ that use constants to ones that just use registers. */
+
+static rtx
+frv_ifcvt_load_value (value, insn)
+ rtx value;
+ rtx insn ATTRIBUTE_UNUSED;
+{
+ int num_alloc = frv_ifcvt.cur_scratch_regs;
+ int i;
+ rtx reg;
+
+ /* We know gr0 == 0, so replace any errant uses. */
+ if (value == const0_rtx)
+ return gen_rtx_REG (SImode, GPR_FIRST);
+
+ /* First search all registers currently loaded to see if we have an
+ applicable constant. */
+ if (CONSTANT_P (value)
+ || (GET_CODE (value) == REG && REGNO (value) == LR_REGNO))
+ {
+ for (i = 0; i < num_alloc; i++)
+ {
+ if (rtx_equal_p (SET_SRC (frv_ifcvt.scratch_regs[i]), value))
+ return SET_DEST (frv_ifcvt.scratch_regs[i]);
+ }
+ }
+
+ /* Have we exhausted the number of registers available? */
+ if (num_alloc >= GPR_TEMP_NUM)
+ {
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Too many temporary registers allocated\n");
+
+ return NULL_RTX;
+ }
+
+ /* Allocate the new register. */
+ reg = frv_alloc_temp_reg (&frv_ifcvt.tmp_reg, GPR_REGS, SImode, TRUE, TRUE);
+ if (! reg)
+ {
+ if (rtl_dump_file)
+ fputs ("Could not find a scratch register\n", rtl_dump_file);
+
+ return NULL_RTX;
+ }
+
+ frv_ifcvt.cur_scratch_regs++;
+ frv_ifcvt.scratch_regs[num_alloc] = gen_rtx_SET (VOIDmode, reg, value);
+
+ if (rtl_dump_file)
+ {
+ if (GET_CODE (value) == CONST_INT)
+ fprintf (rtl_dump_file, "Register %s will hold %ld\n",
+ reg_names[ REGNO (reg)], (long)INTVAL (value));
+
+ else if (GET_CODE (value) == REG && REGNO (value) == LR_REGNO)
+ fprintf (rtl_dump_file, "Register %s will hold LR\n",
+ reg_names[ REGNO (reg)]);
+
+ else
+ fprintf (rtl_dump_file, "Register %s will hold a saved value\n",
+ reg_names[ REGNO (reg)]);
+ }
+
+ return reg;
+}
+
+
+/* Update a MEM used in conditional code that might contain an offset to put
+ the offset into a scratch register, so that the conditional load/store
+ operations can be used. This function returns the original pointer if the
+ MEM is valid to use in conditional code, NULL if we can't load up the offset
+ into a temporary register, or the new MEM if we were successful. */
+
+static rtx
+frv_ifcvt_rewrite_mem (mem, mode, insn)
+ rtx mem;
+ enum machine_mode mode;
+ rtx insn;
+{
+ rtx addr = XEXP (mem, 0);
+
+ if (!frv_legitimate_address_p (mode, addr, reload_completed, TRUE))
+ {
+ if (GET_CODE (addr) == PLUS)
+ {
+ rtx addr_op0 = XEXP (addr, 0);
+ rtx addr_op1 = XEXP (addr, 1);
+
+ if (plus_small_data_p (addr_op0, addr_op1))
+ addr = frv_ifcvt_load_value (addr, insn);
+
+ else if (GET_CODE (addr_op0) == REG && CONSTANT_P (addr_op1))
+ {
+ rtx reg = frv_ifcvt_load_value (addr_op1, insn);
+ if (!reg)
+ return NULL_RTX;
+
+ addr = gen_rtx_PLUS (Pmode, addr_op0, reg);
+ }
+
+ else
+ return NULL_RTX;
+ }
+
+ else if (CONSTANT_P (addr))
+ addr = frv_ifcvt_load_value (addr, insn);
+
+ else
+ return NULL_RTX;
+
+ if (addr == NULL_RTX)
+ return NULL_RTX;
+
+ else if (XEXP (mem, 0) != addr)
+ return change_address (mem, mode, addr);
+ }
+
+ return mem;
+}
+
+
+/* Given a PATTERN, return a SET expression if this PATTERN has only a single
+ SET, possibly conditionally executed. It may also have CLOBBERs, USEs. */
+
+static rtx
+single_set_pattern (pattern)
+ rtx pattern;
+{
+ rtx set;
+ int i;
+
+ if (GET_CODE (pattern) == COND_EXEC)
+ pattern = COND_EXEC_CODE (pattern);
+
+ if (GET_CODE (pattern) == SET)
+ return pattern;
+
+ else if (GET_CODE (pattern) == PARALLEL)
+ {
+ for (i = 0, set = 0; i < XVECLEN (pattern, 0); i++)
+ {
+ rtx sub = XVECEXP (pattern, 0, i);
+
+ switch (GET_CODE (sub))
+ {
+ case USE:
+ case CLOBBER:
+ break;
+
+ case SET:
+ if (set)
+ return 0;
+ else
+ set = sub;
+ break;
+
+ default:
+ return 0;
+ }
+ }
+ return set;
+ }
+
+ return 0;
+}
+
+
+/* A C expression to modify the code described by the conditional if
+ information CE_INFO with the new PATTERN in INSN. If PATTERN is a null
+ pointer after the IFCVT_MODIFY_INSN macro executes, it is assumed that that
+ insn cannot be converted to be executed conditionally. */
+
+rtx
+frv_ifcvt_modify_insn (ce_info, pattern, insn)
+ ce_if_block_t *ce_info ATTRIBUTE_UNUSED;
+ rtx pattern;
+ rtx insn;
+{
+ rtx orig_ce_pattern = pattern;
+ rtx set;
+ rtx op0;
+ rtx op1;
+ rtx test;
+
+ if (GET_CODE (pattern) != COND_EXEC)
+ abort ();
+
+ test = COND_EXEC_TEST (pattern);
+ if (GET_CODE (test) == AND)
+ {
+ rtx cr = frv_ifcvt.cr_reg;
+ rtx test_reg;
+
+ op0 = XEXP (test, 0);
+ if (! rtx_equal_p (cr, XEXP (op0, 0)))
+ goto fail;
+
+ op1 = XEXP (test, 1);
+ test_reg = XEXP (op1, 0);
+ if (GET_CODE (test_reg) != REG)
+ goto fail;
+
+ /* Is this the first nested if block in this sequence? If so, generate
+ an andcr or andncr. */
+ if (! frv_ifcvt.last_nested_if_cr)
+ {
+ rtx and_op;
+
+ frv_ifcvt.last_nested_if_cr = test_reg;
+ if (GET_CODE (op0) == NE)
+ and_op = gen_andcr (test_reg, cr, test_reg);
+ else
+ and_op = gen_andncr (test_reg, cr, test_reg);
+
+ frv_ifcvt_add_insn (and_op, insn, TRUE);
+ }
+
+ /* If this isn't the first statement in the nested if sequence, see if we
+ are dealing with the same register. */
+ else if (! rtx_equal_p (test_reg, frv_ifcvt.last_nested_if_cr))
+ goto fail;
+
+ COND_EXEC_TEST (pattern) = test = op1;
+ }
+
+ /* If this isn't a nested if, reset state variables. */
+ else
+ {
+ frv_ifcvt.last_nested_if_cr = NULL_RTX;
+ }
+
+ set = single_set_pattern (pattern);
+ if (set)
+ {
+ rtx dest = SET_DEST (set);
+ rtx src = SET_SRC (set);
+ enum machine_mode mode = GET_MODE (dest);
+
+ /* Check for normal binary operators */
+ if (mode == SImode
+ && (GET_RTX_CLASS (GET_CODE (src)) == '2'
+ || GET_RTX_CLASS (GET_CODE (src)) == 'c'))
+ {
+ op0 = XEXP (src, 0);
+ op1 = XEXP (src, 1);
+
+ /* Special case load of small data address which looks like:
+ r16+symbol_ref */
+ if (GET_CODE (src) == PLUS && plus_small_data_p (op0, op1))
+ {
+ src = frv_ifcvt_load_value (src, insn);
+ if (src)
+ COND_EXEC_CODE (pattern) = gen_rtx_SET (VOIDmode, dest, src);
+ else
+ goto fail;
+ }
+
+ else if (integer_register_operand (op0, SImode) && CONSTANT_P (op1))
+ {
+ op1 = frv_ifcvt_load_value (op1, insn);
+ if (op1)
+ COND_EXEC_CODE (pattern)
+ = gen_rtx_SET (VOIDmode, dest, gen_rtx_fmt_ee (GET_CODE (src),
+ GET_MODE (src),
+ op0, op1));
+ else
+ goto fail;
+ }
+ }
+
+ /* For multiply by a constant, we need to handle the sign extending
+ correctly. Add a USE of the value after the multiply to prevent flow
+ from cratering because only one register out of the two were used. */
+ else if (mode == DImode && GET_CODE (src) == MULT)
+ {
+ op0 = XEXP (src, 0);
+ op1 = XEXP (src, 1);
+ if (GET_CODE (op0) == SIGN_EXTEND && GET_CODE (op1) == CONST_INT)
+ {
+ op1 = frv_ifcvt_load_value (op1, insn);
+ if (op1)
+ {
+ op1 = gen_rtx_SIGN_EXTEND (DImode, op1);
+ COND_EXEC_CODE (pattern)
+ = gen_rtx_SET (VOIDmode, dest,
+ gen_rtx_MULT (DImode, op0, op1));
+ }
+ else
+ goto fail;
+ }
+
+ frv_ifcvt_add_insn (gen_rtx_USE (VOIDmode, dest), insn, FALSE);
+ }
+
+ /* If we are just loading a constant created for a nested conditional
+ execution statement, just load the constant without any conditional
+ execution, since we know that the constant will not interfere with any
+ other registers. */
+ else if (frv_ifcvt.scratch_insns_bitmap
+ && bitmap_bit_p (frv_ifcvt.scratch_insns_bitmap,
+ INSN_UID (insn)))
+ pattern = set;
+
+ else if (mode == QImode || mode == HImode || mode == SImode
+ || mode == SFmode)
+ {
+ int changed_p = FALSE;
+
+ /* Check for just loading up a constant */
+ if (CONSTANT_P (src) && integer_register_operand (dest, mode))
+ {
+ src = frv_ifcvt_load_value (src, insn);
+ if (!src)
+ goto fail;
+
+ changed_p = TRUE;
+ }
+
+ /* See if we need to fix up stores */
+ if (GET_CODE (dest) == MEM)
+ {
+ rtx new_mem = frv_ifcvt_rewrite_mem (dest, mode, insn);
+
+ if (!new_mem)
+ goto fail;
+
+ else if (new_mem != dest)
+ {
+ changed_p = TRUE;
+ dest = new_mem;
+ }
+ }
+
+ /* See if we need to fix up loads */
+ if (GET_CODE (src) == MEM)
+ {
+ rtx new_mem = frv_ifcvt_rewrite_mem (src, mode, insn);
+
+ if (!new_mem)
+ goto fail;
+
+ else if (new_mem != src)
+ {
+ changed_p = TRUE;
+ src = new_mem;
+ }
+ }
+
+ /* If either src or destination changed, redo SET. */
+ if (changed_p)
+ COND_EXEC_CODE (pattern) = gen_rtx_SET (VOIDmode, dest, src);
+ }
+
+ /* Rewrite a nested set cccr in terms of IF_THEN_ELSE. Also deal with
+ rewriting the CC register to be the same as the paired CC/CR register
+ for nested ifs. */
+ else if (mode == CC_CCRmode && GET_RTX_CLASS (GET_CODE (src)) == '<')
+ {
+ int regno = REGNO (XEXP (src, 0));
+ rtx if_else;
+
+ if (ce_info->pass > 1
+ && regno != (int)REGNO (frv_ifcvt.nested_cc_reg)
+ && TEST_HARD_REG_BIT (frv_ifcvt.nested_cc_ok_rewrite, regno))
+ {
+ src = gen_rtx_fmt_ee (GET_CODE (src),
+ CC_CCRmode,
+ frv_ifcvt.nested_cc_reg,
+ XEXP (src, 1));
+ }
+
+ if_else = gen_rtx_IF_THEN_ELSE (CC_CCRmode, test, src, const0_rtx);
+ pattern = gen_rtx_SET (VOIDmode, dest, if_else);
+ }
+
+ /* Remap a nested compare instruction to use the paired CC/CR reg. */
+ else if (ce_info->pass > 1
+ && GET_CODE (dest) == REG
+ && CC_P (REGNO (dest))
+ && REGNO (dest) != REGNO (frv_ifcvt.nested_cc_reg)
+ && TEST_HARD_REG_BIT (frv_ifcvt.nested_cc_ok_rewrite,
+ REGNO (dest))
+ && GET_CODE (src) == COMPARE)
+ {
+ PUT_MODE (frv_ifcvt.nested_cc_reg, GET_MODE (dest));
+ COND_EXEC_CODE (pattern)
+ = gen_rtx_SET (VOIDmode, frv_ifcvt.nested_cc_reg, copy_rtx (src));
+ }
+ }
+
+ if (TARGET_DEBUG_COND_EXEC)
+ {
+ rtx orig_pattern = PATTERN (insn);
+
+ PATTERN (insn) = pattern;
+ fprintf (stderr,
+ "\n:::::::::: frv_ifcvt_modify_insn: pass = %d, insn after modification:\n",
+ ce_info->pass);
+
+ debug_rtx (insn);
+ PATTERN (insn) = orig_pattern;
+ }
+
+ return pattern;
+
+ fail:
+ if (TARGET_DEBUG_COND_EXEC)
+ {
+ rtx orig_pattern = PATTERN (insn);
+
+ PATTERN (insn) = orig_ce_pattern;
+ fprintf (stderr,
+ "\n:::::::::: frv_ifcvt_modify_insn: pass = %d, insn could not be modified:\n",
+ ce_info->pass);
+
+ debug_rtx (insn);
+ PATTERN (insn) = orig_pattern;
+ }
+
+ return NULL_RTX;
+}
+
+
+/* A C expression to perform any final machine dependent modifications in
+ converting code to conditional execution in the code described by the
+ conditional if information CE_INFO. */
+
+void
+frv_ifcvt_modify_final (ce_info)
+ ce_if_block_t *ce_info ATTRIBUTE_UNUSED;
+{
+ rtx existing_insn;
+ rtx check_insn;
+ rtx p = frv_ifcvt.added_insns_list;
+ int i;
+
+ /* Loop inserting the check insns. The last check insn is the first test,
+ and is the appropriate place to insert constants. */
+ if (! p)
+ abort ();
+
+ do
+ {
+ rtx check_and_insert_insns = XEXP (p, 0);
+ rtx old_p = p;
+
+ check_insn = XEXP (check_and_insert_insns, 0);
+ existing_insn = XEXP (check_and_insert_insns, 1);
+ p = XEXP (p, 1);
+
+ /* The jump bit is used to say that the new insn is to be inserted BEFORE
+ the existing insn, otherwise it is to be inserted AFTER. */
+ if (check_and_insert_insns->jump)
+ {
+ emit_insn_before (check_insn, existing_insn);
+ check_and_insert_insns->jump = 0;
+ }
+ else
+ emit_insn_after (check_insn, existing_insn);
+
+ free_EXPR_LIST_node (check_and_insert_insns);
+ free_EXPR_LIST_node (old_p);
+ }
+ while (p != NULL_RTX);
+
+ /* Load up any constants needed into temp gprs */
+ for (i = 0; i < frv_ifcvt.cur_scratch_regs; i++)
+ {
+ rtx insn = emit_insn_before (frv_ifcvt.scratch_regs[i], existing_insn);
+ if (! frv_ifcvt.scratch_insns_bitmap)
+ frv_ifcvt.scratch_insns_bitmap = BITMAP_XMALLOC ();
+ bitmap_set_bit (frv_ifcvt.scratch_insns_bitmap, INSN_UID (insn));
+ frv_ifcvt.scratch_regs[i] = NULL_RTX;
+ }
+
+ frv_ifcvt.added_insns_list = NULL_RTX;
+ frv_ifcvt.cur_scratch_regs = 0;
+}
+
+
+/* A C expression to cancel any machine dependent modifications in converting
+ code to conditional execution in the code described by the conditional if
+ information CE_INFO. */
+
+void
+frv_ifcvt_modify_cancel (ce_info)
+ ce_if_block_t *ce_info ATTRIBUTE_UNUSED;
+{
+ int i;
+ rtx p = frv_ifcvt.added_insns_list;
+
+ /* Loop freeing up the EXPR_LIST's allocated. */
+ while (p != NULL_RTX)
+ {
+ rtx check_and_jump = XEXP (p, 0);
+ rtx old_p = p;
+
+ p = XEXP (p, 1);
+ free_EXPR_LIST_node (check_and_jump);
+ free_EXPR_LIST_node (old_p);
+ }
+
+ /* Release any temporary gprs allocated. */
+ for (i = 0; i < frv_ifcvt.cur_scratch_regs; i++)
+ frv_ifcvt.scratch_regs[i] = NULL_RTX;
+
+ frv_ifcvt.added_insns_list = NULL_RTX;
+ frv_ifcvt.cur_scratch_regs = 0;
+ return;
+}
+
+/* A C expression for the size in bytes of the trampoline, as an integer.
+ The template is:
+
+ setlo #0, <jmp_reg>
+ setlo #0, <static_chain>
+ sethi #0, <jmp_reg>
+ sethi #0, <static_chain>
+ jmpl @(gr0,<jmp_reg>) */
+
+int
+frv_trampoline_size ()
+{
+ return 5 /* instructions */ * 4 /* instruction size */;
+}
+
+
+/* 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 RTX for the static chain value that
+ should be passed to the function when it is called.
+
+ The template is:
+
+ setlo #0, <jmp_reg>
+ setlo #0, <static_chain>
+ sethi #0, <jmp_reg>
+ sethi #0, <static_chain>
+ jmpl @(gr0,<jmp_reg>) */
+
+void
+frv_initialize_trampoline (addr, fnaddr, static_chain)
+ rtx addr;
+ rtx fnaddr;
+ rtx static_chain;
+{
+ rtx sc_reg = force_reg (Pmode, static_chain);
+
+ emit_library_call (gen_rtx_SYMBOL_REF (SImode, "__trampoline_setup"),
+ FALSE, VOIDmode, 4,
+ addr, Pmode,
+ GEN_INT (frv_trampoline_size ()), SImode,
+ fnaddr, Pmode,
+ sc_reg, Pmode);
+}
+
+
+/* Many machines have some registers that cannot be copied directly to or from
+ memory or even from other types of registers. An example is the `MQ'
+ register, which on most machines, can only be copied to or from general
+ registers, but not memory. Some machines allow copying all registers to and
+ from memory, but require a scratch register for stores to some memory
+ locations (e.g., those with symbolic address on the RT, and those with
+ certain symbolic address on the SPARC when compiling PIC). In some cases,
+ both an intermediate and a scratch register are required.
+
+ You should define these macros to indicate to the reload phase that it may
+ need to allocate at least one register for a reload in addition to the
+ register to contain the data. Specifically, if copying X to a register
+ CLASS in MODE requires an intermediate register, you should define
+ `SECONDARY_INPUT_RELOAD_CLASS' to return the largest register class all of
+ whose registers can be used as intermediate registers or scratch registers.
+
+ If copying a register CLASS in MODE to X requires an intermediate or scratch
+ register, `SECONDARY_OUTPUT_RELOAD_CLASS' should be defined to return the
+ largest register class required. If the requirements for input and output
+ reloads are the same, the macro `SECONDARY_RELOAD_CLASS' should be used
+ instead of defining both macros identically.
+
+ The values returned by these macros are often `GENERAL_REGS'. Return
+ `NO_REGS' if no spare register is needed; i.e., if X can be directly copied
+ to or from a register of CLASS in MODE without requiring a scratch register.
+ Do not define this macro if it would always return `NO_REGS'.
+
+ If a scratch register is required (either with or without an intermediate
+ register), you should define patterns for `reload_inM' or `reload_outM', as
+ required.. These patterns, which will normally be implemented with a
+ `define_expand', should be similar to the `movM' patterns, except that
+ operand 2 is the scratch register.
+
+ Define constraints for the reload register and scratch register that contain
+ a single register class. If the original reload register (whose class is
+ CLASS) can meet the constraint given in the pattern, the value returned by
+ these macros is used for the class of the scratch register. Otherwise, two
+ additional reload registers are required. Their classes are obtained from
+ the constraints in the insn pattern.
+
+ X might be a pseudo-register or a `subreg' of a pseudo-register, which could
+ either be in a hard register or in memory. Use `true_regnum' to find out;
+ it will return -1 if the pseudo is in memory and the hard register number if
+ it is in a register.
+
+ These macros should not be used in the case where a particular class of
+ registers can only be copied to memory and not to another class of
+ registers. In that case, secondary reload registers are not needed and
+ would not be helpful. Instead, a stack location must be used to perform the
+ copy and the `movM' pattern should use memory as an intermediate storage.
+ This case often occurs between floating-point and general registers. */
+
+enum reg_class
+frv_secondary_reload_class (class, mode, x, in_p)
+ enum reg_class class;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ rtx x;
+ int in_p ATTRIBUTE_UNUSED;
+{
+ enum reg_class ret;
+
+ switch (class)
+ {
+ default:
+ ret = NO_REGS;
+ break;
+
+ /* Accumulators/Accumulator guard registers need to go through floating
+ point registers. */
+ case QUAD_REGS:
+ case EVEN_REGS:
+ case GPR_REGS:
+ ret = NO_REGS;
+ if (x && GET_CODE (x) == REG)
+ {
+ int regno = REGNO (x);
+
+ if (ACC_P (regno) || ACCG_P (regno))
+ ret = FPR_REGS;
+ }
+ break;
+
+ /* Nonzero constants should be loaded into an FPR through a GPR. */
+ case QUAD_FPR_REGS:
+ case FEVEN_REGS:
+ case FPR_REGS:
+ if (x && CONSTANT_P (x) && !ZERO_P (x))
+ ret = GPR_REGS;
+ else
+ ret = NO_REGS;
+ break;
+
+ /* All of these types need gpr registers. */
+ case ICC_REGS:
+ case FCC_REGS:
+ case CC_REGS:
+ case ICR_REGS:
+ case FCR_REGS:
+ case CR_REGS:
+ case LCR_REG:
+ case LR_REG:
+ ret = GPR_REGS;
+ break;
+
+ /* The accumulators need fpr registers */
+ case ACC_REGS:
+ case EVEN_ACC_REGS:
+ case QUAD_ACC_REGS:
+ case ACCG_REGS:
+ ret = FPR_REGS;
+ break;
+ }
+
+ return ret;
+}
+
+
+/* A C expression whose value is nonzero if pseudos that have been assigned to
+ registers of class CLASS would likely be spilled because registers of CLASS
+ are needed for spill registers.
+
+ The default value of this macro returns 1 if CLASS has exactly one register
+ and zero otherwise. On most machines, this default should be used. Only
+ define this macro to some other expression if pseudo allocated by
+ `local-alloc.c' end up in memory because their hard registers were needed
+ for spill registers. If this macro returns nonzero for those classes, those
+ pseudos will only be allocated by `global.c', which knows how to reallocate
+ the pseudo to another register. If there would not be another register
+ available for reallocation, you should not change the definition of this
+ macro since the only effect of such a definition would be to slow down
+ register allocation. */
+
+int
+frv_class_likely_spilled_p (class)
+ enum reg_class class;
+{
+ switch (class)
+ {
+ default:
+ break;
+
+ case ICC_REGS:
+ case FCC_REGS:
+ case CC_REGS:
+ case ICR_REGS:
+ case FCR_REGS:
+ case CR_REGS:
+ case LCR_REG:
+ case LR_REG:
+ case SPR_REGS:
+ case QUAD_ACC_REGS:
+ case EVEN_ACC_REGS:
+ case ACC_REGS:
+ case ACCG_REGS:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/* An expression for the alignment of a structure field FIELD if the
+ alignment computed in the usual way is COMPUTED. GNU CC uses this
+ value instead of the value in `BIGGEST_ALIGNMENT' or
+ `BIGGEST_FIELD_ALIGNMENT', if defined, for structure fields only. */
+
+/* The definition type of the bit field data is either char, short, long or
+ long long. The maximum bit size is the number of bits of its own type.
+
+ The bit field data is assigned to a storage unit that has an adequate size
+ for bit field data retention and is located at the smallest address.
+
+ Consecutive bit field data are packed at consecutive bits having the same
+ storage unit, with regard to the type, beginning with the MSB and continuing
+ toward the LSB.
+
+ If a field to be assigned lies over a bit field type boundary, its
+ assignment is completed by aligning it with a boundary suitable for the
+ type.
+
+ When a bit field having a bit length of 0 is declared, it is forcibly
+ assigned to the next storage unit.
+
+ e.g)
+ struct {
+ int a:2;
+ int b:6;
+ char c:4;
+ int d:10;
+ int :0;
+ int f:2;
+ } x;
+
+ +0 +1 +2 +3
+ &x 00000000 00000000 00000000 00000000
+ MLM----L
+ a b
+ &x+4 00000000 00000000 00000000 00000000
+ M--L
+ c
+ &x+8 00000000 00000000 00000000 00000000
+ M----------L
+ d
+ &x+12 00000000 00000000 00000000 00000000
+ ML
+ f
+*/
+
+int
+frv_adjust_field_align (field, computed)
+ tree field;
+ int computed;
+{
+ /* C++ provides a null DECL_CONTEXT if the bit field is wider than its
+ type. */
+ if (DECL_BIT_FIELD (field) && DECL_CONTEXT (field))
+ {
+ tree parent = DECL_CONTEXT (field);
+ tree prev = NULL_TREE;
+ tree cur;
+
+ /* Loop finding the previous field to the current one */
+ for (cur = TYPE_FIELDS (parent); cur && cur != field; cur = TREE_CHAIN (cur))
+ {
+ if (TREE_CODE (cur) != FIELD_DECL)
+ continue;
+
+ prev = cur;
+ }
+
+ if (!cur)
+ abort ();
+
+ /* If this isn't a :0 field and if the previous element is a bitfield
+ also, see if the type is different, if so, we will need to align the
+ bit-field to the next boundary */
+ if (prev
+ && ! DECL_PACKED (field)
+ && ! integer_zerop (DECL_SIZE (field))
+ && DECL_BIT_FIELD_TYPE (field) != DECL_BIT_FIELD_TYPE (prev))
+ {
+ int prev_align = TYPE_ALIGN (TREE_TYPE (prev));
+ int cur_align = TYPE_ALIGN (TREE_TYPE (field));
+ computed = (prev_align > cur_align) ? prev_align : cur_align;
+ }
+ }
+
+ return computed;
+}
+
+
+/* A C expression that is nonzero if it is permissible to store a value of mode
+ MODE in hard register number REGNO (or in several registers starting with
+ that one). For a machine where all registers are equivalent, a suitable
+ definition is
+
+ #define HARD_REGNO_MODE_OK(REGNO, MODE) 1
+
+ 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.
+
+ 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.
+
+ The minimum requirement for a mode to be OK in a register is that the
+ `movMODE' 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.
+
+ Since the same instruction used to move `SImode' will work for all narrower
+ integer modes, it is not necessary on any machine for `HARD_REGNO_MODE_OK'
+ to distinguish between these modes, provided you define patterns `movhi',
+ etc., to take advantage of this. This is useful because of the interaction
+ between `HARD_REGNO_MODE_OK' and `MODES_TIEABLE_P'; it is very desirable for
+ all integer modes to be tieable.
+
+ Many machines have special registers for floating point arithmetic. Often
+ people assume that floating point machine modes are allowed only in floating
+ point registers. This is not true. Any registers that can hold integers
+ can safely *hold* a floating point machine mode, whether or not floating
+ arithmetic can be done on it in those registers. Integer move instructions
+ can be used to move the values.
+
+ On some machines, though, the converse is true: fixed-point machine modes
+ may not go in floating registers. This is true if the floating registers
+ normalize any value stored in them, because storing a non-floating value
+ there would garble it. In this case, `HARD_REGNO_MODE_OK' should reject
+ fixed-point machine modes in floating registers. But if the floating
+ registers do not automatically normalize, if you can store any bit pattern
+ in one and retrieve it unchanged without a trap, then any machine mode may
+ go in a floating register, so you can define this macro to say so.
+
+ The primary significance of special floating registers is rather that they
+ are the registers acceptable in floating point arithmetic instructions.
+ However, this is of no concern to `HARD_REGNO_MODE_OK'. You handle it by
+ writing the proper constraints for those instructions.
+
+ On some machines, the floating registers are especially slow to access, so
+ that it is better to store a value in a stack frame than in such a register
+ if floating point arithmetic is not being done. As long as the floating
+ registers are not in class `GENERAL_REGS', they will not be used unless some
+ pattern's constraint asks for one. */
+
+int
+frv_hard_regno_mode_ok (regno, mode)
+ int regno;
+ enum machine_mode mode;
+{
+ int base;
+ int mask;
+
+ switch (mode)
+ {
+ case CCmode:
+ case CC_UNSmode:
+ return ICC_P (regno) || GPR_P (regno);
+
+ case CC_CCRmode:
+ return CR_P (regno) || GPR_P (regno);
+
+ case CC_FPmode:
+ return FCC_P (regno) || GPR_P (regno);
+
+ default:
+ break;
+ }
+
+ /* Set BASE to the first register in REGNO's class. Set MASK to the
+ bits that must be clear in (REGNO - BASE) for the register to be
+ well-aligned. */
+ if (INTEGRAL_MODE_P (mode) || FLOAT_MODE_P (mode) || VECTOR_MODE_P (mode))
+ {
+ if (ACCG_P (regno))
+ {
+ /* ACCGs store one byte. Two-byte quantities must start in
+ even-numbered registers, four-byte ones in registers whose
+ numbers are divisible by four, and so on. */
+ base = ACCG_FIRST;
+ mask = GET_MODE_SIZE (mode) - 1;
+ }
+ else
+ {
+ /* The other registers store one word. */
+ if (GPR_P (regno))
+ base = GPR_FIRST;
+
+ else if (FPR_P (regno))
+ base = FPR_FIRST;
+
+ else if (ACC_P (regno))
+ base = ACC_FIRST;
+
+ else
+ return 0;
+
+ /* Anything smaller than an SI is OK in any word-sized register. */
+ if (GET_MODE_SIZE (mode) < 4)
+ return 1;
+
+ mask = (GET_MODE_SIZE (mode) / 4) - 1;
+ }
+ return (((regno - base) & mask) == 0);
+ }
+
+ return 0;
+}
+
+
+/* A C expression for the number of consecutive hard registers, starting at
+ register number REGNO, required to hold a value of mode MODE.
+
+ On a machine where all registers are exactly one word, a suitable definition
+ of this macro is
+
+ #define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
+ / UNITS_PER_WORD)) */
+
+/* On the FRV, make the CC_FP mode take 3 words in the integer registers, so
+ that we can build the appropriate instructions to properly reload the
+ values. Also, make the byte-sized accumulator guards use one guard
+ for each byte. */
+
+int
+frv_hard_regno_nregs (regno, mode)
+ int regno;
+ enum machine_mode mode;
+{
+ if (ACCG_P (regno))
+ return GET_MODE_SIZE (mode);
+ else
+ return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+}
+
+
+/* A C expression for the maximum number of consecutive registers of
+ class CLASS needed to hold a value of mode MODE.
+
+ This is closely related to the macro `HARD_REGNO_NREGS'. In fact, the value
+ of the macro `CLASS_MAX_NREGS (CLASS, MODE)' should be the maximum value of
+ `HARD_REGNO_NREGS (REGNO, MODE)' for all REGNO values in the class CLASS.
+
+ This macro helps control the handling of multiple-word values in
+ the reload pass.
+
+ This declaration is required. */
+
+int
+frv_class_max_nregs (class, mode)
+ enum reg_class class;
+ enum machine_mode mode;
+{
+ if (class == ACCG_REGS)
+ /* An N-byte value requires N accumulator guards. */
+ return GET_MODE_SIZE (mode);
+ else
+ return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+}
+
+
+/* A C expression that is nonzero if X is a legitimate constant for an
+ immediate operand on the target machine. You can assume that X satisfies
+ `CONSTANT_P', so you need not check this. In fact, `1' is a suitable
+ definition for this macro on machines where anything `CONSTANT_P' is valid. */
+
+int
+frv_legitimate_constant_p (x)
+ rtx x;
+{
+ enum machine_mode mode = GET_MODE (x);
+
+ /* All of the integer constants are ok */
+ if (GET_CODE (x) != CONST_DOUBLE)
+ return TRUE;
+
+ /* double integer constants are ok */
+ if (mode == VOIDmode || mode == DImode)
+ return TRUE;
+
+ /* 0 is always ok */
+ if (x == CONST0_RTX (mode))
+ return TRUE;
+
+ /* If floating point is just emulated, allow any constant, since it will be
+ constructed in the GPRs */
+ if (!TARGET_HAS_FPRS)
+ return TRUE;
+
+ if (mode == DFmode && !TARGET_DOUBLE)
+ return TRUE;
+
+ /* Otherwise store the constant away and do a load. */
+ return FALSE;
+}
+
+/* A C expression for the cost of moving data from a register in class FROM to
+ one in class TO. The classes are expressed using the enumeration values
+ such as `GENERAL_REGS'. A value of 4 is the default; other values are
+ interpreted relative to that.
+
+ It is not required that the cost always equal 2 when FROM is the same as TO;
+ on some machines it is expensive to move between registers if they are not
+ general registers.
+
+ If reload sees an insn consisting of a single `set' between two hard
+ registers, and if `REGISTER_MOVE_COST' applied to their classes returns a
+ value of 2, reload does not check to ensure that the constraints of the insn
+ are met. Setting a cost of other than 2 will allow reload to verify that
+ the constraints are met. You should do this if the `movM' pattern's
+ constraints do not allow such copying. */
+
+#define HIGH_COST 40
+#define MEDIUM_COST 3
+#define LOW_COST 1
+
+int
+frv_register_move_cost (from, to)
+ enum reg_class from;
+ enum reg_class to;
+{
+ switch (from)
+ {
+ default:
+ break;
+
+ case QUAD_REGS:
+ case EVEN_REGS:
+ case GPR_REGS:
+ switch (to)
+ {
+ default:
+ break;
+
+ case QUAD_REGS:
+ case EVEN_REGS:
+ case GPR_REGS:
+ return LOW_COST;
+
+ case FEVEN_REGS:
+ case FPR_REGS:
+ return LOW_COST;
+
+ case LCR_REG:
+ case LR_REG:
+ case SPR_REGS:
+ return LOW_COST;
+ }
+
+ case FEVEN_REGS:
+ case FPR_REGS:
+ switch (to)
+ {
+ default:
+ break;
+
+ case QUAD_REGS:
+ case EVEN_REGS:
+ case GPR_REGS:
+ case ACC_REGS:
+ case EVEN_ACC_REGS:
+ case QUAD_ACC_REGS:
+ case ACCG_REGS:
+ return MEDIUM_COST;
+
+ case FEVEN_REGS:
+ case FPR_REGS:
+ return LOW_COST;
+ }
+
+ case LCR_REG:
+ case LR_REG:
+ case SPR_REGS:
+ switch (to)
+ {
+ default:
+ break;
+
+ case QUAD_REGS:
+ case EVEN_REGS:
+ case GPR_REGS:
+ return MEDIUM_COST;
+ }
+
+ case ACC_REGS:
+ case EVEN_ACC_REGS:
+ case QUAD_ACC_REGS:
+ case ACCG_REGS:
+ switch (to)
+ {
+ default:
+ break;
+
+ case FEVEN_REGS:
+ case FPR_REGS:
+ return MEDIUM_COST;
+
+ }
+ }
+
+ return HIGH_COST;
+}
+
+/* Implementation of TARGET_ASM_INTEGER. In the FRV case we need to
+ use ".picptr" to generate safe relocations for PIC code. We also
+ need a fixup entry for aligned (non-debugging) code. */
+
+static bool
+frv_assemble_integer (value, size, aligned_p)
+ rtx value;
+ unsigned int size;
+ int aligned_p;
+{
+ if (flag_pic && size == UNITS_PER_WORD)
+ {
+ if (GET_CODE (value) == CONST
+ || GET_CODE (value) == SYMBOL_REF
+ || GET_CODE (value) == LABEL_REF)
+ {
+ if (aligned_p)
+ {
+ static int label_num = 0;
+ char buf[256];
+ const char *p;
+
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", label_num++);
+ p = (* targetm.strip_name_encoding) (buf);
+
+ fprintf (asm_out_file, "%s:\n", p);
+ fprintf (asm_out_file, "%s\n", FIXUP_SECTION_ASM_OP);
+ fprintf (asm_out_file, "\t.picptr\t%s\n", p);
+ fprintf (asm_out_file, "\t.previous\n");
+ }
+ assemble_integer_with_op ("\t.picptr\t", value);
+ return true;
+ }
+ if (!aligned_p)
+ {
+ /* We've set the unaligned SI op to NULL, so we always have to
+ handle the unaligned case here. */
+ assemble_integer_with_op ("\t.4byte\t", value);
+ return true;
+ }
+ }
+ return default_assemble_integer (value, size, aligned_p);
+}
+
+/* Function to set up the backend function structure. */
+
+static struct machine_function *
+frv_init_machine_status ()
+{
+ return ggc_alloc_cleared (sizeof (struct machine_function));
+}
+
+
+/* Update the register state information, to know about which registers are set
+ or clobbered. */
+
+static void
+frv_registers_update (x, reg_state, modified, p_num_mod, flag)
+ rtx x;
+ unsigned char reg_state[];
+ int modified[];
+ int *p_num_mod;
+ int flag;
+{
+ int regno, reg_max;
+ rtx reg;
+ rtx cond;
+ const char *format;
+ int length;
+ int j;
+
+ switch (GET_CODE (x))
+ {
+ default:
+ break;
+
+ /* Clobber just modifies a register, it doesn't make it live. */
+ case CLOBBER:
+ frv_registers_update (XEXP (x, 0), reg_state, modified, p_num_mod,
+ flag | REGSTATE_MODIFIED);
+ return;
+
+ /* Pre modify updates the first argument, just references the second. */
+ case PRE_MODIFY:
+ case SET:
+ frv_registers_update (XEXP (x, 0), reg_state, modified, p_num_mod,
+ flag | REGSTATE_MODIFIED | REGSTATE_LIVE);
+ frv_registers_update (XEXP (x, 1), reg_state, modified, p_num_mod, flag);
+ return;
+
+ /* For COND_EXEC, pass the appropriate flag to evaluate the conditional
+ statement, but just to be sure, make sure it is the type of cond_exec
+ we expect. */
+ case COND_EXEC:
+ cond = XEXP (x, 0);
+ if ((GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
+ && GET_CODE (XEXP (cond, 0)) == REG
+ && CR_P (REGNO (XEXP (cond, 0)))
+ && GET_CODE (XEXP (cond, 1)) == CONST_INT
+ && INTVAL (XEXP (cond, 1)) == 0
+ && (flag & (REGSTATE_MODIFIED | REGSTATE_IF_EITHER)) == 0)
+ {
+ frv_registers_update (cond, reg_state, modified, p_num_mod, flag);
+ flag |= ((REGNO (XEXP (cond, 0)) - CR_FIRST)
+ | ((GET_CODE (cond) == NE)
+ ? REGSTATE_IF_TRUE
+ : REGSTATE_IF_FALSE));
+
+ frv_registers_update (XEXP (x, 1), reg_state, modified, p_num_mod,
+ flag);
+ return;
+ }
+ else
+ fatal_insn ("frv_registers_update", x);
+
+ /* MEM resets the modification bits. */
+ case MEM:
+ flag &= ~REGSTATE_MODIFIED;
+ break;
+
+ /* See if we need to set the modified flag. */
+ case SUBREG:
+ reg = SUBREG_REG (x);
+ if (GET_CODE (reg) == REG)
+ {
+ regno = subreg_regno (x);
+ reg_max = REGNO (reg) + HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ goto reg_common;
+ }
+ break;
+
+ case REG:
+ regno = REGNO (x);
+ reg_max = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+ /* fall through */
+
+ reg_common:
+ if (flag & REGSTATE_MODIFIED)
+ {
+ flag &= REGSTATE_MASK;
+ while (regno < reg_max)
+ {
+ int rs = reg_state[regno];
+
+ if (flag != rs)
+ {
+ if ((rs & REGSTATE_MODIFIED) == 0)
+ {
+ modified[ *p_num_mod ] = regno;
+ (*p_num_mod)++;
+ }
+
+ /* If the previous register state had the register as
+ modified, possibly in some conditional execution context,
+ and the current insn modifies in some other context, or
+ outside of conditional execution, just mark the variable
+ as modified. */
+ else
+ flag &= ~(REGSTATE_IF_EITHER | REGSTATE_CC_MASK);
+
+ reg_state[regno] = (rs | flag);
+ }
+ regno++;
+ }
+ }
+ return;
+ }
+
+
+ length = GET_RTX_LENGTH (GET_CODE (x));
+ format = GET_RTX_FORMAT (GET_CODE (x));
+
+ for (j = 0; j < length; ++j)
+ {
+ switch (format[j])
+ {
+ case 'e':
+ frv_registers_update (XEXP (x, j), reg_state, modified, p_num_mod,
+ flag);
+ break;
+
+ case 'V':
+ case 'E':
+ if (XVEC (x, j) != 0)
+ {
+ int k;
+ for (k = 0; k < XVECLEN (x, j); ++k)
+ frv_registers_update (XVECEXP (x, j, k), reg_state, modified,
+ p_num_mod, flag);
+ }
+ break;
+
+ default:
+ /* Nothing to do. */
+ break;
+ }
+ }
+
+ return;
+}
+
+
+/* Return if any registers in a hard register set were used an insn. */
+
+static int
+frv_registers_used_p (x, reg_state, flag)
+ rtx x;
+ unsigned char reg_state[];
+ int flag;
+{
+ int regno, reg_max;
+ rtx reg;
+ rtx cond;
+ rtx dest;
+ const char *format;
+ int result;
+ int length;
+ int j;
+
+ switch (GET_CODE (x))
+ {
+ default:
+ break;
+
+ /* Skip clobber, that doesn't use the previous value */
+ case CLOBBER:
+ return FALSE;
+
+ /* For SET, if a conditional jump has occurred in the same insn, only
+ allow a set of a CR register if that register is not currently live.
+ This is because on the FR-V, B0/B1 instructions are always last.
+ Otherwise, don't look at the result, except within a MEM, but do look
+ at the source. */
+ case SET:
+ dest = SET_DEST (x);
+ if (flag & REGSTATE_CONDJUMP
+ && GET_CODE (dest) == REG && CR_P (REGNO (dest))
+ && (reg_state[ REGNO (dest) ] & REGSTATE_LIVE) != 0)
+ return TRUE;
+
+ if (GET_CODE (dest) == MEM)
+ {
+ result = frv_registers_used_p (XEXP (dest, 0), reg_state, flag);
+ if (result)
+ return result;
+ }
+
+ return frv_registers_used_p (SET_SRC (x), reg_state, flag);
+
+ /* For COND_EXEC, pass the appropriate flag to evaluate the conditional
+ statement, but just to be sure, make sure it is the type of cond_exec
+ we expect. */
+ case COND_EXEC:
+ cond = XEXP (x, 0);
+ if ((GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
+ && GET_CODE (XEXP (cond, 0)) == REG
+ && CR_P (REGNO (XEXP (cond, 0)))
+ && GET_CODE (XEXP (cond, 1)) == CONST_INT
+ && INTVAL (XEXP (cond, 1)) == 0
+ && (flag & (REGSTATE_MODIFIED | REGSTATE_IF_EITHER)) == 0)
+ {
+ result = frv_registers_used_p (cond, reg_state, flag);
+ if (result)
+ return result;
+
+ flag |= ((REGNO (XEXP (cond, 0)) - CR_FIRST)
+ | ((GET_CODE (cond) == NE)
+ ? REGSTATE_IF_TRUE
+ : REGSTATE_IF_FALSE));
+
+ return frv_registers_used_p (XEXP (x, 1), reg_state, flag);
+ }
+ else
+ fatal_insn ("frv_registers_used_p", x);
+
+ /* See if a register or subreg was modified in the same VLIW insn. */
+ case SUBREG:
+ reg = SUBREG_REG (x);
+ if (GET_CODE (reg) == REG)
+ {
+ regno = subreg_regno (x);
+ reg_max = REGNO (reg) + HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ goto reg_common;
+ }
+ break;
+
+ case REG:
+ regno = REGNO (x);
+ reg_max = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+ /* fall through */
+
+ reg_common:
+ while (regno < reg_max)
+ {
+ int rs = reg_state[regno];
+
+ if (rs & REGSTATE_MODIFIED)
+ {
+ int rs_if = rs & REGSTATE_IF_EITHER;
+ int flag_if = flag & REGSTATE_IF_EITHER;
+
+ /* Simple modification, no conditional execution */
+ if ((rs & REGSTATE_IF_EITHER) == 0)
+ return TRUE;
+
+ /* See if the variable is only modified in a conditional
+ execution expression opposite to the conditional execution
+ expression that governs this expression (ie, true vs. false
+ for the same CC register). If this isn't two halves of the
+ same conditional expression, consider the register
+ modified. */
+ if (((rs_if == REGSTATE_IF_TRUE && flag_if == REGSTATE_IF_FALSE)
+ || (rs_if == REGSTATE_IF_FALSE && flag_if == REGSTATE_IF_TRUE))
+ && ((rs & REGSTATE_CC_MASK) == (flag & REGSTATE_CC_MASK)))
+ ;
+ else
+ return TRUE;
+ }
+
+ regno++;
+ }
+ return FALSE;
+ }
+
+
+ length = GET_RTX_LENGTH (GET_CODE (x));
+ format = GET_RTX_FORMAT (GET_CODE (x));
+
+ for (j = 0; j < length; ++j)
+ {
+ switch (format[j])
+ {
+ case 'e':
+ result = frv_registers_used_p (XEXP (x, j), reg_state, flag);
+ if (result != 0)
+ return result;
+ break;
+
+ case 'V':
+ case 'E':
+ if (XVEC (x, j) != 0)
+ {
+ int k;
+ for (k = 0; k < XVECLEN (x, j); ++k)
+ {
+ result = frv_registers_used_p (XVECEXP (x, j, k), reg_state,
+ flag);
+ if (result != 0)
+ return result;
+ }
+ }
+ break;
+
+ default:
+ /* Nothing to do. */
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* Return if any registers in a hard register set were set in an insn. */
+
+static int
+frv_registers_set_p (x, reg_state, modify_p)
+ rtx x;
+ unsigned char reg_state[];
+ int modify_p;
+{
+ int regno, reg_max;
+ rtx reg;
+ rtx cond;
+ const char *format;
+ int length;
+ int j;
+
+ switch (GET_CODE (x))
+ {
+ default:
+ break;
+
+ case CLOBBER:
+ return frv_registers_set_p (XEXP (x, 0), reg_state, TRUE);
+
+ case PRE_MODIFY:
+ case SET:
+ return (frv_registers_set_p (XEXP (x, 0), reg_state, TRUE)
+ || frv_registers_set_p (XEXP (x, 1), reg_state, FALSE));
+
+ case COND_EXEC:
+ cond = XEXP (x, 0);
+ /* just to be sure, make sure it is the type of cond_exec we
+ expect. */
+ if ((GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
+ && GET_CODE (XEXP (cond, 0)) == REG
+ && CR_P (REGNO (XEXP (cond, 0)))
+ && GET_CODE (XEXP (cond, 1)) == CONST_INT
+ && INTVAL (XEXP (cond, 1)) == 0
+ && !modify_p)
+ return frv_registers_set_p (XEXP (x, 1), reg_state, modify_p);
+ else
+ fatal_insn ("frv_registers_set_p", x);
+
+ /* MEM resets the modification bits. */
+ case MEM:
+ modify_p = FALSE;
+ break;
+
+ /* See if we need to set the modified modify_p. */
+ case SUBREG:
+ reg = SUBREG_REG (x);
+ if (GET_CODE (reg) == REG)
+ {
+ regno = subreg_regno (x);
+ reg_max = REGNO (reg) + HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ goto reg_common;
+ }
+ break;
+
+ case REG:
+ regno = REGNO (x);
+ reg_max = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+ /* fall through */
+
+ reg_common:
+ if (modify_p)
+ while (regno < reg_max)
+ {
+ int rs = reg_state[regno];
+
+ if (rs & REGSTATE_MODIFIED)
+ return TRUE;
+ regno++;
+ }
+ return FALSE;
+ }
+
+
+ length = GET_RTX_LENGTH (GET_CODE (x));
+ format = GET_RTX_FORMAT (GET_CODE (x));
+
+ for (j = 0; j < length; ++j)
+ {
+ switch (format[j])
+ {
+ case 'e':
+ if (frv_registers_set_p (XEXP (x, j), reg_state, modify_p))
+ return TRUE;
+ break;
+
+ case 'V':
+ case 'E':
+ if (XVEC (x, j) != 0)
+ {
+ int k;
+ for (k = 0; k < XVECLEN (x, j); ++k)
+ if (frv_registers_set_p (XVECEXP (x, j, k), reg_state,
+ modify_p))
+ return TRUE;
+ }
+ break;
+
+ default:
+ /* Nothing to do. */
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/* 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 FR-V, this pass is used to rescan the insn chain, and pack
+ conditional branches/calls/jumps, etc. with previous insns where it can. It
+ does not reorder the instructions. We assume the scheduler left the flow
+ information in a reasonable state. */
+
+static void
+frv_pack_insns ()
+{
+ state_t frv_state; /* frv state machine */
+ int cur_start_vliw_p; /* current insn starts a VLIW insn */
+ int next_start_vliw_p; /* next insn starts a VLIW insn */
+ int cur_condjump_p; /* flag if current insn is a cond jump*/
+ int next_condjump_p; /* flag if next insn is a cond jump */
+ rtx insn;
+ rtx link;
+ int j;
+ int num_mod = 0; /* # of modified registers */
+ int modified[FIRST_PSEUDO_REGISTER]; /* registers modified in current VLIW */
+ /* register state information */
+ unsigned char reg_state[FIRST_PSEUDO_REGISTER];
+
+ /* If we weren't going to pack the insns, don't bother with this pass. */
+ if (!optimize || !flag_schedule_insns_after_reload || TARGET_NO_VLIW_BRANCH)
+ return;
+
+ switch (frv_cpu_type)
+ {
+ default:
+ case FRV_CPU_FR300: /* FR300/simple are single issue */
+ case FRV_CPU_SIMPLE:
+ return;
+
+ case FRV_CPU_GENERIC: /* FR-V and FR500 are multi-issue */
+ case FRV_CPU_FR400:
+ case FRV_CPU_FR500:
+ case FRV_CPU_TOMCAT:
+ break;
+ }
+
+ /* Set up the instruction and register states. */
+ dfa_start ();
+ frv_state = (state_t) xmalloc (state_size ());
+ memset ((PTR) reg_state, REGSTATE_DEAD, sizeof (reg_state));
+
+ /* Go through the insns, and repack the insns. */
+ state_reset (frv_state);
+ cur_start_vliw_p = FALSE;
+ next_start_vliw_p = TRUE;
+ cur_condjump_p = 0;
+ next_condjump_p = 0;
+
+ for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
+ {
+ enum rtx_code code = GET_CODE (insn);
+ enum rtx_code pattern_code;
+
+ /* For basic block begin notes redo the live information, and skip other
+ notes. */
+ if (code == NOTE)
+ {
+ if (NOTE_LINE_NUMBER (insn) == (int)NOTE_INSN_BASIC_BLOCK)
+ {
+ regset live;
+
+ for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
+ reg_state[j] &= ~ REGSTATE_LIVE;
+
+ live = NOTE_BASIC_BLOCK (insn)->global_live_at_start;
+ EXECUTE_IF_SET_IN_REG_SET(live, 0, j,
+ {
+ reg_state[j] |= REGSTATE_LIVE;
+ });
+ }
+
+ continue;
+ }
+
+ /* things like labels reset everything. */
+ if (GET_RTX_CLASS (code) != 'i')
+ {
+ next_start_vliw_p = TRUE;
+ continue;
+ }
+
+ /* Clear the VLIW start flag on random USE and CLOBBER insns, which is
+ set on the USE insn that preceeds the return, and potentially on
+ CLOBBERs for setting multiword variables. Also skip the ADDR_VEC
+ holding the case table labels. */
+ pattern_code = GET_CODE (PATTERN (insn));
+ if (pattern_code == USE || pattern_code == CLOBBER
+ || pattern_code == ADDR_VEC || pattern_code == ADDR_DIFF_VEC)
+ {
+ CLEAR_VLIW_START (insn);
+ continue;
+ }
+
+ cur_start_vliw_p = next_start_vliw_p;
+ next_start_vliw_p = FALSE;
+
+ cur_condjump_p |= next_condjump_p;
+ next_condjump_p = 0;
+
+ /* Unconditional branches and calls end the current VLIW insn. */
+ if (code == CALL_INSN)
+ {
+ next_start_vliw_p = TRUE;
+
+ /* On a TOMCAT, calls must be alone in the VLIW insns. */
+ if (frv_cpu_type == FRV_CPU_TOMCAT)
+ cur_start_vliw_p = TRUE;
+ }
+ else if (code == JUMP_INSN)
+ {
+ if (any_condjump_p (insn))
+ next_condjump_p = REGSTATE_CONDJUMP;
+ else
+ next_start_vliw_p = TRUE;
+ }
+
+ /* Only allow setting a CCR register after a conditional branch. */
+ else if (((cur_condjump_p & REGSTATE_CONDJUMP) != 0)
+ && get_attr_type (insn) != TYPE_CCR)
+ cur_start_vliw_p = TRUE;
+
+ /* Determine if we need to start a new VLIW instruction. */
+ if (cur_start_vliw_p
+ /* Do not check for register conflicts in a setlo instruction
+ because any output or true dependencies will be with the
+ partnering sethi instruction, with which it can be packed.
+
+ Although output dependencies are rare they are still
+ possible. So check output dependencies in VLIW insn. */
+ || (get_attr_type (insn) != TYPE_SETLO
+ && (frv_registers_used_p (PATTERN (insn),
+ reg_state,
+ cur_condjump_p)
+ || frv_registers_set_p (PATTERN (insn), reg_state, FALSE)))
+ || state_transition (frv_state, insn) >= 0)
+ {
+ SET_VLIW_START (insn);
+ state_reset (frv_state);
+ state_transition (frv_state, insn);
+ cur_condjump_p = 0;
+
+ /* Update the modified registers. */
+ for (j = 0; j < num_mod; j++)
+ reg_state[ modified[j] ] &= ~(REGSTATE_CC_MASK
+ | REGSTATE_IF_EITHER
+ | REGSTATE_MODIFIED);
+
+ num_mod = 0;
+ }
+ else
+ CLEAR_VLIW_START (insn);
+
+ /* Record which registers are modified. */
+ frv_registers_update (PATTERN (insn), reg_state, modified, &num_mod, 0);
+
+ /* Process the death notices */
+ for (link = REG_NOTES (insn);
+ link != NULL_RTX;
+ link = XEXP (link, 1))
+ {
+ rtx reg = XEXP (link, 0);
+
+ if (REG_NOTE_KIND (link) == REG_DEAD && GET_CODE (reg) == REG)
+ {
+ int regno = REGNO (reg);
+ int n = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ for (; regno < n; regno++)
+ reg_state[regno] &= ~REGSTATE_LIVE;
+ }
+ }
+ }
+
+ free ((PTR) frv_state);
+ dfa_finish ();
+ return;
+}
+
+
+#define def_builtin(name, type, code) \
+ builtin_function ((name), (type), (code), BUILT_IN_MD, NULL, NULL)
+
+struct builtin_description
+{
+ enum insn_code icode;
+ const char *name;
+ enum frv_builtins code;
+ enum rtx_code comparison;
+ unsigned int flag;
+};
+
+/* Media intrinsics that take a single, constant argument. */
+
+static struct builtin_description bdesc_set[] =
+{
+ { CODE_FOR_mhdsets, "__MHDSETS", FRV_BUILTIN_MHDSETS, 0, 0 }
+};
+
+/* Media intrinsics that take just one argument. */
+
+static struct builtin_description bdesc_1arg[] =
+{
+ { CODE_FOR_mnot, "__MNOT", FRV_BUILTIN_MNOT, 0, 0 },
+ { CODE_FOR_munpackh, "__MUNPACKH", FRV_BUILTIN_MUNPACKH, 0, 0 },
+ { CODE_FOR_mbtoh, "__MBTOH", FRV_BUILTIN_MBTOH, 0, 0 },
+ { CODE_FOR_mhtob, "__MHTOB", FRV_BUILTIN_MHTOB, 0, 0 },
+ { CODE_FOR_mabshs, "__MABSHS", FRV_BUILTIN_MABSHS, 0, 0 }
+};
+
+/* Media intrinsics that take two arguments. */
+
+static struct builtin_description bdesc_2arg[] =
+{
+ { CODE_FOR_mand, "__MAND", FRV_BUILTIN_MAND, 0, 0 },
+ { CODE_FOR_mor, "__MOR", FRV_BUILTIN_MOR, 0, 0 },
+ { CODE_FOR_mxor, "__MXOR", FRV_BUILTIN_MXOR, 0, 0 },
+ { CODE_FOR_maveh, "__MAVEH", FRV_BUILTIN_MAVEH, 0, 0 },
+ { CODE_FOR_msaths, "__MSATHS", FRV_BUILTIN_MSATHS, 0, 0 },
+ { CODE_FOR_msathu, "__MSATHU", FRV_BUILTIN_MSATHU, 0, 0 },
+ { CODE_FOR_maddhss, "__MADDHSS", FRV_BUILTIN_MADDHSS, 0, 0 },
+ { CODE_FOR_maddhus, "__MADDHUS", FRV_BUILTIN_MADDHUS, 0, 0 },
+ { CODE_FOR_msubhss, "__MSUBHSS", FRV_BUILTIN_MSUBHSS, 0, 0 },
+ { CODE_FOR_msubhus, "__MSUBHUS", FRV_BUILTIN_MSUBHUS, 0, 0 },
+ { CODE_FOR_mqaddhss, "__MQADDHSS", FRV_BUILTIN_MQADDHSS, 0, 0 },
+ { CODE_FOR_mqaddhus, "__MQADDHUS", FRV_BUILTIN_MQADDHUS, 0, 0 },
+ { CODE_FOR_mqsubhss, "__MQSUBHSS", FRV_BUILTIN_MQSUBHSS, 0, 0 },
+ { CODE_FOR_mqsubhus, "__MQSUBHUS", FRV_BUILTIN_MQSUBHUS, 0, 0 },
+ { CODE_FOR_mpackh, "__MPACKH", FRV_BUILTIN_MPACKH, 0, 0 },
+ { CODE_FOR_mdpackh, "__MDPACKH", FRV_BUILTIN_MDPACKH, 0, 0 },
+ { CODE_FOR_mcop1, "__Mcop1", FRV_BUILTIN_MCOP1, 0, 0 },
+ { CODE_FOR_mcop2, "__Mcop2", FRV_BUILTIN_MCOP2, 0, 0 },
+ { CODE_FOR_mwcut, "__MWCUT", FRV_BUILTIN_MWCUT, 0, 0 },
+ { CODE_FOR_mqsaths, "__MQSATHS", FRV_BUILTIN_MQSATHS, 0, 0 }
+};
+
+/* Media intrinsics that take two arguments, the first being an ACC number. */
+
+static struct builtin_description bdesc_cut[] =
+{
+ { CODE_FOR_mcut, "__MCUT", FRV_BUILTIN_MCUT, 0, 0 },
+ { CODE_FOR_mcutss, "__MCUTSS", FRV_BUILTIN_MCUTSS, 0, 0 },
+ { CODE_FOR_mdcutssi, "__MDCUTSSI", FRV_BUILTIN_MDCUTSSI, 0, 0 }
+};
+
+/* Two-argument media intrinsics with an immediate second argument. */
+
+static struct builtin_description bdesc_2argimm[] =
+{
+ { CODE_FOR_mrotli, "__MROTLI", FRV_BUILTIN_MROTLI, 0, 0 },
+ { CODE_FOR_mrotri, "__MROTRI", FRV_BUILTIN_MROTRI, 0, 0 },
+ { CODE_FOR_msllhi, "__MSLLHI", FRV_BUILTIN_MSLLHI, 0, 0 },
+ { CODE_FOR_msrlhi, "__MSRLHI", FRV_BUILTIN_MSRLHI, 0, 0 },
+ { CODE_FOR_msrahi, "__MSRAHI", FRV_BUILTIN_MSRAHI, 0, 0 },
+ { CODE_FOR_mexpdhw, "__MEXPDHW", FRV_BUILTIN_MEXPDHW, 0, 0 },
+ { CODE_FOR_mexpdhd, "__MEXPDHD", FRV_BUILTIN_MEXPDHD, 0, 0 },
+ { CODE_FOR_mdrotli, "__MDROTLI", FRV_BUILTIN_MDROTLI, 0, 0 },
+ { CODE_FOR_mcplhi, "__MCPLHI", FRV_BUILTIN_MCPLHI, 0, 0 },
+ { CODE_FOR_mcpli, "__MCPLI", FRV_BUILTIN_MCPLI, 0, 0 },
+ { CODE_FOR_mhsetlos, "__MHSETLOS", FRV_BUILTIN_MHSETLOS, 0, 0 },
+ { CODE_FOR_mhsetloh, "__MHSETLOH", FRV_BUILTIN_MHSETLOH, 0, 0 },
+ { CODE_FOR_mhsethis, "__MHSETHIS", FRV_BUILTIN_MHSETHIS, 0, 0 },
+ { CODE_FOR_mhsethih, "__MHSETHIH", FRV_BUILTIN_MHSETHIH, 0, 0 },
+ { CODE_FOR_mhdseth, "__MHDSETH", FRV_BUILTIN_MHDSETH, 0, 0 }
+};
+
+/* Media intrinsics that take two arguments and return void, the first argument
+ being a pointer to 4 words in memory. */
+
+static struct builtin_description bdesc_void2arg[] =
+{
+ { CODE_FOR_mdunpackh, "__MDUNPACKH", FRV_BUILTIN_MDUNPACKH, 0, 0 },
+ { CODE_FOR_mbtohe, "__MBTOHE", FRV_BUILTIN_MBTOHE, 0, 0 },
+};
+
+/* Media intrinsics that take three arguments, the first being a const_int that
+ denotes an accumulator, and that return void. */
+
+static struct builtin_description bdesc_void3arg[] =
+{
+ { CODE_FOR_mcpxrs, "__MCPXRS", FRV_BUILTIN_MCPXRS, 0, 0 },
+ { CODE_FOR_mcpxru, "__MCPXRU", FRV_BUILTIN_MCPXRU, 0, 0 },
+ { CODE_FOR_mcpxis, "__MCPXIS", FRV_BUILTIN_MCPXIS, 0, 0 },
+ { CODE_FOR_mcpxiu, "__MCPXIU", FRV_BUILTIN_MCPXIU, 0, 0 },
+ { CODE_FOR_mmulhs, "__MMULHS", FRV_BUILTIN_MMULHS, 0, 0 },
+ { CODE_FOR_mmulhu, "__MMULHU", FRV_BUILTIN_MMULHU, 0, 0 },
+ { CODE_FOR_mmulxhs, "__MMULXHS", FRV_BUILTIN_MMULXHS, 0, 0 },
+ { CODE_FOR_mmulxhu, "__MMULXHU", FRV_BUILTIN_MMULXHU, 0, 0 },
+ { CODE_FOR_mmachs, "__MMACHS", FRV_BUILTIN_MMACHS, 0, 0 },
+ { CODE_FOR_mmachu, "__MMACHU", FRV_BUILTIN_MMACHU, 0, 0 },
+ { CODE_FOR_mmrdhs, "__MMRDHS", FRV_BUILTIN_MMRDHS, 0, 0 },
+ { CODE_FOR_mmrdhu, "__MMRDHU", FRV_BUILTIN_MMRDHU, 0, 0 },
+ { CODE_FOR_mqcpxrs, "__MQCPXRS", FRV_BUILTIN_MQCPXRS, 0, 0 },
+ { CODE_FOR_mqcpxru, "__MQCPXRU", FRV_BUILTIN_MQCPXRU, 0, 0 },
+ { CODE_FOR_mqcpxis, "__MQCPXIS", FRV_BUILTIN_MQCPXIS, 0, 0 },
+ { CODE_FOR_mqcpxiu, "__MQCPXIU", FRV_BUILTIN_MQCPXIU, 0, 0 },
+ { CODE_FOR_mqmulhs, "__MQMULHS", FRV_BUILTIN_MQMULHS, 0, 0 },
+ { CODE_FOR_mqmulhu, "__MQMULHU", FRV_BUILTIN_MQMULHU, 0, 0 },
+ { CODE_FOR_mqmulxhs, "__MQMULXHS", FRV_BUILTIN_MQMULXHS, 0, 0 },
+ { CODE_FOR_mqmulxhu, "__MQMULXHU", FRV_BUILTIN_MQMULXHU, 0, 0 },
+ { CODE_FOR_mqmachs, "__MQMACHS", FRV_BUILTIN_MQMACHS, 0, 0 },
+ { CODE_FOR_mqmachu, "__MQMACHU", FRV_BUILTIN_MQMACHU, 0, 0 },
+ { CODE_FOR_mqxmachs, "__MQXMACHS", FRV_BUILTIN_MQXMACHS, 0, 0 },
+ { CODE_FOR_mqxmacxhs, "__MQXMACXHS", FRV_BUILTIN_MQXMACXHS, 0, 0 },
+ { CODE_FOR_mqmacxhs, "__MQMACXHS", FRV_BUILTIN_MQMACXHS, 0, 0 }
+};
+
+/* Media intrinsics that take two accumulator numbers as argument and
+ return void. */
+
+static struct builtin_description bdesc_voidacc[] =
+{
+ { CODE_FOR_maddaccs, "__MADDACCS", FRV_BUILTIN_MADDACCS, 0, 0 },
+ { CODE_FOR_msubaccs, "__MSUBACCS", FRV_BUILTIN_MSUBACCS, 0, 0 },
+ { CODE_FOR_masaccs, "__MASACCS", FRV_BUILTIN_MASACCS, 0, 0 },
+ { CODE_FOR_mdaddaccs, "__MDADDACCS", FRV_BUILTIN_MDADDACCS, 0, 0 },
+ { CODE_FOR_mdsubaccs, "__MDSUBACCS", FRV_BUILTIN_MDSUBACCS, 0, 0 },
+ { CODE_FOR_mdasaccs, "__MDASACCS", FRV_BUILTIN_MDASACCS, 0, 0 }
+};
+
+/* Initialize media builtins. */
+
+static void
+frv_init_builtins ()
+{
+ tree endlink = void_list_node;
+ tree accumulator = integer_type_node;
+ tree integer = integer_type_node;
+ tree voidt = void_type_node;
+ tree uhalf = short_unsigned_type_node;
+ tree sword1 = long_integer_type_node;
+ tree uword1 = long_unsigned_type_node;
+ tree sword2 = long_long_integer_type_node;
+ tree uword2 = long_long_unsigned_type_node;
+ tree uword4 = build_pointer_type (uword1);
+
+#define UNARY(RET, T1) \
+ build_function_type (RET, tree_cons (NULL_TREE, T1, endlink))
+
+#define BINARY(RET, T1, T2) \
+ build_function_type (RET, tree_cons (NULL_TREE, T1, \
+ tree_cons (NULL_TREE, T2, endlink)))
+
+#define TRINARY(RET, T1, T2, T3) \
+ build_function_type (RET, tree_cons (NULL_TREE, T1, \
+ tree_cons (NULL_TREE, T2, \
+ tree_cons (NULL_TREE, T3, endlink))))
+
+ tree void_ftype_void = build_function_type (voidt, endlink);
+
+ tree void_ftype_acc = UNARY (voidt, accumulator);
+ tree void_ftype_uw4_uw1 = BINARY (voidt, uword4, uword1);
+ tree void_ftype_uw4_uw2 = BINARY (voidt, uword4, uword2);
+ tree void_ftype_acc_uw1 = BINARY (voidt, accumulator, uword1);
+ tree void_ftype_acc_acc = BINARY (voidt, accumulator, accumulator);
+ tree void_ftype_acc_uw1_uw1 = TRINARY (voidt, accumulator, uword1, uword1);
+ tree void_ftype_acc_sw1_sw1 = TRINARY (voidt, accumulator, sword1, sword1);
+ tree void_ftype_acc_uw2_uw2 = TRINARY (voidt, accumulator, uword2, uword2);
+ tree void_ftype_acc_sw2_sw2 = TRINARY (voidt, accumulator, sword2, sword2);
+
+ tree uw1_ftype_uw1 = UNARY (uword1, uword1);
+ tree uw1_ftype_sw1 = UNARY (uword1, sword1);
+ tree uw1_ftype_uw2 = UNARY (uword1, uword2);
+ tree uw1_ftype_acc = UNARY (uword1, accumulator);
+ tree uw1_ftype_uh_uh = BINARY (uword1, uhalf, uhalf);
+ tree uw1_ftype_uw1_uw1 = BINARY (uword1, uword1, uword1);
+ tree uw1_ftype_uw1_int = BINARY (uword1, uword1, integer);
+ tree uw1_ftype_acc_uw1 = BINARY (uword1, accumulator, uword1);
+ tree uw1_ftype_acc_sw1 = BINARY (uword1, accumulator, sword1);
+ tree uw1_ftype_uw2_uw1 = BINARY (uword1, uword2, uword1);
+ tree uw1_ftype_uw2_int = BINARY (uword1, uword2, integer);
+
+ tree sw1_ftype_int = UNARY (sword1, integer);
+ tree sw1_ftype_sw1_sw1 = BINARY (sword1, sword1, sword1);
+ tree sw1_ftype_sw1_int = BINARY (sword1, sword1, integer);
+
+ tree uw2_ftype_uw1 = UNARY (uword2, uword1);
+ tree uw2_ftype_uw1_int = BINARY (uword2, uword1, integer);
+ tree uw2_ftype_uw2_uw2 = BINARY (uword2, uword2, uword2);
+ tree uw2_ftype_uw2_int = BINARY (uword2, uword2, integer);
+ tree uw2_ftype_acc_int = BINARY (uword2, accumulator, integer);
+
+ tree sw2_ftype_sw2_sw2 = BINARY (sword2, sword2, sword2);
+
+ def_builtin ("__MAND", uw1_ftype_uw1_uw1, FRV_BUILTIN_MAND);
+ def_builtin ("__MOR", uw1_ftype_uw1_uw1, FRV_BUILTIN_MOR);
+ def_builtin ("__MXOR", uw1_ftype_uw1_uw1, FRV_BUILTIN_MXOR);
+ def_builtin ("__MNOT", uw1_ftype_uw1, FRV_BUILTIN_MNOT);
+ def_builtin ("__MROTLI", uw1_ftype_uw1_int, FRV_BUILTIN_MROTLI);
+ def_builtin ("__MROTRI", uw1_ftype_uw1_int, FRV_BUILTIN_MROTRI);
+ def_builtin ("__MWCUT", uw1_ftype_uw2_uw1, FRV_BUILTIN_MWCUT);
+ def_builtin ("__MAVEH", uw1_ftype_uw1_uw1, FRV_BUILTIN_MAVEH);
+ def_builtin ("__MSLLHI", uw1_ftype_uw1_int, FRV_BUILTIN_MSLLHI);
+ def_builtin ("__MSRLHI", uw1_ftype_uw1_int, FRV_BUILTIN_MSRLHI);
+ def_builtin ("__MSRAHI", sw1_ftype_sw1_int, FRV_BUILTIN_MSRAHI);
+ def_builtin ("__MSATHS", sw1_ftype_sw1_sw1, FRV_BUILTIN_MSATHS);
+ def_builtin ("__MSATHU", uw1_ftype_uw1_uw1, FRV_BUILTIN_MSATHU);
+ def_builtin ("__MADDHSS", sw1_ftype_sw1_sw1, FRV_BUILTIN_MADDHSS);
+ def_builtin ("__MADDHUS", uw1_ftype_uw1_uw1, FRV_BUILTIN_MADDHUS);
+ def_builtin ("__MSUBHSS", sw1_ftype_sw1_sw1, FRV_BUILTIN_MSUBHSS);
+ def_builtin ("__MSUBHUS", uw1_ftype_uw1_uw1, FRV_BUILTIN_MSUBHUS);
+ def_builtin ("__MMULHS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MMULHS);
+ def_builtin ("__MMULHU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MMULHU);
+ def_builtin ("__MMULXHS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MMULXHS);
+ def_builtin ("__MMULXHU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MMULXHU);
+ def_builtin ("__MMACHS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MMACHS);
+ def_builtin ("__MMACHU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MMACHU);
+ def_builtin ("__MMRDHS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MMRDHS);
+ def_builtin ("__MMRDHU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MMRDHU);
+ def_builtin ("__MQADDHSS", sw2_ftype_sw2_sw2, FRV_BUILTIN_MQADDHSS);
+ def_builtin ("__MQADDHUS", uw2_ftype_uw2_uw2, FRV_BUILTIN_MQADDHUS);
+ def_builtin ("__MQSUBHSS", sw2_ftype_sw2_sw2, FRV_BUILTIN_MQSUBHSS);
+ def_builtin ("__MQSUBHUS", uw2_ftype_uw2_uw2, FRV_BUILTIN_MQSUBHUS);
+ def_builtin ("__MQMULHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQMULHS);
+ def_builtin ("__MQMULHU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQMULHU);
+ def_builtin ("__MQMULXHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQMULXHS);
+ def_builtin ("__MQMULXHU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQMULXHU);
+ def_builtin ("__MQMACHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQMACHS);
+ def_builtin ("__MQMACHU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQMACHU);
+ def_builtin ("__MCPXRS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MCPXRS);
+ def_builtin ("__MCPXRU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MCPXRU);
+ def_builtin ("__MCPXIS", void_ftype_acc_sw1_sw1, FRV_BUILTIN_MCPXIS);
+ def_builtin ("__MCPXIU", void_ftype_acc_uw1_uw1, FRV_BUILTIN_MCPXIU);
+ def_builtin ("__MQCPXRS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQCPXRS);
+ def_builtin ("__MQCPXRU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQCPXRU);
+ def_builtin ("__MQCPXIS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQCPXIS);
+ def_builtin ("__MQCPXIU", void_ftype_acc_uw2_uw2, FRV_BUILTIN_MQCPXIU);
+ def_builtin ("__MCUT", uw1_ftype_acc_uw1, FRV_BUILTIN_MCUT);
+ def_builtin ("__MCUTSS", uw1_ftype_acc_sw1, FRV_BUILTIN_MCUTSS);
+ def_builtin ("__MEXPDHW", uw1_ftype_uw1_int, FRV_BUILTIN_MEXPDHW);
+ def_builtin ("__MEXPDHD", uw2_ftype_uw1_int, FRV_BUILTIN_MEXPDHD);
+ def_builtin ("__MPACKH", uw1_ftype_uh_uh, FRV_BUILTIN_MPACKH);
+ def_builtin ("__MUNPACKH", uw2_ftype_uw1, FRV_BUILTIN_MUNPACKH);
+ def_builtin ("__MDPACKH", uw2_ftype_uw2_uw2, FRV_BUILTIN_MDPACKH);
+ def_builtin ("__MDUNPACKH", void_ftype_uw4_uw2, FRV_BUILTIN_MDUNPACKH);
+ def_builtin ("__MBTOH", uw2_ftype_uw1, FRV_BUILTIN_MBTOH);
+ def_builtin ("__MHTOB", uw1_ftype_uw2, FRV_BUILTIN_MHTOB);
+ def_builtin ("__MBTOHE", void_ftype_uw4_uw1, FRV_BUILTIN_MBTOHE);
+ def_builtin ("__MCLRACC", void_ftype_acc, FRV_BUILTIN_MCLRACC);
+ def_builtin ("__MCLRACCA", void_ftype_void, FRV_BUILTIN_MCLRACCA);
+ def_builtin ("__MRDACC", uw1_ftype_acc, FRV_BUILTIN_MRDACC);
+ def_builtin ("__MRDACCG", uw1_ftype_acc, FRV_BUILTIN_MRDACCG);
+ def_builtin ("__MWTACC", void_ftype_acc_uw1, FRV_BUILTIN_MWTACC);
+ def_builtin ("__MWTACCG", void_ftype_acc_uw1, FRV_BUILTIN_MWTACCG);
+ def_builtin ("__Mcop1", uw1_ftype_uw1_uw1, FRV_BUILTIN_MCOP1);
+ def_builtin ("__Mcop2", uw1_ftype_uw1_uw1, FRV_BUILTIN_MCOP2);
+ def_builtin ("__MTRAP", void_ftype_void, FRV_BUILTIN_MTRAP);
+ def_builtin ("__MQXMACHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQXMACHS);
+ def_builtin ("__MQXMACXHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQXMACXHS);
+ def_builtin ("__MQMACXHS", void_ftype_acc_sw2_sw2, FRV_BUILTIN_MQMACXHS);
+ def_builtin ("__MADDACCS", void_ftype_acc_acc, FRV_BUILTIN_MADDACCS);
+ def_builtin ("__MSUBACCS", void_ftype_acc_acc, FRV_BUILTIN_MSUBACCS);
+ def_builtin ("__MASACCS", void_ftype_acc_acc, FRV_BUILTIN_MASACCS);
+ def_builtin ("__MDADDACCS", void_ftype_acc_acc, FRV_BUILTIN_MDADDACCS);
+ def_builtin ("__MDSUBACCS", void_ftype_acc_acc, FRV_BUILTIN_MDSUBACCS);
+ def_builtin ("__MDASACCS", void_ftype_acc_acc, FRV_BUILTIN_MDASACCS);
+ def_builtin ("__MABSHS", uw1_ftype_sw1, FRV_BUILTIN_MABSHS);
+ def_builtin ("__MDROTLI", uw2_ftype_uw2_int, FRV_BUILTIN_MDROTLI);
+ def_builtin ("__MCPLHI", uw1_ftype_uw2_int, FRV_BUILTIN_MCPLHI);
+ def_builtin ("__MCPLI", uw1_ftype_uw2_int, FRV_BUILTIN_MCPLI);
+ def_builtin ("__MDCUTSSI", uw2_ftype_acc_int, FRV_BUILTIN_MDCUTSSI);
+ def_builtin ("__MQSATHS", sw2_ftype_sw2_sw2, FRV_BUILTIN_MQSATHS);
+ def_builtin ("__MHSETLOS", sw1_ftype_sw1_int, FRV_BUILTIN_MHSETLOS);
+ def_builtin ("__MHSETHIS", sw1_ftype_sw1_int, FRV_BUILTIN_MHSETHIS);
+ def_builtin ("__MHDSETS", sw1_ftype_int, FRV_BUILTIN_MHDSETS);
+ def_builtin ("__MHSETLOH", uw1_ftype_uw1_int, FRV_BUILTIN_MHSETLOH);
+ def_builtin ("__MHSETHIH", uw1_ftype_uw1_int, FRV_BUILTIN_MHSETHIH);
+ def_builtin ("__MHDSETH", uw1_ftype_uw1_int, FRV_BUILTIN_MHDSETH);
+
+#undef UNARY
+#undef BINARY
+#undef TRINARY
+}
+
+/* Convert an integer constant to an accumulator register. ICODE is the
+ code of the target instruction, OPNUM is the number of the
+ accumulator operand and OPVAL is the constant integer. Try both
+ ACC and ACCG registers; only report an error if neither fit the
+ instruction. */
+
+static rtx
+frv_int_to_acc (icode, opnum, opval)
+ enum insn_code icode;
+ int opnum;
+ rtx opval;
+{
+ rtx reg;
+
+ if (GET_CODE (opval) != CONST_INT)
+ {
+ error ("accumulator is not a constant integer");
+ return NULL_RTX;
+ }
+ if (! IN_RANGE_P (INTVAL (opval), 0, NUM_ACCS - 1))
+ {
+ error ("accumulator number is out of bounds");
+ return NULL_RTX;
+ }
+
+ reg = gen_rtx_REG (insn_data[icode].operand[opnum].mode,
+ ACC_FIRST + INTVAL (opval));
+ if (! (*insn_data[icode].operand[opnum].predicate) (reg, VOIDmode))
+ REGNO (reg) = ACCG_FIRST + INTVAL (opval);
+
+ if (! (*insn_data[icode].operand[opnum].predicate) (reg, VOIDmode))
+ {
+ error ("inappropriate accumulator for `%s'", insn_data[icode].name);
+ return NULL_RTX;
+ }
+ return reg;
+}
+
+/* If an ACC rtx has mode MODE, return the mode that the matching ACCG
+ should have. */
+
+static enum machine_mode
+frv_matching_accg_mode (mode)
+ enum machine_mode mode;
+{
+ switch (mode)
+ {
+ case V4SImode:
+ return V4QImode;
+
+ case DImode:
+ return HImode;
+
+ case SImode:
+ return QImode;
+
+ default:
+ abort ();
+ }
+}
+
+/* Return the accumulator guard that should be paired with accumulator
+ register ACC. The mode of the returned register is in the same
+ class as ACC, but is four times smaller. */
+
+rtx
+frv_matching_accg_for_acc (acc)
+ rtx acc;
+{
+ return gen_rtx_REG (frv_matching_accg_mode (GET_MODE (acc)),
+ REGNO (acc) - ACC_FIRST + ACCG_FIRST);
+}
+
+/* Read a value from the head of the tree list pointed to by ARGLISTPTR.
+ Return the value as an rtx and replace *ARGLISTPTR with the tail of the
+ list. */
+
+static rtx
+frv_read_argument (arglistptr)
+ tree *arglistptr;
+{
+ tree next = TREE_VALUE (*arglistptr);
+ *arglistptr = TREE_CHAIN (*arglistptr);
+ return expand_expr (next, NULL_RTX, VOIDmode, 0);
+}
+
+/* Return true if OPVAL can be used for operand OPNUM of instruction ICODE.
+ The instruction should require a constant operand of some sort. The
+ function prints an error if OPVAL is not valid. */
+
+static int
+frv_check_constant_argument (icode, opnum, opval)
+ enum insn_code icode;
+ int opnum;
+ rtx opval;
+{
+ if (GET_CODE (opval) != CONST_INT)
+ {
+ error ("`%s' expects a constant argument", insn_data[icode].name);
+ return FALSE;
+ }
+ if (! (*insn_data[icode].operand[opnum].predicate) (opval, VOIDmode))
+ {
+ error ("constant argument out of range for `%s'", insn_data[icode].name);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Return a legitimate rtx for instruction ICODE's return value. Use TARGET
+ if it's not null, has the right mode, and satisfies operand 0's
+ predicate. */
+
+static rtx
+frv_legitimize_target (icode, target)
+ enum insn_code icode;
+ rtx target;
+{
+ enum machine_mode mode = insn_data[icode].operand[0].mode;
+
+ if (! target
+ || GET_MODE (target) != mode
+ || ! (*insn_data[icode].operand[0].predicate) (target, mode))
+ return gen_reg_rtx (mode);
+ else
+ return target;
+}
+
+/* Given that ARG is being passed as operand OPNUM to instruction ICODE,
+ check whether ARG satisfies the operand's contraints. If it doesn't,
+ copy ARG to a temporary register and return that. Otherwise return ARG
+ itself. */
+
+static rtx
+frv_legitimize_argument (icode, opnum, arg)
+ enum insn_code icode;
+ int opnum;
+ rtx arg;
+{
+ enum machine_mode mode = insn_data[icode].operand[opnum].mode;
+
+ if ((*insn_data[icode].operand[opnum].predicate) (arg, mode))
+ return arg;
+ else
+ return copy_to_mode_reg (mode, arg);
+}
+
+/* Expand builtins that take a single, constant argument. At the moment,
+ only MHDSETS falls into this category. */
+
+static rtx
+frv_expand_set_builtin (icode, arglist, target)
+ enum insn_code icode;
+ tree arglist;
+ rtx target;
+{
+ rtx pat;
+ rtx op0 = frv_read_argument (&arglist);
+
+ if (! frv_check_constant_argument (icode, 1, op0))
+ return NULL_RTX;
+
+ target = frv_legitimize_target (icode, target);
+ pat = GEN_FCN (icode) (target, op0);
+ if (! pat)
+ return NULL_RTX;
+
+ emit_insn (pat);
+ return target;
+}
+
+/* Expand builtins that take one operand. */
+
+static rtx
+frv_expand_unop_builtin (icode, arglist, target)
+ enum insn_code icode;
+ tree arglist;
+ rtx target;
+{
+ rtx pat;
+ rtx op0 = frv_read_argument (&arglist);
+
+ target = frv_legitimize_target (icode, target);
+ op0 = frv_legitimize_argument (icode, 1, op0);
+ pat = GEN_FCN (icode) (target, op0);
+ if (! pat)
+ return NULL_RTX;
+
+ emit_insn (pat);
+ return target;
+}
+
+/* Expand builtins that take two operands. */
+
+static rtx
+frv_expand_binop_builtin (icode, arglist, target)
+ enum insn_code icode;
+ tree arglist;
+ rtx target;
+{
+ rtx pat;
+ rtx op0 = frv_read_argument (&arglist);
+ rtx op1 = frv_read_argument (&arglist);
+
+ target = frv_legitimize_target (icode, target);
+ op0 = frv_legitimize_argument (icode, 1, op0);
+ op1 = frv_legitimize_argument (icode, 2, op1);
+ pat = GEN_FCN (icode) (target, op0, op1);
+ if (! pat)
+ return NULL_RTX;
+
+ emit_insn (pat);
+ return target;
+}
+
+/* Expand cut-style builtins, which take two operands and an implicit ACCG
+ one. */
+
+static rtx
+frv_expand_cut_builtin (icode, arglist, target)
+ enum insn_code icode;
+ tree arglist;
+ rtx target;
+{
+ rtx pat;
+ rtx op0 = frv_read_argument (&arglist);
+ rtx op1 = frv_read_argument (&arglist);
+ rtx op2;
+
+ target = frv_legitimize_target (icode, target);
+ op0 = frv_int_to_acc (icode, 1, op0);
+ if (! op0)
+ return NULL_RTX;
+
+ if (icode == CODE_FOR_mdcutssi || GET_CODE (op1) == CONST_INT)
+ {
+ if (! frv_check_constant_argument (icode, 2, op1))
+ return NULL_RTX;
+ }
+ else
+ op1 = frv_legitimize_argument (icode, 2, op1);
+
+ op2 = frv_matching_accg_for_acc (op0);
+ pat = GEN_FCN (icode) (target, op0, op1, op2);
+ if (! pat)
+ return NULL_RTX;
+
+ emit_insn (pat);
+ return target;
+}
+
+/* Expand builtins that take two operands and the second is immediate. */
+
+static rtx
+frv_expand_binopimm_builtin (icode, arglist, target)
+ enum insn_code icode;
+ tree arglist;
+ rtx target;
+{
+ rtx pat;
+ rtx op0 = frv_read_argument (&arglist);
+ rtx op1 = frv_read_argument (&arglist);
+
+ if (! frv_check_constant_argument (icode, 2, op1))
+ return NULL_RTX;
+
+ target = frv_legitimize_target (icode, target);
+ op0 = frv_legitimize_argument (icode, 1, op0);
+ pat = GEN_FCN (icode) (target, op0, op1);
+ if (! pat)
+ return NULL_RTX;
+
+ emit_insn (pat);
+ return target;
+}
+
+/* Expand builtins that take two operands, the first operand being a pointer to
+ ints and return void. */
+
+static rtx
+frv_expand_voidbinop_builtin (icode, arglist)
+ enum insn_code icode;
+ tree arglist;
+{
+ rtx pat;
+ rtx op0 = frv_read_argument (&arglist);
+ rtx op1 = frv_read_argument (&arglist);
+ enum machine_mode mode0 = insn_data[icode].operand[0].mode;
+ rtx addr;
+
+ if (GET_CODE (op0) != MEM)
+ {
+ rtx reg = op0;
+
+ if (! offsettable_address_p (0, mode0, op0))
+ {
+ reg = gen_reg_rtx (Pmode);
+ emit_insn (gen_rtx_SET (VOIDmode, reg, op0));
+ }
+
+ op0 = gen_rtx_MEM (SImode, reg);
+ }
+
+ addr = XEXP (op0, 0);
+ if (! offsettable_address_p (0, mode0, addr))
+ addr = copy_to_mode_reg (Pmode, op0);
+
+ op0 = change_address (op0, V4SImode, addr);
+ op1 = frv_legitimize_argument (icode, 1, op1);
+ pat = GEN_FCN (icode) (op0, op1);
+ if (! pat)
+ return 0;
+
+ emit_insn (pat);
+ return 0;
+}
+
+/* Expand builtins that take three operands and return void. The first
+ argument must be a constant that describes a pair or quad accumulators. A
+ fourth argument is created that is the accumulator guard register that
+ corresponds to the accumulator. */
+
+static rtx
+frv_expand_voidtriop_builtin (icode, arglist)
+ enum insn_code icode;
+ tree arglist;
+{
+ rtx pat;
+ rtx op0 = frv_read_argument (&arglist);
+ rtx op1 = frv_read_argument (&arglist);
+ rtx op2 = frv_read_argument (&arglist);
+ rtx op3;
+
+ op0 = frv_int_to_acc (icode, 0, op0);
+ if (! op0)
+ return NULL_RTX;
+
+ op1 = frv_legitimize_argument (icode, 1, op1);
+ op2 = frv_legitimize_argument (icode, 2, op2);
+ op3 = frv_matching_accg_for_acc (op0);
+ pat = GEN_FCN (icode) (op0, op1, op2, op3);
+ if (! pat)
+ return NULL_RTX;
+
+ emit_insn (pat);
+ return NULL_RTX;
+}
+
+/* Expand builtins that perform accumulator-to-accumulator operations.
+ These builtins take two accumulator numbers as argument and return
+ void. */
+
+static rtx
+frv_expand_voidaccop_builtin (icode, arglist)
+ enum insn_code icode;
+ tree arglist;
+{
+ rtx pat;
+ rtx op0 = frv_read_argument (&arglist);
+ rtx op1 = frv_read_argument (&arglist);
+ rtx op2;
+ rtx op3;
+
+ op0 = frv_int_to_acc (icode, 0, op0);
+ if (! op0)
+ return NULL_RTX;
+
+ op1 = frv_int_to_acc (icode, 1, op1);
+ if (! op1)
+ return NULL_RTX;
+
+ op2 = frv_matching_accg_for_acc (op0);
+ op3 = frv_matching_accg_for_acc (op1);
+ pat = GEN_FCN (icode) (op0, op1, op2, op3);
+ if (! pat)
+ return NULL_RTX;
+
+ emit_insn (pat);
+ return NULL_RTX;
+}
+
+/* Expand the MCLRACC builtin. This builtin takes a single accumulator
+ number as argument. */
+
+static rtx
+frv_expand_mclracc_builtin (arglist)
+ tree arglist;
+{
+ enum insn_code icode = CODE_FOR_mclracc;
+ rtx pat;
+ rtx op0 = frv_read_argument (&arglist);
+
+ op0 = frv_int_to_acc (icode, 0, op0);
+ if (! op0)
+ return NULL_RTX;
+
+ pat = GEN_FCN (icode) (op0);
+ if (pat)
+ emit_insn (pat);
+
+ return NULL_RTX;
+}
+
+/* Expand builtins that take no arguments. */
+
+static rtx
+frv_expand_noargs_builtin (icode)
+ enum insn_code icode;
+{
+ rtx pat = GEN_FCN (icode) (GEN_INT (0));
+ if (pat)
+ emit_insn (pat);
+
+ return NULL_RTX;
+}
+
+/* Expand MRDACC and MRDACCG. These builtins take a single accumulator
+ number or accumulator guard number as argument and return an SI integer. */
+
+static rtx
+frv_expand_mrdacc_builtin (icode, arglist)
+ enum insn_code icode;
+ tree arglist;
+{
+ rtx pat;
+ rtx target = gen_reg_rtx (SImode);
+ rtx op0 = frv_read_argument (&arglist);
+
+ op0 = frv_int_to_acc (icode, 1, op0);
+ if (! op0)
+ return NULL_RTX;
+
+ pat = GEN_FCN (icode) (target, op0);
+ if (! pat)
+ return NULL_RTX;
+
+ emit_insn (pat);
+ return target;
+}
+
+/* Expand MWTACC and MWTACCG. These builtins take an accumulator or
+ accumulator guard as their first argument and an SImode value as their
+ second. */
+
+static rtx
+frv_expand_mwtacc_builtin (icode, arglist)
+ enum insn_code icode;
+ tree arglist;
+{
+ rtx pat;
+ rtx op0 = frv_read_argument (&arglist);
+ rtx op1 = frv_read_argument (&arglist);
+
+ op0 = frv_int_to_acc (icode, 0, op0);
+ if (! op0)
+ return NULL_RTX;
+
+ op1 = frv_legitimize_argument (icode, 1, op1);
+ pat = GEN_FCN (icode) (op0, op1);
+ if (pat)
+ emit_insn (pat);
+
+ return NULL_RTX;
+}
+
+/* Expand builtins. */
+
+static rtx
+frv_expand_builtin (exp, target, subtarget, mode, ignore)
+ tree exp;
+ rtx target;
+ rtx subtarget ATTRIBUTE_UNUSED;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ int ignore ATTRIBUTE_UNUSED;
+{
+ tree arglist = TREE_OPERAND (exp, 1);
+ tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ unsigned fcode = (unsigned)DECL_FUNCTION_CODE (fndecl);
+ unsigned i;
+ struct builtin_description *d;
+
+ if (! TARGET_MEDIA)
+ {
+ error ("media functions are not available unless -mmedia is used");
+ return NULL_RTX;
+ }
+
+ switch (fcode)
+ {
+ case FRV_BUILTIN_MCOP1:
+ case FRV_BUILTIN_MCOP2:
+ case FRV_BUILTIN_MDUNPACKH:
+ case FRV_BUILTIN_MBTOHE:
+ if (! TARGET_MEDIA_REV1)
+ {
+ error ("this media function is only available on the fr500");
+ return NULL_RTX;
+ }
+ break;
+
+ case FRV_BUILTIN_MQXMACHS:
+ case FRV_BUILTIN_MQXMACXHS:
+ case FRV_BUILTIN_MQMACXHS:
+ case FRV_BUILTIN_MADDACCS:
+ case FRV_BUILTIN_MSUBACCS:
+ case FRV_BUILTIN_MASACCS:
+ case FRV_BUILTIN_MDADDACCS:
+ case FRV_BUILTIN_MDSUBACCS:
+ case FRV_BUILTIN_MDASACCS:
+ case FRV_BUILTIN_MABSHS:
+ case FRV_BUILTIN_MDROTLI:
+ case FRV_BUILTIN_MCPLHI:
+ case FRV_BUILTIN_MCPLI:
+ case FRV_BUILTIN_MDCUTSSI:
+ case FRV_BUILTIN_MQSATHS:
+ case FRV_BUILTIN_MHSETLOS:
+ case FRV_BUILTIN_MHSETLOH:
+ case FRV_BUILTIN_MHSETHIS:
+ case FRV_BUILTIN_MHSETHIH:
+ case FRV_BUILTIN_MHDSETS:
+ case FRV_BUILTIN_MHDSETH:
+ if (! TARGET_MEDIA_REV2)
+ {
+ error ("this media function is only available on the fr400");
+ return NULL_RTX;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Expand unique builtins. */
+
+ switch (fcode)
+ {
+ case FRV_BUILTIN_MTRAP:
+ return frv_expand_noargs_builtin (CODE_FOR_mtrap);
+
+ case FRV_BUILTIN_MCLRACC:
+ return frv_expand_mclracc_builtin (arglist);
+
+ case FRV_BUILTIN_MCLRACCA:
+ if (TARGET_ACC_8)
+ return frv_expand_noargs_builtin (CODE_FOR_mclracca8);
+ else
+ return frv_expand_noargs_builtin (CODE_FOR_mclracca4);
+
+ case FRV_BUILTIN_MRDACC:
+ return frv_expand_mrdacc_builtin (CODE_FOR_mrdacc, arglist);
+
+ case FRV_BUILTIN_MRDACCG:
+ return frv_expand_mrdacc_builtin (CODE_FOR_mrdaccg, arglist);
+
+ case FRV_BUILTIN_MWTACC:
+ return frv_expand_mwtacc_builtin (CODE_FOR_mwtacc, arglist);
+
+ case FRV_BUILTIN_MWTACCG:
+ return frv_expand_mwtacc_builtin (CODE_FOR_mwtaccg, arglist);
+
+ default:
+ break;
+ }
+
+ /* Expand groups of builtins. */
+
+ for (i = 0, d = bdesc_set; i < sizeof (bdesc_set) / sizeof *d; i++, d++)
+ if (d->code == fcode)
+ return frv_expand_set_builtin (d->icode, arglist, target);
+
+ for (i = 0, d = bdesc_1arg; i < sizeof (bdesc_1arg) / sizeof *d; i++, d++)
+ if (d->code == fcode)
+ return frv_expand_unop_builtin (d->icode, arglist, target);
+
+ for (i = 0, d = bdesc_2arg; i < sizeof (bdesc_2arg) / sizeof *d; i++, d++)
+ if (d->code == fcode)
+ return frv_expand_binop_builtin (d->icode, arglist, target);
+
+ for (i = 0, d = bdesc_cut; i < sizeof (bdesc_cut) / sizeof *d; i++, d++)
+ if (d->code == fcode)
+ return frv_expand_cut_builtin (d->icode, arglist, target);
+
+ for (i = 0, d = bdesc_2argimm;
+ i < sizeof (bdesc_2argimm) / sizeof *d;
+ i++, d++)
+ {
+ if (d->code == fcode)
+ return frv_expand_binopimm_builtin (d->icode, arglist, target);
+ }
+
+ for (i = 0, d = bdesc_void2arg;
+ i < sizeof (bdesc_void2arg) / sizeof *d;
+ i++, d++)
+ {
+ if (d->code == fcode)
+ return frv_expand_voidbinop_builtin (d->icode, arglist);
+ }
+
+ for (i = 0, d = bdesc_void3arg;
+ i < sizeof (bdesc_void3arg) / sizeof *d;
+ i++, d++)
+ {
+ if (d->code == fcode)
+ return frv_expand_voidtriop_builtin (d->icode, arglist);
+ }
+
+ for (i = 0, d = bdesc_voidacc;
+ i < sizeof (bdesc_voidacc) / sizeof *d;
+ i++, d++)
+ {
+ if (d->code == fcode)
+ return frv_expand_voidaccop_builtin (d->icode, arglist);
+ }
+ return 0;
+}
+
+static const char *
+frv_strip_name_encoding (str)
+ const char *str;
+{
+ while (*str == '*' || *str == SDATA_FLAG_CHAR)
+ str++;
+ return str;
+}
+
+static bool
+frv_in_small_data_p (decl)
+ tree decl;
+{
+ HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
+
+ return symbol_ref_small_data_p (XEXP (DECL_RTL (decl), 0))
+ && size > 0 && size <= g_switch_value;
+}
diff --git a/contrib/gcc/config/frv/frv.h b/contrib/gcc/config/frv/frv.h
new file mode 100644
index 0000000..f9900b2
--- /dev/null
+++ b/contrib/gcc/config/frv/frv.h
@@ -0,0 +1,3592 @@
+/* Target macros for the FRV port of GCC.
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Contributed by Red Hat Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef __FRV_H__
+#define __FRV_H__
+
+/* Set up System V.4 (aka ELF) defaults. */
+#include "svr4.h"
+
+
+/* Frv general purpose macros. */
+/* Align an address. */
+#define ADDR_ALIGN(addr,align) (((addr) + (align) - 1) & ~((align) - 1))
+
+/* Return true if a value is inside a range. */
+#define IN_RANGE_P(VALUE, LOW, HIGH) \
+ ( (((HOST_WIDE_INT)(VALUE)) >= (HOST_WIDE_INT)(LOW)) \
+ && (((HOST_WIDE_INT)(VALUE)) <= ((HOST_WIDE_INT)(HIGH))))
+
+
+/* Driver configuration. */
+
+/* A C expression which determines whether the option `-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.
+
+ Defined in svr4.h. */
+#undef SWITCH_TAKES_ARG
+#define SWITCH_TAKES_ARG(CHAR) \
+ (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G')
+
+/* A C expression which determines whether the option `-NAME' takes arguments.
+ The value should be the number of arguments that option takes-zero, for many
+ options. This macro rather than `SWITCH_TAKES_ARG' is used for
+ multi-character option names.
+
+ By default, this macro is defined as `DEFAULT_WORD_SWITCH_TAKES_ARG', which
+ handles the standard options properly. You need not define
+ `WORD_SWITCH_TAKES_ARG' unless you wish to add additional options which take
+ arguments. Any redefinition should call `DEFAULT_WORD_SWITCH_TAKES_ARG' and
+ then check for additional options.
+
+ Defined in svr4.h. */
+#undef WORD_SWITCH_TAKES_ARG
+
+/* A C string constant that tells the GNU CC driver program options to pass to
+ the assembler. It can also specify how to translate options you give to GNU
+ CC into options for GNU CC to pass to the assembler. See the file `sun3.h'
+ for an example of this.
+
+ Do not define this macro if it does not need to do anything.
+
+ Defined in svr4.h. */
+#undef ASM_SPEC
+#define ASM_SPEC "\
+%{G*} %{v} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
+%{mtomcat-stats} \
+%{!mno-eflags: \
+ %{mcpu=*} \
+ %{mgpr-*} %{mfpr-*} \
+ %{msoft-float} %{mhard-float} \
+ %{mdword} %{mno-dword} \
+ %{mdouble} %{mno-double} \
+ %{mmedia} %{mno-media} \
+ %{mmuladd} %{mno-muladd} \
+ %{mpack} %{mno-pack} \
+ %{fpic: -mpic} %{fPIC: -mPIC} %{mlibrary-pic}}"
+
+/* Another C string constant used much like `LINK_SPEC'. The difference
+ between the two is that `STARTFILE_SPEC' is used at the very beginning of
+ the command given to the linker.
+
+ If this macro is not defined, a default is provided that loads the standard
+ C startup file from the usual place. See `gcc.c'.
+
+ Defined in svr4.h. */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "crt0%O%s frvbegin%O%s"
+
+/* Another C string constant used much like `LINK_SPEC'. The difference
+ between the two is that `ENDFILE_SPEC' is used at the very end of the
+ command given to the linker.
+
+ Do not define this macro if it does not need to do anything.
+
+ Defined in svr4.h. */
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "frvend%O%s"
+
+/* A C string constant that tells the GNU CC driver program options to pass to
+ CPP. It can also specify how to translate options you give to GNU CC into
+ options for GNU CC to pass to the CPP.
+
+ Do not define this macro if it does not need to do anything. */
+
+/* The idea here is to use the -mcpu option to define macros based on the
+ processor's features, using the features of the default processor if
+ no -mcpu option is given. These macros can then be overridden by
+ other -m options. */
+#define CPP_SPEC "\
+%{mcpu=frv: %(cpp_frv)} \
+%{mcpu=fr500: %(cpp_fr500)} \
+%{mcpu=fr400: %(cpp_fr400)} \
+%{mcpu=fr300: %(cpp_simple)} \
+%{mcpu=tomcat: %(cpp_fr500)} \
+%{mcpu=simple: %(cpp_simple)} \
+%{!mcpu*: %(cpp_cpu_default)} \
+%{mno-media: -D__FRV_ACC__=0 %{msoft-float: -D__FRV_FPR__=0}} \
+%{mhard-float: -D__FRV_HARD_FLOAT__} \
+%{msoft-float: -U__FRV_HARD_FLOAT__} \
+%{mgpr-32: -U__FRV_GPR__ -D__FRV_GPR__=32} \
+%{mgpr-64: -U__FRV_GPR__ -D__FRV_GPR__=64} \
+%{mfpr-32: -U__FRV_FPR__ -D__FRV_FPR__=32} \
+%{mfpr-64: -U__FRV_FPR__ -D__FRV_FPR__=64} \
+%{macc-4: -U__FRV_ACC__ -D__FRV_ACC__=4} \
+%{macc-8: -U__FRV_ACC__ -D__FRV_ACC__=8} \
+%{mdword: -D__FRV_DWORD__} \
+%{mno-dword: -U__FRV_DWORD__} \
+%{mno-pack: -U__FRV_VLIW__} \
+%{fleading-underscore: -D__FRV_UNDERSCORE__}"
+
+/* CPU defaults. Each CPU has its own CPP spec that defines the default
+ macros for that CPU. Each CPU also has its own default target mask.
+
+ CPU GPRs FPRs ACCs FPU MulAdd ldd/std Issue rate
+ --- ---- ---- ---- --- ------ ------- ----------
+ FRV 64 64 8 double yes yes 4
+ FR500 64 64 8 single no yes 4
+ FR400 32 32 4 none no yes 2
+ Simple 32 0 0 none no no 1 */
+
+
+#define CPP_FRV_SPEC "\
+-D__FRV_GPR__=64 \
+-D__FRV_FPR__=64 \
+-D__FRV_ACC__=8 \
+-D__FRV_HARD_FLOAT__ \
+-D__FRV_DWORD__ \
+-D__FRV_VLIW__=4"
+
+#define CPP_FR500_SPEC "\
+-D__FRV_GPR__=64 \
+-D__FRV_FPR__=64 \
+-D__FRV_ACC__=8 \
+-D__FRV_HARD_FLOAT__ \
+-D__FRV_DWORD__ \
+-D__FRV_VLIW__=4"
+
+#define CPP_FR400_SPEC "\
+-D__FRV_GPR__=32 \
+-D__FRV_FPR__=32 \
+-D__FRV_ACC__=4 \
+-D__FRV_DWORD__ \
+-D__FRV_VLIW__=2"
+
+#define CPP_SIMPLE_SPEC "\
+-D__FRV_GPR__=32 \
+-D__FRV_FPR__=0 \
+-D__FRV_ACC__=0 \
+%{mmedia: -D__FRV_ACC__=8} \
+%{mhard-float|mmedia: -D__FRV_FPR__=64}"
+
+#define MASK_DEFAULT_FRV \
+ (MASK_MEDIA \
+ | MASK_DOUBLE \
+ | MASK_MULADD \
+ | MASK_DWORD \
+ | MASK_PACK)
+
+#define MASK_DEFAULT_FR500 \
+ (MASK_MEDIA | MASK_DWORD | MASK_PACK)
+
+#define MASK_DEFAULT_FR400 \
+ (MASK_GPR_32 \
+ | MASK_FPR_32 \
+ | MASK_MEDIA \
+ | MASK_ACC_4 \
+ | MASK_SOFT_FLOAT \
+ | MASK_DWORD \
+ | MASK_PACK)
+
+#define MASK_DEFAULT_SIMPLE \
+ (MASK_GPR_32 | MASK_SOFT_FLOAT)
+
+/* A C string constant that tells the GNU CC driver program options to pass to
+ `cc1'. It can also specify how to translate options you give to GNU CC into
+ options for GNU CC to pass to the `cc1'.
+
+ Do not define this macro if it does not need to do anything. */
+/* For ABI compliance, we need to put bss data into the normal data section. */
+#define CC1_SPEC "%{G*}"
+
+/* A C string constant that tells the GNU CC driver program options to pass to
+ the linker. It can also specify how to translate options you give to GNU CC
+ into options for GNU CC to pass to the linker.
+
+ Do not define this macro if it does not need to do anything.
+
+ Defined in svr4.h. */
+/* Override the svr4.h version with one that dispenses without the svr4
+ shared library options, notably -G. */
+#undef LINK_SPEC
+#define LINK_SPEC "\
+%{h*} %{v:-V} \
+%{b} %{Wl,*:%*} \
+%{static:-dn -Bstatic} \
+%{shared:-Bdynamic} \
+%{symbolic:-Bsymbolic} \
+%{G*} \
+%{YP,*} \
+%{Qy:} %{!Qn:-Qy}"
+
+/* Another C string constant used much like `LINK_SPEC'. The difference
+ between the two is that `LIB_SPEC' is used at the end of the command given
+ to the linker.
+
+ If this macro is not defined, a default is provided that loads the standard
+ C library from the usual place. See `gcc.c'.
+
+ Defined in svr4.h. */
+
+#undef LIB_SPEC
+#define LIB_SPEC "--start-group -lc -lsim --end-group"
+
+/* 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_frv", CPP_FRV_SPEC }, \
+ { "cpp_fr500", CPP_FR500_SPEC }, \
+ { "cpp_fr400", CPP_FR400_SPEC }, \
+ { "cpp_simple", CPP_SIMPLE_SPEC }, \
+ { "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \
+ SUBTARGET_EXTRA_SPECS
+
+#ifndef CPP_CPU_DEFAULT_SPEC
+#define CPP_CPU_DEFAULT_SPEC CPP_FR500_SPEC
+#define CPU_TYPE FRV_CPU_FR500
+#endif
+
+/* Allow us to easily change the default for -malloc-cc. */
+#ifndef DEFAULT_NO_ALLOC_CC
+#define MASK_DEFAULT_ALLOC_CC MASK_ALLOC_CC
+#else
+#define MASK_DEFAULT_ALLOC_CC 0
+#endif
+
+/* Run-time target specifications */
+
+/* Define this to be a string constant containing `-D' options to define the
+ predefined macros that identify this machine and system. These macros will
+ be predefined unless the `-ansi' option is specified.
+
+ In addition, a parallel set of macros are predefined, whose names are made
+ by appending `__' at the beginning and at the end. These `__' macros are
+ permitted by the ANSI standard, so they are predefined regardless of whether
+ `-ansi' is specified. */
+
+#define CPP_PREDEFINES "-D__frv__ -Amachine(frv)"
+
+
+/* This declaration should be present. */
+extern int target_flags;
+
+/* This series of macros is to allow compiler command arguments to enable or
+ disable the use of optional features of the target machine. For example,
+ one machine description serves both the 68000 and the 68020; a command
+ argument tells the compiler whether it should use 68020-only instructions or
+ not. This command argument works by means of a macro `TARGET_68020' that
+ tests a bit in `target_flags'.
+
+ Define a macro `TARGET_FEATURENAME' for each such option. Its definition
+ should test a bit in `target_flags'; for example:
+
+ #define TARGET_68020 (target_flags & 1)
+
+ One place where these macros are used is in the condition-expressions of
+ instruction patterns. Note how `TARGET_68020' appears frequently in the
+ 68000 machine description file, `m68k.md'. Another place they are used is
+ in the definitions of the other macros in the `MACHINE.h' file. */
+
+#define MASK_GPR_32 0x00000001 /* Limit gprs to 32 registers */
+#define MASK_FPR_32 0x00000002 /* Limit fprs to 32 registers */
+#define MASK_SOFT_FLOAT 0x00000004 /* Use software floating point */
+#define MASK_ALLOC_CC 0x00000008 /* Dynamically allocate icc/fcc's */
+#define MASK_DWORD 0x00000010 /* Change ABi to allow dbl word insns*/
+#define MASK_DOUBLE 0x00000020 /* Use double precision instructions */
+#define MASK_MEDIA 0x00000040 /* Use media instructions */
+#define MASK_MULADD 0x00000080 /* Use multiply add/subtract insns */
+#define MASK_LIBPIC 0x00000100 /* -fpic that can be linked w/o pic */
+#define MASK_ACC_4 0x00000200 /* Only use four media accumulators */
+#define MASK_PACK 0x00000400 /* Set to enable packed output */
+
+ /* put debug masks up high */
+#define MASK_DEBUG_ARG 0x40000000 /* debug argument handling */
+#define MASK_DEBUG_ADDR 0x20000000 /* debug go_if_legitimate_address */
+#define MASK_DEBUG_STACK 0x10000000 /* debug stack frame */
+#define MASK_DEBUG 0x08000000 /* general debugging switch */
+#define MASK_DEBUG_LOC 0x04000000 /* optimize line # table */
+#define MASK_DEBUG_COND_EXEC 0x02000000 /* debug cond exec code */
+#define MASK_NO_COND_MOVE 0x01000000 /* disable conditional moves */
+#define MASK_NO_SCC 0x00800000 /* disable set conditional codes */
+#define MASK_NO_COND_EXEC 0x00400000 /* disable conditional execution */
+#define MASK_NO_VLIW_BRANCH 0x00200000 /* disable repacking branches */
+#define MASK_NO_MULTI_CE 0x00100000 /* disable multi-level cond exec */
+#define MASK_NO_NESTED_CE 0x00080000 /* disable nested cond exec */
+
+#define MASK_DEFAULT MASK_DEFAULT_ALLOC_CC
+
+#define TARGET_GPR_32 ((target_flags & MASK_GPR_32) != 0)
+#define TARGET_FPR_32 ((target_flags & MASK_FPR_32) != 0)
+#define TARGET_SOFT_FLOAT ((target_flags & MASK_SOFT_FLOAT) != 0)
+#define TARGET_ALLOC_CC ((target_flags & MASK_ALLOC_CC) != 0)
+#define TARGET_DWORD ((target_flags & MASK_DWORD) != 0)
+#define TARGET_DOUBLE ((target_flags & MASK_DOUBLE) != 0)
+#define TARGET_MEDIA ((target_flags & MASK_MEDIA) != 0)
+#define TARGET_MULADD ((target_flags & MASK_MULADD) != 0)
+#define TARGET_LIBPIC ((target_flags & MASK_LIBPIC) != 0)
+#define TARGET_ACC_4 ((target_flags & MASK_ACC_4) != 0)
+#define TARGET_DEBUG_ARG ((target_flags & MASK_DEBUG_ARG) != 0)
+#define TARGET_DEBUG_ADDR ((target_flags & MASK_DEBUG_ADDR) != 0)
+#define TARGET_DEBUG_STACK ((target_flags & MASK_DEBUG_STACK) != 0)
+#define TARGET_DEBUG ((target_flags & MASK_DEBUG) != 0)
+#define TARGET_DEBUG_LOC ((target_flags & MASK_DEBUG_LOC) != 0)
+#define TARGET_DEBUG_COND_EXEC ((target_flags & MASK_DEBUG_COND_EXEC) != 0)
+#define TARGET_NO_COND_MOVE ((target_flags & MASK_NO_COND_MOVE) != 0)
+#define TARGET_NO_SCC ((target_flags & MASK_NO_SCC) != 0)
+#define TARGET_NO_COND_EXEC ((target_flags & MASK_NO_COND_EXEC) != 0)
+#define TARGET_NO_VLIW_BRANCH ((target_flags & MASK_NO_VLIW_BRANCH) != 0)
+#define TARGET_NO_MULTI_CE ((target_flags & MASK_NO_MULTI_CE) != 0)
+#define TARGET_NO_NESTED_CE ((target_flags & MASK_NO_NESTED_CE) != 0)
+#define TARGET_PACK ((target_flags & MASK_PACK) != 0)
+
+#define TARGET_GPR_64 (! TARGET_GPR_32)
+#define TARGET_FPR_64 (! TARGET_FPR_32)
+#define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT)
+#define TARGET_FIXED_CC (! TARGET_ALLOC_CC)
+#define TARGET_COND_MOVE (! TARGET_NO_COND_MOVE)
+#define TARGET_SCC (! TARGET_NO_SCC)
+#define TARGET_COND_EXEC (! TARGET_NO_COND_EXEC)
+#define TARGET_VLIW_BRANCH (! TARGET_NO_VLIW_BRANCH)
+#define TARGET_MULTI_CE (! TARGET_NO_MULTI_CE)
+#define TARGET_NESTED_CE (! TARGET_NO_NESTED_CE)
+#define TARGET_ACC_8 (! TARGET_ACC_4)
+
+#define TARGET_HAS_FPRS (TARGET_HARD_FLOAT || TARGET_MEDIA)
+
+#define NUM_GPRS (TARGET_GPR_32? 32 : 64)
+#define NUM_FPRS (!TARGET_HAS_FPRS? 0 : TARGET_FPR_32? 32 : 64)
+#define NUM_ACCS (!TARGET_MEDIA? 0 : TARGET_ACC_4? 4 : 8)
+
+/* Macros to identify the blend of media instructions available. Revision 1
+ is the one found on the FR500. Revision 2 includes the changes made for
+ the FR400.
+
+ Treat the generic processor as a revision 1 machine for now, for
+ compatibility with earlier releases. */
+
+#define TARGET_MEDIA_REV1 \
+ (TARGET_MEDIA \
+ && (frv_cpu_type == FRV_CPU_GENERIC \
+ || frv_cpu_type == FRV_CPU_FR500))
+
+#define TARGET_MEDIA_REV2 \
+ (TARGET_MEDIA && frv_cpu_type == FRV_CPU_FR400)
+
+/* This macro defines names of command options to set and clear bits in
+ `target_flags'. Its definition is an initializer with a subgrouping for
+ each command option.
+
+ Each subgrouping contains a string constant, that defines the option name,
+ a number, which contains the bits to set in `target_flags', and an optional
+ second string which is the textual description that will be displayed when
+ the user passes --help on the command line. If the number entry is negative
+ then the specified bits will be cleared instead of being set. If the second
+ string entry is present but empty, then no help information will be displayed
+ for that option, but it will not count as an undocumented option. The actual
+ option name, asseen on the command line is made by appending `-m' to the
+ specified name.
+
+ One of the subgroupings should have a null string. The number in this
+ grouping is the default value for `target_flags'. Any target options act
+ starting with that value.
+
+ Here is an example which defines `-m68000' and `-m68020' with opposite
+ meanings, and picks the latter as the default:
+
+ #define TARGET_SWITCHES \
+ { { "68020", 1, ""}, \
+ { "68000", -1, "Compile for the m68000"}, \
+ { "", 1, }}
+
+ This declaration must be present. */
+
+#define TARGET_SWITCHES \
+{{ "gpr-32", MASK_GPR_32, "Only use 32 gprs"}, \
+ { "gpr-64", -MASK_GPR_32, "Use 64 gprs"}, \
+ { "fpr-32", MASK_FPR_32, "Only use 32 fprs"}, \
+ { "fpr-64", -MASK_FPR_32, "Use 64 fprs"}, \
+ { "hard-float", -MASK_SOFT_FLOAT, "Use hardware floating point" },\
+ { "soft-float", MASK_SOFT_FLOAT, "Use software floating point" },\
+ { "alloc-cc", MASK_ALLOC_CC, "Dynamically allocate cc's" }, \
+ { "fixed-cc", -MASK_ALLOC_CC, "Just use icc0/fcc0" }, \
+ { "dword", MASK_DWORD, "Change ABI to allow double word insns" }, \
+ { "no-dword", -MASK_DWORD, "Do not use double word insns" }, \
+ { "double", MASK_DOUBLE, "Use fp double instructions" }, \
+ { "no-double", -MASK_DOUBLE, "Do not use fp double insns" }, \
+ { "media", MASK_MEDIA, "Use media instructions" }, \
+ { "no-media", -MASK_MEDIA, "Do not use media insns" }, \
+ { "muladd", MASK_MULADD, "Use multiply add/subtract instructions" }, \
+ { "no-muladd", -MASK_MULADD, "Do not use multiply add/subtract insns" }, \
+ { "library-pic", MASK_LIBPIC, "PIC support for building libraries" }, \
+ { "acc-4", MASK_ACC_4, "Use 4 media accumulators" }, \
+ { "acc-8", -MASK_ACC_4, "Use 8 media accumulators" }, \
+ { "pack", MASK_PACK, "Pack VLIW instructions" }, \
+ { "no-pack", -MASK_PACK, "Do not pack VLIW instructions" }, \
+ { "no-eflags", 0, "Do not mark ABI switches in e_flags" }, \
+ { "debug-arg", MASK_DEBUG_ARG, "Internal debug switch" }, \
+ { "debug-addr", MASK_DEBUG_ADDR, "Internal debug switch" }, \
+ { "debug-stack", MASK_DEBUG_STACK, "Internal debug switch" }, \
+ { "debug", MASK_DEBUG, "Internal debug switch" }, \
+ { "debug-cond-exec", MASK_DEBUG_COND_EXEC, "Internal debug switch" }, \
+ { "debug-loc", MASK_DEBUG_LOC, "Internal debug switch" }, \
+ { "cond-move", -MASK_NO_COND_MOVE, "Enable conditional moves" }, \
+ { "no-cond-move", MASK_NO_COND_MOVE, "Disable conditional moves" }, \
+ { "scc", -MASK_NO_SCC, "Enable setting gprs to the result of comparisons" }, \
+ { "no-scc", MASK_NO_SCC, "Disable setting gprs to the result of comparisons" }, \
+ { "cond-exec", -MASK_NO_COND_EXEC, "Enable conditional execution other than moves/scc" }, \
+ { "no-cond-exec", MASK_NO_COND_EXEC, "Disable conditional execution other than moves/scc" }, \
+ { "vliw-branch", -MASK_NO_VLIW_BRANCH, "Run pass to pack branches into VLIW insns" }, \
+ { "no-vliw-branch", MASK_NO_VLIW_BRANCH, "Do not run pass to pack branches into VLIW insns" }, \
+ { "multi-cond-exec", -MASK_NO_MULTI_CE, "Disable optimizing &&/|| in conditional execution" }, \
+ { "no-multi-cond-exec", MASK_NO_MULTI_CE, "Enable optimizing &&/|| in conditional execution" }, \
+ { "nested-cond-exec", -MASK_NO_NESTED_CE, "Enable nested conditional execution optimizations" }, \
+ { "no-nested-cond-exec" ,MASK_NO_NESTED_CE, "Disable nested conditional execution optimizations" }, \
+ { "tomcat-stats", 0, "Cause gas to print tomcat statistics" }, \
+ { "", MASK_DEFAULT, "" }} \
+
+/* This macro is similar to `TARGET_SWITCHES' but defines names of command
+ options that have values. Its definition is an initializer with a
+ subgrouping for each command option.
+
+ Each subgrouping contains a string constant, that defines the fixed part of
+ the option name, the address of a variable, and an optional description string.
+ The variable, of type `char *', is set to the text following the fixed part of
+ the option as it is specified on the command line. The actual option name is
+ made by appending `-m' to the specified name.
+
+ Here is an example which defines `-mshort-data-NUMBER'. If the given option
+ is `-mshort-data-512', the variable `m88k_short_data' will be set to the
+ string `"512"'.
+
+ extern char *m88k_short_data;
+ #define TARGET_OPTIONS \
+ { { "short-data-", & m88k_short_data, \
+ "Specify the size of the short data section" } }
+
+ This declaration is optional. */
+#define TARGET_OPTIONS \
+{ \
+ { "cpu=", &frv_cpu_string, "Set cpu type" }, \
+ { "branch-cost=", &frv_branch_cost_string, "Internal debug switch" }, \
+ { "cond-exec-insns=", &frv_condexec_insns_str, "Internal debug switch" }, \
+ { "cond-exec-temps=", &frv_condexec_temps_str, "Internal debug switch" }, \
+ { "sched-lookahead=", &frv_sched_lookahead_str,"Internal debug switch" }, \
+}
+
+/* This macro is a C statement to print on `stderr' a string describing the
+ particular machine description choice. Every machine description should
+ define `TARGET_VERSION'. For example:
+
+ #ifdef MOTOROLA
+ #define TARGET_VERSION \
+ fprintf (stderr, " (68k, Motorola syntax)");
+ #else
+ #define TARGET_VERSION \
+ fprintf (stderr, " (68k, MIT syntax)");
+ #endif */
+#define TARGET_VERSION fprintf (stderr, _(" (frv)"))
+
+/* Sometimes certain combinations of command options do not make sense on a
+ particular target machine. You can define a macro `OVERRIDE_OPTIONS' to
+ take account of this. This macro, if defined, is executed once just after
+ all the command options have been parsed.
+
+ Don't use this macro to turn on various extra optimizations for `-O'. That
+ is what `OPTIMIZATION_OPTIONS' is for. */
+
+#define OVERRIDE_OPTIONS frv_override_options ()
+
+/* Some machines may desire to change what optimizations are performed for
+ various optimization levels. This macro, if defined, is executed once just
+ after the optimization level is determined and before the remainder of the
+ command options have been parsed. Values set in this macro are used as the
+ default values for the other command line options.
+
+ LEVEL is the optimization level specified; 2 if `-O2' is specified, 1 if
+ `-O' is specified, and 0 if neither is specified.
+
+ SIZE is nonzero if `-Os' is specified, 0 otherwise.
+
+ 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.
+
+ *Do not examine `write_symbols' in this macro!* The debugging options are
+ *not supposed to alter the generated code. */
+#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) frv_optimization_options (LEVEL, SIZE)
+
+
+/* Define this macro if debugging can be performed even without a frame
+ pointer. If this macro is defined, GNU CC will turn on the
+ `-fomit-frame-pointer' option whenever `-O' is specified. */
+/* Frv needs a specific frame layout that includes the frame pointer */
+
+#define CAN_DEBUG_WITHOUT_FP
+
+
+/* Small Data Area Support. */
+/* Maximum size of variables that go in .sdata/.sbss.
+ The -msdata=foo switch also controls how small variables are handled. */
+#ifndef SDATA_DEFAULT_SIZE
+#define SDATA_DEFAULT_SIZE 8
+#endif
+
+extern int g_switch_value; /* value of the -G xx switch */
+extern int g_switch_set; /* whether -G xx was passed. */
+
+
+/* Storage Layout */
+
+/* Define this macro to have the value 1 if the most significant bit in a byte
+ has the lowest number; otherwise define it to have the value zero. This
+ means that bit-field instructions count from the most significant bit. If
+ the machine has no bit-field instructions, then this must still be defined,
+ but it doesn't matter which value it is defined to. This macro need not be
+ a constant.
+
+ This macro does not affect the way structure fields are packed into bytes or
+ words; that is controlled by `BYTES_BIG_ENDIAN'. */
+#define BITS_BIG_ENDIAN 1
+
+/* Define this macro to have the value 1 if the most significant byte in a word
+ has the lowest number. This macro need not be a constant. */
+#define BYTES_BIG_ENDIAN 1
+
+/* Define this macro to have the value 1 if, in a multiword object, the most
+ significant word has the lowest number. This applies to both memory
+ locations and registers; GNU CC fundamentally assumes that the order of
+ words in memory is the same as the order in registers. This macro need not
+ be a constant. */
+#define WORDS_BIG_ENDIAN 1
+
+/* Number of storage units in a word; normally 4. */
+#define UNITS_PER_WORD 4
+
+/* A macro to update MODE and UNSIGNEDP when an object whose type is TYPE and
+ which has the specified mode and signedness is to be stored in a register.
+ This macro is only called when TYPE is a scalar type.
+
+ On most RISC machines, which only have operations that operate on a full
+ register, define this macro to set M to `word_mode' if M is an integer mode
+ narrower than `BITS_PER_WORD'. In most cases, only integer modes should be
+ widened because wider-precision floating-point operations are usually more
+ expensive than their narrower counterparts.
+
+ For most machines, the macro definition does not change UNSIGNEDP. However,
+ some machines, have instructions that preferentially handle either signed or
+ unsigned quantities of certain modes. For example, on the DEC Alpha, 32-bit
+ loads from memory and 32-bit add instructions sign-extend the result to 64
+ bits. On such machines, set UNSIGNEDP according to which kind of extension
+ is more efficient.
+
+ Do not define this macro if it would never modify MODE. */
+#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
+ do \
+ { \
+ if (GET_MODE_CLASS (MODE) == MODE_INT \
+ && GET_MODE_SIZE (MODE) < 4) \
+ (MODE) = SImode; \
+ } \
+ while (0)
+
+/* Normal alignment required for function parameters on the stack, in bits.
+ All stack parameters receive at least this much alignment regardless of data
+ type. On most machines, this is the same as the size of an integer. */
+#define PARM_BOUNDARY 32
+
+/* Define this macro if you wish to preserve a certain alignment for the stack
+ pointer. The definition is a C expression for the desired alignment
+ (measured in bits).
+
+ If `PUSH_ROUNDING' is not defined, the stack will always be aligned to the
+ specified boundary. If `PUSH_ROUNDING' is defined and specifies a less
+ strict alignment than `STACK_BOUNDARY', the stack may be momentarily
+ unaligned while pushing arguments. */
+#define STACK_BOUNDARY 64
+
+/* Alignment required for a function entry point, in bits. */
+#define FUNCTION_BOUNDARY 128
+
+/* Biggest alignment that any data type can require on this machine,
+ in bits. */
+#define BIGGEST_ALIGNMENT 64
+
+/* @@@ A hack, needed because libobjc wants to use ADJUST_FIELD_ALIGN for
+ some reason. */
+#ifdef IN_TARGET_LIBS
+#define BIGGEST_FIELD_ALIGNMENT 64
+#else
+/* An expression for the alignment of a structure field FIELD if the
+ alignment computed in the usual way is COMPUTED. GNU CC uses this
+ value instead of the value in `BIGGEST_ALIGNMENT' or
+ `BIGGEST_FIELD_ALIGNMENT', if defined, for structure fields only. */
+#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
+ frv_adjust_field_align (FIELD, COMPUTED)
+#endif
+
+/* If defined, a C expression to compute the alignment for a static variable.
+ TYPE is the data type, and ALIGN is the alignment that the object
+ would ordinarily have. The value of this macro is used instead of that
+ alignment to align the object.
+
+ If this macro is not defined, then ALIGN is used.
+
+ One use of this macro is to increase alignment of medium-size data to make
+ it all fit in fewer cache lines. Another is to cause character arrays to be
+ word-aligned so that `strcpy' calls that copy constants to character arrays
+ can be done inline. */
+#define DATA_ALIGNMENT(TYPE, ALIGN) \
+ (TREE_CODE (TYPE) == ARRAY_TYPE \
+ && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
+ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
+
+/* If defined, a C expression to compute the alignment given to a constant that
+ is being placed in memory. CONSTANT is the constant and ALIGN is the
+ alignment that the object would ordinarily have. The value of this macro is
+ used instead of that alignment to align the object.
+
+ If this macro is not defined, then ALIGN is used.
+
+ The typical use of this macro is to increase alignment for string constants
+ to be word aligned so that `strcpy' calls that copy constants can be done
+ inline. */
+#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
+ (TREE_CODE (EXP) == STRING_CST \
+ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
+
+/* 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. */
+#define STRICT_ALIGNMENT 1
+
+/* Define this if you wish to imitate the way many other C compilers handle
+ alignment of bitfields and the structures that contain them.
+
+ The behavior is that the type written for a bit-field (`int', `short', or
+ other integer type) imposes an alignment for the entire structure, as if the
+ structure really did contain an ordinary field of that type. In addition,
+ the bit-field is placed within the structure so that it would fit within such
+ a field, not crossing a boundary for it.
+
+ Thus, on most machines, a bit-field whose type is written as `int' would not
+ cross a four-byte boundary, and would force four-byte alignment for the
+ whole structure. (The alignment used may not be four bytes; it is
+ controlled by the other alignment parameters.)
+
+ If the macro is defined, its definition should be a C expression; a nonzero
+ value for the expression enables this behavior.
+
+ Note that if this macro is not defined, or its value is zero, some bitfields
+ may cross more than one alignment boundary. The compiler can support such
+ references if there are `insv', `extv', and `extzv' insns that can directly
+ reference memory.
+
+ The other known way of making bitfields work is to define
+ `STRUCTURE_SIZE_BOUNDARY' as large as `BIGGEST_ALIGNMENT'. Then every
+ structure can be accessed with fullwords.
+
+ Unless the machine has bit-field instructions or you define
+ `STRUCTURE_SIZE_BOUNDARY' that way, you must define
+ `PCC_BITFIELD_TYPE_MATTERS' to have a nonzero value.
+
+ If your aim is to make GNU CC use the same conventions for laying out
+ bitfields as are used by another compiler, here is how to investigate what
+ the other compiler does. Compile and run this program:
+
+ struct foo1
+ {
+ char x;
+ char :0;
+ char y;
+ };
+
+ struct foo2
+ {
+ char x;
+ int :0;
+ char y;
+ };
+
+ main ()
+ {
+ printf ("Size of foo1 is %d\n",
+ sizeof (struct foo1));
+ printf ("Size of foo2 is %d\n",
+ sizeof (struct foo2));
+ exit (0);
+ }
+
+ If this prints 2 and 5, then the compiler's behavior is what you would get
+ from `PCC_BITFIELD_TYPE_MATTERS'.
+
+ Defined in svr4.h. */
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+
+/* Layout of Source Language Data Types. */
+
+#define CHAR_TYPE_SIZE 8
+#define SHORT_TYPE_SIZE 16
+#define INT_TYPE_SIZE 32
+#define LONG_TYPE_SIZE 32
+#define LONG_LONG_TYPE_SIZE 64
+#define FLOAT_TYPE_SIZE 32
+#define DOUBLE_TYPE_SIZE 64
+#define LONG_DOUBLE_TYPE_SIZE 64
+
+/* An expression whose value is 1 or 0, according to whether the type `char'
+ should be signed or unsigned by default. The user can always override this
+ default with the options `-fsigned-char' and `-funsigned-char'. */
+#define DEFAULT_SIGNED_CHAR 1
+
+
+/* General purpose registers. */
+#define GPR_FIRST 0 /* First gpr */
+#define GPR_LAST (GPR_FIRST + 63) /* Last gpr */
+#define GPR_R0 GPR_FIRST /* R0, constant 0 */
+#define GPR_FP (GPR_FIRST + 2) /* Frame pointer */
+#define GPR_SP (GPR_FIRST + 1) /* Stack pointer */
+ /* small data register */
+#define SDA_BASE_REG ((unsigned)(flag_pic ? PIC_REGNO : (GPR_FIRST+16)))
+#define PIC_REGNO (GPR_FIRST + 17) /* PIC register */
+
+#define FPR_FIRST 64 /* First FP reg */
+#define FPR_LAST 127 /* Last FP reg */
+
+#define DEFAULT_CONDEXEC_TEMPS 4 /* reserve 4 regs by default */
+#define GPR_TEMP_NUM frv_condexec_temps /* # gprs to reserve for temps */
+
+/* We reserve the last CR and CCR in each category to be used as a reload
+ register to reload the CR/CCR registers. This is a kludge. */
+#define CC_FIRST 128 /* First ICC/FCC reg */
+#define CC_LAST 135 /* Last ICC/FCC reg */
+#define ICC_FIRST (CC_FIRST + 4) /* First ICC reg */
+#define ICC_LAST (CC_FIRST + 7) /* Last ICC reg */
+#define ICC_TEMP (CC_FIRST + 7) /* Temporary ICC reg */
+#define FCC_FIRST (CC_FIRST) /* First FCC reg */
+#define FCC_LAST (CC_FIRST + 3) /* Last FCC reg */
+
+/* Amount to shift a value to locate a ICC or FCC register in the CCR
+ register and shift it to the bottom 4 bits. */
+#define CC_SHIFT_RIGHT(REGNO) (((REGNO) - CC_FIRST) << 2)
+
+/* Mask to isolate a single ICC/FCC value. */
+#define CC_MASK 0xf
+
+/* Masks to isolate the various bits in an ICC field. */
+#define ICC_MASK_N 0x8 /* negative */
+#define ICC_MASK_Z 0x4 /* zero */
+#define ICC_MASK_V 0x2 /* overflow */
+#define ICC_MASK_C 0x1 /* carry */
+
+/* Mask to isolate the N/Z flags in an ICC. */
+#define ICC_MASK_NZ (ICC_MASK_N | ICC_MASK_Z)
+
+/* Mask to isolate the Z/C flags in an ICC. */
+#define ICC_MASK_ZC (ICC_MASK_Z | ICC_MASK_C)
+
+/* Masks to isolate the various bits in a FCC field. */
+#define FCC_MASK_E 0x8 /* equal */
+#define FCC_MASK_L 0x4 /* less than */
+#define FCC_MASK_G 0x2 /* greater than */
+#define FCC_MASK_U 0x1 /* unordered */
+
+/* For CCR registers, the machine wants CR4..CR7 to be used for integer
+ code and CR0..CR3 to be used for floating point. */
+#define CR_FIRST 136 /* First CCR */
+#define CR_LAST 143 /* Last CCR */
+#define CR_NUM (CR_LAST-CR_FIRST+1) /* # of CCRs (8) */
+#define ICR_FIRST (CR_FIRST + 4) /* First integer CCR */
+#define ICR_LAST (CR_FIRST + 7) /* Last integer CCR */
+#define ICR_TEMP ICR_LAST /* Temp integer CCR */
+#define FCR_FIRST (CR_FIRST + 0) /* First float CCR */
+#define FCR_LAST (CR_FIRST + 3) /* Last float CCR */
+
+/* Amount to shift a value to locate a CR register in the CCCR special purpose
+ register and shift it to the bottom 2 bits. */
+#define CR_SHIFT_RIGHT(REGNO) (((REGNO) - CR_FIRST) << 1)
+
+/* Mask to isolate a single CR value. */
+#define CR_MASK 0x3
+
+#define ACC_FIRST 144 /* First acc register */
+#define ACC_LAST 151 /* Last acc register */
+
+#define ACCG_FIRST 152 /* First accg register */
+#define ACCG_LAST 159 /* Last accg register */
+
+#define AP_FIRST 160 /* fake argument pointer */
+
+#define SPR_FIRST 161
+#define SPR_LAST 162
+#define LR_REGNO (SPR_FIRST)
+#define LCR_REGNO (SPR_FIRST + 1)
+
+#define GPR_P(R) IN_RANGE_P (R, GPR_FIRST, GPR_LAST)
+#define GPR_OR_AP_P(R) (GPR_P (R) || (R) == ARG_POINTER_REGNUM)
+#define FPR_P(R) IN_RANGE_P (R, FPR_FIRST, FPR_LAST)
+#define CC_P(R) IN_RANGE_P (R, CC_FIRST, CC_LAST)
+#define ICC_P(R) IN_RANGE_P (R, ICC_FIRST, ICC_LAST)
+#define FCC_P(R) IN_RANGE_P (R, FCC_FIRST, FCC_LAST)
+#define CR_P(R) IN_RANGE_P (R, CR_FIRST, CR_LAST)
+#define ICR_P(R) IN_RANGE_P (R, ICR_FIRST, ICR_LAST)
+#define FCR_P(R) IN_RANGE_P (R, FCR_FIRST, FCR_LAST)
+#define ACC_P(R) IN_RANGE_P (R, ACC_FIRST, ACC_LAST)
+#define ACCG_P(R) IN_RANGE_P (R, ACCG_FIRST, ACCG_LAST)
+#define SPR_P(R) IN_RANGE_P (R, SPR_FIRST, SPR_LAST)
+
+#define GPR_OR_PSEUDO_P(R) (GPR_P (R) || (R) >= FIRST_PSEUDO_REGISTER)
+#define FPR_OR_PSEUDO_P(R) (FPR_P (R) || (R) >= FIRST_PSEUDO_REGISTER)
+#define GPR_AP_OR_PSEUDO_P(R) (GPR_OR_AP_P (R) || (R) >= FIRST_PSEUDO_REGISTER)
+#define CC_OR_PSEUDO_P(R) (CC_P (R) || (R) >= FIRST_PSEUDO_REGISTER)
+#define ICC_OR_PSEUDO_P(R) (ICC_P (R) || (R) >= FIRST_PSEUDO_REGISTER)
+#define FCC_OR_PSEUDO_P(R) (FCC_P (R) || (R) >= FIRST_PSEUDO_REGISTER)
+#define CR_OR_PSEUDO_P(R) (CR_P (R) || (R) >= FIRST_PSEUDO_REGISTER)
+#define ICR_OR_PSEUDO_P(R) (ICR_P (R) || (R) >= FIRST_PSEUDO_REGISTER)
+#define FCR_OR_PSEUDO_P(R) (FCR_P (R) || (R) >= FIRST_PSEUDO_REGISTER)
+#define ACC_OR_PSEUDO_P(R) (ACC_P (R) || (R) >= FIRST_PSEUDO_REGISTER)
+#define ACCG_OR_PSEUDO_P(R) (ACCG_P (R) || (R) >= FIRST_PSEUDO_REGISTER)
+
+#define MAX_STACK_IMMEDIATE_OFFSET 2047
+
+
+/* Register Basics. */
+
+/* Number of hardware registers known to the compiler. They receive numbers 0
+ through `FIRST_PSEUDO_REGISTER-1'; thus, the first pseudo register's number
+ really is assigned the number `FIRST_PSEUDO_REGISTER'. */
+#define FIRST_PSEUDO_REGISTER (SPR_LAST + 1)
+
+/* The first/last register that can contain the arguments to a function. */
+#define FIRST_ARG_REGNUM (GPR_FIRST + 8)
+#define LAST_ARG_REGNUM (FIRST_ARG_REGNUM + FRV_NUM_ARG_REGS - 1)
+
+/* Registers used by the exception handling functions. These should be
+ registers that are not otherwised used by the calling sequence. */
+#define FIRST_EH_REGNUM 14
+#define LAST_EH_REGNUM 15
+
+/* Scratch registers used in the prologue, epilogue and thunks.
+ OFFSET_REGNO is for loading constant addends that are too big for a
+ single instruction. TEMP_REGNO is used for transferring SPRs to and from
+ the stack, and various other activities. */
+#define OFFSET_REGNO 4
+#define TEMP_REGNO 5
+
+/* Registers used in the prologue. OLD_SP_REGNO is the old stack pointer,
+ which is sometimes used to set up the frame pointer. */
+#define OLD_SP_REGNO 6
+
+/* Registers used in the epilogue. STACKADJ_REGNO stores the exception
+ handler's stack adjustment. */
+#define STACKADJ_REGNO 6
+
+/* Registers used in thunks. JMP_REGNO is used for loading the target
+ address. */
+#define JUMP_REGNO 6
+
+#define EH_RETURN_DATA_REGNO(N) ((N) <= (LAST_EH_REGNUM - FIRST_EH_REGNUM)? \
+ (N) + FIRST_EH_REGNUM : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (SImode, STACKADJ_REGNO)
+#define EH_RETURN_HANDLER_RTX RETURN_ADDR_RTX (0, frame_pointer_rtx)
+
+/* An initializer that says which registers are used for fixed purposes all
+ throughout the compiled code and are therefore not available for general
+ allocation. These would include the stack pointer, the frame pointer
+ (except on machines where that can be used as a general register when no
+ frame pointer is needed), the program counter on machines where that is
+ considered one of the addressable registers, and any other numbered register
+ with a standard use.
+
+ This information is expressed as a sequence of numbers, separated by commas
+ and surrounded by braces. The Nth number is 1 if register N is fixed, 0
+ otherwise.
+
+ The table initialized from this macro, and the table initialized by the
+ following one, may be overridden at run time either automatically, by the
+ actions of the macro `CONDITIONAL_REGISTER_USAGE', or by the user with the
+ command options `-ffixed-REG', `-fcall-used-REG' and `-fcall-saved-REG'. */
+
+/* gr0 -- Hard Zero
+ gr1 -- Stack Pointer
+ gr2 -- Frame Pointer
+ gr3 -- Hidden Parameter
+ gr16 -- Small Data reserved
+ gr17 -- Pic reserved
+ gr28 -- OS reserved
+ gr29 -- OS reserved
+ gr30 -- OS reserved
+ gr31 -- OS reserved
+ cr3 -- reserved to reload FCC registers.
+ cr7 -- reserved to reload ICC registers. */
+#define FIXED_REGISTERS \
+{ /* Integer Registers */ \
+ 1, 1, 1, 1, 0, 0, 0, 0, /* 000-007, gr0 - gr7 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 008-015, gr8 - gr15 */ \
+ 1, 1, 0, 0, 0, 0, 0, 0, /* 016-023, gr16 - gr23 */ \
+ 0, 0, 0, 0, 1, 1, 1, 1, /* 024-031, gr24 - gr31 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 032-039, gr32 - gr39 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 040-040, gr48 - gr47 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 048-055, gr48 - gr55 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 056-063, gr56 - gr63 */ \
+ /* Float Registers */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 064-071, fr0 - fr7 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 072-079, fr8 - fr15 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 080-087, fr16 - fr23 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 088-095, fr24 - fr31 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 096-103, fr32 - fr39 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 104-111, fr48 - fr47 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 112-119, fr48 - fr55 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 120-127, fr56 - fr63 */ \
+ /* Condition Code Registers */ \
+ 0, 0, 0, 0, /* 128-131, fcc0 - fcc3 */ \
+ 0, 0, 0, 1, /* 132-135, icc0 - icc3 */ \
+ /* Conditional execution Registers (CCR) */ \
+ 0, 0, 0, 0, 0, 0, 0, 1, /* 136-143, cr0 - cr7 */ \
+ /* Accumulators */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 144-151, acc0 - acc7 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 152-159, accg0 - accg7 */ \
+ /* Other registers */ \
+ 1, /* 160, AP - fake arg ptr */ \
+ 0, /* 161, LR - Link register*/ \
+ 0, /* 162, LCR - Loop count reg*/ \
+}
+
+/* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered (in
+ general) by function calls as well as for fixed registers. This macro
+ therefore identifies the registers that are not available for general
+ allocation of values that must live across function calls.
+
+ If a register has 0 in `CALL_USED_REGISTERS', the compiler automatically
+ saves it on function entry and restores it on function exit, if the register
+ is used within the function. */
+#define CALL_USED_REGISTERS \
+{ /* Integer Registers */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 000-007, gr0 - gr7 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 008-015, gr8 - gr15 */ \
+ 1, 1, 0, 0, 0, 0, 0, 0, /* 016-023, gr16 - gr23 */ \
+ 0, 0, 0, 0, 1, 1, 1, 1, /* 024-031, gr24 - gr31 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 032-039, gr32 - gr39 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 040-040, gr48 - gr47 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 048-055, gr48 - gr55 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 056-063, gr56 - gr63 */ \
+ /* Float Registers */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 064-071, fr0 - fr7 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 072-079, fr8 - fr15 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 080-087, fr16 - fr23 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 088-095, fr24 - fr31 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 096-103, fr32 - fr39 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 104-111, fr48 - fr47 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 112-119, fr48 - fr55 */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 120-127, fr56 - fr63 */ \
+ /* Condition Code Registers */ \
+ 1, 1, 1, 1, /* 128-131, fcc0 - fcc3 */ \
+ 1, 1, 1, 1, /* 132-135, icc0 - icc3 */ \
+ /* Conditional execution Registers (CCR) */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 136-143, cr0 - cr7 */ \
+ /* Accumulators */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 144-151, acc0 - acc7 */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 152-159, accg0 - accg7 */ \
+ /* Other registers */ \
+ 1, /* 160, AP - fake arg ptr */ \
+ 1, /* 161, LR - Link register*/ \
+ 1, /* 162, LCR - Loop count reg */ \
+}
+
+/* Zero or more C statements that may conditionally modify two variables
+ `fixed_regs' and `call_used_regs' (both of type `char []') after they have
+ been initialized from the two preceding macros.
+
+ This is necessary in case the fixed or call-clobbered registers depend on
+ target flags.
+
+ You need not define this macro if it has no work to do.
+
+ 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 `fixed_regs' and
+ `call_used_regs' to 1 for each of the registers in the classes which should
+ not be used by GCC. Also define the macro `REG_CLASS_FROM_LETTER' to return
+ `NO_REGS' if it is called with a letter for a class that shouldn't be used.
+
+ (However, if this class is not included in `GENERAL_REGS' and all of the
+ insn patterns whose constraints permit this class are controlled by target
+ switches, then GCC will automatically avoid using these registers when the
+ target switches are opposed to them.) */
+
+#define CONDITIONAL_REGISTER_USAGE frv_conditional_register_usage ()
+
+
+/* Order of allocation of registers. */
+
+/* If defined, an initializer for a vector of integers, containing the numbers
+ of hard registers in the order in which GNU CC should prefer to use them
+ (from most preferred to least).
+
+ If this macro is not defined, registers are used lowest numbered first (all
+ else being equal).
+
+ 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
+ `REG_ALLOC_ORDER' to be an initializer that lists the highest numbered
+ allocatable register first. */
+
+/* On the FRV, allocate GR16 and GR17 after other saved registers so that we
+ have a better chance of allocating 2 registers at a time and can use the
+ double word load/store instructions in the prologue. */
+#define REG_ALLOC_ORDER \
+{ \
+ /* volatile registers */ \
+ GPR_FIRST + 4, GPR_FIRST + 5, GPR_FIRST + 6, GPR_FIRST + 7, \
+ GPR_FIRST + 8, GPR_FIRST + 9, GPR_FIRST + 10, GPR_FIRST + 11, \
+ GPR_FIRST + 12, GPR_FIRST + 13, GPR_FIRST + 14, GPR_FIRST + 15, \
+ GPR_FIRST + 32, GPR_FIRST + 33, GPR_FIRST + 34, GPR_FIRST + 35, \
+ GPR_FIRST + 36, GPR_FIRST + 37, GPR_FIRST + 38, GPR_FIRST + 39, \
+ GPR_FIRST + 40, GPR_FIRST + 41, GPR_FIRST + 42, GPR_FIRST + 43, \
+ GPR_FIRST + 44, GPR_FIRST + 45, GPR_FIRST + 46, GPR_FIRST + 47, \
+ \
+ FPR_FIRST + 0, FPR_FIRST + 1, FPR_FIRST + 2, FPR_FIRST + 3, \
+ FPR_FIRST + 4, FPR_FIRST + 5, FPR_FIRST + 6, FPR_FIRST + 7, \
+ FPR_FIRST + 8, FPR_FIRST + 9, FPR_FIRST + 10, FPR_FIRST + 11, \
+ FPR_FIRST + 12, FPR_FIRST + 13, FPR_FIRST + 14, FPR_FIRST + 15, \
+ FPR_FIRST + 32, FPR_FIRST + 33, FPR_FIRST + 34, FPR_FIRST + 35, \
+ FPR_FIRST + 36, FPR_FIRST + 37, FPR_FIRST + 38, FPR_FIRST + 39, \
+ FPR_FIRST + 40, FPR_FIRST + 41, FPR_FIRST + 42, FPR_FIRST + 43, \
+ FPR_FIRST + 44, FPR_FIRST + 45, FPR_FIRST + 46, FPR_FIRST + 47, \
+ \
+ ICC_FIRST + 0, ICC_FIRST + 1, ICC_FIRST + 2, ICC_FIRST + 3, \
+ FCC_FIRST + 0, FCC_FIRST + 1, FCC_FIRST + 2, FCC_FIRST + 3, \
+ CR_FIRST + 0, CR_FIRST + 1, CR_FIRST + 2, CR_FIRST + 3, \
+ CR_FIRST + 4, CR_FIRST + 5, CR_FIRST + 6, CR_FIRST + 7, \
+ \
+ /* saved registers */ \
+ GPR_FIRST + 18, GPR_FIRST + 19, \
+ GPR_FIRST + 20, GPR_FIRST + 21, GPR_FIRST + 22, GPR_FIRST + 23, \
+ GPR_FIRST + 24, GPR_FIRST + 25, GPR_FIRST + 26, GPR_FIRST + 27, \
+ GPR_FIRST + 48, GPR_FIRST + 49, GPR_FIRST + 50, GPR_FIRST + 51, \
+ GPR_FIRST + 52, GPR_FIRST + 53, GPR_FIRST + 54, GPR_FIRST + 55, \
+ GPR_FIRST + 56, GPR_FIRST + 57, GPR_FIRST + 58, GPR_FIRST + 59, \
+ GPR_FIRST + 60, GPR_FIRST + 61, GPR_FIRST + 62, GPR_FIRST + 63, \
+ GPR_FIRST + 16, GPR_FIRST + 17, \
+ \
+ FPR_FIRST + 16, FPR_FIRST + 17, FPR_FIRST + 18, FPR_FIRST + 19, \
+ FPR_FIRST + 20, FPR_FIRST + 21, FPR_FIRST + 22, FPR_FIRST + 23, \
+ FPR_FIRST + 24, FPR_FIRST + 25, FPR_FIRST + 26, FPR_FIRST + 27, \
+ FPR_FIRST + 28, FPR_FIRST + 29, FPR_FIRST + 30, FPR_FIRST + 31, \
+ FPR_FIRST + 48, FPR_FIRST + 49, FPR_FIRST + 50, FPR_FIRST + 51, \
+ FPR_FIRST + 52, FPR_FIRST + 53, FPR_FIRST + 54, FPR_FIRST + 55, \
+ FPR_FIRST + 56, FPR_FIRST + 57, FPR_FIRST + 58, FPR_FIRST + 59, \
+ FPR_FIRST + 60, FPR_FIRST + 61, FPR_FIRST + 62, FPR_FIRST + 63, \
+ \
+ /* special or fixed registers */ \
+ GPR_FIRST + 0, GPR_FIRST + 1, GPR_FIRST + 2, GPR_FIRST + 3, \
+ GPR_FIRST + 28, GPR_FIRST + 29, GPR_FIRST + 30, GPR_FIRST + 31, \
+ ACC_FIRST + 0, ACC_FIRST + 1, ACC_FIRST + 2, ACC_FIRST + 3, \
+ ACC_FIRST + 4, ACC_FIRST + 5, ACC_FIRST + 6, ACC_FIRST + 7, \
+ ACCG_FIRST + 0, ACCG_FIRST + 1, ACCG_FIRST + 2, ACCG_FIRST + 3, \
+ ACCG_FIRST + 4, ACCG_FIRST + 5, ACCG_FIRST + 6, ACCG_FIRST + 7, \
+ AP_FIRST, LR_REGNO, LCR_REGNO \
+}
+
+
+/* How Values Fit in Registers. */
+
+/* A C expression for the number of consecutive hard registers, starting at
+ register number REGNO, required to hold a value of mode MODE.
+
+ On a machine where all registers are exactly one word, a suitable definition
+ of this macro is
+
+ #define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
+ / UNITS_PER_WORD)) */
+
+/* On the FRV, make the CC modes take 3 words in the integer registers, so that
+ we can build the appropriate instructions to properly reload the values. */
+#define HARD_REGNO_NREGS(REGNO, MODE) frv_hard_regno_nregs (REGNO, MODE)
+
+/* A C expression that is nonzero if it is permissible to store a value of mode
+ MODE in hard register number REGNO (or in several registers starting with
+ that one). For a machine where all registers are equivalent, a suitable
+ definition is
+
+ #define HARD_REGNO_MODE_OK(REGNO, MODE) 1
+
+ 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.
+
+ 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.
+
+ The minimum requirement for a mode to be OK in a register is that the
+ `movMODE' 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.
+
+ Since the same instruction used to move `SImode' will work for all narrower
+ integer modes, it is not necessary on any machine for `HARD_REGNO_MODE_OK'
+ to distinguish between these modes, provided you define patterns `movhi',
+ etc., to take advantage of this. This is useful because of the interaction
+ between `HARD_REGNO_MODE_OK' and `MODES_TIEABLE_P'; it is very desirable for
+ all integer modes to be tieable.
+
+ Many machines have special registers for floating point arithmetic. Often
+ people assume that floating point machine modes are allowed only in floating
+ point registers. This is not true. Any registers that can hold integers
+ can safely *hold* a floating point machine mode, whether or not floating
+ arithmetic can be done on it in those registers. Integer move instructions
+ can be used to move the values.
+
+ On some machines, though, the converse is true: fixed-point machine modes
+ may not go in floating registers. This is true if the floating registers
+ normalize any value stored in them, because storing a non-floating value
+ there would garble it. In this case, `HARD_REGNO_MODE_OK' should reject
+ fixed-point machine modes in floating registers. But if the floating
+ registers do not automatically normalize, if you can store any bit pattern
+ in one and retrieve it unchanged without a trap, then any machine mode may
+ go in a floating register, so you can define this macro to say so.
+
+ The primary significance of special floating registers is rather that they
+ are the registers acceptable in floating point arithmetic instructions.
+ However, this is of no concern to `HARD_REGNO_MODE_OK'. You handle it by
+ writing the proper constraints for those instructions.
+
+ On some machines, the floating registers are especially slow to access, so
+ that it is better to store a value in a stack frame than in such a register
+ if floating point arithmetic is not being done. As long as the floating
+ registers are not in class `GENERAL_REGS', they will not be used unless some
+ pattern's constraint asks for one. */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) frv_hard_regno_mode_ok (REGNO, MODE)
+
+/* 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 MODE1
+ and a value of mode MODE2.
+
+ If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, MODE2)' are
+ ever different for any R, then `MODES_TIEABLE_P (MODE1, MODE2)' must be
+ zero. */
+#define MODES_TIEABLE_P(MODE1, MODE2) (MODE1 == MODE2)
+
+/* Define this macro if the compiler should avoid copies to/from CCmode
+ registers. You should only define this macro if support fo copying to/from
+ CCmode is incomplete. */
+#define AVOID_CCMODE_COPIES
+
+
+/* Register Classes. */
+
+/* An enumeral type that must be defined with all the register class names as
+ enumeral values. `NO_REGS' must be first. `ALL_REGS' must be the last
+ register class, followed by one more enumeral value, `LIM_REG_CLASSES',
+ which is not a register class but rather tells how many classes there are.
+
+ Each register class has a number, which is the value of casting the class
+ name to type `int'. The number serves as an index in many of the tables
+ described below. */
+enum reg_class
+{
+ NO_REGS,
+ ICC_REGS,
+ FCC_REGS,
+ CC_REGS,
+ ICR_REGS,
+ FCR_REGS,
+ CR_REGS,
+ LCR_REG,
+ LR_REG,
+ SPR_REGS,
+ QUAD_ACC_REGS,
+ EVEN_ACC_REGS,
+ ACC_REGS,
+ ACCG_REGS,
+ QUAD_FPR_REGS,
+ FEVEN_REGS,
+ FPR_REGS,
+ QUAD_REGS,
+ EVEN_REGS,
+ GPR_REGS,
+ ALL_REGS,
+ LIM_REG_CLASSES
+};
+
+#define GENERAL_REGS GPR_REGS
+
+/* The number of distinct register classes, defined as follows:
+
+ #define N_REG_CLASSES (int) LIM_REG_CLASSES */
+#define N_REG_CLASSES ((int) LIM_REG_CLASSES)
+
+/* An initializer containing the names of the register classes as C string
+ constants. These names are used in writing some of the debugging dumps. */
+#define REG_CLASS_NAMES { \
+ "NO_REGS", \
+ "ICC_REGS", \
+ "FCC_REGS", \
+ "CC_REGS", \
+ "ICR_REGS", \
+ "FCR_REGS", \
+ "CR_REGS", \
+ "LCR_REG", \
+ "LR_REG", \
+ "SPR_REGS", \
+ "QUAD_ACC_REGS", \
+ "EVEN_ACC_REGS", \
+ "ACC_REGS", \
+ "ACCG_REGS", \
+ "QUAD_FPR_REGS", \
+ "FEVEN_REGS", \
+ "FPR_REGS", \
+ "QUAD_REGS", \
+ "EVEN_REGS", \
+ "GPR_REGS", \
+ "ALL_REGS" \
+}
+
+/* An initializer containing the contents of the register classes, as integers
+ which are bit masks. The Nth integer specifies the contents of class N.
+ The way the integer MASK is interpreted is that register R is in the class
+ if `MASK & (1 << R)' is 1.
+
+ When the machine has more than 32 registers, an integer does not suffice.
+ 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 `HARD_REG_SET' which is defined in
+ `hard-reg-set.h'. */
+#define REG_CLASS_CONTENTS \
+{ /* gr0-gr31 gr32-gr63 fr0-fr31 fr32-fr-63 cc/ccr/acc ap/spr */ \
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x0}, /* NO_REGS */\
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0x000000f0,0x0}, /* ICC_REGS */\
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0x0000000f,0x0}, /* FCC_REGS */\
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0x000000ff,0x0}, /* CC_REGS */\
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0x0000f000,0x0}, /* ICR_REGS */\
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0x00000f00,0x0}, /* FCR_REGS */\
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0x0000ff00,0x0}, /* CR_REGS */\
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x4}, /* LCR_REGS */\
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x2}, /* LR_REGS */\
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x6}, /* SPR_REGS */\
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0x00ff0000,0x0}, /* QUAD_ACC */\
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0x00ff0000,0x0}, /* EVEN_ACC */\
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0x00ff0000,0x0}, /* ACC_REGS */\
+ { 0x00000000,0x00000000,0x00000000,0x00000000,0xff000000,0x0}, /* ACCG_REGS*/\
+ { 0x00000000,0x00000000,0xffffffff,0xffffffff,0x00000000,0x0}, /* QUAD_FPR */\
+ { 0x00000000,0x00000000,0xffffffff,0xffffffff,0x00000000,0x0}, /* FEVEN_REG*/\
+ { 0x00000000,0x00000000,0xffffffff,0xffffffff,0x00000000,0x0}, /* FPR_REGS */\
+ { 0x0ffffffc,0xffffffff,0x00000000,0x00000000,0x00000000,0x0}, /* QUAD_REGS*/\
+ { 0xfffffffc,0xffffffff,0x00000000,0x00000000,0x00000000,0x0}, /* EVEN_REGS*/\
+ { 0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000,0x1}, /* GPR_REGS */\
+ { 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0x7}, /* ALL_REGS */\
+}
+
+/* A C expression whose value is a register class containing hard register
+ REGNO. In general there is more than one such class; choose a class which
+ is "minimal", meaning that no smaller class also contains the register. */
+
+extern enum reg_class regno_reg_class[];
+#define REGNO_REG_CLASS(REGNO) regno_reg_class [REGNO]
+
+/* A macro whose definition is the name of the class to which a valid base
+ register must belong. A base register is one used in an address which is
+ the register value plus a displacement. */
+#define BASE_REG_CLASS GPR_REGS
+
+/* A macro whose definition is the name of the class to which a valid index
+ register must belong. An index register is one used in an address where its
+ value is either multiplied by a scale factor or added to another register
+ (as well as added to a displacement). */
+#define INDEX_REG_CLASS GPR_REGS
+
+/* A C expression which defines the machine-dependent operand constraint
+ letters for register classes. If CHAR is such a letter, the value should be
+ the register class corresponding to it. Otherwise, the value should be
+ `NO_REGS'. The register letter `r', corresponding to class `GENERAL_REGS',
+ will not be passed to this macro; you do not need to handle it.
+
+ The following letters are unavailable, due to being used as
+ constraints:
+ '0'..'9'
+ '<', '>'
+ 'E', 'F', 'G', 'H'
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'
+ 'Q', 'R', 'S', 'T', 'U'
+ 'V', 'X'
+ 'g', 'i', 'm', 'n', 'o', 'p', 'r', 's' */
+
+extern enum reg_class reg_class_from_letter[];
+#define REG_CLASS_FROM_LETTER(CHAR) reg_class_from_letter [(unsigned char)(CHAR)]
+
+/* A C expression which is nonzero if register number NUM is 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. */
+#define REGNO_OK_FOR_BASE_P(NUM) \
+ ((NUM) < FIRST_PSEUDO_REGISTER \
+ ? GPR_P (NUM) \
+ : (reg_renumber [NUM] >= 0 && GPR_P (reg_renumber [NUM])))
+
+/* A C expression which is nonzero if register number NUM is suitable for use
+ as an index register in operand addresses. It may be either a suitable hard
+ register or a pseudo register that has been allocated such a hard register.
+
+ The difference between an index register and a base register is that the
+ index register may be scaled. If an address involves the sum of two
+ registers, neither one of them scaled, then either one may be labeled the
+ "base" and the other the "index"; but whichever labeling is used must fit
+ the machine's constraints of which registers may serve in each capacity.
+ The compiler will try both labelings, looking for one that is valid, and
+ will reload one or both registers only if neither labeling works. */
+#define REGNO_OK_FOR_INDEX_P(NUM) \
+ ((NUM) < FIRST_PSEUDO_REGISTER \
+ ? GPR_P (NUM) \
+ : (reg_renumber [NUM] >= 0 && GPR_P (reg_renumber [NUM])))
+
+/* A C expression that places additional restrictions on the register class to
+ use when it is necessary to copy value X into a register in class CLASS.
+ The value is a register class; perhaps CLASS, or perhaps another, smaller
+ class. On many machines, the following definition is safe:
+
+ #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
+
+ Sometimes returning a more restrictive class makes better code. For
+ example, on the 68000, when X is an integer constant that is in range for a
+ `moveq' instruction, the value of this macro is always `DATA_REGS' as long
+ as CLASS includes the data registers. Requiring a data register guarantees
+ that a `moveq' will be used.
+
+ If X is a `const_double', by returning `NO_REGS' you can force X into a
+ memory constant. This is useful on certain machines where immediate
+ floating values cannot be loaded into certain kinds of registers.
+
+ This declaration must be present. */
+#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS
+
+#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
+ frv_secondary_reload_class (CLASS, MODE, X, TRUE)
+
+#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
+ frv_secondary_reload_class (CLASS, MODE, X, FALSE)
+
+/* A C expression whose value is nonzero if pseudos that have been assigned to
+ registers of class CLASS would likely be spilled because registers of CLASS
+ are needed for spill registers.
+
+ The default value of this macro returns 1 if CLASS has exactly one register
+ and zero otherwise. On most machines, this default should be used. Only
+ define this macro to some other expression if pseudo allocated by
+ `local-alloc.c' end up in memory because their hard registers were needed
+ for spill registers. If this macro returns nonzero for those classes, those
+ pseudos will only be allocated by `global.c', which knows how to reallocate
+ the pseudo to another register. If there would not be another register
+ available for reallocation, you should not change the definition of this
+ macro since the only effect of such a definition would be to slow down
+ register allocation. */
+#define CLASS_LIKELY_SPILLED_P(CLASS) frv_class_likely_spilled_p (CLASS)
+
+/* A C expression for the maximum number of consecutive registers of
+ class CLASS needed to hold a value of mode MODE.
+
+ This is closely related to the macro `HARD_REGNO_NREGS'. In fact, the value
+ of the macro `CLASS_MAX_NREGS (CLASS, MODE)' should be the maximum value of
+ `HARD_REGNO_NREGS (REGNO, MODE)' for all REGNO values in the class CLASS.
+
+ This macro helps control the handling of multiple-word values in
+ the reload pass.
+
+ This declaration is required. */
+#define CLASS_MAX_NREGS(CLASS, MODE) frv_class_max_nregs (CLASS, MODE)
+
+#define ZERO_P(x) (x == CONST0_RTX (GET_MODE (x)))
+
+/* 6 bit signed immediate. */
+#define CONST_OK_FOR_I(VALUE) IN_RANGE_P(VALUE, -32, 31)
+/* 10 bit signed immediate. */
+#define CONST_OK_FOR_J(VALUE) IN_RANGE_P(VALUE, -512, 511)
+/* Unused */
+#define CONST_OK_FOR_K(VALUE) 0
+/* 16 bit signed immediate. */
+#define CONST_OK_FOR_L(VALUE) IN_RANGE_P(VALUE, -32768, 32767)
+/* 16 bit unsigned immediate. */
+#define CONST_OK_FOR_M(VALUE) IN_RANGE_P (VALUE, 0, 65535)
+/* 12 bit signed immediate that is negative. */
+#define CONST_OK_FOR_N(VALUE) IN_RANGE_P(VALUE, -2048, -1)
+/* Zero */
+#define CONST_OK_FOR_O(VALUE) ((VALUE) == 0)
+/* 12 bit signed immediate that is negative. */
+#define CONST_OK_FOR_P(VALUE) IN_RANGE_P(VALUE, 1, 2047)
+
+/* A C expression that defines the machine-dependent operand constraint letters
+ (`I', `J', `K', .. 'P') that specify particular ranges of integer values.
+ If C is one of those letters, the expression should check that VALUE, an
+ integer, is in the appropriate range and return 1 if so, 0 otherwise. If C
+ is not one of those letters, the value should be 0 regardless of VALUE. */
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+ ( (C) == 'I' ? CONST_OK_FOR_I (VALUE) \
+ : (C) == 'J' ? CONST_OK_FOR_J (VALUE) \
+ : (C) == 'K' ? CONST_OK_FOR_K (VALUE) \
+ : (C) == 'L' ? CONST_OK_FOR_L (VALUE) \
+ : (C) == 'M' ? CONST_OK_FOR_M (VALUE) \
+ : (C) == 'N' ? CONST_OK_FOR_N (VALUE) \
+ : (C) == 'O' ? CONST_OK_FOR_O (VALUE) \
+ : (C) == 'P' ? CONST_OK_FOR_P (VALUE) \
+ : 0)
+
+
+/* A C expression that defines the machine-dependent operand constraint letters
+ (`G', `H') that specify particular ranges of `const_double' values.
+
+ If C is one of those letters, the expression should check that VALUE, an RTX
+ of code `const_double', is in the appropriate range and return 1 if so, 0
+ otherwise. If C is not one of those letters, the value should be 0
+ regardless of VALUE.
+
+ `const_double' is used for all floating-point constants and for `DImode'
+ fixed-point constants. A given letter can accept either or both kinds of
+ values. It can use `GET_MODE' to distinguish between these kinds. */
+
+#define CONST_DOUBLE_OK_FOR_G(VALUE) \
+ ((GET_MODE (VALUE) == VOIDmode \
+ && CONST_DOUBLE_LOW (VALUE) == 0 \
+ && CONST_DOUBLE_HIGH (VALUE) == 0) \
+ || ((GET_MODE (VALUE) == SFmode \
+ || GET_MODE (VALUE) == DFmode) \
+ && (VALUE) == CONST0_RTX (GET_MODE (VALUE))))
+
+#define CONST_DOUBLE_OK_FOR_H(VALUE) 0
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+ ( (C) == 'G' ? CONST_DOUBLE_OK_FOR_G (VALUE) \
+ : (C) == 'H' ? CONST_DOUBLE_OK_FOR_H (VALUE) \
+ : 0)
+
+/* A C expression that defines the optional machine-dependent constraint
+ letters (`Q', `R', `S', `T', `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 VALUE corresponds to the operand type
+ represented by the constraint letter C. If C is not defined as an extra
+ constraint, the value returned should be 0 regardless of VALUE.
+
+ For example, on the ROMP, load instructions cannot have their output in r0
+ if the memory reference contains a symbolic address. Constraint letter `Q'
+ is defined as representing a memory address that does *not* contain a
+ symbolic address. An alternative is specified with a `Q' constraint on the
+ input and `r' on the output. The next alternative specifies `m' on the
+ input and a register class that does not include r0 on the output. */
+
+/* Small data references */
+#define EXTRA_CONSTRAINT_FOR_Q(VALUE) \
+ (small_data_symbolic_operand (VALUE, GET_MODE (VALUE)))
+
+/* Double word memory ops that take one instruction. */
+#define EXTRA_CONSTRAINT_FOR_R(VALUE) \
+ (dbl_memory_one_insn_operand (VALUE, GET_MODE (VALUE)))
+
+/* SYMBOL_REF */
+#define EXTRA_CONSTRAINT_FOR_S(VALUE) (GET_CODE (VALUE) == SYMBOL_REF)
+
+/* Double word memory ops that take two instructions. */
+#define EXTRA_CONSTRAINT_FOR_T(VALUE) \
+ (dbl_memory_two_insn_operand (VALUE, GET_MODE (VALUE)))
+
+/* Memory operand for conditional execution. */
+#define EXTRA_CONSTRAINT_FOR_U(VALUE) \
+ (condexec_memory_operand (VALUE, GET_MODE (VALUE)))
+
+#define EXTRA_CONSTRAINT(VALUE, C) \
+ ( (C) == 'Q' ? EXTRA_CONSTRAINT_FOR_Q (VALUE) \
+ : (C) == 'R' ? EXTRA_CONSTRAINT_FOR_R (VALUE) \
+ : (C) == 'S' ? EXTRA_CONSTRAINT_FOR_S (VALUE) \
+ : (C) == 'T' ? EXTRA_CONSTRAINT_FOR_T (VALUE) \
+ : (C) == 'U' ? EXTRA_CONSTRAINT_FOR_U (VALUE) \
+ : 0)
+
+
+/* Basic Stack Layout. */
+
+/* Structure to describe information about a saved range of registers */
+
+typedef struct frv_stack_regs {
+ const char * name; /* name of the register ranges */
+ int first; /* first register in the range */
+ int last; /* last register in the range */
+ int size_1word; /* # of bytes to be stored via 1 word stores */
+ int size_2words; /* # of bytes to be stored via 2 word stores */
+ unsigned char field_p; /* true if the registers are a single SPR */
+ unsigned char dword_p; /* true if we can do dword stores */
+ unsigned char special_p; /* true if the regs have a fixed save loc. */
+} frv_stack_regs_t;
+
+/* Register ranges to look into saving. */
+#define STACK_REGS_GPR 0 /* Gprs (normally gr16..gr31, gr48..gr63) */
+#define STACK_REGS_FPR 1 /* Fprs (normally fr16..fr31, fr48..fr63) */
+#define STACK_REGS_LR 2 /* LR register */
+#define STACK_REGS_CC 3 /* CCrs (normally not saved) */
+#define STACK_REGS_LCR 5 /* lcr register */
+#define STACK_REGS_STDARG 6 /* stdarg registers */
+#define STACK_REGS_STRUCT 7 /* structure return (gr3) */
+#define STACK_REGS_FP 8 /* FP register */
+#define STACK_REGS_MAX 9 /* # of register ranges */
+
+/* Values for save_p field. */
+#define REG_SAVE_NO_SAVE 0 /* register not saved */
+#define REG_SAVE_1WORD 1 /* save the register */
+#define REG_SAVE_2WORDS 2 /* save register and register+1 */
+
+/* Structure used to define the frv stack. */
+
+typedef struct frv_stack {
+ int total_size; /* total bytes allocated for stack */
+ int vars_size; /* variable save area size */
+ int parameter_size; /* outgoing parameter size */
+ int stdarg_size; /* size of regs needed to be saved for stdarg */
+ int regs_size; /* size of the saved registers */
+ int regs_size_1word; /* # of bytes to be stored via 1 word stores */
+ int regs_size_2words; /* # of bytes to be stored via 2 word stores */
+ int header_size; /* size of the old FP, struct ret., LR save */
+ int pretend_size; /* size of pretend args */
+ int vars_offset; /* offset to save local variables from new SP*/
+ int regs_offset; /* offset to save registers from new SP */
+ /* register range information */
+ frv_stack_regs_t regs[STACK_REGS_MAX];
+ /* offset to store each register */
+ int reg_offset[FIRST_PSEUDO_REGISTER];
+ /* whether to save register (& reg+1) */
+ unsigned char save_p[FIRST_PSEUDO_REGISTER];
+} frv_stack_t;
+
+/* Define this macro if pushing a word onto the stack moves the stack pointer
+ to a smaller address. */
+#define STACK_GROWS_DOWNWARD 1
+
+/* Define this macro if the addresses of local variable slots are at negative
+ offsets from the frame pointer. */
+#define FRAME_GROWS_DOWNWARD
+
+/* Offset from the frame pointer to the first local variable slot to be
+ allocated.
+
+ If `FRAME_GROWS_DOWNWARD', find the next slot's offset by subtracting the
+ first slot's length from `STARTING_FRAME_OFFSET'. Otherwise, it is found by
+ adding the length of the first slot to the value `STARTING_FRAME_OFFSET'. */
+#define STARTING_FRAME_OFFSET 0
+
+/* Offset from the stack pointer register to the first location at which
+ outgoing arguments are placed. If not specified, the default value of zero
+ is used. This is the proper value for most machines.
+
+ If `ARGS_GROW_DOWNWARD', this is the offset to the location above the first
+ location at which outgoing arguments are placed. */
+#define STACK_POINTER_OFFSET 0
+
+/* 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.
+
+ If `ARGS_GROW_DOWNWARD', this is the offset to the location above the first
+ argument's address. */
+#define FIRST_PARM_OFFSET(FUNDECL) 0
+
+/* A C expression whose value is RTL representing the address in a stack frame
+ where the pointer to the caller's frame is stored. Assume that FRAMEADDR is
+ an RTL expression for the address of the stack frame itself.
+
+ If you don't define this macro, the default is to return the value of
+ FRAMEADDR--that is, the stack frame address is also the address of the stack
+ word that points to the previous frame. */
+#define DYNAMIC_CHAIN_ADDRESS(FRAMEADDR) frv_dynamic_chain_address (FRAMEADDR)
+
+/* A C expression whose value is RTL representing the value of 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, or the frame
+ pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is
+ defined.
+
+ The value of the expression must always be the correct address when COUNT is
+ zero, but may be `NULL_RTX' if there is not way to determine the return
+ address of other frames. */
+#define RETURN_ADDR_RTX(COUNT, FRAMEADDR) frv_return_addr_rtx (COUNT, FRAMEADDR)
+
+/* This function contains machine specific function data. */
+struct machine_function GTY(())
+{
+ /* True if we have created an rtx that relies on the stack frame. */
+ int frame_needed;
+};
+
+#define RETURN_POINTER_REGNUM LR_REGNO
+
+/* 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 `REG', indicating that the return value is saved in `REG',
+ or a `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. */
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (SImode, RETURN_POINTER_REGNUM)
+
+
+/* Register That Address the Stack Frame. */
+
+/* The register number of the stack pointer register, which must also be a
+ fixed register according to `FIXED_REGISTERS'. On most machines, the
+ hardware determines which register this is. */
+#define STACK_POINTER_REGNUM (GPR_FIRST + 1)
+
+/* The register number of the frame pointer register, which is used to access
+ automatic variables in the stack frame. On some machines, the hardware
+ determines which register this is. On other machines, you can choose any
+ register you wish for this purpose. */
+#define FRAME_POINTER_REGNUM (GPR_FIRST + 2)
+
+/* The register number of the arg pointer register, which is used to access the
+ function's argument list. On some machines, this is the same as the frame
+ pointer register. On some machines, the hardware determines which register
+ this is. On other machines, you can choose any register you wish for this
+ purpose. If this is not the same register as the frame pointer register,
+ then you must mark it as a fixed register according to `FIXED_REGISTERS', or
+ arrange to be able to eliminate it. */
+
+/* On frv this is a fake register that is eliminated in
+ terms of either the frame pointer or stack pointer. */
+#define ARG_POINTER_REGNUM AP_FIRST
+
+/* Register numbers used for passing a function's static chain pointer. If
+ register windows are used, the register number as seen by the called
+ function is `STATIC_CHAIN_INCOMING_REGNUM', while the register number as
+ seen by the calling function is `STATIC_CHAIN_REGNUM'. If these registers
+ are the same, `STATIC_CHAIN_INCOMING_REGNUM' need not be defined.
+
+ The static chain register need not be a fixed register.
+
+ If the static chain is passed in memory, these macros should not be defined;
+ instead, the next two macros should be defined. */
+#define STATIC_CHAIN_REGNUM (GPR_FIRST + 7)
+#define STATIC_CHAIN_INCOMING_REGNUM (GPR_FIRST + 7)
+
+
+/* Eliminating the Frame Pointer and the Arg Pointer. */
+
+/* A C expression which is nonzero if a function must have and use a frame
+ pointer. This expression is evaluated in the reload pass. If its value is
+ nonzero the function will have a frame pointer.
+
+ The expression can in principle examine the current function and decide
+ according to the facts, but on most machines the constant 0 or the constant
+ 1 suffices. Use 0 when the machine allows code to be generated with no
+ frame pointer, and doing so saves some time or space. Use 1 when there is
+ no possible advantage to avoiding a frame pointer.
+
+ In certain cases, the compiler does not know how to produce valid code
+ without a frame pointer. The compiler recognizes those cases and
+ automatically gives the function a frame pointer regardless of what
+ `FRAME_POINTER_REQUIRED' says. You don't need to worry about them.
+
+ In a function that does not require a frame pointer, the frame pointer
+ register can be allocated for ordinary usage, unless you mark it as a fixed
+ register. See `FIXED_REGISTERS' for more information. */
+#define FRAME_POINTER_REQUIRED frv_frame_pointer_required ()
+
+/* 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 is to replace references to
+ the frame pointer with references to the stack pointer.
+
+ The definition of this macro is a list of structure initializations, each of
+ which specifies an original and replacement register.
+
+ On some machines, the position of the argument pointer is not known until
+ the compilation is completed. In such a case, a separate hard register must
+ be used for the argument pointer. This register can be eliminated by
+ replacing it with either the frame pointer or the argument pointer,
+ depending on whether or not the frame pointer has been eliminated.
+
+ In this case, you might specify:
+ #define ELIMINABLE_REGS \
+ {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
+ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
+
+ Note that the elimination of the argument pointer with the stack pointer is
+ specified first since that is the preferred elimination. */
+
+#define ELIMINABLE_REGS \
+{ \
+ {ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
+ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM} \
+}
+
+/* A C expression that returns nonzero if the compiler is allowed to try to
+ replace register number FROM with register number TO. This macro need only
+ be defined if `ELIMINABLE_REGS' is defined, and will usually be the constant
+ 1, since most of the cases preventing register elimination are things that
+ the compiler already knows about. */
+
+#define CAN_ELIMINATE(FROM, TO) \
+ ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM \
+ ? ! frame_pointer_needed \
+ : 1)
+
+/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It specifies the
+ initial difference between the specified pair of registers. This macro must
+ be defined if `ELIMINABLE_REGS' is defined. */
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+ (OFFSET) = frv_initial_elimination_offset (FROM, TO)
+
+
+/* Passing Function Arguments on the Stack. */
+
+/* If defined, the maximum amount of space required for outgoing arguments will
+ be computed and placed into the variable
+ `current_function_outgoing_args_size'. No space will be pushed onto the
+ stack for each call; instead, the function prologue should increase the
+ stack frame size by this amount.
+
+ Defining both `PUSH_ROUNDING' and `ACCUMULATE_OUTGOING_ARGS' is not
+ proper. */
+#define ACCUMULATE_OUTGOING_ARGS 1
+
+/* A C expression that should indicate the number of bytes of its own 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.
+
+ FUNDECL is a C variable whose value is a tree node that describes the
+ function in question. Normally it is a node of type `FUNCTION_DECL' that
+ describes the declaration of the function. From this it is possible to
+ obtain the DECL_ATTRIBUTES of the function.
+
+ FUNTYPE is a C variable whose value is a tree node that describes the
+ function in question. Normally it is a node of type `FUNCTION_TYPE' that
+ describes the data type of the function. 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, FUNTYPE 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 a function used to
+ perform arithmetic, whose name is known specially in the compiler and was
+ not mentioned in the C code being compiled.
+
+ STACK-SIZE is the number of bytes of arguments passed on the stack. If a
+ variable number of bytes is passed, it is zero, and argument popping will
+ always be the responsibility of the calling function.
+
+ On the VAX, all functions always pop their arguments, so the definition of
+ this macro is STACK-SIZE. On the 68000, using the standard calling
+ convention, no functions pop their arguments, so the value of the macro is
+ always 0 in this case. But an alternative calling convention is available
+ in which functions that take a fixed number of arguments pop them but other
+ functions (such as `printf') pop nothing (the caller pops all). When this
+ convention is in use, FUNTYPE is examined to determine whether a function
+ takes a fixed number of arguments. */
+#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
+
+
+/* Function Arguments in Registers. */
+
+/* Nonzero if we do not know how to pass TYPE solely in registers.
+ We cannot do so in the following cases:
+
+ - if the type has variable size
+ - if the type is marked as addressable (it is required to be constructed
+ into the stack)
+ - if the type is a structure or union. */
+
+#define MUST_PASS_IN_STACK(MODE,TYPE) \
+ (((MODE) == BLKmode) \
+ || ((TYPE) != 0 \
+ && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
+ || TREE_CODE (TYPE) == RECORD_TYPE \
+ || TREE_CODE (TYPE) == UNION_TYPE \
+ || TREE_CODE (TYPE) == QUAL_UNION_TYPE \
+ || TREE_ADDRESSABLE (TYPE))))
+
+/* The number of register assigned to holding function arguments. */
+
+#define FRV_NUM_ARG_REGS 6
+
+/* A C expression that controls whether a function argument is passed in a
+ register, and which register.
+
+ The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes (in a way
+ defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE) all of the previous
+ arguments so far passed in registers; MODE, the machine mode of the argument;
+ TYPE, the data type of the argument as a tree node or 0 if that is not known
+ (which happens for C support library functions); and NAMED, which is 1 for an
+ ordinary argument and 0 for nameless arguments that correspond to `...' in the
+ called function's prototype.
+
+ The value of the expression should either be a `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 usual way to make the ANSI library `stdarg.h' work on a machine where
+ some arguments are usually passed in registers, is to cause nameless
+ arguments to be passed on the stack instead. This is done by making
+ `FUNCTION_ARG' return 0 whenever NAMED is 0.
+
+ You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of
+ this macro to determine if this argument is of a type that must be passed in
+ the stack. If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG'
+ returns nonzero for such an argument, the compiler will abort. If
+ `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the
+ stack and then loaded into a register. */
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+ frv_function_arg (&CUM, MODE, TYPE, NAMED, FALSE)
+
+/* Define this macro if the target machine has "register windows", so that the
+ register in which a function sees an arguments is not necessarily the same
+ as the one in which the caller passed the argument.
+
+ For such machines, `FUNCTION_ARG' computes the register in which the caller
+ passes the value, and `FUNCTION_INCOMING_ARG' should be defined in a similar
+ fashion to tell the function being called where the arguments will arrive.
+
+ If `FUNCTION_INCOMING_ARG' is not defined, `FUNCTION_ARG' serves both
+ purposes. */
+
+#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
+ frv_function_arg (&CUM, MODE, TYPE, NAMED, TRUE)
+
+/* A C expression for the number of words, at the beginning of an argument,
+ must be put in registers. The value must be zero for arguments that are
+ passed entirely in registers or that are entirely pushed on the stack.
+
+ On some machines, certain arguments must be passed partially in registers
+ and partially in memory. On these machines, typically the first N words of
+ arguments are passed in registers, and the rest on the stack. If a
+ multi-word argument (a `double' or a structure) crosses that boundary, its
+ first few words must be passed in registers and the rest must be pushed.
+ This macro tells the compiler when this occurs, and how many of the words
+ should go in registers.
+
+ `FUNCTION_ARG' for these arguments should return the first register to be
+ used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for
+ the called function. */
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+ frv_function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED)
+
+/* extern int frv_function_arg_partial_nregs PARAMS ((CUMULATIVE_ARGS, int, Tree, int)); */
+
+/* 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.
+
+ On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable
+ definition of this macro might be
+ #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
+ MUST_PASS_IN_STACK (MODE, TYPE) */
+#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
+ frv_function_arg_pass_by_reference (&CUM, MODE, TYPE, NAMED)
+
+/* If defined, 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. */
+#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \
+ frv_function_arg_callee_copies (&CUM, MODE, TYPE, NAMED)
+
+/* If defined, a C expression that indicates when it is more desirable to keep
+ an argument passed by invisible reference as a reference, rather than
+ copying it to a pseudo register. */
+#define FUNCTION_ARG_KEEP_AS_REFERENCE(CUM, MODE, TYPE, NAMED) \
+ frv_function_arg_keep_as_reference (&CUM, MODE, TYPE, NAMED)
+
+/* A C type for declaring a variable that is used as the first argument of
+ `FUNCTION_ARG' and other related values. For some target machines, the type
+ `int' suffices and can hold the number of bytes of argument so far.
+
+ There is no need to record in `CUMULATIVE_ARGS' anything about the arguments
+ that have been passed on the stack. The compiler has other variables to
+ keep track of that. For target machines on which all arguments are passed
+ on the stack, there is no need to store anything in `CUMULATIVE_ARGS';
+ however, the data structure must exist and should not be empty, so use
+ `int'. */
+#define CUMULATIVE_ARGS int
+
+/* A C statement (sans semicolon) for initializing the variable CUM for the
+ state at the beginning of the argument list. The variable has type
+ `CUMULATIVE_ARGS'. The value of 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. The value of INDIRECT is nonzero when
+ processing an indirect call, for example a call through a function pointer.
+ The value of INDIRECT is zero for a call to an explicitly named function, a
+ library function call, or when `INIT_CUMULATIVE_ARGS' is used to find
+ arguments for the function being compiled.
+
+ When processing a call to a compiler support library function, LIBNAME
+ identifies which one. It is a `symbol_ref' rtx which contains the name of
+ the function, as a string. LIBNAME is 0 when an ordinary C function call is
+ being processed. Thus, each time this macro is called, either LIBNAME or
+ FNTYPE is nonzero, but never both of them at once. */
+
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
+ frv_init_cumulative_args (&CUM, FNTYPE, LIBNAME, INDIRECT, FALSE)
+
+/* Like `INIT_CUMULATIVE_ARGS' but overrides it for the purposes of finding the
+ arguments for the function being compiled. If this macro is undefined,
+ `INIT_CUMULATIVE_ARGS' is used instead.
+
+ The value passed for LIBNAME is always 0, since library routines with
+ special calling conventions are never compiled with GNU CC. The argument
+ LIBNAME exists for symmetry with `INIT_CUMULATIVE_ARGS'. */
+
+#define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \
+ frv_init_cumulative_args (&CUM, FNTYPE, LIBNAME, FALSE, TRUE)
+
+/* A C statement (sans semicolon) to update the summarizer variable CUM to
+ advance past an argument in the argument list. The values MODE, TYPE and
+ NAMED describe that argument. Once this is done, the variable CUM is
+ suitable for analyzing the *following* argument with `FUNCTION_ARG', etc.
+
+ This macro need not do anything if the argument in question was passed on
+ the stack. The compiler knows how to track the amount of stack space used
+ for arguments without any special help. */
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ frv_function_arg_advance (&CUM, MODE, TYPE, NAMED)
+
+/* 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) \
+ frv_function_arg_boundary (MODE, TYPE)
+
+/* A C expression that is nonzero if REGNO is the number of a hard register in
+ which function arguments are sometimes passed. This does *not* include
+ implicit arguments such as the static chain and the structure-value address.
+ On many machines, no registers can be used for this purpose since all
+ function arguments are pushed on the stack. */
+#define FUNCTION_ARG_REGNO_P(REGNO) \
+ ((REGNO) >= FIRST_ARG_REGNUM && ((REGNO) <= LAST_ARG_REGNUM))
+
+
+/* How Scalar Function Values are Returned. */
+
+/* The number of the hard register that is used to return a scalar value from a
+ function call. */
+#define RETURN_VALUE_REGNUM (GPR_FIRST + 8)
+
+/* A C expression to create an RTX representing the place where a function
+ returns a value of data type VALTYPE. VALTYPE is a tree node representing a
+ data type. Write `TYPE_MODE (VALTYPE)' to get the machine mode used to
+ represent that type. On many machines, only the mode is relevant.
+ (Actually, on most machines, scalar values are returned in the same place
+ regardless of mode).
+
+ If `PROMOTE_FUNCTION_RETURN' is defined, you must apply the same promotion
+ rules specified in `PROMOTE_MODE' if VALTYPE is a scalar type.
+
+ If the precise function being called is known, FUNC is a tree node
+ (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer. This makes it
+ possible to use a different value-returning convention for specific
+ functions when all their calls are known.
+
+ `FUNCTION_VALUE' is not used for return vales with aggregate data types,
+ because these are returned in another way. See `STRUCT_VALUE_REGNUM' and
+ related macros, below. */
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), RETURN_VALUE_REGNUM)
+
+/* A C expression to create an RTX representing the place where a library
+ function returns a value of mode MODE.
+
+ Note that "library function" in this context means a compiler support
+ routine, used to perform arithmetic, whose name is known specially by the
+ compiler and was not mentioned in the C code being compiled.
+
+ The definition of `LIBRARY_VALUE' need not be concerned aggregate data
+ types, because none of the library functions returns such types. */
+#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, RETURN_VALUE_REGNUM)
+
+/* A C expression that is nonzero if REGNO is the number of a hard register in
+ which the values of called function may come back.
+
+ A register whose use for returning values is limited to serving as the
+ second of a pair (for a value of type `double', say) need not be recognized
+ by this macro. So for most machines, this definition suffices:
+
+ #define FUNCTION_VALUE_REGNO_P(N) ((N) == RETURN)
+
+ If the machine has register windows, so that the caller and the called
+ function use different registers for the return value, this macro should
+ recognize only the caller's register numbers. */
+#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == RETURN_VALUE_REGNUM)
+
+
+/* How Large Values are Returned. */
+
+/* If the structure value address is passed in a register, then
+ `STRUCT_VALUE_REGNUM' should be the number of that register. */
+#define STRUCT_VALUE_REGNUM (GPR_FIRST + 3)
+
+
+/* Function Entry and Exit. */
+
+/* Define this macro as a C expression that is nonzero if the return
+ instruction or the function epilogue ignores the value of the stack pointer;
+ in other words, if it is safe to delete an instruction to adjust the stack
+ pointer before a return from the function.
+
+ Note that this macro's value is relevant only for functions for which 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 `EXIT_IGNORE_STACK'. */
+#define EXIT_IGNORE_STACK 1
+
+/* Generating Code for Profiling. */
+
+/* A C statement or compound statement to output to FILE some assembler code to
+ call the profiling subroutine `mcount'. Before calling, the assembler code
+ must load the address of a counter variable into a register where `mcount'
+ expects to find the address. The name of this variable is `LP' followed by
+ the number LABELNO, so you would generate the name using `LP%d' in a
+ `fprintf'.
+
+ The details of how the address should be passed to `mcount' are determined
+ by your operating system environment, not by GNU CC. To figure them out,
+ compile a small program for profiling using the system's installed C
+ compiler and look at the assembler code that results.
+
+ This declaration must be present, but it can be an abort if profiling is
+ not implemented. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) abort ()
+
+
+/* Implementing the Varargs Macros. */
+
+/* If defined, is a C expression that produces the machine-specific code for a
+ call to `__builtin_saveregs'. This code will be moved to the very beginning
+ of the function, before any parameter access are made. The return value of
+ this function should be an RTX that contains the value to use as the return
+ of `__builtin_saveregs'.
+
+ If this macro is not defined, the compiler will output an ordinary call to
+ the library function `__builtin_saveregs'. */
+
+#define EXPAND_BUILTIN_SAVEREGS() frv_expand_builtin_saveregs ()
+
+/* This macro offers an alternative to using `__builtin_saveregs' and defining
+ the macro `EXPAND_BUILTIN_SAVEREGS'. Use it to store the anonymous register
+ arguments into the stack so that all the arguments appear to have been
+ passed consecutively on the stack. Once this is done, you can use the
+ standard implementation of varargs that works for machines that pass all
+ their arguments on the stack.
+
+ The argument ARGS_SO_FAR is the `CUMULATIVE_ARGS' data structure, containing
+ the values that obtain after processing of the named arguments. The
+ arguments MODE and TYPE describe the last named argument--its machine mode
+ and its data type as a tree node.
+
+ The macro implementation should do two things: first, push onto the stack
+ all the argument registers *not* used for the named arguments, and second,
+ store the size of the data thus pushed into the `int'-valued variable whose
+ name is supplied as the argument PRETEND_ARGS_SIZE. The value that you
+ store here will serve as additional offset for setting up the stack frame.
+
+ Because you must generate code to push the anonymous arguments at compile
+ time without knowing their data types, `SETUP_INCOMING_VARARGS' is only
+ useful on machines that have just a single category of argument register and
+ use it uniformly for all data types.
+
+ If the argument SECOND_TIME is nonzero, it means that the arguments of the
+ function are being analyzed for the second time. This happens for an inline
+ function, which is not actually compiled until the end of the source file.
+ The macro `SETUP_INCOMING_VARARGS' should not generate any instructions in
+ this case. */
+#define SETUP_INCOMING_VARARGS(ARGS_SO_FAR, MODE, TYPE, PRETEND_ARGS_SIZE, SECOND_TIME) \
+ frv_setup_incoming_varargs (& ARGS_SO_FAR, (int) MODE, TYPE, \
+ & PRETEND_ARGS_SIZE, SECOND_TIME)
+
+/* Implement the stdarg/varargs va_start macro. STDARG_P is nonzero if this
+ is stdarg.h instead of varargs.h. VALIST is the tree of the va_list
+ variable to initialize. NEXTARG is the machine independent notion of the
+ 'next' argument after the variable arguments. If not defined, a standard
+ implementation will be defined that works for arguments passed on the stack. */
+
+#define EXPAND_BUILTIN_VA_START(VALIST, NEXTARG) \
+ (frv_expand_builtin_va_start(VALIST, NEXTARG))
+
+/* Implement the stdarg/varargs va_arg macro. VALIST is the variable of type
+ va_list as a tree, TYPE is the type passed to va_arg. */
+
+#define EXPAND_BUILTIN_VA_ARG(VALIST, TYPE) \
+ (frv_expand_builtin_va_arg (VALIST, TYPE))
+
+
+/* Trampolines for Nested Functions. */
+
+/* A C expression for the size in bytes of the trampoline, as an integer. */
+#define TRAMPOLINE_SIZE frv_trampoline_size ()
+
+/* Alignment required for trampolines, in bits.
+
+ If you don't define this macro, the value of `BIGGEST_ALIGNMENT' is used for
+ aligning trampolines. */
+#define TRAMPOLINE_ALIGNMENT 32
+
+/* 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 RTX for the static chain value that
+ should be passed to the function when it is called. */
+#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, STATIC_CHAIN) \
+ frv_initialize_trampoline (ADDR, FNADDR, STATIC_CHAIN)
+
+/* Define this macro if trampolines need a special subroutine to do their work.
+ The macro should expand to a series of `asm' statements which will be
+ compiled with GNU CC. They go in a library function named
+ `__transfer_from_trampoline'.
+
+ If you need to avoid executing the ordinary prologue code of a compiled C
+ function when you jump to the subroutine, you can do so by placing a special
+ label of your own in the assembler code. Use one `asm' statement to
+ generate an assembler label, and another to make the label global. Then
+ trampolines can use that label to jump directly to your special assembler
+ code. */
+
+#ifdef __FRV_UNDERSCORE__
+#define TRAMPOLINE_TEMPLATE_NAME "___trampoline_template"
+#else
+#define TRAMPOLINE_TEMPLATE_NAME "__trampoline_template"
+#endif
+
+#define TRANSFER_FROM_TRAMPOLINE \
+extern int _write (int, const void *, unsigned); \
+ \
+void \
+__trampoline_setup (addr, size, fnaddr, sc) \
+ short * addr; \
+ int size; \
+ int fnaddr; \
+ int sc; \
+{ \
+ extern short __trampoline_template[]; \
+ short * to = addr; \
+ short * from = &__trampoline_template[0]; \
+ int i; \
+ \
+ if (size < 20) \
+ { \
+ _write (2, "__trampoline_setup bad size\n", \
+ sizeof ("__trampoline_setup bad size\n") - 1); \
+ exit (-1); \
+ } \
+ \
+ to[0] = from[0]; \
+ to[1] = (short)(fnaddr); \
+ to[2] = from[2]; \
+ to[3] = (short)(sc); \
+ to[4] = from[4]; \
+ to[5] = (short)(fnaddr >> 16); \
+ to[6] = from[6]; \
+ to[7] = (short)(sc >> 16); \
+ to[8] = from[8]; \
+ to[9] = from[9]; \
+ \
+ for (i = 0; i < 20; i++) \
+ __asm__ volatile ("dcf @(%0,%1)\n\tici @(%0,%1)" :: "r" (to), "r" (i)); \
+} \
+ \
+__asm__("\n" \
+ "\t.globl " TRAMPOLINE_TEMPLATE_NAME "\n" \
+ "\t.text\n" \
+ TRAMPOLINE_TEMPLATE_NAME ":\n" \
+ "\tsetlos #0, gr6\n" /* jump register */ \
+ "\tsetlos #0, gr7\n" /* static chain */ \
+ "\tsethi #0, gr6\n" \
+ "\tsethi #0, gr7\n" \
+ "\tjmpl @(gr0,gr6)\n");
+
+
+/* Implicit Calls to Library Routines. */
+
+/* A C string constant giving the name of the function to call for the
+ remainder in division of one signed full-word by another. If you do not
+ define this macro, the default name is used, which is `__modsi3', a function
+ defined in `libgcc.a'. */
+#define MODSI3_LIBCALL "__modi"
+
+/* A C string constant giving the name of the function to call for the
+ remainder in division of one unsigned full-word by another. If you do not
+ define this macro, the default name is used, which is `__umodsi3', a
+ function defined in `libgcc.a'. */
+#define UMODSI3_LIBCALL "__umodi"
+
+/* A C string constant giving the name of the function to call for
+ multiplication of one signed double-word by another. If you do not define
+ this macro, the default name is used, which is `__muldi3', a function
+ defined in `libgcc.a'. */
+#define MULDI3_LIBCALL "__mulll"
+
+/* A C string constant giving the name of the function to call for division of
+ one signed double-word by another. If you do not define this macro, the
+ default name is used, which is `__divdi3', a function defined in `libgcc.a'. */
+#define DIVDI3_LIBCALL "__divll"
+
+/* A C string constant giving the name of the function to call for division of
+ one unsigned full-word by another. If you do not define this macro, the
+ default name is used, which is `__udivdi3', a function defined in
+ `libgcc.a'. */
+#define UDIVDI3_LIBCALL "__udivll"
+
+/* A C string constant giving the name of the function to call for the
+ remainder in division of one signed double-word by another. If you do not
+ define this macro, the default name is used, which is `__moddi3', a function
+ defined in `libgcc.a'. */
+#define MODDI3_LIBCALL "__modll"
+
+/* A C string constant giving the name of the function to call for the
+ remainder in division of one unsigned full-word by another. If you do not
+ define this macro, the default name is used, which is `__umoddi3', a
+ function defined in `libgcc.a'. */
+#define UMODDI3_LIBCALL "__umodll"
+
+/* Define this macro as a C statement that declares additional library routines
+ renames existing ones. `init_optabs' calls this macro after initializing all
+ the normal library routines. */
+#define INIT_TARGET_OPTABS \
+ do \
+ { \
+ add_optab->handlers [(int) DImode].libfunc \
+ = init_one_libfunc ("__addll"); \
+ sub_optab->handlers [(int) DImode].libfunc \
+ = init_one_libfunc ("__subll"); \
+ and_optab->handlers [(int) DImode].libfunc \
+ = init_one_libfunc ("__andll"); \
+ ior_optab->handlers [(int) DImode].libfunc \
+ = init_one_libfunc ("__orll"); \
+ xor_optab->handlers [(int) DImode].libfunc \
+ = init_one_libfunc ("__xorll"); \
+ one_cmpl_optab->handlers [(int) DImode].libfunc \
+ = init_one_libfunc ("__notll"); \
+ add_optab->handlers [(int) SFmode].libfunc \
+ = init_one_libfunc ("__addf"); \
+ sub_optab->handlers [(int) SFmode].libfunc \
+ = init_one_libfunc ("__subf"); \
+ smul_optab->handlers [(int) SFmode].libfunc \
+ = init_one_libfunc ("__mulf"); \
+ sdiv_optab->handlers [(int) SFmode].libfunc \
+ = init_one_libfunc ("__divf"); \
+ add_optab->handlers [(int) DFmode].libfunc \
+ = init_one_libfunc ("__addd"); \
+ sub_optab->handlers [(int) DFmode].libfunc \
+ = init_one_libfunc ("__subd"); \
+ smul_optab->handlers [(int) DFmode].libfunc \
+ = init_one_libfunc ("__muld"); \
+ sdiv_optab->handlers [(int) DFmode].libfunc \
+ = init_one_libfunc ("__divd"); \
+ fixsfsi_libfunc = init_one_libfunc ("__ftoi"); \
+ fixunssfsi_libfunc = init_one_libfunc ("__ftoui"); \
+ fixsfdi_libfunc = init_one_libfunc ("__ftoll"); \
+ fixunssfdi_libfunc = init_one_libfunc ("__ftoull"); \
+ fixdfsi_libfunc = init_one_libfunc ("__dtoi"); \
+ fixunsdfsi_libfunc = init_one_libfunc ("__dtoui"); \
+ fixdfdi_libfunc = init_one_libfunc ("__dtoll"); \
+ fixunsdfdi_libfunc = init_one_libfunc ("__dtoull"); \
+ floatsisf_libfunc = init_one_libfunc ("__itof"); \
+ floatdisf_libfunc = init_one_libfunc ("__lltof"); \
+ floatsidf_libfunc = init_one_libfunc ("__itod"); \
+ floatdidf_libfunc = init_one_libfunc ("__lltod"); \
+ extendsfdf2_libfunc = init_one_libfunc ("__ftod"); \
+ truncdfsf2_libfunc = init_one_libfunc ("__dtof"); \
+ } \
+ while (0)
+
+
+/* Addressing Modes. */
+
+/* A C expression that is 1 if the RTX X is a constant which is a valid
+ address. On most machines, this can be defined as `CONSTANT_P (X)', but a
+ few machines are more restrictive in which constant addresses are supported.
+
+ `CONSTANT_P' accepts integer-values expressions whose values are not
+ explicitly known, such as `symbol_ref', `label_ref', and `high' expressions
+ and `const' arithmetic expressions, in addition to `const_int' and
+ `const_double' expressions. */
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+
+/* A number, the maximum number of registers that can appear in a valid memory
+ address. Note that it is up to you to specify a value equal to the maximum
+ number that `GO_IF_LEGITIMATE_ADDRESS' would ever accept. */
+#define MAX_REGS_PER_ADDRESS 2
+
+/* A C compound statement with a conditional `goto LABEL;' executed if X (an
+ RTX) is a legitimate memory address on the target machine for a memory
+ operand of mode MODE.
+
+ It usually pays to define several simpler macros to serve as subroutines for
+ this one. Otherwise it may be too complicated to understand.
+
+ This macro must exist in two variants: a strict variant and a non-strict
+ one. The strict variant is used in the reload pass. It must be defined so
+ that any pseudo-register that has not been allocated a hard register is
+ considered a memory reference. In contexts where some kind of register is
+ required, a pseudo-register with no hard register must be rejected.
+
+ The non-strict variant is used in other passes. It must be defined to
+ accept all pseudo-registers in every context where some kind of register is
+ required.
+
+ Compiler source files that want to use the strict variant of this macro
+ define the macro `REG_OK_STRICT'. You should use an `#ifdef REG_OK_STRICT'
+ conditional to define the strict variant in that case and the non-strict
+ variant otherwise.
+
+ Subroutines to check for acceptable registers for various purposes (one for
+ base registers, one for index registers, and so on) are typically among the
+ subroutines used to define `GO_IF_LEGITIMATE_ADDRESS'. Then only these
+ subroutine macros need have two variants; the higher levels of macros may be
+ the same whether strict or not.
+
+ Normally, constant addresses which are the sum of a `symbol_ref' and an
+ integer are stored inside a `const' RTX to mark them as constant.
+ Therefore, there is no need to recognize such sums specifically as
+ legitimate addresses. Normally you would simply recognize any `const' as
+ legitimate.
+
+ Usually `PRINT_OPERAND_ADDRESS' is not prepared to handle constant sums that
+ are not marked with `const'. It assumes that a naked `plus' indicates
+ indexing. If so, then you *must* reject such naked constant sums as
+ illegitimate addresses, so that none of them will be given to
+ `PRINT_OPERAND_ADDRESS'.
+
+ On some machines, whether a symbolic address is legitimate depends on the
+ section that the address refers to. On these machines, define the macro
+ `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and
+ then check for it here. When you see a `const', you will have to look
+ inside it to find the `symbol_ref' in order to determine the section.
+
+ The best way to modify the name string is by adding text to the beginning,
+ with suitable punctuation to prevent any ambiguity. Allocate the new name
+ in `saveable_obstack'. You will have to modify `ASM_OUTPUT_LABELREF' to
+ remove and decode the added text and output the name accordingly, and define
+ `(* targetm.strip_name_encoding)' to access the original name string.
+
+ You can check the information stored here into the `symbol_ref' in the
+ definitions of the macros `GO_IF_LEGITIMATE_ADDRESS' and
+ `PRINT_OPERAND_ADDRESS'. */
+
+#ifdef REG_OK_STRICT
+#define REG_OK_STRICT_P 1
+#else
+#define REG_OK_STRICT_P 0
+#endif
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
+ do \
+ { \
+ if (frv_legitimate_address_p (MODE, X, REG_OK_STRICT_P, FALSE)) \
+ goto LABEL; \
+ } \
+ while (0)
+
+/* A C expression that is nonzero if X (assumed to be a `reg' RTX) is valid for
+ use as a base register. For hard registers, it should always accept those
+ which the hardware permits and reject the others. Whether the macro accepts
+ or rejects pseudo registers must be controlled by `REG_OK_STRICT' as
+ described above. This usually requires two variant definitions, of which
+ `REG_OK_STRICT' controls the one actually used. */
+#ifdef REG_OK_STRICT
+#define REG_OK_FOR_BASE_P(X) GPR_P (REGNO (X))
+#else
+#define REG_OK_FOR_BASE_P(X) GPR_AP_OR_PSEUDO_P (REGNO (X))
+#endif
+
+/* A C expression that is nonzero if X (assumed to be a `reg' RTX) is valid for
+ use as an index register.
+
+ The difference between an index register and a base register is that the
+ index register may be scaled. If an address involves the sum of two
+ registers, neither one of them scaled, then either one may be labeled the
+ "base" and the other the "index"; but whichever labeling is used must fit
+ the machine's constraints of which registers may serve in each capacity.
+ The compiler will try both labelings, looking for one that is valid, and
+ will reload one or both registers only if neither labeling works. */
+#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X)
+
+/* 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 statement label
+ elsewhere in the code; the macro definition may use
+
+ GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN);
+
+ to avoid further processing if the address has become legitimate.
+
+ X will always be the result of a call to `break_out_memory_refs', and OLDX
+ will be the operand that was given to that function to produce X.
+
+ The code generated by this macro should not alter the substructure of X. If
+ it transforms X into a more legitimate form, it should assign X (which will
+ always be a C variable) a new value.
+
+ It is not necessary for this macro to come up with a legitimate address.
+ The compiler has standard ways of doing so in all cases. In fact, it is
+ safe for this macro to do nothing. But often a machine-dependent strategy
+ can generate better code. */
+
+/* On the FRV, we use it to convert small data and pic references into using
+ the appropriate pointer in the address. */
+#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
+ do \
+ { \
+ rtx newx = frv_legitimize_address (X, OLDX, MODE); \
+ \
+ if (newx) \
+ { \
+ (X) = newx; \
+ goto WIN; \
+ } \
+ } \
+ while (0)
+
+/* A C statement or compound statement with a conditional `goto LABEL;'
+ executed if memory address X (an RTX) can have different meanings depending
+ on the machine mode of the memory reference it is used for or if the address
+ is valid for some modes but not others.
+
+ Autoincrement and autodecrement addresses typically have mode-dependent
+ effects because the amount of the increment or decrement is the size of the
+ operand being addressed. Some machines have other mode-dependent addresses.
+ Many RISC machines have no mode-dependent addresses.
+
+ You may assume that ADDR is a valid address for the machine. */
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
+
+/* A C expression that is nonzero if X is a legitimate constant for an
+ immediate operand on the target machine. You can assume that X satisfies
+ `CONSTANT_P', so you need not check this. In fact, `1' is a suitable
+ definition for this macro on machines where anything `CONSTANT_P' is valid. */
+#define LEGITIMATE_CONSTANT_P(X) frv_legitimate_constant_p (X)
+
+/* The load-and-update commands allow pre-modification in addresses.
+ The index has to be in a register. */
+#define HAVE_PRE_MODIFY_REG 1
+
+
+/* Returns a mode from class `MODE_CC' to be used when comparison operation
+ code OP is applied to rtx X and Y. For example, on the SPARC,
+ `SELECT_CC_MODE' is defined as (see *note Jump Patterns::. for a
+ description of the reason for this definition)
+
+ #define SELECT_CC_MODE(OP,X,Y) \
+ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
+ ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \
+ : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \
+ || GET_CODE (X) == NEG) \
+ ? CC_NOOVmode : CCmode))
+
+ You need not define this macro if `EXTRA_CC_MODES' is not defined. */
+#define SELECT_CC_MODE(OP, X, Y) \
+ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
+ ? CC_FPmode \
+ : (((OP) == LEU || (OP) == GTU || (OP) == LTU || (OP) == GEU) \
+ ? CC_UNSmode \
+ : CCmode))
+
+/* A C expression whose value is one if it is always safe to reverse a
+ comparison whose mode is MODE. If `SELECT_CC_MODE' can ever return MODE for
+ a floating-point inequality comparison, then `REVERSIBLE_CC_MODE (MODE)'
+ must be zero.
+
+ You need not define this macro if it would always returns zero or if the
+ floating-point format is anything other than `IEEE_FLOAT_FORMAT'. For
+ example, here is the definition used on the SPARC, where floating-point
+ inequality comparisons are always given `CCFPEmode':
+
+ #define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode) */
+
+/* On frv, don't consider floating point comparisons to be reversible. In
+ theory, fp equality comparisons can be reversible */
+#define REVERSIBLE_CC_MODE(MODE) ((MODE) == CCmode || (MODE) == CC_UNSmode)
+
+/* Frv CCR_MODE's are not reversible. */
+#define REVERSE_CONDEXEC_PREDICATES_P(x,y) 0
+
+
+/* Describing Relative Costs of Operations. */
+
+/* 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(X, CODE, OUTER_CODE) \
+ case CONST: \
+ case LABEL_REF: \
+ case SYMBOL_REF: \
+ case CONST_DOUBLE: \
+ return COSTS_N_INSNS (2); \
+ \
+ case CONST_INT: \
+ /* Make 12 bit integers really cheap */ \
+ return IN_RANGE_P (INTVAL (X), -2048, 2047) ? 0 : COSTS_N_INSNS (2); \
+
+/* 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 PLUS: \
+ case MINUS: \
+ case AND: \
+ case IOR: \
+ case XOR: \
+ case ASHIFT: \
+ case ASHIFTRT: \
+ case LSHIFTRT: \
+ case NOT: \
+ case NEG: \
+ case COMPARE: \
+ if (GET_MODE (X) == SImode) \
+ return COSTS_N_INSNS (1); \
+ else if (GET_MODE (X) == DImode) \
+ return COSTS_N_INSNS (2); \
+ else \
+ return COSTS_N_INSNS (3); /* guess */ \
+ \
+ case MULT: \
+ if (GET_MODE (X) == SImode) \
+ return COSTS_N_INSNS (2); \
+ else \
+ return COSTS_N_INSNS (6); /* guess */ \
+ \
+ case DIV: \
+ case UDIV: \
+ return COSTS_N_INSNS (18);
+
+/* A C expression for the cost of moving data from a register in class FROM to
+ one in class TO. The classes are expressed using the enumeration values
+ such as `GENERAL_REGS'. A value of 4 is the default; other values are
+ interpreted relative to that.
+
+ It is not required that the cost always equal 2 when FROM is the same as TO;
+ on some machines it is expensive to move between registers if they are not
+ general registers.
+
+ If reload sees an insn consisting of a single `set' between two hard
+ registers, and if `REGISTER_MOVE_COST' applied to their classes returns a
+ value of 2, reload does not check to ensure that the constraints of the insn
+ are met. Setting a cost of other than 2 will allow reload to verify that
+ the constraints are met. You should do this if the `movM' pattern's
+ constraints do not allow such copying. */
+#define REGISTER_MOVE_COST(MODE, FROM, TO) frv_register_move_cost (FROM, TO)
+
+/* A C expression for the cost of moving data of mode M between a register and
+ memory. A value of 2 is the default; this cost is relative to those in
+ `REGISTER_MOVE_COST'.
+
+ If moving between registers and memory is more expensive than between two
+ registers, you should define this macro to express the relative cost. */
+#define MEMORY_MOVE_COST(M,C,I) 4
+
+/* A C expression for the cost of a branch instruction. A value of 1 is the
+ default; other values are interpreted relative to that. */
+
+/* Here are additional macros which do not specify precise relative costs, but
+ only that certain actions are more expensive than GNU CC would ordinarily
+ expect. */
+
+/* We used to default the branch cost to 2, but I changed it to 1, to avoid
+ generating SCC instructions and or/and-ing them together, and then doing the
+ branch on the result, which collectively generate much worse code. */
+#ifndef DEFAULT_BRANCH_COST
+#define DEFAULT_BRANCH_COST 1
+#endif
+
+#define BRANCH_COST frv_branch_cost_int
+
+/* 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 1
+
+/* 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. */
+#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
+
+
+/* Dividing the output into sections. */
+
+/* A C expression whose value is a string containing the assembler operation
+ that should precede instructions and read-only data. Normally `".text"' is
+ right. */
+#define TEXT_SECTION_ASM_OP "\t.text"
+
+/* A C expression whose value is a string containing the assembler operation to
+ identify the following data as writable initialized data. Normally
+ `".data"' is right. */
+#define DATA_SECTION_ASM_OP "\t.data"
+
+/* 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
+ `ASM_OUTPUT_BSS' nor `ASM_OUTPUT_ALIGNED_BSS' are defined,
+ uninitialized global data will be output in the data section if
+ `-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be
+ used. */
+#define BSS_SECTION_ASM_OP "\t.section .bss,\"aw\""
+
+/* Short Data Support */
+#define SDATA_SECTION_ASM_OP "\t.section .sdata,\"aw\""
+#define SBSS_SECTION_ASM_OP "\t.section .sbss,\"aw\""
+
+/* On svr4, we *do* have support for the .init and .fini sections, and we
+ can put stuff in there to be executed before and after `main'. We let
+ crtstuff.c and other files know this by defining the following symbols.
+ The definitions say how to change sections to the .init and .fini
+ sections. This is the same for all known svr4 assemblers.
+
+ The standard System V.4 macros will work, but they look ugly in the
+ assembly output, so redefine them. */
+
+#undef INIT_SECTION_ASM_OP
+#undef FINI_SECTION_ASM_OP
+#define INIT_SECTION_ASM_OP "\t.section .init,\"ax\""
+#define FINI_SECTION_ASM_OP "\t.section .fini,\"ax\""
+
+/* A C expression whose value is a string containing the assembler operation to
+ switch to the fixup section that records all initialized pointers in a -fpic
+ program so they can be changed program startup time if the program is loaded
+ at a different address than linked for. */
+#define FIXUP_SECTION_ASM_OP "\t.section .rofixup,\"a\""
+
+/* A list of names for sections other than the standard two, which are
+ `in_text' and `in_data'. You need not define this macro
+ on a system with no other sections (that GCC needs to use). */
+#undef EXTRA_SECTIONS
+#define EXTRA_SECTIONS in_sdata, in_sbss, in_const, in_fixup
+
+/* One or more functions to be defined in "varasm.c". These
+ functions should do jobs analogous to those of `text_section' and
+ `data_section', for your additional sections. Do not define this
+ macro if you do not define `EXTRA_SECTIONS'. */
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS \
+SDATA_SECTION_FUNCTION \
+SBSS_SECTION_FUNCTION \
+FIXUP_SECTION_FUNCTION
+
+
+#define SDATA_SECTION_FUNCTION \
+void \
+sdata_section () \
+{ \
+ if (in_section != in_sdata) \
+ { \
+ fprintf (asm_out_file, "%s\n", SDATA_SECTION_ASM_OP); \
+ in_section = in_sdata; \
+ } \
+} \
+
+#define SBSS_SECTION_FUNCTION \
+void \
+sbss_section () \
+{ \
+ if (in_section != in_sbss) \
+ { \
+ fprintf (asm_out_file, "%s\n", SBSS_SECTION_ASM_OP); \
+ in_section = in_sbss; \
+ } \
+} \
+
+#define FIXUP_SECTION_FUNCTION \
+void \
+fixup_section () \
+{ \
+ if (in_section != in_fixup) \
+ { \
+ fprintf (asm_out_file, "%s\n", FIXUP_SECTION_ASM_OP); \
+ in_section = in_fixup; \
+ } \
+} \
+
+#define SDATA_FLAG_CHAR '@'
+
+#define SDATA_NAME_P(NAME) (*(NAME) == SDATA_FLAG_CHAR)
+
+/* Position Independent Code. */
+
+/* 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) \
+ ( GET_CODE (X) == CONST_INT \
+ || GET_CODE (X) == CONST_DOUBLE \
+ || (GET_CODE (X) == HIGH && GET_CODE (XEXP (X, 0)) == CONST_INT) \
+ || GET_CODE (X) == CONSTANT_P_RTX)
+
+
+/* The Overall Framework of an Assembler File. */
+
+/* A C string constant describing how to begin a comment in the target
+ assembler language. The compiler assumes that the comment will end at the
+ end of the line. */
+#define ASM_COMMENT_START ";"
+
+/* A C string constant for text to be output before each `asm' statement or
+ group of consecutive ones. Normally this is `"#APP"', which is a comment
+ that has no effect on most assemblers but tells the GNU assembler that it
+ must check the lines that follow for all valid assembler constructs. */
+#define ASM_APP_ON "#APP\n"
+
+/* A C string constant for text to be output after each `asm' statement or
+ group of consecutive ones. Normally this is `"#NO_APP"', which tells the
+ GNU assembler to resume making the time-saving assumptions that are valid
+ for ordinary compiler output. */
+#define ASM_APP_OFF "#NO_APP\n"
+
+
+/* Output of Data. */
+
+/* This is how to output a label to dwarf/dwarf2. */
+#define ASM_OUTPUT_DWARF_ADDR(STREAM, LABEL) \
+do { \
+ fprintf (STREAM, "\t.picptr\t"); \
+ assemble_name (STREAM, LABEL); \
+} while (0)
+
+/* Whether to emit the gas specific dwarf2 line number support. */
+#define DWARF2_ASM_LINE_DEBUG_INFO (TARGET_DEBUG_LOC)
+
+/* Output of Uninitialized Variables. */
+
+/* A C statement (sans semicolon) to output to the stdio stream STREAM the
+ assembler definition of a local-common-label named NAME whose size is SIZE
+ bytes. The variable ROUNDED is the size rounded up to whatever alignment
+ the caller wants.
+
+ Use the expression `assemble_name (STREAM, 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 static
+ variables are output. */
+#undef ASM_OUTPUT_LOCAL
+
+/* Like `ASM_OUTPUT_LOCAL' except takes the required alignment as a separate,
+ explicit argument. If you define this macro, it is used in place of
+ `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.
+
+ Defined in svr4.h. */
+#undef ASM_OUTPUT_ALIGNED_LOCAL
+
+/* This is for final.c, because it is used by ASM_DECLARE_OBJECT_NAME. */
+extern int size_directive_output;
+
+/* Like `ASM_OUTPUT_ALIGNED_LOCAL' except that it takes an additional
+ parameter - the DECL of variable to be output, if there is one.
+ This macro can be called with DECL == NULL_TREE. If you define
+ this macro, it is used in place of `ASM_OUTPUT_LOCAL' and
+ `ASM_OUTPUT_ALIGNED_LOCAL', and gives you more flexibility in
+ handling the destination of the variable. */
+#undef ASM_OUTPUT_ALIGNED_DECL_LOCAL
+#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGN) \
+do { \
+ if (SDATA_NAME_P (NAME)) \
+ sbss_section (); \
+ else \
+ bss_section (); \
+ ASM_OUTPUT_ALIGN (STREAM, floor_log2 ((ALIGN) / BITS_PER_UNIT)); \
+ ASM_DECLARE_OBJECT_NAME (STREAM, NAME, DECL); \
+ ASM_OUTPUT_SKIP (STREAM, (SIZE) ? (SIZE) : 1); \
+} while (0)
+
+
+/* Output and Generation of Labels. */
+
+/* A C statement (sans semicolon) to output to the stdio stream STREAM the
+ assembler definition of a label named NAME. Use the expression
+ `assemble_name (STREAM, NAME)' to output the name itself; before and after
+ that, output the additional assembler syntax for defining the name, and a
+ newline. */
+#define ASM_OUTPUT_LABEL(STREAM, NAME) \
+do { \
+ assemble_name (STREAM, NAME); \
+ fputs (":\n", STREAM); \
+} while (0)
+
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.globl "
+
+/* A C statement (sans semicolon) to output to the stdio stream STREAM a
+ reference in assembler syntax to a label named NAME. This should add `_' to
+ the front of the name, if that is customary on your operating system, as it
+ is in most Berkeley Unix systems. This macro is used in `assemble_name'. */
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
+do { \
+ const char *_name = (NAME); \
+ while (*_name == '*' || *_name == SDATA_FLAG_CHAR) \
+ _name++; \
+ asm_fprintf (STREAM, "%U%s", _name); \
+} while (0)
+
+/* A C statement to store into the string STRING a label whose name is made
+ from the string PREFIX and the number NUM.
+
+ This string, when output subsequently by `assemble_name', should produce the
+ output that `ASM_OUTPUT_INTERNAL_LABEL' would produce with the same PREFIX
+ and NUM.
+
+ If the string begins with `*', then `assemble_name' will output the rest of
+ the string unchanged. It is often convenient for
+ `ASM_GENERATE_INTERNAL_LABEL' to use `*' in this way. If the string doesn't
+ start with `*', then `ASM_OUTPUT_LABELREF' gets to output the string, and
+ may change it. (Of course, `ASM_OUTPUT_LABELREF' is also part of your
+ machine description, so you should know what it does on your machine.)
+
+ Defined in svr4.h. */
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
+do { \
+ sprintf (LABEL, "*.%s%ld", PREFIX, (long)NUM); \
+} while (0)
+
+/* A C expression to assign to OUTVAR (which is a variable of type `char *') a
+ newly allocated string made from the string NAME and the number NUMBER, with
+ some suitable punctuation added. Use `alloca' to get space for the string.
+
+ The string will be used as an argument to `ASM_OUTPUT_LABELREF' to produce
+ an assembler label for an internal static variable whose name is NAME.
+ Therefore, the string must be such as to result in valid assembler code.
+ The argument NUMBER is different each time this macro is executed; it
+ prevents conflicts between similarly-named internal static variables in
+ different scopes.
+
+ Ideally this string should not be a valid C identifier, to prevent any
+ conflict with the user's own symbols. Most assemblers allow periods or
+ percent signs in assembler symbols; putting at least one of these between
+ the name and the number will suffice. */
+#define ASM_FORMAT_PRIVATE_NAME(OUTVAR, NAME, NUMBER) \
+do { \
+ (OUTVAR) = (char *) alloca (strlen ((NAME)) + 12); \
+ sprintf ((OUTVAR), "%s.%ld", (NAME), (long)(NUMBER)); \
+} while (0)
+
+
+/* Macros Controlling Initialization Routines. */
+
+/* If defined, a C string constant for the assembler operation to identify the
+ following data as initialization code. If not defined, GNU CC will assume
+ such a section does not exist. When you are using special sections for
+ initialization and termination functions, this macro also controls how
+ `crtstuff.c' and `libgcc2.c' arrange to run the initialization functions.
+
+ Defined in svr4.h. */
+#undef INIT_SECTION_ASM_OP
+
+/* If defined, `main' will call `__main' despite the presence of
+ `INIT_SECTION_ASM_OP'. This macro should be defined for systems where the
+ init section is not actually run automatically, but is still useful for
+ collecting the lists of constructors and destructors. */
+#define INVOKE__main
+
+/* Output appropriate code tp call a static constructor. */
+#undef ASM_OUTPUT_CONSTRUCTOR
+#define ASM_OUTPUT_CONSTRUCTOR(STREAM,NAME) \
+do { \
+ ctors_section (); \
+ fprintf (STREAM, "\t.picptr\t"); \
+ assemble_name (STREAM, NAME); \
+ fprintf (STREAM, "\n"); \
+} while (0)
+
+/* Output appropriate code tp call a static destructor. */
+#undef ASM_OUTPUT_DESTRUCTOR
+#define ASM_OUTPUT_DESTRUCTOR(STREAM,NAME) \
+do { \
+ dtors_section (); \
+ fprintf (STREAM, "\t.picptr\t"); \
+ assemble_name (STREAM, NAME); \
+ fprintf (STREAM, "\n"); \
+} while (0)
+
+
+/* Output of Assembler Instructions. */
+
+/* A C initializer containing the assembler's names for the machine registers,
+ each one as a C string constant. This is what translates register numbers
+ in the compiler into assembler language. */
+#define REGISTER_NAMES \
+{ \
+ "gr0", "sp", "fp", "gr3", "gr4", "gr5", "gr6", "gr7", \
+ "gr8", "gr9", "gr10", "gr11", "gr12", "gr13", "gr14", "gr15", \
+ "gr16", "gr17", "gr18", "gr19", "gr20", "gr21", "gr22", "gr23", \
+ "gr24", "gr25", "gr26", "gr27", "gr28", "gr29", "gr30", "gr31", \
+ "gr32", "gr33", "gr34", "gr35", "gr36", "gr37", "gr38", "gr39", \
+ "gr40", "gr41", "gr42", "gr43", "gr44", "gr45", "gr46", "gr47", \
+ "gr48", "gr49", "gr50", "gr51", "gr52", "gr53", "gr54", "gr55", \
+ "gr56", "gr57", "gr58", "gr59", "gr60", "gr61", "gr62", "gr63", \
+ \
+ "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7", \
+ "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15", \
+ "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23", \
+ "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31", \
+ "fr32", "fr33", "fr34", "fr35", "fr36", "fr37", "fr38", "fr39", \
+ "fr40", "fr41", "fr42", "fr43", "fr44", "fr45", "fr46", "fr47", \
+ "fr48", "fr49", "fr50", "fr51", "fr52", "fr53", "fr54", "fr55", \
+ "fr56", "fr57", "fr58", "fr59", "fr60", "fr61", "fr62", "fr63", \
+ \
+ "fcc0", "fcc1", "fcc2", "fcc3", "icc0", "icc1", "icc2", "icc3", \
+ "cc0", "cc1", "cc2", "cc3", "cc4", "cc5", "cc6", "cc7", \
+ "acc0", "acc1", "acc2", "acc3", "acc4", "acc5", "acc6", "acc7", \
+ "accg0","accg1","accg2","accg3","accg4","accg5","accg6","accg7", \
+ "ap", "lr", "lcr" \
+}
+
+/* Define this macro if you are using an unusual assembler that
+ requires different names for the machine instructions.
+
+ The definition is a C statement or statements which output an
+ assembler instruction opcode to the stdio stream STREAM. The
+ macro-operand PTR is a variable of type `char *' which points to
+ the opcode name in its "internal" form--the form that is written
+ in the machine description. The definition should output the
+ opcode name to STREAM, performing any translation you desire, and
+ increment the variable PTR to point at the end of the opcode so
+ that it will not be output twice.
+
+ In fact, your macro definition may process less than the entire
+ opcode name, or more than the opcode name; but if you want to
+ process text that includes `%'-sequences to substitute operands,
+ you must take care of the substitution yourself. Just be sure to
+ increment PTR over whatever text should not be output normally.
+
+ If you need to look at the operand values, they can be found as the
+ elements of `recog_operand'.
+
+ If the macro definition does nothing, the instruction is output in
+ the usual way. */
+
+#define ASM_OUTPUT_OPCODE(STREAM, PTR)\
+ (PTR) = frv_asm_output_opcode (STREAM, PTR)
+
+/* If defined, 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.
+
+ This macro is useful when various assembler syntaxes share a single
+ file of instruction patterns; by defining this macro differently,
+ you can cause a large class of instructions to be output
+ differently (such as with rearranged operands). Naturally,
+ variations in assembler syntax affecting individual insn patterns
+ ought to be handled by writing conditional output routines in
+ those patterns.
+
+ If this macro is not defined, it is equivalent to a null statement. */
+
+#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS)\
+ frv_final_prescan_insn (INSN, OPVEC, NOPERANDS)
+
+
+/* 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'.
+
+ 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. */
+#define PRINT_OPERAND(STREAM, X, CODE) frv_print_operand (STREAM, X, CODE)
+
+/* A C expression which evaluates to true if CODE is a valid punctuation
+ character for use in the `PRINT_OPERAND' macro. If
+ `PRINT_OPERAND_PUNCT_VALID_P' is not defined, it means that no punctuation
+ characters (except for the standard one, `%') are used in this way. */
+/* . == gr0
+ # == hint operand -- always zero for now
+ @ == small data base register (gr16)
+ ~ == pic register (gr17)
+ * == temporary integer CCR register (cr3)
+ & == temporary integer ICC register (icc3) */
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
+((CODE) == '.' || (CODE) == '#' || (CODE) == SDATA_FLAG_CHAR || (CODE) == '~' \
+ || (CODE) == '*' || (CODE) == '&')
+
+/* A C compound statement to output to stdio stream STREAM the assembler syntax
+ for an instruction operand that is a memory reference whose address is X. X
+ is an RTL expression.
+
+ On some machines, the syntax for a symbolic address depends on the section
+ that the address refers to. On these machines, define the macro
+ `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and
+ then check for it here.
+
+ This declaration must be present. */
+#define PRINT_OPERAND_ADDRESS(STREAM, X) frv_print_operand_address (STREAM, X)
+
+/* If defined, C string expressions to be used for the `%R', `%L', `%U', and
+ `%I' options of `asm_fprintf' (see `final.c'). These are useful when a
+ single `md' file must support multiple assembler formats. In that case, the
+ various `tm.h' files can define these macros differently.
+
+ USER_LABEL_PREFIX is defined in svr4.h. */
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+#define REGISTER_PREFIX ""
+#define LOCAL_LABEL_PREFIX "."
+#define IMMEDIATE_PREFIX "#"
+
+
+/* Output of dispatch tables. */
+
+/* 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 STREAM
+ an assembler pseudo-instruction to generate a difference between two labels.
+ VALUE and REL are the numbers of two internal labels. The definitions of
+ these labels are output using `ASM_OUTPUT_INTERNAL_LABEL', and they must be
+ printed in the same way here. For example,
+
+ fprintf (STREAM, "\t.word L%d-L%d\n", VALUE, REL) */
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
+fprintf (STREAM, "\t.word .L%d-.L%d\n", VALUE, REL)
+
+/* This macro should be provided on machines where the addresses in a dispatch
+ table are absolute.
+
+ The definition should be a C statement to output to the stdio stream STREAM
+ an assembler pseudo-instruction to generate a reference to a label. VALUE
+ is the number of an internal label whose definition is output using
+ `ASM_OUTPUT_INTERNAL_LABEL'. For example,
+
+ fprintf (STREAM, "\t.word L%d\n", VALUE) */
+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
+fprintf (STREAM, "\t.word .L%d\n", VALUE)
+
+/* Define this if the label before a jump-table needs to be output specially.
+ The first three arguments are the same as for `ASM_OUTPUT_INTERNAL_LABEL';
+ the fourth argument is the jump-table which follows (a `jump_insn'
+ containing an `addr_vec' or `addr_diff_vec').
+
+ This feature is used on system V to output a `swbeg' statement for the
+ table.
+
+ If this macro is not defined, these labels are output with
+ `ASM_OUTPUT_INTERNAL_LABEL'.
+
+ Defined in svr4.h. */
+/* When generating embedded PIC or mips16 code we want to put the jump
+ table in the .text section. In all other cases, we want to put the
+ jump table in the .rdata section. Unfortunately, we can't use
+ JUMP_TABLES_IN_TEXT_SECTION, because it is not conditional.
+ Instead, we use ASM_OUTPUT_CASE_LABEL to switch back to the .text
+ section if appropriate. */
+
+#undef ASM_OUTPUT_CASE_LABEL
+#define ASM_OUTPUT_CASE_LABEL(STREAM, PREFIX, NUM, TABLE) \
+do { \
+ if (flag_pic) \
+ function_section (current_function_decl); \
+ ASM_OUTPUT_INTERNAL_LABEL (STREAM, PREFIX, NUM); \
+} while (0)
+
+/* Define this to determine whether case statement labels are relative to
+ the start of the case statement or not. */
+
+#define CASE_VECTOR_PC_RELATIVE (flag_pic)
+
+
+/* Assembler Commands for Exception Regions. */
+
+/* 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
+ `INCOMING_RETURN_ADDR_RTX' and either `UNALIGNED_INT_ASM_OP' or
+ `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. */
+#define DWARF2_UNWIND_INFO 1
+
+#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LR_REGNO)
+
+/* Assembler Commands for Alignment. */
+
+/* A C statement to output to the stdio stream STREAM an assembler instruction
+ to advance the location counter by NBYTES bytes. Those bytes should be zero
+ when loaded. NBYTES will be a C expression of type `int'.
+
+ Defined in svr4.h. */
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(STREAM, NBYTES) \
+ fprintf (STREAM, "\t.zero\t%u\n", (NBYTES))
+
+/* A C statement to output to the stdio stream STREAM an assembler command to
+ advance the location counter to a multiple of 2 to the POWER bytes. POWER
+ will be a C expression of type `int'. */
+#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
+ fprintf ((STREAM), "\t.p2align %d\n", (POWER))
+
+
+/* Macros Affecting all Debug Formats. */
+
+/* A C expression that returns the DBX register number for the compiler
+ register number REGNO. In simple cases, the value of this expression may be
+ REGNO itself. But sometimes there are some registers that the compiler
+ knows about and DBX does not, or vice versa. In such cases, some register
+ may need to have one number in the compiler and another for DBX.
+
+ If two registers have consecutive numbers inside GNU CC, and they can be
+ used as a pair to hold a multiword value, then they *must* have consecutive
+ numbers after renumbering with `DBX_REGISTER_NUMBER'. Otherwise, debuggers
+ will be unable to access such a pair, because they expect register pairs to
+ be consecutive in their own numbering scheme.
+
+ If you find yourself defining `DBX_REGISTER_NUMBER' in way that does not
+ preserve register pairs, then what you must do instead is redefine the
+ actual register numbering scheme.
+
+ This declaration is required. */
+#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+
+/* A C expression that returns the type of debugging output GNU CC produces
+ when the user specifies `-g' or `-ggdb'. Define this if you have arranged
+ for GNU CC to support more than one format of debugging output. Currently,
+ the allowable values are `DBX_DEBUG', `SDB_DEBUG', `DWARF_DEBUG',
+ `DWARF2_DEBUG', and `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 `-gstabs', `-gcoff',
+ `-gdwarf-1', `-gdwarf-2', or `-gxcoff'.
+
+ Defined in svr4.h. */
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+/* Miscellaneous Parameters. */
+
+/* Define this if you have defined special-purpose predicates in the file
+ `MACHINE.c'. This macro is called within an initializer of an array of
+ structures. The first field in the structure is the name of a predicate and
+ the second field is an array of rtl codes. For each predicate, list all rtl
+ codes that can be in expressions matched by the predicate. The list should
+ have a trailing comma. Here is an example of two entries in the list for a
+ typical RISC machine:
+
+ #define PREDICATE_CODES \
+ {"gen_reg_rtx_operand", {SUBREG, REG}}, \
+ {"reg_or_short_cint_operand", {SUBREG, REG, CONST_INT}},
+
+ Defining this macro does not affect the generated code (however, incorrect
+ definitions that omit an rtl code that may be matched by the predicate can
+ cause the compiler to malfunction). Instead, it allows the table built by
+ `genrecog' to be more compact and efficient, thus speeding up the compiler.
+ The most important predicates to include in the list specified by this macro
+ are thoses used in the most insn patterns. */
+#define PREDICATE_CODES \
+ { "integer_register_operand", { REG, SUBREG }}, \
+ { "frv_load_operand", { REG, SUBREG, MEM }}, \
+ { "gpr_no_subreg_operand", { REG }}, \
+ { "gpr_or_fpr_operand", { REG, SUBREG }}, \
+ { "gpr_or_int12_operand", { REG, SUBREG, CONST_INT }}, \
+ { "gpr_fpr_or_int12_operand", { REG, SUBREG, CONST_INT }}, \
+ { "gpr_or_int10_operand", { REG, SUBREG, CONST_INT }}, \
+ { "gpr_or_int_operand", { REG, SUBREG, CONST_INT }}, \
+ { "move_source_operand", { REG, SUBREG, CONST_INT, MEM, \
+ CONST_DOUBLE, CONST, \
+ SYMBOL_REF, LABEL_REF }}, \
+ { "move_destination_operand", { REG, SUBREG, MEM }}, \
+ { "condexec_source_operand", { REG, SUBREG, CONST_INT, MEM, \
+ CONST_DOUBLE }}, \
+ { "condexec_dest_operand", { REG, SUBREG, MEM }}, \
+ { "reg_or_0_operand", { REG, SUBREG, CONST_INT }}, \
+ { "lr_operand", { REG }}, \
+ { "gpr_or_memory_operand", { REG, SUBREG, MEM }}, \
+ { "fpr_or_memory_operand", { REG, SUBREG, MEM }}, \
+ { "int12_operand", { CONST_INT }}, \
+ { "int_2word_operand", { CONST_INT, CONST_DOUBLE, \
+ SYMBOL_REF, LABEL_REF, CONST }}, \
+ { "pic_register_operand", { REG }}, \
+ { "pic_symbolic_operand", { SYMBOL_REF, LABEL_REF, CONST }}, \
+ { "small_data_register_operand", { REG }}, \
+ { "small_data_symbolic_operand", { SYMBOL_REF, CONST }}, \
+ { "icc_operand", { REG }}, \
+ { "fcc_operand", { REG }}, \
+ { "cc_operand", { REG }}, \
+ { "icr_operand", { REG }}, \
+ { "fcr_operand", { REG }}, \
+ { "cr_operand", { REG }}, \
+ { "fpr_operand", { REG, SUBREG }}, \
+ { "even_reg_operand", { REG, SUBREG }}, \
+ { "odd_reg_operand", { REG, SUBREG }}, \
+ { "even_gpr_operand", { REG, SUBREG }}, \
+ { "odd_gpr_operand", { REG, SUBREG }}, \
+ { "quad_fpr_operand", { REG, SUBREG }}, \
+ { "even_fpr_operand", { REG, SUBREG }}, \
+ { "odd_fpr_operand", { REG, SUBREG }}, \
+ { "dbl_memory_one_insn_operand", { MEM }}, \
+ { "dbl_memory_two_insn_operand", { MEM }}, \
+ { "call_operand", { REG, SUBREG, PLUS, CONST_INT, \
+ SYMBOL_REF, LABEL_REF, CONST }}, \
+ { "upper_int16_operand", { CONST_INT }}, \
+ { "uint16_operand", { CONST_INT }}, \
+ { "relational_operator", { EQ, NE, LE, LT, GE, GT, \
+ LEU, LTU, GEU, GTU }}, \
+ { "signed_relational_operator", { EQ, NE, LE, LT, GE, GT }}, \
+ { "unsigned_relational_operator", { LEU, LTU, GEU, GTU }}, \
+ { "float_relational_operator", { EQ, NE, LE, LT, GE, GT }}, \
+ { "ccr_eqne_operator", { EQ, NE }}, \
+ { "minmax_operator", { SMIN, SMAX, UMIN, UMAX }}, \
+ { "condexec_si_binary_operator", { PLUS, MINUS, AND, IOR, XOR, \
+ ASHIFT, ASHIFTRT, LSHIFTRT }}, \
+ { "condexec_si_divide_operator", { DIV, UDIV }}, \
+ { "condexec_si_unary_operator", { NOT, NEG }}, \
+ { "condexec_sf_binary_operator", { PLUS, MINUS, MULT, DIV }}, \
+ { "condexec_sf_unary_operator", { ABS, NEG, SQRT }}, \
+ { "intop_compare_operator", { PLUS, MINUS, AND, IOR, XOR, \
+ ASHIFT, ASHIFTRT, LSHIFTRT }}, \
+ { "condexec_intop_cmp_operator", { PLUS, MINUS, AND, IOR, XOR, \
+ ASHIFT, ASHIFTRT, LSHIFTRT }}, \
+ { "fpr_or_int6_operand", { REG, SUBREG, CONST_INT }}, \
+ { "int6_operand", { CONST_INT }}, \
+ { "int5_operand", { CONST_INT }}, \
+ { "uint5_operand", { CONST_INT }}, \
+ { "uint4_operand", { CONST_INT }}, \
+ { "uint1_operand", { CONST_INT }}, \
+ { "acc_operand", { REG, SUBREG }}, \
+ { "even_acc_operand", { REG, SUBREG }}, \
+ { "quad_acc_operand", { REG, SUBREG }}, \
+ { "accg_operand", { REG, SUBREG }},
+
+/* An alias for a machine mode name. This is the machine mode that elements of
+ a jump-table should have. */
+#define CASE_VECTOR_MODE SImode
+
+/* Define this macro if operations between registers with integral mode smaller
+ than a word are always performed on the entire register. Most RISC machines
+ have this property and most CISC machines do not. */
+#define WORD_REGISTER_OPERATIONS
+
+/* Define this macro to be a C expression indicating when insns that read
+ memory in MODE, an integral mode narrower than a word, set the bits outside
+ of MODE to be either the sign-extension or the zero-extension of the data
+ read. Return `SIGN_EXTEND' for values of MODE for which the insn
+ sign-extends, `ZERO_EXTEND' for which it zero-extends, and `NIL' for other
+ modes.
+
+ This macro is not called with MODE non-integral or with a width greater than
+ or equal to `BITS_PER_WORD', so you may return any value in this case. Do
+ not define this macro if it would always return `NIL'. On machines where
+ this macro is defined, you will normally define it as the constant
+ `SIGN_EXTEND' or `ZERO_EXTEND'. */
+#define LOAD_EXTEND_OP(MODE) SIGN_EXTEND
+
+/* Define if loading short immediate values into registers sign extends. */
+#define SHORT_IMMEDIATES_SIGN_EXTEND
+
+/* The maximum number of bytes that a single instruction can move quickly from
+ memory to memory. */
+#define MOVE_MAX 8
+
+/* A C expression which is nonzero if on this machine it is safe to "convert"
+ an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller
+ than INPREC) by merely operating on it as if it had only OUTPREC bits.
+
+ On many machines, this expression can be 1.
+
+ When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for
+ which `MODES_TIEABLE_P' is 0, suboptimal code can result. If this is the
+ case, making `TRULY_NOOP_TRUNCATION' return 0 in such cases may improve
+ things. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* An alias for the machine mode for pointers. On most machines, define this
+ to be the integer mode corresponding to the width of a hardware pointer;
+ `SImode' on 32-bit machine or `DImode' on 64-bit machines. On some machines
+ you must define this to be one of the partial integer modes, such as
+ `PSImode'.
+
+ The width of `Pmode' must be at least as large as the value of
+ `POINTER_SIZE'. If it is not equal, you must define the macro
+ `POINTERS_EXTEND_UNSIGNED' to specify how pointers are extended to `Pmode'. */
+#define Pmode SImode
+
+/* An alias for the machine mode used for memory references to functions being
+ called, in `call' RTL expressions. On most machines this should be
+ `QImode'. */
+#define FUNCTION_MODE QImode
+
+/* Define this macro to handle System V style pragmas: #pragma pack and
+ #pragma weak. Note, #pragma weak will only be supported if SUPPORT_WEAK is
+ defined.
+
+ Defined in svr4.h. */
+#define HANDLE_SYSV_PRAGMA 1
+
+/* A C expression for the maximum number of instructions to execute via
+ conditional execution instructions instead of a branch. A value of
+ BRANCH_COST+1 is the default if the machine does not use
+ cc0, and 1 if it does use cc0. */
+#define MAX_CONDITIONAL_EXECUTE frv_condexec_insns
+
+/* Default value of MAX_CONDITIONAL_EXECUTE if no -mcond-exec-insns= */
+#define DEFAULT_CONDEXEC_INSNS 8
+
+/* A C expression to modify the code described by the conditional if
+ information CE_INFO, possibly updating the tests in TRUE_EXPR, and
+ FALSE_EXPR for converting if-then and if-then-else code to conditional
+ instructions. Set either TRUE_EXPR or FALSE_EXPR to a null pointer if the
+ tests cannot be converted. */
+#define IFCVT_MODIFY_TESTS(CE_INFO, TRUE_EXPR, FALSE_EXPR) \
+frv_ifcvt_modify_tests (CE_INFO, &TRUE_EXPR, &FALSE_EXPR)
+
+/* A C expression to modify the code described by the conditional if
+ information CE_INFO, for the basic block BB, possibly updating the tests in
+ TRUE_EXPR, and FALSE_EXPR for converting the && and || parts of if-then or
+ if-then-else code to conditional instructions. OLD_TRUE and OLD_FALSE are
+ the previous tests. Set either TRUE_EXPR or FALSE_EXPR to a null pointer if
+ the tests cannot be converted. */
+#define IFCVT_MODIFY_MULTIPLE_TESTS(CE_INFO, BB, TRUE_EXPR, FALSE_EXPR) \
+frv_ifcvt_modify_multiple_tests (CE_INFO, BB, &TRUE_EXPR, &FALSE_EXPR)
+
+/* A C expression to modify the code described by the conditional if
+ information CE_INFO with the new PATTERN in INSN. If PATTERN is a null
+ pointer after the IFCVT_MODIFY_INSN macro executes, it is assumed that that
+ insn cannot be converted to be executed conditionally. */
+#define IFCVT_MODIFY_INSN(CE_INFO, PATTERN, INSN) \
+(PATTERN) = frv_ifcvt_modify_insn (CE_INFO, PATTERN, INSN)
+
+/* A C expression to perform any final machine dependent modifications in
+ converting code to conditional execution in the code described by the
+ conditional if information CE_INFO. */
+#define IFCVT_MODIFY_FINAL(CE_INFO) frv_ifcvt_modify_final (CE_INFO)
+
+/* A C expression to cancel any machine dependent modifications in converting
+ code to conditional execution in the code described by the conditional if
+ information CE_INFO. */
+#define IFCVT_MODIFY_CANCEL(CE_INFO) frv_ifcvt_modify_cancel (CE_INFO)
+
+/* Initialize the extra fields provided by IFCVT_EXTRA_FIELDS. */
+#define IFCVT_INIT_EXTRA_FIELDS(CE_INFO) frv_ifcvt_init_extra_fields (CE_INFO)
+
+/* Indicate how many instructions can be issued at the same time. */
+#define ISSUE_RATE \
+(! TARGET_PACK ? 1 \
+ : (frv_cpu_type == FRV_CPU_GENERIC \
+ || frv_cpu_type == FRV_CPU_FR500 \
+ || frv_cpu_type == FRV_CPU_TOMCAT) ? 4 \
+ : frv_cpu_type == FRV_CPU_FR400 ? 2 : 1)
+
+/* Set and clear whether this insn begins a VLIW insn. */
+#define CLEAR_VLIW_START(INSN) PUT_MODE (INSN, VOIDmode)
+#define SET_VLIW_START(INSN) PUT_MODE (INSN, TImode)
+
+/* The definition of the following macro results in that the 2nd jump
+ optimization (after the 2nd insn scheduling) is minimal. It is
+ necessary to define when start cycle marks of insns (TImode is used
+ for this) is used for VLIW insn packing. Some jump optimizations
+ make such marks invalid. These marks are corrected for some
+ (minimal) optimizations. ??? Probably the macro is temporary.
+ Final solution could making the 2nd jump optimizations before the
+ 2nd instruction scheduling or corrections of the marks for all jump
+ optimizations. Although some jump optimizations are actually
+ deoptimizations for VLIW (super-scalar) processors. */
+
+#define MINIMAL_SECOND_JUMP_OPTIMIZATION
+
+/* Return true if parallel operations are expected to be emitted via the
+ packing flag. */
+#define PACKING_FLAG_USED_P() \
+(optimize && flag_schedule_insns_after_reload && ISSUE_RATE > 1)
+
+/* If the following macro is defined and nonzero and deterministic
+ finite state automata are used for pipeline hazard recognition, the
+ code making resource-constrained software pipelining is on. */
+#define RCSP_SOFTWARE_PIPELINING 1
+
+/* If the following macro is defined and nonzero and deterministic
+ finite state automata are used for pipeline hazard recognition, we
+ will try to exchange insns in queue ready to improve the schedule.
+ The more macro value, the more tries will be made. */
+#define FIRST_CYCLE_MULTIPASS_SCHEDULING 1
+
+/* The following macro is used only when value of
+ FIRST_CYCLE_MULTIPASS_SCHEDULING is nonzero. The more macro value,
+ the more tries will be made to choose better schedule. If the
+ macro value is zero or negative there will be no multi-pass
+ scheduling. */
+#define FIRST_CYCLE_MULTIPASS_SCHEDULING_LOOKAHEAD frv_sched_lookahead
+
+/* Return true if a function is ok to be called as a sibcall. */
+#define FUNCTION_OK_FOR_SIBCALL(DECL) 0
+
+enum frv_builtins
+{
+ FRV_BUILTIN_MAND,
+ FRV_BUILTIN_MOR,
+ FRV_BUILTIN_MXOR,
+ FRV_BUILTIN_MNOT,
+ FRV_BUILTIN_MAVEH,
+ FRV_BUILTIN_MSATHS,
+ FRV_BUILTIN_MSATHU,
+ FRV_BUILTIN_MADDHSS,
+ FRV_BUILTIN_MADDHUS,
+ FRV_BUILTIN_MSUBHSS,
+ FRV_BUILTIN_MSUBHUS,
+ FRV_BUILTIN_MPACKH,
+ FRV_BUILTIN_MQADDHSS,
+ FRV_BUILTIN_MQADDHUS,
+ FRV_BUILTIN_MQSUBHSS,
+ FRV_BUILTIN_MQSUBHUS,
+ FRV_BUILTIN_MUNPACKH,
+ FRV_BUILTIN_MDPACKH,
+ FRV_BUILTIN_MBTOH,
+ FRV_BUILTIN_MHTOB,
+ FRV_BUILTIN_MCOP1,
+ FRV_BUILTIN_MCOP2,
+ FRV_BUILTIN_MROTLI,
+ FRV_BUILTIN_MROTRI,
+ FRV_BUILTIN_MWCUT,
+ FRV_BUILTIN_MSLLHI,
+ FRV_BUILTIN_MSRLHI,
+ FRV_BUILTIN_MSRAHI,
+ FRV_BUILTIN_MEXPDHW,
+ FRV_BUILTIN_MEXPDHD,
+ FRV_BUILTIN_MMULHS,
+ FRV_BUILTIN_MMULHU,
+ FRV_BUILTIN_MMULXHS,
+ FRV_BUILTIN_MMULXHU,
+ FRV_BUILTIN_MMACHS,
+ FRV_BUILTIN_MMACHU,
+ FRV_BUILTIN_MMRDHS,
+ FRV_BUILTIN_MMRDHU,
+ FRV_BUILTIN_MQMULHS,
+ FRV_BUILTIN_MQMULHU,
+ FRV_BUILTIN_MQMULXHU,
+ FRV_BUILTIN_MQMULXHS,
+ FRV_BUILTIN_MQMACHS,
+ FRV_BUILTIN_MQMACHU,
+ FRV_BUILTIN_MCPXRS,
+ FRV_BUILTIN_MCPXRU,
+ FRV_BUILTIN_MCPXIS,
+ FRV_BUILTIN_MCPXIU,
+ FRV_BUILTIN_MQCPXRS,
+ FRV_BUILTIN_MQCPXRU,
+ FRV_BUILTIN_MQCPXIS,
+ FRV_BUILTIN_MQCPXIU,
+ FRV_BUILTIN_MCUT,
+ FRV_BUILTIN_MCUTSS,
+ FRV_BUILTIN_MWTACC,
+ FRV_BUILTIN_MWTACCG,
+ FRV_BUILTIN_MRDACC,
+ FRV_BUILTIN_MRDACCG,
+ FRV_BUILTIN_MTRAP,
+ FRV_BUILTIN_MCLRACC,
+ FRV_BUILTIN_MCLRACCA,
+ FRV_BUILTIN_MDUNPACKH,
+ FRV_BUILTIN_MBTOHE,
+ FRV_BUILTIN_MQXMACHS,
+ FRV_BUILTIN_MQXMACXHS,
+ FRV_BUILTIN_MQMACXHS,
+ FRV_BUILTIN_MADDACCS,
+ FRV_BUILTIN_MSUBACCS,
+ FRV_BUILTIN_MASACCS,
+ FRV_BUILTIN_MDADDACCS,
+ FRV_BUILTIN_MDSUBACCS,
+ FRV_BUILTIN_MDASACCS,
+ FRV_BUILTIN_MABSHS,
+ FRV_BUILTIN_MDROTLI,
+ FRV_BUILTIN_MCPLHI,
+ FRV_BUILTIN_MCPLI,
+ FRV_BUILTIN_MDCUTSSI,
+ FRV_BUILTIN_MQSATHS,
+ FRV_BUILTIN_MHSETLOS,
+ FRV_BUILTIN_MHSETLOH,
+ FRV_BUILTIN_MHSETHIS,
+ FRV_BUILTIN_MHSETHIH,
+ FRV_BUILTIN_MHDSETS,
+ FRV_BUILTIN_MHDSETH
+};
+
+/* Enable prototypes on the call rtl functions. */
+#define MD_CALL_PROTOTYPES 1
+
+extern GTY(()) rtx frv_compare_op0; /* operand save for */
+extern GTY(()) rtx frv_compare_op1; /* comparison generation */
+
+#endif /* __FRV_H__ */
diff --git a/contrib/gcc/config/frv/frv.md b/contrib/gcc/config/frv/frv.md
new file mode 100644
index 0000000..a5e82ee
--- /dev/null
+++ b/contrib/gcc/config/frv/frv.md
@@ -0,0 +1,7441 @@
+;; Frv Machine Description
+;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+;; Contributed by Red Hat, Inc.
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Unspec's used
+;; ::
+;; ::::::::::::::::::::
+
+(define_constants
+ [(UNSPEC_BLOCKAGE 0)
+ (UNSPEC_CC_TO_GPR 1)
+ (UNSPEC_GPR_TO_CC 2)
+ (UNSPEC_PIC_PROLOGUE 3)
+ (UNSPEC_CR_LOGIC 4)
+ (UNSPEC_STACK_ADJUST 5)
+ (UNSPEC_EH_RETURN_EPILOGUE 6)])
+
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Constraints
+;; ::
+;; ::::::::::::::::::::
+
+;; Standard Constraints
+;;
+;; `m' A memory operand is allowed, with any kind of address that the
+;; machine supports in general.
+;;
+;; `o' A memory operand is allowed, but only if the address is
+;; "offsettable". This means that adding a small integer (actually, the
+;; width in bytes of the operand, as determined by its machine mode) may be
+;; added to the address and the result is also a valid memory address.
+;;
+;; `V' A memory operand that is not offsettable. In other words,
+;; anything that would fit the `m' constraint but not the `o' constraint.
+;;
+;; `<' A memory operand with autodecrement addressing (either
+;; predecrement or postdecrement) is allowed.
+;;
+;; `>' A memory operand with autoincrement addressing (either
+;; preincrement or postincrement) is allowed.
+;;
+;; `r' A register operand is allowed provided that it is in a general
+;; register.
+;;
+;; `d', `a', `f', ...
+;; Other letters can be defined in machine-dependent fashion to stand for
+;; particular classes of registers. `d', `a' and `f' are defined on the
+;; 68000/68020 to stand for data, address and floating point registers.
+;;
+;; `i' An immediate integer operand (one with constant value) is allowed.
+;; This includes symbolic constants whose values will be known only at
+;; assembly time.
+;;
+;; `n' An immediate integer operand with a known numeric value is allowed.
+;; Many systems cannot support assembly-time constants for operands less
+;; than a word wide. Constraints for these operands should use `n' rather
+;; than `i'.
+;;
+;; 'I' First machine-dependent integer constant (6 bit signed ints).
+;; 'J' Second machine-dependent integer constant (10 bit signed ints).
+;; 'K' Third machine-dependent integer constant (-2048).
+;; 'L' Fourth machine-dependent integer constant (16 bit signed ints).
+;; 'M' Fifth machine-dependent integer constant (16 bit unsigned ints).
+;; 'N' Sixth machine-dependent integer constant (-2047..-1).
+;; 'O' Seventh machine-dependent integer constant (zero).
+;; 'P' Eighth machine-dependent integer constant (1..2047).
+;;
+;; Other letters in the range `I' through `P' may be defined in a
+;; machine-dependent fashion to permit immediate integer operands with
+;; explicit integer values in specified ranges. For example, on the 68000,
+;; `I' is defined to stand for the range of values 1 to 8. This is the
+;; range permitted as a shift count in the shift instructions.
+;;
+;; `E' An immediate floating operand (expression code `const_double') is
+;; allowed, but only if the target floating point format is the same as
+;; that of the host machine (on which the compiler is running).
+;;
+;; `F' An immediate floating operand (expression code `const_double') is
+;; allowed.
+;;
+;; 'G' First machine-dependent const_double.
+;; 'H' Second machine-dependent const_double.
+;;
+;; `s' An immediate integer operand whose value is not an explicit
+;; integer is allowed.
+;;
+;; This might appear strange; if an insn allows a constant operand with a
+;; value not known at compile time, it certainly must allow any known
+;; value. So why use `s' instead of `i'? Sometimes it allows better code
+;; to be generated.
+;;
+;; For example, on the 68000 in a fullword instruction it is possible to
+;; use an immediate operand; but if the immediate value is between -128 and
+;; 127, better code results from loading the value into a register and
+;; using the register. This is because the load into the register can be
+;; done with a `moveq' instruction. We arrange for this to happen by
+;; defining the letter `K' to mean "any integer outside the range -128 to
+;; 127", and then specifying `Ks' in the operand constraints.
+;;
+;; `g' Any register, memory or immediate integer operand is allowed,
+;; except for registers that are not general registers.
+;;
+;; `X' Any operand whatsoever is allowed, even if it does not satisfy
+;; `general_operand'. This is normally used in the constraint of a
+;; `match_scratch' when certain alternatives will not actually require a
+;; scratch register.
+;;
+;; `0' Match operand 0.
+;; `1' Match operand 1.
+;; `2' Match operand 2.
+;; `3' Match operand 3.
+;; `4' Match operand 4.
+;; `5' Match operand 5.
+;; `6' Match operand 6.
+;; `7' Match operand 7.
+;; `8' Match operand 8.
+;; `9' Match operand 9.
+;;
+;; An operand that matches the specified operand number is allowed. If a
+;; digit is used together with letters within the same alternative, the
+;; digit should come last.
+;;
+;; This is called a "matching constraint" and what it really means is that
+;; the assembler has only a single operand that fills two roles considered
+;; separate in the RTL insn. For example, an add insn has two input
+;; operands and one output operand in the RTL, but on most CISC machines an
+;; add instruction really has only two operands, one of them an
+;; input-output operand:
+;;
+;; addl #35,r12
+;;
+;; Matching constraints are used in these circumstances. More precisely,
+;; the two operands that match must include one input-only operand and one
+;; output-only operand. Moreover, the digit must be a smaller number than
+;; the number of the operand that uses it in the constraint.
+;;
+;; For operands to match in a particular case usually means that they are
+;; identical-looking RTL expressions. But in a few special cases specific
+;; kinds of dissimilarity are allowed. For example, `*x' as an input
+;; operand will match `*x++' as an output operand. For proper results in
+;; such cases, the output template should always use the output-operand's
+;; number when printing the operand.
+;;
+;; `p' An operand that is a valid memory address is allowed. This is for
+;; "load address" and "push address" instructions.
+;;
+;; `p' in the constraint must be accompanied by `address_operand' as the
+;; predicate in the `match_operand'. This predicate interprets the mode
+;; specified in the `match_operand' as the mode of the memory reference for
+;; which the address would be valid.
+;;
+;; `Q` First non constant, non register machine-dependent insns
+;; `R` Second non constant, non register machine-dependent insns
+;; `S` Third non constant, non register machine-dependent insns
+;; `T` Fourth non constant, non register machine-dependent insns
+;; `U` Fifth non constant, non register machine-dependent insns
+;;
+;; Letters in the range `Q' through `U' may be defined in a
+;; machine-dependent fashion to stand for arbitrary operand types. The
+;; machine description macro `EXTRA_CONSTRAINT' is passed the operand as
+;; its first argument and the constraint letter as its second operand.
+;;
+;; A typical use for this would be to distinguish certain types of memory
+;; references that affect other insn operands.
+;;
+;; Do not define these constraint letters to accept register references
+;; (`reg'); the reload pass does not expect this and would not handle it
+;; properly.
+
+;; Multiple Alternative Constraints
+;; `?' Disparage slightly the alternative that the `?' appears in, as a
+;; choice when no alternative applies exactly. The compiler regards this
+;; alternative as one unit more costly for each `?' that appears in it.
+;;
+;; `!' Disparage severely the alternative that the `!' appears in. This
+;; alternative can still be used if it fits without reloading, but if
+;; reloading is needed, some other alternative will be used.
+
+;; Constraint modifiers
+;; `=' Means that this operand is write-only for this instruction: the
+;; previous value is discarded and replaced by output data.
+;;
+;; `+' Means that this operand is both read and written by the
+;; instruction.
+;;
+;; When the compiler fixes up the operands to satisfy the constraints, it
+;; needs to know which operands are inputs to the instruction and which are
+;; outputs from it. `=' identifies an output; `+' identifies an operand
+;; that is both input and output; all other operands are assumed to be
+;; input only.
+;;
+;; `&' 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.
+;;
+;; `&' applies only to the alternative in which it is written. In
+;; constraints with multiple alternatives, sometimes one alternative
+;; requires `&' while others do not.
+;;
+;; `&' does not obviate the need to write `='.
+;;
+;; `%' Declares the instruction to be commutative for this operand and the
+;; following operand. This means that the compiler may interchange the two
+;; operands if that is the cheapest way to make all operands fit the
+;; constraints. This is often used in patterns for addition instructions
+;; that really have only two operands: the result must go in one of the
+;; arguments.
+;;
+;; `#' Says that all following characters, up to the next comma, are to be
+;; ignored as a constraint. They are significant only for choosing
+;; register preferences.
+;;
+;; `*' Says that the following character should be ignored when choosing
+;; register preferences. `*' has no effect on the meaning of the
+;; constraint as a constraint, and no effect on reloading.
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Attributes
+;; ::
+;; ::::::::::::::::::::
+
+;; The `define_attr' expression is used to define each attribute required by
+;; the target machine. It looks like:
+;;
+;; (define_attr NAME LIST-OF-VALUES DEFAULT)
+
+;; NAME is a string specifying the name of the attribute being defined.
+
+;; LIST-OF-VALUES is either a string that specifies a comma-separated list of
+;; values that can be assigned to the attribute, or a null string to indicate
+;; that the attribute takes numeric values.
+
+;; DEFAULT is an attribute expression that gives the value of this attribute
+;; for insns that match patterns whose definition does not include an explicit
+;; value for this attribute.
+
+;; For each defined attribute, a number of definitions are written to the
+;; `insn-attr.h' file. For cases where an explicit set of values is specified
+;; for an attribute, the following are defined:
+
+;; * A `#define' is written for the symbol `HAVE_ATTR_NAME'.
+;;
+;; * An enumeral class is defined for `attr_NAME' with elements of the
+;; form `UPPER-NAME_UPPER-VALUE' where the attribute name and value are first
+;; converted to upper case.
+;;
+;; * A function `get_attr_NAME' is defined that is passed an insn and
+;; returns the attribute value for that insn.
+
+;; For example, if the following is present in the `md' file:
+;;
+;; (define_attr "type" "branch,fp,load,store,arith" ...)
+;;
+;; the following lines will be written to the file `insn-attr.h'.
+;;
+;; #define HAVE_ATTR_type
+;; enum attr_type {TYPE_BRANCH, TYPE_FP, TYPE_LOAD, TYPE_STORE, TYPE_ARITH};
+;; extern enum attr_type get_attr_type ();
+
+;; If the attribute takes numeric values, no `enum' type will be defined and
+;; the function to obtain the attribute's value will return `int'.
+
+(define_attr "length" "" (const_int 4))
+
+;; Processor type -- this attribute must exactly match the processor_type
+;; enumeration in frv-protos.h.
+
+(define_attr "cpu" "generic,fr500,fr400,fr300,simple,tomcat"
+ (const (symbol_ref "frv_cpu_type")))
+
+;; Attribute is "yes" for branches and jumps that span too great a distance
+;; to be implemented in the most natural way. Such instructions will use
+;; a call instruction in some way.
+
+(define_attr "far_jump" "yes,no" (const_string "no"))
+
+;; Instruction type
+
+;; The table below summarises the types of media instruction and their
+;; scheduling classification. Headings are:
+
+;; Type: the name of the define_attr type
+;; Conditions: "yes" if conditional variants are available
+;; FR500: Fujitsu's categorisation for the FR500
+;; FR400: Fujitsu's categorisation for the FR400 (but see below).
+
+;; On the FR400, media instructions are divided into 2 broad categories.
+;; Category 1 instructions can execute in either the M0 or M1 unit and can
+;; execute in parallel with other category 1 instructions. Category 2
+;; instructions must use the M0 unit, and therefore cannot run in parallel
+;; with other media instructions.
+
+;; The FR400 documentation also divides media instructions into one of seven
+;; categories (m1 to m7). m1 to m4 contain both Category 1 and Category 2
+;; instructions, so we use a combination of the categories here.
+
+;; Type Conditional FR500 FR400
+;; ---- ---------- ----- -----
+;; mlogic yes m1 m1:1
+;; mrdacc no m2 m4:1
+;; mwtacc no m3 m5:1
+;; maveh no m1 m1:1
+;; msath no m1 m1:1
+;; maddh yes m1 m1:1
+;; mqaddh yes m1 m1:2
+;; mpackh no m2 m3:1
+;; munpackh no m2 m3:2
+;; mdpackh no m5 m3:2
+;; mbhconv yes m2 m3:2
+;; mrot no m2 m3:1
+;; mshift no m2 m3:1
+;; mexpdhw yes m2 m3:1
+;; mexpdhd yes m2 m3:2
+;; mwcut no m2 m3:2
+;; mmulh yes m4 m2:1
+;; mmulxh no m4 m2:1
+;; mmach yes m4 m2:1
+;; mmrdh no m4 m2:1
+;; mqmulh yes m4 m2:2
+;; mqmulxh no m4 m2:2
+;; mqmach yes m4 m2:2
+;; mcpx yes m4 m2:1
+;; mqcpx yes m4 m2:2
+;; mcut no m2 m4:1
+;; mclracc no m3 m4:1
+;; mclracca no m6 m4:2
+;; mdunpackh no m2 n/a
+;; mbhconve no m2 n/a
+;; maddacc no n/a m2:1
+;; mdaddacc no n/a m2:2
+;; mabsh no n/a m1:1
+;; mdrot no n/a m3:2
+;; mcpl no n/a m3:2
+;; mdcut no n/a m4:2
+;; mqsath no n/a m1:2
+;; mset no n/a m1:1
+
+(define_attr "type"
+ "int,sethi,setlo,mul,div,gload,gstore,fload,fstore,movfg,movgf,branch,jump,jumpl,call,spr,trap,fsconv,fsadd,fsmul,fmas,fsdiv,sqrt_single,fdconv,fdadd,fdmul,fddiv,sqrt_double,mlogic,maveh,msath,maddh,mqaddh,mpackh,munpackh,mdpackh,mbhconv,mrot,mshift,mexpdhw,mexpdhd,mwcut,mmulh,mmulxh,mmach,mmrdh,mqmulh,mqmulxh,mqmach,mcpx,mqcpx,mcut,mclracc,mclracca,mdunpackh,mbhconve,mrdacc,mwtacc,maddacc,mdaddacc,mabsh,mdrot,mcpl,mdcut,mqsath,mset,m7,ccr,multi,unknown"
+ (const_string "unknown"))
+
+
+
+/* This is description of pipeline hazards based on DFA. The
+ following constructions can be used for this:
+
+ o define_cpu_unit string [string]) describes a cpu functional unit
+ (separated by comma).
+
+ 1st operand: Names of cpu function units.
+ 2nd operand: Name of automaton (see comments for
+ DEFINE_AUTOMATON).
+
+ All define_reservations and define_cpu_units should have unique
+ names which can not be "nothing".
+
+ o (exclusion_set string string) means that each CPU function unit
+ in the first string can not be reserved simultaneously with each
+ unit whose name is in the second string and vise versa. CPU
+ units in the string are separated by commas. For example, it is
+ useful for description CPU with fully pipelined floating point
+ functional unit which can execute simultaneously only single
+ floating point insns or only double floating point insns.
+
+ o (presence_set string string) means that each CPU function unit in
+ the first string can not be reserved unless at least one of units
+ whose names are in the second string is reserved. This is an
+ asymmetric relation. CPU units in the string are separated by
+ commas. For example, it is useful for description that slot1 is
+ reserved after slot0 reservation for a VLIW processor.
+
+ o (absence_set string string) means that each CPU function unit in
+ the first string can not be reserved only if each unit whose name
+ is in the second string is not reserved. This is an asymmetric
+ relation (actually exclusion set is analogous to this one but it
+ is symmetric). CPU units in the string are separated by commas.
+ For example, it is useful for description that slot0 can not be
+ reserved after slot1 or slot2 reservation for a VLIW processor.
+
+ o (define_bypass number out_insn_names in_insn_names) names bypass with
+ given latency (the first number) from insns given by the first
+ string (see define_insn_reservation) into insns given by the
+ second string. Insn names in the strings are separated by
+ commas.
+
+ o (define_automaton string) describes names of an automaton
+ generated and used for pipeline hazards recognition. The names
+ are separated by comma. Actually it is possibly to generate the
+ single automaton but unfortunately it can be very large. If we
+ use more one automata, the summary size of the automata usually
+ is less than the single one. The automaton name is used in
+ define_cpu_unit. All automata should have unique names.
+
+ o (define_reservation string string) names reservation (the first
+ string) of cpu functional units (the 2nd string). Sometimes unit
+ reservations for different insns contain common parts. In such
+ case, you describe common part and use one its name (the 1st
+ parameter) in regular expression in define_insn_reservation. All
+ define_reservations, define results and define_cpu_units should
+ have unique names which can not be "nothing".
+
+ o (define_insn_reservation name default_latency condition regexpr)
+ describes reservation of cpu functional units (the 3nd operand)
+ for instruction which is selected by the condition (the 2nd
+ parameter). The first parameter is used for output of debugging
+ information. The reservations are described by a regular
+ expression according the following syntax:
+
+ regexp = regexp "," oneof
+ | oneof
+
+ oneof = oneof "|" allof
+ | allof
+
+ allof = allof "+" repeat
+ | repeat
+
+ repeat = element "*" number
+ | element
+
+ element = cpu_function_name
+ | reservation_name
+ | result_name
+ | "nothing"
+ | "(" regexp ")"
+
+ 1. "," is used for describing start of the next cycle in
+ reservation.
+
+ 2. "|" is used for describing the reservation described by the
+ first regular expression *or* the reservation described by
+ the second regular expression *or* etc.
+
+ 3. "+" is used for describing the reservation described by the
+ first regular expression *and* the reservation described by
+ the second regular expression *and* etc.
+
+ 4. "*" is used for convinience and simply means sequence in
+ which the regular expression are repeated NUMBER times with
+ cycle advancing (see ",").
+
+ 5. cpu function unit name which means reservation.
+
+ 6. reservation name -- see define_reservation.
+
+ 7. string "nothing" means no units reservation.
+
+*/
+
+(define_automaton "nodiv, idiv, div")
+
+;; An FR500 packet can contain a single control instruction or a sequence
+;; of up to four operations matching the regular expression:
+
+;; (I FM? I? FM? | FM? FM?) B? B?
+
+;; where I denotes an integer operation, FM a floating-point or media
+;; operation, and B a branch operation. There are two units for each type
+;; of instruction: I0 and I1, FM0 and FM1, and B0 and B1. Units are
+;; allocated left-to-right: the first integer instruction uses I0, the
+;; second uses I1, and so on.
+
+;; The FR400 is similar to the FR500 except that it allows only 2 operations
+;; per packet and has only one branch unit. We can use the FR500 conflict
+;; description for the FR400, but need to define different cpu_units
+;; later.
+
+;; Slot/unit combinations available on the FR400 and above:
+(define_cpu_unit "sl0_i0, sl0_fm0, sl0_b0, sl0_c" "nodiv")
+(define_cpu_unit "sl1_fm0, sl1_i1, sl1_fm1, sl1_b0" "nodiv")
+
+;; These are available on the FR500 and above:
+(define_cpu_unit "sl1_b1" "nodiv")
+(define_cpu_unit "sl2_i1, sl2_fm1, sl2_b0, sl2_b1" "nodiv")
+(define_cpu_unit "sl3_fm1, sl3_b0, sl3_b1" "nodiv")
+
+;; The following describes conlicts by slots
+;; slot0
+(exclusion_set "sl0_i0" "sl0_fm0,sl0_b0,sl0_c")
+(exclusion_set "sl0_fm0" "sl0_b0,sl0_c")
+(exclusion_set "sl0_b0" "sl0_c")
+
+;; slot1
+(exclusion_set "sl1_fm0" "sl1_i1,sl1_fm1,sl1_b0,sl1_b1")
+(exclusion_set "sl1_i1" "sl1_fm1,sl1_b0,sl1_b1")
+(exclusion_set "sl1_fm1" "sl1_b0,sl1_b1")
+(exclusion_set "sl1_b0" "sl1_b1")
+
+;; slot2
+(exclusion_set "sl2_i1" "sl2_fm1,sl2_b0,sl2_b1")
+(exclusion_set "sl2_fm1" "sl2_b0,sl2_b1")
+(exclusion_set "sl2_b0" "sl2_b1")
+
+;; slot3
+(exclusion_set "sl3_fm1" "sl3_b0,sl3_b1")
+(exclusion_set "sl3_b0" "sl3_b1")
+
+;; The following describes conlicts by units
+;; fm0
+(exclusion_set "sl0_fm0" "sl1_fm0")
+
+;; b0
+(exclusion_set "sl0_b0" "sl1_b0,sl2_b0,sl3_b0")
+(exclusion_set "sl1_b0" "sl2_b0,sl3_b0")
+(exclusion_set "sl2_b0" "sl3_b0")
+
+;; i1
+(exclusion_set "sl1_i1" "sl2_i1")
+
+;; fm1
+(exclusion_set "sl1_fm1" "sl2_fm1,sl3_fm1")
+(exclusion_set "sl2_fm1" "sl3_fm1")
+
+;; b1
+(exclusion_set "sl1_b1" "sl2_b1,sl3_b1")
+(exclusion_set "sl2_b1" "sl3_b1")
+
+;; The following describes remaining combinations of conflicts
+;; slot0
+(exclusion_set "sl0_i0" "sl1_fm1,sl1_b1")
+(exclusion_set "sl0_fm0" "sl1_i1,sl1_b1,sl2_i1,sl2_fm1,sl3_fm1,sl3_b0")
+(exclusion_set "sl0_b0" "sl1_fm0,sl1_i1,sl1_fm1,sl2_i1,sl2_fm1,sl2_b1,\
+ sl3_fm1,sl3_b1")
+(exclusion_set "sl0_c" "sl1_fm0,sl1_i1,sl1_fm1,sl1_b0,sl1_b1,sl2_i1,sl2_fm1,\
+ sl2_b0,sl2_b1,sl3_fm1,sl3_b0,sl3_b1")
+
+
+;; slot1
+(exclusion_set "sl1_fm0" "sl2_b1")
+(exclusion_set "sl1_i1" "sl2_fm1,sl2_b1,sl3_fm1,sl3_b0")
+(exclusion_set "sl1_fm1" "sl2_i1,sl2_b1,sl3_b0")
+(exclusion_set "sl1_b0" "sl2_i1,sl2_fm1,sl3_fm1,sl3_b1")
+(exclusion_set "sl1_b1" "sl2_i1,sl2_fm1,sl2_b0,sl3_fm1,sl3_b0")
+
+;; slot2
+(exclusion_set "sl2_i1" "sl3_b1")
+(exclusion_set "sl2_fm1" "sl3_b1")
+(exclusion_set "sl2_b0" "sl3_fm1")
+(exclusion_set "sl2_b1" "sl3_fm1,sl3_b0")
+
+;; slot3
+(exclusion_set "sl1_fm0" "sl2_i1,sl2_fm1,sl2_b0,sl2_b1,sl3_fm1,sl3_b0,sl3_b1")
+(exclusion_set "sl3_fm1" "sl2_i1,sl2_fm1,sl2_b0,sl2_b1,sl3_b0,sl3_b1")
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Generic/FR500 scheduler description
+;; ::
+;; ::::::::::::::::::::
+
+;; Define reservation in order to describe only in terms of units.
+
+(define_reservation "i0" "sl0_i0")
+(define_reservation "f0" "sl0_fm0|sl1_fm0")
+(define_reservation "m0" "f0")
+(define_reservation "b0" "sl0_b0|sl1_b0|sl2_b0|sl3_b0")
+(define_reservation "c" "sl0_c")
+(define_reservation "i1" "sl1_i1|sl2_i1")
+(define_reservation "f1" "sl1_fm1|sl2_fm1|sl3_fm1")
+(define_reservation "m1" "f1")
+(define_reservation "b1" "sl1_b1|sl2_b1|sl3_b1")
+
+;; Integer insns
+;; It is not possibly to issue load & store in one VLIW insn.
+(define_cpu_unit "idiv1" "idiv")
+(define_cpu_unit "idiv2" "idiv")
+(define_cpu_unit "l0" "nodiv")
+(define_cpu_unit "l1" "nodiv")
+(define_cpu_unit "s0" "nodiv")
+
+(exclusion_set "l1,l0" "s0")
+
+;; We set the default_latency of sethi to be 0 to allow sethi and setlo to be
+;; combined in the same VLIW instruction as allowed by the architecture. This
+;; assumes the only use of sethi is always followed by a setlo of the same
+;; register.
+(define_insn_reservation "i1_sethi" 0
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "sethi"))
+ "i0|i1")
+
+(define_insn_reservation "i1_setlo" 1
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "setlo"))
+ "i0|i1")
+
+(define_insn_reservation "i1_int" 1
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "int"))
+ "i0|i1")
+
+(define_insn_reservation "i1_mul" 3
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "mul"))
+ "i0|i1")
+
+(define_insn_reservation "i1_div" 19
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "div"))
+ "(i0|i1),(idiv1*18|idiv2*18)")
+
+(define_insn_reservation "i2_gload" 4
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "gload"))
+ "(i0|i1)+(l0|l1)")
+
+(define_insn_reservation "i2_fload" 4
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "fload"))
+ "(i0|i1)+(l0|l1)")
+
+(define_insn_reservation "i3_gstore" 0
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "gstore"))
+ "i0+s0")
+
+(define_insn_reservation "i3_fstore" 0
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "fstore"))
+ "i0+s0")
+
+(define_insn_reservation "i4_move_gf" 3
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "movgf"))
+ "i0")
+
+(define_insn_reservation "i4_move_fg" 3
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "movfg"))
+ "i0")
+
+(define_insn_reservation "i5" 0
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "jumpl"))
+ "i0")
+
+;; Clear/commit is not generated now:
+(define_insn_reservation "i6" 0 (const_int 0) "i0|i1")
+
+;;
+;; Branch-instructions
+;;
+(define_insn_reservation "b1/b3" 0
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "jump,branch,ccr"))
+ "b0|b1")
+
+;; The following insn is not generated now.
+
+(define_insn_reservation "b2" 0 (const_int 0) "b0")
+
+(define_insn_reservation "b4" 0
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "call"))
+ "b0")
+
+;; The following insns are not generated now.
+(define_insn_reservation "b5" 0 (const_int 0) "b0|b1")
+(define_insn_reservation "b6" 0 (const_int 0) "b0|b1")
+
+;; Control insns
+(define_insn_reservation "trap" 0
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "trap"))
+ "c")
+
+(define_insn_reservation "control" 0
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "spr"))
+ "c")
+
+;; Floating point insns
+(define_cpu_unit "add0" "nodiv")
+(define_cpu_unit "add1" "nodiv")
+(define_cpu_unit "mul0" "nodiv")
+(define_cpu_unit "mul1" "nodiv")
+(define_cpu_unit "div1" "div")
+(define_cpu_unit "div2" "div")
+(define_cpu_unit "root" "div")
+
+(define_bypass 4 "f1" "m1,m2,m3,m4,m5,m6,m7")
+(define_insn_reservation "f1" 3
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "fsconv,fdconv"))
+ "(f0|f1)")
+
+(define_bypass 4 "f2" "m1,m2,m3,m4,m5,m6,m7")
+(define_insn_reservation "f2" 3
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "fsadd,fdadd"))
+ "(f0|f1)+(add0|add1)")
+
+(define_bypass 4 "f3" "m1,m2,m3,m4,m5,m6,m7")
+(define_insn_reservation "f3" 3
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "fsmul,fdmul"))
+ "(f0|f1)+(mul0|mul1)")
+
+(define_bypass 11 "f4_div" "m1,m2,m3,m4,m5,m6,m7")
+(define_insn_reservation "f4_div" 10
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "fsdiv,fddiv"))
+ "(f0|f1),(div1*9|div2*9)")
+
+(define_bypass 16 "f4_root" "m1,m2,m3,m4,m5,m6,m7")
+(define_insn_reservation "f4_root" 15
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "sqrt_single,sqrt_double"))
+ "(f0|f1)+root*15")
+
+(define_bypass 4 "f5" "m1,m2,m3,m4,m5,m6,m7")
+(define_insn_reservation "f5" 3
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "fmas"))
+ "(f0|f1)+(add0|add1)+(mul0|mul1)")
+
+;; The following insns are not generated by gcc now:
+(define_insn_reservation "f6" 0 (const_int 0) "(f0|f1)+add0+add1")
+(define_insn_reservation "f7" 0 (const_int 0) "(f0|f1)+mul0+mul1")
+
+;; Media insns. Now they are all not generated now.
+(define_cpu_unit "m1_0" "nodiv")
+(define_cpu_unit "m1_1" "nodiv")
+(define_cpu_unit "m2_0" "nodiv")
+(define_cpu_unit "m2_1" "nodiv")
+(define_cpu_unit "m3_0" "nodiv")
+(define_cpu_unit "m3_1" "nodiv")
+(define_cpu_unit "m4_0" "nodiv")
+(define_cpu_unit "m4_1" "nodiv")
+(define_cpu_unit "m5" "nodiv")
+(define_cpu_unit "m6" "nodiv")
+(define_cpu_unit "m7" "nodiv")
+
+(exclusion_set "m5,m6,m7" "m2_0,m2_1,m3_0,m3_1")
+(exclusion_set "m5" "m6,m7")
+(exclusion_set "m6" "m4_0,m4_1,m7")
+(exclusion_set "m7" "m1_0,m1_1,add0,add1,mul0,mul1")
+
+(define_bypass 2 "m1" "m1,m2,m3,m4,m5,m6,m7")
+(define_bypass 4 "m1" "f1,f2,f3,f4_div,f4_root,f5,f6,f7")
+(define_insn_reservation "m1" 3
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "mlogic,maveh,msath,maddh,mqaddh"))
+ "(m0|m1)+(m1_0|m1_1)")
+
+(define_bypass 2 "m2" "m1,m2,m3,m4,m5,m6,m7")
+(define_bypass 4 "m2" "f1,f2,f3,f4_div,f4_root,f5,f6,f7")
+(define_insn_reservation "m2" 3
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "mrdacc,mpackh,munpackh,mbhconv,mrot,mshift,mexpdhw,mexpdhd,mwcut,mcut,mdunpackh,mbhconve"))
+ "(m0|m1)+(m2_0|m2_1)")
+
+(define_bypass 1 "m3" "m4")
+(define_insn_reservation "m3" 2
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "mclracc,mwtacc"))
+ "(m0|m1)+(m3_0|m3_1)")
+
+(define_bypass 1 "m4" "m4")
+(define_insn_reservation "m4" 2
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "mmulh,mmulxh,mmach,mmrdh,mqmulh,mqmulxh,mqmach,mcpx,mqcpx"))
+ "(m0|m1)+(m4_0|m4_1)")
+
+(define_bypass 2 "m5" "m1,m2,m3,m4,m5,m6,m7")
+(define_bypass 4 "m5" "f1,f2,f3,f4_div,f4_root,f5,f6,f7")
+(define_insn_reservation "m5" 3
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "mdpackh"))
+ "(m0|m1)+m5")
+
+(define_bypass 1 "m6" "m4")
+(define_insn_reservation "m6" 2
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "mclracca"))
+ "(m0|m1)+m6")
+
+(define_bypass 2 "m7" "m1,m2,m3,m4,m5,m6,m7")
+(define_bypass 4 "m7" "f1,f2,f3,f4_div,f4_root,f5,f6,f7")
+
+(define_insn_reservation "m7" 3
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "m7"))
+ "(m0|m1)+m7")
+
+;; Unknown & multi insns starts on new cycle and the next insn starts
+;; on new cycle. To describe this we consider as a control insn.
+(define_insn_reservation "unknown" 1
+ (and (eq_attr "cpu" "generic,fr500,tomcat")
+ (eq_attr "type" "unknown,multi"))
+ "c")
+
+;; ::::::::::::::::::::
+;; ::
+;; :: FR400 scheduler description
+;; ::
+;; ::::::::::::::::::::
+
+;; Category 2 media instructions use both media units, but can be packed
+;; with non-media instructions. Use fr400_m1unit to claim the M1 unit
+;; without claiming a slot.
+
+(define_cpu_unit "fr400_m1unit" "nodiv")
+
+(define_reservation "fr400_i0" "sl0_i0")
+(define_reservation "fr400_i1" "sl1_i1")
+(define_reservation "fr400_m0" "sl0_fm0|sl1_fm0")
+(define_reservation "fr400_m1" "sl1_fm1")
+(define_reservation "fr400_meither" "fr400_m0|(fr400_m1+fr400_m1unit)")
+(define_reservation "fr400_mboth" "fr400_m0+fr400_m1unit")
+(define_reservation "fr400_b" "sl0_b0|sl1_b0")
+(define_reservation "fr400_c" "sl0_c")
+
+;; Name Class Units Latency
+;; ==== ===== ===== =======
+;; int I1 I0/I1 1
+;; sethi I1 I0/I1 0 -- does not interfere with setlo
+;; setlo I1 I0/I1 1
+;; mul I1 I0 3 (*)
+;; div I1 I0 20 (*)
+;; gload I2 I0 4 (*)
+;; fload I2 I0 4 -- only 3 if read by a media insn
+;; gstore I3 I0 0 -- provides no result
+;; fstore I3 I0 0 -- provides no result
+;; movfg I4 I0 3 (*)
+;; movgf I4 I0 3 (*)
+;; jumpl I5 I0 0 -- provides no result
+;;
+;; (*) The results of these instructions can be read one cycle earlier
+;; than indicated. The penalty given is for instructions with write-after-
+;; write dependencies.
+
+;; The FR400 can only do loads and stores in I0, so we there's no danger
+;; of memory unit collision in the same packet. There's only one divide
+;; unit too.
+
+(define_insn_reservation "fr400_i1_int" 1
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "int"))
+ "fr400_i0|fr400_i1")
+
+(define_insn_reservation "fr400_i1_sethi" 0
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "sethi"))
+ "fr400_i0|fr400_i1")
+
+(define_insn_reservation "fr400_i1_setlo" 1
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "setlo"))
+ "fr400_i0|fr400_i1")
+
+(define_insn_reservation "fr400_i1_mul" 3
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "mul"))
+ "fr400_i0")
+
+(define_insn_reservation "fr400_i1_div" 20
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "div"))
+ "fr400_i0+idiv1*19")
+
+(define_insn_reservation "fr400_i2_gload" 4
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "gload"))
+ "fr400_i0")
+
+(define_insn_reservation "fr400_i2_fload" 4
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "fload"))
+ "fr400_i0")
+
+(define_insn_reservation "fr400_i3_gstore" 0
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "gstore"))
+ "fr400_i0")
+
+(define_insn_reservation "fr400_i3_fstore" 0
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "fstore"))
+ "fr400_i0")
+
+(define_insn_reservation "fr400_i4_movfg" 3
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "movfg"))
+ "fr400_i0")
+
+(define_insn_reservation "fr400_i4_movgf" 3
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "movgf"))
+ "fr400_i0")
+
+(define_insn_reservation "fr400_i5_jumpl" 0
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "jumpl"))
+ "fr400_i0")
+
+;; The bypass between FPR loads and media instructions, described above.
+
+(define_bypass 3
+ "fr400_i2_fload"
+ "fr400_m1_1,fr400_m1_2,\
+ fr400_m2_1,fr400_m2_2,\
+ fr400_m3_1,fr400_m3_2,\
+ fr400_m4_1,fr400_m4_2,\
+ fr400_m5")
+
+;; The branch instructions all use the B unit and produce no result.
+
+(define_insn_reservation "fr400_b" 0
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "jump,branch,ccr,call"))
+ "fr400_b")
+
+;; Control instructions use the C unit, which excludes all the others.
+
+(define_insn_reservation "fr400_c" 0
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "spr,trap"))
+ "fr400_c")
+
+;; Unknown instructions use the C unit, since it requires single-operation
+;; packets.
+
+(define_insn_reservation "fr400_unknown" 1
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "unknown,multi"))
+ "fr400_c")
+
+;; FP->FP moves are marked as "fsconv" instructions in the define_insns
+;; below, but are implemented on the FR400 using "mlogic" instructions.
+;; It's easier to class "fsconv" as a "m1:1" instruction than provide
+;; separate define_insns for the FR400.
+
+;; M1 instructions store their results in FPRs. Any instruction can read
+;; the result in the following cycle, so no penalty occurs.
+
+(define_insn_reservation "fr400_m1_1" 1
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "fsconv,mlogic,maveh,msath,maddh,mabsh,mset"))
+ "fr400_meither")
+
+(define_insn_reservation "fr400_m1_2" 1
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "mqaddh,mqsath"))
+ "fr400_mboth")
+
+;; M2 instructions store their results in accumulators, which are read
+;; by M2 or M4 media commands. M2 instructions can read the results in
+;; the following cycle, but M4 instructions must wait a cycle more.
+
+(define_bypass 1
+ "fr400_m2_1,fr400_m2_2"
+ "fr400_m2_1,fr400_m2_2")
+
+(define_insn_reservation "fr400_m2_1" 2
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "mmulh,mmulxh,mmach,mmrdh,mcpx,maddacc"))
+ "fr400_meither")
+
+(define_insn_reservation "fr400_m2_2" 2
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "mqmulh,mqmulxh,mqmach,mqcpx,mdaddacc"))
+ "fr400_mboth")
+
+;; For our purposes, there seems to be little real difference between
+;; M1 and M3 instructions. Keep them separate anyway in case the distinction
+;; is needed later.
+
+(define_insn_reservation "fr400_m3_1" 1
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "mpackh,mrot,mshift,mexpdhw"))
+ "fr400_meither")
+
+(define_insn_reservation "fr400_m3_2" 1
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "munpackh,mdpackh,mbhconv,mexpdhd,mwcut,mdrot,mcpl"))
+ "fr400_mboth")
+
+;; M4 instructions write to accumulators or FPRs. MOVFG and STF
+;; instructions can read an FPR result in the following cycle, but
+;; M-unit instructions must wait a cycle more for either kind of result.
+
+(define_bypass 1
+ "fr400_m4_1,fr400_m4_2"
+ "fr400_i3_fstore,fr400_i4_movfg")
+
+(define_insn_reservation "fr400_m4_1" 2
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "mrdacc,mcut,mclracc"))
+ "fr400_meither")
+
+(define_insn_reservation "fr400_m4_2" 2
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "mclracca,mdcut"))
+ "fr400_mboth")
+
+;; M5 instructions always incur a 1-cycle penalty.
+
+(define_insn_reservation "fr400_m5" 2
+ (and (eq_attr "cpu" "fr400")
+ (eq_attr "type" "mwtacc"))
+ "fr400_mboth")
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Simple/FR300 scheduler description
+;; ::
+;; ::::::::::::::::::::
+
+;; Fr300 or simple processor. To describe it as 1 insn issue
+;; processor, we use control unit.
+
+(define_insn_reservation "fr300_lat1" 1
+ (and (eq_attr "cpu" "fr300,simple")
+ (eq_attr "type" "!gload,fload,movfg,movgf"))
+ "c")
+
+(define_insn_reservation "fr300_lat2" 2
+ (and (eq_attr "cpu" "fr300,simple")
+ (eq_attr "type" "gload,fload,movfg,movgf"))
+ "c")
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Delay Slots
+;; ::
+;; ::::::::::::::::::::
+
+;; The insn attribute mechanism can be used to specify the requirements for
+;; delay slots, if any, on a target machine. An instruction is said to require
+;; a "delay slot" if some instructions that are physically after the
+;; instruction are executed as if they were located before it. Classic
+;; examples are branch and call instructions, which often execute the following
+;; instruction before the branch or call is performed.
+
+;; On some machines, conditional branch instructions can optionally "annul"
+;; instructions in the delay slot. This means that the 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
+;; instructions. See the next section for a discussion of data-dependent
+;; instruction scheduling.
+
+;; The requirement of an insn needing one or more delay slots is indicated via
+;; the `define_delay' expression. It has the following form:
+;;
+;; (define_delay TEST
+;; [DELAY-1 ANNUL-TRUE-1 ANNUL-FALSE-1
+;; DELAY-2 ANNUL-TRUE-2 ANNUL-FALSE-2
+;; ...])
+
+;; TEST is an attribute test that indicates whether this `define_delay' applies
+;; to a particular insn. If so, the number of required delay slots is
+;; determined by the length of the vector specified as the second argument. An
+;; insn placed in delay slot N must satisfy attribute test DELAY-N.
+;; ANNUL-TRUE-N is an attribute test that specifies which insns may be annulled
+;; if the branch is true. Similarly, ANNUL-FALSE-N specifies which insns in
+;; the delay slot may be annulled if the branch is false. If annulling is not
+;; supported for that delay slot, `(nil)' should be coded.
+
+;; For example, in the common case where branch and call insns require a single
+;; delay slot, which may contain any insn other than a branch or call, the
+;; following would be placed in the `md' file:
+
+;; (define_delay (eq_attr "type" "branch,call")
+;; [(eq_attr "type" "!branch,call") (nil) (nil)])
+
+;; Multiple `define_delay' expressions may be specified. In this case, each
+;; such expression specifies different delay slot requirements and there must
+;; be no insn for which tests in two `define_delay' expressions are both true.
+
+;; For example, if we have a machine that requires one delay slot for branches
+;; but two for calls, no delay slot can contain a branch or call insn, and any
+;; valid insn in the delay slot for the branch can be annulled if the branch is
+;; true, we might represent this as follows:
+
+;; (define_delay (eq_attr "type" "branch")
+;; [(eq_attr "type" "!branch,call")
+;; (eq_attr "type" "!branch,call")
+;; (nil)])
+;;
+;; (define_delay (eq_attr "type" "call")
+;; [(eq_attr "type" "!branch,call") (nil) (nil)
+;; (eq_attr "type" "!branch,call") (nil) (nil)])
+
+;; Note - it is the backend's responsibility to fill any unfilled delay slots
+;; at assembler generation time. This is usually done by adding a special print
+;; operand to the delayed insrtuction, and then in the PRINT_OPERAND function
+;; calling dbr_sequence_length() to determine how many delay slots were filled.
+;; For example:
+;;
+;; --------------<machine>.md-----------------
+;; (define_insn "call"
+;; [(call (match_operand 0 "memory_operand" "m")
+;; (match_operand 1 "" ""))]
+;; ""
+;; "call_delayed %0,%1,%2%#"
+;; [(set_attr "length" "4")
+;; (set_attr "type" "call")])
+;;
+;; -------------<machine>.h-------------------
+;; #define PRINT_OPERAND_PUNCT_VALID_P(CODE) (CODE == '#')
+;;
+;; ------------<machine>.c------------------
+;; void
+;; machine_print_operand (file, x, code)
+;; FILE * file;
+;; rtx x;
+;; int code;
+;; {
+;; switch (code)
+;; {
+;; case '#':
+;; if (dbr_sequence_length () == 0)
+;; fputs ("\n\tnop", file);
+;; return;
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Notes on Patterns
+;; ::
+;; ::::::::::::::::::::
+
+;; If you need to construct a sequence of assembler instructions in order
+;; to implement a pattern be sure to escape any backslashes and double quotes
+;; that you use, eg:
+;;
+;; (define_insn "an example"
+;; [(some rtl)]
+;; ""
+;; "*
+;; { static char buffer [100];
+;; sprintf (buffer, \"insn \\t %d\", REGNO (operands[1]));
+;; return buffer;
+;; }"
+;; )
+;;
+;; Also if there is more than one instruction, they can be separated by \\;
+;; which is a space saving synonym for \\n\\t:
+;;
+;; (define_insn "another example"
+;; [(some rtl)]
+;; ""
+;; "*
+;; { static char buffer [100];
+;; sprintf (buffer, \"insn1 \\t %d\\;insn2 \\t %%1\",
+;; REGNO (operands[1]));
+;; return buffer;
+;; }"
+;; )
+;;
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Moves
+;; ::
+;; ::::::::::::::::::::
+
+;; Wrap moves in define_expand to prevent memory->memory moves from being
+;; generated at the RTL level, which generates better code for most machines
+;; which can't do mem->mem moves.
+
+;; If operand 0 is a `subreg' with mode M of a register whose own mode is wider
+;; than M, the effect of this instruction is to store the specified value in
+;; the part of the register that corresponds to mode M. The effect on the rest
+;; of the register is undefined.
+
+;; This class of patterns is special in several ways. First of all, each of
+;; these names *must* be defined, because there is no other way to copy a datum
+;; from one place to another.
+
+;; Second, these patterns are not used solely in the RTL generation pass. Even
+;; the reload pass can generate move insns to copy values from stack slots into
+;; temporary registers. When it does so, one of the operands is a hard
+;; register and the other is an operand that can need to be reloaded into a
+;; register.
+
+;; Therefore, when given such a pair of operands, the pattern must
+;; generate RTL which needs no reloading and needs no temporary
+;; registers--no registers other than the operands. For example, if
+;; you support the pattern with a `define_expand', then in such a
+;; case the `define_expand' mustn't call `force_reg' or any other such
+;; function which might generate new pseudo registers.
+
+;; This requirement exists even for subword modes on a RISC machine
+;; where fetching those modes from memory normally requires several
+;; insns and some temporary registers. Look in `spur.md' to see how
+;; the requirement can be satisfied.
+
+;; During reload a memory reference with an invalid address may be passed as an
+;; operand. Such an address will be replaced with a valid address later in the
+;; reload pass. In this case, nothing may be done with the address except to
+;; use it as it stands. If it is copied, it will not be replaced with a valid
+;; address. No attempt should be made to make such an address into a valid
+;; address and no routine (such as `change_address') that will do so may be
+;; called. Note that `general_operand' will fail when applied to such an
+;; address.
+;;
+;; The global variable `reload_in_progress' (which must be explicitly declared
+;; if required) can be used to determine whether such special handling is
+;; required.
+;;
+;; The variety of operands that have reloads depends on the rest of
+;; the machine description, but typically on a RISC machine these can
+;; only be pseudo registers that did not get hard registers, while on
+;; other machines explicit memory references will get optional
+;; reloads.
+;;
+;; If a scratch register is required to move an object to or from memory, it
+;; can be allocated using `gen_reg_rtx' prior to reload. But this is
+;; impossible during and after reload. If there are cases needing scratch
+;; registers after reload, you must define `SECONDARY_INPUT_RELOAD_CLASS' and
+;; perhaps also `SECONDARY_OUTPUT_RELOAD_CLASS' to detect them, and provide
+;; patterns `reload_inM' or `reload_outM' to handle them.
+
+;; The constraints on a `moveM' must permit moving any hard register to any
+;; other hard register provided that `HARD_REGNO_MODE_OK' permits mode M in
+;; both registers and `REGISTER_MOVE_COST' applied to their classes returns a
+;; value of 2.
+
+;; It is obligatory to support floating point `moveM' instructions
+;; into and out of any registers that can hold fixed point values,
+;; because unions and structures (which have modes `SImode' or
+;; `DImode') can be in those registers and they may have floating
+;; point members.
+
+;; There may also be a need to support fixed point `moveM' 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 `HARD_REGNO_MODE_OK'
+;; rejects fixed point values in floating point registers, then the constraints
+;; of the fixed point `moveM' instructions must be designed to avoid ever
+;; trying to reload into a floating point register.
+
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (!reload_in_progress
+ && !reload_completed
+ && !register_operand (operands[0], QImode)
+ && !reg_or_0_operand (operands[1], QImode))
+ operands[1] = copy_to_mode_reg (QImode, operands[1]);
+}")
+
+(define_insn "*movqi_load"
+ [(set (match_operand:QI 0 "register_operand" "=d,f")
+ (match_operand:QI 1 "frv_load_operand" "m,m"))]
+ ""
+ "* return output_move_single (operands, insn);"
+ [(set_attr "length" "4")
+ (set_attr "type" "gload,fload")])
+
+(define_insn "*movqi_internal"
+ [(set (match_operand:QI 0 "move_destination_operand" "=d,d,m,m,?f,?f,?d,?m,f")
+ (match_operand:QI 1 "move_source_operand" "L,d,d,O, d, f, f, f,GO"))]
+ "register_operand(operands[0], QImode) || reg_or_0_operand (operands[1], QImode)"
+ "* return output_move_single (operands, insn);"
+ [(set_attr "length" "4")
+ (set_attr "type" "int,int,gstore,gstore,movgf,fsconv,movfg,fstore,movgf")])
+
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "general_operand" "")
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (!reload_in_progress
+ && !reload_completed
+ && !register_operand (operands[0], HImode)
+ && !reg_or_0_operand (operands[1], HImode))
+ operands[1] = copy_to_mode_reg (HImode, operands[1]);
+}")
+
+(define_insn "*movhi_load"
+ [(set (match_operand:HI 0 "register_operand" "=d,f")
+ (match_operand:HI 1 "frv_load_operand" "m,m"))]
+ ""
+ "* return output_move_single (operands, insn);"
+ [(set_attr "length" "4")
+ (set_attr "type" "gload,fload")])
+
+(define_insn "*movhi_internal"
+ [(set (match_operand:HI 0 "move_destination_operand" "=d,d,d,m,m,?f,?f,?d,?m,f")
+ (match_operand:HI 1 "move_source_operand" "L,i,d,d,O, d, f, f, f,GO"))]
+ "register_operand(operands[0], HImode) || reg_or_0_operand (operands[1], HImode)"
+ "* return output_move_single (operands, insn);"
+ [(set_attr "length" "4,8,4,4,4,4,4,4,4,4")
+ (set_attr "type" "int,multi,int,gstore,gstore,movgf,fsconv,movfg,fstore,movgf")])
+
+;; Split 2 word load of constants into sethi/setlo instructions
+(define_split
+ [(set (match_operand:HI 0 "integer_register_operand" "")
+ (match_operand:HI 1 "int_2word_operand" ""))]
+ "reload_completed"
+ [(set (match_dup 0)
+ (high:HI (match_dup 1)))
+ (set (match_dup 0)
+ (lo_sum:HI (match_dup 0)
+ (match_dup 1)))]
+ "")
+
+(define_insn "movhi_high"
+ [(set (match_operand:HI 0 "integer_register_operand" "=d")
+ (high:HI (match_operand:HI 1 "int_2word_operand" "i")))]
+ ""
+ "sethi #hi(%1), %0"
+ [(set_attr "type" "sethi")
+ (set_attr "length" "4")])
+
+(define_insn "movhi_lo_sum"
+ [(set (match_operand:HI 0 "integer_register_operand" "+d")
+ (lo_sum:HI (match_dup 0)
+ (match_operand:HI 1 "int_2word_operand" "i")))]
+ ""
+ "setlo #lo(%1), %0"
+ [(set_attr "type" "setlo")
+ (set_attr "length" "4")])
+
+(define_expand "movsi"
+ [(set (match_operand:SI 0 "move_destination_operand" "")
+ (match_operand:SI 1 "move_source_operand" ""))]
+ ""
+ "
+{
+ if (frv_emit_movsi (operands[0], operands[1]))
+ DONE;
+}")
+
+;; Note - it is best to only have one movsi pattern and to handle
+;; all the various contingencies by the use of alternatives. This
+;; allows reload the greatest amount of flexability (since reload will
+;; only choose amoungst alternatives for a selected insn, it will not
+;; replace the insn with another one).
+
+;; Unfortunately, we do have to separate out load-type moves from the rest,
+;; and only allow memory source operands in the former. If we do memory and
+;; constant loads in a single pattern, reload will be tempted to force
+;; constants into memory when the destination is a floating-point register.
+;; That may make a function use a PIC pointer when it didn't before, and we
+;; cannot change PIC usage (and hence stack layout) so late in the game.
+;; The resulting sequences for loading cosntants into FPRs are preferable
+;; even when we're not generating PIC code.
+
+(define_insn "*movsi_load"
+ [(set (match_operand:SI 0 "register_operand" "=d,f")
+ (match_operand:SI 1 "frv_load_operand" "m,m"))]
+ ""
+ "* return output_move_single (operands, insn);"
+ [(set_attr "length" "4")
+ (set_attr "type" "gload,fload")])
+
+(define_insn "*movsi_internal"
+ [(set (match_operand:SI 0 "move_destination_operand" "=d,d,d,m,m,z,d,d,f,f,m,?f,?z")
+ (match_operand:SI 1 "move_source_operand" "LQ,i,d,d,O,d,z,f,d,f,f,GO,GO"))]
+ "register_operand (operands[0], SImode) || reg_or_0_operand (operands[1], SImode)"
+ "* return output_move_single (operands, insn);"
+ [(set_attr "length" "4,8,4,4,4,4,4,4,4,4,4,4,4")
+ (set_attr "type" "int,multi,int,gstore,gstore,spr,spr,movfg,movgf,fsconv,fstore,movgf,spr")])
+
+(define_insn "*movsi_lda_sdata"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "small_data_register_operand" "d")
+ (match_operand:SI 2 "small_data_symbolic_operand" "Q")))]
+ ""
+ "addi %1, #gprel12(%2), %0"
+ [(set_attr "type" "int")
+ (set_attr "length" "4")])
+
+;; Split 2 word load of constants into sethi/setlo instructions
+(define_split
+ [(set (match_operand:SI 0 "integer_register_operand" "")
+ (match_operand:SI 1 "int_2word_operand" ""))]
+ "reload_completed"
+ [(set (match_dup 0)
+ (high:SI (match_dup 1)))
+ (set (match_dup 0)
+ (lo_sum:SI (match_dup 0)
+ (match_dup 1)))]
+ "")
+
+(define_insn "movsi_high"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (high:SI (match_operand:SI 1 "int_2word_operand" "i")))]
+ ""
+ "sethi #hi(%1), %0"
+ [(set_attr "type" "sethi")
+ (set_attr "length" "4")])
+
+(define_insn "movsi_lo_sum"
+ [(set (match_operand:SI 0 "integer_register_operand" "+d")
+ (lo_sum:SI (match_dup 0)
+ (match_operand:SI 1 "int_2word_operand" "i")))]
+ ""
+ "setlo #lo(%1), %0"
+ [(set_attr "type" "setlo")
+ (set_attr "length" "4")])
+
+;; Split loads of addresses with PIC specified into 3 separate instructions
+(define_insn_and_split "*movsi_pic"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "pic_register_operand" "d")
+ (match_operand:SI 2 "pic_symbolic_operand" "")))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0)
+ (high:SI (match_dup 2)))
+ (set (match_dup 0)
+ (lo_sum:SI (match_dup 0)
+ (match_dup 2)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0) (match_dup 1)))]
+
+ ""
+ [(set_attr "type" "multi")
+ (set_attr "length" "12")])
+
+(define_insn "movsi_high_pic"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (high:SI (match_operand:SI 1 "pic_symbolic_operand" "")))]
+ ""
+ "sethi #gprelhi(%1), %0"
+ [(set_attr "type" "sethi")
+ (set_attr "length" "4")])
+
+(define_insn "movsi_lo_sum_pic"
+ [(set (match_operand:SI 0 "integer_register_operand" "+d")
+ (lo_sum:SI (match_dup 0)
+ (match_operand:SI 1 "pic_symbolic_operand" "")))]
+ ""
+ "setlo #gprello(%1), %0"
+ [(set_attr "type" "setlo")
+ (set_attr "length" "4")])
+
+(define_expand "movdi"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (!reload_in_progress
+ && !reload_completed
+ && !register_operand (operands[0], DImode)
+ && !reg_or_0_operand (operands[1], DImode))
+ operands[1] = copy_to_mode_reg (DImode, operands[1]);
+}")
+
+(define_insn "*movdi_double"
+ [(set (match_operand:DI 0 "move_destination_operand" "=e,?h,??d,??f,R,?R,??m,??m,e,?h,??d,??f,?e,??d,?h,??f,R,m,e,??d,e,??d,?h,??f")
+ (match_operand:DI 1 "move_source_operand" " e,h,d,f,e,h,d,f,R,R,m,m,h,f,e,d,GO,GO,GO,GO,nF,nF,GO,GO"))]
+ "TARGET_DOUBLE
+ && (register_operand (operands[0], DImode)
+ || reg_or_0_operand (operands[1], DImode))"
+ "* return output_move_double (operands, insn);"
+ [(set_attr "length" "8,4,8,8,4,4,8,8,4,4,8,8,4,8,4,8,4,8,8,8,16,16,8,8")
+ (set_attr "type" "multi,fdconv,multi,multi,gstore,fstore,gstore,fstore,gload,fload,gload,fload,movfg,movfg,movgf,movgf,gstore,gstore,multi,multi,multi,multi,movgf,movgf")])
+
+(define_insn "*movdi_nodouble"
+ [(set (match_operand:DI 0 "move_destination_operand" "=e,?h,??d,??f,R,?R,??m,??m,e,?h,??d,??f,?e,??d,?h,??f,R,m,e,??d,e,??d,?h,??f")
+ (match_operand:DI 1 "move_source_operand" " e,h,d,f,e,h,d,f,R,R,m,m,h,f,e,d,GO,GO,GO,GO,nF,nF,GO,GO"))]
+ "!TARGET_DOUBLE
+ && (register_operand (operands[0], DImode)
+ || reg_or_0_operand (operands[1], DImode))"
+ "* return output_move_double (operands, insn);"
+ [(set_attr "length" "8,8,8,8,4,4,8,8,4,4,8,8,8,8,8,8,4,8,8,8,16,16,8,8")
+ (set_attr "type" "multi,multi,multi,multi,gstore,fstore,gstore,fstore,gload,fload,gload,fload,movfg,movfg,movgf,movgf,gstore,gstore,multi,multi,multi,multi,movgf,movgf")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "dbl_memory_two_insn_operand" ""))]
+ "reload_completed"
+ [(const_int 0)]
+ "frv_split_double_load (operands[0], operands[1]);")
+
+(define_split
+ [(set (match_operand:DI 0 "odd_reg_operand" "")
+ (match_operand:DI 1 "memory_operand" ""))]
+ "reload_completed"
+ [(const_int 0)]
+ "frv_split_double_load (operands[0], operands[1]);")
+
+(define_split
+ [(set (match_operand:DI 0 "dbl_memory_two_insn_operand" "")
+ (match_operand:DI 1 "reg_or_0_operand" ""))]
+ "reload_completed"
+ [(const_int 0)]
+ "frv_split_double_store (operands[0], operands[1]);")
+
+(define_split
+ [(set (match_operand:DI 0 "memory_operand" "")
+ (match_operand:DI 1 "odd_reg_operand" ""))]
+ "reload_completed"
+ [(const_int 0)]
+ "frv_split_double_store (operands[0], operands[1]);")
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "register_operand" ""))]
+ "reload_completed
+ && (odd_reg_operand (operands[0], DImode)
+ || odd_reg_operand (operands[1], DImode)
+ || (integer_register_operand (operands[0], DImode)
+ && integer_register_operand (operands[1], DImode))
+ || (!TARGET_DOUBLE
+ && fpr_operand (operands[0], DImode)
+ && fpr_operand (operands[1], DImode)))"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+ "
+{
+ rtx op0 = operands[0];
+ rtx op0_low = gen_lowpart (SImode, op0);
+ rtx op0_high = gen_highpart (SImode, op0);
+ rtx op1 = operands[1];
+ rtx op1_low = gen_lowpart (SImode, op1);
+ rtx op1_high = gen_highpart (SImode, op1);
+
+ /* We normally copy the low-numbered register first. However, if the first
+ register operand 0 is the same as the second register of operand 1, we
+ must copy in the opposite order. */
+
+ if (REGNO (op0_high) == REGNO (op1_low))
+ {
+ operands[2] = op0_low;
+ operands[3] = op0_high;
+ operands[4] = op1_low;
+ operands[5] = op1_high;
+ }
+ else
+ {
+ operands[2] = op0_high;
+ operands[3] = op0_low;
+ operands[4] = op1_high;
+ operands[5] = op1_low;
+ }
+}")
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "const_int_operand" ""))]
+ "reload_completed"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 1))]
+ "
+{
+ rtx op0 = operands[0];
+ rtx op1 = operands[1];
+
+ operands[2] = gen_highpart (SImode, op0);
+ operands[3] = gen_lowpart (SImode, op0);
+ operands[4] = GEN_INT ((INTVAL (op1) < 0) ? -1 : 0);
+}")
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "const_double_operand" ""))]
+ "reload_completed"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+ "
+{
+ rtx op0 = operands[0];
+ rtx op1 = operands[1];
+
+ operands[2] = gen_highpart (SImode, op0);
+ operands[3] = gen_lowpart (SImode, op0);
+ operands[4] = GEN_INT (CONST_DOUBLE_HIGH (op1));
+ operands[5] = GEN_INT (CONST_DOUBLE_LOW (op1));
+}")
+
+;; Floating Point Moves
+;;
+;; Note - Patterns for SF mode moves are compulsory, but
+;; patterns for DF are optional, as GCC can synthesize them.
+
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (match_operand:SF 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (!reload_in_progress
+ && !reload_completed
+ && !register_operand (operands[0], SFmode)
+ && !reg_or_0_operand (operands[1], SFmode))
+ operands[1] = copy_to_mode_reg (SFmode, operands[1]);
+}")
+
+(define_split
+ [(set (match_operand:SF 0 "integer_register_operand" "")
+ (match_operand:SF 1 "int_2word_operand" ""))]
+ "reload_completed"
+ [(set (match_dup 0)
+ (high:SF (match_dup 1)))
+ (set (match_dup 0)
+ (lo_sum:SF (match_dup 0)
+ (match_dup 1)))]
+ "")
+
+(define_insn "*movsf_load_has_fprs"
+ [(set (match_operand:SF 0 "register_operand" "=f,d")
+ (match_operand:SF 1 "frv_load_operand" "m,m"))]
+ "TARGET_HAS_FPRS"
+ "* return output_move_single (operands, insn);"
+ [(set_attr "length" "4")
+ (set_attr "type" "fload,gload")])
+
+(define_insn "*movsf_internal_has_fprs"
+ [(set (match_operand:SF 0 "move_destination_operand" "=f,f,m,m,?f,?d,?d,m,?d")
+ (match_operand:SF 1 "move_source_operand" "f,OG,f,OG,d,f,d,d,F"))]
+ "TARGET_HAS_FPRS
+ && (register_operand (operands[0], SFmode) || reg_or_0_operand (operands[1], SFmode))"
+ "* return output_move_single (operands, insn);"
+ [(set_attr "length" "4,4,4,4,4,4,4,4,8")
+ (set_attr "type" "fsconv,movgf,fstore,gstore,movgf,movfg,int,gstore,multi")])
+
+;; If we don't support the double instructions, prefer gprs over fprs, since it
+;; will all be emulated
+(define_insn "*movsf_internal_no_fprs"
+ [(set (match_operand:SF 0 "move_destination_operand" "=d,d,m,d,d")
+ (match_operand:SF 1 "move_source_operand" " d,OG,dOG,m,F"))]
+ "!TARGET_HAS_FPRS
+ && (register_operand (operands[0], SFmode) || reg_or_0_operand (operands[1], SFmode))"
+ "* return output_move_single (operands, insn);"
+ [(set_attr "length" "4,4,4,4,8")
+ (set_attr "type" "int,int,gstore,gload,multi")])
+
+(define_insn "movsf_high"
+ [(set (match_operand:SF 0 "integer_register_operand" "=d")
+ (high:SF (match_operand:SF 1 "int_2word_operand" "i")))]
+ ""
+ "sethi #hi(%1), %0"
+ [(set_attr "type" "sethi")
+ (set_attr "length" "4")])
+
+(define_insn "movsf_lo_sum"
+ [(set (match_operand:SF 0 "integer_register_operand" "+d")
+ (lo_sum:SF (match_dup 0)
+ (match_operand:SF 1 "int_2word_operand" "i")))]
+ ""
+ "setlo #lo(%1), %0"
+ [(set_attr "type" "setlo")
+ (set_attr "length" "4")])
+
+(define_expand "movdf"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (!reload_in_progress
+ && !reload_completed
+ && !register_operand (operands[0], DFmode)
+ && !reg_or_0_operand (operands[1], DFmode))
+ operands[1] = copy_to_mode_reg (DFmode, operands[1]);
+}")
+
+(define_insn "*movdf_double"
+ [(set (match_operand:DF 0 "move_destination_operand" "=h,?e,??f,??d,R,?R,??m,??m,h,?e,??f,??d,?h,??f,?e,??d,R,m,h,??f,e,??d")
+ (match_operand:DF 1 "move_source_operand" " h,e,f,d,h,e,f,d,R,R,m,m,e,d,h,f,GO,GO,GO,GO,GO,GO"))]
+ "TARGET_DOUBLE
+ && (register_operand (operands[0], DFmode)
+ || reg_or_0_operand (operands[1], DFmode))"
+ "* return output_move_double (operands, insn);"
+ [(set_attr "length" "4,8,8,8,4,4,8,8,4,4,8,8,4,8,4,8,4,8,8,8,8,8")
+ (set_attr "type" "fdconv,multi,multi,multi,fstore,gstore,fstore,gstore,fload,gload,fload,gload,movgf,movgf,movfg,movfg,gstore,gstore,movgf,movgf,multi,multi")])
+
+;; If we don't support the double instructions, prefer gprs over fprs, since it
+;; will all be emulated
+(define_insn "*movdf_nodouble"
+ [(set (match_operand:DF 0 "move_destination_operand" "=e,?h,??d,??f,R,?R,??m,??m,e,?h,??d,??f,?e,??d,?h,??f,R,m,e,??d,e,??d,?h,??f")
+ (match_operand:DF 1 "move_source_operand" " e,h,d,f,e,h,d,f,R,R,m,m,h,f,e,d,GO,GO,GO,GO,nF,nF,GO,GO"))]
+ "!TARGET_DOUBLE
+ && (register_operand (operands[0], DFmode)
+ || reg_or_0_operand (operands[1], DFmode))"
+ "* return output_move_double (operands, insn);"
+ [(set_attr "length" "8,8,8,8,4,4,8,8,4,4,8,8,8,8,8,8,4,8,8,8,16,16,8,8")
+ (set_attr "type" "multi,multi,multi,multi,gstore,fstore,gstore,fstore,gload,fload,gload,fload,movfg,movfg,movgf,movgf,gstore,gstore,multi,multi,multi,multi,movgf,movgf")])
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "dbl_memory_two_insn_operand" ""))]
+ "reload_completed"
+ [(const_int 0)]
+ "frv_split_double_load (operands[0], operands[1]);")
+
+(define_split
+ [(set (match_operand:DF 0 "odd_reg_operand" "")
+ (match_operand:DF 1 "memory_operand" ""))]
+ "reload_completed"
+ [(const_int 0)]
+ "frv_split_double_load (operands[0], operands[1]);")
+
+(define_split
+ [(set (match_operand:DF 0 "dbl_memory_two_insn_operand" "")
+ (match_operand:DF 1 "reg_or_0_operand" ""))]
+ "reload_completed"
+ [(const_int 0)]
+ "frv_split_double_store (operands[0], operands[1]);")
+
+(define_split
+ [(set (match_operand:DF 0 "memory_operand" "")
+ (match_operand:DF 1 "odd_reg_operand" ""))]
+ "reload_completed"
+ [(const_int 0)]
+ "frv_split_double_store (operands[0], operands[1]);")
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "register_operand" ""))]
+ "reload_completed
+ && (odd_reg_operand (operands[0], DFmode)
+ || odd_reg_operand (operands[1], DFmode)
+ || (integer_register_operand (operands[0], DFmode)
+ && integer_register_operand (operands[1], DFmode))
+ || (!TARGET_DOUBLE
+ && fpr_operand (operands[0], DFmode)
+ && fpr_operand (operands[1], DFmode)))"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+ "
+{
+ rtx op0 = operands[0];
+ rtx op0_low = gen_lowpart (SImode, op0);
+ rtx op0_high = gen_highpart (SImode, op0);
+ rtx op1 = operands[1];
+ rtx op1_low = gen_lowpart (SImode, op1);
+ rtx op1_high = gen_highpart (SImode, op1);
+
+ /* We normally copy the low-numbered register first. However, if the first
+ register operand 0 is the same as the second register of operand 1, we
+ must copy in the opposite order. */
+
+ if (REGNO (op0_high) == REGNO (op1_low))
+ {
+ operands[2] = op0_low;
+ operands[3] = op0_high;
+ operands[4] = op1_low;
+ operands[5] = op1_high;
+ }
+ else
+ {
+ operands[2] = op0_high;
+ operands[3] = op0_low;
+ operands[4] = op1_high;
+ operands[5] = op1_low;
+ }
+}")
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "const_int_operand" ""))]
+ "reload_completed"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 1))]
+ "
+{
+ rtx op0 = operands[0];
+ rtx op1 = operands[1];
+
+ operands[2] = gen_highpart (SImode, op0);
+ operands[3] = gen_lowpart (SImode, op0);
+ operands[4] = GEN_INT ((INTVAL (op1) < 0) ? -1 : 0);
+}")
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "const_double_operand" ""))]
+ "reload_completed"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+ "
+{
+ rtx op0 = operands[0];
+ rtx op1 = operands[1];
+ REAL_VALUE_TYPE rv;
+ long l[2];
+
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, op1);
+ REAL_VALUE_TO_TARGET_DOUBLE (rv, l);
+
+ operands[2] = gen_highpart (SImode, op0);
+ operands[3] = gen_lowpart (SImode, op0);
+ operands[4] = GEN_INT (l[0]);
+ operands[5] = GEN_INT (l[1]);
+}")
+
+;; String/block move insn.
+;; Argument 0 is the destination
+;; Argument 1 is the source
+;; Argument 2 is the length
+;; Argument 3 is the alignment
+
+(define_expand "movstrsi"
+ [(parallel [(set (match_operand:BLK 0 "" "")
+ (match_operand:BLK 1 "" ""))
+ (use (match_operand:SI 2 "" ""))
+ (use (match_operand:SI 3 "" ""))])]
+ ""
+ "
+{
+ if (frv_expand_block_move (operands))
+ DONE;
+ else
+ FAIL;
+}")
+
+;; String/block clear insn.
+;; Argument 0 is the destination
+;; Argument 1 is the length
+;; Argument 2 is the alignment
+
+(define_expand "clrstrsi"
+ [(parallel [(set (match_operand:BLK 0 "" "")
+ (const_int 0))
+ (use (match_operand:SI 1 "" ""))
+ (use (match_operand:SI 2 "" ""))])]
+ ""
+ "
+{
+ if (frv_expand_block_clear (operands))
+ DONE;
+ else
+ FAIL;
+}")
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Reload CC registers
+;; ::
+;; ::::::::::::::::::::
+
+;; Use as a define_expand so that cse/gcse/combine can't accidentally
+;; create movcc insns.
+
+(define_expand "movcc"
+ [(parallel [(set (match_operand:CC 0 "move_destination_operand" "")
+ (match_operand:CC 1 "move_source_operand" ""))
+ (clobber (match_dup 2))])]
+ ""
+ "
+{
+ if (! reload_in_progress && ! reload_completed)
+ FAIL;
+
+ operands[2] = gen_rtx_REG (CC_CCRmode, ICR_TEMP);
+}")
+
+(define_insn "*internal_movcc"
+ [(set (match_operand:CC 0 "move_destination_operand" "=t,d,d,m,d")
+ (match_operand:CC 1 "move_source_operand" "d,d,m,d,t"))
+ (clobber (match_scratch:CC_CCR 2 "=X,X,X,X,&v"))]
+ "reload_in_progress || reload_completed"
+ "@
+ cmpi %1, #0, %0
+ mov %1, %0
+ ld%I1%U1 %M1, %0
+ st%I0%U0 %1, %M0
+ #"
+ [(set_attr "length" "4,4,4,4,20")
+ (set_attr "type" "int,int,gload,gstore,multi")])
+
+;; To move an ICC value to a GPR for a signed comparison, we create a value
+;; that when compared to 0, sets the N and Z flags appropriately (we don't care
+;; about the V and C flags, since these comparisons are signed).
+
+(define_split
+ [(set (match_operand:CC 0 "integer_register_operand" "")
+ (match_operand:CC 1 "icc_operand" ""))
+ (clobber (match_operand:CC_CCR 2 "icr_operand" ""))]
+ "reload_in_progress || reload_completed"
+ [(match_dup 3)]
+ "
+{
+ rtx dest = simplify_gen_subreg (SImode, operands[0], CCmode, 0);
+ rtx icc = operands[1];
+ rtx icr = operands[2];
+
+ start_sequence ();
+
+ emit_insn (gen_rtx_SET (VOIDmode, icr,
+ gen_rtx_LT (CC_CCRmode, icc, const0_rtx)));
+
+ emit_insn (gen_movsi (dest, const1_rtx));
+
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_NE (CC_CCRmode, icr, const0_rtx),
+ gen_rtx_SET (VOIDmode, dest,
+ gen_rtx_NEG (SImode, dest))));
+
+ emit_insn (gen_rtx_SET (VOIDmode, icr,
+ gen_rtx_EQ (CC_CCRmode, icc, const0_rtx)));
+
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_NE (CC_CCRmode, icr, const0_rtx),
+ gen_rtx_SET (VOIDmode, dest, const0_rtx)));
+
+ operands[3] = get_insns ();
+ end_sequence ();
+}")
+
+(define_expand "reload_incc"
+ [(parallel [(set (match_operand:CC 2 "integer_register_operand" "=&d")
+ (match_operand:CC 1 "memory_operand" "m"))
+ (clobber (match_scratch:CC_CCR 3 ""))])
+ (parallel [(set (match_operand:CC 0 "icc_operand" "=t")
+ (match_dup 2))
+ (clobber (match_scratch:CC_CCR 4 ""))])]
+ ""
+ "")
+
+(define_expand "reload_outcc"
+ [(parallel [(set (match_operand:CC 2 "integer_register_operand" "=&d")
+ (match_operand:CC 1 "icc_operand" "t"))
+ (clobber (match_dup 3))])
+ (parallel [(set (match_operand:CC 0 "memory_operand" "=m")
+ (match_dup 2))
+ (clobber (match_scratch:CC_CCR 4 ""))])]
+ ""
+ "operands[3] = gen_rtx_REG (CC_CCRmode, ICR_TEMP);")
+
+;; Reload CC_UNSmode for unsigned integer comparisons
+;; Use define_expand so that cse/gcse/combine can't create movcc_uns insns
+
+(define_expand "movcc_uns"
+ [(parallel [(set (match_operand:CC_UNS 0 "move_destination_operand" "")
+ (match_operand:CC_UNS 1 "move_source_operand" ""))
+ (clobber (match_dup 2))])]
+ ""
+ "
+{
+ if (! reload_in_progress && ! reload_completed)
+ FAIL;
+ operands[2] = gen_rtx_REG (CC_CCRmode, ICR_TEMP);
+}")
+
+(define_insn "*internal_movcc_uns"
+ [(set (match_operand:CC_UNS 0 "move_destination_operand" "=t,d,d,m,d")
+ (match_operand:CC_UNS 1 "move_source_operand" "d,d,m,d,t"))
+ (clobber (match_scratch:CC_CCR 2 "=X,X,X,X,&v"))]
+ "reload_in_progress || reload_completed"
+ "@
+ cmpi %1, #1, %0
+ mov %1, %0
+ ld%I1%U1 %M1, %0
+ st%I0%U0 %1, %M0
+ #"
+ [(set_attr "length" "4,4,4,4,20")
+ (set_attr "type" "int,int,gload,gstore,multi")])
+
+;; To move an ICC value to a GPR for an unsigned comparison, we create a value
+;; that when compared to 1, sets the Z, V, and C flags appropriately (we don't
+;; care about the N flag, since these comparisons are unsigned).
+
+(define_split
+ [(set (match_operand:CC_UNS 0 "integer_register_operand" "")
+ (match_operand:CC_UNS 1 "icc_operand" ""))
+ (clobber (match_operand:CC_CCR 2 "icr_operand" ""))]
+ "reload_in_progress || reload_completed"
+ [(match_dup 3)]
+ "
+{
+ rtx dest = simplify_gen_subreg (SImode, operands[0], CC_UNSmode, 0);
+ rtx icc = operands[1];
+ rtx icr = operands[2];
+
+ start_sequence ();
+
+ emit_insn (gen_rtx_SET (VOIDmode, icr,
+ gen_rtx_GTU (CC_CCRmode, icc, const0_rtx)));
+
+ emit_insn (gen_movsi (dest, const1_rtx));
+
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_NE (CC_CCRmode, icr, const0_rtx),
+ gen_addsi3 (dest, dest, dest)));
+
+ emit_insn (gen_rtx_SET (VOIDmode, icr,
+ gen_rtx_LTU (CC_CCRmode, icc, const0_rtx)));
+
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_NE (CC_CCRmode, icr, const0_rtx),
+ gen_rtx_SET (VOIDmode, dest, const0_rtx)));
+
+ operands[3] = get_insns ();
+ end_sequence ();
+}")
+
+(define_expand "reload_incc_uns"
+ [(parallel [(set (match_operand:CC_UNS 2 "integer_register_operand" "=&d")
+ (match_operand:CC_UNS 1 "memory_operand" "m"))
+ (clobber (match_scratch:CC_CCR 3 ""))])
+ (parallel [(set (match_operand:CC_UNS 0 "icc_operand" "=t")
+ (match_dup 2))
+ (clobber (match_scratch:CC_CCR 4 ""))])]
+ ""
+ "")
+
+(define_expand "reload_outcc_uns"
+ [(parallel [(set (match_operand:CC_UNS 2 "integer_register_operand" "=&d")
+ (match_operand:CC_UNS 1 "icc_operand" "t"))
+ (clobber (match_dup 3))])
+ (parallel [(set (match_operand:CC_UNS 0 "memory_operand" "=m")
+ (match_dup 2))
+ (clobber (match_scratch:CC_CCR 4 ""))])]
+ ""
+ "operands[3] = gen_rtx_REG (CC_CCRmode, ICR_TEMP);")
+
+;; Reload CC_FPmode for floating point comparisons
+;; We use a define_expand here so that cse/gcse/combine can't accidentally
+;; create movcc insns. If this was a named define_insn, we would not be able
+;; to make it conditional on reload.
+
+(define_expand "movcc_fp"
+ [(set (match_operand:CC_FP 0 "move_destination_operand" "")
+ (match_operand:CC_FP 1 "move_source_operand" ""))]
+ "TARGET_HAS_FPRS"
+ "
+{
+ if (! reload_in_progress && ! reload_completed)
+ FAIL;
+}")
+
+(define_insn "*movcc_fp_internal"
+ [(set (match_operand:CC_FP 0 "move_destination_operand" "=d,d,d,m")
+ (match_operand:CC_FP 1 "move_source_operand" "u,d,m,d"))]
+ "TARGET_HAS_FPRS && (reload_in_progress || reload_completed)"
+ "@
+ #
+ mov %1, %0
+ ld%I1%U1 %M1, %0
+ st%I0%U0 %1, %M0"
+ [(set_attr "length" "12,4,4,4")
+ (set_attr "type" "multi,int,gload,gstore")])
+
+
+(define_expand "reload_incc_fp"
+ [(match_operand:CC_FP 0 "fcc_operand" "=u")
+ (match_operand:CC_FP 1 "memory_operand" "m")
+ (match_operand:TI 2 "integer_register_operand" "=&d")]
+ "TARGET_HAS_FPRS"
+ "
+{
+ rtx cc_op2 = simplify_gen_subreg (CC_FPmode, operands[2], TImode, 0);
+ rtx int_op2 = simplify_gen_subreg (SImode, operands[2], TImode, 0);
+ rtx temp1 = simplify_gen_subreg (SImode, operands[2], TImode, 4);
+ rtx temp2 = simplify_gen_subreg (SImode, operands[2], TImode, 8);
+ int shift = CC_SHIFT_RIGHT (REGNO (operands[0]));
+ HOST_WIDE_INT mask;
+
+ emit_insn (gen_movcc_fp (cc_op2, operands[1]));
+ if (shift)
+ emit_insn (gen_ashlsi3 (int_op2, int_op2, GEN_INT (shift)));
+
+ mask = ~ ((HOST_WIDE_INT)CC_MASK << shift);
+ emit_insn (gen_movsi (temp1, GEN_INT (mask)));
+ emit_insn (gen_update_fcc (operands[0], int_op2, temp1, temp2));
+ DONE;
+}")
+
+(define_expand "reload_outcc_fp"
+ [(set (match_operand:CC_FP 2 "integer_register_operand" "=&d")
+ (match_operand:CC_FP 1 "fcc_operand" "u"))
+ (set (match_operand:CC_FP 0 "memory_operand" "=m")
+ (match_dup 2))]
+ "TARGET_HAS_FPRS"
+ "")
+
+;; Convert a FCC value to gpr
+(define_insn "read_fcc"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (unspec:SI [(match_operand:CC_FP 1 "fcc_operand" "u")]
+ UNSPEC_CC_TO_GPR))]
+ "TARGET_HAS_FPRS"
+ "movsg ccr, %0"
+ [(set_attr "type" "spr")
+ (set_attr "length" "4")])
+
+(define_split
+ [(set (match_operand:CC_FP 0 "integer_register_operand" "")
+ (match_operand:CC_FP 1 "fcc_operand" ""))]
+ "reload_completed && TARGET_HAS_FPRS"
+ [(match_dup 2)]
+ "
+{
+ rtx int_op0 = simplify_gen_subreg (SImode, operands[0], CC_FPmode, 0);
+ int shift = CC_SHIFT_RIGHT (REGNO (operands[1]));
+
+ start_sequence ();
+
+ emit_insn (gen_read_fcc (int_op0, operands[1]));
+ if (shift)
+ emit_insn (gen_lshrsi3 (int_op0, int_op0, GEN_INT (shift)));
+
+ emit_insn (gen_andsi3 (int_op0, int_op0, GEN_INT (CC_MASK)));
+
+ operands[2] = get_insns ();
+ end_sequence ();
+}")
+
+;; Move a gpr value to FCC.
+;; Operand0 = FCC
+;; Operand1 = reloaded value shifted appropriately
+;; Operand2 = mask to eliminate current register
+;; Operand3 = temporary to load/store ccr
+(define_insn "update_fcc"
+ [(set (match_operand:CC_FP 0 "fcc_operand" "=u")
+ (unspec:CC_FP [(match_operand:SI 1 "integer_register_operand" "d")
+ (match_operand:SI 2 "integer_register_operand" "d")]
+ UNSPEC_GPR_TO_CC))
+ (clobber (match_operand:SI 3 "integer_register_operand" "=&d"))]
+ "TARGET_HAS_FPRS"
+ "movsg ccr, %3\;and %2, %3, %3\;or %1, %3, %3\;movgs %3, ccr"
+ [(set_attr "type" "multi")
+ (set_attr "length" "16")])
+
+;; Reload CC_CCRmode for conditional execution registers
+(define_insn "movcc_ccr"
+ [(set (match_operand:CC_CCR 0 "move_destination_operand" "=d,d,d,m,v,?w,C,d")
+ (match_operand:CC_CCR 1 "move_source_operand" "C,d,m,d,n,n,C,L"))]
+ ""
+ "@
+ #
+ mov %1, %0
+ ld%I1%U1 %M1, %0
+ st%I0%U0 %1, %M0
+ #
+ #
+ orcr %1, %1, %0
+ setlos #%1, %0"
+ [(set_attr "length" "8,4,4,4,8,12,4,4")
+ (set_attr "type" "multi,int,gload,gstore,multi,multi,ccr,int")])
+
+(define_expand "reload_incc_ccr"
+ [(match_operand:CC_CCR 0 "cr_operand" "=C")
+ (match_operand:CC_CCR 1 "memory_operand" "m")
+ (match_operand:CC_CCR 2 "integer_register_operand" "=&d")]
+ ""
+ "
+{
+ rtx icc = gen_rtx_REG (CCmode, ICC_TEMP);
+ rtx int_op2 = simplify_gen_subreg (SImode, operands[2], CC_CCRmode, 0);
+ rtx icr = (ICR_P (REGNO (operands[0]))
+ ? operands[0] : gen_rtx_REG (CC_CCRmode, ICR_TEMP));
+
+ emit_insn (gen_movcc_ccr (operands[2], operands[1]));
+ emit_insn (gen_cmpsi_cc (icc, int_op2, const0_rtx));
+ emit_insn (gen_movcc_ccr (icr, gen_rtx_NE (CC_CCRmode, icc, const0_rtx)));
+
+ if (! ICR_P (REGNO (operands[0])))
+ emit_insn (gen_movcc_ccr (operands[0], icr));
+
+ DONE;
+}")
+
+(define_expand "reload_outcc_ccr"
+ [(set (match_operand:CC_CCR 2 "integer_register_operand" "=&d")
+ (match_operand:CC_CCR 1 "cr_operand" "C"))
+ (set (match_operand:CC_CCR 0 "memory_operand" "=m")
+ (match_dup 2))]
+ ""
+ "")
+
+(define_split
+ [(set (match_operand:CC_CCR 0 "integer_register_operand" "")
+ (match_operand:CC_CCR 1 "cr_operand" ""))]
+ "reload_completed"
+ [(match_dup 2)]
+ "
+{
+ rtx int_op0 = simplify_gen_subreg (SImode, operands[0], CC_CCRmode, 0);
+
+ start_sequence ();
+ emit_move_insn (operands[0], const1_rtx);
+ emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+ gen_rtx_EQ (CC_CCRmode,
+ operands[1],
+ const0_rtx),
+ gen_rtx_SET (VOIDmode, int_op0,
+ const0_rtx)));
+
+ operands[2] = get_insns ();
+ end_sequence ();
+}")
+
+(define_split
+ [(set (match_operand:CC_CCR 0 "cr_operand" "")
+ (match_operand:CC_CCR 1 "const_int_operand" ""))]
+ "reload_completed"
+ [(match_dup 2)]
+ "
+{
+ rtx icc = gen_rtx_REG (CCmode, ICC_TEMP);
+ rtx r0 = gen_rtx_REG (SImode, GPR_FIRST);
+ rtx icr = (ICR_P (REGNO (operands[0]))
+ ? operands[0] : gen_rtx_REG (CC_CCRmode, ICR_TEMP));
+
+ start_sequence ();
+
+ emit_insn (gen_cmpsi_cc (icc, r0, const0_rtx));
+
+ emit_insn (gen_movcc_ccr (icr,
+ gen_rtx_fmt_ee (((INTVAL (operands[1]) == 0)
+ ? EQ : NE), CC_CCRmode,
+ r0, const0_rtx)));
+
+ if (! ICR_P (REGNO (operands[0])))
+ emit_insn (gen_movcc_ccr (operands[0], icr));
+
+ operands[2] = get_insns ();
+ end_sequence ();
+}")
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Conversions
+;; ::
+;; ::::::::::::::::::::
+
+;; Signed conversions from a smaller integer to a larger integer
+;;
+;; These operations are optional. If they are not
+;; present GCC will synthesize them for itself
+;; Even though frv does not provide these instructions, we define them
+;; to allow load + sign extend to be collapsed together
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "integer_register_operand" "=d,d")
+ (sign_extend:HI (match_operand:QI 1 "gpr_or_memory_operand" "d,m")))]
+ ""
+ "@
+ #
+ ldsb%I1%U1 %M1,%0"
+ [(set_attr "length" "8,4")
+ (set_attr "type" "multi,gload")])
+
+(define_split
+ [(set (match_operand:HI 0 "integer_register_operand" "")
+ (sign_extend:HI (match_operand:QI 1 "integer_register_operand" "")))]
+ "reload_completed"
+ [(match_dup 2)
+ (match_dup 3)]
+ "
+{
+ rtx op0 = gen_lowpart (SImode, operands[0]);
+ rtx op1 = gen_lowpart (SImode, operands[1]);
+ rtx shift = GEN_INT (24);
+
+ operands[2] = gen_ashlsi3 (op0, op1, shift);
+ operands[3] = gen_ashrsi3 (op0, op0, shift);
+}")
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d")
+ (sign_extend:SI (match_operand:QI 1 "gpr_or_memory_operand" "d,m")))]
+ ""
+ "@
+ #
+ ldsb%I1%U1 %M1,%0"
+ [(set_attr "length" "8,4")
+ (set_attr "type" "multi,gload")])
+
+(define_split
+ [(set (match_operand:SI 0 "integer_register_operand" "")
+ (sign_extend:SI (match_operand:QI 1 "integer_register_operand" "")))]
+ "reload_completed"
+ [(match_dup 2)
+ (match_dup 3)]
+ "
+{
+ rtx op0 = gen_lowpart (SImode, operands[0]);
+ rtx op1 = gen_lowpart (SImode, operands[1]);
+ rtx shift = GEN_INT (24);
+
+ operands[2] = gen_ashlsi3 (op0, op1, shift);
+ operands[3] = gen_ashrsi3 (op0, op0, shift);
+}")
+
+;;(define_insn "extendqidi2"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (sign_extend:DI (match_operand:QI 1 "general_operand" "g")))]
+;; ""
+;; "extendqihi2 %0,%1"
+;; [(set_attr "length" "4")])
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d")
+ (sign_extend:SI (match_operand:HI 1 "gpr_or_memory_operand" "d,m")))]
+ ""
+ "@
+ #
+ ldsh%I1%U1 %M1,%0"
+ [(set_attr "length" "8,4")
+ (set_attr "type" "multi,gload")])
+
+(define_split
+ [(set (match_operand:SI 0 "integer_register_operand" "")
+ (sign_extend:SI (match_operand:HI 1 "integer_register_operand" "")))]
+ "reload_completed"
+ [(match_dup 2)
+ (match_dup 3)]
+ "
+{
+ rtx op0 = gen_lowpart (SImode, operands[0]);
+ rtx op1 = gen_lowpart (SImode, operands[1]);
+ rtx shift = GEN_INT (16);
+
+ operands[2] = gen_ashlsi3 (op0, op1, shift);
+ operands[3] = gen_ashrsi3 (op0, op0, shift);
+}")
+
+;;(define_insn "extendhidi2"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (sign_extend:DI (match_operand:HI 1 "general_operand" "g")))]
+;; ""
+;; "extendhihi2 %0,%1"
+;; [(set_attr "length" "4")])
+;;
+;;(define_insn "extendsidi2"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (sign_extend:DI (match_operand:SI 1 "general_operand" "g")))]
+;; ""
+;; "extendsidi2 %0,%1"
+;; [(set_attr "length" "4")])
+
+;; Unsigned conversions from a smaller integer to a larger integer
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d")
+ (zero_extend:HI
+ (match_operand:QI 1 "gpr_or_memory_operand" "d,L,m")))]
+ ""
+ "@
+ andi %1,#0xff,%0
+ setlos %1,%0
+ ldub%I1%U1 %M1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int,int,gload")])
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d")
+ (zero_extend:SI
+ (match_operand:QI 1 "gpr_or_memory_operand" "d,L,m")))]
+ ""
+ "@
+ andi %1,#0xff,%0
+ setlos %1,%0
+ ldub%I1%U1 %M1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int,int,gload")])
+
+;;(define_insn "zero_extendqidi2"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (zero_extend:DI (match_operand:QI 1 "general_operand" "g")))]
+;; ""
+;; "zero_extendqihi2 %0,%1"
+;; [(set_attr "length" "4")])
+
+;; Do not set the type for the sethi to "sethi", since the scheduler will think
+;; the sethi takes 0 cycles as part of allowing sethi/setlo to be in the same
+;; VLIW instruction.
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d")
+ (zero_extend:SI (match_operand:HI 1 "gpr_or_memory_operand" "0,m")))]
+ ""
+ "@
+ sethi #hi(#0),%0
+ lduh%I1%U1 %M1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int,gload")])
+
+;;(define_insn "zero_extendhidi2"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (zero_extend:DI (match_operand:HI 1 "general_operand" "g")))]
+;; ""
+;; "zero_extendhihi2 %0,%1"
+;; [(set_attr "length" "4")])
+;;
+;;(define_insn "zero_extendsidi2"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (zero_extend:DI (match_operand:SI 1 "general_operand" "g")))]
+;; ""
+;; "zero_extendsidi2 %0,%1"
+;; [(set_attr "length" "4")])
+;;
+;;;; Convert between floating point types of different sizes.
+;;
+;;(define_insn "extendsfdf2"
+;; [(set (match_operand:DF 0 "register_operand" "=r")
+;; (float_extend:DF (match_operand:SF 1 "register_operand" "r")))]
+;; ""
+;; "extendsfdf2 %0,%1"
+;; [(set_attr "length" "4")])
+;;
+;;(define_insn "truncdfsf2"
+;; [(set (match_operand:SF 0 "register_operand" "=r")
+;; (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))]
+;; ""
+;; "truncdfsf2 %0,%1"
+;; [(set_attr "length" "4")])
+
+;;;; Convert between signed integer types and floating point.
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "fpr_operand" "=f")
+ (float:SF (match_operand:SI 1 "fpr_operand" "f")))]
+ "TARGET_HARD_FLOAT"
+ "fitos %1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsconv")])
+
+(define_insn "floatsidf2"
+ [(set (match_operand:DF 0 "fpr_operand" "=h")
+ (float:DF (match_operand:SI 1 "fpr_operand" "f")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ "fitod %1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fdconv")])
+
+;;(define_insn "floatdisf2"
+;; [(set (match_operand:SF 0 "register_operand" "=r")
+;; (float:SF (match_operand:DI 1 "register_operand" "r")))]
+;; ""
+;; "floatdisf2 %0,%1"
+;; [(set_attr "length" "4")])
+;;
+;;(define_insn "floatdidf2"
+;; [(set (match_operand:DF 0 "register_operand" "=r")
+;; (float:DF (match_operand:DI 1 "register_operand" "r")))]
+;; ""
+;; "floatdidf2 %0,%1"
+;; [(set_attr "length" "4")])
+
+(define_insn "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (fix:SI (match_operand:SF 1 "fpr_operand" "f")))]
+ "TARGET_HARD_FLOAT"
+ "fstoi %1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsconv")])
+
+(define_insn "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (fix:SI (match_operand:DF 1 "fpr_operand" "h")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ "fdtoi %1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fdconv")])
+
+;;(define_insn "fix_truncsfdi2"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (fix:DI (match_operand:SF 1 "register_operand" "r")))]
+;; ""
+;; "fix_truncsfdi2 %0,%1"
+;; [(set_attr "length" "4")])
+;;
+;;(define_insn "fix_truncdfdi2"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (fix:DI (match_operand:DF 1 "register_operand" "r")))]
+;; ""
+;; "fix_truncdfdi2 %0,%1"
+;; [(set_attr "length" "4")])
+;;
+;;;; Convert between unsigned integer types and floating point.
+;;
+;;(define_insn "floatunssisf2"
+;; [(set (match_operand:SF 0 "register_operand" "=r")
+;; (unsigned_float:SF (match_operand:SI 1 "register_operand" "r")))]
+;; ""
+;; "floatunssisf2 %0,%1"
+;; [(set_attr "length" "4")])
+;;
+;;(define_insn "floatunssidf2"
+;; [(set (match_operand:DF 0 "register_operand" "=r")
+;; (unsigned_float:DF (match_operand:SI 1 "register_operand" "r")))]
+;; ""
+;; "floatunssidf2 %0,%1"
+;; [(set_attr "length" "4")])
+;;
+;;(define_insn "floatunsdisf2"
+;; [(set (match_operand:SF 0 "register_operand" "=r")
+;; (unsigned_float:SF (match_operand:DI 1 "register_operand" "r")))]
+;; ""
+;; "floatunsdisf2 %0,%1"
+;; [(set_attr "length" "4")])
+;;
+;;(define_insn "floatunsdidf2"
+;; [(set (match_operand:DF 0 "register_operand" "=r")
+;; (unsigned_float:DF (match_operand:DI 1 "register_operand" "r")))]
+;; ""
+;; "floatunsdidf2 %0,%1"
+;; [(set_attr "length" "4")])
+;;
+;;(define_insn "fixuns_truncsfsi2"
+;; [(set (match_operand:SI 0 "register_operand" "=r")
+;; (unsigned_fix:SI (match_operand:SF 1 "register_operand" "r")))]
+;; ""
+;; "fixuns_truncsfsi2 %0,%1"
+;; [(set_attr "length" "4")])
+;;
+;;(define_insn "fixuns_truncdfsi2"
+;; [(set (match_operand:SI 0 "register_operand" "=r")
+;; (unsigned_fix:SI (match_operand:DF 1 "register_operand" "r")))]
+;; ""
+;; "fixuns_truncdfsi2 %0,%1"
+;; [(set_attr "length" "4")])
+;;
+;;(define_insn "fixuns_truncsfdi2"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (unsigned_fix:DI (match_operand:SF 1 "register_operand" "r")))]
+;; ""
+;; "fixuns_truncsfdi2 %0,%1"
+;; [(set_attr "length" "4")])
+;;
+;;(define_insn "fixuns_truncdfdi2"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (unsigned_fix:DI (match_operand:DF 1 "register_operand" "r")))]
+;; ""
+;; "fixuns_truncdfdi2 %0,%1"
+;; [(set_attr "length" "4")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 32 bit Integer arithmetic
+;; ::
+;; ::::::::::::::::::::
+
+;; Addition
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "integer_register_operand" "%d")
+ (match_operand:SI 2 "gpr_or_int12_operand" "dNOP")))]
+ ""
+ "add%I2 %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+;; Subtraction. No need to worry about constants, since the compiler
+;; canonicalizes them into addsi3's. We prevent SUBREG's here to work around a
+;; combine bug, that combines the 32x32->upper 32 bit multiply that uses a
+;; SUBREG with a minus that shows up in modulus by constants.
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (minus:SI (match_operand:SI 1 "gpr_no_subreg_operand" "d")
+ (match_operand:SI 2 "gpr_no_subreg_operand" "d")))]
+ ""
+ "sub %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+;; Signed multiplication producing 64 bit results from 32 bit inputs
+;; Note, frv doesn't have a 32x32->32 bit multiply, but the compiler
+;; will do the 32x32->64 bit multiply and use the bottom word.
+(define_expand "mulsidi3"
+ [(set (match_operand:DI 0 "integer_register_operand" "")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "integer_register_operand" ""))
+ (sign_extend:DI (match_operand:SI 2 "gpr_or_int12_operand" ""))))]
+ ""
+ "
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ emit_insn (gen_mulsidi3_const (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+}")
+
+(define_insn "*mulsidi3_reg"
+ [(set (match_operand:DI 0 "even_gpr_operand" "=e")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "integer_register_operand" "%d"))
+ (sign_extend:DI (match_operand:SI 2 "integer_register_operand" "d"))))]
+ ""
+ "smul %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mul")])
+
+(define_insn "mulsidi3_const"
+ [(set (match_operand:DI 0 "even_gpr_operand" "=e")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "integer_register_operand" "d"))
+ (match_operand:SI 2 "int12_operand" "NOP")))]
+ ""
+ "smuli %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mul")])
+
+;; Unsigned multiplication producing 64 bit results from 32 bit inputs
+(define_expand "umulsidi3"
+ [(set (match_operand:DI 0 "even_gpr_operand" "")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "integer_register_operand" ""))
+ (zero_extend:DI (match_operand:SI 2 "gpr_or_int12_operand" ""))))]
+ ""
+ "
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ emit_insn (gen_umulsidi3_const (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+}")
+
+(define_insn "*mulsidi3_reg"
+ [(set (match_operand:DI 0 "even_gpr_operand" "=e")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "integer_register_operand" "%d"))
+ (zero_extend:DI (match_operand:SI 2 "integer_register_operand" "d"))))]
+ ""
+ "umul %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mul")])
+
+(define_insn "umulsidi3_const"
+ [(set (match_operand:DI 0 "even_gpr_operand" "=e")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "integer_register_operand" "d"))
+ (match_operand:SI 2 "int12_operand" "NOP")))]
+ ""
+ "umuli %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mul")])
+
+;; Signed Division
+(define_insn "divsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (div:SI (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))]
+ ""
+ "sdiv%I2 %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "div")])
+
+;; Unsigned Division
+(define_insn "udivsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (udiv:SI (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))]
+ ""
+ "udiv%I2 %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "div")])
+
+;; Negation
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (neg:SI (match_operand:SI 1 "integer_register_operand" "d")))]
+ ""
+ "sub %.,%1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+;; Find first one bit
+;; (define_insn "ffssi2"
+;; [(set (match_operand:SI 0 "register_operand" "=r")
+;; (ffs:SI (match_operand:SI 1 "register_operand" "r")))]
+;; ""
+;; "ffssi2 %0,%1"
+;; [(set_attr "length" "4")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 64 bit Integer arithmetic
+;; ::
+;; ::::::::::::::::::::
+
+;; Addition
+(define_expand "adddi3"
+ [(parallel [(set (match_operand:DI 0 "integer_register_operand" "")
+ (plus:DI (match_operand:DI 1 "integer_register_operand" "")
+ (match_operand:DI 2 "gpr_or_int10_operand" "")))
+ (clobber (match_scratch:CC 3 ""))])]
+ ""
+ "
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == -2048
+ && !no_new_pseudos)
+ operands[2] = force_reg (DImode, operands[2]);
+}")
+
+(define_insn_and_split "*adddi3_internal"
+ [(set (match_operand:DI 0 "integer_register_operand" "=&e,e,e,&e,e,&e,e")
+ (plus:DI (match_operand:DI 1 "integer_register_operand" "%e,0,e,e,0,e,0")
+ (match_operand:DI 2 "gpr_or_int10_operand" "e,e,0,N,N,OP,OP")))
+ (clobber (match_scratch:CC 3 "=t,t,t,t,t,t,t"))]
+ "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -2048"
+ "#"
+ "reload_completed"
+ [(match_dup 4)
+ (match_dup 5)]
+ "
+{
+ rtx op0_high = gen_highpart (SImode, operands[0]);
+ rtx op1_high = gen_highpart (SImode, operands[1]);
+ rtx op0_low = gen_lowpart (SImode, operands[0]);
+ rtx op1_low = gen_lowpart (SImode, operands[1]);
+ rtx op2 = operands[2];
+ rtx op3 = operands[3];
+
+ if (GET_CODE (op2) != CONST_INT)
+ {
+ rtx op2_high = gen_highpart (SImode, operands[2]);
+ rtx op2_low = gen_lowpart (SImode, operands[2]);
+ operands[4] = gen_adddi3_lower (op0_low, op1_low, op2_low, op3);
+ operands[5] = gen_adddi3_upper (op0_high, op1_high, op2_high, op3);
+ }
+ else if (INTVAL (op2) >= 0)
+ {
+ operands[4] = gen_adddi3_lower (op0_low, op1_low, op2, op3);
+ operands[5] = gen_adddi3_upper (op0_high, op1_high, const0_rtx, op3);
+ }
+ else
+ {
+ operands[4] = gen_subdi3_lower (op0_low, op1_low,
+ GEN_INT (- INTVAL (op2)), op3);
+ operands[5] = gen_subdi3_upper (op0_high, op1_high, const0_rtx, op3);
+ }
+}"
+ [(set_attr "length" "8")
+ (set_attr "type" "multi")])
+
+;; Subtraction No need to worry about constants, since the compiler
+;; canonicalizes them into adddi3's.
+(define_expand "subdi3"
+ [(parallel [(set (match_operand:DI 0 "integer_register_operand" "")
+ (minus:DI (match_operand:DI 1 "integer_register_operand" "")
+ (match_operand:DI 2 "integer_register_operand" "")))
+ (clobber (match_dup 3))])]
+ ""
+ "
+{
+ operands[3] = gen_reg_rtx (CCmode);
+}")
+
+(define_insn_and_split "*subdi3_internal"
+ [(set (match_operand:DI 0 "integer_register_operand" "=&e,e,e")
+ (minus:DI (match_operand:DI 1 "integer_register_operand" "e,0,e")
+ (match_operand:DI 2 "integer_register_operand" "e,e,0")))
+ (clobber (match_operand:CC 3 "icc_operand" "=t,t,t"))]
+ ""
+ "#"
+ "reload_completed"
+ [(match_dup 4)
+ (match_dup 5)]
+ "
+{
+ rtx op0_high = gen_highpart (SImode, operands[0]);
+ rtx op1_high = gen_highpart (SImode, operands[1]);
+ rtx op2_high = gen_highpart (SImode, operands[2]);
+ rtx op0_low = gen_lowpart (SImode, operands[0]);
+ rtx op1_low = gen_lowpart (SImode, operands[1]);
+ rtx op2_low = gen_lowpart (SImode, operands[2]);
+ rtx op3 = operands[3];
+
+ operands[4] = gen_subdi3_lower (op0_low, op1_low, op2_low, op3);
+ operands[5] = gen_subdi3_upper (op0_high, op1_high, op2_high, op3);
+}"
+ [(set_attr "length" "8")
+ (set_attr "type" "multi")])
+
+;; Patterns for addsi3/subdi3 after spliting
+(define_insn "adddi3_lower"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "integer_register_operand" "d")
+ (match_operand:SI 2 "gpr_or_int10_operand" "dOP")))
+ (set (match_operand:CC 3 "icc_operand" "=t")
+ (compare:CC (plus:SI (match_dup 1)
+ (match_dup 2))
+ (const_int 0)))]
+ "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) >= 0"
+ "add%I2cc %1,%2,%0,%3"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+(define_insn "adddi3_upper"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d")
+ (plus:SI (match_operand:SI 1 "integer_register_operand" "d,d")
+ (plus:SI (match_operand:SI 2 "reg_or_0_operand" "d,O")
+ (match_operand:CC 3 "icc_operand" "t,t"))))]
+ ""
+ "@
+ addx %1,%2,%0,%3
+ addx %1,%.,%0,%3"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+(define_insn "subdi3_lower"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (minus:SI (match_operand:SI 1 "integer_register_operand" "d")
+ (match_operand:SI 2 "gpr_or_int10_operand" "dOP")))
+ (set (match_operand:CC 3 "icc_operand" "=t")
+ (compare:CC (plus:SI (match_dup 1)
+ (match_dup 2))
+ (const_int 0)))]
+ "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) >= 0"
+ "sub%I2cc %1,%2,%0,%3"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+(define_insn "subdi3_upper"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d")
+ (minus:SI (match_operand:SI 1 "integer_register_operand" "d,d")
+ (minus:SI (match_operand:SI 2 "reg_or_0_operand" "d,O")
+ (match_operand:CC 3 "icc_operand" "t,t"))))]
+ ""
+ "@
+ subx %1,%2,%0,%3
+ subx %1,%.,%0,%3"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+;; Multiplication (same size)
+;; (define_insn "muldi3"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (mult:DI (match_operand:DI 1 "register_operand" "%r")
+;; (match_operand:DI 2 "nonmemory_operand" "ri")))]
+;; ""
+;; "muldi3 %0,%1,%2"
+;; [(set_attr "length" "4")])
+
+;; Signed Division
+;; (define_insn "divdi3"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (div:DI (match_operand:DI 1 "register_operand" "r")
+;; (match_operand:DI 2 "nonmemory_operand" "ri")))]
+;; ""
+;; "divdi3 %0,%1,%2"
+;; [(set_attr "length" "4")])
+
+;; Undsgned Division
+;; (define_insn "udivdi3"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (udiv:DI (match_operand:DI 1 "register_operand" "r")
+;; (match_operand:DI 2 "nonmemory_operand" "ri")))]
+;; ""
+;; "udivdi3 %0,%1,%2"
+;; [(set_attr "length" "4")])
+
+;; Negation
+;; (define_insn "negdi2"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (neg:DI (match_operand:DI 1 "register_operand" "r")))]
+;; ""
+;; "negdi2 %0,%1"
+;; [(set_attr "length" "4")])
+
+;; Find first one bit
+;; (define_insn "ffsdi2"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (ffs:DI (match_operand:DI 1 "register_operand" "r")))]
+;; ""
+;; "ffsdi2 %0,%1"
+;; [(set_attr "length" "4")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 32 bit floating point arithmetic
+;; ::
+;; ::::::::::::::::::::
+
+;; Addition
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "fpr_operand" "=f")
+ (plus:SF (match_operand:SF 1 "fpr_operand" "%f")
+ (match_operand:SF 2 "fpr_operand" "f")))]
+ "TARGET_HARD_FLOAT"
+ "fadds %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsadd")])
+
+;; Subtraction
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "fpr_operand" "=f")
+ (minus:SF (match_operand:SF 1 "fpr_operand" "f")
+ (match_operand:SF 2 "fpr_operand" "f")))]
+ "TARGET_HARD_FLOAT"
+ "fsubs %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsadd")])
+
+;; Multiplication
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "fpr_operand" "=f")
+ (mult:SF (match_operand:SF 1 "fpr_operand" "%f")
+ (match_operand:SF 2 "fpr_operand" "f")))]
+ "TARGET_HARD_FLOAT"
+ "fmuls %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsmul")])
+
+;; Multiplication with addition/subtraction
+(define_insn "*muladdsf4"
+ [(set (match_operand:SF 0 "fpr_operand" "=f")
+ (plus:SF (mult:SF (match_operand:SF 1 "fpr_operand" "%f")
+ (match_operand:SF 2 "fpr_operand" "f"))
+ (match_operand:SF 3 "fpr_operand" "0")))]
+ "TARGET_HARD_FLOAT && TARGET_MULADD"
+ "fmadds %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fmas")])
+
+(define_insn "*mulsubsf4"
+ [(set (match_operand:SF 0 "fpr_operand" "=f")
+ (minus:SF (mult:SF (match_operand:SF 1 "fpr_operand" "%f")
+ (match_operand:SF 2 "fpr_operand" "f"))
+ (match_operand:SF 3 "fpr_operand" "0")))]
+ "TARGET_HARD_FLOAT && TARGET_MULADD"
+ "fmsubs %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fmas")])
+
+;; Division
+(define_insn "divsf3"
+ [(set (match_operand:SF 0 "fpr_operand" "=f")
+ (div:SF (match_operand:SF 1 "fpr_operand" "f")
+ (match_operand:SF 2 "fpr_operand" "f")))]
+ "TARGET_HARD_FLOAT"
+ "fdivs %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsdiv")])
+
+;; Negation
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "fpr_operand" "=f")
+ (neg:SF (match_operand:SF 1 "fpr_operand" "f")))]
+ "TARGET_HARD_FLOAT"
+ "fnegs %1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsconv")])
+
+;; Absolute value
+(define_insn "abssf2"
+ [(set (match_operand:SF 0 "fpr_operand" "=f")
+ (abs:SF (match_operand:SF 1 "fpr_operand" "f")))]
+ "TARGET_HARD_FLOAT"
+ "fabss %1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsconv")])
+
+;; Square root
+(define_insn "sqrtsf2"
+ [(set (match_operand:SF 0 "fpr_operand" "=f")
+ (sqrt:SF (match_operand:SF 1 "fpr_operand" "f")))]
+ "TARGET_HARD_FLOAT"
+ "fsqrts %1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "sqrt_single")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 64 bit floating point arithmetic
+;; ::
+;; ::::::::::::::::::::
+
+;; Addition
+(define_insn "adddf3"
+ [(set (match_operand:DF 0 "even_fpr_operand" "=h")
+ (plus:DF (match_operand:DF 1 "fpr_operand" "%h")
+ (match_operand:DF 2 "fpr_operand" "h")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ "faddd %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fdadd")])
+
+;; Subtraction
+(define_insn "subdf3"
+ [(set (match_operand:DF 0 "even_fpr_operand" "=h")
+ (minus:DF (match_operand:DF 1 "fpr_operand" "h")
+ (match_operand:DF 2 "fpr_operand" "h")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ "fsubd %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fdadd")])
+
+;; Multiplication
+(define_insn "muldf3"
+ [(set (match_operand:DF 0 "even_fpr_operand" "=h")
+ (mult:DF (match_operand:DF 1 "fpr_operand" "%h")
+ (match_operand:DF 2 "fpr_operand" "h")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ "fmuld %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fdmul")])
+
+;; Multiplication with addition/subtraction
+(define_insn "*muladddf4"
+ [(set (match_operand:DF 0 "fpr_operand" "=f")
+ (plus:DF (mult:DF (match_operand:DF 1 "fpr_operand" "%f")
+ (match_operand:DF 2 "fpr_operand" "f"))
+ (match_operand:DF 3 "fpr_operand" "0")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE && TARGET_MULADD"
+ "fmaddd %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fmas")])
+
+(define_insn "*mulsubdf4"
+ [(set (match_operand:DF 0 "fpr_operand" "=f")
+ (minus:DF (mult:DF (match_operand:DF 1 "fpr_operand" "%f")
+ (match_operand:DF 2 "fpr_operand" "f"))
+ (match_operand:DF 3 "fpr_operand" "0")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE && TARGET_MULADD"
+ "fmsubd %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fmas")])
+
+;; Division
+(define_insn "divdf3"
+ [(set (match_operand:DF 0 "even_fpr_operand" "=h")
+ (div:DF (match_operand:DF 1 "fpr_operand" "h")
+ (match_operand:DF 2 "fpr_operand" "h")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ "fdivd %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fddiv")])
+
+;; Negation
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "even_fpr_operand" "=h")
+ (neg:DF (match_operand:DF 1 "fpr_operand" "h")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ "fnegd %1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fdconv")])
+
+;; Absolute value
+(define_insn "absdf2"
+ [(set (match_operand:DF 0 "even_fpr_operand" "=h")
+ (abs:DF (match_operand:DF 1 "fpr_operand" "h")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ "fabsd %1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fdconv")])
+
+;; Square root
+(define_insn "sqrtdf2"
+ [(set (match_operand:DF 0 "even_fpr_operand" "=h")
+ (sqrt:DF (match_operand:DF 1 "fpr_operand" "h")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ "fsqrtd %1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "sqrt_double")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 32 bit Integer Shifts and Rotates
+;; ::
+;; ::::::::::::::::::::
+
+;; Arithmetic Shift Left
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d")
+ (ashift:SI (match_operand:SI 1 "integer_register_operand" "d,d")
+ (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))]
+ ""
+ "sll%I2 %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+;; Arithmetic Shift Right
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d")
+ (ashiftrt:SI (match_operand:SI 1 "integer_register_operand" "d,d")
+ (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))]
+ ""
+ "sra%I2 %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+;; Logical Shift Right
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d")
+ (lshiftrt:SI (match_operand:SI 1 "integer_register_operand" "d,d")
+ (match_operand:SI 2 "gpr_or_int12_operand" "d,NOP")))]
+ ""
+ "srl%I2 %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+;; Rotate Left
+;; (define_insn "rotlsi3"
+;; [(set (match_operand:SI 0 "register_operand" "=r")
+;; (rotate:SI (match_operand:SI 1 "register_operand" "r")
+;; (match_operand:SI 2 "nonmemory_operand" "ri")))]
+;; ""
+;; "rotlsi3 %0,%1,%2"
+;; [(set_attr "length" "4")])
+
+;; Rotate Right
+;; (define_insn "rotrsi3"
+;; [(set (match_operand:SI 0 "register_operand" "=r")
+;; (rotatert:SI (match_operand:SI 1 "register_operand" "r")
+;; (match_operand:SI 2 "nonmemory_operand" "ri")))]
+;; ""
+;; "rotrsi3 %0,%1,%2"
+;; [(set_attr "length" "4")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 64 bit Integer Shifts and Rotates
+;; ::
+;; ::::::::::::::::::::
+
+;; Arithmetic Shift Left
+;; (define_insn "ashldi3"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (ashift:DI (match_operand:DI 1 "register_operand" "r")
+;; (match_operand:SI 2 "nonmemory_operand" "ri")))]
+;; ""
+;; "ashldi3 %0,%1,%2"
+;; [(set_attr "length" "4")])
+
+;; Arithmetic Shift Right
+;; (define_insn "ashrdi3"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
+;; (match_operand:SI 2 "nonmemory_operand" "ri")))]
+;; ""
+;; "ashrdi3 %0,%1,%2"
+;; [(set_attr "length" "4")])
+
+;; Logical Shift Right
+;; (define_insn "lshrdi3"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
+;; (match_operand:SI 2 "nonmemory_operand" "ri")))]
+;; ""
+;; "lshrdi3 %0,%1,%2"
+;; [(set_attr "length" "4")])
+
+;; Rotate Left
+;; (define_insn "rotldi3"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (rotate:DI (match_operand:DI 1 "register_operand" "r")
+;; (match_operand:SI 2 "nonmemory_operand" "ri")))]
+;; ""
+;; "rotldi3 %0,%1,%2"
+;; [(set_attr "length" "4")])
+
+;; Rotate Right
+;; (define_insn "rotrdi3"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (rotatert:DI (match_operand:DI 1 "register_operand" "r")
+;; (match_operand:SI 2 "nonmemory_operand" "ri")))]
+;; ""
+;; "rotrdi3 %0,%1,%2"
+;; [(set_attr "length" "4")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 32 Bit Integer Logical operations
+;; ::
+;; ::::::::::::::::::::
+
+;; Logical AND, 32 bit integers
+(define_insn "andsi3_media"
+ [(set (match_operand:SI 0 "gpr_or_fpr_operand" "=d,f")
+ (and:SI (match_operand:SI 1 "gpr_or_fpr_operand" "%d,f")
+ (match_operand:SI 2 "gpr_fpr_or_int12_operand" "dNOP,f")))]
+ "TARGET_MEDIA"
+ "@
+ and%I2 %1, %2, %0
+ mand %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int,mlogic")])
+
+(define_insn "andsi3_nomedia"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (and:SI (match_operand:SI 1 "integer_register_operand" "%d")
+ (match_operand:SI 2 "gpr_or_int12_operand" "dNOP")))]
+ "!TARGET_MEDIA"
+ "and%I2 %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+(define_expand "andsi3"
+ [(set (match_operand:SI 0 "gpr_or_fpr_operand" "")
+ (and:SI (match_operand:SI 1 "gpr_or_fpr_operand" "")
+ (match_operand:SI 2 "gpr_fpr_or_int12_operand" "")))]
+ ""
+ "")
+
+;; Inclusive OR, 32 bit integers
+(define_insn "iorsi3_media"
+ [(set (match_operand:SI 0 "gpr_or_fpr_operand" "=d,f")
+ (ior:SI (match_operand:SI 1 "gpr_or_fpr_operand" "%d,f")
+ (match_operand:SI 2 "gpr_fpr_or_int12_operand" "dNOP,f")))]
+ "TARGET_MEDIA"
+ "@
+ or%I2 %1, %2, %0
+ mor %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int,mlogic")])
+
+(define_insn "iorsi3_nomedia"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (ior:SI (match_operand:SI 1 "integer_register_operand" "%d")
+ (match_operand:SI 2 "gpr_or_int12_operand" "dNOP")))]
+ "!TARGET_MEDIA"
+ "or%I2 %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+(define_expand "iorsi3"
+ [(set (match_operand:SI 0 "gpr_or_fpr_operand" "")
+ (ior:SI (match_operand:SI 1 "gpr_or_fpr_operand" "")
+ (match_operand:SI 2 "gpr_fpr_or_int12_operand" "")))]
+ ""
+ "")
+
+;; Exclusive OR, 32 bit integers
+(define_insn "xorsi3_media"
+ [(set (match_operand:SI 0 "gpr_or_fpr_operand" "=d,f")
+ (xor:SI (match_operand:SI 1 "gpr_or_fpr_operand" "%d,f")
+ (match_operand:SI 2 "gpr_fpr_or_int12_operand" "dNOP,f")))]
+ "TARGET_MEDIA"
+ "@
+ xor%I2 %1, %2, %0
+ mxor %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int,mlogic")])
+
+(define_insn "xorsi3_nomedia"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (xor:SI (match_operand:SI 1 "integer_register_operand" "%d")
+ (match_operand:SI 2 "gpr_or_int12_operand" "dNOP")))]
+ "!TARGET_MEDIA"
+ "xor%I2 %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+(define_expand "xorsi3"
+ [(set (match_operand:SI 0 "gpr_or_fpr_operand" "")
+ (xor:SI (match_operand:SI 1 "gpr_or_fpr_operand" "")
+ (match_operand:SI 2 "gpr_fpr_or_int12_operand" "")))]
+ ""
+ "")
+
+;; One's complement, 32 bit integers
+(define_insn "one_cmplsi2_media"
+ [(set (match_operand:SI 0 "gpr_or_fpr_operand" "=d,f")
+ (not:SI (match_operand:SI 1 "gpr_or_fpr_operand" "d,f")))]
+ "TARGET_MEDIA"
+ "@
+ not %1, %0
+ mnot %1, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int,mlogic")])
+
+(define_insn "one_cmplsi2_nomedia"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (not:SI (match_operand:SI 1 "integer_register_operand" "d")))]
+ "!TARGET_MEDIA"
+ "not %1,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+(define_expand "one_cmplsi2"
+ [(set (match_operand:SI 0 "gpr_or_fpr_operand" "")
+ (not:SI (match_operand:SI 1 "gpr_or_fpr_operand" "")))]
+ ""
+ "")
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: 64 Bit Integer Logical operations
+;; ::
+;; ::::::::::::::::::::
+
+;; Logical AND, 64 bit integers
+;; (define_insn "anddi3"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (and:DI (match_operand:DI 1 "register_operand" "%r")
+;; (match_operand:DI 2 "nonmemory_operand" "ri")))]
+;; ""
+;; "anddi3 %0,%1,%2"
+;; [(set_attr "length" "4")])
+
+;; Includive OR, 64 bit integers
+;; (define_insn "iordi3"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (ior:DI (match_operand:DI 1 "register_operand" "%r")
+;; (match_operand:DI 2 "nonmemory_operand" "ri")))]
+;; ""
+;; "iordi3 %0,%1,%2"
+;; [(set_attr "length" "4")])
+
+;; Excludive OR, 64 bit integers
+;; (define_insn "xordi3"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (xor:DI (match_operand:DI 1 "register_operand" "%r")
+;; (match_operand:DI 2 "nonmemory_operand" "ri")))]
+;; ""
+;; "xordi3 %0,%1,%2"
+;; [(set_attr "length" "4")])
+
+;; One's complement, 64 bit integers
+;; (define_insn "one_cmpldi2"
+;; [(set (match_operand:DI 0 "register_operand" "=r")
+;; (not:DI (match_operand:DI 1 "register_operand" "r")))]
+;; ""
+;; "notdi3 %0,%1"
+;; [(set_attr "length" "4")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Combination of integer operation with comparison
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn "*combo_intop_compare1"
+ [(set (match_operand:CC 0 "icc_operand" "=t")
+ (compare:CC (match_operator:SI 1 "intop_compare_operator"
+ [(match_operand:SI 2 "integer_register_operand" "d")
+ (match_operand:SI 3 "gpr_or_int10_operand" "dJ")])
+ (const_int 0)))]
+ ""
+ "%O1%I3cc %2, %3, %., %0"
+ [(set_attr "type" "int")
+ (set_attr "length" "4")])
+
+(define_insn "*combo_intop_compare2"
+ [(set (match_operand:CC_UNS 0 "icc_operand" "=t")
+ (compare:CC_UNS (match_operator:SI 1 "intop_compare_operator"
+ [(match_operand:SI 2 "integer_register_operand" "d")
+ (match_operand:SI 3 "gpr_or_int10_operand" "dJ")])
+ (const_int 0)))]
+ ""
+ "%O1%I3cc %2, %3, %., %0"
+ [(set_attr "type" "int")
+ (set_attr "length" "4")])
+
+(define_insn "*combo_intop_compare3"
+ [(set (match_operand:CC 0 "icc_operand" "=t")
+ (compare:CC (match_operator:SI 1 "intop_compare_operator"
+ [(match_operand:SI 2 "integer_register_operand" "d")
+ (match_operand:SI 3 "gpr_or_int10_operand" "dJ")])
+ (const_int 0)))
+ (set (match_operand:SI 4 "integer_register_operand" "=d")
+ (match_operator:SI 5 "intop_compare_operator"
+ [(match_dup 2)
+ (match_dup 3)]))]
+ "GET_CODE (operands[1]) == GET_CODE (operands[5])"
+ "%O1%I3cc %2, %3, %4, %0"
+ [(set_attr "type" "int")
+ (set_attr "length" "4")])
+
+(define_insn "*combo_intop_compare4"
+ [(set (match_operand:CC_UNS 0 "icc_operand" "=t")
+ (compare:CC_UNS (match_operator:SI 1 "intop_compare_operator"
+ [(match_operand:SI 2 "integer_register_operand" "d")
+ (match_operand:SI 3 "gpr_or_int10_operand" "dJ")])
+ (const_int 0)))
+ (set (match_operand:SI 4 "integer_register_operand" "=d")
+ (match_operator:SI 5 "intop_compare_operator"
+ [(match_dup 2)
+ (match_dup 3)]))]
+ "GET_CODE (operands[1]) == GET_CODE (operands[5])"
+ "%O1%I3cc %2, %3, %4, %0"
+ [(set_attr "type" "int")
+ (set_attr "length" "4")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Comparisons
+;; ::
+;; ::::::::::::::::::::
+
+;; Note, we store the operands in the comparison insns, and use them later
+;; when generating the branch or scc operation.
+
+;; First the routines called by the machine independent part of the compiler
+(define_expand "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "integer_register_operand" "")
+ (match_operand:SI 1 "gpr_or_int10_operand" "")))]
+ ""
+ "
+{
+ frv_compare_op0 = operands[0];
+ frv_compare_op1 = operands[1];
+ DONE;
+}")
+
+;(define_expand "cmpdi"
+; [(set (cc0)
+; (compare (match_operand:DI 0 "register_operand" "")
+; (match_operand:DI 1 "nonmemory_operand" "")))]
+; ""
+; "
+;{
+; frv_compare_op0 = operands[0];
+; frv_compare_op1 = operands[1];
+; DONE;
+;}")
+
+(define_expand "cmpsf"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "fpr_operand" "")
+ (match_operand:SF 1 "fpr_operand" "")))]
+ "TARGET_HARD_FLOAT"
+ "
+{
+ frv_compare_op0 = operands[0];
+ frv_compare_op1 = operands[1];
+ DONE;
+}")
+
+(define_expand "cmpdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "fpr_operand" "")
+ (match_operand:DF 1 "fpr_operand" "")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ "
+{
+ frv_compare_op0 = operands[0];
+ frv_compare_op1 = operands[1];
+ DONE;
+}")
+
+;; Now, the actual comparisons, generated by the branch and/or scc operations
+
+(define_insn "cmpsi_cc"
+ [(set (match_operand:CC 0 "icc_operand" "=t,t")
+ (compare:CC (match_operand:SI 1 "integer_register_operand" "d,d")
+ (match_operand:SI 2 "gpr_or_int10_operand" "d,J")))]
+ ""
+ "cmp%I2 %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+(define_insn "*cmpsi_cc_uns"
+ [(set (match_operand:CC_UNS 0 "icc_operand" "=t,t")
+ (compare:CC_UNS (match_operand:SI 1 "integer_register_operand" "d,d")
+ (match_operand:SI 2 "gpr_or_int10_operand" "d,J")))]
+ ""
+ "cmp%I2 %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+(define_insn "*cmpsf_cc_fp"
+ [(set (match_operand:CC_FP 0 "fcc_operand" "=u")
+ (compare:CC_FP (match_operand:SF 1 "fpr_operand" "f")
+ (match_operand:SF 2 "fpr_operand" "f")))]
+ "TARGET_HARD_FLOAT"
+ "fcmps %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsadd")])
+
+(define_insn "*cmpdf_cc_fp"
+ [(set (match_operand:CC_FP 0 "fcc_operand" "=u")
+ (compare:CC_FP (match_operand:DF 1 "even_fpr_operand" "h")
+ (match_operand:DF 2 "even_fpr_operand" "h")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ "fcmpd %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fdadd")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Branches
+;; ::
+;; ::::::::::::::::::::
+
+;; Define_expands called by the machine independent part of the compiler
+;; to allocate a new comparison register. Each of these named patterns
+;; must be present, and they cannot be amalgamated into one pattern.
+;;
+;; If a fixed condition code register is being used, (as opposed to, say,
+;; using cc0), then the expands should look like this:
+;;
+;; (define_expand "<name_of_test>"
+;; [(set (reg:CC <number_of_CC_register>)
+;; (compare:CC (match_dup 1)
+;; (match_dup 2)))
+;; (set (pc)
+;; (if_then_else (eq:CC (reg:CC <number_of_CC_register>)
+;; (const_int 0))
+;; (label_ref (match_operand 0 "" ""))
+;; (pc)))]
+;; ""
+;; "{
+;; operands[1] = frv_compare_op0;
+;; operands[2] = frv_compare_op1;
+;; }"
+;; )
+
+(define_expand "beq"
+ [(use (match_operand 0 "" ""))]
+ ""
+ "
+{
+ if (! frv_emit_cond_branch (EQ, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "bne"
+ [(use (match_operand 0 "" ""))]
+ ""
+ "
+{
+ if (! frv_emit_cond_branch (NE, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "blt"
+ [(use (match_operand 0 "" ""))]
+ ""
+ "
+{
+ if (! frv_emit_cond_branch (LT, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "ble"
+ [(use (match_operand 0 "" ""))]
+ ""
+ "
+{
+ if (! frv_emit_cond_branch (LE, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "bgt"
+ [(use (match_operand 0 "" ""))]
+ ""
+ "
+{
+ if (! frv_emit_cond_branch (GT, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "bge"
+ [(use (match_operand 0 "" ""))]
+ ""
+ "
+{
+ if (! frv_emit_cond_branch (GE, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "bltu"
+ [(use (match_operand 0 "" ""))]
+ ""
+ "
+{
+ if (! frv_emit_cond_branch (LTU, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "bleu"
+ [(use (match_operand 0 "" ""))]
+ ""
+ "
+{
+ if (! frv_emit_cond_branch (LEU, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "bgtu"
+ [(use (match_operand 0 "" ""))]
+ ""
+ "
+{
+ if (! frv_emit_cond_branch (GTU, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "bgeu"
+ [(use (match_operand 0 "" ""))]
+ ""
+ "
+{
+ if (! frv_emit_cond_branch (GEU, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+;; Actual branches. We must allow for the (label_ref) and the (pc) to be
+;; swapped. If they are swapped, it reverses the sense of the branch.
+;;
+;; Note - unlike the define expands above, these patterns can be amalgamated
+;; into one pattern for branch-if-true and one for branch-if-false. This does
+;; require an operand operator to select the correct branch mnemonic.
+;;
+;; If a fixed condition code register is being used, (as opposed to, say,
+;; using cc0), then the expands could look like this:
+;;
+;; (define_insn "*branch_true"
+;; [(set (pc)
+;; (if_then_else (match_operator:CC 0 "comparison_operator"
+;; [(reg:CC <number_of_CC_register>)
+;; (const_int 0)])
+;; (label_ref (match_operand 1 "" ""))
+;; (pc)))]
+;; ""
+;; "b%B0 %1"
+;; [(set_attr "length" "4")]
+;; )
+;;
+;; In the above example the %B is a directive to frv_print_operand()
+;; to decode and print the correct branch mnemonic.
+
+(define_insn "*branch_signed_true"
+ [(set (pc)
+ (if_then_else (match_operator:CC 0 "signed_relational_operator"
+ [(match_operand 1 "icc_operand" "t")
+ (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ if (get_attr_length (insn) == 4)
+ return \"b%c0 %1,%#,%l2\";
+ else
+ return \"b%C0 %1,%#,1f\;call %l2\\n1:\";
+}"
+ [(set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
+ (le (minus (match_dup 2) (pc)) (const_int 32764)))
+ (const_int 4)
+ (const_int 8)))
+ (set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "4")
+ (const_string "no")
+ (const_string "yes")))
+ (set (attr "type")
+ (if_then_else
+ (eq_attr "length" "4")
+ (const_string "branch")
+ (const_string "multi")))])
+
+(define_insn "*branch_signed_false"
+ [(set (pc)
+ (if_then_else (match_operator:CC 0 "signed_relational_operator"
+ [(match_operand 1 "icc_operand" "t")
+ (const_int 0)])
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ ""
+ "*
+{
+ if (get_attr_length (insn) == 4)
+ return \"b%C0 %1,%#,%l2\";
+ else
+ return \"b%c0 %1,%#,1f\;call %l2\\n1:\";
+}"
+ [(set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
+ (le (minus (match_dup 2) (pc)) (const_int 32764)))
+ (const_int 4)
+ (const_int 8)))
+ (set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "4")
+ (const_string "no")
+ (const_string "yes")))
+ (set (attr "type")
+ (if_then_else
+ (eq_attr "length" "4")
+ (const_string "branch")
+ (const_string "multi")))])
+
+(define_insn "*branch_unsigned_true"
+ [(set (pc)
+ (if_then_else (match_operator:CC_UNS 0 "unsigned_relational_operator"
+ [(match_operand 1 "icc_operand" "t")
+ (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ if (get_attr_length (insn) == 4)
+ return \"b%c0 %1,%#,%l2\";
+ else
+ return \"b%C0 %1,%#,1f\;call %l2\\n1:\";
+}"
+ [(set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
+ (le (minus (match_dup 2) (pc)) (const_int 32764)))
+ (const_int 4)
+ (const_int 8)))
+ (set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "4")
+ (const_string "no")
+ (const_string "yes")))
+ (set (attr "type")
+ (if_then_else
+ (eq_attr "length" "4")
+ (const_string "branch")
+ (const_string "multi")))])
+
+(define_insn "*branch_unsigned_false"
+ [(set (pc)
+ (if_then_else (match_operator:CC_UNS 0 "unsigned_relational_operator"
+ [(match_operand 1 "icc_operand" "t")
+ (const_int 0)])
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ ""
+ "*
+{
+ if (get_attr_length (insn) == 4)
+ return \"b%C0 %1,%#,%l2\";
+ else
+ return \"b%c0 %1,%#,1f\;call %l2\\n1:\";
+}"
+ [(set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
+ (le (minus (match_dup 2) (pc)) (const_int 32764)))
+ (const_int 4)
+ (const_int 8)))
+ (set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "4")
+ (const_string "no")
+ (const_string "yes")))
+ (set (attr "type")
+ (if_then_else
+ (eq_attr "length" "4")
+ (const_string "branch")
+ (const_string "multi")))])
+
+(define_insn "*branch_fp_true"
+ [(set (pc)
+ (if_then_else (match_operator:CC_FP 0 "float_relational_operator"
+ [(match_operand 1 "fcc_operand" "u")
+ (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ if (get_attr_length (insn) == 4)
+ return \"fb%f0 %1,%#,%l2\";
+ else
+ return \"fb%F0 %1,%#,1f\;call %l2\\n1:\";
+}"
+ [(set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
+ (le (minus (match_dup 2) (pc)) (const_int 32764)))
+ (const_int 4)
+ (const_int 8)))
+ (set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "4")
+ (const_string "no")
+ (const_string "yes")))
+ (set (attr "type")
+ (if_then_else
+ (eq_attr "length" "4")
+ (const_string "branch")
+ (const_string "multi")))])
+
+(define_insn "*branch_fp_false"
+ [(set (pc)
+ (if_then_else (match_operator:CC_FP 0 "float_relational_operator"
+ [(match_operand 1 "fcc_operand" "u")
+ (const_int 0)])
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ ""
+ "*
+{
+ if (get_attr_length (insn) == 4)
+ return \"fb%F0 %1,%#,%l2\";
+ else
+ return \"fb%f0 %1,%#,1f\;call %l2\\n1:\";
+}"
+ [(set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
+ (le (minus (match_dup 2) (pc)) (const_int 32764)))
+ (const_int 4)
+ (const_int 8)))
+ (set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "4")
+ (const_string "no")
+ (const_string "yes")))
+ (set (attr "type")
+ (if_then_else
+ (eq_attr "length" "4")
+ (const_string "branch")
+ (const_string "multi")))])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Set flag operations
+;; ::
+;; ::::::::::::::::::::
+
+;; Define_expands called by the machine independent part of the compiler
+;; to allocate a new comparison register
+
+(define_expand "seq"
+ [(match_operand:SI 0 "integer_register_operand" "")]
+ "TARGET_SCC"
+ "
+{
+ if (! frv_emit_scc (EQ, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "sne"
+ [(match_operand:SI 0 "integer_register_operand" "")]
+ "TARGET_SCC"
+ "
+{
+ if (! frv_emit_scc (NE, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "slt"
+ [(match_operand:SI 0 "integer_register_operand" "")]
+ "TARGET_SCC"
+ "
+{
+ if (! frv_emit_scc (LT, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "sle"
+ [(match_operand:SI 0 "integer_register_operand" "")]
+ "TARGET_SCC"
+ "
+{
+ if (! frv_emit_scc (LE, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "sgt"
+ [(match_operand:SI 0 "integer_register_operand" "")]
+ "TARGET_SCC"
+ "
+{
+ if (! frv_emit_scc (GT, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "sge"
+ [(match_operand:SI 0 "integer_register_operand" "")]
+ "TARGET_SCC"
+ "
+{
+ if (! frv_emit_scc (GE, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "sltu"
+ [(match_operand:SI 0 "integer_register_operand" "")]
+ "TARGET_SCC"
+ "
+{
+ if (! frv_emit_scc (LTU, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "sleu"
+ [(match_operand:SI 0 "integer_register_operand" "")]
+ "TARGET_SCC"
+ "
+{
+ if (! frv_emit_scc (LEU, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "sgtu"
+ [(match_operand:SI 0 "integer_register_operand" "")]
+ "TARGET_SCC"
+ "
+{
+ if (! frv_emit_scc (GTU, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_expand "sgeu"
+ [(match_operand:SI 0 "integer_register_operand" "")]
+ "TARGET_SCC"
+ "
+{
+ if (! frv_emit_scc (GEU, operands[0]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_insn "*scc_signed"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (match_operator:SI 1 "signed_relational_operator"
+ [(match_operand:CC 2 "icc_operand" "t")
+ (const_int 0)]))
+ (clobber (match_operand:CC_CCR 3 "icr_operand" "=v"))]
+ ""
+ "#"
+ [(set_attr "length" "12")
+ (set_attr "type" "multi")])
+
+(define_insn "*scc_unsigned"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (match_operator:SI 1 "unsigned_relational_operator"
+ [(match_operand:CC_UNS 2 "icc_operand" "t")
+ (const_int 0)]))
+ (clobber (match_operand:CC_CCR 3 "icr_operand" "=v"))]
+ ""
+ "#"
+ [(set_attr "length" "12")
+ (set_attr "type" "multi")])
+
+(define_insn "*scc_float"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (match_operator:SI 1 "float_relational_operator"
+ [(match_operand:CC_FP 2 "fcc_operand" "u")
+ (const_int 0)]))
+ (clobber (match_operand:CC_CCR 3 "fcr_operand" "=w"))]
+ ""
+ "#"
+ [(set_attr "length" "12")
+ (set_attr "type" "multi")])
+
+;; XXX -- add reload_completed to the splits, because register allocation
+;; currently isn't ready to see cond_exec packets.
+(define_split
+ [(set (match_operand:SI 0 "integer_register_operand" "")
+ (match_operator:SI 1 "relational_operator"
+ [(match_operand 2 "cc_operand" "")
+ (const_int 0)]))
+ (clobber (match_operand 3 "cr_operand" ""))]
+ "reload_completed"
+ [(match_dup 4)]
+ "operands[4] = frv_split_scc (operands[0], operands[1], operands[2],
+ operands[3], (HOST_WIDE_INT) 1);")
+
+(define_insn "*scc_neg1_signed"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (neg:SI (match_operator:SI 1 "signed_relational_operator"
+ [(match_operand:CC 2 "icc_operand" "t")
+ (const_int 0)])))
+ (clobber (match_operand:CC_CCR 3 "icr_operand" "=v"))]
+ ""
+ "#"
+ [(set_attr "length" "12")
+ (set_attr "type" "multi")])
+
+(define_insn "*scc_neg1_unsigned"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (neg:SI (match_operator:SI 1 "unsigned_relational_operator"
+ [(match_operand:CC_UNS 2 "icc_operand" "t")
+ (const_int 0)])))
+ (clobber (match_operand:CC_CCR 3 "icr_operand" "=v"))]
+ ""
+ "#"
+ [(set_attr "length" "12")
+ (set_attr "type" "multi")])
+
+(define_insn "*scc_neg1_float"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (neg:SI (match_operator:SI 1 "float_relational_operator"
+ [(match_operand:CC_FP 2 "fcc_operand" "u")
+ (const_int 0)])))
+ (clobber (match_operand:CC_CCR 3 "fcr_operand" "=w"))]
+ ""
+ "#"
+ [(set_attr "length" "12")
+ (set_attr "type" "multi")])
+
+(define_split
+ [(set (match_operand:SI 0 "integer_register_operand" "")
+ (neg:SI (match_operator:SI 1 "relational_operator"
+ [(match_operand 2 "cc_operand" "")
+ (const_int 0)])))
+ (clobber (match_operand 3 "cr_operand" ""))]
+ "reload_completed"
+ [(match_dup 4)]
+ "operands[4] = frv_split_scc (operands[0], operands[1], operands[2],
+ operands[3], (HOST_WIDE_INT) -1);")
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Conditionally executed instructions
+;; ::
+;; ::::::::::::::::::::
+
+;; Convert ICC/FCC comparison into CCR bits so we can do conditional execution
+(define_insn "*ck_signed"
+ [(set (match_operand:CC_CCR 0 "icr_operand" "=v")
+ (match_operator:CC_CCR 1 "signed_relational_operator"
+ [(match_operand:CC 2 "icc_operand" "t")
+ (const_int 0)]))]
+ ""
+ "ck%c1 %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "ccr")])
+
+(define_insn "*ck_unsigned"
+ [(set (match_operand:CC_CCR 0 "icr_operand" "=v")
+ (match_operator:CC_CCR 1 "unsigned_relational_operator"
+ [(match_operand:CC_UNS 2 "icc_operand" "t")
+ (const_int 0)]))]
+ ""
+ "ck%c1 %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "ccr")])
+
+(define_insn "*fck_float"
+ [(set (match_operand:CC_CCR 0 "fcr_operand" "=w")
+ (match_operator:CC_CCR 1 "float_relational_operator"
+ [(match_operand:CC_FP 2 "fcc_operand" "u")
+ (const_int 0)]))]
+ "TARGET_HAS_FPRS"
+ "fck%c1 %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "ccr")])
+
+;; Conditionally convert ICC/FCC comparison into CCR bits to provide && and ||
+;; tests in conditional execution
+(define_insn "cond_exec_ck"
+ [(set (match_operand:CC_CCR 0 "cr_operand" "=v,w")
+ (if_then_else:CC_CCR (match_operator 1 "ccr_eqne_operator"
+ [(match_operand 2 "cr_operand" "C,C")
+ (const_int 0)])
+ (match_operator 3 "relational_operator"
+ [(match_operand 4 "cc_operand" "t,u")
+ (const_int 0)])
+ (const_int 0)))]
+ ""
+ "@
+ cck%c3 %4, %0, %2, %e1
+ cfck%f3 %4, %0, %2, %e1"
+ [(set_attr "length" "4")
+ (set_attr "type" "ccr")])
+
+;; Conditionally set a register to either 0 or another register
+(define_insn "*cond_exec_movqi"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C,C,C,C,C,C")
+ (const_int 0)])
+ (set (match_operand:QI 2 "condexec_dest_operand" "=d,d,U,?f,?f,?d")
+ (match_operand:QI 3 "condexec_source_operand" "dO,U,dO,f,d,f")))]
+ "register_operand(operands[2], QImode) || reg_or_0_operand (operands[3], QImode)"
+ "* return output_condmove_single (operands, insn);"
+ [(set_attr "length" "4")
+ (set_attr "type" "int,gload,gstore,fsconv,movgf,movfg")])
+
+(define_insn "*cond_exec_movhi"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C,C,C,C,C,C")
+ (const_int 0)])
+ (set (match_operand:HI 2 "condexec_dest_operand" "=d,d,U,?f,?f,?d")
+ (match_operand:HI 3 "condexec_source_operand" "dO,U,dO,f,d,f")))]
+ "register_operand(operands[2], HImode) || reg_or_0_operand (operands[3], HImode)"
+ "* return output_condmove_single (operands, insn);"
+ [(set_attr "length" "4")
+ (set_attr "type" "int,gload,gstore,fsconv,movgf,movfg")])
+
+(define_insn "*cond_exec_movsi"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C,C,C,C,C,C,C,C")
+ (const_int 0)])
+ (set (match_operand:SI 2 "condexec_dest_operand" "=d,d,U,?f,?f,?d,?f,?m")
+ (match_operand:SI 3 "condexec_source_operand" "dO,U,dO,f,d,f,m,f")))]
+ "register_operand(operands[2], SImode) || reg_or_0_operand (operands[3], SImode)"
+ "* return output_condmove_single (operands, insn);"
+ [(set_attr "length" "4")
+ (set_attr "type" "int,gload,gstore,fsconv,movgf,movfg,fload,fstore")])
+
+
+(define_insn "*cond_exec_movsf_has_fprs"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C,C,C,C,C,C,C,C,C,C")
+ (const_int 0)])
+ (set (match_operand:SF 2 "condexec_dest_operand" "=f,?d,?d,?f,f,f,?d,U,?U,U")
+ (match_operand:SF 3 "condexec_source_operand" "f,d,f,d,G,U,U,f,d,G")))]
+ "TARGET_HAS_FPRS"
+ "* return output_condmove_single (operands, insn);"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsconv,int,movgf,movfg,movgf,fload,gload,fstore,gstore,gstore")])
+
+(define_insn "*cond_exec_movsf_no_fprs"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C,C,C")
+ (const_int 0)])
+ (set (match_operand:SF 2 "condexec_dest_operand" "=d,d,U")
+ (match_operand:SF 3 "condexec_source_operand" "d,U,dG")))]
+ "! TARGET_HAS_FPRS"
+ "* return output_condmove_single (operands, insn);"
+ [(set_attr "length" "4")
+ (set_attr "type" "int,gload,gstore")])
+
+(define_insn "*cond_exec_si_binary1"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SI 2 "integer_register_operand" "=d")
+ (match_operator:SI 3 "condexec_si_binary_operator"
+ [(match_operand:SI 4 "integer_register_operand" "d")
+ (match_operand:SI 5 "integer_register_operand" "d")])))]
+ ""
+ "*
+{
+ switch (GET_CODE (operands[3]))
+ {
+ case PLUS: return \"cadd %4, %z5, %2, %1, %e0\";
+ case MINUS: return \"csub %4, %z5, %2, %1, %e0\";
+ case AND: return \"cand %4, %z5, %2, %1, %e0\";
+ case IOR: return \"cor %4, %z5, %2, %1, %e0\";
+ case XOR: return \"cxor %4, %z5, %2, %1, %e0\";
+ case ASHIFT: return \"csll %4, %z5, %2, %1, %e0\";
+ case ASHIFTRT: return \"csra %4, %z5, %2, %1, %e0\";
+ case LSHIFTRT: return \"csrl %4, %z5, %2, %1, %e0\";
+ default: abort ();
+ }
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+(define_insn "*cond_exec_si_binary2"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SI 2 "fpr_operand" "=f")
+ (match_operator:SI 3 "condexec_si_media_operator"
+ [(match_operand:SI 4 "fpr_operand" "f")
+ (match_operand:SI 5 "fpr_operand" "f")])))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (GET_CODE (operands[3]))
+ {
+ case AND: return \"cmand %4, %5, %2, %1, %e0\";
+ case IOR: return \"cmor %4, %5, %2, %1, %e0\";
+ case XOR: return \"cmxor %4, %5, %2, %1, %e0\";
+ default: abort ();
+ }
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mlogic")])
+
+;; Note, flow does not (currently) know how to handle an operation that uses
+;; only part of the hard registers allocated for a multiregister value, such as
+;; DImode in this case if the user is only interested in the lower 32-bits. So
+;; we emit a USE of the entire register after the csmul instruction so it won't
+;; get confused. See frv_ifcvt_modify_insn for more details.
+
+(define_insn "*cond_exec_si_smul"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:DI 2 "even_gpr_operand" "=e")
+ (mult:DI (sign_extend:DI (match_operand:SI 3 "integer_register_operand" "%d"))
+ (sign_extend:DI (match_operand:SI 4 "integer_register_operand" "d")))))]
+ ""
+ "csmul %3, %4, %2, %1, %e0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mul")])
+
+(define_insn "*cond_exec_si_divide"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SI 2 "integer_register_operand" "=d")
+ (match_operator:SI 3 "condexec_si_divide_operator"
+ [(match_operand:SI 4 "integer_register_operand" "d")
+ (match_operand:SI 5 "integer_register_operand" "d")])))]
+ ""
+ "*
+{
+ switch (GET_CODE (operands[3]))
+ {
+ case DIV: return \"csdiv %4, %z5, %2, %1, %e0\";
+ case UDIV: return \"cudiv %4, %z5, %2, %1, %e0\";
+ default: abort ();
+ }
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "div")])
+
+(define_insn "*cond_exec_si_unary1"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SI 2 "integer_register_operand" "=d")
+ (match_operator:SI 3 "condexec_si_unary_operator"
+ [(match_operand:SI 4 "integer_register_operand" "d")])))]
+ ""
+ "*
+{
+ switch (GET_CODE (operands[3]))
+ {
+ case NOT: return \"cnot %4, %2, %1, %e0\";
+ case NEG: return \"csub %., %4, %2, %1, %e0\";
+ default: abort ();
+ }
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+(define_insn "*cond_exec_si_unary2"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SI 2 "fpr_operand" "=f")
+ (not:SI (match_operand:SI 3 "fpr_operand" "f"))))]
+ "TARGET_MEDIA"
+ "cmnot %3, %2, %1, %e0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mlogic")])
+
+(define_insn "*cond_exec_cmpsi_cc"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:CC 2 "icc_operand" "=t")
+ (compare:CC (match_operand:SI 3 "integer_register_operand" "d")
+ (match_operand:SI 4 "reg_or_0_operand" "dO"))))]
+ "reload_completed
+ && REGNO (operands[1]) == REGNO (operands[2]) - ICC_FIRST + ICR_FIRST"
+ "ccmp %3, %z4, %1, %e0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+(define_insn "*cond_exec_cmpsi_cc_uns"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:CC_UNS 2 "icc_operand" "=t")
+ (compare:CC_UNS (match_operand:SI 3 "integer_register_operand" "d")
+ (match_operand:SI 4 "reg_or_0_operand" "dO"))))]
+ "reload_completed
+ && REGNO (operands[1]) == REGNO (operands[2]) - ICC_FIRST + ICR_FIRST"
+ "ccmp %3, %z4, %1, %e0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+(define_insn "*cond_exec_sf_conv"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SF 2 "fpr_operand" "=f")
+ (match_operator:SF 3 "condexec_sf_conv_operator"
+ [(match_operand:SF 4 "fpr_operand" "f")])))]
+ "TARGET_HARD_FLOAT"
+ "*
+{
+ switch (GET_CODE (operands[3]))
+ {
+ case ABS: return \"cfabss %4, %2, %1, %e0\";
+ case NEG: return \"cfnegs %4, %2, %1, %e0\";
+ default: abort ();
+ }
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsconv")])
+
+(define_insn "*cond_exec_sf_add"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SF 2 "fpr_operand" "=f")
+ (match_operator:SF 3 "condexec_sf_add_operator"
+ [(match_operand:SF 4 "fpr_operand" "f")
+ (match_operand:SF 5 "fpr_operand" "f")])))]
+ "TARGET_HARD_FLOAT"
+ "*
+{
+ switch (GET_CODE (operands[3]))
+ {
+ case PLUS: return \"cfadds %4, %5, %2, %1, %e0\";
+ case MINUS: return \"cfsubs %4, %5, %2, %1, %e0\";
+ default: abort ();
+ }
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsadd")])
+
+(define_insn "*cond_exec_sf_mul"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SF 2 "fpr_operand" "=f")
+ (mult:SF (match_operand:SF 3 "fpr_operand" "f")
+ (match_operand:SF 4 "fpr_operand" "f"))))]
+ "TARGET_HARD_FLOAT"
+ "cfmuls %3, %4, %2, %1, %e0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsmul")])
+
+(define_insn "*cond_exec_sf_div"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SF 2 "fpr_operand" "=f")
+ (div:SF (match_operand:SF 3 "fpr_operand" "f")
+ (match_operand:SF 4 "fpr_operand" "f"))))]
+ "TARGET_HARD_FLOAT"
+ "cfdivs %3, %4, %2, %1, %e0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsdiv")])
+
+(define_insn "*cond_exec_sf_sqrt"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SF 2 "fpr_operand" "=f")
+ (sqrt:SF (match_operand:SF 3 "fpr_operand" "f"))))]
+ "TARGET_HARD_FLOAT"
+ "cfsqrts %3, %2, %1, %e0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsdiv")])
+
+(define_insn "*cond_exec_cmpsi_cc_fp"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:CC_FP 2 "fcc_operand" "=u")
+ (compare:CC_FP (match_operand:SF 3 "fpr_operand" "f")
+ (match_operand:SF 4 "fpr_operand" "f"))))]
+ "reload_completed && TARGET_HARD_FLOAT
+ && REGNO (operands[1]) == REGNO (operands[2]) - FCC_FIRST + FCR_FIRST"
+ "cfcmps %3, %4, %2, %1, %e0"
+ [(set_attr "length" "4")
+ (set_attr "type" "fsconv")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Logical operations on CR registers
+;; ::
+;; ::::::::::::::::::::
+
+;; We use UNSPEC to encode andcr/iorcr/etc. rather than the normal RTL
+;; operations, since the RTL operations only have an idea of TRUE and FALSE,
+;; while the CRs have TRUE, FALSE, and UNDEFINED.
+
+(define_expand "andcr"
+ [(set (match_operand:CC_CCR 0 "cr_operand" "")
+ (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "")
+ (match_operand:CC_CCR 2 "cr_operand" "")
+ (const_int 0)] UNSPEC_CR_LOGIC))]
+ ""
+ "")
+
+(define_expand "orcr"
+ [(set (match_operand:CC_CCR 0 "cr_operand" "")
+ (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "")
+ (match_operand:CC_CCR 2 "cr_operand" "")
+ (const_int 1)] UNSPEC_CR_LOGIC))]
+ ""
+ "")
+
+(define_expand "xorcr"
+ [(set (match_operand:CC_CCR 0 "cr_operand" "")
+ (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "")
+ (match_operand:CC_CCR 2 "cr_operand" "")
+ (const_int 2)] UNSPEC_CR_LOGIC))]
+ ""
+ "")
+
+(define_expand "nandcr"
+ [(set (match_operand:CC_CCR 0 "cr_operand" "")
+ (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "")
+ (match_operand:CC_CCR 2 "cr_operand" "")
+ (const_int 3)] UNSPEC_CR_LOGIC))]
+ ""
+ "")
+
+(define_expand "norcr"
+ [(set (match_operand:CC_CCR 0 "cr_operand" "")
+ (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "")
+ (match_operand:CC_CCR 2 "cr_operand" "")
+ (const_int 4)] UNSPEC_CR_LOGIC))]
+ ""
+ "")
+
+(define_expand "andncr"
+ [(set (match_operand:CC_CCR 0 "cr_operand" "")
+ (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "")
+ (match_operand:CC_CCR 2 "cr_operand" "")
+ (const_int 5)] UNSPEC_CR_LOGIC))]
+ ""
+ "")
+
+(define_expand "orncr"
+ [(set (match_operand:CC_CCR 0 "cr_operand" "")
+ (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "")
+ (match_operand:CC_CCR 2 "cr_operand" "")
+ (const_int 6)] UNSPEC_CR_LOGIC))]
+ ""
+ "")
+
+(define_expand "nandncr"
+ [(set (match_operand:CC_CCR 0 "cr_operand" "")
+ (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "")
+ (match_operand:CC_CCR 2 "cr_operand" "")
+ (const_int 7)] UNSPEC_CR_LOGIC))]
+ ""
+ "")
+
+(define_expand "norncr"
+ [(set (match_operand:CC_CCR 0 "cr_operand" "")
+ (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "")
+ (match_operand:CC_CCR 2 "cr_operand" "")
+ (const_int 8)] UNSPEC_CR_LOGIC))]
+ ""
+ "")
+
+(define_expand "notcr"
+ [(set (match_operand:CC_CCR 0 "cr_operand" "")
+ (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "")
+ (match_dup 1)
+ (const_int 9)] UNSPEC_CR_LOGIC))]
+ ""
+ "")
+
+(define_insn "*logical_cr"
+ [(set (match_operand:CC_CCR 0 "cr_operand" "=C")
+ (unspec:CC_CCR [(match_operand:CC_CCR 1 "cr_operand" "C")
+ (match_operand:CC_CCR 2 "cr_operand" "C")
+ (match_operand:SI 3 "const_int_operand" "n")]
+ UNSPEC_CR_LOGIC))]
+ ""
+ "*
+{
+ switch (INTVAL (operands[3]))
+ {
+ default: break;
+ case 0: return \"andcr %1, %2, %0\";
+ case 1: return \"orcr %1, %2, %0\";
+ case 2: return \"xorcr %1, %2, %0\";
+ case 3: return \"nandcr %1, %2, %0\";
+ case 4: return \"norcr %1, %2, %0\";
+ case 5: return \"andncr %1, %2, %0\";
+ case 6: return \"orncr %1, %2, %0\";
+ case 7: return \"nandncr %1, %2, %0\";
+ case 8: return \"norncr %1, %2, %0\";
+ case 9: return \"notcr %1, %0\";
+ }
+
+ fatal_insn (\"logical_cr\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "ccr")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Conditional move instructions
+;; ::
+;; ::::::::::::::::::::
+
+
+;; - conditional moves based on floating-point comparisons require
+;; TARGET_HARD_FLOAT, because an FPU is required to do the comparison.
+
+;; - conditional moves between FPRs based on integer comparisons
+;; require TARGET_HAS_FPRS.
+
+(define_expand "movqicc"
+ [(set (match_operand:QI 0 "integer_register_operand" "")
+ (if_then_else:QI (match_operand 1 "" "")
+ (match_operand:QI 2 "gpr_or_int_operand" "")
+ (match_operand:QI 3 "gpr_or_int_operand" "")))]
+ "TARGET_COND_MOVE"
+ "
+{
+ if (!frv_emit_cond_move (operands[0], operands[1], operands[2], operands[3]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_insn "*movqicc_internal1_signed"
+ [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d")
+ (if_then_else:QI (match_operator:CC 1 "signed_relational_operator"
+ [(match_operand:CC 2 "icc_operand" "t,t,t")
+ (const_int 0)])
+ (match_operand:QI 3 "reg_or_0_operand" "0,dO,dO")
+ (match_operand:QI 4 "reg_or_0_operand" "dO,0,dO")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))]
+ ""
+ "#"
+ [(set_attr "length" "8,8,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movqicc_internal1_unsigned"
+ [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d")
+ (if_then_else:QI (match_operator:CC_UNS 1 "unsigned_relational_operator"
+ [(match_operand:CC_UNS 2 "icc_operand" "t,t,t")
+ (const_int 0)])
+ (match_operand:QI 3 "reg_or_0_operand" "0,dO,dO")
+ (match_operand:QI 4 "reg_or_0_operand" "dO,0,dO")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))]
+ ""
+ "#"
+ [(set_attr "length" "8,8,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movqicc_internal1_float"
+ [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d")
+ (if_then_else:QI (match_operator:CC_FP 1 "float_relational_operator"
+ [(match_operand:CC_FP 2 "fcc_operand" "u,u,u")
+ (const_int 0)])
+ (match_operand:QI 3 "reg_or_0_operand" "0,dO,dO")
+ (match_operand:QI 4 "reg_or_0_operand" "dO,0,dO")))
+ (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))]
+ "TARGET_HARD_FLOAT"
+ "#"
+ [(set_attr "length" "8,8,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movqicc_internal2_signed"
+ [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d,d,d")
+ (if_then_else:QI (match_operator:CC 1 "signed_relational_operator"
+ [(match_operand:CC 2 "icc_operand" "t,t,t,t,t")
+ (const_int 0)])
+ (match_operand:QI 3 "const_int_operand" "O,O,L,n,n")
+ (match_operand:QI 4 "const_int_operand" "L,n,O,O,n")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))]
+ "(INTVAL (operands[3]) == 0
+ || INTVAL (operands[4]) == 0
+ || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047)
+ && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))"
+ "#"
+ [(set_attr "length" "8,12,8,12,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movqicc_internal2_unsigned"
+ [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d,d,d")
+ (if_then_else:QI (match_operator:CC_UNS 1 "unsigned_relational_operator"
+ [(match_operand:CC_UNS 2 "icc_operand" "t,t,t,t,t")
+ (const_int 0)])
+ (match_operand:QI 3 "const_int_operand" "O,O,L,n,n")
+ (match_operand:QI 4 "const_int_operand" "L,n,O,O,n")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))]
+ "(INTVAL (operands[3]) == 0
+ || INTVAL (operands[4]) == 0
+ || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047)
+ && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))"
+ "#"
+ [(set_attr "length" "8,12,8,12,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movqicc_internal2_float"
+ [(set (match_operand:QI 0 "integer_register_operand" "=d,d,d,d,d")
+ (if_then_else:QI (match_operator:CC_FP 1 "float_relational_operator"
+ [(match_operand:CC_FP 2 "fcc_operand" "u,u,u,u,u")
+ (const_int 0)])
+ (match_operand:QI 3 "const_int_operand" "O,O,L,n,n")
+ (match_operand:QI 4 "const_int_operand" "L,n,O,O,n")))
+ (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w,w,w"))]
+ "TARGET_HARD_FLOAT
+ && (INTVAL (operands[3]) == 0
+ || INTVAL (operands[4]) == 0
+ || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047)
+ && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))"
+ "#"
+ [(set_attr "length" "8,12,8,12,12")
+ (set_attr "type" "multi")])
+
+(define_split
+ [(set (match_operand:QI 0 "integer_register_operand" "")
+ (if_then_else:QI (match_operator 1 "relational_operator"
+ [(match_operand 2 "cc_operand" "")
+ (const_int 0)])
+ (match_operand:QI 3 "gpr_or_int_operand" "")
+ (match_operand:QI 4 "gpr_or_int_operand" "")))
+ (clobber (match_operand:CC_CCR 5 "cr_operand" ""))]
+ "reload_completed"
+ [(match_dup 6)]
+ "operands[6] = frv_split_cond_move (operands);")
+
+(define_expand "movhicc"
+ [(set (match_operand:HI 0 "integer_register_operand" "")
+ (if_then_else:HI (match_operand 1 "" "")
+ (match_operand:HI 2 "gpr_or_int_operand" "")
+ (match_operand:HI 3 "gpr_or_int_operand" "")))]
+ "TARGET_COND_MOVE"
+ "
+{
+ if (!frv_emit_cond_move (operands[0], operands[1], operands[2], operands[3]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_insn "*movhicc_internal1_signed"
+ [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d")
+ (if_then_else:HI (match_operator:CC 1 "signed_relational_operator"
+ [(match_operand:CC 2 "icc_operand" "t,t,t")
+ (const_int 0)])
+ (match_operand:HI 3 "reg_or_0_operand" "0,dO,dO")
+ (match_operand:HI 4 "reg_or_0_operand" "dO,0,dO")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))]
+ ""
+ "#"
+ [(set_attr "length" "8,8,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movhicc_internal1_unsigned"
+ [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d")
+ (if_then_else:HI (match_operator:CC_UNS 1 "unsigned_relational_operator"
+ [(match_operand:CC_UNS 2 "icc_operand" "t,t,t")
+ (const_int 0)])
+ (match_operand:HI 3 "reg_or_0_operand" "0,dO,dO")
+ (match_operand:HI 4 "reg_or_0_operand" "dO,0,dO")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))]
+ ""
+ "#"
+ [(set_attr "length" "8,8,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movhicc_internal1_float"
+ [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d")
+ (if_then_else:HI (match_operator:CC_FP 1 "float_relational_operator"
+ [(match_operand:CC_FP 2 "fcc_operand" "u,u,u")
+ (const_int 0)])
+ (match_operand:HI 3 "reg_or_0_operand" "0,dO,dO")
+ (match_operand:HI 4 "reg_or_0_operand" "dO,0,dO")))
+ (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))]
+ "TARGET_HARD_FLOAT"
+ "#"
+ [(set_attr "length" "8,8,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movhicc_internal2_signed"
+ [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d,d,d")
+ (if_then_else:HI (match_operator:CC 1 "signed_relational_operator"
+ [(match_operand:CC 2 "icc_operand" "t,t,t,t,t")
+ (const_int 0)])
+ (match_operand:HI 3 "const_int_operand" "O,O,L,n,n")
+ (match_operand:HI 4 "const_int_operand" "L,n,O,O,n")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))]
+ "(INTVAL (operands[3]) == 0
+ || INTVAL (operands[4]) == 0
+ || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047)
+ && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))"
+ "#"
+ [(set_attr "length" "8,12,8,12,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movhicc_internal2_unsigned"
+ [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d,d,d")
+ (if_then_else:HI (match_operator:CC_UNS 1 "unsigned_relational_operator"
+ [(match_operand:CC_UNS 2 "icc_operand" "t,t,t,t,t")
+ (const_int 0)])
+ (match_operand:HI 3 "const_int_operand" "O,O,L,n,n")
+ (match_operand:HI 4 "const_int_operand" "L,n,O,O,n")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))]
+ "(INTVAL (operands[3]) == 0
+ || INTVAL (operands[4]) == 0
+ || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047)
+ && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))"
+ "#"
+ [(set_attr "length" "8,12,8,12,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movhicc_internal2_float"
+ [(set (match_operand:HI 0 "integer_register_operand" "=d,d,d,d,d")
+ (if_then_else:HI (match_operator:CC_FP 1 "float_relational_operator"
+ [(match_operand:CC_FP 2 "fcc_operand" "u,u,u,u,u")
+ (const_int 0)])
+ (match_operand:HI 3 "const_int_operand" "O,O,L,n,n")
+ (match_operand:HI 4 "const_int_operand" "L,n,O,O,n")))
+ (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w,w,w"))]
+ "TARGET_HARD_FLOAT
+ && (INTVAL (operands[3]) == 0
+ || INTVAL (operands[4]) == 0
+ || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047)
+ && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))"
+ "#"
+ [(set_attr "length" "8,12,8,12,12")
+ (set_attr "type" "multi")])
+
+(define_split
+ [(set (match_operand:HI 0 "integer_register_operand" "")
+ (if_then_else:HI (match_operator 1 "relational_operator"
+ [(match_operand 2 "cc_operand" "")
+ (const_int 0)])
+ (match_operand:HI 3 "gpr_or_int_operand" "")
+ (match_operand:HI 4 "gpr_or_int_operand" "")))
+ (clobber (match_operand:CC_CCR 5 "cr_operand" ""))]
+ "reload_completed"
+ [(match_dup 6)]
+ "operands[6] = frv_split_cond_move (operands);")
+
+(define_expand "movsicc"
+ [(set (match_operand:SI 0 "integer_register_operand" "")
+ (if_then_else:SI (match_operand 1 "" "")
+ (match_operand:SI 2 "gpr_or_int_operand" "")
+ (match_operand:SI 3 "gpr_or_int_operand" "")))]
+ "TARGET_COND_MOVE"
+ "
+{
+ if (!frv_emit_cond_move (operands[0], operands[1], operands[2], operands[3]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_insn "*movsicc_internal1_signed"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d")
+ (if_then_else:SI (match_operator:CC 1 "signed_relational_operator"
+ [(match_operand:CC 2 "icc_operand" "t,t,t")
+ (const_int 0)])
+ (match_operand:SI 3 "reg_or_0_operand" "0,dO,dO")
+ (match_operand:SI 4 "reg_or_0_operand" "dO,0,dO")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))]
+ ""
+ "#"
+ [(set_attr "length" "8,8,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movsicc_internal1_unsigned"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d")
+ (if_then_else:SI (match_operator:CC_UNS 1 "unsigned_relational_operator"
+ [(match_operand:CC_UNS 2 "icc_operand" "t,t,t")
+ (const_int 0)])
+ (match_operand:SI 3 "reg_or_0_operand" "0,dO,dO")
+ (match_operand:SI 4 "reg_or_0_operand" "dO,0,dO")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))]
+ ""
+ "#"
+ [(set_attr "length" "8,8,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movsicc_internal1_float"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d")
+ (if_then_else:SI (match_operator:CC_FP 1 "float_relational_operator"
+ [(match_operand:CC_FP 2 "fcc_operand" "u,u,u")
+ (const_int 0)])
+ (match_operand:SI 3 "reg_or_0_operand" "0,dO,dO")
+ (match_operand:SI 4 "reg_or_0_operand" "dO,0,dO")))
+ (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))]
+ "TARGET_HARD_FLOAT"
+ "#"
+ [(set_attr "length" "8,8,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movsicc_internal2_signed"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d,d,d")
+ (if_then_else:SI (match_operator:CC 1 "signed_relational_operator"
+ [(match_operand:CC 2 "icc_operand" "t,t,t,t,t")
+ (const_int 0)])
+ (match_operand:SI 3 "const_int_operand" "O,O,L,n,n")
+ (match_operand:SI 4 "const_int_operand" "L,n,O,O,n")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))]
+ "(INTVAL (operands[3]) == 0
+ || INTVAL (operands[4]) == 0
+ || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047)
+ && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))"
+ "#"
+ [(set_attr "length" "8,12,8,12,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movsicc_internal2_unsigned"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d,d,d")
+ (if_then_else:SI (match_operator:CC_UNS 1 "unsigned_relational_operator"
+ [(match_operand:CC_UNS 2 "icc_operand" "t,t,t,t,t")
+ (const_int 0)])
+ (match_operand:SI 3 "const_int_operand" "O,O,L,n,n")
+ (match_operand:SI 4 "const_int_operand" "L,n,O,O,n")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v"))]
+ "(INTVAL (operands[3]) == 0
+ || INTVAL (operands[4]) == 0
+ || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047)
+ && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))"
+ "#"
+ [(set_attr "length" "8,12,8,12,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movsicc_internal2_float"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d,d,d,d")
+ (if_then_else:SI (match_operator:CC_FP 1 "float_relational_operator"
+ [(match_operand:CC_FP 2 "fcc_operand" "u,u,u,u,u")
+ (const_int 0)])
+ (match_operand:SI 3 "const_int_operand" "O,O,L,n,n")
+ (match_operand:SI 4 "const_int_operand" "L,n,O,O,n")))
+ (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w,w,w"))]
+ "TARGET_HARD_FLOAT
+ && (INTVAL (operands[3]) == 0
+ || INTVAL (operands[4]) == 0
+ || (IN_RANGE_P (INTVAL (operands[3]), -2048, 2047)
+ && IN_RANGE_P (INTVAL (operands[4]) - INTVAL (operands[3]), -2048, 2047)))"
+ "#"
+ [(set_attr "length" "8,12,8,12,12")
+ (set_attr "type" "multi")])
+
+(define_split
+ [(set (match_operand:SI 0 "integer_register_operand" "")
+ (if_then_else:SI (match_operator 1 "relational_operator"
+ [(match_operand 2 "cc_operand" "")
+ (const_int 0)])
+ (match_operand:SI 3 "gpr_or_int_operand" "")
+ (match_operand:SI 4 "gpr_or_int_operand" "")))
+ (clobber (match_operand:CC_CCR 5 "cr_operand" ""))]
+ "reload_completed"
+ [(match_dup 6)]
+ "operands[6] = frv_split_cond_move (operands);")
+
+(define_expand "movsfcc"
+ [(set (match_operand:SF 0 "register_operand" "")
+ (if_then_else:SF (match_operand 1 "" "")
+ (match_operand:SF 2 "register_operand" "")
+ (match_operand:SF 3 "register_operand" "")))]
+ "TARGET_COND_MOVE"
+ "
+{
+ if (!frv_emit_cond_move (operands[0], operands[1], operands[2], operands[3]))
+ FAIL;
+
+ DONE;
+}")
+
+(define_insn "*movsfcc_has_fprs_signed"
+ [(set (match_operand:SF 0 "register_operand" "=f,f,f,?f,?f,?d")
+ (if_then_else:SF (match_operator:CC 1 "signed_relational_operator"
+ [(match_operand:CC 2 "icc_operand" "t,t,t,t,t,t")
+ (const_int 0)])
+ (match_operand:SF 3 "register_operand" "0,f,f,f,d,fd")
+ (match_operand:SF 4 "register_operand" "f,0,f,d,fd,fd")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v,v"))]
+ "TARGET_HAS_FPRS"
+ "#"
+ [(set_attr "length" "8,8,12,12,12,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movsfcc_has_fprs_unsigned"
+ [(set (match_operand:SF 0 "register_operand" "=f,f,f,?f,?f,?d")
+ (if_then_else:SF (match_operator:CC_UNS 1 "unsigned_relational_operator"
+ [(match_operand:CC_UNS 2 "icc_operand" "t,t,t,t,t,t")
+ (const_int 0)])
+ (match_operand:SF 3 "register_operand" "0,f,f,f,d,fd")
+ (match_operand:SF 4 "register_operand" "f,0,f,d,fd,fd")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v,v,v,v"))]
+ "TARGET_HAS_FPRS"
+ "#"
+ [(set_attr "length" "8,8,12,12,12,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movsfcc_hardfloat_float"
+ [(set (match_operand:SF 0 "register_operand" "=f,f,f,?f,?f,?d")
+ (if_then_else:SF (match_operator:CC_FP 1 "float_relational_operator"
+ [(match_operand:CC_FP 2 "fcc_operand" "u,u,u,u,u,u")
+ (const_int 0)])
+ (match_operand:SF 3 "register_operand" "0,f,f,f,d,fd")
+ (match_operand:SF 4 "register_operand" "f,0,f,d,fd,fd")))
+ (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w,w,w,w"))]
+ "TARGET_HARD_FLOAT"
+ "#"
+ [(set_attr "length" "8,8,12,12,12,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movsfcc_no_fprs_signed"
+ [(set (match_operand:SF 0 "integer_register_operand" "=d,d,d")
+ (if_then_else:SF (match_operator:CC 1 "signed_relational_operator"
+ [(match_operand:CC 2 "icc_operand" "t,t,t")
+ (const_int 0)])
+ (match_operand:SF 3 "integer_register_operand" "0,d,d")
+ (match_operand:SF 4 "integer_register_operand" "d,0,d")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))]
+ "! TARGET_HAS_FPRS"
+ "#"
+ [(set_attr "length" "8,8,12")
+ (set_attr "type" "multi")])
+
+(define_insn "*movsfcc_no_fprs_unsigned"
+ [(set (match_operand:SF 0 "integer_register_operand" "=d,d,d")
+ (if_then_else:SF (match_operator:CC_UNS 1 "unsigned_relational_operator"
+ [(match_operand:CC_UNS 2 "icc_operand" "t,t,t")
+ (const_int 0)])
+ (match_operand:SF 3 "integer_register_operand" "0,d,d")
+ (match_operand:SF 4 "integer_register_operand" "d,0,d")))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))]
+ "! TARGET_HAS_FPRS"
+ "#"
+ [(set_attr "length" "8,8,12")
+ (set_attr "type" "multi")])
+
+(define_split
+ [(set (match_operand:SF 0 "register_operand" "")
+ (if_then_else:SF (match_operator 1 "relational_operator"
+ [(match_operand 2 "cc_operand" "")
+ (const_int 0)])
+ (match_operand:SF 3 "register_operand" "")
+ (match_operand:SF 4 "register_operand" "")))
+ (clobber (match_operand:CC_CCR 5 "cr_operand" ""))]
+ "reload_completed"
+ [(match_dup 6)]
+ "operands[6] = frv_split_cond_move (operands);")
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Minimum, maximum, and integer absolute value
+;; ::
+;; ::::::::::::::::::::
+
+;; These 'instructions' are provided to give the compiler a slightly better
+;; nudge at register allocation, then it would if it constructed the
+;; instructions from basic building blocks (since it indicates it prefers one
+;; of the operands to be the same as the destination. It also helps the
+;; earlier passes of the compiler, by not breaking things into small basic
+;; blocks.
+
+(define_expand "abssi2"
+ [(parallel [(set (match_operand:SI 0 "integer_register_operand" "")
+ (abs:SI (match_operand:SI 1 "integer_register_operand" "")))
+ (clobber (match_dup 2))
+ (clobber (match_dup 3))])]
+ "TARGET_COND_MOVE"
+ "
+{
+ operands[2] = gen_reg_rtx (CCmode);
+ operands[3] = gen_reg_rtx (CC_CCRmode);
+}")
+
+(define_insn_and_split "*abssi2_internal"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d")
+ (abs:SI (match_operand:SI 1 "integer_register_operand" "0,d")))
+ (clobber (match_operand:CC 2 "icc_operand" "=t,t"))
+ (clobber (match_operand:CC_CCR 3 "icr_operand" "=v,v"))]
+ "TARGET_COND_MOVE"
+ "#"
+ "reload_completed"
+ [(match_dup 4)]
+ "operands[4] = frv_split_abs (operands);"
+ [(set_attr "length" "12,16")
+ (set_attr "type" "multi")])
+
+(define_expand "sminsi3"
+ [(parallel [(set (match_operand:SI 0 "integer_register_operand" "")
+ (smin:SI (match_operand:SI 1 "integer_register_operand" "")
+ (match_operand:SI 2 "gpr_or_int10_operand" "")))
+ (clobber (match_dup 3))
+ (clobber (match_dup 4))])]
+ "TARGET_COND_MOVE"
+ "
+{
+ operands[3] = gen_reg_rtx (CCmode);
+ operands[4] = gen_reg_rtx (CC_CCRmode);
+}")
+
+(define_expand "smaxsi3"
+ [(parallel [(set (match_operand:SI 0 "integer_register_operand" "")
+ (smax:SI (match_operand:SI 1 "integer_register_operand" "")
+ (match_operand:SI 2 "gpr_or_int10_operand" "")))
+ (clobber (match_dup 3))
+ (clobber (match_dup 4))])]
+ "TARGET_COND_MOVE"
+ "
+{
+ operands[3] = gen_reg_rtx (CCmode);
+ operands[4] = gen_reg_rtx (CC_CCRmode);
+}")
+
+(define_insn_and_split "*minmax_si_signed"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d,&d")
+ (match_operator:SI 1 "minmax_operator"
+ [(match_operand:SI 2 "integer_register_operand" "%0,dO,d")
+ (match_operand:SI 3 "gpr_or_int10_operand" "dO,0,dJ")]))
+ (clobber (match_operand:CC 4 "icc_operand" "=t,t,t"))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))]
+ "TARGET_COND_MOVE"
+ "#"
+ "reload_completed"
+ [(match_dup 6)]
+ "operands[6] = frv_split_minmax (operands);"
+ [(set_attr "length" "12,12,16")
+ (set_attr "type" "multi")])
+
+(define_expand "uminsi3"
+ [(parallel [(set (match_operand:SI 0 "integer_register_operand" "")
+ (umin:SI (match_operand:SI 1 "integer_register_operand" "")
+ (match_operand:SI 2 "gpr_or_int10_operand" "")))
+ (clobber (match_dup 3))
+ (clobber (match_dup 4))])]
+ "TARGET_COND_MOVE"
+ "
+{
+ operands[3] = gen_reg_rtx (CC_UNSmode);
+ operands[4] = gen_reg_rtx (CC_CCRmode);
+}")
+
+(define_expand "umaxsi3"
+ [(parallel [(set (match_operand:SI 0 "integer_register_operand" "")
+ (umax:SI (match_operand:SI 1 "integer_register_operand" "")
+ (match_operand:SI 2 "gpr_or_int10_operand" "")))
+ (clobber (match_dup 3))
+ (clobber (match_dup 4))])]
+ "TARGET_COND_MOVE"
+ "
+{
+ operands[3] = gen_reg_rtx (CC_UNSmode);
+ operands[4] = gen_reg_rtx (CC_CCRmode);
+}")
+
+(define_insn_and_split "*minmax_si_unsigned"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d,d,&d")
+ (match_operator:SI 1 "minmax_operator"
+ [(match_operand:SI 2 "integer_register_operand" "%0,dO,d")
+ (match_operand:SI 3 "gpr_or_int10_operand" "dO,0,dJ")]))
+ (clobber (match_operand:CC_UNS 4 "icc_operand" "=t,t,t"))
+ (clobber (match_operand:CC_CCR 5 "icr_operand" "=v,v,v"))]
+ "TARGET_COND_MOVE"
+ "#"
+ "reload_completed"
+ [(match_dup 6)]
+ "operands[6] = frv_split_minmax (operands);"
+ [(set_attr "length" "12,12,16")
+ (set_attr "type" "multi")])
+
+(define_expand "sminsf3"
+ [(parallel [(set (match_operand:SF 0 "fpr_operand" "")
+ (smin:SF (match_operand:SF 1 "fpr_operand" "")
+ (match_operand:SF 2 "fpr_operand" "")))
+ (clobber (match_dup 3))
+ (clobber (match_dup 4))])]
+ "TARGET_COND_MOVE && TARGET_HARD_FLOAT"
+ "
+{
+ operands[3] = gen_reg_rtx (CC_FPmode);
+ operands[4] = gen_reg_rtx (CC_CCRmode);
+}")
+
+(define_expand "smaxsf3"
+ [(parallel [(set (match_operand:SF 0 "fpr_operand" "")
+ (smax:SF (match_operand:SF 1 "fpr_operand" "")
+ (match_operand:SF 2 "fpr_operand" "")))
+ (clobber (match_dup 3))
+ (clobber (match_dup 4))])]
+ "TARGET_COND_MOVE && TARGET_HARD_FLOAT"
+ "
+{
+ operands[3] = gen_reg_rtx (CC_FPmode);
+ operands[4] = gen_reg_rtx (CC_CCRmode);
+}")
+
+(define_insn_and_split "*minmax_sf"
+ [(set (match_operand:SF 0 "fpr_operand" "=f,f,f")
+ (match_operator:SF 1 "minmax_operator"
+ [(match_operand:SF 2 "fpr_operand" "%0,f,f")
+ (match_operand:SF 3 "fpr_operand" "f,0,f")]))
+ (clobber (match_operand:CC_FP 4 "fcc_operand" "=u,u,u"))
+ (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))]
+ "TARGET_COND_MOVE && TARGET_HARD_FLOAT"
+ "#"
+ "reload_completed"
+ [(match_dup 6)]
+ "operands[6] = frv_split_minmax (operands);"
+ [(set_attr "length" "12,12,16")
+ (set_attr "type" "multi")])
+
+(define_expand "smindf3"
+ [(parallel [(set (match_operand:DF 0 "fpr_operand" "")
+ (smin:DF (match_operand:DF 1 "fpr_operand" "")
+ (match_operand:DF 2 "fpr_operand" "")))
+ (clobber (match_dup 3))
+ (clobber (match_dup 4))])]
+ "TARGET_COND_MOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ "
+{
+ operands[3] = gen_reg_rtx (CC_FPmode);
+ operands[4] = gen_reg_rtx (CC_CCRmode);
+}")
+
+(define_expand "smaxdf3"
+ [(parallel [(set (match_operand:DF 0 "fpr_operand" "")
+ (smax:DF (match_operand:DF 1 "fpr_operand" "")
+ (match_operand:DF 2 "fpr_operand" "")))
+ (clobber (match_dup 3))
+ (clobber (match_dup 4))])]
+ "TARGET_COND_MOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ "
+{
+ operands[3] = gen_reg_rtx (CC_FPmode);
+ operands[4] = gen_reg_rtx (CC_CCRmode);
+}")
+
+(define_insn_and_split "*minmax_df"
+ [(set (match_operand:DF 0 "fpr_operand" "=f,f,f")
+ (match_operator:DF 1 "minmax_operator"
+ [(match_operand:DF 2 "fpr_operand" "%0,f,f")
+ (match_operand:DF 3 "fpr_operand" "f,0,f")]))
+ (clobber (match_operand:CC_FP 4 "fcc_operand" "=u,u,u"))
+ (clobber (match_operand:CC_CCR 5 "fcr_operand" "=w,w,w"))]
+ "TARGET_COND_MOVE && TARGET_HARD_FLOAT && TARGET_DOUBLE"
+ "#"
+ "reload_completed"
+ [(match_dup 6)]
+ "operands[6] = frv_split_minmax (operands);"
+ [(set_attr "length" "12,12,16")
+ (set_attr "type" "multi")])
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Call and branch instructions
+;; ::
+;; ::::::::::::::::::::
+
+;; Subroutine call instruction returning no value. Operand 0 is the function
+;; to call; operand 1 is the number of bytes of arguments pushed (in mode
+;; `SImode', except it is normally a `const_int'); operand 2 is the number of
+;; registers used as operands.
+
+;; On most machines, operand 2 is not actually stored into the RTL pattern. It
+;; is supplied for the sake of some RISC machines which need to put this
+;; information into the assembler code; they can put it in the RTL instead of
+;; operand 1.
+
+(define_expand "call"
+ [(use (match_operand:QI 0 "" ""))
+ (use (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (use (match_operand 3 "" ""))]
+ ""
+ "
+{
+ rtx lr = gen_rtx_REG (Pmode, LR_REGNO);
+ rtx addr;
+
+ if (GET_CODE (operands[0]) != MEM)
+ abort ();
+
+ addr = XEXP (operands[0], 0);
+ if (! call_operand (addr, Pmode))
+ addr = force_reg (Pmode, addr);
+
+ if (! operands[2])
+ operands[2] = const0_rtx;
+
+ emit_call_insn (gen_call_internal (addr, operands[1], operands[2], lr));
+ DONE;
+}")
+
+(define_insn "call_internal"
+ [(call (mem:QI (match_operand:SI 0 "call_operand" "S,dNOP"))
+ (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (clobber (match_operand:SI 3 "lr_operand" "=l,l"))]
+ ""
+ "@
+ call %0
+ call%i0l %M0"
+ [(set_attr "length" "4")
+ (set_attr "type" "call,jumpl")])
+
+;; Subroutine call instruction returning a value. Operand 0 is the hard
+;; register in which the value is returned. There are three more operands, the
+;; same as the three operands of the `call' instruction (but with numbers
+;; increased by one).
+
+;; Subroutines that return `BLKmode' objects use the `call' insn.
+
+(define_expand "call_value"
+ [(use (match_operand 0 "" ""))
+ (use (match_operand:QI 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (use (match_operand 3 "" ""))
+ (use (match_operand 4 "" ""))]
+ ""
+ "
+{
+ rtx lr = gen_rtx_REG (Pmode, LR_REGNO);
+ rtx addr;
+
+ if (GET_CODE (operands[1]) != MEM)
+ abort ();
+
+ addr = XEXP (operands[1], 0);
+ if (! call_operand (addr, Pmode))
+ addr = force_reg (Pmode, addr);
+
+ if (! operands[3])
+ operands[3] = const0_rtx;
+
+ emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2],
+ operands[3], lr));
+ DONE;
+}")
+
+(define_insn "call_value_internal"
+ [(set (match_operand 0 "register_operand" "=d,d")
+ (call (mem:QI (match_operand:SI 1 "call_operand" "S,dNOP"))
+ (match_operand 2 "" "")))
+ (use (match_operand 3 "" ""))
+ (clobber (match_operand:SI 4 "lr_operand" "=l,l"))]
+ ""
+ "@
+ call %1
+ call%i1l %M1"
+ [(set_attr "length" "4")
+ (set_attr "type" "call,jumpl")])
+
+;; return instruction generated instead of jmp to epilog
+(define_expand "return"
+ [(parallel [(return)
+ (use (match_dup 0))
+ (use (const_int 1))])]
+ "direct_return_p ()"
+ "
+{
+ operands[0] = gen_rtx_REG (Pmode, LR_REGNO);
+}")
+
+;; return instruction generated by the epilogue
+(define_expand "epilogue_return"
+ [(parallel [(return)
+ (use (match_operand:SI 0 "register_operand" ""))
+ (use (const_int 0))])]
+ ""
+ "")
+
+(define_insn "*return_internal"
+ [(return)
+ (use (match_operand:SI 0 "register_operand" "l,d"))
+ (use (match_operand:SI 1 "immediate_operand" "n,n"))]
+ ""
+ "@
+ ret
+ jmpl @(%0,%.)"
+ [(set_attr "length" "4")
+ (set_attr "type" "jump,jumpl")])
+
+;; A version of addsi3 for deallocating stack space at the end of the
+;; epilogue. The addition is done in parallel with an (unspec_volatile),
+;; which represents the clobbering of the deallocated space.
+(define_insn "stack_adjust"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "general_operand" "dNOP")))
+ (unspec_volatile [(const_int 0)] UNSPEC_STACK_ADJUST)]
+ ""
+ "add%I2 %1,%2,%0"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+;; Normal unconditional jump
+
+;; Use the "call" instruction for long branches, but prefer to use "bra" for
+;; short ones since it does not force us to save the link register.
+
+;; This define_insn uses the branch-shortening code to decide which
+;; instruction it emits. Since the main branch-shortening interface is
+;; through get_attr_length(), the two alternatives must be given different
+;; lengths. Here we pretend that the far jump is 8 rather than 4 bytes
+;; long, though both alternatives are really the same size.
+(define_insn "jump"
+ [(set (pc) (label_ref (match_operand 0 "" "")))]
+ ""
+ "*
+{
+ if (get_attr_length (insn) == 4)
+ return \"bra %l0\";
+ else
+ return \"call %l0\";
+}"
+ [(set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 0) (pc)) (const_int -32768))
+ (le (minus (match_dup 0) (pc)) (const_int 32764)))
+ (const_int 4)
+ (const_int 8)))
+ (set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "4")
+ (const_string "no")
+ (const_string "yes")))
+ (set (attr "type")
+ (if_then_else
+ (eq_attr "length" "4")
+ (const_string "jump")
+ (const_string "call")))])
+
+;; Indirect jump through a register
+(define_insn "indirect_jump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "d,l"))]
+ ""
+ "@
+ jmpl @(%0,%.)
+ bralr"
+ [(set_attr "length" "4")
+ (set_attr "type" "jumpl,branch")])
+
+;; Instruction to jump to a variable address. This is a low-level capability
+;; which can be used to implement a dispatch table when there is no `casesi'
+;; pattern. Either the 'casesi' pattern or the 'tablejump' pattern, or both,
+;; MUST be present in this file.
+
+;; This pattern requires two operands: the address or offset, and a label which
+;; should immediately precede the jump table. If the macro
+;; `CASE_VECTOR_PC_RELATIVE' is defined then the first operand is an offset
+;; which counts from the address of the table; otherwise, it is an absolute
+;; address to jump to. In either case, the first operand has mode `Pmode'.
+
+;; The `tablejump' insn is always the last insn before the jump 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.
+
+(define_expand "tablejump"
+ [(parallel [(set (pc) (match_operand:SI 0 "address_operand" "p"))
+ (use (label_ref (match_operand 1 "" "")))])]
+ "!flag_pic"
+ "")
+
+(define_insn "tablejump_insn"
+ [(set (pc) (match_operand:SI 0 "address_operand" "p"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "jmp%I0l %M0"
+ [(set_attr "length" "4")
+ (set_attr "type" "jumpl")])
+
+;; Implement switch statements when generating PIC code. Switches are
+;; implemented by `tablejump' when not using -fpic.
+
+;; Emit code here to do the range checking and make the index zero based.
+;; operand 0 is the index
+;; operand 1 is the lower bound
+;; operand 2 is the range of indices (highest - lowest + 1)
+;; operand 3 is the label that precedes the table itself
+;; operand 4 is the fall through label
+
+(define_expand "casesi"
+ [(use (match_operand:SI 0 "integer_register_operand" ""))
+ (use (match_operand:SI 1 "const_int_operand" ""))
+ (use (match_operand:SI 2 "const_int_operand" ""))
+ (use (match_operand 3 "" ""))
+ (use (match_operand 4 "" ""))]
+ "flag_pic"
+ "
+{
+ rtx indx;
+ rtx scale;
+ rtx low = operands[1];
+ rtx range = operands[2];
+ rtx table = operands[3];
+ rtx treg;
+ rtx fail = operands[4];
+ rtx mem;
+ rtx reg2;
+ rtx reg3;
+
+ if (GET_CODE (operands[1]) != CONST_INT)
+ abort ();
+
+ if (GET_CODE (operands[2]) != CONST_INT)
+ abort ();
+
+ /* If we can't generate an immediate instruction, promote to register */
+ if (! IN_RANGE_P (INTVAL (range), -2048, 2047))
+ range = force_reg (SImode, range);
+
+ /* If low bound is 0, we don't have to subtract it. */
+ if (INTVAL (operands[1]) == 0)
+ indx = operands[0];
+ else
+ {
+ indx = gen_reg_rtx (SImode);
+ if (IN_RANGE_P (INTVAL (low), -2047, 2048))
+ emit_insn (gen_addsi3 (indx, operands[0], GEN_INT (- INTVAL (low))));
+ else
+ emit_insn (gen_subsi3 (indx, operands[0], force_reg (SImode, low)));
+ }
+
+ /* Do an unsigned comparison (in the proper mode) between the index
+ expression and the value which represents the length of the range.
+ Since we just finished subtracting the lower bound of the range
+ from the index expression, this comparison allows us to simultaneously
+ check that the original index expression value is both greater than
+ or equal to the minimum value of the range and less than or equal to
+ the maximum value of the range. */
+
+ emit_cmp_and_jump_insns (indx, range, GTU, NULL_RTX, SImode, 1, fail);
+
+ /* Move the table address to a register */
+ treg = gen_reg_rtx (Pmode);
+ emit_insn (gen_movsi (treg, gen_rtx_LABEL_REF (VOIDmode, table)));
+
+ /* scale index-low by wordsize */
+ scale = gen_reg_rtx (SImode);
+ emit_insn (gen_ashlsi3 (scale, indx, GEN_INT (2)));
+
+ /* Load the address, add the start of the table back in,
+ and jump to it. */
+ mem = gen_rtx_MEM (SImode, gen_rtx_PLUS (Pmode, scale, treg));
+ reg2 = gen_reg_rtx (SImode);
+ reg3 = gen_reg_rtx (SImode);
+ emit_insn (gen_movsi (reg2, mem));
+ emit_insn (gen_addsi3 (reg3, reg2, treg));
+ emit_jump_insn (gen_tablejump_insn (reg3, table));
+ DONE;
+}")
+
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Prologue and Epilogue instructions
+;; ::
+;; ::::::::::::::::::::
+
+;; Called after register allocation to add any instructions needed for the
+;; prologue. Using a prologue insn is favored compared to putting all of the
+;; instructions in the FUNCTION_PROLOGUE macro, since it allows the scheduler
+;; to intermix instructions with the saves of the caller saved registers. In
+;; some cases, it might be necessary to emit a barrier instruction as the last
+;; insn to prevent such scheduling.
+(define_expand "prologue"
+ [(const_int 1)]
+ ""
+ "
+{
+ frv_expand_prologue ();
+ DONE;
+}")
+
+;; Called after register allocation to add any instructions needed for the
+;; epilogue. Using an epilogue insn is favored compared to putting all of the
+;; instructions in the FUNCTION_EPILOGUE macro, since it allows the scheduler
+;; to intermix instructions with the restires of the caller saved registers.
+;; In some cases, it might be necessary to emit a barrier instruction as the
+;; first insn to prevent such scheduling.
+(define_expand "epilogue"
+ [(const_int 2)]
+ ""
+ "
+{
+ frv_expand_epilogue (FALSE);
+ DONE;
+}")
+
+;; This pattern, if defined, emits RTL for exit from a function without the final
+;; branch back to the calling function. This pattern will be emitted before any
+;; sibling call (aka tail call) sites.
+;;
+;; The sibcall_epilogue pattern must not clobber any arguments used for
+;; parameter passing or any stack slots for arguments passed to the current
+;; function.
+(define_expand "sibcall_epilogue"
+ [(const_int 3)]
+ ""
+ "
+{
+ frv_expand_epilogue (TRUE);
+ DONE;
+}")
+
+;; Set up the pic register to hold the address of the pic table
+(define_insn "pic_prologue"
+ [(set (match_operand:SI 0 "integer_register_operand" "=d")
+ (unspec_volatile:SI [(const_int 0)] UNSPEC_PIC_PROLOGUE))
+ (clobber (match_operand:SI 1 "lr_operand" "=l"))
+ (clobber (match_operand:SI 2 "integer_register_operand" "=d"))]
+ ""
+ "*
+{
+ static int frv_pic_labelno = 0;
+
+ operands[3] = GEN_INT (frv_pic_labelno++);
+ return \"call %P3\\n%P3:\;movsg %1, %0\;sethi #gprelhi(%P3), %2\;setlo #gprello(%P3), %2\;sub %0,%2,%0\";
+}"
+ [(set_attr "length" "16")
+ (set_attr "type" "multi")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Miscellaneous instructions
+;; ::
+;; ::::::::::::::::::::
+
+;; No operation, needed in case the user uses -g but not -O.
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop"
+ [(set_attr "length" "4")
+ (set_attr "type" "int")])
+
+;; Pseudo instruction that prevents the scheduler from moving code above this
+;; point. Note, type unknown is used to make sure the VLIW instructions are
+;; not continued past this point.
+(define_insn "blockage"
+ [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
+ ""
+ "# blockage"
+ [(set_attr "length" "0")
+ (set_attr "type" "unknown")])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Media instructions
+;; ::
+;; ::::::::::::::::::::
+
+;; Unimplemented instructions:
+;; - MCMPSH, MCMPUH
+
+(define_constants
+ [(UNSPEC_MLOGIC 100)
+ (UNSPEC_MNOT 101)
+ (UNSPEC_MAVEH 102)
+ (UNSPEC_MSATH 103)
+ (UNSPEC_MADDH 104)
+ (UNSPEC_MQADDH 105)
+ (UNSPEC_MPACKH 106)
+ (UNSPEC_MUNPACKH 107)
+ (UNSPEC_MDPACKH 108)
+ (UNSPEC_MBTOH 109)
+ (UNSPEC_MHTOB 110)
+ (UNSPEC_MROT 111)
+ (UNSPEC_MSHIFT 112)
+ (UNSPEC_MEXPDHW 113)
+ (UNSPEC_MEXPDHD 114)
+ (UNSPEC_MWCUT 115)
+ (UNSPEC_MMULH 116)
+ (UNSPEC_MMULXH 117)
+ (UNSPEC_MMACH 118)
+ (UNSPEC_MMRDH 119)
+ (UNSPEC_MQMULH 120)
+ (UNSPEC_MQMULXH 121)
+ (UNSPEC_MQMACH 122)
+ (UNSPEC_MCPX 123)
+ (UNSPEC_MQCPX 124)
+ (UNSPEC_MCUT 125)
+ (UNSPEC_MRDACC 126)
+ (UNSPEC_MRDACCG 127)
+ (UNSPEC_MWTACC 128)
+ (UNSPEC_MWTACCG 129)
+ (UNSPEC_MTRAP 130)
+ (UNSPEC_MCLRACC 131)
+ (UNSPEC_MCLRACCA 132)
+ (UNSPEC_MCOP1 133)
+ (UNSPEC_MCOP2 134)
+ (UNSPEC_MDUNPACKH 135)
+ (UNSPEC_MDUNPACKH_INTERNAL 136)
+ (UNSPEC_MBTOHE 137)
+ (UNSPEC_MBTOHE_INTERNAL 138)
+ (UNSPEC_MBTOHE 137)
+ (UNSPEC_MBTOHE_INTERNAL 138)
+ (UNSPEC_MQMACH2 139)
+ (UNSPEC_MADDACC 140)
+ (UNSPEC_MDADDACC 141)
+ (UNSPEC_MABSHS 142)
+ (UNSPEC_MDROTLI 143)
+ (UNSPEC_MCPLHI 144)
+ (UNSPEC_MCPLI 145)
+ (UNSPEC_MDCUTSSI 146)
+ (UNSPEC_MQSATHS 147)
+ (UNSPEC_MHSETLOS 148)
+ (UNSPEC_MHSETLOH 149)
+ (UNSPEC_MHSETHIS 150)
+ (UNSPEC_MHSETHIH 151)
+ (UNSPEC_MHDSETS 152)
+ (UNSPEC_MHDSETH 153)
+])
+
+;; Logic operations: type "mlogic"
+
+(define_expand "mand"
+ [(set (match_operand:SI 0 "fpr_operand" "")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "")
+ (match_operand:SI 2 "fpr_operand" "")
+ (match_dup 3)]
+ UNSPEC_MLOGIC))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MAND);")
+
+(define_expand "mor"
+ [(set (match_operand:SI 0 "fpr_operand" "")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "")
+ (match_operand:SI 2 "fpr_operand" "")
+ (match_dup 3)]
+ UNSPEC_MLOGIC))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MOR);")
+
+(define_expand "mxor"
+ [(set (match_operand:SI 0 "fpr_operand" "")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "")
+ (match_operand:SI 2 "fpr_operand" "")
+ (match_dup 3)]
+ UNSPEC_MLOGIC))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MXOR);")
+
+(define_insn "*mlogic"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_operand:SI 3 "const_int_operand" "n")]
+ UNSPEC_MLOGIC))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[3]))
+ {
+ default: break;
+ case FRV_BUILTIN_MAND: return \"mand %1, %2, %0\";
+ case FRV_BUILTIN_MOR: return \"mor %1, %2, %0\";
+ case FRV_BUILTIN_MXOR: return \"mxor %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mlogic\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mlogic")])
+
+(define_insn "*cond_exec_mlogic"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SI 2 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 3 "fpr_operand" "f")
+ (match_operand:SI 4 "fpr_operand" "f")
+ (match_operand:SI 5 "const_int_operand" "n")]
+ UNSPEC_MLOGIC)))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[5]))
+ {
+ default: break;
+ case FRV_BUILTIN_MAND: return \"cmand %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MOR: return \"cmor %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MXOR: return \"cmxor %3, %4, %2, %1, %e0\";
+ }
+
+ fatal_insn (\"Bad media insn, cond_exec_mlogic\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mlogic")])
+
+;; Logical not: type "mlogic"
+
+(define_insn "mnot"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")] UNSPEC_MNOT))]
+ "TARGET_MEDIA"
+ "mnot %1, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mlogic")])
+
+(define_insn "*cond_exec_mnot"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SI 2 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 3 "fpr_operand" "f")] UNSPEC_MNOT)))]
+ "TARGET_MEDIA"
+ "cmnot %3, %2, %1, %e0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mlogic")])
+
+;; Dual average (halfword): type "maveh"
+
+(define_insn "maveh"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")]
+ UNSPEC_MAVEH))]
+ "TARGET_MEDIA"
+ "maveh %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "maveh")])
+
+;; Dual saturation (halfword): type "msath"
+
+(define_expand "msaths"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_dup 3)]
+ UNSPEC_MSATH))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MSATHS);")
+
+(define_expand "msathu"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_dup 3)]
+ UNSPEC_MSATH))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MSATHU);")
+
+(define_insn "*msath"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_operand:SI 3 "const_int_operand" "n")]
+ UNSPEC_MSATH))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[3]))
+ {
+ default: break;
+ case FRV_BUILTIN_MSATHS: return \"msaths %1, %2, %0\";
+ case FRV_BUILTIN_MSATHU: return \"msathu %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, msath\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "msath")])
+
+;; Dual addition/subtraction with saturation (halfword): type "maddh"
+
+(define_expand "maddhss"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_dup 3)]
+ UNSPEC_MADDH))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MADDHSS);")
+
+(define_expand "maddhus"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_dup 3)]
+ UNSPEC_MADDH))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MADDHUS);")
+
+(define_expand "msubhss"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_dup 3)]
+ UNSPEC_MADDH))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MSUBHSS);")
+
+(define_expand "msubhus"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_dup 3)]
+ UNSPEC_MADDH))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MSUBHUS);")
+
+(define_insn "*maddh"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_operand:SI 3 "const_int_operand" "n")]
+ UNSPEC_MADDH))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[3]))
+ {
+ default: break;
+ case FRV_BUILTIN_MADDHSS: return \"maddhss %1, %2, %0\";
+ case FRV_BUILTIN_MADDHUS: return \"maddhus %1, %2, %0\";
+ case FRV_BUILTIN_MSUBHSS: return \"msubhss %1, %2, %0\";
+ case FRV_BUILTIN_MSUBHUS: return \"msubhus %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, maddh\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "maddh")])
+
+(define_insn "*cond_exec_maddh"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SI 2 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 3 "fpr_operand" "f")
+ (match_operand:SI 4 "fpr_operand" "f")
+ (match_operand:SI 5 "const_int_operand" "n")]
+ UNSPEC_MADDH)))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[5]))
+ {
+ default: break;
+ case FRV_BUILTIN_MADDHSS: return \"cmaddhss %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MADDHUS: return \"cmaddhus %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MSUBHSS: return \"cmsubhss %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MSUBHUS: return \"cmsubhus %3, %4, %2, %1, %e0\";
+ }
+
+ fatal_insn (\"Bad media insn, cond_exec_maddh\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "maddh")])
+
+;; Quad addition/subtraction with saturation (halfword): type "mqaddh"
+
+(define_expand "mqaddhss"
+ [(set (match_operand:DI 0 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_dup 3)]
+ UNSPEC_MQADDH))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MQADDHSS);")
+
+(define_expand "mqaddhus"
+ [(set (match_operand:DI 0 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_dup 3)]
+ UNSPEC_MQADDH))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MQADDHUS);")
+
+(define_expand "mqsubhss"
+ [(set (match_operand:DI 0 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_dup 3)]
+ UNSPEC_MQADDH))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MQSUBHSS);")
+
+(define_expand "mqsubhus"
+ [(set (match_operand:DI 0 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_dup 3)]
+ UNSPEC_MQADDH))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MQSUBHUS);")
+
+(define_insn "*mqaddh"
+ [(set (match_operand:DI 0 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_operand:SI 3 "const_int_operand" "n")]
+ UNSPEC_MQADDH))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[3]))
+ {
+ default: break;
+ case FRV_BUILTIN_MQADDHSS: return \"mqaddhss %1, %2, %0\";
+ case FRV_BUILTIN_MQADDHUS: return \"mqaddhus %1, %2, %0\";
+ case FRV_BUILTIN_MQSUBHSS: return \"mqsubhss %1, %2, %0\";
+ case FRV_BUILTIN_MQSUBHUS: return \"mqsubhus %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mqaddh\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mqaddh")])
+
+(define_insn "*cond_exec_mqaddh"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:DI 2 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:DI 3 "even_fpr_operand" "h")
+ (match_operand:DI 4 "even_fpr_operand" "h")
+ (match_operand:SI 5 "const_int_operand" "n")]
+ UNSPEC_MQADDH)))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[5]))
+ {
+ default: break;
+ case FRV_BUILTIN_MQADDHSS: return \"cmqaddhss %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MQADDHUS: return \"cmqaddhus %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MQSUBHSS: return \"cmqsubhss %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MQSUBHUS: return \"cmqsubhus %3, %4, %2, %1, %e0\";
+ }
+
+ fatal_insn (\"Bad media insn, cond_exec_mqaddh\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mqaddh")])
+
+;; Pack halfword: type "mpackh"
+
+(define_insn "mpackh"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:HI 1 "fpr_operand" "f")
+ (match_operand:HI 2 "fpr_operand" "f")]
+ UNSPEC_MPACKH))]
+ "TARGET_MEDIA"
+ "mpackh %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mpackh")])
+
+;; Unpack halfword: type "mpackh"
+
+(define_insn "munpackh"
+ [(set (match_operand:DI 0 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:SI 1 "fpr_operand" "f")]
+ UNSPEC_MUNPACKH))]
+ "TARGET_MEDIA"
+ "munpackh %1, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "munpackh")])
+
+;; Dual pack halfword: type "mdpackh"
+
+(define_insn "mdpackh"
+ [(set (match_operand:DI 0 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")]
+ UNSPEC_MDPACKH))]
+ "TARGET_MEDIA"
+ "mdpackh %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mdpackh")])
+
+;; Byte-halfword conversion: type "mbhconv"
+
+(define_insn "mbtoh"
+ [(set (match_operand:DI 0 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:SI 1 "fpr_operand" "f")]
+ UNSPEC_MBTOH))]
+ "TARGET_MEDIA"
+ "mbtoh %1, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mbhconv")])
+
+(define_insn "*cond_exec_mbtoh"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:DI 2 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:SI 3 "fpr_operand" "f")]
+ UNSPEC_MBTOH)))]
+ "TARGET_MEDIA"
+ "cmbtoh %3, %2, %1, %e0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mbhconv")])
+
+(define_insn "mhtob"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:DI 1 "even_fpr_operand" "h")]
+ UNSPEC_MHTOB))]
+ "TARGET_MEDIA"
+ "mhtob %1, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mbhconv")])
+
+(define_insn "*cond_exec_mhtob"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SI 2 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:DI 3 "even_fpr_operand" "h")]
+ UNSPEC_MHTOB)))]
+ "TARGET_MEDIA"
+ "cmhtob %3, %2, %1, %e0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mbhconv")])
+
+;; Rotate: type "mrot"
+
+(define_expand "mrotli"
+ [(set (match_operand:SI 0 "fpr_operand" "")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "")
+ (match_operand:SI 2 "uint5_operand" "")
+ (match_dup 3)]
+ UNSPEC_MROT))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MROTLI);")
+
+(define_expand "mrotri"
+ [(set (match_operand:SI 0 "fpr_operand" "")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "")
+ (match_operand:SI 2 "uint5_operand" "")
+ (match_dup 3)]
+ UNSPEC_MROT))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MROTRI);")
+
+(define_insn "*mrot"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "uint5_operand" "I")
+ (match_operand:SI 3 "const_int_operand" "n")]
+ UNSPEC_MROT))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[3]))
+ {
+ default: break;
+ case FRV_BUILTIN_MROTLI: return \"mrotli %1, %2, %0\";
+ case FRV_BUILTIN_MROTRI: return \"mrotri %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mrot\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mrot")])
+
+;; Dual shift halfword: type "msh"
+
+(define_expand "msllhi"
+ [(set (match_operand:SI 0 "fpr_operand" "")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "")
+ (match_operand:SI 2 "uint4_operand" "")
+ (match_dup 3)]
+ UNSPEC_MSHIFT))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MSLLHI);")
+
+(define_expand "msrlhi"
+ [(set (match_operand:SI 0 "fpr_operand" "")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "")
+ (match_operand:SI 2 "uint4_operand" "")
+ (match_dup 3)]
+ UNSPEC_MSHIFT))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MSRLHI);")
+
+(define_expand "msrahi"
+ [(set (match_operand:SI 0 "fpr_operand" "")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "")
+ (match_operand:SI 2 "uint4_operand" "")
+ (match_dup 3)]
+ UNSPEC_MSHIFT))]
+ "TARGET_MEDIA"
+ "operands[3] = GEN_INT (FRV_BUILTIN_MSRAHI);")
+
+(define_insn "*mshift"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "uint4_operand" "I")
+ (match_operand:SI 3 "const_int_operand" "n")]
+ UNSPEC_MSHIFT))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[3]))
+ {
+ default: break;
+ case FRV_BUILTIN_MSLLHI: return \"msllhi %1, %2, %0\";
+ case FRV_BUILTIN_MSRLHI: return \"msrlhi %1, %2, %0\";
+ case FRV_BUILTIN_MSRAHI: return \"msrahi %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mshift\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mshift")])
+
+;; Expand halfword to word: type "mexpdhw"
+
+(define_insn "mexpdhw"
+ [(set (match_operand:SI 0 "even_fpr_operand" "=h")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "uint1_operand" "I")]
+ UNSPEC_MEXPDHW))]
+ "TARGET_MEDIA"
+ "mexpdhw %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mexpdhw")])
+
+(define_insn "*cond_exec_mexpdhw"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:SI 2 "even_fpr_operand" "=h")
+ (unspec:SI [(match_operand:SI 3 "fpr_operand" "f")
+ (match_operand:SI 4 "uint1_operand" "I")]
+ UNSPEC_MEXPDHW)))]
+ "TARGET_MEDIA"
+ "cmexpdhw %3, %4, %2, %1, %e0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mexpdhw")])
+
+;; Expand halfword to double: type "mexpdhd"
+
+(define_insn "mexpdhd"
+ [(set (match_operand:DI 0 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "uint1_operand" "I")]
+ UNSPEC_MEXPDHD))]
+ "TARGET_MEDIA"
+ "mexpdhd %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mexpdhd")])
+
+(define_insn "*cond_exec_mexpdhd"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (set (match_operand:DI 2 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:SI 3 "fpr_operand" "f")
+ (match_operand:SI 4 "uint1_operand" "I")]
+ UNSPEC_MEXPDHD)))]
+ "TARGET_MEDIA"
+ "cmexpdhd %3, %4, %2, %1, %e0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mexpdhd")])
+
+;; FR cut: type "mwcut"
+
+(define_insn "mwcut"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:DI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_or_int6_operand" "fI")]
+ UNSPEC_MWCUT))]
+ "TARGET_MEDIA"
+ "mwcut%i2 %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mwcut")])
+
+;; Dual multiplication (halfword): type "mmulh"
+
+(define_expand "mmulhs"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b")
+ (unspec:DI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_dup 4)]
+ UNSPEC_MMULH))
+ (set (match_operand:HI 3 "accg_operand" "=B")
+ (unspec:HI [(const_int 0)] UNSPEC_MMULH))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MMULHS);")
+
+(define_expand "mmulhu"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b")
+ (unspec:DI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_dup 4)]
+ UNSPEC_MMULH))
+ (set (match_operand:HI 3 "accg_operand" "=B")
+ (unspec:HI [(const_int 0)] UNSPEC_MMULH))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MMULHU);")
+
+(define_insn "*mmulh"
+ [(set (match_operand:DI 0 "even_acc_operand" "=b")
+ (unspec:DI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_operand:SI 3 "const_int_operand" "n")]
+ UNSPEC_MMULH))
+ (set (match_operand:HI 4 "accg_operand" "=B")
+ (unspec:HI [(const_int 0)] UNSPEC_MMULH))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[3]))
+ {
+ default: break;
+ case FRV_BUILTIN_MMULHS: return \"mmulhs %1, %2, %0\";
+ case FRV_BUILTIN_MMULHU: return \"mmulhu %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mmulh\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mmulh")])
+
+(define_insn "*cond_exec_mmulh"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (parallel [(set (match_operand:DI 2 "even_acc_operand" "=b")
+ (unspec:DI [(match_operand:SI 3 "fpr_operand" "f")
+ (match_operand:SI 4 "fpr_operand" "f")
+ (match_operand:SI 5 "const_int_operand" "n")]
+ UNSPEC_MMULH))
+ (set (match_operand:HI 6 "accg_operand" "=B")
+ (unspec:HI [(const_int 0)] UNSPEC_MMULH))]))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[5]))
+ {
+ default: break;
+ case FRV_BUILTIN_MMULHS: return \"cmmulhs %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MMULHU: return \"cmmulhu %3, %4, %2, %1, %e0\";
+ }
+
+ fatal_insn (\"Bad media insn, cond_exec_mmulh\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mmulh")])
+
+;; Dual cross multiplication (halfword): type "mmulxh"
+
+(define_expand "mmulxhs"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b")
+ (unspec:DI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_dup 4)]
+ UNSPEC_MMULXH))
+ (set (match_operand:HI 3 "accg_operand" "=B")
+ (unspec:HI [(const_int 0)] UNSPEC_MMULXH))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MMULXHS);")
+
+(define_expand "mmulxhu"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b")
+ (unspec:DI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_dup 4)]
+ UNSPEC_MMULXH))
+ (set (match_operand:HI 3 "accg_operand" "=B")
+ (unspec:HI [(const_int 0)] UNSPEC_MMULXH))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MMULXHU);")
+
+(define_insn "*mmulxh"
+ [(set (match_operand:DI 0 "even_acc_operand" "=b")
+ (unspec:DI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_operand:SI 3 "const_int_operand" "n")]
+ UNSPEC_MMULXH))
+ (set (match_operand:HI 4 "accg_operand" "=B")
+ (unspec:HI [(const_int 0)] UNSPEC_MMULXH))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[3]))
+ {
+ default: break;
+ case FRV_BUILTIN_MMULXHS: return \"mmulxhs %1, %2, %0\";
+ case FRV_BUILTIN_MMULXHU: return \"mmulxhu %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mmulxh\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mmulxh")])
+
+;; Dual product-sum (halfword): type "mmach"
+
+(define_expand "mmachs"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "+b")
+ (unspec:DI [(match_dup 0)
+ (match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_operand:HI 3 "accg_operand" "+B")
+ (match_dup 4)]
+ UNSPEC_MMACH))
+ (set (match_dup 3)
+ (unspec:HI [(const_int 0)] UNSPEC_MMACH))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MMACHS);")
+
+(define_expand "mmachu"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "+b")
+ (unspec:DI [(match_dup 0)
+ (match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_operand:HI 3 "accg_operand" "+B")
+ (match_dup 4)]
+ UNSPEC_MMACH))
+ (set (match_dup 3)
+ (unspec:HI [(const_int 0)] UNSPEC_MMACH))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MMACHU);")
+
+(define_insn "*mmach"
+ [(set (match_operand:DI 0 "even_acc_operand" "+b")
+ (unspec:DI [(match_dup 0)
+ (match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_operand:HI 3 "accg_operand" "+B")
+ (match_operand:SI 4 "const_int_operand" "n")]
+ UNSPEC_MMACH))
+ (set (match_dup 3) (unspec:HI [(const_int 0)] UNSPEC_MMACH))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[4]))
+ {
+ default: break;
+ case FRV_BUILTIN_MMACHS: return \"mmachs %1, %2, %0\";
+ case FRV_BUILTIN_MMACHU: return \"mmachu %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mmach\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mmach")])
+
+(define_insn "*cond_exec_mmach"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (parallel [(set (match_operand:DI 2 "even_acc_operand" "+b")
+ (unspec:DI [(match_dup 2)
+ (match_operand:SI 3 "fpr_operand" "f")
+ (match_operand:SI 4 "fpr_operand" "f")
+ (match_operand:HI 5 "accg_operand" "+B")
+ (match_operand:SI 6 "const_int_operand" "n")]
+ UNSPEC_MMACH))
+ (set (match_dup 5)
+ (unspec:HI [(const_int 0)] UNSPEC_MMACH))]))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[6]))
+ {
+ default: break;
+ case FRV_BUILTIN_MMACHS: return \"cmmachs %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MMACHU: return \"cmmachu %3, %4, %2, %1, %e0\";
+ }
+
+ fatal_insn (\"Bad media insn, cond_exec_mmach\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mmach")])
+
+;; Dual product-difference: type "mmrdh"
+
+(define_expand "mmrdhs"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "+b")
+ (unspec:DI [(match_dup 0)
+ (match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_operand:HI 3 "accg_operand" "+B")
+ (match_dup 4)]
+ UNSPEC_MMRDH))
+ (set (match_dup 3)
+ (unspec:HI [(const_int 0)] UNSPEC_MMRDH))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MMRDHS);")
+
+(define_expand "mmrdhu"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "+b")
+ (unspec:DI [(match_dup 0)
+ (match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_operand:HI 3 "accg_operand" "+B")
+ (match_dup 4)]
+ UNSPEC_MMRDH))
+ (set (match_dup 3)
+ (unspec:HI [(const_int 0)] UNSPEC_MMRDH))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MMRDHU);")
+
+(define_insn "*mmrdh"
+ [(set (match_operand:DI 0 "even_acc_operand" "+b")
+ (unspec:DI [(match_dup 0)
+ (match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_operand:HI 3 "accg_operand" "+B")
+ (match_operand:SI 4 "const_int_operand" "n")]
+ UNSPEC_MMRDH))
+ (set (match_dup 3)
+ (unspec:HI [(const_int 0)] UNSPEC_MMRDH))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[4]))
+ {
+ default: break;
+ case FRV_BUILTIN_MMRDHS: return \"mmrdhs %1, %2, %0\";
+ case FRV_BUILTIN_MMRDHU: return \"mmrdhu %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mrdh\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mmrdh")])
+
+;; Quad multiply (halfword): type "mqmulh"
+
+(define_expand "mqmulhs"
+ [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "=A")
+ (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_dup 4)]
+ UNSPEC_MQMULH))
+ (set (match_operand:V4QI 3 "accg_operand" "=B")
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMULH))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MQMULHS);")
+
+(define_expand "mqmulhu"
+ [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "=A")
+ (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_dup 4)]
+ UNSPEC_MQMULH))
+ (set (match_operand:V4QI 3 "accg_operand" "=B")
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMULH))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MQMULHU);")
+
+(define_insn "*mqmulh"
+ [(set (match_operand:V4SI 0 "quad_acc_operand" "=A")
+ (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_operand:SI 3 "const_int_operand" "n")]
+ UNSPEC_MQMULH))
+ (set (match_operand:V4QI 4 "accg_operand" "=B")
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMULH))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[3]))
+ {
+ default: break;
+ case FRV_BUILTIN_MQMULHS: return \"mqmulhs %1, %2, %0\";
+ case FRV_BUILTIN_MQMULHU: return \"mqmulhu %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mqmulh\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mqmulh")])
+
+(define_insn "*cond_exec_mqmulh"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (parallel [(set (match_operand:V4SI 2 "quad_acc_operand" "=A")
+ (unspec:V4SI [(match_operand:DI 3 "even_fpr_operand" "h")
+ (match_operand:DI 4 "even_fpr_operand" "h")
+ (match_operand:SI 5 "const_int_operand" "n")]
+ UNSPEC_MQMULH))
+ (set (match_operand:V4QI 6 "accg_operand" "=B")
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMULH))]))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[5]))
+ {
+ default: break;
+ case FRV_BUILTIN_MQMULHS: return \"cmqmulhs %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MQMULHU: return \"cmqmulhu %3, %4, %2, %1, %e0\";
+ }
+
+ fatal_insn (\"Bad media insn, cond_exec_mqmulh\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mqmulh")])
+
+;; Quad cross multiply (halfword): type "mqmulxh"
+
+(define_expand "mqmulxhs"
+ [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "=A")
+ (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_dup 4)]
+ UNSPEC_MQMULXH))
+ (set (match_operand:V4QI 3 "accg_operand" "=B")
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMULXH))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MQMULXHS);")
+
+(define_expand "mqmulxhu"
+ [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "=A")
+ (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_dup 4)]
+ UNSPEC_MQMULXH))
+ (set (match_operand:V4QI 3 "accg_operand" "=B")
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMULXH))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MQMULXHU);")
+
+(define_insn "*mqmulxh"
+ [(set (match_operand:V4SI 0 "quad_acc_operand" "=A")
+ (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_operand:SI 3 "const_int_operand" "n")]
+ UNSPEC_MQMULXH))
+ (set (match_operand:V4QI 4 "accg_operand" "=B")
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMULXH))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[3]))
+ {
+ default: break;
+ case FRV_BUILTIN_MQMULXHS: return \"mqmulxhs %1, %2, %0\";
+ case FRV_BUILTIN_MQMULXHU: return \"mqmulxhu %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mqmulxh\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mqmulxh")])
+
+;; Quad product-sum (halfword): type "mqmach"
+
+(define_expand "mqmachs"
+ [(parallel [(set (match_operand:V4SI 0 "even_acc_operand" "+A")
+ (unspec:V4SI [(match_dup 0)
+ (match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_operand:V4QI 3 "accg_operand" "+B")
+ (match_dup 4)]
+ UNSPEC_MQMACH))
+ (set (match_dup 3)
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MQMACHS);")
+
+(define_expand "mqmachu"
+ [(parallel [(set (match_operand:V4SI 0 "even_acc_operand" "+A")
+ (unspec:V4SI [(match_dup 0)
+ (match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_operand:V4QI 3 "accg_operand" "+B")
+ (match_dup 4)]
+ UNSPEC_MQMACH))
+ (set (match_dup 3)
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MQMACHU);")
+
+(define_insn "*mqmach"
+ [(set (match_operand:V4SI 0 "even_acc_operand" "+A")
+ (unspec:V4SI [(match_dup 0)
+ (match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_operand:V4QI 3 "accg_operand" "+B")
+ (match_operand:SI 4 "const_int_operand" "n")]
+ UNSPEC_MQMACH))
+ (set (match_dup 3)
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[4]))
+ {
+ default: break;
+ case FRV_BUILTIN_MQMACHS: return \"mqmachs %1, %2, %0\";
+ case FRV_BUILTIN_MQMACHU: return \"mqmachu %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mqmach\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mqmach")])
+
+(define_insn "*cond_exec_mqmach"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (parallel [(set (match_operand:V4SI 2 "even_acc_operand" "+A")
+ (unspec:V4SI [(match_dup 2)
+ (match_operand:DI 3 "even_fpr_operand" "h")
+ (match_operand:DI 4 "even_fpr_operand" "h")
+ (match_operand:V4QI 5 "accg_operand" "+B")
+ (match_operand:SI 6 "const_int_operand" "n")]
+ UNSPEC_MQMACH))
+ (set (match_dup 5)
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH))]))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[6]))
+ {
+ default: break;
+ case FRV_BUILTIN_MQMACHS: return \"cmqmachs %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MQMACHU: return \"cmqmachu %3, %4, %2, %1, %e0\";
+ }
+
+ fatal_insn (\"Bad media insn, cond_exec_mqmach\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mqmach")])
+
+;; Dual complex number product-sum (halfword)
+
+(define_expand "mcpxrs"
+ [(parallel [(set (match_operand:SI 0 "acc_operand" "=a")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_dup 4)]
+ UNSPEC_MCPX))
+ (set (match_operand:QI 3 "accg_operand" "=B")
+ (unspec:QI [(const_int 0)] UNSPEC_MCPX))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MCPXRS);")
+
+(define_expand "mcpxru"
+ [(parallel [(set (match_operand:SI 0 "acc_operand" "=a")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_dup 4)]
+ UNSPEC_MCPX))
+ (set (match_operand:QI 3 "accg_operand" "=B")
+ (unspec:QI [(const_int 0)] UNSPEC_MCPX))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MCPXRU);")
+
+(define_expand "mcpxis"
+ [(parallel [(set (match_operand:SI 0 "acc_operand" "=a")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_dup 4)]
+ UNSPEC_MCPX))
+ (set (match_operand:QI 3 "accg_operand" "=B")
+ (unspec:QI [(const_int 0)] UNSPEC_MCPX))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MCPXIS);")
+
+(define_expand "mcpxiu"
+ [(parallel [(set (match_operand:SI 0 "acc_operand" "=a")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_dup 4)]
+ UNSPEC_MCPX))
+ (set (match_operand:QI 3 "accg_operand" "=B")
+ (unspec:QI [(const_int 0)] UNSPEC_MCPX))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MCPXIU);")
+
+(define_insn "*mcpx"
+ [(parallel [(set (match_operand:SI 0 "acc_operand" "=a")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")
+ (match_operand:SI 3 "const_int_operand" "n")]
+ UNSPEC_MCPX))
+ (set (match_operand:QI 4 "accg_operand" "=B")
+ (unspec:QI [(const_int 0)] UNSPEC_MCPX))])]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[3]))
+ {
+ default: break;
+ case FRV_BUILTIN_MCPXRS: return \"mcpxrs %1, %2, %0\";
+ case FRV_BUILTIN_MCPXRU: return \"mcpxru %1, %2, %0\";
+ case FRV_BUILTIN_MCPXIS: return \"mcpxis %1, %2, %0\";
+ case FRV_BUILTIN_MCPXIU: return \"mcpxiu %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mcpx\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mcpx")])
+
+(define_insn "*cond_exec_mcpx"
+ [(cond_exec
+ (match_operator 0 "ccr_eqne_operator"
+ [(match_operand 1 "cr_operand" "C")
+ (const_int 0)])
+ (parallel [(set (match_operand:SI 2 "acc_operand" "=a")
+ (unspec:SI [(match_operand:SI 3 "fpr_operand" "f")
+ (match_operand:SI 4 "fpr_operand" "f")
+ (match_operand:SI 5 "const_int_operand" "n")]
+ UNSPEC_MCPX))
+ (set (match_operand:QI 6 "accg_operand" "=B")
+ (unspec:QI [(const_int 0)] UNSPEC_MCPX))]))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[5]))
+ {
+ default: break;
+ case FRV_BUILTIN_MCPXRS: return \"cmcpxrs %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MCPXRU: return \"cmcpxru %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MCPXIS: return \"cmcpxis %3, %4, %2, %1, %e0\";
+ case FRV_BUILTIN_MCPXIU: return \"cmcpxiu %3, %4, %2, %1, %e0\";
+ }
+
+ fatal_insn (\"Bad media insn, cond_exec_mcpx\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mcpx")])
+
+;; Quad complex number product-sum (halfword): type "mqcpx"
+
+(define_expand "mqcpxrs"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b")
+ (unspec:DI [(match_operand:DI 1 "fpr_operand" "f")
+ (match_operand:DI 2 "fpr_operand" "f")
+ (match_dup 4)]
+ UNSPEC_MQCPX))
+ (set (match_operand:HI 3 "accg_operand" "=B")
+ (unspec:HI [(const_int 0)] UNSPEC_MQCPX))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MQCPXRS);")
+
+(define_expand "mqcpxru"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b")
+ (unspec:DI [(match_operand:DI 1 "fpr_operand" "f")
+ (match_operand:DI 2 "fpr_operand" "f")
+ (match_dup 4)]
+ UNSPEC_MQCPX))
+ (set (match_operand:HI 3 "accg_operand" "=B")
+ (unspec:HI [(const_int 0)] UNSPEC_MQCPX))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MQCPXRU);")
+
+(define_expand "mqcpxis"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b")
+ (unspec:DI [(match_operand:DI 1 "fpr_operand" "f")
+ (match_operand:DI 2 "fpr_operand" "f")
+ (match_dup 4)]
+ UNSPEC_MQCPX))
+ (set (match_operand:HI 3 "accg_operand" "=B")
+ (unspec:HI [(const_int 0)] UNSPEC_MQCPX))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MQCPXIS);")
+
+(define_expand "mqcpxiu"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "=b")
+ (unspec:DI [(match_operand:DI 1 "fpr_operand" "f")
+ (match_operand:DI 2 "fpr_operand" "f")
+ (match_dup 4)]
+ UNSPEC_MQCPX))
+ (set (match_operand:HI 3 "accg_operand" "=B")
+ (unspec:HI [(const_int 0)] UNSPEC_MQCPX))])]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MQCPXIU);")
+
+(define_insn "*mqcpx"
+ [(set (match_operand:DI 0 "even_acc_operand" "=b")
+ (unspec:DI [(match_operand:DI 1 "fpr_operand" "f")
+ (match_operand:DI 2 "fpr_operand" "f")
+ (match_operand:SI 3 "const_int_operand" "n")]
+ UNSPEC_MQCPX))
+ (set (match_operand:HI 4 "accg_operand" "=B")
+ (unspec:HI [(const_int 0)] UNSPEC_MQCPX))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[3]))
+ {
+ default: break;
+ case FRV_BUILTIN_MQCPXRS: return \"mqcpxrs %1, %2, %0\";
+ case FRV_BUILTIN_MQCPXRU: return \"mqcpxru %1, %2, %0\";
+ case FRV_BUILTIN_MQCPXIS: return \"mqcpxis %1, %2, %0\";
+ case FRV_BUILTIN_MQCPXIU: return \"mqcpxiu %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mqcpx\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mqcpx")])
+
+;; Cut: type "mcut"
+
+(define_expand "mcut"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "acc_operand" "a")
+ (match_operand:SI 2 "fpr_or_int6_operand" "fI")
+ (match_operand:QI 3 "accg_operand" "B")
+ (match_dup 4)]
+ UNSPEC_MCUT))]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MCUT);")
+
+(define_expand "mcutss"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "acc_operand" "a")
+ (match_operand:SI 2 "fpr_or_int6_operand" "fI")
+ (match_operand:QI 3 "accg_operand" "B")
+ (match_dup 4)]
+ UNSPEC_MCUT))]
+ "TARGET_MEDIA"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MCUTSS);")
+
+(define_insn "*mcut"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "acc_operand" "a")
+ (match_operand:SI 2 "fpr_or_int6_operand" "fI")
+ (match_operand:QI 3 "accg_operand" "B")
+ (match_operand:SI 4 "const_int_operand" "n")]
+ UNSPEC_MCUT))]
+ "TARGET_MEDIA"
+ "*
+{
+ switch (INTVAL (operands[4]))
+ {
+ default: break;
+ case FRV_BUILTIN_MCUT: return \"mcut%i2 %1, %2, %0\";
+ case FRV_BUILTIN_MCUTSS: return \"mcutss%i2 %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mcut\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mcut")])
+
+;; Accumulator read: type "mrdacc"
+
+(define_insn "mrdacc"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "acc_operand" "a")] UNSPEC_MRDACC))]
+ "TARGET_MEDIA"
+ "mrdacc %1, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mrdacc")])
+
+(define_insn "mrdaccg"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:QI 1 "accg_operand" "B")] UNSPEC_MRDACCG))]
+ "TARGET_MEDIA"
+ "mrdaccg %1, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mrdacc")])
+
+;; Accumulator write: type "mwtacc"
+
+(define_insn "mwtacc"
+ [(set (match_operand:SI 0 "acc_operand" "=a")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")] UNSPEC_MWTACC))]
+ "TARGET_MEDIA"
+ "mwtacc %1, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mwtacc")])
+
+(define_insn "mwtaccg"
+ [(set (match_operand:QI 0 "accg_operand" "=B")
+ (unspec:QI [(match_operand:SI 1 "fpr_operand" "f")] UNSPEC_MWTACCG))]
+ "TARGET_MEDIA"
+ "mwtaccg %1, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mwtacc")])
+
+;; Trap: This one executes on the control unit, not the media units.
+
+(define_insn "mtrap"
+ [(unspec_volatile [(const_int 0)] UNSPEC_MTRAP)]
+ "TARGET_MEDIA"
+ "mtrap"
+ [(set_attr "length" "4")
+ (set_attr "type" "trap")])
+
+;; Clear single accumulator: type "mclracc"
+
+(define_insn "mclracc_internal"
+ [(set (match_operand:SI 0 "acc_operand" "=a")
+ (unspec:SI [(const_int 0)] UNSPEC_MCLRACC))
+ (set (match_operand:QI 1 "accg_operand" "=B")
+ (unspec:QI [(const_int 0)] UNSPEC_MCLRACC))]
+ "TARGET_MEDIA"
+ "mclracc %0,#0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mclracc")])
+
+(define_expand "mclracc"
+ [(parallel [(set (match_operand:SI 0 "acc_operand" "=a")
+ (unspec:SI [(const_int 0)] UNSPEC_MCLRACC))
+ (set (match_dup 1)
+ (unspec:QI [(const_int 0)] UNSPEC_MCLRACC))])]
+ "TARGET_MEDIA"
+ "
+{
+ if (GET_CODE (operands[0]) != REG || !ACC_P (REGNO (operands[0])))
+ FAIL;
+
+ operands[1] = frv_matching_accg_for_acc (operands[0]);
+}")
+
+;; Clear all accumulators: type "mclracca"
+
+(define_insn "mclracca8_internal"
+ [(set (match_operand:V4SI 0 "quad_acc_operand" "=b")
+ (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA))
+ (set (match_operand:V4SI 1 "quad_acc_operand" "=b")
+ (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA))
+ (set (match_operand:V4QI 2 "accg_operand" "=B")
+ (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA))
+ (set (match_operand:V4QI 3 "accg_operand" "=B")
+ (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA))]
+ "TARGET_MEDIA && TARGET_ACC_8"
+ "mclracc acc0,#1"
+ [(set_attr "length" "4")
+ (set_attr "type" "mclracca")])
+
+(define_insn "mclracca4_internal"
+ [(set (match_operand:V4SI 0 "quad_acc_operand" "=b")
+ (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA))
+ (set (match_operand:V4QI 1 "accg_operand" "=B")
+ (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA))]
+ "TARGET_MEDIA && TARGET_ACC_4"
+ "mclracc acc0,#1"
+ [(set_attr "length" "4")
+ (set_attr "type" "mclracca")])
+
+(define_expand "mclracca8"
+ [(parallel [(set (match_dup 0) (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA))
+ (set (match_dup 1) (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA))
+ (set (match_dup 2) (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA))
+ (set (match_dup 3) (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA))])]
+ "TARGET_MEDIA && TARGET_ACC_8"
+ "
+{
+ operands[0] = gen_rtx_REG (V4SImode, ACC_FIRST);
+ operands[1] = gen_rtx_REG (V4SImode, ACC_FIRST + 4);
+ operands[2] = gen_rtx_REG (V4QImode, ACCG_FIRST);
+ operands[3] = gen_rtx_REG (V4QImode, ACCG_FIRST + 4);
+}")
+
+(define_expand "mclracca4"
+ [(parallel [(set (match_dup 0) (unspec:V4SI [(const_int 0)] UNSPEC_MCLRACCA))
+ (set (match_dup 1) (unspec:V4QI [(const_int 0)] UNSPEC_MCLRACCA))])]
+ "TARGET_MEDIA && TARGET_ACC_4"
+ "
+{
+ operands[0] = gen_rtx_REG (V4SImode, ACC_FIRST);
+ operands[1] = gen_rtx_REG (V4QImode, ACCG_FIRST);
+}")
+
+(define_insn "mcop1"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")] UNSPEC_MCOP1))]
+ "TARGET_MEDIA_REV1"
+ "mcop1 %1, %2, %0"
+ [(set_attr "length" "4")
+;; What is the class of the insn ???
+ (set_attr "type" "multi")])
+
+(define_insn "mcop2"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")
+ (match_operand:SI 2 "fpr_operand" "f")] UNSPEC_MCOP2))]
+ "TARGET_MEDIA_REV1"
+ "mcop2 %1, %2, %0"
+ [(set_attr "length" "4")
+;; What is the class of the insn ???
+ (set_attr "type" "multi")])
+
+(define_insn "*mdunpackh_internal"
+ [(set (match_operand:V4SI 0 "quad_fpr_operand" "=x")
+ (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h")]
+ UNSPEC_MDUNPACKH_INTERNAL))]
+ "TARGET_MEDIA_REV1"
+ "mdunpackh %1, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mdunpackh")])
+
+(define_insn_and_split "mdunpackh"
+ [(set (match_operand:V4SI 0 "memory_operand" "=o")
+ (unspec:V4SI [(match_operand:DI 1 "even_fpr_operand" "h")]
+ UNSPEC_MDUNPACKH))
+ (clobber (match_scratch:V4SI 2 "=x"))]
+ "TARGET_MEDIA_REV1"
+ "#"
+ "reload_completed"
+ [(set (match_dup 2)
+ (unspec:V4SI [(match_dup 1)] UNSPEC_MDUNPACKH_INTERNAL))
+ (set (match_dup 3)
+ (match_dup 4))
+ (set (match_dup 5)
+ (match_dup 6))]
+ "
+{
+ operands[3] = change_address (operands[0], DImode, NULL_RTX);
+ operands[4] = gen_rtx_REG (DImode, REGNO (operands[2]));
+ operands[5] = frv_index_memory (operands[0], DImode, 1);
+ operands[6] = gen_rtx_REG (DImode, REGNO (operands[2])+2);
+}"
+ [(set_attr "length" "20")
+ (set_attr "type" "multi")])
+
+(define_insn "*mbtohe_internal"
+ [(set (match_operand:V4SI 0 "quad_fpr_operand" "=x")
+ (unspec:V4SI [(match_operand:SI 1 "fpr_operand" "f")]
+ UNSPEC_MBTOHE_INTERNAL))]
+ "TARGET_MEDIA_REV1"
+ "mbtohe %1, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mbhconve")])
+
+(define_insn_and_split "mbtohe"
+ [(set (match_operand:V4SI 0 "memory_operand" "=o")
+ (unspec:V4SI [(match_operand:SI 1 "fpr_operand" "f")]
+ UNSPEC_MBTOHE))
+ (clobber (match_scratch:V4SI 2 "=x"))]
+ "TARGET_MEDIA_REV1"
+ "#"
+ "reload_completed"
+ [(set (match_dup 2)
+ (unspec:V4SI [(match_dup 1)] UNSPEC_MBTOHE_INTERNAL))
+ (set (match_dup 3)
+ (match_dup 4))
+ (set (match_dup 5)
+ (match_dup 6))]
+ "
+{
+ operands[3] = change_address (operands[0], DImode, NULL_RTX);
+ operands[4] = gen_rtx_REG (DImode, REGNO (operands[2]));
+ operands[5] = frv_index_memory (operands[0], DImode, 1);
+ operands[6] = gen_rtx_REG (DImode, REGNO (operands[2])+2);
+}"
+ [(set_attr "length" "20")
+ (set_attr "type" "multi")])
+
+;; Quad product-sum (halfword) instructions only found on the FR400.
+;; type "mqmach"
+
+(define_expand "mqxmachs"
+ [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "")
+ (unspec:V4SI [(match_dup 0)
+ (match_operand:DI 1 "even_fpr_operand" "")
+ (match_operand:DI 2 "even_fpr_operand" "")
+ (match_operand:V4QI 3 "accg_operand" "")
+ (match_dup 4)]
+ UNSPEC_MQMACH2))
+ (set (match_dup 3)
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH2))])]
+ "TARGET_MEDIA_REV2"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MQXMACHS);")
+
+(define_expand "mqxmacxhs"
+ [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "")
+ (unspec:V4SI [(match_dup 0)
+ (match_operand:DI 1 "even_fpr_operand" "")
+ (match_operand:DI 2 "even_fpr_operand" "")
+ (match_operand:V4QI 3 "accg_operand" "")
+ (match_dup 4)]
+ UNSPEC_MQMACH2))
+ (set (match_dup 3)
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH2))])]
+ "TARGET_MEDIA_REV2"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MQXMACXHS);")
+
+(define_expand "mqmacxhs"
+ [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "")
+ (unspec:V4SI [(match_dup 0)
+ (match_operand:DI 1 "even_fpr_operand" "")
+ (match_operand:DI 2 "even_fpr_operand" "")
+ (match_operand:V4QI 3 "accg_operand" "")
+ (match_dup 4)]
+ UNSPEC_MQMACH2))
+ (set (match_dup 3)
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH2))])]
+ "TARGET_MEDIA_REV2"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MQMACXHS);")
+
+(define_insn "*mqmach2"
+ [(set (match_operand:V4SI 0 "quad_acc_operand" "+A")
+ (unspec:V4SI [(match_dup 0)
+ (match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")
+ (match_operand:V4QI 3 "accg_operand" "+B")
+ (match_operand:SI 4 "const_int_operand" "n")]
+ UNSPEC_MQMACH2))
+ (set (match_dup 3)
+ (unspec:V4QI [(const_int 0)] UNSPEC_MQMACH2))]
+ "TARGET_MEDIA_REV2"
+ "*
+{
+ switch (INTVAL (operands[4]))
+ {
+ default: break;
+ case FRV_BUILTIN_MQXMACHS: return \"mqxmachs %1, %2, %0\";
+ case FRV_BUILTIN_MQXMACXHS: return \"mqxmacxhs %1, %2, %0\";
+ case FRV_BUILTIN_MQMACXHS: return \"mqmacxhs %1, %2, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mqmach2\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mqmach")])
+
+;; Accumulator addition/subtraction: type "maddacc"
+
+(define_expand "maddaccs"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "")
+ (unspec:DI [(match_dup 0)
+ (match_operand:DI 1 "even_acc_operand" "")]
+ UNSPEC_MADDACC))
+ (set (match_operand:HI 2 "accg_operand" "")
+ (unspec:HI [(match_dup 2)
+ (match_operand:HI 3 "accg_operand" "")
+ (match_dup 4)]
+ UNSPEC_MADDACC))])]
+ "TARGET_MEDIA_REV2"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MADDACCS);")
+
+(define_expand "msubaccs"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "")
+ (unspec:DI [(match_dup 0)
+ (match_operand:DI 1 "even_acc_operand" "")]
+ UNSPEC_MADDACC))
+ (set (match_operand:HI 2 "accg_operand" "")
+ (unspec:HI [(match_dup 2)
+ (match_operand:HI 3 "accg_operand" "")
+ (match_dup 4)]
+ UNSPEC_MADDACC))])]
+ "TARGET_MEDIA_REV2"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MSUBACCS);")
+
+(define_expand "masaccs"
+ [(parallel [(set (match_operand:DI 0 "even_acc_operand" "")
+ (unspec:DI [(match_dup 0)
+ (match_operand:DI 1 "even_acc_operand" "")]
+ UNSPEC_MADDACC))
+ (set (match_operand:HI 2 "accg_operand" "")
+ (unspec:HI [(match_dup 2)
+ (match_operand:HI 3 "accg_operand" "")
+ (match_dup 4)]
+ UNSPEC_MADDACC))])]
+ "TARGET_MEDIA_REV2"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MASACCS);")
+
+(define_insn "*maddacc"
+ [(set (match_operand:DI 0 "even_acc_operand" "+b")
+ (unspec:DI [(match_dup 0)
+ (match_operand:DI 1 "even_acc_operand" "b")]
+ UNSPEC_MADDACC))
+ (set (match_operand:HI 2 "accg_operand" "+B")
+ (unspec:HI [(match_dup 2)
+ (match_operand:HI 3 "accg_operand" "B")
+ (match_operand:SI 4 "const_int_operand" "n")]
+ UNSPEC_MADDACC))]
+ "TARGET_MEDIA_REV2"
+ "*
+{
+ switch (INTVAL (operands[4]))
+ {
+ default: break;
+ case FRV_BUILTIN_MADDACCS: return \"maddaccs %1, %0\";
+ case FRV_BUILTIN_MSUBACCS: return \"msubaccs %1, %0\";
+ case FRV_BUILTIN_MASACCS: return \"masaccs %1, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, maddacc\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "maddacc")])
+
+;; Dual accumulator addition/subtraction: type "mdaddacc"
+
+(define_expand "mdaddaccs"
+ [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "")
+ (unspec:V4SI [(match_dup 0)
+ (match_operand:V4SI 1 "quad_acc_operand" "")]
+ UNSPEC_MDADDACC))
+ (set (match_operand:V4QI 2 "accg_operand" "")
+ (unspec:V4QI [(match_dup 2)
+ (match_operand:V4QI 3 "accg_operand" "")
+ (match_dup 4)]
+ UNSPEC_MDADDACC))])]
+ "TARGET_MEDIA_REV2"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MDADDACCS);")
+
+(define_expand "mdsubaccs"
+ [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "")
+ (unspec:V4SI [(match_dup 0)
+ (match_operand:V4SI 1 "quad_acc_operand" "")]
+ UNSPEC_MDADDACC))
+ (set (match_operand:V4QI 2 "accg_operand" "")
+ (unspec:V4QI [(match_dup 2)
+ (match_operand:V4QI 3 "accg_operand" "")
+ (match_dup 4)]
+ UNSPEC_MDADDACC))])]
+ "TARGET_MEDIA_REV2"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MDSUBACCS);")
+
+(define_expand "mdasaccs"
+ [(parallel [(set (match_operand:V4SI 0 "quad_acc_operand" "")
+ (unspec:V4SI [(match_dup 0)
+ (match_operand:V4SI 1 "quad_acc_operand" "")]
+ UNSPEC_MDADDACC))
+ (set (match_operand:V4QI 2 "accg_operand" "")
+ (unspec:V4QI [(match_dup 2)
+ (match_operand:V4QI 3 "accg_operand" "")
+ (match_dup 4)]
+ UNSPEC_MDADDACC))])]
+ "TARGET_MEDIA_REV2"
+ "operands[4] = GEN_INT (FRV_BUILTIN_MDASACCS);")
+
+(define_insn "*mdaddacc"
+ [(set (match_operand:V4SI 0 "quad_acc_operand" "+A")
+ (unspec:V4SI [(match_dup 0)
+ (match_operand:V4SI 1 "quad_acc_operand" "A")]
+ UNSPEC_MDADDACC))
+ (set (match_operand:V4QI 2 "accg_operand" "+B")
+ (unspec:V4QI [(match_dup 2)
+ (match_operand:V4QI 3 "accg_operand" "B")
+ (match_operand:SI 4 "const_int_operand" "n")]
+ UNSPEC_MDADDACC))]
+ "TARGET_MEDIA_REV2"
+ "*
+{
+ switch (INTVAL (operands[4]))
+ {
+ default: break;
+ case FRV_BUILTIN_MDADDACCS: return \"mdaddaccs %1, %0\";
+ case FRV_BUILTIN_MDSUBACCS: return \"mdsubaccs %1, %0\";
+ case FRV_BUILTIN_MDASACCS: return \"mdasaccs %1, %0\";
+ }
+
+ fatal_insn (\"Bad media insn, mdaddacc\", insn);
+}"
+ [(set_attr "length" "4")
+ (set_attr "type" "mdaddacc")])
+
+;; Dual absolute (halfword): type "mabsh"
+
+(define_insn "mabshs"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "f")] UNSPEC_MABSHS))]
+ "TARGET_MEDIA_REV2"
+ "mabshs %1, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mabsh")])
+
+;; Dual rotate: type "mdrot"
+
+(define_insn "mdrotli"
+ [(set (match_operand:DI 0 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:SI 2 "uint5_operand" "I")]
+ UNSPEC_MDROTLI))]
+ "TARGET_MEDIA_REV2"
+ "mdrotli %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mdrot")])
+
+;; Dual coupling (concatenation): type "mcpl"
+
+(define_insn "mcplhi"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:DI 1 "fpr_operand" "h")
+ (match_operand:SI 2 "uint4_operand" "I")]
+ UNSPEC_MCPLHI))]
+ "TARGET_MEDIA_REV2"
+ "mcplhi %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mcpl")])
+
+(define_insn "mcpli"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:DI 1 "fpr_operand" "h")
+ (match_operand:SI 2 "uint5_operand" "I")]
+ UNSPEC_MCPLI))]
+ "TARGET_MEDIA_REV2"
+ "mcpli %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mcpl")])
+
+;; Dual cut: type "mdcut"
+
+(define_insn "mdcutssi"
+ [(set (match_operand:DI 0 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:DI 1 "even_acc_operand" "b")
+ (match_operand:SI 2 "int6_operand" "I")
+ (match_operand:HI 3 "accg_operand" "B")]
+ UNSPEC_MDCUTSSI))]
+ "TARGET_MEDIA_REV2"
+ "mdcutssi %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mdcut")])
+
+;; Quad saturate (halfword): type "mqsath"
+
+(define_insn "mqsaths"
+ [(set (match_operand:DI 0 "even_fpr_operand" "=h")
+ (unspec:DI [(match_operand:DI 1 "even_fpr_operand" "h")
+ (match_operand:DI 2 "even_fpr_operand" "h")]
+ UNSPEC_MQSATHS))]
+ "TARGET_MEDIA_REV2"
+ "mqsaths %1, %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mqsath")])
+
+;; Set hi/lo instrctions: type "mset"
+
+(define_insn "mhsetlos"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "0")
+ (match_operand:SI 2 "int12_operand" "NOP")]
+ UNSPEC_MHSETLOS))]
+ "TARGET_MEDIA_REV2"
+ "mhsetlos %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mset")])
+
+(define_insn "mhsetloh"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "0")
+ (match_operand:SI 2 "int5_operand" "I")]
+ UNSPEC_MHSETLOH))]
+ "TARGET_MEDIA_REV2"
+ "mhsetloh %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mset")])
+
+(define_insn "mhsethis"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "0")
+ (match_operand:SI 2 "int12_operand" "NOP")]
+ UNSPEC_MHSETHIS))]
+ "TARGET_MEDIA_REV2"
+ "mhsethis %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mset")])
+
+(define_insn "mhsethih"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "0")
+ (match_operand:SI 2 "int5_operand" "I")]
+ UNSPEC_MHSETHIH))]
+ "TARGET_MEDIA_REV2"
+ "mhsethih %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mset")])
+
+(define_insn "mhdsets"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "int12_operand" "NOP")]
+ UNSPEC_MHDSETS))]
+ "TARGET_MEDIA_REV2"
+ "mhdsets %1, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mset")])
+
+(define_insn "mhdseth"
+ [(set (match_operand:SI 0 "fpr_operand" "=f")
+ (unspec:SI [(match_operand:SI 1 "fpr_operand" "0")
+ (match_operand:SI 2 "int5_operand" "I")]
+ UNSPEC_MHDSETH))]
+ "TARGET_MEDIA_REV2"
+ "mhdseth %2, %0"
+ [(set_attr "length" "4")
+ (set_attr "type" "mset")])
diff --git a/contrib/gcc/config/frv/frvbegin.c b/contrib/gcc/config/frv/frvbegin.c
new file mode 100644
index 0000000..a5f5b1f
--- /dev/null
+++ b/contrib/gcc/config/frv/frvbegin.c
@@ -0,0 +1,150 @@
+/* Frv initialization file linked before all user modules
+ Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+ Contributed by Red Hat, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software ; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation * either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY ; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ This file was originally taken from the file crtstuff.c in the
+ main compiler directory, and simplified. */
+
+#include "defaults.h"
+#include <stddef.h>
+#include "unwind-dw2-fde.h"
+#include "gbl-ctors.h"
+
+/* Declare a pointer to void function type. */
+#define STATIC static
+
+#ifdef __FRV_UNDERSCORE__
+#define UNDERSCORE "_"
+#else
+#define UNDERSCORE ""
+#endif
+
+#define INIT_SECTION_NEG_ONE(SECTION, FLAGS, NAME) \
+__asm__ (".section " SECTION "," FLAGS "\n\t" \
+ ".globl " UNDERSCORE NAME "\n\t" \
+ ".type " UNDERSCORE NAME ",@object\n\t" \
+ ".p2align 2\n" \
+ UNDERSCORE NAME ":\n\t" \
+ ".word -1\n\t" \
+ ".previous")
+
+#define INIT_SECTION(SECTION, FLAGS, NAME) \
+__asm__ (".section " SECTION "," FLAGS "\n\t" \
+ ".globl " UNDERSCORE NAME "\n\t" \
+ ".type " UNDERSCORE NAME ",@object\n\t" \
+ ".p2align 2\n" \
+ UNDERSCORE NAME ":\n\t" \
+ ".previous")
+
+/* Beginning of .ctor/.dtor sections that provides a list of constructors and
+ destructors to run. */
+
+INIT_SECTION_NEG_ONE (".ctors", "\"aw\"", "__CTOR_LIST__");
+INIT_SECTION_NEG_ONE (".dtors", "\"aw\"", "__DTOR_LIST__");
+
+/* Beginning of .eh_frame section that provides all of the exception handling
+ tables. */
+
+INIT_SECTION (".eh_frame", "\"aw\"", "__EH_FRAME_BEGIN__");
+
+/* Beginning of .rofixup section that provides a list of pointers that we
+ need to adjust. */
+
+INIT_SECTION (".rofixup", "\"a\"", "__ROFIXUP_LIST__");
+
+extern void __frv_register_eh(void) __attribute__((__constructor__));
+extern void __frv_deregister_eh(void) __attribute__((__destructor__));
+
+extern func_ptr __EH_FRAME_BEGIN__[];
+
+/* Register the exeception handling table as the first constructor */
+void
+__frv_register_eh (void)
+{
+ static struct object object;
+ if (__register_frame_info)
+ __register_frame_info (__EH_FRAME_BEGIN__, &object);
+}
+
+/* Note, do not declare __{,de}register_frame_info weak as it seems
+ to interfere with the pic support. */
+
+/* Unregister the exeception handling table as a deconstructor */
+void
+__frv_deregister_eh (void)
+{
+ static int completed = 0;
+
+ if (completed)
+ return;
+
+ if (__deregister_frame_info)
+ __deregister_frame_info (__EH_FRAME_BEGIN__);
+
+ completed = 1;
+}
+
+/* Run the global destructors */
+void
+__do_global_dtors ()
+{
+ static func_ptr *p = __DTOR_LIST__ + 1;
+ while (*p)
+ {
+ p++;
+ (*(p-1)) ();
+ }
+}
+
+/* Run the global constructors */
+void
+__do_global_ctors ()
+{
+ unsigned long nptrs = (unsigned long) __CTOR_LIST__[0];
+ unsigned i;
+
+ if (nptrs == (unsigned long)-1)
+ for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++);
+
+ for (i = nptrs; i >= 1; i--)
+ __CTOR_LIST__[i] ();
+
+ atexit (__do_global_dtors);
+}
+
+/* Subroutine called automatically by `main'.
+ Compiling a global function named `main'
+ produces an automatic call to this function at the beginning.
+
+ For many systems, this routine calls __do_global_ctors.
+ For systems which support a .init section we use the .init section
+ to run __do_global_ctors, so we need not do anything here. */
+
+void
+__main ()
+{
+ /* Support recursive calls to `main': run initializers just once. */
+ static int initialized;
+ if (! initialized)
+ {
+ initialized = 1;
+ __do_global_ctors ();
+ }
+}
diff --git a/contrib/gcc/config/frv/frvend.c b/contrib/gcc/config/frv/frvend.c
new file mode 100644
index 0000000..f1635cc
--- /dev/null
+++ b/contrib/gcc/config/frv/frvend.c
@@ -0,0 +1,63 @@
+/* Frv initialization file linked after all user modules
+ Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+ Contributed by Red Hat, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software ; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation * either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY ; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defaults.h"
+#include <stddef.h>
+#include "unwind-dw2-fde.h"
+
+#ifdef __FRV_UNDERSCORE__
+#define UNDERSCORE "_"
+#else
+#define UNDERSCORE ""
+#endif
+
+#define FINI_SECTION_ZERO(SECTION, FLAGS, NAME) \
+__asm__ (".section " SECTION "," FLAGS "\n\t" \
+ ".globl " UNDERSCORE NAME "\n\t" \
+ ".type " UNDERSCORE NAME ",@object\n\t" \
+ ".p2align 2\n" \
+ UNDERSCORE NAME ":\n\t" \
+ ".word 0\n\t" \
+ ".previous")
+
+#define FINI_SECTION(SECTION, FLAGS, NAME) \
+__asm__ (".section " SECTION "," FLAGS "\n\t" \
+ ".globl " UNDERSCORE NAME "\n\t" \
+ ".type " UNDERSCORE NAME ",@object\n\t" \
+ ".p2align 2\n" \
+ UNDERSCORE NAME ":\n\t" \
+ ".previous")
+
+/* End of .ctor/.dtor sections that provides a list of constructors and
+ destructors to run. */
+
+FINI_SECTION_ZERO (".ctors", "\"aw\"", "__CTOR_END__");
+FINI_SECTION_ZERO (".dtors", "\"aw\"", "__DTOR_END__");
+
+/* End of .eh_frame section that provides all of the exception handling
+ tables. */
+
+FINI_SECTION_ZERO (".eh_frame", "\"aw\"", "__FRAME_END__");
+
+/* End of .rofixup section that provides a list of pointers that we
+ need to adjust. */
+
+FINI_SECTION (".rofixup", "\"a\"", "__ROFIXUP_END__");
diff --git a/contrib/gcc/config/frv/lib1funcs.asm b/contrib/gcc/config/frv/lib1funcs.asm
new file mode 100644
index 0000000..18a8142
--- /dev/null
+++ b/contrib/gcc/config/frv/lib1funcs.asm
@@ -0,0 +1,275 @@
+/* Library functions.
+ Copyright (C) 2000 Free Software Foundation, Inc.
+ Contributed by Red Hat, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software ; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation * either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY ; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <frv-asm.h>
+
+
+#ifdef L_cmpll
+/* icc0 = __cmpll (long long a, long long b) */
+
+ .file "_cmpll.s"
+ .globl EXT(__cmpll)
+ .type EXT(__cmpll),@function
+ .text
+ .p2align 4
+EXT(__cmpll):
+ cmp gr8, gr10, icc0
+ ckeq icc0, cc4
+ P(ccmp) gr9, gr11, cc4, 1
+ ret
+.Lend:
+ .size EXT(__cmpll),.Lend-EXT(__cmpll)
+#endif /* L_cmpll */
+
+#ifdef L_cmpf
+/* icc0 = __cmpf (float a, float b) */
+/* Note, because this function returns the result in ICC0, it means it can't
+ handle NaNs. */
+
+ .file "_cmpf.s"
+ .globl EXT(__cmpf)
+ .type EXT(__cmpf),@function
+ .text
+ .p2align 4
+EXT(__cmpf):
+#ifdef __FRV_HARD_FLOAT__ /* floating point instructions available */
+ movgf gr8, fr0
+ P(movgf) gr9, fr1
+ setlos #1, gr8
+ fcmps fr0, fr1, fcc0
+ P(fcklt) fcc0, cc0
+ fckeq fcc0, cc1
+ csub gr0, gr8, gr8, cc0, 1
+ cmov gr0, gr8, cc1, 1
+ cmpi gr8, 0, icc0
+ ret
+#else /* no floating point instructions available */
+ movsg lr, gr4
+ addi sp, #-16, sp
+ sti gr4, @(sp, 8)
+ st fp, @(sp, gr0)
+ mov sp, fp
+ call EXT(__cmpsf2)
+ cmpi gr8, #0, icc0
+ ldi @(sp, 8), gr4
+ movgs gr4, lr
+ ld @(sp,gr0), fp
+ addi sp, #16, sp
+ ret
+#endif
+.Lend:
+ .size EXT(__cmpf),.Lend-EXT(__cmpf)
+#endif
+
+#ifdef L_cmpd
+/* icc0 = __cmpd (double a, double b) */
+/* Note, because this function returns the result in ICC0, it means it can't
+ handle NaNs. */
+
+ .file "_cmpd.s"
+ .globl EXT(__cmpd)
+ .type EXT(__cmpd),@function
+ .text
+ .p2align 4
+EXT(__cmpd):
+ movsg lr, gr4
+ addi sp, #-16, sp
+ sti gr4, @(sp, 8)
+ st fp, @(sp, gr0)
+ mov sp, fp
+ call EXT(__cmpdf2)
+ cmpi gr8, #0, icc0
+ ldi @(sp, 8), gr4
+ movgs gr4, lr
+ ld @(sp,gr0), fp
+ addi sp, #16, sp
+ ret
+.Lend:
+ .size EXT(__cmpd),.Lend-EXT(__cmpd)
+#endif
+
+#ifdef L_addll
+/* gr8,gr9 = __addll (long long a, long long b) */
+/* Note, gcc will never call this function, but it is present in case an
+ ABI program calls it. */
+
+ .file "_addll.s"
+ .globl EXT(__addll)
+ .type EXT(__addll),@function
+ .text
+ .p2align
+EXT(__addll):
+ addcc gr9, gr11, gr9, icc0
+ addx gr8, gr10, gr8, icc0
+ ret
+.Lend:
+ .size EXT(__addll),.Lend-EXT(__addll)
+#endif
+
+#ifdef L_subll
+/* gr8,gr9 = __subll (long long a, long long b) */
+/* Note, gcc will never call this function, but it is present in case an
+ ABI program calls it. */
+
+ .file "_subll.s"
+ .globl EXT(__subll)
+ .type EXT(__subll),@function
+ .text
+ .p2align 4
+EXT(__subll):
+ subcc gr9, gr11, gr9, icc0
+ subx gr8, gr10, gr8, icc0
+ ret
+.Lend:
+ .size EXT(__subll),.Lend-EXT(__subll)
+#endif
+
+#ifdef L_andll
+/* gr8,gr9 = __andll (long long a, long long b) */
+/* Note, gcc will never call this function, but it is present in case an
+ ABI program calls it. */
+
+ .file "_andll.s"
+ .globl EXT(__andll)
+ .type EXT(__andll),@function
+ .text
+ .p2align 4
+EXT(__andll):
+ P(and) gr9, gr11, gr9
+ P2(and) gr8, gr10, gr8
+ ret
+.Lend:
+ .size EXT(__andll),.Lend-EXT(__andll)
+#endif
+
+#ifdef L_orll
+/* gr8,gr9 = __orll (long long a, long long b) */
+/* Note, gcc will never call this function, but it is present in case an
+ ABI program calls it. */
+
+ .file "_orll.s"
+ .globl EXT(__orll)
+ .type EXT(__orll),@function
+ .text
+ .p2align 4
+EXT(__orll):
+ P(or) gr9, gr11, gr9
+ P2(or) gr8, gr10, gr8
+ ret
+.Lend:
+ .size EXT(__orll),.Lend-EXT(__orll)
+#endif
+
+#ifdef L_xorll
+/* gr8,gr9 = __xorll (long long a, long long b) */
+/* Note, gcc will never call this function, but it is present in case an
+ ABI program calls it. */
+
+ .file "_xorll.s"
+ .globl EXT(__xorll)
+ .type EXT(__xorll),@function
+ .text
+ .p2align 4
+EXT(__xorll):
+ P(xor) gr9, gr11, gr9
+ P2(xor) gr8, gr10, gr8
+ ret
+.Lend:
+ .size EXT(__xorll),.Lend-EXT(__xorll)
+#endif
+
+#ifdef L_notll
+/* gr8,gr9 = __notll (long long a) */
+/* Note, gcc will never call this function, but it is present in case an
+ ABI program calls it. */
+
+ .file "_notll.s"
+ .globl EXT(__notll)
+ .type EXT(__notll),@function
+ .text
+ .p2align 4
+EXT(__notll):
+ P(not) gr9, gr9
+ P2(not) gr8, gr8
+ ret
+.Lend:
+ .size EXT(__notll),.Lend-EXT(__notll)
+#endif
+
+#ifdef L_cmov
+/* (void) __cmov (char *dest, const char *src, size_t len) */
+/*
+ * void __cmov (char *dest, const char *src, size_t len)
+ * {
+ * size_t i;
+ *
+ * if (dest < src || dest > src+len)
+ * {
+ * for (i = 0; i < len; i++)
+ * dest[i] = src[i];
+ * }
+ * else
+ * {
+ * while (len-- > 0)
+ * dest[len] = src[len];
+ * }
+ * }
+ */
+
+ .file "_cmov.s"
+ .globl EXT(__cmov)
+ .type EXT(__cmov),@function
+ .text
+ .p2align 4
+EXT(__cmov):
+ P(cmp) gr8, gr9, icc0
+ add gr9, gr10, gr4
+ P(cmp) gr8, gr4, icc1
+ bc icc0, 0, .Lfwd
+ bls icc1, 0, .Lback
+.Lfwd:
+ /* move bytes in a forward direction */
+ P(setlos) #0, gr5
+ cmp gr0, gr10, icc0
+ P(subi) gr9, #1, gr9
+ P2(subi) gr8, #1, gr8
+ bnc icc0, 0, .Lret
+.Lfloop:
+ /* forward byte move loop */
+ addi gr5, #1, gr5
+ P(ldsb) @(gr9, gr5), gr4
+ cmp gr5, gr10, icc0
+ P(stb) gr4, @(gr8, gr5)
+ bc icc0, 0, .Lfloop
+ ret
+.Lbloop:
+ /* backward byte move loop body */
+ ldsb @(gr9,gr10),gr4
+ stb gr4,@(gr8,gr10)
+.Lback:
+ P(cmpi) gr10, #0, icc0
+ addi gr10, #-1, gr10
+ bne icc0, 0, .Lbloop
+.Lret:
+ ret
+.Lend:
+ .size EXT(__cmov),.Lend-EXT(__cmov)
+#endif
diff --git a/contrib/gcc/config/frv/modi.c b/contrib/gcc/config/frv/modi.c
new file mode 100644
index 0000000..d5a91fc
--- /dev/null
+++ b/contrib/gcc/config/frv/modi.c
@@ -0,0 +1,4 @@
+int __modi (int a, int b)
+{
+ return a % b;
+}
diff --git a/contrib/gcc/config/frv/t-frv b/contrib/gcc/config/frv/t-frv
new file mode 100644
index 0000000..a92f63b
--- /dev/null
+++ b/contrib/gcc/config/frv/t-frv
@@ -0,0 +1,93 @@
+# Name of assembly file containing libgcc1 functions.
+# This entry must be present, but it can be empty if the target does
+# not need any assembler functions to support its code generation.
+#
+# Alternatively if assembler functions *are* needed then define the
+# entries below:
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIB1ASMSRC = frv/lib1funcs.asm
+LIB1ASMFUNCS = _cmpll _cmpf _cmpd _addll _subll _andll _orll _xorll _notll _cmov
+LIB2FUNCS_EXTRA = cmovh.c cmovw.c cmovd.c modi.c umodi.c uitof.c uitod.c ulltof.c ulltod.c
+
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+# If any special flags are necessary when building libgcc2 put them here.
+TARGET_LIBGCC2_CFLAGS =
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define FLOAT' > fp-bit.c
+ echo '#include "frv/frv-abi.h"' >> fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#include "frv/frv-abi.h"' > dp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
+cmovh.c: $(srcdir)/config/frv/cmovh.c
+ $(LN_S) $(srcdir)/config/frv/cmovh.c .
+
+cmovw.c: $(srcdir)/config/frv/cmovw.c
+ $(LN_S) $(srcdir)/config/frv/cmovw.c .
+
+cmovd.c: $(srcdir)/config/frv/cmovd.c
+ $(LN_S) $(srcdir)/config/frv/cmovd.c .
+
+modi.c: $(srcdir)/config/frv/modi.c
+ $(LN_S) $(srcdir)/config/frv/modi.c .
+
+umodi.c: $(srcdir)/config/frv/umodi.c
+ $(LN_S) $(srcdir)/config/frv/umodi.c .
+
+uitof.c: $(srcdir)/config/frv/uitof.c
+ $(LN_S) $(srcdir)/config/frv/uitof.c .
+
+uitod.c: $(srcdir)/config/frv/uitod.c
+ $(LN_S) $(srcdir)/config/frv/uitod.c .
+
+ulltof.c: $(srcdir)/config/frv/ulltof.c
+ $(LN_S) $(srcdir)/config/frv/ulltof.c .
+
+ulltod.c: $(srcdir)/config/frv/ulltod.c
+ $(LN_S) $(srcdir)/config/frv/ulltod.c .
+
+# Build frvbegin.o and frvend.o
+EXTRA_MULTILIB_PARTS=frvbegin.o frvend.o
+
+# Compile two additional files that are linked with every program
+# linked using GCC on systems using COFF or ELF, for the sake of C++
+# constructors.
+
+FRVSTUFF_CFLAGS = $(TARGET_LIBGCC2_CFLAGS)
+
+$(T)frvbegin$(objext): $(srcdir)/config/frv/frvbegin.c $(GCC_PASSES) \
+ $(CONFIG_H) defaults.h unwind-dw2-fde.h gbl-ctors.h
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) $(FRVSTUFF_CFLAGS) \
+ -c $(srcdir)/config/frv/frvbegin.c -o $(T)frvbegin$(objext)
+
+$(T)frvend$(objext): $(srcdir)/config/frv/frvend.c $(GCC_PASSES) \
+ $(CONFIG_H) defaults.h unwind-dw2-fde.h gbl-ctors.h
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) $(FRVSTUFF_CFLAGS) \
+ -c $(srcdir)/config/frv/frvend.c -o $(T)frvend$(objext)
+
+# Enable the following if multilibs are needed.
+# See gcc/genmultilib, gcc/gcc.texi and gcc/tm.texi for a
+# description of the options and their values.
+#
+#MULTILIB_OPTIONS = mcpu=fr500/mcpu=tomcat/mcpu=simple/mcpu=frv msoft-float mdword/mno-dword
+#MULTILIB_DIRNAMES = fr500 tomcat simple frv nof dw no-dw
+#MULTILIB_MATCHES = mcpu?simple=mcpu?fr300 mno-double=mcpu?fr500 mcpu?frv=mdouble
+#MULTILIB_EXCEPTIONS = *mcpu=simple/*msoft-float* *mcpu=frv/*msoft-float*
+#MULTILIB_EXTRA_OPTS = mlibrary-pic
+
+MULTILIB_OPTIONS = mcpu=frv/mcpu=fr400/mcpu=simple mno-pack mlibrary-pic
+MULTILIB_DIRNAMES = frv fr400 simple unpacked pic
+MULTILIB_MATCHES = mcpu?simple=mcpu?fr300 mlibrary-pic=fpic mlibrary-pic=fPIC
+MULTILIB_EXCEPTIONS = mcpu=frv/mno-pack* mcpu=simple/mno-pack*
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+EXTRA_HEADERS = $(srcdir)/config/frv/frv-asm.h $(srcdir)/config/frv/media.h
diff --git a/contrib/gcc/config/frv/uitod.c b/contrib/gcc/config/frv/uitod.c
new file mode 100644
index 0000000..14290ab
--- /dev/null
+++ b/contrib/gcc/config/frv/uitod.c
@@ -0,0 +1,4 @@
+double __uitod (unsigned int a)
+{
+ return a;
+}
diff --git a/contrib/gcc/config/frv/uitof.c b/contrib/gcc/config/frv/uitof.c
new file mode 100644
index 0000000..059bc7c
--- /dev/null
+++ b/contrib/gcc/config/frv/uitof.c
@@ -0,0 +1,4 @@
+float __uitof (unsigned int a)
+{
+ return a;
+}
diff --git a/contrib/gcc/config/frv/ulltod.c b/contrib/gcc/config/frv/ulltod.c
new file mode 100644
index 0000000..e6bee12
--- /dev/null
+++ b/contrib/gcc/config/frv/ulltod.c
@@ -0,0 +1,4 @@
+double __ulltod (unsigned long long a)
+{
+ return a;
+}
diff --git a/contrib/gcc/config/frv/ulltof.c b/contrib/gcc/config/frv/ulltof.c
new file mode 100644
index 0000000..29cdfd4
--- /dev/null
+++ b/contrib/gcc/config/frv/ulltof.c
@@ -0,0 +1,4 @@
+float __ulltof (unsigned long long a)
+{
+ return a;
+}
diff --git a/contrib/gcc/config/frv/umodi.c b/contrib/gcc/config/frv/umodi.c
new file mode 100644
index 0000000..4ffe5ad
--- /dev/null
+++ b/contrib/gcc/config/frv/umodi.c
@@ -0,0 +1,4 @@
+unsigned int __umodi (unsigned int a, unsigned int b)
+{
+ return a % b;
+}
diff --git a/contrib/gcc/config/gnu.h b/contrib/gcc/config/gnu.h
index 1f4b93a..f5f4184 100644
--- a/contrib/gcc/config/gnu.h
+++ b/contrib/gcc/config/gnu.h
@@ -13,6 +13,7 @@
#define STANDARD_INCLUDE_DIR "/include"
/* Implicit library calls should use memcpy, not bcopy, etc. */
+#undef TARGET_MEM_FUNCTIONS
#define TARGET_MEM_FUNCTIONS
/* The system headers under GNU are C++-aware. */
diff --git a/contrib/gcc/config/gofast.h b/contrib/gcc/config/gofast.h
index 4c3c0ea..84e9018 100644
--- a/contrib/gcc/config/gofast.h
+++ b/contrib/gcc/config/gofast.h
@@ -1,5 +1,5 @@
/* US Software GOFAST floating point library support.
- Copyright (C) 1994, 1998, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1998, 1999, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -43,6 +43,11 @@ Boston, MA 02111-1307, USA. */
neg_optab->handlers[(int) mode].libfunc = NULL_RTX; \
} while (0)
+/* GCC does not use fpcmp/dpcmp for gt or ge because its own
+ FP-emulation library returns +1 for both > and unord. So we leave
+ gt and ge unset, such that, instead of fpcmp(a,b) >[=], we generate
+ fpcmp(b,a) <[=] 0, which is unambiguous. For unord libfuncs, we
+ use our own functions, since GOFAST doesn't supply them. */
#define GOFAST_RENAME_LIBCALLS \
add_optab->handlers[(int) SFmode].libfunc = init_one_libfunc ("fpadd"); \
add_optab->handlers[(int) DFmode].libfunc = init_one_libfunc ("dpadd"); \
@@ -58,17 +63,24 @@ Boston, MA 02111-1307, USA. */
extendsfdf2_libfunc = init_one_libfunc ("fptodp"); \
truncdfsf2_libfunc = init_one_libfunc ("dptofp"); \
\
+ eqhf2_libfunc = NULL_RTX; \
+ nehf2_libfunc = NULL_RTX; \
+ gthf2_libfunc = NULL_RTX; \
+ gehf2_libfunc = NULL_RTX; \
+ lthf2_libfunc = NULL_RTX; \
+ lehf2_libfunc = NULL_RTX; \
+\
eqsf2_libfunc = init_one_libfunc ("fpcmp"); \
nesf2_libfunc = init_one_libfunc ("fpcmp"); \
- gtsf2_libfunc = init_one_libfunc ("fpcmp"); \
- gesf2_libfunc = init_one_libfunc ("fpcmp"); \
+ gtsf2_libfunc = NULL_RTX; \
+ gesf2_libfunc = NULL_RTX; \
ltsf2_libfunc = init_one_libfunc ("fpcmp"); \
lesf2_libfunc = init_one_libfunc ("fpcmp"); \
\
eqdf2_libfunc = init_one_libfunc ("dpcmp"); \
nedf2_libfunc = init_one_libfunc ("dpcmp"); \
- gtdf2_libfunc = init_one_libfunc ("dpcmp"); \
- gedf2_libfunc = init_one_libfunc ("dpcmp"); \
+ gtdf2_libfunc = NULL_RTX; \
+ gedf2_libfunc = NULL_RTX; \
ltdf2_libfunc = init_one_libfunc ("dpcmp"); \
ledf2_libfunc = init_one_libfunc ("dpcmp"); \
\
diff --git a/contrib/gcc/config/i386/athlon.md b/contrib/gcc/config/i386/athlon.md
new file mode 100644
index 0000000..548f2ad
--- /dev/null
+++ b/contrib/gcc/config/i386/athlon.md
@@ -0,0 +1,206 @@
+;; AMD Athlon Scheduling
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU CC.
+;;
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA. */
+(define_attr "athlon_decode" "direct,vector"
+ (cond [(eq_attr "type" "call,imul,idiv,other,multi,fcmov,fpspc,str,pop,cld,fcmov")
+ (const_string "vector")
+ (and (eq_attr "type" "push")
+ (match_operand 1 "memory_operand" ""))
+ (const_string "vector")
+ (and (eq_attr "type" "fmov")
+ (and (eq_attr "memory" "load,store")
+ (eq_attr "mode" "XF")))
+ (const_string "vector")]
+ (const_string "direct")))
+
+;; The Athlon does contain three pipelined FP units, three integer units and
+;; three address generation units.
+;;
+;; The predecode logic is determining boundaries of instructions in the 64
+;; byte cache line. So the cache line straddling problem of K6 might be issue
+;; here as well, but it is not noted in the documentation.
+;;
+;; Three DirectPath instructions decoders and only one VectorPath decoder
+;; is available. They can decode three DirectPath instructions or one VectorPath
+;; instruction per cycle.
+;; Decoded macro instructions are then passed to 72 entry instruction control
+;; unit, that passes
+;; it to the specialized integer (18 entry) and fp (36 entry) schedulers.
+;;
+;; The load/store queue unit is not attached to the schedulers but
+;; communicates with all the execution units separately instead.
+
+(define_function_unit "athlon_vectordec" 1 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "athlon_decode" "vector"))
+ 1 1)
+
+(define_function_unit "athlon_directdec" 3 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "athlon_decode" "direct"))
+ 1 1)
+
+(define_function_unit "athlon_vectordec" 1 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "athlon_decode" "direct"))
+ 1 1 [(eq_attr "athlon_decode" "vector")])
+
+(define_function_unit "athlon_ieu" 3 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "type" "alu1,negnot,alu,icmp,test,imov,imovx,lea,incdec,ishift,ishift1,rotate,rotate1,ibr,call,callv,icmov,cld,pop,setcc,push,pop"))
+ 1 1)
+
+(define_function_unit "athlon_ieu" 3 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "type" "str"))
+ 15 15)
+
+(define_function_unit "athlon_ieu" 3 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "type" "imul"))
+ 5 0)
+
+(define_function_unit "athlon_ieu" 3 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "type" "idiv"))
+ 42 0)
+
+(define_function_unit "athlon_muldiv" 1 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "type" "imul"))
+ 5 0)
+
+(define_function_unit "athlon_muldiv" 1 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "type" "idiv"))
+ 42 42)
+
+(define_attr "athlon_fpunits" "none,store,mul,add,muladd,any"
+ (cond [(eq_attr "type" "fop,fcmp,fistp")
+ (const_string "add")
+ (eq_attr "type" "fmul,fdiv,fpspc,fsgn,fcmov")
+ (const_string "mul")
+ (and (eq_attr "type" "fmov") (eq_attr "memory" "store,both"))
+ (const_string "store")
+ (and (eq_attr "type" "fmov") (eq_attr "memory" "load"))
+ (const_string "any")
+ (and (eq_attr "type" "fmov")
+ (ior (match_operand:SI 1 "register_operand" "")
+ (match_operand 1 "immediate_operand" "")))
+ (const_string "store")
+ (eq_attr "type" "fmov")
+ (const_string "muladd")]
+ (const_string "none")))
+
+;; We use latencies 1 for definitions. This is OK to model colisions
+;; in execution units. The real latencies are modeled in the "fp" pipeline.
+
+;; fsin, fcos: 96-192
+;; fsincos: 107-211
+;; fsqrt: 19 for SFmode, 27 for DFmode, 35 for XFmode.
+(define_function_unit "athlon_fp" 3 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "type" "fpspc"))
+ 100 1)
+
+;; 16 cycles for SFmode, 20 for DFmode and 24 for XFmode.
+(define_function_unit "athlon_fp" 3 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "type" "fdiv"))
+ 24 1)
+
+(define_function_unit "athlon_fp" 3 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "type" "fop,fmul,fistp"))
+ 4 1)
+
+;; XFmode loads are slow.
+;; XFmode store is slow too (8 cycles), but we don't need to model it, because
+;; there are no dependent instructions.
+
+(define_function_unit "athlon_fp" 3 0
+ (and (eq_attr "cpu" "athlon")
+ (and (eq_attr "type" "fmov")
+ (and (eq_attr "memory" "load")
+ (eq_attr "mode" "XF"))))
+ 10 1)
+
+(define_function_unit "athlon_fp" 3 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "type" "fmov,fsgn"))
+ 2 1)
+
+;; fcmp and ftst instructions
+(define_function_unit "athlon_fp" 3 0
+ (and (eq_attr "cpu" "athlon")
+ (and (eq_attr "type" "fcmp")
+ (eq_attr "athlon_decode" "direct")))
+ 3 1)
+
+;; fcmpi instructions.
+(define_function_unit "athlon_fp" 3 0
+ (and (eq_attr "cpu" "athlon")
+ (and (eq_attr "type" "fcmp")
+ (eq_attr "athlon_decode" "vector")))
+ 3 1)
+
+(define_function_unit "athlon_fp" 3 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "type" "fcmov"))
+ 7 1)
+
+(define_function_unit "athlon_fp_mul" 1 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "athlon_fpunits" "mul"))
+ 1 1)
+
+(define_function_unit "athlon_fp_add" 1 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "athlon_fpunits" "add"))
+ 1 1)
+
+(define_function_unit "athlon_fp_muladd" 2 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "athlon_fpunits" "muladd,mul,add"))
+ 1 1)
+
+(define_function_unit "athlon_fp_store" 1 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "athlon_fpunits" "store"))
+ 1 1)
+
+;; We don't need to model the Address Generation Unit, since we don't model
+;; the re-order buffer yet and thus we never schedule more than three operations
+;; at time. Later we may want to experiment with MD_SCHED macros modeling the
+;; decoders independently on the functional units.
+
+;(define_function_unit "athlon_agu" 3 0
+; (and (eq_attr "cpu" "athlon")
+; (and (eq_attr "memory" "!none")
+; (eq_attr "athlon_fpunits" "none")))
+; 1 1)
+
+;; Model load unit to avoid too long sequences of loads. We don't need to
+;; model store queue, since it is hardly going to be bottleneck.
+
+(define_function_unit "athlon_load" 2 0
+ (and (eq_attr "cpu" "athlon")
+ (eq_attr "memory" "load,both"))
+ 1 1)
+
diff --git a/contrib/gcc/config/i386/att.h b/contrib/gcc/config/i386/att.h
index f16a5ea..70ae164 100644
--- a/contrib/gcc/config/i386/att.h
+++ b/contrib/gcc/config/i386/att.h
@@ -1,5 +1,6 @@
/* Definitions for AT&T assembler syntax for the Intel 80386.
- Copyright (C) 1988, 1996, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1996, 2000, 2001, 2002
+ Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,10 +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 common aspects of all 386 Unix assemblers. */
-#include "i386/unix.h"
-
-#define TARGET_VERSION fprintf (stderr, " (80386, ATT syntax)");
/* Define the syntax of instructions and addresses. */
diff --git a/contrib/gcc/config/i386/beos-elf.h b/contrib/gcc/config/i386/beos-elf.h
index be51b4a..b84519f 100644
--- a/contrib/gcc/config/i386/beos-elf.h
+++ b/contrib/gcc/config/i386/beos-elf.h
@@ -1,5 +1,5 @@
/* Definitions for Intel x86 running BeOS
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,7 +19,6 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i386 BeOS/ELF)");
/* Change debugging to Dwarf2. */
@@ -41,21 +40,8 @@ Boston, MA 02111-1307, USA. */
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(FILE, LABELNO) \
-{ \
- if (flag_pic) \
- { \
- fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n", \
- LPREFIX, (LABELNO)); \
- fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \
- } \
- else \
- { \
- fprintf (FILE, "\tmovl $%sP%d,%%edx\n", LPREFIX, (LABELNO)); \
- fprintf (FILE, "\tcall mcount\n"); \
- } \
-}
+#undef MCOUNT_NAME
+#define MCOUNT_NAME "mcount"
#undef SIZE_TYPE
#define SIZE_TYPE "long unsigned int"
@@ -66,22 +52,28 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE
#define WCHAR_TYPE "short unsigned int"
-#undef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 1
-
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 16
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__ -D__BEOS__ -D__INTEL__ -D_X86_=1 \
--D__stdcall=__attribute__((__stdcall__)) \
--D__cdecl=__attribute__((__cdecl__)) \
--D__declspec(x)=__attribute__((x)) \
--Asystem=beos"
-
-#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu) %{!no-fPIC:%{!no-fpic:-D__PIC__ -D__pic__}}"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__ELF__"); \
+ builtin_define ("__BEOS__"); \
+ builtin_define ("__INTEL__"); \
+ builtin_define ("_X86_"); \
+ builtin_define ("__stdcall=__attribute__((__stdcall__))"); \
+ builtin_define ("__cdecl=__attribute__((__cdecl__))"); \
+ builtin_define ("__declspec(x)=__attribute__((x))"); \
+ builtin_assert ("system=beos"); \
+ if (flag_pic) \
+ { \
+ builtin_define ("__PIC__"); \
+ builtin_define ("__pic__"); \
+ } \
+ } \
+ while (0)
+
/* BeOS uses lots of multichars, so don't warn about them unless the
user explicitly asks for the warnings with -Wmultichar. Note that
CC1_SPEC is used for both cc1 and cc1plus. */
diff --git a/contrib/gcc/config/i386/biarch64.h b/contrib/gcc/config/i386/biarch64.h
index e2a5d91..2d34698 100644
--- a/contrib/gcc/config/i386/biarch64.h
+++ b/contrib/gcc/config/i386/biarch64.h
@@ -21,5 +21,5 @@ 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_64BIT_DEFAULT
-#define TARGET_BI_ARCH
+#define TARGET_64BIT_DEFAULT MASK_64BIT
+#define TARGET_BI_ARCH 1
diff --git a/contrib/gcc/config/i386/bsd.h b/contrib/gcc/config/i386/bsd.h
index c58db1b..69ad168 100644
--- a/contrib/gcc/config/i386/bsd.h
+++ b/contrib/gcc/config/i386/bsd.h
@@ -1,7 +1,7 @@
/* Definitions for BSD assembler syntax for Intel 386
(actually AT&T syntax for insns and operands,
adapted to BSD conventions for symbol names and debugging.)
- Copyright (C) 1988, 1996, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1996, 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,23 +20,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. */
-/* Include common aspects of all 386 Unix assemblers. */
-#include "i386/unix.h"
-
/* Use the Sequent Symmetry assembler syntax. */
-
-#define TARGET_VERSION fprintf (stderr, " (80386, BSD syntax)");
/* Define the syntax of pseudo-ops, labels and comments. */
/* Prefix for internally generated assembler labels. If we aren't using
underscores, we are using prefix `.'s to identify labels that should
be ignored, as in `i386/gas.h' --karl@cs.umb.edu */
-#ifdef NO_UNDERSCORES
-#define LPREFIX ".L"
-#else
+
#define LPREFIX "L"
-#endif /* not NO_UNDERSCORES */
/* Assembler pseudos to introduce constants of various size. */
@@ -93,32 +85,18 @@ Boston, MA 02111-1307, USA. */
PREFIX is the class of label and NUM is the number within the class.
This is suitable for output with `assemble_name'. */
-#ifdef NO_UNDERSCORES
-#define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \
- sprintf ((BUF), "*.%s%ld", (PREFIX), (long)(NUMBER))
-#else
#define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \
sprintf ((BUF), "*%s%ld", (PREFIX), (long)(NUMBER))
-#endif
/* This is how to output an internal numbered label where
PREFIX is the class of label and NUM is the number within the class. */
-#ifdef NO_UNDERSCORES
-#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
- fprintf (FILE, ".%s%d:\n", PREFIX, NUM)
-#else
#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
fprintf (FILE, "%s%d:\n", PREFIX, NUM)
-#endif
/* The prefix to add to user-visible assembler symbols. */
-#ifdef NO_UNDERSCORES
-#define USER_LABEL_PREFIX ""
-#else
#define USER_LABEL_PREFIX "_"
-#endif /* not NO_UNDERSCORES */
/* Sequent has some changes in the format of DBX symbols. */
#define DBX_NO_XREFS 1
diff --git a/contrib/gcc/config/i386/crtdll.h b/contrib/gcc/config/i386/crtdll.h
index f3eae84..dab60c1 100644
--- a/contrib/gcc/config/i386/crtdll.h
+++ b/contrib/gcc/config/i386/crtdll.h
@@ -20,10 +20,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. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D_WIN32 -DWIN32 \
- -D__MINGW32__=0.2 -DWINNT -D_X86_=1 \
- -Asystem=winnt"
+#undef EXTRA_OS_CPP_BUILTINS
+#define EXTRA_OS_CPP_BUILTINS() \
+ do { builtin_define ("__MINGW32__=0.2"); } while (0)
#undef LIBGCC_SPEC
#define LIBGCC_SPEC \
diff --git a/contrib/gcc/config/i386/cygwin.h b/contrib/gcc/config/i386/cygwin.h
index a0b8834..03e372e 100644
--- a/contrib/gcc/config/i386/cygwin.h
+++ b/contrib/gcc/config/i386/cygwin.h
@@ -1,6 +1,6 @@
/* Operating system specific defines to be used when targeting GCC for
hosting on Windows32, using a Unix style C library and tools.
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,50 +20,57 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#define YES_UNDERSCORES
-
-#define DBX_DEBUGGING_INFO
-#define SDB_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
+#define SDB_DEBUGGING_INFO 1
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+#define TARGET_VERSION fprintf (stderr, " (x86 Cygwin)");
#define TARGET_EXECUTABLE_SUFFIX ".exe"
#include <stdio.h>
+#include "i386/i386.h"
+#include "i386/unix.h"
+#include "i386/bsd.h"
#include "i386/gas.h"
#include "dbxcoff.h"
-/* Augment TARGET_SWITCHES with the cygwin/no-cygwin options. */
-#define MASK_WIN32 0x40000000 /* Use -lming32 interface */
-#define MASK_CYGWIN 0x20000000 /* Use -lcygwin interface */
-#define MASK_WINDOWS 0x10000000 /* Use windows interface */
-#define MASK_DLL 0x08000000 /* Use dll interface */
-#define MASK_NOP_FUN_DLLIMPORT 0x20000 /* Ignore dllimport for functions */
-
-#define TARGET_WIN32 (target_flags & MASK_WIN32)
-#define TARGET_CYGWIN (target_flags & MASK_CYGWIN)
-#define TARGET_WINDOWS (target_flags & MASK_WINDOWS)
-#define TARGET_DLL (target_flags & MASK_DLL)
+/* Masks for subtarget switches used by other files. */
+#define MASK_NOP_FUN_DLLIMPORT 0x08000000 /* Ignore dllimport for functions */
+
+/* Used in winnt.c. */
#define TARGET_NOP_FUN_DLLIMPORT (target_flags & MASK_NOP_FUN_DLLIMPORT)
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
-{ "cygwin", MASK_CYGWIN, \
- N_("Use the Cygwin interface") }, \
-{ "no-cygwin", MASK_WIN32, \
- N_("Use the Mingw32 interface") }, \
-{ "windows", MASK_WINDOWS, N_("Create GUI application") }, \
-{ "no-win32", -MASK_WIN32, N_("Don't set Windows defines") },\
-{ "win32", 0, N_("Set Windows defines") }, \
-{ "console", -MASK_WINDOWS, \
- N_("Create console application") }, \
-{ "dll", MASK_DLL, N_("Generate code for a DLL") }, \
-{ "nop-fun-dllimport", MASK_NOP_FUN_DLLIMPORT, \
- N_("Ignore dllimport for functions") }, \
-{ "no-nop-fun-dllimport", -MASK_NOP_FUN_DLLIMPORT, "" }, \
+{ "cygwin", 0, N_("Use the Cygwin interface") }, \
+{ "no-cygwin", 0, N_("Use the Mingw32 interface") }, \
+{ "windows", 0, N_("Create GUI application") }, \
+{ "no-win32", 0, N_("Don't set Windows defines") }, \
+{ "win32", 0, N_("Set Windows defines") }, \
+{ "console", 0, N_("Create console application") },\
+{ "dll", 0, N_("Generate code for a DLL") }, \
+{ "nop-fun-dllimport", MASK_NOP_FUN_DLLIMPORT, \
+ N_("Ignore dllimport for functions") }, \
+{ "no-nop-fun-dllimport", -MASK_NOP_FUN_DLLIMPORT, "" }, \
{ "threads", 0, N_("Use Mingw-specific thread support") },
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D_X86_=1 -Asystem=winnt"
+#define MAYBE_UWIN_CPP_BUILTINS() /* Nothing. */
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("_X86_=1"); \
+ builtin_assert ("system=winnt"); \
+ builtin_define ("__stdcall=__attribute__((__stdcall__))"); \
+ builtin_define ("__cdecl=__attribute__((__cdecl__))"); \
+ builtin_define ("__declspec(x)=__attribute__((x))"); \
+ if (!flag_iso) \
+ { \
+ builtin_define ("_stdcall=__attribute__((__stdcall__))"); \
+ builtin_define ("_cdecl=__attribute__((__cdecl__))"); \
+ } \
+ MAYBE_UWIN_CPP_BUILTINS (); \
+ } \
+ while (0)
#ifdef CROSS_COMPILE
#define CYGWIN_INCLUDES "%{!nostdinc:-idirafter " CYGWIN_CROSS_DIR "/include}"
@@ -104,13 +111,7 @@ Boston, MA 02111-1307, USA. */
existing args. */
#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE} \
- -D__stdcall=__attribute__((__stdcall__)) \
- -D__cdecl=__attribute__((__cdecl__)) \
- %{!ansi:-D_stdcall=__attribute__((__stdcall__)) \
- -D_cdecl=__attribute__((__cdecl__))} \
- -D__declspec(x)=__attribute__((x)) \
- -D__i386__ -D__i386 \
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} \
%{mno-win32:%{mno-cygwin: %emno-cygwin and mno-win32 are not compatible}} \
%{mno-cygwin:-D__MSVCRT__ -D__MINGW32__ %{mthreads:-D_MT} "\
MINGW_INCLUDES "} \
@@ -133,7 +134,8 @@ Boston, MA 02111-1307, USA. */
by calling the init function from the prologue. */
#undef LIBGCC_SPEC
-#define LIBGCC_SPEC "%{mno-cygwin: %{mthreads:-lmingwthrd} -lmingw32} -lgcc %{mno-cygwin:-lmoldname -lmsvcrt}"
+#define LIBGCC_SPEC "%{mno-cygwin: %{mthreads:-lmingwthrd} -lmingw32} \
+ -lgcc %{mno-cygwin:-lmoldname -lmingwex -lmsvcrt}"
/* This macro defines names of additional specifications to put in the specs
that can be used in various specifications like CC1_SPEC. Its definition
@@ -179,7 +181,6 @@ Boston, MA 02111-1307, USA. */
#define SIZE_TYPE "unsigned int"
#define PTRDIFF_TYPE "int"
-#define WCHAR_UNSIGNED 1
#define WCHAR_TYPE_SIZE 16
#define WCHAR_TYPE "short unsigned int"
@@ -189,19 +190,6 @@ Boston, MA 02111-1307, USA. */
union tree_node;
#define TREE union tree_node *
-
-/* Used to implement dllexport overriding dllimport semantics. It's also used
- to handle vtables - the first pass won't do anything because
- DECL_CONTEXT (DECL) will be 0 so i386_pe_dll{ex,im}port_p will return 0.
- It's also used to handle dllimport override semantics. */
-#if 0
-#define REDO_SECTION_INFO_P(DECL) \
- ((DECL_ATTRIBUTES (DECL) != NULL_TREE) \
- || (TREE_CODE (DECL) == VAR_DECL && DECL_VIRTUAL_P (DECL)))
-#else
-#define REDO_SECTION_INFO_P(DECL) 1
-#endif
-
#undef EXTRA_SECTIONS
#define EXTRA_SECTIONS in_drectve
@@ -277,47 +265,16 @@ do { \
section and we need to set DECL_SECTION_NAME so we do that here.
Note that we can be called twice on the same decl. */
-extern void i386_pe_encode_section_info PARAMS ((TREE));
-
-#ifdef ENCODE_SECTION_INFO
-#undef ENCODE_SECTION_INFO
-#endif
-#define ENCODE_SECTION_INFO(DECL) i386_pe_encode_section_info (DECL)
-
-/* Utility used only in this file. */
-#define I386_PE_STRIP_ENCODING(SYM_NAME) \
- ((SYM_NAME) + ((SYM_NAME)[0] == '@' \
- ? ((SYM_NAME)[3] == '*' ? 4 : 3) : 0) \
- + ((SYM_NAME)[0] == '*' ? 1 : 0))
-
-/* This macro gets just the user-specified name
- out of the string in a SYMBOL_REF. Discard
- trailing @[NUM] encoded by ENCODE_SECTION_INFO. */
-#undef STRIP_NAME_ENCODING
-#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
-do { \
- const char *_p; \
- const char *_name = I386_PE_STRIP_ENCODING (SYMBOL_NAME); \
- for (_p = _name; *_p && *_p != '@'; ++_p) \
- ; \
- if (*_p == '@') \
- { \
- int _len = _p - _name; \
- char *_new_name = (char *) alloca (_len + 1); \
- strncpy (_new_name, _name, _len); \
- _new_name[_len] = '\0'; \
- (VAR) = _new_name; \
- } \
- else \
- (VAR) = _name; \
-} while (0)
-
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING i386_pe_strip_name_encoding_full
/* Output a reference to a label. */
#undef ASM_OUTPUT_LABELREF
#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
fprintf (STREAM, "%s%s", USER_LABEL_PREFIX, \
- I386_PE_STRIP_ENCODING (NAME)) \
+ i386_pe_strip_name_encoding (NAME)) \
/* Output a common block. */
#undef ASM_OUTPUT_COMMON
@@ -350,11 +307,13 @@ do { \
#define CHECK_STACK_LIMIT 4000
/* By default, target has a 80387, uses IEEE compatible arithmetic,
- and returns float values in the 387 and needs stack probes */
-#undef TARGET_SUBTARGET_DEFAULT
+ returns float values in the 387 and needs stack probes.
+ We also align doubles to 64-bits for MSVC default compatibility. */
+#undef TARGET_SUBTARGET_DEFAULT
#define TARGET_SUBTARGET_DEFAULT \
- (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE)
+ (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE \
+ | MASK_ALIGN_DOUBLE)
/* This is how to output an assembler line
that says to advance the location counter
@@ -371,7 +330,7 @@ do { \
#define MULTIPLE_SYMBOL_SPACES
extern void i386_pe_unique_section PARAMS ((TREE, int));
-#define UNIQUE_SECTION(DECL,RELOC) i386_pe_unique_section (DECL, RELOC)
+#define TARGET_ASM_UNIQUE_SECTION i386_pe_unique_section
#define SUPPORTS_ONE_ONLY 1
@@ -423,9 +382,9 @@ extern void i386_pe_unique_section PARAMS ((TREE, int));
#undef ASM_COMMENT_START
#define ASM_COMMENT_START " #"
-/* DWARF2 Unwinding doesn't work with exception handling yet. To make it
- work, we need to build a libgcc_s.dll, and dcrt0.o should be changed to
- call __register_frame_info/__deregister_frame_info. */
+/* DWARF2 Unwinding doesn't work with exception handling yet. To make
+ it work, we need to build a libgcc_s.dll, and dcrt0.o should be
+ changed to call __register_frame_info/__deregister_frame_info. */
#define DWARF2_UNWIND_INFO 0
/* Don't assume anything about the header files. */
@@ -441,6 +400,15 @@ extern void i386_pe_unique_section PARAMS ((TREE, int));
const0_rtx)); \
}
+/* Java Native Interface (JNI) methods on Win32 are invoked using the
+ stdcall calling convention. */
+#undef MODIFY_JNI_METHOD_CALL
+#define MODIFY_JNI_METHOD_CALL(MDECL) \
+ build_type_attribute_variant ((MDECL), \
+ build_tree_list (get_identifier ("stdcall"), \
+ NULL))
+
+
/* External function declarations. */
extern void i386_pe_record_external_function PARAMS ((const char *));
@@ -462,7 +430,7 @@ extern int i386_pe_dllimport_name_p PARAMS ((const char *));
#undef BIGGEST_FIELD_ALIGNMENT
#define BIGGEST_FIELD_ALIGNMENT 64
-/* A bitfield declared as `int' forces `int' alignment for the struct. */
+/* A bit-field declared as `int' forces `int' alignment for the struct. */
#undef PCC_BITFIELD_TYPE_MATTERS
#define PCC_BITFIELD_TYPE_MATTERS 1
#define GROUP_BITFIELDS_BY_ALIGN TYPE_NATIVE(rec)
diff --git a/contrib/gcc/config/i386/darwin.h b/contrib/gcc/config/i386/darwin.h
new file mode 100644
index 0000000..55c29fd
--- /dev/null
+++ b/contrib/gcc/config/i386/darwin.h
@@ -0,0 +1,120 @@
+/* Target definitions for x86 running Darwin.
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Contributed by Apple Computer Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Enable Mach-O bits in generic x86 code. */
+#undef TARGET_MACHO
+#define TARGET_MACHO 1
+
+#define TARGET_VERSION fprintf (stderr, " (i386 Darwin)");
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__i386__"); \
+ builtin_define ("__LITTLE_ENDIAN__"); \
+ builtin_define ("__MACH__"); \
+ builtin_define ("__APPLE__"); \
+ } \
+ while (0)
+
+/* We want -fPIC by default, unless we're using -static to compile for
+ the kernel or some such. */
+
+#undef CC1_SPEC
+#define CC1_SPEC "%{!static:-fPIC}"
+
+/* The Darwin assembler mostly follows AT&T syntax. */
+#undef ASSEMBLER_DIALECT
+#define ASSEMBLER_DIALECT ASM_ATT
+
+/* Define macro used to output shift-double opcodes when the shift
+ 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 SHIFT_DOUBLE_OMITS_COUNT 0
+
+/* Define the syntax of pseudo-ops, labels and comments. */
+
+/* String containing the assembler's comment-starter. */
+
+#define ASM_COMMENT_START "#"
+
+/* By default, target has a 80387, uses IEEE compatible arithmetic,
+ and returns float values in the 387. */
+
+#define TARGET_SUBTARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS)
+
+/* TARGET_DEEP_BRANCH_PREDICTION is incompatible with Mach-O PIC. */
+
+#undef TARGET_DEEP_BRANCH_PREDICTION
+#define TARGET_DEEP_BRANCH_PREDICTION 0
+
+/* Define the syntax of pseudo-ops, labels and comments. */
+
+#define LPREFIX "L"
+
+/* Assembler pseudos to introduce constants of various size. */
+
+#define ASM_BYTE_OP "\t.byte\t"
+#define ASM_SHORT "\t.word\t"
+#define ASM_LONG "\t.long\t"
+/* Darwin as doesn't do ".quad". */
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ do { if ((LOG) != 0) \
+ { \
+ if (in_text_section ()) \
+ fprintf (FILE, "\t%s %d,0x90\n", ALIGN_ASM_OP, (LOG)); \
+ else \
+ fprintf (FILE, "\t%s %d\n", ALIGN_ASM_OP, (LOG)); \
+ } \
+ } while (0)
+
+/* This says how to output an assembler line
+ to define a global common symbol. */
+
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* This says how to output an assembler line
+ to define a local common symbol. */
+
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs (".lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (ROUNDED)))
+
+/* Darwin profiling -- call mcount. */
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ do { \
+ if (MACHOPIC_INDIRECT) \
+ { \
+ const char *name = machopic_stub_name ("*mcount"); \
+ fprintf (FILE, "\tcall %s\n", name+1); /* skip '&' */ \
+ machopic_validate_stub_or_non_lazy_ptr (name, /*stub:*/1); \
+ } \
+ else fprintf (FILE, "\tcall mcount\n"); \
+ } while (0)
diff --git a/contrib/gcc/config/i386/djgpp.h b/contrib/gcc/config/i386/djgpp.h
index 600a11e..6780780 100644
--- a/contrib/gcc/config/i386/djgpp.h
+++ b/contrib/gcc/config/i386/djgpp.h
@@ -1,5 +1,6 @@
/* Configuration for an i386 running MS-DOS with DJGPP.
- Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
+ Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,21 +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. */
-#include "dbxcoff.h"
-
/* Support generation of DWARF2 debugging info. */
-#define DWARF2_DEBUGGING_INFO
+#define DWARF2_DEBUGGING_INFO 1
/* Don't assume anything about the header files. */
#define NO_IMPLICIT_EXTERN_C
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
/* Enable parsing of #pragma pack(push,<n>) and #pragma pack(pop). */
#define HANDLE_PRAGMA_PACK_PUSH_POP 1
-#define YES_UNDERSCORES
-
+#include "i386/unix.h"
+#include "i386/bsd.h"
#include "i386/gas.h"
/* If defined, a C expression whose value is a string containing the
@@ -83,13 +82,18 @@ Boston, MA 02111-1307, USA. */
(((NAME)[0] == '/') || ((NAME)[0] == '\\') || \
(((NAME)[0] >= 'A') && ((NAME)[0] <= 'z') && ((NAME)[1] == ':')))
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__MSDOS__ -D__GO32__ -Asystem=msdos"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("MSDOS"); \
+ builtin_define_std ("GO32"); \
+ builtin_assert ("system=msdos"); \
+ } \
+ while (0)
/* Include <sys/version.h> so __DJGPP__ and __DJGPP_MINOR__ are defined. */
#undef CPP_SPEC
-#define CPP_SPEC "-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE} \
- %{!ansi:%{!std=c*:%{!std=i*:-DMSDOS}}} %{!ansi:%{!std=c*:%{!std=i*:-DGO32}}} \
+#define CPP_SPEC "-remap %{posix:-D_POSIX_SOURCE} \
-imacros %s../include/sys/version.h"
/* We need to override link_command_spec in gcc.c so support -Tdjgpp.djl.
@@ -132,6 +136,8 @@ Boston, MA 02111-1307, USA. */
#undef ASM_FILE_START
#define ASM_FILE_START(FILE) \
do { \
+ if (ix86_asm_dialect == ASM_INTEL) \
+ fputs ("\t.intel_syntax\n", FILE); \
output_file_directive (FILE, main_input_filename); \
} while (0)
@@ -160,9 +166,6 @@ Boston, MA 02111-1307, USA. */
/* Definitions for types and sizes. Wide characters are 16-bits long so
Win32 compiler add-ons will be wide character compatible. */
-#undef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 1
-
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 16
@@ -186,6 +189,8 @@ Boston, MA 02111-1307, USA. */
#undef MASK_BNU210
#define MASK_BNU210 (0x40000000)
+#define TARGET_VERSION fprintf (stderr, " (80386, MS-DOS DJGPP)");
+
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
{ "no-bnu210", -MASK_BNU210, "Ignored (obsolete)" }, \
@@ -206,37 +211,3 @@ while (0)
/* Support for C++ templates. */
#undef MAKE_DECL_ONE_ONLY
#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
-
-#undef UNIQUE_SECTION
-#define UNIQUE_SECTION(DECL,RELOC) \
-do { \
- int len; \
- const char *name, *prefix; \
- char *string; \
- \
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
- /* Strip off any encoding in fnname. */ \
- STRIP_NAME_ENCODING (name, name); \
- \
- if (! DECL_ONE_ONLY (DECL)) \
- { \
- if (TREE_CODE (DECL) == FUNCTION_DECL) \
- prefix = ".text."; \
- else if (DECL_READONLY_SECTION (DECL, RELOC)) \
- prefix = ".rodata."; \
- else \
- prefix = ".data."; \
- } \
- else if (TREE_CODE (DECL) == FUNCTION_DECL) \
- prefix = ".gnu.linkonce.t."; \
- else if (DECL_READONLY_SECTION (DECL, RELOC)) \
- prefix = ".gnu.linkonce.r."; \
- else \
- prefix = ".gnu.linkonce.d."; \
- \
- len = strlen (name) + strlen (prefix); \
- string = alloca (len + 1); \
- sprintf (string, "%s%s", prefix, name); \
- \
- DECL_SECTION_NAME (DECL) = build_string (len, string); \
-} while (0)
diff --git a/contrib/gcc/config/i386/freebsd-aout.h b/contrib/gcc/config/i386/freebsd-aout.h
index 0a3c6d7..85e2703 100644
--- a/contrib/gcc/config/i386/freebsd-aout.h
+++ b/contrib/gcc/config/i386/freebsd-aout.h
@@ -1,8 +1,9 @@
/* Definitions of target machine for GNU compiler for Intel 80386
running FreeBSD.
- Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2002 Free Software
- Foundation, Inc.
+ Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2002, 2003
+ Free Software Foundation, Inc.
Contributed by Poul-Henning Kamp <phk@login.dkuug.dk>
+ Continued development by David O'Brien <obrien@NUXI.org>
This file is part of GNU CC.
@@ -21,14 +22,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. */
-/* This is tested by i386gas.h. */
-#define YES_UNDERSCORES
-
/* Don't assume anything about the header files. */
#define NO_IMPLICIT_EXTERN_C
-#include "i386/gstabs.h"
-
/* This goes away when the math-emulator is fixed */
#undef TARGET_SUBTARGET_DEFAULT
#define TARGET_SUBTARGET_DEFAULT \
@@ -41,9 +37,16 @@ Boston, MA 02111-1307, USA. */
defaults.h works. */
#undef ASM_PREFERRED_EH_DATA_FORMAT
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dunix -D__FreeBSD__\
- -Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("unix"); \
+ builtin_define ("__FreeBSD__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=bsd"); \
+ builtin_assert ("system=FreeBSD"); \
+ } \
+ while (0)
/* Like the default, except no -lg. */
#define LIB_SPEC "%{!shared:%{!pg:-lc}%{pg:-lc_p}}"
@@ -57,8 +60,6 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE
#define WCHAR_TYPE "int"
-#define WCHAR_UNSIGNED 0
-
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
@@ -93,22 +94,13 @@ Boston, MA 02111-1307, USA. */
/* Profiling routines, partially copied from i386/osfrose.h. */
-/* Redefine this to use %eax instead of %edx. */
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(FILE, LABELNO) \
-{ \
- if (flag_pic) \
- { \
- fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%eax\n", \
- LPREFIX, (LABELNO)); \
- fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \
- } \
- else \
- { \
- fprintf (FILE, "\tmovl $%sP%d,%%eax\n", LPREFIX, (LABELNO)); \
- fprintf (FILE, "\tcall mcount\n"); \
- } \
-}
+/* Tell final.c that we don't need a label passed to mcount. */
+#define NO_PROFILE_COUNTERS 1
+
+#undef MCOUNT_NAME
+#define MCOUNT_NAME "mcount"
+#undef PROFILE_COUNT_REGISTER
+#define PROFILE_COUNT_REGISTER "eax"
/*
* Some imports from svr4.h in support of shared libraries.
@@ -123,6 +115,7 @@ Boston, MA 02111-1307, USA. */
#define TYPE_ASM_OP "\t.type\t"
#define SIZE_ASM_OP "\t.size\t"
+#define SET_ASM_OP "\t.set\t"
/* The following macro defines the format used to output the second
operand of the .type assembler directive. Different svr4 assemblers
@@ -132,6 +125,12 @@ Boston, MA 02111-1307, USA. */
#define TYPE_OPERAND_FMT "@%s"
+#define HANDLE_SYSV_PRAGMA 1
+
+#define ASM_WEAKEN_LABEL(FILE,NAME) \
+ do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
+ fputc ('\n', FILE); } while (0)
+
/* Write the extra assembler code needed to declare a function's result.
Most svr4 assemblers don't require any special declaration of the
result value, but there are exceptions. */
@@ -149,36 +148,36 @@ Boston, MA 02111-1307, USA. */
Some svr4 assemblers need to also have something extra said about the
function's return value. We allow for that here. */
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
- do { \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
- putc ('\n', FILE); \
- ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
- ASM_OUTPUT_LABEL(FILE, NAME); \
- } while (0)
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
+ ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+ } \
+ while (0)
/* Write the extra assembler code needed to declare an object properly. */
-#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
- do { \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
- putc ('\n', FILE); \
- size_directive_output = 0; \
- if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
- { \
- size_directive_output = 1; \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \
- } \
- ASM_OUTPUT_LABEL(FILE, NAME); \
- } while (0)
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ HOST_WIDE_INT size; \
+ \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
+ \
+ size_directive_output = 0; \
+ if (!flag_inhibit_size_directive \
+ && (DECL) && DECL_SIZE (DECL)) \
+ { \
+ size_directive_output = 1; \
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \
+ } \
+ \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+ } \
+ while (0)
/* Output the size directive for a decl in rest_of_decl_compilation
in the case where we did not do so before the initializer.
@@ -189,37 +188,24 @@ Boston, MA 02111-1307, USA. */
#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
do { \
const char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
+ HOST_WIDE_INT size; \
if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
&& ! AT_END && TOP_LEVEL \
&& DECL_INITIAL (DECL) == error_mark_node \
&& !size_directive_output) \
{ \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, name); \
- fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL)));\
- } \
+ size_directive_output = 1; \
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, name, size); \
+ } \
} while (0)
-
/* This is how to declare the size of a function. */
#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
do { \
if (!flag_inhibit_size_directive) \
- { \
- char label[256]; \
- static int labelno; \
- labelno++; \
- ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \
- ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, (FNAME)); \
- fprintf (FILE, ","); \
- assemble_name (FILE, label); \
- fprintf (FILE, "-"); \
- assemble_name (FILE, (FNAME)); \
- putc ('\n', FILE); \
- } \
+ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
} while (0)
#define ASM_SPEC " %| %{fpic:-k} %{fPIC:-k}"
diff --git a/contrib/gcc/config/i386/freebsd.h b/contrib/gcc/config/i386/freebsd.h
index 274260b..603e3ac 100644
--- a/contrib/gcc/config/i386/freebsd.h
+++ b/contrib/gcc/config/i386/freebsd.h
@@ -23,23 +23,22 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i386 FreeBSD/ELF)");
/* Override the default comment-starter of "/". */
-#undef ASM_COMMENT_START
+#undef ASM_COMMENT_START
#define ASM_COMMENT_START "#"
-#undef ASM_APP_ON
+#undef ASM_APP_ON
#define ASM_APP_ON "#APP\n"
-#undef ASM_APP_OFF
+#undef ASM_APP_OFF
#define ASM_APP_OFF "#NO_APP\n"
-#undef SET_ASM_OP
+#undef SET_ASM_OP
#define SET_ASM_OP "\t.set\t"
-#undef DBX_REGISTER_NUMBER
+#undef DBX_REGISTER_NUMBER
#define DBX_REGISTER_NUMBER(n) \
(TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n])
@@ -48,24 +47,18 @@ Boston, MA 02111-1307, USA. */
/* Tell final.c that we don't need a label passed to mcount. */
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(FILE, LABELNO) \
-{ \
- if (flag_pic) \
- fprintf ((FILE), "\tcall *.mcount@GOT(%%ebx)\n"); \
- else \
- fprintf ((FILE), "\tcall .mcount\n"); \
-}
+#undef MCOUNT_NAME
+#define MCOUNT_NAME ".mcount"
/* Make gcc agree with <machine/ansi.h>. */
-#undef SIZE_TYPE
+#undef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
-#undef PTRDIFF_TYPE
+#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE "int"
-#undef WCHAR_TYPE_SIZE
+#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
/* Provide a STARTFILE_SPEC appropriate for FreeBSD. Here we add
@@ -139,3 +132,13 @@ Boston, MA 02111-1307, USA. */
#undef DEFAULT_PCC_STRUCT_RETURN
#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* FreeBSD sets the rounding precision of the FPU to 53 bits. Let the
+ compiler get the contents of <float.h> and std::numeric_limits correct. */
+#define SUBTARGET_OVERRIDE_OPTIONS \
+ do { \
+ real_format_for_mode[XFmode - QFmode] \
+ = &ieee_extended_intel_96_round_53_format; \
+ real_format_for_mode[TFmode - QFmode] \
+ = &ieee_extended_intel_96_round_53_format; \
+ } while (0)
diff --git a/contrib/gcc/config/i386/freebsd64.h b/contrib/gcc/config/i386/freebsd64.h
index ebd6618..12ca062 100644
--- a/contrib/gcc/config/i386/freebsd64.h
+++ b/contrib/gcc/config/i386/freebsd64.h
@@ -20,7 +20,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#undef TARGET_VERSION
+#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (FreeBSD/x86-64 ELF)");
/* Provide a LINK_SPEC appropriate for the FreeBSD/x86-64 ELF target.
@@ -29,8 +29,7 @@ Boston, MA 02111-1307, USA. */
#undef LINK_SPEC
#define LINK_SPEC "\
- %{!m32:-m elf_x86_64} \
- %{m32:-m elf_i386} \
+ %{m32:-m elf_i386_fbsd} \
%{Wl,*:%*} \
%{v:-V} \
%{assert*} %{R*} %{rpath*} %{defsym*} \
diff --git a/contrib/gcc/config/i386/gas.h b/contrib/gcc/config/i386/gas.h
index 6c01b07..075d749 100644
--- a/contrib/gcc/config/i386/gas.h
+++ b/contrib/gcc/config/i386/gas.h
@@ -1,5 +1,5 @@
/* Definitions for Intel 386 using GAS.
- Copyright (C) 1988, 1993, 1994, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1993, 1994, 1996, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -21,13 +21,6 @@ Boston, MA 02111-1307, USA. */
/* Note that i386/seq-gas.h is a GAS configuration that does not use this
file. */
-#include "i386/i386.h"
-
-#ifndef YES_UNDERSCORES
-/* Define this now, because i386/bsd.h tests it. */
-#define NO_UNDERSCORES
-#endif
-
/* Use the bsd assembler syntax. */
/* we need to do this because gas is really a bsd style assembler,
* and so doesn't work well this these att-isms:
@@ -44,24 +37,13 @@ Boston, MA 02111-1307, USA. */
* people who want both form will have to compile twice.
*/
-#include "i386/bsd.h"
-
/* these come from i386/bsd.h, but are specific to sequent */
#undef DBX_NO_XREFS
#undef DBX_CONTIN_LENGTH
/* Ask for COFF symbols. */
-#define SDB_DEBUGGING_INFO
-
-/* Specify predefined symbols in preprocessor. */
-
-#define CPP_PREDEFINES "-Dunix"
-#define CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE}"
-
-/* Allow #sccs in preprocessor. */
-
-#define SCCS_DIRECTIVE
+#define SDB_DEBUGGING_INFO 1
/* Output #ident as a .ident. */
@@ -139,28 +121,6 @@ Boston, MA 02111-1307, USA. */
/* Print opcodes the way that GAS expects them. */
#define GAS_MNEMONICS 1
-#ifdef NO_UNDERSCORES /* If user-symbols don't have underscores,
- then it must take more than `L' to identify
- a label that should be ignored. */
-
-/* This is how to store into the string BUF
- the symbol_ref name of an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class.
- This is suitable for output with `assemble_name'. */
-
-#undef ASM_GENERATE_INTERNAL_LABEL
-#define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \
- sprintf ((BUF), ".%s%ld", (PREFIX), (long)(NUMBER))
-
-/* 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)
-
-#endif /* NO_UNDERSCORES */
-
/* Output at beginning of assembler file. */
/* The .file command should always begin the output. */
#undef ASM_FILE_START
diff --git a/contrib/gcc/config/i386/gnu.h b/contrib/gcc/config/i386/gnu.h
index b14328f..acf2d3f 100644
--- a/contrib/gcc/config/i386/gnu.h
+++ b/contrib/gcc/config/i386/gnu.h
@@ -3,14 +3,29 @@
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i386 GNU)");
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__ -DMACH -Asystem=mach \
- -Dunix -Asystem=unix -Asystem=posix -D__gnu_hurd__ -D__GNU__ -Asystem=gnu"
+#undef TARGET_OS_CPP_BUILTINS /* config.gcc includes i386/linux.h. */
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("MACH"); \
+ builtin_define_std ("unix"); \
+ builtin_define ("__ELF__"); \
+ builtin_define ("__GNU__"); \
+ builtin_define ("__gnu_hurd__"); \
+ builtin_assert ("system=gnu"); \
+ builtin_assert ("system=mach"); \
+ builtin_assert ("system=posix"); \
+ builtin_assert ("system=unix"); \
+ if (flag_pic) \
+ { \
+ builtin_define ("__PIC__"); \
+ builtin_define ("__pic__"); \
+ } \
+ } \
+ while (0)
#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu) \
- %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} \
- %{posix:-D_POSIX_SOURCE} %{bsd:-D_BSD_SOURCE}"
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{bsd:-D_BSD_SOURCE}"
#undef CC1_SPEC
#define CC1_SPEC "%(cc1_cpu)"
diff --git a/contrib/gcc/config/i386/gstabs.h b/contrib/gcc/config/i386/gstabs.h
index 5f0ae34..e9a6218 100644
--- a/contrib/gcc/config/i386/gstabs.h
+++ b/contrib/gcc/config/i386/gstabs.h
@@ -1,9 +1,7 @@
-#include "i386/gas.h"
-
/* We do not want to output SDB debugging information. */
#undef SDB_DEBUGGING_INFO
/* We want to output DBX debugging information. */
-#define DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
diff --git a/contrib/gcc/config/i386/gthr-win32.c b/contrib/gcc/config/i386/gthr-win32.c
new file mode 100644
index 0000000..06dc204
--- /dev/null
+++ b/contrib/gcc/config/i386/gthr-win32.c
@@ -0,0 +1,174 @@
+/* Implementation of W32-specific threads compatibility routines for
+ libgcc2. */
+
+/* Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
+ Contributed by Mumit Khan <khan@xraylith.wisc.edu>.
+ Modified and moved to separate file by Danny Smith
+ <dannysmith@users.sourceforge.net>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+/* 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. */
+
+
+#ifndef __GTHREAD_HIDE_WIN32API
+# define __GTHREAD_HIDE_WIN32API
+#endif
+#include <gthr-win32.h>
+#include <windows.h>
+
+/* Windows32 threads specific definitions. The windows32 threading model
+ does not map well into pthread-inspired gcc's threading model, and so
+ there are caveats one needs to be aware of.
+
+ 1. The destructor supplied to __gthread_key_create is ignored for
+ generic x86-win32 ports. This will certainly cause memory leaks
+ due to unreclaimed eh contexts (sizeof (eh_context) is at least
+ 24 bytes for x86 currently).
+
+ This memory leak may be significant for long-running applications
+ that make heavy use of C++ EH.
+
+ However, Mingw runtime (version 0.3 or newer) provides a mechanism
+ to emulate pthreads key dtors; the runtime provides a special DLL,
+ linked in if -mthreads option is specified, that runs the dtors in
+ the reverse order of registration when each thread exits. If
+ -mthreads option is not given, a stub is linked in instead of the
+ DLL, which results in memory leak. Other x86-win32 ports can use
+ the same technique of course to avoid the leak.
+
+ 2. The error codes returned are non-POSIX like, and cast into ints.
+ This may cause incorrect error return due to truncation values on
+ hw where sizeof (DWORD) > sizeof (int).
+
+ 3. We might consider using Critical Sections instead of Windows32
+ mutexes for better performance, but emulating __gthread_mutex_trylock
+ interface becomes more complicated (Win9x does not support
+ TryEnterCriticalSectioni, while NT does).
+
+ The basic framework should work well enough. In the long term, GCC
+ needs to use Structured Exception Handling on Windows32. */
+
+int
+__gthr_win32_once (__gthread_once_t *once, void (*func) (void))
+{
+ if (once == NULL || func == NULL)
+ return EINVAL;
+
+ if (! once->done)
+ {
+ if (InterlockedIncrement (&(once->started)) == 0)
+ {
+ (*func) ();
+ once->done = TRUE;
+ }
+ else
+ {
+ /* Another thread is currently executing the code, so wait for it
+ to finish; yield the CPU in the meantime. If performance
+ does become an issue, the solution is to use an Event that
+ we wait on here (and set above), but that implies a place to
+ create the event before this routine is called. */
+ while (! once->done)
+ Sleep (0);
+ }
+ }
+ return 0;
+}
+
+/* Windows32 thread local keys don't support destructors; this leads to
+ leaks, especially in threaded applications making extensive use of
+ C++ EH. Mingw uses a thread-support DLL to work-around this problem. */
+
+int
+__gthr_win32_key_create (__gthread_key_t *key, void (*dtor) (void *))
+{
+ int status = 0;
+ DWORD tls_index = TlsAlloc ();
+ if (tls_index != 0xFFFFFFFF)
+ {
+ *key = tls_index;
+#ifdef MINGW32_SUPPORTS_MT_EH
+ /* Mingw runtime will run the dtors in reverse order for each thread
+ when the thread exits. */
+ status = __mingwthr_key_dtor (*key, dtor);
+#endif
+ }
+ else
+ status = (int) GetLastError ();
+ return status;
+}
+
+int
+__gthr_win32_key_delete (__gthread_key_t key)
+{
+ return (TlsFree (key) != 0) ? 0 : (int) GetLastError ();
+}
+
+void *
+__gthr_win32_getspecific (__gthread_key_t key)
+{
+ DWORD lasterror;
+ void *ptr;
+ lasterror = GetLastError();
+ ptr = TlsGetValue(key);
+ SetLastError( lasterror );
+ return ptr;
+}
+
+int
+__gthr_win32_setspecific (__gthread_key_t key, const void *ptr)
+{
+ return (TlsSetValue (key, (void*) ptr) != 0) ? 0 : (int) GetLastError ();
+}
+
+void
+__gthr_win32_mutex_init_function (__gthread_mutex_t *mutex)
+{
+ /* Create unnamed mutex with default security attr and no initial owner. */
+ *mutex = CreateMutex (NULL, 0, NULL);
+}
+
+int
+__gthr_win32_mutex_lock (__gthread_mutex_t *mutex)
+{
+ if (WaitForSingleObject (*mutex, INFINITE) == WAIT_OBJECT_0)
+ return 0;
+ else
+ return 1;
+}
+
+int
+__gthr_win32_mutex_trylock (__gthread_mutex_t *mutex)
+{
+ if (WaitForSingleObject (*mutex, 0) == WAIT_OBJECT_0)
+ return 0;
+ else
+ return 1;
+}
+
+int
+__gthr_win32_mutex_unlock (__gthread_mutex_t *mutex)
+{
+ return (ReleaseMutex (*mutex) != 0) ? 0 : 1;
+}
diff --git a/contrib/gcc/config/i386/i386-aout.h b/contrib/gcc/config/i386/i386-aout.h
index 7385bec..ca0cb25 100644
--- a/contrib/gcc/config/i386/i386-aout.h
+++ b/contrib/gcc/config/i386/i386-aout.h
@@ -1,7 +1,7 @@
/* Definitions for "naked" Intel 386 using a.out (or coff encap'd
a.out) object format and stabs debugging info.
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -21,14 +21,6 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* This is tested by gas.h. */
-#define YES_UNDERSCORES
-
-#include "i386/gstabs.h"
-
-/* Specify predefined symbols in preprocessor. */
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES ""
+#define TARGET_VERSION fprintf (stderr, " (80386, BSD a.out syntax)");
/* end of i386-aout.h */
diff --git a/contrib/gcc/config/i386/i386-coff.h b/contrib/gcc/config/i386/i386-coff.h
index c1ae670..e8c5de9 100644
--- a/contrib/gcc/config/i386/i386-coff.h
+++ b/contrib/gcc/config/i386/i386-coff.h
@@ -1,7 +1,7 @@
/* Definitions for "naked" Intel 386 using coff object format files
and coff debugging info.
- Copyright (C) 1994, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1994, 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -21,18 +21,13 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "i386/gas.h"
-#include "dbxcoff.h"
+#define TARGET_VERSION fprintf (stderr, " (80386, COFF BSD syntax)");
-/* Specify predefined symbols in preprocessor. */
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES ""
+#define TARGET_OS_CPP_BUILTINS() /* Sweet FA. */
/* We want to be able to get DBX debugging information via -gstabs. */
-#undef DBX_DEBUGGING_INFO
-#define DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG
@@ -40,4 +35,36 @@ Boston, MA 02111-1307, USA. */
/* Switch into a generic section. */
#define TARGET_ASM_NAMED_SECTION default_coff_asm_named_section
+/* Prefix for internally generated assembler labels. If we aren't using
+ underscores, we are using prefix `.'s to identify labels that should
+ be ignored, as in `i386/gas.h' --karl@cs.umb.edu */
+
+#undef LPREFIX
+#define LPREFIX ".L"
+
+/* The prefix to add to user-visible assembler symbols. */
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
+/* If user-symbols don't have underscores,
+ then it must take more than `L' to identify
+ a label that should be ignored. */
+
+/* This is how to store into the string BUF
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \
+ sprintf ((BUF), ".%s%ld", (PREFIX), (long)(NUMBER))
+
+/* 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)
+
/* end of i386-coff.h */
diff --git a/contrib/gcc/config/i386/i386-interix.h b/contrib/gcc/config/i386/i386-interix.h
index 76357f3..d309087 100644
--- a/contrib/gcc/config/i386/i386-interix.h
+++ b/contrib/gcc/config/i386/i386-interix.h
@@ -1,5 +1,5 @@
/* Target definitions for GNU compiler for Intel 80386 running Interix
- Parts Copyright (C) 1991, 1999, 2000 Free Software Foundation, Inc.
+ Parts Copyright (C) 1991, 1999, 2000, 2002 Free Software Foundation, Inc.
Parts:
by Douglas B. Rupp (drupp@cs.washington.edu).
@@ -24,17 +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. */
-#define YES_UNDERSCORES
-
-/* YES_UNDERSCORES must precede gas.h */
-#include <i386/gas.h>
/* The rest must follow. */
-#define DBX_DEBUGGING_INFO
-#define SDB_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
+#define SDB_DEBUGGING_INFO 1
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
#undef HANDLE_PRAGMA_WEAK /* until the link format can handle it */
/* By default, target has a 80387, uses IEEE compatible arithmetic,
@@ -48,7 +44,6 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_CPU_DEFAULT
#define TARGET_CPU_DEFAULT 2 /* 486 */
-#define WCHAR_UNSIGNED 1
#define WCHAR_TYPE_SIZE 16
#define WCHAR_TYPE "short unsigned int"
@@ -58,35 +53,39 @@ Boston, MA 02111-1307, USA. */
#define ASM_LOAD_ADDR(loc, reg) " leal " #loc "," #reg "\n"
/* cpp handles __STDC__ */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES " \
- -D__INTERIX \
- -D__OPENNT \
- -D_M_IX86=300 -D_X86_=1 \
- -D__stdcall=__attribute__((__stdcall__)) \
- -D__cdecl=__attribute__((__cdecl__)) \
- -D__declspec(x)=__attribute__((x)) \
- -Asystem=unix -Asystem=interix"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__INTERIX"); \
+ builtin_define ("__OPENNT"); \
+ builtin_define ("_M_IX86=300"); \
+ builtin_define ("_X86_=1"); \
+ builtin_define ("__stdcall=__attribute__((__stdcall__))"); \
+ builtin_define ("__cdecl=__attribute__((__cdecl__))"); \
+ builtin_define ("__declspec(x)=__attribute__((x))"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=interix"); \
+ if (preprocessing_asm_p ()) \
+ builtin_define_std ("LANGUAGE_ASSEMBLY"); \
+ else \
+ { \
+ builtin_define_std ("LANGUAGE_C"); \
+ if (c_language == clk_cplusplus) \
+ builtin_define_std ("LANGUAGE_C_PLUS_PLUS"); \
+ if (flag_objc) \
+ builtin_define_std ("LANGUAGE_OBJECTIVE_C"); \
+ } \
+ } \
+ while (0)
#undef CPP_SPEC
/* Write out the correct language type definition for the header files.
Unless we have assembler language, write out the symbols for C.
- cpp_cpu is an Intel specific variant. See i386.h
mieee is an Alpha specific variant. Cross polination a bad idea.
*/
-#define CPP_SPEC "\
-%{!.S: -D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}} \
-%{.S: -D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{.cc: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
-%{.cxx: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
-%{.C: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
-%{.m: -D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C} \
--remap \
-%(cpp_cpu) \
-%{posix:-D_POSIX_SOURCE} \
+#define CPP_SPEC "-remap %{posix:-D_POSIX_SOURCE} \
-isystem %$INTERIX_ROOT/usr/include"
-#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i386 Interix)");
/* The global __fltused is necessary to cause the printf/scanf routines
@@ -238,50 +237,15 @@ Boston, MA 02111-1307, USA. */
#undef LD_INIT_SWITCH
#undef LD_FINI_SWITCH
-#define EH_FRAME_IN_DATA_SECTION
-
-/* Note that there appears to be two different ways to support const
- sections at the moment. You can either #define the symbol
- READONLY_DATA_SECTION (giving it some code which switches to the
- readonly data section) or else you can #define the symbols
- EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
- SELECT_RTX_SECTION. We do both here just to be on the safe side. */
-
-#define USE_CONST_SECTION 1
-
-#define CONST_SECTION_ASM_OP "\t.section\t.rdata,\"r\""
-
-/* A default list of other sections which we might be "in" at any given
- time. For targets that use additional sections (e.g. .tdesc) you
- should override this definition in the target-specific file which
- includes this file. */
-
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const
+/* The following are needed for us to be able to use winnt.c, but are not
+ otherwise meaningful to Interix. (The functions that use these are
+ never called because we don't do DLLs.) */
+#define TARGET_NOP_FUN_DLLIMPORT 1
+#define drectve_section() /* nothing */
-/* A default list of extra section function definitions. For targets
- that use additional sections (e.g. .tdesc) you should override this
- definition in the target-specific file which includes this file. */
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- CONST_SECTION_FUNCTION
-
-#undef READONLY_DATA_SECTION
-#define READONLY_DATA_SECTION() const_section ()
+#define EH_FRAME_IN_DATA_SECTION
-#define CONST_SECTION_FUNCTION \
-void \
-const_section () \
-{ \
- if (!USE_CONST_SECTION) \
- text_section(); \
- else if (in_section != in_const) \
- { \
- fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
- in_section = in_const; \
- } \
-}
+#define READONLY_DATA_SECTION_ASM_OP "\t.section\t.rdata,\"r\""
/* The MS compilers take alignment as a number of bytes, so we do as well */
#undef ASM_OUTPUT_ALIGN
@@ -346,57 +310,13 @@ while (0)
/* Define this macro if references to a symbol must be treated
differently depending on something about the variable or
- function named by the symbol (such as what section it is in).
-
- Apply stddef, handle (as yet unimplemented) pic.
-
- stddef renaming does NOT apply to Alpha. */
-
-union tree_node;
-const char *gen_stdcall_suffix PARAMS ((union tree_node *));
-
-#undef ENCODE_SECTION_INFO
-#define ENCODE_SECTION_INFO(DECL) \
-do \
- { \
- if (flag_pic) \
- { \
- rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
- ? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \
- SYMBOL_REF_FLAG (XEXP (rtl, 0)) \
- = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
- || ! TREE_PUBLIC (DECL)); \
- } \
- if (TREE_CODE (DECL) == FUNCTION_DECL) \
- if (lookup_attribute ("stdcall", \
- TYPE_ATTRIBUTES (TREE_TYPE (DECL)))) \
- XEXP (DECL_RTL (DECL), 0) = \
- gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (DECL)); \
- } \
-while (0)
+ function named by the symbol (such as what section it is in). */
+
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING i386_pe_strip_name_encoding_full
-/* This macro gets just the user-specified name
- out of the string in a SYMBOL_REF. Discard
- trailing @[NUM] encoded by ENCODE_SECTION_INFO. */
-#undef STRIP_NAME_ENCODING
-#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
-do { \
- const char *_p; \
- const char *_name = SYMBOL_NAME; \
- for (_p = _name; *_p && *_p != '@'; ++_p) \
- ; \
- if (*_p == '@') \
- { \
- int _len = _p - _name; \
- char *_new_name = (char *) alloca (_len + 1); \
- strncpy (_new_name, _name, _len); \
- _new_name[_len] = '\0'; \
- (VAR) = _new_name; \
- } \
- else \
- (VAR) = _name; \
-} while (0)
-
#if 0
/* Turn this back on when the linker is updated to handle grouped
.data$ sections correctly. See corresponding note in i386/interix.c.
@@ -408,8 +328,8 @@ do { \
symbols must be explicitly imported from shared libraries (DLLs). */
#define MULTIPLE_SYMBOL_SPACES
-extern void i386_pe_unique_section ();
-#define UNIQUE_SECTION(DECL,RELOC) i386_pe_unique_section (DECL, RELOC)
+extern void i386_pe_unique_section PARAMS ((tree, int));
+#define TARGET_ASM_UNIQUE_SECTION i386_pe_unique_section
#define SUPPORTS_ONE_ONLY 1
#endif /* 0 */
diff --git a/contrib/gcc/config/i386/i386-interix3.h b/contrib/gcc/config/i386/i386-interix3.h
index 274972b..aafe57f 100644
--- a/contrib/gcc/config/i386/i386-interix3.h
+++ b/contrib/gcc/config/i386/i386-interix3.h
@@ -20,13 +20,5 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#undef CPP_SPEC
-#define CPP_SPEC "\
-%{!.S: -D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}} \
-%{.S: -D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{.cc: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
-%{.cxx: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
-%{.C: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
-%{.m: -D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C} \
-%(cpp_cpu) \
-%{posix:-D_POSIX_SOURCE}"
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE}"
diff --git a/contrib/gcc/config/i386/i386-modes.def b/contrib/gcc/config/i386/i386-modes.def
new file mode 100644
index 0000000..5ef800f
--- /dev/null
+++ b/contrib/gcc/config/i386/i386-modes.def
@@ -0,0 +1,46 @@
+/* Definitions of target machine for GNU compiler for IA-32.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Add any extra modes needed to represent the condition code.
+
+ For the i386, we need separate modes when floating-point
+ equality comparisons are being done.
+
+ Add CCNO to indicate comparisons against zero that requires
+ Overflow flag to be unset. Sign bit test is used instead and
+ thus can be used to form "a&b>0" type of tests.
+
+ Add CCGC to indicate comparisons agains zero that allows
+ unspecified garbage in the Carry flag. This mode is used
+ by inc/dec instructions.
+
+ Add CCGOC to indicate comparisons agains zero that allows
+ unspecified garbage in the Carry and Overflow flag. This
+ mode is used to simulate comparisons of (a-b) and (a+b)
+ against zero using sub/cmp/add operations.
+
+ Add CCZ to indicate that only the Zero flag is valid. */
+
+CC (CCGC)
+CC (CCGOC)
+CC (CCNO)
+CC (CCZ)
+CC (CCFP)
+CC (CCFPU)
diff --git a/contrib/gcc/config/i386/i386-protos.h b/contrib/gcc/config/i386/i386-protos.h
index 03de4b1..b5ddb37 100644
--- a/contrib/gcc/config/i386/i386-protos.h
+++ b/contrib/gcc/config/i386/i386-protos.h
@@ -28,7 +28,6 @@ extern int ix86_frame_pointer_required PARAMS ((void));
extern void ix86_setup_frame_addresses PARAMS ((void));
extern void ix86_asm_file_end PARAMS ((FILE *));
-extern void load_pic_register PARAMS ((void));
extern HOST_WIDE_INT ix86_initial_elimination_offset PARAMS((int, int));
extern void ix86_expand_prologue PARAMS ((void));
extern void ix86_expand_epilogue PARAMS ((int));
@@ -43,6 +42,12 @@ extern int standard_80387_constant_p PARAMS ((rtx));
extern int standard_sse_constant_p PARAMS ((rtx));
extern int symbolic_reference_mentioned_p PARAMS ((rtx));
+extern int any_fp_register_operand PARAMS ((rtx, enum machine_mode));
+extern int register_and_not_any_fp_reg_operand PARAMS ((rtx, enum machine_mode));
+
+extern int fp_register_operand PARAMS ((rtx, enum machine_mode));
+extern int register_and_not_fp_reg_operand PARAMS ((rtx, enum machine_mode));
+
extern int x86_64_general_operand PARAMS ((rtx, enum machine_mode));
extern int x86_64_szext_general_operand PARAMS ((rtx, enum machine_mode));
extern int x86_64_nonmemory_operand PARAMS ((rtx, enum machine_mode));
@@ -51,6 +56,11 @@ extern int x86_64_immediate_operand PARAMS ((rtx, enum machine_mode));
extern int x86_64_zext_immediate_operand PARAMS ((rtx, enum machine_mode));
extern int const_int_1_operand PARAMS ((rtx, enum machine_mode));
extern int symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int tls_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int global_dynamic_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int local_dynamic_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int initial_exec_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int local_exec_symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int pic_symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int call_insn_operand PARAMS ((rtx, enum machine_mode));
extern int constant_call_address_operand PARAMS ((rtx, enum machine_mode));
@@ -84,6 +94,9 @@ extern int ix86_expand_movstr PARAMS ((rtx, rtx, rtx, rtx));
extern int ix86_expand_clrstr PARAMS ((rtx, rtx, rtx));
extern int ix86_expand_strlen PARAMS ((rtx, rtx, rtx, rtx));
+extern bool legitimate_constant_p PARAMS ((rtx));
+extern bool constant_address_p PARAMS ((rtx));
+extern bool legitimate_pic_operand_p PARAMS ((rtx));
extern int legitimate_pic_address_disp_p PARAMS ((rtx));
extern int legitimate_address_p PARAMS ((enum machine_mode, rtx, int));
extern rtx legitimize_pic_address PARAMS ((rtx, rtx));
@@ -92,15 +105,18 @@ extern rtx legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
extern void print_reg PARAMS ((rtx, int, FILE*));
extern void print_operand PARAMS ((FILE*, rtx, int));
extern void print_operand_address PARAMS ((FILE*, rtx));
+extern bool output_addr_const_extra PARAMS ((FILE*, rtx));
extern void split_di PARAMS ((rtx[], int, rtx[], rtx[]));
extern void split_ti PARAMS ((rtx[], int, rtx[], rtx[]));
+extern const char *output_set_got PARAMS ((rtx));
extern const char *output_387_binary_op PARAMS ((rtx, rtx*));
extern const char *output_fix_trunc PARAMS ((rtx, rtx*));
extern const char *output_fp_compare PARAMS ((rtx, rtx*, int, int));
extern void i386_dwarf_output_addr_const PARAMS ((FILE*, rtx));
+extern void i386_output_dwarf_dtprel PARAMS ((FILE*, int, rtx));
extern rtx i386_simplify_dwarf_addr PARAMS ((rtx));
extern void ix86_expand_clear PARAMS ((rtx));
@@ -121,6 +137,7 @@ extern void ix86_expand_branch PARAMS ((enum rtx_code, rtx));
extern int ix86_expand_setcc PARAMS ((enum rtx_code, rtx));
extern int ix86_expand_int_movcc PARAMS ((rtx[]));
extern int ix86_expand_fp_movcc PARAMS ((rtx[]));
+extern void ix86_expand_call PARAMS ((rtx, rtx, rtx, rtx, rtx));
extern void x86_initialize_trampoline PARAMS ((rtx, rtx, rtx));
extern rtx ix86_zero_extend_to_Pmode PARAMS ((rtx));
extern void ix86_split_long_move PARAMS ((rtx[]));
@@ -129,6 +146,7 @@ extern void ix86_split_ashrdi PARAMS ((rtx *, rtx));
extern void ix86_split_lshrdi PARAMS ((rtx *, rtx));
extern int ix86_address_cost PARAMS ((rtx));
extern rtx ix86_find_base_term PARAMS ((rtx));
+extern int ix86_check_movabs PARAMS ((rtx, int));
extern rtx assign_386_stack_local PARAMS ((enum machine_mode, int));
extern int ix86_attr_length_immediate_default PARAMS ((rtx, int));
@@ -143,7 +161,7 @@ extern bool ix86_function_value_regno_p PARAMS ((int));
extern bool ix86_function_arg_regno_p PARAMS ((int));
extern int ix86_function_arg_boundary PARAMS ((enum machine_mode, tree));
extern int ix86_return_in_memory PARAMS ((tree));
-extern void ix86_va_start PARAMS ((int, tree, rtx));
+extern void ix86_va_start PARAMS ((tree, rtx));
extern rtx ix86_va_arg PARAMS ((tree, tree));
extern void ix86_setup_incoming_varargs PARAMS ((CUMULATIVE_ARGS *,
enum machine_mode,
@@ -167,11 +185,15 @@ extern void ix86_set_move_mem_attrs PARAMS ((rtx, rtx, rtx, rtx, rtx));
extern void emit_i387_cw_initialization PARAMS ((rtx, rtx));
extern bool ix86_fp_jump_nontrivial_p PARAMS ((enum rtx_code));
extern void x86_order_regs_for_local_alloc PARAMS ((void));
+extern void x86_function_profiler PARAMS ((FILE *, int));
#ifdef TREE_CODE
extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx));
extern rtx function_arg PARAMS ((CUMULATIVE_ARGS *, enum machine_mode, tree, int));
+extern int function_arg_pass_by_reference PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode,
+ tree, int));
extern void function_arg_advance PARAMS ((CUMULATIVE_ARGS *, enum machine_mode,
tree, int));
extern rtx ix86_function_value PARAMS ((tree));
@@ -194,6 +216,20 @@ extern tree ix86_handle_shared_attribute PARAMS ((tree *, tree, tree, int, bool
extern unsigned int i386_pe_section_type_flags PARAMS ((tree, const char *,
int));
extern void i386_pe_asm_named_section PARAMS ((const char *, unsigned int));
-extern void x86_output_mi_thunk PARAMS ((FILE *, int, tree));
extern int x86_field_alignment PARAMS ((tree, int));
#endif
+
+extern rtx ix86_tls_get_addr PARAMS ((void));
+extern void x86_machine_dependent_reorg PARAMS ((rtx));
+
+/* In winnt.c */
+extern int i386_pe_dllexport_name_p PARAMS ((const char *));
+extern int i386_pe_dllimport_name_p PARAMS ((const char *));
+extern void i386_pe_unique_section PARAMS ((tree, int));
+extern void i386_pe_declare_function_type PARAMS ((FILE *, const char *, int));
+extern void i386_pe_record_external_function PARAMS ((const char *));
+extern void i386_pe_record_exported_symbol PARAMS ((const char *, int));
+extern void i386_pe_asm_file_end PARAMS ((FILE *));
+extern void i386_pe_encode_section_info PARAMS ((tree, int));
+extern const char *i386_pe_strip_name_encoding PARAMS ((const char *));
+extern const char *i386_pe_strip_name_encoding_full PARAMS ((const char *));
diff --git a/contrib/gcc/config/i386/i386.c b/contrib/gcc/config/i386/i386.c
index 054a925..8d033b9 100644
--- a/contrib/gcc/config/i386/i386.c
+++ b/contrib/gcc/config/i386/i386.c
@@ -1,6 +1,6 @@
/* Subroutines used for code generation on IA-32.
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002 Free Software Foundation, Inc.
+ 2002, 2003 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -42,13 +42,14 @@ Boston, MA 02111-1307, USA. */
#include "ggc.h"
#include "target.h"
#include "target-def.h"
+#include "langhooks.h"
#ifndef CHECK_STACK_LIMIT
#define CHECK_STACK_LIMIT (-1)
#endif
/* Processor costs (relative to an add) */
-static const
+static const
struct processor_costs size_cost = { /* costs for tunning for size */
2, /* cost of an add instruction */
3, /* cost of a lea instruction */
@@ -83,9 +84,16 @@ struct processor_costs size_cost = { /* costs for tunning for size */
3, /* MMX or SSE register to integer */
0, /* size of prefetch block */
0, /* number of parallel prefetches */
+ 2, /* cost of FADD and FSUB insns. */
+ 2, /* cost of FMUL instruction. */
+ 2, /* cost of FDIV instruction. */
+ 2, /* cost of FABS instruction. */
+ 2, /* cost of FCHS instruction. */
+ 2, /* cost of FSQRT instruction. */
};
+
/* Processor costs (relative to an add) */
-static const
+static const
struct processor_costs i386_cost = { /* 386 specific costs */
1, /* cost of an add instruction */
1, /* cost of a lea instruction */
@@ -120,9 +128,15 @@ struct processor_costs i386_cost = { /* 386 specific costs */
3, /* MMX or SSE register to integer */
0, /* size of prefetch block */
0, /* number of parallel prefetches */
+ 23, /* cost of FADD and FSUB insns. */
+ 27, /* cost of FMUL instruction. */
+ 88, /* cost of FDIV instruction. */
+ 22, /* cost of FABS instruction. */
+ 24, /* cost of FCHS instruction. */
+ 122, /* cost of FSQRT instruction. */
};
-static const
+static const
struct processor_costs i486_cost = { /* 486 specific costs */
1, /* cost of an add instruction */
1, /* cost of a lea instruction */
@@ -157,9 +171,15 @@ struct processor_costs i486_cost = { /* 486 specific costs */
3, /* MMX or SSE register to integer */
0, /* size of prefetch block */
0, /* number of parallel prefetches */
+ 8, /* cost of FADD and FSUB insns. */
+ 16, /* cost of FMUL instruction. */
+ 73, /* cost of FDIV instruction. */
+ 3, /* cost of FABS instruction. */
+ 3, /* cost of FCHS instruction. */
+ 83, /* cost of FSQRT instruction. */
};
-static const
+static const
struct processor_costs pentium_cost = {
1, /* cost of an add instruction */
1, /* cost of a lea instruction */
@@ -194,9 +214,15 @@ struct processor_costs pentium_cost = {
3, /* MMX or SSE register to integer */
0, /* size of prefetch block */
0, /* number of parallel prefetches */
+ 3, /* cost of FADD and FSUB insns. */
+ 3, /* cost of FMUL instruction. */
+ 39, /* cost of FDIV instruction. */
+ 1, /* cost of FABS instruction. */
+ 1, /* cost of FCHS instruction. */
+ 70, /* cost of FSQRT instruction. */
};
-static const
+static const
struct processor_costs pentiumpro_cost = {
1, /* cost of an add instruction */
1, /* cost of a lea instruction */
@@ -231,9 +257,15 @@ struct processor_costs pentiumpro_cost = {
3, /* MMX or SSE register to integer */
32, /* size of prefetch block */
6, /* number of parallel prefetches */
+ 3, /* cost of FADD and FSUB insns. */
+ 5, /* cost of FMUL instruction. */
+ 56, /* cost of FDIV instruction. */
+ 2, /* cost of FABS instruction. */
+ 2, /* cost of FCHS instruction. */
+ 56, /* cost of FSQRT instruction. */
};
-static const
+static const
struct processor_costs k6_cost = {
1, /* cost of an add instruction */
2, /* cost of a lea instruction */
@@ -268,9 +300,15 @@ struct processor_costs k6_cost = {
6, /* MMX or SSE register to integer */
32, /* size of prefetch block */
1, /* number of parallel prefetches */
+ 2, /* cost of FADD and FSUB insns. */
+ 2, /* cost of FMUL instruction. */
+ 56, /* cost of FDIV instruction. */
+ 2, /* cost of FABS instruction. */
+ 2, /* cost of FCHS instruction. */
+ 56, /* cost of FSQRT instruction. */
};
-static const
+static const
struct processor_costs athlon_cost = {
1, /* cost of an add instruction */
2, /* cost of a lea instruction */
@@ -305,9 +343,15 @@ struct processor_costs athlon_cost = {
5, /* MMX or SSE register to integer */
64, /* size of prefetch block */
6, /* number of parallel prefetches */
+ 4, /* cost of FADD and FSUB insns. */
+ 4, /* cost of FMUL instruction. */
+ 24, /* cost of FDIV instruction. */
+ 2, /* cost of FABS instruction. */
+ 2, /* cost of FCHS instruction. */
+ 35, /* cost of FSQRT instruction. */
};
-static const
+static const
struct processor_costs pentium4_cost = {
1, /* cost of an add instruction */
1, /* cost of a lea instruction */
@@ -342,6 +386,12 @@ struct processor_costs pentium4_cost = {
10, /* MMX or SSE register to integer */
64, /* size of prefetch block */
6, /* number of parallel prefetches */
+ 5, /* cost of FADD and FSUB insns. */
+ 7, /* cost of FMUL instruction. */
+ 43, /* cost of FDIV instruction. */
+ 2, /* cost of FABS instruction. */
+ 2, /* cost of FCHS instruction. */
+ 43, /* cost of FSQRT instruction. */
};
const struct processor_costs *ix86_cost = &pentium_cost;
@@ -375,7 +425,8 @@ const int x86_use_cltd = ~(m_PENT | m_K6);
const int x86_read_modify_write = ~m_PENT;
const int x86_read_modify = ~(m_PENT | m_PPRO);
const int x86_split_long_moves = m_PPRO;
-const int x86_promote_QImode = m_K6 | m_PENT | m_386 | m_486;
+const int x86_promote_QImode = m_K6 | m_PENT | m_386 | m_486 | m_ATHLON;
+const int x86_fast_prefix = ~(m_PENT | m_486 | m_386);
const int x86_single_stringop = m_386 | m_PENT4;
const int x86_qimode_math = ~(0);
const int x86_promote_qi_regs = 0;
@@ -385,28 +436,29 @@ const int x86_sub_esp_4 = m_ATHLON | m_PPRO | m_PENT4;
const int x86_sub_esp_8 = m_ATHLON | m_PPRO | m_386 | m_486 | m_PENT4;
const int x86_add_esp_4 = m_ATHLON | m_K6 | m_PENT4;
const int x86_add_esp_8 = m_ATHLON | m_PPRO | m_K6 | m_386 | m_486 | m_PENT4;
-const int x86_integer_DFmode_moves = ~(m_ATHLON | m_PENT4);
+const int x86_integer_DFmode_moves = ~(m_ATHLON | m_PENT4 | m_PPRO);
const int x86_partial_reg_dependency = m_ATHLON | m_PENT4;
const int x86_memory_mismatch_stall = m_ATHLON | m_PENT4;
const int x86_accumulate_outgoing_args = m_ATHLON | m_PENT4 | m_PPRO;
const int x86_prologue_using_move = m_ATHLON | m_PENT4 | m_PPRO;
const int x86_epilogue_using_move = m_ATHLON | m_PENT4 | m_PPRO;
const int x86_decompose_lea = m_PENT4;
-const int x86_arch_always_fancy_math_387 = m_PENT|m_PPRO|m_ATHLON|m_PENT4;
+const int x86_shift1 = ~m_486;
+const int x86_arch_always_fancy_math_387 = m_PENT | m_PPRO | m_ATHLON | m_PENT4;
/* In case the avreage insn count for single function invocation is
lower than this constant, emit fast (but longer) prologue and
epilogue code. */
#define FAST_PROLOGUE_INSN_COUNT 30
+
/* Set by prologue expander and used by epilogue expander to determine
the style used. */
static int use_fast_prologue_epilogue;
-#define AT_BP(MODE) (gen_rtx_MEM ((MODE), hard_frame_pointer_rtx))
-
-static const char *const hi_reg_name[] = HI_REGISTER_NAMES; /* names for 16 bit regs */
-static const char *const qi_reg_name[] = QI_REGISTER_NAMES; /* names for 8 bit regs (low) */
-static const char *const qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES; /* names for 8 bit regs (high) */
+/* Names for 8 (low), 8 (high), and 16-bit registers, respectively. */
+static const char *const qi_reg_name[] = QI_REGISTER_NAMES;
+static const char *const qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES;
+static const char *const hi_reg_name[] = HI_REGISTER_NAMES;
/* Array of the smallest class containing reg number REGNO, indexed by
REGNO. Used by REGNO_REG_CLASS in i386.h. */
@@ -447,11 +499,16 @@ int const dbx_register_map[FIRST_PSEUDO_REGISTER] =
-1, -1, -1, -1, -1, -1, -1, -1, /* extended SSE registers */
};
-static int const x86_64_int_parameter_registers[6] = {5 /*RDI*/, 4 /*RSI*/,
- 1 /*RDX*/, 2 /*RCX*/,
- FIRST_REX_INT_REG /*R8 */,
- FIRST_REX_INT_REG + 1 /*R9 */};
-static int const x86_64_int_return_registers[4] = {0 /*RAX*/, 1 /*RDI*/, 5, 4};
+static int const x86_64_int_parameter_registers[6] =
+{
+ 5 /*RDI*/, 4 /*RSI*/, 1 /*RDX*/, 2 /*RCX*/,
+ FIRST_REX_INT_REG /*R8 */, FIRST_REX_INT_REG + 1 /*R9 */
+};
+
+static int const x86_64_int_return_registers[4] =
+{
+ 0 /*RAX*/, 1 /*RDI*/, 5 /*RDI*/, 4 /*RSI*/
+};
/* The "default" register map used in 64bit mode. */
int const dbx64_register_map[FIRST_PSEUDO_REGISTER] =
@@ -536,14 +593,19 @@ int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER] =
rtx ix86_compare_op0 = NULL_RTX;
rtx ix86_compare_op1 = NULL_RTX;
+/* The encoding characters for the four TLS models present in ELF. */
+
+static char const tls_model_chars[] = " GLil";
+
#define MAX_386_STACK_LOCALS 3
/* Size of the register save area. */
#define X86_64_VARARGS_SIZE (REGPARM_MAX * UNITS_PER_WORD + SSE_REGPARM_MAX * 16)
/* Define the structure for the machine field in struct function. */
-struct machine_function
+struct machine_function GTY(())
{
rtx stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
+ const char *some_ld_name;
int save_varrargs_registers;
int accesses_prev_frame;
};
@@ -596,15 +658,17 @@ enum cmodel ix86_cmodel;
/* Asm dialect. */
const char *ix86_asm_string;
enum asm_dialect ix86_asm_dialect = ASM_ATT;
+/* TLS dialext. */
+const char *ix86_tls_dialect_string;
+enum tls_dialect ix86_tls_dialect = TLS_DIALECT_GNU;
-/* which cpu are we scheduling for */
-enum processor_type ix86_cpu;
-
-/* which unit we are generating floating point math for */
+/* Which unit we are generating floating point math for. */
enum fpmath_unit ix86_fpmath;
-/* which instruction set architecture to use. */
-int ix86_arch;
+/* Which cpu are we scheduling for. */
+enum processor_type ix86_cpu;
+/* Which instruction set architecture to use. */
+enum processor_type ix86_arch;
/* Strings to hold which cpu and instruction set architecture to use. */
const char *ix86_cpu_string; /* for -mcpu=<xxx> */
@@ -646,35 +710,33 @@ static char internal_label_prefix[16];
static int internal_label_prefix_len;
static int local_symbolic_operand PARAMS ((rtx, enum machine_mode));
+static int tls_symbolic_operand_1 PARAMS ((rtx, enum tls_model));
static void output_pic_addr_const PARAMS ((FILE *, rtx, int));
static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode,
int, int, FILE *));
+static const char *get_some_local_dynamic_name PARAMS ((void));
+static int get_some_local_dynamic_name_1 PARAMS ((rtx *, void *));
+static rtx maybe_get_pool_constant PARAMS ((rtx));
static rtx ix86_expand_int_compare PARAMS ((enum rtx_code, rtx, rtx));
static enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code,
rtx *, rtx *));
+static rtx get_thread_pointer PARAMS ((void));
+static void get_pc_thunk_name PARAMS ((char [32], unsigned int));
static rtx gen_push PARAMS ((rtx));
static int memory_address_length PARAMS ((rtx addr));
static int ix86_flags_dependant PARAMS ((rtx, rtx, enum attr_type));
static int ix86_agi_dependant PARAMS ((rtx, rtx, enum attr_type));
-static int ix86_safe_length PARAMS ((rtx));
-static enum attr_memory ix86_safe_memory PARAMS ((rtx));
-static enum attr_pent_pair ix86_safe_pent_pair PARAMS ((rtx));
static enum attr_ppro_uops ix86_safe_ppro_uops PARAMS ((rtx));
static void ix86_dump_ppro_packet PARAMS ((FILE *));
static void ix86_reorder_insn PARAMS ((rtx *, rtx *));
-static rtx * ix86_pent_find_pair PARAMS ((rtx *, rtx *, enum attr_pent_pair,
- rtx));
-static void ix86_init_machine_status PARAMS ((struct function *));
-static void ix86_mark_machine_status PARAMS ((struct function *));
-static void ix86_free_machine_status PARAMS ((struct function *));
+static struct machine_function * ix86_init_machine_status PARAMS ((void));
static int ix86_split_to_parts PARAMS ((rtx, rtx *, enum machine_mode));
-static int ix86_safe_length_prefix PARAMS ((rtx));
static int ix86_nsaved_regs PARAMS ((void));
static void ix86_emit_save_regs PARAMS ((void));
static void ix86_emit_save_regs_using_mov PARAMS ((rtx, HOST_WIDE_INT));
static void ix86_emit_restore_regs_using_mov PARAMS ((rtx, int, int));
+static void ix86_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
static void ix86_set_move_mem_attrs_1 PARAMS ((rtx, rtx, rtx, rtx, rtx));
-static void ix86_sched_reorder_pentium PARAMS ((rtx *, rtx *));
static void ix86_sched_reorder_ppro PARAMS ((rtx *, rtx *));
static HOST_WIDE_INT ix86_GOT_alias_set PARAMS ((void));
static void ix86_adjust_counter PARAMS ((rtx, HOST_WIDE_INT));
@@ -685,7 +747,14 @@ static int ix86_adjust_cost PARAMS ((rtx, rtx, rtx, int));
static void ix86_sched_init PARAMS ((FILE *, int, int));
static int ix86_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));
static int ix86_variable_issue PARAMS ((FILE *, int, rtx, int));
+static int ia32_use_dfa_pipeline_interface PARAMS ((void));
+static int ia32_multipass_dfa_lookahead PARAMS ((void));
static void ix86_init_mmx_sse_builtins PARAMS ((void));
+static rtx x86_this_parameter PARAMS ((tree));
+static void x86_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+ HOST_WIDE_INT, tree));
+static bool x86_can_output_mi_thunk PARAMS ((tree, HOST_WIDE_INT,
+ HOST_WIDE_INT, tree));
struct ix86_address
{
@@ -694,6 +763,11 @@ struct ix86_address
};
static int ix86_decompose_address PARAMS ((rtx, struct ix86_address *));
+static bool ix86_cannot_force_const_mem PARAMS ((rtx));
+
+static void ix86_encode_section_info PARAMS ((tree, int)) ATTRIBUTE_UNUSED;
+static const char *ix86_strip_name_encoding PARAMS ((const char *))
+ ATTRIBUTE_UNUSED;
struct builtin_description;
static rtx ix86_expand_sse_comi PARAMS ((const struct builtin_description *,
@@ -703,8 +777,6 @@ static rtx ix86_expand_sse_compare PARAMS ((const struct builtin_description *,
static rtx ix86_expand_unop1_builtin PARAMS ((enum insn_code, tree, rtx));
static rtx ix86_expand_unop_builtin PARAMS ((enum insn_code, tree, rtx, int));
static rtx ix86_expand_binop_builtin PARAMS ((enum insn_code, tree, rtx));
-static rtx ix86_expand_timode_binop_builtin PARAMS ((enum insn_code,
- tree, rtx));
static rtx ix86_expand_store_builtin PARAMS ((enum insn_code, tree));
static rtx safe_vector_operand PARAMS ((rtx, enum machine_mode));
static enum rtx_code ix86_fp_compare_code_to_integer PARAMS ((enum rtx_code));
@@ -718,14 +790,18 @@ static int ix86_fp_comparison_arithmetics_cost PARAMS ((enum rtx_code code));
static int ix86_fp_comparison_fcomi_cost PARAMS ((enum rtx_code code));
static int ix86_fp_comparison_sahf_cost PARAMS ((enum rtx_code code));
static int ix86_fp_comparison_cost PARAMS ((enum rtx_code code));
-static int ix86_save_reg PARAMS ((int, int));
+static unsigned int ix86_select_alt_pic_regnum PARAMS ((void));
+static int ix86_save_reg PARAMS ((unsigned int, int));
static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
static int ix86_comp_type_attributes PARAMS ((tree, tree));
+static int ix86_fntype_regparm PARAMS ((tree));
const struct attribute_spec ix86_attribute_table[];
static tree ix86_handle_cdecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
static tree ix86_handle_regparm_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static int ix86_value_regno PARAMS ((enum machine_mode));
+static bool contains_128bit_aligned_vector_p PARAMS ((tree));
-#ifdef DO_GLOBAL_CTORS_BODY
+#if defined (DO_GLOBAL_CTORS_BODY) && defined (HAS_INIT_SECTION)
static void ix86_svr3_asm_out_constructor PARAMS ((rtx, int));
#endif
@@ -781,12 +857,8 @@ static enum x86_64_reg_class merge_classes PARAMS ((enum x86_64_reg_class,
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN ix86_expand_builtin
-#if defined (OSF_OS) || defined (TARGET_OSF1ELF)
- static void ix86_osf_output_function_prologue PARAMS ((FILE *,
- HOST_WIDE_INT));
-# undef TARGET_ASM_FUNCTION_PROLOGUE
-# define TARGET_ASM_FUNCTION_PROLOGUE ix86_osf_output_function_prologue
-#endif
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE ix86_output_function_epilogue
#undef TARGET_ASM_OPEN_PAREN
#define TARGET_ASM_OPEN_PAREN ""
@@ -819,9 +891,33 @@ static enum x86_64_reg_class merge_classes PARAMS ((enum x86_64_reg_class,
#define TARGET_SCHED_INIT ix86_sched_init
#undef TARGET_SCHED_REORDER
#define TARGET_SCHED_REORDER ix86_sched_reorder
+#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
+#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE \
+ ia32_use_dfa_pipeline_interface
+#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
+#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
+ ia32_multipass_dfa_lookahead
+
+#ifdef HAVE_AS_TLS
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS true
+#endif
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM ix86_cannot_force_const_mem
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK x86_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK x86_can_output_mi_thunk
struct gcc_target targetm = TARGET_INITIALIZER;
+/* The svr4 ABI for the i386 says that records and unions are returned
+ in memory. */
+#ifndef DEFAULT_PCC_STRUCT_RETURN
+#define DEFAULT_PCC_STRUCT_RETURN 1
+#endif
+
/* 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
@@ -883,6 +979,9 @@ override_options ()
{"i586", PROCESSOR_PENTIUM, 0},
{"pentium", PROCESSOR_PENTIUM, 0},
{"pentium-mmx", PROCESSOR_PENTIUM, PTA_MMX},
+ {"winchip-c6", PROCESSOR_I486, PTA_MMX},
+ {"winchip2", PROCESSOR_I486, PTA_MMX | PTA_3DNOW},
+ {"c3", PROCESSOR_I486, PTA_MMX | PTA_3DNOW},
{"i686", PROCESSOR_PENTIUMPRO, 0},
{"pentiumpro", PROCESSOR_PENTIUMPRO, 0},
{"pentium2", PROCESSOR_PENTIUMPRO, PTA_MMX},
@@ -904,7 +1003,12 @@ override_options ()
| PTA_3DNOW_A | PTA_SSE},
};
- int const pta_size = sizeof (processor_alias_table) / sizeof (struct pta);
+ int const pta_size = ARRAY_SIZE (processor_alias_table);
+
+ /* By default our XFmode is the 80-bit extended format. If we have
+ use TFmode instead, it's also the 80-bit format, but with padding. */
+ real_format_for_mode[XFmode - QFmode] = &ieee_extended_intel_96_format;
+ real_format_for_mode[TFmode - QFmode] = &ieee_extended_intel_128_format;
/* Set the default values for switches whose default depends on TARGET_64BIT
in case they weren't overwriten by command line options. */
@@ -986,19 +1090,19 @@ override_options ()
/* Default cpu tuning to the architecture. */
ix86_cpu = ix86_arch;
if (processor_alias_table[i].flags & PTA_MMX
- && !(target_flags & MASK_MMX_SET))
+ && !(target_flags_explicit & MASK_MMX))
target_flags |= MASK_MMX;
if (processor_alias_table[i].flags & PTA_3DNOW
- && !(target_flags & MASK_3DNOW_SET))
+ && !(target_flags_explicit & MASK_3DNOW))
target_flags |= MASK_3DNOW;
if (processor_alias_table[i].flags & PTA_3DNOW_A
- && !(target_flags & MASK_3DNOW_A_SET))
+ && !(target_flags_explicit & MASK_3DNOW_A))
target_flags |= MASK_3DNOW_A;
if (processor_alias_table[i].flags & PTA_SSE
- && !(target_flags & MASK_SSE_SET))
+ && !(target_flags_explicit & MASK_SSE))
target_flags |= MASK_SSE;
if (processor_alias_table[i].flags & PTA_SSE2
- && !(target_flags & MASK_SSE2_SET))
+ && !(target_flags_explicit & MASK_SSE2))
target_flags |= MASK_SSE2;
if (processor_alias_table[i].flags & PTA_PREFETCH_SSE)
x86_prefetch_sse = true;
@@ -1028,8 +1132,6 @@ override_options ()
/* Arrange to set up i386_stack_locals for all functions. */
init_machine_status = ix86_init_machine_status;
- mark_machine_status = ix86_mark_machine_status;
- free_machine_status = ix86_free_machine_status;
/* Validate -mregparm= value. */
if (ix86_regparm_string)
@@ -1130,6 +1232,17 @@ override_options ()
ix86_branch_cost = i;
}
+ if (ix86_tls_dialect_string)
+ {
+ if (strcmp (ix86_tls_dialect_string, "gnu") == 0)
+ ix86_tls_dialect = TLS_DIALECT_GNU;
+ else if (strcmp (ix86_tls_dialect_string, "sun") == 0)
+ ix86_tls_dialect = TLS_DIALECT_SUN;
+ else
+ error ("bad value (%s) for -mtls-dialect= switch",
+ ix86_tls_dialect_string);
+ }
+
/* Keep nonleaf frame pointers. */
if (TARGET_OMIT_LEAF_FRAME_POINTER)
flag_omit_frame_pointer = 1;
@@ -1187,7 +1300,7 @@ override_options ()
else
ix86_fpmath = FPMATH_SSE | FPMATH_387;
}
- else
+ else
error ("bad value (%s) for -mfpmath= switch", ix86_fpmath_string);
}
@@ -1209,7 +1322,7 @@ override_options ()
target_flags |= MASK_3DNOW_A;
}
if ((x86_accumulate_outgoing_args & CPUMASK)
- && !(target_flags & MASK_ACCUMULATE_OUTGOING_ARGS_SET)
+ && !(target_flags_explicit & MASK_ACCUMULATE_OUTGOING_ARGS)
&& !optimize_size)
target_flags |= MASK_ACCUMULATE_OUTGOING_ARGS;
@@ -1234,6 +1347,7 @@ optimization_options (level, size)
if (level > 1)
flag_schedule_insns = 0;
#endif
+
/* The default values of these switches depend on the TARGET_64BIT
that is not known at this moment. Mark these values with 2 and
let user the to override these. In case there is no command line option
@@ -1334,105 +1448,6 @@ ix86_handle_regparm_attribute (node, name, args, flags, no_add_attrs)
return NULL_TREE;
}
-#if defined (OSF_OS) || defined (TARGET_OSF1ELF)
-
-/* Generate the assembly code for function entry. FILE is a stdio
- stream to output the code to. SIZE is an int: how many units of
- temporary storage to allocate.
-
- Refer to the array `regs_ever_live' to determine which registers to
- save; `regs_ever_live[I]' is nonzero if register number I is ever
- used in the function. This function is responsible for knowing
- which registers should not be saved even if used.
-
- We override it here to allow for the new profiling code to go before
- the prologue and the old mcount code to go after the prologue (and
- after %ebx has been set up for ELF shared library support). */
-
-static void
-ix86_osf_output_function_prologue (file, size)
- FILE *file;
- HOST_WIDE_INT size;
-{
- const char *prefix = "";
- const char *const lprefix = LPREFIX;
- int labelno = current_function_profile_label_no;
-
-#ifdef OSF_OS
-
- if (TARGET_UNDERSCORES)
- prefix = "_";
-
- if (current_function_profile && OSF_PROFILE_BEFORE_PROLOGUE)
- {
- if (!flag_pic && !HALF_PIC_P ())
- {
- fprintf (file, "\tmovl $%sP%d,%%edx\n", lprefix, labelno);
- fprintf (file, "\tcall *%s_mcount_ptr\n", prefix);
- }
-
- else if (HALF_PIC_P ())
- {
- rtx symref;
-
- HALF_PIC_EXTERNAL ("_mcount_ptr");
- symref = HALF_PIC_PTR (gen_rtx_SYMBOL_REF (Pmode,
- "_mcount_ptr"));
-
- fprintf (file, "\tmovl $%sP%d,%%edx\n", lprefix, labelno);
- fprintf (file, "\tmovl %s%s,%%eax\n", prefix,
- XSTR (symref, 0));
- fprintf (file, "\tcall *(%%eax)\n");
- }
-
- else
- {
- static int call_no = 0;
-
- fprintf (file, "\tcall %sPc%d\n", lprefix, call_no);
- fprintf (file, "%sPc%d:\tpopl %%eax\n", lprefix, call_no);
- fprintf (file, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-%sPc%d],%%eax\n",
- lprefix, call_no++);
- fprintf (file, "\tleal %sP%d@GOTOFF(%%eax),%%edx\n",
- lprefix, labelno);
- fprintf (file, "\tmovl %s_mcount_ptr@GOT(%%eax),%%eax\n",
- prefix);
- fprintf (file, "\tcall *(%%eax)\n");
- }
- }
-
-#else /* !OSF_OS */
-
- if (current_function_profile && OSF_PROFILE_BEFORE_PROLOGUE)
- {
- if (!flag_pic)
- {
- fprintf (file, "\tmovl $%sP%d,%%edx\n", lprefix, labelno);
- fprintf (file, "\tcall *%s_mcount_ptr\n", prefix);
- }
-
- else
- {
- static int call_no = 0;
-
- fprintf (file, "\tcall %sPc%d\n", lprefix, call_no);
- fprintf (file, "%sPc%d:\tpopl %%eax\n", lprefix, call_no);
- fprintf (file, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-%sPc%d],%%eax\n",
- lprefix, call_no++);
- fprintf (file, "\tleal %sP%d@GOTOFF(%%eax),%%edx\n",
- lprefix, labelno);
- fprintf (file, "\tmovl %s_mcount_ptr@GOT(%%eax),%%eax\n",
- prefix);
- fprintf (file, "\tcall *(%%eax)\n");
- }
- }
-#endif /* !OSF_OS */
-
- function_prologue (file, size);
-}
-
-#endif /* OSF_OS || TARGET_OSF1ELF */
-
/* Return 0 if the attributes for two types are incompatible, 1 if they
are compatible, and 2 if they are nearly compatible (which causes a
warning to be generated). */
@@ -1455,6 +1470,21 @@ ix86_comp_type_attributes (type1, type2)
return 1;
}
+/* Return the regparm value for a fuctio with the indicated TYPE. */
+
+static int
+ix86_fntype_regparm (type)
+ tree type;
+{
+ tree attr;
+
+ attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
+ if (attr)
+ return TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
+ else
+ return ix86_regparm;
+}
+
/* Value is the number of bytes of arguments automatically
popped when returning from a subroutine call.
FUNDECL is the declaration node of the function (as a tree),
@@ -1498,15 +1528,7 @@ ix86_return_pops_args (fundecl, funtype, size)
if (aggregate_value_p (TREE_TYPE (funtype))
&& !TARGET_64BIT)
{
- int nregs = ix86_regparm;
-
- if (funtype)
- {
- tree attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (funtype));
-
- if (attr)
- nregs = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
- }
+ int nregs = ix86_fntype_regparm (funtype);
if (!nregs)
return GET_MODE_SIZE (Pmode);
@@ -1673,8 +1695,8 @@ classify_argument (mode, type, classes, bit_offset)
(mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
int words = (bytes + (bit_offset % 64) / 8 + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
- /* Variable sized structures are always passed on the stack. */
- if (mode == BLKmode && type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+ /* Variable sized entities are always passed/returned in memory. */
+ if (bytes < 0)
return 0;
if (type && AGGREGATE_TYPE_P (type))
@@ -1722,7 +1744,7 @@ classify_argument (mode, type, classes, bit_offset)
return 0;
for (i = 0; i < num; i++)
{
- int pos = (offset + bit_offset) / 8 / 8;
+ int pos = (offset + (bit_offset % 64)) / 8 / 8;
classes[i + pos] =
merge_classes (subclasses[i], classes[i + pos]);
}
@@ -1759,7 +1781,7 @@ classify_argument (mode, type, classes, bit_offset)
for (i = 0; i < num; i++)
{
int pos =
- (int_bit_position (field) + bit_offset) / 8 / 8;
+ (int_bit_position (field) + (bit_offset % 64)) / 8 / 8;
classes[i + pos] =
merge_classes (subclasses[i], classes[i + pos]);
}
@@ -1805,12 +1827,12 @@ classify_argument (mode, type, classes, bit_offset)
num = classify_argument (TYPE_MODE (type),
type, subclasses,
- (offset + bit_offset) % 256);
+ (offset + (bit_offset % 64)) % 256);
if (!num)
return 0;
for (i = 0; i < num; i++)
{
- int pos = (offset + bit_offset) / 8 / 8;
+ int pos = (offset + (bit_offset % 64)) / 8 / 8;
classes[i + pos] =
merge_classes (subclasses[i], classes[i + pos]);
}
@@ -1922,6 +1944,10 @@ classify_argument (mode, type, classes, bit_offset)
return 1;
case V4SFmode:
case V4SImode:
+ case V16QImode:
+ case V8HImode:
+ case V2DFmode:
+ case V2DImode:
classes[0] = X86_64_SSE_CLASS;
classes[1] = X86_64_SSEUP_CLASS;
return 2;
@@ -1929,8 +1955,7 @@ classify_argument (mode, type, classes, bit_offset)
case V2SImode:
case V4HImode:
case V8QImode:
- classes[0] = X86_64_SSE_CLASS;
- return 1;
+ return 0;
case BLKmode:
case VOIDmode:
return 0;
@@ -2099,13 +2124,15 @@ construct_container (mode, type, in_return, nintregs, nsseregs, intreg, sse_regn
break;
case X86_64_SSE_CLASS:
if (i < n - 1 && class[i + 1] == X86_64_SSEUP_CLASS)
- tmpmode = TImode, i++;
+ tmpmode = TImode;
else
tmpmode = DImode;
exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (tmpmode,
SSE_REGNO (sse_regno)),
GEN_INT (i*8));
+ if (tmpmode == TImode)
+ i++;
sse_regno++;
break;
default:
@@ -2232,6 +2259,9 @@ function_arg (cum, mode, type, named)
break;
case BLKmode:
+ if (bytes < 0)
+ break;
+ /* FALLTHRU */
case DImode:
case SImode:
case HImode:
@@ -2248,11 +2278,11 @@ function_arg (cum, mode, type, named)
if (TARGET_DEBUG_ARG)
{
fprintf (stderr,
- "function_arg (size=%d, wds=%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)
- fprintf (stderr, ", reg=%%e%s", reg_names[ REGNO (ret) ]);
+ print_simple_rtl (stderr, ret);
else
fprintf (stderr, ", stack");
@@ -2262,6 +2292,90 @@ function_arg (cum, mode, type, named)
return ret;
}
+/* Return true when TYPE should be 128bit aligned for 32bit argument passing
+ ABI */
+static bool
+contains_128bit_aligned_vector_p (type)
+ tree type;
+{
+ enum machine_mode mode = TYPE_MODE (type);
+ if (SSE_REG_MODE_P (mode)
+ && (!TYPE_USER_ALIGN (type) || TYPE_ALIGN (type) > 128))
+ return true;
+ if (TYPE_ALIGN (type) < 128)
+ return false;
+
+ if (AGGREGATE_TYPE_P (type))
+ {
+ /* Walk the agregates recursivly. */
+ if (TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE
+ || TREE_CODE (type) == QUAL_UNION_TYPE)
+ {
+ tree field;
+
+ if (TYPE_BINFO (type) != NULL
+ && TYPE_BINFO_BASETYPES (type) != NULL)
+ {
+ tree bases = TYPE_BINFO_BASETYPES (type);
+ int n_bases = TREE_VEC_LENGTH (bases);
+ int i;
+
+ for (i = 0; i < n_bases; ++i)
+ {
+ tree binfo = TREE_VEC_ELT (bases, i);
+ tree type = BINFO_TYPE (binfo);
+
+ if (contains_128bit_aligned_vector_p (type))
+ return true;
+ }
+ }
+ /* And now merge the fields of structure. */
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) == FIELD_DECL
+ && contains_128bit_aligned_vector_p (TREE_TYPE (field)))
+ return true;
+ }
+ }
+ /* Just for use if some languages passes arrays by value. */
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ if (contains_128bit_aligned_vector_p (TREE_TYPE (type)))
+ return true;
+ }
+ else
+ abort ();
+ }
+ return false;
+}
+
+/* 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. */
+
+int
+function_arg_pass_by_reference (cum, mode, type, named)
+ CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ tree type;
+ int named ATTRIBUTE_UNUSED;
+{
+ if (!TARGET_64BIT)
+ return 0;
+
+ if (type && int_size_in_bytes (type) == -1)
+ {
+ if (TARGET_DEBUG_ARG)
+ fprintf (stderr, "function_arg_pass_by_reference\n");
+ return 1;
+ }
+
+ return 0;
+}
+
/* Gives the alignment boundary, in bits, of an argument with the specified mode
and type. */
@@ -2271,14 +2385,34 @@ ix86_function_arg_boundary (mode, type)
tree type;
{
int align;
- if (!TARGET_64BIT)
- return PARM_BOUNDARY;
if (type)
align = TYPE_ALIGN (type);
else
align = GET_MODE_ALIGNMENT (mode);
if (align < PARM_BOUNDARY)
align = PARM_BOUNDARY;
+ if (!TARGET_64BIT)
+ {
+ /* i386 ABI defines all arguments to be 4 byte aligned. We have to
+ make an exception for SSE modes since these require 128bit
+ alignment.
+
+ The handling here differs from field_alignment. ICC aligns MMX
+ arguments to 4 byte boundaries, while structure fields are aligned
+ to 8 byte boundaries. */
+ if (!type)
+ {
+ if (!SSE_REG_MODE_P (mode))
+ align = PARM_BOUNDARY;
+ }
+ else
+ {
+ if (!contains_128bit_aligned_vector_p (type))
+ align = PARM_BOUNDARY;
+ }
+ if (align != PARM_BOUNDARY && !TARGET_SSE)
+ abort();
+ }
if (align > 128)
align = 128;
return align;
@@ -2320,7 +2454,8 @@ ix86_function_value (valtype)
return ret;
}
else
- return gen_rtx_REG (TYPE_MODE (valtype), VALUE_REGNO (TYPE_MODE (valtype)));
+ return gen_rtx_REG (TYPE_MODE (valtype),
+ ix86_value_regno (TYPE_MODE (valtype)));
}
/* Return false iff type is returned in memory. */
@@ -2370,7 +2505,20 @@ ix86_libcall_value (mode)
}
}
else
- return gen_rtx_REG (mode, VALUE_REGNO (mode));
+ return gen_rtx_REG (mode, ix86_value_regno (mode));
+}
+
+/* Given a mode, return the register to use for a return value. */
+
+static int
+ix86_value_regno (mode)
+ enum machine_mode mode;
+{
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_FLOAT_RETURNS_IN_80387)
+ return FIRST_FLOAT_REG;
+ if (mode == TImode || VECTOR_MODE_P (mode))
+ return FIRST_SSE_REG;
+ return 0;
}
/* Create the va_list data type. */
@@ -2384,12 +2532,12 @@ ix86_build_va_list ()
if (!TARGET_64BIT)
return build_pointer_type (char_type_node);
- record = make_lang_type (RECORD_TYPE);
+ record = (*lang_hooks.types.make_type) (RECORD_TYPE);
type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
- f_gpr = build_decl (FIELD_DECL, get_identifier ("gp_offset"),
+ f_gpr = build_decl (FIELD_DECL, get_identifier ("gp_offset"),
unsigned_type_node);
- f_fpr = build_decl (FIELD_DECL, get_identifier ("fp_offset"),
+ f_fpr = build_decl (FIELD_DECL, get_identifier ("fp_offset"),
unsigned_type_node);
f_ovf = build_decl (FIELD_DECL, get_identifier ("overflow_arg_area"),
ptr_type_node);
@@ -2415,7 +2563,7 @@ ix86_build_va_list ()
}
/* Perform any needed actions needed for a function that is receiving a
- variable number of arguments.
+ variable number of arguments.
CUM is as above.
@@ -2454,6 +2602,8 @@ ix86_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
/* Indicate to allocate space on the stack for varargs save area. */
ix86_save_varrargs_registers = 1;
+ cfun->stack_alignment_needed = 128;
+
fntype = TREE_TYPE (current_function_decl);
stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
@@ -2529,8 +2679,7 @@ ix86_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
/* Implement va_start. */
void
-ix86_va_start (stdarg_p, valist, nextarg)
- int stdarg_p;
+ix86_va_start (valist, nextarg)
tree valist;
rtx nextarg;
{
@@ -2541,7 +2690,7 @@ ix86_va_start (stdarg_p, valist, nextarg)
/* Only 64bit target needs something special. */
if (!TARGET_64BIT)
{
- std_expand_builtin_va_start (stdarg_p, valist, nextarg);
+ std_expand_builtin_va_start (valist, nextarg);
return;
}
@@ -2590,7 +2739,6 @@ ix86_va_start (stdarg_p, valist, nextarg)
t = build (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
- cfun->preferred_stack_boundary = 128;
}
/* Implement va_arg. */
@@ -2598,13 +2746,14 @@ rtx
ix86_va_arg (valist, type)
tree valist, type;
{
- static int intreg[6] = { 0, 1, 2, 3, 4, 5 };
+ static const int intreg[6] = { 0, 1, 2, 3, 4, 5 };
tree f_gpr, f_fpr, f_ovf, f_sav;
tree gpr, fpr, ovf, sav, t;
int size, rsize;
rtx lab_false, lab_over = NULL_RTX;
rtx addr_rtx, r;
rtx container;
+ int indirect_p = 0;
/* Only 64bit target needs something special. */
if (!TARGET_64BIT)
@@ -2624,6 +2773,13 @@ ix86_va_arg (valist, type)
sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
size = int_size_in_bytes (type);
+ if (size == -1)
+ {
+ /* Passed by reference. */
+ indirect_p = 1;
+ type = build_pointer_type (type);
+ size = int_size_in_bytes (type);
+ }
rsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
container = construct_container (TYPE_MODE (type), type, 0,
@@ -2728,10 +2884,12 @@ ix86_va_arg (valist, type)
{
int i;
rtx mem;
+ rtx x;
/* Never use the memory itself, as it has the alias set. */
- addr_rtx = XEXP (assign_temp (type, 0, 1, 0), 0);
- mem = gen_rtx_MEM (BLKmode, addr_rtx);
+ x = XEXP (assign_temp (type, 0, 1, 0), 0);
+ mem = gen_rtx_MEM (BLKmode, x);
+ force_operand (x, addr_rtx);
set_mem_alias_set (mem, get_varargs_alias_set ());
set_mem_align (mem, BITS_PER_UNIT);
@@ -2814,9 +2972,53 @@ ix86_va_arg (valist, type)
if (container)
emit_label (lab_over);
+ if (indirect_p)
+ {
+ r = gen_rtx_MEM (Pmode, addr_rtx);
+ set_mem_alias_set (r, get_varargs_alias_set ());
+ emit_move_insn (addr_rtx, r);
+ }
+
return addr_rtx;
}
+/* Return nonzero if OP is either a i387 or SSE fp register. */
+int
+any_fp_register_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return ANY_FP_REG_P (op);
+}
+
+/* Return nonzero if OP is an i387 fp register. */
+int
+fp_register_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return FP_REG_P (op);
+}
+
+/* Return nonzero if OP is a non-fp register_operand. */
+int
+register_and_not_any_fp_reg_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return register_operand (op, mode) && !ANY_FP_REG_P (op);
+}
+
+/* Return nonzero of OP is a register operand other than an
+ i387 fp register. */
+int
+register_and_not_fp_reg_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return register_operand (op, mode) && !FP_REG_P (op);
+}
+
/* Return nonzero if OP is general operand representable on x86_64. */
int
@@ -2876,6 +3078,29 @@ x86_64_movabs_operand (op, mode)
return 0;
}
+/* Return nonzero if OPNUM's MEM should be matched
+ in movabs* patterns. */
+
+int
+ix86_check_movabs (insn, opnum)
+ rtx insn;
+ int opnum;
+{
+ rtx set, mem;
+
+ set = PATTERN (insn);
+ if (GET_CODE (set) == PARALLEL)
+ set = XVECEXP (set, 0, 0);
+ if (GET_CODE (set) != SET)
+ abort ();
+ mem = XEXP (set, opnum);
+ while (GET_CODE (mem) == SUBREG)
+ mem = SUBREG_REG (mem);
+ if (GET_CODE (mem) != MEM)
+ abort ();
+ return (volatile_ok || !MEM_VOLATILE_P (mem));
+}
+
/* Return nonzero if OP is nonmemory operand representable on x86_64. */
int
@@ -2953,9 +3178,9 @@ symbolic_operand (op, mode)
if (GET_CODE (op) == SYMBOL_REF
|| GET_CODE (op) == LABEL_REF
|| (GET_CODE (op) == UNSPEC
- && (XINT (op, 1) == 6
- || XINT (op, 1) == 7
- || XINT (op, 1) == 15)))
+ && (XINT (op, 1) == UNSPEC_GOT
+ || XINT (op, 1) == UNSPEC_GOTOFF
+ || XINT (op, 1) == UNSPEC_GOTPCREL)))
return 1;
if (GET_CODE (op) != PLUS
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
@@ -2967,7 +3192,7 @@ symbolic_operand (op, mode)
return 1;
/* Only @GOTOFF gets offsets. */
if (GET_CODE (op) != UNSPEC
- || XINT (op, 1) != 7)
+ || XINT (op, 1) != UNSPEC_GOTOFF)
return 0;
op = XVECEXP (op, 0, 0);
@@ -2996,7 +3221,7 @@ pic_symbolic_operand (op, mode)
if (GET_CODE (XEXP (op, 0)) == UNSPEC)
return 1;
}
- else
+ else
{
if (GET_CODE (op) == UNSPEC)
return 1;
@@ -3017,14 +3242,14 @@ local_symbolic_operand (op, mode)
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
- if (GET_CODE (op) == LABEL_REF)
- return 1;
-
if (GET_CODE (op) == CONST
&& GET_CODE (XEXP (op, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
op = XEXP (XEXP (op, 0), 0);
+ if (GET_CODE (op) == LABEL_REF)
+ return 1;
+
if (GET_CODE (op) != SYMBOL_REF)
return 0;
@@ -3034,10 +3259,10 @@ local_symbolic_operand (op, mode)
return 1;
/* There is, however, a not insubstantial body of code in the rest of
- the compiler that assumes it can just stick the results of
+ the compiler that assumes it can just stick the results of
ASM_GENERATE_INTERNAL_LABEL in a symbol_ref and have done. */
/* ??? This is a hack. Should update the body of the compiler to
- always create a DECL an invoke ENCODE_SECTION_INFO. */
+ always create a DECL an invoke targetm.encode_section_info. */
if (strncmp (XSTR (op, 0), internal_label_prefix,
internal_label_prefix_len) == 0)
return 1;
@@ -3045,6 +3270,70 @@ local_symbolic_operand (op, mode)
return 0;
}
+/* Test for various thread-local symbols. See ix86_encode_section_info. */
+
+int
+tls_symbolic_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ const char *symbol_str;
+
+ if (GET_CODE (op) != SYMBOL_REF)
+ return 0;
+ symbol_str = XSTR (op, 0);
+
+ if (symbol_str[0] != '%')
+ return 0;
+ return strchr (tls_model_chars, symbol_str[1]) - tls_model_chars;
+}
+
+static int
+tls_symbolic_operand_1 (op, kind)
+ rtx op;
+ enum tls_model kind;
+{
+ const char *symbol_str;
+
+ if (GET_CODE (op) != SYMBOL_REF)
+ return 0;
+ symbol_str = XSTR (op, 0);
+
+ return symbol_str[0] == '%' && symbol_str[1] == tls_model_chars[kind];
+}
+
+int
+global_dynamic_symbolic_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return tls_symbolic_operand_1 (op, TLS_MODEL_GLOBAL_DYNAMIC);
+}
+
+int
+local_dynamic_symbolic_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return tls_symbolic_operand_1 (op, TLS_MODEL_LOCAL_DYNAMIC);
+}
+
+int
+initial_exec_symbolic_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return tls_symbolic_operand_1 (op, TLS_MODEL_INITIAL_EXEC);
+}
+
+int
+local_exec_symbolic_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return tls_symbolic_operand_1 (op, TLS_MODEL_LOCAL_EXEC);
+}
+
/* Test for a valid operand for a call instruction. Don't allow the
arg pointer register or virtual regs since they may decay into
reg + const, which the patterns can't handle. */
@@ -3072,11 +3361,6 @@ call_insn_operand (op, mode)
if (GET_CODE (op) == SYMBOL_REF)
return 1;
- /* Half-pic doesn't allow anything but registers and constants.
- We've just taken care of the later. */
- if (HALF_PIC_P ())
- return register_operand (op, Pmode);
-
/* Otherwise we can allow any general_operand in the address. */
return general_operand (op, Pmode);
}
@@ -3221,6 +3505,30 @@ nonmemory_no_elim_operand (op, mode)
return GET_CODE (op) == CONST_INT || register_operand (op, mode);
}
+/* Return false if this is any eliminable register or stack register,
+ otherwise work like register_operand. */
+
+int
+index_register_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ rtx t = op;
+ if (GET_CODE (t) == SUBREG)
+ t = SUBREG_REG (t);
+ if (!REG_P (t))
+ return 0;
+ if (t == arg_pointer_rtx
+ || t == frame_pointer_rtx
+ || t == virtual_incoming_args_rtx
+ || t == virtual_stack_vars_rtx
+ || t == virtual_stack_dynamic_rtx
+ || REGNO (t) == STACK_POINTER_REGNUM)
+ return 0;
+
+ return general_operand (op, mode);
+}
+
/* Return true if op is a Q_REGS class register. */
int
@@ -3249,6 +3557,19 @@ non_q_regs_operand (op, mode)
return NON_QI_REG_P (op);
}
+/* Return 1 when OP is operand acceptable for standard SSE move. */
+int
+vector_move_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (nonimmediate_operand (op, mode))
+ return 1;
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return 0;
+ return (op == CONST0_RTX (GET_MODE (op)));
+}
+
/* Return 1 if OP is a comparison that can be used in the CMPSS/CMPPS
insns. */
int
@@ -3560,6 +3881,11 @@ aligned_operand (op, mode)
if (! ix86_decompose_address (op, &parts))
abort ();
+ if (parts.base && GET_CODE (parts.base) == SUBREG)
+ parts.base = SUBREG_REG (parts.base);
+ if (parts.index && GET_CODE (parts.index) == SUBREG)
+ parts.index = SUBREG_REG (parts.index);
+
/* Look for some component that isn't known to be aligned. */
if (parts.index)
{
@@ -3609,8 +3935,8 @@ int
standard_sse_constant_p (x)
rtx x;
{
- if (GET_CODE (x) != CONST_DOUBLE)
- return -1;
+ if (x == const0_rtx)
+ return 1;
return (x == CONST0_RTX (GET_MODE (x)));
}
@@ -3700,22 +4026,33 @@ x86_64_sign_extended_value (value)
}
break;
- /* For certain code models, the symbolic references are known to fit. */
+ /* For certain code models, the symbolic references are known to fit.
+ in CM_SMALL_PIC model we know it fits if it is local to the shared
+ library. Don't count TLS SYMBOL_REFs here, since they should fit
+ only if inside of UNSPEC handled below. */
case SYMBOL_REF:
- return ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL;
+ return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL);
/* For certain code models, the code is near as well. */
case LABEL_REF:
- return ix86_cmodel != CM_LARGE && ix86_cmodel != CM_SMALL_PIC;
+ return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM
+ || ix86_cmodel == CM_KERNEL);
/* We also may accept the offsetted memory references in certain special
cases. */
case CONST:
- if (GET_CODE (XEXP (value, 0)) == UNSPEC
- && XVECLEN (XEXP (value, 0), 0) == 1
- && XINT (XEXP (value, 0), 1) == 15)
- return 1;
- else if (GET_CODE (XEXP (value, 0)) == PLUS)
+ if (GET_CODE (XEXP (value, 0)) == UNSPEC)
+ switch (XINT (XEXP (value, 0), 1))
+ {
+ case UNSPEC_GOTPCREL:
+ case UNSPEC_DTPOFF:
+ case UNSPEC_GOTNTPOFF:
+ case UNSPEC_NTPOFF:
+ return 1;
+ default:
+ break;
+ }
+ if (GET_CODE (XEXP (value, 0)) == PLUS)
{
rtx op1 = XEXP (XEXP (value, 0), 0);
rtx op2 = XEXP (XEXP (value, 0), 1);
@@ -3729,12 +4066,12 @@ x86_64_sign_extended_value (value)
switch (GET_CODE (op1))
{
case SYMBOL_REF:
- /* For CM_SMALL assume that latest object is 1MB before
+ /* For CM_SMALL assume that latest object is 16MB before
end of 31bits boundary. We may also accept pretty
large negative constants knowing that all objects are
in the positive half of address space. */
if (ix86_cmodel == CM_SMALL
- && offset < 1024*1024*1024
+ && offset < 16*1024*1024
&& trunc_int_for_mode (offset, SImode) == offset)
return 1;
/* For CM_KERNEL we know that all object resist in the
@@ -3750,7 +4087,7 @@ x86_64_sign_extended_value (value)
/* These conditions are similar to SYMBOL_REF ones, just the
constraints for code models differ. */
if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM)
- && offset < 1024*1024*1024
+ && offset < 16*1024*1024
&& trunc_int_for_mode (offset, SImode) == offset)
return 1;
if (ix86_cmodel == CM_KERNEL
@@ -3758,6 +4095,16 @@ x86_64_sign_extended_value (value)
&& trunc_int_for_mode (offset, SImode) == offset)
return 1;
break;
+ case UNSPEC:
+ switch (XINT (op1, 1))
+ {
+ case UNSPEC_DTPOFF:
+ case UNSPEC_NTPOFF:
+ if (offset > 0
+ && trunc_int_for_mode (offset, SImode) == offset)
+ return 1;
+ }
+ break;
default:
return 0;
}
@@ -3865,7 +4212,11 @@ ix86_frame_pointer_required ()
/* In override_options, TARGET_OMIT_LEAF_FRAME_POINTER turns off
the frame pointer by default. Turn it back on now if we've not
got a leaf function. */
- if (TARGET_OMIT_LEAF_FRAME_POINTER && ! leaf_function_p ())
+ if (TARGET_OMIT_LEAF_FRAME_POINTER
+ && (!current_function_is_leaf))
+ return 1;
+
+ if (current_function_profile)
return 1;
return 0;
@@ -3879,7 +4230,28 @@ ix86_setup_frame_addresses ()
cfun->machine->accesses_prev_frame = 1;
}
-static char pic_label_name[32];
+#if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY)
+# define USE_HIDDEN_LINKONCE 1
+#else
+# define USE_HIDDEN_LINKONCE 0
+#endif
+
+static int pic_labels_used;
+
+/* Fills in the label name that should be used for a pc thunk for
+ the given register. */
+
+static void
+get_pc_thunk_name (name, regno)
+ char name[32];
+ unsigned int regno;
+{
+ if (USE_HIDDEN_LINKONCE)
+ sprintf (name, "__i686.get_pc_thunk.%s", reg_names[regno]);
+ else
+ ASM_GENERATE_INTERNAL_LABEL (name, "LPR", regno);
+}
+
/* This function generates code for -fpic that loads %ebx with
the return address of the caller and then returns. */
@@ -3889,74 +4261,97 @@ ix86_asm_file_end (file)
FILE *file;
{
rtx xops[2];
+ int regno;
- if (! TARGET_DEEP_BRANCH_PREDICTION || pic_label_name[0] == 0)
- return;
+ for (regno = 0; regno < 8; ++regno)
+ {
+ char name[32];
- /* ??? Binutils 2.10 and earlier has a linkonce elimination bug related
- to updating relocations to a section being discarded such that this
- doesn't work. Ought to detect this at configure time. */
-#if 0
- /* The trick here is to create a linkonce section containing the
- pic label thunk, but to refer to it with an internal label.
- Because the label is internal, we don't have inter-dso name
- binding issues on hosts that don't support ".hidden".
-
- In order to use these macros, however, we must create a fake
- function decl. */
- if (targetm.have_named_sections)
- {
- tree decl = build_decl (FUNCTION_DECL,
- get_identifier ("i686.get_pc_thunk"),
- error_mark_node);
- DECL_ONE_ONLY (decl) = 1;
- UNIQUE_SECTION (decl, 0);
- named_section (decl, NULL);
- }
- else
-#else
- text_section ();
-#endif
+ if (! ((pic_labels_used >> regno) & 1))
+ continue;
+
+ get_pc_thunk_name (name, regno);
+
+ if (USE_HIDDEN_LINKONCE)
+ {
+ tree decl;
- /* This used to call ASM_DECLARE_FUNCTION_NAME() but since it's an
- internal (non-global) label that's being emitted, it didn't make
- sense to have .type information for local labels. This caused
- the SCO OpenServer 5.0.4 ELF assembler grief (why are you giving
- me debug info for a label that you're declaring non-global?) this
- was changed to call ASM_OUTPUT_LABEL() instead. */
+ decl = build_decl (FUNCTION_DECL, get_identifier (name),
+ error_mark_node);
+ TREE_PUBLIC (decl) = 1;
+ TREE_STATIC (decl) = 1;
+ DECL_ONE_ONLY (decl) = 1;
- ASM_OUTPUT_LABEL (file, pic_label_name);
+ (*targetm.asm_out.unique_section) (decl, 0);
+ named_section (decl, NULL, 0);
+
+ (*targetm.asm_out.globalize_label) (file, name);
+ fputs ("\t.hidden\t", file);
+ assemble_name (file, name);
+ fputc ('\n', file);
+ ASM_DECLARE_FUNCTION_NAME (file, name, decl);
+ }
+ else
+ {
+ text_section ();
+ ASM_OUTPUT_LABEL (file, name);
+ }
- xops[0] = pic_offset_table_rtx;
- xops[1] = gen_rtx_MEM (SImode, stack_pointer_rtx);
- output_asm_insn ("mov{l}\t{%1, %0|%0, %1}", xops);
- output_asm_insn ("ret", xops);
+ xops[0] = gen_rtx_REG (SImode, regno);
+ xops[1] = gen_rtx_MEM (SImode, stack_pointer_rtx);
+ output_asm_insn ("mov{l}\t{%1, %0|%0, %1}", xops);
+ output_asm_insn ("ret", xops);
+ }
}
-void
-load_pic_register ()
-{
- rtx gotsym, pclab;
+/* Emit code for the SET_GOT patterns. */
- if (TARGET_64BIT)
- abort ();
+const char *
+output_set_got (dest)
+ rtx dest;
+{
+ rtx xops[3];
- gotsym = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+ xops[0] = dest;
+ xops[1] = gen_rtx_SYMBOL_REF (Pmode, GOT_SYMBOL_NAME);
- if (TARGET_DEEP_BRANCH_PREDICTION)
+ if (! TARGET_DEEP_BRANCH_PREDICTION || !flag_pic)
{
- if (! pic_label_name[0])
- ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", 0);
- pclab = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, pic_label_name));
+ xops[2] = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
+
+ if (!flag_pic)
+ output_asm_insn ("mov{l}\t{%2, %0|%0, %2}", xops);
+ else
+ output_asm_insn ("call\t%a2", xops);
+
+#if TARGET_MACHO
+ /* Output the "canonical" label name ("Lxx$pb") here too. This
+ is what will be referred to by the Mach-O PIC subsystem. */
+ ASM_OUTPUT_LABEL (asm_out_file, machopic_function_base_name ());
+#endif
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (XEXP (xops[2], 0)));
+
+ if (flag_pic)
+ output_asm_insn ("pop{l}\t%0", xops);
}
else
{
- pclab = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+ char name[32];
+ get_pc_thunk_name (name, REGNO (dest));
+ pic_labels_used |= 1 << REGNO (dest);
+
+ xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
+ xops[2] = gen_rtx_MEM (QImode, xops[2]);
+ output_asm_insn ("call\t%X2", xops);
}
- emit_insn (gen_prologue_get_pc (pic_offset_table_rtx, pclab));
+ if (!flag_pic || TARGET_DEEP_BRANCH_PREDICTION)
+ output_asm_insn ("add{l}\t{%1, %0|%0, %1}", xops);
+ else if (!TARGET_MACHO)
+ output_asm_insn ("add{l}\t{%1+[.-%a2], %0|%0, %a1+(.-%a2)}", xops);
- emit_insn (gen_prologue_set_got (pic_offset_table_rtx, gotsym, pclab));
+ return "";
}
/* Generate an "push" pattern for input ARG. */
@@ -3972,17 +4367,40 @@ gen_push (arg)
arg);
}
+/* Return >= 0 if there is an unused call-clobbered register available
+ for the entire function. */
+
+static unsigned int
+ix86_select_alt_pic_regnum ()
+{
+ if (current_function_is_leaf && !current_function_profile)
+ {
+ int i;
+ for (i = 2; i >= 0; --i)
+ if (!regs_ever_live[i])
+ return i;
+ }
+
+ return INVALID_REGNUM;
+}
+
/* Return 1 if we need to save REGNO. */
static int
ix86_save_reg (regno, maybe_eh_return)
- int regno;
+ unsigned int regno;
int maybe_eh_return;
{
- if (regno == PIC_OFFSET_TABLE_REGNUM
- && (current_function_uses_pic_offset_table
- || current_function_uses_const_pool
- || current_function_calls_eh_return))
- return 1;
+ if (pic_offset_table_rtx
+ && regno == REAL_PIC_OFFSET_TABLE_REGNUM
+ && (regs_ever_live[REAL_PIC_OFFSET_TABLE_REGNUM]
+ || current_function_profile
+ || current_function_calls_eh_return
+ || current_function_uses_const_pool))
+ {
+ if (ix86_select_alt_pic_regnum () != INVALID_REGNUM)
+ return 0;
+ return 1;
+ }
if (current_function_calls_eh_return && maybe_eh_return)
{
@@ -3992,7 +4410,7 @@ ix86_save_reg (regno, maybe_eh_return)
unsigned test = EH_RETURN_DATA_REGNO (i);
if (test == INVALID_REGNUM)
break;
- if (test == (unsigned) regno)
+ if (test == regno)
return 1;
}
}
@@ -4061,7 +4479,7 @@ ix86_compute_frame_layout (frame)
frame->nregs = ix86_nsaved_regs ();
total_size = size;
- /* Skip return value and save base pointer. */
+ /* Skip return address and saved base pointer. */
offset = frame_pointer_needed ? UNITS_PER_WORD * 2 : UNITS_PER_WORD;
frame->hard_frame_pointer_offset = offset;
@@ -4203,9 +4621,7 @@ void
ix86_expand_prologue ()
{
rtx insn;
- int pic_reg_used = (flag_pic && (current_function_uses_pic_offset_table
- || current_function_uses_const_pool)
- && !TARGET_64BIT);
+ bool pic_reg_used;
struct ix86_frame frame;
int use_mov = 0;
HOST_WIDE_INT allocate;
@@ -4270,6 +4686,10 @@ ix86_expand_prologue ()
CALL_INSN_FUNCTION_USAGE (insn)
= gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_USE (VOIDmode, arg0),
CALL_INSN_FUNCTION_USAGE (insn));
+
+ /* Don't allow scheduling pass to move insns across __alloca
+ call. */
+ emit_insn (gen_blockage (const0_rtx));
}
if (use_mov)
{
@@ -4284,14 +4704,36 @@ ix86_expand_prologue ()
SUBTARGET_PROLOGUE;
#endif
+ pic_reg_used = false;
+ if (pic_offset_table_rtx
+ && (regs_ever_live[REAL_PIC_OFFSET_TABLE_REGNUM]
+ || current_function_profile))
+ {
+ unsigned int alt_pic_reg_used = ix86_select_alt_pic_regnum ();
+
+ if (alt_pic_reg_used != INVALID_REGNUM)
+ REGNO (pic_offset_table_rtx) = alt_pic_reg_used;
+
+ pic_reg_used = true;
+ }
+
if (pic_reg_used)
- load_pic_register ();
+ {
+ insn = emit_insn (gen_set_got (pic_offset_table_rtx));
- /* 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 (current_function_profile && ! pic_reg_used)
- emit_insn (gen_blockage ());
+ /* Even with accurate pre-reload life analysis, we can wind up
+ deleting all references to the pic register after reload.
+ Consider if cross-jumping unifies two sides of a branch
+ controled by a comparison vs the only read from a global.
+ In which case, allow the set_got to be deleted, though we're
+ too late to do anything about the ebx save in the prologue. */
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
+ }
+
+ /* Prevent function calls from be scheduled before the call to mcount.
+ In the pic_reg_used case, make sure that the got load isn't deleted. */
+ if (current_function_profile)
+ emit_insn (gen_blockage (pic_reg_used ? pic_offset_table_rtx : const0_rtx));
}
/* Emit code to restore saved registers using MOV insns. First register
@@ -4480,6 +4922,17 @@ ix86_expand_epilogue (style)
else
emit_jump_insn (gen_return_internal ());
}
+
+/* Reset from the function's potential modifications. */
+
+static void
+ix86_output_function_epilogue (file, size)
+ FILE *file ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+{
+ if (pic_offset_table_rtx)
+ REGNO (pic_offset_table_rtx) = REAL_PIC_OFFSET_TABLE_REGNUM;
+}
/* Extract the parts of an RTL expression that is a valid memory address
for an instruction. Return 0 if the structure of the address is
@@ -4499,7 +4952,7 @@ ix86_decompose_address (addr, out)
rtx scale_rtx = NULL_RTX;
int retval = 1;
- if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG)
+ if (REG_P (addr) || GET_CODE (addr) == SUBREG)
base = addr;
else if (GET_CODE (addr) == PLUS)
{
@@ -4626,6 +5079,11 @@ ix86_address_cost (x)
if (!ix86_decompose_address (x, &parts))
abort ();
+ if (parts.base && GET_CODE (parts.base) == SUBREG)
+ parts.base = SUBREG_REG (parts.base);
+ if (parts.index && GET_CODE (parts.index) == SUBREG)
+ parts.index = SUBREG_REG (parts.index);
+
/* More complex memory references are better. */
if (parts.disp && parts.disp != const0_rtx)
cost--;
@@ -4689,8 +5147,7 @@ ix86_find_base_term (x)
|| GET_CODE (XEXP (term, 1)) == CONST_DOUBLE))
term = XEXP (term, 0);
if (GET_CODE (term) != UNSPEC
- || XVECLEN (term, 0) != 1
- || XINT (term, 1) != 15)
+ || XINT (term, 1) != UNSPEC_GOTPCREL)
return x;
term = XVECEXP (term, 0, 0);
@@ -4713,8 +5170,7 @@ ix86_find_base_term (x)
term = XEXP (term, 0);
if (GET_CODE (term) != UNSPEC
- || XVECLEN (term, 0) != 1
- || XINT (term, 1) != 7)
+ || XINT (term, 1) != UNSPEC_GOTOFF)
return x;
term = XVECEXP (term, 0, 0);
@@ -4726,6 +5182,125 @@ ix86_find_base_term (x)
return term;
}
+/* Determine if a given RTX is a valid constant. We already know this
+ satisfies CONSTANT_P. */
+
+bool
+legitimate_constant_p (x)
+ rtx x;
+{
+ rtx inner;
+
+ switch (GET_CODE (x))
+ {
+ case SYMBOL_REF:
+ /* TLS symbols are not constant. */
+ if (tls_symbolic_operand (x, Pmode))
+ return false;
+ break;
+
+ case CONST:
+ inner = XEXP (x, 0);
+
+ /* Offsets of TLS symbols are never valid.
+ Discourage CSE from creating them. */
+ if (GET_CODE (inner) == PLUS
+ && tls_symbolic_operand (XEXP (inner, 0), Pmode))
+ return false;
+
+ /* Only some unspecs are valid as "constants". */
+ if (GET_CODE (inner) == UNSPEC)
+ switch (XINT (inner, 1))
+ {
+ case UNSPEC_TPOFF:
+ return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
+ default:
+ return false;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Otherwise we handle everything else in the move patterns. */
+ return true;
+}
+
+/* Determine if it's legal to put X into the constant pool. This
+ is not possible for the address of thread-local symbols, which
+ is checked above. */
+
+static bool
+ix86_cannot_force_const_mem (x)
+ rtx x;
+{
+ return !legitimate_constant_p (x);
+}
+
+/* Determine if a given RTX is a valid constant address. */
+
+bool
+constant_address_p (x)
+ rtx x;
+{
+ switch (GET_CODE (x))
+ {
+ case LABEL_REF:
+ case CONST_INT:
+ return true;
+
+ case CONST_DOUBLE:
+ return TARGET_64BIT;
+
+ case CONST:
+ /* For Mach-O, really believe the CONST. */
+ if (TARGET_MACHO)
+ return true;
+ /* Otherwise fall through. */
+ case SYMBOL_REF:
+ return !flag_pic && legitimate_constant_p (x);
+
+ default:
+ return false;
+ }
+}
+
+/* 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. */
+
+bool
+legitimate_pic_operand_p (x)
+ rtx x;
+{
+ rtx inner;
+
+ switch (GET_CODE (x))
+ {
+ case CONST:
+ inner = XEXP (x, 0);
+
+ /* Only some unspecs are valid as "constants". */
+ if (GET_CODE (inner) == UNSPEC)
+ switch (XINT (inner, 1))
+ {
+ case UNSPEC_TPOFF:
+ return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
+ default:
+ return false;
+ }
+ /* FALLTHRU */
+
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return legitimate_pic_address_disp_p (x);
+
+ default:
+ return true;
+ }
+}
+
/* Determine if a given CONST RTX is a valid memory displacement
in PIC mode. */
@@ -4733,21 +5308,32 @@ int
legitimate_pic_address_disp_p (disp)
register rtx disp;
{
+ bool saw_plus;
+
/* In 64bit mode we can allow direct addresses of symbols and labels
when they are not dynamic symbols. */
if (TARGET_64BIT)
{
- rtx x = disp;
- if (GET_CODE (disp) == CONST)
- x = XEXP (disp, 0);
- /* ??? Handle PIC code models */
- if (GET_CODE (x) == PLUS
- && (GET_CODE (XEXP (x, 1)) == CONST_INT
- && ix86_cmodel == CM_SMALL_PIC
- && INTVAL (XEXP (x, 1)) < 1024*1024*1024
- && INTVAL (XEXP (x, 1)) > -1024*1024*1024))
- x = XEXP (x, 0);
- if (local_symbolic_operand (x, Pmode))
+ /* TLS references should always be enclosed in UNSPEC. */
+ if (tls_symbolic_operand (disp, GET_MODE (disp)))
+ return 0;
+ if (GET_CODE (disp) == SYMBOL_REF
+ && ix86_cmodel == CM_SMALL_PIC
+ && (CONSTANT_POOL_ADDRESS_P (disp)
+ || SYMBOL_REF_FLAG (disp)))
+ return 1;
+ if (GET_CODE (disp) == LABEL_REF)
+ return 1;
+ if (GET_CODE (disp) == CONST
+ && GET_CODE (XEXP (disp, 0)) == PLUS
+ && ((GET_CODE (XEXP (XEXP (disp, 0), 0)) == SYMBOL_REF
+ && ix86_cmodel == CM_SMALL_PIC
+ && (CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (disp, 0), 0))
+ || SYMBOL_REF_FLAG (XEXP (XEXP (disp, 0), 0))))
+ || GET_CODE (XEXP (XEXP (disp, 0), 0)) == LABEL_REF)
+ && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT
+ && INTVAL (XEXP (XEXP (disp, 0), 1)) < 16*1024*1024
+ && INTVAL (XEXP (XEXP (disp, 0), 1)) >= -16*1024*1024)
return 1;
}
if (GET_CODE (disp) != CONST)
@@ -4759,8 +5345,7 @@ legitimate_pic_address_disp_p (disp)
/* We are unsafe to allow PLUS expressions. This limit allowed distance
of GOT tables. We should not need these anyway. */
if (GET_CODE (disp) != UNSPEC
- || XVECLEN (disp, 0) != 1
- || XINT (disp, 1) != 15)
+ || XINT (disp, 1) != UNSPEC_GOTPCREL)
return 0;
if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
@@ -4769,27 +5354,51 @@ legitimate_pic_address_disp_p (disp)
return 1;
}
+ saw_plus = false;
if (GET_CODE (disp) == PLUS)
{
if (GET_CODE (XEXP (disp, 1)) != CONST_INT)
return 0;
disp = XEXP (disp, 0);
+ saw_plus = true;
}
- if (GET_CODE (disp) != UNSPEC
- || XVECLEN (disp, 0) != 1)
+ /* Allow {LABEL | SYMBOL}_REF - SYMBOL_REF-FOR-PICBASE for Mach-O. */
+ if (TARGET_MACHO && GET_CODE (disp) == MINUS)
+ {
+ if (GET_CODE (XEXP (disp, 0)) == LABEL_REF
+ || GET_CODE (XEXP (disp, 0)) == SYMBOL_REF)
+ if (GET_CODE (XEXP (disp, 1)) == SYMBOL_REF)
+ {
+ const char *sym_name = XSTR (XEXP (disp, 1), 0);
+ if (strstr (sym_name, "$pb") != 0)
+ return 1;
+ }
+ }
+
+ if (GET_CODE (disp) != UNSPEC)
return 0;
- /* Must be @GOT or @GOTOFF. */
switch (XINT (disp, 1))
{
- case 6: /* @GOT */
+ case UNSPEC_GOT:
+ if (saw_plus)
+ return false;
return GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF;
-
- case 7: /* @GOTOFF */
+ case UNSPEC_GOTOFF:
return local_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
+ case UNSPEC_GOTTPOFF:
+ case UNSPEC_GOTNTPOFF:
+ case UNSPEC_INDNTPOFF:
+ if (saw_plus)
+ return false;
+ return initial_exec_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
+ case UNSPEC_NTPOFF:
+ return local_exec_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
+ case UNSPEC_DTPOFF:
+ return local_dynamic_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
}
-
+
return 0;
}
@@ -4821,6 +5430,13 @@ legitimate_address_p (mode, addr, strict)
debug_rtx (addr);
}
+ if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_TP)
+ {
+ if (TARGET_DEBUG_ADDR)
+ fprintf (stderr, "Success.\n");
+ return TRUE;
+ }
+
if (ix86_decompose_address (addr, &parts) <= 0)
{
reason = "decomposition failed";
@@ -4840,9 +5456,15 @@ legitimate_address_p (mode, addr, strict)
if (base)
{
+ rtx reg;
reason_rtx = base;
- if (GET_CODE (base) != REG)
+ if (GET_CODE (base) == SUBREG)
+ reg = SUBREG_REG (base);
+ else
+ reg = base;
+
+ if (GET_CODE (reg) != REG)
{
reason = "base is not a register";
goto report_error;
@@ -4854,8 +5476,8 @@ legitimate_address_p (mode, addr, strict)
goto report_error;
}
- 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 (reg))
+ || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (reg)))
{
reason = "base is not valid";
goto report_error;
@@ -4870,9 +5492,15 @@ legitimate_address_p (mode, addr, strict)
if (index)
{
+ rtx reg;
reason_rtx = index;
- if (GET_CODE (index) != REG)
+ if (GET_CODE (index) == SUBREG)
+ reg = SUBREG_REG (index);
+ else
+ reg = index;
+
+ if (GET_CODE (reg) != REG)
{
reason = "index is not a register";
goto report_error;
@@ -4884,8 +5512,8 @@ legitimate_address_p (mode, addr, strict)
goto report_error;
}
- if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (index))
- || (! strict && ! REG_OK_FOR_INDEX_NONSTRICT_P (index)))
+ if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (reg))
+ || (! strict && ! REG_OK_FOR_INDEX_NONSTRICT_P (reg)))
{
reason = "index is not valid";
goto report_error;
@@ -4914,37 +5542,51 @@ legitimate_address_p (mode, addr, strict)
{
reason_rtx = disp;
- if (!CONSTANT_ADDRESS_P (disp))
- {
- reason = "displacement is not constant";
- goto report_error;
- }
+ if (GET_CODE (disp) == CONST
+ && GET_CODE (XEXP (disp, 0)) == UNSPEC)
+ switch (XINT (XEXP (disp, 0), 1))
+ {
+ case UNSPEC_GOT:
+ case UNSPEC_GOTOFF:
+ case UNSPEC_GOTPCREL:
+ if (!flag_pic)
+ abort ();
+ goto is_legitimate_pic;
- if (TARGET_64BIT)
- {
- if (!x86_64_sign_extended_value (disp))
- {
- reason = "displacement is out of range";
- goto report_error;
- }
- }
- else
- {
- if (GET_CODE (disp) == CONST_DOUBLE)
- {
- reason = "displacement is a const_double";
- goto report_error;
- }
- }
+ case UNSPEC_GOTTPOFF:
+ case UNSPEC_GOTNTPOFF:
+ case UNSPEC_INDNTPOFF:
+ case UNSPEC_NTPOFF:
+ case UNSPEC_DTPOFF:
+ break;
- if (flag_pic && SYMBOLIC_CONST (disp))
+ default:
+ reason = "invalid address unspec";
+ goto report_error;
+ }
+
+ else if (flag_pic && (SYMBOLIC_CONST (disp)
+#if TARGET_MACHO
+ && !machopic_operand_p (disp)
+#endif
+ ))
{
+ is_legitimate_pic:
if (TARGET_64BIT && (index || base))
{
- reason = "non-constant pic memory reference";
- goto report_error;
+ /* foo@dtpoff(%rX) is ok. */
+ if (GET_CODE (disp) != CONST
+ || GET_CODE (XEXP (disp, 0)) != PLUS
+ || GET_CODE (XEXP (XEXP (disp, 0), 0)) != UNSPEC
+ || GET_CODE (XEXP (XEXP (disp, 0), 1)) != CONST_INT
+ || (XINT (XEXP (XEXP (disp, 0), 0), 1) != UNSPEC_DTPOFF
+ && XINT (XEXP (XEXP (disp, 0), 0), 1) != UNSPEC_NTPOFF))
+ {
+ reason = "non-constant pic memory reference";
+ goto report_error;
+ }
}
- if (! legitimate_pic_address_disp_p (disp))
+ else if (! legitimate_pic_address_disp_p (disp))
{
reason = "displacement is an invalid pic construct";
goto report_error;
@@ -4972,14 +5614,20 @@ legitimate_address_p (mode, addr, strict)
that never results in lea, this seems to be easier and
correct fix for crash to disable this test. */
}
- else if (HALF_PIC_P ())
+ else if (!CONSTANT_ADDRESS_P (disp))
{
- if (! HALF_PIC_ADDRESS_P (disp)
- || (base != NULL_RTX || index != NULL_RTX))
- {
- reason = "displacement is an invalid half-pic reference";
- goto report_error;
- }
+ reason = "displacement is not constant";
+ goto report_error;
+ }
+ else if (TARGET_64BIT && !x86_64_sign_extended_value (disp))
+ {
+ reason = "displacement is out of range";
+ goto report_error;
+ }
+ else if (!TARGET_64BIT && GET_CODE (disp) == CONST_DOUBLE)
+ {
+ reason = "displacement is a const_double";
+ goto report_error;
}
}
@@ -4988,7 +5636,7 @@ legitimate_address_p (mode, addr, strict)
fprintf (stderr, "Success.\n");
return TRUE;
-report_error:
+ report_error:
if (TARGET_DEBUG_ADDR)
{
fprintf (stderr, "Error: %s\n", reason);
@@ -5002,10 +5650,10 @@ report_error:
static HOST_WIDE_INT
ix86_GOT_alias_set ()
{
- static HOST_WIDE_INT set = -1;
- if (set == -1)
- set = new_alias_set ();
- return set;
+ static HOST_WIDE_INT set = -1;
+ if (set == -1)
+ set = new_alias_set ();
+ return set;
}
/* Return a legitimate reference for ORIG (an address) using the
@@ -5035,34 +5683,37 @@ legitimize_pic_address (orig, reg)
rtx new = orig;
rtx base;
- if (local_symbolic_operand (addr, Pmode))
+#if TARGET_MACHO
+ if (reg == 0)
+ reg = gen_reg_rtx (Pmode);
+ /* Use the generic Mach-O PIC machinery. */
+ return machopic_legitimize_pic_address (orig, GET_MODE (orig), reg);
+#endif
+
+ if (TARGET_64BIT && legitimate_pic_address_disp_p (addr))
+ new = addr;
+ else if (!TARGET_64BIT && local_symbolic_operand (addr, Pmode))
{
- /* In 64bit mode we can address such objects directly. */
- if (TARGET_64BIT)
- new = addr;
- else
- {
- /* This symbol may be referenced via a displacement from the PIC
- base address (@GOTOFF). */
+ /* This symbol may be referenced via a displacement from the PIC
+ base address (@GOTOFF). */
- current_function_uses_pic_offset_table = 1;
- new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 7);
- new = gen_rtx_CONST (Pmode, new);
- new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
+ if (reload_in_progress)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
+ new = gen_rtx_CONST (Pmode, new);
+ new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
- if (reg != 0)
- {
- emit_move_insn (reg, new);
- new = reg;
- }
- }
+ if (reg != 0)
+ {
+ emit_move_insn (reg, new);
+ new = reg;
+ }
}
else if (GET_CODE (addr) == SYMBOL_REF)
{
if (TARGET_64BIT)
{
- current_function_uses_pic_offset_table = 1;
- new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 15);
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTPCREL);
new = gen_rtx_CONST (Pmode, new);
new = gen_rtx_MEM (Pmode, new);
RTX_UNCHANGING_P (new) = 1;
@@ -5081,8 +5732,9 @@ legitimize_pic_address (orig, reg)
/* This symbol must be referenced via a load from the
Global Offset Table (@GOT). */
- current_function_uses_pic_offset_table = 1;
- new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 6);
+ if (reload_in_progress)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
new = gen_rtx_CONST (Pmode, new);
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
new = gen_rtx_MEM (Pmode, new);
@@ -5122,8 +5774,10 @@ legitimize_pic_address (orig, reg)
{
if (!TARGET_64BIT)
{
- current_function_uses_pic_offset_table = 1;
- new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), 7);
+ if (reload_in_progress)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0),
+ UNSPEC_GOTOFF);
new = gen_rtx_PLUS (Pmode, new, op1);
new = gen_rtx_CONST (Pmode, new);
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
@@ -5136,7 +5790,9 @@ legitimize_pic_address (orig, reg)
}
else
{
- /* ??? We need to limit offsets here. */
+ if (INTVAL (op1) < -16*1024*1024
+ || INTVAL (op1) >= 16*1024*1024)
+ new = gen_rtx_PLUS (Pmode, op0, force_reg (Pmode, op1));
}
}
else
@@ -5161,7 +5817,102 @@ legitimize_pic_address (orig, reg)
}
return new;
}
+
+static void
+ix86_encode_section_info (decl, first)
+ tree decl;
+ int first ATTRIBUTE_UNUSED;
+{
+ bool local_p = (*targetm.binds_local_p) (decl);
+ rtx rtl, symbol;
+
+ rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl);
+ if (GET_CODE (rtl) != MEM)
+ return;
+ symbol = XEXP (rtl, 0);
+ if (GET_CODE (symbol) != SYMBOL_REF)
+ return;
+
+ /* For basic x86, if using PIC, mark a SYMBOL_REF for a non-global
+ symbol so that we may access it directly in the GOT. */
+
+ if (flag_pic)
+ SYMBOL_REF_FLAG (symbol) = local_p;
+
+ /* For ELF, encode thread-local data with %[GLil] for "global dynamic",
+ "local dynamic", "initial exec" or "local exec" TLS models
+ respectively. */
+
+ if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
+ {
+ const char *symbol_str;
+ char *newstr;
+ size_t len;
+ enum tls_model kind = decl_tls_model (decl);
+
+ if (TARGET_64BIT && ! flag_pic)
+ {
+ /* x86-64 doesn't allow non-pic code for shared libraries,
+ so don't generate GD/LD TLS models for non-pic code. */
+ switch (kind)
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ kind = TLS_MODEL_INITIAL_EXEC; break;
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ kind = TLS_MODEL_LOCAL_EXEC; break;
+ default:
+ break;
+ }
+ }
+
+ symbol_str = XSTR (symbol, 0);
+
+ if (symbol_str[0] == '%')
+ {
+ if (symbol_str[1] == tls_model_chars[kind])
+ return;
+ symbol_str += 2;
+ }
+ len = strlen (symbol_str) + 1;
+ newstr = alloca (len + 2);
+
+ newstr[0] = '%';
+ newstr[1] = tls_model_chars[kind];
+ memcpy (newstr + 2, symbol_str, len);
+
+ XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1);
+ }
+}
+
+/* Undo the above when printing symbol names. */
+
+static const char *
+ix86_strip_name_encoding (str)
+ const char *str;
+{
+ if (str[0] == '%')
+ str += 2;
+ if (str [0] == '*')
+ str += 1;
+ return str;
+}
+/* Load the thread pointer into a register. */
+
+static rtx
+get_thread_pointer ()
+{
+ rtx tp;
+
+ tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP);
+ tp = gen_rtx_MEM (Pmode, tp);
+ RTX_UNCHANGING_P (tp) = 1;
+ set_mem_alias_set (tp, ix86_GOT_alias_set ());
+ tp = force_reg (Pmode, tp);
+
+ return tp;
+}
+
/* Try machine-dependent ways of modifying an illegitimate address
to be legitimate. If we find one, return the new, valid address.
This macro is used in only one place: `memory_address' in explow.c.
@@ -5199,6 +5950,123 @@ legitimize_address (x, oldx, mode)
debug_rtx (x);
}
+ log = tls_symbolic_operand (x, mode);
+ if (log)
+ {
+ rtx dest, base, off, pic;
+ int type;
+
+ switch (log)
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ dest = gen_reg_rtx (Pmode);
+ if (TARGET_64BIT)
+ {
+ rtx rax = gen_rtx_REG (Pmode, 0), insns;
+
+ start_sequence ();
+ emit_call_insn (gen_tls_global_dynamic_64 (rax, x));
+ insns = get_insns ();
+ end_sequence ();
+
+ emit_libcall_block (insns, dest, rax, x);
+ }
+ else
+ emit_insn (gen_tls_global_dynamic_32 (dest, x));
+ break;
+
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ base = gen_reg_rtx (Pmode);
+ if (TARGET_64BIT)
+ {
+ rtx rax = gen_rtx_REG (Pmode, 0), insns, note;
+
+ start_sequence ();
+ emit_call_insn (gen_tls_local_dynamic_base_64 (rax));
+ insns = get_insns ();
+ end_sequence ();
+
+ note = gen_rtx_EXPR_LIST (VOIDmode, const0_rtx, NULL);
+ note = gen_rtx_EXPR_LIST (VOIDmode, ix86_tls_get_addr (), note);
+ emit_libcall_block (insns, base, rax, note);
+ }
+ else
+ emit_insn (gen_tls_local_dynamic_base_32 (base));
+
+ off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPOFF);
+ off = gen_rtx_CONST (Pmode, off);
+
+ return gen_rtx_PLUS (Pmode, base, off);
+
+ case TLS_MODEL_INITIAL_EXEC:
+ if (TARGET_64BIT)
+ {
+ pic = NULL;
+ type = UNSPEC_GOTNTPOFF;
+ }
+ else if (flag_pic)
+ {
+ if (reload_in_progress)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+ pic = pic_offset_table_rtx;
+ type = TARGET_GNU_TLS ? UNSPEC_GOTNTPOFF : UNSPEC_GOTTPOFF;
+ }
+ else if (!TARGET_GNU_TLS)
+ {
+ pic = gen_reg_rtx (Pmode);
+ emit_insn (gen_set_got (pic));
+ type = UNSPEC_GOTTPOFF;
+ }
+ else
+ {
+ pic = NULL;
+ type = UNSPEC_INDNTPOFF;
+ }
+
+ base = get_thread_pointer ();
+
+ off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), type);
+ off = gen_rtx_CONST (Pmode, off);
+ if (pic)
+ off = gen_rtx_PLUS (Pmode, pic, off);
+ off = gen_rtx_MEM (Pmode, off);
+ RTX_UNCHANGING_P (off) = 1;
+ set_mem_alias_set (off, ix86_GOT_alias_set ());
+ dest = gen_reg_rtx (Pmode);
+
+ if (TARGET_64BIT || TARGET_GNU_TLS)
+ {
+ emit_move_insn (dest, off);
+ return gen_rtx_PLUS (Pmode, base, dest);
+ }
+ else
+ emit_insn (gen_subsi3 (dest, base, off));
+ break;
+
+ case TLS_MODEL_LOCAL_EXEC:
+ base = get_thread_pointer ();
+
+ off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
+ (TARGET_64BIT || TARGET_GNU_TLS)
+ ? UNSPEC_NTPOFF : UNSPEC_TPOFF);
+ off = gen_rtx_CONST (Pmode, off);
+
+ if (TARGET_64BIT || TARGET_GNU_TLS)
+ return gen_rtx_PLUS (Pmode, base, off);
+ else
+ {
+ dest = gen_reg_rtx (Pmode);
+ emit_insn (gen_subsi3 (dest, base, off));
+ }
+ break;
+
+ default:
+ abort ();
+ }
+
+ return dest;
+ }
+
if (flag_pic && SYMBOLIC_CONST (x))
return legitimize_pic_address (x, 0);
@@ -5371,7 +6239,7 @@ output_pic_addr_const (file, x, code)
case SYMBOL_REF:
assemble_name (file, XSTR (x, 0));
- if (code == 'P' && ! SYMBOL_REF_FLAG (x))
+ if (!TARGET_MACHO && code == 'P' && ! SYMBOL_REF_FLAG (x))
fputs ("@PLT", file);
break;
@@ -5429,30 +6297,54 @@ output_pic_addr_const (file, x, code)
break;
case MINUS:
- putc (ASSEMBLER_DIALECT == ASM_INTEL ? '(' : '[', file);
+ if (!TARGET_MACHO)
+ putc (ASSEMBLER_DIALECT == ASM_INTEL ? '(' : '[', file);
output_pic_addr_const (file, XEXP (x, 0), code);
putc ('-', file);
output_pic_addr_const (file, XEXP (x, 1), code);
- putc (ASSEMBLER_DIALECT == ASM_INTEL ? ')' : ']', file);
+ if (!TARGET_MACHO)
+ putc (ASSEMBLER_DIALECT == ASM_INTEL ? ')' : ']', file);
break;
case UNSPEC:
if (XVECLEN (x, 0) != 1)
- abort ();
+ abort ();
output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
switch (XINT (x, 1))
{
- case 6:
+ case UNSPEC_GOT:
fputs ("@GOT", file);
break;
- case 7:
+ case UNSPEC_GOTOFF:
fputs ("@GOTOFF", file);
break;
- case 8:
- fputs ("@PLT", file);
+ case UNSPEC_GOTPCREL:
+ fputs ("@GOTPCREL(%rip)", file);
+ break;
+ case UNSPEC_GOTTPOFF:
+ /* FIXME: This might be @TPOFF in Sun ld too. */
+ fputs ("@GOTTPOFF", file);
+ break;
+ case UNSPEC_TPOFF:
+ fputs ("@TPOFF", file);
break;
- case 15:
- fputs ("@GOTPCREL(%RIP)", file);
+ case UNSPEC_NTPOFF:
+ if (TARGET_64BIT)
+ fputs ("@TPOFF", file);
+ else
+ fputs ("@NTPOFF", file);
+ break;
+ case UNSPEC_DTPOFF:
+ fputs ("@DTPOFF", file);
+ break;
+ case UNSPEC_GOTNTPOFF:
+ if (TARGET_64BIT)
+ fputs ("@GOTTPOFF(%rip)", file);
+ else
+ fputs ("@GOTNTPOFF", file);
+ break;
+ case UNSPEC_INDNTPOFF:
+ fputs ("@INDNTPOFF", file);
break;
default:
output_operand_lossage ("invalid UNSPEC as operand");
@@ -5487,6 +6379,30 @@ i386_dwarf_output_addr_const (file, x)
fputc ('\n', file);
}
+/* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL.
+ We need to emit DTP-relative relocations. */
+
+void
+i386_output_dwarf_dtprel (file, size, x)
+ FILE *file;
+ int size;
+ rtx x;
+{
+ fputs (ASM_LONG, file);
+ output_addr_const (file, x);
+ fputs ("@DTPOFF", file);
+ switch (size)
+ {
+ case 4:
+ break;
+ case 8:
+ fputs (", 0", file);
+ break;
+ default:
+ abort ();
+ }
+}
+
/* In the name of slightly smaller debug output, and to cater to
general assembler losage, recognize PIC+GOTOFF and turn it back
into a direct symbol reference. */
@@ -5504,7 +6420,7 @@ i386_simplify_dwarf_addr (orig_x)
{
if (GET_CODE (x) != CONST
|| GET_CODE (XEXP (x, 0)) != UNSPEC
- || XINT (XEXP (x, 0), 1) != 15
+ || XINT (XEXP (x, 0), 1) != UNSPEC_GOTPCREL
|| GET_CODE (orig_x) != MEM)
return orig_x;
return XVECEXP (XEXP (x, 0), 0, 0);
@@ -5540,8 +6456,8 @@ i386_simplify_dwarf_addr (orig_x)
x = XEXP (XEXP (x, 1), 0);
if (GET_CODE (x) == UNSPEC
- && ((XINT (x, 1) == 6 && GET_CODE (orig_x) == MEM)
- || (XINT (x, 1) == 7 && GET_CODE (orig_x) != MEM)))
+ && ((XINT (x, 1) == UNSPEC_GOT && GET_CODE (orig_x) == MEM)
+ || (XINT (x, 1) == UNSPEC_GOTOFF && GET_CODE (orig_x) != MEM)))
{
if (y)
return gen_rtx_PLUS (Pmode, y, XVECEXP (x, 0, 0));
@@ -5551,8 +6467,9 @@ i386_simplify_dwarf_addr (orig_x)
if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 0)) == UNSPEC
&& GET_CODE (XEXP (x, 1)) == CONST_INT
- && ((XINT (XEXP (x, 0), 1) == 6 && GET_CODE (orig_x) == MEM)
- || (XINT (XEXP (x, 0), 1) == 7 && GET_CODE (orig_x) != MEM)))
+ && ((XINT (XEXP (x, 0), 1) == UNSPEC_GOT && GET_CODE (orig_x) == MEM)
+ || (XINT (XEXP (x, 0), 1) == UNSPEC_GOTOFF
+ && GET_CODE (orig_x) != MEM)))
{
x = gen_rtx_PLUS (VOIDmode, XVECEXP (XEXP (x, 0), 0, 0), XEXP (x, 1));
if (y)
@@ -5665,7 +6582,7 @@ print_reg (x, code, file)
|| REGNO (x) == FPSR_REG)
abort ();
- if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0)
+ if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0)
putc ('%', file);
if (code == 'w' || MMX_REG_P (x))
@@ -5742,6 +6659,43 @@ print_reg (x, code, file)
}
}
+/* Locate some local-dynamic symbol still in use by this function
+ so that we can print its name in some tls_local_dynamic_base
+ pattern. */
+
+static const char *
+get_some_local_dynamic_name ()
+{
+ rtx insn;
+
+ if (cfun->machine->some_ld_name)
+ return cfun->machine->some_ld_name;
+
+ for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
+ if (INSN_P (insn)
+ && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
+ return cfun->machine->some_ld_name;
+
+ abort ();
+}
+
+static int
+get_some_local_dynamic_name_1 (px, data)
+ rtx *px;
+ void *data ATTRIBUTE_UNUSED;
+{
+ rtx x = *px;
+
+ if (GET_CODE (x) == SYMBOL_REF
+ && local_dynamic_symbolic_operand (x, Pmode))
+ {
+ cfun->machine->some_ld_name = XSTR (x, 0);
+ return 1;
+ }
+
+ return 0;
+}
+
/* Meaning of CODE:
L,W,B,Q,S,T -- print the opcode suffix for specified size of operand.
C -- print opcode suffix for set/cmov insn.
@@ -5766,6 +6720,7 @@ print_reg (x, code, file)
D -- print condition for SSE cmp instruction.
P -- if PIC, print an @PLT suffix.
X -- don't print any sort of PIC '@' suffix for a symbol.
+ & -- print some in-use local-dynamic symbol name.
*/
void
@@ -5783,6 +6738,10 @@ print_operand (file, x, code)
putc ('*', file);
return;
+ case '&':
+ assemble_name (file, get_some_local_dynamic_name ());
+ return;
+
case 'A':
if (ASSEMBLER_DIALECT == ASM_ATT)
putc ('*', file);
@@ -5976,7 +6935,7 @@ print_operand (file, x, code)
/* Like above, but reverse condition */
case 'c':
- /* Check to see if argument to %c is really a constant
+ /* Check to see if argument to %c is really a constant
and not a condition code which needs to be reversed. */
if (GET_RTX_CLASS (GET_CODE (x)) != '<')
{
@@ -6069,9 +7028,11 @@ print_operand (file, x, code)
if (flag_pic && CONSTANT_ADDRESS_P (x))
output_pic_addr_const (file, x, code);
/* Avoid (%rip) for call operands. */
- else if (CONSTANT_ADDRESS_P (x) && code =='P'
+ else if (CONSTANT_ADDRESS_P (x) && code == 'P'
&& GET_CODE (x) != CONST_INT)
output_addr_const (file, x);
+ else if (this_is_asm_operands && ! address_operand (x, VOIDmode))
+ output_operand_lossage ("invalid constraints for operand");
else
output_address (x);
}
@@ -6092,24 +7053,21 @@ print_operand (file, x, code)
/* 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_FROM_CONST_DOUBLE (r, x);
- REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
+ real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (x), sizeof (dstr), 0, 1);
fprintf (file, "%s", dstr);
}
else if (GET_CODE (x) == CONST_DOUBLE
&& (GET_MODE (x) == XFmode || GET_MODE (x) == TFmode))
{
- REAL_VALUE_TYPE r;
char dstr[30];
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
+ real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (x), sizeof (dstr), 0, 1);
fprintf (file, "%s", dstr);
}
+
else
{
if (code != 'P')
@@ -6148,12 +7106,22 @@ print_operand_address (file, addr)
rtx base, index, disp;
int scale;
- if (! ix86_decompose_address (addr, &parts))
+ if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_TP)
{
- output_operand_lossage ("Wrong address expression or operand constraint");
+ if (ASSEMBLER_DIALECT == ASM_INTEL)
+ fputs ("DWORD PTR ", file);
+ if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0)
+ putc ('%', file);
+ if (TARGET_64BIT)
+ fputs ("fs:0", file);
+ else
+ fputs ("gs:0", file);
return;
}
+ if (! ix86_decompose_address (addr, &parts))
+ abort ();
+
base = parts.base;
index = parts.index;
disp = parts.disp;
@@ -6179,7 +7147,15 @@ print_operand_address (file, addr)
output_addr_const (file, addr);
/* Use one byte shorter RIP relative addressing for 64bit mode. */
- if (GET_CODE (disp) != CONST_INT && TARGET_64BIT)
+ if (TARGET_64BIT
+ && ((GET_CODE (addr) == SYMBOL_REF
+ && ! tls_symbolic_operand (addr, GET_MODE (addr)))
+ || GET_CODE (addr) == LABEL_REF
+ || (GET_CODE (addr) == CONST
+ && GET_CODE (XEXP (addr, 0)) == PLUS
+ && (GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF
+ || GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF)
+ && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)))
fputs ("(%rip)", file);
}
else
@@ -6261,6 +7237,58 @@ print_operand_address (file, addr)
}
}
}
+
+bool
+output_addr_const_extra (file, x)
+ FILE *file;
+ rtx x;
+{
+ rtx op;
+
+ if (GET_CODE (x) != UNSPEC)
+ return false;
+
+ op = XVECEXP (x, 0, 0);
+ switch (XINT (x, 1))
+ {
+ case UNSPEC_GOTTPOFF:
+ output_addr_const (file, op);
+ /* FIXME: This might be @TPOFF in Sun ld. */
+ fputs ("@GOTTPOFF", file);
+ break;
+ case UNSPEC_TPOFF:
+ output_addr_const (file, op);
+ fputs ("@TPOFF", file);
+ break;
+ case UNSPEC_NTPOFF:
+ output_addr_const (file, op);
+ if (TARGET_64BIT)
+ fputs ("@TPOFF", file);
+ else
+ fputs ("@NTPOFF", file);
+ break;
+ case UNSPEC_DTPOFF:
+ output_addr_const (file, op);
+ fputs ("@DTPOFF", file);
+ break;
+ case UNSPEC_GOTNTPOFF:
+ output_addr_const (file, op);
+ if (TARGET_64BIT)
+ fputs ("@GOTTPOFF(%rip)", file);
+ else
+ fputs ("@GOTNTPOFF", file);
+ break;
+ case UNSPEC_INDNTPOFF:
+ output_addr_const (file, op);
+ fputs ("@INDNTPOFF", file);
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
/* Split one or more DImode RTL references into pairs of SImode
references. The RTL can be REG, offsettable MEM, integer constant, or
@@ -6630,12 +7658,12 @@ output_fp_compare (insn, operands, eflags_p, unordered_p)
if (unordered_p)
return "ucomiss\t{%1, %0|%0, %1}";
else
- return "comiss\t{%1, %0|%0, %y}";
+ return "comiss\t{%1, %0|%0, %1}";
else
if (unordered_p)
return "ucomisd\t{%1, %0|%0, %1}";
else
- return "comisd\t{%1, %0|%0, %y}";
+ return "comisd\t{%1, %0|%0, %1}";
}
if (! STACK_TOP_P (cmp_op0))
@@ -6760,13 +7788,18 @@ ix86_output_addr_diff_elt (file, value, rel)
int value, rel;
{
if (TARGET_64BIT)
- fprintf (file, "%s%s%d-.+(.-%s%d)\n",
+ fprintf (file, "%s%s%d-%s%d\n",
ASM_LONG, LPREFIX, value, LPREFIX, rel);
else if (HAVE_AS_GOTOFF_IN_DATA)
fprintf (file, "%s%s%d@GOTOFF\n", ASM_LONG, LPREFIX, value);
+#if TARGET_MACHO
+ else if (TARGET_MACHO)
+ fprintf (file, "%s%s%d-%s\n", ASM_LONG, LPREFIX, value,
+ machopic_function_base_name () + 1);
+#endif
else
- asm_fprintf (file, "%s%U_GLOBAL_OFFSET_TABLE_+[.-%s%d]\n",
- ASM_LONG, LPREFIX, value);
+ asm_fprintf (file, "%s%U%s+[.-%s%d]\n",
+ ASM_LONG, GOT_SYMBOL_NAME, LPREFIX, value);
}
/* Generate either "mov $0, reg" or "xor reg, reg", as appropriate
@@ -6798,51 +7831,117 @@ ix86_expand_clear (dest)
emit_insn (tmp);
}
+/* X is an unchanging MEM. If it is a constant pool reference, return
+ the constant pool rtx, else NULL. */
+
+static rtx
+maybe_get_pool_constant (x)
+ rtx x;
+{
+ x = XEXP (x, 0);
+
+ if (flag_pic && ! TARGET_64BIT)
+ {
+ if (GET_CODE (x) != PLUS)
+ return NULL_RTX;
+ if (XEXP (x, 0) != pic_offset_table_rtx)
+ return NULL_RTX;
+ x = XEXP (x, 1);
+ if (GET_CODE (x) != CONST)
+ return NULL_RTX;
+ x = XEXP (x, 0);
+ if (GET_CODE (x) != UNSPEC)
+ return NULL_RTX;
+ if (XINT (x, 1) != UNSPEC_GOTOFF)
+ return NULL_RTX;
+ x = XVECEXP (x, 0, 0);
+ }
+
+ if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
+ return get_pool_constant (x);
+
+ return NULL_RTX;
+}
+
void
ix86_expand_move (mode, operands)
enum machine_mode mode;
rtx operands[];
{
int strict = (reload_in_progress || reload_completed);
- rtx insn;
+ rtx insn, op0, op1, tmp;
- if (flag_pic && mode == Pmode && symbolic_operand (operands[1], Pmode))
- {
- /* Emit insns to move operands[1] into operands[0]. */
+ op0 = operands[0];
+ op1 = operands[1];
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (Pmode, operands[1]);
+ if (tls_symbolic_operand (op1, Pmode))
+ {
+ op1 = legitimize_address (op1, op1, VOIDmode);
+ if (GET_CODE (op0) == MEM)
+ {
+ tmp = gen_reg_rtx (mode);
+ emit_insn (gen_rtx_SET (VOIDmode, tmp, op1));
+ op1 = tmp;
+ }
+ }
+ else if (flag_pic && mode == Pmode && symbolic_operand (op1, Pmode))
+ {
+#if TARGET_MACHO
+ if (MACHOPIC_PURE)
+ {
+ rtx temp = ((reload_in_progress
+ || ((op0 && GET_CODE (op0) == REG)
+ && mode == Pmode))
+ ? op0 : gen_reg_rtx (Pmode));
+ op1 = machopic_indirect_data_reference (op1, temp);
+ op1 = machopic_legitimize_pic_address (op1, mode,
+ temp == op1 ? 0 : temp);
+ }
else
{
- rtx temp = operands[0];
+ if (MACHOPIC_INDIRECT)
+ op1 = machopic_indirect_data_reference (op1, 0);
+ }
+ if (op0 != op1)
+ {
+ insn = gen_rtx_SET (VOIDmode, op0, op1);
+ emit_insn (insn);
+ }
+ return;
+#endif /* TARGET_MACHO */
+ if (GET_CODE (op0) == MEM)
+ op1 = force_reg (Pmode, op1);
+ else
+ {
+ rtx temp = op0;
if (GET_CODE (temp) != REG)
temp = gen_reg_rtx (Pmode);
- temp = legitimize_pic_address (operands[1], temp);
- if (temp == operands[0])
+ temp = legitimize_pic_address (op1, temp);
+ if (temp == op0)
return;
- operands[1] = temp;
+ op1 = temp;
}
}
else
{
- if (GET_CODE (operands[0]) == MEM
+ if (GET_CODE (op0) == MEM
&& (PUSH_ROUNDING (GET_MODE_SIZE (mode)) != GET_MODE_SIZE (mode)
- || !push_operand (operands[0], mode))
- && GET_CODE (operands[1]) == MEM)
- operands[1] = force_reg (mode, operands[1]);
+ || !push_operand (op0, mode))
+ && GET_CODE (op1) == MEM)
+ op1 = force_reg (mode, op1);
- if (push_operand (operands[0], mode)
- && ! general_no_elim_operand (operands[1], mode))
- operands[1] = copy_to_mode_reg (mode, operands[1]);
+ if (push_operand (op0, mode)
+ && ! general_no_elim_operand (op1, mode))
+ op1 = copy_to_mode_reg (mode, op1);
/* Force large constants in 64bit compilation into register
to get them CSEed. */
if (TARGET_64BIT && mode == DImode
- && immediate_operand (operands[1], mode)
- && !x86_64_zero_extended_value (operands[1])
- && !register_operand (operands[0], mode)
+ && immediate_operand (op1, mode)
+ && !x86_64_zero_extended_value (op1)
+ && !register_operand (op0, mode)
&& optimize && !reload_completed && !reload_in_progress)
- operands[1] = copy_to_mode_reg (mode, operands[1]);
+ op1 = copy_to_mode_reg (mode, op1);
if (FLOAT_MODE_P (mode))
{
@@ -6852,13 +7951,21 @@ ix86_expand_move (mode, operands)
if (strict)
;
- else if (GET_CODE (operands[1]) == CONST_DOUBLE
- && register_operand (operands[0], mode))
- operands[1] = validize_mem (force_const_mem (mode, operands[1]));
+ else if (GET_CODE (op1) == CONST_DOUBLE)
+ {
+ op1 = validize_mem (force_const_mem (mode, op1));
+ if (!register_operand (op0, mode))
+ {
+ rtx temp = gen_reg_rtx (mode);
+ emit_insn (gen_rtx_SET (VOIDmode, temp, op1));
+ emit_move_insn (op0, temp);
+ return;
+ }
+ }
}
}
- insn = gen_rtx_SET (VOIDmode, operands[0], operands[1]);
+ insn = gen_rtx_SET (VOIDmode, op0, op1);
emit_insn (insn);
}
@@ -6874,15 +7981,15 @@ ix86_expand_vector_move (mode, operands)
to handle some of them more efficiently. */
if ((reload_in_progress | reload_completed) == 0
&& register_operand (operands[0], mode)
- && CONSTANT_P (operands[1]))
+ && CONSTANT_P (operands[1]) && operands[1] != CONST0_RTX (mode))
{
- rtx addr = gen_reg_rtx (Pmode);
- emit_move_insn (addr, XEXP (force_const_mem (mode, operands[1]), 0));
- operands[1] = gen_rtx_MEM (mode, addr);
+ operands[1] = force_const_mem (mode, operands[1]);
+ emit_move_insn (operands[0], operands[1]);
+ return;
}
/* Make operand1 a register if it isn't already. */
- if ((reload_in_progress | reload_completed) == 0
+ if (!no_new_pseudos
&& !register_operand (operands[0], mode)
&& !register_operand (operands[1], mode))
{
@@ -6892,7 +7999,7 @@ ix86_expand_vector_move (mode, operands)
}
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
-}
+}
/* Attempt to expand a binary operator. Make the expansion closer to the
actual machine, then just general_operand, which will allow 3 separate
@@ -7540,7 +8647,7 @@ ix86_expand_fp_compare (code, op0, op1, scratch, second_test, bypass_test)
else
{
tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
- tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), 9);
+ tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
if (!scratch)
scratch = gen_reg_rtx (HImode);
emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp2));
@@ -7563,7 +8670,7 @@ ix86_expand_fp_compare (code, op0, op1, scratch, second_test, bypass_test)
{
/* Sadness wrt reg-stack pops killing fpsr -- gotta get fnstsw first. */
tmp = gen_rtx_COMPARE (fpcmp_mode, op0, op1);
- tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), 9);
+ tmp2 = gen_rtx_UNSPEC (HImode, gen_rtvec (1, tmp), UNSPEC_FNSTSW);
if (!scratch)
scratch = gen_reg_rtx (HImode);
emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp2));
@@ -7757,7 +8864,7 @@ ix86_expand_branch (code, label)
code = ix86_prepare_fp_compare_args (code, &ix86_compare_op0,
&ix86_compare_op1);
-
+
ix86_fp_comparison_codes (code, &bypass_code, &first_code, &second_code);
/* Check whether we will use the natural sequence with one jump. If
@@ -8074,7 +9181,7 @@ ix86_expand_int_movcc (operands)
start_sequence ();
compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
- compare_seq = gen_sequence ();
+ compare_seq = get_insns ();
end_sequence ();
compare_code = GET_CODE (compare_op);
@@ -8095,14 +9202,13 @@ ix86_expand_int_movcc (operands)
if ((compare_code == LTU || compare_code == GEU)
&& !second_test && !bypass_test)
{
-
/* Detect overlap between destination and compare sources. */
rtx tmp = out;
/* To simplify rest of code, restrict to the GEU case. */
if (compare_code == LTU)
{
- int tmp = ct;
+ HOST_WIDE_INT tmp = ct;
ct = cf;
cf = tmp;
compare_code = reverse_condition (compare_code);
@@ -8152,7 +9258,7 @@ ix86_expand_int_movcc (operands)
/*
* cmpl op0,op1
* sbbl dest,dest
- * xorl $-1, dest
+ * notl dest
* [addl dest, cf]
*
* Size 8 - 11.
@@ -8168,15 +9274,23 @@ ix86_expand_int_movcc (operands)
/*
* cmpl op0,op1
* sbbl dest,dest
+ * [notl dest]
* andl cf - ct, dest
* [addl dest, ct]
*
* Size 8 - 11.
*/
+
+ if (cf == 0)
+ {
+ cf = ct;
+ ct = 0;
+ tmp = expand_simple_unop (mode, NOT, tmp, tmp, 1);
+ }
+
tmp = expand_simple_binop (mode, AND,
tmp,
- GEN_INT (trunc_int_for_mode
- (cf - ct, mode)),
+ gen_int_mode (cf - ct, mode),
tmp, 1, OPTAB_DIRECT);
if (ct)
tmp = expand_simple_binop (mode, PLUS,
@@ -8211,6 +9325,61 @@ ix86_expand_int_movcc (operands)
code = reverse_condition (code);
}
}
+
+ compare_code = NIL;
+ if (GET_MODE_CLASS (GET_MODE (ix86_compare_op0)) == MODE_INT
+ && GET_CODE (ix86_compare_op1) == CONST_INT)
+ {
+ if (ix86_compare_op1 == const0_rtx
+ && (code == LT || code == GE))
+ compare_code = code;
+ else if (ix86_compare_op1 == constm1_rtx)
+ {
+ if (code == LE)
+ compare_code = LT;
+ else if (code == GT)
+ compare_code = GE;
+ }
+ }
+
+ /* Optimize dest = (op0 < 0) ? -1 : cf. */
+ if (compare_code != NIL
+ && GET_MODE (ix86_compare_op0) == GET_MODE (out)
+ && (cf == -1 || ct == -1))
+ {
+ /* If lea code below could be used, only optimize
+ if it results in a 2 insn sequence. */
+
+ if (! (diff == 1 || diff == 2 || diff == 4 || diff == 8
+ || diff == 3 || diff == 5 || diff == 9)
+ || (compare_code == LT && ct == -1)
+ || (compare_code == GE && cf == -1))
+ {
+ /*
+ * notl op1 (if necessary)
+ * sarl $31, op1
+ * orl cf, op1
+ */
+ if (ct != -1)
+ {
+ cf = ct;
+ ct = -1;
+ code = reverse_condition (code);
+ }
+
+ out = emit_store_flag (out, code, ix86_compare_op0,
+ ix86_compare_op1, VOIDmode, 0, -1);
+
+ out = expand_simple_binop (mode, IOR,
+ out, GEN_INT (cf),
+ out, 1, OPTAB_DIRECT);
+ if (out != operands[0])
+ emit_move_insn (operands[0], out);
+
+ return 1; /* DONE */
+ }
+ }
+
if ((diff == 1 || diff == 2 || diff == 4 || diff == 8
|| diff == 3 || diff == 5 || diff == 9)
&& (mode != DImode || x86_64_sign_extended_value (GEN_INT (cf))))
@@ -8233,14 +9402,14 @@ ix86_expand_int_movcc (operands)
ix86_compare_op1, VOIDmode, 0, 1);
nops = 0;
- /* On x86_64 the lea instruction operates on Pmode, so we need to get arithmetics
- done in proper mode to match. */
+ /* On x86_64 the lea instruction operates on Pmode, so we need
+ to get arithmetics done in proper mode to match. */
if (diff == 1)
- tmp = out;
+ tmp = copy_rtx (out);
else
{
rtx out1;
- out1 = out;
+ out1 = copy_rtx (out);
tmp = gen_rtx_MULT (mode, out1, GEN_INT (diff & ~1));
nops++;
if (diff & 1)
@@ -8258,21 +9427,12 @@ ix86_expand_int_movcc (operands)
&& (GET_CODE (tmp) != SUBREG || SUBREG_REG (tmp) != out))
{
if (nops == 1)
- {
- rtx clob;
-
- clob = gen_rtx_REG (CCmode, FLAGS_REG);
- clob = gen_rtx_CLOBBER (VOIDmode, clob);
-
- tmp = gen_rtx_SET (VOIDmode, out, tmp);
- tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, copy_rtx (tmp), clob));
- emit_insn (tmp);
- }
+ out = force_operand (tmp, copy_rtx (out));
else
- emit_insn (gen_rtx_SET (VOIDmode, out, tmp));
+ emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (out), copy_rtx (tmp)));
}
if (out != operands[0])
- emit_move_insn (operands[0], out);
+ emit_move_insn (operands[0], copy_rtx (out));
return 1; /* DONE */
}
@@ -8298,40 +9458,68 @@ ix86_expand_int_movcc (operands)
if (!optimize_size && !TARGET_CMOVE)
{
- if (ct == 0)
+ if (cf == 0)
{
- ct = cf;
- cf = 0;
+ cf = ct;
+ ct = 0;
if (FLOAT_MODE_P (GET_MODE (ix86_compare_op0)))
+ /* We may be reversing unordered compare to normal compare,
+ that is not valid in general (we may convert non-trapping
+ condition to trapping one), however on i386 we currently
+ emit all comparisons unordered. */
+ code = reverse_condition_maybe_unordered (code);
+ else
+ {
+ code = reverse_condition (code);
+ if (compare_code != NIL)
+ compare_code = reverse_condition (compare_code);
+ }
+ }
+
+ if (compare_code != NIL)
+ {
+ /* notl op1 (if needed)
+ sarl $31, op1
+ andl (cf-ct), op1
+ addl ct, op1
+
+ For x < 0 (resp. x <= -1) there will be no notl,
+ so if possible swap the constants to get rid of the
+ complement.
+ True/false will be -1/0 while code below (store flag
+ followed by decrement) is 0/-1, so the constants need
+ to be exchanged once more. */
+
+ if (compare_code == GE || !cf)
{
- /* We may be reversing unordered compare to normal compare,
- that is not valid in general (we may convert non-trapping
- condition to trapping one), however on i386 we currently
- emit all comparisons unordered. */
- compare_code = reverse_condition_maybe_unordered (compare_code);
- code = reverse_condition_maybe_unordered (code);
+ code = reverse_condition (code);
+ compare_code = LT;
}
else
{
- compare_code = reverse_condition (compare_code);
- code = reverse_condition (code);
+ HOST_WIDE_INT tmp = cf;
+ cf = ct;
+ ct = tmp;
}
+
+ out = emit_store_flag (out, code, ix86_compare_op0,
+ ix86_compare_op1, VOIDmode, 0, -1);
}
+ else
+ {
+ out = emit_store_flag (out, code, ix86_compare_op0,
+ ix86_compare_op1, VOIDmode, 0, 1);
- out = emit_store_flag (out, code, ix86_compare_op0,
- ix86_compare_op1, VOIDmode, 0, 1);
+ out = expand_simple_binop (mode, PLUS, out, constm1_rtx,
+ out, 1, OPTAB_DIRECT);
+ }
- out = expand_simple_binop (mode, PLUS,
- out, constm1_rtx,
- out, 1, OPTAB_DIRECT);
- out = expand_simple_binop (mode, AND,
- out,
- GEN_INT (trunc_int_for_mode
- (cf - ct, mode)),
- out, 1, OPTAB_DIRECT);
- out = expand_simple_binop (mode, PLUS,
- out, GEN_INT (ct),
+ out = expand_simple_binop (mode, AND, out,
+ gen_int_mode (cf - ct, mode),
out, 1, OPTAB_DIRECT);
+ if (ct)
+ out = expand_simple_binop (mode, PLUS, out, GEN_INT (ct),
+ out, 1, OPTAB_DIRECT);
if (out != operands[0])
emit_move_insn (operands[0], out);
@@ -8622,13 +9810,14 @@ ix86_split_to_parts (operand, parts, mode)
if (size < 2 || size > 3)
abort ();
- /* Optimize constant pool reference to immediates. This is used by fp moves,
- that force all constants to memory to allow combining. */
-
- if (GET_CODE (operand) == MEM
- && GET_CODE (XEXP (operand, 0)) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (XEXP (operand, 0)))
- operand = get_pool_constant (XEXP (operand, 0));
+ /* Optimize constant pool reference to immediates. This is used by fp
+ moves, that force all constants to memory to allow combining. */
+ if (GET_CODE (operand) == MEM && RTX_UNCHANGING_P (operand))
+ {
+ rtx tmp = maybe_get_pool_constant (operand);
+ if (tmp)
+ operand = tmp;
+ }
if (GET_CODE (operand) == MEM && !offsettable_memref_p (operand))
{
@@ -8674,7 +9863,7 @@ ix86_split_to_parts (operand, parts, mode)
case XFmode:
case TFmode:
REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
- parts[2] = GEN_INT (trunc_int_for_mode (l[2], SImode));
+ parts[2] = gen_int_mode (l[2], SImode);
break;
case DFmode:
REAL_VALUE_TO_TARGET_DOUBLE (r, l);
@@ -8682,8 +9871,8 @@ ix86_split_to_parts (operand, parts, mode)
default:
abort ();
}
- parts[1] = GEN_INT (trunc_int_for_mode (l[1], SImode));
- parts[0] = GEN_INT (trunc_int_for_mode (l[0], SImode));
+ parts[1] = gen_int_mode (l[1], SImode);
+ parts[0] = gen_int_mode (l[0], SImode);
}
else
abort ();
@@ -8718,13 +9907,13 @@ ix86_split_to_parts (operand, parts, mode)
/* Do not use shift by 32 to avoid warning on 32bit systems. */
if (HOST_BITS_PER_WIDE_INT >= 64)
parts[0]
- = GEN_INT (trunc_int_for_mode
+ = gen_int_mode
((l[0] & (((HOST_WIDE_INT) 2 << 31) - 1))
+ ((((HOST_WIDE_INT) l[1]) << 31) << 1),
- DImode));
+ DImode);
else
parts[0] = immed_double_const (l[0], l[1], DImode);
- parts[1] = GEN_INT (trunc_int_for_mode (l[2], SImode));
+ parts[1] = gen_int_mode (l[2], SImode);
}
else
abort ();
@@ -8819,15 +10008,24 @@ ix86_split_long_move (operands)
Do an lea to the last part and use only one colliding move. */
else if (collisions > 1)
{
+ rtx base;
+
collisions = 1;
- emit_insn (gen_rtx_SET (VOIDmode, part[0][nparts - 1],
- XEXP (part[1][0], 0)));
- part[1][0] = change_address (part[1][0],
- TARGET_64BIT ? DImode : SImode,
- part[0][nparts - 1]);
- part[1][1] = adjust_address (part[1][0], VOIDmode, UNITS_PER_WORD);
+
+ base = part[0][nparts - 1];
+
+ /* Handle the case when the last part isn't valid for lea.
+ Happens in 64-bit mode storing the 12-byte XFmode. */
+ if (GET_MODE (base) != Pmode)
+ base = gen_rtx_REG (Pmode, REGNO (base));
+
+ emit_insn (gen_rtx_SET (VOIDmode, base, XEXP (part[1][0], 0)));
+ part[1][0] = replace_equiv_address (part[1][0], base);
+ part[1][1] = replace_equiv_address (part[1][1],
+ plus_constant (base, UNITS_PER_WORD));
if (nparts == 3)
- part[1][2] = adjust_address (part[1][0], VOIDmode, 8);
+ part[1][2] = replace_equiv_address (part[1][2],
+ plus_constant (base, 8));
}
}
@@ -9356,7 +10554,7 @@ ix86_expand_movstr (dst, src, count_exp, align_exp)
end_sequence ();
ix86_set_move_mem_attrs (insns, dst, src, destreg, srcreg);
- emit_insns (insns);
+ emit_insn (insns);
return 1;
}
@@ -9757,8 +10955,7 @@ ix86_expand_strlensi_unroll_1 (out, align_rtx)
emit_insn (gen_one_cmplsi2 (scratch, scratch));
emit_insn (gen_andsi3 (tmpreg, tmpreg, scratch));
emit_insn (gen_andsi3 (tmpreg, tmpreg,
- GEN_INT (trunc_int_for_mode
- (0x80808080, SImode))));
+ gen_int_mode (0x80808080, SImode)));
emit_cmp_and_jump_insns (tmpreg, const0_rtx, EQ, 0, SImode, 1,
align_4_label);
@@ -9824,43 +11021,66 @@ ix86_expand_strlensi_unroll_1 (out, align_rtx)
emit_label (end_0_label);
}
-
-/* Clear stack slot assignments remembered from previous functions.
- This is called from INIT_EXPANDERS once before RTL is emitted for each
- function. */
-static void
-ix86_init_machine_status (p)
- struct function *p;
+void
+ix86_expand_call (retval, fnaddr, callarg1, callarg2, pop)
+ rtx retval, fnaddr, callarg1, callarg2, pop;
{
- p->machine = (struct machine_function *)
- xcalloc (1, sizeof (struct machine_function));
-}
+ rtx use = NULL, call;
-/* Mark machine specific bits of P for GC. */
-static void
-ix86_mark_machine_status (p)
- struct function *p;
-{
- struct machine_function *machine = p->machine;
- enum machine_mode mode;
- int n;
+ if (pop == const0_rtx)
+ pop = NULL;
+ if (TARGET_64BIT && pop)
+ abort ();
- if (! machine)
- return;
+#if TARGET_MACHO
+ if (flag_pic && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF)
+ fnaddr = machopic_indirect_call_target (fnaddr);
+#else
+ /* Static functions and indirect calls don't need the pic register. */
+ if (! TARGET_64BIT && flag_pic
+ && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
+ && ! SYMBOL_REF_FLAG (XEXP (fnaddr, 0)))
+ use_reg (&use, pic_offset_table_rtx);
+
+ if (TARGET_64BIT && INTVAL (callarg2) >= 0)
+ {
+ rtx al = gen_rtx_REG (QImode, 0);
+ emit_move_insn (al, callarg2);
+ use_reg (&use, al);
+ }
+#endif /* TARGET_MACHO */
+
+ if (! call_insn_operand (XEXP (fnaddr, 0), Pmode))
+ {
+ fnaddr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0));
+ fnaddr = gen_rtx_MEM (QImode, fnaddr);
+ }
- for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
- mode = (enum machine_mode) ((int) mode + 1))
- for (n = 0; n < MAX_386_STACK_LOCALS; n++)
- ggc_mark_rtx (machine->stack_locals[(int) mode][n]);
+ call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
+ if (retval)
+ call = gen_rtx_SET (VOIDmode, retval, call);
+ if (pop)
+ {
+ pop = gen_rtx_PLUS (Pmode, stack_pointer_rtx, pop);
+ pop = gen_rtx_SET (VOIDmode, stack_pointer_rtx, pop);
+ call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, call, pop));
+ }
+
+ call = emit_call_insn (call);
+ if (use)
+ CALL_INSN_FUNCTION_USAGE (call) = use;
}
-static void
-ix86_free_machine_status (p)
- struct function *p;
+
+/* Clear stack slot assignments remembered from previous functions.
+ This is called from INIT_EXPANDERS once before RTL is emitted for each
+ function. */
+
+static struct machine_function *
+ix86_init_machine_status ()
{
- free (p->machine);
- p->machine = NULL;
+ return ggc_alloc_cleared (sizeof (struct machine_function));
}
/* Return a MEM corresponding to a stack slot with mode MODE.
@@ -9883,6 +11103,24 @@ assign_386_stack_local (mode, n)
return ix86_stack_locals[(int) mode][n];
}
+
+/* Construct the SYMBOL_REF for the tls_get_addr function. */
+
+static GTY(()) rtx ix86_tls_symbol;
+rtx
+ix86_tls_get_addr ()
+{
+
+ if (!ix86_tls_symbol)
+ {
+ ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode,
+ (TARGET_GNU_TLS && !TARGET_64BIT)
+ ? "___tls_get_addr"
+ : "__tls_get_addr");
+ }
+
+ return ix86_tls_symbol;
+}
/* Calculate the length of the memory address in the instruction
encoding. Does not include the one-byte modrm, opcode, or prefix. */
@@ -9930,7 +11168,8 @@ memory_address_length (addr)
if (disp)
{
if (GET_CODE (disp) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (disp), 'K'))
+ && CONST_OK_FOR_LETTER_P (INTVAL (disp), 'K')
+ && base)
len = 1;
else
len = 4;
@@ -9944,8 +11183,8 @@ memory_address_length (addr)
return len;
}
-/* Compute default value for "length_immediate" attribute. When SHORTFORM is set
- expect that insn have 8bit immediate alternative. */
+/* Compute default value for "length_immediate" attribute. When SHORTFORM
+ is set, expect that insn have 8bit immediate alternative. */
int
ix86_attr_length_immediate_default (insn, shortform)
rtx insn;
@@ -9993,6 +11232,26 @@ ix86_attr_length_address_default (insn)
rtx insn;
{
int i;
+
+ if (get_attr_type (insn) == TYPE_LEA)
+ {
+ rtx set = PATTERN (insn);
+ if (GET_CODE (set) == SET)
+ ;
+ else if (GET_CODE (set) == PARALLEL
+ && GET_CODE (XVECEXP (set, 0, 0)) == SET)
+ set = XVECEXP (set, 0, 0);
+ else
+ {
+#ifdef ENABLE_CHECKING
+ abort ();
+#endif
+ return 0;
+ }
+
+ return memory_address_length (SET_SRC (set));
+ }
+
extract_insn_cached (insn);
for (i = recog_data.n_operands - 1; i >= 0; --i)
if (GET_CODE (recog_data.operand[i]) == MEM)
@@ -10271,46 +11530,6 @@ static union
} ppro;
} ix86_sched_data;
-static int
-ix86_safe_length (insn)
- rtx insn;
-{
- if (recog_memoized (insn) >= 0)
- return get_attr_length (insn);
- else
- return 128;
-}
-
-static int
-ix86_safe_length_prefix (insn)
- rtx insn;
-{
- if (recog_memoized (insn) >= 0)
- return get_attr_length (insn);
- else
- return 0;
-}
-
-static enum attr_memory
-ix86_safe_memory (insn)
- rtx insn;
-{
- if (recog_memoized (insn) >= 0)
- return get_attr_memory (insn);
- else
- return MEMORY_UNKNOWN;
-}
-
-static enum attr_pent_pair
-ix86_safe_pent_pair (insn)
- rtx insn;
-{
- if (recog_memoized (insn) >= 0)
- return get_attr_pent_pair (insn);
- else
- return PENT_PAIR_NP;
-}
-
static enum attr_ppro_uops
ix86_safe_ppro_uops (insn)
rtx insn;
@@ -10364,129 +11583,6 @@ ix86_reorder_insn (insnp, slot)
}
}
-/* Find an instruction with given pairability and minimal amount of cycles
- lost by the fact that the CPU waits for both pipelines to finish before
- reading next instructions. Also take care that both instructions together
- can not exceed 7 bytes. */
-
-static rtx *
-ix86_pent_find_pair (e_ready, ready, type, first)
- rtx *e_ready;
- rtx *ready;
- enum attr_pent_pair type;
- rtx first;
-{
- int mincycles, cycles;
- enum attr_pent_pair tmp;
- enum attr_memory memory;
- rtx *insnp, *bestinsnp = NULL;
-
- if (ix86_safe_length (first) > 7 + ix86_safe_length_prefix (first))
- return NULL;
-
- memory = ix86_safe_memory (first);
- cycles = result_ready_cost (first);
- mincycles = INT_MAX;
-
- for (insnp = e_ready; insnp >= ready && mincycles; --insnp)
- if ((tmp = ix86_safe_pent_pair (*insnp)) == type
- && ix86_safe_length (*insnp) <= 7 + ix86_safe_length_prefix (*insnp))
- {
- enum attr_memory second_memory;
- int secondcycles, currentcycles;
-
- second_memory = ix86_safe_memory (*insnp);
- secondcycles = result_ready_cost (*insnp);
- currentcycles = abs (cycles - secondcycles);
-
- if (secondcycles >= 1 && cycles >= 1)
- {
- /* Two read/modify/write instructions together takes two
- cycles longer. */
- if (memory == MEMORY_BOTH && second_memory == MEMORY_BOTH)
- currentcycles += 2;
-
- /* Read modify/write instruction followed by read/modify
- takes one cycle longer. */
- if (memory == MEMORY_BOTH && second_memory == MEMORY_LOAD
- && tmp != PENT_PAIR_UV
- && ix86_safe_pent_pair (first) != PENT_PAIR_UV)
- currentcycles += 1;
- }
- if (currentcycles < mincycles)
- bestinsnp = insnp, mincycles = currentcycles;
- }
-
- return bestinsnp;
-}
-
-/* Subroutines of ix86_sched_reorder. */
-
-static void
-ix86_sched_reorder_pentium (ready, e_ready)
- rtx *ready;
- rtx *e_ready;
-{
- enum attr_pent_pair pair1, pair2;
- rtx *insnp;
-
- /* This wouldn't be necessary if Haifa knew that static insn ordering
- is important to which pipe an insn is issued to. So we have to make
- some minor rearrangements. */
-
- pair1 = ix86_safe_pent_pair (*e_ready);
-
- /* If the first insn is non-pairable, let it be. */
- if (pair1 == PENT_PAIR_NP)
- return;
-
- pair2 = PENT_PAIR_NP;
- insnp = 0;
-
- /* If the first insn is UV or PV pairable, search for a PU
- insn to go with. */
- if (pair1 == PENT_PAIR_UV || pair1 == PENT_PAIR_PV)
- {
- insnp = ix86_pent_find_pair (e_ready-1, ready,
- PENT_PAIR_PU, *e_ready);
- if (insnp)
- pair2 = PENT_PAIR_PU;
- }
-
- /* If the first insn is PU or UV pairable, search for a PV
- insn to go with. */
- if (pair2 == PENT_PAIR_NP
- && (pair1 == PENT_PAIR_PU || pair1 == PENT_PAIR_UV))
- {
- insnp = ix86_pent_find_pair (e_ready-1, ready,
- PENT_PAIR_PV, *e_ready);
- if (insnp)
- pair2 = PENT_PAIR_PV;
- }
-
- /* If the first insn is pairable, search for a UV
- insn to go with. */
- if (pair2 == PENT_PAIR_NP)
- {
- insnp = ix86_pent_find_pair (e_ready-1, ready,
- PENT_PAIR_UV, *e_ready);
- if (insnp)
- pair2 = PENT_PAIR_UV;
- }
-
- if (pair2 == PENT_PAIR_NP)
- return;
-
- /* Found something! Decide if we need to swap the order. */
- if (pair1 == PENT_PAIR_PV || pair2 == PENT_PAIR_PU
- || (pair1 == PENT_PAIR_UV && pair2 == PENT_PAIR_UV
- && ix86_safe_memory (*e_ready) == MEMORY_BOTH
- && ix86_safe_memory (*insnp) == MEMORY_LOAD))
- ix86_reorder_insn (insnp, e_ready);
- else
- ix86_reorder_insn (insnp, e_ready - 1);
-}
-
static void
ix86_sched_reorder_ppro (ready, e_ready)
rtx *ready;
@@ -10541,7 +11637,7 @@ ix86_sched_reorder_ppro (ready, e_ready)
for (i = 1; i < 3; ++i)
if (decode[i] == NULL)
{
- if (ready >= e_ready)
+ if (ready > e_ready)
goto ppro_done;
insnp = e_ready;
@@ -10585,18 +11681,20 @@ ix86_sched_reorder (dump, sched_verbose, ready, n_readyp, clock_var)
int n_ready = *n_readyp;
rtx *e_ready = ready + n_ready - 1;
+ /* Make sure to go ahead and initialize key items in
+ ix86_sched_data if we are not going to bother trying to
+ reorder the ready queue. */
if (n_ready < 2)
- goto out;
+ {
+ ix86_sched_data.ppro.issued_this_cycle = 1;
+ goto out;
+ }
switch (ix86_cpu)
{
default:
break;
- case PROCESSOR_PENTIUM:
- ix86_sched_reorder_pentium (ready, e_ready);
- break;
-
case PROCESSOR_PENTIUMPRO:
ix86_sched_reorder_ppro (ready, e_ready);
break;
@@ -10668,6 +11766,28 @@ ix86_variable_issue (dump, sched_verbose, insn, can_issue_more)
return --ix86_sched_data.ppro.issued_this_cycle;
}
}
+
+static int
+ia32_use_dfa_pipeline_interface ()
+{
+ if (ix86_cpu == PROCESSOR_PENTIUM)
+ return 1;
+ return 0;
+}
+
+/* How many alternative schedules to try. This should be as wide as the
+ scheduling freedom in the DFA, but no wider. Making this value too
+ large results extra work for the scheduler. */
+
+static int
+ia32_multipass_dfa_lookahead ()
+{
+ if (ix86_cpu == PROCESSOR_PENTIUM)
+ return 2;
+ else
+ return 0;
+}
+
/* Walk through INSNS and look for MEM references whose address is DSTREG or
SRCREG and set the memory attribute to those of DSTREF and SRCREF, as
@@ -10877,10 +11997,10 @@ x86_initialize_trampoline (tramp, fnaddr, cxt)
plus_constant (tramp, 10),
NULL_RTX, 1, OPTAB_DIRECT);
emit_move_insn (gen_rtx_MEM (QImode, tramp),
- GEN_INT (trunc_int_for_mode (0xb9, QImode)));
+ gen_int_mode (0xb9, QImode));
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 1)), cxt);
emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, 5)),
- GEN_INT (trunc_int_for_mode (0xe9, QImode)));
+ gen_int_mode (0xe9, QImode));
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, 6)), disp);
}
else
@@ -10893,7 +12013,7 @@ x86_initialize_trampoline (tramp, fnaddr, cxt)
{
fnaddr = copy_to_mode_reg (DImode, fnaddr);
emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, offset)),
- GEN_INT (trunc_int_for_mode (0xbb41, HImode)));
+ gen_int_mode (0xbb41, HImode));
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (tramp, offset + 2)),
gen_lowpart (SImode, fnaddr));
offset += 6;
@@ -10901,32 +12021,39 @@ x86_initialize_trampoline (tramp, fnaddr, cxt)
else
{
emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, offset)),
- GEN_INT (trunc_int_for_mode (0xbb49, HImode)));
+ gen_int_mode (0xbb49, HImode));
emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, offset + 2)),
fnaddr);
offset += 10;
}
/* Load static chain using movabs to r10. */
emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, offset)),
- GEN_INT (trunc_int_for_mode (0xba49, HImode)));
+ gen_int_mode (0xba49, HImode));
emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, offset + 2)),
cxt);
offset += 10;
/* Jump to the r11 */
emit_move_insn (gen_rtx_MEM (HImode, plus_constant (tramp, offset)),
- GEN_INT (trunc_int_for_mode (0xff49, HImode)));
+ gen_int_mode (0xff49, HImode));
emit_move_insn (gen_rtx_MEM (QImode, plus_constant (tramp, offset+2)),
- GEN_INT (trunc_int_for_mode (0xe3, QImode)));
+ gen_int_mode (0xe3, QImode));
offset += 3;
if (offset > TRAMPOLINE_SIZE)
abort ();
}
+
+#ifdef TRANSFER_FROM_TRAMPOLINE
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
+ LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
+#endif
}
-#define def_builtin(MASK, NAME, TYPE, CODE) \
-do { \
- if ((MASK) & target_flags) \
- builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL); \
+#define def_builtin(MASK, NAME, TYPE, CODE) \
+do { \
+ if ((MASK) & target_flags \
+ && (!((MASK) & MASK_64BIT) || TARGET_64BIT)) \
+ builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
+ NULL, NULL_TREE); \
} while (0)
struct builtin_description
@@ -10939,73 +12066,97 @@ struct builtin_description
const unsigned int flag;
};
+/* Used for builtins that are enabled both by -msse and -msse2. */
+#define MASK_SSE1 (MASK_SSE | MASK_SSE2)
+#define MASK_SSE164 (MASK_SSE | MASK_SSE2 | MASK_64BIT)
+#define MASK_SSE264 (MASK_SSE2 | MASK_64BIT)
+
static const struct builtin_description bdesc_comi[] =
{
- { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comieq", IX86_BUILTIN_COMIEQSS, EQ, 0 },
- { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comilt", IX86_BUILTIN_COMILTSS, LT, 0 },
- { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comile", IX86_BUILTIN_COMILESS, LE, 0 },
- { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comigt", IX86_BUILTIN_COMIGTSS, LT, 1 },
- { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comige", IX86_BUILTIN_COMIGESS, LE, 1 },
- { MASK_SSE, CODE_FOR_sse_comi, "__builtin_ia32_comineq", IX86_BUILTIN_COMINEQSS, NE, 0 },
- { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomieq", IX86_BUILTIN_UCOMIEQSS, EQ, 0 },
- { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomilt", IX86_BUILTIN_UCOMILTSS, LT, 0 },
- { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomile", IX86_BUILTIN_UCOMILESS, LE, 0 },
- { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomigt", IX86_BUILTIN_UCOMIGTSS, LT, 1 },
- { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomige", IX86_BUILTIN_UCOMIGESS, LE, 1 },
- { MASK_SSE, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomineq", IX86_BUILTIN_UCOMINEQSS, NE, 0 }
+ { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comieq", IX86_BUILTIN_COMIEQSS, UNEQ, 0 },
+ { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comilt", IX86_BUILTIN_COMILTSS, UNLT, 0 },
+ { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comile", IX86_BUILTIN_COMILESS, UNLE, 0 },
+ { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comigt", IX86_BUILTIN_COMIGTSS, GT, 0 },
+ { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comige", IX86_BUILTIN_COMIGESS, GE, 0 },
+ { MASK_SSE1, CODE_FOR_sse_comi, "__builtin_ia32_comineq", IX86_BUILTIN_COMINEQSS, LTGT, 0 },
+ { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomieq", IX86_BUILTIN_UCOMIEQSS, UNEQ, 0 },
+ { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomilt", IX86_BUILTIN_UCOMILTSS, UNLT, 0 },
+ { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomile", IX86_BUILTIN_UCOMILESS, UNLE, 0 },
+ { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomigt", IX86_BUILTIN_UCOMIGTSS, GT, 0 },
+ { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomige", IX86_BUILTIN_UCOMIGESS, GE, 0 },
+ { MASK_SSE1, CODE_FOR_sse_ucomi, "__builtin_ia32_ucomineq", IX86_BUILTIN_UCOMINEQSS, LTGT, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdeq", IX86_BUILTIN_COMIEQSD, UNEQ, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdlt", IX86_BUILTIN_COMILTSD, UNLT, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdle", IX86_BUILTIN_COMILESD, UNLE, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdgt", IX86_BUILTIN_COMIGTSD, GT, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdge", IX86_BUILTIN_COMIGESD, GE, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_comi, "__builtin_ia32_comisdneq", IX86_BUILTIN_COMINEQSD, LTGT, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdeq", IX86_BUILTIN_UCOMIEQSD, UNEQ, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdlt", IX86_BUILTIN_UCOMILTSD, UNLT, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdle", IX86_BUILTIN_UCOMILESD, UNLE, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdgt", IX86_BUILTIN_UCOMIGTSD, GT, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdge", IX86_BUILTIN_UCOMIGESD, GE, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_ucomi, "__builtin_ia32_ucomisdneq", IX86_BUILTIN_UCOMINEQSD, LTGT, 0 },
};
static const struct builtin_description bdesc_2arg[] =
{
/* SSE */
- { MASK_SSE, CODE_FOR_addv4sf3, "__builtin_ia32_addps", IX86_BUILTIN_ADDPS, 0, 0 },
- { MASK_SSE, CODE_FOR_subv4sf3, "__builtin_ia32_subps", IX86_BUILTIN_SUBPS, 0, 0 },
- { MASK_SSE, CODE_FOR_mulv4sf3, "__builtin_ia32_mulps", IX86_BUILTIN_MULPS, 0, 0 },
- { MASK_SSE, CODE_FOR_divv4sf3, "__builtin_ia32_divps", IX86_BUILTIN_DIVPS, 0, 0 },
- { MASK_SSE, CODE_FOR_vmaddv4sf3, "__builtin_ia32_addss", IX86_BUILTIN_ADDSS, 0, 0 },
- { MASK_SSE, CODE_FOR_vmsubv4sf3, "__builtin_ia32_subss", IX86_BUILTIN_SUBSS, 0, 0 },
- { MASK_SSE, CODE_FOR_vmmulv4sf3, "__builtin_ia32_mulss", IX86_BUILTIN_MULSS, 0, 0 },
- { MASK_SSE, CODE_FOR_vmdivv4sf3, "__builtin_ia32_divss", IX86_BUILTIN_DIVSS, 0, 0 },
-
- { MASK_SSE, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpeqps", IX86_BUILTIN_CMPEQPS, EQ, 0 },
- { MASK_SSE, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpltps", IX86_BUILTIN_CMPLTPS, LT, 0 },
- { MASK_SSE, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpleps", IX86_BUILTIN_CMPLEPS, LE, 0 },
- { MASK_SSE, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpgtps", IX86_BUILTIN_CMPGTPS, LT, 1 },
- { MASK_SSE, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpgeps", IX86_BUILTIN_CMPGEPS, LE, 1 },
- { MASK_SSE, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpunordps", IX86_BUILTIN_CMPUNORDPS, UNORDERED, 0 },
- { MASK_SSE, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpneqps", IX86_BUILTIN_CMPNEQPS, EQ, 0 },
- { MASK_SSE, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpnltps", IX86_BUILTIN_CMPNLTPS, LT, 0 },
- { MASK_SSE, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpnleps", IX86_BUILTIN_CMPNLEPS, LE, 0 },
- { MASK_SSE, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpngtps", IX86_BUILTIN_CMPNGTPS, LT, 1 },
- { MASK_SSE, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpngeps", IX86_BUILTIN_CMPNGEPS, LE, 1 },
- { MASK_SSE, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpordps", IX86_BUILTIN_CMPORDPS, UNORDERED, 0 },
- { MASK_SSE, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpeqss", IX86_BUILTIN_CMPEQSS, EQ, 0 },
- { MASK_SSE, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpltss", IX86_BUILTIN_CMPLTSS, LT, 0 },
- { MASK_SSE, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpless", IX86_BUILTIN_CMPLESS, LE, 0 },
- { MASK_SSE, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpunordss", IX86_BUILTIN_CMPUNORDSS, UNORDERED, 0 },
- { MASK_SSE, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpneqss", IX86_BUILTIN_CMPNEQSS, EQ, 0 },
- { MASK_SSE, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpnltss", IX86_BUILTIN_CMPNLTSS, LT, 0 },
- { MASK_SSE, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpnless", IX86_BUILTIN_CMPNLESS, LE, 0 },
- { MASK_SSE, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpordss", IX86_BUILTIN_CMPORDSS, UNORDERED, 0 },
-
- { MASK_SSE, CODE_FOR_sminv4sf3, "__builtin_ia32_minps", IX86_BUILTIN_MINPS, 0, 0 },
- { MASK_SSE, CODE_FOR_smaxv4sf3, "__builtin_ia32_maxps", IX86_BUILTIN_MAXPS, 0, 0 },
- { MASK_SSE, CODE_FOR_vmsminv4sf3, "__builtin_ia32_minss", IX86_BUILTIN_MINSS, 0, 0 },
- { MASK_SSE, CODE_FOR_vmsmaxv4sf3, "__builtin_ia32_maxss", IX86_BUILTIN_MAXSS, 0, 0 },
-
- { MASK_SSE, CODE_FOR_sse_movss, "__builtin_ia32_movss", IX86_BUILTIN_MOVSS, 0, 0 },
- { MASK_SSE, CODE_FOR_sse_movhlps, "__builtin_ia32_movhlps", IX86_BUILTIN_MOVHLPS, 0, 0 },
- { MASK_SSE, CODE_FOR_sse_movlhps, "__builtin_ia32_movlhps", IX86_BUILTIN_MOVLHPS, 0, 0 },
- { MASK_SSE, CODE_FOR_sse_unpckhps, "__builtin_ia32_unpckhps", IX86_BUILTIN_UNPCKHPS, 0, 0 },
- { MASK_SSE, CODE_FOR_sse_unpcklps, "__builtin_ia32_unpcklps", IX86_BUILTIN_UNPCKLPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_addv4sf3, "__builtin_ia32_addps", IX86_BUILTIN_ADDPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_subv4sf3, "__builtin_ia32_subps", IX86_BUILTIN_SUBPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_mulv4sf3, "__builtin_ia32_mulps", IX86_BUILTIN_MULPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_divv4sf3, "__builtin_ia32_divps", IX86_BUILTIN_DIVPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_vmaddv4sf3, "__builtin_ia32_addss", IX86_BUILTIN_ADDSS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_vmsubv4sf3, "__builtin_ia32_subss", IX86_BUILTIN_SUBSS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_vmmulv4sf3, "__builtin_ia32_mulss", IX86_BUILTIN_MULSS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_vmdivv4sf3, "__builtin_ia32_divss", IX86_BUILTIN_DIVSS, 0, 0 },
+
+ { MASK_SSE1, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpeqps", IX86_BUILTIN_CMPEQPS, EQ, 0 },
+ { MASK_SSE1, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpltps", IX86_BUILTIN_CMPLTPS, LT, 0 },
+ { MASK_SSE1, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpleps", IX86_BUILTIN_CMPLEPS, LE, 0 },
+ { MASK_SSE1, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpgtps", IX86_BUILTIN_CMPGTPS, LT, 1 },
+ { MASK_SSE1, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpgeps", IX86_BUILTIN_CMPGEPS, LE, 1 },
+ { MASK_SSE1, CODE_FOR_maskcmpv4sf3, "__builtin_ia32_cmpunordps", IX86_BUILTIN_CMPUNORDPS, UNORDERED, 0 },
+ { MASK_SSE1, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpneqps", IX86_BUILTIN_CMPNEQPS, EQ, 0 },
+ { MASK_SSE1, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpnltps", IX86_BUILTIN_CMPNLTPS, LT, 0 },
+ { MASK_SSE1, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpnleps", IX86_BUILTIN_CMPNLEPS, LE, 0 },
+ { MASK_SSE1, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpngtps", IX86_BUILTIN_CMPNGTPS, LT, 1 },
+ { MASK_SSE1, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpngeps", IX86_BUILTIN_CMPNGEPS, LE, 1 },
+ { MASK_SSE1, CODE_FOR_maskncmpv4sf3, "__builtin_ia32_cmpordps", IX86_BUILTIN_CMPORDPS, UNORDERED, 0 },
+ { MASK_SSE1, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpeqss", IX86_BUILTIN_CMPEQSS, EQ, 0 },
+ { MASK_SSE1, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpltss", IX86_BUILTIN_CMPLTSS, LT, 0 },
+ { MASK_SSE1, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpless", IX86_BUILTIN_CMPLESS, LE, 0 },
+ { MASK_SSE1, CODE_FOR_vmmaskcmpv4sf3, "__builtin_ia32_cmpunordss", IX86_BUILTIN_CMPUNORDSS, UNORDERED, 0 },
+ { MASK_SSE1, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpneqss", IX86_BUILTIN_CMPNEQSS, EQ, 0 },
+ { MASK_SSE1, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpnltss", IX86_BUILTIN_CMPNLTSS, LT, 0 },
+ { MASK_SSE1, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpnless", IX86_BUILTIN_CMPNLESS, LE, 0 },
+ { MASK_SSE1, CODE_FOR_vmmaskncmpv4sf3, "__builtin_ia32_cmpordss", IX86_BUILTIN_CMPORDSS, UNORDERED, 0 },
+
+ { MASK_SSE1, CODE_FOR_sminv4sf3, "__builtin_ia32_minps", IX86_BUILTIN_MINPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_smaxv4sf3, "__builtin_ia32_maxps", IX86_BUILTIN_MAXPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_vmsminv4sf3, "__builtin_ia32_minss", IX86_BUILTIN_MINSS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_vmsmaxv4sf3, "__builtin_ia32_maxss", IX86_BUILTIN_MAXSS, 0, 0 },
+
+ { MASK_SSE1, CODE_FOR_sse_andv4sf3, "__builtin_ia32_andps", IX86_BUILTIN_ANDPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_sse_nandv4sf3, "__builtin_ia32_andnps", IX86_BUILTIN_ANDNPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_sse_iorv4sf3, "__builtin_ia32_orps", IX86_BUILTIN_ORPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_sse_xorv4sf3, "__builtin_ia32_xorps", IX86_BUILTIN_XORPS, 0, 0 },
+
+ { MASK_SSE1, CODE_FOR_sse_movss, "__builtin_ia32_movss", IX86_BUILTIN_MOVSS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_sse_movhlps, "__builtin_ia32_movhlps", IX86_BUILTIN_MOVHLPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_sse_movlhps, "__builtin_ia32_movlhps", IX86_BUILTIN_MOVLHPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_sse_unpckhps, "__builtin_ia32_unpckhps", IX86_BUILTIN_UNPCKHPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_sse_unpcklps, "__builtin_ia32_unpcklps", IX86_BUILTIN_UNPCKLPS, 0, 0 },
/* MMX */
{ MASK_MMX, CODE_FOR_addv8qi3, "__builtin_ia32_paddb", IX86_BUILTIN_PADDB, 0, 0 },
{ MASK_MMX, CODE_FOR_addv4hi3, "__builtin_ia32_paddw", IX86_BUILTIN_PADDW, 0, 0 },
{ MASK_MMX, CODE_FOR_addv2si3, "__builtin_ia32_paddd", IX86_BUILTIN_PADDD, 0, 0 },
+ { MASK_MMX, CODE_FOR_mmx_adddi3, "__builtin_ia32_paddq", IX86_BUILTIN_PADDQ, 0, 0 },
{ MASK_MMX, CODE_FOR_subv8qi3, "__builtin_ia32_psubb", IX86_BUILTIN_PSUBB, 0, 0 },
{ MASK_MMX, CODE_FOR_subv4hi3, "__builtin_ia32_psubw", IX86_BUILTIN_PSUBW, 0, 0 },
{ MASK_MMX, CODE_FOR_subv2si3, "__builtin_ia32_psubd", IX86_BUILTIN_PSUBD, 0, 0 },
+ { MASK_MMX, CODE_FOR_mmx_subdi3, "__builtin_ia32_psubq", IX86_BUILTIN_PSUBQ, 0, 0 },
{ MASK_MMX, CODE_FOR_ssaddv8qi3, "__builtin_ia32_paddsb", IX86_BUILTIN_PADDSB, 0, 0 },
{ MASK_MMX, CODE_FOR_ssaddv4hi3, "__builtin_ia32_paddsw", IX86_BUILTIN_PADDSW, 0, 0 },
@@ -11018,15 +12169,15 @@ static const struct builtin_description bdesc_2arg[] =
{ MASK_MMX, CODE_FOR_mulv4hi3, "__builtin_ia32_pmullw", IX86_BUILTIN_PMULLW, 0, 0 },
{ MASK_MMX, CODE_FOR_smulv4hi3_highpart, "__builtin_ia32_pmulhw", IX86_BUILTIN_PMULHW, 0, 0 },
- { MASK_SSE | MASK_3DNOW_A, CODE_FOR_umulv4hi3_highpart, "__builtin_ia32_pmulhuw", IX86_BUILTIN_PMULHUW, 0, 0 },
+ { MASK_SSE1 | MASK_3DNOW_A, CODE_FOR_umulv4hi3_highpart, "__builtin_ia32_pmulhuw", IX86_BUILTIN_PMULHUW, 0, 0 },
{ MASK_MMX, CODE_FOR_mmx_anddi3, "__builtin_ia32_pand", IX86_BUILTIN_PAND, 0, 0 },
{ MASK_MMX, CODE_FOR_mmx_nanddi3, "__builtin_ia32_pandn", IX86_BUILTIN_PANDN, 0, 0 },
{ MASK_MMX, CODE_FOR_mmx_iordi3, "__builtin_ia32_por", IX86_BUILTIN_POR, 0, 0 },
{ MASK_MMX, CODE_FOR_mmx_xordi3, "__builtin_ia32_pxor", IX86_BUILTIN_PXOR, 0, 0 },
- { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_uavgv8qi3, "__builtin_ia32_pavgb", IX86_BUILTIN_PAVGB, 0, 0 },
- { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_uavgv4hi3, "__builtin_ia32_pavgw", IX86_BUILTIN_PAVGW, 0, 0 },
+ { MASK_SSE1 | MASK_3DNOW_A, CODE_FOR_mmx_uavgv8qi3, "__builtin_ia32_pavgb", IX86_BUILTIN_PAVGB, 0, 0 },
+ { MASK_SSE1 | MASK_3DNOW_A, CODE_FOR_mmx_uavgv4hi3, "__builtin_ia32_pavgw", IX86_BUILTIN_PAVGW, 0, 0 },
{ MASK_MMX, CODE_FOR_eqv8qi3, "__builtin_ia32_pcmpeqb", IX86_BUILTIN_PCMPEQB, 0, 0 },
{ MASK_MMX, CODE_FOR_eqv4hi3, "__builtin_ia32_pcmpeqw", IX86_BUILTIN_PCMPEQW, 0, 0 },
@@ -11035,10 +12186,10 @@ static const struct builtin_description bdesc_2arg[] =
{ MASK_MMX, CODE_FOR_gtv4hi3, "__builtin_ia32_pcmpgtw", IX86_BUILTIN_PCMPGTW, 0, 0 },
{ MASK_MMX, CODE_FOR_gtv2si3, "__builtin_ia32_pcmpgtd", IX86_BUILTIN_PCMPGTD, 0, 0 },
- { MASK_SSE | MASK_3DNOW_A, CODE_FOR_umaxv8qi3, "__builtin_ia32_pmaxub", IX86_BUILTIN_PMAXUB, 0, 0 },
- { MASK_SSE | MASK_3DNOW_A, CODE_FOR_smaxv4hi3, "__builtin_ia32_pmaxsw", IX86_BUILTIN_PMAXSW, 0, 0 },
- { MASK_SSE | MASK_3DNOW_A, CODE_FOR_uminv8qi3, "__builtin_ia32_pminub", IX86_BUILTIN_PMINUB, 0, 0 },
- { MASK_SSE | MASK_3DNOW_A, CODE_FOR_sminv4hi3, "__builtin_ia32_pminsw", IX86_BUILTIN_PMINSW, 0, 0 },
+ { MASK_SSE1 | MASK_3DNOW_A, CODE_FOR_umaxv8qi3, "__builtin_ia32_pmaxub", IX86_BUILTIN_PMAXUB, 0, 0 },
+ { MASK_SSE1 | MASK_3DNOW_A, CODE_FOR_smaxv4hi3, "__builtin_ia32_pmaxsw", IX86_BUILTIN_PMAXSW, 0, 0 },
+ { MASK_SSE1 | MASK_3DNOW_A, CODE_FOR_uminv8qi3, "__builtin_ia32_pminub", IX86_BUILTIN_PMINUB, 0, 0 },
+ { MASK_SSE1 | MASK_3DNOW_A, CODE_FOR_sminv4hi3, "__builtin_ia32_pminsw", IX86_BUILTIN_PMINSW, 0, 0 },
{ MASK_MMX, CODE_FOR_mmx_punpckhbw, "__builtin_ia32_punpckhbw", IX86_BUILTIN_PUNPCKHBW, 0, 0 },
{ MASK_MMX, CODE_FOR_mmx_punpckhwd, "__builtin_ia32_punpckhwd", IX86_BUILTIN_PUNPCKHWD, 0, 0 },
@@ -11052,8 +12203,9 @@ static const struct builtin_description bdesc_2arg[] =
{ MASK_MMX, CODE_FOR_mmx_packssdw, 0, IX86_BUILTIN_PACKSSDW, 0, 0 },
{ MASK_MMX, CODE_FOR_mmx_packuswb, 0, IX86_BUILTIN_PACKUSWB, 0, 0 },
- { MASK_SSE, CODE_FOR_cvtpi2ps, 0, IX86_BUILTIN_CVTPI2PS, 0, 0 },
- { MASK_SSE, CODE_FOR_cvtsi2ss, 0, IX86_BUILTIN_CVTSI2SS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_cvtpi2ps, 0, IX86_BUILTIN_CVTPI2PS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_cvtsi2ss, 0, IX86_BUILTIN_CVTSI2SS, 0, 0 },
+ { MASK_SSE164, CODE_FOR_cvtsi2ssq, 0, IX86_BUILTIN_CVTSI642SS, 0, 0 },
{ MASK_MMX, CODE_FOR_ashlv4hi3, 0, IX86_BUILTIN_PSLLW, 0, 0 },
{ MASK_MMX, CODE_FOR_ashlv4hi3, 0, IX86_BUILTIN_PSLLWI, 0, 0 },
@@ -11074,25 +12226,185 @@ static const struct builtin_description bdesc_2arg[] =
{ MASK_MMX, CODE_FOR_ashrv2si3, 0, IX86_BUILTIN_PSRAD, 0, 0 },
{ MASK_MMX, CODE_FOR_ashrv2si3, 0, IX86_BUILTIN_PSRADI, 0, 0 },
- { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_psadbw, 0, IX86_BUILTIN_PSADBW, 0, 0 },
- { MASK_MMX, CODE_FOR_mmx_pmaddwd, 0, IX86_BUILTIN_PMADDWD, 0, 0 }
-
+ { MASK_SSE1 | MASK_3DNOW_A, CODE_FOR_mmx_psadbw, 0, IX86_BUILTIN_PSADBW, 0, 0 },
+ { MASK_MMX, CODE_FOR_mmx_pmaddwd, 0, IX86_BUILTIN_PMADDWD, 0, 0 },
+
+ /* SSE2 */
+ { MASK_SSE2, CODE_FOR_addv2df3, "__builtin_ia32_addpd", IX86_BUILTIN_ADDPD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_subv2df3, "__builtin_ia32_subpd", IX86_BUILTIN_SUBPD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_mulv2df3, "__builtin_ia32_mulpd", IX86_BUILTIN_MULPD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_divv2df3, "__builtin_ia32_divpd", IX86_BUILTIN_DIVPD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_vmaddv2df3, "__builtin_ia32_addsd", IX86_BUILTIN_ADDSD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_vmsubv2df3, "__builtin_ia32_subsd", IX86_BUILTIN_SUBSD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_vmmulv2df3, "__builtin_ia32_mulsd", IX86_BUILTIN_MULSD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_vmdivv2df3, "__builtin_ia32_divsd", IX86_BUILTIN_DIVSD, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_maskcmpv2df3, "__builtin_ia32_cmpeqpd", IX86_BUILTIN_CMPEQPD, EQ, 0 },
+ { MASK_SSE2, CODE_FOR_maskcmpv2df3, "__builtin_ia32_cmpltpd", IX86_BUILTIN_CMPLTPD, LT, 0 },
+ { MASK_SSE2, CODE_FOR_maskcmpv2df3, "__builtin_ia32_cmplepd", IX86_BUILTIN_CMPLEPD, LE, 0 },
+ { MASK_SSE2, CODE_FOR_maskcmpv2df3, "__builtin_ia32_cmpgtpd", IX86_BUILTIN_CMPGTPD, LT, 1 },
+ { MASK_SSE2, CODE_FOR_maskcmpv2df3, "__builtin_ia32_cmpgepd", IX86_BUILTIN_CMPGEPD, LE, 1 },
+ { MASK_SSE2, CODE_FOR_maskcmpv2df3, "__builtin_ia32_cmpunordpd", IX86_BUILTIN_CMPUNORDPD, UNORDERED, 0 },
+ { MASK_SSE2, CODE_FOR_maskncmpv2df3, "__builtin_ia32_cmpneqpd", IX86_BUILTIN_CMPNEQPD, EQ, 0 },
+ { MASK_SSE2, CODE_FOR_maskncmpv2df3, "__builtin_ia32_cmpnltpd", IX86_BUILTIN_CMPNLTPD, LT, 0 },
+ { MASK_SSE2, CODE_FOR_maskncmpv2df3, "__builtin_ia32_cmpnlepd", IX86_BUILTIN_CMPNLEPD, LE, 0 },
+ { MASK_SSE2, CODE_FOR_maskncmpv2df3, "__builtin_ia32_cmpngtpd", IX86_BUILTIN_CMPNGTPD, LT, 1 },
+ { MASK_SSE2, CODE_FOR_maskncmpv2df3, "__builtin_ia32_cmpngepd", IX86_BUILTIN_CMPNGEPD, LE, 1 },
+ { MASK_SSE2, CODE_FOR_maskncmpv2df3, "__builtin_ia32_cmpordpd", IX86_BUILTIN_CMPORDPD, UNORDERED, 0 },
+ { MASK_SSE2, CODE_FOR_vmmaskcmpv2df3, "__builtin_ia32_cmpeqsd", IX86_BUILTIN_CMPEQSD, EQ, 0 },
+ { MASK_SSE2, CODE_FOR_vmmaskcmpv2df3, "__builtin_ia32_cmpltsd", IX86_BUILTIN_CMPLTSD, LT, 0 },
+ { MASK_SSE2, CODE_FOR_vmmaskcmpv2df3, "__builtin_ia32_cmplesd", IX86_BUILTIN_CMPLESD, LE, 0 },
+ { MASK_SSE2, CODE_FOR_vmmaskcmpv2df3, "__builtin_ia32_cmpunordsd", IX86_BUILTIN_CMPUNORDSD, UNORDERED, 0 },
+ { MASK_SSE2, CODE_FOR_vmmaskncmpv2df3, "__builtin_ia32_cmpneqsd", IX86_BUILTIN_CMPNEQSD, EQ, 0 },
+ { MASK_SSE2, CODE_FOR_vmmaskncmpv2df3, "__builtin_ia32_cmpnltsd", IX86_BUILTIN_CMPNLTSD, LT, 0 },
+ { MASK_SSE2, CODE_FOR_vmmaskncmpv2df3, "__builtin_ia32_cmpnlesd", IX86_BUILTIN_CMPNLESD, LE, 0 },
+ { MASK_SSE2, CODE_FOR_vmmaskncmpv2df3, "__builtin_ia32_cmpordsd", IX86_BUILTIN_CMPORDSD, UNORDERED, 0 },
+
+ { MASK_SSE2, CODE_FOR_sminv2df3, "__builtin_ia32_minpd", IX86_BUILTIN_MINPD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_smaxv2df3, "__builtin_ia32_maxpd", IX86_BUILTIN_MAXPD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_vmsminv2df3, "__builtin_ia32_minsd", IX86_BUILTIN_MINSD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_vmsmaxv2df3, "__builtin_ia32_maxsd", IX86_BUILTIN_MAXSD, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_sse2_andv2df3, "__builtin_ia32_andpd", IX86_BUILTIN_ANDPD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_nandv2df3, "__builtin_ia32_andnpd", IX86_BUILTIN_ANDNPD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_iorv2df3, "__builtin_ia32_orpd", IX86_BUILTIN_ORPD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_xorv2df3, "__builtin_ia32_xorpd", IX86_BUILTIN_XORPD, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_sse2_movsd, "__builtin_ia32_movsd", IX86_BUILTIN_MOVSD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_unpckhpd, "__builtin_ia32_unpckhpd", IX86_BUILTIN_UNPCKHPD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_unpcklpd, "__builtin_ia32_unpcklpd", IX86_BUILTIN_UNPCKLPD, 0, 0 },
+
+ /* SSE2 MMX */
+ { MASK_SSE2, CODE_FOR_addv16qi3, "__builtin_ia32_paddb128", IX86_BUILTIN_PADDB128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_addv8hi3, "__builtin_ia32_paddw128", IX86_BUILTIN_PADDW128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_addv4si3, "__builtin_ia32_paddd128", IX86_BUILTIN_PADDD128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_addv2di3, "__builtin_ia32_paddq128", IX86_BUILTIN_PADDQ128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_subv16qi3, "__builtin_ia32_psubb128", IX86_BUILTIN_PSUBB128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_subv8hi3, "__builtin_ia32_psubw128", IX86_BUILTIN_PSUBW128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_subv4si3, "__builtin_ia32_psubd128", IX86_BUILTIN_PSUBD128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_subv2di3, "__builtin_ia32_psubq128", IX86_BUILTIN_PSUBQ128, 0, 0 },
+
+ { MASK_MMX, CODE_FOR_ssaddv16qi3, "__builtin_ia32_paddsb128", IX86_BUILTIN_PADDSB128, 0, 0 },
+ { MASK_MMX, CODE_FOR_ssaddv8hi3, "__builtin_ia32_paddsw128", IX86_BUILTIN_PADDSW128, 0, 0 },
+ { MASK_MMX, CODE_FOR_sssubv16qi3, "__builtin_ia32_psubsb128", IX86_BUILTIN_PSUBSB128, 0, 0 },
+ { MASK_MMX, CODE_FOR_sssubv8hi3, "__builtin_ia32_psubsw128", IX86_BUILTIN_PSUBSW128, 0, 0 },
+ { MASK_MMX, CODE_FOR_usaddv16qi3, "__builtin_ia32_paddusb128", IX86_BUILTIN_PADDUSB128, 0, 0 },
+ { MASK_MMX, CODE_FOR_usaddv8hi3, "__builtin_ia32_paddusw128", IX86_BUILTIN_PADDUSW128, 0, 0 },
+ { MASK_MMX, CODE_FOR_ussubv16qi3, "__builtin_ia32_psubusb128", IX86_BUILTIN_PSUBUSB128, 0, 0 },
+ { MASK_MMX, CODE_FOR_ussubv8hi3, "__builtin_ia32_psubusw128", IX86_BUILTIN_PSUBUSW128, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_mulv8hi3, "__builtin_ia32_pmullw128", IX86_BUILTIN_PMULLW128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_smulv8hi3_highpart, "__builtin_ia32_pmulhw128", IX86_BUILTIN_PMULHW128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_umulsidi3, "__builtin_ia32_pmuludq", IX86_BUILTIN_PMULUDQ, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_umulv2siv2di3, "__builtin_ia32_pmuludq128", IX86_BUILTIN_PMULUDQ128, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_sse2_andv2di3, "__builtin_ia32_pand128", IX86_BUILTIN_PAND128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_nandv2di3, "__builtin_ia32_pandn128", IX86_BUILTIN_PANDN128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_iorv2di3, "__builtin_ia32_por128", IX86_BUILTIN_POR128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_xorv2di3, "__builtin_ia32_pxor128", IX86_BUILTIN_PXOR128, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_sse2_uavgv16qi3, "__builtin_ia32_pavgb128", IX86_BUILTIN_PAVGB128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_uavgv8hi3, "__builtin_ia32_pavgw128", IX86_BUILTIN_PAVGW128, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_eqv16qi3, "__builtin_ia32_pcmpeqb128", IX86_BUILTIN_PCMPEQB128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_eqv8hi3, "__builtin_ia32_pcmpeqw128", IX86_BUILTIN_PCMPEQW128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_eqv4si3, "__builtin_ia32_pcmpeqd128", IX86_BUILTIN_PCMPEQD128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_gtv16qi3, "__builtin_ia32_pcmpgtb128", IX86_BUILTIN_PCMPGTB128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_gtv8hi3, "__builtin_ia32_pcmpgtw128", IX86_BUILTIN_PCMPGTW128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_gtv4si3, "__builtin_ia32_pcmpgtd128", IX86_BUILTIN_PCMPGTD128, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_umaxv16qi3, "__builtin_ia32_pmaxub128", IX86_BUILTIN_PMAXUB128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_smaxv8hi3, "__builtin_ia32_pmaxsw128", IX86_BUILTIN_PMAXSW128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_uminv16qi3, "__builtin_ia32_pminub128", IX86_BUILTIN_PMINUB128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sminv8hi3, "__builtin_ia32_pminsw128", IX86_BUILTIN_PMINSW128, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_sse2_punpckhbw, "__builtin_ia32_punpckhbw128", IX86_BUILTIN_PUNPCKHBW128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_punpckhwd, "__builtin_ia32_punpckhwd128", IX86_BUILTIN_PUNPCKHWD128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_punpckhdq, "__builtin_ia32_punpckhdq128", IX86_BUILTIN_PUNPCKHDQ128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_punpckhqdq, "__builtin_ia32_punpckhqdq128", IX86_BUILTIN_PUNPCKHQDQ128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_punpcklbw, "__builtin_ia32_punpcklbw128", IX86_BUILTIN_PUNPCKLBW128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_punpcklwd, "__builtin_ia32_punpcklwd128", IX86_BUILTIN_PUNPCKLWD128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_punpckldq, "__builtin_ia32_punpckldq128", IX86_BUILTIN_PUNPCKLDQ128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_punpcklqdq, "__builtin_ia32_punpcklqdq128", IX86_BUILTIN_PUNPCKLQDQ128, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_sse2_packsswb, "__builtin_ia32_packsswb128", IX86_BUILTIN_PACKSSWB128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_packssdw, "__builtin_ia32_packssdw128", IX86_BUILTIN_PACKSSDW128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_packuswb, "__builtin_ia32_packuswb128", IX86_BUILTIN_PACKUSWB128, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_umulv8hi3_highpart, "__builtin_ia32_pmulhuw128", IX86_BUILTIN_PMULHUW128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_psadbw, 0, IX86_BUILTIN_PSADBW128, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_ashlv8hi3_ti, 0, IX86_BUILTIN_PSLLW128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_ashlv8hi3, 0, IX86_BUILTIN_PSLLWI128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_ashlv4si3_ti, 0, IX86_BUILTIN_PSLLD128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_ashlv4si3, 0, IX86_BUILTIN_PSLLDI128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_ashlv2di3_ti, 0, IX86_BUILTIN_PSLLQ128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_ashlv2di3, 0, IX86_BUILTIN_PSLLQI128, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_lshrv8hi3_ti, 0, IX86_BUILTIN_PSRLW128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_lshrv8hi3, 0, IX86_BUILTIN_PSRLWI128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_lshrv4si3_ti, 0, IX86_BUILTIN_PSRLD128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_lshrv4si3, 0, IX86_BUILTIN_PSRLDI128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_lshrv2di3_ti, 0, IX86_BUILTIN_PSRLQ128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_lshrv2di3, 0, IX86_BUILTIN_PSRLQI128, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_ashrv8hi3_ti, 0, IX86_BUILTIN_PSRAW128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_ashrv8hi3, 0, IX86_BUILTIN_PSRAWI128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_ashrv4si3_ti, 0, IX86_BUILTIN_PSRAD128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_ashrv4si3, 0, IX86_BUILTIN_PSRADI128, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_sse2_pmaddwd, 0, IX86_BUILTIN_PMADDWD128, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_cvtsi2sd, 0, IX86_BUILTIN_CVTSI2SD, 0, 0 },
+ { MASK_SSE264, CODE_FOR_cvtsi2sdq, 0, IX86_BUILTIN_CVTSI642SD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_cvtsd2ss, 0, IX86_BUILTIN_CVTSD2SS, 0, 0 },
+ { MASK_SSE2, CODE_FOR_cvtss2sd, 0, IX86_BUILTIN_CVTSS2SD, 0, 0 }
};
static const struct builtin_description bdesc_1arg[] =
{
- { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_pmovmskb, 0, IX86_BUILTIN_PMOVMSKB, 0, 0 },
- { MASK_SSE, CODE_FOR_sse_movmskps, 0, IX86_BUILTIN_MOVMSKPS, 0, 0 },
+ { MASK_SSE1 | MASK_3DNOW_A, CODE_FOR_mmx_pmovmskb, 0, IX86_BUILTIN_PMOVMSKB, 0, 0 },
+ { MASK_SSE1, CODE_FOR_sse_movmskps, 0, IX86_BUILTIN_MOVMSKPS, 0, 0 },
+
+ { MASK_SSE1, CODE_FOR_sqrtv4sf2, 0, IX86_BUILTIN_SQRTPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_rsqrtv4sf2, 0, IX86_BUILTIN_RSQRTPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_rcpv4sf2, 0, IX86_BUILTIN_RCPPS, 0, 0 },
- { MASK_SSE, CODE_FOR_sqrtv4sf2, 0, IX86_BUILTIN_SQRTPS, 0, 0 },
- { MASK_SSE, CODE_FOR_rsqrtv4sf2, 0, IX86_BUILTIN_RSQRTPS, 0, 0 },
- { MASK_SSE, CODE_FOR_rcpv4sf2, 0, IX86_BUILTIN_RCPPS, 0, 0 },
+ { MASK_SSE1, CODE_FOR_cvtps2pi, 0, IX86_BUILTIN_CVTPS2PI, 0, 0 },
+ { MASK_SSE1, CODE_FOR_cvtss2si, 0, IX86_BUILTIN_CVTSS2SI, 0, 0 },
+ { MASK_SSE164, CODE_FOR_cvtss2siq, 0, IX86_BUILTIN_CVTSS2SI64, 0, 0 },
+ { MASK_SSE1, CODE_FOR_cvttps2pi, 0, IX86_BUILTIN_CVTTPS2PI, 0, 0 },
+ { MASK_SSE1, CODE_FOR_cvttss2si, 0, IX86_BUILTIN_CVTTSS2SI, 0, 0 },
+ { MASK_SSE164, CODE_FOR_cvttss2siq, 0, IX86_BUILTIN_CVTTSS2SI64, 0, 0 },
- { MASK_SSE, CODE_FOR_cvtps2pi, 0, IX86_BUILTIN_CVTPS2PI, 0, 0 },
- { MASK_SSE, CODE_FOR_cvtss2si, 0, IX86_BUILTIN_CVTSS2SI, 0, 0 },
- { MASK_SSE, CODE_FOR_cvttps2pi, 0, IX86_BUILTIN_CVTTPS2PI, 0, 0 },
- { MASK_SSE, CODE_FOR_cvttss2si, 0, IX86_BUILTIN_CVTTSS2SI, 0, 0 }
+ { MASK_SSE2, CODE_FOR_sse2_pmovmskb, 0, IX86_BUILTIN_PMOVMSKB128, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_movmskpd, 0, IX86_BUILTIN_MOVMSKPD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_movq2dq, 0, IX86_BUILTIN_MOVQ2DQ, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sse2_movdq2q, 0, IX86_BUILTIN_MOVDQ2Q, 0, 0 },
+ { MASK_SSE2, CODE_FOR_sqrtv2df2, 0, IX86_BUILTIN_SQRTPD, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_cvtdq2pd, 0, IX86_BUILTIN_CVTDQ2PD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_cvtdq2ps, 0, IX86_BUILTIN_CVTDQ2PS, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_cvtpd2dq, 0, IX86_BUILTIN_CVTPD2DQ, 0, 0 },
+ { MASK_SSE2, CODE_FOR_cvtpd2pi, 0, IX86_BUILTIN_CVTPD2PI, 0, 0 },
+ { MASK_SSE2, CODE_FOR_cvtpd2ps, 0, IX86_BUILTIN_CVTPD2PS, 0, 0 },
+ { MASK_SSE2, CODE_FOR_cvttpd2dq, 0, IX86_BUILTIN_CVTTPD2DQ, 0, 0 },
+ { MASK_SSE2, CODE_FOR_cvttpd2pi, 0, IX86_BUILTIN_CVTTPD2PI, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_cvtpi2pd, 0, IX86_BUILTIN_CVTPI2PD, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_cvtsd2si, 0, IX86_BUILTIN_CVTSD2SI, 0, 0 },
+ { MASK_SSE2, CODE_FOR_cvttsd2si, 0, IX86_BUILTIN_CVTTSD2SI, 0, 0 },
+ { MASK_SSE264, CODE_FOR_cvtsd2siq, 0, IX86_BUILTIN_CVTSD2SI64, 0, 0 },
+ { MASK_SSE264, CODE_FOR_cvttsd2siq, 0, IX86_BUILTIN_CVTTSD2SI64, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_cvtps2dq, 0, IX86_BUILTIN_CVTPS2DQ, 0, 0 },
+ { MASK_SSE2, CODE_FOR_cvtps2pd, 0, IX86_BUILTIN_CVTPS2PD, 0, 0 },
+ { MASK_SSE2, CODE_FOR_cvttps2dq, 0, IX86_BUILTIN_CVTTPS2DQ, 0, 0 },
+
+ { MASK_SSE2, CODE_FOR_sse2_movq, 0, IX86_BUILTIN_MOVQ, 0, 0 }
};
void
@@ -11110,218 +12422,303 @@ ix86_init_mmx_sse_builtins ()
{
const struct builtin_description * d;
size_t i;
- tree endlink = void_list_node;
tree pchar_type_node = build_pointer_type (char_type_node);
+ tree pcchar_type_node = build_pointer_type (
+ build_type_variant (char_type_node, 1, 0));
tree pfloat_type_node = build_pointer_type (float_type_node);
+ tree pcfloat_type_node = build_pointer_type (
+ build_type_variant (float_type_node, 1, 0));
tree pv2si_type_node = build_pointer_type (V2SI_type_node);
+ tree pv2di_type_node = build_pointer_type (V2DI_type_node);
tree pdi_type_node = build_pointer_type (long_long_unsigned_type_node);
/* Comparisons. */
tree int_ftype_v4sf_v4sf
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE,
- V4SF_type_node,
- endlink)));
+ = build_function_type_list (integer_type_node,
+ V4SF_type_node, V4SF_type_node, NULL_TREE);
tree v4si_ftype_v4sf_v4sf
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE,
- V4SF_type_node,
- endlink)));
+ = build_function_type_list (V4SI_type_node,
+ V4SF_type_node, V4SF_type_node, NULL_TREE);
/* MMX/SSE/integer conversions. */
tree int_ftype_v4sf
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- endlink));
+ = build_function_type_list (integer_type_node,
+ V4SF_type_node, NULL_TREE);
+ tree int64_ftype_v4sf
+ = build_function_type_list (long_long_integer_type_node,
+ V4SF_type_node, NULL_TREE);
tree int_ftype_v8qi
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- endlink));
+ = build_function_type_list (integer_type_node, V8QI_type_node, NULL_TREE);
tree v4sf_ftype_v4sf_int
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- endlink)));
+ = build_function_type_list (V4SF_type_node,
+ V4SF_type_node, integer_type_node, NULL_TREE);
+ tree v4sf_ftype_v4sf_int64
+ = build_function_type_list (V4SF_type_node,
+ V4SF_type_node, long_long_integer_type_node,
+ NULL_TREE);
tree v4sf_ftype_v4sf_v2si
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- endlink)));
+ = build_function_type_list (V4SF_type_node,
+ V4SF_type_node, V2SI_type_node, NULL_TREE);
tree int_ftype_v4hi_int
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- endlink)));
+ = build_function_type_list (integer_type_node,
+ V4HI_type_node, integer_type_node, NULL_TREE);
tree v4hi_ftype_v4hi_int_int
- = build_function_type (V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
+ = build_function_type_list (V4HI_type_node, V4HI_type_node,
+ integer_type_node, integer_type_node,
+ NULL_TREE);
/* Miscellaneous. */
tree v8qi_ftype_v4hi_v4hi
- = build_function_type (V8QI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- endlink)));
+ = build_function_type_list (V8QI_type_node,
+ V4HI_type_node, V4HI_type_node, NULL_TREE);
tree v4hi_ftype_v2si_v2si
- = build_function_type (V4HI_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- endlink)));
+ = build_function_type_list (V4HI_type_node,
+ V2SI_type_node, V2SI_type_node, NULL_TREE);
tree v4sf_ftype_v4sf_v4sf_int
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
- tree v4hi_ftype_v8qi_v8qi
- = build_function_type (V4HI_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- endlink)));
+ = build_function_type_list (V4SF_type_node,
+ V4SF_type_node, V4SF_type_node,
+ integer_type_node, NULL_TREE);
tree v2si_ftype_v4hi_v4hi
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- endlink)));
+ = build_function_type_list (V2SI_type_node,
+ V4HI_type_node, V4HI_type_node, NULL_TREE);
tree v4hi_ftype_v4hi_int
- = build_function_type (V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- endlink)));
+ = build_function_type_list (V4HI_type_node,
+ V4HI_type_node, integer_type_node, NULL_TREE);
tree v4hi_ftype_v4hi_di
- = build_function_type (V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE,
- long_long_integer_type_node,
- endlink)));
+ = build_function_type_list (V4HI_type_node,
+ V4HI_type_node, long_long_unsigned_type_node,
+ NULL_TREE);
tree v2si_ftype_v2si_di
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- tree_cons (NULL_TREE,
- long_long_integer_type_node,
- endlink)));
+ = build_function_type_list (V2SI_type_node,
+ V2SI_type_node, long_long_unsigned_type_node,
+ NULL_TREE);
tree void_ftype_void
- = build_function_type (void_type_node, endlink);
+ = build_function_type (void_type_node, void_list_node);
tree void_ftype_unsigned
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, unsigned_type_node,
- endlink));
+ = build_function_type_list (void_type_node, unsigned_type_node, NULL_TREE);
tree unsigned_ftype_void
- = build_function_type (unsigned_type_node, endlink);
+ = build_function_type (unsigned_type_node, void_list_node);
tree di_ftype_void
- = build_function_type (long_long_unsigned_type_node, endlink);
+ = build_function_type (long_long_unsigned_type_node, void_list_node);
tree v4sf_ftype_void
- = build_function_type (V4SF_type_node, endlink);
+ = build_function_type (V4SF_type_node, void_list_node);
tree v2si_ftype_v4sf
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- endlink));
+ = build_function_type_list (V2SI_type_node, V4SF_type_node, NULL_TREE);
/* Loads/stores. */
- tree maskmovq_args = tree_cons (NULL_TREE, V8QI_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- tree_cons (NULL_TREE,
- pchar_type_node,
- endlink)));
tree void_ftype_v8qi_v8qi_pchar
- = build_function_type (void_type_node, maskmovq_args);
- tree v4sf_ftype_pfloat
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, pfloat_type_node,
- endlink));
+ = build_function_type_list (void_type_node,
+ V8QI_type_node, V8QI_type_node,
+ pchar_type_node, NULL_TREE);
+ tree v4sf_ftype_pcfloat
+ = build_function_type_list (V4SF_type_node, pcfloat_type_node, NULL_TREE);
/* @@@ the type is bogus */
tree v4sf_ftype_v4sf_pv2si
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE, pv2si_type_node,
- endlink)));
+ = build_function_type_list (V4SF_type_node,
+ V4SF_type_node, pv2si_type_node, NULL_TREE);
tree void_ftype_pv2si_v4sf
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, pv2si_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- endlink)));
+ = build_function_type_list (void_type_node,
+ pv2si_type_node, V4SF_type_node, NULL_TREE);
tree void_ftype_pfloat_v4sf
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, pfloat_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- endlink)));
+ = build_function_type_list (void_type_node,
+ pfloat_type_node, V4SF_type_node, NULL_TREE);
tree void_ftype_pdi_di
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, pdi_type_node,
- tree_cons (NULL_TREE,
- long_long_unsigned_type_node,
- endlink)));
+ = build_function_type_list (void_type_node,
+ pdi_type_node, long_long_unsigned_type_node,
+ NULL_TREE);
+ tree void_ftype_pv2di_v2di
+ = build_function_type_list (void_type_node,
+ pv2di_type_node, V2DI_type_node, NULL_TREE);
/* Normal vector unops. */
tree v4sf_ftype_v4sf
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- endlink));
+ = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE);
/* Normal vector binops. */
tree v4sf_ftype_v4sf_v4sf
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- endlink)));
+ = build_function_type_list (V4SF_type_node,
+ V4SF_type_node, V4SF_type_node, NULL_TREE);
tree v8qi_ftype_v8qi_v8qi
- = build_function_type (V8QI_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- tree_cons (NULL_TREE, V8QI_type_node,
- endlink)));
+ = build_function_type_list (V8QI_type_node,
+ V8QI_type_node, V8QI_type_node, NULL_TREE);
tree v4hi_ftype_v4hi_v4hi
- = build_function_type (V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- tree_cons (NULL_TREE, V4HI_type_node,
- endlink)));
+ = build_function_type_list (V4HI_type_node,
+ V4HI_type_node, V4HI_type_node, NULL_TREE);
tree v2si_ftype_v2si_v2si
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- endlink)));
+ = build_function_type_list (V2SI_type_node,
+ V2SI_type_node, V2SI_type_node, NULL_TREE);
tree di_ftype_di_di
- = build_function_type (long_long_unsigned_type_node,
- tree_cons (NULL_TREE, long_long_unsigned_type_node,
- tree_cons (NULL_TREE,
- long_long_unsigned_type_node,
- endlink)));
+ = build_function_type_list (long_long_unsigned_type_node,
+ long_long_unsigned_type_node,
+ long_long_unsigned_type_node, NULL_TREE);
tree v2si_ftype_v2sf
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, V2SF_type_node,
- endlink));
+ = build_function_type_list (V2SI_type_node, V2SF_type_node, NULL_TREE);
tree v2sf_ftype_v2si
- = build_function_type (V2SF_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- endlink));
+ = build_function_type_list (V2SF_type_node, V2SI_type_node, NULL_TREE);
tree v2si_ftype_v2si
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, V2SI_type_node,
- endlink));
+ = build_function_type_list (V2SI_type_node, V2SI_type_node, NULL_TREE);
tree v2sf_ftype_v2sf
- = build_function_type (V2SF_type_node,
- tree_cons (NULL_TREE, V2SF_type_node,
- endlink));
+ = build_function_type_list (V2SF_type_node, V2SF_type_node, NULL_TREE);
tree v2sf_ftype_v2sf_v2sf
- = build_function_type (V2SF_type_node,
- tree_cons (NULL_TREE, V2SF_type_node,
- tree_cons (NULL_TREE,
- V2SF_type_node,
- endlink)));
+ = build_function_type_list (V2SF_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
tree v2si_ftype_v2sf_v2sf
- = build_function_type (V2SI_type_node,
- tree_cons (NULL_TREE, V2SF_type_node,
- tree_cons (NULL_TREE,
- V2SF_type_node,
- endlink)));
+ = build_function_type_list (V2SI_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
+ tree pint_type_node = build_pointer_type (integer_type_node);
+ tree pcint_type_node = build_pointer_type (
+ build_type_variant (integer_type_node, 1, 0));
+ tree pdouble_type_node = build_pointer_type (double_type_node);
+ tree pcdouble_type_node = build_pointer_type (
+ build_type_variant (double_type_node, 1, 0));
+ tree int_ftype_v2df_v2df
+ = build_function_type_list (integer_type_node,
+ V2DF_type_node, V2DF_type_node, NULL_TREE);
+
+ tree ti_ftype_void
+ = build_function_type (intTI_type_node, void_list_node);
+ tree v2di_ftype_void
+ = build_function_type (V2DI_type_node, void_list_node);
+ tree ti_ftype_ti_ti
+ = build_function_type_list (intTI_type_node,
+ intTI_type_node, intTI_type_node, NULL_TREE);
+ tree void_ftype_pcvoid
+ = build_function_type_list (void_type_node, const_ptr_type_node, NULL_TREE);
+ tree v2di_ftype_di
+ = build_function_type_list (V2DI_type_node,
+ long_long_unsigned_type_node, NULL_TREE);
+ tree di_ftype_v2di
+ = build_function_type_list (long_long_unsigned_type_node,
+ V2DI_type_node, NULL_TREE);
+ tree v4sf_ftype_v4si
+ = build_function_type_list (V4SF_type_node, V4SI_type_node, NULL_TREE);
+ tree v4si_ftype_v4sf
+ = build_function_type_list (V4SI_type_node, V4SF_type_node, NULL_TREE);
+ tree v2df_ftype_v4si
+ = build_function_type_list (V2DF_type_node, V4SI_type_node, NULL_TREE);
+ tree v4si_ftype_v2df
+ = build_function_type_list (V4SI_type_node, V2DF_type_node, NULL_TREE);
+ tree v2si_ftype_v2df
+ = build_function_type_list (V2SI_type_node, V2DF_type_node, NULL_TREE);
+ tree v4sf_ftype_v2df
+ = build_function_type_list (V4SF_type_node, V2DF_type_node, NULL_TREE);
+ tree v2df_ftype_v2si
+ = build_function_type_list (V2DF_type_node, V2SI_type_node, NULL_TREE);
+ tree v2df_ftype_v4sf
+ = build_function_type_list (V2DF_type_node, V4SF_type_node, NULL_TREE);
+ tree int_ftype_v2df
+ = build_function_type_list (integer_type_node, V2DF_type_node, NULL_TREE);
+ tree int64_ftype_v2df
+ = build_function_type_list (long_long_integer_type_node,
+ V2DF_type_node, NULL_TREE);
+ tree v2df_ftype_v2df_int
+ = build_function_type_list (V2DF_type_node,
+ V2DF_type_node, integer_type_node, NULL_TREE);
+ tree v2df_ftype_v2df_int64
+ = build_function_type_list (V2DF_type_node,
+ V2DF_type_node, long_long_integer_type_node,
+ NULL_TREE);
+ tree v4sf_ftype_v4sf_v2df
+ = build_function_type_list (V4SF_type_node,
+ V4SF_type_node, V2DF_type_node, NULL_TREE);
+ tree v2df_ftype_v2df_v4sf
+ = build_function_type_list (V2DF_type_node,
+ V2DF_type_node, V4SF_type_node, NULL_TREE);
+ tree v2df_ftype_v2df_v2df_int
+ = build_function_type_list (V2DF_type_node,
+ V2DF_type_node, V2DF_type_node,
+ integer_type_node,
+ NULL_TREE);
+ tree v2df_ftype_v2df_pv2si
+ = build_function_type_list (V2DF_type_node,
+ V2DF_type_node, pv2si_type_node, NULL_TREE);
+ tree void_ftype_pv2si_v2df
+ = build_function_type_list (void_type_node,
+ pv2si_type_node, V2DF_type_node, NULL_TREE);
+ tree void_ftype_pdouble_v2df
+ = build_function_type_list (void_type_node,
+ pdouble_type_node, V2DF_type_node, NULL_TREE);
+ tree void_ftype_pint_int
+ = build_function_type_list (void_type_node,
+ pint_type_node, integer_type_node, NULL_TREE);
+ tree void_ftype_v16qi_v16qi_pchar
+ = build_function_type_list (void_type_node,
+ V16QI_type_node, V16QI_type_node,
+ pchar_type_node, NULL_TREE);
+ tree v2df_ftype_pcdouble
+ = build_function_type_list (V2DF_type_node, pcdouble_type_node, NULL_TREE);
+ tree v2df_ftype_v2df_v2df
+ = build_function_type_list (V2DF_type_node,
+ V2DF_type_node, V2DF_type_node, NULL_TREE);
+ tree v16qi_ftype_v16qi_v16qi
+ = build_function_type_list (V16QI_type_node,
+ V16QI_type_node, V16QI_type_node, NULL_TREE);
+ tree v8hi_ftype_v8hi_v8hi
+ = build_function_type_list (V8HI_type_node,
+ V8HI_type_node, V8HI_type_node, NULL_TREE);
+ tree v4si_ftype_v4si_v4si
+ = build_function_type_list (V4SI_type_node,
+ V4SI_type_node, V4SI_type_node, NULL_TREE);
+ tree v2di_ftype_v2di_v2di
+ = build_function_type_list (V2DI_type_node,
+ V2DI_type_node, V2DI_type_node, NULL_TREE);
+ tree v2di_ftype_v2df_v2df
+ = build_function_type_list (V2DI_type_node,
+ V2DF_type_node, V2DF_type_node, NULL_TREE);
+ tree v2df_ftype_v2df
+ = build_function_type_list (V2DF_type_node, V2DF_type_node, NULL_TREE);
+ tree v2df_ftype_double
+ = build_function_type_list (V2DF_type_node, double_type_node, NULL_TREE);
+ tree v2df_ftype_double_double
+ = build_function_type_list (V2DF_type_node,
+ double_type_node, double_type_node, NULL_TREE);
+ tree int_ftype_v8hi_int
+ = build_function_type_list (integer_type_node,
+ V8HI_type_node, integer_type_node, NULL_TREE);
+ tree v8hi_ftype_v8hi_int_int
+ = build_function_type_list (V8HI_type_node,
+ V8HI_type_node, integer_type_node,
+ integer_type_node, NULL_TREE);
+ tree v2di_ftype_v2di_int
+ = build_function_type_list (V2DI_type_node,
+ V2DI_type_node, integer_type_node, NULL_TREE);
+ tree v4si_ftype_v4si_int
+ = build_function_type_list (V4SI_type_node,
+ V4SI_type_node, integer_type_node, NULL_TREE);
+ tree v8hi_ftype_v8hi_int
+ = build_function_type_list (V8HI_type_node,
+ V8HI_type_node, integer_type_node, NULL_TREE);
+ tree v8hi_ftype_v8hi_v2di
+ = build_function_type_list (V8HI_type_node,
+ V8HI_type_node, V2DI_type_node, NULL_TREE);
+ tree v4si_ftype_v4si_v2di
+ = build_function_type_list (V4SI_type_node,
+ V4SI_type_node, V2DI_type_node, NULL_TREE);
+ tree v4si_ftype_v8hi_v8hi
+ = build_function_type_list (V4SI_type_node,
+ V8HI_type_node, V8HI_type_node, NULL_TREE);
+ tree di_ftype_v8qi_v8qi
+ = build_function_type_list (long_long_unsigned_type_node,
+ V8QI_type_node, V8QI_type_node, NULL_TREE);
+ tree v2di_ftype_v16qi_v16qi
+ = build_function_type_list (V2DI_type_node,
+ V16QI_type_node, V16QI_type_node, NULL_TREE);
+ tree int_ftype_v16qi
+ = build_function_type_list (integer_type_node, V16QI_type_node, NULL_TREE);
+ tree v16qi_ftype_pcchar
+ = build_function_type_list (V16QI_type_node, pcchar_type_node, NULL_TREE);
+ tree void_ftype_pchar_v16qi
+ = build_function_type_list (void_type_node,
+ pchar_type_node, V16QI_type_node, NULL_TREE);
+ tree v4si_ftype_pcint
+ = build_function_type_list (V4SI_type_node, pcint_type_node, NULL_TREE);
+ tree void_ftype_pcint_v4si
+ = build_function_type_list (void_type_node,
+ pcint_type_node, V4SI_type_node, NULL_TREE);
+ tree v2di_ftype_v2di
+ = build_function_type_list (V2DI_type_node, V2DI_type_node, NULL_TREE);
/* Add all builtins that are more or less simple operations on two
operands. */
- for (i = 0, d = bdesc_2arg; i < sizeof (bdesc_2arg) / sizeof *d; i++, d++)
+ for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
{
/* Use one of the operands; the target can have a different mode for
mask-generating compares. */
@@ -11334,6 +12731,24 @@ ix86_init_mmx_sse_builtins ()
switch (mode)
{
+ case V16QImode:
+ type = v16qi_ftype_v16qi_v16qi;
+ break;
+ case V8HImode:
+ type = v8hi_ftype_v8hi_v8hi;
+ break;
+ case V4SImode:
+ type = v4si_ftype_v4si_v4si;
+ break;
+ case V2DImode:
+ type = v2di_ftype_v2di_v2di;
+ break;
+ case V2DFmode:
+ type = v2df_ftype_v2df_v2df;
+ break;
+ case TImode:
+ type = ti_ftype_ti_ti;
+ break;
case V4SFmode:
type = v4sf_ftype_v4sf_v4sf;
break;
@@ -11361,14 +12776,18 @@ ix86_init_mmx_sse_builtins ()
|| d->icode == CODE_FOR_vmmaskncmpv4sf3)
type = v4si_ftype_v4sf_v4sf;
+ if (d->icode == CODE_FOR_maskcmpv2df3
+ || d->icode == CODE_FOR_maskncmpv2df3
+ || d->icode == CODE_FOR_vmmaskcmpv2df3
+ || d->icode == CODE_FOR_vmmaskncmpv2df3)
+ type = v2di_ftype_v2df_v2df;
+
def_builtin (d->mask, d->name, type, d->code);
}
/* Add the remaining MMX insns with somewhat more complicated types. */
def_builtin (MASK_MMX, "__builtin_ia32_mmx_zero", di_ftype_void, IX86_BUILTIN_MMX_ZERO);
def_builtin (MASK_MMX, "__builtin_ia32_emms", void_ftype_void, IX86_BUILTIN_EMMS);
- def_builtin (MASK_MMX, "__builtin_ia32_ldmxcsr", void_ftype_unsigned, IX86_BUILTIN_LDMXCSR);
- def_builtin (MASK_MMX, "__builtin_ia32_stmxcsr", unsigned_ftype_void, IX86_BUILTIN_STMXCSR);
def_builtin (MASK_MMX, "__builtin_ia32_psllw", v4hi_ftype_v4hi_di, IX86_BUILTIN_PSLLW);
def_builtin (MASK_MMX, "__builtin_ia32_pslld", v2si_ftype_v2si_di, IX86_BUILTIN_PSLLD);
def_builtin (MASK_MMX, "__builtin_ia32_psllq", di_ftype_di_di, IX86_BUILTIN_PSLLQ);
@@ -11384,59 +12803,62 @@ ix86_init_mmx_sse_builtins ()
def_builtin (MASK_MMX, "__builtin_ia32_pmaddwd", v2si_ftype_v4hi_v4hi, IX86_BUILTIN_PMADDWD);
/* comi/ucomi insns. */
- for (i = 0, d = bdesc_comi; i < sizeof (bdesc_comi) / sizeof *d; i++, d++)
- def_builtin (d->mask, d->name, int_ftype_v4sf_v4sf, d->code);
+ for (i = 0, d = bdesc_comi; i < ARRAY_SIZE (bdesc_comi); i++, d++)
+ if (d->mask == MASK_SSE2)
+ def_builtin (d->mask, d->name, int_ftype_v2df_v2df, d->code);
+ else
+ def_builtin (d->mask, d->name, int_ftype_v4sf_v4sf, d->code);
def_builtin (MASK_MMX, "__builtin_ia32_packsswb", v8qi_ftype_v4hi_v4hi, IX86_BUILTIN_PACKSSWB);
def_builtin (MASK_MMX, "__builtin_ia32_packssdw", v4hi_ftype_v2si_v2si, IX86_BUILTIN_PACKSSDW);
def_builtin (MASK_MMX, "__builtin_ia32_packuswb", v8qi_ftype_v4hi_v4hi, IX86_BUILTIN_PACKUSWB);
- def_builtin (MASK_SSE, "__builtin_ia32_cvtpi2ps", v4sf_ftype_v4sf_v2si, IX86_BUILTIN_CVTPI2PS);
- def_builtin (MASK_SSE, "__builtin_ia32_cvtps2pi", v2si_ftype_v4sf, IX86_BUILTIN_CVTPS2PI);
- def_builtin (MASK_SSE, "__builtin_ia32_cvtsi2ss", v4sf_ftype_v4sf_int, IX86_BUILTIN_CVTSI2SS);
- def_builtin (MASK_SSE, "__builtin_ia32_cvtss2si", int_ftype_v4sf, IX86_BUILTIN_CVTSS2SI);
- def_builtin (MASK_SSE, "__builtin_ia32_cvttps2pi", v2si_ftype_v4sf, IX86_BUILTIN_CVTTPS2PI);
- def_builtin (MASK_SSE, "__builtin_ia32_cvttss2si", int_ftype_v4sf, IX86_BUILTIN_CVTTSS2SI);
-
- def_builtin (MASK_SSE, "__builtin_ia32_andps", v4sf_ftype_v4sf_v4sf, IX86_BUILTIN_ANDPS);
- def_builtin (MASK_SSE, "__builtin_ia32_andnps", v4sf_ftype_v4sf_v4sf, IX86_BUILTIN_ANDNPS);
- def_builtin (MASK_SSE, "__builtin_ia32_orps", v4sf_ftype_v4sf_v4sf, IX86_BUILTIN_ORPS);
- def_builtin (MASK_SSE, "__builtin_ia32_xorps", v4sf_ftype_v4sf_v4sf, IX86_BUILTIN_XORPS);
-
- def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_pextrw", int_ftype_v4hi_int, IX86_BUILTIN_PEXTRW);
- def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_pinsrw", v4hi_ftype_v4hi_int_int, IX86_BUILTIN_PINSRW);
-
- def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_maskmovq", void_ftype_v8qi_v8qi_pchar, IX86_BUILTIN_MASKMOVQ);
-
- def_builtin (MASK_SSE, "__builtin_ia32_loadaps", v4sf_ftype_pfloat, IX86_BUILTIN_LOADAPS);
- def_builtin (MASK_SSE, "__builtin_ia32_loadups", v4sf_ftype_pfloat, IX86_BUILTIN_LOADUPS);
- def_builtin (MASK_SSE, "__builtin_ia32_loadss", v4sf_ftype_pfloat, IX86_BUILTIN_LOADSS);
- def_builtin (MASK_SSE, "__builtin_ia32_storeaps", void_ftype_pfloat_v4sf, IX86_BUILTIN_STOREAPS);
- def_builtin (MASK_SSE, "__builtin_ia32_storeups", void_ftype_pfloat_v4sf, IX86_BUILTIN_STOREUPS);
- def_builtin (MASK_SSE, "__builtin_ia32_storess", void_ftype_pfloat_v4sf, IX86_BUILTIN_STORESS);
-
- def_builtin (MASK_SSE, "__builtin_ia32_loadhps", v4sf_ftype_v4sf_pv2si, IX86_BUILTIN_LOADHPS);
- def_builtin (MASK_SSE, "__builtin_ia32_loadlps", v4sf_ftype_v4sf_pv2si, IX86_BUILTIN_LOADLPS);
- def_builtin (MASK_SSE, "__builtin_ia32_storehps", void_ftype_pv2si_v4sf, IX86_BUILTIN_STOREHPS);
- def_builtin (MASK_SSE, "__builtin_ia32_storelps", void_ftype_pv2si_v4sf, IX86_BUILTIN_STORELPS);
-
- def_builtin (MASK_SSE, "__builtin_ia32_movmskps", int_ftype_v4sf, IX86_BUILTIN_MOVMSKPS);
- def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_pmovmskb", int_ftype_v8qi, IX86_BUILTIN_PMOVMSKB);
- def_builtin (MASK_SSE, "__builtin_ia32_movntps", void_ftype_pfloat_v4sf, IX86_BUILTIN_MOVNTPS);
- def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_movntq", void_ftype_pdi_di, IX86_BUILTIN_MOVNTQ);
-
- def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_sfence", void_ftype_void, IX86_BUILTIN_SFENCE);
-
- def_builtin (MASK_SSE | MASK_3DNOW_A, "__builtin_ia32_psadbw", v4hi_ftype_v8qi_v8qi, IX86_BUILTIN_PSADBW);
-
- def_builtin (MASK_SSE, "__builtin_ia32_rcpps", v4sf_ftype_v4sf, IX86_BUILTIN_RCPPS);
- def_builtin (MASK_SSE, "__builtin_ia32_rcpss", v4sf_ftype_v4sf, IX86_BUILTIN_RCPSS);
- def_builtin (MASK_SSE, "__builtin_ia32_rsqrtps", v4sf_ftype_v4sf, IX86_BUILTIN_RSQRTPS);
- def_builtin (MASK_SSE, "__builtin_ia32_rsqrtss", v4sf_ftype_v4sf, IX86_BUILTIN_RSQRTSS);
- def_builtin (MASK_SSE, "__builtin_ia32_sqrtps", v4sf_ftype_v4sf, IX86_BUILTIN_SQRTPS);
- def_builtin (MASK_SSE, "__builtin_ia32_sqrtss", v4sf_ftype_v4sf, IX86_BUILTIN_SQRTSS);
-
- def_builtin (MASK_SSE, "__builtin_ia32_shufps", v4sf_ftype_v4sf_v4sf_int, IX86_BUILTIN_SHUFPS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_ldmxcsr", void_ftype_unsigned, IX86_BUILTIN_LDMXCSR);
+ def_builtin (MASK_SSE1, "__builtin_ia32_stmxcsr", unsigned_ftype_void, IX86_BUILTIN_STMXCSR);
+ def_builtin (MASK_SSE1, "__builtin_ia32_cvtpi2ps", v4sf_ftype_v4sf_v2si, IX86_BUILTIN_CVTPI2PS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_cvtps2pi", v2si_ftype_v4sf, IX86_BUILTIN_CVTPS2PI);
+ def_builtin (MASK_SSE1, "__builtin_ia32_cvtsi2ss", v4sf_ftype_v4sf_int, IX86_BUILTIN_CVTSI2SS);
+ def_builtin (MASK_SSE164, "__builtin_ia32_cvtsi642ss", v4sf_ftype_v4sf_int64, IX86_BUILTIN_CVTSI642SS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_cvtss2si", int_ftype_v4sf, IX86_BUILTIN_CVTSS2SI);
+ def_builtin (MASK_SSE164, "__builtin_ia32_cvtss2si64", int64_ftype_v4sf, IX86_BUILTIN_CVTSS2SI64);
+ def_builtin (MASK_SSE1, "__builtin_ia32_cvttps2pi", v2si_ftype_v4sf, IX86_BUILTIN_CVTTPS2PI);
+ def_builtin (MASK_SSE1, "__builtin_ia32_cvttss2si", int_ftype_v4sf, IX86_BUILTIN_CVTTSS2SI);
+ def_builtin (MASK_SSE164, "__builtin_ia32_cvttss2si64", int64_ftype_v4sf, IX86_BUILTIN_CVTTSS2SI64);
+
+ def_builtin (MASK_SSE1 | MASK_3DNOW_A, "__builtin_ia32_pextrw", int_ftype_v4hi_int, IX86_BUILTIN_PEXTRW);
+ def_builtin (MASK_SSE1 | MASK_3DNOW_A, "__builtin_ia32_pinsrw", v4hi_ftype_v4hi_int_int, IX86_BUILTIN_PINSRW);
+
+ def_builtin (MASK_SSE1 | MASK_3DNOW_A, "__builtin_ia32_maskmovq", void_ftype_v8qi_v8qi_pchar, IX86_BUILTIN_MASKMOVQ);
+
+ def_builtin (MASK_SSE1, "__builtin_ia32_loadaps", v4sf_ftype_pcfloat, IX86_BUILTIN_LOADAPS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_loadups", v4sf_ftype_pcfloat, IX86_BUILTIN_LOADUPS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_loadss", v4sf_ftype_pcfloat, IX86_BUILTIN_LOADSS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_storeaps", void_ftype_pfloat_v4sf, IX86_BUILTIN_STOREAPS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_storeups", void_ftype_pfloat_v4sf, IX86_BUILTIN_STOREUPS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_storess", void_ftype_pfloat_v4sf, IX86_BUILTIN_STORESS);
+
+ def_builtin (MASK_SSE1, "__builtin_ia32_loadhps", v4sf_ftype_v4sf_pv2si, IX86_BUILTIN_LOADHPS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_loadlps", v4sf_ftype_v4sf_pv2si, IX86_BUILTIN_LOADLPS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_storehps", void_ftype_pv2si_v4sf, IX86_BUILTIN_STOREHPS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_storelps", void_ftype_pv2si_v4sf, IX86_BUILTIN_STORELPS);
+
+ def_builtin (MASK_SSE1, "__builtin_ia32_movmskps", int_ftype_v4sf, IX86_BUILTIN_MOVMSKPS);
+ def_builtin (MASK_SSE1 | MASK_3DNOW_A, "__builtin_ia32_pmovmskb", int_ftype_v8qi, IX86_BUILTIN_PMOVMSKB);
+ def_builtin (MASK_SSE1, "__builtin_ia32_movntps", void_ftype_pfloat_v4sf, IX86_BUILTIN_MOVNTPS);
+ def_builtin (MASK_SSE1 | MASK_3DNOW_A, "__builtin_ia32_movntq", void_ftype_pdi_di, IX86_BUILTIN_MOVNTQ);
+
+ def_builtin (MASK_SSE1 | MASK_3DNOW_A, "__builtin_ia32_sfence", void_ftype_void, IX86_BUILTIN_SFENCE);
+
+ def_builtin (MASK_SSE1 | MASK_3DNOW_A, "__builtin_ia32_psadbw", di_ftype_v8qi_v8qi, IX86_BUILTIN_PSADBW);
+
+ def_builtin (MASK_SSE1, "__builtin_ia32_rcpps", v4sf_ftype_v4sf, IX86_BUILTIN_RCPPS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_rcpss", v4sf_ftype_v4sf, IX86_BUILTIN_RCPSS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_rsqrtps", v4sf_ftype_v4sf, IX86_BUILTIN_RSQRTPS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_rsqrtss", v4sf_ftype_v4sf, IX86_BUILTIN_RSQRTSS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_sqrtps", v4sf_ftype_v4sf, IX86_BUILTIN_SQRTPS);
+ def_builtin (MASK_SSE1, "__builtin_ia32_sqrtss", v4sf_ftype_v4sf, IX86_BUILTIN_SQRTSS);
+
+ def_builtin (MASK_SSE1, "__builtin_ia32_shufps", v4sf_ftype_v4sf_v4sf_int, IX86_BUILTIN_SHUFPS);
/* Original 3DNow! */
def_builtin (MASK_3DNOW, "__builtin_ia32_femms", void_ftype_void, IX86_BUILTIN_FEMMS);
@@ -11468,7 +12890,116 @@ ix86_init_mmx_sse_builtins ()
def_builtin (MASK_3DNOW_A, "__builtin_ia32_pswapdsf", v2sf_ftype_v2sf, IX86_BUILTIN_PSWAPDSF);
def_builtin (MASK_3DNOW_A, "__builtin_ia32_pswapdsi", v2si_ftype_v2si, IX86_BUILTIN_PSWAPDSI);
- def_builtin (MASK_SSE, "__builtin_ia32_setzerops", v4sf_ftype_void, IX86_BUILTIN_SSE_ZERO);
+ def_builtin (MASK_SSE1, "__builtin_ia32_setzerops", v4sf_ftype_void, IX86_BUILTIN_SSE_ZERO);
+
+ /* SSE2 */
+ def_builtin (MASK_SSE2, "__builtin_ia32_pextrw128", int_ftype_v8hi_int, IX86_BUILTIN_PEXTRW128);
+ def_builtin (MASK_SSE2, "__builtin_ia32_pinsrw128", v8hi_ftype_v8hi_int_int, IX86_BUILTIN_PINSRW128);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_maskmovdqu", void_ftype_v16qi_v16qi_pchar, IX86_BUILTIN_MASKMOVDQU);
+ def_builtin (MASK_SSE2, "__builtin_ia32_movq2dq", v2di_ftype_di, IX86_BUILTIN_MOVQ2DQ);
+ def_builtin (MASK_SSE2, "__builtin_ia32_movdq2q", di_ftype_v2di, IX86_BUILTIN_MOVDQ2Q);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_loadapd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADAPD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_loadupd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADUPD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_loadsd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADSD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_storeapd", void_ftype_pdouble_v2df, IX86_BUILTIN_STOREAPD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_storeupd", void_ftype_pdouble_v2df, IX86_BUILTIN_STOREUPD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_storesd", void_ftype_pdouble_v2df, IX86_BUILTIN_STORESD);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_loadhpd", v2df_ftype_v2df_pv2si, IX86_BUILTIN_LOADHPD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_loadlpd", v2df_ftype_v2df_pv2si, IX86_BUILTIN_LOADLPD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_storehpd", void_ftype_pv2si_v2df, IX86_BUILTIN_STOREHPD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_storelpd", void_ftype_pv2si_v2df, IX86_BUILTIN_STORELPD);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_movmskpd", int_ftype_v2df, IX86_BUILTIN_MOVMSKPD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_pmovmskb128", int_ftype_v16qi, IX86_BUILTIN_PMOVMSKB128);
+ def_builtin (MASK_SSE2, "__builtin_ia32_movnti", void_ftype_pint_int, IX86_BUILTIN_MOVNTI);
+ def_builtin (MASK_SSE2, "__builtin_ia32_movntpd", void_ftype_pdouble_v2df, IX86_BUILTIN_MOVNTPD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_movntdq", void_ftype_pv2di_v2di, IX86_BUILTIN_MOVNTDQ);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_pshufd", v4si_ftype_v4si_int, IX86_BUILTIN_PSHUFD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_pshuflw", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSHUFLW);
+ def_builtin (MASK_SSE2, "__builtin_ia32_pshufhw", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSHUFHW);
+ def_builtin (MASK_SSE2, "__builtin_ia32_psadbw128", v2di_ftype_v16qi_v16qi, IX86_BUILTIN_PSADBW128);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_sqrtpd", v2df_ftype_v2df, IX86_BUILTIN_SQRTPD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_sqrtsd", v2df_ftype_v2df, IX86_BUILTIN_SQRTSD);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_shufpd", v2df_ftype_v2df_v2df_int, IX86_BUILTIN_SHUFPD);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvtdq2pd", v2df_ftype_v4si, IX86_BUILTIN_CVTDQ2PD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvtdq2ps", v4sf_ftype_v4si, IX86_BUILTIN_CVTDQ2PS);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvtpd2dq", v4si_ftype_v2df, IX86_BUILTIN_CVTPD2DQ);
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvtpd2pi", v2si_ftype_v2df, IX86_BUILTIN_CVTPD2PI);
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvtpd2ps", v4sf_ftype_v2df, IX86_BUILTIN_CVTPD2PS);
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvttpd2dq", v4si_ftype_v2df, IX86_BUILTIN_CVTTPD2DQ);
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvttpd2pi", v2si_ftype_v2df, IX86_BUILTIN_CVTTPD2PI);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvtpi2pd", v2df_ftype_v2si, IX86_BUILTIN_CVTPI2PD);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvtsd2si", int_ftype_v2df, IX86_BUILTIN_CVTSD2SI);
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvttsd2si", int_ftype_v2df, IX86_BUILTIN_CVTTSD2SI);
+ def_builtin (MASK_SSE264, "__builtin_ia32_cvtsd2si64", int64_ftype_v2df, IX86_BUILTIN_CVTSD2SI64);
+ def_builtin (MASK_SSE264, "__builtin_ia32_cvttsd2si64", int64_ftype_v2df, IX86_BUILTIN_CVTTSD2SI64);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvtps2dq", v4si_ftype_v4sf, IX86_BUILTIN_CVTPS2DQ);
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvtps2pd", v2df_ftype_v4sf, IX86_BUILTIN_CVTPS2PD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvttps2dq", v4si_ftype_v4sf, IX86_BUILTIN_CVTTPS2DQ);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvtsi2sd", v2df_ftype_v2df_int, IX86_BUILTIN_CVTSI2SD);
+ def_builtin (MASK_SSE264, "__builtin_ia32_cvtsi642sd", v2df_ftype_v2df_int64, IX86_BUILTIN_CVTSI642SD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvtsd2ss", v4sf_ftype_v4sf_v2df, IX86_BUILTIN_CVTSD2SS);
+ def_builtin (MASK_SSE2, "__builtin_ia32_cvtss2sd", v2df_ftype_v2df_v4sf, IX86_BUILTIN_CVTSS2SD);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_setpd1", v2df_ftype_double, IX86_BUILTIN_SETPD1);
+ def_builtin (MASK_SSE2, "__builtin_ia32_setpd", v2df_ftype_double_double, IX86_BUILTIN_SETPD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_setzeropd", ti_ftype_void, IX86_BUILTIN_CLRPD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_loadpd1", v2df_ftype_pcdouble, IX86_BUILTIN_LOADPD1);
+ def_builtin (MASK_SSE2, "__builtin_ia32_loadrpd", v2df_ftype_pcdouble, IX86_BUILTIN_LOADRPD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_storepd1", void_ftype_pdouble_v2df, IX86_BUILTIN_STOREPD1);
+ def_builtin (MASK_SSE2, "__builtin_ia32_storerpd", void_ftype_pdouble_v2df, IX86_BUILTIN_STORERPD);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_clflush", void_ftype_pcvoid, IX86_BUILTIN_CLFLUSH);
+ def_builtin (MASK_SSE2, "__builtin_ia32_lfence", void_ftype_void, IX86_BUILTIN_LFENCE);
+ def_builtin (MASK_SSE2, "__builtin_ia32_mfence", void_ftype_void, IX86_BUILTIN_MFENCE);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_loaddqa", v16qi_ftype_pcchar, IX86_BUILTIN_LOADDQA);
+ def_builtin (MASK_SSE2, "__builtin_ia32_loaddqu", v16qi_ftype_pcchar, IX86_BUILTIN_LOADDQU);
+ def_builtin (MASK_SSE2, "__builtin_ia32_loadd", v4si_ftype_pcint, IX86_BUILTIN_LOADD);
+ def_builtin (MASK_SSE2, "__builtin_ia32_storedqa", void_ftype_pchar_v16qi, IX86_BUILTIN_STOREDQA);
+ def_builtin (MASK_SSE2, "__builtin_ia32_storedqu", void_ftype_pchar_v16qi, IX86_BUILTIN_STOREDQU);
+ def_builtin (MASK_SSE2, "__builtin_ia32_stored", void_ftype_pcint_v4si, IX86_BUILTIN_STORED);
+ def_builtin (MASK_SSE2, "__builtin_ia32_movq", v2di_ftype_v2di, IX86_BUILTIN_MOVQ);
+
+ def_builtin (MASK_SSE1, "__builtin_ia32_setzero128", v2di_ftype_void, IX86_BUILTIN_CLRTI);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_psllw128", v8hi_ftype_v8hi_v2di, IX86_BUILTIN_PSLLW128);
+ def_builtin (MASK_SSE2, "__builtin_ia32_pslld128", v4si_ftype_v4si_v2di, IX86_BUILTIN_PSLLD128);
+ def_builtin (MASK_SSE2, "__builtin_ia32_psllq128", v2di_ftype_v2di_v2di, IX86_BUILTIN_PSLLQ128);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_psrlw128", v8hi_ftype_v8hi_v2di, IX86_BUILTIN_PSRLW128);
+ def_builtin (MASK_SSE2, "__builtin_ia32_psrld128", v4si_ftype_v4si_v2di, IX86_BUILTIN_PSRLD128);
+ def_builtin (MASK_SSE2, "__builtin_ia32_psrlq128", v2di_ftype_v2di_v2di, IX86_BUILTIN_PSRLQ128);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_psraw128", v8hi_ftype_v8hi_v2di, IX86_BUILTIN_PSRAW128);
+ def_builtin (MASK_SSE2, "__builtin_ia32_psrad128", v4si_ftype_v4si_v2di, IX86_BUILTIN_PSRAD128);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_pslldqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSLLDQI128);
+ def_builtin (MASK_SSE2, "__builtin_ia32_psllwi128", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSLLWI128);
+ def_builtin (MASK_SSE2, "__builtin_ia32_pslldi128", v4si_ftype_v4si_int, IX86_BUILTIN_PSLLDI128);
+ def_builtin (MASK_SSE2, "__builtin_ia32_psllqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSLLQI128);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_psrldqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSRLDQI128);
+ def_builtin (MASK_SSE2, "__builtin_ia32_psrlwi128", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSRLWI128);
+ def_builtin (MASK_SSE2, "__builtin_ia32_psrldi128", v4si_ftype_v4si_int, IX86_BUILTIN_PSRLDI128);
+ def_builtin (MASK_SSE2, "__builtin_ia32_psrlqi128", v2di_ftype_v2di_int, IX86_BUILTIN_PSRLQI128);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_psrawi128", v8hi_ftype_v8hi_int, IX86_BUILTIN_PSRAWI128);
+ def_builtin (MASK_SSE2, "__builtin_ia32_psradi128", v4si_ftype_v4si_int, IX86_BUILTIN_PSRADI128);
+
+ def_builtin (MASK_SSE2, "__builtin_ia32_pmaddwd128", v4si_ftype_v8hi_v8hi, IX86_BUILTIN_PMADDWD128);
}
/* Errors in the source file can cause expand_expr to return const0_rtx
@@ -11519,6 +13050,13 @@ ix86_expand_binop_builtin (icode, arglist, target)
|| ! (*insn_data[icode].operand[0].predicate) (target, tmode))
target = gen_reg_rtx (tmode);
+ if (GET_MODE (op1) == SImode && mode1 == TImode)
+ {
+ rtx x = gen_reg_rtx (V4SImode);
+ emit_insn (gen_sse2_loadd (x, op1));
+ op1 = gen_lowpart (TImode, x);
+ }
+
/* In case the insn wants input operands in modes different from
the result, abort. */
if (GET_MODE (op0) != mode0 || GET_MODE (op1) != mode1)
@@ -11542,45 +13080,6 @@ ix86_expand_binop_builtin (icode, arglist, target)
return target;
}
-/* In type_for_mode we restrict the ability to create TImode types
- to hosts with 64-bit H_W_I. So we've defined the SSE logicals
- to have a V4SFmode signature. Convert them in-place to TImode. */
-
-static rtx
-ix86_expand_timode_binop_builtin (icode, arglist, target)
- enum insn_code icode;
- tree arglist;
- rtx target;
-{
- rtx pat;
- tree arg0 = TREE_VALUE (arglist);
- tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
-
- op0 = gen_lowpart (TImode, op0);
- op1 = gen_lowpart (TImode, op1);
- target = gen_reg_rtx (TImode);
-
- if (! (*insn_data[icode].operand[1].predicate) (op0, TImode))
- op0 = copy_to_mode_reg (TImode, op0);
- if (! (*insn_data[icode].operand[2].predicate) (op1, TImode))
- op1 = copy_to_mode_reg (TImode, op1);
-
- /* In the commutative cases, both op0 and op1 are nonimmediate_operand,
- yet one of the two must not be a memory. This is normally enforced
- by expanders, but we didn't bother to create one here. */
- if (GET_CODE (op0) == MEM && GET_CODE (op1) == MEM)
- op0 = copy_to_mode_reg (TImode, op0);
-
- pat = GEN_FCN (icode) (target, op0, op1);
- if (! pat)
- return 0;
- emit_insn (pat);
-
- return gen_lowpart (V4SFmode, target);
-}
-
/* Subroutine of ix86_expand_builtin to take care of stores. */
static rtx
@@ -11600,9 +13099,7 @@ ix86_expand_store_builtin (icode, arglist)
op1 = safe_vector_operand (op1, mode1);
op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
-
- if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
- op1 = copy_to_mode_reg (mode1, op1);
+ op1 = copy_to_mode_reg (mode1, op1);
pat = GEN_FCN (icode) (op0, op1);
if (pat)
@@ -11672,11 +13169,11 @@ ix86_expand_unop1_builtin (icode, arglist, target)
if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
op0 = copy_to_mode_reg (mode0, op0);
-
+
op1 = op0;
if (! (*insn_data[icode].operand[2].predicate) (op1, mode0))
op1 = copy_to_mode_reg (mode0, op1);
-
+
pat = GEN_FCN (icode) (target, op0, op1);
if (! pat)
return 0;
@@ -11778,14 +13275,14 @@ ix86_expand_sse_comi (d, arglist, target)
op1 = copy_to_mode_reg (mode1, op1);
op2 = gen_rtx_fmt_ee (comparison, mode0, op0, op1);
- pat = GEN_FCN (d->icode) (op0, op1, op2);
+ pat = GEN_FCN (d->icode) (op0, op1);
if (! pat)
return 0;
emit_insn (pat);
emit_insn (gen_rtx_SET (VOIDmode,
gen_rtx_STRICT_LOW_PART (VOIDmode, target),
gen_rtx_fmt_ee (comparison, QImode,
- gen_rtx_REG (CCmode, FLAGS_REG),
+ SET_DEST (pat),
const0_rtx)));
return SUBREG_REG (target);
@@ -11826,7 +13323,10 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
return 0;
case IX86_BUILTIN_PEXTRW:
- icode = CODE_FOR_mmx_pextrw;
+ case IX86_BUILTIN_PEXTRW128:
+ icode = (fcode == IX86_BUILTIN_PEXTRW
+ ? CODE_FOR_mmx_pextrw
+ : CODE_FOR_sse2_pextrw);
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
@@ -11854,7 +13354,10 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
return target;
case IX86_BUILTIN_PINSRW:
- icode = CODE_FOR_mmx_pinsrw;
+ case IX86_BUILTIN_PINSRW128:
+ icode = (fcode == IX86_BUILTIN_PINSRW
+ ? CODE_FOR_mmx_pinsrw
+ : CODE_FOR_sse2_pinsrw);
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
@@ -11887,7 +13390,11 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
return target;
case IX86_BUILTIN_MASKMOVQ:
- icode = TARGET_64BIT ? CODE_FOR_mmx_maskmovq_rex : CODE_FOR_mmx_maskmovq;
+ case IX86_BUILTIN_MASKMOVDQU:
+ icode = (fcode == IX86_BUILTIN_MASKMOVQ
+ ? (TARGET_64BIT ? CODE_FOR_mmx_maskmovq_rex : CODE_FOR_mmx_maskmovq)
+ : (TARGET_64BIT ? CODE_FOR_sse2_maskmovdqu_rex64
+ : CODE_FOR_sse2_maskmovdqu));
/* Note the arg order is different from the operand order. */
arg1 = TREE_VALUE (arglist);
arg2 = TREE_VALUE (TREE_CHAIN (arglist));
@@ -11918,19 +13425,6 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
case IX86_BUILTIN_RCPSS:
return ix86_expand_unop1_builtin (CODE_FOR_vmrcpv4sf2, arglist, target);
- case IX86_BUILTIN_ANDPS:
- return ix86_expand_timode_binop_builtin (CODE_FOR_sse_andti3,
- arglist, target);
- case IX86_BUILTIN_ANDNPS:
- return ix86_expand_timode_binop_builtin (CODE_FOR_sse_nandti3,
- arglist, target);
- case IX86_BUILTIN_ORPS:
- return ix86_expand_timode_binop_builtin (CODE_FOR_sse_iorti3,
- arglist, target);
- case IX86_BUILTIN_XORPS:
- return ix86_expand_timode_binop_builtin (CODE_FOR_sse_xorti3,
- arglist, target);
-
case IX86_BUILTIN_LOADAPS:
return ix86_expand_unop_builtin (CODE_FOR_sse_movaps, arglist, target, 1);
@@ -11939,6 +13433,7 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
case IX86_BUILTIN_STOREAPS:
return ix86_expand_store_builtin (CODE_FOR_sse_movaps, arglist);
+
case IX86_BUILTIN_STOREUPS:
return ix86_expand_store_builtin (CODE_FOR_sse_movups, arglist);
@@ -11950,8 +13445,12 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
case IX86_BUILTIN_LOADHPS:
case IX86_BUILTIN_LOADLPS:
- icode = (fcode == IX86_BUILTIN_LOADHPS
- ? CODE_FOR_sse_movhps : CODE_FOR_sse_movlps);
+ case IX86_BUILTIN_LOADHPD:
+ case IX86_BUILTIN_LOADLPD:
+ icode = (fcode == IX86_BUILTIN_LOADHPS ? CODE_FOR_sse_movhps
+ : fcode == IX86_BUILTIN_LOADLPS ? CODE_FOR_sse_movlps
+ : fcode == IX86_BUILTIN_LOADHPD ? CODE_FOR_sse2_movhpd
+ : CODE_FOR_sse2_movlpd);
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
@@ -11975,8 +13474,12 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
case IX86_BUILTIN_STOREHPS:
case IX86_BUILTIN_STORELPS:
- icode = (fcode == IX86_BUILTIN_STOREHPS
- ? CODE_FOR_sse_movhps : CODE_FOR_sse_movlps);
+ case IX86_BUILTIN_STOREHPD:
+ case IX86_BUILTIN_STORELPD:
+ icode = (fcode == IX86_BUILTIN_STOREHPS ? CODE_FOR_sse_movhps
+ : fcode == IX86_BUILTIN_STORELPS ? CODE_FOR_sse_movlps
+ : fcode == IX86_BUILTIN_STOREHPD ? CODE_FOR_sse2_movhpd
+ : CODE_FOR_sse2_movlpd);
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
@@ -12012,7 +13515,10 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
return copy_to_mode_reg (SImode, target);
case IX86_BUILTIN_SHUFPS:
- icode = CODE_FOR_sse_shufps;
+ case IX86_BUILTIN_SHUFPD:
+ icode = (fcode == IX86_BUILTIN_SHUFPS
+ ? CODE_FOR_sse_shufps
+ : CODE_FOR_sse2_shufpd);
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
@@ -12045,7 +13551,13 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
return target;
case IX86_BUILTIN_PSHUFW:
- icode = CODE_FOR_mmx_pshufw;
+ case IX86_BUILTIN_PSHUFD:
+ case IX86_BUILTIN_PSHUFHW:
+ case IX86_BUILTIN_PSHUFLW:
+ icode = ( fcode == IX86_BUILTIN_PSHUFHW ? CODE_FOR_sse2_pshufhw
+ : fcode == IX86_BUILTIN_PSHUFLW ? CODE_FOR_sse2_pshuflw
+ : fcode == IX86_BUILTIN_PSHUFD ? CODE_FOR_sse2_pshufd
+ : CODE_FOR_mmx_pshufw);
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
@@ -12072,6 +13584,35 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
emit_insn (pat);
return target;
+ case IX86_BUILTIN_PSLLDQI128:
+ case IX86_BUILTIN_PSRLDQI128:
+ icode = ( fcode == IX86_BUILTIN_PSLLDQI128 ? CODE_FOR_sse2_ashlti3
+ : CODE_FOR_sse2_lshrti3);
+ arg0 = TREE_VALUE (arglist);
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ tmode = insn_data[icode].operand[0].mode;
+ mode1 = insn_data[icode].operand[1].mode;
+ mode2 = insn_data[icode].operand[2].mode;
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode1))
+ {
+ op0 = copy_to_reg (op0);
+ op0 = simplify_gen_subreg (mode1, op0, GET_MODE (op0), 0);
+ }
+ if (! (*insn_data[icode].operand[2].predicate) (op1, mode2))
+ {
+ error ("shift must be an immediate");
+ return const0_rtx;
+ }
+ target = gen_reg_rtx (V2DImode);
+ pat = GEN_FCN (icode) (simplify_gen_subreg (tmode, target, V2DImode, 0), op0, op1);
+ if (! pat)
+ return 0;
+ emit_insn (pat);
+ return target;
+
case IX86_BUILTIN_FEMMS:
emit_insn (gen_femms ());
return NULL_RTX;
@@ -12161,28 +13702,138 @@ ix86_expand_builtin (exp, target, subtarget, mode, ignore)
emit_insn (gen_mmx_clrdi (target));
return target;
+ case IX86_BUILTIN_CLRTI:
+ target = gen_reg_rtx (V2DImode);
+ emit_insn (gen_sse2_clrti (simplify_gen_subreg (TImode, target, V2DImode, 0)));
+ return target;
+
+
+ case IX86_BUILTIN_SQRTSD:
+ return ix86_expand_unop1_builtin (CODE_FOR_vmsqrtv2df2, arglist, target);
+ case IX86_BUILTIN_LOADAPD:
+ return ix86_expand_unop_builtin (CODE_FOR_sse2_movapd, arglist, target, 1);
+ case IX86_BUILTIN_LOADUPD:
+ return ix86_expand_unop_builtin (CODE_FOR_sse2_movupd, arglist, target, 1);
+
+ case IX86_BUILTIN_STOREAPD:
+ return ix86_expand_store_builtin (CODE_FOR_sse2_movapd, arglist);
+ case IX86_BUILTIN_STOREUPD:
+ return ix86_expand_store_builtin (CODE_FOR_sse2_movupd, arglist);
+
+ case IX86_BUILTIN_LOADSD:
+ return ix86_expand_unop_builtin (CODE_FOR_sse2_loadsd, arglist, target, 1);
+
+ case IX86_BUILTIN_STORESD:
+ return ix86_expand_store_builtin (CODE_FOR_sse2_storesd, arglist);
+
+ case IX86_BUILTIN_SETPD1:
+ target = assign_386_stack_local (DFmode, 0);
+ arg0 = TREE_VALUE (arglist);
+ emit_move_insn (adjust_address (target, DFmode, 0),
+ expand_expr (arg0, NULL_RTX, VOIDmode, 0));
+ op0 = gen_reg_rtx (V2DFmode);
+ emit_insn (gen_sse2_loadsd (op0, adjust_address (target, V2DFmode, 0)));
+ emit_insn (gen_sse2_shufpd (op0, op0, op0, GEN_INT (0)));
+ return op0;
+
+ case IX86_BUILTIN_SETPD:
+ target = assign_386_stack_local (V2DFmode, 0);
+ arg0 = TREE_VALUE (arglist);
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ emit_move_insn (adjust_address (target, DFmode, 0),
+ expand_expr (arg0, NULL_RTX, VOIDmode, 0));
+ emit_move_insn (adjust_address (target, DFmode, 8),
+ expand_expr (arg1, NULL_RTX, VOIDmode, 0));
+ op0 = gen_reg_rtx (V2DFmode);
+ emit_insn (gen_sse2_movapd (op0, target));
+ return op0;
+
+ case IX86_BUILTIN_LOADRPD:
+ target = ix86_expand_unop_builtin (CODE_FOR_sse2_movapd, arglist,
+ gen_reg_rtx (V2DFmode), 1);
+ emit_insn (gen_sse2_shufpd (target, target, target, GEN_INT (1)));
+ return target;
+
+ case IX86_BUILTIN_LOADPD1:
+ target = ix86_expand_unop_builtin (CODE_FOR_sse2_loadsd, arglist,
+ gen_reg_rtx (V2DFmode), 1);
+ emit_insn (gen_sse2_shufpd (target, target, target, const0_rtx));
+ return target;
+
+ case IX86_BUILTIN_STOREPD1:
+ return ix86_expand_store_builtin (CODE_FOR_sse2_movapd, arglist);
+ case IX86_BUILTIN_STORERPD:
+ return ix86_expand_store_builtin (CODE_FOR_sse2_movapd, arglist);
+
+ case IX86_BUILTIN_CLRPD:
+ target = gen_reg_rtx (V2DFmode);
+ emit_insn (gen_sse_clrv2df (target));
+ return target;
+
+ case IX86_BUILTIN_MFENCE:
+ emit_insn (gen_sse2_mfence ());
+ return 0;
+ case IX86_BUILTIN_LFENCE:
+ emit_insn (gen_sse2_lfence ());
+ return 0;
+
+ case IX86_BUILTIN_CLFLUSH:
+ arg0 = TREE_VALUE (arglist);
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ icode = CODE_FOR_sse2_clflush;
+ if (! (*insn_data[icode].operand[0].predicate) (op0, Pmode))
+ op0 = copy_to_mode_reg (Pmode, op0);
+
+ emit_insn (gen_sse2_clflush (op0));
+ return 0;
+
+ case IX86_BUILTIN_MOVNTPD:
+ return ix86_expand_store_builtin (CODE_FOR_sse2_movntv2df, arglist);
+ case IX86_BUILTIN_MOVNTDQ:
+ return ix86_expand_store_builtin (CODE_FOR_sse2_movntv2di, arglist);
+ case IX86_BUILTIN_MOVNTI:
+ return ix86_expand_store_builtin (CODE_FOR_sse2_movntsi, arglist);
+
+ case IX86_BUILTIN_LOADDQA:
+ return ix86_expand_unop_builtin (CODE_FOR_sse2_movdqa, arglist, target, 1);
+ case IX86_BUILTIN_LOADDQU:
+ return ix86_expand_unop_builtin (CODE_FOR_sse2_movdqu, arglist, target, 1);
+ case IX86_BUILTIN_LOADD:
+ return ix86_expand_unop_builtin (CODE_FOR_sse2_loadd, arglist, target, 1);
+
+ case IX86_BUILTIN_STOREDQA:
+ return ix86_expand_store_builtin (CODE_FOR_sse2_movdqa, arglist);
+ case IX86_BUILTIN_STOREDQU:
+ return ix86_expand_store_builtin (CODE_FOR_sse2_movdqu, arglist);
+ case IX86_BUILTIN_STORED:
+ return ix86_expand_store_builtin (CODE_FOR_sse2_stored, arglist);
+
default:
break;
}
- for (i = 0, d = bdesc_2arg; i < sizeof (bdesc_2arg) / sizeof *d; i++, d++)
+ for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
if (d->code == fcode)
{
/* Compares are treated specially. */
if (d->icode == CODE_FOR_maskcmpv4sf3
|| d->icode == CODE_FOR_vmmaskcmpv4sf3
|| d->icode == CODE_FOR_maskncmpv4sf3
- || d->icode == CODE_FOR_vmmaskncmpv4sf3)
+ || d->icode == CODE_FOR_vmmaskncmpv4sf3
+ || d->icode == CODE_FOR_maskcmpv2df3
+ || d->icode == CODE_FOR_vmmaskcmpv2df3
+ || d->icode == CODE_FOR_maskncmpv2df3
+ || d->icode == CODE_FOR_vmmaskncmpv2df3)
return ix86_expand_sse_compare (d, arglist, target);
return ix86_expand_binop_builtin (d->icode, arglist, target);
}
- for (i = 0, d = bdesc_1arg; i < sizeof (bdesc_1arg) / sizeof *d; i++, d++)
+ for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
if (d->code == fcode)
return ix86_expand_unop_builtin (d->icode, arglist, target, 0);
- for (i = 0, d = bdesc_comi; i < sizeof (bdesc_comi) / sizeof *d; i++, d++)
+ for (i = 0, d = bdesc_comi; i < ARRAY_SIZE (bdesc_comi); i++, d++)
if (d->code == fcode)
return ix86_expand_sse_comi (d, arglist, target);
@@ -12304,6 +13955,8 @@ ix86_preferred_reload_class (x, class)
rtx x;
enum reg_class class;
{
+ if (GET_CODE (x) == CONST_VECTOR && x != CONST0_RTX (GET_MODE (x)))
+ return NO_REGS;
if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
{
/* SSE can't load any constant directly yet. */
@@ -12435,9 +14088,10 @@ ix86_hard_regno_mode_ok (regno, mode)
if (FP_REGNO_P (regno))
return VALID_FP_MODE_P (mode);
if (SSE_REGNO_P (regno))
- return VALID_SSE_REG_MODE (mode);
+ return (TARGET_SSE ? VALID_SSE_REG_MODE (mode) : 0);
if (MMX_REGNO_P (regno))
- return VALID_MMX_REG_MODE (mode) || VALID_MMX_REG_MODE_3DNOW (mode);
+ return (TARGET_MMX
+ ? VALID_MMX_REG_MODE (mode) || VALID_MMX_REG_MODE_3DNOW (mode) : 0);
/* We handle both integer and floats in the general purpose registers.
In future we should be able to handle vector modes as well. */
if (!VALID_INT_MODE_P (mode) && !VALID_FP_MODE_P (mode))
@@ -12538,11 +14192,12 @@ ix86_memory_move_cost (mode, class, in)
if (mode == TFmode)
mode = XFmode;
return ((in ? ix86_cost->int_load[2] : ix86_cost->int_store[2])
- * (int) GET_MODE_SIZE (mode) / 4);
+ * ((int) GET_MODE_SIZE (mode)
+ + UNITS_PER_WORD -1 ) / UNITS_PER_WORD);
}
}
-#ifdef DO_GLOBAL_CTORS_BODY
+#if defined (DO_GLOBAL_CTORS_BODY) && defined (HAS_INIT_SECTION)
static void
ix86_svr3_asm_out_constructor (symbol, priority)
rtx symbol;
@@ -12555,6 +14210,71 @@ ix86_svr3_asm_out_constructor (symbol, priority)
}
#endif
+#if TARGET_MACHO
+
+static int current_machopic_label_num;
+
+/* Given a symbol name and its associated stub, write out the
+ definition of the stub. */
+
+void
+machopic_output_stub (file, symb, stub)
+ FILE *file;
+ const char *symb, *stub;
+{
+ unsigned int length;
+ char *binder_name, *symbol_name, lazy_ptr_name[32];
+ int label = ++current_machopic_label_num;
+
+ /* Lose our funky encoding stuff so it doesn't contaminate the stub. */
+ symb = (*targetm.strip_name_encoding) (symb);
+
+ length = strlen (stub);
+ binder_name = alloca (length + 32);
+ GEN_BINDER_NAME_FOR_STUB (binder_name, stub, length);
+
+ length = strlen (symb);
+ symbol_name = alloca (length + 32);
+ GEN_SYMBOL_NAME_FOR_SYMBOL (symbol_name, symb, length);
+
+ sprintf (lazy_ptr_name, "L%d$lz", label);
+
+ if (MACHOPIC_PURE)
+ machopic_picsymbol_stub_section ();
+ else
+ machopic_symbol_stub_section ();
+
+ fprintf (file, "%s:\n", stub);
+ fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
+
+ if (MACHOPIC_PURE)
+ {
+ fprintf (file, "\tcall LPC$%d\nLPC$%d:\tpopl %%eax\n", label, label);
+ fprintf (file, "\tmovl %s-LPC$%d(%%eax),%%edx\n", lazy_ptr_name, label);
+ fprintf (file, "\tjmp %%edx\n");
+ }
+ else
+ fprintf (file, "\tjmp *%s\n", lazy_ptr_name);
+
+ fprintf (file, "%s:\n", binder_name);
+
+ if (MACHOPIC_PURE)
+ {
+ fprintf (file, "\tlea %s-LPC$%d(%%eax),%%eax\n", lazy_ptr_name, label);
+ fprintf (file, "\tpushl %%eax\n");
+ }
+ else
+ fprintf (file, "\t pushl $%s\n", lazy_ptr_name);
+
+ fprintf (file, "\tjmp dyld_stub_binding_helper\n");
+
+ machopic_lazy_symbol_ptr_section ();
+ fprintf (file, "%s:\n", lazy_ptr_name);
+ fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
+ fprintf (file, "\t.long %s\n", binder_name);
+}
+#endif /* TARGET_MACHO */
+
/* Order the registers for register allocator. */
void
@@ -12578,7 +14298,7 @@ x86_order_regs_for_local_alloc ()
if (!TARGET_SSE_MATH)
for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
reg_alloc_order [pos++] = i;
-
+
/* SSE registers. */
for (i = FIRST_SSE_REG; i <= LAST_SSE_REG; i++)
reg_alloc_order [pos++] = i;
@@ -12599,77 +14319,191 @@ x86_order_regs_for_local_alloc ()
reg_alloc_order [pos++] = 0;
}
-void
-x86_output_mi_thunk (file, delta, function)
- FILE *file;
- int delta;
+/* Returns an expression indicating where the this parameter is
+ located on entry to the FUNCTION. */
+
+static rtx
+x86_this_parameter (function)
tree function;
{
- tree parm;
- rtx xops[3];
+ tree type = TREE_TYPE (function);
+
+ if (TARGET_64BIT)
+ {
+ int n = aggregate_value_p (TREE_TYPE (type)) != 0;
+ return gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
+ }
+
+ if (ix86_fntype_regparm (type) > 0)
+ {
+ tree parm;
+
+ parm = TYPE_ARG_TYPES (type);
+ /* Figure out whether or not the function has a variable number of
+ arguments. */
+ for (; parm; parm = TREE_CHAIN (parm))
+ if (TREE_VALUE (parm) == void_type_node)
+ break;
+ /* If not, the this parameter is in %eax. */
+ if (parm)
+ return gen_rtx_REG (SImode, 0);
+ }
- if (ix86_regparm > 0)
- parm = TYPE_ARG_TYPES (TREE_TYPE (function));
+ if (aggregate_value_p (TREE_TYPE (type)))
+ return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
else
- parm = NULL_TREE;
- for (; parm; parm = TREE_CHAIN (parm))
- if (TREE_VALUE (parm) == void_type_node)
- break;
+ return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4));
+}
- xops[0] = GEN_INT (delta);
+/* Determine whether x86_output_mi_thunk can succeed. */
+
+static bool
+x86_can_output_mi_thunk (thunk, delta, vcall_offset, function)
+ tree thunk ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT delta ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT vcall_offset;
+ tree function;
+{
+ /* 64-bit can handle anything. */
if (TARGET_64BIT)
+ return true;
+
+ /* For 32-bit, everything's fine if we have one free register. */
+ if (ix86_fntype_regparm (TREE_TYPE (function)) < 3)
+ return true;
+
+ /* Need a free register for vcall_offset. */
+ if (vcall_offset)
+ return false;
+
+ /* Need a free register for GOT references. */
+ if (flag_pic && !(*targetm.binds_local_p) (function))
+ return false;
+
+ /* Otherwise ok. */
+ return true;
+}
+
+/* Output the assembler code for a thunk function. THUNK_DECL is the
+ declaration for the thunk function itself, FUNCTION is the decl for
+ the target function. DELTA is an immediate constant offset to be
+ added to THIS. If VCALL_OFFSET is non-zero, the word at
+ *(*this + vcall_offset) should be added to THIS. */
+
+static void
+x86_output_mi_thunk (file, thunk, delta, vcall_offset, function)
+ FILE *file ATTRIBUTE_UNUSED;
+ tree thunk ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT delta;
+ HOST_WIDE_INT vcall_offset;
+ tree function;
+{
+ rtx xops[3];
+ rtx this = x86_this_parameter (function);
+ rtx this_reg, tmp;
+
+ /* If VCALL_OFFSET, we'll need THIS in a register. Might as well
+ pull it in now and let DELTA benefit. */
+ if (REG_P (this))
+ this_reg = this;
+ else if (vcall_offset)
{
- int n = aggregate_value_p (TREE_TYPE (TREE_TYPE (function))) != 0;
- xops[1] = gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
- output_asm_insn ("add{q} {%0, %1|%1, %0}", xops);
- if (flag_pic)
+ /* Put the this parameter into %eax. */
+ xops[0] = this;
+ xops[1] = this_reg = gen_rtx_REG (Pmode, 0);
+ output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
+ }
+ else
+ this_reg = NULL_RTX;
+
+ /* Adjust the this parameter by a fixed constant. */
+ if (delta)
+ {
+ xops[0] = GEN_INT (delta);
+ xops[1] = this_reg ? this_reg : this;
+ if (TARGET_64BIT)
{
- fprintf (file, "\tjmp *");
- assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
- fprintf (file, "@GOTPCREL(%%rip)\n");
+ if (!x86_64_general_operand (xops[0], DImode))
+ {
+ tmp = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 2 /* R10 */);
+ xops[1] = tmp;
+ output_asm_insn ("mov{q}\t{%1, %0|%0, %1}", xops);
+ xops[0] = tmp;
+ xops[1] = this;
+ }
+ output_asm_insn ("add{q}\t{%0, %1|%1, %0}", xops);
}
else
- {
- fprintf (file, "\tjmp ");
- assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
- fprintf (file, "\n");
- }
+ output_asm_insn ("add{l}\t{%0, %1|%1, %0}", xops);
}
- else
+
+ /* Adjust the this parameter by a value stored in the vtable. */
+ if (vcall_offset)
{
- if (parm)
- xops[1] = gen_rtx_REG (SImode, 0);
- else if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
- xops[1] = gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
+ if (TARGET_64BIT)
+ tmp = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 2 /* R10 */);
else
- xops[1] = gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4));
- output_asm_insn ("add{l} {%0, %1|%1, %0}", xops);
+ tmp = gen_rtx_REG (SImode, 2 /* ECX */);
- if (flag_pic)
+ xops[0] = gen_rtx_MEM (Pmode, this_reg);
+ xops[1] = tmp;
+ if (TARGET_64BIT)
+ output_asm_insn ("mov{q}\t{%0, %1|%1, %0}", xops);
+ else
+ output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
+
+ /* Adjust the this parameter. */
+ xops[0] = gen_rtx_MEM (Pmode, plus_constant (tmp, vcall_offset));
+ if (TARGET_64BIT && !memory_operand (xops[0], Pmode))
{
- xops[0] = pic_offset_table_rtx;
- xops[1] = gen_label_rtx ();
- xops[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+ rtx tmp2 = gen_rtx_REG (DImode, FIRST_REX_INT_REG + 3 /* R11 */);
+ xops[0] = GEN_INT (vcall_offset);
+ xops[1] = tmp2;
+ output_asm_insn ("mov{q}\t{%0, %1|%1, %0}", xops);
+ xops[0] = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, tmp, tmp2));
+ }
+ xops[1] = this_reg;
+ if (TARGET_64BIT)
+ output_asm_insn ("add{q}\t{%0, %1|%1, %0}", xops);
+ else
+ output_asm_insn ("add{l}\t{%0, %1|%1, %0}", xops);
+ }
- if (ix86_regparm > 2)
- abort ();
- output_asm_insn ("push{l}\t%0", xops);
- output_asm_insn ("call\t%P1", xops);
- ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (xops[1]));
- output_asm_insn ("pop{l}\t%0", xops);
- output_asm_insn
- ("add{l}\t{%2+[.-%P1], %0|%0, OFFSET FLAT: %2+[.-%P1]}", xops);
- xops[0] = gen_rtx_MEM (SImode, XEXP (DECL_RTL (function), 0));
- output_asm_insn
- ("mov{l}\t{%0@GOT(%%ebx), %%ecx|%%ecx, %0@GOT[%%ebx]}", xops);
- asm_fprintf (file, "\tpop{l\t%%ebx|\t%%ebx}\n");
- asm_fprintf (file, "\tjmp\t{*%%ecx|%%ecx}\n");
+ /* If necessary, drop THIS back to its stack slot. */
+ if (this_reg && this_reg != this)
+ {
+ xops[0] = this_reg;
+ xops[1] = this;
+ output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
+ }
+
+ xops[0] = DECL_RTL (function);
+ if (TARGET_64BIT)
+ {
+ if (!flag_pic || (*targetm.binds_local_p) (function))
+ output_asm_insn ("jmp\t%P0", xops);
+ else
+ {
+ tmp = XEXP (xops[0], 0);
+ tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, tmp), UNSPEC_GOTPCREL);
+ tmp = gen_rtx_CONST (Pmode, tmp);
+ tmp = gen_rtx_MEM (QImode, tmp);
+ xops[0] = tmp;
+ output_asm_insn ("jmp\t%A0", xops);
}
+ }
+ else
+ {
+ if (!flag_pic || (*targetm.binds_local_p) (function))
+ output_asm_insn ("jmp\t%P0", xops);
else
{
- fprintf (file, "\tjmp ");
- assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
- fprintf (file, "\n");
+ tmp = gen_rtx_REG (SImode, 2 /* ECX */);
+ output_set_got (tmp);
+
+ xops[1] = tmp;
+ output_asm_insn ("mov{l}\t{%0@GOT(%1), %1|%1, %0@GOT[%1]}", xops);
+ output_asm_insn ("jmp\t{*}%1", xops);
}
}
}
@@ -12692,3 +14526,88 @@ x86_field_alignment (field, computed)
return MIN (32, computed);
return computed;
}
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+void
+x86_function_profiler (file, labelno)
+ FILE *file;
+ int labelno;
+{
+ if (TARGET_64BIT)
+ if (flag_pic)
+ {
+#ifndef NO_PROFILE_COUNTERS
+ fprintf (file, "\tleaq\t%sP%d@(%%rip),%%r11\n", LPREFIX, labelno);
+#endif
+ fprintf (file, "\tcall\t*%s@GOTPCREL(%%rip)\n", MCOUNT_NAME);
+ }
+ else
+ {
+#ifndef NO_PROFILE_COUNTERS
+ fprintf (file, "\tmovq\t$%sP%d,%%r11\n", LPREFIX, labelno);
+#endif
+ fprintf (file, "\tcall\t%s\n", MCOUNT_NAME);
+ }
+ else if (flag_pic)
+ {
+#ifndef NO_PROFILE_COUNTERS
+ fprintf (file, "\tleal\t%sP%d@GOTOFF(%%ebx),%%%s\n",
+ LPREFIX, labelno, PROFILE_COUNT_REGISTER);
+#endif
+ fprintf (file, "\tcall\t*%s@GOT(%%ebx)\n", MCOUNT_NAME);
+ }
+ else
+ {
+#ifndef NO_PROFILE_COUNTERS
+ fprintf (file, "\tmovl\t$%sP%d,%%%s\n", LPREFIX, labelno,
+ PROFILE_COUNT_REGISTER);
+#endif
+ fprintf (file, "\tcall\t%s\n", MCOUNT_NAME);
+ }
+}
+
+/* Implement machine specific optimizations.
+ At the moment we implement single transformation: AMD Athlon works faster
+ when RET is not destination of conditional jump or directly preceeded
+ by other jump instruction. We avoid the penalty by inserting NOP just
+ before the RET instructions in such cases. */
+void
+x86_machine_dependent_reorg (first)
+ rtx first ATTRIBUTE_UNUSED;
+{
+ edge e;
+
+ if (!TARGET_ATHLON || !optimize || optimize_size)
+ return;
+ for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
+ {
+ basic_block bb = e->src;
+ rtx ret = bb->end;
+ rtx prev;
+ bool insert = false;
+
+ if (!returnjump_p (ret) || !maybe_hot_bb_p (bb))
+ continue;
+ prev = prev_nonnote_insn (ret);
+ if (prev && GET_CODE (prev) == CODE_LABEL)
+ {
+ edge e;
+ for (e = bb->pred; e; e = e->pred_next)
+ if (EDGE_FREQUENCY (e) && e->src->index > 0
+ && !(e->flags & EDGE_FALLTHRU))
+ insert = 1;
+ }
+ if (!insert)
+ {
+ prev = prev_real_insn (ret);
+ if (prev && GET_CODE (prev) == JUMP_INSN
+ && any_condjump_p (prev))
+ insert = 1;
+ }
+ if (insert)
+ emit_insn_before (gen_nop (), ret);
+ }
+}
+
+#include "gt-i386.h"
diff --git a/contrib/gcc/config/i386/i386.h b/contrib/gcc/config/i386/i386.h
index 7ab9063..ead133b 100644
--- a/contrib/gcc/config/i386/i386.h
+++ b/contrib/gcc/config/i386/i386.h
@@ -34,20 +34,6 @@ Boston, MA 02111-1307, USA. */
ADDR_BEG, ADDR_END, PRINT_IREG, PRINT_SCALE, PRINT_B_I_S, and many
that start with ASM_ or end in ASM_OP. */
-/* Stubs for half-pic support if not OSF/1 reference platform. */
-
-#ifndef HALF_PIC_P
-#define HALF_PIC_P() 0
-#define HALF_PIC_NUMBER_PTRS 0
-#define HALF_PIC_NUMBER_REFS 0
-#define HALF_PIC_ENCODE(DECL)
-#define HALF_PIC_DECLARE(NAME)
-#define HALF_PIC_INIT() error ("half-pic init called on systems that don't support it")
-#define HALF_PIC_ADDRESS_P(X) 0
-#define HALF_PIC_PTR(X) (X)
-#define HALF_PIC_FINISH(STREAM)
-#endif
-
/* Define the specific costs for a given cpu */
struct processor_costs {
@@ -89,6 +75,12 @@ struct processor_costs {
const int prefetch_block; /* bytes moved to cache for prefetch. */
const int simultaneous_prefetches; /* number of parallel prefetch
operations. */
+ const int fadd; /* cost of FADD and FSUB instructions. */
+ const int fmul; /* cost of FMUL instruction. */
+ const int fdiv; /* cost of FDIV instruction. */
+ const int fabs; /* cost of FABS instruction. */
+ const int fchs; /* cost of FCHS instruction. */
+ const int fsqrt; /* cost of FSQRT instruction. */
};
extern const struct processor_costs *ix86_cost;
@@ -119,19 +111,16 @@ extern int target_flags;
#define MASK_INLINE_ALL_STROPS 0x00000400 /* Inline stringops in all cases */
#define MASK_NO_PUSH_ARGS 0x00000800 /* Use push instructions */
#define MASK_ACCUMULATE_OUTGOING_ARGS 0x00001000/* Accumulate outgoing args */
-#define MASK_ACCUMULATE_OUTGOING_ARGS_SET 0x00002000
-#define MASK_MMX 0x00004000 /* Support MMX regs/builtins */
-#define MASK_MMX_SET 0x00008000
-#define MASK_SSE 0x00010000 /* Support SSE regs/builtins */
-#define MASK_SSE_SET 0x00020000
-#define MASK_SSE2 0x00040000 /* Support SSE2 regs/builtins */
-#define MASK_SSE2_SET 0x00080000
-#define MASK_3DNOW 0x00100000 /* Support 3Dnow builtins */
-#define MASK_3DNOW_SET 0x00200000
-#define MASK_3DNOW_A 0x00400000 /* Support Athlon 3Dnow builtins */
-#define MASK_3DNOW_A_SET 0x00800000
-#define MASK_128BIT_LONG_DOUBLE 0x01000000 /* long double size is 128bit */
-#define MASK_64BIT 0x02000000 /* Produce 64bit code */
+#define MASK_MMX 0x00002000 /* Support MMX regs/builtins */
+#define MASK_SSE 0x00004000 /* Support SSE regs/builtins */
+#define MASK_SSE2 0x00008000 /* Support SSE2 regs/builtins */
+#define MASK_3DNOW 0x00010000 /* Support 3Dnow builtins */
+#define MASK_3DNOW_A 0x00020000 /* Support Athlon 3Dnow builtins */
+#define MASK_128BIT_LONG_DOUBLE 0x00040000 /* long double size is 128bit */
+#define MASK_64BIT 0x00080000 /* Produce 64bit code */
+
+/* Unused: 0x03f0000 */
+
/* ... overlap with subtarget options starts by 0x04000000. */
#define MASK_NO_RED_ZONE 0x04000000 /* Do not use red zone */
@@ -140,7 +129,7 @@ extern int target_flags;
/* Compile using ret insn that pops args.
This will not work unless you use prototypes at least
- for all functions that can take varying numbers of args. */
+ for all functions that can take varying numbers of args. */
#define TARGET_RTD (target_flags & MASK_RTD)
/* Align doubles to a two word boundary. This breaks compatibility with
@@ -188,16 +177,25 @@ extern int target_flags;
/* Debug FUNCTION_ARG macros */
#define TARGET_DEBUG_ARG (ix86_debug_arg_string != 0)
-/* 64bit Sledgehammer mode */
+/* 64bit Sledgehammer mode. For libgcc2 we make sure this is a
+ compile-time constant. */
+#ifdef IN_LIBGCC2
+#ifdef __x86_64__
+#define TARGET_64BIT 1
+#else
+#define TARGET_64BIT 0
+#endif
+#else
#ifdef TARGET_BI_ARCH
#define TARGET_64BIT (target_flags & MASK_64BIT)
#else
-#ifdef TARGET_64BIT_DEFAULT
+#if TARGET_64BIT_DEFAULT
#define TARGET_64BIT 1
#else
#define TARGET_64BIT 0
#endif
#endif
+#endif
#define TARGET_386 (ix86_cpu == PROCESSOR_I386)
#define TARGET_486 (ix86_cpu == PROCESSOR_I486)
@@ -215,14 +213,14 @@ extern const int x86_double_with_add, x86_partial_reg_stall, x86_movx;
extern const int x86_use_loop, x86_use_fiop, x86_use_mov0;
extern const int x86_use_cltd, x86_read_modify_write;
extern const int x86_read_modify, x86_split_long_moves;
-extern const int x86_promote_QImode, x86_single_stringop;
+extern const int x86_promote_QImode, x86_single_stringop, x86_fast_prefix;
extern const int x86_himode_math, x86_qimode_math, x86_promote_qi_regs;
extern const int x86_promote_hi_regs, x86_integer_DFmode_moves;
extern const int x86_add_esp_4, x86_add_esp_8, x86_sub_esp_4, x86_sub_esp_8;
extern const int x86_partial_reg_dependency, x86_memory_mismatch_stall;
extern const int x86_accumulate_outgoing_args, x86_prologue_using_move;
extern const int x86_epilogue_using_move, x86_decompose_lea;
-extern const int x86_arch_always_fancy_math_387;
+extern const int x86_arch_always_fancy_math_387, x86_shift1;
extern int x86_prefetch_sse;
#define TARGET_USE_LEAVE (x86_use_leave & CPUMASK)
@@ -247,6 +245,7 @@ extern int x86_prefetch_sse;
#define TARGET_READ_MODIFY_WRITE (x86_read_modify_write & CPUMASK)
#define TARGET_READ_MODIFY (x86_read_modify & CPUMASK)
#define TARGET_PROMOTE_QImode (x86_promote_QImode & CPUMASK)
+#define TARGET_FAST_PREFIX (x86_fast_prefix & CPUMASK)
#define TARGET_SINGLE_STRINGOP (x86_single_stringop & CPUMASK)
#define TARGET_QIMODE_MATH (x86_qimode_math & CPUMASK)
#define TARGET_HIMODE_MATH (x86_himode_math & CPUMASK)
@@ -263,6 +262,7 @@ extern int x86_prefetch_sse;
#define TARGET_EPILOGUE_USING_MOVE (x86_epilogue_using_move & CPUMASK)
#define TARGET_DECOMPOSE_LEA (x86_decompose_lea & CPUMASK)
#define TARGET_PREFETCH_SSE (x86_prefetch_sse)
+#define TARGET_SHIFT1 (x86_shift1 & CPUMASK)
#define TARGET_STACK_PROBE (target_flags & MASK_STACK_PROBE)
@@ -282,6 +282,9 @@ extern int x86_prefetch_sse;
#define TARGET_RED_ZONE (!(target_flags & MASK_NO_RED_ZONE))
+#define TARGET_GNU_TLS (ix86_tls_dialect == TLS_DIALECT_GNU)
+#define TARGET_SUN_TLS (ix86_tls_dialect == TLS_DIALECT_SUN)
+
/* WARNING: Do not mark empty strings for translation, as calling
gettext on an empty string does NOT return an empty
string. */
@@ -343,30 +346,25 @@ extern int x86_prefetch_sse;
N_("Use push instructions to save outgoing arguments") }, \
{ "no-push-args", MASK_NO_PUSH_ARGS, \
N_("Do not use push instructions to save outgoing arguments") }, \
- { "accumulate-outgoing-args", (MASK_ACCUMULATE_OUTGOING_ARGS \
- | MASK_ACCUMULATE_OUTGOING_ARGS_SET), \
+ { "accumulate-outgoing-args", MASK_ACCUMULATE_OUTGOING_ARGS, \
N_("Use push instructions to save outgoing arguments") }, \
- { "no-accumulate-outgoing-args",MASK_ACCUMULATE_OUTGOING_ARGS_SET, \
+ { "no-accumulate-outgoing-args",-MASK_ACCUMULATE_OUTGOING_ARGS, \
N_("Do not use push instructions to save outgoing arguments") }, \
- { "mmx", MASK_MMX | MASK_MMX_SET, \
+ { "mmx", MASK_MMX, \
N_("Support MMX built-in functions") }, \
{ "no-mmx", -MASK_MMX, \
N_("Do not support MMX built-in functions") }, \
- { "no-mmx", MASK_MMX_SET, "" }, \
- { "3dnow", MASK_3DNOW | MASK_3DNOW_SET, \
+ { "3dnow", MASK_3DNOW, \
N_("Support 3DNow! built-in functions") }, \
- { "no-3dnow", -MASK_3DNOW, "" }, \
- { "no-3dnow", MASK_3DNOW_SET, \
+ { "no-3dnow", -MASK_3DNOW, \
N_("Do not support 3DNow! built-in functions") }, \
- { "sse", MASK_SSE | MASK_SSE_SET, \
+ { "sse", MASK_SSE, \
N_("Support MMX and SSE built-in functions and code generation") }, \
- { "no-sse", -MASK_SSE, "" }, \
- { "no-sse", MASK_SSE_SET, \
+ { "no-sse", -MASK_SSE, \
N_("Do not support MMX and SSE built-in functions and code generation") },\
- { "sse2", MASK_SSE2 | MASK_SSE2_SET, \
+ { "sse2", MASK_SSE2, \
N_("Support MMX, SSE and SSE2 built-in functions and code generation") }, \
- { "no-sse2", -MASK_SSE2, "" }, \
- { "no-sse2", MASK_SSE2_SET, \
+ { "no-sse2", -MASK_SSE2, \
N_("Do not support MMX, SSE and SSE2 built-in functions and code generation") }, \
{ "128bit-long-double", MASK_128BIT_LONG_DOUBLE, \
N_("sizeof(long double) is 16") }, \
@@ -381,38 +379,21 @@ extern int x86_prefetch_sse;
{ "no-red-zone", MASK_NO_RED_ZONE, \
N_("Do not use red-zone in the x86-64 code") }, \
SUBTARGET_SWITCHES \
- { "", TARGET_DEFAULT, 0 }}
+ { "", TARGET_DEFAULT | TARGET_64BIT_DEFAULT | TARGET_SUBTARGET_DEFAULT, 0 }}
-#ifdef TARGET_64BIT_DEFAULT
-#define TARGET_DEFAULT (MASK_64BIT | TARGET_SUBTARGET_DEFAULT)
-#else
-#define TARGET_DEFAULT TARGET_SUBTARGET_DEFAULT
+#ifndef TARGET_64BIT_DEFAULT
+#define TARGET_64BIT_DEFAULT 0
#endif
-/* 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,
- PROCESSOR_K6,
- PROCESSOR_ATHLON,
- PROCESSOR_PENTIUM4,
- PROCESSOR_max
-};
-enum fpmath_unit
-{
- FPMATH_387 = 1,
- FPMATH_SSE = 2
-};
-
-extern enum processor_type ix86_cpu;
-extern enum fpmath_unit ix86_fpmath;
+/* Once GDB has been enhanced to deal with functions without frame
+ pointers, we can change this to allow for elimination of
+ the frame pointer in leaf functions. */
+#define TARGET_DEFAULT 0
-extern int ix86_arch;
+/* This is not really a target flag, but is done this way so that
+ it's analogous to similar code for Mach-O on PowerPC. darwin.h
+ redefines this to 1. */
+#define TARGET_MACHO 0
/* This macro is similar to `TARGET_SWITCHES' but defines names of
command options that have values. Its definition is an
@@ -451,6 +432,8 @@ extern int ix86_arch;
"" /* Undocumented. */ }, \
{ "asm=", &ix86_asm_string, \
N_("Use given assembler dialect") }, \
+ { "tls-dialect=", &ix86_tls_dialect_string, \
+ N_("Use given thread-local storage dialect") }, \
SUBTARGET_OPTIONS \
}
@@ -492,6 +475,138 @@ extern int ix86_arch;
%n`-mno-intel-syntax' is deprecated. Use `-masm=att' instead.\n}"
#endif
+/* Target CPU builtins. */
+#define TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ size_t arch_len = strlen (ix86_arch_string); \
+ size_t cpu_len = strlen (ix86_cpu_string); \
+ int last_arch_char = ix86_arch_string[arch_len - 1]; \
+ int last_cpu_char = ix86_cpu_string[cpu_len - 1]; \
+ \
+ if (TARGET_64BIT) \
+ { \
+ builtin_assert ("cpu=x86_64"); \
+ builtin_define ("__x86_64"); \
+ builtin_define ("__x86_64__"); \
+ builtin_define ("__amd64"); \
+ builtin_define ("__amd64__"); \
+ } \
+ else \
+ { \
+ builtin_assert ("cpu=i386"); \
+ builtin_assert ("machine=i386"); \
+ builtin_define_std ("i386"); \
+ } \
+ \
+ /* Built-ins based on -mcpu= (or -march= if no \
+ CPU given). */ \
+ if (TARGET_386) \
+ builtin_define ("__tune_i386__"); \
+ else if (TARGET_486) \
+ builtin_define ("__tune_i486__"); \
+ else if (TARGET_PENTIUM) \
+ { \
+ builtin_define ("__tune_i586__"); \
+ builtin_define ("__tune_pentium__"); \
+ if (last_cpu_char == 'x') \
+ builtin_define ("__tune_pentium_mmx__"); \
+ } \
+ else if (TARGET_PENTIUMPRO) \
+ { \
+ builtin_define ("__tune_i686__"); \
+ builtin_define ("__tune_pentiumpro__"); \
+ switch (last_cpu_char) \
+ { \
+ case '3': \
+ builtin_define ("__tune_pentium3__"); \
+ /* FALLTHRU */ \
+ case '2': \
+ builtin_define ("__tune_pentium2__"); \
+ break; \
+ } \
+ } \
+ else if (TARGET_K6) \
+ { \
+ builtin_define ("__tune_k6__"); \
+ if (last_cpu_char == '2') \
+ builtin_define ("__tune_k6_2__"); \
+ else if (last_cpu_char == '3') \
+ builtin_define ("__tune_k6_3__"); \
+ } \
+ else if (TARGET_ATHLON) \
+ { \
+ builtin_define ("__tune_athlon__"); \
+ /* Only plain "athlon" lacks SSE. */ \
+ if (last_cpu_char != 'n') \
+ builtin_define ("__tune_athlon_sse__"); \
+ } \
+ else if (TARGET_PENTIUM4) \
+ builtin_define ("__tune_pentium4__"); \
+ \
+ if (TARGET_MMX) \
+ builtin_define ("__MMX__"); \
+ if (TARGET_3DNOW) \
+ builtin_define ("__3dNOW__"); \
+ if (TARGET_3DNOW_A) \
+ builtin_define ("__3dNOW_A__"); \
+ if (TARGET_SSE) \
+ builtin_define ("__SSE__"); \
+ if (TARGET_SSE2) \
+ builtin_define ("__SSE2__"); \
+ if (TARGET_SSE_MATH && TARGET_SSE) \
+ builtin_define ("__SSE_MATH__"); \
+ if (TARGET_SSE_MATH && TARGET_SSE2) \
+ builtin_define ("__SSE2_MATH__"); \
+ \
+ /* Built-ins based on -march=. */ \
+ if (ix86_arch == PROCESSOR_I486) \
+ { \
+ builtin_define ("__i486"); \
+ builtin_define ("__i486__"); \
+ } \
+ else if (ix86_arch == PROCESSOR_PENTIUM) \
+ { \
+ builtin_define ("__i586"); \
+ builtin_define ("__i586__"); \
+ builtin_define ("__pentium"); \
+ builtin_define ("__pentium__"); \
+ if (last_arch_char == 'x') \
+ builtin_define ("__pentium_mmx__"); \
+ } \
+ else if (ix86_arch == PROCESSOR_PENTIUMPRO) \
+ { \
+ builtin_define ("__i686"); \
+ builtin_define ("__i686__"); \
+ builtin_define ("__pentiumpro"); \
+ builtin_define ("__pentiumpro__"); \
+ } \
+ else if (ix86_arch == PROCESSOR_K6) \
+ { \
+ \
+ builtin_define ("__k6"); \
+ builtin_define ("__k6__"); \
+ if (last_arch_char == '2') \
+ builtin_define ("__k6_2__"); \
+ else if (last_arch_char == '3') \
+ builtin_define ("__k6_3__"); \
+ } \
+ else if (ix86_arch == PROCESSOR_ATHLON) \
+ { \
+ builtin_define ("__athlon"); \
+ builtin_define ("__athlon__"); \
+ /* Only plain "athlon" lacks SSE. */ \
+ if (last_arch_char != 'n') \
+ builtin_define ("__athlon_sse__"); \
+ } \
+ else if (ix86_arch == PROCESSOR_PENTIUM4) \
+ { \
+ builtin_define ("__pentium4"); \
+ builtin_define ("__pentium4__"); \
+ } \
+ } \
+ while (0)
+
#define TARGET_CPU_DEFAULT_i386 0
#define TARGET_CPU_DEFAULT_i486 1
#define TARGET_CPU_DEFAULT_pentium 2
@@ -510,137 +625,6 @@ extern int ix86_arch;
"pentiumpro", "pentium2", "pentium3", \
"pentium4", "k6", "k6-2", "k6-3",\
"athlon", "athlon-4"}
-#ifndef CPP_CPU_DEFAULT_SPEC
-#if TARGET_CPU_DEFAULT == TARGET_CPU_DEFAULT_i486
-#define CPP_CPU_DEFAULT_SPEC "-D__tune_i486__"
-#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_DEFAULT_pentium
-#define CPP_CPU_DEFAULT_SPEC "-D__tune_i586__ -D__tune_pentium__"
-#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_DEFAULT_pentium_mmx
-#define CPP_CPU_DEFAULT_SPEC "-D__tune_i586__ -D__tune_pentium__ -D__tune_pentium_mmx__"
-#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_DEFAULT_pentiumpro
-#define CPP_CPU_DEFAULT_SPEC "-D__tune_i686__ -D__tune_pentiumpro__"
-#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_DEFAULT_pentium2
-#define CPP_CPU_DEFAULT_SPEC "-D__tune_i686__ -D__tune_pentiumpro__ \
--D__tune_pentium2__"
-#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_DEFAULT_pentium3
-#define CPP_CPU_DEFAULT_SPEC "-D__tune_i686__ -D__tune_pentiumpro__ \
--D__tune_pentium2__ -D__tune_pentium3__"
-#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_DEFAULT_pentium4
-#define CPP_CPU_DEFAULT_SPEC "-D__tune_pentium4__"
-#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_DEFAULT_k6
-#define CPP_CPU_DEFAULT_SPEC "-D__tune_k6__"
-#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_DEFAULT_k6_2
-#define CPP_CPU_DEFAULT_SPEC "-D__tune_k6__ -D__tune_k6_2__"
-#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_DEFAULT_k6_3
-#define CPP_CPU_DEFAULT_SPEC "-D__tune_k6__ -D__tune_k6_3__"
-#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_DEFAULT_athlon
-#define CPP_CPU_DEFAULT_SPEC "-D__tune_athlon__"
-#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_DEFAULT_athlon_sse
-#define CPP_CPU_DEFAULT_SPEC "-D__tune_athlon__ -D__tune_athlon_sse__"
-#endif
-#ifndef CPP_CPU_DEFAULT_SPEC
-#define CPP_CPU_DEFAULT_SPEC "-D__tune_i386__"
-#endif
-#endif /* CPP_CPU_DEFAULT_SPEC */
-
-#ifdef TARGET_BI_ARCH
-#define NO_BUILTIN_SIZE_TYPE
-#define NO_BUILTIN_PTRDIFF_TYPE
-#endif
-
-#ifdef NO_BUILTIN_SIZE_TYPE
-#define CPP_CPU32_SIZE_TYPE_SPEC \
- " -D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int"
-#define CPP_CPU64_SIZE_TYPE_SPEC \
- " -D__SIZE_TYPE__=unsigned\\ long\\ int -D__PTRDIFF_TYPE__=long\\ int"
-#else
-#define CPP_CPU32_SIZE_TYPE_SPEC ""
-#define CPP_CPU64_SIZE_TYPE_SPEC ""
-#endif
-
-#define CPP_CPU32_SPEC \
- "-Acpu=i386 -Amachine=i386 %{!ansi:%{!std=c*:%{!std=i*:-Di386}}} -D__i386 \
--D__i386__ %(cpp_cpu32sizet)"
-
-#define CPP_CPU64_SPEC \
- "-Acpu=x86_64 -Amachine=x86_64 -D__x86_64 -D__x86_64__ %(cpp_cpu64sizet)"
-
-#define CPP_CPUCOMMON_SPEC "\
-%{march=i386:%{!mcpu*:-D__tune_i386__ }}\
-%{march=i486:-D__i486 -D__i486__ %{!mcpu*:-D__tune_i486__ }}\
-%{march=pentium|march=i586:-D__i586 -D__i586__ -D__pentium -D__pentium__ \
- %{!mcpu*:-D__tune_i586__ -D__tune_pentium__ }}\
-%{march=pentium-mmx:-D__i586 -D__i586__ -D__pentium -D__pentium__ \
- -D__pentium__mmx__ \
- %{!mcpu*:-D__tune_i586__ -D__tune_pentium__ -D__tune_pentium_mmx__}}\
-%{march=pentiumpro|march=i686|march=pentium2|march=pentium3:-D__i686 -D__i686__ \
- -D__pentiumpro -D__pentiumpro__ \
- %{!mcpu*:-D__tune_i686__ -D__tune_pentiumpro__ }}\
-%{march=march=pentium2|march=pentium3: -D__pentium2 -D__pentium2__\
- %{!mcpu*:-D__tune_pentium2__ }}\
-%{march=pentium3: -D__pentium3 -D__pentium3__\
- %{!mcpu*:-D__tune_pentium3__ }}\
-%{march=k6:-D__k6 -D__k6__ %{!mcpu*:-D__tune_k6__ }}\
-%{march=k6-2:-D__k6 -D__k6__ -D__k6_2__ \
- %{!mcpu*:-D__tune_k6__ -D__tune_k6_2__ }}\
-%{march=k6-3:-D__k6 -D__k6__ -D__k6_3__ \
- %{!mcpu*:-D__tune_k6__ -D__tune_k6_3__ }}\
-%{march=athlon|march=athlon-tbird:-D__athlon -D__athlon__ \
- %{!mcpu*:-D__tune_athlon__ }}\
-%{march=athlon-4|march=athlon-xp|march=athlon-mp:-D__athlon -D__athlon__ \
- -D__athlon_sse__ \
- %{!mcpu*:-D__tune_athlon__ -D__tune_athlon_sse__ }}\
-%{march=pentium4:-D__pentium4 -D__pentium4__ %{!mcpu*:-D__tune_pentium4__ }}\
-%{m386|mcpu=i386:-D__tune_i386__ }\
-%{m486|mcpu=i486:-D__tune_i486__ }\
-%{mpentium|mcpu=pentium|mcpu=i586|mcpu=pentium-mmx:-D__tune_i586__ -D__tune_pentium__ }\
-%{mpentiumpro|mcpu=pentiumpro|mcpu=i686|mcpu=pentium2|mcpu=pentium3:-D__tune_i686__ \
--D__tune_pentiumpro__ }\
-%{mcpu=k6|mcpu=k6-2|mcpu=k6-3:-D__tune_k6__ }\
-%{mcpu=athlon|mcpu=athlon-tbird|mcpu=athlon-4|mcpu=athlon-xp|mcpu=athlon-mp:\
--D__tune_athlon__ }\
-%{mcpu=athlon-4|mcpu=athlon-xp|mcpu=athlon-mp:\
--D__tune_athlon_sse__ }\
-%{mcpu=pentium4:-D__tune_pentium4__ }\
-%{march=athlon-xp|march=athlon-mp|march=pentium3|march=pentium4|msse|msse2:\
--D__SSE__ }\
-%{march=pentium-mmx|march=k6|march=k6-2|march=k6-3\
-|march=athlon|march=athlon-tbird|march=athlon-4|march=athlon-xp\
-|march=athlon-mp|march=pentium2|march=pentium3|march=pentium4|mmx|msse|m3dnow: -D__MMX__ }\
-%{march=k6-2|march=k6-3\
-|march=athlon|march=athlon-tbird|march=athlon-4|march=athlon-xp\
-|march=athlon-mp|m3dnow: -D__3dNOW__ }\
-%{march=athlon|march=athlon-tbird|march=athlon-4|march=athlon-xp\
-|march=athlon-mp: -D__3dNOW_A__ }\
-%{march=pentium4|msse2: -D__SSE2__ }\
-%{!march*:%{!mcpu*:%{!m386:%{!m486:%{!mpentium*:%(cpp_cpu_default)}}}}}"
-
-#ifndef CPP_CPU_SPEC
-#ifdef TARGET_BI_ARCH
-#ifdef TARGET_64BIT_DEFAULT
-#define CPP_CPU_SPEC "%{m32:%(cpp_cpu32)}%{!m32:%(cpp_cpu64)} %(cpp_cpucommon)"
-#else
-#define CPP_CPU_SPEC "%{m64:%(cpp_cpu64)}%{!m64:%(cpp_cpu32)} %(cpp_cpucommon)"
-#endif
-#else
-#ifdef TARGET_64BIT_DEFAULT
-#define CPP_CPU_SPEC "%(cpp_cpu64) %(cpp_cpucommon)"
-#else
-#define CPP_CPU_SPEC "%(cpp_cpu32) %(cpp_cpucommon)"
-#endif
-#endif
-#endif
#ifndef CC1_SPEC
#define CC1_SPEC "%(cc1_cpu) "
@@ -661,24 +645,14 @@ extern int ix86_arch;
#endif
#define EXTRA_SPECS \
- { "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \
- { "cpp_cpu", CPP_CPU_SPEC }, \
- { "cpp_cpu32", CPP_CPU32_SPEC }, \
- { "cpp_cpu64", CPP_CPU64_SPEC }, \
- { "cpp_cpu32sizet", CPP_CPU32_SIZE_TYPE_SPEC }, \
- { "cpp_cpu64sizet", CPP_CPU64_SIZE_TYPE_SPEC }, \
- { "cpp_cpucommon", CPP_CPUCOMMON_SPEC }, \
{ "cc1_cpu", CC1_CPU_SPEC }, \
SUBTARGET_EXTRA_SPECS
/* target machine storage layout */
/* Define for XFmode or TFmode extended real floating point support.
- This will automatically cause REAL_ARITHMETIC to be defined.
-
The XFmode is specified by i386 ABI, while TFmode may be faster
- due to alignment and simplifications in the address calculations.
- */
+ due to alignment and simplifications in the address calculations. */
#define LONG_DOUBLE_TYPE_SIZE (TARGET_128BIT_LONG_DOUBLE ? 128 : 96)
#define MAX_LONG_DOUBLE_TYPE_SIZE 128
#ifdef __x86_64__
@@ -686,10 +660,14 @@ extern int ix86_arch;
#else
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 96
#endif
-/* Tell real.c that this is the 80-bit Intel extended float format
- packaged in a 128-bit or 96bit entity. */
-#define INTEL_EXTENDED_IEEE_FORMAT 1
+/* Set the value of FLT_EVAL_METHOD in float.h. When using only the
+ FPU, assume that the fpcw is set to extended precision; when using
+ only SSE, rounding is correct; when using both SSE and the FPU,
+ the rounding precision is indeterminate, since either may be chosen
+ apparently at random. */
+#define TARGET_FLT_EVAL_METHOD \
+ (TARGET_MIX_SSE_I387 ? -1 : TARGET_SSE_MATH ? 1 : 2)
#define SHORT_TYPE_SIZE 16
#define INT_TYPE_SIZE 32
@@ -699,7 +677,7 @@ extern int ix86_arch;
#define DOUBLE_TYPE_SIZE 64
#define LONG_LONG_TYPE_SIZE 64
-#if defined (TARGET_BI_ARCH) || defined (TARGET_64BIT_DEFAULT)
+#if defined (TARGET_BI_ARCH) || TARGET_64BIT_DEFAULT
#define MAX_BITS_PER_WORD 64
#define MAX_LONG_TYPE_SIZE 64
#else
@@ -707,11 +685,6 @@ extern int ix86_arch;
#define MAX_LONG_TYPE_SIZE 32
#endif
-/* Define if you don't want extended real, but do want to use the
- software floating point emulator for REAL_ARITHMETIC and
- decimal <-> binary conversion. */
-/* #define REAL_ARITHMETIC */
-
/* Define this if most significant byte of a word is the lowest numbered. */
/* That is true on the 80386. */
@@ -726,22 +699,13 @@ extern int ix86_arch;
/* Not true for 80386 */
#define WORDS_BIG_ENDIAN 0
-/* number of bits in an addressable storage unit */
-#define BITS_PER_UNIT 8
-
-/* Width in bits of a "word", which is the contents of a machine register.
- Note that this is not necessarily the width of data type `int';
- if using 16-bit ints on a 80386, this would still be 32.
- But on a machine with 16-bit registers, this would be 16. */
-#define BITS_PER_WORD (TARGET_64BIT ? 64 : 32)
-
/* Width of a word, in units (bytes). */
#define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4)
-#define MIN_UNITS_PER_WORD 4
-
-/* Width in bits of a pointer.
- See also the macro `Pmode' defined below. */
-#define POINTER_SIZE BITS_PER_WORD
+#ifdef IN_LIBGCC2
+#define MIN_UNITS_PER_WORD (TARGET_64BIT ? 8 : 4)
+#else
+#define MIN_UNITS_PER_WORD 4
+#endif
/* Allocation boundary (in *bits*) for storing arguments in argument list. */
#define PARM_BOUNDARY BITS_PER_WORD
@@ -774,16 +738,15 @@ extern int ix86_arch;
and all fundamental data types supported by the hardware
might need to be aligned. No data type wants to be aligned
rounder than this.
-
+
Pentium+ preferrs DFmode values to be aligned to 64 bit boundary
and Pentium Pro XFmode values at 128 bit boundaries. */
#define BIGGEST_ALIGNMENT 128
-/* Decide whether a variable of mode MODE must be 128 bit aligned. */
+/* Decide whether a variable of mode MODE should be 128 bit aligned. */
#define ALIGN_MODE_128(MODE) \
- ((MODE) == XFmode || (MODE) == TFmode || ((MODE) == TImode) \
- || (MODE) == V4SFmode || (MODE) == V4SImode)
+ ((MODE) == XFmode || (MODE) == TFmode || SSE_REG_MODE_P (MODE))
/* The published ABIs say that doubles should be aligned on word
boundaries, so lower the aligment for structure fields unless
@@ -793,7 +756,11 @@ extern int ix86_arch;
supports no vector modes, cut out the complexity and fall back
on BIGGEST_FIELD_ALIGNMENT. */
#ifdef IN_TARGET_LIBS
+#ifdef __x86_64__
+#define BIGGEST_FIELD_ALIGNMENT 128
+#else
#define BIGGEST_FIELD_ALIGNMENT 32
+#endif
#else
#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
x86_field_alignment (FIELD, COMPUTED)
@@ -846,13 +813,13 @@ extern int ix86_arch;
#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
ix86_function_arg_boundary ((MODE), (TYPE))
-/* Set this non-zero if move instructions will actually fail to work
+/* Set this nonzero if move instructions will actually fail to work
when given unaligned data. */
#define STRICT_ALIGNMENT 0
/* If bit field type is int, don't let it cross an int,
and give entire struct the alignment of an int. */
-/* Required on the 386 since it doesn't have bitfield insns. */
+/* Required on the 386 since it doesn't have bit-field insns. */
#define PCC_BITFIELD_TYPE_MATTERS 1
/* Standard register usage. */
@@ -891,7 +858,7 @@ extern int ix86_arch;
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
On the 80386, the stack pointer is such, as is the arg pointer.
-
+
The value is an mask - bit 1 is set for fixed registers
for 32bit target, while 2 is set for fixed registers for 64bit.
Proper value is computed in the CONDITIONAL_REGISTER_USAGE.
@@ -909,15 +876,15 @@ extern int ix86_arch;
1, 1, 1, 1, 1, 1, 1, 1, \
/*xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15*/ \
1, 1, 1, 1, 1, 1, 1, 1}
-
+
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
registers that can be used without being saved.
The latter must include the registers where values are returned
and the register where structure-value addresses are passed.
- Aside from that, you can include as many other registers as you like.
-
+ Aside from that, you can include as many other registers as you like.
+
The value is an mask - bit 1 is set for call used
for 32bit target, while 2 is set for call used for 64bit.
Proper value is computed in the CONDITIONAL_REGISTER_USAGE.
@@ -1003,7 +970,7 @@ do { \
This is ordinarily the length in words of a value of mode MODE
but can be less for certain modes in special long registers.
- Actually there are no two word move instructions for consecutive
+ Actually there are no two word move instructions for consecutive
registers. And only registers 0-3 may have mov byte instructions
applied to them.
*/
@@ -1017,9 +984,15 @@ do { \
? (TARGET_64BIT ? 4 : 6) \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)))
+#define VALID_SSE2_REG_MODE(MODE) \
+ ((MODE) == V16QImode || (MODE) == V8HImode || (MODE) == V2DFmode \
+ || (MODE) == V2DImode)
+
#define VALID_SSE_REG_MODE(MODE) \
((MODE) == TImode || (MODE) == V4SFmode || (MODE) == V4SImode \
|| (MODE) == SFmode \
+ /* Always accept SSE2 modes so that xmmintrin.h compiles. */ \
+ || VALID_SSE2_REG_MODE (MODE) \
|| (TARGET_SSE2 && ((MODE) == DFmode || VALID_MMX_REG_MODE (MODE))))
#define VALID_MMX_REG_MODE_3DNOW(MODE) \
@@ -1047,6 +1020,17 @@ do { \
|| (MODE) == CDImode \
|| (TARGET_64BIT && ((MODE) == TImode || (MODE) == CTImode)))
+/* Return true for modes passed in SSE registers. */
+#define SSE_REG_MODE_P(MODE) \
+ ((MODE) == TImode || (MODE) == V16QImode \
+ || (MODE) == V8HImode || (MODE) == V2DFmode || (MODE) == V2DImode \
+ || (MODE) == V4SFmode || (MODE) == V4SImode)
+
+/* Return true for modes passed in MMX registers. */
+#define MMX_REG_MODE_P(MODE) \
+ ((MODE) == V8QImode || (MODE) == V4HImode || (MODE) == V2SImode \
+ || (MODE) == V2SFmode)
+
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
@@ -1064,7 +1048,7 @@ do { \
&& (TARGET_64BIT || !TARGET_PARTIAL_REG_STALL)) \
|| ((MODE1) == DImode && TARGET_64BIT)) \
&& ((MODE2) == HImode || (MODE2) == SImode \
- || ((MODE1) == QImode \
+ || ((MODE2) == QImode \
&& (TARGET_64BIT || !TARGET_PARTIAL_REG_STALL)) \
|| ((MODE2) == DImode && TARGET_64BIT))))
@@ -1110,7 +1094,7 @@ do { \
#define FIRST_SSE_REG (FRAME_POINTER_REGNUM + 1)
#define LAST_SSE_REG (FIRST_SSE_REG + 7)
-
+
#define FIRST_MMX_REG (LAST_SSE_REG + 1)
#define LAST_MMX_REG (FIRST_MMX_REG + 7)
@@ -1146,9 +1130,20 @@ do { \
/* Register to hold the addressing base for position independent
code access to data items. We don't use PIC pointer for 64bit
mode. Define the regnum to dummy value to prevent gcc from
- pessimizing code dealing with EBX. */
-#define PIC_OFFSET_TABLE_REGNUM \
- (TARGET_64BIT || !flag_pic ? INVALID_REGNUM : 3)
+ pessimizing code dealing with EBX.
+
+ To avoid clobbering a call-saved register unnecessarily, we renumber
+ the pic register when possible. The change is visible after the
+ prologue has been emitted. */
+
+#define REAL_PIC_OFFSET_TABLE_REGNUM 3
+
+#define PIC_OFFSET_TABLE_REGNUM \
+ (TARGET_64BIT || !flag_pic ? INVALID_REGNUM \
+ : reload_completed ? REGNO (pic_offset_table_rtx) \
+ : REAL_PIC_OFFSET_TABLE_REGNUM)
+
+#define GOT_SYMBOL_NAME "_GLOBAL_OFFSET_TABLE_"
/* Register in which address to store a structure value
arrives in the function. On the 386, the prologue
@@ -1350,7 +1345,7 @@ enum reg_class
#define MMX_REGNO_P(N) ((N) >= FIRST_MMX_REG && (N) <= LAST_MMX_REG)
#define MMX_REG_P(XOP) (REG_P (XOP) && MMX_REGNO_P (REGNO (XOP)))
-
+
#define STACK_REG_P(XOP) \
(REG_P (XOP) && \
REGNO (XOP) >= FIRST_STACK_REG && \
@@ -1430,7 +1425,7 @@ enum reg_class
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
((C) == 'G' ? standard_80387_constant_p (VALUE) \
- : ((C) == 'H' ? standard_sse_constant_p (VALUE) : 0))
+ : 0)
/* A C expression that defines the optional machine-dependent
constraint letters that can be used to segregate specific types of
@@ -1444,9 +1439,10 @@ enum reg_class
the constraint letter C. If C is not defined as an extra
constraint, the value returned should be 0 regardless of VALUE. */
-#define EXTRA_CONSTRAINT(VALUE, C) \
- ((C) == 'e' ? x86_64_sign_extended_value (VALUE) \
- : (C) == 'Z' ? x86_64_zero_extended_value (VALUE) \
+#define EXTRA_CONSTRAINT(VALUE, D) \
+ ((D) == 'e' ? x86_64_sign_extended_value (VALUE) \
+ : (D) == 'Z' ? x86_64_zero_extended_value (VALUE) \
+ : (D) == 'C' ? standard_sse_constant_p (VALUE) \
: 0)
/* Place additional restrictions on the register class to use when it
@@ -1481,7 +1477,7 @@ enum reg_class
ix86_secondary_memory_needed ((CLASS1), (CLASS2), (MODE), 1)
/* QImode spills from non-QI registers need a scratch. This does not
- happen often -- the only example so far requires an uninitialized
+ happen often -- the only example so far requires an uninitialized
pseudo. */
#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, OUT) \
@@ -1527,8 +1523,22 @@ enum reg_class
|| ((CLASS) == SIREG) \
|| ((CLASS) == DIREG))
+/* Return a class of registers that cannot change FROM mode to TO mode.
+
+ x87 registers can't do subreg as all values are reformated to extended
+ precision. XMM registers does not support with nonzero offsets equal
+ to 4, 8 and 12 otherwise valid for integer registers. Since we can't
+ determine these, prohibit all nonparadoxical subregs changing size. */
+
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_SIZE (TO) < GET_MODE_SIZE (FROM) \
+ ? reg_classes_intersect_p (FLOAT_SSE_REGS, (CLASS)) \
+ || MAYBE_MMX_CLASS_P (CLASS) \
+ : GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? reg_classes_intersect_p (FLOAT_REGS, (CLASS)) : 0)
+
/* A C statement that adds to CLOBBERS any hard regs the port wishes
- to automatically clobber for all asms.
+ to automatically clobber for all asms.
We do this in the new i386 backend to maintain source compatibility
with the old cc0-based compiler. */
@@ -1566,7 +1576,7 @@ enum reg_class
On 386 pushw decrements by exactly 2 no matter what the position was.
On the 386 there is no pushb; we use pushw instead, and this
has the effect of rounding up to 2.
-
+
For 64bit ABI we round up to 8 bytes.
*/
@@ -1721,17 +1731,28 @@ typedef struct ix86_args {
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
+/* 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) \
+ function_arg_pass_by_reference(&CUM, MODE, TYPE, NAMED)
+
/* If PIC, we cannot make sibling calls to global functions
because the PLT requires %ebx live.
- If we are returning floats on the register stack, we cannot make
- sibling calls to functions that return floats. (The stack adjust
- instruction will wind up after the sibcall jump, and not be executed.) */
+ If we are returning floats on the 80387 register stack, we cannot
+ make a sibcall from a function that doesn't return a float to a
+ function that does or, conversely, from a function that does return
+ a float to a function that doesn't; the necessary stack adjustment
+ would not be executed. */
#define FUNCTION_OK_FOR_SIBCALL(DECL) \
((DECL) \
&& (! flag_pic || ! TREE_PUBLIC (DECL)) \
&& (! TARGET_FLOAT_RETURNS_IN_80387 \
- || ! FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (TREE_TYPE (DECL)))) \
- || FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (TREE_TYPE (cfun->decl))))))
+ || (FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (TREE_TYPE (DECL)))) \
+ == FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (TREE_TYPE (cfun->decl)))))))
/* Perform any needed actions needed for a function that is receiving a
variable number of arguments.
@@ -1756,8 +1777,8 @@ typedef struct ix86_args {
((VALIST) = ix86_build_va_list ())
/* Implement `va_start' for varargs and stdarg. */
-#define EXPAND_BUILTIN_VA_START(STDARG, VALIST, NEXTARG) \
- ix86_va_start ((STDARG), (VALIST), (NEXTARG))
+#define EXPAND_BUILTIN_VA_START(VALIST, NEXTARG) \
+ ix86_va_start (VALIST, NEXTARG)
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(VALIST, TYPE) \
@@ -1772,26 +1793,17 @@ typedef struct ix86_args {
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
-#define FUNCTION_PROFILER(FILE, LABELNO) \
-do { \
- if (flag_pic) \
- { \
- fprintf ((FILE), "\tleal\t%sP%d@GOTOFF(%%ebx),%%edx\n", \
- LPREFIX, (LABELNO)); \
- fprintf ((FILE), "\tcall\t*_mcount@GOT(%%ebx)\n"); \
- } \
- else \
- { \
- fprintf ((FILE), "\tmovl\t$%sP%d,%%edx\n", LPREFIX, (LABELNO)); \
- fprintf ((FILE), "\tcall\t_mcount\n"); \
- } \
-} while (0)
+#define FUNCTION_PROFILER(FILE, LABELNO) x86_function_profiler (FILE, LABELNO)
+
+#define MCOUNT_NAME "_mcount"
+
+#define PROFILE_COUNT_REGISTER "edx"
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
the stack pointer does not matter. The value is tested only in
functions that have frame pointers.
No definition is equivalent to always zero. */
-/* Note on the 386 it might be more efficient not to define this since
+/* Note on the 386 it might be more efficient not to define this since
we have to restore it ourselves from the frame pointer, in order to
use pop */
@@ -1945,15 +1957,12 @@ do { \
#define MAX_REGS_PER_ADDRESS 2
-#define CONSTANT_ADDRESS_P(X) \
- (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \
- || GET_CODE (X) == CONST_DOUBLE)
+#define CONSTANT_ADDRESS_P(X) constant_address_p (X)
/* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
-#define LEGITIMATE_CONSTANT_P(X) 1
+#define LEGITIMATE_CONSTANT_P(X) legitimate_constant_p (X)
#ifdef REG_OK_STRICT
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
@@ -2013,12 +2022,10 @@ do { \
#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
+ when generating PIC code. It is given that flag_pic is on and
that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
-#define LEGITIMATE_PIC_OPERAND_P(X) \
- (! SYMBOLIC_CONST (X) \
- || legitimate_pic_address_disp_p (X))
+#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)
#define SYMBOLIC_CONST(X) \
(GET_CODE (X) == SYMBOL_REF \
@@ -2087,9 +2094,12 @@ enum ix86_builtins
IX86_BUILTIN_CVTPI2PS,
IX86_BUILTIN_CVTPS2PI,
IX86_BUILTIN_CVTSI2SS,
+ IX86_BUILTIN_CVTSI642SS,
IX86_BUILTIN_CVTSS2SI,
+ IX86_BUILTIN_CVTSS2SI64,
IX86_BUILTIN_CVTTPS2PI,
IX86_BUILTIN_CVTTSS2SI,
+ IX86_BUILTIN_CVTTSS2SI64,
IX86_BUILTIN_MAXPS,
IX86_BUILTIN_MAXSS,
@@ -2118,6 +2128,16 @@ enum ix86_builtins
IX86_BUILTIN_MOVNTPS,
IX86_BUILTIN_MOVNTQ,
+ IX86_BUILTIN_LOADDQA,
+ IX86_BUILTIN_LOADDQU,
+ IX86_BUILTIN_STOREDQA,
+ IX86_BUILTIN_STOREDQU,
+ IX86_BUILTIN_MOVQ,
+ IX86_BUILTIN_LOADD,
+ IX86_BUILTIN_STORED,
+
+ IX86_BUILTIN_CLRTI,
+
IX86_BUILTIN_PACKSSWB,
IX86_BUILTIN_PACKSSDW,
IX86_BUILTIN_PACKUSWB,
@@ -2125,6 +2145,7 @@ enum ix86_builtins
IX86_BUILTIN_PADDB,
IX86_BUILTIN_PADDW,
IX86_BUILTIN_PADDD,
+ IX86_BUILTIN_PADDQ,
IX86_BUILTIN_PADDSB,
IX86_BUILTIN_PADDSW,
IX86_BUILTIN_PADDUSB,
@@ -2132,6 +2153,7 @@ enum ix86_builtins
IX86_BUILTIN_PSUBB,
IX86_BUILTIN_PSUBW,
IX86_BUILTIN_PSUBD,
+ IX86_BUILTIN_PSUBQ,
IX86_BUILTIN_PSUBSB,
IX86_BUILTIN_PSUBSW,
IX86_BUILTIN_PSUBUSB,
@@ -2201,7 +2223,7 @@ enum ix86_builtins
IX86_BUILTIN_RSQRTSS,
IX86_BUILTIN_SQRTPS,
IX86_BUILTIN_SQRTSS,
-
+
IX86_BUILTIN_UNPCKHPS,
IX86_BUILTIN_UNPCKLPS,
@@ -2248,50 +2270,233 @@ enum ix86_builtins
IX86_BUILTIN_SSE_ZERO,
IX86_BUILTIN_MMX_ZERO,
+ /* SSE2 */
+ IX86_BUILTIN_ADDPD,
+ IX86_BUILTIN_ADDSD,
+ IX86_BUILTIN_DIVPD,
+ IX86_BUILTIN_DIVSD,
+ IX86_BUILTIN_MULPD,
+ IX86_BUILTIN_MULSD,
+ IX86_BUILTIN_SUBPD,
+ IX86_BUILTIN_SUBSD,
+
+ IX86_BUILTIN_CMPEQPD,
+ IX86_BUILTIN_CMPLTPD,
+ IX86_BUILTIN_CMPLEPD,
+ IX86_BUILTIN_CMPGTPD,
+ IX86_BUILTIN_CMPGEPD,
+ IX86_BUILTIN_CMPNEQPD,
+ IX86_BUILTIN_CMPNLTPD,
+ IX86_BUILTIN_CMPNLEPD,
+ IX86_BUILTIN_CMPNGTPD,
+ IX86_BUILTIN_CMPNGEPD,
+ IX86_BUILTIN_CMPORDPD,
+ IX86_BUILTIN_CMPUNORDPD,
+ IX86_BUILTIN_CMPNEPD,
+ IX86_BUILTIN_CMPEQSD,
+ IX86_BUILTIN_CMPLTSD,
+ IX86_BUILTIN_CMPLESD,
+ IX86_BUILTIN_CMPNEQSD,
+ IX86_BUILTIN_CMPNLTSD,
+ IX86_BUILTIN_CMPNLESD,
+ IX86_BUILTIN_CMPORDSD,
+ IX86_BUILTIN_CMPUNORDSD,
+ IX86_BUILTIN_CMPNESD,
+
+ IX86_BUILTIN_COMIEQSD,
+ IX86_BUILTIN_COMILTSD,
+ IX86_BUILTIN_COMILESD,
+ IX86_BUILTIN_COMIGTSD,
+ IX86_BUILTIN_COMIGESD,
+ IX86_BUILTIN_COMINEQSD,
+ IX86_BUILTIN_UCOMIEQSD,
+ IX86_BUILTIN_UCOMILTSD,
+ IX86_BUILTIN_UCOMILESD,
+ IX86_BUILTIN_UCOMIGTSD,
+ IX86_BUILTIN_UCOMIGESD,
+ IX86_BUILTIN_UCOMINEQSD,
+
+ IX86_BUILTIN_MAXPD,
+ IX86_BUILTIN_MAXSD,
+ IX86_BUILTIN_MINPD,
+ IX86_BUILTIN_MINSD,
+
+ IX86_BUILTIN_ANDPD,
+ IX86_BUILTIN_ANDNPD,
+ IX86_BUILTIN_ORPD,
+ IX86_BUILTIN_XORPD,
+
+ IX86_BUILTIN_SQRTPD,
+ IX86_BUILTIN_SQRTSD,
+
+ IX86_BUILTIN_UNPCKHPD,
+ IX86_BUILTIN_UNPCKLPD,
+
+ IX86_BUILTIN_SHUFPD,
+
+ IX86_BUILTIN_LOADAPD,
+ IX86_BUILTIN_LOADUPD,
+ IX86_BUILTIN_STOREAPD,
+ IX86_BUILTIN_STOREUPD,
+ IX86_BUILTIN_LOADSD,
+ IX86_BUILTIN_STORESD,
+ IX86_BUILTIN_MOVSD,
+
+ IX86_BUILTIN_LOADHPD,
+ IX86_BUILTIN_LOADLPD,
+ IX86_BUILTIN_STOREHPD,
+ IX86_BUILTIN_STORELPD,
+
+ IX86_BUILTIN_CVTDQ2PD,
+ IX86_BUILTIN_CVTDQ2PS,
+
+ IX86_BUILTIN_CVTPD2DQ,
+ IX86_BUILTIN_CVTPD2PI,
+ IX86_BUILTIN_CVTPD2PS,
+ IX86_BUILTIN_CVTTPD2DQ,
+ IX86_BUILTIN_CVTTPD2PI,
+
+ IX86_BUILTIN_CVTPI2PD,
+ IX86_BUILTIN_CVTSI2SD,
+ IX86_BUILTIN_CVTSI642SD,
+
+ IX86_BUILTIN_CVTSD2SI,
+ IX86_BUILTIN_CVTSD2SI64,
+ IX86_BUILTIN_CVTSD2SS,
+ IX86_BUILTIN_CVTSS2SD,
+ IX86_BUILTIN_CVTTSD2SI,
+ IX86_BUILTIN_CVTTSD2SI64,
+
+ IX86_BUILTIN_CVTPS2DQ,
+ IX86_BUILTIN_CVTPS2PD,
+ IX86_BUILTIN_CVTTPS2DQ,
+
+ IX86_BUILTIN_MOVNTI,
+ IX86_BUILTIN_MOVNTPD,
+ IX86_BUILTIN_MOVNTDQ,
+
+ IX86_BUILTIN_SETPD1,
+ IX86_BUILTIN_SETPD,
+ IX86_BUILTIN_CLRPD,
+ IX86_BUILTIN_SETRPD,
+ IX86_BUILTIN_LOADPD1,
+ IX86_BUILTIN_LOADRPD,
+ IX86_BUILTIN_STOREPD1,
+ IX86_BUILTIN_STORERPD,
+
+ /* SSE2 MMX */
+ IX86_BUILTIN_MASKMOVDQU,
+ IX86_BUILTIN_MOVMSKPD,
+ IX86_BUILTIN_PMOVMSKB128,
+ IX86_BUILTIN_MOVQ2DQ,
+ IX86_BUILTIN_MOVDQ2Q,
+
+ IX86_BUILTIN_PACKSSWB128,
+ IX86_BUILTIN_PACKSSDW128,
+ IX86_BUILTIN_PACKUSWB128,
+
+ IX86_BUILTIN_PADDB128,
+ IX86_BUILTIN_PADDW128,
+ IX86_BUILTIN_PADDD128,
+ IX86_BUILTIN_PADDQ128,
+ IX86_BUILTIN_PADDSB128,
+ IX86_BUILTIN_PADDSW128,
+ IX86_BUILTIN_PADDUSB128,
+ IX86_BUILTIN_PADDUSW128,
+ IX86_BUILTIN_PSUBB128,
+ IX86_BUILTIN_PSUBW128,
+ IX86_BUILTIN_PSUBD128,
+ IX86_BUILTIN_PSUBQ128,
+ IX86_BUILTIN_PSUBSB128,
+ IX86_BUILTIN_PSUBSW128,
+ IX86_BUILTIN_PSUBUSB128,
+ IX86_BUILTIN_PSUBUSW128,
+
+ IX86_BUILTIN_PAND128,
+ IX86_BUILTIN_PANDN128,
+ IX86_BUILTIN_POR128,
+ IX86_BUILTIN_PXOR128,
+
+ IX86_BUILTIN_PAVGB128,
+ IX86_BUILTIN_PAVGW128,
+
+ IX86_BUILTIN_PCMPEQB128,
+ IX86_BUILTIN_PCMPEQW128,
+ IX86_BUILTIN_PCMPEQD128,
+ IX86_BUILTIN_PCMPGTB128,
+ IX86_BUILTIN_PCMPGTW128,
+ IX86_BUILTIN_PCMPGTD128,
+
+ IX86_BUILTIN_PEXTRW128,
+ IX86_BUILTIN_PINSRW128,
+
+ IX86_BUILTIN_PMADDWD128,
+
+ IX86_BUILTIN_PMAXSW128,
+ IX86_BUILTIN_PMAXUB128,
+ IX86_BUILTIN_PMINSW128,
+ IX86_BUILTIN_PMINUB128,
+
+ IX86_BUILTIN_PMULUDQ,
+ IX86_BUILTIN_PMULUDQ128,
+ IX86_BUILTIN_PMULHUW128,
+ IX86_BUILTIN_PMULHW128,
+ IX86_BUILTIN_PMULLW128,
+
+ IX86_BUILTIN_PSADBW128,
+ IX86_BUILTIN_PSHUFHW,
+ IX86_BUILTIN_PSHUFLW,
+ IX86_BUILTIN_PSHUFD,
+
+ IX86_BUILTIN_PSLLW128,
+ IX86_BUILTIN_PSLLD128,
+ IX86_BUILTIN_PSLLQ128,
+ IX86_BUILTIN_PSRAW128,
+ IX86_BUILTIN_PSRAD128,
+ IX86_BUILTIN_PSRLW128,
+ IX86_BUILTIN_PSRLD128,
+ IX86_BUILTIN_PSRLQ128,
+ IX86_BUILTIN_PSLLDQI128,
+ IX86_BUILTIN_PSLLWI128,
+ IX86_BUILTIN_PSLLDI128,
+ IX86_BUILTIN_PSLLQI128,
+ IX86_BUILTIN_PSRAWI128,
+ IX86_BUILTIN_PSRADI128,
+ IX86_BUILTIN_PSRLDQI128,
+ IX86_BUILTIN_PSRLWI128,
+ IX86_BUILTIN_PSRLDI128,
+ IX86_BUILTIN_PSRLQI128,
+
+ IX86_BUILTIN_PUNPCKHBW128,
+ IX86_BUILTIN_PUNPCKHWD128,
+ IX86_BUILTIN_PUNPCKHDQ128,
+ IX86_BUILTIN_PUNPCKHQDQ128,
+ IX86_BUILTIN_PUNPCKLBW128,
+ IX86_BUILTIN_PUNPCKLWD128,
+ IX86_BUILTIN_PUNPCKLDQ128,
+ IX86_BUILTIN_PUNPCKLQDQ128,
+
+ IX86_BUILTIN_CLFLUSH,
+ IX86_BUILTIN_MFENCE,
+ IX86_BUILTIN_LFENCE,
+
IX86_BUILTIN_MAX
};
-/* Define this macro if references to a symbol must be treated
- differently depending on something about the variable or
- function named by the symbol (such as what section it is in).
-
- On i386, if using PIC, mark a SYMBOL_REF for a non-global symbol
- so that we may access it directly in the GOT. */
-
-#define ENCODE_SECTION_INFO(DECL) \
-do { \
- if (flag_pic) \
- { \
- rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
- ? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \
- \
- if (GET_CODE (rtl) == MEM) \
- { \
- if (TARGET_DEBUG_ADDR \
- && TREE_CODE_CLASS (TREE_CODE (DECL)) == 'd') \
- { \
- fprintf (stderr, "Encode %s, public = %d\n", \
- IDENTIFIER_POINTER (DECL_NAME (DECL)), \
- TREE_PUBLIC (DECL)); \
- } \
- \
- SYMBOL_REF_FLAG (XEXP (rtl, 0)) \
- = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
- || ! TREE_PUBLIC (DECL)); \
- } \
- } \
-} while (0)
-
-/* 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 \
- (current_function_uses_pic_offset_table |= current_function_profile)
-
+#define TARGET_ENCODE_SECTION_INFO ix86_encode_section_info
+#define TARGET_STRIP_NAME_ENCODING ix86_strip_name_encoding
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ do { \
+ const char *xname = (NAME); \
+ if (xname[0] == '%') \
+ xname += 2; \
+ if (xname[0] == '*') \
+ xname += 1; \
+ else \
+ fputs (user_label_prefix, FILE); \
+ fputs (xname, FILE); \
+ } while (0)
/* Max number of args passed in registers. If this is more than 3, we will
have problems with ebx (register #4), since it is a caller save register and
@@ -2359,7 +2564,7 @@ do { \
/* When a prototype says `char' or `short', really pass an `int'.
(The 386 can't easily push less than an int.) */
-#define PROMOTE_PROTOTYPES (!TARGET_64BIT)
+#define PROMOTE_PROTOTYPES 1
/* A macro to update M and UNSIGNEDP when an object whose type is
TYPE and which has the specified mode and signedness is to be
@@ -2395,7 +2600,7 @@ do { \
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)'. */
@@ -2411,16 +2616,21 @@ do { \
return flag_pic && SYMBOLIC_CONST (RTX) ? 1 : 0; \
\
case CONST_DOUBLE: \
- { \
- int code; \
- if (GET_MODE (RTX) == VOIDmode) \
- return 0; \
- \
- code = standard_80387_constant_p (RTX); \
- return code == 1 ? 1 : \
- code == 2 ? 2 : \
- 3; \
- }
+ if (GET_MODE (RTX) == VOIDmode) \
+ return 0; \
+ switch (standard_80387_constant_p (RTX)) \
+ { \
+ case 1: /* 0.0 */ \
+ return 1; \
+ case 2: /* 1.0 */ \
+ return 2; \
+ default: \
+ /* Start with (MEM (SYMBOL_REF)), since that's where \
+ it'll probably end up. Add a penalty for size. */ \
+ return (COSTS_N_INSNS (1) + (flag_pic != 0) \
+ + (GET_MODE (RTX) == SFmode ? 0 \
+ : GET_MODE (RTX) == DFmode ? 1 : 2)); \
+ }
/* Delete the definition here when TOPLEVEL_COSTS_N_INSNS gets added to cse.c */
#define TOPLEVEL_COSTS_N_INSNS(N) \
@@ -2497,7 +2707,9 @@ do { \
break; \
\
case MULT: \
- if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
+ if (FLOAT_MODE_P (GET_MODE (X))) \
+ TOPLEVEL_COSTS_N_INSNS (ix86_cost->fmul); \
+ else if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
{ \
unsigned HOST_WIDE_INT value = INTVAL (XEXP (X, 1)); \
int nbits = 0; \
@@ -2519,10 +2731,16 @@ do { \
case UDIV: \
case MOD: \
case UMOD: \
- TOPLEVEL_COSTS_N_INSNS (ix86_cost->divide); \
+ if (FLOAT_MODE_P (GET_MODE (X))) \
+ TOPLEVEL_COSTS_N_INSNS (ix86_cost->fdiv); \
+ else \
+ TOPLEVEL_COSTS_N_INSNS (ix86_cost->divide); \
+ break; \
\
case PLUS: \
- if (!TARGET_DECOMPOSE_LEA \
+ if (FLOAT_MODE_P (GET_MODE (X))) \
+ TOPLEVEL_COSTS_N_INSNS (ix86_cost->fadd); \
+ else if (!TARGET_DECOMPOSE_LEA \
&& INTEGRAL_MODE_P (GET_MODE (X)) \
&& GET_MODE_BITSIZE (GET_MODE (X)) <= GET_MODE_BITSIZE (Pmode)) \
{ \
@@ -2562,26 +2780,50 @@ do { \
+ rtx_cost (XEXP (X, 1), (OUTER_CODE))); \
} \
} \
+ /* fall through */ \
\
+ case MINUS: \
+ if (FLOAT_MODE_P (GET_MODE (X))) \
+ TOPLEVEL_COSTS_N_INSNS (ix86_cost->fadd); \
/* fall through */ \
+ \
case AND: \
case IOR: \
case XOR: \
- case MINUS: \
if (!TARGET_64BIT && 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))); \
- \
/* fall through */ \
+ \
case NEG: \
+ if (FLOAT_MODE_P (GET_MODE (X))) \
+ TOPLEVEL_COSTS_N_INSNS (ix86_cost->fchs); \
+ /* fall through */ \
+ \
case NOT: \
if (!TARGET_64BIT && GET_MODE (X) == DImode) \
TOPLEVEL_COSTS_N_INSNS (ix86_cost->add * 2); \
TOPLEVEL_COSTS_N_INSNS (ix86_cost->add); \
\
+ case FLOAT_EXTEND: \
+ if (!TARGET_SSE_MATH \
+ || !VALID_SSE_REG_MODE (GET_MODE (X))) \
+ TOPLEVEL_COSTS_N_INSNS (0); \
+ break; \
+ \
+ case ABS: \
+ if (FLOAT_MODE_P (GET_MODE (X))) \
+ TOPLEVEL_COSTS_N_INSNS (ix86_cost->fabs); \
+ break; \
+ \
+ case SQRT: \
+ if (FLOAT_MODE_P (GET_MODE (X))) \
+ TOPLEVEL_COSTS_N_INSNS (ix86_cost->fsqrt); \
+ break; \
+ \
egress_rtx_costs: \
break;
@@ -2686,10 +2928,10 @@ do { \
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
+ When this macro is nonzero, the compiler will act as if
+ `STRICT_ALIGNMENT' were nonzero 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
+ produced. Therefore, do not set this macro nonzero 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. */
@@ -2716,34 +2958,6 @@ do { \
#define NO_RECURSIVE_FUNCTION_CSE
-/* Add any extra modes needed to represent the condition code.
-
- For the i386, we need separate modes when floating-point
- equality comparisons are being done.
-
- Add CCNO to indicate comparisons against zero that requires
- Overflow flag to be unset. Sign bit test is used instead and
- thus can be used to form "a&b>0" type of tests.
-
- Add CCGC to indicate comparisons agains zero that allows
- unspecified garbage in the Carry flag. This mode is used
- by inc/dec instructions.
-
- Add CCGOC to indicate comparisons agains zero that allows
- unspecified garbage in the Carry and Overflow flag. This
- mode is used to simulate comparisons of (a-b) and (a+b)
- against zero using sub/cmp/add operations.
-
- Add CCZ to indicate that only the Zero flag is valid. */
-
-#define EXTRA_CC_MODES \
- CC (CCGCmode, "CCGC") \
- CC (CCGOCmode, "CCGOC") \
- CC (CCNOmode, "CCNO") \
- CC (CCZmode, "CCZ") \
- CC (CCFPmode, "CCFP") \
- CC (CCFPUmode, "CCFPU")
-
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison.
@@ -2755,7 +2969,7 @@ do { \
#define SELECT_CC_MODE(OP, X, Y) ix86_cc_mode ((OP), (X), (Y))
-/* Return non-zero if MODE implies a floating point inequality can be
+/* Return nonzero if MODE implies a floating point inequality can be
reversed. */
#define REVERSIBLE_CC_MODE(MODE) 1
@@ -2779,7 +2993,7 @@ do { \
For float regs, the stack top is sometimes referred to as "%st(0)"
instead of just "%st". PRINT_REG handles this with the "y" code. */
-#undef HI_REGISTER_NAMES
+#undef HI_REGISTER_NAMES
#define HI_REGISTER_NAMES \
{"ax","dx","cx","bx","si","di","bp","sp", \
"st","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)","", \
@@ -2829,7 +3043,7 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
/* 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 \
@@ -2860,12 +3074,6 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
? ((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4\
: DW_EH_PE_absptr)
-/* This is how to output the definition of a user-level label named NAME,
- such as the label on a static function or variable NAME. */
-
-#define ASM_OUTPUT_LABEL(FILE, NAME) \
- (assemble_name ((FILE), (NAME)), fputs (":\n", (FILE)))
-
/* Store in OUTPUT a string (made with alloca) containing
an assembler-name for a local static variable named NAME.
LABELNO is an integer which is different for each call. */
@@ -2914,7 +3122,7 @@ do { \
#define JUMP_TABLES_IN_TEXT_SECTION \
(!TARGET_64BIT && flag_pic && !HAVE_AS_GOTOFF_IN_DATA)
-/* A C statement that outputs an address constant appropriate to
+/* A C statement that outputs an address constant appropriate to
for DWARF debugging. */
#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE, X) \
@@ -2925,6 +3133,13 @@ do { \
#define ASM_SIMPLIFY_DWARF_ADDR(X) \
i386_simplify_dwarf_addr (X)
+/* Emit a dtp-relative reference to a TLS variable. */
+
+#ifdef HAVE_AS_TLS
+#define ASM_OUTPUT_DWARF_DTPREL(FILE, SIZE, X) \
+ i386_output_dwarf_dtprel (FILE, SIZE, X)
+#endif
+
/* Switch to init or fini section via SECTION_OP, emit a call to FUNC,
and switch back. For x86 we do this only to save a few bytes that
would otherwise be unused in the text section. */
@@ -2939,7 +3154,7 @@ do { \
print_operand function. */
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
- ((CODE) == '*' || (CODE) == '+')
+ ((CODE) == '*' || (CODE) == '+' || (CODE) == '&')
/* Print the name of a register based on its machine mode and number.
If CODE is 'w', pretend the mode is HImode.
@@ -2958,6 +3173,12 @@ do { \
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
print_operand_address ((FILE), (ADDR))
+#define OUTPUT_ADDR_CONST_EXTRA(FILE, X, FAIL) \
+do { \
+ if (! output_addr_const_extra (FILE, (X))) \
+ goto FAIL; \
+} while (0);
+
/* Print the name of a register for based on its machine mode and number.
This macro is used to print debugging output.
This macro is different from PRINT_REG in that it may be used in
@@ -3064,6 +3285,7 @@ do { \
{"general_no_elim_operand", {CONST_INT, CONST_DOUBLE, CONST, \
SYMBOL_REF, LABEL_REF, SUBREG, REG, MEM}}, \
{"nonmemory_no_elim_operand", {CONST_INT, REG, SUBREG}}, \
+ {"index_register_operand", {SUBREG, REG}}, \
{"q_regs_operand", {SUBREG, REG}}, \
{"non_q_regs_operand", {SUBREG, REG}}, \
{"fcmov_comparison_operator", {EQ, NE, LTU, GTU, LEU, GEU, UNORDERED, \
@@ -3088,7 +3310,17 @@ do { \
{"memory_displacement_operand", {MEM}}, \
{"cmpsi_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
LABEL_REF, SUBREG, REG, MEM, AND}}, \
- {"long_memory_operand", {MEM}},
+ {"long_memory_operand", {MEM}}, \
+ {"tls_symbolic_operand", {SYMBOL_REF}}, \
+ {"global_dynamic_symbolic_operand", {SYMBOL_REF}}, \
+ {"local_dynamic_symbolic_operand", {SYMBOL_REF}}, \
+ {"initial_exec_symbolic_operand", {SYMBOL_REF}}, \
+ {"local_exec_symbolic_operand", {SYMBOL_REF}}, \
+ {"any_fp_register_operand", {REG}}, \
+ {"register_and_not_any_fp_reg_operand", {REG}}, \
+ {"fp_register_operand", {REG}}, \
+ {"register_and_not_fp_reg_operand", {REG}}, \
+ {"vector_move_operand", {CONST_VECTOR, SUBREG, REG, MEM}}, \
/* A list of predicates that do special things with modes, and so
should not elicit warnings for VOIDmode match_operand. */
@@ -3096,57 +3328,90 @@ do { \
#define SPECIAL_MODE_PREDICATES \
"ext_register_operand",
-/* CM_32 is used by 32bit ABI
- CM_SMALL is small model assuming that all code and data fits in the first
- 31bits of address space.
- CM_KERNEL is model assuming that all code and data fits in the negative
- 31bits of address space.
- CM_MEDIUM is model assuming that code fits in the first 31bits of address
- space. Size of data is unlimited.
- CM_LARGE is model making no assumptions about size of particular sections.
-
- CM_SMALL_PIC is model for PIC libraries assuming that code+data+got/plt
- tables first in 31bits of address space.
- */
+/* 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,
+ PROCESSOR_K6,
+ PROCESSOR_ATHLON,
+ PROCESSOR_PENTIUM4,
+ PROCESSOR_max
+};
+
+extern enum processor_type ix86_cpu;
+extern const char *ix86_cpu_string;
+
+extern enum processor_type ix86_arch;
+extern const char *ix86_arch_string;
+
+enum fpmath_unit
+{
+ FPMATH_387 = 1,
+ FPMATH_SSE = 2
+};
+
+extern enum fpmath_unit ix86_fpmath;
+extern const char *ix86_fpmath_string;
+
+enum tls_dialect
+{
+ TLS_DIALECT_GNU,
+ TLS_DIALECT_SUN
+};
+
+extern enum tls_dialect ix86_tls_dialect;
+extern const char *ix86_tls_dialect_string;
+
enum cmodel {
- CM_32,
- CM_SMALL,
- CM_KERNEL,
- CM_MEDIUM,
- CM_LARGE,
- CM_SMALL_PIC
+ CM_32, /* The traditional 32-bit ABI. */
+ CM_SMALL, /* Assumes all code and data fits in the low 31 bits. */
+ CM_KERNEL, /* Assumes all code and data fits in the high 31 bits. */
+ CM_MEDIUM, /* Assumes code fits in the low 31 bits; data unlimited. */
+ CM_LARGE, /* No assumptions. */
+ CM_SMALL_PIC /* Assumes code+data+got/plt fits in a 31 bit region. */
};
+extern enum cmodel ix86_cmodel;
+extern const char *ix86_cmodel_string;
+
/* Size of the RED_ZONE area. */
#define RED_ZONE_SIZE 128
/* Reserved area of the red zone for temporaries. */
#define RED_ZONE_RESERVE 8
-extern const char *ix86_debug_arg_string, *ix86_debug_addr_string;
enum asm_dialect {
ASM_ATT,
ASM_INTEL
};
+
extern const char *ix86_asm_string;
extern enum asm_dialect ix86_asm_dialect;
-/* Value of -mcmodel specified by user. */
-extern const char *ix86_cmodel_string;
-extern enum cmodel ix86_cmodel;
-
-/* Variables in i386.c */
-extern const char *ix86_cpu_string; /* for -mcpu=<xxx> */
-extern const char *ix86_arch_string; /* for -march=<xxx> */
-extern const char *ix86_fpmath_string; /* for -mfpmath=<xxx> */
-extern const char *ix86_regparm_string; /* # registers to use to pass args */
-extern const char *ix86_align_loops_string; /* power of two alignment for loops */
-extern const char *ix86_align_jumps_string; /* power of two alignment for non-loop jumps */
-extern const char *ix86_align_funcs_string; /* power of two alignment for functions */
-extern const char *ix86_preferred_stack_boundary_string;/* power of two alignment for stack boundary */
-extern const char *ix86_branch_cost_string; /* values 1-5: see jump.c */
-extern int ix86_regparm; /* ix86_regparm_string as a number */
-extern int ix86_preferred_stack_boundary; /* preferred stack boundary alignment in bits */
-extern int ix86_branch_cost; /* values 1-5: see jump.c */
-extern enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER]; /* smalled class containing REGNO */
+
+extern int ix86_regparm;
+extern const char *ix86_regparm_string;
+
+extern int ix86_preferred_stack_boundary;
+extern const char *ix86_preferred_stack_boundary_string;
+
+extern int ix86_branch_cost;
+extern const char *ix86_branch_cost_string;
+
+extern const char *ix86_debug_arg_string;
+extern const char *ix86_debug_addr_string;
+
+/* Obsoleted by -f options. Remove before 3.2 ships. */
+extern const char *ix86_align_loops_string;
+extern const char *ix86_align_jumps_string;
+extern const char *ix86_align_funcs_string;
+
+/* Smallest class containing REGNO. */
+extern enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER];
+
extern rtx ix86_compare_op0; /* operand 0 for comparisons */
extern rtx ix86_compare_op1; /* operand 1 for comparisons */
@@ -3156,12 +3421,12 @@ extern rtx ix86_compare_op1; /* operand 1 for comparisons */
redundant computation of new control word by the mode switching pass.
The fldcw instructions are still emitted redundantly, but this is probably
not going to be noticeable problem, as most CPUs do have fast path for
- the sequence.
+ the sequence.
The machinery is to emit simple truncation instructions and split them
before reload to instructions having USEs of two memory locations that
are filled by this code to old and new control word.
-
+
Post-reload pass may be later used to eliminate the redundant fildcw if
needed. */
@@ -3222,6 +3487,10 @@ enum fp_cw_mode {FP_CW_STORED, FP_CW_UNINITIALIZED, FP_CW_ANY};
((SRC) < FIRST_STACK_REG || (SRC) > LAST_STACK_REG)
+#define MACHINE_DEPENDENT_REORG(X) x86_machine_dependent_reorg(X)
+
+#define DLL_IMPORT_EXPORT_PREFIX '@'
+
/*
Local variables:
version-control: t
diff --git a/contrib/gcc/config/i386/i386.md b/contrib/gcc/config/i386/i386.md
index 36a0497..1fa2998 100644
--- a/contrib/gcc/config/i386/i386.md
+++ b/contrib/gcc/config/i386/i386.md
@@ -1,5 +1,6 @@
;; GCC machine description for IA-32 and x86-64.
-;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+;; 2001, 2002, 2003
;; Free Software Foundation, Inc.
;; Mostly by William Schelter.
;; x86_64 support added by Jan Hubicka
@@ -49,55 +50,77 @@
;; '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.
-;;
+
;; UNSPEC usage:
-;; 0 This is a `scas' operation. The mode of the UNSPEC is always SImode.
-;; operand 0 is the memory address to scan.
-;; operand 1 is a register containing the value to scan for. The mode
-;; of the scas opcode will be the same as the mode of this operand.
-;; operand 2 is the known alignment of operand 0.
-;; 1 This is a `sin' operation. The mode of the UNSPEC is MODE_FLOAT.
-;; operand 0 is the argument for `sin'.
-;; 2 This is a `cos' operation. The mode of the UNSPEC is MODE_FLOAT.
-;; operand 0 is the argument for `cos'.
-;; 3 This is part of a `stack probe' operation. The mode of the UNSPEC is
-;; always SImode. operand 0 is the size of the stack allocation.
-;; 4 This is the source of a fake SET of the frame pointer which is used to
-;; prevent insns referencing it being scheduled across the initial
-;; decrement of the stack pointer.
-;; 5 This is a `bsf' operation.
-;; 6 This is the @GOT offset of a PIC address.
-;; 7 This is the @GOTOFF offset of a PIC address.
-;; 8 This is a reference to a symbol's @PLT address.
-;; 9 This is an `fnstsw' operation.
-;; 10 This is a `sahf' operation.
-;; 11 This is a `fstcw' operation
-;; 12 This is behaviour of add when setting carry flag.
-;; 13 This is a `eh_return' placeholder.
-
-;; For SSE/MMX support:
-;; 30 This is `fix', guaranteed to be truncating.
-;; 31 This is a `emms' operation.
-;; 32 This is a `maskmov' operation.
-;; 33 This is a `movmsk' operation.
-;; 34 This is a `non-temporal' move.
-;; 36 This is used to distinguish COMISS from UCOMISS.
-;; 37 This is a `ldmxcsr' operation.
-;; 38 This is a forced `movaps' instruction (rather than whatever movti does)
-;; 39 This is a forced `movups' instruction (rather than whatever movti does)
-;; 40 This is a `stmxcsr' operation.
-;; 41 This is a `shuffle' operation.
-;; 42 This is a `rcp' operation.
-;; 43 This is a `rsqsrt' operation.
-;; 44 This is a `sfence' operation.
-;; 45 This is a noop to prevent excessive combiner cleverness.
-;; 46 This is a `femms' operation.
-;; 49 This is a 'pavgusb' operation.
-;; 50 This is a `pfrcp' operation.
-;; 51 This is a `pfrcpit1' operation.
-;; 52 This is a `pfrcpit2' operation.
-;; 53 This is a `pfrsqrt' operation.
-;; 54 This is a `pfrsqrit1' operation.
+
+(define_constants
+ [; Relocation specifiers
+ (UNSPEC_GOT 0)
+ (UNSPEC_GOTOFF 1)
+ (UNSPEC_GOTPCREL 2)
+ (UNSPEC_GOTTPOFF 3)
+ (UNSPEC_TPOFF 4)
+ (UNSPEC_NTPOFF 5)
+ (UNSPEC_DTPOFF 6)
+ (UNSPEC_GOTNTPOFF 7)
+ (UNSPEC_INDNTPOFF 8)
+
+ ; Prologue support
+ (UNSPEC_STACK_PROBE 10)
+ (UNSPEC_STACK_ALLOC 11)
+ (UNSPEC_SET_GOT 12)
+ (UNSPEC_SSE_PROLOGUE_SAVE 13)
+
+ ; TLS support
+ (UNSPEC_TP 15)
+ (UNSPEC_TLS_GD 16)
+ (UNSPEC_TLS_LD_BASE 17)
+
+ ; Other random patterns
+ (UNSPEC_SCAS 20)
+ (UNSPEC_SIN 21)
+ (UNSPEC_COS 22)
+ (UNSPEC_BSF 23)
+ (UNSPEC_FNSTSW 24)
+ (UNSPEC_SAHF 25)
+ (UNSPEC_FSTCW 26)
+ (UNSPEC_ADD_CARRY 27)
+ (UNSPEC_FLDCW 28)
+
+ ; For SSE/MMX support:
+ (UNSPEC_FIX 30)
+ (UNSPEC_MASKMOV 32)
+ (UNSPEC_MOVMSK 33)
+ (UNSPEC_MOVNT 34)
+ (UNSPEC_MOVA 38)
+ (UNSPEC_MOVU 39)
+ (UNSPEC_SHUFFLE 41)
+ (UNSPEC_RCP 42)
+ (UNSPEC_RSQRT 43)
+ (UNSPEC_SFENCE 44)
+ (UNSPEC_NOP 45) ; prevents combiner cleverness
+ (UNSPEC_PAVGUSB 49)
+ (UNSPEC_PFRCP 50)
+ (UNSPEC_PFRCPIT1 51)
+ (UNSPEC_PFRCPIT2 52)
+ (UNSPEC_PFRSQRT 53)
+ (UNSPEC_PFRSQIT1 54)
+ (UNSPEC_PSHUFLW 55)
+ (UNSPEC_PSHUFHW 56)
+ (UNSPEC_MFENCE 59)
+ (UNSPEC_LFENCE 60)
+ (UNSPEC_PSADBW 61)
+ ])
+
+(define_constants
+ [(UNSPECV_BLOCKAGE 0)
+ (UNSPECV_EH_RETURN 13)
+ (UNSPECV_EMMS 31)
+ (UNSPECV_LDMXCSR 37)
+ (UNSPECV_STMXCSR 40)
+ (UNSPECV_FEMMS 46)
+ (UNSPECV_CLFLUSH 57)
+ ])
;; Insns whose names begin with "x86_" are emitted by gen_FOO calls
;; from i386.c.
@@ -116,26 +139,44 @@
;; A basic instruction type. Refinements due to arguments to be
;; provided in other attributes.
(define_attr "type"
- "other,multi,alu1,negnot,alu,icmp,test,imov,imovx,lea,incdec,ishift,imul,idiv,ibr,setcc,push,pop,call,callv,icmov,fmov,fop,fop1,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,str,cld,sse,mmx,fistp"
+ "other,multi,
+ alu,alu1,negnot,imov,imovx,lea,
+ incdec,ishift,ishift1,rotate,rotate1,imul,idiv,
+ icmp,test,ibr,setcc,icmov,
+ push,pop,call,callv,
+ str,cld,
+ fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp,
+ sselog,sseiadd,sseishft,sseimul,
+ sse,ssemov,sseadd,ssemul,ssecmp,ssecvt,ssediv,
+ mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
(const_string "other"))
;; Main data type used by the insn
-(define_attr "mode" "unknown,none,QI,HI,SI,DI,unknownfp,SF,DF,XF,TI"
+(define_attr "mode"
+ "unknown,none,QI,HI,SI,DI,unknownfp,SF,DF,XF,TI,V4SF,V2DF,V2SF"
(const_string "unknown"))
-;; Set for i387 operations.
-(define_attr "i387" ""
- (if_then_else (eq_attr "type" "fmov,fop,fop1,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp")
- (const_int 1)
- (const_int 0)))
+;; The CPU unit operations uses.
+(define_attr "unit" "integer,i387,sse,mmx,unknown"
+ (cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp")
+ (const_string "i387")
+ (eq_attr "type" "sselog,sseiadd,sseishft,sseimul,
+ sse,ssemov,sseadd,ssemul,ssecmp,ssecvt,ssediv")
+ (const_string "sse")
+ (eq_attr "type" "mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft")
+ (const_string "mmx")
+ (eq_attr "type" "other")
+ (const_string "unknown")]
+ (const_string "integer")))
;; The (bounding maximum) length of an instruction immediate.
(define_attr "length_immediate" ""
- (cond [(eq_attr "type" "incdec,setcc,icmov,ibr,str,cld,lea,other,multi,idiv,sse,mmx")
+ (cond [(eq_attr "type" "incdec,setcc,icmov,str,cld,lea,other,multi,idiv")
(const_int 0)
- (eq_attr "i387" "1")
+ (eq_attr "unit" "i387,sse,mmx")
(const_int 0)
- (eq_attr "type" "alu1,negnot,alu,icmp,imovx,ishift,imul,push,pop")
+ (eq_attr "type" "alu,alu1,negnot,imovx,ishift,rotate,ishift1,rotate1,
+ imul,icmp,push,pop")
(symbol_ref "ix86_attr_length_immediate_default(insn,1)")
(eq_attr "type" "imov,test")
(symbol_ref "ix86_attr_length_immediate_default(insn,0)")
@@ -147,22 +188,20 @@
(if_then_else (match_operand 1 "constant_call_address_operand" "")
(const_int 4)
(const_int 0))
+ ;; We don't know the size before shorten_branches. Expect
+ ;; the instruction to fit for better scheduling.
(eq_attr "type" "ibr")
- (if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -128))
- (lt (minus (match_dup 0) (pc))
- (const_int 124)))
- (const_int 1)
- (const_int 4))
+ (const_int 1)
]
- (symbol_ref "/* Update immediate_length and other attributes! */ abort(),1")))
+ (symbol_ref "/* Update immediate_length and other attributes! */
+ abort(),1")))
;; The (bounding maximum) length of an instruction address.
(define_attr "length_address" ""
(cond [(eq_attr "type" "str,cld,other,multi,fxch")
(const_int 0)
(and (eq_attr "type" "call")
- (match_operand 1 "constant_call_address_operand" ""))
+ (match_operand 0 "constant_call_address_operand" ""))
(const_int 0)
(and (eq_attr "type" "callv")
(match_operand 1 "constant_call_address_operand" ""))
@@ -172,16 +211,25 @@
;; Set when length prefix is used.
(define_attr "prefix_data16" ""
- (if_then_else (eq_attr "mode" "HI")
+ (if_then_else (ior (eq_attr "mode" "HI")
+ (and (eq_attr "unit" "sse") (eq_attr "mode" "V2DF")))
(const_int 1)
(const_int 0)))
;; Set when string REP prefix is used.
-(define_attr "prefix_rep" "" (const_int 0))
+(define_attr "prefix_rep" ""
+ (if_then_else (and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF"))
+ (const_int 1)
+ (const_int 0)))
;; Set when 0f opcode prefix is used.
(define_attr "prefix_0f" ""
- (if_then_else (eq_attr "type" "imovx,setcc,icmov,sse,mmx")
+ (if_then_else
+ (eq_attr "type"
+ "imovx,setcc,icmov,
+ sselog,sseiadd,sseishft,sseimul,
+ sse,ssemov,sseadd,ssemul,ssecmp,ssecvt,ssediv,
+ mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft")
(const_int 1)
(const_int 0)))
@@ -189,7 +237,7 @@
(define_attr "modrm" ""
(cond [(eq_attr "type" "str,cld")
(const_int 0)
- (eq_attr "i387" "1")
+ (eq_attr "unit" "i387")
(const_int 0)
(and (eq_attr "type" "incdec")
(ior (match_operand:SI 1 "register_operand" "")
@@ -205,6 +253,12 @@
(and (match_operand 0 "register_operand" "")
(match_operand 1 "immediate_operand" "")))
(const_int 0)
+ (and (eq_attr "type" "call")
+ (match_operand 0 "constant_call_address_operand" ""))
+ (const_int 0)
+ (and (eq_attr "type" "callv")
+ (match_operand 1 "constant_call_address_operand" ""))
+ (const_int 0)
]
(const_int 1)))
@@ -214,11 +268,15 @@
(define_attr "length" ""
(cond [(eq_attr "type" "other,multi,fistp")
(const_int 16)
- ]
+ (eq_attr "type" "fcmp")
+ (const_int 4)
+ (eq_attr "unit" "i387")
+ (plus (const_int 2)
+ (plus (attr "prefix_data16")
+ (attr "length_address")))]
(plus (plus (attr "modrm")
(plus (attr "prefix_0f")
- (plus (attr "i387")
- (const_int 1))))
+ (const_int 1)))
(plus (attr "prefix_rep")
(plus (attr "prefix_data16")
(plus (attr "length_immediate")
@@ -243,7 +301,7 @@
(if_then_else (match_operand 0 "memory_operand" "")
(const_string "both")
(const_string "load"))
- (eq_attr "type" "icmp,test")
+ (eq_attr "type" "icmp,test,ssecmp,mmxcmp,fcmp")
(if_then_else (ior (match_operand 0 "memory_operand" "")
(match_operand 1 "memory_operand" ""))
(const_string "load")
@@ -270,7 +328,12 @@
(const_string "store")
(match_operand 1 "memory_operand" "")
(const_string "load")
- (and (eq_attr "type" "!icmp,test,alu1,negnot,fop1,fsgn,imov,imovx,fmov,fcmp,sse,mmx")
+ (and (eq_attr "type"
+ "!alu1,negnot,
+ imov,imovx,icmp,test,
+ fmov,fcmp,fsgn,
+ sse,ssemov,ssecmp,ssecvt,
+ mmx,mmxmov,mmxcmp,mmxcvt")
(match_operand 2 "memory_operand" ""))
(const_string "load")
(and (eq_attr "type" "icmov")
@@ -284,11 +347,11 @@
(define_attr "imm_disp" "false,true,unknown"
(cond [(eq_attr "type" "other,multi")
(const_string "unknown")
- (and (eq_attr "type" "icmp,test,imov")
+ (and (eq_attr "type" "icmp,test,imov,alu1,ishift1,rotate1")
(and (match_operand 0 "memory_displacement_operand" "")
(match_operand 1 "immediate_operand" "")))
(const_string "true")
- (and (eq_attr "type" "alu,ishift,imul,idiv")
+ (and (eq_attr "type" "alu,ishift,rotate,imul,idiv")
(and (match_operand 0 "memory_displacement_operand" "")
(match_operand 2 "immediate_operand" "")))
(const_string "true")
@@ -305,710 +368,10 @@
[(set_attr "length" "128")
(set_attr "type" "multi")])
-;; Pentium Scheduling
-;;
-;; The Pentium is an in-order core with two integer pipelines.
-
-;; True for insns that behave like prefixed insns on the Pentium.
-(define_attr "pent_prefix" "false,true"
- (if_then_else (ior (eq_attr "prefix_0f" "1")
- (ior (eq_attr "prefix_data16" "1")
- (eq_attr "prefix_rep" "1")))
- (const_string "true")
- (const_string "false")))
-
-;; Categorize how an instruction slots.
-
-;; The non-MMX Pentium slots an instruction with prefixes on U pipe only,
-;; while MMX Pentium can slot it on either U or V. Model non-MMX Pentium
-;; rules, because it results in noticeably better code on non-MMX Pentium
-;; and doesn't hurt much on MMX. (Prefixed instructions are not very
-;; common, so the scheduler usualy has a non-prefixed insn to pair).
-
-(define_attr "pent_pair" "uv,pu,pv,np"
- (cond [(eq_attr "imm_disp" "true")
- (const_string "np")
- (ior (eq_attr "type" "alu1,alu,imov,icmp,test,lea,incdec")
- (and (eq_attr "type" "pop,push")
- (eq_attr "memory" "!both")))
- (if_then_else (eq_attr "pent_prefix" "true")
- (const_string "pu")
- (const_string "uv"))
- (eq_attr "type" "ibr")
- (const_string "pv")
- (and (eq_attr "type" "ishift")
- (match_operand 2 "const_int_operand" ""))
- (const_string "pu")
- (and (eq_attr "type" "call")
- (match_operand 0 "constant_call_address_operand" ""))
- (const_string "pv")
- (and (eq_attr "type" "callv")
- (match_operand 1 "constant_call_address_operand" ""))
- (const_string "pv")
- ]
- (const_string "np")))
-
-;; Rough readiness numbers. Fine tuning happens in i386.c.
-;;
-;; u describes pipe U
-;; v describes pipe V
-;; uv describes either pipe U or V for those that can issue to either
-;; np describes not paring
-;; fpu describes fpu
-;; fpm describes fp insns of different types are not pipelined.
-;;
-;; ??? fxch isn't handled; not an issue until sched3 after reg-stack is real.
-
-(define_function_unit "pent_np" 1 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "type" "imul"))
- 11 11)
-
-(define_function_unit "pent_mul" 1 1
- (and (eq_attr "cpu" "pentium")
- (eq_attr "type" "imul"))
- 11 11)
-
-;; Rep movs takes minimally 12 cycles.
-(define_function_unit "pent_np" 1 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "type" "str"))
- 12 12)
-
-; ??? IDIV for SI takes 46 cycles, for HI 30, for QI 22
-(define_function_unit "pent_np" 1 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "type" "idiv"))
- 46 46)
-
-; Fp reg-reg moves takes 1 cycle. Loads takes 1 cycle for SF/DF mode,
-; 3 cycles for XFmode. Stores takes 2 cycles for SF/DF and 3 for XF.
-; fldz and fld1 takes 2 cycles. Only reg-reg moves are pairable.
-; The integer <-> fp conversion is not modeled correctly. Fild behaves
-; like normal fp operation and fist takes 6 cycles.
-
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentium")
- (and (eq_attr "type" "fmov")
- (and (eq_attr "memory" "load,store")
- (eq_attr "mode" "XF"))))
- 3 3)
-
-(define_function_unit "pent_np" 1 0
- (and (eq_attr "cpu" "pentium")
- (and (eq_attr "type" "fmov")
- (and (eq_attr "memory" "load,store")
- (eq_attr "mode" "XF"))))
- 3 3)
-
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentium")
- (and (eq_attr "type" "fmov")
- (ior (match_operand 1 "immediate_operand" "")
- (eq_attr "memory" "store"))))
- 2 2)
-
-(define_function_unit "pent_np" 1 0
- (and (eq_attr "cpu" "pentium")
- (and (eq_attr "type" "fmov")
- (ior (match_operand 1 "immediate_operand" "")
- (eq_attr "memory" "store"))))
- 2 2)
-
-(define_function_unit "pent_np" 1 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "type" "cld"))
- 2 2)
-
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentium")
- (and (eq_attr "type" "fmov")
- (eq_attr "memory" "none,load")))
- 1 1)
-
-; Read/Modify/Write instructions usually take 3 cycles.
-(define_function_unit "pent_u" 1 0
- (and (eq_attr "cpu" "pentium")
- (and (eq_attr "type" "alu,alu1,ishift")
- (and (eq_attr "pent_pair" "pu")
- (eq_attr "memory" "both"))))
- 3 3)
-
-(define_function_unit "pent_uv" 2 0
- (and (eq_attr "cpu" "pentium")
- (and (eq_attr "type" "alu,alu1,ishift")
- (and (eq_attr "pent_pair" "!np")
- (eq_attr "memory" "both"))))
- 3 3)
-
-(define_function_unit "pent_np" 1 0
- (and (eq_attr "cpu" "pentium")
- (and (eq_attr "type" "alu,alu1,negnot,ishift")
- (and (eq_attr "pent_pair" "np")
- (eq_attr "memory" "both"))))
- 3 3)
-
-; Read/Modify or Modify/Write instructions usually take 2 cycles.
-(define_function_unit "pent_u" 1 0
- (and (eq_attr "cpu" "pentium")
- (and (eq_attr "type" "alu,ishift")
- (and (eq_attr "pent_pair" "pu")
- (eq_attr "memory" "load,store"))))
- 2 2)
-
-(define_function_unit "pent_uv" 2 0
- (and (eq_attr "cpu" "pentium")
- (and (eq_attr "type" "alu,ishift")
- (and (eq_attr "pent_pair" "!np")
- (eq_attr "memory" "load,store"))))
- 2 2)
-
-(define_function_unit "pent_np" 1 0
- (and (eq_attr "cpu" "pentium")
- (and (eq_attr "type" "alu,ishift")
- (and (eq_attr "pent_pair" "np")
- (eq_attr "memory" "load,store"))))
- 2 2)
-
-; Insns w/o memory operands and move instructions usually take one cycle.
-(define_function_unit "pent_u" 1 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "pent_pair" "pu"))
- 1 1)
-
-(define_function_unit "pent_v" 1 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "pent_pair" "pv"))
- 1 1)
-
-(define_function_unit "pent_uv" 2 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "pent_pair" "!np"))
- 1 1)
-
-(define_function_unit "pent_np" 1 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "pent_pair" "np"))
- 1 1)
-
-; Pairable insns only conflict with other non-pairable insns.
-(define_function_unit "pent_np" 1 0
- (and (eq_attr "cpu" "pentium")
- (and (eq_attr "type" "alu,alu1,ishift")
- (and (eq_attr "pent_pair" "!np")
- (eq_attr "memory" "both"))))
- 3 3
- [(eq_attr "pent_pair" "np")])
-
-(define_function_unit "pent_np" 1 0
- (and (eq_attr "cpu" "pentium")
- (and (eq_attr "type" "alu,alu1,ishift")
- (and (eq_attr "pent_pair" "!np")
- (eq_attr "memory" "load,store"))))
- 2 2
- [(eq_attr "pent_pair" "np")])
-
-(define_function_unit "pent_np" 1 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "pent_pair" "!np"))
- 1 1
- [(eq_attr "pent_pair" "np")])
-
-; Floating point instructions usually blocks cycle longer when combined with
-; integer instructions, because of the inpaired fxch instruction.
-(define_function_unit "pent_np" 1 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "type" "fmov,fop,fop1,fsgn,fmul,fpspc,fcmov,fcmp,fistp"))
- 2 2
- [(eq_attr "type" "!fmov,fop,fop1,fsgn,fmul,fpspc,fcmov,fcmp,fistp")])
-
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "type" "fcmp,fxch,fsgn"))
- 1 1)
-
-; Addition takes 3 cycles; assume other random cruft does as well.
-; ??? Trivial fp operations such as fabs or fchs takes only one cycle.
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "type" "fop,fop1,fistp"))
- 3 1)
-
-; Multiplication takes 3 cycles and is only half pipelined.
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "type" "fmul"))
- 3 1)
-
-(define_function_unit "pent_mul" 1 1
- (and (eq_attr "cpu" "pentium")
- (eq_attr "type" "fmul"))
- 2 2)
-
-; ??? This is correct only for fdiv and sqrt -- sin/cos take 65-100 cycles.
-; They can overlap with integer insns. Only the last two cycles can overlap
-; with other fp insns. Only fsin/fcos can overlap with multiplies.
-; Only last two cycles of fsin/fcos can overlap with other instructions.
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "type" "fdiv"))
- 39 37)
-
-(define_function_unit "pent_mul" 1 1
- (and (eq_attr "cpu" "pentium")
- (eq_attr "type" "fdiv"))
- 39 39)
-
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentium")
- (eq_attr "type" "fpspc"))
- 70 68)
-
-(define_function_unit "pent_mul" 1 1
- (and (eq_attr "cpu" "pentium")
- (eq_attr "type" "fpspc"))
- 70 70)
-
-;; Pentium Pro/PII Scheduling
-;;
-;; The PPro has an out-of-order core, but the instruction decoders are
-;; naturally in-order and asymmetric. We get best performance by scheduling
-;; for the decoders, for in doing so we give the oo execution unit the
-;; most choices.
-
-;; Categorize how many uops an ia32 instruction evaluates to:
-;; one -- an instruction with 1 uop can be decoded by any of the
-;; three decoders.
-;; few -- an instruction with 1 to 4 uops can be decoded only by
-;; decoder 0.
-;; many -- a complex instruction may take an unspecified number of
-;; cycles to decode in decoder 0.
-
-(define_attr "ppro_uops" "one,few,many"
- (cond [(eq_attr "type" "other,multi,call,callv,fpspc,str")
- (const_string "many")
- (eq_attr "type" "icmov,fcmov,str,cld")
- (const_string "few")
- (eq_attr "type" "imov")
- (if_then_else (eq_attr "memory" "store,both")
- (const_string "few")
- (const_string "one"))
- (eq_attr "memory" "!none")
- (const_string "few")
- ]
- (const_string "one")))
-
-;; Rough readiness numbers. Fine tuning happens in i386.c.
-;;
-;; p0 describes port 0.
-;; p01 describes ports 0 and 1 as a pair; alu insns can issue to either.
-;; p2 describes port 2 for loads.
-;; p34 describes ports 3 and 4 for stores.
-;; fpu describes the fpu accessed via port 0.
-;; ??? It is less than clear if there are separate fadd and fmul units
-;; that could operate in parallel.
-;;
-;; ??? fxch isn't handled; not an issue until sched3 after reg-stack is real.
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "ishift,lea,ibr,cld"))
- 1 1)
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "imul"))
- 4 1)
-
-;; ??? Does the divider lock out the pipe while it works,
-;; or is there a disconnected unit?
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "idiv"))
- 17 17)
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fop,fop1,fsgn,fistp"))
- 3 1)
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fcmov"))
- 2 1)
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fcmp"))
- 1 1)
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fmov"))
- 1 1)
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fmul"))
- 5 1)
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fdiv,fpspc"))
- 56 1)
-
-(define_function_unit "ppro_p01" 2 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "!imov,fmov"))
- 1 1)
-
-(define_function_unit "ppro_p01" 2 0
- (and (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "imov,fmov"))
- (eq_attr "memory" "none"))
- 1 1)
-
-(define_function_unit "ppro_p2" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (ior (eq_attr "type" "pop")
- (eq_attr "memory" "load,both")))
- 3 1)
-
-(define_function_unit "ppro_p34" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (ior (eq_attr "type" "push")
- (eq_attr "memory" "store,both")))
- 1 1)
-
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fop,fop1,fsgn,fmov,fcmp,fcmov,fistp"))
- 1 1)
-
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fmul"))
- 5 2)
-
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fdiv,fpspc"))
- 56 56)
-
-;; imul uses the fpu. ??? does it have the same throughput as fmul?
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "imul"))
- 4 1)
-
-;; AMD K6/K6-2 Scheduling
-;;
-;; The K6 has similar architecture to PPro. Important difference is, that
-;; there are only two decoders and they seems to be much slower than execution
-;; units. So we have to pay much more attention to proper decoding for
-;; schedulers. We share most of scheduler code for PPro in i386.c
-;;
-;; The fp unit is not pipelined and do one operation per two cycles including
-;; the FXCH.
-;;
-;; alu describes both ALU units (ALU-X and ALU-Y).
-;; alux describes X alu unit
-;; fpu describes FPU unit
-;; load describes load unit.
-;; branch describes branch unit.
-;; store decsribes store unit. This unit is not modelled completely and only
-;; used to model lea operation. Otherwise it lie outside of the critical
-;; path.
-;;
-;; ??? fxch isn't handled; not an issue until sched3 after reg-stack is real.
-
-;; The decoder specification is in the PPro section above!
-
-;; Shift instructions and certain arithmetic are issued only to X pipe.
-(define_function_unit "k6_alux" 1 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "ishift,alu1,negnot,cld"))
- 1 1)
-
-;; The QI mode arithmetic is issued to X pipe only.
-(define_function_unit "k6_alux" 1 0
- (and (eq_attr "cpu" "k6")
- (and (eq_attr "type" "alu,alu1,negnot,icmp,test,imovx,incdec")
- (match_operand:QI 0 "general_operand" "")))
- 1 1)
-
-(define_function_unit "k6_alu" 2 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "ishift,alu1,negnot,alu,icmp,test,imovx,incdec,setcc,lea"))
- 1 1)
-
-(define_function_unit "k6_alu" 2 0
- (and (eq_attr "cpu" "k6")
- (and (eq_attr "type" "imov")
- (eq_attr "memory" "none")))
- 1 1)
-
-(define_function_unit "k6_branch" 1 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "call,callv,ibr"))
- 1 1)
-
-;; Load unit have two cycle latency, but we take care for it in adjust_cost
-(define_function_unit "k6_load" 1 0
- (and (eq_attr "cpu" "k6")
- (ior (eq_attr "type" "pop")
- (eq_attr "memory" "load,both")))
- 1 1)
-
-(define_function_unit "k6_load" 1 0
- (and (eq_attr "cpu" "k6")
- (and (eq_attr "type" "str")
- (eq_attr "memory" "load,both")))
- 10 10)
-
-;; Lea have two instructions, so latency is probably 2
-(define_function_unit "k6_store" 1 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "lea"))
- 2 1)
-
-(define_function_unit "k6_store" 1 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "str"))
- 10 10)
-
-(define_function_unit "k6_store" 1 0
- (and (eq_attr "cpu" "k6")
- (ior (eq_attr "type" "push")
- (eq_attr "memory" "store,both")))
- 1 1)
-
-(define_function_unit "k6_fpu" 1 1
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "fop,fop1,fmov,fcmp,fistp"))
- 2 2)
-
-(define_function_unit "k6_fpu" 1 1
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "fmul"))
- 2 2)
-
-;; ??? Guess
-(define_function_unit "k6_fpu" 1 1
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "fdiv,fpspc"))
- 56 56)
-
-(define_function_unit "k6_alu" 2 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "imul"))
- 2 2)
-
-(define_function_unit "k6_alux" 1 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "imul"))
- 2 2)
-
-;; ??? Guess
-(define_function_unit "k6_alu" 2 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "idiv"))
- 17 17)
-
-(define_function_unit "k6_alux" 1 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "idiv"))
- 17 17)
-
-;; AMD Athlon Scheduling
-;;
-;; The Athlon does contain three pipelined FP units, three integer units and
-;; three address generation units.
-;;
-;; The predecode logic is determining boundaries of instructions in the 64
-;; byte cache line. So the cache line straddling problem of K6 might be issue
-;; here as well, but it is not noted in the documentation.
-;;
-;; Three DirectPath instructions decoders and only one VectorPath decoder
-;; is available. They can decode three DirectPath instructions or one VectorPath
-;; instruction per cycle.
-;; Decoded macro instructions are then passed to 72 entry instruction control
-;; unit, that passes
-;; it to the specialized integer (18 entry) and fp (36 entry) schedulers.
-;;
-;; The load/store queue unit is not attached to the schedulers but
-;; communicates with all the execution units separately instead.
-
-(define_attr "athlon_decode" "direct,vector"
- (cond [(eq_attr "type" "call,imul,idiv,other,multi,fcmov,fpspc,str,pop,cld,fcmov")
- (const_string "vector")
- (and (eq_attr "type" "push")
- (match_operand 1 "memory_operand" ""))
- (const_string "vector")
- (and (eq_attr "type" "fmov")
- (and (eq_attr "memory" "load,store")
- (eq_attr "mode" "XF")))
- (const_string "vector")]
- (const_string "direct")))
-
-(define_function_unit "athlon_vectordec" 1 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "athlon_decode" "vector"))
- 1 1)
-
-(define_function_unit "athlon_directdec" 3 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "athlon_decode" "direct"))
- 1 1)
-
-(define_function_unit "athlon_vectordec" 1 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "athlon_decode" "direct"))
- 1 1 [(eq_attr "athlon_decode" "vector")])
-
-(define_function_unit "athlon_ieu" 3 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "type" "alu1,negnot,alu,icmp,test,imov,imovx,lea,incdec,ishift,ibr,call,callv,icmov,cld,pop,setcc,push,pop"))
- 1 1)
-
-(define_function_unit "athlon_ieu" 3 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "type" "str"))
- 15 15)
-
-(define_function_unit "athlon_ieu" 3 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "type" "imul"))
- 5 0)
-
-(define_function_unit "athlon_ieu" 3 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "type" "idiv"))
- 42 0)
-
-(define_function_unit "athlon_muldiv" 1 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "type" "imul"))
- 5 0)
-
-(define_function_unit "athlon_muldiv" 1 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "type" "idiv"))
- 42 42)
-
-(define_attr "athlon_fpunits" "none,store,mul,add,muladd,any"
- (cond [(eq_attr "type" "fop,fop1,fcmp,fistp")
- (const_string "add")
- (eq_attr "type" "fmul,fdiv,fpspc,fsgn,fcmov")
- (const_string "mul")
- (and (eq_attr "type" "fmov") (eq_attr "memory" "store,both"))
- (const_string "store")
- (and (eq_attr "type" "fmov") (eq_attr "memory" "load"))
- (const_string "any")
- (and (eq_attr "type" "fmov")
- (ior (match_operand:SI 1 "register_operand" "")
- (match_operand 1 "immediate_operand" "")))
- (const_string "store")
- (eq_attr "type" "fmov")
- (const_string "muladd")]
- (const_string "none")))
-
-;; We use latencies 1 for definitions. This is OK to model colisions
-;; in execution units. The real latencies are modeled in the "fp" pipeline.
-
-;; fsin, fcos: 96-192
-;; fsincos: 107-211
-;; fsqrt: 19 for SFmode, 27 for DFmode, 35 for XFmode.
-(define_function_unit "athlon_fp" 3 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "type" "fpspc"))
- 100 1)
-
-;; 16 cycles for SFmode, 20 for DFmode and 24 for XFmode.
-(define_function_unit "athlon_fp" 3 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "type" "fdiv"))
- 24 1)
-
-(define_function_unit "athlon_fp" 3 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "type" "fop,fop1,fmul,fistp"))
- 4 1)
-
-;; XFmode loads are slow.
-;; XFmode store is slow too (8 cycles), but we don't need to model it, because
-;; there are no dependent instructions.
-
-(define_function_unit "athlon_fp" 3 0
- (and (eq_attr "cpu" "athlon")
- (and (eq_attr "type" "fmov")
- (and (eq_attr "memory" "load")
- (eq_attr "mode" "XF"))))
- 10 1)
-
-(define_function_unit "athlon_fp" 3 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "type" "fmov,fsgn"))
- 2 1)
-
-;; fcmp and ftst instructions
-(define_function_unit "athlon_fp" 3 0
- (and (eq_attr "cpu" "athlon")
- (and (eq_attr "type" "fcmp")
- (eq_attr "athlon_decode" "direct")))
- 3 1)
-
-;; fcmpi instructions.
-(define_function_unit "athlon_fp" 3 0
- (and (eq_attr "cpu" "athlon")
- (and (eq_attr "type" "fcmp")
- (eq_attr "athlon_decode" "vector")))
- 3 1)
-
-(define_function_unit "athlon_fp" 3 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "type" "fcmov"))
- 7 1)
-
-(define_function_unit "athlon_fp_mul" 1 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "athlon_fpunits" "mul"))
- 1 1)
-
-(define_function_unit "athlon_fp_add" 1 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "athlon_fpunits" "add"))
- 1 1)
-
-(define_function_unit "athlon_fp_muladd" 2 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "athlon_fpunits" "muladd,mul,add"))
- 1 1)
-
-(define_function_unit "athlon_fp_store" 1 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "athlon_fpunits" "store"))
- 1 1)
-
-;; We don't need to model the Address Generation Unit, since we don't model
-;; the re-order buffer yet and thus we never schedule more than three operations
-;; at time. Later we may want to experiment with MD_SCHED macros modeling the
-;; decoders independently on the functional units.
-
-;(define_function_unit "athlon_agu" 3 0
-; (and (eq_attr "cpu" "athlon")
-; (and (eq_attr "memory" "!none")
-; (eq_attr "athlon_fpunits" "none")))
-; 1 1)
-
-;; Model load unit to avoid too long sequences of loads. We don't need to
-;; model store queue, since it is hardly going to be bottleneck.
-
-(define_function_unit "athlon_load" 2 0
- (and (eq_attr "cpu" "athlon")
- (eq_attr "memory" "load,both"))
- 1 1)
-
+(include "pentium.md")
+(include "ppro.md")
+(include "k6.md")
+(include "athlon.md")
;; Compare instructions.
@@ -1382,7 +745,8 @@
[(set (match_operand:HI 0 "register_operand" "=a")
(unspec:HI
[(compare:CCFP (match_operand 1 "register_operand" "f")
- (match_operand 2 "const0_operand" "X"))] 9))]
+ (match_operand 2 "const0_operand" "X"))]
+ UNSPEC_FNSTSW))]
"TARGET_80387
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])"
@@ -1413,7 +777,8 @@
(unspec:HI
[(compare:CCFP
(match_operand:SF 1 "register_operand" "f")
- (match_operand:SF 2 "nonimmediate_operand" "fm"))] 9))]
+ (match_operand:SF 2 "nonimmediate_operand" "fm"))]
+ UNSPEC_FNSTSW))]
"TARGET_80387"
"* return output_fp_compare (insn, operands, 2, 0);"
[(set_attr "type" "fcmp")
@@ -1434,7 +799,8 @@
(unspec:HI
[(compare:CCFP
(match_operand:DF 1 "register_operand" "f")
- (match_operand:DF 2 "nonimmediate_operand" "fm"))] 9))]
+ (match_operand:DF 2 "nonimmediate_operand" "fm"))]
+ UNSPEC_FNSTSW))]
"TARGET_80387"
"* return output_fp_compare (insn, operands, 2, 0);"
[(set_attr "type" "multi")
@@ -1465,7 +831,8 @@
(unspec:HI
[(compare:CCFP
(match_operand:XF 1 "register_operand" "f")
- (match_operand:XF 2 "register_operand" "f"))] 9))]
+ (match_operand:XF 2 "register_operand" "f"))]
+ UNSPEC_FNSTSW))]
"!TARGET_64BIT && TARGET_80387"
"* return output_fp_compare (insn, operands, 2, 0);"
[(set_attr "type" "multi")
@@ -1476,7 +843,8 @@
(unspec:HI
[(compare:CCFP
(match_operand:TF 1 "register_operand" "f")
- (match_operand:TF 2 "register_operand" "f"))] 9))]
+ (match_operand:TF 2 "register_operand" "f"))]
+ UNSPEC_FNSTSW))]
"TARGET_80387"
"* return output_fp_compare (insn, operands, 2, 0);"
[(set_attr "type" "multi")
@@ -1499,7 +867,8 @@
(unspec:HI
[(compare:CCFPU
(match_operand 1 "register_operand" "f")
- (match_operand 2 "register_operand" "f"))] 9))]
+ (match_operand 2 "register_operand" "f"))]
+ UNSPEC_FNSTSW))]
"TARGET_80387
&& FLOAT_MODE_P (GET_MODE (operands[1]))
&& GET_MODE (operands[1]) == GET_MODE (operands[2])"
@@ -1547,12 +916,12 @@
(define_insn "x86_fnstsw_1"
[(set (match_operand:HI 0 "register_operand" "=a")
- (unspec:HI [(reg 18)] 9))]
+ (unspec:HI [(reg 18)] UNSPEC_FNSTSW))]
"TARGET_80387"
"fnstsw\t%0"
[(set_attr "length" "2")
(set_attr "mode" "SI")
- (set_attr "i387" "1")
+ (set_attr "unit" "i387")
(set_attr "ppro_uops" "few")])
;; FP compares, step 3
@@ -1560,7 +929,7 @@
(define_insn "x86_sahf_1"
[(set (reg:CC 17)
- (unspec:CC [(match_operand:HI 0 "register_operand" "a")] 10))]
+ (unspec:CC [(match_operand:HI 0 "register_operand" "a")] UNSPEC_SAHF))]
"!TARGET_64BIT"
"sahf"
[(set_attr "length" "1")
@@ -1591,7 +960,7 @@
&& SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[0])"
"* return output_fp_compare (insn, operands, 1, 0);"
- [(set_attr "type" "fcmp,sse")
+ [(set_attr "type" "fcmp,ssecmp")
(set_attr "mode" "unknownfp")
(set_attr "athlon_decode" "vector")])
@@ -1602,7 +971,7 @@
"SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[0])"
"* return output_fp_compare (insn, operands, 1, 0);"
- [(set_attr "type" "sse")
+ [(set_attr "type" "ssecmp")
(set_attr "mode" "unknownfp")
(set_attr "athlon_decode" "vector")])
@@ -1627,7 +996,7 @@
&& SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 1);"
- [(set_attr "type" "fcmp,sse")
+ [(set_attr "type" "fcmp,ssecmp")
(set_attr "mode" "unknownfp")
(set_attr "athlon_decode" "vector")])
@@ -1638,7 +1007,7 @@
"SSE_FLOAT_MODE_P (GET_MODE (operands[0]))
&& GET_MODE (operands[0]) == GET_MODE (operands[1])"
"* return output_fp_compare (insn, operands, 1, 1);"
- [(set_attr "type" "sse")
+ [(set_attr "type" "ssecmp")
(set_attr "mode" "unknownfp")
(set_attr "athlon_decode" "vector")])
@@ -1733,25 +1102,20 @@
(set_attr "mode" "SI")
(set_attr "length_immediate" "1")])
-; The first alternative is used only to compute proper length of instruction.
-; Reload's algorithm does not take into account the cost of spill instructions
-; needed to free register in given class, so avoid it from choosing the first
-; alternative when eax is not available.
-
(define_insn "*movsi_1"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=*?a,r,*?a,m,!*y,!rm,!*y,!*Y,!rm,!*Y")
- (match_operand:SI 1 "general_operand" "im,rinm,rinm,rin,rm,*y,*y,rm,*Y,*Y"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m,!*y,!rm,!*y,!*Y,!*Y,!rm")
+ (match_operand:SI 1 "general_operand" "rinm,rin,rm,*y,*y,*Y,rm,*Y"))]
"GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
{
switch (get_attr_type (insn))
{
- case TYPE_SSE:
- if (get_attr_mode (insn) == TImode)
+ case TYPE_SSEMOV:
+ if (get_attr_mode (insn) == MODE_TI)
return "movdqa\t{%1, %0|%0, %1}";
return "movd\t{%1, %0|%0, %1}";
- case TYPE_MMX:
- if (get_attr_mode (insn) == DImode)
+ case TYPE_MMXMOV:
+ if (get_attr_mode (insn) == MODE_DI)
return "movq\t{%1, %0|%0, %1}";
return "movd\t{%1, %0|%0, %1}";
@@ -1759,46 +1123,44 @@
return "lea{l}\t{%1, %0|%0, %1}";
default:
- if (flag_pic && SYMBOLIC_CONST (operands[1]))
+ if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1]))
abort();
return "mov{l}\t{%1, %0|%0, %1}";
}
}
[(set (attr "type")
- (cond [(eq_attr "alternative" "4,5,6")
- (const_string "mmx")
- (eq_attr "alternative" "7,8,9")
- (const_string "sse")
+ (cond [(eq_attr "alternative" "2,3,4")
+ (const_string "mmxmov")
+ (eq_attr "alternative" "5,6,7")
+ (const_string "ssemov")
(and (ne (symbol_ref "flag_pic") (const_int 0))
(match_operand:SI 1 "symbolic_operand" ""))
(const_string "lea")
]
(const_string "imov")))
- (set_attr "modrm" "0,*,0,*,*,*,*,*,*,*")
- (set_attr "mode" "SI,SI,SI,SI,SI,SI,DI,TI,SI,SI")])
+ (set_attr "mode" "SI,SI,SI,SI,DI,TI,SI,SI")])
;; Stores and loads of ax to arbitary constant address.
;; We fake an second form of instruction to force reload to load address
;; into register when rax is not available
(define_insn "*movabssi_1_rex64"
- [(set (mem:SI (match_operand:DI 0 "x86_64_movabs_operand" "i,r,r"))
- (match_operand:SI 1 "nonmemory_operand" "a,er,i"))]
- "TARGET_64BIT"
+ [(set (mem:SI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
+ (match_operand:SI 1 "nonmemory_operand" "a,er"))]
+ "TARGET_64BIT && ix86_check_movabs (insn, 0)"
"@
movabs{l}\t{%1, %P0|%P0, %1}
- mov{l}\t{%1, %a0|%a0, %1}
- movabs{l}\t{%1, %a0|%a0, %1}"
+ mov{l}\t{%1, %a0|%a0, %1}"
[(set_attr "type" "imov")
- (set_attr "modrm" "0,*,*")
- (set_attr "length_address" "8,0,0")
- (set_attr "length_immediate" "0,*,*")
+ (set_attr "modrm" "0,*")
+ (set_attr "length_address" "8,0")
+ (set_attr "length_immediate" "0,*")
(set_attr "memory" "store")
(set_attr "mode" "SI")])
(define_insn "*movabssi_2_rex64"
[(set (match_operand:SI 0 "register_operand" "=a,r")
(mem:SI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
- "TARGET_64BIT"
+ "TARGET_64BIT && ix86_check_movabs (insn, 1)"
"@
movabs{l}\t{%P1, %0|%0, %P1}
mov{l}\t{%a1, %0|%0, %a1}"
@@ -1848,14 +1210,9 @@
[(set_attr "type" "push")
(set_attr "mode" "QI")])
-; The first alternative is used only to compute proper length of instruction.
-; Reload's algorithm does not take into account the cost of spill instructions
-; needed to free register in given class, so avoid it from choosing the first
-; alternative when eax is not available.
-
(define_insn "*movhi_1"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=*?a,r,r,*?a,r,m")
- (match_operand:HI 1 "general_operand" "i,r,rn,rm,rm,rn"))]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
+ (match_operand:HI 1 "general_operand" "r,rn,rm,rn"))]
"GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
{
switch (get_attr_type (insn))
@@ -1872,59 +1229,57 @@
}
}
[(set (attr "type")
- (cond [(and (eq_attr "alternative" "0,1")
+ (cond [(and (eq_attr "alternative" "0")
(ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
(const_int 0))
(eq (symbol_ref "TARGET_HIMODE_MATH")
(const_int 0))))
(const_string "imov")
- (and (eq_attr "alternative" "2,3,4")
+ (and (eq_attr "alternative" "1,2")
(match_operand:HI 1 "aligned_operand" ""))
(const_string "imov")
(and (ne (symbol_ref "TARGET_MOVX")
(const_int 0))
- (eq_attr "alternative" "0,1,3,4"))
+ (eq_attr "alternative" "0,2"))
(const_string "imovx")
]
(const_string "imov")))
(set (attr "mode")
(cond [(eq_attr "type" "imovx")
(const_string "SI")
- (and (eq_attr "alternative" "2,3,4")
+ (and (eq_attr "alternative" "1,2")
(match_operand:HI 1 "aligned_operand" ""))
(const_string "SI")
- (and (eq_attr "alternative" "0,1")
+ (and (eq_attr "alternative" "0")
(ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
(const_int 0))
(eq (symbol_ref "TARGET_HIMODE_MATH")
(const_int 0))))
(const_string "SI")
]
- (const_string "HI")))
- (set_attr "modrm" "0,*,*,0,*,*")])
+ (const_string "HI")))])
;; Stores and loads of ax to arbitary constant address.
;; We fake an second form of instruction to force reload to load address
;; into register when rax is not available
(define_insn "*movabshi_1_rex64"
- [(set (mem:HI (match_operand:DI 0 "x86_64_movabs_operand" "i,r,r"))
- (match_operand:HI 1 "nonmemory_operand" "a,er,i"))]
- "TARGET_64BIT"
+ [(set (mem:HI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
+ (match_operand:HI 1 "nonmemory_operand" "a,er"))]
+ "TARGET_64BIT && ix86_check_movabs (insn, 0)"
"@
movabs{w}\t{%1, %P0|%P0, %1}
- mov{w}\t{%1, %a0|%a0, %1}
- movabs{w}\t{%1, %a0|%a0, %1}"
+ mov{w}\t{%1, %a0|%a0, %1}"
[(set_attr "type" "imov")
- (set_attr "modrm" "0,*,*")
- (set_attr "length_address" "8,0,0")
- (set_attr "length_immediate" "0,*,*")
+ (set_attr "modrm" "0,*")
+ (set_attr "length_address" "8,0")
+ (set_attr "length_immediate" "0,*")
(set_attr "memory" "store")
(set_attr "mode" "HI")])
(define_insn "*movabshi_2_rex64"
[(set (match_operand:HI 0 "register_operand" "=a,r")
(mem:HI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
- "TARGET_64BIT"
+ "TARGET_64BIT && ix86_check_movabs (insn, 1)"
"@
movabs{w}\t{%P1, %0|%0, %P1}
mov{w}\t{%a1, %0|%0, %a1}"
@@ -2122,7 +1477,7 @@
(define_expand "movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
(match_operand:QI 1 "general_operand" ""))]
- "! TARGET_PARTIAL_REG_STALL"
+ "! TARGET_PARTIAL_REG_STALL || optimize_size"
{
/* Don't generate memory->memory moves, go through a register. */
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
@@ -2132,7 +1487,7 @@
(define_insn "*movstrictqi_1"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
(match_operand:QI 1 "general_operand" "*qn,m"))]
- "! TARGET_PARTIAL_REG_STALL
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"mov{b}\t{%1, %0|%0, %1}"
[(set_attr "type" "imov")
@@ -2226,24 +1581,23 @@
;; We fake an second form of instruction to force reload to load address
;; into register when rax is not available
(define_insn "*movabsqi_1_rex64"
- [(set (mem:QI (match_operand:DI 0 "x86_64_movabs_operand" "i,r,r"))
- (match_operand:QI 1 "nonmemory_operand" "a,er,i"))]
- "TARGET_64BIT"
+ [(set (mem:QI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
+ (match_operand:QI 1 "nonmemory_operand" "a,er"))]
+ "TARGET_64BIT && ix86_check_movabs (insn, 0)"
"@
movabs{b}\t{%1, %P0|%P0, %1}
- mov{b}\t{%1, %a0|%a0, %1}
- movabs{b}\t{%1, %a0|%a0, %1}"
+ mov{b}\t{%1, %a0|%a0, %1}"
[(set_attr "type" "imov")
- (set_attr "modrm" "0,*,*")
- (set_attr "length_address" "8,0,0")
- (set_attr "length_immediate" "0,*,*")
+ (set_attr "modrm" "0,*")
+ (set_attr "length_address" "8,0")
+ (set_attr "length_immediate" "0,*")
(set_attr "memory" "store")
(set_attr "mode" "QI")])
(define_insn "*movabsqi_2_rex64"
[(set (match_operand:QI 0 "register_operand" "=a,r")
(mem:QI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
- "TARGET_64BIT"
+ "TARGET_64BIT && ix86_check_movabs (insn, 1)"
"@
movabs{b}\t{%P1, %0|%0, %P1}
mov{b}\t{%a1, %0|%0, %a1}"
@@ -2484,7 +1838,7 @@
movq\t{%1, %0|%0, %1}
movdqa\t{%1, %0|%0, %1}
movq\t{%1, %0|%0, %1}"
- [(set_attr "type" "*,*,mmx,mmx,sse,sse,sse")
+ [(set_attr "type" "*,*,mmx,mmx,ssemov,ssemov,ssemov")
(set_attr "mode" "DI,DI,DI,DI,DI,TI,DI")])
(define_split
@@ -2513,19 +1867,19 @@
{
switch (get_attr_type (insn))
{
- case TYPE_SSE:
+ case TYPE_SSEMOV:
if (register_operand (operands[0], DImode)
&& register_operand (operands[1], DImode))
return "movdqa\t{%1, %0|%0, %1}";
/* FALLTHRU */
- case TYPE_MMX:
+ case TYPE_MMXMOV:
return "movq\t{%1, %0|%0, %1}";
case TYPE_MULTI:
return "#";
case TYPE_LEA:
return "lea{q}\t{%a1, %0|%0, %a1}";
default:
- if (flag_pic && SYMBOLIC_CONST (operands[1]))
+ if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1]))
abort ();
if (get_attr_mode (insn) == MODE_SI)
return "mov{l}\t{%k1, %k0|%k0, %k1}";
@@ -2537,9 +1891,9 @@
}
[(set (attr "type")
(cond [(eq_attr "alternative" "5,6")
- (const_string "mmx")
- (eq_attr "alternative" "7,8")
- (const_string "sse")
+ (const_string "mmxmov")
+ (eq_attr "alternative" "7,8,9")
+ (const_string "ssemov")
(eq_attr "alternative" "4")
(const_string "multi")
(and (ne (symbol_ref "flag_pic") (const_int 0))
@@ -2557,7 +1911,7 @@
(define_insn "*movabsdi_1_rex64"
[(set (mem:DI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
(match_operand:DI 1 "nonmemory_operand" "a,er"))]
- "TARGET_64BIT"
+ "TARGET_64BIT && ix86_check_movabs (insn, 0)"
"@
movabs{q}\t{%1, %P0|%P0, %1}
mov{q}\t{%1, %a0|%a0, %1}"
@@ -2571,7 +1925,7 @@
(define_insn "*movabsdi_2_rex64"
[(set (match_operand:DI 0 "register_operand" "=a,r")
(mem:DI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
- "TARGET_64BIT"
+ "TARGET_64BIT && ix86_check_movabs (insn, 1)"
"@
movabs{q}\t{%P1, %0|%0, %P1}
mov{q}\t{%a1, %0|%0, %a1}"
@@ -2711,21 +2065,21 @@
;; %%% Kill this when call knows how to work this out.
(define_split
[(set (match_operand:SF 0 "push_operand" "")
- (match_operand:SF 1 "register_operand" ""))]
- "!TARGET_64BIT && ANY_FP_REGNO_P (REGNO (operands[1]))"
+ (match_operand:SF 1 "any_fp_register_operand" ""))]
+ "!TARGET_64BIT"
[(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -4)))
(set (mem:SF (reg:SI 7)) (match_dup 1))])
(define_split
[(set (match_operand:SF 0 "push_operand" "")
- (match_operand:SF 1 "register_operand" ""))]
- "TARGET_64BIT && ANY_FP_REGNO_P (REGNO (operands[1]))"
+ (match_operand:SF 1 "any_fp_register_operand" ""))]
+ "TARGET_64BIT"
[(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -8)))
(set (mem:SF (reg:DI 7)) (match_dup 1))])
(define_insn "*movsf_1"
[(set (match_operand:SF 0 "nonimmediate_operand" "=f#xr,m,f#xr,r#xf,m,x#rf,x#rf,x#rf,m,!*y,!rm,!*y")
- (match_operand:SF 1 "general_operand" "fm#rx,f#rx,G,rmF#fx,Fr#fx,H,x,xm#rf,x#rf,rm,*y,*y"))]
+ (match_operand:SF 1 "general_operand" "fm#rx,f#rx,G,rmF#fx,Fr#fx,C,x,xm#rf,x#rf,rm,*y,*y"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
&& (reload_in_progress || reload_completed
|| (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
@@ -2763,7 +2117,7 @@
case 4:
return "mov{l}\t{%1, %0|%0, %1}";
case 5:
- if (TARGET_SSE2)
+ if (TARGET_SSE2 && !TARGET_ATHLON)
return "pxor\t%0, %0";
else
return "xorps\t%0, %0";
@@ -2787,7 +2141,7 @@
abort();
}
}
- [(set_attr "type" "fmov,fmov,fmov,imov,imov,sse,sse,sse,sse,mmx,mmx,mmx")
+ [(set_attr "type" "fmov,fmov,fmov,imov,imov,ssemov,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov")
(set_attr "mode" "SF,SF,SF,SI,SI,TI,SF,SF,SF,SI,SI,DI")])
(define_insn "*swapsf"
@@ -2883,16 +2237,16 @@
;; %%% Kill this when call knows how to work this out.
(define_split
[(set (match_operand:DF 0 "push_operand" "")
- (match_operand:DF 1 "register_operand" ""))]
- "!TARGET_64BIT && reload_completed && ANY_FP_REGNO_P (REGNO (operands[1]))"
+ (match_operand:DF 1 "any_fp_register_operand" ""))]
+ "!TARGET_64BIT && reload_completed"
[(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8)))
(set (mem:DF (reg:SI 7)) (match_dup 1))]
"")
(define_split
[(set (match_operand:DF 0 "push_operand" "")
- (match_operand:DF 1 "register_operand" ""))]
- "TARGET_64BIT && reload_completed && ANY_FP_REGNO_P (REGNO (operands[1]))"
+ (match_operand:DF 1 "any_fp_register_operand" ""))]
+ "TARGET_64BIT && reload_completed"
[(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -8)))
(set (mem:DF (reg:DI 7)) (match_dup 1))]
"")
@@ -2910,7 +2264,7 @@
(define_insn "*movdf_nointeger"
[(set (match_operand:DF 0 "nonimmediate_operand" "=f#Y,m,f#Y,*r,o,Y#f,Y#f,Y#f,m")
- (match_operand:DF 1 "general_operand" "fm#Y,f#Y,G,*roF,F*r,H,Y#f,YHm#f,Y#f"))]
+ (match_operand:DF 1 "general_operand" "fm#Y,f#Y,G,*roF,F*r,C,Y#f,YHm#f,Y#f"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
&& (optimize_size || !TARGET_INTEGER_DFMODE_MOVES)
&& (reload_in_progress || reload_completed
@@ -2949,7 +2303,10 @@
case 4:
return "#";
case 5:
- return "pxor\t%0, %0";
+ if (TARGET_ATHLON)
+ return "xorpd\t%0, %0";
+ else
+ return "pxor\t%0, %0";
case 6:
if (TARGET_PARTIAL_REG_DEPENDENCY)
return "movapd\t{%1, %0|%0, %1}";
@@ -2963,12 +2320,12 @@
abort();
}
}
- [(set_attr "type" "fmov,fmov,fmov,multi,multi,sse,sse,sse,sse")
+ [(set_attr "type" "fmov,fmov,fmov,multi,multi,ssemov,ssemov,ssemov,ssemov")
(set_attr "mode" "DF,DF,DF,SI,SI,TI,DF,DF,DF")])
(define_insn "*movdf_integer"
[(set (match_operand:DF 0 "nonimmediate_operand" "=f#Yr,m,f#Yr,r#Yf,o,Y#rf,Y#rf,Y#rf,m")
- (match_operand:DF 1 "general_operand" "fm#Yr,f#Yr,G,roF#Yf,Fr#Yf,H,Y#rf,Ym#rf,Y#rf"))]
+ (match_operand:DF 1 "general_operand" "fm#Yr,f#Yr,G,roF#Yf,Fr#Yf,C,Y#rf,Ym#rf,Y#rf"))]
"(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
&& !optimize_size && TARGET_INTEGER_DFMODE_MOVES
&& (reload_in_progress || reload_completed
@@ -3008,7 +2365,10 @@
return "#";
case 5:
- return "pxor\t%0, %0";
+ if (TARGET_ATHLON)
+ return "xorpd\t%0, %0";
+ else
+ return "pxor\t%0, %0";
case 6:
if (TARGET_PARTIAL_REG_DEPENDENCY)
return "movapd\t{%1, %0|%0, %1}";
@@ -3022,7 +2382,7 @@
abort();
}
}
- [(set_attr "type" "fmov,fmov,fmov,multi,multi,sse,sse,sse,sse")
+ [(set_attr "type" "fmov,fmov,fmov,multi,multi,ssemov,ssemov,ssemov,ssemov")
(set_attr "mode" "DF,DF,DF,SI,SI,TI,DF,DF,DF")])
(define_split
@@ -3196,28 +2556,28 @@
&& (GET_MODE (operands[0]) == XFmode
|| GET_MODE (operands[0]) == TFmode
|| GET_MODE (operands[0]) == DFmode)
- && (!REG_P (operands[1]) || !ANY_FP_REGNO_P (REGNO (operands[1])))"
+ && !ANY_FP_REG_P (operands[1])"
[(const_int 0)]
"ix86_split_long_move (operands); DONE;")
(define_split
[(set (match_operand:XF 0 "push_operand" "")
- (match_operand:XF 1 "register_operand" ""))]
- "!TARGET_64BIT && ANY_FP_REGNO_P (REGNO (operands[1]))"
+ (match_operand:XF 1 "any_fp_register_operand" ""))]
+ "!TARGET_64BIT"
[(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12)))
(set (mem:XF (reg:SI 7)) (match_dup 1))])
(define_split
[(set (match_operand:TF 0 "push_operand" "")
- (match_operand:TF 1 "register_operand" ""))]
- "!TARGET_64BIT && ANY_FP_REGNO_P (REGNO (operands[1]))"
+ (match_operand:TF 1 "any_fp_register_operand" ""))]
+ "!TARGET_64BIT"
[(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16)))
(set (mem:TF (reg:SI 7)) (match_dup 1))])
(define_split
[(set (match_operand:TF 0 "push_operand" "")
- (match_operand:TF 1 "register_operand" ""))]
- "TARGET_64BIT && ANY_FP_REGNO_P (REGNO (operands[1]))"
+ (match_operand:TF 1 "any_fp_register_operand" ""))]
+ "TARGET_64BIT"
[(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -16)))
(set (mem:TF (reg:DI 7)) (match_dup 1))])
@@ -3969,15 +3329,15 @@
(define_split
[(set (match_operand:DF 0 "push_operand" "")
- (float_extend:DF (match_operand:SF 1 "register_operand" "")))]
- "!TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))"
+ (float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))]
+ "!TARGET_64BIT"
[(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8)))
(set (mem:DF (reg:SI 7)) (float_extend:DF (match_dup 1)))])
(define_split
[(set (match_operand:DF 0 "push_operand" "")
- (float_extend:DF (match_operand:SF 1 "register_operand" "")))]
- "TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))"
+ (float_extend:DF (match_operand:SF 1 "fp_register_operand" "")))]
+ "TARGET_64BIT"
[(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -8)))
(set (mem:DF (reg:DI 7)) (float_extend:DF (match_dup 1)))])
@@ -3989,8 +3349,8 @@
(define_split
[(set (match_operand:XF 0 "push_operand" "")
- (float_extend:XF (match_operand:SF 1 "register_operand" "")))]
- "!TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))"
+ (float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))]
+ "!TARGET_64BIT"
[(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12)))
(set (mem:XF (reg:SI 7)) (float_extend:XF (match_dup 1)))])
@@ -4002,15 +3362,15 @@
(define_split
[(set (match_operand:TF 0 "push_operand" "")
- (float_extend:TF (match_operand:SF 1 "register_operand" "")))]
- "!TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))"
+ (float_extend:TF (match_operand:SF 1 "fp_register_operand" "")))]
+ "!TARGET_64BIT"
[(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16)))
(set (mem:TF (reg:SI 7)) (float_extend:TF (match_dup 1)))])
(define_split
[(set (match_operand:TF 0 "push_operand" "")
- (float_extend:TF (match_operand:SF 1 "register_operand" "")))]
- "TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))"
+ (float_extend:TF (match_operand:SF 1 "fp_register_operand" "")))]
+ "TARGET_64BIT"
[(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -16)))
(set (mem:DF (reg:DI 7)) (float_extend:TF (match_dup 1)))])
@@ -4022,8 +3382,8 @@
(define_split
[(set (match_operand:XF 0 "push_operand" "")
- (float_extend:XF (match_operand:DF 1 "register_operand" "")))]
- "!TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))"
+ (float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))]
+ "!TARGET_64BIT"
[(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12)))
(set (mem:DF (reg:SI 7)) (float_extend:XF (match_dup 1)))])
@@ -4035,23 +3395,27 @@
(define_split
[(set (match_operand:TF 0 "push_operand" "")
- (float_extend:TF (match_operand:DF 1 "register_operand" "")))]
- "!TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))"
+ (float_extend:TF (match_operand:DF 1 "fp_register_operand" "")))]
+ "!TARGET_64BIT"
[(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16)))
(set (mem:TF (reg:SI 7)) (float_extend:XF (match_dup 1)))])
(define_split
[(set (match_operand:TF 0 "push_operand" "")
- (float_extend:TF (match_operand:DF 1 "register_operand" "")))]
- "TARGET_64BIT && FP_REGNO_P (REGNO (operands[1]))"
+ (float_extend:TF (match_operand:DF 1 "fp_register_operand" "")))]
+ "TARGET_64BIT"
[(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -16)))
(set (mem:TF (reg:DI 7)) (float_extend:TF (match_dup 1)))])
(define_expand "extendsfdf2"
[(set (match_operand:DF 0 "nonimmediate_operand" "")
- (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "")))]
+ (float_extend:DF (match_operand:SF 1 "general_operand" "")))]
"TARGET_80387 || TARGET_SSE2"
{
+ /* ??? Needed for compress_float_constant since all fp constants
+ are LEGITIMATE_CONSTANT_P. */
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (SFmode, operands[1]);
})
@@ -4086,7 +3450,7 @@
abort ();
}
}
- [(set_attr "type" "fmov,fmov,sse")
+ [(set_attr "type" "fmov,fmov,ssecvt")
(set_attr "mode" "SF,XF,DF")])
(define_insn "*extendsfdf2_1_sse_only"
@@ -4095,14 +3459,18 @@
"!TARGET_80387 && TARGET_SSE2
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"cvtss2sd\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
+ [(set_attr "type" "ssecvt")
(set_attr "mode" "DF")])
(define_expand "extendsfxf2"
[(set (match_operand:XF 0 "nonimmediate_operand" "")
- (float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "")))]
+ (float_extend:XF (match_operand:SF 1 "general_operand" "")))]
"!TARGET_64BIT && TARGET_80387"
{
+ /* ??? Needed for compress_float_constant since all fp constants
+ are LEGITIMATE_CONSTANT_P. */
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (SFmode, operands[1]);
})
@@ -4141,9 +3509,13 @@
(define_expand "extendsftf2"
[(set (match_operand:TF 0 "nonimmediate_operand" "")
- (float_extend:TF (match_operand:SF 1 "nonimmediate_operand" "")))]
+ (float_extend:TF (match_operand:SF 1 "general_operand" "")))]
"TARGET_80387"
{
+ /* ??? Needed for compress_float_constant since all fp constants
+ are LEGITIMATE_CONSTANT_P. */
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (SFmode, operands[1]);
})
@@ -4182,9 +3554,13 @@
(define_expand "extenddfxf2"
[(set (match_operand:XF 0 "nonimmediate_operand" "")
- (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "")))]
+ (float_extend:XF (match_operand:DF 1 "general_operand" "")))]
"!TARGET_64BIT && TARGET_80387"
{
+ /* ??? Needed for compress_float_constant since all fp constants
+ are LEGITIMATE_CONSTANT_P. */
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ operands[1] = validize_mem (force_const_mem (DFmode, operands[1]));
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (DFmode, operands[1]);
})
@@ -4223,9 +3599,13 @@
(define_expand "extenddftf2"
[(set (match_operand:TF 0 "nonimmediate_operand" "")
- (float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "")))]
+ (float_extend:TF (match_operand:DF 1 "general_operand" "")))]
"TARGET_80387"
{
+ /* ??? Needed for compress_float_constant since all fp constants
+ are LEGITIMATE_CONSTANT_P. */
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ operands[1] = validize_mem (force_const_mem (DFmode, operands[1]));
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (DFmode, operands[1]);
})
@@ -4325,7 +3705,7 @@
abort ();
}
}
- [(set_attr "type" "fmov,multi,multi,multi,sse")
+ [(set_attr "type" "fmov,multi,multi,multi,ssecvt")
(set_attr "mode" "SF,SF,SF,SF,DF")])
(define_insn "*truncdfsf2_2"
@@ -4348,7 +3728,7 @@
abort ();
}
}
- [(set_attr "type" "sse,fmov")
+ [(set_attr "type" "ssecvt,fmov")
(set_attr "mode" "DF,SF")])
(define_insn "truncdfsf2_3"
@@ -4371,7 +3751,7 @@
(match_operand:DF 1 "nonimmediate_operand" "mY")))]
"!TARGET_80387 && TARGET_SSE2"
"cvtsd2ss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
+ [(set_attr "type" "ssecvt")
(set_attr "mode" "DF")])
(define_split
@@ -4396,10 +3776,9 @@
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(float_truncate:SF
- (match_operand:DF 1 "register_operand" "")))
+ (match_operand:DF 1 "fp_register_operand" "")))
(clobber (match_operand:SF 2 "memory_operand" ""))]
- "TARGET_80387 && reload_completed
- && FP_REG_P (operands[1])"
+ "TARGET_80387 && reload_completed"
[(set (match_dup 2) (float_truncate:SF (match_dup 1)))
(set (match_dup 0) (match_dup 2))]
"")
@@ -4788,14 +4167,14 @@
(fix:DI (match_operand:SF 1 "nonimmediate_operand" "xm")))]
"TARGET_64BIT && TARGET_SSE"
"cvttss2si{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")])
(define_insn "fix_truncdfdi_sse"
[(set (match_operand:DI 0 "register_operand" "=r")
(fix:DI (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
"TARGET_64BIT && TARGET_SSE2"
"cvttsd2si{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")])
;; Signed conversion to SImode.
@@ -4896,14 +4275,14 @@
(fix:SI (match_operand:SF 1 "nonimmediate_operand" "xm")))]
"TARGET_SSE"
"cvttss2si\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")])
(define_insn "fix_truncdfsi_sse"
[(set (match_operand:SI 0 "register_operand" "=r")
(fix:SI (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
"TARGET_SSE2"
"cvttsd2si\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -5034,22 +4413,22 @@
;; %% Not used yet.
(define_insn "x86_fnstcw_1"
[(set (match_operand:HI 0 "memory_operand" "=m")
- (unspec:HI [(reg:HI 18)] 11))]
+ (unspec:HI [(reg:HI 18)] UNSPEC_FSTCW))]
"TARGET_80387"
"fnstcw\t%0"
[(set_attr "length" "2")
(set_attr "mode" "HI")
- (set_attr "i387" "1")
+ (set_attr "unit" "i387")
(set_attr "ppro_uops" "few")])
(define_insn "x86_fldcw_1"
[(set (reg:HI 18)
- (unspec:HI [(match_operand:HI 0 "memory_operand" "m")] 12))]
+ (unspec:HI [(match_operand:HI 0 "memory_operand" "m")] UNSPEC_FLDCW))]
"TARGET_80387"
"fldcw\t%0"
[(set_attr "length" "2")
(set_attr "mode" "HI")
- (set_attr "i387" "1")
+ (set_attr "unit" "i387")
(set_attr "athlon_decode" "vector")
(set_attr "ppro_uops" "few")])
@@ -5083,7 +4462,7 @@
fild%z1\t%1
#
cvtsi2ss\t{%1, %0|%0, %1}"
- [(set_attr "type" "fmov,multi,sse")
+ [(set_attr "type" "fmov,multi,ssecvt")
(set_attr "mode" "SF")
(set_attr "fp_int_src" "true")])
@@ -5092,7 +4471,7 @@
(float:SF (match_operand:SI 1 "nonimmediate_operand" "mr")))]
"TARGET_SSE"
"cvtsi2ss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
+ [(set_attr "type" "ssecvt")
(set_attr "mode" "SF")
(set_attr "fp_int_src" "true")])
@@ -5121,7 +4500,7 @@
fild%z1\t%1
#
cvtsi2ss{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "fmov,multi,sse")
+ [(set_attr "type" "fmov,multi,ssecvt")
(set_attr "mode" "SF")
(set_attr "fp_int_src" "true")])
@@ -5130,7 +4509,7 @@
(float:SF (match_operand:DI 1 "nonimmediate_operand" "mr")))]
"TARGET_64BIT && TARGET_SSE"
"cvtsi2ss{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
+ [(set_attr "type" "ssecvt")
(set_attr "mode" "SF")
(set_attr "fp_int_src" "true")])
@@ -5159,7 +4538,7 @@
fild%z1\t%1
#
cvtsi2sd\t{%1, %0|%0, %1}"
- [(set_attr "type" "fmov,multi,sse")
+ [(set_attr "type" "fmov,multi,ssecvt")
(set_attr "mode" "DF")
(set_attr "fp_int_src" "true")])
@@ -5168,7 +4547,7 @@
(float:DF (match_operand:SI 1 "nonimmediate_operand" "mr")))]
"TARGET_SSE2"
"cvtsi2sd\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
+ [(set_attr "type" "ssecvt")
(set_attr "mode" "DF")
(set_attr "fp_int_src" "true")])
@@ -5197,7 +4576,7 @@
fild%z1\t%1
#
cvtsi2sd{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "fmov,multi,sse")
+ [(set_attr "type" "fmov,multi,ssecvt")
(set_attr "mode" "DF")
(set_attr "fp_int_src" "true")])
@@ -5206,7 +4585,7 @@
(float:DF (match_operand:DI 1 "nonimmediate_operand" "mr")))]
"TARGET_SSE2"
"cvtsi2sd{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
+ [(set_attr "type" "ssecvt")
(set_attr "mode" "DF")
(set_attr "fp_int_src" "true")])
@@ -5278,10 +4657,9 @@
;; %%% Kill these when reload knows how to do it.
(define_split
- [(set (match_operand 0 "register_operand" "")
+ [(set (match_operand 0 "fp_register_operand" "")
(float (match_operand 1 "register_operand" "")))]
- "reload_completed && FLOAT_MODE_P (GET_MODE (operands[0]))
- && FP_REG_P (operands[0])"
+ "reload_completed && FLOAT_MODE_P (GET_MODE (operands[0]))"
[(const_int 0)]
{
operands[2] = ix86_force_to_memory (GET_MODE (operands[1]), operands[1]);
@@ -5320,7 +4698,8 @@
(match_operand:DI 2 "general_operand" "")))
(clobber (reg:CC 17))]
"!TARGET_64BIT && reload_completed"
- [(parallel [(set (reg:CC 17) (unspec:CC [(match_dup 1) (match_dup 2)] 12))
+ [(parallel [(set (reg:CC 17) (unspec:CC [(match_dup 1) (match_dup 2)]
+ UNSPEC_ADD_CARRY))
(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
(parallel [(set (match_dup 3)
(plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
@@ -5345,8 +4724,10 @@
(set_attr "ppro_uops" "few")])
(define_insn "*adddi3_cc_rex64"
- [(set (reg:CC 17) (unspec:CC [(match_operand:DI 1 "nonimmediate_operand" "%0,0")
- (match_operand:DI 2 "x86_64_general_operand" "re,rm")] 12))
+ [(set (reg:CC 17)
+ (unspec:CC [(match_operand:DI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:DI 2 "x86_64_general_operand" "re,rm")]
+ UNSPEC_ADD_CARRY))
(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
(plus:DI (match_dup 1) (match_dup 2)))]
"TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
@@ -5382,8 +4763,10 @@
(set_attr "ppro_uops" "few")])
(define_insn "*addsi3_cc"
- [(set (reg:CC 17) (unspec:CC [(match_operand:SI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "ri,rm")] 12))
+ [(set (reg:CC 17)
+ (unspec:CC [(match_operand:SI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "ri,rm")]
+ UNSPEC_ADD_CARRY))
(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
(plus:SI (match_dup 1) (match_dup 2)))]
"ix86_binary_operator_ok (PLUS, SImode, operands)"
@@ -5392,8 +4775,10 @@
(set_attr "mode" "SI")])
(define_insn "addqi3_cc"
- [(set (reg:CC 17) (unspec:CC [(match_operand:QI 1 "nonimmediate_operand" "%0,0")
- (match_operand:QI 2 "general_operand" "qi,qm")] 12))
+ [(set (reg:CC 17)
+ (unspec:CC [(match_operand:QI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "qi,qm")]
+ UNSPEC_ADD_CARRY))
(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
(plus:QI (match_dup 1) (match_dup 2)))]
"ix86_binary_operator_ok (PLUS, QImode, operands)"
@@ -5446,7 +4831,7 @@
(define_insn_and_split "*lea_general_1"
[(set (match_operand 0 "register_operand" "=r")
- (plus (plus (match_operand 1 "register_operand" "r")
+ (plus (plus (match_operand 1 "index_register_operand" "r")
(match_operand 2 "register_operand" "r"))
(match_operand 3 "immediate_operand" "i")))]
"(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
@@ -5478,7 +4863,7 @@
(define_insn_and_split "*lea_general_1_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
- (plus:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (plus:SI (plus:SI (match_operand:SI 1 "index_register_operand" "r")
(match_operand:SI 2 "register_operand" "r"))
(match_operand:SI 3 "immediate_operand" "i"))))]
"TARGET_64BIT"
@@ -5498,7 +4883,7 @@
(define_insn_and_split "*lea_general_2"
[(set (match_operand 0 "register_operand" "=r")
- (plus (mult (match_operand 1 "register_operand" "r")
+ (plus (mult (match_operand 1 "index_register_operand" "r")
(match_operand 2 "const248_operand" "i"))
(match_operand 3 "nonmemory_operand" "ri")))]
"(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
@@ -5528,7 +4913,7 @@
(define_insn_and_split "*lea_general_2_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
+ (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "r")
(match_operand:SI 2 "const248_operand" "n"))
(match_operand:SI 3 "nonmemory_operand" "ri"))))]
"TARGET_64BIT"
@@ -5547,7 +4932,7 @@
(define_insn_and_split "*lea_general_3"
[(set (match_operand 0 "register_operand" "=r")
- (plus (plus (mult (match_operand 1 "register_operand" "r")
+ (plus (plus (mult (match_operand 1 "index_register_operand" "r")
(match_operand 2 "const248_operand" "i"))
(match_operand 3 "register_operand" "r"))
(match_operand 4 "immediate_operand" "i")))]
@@ -5581,7 +4966,7 @@
(define_insn_and_split "*lea_general_3_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
- (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
+ (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "index_register_operand" "r")
(match_operand:SI 2 "const248_operand" "n"))
(match_operand:SI 3 "register_operand" "r"))
(match_operand:SI 4 "immediate_operand" "i"))))]
@@ -6318,9 +5703,7 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{w}\t%0";
- else if (operands[2] == constm1_rtx
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 65535))
+ else if (operands[2] == constm1_rtx)
return "dec{w}\t%0";
abort();
@@ -6359,9 +5742,7 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{w}\t%0";
- else if (operands[2] == constm1_rtx
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 65535))
+ else if (operands[2] == constm1_rtx)
return "dec{w}\t%0";
abort();
@@ -6401,9 +5782,7 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{w}\t%0";
- else if (operands[2] == constm1_rtx
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 65535))
+ else if (operands[2] == constm1_rtx)
return "dec{w}\t%0";
abort();
@@ -6440,9 +5819,7 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{w}\t%0";
- else if (operands[2] == constm1_rtx
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 65535))
+ else if (operands[2] == constm1_rtx)
return "dec{w}\t%0";
abort();
@@ -6478,9 +5855,7 @@
switch (get_attr_type (insn))
{
case TYPE_INCDEC:
- if (operands[2] == constm1_rtx
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 65535))
+ if (operands[2] == constm1_rtx)
return "inc{w}\t%0";
else if (operands[2] == const1_rtx)
return "dec{w}\t%0";
@@ -6522,9 +5897,7 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return "inc{w}\t%0";
- else if (operands[2] == constm1_rtx
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 65535))
+ else if (operands[2] == constm1_rtx)
return "dec{w}\t%0";
abort();
@@ -6573,9 +5946,7 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
- else if (operands[2] == constm1_rtx
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 255))
+ else if (operands[2] == constm1_rtx)
return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
abort();
@@ -6621,9 +5992,7 @@
case TYPE_INCDEC:
if (operands[2] == const1_rtx)
return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
- else if (operands[2] == constm1_rtx
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 255))
+ else if (operands[2] == constm1_rtx)
return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
abort();
@@ -6653,6 +6022,40 @@
(const_string "alu")))
(set_attr "mode" "QI,QI,SI")])
+(define_insn "*addqi_1_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
+ (plus:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "qn,qnm")))
+ (clobber (reg:CC 17))]
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+{
+ switch (get_attr_type (insn))
+ {
+ case TYPE_INCDEC:
+ if (operands[1] == const1_rtx)
+ return "inc{b}\t%0";
+ else if (operands[1] == constm1_rtx)
+ return "dec{b}\t%0";
+ abort();
+
+ default:
+ /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. */
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) < 0)
+ {
+ operands[2] = GEN_INT (-INTVAL (operands[2]));
+ return "sub{b}\t{%1, %0|%0, %1}";
+ }
+ return "add{b}\t{%1, %0|%0, %1}";
+ }
+}
+ [(set (attr "type")
+ (if_then_else (match_operand:QI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu1")))
+ (set_attr "mode" "QI")])
+
(define_insn "*addqi_2"
[(set (reg 17)
(compare
@@ -7184,6 +6587,17 @@
[(set_attr "type" "alu")
(set_attr "mode" "QI")])
+(define_insn "*subqi_1_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
+ (minus:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "qn,qmn")))
+ (clobber (reg:CC 17))]
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "sub{b}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "alu1")
+ (set_attr "mode" "QI")])
+
(define_insn "*subqi_2"
[(set (reg 17)
(compare
@@ -7822,7 +7236,7 @@
(use (match_dup 3))
(clobber (reg:CC 17))])]
{
- /* Avoid use of cltd in favour of a mov+shift. */
+ /* Avoid use of cltd in favor of a mov+shift. */
if (!TARGET_USE_CLTD && !optimize_size)
{
if (true_regnum (operands[1]))
@@ -7907,7 +7321,7 @@
(use (match_dup 3))
(clobber (reg:CC 17))])]
{
- /* Avoid use of cltd in favour of a mov+shift. */
+ /* Avoid use of cltd in favor of a mov+shift. */
if (!TARGET_USE_CLTD && !optimize_size)
{
if (true_regnum (operands[1]))
@@ -8180,8 +7594,7 @@
(const_int 8))
(match_operand 1 "const_int_operand" "n"))
(const_int 0)))]
- "(unsigned HOST_WIDE_INT) INTVAL (operands[1]) <= 0xff
- && ix86_match_ccmode (insn, CCNOmode)"
+ "ix86_match_ccmode (insn, CCNOmode)"
"test{b}\t{%1, %h0|%h0, %1}"
[(set_attr "type" "test")
(set_attr "mode" "QI")
@@ -8319,10 +7732,57 @@
mask = ((HOST_WIDE_INT)1 << (pos + len)) - 1;
mask &= ~(((HOST_WIDE_INT)1 << pos) - 1);
- operands[3] = gen_rtx_AND (mode, operands[0],
- GEN_INT (trunc_int_for_mode (mask, mode)));
+ operands[3] = gen_rtx_AND (mode, operands[0], gen_int_mode (mask, mode));
})
+;; Convert HImode/SImode test instructions with immediate to QImode ones.
+;; i386 does not allow to encode test with 8bit sign extended immediate, so
+;; this is relatively important trick.
+;; Do the converison only post-reload to avoid limiting of the register class
+;; to QI regs.
+(define_split
+ [(set (reg 17)
+ (compare
+ (and (match_operand 0 "register_operand" "")
+ (match_operand 1 "const_int_operand" ""))
+ (const_int 0)))]
+ "reload_completed
+ && QI_REG_P (operands[0])
+ && ((ix86_match_ccmode (insn, CCZmode)
+ && !(INTVAL (operands[1]) & ~(255 << 8)))
+ || (ix86_match_ccmode (insn, CCNOmode)
+ && !(INTVAL (operands[1]) & ~(127 << 8))))
+ && GET_MODE (operands[0]) != QImode"
+ [(set (reg:CCNO 17)
+ (compare:CCNO
+ (and:SI (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
+ (match_dup 1))
+ (const_int 0)))]
+ "operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_int_mode (INTVAL (operands[1]) >> 8, SImode);")
+
+(define_split
+ [(set (reg 17)
+ (compare
+ (and (match_operand 0 "nonimmediate_operand" "")
+ (match_operand 1 "const_int_operand" ""))
+ (const_int 0)))]
+ "reload_completed
+ && (!REG_P (operands[0]) || ANY_QI_REG_P (operands[0]))
+ && ((ix86_match_ccmode (insn, CCZmode)
+ && !(INTVAL (operands[1]) & ~255))
+ || (ix86_match_ccmode (insn, CCNOmode)
+ && !(INTVAL (operands[1]) & ~127)))
+ && GET_MODE (operands[0]) != QImode"
+ [(set (reg:CCNO 17)
+ (compare:CCNO
+ (and:QI (match_dup 0)
+ (match_dup 1))
+ (const_int 0)))]
+ "operands[0] = gen_lowpart (QImode, operands[0]);
+ operands[1] = gen_lowpart (QImode, operands[1]);")
+
+
;; %%% This used to optimize known byte-wide and operations to memory,
;; and sometimes to QImode registers. If this is considered useful,
;; it should be done with splitters.
@@ -8445,7 +7905,7 @@
(and (match_dup 0)
(const_int -65536)))
(clobber (reg:CC 17))]
- "optimize_size"
+ "optimize_size || (TARGET_FAST_PREFIX && !TARGET_PARTIAL_REG_STALL)"
[(set (strict_low_part (match_dup 1)) (const_int 0))]
"operands[1] = gen_lowpart (HImode, operands[0]);")
@@ -8591,7 +8051,8 @@
(and:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "qi,qmi")))
(clobber (reg:CC 17))]
- ""
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"and{b}\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
(set_attr "mode" "QI")])
@@ -8627,7 +8088,9 @@
(const_int 0)))
(set (strict_low_part (match_dup 0))
(and:QI (match_dup 0) (match_dup 1)))]
- "ix86_match_ccmode (insn, CCNOmode)"
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && ix86_match_ccmode (insn, CCNOmode)
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"and{b}\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
(set_attr "mode" "QI")])
@@ -8647,7 +8110,7 @@
(const_int 8))
(match_operand 2 "const_int_operand" "n")))
(clobber (reg:CC 17))]
- "(unsigned HOST_WIDE_INT)INTVAL (operands[2]) <= 0xff"
+ ""
"and{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
(set_attr "length_immediate" "1")
@@ -8675,8 +8138,7 @@
(const_int 8)
(const_int 8))
(match_dup 2)))]
- "ix86_match_ccmode (insn, CCNOmode)
- && (unsigned HOST_WIDE_INT)INTVAL (operands[2]) <= 0xff"
+ "ix86_match_ccmode (insn, CCNOmode)"
"and{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
(set_attr "length_immediate" "1")
@@ -8737,6 +8199,51 @@
[(set_attr "type" "alu")
(set_attr "length_immediate" "0")
(set_attr "mode" "QI")])
+
+;; Convert wide AND instructions with immediate operand to shorter QImode
+;; equivalents when possible.
+;; Don't do the splitting with memory operands, since it intoduces risc
+;; of memory mismatch stalls. We may want to do the splitting for optimizing
+;; for size, but that can (should?) be handled by generic code instead.
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (and (match_operand 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")))
+ (clobber (reg:CC 17))]
+ "reload_completed
+ && QI_REG_P (operands[0])
+ && (!TARGET_PARTIAL_REG_STALL || optimize_size)
+ && !(~INTVAL (operands[2]) & ~(255 << 8))
+ && GET_MODE (operands[0]) != QImode"
+ [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
+ (and:SI (zero_extract:SI (match_dup 1)
+ (const_int 8) (const_int 8))
+ (match_dup 2)))
+ (clobber (reg:CC 17))])]
+ "operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
+
+;; Since AND can be encoded with sign extended immediate, this is only
+;; profitable when 7th bit is not set.
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (and (match_operand 1 "general_operand" "")
+ (match_operand 2 "const_int_operand" "")))
+ (clobber (reg:CC 17))]
+ "reload_completed
+ && ANY_QI_REG_P (operands[0])
+ && (!TARGET_PARTIAL_REG_STALL || optimize_size)
+ && !(~INTVAL (operands[2]) & ~255)
+ && !(INTVAL (operands[2]) & 128)
+ && GET_MODE (operands[0]) != QImode"
+ [(parallel [(set (strict_low_part (match_dup 0))
+ (and:QI (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC 17))])]
+ "operands[0] = gen_lowpart (QImode, operands[0]);
+ operands[1] = gen_lowpart (QImode, operands[1]);
+ operands[2] = gen_lowpart (QImode, operands[2]);")
;; Logical inclusive OR instructions
@@ -8953,7 +8460,8 @@
(ior:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "qmi,qi")))
(clobber (reg:CC 17))]
- ""
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"or{b}\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
(set_attr "mode" "QI")])
@@ -8978,7 +8486,9 @@
(const_int 0)))
(set (strict_low_part (match_dup 0))
(ior:QI (match_dup 0) (match_dup 1)))]
- "ix86_match_ccmode (insn, CCNOmode)"
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && ix86_match_ccmode (insn, CCNOmode)
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"or{b}\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
(set_attr "mode" "QI")])
@@ -8995,6 +8505,118 @@
[(set_attr "type" "alu")
(set_attr "mode" "QI")])
+(define_insn "iorqi_ext_0"
+ [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
+ (const_int 8)
+ (const_int 8))
+ (ior:SI
+ (zero_extract:SI
+ (match_operand 1 "ext_register_operand" "0")
+ (const_int 8)
+ (const_int 8))
+ (match_operand 2 "const_int_operand" "n")))
+ (clobber (reg:CC 17))]
+ "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
+ "or{b}\t{%2, %h0|%h0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "length_immediate" "1")
+ (set_attr "mode" "QI")])
+
+(define_insn "*iorqi_ext_1"
+ [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
+ (const_int 8)
+ (const_int 8))
+ (ior:SI
+ (zero_extract:SI
+ (match_operand 1 "ext_register_operand" "0")
+ (const_int 8)
+ (const_int 8))
+ (zero_extend:SI
+ (match_operand:QI 2 "general_operand" "Qm"))))
+ (clobber (reg:CC 17))]
+ "!TARGET_64BIT
+ && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
+ "or{b}\t{%2, %h0|%h0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
+
+(define_insn "*iorqi_ext_1_rex64"
+ [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
+ (const_int 8)
+ (const_int 8))
+ (ior:SI
+ (zero_extract:SI
+ (match_operand 1 "ext_register_operand" "0")
+ (const_int 8)
+ (const_int 8))
+ (zero_extend:SI
+ (match_operand 2 "ext_register_operand" "Q"))))
+ (clobber (reg:CC 17))]
+ "TARGET_64BIT
+ && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
+ "or{b}\t{%2, %h0|%h0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
+
+(define_insn "*iorqi_ext_2"
+ [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
+ (const_int 8)
+ (const_int 8))
+ (ior:SI
+ (zero_extract:SI (match_operand 1 "ext_register_operand" "0")
+ (const_int 8)
+ (const_int 8))
+ (zero_extract:SI (match_operand 2 "ext_register_operand" "Q")
+ (const_int 8)
+ (const_int 8))))
+ (clobber (reg:CC 17))]
+ "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
+ "ior{b}\t{%h2, %h0|%h0, %h2}"
+ [(set_attr "type" "alu")
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
+
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (ior (match_operand 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")))
+ (clobber (reg:CC 17))]
+ "reload_completed
+ && QI_REG_P (operands[0])
+ && (!TARGET_PARTIAL_REG_STALL || optimize_size)
+ && !(INTVAL (operands[2]) & ~(255 << 8))
+ && GET_MODE (operands[0]) != QImode"
+ [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
+ (ior:SI (zero_extract:SI (match_dup 1)
+ (const_int 8) (const_int 8))
+ (match_dup 2)))
+ (clobber (reg:CC 17))])]
+ "operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
+
+;; Since OR can be encoded with sign extended immediate, this is only
+;; profitable when 7th bit is set.
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (ior (match_operand 1 "general_operand" "")
+ (match_operand 2 "const_int_operand" "")))
+ (clobber (reg:CC 17))]
+ "reload_completed
+ && ANY_QI_REG_P (operands[0])
+ && (!TARGET_PARTIAL_REG_STALL || optimize_size)
+ && !(INTVAL (operands[2]) & ~255)
+ && (INTVAL (operands[2]) & 128)
+ && GET_MODE (operands[0]) != QImode"
+ [(parallel [(set (strict_low_part (match_dup 0))
+ (ior:QI (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC 17))])]
+ "operands[0] = gen_lowpart (QImode, operands[0]);
+ operands[1] = gen_lowpart (QImode, operands[1]);
+ operands[2] = gen_lowpart (QImode, operands[2]);")
;; Logical XOR instructions
@@ -9210,11 +8832,77 @@
[(set_attr "type" "alu")
(set_attr "mode" "QI,QI,SI")])
+(define_insn "*xorqi_1_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
+ (xor:QI (match_dup 0)
+ (match_operand:QI 1 "general_operand" "qi,qmi")))
+ (clobber (reg:CC 17))]
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "xor{b}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "alu1")
+ (set_attr "mode" "QI")])
+
+(define_insn "xorqi_ext_0"
+ [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
+ (const_int 8)
+ (const_int 8))
+ (xor:SI
+ (zero_extract:SI
+ (match_operand 1 "ext_register_operand" "0")
+ (const_int 8)
+ (const_int 8))
+ (match_operand 2 "const_int_operand" "n")))
+ (clobber (reg:CC 17))]
+ "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
+ "xor{b}\t{%2, %h0|%h0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "length_immediate" "1")
+ (set_attr "mode" "QI")])
+
(define_insn "*xorqi_ext_1"
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
(const_int 8)
(const_int 8))
(xor:SI
+ (zero_extract:SI
+ (match_operand 1 "ext_register_operand" "0")
+ (const_int 8)
+ (const_int 8))
+ (zero_extend:SI
+ (match_operand:QI 2 "general_operand" "Qm"))))
+ (clobber (reg:CC 17))]
+ "!TARGET_64BIT
+ && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
+ "xor{b}\t{%2, %h0|%h0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
+
+(define_insn "*xorqi_ext_1_rex64"
+ [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
+ (const_int 8)
+ (const_int 8))
+ (xor:SI
+ (zero_extract:SI
+ (match_operand 1 "ext_register_operand" "0")
+ (const_int 8)
+ (const_int 8))
+ (zero_extend:SI
+ (match_operand 2 "ext_register_operand" "Q"))))
+ (clobber (reg:CC 17))]
+ "TARGET_64BIT
+ && (!TARGET_PARTIAL_REG_STALL || optimize_size)"
+ "xor{b}\t{%2, %h0|%h0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
+
+(define_insn "*xorqi_ext_2"
+ [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
+ (const_int 8)
+ (const_int 8))
+ (xor:SI
(zero_extract:SI (match_operand 1 "ext_register_operand" "0")
(const_int 8)
(const_int 8))
@@ -9222,7 +8910,7 @@
(const_int 8)
(const_int 8))))
(clobber (reg:CC 17))]
- ""
+ "(!TARGET_PARTIAL_REG_STALL || optimize_size)"
"xor{b}\t{%h2, %h0|%h0, %h2}"
[(set_attr "type" "alu")
(set_attr "length_immediate" "0")
@@ -9242,6 +8930,20 @@
[(set_attr "type" "alu")
(set_attr "mode" "QI")])
+(define_insn "*xorqi_2_slp"
+ [(set (reg 17)
+ (compare (xor:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
+ (match_operand:QI 1 "general_operand" "qim,qi"))
+ (const_int 0)))
+ (set (strict_low_part (match_dup 0))
+ (xor:QI (match_dup 0) (match_dup 1)))]
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && ix86_match_ccmode (insn, CCNOmode)
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "xor{b}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "alu1")
+ (set_attr "mode" "QI")])
+
(define_insn "*xorqi_cc_2"
[(set (reg 17)
(compare
@@ -9316,6 +9018,46 @@
(match_dup 2)))])]
""
"")
+
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (xor (match_operand 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")))
+ (clobber (reg:CC 17))]
+ "reload_completed
+ && QI_REG_P (operands[0])
+ && (!TARGET_PARTIAL_REG_STALL || optimize_size)
+ && !(INTVAL (operands[2]) & ~(255 << 8))
+ && GET_MODE (operands[0]) != QImode"
+ [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
+ (xor:SI (zero_extract:SI (match_dup 1)
+ (const_int 8) (const_int 8))
+ (match_dup 2)))
+ (clobber (reg:CC 17))])]
+ "operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ operands[2] = gen_int_mode ((INTVAL (operands[2]) >> 8) & 0xff, SImode);")
+
+;; Since XOR can be encoded with sign extended immediate, this is only
+;; profitable when 7th bit is set.
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (xor (match_operand 1 "general_operand" "")
+ (match_operand 2 "const_int_operand" "")))
+ (clobber (reg:CC 17))]
+ "reload_completed
+ && ANY_QI_REG_P (operands[0])
+ && (!TARGET_PARTIAL_REG_STALL || optimize_size)
+ && !(INTVAL (operands[2]) & ~255)
+ && (INTVAL (operands[2]) & 128)
+ && GET_MODE (operands[0]) != QImode"
+ [(parallel [(set (strict_low_part (match_dup 0))
+ (xor:QI (match_dup 1)
+ (match_dup 2)))
+ (clobber (reg:CC 17))])]
+ "operands[0] = gen_lowpart (QImode, operands[0]);
+ operands[1] = gen_lowpart (QImode, operands[1]);
+ operands[2] = gen_lowpart (QImode, operands[2]);")
;; Negation instructions
@@ -9519,8 +9261,7 @@
operands[0] = force_reg (SFmode, operands[0]);
emit_move_insn (reg,
gen_lowpart (SFmode,
- GEN_INT (trunc_int_for_mode (0x80000000,
- SImode))));
+ gen_int_mode (0x80000000, SImode)));
emit_insn (gen_negsf2_ifs (operands[0], operands[1], reg));
if (dest != operands[0])
emit_move_insn (dest, operands[0]);
@@ -9599,22 +9340,22 @@
"#")
(define_split
- [(set (match_operand:SF 0 "register_operand" "")
+ [(set (match_operand:SF 0 "fp_register_operand" "")
(neg:SF (match_operand:SF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed"
+ "TARGET_80387 && reload_completed"
[(set (match_dup 0)
(neg:SF (match_dup 1)))]
"")
(define_split
- [(set (match_operand:SF 0 "register_operand" "")
+ [(set (match_operand:SF 0 "register_and_not_fp_reg_operand" "")
(neg:SF (match_operand:SF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed && !FP_REGNO_P (REGNO (operands[0]))"
+ "TARGET_80387 && reload_completed"
[(parallel [(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1)))
(clobber (reg:CC 17))])]
- "operands[1] = GEN_INT (trunc_int_for_mode (0x80000000, SImode));
+ "operands[1] = gen_int_mode (0x80000000, SImode);
operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));")
(define_split
@@ -9631,7 +9372,7 @@
if (size >= 12)
size = 10;
operands[0] = adjust_address (operands[0], QImode, size - 1);
- operands[1] = GEN_INT (trunc_int_for_mode (0x80, QImode));
+ operands[1] = gen_int_mode (0x80, QImode);
})
(define_expand "negdf2"
@@ -9651,8 +9392,7 @@
in register. */
rtx reg = gen_reg_rtx (DFmode);
#if HOST_BITS_PER_WIDE_INT >= 64
- rtx imm = GEN_INT (trunc_int_for_mode(((HOST_WIDE_INT)1) << 63,
- DImode));
+ rtx imm = gen_int_mode (((HOST_WIDE_INT)1) << 63, DImode);
#else
rtx imm = immed_double_const (0, 0x80000000, DImode);
#endif
@@ -9688,9 +9428,9 @@
"#")
(define_insn "*negdf2_ifs_rex64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#fr,Y#fr,fm#Yr,r#Yf")
- (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#fr,0,0")))
- (use (match_operand:DF 2 "general_operand" "Y,0,*g#Yr,*rm"))
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#f,Y#f,fm#Y")
+ (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#f,0")))
+ (use (match_operand:DF 2 "general_operand" "Y,0,*g#Y*r"))
(clobber (reg:CC 17))]
"TARGET_64BIT && TARGET_SSE2
&& (reload_in_progress || reload_completed
@@ -9775,23 +9515,22 @@
"#")
(define_split
- [(set (match_operand:DF 0 "register_operand" "")
+ [(set (match_operand:DF 0 "fp_register_operand" "")
(neg:DF (match_operand:DF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed"
+ "TARGET_80387 && reload_completed"
[(set (match_dup 0)
(neg:DF (match_dup 1)))]
"")
(define_split
- [(set (match_operand:DF 0 "register_operand" "")
+ [(set (match_operand:DF 0 "register_and_not_fp_reg_operand" "")
(neg:DF (match_operand:DF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_80387 && reload_completed
- && !FP_REGNO_P (REGNO (operands[0]))"
+ "!TARGET_64BIT && TARGET_80387 && reload_completed"
[(parallel [(set (match_dup 3) (xor:SI (match_dup 3) (match_dup 4)))
(clobber (reg:CC 17))])]
- "operands[4] = GEN_INT (trunc_int_for_mode (0x80000000, SImode));
+ "operands[4] = gen_int_mode (0x80000000, SImode);
split_di (operands+0, 1, operands+2, operands+3);")
(define_expand "negxf2"
@@ -9820,19 +9559,19 @@
"#")
(define_split
- [(set (match_operand:XF 0 "register_operand" "")
+ [(set (match_operand:XF 0 "fp_register_operand" "")
(neg:XF (match_operand:XF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed"
+ "TARGET_80387 && reload_completed"
[(set (match_dup 0)
(neg:XF (match_dup 1)))]
"")
(define_split
- [(set (match_operand:XF 0 "register_operand" "")
+ [(set (match_operand:XF 0 "register_and_not_fp_reg_operand" "")
(neg:XF (match_operand:XF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed && !FP_REGNO_P (REGNO (operands[0]))"
+ "TARGET_80387 && reload_completed"
[(parallel [(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1)))
(clobber (reg:CC 17))])]
"operands[1] = GEN_INT (0x8000);
@@ -9850,19 +9589,19 @@
"#")
(define_split
- [(set (match_operand:TF 0 "register_operand" "")
+ [(set (match_operand:TF 0 "fp_register_operand" "")
(neg:TF (match_operand:TF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed"
+ "TARGET_80387 && reload_completed"
[(set (match_dup 0)
(neg:TF (match_dup 1)))]
"")
(define_split
- [(set (match_operand:TF 0 "register_operand" "")
+ [(set (match_operand:TF 0 "register_and_not_fp_reg_operand" "")
(neg:TF (match_operand:TF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed && !FP_REGNO_P (REGNO (operands[0]))"
+ "TARGET_80387 && reload_completed"
[(parallel [(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1)))
(clobber (reg:CC 17))])]
"operands[1] = GEN_INT (0x8000);
@@ -9982,8 +9721,7 @@
operands[0] = force_reg (SFmode, operands[0]);
emit_move_insn (reg,
gen_lowpart (SFmode,
- GEN_INT (trunc_int_for_mode (0x80000000,
- SImode))));
+ gen_int_mode (0x80000000, SImode)));
emit_insn (gen_abssf2_ifs (operands[0], operands[1], reg));
if (dest != operands[0])
emit_move_insn (dest, operands[0]);
@@ -10051,22 +9789,22 @@
"#")
(define_split
- [(set (match_operand:SF 0 "register_operand" "")
+ [(set (match_operand:SF 0 "fp_register_operand" "")
(abs:SF (match_operand:SF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "TARGET_80387 && FP_REGNO_P (REGNO (operands[0]))"
+ "TARGET_80387"
[(set (match_dup 0)
(abs:SF (match_dup 1)))]
"")
(define_split
- [(set (match_operand:SF 0 "register_operand" "")
+ [(set (match_operand:SF 0 "register_and_not_fp_reg_operand" "")
(abs:SF (match_operand:SF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed && !FP_REGNO_P (REGNO (operands[0]))"
+ "TARGET_80387 && reload_completed"
[(parallel [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 1)))
(clobber (reg:CC 17))])]
- "operands[1] = GEN_INT (trunc_int_for_mode (~0x80000000, SImode));
+ "operands[1] = gen_int_mode (~0x80000000, SImode);
operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));")
(define_split
@@ -10083,7 +9821,7 @@
if (size >= 12)
size = 10;
operands[0] = adjust_address (operands[0], QImode, size - 1);
- operands[1] = GEN_INT (trunc_int_for_mode (~0x80, QImode));
+ operands[1] = gen_int_mode (~0x80, QImode);
})
(define_expand "absdf2"
@@ -10103,8 +9841,7 @@
in register. */
rtx reg = gen_reg_rtx (DFmode);
#if HOST_BITS_PER_WIDE_INT >= 64
- rtx imm = GEN_INT (trunc_int_for_mode(((HOST_WIDE_INT)1) << 63,
- DImode));
+ rtx imm = gen_int_mode (((HOST_WIDE_INT)1) << 63, DImode);
#else
rtx imm = immed_double_const (0, 0x80000000, DImode);
#endif
@@ -10205,23 +9942,22 @@
"#")
(define_split
- [(set (match_operand:DF 0 "register_operand" "")
+ [(set (match_operand:DF 0 "fp_register_operand" "")
(abs:DF (match_operand:DF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed"
+ "TARGET_80387 && reload_completed"
[(set (match_dup 0)
(abs:DF (match_dup 1)))]
"")
(define_split
- [(set (match_operand:DF 0 "register_operand" "")
+ [(set (match_operand:DF 0 "register_and_not_fp_reg_operand" "")
(abs:DF (match_operand:DF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "!TARGET_64BIT && TARGET_80387 && reload_completed &&
- !FP_REGNO_P (REGNO (operands[0]))"
+ "!TARGET_64BIT && TARGET_80387 && reload_completed"
[(parallel [(set (match_dup 3) (and:SI (match_dup 3) (match_dup 4)))
(clobber (reg:CC 17))])]
- "operands[4] = GEN_INT (trunc_int_for_mode (~0x80000000, SImode));
+ "operands[4] = gen_int_mode (~0x80000000, SImode);
split_di (operands+0, 1, operands+2, operands+3);")
(define_expand "absxf2"
@@ -10250,19 +9986,19 @@
"#")
(define_split
- [(set (match_operand:XF 0 "register_operand" "")
+ [(set (match_operand:XF 0 "fp_register_operand" "")
(abs:XF (match_operand:XF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed"
+ "TARGET_80387 && reload_completed"
[(set (match_dup 0)
(abs:XF (match_dup 1)))]
"")
(define_split
- [(set (match_operand:XF 0 "register_operand" "")
+ [(set (match_operand:XF 0 "register_and_not_fp_reg_operand" "")
(abs:XF (match_operand:XF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed && !FP_REGNO_P (REGNO (operands[0]))"
+ "TARGET_80387 && reload_completed"
[(parallel [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 1)))
(clobber (reg:CC 17))])]
"operands[1] = GEN_INT (~0x8000);
@@ -10277,19 +10013,19 @@
"#")
(define_split
- [(set (match_operand:TF 0 "register_operand" "")
+ [(set (match_operand:TF 0 "fp_register_operand" "")
(abs:TF (match_operand:TF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "TARGET_80387 && FP_REGNO_P (REGNO (operands[0])) && reload_completed"
+ "TARGET_80387 && reload_completed"
[(set (match_dup 0)
(abs:TF (match_dup 1)))]
"")
(define_split
- [(set (match_operand:TF 0 "register_operand" "")
+ [(set (match_operand:TF 0 "register_and_not_any_fp_reg_operand" "")
(abs:TF (match_operand:TF 1 "register_operand" "")))
(clobber (reg:CC 17))]
- "TARGET_80387 && reload_completed && !FP_REGNO_P (REGNO (operands[0]))"
+ "TARGET_80387 && reload_completed"
[(parallel [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 1)))
(clobber (reg:CC 17))])]
"operands[1] = GEN_INT (~0x8000);
@@ -10643,7 +10379,7 @@
return "sal{q}\t{%b2, %0|%0, %b2}";
else if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 1
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+ && (TARGET_SHIFT1 || optimize_size))
return "sal{q}\t%0";
else
return "sal{q}\t{%2, %0|%0, %2}";
@@ -10672,8 +10408,7 @@
[(set (match_dup 0)
(mult:DI (match_dup 1)
(match_dup 2)))]
- "operands[2] = GEN_INT (trunc_int_for_mode (1 << INTVAL (operands[2]),
- DImode));")
+ "operands[2] = gen_int_mode (1 << INTVAL (operands[2]), DImode);")
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
@@ -10701,7 +10436,7 @@
return "sal{q}\t{%b2, %0|%0, %b2}";
else if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 1
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+ && (TARGET_SHIFT1 || optimize_size))
return "sal{q}\t%0";
else
return "sal{q}\t{%2, %0|%0, %2}";
@@ -10849,7 +10584,7 @@
return "sal{l}\t{%b2, %0|%0, %b2}";
else if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 1
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+ && (TARGET_SHIFT1 || optimize_size))
return "sal{l}\t%0";
else
return "sal{l}\t{%2, %0|%0, %2}";
@@ -10870,7 +10605,7 @@
;; Convert lea to the lea pattern to avoid flags dependency.
(define_split
[(set (match_operand 0 "register_operand" "")
- (ashift (match_operand 1 "register_operand" "")
+ (ashift (match_operand 1 "index_register_operand" "")
(match_operand:QI 2 "const_int_operand" "")))
(clobber (reg:CC 17))]
"reload_completed
@@ -10880,8 +10615,7 @@
rtx pat;
operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[2] = GEN_INT (trunc_int_for_mode (1 << INTVAL (operands[2]),
- Pmode));
+ operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
pat = gen_rtx_MULT (Pmode, operands[1], operands[2]);
if (Pmode != SImode)
pat = gen_rtx_SUBREG (SImode, pat, 0);
@@ -10889,6 +10623,26 @@
DONE;
})
+;; Rare case of shifting RSP is handled by generating move and shift
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (ashift (match_operand 1 "register_operand" "")
+ (match_operand:QI 2 "const_int_operand" "")))
+ (clobber (reg:CC 17))]
+ "reload_completed
+ && true_regnum (operands[0]) != true_regnum (operands[1])"
+ [(const_int 0)]
+{
+ rtx pat, clob;
+ emit_move_insn (operands[1], operands[0]);
+ pat = gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_ASHIFT (GET_MODE (operands[0]),
+ operands[0], operands[2]));
+ clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clob)));
+ DONE;
+})
+
(define_insn "*ashlsi3_1_zext"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(zero_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "0,r")
@@ -10911,7 +10665,7 @@
return "sal{l}\t{%b2, %k0|%k0, %b2}";
else if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 1
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+ && (TARGET_SHIFT1 || optimize_size))
return "sal{l}\t%k0";
else
return "sal{l}\t{%2, %k0|%k0, %2}";
@@ -10939,8 +10693,7 @@
[(set (match_dup 0) (zero_extend:DI (subreg:SI (mult:SI (match_dup 1) (match_dup 2)) 0)))]
{
operands[1] = gen_lowpart (Pmode, operands[1]);
- operands[2] = GEN_INT (trunc_int_for_mode (1 << INTVAL (operands[2]),
- Pmode));
+ operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
})
;; This pattern can't accept a variable shift count, since shifts by
@@ -10969,7 +10722,7 @@
return "sal{l}\t{%b2, %0|%0, %b2}";
else if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 1
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+ && (TARGET_SHIFT1 || optimize_size))
return "sal{l}\t%0";
else
return "sal{l}\t{%2, %0|%0, %2}";
@@ -11008,7 +10761,7 @@
return "sal{l}\t{%b2, %k0|%k0, %b2}";
else if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 1
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+ && (TARGET_SHIFT1 || optimize_size))
return "sal{l}\t%k0";
else
return "sal{l}\t{%2, %k0|%k0, %2}";
@@ -11053,7 +10806,7 @@
return "sal{w}\t{%b2, %0|%0, %b2}";
else if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 1
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+ && (TARGET_SHIFT1 || optimize_size))
return "sal{w}\t%0";
else
return "sal{w}\t{%2, %0|%0, %2}";
@@ -11091,7 +10844,7 @@
return "sal{w}\t{%b2, %0|%0, %b2}";
else if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 1
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+ && (TARGET_SHIFT1 || optimize_size))
return "sal{w}\t%0";
else
return "sal{w}\t{%2, %0|%0, %2}";
@@ -11133,7 +10886,7 @@
return "sal{w}\t{%b2, %0|%0, %b2}";
else if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 1
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+ && (TARGET_SHIFT1 || optimize_size))
return "sal{w}\t%0";
else
return "sal{w}\t{%2, %0|%0, %2}";
@@ -11189,7 +10942,7 @@
}
else if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 1
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+ && (TARGET_SHIFT1 || optimize_size))
{
if (get_attr_mode (insn) == MODE_SI)
return "sal{l}\t%0";
@@ -11245,7 +10998,7 @@
}
else if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 1
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+ && (TARGET_SHIFT1 || optimize_size))
{
if (get_attr_mode (insn) == MODE_SI)
return "sal{l}\t%0";
@@ -11297,7 +11050,7 @@
return "sal{b}\t{%b2, %0|%0, %b2}";
else if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 1
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+ && (TARGET_SHIFT1 || optimize_size))
return "sal{b}\t%0";
else
return "sal{b}\t{%2, %0|%0, %2}";
@@ -11353,7 +11106,7 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"sar{q}\t%0"
[(set_attr "type" "ishift")
(set (attr "length")
@@ -11385,7 +11138,7 @@
(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(ashiftrt:DI (match_dup 1) (match_dup 2)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)
+ && (TARGET_SHIFT1 || optimize_size)
&& ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
"sar{q}\t%0"
[(set_attr "type" "ishift")
@@ -11542,7 +11295,7 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"sar{l}\t%0"
[(set_attr "type" "ishift")
(set (attr "length")
@@ -11556,7 +11309,7 @@
(match_operand:QI 2 "const_int_1_operand" ""))))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"sar{l}\t%k0"
[(set_attr "type" "ishift")
(set_attr "length" "2")])
@@ -11597,7 +11350,7 @@
(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(ashiftrt:SI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)
+ && (TARGET_SHIFT1 || optimize_size)
&& ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
"sar{l}\t%0"
[(set_attr "type" "ishift")
@@ -11615,7 +11368,7 @@
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)
+ && (TARGET_SHIFT1 || optimize_size)
&& ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
"sar{l}\t%k0"
[(set_attr "type" "ishift")
@@ -11666,7 +11419,7 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (ASHIFTRT, HImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"sar{w}\t%0"
[(set_attr "type" "ishift")
(set (attr "length")
@@ -11698,7 +11451,7 @@
(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(ashiftrt:HI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)
+ && (TARGET_SHIFT1 || optimize_size)
&& ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
"sar{w}\t%0"
[(set_attr "type" "ishift")
@@ -11738,7 +11491,7 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"sar{b}\t%0"
[(set_attr "type" "ishift")
(set (attr "length")
@@ -11746,6 +11499,21 @@
(const_string "2")
(const_string "*")))])
+(define_insn "*ashrqi3_1_one_bit_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
+ (ashiftrt:QI (match_dup 0)
+ (match_operand:QI 1 "const_int_1_operand" "")))
+ (clobber (reg:CC 17))]
+ "ix86_binary_operator_ok (ASHIFTRT, QImode, operands)
+ && (! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && (TARGET_SHIFT1 || optimize_size)"
+ "sar{b}\t%0"
+ [(set_attr "type" "ishift1")
+ (set (attr "length")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "2")
+ (const_string "*")))])
+
(define_insn "*ashrqi3_1"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
@@ -11758,6 +11526,19 @@
[(set_attr "type" "ishift")
(set_attr "mode" "QI")])
+(define_insn "*ashrqi3_1_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
+ (ashiftrt:QI (match_dup 0)
+ (match_operand:QI 1 "nonmemory_operand" "I,c")))
+ (clobber (reg:CC 17))]
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ sar{b}\t{%1, %0|%0, %1}
+ sar{b}\t{%b1, %0|%0, %b1}"
+ [(set_attr "type" "ishift1")
+ (set_attr "mode" "QI")])
+
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
@@ -11770,7 +11551,7 @@
(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(ashiftrt:QI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)
+ && (TARGET_SHIFT1 || optimize_size)
&& ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
"sar{b}\t%0"
[(set_attr "type" "ishift")
@@ -11822,7 +11603,7 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"shr{q}\t%0"
[(set_attr "type" "ishift")
(set (attr "length")
@@ -11854,7 +11635,7 @@
(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(lshiftrt:DI (match_dup 1) (match_dup 2)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)
+ && (TARGET_SHIFT1 || optimize_size)
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{q}\t%0"
[(set_attr "type" "ishift")
@@ -11932,7 +11713,7 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"shr{l}\t%0"
[(set_attr "type" "ishift")
(set (attr "length")
@@ -11946,7 +11727,7 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"shr{l}\t%k0"
[(set_attr "type" "ishift")
(set_attr "length" "2")])
@@ -11988,7 +11769,7 @@
(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(lshiftrt:SI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)
+ && (TARGET_SHIFT1 || optimize_size)
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{l}\t%0"
[(set_attr "type" "ishift")
@@ -12006,7 +11787,7 @@
(set (match_operand:DI 0 "register_operand" "=r")
(lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
"TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)
+ && (TARGET_SHIFT1 || optimize_size)
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{l}\t%k0"
[(set_attr "type" "ishift")
@@ -12057,7 +11838,7 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"shr{w}\t%0"
[(set_attr "type" "ishift")
(set (attr "length")
@@ -12089,7 +11870,7 @@
(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
(lshiftrt:HI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)
+ && (TARGET_SHIFT1 || optimize_size)
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{w}\t%0"
[(set_attr "type" "ishift")
@@ -12129,7 +11910,7 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (LSHIFTRT, QImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"shr{b}\t%0"
[(set_attr "type" "ishift")
(set (attr "length")
@@ -12137,6 +11918,20 @@
(const_string "2")
(const_string "*")))])
+(define_insn "*lshrqi3_1_one_bit_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
+ (lshiftrt:QI (match_dup 0)
+ (match_operand:QI 1 "const_int_1_operand" "")))
+ (clobber (reg:CC 17))]
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && (TARGET_SHIFT1 || optimize_size)"
+ "shr{b}\t%0"
+ [(set_attr "type" "ishift1")
+ (set (attr "length")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "2")
+ (const_string "*")))])
+
(define_insn "*lshrqi3_1"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
@@ -12149,6 +11944,19 @@
[(set_attr "type" "ishift")
(set_attr "mode" "QI")])
+(define_insn "*lshrqi3_1_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
+ (lshiftrt:QI (match_dup 0)
+ (match_operand:QI 1 "nonmemory_operand" "I,c")))
+ (clobber (reg:CC 17))]
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ shr{b}\t{%1, %0|%0, %1}
+ shr{b}\t{%b1, %0|%0, %b1}"
+ [(set_attr "type" "ishift1")
+ (set_attr "mode" "QI")])
+
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
;; zero are optimized away.
@@ -12161,7 +11969,7 @@
(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(lshiftrt:QI (match_dup 1) (match_dup 2)))]
"ix86_match_ccmode (insn, CCGOCmode)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)
+ && (TARGET_SHIFT1 || optimize_size)
&& ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
"shr{b}\t%0"
[(set_attr "type" "ishift")
@@ -12203,9 +12011,9 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"rol{q}\t%0"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set (attr "length")
(if_then_else (match_operand:DI 0 "register_operand" "")
(const_string "2")
@@ -12220,7 +12028,7 @@
"@
rol{q}\t{%2, %0|%0, %2}
rol{q}\t{%b2, %0|%0, %b2}"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set_attr "mode" "DI")])
(define_expand "rotlsi3"
@@ -12237,9 +12045,9 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (ROTATE, SImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"rol{l}\t%0"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set (attr "length")
(if_then_else (match_operand:SI 0 "register_operand" "")
(const_string "2")
@@ -12252,9 +12060,9 @@
(match_operand:QI 2 "const_int_1_operand" ""))))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"rol{l}\t%k0"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set_attr "length" "2")])
(define_insn "*rotlsi3_1"
@@ -12266,7 +12074,7 @@
"@
rol{l}\t{%2, %0|%0, %2}
rol{l}\t{%b2, %0|%0, %b2}"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set_attr "mode" "SI")])
(define_insn "*rotlsi3_1_zext"
@@ -12279,7 +12087,7 @@
"@
rol{l}\t{%2, %k0|%k0, %2}
rol{l}\t{%b2, %k0|%k0, %b2}"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set_attr "mode" "SI")])
(define_expand "rotlhi3"
@@ -12296,9 +12104,9 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (ROTATE, HImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"rol{w}\t%0"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set (attr "length")
(if_then_else (match_operand 0 "register_operand" "")
(const_string "2")
@@ -12313,7 +12121,7 @@
"@
rol{w}\t{%2, %0|%0, %2}
rol{w}\t{%b2, %0|%0, %b2}"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set_attr "mode" "HI")])
(define_expand "rotlqi3"
@@ -12324,20 +12132,47 @@
"TARGET_QIMODE_MATH"
"ix86_expand_binary_operator (ROTATE, QImode, operands); DONE;")
+(define_insn "*rotlqi3_1_one_bit_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
+ (rotate:QI (match_dup 0)
+ (match_operand:QI 1 "const_int_1_operand" "")))
+ (clobber (reg:CC 17))]
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && (TARGET_SHIFT1 || optimize_size)"
+ "rol{b}\t%0"
+ [(set_attr "type" "rotate1")
+ (set (attr "length")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "2")
+ (const_string "*")))])
+
(define_insn "*rotlqi3_1_one_bit"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (ROTATE, QImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"rol{b}\t%0"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set (attr "length")
(if_then_else (match_operand 0 "register_operand" "")
(const_string "2")
(const_string "*")))])
+(define_insn "*rotlqi3_1_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
+ (rotate:QI (match_dup 0)
+ (match_operand:QI 1 "nonmemory_operand" "I,c")))
+ (clobber (reg:CC 17))]
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ rol{b}\t{%1, %0|%0, %1}
+ rol{b}\t{%b1, %0|%0, %b1}"
+ [(set_attr "type" "rotate1")
+ (set_attr "mode" "QI")])
+
(define_insn "*rotlqi3_1"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
@@ -12347,7 +12182,7 @@
"@
rol{b}\t{%2, %0|%0, %2}
rol{b}\t{%b2, %0|%0, %b2}"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set_attr "mode" "QI")])
(define_expand "rotrdi3"
@@ -12364,9 +12199,9 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"ror{q}\t%0"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set (attr "length")
(if_then_else (match_operand:DI 0 "register_operand" "")
(const_string "2")
@@ -12381,7 +12216,7 @@
"@
ror{q}\t{%2, %0|%0, %2}
ror{q}\t{%b2, %0|%0, %b2}"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set_attr "mode" "DI")])
(define_expand "rotrsi3"
@@ -12398,9 +12233,9 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (ROTATERT, SImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"ror{l}\t%0"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set (attr "length")
(if_then_else (match_operand:SI 0 "register_operand" "")
(const_string "2")
@@ -12413,9 +12248,9 @@
(match_operand:QI 2 "const_int_1_operand" ""))))
(clobber (reg:CC 17))]
"TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"ror{l}\t%k0"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set (attr "length")
(if_then_else (match_operand:SI 0 "register_operand" "")
(const_string "2")
@@ -12430,7 +12265,7 @@
"@
ror{l}\t{%2, %0|%0, %2}
ror{l}\t{%b2, %0|%0, %b2}"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set_attr "mode" "SI")])
(define_insn "*rotrsi3_1_zext"
@@ -12443,7 +12278,7 @@
"@
ror{l}\t{%2, %k0|%k0, %2}
ror{l}\t{%b2, %k0|%k0, %b2}"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set_attr "mode" "SI")])
(define_expand "rotrhi3"
@@ -12460,9 +12295,9 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (ROTATERT, HImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"ror{w}\t%0"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set (attr "length")
(if_then_else (match_operand 0 "register_operand" "")
(const_string "2")
@@ -12477,7 +12312,7 @@
"@
ror{w}\t{%2, %0|%0, %2}
ror{w}\t{%b2, %0|%0, %b2}"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
(set_attr "mode" "HI")])
(define_expand "rotrqi3"
@@ -12494,9 +12329,23 @@
(match_operand:QI 2 "const_int_1_operand" "")))
(clobber (reg:CC 17))]
"ix86_binary_operator_ok (ROTATERT, QImode, operands)
- && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+ && (TARGET_SHIFT1 || optimize_size)"
"ror{b}\t%0"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
+ (set (attr "length")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "2")
+ (const_string "*")))])
+
+(define_insn "*rotrqi3_1_one_bit_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
+ (rotatert:QI (match_dup 0)
+ (match_operand:QI 1 "const_int_1_operand" "")))
+ (clobber (reg:CC 17))]
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && (TARGET_SHIFT1 || optimize_size)"
+ "ror{b}\t%0"
+ [(set_attr "type" "rotate1")
(set (attr "length")
(if_then_else (match_operand 0 "register_operand" "")
(const_string "2")
@@ -12511,7 +12360,20 @@
"@
ror{b}\t{%2, %0|%0, %2}
ror{b}\t{%b2, %0|%0, %b2}"
- [(set_attr "type" "ishift")
+ [(set_attr "type" "rotate")
+ (set_attr "mode" "QI")])
+
+(define_insn "*rotrqi3_1_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
+ (rotatert:QI (match_dup 0)
+ (match_operand:QI 1 "nonmemory_operand" "I,c")))
+ (clobber (reg:CC 17))]
+ "(! TARGET_PARTIAL_REG_STALL || optimize_size)
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ ror{b}\t{%1, %0|%0, %1}
+ ror{b}\t{%b1, %0|%0, %b1}"
+ [(set_attr "type" "rotate1")
(set_attr "mode" "QI")])
;; Bit set / bit test instructions
@@ -12789,7 +12651,7 @@
(match_operand:SF 3 "nonimmediate_operand" "xm")]))]
"TARGET_SSE && reload_completed"
"cmp%D1ss\t{%3, %0|%0, %3}"
- [(set_attr "type" "sse")
+ [(set_attr "type" "ssecmp")
(set_attr "mode" "SF")])
(define_insn "*sse_setccdf"
@@ -12799,7 +12661,7 @@
(match_operand:DF 3 "nonimmediate_operand" "Ym")]))]
"TARGET_SSE2 && reload_completed"
"cmp%D1sd\t{%3, %0|%0, %3}"
- [(set_attr "type" "sse")
+ [(set_attr "type" "ssecmp")
(set_attr "mode" "DF")])
;; Basic conditional jump instructions.
@@ -12961,13 +12823,14 @@
""
"%+j%C1\t%l0"
[(set_attr "type" "ibr")
- (set (attr "prefix_0f")
+ (set_attr "modrm" "0")
+ (set (attr "length")
(if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -128))
+ (const_int -126))
(lt (minus (match_dup 0) (pc))
- (const_int 124)))
- (const_int 0)
- (const_int 1)))])
+ (const_int 128)))
+ (const_int 2)
+ (const_int 6)))])
(define_insn "*jcc_2"
[(set (pc)
@@ -12978,13 +12841,14 @@
""
"%+j%c1\t%l0"
[(set_attr "type" "ibr")
- (set (attr "prefix_0f")
+ (set_attr "modrm" "0")
+ (set (attr "length")
(if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -128))
+ (const_int -126))
(lt (minus (match_dup 0) (pc))
- (const_int 124)))
- (const_int 0)
- (const_int 1)))])
+ (const_int 128)))
+ (const_int 2)
+ (const_int 6)))])
;; In general it is not safe to assume too much about CCmode registers,
;; so simplify-rtx stops when it sees a second one. Under certain
@@ -13244,7 +13108,15 @@
(label_ref (match_operand 0 "" "")))]
""
"jmp\t%l0"
- [(set_attr "type" "ibr")])
+ [(set_attr "type" "ibr")
+ (set (attr "length")
+ (if_then_else (and (ge (minus (match_dup 0) (pc))
+ (const_int -126))
+ (lt (minus (match_dup 0) (pc))
+ (const_int 128)))
+ (const_int 2)
+ (const_int 5)))
+ (set_attr "modrm" "0")])
(define_expand "indirect_jump"
[(set (pc) (match_operand 0 "nonimmediate_operand" "rm"))]
@@ -13270,29 +13142,34 @@
(use (label_ref (match_operand 1 "" "")))])]
""
{
- /* In PIC mode, the table entries are stored GOT-relative. Convert
- the relative address to an absolute address. */
+ /* In PIC mode, the table entries are stored GOT (32-bit) or PC (64-bit)
+ relative. Convert the relative address to an absolute address. */
if (flag_pic)
{
+ rtx op0, op1;
+ enum rtx_code code;
+
if (TARGET_64BIT)
- operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
- gen_rtx_LABEL_REF (Pmode, operands[1]),
- NULL_RTX, 0,
- OPTAB_DIRECT);
- else if (HAVE_AS_GOTOFF_IN_DATA)
{
- operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
- pic_offset_table_rtx, NULL_RTX,
- 1, OPTAB_DIRECT);
- current_function_uses_pic_offset_table = 1;
+ code = PLUS;
+ op0 = operands[0];
+ op1 = gen_rtx_LABEL_REF (Pmode, operands[1]);
+ }
+ else if (TARGET_MACHO || HAVE_AS_GOTOFF_IN_DATA)
+ {
+ code = PLUS;
+ op0 = operands[0];
+ op1 = pic_offset_table_rtx;
}
else
{
- operands[0] = expand_simple_binop (Pmode, MINUS, pic_offset_table_rtx,
- operands[0], NULL_RTX, 1,
- OPTAB_DIRECT);
- current_function_uses_pic_offset_table = 1;
+ code = MINUS;
+ op0 = pic_offset_table_rtx;
+ op1 = operands[0];
}
+
+ operands[0] = expand_simple_binop (Pmode, code, op0, op1, NULL_RTX, 0,
+ OPTAB_DIRECT);
}
})
@@ -13357,14 +13234,17 @@
return "dec{l}\t%1\;%+jne\t%l0";
}
[(set_attr "ppro_uops" "many")
- (set (attr "type")
+ (set (attr "length")
(if_then_else (and (eq_attr "alternative" "0")
(and (ge (minus (match_dup 0) (pc))
- (const_int -128))
+ (const_int -126))
(lt (minus (match_dup 0) (pc))
- (const_int 124))))
- (const_string "ibr")
- (const_string "multi")))])
+ (const_int 128))))
+ (const_int 2)
+ (const_int 16)))
+ ;; We don't know the type before shorten branches. Optimistically expect
+ ;; the loop instruction to match.
+ (set (attr "type") (const_string "ibr"))])
(define_split
[(set (pc)
@@ -13474,21 +13354,8 @@
(match_operand:SI 3 "" "")))])]
"!TARGET_64BIT"
{
- if (operands[3] == const0_rtx)
- {
- emit_insn (gen_call (operands[0], operands[1], constm1_rtx));
- DONE;
- }
- /* Static functions and indirect calls don't need
- current_function_uses_pic_offset_table. */
- if (flag_pic
- && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
- && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
- current_function_uses_pic_offset_table = 1;
- if (! call_insn_operand (XEXP (operands[0], 0), Pmode))
- XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
- if (TARGET_64BIT)
- abort();
+ ix86_expand_call (NULL, operands[0], operands[1], operands[2], operands[3]);
+ DONE;
})
(define_insn "*call_pop_0"
@@ -13530,37 +13397,12 @@
[(call (match_operand:QI 0 "" "")
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))]
- ;; Operand 1 not used on the i386.
""
{
- rtx insn;
- /* Static functions and indirect calls don't need
- current_function_uses_pic_offset_table. */
- if (flag_pic
- && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
- && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
- current_function_uses_pic_offset_table = 1;
-
- if (! call_insn_operand (XEXP (operands[0], 0), Pmode))
- XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
- if (TARGET_64BIT && INTVAL (operands[2]) >= 0)
- {
- rtx reg = gen_rtx_REG (QImode, 0);
- emit_move_insn (reg, operands[2]);
- insn = emit_call_insn (gen_call_exp (operands[0], operands[1]));
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg);
- DONE;
- }
- insn = emit_call_insn (gen_call_exp (operands[0], operands[1]));
- DONE;
+ ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL);
+ DONE;
})
-(define_expand "call_exp"
- [(call (match_operand:QI 0 "" "")
- (match_operand 1 "" ""))]
- ""
- "")
-
(define_insn "*call_0"
[(call (mem:QI (match_operand 0 "constant_call_address_operand" ""))
(match_operand 1 "" ""))]
@@ -13612,7 +13454,6 @@
[(set_attr "type" "call")])
;; Call subroutine, returning value in operand 0
-;; (which must be a hard register).
(define_expand "call_value_pop"
[(parallel [(set (match_operand 0 "" "")
@@ -13623,20 +13464,9 @@
(match_operand:SI 4 "" "")))])]
"!TARGET_64BIT"
{
- if (operands[4] == const0_rtx)
- {
- emit_insn (gen_call_value (operands[0], operands[1], operands[2],
- constm1_rtx));
- DONE;
- }
- /* Static functions and indirect calls don't need
- current_function_uses_pic_offset_table. */
- if (flag_pic
- && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
- && ! SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
- current_function_uses_pic_offset_table = 1;
- if (! call_insn_operand (XEXP (operands[1], 0), Pmode))
- XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
+ ix86_expand_call (operands[0], operands[1], operands[2],
+ operands[3], operands[4]);
+ DONE;
})
(define_expand "call_value"
@@ -13647,36 +13477,10 @@
;; Operand 2 not used on the i386.
""
{
- rtx insn;
- /* Static functions and indirect calls don't need
- current_function_uses_pic_offset_table. */
- if (flag_pic
- && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
- && ! SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
- current_function_uses_pic_offset_table = 1;
- if (! call_insn_operand (XEXP (operands[1], 0), Pmode))
- XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
- if (TARGET_64BIT && INTVAL (operands[3]) >= 0)
- {
- rtx reg = gen_rtx_REG (QImode, 0);
- emit_move_insn (reg, operands[3]);
- insn = emit_call_insn (gen_call_value_exp (operands[0], operands[1],
- operands[2]));
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg);
- DONE;
- }
- insn = emit_call_insn (gen_call_value_exp (operands[0], operands[1],
- operands[2]));
+ ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL);
DONE;
})
-(define_expand "call_value_exp"
- [(set (match_operand 0 "" "")
- (call (match_operand:QI 1 "" "")
- (match_operand:SI 2 "" "")))]
- ""
- "")
-
;; Call subroutine returning any type.
(define_expand "untyped_call"
@@ -13693,12 +13497,10 @@
simply pretend the untyped call returns a complex long double
value. */
- emit_call_insn (TARGET_FLOAT_RETURNS_IN_80387
- ? gen_call_value (gen_rtx_REG (XCmode, FIRST_FLOAT_REG),
- operands[0], const0_rtx,
- GEN_INT (SSE_REGPARM_MAX - 1))
- : gen_call (operands[0], const0_rtx,
- GEN_INT (SSE_REGPARM_MAX - 1)));
+ ix86_expand_call ((TARGET_FLOAT_RETURNS_IN_80387
+ ? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL),
+ operands[0], const0_rtx, GEN_INT (SSE_REGPARM_MAX - 1),
+ NULL);
for (i = 0; i < XVECLEN (operands[2], 0); i++)
{
@@ -13710,7 +13512,7 @@
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 ());
+ emit_insn (gen_blockage (const0_rtx));
DONE;
})
@@ -13721,7 +13523,7 @@
;; all of memory. This blocks insns from being moved across this point.
(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] 0)]
+ [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_BLOCKAGE)]
""
""
[(set_attr "length" "0")])
@@ -13781,45 +13583,14 @@
""
"ix86_expand_prologue (); DONE;")
-(define_insn "prologue_set_got"
+(define_insn "set_got"
[(set (match_operand:SI 0 "register_operand" "=r")
- (unspec_volatile:SI
- [(plus:SI (match_dup 0)
- (plus:SI (match_operand:SI 1 "symbolic_operand" "")
- (minus:SI (pc) (match_operand 2 "" ""))))] 1))
+ (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
(clobber (reg:CC 17))]
"!TARGET_64BIT"
-{
- if (GET_CODE (operands[2]) == LABEL_REF)
- operands[2] = XEXP (operands[2], 0);
- if (TARGET_DEEP_BRANCH_PREDICTION)
- return "add{l}\t{%1, %0|%0, %1}";
- else
- return "add{l}\t{%1+[.-%X2], %0|%0, %a1+(.-%X2)}";
-}
- [(set_attr "type" "alu")
- ; Since this insn may have two constant operands, we must set the
- ; length manually.
- (set_attr "length_immediate" "4")
- (set_attr "mode" "SI")])
-
-(define_insn "prologue_get_pc"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec_volatile:SI [(plus:SI (pc) (match_operand 1 "" ""))] 2))]
- "!TARGET_64BIT"
-{
- if (GET_CODE (operands[1]) == LABEL_REF)
- operands[1] = XEXP (operands[1], 0);
- output_asm_insn ("call\t%X1", operands);
- if (! TARGET_DEEP_BRANCH_PREDICTION)
- {
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
- CODE_LABEL_NUMBER (operands[1]));
- return "pop{l}\t%0";
- }
- RET;
-}
- [(set_attr "type" "multi")])
+ { return output_set_got (operands[0]); }
+ [(set_attr "type" "multi")
+ (set_attr "length" "12")])
(define_expand "epilogue"
[(const_int 1)]
@@ -13832,11 +13603,10 @@
"ix86_expand_epilogue (0); DONE;")
(define_expand "eh_return"
- [(use (match_operand 0 "register_operand" ""))
- (use (match_operand 1 "register_operand" ""))]
+ [(use (match_operand 0 "register_operand" ""))]
""
{
- rtx tmp, sa = operands[0], ra = operands[1];
+ rtx tmp, sa = EH_RETURN_STACKADJ_RTX, ra = operands[0];
/* Tricky bit: we write the address of the handler to which we will
be returning into someone else's stack frame, one word below the
@@ -13855,7 +13625,8 @@
})
(define_insn_and_split "eh_return_si"
- [(unspec_volatile [(match_operand:SI 0 "register_operand" "c")] 13)]
+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "c")]
+ UNSPECV_EH_RETURN)]
"!TARGET_64BIT"
"#"
"reload_completed"
@@ -13863,7 +13634,8 @@
"ix86_expand_epilogue (2); DONE;")
(define_insn_and_split "eh_return_di"
- [(unspec_volatile [(match_operand:DI 0 "register_operand" "c")] 13)]
+ [(unspec_volatile [(match_operand:DI 0 "register_operand" "c")]
+ UNSPECV_EH_RETURN)]
"TARGET_64BIT"
"#"
"reload_completed"
@@ -13879,7 +13651,6 @@
[(set_attr "length_immediate" "0")
(set_attr "length" "1")
(set_attr "modrm" "0")
- (set_attr "modrm" "0")
(set_attr "athlon_decode" "vector")
(set_attr "ppro_uops" "few")])
@@ -13892,13 +13663,12 @@
[(set_attr "length_immediate" "0")
(set_attr "length" "1")
(set_attr "modrm" "0")
- (set_attr "modrm" "0")
(set_attr "athlon_decode" "vector")
(set_attr "ppro_uops" "few")])
(define_expand "ffssi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "")
- (ffs:SI (match_operand:SI 1 "general_operand" "")))]
+ (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
""
{
rtx out = gen_reg_rtx (SImode), tmp = gen_reg_rtx (SImode);
@@ -13987,7 +13757,7 @@
(compare:CCZ (match_operand:SI 1 "nonimmediate_operand" "rm")
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_dup 1)] 5))]
+ (unspec:SI [(match_dup 1)] UNSPEC_BSF))]
""
"bsf{l}\t{%1, %0|%0, %1}"
[(set_attr "prefix_0f" "1")
@@ -13996,6 +13766,173 @@
;; ffshi2 is not useful -- 4 word prefix ops are needed, which is larger
;; and slower than the two-byte movzx insn needed to do the work in SImode.
+;; Thread-local storage patterns for ELF.
+;;
+;; Note that these code sequences must appear exactly as shown
+;; in order to allow linker relaxation.
+
+(define_insn "*tls_global_dynamic_32_gnu"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ (match_operand:SI 2 "tls_symbolic_operand" "")
+ (match_operand:SI 3 "call_insn_operand" "")]
+ UNSPEC_TLS_GD))
+ (clobber (match_scratch:SI 4 "=d"))
+ (clobber (match_scratch:SI 5 "=c"))
+ (clobber (reg:CC 17))]
+ "!TARGET_64BIT && TARGET_GNU_TLS"
+ "lea{l}\t{%a2@TLSGD(,%1,1), %0|%0, %a2@TLSGD[%1*1]}\;call\t%P3"
+ [(set_attr "type" "multi")
+ (set_attr "length" "12")])
+
+(define_insn "*tls_global_dynamic_32_sun"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ (match_operand:SI 2 "tls_symbolic_operand" "")
+ (match_operand:SI 3 "call_insn_operand" "")]
+ UNSPEC_TLS_GD))
+ (clobber (match_scratch:SI 4 "=d"))
+ (clobber (match_scratch:SI 5 "=c"))
+ (clobber (reg:CC 17))]
+ "!TARGET_64BIT && TARGET_SUN_TLS"
+ "lea{l}\t{%a2@DTLNDX(%1), %4|%4, %a2@DTLNDX[%1]}
+ push{l}\t%4\;call\t%a2@TLSPLT\;pop{l}\t%4\;nop"
+ [(set_attr "type" "multi")
+ (set_attr "length" "14")])
+
+(define_expand "tls_global_dynamic_32"
+ [(parallel [(set (match_operand:SI 0 "register_operand" "")
+ (unspec:SI
+ [(match_dup 2)
+ (match_operand:SI 1 "tls_symbolic_operand" "")
+ (match_dup 3)]
+ UNSPEC_TLS_GD))
+ (clobber (match_scratch:SI 4 ""))
+ (clobber (match_scratch:SI 5 ""))
+ (clobber (reg:CC 17))])]
+ ""
+{
+ if (flag_pic)
+ operands[2] = pic_offset_table_rtx;
+ else
+ {
+ operands[2] = gen_reg_rtx (Pmode);
+ emit_insn (gen_set_got (operands[2]));
+ }
+ operands[3] = ix86_tls_get_addr ();
+})
+
+(define_insn "*tls_global_dynamic_64"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (call (mem:QI (match_operand:DI 2 "call_insn_operand" ""))
+ (match_operand:DI 3 "" "")))
+ (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+ UNSPEC_TLS_GD)]
+ "TARGET_64BIT"
+ ".byte\t0x66\;lea{q}\t{%a1@TLSGD(%%rip), %%rdi|%%rdi, %a1@TLSGD[%%rip]}\;.word\t0x6666\;rex64\;call\t%P2"
+ [(set_attr "type" "multi")
+ (set_attr "length" "16")])
+
+(define_expand "tls_global_dynamic_64"
+ [(parallel [(set (match_operand:DI 0 "register_operand" "")
+ (call (mem:QI (match_dup 2)) (const_int 0)))
+ (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+ UNSPEC_TLS_GD)])]
+ ""
+{
+ operands[2] = ix86_tls_get_addr ();
+})
+
+(define_insn "*tls_local_dynamic_base_32_gnu"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ (match_operand:SI 2 "call_insn_operand" "")]
+ UNSPEC_TLS_LD_BASE))
+ (clobber (match_scratch:SI 3 "=d"))
+ (clobber (match_scratch:SI 4 "=c"))
+ (clobber (reg:CC 17))]
+ "!TARGET_64BIT && TARGET_GNU_TLS"
+ "lea{l}\t{%&@TLSLDM(%1), %0|%0, %&@TLSLDM[%1]}\;call\t%P2"
+ [(set_attr "type" "multi")
+ (set_attr "length" "11")])
+
+(define_insn "*tls_local_dynamic_base_32_sun"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ (match_operand:SI 2 "call_insn_operand" "")]
+ UNSPEC_TLS_LD_BASE))
+ (clobber (match_scratch:SI 3 "=d"))
+ (clobber (match_scratch:SI 4 "=c"))
+ (clobber (reg:CC 17))]
+ "!TARGET_64BIT && TARGET_SUN_TLS"
+ "lea{l}\t{%&@TMDNX(%1), %3|%3, %&@TMDNX[%1]}
+ push{l}\t%3\;call\t%&@TLSPLT\;pop{l}\t%3"
+ [(set_attr "type" "multi")
+ (set_attr "length" "13")])
+
+(define_expand "tls_local_dynamic_base_32"
+ [(parallel [(set (match_operand:SI 0 "register_operand" "")
+ (unspec:SI [(match_dup 1) (match_dup 2)]
+ UNSPEC_TLS_LD_BASE))
+ (clobber (match_scratch:SI 3 ""))
+ (clobber (match_scratch:SI 4 ""))
+ (clobber (reg:CC 17))])]
+ ""
+{
+ if (flag_pic)
+ operands[1] = pic_offset_table_rtx;
+ else
+ {
+ operands[1] = gen_reg_rtx (Pmode);
+ emit_insn (gen_set_got (operands[1]));
+ }
+ operands[2] = ix86_tls_get_addr ();
+})
+
+(define_insn "*tls_local_dynamic_base_64"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (call (mem:QI (match_operand:DI 1 "call_insn_operand" ""))
+ (match_operand:DI 2 "" "")))
+ (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)]
+ "TARGET_64BIT"
+ "lea{q}\t{%&@TLSLD(%%rip), %%rdi|%%rdi, %&@TLSLD[%%rip]}\;call\t%P1"
+ [(set_attr "type" "multi")
+ (set_attr "length" "12")])
+
+(define_expand "tls_local_dynamic_base_64"
+ [(parallel [(set (match_operand:DI 0 "register_operand" "")
+ (call (mem:QI (match_dup 1)) (const_int 0)))
+ (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])]
+ ""
+{
+ operands[1] = ix86_tls_get_addr ();
+})
+
+;; Local dynamic of a single variable is a lose. Show combine how
+;; to convert that back to global dynamic.
+
+(define_insn_and_split "*tls_local_dynamic_32_once"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (plus:SI (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ (match_operand:SI 2 "call_insn_operand" "")]
+ UNSPEC_TLS_LD_BASE)
+ (const:SI (unspec:SI
+ [(match_operand:SI 3 "tls_symbolic_operand" "")]
+ UNSPEC_DTPOFF))))
+ (clobber (match_scratch:SI 4 "=d"))
+ (clobber (match_scratch:SI 5 "=c"))
+ (clobber (reg:CC 17))]
+ ""
+ "#"
+ ""
+ [(parallel [(set (match_dup 0)
+ (unspec:SI [(match_dup 1) (match_dup 3) (match_dup 2)]
+ UNSPEC_TLS_GD))
+ (clobber (match_dup 4))
+ (clobber (match_dup 5))
+ (clobber (reg:CC 17))])]
+ "")
+
;; These patterns match the binary 387 instructions for addM3, subM3,
;; mulM3 and divM3. There are three patterns for each of DFmode and
;; SFmode. The first is the normal insn, the second the same insn but
@@ -14032,7 +13969,9 @@
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
(if_then_else (eq_attr "alternative" "1")
- (const_string "sse")
+ (if_then_else (match_operand:SF 3 "mult_operator" "")
+ (const_string "ssemul")
+ (const_string "sseadd"))
(if_then_else (match_operand:SF 3 "mult_operator" "")
(const_string "fmul")
(const_string "fop"))))
@@ -14046,7 +13985,10 @@
"TARGET_SSE_MATH && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
- [(set_attr "type" "sse")
+ [(set (attr "type")
+ (if_then_else (match_operand:SF 3 "mult_operator" "")
+ (const_string "ssemul")
+ (const_string "sseadd")))
(set_attr "mode" "SF")])
(define_insn "*fop_df_comm_nosse"
@@ -14075,7 +14017,9 @@
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
(if_then_else (eq_attr "alternative" "1")
- (const_string "sse")
+ (if_then_else (match_operand:SF 3 "mult_operator" "")
+ (const_string "ssemul")
+ (const_string "sseadd"))
(if_then_else (match_operand:SF 3 "mult_operator" "")
(const_string "fmul")
(const_string "fop"))))
@@ -14090,7 +14034,10 @@
&& GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
- [(set_attr "type" "sse")
+ [(set (attr "type")
+ (if_then_else (match_operand:SF 3 "mult_operator" "")
+ (const_string "ssemul")
+ (const_string "sseadd")))
(set_attr "mode" "DF")])
(define_insn "*fop_xf_comm"
@@ -14148,8 +14095,14 @@
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
- (cond [(eq_attr "alternative" "2")
- (const_string "sse")
+ (cond [(and (eq_attr "alternative" "2")
+ (match_operand:SF 3 "mult_operator" ""))
+ (const_string "ssemul")
+ (and (eq_attr "alternative" "2")
+ (match_operand:SF 3 "div_operator" ""))
+ (const_string "ssediv")
+ (eq_attr "alternative" "2")
+ (const_string "sseadd")
(match_operand:SF 3 "mult_operator" "")
(const_string "fmul")
(match_operand:SF 3 "div_operator" "")
@@ -14166,7 +14119,13 @@
"TARGET_SSE_MATH
&& GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'"
"* return output_387_binary_op (insn, operands);"
- [(set_attr "type" "sse")
+ [(set (attr "type")
+ (cond [(match_operand:SF 3 "mult_operator" "")
+ (const_string "ssemul")
+ (match_operand:SF 3 "div_operator" "")
+ (const_string "ssediv")
+ ]
+ (const_string "sseadd")))
(set_attr "mode" "SF")])
;; ??? Add SSE splitters for these!
@@ -14218,7 +14177,7 @@
[(set (attr "type")
(cond [(match_operand:DF 3 "mult_operator" "")
(const_string "fmul")
- (match_operand:DF 3 "div_operator" "")
+ (match_operand:DF 3 "div_operator" "")
(const_string "fdiv")
]
(const_string "fop")))
@@ -14235,8 +14194,14 @@
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"* return output_387_binary_op (insn, operands);"
[(set (attr "type")
- (cond [(eq_attr "alternative" "2")
- (const_string "sse")
+ (cond [(and (eq_attr "alternative" "2")
+ (match_operand:SF 3 "mult_operator" ""))
+ (const_string "ssemul")
+ (and (eq_attr "alternative" "2")
+ (match_operand:SF 3 "div_operator" ""))
+ (const_string "ssediv")
+ (eq_attr "alternative" "2")
+ (const_string "sseadd")
(match_operand:DF 3 "mult_operator" "")
(const_string "fmul")
(match_operand:DF 3 "div_operator" "")
@@ -14253,7 +14218,14 @@
"TARGET_SSE2 && TARGET_SSE_MATH
&& GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'"
"* return output_387_binary_op (insn, operands);"
- [(set_attr "type" "sse")])
+ [(set_attr "mode" "DF")
+ (set (attr "type")
+ (cond [(match_operand:SF 3 "mult_operator" "")
+ (const_string "ssemul")
+ (match_operand:SF 3 "div_operator" "")
+ (const_string "ssediv")
+ ]
+ (const_string "sseadd")))])
;; ??? Add SSE splitters for these!
(define_insn "*fop_df_2"
@@ -14760,7 +14732,7 @@
(define_insn "sindf2"
[(set (match_operand:DF 0 "register_operand" "=f")
- (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
+ (unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_SIN))]
"! TARGET_NO_FANCY_MATH_387 && TARGET_80387
&& flag_unsafe_math_optimizations"
"fsin"
@@ -14769,7 +14741,7 @@
(define_insn "sinsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))]
+ (unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_SIN))]
"! TARGET_NO_FANCY_MATH_387 && TARGET_80387
&& flag_unsafe_math_optimizations"
"fsin"
@@ -14779,7 +14751,8 @@
(define_insn "*sinextendsfdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
(unspec:DF [(float_extend:DF
- (match_operand:SF 1 "register_operand" "0"))] 1))]
+ (match_operand:SF 1 "register_operand" "0"))]
+ UNSPEC_SIN))]
"! TARGET_NO_FANCY_MATH_387 && TARGET_80387
&& flag_unsafe_math_optimizations"
"fsin"
@@ -14788,7 +14761,7 @@
(define_insn "sinxf2"
[(set (match_operand:XF 0 "register_operand" "=f")
- (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))]
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_SIN))]
"!TARGET_64BIT && TARGET_80387 && !TARGET_NO_FANCY_MATH_387
&& flag_unsafe_math_optimizations"
"fsin"
@@ -14797,7 +14770,7 @@
(define_insn "sintf2"
[(set (match_operand:TF 0 "register_operand" "=f")
- (unspec:TF [(match_operand:TF 1 "register_operand" "0")] 1))]
+ (unspec:TF [(match_operand:TF 1 "register_operand" "0")] UNSPEC_SIN))]
"! TARGET_NO_FANCY_MATH_387 && TARGET_80387
&& flag_unsafe_math_optimizations"
"fsin"
@@ -14806,7 +14779,7 @@
(define_insn "cosdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
- (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
+ (unspec:DF [(match_operand:DF 1 "register_operand" "0")] UNSPEC_COS))]
"! TARGET_NO_FANCY_MATH_387 && TARGET_80387
&& flag_unsafe_math_optimizations"
"fcos"
@@ -14815,7 +14788,7 @@
(define_insn "cossf2"
[(set (match_operand:SF 0 "register_operand" "=f")
- (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))]
+ (unspec:SF [(match_operand:SF 1 "register_operand" "0")] UNSPEC_COS))]
"! TARGET_NO_FANCY_MATH_387 && TARGET_80387
&& flag_unsafe_math_optimizations"
"fcos"
@@ -14825,7 +14798,8 @@
(define_insn "*cosextendsfdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
(unspec:DF [(float_extend:DF
- (match_operand:SF 1 "register_operand" "0"))] 2))]
+ (match_operand:SF 1 "register_operand" "0"))]
+ UNSPEC_COS))]
"! TARGET_NO_FANCY_MATH_387 && TARGET_80387
&& flag_unsafe_math_optimizations"
"fcos"
@@ -14834,8 +14808,8 @@
(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
+ (unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_COS))]
+ "!TARGET_64BIT && ! TARGET_NO_FANCY_MATH_387 && TARGET_80387
&& flag_unsafe_math_optimizations"
"fcos"
[(set_attr "type" "fpspc")
@@ -14843,7 +14817,7 @@
(define_insn "costf2"
[(set (match_operand:TF 0 "register_operand" "=f")
- (unspec:TF [(match_operand:TF 1 "register_operand" "0")] 2))]
+ (unspec:TF [(match_operand:TF 1 "register_operand" "0")] UNSPEC_COS))]
"! TARGET_NO_FANCY_MATH_387 && TARGET_80387
&& flag_unsafe_math_optimizations"
"fcos"
@@ -15737,7 +15711,7 @@
[(set (match_operand:SI 0 "register_operand" "")
(unspec:SI [(match_operand:BLK 1 "general_operand" "")
(match_operand:QI 2 "immediate_operand" "")
- (match_operand 3 "immediate_operand" "")] 0))]
+ (match_operand 3 "immediate_operand" "")] UNSPEC_SCAS))]
""
{
if (ix86_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
@@ -15750,7 +15724,7 @@
[(set (match_operand:DI 0 "register_operand" "")
(unspec:DI [(match_operand:BLK 1 "general_operand" "")
(match_operand:QI 2 "immediate_operand" "")
- (match_operand 3 "immediate_operand" "")] 0))]
+ (match_operand 3 "immediate_operand" "")] UNSPEC_SCAS))]
""
{
if (ix86_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
@@ -15764,7 +15738,7 @@
(unspec:SI [(mem:BLK (match_operand:SI 5 "register_operand" "1"))
(match_operand:QI 2 "register_operand" "a")
(match_operand:SI 3 "immediate_operand" "i")
- (match_operand:SI 4 "register_operand" "0")] 0))
+ (match_operand:SI 4 "register_operand" "0")] UNSPEC_SCAS))
(use (reg:SI 19))
(clobber (match_operand:SI 1 "register_operand" "=D"))
(clobber (reg:CC 17))]
@@ -15779,7 +15753,7 @@
(unspec:DI [(mem:BLK (match_operand:DI 5 "register_operand" "1"))
(match_operand:QI 2 "register_operand" "a")
(match_operand:DI 3 "immediate_operand" "i")
- (match_operand:DI 4 "register_operand" "0")] 0))
+ (match_operand:DI 4 "register_operand" "0")] UNSPEC_SCAS))
(use (reg:SI 19))
(clobber (match_operand:DI 1 "register_operand" "=D"))
(clobber (reg:CC 17))]
@@ -15895,6 +15869,7 @@
; Since we don't have the proper number of operands for an alu insn,
; fill in all the blanks.
[(set_attr "type" "alu")
+ (set_attr "pent_pair" "pu")
(set_attr "memory" "none")
(set_attr "imm_disp" "false")
(set_attr "mode" "DI")
@@ -15937,6 +15912,7 @@
; Since we don't have the proper number of operands for an alu insn,
; fill in all the blanks.
[(set_attr "type" "alu")
+ (set_attr "pent_pair" "pu")
(set_attr "memory" "none")
(set_attr "imm_disp" "false")
(set_attr "mode" "SI")
@@ -16043,12 +16019,12 @@
(set_attr "mode" "DF")])
(define_split
- [(set (match_operand:DF 0 "register_operand" "")
+ [(set (match_operand:DF 0 "register_and_not_any_fp_reg_operand" "")
(if_then_else:DF (match_operator 1 "fcmov_comparison_operator"
[(match_operand 4 "" "") (const_int 0)])
(match_operand:DF 2 "nonimmediate_operand" "")
(match_operand:DF 3 "nonimmediate_operand" "")))]
- "!TARGET_64BIT && !ANY_FP_REG_P (operands[0]) && reload_completed"
+ "!TARGET_64BIT && reload_completed"
[(set (match_dup 2)
(if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)])
(match_dup 5)
@@ -16156,13 +16132,13 @@
;; We can't represent the LT test directly. Do this by swapping the operands.
(define_split
- [(set (match_operand:SF 0 "register_operand" "")
+ [(set (match_operand:SF 0 "fp_register_operand" "")
(if_then_else:SF (lt (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "register_operand" ""))
(match_operand:SF 3 "register_operand" "")
(match_operand:SF 4 "register_operand" "")))
(clobber (reg:CC 17))]
- "FP_REG_P (operands[0]) && reload_completed
+ "reload_completed
&& ((operands_match_p (operands[1], operands[3])
&& operands_match_p (operands[2], operands[4]))
|| (operands_match_p (operands[1], operands[4])
@@ -16238,13 +16214,13 @@
;; We can't represent the LT test directly. Do this by swapping the operands.
(define_split
- [(set (match_operand:DF 0 "register_operand" "")
+ [(set (match_operand:DF 0 "fp_register_operand" "")
(if_then_else:DF (lt (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "register_operand" ""))
(match_operand:DF 3 "register_operand" "")
(match_operand:DF 4 "register_operand" "")))
(clobber (reg:CC 17))]
- "FP_REG_P (operands[0]) && reload_completed
+ "reload_completed
&& ((operands_match_p (operands[1], operands[3])
&& operands_match_p (operands[2], operands[4]))
|| (operands_match_p (operands[1], operands[4])
@@ -16319,13 +16295,13 @@
(match_dup 2)))])
(define_split
- [(set (match_operand:SF 0 "register_operand" "")
+ [(set (match_operand:SF 0 "fp_register_operand" "")
(if_then_else:SF (gt (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "register_operand" ""))
(match_operand:SF 3 "register_operand" "")
(match_operand:SF 4 "register_operand" "")))
(clobber (reg:CC 17))]
- "FP_REG_P (operands[0]) && reload_completed
+ "reload_completed
&& ((operands_match_p (operands[1], operands[3])
&& operands_match_p (operands[2], operands[4]))
|| (operands_match_p (operands[1], operands[4])
@@ -16400,13 +16376,13 @@
(match_dup 2)))])
(define_split
- [(set (match_operand:DF 0 "register_operand" "")
+ [(set (match_operand:DF 0 "fp_register_operand" "")
(if_then_else:DF (gt (match_operand:DF 1 "register_operand" "")
(match_operand:DF 2 "register_operand" ""))
(match_operand:DF 3 "register_operand" "")
(match_operand:DF 4 "register_operand" "")))
(clobber (reg:CC 17))]
- "FP_REG_P (operands[0]) && reload_completed
+ "reload_completed
&& ((operands_match_p (operands[1], operands[3])
&& operands_match_p (operands[2], operands[4]))
|| (operands_match_p (operands[1], operands[4])
@@ -16628,7 +16604,7 @@
;; cmpCC op0, op4 - set op0 to 0 or ffffffff depending on the comparison
;; and op2, op0 - zero op2 if comparison was false
;; nand op0, op3 - load op3 to op0 if comparison was false
-;; or op2, op0 - get the non-zero one into the result.
+;; or op2, op0 - get the nonzero one into the result.
(define_split
[(set (match_operand 0 "register_operand" "")
(if_then_else (match_operator 1 "sse_comparison_operator"
@@ -16744,7 +16720,7 @@
(define_split
[(set (match_operand 0 "register_operand" "")
(if_then_else (match_operator 1 "comparison_operator"
- [(match_operand 4 "register_operand" "")
+ [(match_operand 4 "nonimmediate_operand" "")
(match_operand 5 "nonimmediate_operand" "")])
(match_operand 2 "nonmemory_operand" "")
(match_operand 3 "nonmemory_operand" "")))]
@@ -16756,13 +16732,16 @@
(subreg:TI (match_dup 7) 0)))]
{
PUT_MODE (operands[1], GET_MODE (operands[0]));
- if (!sse_comparison_operator (operands[1], VOIDmode))
+ if (!sse_comparison_operator (operands[1], VOIDmode)
+ || !rtx_equal_p (operands[0], operands[4]))
{
rtx tmp = operands[5];
operands[5] = operands[4];
operands[4] = tmp;
PUT_CODE (operands[1], swap_condition (GET_CODE (operands[1])));
}
+ if (!rtx_equal_p (operands[0], operands[4]))
+ abort ();
if (const0_operand (operands[2], GET_MODE (operands[0])))
{
operands[7] = operands[3];
@@ -16788,7 +16767,7 @@
})
(define_insn "allocate_stack_worker_1"
- [(unspec:SI [(match_operand:SI 0 "register_operand" "a")] 3)
+ [(unspec:SI [(match_operand:SI 0 "register_operand" "a")] UNSPEC_STACK_PROBE)
(set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0)))
(clobber (match_dup 0))
(clobber (reg:CC 17))]
@@ -16798,7 +16777,7 @@
(set_attr "length" "5")])
(define_insn "allocate_stack_worker_rex64"
- [(unspec:DI [(match_operand:DI 0 "register_operand" "a")] 3)
+ [(unspec:DI [(match_operand:DI 0 "register_operand" "a")] UNSPEC_STACK_PROBE)
(set (reg:DI 7) (minus:DI (reg:DI 7) (match_dup 0)))
(clobber (match_dup 0))
(clobber (reg:CC 17))]
@@ -16835,7 +16814,7 @@
[(label_ref (match_operand 0 "" ""))]
"!TARGET_64BIT && flag_pic"
{
- load_pic_register ();
+ emit_insn (gen_set_got (pic_offset_table_rtx));
DONE;
})
@@ -16849,7 +16828,8 @@
(clobber (reg:CC 17))]
"! TARGET_PARTIAL_REG_STALL && reload_completed
&& ((GET_MODE (operands[0]) == HImode
- && (!optimize_size || GET_CODE (operands[2]) != CONST_INT
+ && ((!optimize_size && !TARGET_FAST_PREFIX)
+ || GET_CODE (operands[2]) != CONST_INT
|| CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')))
|| (GET_MODE (operands[0]) == QImode
&& (TARGET_PROMOTE_QImode || optimize_size)))"
@@ -16862,6 +16842,10 @@
operands[2] = gen_lowpart (SImode, operands[2]);
PUT_MODE (operands[3], SImode);")
+; Promote the QImode tests, as i386 has encoding of the AND
+; instruction with 32-bit sign-extended immediate and thus the
+; instruction size is unchanged, except in the %eax case for
+; which it is increased by one byte, hence the ! optimize_size.
(define_split
[(set (reg 17)
(compare (and (match_operand 1 "aligned_operand" "")
@@ -16870,39 +16854,44 @@
(set (match_operand 0 "register_operand" "")
(and (match_dup 1) (match_dup 2)))]
"! TARGET_PARTIAL_REG_STALL && reload_completed
- && ix86_match_ccmode (insn, CCNOmode)
- && (GET_MODE (operands[0]) == HImode
- || (GET_MODE (operands[0]) == QImode
- && (TARGET_PROMOTE_QImode || optimize_size)))"
+ /* Ensure that the operand will remain sign-extended immediate. */
+ && ix86_match_ccmode (insn, INTVAL (operands[2]) >= 0 ? CCNOmode : CCZmode)
+ && ! optimize_size
+ && ((GET_MODE (operands[0]) == HImode && ! TARGET_FAST_PREFIX)
+ || (GET_MODE (operands[0]) == QImode && TARGET_PROMOTE_QImode))"
[(parallel [(set (reg:CCNO 17)
(compare:CCNO (and:SI (match_dup 1) (match_dup 2))
(const_int 0)))
(set (match_dup 0)
(and:SI (match_dup 1) (match_dup 2)))])]
"operands[2]
- = GEN_INT (trunc_int_for_mode (INTVAL (operands[2])
- & GET_MODE_MASK (GET_MODE (operands[0])),
- SImode));
+ = gen_int_mode (INTVAL (operands[2])
+ & GET_MODE_MASK (GET_MODE (operands[0])),
+ SImode);
operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = gen_lowpart (SImode, operands[1]);")
+; Don't promote the QImode tests, as i386 doesn't have encoding of
+; the TEST instruction with 32-bit sign-extended immediate and thus
+; the instruction size would at least double, which is not what we
+; want even with ! optimize_size.
(define_split
[(set (reg 17)
- (compare (and (match_operand 0 "aligned_operand" "")
- (match_operand 1 "const_int_operand" ""))
+ (compare (and (match_operand:HI 0 "aligned_operand" "")
+ (match_operand:HI 1 "const_int_operand" ""))
(const_int 0)))]
"! TARGET_PARTIAL_REG_STALL && reload_completed
- && ix86_match_ccmode (insn, CCNOmode)
- && (GET_MODE (operands[0]) == HImode
- || (GET_MODE (operands[0]) == QImode
- && (TARGET_PROMOTE_QImode || optimize_size)))"
+ /* Ensure that the operand will remain sign-extended immediate. */
+ && ix86_match_ccmode (insn, INTVAL (operands[1]) >= 0 ? CCNOmode : CCZmode)
+ && ! TARGET_FAST_PREFIX
+ && ! optimize_size"
[(set (reg:CCNO 17)
(compare:CCNO (and:SI (match_dup 0) (match_dup 1))
(const_int 0)))]
"operands[1]
- = GEN_INT (trunc_int_for_mode (INTVAL (operands[1])
- & GET_MODE_MASK (GET_MODE (operands[0])),
- SImode));
+ = gen_int_mode (INTVAL (operands[1])
+ & GET_MODE_MASK (GET_MODE (operands[0])),
+ SImode);
operands[0] = gen_lowpart (SImode, operands[0]);")
(define_split
@@ -17152,7 +17141,8 @@
(const_int 0)))]
"ix86_match_ccmode (insn, CCNOmode)
&& (true_regnum (operands[0]) != 0
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K'))
+ || (GET_CODE (operands[1]) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K')))
&& find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
[(parallel
[(set (reg:CCNO 17)
@@ -17375,7 +17365,7 @@
[(set (match_operand:SI 0 "register_operand" "")
(subreg:SI (mult:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "const_int_operand" "")) 0))]
- "exact_log2 (INTVAL (operands[1])) >= 0
+ "exact_log2 (INTVAL (operands[2])) >= 0
&& REGNO (operands[0]) == REGNO (operands[1])
&& peep2_regno_dead_p (0, FLAGS_REG)"
[(parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))
@@ -17853,52 +17843,92 @@
;; Moves for SSE/MMX regs.
(define_insn "movv4sf_internal"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m")
- (match_operand:V4SF 1 "nonimmediate_operand" "xm,x"))]
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m")
+ (match_operand:V4SF 1 "vector_move_operand" "C,xm,x"))]
"TARGET_SSE"
;; @@@ let's try to use movaps here.
- "movaps\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ "@
+ xorps\t%0, %0
+ movaps\t{%1, %0|%0, %1}
+ movaps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V4SF")])
(define_insn "movv4si_internal"
- [(set (match_operand:V4SI 0 "nonimmediate_operand" "=x,m")
- (match_operand:V4SI 1 "nonimmediate_operand" "xm,x"))]
+ [(set (match_operand:V4SI 0 "nonimmediate_operand" "=x,x,m")
+ (match_operand:V4SI 1 "vector_move_operand" "C,xm,x"))]
"TARGET_SSE"
;; @@@ let's try to use movaps here.
- "movaps\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ "@
+ xorps\t%0, %0
+ movaps\t{%1, %0|%0, %1}
+ movaps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "movv2di_internal"
+ [(set (match_operand:V2DI 0 "nonimmediate_operand" "=x,x,m")
+ (match_operand:V2DI 1 "vector_move_operand" "C,xm,x"))]
+ "TARGET_SSE"
+ ;; @@@ let's try to use movaps here.
+ "@
+ pxor\t%0, %0
+ movdqa\t{%1, %0|%0, %1}
+ movdqa\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V4SF")])
(define_insn "movv8qi_internal"
- [(set (match_operand:V8QI 0 "nonimmediate_operand" "=y,m")
- (match_operand:V8QI 1 "nonimmediate_operand" "ym,y"))]
- "TARGET_MMX"
- "movq\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmx")])
+ [(set (match_operand:V8QI 0 "nonimmediate_operand" "=y,y,m")
+ (match_operand:V8QI 1 "vector_move_operand" "C,ym,y"))]
+ "TARGET_MMX
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ pxor\t%0, %0
+ movq\t{%1, %0|%0, %1}
+ movq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxmov")
+ (set_attr "mode" "DI")])
(define_insn "movv4hi_internal"
- [(set (match_operand:V4HI 0 "nonimmediate_operand" "=y,m")
- (match_operand:V4HI 1 "nonimmediate_operand" "ym,y"))]
- "TARGET_MMX"
- "movq\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmx")])
+ [(set (match_operand:V4HI 0 "nonimmediate_operand" "=y,y,m")
+ (match_operand:V4HI 1 "vector_move_operand" "C,ym,y"))]
+ "TARGET_MMX
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ pxor\t%0, %0
+ movq\t{%1, %0|%0, %1}
+ movq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxmov")
+ (set_attr "mode" "DI")])
(define_insn "movv2si_internal"
- [(set (match_operand:V2SI 0 "nonimmediate_operand" "=y,m")
- (match_operand:V2SI 1 "nonimmediate_operand" "ym,y"))]
- "TARGET_MMX"
- "movq\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmx")])
+ [(set (match_operand:V2SI 0 "nonimmediate_operand" "=y,y,m")
+ (match_operand:V2SI 1 "vector_move_operand" "C,ym,y"))]
+ "TARGET_MMX
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ pxor\t%0, %0
+ movq\t{%1, %0|%0, %1}
+ movq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
(define_insn "movv2sf_internal"
- [(set (match_operand:V2SF 0 "nonimmediate_operand" "=y,m")
- (match_operand:V2SF 1 "nonimmediate_operand" "ym,y"))]
- "TARGET_3DNOW"
- "movq\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmx")])
+ [(set (match_operand:V2SF 0 "nonimmediate_operand" "=y,y,m")
+ (match_operand:V2SF 1 "vector_move_operand" "C,ym,y"))]
+ "TARGET_3DNOW
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ pxor\t%0, %0
+ movq\t{%1, %0|%0, %1}
+ movq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
(define_expand "movti"
- [(set (match_operand:TI 0 "general_operand" "")
- (match_operand:TI 1 "general_operand" ""))]
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (match_operand:TI 1 "nonimmediate_operand" ""))]
"TARGET_SSE || TARGET_64BIT"
{
if (TARGET_64BIT)
@@ -17908,9 +17938,72 @@
DONE;
})
+(define_insn "movv2df_internal"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,m")
+ (match_operand:V2DF 1 "vector_move_operand" "C,xm,x"))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ xorpd\t%0, %0
+ movapd\t{%1, %0|%0, %1}
+ movapd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "movv8hi_internal"
+ [(set (match_operand:V8HI 0 "nonimmediate_operand" "=x,x,m")
+ (match_operand:V8HI 1 "vector_move_operand" "C,xm,x"))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ xorps\t%0, %0
+ movaps\t{%1, %0|%0, %1}
+ movaps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "movv16qi_internal"
+ [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,x,m")
+ (match_operand:V16QI 1 "vector_move_operand" "C,xm,x"))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ xorps\t%0, %0
+ movaps\t{%1, %0|%0, %1}
+ movaps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V4SF")])
+
+(define_expand "movv2df"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "")
+ (match_operand:V2DF 1 "nonimmediate_operand" ""))]
+ "TARGET_SSE2"
+{
+ ix86_expand_vector_move (V2DFmode, operands);
+ DONE;
+})
+
+(define_expand "movv8hi"
+ [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
+ (match_operand:V8HI 1 "nonimmediate_operand" ""))]
+ "TARGET_SSE2"
+{
+ ix86_expand_vector_move (V8HImode, operands);
+ DONE;
+})
+
+(define_expand "movv16qi"
+ [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
+ (match_operand:V16QI 1 "nonimmediate_operand" ""))]
+ "TARGET_SSE2"
+{
+ ix86_expand_vector_move (V16QImode, operands);
+ DONE;
+})
+
(define_expand "movv4sf"
- [(set (match_operand:V4SF 0 "general_operand" "")
- (match_operand:V4SF 1 "general_operand" ""))]
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
+ (match_operand:V4SF 1 "nonimmediate_operand" ""))]
"TARGET_SSE"
{
ix86_expand_vector_move (V4SFmode, operands);
@@ -17918,17 +18011,26 @@
})
(define_expand "movv4si"
- [(set (match_operand:V4SI 0 "general_operand" "")
- (match_operand:V4SI 1 "general_operand" ""))]
- "TARGET_MMX"
+ [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
+ (match_operand:V4SI 1 "nonimmediate_operand" ""))]
+ "TARGET_SSE"
{
ix86_expand_vector_move (V4SImode, operands);
DONE;
})
+(define_expand "movv2di"
+ [(set (match_operand:V2DI 0 "nonimmediate_operand" "")
+ (match_operand:V2DI 1 "nonimmediate_operand" ""))]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_move (V2DImode, operands);
+ DONE;
+})
+
(define_expand "movv2si"
- [(set (match_operand:V2SI 0 "general_operand" "")
- (match_operand:V2SI 1 "general_operand" ""))]
+ [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
+ (match_operand:V2SI 1 "nonimmediate_operand" ""))]
"TARGET_MMX"
{
ix86_expand_vector_move (V2SImode, operands);
@@ -17936,8 +18038,8 @@
})
(define_expand "movv4hi"
- [(set (match_operand:V4HI 0 "general_operand" "")
- (match_operand:V4HI 1 "general_operand" ""))]
+ [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
+ (match_operand:V4HI 1 "nonimmediate_operand" ""))]
"TARGET_MMX"
{
ix86_expand_vector_move (V4HImode, operands);
@@ -17945,8 +18047,8 @@
})
(define_expand "movv8qi"
- [(set (match_operand:V8QI 0 "general_operand" "")
- (match_operand:V8QI 1 "general_operand" ""))]
+ [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
+ (match_operand:V8QI 1 "nonimmediate_operand" ""))]
"TARGET_MMX"
{
ix86_expand_vector_move (V8QImode, operands);
@@ -17954,14 +18056,97 @@
})
(define_expand "movv2sf"
- [(set (match_operand:V2SF 0 "general_operand" "")
- (match_operand:V2SF 1 "general_operand" ""))]
+ [(set (match_operand:V2SF 0 "nonimmediate_operand" "")
+ (match_operand:V2SF 1 "nonimmediate_operand" ""))]
"TARGET_3DNOW"
{
ix86_expand_vector_move (V2SFmode, operands);
DONE;
})
+(define_insn "*pushv2df"
+ [(set (match_operand:V2DF 0 "push_operand" "=<")
+ (match_operand:V2DF 1 "register_operand" "x"))]
+ "TARGET_SSE"
+ "#")
+
+(define_insn "*pushv2di"
+ [(set (match_operand:V2DI 0 "push_operand" "=<")
+ (match_operand:V2DI 1 "register_operand" "x"))]
+ "TARGET_SSE2"
+ "#")
+
+(define_insn "*pushv8hi"
+ [(set (match_operand:V8HI 0 "push_operand" "=<")
+ (match_operand:V8HI 1 "register_operand" "x"))]
+ "TARGET_SSE2"
+ "#")
+
+(define_insn "*pushv16qi"
+ [(set (match_operand:V16QI 0 "push_operand" "=<")
+ (match_operand:V16QI 1 "register_operand" "x"))]
+ "TARGET_SSE2"
+ "#")
+
+(define_insn "*pushv4sf"
+ [(set (match_operand:V4SF 0 "push_operand" "=<")
+ (match_operand:V4SF 1 "register_operand" "x"))]
+ "TARGET_SSE"
+ "#")
+
+(define_insn "*pushv4si"
+ [(set (match_operand:V4SI 0 "push_operand" "=<")
+ (match_operand:V4SI 1 "register_operand" "x"))]
+ "TARGET_SSE2"
+ "#")
+
+(define_insn "*pushv2si"
+ [(set (match_operand:V2SI 0 "push_operand" "=<")
+ (match_operand:V2SI 1 "register_operand" "y"))]
+ "TARGET_MMX"
+ "#")
+
+(define_insn "*pushv4hi"
+ [(set (match_operand:V4HI 0 "push_operand" "=<")
+ (match_operand:V4HI 1 "register_operand" "y"))]
+ "TARGET_MMX"
+ "#")
+
+(define_insn "*pushv8qi"
+ [(set (match_operand:V8QI 0 "push_operand" "=<")
+ (match_operand:V8QI 1 "register_operand" "y"))]
+ "TARGET_MMX"
+ "#")
+
+(define_insn "*pushv2sf"
+ [(set (match_operand:V2SF 0 "push_operand" "=<")
+ (match_operand:V2SF 1 "register_operand" "y"))]
+ "TARGET_3DNOW"
+ "#")
+
+(define_split
+ [(set (match_operand 0 "push_operand" "")
+ (match_operand 1 "register_operand" ""))]
+ "!TARGET_64BIT && reload_completed
+ && (SSE_REG_P (operands[1]) || MMX_REG_P (operands[1]))"
+ [(set (reg:SI 7) (plus:SI (reg:SI 7) (match_dup 3)))
+ (set (match_dup 2) (match_dup 1))]
+ "operands[2] = change_address (operands[0], GET_MODE (operands[0]),
+ stack_pointer_rtx);
+ operands[3] = GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[0])));")
+
+(define_split
+ [(set (match_operand 0 "push_operand" "")
+ (match_operand 1 "register_operand" ""))]
+ "TARGET_64BIT && reload_completed
+ && (SSE_REG_P (operands[1]) || MMX_REG_P (operands[1]))"
+ [(set (reg:DI 7) (plus:DI (reg:DI 7) (match_dup 3)))
+ (set (match_dup 2) (match_dup 1))]
+ "operands[2] = change_address (operands[0], GET_MODE (operands[0]),
+ stack_pointer_rtx);
+ operands[3] = GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[0])));")
+
+
(define_insn_and_split "*pushti"
[(set (match_operand:TI 0 "push_operand" "=<")
(match_operand:TI 1 "nonmemory_operand" "x"))]
@@ -17971,7 +18156,51 @@
[(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16)))
(set (mem:TI (reg:SI 7)) (match_dup 1))]
""
- [(set_attr "type" "sse")])
+ [(set_attr "type" "multi")])
+
+(define_insn_and_split "*pushv2df"
+ [(set (match_operand:V2DF 0 "push_operand" "=<")
+ (match_operand:V2DF 1 "nonmemory_operand" "x"))]
+ "TARGET_SSE2"
+ "#"
+ ""
+ [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16)))
+ (set (mem:V2DF (reg:SI 7)) (match_dup 1))]
+ ""
+ [(set_attr "type" "multi")])
+
+(define_insn_and_split "*pushv2di"
+ [(set (match_operand:V2DI 0 "push_operand" "=<")
+ (match_operand:V2DI 1 "nonmemory_operand" "x"))]
+ "TARGET_SSE2"
+ "#"
+ ""
+ [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16)))
+ (set (mem:V2DI (reg:SI 7)) (match_dup 1))]
+ ""
+ [(set_attr "type" "multi")])
+
+(define_insn_and_split "*pushv8hi"
+ [(set (match_operand:V8HI 0 "push_operand" "=<")
+ (match_operand:V8HI 1 "nonmemory_operand" "x"))]
+ "TARGET_SSE2"
+ "#"
+ ""
+ [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16)))
+ (set (mem:V8HI (reg:SI 7)) (match_dup 1))]
+ ""
+ [(set_attr "type" "multi")])
+
+(define_insn_and_split "*pushv16qi"
+ [(set (match_operand:V16QI 0 "push_operand" "=<")
+ (match_operand:V16QI 1 "nonmemory_operand" "x"))]
+ "TARGET_SSE2"
+ "#"
+ ""
+ [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16)))
+ (set (mem:V16QI (reg:SI 7)) (match_dup 1))]
+ ""
+ [(set_attr "type" "multi")])
(define_insn_and_split "*pushv4sf"
[(set (match_operand:V4SF 0 "push_operand" "=<")
@@ -17982,7 +18211,7 @@
[(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16)))
(set (mem:V4SF (reg:SI 7)) (match_dup 1))]
""
- [(set_attr "type" "sse")])
+ [(set_attr "type" "multi")])
(define_insn_and_split "*pushv4si"
[(set (match_operand:V4SI 0 "push_operand" "=<")
@@ -17993,7 +18222,7 @@
[(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16)))
(set (mem:V4SI (reg:SI 7)) (match_dup 1))]
""
- [(set_attr "type" "sse")])
+ [(set_attr "type" "multi")])
(define_insn_and_split "*pushv2si"
[(set (match_operand:V2SI 0 "push_operand" "=<")
@@ -18041,17 +18270,19 @@
(define_insn "movti_internal"
[(set (match_operand:TI 0 "nonimmediate_operand" "=x,x,m")
- (match_operand:TI 1 "general_operand" "O,xm,x"))]
- "TARGET_SSE && !TARGET_64BIT"
+ (match_operand:TI 1 "vector_move_operand" "C,xm,x"))]
+ "TARGET_SSE && !TARGET_64BIT
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"@
xorps\t%0, %0
movaps\t{%1, %0|%0, %1}
movaps\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssemov,ssemov,ssemov")
+ (set_attr "mode" "V4SF")])
(define_insn "*movti_rex64"
[(set (match_operand:TI 0 "nonimmediate_operand" "=r,o,x,mx,x")
- (match_operand:TI 1 "general_operand" "riFo,riF,O,x,m"))]
+ (match_operand:TI 1 "general_operand" "riFo,riF,C,x,m"))]
"TARGET_64BIT
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"@
@@ -18060,8 +18291,8 @@
xorps\t%0, %0
movaps\\t{%1, %0|%0, %1}
movaps\\t{%1, %0|%0, %1}"
- [(set_attr "type" "*,*,sse,sse,sse")
- (set_attr "mode" "TI")])
+ [(set_attr "type" "*,*,ssemov,ssemov,ssemov")
+ (set_attr "mode" "V4SF")])
(define_split
[(set (match_operand:TI 0 "nonimmediate_operand" "")
@@ -18073,74 +18304,116 @@
;; These two patterns are useful for specifying exactly whether to use
;; movaps or movups
-(define_insn "sse_movaps"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m")
- (unspec:V4SF
- [(match_operand:V4SF 1 "nonimmediate_operand" "xm,x")] 38))]
+(define_expand "sse_movaps"
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
+ (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "")]
+ UNSPEC_MOVA))]
"TARGET_SSE"
- "@
- movaps\t{%1, %0|%0, %1}
- movaps\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ {
+ rtx tmp = gen_reg_rtx (V4SFmode);
+ emit_insn (gen_sse_movaps (tmp, operands[1]));
+ emit_move_insn (operands[0], tmp);
+ DONE;
+ }
+})
-(define_insn "sse_movups"
+(define_insn "*sse_movaps_1"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m")
- (unspec:V4SF
- [(match_operand:V4SF 1 "nonimmediate_operand" "xm,x")] 39))]
+ (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm,x")]
+ UNSPEC_MOVA))]
+ "TARGET_SSE
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "movaps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov,ssemov")
+ (set_attr "mode" "V4SF")])
+
+(define_expand "sse_movups"
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
+ (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "")]
+ UNSPEC_MOVU))]
"TARGET_SSE"
- "@
- movups\t{%1, %0|%0, %1}
- movups\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+{
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+ {
+ rtx tmp = gen_reg_rtx (V4SFmode);
+ emit_insn (gen_sse_movups (tmp, operands[1]));
+ emit_move_insn (operands[0], tmp);
+ DONE;
+ }
+})
+(define_insn "*sse_movups_1"
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m")
+ (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm,x")]
+ UNSPEC_MOVU))]
+ "TARGET_SSE
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "movups\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt,ssecvt")
+ (set_attr "mode" "V4SF")])
;; SSE Strange Moves.
(define_insn "sse_movmskps"
[(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:V4SF 1 "register_operand" "x")] 33))]
+ (unspec:SI [(match_operand:V4SF 1 "register_operand" "x")]
+ UNSPEC_MOVMSK))]
"TARGET_SSE"
"movmskps\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
(define_insn "mmx_pmovmskb"
[(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:V8QI 1 "register_operand" "y")] 33))]
+ (unspec:SI [(match_operand:V8QI 1 "register_operand" "y")]
+ UNSPEC_MOVMSK))]
"TARGET_SSE || TARGET_3DNOW_A"
"pmovmskb\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
+
(define_insn "mmx_maskmovq"
[(set (mem:V8QI (match_operand:SI 0 "register_operand" "D"))
(unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")] 32))]
+ (match_operand:V8QI 2 "register_operand" "y")]
+ UNSPEC_MASKMOV))]
"(TARGET_SSE || TARGET_3DNOW_A) && !TARGET_64BIT"
;; @@@ check ordering of operands in intel/nonintel syntax
"maskmovq\t{%2, %1|%1, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
(define_insn "mmx_maskmovq_rex"
[(set (mem:V8QI (match_operand:DI 0 "register_operand" "D"))
(unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y")
- (match_operand:V8QI 2 "register_operand" "y")] 32))]
+ (match_operand:V8QI 2 "register_operand" "y")]
+ UNSPEC_MASKMOV))]
"(TARGET_SSE || TARGET_3DNOW_A) && TARGET_64BIT"
;; @@@ check ordering of operands in intel/nonintel syntax
"maskmovq\t{%2, %1|%1, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
(define_insn "sse_movntv4sf"
[(set (match_operand:V4SF 0 "memory_operand" "=m")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "x")] 34))]
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "x")]
+ UNSPEC_MOVNT))]
"TARGET_SSE"
"movntps\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V4SF")])
(define_insn "sse_movntdi"
[(set (match_operand:DI 0 "memory_operand" "=m")
- (unspec:DI [(match_operand:DI 1 "register_operand" "y")] 34))]
+ (unspec:DI [(match_operand:DI 1 "register_operand" "y")]
+ UNSPEC_MOVNT))]
"TARGET_SSE || TARGET_3DNOW_A"
"movntq\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "mmxmov")
+ (set_attr "mode" "DI")])
(define_insn "sse_movhlps"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18154,7 +18427,8 @@
(const_int 3)))]
"TARGET_SSE"
"movhlps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
(define_insn "sse_movlhps"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18168,7 +18442,8 @@
(const_int 12)))]
"TARGET_SSE"
"movlhps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
(define_insn "sse_movhps"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m")
@@ -18179,7 +18454,8 @@
"TARGET_SSE
&& (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)"
"movhps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
(define_insn "sse_movlps"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m")
@@ -18190,17 +18466,29 @@
"TARGET_SSE
&& (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)"
"movlps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
-(define_insn "sse_loadss"
+(define_expand "sse_loadss"
+ [(match_operand:V4SF 0 "register_operand" "")
+ (match_operand:SF 1 "memory_operand" "")]
+ "TARGET_SSE"
+{
+ emit_insn (gen_sse_loadss_1 (operands[0], operands[1],
+ CONST0_RTX (V4SFmode)));
+ DONE;
+})
+
+(define_insn "sse_loadss_1"
[(set (match_operand:V4SF 0 "register_operand" "=x")
(vec_merge:V4SF
- (match_operand:V4SF 1 "memory_operand" "m")
- (vec_duplicate:V4SF (float:SF (const_int 0)))
+ (vec_duplicate:V4SF (match_operand:SF 1 "memory_operand" "m"))
+ (match_operand:V4SF 2 "const0_operand" "X")
(const_int 1)))]
"TARGET_SSE"
"movss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "SF")])
(define_insn "sse_movss"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18210,7 +18498,8 @@
(const_int 1)))]
"TARGET_SSE"
"movss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "SF")])
(define_insn "sse_storess"
[(set (match_operand:SF 0 "memory_operand" "=m")
@@ -18219,17 +18508,20 @@
(parallel [(const_int 0)])))]
"TARGET_SSE"
"movss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "SF")])
(define_insn "sse_shufps"
[(set (match_operand:V4SF 0 "register_operand" "=x")
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "0")
(match_operand:V4SF 2 "nonimmediate_operand" "xm")
- (match_operand:SI 3 "immediate_operand" "i")] 41))]
+ (match_operand:SI 3 "immediate_operand" "i")]
+ UNSPEC_SHUFFLE))]
"TARGET_SSE"
;; @@@ check operand order for intel/nonintel syntax
"shufps\t{%3, %2, %0|%0, %2, %3}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
;; SSE arithmetic
@@ -18240,7 +18532,8 @@
(match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
"TARGET_SSE"
"addps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V4SF")])
(define_insn "vmaddv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18251,7 +18544,8 @@
(const_int 1)))]
"TARGET_SSE"
"addss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "SF")])
(define_insn "subv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18259,7 +18553,8 @@
(match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
"TARGET_SSE"
"subps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V4SF")])
(define_insn "vmsubv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18270,7 +18565,8 @@
(const_int 1)))]
"TARGET_SSE"
"subss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "SF")])
(define_insn "mulv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18278,7 +18574,8 @@
(match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
"TARGET_SSE"
"mulps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssemul")
+ (set_attr "mode" "V4SF")])
(define_insn "vmmulv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18289,7 +18586,8 @@
(const_int 1)))]
"TARGET_SSE"
"mulss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssemul")
+ (set_attr "mode" "SF")])
(define_insn "divv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18297,7 +18595,8 @@
(match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
"TARGET_SSE"
"divps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssediv")
+ (set_attr "mode" "V4SF")])
(define_insn "vmdivv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18308,7 +18607,8 @@
(const_int 1)))]
"TARGET_SSE"
"divss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssediv")
+ (set_attr "mode" "SF")])
;; SSE square root/reciprocal
@@ -18316,45 +18616,52 @@
(define_insn "rcpv4sf2"
[(set (match_operand:V4SF 0 "register_operand" "=x")
(unspec:V4SF
- [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] 42))]
+ [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_RCP))]
"TARGET_SSE"
"rcpps\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V4SF")])
(define_insn "vmrcpv4sf2"
[(set (match_operand:V4SF 0 "register_operand" "=x")
(vec_merge:V4SF
- (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] 42)
+ (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
+ UNSPEC_RCP)
(match_operand:V4SF 2 "register_operand" "0")
(const_int 1)))]
"TARGET_SSE"
"rcpss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sse")
+ (set_attr "mode" "SF")])
(define_insn "rsqrtv4sf2"
[(set (match_operand:V4SF 0 "register_operand" "=x")
(unspec:V4SF
- [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] 43))]
+ [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_RSQRT))]
"TARGET_SSE"
"rsqrtps\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V4SF")])
(define_insn "vmrsqrtv4sf2"
[(set (match_operand:V4SF 0 "register_operand" "=x")
(vec_merge:V4SF
- (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] 43)
+ (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
+ UNSPEC_RSQRT)
(match_operand:V4SF 2 "register_operand" "0")
(const_int 1)))]
"TARGET_SSE"
"rsqrtss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sse")
+ (set_attr "mode" "SF")])
(define_insn "sqrtv4sf2"
[(set (match_operand:V4SF 0 "register_operand" "=x")
(sqrt:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "xm")))]
"TARGET_SSE"
"sqrtps\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V4SF")])
(define_insn "vmsqrtv4sf2"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18364,206 +18671,358 @@
(const_int 1)))]
"TARGET_SSE"
"sqrtss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sse")
+ (set_attr "mode" "SF")])
;; SSE logical operations.
+;; SSE defines logical operations on floating point values. This brings
+;; interesting challenge to RTL representation where logicals are only valid
+;; on integral types. We deal with this by representing the floating point
+;; logical as logical on arguments casted to TImode as this is what hardware
+;; really does. Unfortunately hardware requires the type information to be
+;; present and thus we must avoid subregs from being simplified and elliminated
+;; in later compilation phases.
+;;
+;; We have following variants from each instruction:
+;; sse_andsf3 - the operation taking V4SF vector operands
+;; and doing TImode cast on them
+;; *sse_andsf3_memory - the operation taking one memory operand casted to
+;; TImode, since backend insist on elliminating casts
+;; on memory operands
+;; sse_andti3_sf_1 - the operation taking SF scalar operands.
+;; We can not accept memory operand here as instruction reads
+;; whole scalar. This is generated only post reload by GCC
+;; scalar float operations that expands to logicals (fabs)
+;; sse_andti3_sf_2 - the operation taking SF scalar input and TImode
+;; memory operand. Eventually combine can be able
+;; to synthetize these using splitter.
+;; sse2_anddf3, *sse2_anddf3_memory
+;;
+;;
;; These are not called andti3 etc. because we really really don't want
;; the compiler to widen DImode ands to TImode ands and then try to move
;; into DImode subregs of SSE registers, and them together, and move out
;; of DImode subregs again!
+;; SSE1 single precision floating point logical operation
+(define_expand "sse_andv4sf3"
+ [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "") 0)
+ (and:TI (subreg:TI (match_operand:V4SF 1 "register_operand" "") 0)
+ (subreg:TI (match_operand:V4SF 2 "nonimmediate_operand" "") 0)))]
+ "TARGET_SSE"
+ "")
-(define_insn "*sse_andti3_df_1"
- [(set (subreg:TI (match_operand:DF 0 "register_operand" "=Y") 0)
- (and:TI (subreg:TI (match_operand:DF 1 "register_operand" "%0") 0)
- (subreg:TI (match_operand:DF 2 "register_operand" "Y") 0)))]
- "TARGET_SSE2"
- "andpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
-
-(define_insn "*sse_andti3_df_2"
- [(set (subreg:TI (match_operand:DF 0 "register_operand" "=Y") 0)
- (and:TI (subreg:TI (match_operand:DF 1 "register_operand" "0") 0)
- (match_operand:TI 2 "nonimmediate_operand" "Ym")))]
- "TARGET_SSE2"
- "andpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+(define_insn "*sse_andv4sf3"
+ [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "=x") 0)
+ (and:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
+ (match_operand:TI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "andps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
-(define_insn "*sse_andti3_sf_1"
+(define_insn "*sse_andsf3"
[(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0)
- (and:TI (subreg:TI (match_operand:SF 1 "register_operand" "%0") 0)
- (subreg:TI (match_operand:SF 2 "register_operand" "x") 0)))]
- "TARGET_SSE"
+ (and:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
+ (match_operand:TI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"andps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
+
+(define_expand "sse_nandv4sf3"
+ [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "") 0)
+ (and:TI (not:TI (subreg:TI (match_operand:V4SF 1 "register_operand" "") 0))
+ (subreg:TI (match_operand:V4SF 2 "nonimmediate_operand" "") 0)))]
+ "TARGET_SSE"
+ "")
+
+(define_insn "*sse_nandv4sf3"
+ [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "=x") 0)
+ (and:TI (not:TI (match_operand:TI 1 "register_operand" "0"))
+ (match_operand:TI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE"
+ "andnps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
-(define_insn "*sse_andti3_sf_2"
+(define_insn "*sse_nandsf3"
[(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0)
- (and:TI (subreg:TI (match_operand:SF 1 "register_operand" "0") 0)
- (match_operand:TI 2 "nonimmediate_operand" "xm")))]
+ (and:TI (not:TI (match_operand:TI 1 "register_operand" "0"))
+ (match_operand:TI 2 "nonimmediate_operand" "xm")))]
"TARGET_SSE"
- "andps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ "andnps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
-(define_insn "sse_andti3"
- [(set (match_operand:TI 0 "register_operand" "=x")
- (and:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
+(define_expand "sse_iorv4sf3"
+ [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "") 0)
+ (ior:TI (subreg:TI (match_operand:V4SF 1 "register_operand" "") 0)
+ (subreg:TI (match_operand:V4SF 2 "nonimmediate_operand" "") 0)))]
+ "TARGET_SSE"
+ "")
+
+(define_insn "*sse_iorv4sf3"
+ [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "=x") 0)
+ (ior:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
(match_operand:TI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE && !TARGET_SSE2
+ "TARGET_SSE
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "andps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ "orps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
-(define_insn "*sse_andti3_sse2"
- [(set (match_operand:TI 0 "register_operand" "=x")
- (and:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
+(define_insn "*sse_iorsf3"
+ [(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0)
+ (ior:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
(match_operand:TI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2
+ "TARGET_SSE
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "pand\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ "orps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
-(define_insn "*sse_nandti3_df"
- [(set (subreg:TI (match_operand:DF 0 "register_operand" "=Y") 0)
- (and:TI (not:TI (subreg:TI (match_operand:DF 1 "register_operand" "0") 0))
- (match_operand:TI 2 "nonimmediate_operand" "Ym")))]
- "TARGET_SSE2"
- "andnpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+(define_expand "sse_xorv4sf3"
+ [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "") 0)
+ (xor:TI (subreg:TI (match_operand:V4SF 1 "register_operand" "") 0)
+ (subreg:TI (match_operand:V4SF 2 "nonimmediate_operand" "") 0)))]
+ "TARGET_SSE
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "")
+
+(define_insn "*sse_xorv4sf3"
+ [(set (subreg:TI (match_operand:V4SF 0 "register_operand" "=x") 0)
+ (xor:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
+ (match_operand:TI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "xorps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
-(define_insn "*sse_nandti3_sf"
+(define_insn "*sse_xorsf3"
[(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0)
- (and:TI (not:TI (subreg:TI (match_operand:SF 1 "register_operand" "0") 0))
+ (xor:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
(match_operand:TI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE"
- "andnps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ "TARGET_SSE
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "xorps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
-(define_insn "sse_nandti3"
- [(set (match_operand:TI 0 "register_operand" "=x")
- (and:TI (not:TI (match_operand:TI 1 "register_operand" "0"))
+;; SSE2 double precision floating point logical operation
+
+(define_expand "sse2_andv2df3"
+ [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "") 0)
+ (and:TI (subreg:TI (match_operand:V2DF 1 "register_operand" "") 0)
+ (subreg:TI (match_operand:V2DF 2 "nonimmediate_operand" "") 0)))]
+ "TARGET_SSE2"
+ "")
+
+(define_insn "*sse2_andv2df3"
+ [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "=x") 0)
+ (and:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
(match_operand:TI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE && !TARGET_SSE2"
- "andnps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ "TARGET_SSE2
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "andpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
-(define_insn "*sse_nandti3_sse2"
- [(set (match_operand:TI 0 "register_operand" "=x")
- (and:TI (not:TI (match_operand:TI 1 "register_operand" "0"))
+(define_insn "*sse2_andv2df3"
+ [(set (subreg:TI (match_operand:DF 0 "register_operand" "=x") 0)
+ (and:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
(match_operand:TI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "andpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
+
+(define_expand "sse2_nandv2df3"
+ [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "") 0)
+ (and:TI (not:TI (subreg:TI (match_operand:V2DF 1 "register_operand" "") 0))
+ (subreg:TI (match_operand:V2DF 2 "nonimmediate_operand" "") 0)))]
"TARGET_SSE2"
- "pnand\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ "")
-(define_insn "*sse_iorti3_df_1"
- [(set (subreg:TI (match_operand:DF 0 "register_operand" "=Y") 0)
- (ior:TI (subreg:TI (match_operand:DF 1 "register_operand" "%0") 0)
- (subreg:TI (match_operand:DF 2 "register_operand" "Y") 0)))]
+(define_insn "*sse2_nandv2df3"
+ [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "=x") 0)
+ (and:TI (not:TI (match_operand:TI 1 "register_operand" "0"))
+ (match_operand:TI 2 "nonimmediate_operand" "xm")))]
"TARGET_SSE2"
- "orpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ "andnpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
-(define_insn "*sse_iorti3_df_2"
+(define_insn "*sse_nandti3_df"
[(set (subreg:TI (match_operand:DF 0 "register_operand" "=Y") 0)
- (ior:TI (subreg:TI (match_operand:DF 1 "register_operand" "0") 0)
+ (and:TI (not:TI (match_operand:TI 1 "register_operand" "0"))
(match_operand:TI 2 "nonimmediate_operand" "Ym")))]
"TARGET_SSE2"
- "orpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
-
-(define_insn "*sse_iorti3_sf_1"
- [(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0)
- (ior:TI (subreg:TI (match_operand:SF 1 "register_operand" "%0") 0)
- (subreg:TI (match_operand:SF 2 "register_operand" "x") 0)))]
- "TARGET_SSE"
- "orps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ "andnpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
-(define_insn "*sse_iorti3_sf_2"
- [(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0)
- (ior:TI (subreg:TI (match_operand:SF 1 "register_operand" "0") 0)
- (match_operand:TI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE"
- "orps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+(define_expand "sse2_iorv2df3"
+ [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "") 0)
+ (ior:TI (subreg:TI (match_operand:V2DF 1 "register_operand" "") 0)
+ (subreg:TI (match_operand:V2DF 2 "nonimmediate_operand" "") 0)))]
+ "TARGET_SSE2"
+ "")
-(define_insn "sse_iorti3"
- [(set (match_operand:TI 0 "register_operand" "=x")
+(define_insn "*sse2_iorv2df3"
+ [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "=x") 0)
(ior:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
(match_operand:TI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE && !TARGET_SSE2
+ "TARGET_SSE2
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "orps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ "orpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
-(define_insn "*sse_iorti3_sse2"
- [(set (match_operand:TI 0 "register_operand" "=x")
+(define_insn "*sse2_iordf3"
+ [(set (subreg:TI (match_operand:DF 0 "register_operand" "=x") 0)
(ior:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
(match_operand:TI 2 "nonimmediate_operand" "xm")))]
"TARGET_SSE2
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "por\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ "orpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
-(define_insn "*sse_xorti3_df_1"
- [(set (subreg:TI (match_operand:DF 0 "register_operand" "=Y") 0)
- (xor:TI (subreg:TI (match_operand:DF 1 "register_operand" "%0") 0)
- (subreg:TI (match_operand:DF 2 "register_operand" "Y") 0)))]
+(define_expand "sse2_xorv2df3"
+ [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "") 0)
+ (xor:TI (subreg:TI (match_operand:V2DF 1 "nonimmediate_operand" "") 0)
+ (subreg:TI (match_operand:V2DF 2 "nonimmediate_operand" "") 0)))]
"TARGET_SSE2"
+ "")
+
+(define_insn "*sse2_xorv2df3"
+ [(set (subreg:TI (match_operand:V2DF 0 "register_operand" "=x") 0)
+ (xor:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
+ (match_operand:TI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"xorpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
-(define_insn "*sse_xorti3_df_2"
- [(set (subreg:TI (match_operand:DF 0 "register_operand" "=Y") 0)
- (xor:TI (subreg:TI (match_operand:DF 1 "register_operand" "0") 0)
- (match_operand:TI 2 "nonimmediate_operand" "Ym")))]
- "TARGET_SSE2"
+(define_insn "*sse2_xordf3"
+ [(set (subreg:TI (match_operand:DF 0 "register_operand" "=x") 0)
+ (xor:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
+ (match_operand:TI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"xorpd\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
-(define_insn "*sse_xorti3_sf_1"
- [(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0)
- (xor:TI (subreg:TI (match_operand:SF 1 "register_operand" "%0") 0)
- (subreg:TI (match_operand:SF 2 "register_operand" "x") 0)))]
- "TARGET_SSE"
- "xorps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+;; SSE2 integral logicals. These patterns must always come after floating
+;; point ones since we don't want compiler to use integer opcodes on floating
+;; point SSE values to avoid matching of subregs in the match_operand.
+(define_insn "*sse2_andti3"
+ [(set (match_operand:TI 0 "register_operand" "=x")
+ (and:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
+ (match_operand:TI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "pand\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
-(define_insn "*sse_xorti3_sf_2"
- [(set (subreg:TI (match_operand:SF 0 "register_operand" "=x") 0)
- (xor:TI (subreg:TI (match_operand:SF 1 "register_operand" "0") 0)
+(define_insn "sse2_andv2di3"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (and:V2DI (match_operand:V2DI 1 "nonimmediate_operand" "%0")
+ (match_operand:V2DI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "pand\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "*sse2_nandti3"
+ [(set (match_operand:TI 0 "register_operand" "=x")
+ (and:TI (not:TI (match_operand:TI 1 "register_operand" "0"))
(match_operand:TI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE"
- "xorps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ "TARGET_SSE2"
+ "pandn\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
-(define_insn "sse_xorti3"
+(define_insn "sse2_nandv2di3"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (and:V2DI (not:V2DI (match_operand:V2DI 1 "nonimmediate_operand" "0"))
+ (match_operand:V2DI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "pandn\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "*sse2_iorti3"
[(set (match_operand:TI 0 "register_operand" "=x")
- (xor:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
+ (ior:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
(match_operand:TI 2 "nonimmediate_operand" "xm")))]
- "TARGET_SSE && !TARGET_SSE2
+ "TARGET_SSE2
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
- "xorps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ "por\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_iorv2di3"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (ior:V2DI (match_operand:V2DI 1 "nonimmediate_operand" "%0")
+ (match_operand:V2DI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "por\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
-(define_insn "*sse_xorti3_sse2"
+(define_insn "*sse2_xorti3"
[(set (match_operand:TI 0 "register_operand" "=x")
(xor:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
(match_operand:TI 2 "nonimmediate_operand" "xm")))]
"TARGET_SSE2
&& (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
"pxor\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_xorv2di3"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (xor:V2DI (match_operand:V2DI 1 "nonimmediate_operand" "%0")
+ (match_operand:V2DI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+ "pxor\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
;; Use xor, but don't show input operands so they aren't live before
;; this insn.
(define_insn "sse_clrv4sf"
[(set (match_operand:V4SF 0 "register_operand" "=x")
- (unspec:V4SF [(const_int 0)] 45))]
+ (unspec:V4SF [(const_int 0)] UNSPEC_NOP))]
"TARGET_SSE"
"xorps\t{%0, %0|%0, %0}"
- [(set_attr "type" "sse")
- (set_attr "memory" "none")])
+ [(set_attr "type" "sselog")
+ (set_attr "memory" "none")
+ (set_attr "mode" "V4SF")])
+
+;; Use xor, but don't show input operands so they aren't live before
+;; this insn.
+(define_insn "sse_clrv2df"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (unspec:V2DF [(const_int 0)] UNSPEC_NOP))]
+ "TARGET_SSE2"
+ "xorpd\t{%0, %0|%0, %0}"
+ [(set_attr "type" "sselog")
+ (set_attr "memory" "none")
+ (set_attr "mode" "V4SF")])
;; SSE mask-generating compares
@@ -18574,7 +19033,8 @@
(match_operand:V4SF 2 "register_operand" "x")]))]
"TARGET_SSE"
"cmp%D3ps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "V4SF")])
(define_insn "maskncmpv4sf3"
[(set (match_operand:V4SI 0 "register_operand" "=x")
@@ -18589,7 +19049,8 @@
else
return "cmpn%D3ps\t{%2, %0|%0, %2}";
}
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "V4SF")])
(define_insn "vmmaskcmpv4sf3"
[(set (match_operand:V4SI 0 "register_operand" "=x")
@@ -18597,11 +19058,12 @@
(match_operator:V4SI 3 "sse_comparison_operator"
[(match_operand:V4SF 1 "register_operand" "0")
(match_operand:V4SF 2 "register_operand" "x")])
- (match_dup 1)
+ (subreg:V4SI (match_dup 1) 0)
(const_int 1)))]
"TARGET_SSE"
"cmp%D3ss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "SF")])
(define_insn "vmmaskncmpv4sf3"
[(set (match_operand:V4SI 0 "register_operand" "=x")
@@ -18619,33 +19081,34 @@
else
return "cmpn%D3ss\t{%2, %0|%0, %2}";
}
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "SF")])
(define_insn "sse_comi"
[(set (reg:CCFP 17)
- (match_operator:CCFP 2 "sse_comparison_operator"
- [(vec_select:SF
- (match_operand:V4SF 0 "register_operand" "x")
- (parallel [(const_int 0)]))
- (vec_select:SF
- (match_operand:V4SF 1 "register_operand" "x")
- (parallel [(const_int 0)]))]))]
+ (compare:CCFP (vec_select:SF
+ (match_operand:V4SF 0 "register_operand" "x")
+ (parallel [(const_int 0)]))
+ (vec_select:SF
+ (match_operand:V4SF 1 "register_operand" "x")
+ (parallel [(const_int 0)]))))]
"TARGET_SSE"
"comiss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "SF")])
(define_insn "sse_ucomi"
[(set (reg:CCFPU 17)
- (match_operator:CCFPU 2 "sse_comparison_operator"
- [(vec_select:SF
- (match_operand:V4SF 0 "register_operand" "x")
- (parallel [(const_int 0)]))
- (vec_select:SF
- (match_operand:V4SF 1 "register_operand" "x")
- (parallel [(const_int 0)]))]))]
+ (compare:CCFPU (vec_select:SF
+ (match_operand:V4SF 0 "register_operand" "x")
+ (parallel [(const_int 0)]))
+ (vec_select:SF
+ (match_operand:V4SF 1 "register_operand" "x")
+ (parallel [(const_int 0)]))))]
"TARGET_SSE"
"ucomiss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "SF")])
;; SSE unpack
@@ -18666,7 +19129,8 @@
(const_int 5)))]
"TARGET_SSE"
"unpckhps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
(define_insn "sse_unpcklps"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18684,7 +19148,8 @@
(const_int 5)))]
"TARGET_SSE"
"unpcklps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
;; SSE min/max
@@ -18695,7 +19160,8 @@
(match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
"TARGET_SSE"
"maxps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V4SF")])
(define_insn "vmsmaxv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18706,7 +19172,8 @@
(const_int 1)))]
"TARGET_SSE"
"maxss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sse")
+ (set_attr "mode" "SF")])
(define_insn "sminv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18714,7 +19181,8 @@
(match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
"TARGET_SSE"
"minps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V4SF")])
(define_insn "vmsminv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18725,8 +19193,8 @@
(const_int 1)))]
"TARGET_SSE"
"minss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
-
+ [(set_attr "type" "sse")
+ (set_attr "mode" "SF")])
;; SSE <-> integer/MMX conversions
@@ -18739,7 +19207,8 @@
(const_int 12)))]
"TARGET_SSE"
"cvtpi2ps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
(define_insn "cvtps2pi"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -18748,16 +19217,19 @@
(parallel [(const_int 0) (const_int 1)])))]
"TARGET_SSE"
"cvtps2pi\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
(define_insn "cvttps2pi"
[(set (match_operand:V2SI 0 "register_operand" "=y")
(vec_select:V2SI
- (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] 30)
+ (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
+ UNSPEC_FIX)
(parallel [(const_int 0) (const_int 1)])))]
"TARGET_SSE"
"cvttps2pi\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "SF")])
(define_insn "cvtsi2ss"
[(set (match_operand:V4SF 0 "register_operand" "=x")
@@ -18768,7 +19240,21 @@
(const_int 14)))]
"TARGET_SSE"
"cvtsi2ss\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "SF")])
+
+(define_insn "cvtsi2ssq"
+ [(set (match_operand:V4SF 0 "register_operand" "=x,x")
+ (vec_merge:V4SF
+ (match_operand:V4SF 1 "register_operand" "0,0")
+ (vec_duplicate:V4SF
+ (float:SF (match_operand:DI 2 "nonimmediate_operand" "r,rm")))
+ (const_int 14)))]
+ "TARGET_SSE && TARGET_64BIT"
+ "cvtsi2ssq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "athlon_decode" "vector,vector")
+ (set_attr "mode" "SF")])
(define_insn "cvtss2si"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -18777,16 +19263,42 @@
(parallel [(const_int 0)])))]
"TARGET_SSE"
"cvtss2si\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "SF")])
+
+(define_insn "cvtss2siq"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (vec_select:DI
+ (fix:V4DI (match_operand:V4SF 1 "nonimmediate_operand" "x,m"))
+ (parallel [(const_int 0)])))]
+ "TARGET_SSE"
+ "cvtss2siq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "athlon_decode" "vector,vector")
+ (set_attr "mode" "SF")])
(define_insn "cvttss2si"
[(set (match_operand:SI 0 "register_operand" "=r")
(vec_select:SI
- (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] 30)
+ (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
+ UNSPEC_FIX)
(parallel [(const_int 0)])))]
"TARGET_SSE"
"cvttss2si\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "SF")])
+
+(define_insn "cvttss2siq"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (vec_select:DI
+ (unspec:V4DI [(match_operand:V4SF 1 "nonimmediate_operand" "x,xm")]
+ UNSPEC_FIX)
+ (parallel [(const_int 0)])))]
+ "TARGET_SSE && TARGET_64BIT"
+ "cvttss2siq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "SF")
+ (set_attr "athlon_decode" "vector,vector")])
;; MMX insns
@@ -18795,59 +19307,77 @@
(define_insn "addv8qi3"
[(set (match_operand:V8QI 0 "register_operand" "=y")
- (plus:V8QI (match_operand:V8QI 1 "register_operand" "0")
+ (plus:V8QI (match_operand:V8QI 1 "register_operand" "%0")
(match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"paddb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "addv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
- (plus:V4HI (match_operand:V4HI 1 "register_operand" "0")
+ (plus:V4HI (match_operand:V4HI 1 "register_operand" "%0")
(match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"paddw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "addv2si3"
[(set (match_operand:V2SI 0 "register_operand" "=y")
- (plus:V2SI (match_operand:V2SI 1 "register_operand" "0")
+ (plus:V2SI (match_operand:V2SI 1 "register_operand" "%0")
(match_operand:V2SI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"paddd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_adddi3"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (unspec:DI
+ [(plus:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "nonimmediate_operand" "ym"))]
+ UNSPEC_NOP))]
+ "TARGET_MMX"
+ "paddq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "ssaddv8qi3"
[(set (match_operand:V8QI 0 "register_operand" "=y")
- (ss_plus:V8QI (match_operand:V8QI 1 "register_operand" "0")
+ (ss_plus:V8QI (match_operand:V8QI 1 "register_operand" "%0")
(match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"paddsb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "ssaddv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
- (ss_plus:V4HI (match_operand:V4HI 1 "register_operand" "0")
+ (ss_plus:V4HI (match_operand:V4HI 1 "register_operand" "%0")
(match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"paddsw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "usaddv8qi3"
[(set (match_operand:V8QI 0 "register_operand" "=y")
- (us_plus:V8QI (match_operand:V8QI 1 "register_operand" "0")
+ (us_plus:V8QI (match_operand:V8QI 1 "register_operand" "%0")
(match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"paddusb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "usaddv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
- (us_plus:V4HI (match_operand:V4HI 1 "register_operand" "0")
+ (us_plus:V4HI (match_operand:V4HI 1 "register_operand" "%0")
(match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"paddusw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "subv8qi3"
[(set (match_operand:V8QI 0 "register_operand" "=y")
@@ -18855,7 +19385,8 @@
(match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"psubb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "subv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -18863,7 +19394,8 @@
(match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"psubw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "subv2si3"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -18871,7 +19403,19 @@
(match_operand:V2SI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"psubd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_subdi3"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (unspec:DI
+ [(minus:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "nonimmediate_operand" "ym"))]
+ UNSPEC_NOP))]
+ "TARGET_MMX"
+ "psubq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "sssubv8qi3"
[(set (match_operand:V8QI 0 "register_operand" "=y")
@@ -18879,7 +19423,8 @@
(match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"psubsb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "sssubv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -18887,7 +19432,8 @@
(match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"psubsw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "ussubv8qi3"
[(set (match_operand:V8QI 0 "register_operand" "=y")
@@ -18895,7 +19441,8 @@
(match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"psubusb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "ussubv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -18903,7 +19450,8 @@
(match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"psubusw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "mulv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -18911,7 +19459,8 @@
(match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"pmullw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxmul")
+ (set_attr "mode" "DI")])
(define_insn "smulv4hi3_highpart"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -18924,7 +19473,8 @@
(const_int 16))))]
"TARGET_MMX"
"pmulhw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxmul")
+ (set_attr "mode" "DI")])
(define_insn "umulv4hi3_highpart"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -18937,7 +19487,8 @@
(const_int 16))))]
"TARGET_SSE || TARGET_3DNOW_A"
"pmulhuw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxmul")
+ (set_attr "mode" "DI")])
(define_insn "mmx_pmaddwd"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -18958,7 +19509,8 @@
(const_int 3)]))))))]
"TARGET_MMX"
"pmaddwd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxmul")
+ (set_attr "mode" "DI")])
;; MMX logical operations
@@ -18968,49 +19520,58 @@
(define_insn "mmx_iordi3"
[(set (match_operand:DI 0 "register_operand" "=y")
(unspec:DI
- [(ior:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "nonimmediate_operand" "ym"))] 45))]
+ [(ior:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "nonimmediate_operand" "ym"))]
+ UNSPEC_NOP))]
"TARGET_MMX"
"por\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "mmx_xordi3"
[(set (match_operand:DI 0 "register_operand" "=y")
(unspec:DI
- [(xor:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "nonimmediate_operand" "ym"))] 45))]
+ [(xor:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "nonimmediate_operand" "ym"))]
+ UNSPEC_NOP))]
"TARGET_MMX"
"pxor\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")
(set_attr "memory" "none")])
;; Same as pxor, but don't show input operands so that we don't think
;; they are live.
(define_insn "mmx_clrdi"
[(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI [(const_int 0)] 45))]
+ (unspec:DI [(const_int 0)] UNSPEC_NOP))]
"TARGET_MMX"
"pxor\t{%0, %0|%0, %0}"
- [(set_attr "type" "mmx")
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")
(set_attr "memory" "none")])
(define_insn "mmx_anddi3"
[(set (match_operand:DI 0 "register_operand" "=y")
(unspec:DI
- [(and:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "nonimmediate_operand" "ym"))] 45))]
+ [(and:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "nonimmediate_operand" "ym"))]
+ UNSPEC_NOP))]
"TARGET_MMX"
"pand\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "mmx_nanddi3"
[(set (match_operand:DI 0 "register_operand" "=y")
(unspec:DI
[(and:DI (not:DI (match_operand:DI 1 "register_operand" "0"))
- (match_operand:DI 2 "nonimmediate_operand" "ym"))] 45))]
+ (match_operand:DI 2 "nonimmediate_operand" "ym"))]
+ UNSPEC_NOP))]
"TARGET_MMX"
"pandn\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
;; MMX unsigned averages/sum of absolute differences
@@ -19032,7 +19593,8 @@
(const_int 1)))]
"TARGET_SSE || TARGET_3DNOW_A"
"pavgb\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
(define_insn "mmx_uavgv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -19047,15 +19609,18 @@
(const_int 1)))]
"TARGET_SSE || TARGET_3DNOW_A"
"pavgw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
(define_insn "mmx_psadbw"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (abs:V8QI (minus:V8QI (match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym"))))]
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (unspec:DI [(match_operand:V8QI 1 "register_operand" "0")
+ (match_operand:V8QI 2 "nonimmediate_operand" "ym")]
+ UNSPEC_PSADBW))]
"TARGET_SSE || TARGET_3DNOW_A"
"psadbw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
;; MMX insert/extract/shuffle
@@ -19068,7 +19633,8 @@
(match_operand:SI 3 "immediate_operand" "i")))]
"TARGET_SSE || TARGET_3DNOW_A"
"pinsrw\t{%3, %2, %0|%0, %2, %3}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
(define_insn "mmx_pextrw"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -19077,15 +19643,18 @@
[(match_operand:SI 2 "immediate_operand" "i")]))))]
"TARGET_SSE || TARGET_3DNOW_A"
"pextrw\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
(define_insn "mmx_pshufw"
[(set (match_operand:V4HI 0 "register_operand" "=y")
(unspec:V4HI [(match_operand:V4HI 1 "register_operand" "0")
- (match_operand:SI 2 "immediate_operand" "i")] 41))]
+ (match_operand:SI 2 "immediate_operand" "i")]
+ UNSPEC_SHUFFLE))]
"TARGET_SSE || TARGET_3DNOW_A"
"pshufw\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
;; MMX mask-generating comparisons
@@ -19096,7 +19665,8 @@
(match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"pcmpeqb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcmp")
+ (set_attr "mode" "DI")])
(define_insn "eqv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -19104,7 +19674,8 @@
(match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"pcmpeqw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcmp")
+ (set_attr "mode" "DI")])
(define_insn "eqv2si3"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -19112,7 +19683,8 @@
(match_operand:V2SI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"pcmpeqd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcmp")
+ (set_attr "mode" "DI")])
(define_insn "gtv8qi3"
[(set (match_operand:V8QI 0 "register_operand" "=y")
@@ -19120,7 +19692,8 @@
(match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"pcmpgtb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcmp")
+ (set_attr "mode" "DI")])
(define_insn "gtv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -19128,7 +19701,8 @@
(match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"pcmpgtw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcmp")
+ (set_attr "mode" "DI")])
(define_insn "gtv2si3"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -19136,7 +19710,8 @@
(match_operand:V2SI 2 "nonimmediate_operand" "ym")))]
"TARGET_MMX"
"pcmpgtd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcmp")
+ (set_attr "mode" "DI")])
;; MMX max/min insns
@@ -19147,7 +19722,8 @@
(match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
"TARGET_SSE || TARGET_3DNOW_A"
"pmaxub\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "smaxv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -19155,7 +19731,8 @@
(match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
"TARGET_SSE || TARGET_3DNOW_A"
"pmaxsw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "uminv8qi3"
[(set (match_operand:V8QI 0 "register_operand" "=y")
@@ -19163,7 +19740,8 @@
(match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
"TARGET_SSE || TARGET_3DNOW_A"
"pminub\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
(define_insn "sminv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -19171,7 +19749,8 @@
(match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
"TARGET_SSE || TARGET_3DNOW_A"
"pminsw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sse")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
;; MMX shifts
@@ -19182,7 +19761,8 @@
(match_operand:DI 2 "nonmemory_operand" "yi")))]
"TARGET_MMX"
"psraw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
(define_insn "ashrv2si3"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -19190,7 +19770,8 @@
(match_operand:DI 2 "nonmemory_operand" "yi")))]
"TARGET_MMX"
"psrad\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
(define_insn "lshrv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -19198,7 +19779,8 @@
(match_operand:DI 2 "nonmemory_operand" "yi")))]
"TARGET_MMX"
"psrlw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
(define_insn "lshrv2si3"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -19206,17 +19788,20 @@
(match_operand:DI 2 "nonmemory_operand" "yi")))]
"TARGET_MMX"
"psrld\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
;; See logical MMX insns.
(define_insn "mmx_lshrdi3"
[(set (match_operand:DI 0 "register_operand" "=y")
(unspec:DI
[(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yi"))] 45))]
+ (match_operand:DI 2 "nonmemory_operand" "yi"))]
+ UNSPEC_NOP))]
"TARGET_MMX"
"psrlq\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
(define_insn "ashlv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -19224,7 +19809,8 @@
(match_operand:DI 2 "nonmemory_operand" "yi")))]
"TARGET_MMX"
"psllw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
(define_insn "ashlv2si3"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -19232,17 +19818,20 @@
(match_operand:DI 2 "nonmemory_operand" "yi")))]
"TARGET_MMX"
"pslld\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
;; See logical MMX insns.
(define_insn "mmx_ashldi3"
[(set (match_operand:DI 0 "register_operand" "=y")
(unspec:DI
[(ashift:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yi"))] 45))]
+ (match_operand:DI 2 "nonmemory_operand" "yi"))]
+ UNSPEC_NOP))]
"TARGET_MMX"
"psllq\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
;; MMX pack/unpack insns.
@@ -19254,7 +19843,8 @@
(ss_truncate:V4QI (match_operand:V4HI 2 "register_operand" "y"))))]
"TARGET_MMX"
"packsswb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
(define_insn "mmx_packssdw"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -19263,7 +19853,8 @@
(ss_truncate:V2HI (match_operand:V2SI 2 "register_operand" "y"))))]
"TARGET_MMX"
"packssdw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
(define_insn "mmx_packuswb"
[(set (match_operand:V8QI 0 "register_operand" "=y")
@@ -19272,7 +19863,8 @@
(us_truncate:V4QI (match_operand:V4HI 2 "register_operand" "y"))))]
"TARGET_MMX"
"packuswb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
(define_insn "mmx_punpckhbw"
[(set (match_operand:V8QI 0 "register_operand" "=y")
@@ -19298,7 +19890,8 @@
(const_int 85)))]
"TARGET_MMX"
"punpckhbw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
(define_insn "mmx_punpckhwd"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -19316,21 +19909,21 @@
(const_int 5)))]
"TARGET_MMX"
"punpckhwd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
(define_insn "mmx_punpckhdq"
[(set (match_operand:V2SI 0 "register_operand" "=y")
(vec_merge:V2SI
- (vec_select:V2SI (match_operand:V2SI 1 "register_operand" "0")
- (parallel [(const_int 0)
- (const_int 1)]))
+ (match_operand:V2SI 1 "register_operand" "0")
(vec_select:V2SI (match_operand:V2SI 2 "register_operand" "y")
(parallel [(const_int 1)
(const_int 0)]))
(const_int 1)))]
"TARGET_MMX"
"punpckhdq\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
(define_insn "mmx_punpcklbw"
[(set (match_operand:V8QI 0 "register_operand" "=y")
@@ -19356,7 +19949,8 @@
(const_int 85)))]
"TARGET_MMX"
"punpcklbw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
(define_insn "mmx_punpcklwd"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -19374,7 +19968,8 @@
(const_int 5)))]
"TARGET_MMX"
"punpcklwd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
(define_insn "mmx_punpckldq"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -19382,19 +19977,18 @@
(vec_select:V2SI (match_operand:V2SI 1 "register_operand" "0")
(parallel [(const_int 1)
(const_int 0)]))
- (vec_select:V2SI (match_operand:V2SI 2 "register_operand" "y")
- (parallel [(const_int 0)
- (const_int 1)]))
+ (match_operand:V2SI 2 "register_operand" "y")
(const_int 1)))]
"TARGET_MMX"
"punpckldq\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
;; Miscellaneous stuff
(define_insn "emms"
- [(unspec_volatile [(const_int 0)] 31)
+ [(unspec_volatile [(const_int 0)] UNSPECV_EMMS)
(clobber (reg:XF 8))
(clobber (reg:XF 9))
(clobber (reg:XF 10))
@@ -19417,23 +20011,24 @@
(set_attr "memory" "unknown")])
(define_insn "ldmxcsr"
- [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] 37)]
- "TARGET_MMX"
+ [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")]
+ UNSPECV_LDMXCSR)]
+ "TARGET_SSE"
"ldmxcsr\t%0"
- [(set_attr "type" "mmx")
+ [(set_attr "type" "sse")
(set_attr "memory" "load")])
(define_insn "stmxcsr"
[(set (match_operand:SI 0 "memory_operand" "=m")
- (unspec_volatile:SI [(const_int 0)] 40))]
- "TARGET_MMX"
+ (unspec_volatile:SI [(const_int 0)] UNSPECV_STMXCSR))]
+ "TARGET_SSE"
"stmxcsr\t%0"
- [(set_attr "type" "mmx")
+ [(set_attr "type" "sse")
(set_attr "memory" "store")])
(define_expand "sfence"
[(set (match_dup 0)
- (unspec:BLK [(match_dup 0)] 44))]
+ (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
"TARGET_SSE || TARGET_3DNOW_A"
{
operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
@@ -19442,7 +20037,7 @@
(define_insn "*sfence_insn"
[(set (match_operand:BLK 0 "" "")
- (unspec:BLK [(match_dup 0)] 44))]
+ (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
"TARGET_SSE || TARGET_3DNOW_A"
"sfence"
[(set_attr "type" "sse")
@@ -19457,7 +20052,7 @@
(reg:DI 25)
(reg:DI 26)
(reg:DI 27)
- (reg:DI 28)] 13))
+ (reg:DI 28)] UNSPEC_SSE_PROLOGUE_SAVE))
(use (match_operand:DI 1 "register_operand" ""))
(use (match_operand:DI 2 "immediate_operand" ""))
(use (label_ref:DI (match_operand 3 "" "")))])]
@@ -19474,7 +20069,7 @@
(reg:DI 25)
(reg:DI 26)
(reg:DI 27)
- (reg:DI 28)] 13))
+ (reg:DI 28)] UNSPEC_SSE_PROLOGUE_SAVE))
(use (match_operand:DI 1 "register_operand" "r"))
(use (match_operand:DI 2 "const_int_operand" "i"))
(use (label_ref:DI (match_operand 3 "" "X")))]
@@ -19517,7 +20112,8 @@
(match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
"TARGET_3DNOW"
"pfadd\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
(define_insn "subv2sf3"
[(set (match_operand:V2SF 0 "register_operand" "=y")
@@ -19525,7 +20121,8 @@
(match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
"TARGET_3DNOW"
"pfsub\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
(define_insn "subrv2sf3"
[(set (match_operand:V2SF 0 "register_operand" "=y")
@@ -19533,7 +20130,8 @@
(match_operand:V2SF 1 "register_operand" "0")))]
"TARGET_3DNOW"
"pfsubr\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
(define_insn "gtv2sf3"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -19541,7 +20139,8 @@
(match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
"TARGET_3DNOW"
"pfcmpgt\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcmp")
+ (set_attr "mode" "V2SF")])
(define_insn "gev2sf3"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -19549,7 +20148,8 @@
(match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
"TARGET_3DNOW"
"pfcmpge\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcmp")
+ (set_attr "mode" "V2SF")])
(define_insn "eqv2sf3"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -19557,7 +20157,8 @@
(match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
"TARGET_3DNOW"
"pfcmpeq\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcmp")
+ (set_attr "mode" "V2SF")])
(define_insn "pfmaxv2sf3"
[(set (match_operand:V2SF 0 "register_operand" "=y")
@@ -19565,7 +20166,8 @@
(match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
"TARGET_3DNOW"
"pfmax\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
(define_insn "pfminv2sf3"
[(set (match_operand:V2SF 0 "register_operand" "=y")
@@ -19573,7 +20175,8 @@
(match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
"TARGET_3DNOW"
"pfmin\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
(define_insn "mulv2sf3"
[(set (match_operand:V2SF 0 "register_operand" "=y")
@@ -19581,10 +20184,11 @@
(match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
"TARGET_3DNOW"
"pfmul\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxmul")
+ (set_attr "mode" "V2SF")])
(define_insn "femms"
- [(unspec_volatile [(const_int 0)] 46)
+ [(unspec_volatile [(const_int 0)] UNSPECV_FEMMS)
(clobber (reg:XF 8))
(clobber (reg:XF 9))
(clobber (reg:XF 10))
@@ -19603,14 +20207,16 @@
(clobber (reg:DI 36))]
"TARGET_3DNOW"
"femms"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmx")
+ (set_attr "memory" "none")])
(define_insn "pf2id"
[(set (match_operand:V2SI 0 "register_operand" "=y")
(fix:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "ym")))]
"TARGET_3DNOW"
"pf2id\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "V2SF")])
(define_insn "pf2iw"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -19619,7 +20225,8 @@
(fix:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "ym")))))]
"TARGET_3DNOW_A"
"pf2iw\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "V2SF")])
(define_insn "pfacc"
[(set (match_operand:V2SF 0 "register_operand" "=y")
@@ -19636,7 +20243,8 @@
(parallel [(const_int 1)])))))]
"TARGET_3DNOW"
"pfacc\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
(define_insn "pfnacc"
[(set (match_operand:V2SF 0 "register_operand" "=y")
@@ -19653,7 +20261,8 @@
(parallel [(const_int 1)])))))]
"TARGET_3DNOW_A"
"pfnacc\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
(define_insn "pfpnacc"
[(set (match_operand:V2SF 0 "register_operand" "=y")
@@ -19670,7 +20279,8 @@
(parallel [(const_int 1)])))))]
"TARGET_3DNOW_A"
"pfpnacc\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
(define_insn "pi2fw"
[(set (match_operand:V2SF 0 "register_operand" "=y")
@@ -19686,14 +20296,16 @@
(parallel [(const_int 1)])))))))]
"TARGET_3DNOW_A"
"pi2fw\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "V2SF")])
(define_insn "floatv2si2"
[(set (match_operand:V2SF 0 "register_operand" "=y")
(float:V2SF (match_operand:V2SI 1 "nonimmediate_operand" "ym")))]
"TARGET_3DNOW"
"pi2fd\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "V2SF")])
;; This insn is identical to pavgb in operation, but the opcode is
;; different. To avoid accidentally matching pavgb, use an unspec.
@@ -19702,50 +20314,62 @@
[(set (match_operand:V8QI 0 "register_operand" "=y")
(unspec:V8QI
[(match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")] 49))]
+ (match_operand:V8QI 2 "nonimmediate_operand" "ym")]
+ UNSPEC_PAVGUSB))]
"TARGET_3DNOW"
"pavgusb\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "TI")])
;; 3DNow reciprical and sqrt
(define_insn "pfrcpv2sf2"
[(set (match_operand:V2SF 0 "register_operand" "=y")
- (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")] 50))]
+ (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")]
+ UNSPEC_PFRCP))]
"TARGET_3DNOW"
"pfrcp\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmx")
+ (set_attr "mode" "TI")])
(define_insn "pfrcpit1v2sf3"
[(set (match_operand:V2SF 0 "register_operand" "=y")
(unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")] 51))]
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
+ UNSPEC_PFRCPIT1))]
"TARGET_3DNOW"
"pfrcpit1\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmx")
+ (set_attr "mode" "TI")])
(define_insn "pfrcpit2v2sf3"
[(set (match_operand:V2SF 0 "register_operand" "=y")
(unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")] 52))]
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
+ UNSPEC_PFRCPIT2))]
"TARGET_3DNOW"
"pfrcpit2\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmx")
+ (set_attr "mode" "TI")])
(define_insn "pfrsqrtv2sf2"
[(set (match_operand:V2SF 0 "register_operand" "=y")
- (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")] 53))]
+ (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")]
+ UNSPEC_PFRSQRT))]
"TARGET_3DNOW"
- "pfrsqrt\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmx")])
+ "pfrsqrt\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmx")
+ (set_attr "mode" "TI")])
(define_insn "pfrsqit1v2sf3"
[(set (match_operand:V2SF 0 "register_operand" "=y")
(unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")] 54))]
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
+ UNSPEC_PFRSQIT1))]
"TARGET_3DNOW"
"pfrsqit1\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmx")
+ (set_attr "mode" "TI")])
(define_insn "pmulhrwv4hi3"
[(set (match_operand:V4HI 0 "register_operand" "=y")
@@ -19764,7 +20388,8 @@
(const_int 16))))]
"TARGET_3DNOW"
"pmulhrw\\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxmul")
+ (set_attr "mode" "TI")])
(define_insn "pswapdv2si2"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -19772,7 +20397,8 @@
(parallel [(const_int 1) (const_int 0)])))]
"TARGET_3DNOW_A"
"pswapd\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "TI")])
(define_insn "pswapdv2sf2"
[(set (match_operand:V2SF 0 "register_operand" "=y")
@@ -19780,7 +20406,8 @@
(parallel [(const_int 1) (const_int 0)])))]
"TARGET_3DNOW_A"
"pswapd\\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "TI")])
(define_expand "prefetch"
[(prefetch (match_operand 0 "address_operand" "")
@@ -19843,7 +20470,8 @@
return patterns[locality];
}
- [(set_attr "type" "sse")])
+ [(set_attr "type" "sse")
+ (set_attr "memory" "none")])
(define_insn "*prefetch_3dnow"
[(prefetch (match_operand:SI 0 "address_operand" "p")
@@ -19870,4 +20498,1577 @@
else
return "prefetchw\t%a0";
}
- [(set_attr "type" "mmx")])
+ [(set_attr "type" "mmx")
+ (set_attr "memory" "none")])
+
+;; SSE2 support
+
+(define_insn "addv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (plus:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "addpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "vmaddv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF (plus:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "addsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "DF")])
+
+(define_insn "subv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (minus:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "subpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "vmsubv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF (minus:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "subsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "DF")])
+
+(define_insn "mulv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (mult:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "mulpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssemul")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "vmmulv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF (mult:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "mulsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssemul")
+ (set_attr "mode" "DF")])
+
+(define_insn "divv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (div:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "divpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssediv")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "vmdivv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF (div:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "divsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssediv")
+ (set_attr "mode" "DF")])
+
+;; SSE min/max
+
+(define_insn "smaxv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (smax:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "maxpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "vmsmaxv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF (smax:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "maxsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "DF")])
+
+(define_insn "sminv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (smin:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "minpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "vmsminv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF (smin:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "minsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "DF")])
+;; SSE2 square root. There doesn't appear to be an extension for the
+;; reciprocal/rsqrt instructions if the Intel manual is to be believed.
+
+(define_insn "sqrtv2df2"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (sqrt:V2DF (match_operand:V2DF 1 "register_operand" "xm")))]
+ "TARGET_SSE2"
+ "sqrtpd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "vmsqrtv2df2"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF (sqrt:V2DF (match_operand:V2DF 1 "register_operand" "xm"))
+ (match_operand:V2DF 2 "register_operand" "0")
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "sqrtsd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "SF")])
+
+;; SSE mask-generating compares
+
+(define_insn "maskcmpv2df3"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (match_operator:V2DI 3 "sse_comparison_operator"
+ [(match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "x")]))]
+ "TARGET_SSE2"
+ "cmp%D3pd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "maskncmpv2df3"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (not:V2DI
+ (match_operator:V2DI 3 "sse_comparison_operator"
+ [(match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "x")])))]
+ "TARGET_SSE2"
+{
+ if (GET_CODE (operands[3]) == UNORDERED)
+ return "cmpordps\t{%2, %0|%0, %2}";
+ else
+ return "cmpn%D3pd\t{%2, %0|%0, %2}";
+}
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "vmmaskcmpv2df3"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (vec_merge:V2DI
+ (match_operator:V2DI 3 "sse_comparison_operator"
+ [(match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "x")])
+ (subreg:V2DI (match_dup 1) 0)
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "cmp%D3sd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "DF")])
+
+(define_insn "vmmaskncmpv2df3"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (vec_merge:V2DI
+ (not:V2DI
+ (match_operator:V2DI 3 "sse_comparison_operator"
+ [(match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "x")]))
+ (subreg:V2DI (match_dup 1) 0)
+ (const_int 1)))]
+ "TARGET_SSE2"
+{
+ if (GET_CODE (operands[3]) == UNORDERED)
+ return "cmpordsd\t{%2, %0|%0, %2}";
+ else
+ return "cmpn%D3sd\t{%2, %0|%0, %2}";
+}
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "DF")])
+
+(define_insn "sse2_comi"
+ [(set (reg:CCFP 17)
+ (compare:CCFP (vec_select:DF
+ (match_operand:V2DF 0 "register_operand" "x")
+ (parallel [(const_int 0)]))
+ (vec_select:DF
+ (match_operand:V2DF 1 "register_operand" "x")
+ (parallel [(const_int 0)]))))]
+ "TARGET_SSE2"
+ "comisd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "DF")])
+
+(define_insn "sse2_ucomi"
+ [(set (reg:CCFPU 17)
+ (compare:CCFPU (vec_select:DF
+ (match_operand:V2DF 0 "register_operand" "x")
+ (parallel [(const_int 0)]))
+ (vec_select:DF
+ (match_operand:V2DF 1 "register_operand" "x")
+ (parallel [(const_int 0)]))))]
+ "TARGET_SSE2"
+ "ucomisd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "DF")])
+
+;; SSE Strange Moves.
+
+(define_insn "sse2_movmskpd"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:V2DF 1 "register_operand" "x")]
+ UNSPEC_MOVMSK))]
+ "TARGET_SSE2"
+ "movmskpd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_pmovmskb"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:V16QI 1 "register_operand" "x")]
+ UNSPEC_MOVMSK))]
+ "TARGET_SSE2"
+ "pmovmskb\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_maskmovdqu"
+ [(set (mem:V16QI (match_operand:SI 0 "register_operand" "D"))
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "x")
+ (match_operand:V16QI 2 "register_operand" "x")]
+ UNSPEC_MASKMOV))]
+ "TARGET_SSE2"
+ ;; @@@ check ordering of operands in intel/nonintel syntax
+ "maskmovdqu\t{%2, %1|%1, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_maskmovdqu_rex64"
+ [(set (mem:V16QI (match_operand:DI 0 "register_operand" "D"))
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "x")
+ (match_operand:V16QI 2 "register_operand" "x")]
+ UNSPEC_MASKMOV))]
+ "TARGET_SSE2"
+ ;; @@@ check ordering of operands in intel/nonintel syntax
+ "maskmovdqu\t{%2, %1|%1, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_movntv2df"
+ [(set (match_operand:V2DF 0 "memory_operand" "=m")
+ (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "x")]
+ UNSPEC_MOVNT))]
+ "TARGET_SSE2"
+ "movntpd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_movntv2di"
+ [(set (match_operand:V2DI 0 "memory_operand" "=m")
+ (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "x")]
+ UNSPEC_MOVNT))]
+ "TARGET_SSE2"
+ "movntdq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_movntsi"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
+ UNSPEC_MOVNT))]
+ "TARGET_SSE2"
+ "movnti\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+;; SSE <-> integer/MMX conversions
+
+;; Conversions between SI and SF
+
+(define_insn "cvtdq2ps"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (float:V4SF (match_operand:V4SI 1 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "cvtdq2ps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "cvtps2dq"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "cvtps2dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "cvttps2dq"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
+ UNSPEC_FIX))]
+ "TARGET_SSE2"
+ "cvttps2dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+;; Conversions between SI and DF
+
+(define_insn "cvtdq2pd"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (float:V2DF (vec_select:V2SI
+ (match_operand:V4SI 1 "nonimmediate_operand" "xm")
+ (parallel
+ [(const_int 0)
+ (const_int 1)]))))]
+ "TARGET_SSE2"
+ "cvtdq2pd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "cvtpd2dq"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (vec_concat:V4SI
+ (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "xm"))
+ (const_vector:V2SI [(const_int 0) (const_int 0)])))]
+ "TARGET_SSE2"
+ "cvtpd2dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "cvttpd2dq"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (vec_concat:V4SI
+ (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "xm")]
+ UNSPEC_FIX)
+ (const_vector:V2SI [(const_int 0) (const_int 0)])))]
+ "TARGET_SSE2"
+ "cvttpd2dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "cvtpd2pi"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "cvtpd2pi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "cvttpd2pi"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "xm")]
+ UNSPEC_FIX))]
+ "TARGET_SSE2"
+ "cvttpd2pi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "cvtpi2pd"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (float:V2DF (match_operand:V2SI 1 "nonimmediate_operand" "ym")))]
+ "TARGET_SSE2"
+ "cvtpi2pd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+;; Conversions between SI and DF
+
+(define_insn "cvtsd2si"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (fix:SI (vec_select:DF (match_operand:V2DF 1 "register_operand" "xm")
+ (parallel [(const_int 0)]))))]
+ "TARGET_SSE2"
+ "cvtsd2si\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "SI")])
+
+(define_insn "cvtsd2siq"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (fix:DI (vec_select:DF (match_operand:V2DF 1 "register_operand" "xm")
+ (parallel [(const_int 0)]))))]
+ "TARGET_SSE2 && TARGET_64BIT"
+ "cvtsd2siq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "SI")])
+
+(define_insn "cvttsd2si"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(vec_select:DF (match_operand:V2DF 1 "register_operand" "xm")
+ (parallel [(const_int 0)]))] UNSPEC_FIX))]
+ "TARGET_SSE2"
+ "cvttsd2si\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "SI")])
+
+(define_insn "cvttsd2siq"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (unspec:DI [(vec_select:DF (match_operand:V2DF 1 "register_operand" "x,xm")
+ (parallel [(const_int 0)]))] UNSPEC_FIX))]
+ "TARGET_SSE2 && TARGET_64BIT"
+ "cvttsd2siq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "DI")
+ (set_attr "athlon_decode" "vector,vector")])
+
+(define_insn "cvtsi2sd"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (vec_duplicate:V2DF
+ (float:DF
+ (match_operand:SI 2 "nonimmediate_operand" "rm")))
+ (const_int 2)))]
+ "TARGET_SSE2"
+ "cvtsi2sd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "DF")])
+
+(define_insn "cvtsi2sdq"
+ [(set (match_operand:V2DF 0 "register_operand" "=x,x")
+ (vec_merge:V2DF (match_operand:V2DF 1 "register_operand" "0,0")
+ (vec_duplicate:V2DF
+ (float:DF
+ (match_operand:DI 2 "nonimmediate_operand" "r,rm")))
+ (const_int 2)))]
+ "TARGET_SSE2 && TARGET_64BIT"
+ "cvtsi2sdq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "DF")
+ (set_attr "athlon_decode" "vector,direct")])
+
+;; Conversions between SF and DF
+
+(define_insn "cvtsd2ss"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_merge:V4SF (match_operand:V4SF 1 "register_operand" "0")
+ (vec_duplicate:V4SF
+ (float_truncate:V2SF
+ (match_operand:V2DF 2 "register_operand" "xm")))
+ (const_int 14)))]
+ "TARGET_SSE2"
+ "cvtsd2ss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "SF")])
+
+(define_insn "cvtss2sd"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (float_extend:V2DF
+ (vec_select:V2SF
+ (match_operand:V4SF 2 "register_operand" "xm")
+ (parallel [(const_int 0)
+ (const_int 1)])))
+ (const_int 2)))]
+ "TARGET_SSE2"
+ "cvtss2sd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "DF")])
+
+(define_insn "cvtpd2ps"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (subreg:V4SF
+ (vec_concat:V4SI
+ (subreg:V2SI (float_truncate:V2SF
+ (match_operand:V2DF 1 "nonimmediate_operand" "xm")) 0)
+ (const_vector:V2SI [(const_int 0) (const_int 0)])) 0))]
+ "TARGET_SSE2"
+ "cvtpd2ps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "cvtps2pd"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (float_extend:V2DF
+ (vec_select:V2SF (match_operand:V4SF 1 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0)
+ (const_int 1)]))))]
+ "TARGET_SSE2"
+ "cvtps2pd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+;; SSE2 variants of MMX insns
+
+;; MMX arithmetic
+
+(define_insn "addv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (plus:V16QI (match_operand:V16QI 1 "register_operand" "%0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "paddb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "addv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (plus:V8HI (match_operand:V8HI 1 "register_operand" "%0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "paddw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "addv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (plus:V4SI (match_operand:V4SI 1 "register_operand" "%0")
+ (match_operand:V4SI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "paddd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "addv2di3"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (plus:V2DI (match_operand:V2DI 1 "register_operand" "%0")
+ (match_operand:V2DI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "paddq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "ssaddv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (ss_plus:V16QI (match_operand:V16QI 1 "register_operand" "%0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "paddsb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "ssaddv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (ss_plus:V8HI (match_operand:V8HI 1 "register_operand" "%0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "paddsw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "usaddv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (us_plus:V16QI (match_operand:V16QI 1 "register_operand" "%0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "paddusb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "usaddv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (us_plus:V8HI (match_operand:V8HI 1 "register_operand" "%0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "paddusw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "subv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (minus:V16QI (match_operand:V16QI 1 "register_operand" "0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "psubb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "subv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (minus:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "psubw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "subv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (minus:V4SI (match_operand:V4SI 1 "register_operand" "0")
+ (match_operand:V4SI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "psubd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "subv2di3"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (minus:V2DI (match_operand:V2DI 1 "register_operand" "0")
+ (match_operand:V2DI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "psubq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "sssubv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (ss_minus:V16QI (match_operand:V16QI 1 "register_operand" "0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "psubsb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "sssubv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (ss_minus:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "psubsw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "ussubv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (us_minus:V16QI (match_operand:V16QI 1 "register_operand" "0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "psubusb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "ussubv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (us_minus:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "psubusw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "mulv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (mult:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "pmullw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseimul")
+ (set_attr "mode" "TI")])
+
+(define_insn "smulv8hi3_highpart"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (truncate:V8HI
+ (lshiftrt:V8SI
+ (mult:V8SI (sign_extend:V8SI (match_operand:V8HI 1 "register_operand" "0"))
+ (sign_extend:V8SI (match_operand:V8HI 2 "nonimmediate_operand" "xm")))
+ (const_int 16))))]
+ "TARGET_SSE2"
+ "pmulhw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseimul")
+ (set_attr "mode" "TI")])
+
+(define_insn "umulv8hi3_highpart"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (truncate:V8HI
+ (lshiftrt:V8SI
+ (mult:V8SI (zero_extend:V8SI (match_operand:V8HI 1 "register_operand" "0"))
+ (zero_extend:V8SI (match_operand:V8HI 2 "nonimmediate_operand" "xm")))
+ (const_int 16))))]
+ "TARGET_SSE2"
+ "pmulhuw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseimul")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_umulsidi3"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (mult:DI (zero_extend:DI (vec_select:SI
+ (match_operand:V2SI 1 "register_operand" "0")
+ (parallel [(const_int 0)])))
+ (zero_extend:DI (vec_select:SI
+ (match_operand:V2SI 2 "nonimmediate_operand" "ym")
+ (parallel [(const_int 0)])))))]
+ "TARGET_SSE2"
+ "pmuludq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseimul")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_umulv2siv2di3"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (mult:V2DI (zero_extend:V2DI
+ (vec_select:V2SI
+ (match_operand:V4SI 1 "register_operand" "0")
+ (parallel [(const_int 0) (const_int 2)])))
+ (zero_extend:V2DI
+ (vec_select:V2SI
+ (match_operand:V4SI 2 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0) (const_int 2)])))))]
+ "TARGET_SSE2"
+ "pmuludq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseimul")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_pmaddwd"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (plus:V4SI
+ (mult:V4SI
+ (sign_extend:V4SI (vec_select:V4HI (match_operand:V8HI 1 "register_operand" "0")
+ (parallel [(const_int 0)
+ (const_int 2)
+ (const_int 4)
+ (const_int 6)])))
+ (sign_extend:V4SI (vec_select:V4HI (match_operand:V8HI 2 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0)
+ (const_int 2)
+ (const_int 4)
+ (const_int 6)]))))
+ (mult:V4SI
+ (sign_extend:V4SI (vec_select:V4HI (match_dup 1)
+ (parallel [(const_int 1)
+ (const_int 3)
+ (const_int 5)
+ (const_int 7)])))
+ (sign_extend:V4SI (vec_select:V4HI (match_dup 2)
+ (parallel [(const_int 1)
+ (const_int 3)
+ (const_int 5)
+ (const_int 7)]))))))]
+ "TARGET_SSE2"
+ "pmaddwd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+;; Same as pxor, but don't show input operands so that we don't think
+;; they are live.
+(define_insn "sse2_clrti"
+ [(set (match_operand:TI 0 "register_operand" "=x") (const_int 0))]
+ "TARGET_SSE2"
+ "pxor\t{%0, %0|%0, %0}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "memory" "none")
+ (set_attr "mode" "TI")])
+
+;; MMX unsigned averages/sum of absolute differences
+
+(define_insn "sse2_uavgv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (ashiftrt:V16QI
+ (plus:V16QI (plus:V16QI
+ (match_operand:V16QI 1 "register_operand" "0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm"))
+ (const_vector:V16QI [(const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)]))
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "pavgb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_uavgv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (ashiftrt:V8HI
+ (plus:V8HI (plus:V8HI
+ (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm"))
+ (const_vector:V8HI [(const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)]))
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "pavgw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+;; @@@ this isn't the right representation.
+(define_insn "sse2_psadbw"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (unspec:V2DI [(match_operand:V16QI 1 "register_operand" "0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")]
+ UNSPEC_PSADBW))]
+ "TARGET_SSE2"
+ "psadbw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+
+;; MMX insert/extract/shuffle
+
+(define_insn "sse2_pinsrw"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (vec_merge:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (vec_duplicate:V8HI
+ (truncate:HI
+ (match_operand:SI 2 "nonimmediate_operand" "rm")))
+ (match_operand:SI 3 "immediate_operand" "i")))]
+ "TARGET_SSE2"
+ "pinsrw\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_pextrw"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI
+ (vec_select:HI (match_operand:V8HI 1 "register_operand" "x")
+ (parallel
+ [(match_operand:SI 2 "immediate_operand" "i")]))))]
+ "TARGET_SSE2"
+ "pextrw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_pshufd"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "0")
+ (match_operand:SI 2 "immediate_operand" "i")]
+ UNSPEC_SHUFFLE))]
+ "TARGET_SSE2"
+ "pshufd\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_pshuflw"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:SI 2 "immediate_operand" "i")]
+ UNSPEC_PSHUFLW))]
+ "TARGET_SSE2"
+ "pshuflw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_pshufhw"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:SI 2 "immediate_operand" "i")]
+ UNSPEC_PSHUFHW))]
+ "TARGET_SSE2"
+ "pshufhw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+;; MMX mask-generating comparisons
+
+(define_insn "eqv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (eq:V16QI (match_operand:V16QI 1 "register_operand" "0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "pcmpeqb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "TI")])
+
+(define_insn "eqv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (eq:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "pcmpeqw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "TI")])
+
+(define_insn "eqv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (eq:V4SI (match_operand:V4SI 1 "register_operand" "0")
+ (match_operand:V4SI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "pcmpeqd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "TI")])
+
+(define_insn "gtv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (gt:V16QI (match_operand:V16QI 1 "register_operand" "0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "pcmpgtb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "TI")])
+
+(define_insn "gtv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (gt:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "pcmpgtw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "TI")])
+
+(define_insn "gtv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (gt:V4SI (match_operand:V4SI 1 "register_operand" "0")
+ (match_operand:V4SI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "pcmpgtd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "TI")])
+
+
+;; MMX max/min insns
+
+(define_insn "umaxv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (umax:V16QI (match_operand:V16QI 1 "register_operand" "0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "pmaxub\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "smaxv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (smax:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "pmaxsw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "uminv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (umin:V16QI (match_operand:V16QI 1 "register_operand" "0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "pminub\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "sminv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (smin:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "pminsw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+
+;; MMX shifts
+
+(define_insn "ashrv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (ashiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:TI 2 "nonmemory_operand" "xi")))]
+ "TARGET_SSE2"
+ "psraw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "ashrv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (ashiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0")
+ (match_operand:TI 2 "nonmemory_operand" "xi")))]
+ "TARGET_SSE2"
+ "psrad\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "lshrv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (lshiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:TI 2 "nonmemory_operand" "xi")))]
+ "TARGET_SSE2"
+ "psrlw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "lshrv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (lshiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0")
+ (match_operand:TI 2 "nonmemory_operand" "xi")))]
+ "TARGET_SSE2"
+ "psrld\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "lshrv2di3"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (lshiftrt:V2DI (match_operand:V2DI 1 "register_operand" "0")
+ (match_operand:TI 2 "nonmemory_operand" "xi")))]
+ "TARGET_SSE2"
+ "psrlq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "ashlv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (ashift:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:TI 2 "nonmemory_operand" "xi")))]
+ "TARGET_SSE2"
+ "psllw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "ashlv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (ashift:V4SI (match_operand:V4SI 1 "register_operand" "0")
+ (match_operand:TI 2 "nonmemory_operand" "xi")))]
+ "TARGET_SSE2"
+ "pslld\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "ashlv2di3"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (ashift:V2DI (match_operand:V2DI 1 "register_operand" "0")
+ (match_operand:TI 2 "nonmemory_operand" "xi")))]
+ "TARGET_SSE2"
+ "psllq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "ashrv8hi3_ti"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (ashiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
+ "TARGET_SSE2"
+ "psraw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "ashrv4si3_ti"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (ashiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0")
+ (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
+ "TARGET_SSE2"
+ "psrad\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "lshrv8hi3_ti"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (lshiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
+ "TARGET_SSE2"
+ "psrlw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "lshrv4si3_ti"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (lshiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0")
+ (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
+ "TARGET_SSE2"
+ "psrld\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "lshrv2di3_ti"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (lshiftrt:V2DI (match_operand:V2DI 1 "register_operand" "0")
+ (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
+ "TARGET_SSE2"
+ "psrlq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "ashlv8hi3_ti"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (ashift:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
+ "TARGET_SSE2"
+ "psllw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "ashlv4si3_ti"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (ashift:V4SI (match_operand:V4SI 1 "register_operand" "0")
+ (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
+ "TARGET_SSE2"
+ "pslld\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "ashlv2di3_ti"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (ashift:V2DI (match_operand:V2DI 1 "register_operand" "0")
+ (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))]
+ "TARGET_SSE2"
+ "psllq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+;; See logical MMX insns for the reason for the unspec. Strictly speaking
+;; we wouldn't need here it since we never generate TImode arithmetic.
+
+;; There has to be some kind of prize for the weirdest new instruction...
+(define_insn "sse2_ashlti3"
+ [(set (match_operand:TI 0 "register_operand" "=x")
+ (unspec:TI
+ [(ashift:TI (match_operand:TI 1 "register_operand" "0")
+ (mult:SI (match_operand:SI 2 "immediate_operand" "i")
+ (const_int 8)))] UNSPEC_NOP))]
+ "TARGET_SSE2"
+ "pslldq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_lshrti3"
+ [(set (match_operand:TI 0 "register_operand" "=x")
+ (unspec:TI
+ [(lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
+ (mult:SI (match_operand:SI 2 "immediate_operand" "i")
+ (const_int 8)))] UNSPEC_NOP))]
+ "TARGET_SSE2"
+ "psrldq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+;; SSE unpack
+
+(define_insn "sse2_unpckhpd"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_concat:V2DF
+ (vec_select:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (parallel [(const_int 1)]))
+ (vec_select:V2DF (match_operand:V2DF 2 "register_operand" "x")
+ (parallel [(const_int 0)]))))]
+ "TARGET_SSE2"
+ "unpckhpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_unpcklpd"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_concat:V2DF
+ (vec_select:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (parallel [(const_int 0)]))
+ (vec_select:V2DF (match_operand:V2DF 2 "register_operand" "x")
+ (parallel [(const_int 1)]))))]
+ "TARGET_SSE2"
+ "unpcklpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+;; MMX pack/unpack insns.
+
+(define_insn "sse2_packsswb"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (vec_concat:V16QI
+ (ss_truncate:V8QI (match_operand:V8HI 1 "register_operand" "0"))
+ (ss_truncate:V8QI (match_operand:V8HI 2 "register_operand" "x"))))]
+ "TARGET_SSE2"
+ "packsswb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_packssdw"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (vec_concat:V8HI
+ (ss_truncate:V4HI (match_operand:V4SI 1 "register_operand" "0"))
+ (ss_truncate:V4HI (match_operand:V4SI 2 "register_operand" "x"))))]
+ "TARGET_SSE2"
+ "packssdw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_packuswb"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (vec_concat:V16QI
+ (us_truncate:V8QI (match_operand:V8HI 1 "register_operand" "0"))
+ (us_truncate:V8QI (match_operand:V8HI 2 "register_operand" "x"))))]
+ "TARGET_SSE2"
+ "packuswb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpckhbw"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (vec_merge:V16QI
+ (vec_select:V16QI (match_operand:V16QI 1 "register_operand" "0")
+ (parallel [(const_int 8) (const_int 0)
+ (const_int 9) (const_int 1)
+ (const_int 10) (const_int 2)
+ (const_int 11) (const_int 3)
+ (const_int 12) (const_int 4)
+ (const_int 13) (const_int 5)
+ (const_int 14) (const_int 6)
+ (const_int 15) (const_int 7)]))
+ (vec_select:V16QI (match_operand:V16QI 2 "register_operand" "x")
+ (parallel [(const_int 0) (const_int 8)
+ (const_int 1) (const_int 9)
+ (const_int 2) (const_int 10)
+ (const_int 3) (const_int 11)
+ (const_int 4) (const_int 12)
+ (const_int 5) (const_int 13)
+ (const_int 6) (const_int 14)
+ (const_int 7) (const_int 15)]))
+ (const_int 21845)))]
+ "TARGET_SSE2"
+ "punpckhbw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpckhwd"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (vec_merge:V8HI
+ (vec_select:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (parallel [(const_int 4) (const_int 0)
+ (const_int 5) (const_int 1)
+ (const_int 6) (const_int 2)
+ (const_int 7) (const_int 3)]))
+ (vec_select:V8HI (match_operand:V8HI 2 "register_operand" "x")
+ (parallel [(const_int 0) (const_int 4)
+ (const_int 1) (const_int 5)
+ (const_int 2) (const_int 6)
+ (const_int 3) (const_int 7)]))
+ (const_int 85)))]
+ "TARGET_SSE2"
+ "punpckhwd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpckhdq"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (vec_merge:V4SI
+ (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "0")
+ (parallel [(const_int 2) (const_int 0)
+ (const_int 3) (const_int 1)]))
+ (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "x")
+ (parallel [(const_int 0) (const_int 2)
+ (const_int 1) (const_int 3)]))
+ (const_int 5)))]
+ "TARGET_SSE2"
+ "punpckhdq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpcklbw"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (vec_merge:V16QI
+ (vec_select:V16QI (match_operand:V16QI 1 "register_operand" "0")
+ (parallel [(const_int 0) (const_int 8)
+ (const_int 1) (const_int 9)
+ (const_int 2) (const_int 10)
+ (const_int 3) (const_int 11)
+ (const_int 4) (const_int 12)
+ (const_int 5) (const_int 13)
+ (const_int 6) (const_int 14)
+ (const_int 7) (const_int 15)]))
+ (vec_select:V16QI (match_operand:V16QI 2 "register_operand" "x")
+ (parallel [(const_int 8) (const_int 0)
+ (const_int 9) (const_int 1)
+ (const_int 10) (const_int 2)
+ (const_int 11) (const_int 3)
+ (const_int 12) (const_int 4)
+ (const_int 13) (const_int 5)
+ (const_int 14) (const_int 6)
+ (const_int 15) (const_int 7)]))
+ (const_int 21845)))]
+ "TARGET_SSE2"
+ "punpcklbw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpcklwd"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (vec_merge:V8HI
+ (vec_select:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (parallel [(const_int 0) (const_int 4)
+ (const_int 1) (const_int 5)
+ (const_int 2) (const_int 6)
+ (const_int 3) (const_int 7)]))
+ (vec_select:V8HI (match_operand:V8HI 2 "register_operand" "x")
+ (parallel [(const_int 4) (const_int 0)
+ (const_int 5) (const_int 1)
+ (const_int 6) (const_int 2)
+ (const_int 7) (const_int 3)]))
+ (const_int 85)))]
+ "TARGET_SSE2"
+ "punpcklwd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpckldq"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (vec_merge:V4SI
+ (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "0")
+ (parallel [(const_int 0) (const_int 2)
+ (const_int 1) (const_int 3)]))
+ (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "x")
+ (parallel [(const_int 2) (const_int 0)
+ (const_int 3) (const_int 1)]))
+ (const_int 5)))]
+ "TARGET_SSE2"
+ "punpckldq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpcklqdq"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (vec_merge:V2DI
+ (vec_select:V2DI (match_operand:V2DI 2 "register_operand" "x")
+ (parallel [(const_int 1)
+ (const_int 0)]))
+ (match_operand:V2DI 1 "register_operand" "0")
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "punpcklqdq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpckhqdq"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (vec_merge:V2DI
+ (match_operand:V2DI 1 "register_operand" "0")
+ (vec_select:V2DI (match_operand:V2DI 2 "register_operand" "x")
+ (parallel [(const_int 1)
+ (const_int 0)]))
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "punpckhqdq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+;; SSE2 moves
+
+(define_insn "sse2_movapd"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,m")
+ (unspec:V2DF [(match_operand:V2DF 1 "nonimmediate_operand" "xm,x")]
+ UNSPEC_MOVA))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "movapd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_movupd"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,m")
+ (unspec:V2DF [(match_operand:V2DF 1 "nonimmediate_operand" "xm,x")]
+ UNSPEC_MOVU))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "movupd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_movdqa"
+ [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,m")
+ (unspec:V16QI [(match_operand:V16QI 1 "nonimmediate_operand" "xm,x")]
+ UNSPEC_MOVA))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "movdqa\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_movdqu"
+ [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,m")
+ (unspec:V16QI [(match_operand:V16QI 1 "nonimmediate_operand" "xm,x")]
+ UNSPEC_MOVU))]
+ "TARGET_SSE2
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "movdqu\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_movdq2q"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,y")
+ (vec_select:DI (match_operand:V2DI 1 "register_operand" "x,x")
+ (parallel [(const_int 0)])))]
+ "TARGET_SSE2 && !TARGET_64BIT"
+ "@
+ movq\t{%1, %0|%0, %1}
+ movdq2q\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_movdq2q_rex64"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,y,r")
+ (vec_select:DI (match_operand:V2DI 1 "register_operand" "x,x,x")
+ (parallel [(const_int 0)])))]
+ "TARGET_SSE2 && TARGET_64BIT"
+ "@
+ movq\t{%1, %0|%0, %1}
+ movdq2q\t{%1, %0|%0, %1}
+ movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_movq2dq"
+ [(set (match_operand:V2DI 0 "register_operand" "=x,?x")
+ (vec_concat:V2DI (match_operand:DI 1 "nonimmediate_operand" "m,y")
+ (const_int 0)))]
+ "TARGET_SSE2 && !TARGET_64BIT"
+ "@
+ movq\t{%1, %0|%0, %1}
+ movq2dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt,ssemov")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_movq2dq_rex64"
+ [(set (match_operand:V2DI 0 "register_operand" "=x,?x,?x")
+ (vec_concat:V2DI (match_operand:DI 1 "nonimmediate_operand" "m,y,r")
+ (const_int 0)))]
+ "TARGET_SSE2 && TARGET_64BIT"
+ "@
+ movq\t{%1, %0|%0, %1}
+ movq2dq\t{%1, %0|%0, %1}
+ movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt,ssemov,ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_movq"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (vec_concat:V2DI (vec_select:DI
+ (match_operand:V2DI 1 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0)]))
+ (const_int 0)))]
+ "TARGET_SSE2"
+ "movq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_loadd"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (vec_merge:V4SI
+ (vec_duplicate:V4SI (match_operand:SI 1 "nonimmediate_operand" "mr"))
+ (const_vector:V4SI [(const_int 0)
+ (const_int 0)
+ (const_int 0)
+ (const_int 0)])
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_stored"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=mr")
+ (vec_select:SI
+ (match_operand:V4SI 1 "register_operand" "x")
+ (parallel [(const_int 0)])))]
+ "TARGET_SSE2"
+ "movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_movhpd"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,m")
+ (vec_merge:V2DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "0,0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "m,x")
+ (const_int 2)))]
+ "TARGET_SSE2 && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)"
+ "movhpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_movlpd"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,m")
+ (vec_merge:V2DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "0,0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "m,x")
+ (const_int 1)))]
+ "TARGET_SSE2 && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)"
+ "movlpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_expand "sse2_loadsd"
+ [(match_operand:V2DF 0 "register_operand" "")
+ (match_operand:DF 1 "memory_operand" "")]
+ "TARGET_SSE2"
+{
+ emit_insn (gen_sse2_loadsd_1 (operands[0], operands[1],
+ CONST0_RTX (V2DFmode)));
+ DONE;
+})
+
+(define_insn "sse2_loadsd_1"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF
+ (vec_duplicate:V2DF (match_operand:DF 1 "memory_operand" "m"))
+ (match_operand:V2DF 2 "const0_operand" "X")
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "movsd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "DF")])
+
+(define_insn "sse2_movsd"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF
+ (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "register_operand" "x")
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "movsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "DF")])
+
+(define_insn "sse2_storesd"
+ [(set (match_operand:DF 0 "memory_operand" "=m")
+ (vec_select:DF
+ (match_operand:V2DF 1 "register_operand" "x")
+ (parallel [(const_int 0)])))]
+ "TARGET_SSE2"
+ "movsd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "DF")])
+
+(define_insn "sse2_shufpd"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")
+ (match_operand:SI 3 "immediate_operand" "i")]
+ UNSPEC_SHUFFLE))]
+ "TARGET_SSE2"
+ ;; @@@ check operand order for intel/nonintel syntax
+ "shufpd\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_clflush"
+ [(unspec_volatile [(match_operand 0 "address_operand" "p")]
+ UNSPECV_CLFLUSH)]
+ "TARGET_SSE2"
+ "clflush %0"
+ [(set_attr "type" "sse")
+ (set_attr "memory" "unknown")])
+
+(define_expand "sse2_mfence"
+ [(set (match_dup 0)
+ (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
+ "TARGET_SSE2"
+{
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (operands[0]) = 1;
+})
+
+(define_insn "*mfence_insn"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
+ "TARGET_SSE2"
+ "mfence"
+ [(set_attr "type" "sse")
+ (set_attr "memory" "unknown")])
+
+(define_expand "sse2_lfence"
+ [(set (match_dup 0)
+ (unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
+ "TARGET_SSE2"
+{
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (operands[0]) = 1;
+})
+
+(define_insn "*lfence_insn"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
+ "TARGET_SSE2"
+ "lfence"
+ [(set_attr "type" "sse")
+ (set_attr "memory" "unknown")])
diff --git a/contrib/gcc/config/i386/i386elf.h b/contrib/gcc/config/i386/i386elf.h
index ddf19b6..cd01db2 100644
--- a/contrib/gcc/config/i386/i386elf.h
+++ b/contrib/gcc/config/i386/i386elf.h
@@ -1,5 +1,6 @@
/* Target definitions for GNU compiler for Intel 80386 using ELF
- Copyright (C) 1988, 1991, 1995, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1991, 1995, 2000, 2001, 2002
+ Free Software Foundation, Inc.
Derived from sysv4.h written by Ron Guilmette (rfg@netcom.com).
@@ -24,7 +25,6 @@ Boston, MA 02111-1307, USA. */
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i386 bare ELF target)");
/* By default, target has a 80387, uses IEEE compatible arithmetic,
@@ -40,12 +40,8 @@ Boston, MA 02111-1307, USA. */
(TYPE_MODE (TYPE) == BLKmode \
|| (VECTOR_MODE_P (TYPE_MODE (TYPE)) && int_size_in_bytes (TYPE) == 8))
-/* This used to define X86, but james@bigtex.cactus.org says that
- is supposed to be defined optionally by user programs--not by default. */
-#define CPP_PREDEFINES ""
-
#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu)"
+#define CPP_SPEC ""
#define ENDFILE_SPEC "crtend.o%s"
diff --git a/contrib/gcc/config/i386/k6.md b/contrib/gcc/config/i386/k6.md
new file mode 100644
index 0000000..af128bf
--- /dev/null
+++ b/contrib/gcc/config/i386/k6.md
@@ -0,0 +1,136 @@
+;; AMD K6/K6-2 Scheduling
+;; Copyright (C) 2002 ;; Free Software Foundation, Inc.
+;;
+;; This file is part of GNU CC.
+;;
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA. */
+;;
+;; The K6 has similar architecture to PPro. Important difference is, that
+;; there are only two decoders and they seems to be much slower than execution
+;; units. So we have to pay much more attention to proper decoding for
+;; schedulers. We share most of scheduler code for PPro in i386.c
+;;
+;; The fp unit is not pipelined and do one operation per two cycles including
+;; the FXCH.
+;;
+;; alu describes both ALU units (ALU-X and ALU-Y).
+;; alux describes X alu unit
+;; fpu describes FPU unit
+;; load describes load unit.
+;; branch describes branch unit.
+;; store decsribes store unit. This unit is not modelled completely and only
+;; used to model lea operation. Otherwise it lie outside of the critical
+;; path.
+;;
+;; ??? fxch isn't handled; not an issue until sched3 after reg-stack is real.
+
+;; The decoder specification is in the PPro section above!
+
+;; Shift instructions and certain arithmetic are issued only to X pipe.
+(define_function_unit "k6_alux" 1 0
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "ishift,ishift1,rotate,rotate1,alu1,negnot,cld"))
+ 1 1)
+
+;; The QI mode arithmetic is issued to X pipe only.
+(define_function_unit "k6_alux" 1 0
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "alu,alu1,negnot,icmp,test,imovx,incdec")
+ (match_operand:QI 0 "general_operand" "")))
+ 1 1)
+
+(define_function_unit "k6_alu" 2 0
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "ishift,ishift1,rotate,rotate1,alu1,negnot,alu,icmp,test,imovx,incdec,setcc,lea"))
+ 1 1)
+
+(define_function_unit "k6_alu" 2 0
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "imov")
+ (eq_attr "memory" "none")))
+ 1 1)
+
+(define_function_unit "k6_branch" 1 0
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "call,callv,ibr"))
+ 1 1)
+
+;; Load unit have two cycle latency, but we take care for it in adjust_cost
+(define_function_unit "k6_load" 1 0
+ (and (eq_attr "cpu" "k6")
+ (ior (eq_attr "type" "pop")
+ (eq_attr "memory" "load,both")))
+ 1 1)
+
+(define_function_unit "k6_load" 1 0
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "str")
+ (eq_attr "memory" "load,both")))
+ 10 10)
+
+;; Lea have two instructions, so latency is probably 2
+(define_function_unit "k6_store" 1 0
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "lea"))
+ 2 1)
+
+(define_function_unit "k6_store" 1 0
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "str"))
+ 10 10)
+
+(define_function_unit "k6_store" 1 0
+ (and (eq_attr "cpu" "k6")
+ (ior (eq_attr "type" "push")
+ (eq_attr "memory" "store,both")))
+ 1 1)
+
+(define_function_unit "k6_fpu" 1 1
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "fop,fmov,fcmp,fistp"))
+ 2 2)
+
+(define_function_unit "k6_fpu" 1 1
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "fmul"))
+ 2 2)
+
+;; ??? Guess
+(define_function_unit "k6_fpu" 1 1
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "fdiv,fpspc"))
+ 56 56)
+
+(define_function_unit "k6_alu" 2 0
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "imul"))
+ 2 2)
+
+(define_function_unit "k6_alux" 1 0
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "imul"))
+ 2 2)
+
+;; ??? Guess
+(define_function_unit "k6_alu" 2 0
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "idiv"))
+ 17 17)
+
+(define_function_unit "k6_alux" 1 0
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "idiv"))
+ 17 17)
diff --git a/contrib/gcc/config/i386/linux-aout.h b/contrib/gcc/config/i386/linux-aout.h
index 4b9cd5c..783b8a9 100644
--- a/contrib/gcc/config/i386/linux-aout.h
+++ b/contrib/gcc/config/i386/linux-aout.h
@@ -1,5 +1,6 @@
/* Definitions for Intel 386 running Linux-based GNU systems using a.out.
- Copyright (C) 1992, 1994, 1995, 1997, 1998, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1994, 1995, 1997, 1998, 2002
+ Free Software Foundation, Inc.
Contributed by H.J. Lu (hjl@nynexst.com)
This file is part of GNU CC.
@@ -19,22 +20,26 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* This is tested by i386/gas.h. */
-#define YES_UNDERSCORES
-
-#include <i386/gstabs.h>
-#include <linux-aout.h> /* some common stuff */
-
#undef ASM_COMMENT_START
#define ASM_COMMENT_START "#"
-/* Specify predefined symbols in preprocessor. */
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dunix -D__gnu_linux__ -Dlinux -Asystem=posix"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("linux"); \
+ builtin_define_std ("unix"); \
+ builtin_define ("__gnu_linux__"); \
+ builtin_assert ("system=posix"); \
+ if (flag_pic) \
+ { \
+ builtin_define ("__PIC__"); \
+ builtin_define ("__pic__"); \
+ } \
+ } \
+ while (0)
#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}"
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE}"
#undef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
diff --git a/contrib/gcc/config/i386/linux.h b/contrib/gcc/config/i386/linux.h
index b07bd03..6b553cd 100644
--- a/contrib/gcc/config/i386/linux.h
+++ b/contrib/gcc/config/i386/linux.h
@@ -33,7 +33,6 @@ Boston, MA 02111-1307, USA. */
fputs ("\t.intel_syntax\n", FILE); \
} while (0)
-#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i386 Linux/ELF)");
/* The svr4 ABI for the i386 says that records and unions are returned
@@ -54,23 +53,14 @@ Boston, MA 02111-1307, USA. */
#define NO_PROFILE_COUNTERS
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(FILE, LABELNO) \
-{ \
- if (flag_pic) \
- fprintf (FILE, "\tcall\t*mcount@GOT(%%ebx)\n"); \
- else \
- fprintf (FILE, "\tcall\tmcount\n"); \
-}
+#undef MCOUNT_NAME
+#define MCOUNT_NAME "mcount"
-/* True if it is possible to profile code that does not have a frame
- pointer.
-
- The GLIBC version of mcount for the x86 assumes that there is a
+/* The GLIBC version of mcount for the x86 assumes that there is a
frame, so we cannot allow profiling without a frame pointer. */
-#undef TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
-#define TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER false
+#undef SUBTARGET_FRAME_POINTER_REQUIRED
+#define SUBTARGET_FRAME_POINTER_REQUIRED current_function_profile
#undef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
@@ -84,14 +74,27 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__ -Dunix -D__gnu_linux__ -Dlinux -Asystem=posix"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("linux"); \
+ builtin_define_std ("unix"); \
+ builtin_define ("__ELF__"); \
+ builtin_define ("__gnu_linux__"); \
+ builtin_assert ("system=posix"); \
+ if (flag_pic) \
+ { \
+ builtin_define ("__PIC__"); \
+ builtin_define ("__pic__"); \
+ } \
+ } \
+ while (0)
#undef CPP_SPEC
#ifdef USE_GNULIBC_1
-#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}"
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE}"
#else
-#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
#endif
#undef CC1_SPEC
@@ -221,9 +224,13 @@ Boston, MA 02111-1307, USA. */
state data appropriately. See unwind-dw2.c for the structs. */
#ifdef IN_LIBGCC2
+/* There's no sys/ucontext.h for some (all?) libc1, so no
+ signal-turned-exceptions for them. There's also no configure-run for
+ the target, so we can't check on (e.g.) HAVE_SYS_UCONTEXT_H. Using the
+ target libc1 macro should be enough. */
+#ifndef USE_GNULIBC_1
#include <signal.h>
#include <sys/ucontext.h>
-#endif
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
do { \
@@ -278,3 +285,5 @@ Boston, MA 02111-1307, USA. */
(FS)->retaddr_column = 8; \
goto SUCCESS; \
} while (0)
+#endif /* not USE_GNULIBC_1 */
+#endif /* IN_LIBGCC2 */
diff --git a/contrib/gcc/config/i386/linux64.h b/contrib/gcc/config/i386/linux64.h
index 34c6d3c..7a9e0ba 100644
--- a/contrib/gcc/config/i386/linux64.h
+++ b/contrib/gcc/config/i386/linux64.h
@@ -1,5 +1,5 @@
/* Definitions for AMD x86-64 running Linux-based GNU systems with ELF format.
- Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Jan Hubicka <jh@suse.cz>, based on linux.h.
This file is part of GNU CC.
@@ -21,14 +21,31 @@ Boston, MA 02111-1307, USA. */
#define LINUX_DEFAULT_ELF
-#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (x86-64 Linux/ELF)");
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__ -Dunix -D__gnu_linux__ -Dlinux -Asystem(posix)"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("linux"); \
+ builtin_define_std ("unix"); \
+ builtin_define ("__gnu_linux__"); \
+ builtin_define ("__ELF__"); \
+ builtin_assert ("system=posix"); \
+ if (flag_pic) \
+ { \
+ builtin_define ("__PIC__"); \
+ builtin_define ("__pic__"); \
+ } \
+ if (TARGET_64BIT) \
+ { \
+ builtin_define ("__LP64__"); \
+ builtin_define ("_LP64"); \
+ } \
+ } \
+ while (0)
#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT} %{!m32:-D__LONG_MAX__=9223372036854775807L}"
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
/* The svr4 ABI for the i386 says that records and unions are returned
in memory. In the 64bit compilation we will turn this flag off in
@@ -45,7 +62,7 @@ Boston, MA 02111-1307, USA. */
done. */
#undef LINK_SPEC
-#define LINK_SPEC "%{!m32:-m elf_x86_64 -Y P,/usr/lib64} %{m32:-m elf_i386} \
+#define LINK_SPEC "%{!m32:-m elf_x86_64} %{m32:-m elf_i386} \
%{shared:-shared} \
%{!shared: \
%{!static: \
@@ -104,17 +121,17 @@ Boston, MA 02111-1307, USA. */
(FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[0].loc.offset = (long)&sc_->rax - new_cfa_; \
(FS)->regs.reg[1].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[1].loc.offset = (long)&sc_->rbx - new_cfa_; \
+ (FS)->regs.reg[1].loc.offset = (long)&sc_->rdx - new_cfa_; \
(FS)->regs.reg[2].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[2].loc.offset = (long)&sc_->rcx - new_cfa_; \
(FS)->regs.reg[3].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[3].loc.offset = (long)&sc_->rdx - new_cfa_; \
+ (FS)->regs.reg[3].loc.offset = (long)&sc_->rbx - new_cfa_; \
(FS)->regs.reg[4].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[4].loc.offset = (long)&sc_->rbp - new_cfa_; \
+ (FS)->regs.reg[4].loc.offset = (long)&sc_->rsi - new_cfa_; \
(FS)->regs.reg[5].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[5].loc.offset = (long)&sc_->rsi - new_cfa_; \
+ (FS)->regs.reg[5].loc.offset = (long)&sc_->rdi - new_cfa_; \
(FS)->regs.reg[6].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[6].loc.offset = (long)&sc_->rdi - new_cfa_; \
+ (FS)->regs.reg[6].loc.offset = (long)&sc_->rbp - new_cfa_; \
(FS)->regs.reg[8].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[8].loc.offset = (long)&sc_->r8 - new_cfa_; \
(FS)->regs.reg[9].how = REG_SAVED_OFFSET; \
@@ -131,6 +148,8 @@ Boston, MA 02111-1307, USA. */
(FS)->regs.reg[14].loc.offset = (long)&sc_->r14 - new_cfa_; \
(FS)->regs.reg[15].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[15].loc.offset = (long)&sc_->r15 - new_cfa_; \
+ (FS)->regs.reg[16].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[16].loc.offset = (long)&sc_->rip - new_cfa_; \
(FS)->retaddr_column = 16; \
goto SUCCESS; \
} while (0)
diff --git a/contrib/gcc/config/i386/lynx-ng.h b/contrib/gcc/config/i386/lynx-ng.h
index 49150a3..08fa60f 100644
--- a/contrib/gcc/config/i386/lynx-ng.h
+++ b/contrib/gcc/config/i386/lynx-ng.h
@@ -1,5 +1,5 @@
/* Definitions for Intel 386 running LynxOS, using Lynx's old as and ld.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,12 +18,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. */
-#include <i386/gstabs.h>
-#include <lynx-ng.h>
+#define TARGET_VERSION fprintf (stderr, " (80386, LYNX BSD syntax)");
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dunix -DI386 -DLynx -DIBITS32 \
- -Asystem=unix -Asystem=lynx"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("I386"); \
+ builtin_define_std ("Lynx"); \
+ builtin_define_std ("IBITS32"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=lynx"); \
+ } \
+ while (0)
/* Provide required defaults for linker switches. */
@@ -36,3 +43,35 @@ Boston, MA 02111-1307, USA. */
#define CALL_USED_REGISTERS \
/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \
{ 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
+
+/* Prefix for internally generated assembler labels. If we aren't using
+ underscores, we are using prefix `.'s to identify labels that should
+ be ignored, as in `i386/gas.h' --karl@cs.umb.edu */
+
+#undef LPREFIX
+#define LPREFIX ".L"
+
+/* The prefix to add to user-visible assembler symbols. */
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
+/* If user-symbols don't have underscores,
+ then it must take more than `L' to identify
+ a label that should be ignored. */
+
+/* This is how to store into the string BUF
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \
+ sprintf ((BUF), ".%s%ld", (PREFIX), (long)(NUMBER))
+
+/* 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)
diff --git a/contrib/gcc/config/i386/lynx.h b/contrib/gcc/config/i386/lynx.h
index 91ed31e..7835f27 100644
--- a/contrib/gcc/config/i386/lynx.h
+++ b/contrib/gcc/config/i386/lynx.h
@@ -1,5 +1,5 @@
/* Definitions for Intel 386 running LynxOS.
- Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,11 +18,18 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include <i386/gstabs.h>
-#include <lynx.h>
+#define TARGET_VERSION fprintf (stderr, " (80386, LYNX BSD syntax)");
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-DI386 -DLynx -DIBITS32 -Asystem=unix -Asystem=lynx"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("I386"); \
+ builtin_define_std ("Lynx"); \
+ builtin_define_std ("IBITS32"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=lynx"); \
+ } \
+ while (0)
/* The prefix to add to user-visible assembler symbols. */
@@ -37,3 +44,35 @@ Boston, MA 02111-1307, USA. */
#define CALL_USED_REGISTERS \
/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \
{ 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
+
+/* Prefix for internally generated assembler labels. If we aren't using
+ underscores, we are using prefix `.'s to identify labels that should
+ be ignored, as in `i386/gas.h' --karl@cs.umb.edu */
+
+#undef LPREFIX
+#define LPREFIX ".L"
+
+/* The prefix to add to user-visible assembler symbols. */
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
+/* If user-symbols don't have underscores,
+ then it must take more than `L' to identify
+ a label that should be ignored. */
+
+/* This is how to store into the string BUF
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \
+ sprintf ((BUF), ".%s%ld", (PREFIX), (long)(NUMBER))
+
+/* 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)
diff --git a/contrib/gcc/config/i386/mach.h b/contrib/gcc/config/i386/mach.h
index 7e2b1cc..0aa3846 100644
--- a/contrib/gcc/config/i386/mach.h
+++ b/contrib/gcc/config/i386/mach.h
@@ -1,13 +1,16 @@
/* Configuration for an i386 running Mach as the target machine. */
-/* We do want to add an underscore to the front of each user symbol.
- i386/gas.h checks this. */
-#define YES_UNDERSCORES
+#define TARGET_VERSION fprintf (stderr, " (80386, Mach)");
-#include "i386/gstabs.h"
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dunix -DMACH -Asystem=unix -Asystem=mach"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("MACH"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=mach"); \
+ } \
+ while (0)
/* Specify extra dir to search for include files. */
#define SYSTEM_INCLUDE_DIR "/usr/mach/include"
diff --git a/contrib/gcc/config/i386/mingw32.h b/contrib/gcc/config/i386/mingw32.h
index 629328e..7f62fbd 100644
--- a/contrib/gcc/config/i386/mingw32.h
+++ b/contrib/gcc/config/i386/mingw32.h
@@ -1,6 +1,7 @@
/* Operating system specific defines to be used when targeting GCC for
hosting on Windows32, using GNU tools and the Windows32 API Library.
- Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -32,13 +33,35 @@ Boston, MA 02111-1307, USA. */
#define TARGET_EXECUTABLE_SUFFIX ".exe"
-/* Please keep changes to CPP_PREDEFINES in sync with i386/crtdll. The
- only difference between the two should be __MSVCRT__ needed to
- distinguish MSVC from CRTDLL runtime in mingw headers. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D_WIN32 -D__WIN32 -D__WIN32__ -DWIN32 \
- -D__MINGW32__ -D__MSVCRT__ -DWINNT -D_X86_=1 \
- -Asystem=winnt"
+/* See i386/crtdll.h for an altervative definition. */
+#define EXTRA_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__MSVCRT__"); \
+ builtin_define ("__MINGW32__"); \
+ } \
+ while (0)
+
+#undef TARGET_OS_CPP_BUILTINS /* From cygwin.h. */
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("_WIN32"); \
+ builtin_define_std ("WIN32"); \
+ builtin_define_std ("WINNT"); \
+ builtin_define ("_X86_=1"); \
+ builtin_define ("__stdcall=__attribute__((__stdcall__))"); \
+ builtin_define ("__cdecl=__attribute__((__cdecl__))"); \
+ builtin_define ("__declspec(x)=__attribute__((x))"); \
+ if (!flag_iso) \
+ { \
+ builtin_define ("_stdcall=__attribute__((__stdcall__))"); \
+ builtin_define ("_cdecl=__attribute__((__cdecl__))"); \
+ } \
+ EXTRA_OS_CPP_BUILTINS (); \
+ builtin_assert ("system=winnt"); \
+ } \
+ while (0)
/* Specific a different directory for the standard include files. */
#undef STANDARD_INCLUDE_DIR
@@ -47,14 +70,7 @@ Boston, MA 02111-1307, USA. */
#define STANDARD_INCLUDE_COMPONENT "MINGW"
#undef CPP_SPEC
-#define CPP_SPEC \
- "-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE} %{mthreads:-D_MT} \
- -D__stdcall=__attribute__((__stdcall__)) \
- -D__cdecl=__attribute__((__cdecl__)) \
- %{!ansi:-D_stdcall=__attribute__((__stdcall__)) \
- -D_cdecl=__attribute__((__cdecl__))} \
- -D__declspec(x)=__attribute__((x))"
-
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{mthreads:-D_MT}"
/* For Windows applications, include more libraries, but always include
kernel32. */
@@ -74,7 +90,7 @@ Boston, MA 02111-1307, USA. */
/* Include in the mingw32 libraries with libgcc */
#undef LIBGCC_SPEC
#define LIBGCC_SPEC \
- "%{mthreads:-lmingwthrd} -lmingw32 -lgcc -lmoldname -lmsvcrt"
+ "%{mthreads:-lmingwthrd} -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt"
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "%{shared|mdll:dllcrt2%O%s} \
@@ -85,24 +101,33 @@ Boston, MA 02111-1307, USA. */
#define MATH_LIBRARY ""
/* Output STRING, a string representing a filename, to FILE.
- We canonicalize it to be in MS-DOS format. */
+ We canonicalize it to be in Unix format (backslashe are replaced
+ forward slashes. */
#undef OUTPUT_QUOTED_STRING
-#define OUTPUT_QUOTED_STRING(FILE, STRING) \
-do { \
- char c; \
- \
- putc ('\"', asm_file); \
- \
- while ((c = *string++) != 0) \
- { \
- if (c == '\\') \
- c = '/'; \
- \
- if (c == '\"') \
- putc ('\\', asm_file); \
- putc (c, asm_file); \
- } \
- \
- putc ('\"', asm_file); \
+#define OUTPUT_QUOTED_STRING(FILE, STRING) \
+do { \
+ char c; \
+ \
+ putc ('\"', asm_file); \
+ \
+ while ((c = *string++) != 0) \
+ { \
+ if (c == '\\') \
+ c = '/'; \
+ \
+ if (ISPRINT (c)) \
+ { \
+ if (c == '\"') \
+ putc ('\\', asm_file); \
+ putc (c, asm_file); \
+ } \
+ else \
+ fprintf (asm_file, "\\%03o", (unsigned char) c); \
+ } \
+ \
+ putc ('\"', asm_file); \
} while (0)
+/* Define as short unsigned for compatability with MS runtime. */
+#undef WINT_TYPE
+#define WINT_TYPE "short unsigned int"
diff --git a/contrib/gcc/config/i386/mmintrin.h b/contrib/gcc/config/i386/mmintrin.h
index bbfdd30..7b4aa01 100644
--- a/contrib/gcc/config/i386/mmintrin.h
+++ b/contrib/gcc/config/i386/mmintrin.h
@@ -30,6 +30,9 @@
#ifndef _MMINTRIN_H_INCLUDED
#define _MMINTRIN_H_INCLUDED
+#ifndef __MMX__
+# error "MMX instruction set not enabled"
+#else
/* The data type intended for user use. */
typedef int __m64 __attribute__ ((__mode__ (__V2SI__)));
@@ -53,6 +56,22 @@ _mm_cvtsi32_si64 (int __i)
return (__m64) __tmp;
}
+#ifdef __x86_64__
+/* Convert I to a __m64 object. */
+static __inline __m64
+_mm_cvtsi64x_si64 (long long __i)
+{
+ return (__m64) __i;
+}
+
+/* Convert I to a __m64 object. */
+static __inline __m64
+_mm_set_pi64x (long long __i)
+{
+ return (__m64) __i;
+}
+#endif
+
/* Convert the lower 32 bits of the __m64 object into an integer. */
static __inline int
_mm_cvtsi64_si32 (__m64 __i)
@@ -61,6 +80,15 @@ _mm_cvtsi64_si32 (__m64 __i)
return __tmp;
}
+#ifdef __x86_64__
+/* Convert the lower 32 bits of the __m64 object into an integer. */
+static __inline long long
+_mm_cvtsi64_si64x (__m64 __i)
+{
+ return (long long)__i;
+}
+#endif
+
/* Pack the four 16-bit values from M1 into the lower four 8-bit values of
the result, and the four 16-bit values from M2 into the upper four 8-bit
values of the result, all with signed saturation. */
@@ -157,6 +185,13 @@ _mm_add_pi32 (__m64 __m1, __m64 __m2)
return (__m64) __builtin_ia32_paddd ((__v2si)__m1, (__v2si)__m2);
}
+/* Add the 64-bit values in M1 to the 64-bit values in M2. */
+static __inline __m64
+_mm_add_si64 (__m64 __m1, __m64 __m2)
+{
+ return (__m64) __builtin_ia32_paddq ((long long)__m1, (long long)__m2);
+}
+
/* Add the 8-bit values in M1 to the 8-bit values in M2 using signed
saturated arithmetic. */
static __inline __m64
@@ -210,6 +245,13 @@ _mm_sub_pi32 (__m64 __m1, __m64 __m2)
return (__m64) __builtin_ia32_psubd ((__v2si)__m1, (__v2si)__m2);
}
+/* Add the 64-bit values in M1 to the 64-bit values in M2. */
+static __inline __m64
+_mm_sub_si64 (__m64 __m1, __m64 __m2)
+{
+ return (__m64) __builtin_ia32_psubq ((long long)__m1, (long long)__m2);
+}
+
/* Subtract the 8-bit values in M2 from the 8-bit values in M1 using signed
saturating arithmetic. */
static __inline __m64
@@ -541,4 +583,5 @@ _mm_set1_pi8 (char __b)
return _mm_set1_pi32 (__i);
}
+#endif /* __MMX__ */
#endif /* _MMINTRIN_H_INCLUDED */
diff --git a/contrib/gcc/config/i386/moss.h b/contrib/gcc/config/i386/moss.h
index 200cae0..642c625 100644
--- a/contrib/gcc/config/i386/moss.h
+++ b/contrib/gcc/config/i386/moss.h
@@ -19,8 +19,20 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__ -Dmoss -Asystem=posix"
+#undef TARGET_OS_CPP_BUILTINS /* config.gcc includes i386/linux.h. */
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("moss"); \
+ builtin_define ("__ELF__"); \
+ builtin_assert ("system=posix"); \
+ if (flag_pic) \
+ { \
+ builtin_define ("__PIC__"); \
+ builtin_define ("__pic__"); \
+ } \
+ } \
+ while (0)
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "crt0.o%s"
diff --git a/contrib/gcc/config/i386/netbsd-elf.h b/contrib/gcc/config/i386/netbsd-elf.h
index 30267df..4f49bd3 100644
--- a/contrib/gcc/config/i386/netbsd-elf.h
+++ b/contrib/gcc/config/i386/netbsd-elf.h
@@ -20,28 +20,35 @@ 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. */
-/* Provide a LINK_SPEC appropriate for a NetBSD/i386 ELF target.
- This is a copy of LINK_SPEC from <netbsd-elf.h> tweaked for
- the i386 target. */
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ NETBSD_OS_CPP_BUILTINS_ELF(); \
+ } \
+ while (0)
+
+
+/* Extra specs needed for NetBSD/i386 ELF. */
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "netbsd_cpp_spec", NETBSD_CPP_SPEC }, \
+ { "netbsd_entry_point", NETBSD_ENTRY_POINT },
+
+
+/* Provide a LINK_SPEC appropriate for a NetBSD/i386 ELF target. */
#undef LINK_SPEC
-#define LINK_SPEC \
- "%{assert*} %{R*} \
- %{shared:-shared} \
- %{!shared: \
- -dc -dp \
- %{!nostdlib: \
- %{!r*: \
- %{!e*:-e __start}}} \
- %{!static: \
- %{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /usr/libexec/ld.elf_so}} \
- %{static:-static}}"
-
-/* Names to predefine in the preprocessor for this target machine. */
-
-#define CPP_PREDEFINES \
- "-D__NetBSD__ -D__ELF__ -Asystem=unix -Asystem=NetBSD"
+#define LINK_SPEC NETBSD_LINK_SPEC_ELF
+
+#define NETBSD_ENTRY_POINT "__start"
+
+
+/* Provide a CPP_SPEC appropriate for NetBSD. */
+
+#undef CPP_SPEC
+#define CPP_SPEC "%(netbsd_cpp_spec)"
+
/* Make gcc agree with <machine/ansi.h> */
@@ -114,5 +121,7 @@ Boston, MA 02111-1307, USA. */
we don't care about compatibility with older gcc versions. */
#define DEFAULT_PCC_STRUCT_RETURN 1
-#undef TARGET_VERSION
+/* Attempt to enable execute permissions on the stack. */
+#define TRANSFER_FROM_TRAMPOLINE NETBSD_ENABLE_EXECUTE_STACK
+
#define TARGET_VERSION fprintf (stderr, " (NetBSD/i386 ELF)");
diff --git a/contrib/gcc/config/i386/netbsd.h b/contrib/gcc/config/i386/netbsd.h
index 1d95de2..45ae893 100644
--- a/contrib/gcc/config/i386/netbsd.h
+++ b/contrib/gcc/config/i386/netbsd.h
@@ -1,20 +1,24 @@
-/* This is tested by i386gas.h. */
-#define YES_UNDERSCORES
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ NETBSD_OS_CPP_BUILTINS_AOUT(); \
+ } \
+ while (0)
-#include <i386/gstabs.h>
-
-/* Get generic NetBSD definitions. */
-#include <netbsd.h>
-#include <netbsd-aout.h>
+#define TARGET_VERSION fprintf (stderr, " (NetBSD/i386 a.out)");
/* This goes away when the math-emulator is fixed */
#undef TARGET_SUBTARGET_DEFAULT
#define TARGET_SUBTARGET_DEFAULT \
(MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_NO_FANCY_MATH_387)
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dunix -D__NetBSD__ \
- -Asystem=unix -Asystem=bsd -Asystem=NetBSD"
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "netbsd_cpp_spec", NETBSD_CPP_SPEC },
+
+#undef CPP_SPEC
+#define CPP_SPEC "%(netbsd_cpp_spec)"
+
#undef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
@@ -58,3 +62,11 @@
/* Until they use ELF or something that handles dwarf2 unwinds
and initialization stuff better. */
#define DWARF2_UNWIND_INFO 0
+
+/* Redefine this so that it becomes "_GLOBAL_OFFSET_TABLE_" when the label
+ prefix is added. */
+#undef GOT_SYMBOL_NAME
+#define GOT_SYMBOL_NAME "GLOBAL_OFFSET_TABLE_"
+
+/* Attempt to enable execute permissions on the stack. */
+#define TRANSFER_FROM_TRAMPOLINE NETBSD_ENABLE_EXECUTE_STACK
diff --git a/contrib/gcc/config/i386/netbsd64.h b/contrib/gcc/config/i386/netbsd64.h
index 051f33b..341b6d1 100644
--- a/contrib/gcc/config/i386/netbsd64.h
+++ b/contrib/gcc/config/i386/netbsd64.h
@@ -20,50 +20,40 @@ 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_OS_CPP_BUILTINS() \
+ do \
+ { \
+ NETBSD_OS_CPP_BUILTINS_ELF(); \
+ if (TARGET_64BIT) \
+ NETBSD_OS_CPP_BUILTINS_LP64(); \
+ } \
+ while (0)
-/* Provide a LINK_SPEC appropriate for a NetBSD/x86-64 ELF target.
- This is a copy of LINK_SPEC from <netbsd-elf.h> tweaked for
- the x86-64 target. */
-#undef LINK_SPEC
-#define LINK_SPEC \
- "%{!m32:-m elf_x86_64} \
- %{m32:-m elf_i386} \
- %{assert*} %{R*} \
- %{shared:-shared} \
- %{!shared: \
- -dc -dp \
- %{!nostdlib: \
- %{!r*: \
- %{!e*:-e _start}}} \
- %{!static: \
- %{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /usr/libexec/ld.elf_so}} \
- %{static:-static}}"
-
-
-/* Names to predefine in the preprocessor for this target machine. */
+/* Extra specs needed for NetBSD/x86-64 ELF. */
-#define CPP_PREDEFINES \
- "-D__NetBSD__ -D__ELF__ -Asystem=unix -Asystem=NetBSD"
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "netbsd_cpp_spec", NETBSD_CPP_SPEC }, \
+ { "netbsd_link_spec", NETBSD_LINK_SPEC_ELF }, \
+ { "netbsd_entry_point", NETBSD_ENTRY_POINT },
-/* Provide some extra CPP specs needed by NetBSD/x86_64. */
-#define CPP_LP64_SPEC "%{!m32:-D_LP64}"
+/* Provide a LINK_SPEC appropriate for a NetBSD/x86-64 ELF target. */
-#define CPP_SUBTARGET_SPEC "%(cpp_lp64)"
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%{m32:-m elf_i386} \
+ %{m64:-m elf_x86_64} \
+ %(netbsd_link_spec)"
-#undef SUBTARGET_EXTRA_SPECS
-#define SUBTARGET_EXTRA_SPECS \
- { "cpp_lp64", CPP_LP64_SPEC }, \
- { "cpp_subtarget", CPP_SUBTARGET_SPEC },
+#define NETBSD_ENTRY_POINT "_start"
-/* Provide a CPP_SPEC appropriate for NetBSD. Currently we deal with
- our subtarget specs and the GCC option `-posix'. */
+/* Provide a CPP_SPEC appropriate for NetBSD. */
#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu) %(cpp_subtarget) %{posix:-D_POSIX_SOURCE}"
+#define CPP_SPEC "%(netbsd_cpp_spec)"
/* Output assembler code to FILE to call the profiler. */
@@ -79,6 +69,7 @@ Boston, MA 02111-1307, USA. */
fprintf (FILE, "\tcall __mcount\n"); \
}
+/* Attempt to enable execute permissions on the stack. */
+#define TRANSFER_FROM_TRAMPOLINE NETBSD_ENABLE_EXECUTE_STACK
-#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (NetBSD/x86_64 ELF)");
diff --git a/contrib/gcc/config/i386/openbsd.h b/contrib/gcc/config/i386/openbsd.h
index 5015b9d..60f1657 100644
--- a/contrib/gcc/config/i386/openbsd.h
+++ b/contrib/gcc/config/i386/openbsd.h
@@ -1,5 +1,5 @@
/* Configuration for an OpenBSD i386 target.
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,23 +18,24 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* This is tested by i386gas.h. */
-#define YES_UNDERSCORES
-#include <i386/gstabs.h>
-
-/* Get generic OpenBSD definitions. */
-#define OBSD_OLD_GAS
-#include <openbsd.h>
+#define TARGET_VERSION fprintf (stderr, " (OpenBSD/i386)");
/* This goes away when the math-emulator is fixed */
#undef TARGET_SUBTARGET_DEFAULT
#define TARGET_SUBTARGET_DEFAULT \
(MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_NO_FANCY_MATH_387)
-/* Run-time target specifications */
-#define CPP_PREDEFINES "-D__unix__ -D__OpenBSD__ \
- -Asystem=unix -Asystem=bsd -Asystem=OpenBSD"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__unix__"); \
+ builtin_define ("__OpenBSD__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=bsd"); \
+ builtin_assert ("system=OpenBSD"); \
+ } \
+ while (0)
/* Layout of source language data types. */
@@ -95,9 +96,6 @@ Boston, MA 02111-1307, USA. */
#undef ASM_PREFERRED_EH_DATA_FORMAT
-
-/* Note that we pick up ASM_OUTPUT_MI_THUNK from unix.h. */
-
#undef ASM_COMMENT_START
#define ASM_COMMENT_START ";#"
diff --git a/contrib/gcc/config/i386/pentium.md b/contrib/gcc/config/i386/pentium.md
new file mode 100644
index 0000000..b4c5ece
--- /dev/null
+++ b/contrib/gcc/config/i386/pentium.md
@@ -0,0 +1,312 @@
+;; Pentium Scheduling
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU CC.
+;;
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA. */
+;;
+;; The Pentium is an in-order core with two integer pipelines.
+
+;; True for insns that behave like prefixed insns on the Pentium.
+(define_attr "pent_prefix" "false,true"
+ (if_then_else (ior (eq_attr "prefix_0f" "1")
+ (ior (eq_attr "prefix_data16" "1")
+ (eq_attr "prefix_rep" "1")))
+ (const_string "true")
+ (const_string "false")))
+
+;; Categorize how an instruction slots.
+
+;; The non-MMX Pentium slots an instruction with prefixes on U pipe only,
+;; while MMX Pentium can slot it on either U or V. Model non-MMX Pentium
+;; rules, because it results in noticeably better code on non-MMX Pentium
+;; and doesn't hurt much on MMX. (Prefixed instructions are not very
+;; common, so the scheduler usualy has a non-prefixed insn to pair).
+
+(define_attr "pent_pair" "uv,pu,pv,np"
+ (cond [(eq_attr "imm_disp" "true")
+ (const_string "np")
+ (ior (eq_attr "type" "alu1,alu,imov,icmp,test,lea,incdec")
+ (and (eq_attr "type" "pop,push")
+ (eq_attr "memory" "!both")))
+ (if_then_else (eq_attr "pent_prefix" "true")
+ (const_string "pu")
+ (const_string "uv"))
+ (eq_attr "type" "ibr")
+ (const_string "pv")
+ (and (eq_attr "type" "ishift")
+ (match_operand 2 "const_int_operand" ""))
+ (const_string "pu")
+ (and (eq_attr "type" "rotate")
+ (match_operand 2 "const_int_1_operand" ""))
+ (const_string "pu")
+ (and (eq_attr "type" "ishift1")
+ (match_operand 1 "const_int_operand" ""))
+ (const_string "pu")
+ (and (eq_attr "type" "rotate1")
+ (match_operand 1 "const_int_1_operand" ""))
+ (const_string "pu")
+ (and (eq_attr "type" "call")
+ (match_operand 0 "constant_call_address_operand" ""))
+ (const_string "pv")
+ (and (eq_attr "type" "callv")
+ (match_operand 1 "constant_call_address_operand" ""))
+ (const_string "pv")
+ ]
+ (const_string "np")))
+
+(define_automaton "pentium,pentium_fpu")
+
+;; Pentium do have U and V pipes. Instruction to both pipes
+;; are alwyas issued together, much like on VLIW.
+;;
+;; predecode
+;; / \
+;; decodeu decodev
+;; / | |
+;; fpu executeu executev
+;; | | |
+;; fpu retire retire
+;; |
+;; fpu
+;; We add dummy "port" pipes allocated only first cycle of
+;; instruction to specify this behavior.
+
+(define_cpu_unit "pentium-portu,pentium-portv" "pentium")
+(define_cpu_unit "pentium-u,pentium-v" "pentium")
+(absence_set "pentium-portu" "pentium-u,pentium-v")
+(presence_set "pentium-portv" "pentium-portu")
+
+;; Floating point instructions can overlap with new issue of integer
+;; instructions. We model only first cycle of FP pipeline, as it is
+;; fully pipelined.
+(define_cpu_unit "pentium-fp" "pentium_fpu")
+
+;; There is non-pipelined multiplier unit used for complex operations.
+(define_cpu_unit "pentium-fmul" "pentium_fpu")
+
+;; Pentium preserves memory ordering, so when load-execute-store
+;; instruction is executed together with other instruction loading
+;; data, the execution of the other instruction is delayed to very
+;; last cycle of first instruction, when data are bypassed.
+;; We model this by allocating "memory" unit when store is pending
+;; and using conflicting load units together.
+
+(define_cpu_unit "pentium-memory" "pentium")
+(define_cpu_unit "pentium-load0" "pentium")
+(define_cpu_unit "pentium-load1" "pentium")
+(absence_set "pentium-load0,pentium-load1" "pentium-memory")
+
+(define_reservation "pentium-load" "(pentium-load0 | pentium-load1)")
+(define_reservation "pentium-np" "(pentium-u + pentium-v)")
+(define_reservation "pentium-uv" "(pentium-u | pentium-v)")
+(define_reservation "pentium-portuv" "(pentium-portu | pentium-portv)")
+(define_reservation "pentium-firstu" "(pentium-u + pentium-portu)")
+(define_reservation "pentium-firstv" "(pentium-v + pentium-portuv)")
+(define_reservation "pentium-firstuv" "(pentium-uv + pentium-portuv)")
+(define_reservation "pentium-firstuload" "(pentium-load + pentium-firstu)")
+(define_reservation "pentium-firstvload" "(pentium-load + pentium-firstv)")
+(define_reservation "pentium-firstuvload" "(pentium-load + pentium-firstuv)
+ | (pentium-firstv,pentium-v,
+ (pentium-load+pentium-firstv))")
+(define_reservation "pentium-firstuboth" "(pentium-load + pentium-firstu
+ + pentium-memory)")
+(define_reservation "pentium-firstvboth" "(pentium-load + pentium-firstv
+ + pentium-memory)")
+(define_reservation "pentium-firstuvboth" "(pentium-load + pentium-firstuv
+ + pentium-memory)
+ | (pentium-firstv,pentium-v,
+ (pentium-load+pentium-firstv))")
+
+;; Few common long latency instructions
+(define_insn_reservation "pent_mul" 11
+ (and (eq_attr "cpu" "pentium")
+ (eq_attr "type" "imul"))
+ "pentium-np*11")
+
+(define_insn_reservation "pent_str" 12
+ (and (eq_attr "cpu" "pentium")
+ (eq_attr "type" "str"))
+ "pentium-np*12")
+
+;; Integer division and some other long latency instruction block all
+;; units, including the FP pipe. There is no value in modeling the
+;; latency of these instructions and not modeling the latency
+;; decreases the size of the DFA.
+(define_insn_reservation "pent_block" 1
+ (and (eq_attr "cpu" "pentium")
+ (eq_attr "type" "idiv"))
+ "pentium-np+pentium-fp")
+
+(define_insn_reservation "pent_cld" 2
+ (and (eq_attr "cpu" "pentium")
+ (eq_attr "type" "cld"))
+ "pentium-np*2")
+
+;; Moves usually have one cycle penalty, but there are exceptions.
+(define_insn_reservation "pent_fmov" 1
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "type" "fmov")
+ (eq_attr "memory" "none,load")))
+ "(pentium-fp+pentium-np)")
+
+(define_insn_reservation "pent_fpmovxf" 3
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "type" "fmov")
+ (and (eq_attr "memory" "load,store")
+ (eq_attr "mode" "XF"))))
+ "(pentium-fp+pentium-np)*3")
+
+(define_insn_reservation "pent_fpstore" 2
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "type" "fmov")
+ (ior (match_operand 1 "immediate_operand" "")
+ (eq_attr "memory" "store"))))
+ "(pentium-fp+pentium-np)*2")
+
+(define_insn_reservation "pent_imov" 1
+ (and (eq_attr "cpu" "pentium")
+ (eq_attr "type" "imov"))
+ "pentium-firstuv")
+
+;; Push and pop instructions have 1 cycle latency and special
+;; hardware bypass allows them to be paired with other push,pop
+;; and call instructions.
+(define_bypass 0 "pent_push,pent_pop" "pent_push,pent_pop,pent_call")
+(define_insn_reservation "pent_push" 1
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "type" "push")
+ (eq_attr "memory" "store")))
+ "pentium-firstuv")
+
+(define_insn_reservation "pent_pop" 1
+ (and (eq_attr "cpu" "pentium")
+ (eq_attr "type" "pop"))
+ "pentium-firstuv")
+
+;; Call and branch instruction can execute in either pipe, but
+;; they are only pairable when in the v pipe.
+(define_insn_reservation "pent_call" 10
+ (and (eq_attr "cpu" "pentium")
+ (eq_attr "type" "call,callv"))
+ "pentium-firstv,pentium-v*9")
+
+(define_insn_reservation "pent_branch" 1
+ (and (eq_attr "cpu" "pentium")
+ (eq_attr "type" "ibr"))
+ "pentium-firstv")
+
+;; Floating point instruction dispatch in U pipe, but continue
+;; in FP pipeline allowing other isntructions to be executed.
+(define_insn_reservation "pent_fp" 3
+ (and (eq_attr "cpu" "pentium")
+ (eq_attr "type" "fop,fistp"))
+ "(pentium-firstu+pentium-fp),nothing,nothing")
+
+;; First two cycles of fmul are not pipelined.
+(define_insn_reservation "pent_fmul" 3
+ (and (eq_attr "cpu" "pentium")
+ (eq_attr "type" "fmul"))
+ "(pentium-firstuv+pentium-fp+pentium-fmul),pentium-fmul,nothing")
+
+;; Long latency FP instructions overlap with integer instructions,
+;; but only last 2 cycles with FP ones.
+(define_insn_reservation "pent_fdiv" 39
+ (and (eq_attr "cpu" "pentium")
+ (eq_attr "type" "fdiv"))
+ "(pentium-np+pentium-fp+pentium-fmul),
+ (pentium-fp+pentium-fmul)*36,pentium-fmul*2")
+
+(define_insn_reservation "pent_fpspc" 70
+ (and (eq_attr "cpu" "pentium")
+ (eq_attr "type" "fpspc"))
+ "(pentium-np+pentium-fp+pentium-fmul),
+ (pentium-fp+pentium-fmul)*67,pentium-fmul*2")
+
+;; Integer instructions. Load/execute/store takes 3 cycles,
+;; load/execute 2 cycles and execute only one cycle.
+(define_insn_reservation "pent_uv_both" 3
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "pent_pair" "uv")
+ (eq_attr "memory" "both")))
+ "pentium-firstuvboth,pentium-uv+pentium-memory,pentium-uv")
+
+(define_insn_reservation "pent_u_both" 3
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "pent_pair" "pu")
+ (eq_attr "memory" "both")))
+ "pentium-firstuboth,pentium-u+pentium-memory,pentium-u")
+
+(define_insn_reservation "pent_v_both" 3
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "pent_pair" "pv")
+ (eq_attr "memory" "both")))
+ "pentium-firstvboth,pentium-v+pentium-memory,pentium-v")
+
+(define_insn_reservation "pent_np_both" 3
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "pent_pair" "np")
+ (eq_attr "memory" "both")))
+ "pentium-np,pentium-np,pentium-np")
+
+(define_insn_reservation "pent_uv_load" 2
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "pent_pair" "uv")
+ (eq_attr "memory" "load")))
+ "pentium-firstuvload,pentium-uv")
+
+(define_insn_reservation "pent_u_load" 2
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "pent_pair" "pu")
+ (eq_attr "memory" "load")))
+ "pentium-firstuload,pentium-u")
+
+(define_insn_reservation "pent_v_load" 2
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "pent_pair" "pv")
+ (eq_attr "memory" "load")))
+ "pentium-firstvload,pentium-v")
+
+(define_insn_reservation "pent_np_load" 2
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "pent_pair" "np")
+ (eq_attr "memory" "load")))
+ "pentium-np,pentium-np")
+
+(define_insn_reservation "pent_uv" 1
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "pent_pair" "uv")
+ (eq_attr "memory" "none")))
+ "pentium-firstuv")
+
+(define_insn_reservation "pent_u" 1
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "pent_pair" "pu")
+ (eq_attr "memory" "none")))
+ "pentium-firstu")
+
+(define_insn_reservation "pent_v" 1
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "pent_pair" "pv")
+ (eq_attr "memory" "none")))
+ "pentium-firstv")
+
+(define_insn_reservation "pent_np" 1
+ (and (eq_attr "cpu" "pentium")
+ (and (eq_attr "pent_pair" "np")
+ (eq_attr "memory" "none")))
+ "pentium-np")
+
diff --git a/contrib/gcc/config/i386/ppro.md b/contrib/gcc/config/i386/ppro.md
new file mode 100644
index 0000000..8690685
--- /dev/null
+++ b/contrib/gcc/config/i386/ppro.md
@@ -0,0 +1,150 @@
+;; Pentium Pro/PII Scheduling
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU CC.
+;;
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA. */
+
+;; Categorize how many uops an ia32 instruction evaluates to:
+;; one -- an instruction with 1 uop can be decoded by any of the
+;; three decoders.
+;; few -- an instruction with 1 to 4 uops can be decoded only by
+;; decoder 0.
+;; many -- a complex instruction may take an unspecified number of
+;; cycles to decode in decoder 0.
+
+(define_attr "ppro_uops" "one,few,many"
+ (cond [(eq_attr "type" "other,multi,call,callv,fpspc,str")
+ (const_string "many")
+ (eq_attr "type" "icmov,fcmov,str,cld")
+ (const_string "few")
+ (eq_attr "type" "imov")
+ (if_then_else (eq_attr "memory" "store,both")
+ (const_string "few")
+ (const_string "one"))
+ (eq_attr "memory" "!none")
+ (const_string "few")
+ ]
+ (const_string "one")))
+
+;;
+;; The PPro has an out-of-order core, but the instruction decoders are
+;; naturally in-order and asymmetric. We get best performance by scheduling
+;; for the decoders, for in doing so we give the oo execution unit the
+;; most choices.
+;;
+;; Rough readiness numbers. Fine tuning happens in i386.c.
+;;
+;; p0 describes port 0.
+;; p01 describes ports 0 and 1 as a pair; alu insns can issue to either.
+;; p2 describes port 2 for loads.
+;; p34 describes ports 3 and 4 for stores.
+;; fpu describes the fpu accessed via port 0.
+;; ??? It is less than clear if there are separate fadd and fmul units
+;; that could operate in parallel.
+;;
+;; ??? fxch isn't handled; not an issue until sched3 after reg-stack is real.
+
+(define_function_unit "ppro_p0" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "ishift,rotate,ishift1,rotate1,lea,ibr,cld"))
+ 1 1)
+
+(define_function_unit "ppro_p0" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "imul"))
+ 4 1)
+
+;; ??? Does the divider lock out the pipe while it works,
+;; or is there a disconnected unit?
+(define_function_unit "ppro_p0" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "idiv"))
+ 17 17)
+
+(define_function_unit "ppro_p0" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "fop,fsgn,fistp"))
+ 3 1)
+
+(define_function_unit "ppro_p0" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "fcmov"))
+ 2 1)
+
+(define_function_unit "ppro_p0" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "fcmp"))
+ 1 1)
+
+(define_function_unit "ppro_p0" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "fmov"))
+ 1 1)
+
+(define_function_unit "ppro_p0" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "fmul"))
+ 5 1)
+
+(define_function_unit "ppro_p0" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "fdiv,fpspc"))
+ 56 1)
+
+(define_function_unit "ppro_p01" 2 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "!imov,fmov"))
+ 1 1)
+
+(define_function_unit "ppro_p01" 2 0
+ (and (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "imov,fmov"))
+ (eq_attr "memory" "none"))
+ 1 1)
+
+(define_function_unit "ppro_p2" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (ior (eq_attr "type" "pop")
+ (eq_attr "memory" "load,both")))
+ 3 1)
+
+(define_function_unit "ppro_p34" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (ior (eq_attr "type" "push")
+ (eq_attr "memory" "store,both")))
+ 1 1)
+
+(define_function_unit "fpu" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "fop,fsgn,fmov,fcmp,fcmov,fistp"))
+ 1 1)
+
+(define_function_unit "fpu" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "fmul"))
+ 5 2)
+
+(define_function_unit "fpu" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "fdiv,fpspc"))
+ 56 56)
+
+;; imul uses the fpu. ??? does it have the same throughput as fmul?
+(define_function_unit "fpu" 1 0
+ (and (eq_attr "cpu" "pentiumpro")
+ (eq_attr "type" "imul"))
+ 4 1)
diff --git a/contrib/gcc/config/i386/ptx4-i.h b/contrib/gcc/config/i386/ptx4-i.h
index 0c51703..a7d5710 100644
--- a/contrib/gcc/config/i386/ptx4-i.h
+++ b/contrib/gcc/config/i386/ptx4-i.h
@@ -1,5 +1,5 @@
/* Target definitions for GNU compiler for Intel 80386 running Dynix/ptx v4
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 2002 Free Software Foundation, Inc.
Modified from sysv4.h
Originally written by Ron Guilmette (rfg@netcom.com).
@@ -23,7 +23,6 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i386 Sequent Dynix/ptx Version 4)");
/* The svr4 ABI for the i386 says that records and unions are returned
@@ -34,11 +33,15 @@ Boston, MA 02111-1307, USA. */
(TYPE_MODE (TYPE) == BLKmode \
|| (VECTOR_MODE_P (TYPE_MODE (TYPE)) && int_size_in_bytes (TYPE) == 8))
-/* Define which macros to predefine. _SEQUENT_ is our extension. */
-/* This used to define X86, but james@bigtex.cactus.org says that
- is supposed to be defined optionally by user programs--not by default. */
-#define CPP_PREDEFINES \
- "-Dunix -D_SEQUENT_ -Asystem=unix -Asystem=ptx4"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("unix"); \
+ builtin_define ("_SEQUENT_"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=ptx4"); \
+ } \
+ while (0)
#undef DBX_REGISTER_NUMBER
#define DBX_REGISTER_NUMBER(n) svr4_dbx_register_map[n]
diff --git a/contrib/gcc/config/i386/rtemself.h b/contrib/gcc/config/i386/rtemself.h
index 7e831b9..0967178 100644
--- a/contrib/gcc/config/i386/rtemself.h
+++ b/contrib/gcc/config/i386/rtemself.h
@@ -1,4 +1,4 @@
-/* Definitions for rtems targeting a ix86 using ELF.
+/* Definitions for rtems targeting an ix86 using ELF.
Copyright (C) 1996, 1997, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
@@ -21,11 +21,14 @@ Boston, MA 02111-1307, USA. */
/* Specify predefined symbols in preprocessor. */
-#include <i386/i386elf.h>
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__rtems__ -Asystem=rtems \
- -D__ELF__ -D__i386__ -D__USE_INIT_FINI__"
-
-#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu) %{msoft-float:-D_SOFT_FLOAT}"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__rtems__"); \
+ builtin_define ("__ELF__"); \
+ builtin_define ("__USE_INIT_FINI__"); \
+ builtin_assert ("system=rtems"); \
+ if (!TARGET_80387) \
+ builtin_define ("_SOFT_FLOAT"); \
+ } \
+ while (0)
diff --git a/contrib/gcc/config/i386/sco5.h b/contrib/gcc/config/i386/sco5.h
index 36a04d5..815e457 100644
--- a/contrib/gcc/config/i386/sco5.h
+++ b/contrib/gcc/config/i386/sco5.h
@@ -1,5 +1,5 @@
/* Definitions for Intel 386 running SCO Unix System V 3.2 Version 5.
- Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999, 2000
+ Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2002
Free Software Foundation, Inc.
Contributed by Kean Johnston (hug@netcom.com)
@@ -20,7 +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. */
-#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i386, SCO OpenServer 5 Syntax)");
#undef LPREFIX
@@ -78,17 +77,13 @@ Boston, MA 02111-1307, USA. */
#define DWARF2_UNWIND_INFO \
((TARGET_ELF) ? 1 : 0 )
-#undef CONST_SECTION_ASM_OP
-#define CONST_SECTION_ASM_OP_COFF "\t.section\t.rodata, \"x\""
-#define CONST_SECTION_ASM_OP_ELF "\t.section\t.rodata"
-#define CONST_SECTION_ASM_OP \
- ((TARGET_ELF) ? CONST_SECTION_ASM_OP_ELF : CONST_SECTION_ASM_OP_COFF)
-
-#undef USE_CONST_SECTION
-#define USE_CONST_SECTION_ELF 1
-#define USE_CONST_SECTION_COFF 0
-#define USE_CONST_SECTION \
- ((TARGET_ELF) ? USE_CONST_SECTION_ELF : USE_CONST_SECTION_COFF)
+#undef READONLY_DATA_SECTION_ASM_OP
+#define READONLY_DATA_SECTION_ASM_OP_COFF "\t.section\t.rodata, \"x\""
+#define READONLY_DATA_SECTION_ASM_OP_ELF "\t.section\t.rodata"
+#define READONLY_DATA_SECTION_ASM_OP \
+ ((TARGET_ELF) \
+ ? READONLY_DATA_SECTION_ASM_OP_ELF \
+ : READONLY_DATA_SECTION_ASM_OP_COFF)
#undef INIT_SECTION_ASM_OP
#define INIT_SECTION_ASM_OP_ELF "\t.section\t.init"
@@ -144,13 +139,9 @@ do { \
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
do { \
if (TARGET_ELF) { \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
- putc ('\n', FILE); \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
- ASM_OUTPUT_LABEL(FILE, NAME); \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
} else \
SCO_DEFAULT_ASM_COFF(FILE, NAME); \
} while (0)
@@ -158,34 +149,28 @@ do { \
#undef ASM_DECLARE_FUNCTION_SIZE
#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
do { \
- if (TARGET_ELF) { if (!flag_inhibit_size_directive) \
- { \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, (FNAME)); \
- fprintf (FILE, ",.-"); \
- assemble_name (FILE, (FNAME)); \
- putc ('\n', FILE); \
- } } \
+ if (TARGET_ELF && !flag_inhibit_size_directive) \
+ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
} while (0)
#undef ASM_DECLARE_OBJECT_NAME
#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
do { \
if (TARGET_ELF) { \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
- putc ('\n', FILE); \
+ HOST_WIDE_INT size; \
+ \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
+ \
size_directive_output = 0; \
- if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
- { \
- size_directive_output = 1; \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \
- } \
- ASM_OUTPUT_LABEL(FILE, NAME); \
+ if (!flag_inhibit_size_directive \
+ && (DECL) && DECL_SIZE (DECL)) \
+ { \
+ size_directive_output = 1; \
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \
+ } \
+ \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
} else \
SCO_DEFAULT_ASM_COFF(FILE, NAME); \
} while (0)
@@ -203,17 +188,17 @@ do { \
#undef ASM_FINISH_DECLARE_OBJECT
#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
do { \
- if (TARGET_ELF) { \
+ if (TARGET_ELF) { \
const char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
+ HOST_WIDE_INT size; \
if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
&& ! AT_END && TOP_LEVEL \
&& DECL_INITIAL (DECL) == error_mark_node \
&& !size_directive_output) \
{ \
size_directive_output = 1; \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, name); \
- fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, name, size); \
} \
} \
} while (0)
@@ -353,19 +338,6 @@ do { \
fprintf ((FILE), "\n"); \
} while (0)
-/* Must use data section for relocatable constants when pic. */
-#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE,RTX,ALIGN) \
-{ \
- if (TARGET_ELF) { \
- if (flag_pic && symbolic_operand (RTX, VOIDmode)) \
- data_section (); \
- else \
- const_section (); \
- } else \
- readonly_data_section(); \
-}
-
#undef ASM_OUTPUT_CASE_LABEL
#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \
do { \
@@ -378,13 +350,9 @@ do { \
#define ASM_OUTPUT_IDENT(FILE, NAME) \
fprintf (FILE, "%s\"%s\"\n", IDENT_ASM_OP, NAME);
-#undef ASM_GLOBALIZE_LABEL
-#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
- (fprintf ((FILE), "%s", GLOBAL_ASM_OP), assemble_name (FILE, NAME), fputs ("\n", FILE))
-
#undef ASM_OUTPUT_EXTERNAL_LIBCALL
#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
- if (TARGET_ELF) ASM_GLOBALIZE_LABEL (FILE, XSTR (FUN, 0))
+ if (TARGET_ELF) (*targetm.asm_out.globalize_label) (FILE, XSTR (FUN, 0))
#undef ASM_OUTPUT_INTERNAL_LABEL
#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
@@ -445,42 +413,23 @@ do { \
#define DBX_REGISTER_NUMBER(n) \
((TARGET_ELF) ? svr4_dbx_register_map[n] : dbx_register_map[n])
-#undef DWARF2_DEBUGGING_INFO
-#undef DWARF_DEBUGGING_INFO
-#undef SDB_DEBUGGING_INFO
-#undef DBX_DEBUGGING_INFO
-#undef PREFERRED_DEBUGGING_TYPE
-
#define DWARF2_DEBUGGING_INFO 1
#define DWARF_DEBUGGING_INFO 1
-#define SDB_DEBUGGING_INFO 1
-#define DBX_DEBUGGING_INFO 1
+#define SDB_DEBUGGING_INFO 1
+#define DBX_DEBUGGING_INFO 1
+
+#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE \
((TARGET_ELF) ? DWARF2_DEBUG: SDB_DEBUG)
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const, in_init, in_fini
+#define EXTRA_SECTIONS in_init, in_fini
#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
- CONST_SECTION_FUNCTION \
INIT_SECTION_FUNCTION \
FINI_SECTION_FUNCTION
-#undef CONST_SECTION_FUNCTION
-#define CONST_SECTION_FUNCTION \
-void \
-const_section () \
-{ \
- if (!USE_CONST_SECTION) \
- text_section(); \
- else if (in_section != in_const) \
- { \
- fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
- in_section = in_const; \
- } \
-}
-
#undef FINI_SECTION_FUNCTION
#define FINI_SECTION_FUNCTION \
void \
@@ -541,28 +490,9 @@ init_section () \
== void_type_node))) ? (SIZE) \
: 0))
-#undef SELECT_SECTION
-#define SELECT_SECTION(DECL,RELOC,ALIGN) \
-{ \
- if (TARGET_ELF && flag_pic && RELOC) \
- data_section (); \
- else if (TREE_CODE (DECL) == STRING_CST) \
- { \
- if (! flag_writable_strings) \
- const_section (); \
- else \
- data_section (); \
- } \
- else if (TREE_CODE (DECL) == VAR_DECL) \
- { \
- if (! DECL_READONLY_SECTION (DECL, RELOC)) \
- data_section (); \
- else \
- const_section (); \
- } \
- else \
- const_section (); \
-}
+/* ??? Ignore coff. */
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION default_elf_select_section
#undef SWITCH_TAKES_ARG
#define SWITCH_TAKES_ARG(CHAR) \
@@ -581,7 +511,6 @@ init_section () \
#undef TARGET_SUBTARGET_DEFAULT
#define TARGET_SUBTARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS)
-#undef HANDLE_SYSV_PRAGMA
#define HANDLE_SYSV_PRAGMA 1
/* Though OpenServer supports .weak in COFF, we don't use it.
@@ -593,9 +522,6 @@ init_section () \
do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
fputc ('\n', FILE); } while (0)
-#undef SCCS_DIRECTIVE
-#define SCCS_DIRECTIVE 1
-
/*
* Define sizes and types
*/
@@ -673,13 +599,11 @@ init_section () \
%{pg:gcrt.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}}} \
%{ansi:values-Xc.o%s} \
%{!ansi: \
- %{traditional:values-Xt.o%s} \
- %{!traditional: \
- %{Xa:values-Xa.o%s} \
- %{!Xa:%{Xc:values-Xc.o%s} \
- %{!Xc:%{Xk:values-Xk.o%s} \
- %{!Xk:%{Xt:values-Xt.o%s} \
- %{!Xt:values-Xa.o%s}}}}}} \
+ %{Xa:values-Xa.o%s} \
+ %{!Xa:%{Xc:values-Xc.o%s} \
+ %{!Xc:%{Xk:values-Xk.o%s} \
+ %{!Xk:%{Xt:values-Xt.o%s} \
+ %{!Xt:values-Xa.o%s}}}}} \
%{mcoff:crtbeginS.o%s} %{!mcoff:crtbegin.o%s}"
#undef ENDFILE_SPEC
@@ -688,20 +612,32 @@ init_section () \
%{mcoff:crtendS.o%s} \
%{pg:gcrtn.o%s}%{!pg:crtn.o%s}"
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
- "-Asystem=svr3"
-
-/* You are in a maze of GCC specs ... all alike */
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__unix"); \
+ builtin_define ("_SCO_DS"); \
+ builtin_define ("_M_I386"); \
+ builtin_define ("_M_XENIX"); \
+ builtin_define ("_M_UNIX"); \
+ builtin_assert ("system=svr3"); \
+ if (flag_iso) \
+ cpp_define (pfile, "_STRICT_ANSI"); \
+ if (flag_pic) \
+ { \
+ builtin_define ("__PIC__"); \
+ builtin_define ("__pic__"); \
+ } \
+ } \
+ while (0)
#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu) \
+#define CPP_SPEC "\
%{fpic:%{mcoff:%e-fpic is not valid with -mcoff}} \
%{fPIC:%{mcoff:%e-fPIC is not valid with -mcoff}} \
- -D__i386 -D__unix -D_SCO_DS=1 -D_M_I386 -D_M_XENIX -D_M_UNIX \
%{!Xods30:-D_STRICT_NAMES} \
%{!ansi:%{!posix:%{!Xods30:-D_SCO_XPG_VERS=4}}} \
- %{ansi:-isystem include/ansi%s -isystem /usr/include/ansi -D_STRICT_ANSI} \
+ %{ansi:-isystem include/ansi%s -isystem /usr/include/ansi} \
%{!ansi: \
%{posix:-isystem include/posix%s -isystem /usr/include/posix \
-D_POSIX_C_SOURCE=2 -D_POSIX_SOURCE=1} \
@@ -716,17 +652,13 @@ init_section () \
-DM_BITFIELDS -DM_SYS5 -DM_SYSV -DM_INTERNAT -DM_SYSIII \
-DM_WORDSWAP}}}} \
%{scointl:-DM_INTERNAT -D_M_INTERNAT} \
- %{traditional:-D_KR -D_SVID -D_NO_PROTOTYPE} \
%{!mcoff:-D_SCO_ELF} \
%{mcoff:-D_M_COFF -D_SCO_COFF} \
- %{!mcoff:%{fpic:-D__PIC__ -D__pic__} \
- %{fPIC:%{!fpic:-D__PIC__ -D__pic__}}} \
%{Xa:-D_SCO_C_DIALECT=1} \
%{!Xa:%{Xc:-D_SCO_C_DIALECT=3} \
%{!Xc:%{Xk:-D_SCO_C_DIALECT=4} \
%{!Xk:%{Xt:-D_SCO_C_DIALECT=2} \
- %{!Xt:-D_SCO_C_DIALECT=1}}}} \
- %{traditional:-traditional -D_KR -D_NO_PROTOTYPE}"
+ %{!Xt:-D_SCO_C_DIALECT=1}}}}"
#undef LINK_SPEC
#define LINK_SPEC \
diff --git a/contrib/gcc/config/i386/sol2.h b/contrib/gcc/config/i386/sol2.h
index 5fa5fcd..fb5a184 100644
--- a/contrib/gcc/config/i386/sol2.h
+++ b/contrib/gcc/config/i386/sol2.h
@@ -20,36 +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. */
-
-/* We use stabs-in-elf for debugging, because that is what the native
- toolchain uses. */
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-
-#if ! GAS_REJECTS_MINUS_S
-
-/*
- Changed from config/svr4.h in the following ways:
-
- - Removed -Yd (neither the sun bundled assembler nor gas accept it).
- - Added "-s" so that stabs are not discarded.
-*/
-
-#undef ASM_SPEC
-#define ASM_SPEC \
- "%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s"
-
#define CMOV_SUN_AS_SYNTAX 1
-#else /* GAS_REJECTS_MINUS_S */
-
-/* Same as above, except for -s, unsupported by GNU as. */
-#undef ASM_SPEC
-#define ASM_SPEC \
- "%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*}"
-
-#endif /* GAS_REJECTS_MINUS_S */
-
/* The Solaris 2.0 x86 linker botches alignment of code sections.
It tries to align to a 16 byte boundary by padding with 0x00000090
ints, rather than 0x90 bytes (nop). This generates trash in the
@@ -68,92 +40,26 @@ Boston, MA 02111-1307, USA. */
(flag_pic ? (GLOBAL ? DW_EH_PE_indirect : 0) | DW_EH_PE_datarel \
: DW_EH_PE_absptr)
-/* Solaris 2/Intel uses a wint_t different from the default, as on SPARC. */
-#undef WINT_TYPE
-#define WINT_TYPE "long int"
-
-#undef WINT_TYPE_SIZE
-#define WINT_TYPE_SIZE BITS_PER_WORD
-
-#define HANDLE_PRAGMA_REDEFINE_EXTNAME 1
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
- "-Dunix -D__svr4__ -D__SVR4 -Dsun -D__PRAGMA_REDEFINE_EXTNAME -Asystem=svr4"
-
/* Solaris 2/Intel as chokes on #line directives. */
#undef CPP_SPEC
-#define CPP_SPEC \
- "%{.S:-P} \
- %(cpp_cpu) \
- %{pthreads:-D_REENTRANT -D_PTHREADS} \
- %{!pthreads:%{threads:-D_REENTRANT -D_SOLARIS_THREADS}} \
- %{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude}"
+#define CPP_SPEC "%{.S:-P} %(cpp_subtarget)"
-/* For C++ we need to add some additional macro definitions required
- by the C++ standard library. */
-#define CPLUSPLUS_CPP_SPEC "\
--D_XOPEN_SOURCE=500 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE=1 \
--D__EXTENSIONS__ \
-%(cpp) \
+/* FIXME: Removed -K PIC from generic Solaris 2 ASM_SPEC: the native assembler
+ gives many warnings: R_386_32 relocation is used for symbol ".text". */
+#undef ASM_SPEC
+#define ASM_SPEC "\
+%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s \
+%(asm_cpu) \
"
-#undef LIB_SPEC
-#define LIB_SPEC \
- "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} \
- %{!shared:\
- %{!symbolic:\
- %{pthreads:-lpthread} \
- %{!pthreads:%{threads:-lthread}} \
- -lc}}"
-
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC "crtend.o%s %{pg:crtn.o%s}%{!pg:crtn.o%s}"
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{!shared: \
- %{!symbolic: \
- %{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}}}\
- %{pg:gmon.o%s} crti.o%s \
- %{ansi:values-Xc.o%s} \
- %{!ansi: \
- %{traditional:values-Xt.o%s} \
- %{!traditional:values-Xa.o%s}} \
- crtbegin.o%s"
-
-/* This should be the same as in svr4.h, except with -R added. */
-#undef LINK_SPEC
-#define LINK_SPEC \
- "%{h*} %{v:-V} \
- %{b} %{Wl,*:%*} \
- %{static:-dn -Bstatic} \
- %{shared:-G -dy %{!mimpure-text:-z text}} \
- %{symbolic:-Bsymbolic -G -dy -z text} \
- %{G:-G} \
- %{YP,*} \
- %{R*} \
- %{compat-bsd: \
- %{!YP,*:%{pg:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{!pg:%{p:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{!p:-Y P,/usr/ucblib:/usr/ccs/lib:/usr/lib}}} \
- -R /usr/ucblib} \
- %{!compat-bsd: \
- %{!YP,*:%{pg:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{!pg:%{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{!p:-Y P,/usr/ccs/lib:/usr/lib}}}} \
- %{Qy:} %{!Qn:-Qy}"
-
-/* This defines which switch letters take arguments.
- It is as in svr4.h but with -R added. */
-
-#undef SWITCH_TAKES_ARG
-#define SWITCH_TAKES_ARG(CHAR) \
- (DEFAULT_SWITCH_TAKES_ARG(CHAR) \
- || (CHAR) == 'R' \
- || (CHAR) == 'h' \
- || (CHAR) == 'z')
-
-#define STDC_0_IN_SYSTEM_HEADERS 1
+#define ASM_CPU_SPEC ""
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "cpp_subtarget", CPP_SUBTARGET_SPEC }, \
+ { "asm_cpu", ASM_CPU_SPEC }, \
+ { "startfile_arch", STARTFILE_ARCH_SPEC }, \
+ { "link_arch", LINK_ARCH_SPEC }
#undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX "."
diff --git a/contrib/gcc/config/i386/svr3dbx.h b/contrib/gcc/config/i386/svr3dbx.h
index b0e4237..4be7a70 100644
--- a/contrib/gcc/config/i386/svr3dbx.h
+++ b/contrib/gcc/config/i386/svr3dbx.h
@@ -1,5 +1,5 @@
-/* Definitions for Intel 386 running system V, using dbx-in-coff encapsulation.
- Copyright (C) 1992, 1995 Free Software Foundation, Inc.
+/* Definitions for Intel 385 running system V, using dbx-in-coff encapsulation.
+ Copyright (C) 1992, 1995, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,15 +18,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 "i386/svr3gas.h"
-
/* We do not want to output SDB debugging information. */
#undef SDB_DEBUGGING_INFO
/* We want to output DBX debugging information. */
-#define DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
/* Compensate for botch in dbxout_init/dbxout_source_file which
unconditionally drops the first character from ltext_label_name */
diff --git a/contrib/gcc/config/i386/svr3gas.h b/contrib/gcc/config/i386/svr3gas.h
index 08ada11..b9d94b7 100644
--- a/contrib/gcc/config/i386/svr3gas.h
+++ b/contrib/gcc/config/i386/svr3gas.h
@@ -1,5 +1,5 @@
/* Definitions for Intel 386 running system V, using gas.
- Copyright (C) 1992, 1996, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1996, 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,7 +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. */
-#include "i386/gas.h"
+#define TARGET_VERSION fprintf (stderr, " (80386, ATT syntax)");
/* Add stuff that normally comes from i386/sysv3.h */
@@ -83,22 +83,8 @@ Boston, MA 02111-1307, USA. */
this file should be rewritten to include config/svr3.h
and override what isn't right. */
-/* Support const sections and the ctors and dtors sections for g++.
- Note that there appears to be two different ways to support const
- sections at the moment. You can either #define the symbol
- READONLY_DATA_SECTION (giving it some code which switches to the
- readonly data section) or else you can #define the symbols
- EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
- SELECT_RTX_SECTION. We do both here just to be on the safe side.
- However, use of the const section is turned off by default
- unless the specific tm.h file turns it on by defining
- USE_CONST_SECTION as 1. */
-
-#define USE_CONST_SECTION 0
-
#define INIT_SECTION_ASM_OP "\t.section\t.init"
#define FINI_SECTION_ASM_OP "\t.section .fini,\"x\""
-#define CONST_SECTION_ASM_OP "\t.section\t.rodata, \"x\""
#define CTORS_SECTION_ASM_OP INIT_SECTION_ASM_OP
#define DTORS_SECTION_ASM_OP FINI_SECTION_ASM_OP
@@ -122,14 +108,11 @@ do { \
(*--p) (); \
} while (0)
-/* Add extra sections .rodata, .init and .fini. */
-
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const, in_init, in_fini
+#define EXTRA_SECTIONS in_init, in_fini
#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
- CONST_SECTION_FUNCTION \
INIT_SECTION_FUNCTION \
FINI_SECTION_FUNCTION
@@ -155,56 +138,4 @@ fini_section () \
} \
}
-#define READONLY_DATA_SECTION() const_section ()
-
-#define CONST_SECTION_FUNCTION \
-void \
-const_section () \
-{ \
- if (!USE_CONST_SECTION) \
- text_section(); \
- else if (in_section != in_const) \
- { \
- fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
- in_section = in_const; \
- } \
-}
-
#define TARGET_ASM_CONSTRUCTOR ix86_svr3_asm_out_constructor
-
-/* A C statement or statements to switch to the appropriate
- section for output of DECL. DECL is either a `VAR_DECL' node
- or a constant of some sort. RELOC indicates whether forming
- the initial value of DECL requires link-time relocations. */
-
-#define SELECT_SECTION(DECL,RELOC,ALIGN) \
-{ \
- if (TREE_CODE (DECL) == STRING_CST) \
- { \
- if (! flag_writable_strings) \
- const_section (); \
- else \
- data_section (); \
- } \
- else if (TREE_CODE (DECL) == VAR_DECL) \
- { \
- if ((0 && RELOC) /* should be (flag_pic && RELOC) */ \
- || !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
- || !DECL_INITIAL (DECL) \
- || (DECL_INITIAL (DECL) != error_mark_node \
- && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \
- data_section (); \
- else \
- const_section (); \
- } \
- else \
- const_section (); \
-}
-
-/* A C statement or statements to switch to the appropriate
- section for output of RTX in mode MODE. RTX is some kind
- of constant in RTL. The argument MODE is redundant except
- in the case of a `const_int' rtx. Currently, these always
- go into the const section. */
-
-#define SELECT_RTX_SECTION(MODE,RTX,ALIGN) const_section()
diff --git a/contrib/gcc/config/i386/sysv3.h b/contrib/gcc/config/i386/sysv3.h
index 8eb4bec..93f9445 100644
--- a/contrib/gcc/config/i386/sysv3.h
+++ b/contrib/gcc/config/i386/sysv3.h
@@ -1,5 +1,5 @@
/* Definitions for Intel 386 running system V.
- Copyright (C) 1988, 1996, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1996, 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,17 +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. */
-
-#include "i386/i386.h"
-
-/* Use default settings for system V.3. */
-
-#include "svr3.h"
-
-/* Use the ATT assembler syntax.
- This overrides at least one macro (USER_LABEL_PREFIX) from svr3.h. */
-
-#include "i386/att.h"
+#define TARGET_VERSION fprintf (stderr, " (80386, ATT syntax)");
/* Use crt1.o as a startup file and crtn.o as a closing file. */
@@ -42,11 +32,17 @@ Boston, MA 02111-1307, USA. */
/* Specify predefined symbols in preprocessor. */
-#define CPP_PREDEFINES "-Dunix -Asystem=svr3"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("unix"); \
+ builtin_assert ("system=svr3"); \
+ } \
+ while (0)
-#define CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE}"
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE}"
-/* Writing `int' for a bitfield forces int alignment for the structure. */
+/* Writing `int' for a bit-field forces int alignment for the structure. */
#define PCC_BITFIELD_TYPE_MATTERS 1
@@ -57,8 +53,7 @@ Boston, MA 02111-1307, USA. */
/* We want to be able to get DBX debugging information via -gstabs. */
-#undef DBX_DEBUGGING_INFO
-#define DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG
diff --git a/contrib/gcc/config/i386/sysv4-cpp.h b/contrib/gcc/config/i386/sysv4-cpp.h
new file mode 100644
index 0000000..5b46bf1
--- /dev/null
+++ b/contrib/gcc/config/i386/sysv4-cpp.h
@@ -0,0 +1,32 @@
+/* Target definitions for GNU compiler for Intel 80386 running System V.4
+ Copyright (C) 1991, 2001, 2002 Free Software Foundation, Inc.
+
+ Written by Ron Guilmette (rfg@netcom.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("unix"); \
+ builtin_define ("__svr4__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=svr4"); \
+ } \
+ while (0)
+
diff --git a/contrib/gcc/config/i386/sysv4.h b/contrib/gcc/config/i386/sysv4.h
index 7dc0ac1..6b3335e 100644
--- a/contrib/gcc/config/i386/sysv4.h
+++ b/contrib/gcc/config/i386/sysv4.h
@@ -1,5 +1,5 @@
/* Target definitions for GNU compiler for Intel 80386 running System V.4
- Copyright (C) 1991, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1991, 2001, 2002 Free Software Foundation, Inc.
Written by Ron Guilmette (rfg@netcom.com).
@@ -21,7 +21,6 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i386 System V Release 4)");
/* The svr4 ABI for the i386 says that records and unions are returned
@@ -32,12 +31,6 @@ Boston, MA 02111-1307, USA. */
(TYPE_MODE (TYPE) == BLKmode \
|| (VECTOR_MODE_P (TYPE_MODE (TYPE)) && int_size_in_bytes (TYPE) == 8))
-/* Define which macros to predefine. __svr4__ is our extension. */
-/* This used to define X86, but james@bigtex.cactus.org says that
- is supposed to be defined optionally by user programs--not by default. */
-#define CPP_PREDEFINES \
- "-Dunix -D__svr4__ -Asystem=unix -Asystem=svr4"
-
/* Output at beginning of assembler file. */
/* The .file command should always begin the output. */
@@ -141,6 +134,3 @@ Boston, MA 02111-1307, USA. */
"addl\t$_GLOBAL_OFFSET_TABLE_+[.-.LPR%=],%0" \
: "=d"(BASE))
#endif
-
-#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu)"
diff --git a/contrib/gcc/config/i386/sysv5.h b/contrib/gcc/config/i386/sysv5.h
index 87d6b9c..9b759f4 100644
--- a/contrib/gcc/config/i386/sysv5.h
+++ b/contrib/gcc/config/i386/sysv5.h
@@ -31,4 +31,4 @@ Boston, MA 02111-1307, USA. */
%{!shared:%{!symbolic:-lc -lcrt}}"
#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu) %{pthread:-D_REENTRANT} %{pthreadT:-D_REENTRANT}"
+#define CPP_SPEC "%{pthread:-D_REENTRANT} %{pthreadT:-D_REENTRANT}"
diff --git a/contrib/gcc/config/i386/t-cygwin b/contrib/gcc/config/i386/t-cygwin
index 68d2ac5..6fcb834 100644
--- a/contrib/gcc/config/i386/t-cygwin
+++ b/contrib/gcc/config/i386/t-cygwin
@@ -14,7 +14,7 @@ LIBGCC2_INCLUDES = -I$(srcdir)/../winsup/include \
-I$(srcdir)/../winsup/cygwin/include \
-I$(srcdir)/../winsup/w32api/include
-winnt.o: $(srcdir)/config/i386/winnt.c $(RTL_H) $(TREE_H) $(CONFIG_H)
+winnt.o: $(srcdir)/config/i386/winnt.c $(RTL_H) $(TREE_H) $(CONFIG_H) $(TM_P_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/winnt.c
# Don't run fixproto
diff --git a/contrib/gcc/config/i386/t-interix b/contrib/gcc/config/i386/t-interix
index adcf593..710de8b 100644
--- a/contrib/gcc/config/i386/t-interix
+++ b/contrib/gcc/config/i386/t-interix
@@ -1,6 +1,6 @@
LIB1ASMSRC = i386/cygwin.asm
LIB1ASMFUNCS = _chkstk
-interix.o: $(srcdir)/config/i386/interix.c
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/interix.c
+winnt.o: $(srcdir)/config/i386/winnt.c $(TM_P_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/winnt.c
diff --git a/contrib/gcc/config/i386/t-linux64 b/contrib/gcc/config/i386/t-linux64
index 31b6ad4..3b109d8 100644
--- a/contrib/gcc/config/i386/t-linux64
+++ b/contrib/gcc/config/i386/t-linux64
@@ -12,3 +12,9 @@ LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
+
+# The pushl in CTOR initialization interferes with frame pointer elimination.
+# crtend*.o cannot be compiled without -fno-asynchronous-unwind-tables,
+# because then __FRAME_END__ might not be the last thing in .eh_frame
+# section.
+CRTSTUFF_T_CFLAGS = -fno-omit-frame-pointer -fno-asynchronous-unwind-tables
diff --git a/contrib/gcc/config/i386/t-mingw32 b/contrib/gcc/config/i386/t-mingw32
index fe948c6..28096f8 100644
--- a/contrib/gcc/config/i386/t-mingw32
+++ b/contrib/gcc/config/i386/t-mingw32
@@ -2,3 +2,6 @@
# collect2 doesn't work for i386-mingw32* yet.
#
USE_COLLECT2=
+
+# We hide calls to w32api needed for w32 thread support here:
+LIB2FUNCS_EXTRA = $(srcdir)/config/i386/gthr-win32.c
diff --git a/contrib/gcc/config/i386/t-sco5gas b/contrib/gcc/config/i386/t-sco5gas
index 2d0b48a..edeb554 100644
--- a/contrib/gcc/config/i386/t-sco5gas
+++ b/contrib/gcc/config/i386/t-sco5gas
@@ -1,6 +1,6 @@
# The pushl in CTOR initialization interferes with frame pointer elimination.
CRTSTUFF_T_CFLAGS = -fPIC -fno-omit-frame-pointer
-CRTSTUFF_T_CFLAGS_S = -mcoff -fno-omit-frame-pointer
+CRTSTUFF_T_CFLAGS_S = -fno-omit-frame-pointer
#
# I am still a little unsure of the multilib architecture. The following
diff --git a/contrib/gcc/config/i386/unix.h b/contrib/gcc/config/i386/unix.h
index f7e38b4..e69f26d 100644
--- a/contrib/gcc/config/i386/unix.h
+++ b/contrib/gcc/config/i386/unix.h
@@ -1,5 +1,5 @@
/* Definitions for Unix assembler syntax for the Intel 80386.
- Copyright (C) 1988, 1994, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1994, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -58,26 +58,10 @@ Boston, MA 02111-1307, USA. */
#define BSS_SECTION_ASM_OP "\t.bss"
-/* This is how to output a command to make the user-level label named NAME
- defined for reference from other files. */
-
-#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
- (fputs (".globl ", FILE), assemble_name (FILE, NAME), fputs ("\n", FILE))
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP ".globl "
/* By default, target has a 80387, uses IEEE compatible arithmetic,
and returns float values in the 387. */
#define TARGET_SUBTARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS)
-
-/* Floating-point return values come in the FP register. */
-
-#define VALUE_REGNO(MODE) \
- (GET_MODE_CLASS (MODE) == MODE_FLOAT \
- && TARGET_FLOAT_RETURNS_IN_80387 ? FIRST_FLOAT_REG \
- : (MODE) == TImode || VECTOR_MODE_P (MODE) ? FIRST_SSE_REG \
- : 0)
-
-/* 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) \
- x86_output_mi_thunk (FILE, DELTA, FUNCTION);
diff --git a/contrib/gcc/config/i386/uwin.h b/contrib/gcc/config/i386/uwin.h
index ca39ffd..1210510 100644
--- a/contrib/gcc/config/i386/uwin.h
+++ b/contrib/gcc/config/i386/uwin.h
@@ -2,7 +2,7 @@
hosting on U/WIN (Windows32), using GNU tools and the Windows32 API
Library, as distinct from winnt.h, which is used to build GCC for use
with a windows style library and tool set and uses the Microsoft tools.
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002 Free Software Foundation, Inc.
Contributed by Mumit Khan <khan@xraylith.wisc.edu>.
This file is part of GNU CC.
@@ -25,26 +25,27 @@ Boston, MA 02111-1307, USA. */
/* Most of this is the same as for Cygwin32, except for changing some
specs. */
-#include "i386/cygwin.h"
-
#define STANDARD_INCLUDE_COMPONENT "UWIN"
#define SYSTEM_INCLUDE_DIR "/usr/gnu/include"
#undef MD_STARTFILE_PREFIX
#define MD_STARTFILE_PREFIX "/usr/gnu/lib/"
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D_WIN32 -D__WIN32__ \
- -D_UWIN -DWINNT -D_X86_=1 -D__STDC__=1 \
- -D__UWIN__ -D__MSVCRT__ \
- -D_STD_INCLUDE_DIR=mingw32 \
- -D__stdcall=__attribute__((__stdcall__)) \
- _D_stdcall=__attribute__((__stdcall__)) \
- -D__cdecl=__attribute__((__cdecl__)) \
- -D__declspec(x)=__attribute__((x)) \
- -Asystem=winnt"
+#undef MAYBE_UWIN_CPP_BUILTINS
+#define MAYBE_UWIN_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("WINNT"); \
+ builtin_define ("_WIN32"); \
+ builtin_define ("__WIN32__"); \
+ builtin_define ("_UWIN"); \
+ builtin_define ("__UWIN__"); \
+ builtin_define ("__MSVCRT__"); \
+ builtin_define ("_STD_INCLUDE_DIR=mingw32"); \
+ } \
+ while (0)
#undef CPP_SPEC
-#define CPP_SPEC "-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE} \
+#define CPP_SPEC "-remap %{posix:-D_POSIX_SOURCE} \
-include /usr/include/astwin32.h \
-idirafter /usr/gnu/include/mingw32"
diff --git a/contrib/gcc/config/i386/vsta.h b/contrib/gcc/config/i386/vsta.h
index 1bb897d..9388329 100644
--- a/contrib/gcc/config/i386/vsta.h
+++ b/contrib/gcc/config/i386/vsta.h
@@ -1,5 +1,5 @@
/* Configuration for an i386 running VSTa micro-kernel.
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 2002 Free Software Foundation, Inc.
Contributed by Rob Savoye (rob@cygnus.com).
This file is part of GNU CC.
@@ -19,11 +19,14 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#define YES_UNDERSCORES
+#define TARGET_VERSION fprintf (stderr, " (80386, BSD syntax)");
-#include "i386/gas.h"
-
-#ifdef CPP_PREDEFINES
-#undef CPP_PREDEFINES
-#endif
-#define CPP_PREDEFINES "-Dunix -DVSTA -Asystem=unix -Asystem=vsta"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("unix"); \
+ builtin_define ("VSTA"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=vsta"); \
+ } \
+ while (0)
diff --git a/contrib/gcc/config/i386/vxi386.h b/contrib/gcc/config/i386/vxi386.h
index c050ca7..ee4a740 100644
--- a/contrib/gcc/config/i386/vxi386.h
+++ b/contrib/gcc/config/i386/vxi386.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. VxWorks i386 version.
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,29 +18,33 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#undef CPP_CPU_SPEC
-#define CPP_CPU_SPEC "\
--Asystem=unix -Acpu=i386 -Amachine=i386 \
-%{!ansi:-Di386} -D__i386 -D__i386__ \
-%{march=i386:-DCPU=I80386} \
-%{march=i486:-DCPU=I80486 %(cpp_486)} \
-%{march=pentium:-DCPU=PENTIUM -DCPU_VARIANT=PENTIUM %(cpp_586)} \
-%{march=pentiumpro:-DCPU=PENTIUM -DCPU_VARIANT=PENTIUMPRO %(cpp_686)} \
-%{!march=*: \
- %{mcpu=i386:-DCPU=I80386} \
- %{mcpu=i486:-DCPU=I80486 %(cpp_486)} %{m486:-DCPU=I80486 %(cpp_486)} \
- %{mpentium:-DCPU=PENTIUM -DCPU_VARIANT=PENTIUM %(cpp_586)} \
- %{mcpu=pentium:-DCPU=PENTIUM -DCPU_VARIANT=PENTIUM %(cpp_586)} \
- %{mpentiumpro:-DCPU=PENTIUM -DCPU_VARIANT=PENTIUMPRO %(cpp_686)} \
- %{mcpu=pentiumpro:-DCPU=PENTIUM -DCPU_VARIANT=PENTIUMPRO %(cpp_686)} \
- %{!mcpu*:%{!m486:%{!mpentium*:-DCPU=I80386 %(cpp_cpu_default)}}}}"
-
-#include "i386/i386-aout.h"
-
-#define HANDLE_SYSV_PRAGMA
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__vxworks"
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (80386, VxWorks BSD syntax)");
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__vxworks"); \
+ builtin_assert ("system=unix"); \
+ \
+ if (TARGET_386) \
+ builtin_define ("CPU=I80386"); \
+ else if (TARGET_486) \
+ builtin_define ("CPU=I80486"); \
+ else if (TARGET_PENTIUM) \
+ { \
+ builtin_define ("CPU=PENTIUM"); \
+ builtin_define ("CPU_VARIANT=PENTIUM"); \
+ } \
+ else if (TARGET_PENTIUMPRO) \
+ { \
+ builtin_define ("CPU=PENTIUM"); \
+ builtin_define ("CPU_VARIANT=PENTIUMPRO"); \
+ } \
+ } \
+ while (0)
+
+#define HANDLE_SYSV_PRAGMA 1
/* VxWorks does all the library stuff itself. */
diff --git a/contrib/gcc/config/i386/win32.h b/contrib/gcc/config/i386/win32.h
index 0aa7a57..93f58c9 100644
--- a/contrib/gcc/config/i386/win32.h
+++ b/contrib/gcc/config/i386/win32.h
@@ -2,7 +2,7 @@
hosting on Windows NT 3.x, using a Unix style C library and tools,
as distinct from winnt.h, which is used to build GCC for use with a
windows style library and tool set and uses the Microsoft tools.
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000
+ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002
Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -22,15 +22,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 YES_UNDERSCORES
-
/* Enable parsing of #pragma pack(push,<n>) and #pragma pack(pop). */
#define HANDLE_PRAGMA_PACK_PUSH_POP 1
-#define DBX_DEBUGGING_INFO
-#define SDB_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
+#define SDB_DEBUGGING_INFO 1
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+#include "i386/unix.h"
+#include "i386/bsd.h"
#include "i386/gas.h"
#include "dbxcoff.h"
@@ -62,11 +62,24 @@ Boston, MA 02111-1307, USA. */
{ "no-nop-fun-dllimport", MASK_NOP_FUN_DLLIMPORT, "" },
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D_WIN32 -DWINNT -D_X86_=1 \
- -D__stdcall=__attribute__((__stdcall__)) \
- -D__cdecl=__attribute__((__cdecl__)) \
- -Asystem=winnt"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("_WIN32"); \
+ builtin_define_std ("WINNT"); \
+ builtin_define ("_X86_"); \
+ builtin_define ("__stdcall=__attribute__((__stdcall__))"); \
+ builtin_define ("__cdecl=__attribute__((__cdecl__))"); \
+ builtin_assert ("system=winnt"); \
+ if (TARGET_CYGWIN) \
+ { \
+ builtin_define ("__CYGWIN32__"); \
+ builtin_define ("__CYGWIN__"); \
+ } \
+ else \
+ builtin_define ("__MINGW32__"); \
+ } \
+ while (0)
#undef STARTFILE_SPEC
@@ -74,9 +87,8 @@ Boston, MA 02111-1307, USA. */
%{mcygwin:crt0%O%s} %{pg:gcrt0%O%s}}"
#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE} \
- %{!mcygwin:-iwithprefixbefore include/mingw32 -D__MINGW32__} \
- %{mcygwin:-D__CYGWIN32__ -D__CYGWIN__}"
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} \
+ %{!mcygwin:-iwithprefixbefore include/mingw32}"
/* We have to dynamic link to get to the system DLLs. All of libc, libm and
the Unix stuff is in cygwin.dll. The import library is called
@@ -95,7 +107,6 @@ Boston, MA 02111-1307, USA. */
#define SIZE_TYPE "unsigned int"
#define PTRDIFF_TYPE "int"
-#define WCHAR_UNSIGNED 1
#define WCHAR_TYPE_SIZE 16
#define WCHAR_TYPE "short unsigned int"
/* Currently we do not have the atexit() function,
@@ -103,63 +114,10 @@ Boston, MA 02111-1307, USA. */
#define NEED_ATEXIT 1
-/* Define this macro if references to a symbol must be treated
- differently depending on something about the variable or
- function named by the symbol (such as what section it is in).
-
- On i386, if using PIC, mark a SYMBOL_REF for a non-global symbol
- so that we may access it directly in the GOT.
-
- On i386 running Windows NT, modify the assembler name with a suffix
- consisting of an atsign (@) followed by string of digits that represents
- the number of bytes of arguments passed to the function, if it has the
- attribute STDCALL. */
-
-#ifdef ENCODE_SECTION_INFO
-#undef ENCODE_SECTION_INFO
-#define ENCODE_SECTION_INFO(DECL) \
-do \
- { \
- if (flag_pic) \
- { \
- rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
- ? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \
- SYMBOL_REF_FLAG (XEXP (rtl, 0)) \
- = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
- || ! TREE_PUBLIC (DECL)); \
- } \
- if (TREE_CODE (DECL) == FUNCTION_DECL) \
- if (lookup_attribute ("stdcall", \
- TYPE_ATTRIBUTES (TREE_TYPE (DECL)))) \
- XEXP (DECL_RTL (DECL), 0) = \
- gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (DECL)); \
- } \
-while (0)
-#endif
-
-/* This macro gets just the user-specified name
- out of the string in a SYMBOL_REF. Discard
- trailing @[NUM] encoded by ENCODE_SECTION_INFO.
- Do we need the stripping of leading '*'? */
-#undef STRIP_NAME_ENCODING
-#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
-do { \
- const char *_p; \
- const char *const _name = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*'));\
- for (_p = _name; *_p && *_p != '@'; ++_p) \
- ; \
- if (*_p == '@') \
- { \
- int _len = _p - _name; \
- char *_new_name = (char *) alloca (_len + 1); \
- strncpy (_new_name, _name, _len); \
- _new_name[_len] = '\0'; \
- (VAR) = _new_name; \
- } \
- else \
- (VAR) = _name; \
-} while (0)
-
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING i386_pe_strip_name_encoding_full
/* Emit code to check the stack when allocating more that 4000
bytes in one go. */
@@ -187,8 +145,8 @@ do { \
symbols must be explicitly imported from shared libraries (DLLs). */
#define MULTIPLE_SYMBOL_SPACES
-extern void i386_pe_unique_section ();
-#define UNIQUE_SECTION(DECL,RELOC) i386_pe_unique_section (DECL, RELOC)
+extern void i386_pe_unique_section PARAMS ((tree, int));
+#define TARGET_ASM_UNIQUE_SECTION i386_pe_unique_section
#define SUPPORTS_ONE_ONLY 1
diff --git a/contrib/gcc/config/i386/winnt.c b/contrib/gcc/config/i386/winnt.c
index 6928a8c..00b3dfd 100644
--- a/contrib/gcc/config/i386/winnt.c
+++ b/contrib/gcc/config/i386/winnt.c
@@ -1,6 +1,7 @@
/* Subroutines for insn-output.c for Windows NT.
Contributed by Douglas Rupp (drupp@cs.washington.edu)
- Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002
+ Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -30,6 +31,7 @@ Boston, MA 02111-1307, USA. */
#include "tm_p.h"
#include "toplev.h"
#include "hashtab.h"
+#include "ggc.h"
/* i386/PE specific attribute support.
@@ -133,7 +135,7 @@ associated_type (decl)
return t;
}
-/* Return non-zero if DECL is a dllexport'd object. */
+/* Return nonzero if DECL is a dllexport'd object. */
int
i386_pe_dllexport_p (decl)
@@ -160,7 +162,7 @@ i386_pe_dllexport_p (decl)
return 0;
}
-/* Return non-zero if DECL is a dllimport'd object. */
+/* Return nonzero if DECL is a dllimport'd object. */
int
i386_pe_dllimport_p (decl)
@@ -191,22 +193,24 @@ i386_pe_dllimport_p (decl)
return 0;
}
-/* Return non-zero if SYMBOL is marked as being dllexport'd. */
+/* Return nonzero if SYMBOL is marked as being dllexport'd. */
int
i386_pe_dllexport_name_p (symbol)
const char *symbol;
{
- return symbol[0] == '@' && symbol[1] == 'e' && symbol[2] == '.';
+ return symbol[0] == DLL_IMPORT_EXPORT_PREFIX
+ && symbol[1] == 'e' && symbol[2] == '.';
}
-/* Return non-zero if SYMBOL is marked as being dllimport'd. */
+/* Return nonzero if SYMBOL is marked as being dllimport'd. */
int
i386_pe_dllimport_name_p (symbol)
const char *symbol;
{
- return symbol[0] == '@' && symbol[1] == 'i' && symbol[2] == '.';
+ return symbol[0] == DLL_IMPORT_EXPORT_PREFIX
+ && symbol[1] == 'i' && symbol[2] == '.';
}
/* Mark a DECL as being dllexport'd.
@@ -235,7 +239,7 @@ i386_pe_mark_dllexport (decl)
return; /* already done */
newname = alloca (strlen (oldname) + 4);
- sprintf (newname, "@e.%s", oldname);
+ sprintf (newname, "%ce.%s", DLL_IMPORT_EXPORT_PREFIX, oldname);
/* We pass newname through get_identifier to ensure it has a unique
address. RTL processing can sometimes peek inside the symbol ref
@@ -310,7 +314,7 @@ i386_pe_mark_dllimport (decl)
}
newname = alloca (strlen (oldname) + 11);
- sprintf (newname, "@i._imp__%s", oldname);
+ sprintf (newname, "%ci._imp__%s", DLL_IMPORT_EXPORT_PREFIX, oldname);
/* We pass newname through get_identifier to ensure it has a unique
address. RTL processing can sometimes peek inside the symbol ref
@@ -365,12 +369,14 @@ gen_stdcall_suffix (decl)
return IDENTIFIER_POINTER (get_identifier (newsym));
}
-/* Cover function to implement ENCODE_SECTION_INFO. */
-
void
-i386_pe_encode_section_info (decl)
+i386_pe_encode_section_info (decl, first)
tree decl;
+ int first;
{
+ if (!first)
+ return;
+
/* This bit is copied from i386.h. */
if (optimize > 0 && TREE_CONSTANT (decl)
&& (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
@@ -395,8 +401,8 @@ i386_pe_encode_section_info (decl)
i386_pe_mark_dllimport (decl);
/* It might be that DECL has already been marked as dllimport, but a
subsequent definition nullified that. The attribute is gone but
- DECL_RTL still has @i._imp__foo. We need to remove that. Ditto
- for the DECL_NON_ADDR_CONST_P flag. */
+ DECL_RTL still has (DLL_IMPORT_EXPORT_PREFIX)i._imp__foo. We need
+ to remove that. Ditto for the DECL_NON_ADDR_CONST_P flag. */
else if ((TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == VAR_DECL)
&& DECL_RTL (decl) != NULL_RTX
@@ -418,7 +424,34 @@ i386_pe_encode_section_info (decl)
}
}
-/* Cover function for UNIQUE_SECTION. */
+/* Strip only the leading encoding, leaving the stdcall suffix. */
+
+const char *
+i386_pe_strip_name_encoding (str)
+ const char *str;
+{
+ if (*str == DLL_IMPORT_EXPORT_PREFIX)
+ str += 3;
+ if (*str == '*')
+ str += 1;
+ return str;
+}
+
+/* Also strip the stdcall suffix. */
+
+const char *
+i386_pe_strip_name_encoding_full (str)
+ const char *str;
+{
+ const char *p;
+ const char *name = i386_pe_strip_name_encoding (str);
+
+ p = strchr (name, '@');
+ if (p)
+ return ggc_alloc_string (name, p - name);
+
+ return name;
+}
void
i386_pe_unique_section (decl, reloc)
@@ -430,8 +463,7 @@ i386_pe_unique_section (decl, reloc)
char *string;
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- /* Strip off any encoding in fnname. */
- STRIP_NAME_ENCODING (name, name);
+ name = i386_pe_strip_name_encoding_full (name);
/* The object is put in, for example, section .text$foo.
The linker will then ultimately place them in .text
@@ -441,15 +473,8 @@ i386_pe_unique_section (decl, reloc)
without a .rdata section. */
if (TREE_CODE (decl) == FUNCTION_DECL)
prefix = ".text$";
-/* else if (DECL_INITIAL (decl) == 0
- || DECL_INITIAL (decl) == error_mark_node)
- prefix = ".bss"; */
- else if (DECL_READONLY_SECTION (decl, reloc))
-#ifdef READONLY_DATA_SECTION
+ else if (decl_readonly_section (decl, reloc))
prefix = ".rdata$";
-#else
- prefix = ".text$";
-#endif
else
prefix = ".data$";
len = strlen (name) + strlen (prefix);
@@ -494,7 +519,7 @@ i386_pe_section_type_flags (decl, name, reloc)
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
flags = SECTION_CODE;
- else if (decl && DECL_READONLY_SECTION (decl, reloc))
+ else if (decl && decl_readonly_section (decl, reloc))
flags = 0;
else
{
@@ -560,7 +585,7 @@ i386_pe_asm_named_section (name, flags)
/* Mark a function appropriately. This should only be called for
functions for which we are not emitting COFF debugging information.
FILE is the assembler output file, NAME is the name of the
- function, and PUBLIC is non-zero if the function is globally
+ function, and PUBLIC is nonzero if the function is globally
visible. */
void
@@ -598,7 +623,7 @@ i386_pe_record_external_function (name)
{
struct extern_list *p;
- p = (struct extern_list *) permalloc (sizeof *p);
+ p = (struct extern_list *) xmalloc (sizeof *p);
p->next = extern_head;
p->name = name;
extern_head = p;
@@ -628,7 +653,7 @@ i386_pe_record_exported_symbol (name, is_data)
{
struct export_list *p;
- p = (struct export_list *) permalloc (sizeof *p);
+ p = (struct export_list *) xmalloc (sizeof *p);
p->next = export_head;
p->name = name;
p->is_data = is_data;
@@ -668,7 +693,7 @@ i386_pe_asm_file_end (file)
for (q = export_head; q != NULL; q = q->next)
{
fprintf (file, "\t.ascii \" -export:%s%s\"\n",
- I386_PE_STRIP_ENCODING (q->name),
+ i386_pe_strip_name_encoding (q->name),
(q->is_data) ? ",data" : "");
}
}
diff --git a/contrib/gcc/config/i386/x86-64.h b/contrib/gcc/config/i386/x86-64.h
index 56e4684..37a2a30 100644
--- a/contrib/gcc/config/i386/x86-64.h
+++ b/contrib/gcc/config/i386/x86-64.h
@@ -29,16 +29,8 @@ Boston, MA 02111-1307, USA. */
/* Output assembler code to FILE to call the profiler. */
#define NO_PROFILE_COUNTERS
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(FILE, LABELNO) \
-{ \
- if (TARGET_64BIT && flag_pic) \
- fprintf (FILE, "\tcall\t*mcount@PLT\n"); \
- else if (flag_pic) \
- fprintf (FILE, "\tcall\t*mcount@GOT(%%ebx)\n"); \
- else \
- fprintf (FILE, "\tcall\tmcount\n"); \
-}
+#undef MCOUNT_NAME
+#define MCOUNT_NAME "mcount"
#undef SIZE_TYPE
#define SIZE_TYPE (TARGET_64BIT ? "long unsigned int" : "unsigned int")
@@ -85,9 +77,8 @@ Boston, MA 02111-1307, USA. */
/* i386 System V Release 4 uses DWARF debugging info.
x86-64 ABI specifies DWARF2. */
-#undef DWARF2_DEBUGGING_INFO
#undef DWARF_DEBUGGING_INFO
-#define DWARF2_DEBUGGING_INFO
+#define DWARF2_DEBUGGING_INFO 1
#define DWARF2_UNWIND_INFO 1
/* Incorrectly autodetected in cross compilation. */
#undef HAVE_AS_DWARF2_DEBUG_LINE
diff --git a/contrib/gcc/config/i386/xm-vsta.h b/contrib/gcc/config/i386/xm-vsta.h
index 735d1d5..53943ea 100644
--- a/contrib/gcc/config/i386/xm-vsta.h
+++ b/contrib/gcc/config/i386/xm-vsta.h
@@ -1,2 +1,11 @@
/* Use semicolons to separate elements of a path. */
#define PATH_SEPARATOR ';'
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("unix"); \
+ } \
+ while (0)
+
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE}"
diff --git a/contrib/gcc/config/i386/xmmintrin.h b/contrib/gcc/config/i386/xmmintrin.h
index 409bf17..43a05c1 100644
--- a/contrib/gcc/config/i386/xmmintrin.h
+++ b/contrib/gcc/config/i386/xmmintrin.h
@@ -30,6 +30,10 @@
#ifndef _XMMINTRIN_H_INCLUDED
#define _XMMINTRIN_H_INCLUDED
+#ifndef __SSE__
+# error "SSE instruction set not enabled"
+#else
+
/* We need type definitions from the MMX header file. */
#include <mmintrin.h>
@@ -471,6 +475,16 @@ _mm_cvtss_si32 (__m128 __A)
return __builtin_ia32_cvtss2si ((__v4sf) __A);
}
+#ifdef __x86_64__
+/* Convert the lower SPFP value to a 32-bit integer according to the current
+ rounding mode. */
+static __inline long long
+_mm_cvtss_si64x (__m128 __A)
+{
+ return __builtin_ia32_cvtss2si64 ((__v4sf) __A);
+}
+#endif
+
/* Convert the two lower SPFP values to 32-bit integers according to the
current rounding mode. Return the integers in packed form. */
static __inline __m64
@@ -486,6 +500,15 @@ _mm_cvttss_si32 (__m128 __A)
return __builtin_ia32_cvttss2si ((__v4sf) __A);
}
+#ifdef __x86_64__
+/* Truncate the lower SPFP value to a 32-bit integer. */
+static __inline long long
+_mm_cvttss_si64x (__m128 __A)
+{
+ return __builtin_ia32_cvttss2si64 ((__v4sf) __A);
+}
+#endif
+
/* Truncate the two lower SPFP values to 32-bit integers. Return the
integers in packed form. */
static __inline __m64
@@ -501,6 +524,15 @@ _mm_cvtsi32_ss (__m128 __A, int __B)
return (__m128) __builtin_ia32_cvtsi2ss ((__v4sf) __A, __B);
}
+#ifdef __x86_64__
+/* Convert B to a SPFP value and insert it as element zero in A. */
+static __inline __m128
+_mm_cvtsi64x_ss (__m128 __A, long long __B)
+{
+ return (__m128) __builtin_ia32_cvtsi642ss ((__v4sf) __A, __B);
+}
+#endif
+
/* Convert the two 32-bit values in B to SPFP form and insert them
as the two lower elements in A. */
static __inline __m128
@@ -602,7 +634,7 @@ _mm_cvtps_pi16(__m128 __A)
__v4sf __losf = __builtin_ia32_movhlps (__hisf, __hisf);
__v2si __hisi = __builtin_ia32_cvtps2pi (__hisf);
__v2si __losi = __builtin_ia32_cvtps2pi (__losf);
- return (__m64) __builtin_ia32_packssdw (__losi, __hisi);
+ return (__m64) __builtin_ia32_packssdw (__hisi, __losi);
}
/* Convert the four SPFP values in A to four signed 8-bit integers. */
@@ -644,7 +676,7 @@ _mm_unpacklo_ps (__m128 __A, __m128 __B)
/* Sets the upper two SPFP values with 64-bits of data loaded from P;
the lower two values are passed through from A. */
static __inline __m128
-_mm_loadh_pi (__m128 __A, __m64 *__P)
+_mm_loadh_pi (__m128 __A, __m64 const *__P)
{
return (__m128) __builtin_ia32_loadhps ((__v4sf)__A, (__v2si *)__P);
}
@@ -673,7 +705,7 @@ _mm_movelh_ps (__m128 __A, __m128 __B)
/* Sets the lower two SPFP values with 64-bits of data loaded from P;
the upper two values are passed through from A. */
static __inline __m128
-_mm_loadl_pi (__m128 __A, __m64 *__P)
+_mm_loadl_pi (__m128 __A, __m64 const *__P)
{
return (__m128) __builtin_ia32_loadlps ((__v4sf)__A, (__v2si *)__P);
}
@@ -758,42 +790,42 @@ _MM_SET_FLUSH_ZERO_MODE (unsigned int __mode)
/* Create a vector with element 0 as *P and the rest zero. */
static __inline __m128
-_mm_load_ss (float *__P)
+_mm_load_ss (float const *__P)
{
return (__m128) __builtin_ia32_loadss (__P);
}
/* Create a vector with all four elements equal to *P. */
static __inline __m128
-_mm_load1_ps (float *__P)
+_mm_load1_ps (float const *__P)
{
__v4sf __tmp = __builtin_ia32_loadss (__P);
return (__m128) __builtin_ia32_shufps (__tmp, __tmp, _MM_SHUFFLE (0,0,0,0));
}
static __inline __m128
-_mm_load_ps1 (float *__P)
+_mm_load_ps1 (float const *__P)
{
return _mm_load1_ps (__P);
}
/* Load four SPFP values from P. The address must be 16-byte aligned. */
static __inline __m128
-_mm_load_ps (float *__P)
+_mm_load_ps (float const *__P)
{
return (__m128) __builtin_ia32_loadaps (__P);
}
/* Load four SPFP values from P. The address need not be 16-byte aligned. */
static __inline __m128
-_mm_loadu_ps (float *__P)
+_mm_loadu_ps (float const *__P)
{
return (__m128) __builtin_ia32_loadups (__P);
}
/* Load four SPFP values in reverse order. The address must be aligned. */
static __inline __m128
-_mm_loadr_ps (float *__P)
+_mm_loadr_ps (float const *__P)
{
__v4sf __tmp = __builtin_ia32_loadaps (__P);
return (__m128) __builtin_ia32_shufps (__tmp, __tmp, _MM_SHUFFLE (0,1,2,3));
@@ -887,7 +919,7 @@ _mm_storeu_ps (float *__P, __m128 __A)
__builtin_ia32_storeups (__P, (__v4sf)__A);
}
-/* Store four SPFP values in reverse order. The addres must be aligned. */
+/* Store four SPFP values in reverse order. The address must be aligned. */
static __inline void
_mm_storer_ps (float *__P, __m128 __A)
{
@@ -1033,7 +1065,7 @@ _mm_prefetch (void *__P, enum _mm_hint __I)
static __inline void
_mm_stream_pi (__m64 *__P, __m64 __A)
{
- __builtin_ia32_movntq (__P, (long long)__A);
+ __builtin_ia32_movntq ((unsigned long long *)__P, (unsigned long long)__A);
}
/* Likewise. The address must be 16-byte aligned. */
@@ -1074,4 +1106,1469 @@ do { \
(row3) = __builtin_ia32_shufps (__t2, __t3, 0xDD); \
} while (0)
+#ifdef __SSE2__
+/* SSE2 */
+typedef int __v2df __attribute__ ((mode (V2DF)));
+typedef int __v2di __attribute__ ((mode (V2DI)));
+typedef int __v4si __attribute__ ((mode (V4SI)));
+typedef int __v8hi __attribute__ ((mode (V8HI)));
+typedef int __v16qi __attribute__ ((mode (V16QI)));
+
+/* Create a selector for use with the SHUFPD instruction. */
+#define _MM_SHUFFLE2(fp1,fp0) \
+ (((fp1) << 1) | (fp0))
+
+#define __m128i __v2di
+#define __m128d __v2df
+
+/* Create a vector with element 0 as *P and the rest zero. */
+static __inline __m128d
+_mm_load_sd (double const *__P)
+{
+ return (__m128d) __builtin_ia32_loadsd (__P);
+}
+
+/* Create a vector with all two elements equal to *P. */
+static __inline __m128d
+_mm_load1_pd (double const *__P)
+{
+ __v2df __tmp = __builtin_ia32_loadsd (__P);
+ return (__m128d) __builtin_ia32_shufpd (__tmp, __tmp, _MM_SHUFFLE2 (0,0));
+}
+
+static __inline __m128d
+_mm_load_pd1 (double const *__P)
+{
+ return _mm_load1_pd (__P);
+}
+
+/* Load two DPFP values from P. The addresd must be 16-byte aligned. */
+static __inline __m128d
+_mm_load_pd (double const *__P)
+{
+ return (__m128d) __builtin_ia32_loadapd (__P);
+}
+
+/* Load two DPFP values from P. The addresd need not be 16-byte aligned. */
+static __inline __m128d
+_mm_loadu_pd (double const *__P)
+{
+ return (__m128d) __builtin_ia32_loadupd (__P);
+}
+
+/* Load two DPFP values in reverse order. The addresd must be aligned. */
+static __inline __m128d
+_mm_loadr_pd (double const *__P)
+{
+ __v2df __tmp = __builtin_ia32_loadapd (__P);
+ return (__m128d) __builtin_ia32_shufpd (__tmp, __tmp, _MM_SHUFFLE2 (0,1));
+}
+
+/* Create a vector with element 0 as F and the rest zero. */
+static __inline __m128d
+_mm_set_sd (double __F)
+{
+ return (__m128d) __builtin_ia32_loadsd (&__F);
+}
+
+/* Create a vector with all two elements equal to F. */
+static __inline __m128d
+_mm_set1_pd (double __F)
+{
+ __v2df __tmp = __builtin_ia32_loadsd (&__F);
+ return (__m128d) __builtin_ia32_shufpd (__tmp, __tmp, _MM_SHUFFLE2 (0,0));
+}
+
+static __inline __m128d
+_mm_set_pd1 (double __F)
+{
+ return _mm_set1_pd (__F);
+}
+
+/* Create the vector [Z Y]. */
+static __inline __m128d
+_mm_set_pd (double __Z, double __Y)
+{
+ union {
+ double __a[2];
+ __m128d __v;
+ } __u;
+
+ __u.__a[0] = __Y;
+ __u.__a[1] = __Z;
+
+ return __u.__v;
+}
+
+/* Create the vector [Y Z]. */
+static __inline __m128d
+_mm_setr_pd (double __Z, double __Y)
+{
+ return _mm_set_pd (__Y, __Z);
+}
+
+/* Create a vector of zeros. */
+static __inline __m128d
+_mm_setzero_pd (void)
+{
+ return (__m128d) __builtin_ia32_setzeropd ();
+}
+
+/* Stores the lower DPFP value. */
+static __inline void
+_mm_store_sd (double *__P, __m128d __A)
+{
+ __builtin_ia32_storesd (__P, (__v2df)__A);
+}
+
+/* Store the lower DPFP value acrosd two words. */
+static __inline void
+_mm_store1_pd (double *__P, __m128d __A)
+{
+ __v2df __va = (__v2df)__A;
+ __v2df __tmp = __builtin_ia32_shufpd (__va, __va, _MM_SHUFFLE2 (0,0));
+ __builtin_ia32_storeapd (__P, __tmp);
+}
+
+static __inline void
+_mm_store_pd1 (double *__P, __m128d __A)
+{
+ _mm_store1_pd (__P, __A);
+}
+
+/* Store two DPFP values. The addresd must be 16-byte aligned. */
+static __inline void
+_mm_store_pd (double *__P, __m128d __A)
+{
+ __builtin_ia32_storeapd (__P, (__v2df)__A);
+}
+
+/* Store two DPFP values. The addresd need not be 16-byte aligned. */
+static __inline void
+_mm_storeu_pd (double *__P, __m128d __A)
+{
+ __builtin_ia32_storeupd (__P, (__v2df)__A);
+}
+
+/* Store two DPFP values in reverse order. The addresd must be aligned. */
+static __inline void
+_mm_storer_pd (double *__P, __m128d __A)
+{
+ __v2df __va = (__v2df)__A;
+ __v2df __tmp = __builtin_ia32_shufpd (__va, __va, _MM_SHUFFLE2 (0,1));
+ __builtin_ia32_storeapd (__P, __tmp);
+}
+
+/* Sets the low DPFP value of A from the low value of B. */
+static __inline __m128d
+_mm_move_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d) __builtin_ia32_movsd ((__v2df)__A, (__v2df)__B);
+}
+
+
+static __inline __m128d
+_mm_add_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_addpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_add_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_addsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_sub_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_subpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_sub_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_subsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_mul_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_mulpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_mul_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_mulsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_div_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_divpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_div_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_divsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_sqrt_pd (__m128d __A)
+{
+ return (__m128d)__builtin_ia32_sqrtpd ((__v2df)__A);
+}
+
+/* Return pair {sqrt (A[0), B[1]}. */
+static __inline __m128d
+_mm_sqrt_sd (__m128d __A, __m128d __B)
+{
+ __v2df __tmp = __builtin_ia32_movsd ((__v2df)__A, (__v2df)__B);
+ return (__m128d)__builtin_ia32_sqrtsd ((__v2df)__tmp);
+}
+
+static __inline __m128d
+_mm_min_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_minpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_min_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_minsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_max_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_maxpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_max_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_maxsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_and_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_andpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_andnot_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_andnpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_or_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_orpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_xor_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_xorpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpeq_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpeqpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmplt_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpltpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmple_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmplepd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpgt_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpgtpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpge_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpgepd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpneq_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpneqpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpnlt_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpnltpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpnle_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpnlepd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpngt_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpngtpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpnge_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpngepd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpord_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpordpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpunord_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpunordpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpeq_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpeqsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmplt_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpltsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmple_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmplesd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpgt_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d) __builtin_ia32_movsd ((__v2df) __A,
+ (__v2df)
+ __builtin_ia32_cmpltsd ((__v2df) __B,
+ (__v2df)
+ __A));
+}
+
+static __inline __m128d
+_mm_cmpge_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d) __builtin_ia32_movsd ((__v2df) __A,
+ (__v2df)
+ __builtin_ia32_cmplesd ((__v2df) __B,
+ (__v2df)
+ __A));
+}
+
+static __inline __m128d
+_mm_cmpneq_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpneqsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpnlt_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpnltsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpnle_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpnlesd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpngt_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d) __builtin_ia32_movsd ((__v2df) __A,
+ (__v2df)
+ __builtin_ia32_cmpnltsd ((__v2df) __B,
+ (__v2df)
+ __A));
+}
+
+static __inline __m128d
+_mm_cmpnge_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d) __builtin_ia32_movsd ((__v2df) __A,
+ (__v2df)
+ __builtin_ia32_cmpnlesd ((__v2df) __B,
+ (__v2df)
+ __A));
+}
+
+static __inline __m128d
+_mm_cmpord_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpordsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_cmpunord_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_cmpunordsd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline int
+_mm_comieq_sd (__m128d __A, __m128d __B)
+{
+ return __builtin_ia32_comisdeq ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline int
+_mm_comilt_sd (__m128d __A, __m128d __B)
+{
+ return __builtin_ia32_comisdlt ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline int
+_mm_comile_sd (__m128d __A, __m128d __B)
+{
+ return __builtin_ia32_comisdle ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline int
+_mm_comigt_sd (__m128d __A, __m128d __B)
+{
+ return __builtin_ia32_comisdgt ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline int
+_mm_comige_sd (__m128d __A, __m128d __B)
+{
+ return __builtin_ia32_comisdge ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline int
+_mm_comineq_sd (__m128d __A, __m128d __B)
+{
+ return __builtin_ia32_comisdneq ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline int
+_mm_ucomieq_sd (__m128d __A, __m128d __B)
+{
+ return __builtin_ia32_ucomisdeq ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline int
+_mm_ucomilt_sd (__m128d __A, __m128d __B)
+{
+ return __builtin_ia32_ucomisdlt ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline int
+_mm_ucomile_sd (__m128d __A, __m128d __B)
+{
+ return __builtin_ia32_ucomisdle ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline int
+_mm_ucomigt_sd (__m128d __A, __m128d __B)
+{
+ return __builtin_ia32_ucomisdgt ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline int
+_mm_ucomige_sd (__m128d __A, __m128d __B)
+{
+ return __builtin_ia32_ucomisdge ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline int
+_mm_ucomineq_sd (__m128d __A, __m128d __B)
+{
+ return __builtin_ia32_ucomisdneq ((__v2df)__A, (__v2df)__B);
+}
+
+/* Create a vector with element 0 as *P and the rest zero. */
+
+static __inline __m128i
+_mm_load_si128 (__m128i const *__P)
+{
+ return (__m128i) __builtin_ia32_loaddqa ((char const *)__P);
+}
+
+static __inline __m128i
+_mm_loadu_si128 (__m128i const *__P)
+{
+ return (__m128i) __builtin_ia32_loaddqu ((char const *)__P);
+}
+
+static __inline __m128i
+_mm_loadl_epi64 (__m128i const *__P)
+{
+ return (__m128i) __builtin_ia32_movq2dq (*(unsigned long long *)__P);
+}
+
+static __inline void
+_mm_store_si128 (__m128i *__P, __m128i __B)
+{
+ __builtin_ia32_storedqa ((char *)__P, (__v16qi)__B);
+}
+
+static __inline void
+_mm_storeu_si128 (__m128i *__P, __m128i __B)
+{
+ __builtin_ia32_storedqu ((char *)__P, (__v16qi)__B);
+}
+
+static __inline void
+_mm_storel_epi64 (__m128i *__P, __m128i __B)
+{
+ *(long long *)__P = __builtin_ia32_movdq2q ((__v2di)__B);
+}
+
+static __inline __m64
+_mm_movepi64_pi64 (__m128i __B)
+{
+ return (__m64) __builtin_ia32_movdq2q ((__v2di)__B);
+}
+
+static __inline __m128i
+_mm_move_epi64 (__m128i __A)
+{
+ return (__m128i) __builtin_ia32_movq ((__v2di)__A);
+}
+
+/* Create a vector of zeros. */
+static __inline __m128i
+_mm_setzero_si128 (void)
+{
+ return (__m128i) __builtin_ia32_setzero128 ();
+}
+
+static __inline __m128i
+_mm_set_epi64 (__m64 __A, __m64 __B)
+{
+ __v2di __tmp = (__v2di)__builtin_ia32_movq2dq ((unsigned long long)__A);
+ __v2di __tmp2 = (__v2di)__builtin_ia32_movq2dq ((unsigned long long)__B);
+ return (__m128i)__builtin_ia32_punpcklqdq128 (__tmp2, __tmp);
+}
+
+/* Create the vector [Z Y X W]. */
+static __inline __m128i
+_mm_set_epi32 (int __Z, int __Y, int __X, int __W)
+{
+ union {
+ int __a[4];
+ __m128i __v;
+ } __u;
+
+ __u.__a[0] = __W;
+ __u.__a[1] = __X;
+ __u.__a[2] = __Y;
+ __u.__a[3] = __Z;
+
+ return __u.__v;
+}
+
+#ifdef __x86_64__
+/* Create the vector [Z Y]. */
+static __inline __m128i
+_mm_set_epi64x (long long __Z, long long __Y)
+{
+ union {
+ long __a[2];
+ __m128i __v;
+ } __u;
+
+ __u.__a[0] = __Y;
+ __u.__a[1] = __Z;
+
+ return __u.__v;
+}
+#endif
+
+/* Create the vector [S T U V Z Y X W]. */
+static __inline __m128i
+_mm_set_epi16 (short __Z, short __Y, short __X, short __W,
+ short __V, short __U, short __T, short __S)
+{
+ union {
+ short __a[8];
+ __m128i __v;
+ } __u;
+
+ __u.__a[0] = __S;
+ __u.__a[1] = __T;
+ __u.__a[2] = __U;
+ __u.__a[3] = __V;
+ __u.__a[4] = __W;
+ __u.__a[5] = __X;
+ __u.__a[6] = __Y;
+ __u.__a[7] = __Z;
+
+ return __u.__v;
+}
+
+/* Create the vector [S T U V Z Y X W]. */
+static __inline __m128i
+_mm_set_epi8 (char __Z, char __Y, char __X, char __W,
+ char __V, char __U, char __T, char __S,
+ char __Z1, char __Y1, char __X1, char __W1,
+ char __V1, char __U1, char __T1, char __S1)
+{
+ union {
+ char __a[16];
+ __m128i __v;
+ } __u;
+
+ __u.__a[0] = __S1;
+ __u.__a[1] = __T1;
+ __u.__a[2] = __U1;
+ __u.__a[3] = __V1;
+ __u.__a[4] = __W1;
+ __u.__a[5] = __X1;
+ __u.__a[6] = __Y1;
+ __u.__a[7] = __Z1;
+ __u.__a[8] = __S;
+ __u.__a[9] = __T;
+ __u.__a[10] = __U;
+ __u.__a[11] = __V;
+ __u.__a[12] = __W;
+ __u.__a[13] = __X;
+ __u.__a[14] = __Y;
+ __u.__a[15] = __Z;
+
+ return __u.__v;
+}
+
+static __inline __m128i
+_mm_set1_epi64 (__m64 __A)
+{
+ __v2di __tmp = (__v2di)__builtin_ia32_movq2dq ((unsigned long long)__A);
+ return (__m128i)__builtin_ia32_punpcklqdq128 (__tmp, __tmp);
+}
+
+static __inline __m128i
+_mm_set1_epi32 (int __A)
+{
+ __v4si __tmp = (__v4si)__builtin_ia32_loadd (&__A);
+ return (__m128i) __builtin_ia32_pshufd ((__v4si)__tmp, _MM_SHUFFLE (0,0,0,0));
+}
+
+#ifdef __x86_64__
+static __inline __m128i
+_mm_set1_epi64x (long long __A)
+{
+ __v2di __tmp = (__v2di)__builtin_ia32_movq2dq ((unsigned long long)__A);
+ return (__m128i) __builtin_ia32_shufpd ((__v2df)__tmp, (__v2df)__tmp, _MM_SHUFFLE2 (0,0));
+}
+#endif
+
+static __inline __m128i
+_mm_set1_epi16 (short __A)
+{
+ int __Acopy = (unsigned short)__A;
+ __v4si __tmp = (__v4si)__builtin_ia32_loadd (&__Acopy);
+ __tmp = (__v4si)__builtin_ia32_punpcklwd128 ((__v8hi)__tmp, (__v8hi)__tmp);
+ return (__m128i) __builtin_ia32_pshufd ((__v4si)__tmp, _MM_SHUFFLE (0,0,0,0));
+}
+
+static __inline __m128i
+_mm_set1_epi8 (char __A)
+{
+ int __Acopy = (unsigned char)__A;
+ __v4si __tmp = (__v4si)__builtin_ia32_loadd (&__Acopy);
+ __tmp = (__v4si)__builtin_ia32_punpcklbw128 ((__v16qi)__tmp, (__v16qi)__tmp);
+ __tmp = (__v4si)__builtin_ia32_punpcklbw128 ((__v16qi)__tmp, (__v16qi)__tmp);
+ return (__m128i) __builtin_ia32_pshufd ((__v4si)__tmp, _MM_SHUFFLE (0,0,0,0));
+}
+
+static __inline __m128i
+_mm_setr_epi64 (__m64 __A, __m64 __B)
+{
+ __v2di __tmp = (__v2di)__builtin_ia32_movq2dq ((unsigned long long)__A);
+ __v2di __tmp2 = (__v2di)__builtin_ia32_movq2dq ((unsigned long long)__B);
+ return (__m128i)__builtin_ia32_punpcklqdq128 (__tmp, __tmp2);
+}
+
+/* Create the vector [Z Y X W]. */
+static __inline __m128i
+_mm_setr_epi32 (int __W, int __X, int __Y, int __Z)
+{
+ union {
+ int __a[4];
+ __m128i __v;
+ } __u;
+
+ __u.__a[0] = __W;
+ __u.__a[1] = __X;
+ __u.__a[2] = __Y;
+ __u.__a[3] = __Z;
+
+ return __u.__v;
+}
+/* Create the vector [S T U V Z Y X W]. */
+static __inline __m128i
+_mm_setr_epi16 (short __S, short __T, short __U, short __V,
+ short __W, short __X, short __Y, short __Z)
+{
+ union {
+ short __a[8];
+ __m128i __v;
+ } __u;
+
+ __u.__a[0] = __S;
+ __u.__a[1] = __T;
+ __u.__a[2] = __U;
+ __u.__a[3] = __V;
+ __u.__a[4] = __W;
+ __u.__a[5] = __X;
+ __u.__a[6] = __Y;
+ __u.__a[7] = __Z;
+
+ return __u.__v;
+}
+
+/* Create the vector [S T U V Z Y X W]. */
+static __inline __m128i
+_mm_setr_epi8 (char __S1, char __T1, char __U1, char __V1,
+ char __W1, char __X1, char __Y1, char __Z1,
+ char __S, char __T, char __U, char __V,
+ char __W, char __X, char __Y, char __Z)
+{
+ union {
+ char __a[16];
+ __m128i __v;
+ } __u;
+
+ __u.__a[0] = __S1;
+ __u.__a[1] = __T1;
+ __u.__a[2] = __U1;
+ __u.__a[3] = __V1;
+ __u.__a[4] = __W1;
+ __u.__a[5] = __X1;
+ __u.__a[6] = __Y1;
+ __u.__a[7] = __Z1;
+ __u.__a[8] = __S;
+ __u.__a[9] = __T;
+ __u.__a[10] = __U;
+ __u.__a[11] = __V;
+ __u.__a[12] = __W;
+ __u.__a[13] = __X;
+ __u.__a[14] = __Y;
+ __u.__a[15] = __Z;
+
+ return __u.__v;
+}
+
+static __inline __m128d
+_mm_cvtepi32_pd (__m128i __A)
+{
+ return (__m128d)__builtin_ia32_cvtdq2pd ((__v4si) __A);
+}
+
+static __inline __m128
+_mm_cvtepi32_ps (__m128i __A)
+{
+ return (__m128)__builtin_ia32_cvtdq2ps ((__v4si) __A);
+}
+
+static __inline __m128i
+_mm_cvtpd_epi32 (__m128d __A)
+{
+ return (__m128i)__builtin_ia32_cvtpd2dq ((__v2df) __A);
+}
+
+static __inline __m64
+_mm_cvtpd_pi32 (__m128d __A)
+{
+ return (__m64)__builtin_ia32_cvtpd2pi ((__v2df) __A);
+}
+
+static __inline __m128
+_mm_cvtpd_ps (__m128d __A)
+{
+ return (__m128)__builtin_ia32_cvtpd2ps ((__v2df) __A);
+}
+
+static __inline __m128i
+_mm_cvttpd_epi32 (__m128d __A)
+{
+ return (__m128i)__builtin_ia32_cvttpd2dq ((__v2df) __A);
+}
+
+static __inline __m64
+_mm_cvttpd_pi32 (__m128d __A)
+{
+ return (__m64)__builtin_ia32_cvttpd2pi ((__v2df) __A);
+}
+
+static __inline __m128d
+_mm_cvtpi32_pd (__m64 __A)
+{
+ return (__m128d)__builtin_ia32_cvtpi2pd ((__v2si) __A);
+}
+
+static __inline __m128i
+_mm_cvtps_epi32 (__m128 __A)
+{
+ return (__m128i)__builtin_ia32_cvtps2dq ((__v4sf) __A);
+}
+
+static __inline __m128i
+_mm_cvttps_epi32 (__m128 __A)
+{
+ return (__m128i)__builtin_ia32_cvttps2dq ((__v4sf) __A);
+}
+
+static __inline __m128d
+_mm_cvtps_pd (__m128 __A)
+{
+ return (__m128d)__builtin_ia32_cvtps2pd ((__v4sf) __A);
+}
+
+static __inline int
+_mm_cvtsd_si32 (__m128d __A)
+{
+ return __builtin_ia32_cvtsd2si ((__v2df) __A);
+}
+
+#ifdef __x86_64__
+static __inline long long
+_mm_cvtsd_si64x (__m128d __A)
+{
+ return __builtin_ia32_cvtsd2si64 ((__v2df) __A);
+}
+#endif
+
+static __inline int
+_mm_cvttsd_si32 (__m128d __A)
+{
+ return __builtin_ia32_cvttsd2si ((__v2df) __A);
+}
+
+#ifdef __x86_64__
+static __inline long long
+_mm_cvttsd_si64x (__m128d __A)
+{
+ return __builtin_ia32_cvttsd2si64 ((__v2df) __A);
+}
+#endif
+
+static __inline __m128
+_mm_cvtsd_ss (__m128 __A, __m128d __B)
+{
+ return (__m128)__builtin_ia32_cvtsd2ss ((__v4sf) __A, (__v2df) __B);
+}
+
+static __inline __m128d
+_mm_cvtsi32_sd (__m128d __A, int __B)
+{
+ return (__m128d)__builtin_ia32_cvtsi2sd ((__v2df) __A, __B);
+}
+
+#ifdef __x86_64__
+static __inline __m128d
+_mm_cvtsi64x_sd (__m128d __A, long long __B)
+{
+ return (__m128d)__builtin_ia32_cvtsi642sd ((__v2df) __A, __B);
+}
+#endif
+
+static __inline __m128d
+_mm_cvtss_sd (__m128d __A, __m128 __B)
+{
+ return (__m128d)__builtin_ia32_cvtss2sd ((__v2df) __A, (__v4sf)__B);
+}
+
+#define _mm_shuffle_pd(__A, __B, __C) ((__m128d)__builtin_ia32_shufpd ((__v2df)__A, (__v2df)__B, (__C)))
+
+static __inline __m128d
+_mm_unpackhi_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_unpckhpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_unpacklo_pd (__m128d __A, __m128d __B)
+{
+ return (__m128d)__builtin_ia32_unpcklpd ((__v2df)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_loadh_pd (__m128d __A, double const *__B)
+{
+ return (__m128d)__builtin_ia32_loadhpd ((__v2df)__A, (__v2si *)__B);
+}
+
+static __inline void
+_mm_storeh_pd (double *__A, __m128d __B)
+{
+ __builtin_ia32_storehpd ((__v2si *)__A, (__v2df)__B);
+}
+
+static __inline __m128d
+_mm_loadl_pd (__m128d __A, double const *__B)
+{
+ return (__m128d)__builtin_ia32_loadlpd ((__v2df)__A, (__v2si *)__B);
+}
+
+static __inline void
+_mm_storel_pd (double *__A, __m128d __B)
+{
+ __builtin_ia32_storelpd ((__v2si *)__A, (__v2df)__B);
+}
+
+static __inline int
+_mm_movemask_pd (__m128d __A)
+{
+ return __builtin_ia32_movmskpd ((__v2df)__A);
+}
+
+static __inline __m128i
+_mm_packs_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_packsswb128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_packs_epi32 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_packssdw128 ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i
+_mm_packus_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_packuswb128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_unpackhi_epi8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_punpckhbw128 ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i
+_mm_unpackhi_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_punpckhwd128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_unpackhi_epi32 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_punpckhdq128 ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i
+_mm_unpackhi_epi64 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_punpckhqdq128 ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_unpacklo_epi8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_punpcklbw128 ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i
+_mm_unpacklo_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_punpcklwd128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_unpacklo_epi32 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_punpckldq128 ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i
+_mm_unpacklo_epi64 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_punpcklqdq128 ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_add_epi8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_paddb128 ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i
+_mm_add_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_paddw128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_add_epi32 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_paddd128 ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i
+_mm_add_epi64 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_paddq128 ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_adds_epi8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_paddsb128 ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i
+_mm_adds_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_paddsw128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_adds_epu8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_paddusb128 ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i
+_mm_adds_epu16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_paddusw128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_sub_epi8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psubb128 ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i
+_mm_sub_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psubw128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_sub_epi32 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psubd128 ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i
+_mm_sub_epi64 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psubq128 ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_subs_epi8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psubsb128 ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i
+_mm_subs_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psubsw128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_subs_epu8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psubusb128 ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i
+_mm_subs_epu16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psubusw128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_madd_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pmaddwd128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_mulhi_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pmulhw128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_mullo_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pmullw128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m64
+_mm_mul_su32 (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pmuludq ((__v2si)__A, (__v2si)__B);
+}
+
+static __inline __m128i
+_mm_mul_epu32 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pmuludq128 ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i
+_mm_sll_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psllw128 ((__v8hi)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_sll_epi32 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pslld128 ((__v4si)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_sll_epi64 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psllq128 ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_sra_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psraw128 ((__v8hi)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_sra_epi32 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psrad128 ((__v4si)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_srl_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psrlw128 ((__v8hi)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_srl_epi32 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psrld128 ((__v4si)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_srl_epi64 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psrlq128 ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_slli_epi16 (__m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_psllwi128 ((__v8hi)__A, __B);
+}
+
+static __inline __m128i
+_mm_slli_epi32 (__m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_pslldi128 ((__v4si)__A, __B);
+}
+
+static __inline __m128i
+_mm_slli_epi64 (__m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_psllqi128 ((__v2di)__A, __B);
+}
+
+static __inline __m128i
+_mm_srai_epi16 (__m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_psrawi128 ((__v8hi)__A, __B);
+}
+
+static __inline __m128i
+_mm_srai_epi32 (__m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_psradi128 ((__v4si)__A, __B);
+}
+
+#if 0
+static __m128i __attribute__((__always_inline__))
+_mm_srli_si128 (__m128i __A, const int __B)
+{
+ return ((__m128i)__builtin_ia32_psrldqi128 (__A, __B))
+}
+
+static __m128i __attribute__((__always_inline__))
+_mm_srli_si128 (__m128i __A, const int __B)
+{
+ return ((__m128i)__builtin_ia32_pslldqi128 (__A, __B))
+}
+#endif
+#define _mm_srli_si128(__A, __B) ((__m128i)__builtin_ia32_psrldqi128 (__A, __B))
+#define _mm_slli_si128(__A, __B) ((__m128i)__builtin_ia32_pslldqi128 (__A, __B))
+
+static __inline __m128i
+_mm_srli_epi16 (__m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_psrlwi128 ((__v8hi)__A, __B);
+}
+
+static __inline __m128i
+_mm_srli_epi32 (__m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_psrldi128 ((__v4si)__A, __B);
+}
+
+static __inline __m128i
+_mm_srli_epi64 (__m128i __A, int __B)
+{
+ return (__m128i)__builtin_ia32_psrlqi128 ((__v2di)__A, __B);
+}
+
+static __inline __m128i
+_mm_and_si128 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pand128 ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_andnot_si128 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pandn128 ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_or_si128 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_por128 ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_xor_si128 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pxor128 ((__v2di)__A, (__v2di)__B);
+}
+
+static __inline __m128i
+_mm_cmpeq_epi8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pcmpeqb128 ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i
+_mm_cmpeq_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pcmpeqw128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_cmpeq_epi32 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pcmpeqd128 ((__v4si)__A, (__v4si)__B);
+}
+
+static __inline __m128i
+_mm_cmplt_epi8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pcmpgtb128 ((__v16qi)__B, (__v16qi)__A);
+}
+
+static __inline __m128i
+_mm_cmplt_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pcmpgtw128 ((__v8hi)__B, (__v8hi)__A);
+}
+
+static __inline __m128i
+_mm_cmplt_epi32 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pcmpgtd128 ((__v4si)__B, (__v4si)__A);
+}
+
+static __inline __m128i
+_mm_cmpgt_epi8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pcmpgtb128 ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i
+_mm_cmpgt_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pcmpgtw128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_cmpgt_epi32 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pcmpgtd128 ((__v4si)__A, (__v4si)__B);
+}
+
+#define _mm_extract_epi16(__A, __B) __builtin_ia32_pextrw128 ((__v8hi)__A, __B)
+
+#define _mm_insert_epi16(__A, __B, __C) ((__m128i)__builtin_ia32_pinsrw128 ((__v8hi)__A, __B, __C))
+
+static __inline __m128i
+_mm_max_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pmaxsw128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_max_epu8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pmaxub128 ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i
+_mm_min_epi16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pminsw128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_min_epu8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pminub128 ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline int
+_mm_movemask_epi8 (__m128i __A)
+{
+ return __builtin_ia32_pmovmskb128 ((__v16qi)__A);
+}
+
+static __inline __m128i
+_mm_mulhi_epu16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pmulhuw128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+#define _mm_shufflehi_epi16(__A, __B) ((__m128i)__builtin_ia32_pshufhw ((__v8hi)__A, __B))
+#define _mm_shufflelo_epi16(__A, __B) ((__m128i)__builtin_ia32_pshuflw ((__v8hi)__A, __B))
+#define _mm_shuffle_epi32(__A, __B) ((__m128i)__builtin_ia32_pshufd ((__v4si)__A, __B))
+
+static __inline void
+_mm_maskmoveu_si128 (__m128i __A, __m128i __B, char *__C)
+{
+ __builtin_ia32_maskmovdqu ((__v16qi)__A, (__v16qi)__B, __C);
+}
+
+static __inline __m128i
+_mm_avg_epu8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pavgb128 ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline __m128i
+_mm_avg_epu16 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_pavgw128 ((__v8hi)__A, (__v8hi)__B);
+}
+
+static __inline __m128i
+_mm_sad_epu8 (__m128i __A, __m128i __B)
+{
+ return (__m128i)__builtin_ia32_psadbw128 ((__v16qi)__A, (__v16qi)__B);
+}
+
+static __inline void
+_mm_stream_si32 (int *__A, int __B)
+{
+ __builtin_ia32_movnti (__A, __B);
+}
+
+static __inline void
+_mm_stream_si128 (__m128i *__A, __m128i __B)
+{
+ __builtin_ia32_movntdq ((__v2di *)__A, (__v2di)__B);
+}
+
+static __inline void
+_mm_stream_pd (double *__A, __m128d __B)
+{
+ __builtin_ia32_movntpd (__A, (__v2df)__B);
+}
+
+static __inline __m128i
+_mm_movpi64_epi64 (__m64 __A)
+{
+ return (__m128i)__builtin_ia32_movq2dq ((unsigned long long)__A);
+}
+
+static __inline void
+_mm_clflush (void const *__A)
+{
+ return __builtin_ia32_clflush (__A);
+}
+
+static __inline void
+_mm_lfence (void)
+{
+ __builtin_ia32_lfence ();
+}
+
+static __inline void
+_mm_mfence (void)
+{
+ __builtin_ia32_mfence ();
+}
+
+static __inline __m128i
+_mm_cvtsi32_si128 (int __A)
+{
+ return (__m128i) __builtin_ia32_loadd (&__A);
+}
+
+#ifdef __x86_64__
+static __inline __m128i
+_mm_cvtsi64x_si128 (long long __A)
+{
+ return (__m128i) __builtin_ia32_movq2dq (__A);
+}
+#endif
+
+static __inline int
+_mm_cvtsi128_si32 (__m128i __A)
+{
+ int __tmp;
+ __builtin_ia32_stored (&__tmp, (__v4si)__A);
+ return __tmp;
+}
+
+#ifdef __x86_64__
+static __inline long long
+_mm_cvtsi128_si64x (__m128i __A)
+{
+ return __builtin_ia32_movdq2q ((__v2di)__A);
+}
+#endif
+
+#endif /* __SSE2__ */
+
+#endif /* __SSE__ */
#endif /* _XMMINTRIN_H_INCLUDED */
diff --git a/contrib/gcc/config/ia64/aix.h b/contrib/gcc/config/ia64/aix.h
index fee0732..5eb2334 100644
--- a/contrib/gcc/config/ia64/aix.h
+++ b/contrib/gcc/config/ia64/aix.h
@@ -71,34 +71,36 @@ Boston, MA 02111-1307, USA. */
/* Define this so we can compile MS code for use with WINE. */
#define HANDLE_PRAGMA_PACK_PUSH_POP
+/* Target OS builtins. */
+#define TARGET_OS_CPP_BUILTINS() \
+do { \
+ if (flag_iso) \
+ builtin_define("_ANSI_C_SOURCE"); \
+ builtin_define("_AIX"); \
+ builtin_define("_AIX64"); \
+ builtin_define("unix"); \
+ builtin_assert("system=unix"); \
+ builtin_assert("system=aix"); \
+ builtin_define("__64BIT__"); \
+ builtin_define("_LONG_LONG"); \
+ builtin_define("_IA64"); \
+ builtin_define("__int128=__size128_t"); \
+ if (c_language == clk_cplusplus) \
+ { \
+ builtin_define("_XOPEN_SOURCE=500"); \
+ builtin_define("_XOPEN_SOURCE_EXTENDED=1"); \
+ builtin_define("_LARGE_FILE_API"); \
+ builtin_define("_ALL_SOURCE"); \
+ } \
+} while (0)
+
/* A C string constant that tells the GNU CC driver program options to pass to
CPP. It can also specify how to translate options you give to GNU CC into
options for GNU CC to pass to the CPP. */
-/* If -ansi, we need to define _ANSI_C_SOURCE to get the right headers. */
#undef CPP_SPEC
#define CPP_SPEC "\
-%{mcpu=itanium:-D__itanium__} %{mbig-endian:-D__BIG_ENDIAN__} \
-%{ansi:-D_ANSI_C_SOURCE} \
-%{posix:-D_POSIX_SOURCE} \
-%{cpp_cpu} \
--D__LONG_MAX__=9223372036854775807L"
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "\
- -D_AIX -D_AIX64 -D_LONGLONG -Dunix \
- -Asystem=unix -Asystem=aix \
- -D__64BIT__ -D_LONG_LONG -D_IA64 -D__int128=__size128_t"
-
-/* The GNU C++ standard library requires that these macros be defined. */
-#undef CPLUSPLUS_CPP_SPEC
-#define CPLUSPLUS_CPP_SPEC \
- "-D_XOPEN_SOURCE=500 \
- -D_XOPEN_SOURCE_EXTENDED=1 \
- -D_LARGE_FILE_API \
- -D_ALL_SOURCE \
- -D__LONG_MAX__=9223372036854775807L \
- %{cpp_cpu}"
+%{posix:-D_POSIX_SOURCE}"
/* Define this for shared library support. */
@@ -132,103 +134,14 @@ do { \
#define STANDARD_STARTFILE_PREFIX "/usr/lib/ia64l64/"
#endif
-/* Override SELECT_SECTION and SELECT_RTX_SECTION from config/ia64/sysv4.h;
- these definitions ignore flag_pic as if it were always set;
- it is illegal to have relocations in shared segments on AIX. */
-
-/* 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,ALIGN) \
-{ \
- if (TREE_CODE (DECL) == STRING_CST) \
- { \
- if (! flag_writable_strings) \
- const_section (); \
- else \
- data_section (); \
- } \
- else if (TREE_CODE (DECL) == VAR_DECL) \
- { \
- if (XSTR (XEXP (DECL_RTL (DECL), 0), 0)[0] \
- == SDATA_NAME_FLAG_CHAR) \
- sdata_section (); \
- /* ??? We need the extra ! RELOC check, because the default is to \
- only check RELOC if flag_pic is set, and we don't set flag_pic \
- (yet?). */ \
- else if (DECL_READONLY_SECTION (DECL, RELOC) && ! (RELOC)) \
- const_section (); \
- else \
- data_section (); \
- } \
- /* This could be a CONSTRUCTOR containing ADDR_EXPR of a VAR_DECL, \
- in which case we can't put it in a shared library rodata. */ \
- else if (RELOC) \
- data_section (); \
- else \
- const_section (); \
-}
-
-/* Similarly for constant pool data. */
-
-extern unsigned int ia64_section_threshold;
-#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE, RTX, ALIGN) \
-{ \
- if (GET_MODE_SIZE (MODE) > 0 \
- && GET_MODE_SIZE (MODE) <= ia64_section_threshold) \
- sdata_section (); \
- else if (symbolic_operand ((RTX), (MODE))) \
- data_section (); \
- else \
- const_section (); \
-}
-
-#undef UNIQUE_SECTION
-#define UNIQUE_SECTION(DECL, RELOC) \
- do \
- { \
- int len; \
- int sec; \
- const char *name; \
- char *string; \
- const char *prefix; \
- static const char *const prefixes[/*4*/3][2] = \
- { \
- { ".text.", ".gnu.linkonce.t." }, \
- { ".rodata.", ".gnu.linkonce.r." }, \
- { ".data.", ".gnu.linkonce.d." } \
- /* Do not generate unique sections for uninitialised \
- data since we do not have support for this in the \
- linker scripts yet... \
- ,{ ".bss.", ".gnu.linkonce.b." } */ \
- }; \
- \
- if (TREE_CODE (DECL) == FUNCTION_DECL) \
- sec = 0; \
- /* else if (DECL_INITIAL (DECL) == 0 \
- || DECL_INITIAL (DECL) == error_mark_node) \
- sec = 3; */ \
- else if (DECL_READONLY_SECTION (DECL, RELOC) && ! (RELOC))\
- sec = 1; \
- else \
- sec = 2; \
- \
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
- /* Strip off any encoding in name. */ \
- STRIP_NAME_ENCODING (name, name); \
- prefix = prefixes[sec][DECL_ONE_ONLY(DECL)]; \
- len = strlen (name) + strlen (prefix); \
- string = alloca (len + 1); \
- \
- sprintf (string, "%s%s", prefix, name); \
- \
- DECL_SECTION_NAME (DECL) = build_string (len, string); \
- } \
- while (0)
+/* It is illegal to have relocations in shared segments on AIX.
+ Pretend flag_pic is always set. */
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION ia64_rwreloc_select_section
+#undef TARGET_ASM_UNIQUE_SECTION
+#define TARGET_ASM_UNIQUE_SECTION ia64_rwreloc_unique_section
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION ia64_rwreloc_select_rtx_section
/* Override ia64/sysv4.h setting with that used by AIX5. */
#undef WCHAR_TYPE
diff --git a/contrib/gcc/config/ia64/crtbegin.asm b/contrib/gcc/config/ia64/crtbegin.asm
index 388b24e..cb49e10 100644
--- a/contrib/gcc/config/ia64/crtbegin.asm
+++ b/contrib/gcc/config/ia64/crtbegin.asm
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
Contributed by Jes Sorensen, <Jes.Sorensen@cern.ch>
The GNU C Library is free software; you can redistribute it and/or
@@ -16,6 +16,8 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include "auto-host.h"
+
.section .ctors,"aw","progbits"
.align 8
__CTOR_LIST__:
@@ -52,6 +54,16 @@ __dso_handle:
.hidden __dso_handle#
+#ifdef HAVE_INITFINI_ARRAY
+
+.section .fini_array,"a","progbits"
+ data8 @fptr(__do_global_dtors_aux)
+
+.section .init_array,"a","progbits"
+ data8 @fptr(__do_jv_register_classes)
+ data8 @fptr(__do_global_ctors_aux)
+
+#else /* !HAVE_INITFINI_ARRAY */
/*
* Fragment of the ELF _fini routine that invokes our dtor cleanup.
*
@@ -98,6 +110,7 @@ __dso_handle:
br.call.sptk.many b0 = b6
;;
}
+#endif /* !HAVE_INITFINI_ARRAY */
.section .text
.align 16
diff --git a/contrib/gcc/config/ia64/crtend.asm b/contrib/gcc/config/ia64/crtend.asm
index e5d109a..303f30c 100644
--- a/contrib/gcc/config/ia64/crtend.asm
+++ b/contrib/gcc/config/ia64/crtend.asm
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
Contributed by Jes Sorensen, <Jes.Sorensen@cern.ch>
The GNU C Library is free software; you can redistribute it and/or
@@ -16,6 +16,8 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include "auto-host.h"
+
.section .ctors,"aw","progbits"
.align 8
__CTOR_END__:
@@ -31,6 +33,7 @@ __DTOR_END__:
__JCR_END__:
data8 0
+#ifndef HAVE_INITFINI_ARRAY
/*
* Fragment of the ELF _init routine that invokes our dtor cleanup.
*
@@ -59,9 +62,16 @@ __JCR_END__:
br.call.sptk.many b0 = b6
;;
}
+#endif /* !HAVE_INITFINI_ARRAY */
.text
.align 16
+#ifdef HAVE_INITFINI_ARRAY
+ /* This is referenced from crtbegin.o. */
+ .globl __do_global_ctors_aux#
+ .type __do_global_ctors_aux#,@function
+ .hidden __do_global_ctors_aux#
+#endif
.proc __do_global_ctors_aux#
__do_global_ctors_aux:
/*
diff --git a/contrib/gcc/config/ia64/elf.h b/contrib/gcc/config/ia64/elf.h
index af6d917..e30090d 100644
--- a/contrib/gcc/config/ia64/elf.h
+++ b/contrib/gcc/config/ia64/elf.h
@@ -5,12 +5,6 @@
#define TARGET_VERSION fprintf (stderr, " (IA-64) ELF");
-/* Define this to be a string constant containing `-D' options to define the
- predefined macros that identify this machine and system. These macros will
- be predefined unless the `-ansi' option is specified. */
-/* ??? This is undefed in svr4.h. */
-#define CPP_PREDEFINES "-Dia64 -Amachine=ia64"
-
/* A C string constant that tells the GNU CC driver program options to pass to
the assembler. It can also specify how to translate options you give to GNU
CC into options for GNU CC to pass to the assembler. */
diff --git a/contrib/gcc/config/ia64/freebsd.h b/contrib/gcc/config/ia64/freebsd.h
index 57bb391..34dc885 100644
--- a/contrib/gcc/config/ia64/freebsd.h
+++ b/contrib/gcc/config/ia64/freebsd.h
@@ -42,9 +42,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
We use the GCC defaults instead. */
#undef WCHAR_TYPE
-#undef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
-
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
diff --git a/contrib/gcc/config/ia64/hpux.h b/contrib/gcc/config/ia64/hpux.h
index d46acf2..56c601b 100644
--- a/contrib/gcc/config/ia64/hpux.h
+++ b/contrib/gcc/config/ia64/hpux.h
@@ -1,5 +1,5 @@
/* Definitions of target machine GNU compiler. IA-64 version.
- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Steve Ellcey <sje@cup.hp.com> and
Reva Cuthbertson <reva@cup.hp.com>
@@ -25,26 +25,29 @@ Boston, MA 02111-1307, USA. */
#define TARGET_VERSION fprintf (stderr, " (IA-64) HP-UX");
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "\
- -D__IA64__ -D__hpux -D__hpux__ -Dhpux -Dunix \
- -D__BIG_ENDIAN__ -D_LONGLONG \
- -Asystem=hpux -Asystem=posix -Asystem=unix \
- -D_UINT128_T"
-
-/* -D__fpreg=long double is needed to compensate for the lack of __fpreg
- which is a primitive type in HP C but does not exist in GNU C. Same
- for __float80 and __float128. These types appear in HP-UX header
- files and so must have some definition. */
-
-#undef CPP_SPEC
-#define CPP_SPEC "\
- %{mcpu=itanium:-D__itanium__} \
- %{mlp64:-D__LP64__ -D_LP64 -D__LONG_MAX__=9223372036854775807L} \
- %{!ansi:%{!std=c*:%{!std=i*: -D_HPUX_SOURCE -D__STDC_EXT__}}} \
- -D__fpreg=long\\ double \
- -D__float80=long\\ double \
- -D__float128=long\\ double"
+/* Target OS builtins. */
+/* -D__fpreg=long double is needed to compensate for
+ the lack of __fpreg which is a primative type in
+ HP C but does not exist in GNU C. */
+#define TARGET_OS_CPP_BUILTINS() \
+do { \
+ builtin_assert("system=hpux"); \
+ builtin_assert("system=posix"); \
+ builtin_assert("system=unix"); \
+ builtin_define_std("hpux"); \
+ builtin_define_std("unix"); \
+ builtin_define("__IA64__"); \
+ builtin_define("_LONGLONG"); \
+ builtin_define("_UINT128_T"); \
+ builtin_define("__fpreg=long double"); \
+ builtin_define("__float80=long double"); \
+ builtin_define("__float128=long double"); \
+ if (c_language == clk_cplusplus || !flag_iso) \
+ { \
+ builtin_define("_HPUX_SOURCE"); \
+ builtin_define("__STDC_EXT__"); \
+ } \
+} while (0)
#undef ASM_EXTRA_SPEC
#define ASM_EXTRA_SPEC "%{milp32:-milp32} %{mlp64:-mlp64}"
@@ -52,24 +55,31 @@ Boston, MA 02111-1307, USA. */
#undef ENDFILE_SPEC
#undef STARTFILE_SPEC
-#ifdef CROSS_COMPILE
-#define STARTFILE_SPEC "%{!shared:crt0%O%s}"
-#else
-#define STARTFILE_SPEC "/usr/ccs/lib/hpux64/crt0%O"
-#endif
+#define STARTFILE_SPEC "%{!shared:%{static:crt0%O%s}}"
#undef LINK_SPEC
-#define LINK_SPEC "\
- +Accept TypeMismatch \
- %{shared:-b} \
- %{!shared: \
- -u main \
- %{!static: \
- %{rdynamic:-export-dynamic}} \
- %{static:-static}}"
+#define LINK_SPEC \
+ "+Accept TypeMismatch \
+ %{shared:-b} \
+ %{!shared: \
+ -u main \
+ %{static:-noshared}}"
#undef LIB_SPEC
-#define LIB_SPEC "%{!shared:%{!symbolic:-lc}}"
+#define LIB_SPEC \
+ "%{!shared: \
+ %{p:%{!mlp64:-L/usr/lib/hpux32/libp} \
+ %{mlp64:-L/usr/lib/hpux64/libp} -lprof} \
+ %{pg:%{!mlp64:-L/usr/lib/hpux32/libp} \
+ %{mlp64:-L/usr/lib/hpux64/libp} -lgprof} \
+ %{!symbolic:-lc}}"
+
+#ifndef CROSS_COMPILE
+#undef LIBGCC_SPEC
+#define LIBGCC_SPEC \
+ "%{shared-libgcc:%{!mlp64:-lgcc_s_hpux32}%{mlp64:-lgcc_s_hpux64} -lgcc} \
+ %{!shared-libgcc:-lgcc}"
+#endif
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
@@ -85,34 +95,27 @@ Boston, MA 02111-1307, USA. */
#define JMP_BUF_SIZE (8 * 76)
-#undef CONST_SECTION_ASM_OP
-#define CONST_SECTION_ASM_OP "\t.section\t.rodata,\t\"a\",\t\"progbits\""
-
-#undef BITS_BIG_ENDIAN
-#define BITS_BIG_ENDIAN 1
-
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_DWARF2_ASM | MASK_BIG_ENDIAN)
+#define TARGET_DEFAULT (MASK_DWARF2_ASM | MASK_BIG_ENDIAN | MASK_ILP32)
/* This needs to be set to force structure arguments with a single
field to be treated as structures and not as the type of their
field. Without this a structure with a single char will be
returned just like a char variable and that is wrong on HP-UX
- IA64. TARGET_STRUCT_ARG_REG_LITTLE_ENDIAN triggers the special
- structure handling, this macro simply ensures that single field
- structures are always treated like structures. */
+ IA64. */
-#define MEMBER_TYPE_FORCES_BLK(FIELD) 1
+#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) (TREE_CODE (TREE_TYPE (FIELD)) != REAL_TYPE || (MODE == TFmode && !INTEL_EXTENDED_IEEE_FORMAT))
-/* Override the setting of FUNCTION_ARG_REG_LITTLE_ENDIAN in
- defaults.h. Setting this to true means that we are not passing
- structures in registers in the "normal" big-endian way. See
- See section 8.5 of the "Itanium Software Conventions and Runtime
- Architecture", specifically Table 8-1 and the explanation of Byte 0
- alignment and LSB alignment and a description of how structures
- are passed. */
+/* ASM_OUTPUT_EXTERNAL_LIBCALL defaults to just a globalize_label call,
+ but that doesn't put out the @function type information which causes
+ shared library problems. */
-#define FUNCTION_ARG_REG_LITTLE_ENDIAN 1
+#undef ASM_OUTPUT_EXTERNAL_LIBCALL
+#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
+do { \
+ (*targetm.asm_out.globalize_label) (FILE, XSTR (FUN, 0)); \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, XSTR (FUN, 0), "function"); \
+} while (0)
#undef FUNCTION_ARG_PADDING
#define FUNCTION_ARG_PADDING(MODE, TYPE) \
@@ -120,3 +123,52 @@ Boston, MA 02111-1307, USA. */
#undef PAD_VARARGS_DOWN
#define PAD_VARARGS_DOWN (!AGGREGATE_TYPE_P (type))
+
+#define REGISTER_TARGET_PRAGMAS(PFILE) \
+ cpp_register_pragma (PFILE, 0, "builtin", ia64_hpux_handle_builtin_pragma)
+
+/* Tell ia64.c that we are using the HP linker and we should delay output of
+ function extern declarations so that we don't output them for functions
+ which are never used (and may not be defined). */
+
+#undef TARGET_HPUX_LD
+#define TARGET_HPUX_LD 1
+
+/* Put out the needed function declarations at the end. */
+
+#define ASM_FILE_END(STREAM) ia64_hpux_asm_file_end(STREAM)
+
+#undef CTORS_SECTION_ASM_OP
+#define CTORS_SECTION_ASM_OP "\t.section\t.init_array,\t\"aw\",\"init_array\""
+
+#undef DTORS_SECTION_ASM_OP
+#define DTORS_SECTION_ASM_OP "\t.section\t.fini_array,\t\"aw\",\"fini_array\""
+
+#undef READONLY_DATA_SECTION_ASM_OP
+#define READONLY_DATA_SECTION_ASM_OP "\t.section\t.rodata,\t\"a\",\t\"progbits\""
+
+#undef DATA_SECTION_ASM_OP
+#define DATA_SECTION_ASM_OP "\t.section\t.data,\t\"aw\",\t\"progbits\""
+
+#undef SDATA_SECTION_ASM_OP
+#define SDATA_SECTION_ASM_OP "\t.section\t.sdata,\t\"asw\",\t\"progbits\""
+
+#undef BSS_SECTION_ASM_OP
+#define BSS_SECTION_ASM_OP "\t.section\t.bss,\t\"aw\",\t\"nobits\""
+
+#undef SBSS_SECTION_ASM_OP
+#define SBSS_SECTION_ASM_OP "\t.section\t.sbss,\t\"asw\",\t\"nobits\""
+
+#undef TEXT_SECTION_ASM_OP
+#define TEXT_SECTION_ASM_OP "\t.section\t.text,\t\"ax\",\t\"progbits\""
+
+/* It is illegal to have relocations in shared segments on HPUX.
+ Pretend flag_pic is always set. */
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION ia64_rwreloc_select_section
+#undef TARGET_ASM_UNIQUE_SECTION
+#define TARGET_ASM_UNIQUE_SECTION ia64_rwreloc_unique_section
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION ia64_rwreloc_select_rtx_section
+#undef TARGET_SECTION_TYPE_FLAGS
+#define TARGET_SECTION_TYPE_FLAGS ia64_rwreloc_section_type_flags
diff --git a/contrib/gcc/config/ia64/hpux_longdouble.h b/contrib/gcc/config/ia64/hpux_longdouble.h
index bfc12d4..5333033 100644
--- a/contrib/gcc/config/ia64/hpux_longdouble.h
+++ b/contrib/gcc/config/ia64/hpux_longdouble.h
@@ -18,8 +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. */
-/* Tell real.c that we are not using INTEL_EXTENDED_IEEE_FORMAT */
-
+/* We are using IEEE quad precision, not a double-extended with padding. */
#undef INTEL_EXTENDED_IEEE_FORMAT
#define INTEL_EXTENDED_IEEE_FORMAT 0
@@ -42,6 +41,8 @@ Boston, MA 02111-1307, USA. */
#define FLOATDITF2_LIBCALL "_U_Qfcnvxf_dbl_to_quad"
#define FIX_TRUNCTFSI2_LIBCALL "_U_Qfcnvfxt_quad_to_sgl"
#define FIX_TRUNCTFDI2_LIBCALL "_U_Qfcnvfxt_quad_to_dbl"
+#define FIXUNS_TRUNCTFSI2_LIBCALL "_U_Qfcnvfxut_quad_to_sgl"
+#define FIXUNS_TRUNCTFDI2_LIBCALL "_U_Qfcnvfxut_quad_to_dbl"
#define EQTF2_LIBCALL "_U_Qfeq"
#define NETF2_LIBCALL "_U_Qfne"
#define GTTF2_LIBCALL "_U_Qfgt"
@@ -77,8 +78,8 @@ Boston, MA 02111-1307, USA. */
floatditf_libfunc = gen_rtx_SYMBOL_REF (Pmode, FLOATDITF2_LIBCALL); \
fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFSI2_LIBCALL);\
fixtfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFDI2_LIBCALL);\
- fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFSI2_LIBCALL); \
- fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFDI2_LIBCALL); \
+ fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIXUNS_TRUNCTFSI2_LIBCALL); \
+ fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIXUNS_TRUNCTFDI2_LIBCALL); \
eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, EQTF2_LIBCALL); \
netf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, NETF2_LIBCALL); \
gttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, GTTF2_LIBCALL); \
@@ -86,11 +87,6 @@ Boston, MA 02111-1307, USA. */
lttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, LTTF2_LIBCALL); \
letf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, LETF2_LIBCALL); \
\
- sdiv_optab->handlers[(int) SImode].libfunc = 0; \
- udiv_optab->handlers[(int) SImode].libfunc = 0; \
- smod_optab->handlers[(int) SImode].libfunc = 0; \
- umod_optab->handlers[(int) SImode].libfunc = 0; \
- \
INIT_SUBTARGET_OPTABS; \
} while (0)
diff --git a/contrib/gcc/config/ia64/ia64-c.c b/contrib/gcc/config/ia64/ia64-c.c
new file mode 100644
index 0000000..e44c80b
--- /dev/null
+++ b/contrib/gcc/config/ia64/ia64-c.c
@@ -0,0 +1,191 @@
+/* Definitions of C specific functions for GNU compiler.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Steve Ellcey <sje@cup.hp.com>
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "tree.h"
+#include "cpplib.h"
+#include "c-common.h"
+#include "c-pragma.h"
+#include "toplev.h"
+#include "tm_p.h"
+
+static void ia64_hpux_add_pragma_builtin PARAMS ((tree func));
+
+void
+ia64_hpux_handle_builtin_pragma (pfile)
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
+{
+ /* #pragma builtin name, name, name */
+
+ enum cpp_ttype type;
+ tree x;
+
+ type = c_lex (&x);
+ while (type == CPP_NAME)
+ {
+ ia64_hpux_add_pragma_builtin (x);
+ type = c_lex (&x);
+ if (type == CPP_COMMA)
+ type = c_lex (&x);
+ }
+ if (type != CPP_EOF)
+ warning ("malformed #pragma builtin");
+}
+
+/* List of standard math functions which do not set matherr by default
+ and which have a different version which does set errno and which we
+ want to call *if* we have seen an extern for the routine and we have
+ asked for strict C89 compatibility. */
+
+typedef struct c89_mathlib_names
+{
+ const char *realname; /* User visible function name. */
+ const char *c89name; /* libm special name needed to set errno. */
+} c89_mathlib_names;
+
+static const c89_mathlib_names c89_mathlib_name_list [] =
+{
+ {"acos", "_Acos_e#"},
+ {"acosd", "_Acosd_e#"},
+ {"acosdf", "_Acosdf_e#"},
+ {"acosdl", "_Acosdl_e#"},
+ {"acosdw", "_Acosdw_e#"},
+ {"acosf", "_Acosf_e#"},
+ {"acosh", "_Acosh_e#"},
+ {"acoshf", "_Acoshf_e#"},
+ {"acoshl", "_Acoshl_e#"},
+ {"acoshw", "_Acoshw_e#"},
+ {"acosl", "_Acosl_e#"},
+ {"acosw", "_Acosw_e#"},
+ {"asin", "_Asin_e#"},
+ {"asind", "_Asind_e#"},
+ {"asindf", "_Asindf_e#"},
+ {"asindl", "_Asindl_e#"},
+ {"asindw", "_Asindw_e#"},
+ {"asinf", "_Asinf_e#"},
+ {"asinl", "_Asinl_e#"},
+ {"asinw", "_Asinw_e#"},
+ {"atanh", "_Atanh_e#"},
+ {"atanhf", "_Atanhf_e#"},
+ {"atanhl", "_Atanhl_e#"},
+ {"atanhw", "_Atanhw_e#"},
+ {"cosh", "_Cosh_e#"},
+ {"coshf", "_Coshf_e#"},
+ {"coshl", "_Coshl_e#"},
+ {"coshw", "_Coshw_e#"},
+ {"exp2", "_Exp2_e#"},
+ {"exp2f", "_Exp2f_e#"},
+ {"exp2l", "_Exp2l_e#"},
+ {"exp2w", "_Exp2w_e#"},
+ {"exp", "_Exp_e#"},
+ {"expf", "_Expf_e#"},
+ {"expl", "_Expl_e#"},
+ {"expm1", "_Expm1_e#"},
+ {"expm1f", "_Expm1f_e#"},
+ {"expm1l", "_Expm1l_e#"},
+ {"expm1w", "_Expm1w_e#"},
+ {"expw", "_Expw_e#"},
+ {"fmod", "_Fmod_e#"},
+ {"fmodf", "_Fmodf_e#"},
+ {"fmodl", "_Fmodl_e#"},
+ {"fmodw", "_Fmodw_e#"},
+ {"gamma", "_Gamma_e#"},
+ {"gammaf", "_Gammaf_e#"},
+ {"gammal", "_Gammal_e#"},
+ {"gammaw", "_Gammaw_e#"},
+ {"ldexp", "_Ldexp_e#"},
+ {"ldexpf", "_Ldexpf_e#"},
+ {"ldexpl", "_Ldexpl_e#"},
+ {"ldexpw", "_Ldexpw_e#"},
+ {"lgamma", "_Lgamma_e#"},
+ {"lgammaf", "_Lgammaf_e#"},
+ {"lgammal", "_Lgammal_e#"},
+ {"lgammaw", "_Lgammaw_e#"},
+ {"log10", "_Log10_e#"},
+ {"log10f", "_Log10f_e#"},
+ {"log10l", "_Log10l_e#"},
+ {"log10w", "_Log10w_e#"},
+ {"log1p", "_Log1p_e#"},
+ {"log1pf", "_Log1pf_e#"},
+ {"log1pl", "_Log1pl_e#"},
+ {"log1pw", "_Log1pw_e#"},
+ {"log2", "_Log2_e#"},
+ {"log2f", "_Log2f_e#"},
+ {"log2l", "_Log2l_e#"},
+ {"log2w", "_Log2w_e#"},
+ {"log", "_Log_e#"},
+ {"logb", "_Logb_e#"},
+ {"logbf", "_Logbf_e#"},
+ {"logbl", "_Logbl_e#"},
+ {"logbw", "_Logbw_e#"},
+ {"logf", "_Logf_e#"},
+ {"logl", "_Logl_e#"},
+ {"logw", "_Logw_e#"},
+ {"nextafter", "_Nextafter_e#"},
+ {"nextafterf", "_Nextafterf_e#"},
+ {"nextafterl", "_Nextafterl_e#"},
+ {"nextafterw", "_Nextafterw_e#"},
+ {"pow", "_Pow_e#"},
+ {"powf", "_Powf_e#"},
+ {"powl", "_Powl_e#"},
+ {"poww", "_Poww_e#"},
+ {"remainder", "_Remainder_e#"},
+ {"remainderf", "_Remainderf_e#"},
+ {"remainderl", "_Remainderl_e#"},
+ {"remainderw", "_Remainderw_e#"},
+ {"scalb", "_Scalb_e#"},
+ {"scalbf", "_Scalbf_e#"},
+ {"scalbl", "_Scalbl_e#"},
+ {"scalbw", "_Scalbw_e#"},
+ {"sinh", "_Sinh_e#"},
+ {"sinhf", "_Sinhf_e#"},
+ {"sinhl", "_Sinhl_e#"},
+ {"sinhw", "_Sinhw_e#"},
+ {"sqrt", "_Sqrt_e#"},
+ {"sqrtf", "_Sqrtf_e#"},
+ {"sqrtl", "_Sqrtl_e#"},
+ {"sqrtw", "_Sqrtw_e#"},
+ {"tgamma", "_Tgamma_e#"},
+ {"tgammaf", "_Tgammaf_e#"},
+ {"tgammal", "_Tgammal_e#"},
+ {"tgammaw", "_Tgammaw_e#"}
+};
+
+static void
+ia64_hpux_add_pragma_builtin (func)
+ tree func;
+{
+ size_t i;
+
+ if (!flag_isoc94 && flag_iso)
+ {
+ for (i = 0; i < ARRAY_SIZE (c89_mathlib_name_list); i++)
+ {
+ if (!strcmp(c89_mathlib_name_list[i].realname,
+ IDENTIFIER_POINTER (func)))
+ {
+ add_to_renaming_pragma_list(func,
+ get_identifier(c89_mathlib_name_list[i].c89name));
+ }
+ }
+ }
+}
diff --git a/contrib/gcc/config/ia64/ia64-modes.def b/contrib/gcc/config/ia64/ia64-modes.def
new file mode 100644
index 0000000..0c3eb12
--- /dev/null
+++ b/contrib/gcc/config/ia64/ia64-modes.def
@@ -0,0 +1,29 @@
+/* Definitions of target machine GNU compiler. IA-64 version.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by James E. Wilson <wilson@cygnus.com> and
+ David Mosberger <davidm@hpl.hp.com>.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Add any extra modes needed to represent the condition code.
+
+ CCImode is used to mark a single predicate register instead
+ of a register pair. This is currently only used in reg_raw_mode
+ so that flow doesn't do something stupid. */
+
+CC (CCI)
diff --git a/contrib/gcc/config/ia64/ia64-protos.h b/contrib/gcc/config/ia64/ia64-protos.h
index 659adc5..72c2279 100644
--- a/contrib/gcc/config/ia64/ia64-protos.h
+++ b/contrib/gcc/config/ia64/ia64-protos.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler for IA-64.
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -21,7 +21,8 @@ Boston, MA 02111-1307, USA. */
/* Variables defined in ia64.c. */
#ifdef RTX_CODE
-extern rtx ia64_compare_op0, ia64_compare_op1;
+extern GTY(()) rtx ia64_compare_op0;
+extern GTY(()) rtx ia64_compare_op1;
#endif
/* Functions defined in ia64.c */
@@ -31,6 +32,7 @@ extern int call_operand PARAMS((rtx, enum machine_mode));
extern int sdata_symbolic_operand PARAMS((rtx, enum machine_mode));
extern int got_symbolic_operand PARAMS((rtx, enum machine_mode));
extern int symbolic_operand PARAMS((rtx, enum machine_mode));
+extern int tls_symbolic_operand PARAMS((rtx, enum machine_mode));
extern int function_operand PARAMS((rtx, enum machine_mode));
extern int setjmp_operand PARAMS((rtx, enum machine_mode));
extern int move_operand PARAMS((rtx, enum machine_mode));
@@ -66,14 +68,18 @@ extern int ar_pfs_reg_operand PARAMS((rtx, enum machine_mode));
extern int general_tfmode_operand PARAMS((rtx, enum machine_mode));
extern int destination_tfmode_operand PARAMS((rtx, enum machine_mode));
extern int tfreg_or_fp01_operand PARAMS((rtx, enum machine_mode));
+extern int basereg_operand PARAMS((rtx, enum machine_mode));
+extern rtx ia64_expand_move PARAMS ((rtx, rtx));
extern int ia64_move_ok PARAMS((rtx, rtx));
+extern int addp4_optimize_ok PARAMS((rtx, rtx));
extern int ia64_depz_field_mask PARAMS((rtx, rtx));
-extern rtx ia64_gp_save_reg PARAMS((int));
extern rtx ia64_split_timode PARAMS((rtx[], rtx, rtx));
extern rtx spill_tfmode_operand PARAMS((rtx, int));
extern rtx ia64_expand_compare PARAMS((enum rtx_code, enum machine_mode));
extern void ia64_expand_call PARAMS((rtx, rtx, rtx, int));
+extern void ia64_split_call PARAMS((rtx, rtx, rtx, rtx, rtx, int, int));
+extern void ia64_reload_gp PARAMS((void));
extern HOST_WIDE_INT ia64_initial_elimination_offset PARAMS((int, int));
extern void ia64_expand_prologue PARAMS((void));
@@ -100,7 +106,6 @@ extern rtx ia64_function_arg PARAMS((CUMULATIVE_ARGS *, enum machine_mode,
tree, int, int));
extern rtx ia64_expand_builtin PARAMS((tree, rtx, rtx,
enum machine_mode, int));
-extern void ia64_va_start PARAMS((int, tree, rtx));
extern rtx ia64_va_arg PARAMS((tree, tree));
extern rtx ia64_function_value PARAMS((tree, tree));
#endif /* RTX_CODE */
@@ -118,8 +123,6 @@ extern int ia64_function_arg_pass_by_reference PARAMS((CUMULATIVE_ARGS *,
tree, int));
extern int ia64_return_in_memory PARAMS((tree));
extern void ia64_asm_output_external PARAMS((FILE *, tree, const char *));
-
-extern void ia64_encode_section_info PARAMS((tree));
#endif /* TREE_CODE */
extern int ia64_register_move_cost PARAMS((enum machine_mode, enum reg_class,
@@ -130,6 +133,7 @@ extern void emit_safe_across_calls PARAMS((FILE *));
extern void ia64_init_builtins PARAMS((void));
extern void ia64_override_options PARAMS((void));
extern int ia64_dbx_register_number PARAMS((int));
+extern bool ia64_function_ok_for_sibcall PARAMS ((tree));
#ifdef SDATA_SECTION_ASM_OP
extern void sdata_section PARAMS ((void));
@@ -143,3 +147,9 @@ extern void sbss_section PARAMS ((void));
/* expr.h defines ARGS_SIZE_RTX and `enum direction'. */
extern enum direction ia64_hpux_function_arg_padding PARAMS ((enum machine_mode, tree));
#endif /* ARGS_SIZE_RTX */
+
+#ifdef GCC_C_PRAGMA_H
+extern void ia64_hpux_handle_builtin_pragma PARAMS ((cpp_reader *));
+#endif
+
+extern void ia64_hpux_asm_file_end PARAMS ((FILE *));
diff --git a/contrib/gcc/config/ia64/ia64.c b/contrib/gcc/config/ia64/ia64.c
index 91dd396..a8b13f9 100644
--- a/contrib/gcc/config/ia64/ia64.c
+++ b/contrib/gcc/config/ia64/ia64.c
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler.
- Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by James E. Wilson <wilson@cygnus.com> and
David Mosberger <davidm@hpl.hp.com>.
@@ -35,7 +35,6 @@ Boston, MA 02111-1307, USA. */
#include "recog.h"
#include "expr.h"
#include "optabs.h"
-#include "obstack.h"
#include "except.h"
#include "function.h"
#include "ggc.h"
@@ -46,6 +45,7 @@ Boston, MA 02111-1307, USA. */
#include "target.h"
#include "target-def.h"
#include "tm_p.h"
+#include "langhooks.h"
/* This is used for communication between ASM_OUTPUT_LABEL and
ASM_OUTPUT_LABELREF. */
@@ -95,6 +95,13 @@ static const char * const ia64_output_reg_names[8] =
/* String used with the -mfixed-range= option. */
const char *ia64_fixed_range_string;
+/* Determines whether we use adds, addl, or movl to generate our
+ TLS immediate offsets. */
+int ia64_tls_size = 22;
+
+/* String used with the -mtls-size= option. */
+const char *ia64_tls_size_string;
+
/* Determines whether we run our final scheduling pass or not. We always
avoid the normal second scheduling pass. */
static int ia64_flag_schedule_insns2;
@@ -103,7 +110,42 @@ static int ia64_flag_schedule_insns2;
sections. */
unsigned int ia64_section_threshold;
+
+/* Structure to be filled in by ia64_compute_frame_size with register
+ save masks and offsets for the current function. */
+
+struct ia64_frame_info
+{
+ HOST_WIDE_INT total_size; /* size of the stack frame, not including
+ the caller's scratch area. */
+ HOST_WIDE_INT spill_cfa_off; /* top of the reg spill area from the cfa. */
+ HOST_WIDE_INT spill_size; /* size of the gr/br/fr spill area. */
+ HOST_WIDE_INT extra_spill_size; /* size of spill area for others. */
+ HARD_REG_SET mask; /* mask of saved registers. */
+ unsigned int gr_used_mask; /* mask of registers in use as gr spill
+ registers or long-term scratches. */
+ int n_spilled; /* number of spilled registers. */
+ int reg_fp; /* register for fp. */
+ int reg_save_b0; /* save register for b0. */
+ int reg_save_pr; /* save register for prs. */
+ int reg_save_ar_pfs; /* save register for ar.pfs. */
+ int reg_save_ar_unat; /* save register for ar.unat. */
+ int reg_save_ar_lc; /* save register for ar.lc. */
+ int reg_save_gp; /* save register for gp. */
+ int n_input_regs; /* number of input registers used. */
+ int n_local_regs; /* number of local registers used. */
+ int n_output_regs; /* number of output registers used. */
+ int n_rotate_regs; /* number of rotating registers used. */
+
+ char need_regstk; /* true if a .regstk directive needed. */
+ char initialized; /* true if the data is finalized. */
+};
+
+/* Current frame information calculated by ia64_compute_frame_size. */
+static struct ia64_frame_info current_frame_info;
+static rtx gen_tls_get_addr PARAMS ((void));
+static rtx gen_thread_pointer PARAMS ((void));
static int find_gr_spill PARAMS ((int));
static int next_scratch_gr_reg PARAMS ((void));
static void mark_reg_gr_used_mask PARAMS ((rtx, void *));
@@ -119,13 +161,13 @@ static rtx gen_fr_restore_x PARAMS ((rtx, rtx, rtx));
static enum machine_mode hfa_element_mode PARAMS ((tree, int));
static void fix_range PARAMS ((const char *));
-static void ia64_add_gc_roots PARAMS ((void));
-static void ia64_init_machine_status PARAMS ((struct function *));
-static void ia64_mark_machine_status PARAMS ((struct function *));
-static void ia64_free_machine_status PARAMS ((struct function *));
+static struct machine_function * ia64_init_machine_status PARAMS ((void));
static void emit_insn_group_barriers PARAMS ((FILE *, rtx));
static void emit_all_insn_group_barriers PARAMS ((FILE *, rtx));
static void emit_predicate_relation_info PARAMS ((void));
+static bool ia64_in_small_data_p PARAMS ((tree));
+static void ia64_encode_section_info PARAMS ((tree, int));
+static const char *ia64_strip_name_encoding PARAMS ((const char *));
static void process_epilogue PARAMS ((void));
static int process_set PARAMS ((FILE *, rtx));
@@ -152,8 +194,26 @@ static int ia64_internal_sched_reorder PARAMS ((FILE *, int, rtx *,
static int ia64_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));
static int ia64_sched_reorder2 PARAMS ((FILE *, int, rtx *, int *, int));
static int ia64_variable_issue PARAMS ((FILE *, int, rtx, int));
-static rtx ia64_cycle_display PARAMS ((int, rtx));
+static void ia64_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+ HOST_WIDE_INT, tree));
+
+static void ia64_select_rtx_section PARAMS ((enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT));
+static void ia64_rwreloc_select_section PARAMS ((tree, int,
+ unsigned HOST_WIDE_INT))
+ ATTRIBUTE_UNUSED;
+static void ia64_rwreloc_unique_section PARAMS ((tree, int))
+ ATTRIBUTE_UNUSED;
+static void ia64_rwreloc_select_rtx_section PARAMS ((enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT))
+ ATTRIBUTE_UNUSED;
+static unsigned int ia64_rwreloc_section_type_flags
+ PARAMS ((tree, const char *, int))
+ ATTRIBUTE_UNUSED;
+
+static void ia64_hpux_add_extern_decl PARAMS ((const char *name))
+ ATTRIBUTE_UNUSED;
/* Table of valid machine attributes. */
static const struct attribute_spec ia64_attribute_table[] =
@@ -197,6 +257,13 @@ static const struct attribute_spec ia64_attribute_table[] =
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE ia64_output_function_epilogue
+#undef TARGET_IN_SMALL_DATA_P
+#define TARGET_IN_SMALL_DATA_P ia64_in_small_data_p
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO ia64_encode_section_info
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING ia64_strip_name_encoding
+
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST ia64_adjust_cost
#undef TARGET_SCHED_ISSUE_RATE
@@ -211,8 +278,16 @@ static const struct attribute_spec ia64_attribute_table[] =
#define TARGET_SCHED_REORDER ia64_sched_reorder
#undef TARGET_SCHED_REORDER2
#define TARGET_SCHED_REORDER2 ia64_sched_reorder2
-#undef TARGET_SCHED_CYCLE_DISPLAY
-#define TARGET_SCHED_CYCLE_DISPLAY ia64_cycle_display
+
+#ifdef HAVE_AS_TLS
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS true
+#endif
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK ia64_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
struct gcc_target targetm = TARGET_INITIALIZER;
@@ -223,7 +298,7 @@ call_operand (op, mode)
rtx op;
enum machine_mode mode;
{
- if (mode != GET_MODE (op))
+ if (mode != GET_MODE (op) && mode != VOIDmode)
return 0;
return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG
@@ -250,7 +325,10 @@ sdata_symbolic_operand (op, mode)
if (CONSTANT_POOL_ADDRESS_P (op))
return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold;
else
- return XSTR (op, 0)[0] == SDATA_NAME_FLAG_CHAR;
+ {
+ const char *str = XSTR (op, 0);
+ return (str[0] == ENCODE_SECTION_INFO_CHAR && str[1] == 's');
+ }
default:
break;
@@ -324,6 +402,35 @@ symbolic_operand (op, mode)
return 0;
}
+/* Return tls_model if OP refers to a TLS symbol. */
+
+int
+tls_symbolic_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ const char *str;
+
+ if (GET_CODE (op) != SYMBOL_REF)
+ return 0;
+ str = XSTR (op, 0);
+ if (str[0] != ENCODE_SECTION_INFO_CHAR)
+ return 0;
+ switch (str[1])
+ {
+ case 'G':
+ return TLS_MODEL_GLOBAL_DYNAMIC;
+ case 'L':
+ return TLS_MODEL_LOCAL_DYNAMIC;
+ case 'i':
+ return TLS_MODEL_INITIAL_EXEC;
+ case 'l':
+ return TLS_MODEL_LOCAL_EXEC;
+ }
+ return 0;
+}
+
+
/* Return 1 if OP refers to a function. */
int
@@ -864,6 +971,21 @@ tfreg_or_fp01_operand (op, mode)
return 0;
return fr_reg_or_fp01_operand (op, mode);
}
+
+/* Return 1 if OP is valid as a base register in a reg + offset address. */
+
+int
+basereg_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ /* ??? Should I copy the flag_omit_frame_pointer and cse_not_expected
+ checks from pa.c basereg_operand as well? Seems to be OK without them
+ in test runs. */
+
+ return (register_operand (op, mode) &&
+ REG_POINTER ((GET_CODE (op) == SUBREG) ? SUBREG_REG (op) : op));
+}
/* Return 1 if the operands of a move are ok. */
@@ -889,6 +1011,21 @@ ia64_move_ok (dst, src)
return GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src);
}
+/* Return 0 if we are doing C++ code. This optimization fails with
+ C++ because of GNAT c++/6685. */
+
+int
+addp4_optimize_ok (op1, op2)
+ rtx op1, op2;
+{
+
+ if (!strcmp (lang_hooks.name, "GNU C++"))
+ return 0;
+
+ return (basereg_operand (op1, GET_MODE(op1)) !=
+ basereg_operand (op2, GET_MODE(op2)));
+}
+
/* Check if OP is a mask suitible for use with SHIFT in a dep.z instruction.
Return the length of the field, or <= 0 on failure. */
@@ -918,15 +1055,22 @@ ia64_expand_load_address (dest, src, scratch)
/* The destination could be a MEM during initial rtl generation,
which isn't a valid destination for the PIC load address patterns. */
if (! register_operand (dest, DImode))
- temp = gen_reg_rtx (DImode);
+ if (! scratch || ! register_operand (scratch, DImode))
+ temp = gen_reg_rtx (DImode);
+ else
+ temp = scratch;
else
temp = dest;
+ if (tls_symbolic_operand (src, Pmode))
+ abort ();
+
if (TARGET_AUTO_PIC)
emit_insn (gen_load_gprel64 (temp, src));
else if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_FLAG (src))
emit_insn (gen_load_fptr (temp, src));
- else if (sdata_symbolic_operand (src, DImode))
+ else if ((GET_MODE (src) == Pmode || GET_MODE (src) == ptr_mode)
+ && sdata_symbolic_operand (src, VOIDmode))
emit_insn (gen_load_gprel (temp, src));
else if (GET_CODE (src) == CONST
&& GET_CODE (XEXP (src, 0)) == PLUS
@@ -957,51 +1101,201 @@ ia64_expand_load_address (dest, src, scratch)
scratch = no_new_pseudos ? temp : gen_reg_rtx (DImode);
insn = emit_insn (gen_load_symptr (temp, src, scratch));
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE (temp) != GET_MODE (src))
+ src = convert_memory_address (GET_MODE (temp), src);
+#endif
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, src, REG_NOTES (insn));
}
if (temp != dest)
- emit_move_insn (dest, temp);
+ {
+ if (GET_MODE (dest) != GET_MODE (temp))
+ temp = convert_to_mode (GET_MODE (dest), temp, 0);
+ emit_move_insn (dest, temp);
+ }
}
-rtx
-ia64_gp_save_reg (setjmp_p)
- int setjmp_p;
-{
- rtx save = cfun->machine->ia64_gp_save;
-
- if (save != NULL)
- {
- /* We can't save GP in a pseudo if we are calling setjmp, because
- pseudos won't be restored by longjmp. For now, we save it in r4. */
- /* ??? It would be more efficient to save this directly into a stack
- slot. Unfortunately, the stack slot address gets cse'd across
- the setjmp call because the NOTE_INSN_SETJMP note is in the wrong
- place. */
-
- /* ??? Get the barf bag, Virginia. We've got to replace this thing
- in place, since this rtx is used in exception handling receivers.
- Moreover, we must get this rtx out of regno_reg_rtx or reload
- will do the wrong thing. */
- unsigned int old_regno = REGNO (save);
- if (setjmp_p && old_regno != GR_REG (4))
- {
- REGNO (save) = GR_REG (4);
- regno_reg_rtx[old_regno] = gen_rtx_raw_REG (DImode, old_regno);
- }
+static GTY(()) rtx gen_tls_tga;
+static rtx
+gen_tls_get_addr ()
+{
+ if (!gen_tls_tga)
+ {
+ gen_tls_tga = init_one_libfunc ("__tls_get_addr");
+ }
+ return gen_tls_tga;
+}
+
+static GTY(()) rtx thread_pointer_rtx;
+static rtx
+gen_thread_pointer ()
+{
+ if (!thread_pointer_rtx)
+ {
+ thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
+ RTX_UNCHANGING_P (thread_pointer_rtx) = 1;
}
- else
+ return thread_pointer_rtx;
+}
+
+rtx
+ia64_expand_move (op0, op1)
+ rtx op0, op1;
+{
+ enum machine_mode mode = GET_MODE (op0);
+
+ if (!reload_in_progress && !reload_completed && !ia64_move_ok (op0, op1))
+ op1 = force_reg (mode, op1);
+
+ if (mode == Pmode || mode == ptr_mode)
{
- if (setjmp_p)
- save = gen_rtx_REG (DImode, GR_REG (4));
- else if (! optimize)
- save = gen_rtx_REG (DImode, LOC_REG (0));
- else
- save = gen_reg_rtx (DImode);
- cfun->machine->ia64_gp_save = save;
+ enum tls_model tls_kind;
+ if ((tls_kind = tls_symbolic_operand (op1, Pmode)))
+ {
+ rtx tga_op1, tga_op2, tga_ret, tga_eqv, tmp, insns;
+
+ switch (tls_kind)
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ start_sequence ();
+
+ tga_op1 = gen_reg_rtx (Pmode);
+ emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
+ tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
+ RTX_UNCHANGING_P (tga_op1) = 1;
+
+ tga_op2 = gen_reg_rtx (Pmode);
+ emit_insn (gen_load_ltoff_dtprel (tga_op2, op1));
+ tga_op2 = gen_rtx_MEM (Pmode, tga_op2);
+ RTX_UNCHANGING_P (tga_op2) = 1;
+
+ tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
+ LCT_CONST, Pmode, 2, tga_op1,
+ Pmode, tga_op2, Pmode);
+
+ insns = get_insns ();
+ end_sequence ();
+
+ emit_libcall_block (insns, op0, tga_ret, op1);
+ return NULL_RTX;
+
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ /* ??? This isn't the completely proper way to do local-dynamic
+ If the call to __tls_get_addr is used only by a single symbol,
+ then we should (somehow) move the dtprel to the second arg
+ to avoid the extra add. */
+ start_sequence ();
+
+ tga_op1 = gen_reg_rtx (Pmode);
+ emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
+ tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
+ RTX_UNCHANGING_P (tga_op1) = 1;
+
+ tga_op2 = const0_rtx;
+
+ tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
+ LCT_CONST, Pmode, 2, tga_op1,
+ Pmode, tga_op2, Pmode);
+
+ insns = get_insns ();
+ end_sequence ();
+
+ tga_eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+ UNSPEC_LD_BASE);
+ tmp = gen_reg_rtx (Pmode);
+ emit_libcall_block (insns, tmp, tga_ret, tga_eqv);
+
+ if (register_operand (op0, Pmode))
+ tga_ret = op0;
+ else
+ tga_ret = gen_reg_rtx (Pmode);
+ if (TARGET_TLS64)
+ {
+ emit_insn (gen_load_dtprel (tga_ret, op1));
+ emit_insn (gen_adddi3 (tga_ret, tmp, tga_ret));
+ }
+ else
+ emit_insn (gen_add_dtprel (tga_ret, tmp, op1));
+ if (tga_ret == op0)
+ return NULL_RTX;
+ op1 = tga_ret;
+ break;
+
+ case TLS_MODEL_INITIAL_EXEC:
+ tmp = gen_reg_rtx (Pmode);
+ emit_insn (gen_load_ltoff_tprel (tmp, op1));
+ tmp = gen_rtx_MEM (Pmode, tmp);
+ RTX_UNCHANGING_P (tmp) = 1;
+ tmp = force_reg (Pmode, tmp);
+
+ if (register_operand (op0, Pmode))
+ op1 = op0;
+ else
+ op1 = gen_reg_rtx (Pmode);
+ emit_insn (gen_adddi3 (op1, tmp, gen_thread_pointer ()));
+ if (op1 == op0)
+ return NULL_RTX;
+ break;
+
+ case TLS_MODEL_LOCAL_EXEC:
+ if (register_operand (op0, Pmode))
+ tmp = op0;
+ else
+ tmp = gen_reg_rtx (Pmode);
+ if (TARGET_TLS64)
+ {
+ emit_insn (gen_load_tprel (tmp, op1));
+ emit_insn (gen_adddi3 (tmp, gen_thread_pointer (), tmp));
+ }
+ else
+ emit_insn (gen_add_tprel (tmp, gen_thread_pointer (), op1));
+ if (tmp == op0)
+ return NULL_RTX;
+ op1 = tmp;
+ break;
+
+ default:
+ abort ();
+ }
+ }
+ else if (!TARGET_NO_PIC &&
+ (symbolic_operand (op1, Pmode) ||
+ symbolic_operand (op1, ptr_mode)))
+ {
+ /* Before optimization starts, delay committing to any particular
+ type of PIC address load. If this function gets deferred, we
+ may acquire information that changes the value of the
+ sdata_symbolic_operand predicate.
+
+ But don't delay for function pointers. Loading a function address
+ actually loads the address of the descriptor not the function.
+ If we represent these as SYMBOL_REFs, then they get cse'd with
+ calls, and we end up with calls to the descriptor address instead
+ of calls to the function address. Functions are not candidates
+ for sdata anyways.
+
+ Don't delay for LABEL_REF because the splitter loses REG_LABEL
+ notes. Don't delay for pool addresses on general principals;
+ they'll never become non-local behind our back. */
+
+ if (rtx_equal_function_value_matters
+ && GET_CODE (op1) != LABEL_REF
+ && ! (GET_CODE (op1) == SYMBOL_REF
+ && (SYMBOL_REF_FLAG (op1)
+ || CONSTANT_POOL_ADDRESS_P (op1)
+ || STRING_POOL_ADDRESS_P (op1))))
+ if (GET_MODE (op1) == DImode)
+ emit_insn (gen_movdi_symbolic (op0, op1));
+ else
+ emit_insn (gen_movsi_symbolic (op0, op1));
+ else
+ ia64_expand_load_address (op0, op1, NULL_RTX);
+ return NULL_RTX;
+ }
}
- return save;
+ return op1;
}
/* Split a post-reload TImode reference into two DImode components. */
@@ -1089,12 +1383,12 @@ spill_tfmode_operand (in, force)
&& GET_MODE (SUBREG_REG (in)) == TImode
&& GET_CODE (SUBREG_REG (in)) == REG)
{
- rtx mem = gen_mem_addressof (SUBREG_REG (in), NULL_TREE);
+ rtx mem = gen_mem_addressof (SUBREG_REG (in), NULL_TREE, true);
return gen_rtx_MEM (TFmode, copy_to_reg (XEXP (mem, 0)));
}
else if (force && GET_CODE (in) == REG)
{
- rtx mem = gen_mem_addressof (in, NULL_TREE);
+ rtx mem = gen_mem_addressof (in, NULL_TREE, true);
return gen_rtx_MEM (TFmode, copy_to_reg (XEXP (mem, 0)));
}
else if (GET_CODE (in) == MEM
@@ -1136,72 +1430,151 @@ ia64_expand_compare (code, mode)
}
/* Emit the appropriate sequence for a call. */
-
void
ia64_expand_call (retval, addr, nextarg, sibcall_p)
rtx retval;
rtx addr;
- rtx nextarg;
+ rtx nextarg ATTRIBUTE_UNUSED;
int sibcall_p;
{
- rtx insn, b0, pfs, gp_save, narg_rtx, dest;
- bool indirect_p;
- int narg;
+ rtx insn, b0;
addr = XEXP (addr, 0);
b0 = gen_rtx_REG (DImode, R_BR (0));
- pfs = gen_rtx_REG (DImode, AR_PFS_REGNUM);
-
- if (! nextarg)
- narg = 0;
- else if (IN_REGNO_P (REGNO (nextarg)))
- narg = REGNO (nextarg) - IN_REG (0);
- else
- narg = REGNO (nextarg) - OUT_REG (0);
- narg_rtx = GEN_INT (narg);
+ /* ??? Should do this for functions known to bind local too. */
if (TARGET_NO_PIC || TARGET_AUTO_PIC)
{
if (sibcall_p)
- insn = gen_sibcall_nopic (addr, narg_rtx, b0, pfs);
+ insn = gen_sibcall_nogp (addr);
else if (! retval)
- insn = gen_call_nopic (addr, narg_rtx, b0);
+ insn = gen_call_nogp (addr, b0);
else
- insn = gen_call_value_nopic (retval, addr, narg_rtx, b0);
- emit_call_insn (insn);
- return;
+ insn = gen_call_value_nogp (retval, addr, b0);
+ insn = emit_call_insn (insn);
}
-
- indirect_p = ! symbolic_operand (addr, VOIDmode);
-
- if (sibcall_p || (TARGET_CONST_GP && !indirect_p))
- gp_save = NULL_RTX;
else
- gp_save = ia64_gp_save_reg (setjmp_operand (addr, VOIDmode));
+ {
+ if (sibcall_p)
+ insn = gen_sibcall_gp (addr);
+ else if (! retval)
+ insn = gen_call_gp (addr, b0);
+ else
+ insn = gen_call_value_gp (retval, addr, b0);
+ insn = emit_call_insn (insn);
- if (gp_save)
- emit_move_insn (gp_save, pic_offset_table_rtx);
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
+ }
- /* If this is an indirect call, then we have the address of a descriptor. */
- if (indirect_p)
+ if (sibcall_p)
{
- dest = force_reg (DImode, gen_rtx_MEM (DImode, addr));
- emit_move_insn (pic_offset_table_rtx,
- gen_rtx_MEM (DImode, plus_constant (addr, 8)));
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), b0);
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn),
+ gen_rtx_REG (DImode, AR_PFS_REGNUM));
}
+}
+void
+ia64_reload_gp ()
+{
+ rtx tmp;
+
+ if (current_frame_info.reg_save_gp)
+ tmp = gen_rtx_REG (DImode, current_frame_info.reg_save_gp);
else
- dest = addr;
+ {
+ HOST_WIDE_INT offset;
+
+ offset = (current_frame_info.spill_cfa_off
+ + current_frame_info.spill_size);
+ if (frame_pointer_needed)
+ {
+ tmp = hard_frame_pointer_rtx;
+ offset = -offset;
+ }
+ else
+ {
+ tmp = stack_pointer_rtx;
+ offset = current_frame_info.total_size - offset;
+ }
+
+ if (CONST_OK_FOR_I (offset))
+ emit_insn (gen_adddi3 (pic_offset_table_rtx,
+ tmp, GEN_INT (offset)));
+ else
+ {
+ emit_move_insn (pic_offset_table_rtx, GEN_INT (offset));
+ emit_insn (gen_adddi3 (pic_offset_table_rtx,
+ pic_offset_table_rtx, tmp));
+ }
+
+ tmp = gen_rtx_MEM (DImode, pic_offset_table_rtx);
+ }
+
+ emit_move_insn (pic_offset_table_rtx, tmp);
+}
+
+void
+ia64_split_call (retval, addr, retaddr, scratch_r, scratch_b,
+ noreturn_p, sibcall_p)
+ rtx retval, addr, retaddr, scratch_r, scratch_b;
+ int noreturn_p, sibcall_p;
+{
+ rtx insn;
+ bool is_desc = false;
+
+ /* If we find we're calling through a register, then we're actually
+ calling through a descriptor, so load up the values. */
+ if (REG_P (addr))
+ {
+ rtx tmp;
+ bool addr_dead_p;
+
+ /* ??? We are currently constrained to *not* use peep2, because
+ we can legitimiately change the global lifetime of the GP
+ (in the form of killing where previously live). This is
+ because a call through a descriptor doesn't use the previous
+ value of the GP, while a direct call does, and we do not
+ commit to either form until the split here.
+
+ That said, this means that we lack precise life info for
+ whether ADDR is dead after this call. This is not terribly
+ important, since we can fix things up essentially for free
+ with the POST_DEC below, but it's nice to not use it when we
+ can immediately tell it's not necessary. */
+ addr_dead_p = ((noreturn_p || sibcall_p
+ || TEST_HARD_REG_BIT (regs_invalidated_by_call,
+ REGNO (addr)))
+ && !FUNCTION_ARG_REGNO_P (REGNO (addr)));
+
+ /* Load the code address into scratch_b. */
+ tmp = gen_rtx_POST_INC (Pmode, addr);
+ tmp = gen_rtx_MEM (Pmode, tmp);
+ emit_move_insn (scratch_r, tmp);
+ emit_move_insn (scratch_b, scratch_r);
+
+ /* Load the GP address. If ADDR is not dead here, then we must
+ revert the change made above via the POST_INCREMENT. */
+ if (!addr_dead_p)
+ tmp = gen_rtx_POST_DEC (Pmode, addr);
+ else
+ tmp = addr;
+ tmp = gen_rtx_MEM (Pmode, tmp);
+ emit_move_insn (pic_offset_table_rtx, tmp);
+
+ is_desc = true;
+ addr = scratch_b;
+ }
if (sibcall_p)
- insn = gen_sibcall_pic (dest, narg_rtx, b0, pfs);
- else if (! retval)
- insn = gen_call_pic (dest, narg_rtx, b0);
+ insn = gen_sibcall_nogp (addr);
+ else if (retval)
+ insn = gen_call_value_nogp (retval, addr, retaddr);
else
- insn = gen_call_value_pic (retval, dest, narg_rtx, b0);
+ insn = gen_call_nogp (addr, retaddr);
emit_call_insn (insn);
- if (gp_save)
- emit_move_insn (pic_offset_table_rtx, gp_save);
+ if ((!TARGET_CONST_GP || is_desc) && !noreturn_p && !sibcall_p)
+ ia64_reload_gp ();
}
/* Begin the assembly file. */
@@ -1240,39 +1613,6 @@ emit_safe_across_calls (f)
fputc ('\n', f);
}
-
-/* Structure to be filled in by ia64_compute_frame_size with register
- save masks and offsets for the current function. */
-
-struct ia64_frame_info
-{
- HOST_WIDE_INT total_size; /* size of the stack frame, not including
- the caller's scratch area. */
- HOST_WIDE_INT spill_cfa_off; /* top of the reg spill area from the cfa. */
- HOST_WIDE_INT spill_size; /* size of the gr/br/fr spill area. */
- HOST_WIDE_INT extra_spill_size; /* size of spill area for others. */
- HARD_REG_SET mask; /* mask of saved registers. */
- unsigned int gr_used_mask; /* mask of registers in use as gr spill
- registers or long-term scratches. */
- int n_spilled; /* number of spilled registers. */
- int reg_fp; /* register for fp. */
- int reg_save_b0; /* save register for b0. */
- int reg_save_pr; /* save register for prs. */
- int reg_save_ar_pfs; /* save register for ar.pfs. */
- int reg_save_ar_unat; /* save register for ar.unat. */
- int reg_save_ar_lc; /* save register for ar.lc. */
- int n_input_regs; /* number of input registers used. */
- int n_local_regs; /* number of local registers used. */
- int n_output_regs; /* number of output registers used. */
- int n_rotate_regs; /* number of rotating registers used. */
-
- char need_regstk; /* true if a .regstk directive needed. */
- char initialized; /* true if the data is finalized. */
-};
-
-/* Current frame information calculated by ia64_compute_frame_size. */
-static struct ia64_frame_info current_frame_info;
-
/* Helper function for ia64_compute_frame_size: find an appropriate general
register to spill some special register to. SPECIAL_SPILL_MASK contains
bits in GR0 to GR31 that have already been allocated by this routine.
@@ -1514,6 +1854,17 @@ ia64_compute_frame_size (size)
extra_spill_size += 8;
n_spilled += 1;
}
+
+ /* Similarly for gp. Note that if we're calling setjmp, the stacked
+ registers are clobbered, so we fall back to the stack. */
+ current_frame_info.reg_save_gp
+ = (current_function_calls_setjmp ? 0 : find_gr_spill (1));
+ if (current_frame_info.reg_save_gp == 0)
+ {
+ SET_HARD_REG_BIT (mask, GR_REG (1));
+ spill_size += 8;
+ n_spilled += 1;
+ }
}
else
{
@@ -1523,6 +1874,17 @@ ia64_compute_frame_size (size)
spill_size += 8;
n_spilled += 1;
}
+
+ if (regs_ever_live[AR_PFS_REGNUM])
+ {
+ SET_HARD_REG_BIT (mask, AR_PFS_REGNUM);
+ current_frame_info.reg_save_ar_pfs = find_gr_spill (1);
+ if (current_frame_info.reg_save_ar_pfs == 0)
+ {
+ extra_spill_size += 8;
+ n_spilled += 1;
+ }
+ }
}
/* Unwind descriptor hackery: things are most efficient if we allocate
@@ -1561,8 +1923,10 @@ ia64_compute_frame_size (size)
}
/* If we're forced to use st8.spill, we're forced to save and restore
- ar.unat as well. */
- if (spilled_gr_p || cfun->machine->n_varargs)
+ ar.unat as well. The check for existing liveness allows inline asm
+ to touch ar.unat. */
+ if (spilled_gr_p || cfun->machine->n_varargs
+ || regs_ever_live[AR_UNAT_REGNUM])
{
regs_ever_live[AR_UNAT_REGNUM] = 1;
SET_HARD_REG_BIT (mask, AR_UNAT_REGNUM);
@@ -1796,7 +2160,7 @@ spill_restore_mem (reg, cfa_off)
spill_fill_data.init_reg[iter],
disp_rtx));
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
}
@@ -2023,7 +2387,8 @@ ia64_expand_prologue ()
/* We don't need an alloc instruction if we've used no outputs or locals. */
if (current_frame_info.n_local_regs == 0
&& current_frame_info.n_output_regs == 0
- && current_frame_info.n_input_regs <= current_function_args_info.int_regs)
+ && current_frame_info.n_input_regs <= current_function_args_info.int_regs
+ && !TEST_HARD_REG_BIT (current_frame_info.mask, AR_PFS_REGNUM))
{
/* If there is no alloc, but there are input registers used, then we
need a .regstk directive. */
@@ -2185,8 +2550,8 @@ ia64_expand_prologue ()
/* The alloc insn already copied ar.pfs into a general register. The
only thing we have to do now is copy that register to a stack slot
if we'd not allocated a local register for the job. */
- if (current_frame_info.reg_save_ar_pfs == 0
- && ! current_function_is_leaf)
+ if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_PFS_REGNUM)
+ && current_frame_info.reg_save_ar_pfs == 0)
{
reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
do_spill (gen_movdi_x, ar_pfs_save_reg, cfa_off, reg);
@@ -2217,6 +2582,19 @@ ia64_expand_prologue ()
}
}
+ if (current_frame_info.reg_save_gp)
+ {
+ insn = emit_move_insn (gen_rtx_REG (DImode,
+ current_frame_info.reg_save_gp),
+ pic_offset_table_rtx);
+ /* We don't know for sure yet if this is actually needed, since
+ we've not split the PIC call patterns. If all of the calls
+ are indirect, and not followed by any uses of the gp, then
+ this save is dead. Allow it to go away. */
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, REG_NOTES (insn));
+ }
+
/* We should now be at the base of the gr/br/fr spill area. */
if (cfa_off != (current_frame_info.spill_cfa_off
+ current_frame_info.spill_size))
@@ -2398,8 +2776,13 @@ ia64_expand_epilogue (sibcall_p)
+ current_frame_info.spill_size))
abort ();
+ /* The GP may be stored on the stack in the prologue, but it's
+ never restored in the epilogue. Skip the stack slot. */
+ if (TEST_HARD_REG_BIT (current_frame_info.mask, GR_REG (1)))
+ cfa_off -= 8;
+
/* Restore all general registers. */
- for (regno = GR_REG (1); regno <= GR_REG (31); ++regno)
+ for (regno = GR_REG (2); regno <= GR_REG (31); ++regno)
if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
{
reg = gen_rtx_REG (DImode, regno);
@@ -2587,10 +2970,6 @@ ia64_hard_regno_rename_ok (from, to)
if (PR_REGNO_P (from) && PR_REGNO_P (to))
return (from & 1) == (to & 1);
- /* Reg 4 contains the saved gp; we can't reliably rename this. */
- if (from == GR_REG (4) && current_function_calls_setjmp)
- return 0;
-
return 1;
}
@@ -2603,12 +2982,16 @@ ia64_assemble_integer (x, size, aligned_p)
unsigned int size;
int aligned_p;
{
- if (size == UNITS_PER_WORD && aligned_p
+ if (size == (TARGET_ILP32 ? 4 : 8)
+ && aligned_p
&& !(TARGET_NO_PIC || TARGET_AUTO_PIC)
&& GET_CODE (x) == SYMBOL_REF
&& SYMBOL_REF_FLAG (x))
{
- fputs ("\tdata8\t@fptr(", asm_out_file);
+ if (TARGET_ILP32)
+ fputs ("\tdata4\t@fptr(", asm_out_file);
+ else
+ fputs ("\tdata8\t@fptr(", asm_out_file);
output_addr_const (asm_out_file, x);
fputs (")\n", asm_out_file);
return true;
@@ -2796,9 +3179,8 @@ ia64_setup_incoming_varargs (cum, int_mode, type, pretend_size, second_time)
int * pretend_size;
int second_time ATTRIBUTE_UNUSED;
{
- /* If this is a stdarg function, then skip the current argument. */
- if (! current_function_varargs)
- ia64_function_arg_advance (&cum, int_mode, type, 1);
+ /* Skip the current argument. */
+ ia64_function_arg_advance (&cum, int_mode, type, 1);
if (cum.words < MAX_ARGUMENT_SLOTS)
{
@@ -2840,17 +3222,17 @@ hfa_element_mode (type, nested)
gcc's COMPLEX_TYPEs as HFAs. We need to exclude the integral complex
types though. */
case COMPLEX_TYPE:
- if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT)
+ if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT
+ && (TYPE_MODE (type) != TCmode || INTEL_EXTENDED_IEEE_FORMAT))
return mode_for_size (GET_MODE_UNIT_SIZE (TYPE_MODE (type))
* BITS_PER_UNIT, MODE_FLOAT, 0);
else
return VOIDmode;
case REAL_TYPE:
- /* ??? Should exclude 128-bit long double here. */
/* We want to return VOIDmode for raw REAL_TYPEs, but the actual
mode if this is contained within an aggregate. */
- if (nested)
+ if (nested && (TYPE_MODE (type) != TFmode || INTEL_EXTENDED_IEEE_FORMAT))
return TYPE_MODE (type);
else
return VOIDmode;
@@ -3024,7 +3406,25 @@ ia64_function_arg (cum, mode, type, named, incoming)
happen when we have a SFmode HFA. */
else if (((mode == TFmode) && ! INTEL_EXTENDED_IEEE_FORMAT)
|| (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
- return gen_rtx_REG (mode, basereg + cum->words + offset);
+ {
+ int byte_size = ((mode == BLKmode)
+ ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
+ if (BYTES_BIG_ENDIAN
+ && (mode == BLKmode || (type && AGGREGATE_TYPE_P (type)))
+ && byte_size < UNITS_PER_WORD
+ && byte_size > 0)
+ {
+ rtx gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (DImode,
+ (basereg + cum->words
+ + offset)),
+ const0_rtx);
+ return gen_rtx_PARALLEL (mode, gen_rtvec (1, gr_reg));
+ }
+ else
+ return gen_rtx_REG (mode, basereg + cum->words + offset);
+
+ }
/* If there is a prototype, then FP values go in a FR register when
named, and in a GR registeer when unnamed. */
@@ -3199,27 +3599,6 @@ ia64_function_arg_pass_by_reference (cum, mode, type, named)
return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
}
-/* Implement va_start. */
-
-void
-ia64_va_start (stdarg_p, valist, nextarg)
- int stdarg_p;
- tree valist;
- rtx nextarg;
-{
- int arg_words;
- int ofs;
-
- arg_words = current_function_args_info.words;
-
- if (stdarg_p)
- ofs = 0;
- else
- ofs = (arg_words >= MAX_ARGUMENT_SLOTS ? -UNITS_PER_WORD : 0);
-
- nextarg = plus_constant (nextarg, ofs);
- std_expand_builtin_va_start (1, valist, nextarg);
-}
/* Implement va_arg. */
@@ -3332,7 +3711,30 @@ ia64_function_value (valtype, func)
((mode != TFmode) || INTEL_EXTENDED_IEEE_FORMAT))
return gen_rtx_REG (mode, FR_ARG_FIRST);
else
- return gen_rtx_REG (mode, GR_RET_FIRST);
+ {
+ if (BYTES_BIG_ENDIAN
+ && (mode == BLKmode || (valtype && AGGREGATE_TYPE_P (valtype))))
+ {
+ rtx loc[8];
+ int offset;
+ int bytesize;
+ int i;
+
+ offset = 0;
+ bytesize = int_size_in_bytes (valtype);
+ for (i = 0; offset < bytesize; i++)
+ {
+ loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (DImode,
+ GR_RET_FIRST + i),
+ GEN_INT (offset));
+ offset += UNITS_PER_WORD;
+ }
+ return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+ }
+ else
+ return gen_rtx_REG (mode, GR_RET_FIRST);
+ }
}
/* Print a memory address as an operand to reference that memory location. */
@@ -3777,7 +4179,6 @@ ia64_secondary_reload_class (class, mode, x)
return NO_REGS;
}
-
/* Emit text to declare externally defined variables and functions, because
the Intel assembler does not support undefined externals. */
@@ -3790,8 +4191,13 @@ ia64_asm_output_external (file, decl, name)
{
int save_referenced;
- /* GNU as does not need anything here. */
- if (TARGET_GNU_AS)
+ /* GNU as does not need anything here, but the HP linker does need
+ something for external functions. */
+
+ if (TARGET_GNU_AS
+ && (!TARGET_HPUX_LD
+ || TREE_CODE (decl) != FUNCTION_DECL
+ || strstr(name, "__builtin_") == name))
return;
/* ??? The Intel assembler creates a reference that needs to be satisfied by
@@ -3806,19 +4212,18 @@ ia64_asm_output_external (file, decl, name)
|| ! strcmp (name, "__builtin_args_info"))
return;
- /* assemble_name will set TREE_SYMBOL_REFERENCED, so we must save and
- restore it. */
- save_referenced = TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl));
- if (TREE_CODE (decl) == FUNCTION_DECL)
+ if (TARGET_HPUX_LD)
+ ia64_hpux_add_extern_decl (name);
+ else
{
- fprintf (file, "%s", TYPE_ASM_OP);
- assemble_name (file, name);
- putc (',', file);
- fprintf (file, TYPE_OPERAND_FMT, "function");
- putc ('\n', file);
+ /* assemble_name will set TREE_SYMBOL_REFERENCED, so we must save and
+ restore it. */
+ save_referenced = TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl));
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
+ (*targetm.asm_out.globalize_label) (file, name);
+ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = save_referenced;
}
- ASM_GLOBALIZE_LABEL (file, name);
- TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = save_referenced;
}
/* Parse the -mfixed-range= option string. */
@@ -3887,44 +4292,10 @@ fix_range (const_str)
}
}
-/* Called to register all of our global variables with the garbage
- collector. */
-
-static void
-ia64_add_gc_roots ()
-{
- ggc_add_rtx_root (&ia64_compare_op0, 1);
- ggc_add_rtx_root (&ia64_compare_op1, 1);
-}
-
-static void
-ia64_init_machine_status (p)
- struct function *p;
-{
- p->machine =
- (struct machine_function *) xcalloc (1, sizeof (struct machine_function));
-}
-
-static void
-ia64_mark_machine_status (p)
- struct function *p;
-{
- struct machine_function *machine = p->machine;
-
- if (machine)
- {
- ggc_mark_rtx (machine->ia64_eh_epilogue_sp);
- ggc_mark_rtx (machine->ia64_eh_epilogue_bsp);
- ggc_mark_rtx (machine->ia64_gp_save);
- }
-}
-
-static void
-ia64_free_machine_status (p)
- struct function *p;
+static struct machine_function *
+ia64_init_machine_status ()
{
- free (p->machine);
- p->machine = NULL;
+ return ggc_alloc_cleared (sizeof (struct machine_function));
}
/* Handle TARGET_OPTIONS switches. */
@@ -3935,25 +4306,41 @@ ia64_override_options ()
if (TARGET_AUTO_PIC)
target_flags |= MASK_CONST_GP;
- if (TARGET_INLINE_DIV_LAT && TARGET_INLINE_DIV_THR)
+ if (TARGET_INLINE_FLOAT_DIV_LAT && TARGET_INLINE_FLOAT_DIV_THR)
+ {
+ warning ("cannot optimize floating point division for both latency and throughput");
+ target_flags &= ~MASK_INLINE_FLOAT_DIV_THR;
+ }
+
+ if (TARGET_INLINE_INT_DIV_LAT && TARGET_INLINE_INT_DIV_THR)
{
- warning ("cannot optimize division for both latency and throughput");
- target_flags &= ~MASK_INLINE_DIV_THR;
+ warning ("cannot optimize integer division for both latency and throughput");
+ target_flags &= ~MASK_INLINE_INT_DIV_THR;
}
if (ia64_fixed_range_string)
fix_range (ia64_fixed_range_string);
+ if (ia64_tls_size_string)
+ {
+ char *end;
+ unsigned long tmp = strtoul (ia64_tls_size_string, &end, 10);
+ if (*end || (tmp != 14 && tmp != 22 && tmp != 64))
+ error ("bad value (%s) for -mtls-size= switch", ia64_tls_size_string);
+ else
+ ia64_tls_size = tmp;
+ }
+
ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload;
flag_schedule_insns_after_reload = 0;
ia64_section_threshold = g_switch_set ? g_switch_value : IA64_DEFAULT_GVALUE;
init_machine_status = ia64_init_machine_status;
- mark_machine_status = ia64_mark_machine_status;
- free_machine_status = ia64_free_machine_status;
- ia64_add_gc_roots ();
+ /* Tell the compiler which flavor of TFmode we're using. */
+ if (INTEL_EXTENDED_IEEE_FORMAT)
+ real_format_for_mode[TFmode - QFmode] = &ieee_extended_intel_128_format;
}
static enum attr_itanium_requires_unit0 ia64_safe_itanium_requires_unit0 PARAMS((rtx));
@@ -4564,8 +4951,22 @@ rtx_needs_barrier (x, flags, pred)
case UNSPEC:
switch (XINT (x, 1))
{
- case 1: /* st8.spill */
- case 2: /* ld8.fill */
+ case UNSPEC_LTOFF_DTPMOD:
+ case UNSPEC_LTOFF_DTPREL:
+ case UNSPEC_DTPREL:
+ case UNSPEC_LTOFF_TPREL:
+ case UNSPEC_TPREL:
+ case UNSPEC_PRED_REL_MUTEX:
+ case UNSPEC_PIC_CALL:
+ case UNSPEC_MF:
+ case UNSPEC_FETCHADD_ACQ:
+ case UNSPEC_BSP_VALUE:
+ case UNSPEC_FLUSHRS:
+ case UNSPEC_BUNDLE_SELECTOR:
+ break;
+
+ case UNSPEC_GR_SPILL:
+ case UNSPEC_GR_RESTORE:
{
HOST_WIDE_INT offset = INTVAL (XVECEXP (x, 0, 1));
HOST_WIDE_INT bit = (offset >> 3) & 63;
@@ -4577,32 +4978,22 @@ rtx_needs_barrier (x, flags, pred)
break;
}
- case 3: /* stf.spill */
- case 4: /* ldf.spill */
- case 8: /* popcnt */
+ case UNSPEC_FR_SPILL:
+ case UNSPEC_FR_RESTORE:
+ case UNSPEC_POPCNT:
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
break;
- case 7: /* pred_rel_mutex */
- case 9: /* pic call */
- case 12: /* mf */
- case 19: /* fetchadd_acq */
- case 20: /* mov = ar.bsp */
- case 21: /* flushrs */
- case 22: /* bundle selector */
- case 23: /* cycle display */
- break;
-
- case 24: /* addp4 */
+ case UNSPEC_ADDP4:
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
break;
- case 5: /* recip_approx */
+ case UNSPEC_FR_RECIP_APPROX:
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
need_barrier |= rtx_needs_barrier (XVECEXP (x, 0, 1), flags, pred);
break;
- case 13: /* cmpxchg_acq */
+ case UNSPEC_CMPXCHG_ACQ:
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 1), flags, pred);
need_barrier |= rtx_needs_barrier (XVECEXP (x, 0, 2), flags, pred);
break;
@@ -4615,7 +5006,7 @@ rtx_needs_barrier (x, flags, pred)
case UNSPEC_VOLATILE:
switch (XINT (x, 1))
{
- case 0: /* alloc */
+ case UNSPECV_ALLOC:
/* Alloc must always be the first instruction of a group.
We force this by always returning true. */
/* ??? We might get better scheduling if we explicitly check for
@@ -4629,17 +5020,15 @@ rtx_needs_barrier (x, flags, pred)
rws_access_regno (REG_AR_CFM, new_flags, pred);
return 1;
- case 1: /* blockage */
- case 2: /* insn group barrier */
- return 0;
-
- case 5: /* set_bsp */
+ case UNSPECV_SET_BSP:
need_barrier = 1;
break;
- case 7: /* pred.rel.mutex */
- case 8: /* safe_across_calls all */
- case 9: /* safe_across_calls normal */
+ case UNSPECV_BLOCKAGE:
+ case UNSPECV_INSN_GROUP_BARRIER:
+ case UNSPECV_BREAK:
+ case UNSPECV_PSAC_ALL:
+ case UNSPECV_PSAC_NORMAL:
return 0;
default:
@@ -4866,7 +5255,7 @@ emit_insn_group_barriers (dump, insns)
}
else if (GET_CODE (insn) == INSN
&& GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
- && XINT (PATTERN (insn), 1) == 2)
+ && XINT (PATTERN (insn), 1) == UNSPECV_INSN_GROUP_BARRIER)
{
init_insn_group_barriers ();
last_label = 0;
@@ -5328,7 +5717,9 @@ ia64_adjust_cost (insn, link, dep_insn, cost)
addr = XVECEXP (addr, 0, 0);
while (GET_CODE (addr) == SUBREG || GET_CODE (addr) == ZERO_EXTEND)
addr = XEXP (addr, 0);
- if (GET_CODE (addr) == MEM)
+
+ /* Note that LO_SUM is used for GOT loads. */
+ if (GET_CODE (addr) == MEM || GET_CODE (addr) == LO_SUM)
addr = XEXP (addr, 0);
else
addr = 0;
@@ -5470,18 +5861,13 @@ insn_matches_slot (p, itype, slot, insn)
return 0;
}
-/* Like emit_insn_before, but skip cycle_display insns. This makes the
- assembly output a bit prettier. */
+/* Like emit_insn_before, but skip cycle_display notes.
+ ??? When cycle display notes are implemented, update this. */
static void
ia64_emit_insn_before (insn, before)
rtx insn, before;
{
- rtx prev = PREV_INSN (before);
- if (prev && GET_CODE (prev) == INSN
- && GET_CODE (PATTERN (prev)) == UNSPEC
- && XINT (PATTERN (prev), 1) == 23)
- before = prev;
emit_insn_before (insn, before);
}
@@ -6376,9 +6762,11 @@ ia64_sched_reorder2 (dump, sched_verbose, ready, pn_ready, clock_var)
abort ();
insn_code = recog_memoized (stop);
- /* Ignore cycle displays and .pred.rel.mutex. */
- if (insn_code == CODE_FOR_cycle_display
- || insn_code == CODE_FOR_pred_rel_mutex
+ /* Ignore .pred.rel.mutex.
+
+ ??? Update this to ignore cycle display notes too
+ ??? once those are implemented */
+ if (insn_code == CODE_FOR_pred_rel_mutex
|| insn_code == CODE_FOR_prologue_use)
continue;
@@ -6532,17 +6920,6 @@ ia64_sched_finish (dump, sched_verbose)
free (sched_types);
free (sched_ready);
}
-
-static rtx
-ia64_cycle_display (clock, last)
- int clock;
- rtx last;
-{
- if (ia64_final_schedule)
- return emit_insn_after (gen_cycle_display (GEN_INT (clock)), last);
- else
- return last;
-}
/* Emit pseudo-ops for the assembler to describe predicate relations.
At present this assumes that we only consider predicate pairs to
@@ -6552,11 +6929,10 @@ ia64_cycle_display (clock, last)
static void
emit_predicate_relation_info ()
{
- int i;
+ basic_block bb;
- for (i = n_basic_blocks - 1; i >= 0; --i)
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block bb = BASIC_BLOCK (i);
int r;
rtx head = bb->head;
@@ -6582,9 +6958,8 @@ emit_predicate_relation_info ()
relations around them. Otherwise the assembler will assume the call
returns, and complain about uses of call-clobbered predicates after
the call. */
- for (i = n_basic_blocks - 1; i >= 0; --i)
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block bb = BASIC_BLOCK (i);
rtx insn = bb->head;
while (1)
@@ -6649,7 +7024,7 @@ ia64_emit_nops ()
pat = INSN_P (insn) ? PATTERN (insn) : const0_rtx;
if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
continue;
- if ((GET_CODE (pat) == UNSPEC && XINT (pat, 1) == 22)
+ if ((GET_CODE (pat) == UNSPEC && XINT (pat, 1) == UNSPEC_BUNDLE_SELECTOR)
|| GET_CODE (insn) == CODE_LABEL)
{
if (b)
@@ -6665,7 +7040,8 @@ ia64_emit_nops ()
bundle_pos = 0;
continue;
}
- else if (GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == 2)
+ else if (GET_CODE (pat) == UNSPEC_VOLATILE
+ && XINT (pat, 1) == UNSPECV_INSN_GROUP_BARRIER)
{
int t = INTVAL (XVECEXP (pat, 0, 0));
if (b)
@@ -6718,14 +7094,17 @@ void
ia64_reorg (insns)
rtx insns;
{
+ /* We are freeing block_for_insn in the toplev to keep compatibility
+ with old MDEP_REORGS that are not CFG based. Recompute it now. */
+ compute_bb_for_insn ();
+
/* If optimizing, we'll have split before scheduling. */
if (optimize == 0)
- split_all_insns_noflow ();
+ split_all_insns (0);
- /* Make sure the CFG and global_live_at_start are correct
- for emit_predicate_relation_info. */
- find_basic_blocks (insns, max_reg_num (), NULL);
- life_analysis (insns, NULL, PROP_DEATH_NOTES);
+ /* ??? update_life_info_in_dirty_blocks fails to terminate during
+ non-optimizing bootstrap. */
+ update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
if (ia64_flag_schedule_insns2)
{
@@ -6756,7 +7135,7 @@ ia64_reorg (insns)
insn = prev_active_insn (insn);
if (GET_CODE (insn) == INSN
&& GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
- && XINT (PATTERN (insn), 1) == 2)
+ && XINT (PATTERN (insn), 1) == UNSPECV_INSN_GROUP_BARRIER)
{
saw_stop = 1;
insn = prev_active_insn (insn);
@@ -6861,17 +7240,42 @@ ia64_eh_uses (regno)
code faster because there is one less load. This also includes incomplete
types which can't go in sdata/sbss. */
-/* ??? See select_section. We must put short own readonly variables in
- sdata/sbss instead of the more natural rodata, because we can't perform
- the DECL_READONLY_SECTION test here. */
+static bool
+ia64_in_small_data_p (exp)
+ tree exp;
+{
+ if (TARGET_NO_SDATA)
+ return false;
-extern struct obstack * saveable_obstack;
+ if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
+ {
+ const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
+ if (strcmp (section, ".sdata") == 0
+ || strcmp (section, ".sbss") == 0)
+ return true;
+ }
+ else
+ {
+ HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
-void
-ia64_encode_section_info (decl)
+ /* If this is an incomplete type with size 0, then we can't put it
+ in sdata because it might be too big when completed. */
+ if (size > 0 && size <= ia64_section_threshold)
+ return true;
+ }
+
+ return false;
+}
+
+static void
+ia64_encode_section_info (decl, first)
tree decl;
+ int first ATTRIBUTE_UNUSED;
{
const char *symbol_str;
+ bool is_local;
+ rtx symbol;
+ char encoding = 0;
if (TREE_CODE (decl) == FUNCTION_DECL)
{
@@ -6884,83 +7288,86 @@ ia64_encode_section_info (decl)
|| GET_CODE (DECL_RTL (decl)) != MEM
|| GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
return;
-
- symbol_str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
-
- /* We assume that -fpic is used only to create a shared library (dso).
- With -fpic, no global data can ever be sdata.
- Without -fpic, global common uninitialized data can never be sdata, since
- it can unify with a real definition in a dso. */
- /* ??? Actually, we can put globals in sdata, as long as we don't use gprel
- to access them. The linker may then be able to do linker relaxation to
- optimize references to them. Currently sdata implies use of gprel. */
- /* We need the DECL_EXTERNAL check for C++. static class data members get
- both TREE_STATIC and DECL_EXTERNAL set, to indicate that they are
- statically allocated, but the space is allocated somewhere else. Such
- decls can not be own data. */
- if (! TARGET_NO_SDATA
- && TREE_STATIC (decl) && ! DECL_EXTERNAL (decl)
- && ! (DECL_ONE_ONLY (decl) || DECL_WEAK (decl))
- && ! (TREE_PUBLIC (decl)
- && (flag_pic
- || (DECL_COMMON (decl)
- && (DECL_INITIAL (decl) == 0
- || DECL_INITIAL (decl) == error_mark_node))))
- /* Either the variable must be declared without a section attribute,
- or the section must be sdata or sbss. */
- && (DECL_SECTION_NAME (decl) == 0
- || ! strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
- ".sdata")
- || ! strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
- ".sbss")))
- {
- HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
-
- /* If the variable has already been defined in the output file, then it
- is too late to put it in sdata if it wasn't put there in the first
- place. The test is here rather than above, because if it is already
- in sdata, then it can stay there. */
-
- if (TREE_ASM_WRITTEN (decl))
- ;
-
- /* If this is an incomplete type with size 0, then we can't put it in
- sdata because it might be too big when completed. */
- else if (size > 0
- && size <= (HOST_WIDE_INT) ia64_section_threshold
- && symbol_str[0] != SDATA_NAME_FLAG_CHAR)
- {
- size_t len = strlen (symbol_str);
- char *newstr = alloca (len + 1);
- const char *string;
- *newstr = SDATA_NAME_FLAG_CHAR;
- memcpy (newstr + 1, symbol_str, len + 1);
-
- string = ggc_alloc_string (newstr, len + 1);
- XSTR (XEXP (DECL_RTL (decl), 0), 0) = string;
- }
- }
- /* This decl is marked as being in small data/bss but it shouldn't
- be; one likely explanation for this is that the decl has been
- moved into a different section from the one it was in when
- ENCODE_SECTION_INFO was first called. Remove the '@'. */
- else if (symbol_str[0] == SDATA_NAME_FLAG_CHAR)
+ symbol = XEXP (DECL_RTL (decl), 0);
+ symbol_str = XSTR (symbol, 0);
+
+ is_local = (*targetm.binds_local_p) (decl);
+
+ if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
+ encoding = " GLil"[decl_tls_model (decl)];
+ /* Determine if DECL will wind up in .sdata/.sbss. */
+ else if (is_local && ia64_in_small_data_p (decl))
+ encoding = 's';
+
+ /* Finally, encode this into the symbol string. */
+ if (encoding)
{
- XSTR (XEXP (DECL_RTL (decl), 0), 0)
- = ggc_strdup (symbol_str + 1);
+ char *newstr;
+ size_t len;
+
+ if (symbol_str[0] == ENCODE_SECTION_INFO_CHAR)
+ {
+ if (encoding == symbol_str[1])
+ return;
+ /* ??? Sdata became thread or thread becaome not thread. Lose. */
+ abort ();
+ }
+
+ len = strlen (symbol_str);
+ newstr = alloca (len + 3);
+ newstr[0] = ENCODE_SECTION_INFO_CHAR;
+ newstr[1] = encoding;
+ memcpy (newstr + 2, symbol_str, len + 1);
+
+ XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2);
}
+
+ /* This decl is marked as being in small data/bss but it shouldn't be;
+ one likely explanation for this is that the decl has been moved into
+ a different section from the one it was in when encode_section_info
+ was first called. Remove the encoding. */
+ else if (symbol_str[0] == ENCODE_SECTION_INFO_CHAR)
+ XSTR (symbol, 0) = ggc_strdup (symbol_str + 2);
+}
+
+static const char *
+ia64_strip_name_encoding (str)
+ const char *str;
+{
+ if (str[0] == ENCODE_SECTION_INFO_CHAR)
+ str += 2;
+ if (str[0] == '*')
+ str++;
+ return str;
+}
+
+/* True if it is OK to do sibling call optimization for the specified
+ call expression EXP. DECL will be the called function, or NULL if
+ this is an indirect call. */
+bool
+ia64_function_ok_for_sibcall (decl)
+ tree decl;
+{
+ /* Direct calls are always ok. */
+ if (decl)
+ return true;
+
+ /* If TARGET_CONST_GP is in effect, then our caller expects us to
+ return with our current GP. This means that we'll always have
+ a GP reload after an indirect call. */
+ return !ia64_epilogue_uses (R_GR (1));
}
/* Output assembly directives for prologue regions. */
/* The current basic block number. */
-static int block_num;
+static bool last_block;
/* True if we need a copy_state command at the start of the next block. */
-static int need_copy_state;
+static bool need_copy_state;
/* The function emits unwind directives for the start of an epilogue. */
@@ -6970,10 +7377,10 @@ process_epilogue ()
/* If this isn't the last block of the function, then we need to label the
current state, and copy it back in at the start of the next block. */
- if (block_num != n_basic_blocks - 1)
+ if (!last_block)
{
fprintf (asm_out_file, "\t.label_state 1\n");
- need_copy_state = 1;
+ need_copy_state = true;
}
fprintf (asm_out_file, "\t.restore sp\n");
@@ -6993,7 +7400,7 @@ process_set (asm_out_file, pat)
/* Look for the ALLOC insn. */
if (GET_CODE (src) == UNSPEC_VOLATILE
- && XINT (src, 1) == 0
+ && XINT (src, 1) == UNSPECV_ALLOC
&& GET_CODE (dest) == REG)
{
dest_regno = REGNO (dest);
@@ -7211,18 +7618,18 @@ process_for_unwind_directive (asm_out_file, insn)
if (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
{
- block_num = NOTE_BASIC_BLOCK (insn)->index;
+ last_block = NOTE_BASIC_BLOCK (insn)->next_bb == EXIT_BLOCK_PTR;
/* Restore unwind state from immediately before the epilogue. */
if (need_copy_state)
{
fprintf (asm_out_file, "\t.body\n");
fprintf (asm_out_file, "\t.copy_state 1\n");
- need_copy_state = 0;
+ need_copy_state = false;
}
}
- if (! RTX_FRAME_RELATED_P (insn))
+ if (GET_CODE (insn) == NOTE || ! RTX_FRAME_RELATED_P (insn))
return;
pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
@@ -7262,55 +7669,43 @@ ia64_init_builtins ()
{
tree psi_type_node = build_pointer_type (integer_type_node);
tree pdi_type_node = build_pointer_type (long_integer_type_node);
- tree endlink = void_list_node;
/* __sync_val_compare_and_swap_si, __sync_bool_compare_and_swap_si */
tree si_ftype_psi_si_si
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, psi_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE,
- integer_type_node,
- endlink))));
+ = build_function_type_list (integer_type_node,
+ psi_type_node, integer_type_node,
+ integer_type_node, NULL_TREE);
/* __sync_val_compare_and_swap_di, __sync_bool_compare_and_swap_di */
tree di_ftype_pdi_di_di
- = build_function_type (long_integer_type_node,
- tree_cons (NULL_TREE, pdi_type_node,
- tree_cons (NULL_TREE,
- long_integer_type_node,
- tree_cons (NULL_TREE,
- long_integer_type_node,
- endlink))));
+ = build_function_type_list (long_integer_type_node,
+ pdi_type_node, long_integer_type_node,
+ long_integer_type_node, NULL_TREE);
/* __sync_synchronize */
tree void_ftype_void
- = build_function_type (void_type_node, endlink);
+ = build_function_type (void_type_node, void_list_node);
/* __sync_lock_test_and_set_si */
tree si_ftype_psi_si
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, psi_type_node,
- tree_cons (NULL_TREE, integer_type_node, endlink)));
+ = build_function_type_list (integer_type_node,
+ psi_type_node, integer_type_node, NULL_TREE);
/* __sync_lock_test_and_set_di */
tree di_ftype_pdi_di
- = build_function_type (long_integer_type_node,
- tree_cons (NULL_TREE, pdi_type_node,
- tree_cons (NULL_TREE, long_integer_type_node,
- endlink)));
+ = build_function_type_list (long_integer_type_node,
+ pdi_type_node, long_integer_type_node,
+ NULL_TREE);
/* __sync_lock_release_si */
tree void_ftype_psi
- = build_function_type (void_type_node, tree_cons (NULL_TREE, psi_type_node,
- endlink));
+ = build_function_type_list (void_type_node, psi_type_node, NULL_TREE);
/* __sync_lock_release_di */
tree void_ftype_pdi
- = build_function_type (void_type_node, tree_cons (NULL_TREE, pdi_type_node,
- endlink));
+ = build_function_type_list (void_type_node, pdi_type_node, NULL_TREE);
#define def_builtin(name, type, code) \
- builtin_function ((name), (type), (code), BUILT_IN_MD, NULL)
+ builtin_function ((name), (type), (code), BUILT_IN_MD, NULL, NULL_TREE)
def_builtin ("__sync_val_compare_and_swap_si", si_ftype_psi_si_si,
IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI);
@@ -7334,11 +7729,11 @@ ia64_init_builtins ()
IA64_BUILTIN_LOCK_RELEASE_DI);
def_builtin ("__builtin_ia64_bsp",
- build_function_type (ptr_type_node, endlink),
+ build_function_type (ptr_type_node, void_list_node),
IA64_BUILTIN_BSP);
def_builtin ("__builtin_ia64_flushrs",
- build_function_type (void_type_node, endlink),
+ build_function_type (void_type_node, void_list_node),
IA64_BUILTIN_FLUSHRS);
def_builtin ("__sync_fetch_and_add_si", si_ftype_psi_si,
@@ -7421,6 +7816,10 @@ ia64_expand_fetch_and_op (binoptab, mode, arglist, target)
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mem = expand_expr (arg0, NULL_RTX, Pmode, 0);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE(mem) != Pmode)
+ mem = convert_memory_address (Pmode, mem);
+#endif
value = expand_expr (arg1, NULL_RTX, mode, 0);
mem = gen_rtx_MEM (mode, force_reg (Pmode, mem));
@@ -7480,7 +7879,7 @@ ia64_expand_fetch_and_op (binoptab, mode, arglist, target)
do {
old = tmp;
ar.ccv = tmp;
- ret = tmp + value;
+ ret = tmp <op> value;
cmpxchgsz.acq tmp = [ptr], ret
} while (tmp != old)
*/
@@ -7498,6 +7897,11 @@ ia64_expand_op_and_fetch (binoptab, mode, arglist, target)
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mem = expand_expr (arg0, NULL_RTX, Pmode, 0);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE(mem) != Pmode)
+ mem = convert_memory_address (Pmode, mem);
+#endif
+
value = expand_expr (arg1, NULL_RTX, mode, 0);
mem = gen_rtx_MEM (mode, force_reg (Pmode, mem));
@@ -7561,11 +7965,11 @@ ia64_expand_compare_and_swap (mode, boolp, arglist, target)
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- mem = expand_expr (arg0, NULL_RTX, Pmode, 0);
+ mem = expand_expr (arg0, NULL_RTX, ptr_mode, 0);
old = expand_expr (arg1, NULL_RTX, mode, 0);
new = expand_expr (arg2, NULL_RTX, mode, 0);
- mem = gen_rtx_MEM (mode, force_reg (Pmode, mem));
+ mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
MEM_VOLATILE_P (mem) = 1;
if (! register_operand (old, mode))
@@ -7578,8 +7982,15 @@ ia64_expand_compare_and_swap (mode, boolp, arglist, target)
else
tmp = gen_reg_rtx (mode);
- ccv = gen_rtx_REG (mode, AR_CCV_REGNUM);
- emit_move_insn (ccv, old);
+ ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
+ if (mode == DImode)
+ emit_move_insn (ccv, old);
+ else
+ {
+ rtx ccvtmp = gen_reg_rtx (DImode);
+ emit_insn (gen_zero_extendsidi2 (ccvtmp, old));
+ emit_move_insn (ccv, ccvtmp);
+ }
emit_insn (gen_mf ());
if (mode == SImode)
insn = gen_cmpxchg_acq_si (tmp, mem, new, ccv);
@@ -7610,10 +8021,10 @@ ia64_expand_lock_test_and_set (mode, arglist, target)
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- mem = expand_expr (arg0, NULL_RTX, Pmode, 0);
+ mem = expand_expr (arg0, NULL_RTX, ptr_mode, 0);
new = expand_expr (arg1, NULL_RTX, mode, 0);
- mem = gen_rtx_MEM (mode, force_reg (Pmode, mem));
+ mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
MEM_VOLATILE_P (mem) = 1;
if (! register_operand (new, mode))
new = copy_to_mode_reg (mode, new);
@@ -7644,9 +8055,9 @@ ia64_expand_lock_release (mode, arglist, target)
rtx mem;
arg0 = TREE_VALUE (arglist);
- mem = expand_expr (arg0, NULL_RTX, Pmode, 0);
+ mem = expand_expr (arg0, NULL_RTX, ptr_mode, 0);
- mem = gen_rtx_MEM (mode, force_reg (Pmode, mem));
+ mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
MEM_VOLATILE_P (mem) = 1;
emit_move_insn (mem, const0_rtx);
@@ -7820,3 +8231,221 @@ ia64_hpux_function_arg_padding (mode, type)
: GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)
? downward : upward);
}
+
+/* Linked list of all external functions that are to be emitted by GCC.
+ We output the name if and only if TREE_SYMBOL_REFERENCED is set in
+ order to avoid putting out names that are never really used. */
+
+struct extern_func_list
+{
+ struct extern_func_list *next; /* next external */
+ char *name; /* name of the external */
+} *extern_func_head = 0;
+
+static void
+ia64_hpux_add_extern_decl (name)
+ const char *name;
+{
+ struct extern_func_list *p;
+
+ p = (struct extern_func_list *) xmalloc (sizeof (struct extern_func_list));
+ p->name = xmalloc (strlen (name) + 1);
+ strcpy(p->name, name);
+ p->next = extern_func_head;
+ extern_func_head = p;
+}
+
+/* Print out the list of used global functions. */
+
+void
+ia64_hpux_asm_file_end (file)
+ FILE *file;
+{
+ while (extern_func_head)
+ {
+ const char *real_name;
+ tree decl;
+
+ real_name = (* targetm.strip_name_encoding) (extern_func_head->name);
+ decl = maybe_get_identifier (real_name);
+
+ if (!decl
+ || (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl)))
+ {
+ if (decl)
+ TREE_ASM_WRITTEN (decl) = 1;
+ (*targetm.asm_out.globalize_label) (file, extern_func_head->name);
+ fprintf (file, "%s", TYPE_ASM_OP);
+ assemble_name (file, extern_func_head->name);
+ putc (',', file);
+ fprintf (file, TYPE_OPERAND_FMT, "function");
+ putc ('\n', file);
+ }
+ extern_func_head = extern_func_head->next;
+ }
+}
+
+
+/* Switch to the section to which we should output X. The only thing
+ special we do here is to honor small data. */
+
+static void
+ia64_select_rtx_section (mode, x, align)
+ enum machine_mode mode;
+ rtx x;
+ unsigned HOST_WIDE_INT align;
+{
+ if (GET_MODE_SIZE (mode) > 0
+ && GET_MODE_SIZE (mode) <= ia64_section_threshold)
+ sdata_section ();
+ else
+ default_elf_select_rtx_section (mode, x, align);
+}
+
+/* It is illegal to have relocations in shared segments on AIX and HPUX.
+ Pretend flag_pic is always set. */
+
+static void
+ia64_rwreloc_select_section (exp, reloc, align)
+ tree exp;
+ int reloc;
+ unsigned HOST_WIDE_INT align;
+{
+ default_elf_select_section_1 (exp, reloc, align, true);
+}
+
+static void
+ia64_rwreloc_unique_section (decl, reloc)
+ tree decl;
+ int reloc;
+{
+ default_unique_section_1 (decl, reloc, true);
+}
+
+static void
+ia64_rwreloc_select_rtx_section (mode, x, align)
+ enum machine_mode mode;
+ rtx x;
+ unsigned HOST_WIDE_INT align;
+{
+ int save_pic = flag_pic;
+ flag_pic = 1;
+ ia64_select_rtx_section (mode, x, align);
+ flag_pic = save_pic;
+}
+
+static unsigned int
+ia64_rwreloc_section_type_flags (decl, name, reloc)
+ tree decl;
+ const char *name;
+ int reloc;
+{
+ return default_section_type_flags_1 (decl, name, reloc, true);
+}
+
+
+/* Output the assembler code for a thunk function. THUNK_DECL is the
+ declaration for the thunk function itself, FUNCTION is the decl for
+ the target function. DELTA is an immediate constant offset to be
+ added to THIS. If VCALL_OFFSET is non-zero, the word at
+ *(*this + vcall_offset) should be added to THIS. */
+
+static void
+ia64_output_mi_thunk (file, thunk, delta, vcall_offset, function)
+ FILE *file;
+ tree thunk ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT delta;
+ HOST_WIDE_INT vcall_offset;
+ tree function;
+{
+ rtx this, insn, funexp;
+
+ reload_completed = 1;
+ no_new_pseudos = 1;
+
+ /* Set things up as ia64_expand_prologue might. */
+ last_scratch_gr_reg = 15;
+
+ memset (&current_frame_info, 0, sizeof (current_frame_info));
+ current_frame_info.spill_cfa_off = -16;
+ current_frame_info.n_input_regs = 1;
+ current_frame_info.need_regstk = (TARGET_REG_NAMES != 0);
+
+ if (!TARGET_REG_NAMES)
+ reg_names[IN_REG (0)] = ia64_reg_numbers[0];
+
+ /* Mark the end of the (empty) prologue. */
+ emit_note (NULL, NOTE_INSN_PROLOGUE_END);
+
+ this = gen_rtx_REG (Pmode, IN_REG (0));
+
+ /* Apply the constant offset, if required. */
+ if (delta)
+ {
+ rtx delta_rtx = GEN_INT (delta);
+
+ if (!CONST_OK_FOR_I (delta))
+ {
+ rtx tmp = gen_rtx_REG (Pmode, 2);
+ emit_move_insn (tmp, delta_rtx);
+ delta_rtx = tmp;
+ }
+ emit_insn (gen_adddi3 (this, this, delta_rtx));
+ }
+
+ /* Apply the offset from the vtable, if required. */
+ if (vcall_offset)
+ {
+ rtx vcall_offset_rtx = GEN_INT (vcall_offset);
+ rtx tmp = gen_rtx_REG (Pmode, 2);
+
+ emit_move_insn (tmp, gen_rtx_MEM (Pmode, this));
+
+ if (!CONST_OK_FOR_J (vcall_offset))
+ {
+ rtx tmp2 = gen_rtx_REG (Pmode, next_scratch_gr_reg ());
+ emit_move_insn (tmp2, vcall_offset_rtx);
+ vcall_offset_rtx = tmp2;
+ }
+ emit_insn (gen_adddi3 (tmp, tmp, vcall_offset_rtx));
+
+ emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
+
+ emit_insn (gen_adddi3 (this, this, tmp));
+ }
+
+ /* Generate a tail call to the target function. */
+ if (! TREE_USED (function))
+ {
+ assemble_external (function);
+ TREE_USED (function) = 1;
+ }
+ funexp = XEXP (DECL_RTL (function), 0);
+ funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
+ ia64_expand_call (NULL_RTX, funexp, NULL_RTX, 1);
+ insn = get_last_insn ();
+ SIBLING_CALL_P (insn) = 1;
+
+ /* Code generation for calls relies on splitting. */
+ reload_completed = 1;
+ try_split (PATTERN (insn), insn, 0);
+
+ emit_barrier ();
+
+ /* Run just enough of rest_of_compilation to get the insns emitted.
+ There's not really enough bulk here to make other passes such as
+ instruction scheduling worth while. Note that use_thunk calls
+ assemble_start_function and assemble_end_function. */
+
+ insn = get_insns ();
+ emit_all_insn_group_barriers (NULL, insn);
+ shorten_branches (insn);
+ final_start_function (insn, file, 1);
+ final (insn, file, 1, 0);
+ final_end_function ();
+
+ reload_completed = 0;
+ no_new_pseudos = 0;
+}
+
+#include "gt-ia64.h"
diff --git a/contrib/gcc/config/ia64/ia64.h b/contrib/gcc/config/ia64/ia64.h
index f69983b..724405a 100644
--- a/contrib/gcc/config/ia64/ia64.h
+++ b/contrib/gcc/config/ia64/ia64.h
@@ -31,14 +31,27 @@ Boston, MA 02111-1307, USA. */
/* Run-time target specifications */
+/* Target CPU builtins. */
+#define TARGET_CPU_CPP_BUILTINS() \
+do { \
+ builtin_assert("cpu=ia64"); \
+ builtin_assert("machine=ia64"); \
+ builtin_define("__ia64"); \
+ builtin_define("__ia64__"); \
+ builtin_define("__itanium__"); \
+ builtin_define("__ELF__"); \
+ if (!TARGET_ILP32) \
+ { \
+ builtin_define("_LP64"); \
+ builtin_define("__LP64__"); \
+ } \
+ if (TARGET_BIG_ENDIAN) \
+ builtin_define("__BIG_ENDIAN__"); \
+} while (0)
+
#define EXTRA_SPECS \
- { "cpp_cpu", CPP_CPU_SPEC }, \
{ "asm_extra", ASM_EXTRA_SPEC },
-#define CPP_CPU_SPEC " \
- -Acpu=ia64 -Amachine=ia64 -D__ia64 -D__ia64__ %{!milp32:-D_LP64 -D__LP64__} \
- -D__ELF__"
-
#define CC1_SPEC "%(cc1_cpu) "
#define ASM_EXTRA_SPEC ""
@@ -72,9 +85,13 @@ extern int target_flags;
#define MASK_AUTO_PIC 0x00000400 /* generate automatically PIC */
-#define MASK_INLINE_DIV_LAT 0x00000800 /* inline div, min latency. */
+#define MASK_INLINE_FLOAT_DIV_LAT 0x00000800 /* inline div, min latency. */
+
+#define MASK_INLINE_FLOAT_DIV_THR 0x00001000 /* inline div, max throughput. */
+
+#define MASK_INLINE_INT_DIV_LAT 0x00000800 /* inline div, min latency. */
-#define MASK_INLINE_DIV_THR 0x00001000 /* inline div, max throughput. */
+#define MASK_INLINE_INT_DIV_THR 0x00001000 /* inline div, max throughput. */
#define MASK_DWARF2_ASM 0x40000000 /* test dwarf2 line info via gas. */
@@ -100,15 +117,33 @@ extern int target_flags;
#define TARGET_AUTO_PIC (target_flags & MASK_AUTO_PIC)
-#define TARGET_INLINE_DIV_LAT (target_flags & MASK_INLINE_DIV_LAT)
+#define TARGET_INLINE_FLOAT_DIV_LAT (target_flags & MASK_INLINE_FLOAT_DIV_LAT)
-#define TARGET_INLINE_DIV_THR (target_flags & MASK_INLINE_DIV_THR)
+#define TARGET_INLINE_FLOAT_DIV_THR (target_flags & MASK_INLINE_FLOAT_DIV_THR)
-#define TARGET_INLINE_DIV \
- (target_flags & (MASK_INLINE_DIV_LAT | MASK_INLINE_DIV_THR))
+#define TARGET_INLINE_INT_DIV_LAT (target_flags & MASK_INLINE_INT_DIV_LAT)
+
+#define TARGET_INLINE_INT_DIV_THR (target_flags & MASK_INLINE_INT_DIV_THR)
+
+#define TARGET_INLINE_FLOAT_DIV \
+ (target_flags & (MASK_INLINE_FLOAT_DIV_LAT | MASK_INLINE_FLOAT_DIV_THR))
+
+#define TARGET_INLINE_INT_DIV \
+ (target_flags & (MASK_INLINE_INT_DIV_LAT | MASK_INLINE_INT_DIV_THR))
#define TARGET_DWARF2_ASM (target_flags & MASK_DWARF2_ASM)
+extern int ia64_tls_size;
+#define TARGET_TLS14 (ia64_tls_size == 14)
+#define TARGET_TLS22 (ia64_tls_size == 22)
+#define TARGET_TLS64 (ia64_tls_size == 64)
+
+#define TARGET_HPUX_LD 0
+
+#ifndef HAVE_AS_LTOFFX_LDXMOV_RELOCS
+#define HAVE_AS_LTOFFX_LDXMOV_RELOCS 0
+#endif
+
/* This macro defines names of command options to set and clear bits in
`target_flags'. Its definition is an initializer with a subgrouping for
each command option. */
@@ -145,10 +180,14 @@ extern int target_flags;
N_("gp is constant (but save/restore gp on indirect calls)") }, \
{ "auto-pic", MASK_AUTO_PIC, \
N_("Generate self-relocatable code") }, \
- { "inline-divide-min-latency", MASK_INLINE_DIV_LAT, \
- N_("Generate inline division, optimize for latency") }, \
- { "inline-divide-max-throughput", MASK_INLINE_DIV_THR, \
- N_("Generate inline division, optimize for throughput") }, \
+ { "inline-float-divide-min-latency", MASK_INLINE_FLOAT_DIV_LAT, \
+ N_("Generate inline floating point division, optimize for latency") },\
+ { "inline-float-divide-max-throughput", MASK_INLINE_FLOAT_DIV_THR, \
+ N_("Generate inline floating point division, optimize for throughput") },\
+ { "inline-int-divide-min-latency", MASK_INLINE_INT_DIV_LAT, \
+ N_("Generate inline integer division, optimize for latency") }, \
+ { "inline-int-divide-max-throughput", MASK_INLINE_INT_DIV_THR, \
+ N_("Generate inline integer division, optimize for throughput") },\
{ "dwarf2-asm", MASK_DWARF2_ASM, \
N_("Enable Dwarf 2 line debug info via GNU as")}, \
{ "no-dwarf2-asm", -MASK_DWARF2_ASM, \
@@ -177,10 +216,13 @@ extern int target_flags;
subgrouping for each command option. */
extern const char *ia64_fixed_range_string;
+extern const char *ia64_tls_size_string;
#define TARGET_OPTIONS \
{ \
{ "fixed-range=", &ia64_fixed_range_string, \
N_("Specify range of registers to make fixed")}, \
+ { "tls-size=", &ia64_tls_size_string, \
+ N_("Specify bit size of immediate TLS offsets")}, \
}
/* Sometimes certain combinations of command options do not make sense on a
@@ -201,25 +243,6 @@ extern const char *ia64_fixed_range_string;
/* Driver configuration */
/* A C string constant that tells the GNU CC driver program options to pass to
- CPP. It can also specify how to translate options you give to GNU CC into
- options for GNU CC to pass to the CPP. */
-
-/* ??? __LONG_MAX__ depends on LP64/ILP32 switch. */
-/* ??? An alternative is to modify glimits.h to check for __LP64__ instead
- of checked for CPU specific defines. We could also get rid of all LONG_MAX
- defines in other tm.h files. */
-#define CPP_SPEC \
- "%{mcpu=itanium:-D__itanium__} %{mbig-endian:-D__BIG_ENDIAN__} \
- %(cpp_cpu) \
- -D__LONG_MAX__=9223372036854775807L"
-
-/* This is always "long" so it doesn't "change" in ILP32 vs. LP64. */
-/* #define NO_BUILTIN_SIZE_TYPE */
-
-/* This is always "long" so it doesn't "change" in ILP32 vs. LP64. */
-/* #define NO_BUILTIN_PTRDIFF_TYPE */
-
-/* A C string constant that tells the GNU CC driver program options to pass to
`cc1'. It can also specify how to translate options you give to GNU CC into
options for GNU CC to pass to the `cc1'. */
@@ -252,10 +275,6 @@ extern const char *ia64_fixed_range_string;
#define LIBGCC2_WORDS_BIG_ENDIAN 0
#endif
-#define BITS_PER_UNIT 8
-
-#define BITS_PER_WORD 64
-
#define UNITS_PER_WORD 8
#define POINTER_SIZE (TARGET_ILP32 ? 32 : 64)
@@ -329,10 +348,10 @@ while (0)
/* Define this if you wish to imitate the way many other C compilers handle
alignment of bitfields and the structures that contain them.
- The behavior is that the type written for a bitfield (`int', `short', or
+ The behavior is that the type written for a bit-field (`int', `short', or
other integer type) imposes an alignment for the entire structure, as if the
structure really did contain an ordinary field of that type. In addition,
- the bitfield is placed within the structure so that it would fit within such
+ the bit-field is placed within the structure so that it would fit within such
a field, not crossing a boundary for it. */
#define PCC_BITFIELD_TYPE_MATTERS 1
@@ -342,16 +361,26 @@ while (0)
/* Allow pairs of registers to be used, which is the intent of the default. */
#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TImode)
-/* A code distinguishing the floating point format of the target machine. */
-#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-
/* By default, the C++ compiler will use function addresses in the
- vtable entries. Setting this non-zero tells the compiler to use
+ vtable entries. Setting this nonzero tells the compiler to use
function descriptors instead. The value of this macro says how
many words wide the descriptor is (normally 2). It is assumed
that the address of a function descriptor may be treated as a
- pointer to a function. */
-#define TARGET_VTABLE_USES_DESCRIPTORS 2
+ pointer to a function.
+
+ For reasons known only to HP, the vtable entries (as opposed to
+ normal function descriptors) are 16 bytes wide in 32-bit mode as
+ well, even though the 3rd and 4th words are unused. */
+#define TARGET_VTABLE_USES_DESCRIPTORS (TARGET_ILP32 ? 4 : 2)
+
+/* Due to silliness in the HPUX linker, vtable entries must be
+ 8-byte aligned even in 32-bit mode. Rather than create multiple
+ ABIs, force this restriction on everyone else too. */
+#define TARGET_VTABLE_ENTRY_ALIGN 64
+
+/* Due to the above, we need extra padding for the data entries below 0
+ to retain the alignment of the descriptors. */
+#define TARGET_VTABLE_DATA_ENTRY_DISTANCE (TARGET_ILP32 ? 2 : 1)
/* Layout of Source Language Data Types */
@@ -365,17 +394,14 @@ while (0)
#define LONG_LONG_TYPE_SIZE 64
-#define CHAR_TYPE_SIZE 8
-
#define FLOAT_TYPE_SIZE 32
#define DOUBLE_TYPE_SIZE 64
#define LONG_DOUBLE_TYPE_SIZE 128
-/* Tell real.c that this is the 80-bit Intel extended float format
- packaged in a 128-bit entity. */
-
+/* By default we use the 80-bit Intel extended float format packaged
+ in a 128-bit entity. */
#define INTEL_EXTENDED_IEEE_FORMAT 1
#define DEFAULT_SIGNED_CHAR 1
@@ -599,14 +625,6 @@ while (0)
#define LOCAL_REGNO(REGNO) \
(IN_REGNO_P (REGNO) || LOC_REGNO_P (REGNO))
-/* Add any extra modes needed to represent the condition code.
-
- CCImode is used to mark a single predicate register instead
- of a register pair. This is currently only used in reg_raw_mode
- so that flow doesn't do something stupid. */
-
-#define EXTRA_CC_MODES CC(CCImode, "CCI")
-
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. Must be defined if
EXTRA_CC_MODES is defined. */
@@ -970,7 +988,7 @@ enum reg_class
/* Certain machines have the property that some registers cannot be copied to
some other registers without using memory. Define this macro on those
- machines to be a C expression that is non-zero if objects of mode M in
+ machines to be a C expression that is nonzero if objects of mode M in
registers of CLASS1 can only be copied to registers of class CLASS2 by
storing a register of CLASS1 into memory and loading that memory location
into a register of CLASS2. */
@@ -994,17 +1012,12 @@ enum reg_class
: ((CLASS) == FR_REGS && (MODE) == TFmode) ? 1 \
: (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 mode of the object illegally. */
-
-#define CLASS_CANNOT_CHANGE_MODE FR_REGS
-
-/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.
- In FP regs, we can't change FP values to integer values and vice
+/* In FP regs, we can't change FP values to integer values and vice
versa, but we can change e.g. DImode to SImode. */
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
- (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO))
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO) \
+ ? reg_classes_intersect_p (CLASS, FR_REGS) : 0)
/* A C expression that defines the machine-dependent operand constraint
letters (`I', `J', `K', .. 'P') that specify particular ranges of
@@ -1200,7 +1213,7 @@ enum reg_class
{RETURN_ADDRESS_POINTER_REGNUM, BR_REG (0)}, \
}
-/* A C expression that returns non-zero if the compiler is allowed to try to
+/* A C expression that returns nonzero if the compiler is allowed to try to
replace register number FROM with register number TO. The frame pointer
is automatically handled. */
@@ -1344,10 +1357,6 @@ do { \
(((REGNO) >= GR_ARG_FIRST && (REGNO) < (GR_ARG_FIRST + MAX_ARGUMENT_SLOTS)) \
|| ((REGNO) >= FR_ARG_FIRST && (REGNO) < (FR_ARG_FIRST + MAX_ARGUMENT_SLOTS)))
-/* Implement `va_start' for varargs and stdarg. */
-#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
- ia64_va_start (stdarg, valist, nextarg)
-
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
ia64_va_arg (valist, type)
@@ -1433,48 +1442,20 @@ do { \
#define ASM_FILE_START(FILE) \
emit_safe_across_calls (FILE)
-/* A C compound statement that outputs the assembler code for a thunk function,
- used to implement C++ virtual function calls with multiple inheritance. */
-
-#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
-do { \
- if (CONST_OK_FOR_I (DELTA)) \
- { \
- fprintf (FILE, "\tadds r32 = "); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA)); \
- fprintf (FILE, ", r32\n"); \
- } \
- else \
- { \
- if (CONST_OK_FOR_J (DELTA)) \
- { \
- fprintf (FILE, "\taddl r2 = "); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA)); \
- fprintf (FILE, ", r0\n"); \
- } \
- else \
- { \
- fprintf (FILE, "\tmovl r2 = "); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA)); \
- fprintf (FILE, "\n"); \
- } \
- fprintf (FILE, "\t;;\n"); \
- fprintf (FILE, "\tadd r32 = r2, r32\n"); \
- } \
- fprintf (FILE, "\tbr "); \
- assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
- fprintf (FILE, "\n"); \
-} while (0)
-
/* Output part N of a function descriptor for DECL. For ia64, both
words are emitted with a single relocation, so ignore N > 0. */
#define ASM_OUTPUT_FDESC(FILE, DECL, PART) \
do { \
if ((PART) == 0) \
{ \
- fputs ("\tdata16.ua @iplt(", FILE); \
+ if (TARGET_ILP32) \
+ fputs ("\tdata8.ua @iplt(", FILE); \
+ else \
+ fputs ("\tdata16.ua @iplt(", FILE); \
assemble_name (FILE, XSTR (XEXP (DECL_RTL (DECL), 0), 0)); \
fputs (")\n", FILE); \
+ if (TARGET_ILP32) \
+ fputs ("\tdata8.ua 0\n", FILE); \
} \
} while (0)
@@ -1786,36 +1767,9 @@ do { \
#define BSS_SECTION_ASM_OP "\t.bss"
-/* Define this macro if references to a symbol must be treated differently
- depending on something about the variable or function named by the symbol
- (such as what section it is in). */
-
-#define ENCODE_SECTION_INFO(DECL) ia64_encode_section_info (DECL)
-
-/* If a variable is weakened, made one only or moved into a different
- section, it may be necessary to redo the section info to move the
- variable out of sdata. */
-
-#define REDO_SECTION_INFO_P(DECL) \
- ((TREE_CODE (DECL) == VAR_DECL) \
- && (DECL_ONE_ONLY (DECL) || DECL_WEAK (DECL) || DECL_COMMON (DECL) \
- || DECL_SECTION_NAME (DECL) != 0))
-
-#define SDATA_NAME_FLAG_CHAR '@'
+#define ENCODE_SECTION_INFO_CHAR '@'
#define IA64_DEFAULT_GVALUE 8
-
-/* Decode SYM_NAME and store the real name part in VAR, sans the characters
- that encode section info. */
-
-#define STRIP_NAME_ENCODING(VAR, SYMBOL_NAME) \
-do { \
- (VAR) = (SYMBOL_NAME); \
- if ((VAR)[0] == SDATA_NAME_FLAG_CHAR) \
- (VAR)++; \
- if ((VAR)[0] == '*') \
- (VAR)++; \
-} while (0)
/* Position Independent Code. */
@@ -1859,61 +1813,6 @@ do { \
#define ASM_APP_OFF "#NO_APP\n"
-/* Output of Data. */
-
-/* This is how to output an assembler line defining a `char' constant
- to an xdata segment. */
-
-#define ASM_OUTPUT_XDATA_CHAR(FILE, SECTION, VALUE) \
-do { \
- fprintf (FILE, "\t.xdata1\t\"%s\", ", SECTION); \
- output_addr_const (FILE, (VALUE)); \
- fprintf (FILE, "\n"); \
-} while (0)
-
-/* This is how to output an assembler line defining a `short' constant
- to an xdata segment. */
-
-#define ASM_OUTPUT_XDATA_SHORT(FILE, SECTION, VALUE) \
-do { \
- fprintf (FILE, "\t.xdata2\t\"%s\", ", SECTION); \
- output_addr_const (FILE, (VALUE)); \
- fprintf (FILE, "\n"); \
-} while (0)
-
-/* This is how to output an assembler line defining an `int' constant
- to an xdata segment. We also handle symbol output here. */
-
-/* ??? For ILP32, also need to handle function addresses here. */
-
-#define ASM_OUTPUT_XDATA_INT(FILE, SECTION, VALUE) \
-do { \
- fprintf (FILE, "\t.xdata4\t\"%s\", ", SECTION); \
- output_addr_const (FILE, (VALUE)); \
- fprintf (FILE, "\n"); \
-} while (0)
-
-/* This is how to output an assembler line defining a `long' constant
- to an xdata segment. We also handle symbol output here. */
-
-#define ASM_OUTPUT_XDATA_DOUBLE_INT(FILE, SECTION, VALUE) \
-do { \
- int need_closing_paren = 0; \
- fprintf (FILE, "\t.xdata8\t\"%s\", ", SECTION); \
- if (!(TARGET_NO_PIC || TARGET_AUTO_PIC) \
- && GET_CODE (VALUE) == SYMBOL_REF) \
- { \
- fprintf (FILE, SYMBOL_REF_FLAG (VALUE) ? "@fptr(" : "@segrel("); \
- need_closing_paren = 1; \
- } \
- output_addr_const (FILE, VALUE); \
- if (need_closing_paren) \
- fprintf (FILE, ")"); \
- fprintf (FILE, "\n"); \
-} while (0)
-
-
-
/* Output of Uninitialized Variables. */
/* This is all handled by svr4.h. */
@@ -1936,16 +1835,8 @@ do { \
ia64_asm_output_label = 0; \
} while (0)
-/* A C statement (sans semicolon) to output to the stdio stream STREAM some
- commands that will make the label NAME global; that is, available for
- reference from other files. */
-
-#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
-do { \
- fputs ("\t.global ", STREAM); \
- assemble_name (STREAM, NAME); \
- fputs ("\n", STREAM); \
-} while (0)
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.global "
/* A C statement (sans semicolon) to output to the stdio stream STREAM any text
necessary for declaring the name of an external symbol named NAME which is
@@ -2191,8 +2082,13 @@ do { \
/* ??? Depends on the pointer size. */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
- fprintf (STREAM, "\tdata8 @pcrel(.L%d)\n", VALUE)
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
+ do { \
+ if (TARGET_ILP32) \
+ fprintf (STREAM, "\tdata4 @pcrel(.L%d)\n", VALUE); \
+ else \
+ fprintf (STREAM, "\tdata8 @pcrel(.L%d)\n", VALUE); \
+ } while (0)
/* This is how to output an element of a case-vector that is absolute.
(Ia64 does not use such vectors, but we must define this macro anyway.) */
@@ -2211,7 +2107,8 @@ do { \
true if the symbol may be affected by dynamic relocations. */
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
(((CODE) == 1 ? DW_EH_PE_textrel : DW_EH_PE_datarel) \
- | ((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_udata8)
+ | ((GLOBAL) ? DW_EH_PE_indirect : 0) \
+ | (TARGET_ILP32 ? DW_EH_PE_udata4 : DW_EH_PE_udata8))
/* Handle special EH pointer encodings. Absolute, pc-relative, and
indirect are handled automatically. */
@@ -2284,7 +2181,7 @@ do { \
/* Define this macro if GNU CC should produce dwarf version 2 format debugging
output in response to the `-g' option. */
-#define DWARF2_DEBUGGING_INFO
+#define DWARF2_DEBUGGING_INFO 1
#define DWARF2_ASM_LINE_DEBUG_INFO (TARGET_DWARF2_ASM)
@@ -2316,12 +2213,6 @@ do { \
fputc (')', FILE); \
} while (0)
-/* Cross Compilation and Floating Point. */
-
-/* Define to enable software floating point emulation. */
-#define REAL_ARITHMETIC
-
-
/* Register Renaming Parameters. */
/* A C expression that is nonzero if hard register number REGNO2 can be
@@ -2381,12 +2272,13 @@ do { \
{ "ar_pfs_reg_operand", {REG}}, \
{ "general_tfmode_operand", {SUBREG, REG, CONST_DOUBLE, MEM}}, \
{ "destination_tfmode_operand", {SUBREG, REG, MEM}}, \
-{ "tfreg_or_fp01_operand", {REG, CONST_DOUBLE}},
+{ "tfreg_or_fp01_operand", {REG, CONST_DOUBLE}}, \
+{ "basereg_operand", {SUBREG, REG}},
/* An alias for a machine mode name. This is the machine mode that elements of
a jump-table should have. */
-#define CASE_VECTOR_MODE Pmode
+#define CASE_VECTOR_MODE ptr_mode
/* Define as C expression which evaluates to nonzero if the tablejump
instruction expects the table to contain offsets from the address of the
@@ -2452,7 +2344,7 @@ do { \
#define PREFETCH_BLOCK 32
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
/* In rare cases, correct code generation requires extra machine dependent
processing between the second jump optimization pass and delayed branch
@@ -2476,16 +2368,16 @@ extern int ia64_final_schedule;
#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 15 : INVALID_REGNUM)
/* This function contains machine specific function data. */
-struct machine_function
+struct machine_function GTY(())
{
/* The new stack pointer when unwinding from EH. */
- struct rtx_def* ia64_eh_epilogue_sp;
+ rtx ia64_eh_epilogue_sp;
/* The new bsp value when unwinding from EH. */
- struct rtx_def* ia64_eh_epilogue_bsp;
+ rtx ia64_eh_epilogue_bsp;
/* The GP value save register. */
- struct rtx_def* ia64_gp_save;
+ rtx ia64_gp_save;
/* The number of varargs registers to save. */
int n_varargs;
@@ -2558,4 +2450,5 @@ enum fetchop_code {
#undef PROFILE_BEFORE_PROLOGUE
#define PROFILE_BEFORE_PROLOGUE 1
+#define FUNCTION_OK_FOR_SIBCALL(DECL) ia64_function_ok_for_sibcall (DECL)
/* End of ia64.h */
diff --git a/contrib/gcc/config/ia64/ia64.md b/contrib/gcc/config/ia64/ia64.md
index 7b11c06..4d177c2 100644
--- a/contrib/gcc/config/ia64/ia64.md
+++ b/contrib/gcc/config/ia64/ia64.md
@@ -1,5 +1,5 @@
;; IA-64 Machine description template
-;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
;; Contributed by James E. Wilson <wilson@cygnus.com> and
;; David Mosberger <davidm@hpl.hp.com>.
@@ -48,35 +48,43 @@
;; ??? Need a better way to describe alternate fp status registers.
-;; Unspec usage:
-;;
-;; unspec:
-;; 1 gr_spill
-;; 2 gr_restore
-;; 3 fr_spill
-;; 4 fr_restore
-;; 5 recip_approx
-;; 7 pred_rel_mutex
-;; 8 popcnt
-;; 9 pic call
-;; 12 mf
-;; 13 cmpxchg_acq
-;; 19 fetchadd_acq
-;; 20 bsp_value
-;; 21 flushrs
-;; 22 bundle selector
-;; 23 cycle display
-;; 24 addp4
-;; 25 prologue_use
-;;
-;; unspec_volatile:
-;; 0 alloc
-;; 1 blockage
-;; 2 insn_group_barrier
-;; 3 break
-;; 5 set_bsp
-;; 8 pred.safe_across_calls all
-;; 9 pred.safe_across_calls normal
+(define_constants
+ [; Relocations
+ (UNSPEC_LTOFF_DTPMOD 0)
+ (UNSPEC_LTOFF_DTPREL 1)
+ (UNSPEC_DTPREL 2)
+ (UNSPEC_LTOFF_TPREL 3)
+ (UNSPEC_TPREL 4)
+
+ (UNSPEC_LD_BASE 9)
+ (UNSPEC_GR_SPILL 10)
+ (UNSPEC_GR_RESTORE 11)
+ (UNSPEC_FR_SPILL 12)
+ (UNSPEC_FR_RESTORE 13)
+ (UNSPEC_FR_RECIP_APPROX 14)
+ (UNSPEC_PRED_REL_MUTEX 15)
+ (UNSPEC_POPCNT 16)
+ (UNSPEC_PIC_CALL 17)
+ (UNSPEC_MF 18)
+ (UNSPEC_CMPXCHG_ACQ 19)
+ (UNSPEC_FETCHADD_ACQ 20)
+ (UNSPEC_BSP_VALUE 21)
+ (UNSPEC_FLUSHRS 22)
+ (UNSPEC_BUNDLE_SELECTOR 23)
+ (UNSPEC_ADDP4 24)
+ (UNSPEC_PROLOGUE_USE 25)
+ ])
+
+(define_constants
+ [(UNSPECV_ALLOC 0)
+ (UNSPECV_BLOCKAGE 1)
+ (UNSPECV_INSN_GROUP_BARRIER 2)
+ (UNSPECV_BREAK 3)
+ (UNSPECV_SET_BSP 4)
+ (UNSPECV_PSAC_ALL 5) ; pred.safe_across_calls
+ (UNSPECV_PSAC_NORMAL 6)
+ (UNSPECV_SETJMP_RECEIVER 7)
+ ])
;; ::::::::::::::::::::
;; ::
@@ -100,8 +108,12 @@
;; multiple instructions, patterns which emit 0 instructions, and patterns
;; which emit instruction that can go in any slot (e.g. nop).
-(define_attr "itanium_class" "unknown,ignore,stop_bit,br,fcmp,fcvtfx,fld,fmac,fmisc,frar_i,frar_m,frbr,frfr,frpr,ialu,icmp,ilog,ishf,ld,chk_s,long_i,mmmul,mmshf,mmshfi,rse_m,scall,sem,stf,st,syst_m0,syst_m,tbit,toar_i,toar_m,tobr,tofr,topr,xmpy,xtd,nop_b,nop_f,nop_i,nop_m,nop_x,lfetch"
- (const_string "unknown"))
+(define_attr "itanium_class" "unknown,ignore,stop_bit,br,fcmp,fcvtfx,fld,
+ fmac,fmisc,frar_i,frar_m,frbr,frfr,frpr,ialu,icmp,ilog,ishf,ld,
+ chk_s,long_i,mmmul,mmshf,mmshfi,rse_m,scall,sem,stf,st,syst_m0,
+ syst_m,tbit,toar_i,toar_m,tobr,tofr,topr,xmpy,xtd,nop_b,nop_f,
+ nop_i,nop_m,nop_x,lfetch"
+ (const_string "unknown"))
;; chk_s has an I and an M form; use type A for convenience.
(define_attr "type" "unknown,A,I,M,F,B,L,X,S"
@@ -262,7 +274,7 @@
&& GET_CODE (operands[1]) == REG && PR_REGNO_P (REGNO (operands[1]))"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))
- (set (match_dup 0) (unspec:BI [(match_dup 0)] 7))]
+ (set (match_dup 0) (unspec:BI [(match_dup 0)] UNSPEC_PRED_REL_MUTEX))]
"operands[2] = gen_rtx_REG (CCImode, REGNO (operands[0]));
operands[3] = gen_rtx_REG (CCImode, REGNO (operands[0]) + 1);
operands[4] = gen_rtx_REG (CCImode, REGNO (operands[1]));
@@ -272,12 +284,12 @@
[(set (match_operand:QI 0 "general_operand" "")
(match_operand:QI 1 "general_operand" ""))]
""
- "
{
- if (! reload_in_progress && ! reload_completed
- && ! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (QImode, operands[1]);
-}")
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
(define_insn "*movqi_internal"
[(set (match_operand:QI 0 "destination_operand" "=r,r,r, m, r,*f,*f")
@@ -297,12 +309,12 @@
[(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
- "
{
- if (! reload_in_progress && ! reload_completed
- && ! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (HImode, operands[1]);
-}")
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
(define_insn "*movhi_internal"
[(set (match_operand:HI 0 "destination_operand" "=r,r,r, m, r,*f,*f")
@@ -322,12 +334,35 @@
[(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
- "
{
- if (! reload_in_progress && ! reload_completed
- && ! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (SImode, operands[1]);
-}")
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+;; This is used during early compilation to delay the decision on
+;; how to refer to a variable as long as possible. This is especially
+;; important between initial rtl generation and optimization for
+;; deferred functions, since we may acquire additional information
+;; on the variables used in the meantime.
+
+(define_insn_and_split "movsi_symbolic"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "symbolic_operand" "s"))
+ (clobber (match_scratch:DI 2 "=r"))
+ (use (reg:DI 1))]
+ ""
+ "* abort ();"
+ "!no_new_pseudos || reload_completed"
+ [(const_int 0)]
+{
+ rtx scratch = operands[2];
+ if (!reload_completed)
+ scratch = gen_reg_rtx (Pmode);
+ ia64_expand_load_address (operands[0], operands[1], scratch);
+ DONE;
+})
(define_insn "*movsi_internal"
[(set (match_operand:SI 0 "destination_operand" "=r,r,r,r, m, r,*f,*f, r,*d")
@@ -344,39 +379,19 @@
mov %0 = %1
mov %0 = %1
mov %0 = %r1"
-;; frar_m, toar_m ??? why not frar_i and toar_i
+ ;; frar_m, toar_m ??? why not frar_i and toar_i
[(set_attr "itanium_class" "ialu,ialu,long_i,ld,st,frfr,tofr,fmisc,frar_m,toar_m")])
(define_expand "movdi"
[(set (match_operand:DI 0 "general_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
- "
{
- if (! reload_in_progress && ! reload_completed
- && ! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (DImode, operands[1]);
- if (! TARGET_NO_PIC && symbolic_operand (operands[1], DImode))
- {
- /* Before optimization starts, delay committing to any particular
- type of PIC address load. If this function gets deferred, we
- may acquire information that changes the value of the
- sdata_symbolic_operand predicate. */
- /* But don't delay for function pointers. Loading a function address
- actually loads the address of the descriptor not the function.
- If we represent these as SYMBOL_REFs, then they get cse'd with
- calls, and we end up with calls to the descriptor address instead of
- calls to the function address. Functions are not candidates for
- sdata anyways. */
- if (rtx_equal_function_value_matters
- && ! (GET_CODE (operands[1]) == SYMBOL_REF
- && SYMBOL_REF_FLAG (operands[1])))
- emit_insn (gen_movdi_symbolic (operands[0], operands[1], gen_reg_rtx (DImode)));
- else
- ia64_expand_load_address (operands[0], operands[1], NULL_RTX);
- DONE;
- }
-}")
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
;; This is used during early compilation to delay the decision on
;; how to refer to a variable as long as possible. This is especially
@@ -384,19 +399,22 @@
;; deferred functions, since we may acquire additional information
;; on the variables used in the meantime.
-;; ??? This causes us to lose REG_LABEL notes, because the insn splitter
-;; does not attempt to preserve any REG_NOTES on the input instruction.
-
(define_insn_and_split "movdi_symbolic"
[(set (match_operand:DI 0 "register_operand" "=r")
(match_operand:DI 1 "symbolic_operand" "s"))
- (clobber (match_operand:DI 2 "register_operand" "+r"))
+ (clobber (match_scratch:DI 2 "=r"))
(use (reg:DI 1))]
""
"* abort ();"
- ""
+ "!no_new_pseudos || reload_completed"
[(const_int 0)]
- "ia64_expand_load_address (operands[0], operands[1], operands[2]); DONE;")
+{
+ rtx scratch = operands[2];
+ if (!reload_completed)
+ scratch = gen_reg_rtx (Pmode);
+ ia64_expand_load_address (operands[0], operands[1], scratch);
+ DONE;
+})
(define_insn "*movdi_internal"
[(set (match_operand:DI 0 "destination_operand"
@@ -404,27 +422,26 @@
(match_operand:DI 1 "move_operand"
"rO,J,i,m,rO,*f,rO,*f, Q,*f,*b,rO,*e,rK,*d,rK,*c,rO"))]
"ia64_move_ok (operands[0], operands[1])"
- "*
{
static const char * const alt[] = {
- \"%,mov %0 = %r1\",
- \"%,addl %0 = %1, r0\",
- \"%,movl %0 = %1\",
- \"%,ld8%O1 %0 = %1%P1\",
- \"%,st8%Q0 %0 = %r1%P0\",
- \"%,getf.sig %0 = %1\",
- \"%,setf.sig %0 = %r1\",
- \"%,mov %0 = %1\",
- \"%,ldf8 %0 = %1%P1\",
- \"%,stf8 %0 = %1%P0\",
- \"%,mov %0 = %1\",
- \"%,mov %0 = %r1\",
- \"%,mov %0 = %1\",
- \"%,mov %0 = %1\",
- \"%,mov %0 = %1\",
- \"%,mov %0 = %1\",
- \"mov %0 = pr\",
- \"mov pr = %1, -1\"
+ "%,mov %0 = %r1",
+ "%,addl %0 = %1, r0",
+ "%,movl %0 = %1",
+ "%,ld8%O1 %0 = %1%P1",
+ "%,st8%Q0 %0 = %r1%P0",
+ "%,getf.sig %0 = %1",
+ "%,setf.sig %0 = %r1",
+ "%,mov %0 = %1",
+ "%,ldf8 %0 = %1%P1",
+ "%,stf8 %0 = %1%P0",
+ "%,mov %0 = %1",
+ "%,mov %0 = %r1",
+ "%,mov %0 = %1",
+ "%,mov %0 = %1",
+ "%,mov %0 = %1",
+ "%,mov %0 = %1",
+ "mov %0 = pr",
+ "mov pr = %1, -1"
};
if (which_alternative == 2 && ! TARGET_NO_PIC
@@ -432,7 +449,7 @@
abort ();
return alt[which_alternative];
-}"
+}
[(set_attr "itanium_class" "ialu,ialu,long_i,ld,st,frfr,tofr,fmisc,fld,stf,frbr,tobr,frar_i,toar_i,frar_m,toar_m,frpr,topr")])
(define_split
@@ -440,34 +457,32 @@
(match_operand:DI 1 "symbolic_operand" ""))]
"reload_completed && ! TARGET_NO_PIC"
[(const_int 0)]
- "
{
ia64_expand_load_address (operands[0], operands[1], NULL_RTX);
DONE;
-}")
+})
(define_expand "load_fptr"
[(set (match_dup 2)
- (plus:DI (reg:DI 1) (match_operand:DI 1 "function_operand" "")))
+ (plus:DI (reg:DI 1) (match_operand 1 "function_operand" "")))
(set (match_operand:DI 0 "register_operand" "") (match_dup 3))]
""
- "
{
operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
operands[3] = gen_rtx_MEM (DImode, operands[2]);
RTX_UNCHANGING_P (operands[3]) = 1;
-}")
+})
(define_insn "*load_fptr_internal1"
[(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (reg:DI 1) (match_operand:DI 1 "function_operand" "s")))]
+ (plus:DI (reg:DI 1) (match_operand 1 "function_operand" "s")))]
""
"addl %0 = @ltoff(@fptr(%1)), gp"
[(set_attr "itanium_class" "ialu")])
(define_insn "load_gprel"
[(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (reg:DI 1) (match_operand:DI 1 "sdata_symbolic_operand" "s")))]
+ (plus:DI (reg:DI 1) (match_operand 1 "sdata_symbolic_operand" "s")))]
""
"addl %0 = @gprel(%1), gp"
[(set_attr "itanium_class" "ialu")])
@@ -485,29 +500,171 @@
(set (match_operand:DI 0 "register_operand" "")
(plus:DI (match_dup 3) (match_dup 2)))]
""
- "
{
operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
operands[3] = pic_offset_table_rtx;
-}")
+})
(define_expand "load_symptr"
[(set (match_operand:DI 2 "register_operand" "")
- (plus:DI (match_dup 4) (match_operand:DI 1 "got_symbolic_operand" "")))
- (set (match_operand:DI 0 "register_operand" "") (match_dup 3))]
+ (plus:DI (high:DI (match_operand:DI 1 "got_symbolic_operand" ""))
+ (match_dup 3)))
+ (set (match_operand:DI 0 "register_operand" "")
+ (lo_sum:DI (match_dup 2) (match_dup 1)))]
""
- "
{
- operands[3] = gen_rtx_MEM (DImode, operands[2]);
- operands[4] = pic_offset_table_rtx;
- RTX_UNCHANGING_P (operands[3]) = 1;
-}")
+ operands[3] = pic_offset_table_rtx;
+})
+
+(define_insn "*load_symptr_high"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (high:DI (match_operand 1 "got_symbolic_operand" "s"))
+ (match_operand:DI 2 "register_operand" "a")))]
+ ""
+{
+ if (HAVE_AS_LTOFFX_LDXMOV_RELOCS)
+ return "%,addl %0 = @ltoffx(%1), %2";
+ else
+ return "%,addl %0 = @ltoff(%1), %2";
+}
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*load_symptr_low"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand 2 "got_symbolic_operand" "s")))]
+ ""
+{
+ if (HAVE_AS_LTOFFX_LDXMOV_RELOCS)
+ return "%,ld8.mov %0 = [%1], %2";
+ else
+ return "%,ld8 %0 = [%1]";
+}
+ [(set_attr "itanium_class" "ld")])
+
+(define_insn "load_ltoff_dtpmod"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (reg:DI 1)
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_LTOFF_DTPMOD)))]
+ ""
+ "addl %0 = @ltoff(@dtpmod(%1)), gp"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "load_ltoff_dtprel"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (reg:DI 1)
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_LTOFF_DTPREL)))]
+ ""
+ "addl %0 = @ltoff(@dtprel(%1)), gp"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_expand "load_dtprel"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_DTPREL))]
+ ""
+ "")
-(define_insn "*load_symptr_internal1"
+(define_insn "*load_dtprel64"
[(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (reg:DI 1) (match_operand:DI 1 "got_symbolic_operand" "s")))]
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_DTPREL))]
+ "TARGET_TLS64"
+ "movl %0 = @dtprel(%1)"
+ [(set_attr "itanium_class" "long_i")])
+
+(define_insn "*load_dtprel22"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_DTPREL))]
""
- "addl %0 = @ltoff(%1), gp"
+ "addl %0 = @dtprel(%1), r0"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_expand "add_dtprel"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_operand:DI 1 "register_operand" "")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_DTPREL)))]
+ "!TARGET_TLS64"
+ "")
+
+(define_insn "*add_dtprel14"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_DTPREL)))]
+ "TARGET_TLS14"
+ "adds %0 = @dtprel(%2), %1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*add_dtprel22"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "a")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_DTPREL)))]
+ "TARGET_TLS22"
+ "addl %0 = @dtprel(%2), %1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "load_ltoff_tprel"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (reg:DI 1)
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_LTOFF_TPREL)))]
+ ""
+ "addl %0 = @ltoff(@tprel(%1)), gp"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_expand "load_tprel"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_TPREL))]
+ ""
+ "")
+
+(define_insn "*load_tprel64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_TPREL))]
+ "TARGET_TLS64"
+ "movl %0 = @tprel(%1)"
+ [(set_attr "itanium_class" "long_i")])
+
+(define_insn "*load_tprel22"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_TPREL))]
+ ""
+ "addl %0 = @tprel(%1), r0"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_expand "add_tprel"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_operand:DI 1 "register_operand" "")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_TPREL)))]
+ "!TARGET_TLS64"
+ "")
+
+(define_insn "*add_tprel14"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_TPREL)))]
+ "TARGET_TLS14"
+ "adds %0 = @tprel(%2), %1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*add_tprel22"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "a")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_TPREL)))]
+ "TARGET_TLS22"
+ "addl %0 = @tprel(%2), %1"
[(set_attr "itanium_class" "ialu")])
;; With no offsettable memory references, we've got to have a scratch
@@ -517,12 +674,12 @@
(match_operand:TI 1 "general_operand" ""))
(clobber (match_scratch:DI 2 ""))])]
""
- "
{
- if (! reload_in_progress && ! reload_completed
- && ! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (TImode, operands[1]);
-}")
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
(define_insn_and_split "*movti_internal"
[(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m")
@@ -532,7 +689,6 @@
"#"
"reload_completed"
[(const_int 0)]
- "
{
rtx adj1, adj2, in[2], out[2], insn;
int first;
@@ -567,7 +723,7 @@
XEXP (XEXP (out[!first], 0), 0),
REG_NOTES (insn));
DONE;
-}"
+}
[(set_attr "itanium_class" "unknown")
(set_attr "predicable" "no")])
@@ -581,7 +737,6 @@
"#"
"reload_completed"
[(const_int 0)]
- "
{
rtx in[2], out[2];
int first;
@@ -600,7 +755,7 @@
emit_insn (gen_rtx_SET (VOIDmode, out[first], in[first]));
emit_insn (gen_rtx_SET (VOIDmode, out[!first], in[!first]));
DONE;
-}"
+}
[(set_attr "itanium_class" "unknown")
(set_attr "predicable" "no")])
@@ -609,82 +764,80 @@
(match_operand:TI 1 "" "m"))
(clobber (match_operand:TI 2 "register_operand" "=&r"))])]
""
- "
{
unsigned int s_regno = REGNO (operands[2]);
if (s_regno == REGNO (operands[0]))
s_regno += 1;
operands[2] = gen_rtx_REG (DImode, s_regno);
-}")
+})
(define_expand "reload_outti"
[(parallel [(set (match_operand:TI 0 "" "=m")
(match_operand:TI 1 "register_operand" "r"))
(clobber (match_operand:TI 2 "register_operand" "=&r"))])]
""
- "
{
unsigned int s_regno = REGNO (operands[2]);
if (s_regno == REGNO (operands[1]))
s_regno += 1;
operands[2] = gen_rtx_REG (DImode, s_regno);
-}")
+})
;; Floating Point Moves
;;
;; Note - Patterns for SF mode moves are compulsory, but
-;; patterns for DF are optional, as GCC can synthesise them.
+;; patterns for DF are optional, as GCC can synthesize them.
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand" "")
(match_operand:SF 1 "general_operand" ""))]
""
- "
{
- if (! reload_in_progress && ! reload_completed
- && ! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (SFmode, operands[1]);
-}")
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
(define_insn "*movsf_internal"
[(set (match_operand:SF 0 "destination_operand" "=f,f, Q,*r, f,*r,*r, m")
(match_operand:SF 1 "general_operand" "fG,Q,fG,fG,*r,*r, m,*r"))]
"ia64_move_ok (operands[0], operands[1])"
"@
- mov %0 = %F1
- ldfs %0 = %1%P1
- stfs %0 = %F1%P0
- getf.s %0 = %F1
- setf.s %0 = %1
- mov %0 = %1
- ld4%O1 %0 = %1%P1
- st4%Q0 %0 = %1%P0"
+ mov %0 = %F1
+ ldfs %0 = %1%P1
+ stfs %0 = %F1%P0
+ getf.s %0 = %F1
+ setf.s %0 = %1
+ mov %0 = %1
+ ld4%O1 %0 = %1%P1
+ st4%Q0 %0 = %1%P0"
[(set_attr "itanium_class" "fmisc,fld,stf,frfr,tofr,ialu,ld,st")])
(define_expand "movdf"
[(set (match_operand:DF 0 "general_operand" "")
(match_operand:DF 1 "general_operand" ""))]
""
- "
{
- if (! reload_in_progress && ! reload_completed
- && ! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (DFmode, operands[1]);
-}")
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
(define_insn "*movdf_internal"
[(set (match_operand:DF 0 "destination_operand" "=f,f, Q,*r, f,*r,*r, m")
(match_operand:DF 1 "general_operand" "fG,Q,fG,fG,*r,*r, m,*r"))]
"ia64_move_ok (operands[0], operands[1])"
"@
- mov %0 = %F1
- ldfd %0 = %1%P1
- stfd %0 = %F1%P0
- getf.d %0 = %F1
- setf.d %0 = %1
- mov %0 = %1
- ld8%O1 %0 = %1%P1
- st8%Q0 %0 = %1%P0"
+ mov %0 = %F1
+ ldfd %0 = %1%P1
+ stfd %0 = %F1%P0
+ getf.d %0 = %F1
+ setf.d %0 = %1
+ mov %0 = %1
+ ld8%O1 %0 = %1%P1
+ st8%Q0 %0 = %1%P0"
[(set_attr "itanium_class" "fmisc,fld,stf,frfr,tofr,ialu,ld,st")])
;; With no offsettable memory references, we've got to have a scratch
@@ -693,7 +846,6 @@
[(set (match_operand:TF 0 "general_operand" "")
(match_operand:TF 1 "general_operand" ""))]
"INTEL_EXTENDED_IEEE_FORMAT"
- "
{
/* We must support TFmode loads into general registers for stdarg/vararg
and unprototyped calls. We split them into DImode loads for convenience.
@@ -754,7 +906,7 @@
if (! ia64_move_ok (operands[0], operands[1]))
operands[1] = force_reg (TFmode, operands[1]);
}
-}")
+})
;; ??? There's no easy way to mind volatile acquire/release semantics.
@@ -763,9 +915,9 @@
(match_operand:TF 1 "general_tfmode_operand" "fG,m,fG"))]
"INTEL_EXTENDED_IEEE_FORMAT && ia64_move_ok (operands[0], operands[1])"
"@
- mov %0 = %F1
- ldfe %0 = %1%P1
- stfe %0 = %F1%P0"
+ mov %0 = %F1
+ ldfe %0 = %1%P1
+ stfe %0 = %F1%P0"
[(set_attr "itanium_class" "fmisc,fld,stf")])
;; ::::::::::::::::::::
@@ -902,7 +1054,7 @@
[(set (match_operand:DF 0 "register_operand" "=f")
(float:DF (match_operand:DI 1 "register_operand" "f")))]
"!INTEL_EXTENDED_IEEE_FORMAT"
- "fcvt.xf %0 = %1\;;;\;fnorm.d %0 = %0"
+ "fcvt.xf %0 = %1\;;;\;%,fnorm.d %0 = %0"
[(set_attr "itanium_class" "fcvtfx")])
;; ??? Suboptimal. This should be split somehow.
@@ -910,7 +1062,7 @@
[(set (match_operand:SF 0 "register_operand" "=f")
(float:SF (match_operand:DI 1 "register_operand" "f")))]
"!INTEL_EXTENDED_IEEE_FORMAT"
- "fcvt.xf %0 = %1\;;;\;fnorm.s %0 = %0"
+ "fcvt.xf %0 = %1\;;;\;%,fnorm.s %0 = %0"
[(set_attr "itanium_class" "fcvtfx")])
(define_insn "fix_truncsfdi2"
@@ -1033,7 +1185,6 @@
(match_operand:DI 2 "const_int_operand" ""))
(match_operand:DI 3 "nonmemory_operand" ""))]
""
- "
{
int width = INTVAL (operands[1]);
int shift = INTVAL (operands[2]);
@@ -1101,7 +1252,7 @@
operands[2] = GEN_INT (shift);
#endif
}
-}")
+})
(define_insn "*insv_internal"
[(set (zero_extract:DI (match_operand:DI 0 "gr_register_operand" "+r")
@@ -1113,7 +1264,7 @@
"dep %0 = %3, %0, %2, %1"
[(set_attr "itanium_class" "ishf")])
-;; Combine doesn't like to create bitfield insertions into zero.
+;; Combine doesn't like to create bit-field insertions into zero.
(define_insn "*depz_internal"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
(and:DI (ashift:DI (match_operand:DI 1 "gr_register_operand" "r")
@@ -1121,11 +1272,10 @@
(match_operand:DI 3 "const_int_operand" "n")))]
"CONST_OK_FOR_M (INTVAL (operands[2]))
&& ia64_depz_field_mask (operands[3], operands[2]) > 0"
- "*
{
operands[3] = GEN_INT (ia64_depz_field_mask (operands[3], operands[2]));
- return \"%,dep.z %0 = %1, %2, %3\";
-}"
+ return "%,dep.z %0 = %1, %2, %3";
+}
[(set_attr "itanium_class" "ishf")])
(define_insn "shift_mix4left"
@@ -1289,7 +1439,7 @@
(set (match_dup 0) (const_int 1))
(cond_exec (ne (match_dup 2) (const_int 0))
(set (match_dup 0) (const_int 0)))
- (set (match_dup 0) (unspec:BI [(match_dup 0)] 7))]
+ (set (match_dup 0) (unspec:BI [(match_dup 0)] UNSPEC_PRED_REL_MUTEX))]
"operands[3] = gen_rtx_REG (CCImode, REGNO (operands[1]));
operands[4] = gen_rtx_REG (CCImode, REGNO (operands[2]));")
@@ -1305,7 +1455,7 @@
(set (match_dup 0) (const_int 0)))
(cond_exec (eq (match_dup 1) (const_int 0))
(set (match_dup 0) (const_int 1)))
- (set (match_dup 0) (unspec:BI [(match_dup 0)] 7))]
+ (set (match_dup 0) (unspec:BI [(match_dup 0)] UNSPEC_PRED_REL_MUTEX))]
"")
(define_insn "*cmpsi_and_0"
@@ -1693,7 +1843,7 @@
(set (match_operand:CCI 4 "register_operand" "")
(match_operand:CCI 5 "register_operand" ""))
(set (match_operand:BI 6 "register_operand" "")
- (unspec:BI [(match_dup 6)] 7))]
+ (unspec:BI [(match_dup 6)] UNSPEC_PRED_REL_MUTEX))]
"REGNO (operands[3]) == REGNO (operands[0])
&& REGNO (operands[4]) == REGNO (operands[0]) + 1
&& REGNO (operands[4]) == REGNO (operands[2]) + 1
@@ -1729,9 +1879,9 @@
(match_operand:SI 2 "gr_reg_or_22bit_operand" "r,I,J")))]
""
"@
- add %0 = %1, %2
- adds %0 = %2, %1
- addl %0 = %2, %1"
+ add %0 = %1, %2
+ adds %0 = %2, %1
+ addl %0 = %2, %1"
[(set_attr "itanium_class" "ialu")])
(define_insn "*addsi3_plus1"
@@ -1811,10 +1961,7 @@
(neg:SI (match_dup 1))
(match_dup 1)))]
""
- "
-{
- operands[2] = gen_reg_rtx (BImode);
-}")
+ { operands[2] = gen_reg_rtx (BImode); })
(define_expand "sminsi3"
[(set (match_dup 3)
@@ -1824,10 +1971,7 @@
(if_then_else:SI (ne (match_dup 3) (const_int 0))
(match_dup 2) (match_dup 1)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "smaxsi3"
[(set (match_dup 3)
@@ -1837,10 +1981,7 @@
(if_then_else:SI (ne (match_dup 3) (const_int 0))
(match_dup 1) (match_dup 2)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "uminsi3"
[(set (match_dup 3)
@@ -1850,10 +1991,7 @@
(if_then_else:SI (ne (match_dup 3) (const_int 0))
(match_dup 2) (match_dup 1)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "umaxsi3"
[(set (match_dup 3)
@@ -1863,19 +2001,16 @@
(if_then_else:SI (ne (match_dup 3) (const_int 0))
(match_dup 1) (match_dup 2)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "divsi3"
[(set (match_operand:SI 0 "register_operand" "")
(div:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op1_tf, op2_tf, op0_tf, op0_di, twon34;
+ REAL_VALUE_TYPE twon34_r;
op0_tf = gen_reg_rtx (TFmode);
op0_di = gen_reg_rtx (DImode);
@@ -1891,28 +2026,22 @@
expand_float (op2_tf, operands[2], 0);
/* 2^-34 */
-#if 0
- twon34 = (CONST_DOUBLE_FROM_REAL_VALUE
- (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), TFmode));
+ real_2expN (&twon34_r, -34);
+ twon34 = CONST_DOUBLE_FROM_REAL_VALUE (twon34_r, TFmode);
twon34 = force_reg (TFmode, twon34);
-#else
- twon34 = gen_reg_rtx (TFmode);
- convert_move (twon34, force_const_mem (SFmode, CONST_DOUBLE_FROM_REAL_VALUE (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), SFmode)), 0);
-#endif
emit_insn (gen_divsi3_internal (op0_tf, op1_tf, op2_tf, twon34));
emit_insn (gen_fix_trunctfdi2_alts (op0_di, op0_tf, const1_rtx));
emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
DONE;
-}")
+})
(define_expand "modsi3"
[(set (match_operand:SI 0 "register_operand" "")
(mod:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op2_neg, op1_di, div;
@@ -1929,16 +2058,16 @@
emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
gen_lowpart (SImode, op1_di)));
DONE;
-}")
+})
(define_expand "udivsi3"
[(set (match_operand:SI 0 "register_operand" "")
(udiv:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op1_tf, op2_tf, op0_tf, op0_di, twon34;
+ REAL_VALUE_TYPE twon34_r;
op0_tf = gen_reg_rtx (TFmode);
op0_di = gen_reg_rtx (DImode);
@@ -1954,28 +2083,22 @@
expand_float (op2_tf, operands[2], 1);
/* 2^-34 */
-#if 0
- twon34 = (CONST_DOUBLE_FROM_REAL_VALUE
- (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), TFmode));
+ real_2expN (&twon34_r, -34);
+ twon34 = CONST_DOUBLE_FROM_REAL_VALUE (twon34_r, TFmode);
twon34 = force_reg (TFmode, twon34);
-#else
- twon34 = gen_reg_rtx (TFmode);
- convert_move (twon34, force_const_mem (SFmode, CONST_DOUBLE_FROM_REAL_VALUE (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), SFmode)), 0);
-#endif
emit_insn (gen_divsi3_internal (op0_tf, op1_tf, op2_tf, twon34));
emit_insn (gen_fixuns_trunctfdi2_alts (op0_di, op0_tf, const1_rtx));
emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
DONE;
-}")
+})
(define_expand "umodsi3"
[(set (match_operand:SI 0 "register_operand" "")
(umod:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op2_neg, op1_di, div;
@@ -1992,7 +2115,7 @@
emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
gen_lowpart (SImode, op1_di)));
DONE;
-}")
+})
(define_insn_and_split "divsi3_internal"
[(set (match_operand:TF 0 "fr_register_operand" "=&f")
@@ -2002,11 +2125,12 @@
(clobber (match_scratch:TF 5 "=&f"))
(clobber (match_scratch:BI 6 "=c"))
(use (match_operand:TF 3 "fr_register_operand" "f"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
- (set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)] 5))
+ (set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4) (mult:TF (match_dup 1) (match_dup 0)))
@@ -2047,9 +2171,9 @@
(match_operand:DI 2 "gr_reg_or_22bit_operand" "r,I,J")))]
""
"@
- add %0 = %1, %2
- adds %0 = %2, %1
- addl %0 = %2, %1"
+ add %0 = %1, %2
+ adds %0 = %2, %1
+ addl %0 = %2, %1"
[(set_attr "itanium_class" "ialu")])
(define_insn "*adddi3_plus1"
@@ -2198,10 +2322,7 @@
(neg:DI (match_dup 1))
(match_dup 1)))]
""
- "
-{
- operands[2] = gen_reg_rtx (BImode);
-}")
+ { operands[2] = gen_reg_rtx (BImode); })
(define_expand "smindi3"
[(set (match_dup 3)
@@ -2211,10 +2332,7 @@
(if_then_else:DI (ne (match_dup 3) (const_int 0))
(match_dup 2) (match_dup 1)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "smaxdi3"
[(set (match_dup 3)
@@ -2224,10 +2342,7 @@
(if_then_else:DI (ne (match_dup 3) (const_int 0))
(match_dup 1) (match_dup 2)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "umindi3"
[(set (match_dup 3)
@@ -2237,10 +2352,7 @@
(if_then_else:DI (ne (match_dup 3) (const_int 0))
(match_dup 2) (match_dup 1)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "umaxdi3"
[(set (match_dup 3)
@@ -2250,10 +2362,7 @@
(if_then_else:DI (ne (match_dup 3) (const_int 0))
(match_dup 1) (match_dup 2)))]
""
- "
-{
- operands[3] = gen_reg_rtx (BImode);
-}")
+ { operands[3] = gen_reg_rtx (BImode); })
(define_expand "ffsdi2"
[(set (match_dup 6)
@@ -2261,23 +2370,23 @@
(set (match_dup 2) (plus:DI (match_dup 1) (const_int -1)))
(set (match_dup 5) (const_int 0))
(set (match_dup 3) (xor:DI (match_dup 1) (match_dup 2)))
- (set (match_dup 4) (unspec:DI [(match_dup 3)] 8))
+ (set (match_dup 4) (unspec:DI [(match_dup 3)] UNSPEC_POPCNT))
(set (match_operand:DI 0 "gr_register_operand" "")
(if_then_else:DI (ne (match_dup 6) (const_int 0))
(match_dup 5) (match_dup 4)))]
""
- "
{
operands[2] = gen_reg_rtx (DImode);
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode);
operands[5] = gen_reg_rtx (DImode);
operands[6] = gen_reg_rtx (BImode);
-}")
+})
(define_insn "*popcnt"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "gr_register_operand" "r")] 8))]
+ (unspec:DI [(match_operand:DI 1 "gr_register_operand" "r")]
+ UNSPEC_POPCNT))]
""
"popcnt %0 = %1"
[(set_attr "itanium_class" "mmmul")])
@@ -2286,8 +2395,7 @@
[(set (match_operand:DI 0 "register_operand" "")
(div:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op1_tf, op2_tf, op0_tf;
@@ -2303,21 +2411,20 @@
op2_tf = gen_reg_rtx (TFmode);
expand_float (op2_tf, operands[2], 0);
- if (TARGET_INLINE_DIV_LAT)
+ if (TARGET_INLINE_INT_DIV_LAT)
emit_insn (gen_divdi3_internal_lat (op0_tf, op1_tf, op2_tf));
else
emit_insn (gen_divdi3_internal_thr (op0_tf, op1_tf, op2_tf));
emit_insn (gen_fix_trunctfdi2_alts (operands[0], op0_tf, const1_rtx));
DONE;
-}")
+})
(define_expand "moddi3"
[(set (match_operand:DI 0 "register_operand" "")
(mod:SI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op2_neg, div;
@@ -2328,14 +2435,13 @@
emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
DONE;
-}")
+})
(define_expand "udivdi3"
[(set (match_operand:DI 0 "register_operand" "")
(udiv:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op1_tf, op2_tf, op0_tf;
@@ -2351,21 +2457,20 @@
op2_tf = gen_reg_rtx (TFmode);
expand_float (op2_tf, operands[2], 1);
- if (TARGET_INLINE_DIV_LAT)
+ if (TARGET_INLINE_INT_DIV_LAT)
emit_insn (gen_divdi3_internal_lat (op0_tf, op1_tf, op2_tf));
else
emit_insn (gen_divdi3_internal_thr (op0_tf, op1_tf, op2_tf));
emit_insn (gen_fixuns_trunctfdi2_alts (operands[0], op0_tf, const1_rtx));
DONE;
-}")
+})
(define_expand "umoddi3"
[(set (match_operand:DI 0 "register_operand" "")
(umod:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "general_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV"
{
rtx op2_neg, div;
@@ -2376,7 +2481,7 @@
emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
DONE;
-}")
+})
(define_insn_and_split "divdi3_internal_lat"
[(set (match_operand:TF 0 "fr_register_operand" "=&f")
@@ -2386,11 +2491,12 @@
(clobber (match_scratch:TF 4 "=&f"))
(clobber (match_scratch:TF 5 "=&f"))
(clobber (match_scratch:BI 6 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_LAT"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
- (set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)] 5))
+ (set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
@@ -2444,11 +2550,12 @@
(clobber (match_scratch:TF 3 "=&f"))
(clobber (match_scratch:TF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_THR"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_INT_DIV_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
- (set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)] 5))
+ (set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
@@ -2594,17 +2701,16 @@
[(set (match_operand:SF 0 "fr_register_operand" "")
(div:SF (match_operand:SF 1 "fr_register_operand" "")
(match_operand:SF 2 "fr_register_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
- if (TARGET_INLINE_DIV_LAT)
+ if (TARGET_INLINE_FLOAT_DIV_LAT)
insn = gen_divsf3_internal_lat (operands[0], operands[1], operands[2]);
else
insn = gen_divsf3_internal_thr (operands[0], operands[1], operands[2]);
emit_insn (insn);
DONE;
-}")
+})
(define_insn_and_split "divsf3_internal_lat"
[(set (match_operand:SF 0 "fr_register_operand" "=&f")
@@ -2613,11 +2719,12 @@
(clobber (match_scratch:TF 3 "=&f"))
(clobber (match_scratch:TF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_LAT"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 6) (div:TF (const_int 1) (match_dup 8)))
- (set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)] 5))
+ (set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3) (mult:TF (match_dup 7) (match_dup 6)))
@@ -2653,11 +2760,13 @@
(set (match_dup 0)
(float_truncate:SF (match_dup 6))))
]
- "operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
- operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
- operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
- operands[9] = gen_rtx_REG (DFmode, REGNO (operands[0]));
- operands[10] = CONST1_RTX (TFmode);"
+{
+ operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
+ operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
+ operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
+ operands[9] = gen_rtx_REG (DFmode, REGNO (operands[0]));
+ operands[10] = CONST1_RTX (TFmode);
+}
[(set_attr "predicable" "no")])
(define_insn_and_split "divsf3_internal_thr"
@@ -2667,11 +2776,12 @@
(clobber (match_scratch:TF 3 "=&f"))
(clobber (match_scratch:TF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_THR"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 6) (div:TF (const_int 1) (match_dup 8)))
- (set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)] 5))
+ (set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
@@ -2704,11 +2814,13 @@
(plus:TF (mult:TF (match_dup 4) (match_dup 6))
(match_dup 3)))))
]
- "operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
- operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
- operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
- operands[9] = gen_rtx_REG (SFmode, REGNO (operands[3]));
- operands[10] = CONST1_RTX (TFmode);"
+{
+ operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
+ operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
+ operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
+ operands[9] = gen_rtx_REG (SFmode, REGNO (operands[3]));
+ operands[10] = CONST1_RTX (TFmode);
+}
[(set_attr "predicable" "no")])
;; ::::::::::::::::::::
@@ -2898,17 +3010,16 @@
[(set (match_operand:DF 0 "fr_register_operand" "")
(div:DF (match_operand:DF 1 "fr_register_operand" "")
(match_operand:DF 2 "fr_register_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
- if (TARGET_INLINE_DIV_LAT)
+ if (TARGET_INLINE_FLOAT_DIV_LAT)
insn = gen_divdf3_internal_lat (operands[0], operands[1], operands[2]);
else
insn = gen_divdf3_internal_thr (operands[0], operands[1], operands[2]);
emit_insn (insn);
DONE;
-}")
+})
(define_insn_and_split "divdf3_internal_lat"
[(set (match_operand:DF 0 "fr_register_operand" "=&f")
@@ -2918,11 +3029,12 @@
(clobber (match_scratch:TF 4 "=&f"))
(clobber (match_scratch:TF 5 "=&f"))
(clobber (match_scratch:BI 6 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_LAT"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 7) (div:TF (const_int 1) (match_dup 9)))
- (set (match_dup 6) (unspec:BI [(match_dup 8) (match_dup 9)] 5))
+ (set (match_dup 6) (unspec:BI [(match_dup 8) (match_dup 9)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3) (mult:TF (match_dup 8) (match_dup 7)))
@@ -2980,12 +3092,14 @@
(float_truncate:DF (plus:TF (mult:TF (match_dup 5) (match_dup 7))
(match_dup 3)))))
]
- "operands[7] = gen_rtx_REG (TFmode, REGNO (operands[0]));
- operands[8] = gen_rtx_REG (TFmode, REGNO (operands[1]));
- operands[9] = gen_rtx_REG (TFmode, REGNO (operands[2]));
- operands[10] = gen_rtx_REG (DFmode, REGNO (operands[3]));
- operands[11] = gen_rtx_REG (DFmode, REGNO (operands[5]));
- operands[12] = CONST1_RTX (TFmode);"
+{
+ operands[7] = gen_rtx_REG (TFmode, REGNO (operands[0]));
+ operands[8] = gen_rtx_REG (TFmode, REGNO (operands[1]));
+ operands[9] = gen_rtx_REG (TFmode, REGNO (operands[2]));
+ operands[10] = gen_rtx_REG (DFmode, REGNO (operands[3]));
+ operands[11] = gen_rtx_REG (DFmode, REGNO (operands[5]));
+ operands[12] = CONST1_RTX (TFmode);
+}
[(set_attr "predicable" "no")])
(define_insn_and_split "divdf3_internal_thr"
@@ -2995,11 +3109,12 @@
(clobber (match_scratch:TF 3 "=&f"))
(clobber (match_scratch:DF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_THR"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 6) (div:TF (const_int 1) (match_dup 8)))
- (set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)] 5))
+ (set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
@@ -3044,11 +3159,13 @@
(plus:DF (mult:DF (match_dup 4) (match_dup 0))
(match_dup 9))))
]
- "operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
- operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
- operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
- operands[9] = gen_rtx_REG (DFmode, REGNO (operands[3]));
- operands[10] = CONST1_RTX (TFmode);"
+{
+ operands[6] = gen_rtx_REG (TFmode, REGNO (operands[0]));
+ operands[7] = gen_rtx_REG (TFmode, REGNO (operands[1]));
+ operands[8] = gen_rtx_REG (TFmode, REGNO (operands[2]));
+ operands[9] = gen_rtx_REG (DFmode, REGNO (operands[3]));
+ operands[10] = CONST1_RTX (TFmode);
+}
[(set_attr "predicable" "no")])
;; ::::::::::::::::::::
@@ -3370,17 +3487,16 @@
[(set (match_operand:TF 0 "fr_register_operand" "")
(div:TF (match_operand:TF 1 "fr_register_operand" "")
(match_operand:TF 2 "fr_register_operand" "")))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
- "
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
- if (TARGET_INLINE_DIV_LAT)
+ if (TARGET_INLINE_FLOAT_DIV_LAT)
insn = gen_divtf3_internal_lat (operands[0], operands[1], operands[2]);
else
insn = gen_divtf3_internal_thr (operands[0], operands[1], operands[2]);
emit_insn (insn);
DONE;
-}")
+})
(define_insn_and_split "divtf3_internal_lat"
[(set (match_operand:TF 0 "fr_register_operand" "=&f")
@@ -3391,11 +3507,12 @@
(clobber (match_scratch:TF 5 "=&f"))
(clobber (match_scratch:TF 6 "=&f"))
(clobber (match_scratch:BI 7 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_LAT"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
- (set (match_dup 7) (unspec:BI [(match_dup 1) (match_dup 2)] 5))
+ (set (match_dup 7) (unspec:BI [(match_dup 1) (match_dup 2)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
@@ -3468,11 +3585,12 @@
(clobber (match_scratch:TF 3 "=&f"))
(clobber (match_scratch:TF 4 "=&f"))
(clobber (match_scratch:BI 5 "=c"))]
- "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV_THR"
+ "INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_FLOAT_DIV_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:TF (const_int 1) (match_dup 2)))
- (set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)] 5))
+ (set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)]
+ UNSPEC_FR_RECIP_APPROX))
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
@@ -3546,7 +3664,7 @@
(match_operand:TF 3 "fr_register_operand" "f")))
(set (match_operand:BI 1 "register_operand" "=c")
(unspec:BI [(match_operand:TF 2 "fr_register_operand" "f")
- (match_dup 3)] 5))
+ (match_dup 3)] UNSPEC_FR_RECIP_APPROX))
(use (match_operand:SI 4 "const_int_operand" ""))]
"INTEL_EXTENDED_IEEE_FORMAT"
"frcpa.s%4 %0, %1 = %2, %3"
@@ -3564,7 +3682,6 @@
(ashift:SI (match_operand:SI 1 "gr_register_operand" "")
(match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
""
- "
{
if (GET_CODE (operands[2]) != CONST_INT)
{
@@ -3574,7 +3691,7 @@
emit_insn (gen_zero_extendsidi2 (subshift, operands[2]));
operands[2] = subshift;
}
-}")
+})
(define_insn "*ashlsi3_internal"
[(set (match_operand:SI 0 "gr_register_operand" "=r,r,r")
@@ -3592,7 +3709,6 @@
(ashiftrt:SI (match_operand:SI 1 "gr_register_operand" "")
(match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
""
- "
{
rtx subtarget = gen_reg_rtx (DImode);
if (GET_CODE (operands[2]) == CONST_INT)
@@ -3607,14 +3723,13 @@
}
emit_move_insn (gen_lowpart (DImode, operands[0]), subtarget);
DONE;
-}")
+})
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "gr_register_operand" "")
(lshiftrt:SI (match_operand:SI 1 "gr_register_operand" "")
(match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
""
- "
{
rtx subtarget = gen_reg_rtx (DImode);
if (GET_CODE (operands[2]) == CONST_INT)
@@ -3629,7 +3744,7 @@
}
emit_move_insn (gen_lowpart (DImode, operands[0]), subtarget);
DONE;
-}")
+})
;; Use mix4.r/shr to implement rotrsi3. We only get 32 bits of valid result
;; here, instead of 64 like the patterns above. Keep the pattern together
@@ -3640,7 +3755,6 @@
(rotatert:SI (match_operand:SI 1 "gr_register_operand" "")
(match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
""
- "
{
if (GET_MODE (operands[2]) != VOIDmode)
{
@@ -3648,7 +3762,7 @@
emit_insn (gen_zero_extendsidi2 (tmp, operands[2]));
operands[2] = tmp;
}
-}")
+})
(define_insn_and_split "*rotrsi3_internal"
[(set (match_operand:SI 0 "gr_register_operand" "=&r")
@@ -3669,7 +3783,6 @@
(rotate:SI (match_operand:SI 1 "gr_register_operand" "")
(match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
""
- "
{
if (! shift_32bit_count_operand (operands[2], SImode))
{
@@ -3678,7 +3791,7 @@
emit_insn (gen_rotrsi3 (operands[0], operands[1], tmp));
DONE;
}
-}")
+})
(define_insn_and_split "*rotlsi3_internal"
[(set (match_operand:SI 0 "gr_register_operand" "=r")
@@ -3692,8 +3805,10 @@
(ashift:DI (zero_extend:DI (match_dup 1)) (const_int 32))))
(set (match_dup 3)
(lshiftrt:DI (match_dup 3) (match_dup 2)))]
- "operands[3] = gen_rtx_REG (DImode, REGNO (operands[0]));
- operands[2] = GEN_INT (32 - INTVAL (operands[2]));")
+{
+ operands[3] = gen_rtx_REG (DImode, REGNO (operands[0]));
+ operands[2] = GEN_INT (32 - INTVAL (operands[2]));
+})
;; ::::::::::::::::::::
;; ::
@@ -3776,11 +3891,10 @@
(rotatert:DI (match_operand:DI 1 "gr_register_operand" "")
(match_operand:DI 2 "nonmemory_operand" "")))]
""
- "
{
if (! shift_count_operand (operands[2], DImode))
FAIL;
-}")
+})
(define_insn "*rotrdi3_internal"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
@@ -3795,11 +3909,10 @@
(rotate:DI (match_operand:DI 1 "gr_register_operand" "")
(match_operand:DI 2 "nonmemory_operand" "")))]
""
- "
{
if (! shift_count_operand (operands[2], DImode))
FAIL;
-}")
+})
(define_insn "*rotldi3_internal"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
@@ -3900,72 +4013,66 @@
(compare (match_operand:BI 0 "register_operand" "")
(match_operand:BI 1 "const_int_operand" "")))]
""
- "
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
-}")
+})
(define_expand "cmpsi"
[(set (cc0)
(compare (match_operand:SI 0 "gr_register_operand" "")
(match_operand:SI 1 "gr_reg_or_8bit_and_adjusted_operand" "")))]
""
- "
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
-}")
+})
(define_expand "cmpdi"
[(set (cc0)
(compare (match_operand:DI 0 "gr_register_operand" "")
(match_operand:DI 1 "gr_reg_or_8bit_and_adjusted_operand" "")))]
""
- "
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
-}")
+})
(define_expand "cmpsf"
[(set (cc0)
(compare (match_operand:SF 0 "fr_reg_or_fp01_operand" "")
(match_operand:SF 1 "fr_reg_or_fp01_operand" "")))]
""
- "
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
-}")
+})
(define_expand "cmpdf"
[(set (cc0)
(compare (match_operand:DF 0 "fr_reg_or_fp01_operand" "")
(match_operand:DF 1 "fr_reg_or_fp01_operand" "")))]
""
- "
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
-}")
+})
(define_expand "cmptf"
[(set (cc0)
(compare (match_operand:TF 0 "tfreg_or_fp01_operand" "")
(match_operand:TF 1 "tfreg_or_fp01_operand" "")))]
"INTEL_EXTENDED_IEEE_FORMAT"
- "
{
ia64_compare_op0 = operands[0];
ia64_compare_op1 = operands[1];
DONE;
-}")
+})
(define_insn "*cmpsi_normal"
[(set (match_operand:BI 0 "register_operand" "=c")
@@ -4197,7 +4304,6 @@
(use (match_operand 3 "" "")) ; loop level
(use (match_operand 4 "" ""))] ; label
""
- "
{
/* Only use cloop on innermost loops. */
if (INTVAL (operands[3]) > 1)
@@ -4205,7 +4311,7 @@
emit_jump_insn (gen_doloop_end_internal (gen_rtx_REG (DImode, AR_LC_REGNUM),
operands[4]));
DONE;
-}")
+})
(define_insn "doloop_end_internal"
[(set (pc) (if_then_else (ne (match_operand:DI 0 "ar_lc_reg_operand" "")
@@ -4213,8 +4319,8 @@
(label_ref (match_operand 1 "" ""))
(pc)))
(set (match_dup 0) (if_then_else:DI (ne (match_dup 0) (const_int 0))
- (match_dup 0)
- (plus:DI (match_dup 0) (const_int -1))))]
+ (plus:DI (match_dup 0) (const_int -1))
+ (match_dup 0)))]
""
"br.cloop.sptk.few %l1"
[(set_attr "itanium_class" "br")
@@ -4338,12 +4444,12 @@
"c,c,c,c,c,c,c,c,c,c,c,c,c,c,c")
(const_int 0)])
(match_operand:DI 2 "move_operand"
- "rim, *f, *b,*d*e,rim,rim, rim,*f,*b,*d*e,rO,*f,rOQ,rO, rK")
+ "rnm, *f, *b,*d*e,rnm,rnm, rnm,*f,*b,*d*e,rO,*f,rOQ,rO, rK")
(match_operand:DI 3 "move_operand"
- "rim,rim,rim, rim, *f, *b,*d*e,*f,*b,*d*e,rO,*f,rOQ,rO, rK")))]
+ "rnm,rnm,rnm, rnm, *f, *b,*d*e,*f,*b,*d*e,rO,*f,rOQ,rO, rK")))]
"ia64_move_ok (operands[0], operands[2])
&& ia64_move_ok (operands[0], operands[3])"
- "* abort ();"
+ { abort (); }
[(set_attr "predicable" "no")])
(define_split
@@ -4356,14 +4462,17 @@
(match_operand 3 "move_operand" "")))]
"reload_completed"
[(const_int 0)]
- "
{
rtx tmp;
+ int emitted_something;
+
+ emitted_something = 0;
if (! rtx_equal_p (operands[0], operands[2]))
{
tmp = gen_rtx_SET (VOIDmode, operands[0], operands[2]);
tmp = gen_rtx_COND_EXEC (VOIDmode, operands[4], tmp);
emit_insn (tmp);
+ emitted_something = 1;
}
if (! rtx_equal_p (operands[0], operands[3]))
{
@@ -4373,9 +4482,12 @@
gen_rtx_SET (VOIDmode, operands[0],
operands[3]));
emit_insn (tmp);
+ emitted_something = 1;
}
+ if (! emitted_something)
+ emit_note (NULL, NOTE_INSN_DELETED);
DONE;
-}")
+})
;; Absolute value pattern.
@@ -4422,11 +4534,10 @@
(cond_exec
(match_dup 5)
(set (match_dup 0) (match_dup 3)))]
- "
{
operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? EQ : NE,
VOIDmode, operands[1], const0_rtx);
-}")
+})
;;
;; SImode if_then_else patterns.
@@ -4439,12 +4550,12 @@
[(match_operand:BI 1 "register_operand" "c,c,c,c,c,c,c,c,c")
(const_int 0)])
(match_operand:SI 2 "move_operand"
- "0,0,0,rim*f,rO,rO,rim*f,rO,rO")
+ "0,0,0,rnm*f,rO,rO,rnm*f,rO,rO")
(match_operand:SI 3 "move_operand"
- "rim*f,rO,rO,0,0,0,rim*f,rO,rO")))]
+ "rnm*f,rO,rO,0,0,0,rnm*f,rO,rO")))]
"ia64_move_ok (operands[0], operands[2])
&& ia64_move_ok (operands[0], operands[3])"
- "* abort ();"
+ { abort (); }
[(set_attr "predicable" "no")])
(define_insn "*abssi2_internal"
@@ -4490,11 +4601,10 @@
(cond_exec
(match_dup 5)
(set (match_dup 0) (match_dup 3)))]
- "
{
operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? EQ : NE,
VOIDmode, operands[1], const0_rtx);
-}")
+})
(define_insn_and_split "*cond_opsi2_internal"
[(set (match_operand:SI 0 "gr_register_operand" "=r")
@@ -4515,11 +4625,10 @@
(cond_exec
(match_dup 7)
(set (match_dup 0) (match_op_dup:SI 5 [(match_dup 3) (match_dup 4)])))]
- "
{
operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[6]) == NE ? EQ : NE,
VOIDmode, operands[1], const0_rtx);
-}"
+}
[(set_attr "itanium_class" "ialu")
(set_attr "predicable" "no")])
@@ -4543,11 +4652,10 @@
(cond_exec
(match_dup 7)
(set (match_dup 0) (match_op_dup:SI 5 [(match_dup 4) (match_dup 3)])))]
- "
{
operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[6]) == NE ? EQ : NE,
VOIDmode, operands[1], const0_rtx);
-}"
+}
[(set_attr "itanium_class" "ialu")
(set_attr "predicable" "no")])
@@ -4574,11 +4682,10 @@
(use (match_operand 2 "" ""))
(use (match_operand 3 "" ""))]
""
- "
{
- ia64_expand_call (NULL_RTX, operands[0], operands[2], 0);
+ ia64_expand_call (NULL_RTX, operands[0], operands[2], false);
DONE;
-}")
+})
(define_expand "sibcall"
[(use (match_operand:DI 0 "" ""))
@@ -4586,11 +4693,10 @@
(use (match_operand 2 "" ""))
(use (match_operand 3 "" ""))]
""
- "
{
- ia64_expand_call (NULL_RTX, operands[0], operands[2], 1);
+ ia64_expand_call (NULL_RTX, operands[0], operands[2], true);
DONE;
-}")
+})
;; Subroutine call instruction returning a value. Operand 0 is the hard
;; register in which the value is returned. There are three more operands,
@@ -4606,11 +4712,10 @@
(use (match_operand 3 "" ""))
(use (match_operand 4 "" ""))]
""
- "
{
- ia64_expand_call (operands[0], operands[1], operands[3], 0);
+ ia64_expand_call (operands[0], operands[1], operands[3], false);
DONE;
-}")
+})
(define_expand "sibcall_value"
[(use (match_operand 0 "" ""))
@@ -4619,11 +4724,10 @@
(use (match_operand 3 "" ""))
(use (match_operand 4 "" ""))]
""
- "
{
- ia64_expand_call (operands[0], operands[1], operands[3], 1);
+ ia64_expand_call (operands[0], operands[1], operands[3], true);
DONE;
-}")
+})
;; Call subroutine returning any type.
@@ -4633,7 +4737,6 @@
(match_operand 1 "" "")
(match_operand 2 "" "")])]
""
- "
{
int i;
@@ -4652,61 +4755,127 @@
emit_insn (gen_blockage ());
DONE;
-}")
+})
-(define_insn "call_nopic"
- [(call (mem:DI (match_operand:DI 0 "call_operand" "b,i"))
- (match_operand 1 "" ""))
- (clobber (match_operand:DI 2 "register_operand" "=b,b"))]
+(define_insn "call_nogp"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "?b,i"))
+ (const_int 0))
+ (clobber (match_operand:DI 1 "register_operand" "=b,b"))]
""
- "br.call%+.many %2 = %0"
+ "br.call%+.many %1 = %0"
[(set_attr "itanium_class" "br,scall")])
-(define_insn "call_value_nopic"
+(define_insn "call_value_nogp"
[(set (match_operand 0 "" "")
- (call (mem:DI (match_operand:DI 1 "call_operand" "b,i"))
- (match_operand 2 "" "")))
- (clobber (match_operand:DI 3 "register_operand" "=b,b"))]
+ (call (mem:DI (match_operand:DI 1 "call_operand" "?b,i"))
+ (const_int 0)))
+ (clobber (match_operand:DI 2 "register_operand" "=b,b"))]
""
- "br.call%+.many %3 = %1"
+ "br.call%+.many %2 = %1"
[(set_attr "itanium_class" "br,scall")])
-(define_insn "sibcall_nopic"
- [(call (mem:DI (match_operand:DI 0 "call_operand" "b,i"))
- (match_operand 1 "" ""))
- (use (match_operand:DI 2 "register_operand" "=b,b"))
- (use (match_operand:DI 3 "ar_pfs_reg_operand" ""))]
+(define_insn "sibcall_nogp"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "?b,i"))
+ (const_int 0))]
""
"br%+.many %0"
[(set_attr "itanium_class" "br,scall")])
-(define_insn "call_pic"
- [(call (mem:DI (match_operand:DI 0 "call_operand" "b,i"))
- (match_operand 1 "" ""))
- (use (unspec [(reg:DI 1)] 9))
- (clobber (match_operand:DI 2 "register_operand" "=b,b"))]
+(define_insn "call_gp"
+ [(call (mem (match_operand 0 "call_operand" "?r,i"))
+ (const_int 1))
+ (clobber (match_operand:DI 1 "register_operand" "=b,b"))
+ (clobber (match_scratch:DI 2 "=&r,X"))
+ (clobber (match_scratch:DI 3 "=b,X"))]
""
- "br.call%+.many %2 = %0"
+ "#"
[(set_attr "itanium_class" "br,scall")])
-(define_insn "call_value_pic"
+;; Irritatingly, we don't have access to INSN within the split body.
+;; See commentary in ia64_split_call as to why these aren't peep2.
+(define_split
+ [(call (mem (match_operand 0 "call_operand" ""))
+ (const_int 1))
+ (clobber (match_operand:DI 1 "register_operand" ""))
+ (clobber (match_scratch:DI 2 ""))
+ (clobber (match_scratch:DI 3 ""))]
+ "reload_completed && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+ [(const_int 0)]
+{
+ ia64_split_call (NULL_RTX, operands[0], operands[1], operands[2],
+ operands[3], true, false);
+ DONE;
+})
+
+(define_split
+ [(call (mem (match_operand 0 "call_operand" ""))
+ (const_int 1))
+ (clobber (match_operand:DI 1 "register_operand" ""))
+ (clobber (match_scratch:DI 2 ""))
+ (clobber (match_scratch:DI 3 ""))]
+ "reload_completed"
+ [(const_int 0)]
+{
+ ia64_split_call (NULL_RTX, operands[0], operands[1], operands[2],
+ operands[3], false, false);
+ DONE;
+})
+
+(define_insn "call_value_gp"
[(set (match_operand 0 "" "")
- (call (mem:DI (match_operand:DI 1 "call_operand" "b,i"))
- (match_operand 2 "" "")))
- (use (unspec [(reg:DI 1)] 9))
- (clobber (match_operand:DI 3 "register_operand" "=b,b"))]
+ (call (mem:DI (match_operand:DI 1 "call_operand" "?r,i"))
+ (const_int 1)))
+ (clobber (match_operand:DI 2 "register_operand" "=b,b"))
+ (clobber (match_scratch:DI 3 "=&r,X"))
+ (clobber (match_scratch:DI 4 "=b,X"))]
""
- "br.call%+.many %3 = %1"
+ "#"
[(set_attr "itanium_class" "br,scall")])
-(define_insn "sibcall_pic"
- [(call (mem:DI (match_operand:DI 0 "call_operand" "bi"))
- (match_operand 1 "" ""))
- (use (unspec [(reg:DI 1)] 9))
- (use (match_operand:DI 2 "register_operand" "=b"))
- (use (match_operand:DI 3 "ar_pfs_reg_operand" ""))]
+(define_split
+ [(set (match_operand 0 "" "")
+ (call (mem:DI (match_operand:DI 1 "call_operand" ""))
+ (const_int 1)))
+ (clobber (match_operand:DI 2 "register_operand" ""))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (match_scratch:DI 4 ""))]
+ "reload_completed && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+ [(const_int 0)]
+{
+ ia64_split_call (operands[0], operands[1], operands[2], operands[3],
+ operands[4], true, false);
+ DONE;
+})
+
+(define_split
+ [(set (match_operand 0 "" "")
+ (call (mem:DI (match_operand:DI 1 "call_operand" ""))
+ (const_int 1)))
+ (clobber (match_operand:DI 2 "register_operand" ""))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (match_scratch:DI 4 ""))]
+ "reload_completed"
+ [(const_int 0)]
+{
+ ia64_split_call (operands[0], operands[1], operands[2], operands[3],
+ operands[4], false, false);
+ DONE;
+})
+
+(define_insn_and_split "sibcall_gp"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "?r,i"))
+ (const_int 1))
+ (clobber (match_scratch:DI 1 "=&r,X"))
+ (clobber (match_scratch:DI 2 "=b,X"))]
""
- "br%+.many %0"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ ia64_split_call (NULL_RTX, operands[0], NULL_RTX, operands[1],
+ operands[2], true, true);
+ DONE;
+}
[(set_attr "itanium_class" "br")])
(define_insn "return_internal"
@@ -4817,29 +4986,26 @@
(define_expand "prologue"
[(const_int 1)]
""
- "
{
ia64_expand_prologue ();
DONE;
-}")
+})
(define_expand "epilogue"
[(return)]
""
- "
{
ia64_expand_epilogue (0);
DONE;
-}")
+})
(define_expand "sibcall_epilogue"
[(return)]
""
- "
{
ia64_expand_epilogue (1);
DONE;
-}")
+})
;; This prevents the scheduler from moving the SP decrement past FP-relative
;; stack accesses. This is the same as adddi3 plus the extra set.
@@ -4852,9 +5018,9 @@
(match_dup 3))]
""
"@
- add %0 = %1, %2
- adds %0 = %2, %1
- addl %0 = %2, %1"
+ add %0 = %1, %2
+ adds %0 = %2, %1
+ addl %0 = %2, %1"
[(set_attr "itanium_class" "ialu")])
;; This prevents the scheduler from moving the SP restore past FP-relative
@@ -4868,11 +5034,21 @@
"mov %0 = %1"
[(set_attr "itanium_class" "ialu")])
+;; As USE insns aren't meaningful after reload, this is used instead
+;; to prevent deleting instructions setting registers for EH handling
+(define_insn "prologue_use"
+ [(unspec:DI [(match_operand:DI 0 "register_operand" "")]
+ UNSPEC_PROLOGUE_USE)]
+ ""
+ ""
+ [(set_attr "itanium_class" "ignore")
+ (set_attr "predicable" "no")])
+
;; Allocate a new register frame.
(define_insn "alloc"
[(set (match_operand:DI 0 "register_operand" "=r")
- (unspec_volatile:DI [(const_int 0)] 0))
+ (unspec_volatile:DI [(const_int 0)] UNSPECV_ALLOC))
(use (match_operand:DI 1 "const_int_operand" "i"))
(use (match_operand:DI 2 "const_int_operand" "i"))
(use (match_operand:DI 3 "const_int_operand" "i"))
@@ -4886,7 +5062,8 @@
(define_expand "gr_spill"
[(parallel [(set (match_operand:DI 0 "memory_operand" "=m")
(unspec:DI [(match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "const_int_operand" "")] 1))
+ (match_operand:DI 2 "const_int_operand" "")]
+ UNSPEC_GR_SPILL))
(clobber (match_dup 3))])]
""
"operands[3] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);")
@@ -4894,20 +5071,23 @@
(define_insn "gr_spill_internal"
[(set (match_operand:DI 0 "memory_operand" "=m")
(unspec:DI [(match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "const_int_operand" "")] 1))
+ (match_operand:DI 2 "const_int_operand" "")]
+ UNSPEC_GR_SPILL))
(clobber (match_operand:DI 3 "register_operand" ""))]
""
- "*
{
- return \".mem.offset %2, 0\;%,st8.spill %0 = %1%P0\";
-}"
+ /* Note that we use a C output pattern here to avoid the predicate
+ being automatically added before the .mem.offset directive. */
+ return ".mem.offset %2, 0\;%,st8.spill %0 = %1%P0";
+}
[(set_attr "itanium_class" "st")])
;; Reads ar.unat
(define_expand "gr_restore"
[(parallel [(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(match_operand:DI 1 "memory_operand" "m")
- (match_operand:DI 2 "const_int_operand" "")] 2))
+ (match_operand:DI 2 "const_int_operand" "")]
+ UNSPEC_GR_RESTORE))
(use (match_dup 3))])]
""
"operands[3] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);")
@@ -4915,25 +5095,25 @@
(define_insn "gr_restore_internal"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(match_operand:DI 1 "memory_operand" "m")
- (match_operand:DI 2 "const_int_operand" "")] 2))
+ (match_operand:DI 2 "const_int_operand" "")]
+ UNSPEC_GR_RESTORE))
(use (match_operand:DI 3 "register_operand" ""))]
""
- "*
-{
- return \".mem.offset %2, 0\;%,ld8.fill %0 = %1%P1\";
-}"
+ { return ".mem.offset %2, 0\;%,ld8.fill %0 = %1%P1"; }
[(set_attr "itanium_class" "ld")])
(define_insn "fr_spill"
[(set (match_operand:TF 0 "memory_operand" "=m")
- (unspec:TF [(match_operand:TF 1 "register_operand" "f")] 3))]
+ (unspec:TF [(match_operand:TF 1 "register_operand" "f")]
+ UNSPEC_FR_SPILL))]
""
"stf.spill %0 = %1%P0"
[(set_attr "itanium_class" "stf")])
(define_insn "fr_restore"
[(set (match_operand:TF 0 "register_operand" "=f")
- (unspec:TF [(match_operand:TF 1 "memory_operand" "m")] 4))]
+ (unspec:TF [(match_operand:TF 1 "memory_operand" "m")]
+ UNSPEC_FR_RESTORE))]
""
"ldf.fill %0 = %1%P1"
[(set_attr "itanium_class" "fld")])
@@ -4944,15 +5124,33 @@
(define_insn "bsp_value"
[(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(const_int 0)] 20))]
+ (unspec:DI [(const_int 0)] UNSPEC_BSP_VALUE))]
""
- ";;\;mov %0 = ar.bsp"
+ "*
+{
+ return \";;\;%,mov %0 = ar.bsp\";
+}"
[(set_attr "itanium_class" "frar_i")])
(define_insn "set_bsp"
- [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] 5)]
- ""
- "flushrs\;mov r19=ar.rsc\;;;\;and r19=0x1c,r19\;;;\;mov ar.rsc=r19\;;;\;mov ar.bspstore=%0\;;;\;or r19=0x3,r19\;;;\;loadrs\;invala\;;;\;mov ar.rsc=r19"
+ [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
+ UNSPECV_SET_BSP)]
+ ""
+ "flushrs
+ mov r19=ar.rsc
+ ;;
+ and r19=0x1c,r19
+ ;;
+ mov ar.rsc=r19
+ ;;
+ mov ar.bspstore=%0
+ ;;
+ or r19=0x3,r19
+ ;;
+ loadrs
+ invala
+ ;;
+ mov ar.rsc=r19"
[(set_attr "itanium_class" "unknown")
(set_attr "predicable" "no")])
@@ -4961,10 +5159,11 @@
;; fixed later. This avoids an RSE DV.
(define_insn "flushrs"
- [(unspec [(const_int 0)] 21)]
+ [(unspec [(const_int 0)] UNSPEC_FLUSHRS)]
""
";;\;flushrs\;;;"
- [(set_attr "itanium_class" "rse_m")])
+ [(set_attr "itanium_class" "rse_m")
+ (set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
@@ -5012,34 +5211,25 @@
""
[(set_attr "itanium_class" "nop_x")])
-(define_insn "cycle_display"
- [(unspec [(match_operand 0 "const_int_operand" "")] 23)]
- ""
- "// cycle %0"
- [(set_attr "itanium_class" "ignore")
- (set_attr "predicable" "no")])
-
(define_insn "bundle_selector"
- [(unspec [(match_operand 0 "const_int_operand" "")] 22)]
+ [(unspec [(match_operand 0 "const_int_operand" "")] UNSPEC_BUNDLE_SELECTOR)]
""
- "*
-{
- return get_bundle_name (INTVAL (operands[0]));
-}"
+ { return get_bundle_name (INTVAL (operands[0])); }
[(set_attr "itanium_class" "ignore")
(set_attr "predicable" "no")])
;; Pseudo instruction that prevents the scheduler from moving code above this
;; point.
(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] 1)]
+ [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
""
""
[(set_attr "itanium_class" "ignore")
(set_attr "predicable" "no")])
(define_insn "insn_group_barrier"
- [(unspec_volatile [(match_operand 0 "const_int_operand" "")] 2)]
+ [(unspec_volatile [(match_operand 0 "const_int_operand" "")]
+ UNSPECV_INSN_GROUP_BARRIER)]
""
";;"
[(set_attr "itanium_class" "stop_bit")
@@ -5077,7 +5267,7 @@
(set_attr "predicable" "no")])
(define_insn "break_f"
- [(unspec_volatile [(const_int 0)] 3)]
+ [(unspec_volatile [(const_int 0)] UNSPECV_BREAK)]
""
"break.f 0"
[(set_attr "itanium_class" "nop_f")])
@@ -5119,14 +5309,13 @@
[(use (match_operand:OI 0 "memory_operand" ""))
(use (match_operand:DI 1 "register_operand" ""))]
""
- "
{
emit_library_call (gen_rtx_SYMBOL_REF (Pmode,
\"__ia64_save_stack_nonlocal\"),
0, VOIDmode, 2, XEXP (operands[0], 0), Pmode,
operands[1], Pmode);
DONE;
-}")
+})
(define_expand "nonlocal_goto"
[(use (match_operand 0 "general_operand" ""))
@@ -5134,7 +5323,6 @@
(use (match_operand 2 "general_operand" ""))
(use (match_operand 3 "general_operand" ""))]
""
- "
{
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, \"__ia64_nonlocal_goto\"),
LCT_NORETURN, VOIDmode, 3,
@@ -5143,34 +5331,24 @@
operands[3], Pmode);
emit_barrier ();
DONE;
-}")
-
-;; The rest of the setjmp processing happens with the nonlocal_goto expander.
-;; ??? This is not tested.
-(define_expand "builtin_setjmp_setup"
- [(use (match_operand:DI 0 "" ""))]
- ""
- "
-{
- emit_move_insn (ia64_gp_save_reg (0), gen_rtx_REG (DImode, GR_REG (1)));
- DONE;
-}")
+})
-(define_expand "builtin_setjmp_receiver"
- [(use (match_operand:DI 0 "" ""))]
+(define_insn_and_split "builtin_setjmp_receiver"
+ [(unspec_volatile [(match_operand:DI 0 "" "")] UNSPECV_SETJMP_RECEIVER)]
""
- "
+ "#"
+ "reload_completed"
+ [(const_int 0)]
{
- emit_move_insn (gen_rtx_REG (DImode, GR_REG (1)), ia64_gp_save_reg (0));
+ ia64_reload_gp ();
DONE;
-}")
+})
(define_expand "eh_epilogue"
[(use (match_operand:DI 0 "register_operand" "r"))
(use (match_operand:DI 1 "register_operand" "r"))
(use (match_operand:DI 2 "register_operand" "r"))]
""
- "
{
rtx bsp = gen_rtx_REG (Pmode, 10);
rtx sp = gen_rtx_REG (Pmode, 9);
@@ -5190,7 +5368,7 @@
cfun->machine->ia64_eh_epilogue_sp = sp;
cfun->machine->ia64_eh_epilogue_bsp = bsp;
-}")
+})
;; Builtin apply support.
@@ -5198,31 +5376,29 @@
[(use (match_operand:DI 0 "register_operand" ""))
(use (match_operand:OI 1 "memory_operand" ""))]
""
- "
{
emit_library_call (gen_rtx_SYMBOL_REF (Pmode,
- \"__ia64_restore_stack_nonlocal\"),
+ "__ia64_restore_stack_nonlocal"),
0, VOIDmode, 1,
copy_to_reg (XEXP (operands[1], 0)), Pmode);
DONE;
-}")
+})
;;; Intrinsics support.
(define_expand "mf"
[(set (mem:BLK (match_dup 0))
- (unspec:BLK [(mem:BLK (match_dup 0))] 12))]
+ (unspec:BLK [(mem:BLK (match_dup 0))] UNSPEC_MF))]
""
- "
{
operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
MEM_VOLATILE_P (operands[0]) = 1;
-}")
+})
(define_insn "*mf_internal"
[(set (match_operand:BLK 0 "" "")
- (unspec:BLK [(match_operand:BLK 1 "" "")] 12))]
+ (unspec:BLK [(match_operand:BLK 1 "" "")] UNSPEC_MF))]
""
"mf"
[(set_attr "itanium_class" "syst_m")])
@@ -5232,7 +5408,8 @@
(match_dup 1))
(set (match_operand:SI 1 "not_postinc_memory_operand" "+S")
(unspec:SI [(match_dup 1)
- (match_operand:SI 2 "fetchadd_operand" "n")] 19))]
+ (match_operand:SI 2 "fetchadd_operand" "n")]
+ UNSPEC_FETCHADD_ACQ))]
""
"fetchadd4.acq %0 = %1, %2"
[(set_attr "itanium_class" "sem")])
@@ -5242,7 +5419,8 @@
(match_dup 1))
(set (match_operand:DI 1 "not_postinc_memory_operand" "+S")
(unspec:DI [(match_dup 1)
- (match_operand:DI 2 "fetchadd_operand" "n")] 19))]
+ (match_operand:DI 2 "fetchadd_operand" "n")]
+ UNSPEC_FETCHADD_ACQ))]
""
"fetchadd8.acq %0 = %1, %2"
[(set_attr "itanium_class" "sem")])
@@ -5253,7 +5431,8 @@
(set (match_operand:SI 1 "not_postinc_memory_operand" "+S")
(unspec:SI [(match_dup 1)
(match_operand:SI 2 "gr_register_operand" "r")
- (match_operand:SI 3 "ar_ccv_reg_operand" "")] 13))]
+ (match_operand 3 "ar_ccv_reg_operand" "")]
+ UNSPEC_CMPXCHG_ACQ))]
""
"cmpxchg4.acq %0 = %1, %2, %3"
[(set_attr "itanium_class" "sem")])
@@ -5264,7 +5443,8 @@
(set (match_operand:DI 1 "not_postinc_memory_operand" "+S")
(unspec:DI [(match_dup 1)
(match_operand:DI 2 "gr_register_operand" "r")
- (match_operand:DI 3 "ar_ccv_reg_operand" "")] 13))]
+ (match_operand:DI 3 "ar_ccv_reg_operand" "")]
+ UNSPEC_CMPXCHG_ACQ))]
""
"cmpxchg8.acq %0 = %1, %2, %3"
[(set_attr "itanium_class" "sem")])
@@ -5298,48 +5478,59 @@
(define_insn "pred_rel_mutex"
[(set (match_operand:BI 0 "register_operand" "+c")
- (unspec:BI [(match_dup 0)] 7))]
+ (unspec:BI [(match_dup 0)] UNSPEC_PRED_REL_MUTEX))]
""
".pred.rel.mutex %0, %I0"
[(set_attr "itanium_class" "ignore")
(set_attr "predicable" "no")])
(define_insn "safe_across_calls_all"
- [(unspec_volatile [(const_int 0)] 8)]
+ [(unspec_volatile [(const_int 0)] UNSPECV_PSAC_ALL)]
""
".pred.safe_across_calls p1-p63"
[(set_attr "itanium_class" "ignore")
(set_attr "predicable" "no")])
(define_insn "safe_across_calls_normal"
- [(unspec_volatile [(const_int 0)] 9)]
+ [(unspec_volatile [(const_int 0)] UNSPECV_PSAC_NORMAL)]
""
- "*
{
emit_safe_across_calls (asm_out_file);
- return \"\";
-}"
+ return "";
+}
[(set_attr "itanium_class" "ignore")
(set_attr "predicable" "no")])
-;;
-;;
;; UNSPEC instruction definition to "swizzle" 32 bit pointer into 64 bit
;; pointer. This is used by the HP-UX 32 bit mode.
(define_insn "ptr_extend"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
- (unspec:DI [(match_operand:SI 1 "gr_register_operand" "r")] 24))]
+ (unspec:DI [(match_operand:SI 1 "gr_register_operand" "r")]
+ UNSPEC_ADDP4))]
""
"addp4 %0 = 0,%1"
[(set_attr "itanium_class" "ialu")])
;;
-;; As USE insns aren't meaningful after reload, this is used instead
-;; to prevent deleting instructions setting registers for EH handling
-(define_insn "prologue_use"
- [(unspec:DI [(match_operand:DI 0 "register_operand" "")] 25)]
- ""
- "// %0 needed for EH"
- [(set_attr "itanium_class" "ignore")
- (set_attr "predicable" "no")])
+;; Optimizations for ptr_extend
+
+(define_insn "*ptr_extend_plus_1"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (unspec:DI
+ [(plus:SI (match_operand:SI 1 "basereg_operand" "r")
+ (match_operand:SI 2 "gr_reg_or_14bit_operand" "rI"))]
+ UNSPEC_ADDP4))]
+ "addp4_optimize_ok (operands[1], operands[2])"
+ "addp4 %0 = %2, %1"
+ [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*ptr_extend_plus_2"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (unspec:DI
+ [(plus:SI (match_operand:SI 1 "gr_register_operand" "r")
+ (match_operand:SI 2 "basereg_operand" "r"))]
+ UNSPEC_ADDP4))]
+ "addp4_optimize_ok (operands[1], operands[2])"
+ "addp4 %0 = %1, %2"
+ [(set_attr "itanium_class" "ialu")])
diff --git a/contrib/gcc/config/ia64/linux.h b/contrib/gcc/config/ia64/linux.h
index 07882cd..e1d60f7 100644
--- a/contrib/gcc/config/ia64/linux.h
+++ b/contrib/gcc/config/ia64/linux.h
@@ -9,10 +9,15 @@
#undef CC1_SPEC
#define CC1_SPEC "%{profile:-p} %{G*}"
-/* ??? Maybe this should be in sysv4.h? */
-#define CPP_PREDEFINES "\
- -D__gnu_linux__ -D__linux -D__linux__ -D_LONGLONG \
- -Dlinux -Dunix -Asystem=linux"
+/* Target OS builtins. */
+#define TARGET_OS_CPP_BUILTINS() \
+do { \
+ builtin_assert("system=linux"); \
+ builtin_define_std("linux"); \
+ builtin_define_std("unix"); \
+ builtin_define("__gnu_linux__"); \
+ builtin_define("_LONGLONG"); \
+} while (0)
/* Need to override linux.h STARTFILE_SPEC, since it has crtbeginT.o in. */
#undef STARTFILE_SPEC
diff --git a/contrib/gcc/config/ia64/quadlib.c b/contrib/gcc/config/ia64/quadlib.c
index fac3b28..e55c97d 100644
--- a/contrib/gcc/config/ia64/quadlib.c
+++ b/contrib/gcc/config/ia64/quadlib.c
@@ -1,5 +1,5 @@
/* Subroutines for long double support.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -27,8 +27,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. */
-int _U_Qfcmp (long double a, long double b, int);
-long _U_Qfcnvfxt_quad_to_sgl (long double);
+extern int _U_Qfcmp (long double a, long double b, int);
+
+int _U_Qfeq (long double, long double);
+int _U_Qfne (long double, long double);
+int _U_Qfgt (long double, long double);
+int _U_Qfge (long double, long double);
+int _U_Qflt (long double, long double);
+int _U_Qfle (long double, long double);
+int _U_Qfcomp (long double, long double);
int
_U_Qfeq (long double a, long double b)
@@ -74,9 +81,3 @@ _U_Qfcomp (long double a, long double b)
return (_U_Qfcmp (a, b, 22) != 0 ? 1 : -1);
}
-
-long double
-_U_Qfneg (long double a)
-{
- return (0.0L - a);
-}
diff --git a/contrib/gcc/config/ia64/sysv4.h b/contrib/gcc/config/ia64/sysv4.h
index 840ebdd..3254fa5 100644
--- a/contrib/gcc/config/ia64/sysv4.h
+++ b/contrib/gcc/config/ia64/sysv4.h
@@ -33,8 +33,8 @@
the Intel simulator. So we must explicitly put variables in .bss
instead. This matters only if we care about the Intel assembler. */
-/* This is asm_output_aligned_bss from varasm.c without the ASM_GLOBALIZE_LABEL
- call at the beginning. */
+/* This is asm_output_aligned_bss from varasm.c without the
+ (*targetm.asm_out.globalize_label) call at the beginning. */
/* This is for final.c, because it is used by ASM_DECLARE_OBJECT_NAME. */
extern int size_directive_output;
@@ -42,8 +42,7 @@ extern int size_directive_output;
#undef ASM_OUTPUT_ALIGNED_LOCAL
#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
do { \
- if ((DECL) \
- && XSTR (XEXP (DECL_RTL (DECL), 0), 0)[0] == SDATA_NAME_FLAG_CHAR) \
+ if ((DECL) && sdata_symbolic_operand (XEXP (DECL_RTL (DECL), 0), Pmode)) \
sbss_section (); \
else \
bss_section (); \
@@ -62,8 +61,8 @@ do { \
#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
do { \
const char *name_ = NAME; \
- if (*name_ == SDATA_NAME_FLAG_CHAR) \
- name_++; \
+ if (*name_ == ENCODE_SECTION_INFO_CHAR) \
+ name_ += 2; \
if (*name_ == '*') \
name_++; \
else \
@@ -140,158 +139,15 @@ do { \
emit_safe_across_calls (STREAM); \
} while (0)
-/* A C statement or statements to switch to the appropriate
- section for output of DECL. DECL is either a `VAR_DECL' node
- or a constant of some sort. RELOC indicates whether forming
- the initial value of DECL requires link-time relocations.
-
- Set SECNUM to:
- 0 .text
- 1 .rodata
- 2 .data
- 3 .sdata
- 4 .bss
- 5 .sbss
-*/
-#define DO_SELECT_SECTION(SECNUM, DECL, RELOC) \
- do \
- { \
- if (TREE_CODE (DECL) == FUNCTION_DECL) \
- SECNUM = 0; \
- else if (TREE_CODE (DECL) == STRING_CST) \
- { \
- if (! flag_writable_strings) \
- SECNUM = 0x101; \
- else \
- SECNUM = 2; \
- } \
- else if (TREE_CODE (DECL) == VAR_DECL) \
- { \
- if (XSTR (XEXP (DECL_RTL (DECL), 0), 0)[0] \
- == SDATA_NAME_FLAG_CHAR) \
- SECNUM = 3; \
- /* ??? We need the extra RELOC check, because the default \
- is to only check RELOC if flag_pic is set, and we don't \
- set flag_pic (yet?). */ \
- else if (!DECL_READONLY_SECTION (DECL, RELOC) || (RELOC)) \
- SECNUM = 2; \
- else if (flag_merge_constants < 2) \
- /* C and C++ don't allow different variables to share \
- the same location. -fmerge-all-constants allows \
- even that (at the expense of not conforming). */ \
- SECNUM = 1; \
- else if (TREE_CODE (DECL_INITIAL (DECL)) == STRING_CST) \
- SECNUM = 0x201; \
- else \
- SECNUM = 0x301; \
- } \
- /* This could be a CONSTRUCTOR containing ADDR_EXPR of a VAR_DECL, \
- in which case we can't put it in a shared library rodata. */ \
- else if (flag_pic && (RELOC)) \
- SECNUM = 3; \
- else \
- SECNUM = 2; \
- } \
- while (0)
-
-/* We override svr4.h so that we can support the sdata section. */
-
-#undef SELECT_SECTION
-#define SELECT_SECTION(DECL,RELOC,ALIGN) \
- do \
- { \
- typedef void (*sec_fn) PARAMS ((void)); \
- static sec_fn const sec_functions[6] = \
- { \
- text_section, \
- const_section, \
- data_section, \
- sdata_section, \
- bss_section, \
- sbss_section \
- }; \
- \
- int sec; \
- \
- DO_SELECT_SECTION (sec, DECL, RELOC); \
- \
- switch (sec) \
- { \
- case 0x101: \
- mergeable_string_section (DECL, ALIGN, 0); \
- break; \
- case 0x201: \
- mergeable_string_section (DECL_INITIAL (DECL), \
- ALIGN, 0); \
- break; \
- case 0x301: \
- mergeable_constant_section (DECL_MODE (DECL), \
- ALIGN, 0); \
- break; \
- default: \
- (*sec_functions[sec]) (); \
- break; \
- } \
- } \
- while (0)
-
-#undef UNIQUE_SECTION
-#define UNIQUE_SECTION(DECL, RELOC) \
- do \
- { \
- static const char * const prefixes[6][2] = \
- { \
- { ".text.", ".gnu.linkonce.t." }, \
- { ".rodata.", ".gnu.linkonce.r." }, \
- { ".data.", ".gnu.linkonce.d." }, \
- { ".sdata.", ".gnu.linkonce.s." }, \
- { ".bss.", ".gnu.linkonce.b." }, \
- { ".sbss.", ".gnu.linkonce.sb." } \
- }; \
- \
- int nlen, plen, sec; \
- const char *name, *prefix; \
- char *string; \
- \
- DO_SELECT_SECTION (sec, DECL, RELOC); \
- \
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
- STRIP_NAME_ENCODING (name, name); \
- nlen = strlen (name); \
- \
- prefix = prefixes[sec & 0xff][DECL_ONE_ONLY(DECL)]; \
- plen = strlen (prefix); \
- \
- string = alloca (nlen + plen + 1); \
- \
- memcpy (string, prefix, plen); \
- memcpy (string + plen, name, nlen + 1); \
- \
- DECL_SECTION_NAME (DECL) = build_string (nlen + plen, string); \
- } \
- while (0)
-
-/* Similarly for constant pool data. */
-
-extern unsigned int ia64_section_threshold;
-#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE, RTX, ALIGN) \
-{ \
- if (GET_MODE_SIZE (MODE) > 0 \
- && GET_MODE_SIZE (MODE) <= ia64_section_threshold) \
- sdata_section (); \
- else if (flag_pic && symbolic_operand ((RTX), (MODE))) \
- data_section (); \
- else \
- mergeable_constant_section ((MODE), (ALIGN), 0); \
-}
+/* Override default elf definition. */
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION ia64_select_rtx_section
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const, in_sdata, in_sbss
+#define EXTRA_SECTIONS in_sdata, in_sbss
#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
- CONST_SECTION_FUNCTION \
SDATA_SECTION_FUNCTION \
SBSS_SECTION_FUNCTION
diff --git a/contrib/gcc/config/ia64/t-aix b/contrib/gcc/config/ia64/t-aix
index 2e738f9..7b6df46 100644
--- a/contrib/gcc/config/ia64/t-aix
+++ b/contrib/gcc/config/ia64/t-aix
@@ -6,11 +6,7 @@ CRTSTUFF_T_CFLAGS_S = -fPIC
TARGET_LIBGCC2_CFLAGS = -fPIC -D__64BIT__ -D_LONG_LONG -D_IA64 -D__int128=__size128_t
LIB2ADDEH += $(srcdir)/config/ia64/unwind-aix.c
-# Add crt[in].o to the list defined in t-ia64. These files provide
-# endpoints for crtbegin/end.
-
-EXTRA_PARTS=crti.o crtn.o crtbegin.o crtend.o crtbeginS.o crtendS.o
-
+# Assemble startup files.
crti.o: $(srcdir)/config/ia64/crti.asm $(GCC_PASSES)
$(GCC_FOR_TARGET) -c -o crti.o -x assembler $(srcdir)/config/ia64/crti.asm
crtn.o: $(srcdir)/config/ia64/crtn.asm $(GCC_PASSES)
diff --git a/contrib/gcc/config/ia64/t-hpux b/contrib/gcc/config/ia64/t-hpux
index 9f8296b..7b42fe5 100644
--- a/contrib/gcc/config/ia64/t-hpux
+++ b/contrib/gcc/config/ia64/t-hpux
@@ -13,3 +13,36 @@ LIB2FUNCS_EXTRA=quadlib.c
quadlib.c: $(srcdir)/config/ia64/quadlib.c
cat $(srcdir)/config/ia64/quadlib.c > quadlib.c
+
+# We get an undefined main when building a cross compiler because our
+# linkspec has "-u main" and we want that for linking but it makes
+# LIBGCC1_TEST fail because it uses -nostdlib -nostartup.
+
+LIBGCC1_TEST =
+
+# Don't run fix-headers. HP-UX headers are standards conformant
+# and don't need to be fixed up in this way.
+# If we remove this (and run fix-headers) we should define FIXPROTO_DEFINES
+# and also fix the definition of putenv in sys-protos.h (const char not char).
+
+STMP_FIXPROTO =
+
+# We do not want to include the EH stuff that linux uses, we want to use
+# the HP-UX libunwind library.
+
+LIB2ADDEH =
+
+SHLIB_EXT = .so
+SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
+ -Wl,+h,@shlib_base_name@.so.0 \
+ -o @shlib_base_name@.so @multilib_flags@ @shlib_objs@ -lc && \
+ rm -f @shlib_base_name@.so.0 && \
+ $(LN_S) @shlib_base_name@.so @shlib_base_name@.so.0
+# $(slibdir) double quoted to protect it from expansion while building
+# libgcc.mk. We want this delayed until actual install time.
+SHLIB_INSTALL = $(INSTALL_DATA) @shlib_base_name@.so $$(DESTDIR)$$(slibdir)/@shlib_base_name@.so.0; \
+ rm -f $$(DESTDIR)$$(slibdir)/@shlib_base_name@.so; \
+ $(LN_S) @shlib_base_name@.so.0 $$(DESTDIR)$$(slibdir)/@shlib_base_name@.so; \
+ chmod +x $$(DESTDIR)$$(slibdir)/@shlib_base_name@.so
+
+SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
diff --git a/contrib/gcc/config/ia64/t-ia64 b/contrib/gcc/config/ia64/t-ia64
index 41c0235..7c63b31 100644
--- a/contrib/gcc/config/ia64/t-ia64
+++ b/contrib/gcc/config/ia64/t-ia64
@@ -19,24 +19,30 @@ LIB1ASMFUNCS = __divtf3 __divdf3 __divsf3 \
SHLIB_MAPFILES += $(srcdir)/config/ia64/libgcc-ia64.ver
-# 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_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o
-
# Effectively disable the crtbegin/end rules using crtstuff.c
T = disable
# Assemble startup files.
crtbegin.o: $(srcdir)/config/ia64/crtbegin.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -o crtbegin.o -x assembler-with-cpp $(srcdir)/config/ia64/crtbegin.asm
+ $(GCC_FOR_TARGET) -I. -c -o crtbegin.o -x assembler-with-cpp \
+ $(srcdir)/config/ia64/crtbegin.asm
crtend.o: $(srcdir)/config/ia64/crtend.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -o crtend.o -x assembler-with-cpp $(srcdir)/config/ia64/crtend.asm
+ $(GCC_FOR_TARGET) -I. -c -o crtend.o -x assembler-with-cpp \
+ $(srcdir)/config/ia64/crtend.asm
crtbeginS.o: $(srcdir)/config/ia64/crtbegin.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -DSHARED -c -o crtbeginS.o -x assembler-with-cpp $(srcdir)/config/ia64/crtbegin.asm
+ $(GCC_FOR_TARGET) -I. -DSHARED -c -o crtbeginS.o \
+ -x assembler-with-cpp \
+ $(srcdir)/config/ia64/crtbegin.asm
crtendS.o: $(srcdir)/config/ia64/crtend.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -DSHARED -c -o crtendS.o -x assembler-with-cpp $(srcdir)/config/ia64/crtend.asm
+ $(GCC_FOR_TARGET) -I. -DSHARED -c -o crtendS.o -x assembler-with-cpp \
+ $(srcdir)/config/ia64/crtend.asm
crtfastmath.o: $(srcdir)/config/ia64/crtfastmath.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -c -o crtfastmath.o $(srcdir)/config/ia64/crtfastmath.c
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -c -o crtfastmath.o \
+ $(srcdir)/config/ia64/crtfastmath.c
+
+LIB2ADDEH = $(srcdir)/config/ia64/unwind-ia64.c $(srcdir)/unwind-sjlj.c \
+ $(srcdir)/unwind-c.c
-LIB2ADDEH = $(srcdir)/config/ia64/unwind-ia64.c $(srcdir)/unwind-sjlj.c
+ia64-c.o: $(srcdir)/config/ia64/ia64-c.c $(CONFIG_H) $(SYSTEM_H) \
+ $(TREE_H) $(CPPLIB_H) $(C_COMMON_H) c-pragma.h toplev.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/contrib/gcc/config/ia64/unwind-ia64.c b/contrib/gcc/config/ia64/unwind-ia64.c
index ca91539..12e46ae 100644
--- a/contrib/gcc/config/ia64/unwind-ia64.c
+++ b/contrib/gcc/config/ia64/unwind-ia64.c
@@ -143,7 +143,7 @@ typedef struct unw_state_record
unsigned int any_spills : 1; /* got any register spills? */
unsigned int in_body : 1; /* are we inside a body? */
unsigned int no_reg_stack_frame : 1; /* Don't adjust bsp for i&l regs */
- unsigned char *imask; /* imask of of spill_mask record or NULL */
+ unsigned char *imask; /* imask of spill_mask record or NULL */
unsigned long pr_val; /* predicate values */
unsigned long pr_mask; /* predicate mask */
long spill_offset; /* psp-relative offset for spill base */
@@ -1401,7 +1401,7 @@ unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
-static unw_decoder unw_decode_table[2][8] =
+static const unw_decoder unw_decode_table[2][8] =
{
/* prologue table: */
{
@@ -1642,6 +1642,29 @@ _Unwind_GetRegionStart (struct _Unwind_Context *context)
return context->region_start;
}
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+ struct unw_table_entry *ent;
+ unsigned long segment_base, gp;
+
+ ent = _Unwind_FindTableEntry (pc, &segment_base, &gp);
+ if (ent == NULL)
+ return NULL;
+ else
+ return (void *)(segment_base + ent->start_offset);
+}
+
+/* Get the value of the CFA as saved in CONTEXT. In GCC/Dwarf2 parlance,
+ the CFA is the value of the stack pointer on entry; In IA-64 unwind
+ parlance, this is the PSP. */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+ return (_Unwind_Ptr) context->psp;
+}
+
static _Unwind_Reason_Code
uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
diff --git a/contrib/gcc/config/interix.h b/contrib/gcc/config/interix.h
index 778c9ae..8d9f58f 100644
--- a/contrib/gcc/config/interix.h
+++ b/contrib/gcc/config/interix.h
@@ -85,13 +85,13 @@ for windows/multi thread */
#define STDC_0_IN_SYSTEM_HEADERS 1
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
#undef HANDLE_PRAGMA_WEAK /* until the link format can handle it */
/* Names to predefine in the preprocessor for this target machine. */
-#define DBX_DEBUGGING_INFO
-#define SDB_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
+#define SDB_DEBUGGING_INFO 1
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
@@ -100,12 +100,11 @@ for windows/multi thread */
#undef WCHAR_TYPE
#undef WCHAR_TYPE_SIZE
-#define WCHAR_UNSIGNED 1
#define WCHAR_TYPE "short unsigned int"
#define WCHAR_TYPE_SIZE 16
/* Our strategy for finding global constructors is a bit different, although
- not a lot. */
+ not a lot. */
#define DO_GLOBAL_CTORS_BODY \
do { \
int i; \
diff --git a/contrib/gcc/config/libgloss.h b/contrib/gcc/config/libgloss.h
index 8d7dd5b..f73982b 100644
--- a/contrib/gcc/config/libgloss.h
+++ b/contrib/gcc/config/libgloss.h
@@ -23,7 +23,7 @@ Boston, MA 02111-1307, USA. */
STARTFILE_SPEC is all wrong. */
/* The libgloss standard for crt0.s has the name based on the command line
- option. */
+ option. */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "%{!shared:%{pg:pgcrt0%O%s}%{!pg:%{p:pcrt0%O%s}%{!p:crt0%O%s}}}"
diff --git a/contrib/gcc/config/linux-aout.h b/contrib/gcc/config/linux-aout.h
index 2560bb8..13d9bfd6 100644
--- a/contrib/gcc/config/linux-aout.h
+++ b/contrib/gcc/config/linux-aout.h
@@ -19,11 +19,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. */
-/* Don't assume anything about the header files. */
+/* Don't assume anything about the header files. */
#define NO_IMPLICIT_EXTERN_C
/* GNU/Linux uses ctype from glibc.a. I am not sure how complete it is.
- For now, we play safe. It may change later. */
+ For now, we play safe. It may change later. */
#if 0
#undef MULTIBYTE_CHARS
@@ -41,5 +41,5 @@ Boston, MA 02111-1307, USA. */
#define SET_ASM_OP "\t.set\t"
-/* We need that too. */
-#define HANDLE_SYSV_PRAGMA
+/* We need that too. */
+#define HANDLE_SYSV_PRAGMA 1
diff --git a/contrib/gcc/config/linux.h b/contrib/gcc/config/linux.h
index f4fa716..2ddb9c7 100644
--- a/contrib/gcc/config/linux.h
+++ b/contrib/gcc/config/linux.h
@@ -20,11 +20,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. */
-/* Don't assume anything about the header files. */
+/* Don't assume anything about the header files. */
#define NO_IMPLICIT_EXTERN_C
/* GNU/Linux uses ctype from glibc.a. I am not sure how complete it is.
- For now, we play safe. It may change later. */
+ For now, we play safe. It may change later. */
#if 0
#undef MULTIBYTE_CHARS
@@ -43,7 +43,7 @@ Boston, MA 02111-1307, USA. */
/* 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'. */
+ object constructed before entering `main'. */
#undef STARTFILE_SPEC
#ifdef USE_GNULIBC_1
@@ -73,7 +73,7 @@ Boston, MA 02111-1307, USA. */
#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. */
+/* This is for -profile to use -lc_p instead of -lc. */
#ifndef CC1_SPEC
#define CC1_SPEC "%{profile:-p}"
#endif
@@ -85,7 +85,7 @@ Boston, MA 02111-1307, USA. */
#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. */
+ -profile or -ggdb to LDFLAGS at the link time, respectively. */
#if 1
#ifdef USE_GNULIBC_1
#define LIB_SPEC \
@@ -93,9 +93,9 @@ Boston, MA 02111-1307, USA. */
%{!profile:%{!ggdb:-lc} %{ggdb:-lg}}}"
#else
#define LIB_SPEC \
- "%{shared: -lc} \
- %{!shared: %{mieee-fp:-lieee} %{pthread:-lpthread} \
- %{profile:-lc_p} %{!profile: -lc}}"
+ "%{pthread:-lpthread} \
+ %{shared:-lc} \
+ %{!shared:%{mieee-fp:-lieee} %{profile:-lc_p}%{!profile:-lc}}"
#endif
#else
#define LIB_SPEC \
@@ -110,3 +110,5 @@ Boston, MA 02111-1307, USA. */
/* Define this so we can compile MS code for use with WINE. */
#define HANDLE_PRAGMA_PACK_PUSH_POP
+
+#define TARGET_HAS_F_SETLKW
diff --git a/contrib/gcc/config/lynx-ng.h b/contrib/gcc/config/lynx-ng.h
index 3ae07e1..7c257c7 100644
--- a/contrib/gcc/config/lynx-ng.h
+++ b/contrib/gcc/config/lynx-ng.h
@@ -19,7 +19,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This is for backwards compatibility with older Lynx tools, which use
- a version of a.out format. */
+ a version of a.out format. */
#undef ASM_SPEC
#define ASM_SPEC "%{mcoff:-C}"
@@ -54,7 +54,7 @@ Boston, MA 02111-1307, USA. */
/* We want to output DBX debugging information. */
-#define DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
@@ -62,7 +62,7 @@ Boston, MA 02111-1307, USA. */
we can create debuggable SDB/coff files. This won't be needed when
stabs-in-coff works. */
-#define SDB_DEBUGGING_INFO
+#define SDB_DEBUGGING_INFO 1
/* Generate calls to memcpy, memcmp and memset. */
@@ -70,7 +70,7 @@ Boston, MA 02111-1307, USA. */
/* Handle #pragma pack and sometimes #pragma weak. */
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
#define TARGET_THREADS (target_flags & MASK_THREADS)
#define MASK_THREADS 0x40000000
@@ -103,7 +103,7 @@ Boston, MA 02111-1307, USA. */
#define MD_EXEC_PREFIX "/usr/local/lib/gcc-"
-/* This is needed because /bin/ld does not handle -L options correctly. */
+/* This is needed because /bin/ld does not handle -L options correctly. */
#define LINK_LIBGCC_SPECIAL_1
diff --git a/contrib/gcc/config/lynx.h b/contrib/gcc/config/lynx.h
index 012a701..e060675 100644
--- a/contrib/gcc/config/lynx.h
+++ b/contrib/gcc/config/lynx.h
@@ -1,5 +1,6 @@
/* Target independent definitions for LynxOS.
- Copyright (C) 1993, 1994, 1995, 1996, 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1996, 1999, 2000, 2002
+ Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,27 +20,27 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* LynxOS is a multi-platform Unix, similar to SVR3, but not identical.
- We can get quite a bit from generic svr3, but have to do some overrides. */
+ We can get quite a bit from generic svr3, but have to do some overrides. */
#include "svr3.h"
-/* Define various macros, depending on the combination of flags. */
+/* Define various macros, depending on the combination of flags. */
#undef CPP_SPEC
#define CPP_SPEC "%{mthreads:-D_MULTITHREADED} \
%{mposix:-D_POSIX_SOURCE} \
%{msystem-v:-I/usr/include_v}"
-/* No asm spec needed, since using GNU assembler always. */
+/* No asm spec needed, since using GNU assembler always. */
-/* No linker spec needed, since using GNU linker always. */
+/* No linker spec needed, since using GNU linker always. */
#undef LIB_SPEC
#define LIB_SPEC "%{mthreads:-L/lib/thread/} \
%{msystem-v:-lc_v} \
%{!msystem-v:%{mposix:-lc_p} -lc -lm}"
-/* Set the appropriate names for the Lynx startfiles. */
+/* Set the appropriate names for the Lynx startfiles. */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "%{p:%{mthreads:thread/pinit1.o%s}%{!mthreads:pinit1.o%s}}%{!p:%{msystem-v:vinit1.o%s -e_start}%{!msystem-v:%{mthreads:thread/init1.o%s}%{!mthreads:init1.o%s}}}"
@@ -47,7 +48,7 @@ Boston, MA 02111-1307, USA. */
#undef ENDFILE_SPEC
#define ENDFILE_SPEC "%{p:_etext.o%s}%{!p:initn.o%s}"
-/* Override the svr3 versions. */
+/* Override the svr3 versions. */
#undef WCHAR_TYPE
#define WCHAR_TYPE "int"
@@ -57,16 +58,16 @@ Boston, MA 02111-1307, USA. */
/* We want to output DBX (stabs) debugging information normally. */
-#define DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
/* It is convenient to be able to generate standard coff debugging
- if requested via -gcoff. */
+ if requested via -gcoff. */
-#define SDB_DEBUGGING_INFO
+#define SDB_DEBUGGING_INFO 1
-/* Be function-relative for block and source line stab directives. */
+/* Be function-relative for block and source line stab directives. */
#define DBX_BLOCKS_FUNCTION_RELATIVE 1
@@ -94,9 +95,9 @@ Boston, MA 02111-1307, USA. */
/* Handle #pragma pack and sometimes #pragma weak. */
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
-/* Some additional command-line options. */
+/* Some additional command-line options. */
#define TARGET_THREADS (target_flags & MASK_THREADS)
#define MASK_THREADS 0x40000000
@@ -123,16 +124,15 @@ do { \
} while (0)
/* Since init.o et al put all sorts of stuff into the init section,
- we can't use the standard init section support in crtbegin.o. */
+ we can't use the standard init section support in crtbegin.o. */
#undef INIT_SECTION_ASM_OP
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const, in_fini
+#define EXTRA_SECTIONS in_fini
#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
- CONST_SECTION_FUNCTION \
FINI_SECTION_FUNCTION
#undef CTORS_SECTION_ASM_OP
@@ -143,6 +143,6 @@ do { \
#undef DO_GLOBAL_CTORS_BODY
#undef DO_GLOBAL_DTORS_BODY
-/* LynxOS doesn't have mcount. */
+/* LynxOS doesn't have mcount. */
#undef FUNCTION_PROFILER
#define FUNCTION_PROFILER(file, profile_label_no)
diff --git a/contrib/gcc/config/netbsd-aout.h b/contrib/gcc/config/netbsd-aout.h
index a853df5..7c2f865 100644
--- a/contrib/gcc/config/netbsd-aout.h
+++ b/contrib/gcc/config/netbsd-aout.h
@@ -19,7 +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. */
-/* This defines which switch letters take arguments. */
+/* TARGET_OS_CPP_BUILTINS() common to all NetBSD a.out targets. */
+#define NETBSD_OS_CPP_BUILTINS_AOUT() \
+ do \
+ { \
+ NETBSD_OS_CPP_BUILTINS_COMMON(); \
+ } \
+ while (0)
+
+/* This defines which switch letters take arguments. */
#undef SWITCH_TAKES_ARG
#define SWITCH_TAKES_ARG(CHAR) \
@@ -50,8 +58,8 @@ Boston, MA 02111-1307, USA. */
/* Provide a LINK_SPEC appropriate for NetBSD a.out. Here we provide
support for the special GCC options -static, -assert, and -nostdlib. */
-#undef LINK_SPEC
-#define LINK_SPEC \
+#undef NETBSD_LINK_SPEC_AOUT
+#define NETBSD_LINK_SPEC_AOUT \
"%{nostdlib:-nostdlib} \
%{!shared: \
%{!nostdlib: \
@@ -63,6 +71,9 @@ Boston, MA 02111-1307, USA. */
%{R*} \
%{assert*}"
+/* Default LINK_SPEC. */
+#undef LINK_SPEC
+#define LINK_SPEC NETBSD_LINK_SPEC_AOUT
/* Some imports from svr4.h in support of shared libraries. */
@@ -127,11 +138,7 @@ Boston, MA 02111-1307, USA. */
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
do \
{ \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
- putc ('\n', FILE); \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
ASM_OUTPUT_LABEL(FILE, NAME); \
} \
@@ -140,29 +147,26 @@ Boston, MA 02111-1307, USA. */
/* Write the extra assembler code needed to declare an object properly. */
-#undef ASM_DECLARE_OBJECT_NAME
-#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
- do \
- { \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
- putc ('\n', FILE); \
- size_directive_output = 0; \
- if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
- { \
- size_directive_output = 1; \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, ",%d\n", \
- int_size_in_bytes (TREE_TYPE (DECL))); \
- } \
- ASM_OUTPUT_LABEL(FILE, NAME); \
- } \
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ HOST_WIDE_INT size; \
+ \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
+ \
+ size_directive_output = 0; \
+ if (!flag_inhibit_size_directive \
+ && (DECL) && DECL_SIZE (DECL)) \
+ { \
+ size_directive_output = 1; \
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \
+ } \
+ \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+ } \
while (0)
-
/* Output the size directive for a decl in rest_of_decl_compilation
in the case where we did not do so before the initializer.
Once we find the error_mark_node, we know that the value of
@@ -174,16 +178,15 @@ Boston, MA 02111-1307, USA. */
do \
{ \
const char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
+ HOST_WIDE_INT size; \
if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
&& ! AT_END && TOP_LEVEL \
&& DECL_INITIAL (DECL) == error_mark_node \
&& !size_directive_output) \
{ \
size_directive_output = 1; \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, name); \
- fprintf (FILE, ",%d\n", \
- int_size_in_bytes (TREE_TYPE (DECL))); \
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, name, size); \
} \
} \
while (0)
@@ -196,19 +199,6 @@ Boston, MA 02111-1307, USA. */
do \
{ \
if (!flag_inhibit_size_directive) \
- { \
- char label[256]; \
- static int labelno; \
- labelno++; \
- ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \
- ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, (FNAME)); \
- fprintf (FILE, ","); \
- assemble_name (FILE, label); \
- fprintf (FILE, "-"); \
- assemble_name (FILE, (FNAME)); \
- putc ('\n', FILE); \
- } \
+ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
} \
while (0)
diff --git a/contrib/gcc/config/netbsd-elf.h b/contrib/gcc/config/netbsd-elf.h
index 7dd9ff3..cb38b93 100644
--- a/contrib/gcc/config/netbsd-elf.h
+++ b/contrib/gcc/config/netbsd-elf.h
@@ -19,6 +19,14 @@ 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. */
+/* TARGET_OS_CPP_BUILTINS() common to all NetBSD ELF targets. */
+#define NETBSD_OS_CPP_BUILTINS_ELF() \
+ do \
+ { \
+ NETBSD_OS_CPP_BUILTINS_COMMON(); \
+ builtin_define ("__ELF__"); \
+ } \
+ while (0)
/* This defines which switch letters take arguments. On NetBSD, most
of the normal cases (defined by gcc.c) apply, and we also have -h*
@@ -38,39 +46,50 @@ Boston, MA 02111-1307, USA. */
of the support for getting C++ file-scope static objects
constructed before entering "main". */
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC \
+#define NETBSD_STARTFILE_SPEC \
"%{!shared: \
%{pg:gcrt0%O%s} \
%{!pg: \
%{p:gcrt0%O%s} \
%{!p:crt0%O%s}}} \
- %{!shared:crtbegin%O%s} %{shared:crtbeginS%O%s}"
+ %:if-exists(crti%O%s) \
+ %{static:%:if-exists-else(crtbeginT%O%s crtbegin%O%s)} \
+ %{!static: \
+ %{!shared:crtbegin%O%s} %{shared:crtbeginS%O%s}}"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC NETBSD_STARTFILE_SPEC
/* Provide an ENDFILE_SPEC appropriate for NetBSD ELF. Here we
add crtend.o, which provides part of the support for getting
C++ file-scope static objects deconstructed after exiting "main". */
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC \
- "%{!shared:crtend%O%s} %{shared:crtendS%O%s}"
+#define NETBSD_ENDFILE_SPEC \
+ "%{!shared:crtend%O%s} %{shared:crtendS%O%s} \
+ %:if-exists(crtn%O%s)"
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC NETBSD_ENDFILE_SPEC
/* Provide a LINK_SPEC appropriate for NetBSD ELF. Here we provide
support for the special GCC options -assert, -R, -rpath, -shared,
- -nostdlib, -static, -rdynamic, and -dynamic-linker. */
-
-#undef LINK_SPEC
-#define LINK_SPEC \
- "%{assert*} %{R*} %{rpath*} \
- %{shared:-shared} \
- %{!shared: \
- -dc -dp \
- %{!nostdlib: \
- %{!r*: \
- %{!e*:-e __start}}} \
- %{!static: \
- %{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /usr/libexec/ld.elf_so}} \
+ -nostdlib, -static, -rdynamic, and -dynamic-linker.
+
+ Target-specific code can use this in conjunction with any other
+ target-specific LINK_SPEC options.
+
+ Target-specific code must provide the %(netbsd_entry_point) spec. */
+
+#define NETBSD_LINK_SPEC_ELF \
+ "%{assert*} %{R*} %{rpath*} \
+ %{shared:-shared} \
+ %{!shared: \
+ -dc -dp \
+ %{!nostdlib: \
+ %{!r*: \
+ %{!e*:-e %(netbsd_entry_point)}}} \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /usr/libexec/ld.elf_so}} \
%{static:-static}}"
diff --git a/contrib/gcc/config/netbsd.h b/contrib/gcc/config/netbsd.h
index 227942c..0441389 100644
--- a/contrib/gcc/config/netbsd.h
+++ b/contrib/gcc/config/netbsd.h
@@ -1,6 +1,50 @@
+/* Base configuration file for all NetBSD targets.
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* TARGET_OS_CPP_BUILTINS() common to all NetBSD targets. */
+#define NETBSD_OS_CPP_BUILTINS_COMMON() \
+ do \
+ { \
+ builtin_define ("__NetBSD__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=NetBSD"); \
+ } \
+ while (0)
+
+/* TARGET_OS_CPP_BUILTINS() common to all LP64 NetBSD targets. */
+#define NETBSD_OS_CPP_BUILTINS_LP64() \
+ do \
+ { \
+ builtin_define ("_LP64"); \
+ } \
+ while (0)
+
+/* CPP_SPEC parts common to all NetBSD targets. */
+#define NETBSD_CPP_SPEC \
+ "%{posix:-D_POSIX_SOURCE} \
+ %{pthread:-D_REENTRANT -D_PTHREADS}"
+
/* NETBSD_NATIVE is defined when gcc is integrated into the NetBSD
source tree so it can be configured appropriately without using
- the GNU configure/build mechanism. */
+ the GNU configure/build mechanism. */
#ifdef NETBSD_NATIVE
@@ -35,20 +79,39 @@
#endif /* NETBSD_NATIVE */
-/* Provide a CPP_SPEC appropriate for NetBSD. Currently we just deal with
- the GCC option `-posix'. */
+/* Provide a LIB_SPEC appropriate for NetBSD. Here we:
-#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE}"
+ 1. Select the appropriate set of libs, depending on whether we're
+ profiling.
+ 2. Include the pthread library if -pthread is specified (only
+ if threads are enabled).
-/* Provide a LIB_SPEC appropriate for NetBSD. Just select the appropriate
- libc, depending on whether we're doing profiling; if `-posix' is specified,
- link against the appropriate libposix first. Don't include libc when
- linking a shared library. */
+ 3. Include the posix library if -posix is specified.
-#undef LIB_SPEC
-#define LIB_SPEC \
+ FIXME: Could eliminate the duplication here if we were allowed to
+ use string concatenation. */
+
+#ifdef NETBSD_ENABLE_PTHREADS
+#define NETBSD_LIB_SPEC \
+ "%{pthread: \
+ %{!p: \
+ %{!pg:-lpthread}} \
+ %{p:-lpthread_p} \
+ %{pg:-lpthread_p}} \
+ %{posix: \
+ %{!p: \
+ %{!pg:-lposix}} \
+ %{p:-lposix_p} \
+ %{pg:-lposix_p}} \
+ %{!shared: \
+ %{!symbolic: \
+ %{!p: \
+ %{!pg:-lc}} \
+ %{p:-lc_p} \
+ %{pg:-lc_p}}}"
+#else
+#define NETBSD_LIB_SPEC \
"%{posix: \
%{!p: \
%{!pg:-lposix}} \
@@ -60,24 +123,30 @@
%{!pg:-lc}} \
%{p:-lc_p} \
%{pg:-lc_p}}}"
+#endif
+
+#undef LIB_SPEC
+#define LIB_SPEC NETBSD_LIB_SPEC
/* Provide a LIBGCC_SPEC appropriate for NetBSD. We also want to exclude
libgcc with -symbolic. */
-#undef LIBGCC_SPEC
#ifdef NETBSD_NATIVE
-#define LIBGCC_SPEC \
+#define NETBSD_LIBGCC_SPEC \
"%{!symbolic: \
%{!shared: \
%{!p: \
- %{!pg: -lgcc}}} \
+ %{!pg: -lgcc}}} \
%{shared: -lgcc_pic} \
%{p: -lgcc_p} \
%{pg: -lgcc_p}}"
#else
-#define LIBGCC_SPEC "%{!shared:%{!symbolic: -lgcc}}"
+#define NETBSD_LIBGCC_SPEC "%{!shared:%{!symbolic: -lgcc}}"
#endif
+#undef LIBGCC_SPEC
+#define LIBGCC_SPEC NETBSD_LIBGCC_SPEC
+
/* When building shared libraries, the initialization and finalization
functions for the library are .init and .fini respectively. */
@@ -93,11 +162,6 @@
fprintf ((STREAM), "void __fini() {\n\t%s();\n}\n", (FUNC)); \
} while (0)
-/* Allow #sccs in preprocessor. */
-
-#undef SCCS_DIRECTIVE
-#define SCCS_DIRECTIVE
-
#undef TARGET_HAS_F_SETLKW
#define TARGET_HAS_F_SETLKW
@@ -108,7 +172,7 @@
/* Handle #pragma weak and #pragma pack. */
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
/* Define some types that are the same on all NetBSD platforms,
@@ -122,3 +186,51 @@
#undef WINT_TYPE
#define WINT_TYPE "int"
+
+
+/* Attempt to turn on execute permission for the stack. This may be
+ used by TRANSFER_FROM_TRAMPOLINE of the target needs it (that is,
+ if the target machine can change execute permissions on a page).
+
+ There is no way to query the execute permission of the stack, so
+ we always issue the mprotect() call.
+
+ Note that we go out of our way to use namespace-non-invasive calls
+ here. Unfortunately, there is no libc-internal name for mprotect().
+
+ Also note that no errors should be emitted by this code; it is considered
+ dangerous for library calls to send messages to stdout/stderr. */
+
+#define NETBSD_ENABLE_EXECUTE_STACK \
+extern void __enable_execute_stack (void *); \
+void \
+__enable_execute_stack (addr) \
+ void *addr; \
+{ \
+ extern int mprotect (void *, size_t, int); \
+ extern int __sysctl (int *, unsigned int, void *, size_t *, \
+ void *, size_t); \
+ \
+ static int size; \
+ static long mask; \
+ \
+ char *page, *end; \
+ \
+ if (size == 0) \
+ { \
+ int mib[2]; \
+ size_t len; \
+ \
+ mib[0] = 6; /* CTL_HW */ \
+ mib[1] = 7; /* HW_PAGESIZE */ \
+ len = sizeof (size); \
+ (void) __sysctl (mib, 2, &size, &len, NULL, 0); \
+ mask = ~((long) size - 1); \
+ } \
+ \
+ page = (char *) (((long) addr) & mask); \
+ end = (char *) ((((long) (addr + TRAMPOLINE_SIZE)) & mask) + size); \
+ \
+ /* 7 == PROT_READ | PROT_WRITE | PROT_EXEC */ \
+ (void) mprotect (page, end - page, 7); \
+}
diff --git a/contrib/gcc/config/openbsd-oldgas.h b/contrib/gcc/config/openbsd-oldgas.h
new file mode 100644
index 0000000..823db70
--- /dev/null
+++ b/contrib/gcc/config/openbsd-oldgas.h
@@ -0,0 +1,23 @@
+/* Generic settings for a.out OpenBSD systems.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by David E. O'Brien <obrien@FreeBSD.org>.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+#define OBSD_OLD_GAS
diff --git a/contrib/gcc/config/openbsd.h b/contrib/gcc/config/openbsd.h
index 2c0738f..1c215eb 100644
--- a/contrib/gcc/config/openbsd.h
+++ b/contrib/gcc/config/openbsd.h
@@ -175,10 +175,12 @@ Boston, MA 02111-1307, USA. */
#undef TYPE_ASM_OP
#undef SIZE_ASM_OP
#undef SET_ASM_OP
+#undef GLOBAL_ASM_OP
#define TYPE_ASM_OP "\t.type\t"
#define SIZE_ASM_OP "\t.size\t"
#define SET_ASM_OP "\t.set\t"
+#define GLOBAL_ASM_OP "\t.globl\t"
/* The following macro defines the format used to output the second
operand of the .type assembler directive. */
@@ -203,11 +205,7 @@ Boston, MA 02111-1307, USA. */
#undef ASM_DECLARE_FUNCTION_NAME
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
do { \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- fputs (" , ", FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
- putc ('\n', FILE); \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
ASM_OUTPUT_LABEL(FILE, NAME); \
} while (0)
@@ -216,38 +214,29 @@ Boston, MA 02111-1307, USA. */
#ifndef OBSD_HAS_DECLARE_FUNCTION_SIZE
/* Declare the size of a function. */
#undef ASM_DECLARE_FUNCTION_SIZE
-#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
- do { \
- if (!flag_inhibit_size_directive) \
- { \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, (FNAME)); \
- fputs (" , . - ", FILE); \
- assemble_name (FILE, (FNAME)); \
- putc ('\n', FILE); \
- } \
+#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
+ do { \
+ if (!flag_inhibit_size_directive) \
+ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
} while (0)
#endif
#ifndef OBSD_HAS_DECLARE_OBJECT
/* Extra assembler code needed to declare an object properly. */
#undef ASM_DECLARE_OBJECT_NAME
-#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
- do { \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- fputs (" , ", FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
- putc ('\n', FILE); \
- size_directive_output = 0; \
- if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
- { \
- size_directive_output = 1; \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, " , %d\n", int_size_in_bytes (TREE_TYPE (DECL)));\
- } \
- ASM_OUTPUT_LABEL (FILE, NAME); \
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
+ do { \
+ HOST_WIDE_INT size; \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
+ size_directive_output = 0; \
+ if (!flag_inhibit_size_directive \
+ && (DECL) && DECL_SIZE (DECL)) \
+ { \
+ size_directive_output = 1; \
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \
+ } \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
} while (0)
/* Output the size directive for a decl in rest_of_decl_compilation
@@ -259,15 +248,15 @@ Boston, MA 02111-1307, USA. */
#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
do { \
const char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
+ HOST_WIDE_INT size; \
if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
&& ! AT_END && TOP_LEVEL \
&& DECL_INITIAL (DECL) == error_mark_node \
&& !size_directive_output) \
{ \
size_directive_output = 1; \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, name); \
- fprintf (FILE, " , %d\n", int_size_in_bytes (TREE_TYPE (DECL)));\
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, name, size); \
} \
} while (0)
#endif
@@ -286,14 +275,6 @@ do { \
do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
fputc ('\n', FILE); } while (0)
#endif
-
-/* Tell the assembler that a symbol is global. */
-#ifndef ASM_GLOBALIZE_LABEL
-#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
- do { fputs ("\t.globl\t", FILE); assemble_name (FILE, NAME); \
- fputc ('\n', FILE); } while(0)
-#endif
-
/* Storage layout. */
@@ -306,5 +287,5 @@ do { \
code layout needs HANDLE_PRAGMA_WEAK asserted for __attribute((weak)) to
work. On the other hand, we don't define HANDLE_PRAGMA_WEAK directly,
as this depends on a few other details as well... */
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
diff --git a/contrib/gcc/config/psos.h b/contrib/gcc/config/psos.h
index 9529a21..72825d4 100644
--- a/contrib/gcc/config/psos.h
+++ b/contrib/gcc/config/psos.h
@@ -51,13 +51,13 @@ Boston, MA 02111-1307, USA.
board-support package (e.g. M162) and the run-time configuration
(e.g. application vs. ram-image vs. rom-image). Specify the
startfile in a linker-script created from the generic
- architecture-specific linker-scripts. */
+ architecture-specific linker-scripts. */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC ""
-/* Predefined macros (independent of processor type). */
+/* Predefined macros (independent of processor type). */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dpsos"
@@ -85,4 +85,4 @@ Boston, MA 02111-1307, USA.
/* For pSOS we use DBX debugging info. */
-#define DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
diff --git a/contrib/gcc/config/ptx4.h b/contrib/gcc/config/ptx4.h
index c934c1c..3d8e527 100644
--- a/contrib/gcc/config/ptx4.h
+++ b/contrib/gcc/config/ptx4.h
@@ -160,16 +160,15 @@ Boston, MA 02111-1307, USA.
%{!p:-Y P,/lib:/usr/lib}} \
%{Qy:} %{!Qn:-Qy}"
-/* Gcc automatically adds in one of the files /lib/values-Xc.o,
- /lib/values-Xa.o, or /lib/values-Xt.o for each final link
- step (depending upon the other gcc options selected, such as
- -traditional and -ansi). These files each contain one (initialized)
- copy of a special variable called `_lib_version'. Each one of these
- files has `_lib_version' initialized to a different (enum) value.
- The SVR4 library routines query the value of `_lib_version' at run
- to decide how they should behave. Specifically, they decide (based
- upon the value of `_lib_version') if they will act in a strictly ANSI
- conforming manner or not.
+/* Gcc automatically adds in one of the files /lib/values-Xc.o
+ or /lib/values-Xa.o, for each final link step (depending upon the other
+ gcc options selected, such as -ansi). These files each contain one
+ (initialized) copy of a special variable called `_lib_version'. Each
+ one of these files has `_lib_version' initialized to a different (enum)
+ value. The SVR4 library routines query the value of `_lib_version'
+ at run to decide how they should behave. Specifically, they decide
+ (based upon the value of `_lib_version') if they will act in a strictly
+ ANSI conforming manner or not.
*/
#undef STARTFILE_SPEC
@@ -178,16 +177,10 @@ Boston, MA 02111-1307, USA.
%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}}}\
%{pg:gcrti.o%s}%{!pg:crti.o%s} \
%{ansi:values-Xc.o%s} \
- %{!ansi: \
- %{traditional:values-Xt.o%s} \
- %{!traditional:values-Xa.o%s}} \
+ %{!ansi:values-Xa.o%s} \
crtbegin.o%s"
-/* Allow #sccs in preprocessor. */
-
-#define SCCS_DIRECTIVE
-
-/* Don't use bcopy, which doesn't handle overlaps before DYNIX/ptx 4.6. */
+/* Don't use bcopy, which doesn't handle overlaps before DYNIX/ptx 4.6. */
#undef HAVE_BCOPY
@@ -246,7 +239,7 @@ while (0)
/* This says how to output assembler code to declare an uninitialized
external linkage data item. There's a bug in the DYNIX/ptx linker
(PR 254649) when the alignment for such an object is specified, so
- ignore the ALIGN parameter. */
+ ignore the ALIGN parameter. */
#undef ASM_OUTPUT_ALIGNED_COMMON
#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
diff --git a/contrib/gcc/config/rs6000/aix.h b/contrib/gcc/config/rs6000/aix.h
index d8dde5b..505d758 100644
--- a/contrib/gcc/config/rs6000/aix.h
+++ b/contrib/gcc/config/rs6000/aix.h
@@ -21,14 +21,31 @@ Boston, MA 02111-1307, USA. */
/* Yes! We are AIX! */
#define DEFAULT_ABI ABI_AIX
-#undef TARGET_AIX
+#undef TARGET_AIX
#define TARGET_AIX 1
+
+/* AIX always has a TOC. */
+#define TARGET_NO_TOC 0
+#define TARGET_TOC 1
+#define FIXED_R2 1
+
+/* AIX allows r13 to be used in 32-bit mode. */
+#define FIXED_R13 0
+
+/* AIX does not support Altivec. */
+#undef TARGET_ALTIVEC
+#define TARGET_ALTIVEC 0
+#undef TARGET_ALTIVEC_ABI
+#define TARGET_ALTIVEC_ABI 0
+#undef TARGET_ALTIVEC_VRSAVE
+#define TARGET_ALTIVEC_VRSAVE 0
+
/* The AIX linker will discard static constructors in object files before
collect has a chance to see them, so scan the object files directly. */
#define COLLECT_EXPORT_LIST
/* Handle #pragma weak and #pragma pack. */
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
/* This is the only version of nm that collect2 can work with. */
#define REAL_NM_FILE_NAME "/usr/ucb/nm"
@@ -41,18 +58,26 @@ Boston, MA 02111-1307, USA. */
#define LINK_LIBGCC_SPECIAL_1
/* Names to predefine in the preprocessor for this target machine. */
-#define CPP_PREDEFINES "-D_IBMR2 -D_POWER -D_AIX -D_AIX32 -D_LONG_LONG \
--Asystem=unix -Asystem=aix -Acpu=rs6000 -Amachine=rs6000"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("_IBMR2"); \
+ builtin_define ("_POWER"); \
+ builtin_define ("_AIX"); \
+ builtin_define ("_AIX32"); \
+ builtin_define ("_LONG_LONG"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=aix"); \
+ builtin_assert ("cpu=rs6000"); \
+ builtin_assert ("machine=rs6000"); \
+ } \
+ while (0)
/* Define appropriate architecture macros for preprocessor depending on
target switches. */
#define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\
- %{ansi: -D_ANSI_C_SOURCE}\
- %(cpp_cpu)"
-
-#undef CPP_DEFAULT_SPEC
-#define CPP_DEFAULT_SPEC "-D_ARCH_PWR"
+ %{ansi: -D_ANSI_C_SOURCE}"
#undef ASM_DEFAULT_SPEC
#define ASM_DEFAULT_SPEC ""
@@ -121,8 +146,6 @@ Boston, MA 02111-1307, USA. */
? MAX (MAX ((COMPUTED), (SPECIFIED)), 64) \
: MAX ((COMPUTED), (SPECIFIED)))
-
-
/* Indicate that jump tables go in the text section. */
#define JUMP_TABLES_IN_TEXT_SECTION 1
@@ -176,14 +199,6 @@ Boston, MA 02111-1307, USA. */
} \
} while (0)
-/* AIX always has a TOC. */
-#define TARGET_NO_TOC 0
-#define TARGET_TOC 1
-
-#define FIXED_R2 1
-/* AIX allows r13 to be used. */
-#define FIXED_R13 0
-
/* __throw will restore its own return address to be the same as the
return address of the function that the throw is being made to.
This is unfortunate, because we want to check the original
diff --git a/contrib/gcc/config/rs6000/aix31.h b/contrib/gcc/config/rs6000/aix31.h
index 688e588..7379a34 100644
--- a/contrib/gcc/config/rs6000/aix31.h
+++ b/contrib/gcc/config/rs6000/aix31.h
@@ -29,25 +29,25 @@ Boston, MA 02111-1307, USA. */
where we can't, it gets stripped off. */
#undef ASM_OUTPUT_EXTERNAL
-#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
-{ rtx _symref = XEXP (DECL_RTL (DECL), 0); \
- if ((TREE_CODE (DECL) == VAR_DECL \
- || TREE_CODE (DECL) == FUNCTION_DECL) \
- && (NAME)[strlen (NAME) - 1] != ']') \
- { \
- char *_name = (char *) permalloc (strlen (XSTR (_symref, 0)) + 5); \
- strcpy (_name, XSTR (_symref, 0)); \
- strcat (_name, TREE_CODE (DECL) == FUNCTION_DECL ? "[DS]" : "[RW]"); \
- XSTR (_symref, 0) = _name; \
- } \
- fputs ("\t.extern ", FILE); \
- assemble_name (FILE, XSTR (_symref, 0)); \
- if (TREE_CODE (DECL) == FUNCTION_DECL) \
- { \
- fputs ("\n\t.extern .", FILE); \
- RS6000_OUTPUT_BASENAME (FILE, XSTR (_symref, 0)); \
- } \
- putc ('\n', FILE); \
+#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
+{ rtx _symref = XEXP (DECL_RTL (DECL), 0); \
+ if ((TREE_CODE (DECL) == VAR_DECL \
+ || TREE_CODE (DECL) == FUNCTION_DECL) \
+ && (NAME)[strlen (NAME) - 1] != ']') \
+ { \
+ XSTR (_symref, 0) = concat (XSTR (_symref, 0), \
+ (TREE_CODE (DECL) == FUNCTION_DECL \
+ ? "[DS]" : "[RW]"), \
+ NULL); \
+ } \
+ fputs ("\t.extern ", FILE); \
+ assemble_name (FILE, XSTR (_symref, 0)); \
+ if (TREE_CODE (DECL) == FUNCTION_DECL) \
+ { \
+ fputs ("\n\t.extern .", FILE); \
+ RS6000_OUTPUT_BASENAME (FILE, XSTR (_symref, 0)); \
+ } \
+ putc ('\n', FILE); \
}
/* Similar, but for libcall. We only have to worry about the function name,
@@ -60,8 +60,18 @@ Boston, MA 02111-1307, USA. */
}
/* AIX 3.2 defined _AIX32, but older versions do not. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D_IBMR2 -D_AIX -Asystem=unix -Asystem=aix -Acpu=rs6000 -Amachine=rs6000"
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("_IBMR2"); \
+ builtin_define ("_AIX"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=aix"); \
+ builtin_assert ("cpu=rs6000"); \
+ builtin_assert ("machine=rs6000"); \
+ } \
+ while (0)
/* AIX 3.1 uses bit 15 in CROR as the magic nop. */
#undef RS6000_CALL_GLUE
diff --git a/contrib/gcc/config/rs6000/aix41.h b/contrib/gcc/config/rs6000/aix41.h
index cae1a85..7f23a48 100644
--- a/contrib/gcc/config/rs6000/aix41.h
+++ b/contrib/gcc/config/rs6000/aix41.h
@@ -33,19 +33,26 @@ Boston, MA 02111-1307, USA. */
#undef ASM_DEFAULT_SPEC
#define ASM_DEFAULT_SPEC "-mcom"
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D_IBMR2 -D_POWER -D_AIX -D_AIX32 -D_AIX41 \
--D_LONG_LONG -Asystem=unix -Asystem=aix"
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("_IBMR2"); \
+ builtin_define ("_POWER"); \
+ builtin_define ("_AIX"); \
+ builtin_define ("_AIX32"); \
+ builtin_define ("_AIX41"); \
+ builtin_define ("_LONG_LONG"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=aix"); \
+ } \
+ while (0)
#undef CPP_SPEC
#define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\
%{ansi: -D_ANSI_C_SOURCE}\
%{mpe: -I/usr/lpp/ppe.poe/include}\
- %{pthread: -D_THREAD_SAFE}\
- %(cpp_cpu)"
-
-#undef CPP_DEFAULT_SPEC
-#define CPP_DEFAULT_SPEC "-D_ARCH_COM"
+ %{pthread: -D_THREAD_SAFE}"
#undef TARGET_DEFAULT
#define TARGET_DEFAULT MASK_NEW_MNEMONICS
diff --git a/contrib/gcc/config/rs6000/aix43.h b/contrib/gcc/config/rs6000/aix43.h
index 8fe9859..bcbfcf2 100644
--- a/contrib/gcc/config/rs6000/aix43.h
+++ b/contrib/gcc/config/rs6000/aix43.h
@@ -75,6 +75,8 @@ do { \
%{mcpu=common: -mcom} \
%{mcpu=power: -mpwr} \
%{mcpu=power2: -mpwr2} \
+%{mcpu=power3: -m604} \
+%{mcpu=power4: -m604} \
%{mcpu=powerpc: -mppc} \
%{mcpu=rios: -mpwr} \
%{mcpu=rios1: -mpwr} \
@@ -82,8 +84,6 @@ do { \
%{mcpu=rsc: -mpwr} \
%{mcpu=rsc1: -mpwr} \
%{mcpu=rs64a: -mppc} \
-%{mcpu=403: -mppc} \
-%{mcpu=505: -mppc} \
%{mcpu=601: -m601} \
%{mcpu=602: -mppc} \
%{mcpu=603: -m603} \
@@ -91,24 +91,33 @@ do { \
%{mcpu=604: -m604} \
%{mcpu=604e: -m604} \
%{mcpu=620: -mppc} \
-%{mcpu=630: -mppc} \
-%{mcpu=821: -mppc} \
-%{mcpu=860: -mppc}"
+%{mcpu=630: -m604}"
#undef ASM_DEFAULT_SPEC
#define ASM_DEFAULT_SPEC "-mcom"
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D_IBMR2 -D_POWER -D_AIX -D_AIX32 -D_AIX41 -D_AIX43 \
--D_LONG_LONG -Asystem=unix -Asystem=aix"
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("_IBMR2"); \
+ builtin_define ("_POWER"); \
+ builtin_define ("_AIX"); \
+ builtin_define ("_AIX32"); \
+ builtin_define ("_AIX41"); \
+ builtin_define ("_AIX43"); \
+ builtin_define ("_LONG_LONG"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=aix"); \
+ } \
+ while (0)
#undef CPP_SPEC
#define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\
%{ansi: -D_ANSI_C_SOURCE}\
- %{maix64: -D__64BIT__ -D_ARCH_PPC -D__LONG_MAX__=9223372036854775807L}\
+ %{maix64: -D__64BIT__}\
%{mpe: -I/usr/lpp/ppe.poe/include}\
- %{pthread: -D_THREAD_SAFE}\
- %(cpp_cpu)"
+ %{pthread: -D_THREAD_SAFE}"
/* The GNU C++ standard library requires that these macros be
defined. */
@@ -117,51 +126,16 @@ do { \
"-D_XOPEN_SOURCE=500 \
-D_XOPEN_SOURCE_EXTENDED=1 \
-D_LARGE_FILE_API \
- -D_ALL_SOURCE \
- %{maix64: -D__64BIT__ -D_ARCH_PPC -D__LONG_MAX__=9223372036854775807L}\
- %{mpe: -I/usr/lpp/ppe.poe/include}\
- %{pthread: -D_THREAD_SAFE}\
- %(cpp_cpu)"
-
-/* Common CPP definitions used by CPP_SPEC among the various targets
- for handling -mcpu=xxx switches. */
-#undef CPP_CPU_SPEC
-#define CPP_CPU_SPEC \
-"%{!mcpu*: %{!maix64: \
- %{mpower: %{!mpower2: -D_ARCH_PWR}} \
- %{mpower2: -D_ARCH_PWR2} \
- %{mpowerpc*: -D_ARCH_PPC} \
- %{!mpower*: %{!mpowerpc*: %(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} \
-%{mcpu=rios2: -D_ARCH_PWR2} \
-%{mcpu=rsc: -D_ARCH_PWR} \
-%{mcpu=rsc1: -D_ARCH_PWR} \
-%{mcpu=rs64a: -D_ARCH_PPC} \
-%{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=603e: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC} \
-%{mcpu=620: -D_ARCH_PPC} \
-%{mcpu=630: -D_ARCH_PPC} \
-%{mcpu=821: -D_ARCH_PPC} \
-%{mcpu=860: -D_ARCH_PPC}"
-
-#undef CPP_DEFAULT_SPEC
-#define CPP_DEFAULT_SPEC "-D_ARCH_COM"
+ -D_ALL_SOURCE \
+ %{maix64: -D__64BIT__} \
+ %{mpe: -I/usr/lpp/ppe.poe/include} \
+ %{pthread: -D_THREAD_SAFE}"
#undef TARGET_DEFAULT
#define TARGET_DEFAULT MASK_NEW_MNEMONICS
#undef PROCESSOR_DEFAULT
-#define PROCESSOR_DEFAULT PROCESSOR_PPC604
+#define PROCESSOR_DEFAULT PROCESSOR_PPC604e
/* Define this macro as a C expression for the initializer of an
array of string to tell the driver program which options are
diff --git a/contrib/gcc/config/rs6000/aix51.h b/contrib/gcc/config/rs6000/aix51.h
index 4051dd0..552394e 100644
--- a/contrib/gcc/config/rs6000/aix51.h
+++ b/contrib/gcc/config/rs6000/aix51.h
@@ -75,6 +75,8 @@ do { \
%{mcpu=common: -mcom} \
%{mcpu=power: -mpwr} \
%{mcpu=power2: -mpwr2} \
+%{mcpu=power3: -m604} \
+%{mcpu=power4: -m604} \
%{mcpu=powerpc: -mppc} \
%{mcpu=rios: -mpwr} \
%{mcpu=rios1: -mpwr} \
@@ -82,8 +84,6 @@ do { \
%{mcpu=rsc: -mpwr} \
%{mcpu=rsc1: -mpwr} \
%{mcpu=rs64a: -mppc} \
-%{mcpu=403: -mppc} \
-%{mcpu=505: -mppc} \
%{mcpu=601: -m601} \
%{mcpu=602: -mppc} \
%{mcpu=603: -m603} \
@@ -91,81 +91,52 @@ do { \
%{mcpu=604: -m604} \
%{mcpu=604e: -m604} \
%{mcpu=620: -mppc} \
-%{mcpu=630: -mppc} \
-%{mcpu=821: -mppc} \
-%{mcpu=860: -mppc}"
+%{mcpu=630: -m604}"
#undef ASM_DEFAULT_SPEC
#define ASM_DEFAULT_SPEC "-mcom"
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D_IBMR2 -D_POWER -D_LONG_LONG \
--D_AIX -D_AIX32 -D_AIX41 -D_AIX43 -D_AIX51 -Asystem=unix -Asystem=aix"
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("_IBMR2"); \
+ builtin_define ("_POWER"); \
+ builtin_define ("_LONG_LONG"); \
+ builtin_define ("_AIX"); \
+ builtin_define ("_AIX32"); \
+ builtin_define ("_AIX41"); \
+ builtin_define ("_AIX43"); \
+ builtin_define ("_AIX51"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=aix"); \
+ } \
+ while (0)
#undef CPP_SPEC
-#define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\
- %{ansi: -D_ANSI_C_SOURCE}\
- %{!maix64: -D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{maix64: -D__64BIT__ -D_ARCH_PPC -D__LONG_MAX__=9223372036854775807L \
- -D__WCHAR_TYPE__=unsigned\\ int}\
- %{mpe: -I/usr/lpp/ppe.poe/include}\
- %{pthread: -D_THREAD_SAFE}\
- %(cpp_cpu)"
+#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} \
+ %{ansi: -D_ANSI_C_SOURCE} \
+ %{maix64: -D__64BIT__} \
+ %{mpe: -I/usr/lpp/ppe.poe/include} \
+ %{pthread: -D_THREAD_SAFE}"
/* The GNU C++ standard library requires that these macros be
defined. */
#undef CPLUSPLUS_CPP_SPEC
-#define CPLUSPLUS_CPP_SPEC \
- "-D_XOPEN_SOURCE=500 \
- -D_XOPEN_SOURCE_EXTENDED=1 \
- -D_LARGE_FILE_API \
- -D_ALL_SOURCE \
- %{!maix64: -D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{maix64: -D__64BIT__ -D_ARCH_PPC -D__LONG_MAX__=9223372036854775807L \
- -D__WCHAR_TYPE__=unsigned\\ int}\
- %{mpe: -I/usr/lpp/ppe.poe/include}\
- %{pthread: -D_THREAD_SAFE}\
- %(cpp_cpu)"
-
-/* Common CPP definitions used by CPP_SPEC among the various targets
- for handling -mcpu=xxx switches. */
-#undef CPP_CPU_SPEC
-#define CPP_CPU_SPEC \
-"%{!mcpu*: %{!maix64: \
- %{mpower: %{!mpower2: -D_ARCH_PWR}} \
- %{mpower2: -D_ARCH_PWR2} \
- %{mpowerpc*: -D_ARCH_PPC} \
- %{!mpower*: %{!mpowerpc*: %(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} \
-%{mcpu=rios2: -D_ARCH_PWR2} \
-%{mcpu=rsc: -D_ARCH_PWR} \
-%{mcpu=rsc1: -D_ARCH_PWR} \
-%{mcpu=rs64a: -D_ARCH_PPC} \
-%{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=603e: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC} \
-%{mcpu=620: -D_ARCH_PPC} \
-%{mcpu=630: -D_ARCH_PPC} \
-%{mcpu=821: -D_ARCH_PPC} \
-%{mcpu=860: -D_ARCH_PPC}"
-
-#undef CPP_DEFAULT_SPEC
-#define CPP_DEFAULT_SPEC "-D_ARCH_COM"
+#define CPLUSPLUS_CPP_SPEC \
+ "-D_XOPEN_SOURCE=500 \
+ -D_XOPEN_SOURCE_EXTENDED=1 \
+ -D_LARGE_FILE_API \
+ -D_ALL_SOURCE \
+ %{maix64: -D__64BIT__} \
+ %{mpe: -I/usr/lpp/ppe.poe/include} \
+ %{pthread: -D_THREAD_SAFE}"
#undef TARGET_DEFAULT
#define TARGET_DEFAULT MASK_NEW_MNEMONICS
#undef PROCESSOR_DEFAULT
-#define PROCESSOR_DEFAULT PROCESSOR_PPC604
+#define PROCESSOR_DEFAULT PROCESSOR_PPC604e
/* Define this macro as a C expression for the initializer of an
array of string to tell the driver program which options are
@@ -204,9 +175,6 @@ do { \
#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE "long int"
-/* __WCHAR_TYPE__ is dynamic, so do not define it statically. */
-#define NO_BUILTIN_WCHAR_TYPE
-
/* Type used for wchar_t, as a string used in a declaration. */
#undef WCHAR_TYPE
#define WCHAR_TYPE (!TARGET_64BIT ? "short unsigned int" : "unsigned int")
diff --git a/contrib/gcc/config/rs6000/aix52.h b/contrib/gcc/config/rs6000/aix52.h
new file mode 100644
index 0000000..b61cc30
--- /dev/null
+++ b/contrib/gcc/config/rs6000/aix52.h
@@ -0,0 +1,191 @@
+/* Definitions of target machine for GNU compiler,
+ for IBM RS/6000 POWER running AIX V5.2.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by David Edelsohn (edelsohn@gnu.org).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+/* AIX V5 and above support 64-bit executables. */
+#undef SUBSUBTARGET_SWITCHES
+#define SUBSUBTARGET_SWITCHES \
+ {"aix64", MASK_64BIT | MASK_POWERPC64 | MASK_POWERPC, \
+ N_("Compile for 64-bit pointers") }, \
+ {"aix32", - (MASK_64BIT | MASK_POWERPC64), \
+ N_("Compile for 32-bit pointers") }, \
+ {"pe", 0, \
+ N_("Support message passing with the Parallel Environment") },
+
+/* 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.
+
+ The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to
+ get control. */
+
+#define NON_POWERPC_MASKS (MASK_POWER | MASK_POWER2)
+#define SUBTARGET_OVERRIDE_OPTIONS \
+do { \
+ if (TARGET_64BIT && (target_flags & NON_POWERPC_MASKS)) \
+ { \
+ target_flags &= ~NON_POWERPC_MASKS; \
+ warning ("-maix64 and POWER architecture are incompatible"); \
+ } \
+ if (TARGET_64BIT && ! TARGET_POWERPC64) \
+ { \
+ target_flags |= MASK_POWERPC64; \
+ warning ("-maix64 requires PowerPC64 architecture remain enabled"); \
+ } \
+ if (TARGET_POWERPC64 && ! TARGET_64BIT) \
+ { \
+ error ("-maix64 required: 64-bit computation with 32-bit addressing not yet supported"); \
+ } \
+} while (0);
+
+#undef ASM_SPEC
+#define ASM_SPEC "-u %{maix64:-a64 -mppc64} %(asm_cpu)"
+
+/* Common ASM definitions used by ASM_SPEC amonst the various targets
+ for handling -mcpu=xxx switches. */
+#undef ASM_CPU_SPEC
+#define ASM_CPU_SPEC \
+"%{!mcpu*: %{!maix64: \
+ %{mpowerpc64: -mppc64} \
+ %{!mpower64: %(asm_default)}}} \
+%{mcpu=power3: -m604} \
+%{mcpu=power4: -m604} \
+%{mcpu=powerpc: -mppc} \
+%{mcpu=rs64a: -mppc} \
+%{mcpu=603: -m603} \
+%{mcpu=603e: -m603} \
+%{mcpu=604: -m604} \
+%{mcpu=604e: -m604} \
+%{mcpu=620: -mppc} \
+%{mcpu=630: -m604}"
+
+#undef ASM_DEFAULT_SPEC
+#define ASM_DEFAULT_SPEC "-mppc"
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("_IBMR2"); \
+ builtin_define ("_POWER"); \
+ builtin_define ("_LONG_LONG"); \
+ builtin_define ("_AIX"); \
+ builtin_define ("_AIX32"); \
+ builtin_define ("_AIX41"); \
+ builtin_define ("_AIX43"); \
+ builtin_define ("_AIX51"); \
+ builtin_define ("_AIX52"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=aix"); \
+ } \
+ while (0)
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} \
+ %{ansi: -D_ANSI_C_SOURCE} \
+ %{maix64: -D__64BIT__} \
+ %{mpe: -I/usr/lpp/ppe.poe/include} \
+ %{pthread: -D_THREAD_SAFE}"
+
+/* The GNU C++ standard library requires that these macros be
+ defined. */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC \
+ "-D_XOPEN_SOURCE=500 \
+ -D_XOPEN_SOURCE_EXTENDED=1 \
+ -D_LARGE_FILE_API \
+ -D_ALL_SOURCE \
+ %{maix64: -D__64BIT__} \
+ %{mpe: -I/usr/lpp/ppe.poe/include} \
+ %{pthread: -D_THREAD_SAFE}"
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS)
+
+#undef PROCESSOR_DEFAULT
+#define PROCESSOR_DEFAULT PROCESSOR_PPC630
+#undef PROCESSOR_DEFAULT64
+#define PROCESSOR_DEFAULT64 PROCESSOR_POWER4
+
+#undef TARGET_POWER
+#define TARGET_POWER 0
+
+/* 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
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
+ %{p:-L/lib/profiled -L/usr/lib/profiled}\
+ %{!maix64:%{!shared:%{g*:-lg}}}\
+ %{mpe:-L/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
+ %{pthread:-lpthreads} -lc"
+
+#undef LINK_SPEC
+#define LINK_SPEC "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro} -bnodelcsect\
+ %{static:-bnso %(link_syscalls) } %{shared:-bM:SRE %{!e:-bnoentry}}\
+ %{!maix64:%{!shared:%{g*: %(link_libg) }}} %{maix64:-b64}\
+ %{mpe:-binitfini:poe_remote_main}"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{!shared:\
+ %{maix64:%{pg:gcrt0_64%O%s}%{!pg:%{p:mcrt0_64%O%s}%{!p:crt0_64%O%s}}}\
+ %{!maix64:\
+ %{pthread:%{pg:gcrt0_r%O%s}%{!pg:%{p:mcrt0_r%O%s}%{!p:crt0_r%O%s}}}\
+ %{!pthread:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}}}"
+
+/* AIX V5 typedefs ptrdiff_t as "long" while earlier releases used "int". */
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
+
+/* Type used for wchar_t, as a string used in a declaration. */
+#undef WCHAR_TYPE
+#define WCHAR_TYPE (!TARGET_64BIT ? "short unsigned int" : "unsigned int")
+
+/* Width of wchar_t in bits. */
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE (!TARGET_64BIT ? 16 : 32)
+#define MAX_WCHAR_TYPE_SIZE 32
+
+/* AIX V5 uses PowerPC nop (ori 0,0,0) instruction as call glue for PowerPC
+ and "cror 31,31,31" for POWER architecture. */
+
+#undef RS6000_CALL_GLUE
+#define RS6000_CALL_GLUE "{cror 31,31,31|nop}"
+
+/* AIX 4.2 and above provides initialization and finalization function
+ support from linker command line. */
+#undef HAS_INIT_SECTION
+#define HAS_INIT_SECTION
+
+#undef LD_INIT_SWITCH
+#define LD_INIT_SWITCH "-binitfini"
diff --git a/contrib/gcc/config/rs6000/altivec.h b/contrib/gcc/config/rs6000/altivec.h
index f1387c0..1e2d8c8 100644
--- a/contrib/gcc/config/rs6000/altivec.h
+++ b/contrib/gcc/config/rs6000/altivec.h
@@ -1102,43 +1102,43 @@ vec_cmple (vector float a1, vector float a2)
inline vector signed char
vec_cmplt (vector unsigned char a1, vector unsigned char a2)
{
- return (vector signed char) __builtin_altivec_vcmpgtub ((vector signed char) a1, (vector signed char) a2);
+ return (vector signed char) __builtin_altivec_vcmpgtub ((vector signed char) a2, (vector signed char) a1);
}
inline vector signed char
vec_cmplt (vector signed char a1, vector signed char a2)
{
- return (vector signed char) __builtin_altivec_vcmpgtsb ((vector signed char) a1, (vector signed char) a2);
+ return (vector signed char) __builtin_altivec_vcmpgtsb ((vector signed char) a2, (vector signed char) a1);
}
inline vector signed short
vec_cmplt (vector unsigned short a1, vector unsigned short a2)
{
- return (vector signed short) __builtin_altivec_vcmpgtuh ((vector signed short) a1, (vector signed short) a2);
+ return (vector signed short) __builtin_altivec_vcmpgtuh ((vector signed short) a2, (vector signed short) a1);
}
inline vector signed short
vec_cmplt (vector signed short a1, vector signed short a2)
{
- return (vector signed short) __builtin_altivec_vcmpgtsh ((vector signed short) a1, (vector signed short) a2);
+ return (vector signed short) __builtin_altivec_vcmpgtsh ((vector signed short) a2, (vector signed short) a1);
}
inline vector signed int
vec_cmplt (vector unsigned int a1, vector unsigned int a2)
{
- return (vector signed int) __builtin_altivec_vcmpgtuw ((vector signed int) a1, (vector signed int) a2);
+ return (vector signed int) __builtin_altivec_vcmpgtuw ((vector signed int) a2, (vector signed int) a1);
}
inline vector signed int
vec_cmplt (vector signed int a1, vector signed int a2)
{
- return (vector signed int) __builtin_altivec_vcmpgtsw ((vector signed int) a1, (vector signed int) a2);
+ return (vector signed int) __builtin_altivec_vcmpgtsw ((vector signed int) a2, (vector signed int) a1);
}
inline vector signed int
vec_cmplt (vector float a1, vector float a2)
{
- return (vector signed int) __builtin_altivec_vcmpgtfp ((vector float) a1, (vector float) a2);
+ return (vector signed int) __builtin_altivec_vcmpgtfp ((vector float) a2, (vector float) a1);
}
/* vec_ctf */
@@ -6523,7 +6523,7 @@ __ch (__bin_args_eq (vector unsigned char, (a1), vector unsigned char, (a2)), \
#define vec_cmple(a1, a2) __builtin_altivec_vcmpgefp ((a1), (a2))
-#define vec_cmplt(a1, a2) \
+#define vec_cmplt(a2, a1) \
__ch (__bin_args_eq (vector unsigned char, (a1), vector unsigned char, (a2)), \
((vector signed char) __builtin_altivec_vcmpgtub ((vector signed char) (a1), (vector signed char) (a2))), \
__ch (__bin_args_eq (vector signed char, (a1), vector signed char, (a2)), \
diff --git a/contrib/gcc/config/rs6000/altivec.md b/contrib/gcc/config/rs6000/altivec.md
new file mode 100644
index 0000000..25e4b08
--- /dev/null
+++ b/contrib/gcc/config/rs6000/altivec.md
@@ -0,0 +1,1915 @@
+;; AltiVec patterns.
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+;; Contributed by Aldy Hernandez (aldy@quesejoda.com)
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; Generic LVX load instruction.
+(define_insn "altivec_lvx_4si"
+ [(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
+ (match_operand:V4SI 1 "memory_operand" "m"))]
+ "TARGET_ALTIVEC"
+ "lvx %0,%y1"
+ [(set_attr "type" "vecload")])
+
+(define_insn "altivec_lvx_8hi"
+ [(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
+ (match_operand:V8HI 1 "memory_operand" "m"))]
+ "TARGET_ALTIVEC"
+ "lvx %0,%y1"
+ [(set_attr "type" "vecload")])
+
+(define_insn "altivec_lvx_16qi"
+ [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
+ (match_operand:V16QI 1 "memory_operand" "m"))]
+ "TARGET_ALTIVEC"
+ "lvx %0,%y1"
+ [(set_attr "type" "vecload")])
+
+(define_insn "altivec_lvx_4sf"
+ [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
+ (match_operand:V4SF 1 "memory_operand" "m"))]
+ "TARGET_ALTIVEC"
+ "lvx %0,%y1"
+ [(set_attr "type" "vecload")])
+
+;; Generic STVX store instruction.
+(define_insn "altivec_stvx_4si"
+ [(set (match_operand:V4SI 0 "memory_operand" "=m")
+ (match_operand:V4SI 1 "altivec_register_operand" "v"))]
+ "TARGET_ALTIVEC"
+ "stvx %1,%y0"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "altivec_stvx_8hi"
+ [(set (match_operand:V8HI 0 "memory_operand" "=m")
+ (match_operand:V8HI 1 "altivec_register_operand" "v"))]
+ "TARGET_ALTIVEC"
+ "stvx %1,%y0"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "altivec_stvx_16qi"
+ [(set (match_operand:V16QI 0 "memory_operand" "=m")
+ (match_operand:V16QI 1 "altivec_register_operand" "v"))]
+ "TARGET_ALTIVEC"
+ "stvx %1,%y0"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "altivec_stvx_4sf"
+ [(set (match_operand:V4SF 0 "memory_operand" "=m")
+ (match_operand:V4SF 1 "altivec_register_operand" "v"))]
+ "TARGET_ALTIVEC"
+ "stvx %1,%y0"
+ [(set_attr "type" "vecstore")])
+
+;; Vector move instructions.
+(define_expand "movv4si"
+ [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
+ (match_operand:V4SI 1 "any_operand" ""))]
+ "TARGET_ALTIVEC"
+ "{ rs6000_emit_move (operands[0], operands[1], V4SImode); DONE; }")
+
+(define_insn "*movv4si_internal"
+ [(set (match_operand:V4SI 0 "nonimmediate_operand" "=m,v,v,o,r,r")
+ (match_operand:V4SI 1 "input_operand" "v,m,v,r,o,r"))]
+ "TARGET_ALTIVEC"
+ "@
+ stvx %1,%y0
+ lvx %0,%y1
+ vor %0,%1,%1
+ stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
+ lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
+ mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
+ [(set_attr "type" "altivec")
+ (set_attr "length" "*,*,*,16,16,16")])
+
+(define_expand "movv8hi"
+ [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
+ (match_operand:V8HI 1 "any_operand" ""))]
+ "TARGET_ALTIVEC"
+ "{ rs6000_emit_move (operands[0], operands[1], V8HImode); DONE; }")
+
+(define_insn "*movv8hi_internal1"
+ [(set (match_operand:V8HI 0 "nonimmediate_operand" "=m,v,v,o,r,r")
+ (match_operand:V8HI 1 "input_operand" "v,m,v,r,o,r"))]
+ "TARGET_ALTIVEC"
+ "@
+ stvx %1,%y0
+ lvx %0,%y1
+ vor %0,%1,%1
+ stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
+ lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
+ mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
+ [(set_attr "type" "altivec")
+ (set_attr "length" "*,*,*,16,16,16")])
+
+(define_expand "movv16qi"
+ [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
+ (match_operand:V16QI 1 "any_operand" ""))]
+ "TARGET_ALTIVEC"
+ "{ rs6000_emit_move (operands[0], operands[1], V16QImode); DONE; }")
+
+(define_insn "*movv16qi_internal1"
+ [(set (match_operand:V16QI 0 "nonimmediate_operand" "=m,v,v,o,r,r")
+ (match_operand:V16QI 1 "input_operand" "v,m,v,r,o,r"))]
+ "TARGET_ALTIVEC"
+ "@
+ stvx %1,%y0
+ lvx %0,%y1
+ vor %0,%1,%1
+ stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
+ lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
+ mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
+ [(set_attr "type" "altivec")
+ (set_attr "length" "*,*,*,16,16,16")])
+
+(define_expand "movv4sf"
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
+ (match_operand:V4SF 1 "any_operand" ""))]
+ "TARGET_ALTIVEC"
+ "{ rs6000_emit_move (operands[0], operands[1], V4SFmode); DONE; }")
+
+(define_insn "*movv4sf_internal1"
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "=m,v,v,o,r,r")
+ (match_operand:V4SF 1 "input_operand" "v,m,v,r,o,r"))]
+ "TARGET_ALTIVEC"
+ "@
+ stvx %1,%y0
+ lvx %0,%y1
+ vor %0,%1,%1
+ stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
+ lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
+ mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
+ [(set_attr "type" "altivec")
+ (set_attr "length" "*,*,*,16,16,16")])
+
+(define_insn "get_vrsave_internal"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(reg:SI 109)] 214))]
+ "TARGET_ALTIVEC"
+ "*
+{
+ if (TARGET_MACHO)
+ return \"mfspr %0,256\";
+ else
+ return \"mfvrsave %0\";
+}"
+ [(set_attr "type" "altivec")])
+
+(define_insn "*set_vrsave_internal"
+ [(match_parallel 0 "vrsave_operation"
+ [(set (reg:SI 109)
+ (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")
+ (reg:SI 109)] 30))])]
+ "TARGET_ALTIVEC"
+ "*
+{
+ if (TARGET_MACHO)
+ return \"mtspr 256,%1\";
+ else
+ return \"mtvrsave %1\";
+}"
+ [(set_attr "type" "altivec")])
+
+;; Vector clears
+(define_insn "*movv4si_const0"
+ [(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
+ (match_operand:V4SI 1 "zero_constant" ""))]
+ "TARGET_ALTIVEC"
+ "vxor %0,%0,%0"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*movv4sf_const0"
+ [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
+ (match_operand:V4SF 1 "zero_constant" ""))]
+
+ "TARGET_ALTIVEC"
+ "vxor %0,%0,%0"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*movv8hi_const0"
+ [(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
+ (match_operand:V8HI 1 "zero_constant" ""))]
+ "TARGET_ALTIVEC"
+ "vxor %0,%0,%0"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*movv16qi_const0"
+ [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
+ (match_operand:V16QI 1 "zero_constant" ""))]
+ "TARGET_ALTIVEC"
+ "vxor %0,%0,%0"
+ [(set_attr "type" "vecsimple")])
+
+;; Simple binary operations.
+
+(define_insn "addv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (plus:V16QI (match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vaddubm %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "addv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (plus:V8HI (match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vadduhm %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "addv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (plus:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vadduwm %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "addv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (plus:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vaddfp %0,%1,%2"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "altivec_vaddcuw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 35))]
+ "TARGET_ALTIVEC"
+ "vaddcuw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vaddubs"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 36))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vaddubs %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vaddsbs"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 37))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vaddsbs %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vadduhs"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 38))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vadduhs %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vaddshs"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 39))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vaddshs %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vadduws"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 40))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vadduws %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vaddsws"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 41))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vaddsws %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "andv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (and:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vand %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vandc"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (and:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (not:V4SI (match_operand:V4SI 2 "register_operand" "v"))))]
+ "TARGET_ALTIVEC"
+ "vandc %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vavgub"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 44))]
+ "TARGET_ALTIVEC"
+ "vavgub %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vavgsb"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 45))]
+ "TARGET_ALTIVEC"
+ "vavgsb %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vavguh"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 46))]
+ "TARGET_ALTIVEC"
+ "vavguh %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vavgsh"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 47))]
+ "TARGET_ALTIVEC"
+ "vavgsh %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vavguw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 48))]
+ "TARGET_ALTIVEC"
+ "vavguw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vavgsw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 49))]
+ "TARGET_ALTIVEC"
+ "vavgsw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vcmpbfp"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")] 50))]
+ "TARGET_ALTIVEC"
+ "vcmpbfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "altivec_vcmpequb"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 51))]
+ "TARGET_ALTIVEC"
+ "vcmpequb %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vcmpequh"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 52))]
+ "TARGET_ALTIVEC"
+ "vcmpequh %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vcmpequw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 53))]
+ "TARGET_ALTIVEC"
+ "vcmpequw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vcmpeqfp"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")] 54))]
+ "TARGET_ALTIVEC"
+ "vcmpeqfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "altivec_vcmpgefp"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")] 55))]
+ "TARGET_ALTIVEC"
+ "vcmpgefp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "altivec_vcmpgtub"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 56))]
+ "TARGET_ALTIVEC"
+ "vcmpgtub %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vcmpgtsb"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 57))]
+ "TARGET_ALTIVEC"
+ "vcmpgtsb %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vcmpgtuh"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 58))]
+ "TARGET_ALTIVEC"
+ "vcmpgtuh %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vcmpgtsh"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 59))]
+ "TARGET_ALTIVEC"
+ "vcmpgtsh %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vcmpgtuw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 60))]
+ "TARGET_ALTIVEC"
+ "vcmpgtuw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vcmpgtsw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 61))]
+ "TARGET_ALTIVEC"
+ "vcmpgtsw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vcmpgtfp"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")] 62))]
+ "TARGET_ALTIVEC"
+ "vcmpgtfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+;; Fused multiply add
+(define_insn "altivec_vmaddfp"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (plus:V4SF (mult:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v"))
+ (match_operand:V4SF 3 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vmaddfp %0,%1,%2,%3"
+ [(set_attr "type" "vecfloat")])
+
+;; We do multiply as a fused multiply-add with an add of a -0.0 vector.
+
+(define_expand "mulv4sf3"
+ [(use (match_operand:V4SF 0 "register_operand" ""))
+ (use (match_operand:V4SF 1 "register_operand" ""))
+ (use (match_operand:V4SF 2 "register_operand" ""))]
+ "TARGET_ALTIVEC && TARGET_FUSED_MADD"
+ "
+{
+ rtx neg0;
+
+ /* Generate [-0.0, -0.0, -0.0, -0.0]. */
+ neg0 = gen_reg_rtx (V4SFmode);
+ emit_insn (gen_altivec_vspltisw_v4sf (neg0, GEN_INT (-1)));
+ emit_insn (gen_altivec_vslw_v4sf (neg0, neg0, neg0));
+
+ /* Use the multiply-add. */
+ emit_insn (gen_altivec_vmaddfp (operands[0], operands[1], operands[2],
+ neg0));
+ DONE;
+}")
+
+;; Fused multiply subtract
+(define_insn "altivec_vnmsubfp"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (minus:V4SF (mult:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v"))
+ (match_operand:V4SF 3 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vnmsubfp %0,%1,%2,%3"
+ [(set_attr "type" "vecfloat")])
+
+
+(define_insn "altivec_vmsumubm"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")
+ (match_operand:V4SI 3 "register_operand" "v")] 65))]
+ "TARGET_ALTIVEC"
+ "vmsumubm %0, %1, %2, %3"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmsummbm"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")
+ (match_operand:V4SI 3 "register_operand" "v")] 66))]
+ "TARGET_ALTIVEC"
+ "vmsumubm %0, %1, %2, %3"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmsumuhm"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand:V4SI 3 "register_operand" "v")] 67))]
+ "TARGET_ALTIVEC"
+ "vmsumuhm %0, %1, %2, %3"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmsumshm"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand:V4SI 3 "register_operand" "v")] 68))]
+ "TARGET_ALTIVEC"
+ "vmsumshm %0, %1, %2, %3"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmsumuhs"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand:V4SI 3 "register_operand" "v")] 69))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vmsumuhs %0, %1, %2, %3"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmsumshs"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand:V4SI 3 "register_operand" "v")] 70))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vmsumshs %0, %1, %2, %3"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "umaxv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (umax:V16QI (match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vmaxub %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "smaxv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (smax:V16QI (match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vmaxsb %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "umaxv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (umax:V8HI (match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vmaxuh %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "smaxv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (smax:V8HI (match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vmaxsh %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "umaxv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (umax:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vmaxuw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "smaxv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (smax:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vmaxsw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "smaxv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (smax:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vmaxfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "altivec_vmhaddshs"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand:V8HI 3 "register_operand" "v")] 71))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vmhaddshs %0, %1, %2, %3"
+ [(set_attr "type" "veccomplex")])
+(define_insn "altivec_vmhraddshs"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand:V8HI 3 "register_operand" "v")] 72))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vmhraddshs %0, %1, %2, %3"
+ [(set_attr "type" "veccomplex")])
+(define_insn "altivec_vmladduhm"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand:V8HI 3 "register_operand" "v")] 73))]
+ "TARGET_ALTIVEC"
+ "vmladduhm %0, %1, %2, %3"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmrghb"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (vec_merge:V16QI (vec_select:V16QI (match_operand:V16QI 1 "register_operand" "v")
+ (parallel [(const_int 8)
+ (const_int 9)
+ (const_int 10)
+ (const_int 11)
+ (const_int 12)
+ (const_int 13)
+ (const_int 14)
+ (const_int 15)
+ (const_int 0)
+ (const_int 1)
+ (const_int 2)
+ (const_int 3)
+ (const_int 4)
+ (const_int 5)
+ (const_int 6)
+ (const_int 7)]))
+ (match_operand:V16QI 2 "register_operand" "v")
+ (const_int 255)))]
+ "TARGET_ALTIVEC"
+ "vmrghb %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vmrghh"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (vec_merge:V8HI (vec_select:V8HI (match_operand:V8HI 1 "register_operand" "v")
+ (parallel [(const_int 4)
+ (const_int 5)
+ (const_int 6)
+ (const_int 7)
+ (const_int 0)
+ (const_int 1)
+ (const_int 2)
+ (const_int 3)]))
+ (match_operand:V8HI 2 "register_operand" "v")
+ (const_int 15)))]
+ "TARGET_ALTIVEC"
+ "vmrghh %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vmrghw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (vec_merge:V4SI (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (parallel [(const_int 2)
+ (const_int 3)
+ (const_int 0)
+ (const_int 1)]))
+ (match_operand:V4SI 2 "register_operand" "v")
+ (const_int 12)))]
+ "TARGET_ALTIVEC"
+ "vmrghw %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vmrglb"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (vec_merge:V16QI (vec_select:V16QI (match_operand:V16QI 2 "register_operand" "v")
+ (parallel [(const_int 0)
+ (const_int 1)
+ (const_int 2)
+ (const_int 3)
+ (const_int 4)
+ (const_int 5)
+ (const_int 6)
+ (const_int 7)
+ (const_int 8)
+ (const_int 9)
+ (const_int 10)
+ (const_int 11)
+ (const_int 12)
+ (const_int 13)
+ (const_int 14)
+ (const_int 15)]))
+ (match_operand:V16QI 1 "register_operand" "v")
+ (const_int 255)))]
+ "TARGET_ALTIVEC"
+ "vmrglb %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vmrglh"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (vec_merge:V8HI (vec_select:V8HI (match_operand:V8HI 2 "register_operand" "v")
+ (parallel [(const_int 0)
+ (const_int 1)
+ (const_int 2)
+ (const_int 3)
+ (const_int 4)
+ (const_int 5)
+ (const_int 6)
+ (const_int 7)]))
+ (match_operand:V8HI 1 "register_operand" "v")
+ (const_int 15)))]
+ "TARGET_ALTIVEC"
+ "vmrglh %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vmrglw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (vec_merge:V4SI (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
+ (parallel [(const_int 0)
+ (const_int 1)
+ (const_int 2)
+ (const_int 3)]))
+ (match_operand:V4SI 1 "register_operand" "v")
+ (const_int 12)))]
+ "TARGET_ALTIVEC"
+ "vmrglw %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "uminv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (umin:V16QI (match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vminub %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "sminv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (smin:V16QI (match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vminsb %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "uminv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (umin:V8HI (match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vminuh %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "sminv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (smin:V8HI (match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vminsh %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "uminv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (umin:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vminuw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "sminv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (smin:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vminsw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "sminv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (smin:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vminfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "altivec_vmuleub"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 83))]
+ "TARGET_ALTIVEC"
+ "vmuleub %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmulesb"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 84))]
+ "TARGET_ALTIVEC"
+ "vmulesb %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmuleuh"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 85))]
+ "TARGET_ALTIVEC"
+ "vmuleuh %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmulesh"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 86))]
+ "TARGET_ALTIVEC"
+ "vmulesh %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmuloub"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 87))]
+ "TARGET_ALTIVEC"
+ "vmuloub %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmulosb"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 88))]
+ "TARGET_ALTIVEC"
+ "vmulosb %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmulouh"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 89))]
+ "TARGET_ALTIVEC"
+ "vmulouh %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vmulosh"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 90))]
+ "TARGET_ALTIVEC"
+ "vmulosh %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vnor"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (not:V4SI (ior:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v"))))]
+ "TARGET_ALTIVEC"
+ "vnor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "iorv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (ior:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vpkuhum"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 93))]
+ "TARGET_ALTIVEC"
+ "vpkuhum %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vpkuwum"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 94))]
+ "TARGET_ALTIVEC"
+ "vpkuwum %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vpkpx"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 95))]
+ "TARGET_ALTIVEC"
+ "vpkpx %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vpkuhss"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 96))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vpkuhss %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vpkshss"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 97))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vpkshss %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vpkuwss"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 98))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vpkuwss %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vpkswss"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 99))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vpkswss %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vpkuhus"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 100))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vpkuhus %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vpkshus"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 101))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vpkshus %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vpkuwus"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 102))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vpkuwus %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vpkswus"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 103))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vpkswus %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vrlb"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 104))]
+ "TARGET_ALTIVEC"
+ "vrlb %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vrlh"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 105))]
+ "TARGET_ALTIVEC"
+ "vrlh %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vrlw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 106))]
+ "TARGET_ALTIVEC"
+ "vrlw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vslb"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 107))]
+ "TARGET_ALTIVEC"
+ "vslb %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vslh"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 108))]
+ "TARGET_ALTIVEC"
+ "vslh %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vslw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 109))]
+ "TARGET_ALTIVEC"
+ "vslw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vslw_v4sf"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")] 109))]
+ "TARGET_ALTIVEC"
+ "vslw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vsl"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 110))]
+ "TARGET_ALTIVEC"
+ "vsl %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vslo"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 111))]
+ "TARGET_ALTIVEC"
+ "vslo %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vsrb"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 112))]
+ "TARGET_ALTIVEC"
+ "vsrb %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vsrh"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 113))]
+ "TARGET_ALTIVEC"
+ "vsrh %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vsrw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 114))]
+ "TARGET_ALTIVEC"
+ "vsrw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vsrab"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 115))]
+ "TARGET_ALTIVEC"
+ "vsrab %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vsrah"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 116))]
+ "TARGET_ALTIVEC"
+ "vsrah %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vsraw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 117))]
+ "TARGET_ALTIVEC"
+ "vsraw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vsr"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 118))]
+ "TARGET_ALTIVEC"
+ "vsr %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vsro"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 119))]
+ "TARGET_ALTIVEC"
+ "vsro %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "subv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (minus:V16QI (match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vsububm %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "subv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (minus:V8HI (match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vsubuhm %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "subv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (minus:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vsubuwm %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "subv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (minus:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vsubfp %0,%1,%2"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "altivec_vsubcuw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 124))]
+ "TARGET_ALTIVEC"
+ "vsubcuw %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vsububs"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 125))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vsububs %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vsubsbs"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")] 126))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vsubsbs %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vsubuhs"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 127))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vsubuhs %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vsubshs"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")] 128))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vsubshs %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vsubuws"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 129))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vsubuws %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vsubsws"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 130))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vsubsws %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vsum4ubs"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 131))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vsum4ubs %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vsum4sbs"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 132))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vsum4sbs %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vsum4shs"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 133))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vsum4shs %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vsum2sws"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 134))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vsum2sws %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "altivec_vsumsws"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")] 135))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vsumsws %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_insn "xorv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (xor:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vxor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vspltb"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:QI 2 "immediate_operand" "i")] 136))]
+ "TARGET_ALTIVEC"
+ "vspltb %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vsplth"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:QI 2 "immediate_operand" "i")] 137))]
+ "TARGET_ALTIVEC"
+ "vsplth %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vspltw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:QI 2 "immediate_operand" "i")] 138))]
+ "TARGET_ALTIVEC"
+ "vspltw %0,%1,%2"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vspltisb"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:QI 1 "immediate_operand" "i")] 139))]
+ "TARGET_ALTIVEC"
+ "vspltisb %0, %1"
+ [(set_attr "type" "vecsimple")])
+
+
+(define_insn "altivec_vspltish"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:QI 1 "immediate_operand" "i")] 140))]
+ "TARGET_ALTIVEC"
+ "vspltish %0, %1"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vspltisw"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:QI 1 "immediate_operand" "i")] 141))]
+ "TARGET_ALTIVEC"
+ "vspltisw %0, %1"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_vspltisw_v4sf"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:QI 1 "immediate_operand" "i")] 142))]
+ "TARGET_ALTIVEC"
+ "vspltisw %0, %1"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "ftruncv4sf2"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (fix:V4SF (match_operand:V4SF 1 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vrfiz %0, %1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "altivec_vperm_4si"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")
+ (match_operand:V16QI 3 "register_operand" "v")] 144))]
+ "TARGET_ALTIVEC"
+ "vperm %0,%1,%2,%3"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vperm_4sf"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")
+ (match_operand:V16QI 3 "register_operand" "v")] 145))]
+ "TARGET_ALTIVEC"
+ "vperm %0,%1,%2,%3"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vperm_8hi"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand:V16QI 3 "register_operand" "v")] 146))]
+ "TARGET_ALTIVEC"
+ "vperm %0,%1,%2,%3"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vperm_16qi"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")
+ (match_operand:V16QI 3 "register_operand" "v")] 147))]
+ "TARGET_ALTIVEC"
+ "vperm %0,%1,%2,%3"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vrfip"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 148))]
+ "TARGET_ALTIVEC"
+ "vrfip %0, %1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "altivec_vrfin"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 149))]
+ "TARGET_ALTIVEC"
+ "vrfin %0, %1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "altivec_vrfim"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 150))]
+ "TARGET_ALTIVEC"
+ "vrfim %0, %1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "altivec_vcfux"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:QI 2 "immediate_operand" "i")] 151))]
+ "TARGET_ALTIVEC"
+ "vcfux %0, %1, %2"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "altivec_vcfsx"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:QI 2 "immediate_operand" "i")] 152))]
+ "TARGET_ALTIVEC"
+ "vcfsx %0, %1, %2"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "altivec_vctuxs"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:QI 2 "immediate_operand" "i")] 153))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vctuxs %0, %1, %2"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "altivec_vctsxs"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:QI 2 "immediate_operand" "i")] 154))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ "TARGET_ALTIVEC"
+ "vctsxs %0, %1, %2"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "altivec_vlogefp"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 155))]
+ "TARGET_ALTIVEC"
+ "vlogefp %0, %1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "altivec_vexptefp"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 156))]
+ "TARGET_ALTIVEC"
+ "vexptefp %0, %1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "altivec_vrsqrtefp"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 157))]
+ "TARGET_ALTIVEC"
+ "vrsqrtefp %0, %1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "altivec_vrefp"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 158))]
+ "TARGET_ALTIVEC"
+ "vrefp %0, %1"
+ [(set_attr "type" "vecfloat")])
+
+(define_insn "altivec_vsel_4si"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")
+ (match_operand:V4SI 3 "register_operand" "v")] 159))]
+ "TARGET_ALTIVEC"
+ "vsel %0,%1,%2,%3"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vsel_4sf"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")
+ (match_operand:V4SI 3 "register_operand" "v")] 160))]
+ "TARGET_ALTIVEC"
+ "vsel %0,%1,%2,%3"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vsel_8hi"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand:V8HI 3 "register_operand" "v")] 161))]
+ "TARGET_ALTIVEC"
+ "vsel %0,%1,%2,%3"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vsel_16qi"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")
+ (match_operand:V16QI 3 "register_operand" "v")] 162))]
+ "TARGET_ALTIVEC"
+ "vsel %0,%1,%2,%3"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vsldoi_4si"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")
+ (match_operand:QI 3 "immediate_operand" "i")] 163))]
+ "TARGET_ALTIVEC"
+ "vsldoi %0, %1, %2, %3"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vsldoi_4sf"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")
+ (match_operand:QI 3 "immediate_operand" "i")] 164))]
+ "TARGET_ALTIVEC"
+ "vsldoi %0, %1, %2, %3"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vsldoi_8hi"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand:QI 3 "immediate_operand" "i")] 165))]
+ "TARGET_ALTIVEC"
+ "vsldoi %0, %1, %2, %3"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vsldoi_16qi"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")
+ (match_operand:QI 3 "immediate_operand" "i")] 166))]
+ "TARGET_ALTIVEC"
+ "vsldoi %0, %1, %2, %3"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vupkhsb"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")] 167))]
+ "TARGET_ALTIVEC"
+ "vupkhsb %0, %1"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vupkhpx"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")] 168))]
+ "TARGET_ALTIVEC"
+ "vupkhpx %0, %1"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vupkhsh"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")] 169))]
+ "TARGET_ALTIVEC"
+ "vupkhsh %0, %1"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vupklsb"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")] 170))]
+ "TARGET_ALTIVEC"
+ "vupklsb %0, %1"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vupklpx"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")] 171))]
+ "TARGET_ALTIVEC"
+ "vupklpx %0, %1"
+ [(set_attr "type" "vecperm")])
+
+(define_insn "altivec_vupklsh"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")] 172))]
+ "TARGET_ALTIVEC"
+ "vupklsh %0, %1"
+ [(set_attr "type" "vecperm")])
+
+;; AltiVec predicates.
+
+(define_expand "cr6_test_for_zero"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (eq:SI (reg:CC 74)
+ (const_int 0)))]
+ "TARGET_ALTIVEC"
+ "")
+
+(define_expand "cr6_test_for_zero_reverse"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (eq:SI (reg:CC 74)
+ (const_int 0)))
+ (set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
+ "TARGET_ALTIVEC"
+ "")
+
+(define_expand "cr6_test_for_lt"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lt:SI (reg:CC 74)
+ (const_int 0)))]
+ "TARGET_ALTIVEC"
+ "")
+
+(define_expand "cr6_test_for_lt_reverse"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lt:SI (reg:CC 74)
+ (const_int 0)))
+ (set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
+ "TARGET_ALTIVEC"
+ "")
+
+;; We can get away with generating the opcode on the fly (%3 below)
+;; because all the predicates have the same scheduling parameters.
+
+(define_insn "altivec_predicate_v4si"
+ [(set (reg:CC 74)
+ (unspec:CC [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")
+ (match_operand 3 "any_operand" "")] 173))
+ (clobber (match_scratch:V4SI 0 "=v"))]
+ "TARGET_ALTIVEC"
+ "%3 %0,%1,%2"
+[(set_attr "type" "veccmp")])
+
+(define_insn "altivec_predicate_v4sf"
+ [(set (reg:CC 74)
+ (unspec:CC [(match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")
+ (match_operand 3 "any_operand" "")] 174))
+ (clobber (match_scratch:V4SF 0 "=v"))]
+ "TARGET_ALTIVEC"
+ "%3 %0,%1,%2"
+[(set_attr "type" "veccmp")])
+
+(define_insn "altivec_predicate_v8hi"
+ [(set (reg:CC 74)
+ (unspec:CC [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand 3 "any_operand" "")] 175))
+ (clobber (match_scratch:V8HI 0 "=v"))]
+ "TARGET_ALTIVEC"
+ "%3 %0,%1,%2"
+[(set_attr "type" "veccmp")])
+
+(define_insn "altivec_predicate_v16qi"
+ [(set (reg:CC 74)
+ (unspec:CC [(match_operand:V16QI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")
+ (match_operand 3 "any_operand" "")] 175))
+ (clobber (match_scratch:V16QI 0 "=v"))]
+ "TARGET_ALTIVEC"
+ "%3 %0,%1,%2"
+[(set_attr "type" "veccmp")])
+
+(define_insn "altivec_mtvscr"
+ [(set (reg:SI 110)
+ (unspec_volatile:SI
+ [(match_operand:V4SI 0 "register_operand" "v")] 186))]
+ "TARGET_ALTIVEC"
+ "mtvscr %0"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_mfvscr"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec_volatile:V8HI [(reg:SI 110)] 187))]
+ "TARGET_ALTIVEC"
+ "mfvscr %0"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_dssall"
+ [(unspec [(const_int 0)] 188)]
+ "TARGET_ALTIVEC"
+ "dssall"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_dss"
+ [(unspec [(match_operand:QI 0 "immediate_operand" "i")] 189)]
+ "TARGET_ALTIVEC"
+ "dss %0"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_dst"
+ [(unspec [(match_operand:SI 0 "register_operand" "b")
+ (match_operand:SI 1 "register_operand" "r")
+ (match_operand:QI 2 "immediate_operand" "i")] 190)]
+ "TARGET_ALTIVEC"
+ "dst %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_dstt"
+ [(unspec [(match_operand:SI 0 "register_operand" "b")
+ (match_operand:SI 1 "register_operand" "r")
+ (match_operand:QI 2 "immediate_operand" "i")] 191)]
+ "TARGET_ALTIVEC"
+ "dstt %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_dstst"
+ [(unspec [(match_operand:SI 0 "register_operand" "b")
+ (match_operand:SI 1 "register_operand" "r")
+ (match_operand:QI 2 "immediate_operand" "i")] 192)]
+ "TARGET_ALTIVEC"
+ "dstst %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_dststt"
+ [(unspec [(match_operand:SI 0 "register_operand" "b")
+ (match_operand:SI 1 "register_operand" "r")
+ (match_operand:QI 2 "immediate_operand" "i")] 193)]
+ "TARGET_ALTIVEC"
+ "dststt %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_lvsl"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:SI 1 "register_operand" "b")
+ (match_operand:SI 2 "register_operand" "r")] 194))]
+ "TARGET_ALTIVEC"
+ "lvsl %0,%1,%2"
+ [(set_attr "type" "vecload")])
+
+(define_insn "altivec_lvsr"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:SI 1 "register_operand" "b")
+ (match_operand:SI 2 "register_operand" "r")] 195))]
+ "TARGET_ALTIVEC"
+ "lvsr %0,%1,%2"
+ [(set_attr "type" "vecload")])
+
+;; Parallel some of the LVE* and STV*'s with unspecs because some have
+;; identical rtl but different instructions-- and gcc gets confused.
+
+(define_insn "altivec_lvebx"
+ [(parallel
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (mem:V16QI (plus:SI (match_operand:SI 1 "register_operand" "b")
+ (match_operand:SI 2 "register_operand" "r"))))
+ (unspec [(const_int 0)] 196)])]
+ "TARGET_ALTIVEC"
+ "lvebx %0,%1,%2"
+ [(set_attr "type" "vecload")])
+
+(define_insn "altivec_lvehx"
+ [(parallel
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (mem:V8HI
+ (and:SI (plus:SI (match_operand:SI 1 "register_operand" "b")
+ (match_operand:SI 2 "register_operand" "r"))
+ (const_int -2))))
+ (unspec [(const_int 0)] 197)])]
+ "TARGET_ALTIVEC"
+ "lvehx %0,%1,%2"
+ [(set_attr "type" "vecload")])
+
+(define_insn "altivec_lvewx"
+ [(parallel
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (mem:V4SI
+ (and:SI (plus:SI (match_operand:SI 1 "register_operand" "b")
+ (match_operand:SI 2 "register_operand" "r"))
+ (const_int -4))))
+ (unspec [(const_int 0)] 198)])]
+ "TARGET_ALTIVEC"
+ "lvewx %0,%1,%2"
+ [(set_attr "type" "vecload")])
+
+(define_insn "altivec_lvxl"
+ [(parallel
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (mem:V4SI (plus:SI (match_operand:SI 1 "register_operand" "b")
+ (match_operand:SI 2 "register_operand" "r"))))
+ (unspec [(const_int 0)] 213)])]
+ "TARGET_ALTIVEC"
+ "lvxl %0,%1,%2"
+ [(set_attr "type" "vecload")])
+
+(define_insn "altivec_lvx"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (mem:V4SI (plus:SI (match_operand:SI 1 "register_operand" "b")
+ (match_operand:SI 2 "register_operand" "r"))))]
+ "TARGET_ALTIVEC"
+ "lvx %0,%1,%2"
+ [(set_attr "type" "vecload")])
+
+(define_insn "altivec_stvx"
+ [(parallel
+ [(set (mem:V4SI
+ (and:SI (plus:SI (match_operand:SI 0 "register_operand" "b")
+ (match_operand:SI 1 "register_operand" "r"))
+ (const_int -16)))
+ (match_operand:V4SI 2 "register_operand" "v"))
+ (unspec [(const_int 0)] 201)])]
+ "TARGET_ALTIVEC"
+ "stvx %2,%0,%1"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "altivec_stvxl"
+ [(parallel
+ [(set (mem:V4SI
+ (and:SI (plus:SI (match_operand:SI 0 "register_operand" "b")
+ (match_operand:SI 1 "register_operand" "r"))
+ (const_int -16)))
+ (match_operand:V4SI 2 "register_operand" "v"))
+ (unspec [(const_int 0)] 202)])]
+ "TARGET_ALTIVEC"
+ "stvxl %2,%0,%1"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "altivec_stvebx"
+ [(parallel
+ [(set (mem:V16QI
+ (plus:SI (match_operand:SI 0 "register_operand" "b")
+ (match_operand:SI 1 "register_operand" "r")))
+ (match_operand:V16QI 2 "register_operand" "v"))
+ (unspec [(const_int 0)] 203)])]
+ "TARGET_ALTIVEC"
+ "stvebx %2,%0,%1"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "altivec_stvehx"
+ [(parallel
+ [(set (mem:V8HI
+ (and:SI (plus:SI (match_operand:SI 0 "register_operand" "b")
+ (match_operand:SI 1 "register_operand" "r"))
+ (const_int -2)))
+ (match_operand:V8HI 2 "register_operand" "v"))
+ (unspec [(const_int 0)] 204)])]
+ "TARGET_ALTIVEC"
+ "stvehx %2,%0,%1"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "altivec_stvewx"
+ [(parallel
+ [(set (mem:V4SI
+ (and:SI (plus:SI (match_operand:SI 0 "register_operand" "b")
+ (match_operand:SI 1 "register_operand" "r"))
+ (const_int -4)))
+ (match_operand:V4SI 2 "register_operand" "v"))
+ (unspec [(const_int 0)] 205)])]
+ "TARGET_ALTIVEC"
+ "stvewx %2,%0,%1"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "absv16qi2"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (abs:V16QI (match_operand:V16QI 1 "register_operand" "v")))
+ (clobber (match_scratch:V16QI 2 "=&v"))
+ (clobber (match_scratch:V16QI 3 "=&v"))]
+ "TARGET_ALTIVEC"
+ "vspltisb %2,0\;vsububm %3,%2,%1\;vmaxsb %0,%1,%3"
+ [(set_attr "type" "altivec")
+ (set_attr "length" "12")])
+
+(define_insn "absv8hi2"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (abs:V8HI (match_operand:V8HI 1 "register_operand" "v")))
+ (clobber (match_scratch:V8HI 2 "=&v"))
+ (clobber (match_scratch:V8HI 3 "=&v"))]
+ "TARGET_ALTIVEC"
+ "vspltisb %2,0\;vsubuhm %3,%2,%1\;vmaxsh %0,%1,%3"
+ [(set_attr "type" "altivec")
+ (set_attr "length" "12")])
+
+(define_insn "absv4si2"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (abs:V4SI (match_operand:V4SI 1 "register_operand" "v")))
+ (clobber (match_scratch:V4SI 2 "=&v"))
+ (clobber (match_scratch:V4SI 3 "=&v"))]
+ "TARGET_ALTIVEC"
+ "vspltisb %2,0\;vsubuwm %3,%2,%1\;vmaxsw %0,%1,%3"
+ [(set_attr "type" "altivec")
+ (set_attr "length" "12")])
+
+(define_insn "absv4sf2"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (abs:V4SF (match_operand:V4SF 1 "register_operand" "v")))
+ (clobber (match_scratch:V4SF 2 "=&v"))
+ (clobber (match_scratch:V4SF 3 "=&v"))]
+ "TARGET_ALTIVEC"
+ "vspltisw %2, -1\;vslw %3,%2,%2\;vandc %0,%1,%3"
+ [(set_attr "type" "altivec")
+ (set_attr "length" "12")])
+
+(define_insn "altivec_abss_v16qi"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")] 210))
+ (clobber (match_scratch:V16QI 2 "=&v"))
+ (clobber (match_scratch:V16QI 3 "=&v"))]
+ "TARGET_ALTIVEC"
+ "vspltisb %2,0\;vsubsbs %3,%2,%1\;vmaxsb %0,%1,%3"
+ [(set_attr "type" "altivec")
+ (set_attr "length" "12")])
+
+(define_insn "altivec_abss_v8hi"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")] 211))
+ (clobber (match_scratch:V8HI 2 "=&v"))
+ (clobber (match_scratch:V8HI 3 "=&v"))]
+ "TARGET_ALTIVEC"
+ "vspltisb %2,0\;vsubshs %3,%2,%1\;vmaxsh %0,%1,%3"
+ [(set_attr "type" "altivec")
+ (set_attr "length" "12")])
+
+(define_insn "altivec_abss_v4si"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")] 212))
+ (clobber (match_scratch:V4SI 2 "=&v"))
+ (clobber (match_scratch:V4SI 3 "=&v"))]
+ "TARGET_ALTIVEC"
+ "vspltisb %2,0\;vsubsws %3,%2,%1\;vmaxsw %0,%1,%3"
+ [(set_attr "type" "altivec")
+ (set_attr "length" "12")])
diff --git a/contrib/gcc/config/rs6000/beos.h b/contrib/gcc/config/rs6000/beos.h
index f569c3c..1f788c3 100644
--- a/contrib/gcc/config/rs6000/beos.h
+++ b/contrib/gcc/config/rs6000/beos.h
@@ -38,15 +38,21 @@ Boston, MA 02111-1307, USA. */
#undef ASM_SPEC
#define ASM_SPEC "-u %(asm_cpu)"
-#undef CPP_PREDEFINES
+#undef TARGET_OS_CPP_BUILTINS
/* __POWERPC__ must be defined for some header files */
-#define CPP_PREDEFINES "-D__BEOS__ -D__POWERPC__ -Asystem=beos -Acpu=powerpc -Amachine=powerpc"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__BEOS__"); \
+ builtin_define ("__POWERPC__"); \
+ builtin_assert ("system=beos"); \
+ builtin_assert ("cpu=powerpc"); \
+ builtin_assert ("machine=powerpc"); \
+ } \
+ while (0)
#undef CPP_SPEC
-#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} %(cpp_cpu)"
-
-#undef CPP_DEFAULT_SPEC
-#define CPP_DEFAULT_SPEC "-D_ARCH_PPC"
+#define CPP_SPEC "%{posix: -D_POSIX_SOURCE}"
/* This is the easiest way to disable use of gcc's builtin alloca,
which in the current BeOS release (DR9) is a problem because of the
diff --git a/contrib/gcc/config/rs6000/darwin-tramp.asm b/contrib/gcc/config/rs6000/darwin-tramp.asm
index 02c7be6..22ce80a 100644
--- a/contrib/gcc/config/rs6000/darwin-tramp.asm
+++ b/contrib/gcc/config/rs6000/darwin-tramp.asm
@@ -64,7 +64,7 @@ ___trampoline_setup:
bcl 20,31,LCF0 /* load up __trampoline_initial into r7 */
LCF0:
mflr r11
- addi r7,r11,ha16(LTRAMP-LCF0)
+ addis r7,r11,ha16(LTRAMP-LCF0)
lwz r7,lo16(LTRAMP-LCF0)(r7)
subi r7,r7,4
li r8,trampoline_size /* verify trampoline big enough */
diff --git a/contrib/gcc/config/rs6000/darwin.h b/contrib/gcc/config/rs6000/darwin.h
index 81c24e7..b3468f2 100644
--- a/contrib/gcc/config/rs6000/darwin.h
+++ b/contrib/gcc/config/rs6000/darwin.h
@@ -36,7 +36,7 @@ Boston, MA 02111-1307, USA. */
#define TARGET_NO_TOC 1
/* Handle #pragma weak and #pragma pack. */
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
/* The Darwin ABI always includes AltiVec, can't be (validly) turned
off. */
@@ -44,12 +44,23 @@ Boston, MA 02111-1307, USA. */
#define SUBTARGET_OVERRIDE_OPTIONS \
rs6000_altivec_abi = 1;
-#define CPP_PREDEFINES "-D__ppc__ -D__POWERPC__ -D__NATURAL_ALIGNMENT__ -D__MACH__ -D__BIG_ENDIAN__ -D__APPLE__"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__ppc__"); \
+ builtin_define ("__POWERPC__"); \
+ builtin_define ("__NATURAL_ALIGNMENT__"); \
+ builtin_define ("__MACH__"); \
+ builtin_define ("__APPLE__"); \
+ } \
+ while (0)
/* We want -fPIC by default, unless we're using -static to compile for
the kernel or some such. */
-#define CC1_SPEC "%{!static:-fPIC}"
+#define CC1_SPEC "\
+%{static: %{Zdynamic: %e conflicting code gen style switches are used}}\
+%{!static:-fPIC}"
/* Make both r2 and r3 available for allocation. */
#define FIXED_R2 0
@@ -94,20 +105,10 @@ Boston, MA 02111-1307, USA. */
#define RS6000_OUTPUT_BASENAME(FILE, NAME) \
assemble_name (FILE, NAME);
-/* Output before instructions. */
-/* This is how to output the definition of a user-level label named NAME,
- such as the label on a static function or variable NAME. */
-
-#define ASM_OUTPUT_LABEL(FILE,NAME) \
- do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
-
-/* This is how to output a command to make the user-level label named NAME
- defined for reference from other files. */
-
-#undef ASM_GLOBALIZE_LABEL
-#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
- do { fputs ("\t.globl ", FILE); \
- RS6000_OUTPUT_BASENAME (FILE, NAME); putc ('\n', FILE);} while (0)
+/* Globalizing directive for a label. */
+#undef GLOBAL_ASM_OP
+#define GLOBAL_ASM_OP "\t.globl "
+#undef TARGET_ASM_GLOBALIZE_LABEL
/* This is how to output an internal label prefix. rs6000.c uses this
when generating traceback tables. */
@@ -117,14 +118,6 @@ Boston, MA 02111-1307, USA. */
#define ASM_OUTPUT_INTERNAL_LABEL_PREFIX(FILE,PREFIX) \
fprintf (FILE, "%s", PREFIX)
-#undef TEXT_SECTION_ASM_OP
-#define TEXT_SECTION_ASM_OP ".text"
-
-/* Output before writable data. */
-
-#undef DATA_SECTION_ASM_OP
-#define DATA_SECTION_ASM_OP ".data"
-
/* This says how to output an assembler line to define a global common
symbol. */
/* ? */
@@ -134,9 +127,6 @@ Boston, MA 02111-1307, USA. */
RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
fprintf ((FILE), ",%d\n", (SIZE)); } while (0)
-#define ASM_OUTPUT_SKIP(FILE,SIZE) \
- fprintf (FILE, "\t.space %d\n", SIZE)
-
/* Override the standard rs6000 definition. */
#undef ASM_COMMENT_START
@@ -148,6 +138,21 @@ Boston, MA 02111-1307, USA. */
#define RESTORE_FP_PREFIX "._restf"
#define RESTORE_FP_SUFFIX ""
+/* This is how to output an assembler line that says to advance
+ the location counter to a multiple of 2**LOG bytes using the
+ "nop" instruction as padding. */
+
+#define ASM_OUTPUT_ALIGN_WITH_NOP(FILE,LOG) \
+ do \
+ { \
+ if ((LOG) < 3) \
+ { \
+ ASM_OUTPUT_ALIGN (FILE,LOG); \
+ } \
+ else /* nop == ori r0,r0,0 */ \
+ fprintf (FILE, "\t.align32 %d,0x60000000\n", (LOG)); \
+ } while (0)
+
/* Generate insns to call the profiler. */
#define PROFILE_HOOK(LABEL) output_profile_hook (LABEL)
@@ -226,7 +231,7 @@ Boston, MA 02111-1307, USA. */
: MAX ((COMPUTED), (SPECIFIED)))
/* XXX: Darwin supports neither .quad, or .llong, but it also doesn't
- support 64 bit powerpc either, so this just keeps things happy. */
+ support 64 bit PowerPC either, so this just keeps things happy. */
#define DOUBLE_INT_ASM_OP "\t.quad\t"
/* Get HOST_WIDE_INT and CONST_INT to be 32 bits, for compile time
@@ -237,3 +242,6 @@ Boston, MA 02111-1307, USA. */
/* For binary compatibility with 2.95; Darwin C APIs use bool from
stdbool.h, which was an int-sized enum in 2.95. */
#define BOOL_TYPE_SIZE INT_TYPE_SIZE
+
+#undef REGISTER_TARGET_PRAGMAS
+#define REGISTER_TARGET_PRAGMAS DARWIN_REGISTER_TARGET_PRAGMAS
diff --git a/contrib/gcc/config/rs6000/eabi.asm b/contrib/gcc/config/rs6000/eabi.asm
index 0808e9c..058f9b9 100644
--- a/contrib/gcc/config/rs6000/eabi.asm
+++ b/contrib/gcc/config/rs6000/eabi.asm
@@ -139,7 +139,7 @@ FUNC_START(__eabi)
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 */
+ stw 1,.Linit_p@l(10) /* store a nonzero value in the done flag */
#else /* -mrelocatable */
mflr 0
@@ -155,7 +155,7 @@ FUNC_START(__eabi)
cmplwi 2,9,0 /* init flag != 0? */
mtlr 0 /* restore in case branch was taken */
bnelr 2 /* return now, if we've been called already */
- stwx 1,10,12 /* store a non-zero value in the done flag */
+ stwx 1,10,12 /* store a nonzero value in the done flag */
beq+ 0,.Lsdata /* skip if we don't need to relocate */
/* We need to relocate the .got2 pointers. */
diff --git a/contrib/gcc/config/rs6000/eabi.h b/contrib/gcc/config/rs6000/eabi.h
index 88fb6f8..373dd2b 100644
--- a/contrib/gcc/config/rs6000/eabi.h
+++ b/contrib/gcc/config/rs6000/eabi.h
@@ -31,6 +31,24 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (PowerPC Embedded)");
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
- "-DPPC -D__embedded__ -Asystem=embedded -Acpu=powerpc -Amachine=powerpc"
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("PPC"); \
+ builtin_define ("__embedded__"); \
+ builtin_assert ("system=embedded"); \
+ builtin_assert ("cpu=powerpc"); \
+ builtin_assert ("machine=powerpc"); \
+ } \
+ while (0)
+
+#undef TARGET_SPE_ABI
+#undef TARGET_SPE
+#undef TARGET_ISEL
+#undef TARGET_FPRS
+
+#define TARGET_SPE_ABI rs6000_spe_abi
+#define TARGET_SPE (rs6000_cpu == PROCESSOR_PPC8540)
+#define TARGET_ISEL rs6000_isel
+#define TARGET_FPRS rs6000_fprs
diff --git a/contrib/gcc/config/rs6000/eabiaix.h b/contrib/gcc/config/rs6000/eabiaix.h
index 639a335..4e18067 100644
--- a/contrib/gcc/config/rs6000/eabiaix.h
+++ b/contrib/gcc/config/rs6000/eabiaix.h
@@ -23,9 +23,6 @@ Boston, MA 02111-1307, USA. */
#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
diff --git a/contrib/gcc/config/rs6000/eabisim.h b/contrib/gcc/config/rs6000/eabisim.h
index 92e0957..00f710e 100644
--- a/contrib/gcc/config/rs6000/eabisim.h
+++ b/contrib/gcc/config/rs6000/eabisim.h
@@ -23,9 +23,19 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (PowerPC Simulated)");
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
- "-DPPC -D__embedded__ -D__simulator__ -Asystem=embedded -Asystem=simulator -Acpu=powerpc -Amachine=powerpc"
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("PPC"); \
+ builtin_define ("__embedded__"); \
+ builtin_define ("__simulator__"); \
+ builtin_assert ("system=embedded"); \
+ builtin_assert ("system=simulator"); \
+ builtin_assert ("cpu=powerpc"); \
+ builtin_assert ("machine=powerpc"); \
+ } \
+ while (0)
/* Make the simulator the default */
#undef LIB_DEFAULT_SPEC
diff --git a/contrib/gcc/config/rs6000/eabispe.h b/contrib/gcc/config/rs6000/eabispe.h
new file mode 100644
index 0000000..b0047cd
--- /dev/null
+++ b/contrib/gcc/config/rs6000/eabispe.h
@@ -0,0 +1,51 @@
+/* Core target definitions for GNU compiler
+ for PowerPC embedded targeted systems with SPE support.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Aldy Hernandez (aldyh@redhat.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_EABI)
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (PowerPC Embedded SPE)");
+
+#undef SUBSUBTARGET_OVERRIDE_OPTIONS
+#define SUBSUBTARGET_OVERRIDE_OPTIONS \
+ rs6000_cpu = PROCESSOR_PPC8540; \
+ rs6000_spe_abi = 1; \
+ rs6000_fprs = 0; \
+ /* See note below. */ \
+ /*rs6000_long_double_type_size = 128;*/ \
+ rs6000_isel = 1
+
+/*
+ The e500 ABI says that either long doubles are 128 bits, or if
+ implemented in any other size, the compiler/linker should error out.
+ We have no emulation libraries for 128 bit long doubles, and I hate
+ the dozens of failures on the regression suite. So I'm breaking ABI
+ specifications, until I properly fix the emulation.
+
+ Enable these later.
+#undef CPP_LONGDOUBLE_DEFAULT_SPEC
+#define CPP_LONGDOUBLE_DEFAULT_SPEC "-D__LONG_DOUBLE_128__=1"
+*/
+
+#undef ASM_DEFAULT_SPEC
+#define ASM_DEFAULT_SPEC "-mppc -mspe -me500"
diff --git a/contrib/gcc/config/rs6000/freebsd.h b/contrib/gcc/config/rs6000/freebsd.h
index e4b9fc5..699d2ad 100644
--- a/contrib/gcc/config/rs6000/freebsd.h
+++ b/contrib/gcc/config/rs6000/freebsd.h
@@ -38,6 +38,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#undef LINK_OS_DEFAULT_SPEC
#define LINK_OS_DEFAULT_SPEC "%(link_os_freebsd)"
+/* XXX: This is wrong for many platforms in sysv4.h.
+ We should work on getting that defination fixed. */
+#undef LINK_SHLIB_SPEC
+#define LINK_SHLIB_SPEC "%{shared:-shared} %{!shared: %{static:-static}}"
+
/************************[ Target stuff ]***********************************/
@@ -45,12 +50,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
Needs to agree with <machine/ansi.h>. GCC defaults come from c-decl.c,
c-common.c, and config/<arch>/<arch>.h. */
+#undef SIZE_TYPE
+#define SIZE_TYPE "unsigned int"
+
/* rs6000.h gets this wrong for FreeBSD. We use the GCC defaults instead. */
#undef WCHAR_TYPE
-#undef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
-
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
diff --git a/contrib/gcc/config/rs6000/gnu.h b/contrib/gcc/config/rs6000/gnu.h
index 32bd906..9aeb696 100644
--- a/contrib/gcc/config/rs6000/gnu.h
+++ b/contrib/gcc/config/rs6000/gnu.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler,
- for powerpc machines running GNU.
+ for PowerPC machines running GNU.
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
diff --git a/contrib/gcc/config/rs6000/linux.h b/contrib/gcc/config/rs6000/linux.h
index f5cbd7a..593e961 100644
--- a/contrib/gcc/config/rs6000/linux.h
+++ b/contrib/gcc/config/rs6000/linux.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler,
- for powerpc machines running Linux.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003
+ for PowerPC machines running Linux.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
Contributed by Michael Meissner (meissner@cygnus.com).
@@ -21,15 +21,20 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Don't assume anything about the header files. */
-#define NO_IMPLICIT_EXTERN_C
-
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
- "-DPPC -D__ELF__ -Dpowerpc -Acpu=powerpc -Amachine=powerpc"
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("PPC"); \
+ builtin_define ("__ELF__"); \
+ builtin_define_std ("powerpc"); \
+ builtin_assert ("cpu=powerpc"); \
+ builtin_assert ("machine=powerpc"); \
+ } \
+ while (0)
#undef CPP_OS_DEFAULT_SPEC
#define CPP_OS_DEFAULT_SPEC "%(cpp_os_linux)"
@@ -79,7 +84,18 @@ Boston, MA 02111-1307, USA. */
#ifdef IN_LIBGCC2
#include <signal.h>
-#include <sys/ucontext.h>
+
+/* During the 2.5 kernel series the kernel ucontext was changed, but
+ the new layout is compatible with the old one, so we just define
+ and use the old one here for simplicity and compatibility. */
+
+struct kernel_old_ucontext {
+ unsigned long uc_flags;
+ struct ucontext *uc_link;
+ stack_t uc_stack;
+ struct sigcontext_struct uc_mcontext;
+ sigset_t uc_sigmask;
+};
enum { SIGNAL_FRAMESIZE = 64 };
#endif
@@ -115,7 +131,7 @@ enum { SIGNAL_FRAMESIZE = 64 };
struct siginfo *pinfo; \
void *puc; \
struct siginfo info; \
- struct ucontext uc; \
+ struct kernel_old_ucontext uc; \
} *rt_ = (CONTEXT)->cfa; \
sc_ = &rt_->uc.uc_mcontext; \
} \
@@ -139,15 +155,9 @@ enum { SIGNAL_FRAMESIZE = 64 };
(FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset \
= (long)&(sc_->regs->link) - new_cfa_; \
\
- /* The unwinder expects the IP to point to the following insn, \
- whereas the kernel returns the address of the actual \
- faulting insn. We store NIP+4 in an unused register slot to \
- get the same result for multiple evaluation of the same signal \
- frame. */ \
- sc_->regs->gpr[47] = sc_->regs->nip + 4; \
(FS)->regs.reg[CR0_REGNO].how = REG_SAVED_OFFSET; \
(FS)->regs.reg[CR0_REGNO].loc.offset \
- = (long)&(sc_->regs->gpr[47]) - new_cfa_; \
+ = (long)&(sc_->regs->nip) - new_cfa_; \
(FS)->retaddr_column = CR0_REGNO; \
goto SUCCESS; \
} while (0)
diff --git a/contrib/gcc/config/rs6000/linux64.h b/contrib/gcc/config/rs6000/linux64.h
index ce8f7ac..55065c6 100644
--- a/contrib/gcc/config/rs6000/linux64.h
+++ b/contrib/gcc/config/rs6000/linux64.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler,
- for 64 bit powerpc linux.
+ for 64 bit PowerPC linux.
Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -31,8 +31,10 @@ Boston, MA 02111-1307, USA. */
#define TARGET_DEFAULT \
(MASK_POWERPC | MASK_POWERPC64 | MASK_64BIT | MASK_NEW_MNEMONICS)
-#undef CPP_DEFAULT_SPEC
-#define CPP_DEFAULT_SPEC "-D_ARCH_PPC64"
+#undef PROCESSOR_DEFAULT
+#define PROCESSOR_DEFAULT PROCESSOR_PPC630
+#undef PROCESSOR_DEFAULT64
+#define PROCESSOR_DEFAULT64 PROCESSOR_PPC630
#undef ASM_DEFAULT_SPEC
#define ASM_DEFAULT_SPEC "-mppc64"
@@ -104,18 +106,24 @@ Boston, MA 02111-1307, USA. */
So we have to squirrel it away with this. */
#define SETUP_FRAME_ADDRESSES() rs6000_aix_emit_builtin_unwind_init ()
-/* Don't assume anything about the header files. */
-#define NO_IMPLICIT_EXTERN_C
-
+/* Override svr4.h */
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
- "-D_PPC_ -D__PPC__ -D_PPC64_ -D__PPC64__ -D__powerpc__ -D__powerpc64__ \
- -D_PIC_ -D__PIC__ -D_BIG_ENDIAN -D__BIG_ENDIAN__ -D__ELF__ \
- -D__LONG_MAX__=9223372036854775807L \
- -Acpu=powerpc64 -Amachine=powerpc64"
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__PPC__"); \
+ builtin_define ("__PPC64__"); \
+ builtin_define ("__powerpc__"); \
+ builtin_define ("__powerpc64__"); \
+ builtin_define ("__PIC__"); \
+ builtin_define ("__ELF__"); \
+ builtin_assert ("cpu=powerpc64"); \
+ builtin_assert ("machine=powerpc64"); \
+ } \
+ while (0)
#undef CPP_OS_DEFAULT_SPEC
#define CPP_OS_DEFAULT_SPEC "%(cpp_os_linux)"
@@ -145,29 +153,23 @@ Boston, MA 02111-1307, USA. */
#define LINK_OS_DEFAULT_SPEC "%(link_os_linux)"
#undef LINK_OS_LINUX_SPEC
-#ifndef CROSS_COMPILE
-#define LINK_OS_LINUX_SPEC "-m elf64ppc %{!shared: %{!static: \
- %{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib64/ld.so.1}}}"
-#else
#define LINK_OS_LINUX_SPEC "-m elf64ppc %{!shared: %{!static: \
%{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker ld.so.1}}}"
+ %{!dynamic-linker:-dynamic-linker /lib64/ld64.so.1}}}"
+
+#ifdef NATIVE_CROSS
+#define STARTFILE_PREFIX_SPEC "/usr/local/lib64/ /lib64/ /usr/lib64/"
#endif
-#ifndef CROSS_COMPILE
#undef STARTFILE_LINUX_SPEC
#define STARTFILE_LINUX_SPEC "\
-%{!shared: %{pg:/usr/lib64/gcrt1.o%s} %{!pg:%{p:/usr/lib64/gcrt1.o%s} \
- %{!p:/usr/lib64/crt1.o%s}}} /usr/lib64/crti.o%s \
-%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
-#endif
+%{!shared: %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}} crti.o%s \
+%{static:crtbeginT.o%s} \
+%{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
-#ifndef CROSS_COMPILE
#undef ENDFILE_LINUX_SPEC
#define ENDFILE_LINUX_SPEC "\
-%{!shared:crtend.o%s} %{shared:crtendS.o%s} /usr/lib64/crtn.o%s"
-#endif
+%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
#undef TOC_SECTION_ASM_OP
#define TOC_SECTION_ASM_OP "\t.section\t\".toc\",\"aw\""
@@ -205,6 +207,18 @@ Boston, MA 02111-1307, USA. */
#undef RS6000_MCOUNT
#define RS6000_MCOUNT "_mcount"
+#ifdef __powerpc64__
+/* _init and _fini functions are built from bits spread across many
+ object files, each potentially with a different TOC pointer. For
+ that reason, place a nop after the call so that the linker can
+ restore the TOC pointer if a TOC adjusting call stub is needed. */
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+ asm (SECTION_OP "\n" \
+" bl ." #FUNC "\n" \
+" nop\n" \
+" .previous");
+#endif
+
/* FP save and restore routines. */
#undef SAVE_FP_PREFIX
#define SAVE_FP_PREFIX "._savef"
@@ -219,17 +233,8 @@ Boston, MA 02111-1307, USA. */
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-/* 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. Do not set this flag if the function is weakly defined. */
-
-#undef ENCODE_SECTION_INFO
-#define ENCODE_SECTION_INFO(DECL) \
- if (TREE_CODE (DECL) == FUNCTION_DECL \
- && (TREE_ASM_WRITTEN (DECL) || ! TREE_PUBLIC (DECL)) \
- && ! DECL_WEAK (DECL)) \
- SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO rs6000_xcoff_encode_section_info
/* This is how to output a reference to a user-level label named NAME.
`assemble_name' uses this. */
@@ -290,7 +295,7 @@ do { \
} \
while (0)
-/* Return non-zero if this entry is to be written into the constant
+/* Return nonzero 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
diff --git a/contrib/gcc/config/rs6000/lynx.h b/contrib/gcc/config/rs6000/lynx.h
index 5a859ca..7878ef9 100644
--- a/contrib/gcc/config/rs6000/lynx.h
+++ b/contrib/gcc/config/rs6000/lynx.h
@@ -1,5 +1,5 @@
/* Definitions for Rs6000 running LynxOS.
- Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 2000, 2002 Free Software Foundation, Inc.
Contributed by David Henkel-Wallace, Cygnus Support (gumby@cygnus.com)
This file is part of GNU CC.
@@ -27,9 +27,10 @@ Boston, MA 02111-1307, USA. */
#undef ASM_FILE_START
#undef EXTRA_SECTIONS
#undef READONLY_DATA_SECTION
+#undef READONLY_DATA_SECTION_ASM_OP
#undef EXTRA_SECTION_FUNCTIONS
-#undef SELECT_RTX_SECTION
-#undef SELECT_SECTION
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#undef TARGET_ASM_SELECT_SECTION
#undef USER_LABEL_PREFIX
#undef ASM_OUTPUT_LABELREF
#undef ASM_OUTPUT_INTERNAL_LABEL
@@ -52,8 +53,22 @@ Boston, MA 02111-1307, USA. */
#undef DEFAULT_SIGNED_CHAR
#define DEFAULT_SIGNED_CHAR 1
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Acpu=rs6000 -Amachine=rs6000 -Asystem=lynx -Asystem=unix -DLynx -D_IBMR2 -Dunix -Drs6000 -Dlynx -DLYNX"
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_assert ("cpu=rs6000"); \
+ builtin_assert ("machine=rs6000"); \
+ builtin_assert ("system=lynx"); \
+ builtin_assert ("system=unix"); \
+ builtin_define_std ("Lynx"); \
+ builtin_define ("_IBMR2"); \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("rs6000"); \
+ builtin_define_std ("lynx"); \
+ builtin_define_std ("LYNX"); \
+ } \
+ while (0)
#undef LINK_SPEC
#define LINK_SPEC "-T0x10001000 -H0x1000 -D0x20000000 -btextro -bhalt:4 -bnodelcsect -bnso -bro -bnoglink %{v} %{b*}"
diff --git a/contrib/gcc/config/rs6000/mach.h b/contrib/gcc/config/rs6000/mach.h
index d4395d5..a246f91 100644
--- a/contrib/gcc/config/rs6000/mach.h
+++ b/contrib/gcc/config/rs6000/mach.h
@@ -26,8 +26,19 @@ Boston, MA 02111-1307, USA. */
#define TARGET_VERSION fprintf (stderr, " (Mach-RS/6000)");
/* We don't define AIX under MACH; instead we define `unix'. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Drios -D_IBMR2 -Dunix -Asystem=unix -Asystem=mach -Acpu=rs6000 -Amachine=rs6000"
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("rios"); \
+ builtin_define ("_IBMR2"); \
+ builtin_define_std ("unix"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=mach"); \
+ builtin_assert ("cpu=rs6000"); \
+ builtin_assert ("machine=rs6000"); \
+ } \
+ while (0)
/* Define different binder options for MACH. */
#undef LINK_SPEC
diff --git a/contrib/gcc/config/rs6000/netbsd.h b/contrib/gcc/config/rs6000/netbsd.h
index d41e576..b473a8a 100644
--- a/contrib/gcc/config/rs6000/netbsd.h
+++ b/contrib/gcc/config/rs6000/netbsd.h
@@ -1,6 +1,7 @@
/* Definitions of target machine for GNU compiler,
for PowerPC NetBSD systems.
- Copyright 2001 Free Software Foundation, Inc.
+ Copyright 2002 Free Software Foundation, Inc.
+ Contributed by Wasabi Systems, Inc.
This file is part of GNU CC.
@@ -19,48 +20,74 @@ 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. */
-/* Under NetBSD, the normal location of the various *crt*.o files is
- the /usr/lib directory [from config/netbsd.h]. */
+#undef TARGET_OS_CPP_BUILTINS /* FIXME: sysv4.h should not define this! */
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ NETBSD_OS_CPP_BUILTINS_ELF(); \
+ builtin_define ("__powerpc__"); \
+ builtin_assert ("cpu=powerpc"); \
+ builtin_assert ("machine=powerpc"); \
+ } \
+ while (0)
+
+/* Override the default from rs6000.h to avoid conflicts with macros
+ defined in NetBSD header files. */
+
+#undef RS6000_CPU_CPP_ENDIAN_BUILTINS
+#define RS6000_CPU_CPP_ENDIAN_BUILTINS() \
+ do \
+ { \
+ if (BYTES_BIG_ENDIAN) \
+ { \
+ builtin_define ("__BIG_ENDIAN__"); \
+ builtin_assert ("machine=bigendian"); \
+ } \
+ else \
+ { \
+ builtin_define ("__LITTLE_ENDIAN__"); \
+ builtin_assert ("machine=littleendian"); \
+ } \
+ } \
+ while (0)
+
+/* Make GCC agree with <machine/ansi.h>. */
+
+#undef SIZE_TYPE
+#define SIZE_TYPE "unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
+
+/* Undo the spec mess from sysv4.h, and just define the specs
+ the way NetBSD systems actually expect. */
+
+#undef CPP_SPEC
+#define CPP_SPEC NETBSD_CPP_SPEC
+
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%{!msdata=none:%{G*}} %{msdata=none:-G0} \
+ %(netbsd_link_spec)"
+
+#define NETBSD_ENTRY_POINT "_start"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC NETBSD_STARTFILE_SPEC
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "crtsavres%O%s %(netbsd_endfile_spec)"
+
+#undef LIB_SPEC
+#define LIB_SPEC NETBSD_LIB_SPEC
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "netbsd_link_spec", NETBSD_LINK_SPEC_ELF }, \
+ { "netbsd_entry_point", NETBSD_ENTRY_POINT }, \
+ { "netbsd_endfile_spec", NETBSD_ENDFILE_SPEC },
-#undef STANDARD_STARTFILE_PREFIX
-#define STANDARD_STARTFILE_PREFIX "/usr/lib/"
-
-/* FIXME: Should this macro be treated the same as for the other
- spec's? */
-/* NOTE: -dc and -dp are equivalent yet NetBSD's CC passes both both!
- NetBSD's CC also passes -O1 but we can skip that. NetBSD explictly
- sets ``-e _start'', since LD knows this, skip it. */
-
-#undef LINK_SHLIB_SPEC
-#define LINK_SHLIB_SPEC "\
-%{shared:-shared} \
-%{!shared: %{static:-dc -dp -static}} \
-%{!shared: %{!static:-dc -dp}} \
-"
-
-/* Override the defaults. */
-#undef LIB_DEFAULT_SPEC
-#define LIB_DEFAULT_SPEC "%(lib_netbsd)"
-
-#undef STARTFILE_DEFAULT_SPEC
-#define STARTFILE_DEFAULT_SPEC "%(startfile_netbsd)"
-
-#undef ENDFILE_DEFAULT_SPEC
-#define ENDFILE_DEFAULT_SPEC "%(endfile_netbsd)"
-
-#undef LINK_START_DEFAULT_SPEC
-#define LINK_START_DEFAULT_SPEC "%(link_start_netbsd)"
-
-#undef LINK_OS_DEFAULT_SPEC
-#define LINK_OS_DEFAULT_SPEC "%(link_os_netbsd)"
-
-#undef CPP_OS_DEFAULT_SPEC
-#define CPP_OS_DEFAULT_SPEC "%(cpp_os_netbsd)"
#undef TARGET_VERSION
-#define TARGET_VERSION fprintf (stderr, " (PowerPC NetBSD/ELF)");
-
-/* Use STABS debugging information by default. DWARF2 makes a mess of
- the 1.5.2 linker. */
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+#define TARGET_VERSION fprintf (stderr, " (NetBSD/powerpc ELF)");
diff --git a/contrib/gcc/config/rs6000/ppc-asm.h b/contrib/gcc/config/rs6000/ppc-asm.h
index 27f3635..2822e18 100644
--- a/contrib/gcc/config/rs6000/ppc-asm.h
+++ b/contrib/gcc/config/rs6000/ppc-asm.h
@@ -2,7 +2,6 @@
/* Under winnt, 1) gas supports the following as names and 2) in particular
defining "toc" breaks the FUNC_START macro as ".toc" becomes ".2" */
-#if !defined(__WINNT__)
#define r0 0
#define sp 1
#define toc 2
@@ -77,7 +76,6 @@
#define f29 29
#define f30 30
#define f31 31
-#endif
/*
* Macros to glue together two tokens.
@@ -122,43 +120,6 @@ GLUE(.,name):
GLUE(.L,name): \
.size GLUE(.,name),GLUE(.L,name)-GLUE(.,name)
-#elif defined(__WINNT__)
-#define FUNC_NAME(name) GLUE(..,name)
-#define JUMP_TARGET(name) FUNC_NAME(name)
-#define FUNC_START(name) \
- .pdata; \
- .align 2; \
- .ualong GLUE(..,name),GLUE(name,.e),0,0,GLUE(..,name); \
- .reldata; \
-name: \
- .ualong GLUE(..,name),.toc; \
- .section .text; \
- .globl name; \
- .globl GLUE(..,name); \
-GLUE(..,name):
-
-#define FUNC_END(name) \
-GLUE(name,.e): ; \
-GLUE(FE_MOT_RESVD..,name):
-
-#elif defined(_CALL_NT)
-#define FUNC_NAME(name) GLUE(..,name)
-#define JUMP_TARGET(name) FUNC_NAME(name)
-#define FUNC_START(name) \
- .section DESC_SECTION,"aw"; \
-name: \
- .long GLUE(..,name); \
- .long _GLOBAL_OFFSET_TABLE_; \
- .previous; \
- .type GLUE(..,name),@function; \
- .globl name; \
- .globl GLUE(..,name); \
-GLUE(..,name):
-
-#define FUNC_END(name) \
-GLUE(.L,name): \
- .size GLUE(..,name),GLUE(.L,name)-GLUE(..,name)
-
#elif defined (__powerpc64__)
#define FUNC_NAME(name) GLUE(.,name)
#define JUMP_TARGET(name) FUNC_NAME(name)
diff --git a/contrib/gcc/config/rs6000/ppc64-fp.c b/contrib/gcc/config/rs6000/ppc64-fp.c
new file mode 100644
index 0000000..3f6d7cd
--- /dev/null
+++ b/contrib/gcc/config/rs6000/ppc64-fp.c
@@ -0,0 +1,146 @@
+/* Functions needed for soft-float on powerpc64-linux, copied from
+ libgcc2.c with macros expanded to force the use of specific types.
+
+ Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+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 into combinations with other programs,
+and to distribute those combinations 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 a combine
+executable.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#if defined(__powerpc64__)
+#include "fp-bit.h"
+
+extern DItype __fixdfdi (DFtype);
+extern DItype __fixsfdi (SFtype);
+extern USItype __fixunsdfsi (DFtype);
+extern USItype __fixunssfsi (SFtype);
+extern DFtype __floatdidf (DItype);
+extern SFtype __floatdisf (DItype);
+
+static DItype local_fixunssfdi (SFtype);
+static DItype local_fixunsdfdi (DFtype);
+
+DItype
+__fixdfdi (DFtype a)
+{
+ if (a < 0)
+ return - local_fixunsdfdi (-a);
+ return local_fixunsdfdi (a);
+}
+
+DItype
+__fixsfdi (SFtype a)
+{
+ if (a < 0)
+ return - local_fixunssfdi (-a);
+ return local_fixunssfdi (a);
+}
+
+USItype
+__fixunsdfsi (DFtype a)
+{
+ if (a >= - (DFtype) (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1))
+ return (SItype) (a + (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1))
+ - (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1);
+ return (SItype) a;
+}
+
+USItype
+__fixunssfsi (SFtype a)
+{
+ if (a >= - (SFtype) (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1))
+ return (SItype) (a + (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1))
+ - (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1);
+ return (SItype) a;
+}
+
+DFtype
+__floatdidf (DItype u)
+{
+ DFtype d;
+
+ d = (SItype) (u >> (sizeof (SItype) * 8));
+ d *= (((UDItype) 1) << ((sizeof (SItype) * 8) / 2));
+ d *= (((UDItype) 1) << ((sizeof (SItype) * 8) / 2));
+ d += (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1));
+
+ return d;
+}
+
+SFtype
+__floatdisf (DItype u)
+{
+ DFtype f;
+
+ if (53 < (sizeof (DItype) * 8)
+ && 53 > ((sizeof (DItype) * 8) - 53 + 24))
+ {
+ if (! (- ((DItype) 1 << 53) < u
+ && u < ((DItype) 1 << 53)))
+ {
+ if ((UDItype) u & (((UDItype) 1 << ((sizeof (DItype) * 8) - 53)) - 1))
+ {
+ u &= ~ (((UDItype) 1 << ((sizeof (DItype) * 8) - 53)) - 1);
+ u |= ((UDItype) 1 << ((sizeof (DItype) * 8) - 53));
+ }
+ }
+ }
+ f = (SItype) (u >> (sizeof (SItype) * 8));
+ f *= (((UDItype) 1) << ((sizeof (SItype) * 8) / 2));
+ f *= (((UDItype) 1) << ((sizeof (SItype) * 8) / 2));
+ f += (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1));
+
+ return (SFtype) f;
+}
+
+/* This version is needed to prevent recursion; fixunsdfdi in libgcc
+ calls fixdfdi, which in turn calls calls fixunsdfdi. */
+
+static DItype
+local_fixunsdfdi (DFtype a)
+{
+ USItype hi, lo;
+
+ hi = a / (((UDItype) 1) << (sizeof (SItype) * 8));
+ lo = (a - ((DFtype) hi) * (((UDItype) 1) << (sizeof (SItype) * 8)));
+ return ((UDItype) hi << (sizeof (SItype) * 8)) | lo;
+}
+
+/* This version is needed to prevent recursion; fixunssfdi in libgcc
+ calls fixsfdi, which in turn calls calls fixunssfdi. */
+
+static DItype
+local_fixunssfdi (SFtype original_a)
+{
+ DFtype a = original_a;
+ USItype hi, lo;
+
+ hi = a / (((UDItype) 1) << (sizeof (SItype) * 8));
+ lo = (a - ((DFtype) hi) * (((UDItype) 1) << (sizeof (SItype) * 8)));
+ return ((UDItype) hi << (sizeof (SItype) * 8)) | lo;
+}
+
+#endif /* __powerpc64__ */
diff --git a/contrib/gcc/config/rs6000/rs6000-c.c b/contrib/gcc/config/rs6000/rs6000-c.c
new file mode 100644
index 0000000..03f91ba
--- /dev/null
+++ b/contrib/gcc/config/rs6000/rs6000-c.c
@@ -0,0 +1,128 @@
+/* Subroutines for the C front end on the POWER and PowerPC architectures.
+ Copyright (C) 2002
+ Free Software Foundation, Inc.
+
+ Contributed by Zack Weinberg <zack@codesourcery.com>
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "cpplib.h"
+#include "tree.h"
+#include "c-pragma.h"
+#include "errors.h"
+#include "tm_p.h"
+
+/* Handle the machine specific pragma longcall. Its syntax is
+
+ # pragma longcall ( TOGGLE )
+
+ where TOGGLE is either 0 or 1.
+
+ rs6000_default_long_calls is set to the value of TOGGLE, changing
+ whether or not new function declarations receive a longcall
+ attribute by default. */
+
+#define SYNTAX_ERROR(msgid) do { \
+ warning (msgid); \
+ warning ("ignoring malformed #pragma longcall"); \
+ return; \
+} while (0)
+
+void
+rs6000_pragma_longcall (pfile)
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
+{
+ tree x, n;
+
+ /* If we get here, generic code has already scanned the directive
+ leader and the word "longcall". */
+
+ if (c_lex (&x) != CPP_OPEN_PAREN)
+ SYNTAX_ERROR ("missing open paren");
+ if (c_lex (&n) != CPP_NUMBER)
+ SYNTAX_ERROR ("missing number");
+ if (c_lex (&x) != CPP_CLOSE_PAREN)
+ SYNTAX_ERROR ("missing close paren");
+
+ if (n != integer_zero_node && n != integer_one_node)
+ SYNTAX_ERROR ("number must be 0 or 1");
+
+ if (c_lex (&x) != CPP_EOF)
+ warning ("junk at end of #pragma longcall");
+
+ rs6000_default_long_calls = (n == integer_one_node);
+}
+
+/* Handle defining many CPP flags based on TARGET_xxx. As a general
+ policy, rather than trying to guess what flags a user might want a
+ #define for, it's better to define a flag for everything. */
+
+#define builtin_define(TXT) cpp_define (pfile, TXT)
+#define builtin_assert(TXT) cpp_assert (pfile, TXT)
+
+void
+rs6000_cpu_cpp_builtins (pfile)
+ cpp_reader *pfile;
+{
+ if (TARGET_POWER2)
+ builtin_define ("_ARCH_PWR2");
+ else if (TARGET_POWER)
+ builtin_define ("_ARCH_PWR");
+ if (TARGET_POWERPC)
+ builtin_define ("_ARCH_PPC");
+ if (TARGET_POWERPC64)
+ builtin_define ("_ARCH_PPC64");
+ if (! TARGET_POWER && ! TARGET_POWER2 && ! TARGET_POWERPC)
+ builtin_define ("_ARCH_COM");
+ if (TARGET_ALTIVEC)
+ builtin_define ("__ALTIVEC__");
+ if (TARGET_SPE)
+ builtin_define ("__SPE__");
+ if (TARGET_SOFT_FLOAT)
+ builtin_define ("_SOFT_FLOAT");
+ /* Used by lwarx/stwcx. errata work-around. */
+ if (rs6000_cpu == PROCESSOR_PPC405)
+ builtin_define ("__PPC405__");
+
+ /* May be overridden by target configuration. */
+ RS6000_CPU_CPP_ENDIAN_BUILTINS();
+
+ if (TARGET_LONG_DOUBLE_128)
+ builtin_define ("__LONG_DOUBLE_128__");
+
+ switch (rs6000_current_abi)
+ {
+ case ABI_V4:
+ builtin_define ("_CALL_SYSV");
+ break;
+ case ABI_AIX_NODESC:
+ builtin_define ("_CALL_AIX");
+ break;
+ case ABI_AIX:
+ builtin_define ("_CALL_AIXDESC");
+ builtin_define ("_CALL_AIX");
+ break;
+ case ABI_DARWIN:
+ builtin_define ("_CALL_DARWIN");
+ break;
+ default:
+ break;
+ }
+}
diff --git a/contrib/gcc/config/rs6000/rs6000-modes.def b/contrib/gcc/config/rs6000/rs6000-modes.def
new file mode 100644
index 0000000..ac4112c
--- /dev/null
+++ b/contrib/gcc/config/rs6000/rs6000-modes.def
@@ -0,0 +1,31 @@
+/* Definitions of target machine for GNU compiler, for IBM RS/6000.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Add any extra modes needed to represent the condition code.
+
+ For the RS/6000, we need separate modes when unsigned (logical) comparisons
+ are being done and we need a separate mode for floating-point. We also
+ use a mode for the case when we are comparing the results of two
+ comparisons, as then only the EQ bit is valid in the register. */
+
+CC (CCUNS)
+CC (CCFP)
+CC (CCEQ)
diff --git a/contrib/gcc/config/rs6000/rs6000-protos.h b/contrib/gcc/config/rs6000/rs6000-protos.h
index f6024ec..4d6daa5 100644
--- a/contrib/gcc/config/rs6000/rs6000-protos.h
+++ b/contrib/gcc/config/rs6000/rs6000-protos.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for IBM RS/6000.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GNU CC.
@@ -19,13 +19,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. */
+#ifndef GCC_RS6000_PROTOS_H
+#define GCC_RS6000_PROTOS_H
+
/* Declare functions in rs6000.c */
#ifdef RTX_CODE
#ifdef TREE_CODE
-extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx, int));
-extern void rs6000_va_start PARAMS ((int, tree, rtx));
+extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx, int, int));
+extern void rs6000_va_start PARAMS ((tree, rtx));
#endif /* TREE_CODE */
extern struct rtx_def *rs6000_got_register PARAMS ((rtx));
@@ -61,8 +64,12 @@ extern int non_add_cint_operand PARAMS ((rtx, enum machine_mode));
extern int non_logical_cint_operand PARAMS ((rtx, enum machine_mode));
extern int logical_operand PARAMS ((rtx, enum machine_mode));
extern int mask_operand PARAMS ((rtx, enum machine_mode));
+extern int mask_operand_wrap PARAMS ((rtx, enum machine_mode));
extern int mask64_operand PARAMS ((rtx, enum machine_mode));
+extern int mask64_2_operand PARAMS ((rtx, enum machine_mode));
+extern void build_mask64_2_operands PARAMS ((rtx, rtx *));
extern int and64_operand PARAMS ((rtx, enum machine_mode));
+extern int and64_2_operand PARAMS ((rtx, enum machine_mode));
extern int and_operand PARAMS ((rtx, enum machine_mode));
extern int count_register_operand PARAMS ((rtx, enum machine_mode));
extern int xer_operand PARAMS ((rtx, enum machine_mode));
@@ -96,6 +103,8 @@ extern int addrs_ok_for_quad_peep PARAMS ((rtx, rtx));
extern enum reg_class secondary_reload_class PARAMS ((enum reg_class,
enum machine_mode, rtx));
extern int ccr_bit PARAMS ((rtx, int));
+extern int extract_MB PARAMS ((rtx));
+extern int extract_ME PARAMS ((rtx));
extern void print_operand PARAMS ((FILE *, rtx, int));
extern void print_operand_address PARAMS ((FILE *, rtx));
extern enum rtx_code rs6000_reverse_condition PARAMS ((enum machine_mode,
@@ -120,8 +129,6 @@ extern rtx rs6000_legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
extern rtx rs6000_legitimize_reload_address PARAMS ((rtx, enum machine_mode,
int, int, int, int *));
extern int rs6000_legitimate_address PARAMS ((enum machine_mode, rtx, int));
-extern void rs6000_select_rtx_section PARAMS ((enum machine_mode, rtx));
-
extern rtx rs6000_return_addr PARAMS ((int, rtx));
extern void rs6000_output_symbol_ref PARAMS ((FILE*, rtx));
@@ -144,10 +151,7 @@ extern void setup_incoming_varargs PARAMS ((CUMULATIVE_ARGS *,
enum machine_mode, tree,
int *, int));
extern struct rtx_def *rs6000_va_arg PARAMS ((tree, tree));
-extern void output_mi_thunk PARAMS ((FILE *, tree, int, tree));
-extern void rs6000_encode_section_info PARAMS ((tree));
-extern void rs6000_select_section PARAMS ((tree, int));
-extern void rs6000_unique_section PARAMS ((tree, int));
+extern int function_ok_for_sibcall PARAMS ((tree));
#ifdef ARGS_SIZE_RTX
/* expr.h defines ARGS_SIZE_RTX and `enum direction' */
extern enum direction function_arg_padding PARAMS ((enum machine_mode, tree));
@@ -158,8 +162,6 @@ extern enum direction function_arg_padding PARAMS ((enum machine_mode, tree));
extern void optimization_options PARAMS ((int, int));
extern void rs6000_override_options PARAMS ((const char *));
extern void rs6000_file_start PARAMS ((FILE *, const char *));
-extern struct rtx_def *rs6000_float_const PARAMS ((const char *,
- enum machine_mode));
extern int direct_return PARAMS ((void));
extern union tree_node *rs6000_build_va_list PARAMS ((void));
extern int first_reg_to_save PARAMS ((void));
@@ -185,5 +187,18 @@ extern void rs6000_emit_load_toc_table PARAMS ((int));
extern void rs6000_aix_emit_builtin_unwind_init PARAMS ((void));
extern void rs6000_emit_epilogue PARAMS ((int));
extern void debug_stack_info PARAMS ((rs6000_stack_t *));
+extern const char * output_isel PARAMS ((rtx *));
+extern int vrsave_operation PARAMS ((rtx, enum machine_mode));
+extern int rs6000_register_move_cost PARAMS ((enum machine_mode,
+ enum reg_class, enum reg_class));
+extern int rs6000_memory_move_cost PARAMS ((enum machine_mode,
+ enum reg_class, int));
+
+/* Declare functions in rs6000-c.c */
+
+#ifdef GCC_CPPLIB_H
+extern void rs6000_pragma_longcall PARAMS ((cpp_reader *));
+extern void rs6000_cpu_cpp_builtins PARAMS ((cpp_reader *));
+#endif
-extern void machopic_output_stub PARAMS ((FILE *, const char *, const char *));
+#endif /* rs6000-protos.h */
diff --git a/contrib/gcc/config/rs6000/rs6000.c b/contrib/gcc/config/rs6000/rs6000.c
index 89808cc..591f77d 100644
--- a/contrib/gcc/config/rs6000/rs6000.c
+++ b/contrib/gcc/config/rs6000/rs6000.c
@@ -74,7 +74,25 @@ int rs6000_long_double_type_size;
/* Whether -mabi=altivec has appeared */
int rs6000_altivec_abi;
-/* Set to non-zero once AIX common-mode calls have been defined. */
+/* Whether VRSAVE instructions should be generated. */
+int rs6000_altivec_vrsave;
+
+/* String from -mvrsave= option. */
+const char *rs6000_altivec_vrsave_string;
+
+/* Nonzero if we want SPE ABI extensions. */
+int rs6000_spe_abi;
+
+/* Whether isel instructions should be generated. */
+int rs6000_isel;
+
+/* Nonzero if we have FPRs. */
+int rs6000_fprs = 1;
+
+/* String from -misel=. */
+const char *rs6000_isel_string;
+
+/* Set to nonzero once AIX common-mode calls have been defined. */
static int common_mode_defined;
/* Private copy of original value of flag_pic for ABI_AIX. */
@@ -114,6 +132,14 @@ const char *rs6000_debug_name;
int rs6000_debug_stack; /* debug stack applications */
int rs6000_debug_arg; /* debug argument handling */
+const char *rs6000_traceback_name;
+static enum {
+ traceback_default = 0,
+ traceback_none,
+ traceback_part,
+ traceback_full
+} rs6000_traceback;
+
/* Flag to say the TOC is initialized */
int toc_initialized;
char toc_label_name[10];
@@ -121,6 +147,24 @@ char toc_label_name[10];
/* Alias set for saves and restores from the rs6000 stack. */
static int rs6000_sr_alias_set;
+/* Call distance, overridden by -mlongcall and #pragma longcall(1).
+ The only place that looks at this is rs6000_set_default_type_attributes;
+ everywhere else should rely on the presence or absence of a longcall
+ attribute on the function declaration. */
+int rs6000_default_long_calls;
+const char *rs6000_longcall_switch;
+
+struct builtin_description
+{
+ /* mask is not const because we're going to alter it below. This
+ nonsense will go away when we rewrite the -march infrastructure
+ to give us more target flag bits. */
+ unsigned int mask;
+ const enum insn_code icode;
+ const char *const name;
+ const enum rs6000_builtins code;
+};
+
static void rs6000_add_gc_roots PARAMS ((void));
static int num_insns_constant_wide PARAMS ((HOST_WIDE_INT));
static void validate_condition_mode
@@ -129,6 +173,9 @@ static rtx rs6000_generate_compare PARAMS ((enum rtx_code));
static void rs6000_maybe_dead PARAMS ((rtx));
static void rs6000_emit_stack_tie PARAMS ((void));
static void rs6000_frame_related PARAMS ((rtx, rtx, HOST_WIDE_INT, rtx, rtx));
+static void emit_frame_save PARAMS ((rtx, rtx, enum machine_mode,
+ unsigned int, int, int));
+static rtx gen_frame_mem_offset PARAMS ((enum machine_mode, rtx, int));
static void rs6000_emit_allocate_stack PARAMS ((HOST_WIDE_INT, int));
static unsigned rs6000_hash_constant PARAMS ((rtx));
static unsigned toc_hash_function PARAMS ((const void *));
@@ -136,14 +183,19 @@ static int toc_hash_eq PARAMS ((const void *, const void *));
static int toc_hash_mark_entry PARAMS ((void **, void *));
static void toc_hash_mark_table PARAMS ((void *));
static int constant_pool_expr_1 PARAMS ((rtx, int *, int *));
-static void rs6000_free_machine_status PARAMS ((struct function *));
-static void rs6000_init_machine_status PARAMS ((struct function *));
+static struct machine_function * rs6000_init_machine_status PARAMS ((void));
static bool rs6000_assemble_integer PARAMS ((rtx, unsigned int, int));
+#ifdef HAVE_GAS_HIDDEN
+static void rs6000_assemble_visibility PARAMS ((tree, int));
+#endif
static int rs6000_ra_ever_killed PARAMS ((void));
static tree rs6000_handle_longcall_attribute PARAMS ((tree *, tree, tree, int, bool *));
const struct attribute_spec rs6000_attribute_table[];
+static void rs6000_set_default_type_attributes PARAMS ((tree));
static void rs6000_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static void rs6000_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+static void rs6000_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+ HOST_WIDE_INT, tree));
static rtx rs6000_emit_set_long_const PARAMS ((rtx,
HOST_WIDE_INT, HOST_WIDE_INT));
#if TARGET_ELF
@@ -151,30 +203,64 @@ static unsigned int rs6000_elf_section_type_flags PARAMS ((tree, const char *,
int));
static void rs6000_elf_asm_out_constructor PARAMS ((rtx, int));
static void rs6000_elf_asm_out_destructor PARAMS ((rtx, int));
+static void rs6000_elf_select_section PARAMS ((tree, int,
+ unsigned HOST_WIDE_INT));
+static void rs6000_elf_unique_section PARAMS ((tree, int));
+static void rs6000_elf_select_rtx_section PARAMS ((enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT));
+static void rs6000_elf_encode_section_info PARAMS ((tree, int))
+ ATTRIBUTE_UNUSED;
+static const char *rs6000_elf_strip_name_encoding PARAMS ((const char *));
+static bool rs6000_elf_in_small_data_p PARAMS ((tree));
#endif
-#ifdef OBJECT_FORMAT_COFF
-static void xcoff_asm_named_section PARAMS ((const char *, unsigned int));
+#if TARGET_XCOFF
+static void rs6000_xcoff_asm_globalize_label PARAMS ((FILE *, const char *));
+static void rs6000_xcoff_asm_named_section PARAMS ((const char *, unsigned int));
+static void rs6000_xcoff_select_section PARAMS ((tree, int,
+ unsigned HOST_WIDE_INT));
+static void rs6000_xcoff_unique_section PARAMS ((tree, int));
+static void rs6000_xcoff_select_rtx_section PARAMS ((enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT));
+static const char * rs6000_xcoff_strip_name_encoding PARAMS ((const char *));
+static unsigned int rs6000_xcoff_section_type_flags PARAMS ((tree, const char *, int));
#endif
+static void rs6000_xcoff_encode_section_info PARAMS ((tree, int))
+ ATTRIBUTE_UNUSED;
static bool rs6000_binds_local_p PARAMS ((tree));
static int rs6000_adjust_cost PARAMS ((rtx, rtx, rtx, int));
static int rs6000_adjust_priority PARAMS ((rtx, int));
static int rs6000_issue_rate PARAMS ((void));
static void rs6000_init_builtins PARAMS ((void));
-static void altivec_init_builtins PARAMS ((void));
+static rtx rs6000_expand_unop_builtin PARAMS ((enum insn_code, tree, rtx));
+static rtx rs6000_expand_binop_builtin PARAMS ((enum insn_code, tree, rtx));
+static rtx rs6000_expand_ternop_builtin PARAMS ((enum insn_code, tree, rtx));
static rtx rs6000_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
-static rtx altivec_expand_builtin PARAMS ((tree, rtx));
-static rtx altivec_expand_unop_builtin PARAMS ((enum insn_code, tree, rtx));
-static rtx altivec_expand_binop_builtin PARAMS ((enum insn_code, tree, rtx));
+static void altivec_init_builtins PARAMS ((void));
+static void rs6000_common_init_builtins PARAMS ((void));
+
+static void enable_mask_for_builtins PARAMS ((struct builtin_description *,
+ int, enum rs6000_builtins,
+ enum rs6000_builtins));
+static void spe_init_builtins PARAMS ((void));
+static rtx spe_expand_builtin PARAMS ((tree, rtx, bool *));
+static rtx spe_expand_predicate_builtin PARAMS ((enum insn_code, tree, rtx));
+static rtx spe_expand_evsel_builtin PARAMS ((enum insn_code, tree, rtx));
+static int rs6000_emit_int_cmove PARAMS ((rtx, rtx, rtx, rtx));
+
+static rtx altivec_expand_builtin PARAMS ((tree, rtx, bool *));
+static rtx altivec_expand_ld_builtin PARAMS ((tree, rtx, bool *));
+static rtx altivec_expand_st_builtin PARAMS ((tree, rtx, bool *));
+static rtx altivec_expand_dst_builtin PARAMS ((tree, rtx, bool *));
static rtx altivec_expand_abs_builtin PARAMS ((enum insn_code, tree, rtx));
static rtx altivec_expand_predicate_builtin PARAMS ((enum insn_code, const char *, tree, rtx));
-static rtx altivec_expand_ternop_builtin PARAMS ((enum insn_code, tree, rtx));
static rtx altivec_expand_stv_builtin PARAMS ((enum insn_code, tree));
static void rs6000_parse_abi_options PARAMS ((void));
+static void rs6000_parse_vrsave_option PARAMS ((void));
+static void rs6000_parse_isel_option PARAMS ((void));
static int first_altivec_reg_to_save PARAMS ((void));
static unsigned int compute_vrsave_mask PARAMS ((void));
static void is_altivec_return_reg PARAMS ((rtx, void *));
-int vrsave_operation PARAMS ((rtx, enum machine_mode));
static rtx generate_set_vrsave PARAMS ((rtx, rs6000_stack_t *, int));
static void altivec_frame_fixup PARAMS ((rtx, rtx, HOST_WIDE_INT));
static int easy_vector_constant PARAMS ((rtx));
@@ -198,7 +284,9 @@ char rs6000_reg_names[][8] =
"8", "9", "10", "11", "12", "13", "14", "15",
"16", "17", "18", "19", "20", "21", "22", "23",
"24", "25", "26", "27", "28", "29", "30", "31",
- "vrsave"
+ "vrsave", "vscr",
+ /* SPE registers. */
+ "spe_acc", "spefscr"
};
#ifdef TARGET_REGNAMES
@@ -215,22 +303,29 @@ static const char alt_reg_names[][8] =
"mq", "lr", "ctr", "ap",
"%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7",
"xer",
- /* AltiVec registers. */
+ /* AltiVec registers. */
"%v0", "%v1", "%v2", "%v3", "%v4", "%v5", "%v6", "%v7",
- "%v8", "%v9", "%v10", "%v11", "%v12", "%v13", "%v14", "%v15",
- "%v16", "%v17", "%v18", "%v19", "%v20", "%v21", "%v22", "%v23",
- "%v24", "%v25", "%v26", "%v27", "%v28", "%v29", "%v30", "%v31",
- "vrsave"
+ "%v8", "%v9", "%v10", "%v11", "%v12", "%v13", "%v14", "%v15",
+ "%v16", "%v17", "%v18", "%v19", "%v20", "%v21", "%v22", "%v23",
+ "%v24", "%v25", "%v26", "%v27", "%v28", "%v29", "%v30", "%v31",
+ "vrsave", "vscr",
+ /* SPE registers. */
+ "spe_acc", "spefscr"
};
#endif
#ifndef MASK_STRICT_ALIGN
#define MASK_STRICT_ALIGN 0
#endif
+
+/* The VRSAVE bitmask puts bit %v0 as the most significant bit. */
+#define ALTIVEC_REG_BIT(REGNO) (0x80000000 >> ((REGNO) - FIRST_ALTIVEC_REGNO))
/* Initialize the GCC target structure. */
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE rs6000_attribute_table
+#undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES
+#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES rs6000_set_default_type_attributes
#undef TARGET_ASM_ALIGNED_DI_OP
#define TARGET_ASM_ALIGNED_DI_OP DOUBLE_INT_ASM_OP
@@ -238,7 +333,7 @@ static const char alt_reg_names[][8] =
/* Default unaligned ops are only provided for ELF. Find the ops needed
for non-ELF systems. */
#ifndef OBJECT_FORMAT_ELF
-#ifdef OBJECT_FORMAT_COFF
+#if TARGET_XCOFF
/* For XCOFF. rs6000_assemble_integer will handle unaligned DIs on
64-bit targets. */
#undef TARGET_ASM_UNALIGNED_HI_OP
@@ -261,16 +356,16 @@ static const char alt_reg_names[][8] =
#undef TARGET_ASM_INTEGER
#define TARGET_ASM_INTEGER rs6000_assemble_integer
+#ifdef HAVE_GAS_HIDDEN
+#undef TARGET_ASM_ASSEMBLE_VISIBILITY
+#define TARGET_ASM_ASSEMBLE_VISIBILITY rs6000_assemble_visibility
+#endif
+
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE rs6000_output_function_prologue
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE rs6000_output_function_epilogue
-#if TARGET_ELF
-#undef TARGET_SECTION_TYPE_FLAGS
-#define TARGET_SECTION_TYPE_FLAGS rs6000_elf_section_type_flags
-#endif
-
#undef TARGET_SCHED_ISSUE_RATE
#define TARGET_SCHED_ISSUE_RATE rs6000_issue_rate
#undef TARGET_SCHED_ADJUST_COST
@@ -284,8 +379,18 @@ static const char alt_reg_names[][8] =
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN rs6000_expand_builtin
-/* The VRSAVE bitmask puts bit %v0 as the most significant bit. */
-#define ALTIVEC_REG_BIT(REGNO) (0x80000000 >> ((REGNO) - FIRST_ALTIVEC_REGNO))
+#undef TARGET_BINDS_LOCAL_P
+#define TARGET_BINDS_LOCAL_P rs6000_binds_local_p
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK rs6000_output_mi_thunk
+
+/* ??? Should work everywhere, but ask dje@watson.ibm.com before
+ enabling for AIX. */
+#if TARGET_OBJECT_FORMAT != OBJECT_XCOFF
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
+#endif
struct gcc_target targetm = TARGET_INITIALIZER;
@@ -325,6 +430,9 @@ rs6000_override_options (default_cpu)
{"power3", PROCESSOR_PPC630,
MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
POWER_MASKS | MASK_PPC_GPOPT},
+ {"power4", PROCESSOR_POWER4,
+ MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
+ POWER_MASKS | MASK_PPC_GPOPT},
{"powerpc", PROCESSOR_POWERPC,
MASK_POWERPC | MASK_NEW_MNEMONICS,
POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
@@ -400,6 +508,9 @@ rs6000_override_options (default_cpu)
{"7450", PROCESSOR_PPC7450,
MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
+ {"8540", PROCESSOR_PPC8540,
+ MASK_POWERPC | MASK_PPC_GFXOPT | MASK_NEW_MNEMONICS,
+ POWER_MASKS | MASK_PPC_GPOPT | MASK_POWERPC64},
{"801", PROCESSOR_MPCCORE,
MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64},
@@ -413,7 +524,7 @@ rs6000_override_options (default_cpu)
MASK_POWERPC | MASK_SOFT_FLOAT | MASK_NEW_MNEMONICS,
POWER_MASKS | POWERPC_OPT_MASKS | MASK_POWERPC64}};
- size_t ptt_size = sizeof (processor_target_table) / sizeof (struct ptt);
+ const size_t ptt_size = ARRAY_SIZE (processor_target_table);
/* Save current -mmultiple/-mno-multiple status. */
int multiple = TARGET_MULTIPLE;
@@ -448,10 +559,13 @@ rs6000_override_options (default_cpu)
}
}
- /* If we are optimizing big endian systems for space, use the store
- multiple instructions. */
+ if (rs6000_cpu == PROCESSOR_PPC8540)
+ rs6000_isel = 1;
+
+ /* If we are optimizing big endian systems for space, use the load/store
+ multiple and string instructions. */
if (BYTES_BIG_ENDIAN && optimize_size)
- target_flags |= MASK_MULTIPLE;
+ target_flags |= MASK_MULTIPLE | MASK_STRING;
/* If -mmultiple or -mno-multiple was explicitly used, don't
override with the processor default */
@@ -492,20 +606,9 @@ rs6000_override_options (default_cpu)
flag_pic = 0;
}
-#ifdef XCOFF_DEBUGGING_INFO
- if (flag_function_sections && (write_symbols != NO_DEBUG)
- && DEFAULT_ABI == ABI_AIX)
- {
- warning ("-ffunction-sections disabled on AIX when debugging");
- flag_function_sections = 0;
- }
-
- if (flag_data_sections && (DEFAULT_ABI == ABI_AIX))
- {
- warning ("-fdata-sections not supported on AIX");
- flag_data_sections = 0;
- }
-#endif
+ /* For Darwin, always silently make -fpic and -fPIC identical. */
+ if (flag_pic == 1 && DEFAULT_ABI == ABI_DARWIN)
+ flag_pic = 2;
/* Set debug flags */
if (rs6000_debug_name)
@@ -520,6 +623,19 @@ rs6000_override_options (default_cpu)
error ("unknown -mdebug-%s switch", rs6000_debug_name);
}
+ if (rs6000_traceback_name)
+ {
+ if (! strncmp (rs6000_traceback_name, "full", 4))
+ rs6000_traceback = traceback_full;
+ else if (! strncmp (rs6000_traceback_name, "part", 4))
+ rs6000_traceback = traceback_part;
+ else if (! strncmp (rs6000_traceback_name, "no", 2))
+ rs6000_traceback = traceback_none;
+ else
+ error ("unknown -mtraceback arg `%s'; expecting `full', `partial' or `none'",
+ rs6000_traceback_name);
+ }
+
/* Set size of long double */
rs6000_long_double_type_size = 64;
if (rs6000_long_double_size_string)
@@ -536,12 +652,11 @@ rs6000_override_options (default_cpu)
/* Handle -mabi= options. */
rs6000_parse_abi_options ();
-#ifdef TARGET_REGNAMES
- /* If the user desires alternate register names, copy in the
- alternate names now. */
- if (TARGET_REGNAMES)
- memcpy (rs6000_reg_names, alt_reg_names, sizeof (rs6000_reg_names));
-#endif
+ /* Handle -mvrsave= option. */
+ rs6000_parse_vrsave_option ();
+
+ /* Handle -misel= option. */
+ rs6000_parse_isel_option ();
#ifdef SUBTARGET_OVERRIDE_OPTIONS
SUBTARGET_OVERRIDE_OPTIONS;
@@ -550,6 +665,29 @@ rs6000_override_options (default_cpu)
SUBSUBTARGET_OVERRIDE_OPTIONS;
#endif
+ /* Handle -m(no-)longcall option. This is a bit of a cheap hack,
+ using TARGET_OPTIONS to handle a toggle switch, but we're out of
+ bits in target_flags so TARGET_SWITCHES cannot be used.
+ Assumption here is that rs6000_longcall_switch points into the
+ text of the complete option, rather than being a copy, so we can
+ scan back for the presence or absence of the no- modifier. */
+ if (rs6000_longcall_switch)
+ {
+ const char *base = rs6000_longcall_switch;
+ while (base[-1] != 'm') base--;
+
+ if (*rs6000_longcall_switch != '\0')
+ error ("invalid option `%s'", base);
+ rs6000_default_long_calls = (base[0] != 'n');
+ }
+
+#ifdef TARGET_REGNAMES
+ /* If the user desires alternate register names, copy in the
+ alternate names now. */
+ if (TARGET_REGNAMES)
+ memcpy (rs6000_reg_names, alt_reg_names, sizeof (rs6000_reg_names));
+#endif
+
/* Set TARGET_AIX_STRUCT_RET last, after the ABI is determined.
If -maix-struct-return or -msvr4-struct-return was explicitly
used, don't override with the ABI default. */
@@ -561,6 +699,10 @@ rs6000_override_options (default_cpu)
target_flags |= MASK_AIX_STRUCT_RET;
}
+ if (TARGET_LONG_DOUBLE_128
+ && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN))
+ real_format_for_mode[TFmode - QFmode] = &ibm_extended_format;
+
/* Register global variables with the garbage collector. */
rs6000_add_gc_roots ();
@@ -580,7 +722,36 @@ rs6000_override_options (default_cpu)
/* Arrange to save and restore machine status around nested functions. */
init_machine_status = rs6000_init_machine_status;
- free_machine_status = rs6000_free_machine_status;
+}
+
+/* Handle -misel= option. */
+static void
+rs6000_parse_isel_option ()
+{
+ if (rs6000_isel_string == 0)
+ return;
+ else if (! strcmp (rs6000_isel_string, "yes"))
+ rs6000_isel = 1;
+ else if (! strcmp (rs6000_isel_string, "no"))
+ rs6000_isel = 0;
+ else
+ error ("unknown -misel= option specified: '%s'",
+ rs6000_isel_string);
+}
+
+/* Handle -mvrsave= options. */
+static void
+rs6000_parse_vrsave_option ()
+{
+ /* Generate VRSAVE instructions by default. */
+ if (rs6000_altivec_vrsave_string == 0
+ || ! strcmp (rs6000_altivec_vrsave_string, "yes"))
+ rs6000_altivec_vrsave = 1;
+ else if (! strcmp (rs6000_altivec_vrsave_string, "no"))
+ rs6000_altivec_vrsave = 0;
+ else
+ error ("unknown -mvrsave= option specified: '%s'",
+ rs6000_altivec_vrsave_string);
}
/* Handle -mabi= options. */
@@ -593,6 +764,10 @@ rs6000_parse_abi_options ()
rs6000_altivec_abi = 1;
else if (! strcmp (rs6000_abi_string, "no-altivec"))
rs6000_altivec_abi = 0;
+ else if (! strcmp (rs6000_abi_string, "spe"))
+ rs6000_spe_abi = 1;
+ else if (! strcmp (rs6000_abi_string, "no-spe"))
+ rs6000_spe_abi = 0;
else
error ("unknown ABI specified: '%s'", rs6000_abi_string);
}
@@ -651,21 +826,8 @@ rs6000_file_start (file, default_cpu)
putc ('\n', file);
}
}
-
-
-/* Create a CONST_DOUBLE from a string. */
-
-struct rtx_def *
-rs6000_float_const (string, mode)
- const char *string;
- enum machine_mode mode;
-{
- REAL_VALUE_TYPE value;
- value = REAL_VALUE_ATOF (string, mode);
- return immed_real_const_1 (value, mode);
-}
-/* Return non-zero if this function is known to have a null epilogue. */
+/* Return nonzero if this function is known to have a null epilogue. */
int
direct_return ()
@@ -936,8 +1098,9 @@ reg_or_add_cint64_operand (op, mode)
{
return (gpc_reg_operand (op, mode)
|| (GET_CODE (op) == CONST_INT
+#if HOST_BITS_PER_WIDE_INT == 32
&& INTVAL (op) < 0x7fff8000
-#if HOST_BITS_PER_WIDE_INT != 32
+#else
&& ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80008000)
< 0x100000000ll)
#endif
@@ -954,8 +1117,9 @@ reg_or_sub_cint64_operand (op, mode)
{
return (gpc_reg_operand (op, mode)
|| (GET_CODE (op) == CONST_INT
+#if HOST_BITS_PER_WIDE_INT == 32
&& (- INTVAL (op)) < 0x7fff8000
-#if HOST_BITS_PER_WIDE_INT != 32
+#else
&& ((unsigned HOST_WIDE_INT) ((- INTVAL (op)) + 0x80008000)
< 0x100000000ll)
#endif
@@ -1037,20 +1201,16 @@ num_insns_constant_wide (value)
#if HOST_BITS_PER_WIDE_INT == 64
else if (TARGET_POWERPC64)
{
- HOST_WIDE_INT low = value & 0xffffffff;
- HOST_WIDE_INT high = value >> 32;
+ HOST_WIDE_INT low = ((value & 0xffffffff) ^ 0x80000000) - 0x80000000;
+ HOST_WIDE_INT high = value >> 31;
- low = (low ^ 0x80000000) - 0x80000000; /* sign extend */
-
- if (high == 0 && (low & 0x80000000) == 0)
+ if (high == 0 || high == -1)
return 2;
- else if (high == -1 && (low & 0x80000000) != 0)
- return 2;
+ high >>= 1;
- else if (! low)
+ if (low == 0)
return num_insns_constant_wide (high) + 1;
-
else
return (num_insns_constant_wide (high)
+ num_insns_constant_wide (low) + 1);
@@ -1151,7 +1311,8 @@ easy_fp_constant (op, mode)
return 0;
/* Consider all constants with -msoft-float to be easy. */
- if (TARGET_SOFT_FLOAT && mode != DImode)
+ if ((TARGET_SOFT_FLOAT || !TARGET_FPRS)
+ && mode != DImode)
return 1;
/* If we are using V.4 style PIC, consider all constants to be hard. */
@@ -1165,7 +1326,21 @@ easy_fp_constant (op, mode)
return 0;
#endif
- if (mode == DFmode)
+ if (mode == TFmode)
+ {
+ long k[4];
+ REAL_VALUE_TYPE rv;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
+
+ return (num_insns_constant_wide ((HOST_WIDE_INT) k[0]) == 1
+ && num_insns_constant_wide ((HOST_WIDE_INT) k[1]) == 1
+ && num_insns_constant_wide ((HOST_WIDE_INT) k[2]) == 1
+ && num_insns_constant_wide ((HOST_WIDE_INT) k[3]) == 1);
+ }
+
+ else if (mode == DFmode)
{
long k[2];
REAL_VALUE_TYPE rv;
@@ -1173,8 +1348,8 @@ easy_fp_constant (op, mode)
REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
- return (num_insns_constant_wide ((HOST_WIDE_INT)k[0]) == 1
- && num_insns_constant_wide ((HOST_WIDE_INT)k[1]) == 1);
+ return (num_insns_constant_wide ((HOST_WIDE_INT) k[0]) == 1
+ && num_insns_constant_wide ((HOST_WIDE_INT) k[1]) == 1);
}
else if (mode == SFmode)
@@ -1439,64 +1614,187 @@ mask_operand (op, mode)
return c == -lsb;
}
+/* Return 1 for the PowerPC64 rlwinm corner case. */
+
+int
+mask_operand_wrap (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ HOST_WIDE_INT c, lsb;
+
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+
+ c = INTVAL (op);
+
+ if ((c & 0x80000001) != 0x80000001)
+ return 0;
+
+ c = ~c;
+ if (c == 0)
+ return 0;
+
+ lsb = c & -c;
+ c = ~c;
+ c &= -lsb;
+ lsb = c & -c;
+ return c == -lsb;
+}
+
/* Return 1 if the operand is a constant that is a PowerPC64 mask.
It is if there are no more than one 1->0 or 0->1 transitions.
- Reject all ones and all zeros, since these should have been optimized
- away and confuse the making of MB and ME. */
+ Reject all zeros, since zero should have been optimized away and
+ confuses the making of MB and ME. */
int
mask64_operand (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
if (GET_CODE (op) == CONST_INT)
{
HOST_WIDE_INT c, lsb;
- /* We don't change the number of transitions by inverting,
- so make sure we start with the LS bit zero. */
c = INTVAL (op);
- if (c & 1)
- c = ~c;
- /* Reject all zeros or all ones. */
+ /* Reject all zeros. */
if (c == 0)
return 0;
+ /* We don't change the number of transitions by inverting,
+ so make sure we start with the LS bit zero. */
+ if (c & 1)
+ c = ~c;
+
/* Find the transition, and check that all bits above are 1's. */
lsb = c & -c;
return c == -lsb;
}
- else if (GET_CODE (op) == CONST_DOUBLE
- && (mode == VOIDmode || mode == DImode))
+ return 0;
+}
+
+/* Like mask64_operand, but allow up to three transitions. This
+ predicate is used by insn patterns that generate two rldicl or
+ rldicr machine insns. */
+
+int
+mask64_2_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ if (GET_CODE (op) == CONST_INT)
{
- HOST_WIDE_INT low, high, lsb;
+ HOST_WIDE_INT c, lsb;
- if (HOST_BITS_PER_WIDE_INT < 64)
- high = CONST_DOUBLE_HIGH (op);
+ c = INTVAL (op);
- low = CONST_DOUBLE_LOW (op);
- if (low & 1)
- {
- if (HOST_BITS_PER_WIDE_INT < 64)
- high = ~high;
- low = ~low;
- }
+ /* Disallow all zeros. */
+ if (c == 0)
+ return 0;
- if (low == 0)
- {
- if (HOST_BITS_PER_WIDE_INT >= 64 || high == 0)
- return 0;
+ /* We don't change the number of transitions by inverting,
+ so make sure we start with the LS bit zero. */
+ if (c & 1)
+ c = ~c;
- lsb = high & -high;
- return high == -lsb;
- }
+ /* Find the first transition. */
+ lsb = c & -c;
- lsb = low & -low;
- return low == -lsb && (HOST_BITS_PER_WIDE_INT >= 64 || high == ~0);
+ /* Invert to look for a second transition. */
+ c = ~c;
+
+ /* Erase first transition. */
+ c &= -lsb;
+
+ /* Find the second transition. */
+ lsb = c & -c;
+
+ /* Invert to look for a third transition. */
+ c = ~c;
+
+ /* Erase second transition. */
+ c &= -lsb;
+
+ /* Find the third transition (if any). */
+ lsb = c & -c;
+
+ /* Match if all the bits above are 1's (or c is zero). */
+ return c == -lsb;
+ }
+ return 0;
+}
+
+/* Generates shifts and masks for a pair of rldicl or rldicr insns to
+ implement ANDing by the mask IN. */
+void
+build_mask64_2_operands (in, out)
+ rtx in;
+ rtx *out;
+{
+#if HOST_BITS_PER_WIDE_INT >= 64
+ unsigned HOST_WIDE_INT c, lsb, m1, m2;
+ int shift;
+
+ if (GET_CODE (in) != CONST_INT)
+ abort ();
+
+ c = INTVAL (in);
+ if (c & 1)
+ {
+ /* Assume c initially something like 0x00fff000000fffff. The idea
+ is to rotate the word so that the middle ^^^^^^ group of zeros
+ is at the MS end and can be cleared with an rldicl mask. We then
+ rotate back and clear off the MS ^^ group of zeros with a
+ second rldicl. */
+ c = ~c; /* c == 0xff000ffffff00000 */
+ lsb = c & -c; /* lsb == 0x0000000000100000 */
+ m1 = -lsb; /* m1 == 0xfffffffffff00000 */
+ c = ~c; /* c == 0x00fff000000fffff */
+ c &= -lsb; /* c == 0x00fff00000000000 */
+ lsb = c & -c; /* lsb == 0x0000100000000000 */
+ c = ~c; /* c == 0xff000fffffffffff */
+ c &= -lsb; /* c == 0xff00000000000000 */
+ shift = 0;
+ while ((lsb >>= 1) != 0)
+ shift++; /* shift == 44 on exit from loop */
+ m1 <<= 64 - shift; /* m1 == 0xffffff0000000000 */
+ m1 = ~m1; /* m1 == 0x000000ffffffffff */
+ m2 = ~c; /* m2 == 0x00ffffffffffffff */
}
else
- return 0;
+ {
+ /* Assume c initially something like 0xff000f0000000000. The idea
+ is to rotate the word so that the ^^^ middle group of zeros
+ is at the LS end and can be cleared with an rldicr mask. We then
+ rotate back and clear off the LS group of ^^^^^^^^^^ zeros with
+ a second rldicr. */
+ lsb = c & -c; /* lsb == 0x0000010000000000 */
+ m2 = -lsb; /* m2 == 0xffffff0000000000 */
+ c = ~c; /* c == 0x00fff0ffffffffff */
+ c &= -lsb; /* c == 0x00fff00000000000 */
+ lsb = c & -c; /* lsb == 0x0000100000000000 */
+ c = ~c; /* c == 0xff000fffffffffff */
+ c &= -lsb; /* c == 0xff00000000000000 */
+ shift = 0;
+ while ((lsb >>= 1) != 0)
+ shift++; /* shift == 44 on exit from loop */
+ m1 = ~c; /* m1 == 0x00ffffffffffffff */
+ m1 >>= shift; /* m1 == 0x0000000000000fff */
+ m1 = ~m1; /* m1 == 0xfffffffffffff000 */
+ }
+
+ /* Note that when we only have two 0->1 and 1->0 transitions, one of the
+ masks will be all 1's. We are guaranteed more than one transition. */
+ out[0] = GEN_INT (64 - shift);
+ out[1] = GEN_INT (m1);
+ out[2] = GEN_INT (shift);
+ out[3] = GEN_INT (m2);
+#else
+ (void)in;
+ (void)out;
+ abort ();
+#endif
}
/* Return 1 if the operand is either a non-special register or a constant
@@ -1513,6 +1811,20 @@ and64_operand (op, mode)
return (logical_operand (op, mode) || mask64_operand (op, mode));
}
+/* Like the above, but also match constants that can be implemented
+ with two rldicl or rldicr insns. */
+
+int
+and64_2_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (fixed_regs[CR0_REGNO]) /* CR0 not available, don't do andi./andis. */
+ return gpc_reg_operand (op, mode) || mask64_2_operand (op, mode);
+
+ return logical_operand (op, mode) || mask64_2_operand (op, mode);
+}
+
/* Return 1 if the operand is either a non-special register or a
constant that can be used as the operand of an RS/6000 logical AND insn. */
@@ -1562,9 +1874,21 @@ lwa_operand (op, mode)
|| INTVAL (XEXP (XEXP (inner, 0), 1)) % 4 == 0));
}
+/* Return 1 if the operand, used inside a MEM, is a SYMBOL_REF. */
+
+int
+symbol_ref_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (mode != VOIDmode && GET_MODE (op) != mode)
+ return 0;
+
+ return (GET_CODE (op) == SYMBOL_REF);
+}
+
/* Return 1 if the operand, used inside a MEM, is a valid first argument
- to CALL. This is a SYMBOL_REF or a pseudo-register, which will be
- forced to lr. */
+ to CALL. This is a SYMBOL_REF, a pseudo-register, LR or CTR. */
int
call_operand (op, mode)
@@ -1575,7 +1899,10 @@ call_operand (op, mode)
return 0;
return (GET_CODE (op) == SYMBOL_REF
- || (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER));
+ || (GET_CODE (op) == REG
+ && (REGNO (op) == LINK_REGISTER_REGNUM
+ || REGNO (op) == COUNT_REGISTER_REGNUM
+ || REGNO (op) >= FIRST_PSEUDO_REGISTER)));
}
/* Return 1 if the operand is a SYMBOL_REF for a function known to be in
@@ -1790,10 +2117,8 @@ rs6000_legitimize_address (x, oldx, mode)
{
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 += 0x10000, low_int |= ((HOST_WIDE_INT) -1) << 16;
+ low_int = ((INTVAL (XEXP (x, 1)) & 0xffff) ^ 0x8000) - 0x8000;
+ high_int = INTVAL (XEXP (x, 1)) - low_int;
sum = force_operand (gen_rtx_PLUS (Pmode, XEXP (x, 0),
GEN_INT (high_int)), 0);
return gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));
@@ -1802,7 +2127,9 @@ rs6000_legitimize_address (x, oldx, mode)
&& GET_CODE (XEXP (x, 0)) == REG
&& GET_CODE (XEXP (x, 1)) != CONST_INT
&& GET_MODE_NUNITS (mode) == 1
- && (TARGET_HARD_FLOAT || TARGET_POWERPC64 || mode != DFmode)
+ && ((TARGET_HARD_FLOAT && TARGET_FPRS)
+ || TARGET_POWERPC64
+ || (mode != DFmode && mode != TFmode))
&& (TARGET_POWERPC64 || mode != DImode)
&& mode != TImode)
{
@@ -1821,13 +2148,34 @@ rs6000_legitimize_address (x, oldx, mode)
reg = force_reg (Pmode, x);
return reg;
}
+ else if (SPE_VECTOR_MODE (mode))
+ {
+ /* We accept [reg + reg] and [reg + OFFSET]. */
+
+ if (GET_CODE (x) == PLUS)
+ {
+ rtx op1 = XEXP (x, 0);
+ rtx op2 = XEXP (x, 1);
+
+ op1 = force_reg (Pmode, op1);
+
+ if (GET_CODE (op2) != REG
+ && (GET_CODE (op2) != CONST_INT
+ || !SPE_CONST_OFFSET_OK (INTVAL (op2))))
+ op2 = force_reg (Pmode, op2);
+
+ return gen_rtx_PLUS (Pmode, op1, op2);
+ }
+
+ return force_reg (Pmode, x);
+ }
else if (TARGET_ELF && TARGET_32BIT && TARGET_NO_TOC && ! flag_pic
&& GET_CODE (x) != CONST_INT
&& GET_CODE (x) != CONST_DOUBLE
&& CONSTANT_P (x)
&& GET_MODE_NUNITS (mode) == 1
&& (GET_MODE_BITSIZE (mode) <= 32
- || (TARGET_HARD_FLOAT && mode == DFmode)))
+ || ((TARGET_HARD_FLOAT && TARGET_FPRS) && mode == DFmode)))
{
rtx reg = gen_reg_rtx (Pmode);
emit_insn (gen_elf_high (reg, (x)));
@@ -1838,7 +2186,7 @@ rs6000_legitimize_address (x, oldx, mode)
&& GET_CODE (x) != CONST_INT
&& GET_CODE (x) != CONST_DOUBLE
&& CONSTANT_P (x)
- && (TARGET_HARD_FLOAT || mode != DFmode)
+ && ((TARGET_HARD_FLOAT && TARGET_FPRS) || mode != DFmode)
&& mode != DImode
&& mode != TImode)
{
@@ -1925,6 +2273,7 @@ rs6000_legitimize_reload_address (x, mode, opnum, type, ind_levels, win)
&& REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
&& REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
&& GET_CODE (XEXP (x, 1)) == CONST_INT
+ && !SPE_VECTOR_MODE (mode)
&& !ALTIVEC_VECTOR_MODE (mode))
{
HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
@@ -2013,6 +2362,7 @@ rs6000_legitimate_address (mode, x, reg_ok_strict)
return 1;
if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
&& !ALTIVEC_VECTOR_MODE (mode)
+ && !SPE_VECTOR_MODE (mode)
&& TARGET_UPDATE
&& LEGITIMATE_INDIRECT_ADDRESS_P (XEXP (x, 0), reg_ok_strict))
return 1;
@@ -2030,7 +2380,9 @@ rs6000_legitimate_address (mode, x, reg_ok_strict)
if (LEGITIMATE_OFFSET_ADDRESS_P (mode, x, reg_ok_strict))
return 1;
if (mode != TImode
- && (TARGET_HARD_FLOAT || TARGET_POWERPC64 || mode != DFmode)
+ && ((TARGET_HARD_FLOAT && TARGET_FPRS)
+ || TARGET_POWERPC64
+ || (mode != DFmode && mode != TFmode))
&& (TARGET_POWERPC64 || mode != DImode)
&& LEGITIMATE_INDEXED_ADDRESS_P (x, reg_ok_strict))
return 1;
@@ -2051,35 +2403,59 @@ rs6000_emit_set_const (dest, mode, source, n)
enum machine_mode mode;
int n ATTRIBUTE_UNUSED;
{
+ rtx result, insn, set;
HOST_WIDE_INT c0, c1;
- if (mode == QImode || mode == HImode || mode == SImode)
+ if (mode == QImode || mode == HImode)
{
if (dest == NULL)
dest = gen_reg_rtx (mode);
emit_insn (gen_rtx_SET (VOIDmode, dest, source));
return dest;
}
-
- if (GET_CODE (source) == CONST_INT)
+ else if (mode == SImode)
{
- c0 = INTVAL (source);
- c1 = -(c0 < 0);
+ result = no_new_pseudos ? dest : gen_reg_rtx (SImode);
+
+ emit_insn (gen_rtx_SET (VOIDmode, result,
+ GEN_INT (INTVAL (source)
+ & (~ (HOST_WIDE_INT) 0xffff))));
+ emit_insn (gen_rtx_SET (VOIDmode, dest,
+ gen_rtx_IOR (SImode, result,
+ GEN_INT (INTVAL (source) & 0xffff))));
+ result = dest;
}
- else if (GET_CODE (source) == CONST_DOUBLE)
+ else if (mode == DImode)
{
+ if (GET_CODE (source) == CONST_INT)
+ {
+ c0 = INTVAL (source);
+ c1 = -(c0 < 0);
+ }
+ else if (GET_CODE (source) == CONST_DOUBLE)
+ {
#if HOST_BITS_PER_WIDE_INT >= 64
- c0 = CONST_DOUBLE_LOW (source);
- c1 = -(c0 < 0);
+ c0 = CONST_DOUBLE_LOW (source);
+ c1 = -(c0 < 0);
#else
- c0 = CONST_DOUBLE_LOW (source);
- c1 = CONST_DOUBLE_HIGH (source);
+ c0 = CONST_DOUBLE_LOW (source);
+ c1 = CONST_DOUBLE_HIGH (source);
#endif
+ }
+ else
+ abort ();
+
+ result = rs6000_emit_set_long_const (dest, c0, c1);
}
else
abort ();
- return rs6000_emit_set_long_const (dest, c0, c1);
+ insn = get_last_insn ();
+ set = single_set (insn);
+ if (! CONSTANT_P (SET_SRC (set)))
+ set_unique_reg_note (insn, REG_EQUAL, source);
+
+ return result;
}
/* Having failed to find a 3 insn sequence in rs6000_emit_set_const,
@@ -2190,8 +2566,7 @@ rs6000_emit_move (dest, source, mode)
/* FIXME. This should never happen. */
/* Since it seems that it does, do the safe thing and convert
to a CONST_INT. */
- operands[1] =
- GEN_INT (trunc_int_for_mode (CONST_DOUBLE_LOW (operands[1]), mode));
+ operands[1] = gen_int_mode (CONST_DOUBLE_LOW (operands[1]), mode);
}
if (GET_CODE (operands[1]) == CONST_DOUBLE
&& ! FLOAT_MODE_P (mode)
@@ -2223,10 +2598,25 @@ rs6000_emit_move (dest, source, mode)
return;
}
- if (! no_new_pseudos && GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (mode, operands[1]);
+ if (!no_new_pseudos)
+ {
+ if (GET_CODE (operands[1]) == MEM && optimize > 0
+ && (mode == QImode || mode == HImode || mode == SImode)
+ && GET_MODE_SIZE (mode) < GET_MODE_SIZE (word_mode))
+ {
+ rtx reg = gen_reg_rtx (word_mode);
+
+ emit_insn (gen_rtx_SET (word_mode, reg,
+ gen_rtx_ZERO_EXTEND (word_mode,
+ operands[1])));
+ operands[1] = gen_lowpart (mode, reg);
+ }
+ if (GET_CODE (operands[0]) != REG)
+ operands[1] = force_reg (mode, operands[1]);
+ }
- if (mode == SFmode && ! TARGET_POWERPC && TARGET_HARD_FLOAT
+ if (mode == SFmode && ! TARGET_POWERPC
+ && TARGET_HARD_FLOAT && TARGET_FPRS
&& GET_CODE (operands[0]) == MEM)
{
int regnum;
@@ -2250,16 +2640,15 @@ rs6000_emit_move (dest, source, mode)
}
}
- /* Handle the case where reload calls us with an invalid address;
- and the case of CONSTANT_P_RTX. */
- if (!VECTOR_MODE_P (mode)
+ /* Handle the case where reload calls us with an invalid address. */
+ if (reload_in_progress && mode == Pmode
&& (! general_operand (operands[1], mode)
- || ! nonimmediate_operand (operands[0], mode)
- || GET_CODE (operands[1]) == CONSTANT_P_RTX))
- {
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
- return;
- }
+ || ! nonimmediate_operand (operands[0], mode)))
+ goto emit_set;
+
+ /* Handle the case of CONSTANT_P_RTX. */
+ if (GET_CODE (operands[1]) == CONSTANT_P_RTX)
+ goto emit_set;
/* FIXME: In the long term, this switch statement should go away
and be replaced by a sequence of tests based on things like
@@ -2285,6 +2674,10 @@ rs6000_emit_move (dest, source, mode)
case V8HImode:
case V4SFmode:
case V4SImode:
+ case V4HImode:
+ case V2SFmode:
+ case V2SImode:
+ case V1DImode:
if (CONSTANT_P (operands[1])
&& !easy_vector_constant (operands[1]))
operands[1] = force_const_mem (mode, operands[1]);
@@ -2451,6 +2844,16 @@ rs6000_emit_move (dest, source, mode)
operands[1]
= replace_equiv_address (operands[1],
copy_addr_to_reg (XEXP (operands[1], 0)));
+ if (TARGET_POWER)
+ {
+ emit_insn (gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2,
+ gen_rtx_SET (VOIDmode,
+ operands[0], operands[1]),
+ gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_SCRATCH (SImode)))));
+ return;
+ }
break;
default:
@@ -2460,13 +2863,11 @@ rs6000_emit_move (dest, source, mode)
/* Above, we may have called force_const_mem which may have returned
an invalid address. If we can, fix this up; otherwise, reload will
have to deal with it. */
- if (GET_CODE (operands[1]) == MEM
- && ! memory_address_p (mode, XEXP (operands[1], 0))
- && ! reload_in_progress)
- operands[1] = adjust_address (operands[1], mode, 0);
+ if (GET_CODE (operands[1]) == MEM && ! reload_in_progress)
+ operands[1] = validize_mem (operands[1]);
+ emit_set:
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
- return;
}
/* Initialize a variable CUM of type CUMULATIVE_ARGS
@@ -2477,11 +2878,12 @@ rs6000_emit_move (dest, source, mode)
so we never return a PARALLEL. */
void
-init_cumulative_args (cum, fntype, libname, incoming)
+init_cumulative_args (cum, fntype, libname, incoming, libcall)
CUMULATIVE_ARGS *cum;
tree fntype;
rtx libname ATTRIBUTE_UNUSED;
int incoming;
+ int libcall;
{
static CUMULATIVE_ARGS zero_cumulative;
@@ -2490,7 +2892,8 @@ init_cumulative_args (cum, fntype, libname, incoming)
cum->fregno = FP_ARG_MIN_REG;
cum->vregno = ALTIVEC_ARG_MIN_REG;
cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
- cum->call_cookie = CALL_NORMAL;
+ cum->call_cookie = ((DEFAULT_ABI == ABI_V4 && libcall)
+ ? CALL_LIBCALL : CALL_NORMAL);
cum->sysv_gregno = GP_ARG_MIN_REG;
if (incoming)
@@ -2506,8 +2909,10 @@ init_cumulative_args (cum, fntype, libname, incoming)
cum->orig_nargs = cum->nargs_prototype;
- /* Check for longcall's */
- if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
+ /* Check for a longcall attribute. */
+ if (fntype
+ && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype))
+ && !lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
cum->call_cookie = CALL_LONG;
if (TARGET_DEBUG_ARG)
@@ -2568,6 +2973,8 @@ function_arg_boundary (mode, type)
{
if (DEFAULT_ABI == ABI_V4 && (mode == DImode || mode == DFmode))
return 64;
+ else if (SPE_VECTOR_MODE (mode))
+ return 64;
else if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
return 128;
else
@@ -2594,9 +3001,12 @@ function_arg_advance (cum, mode, type, named)
else
cum->words += RS6000_ARG_SIZE (mode, type);
}
+ else if (TARGET_SPE_ABI && TARGET_SPE && SPE_VECTOR_MODE (mode)
+ && named && cum->sysv_gregno <= GP_ARG_MAX_REG)
+ cum->sysv_gregno++;
else if (DEFAULT_ABI == ABI_V4)
{
- if (TARGET_HARD_FLOAT
+ if (TARGET_HARD_FLOAT && TARGET_FPRS
&& (mode == SFmode || mode == DFmode))
{
if (cum->fregno <= FP_ARG_V4_MAX_REG)
@@ -2620,11 +3030,12 @@ function_arg_advance (cum, mode, type, named)
else
n_words = RS6000_ARG_SIZE (mode, type);
- /* Long long is put in odd registers. */
+ /* Long long and SPE vectors are put in odd registers. */
if (n_words == 2 && (gregno & 1) == 0)
gregno += 1;
- /* Long long is not split between registers and stack. */
+ /* Long long and SPE vectors are not split between registers
+ and stack. */
if (gregno + n_words - 1 > GP_ARG_MAX_REG)
{
/* Long long is aligned on the stack. */
@@ -2656,8 +3067,9 @@ function_arg_advance (cum, mode, type, named)
cum->words += align + RS6000_ARG_SIZE (mode, type);
- if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_HARD_FLOAT)
- cum->fregno++;
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT
+ && TARGET_HARD_FLOAT && TARGET_FPRS)
+ cum->fregno += (mode == TFmode ? 2 : 1);
if (TARGET_DEBUG_ARG)
{
@@ -2689,7 +3101,7 @@ function_arg_advance (cum, mode, type, named)
If this is floating-point and no prototype is specified, we use
both an FP and integer register (or possibly FP reg and stack). Library
- functions (when TYPE is zero) always have the proper types for args,
+ functions (when CALL_LIBCALL is set) always have the proper types for args,
so we can pass the FP value just in one register. emit_library_function
doesn't support PARALLEL anyway. */
@@ -2709,14 +3121,18 @@ function_arg (cum, mode, type, named)
if (mode == VOIDmode)
{
if (abi == ABI_V4
- && TARGET_HARD_FLOAT
&& cum->nargs_prototype < 0
- && type && (cum->prototype || TARGET_NO_PROTOTYPE))
+ && (cum->call_cookie & CALL_LIBCALL) == 0
+ && (cum->prototype || TARGET_NO_PROTOTYPE))
{
- return GEN_INT (cum->call_cookie
- | ((cum->fregno == FP_ARG_MIN_REG)
- ? CALL_V4_SET_FP_ARGS
- : CALL_V4_CLEAR_FP_ARGS));
+ /* For the SPE, we need to crxor CR6 always. */
+ if (TARGET_SPE_ABI)
+ return GEN_INT (cum->call_cookie | CALL_V4_SET_FP_ARGS);
+ else if (TARGET_HARD_FLOAT && TARGET_FPRS)
+ return GEN_INT (cum->call_cookie
+ | ((cum->fregno == FP_ARG_MIN_REG)
+ ? CALL_V4_SET_FP_ARGS
+ : CALL_V4_CLEAR_FP_ARGS));
}
return GEN_INT (cum->call_cookie);
@@ -2729,9 +3145,16 @@ function_arg (cum, mode, type, named)
else
return NULL;
}
+ else if (TARGET_SPE_ABI && TARGET_SPE && SPE_VECTOR_MODE (mode) && named)
+ {
+ if (cum->sysv_gregno <= GP_ARG_MAX_REG)
+ return gen_rtx_REG (mode, cum->sysv_gregno);
+ else
+ return NULL;
+ }
else if (abi == ABI_V4)
{
- if (TARGET_HARD_FLOAT
+ if (TARGET_HARD_FLOAT && TARGET_FPRS
&& (mode == SFmode || mode == DFmode))
{
if (cum->fregno <= FP_ARG_V4_MAX_REG)
@@ -2751,13 +3174,29 @@ function_arg (cum, mode, type, named)
else
n_words = RS6000_ARG_SIZE (mode, type);
- /* Long long is put in odd registers. */
+ /* Long long and SPE vectors are put in odd registers. */
if (n_words == 2 && (gregno & 1) == 0)
gregno += 1;
- /* Long long is not split between registers and stack. */
+ /* Long long and SPE vectors are not split between registers
+ and stack. */
if (gregno + n_words - 1 <= GP_ARG_MAX_REG)
- return gen_rtx_REG (mode, gregno);
+ {
+ /* SPE vectors in ... get split into 2 registers. */
+ if (TARGET_SPE && TARGET_SPE_ABI
+ && SPE_VECTOR_MODE (mode) && !named)
+ {
+ rtx r1, r2;
+ enum machine_mode m = SImode;
+
+ r1 = gen_rtx_REG (m, gregno);
+ r1 = gen_rtx_EXPR_LIST (m, r1, const0_rtx);
+ r2 = gen_rtx_REG (m, gregno + 1);
+ r2 = gen_rtx_EXPR_LIST (m, r2, GEN_INT (4));
+ return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2));
+ }
+ return gen_rtx_REG (mode, gregno);
+ }
else
return NULL;
}
@@ -2850,7 +3289,10 @@ function_arg_partial_nregs (cum, mode, type, named)
the argument itself. The pointer is passed in whatever way is
appropriate for passing a pointer to that type.
- Under V.4, structures and unions are passed by reference. */
+ Under V.4, structures and unions are passed by reference.
+
+ As an extension to all ABIs, variable sized types are passed by
+ reference. */
int
function_arg_pass_by_reference (cum, mode, type, named)
@@ -2868,8 +3310,7 @@ function_arg_pass_by_reference (cum, mode, type, named)
return 1;
}
-
- return 0;
+ return type && int_size_in_bytes (type) <= 0;
}
/* Perform any needed actions needed for a function that is receiving a
@@ -2916,8 +3357,6 @@ setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
if (DEFAULT_ABI == ABI_V4)
{
/* Indicate to allocate space on the stack for varargs save area. */
- /* ??? Does this really have to be located at a magic spot on the
- stack, or can we allocate this with assign_stack_local instead. */
cfun->machine->sysv_varargs_p = 1;
if (! no_rtl)
save_area = plus_constant (virtual_stack_vars_rtx,
@@ -2955,7 +3394,8 @@ setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
/* Save FP registers if needed. */
if (DEFAULT_ABI == ABI_V4
- && TARGET_HARD_FLOAT && ! no_rtl
+ && TARGET_HARD_FLOAT && TARGET_FPRS
+ && ! no_rtl
&& next_cum.fregno <= FP_ARG_V4_MAX_REG)
{
int fregno = next_cum.fregno;
@@ -2996,7 +3436,7 @@ rs6000_build_va_list ()
if (DEFAULT_ABI != ABI_V4)
return build_pointer_type (char_type_node);
- record = make_lang_type (RECORD_TYPE);
+ record = (*lang_hooks.types.make_type) (RECORD_TYPE);
type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
f_gpr = build_decl (FIELD_DECL, get_identifier ("gpr"),
@@ -3029,8 +3469,7 @@ rs6000_build_va_list ()
/* Implement va_start. */
void
-rs6000_va_start (stdarg_p, valist, nextarg)
- int stdarg_p;
+rs6000_va_start (valist, nextarg)
tree valist;
rtx nextarg;
{
@@ -3041,7 +3480,7 @@ rs6000_va_start (stdarg_p, valist, nextarg)
/* Only SVR4 needs something special. */
if (DEFAULT_ABI != ABI_V4)
{
- std_expand_builtin_va_start (stdarg_p, valist, nextarg);
+ std_expand_builtin_va_start (valist, nextarg);
return;
}
@@ -3109,13 +3548,29 @@ rs6000_va_arg (valist, type)
int indirect_p, size, rsize, n_reg, sav_ofs, sav_scale;
rtx lab_false, lab_over, addr_rtx, r;
- /* For AIX, the rule is that structures are passed left-aligned in
- their stack slot. However, GCC does not presently do this:
- structures which are the same size as integer types are passed
- right-aligned, as if they were in fact integers. This only
- matters for structures of size 1 or 2, or 4 when TARGET_64BIT. */
if (DEFAULT_ABI != ABI_V4)
- return std_expand_builtin_va_arg (valist, type);
+ {
+ /* Variable sized types are passed by reference. */
+ if (int_size_in_bytes (type) <= 0)
+ {
+ u = build_pointer_type (type);
+
+ /* Args grow upward. */
+ t = build (POSTINCREMENT_EXPR, TREE_TYPE (valist), valist,
+ build_int_2 (POINTER_SIZE / BITS_PER_UNIT, 0));
+ TREE_SIDE_EFFECTS (t) = 1;
+
+ t = build1 (NOP_EXPR, build_pointer_type (u), t);
+ TREE_SIDE_EFFECTS (t) = 1;
+
+ t = build1 (INDIRECT_REF, u, t);
+ TREE_SIDE_EFFECTS (t) = 1;
+
+ return expand_expr (t, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ }
+ else
+ return std_expand_builtin_va_arg (valist, type);
+ }
f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
f_fpr = TREE_CHAIN (f_gpr);
@@ -3142,7 +3597,7 @@ rs6000_va_arg (valist, type)
size = UNITS_PER_WORD;
rsize = 1;
}
- else if (FLOAT_TYPE_P (type) && ! TARGET_SOFT_FLOAT)
+ else if (FLOAT_TYPE_P (type) && TARGET_HARD_FLOAT && TARGET_FPRS)
{
/* FP args go in FP registers, if present. */
indirect_p = 0;
@@ -3167,8 +3622,8 @@ rs6000_va_arg (valist, type)
lab_over = gen_label_rtx ();
addr_rtx = gen_reg_rtx (Pmode);
- /* Vectors never go in registers. */
- if (TREE_CODE (type) != VECTOR_TYPE)
+ /* AltiVec vectors never go in registers. */
+ if (!TARGET_ALTIVEC || TREE_CODE (type) != VECTOR_TYPE)
{
TREE_THIS_VOLATILE (reg) = 1;
emit_cmp_and_jump_insns
@@ -3222,7 +3677,8 @@ rs6000_va_arg (valist, type)
All AltiVec vectors go in the overflow area. So in the AltiVec
case we need to get the vectors from the overflow area, but
remember where the GPRs and FPRs are. */
- if (n_reg > 1 && TREE_CODE (type) != VECTOR_TYPE)
+ if (n_reg > 1 && (TREE_CODE (type) != VECTOR_TYPE
+ || !TARGET_ALTIVEC))
{
t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, build_int_2 (8, 0));
TREE_SIDE_EFFECTS (t) = 1;
@@ -3236,8 +3692,8 @@ rs6000_va_arg (valist, type)
{
int align;
- /* Vectors are 16 byte aligned. */
- if (TREE_CODE (type) == VECTOR_TYPE)
+ /* AltiVec vectors are 16 byte aligned. */
+ if (TARGET_ALTIVEC && TREE_CODE (type) == VECTOR_TYPE)
align = 15;
else
align = 7;
@@ -3270,20 +3726,13 @@ rs6000_va_arg (valist, type)
/* Builtins. */
-#define def_builtin(MASK, NAME, TYPE, CODE) \
-do { \
- if ((MASK) & target_flags) \
- builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL); \
+#define def_builtin(MASK, NAME, TYPE, CODE) \
+do { \
+ if ((MASK) & target_flags) \
+ builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
+ NULL, NULL_TREE); \
} while (0)
-struct builtin_description
-{
- const unsigned int mask;
- const enum insn_code icode;
- const char *const name;
- const enum rs6000_builtins code;
-};
-
/* Simple ternary operations: VECd = foo (VECa, VECb, VECc). */
static const struct builtin_description bdesc_3arg[] =
@@ -3325,7 +3774,7 @@ static const struct builtin_description bdesc_dst[] =
/* Simple binary operations: VECc = foo (VECa, VECb). */
-static const struct builtin_description bdesc_2arg[] =
+static struct builtin_description bdesc_2arg[] =
{
{ MASK_ALTIVEC, CODE_FOR_addv16qi3, "__builtin_altivec_vaddubm", ALTIVEC_BUILTIN_VADDUBM },
{ MASK_ALTIVEC, CODE_FOR_addv8hi3, "__builtin_altivec_vadduhm", ALTIVEC_BUILTIN_VADDUHM },
@@ -3365,11 +3814,11 @@ static const struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vctuxs, "__builtin_altivec_vctuxs", ALTIVEC_BUILTIN_VCTUXS },
{ MASK_ALTIVEC, CODE_FOR_umaxv16qi3, "__builtin_altivec_vmaxub", ALTIVEC_BUILTIN_VMAXUB },
{ MASK_ALTIVEC, CODE_FOR_smaxv16qi3, "__builtin_altivec_vmaxsb", ALTIVEC_BUILTIN_VMAXSB },
- { MASK_ALTIVEC, CODE_FOR_uminv8hi3, "__builtin_altivec_vmaxuh", ALTIVEC_BUILTIN_VMAXUH },
- { MASK_ALTIVEC, CODE_FOR_sminv8hi3, "__builtin_altivec_vmaxsh", ALTIVEC_BUILTIN_VMAXSH },
- { MASK_ALTIVEC, CODE_FOR_uminv4si3, "__builtin_altivec_vmaxuw", ALTIVEC_BUILTIN_VMAXUW },
- { MASK_ALTIVEC, CODE_FOR_sminv4si3, "__builtin_altivec_vmaxsw", ALTIVEC_BUILTIN_VMAXSW },
- { MASK_ALTIVEC, CODE_FOR_sminv4sf3, "__builtin_altivec_vmaxfp", ALTIVEC_BUILTIN_VMAXFP },
+ { MASK_ALTIVEC, CODE_FOR_umaxv8hi3, "__builtin_altivec_vmaxuh", ALTIVEC_BUILTIN_VMAXUH },
+ { MASK_ALTIVEC, CODE_FOR_smaxv8hi3, "__builtin_altivec_vmaxsh", ALTIVEC_BUILTIN_VMAXSH },
+ { MASK_ALTIVEC, CODE_FOR_umaxv4si3, "__builtin_altivec_vmaxuw", ALTIVEC_BUILTIN_VMAXUW },
+ { MASK_ALTIVEC, CODE_FOR_smaxv4si3, "__builtin_altivec_vmaxsw", ALTIVEC_BUILTIN_VMAXSW },
+ { MASK_ALTIVEC, CODE_FOR_smaxv4sf3, "__builtin_altivec_vmaxfp", ALTIVEC_BUILTIN_VMAXFP },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmrghb, "__builtin_altivec_vmrghb", ALTIVEC_BUILTIN_VMRGHB },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmrghh, "__builtin_altivec_vmrghh", ALTIVEC_BUILTIN_VMRGHH },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmrghw, "__builtin_altivec_vmrghw", ALTIVEC_BUILTIN_VMRGHW },
@@ -3440,6 +3889,150 @@ static const struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vsum2sws, "__builtin_altivec_vsum2sws", ALTIVEC_BUILTIN_VSUM2SWS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vsumsws, "__builtin_altivec_vsumsws", ALTIVEC_BUILTIN_VSUMSWS },
{ MASK_ALTIVEC, CODE_FOR_xorv4si3, "__builtin_altivec_vxor", ALTIVEC_BUILTIN_VXOR },
+
+ /* Place holder, leave as first spe builtin. */
+ { 0, CODE_FOR_spe_evaddw, "__builtin_spe_evaddw", SPE_BUILTIN_EVADDW },
+ { 0, CODE_FOR_spe_evand, "__builtin_spe_evand", SPE_BUILTIN_EVAND },
+ { 0, CODE_FOR_spe_evandc, "__builtin_spe_evandc", SPE_BUILTIN_EVANDC },
+ { 0, CODE_FOR_spe_evdivws, "__builtin_spe_evdivws", SPE_BUILTIN_EVDIVWS },
+ { 0, CODE_FOR_spe_evdivwu, "__builtin_spe_evdivwu", SPE_BUILTIN_EVDIVWU },
+ { 0, CODE_FOR_spe_eveqv, "__builtin_spe_eveqv", SPE_BUILTIN_EVEQV },
+ { 0, CODE_FOR_spe_evfsadd, "__builtin_spe_evfsadd", SPE_BUILTIN_EVFSADD },
+ { 0, CODE_FOR_spe_evfsdiv, "__builtin_spe_evfsdiv", SPE_BUILTIN_EVFSDIV },
+ { 0, CODE_FOR_spe_evfsmul, "__builtin_spe_evfsmul", SPE_BUILTIN_EVFSMUL },
+ { 0, CODE_FOR_spe_evfssub, "__builtin_spe_evfssub", SPE_BUILTIN_EVFSSUB },
+ { 0, CODE_FOR_spe_evmergehi, "__builtin_spe_evmergehi", SPE_BUILTIN_EVMERGEHI },
+ { 0, CODE_FOR_spe_evmergehilo, "__builtin_spe_evmergehilo", SPE_BUILTIN_EVMERGEHILO },
+ { 0, CODE_FOR_spe_evmergelo, "__builtin_spe_evmergelo", SPE_BUILTIN_EVMERGELO },
+ { 0, CODE_FOR_spe_evmergelohi, "__builtin_spe_evmergelohi", SPE_BUILTIN_EVMERGELOHI },
+ { 0, CODE_FOR_spe_evmhegsmfaa, "__builtin_spe_evmhegsmfaa", SPE_BUILTIN_EVMHEGSMFAA },
+ { 0, CODE_FOR_spe_evmhegsmfan, "__builtin_spe_evmhegsmfan", SPE_BUILTIN_EVMHEGSMFAN },
+ { 0, CODE_FOR_spe_evmhegsmiaa, "__builtin_spe_evmhegsmiaa", SPE_BUILTIN_EVMHEGSMIAA },
+ { 0, CODE_FOR_spe_evmhegsmian, "__builtin_spe_evmhegsmian", SPE_BUILTIN_EVMHEGSMIAN },
+ { 0, CODE_FOR_spe_evmhegumiaa, "__builtin_spe_evmhegumiaa", SPE_BUILTIN_EVMHEGUMIAA },
+ { 0, CODE_FOR_spe_evmhegumian, "__builtin_spe_evmhegumian", SPE_BUILTIN_EVMHEGUMIAN },
+ { 0, CODE_FOR_spe_evmhesmf, "__builtin_spe_evmhesmf", SPE_BUILTIN_EVMHESMF },
+ { 0, CODE_FOR_spe_evmhesmfa, "__builtin_spe_evmhesmfa", SPE_BUILTIN_EVMHESMFA },
+ { 0, CODE_FOR_spe_evmhesmfaaw, "__builtin_spe_evmhesmfaaw", SPE_BUILTIN_EVMHESMFAAW },
+ { 0, CODE_FOR_spe_evmhesmfanw, "__builtin_spe_evmhesmfanw", SPE_BUILTIN_EVMHESMFANW },
+ { 0, CODE_FOR_spe_evmhesmi, "__builtin_spe_evmhesmi", SPE_BUILTIN_EVMHESMI },
+ { 0, CODE_FOR_spe_evmhesmia, "__builtin_spe_evmhesmia", SPE_BUILTIN_EVMHESMIA },
+ { 0, CODE_FOR_spe_evmhesmiaaw, "__builtin_spe_evmhesmiaaw", SPE_BUILTIN_EVMHESMIAAW },
+ { 0, CODE_FOR_spe_evmhesmianw, "__builtin_spe_evmhesmianw", SPE_BUILTIN_EVMHESMIANW },
+ { 0, CODE_FOR_spe_evmhessf, "__builtin_spe_evmhessf", SPE_BUILTIN_EVMHESSF },
+ { 0, CODE_FOR_spe_evmhessfa, "__builtin_spe_evmhessfa", SPE_BUILTIN_EVMHESSFA },
+ { 0, CODE_FOR_spe_evmhessfaaw, "__builtin_spe_evmhessfaaw", SPE_BUILTIN_EVMHESSFAAW },
+ { 0, CODE_FOR_spe_evmhessfanw, "__builtin_spe_evmhessfanw", SPE_BUILTIN_EVMHESSFANW },
+ { 0, CODE_FOR_spe_evmhessiaaw, "__builtin_spe_evmhessiaaw", SPE_BUILTIN_EVMHESSIAAW },
+ { 0, CODE_FOR_spe_evmhessianw, "__builtin_spe_evmhessianw", SPE_BUILTIN_EVMHESSIANW },
+ { 0, CODE_FOR_spe_evmheumi, "__builtin_spe_evmheumi", SPE_BUILTIN_EVMHEUMI },
+ { 0, CODE_FOR_spe_evmheumia, "__builtin_spe_evmheumia", SPE_BUILTIN_EVMHEUMIA },
+ { 0, CODE_FOR_spe_evmheumiaaw, "__builtin_spe_evmheumiaaw", SPE_BUILTIN_EVMHEUMIAAW },
+ { 0, CODE_FOR_spe_evmheumianw, "__builtin_spe_evmheumianw", SPE_BUILTIN_EVMHEUMIANW },
+ { 0, CODE_FOR_spe_evmheusiaaw, "__builtin_spe_evmheusiaaw", SPE_BUILTIN_EVMHEUSIAAW },
+ { 0, CODE_FOR_spe_evmheusianw, "__builtin_spe_evmheusianw", SPE_BUILTIN_EVMHEUSIANW },
+ { 0, CODE_FOR_spe_evmhogsmfaa, "__builtin_spe_evmhogsmfaa", SPE_BUILTIN_EVMHOGSMFAA },
+ { 0, CODE_FOR_spe_evmhogsmfan, "__builtin_spe_evmhogsmfan", SPE_BUILTIN_EVMHOGSMFAN },
+ { 0, CODE_FOR_spe_evmhogsmiaa, "__builtin_spe_evmhogsmiaa", SPE_BUILTIN_EVMHOGSMIAA },
+ { 0, CODE_FOR_spe_evmhogsmian, "__builtin_spe_evmhogsmian", SPE_BUILTIN_EVMHOGSMIAN },
+ { 0, CODE_FOR_spe_evmhogumiaa, "__builtin_spe_evmhogumiaa", SPE_BUILTIN_EVMHOGUMIAA },
+ { 0, CODE_FOR_spe_evmhogumian, "__builtin_spe_evmhogumian", SPE_BUILTIN_EVMHOGUMIAN },
+ { 0, CODE_FOR_spe_evmhosmf, "__builtin_spe_evmhosmf", SPE_BUILTIN_EVMHOSMF },
+ { 0, CODE_FOR_spe_evmhosmfa, "__builtin_spe_evmhosmfa", SPE_BUILTIN_EVMHOSMFA },
+ { 0, CODE_FOR_spe_evmhosmfaaw, "__builtin_spe_evmhosmfaaw", SPE_BUILTIN_EVMHOSMFAAW },
+ { 0, CODE_FOR_spe_evmhosmfanw, "__builtin_spe_evmhosmfanw", SPE_BUILTIN_EVMHOSMFANW },
+ { 0, CODE_FOR_spe_evmhosmi, "__builtin_spe_evmhosmi", SPE_BUILTIN_EVMHOSMI },
+ { 0, CODE_FOR_spe_evmhosmia, "__builtin_spe_evmhosmia", SPE_BUILTIN_EVMHOSMIA },
+ { 0, CODE_FOR_spe_evmhosmiaaw, "__builtin_spe_evmhosmiaaw", SPE_BUILTIN_EVMHOSMIAAW },
+ { 0, CODE_FOR_spe_evmhosmianw, "__builtin_spe_evmhosmianw", SPE_BUILTIN_EVMHOSMIANW },
+ { 0, CODE_FOR_spe_evmhossf, "__builtin_spe_evmhossf", SPE_BUILTIN_EVMHOSSF },
+ { 0, CODE_FOR_spe_evmhossfa, "__builtin_spe_evmhossfa", SPE_BUILTIN_EVMHOSSFA },
+ { 0, CODE_FOR_spe_evmhossfaaw, "__builtin_spe_evmhossfaaw", SPE_BUILTIN_EVMHOSSFAAW },
+ { 0, CODE_FOR_spe_evmhossfanw, "__builtin_spe_evmhossfanw", SPE_BUILTIN_EVMHOSSFANW },
+ { 0, CODE_FOR_spe_evmhossiaaw, "__builtin_spe_evmhossiaaw", SPE_BUILTIN_EVMHOSSIAAW },
+ { 0, CODE_FOR_spe_evmhossianw, "__builtin_spe_evmhossianw", SPE_BUILTIN_EVMHOSSIANW },
+ { 0, CODE_FOR_spe_evmhoumi, "__builtin_spe_evmhoumi", SPE_BUILTIN_EVMHOUMI },
+ { 0, CODE_FOR_spe_evmhoumia, "__builtin_spe_evmhoumia", SPE_BUILTIN_EVMHOUMIA },
+ { 0, CODE_FOR_spe_evmhoumiaaw, "__builtin_spe_evmhoumiaaw", SPE_BUILTIN_EVMHOUMIAAW },
+ { 0, CODE_FOR_spe_evmhoumianw, "__builtin_spe_evmhoumianw", SPE_BUILTIN_EVMHOUMIANW },
+ { 0, CODE_FOR_spe_evmhousiaaw, "__builtin_spe_evmhousiaaw", SPE_BUILTIN_EVMHOUSIAAW },
+ { 0, CODE_FOR_spe_evmhousianw, "__builtin_spe_evmhousianw", SPE_BUILTIN_EVMHOUSIANW },
+ { 0, CODE_FOR_spe_evmwhsmf, "__builtin_spe_evmwhsmf", SPE_BUILTIN_EVMWHSMF },
+ { 0, CODE_FOR_spe_evmwhsmfa, "__builtin_spe_evmwhsmfa", SPE_BUILTIN_EVMWHSMFA },
+ { 0, CODE_FOR_spe_evmwhsmi, "__builtin_spe_evmwhsmi", SPE_BUILTIN_EVMWHSMI },
+ { 0, CODE_FOR_spe_evmwhsmia, "__builtin_spe_evmwhsmia", SPE_BUILTIN_EVMWHSMIA },
+ { 0, CODE_FOR_spe_evmwhssf, "__builtin_spe_evmwhssf", SPE_BUILTIN_EVMWHSSF },
+ { 0, CODE_FOR_spe_evmwhssfa, "__builtin_spe_evmwhssfa", SPE_BUILTIN_EVMWHSSFA },
+ { 0, CODE_FOR_spe_evmwhumi, "__builtin_spe_evmwhumi", SPE_BUILTIN_EVMWHUMI },
+ { 0, CODE_FOR_spe_evmwhumia, "__builtin_spe_evmwhumia", SPE_BUILTIN_EVMWHUMIA },
+ { 0, CODE_FOR_spe_evmwlsmiaaw, "__builtin_spe_evmwlsmiaaw", SPE_BUILTIN_EVMWLSMIAAW },
+ { 0, CODE_FOR_spe_evmwlsmianw, "__builtin_spe_evmwlsmianw", SPE_BUILTIN_EVMWLSMIANW },
+ { 0, CODE_FOR_spe_evmwlssiaaw, "__builtin_spe_evmwlssiaaw", SPE_BUILTIN_EVMWLSSIAAW },
+ { 0, CODE_FOR_spe_evmwlssianw, "__builtin_spe_evmwlssianw", SPE_BUILTIN_EVMWLSSIANW },
+ { 0, CODE_FOR_spe_evmwlumi, "__builtin_spe_evmwlumi", SPE_BUILTIN_EVMWLUMI },
+ { 0, CODE_FOR_spe_evmwlumia, "__builtin_spe_evmwlumia", SPE_BUILTIN_EVMWLUMIA },
+ { 0, CODE_FOR_spe_evmwlumiaaw, "__builtin_spe_evmwlumiaaw", SPE_BUILTIN_EVMWLUMIAAW },
+ { 0, CODE_FOR_spe_evmwlumianw, "__builtin_spe_evmwlumianw", SPE_BUILTIN_EVMWLUMIANW },
+ { 0, CODE_FOR_spe_evmwlusiaaw, "__builtin_spe_evmwlusiaaw", SPE_BUILTIN_EVMWLUSIAAW },
+ { 0, CODE_FOR_spe_evmwlusianw, "__builtin_spe_evmwlusianw", SPE_BUILTIN_EVMWLUSIANW },
+ { 0, CODE_FOR_spe_evmwsmf, "__builtin_spe_evmwsmf", SPE_BUILTIN_EVMWSMF },
+ { 0, CODE_FOR_spe_evmwsmfa, "__builtin_spe_evmwsmfa", SPE_BUILTIN_EVMWSMFA },
+ { 0, CODE_FOR_spe_evmwsmfaa, "__builtin_spe_evmwsmfaa", SPE_BUILTIN_EVMWSMFAA },
+ { 0, CODE_FOR_spe_evmwsmfan, "__builtin_spe_evmwsmfan", SPE_BUILTIN_EVMWSMFAN },
+ { 0, CODE_FOR_spe_evmwsmi, "__builtin_spe_evmwsmi", SPE_BUILTIN_EVMWSMI },
+ { 0, CODE_FOR_spe_evmwsmia, "__builtin_spe_evmwsmia", SPE_BUILTIN_EVMWSMIA },
+ { 0, CODE_FOR_spe_evmwsmiaa, "__builtin_spe_evmwsmiaa", SPE_BUILTIN_EVMWSMIAA },
+ { 0, CODE_FOR_spe_evmwsmian, "__builtin_spe_evmwsmian", SPE_BUILTIN_EVMWSMIAN },
+ { 0, CODE_FOR_spe_evmwssf, "__builtin_spe_evmwssf", SPE_BUILTIN_EVMWSSF },
+ { 0, CODE_FOR_spe_evmwssfa, "__builtin_spe_evmwssfa", SPE_BUILTIN_EVMWSSFA },
+ { 0, CODE_FOR_spe_evmwssfaa, "__builtin_spe_evmwssfaa", SPE_BUILTIN_EVMWSSFAA },
+ { 0, CODE_FOR_spe_evmwssfan, "__builtin_spe_evmwssfan", SPE_BUILTIN_EVMWSSFAN },
+ { 0, CODE_FOR_spe_evmwumi, "__builtin_spe_evmwumi", SPE_BUILTIN_EVMWUMI },
+ { 0, CODE_FOR_spe_evmwumia, "__builtin_spe_evmwumia", SPE_BUILTIN_EVMWUMIA },
+ { 0, CODE_FOR_spe_evmwumiaa, "__builtin_spe_evmwumiaa", SPE_BUILTIN_EVMWUMIAA },
+ { 0, CODE_FOR_spe_evmwumian, "__builtin_spe_evmwumian", SPE_BUILTIN_EVMWUMIAN },
+ { 0, CODE_FOR_spe_evnand, "__builtin_spe_evnand", SPE_BUILTIN_EVNAND },
+ { 0, CODE_FOR_spe_evnor, "__builtin_spe_evnor", SPE_BUILTIN_EVNOR },
+ { 0, CODE_FOR_spe_evor, "__builtin_spe_evor", SPE_BUILTIN_EVOR },
+ { 0, CODE_FOR_spe_evorc, "__builtin_spe_evorc", SPE_BUILTIN_EVORC },
+ { 0, CODE_FOR_spe_evrlw, "__builtin_spe_evrlw", SPE_BUILTIN_EVRLW },
+ { 0, CODE_FOR_spe_evslw, "__builtin_spe_evslw", SPE_BUILTIN_EVSLW },
+ { 0, CODE_FOR_spe_evsrws, "__builtin_spe_evsrws", SPE_BUILTIN_EVSRWS },
+ { 0, CODE_FOR_spe_evsrwu, "__builtin_spe_evsrwu", SPE_BUILTIN_EVSRWU },
+ { 0, CODE_FOR_spe_evsubfw, "__builtin_spe_evsubfw", SPE_BUILTIN_EVSUBFW },
+
+ /* SPE binary operations expecting a 5-bit unsigned literal. */
+ { 0, CODE_FOR_spe_evaddiw, "__builtin_spe_evaddiw", SPE_BUILTIN_EVADDIW },
+
+ { 0, CODE_FOR_spe_evrlwi, "__builtin_spe_evrlwi", SPE_BUILTIN_EVRLWI },
+ { 0, CODE_FOR_spe_evslwi, "__builtin_spe_evslwi", SPE_BUILTIN_EVSLWI },
+ { 0, CODE_FOR_spe_evsrwis, "__builtin_spe_evsrwis", SPE_BUILTIN_EVSRWIS },
+ { 0, CODE_FOR_spe_evsrwiu, "__builtin_spe_evsrwiu", SPE_BUILTIN_EVSRWIU },
+ { 0, CODE_FOR_spe_evsubifw, "__builtin_spe_evsubifw", SPE_BUILTIN_EVSUBIFW },
+ { 0, CODE_FOR_spe_evmwhssfaa, "__builtin_spe_evmwhssfaa", SPE_BUILTIN_EVMWHSSFAA },
+ { 0, CODE_FOR_spe_evmwhssmaa, "__builtin_spe_evmwhssmaa", SPE_BUILTIN_EVMWHSSMAA },
+ { 0, CODE_FOR_spe_evmwhsmfaa, "__builtin_spe_evmwhsmfaa", SPE_BUILTIN_EVMWHSMFAA },
+ { 0, CODE_FOR_spe_evmwhsmiaa, "__builtin_spe_evmwhsmiaa", SPE_BUILTIN_EVMWHSMIAA },
+ { 0, CODE_FOR_spe_evmwhusiaa, "__builtin_spe_evmwhusiaa", SPE_BUILTIN_EVMWHUSIAA },
+ { 0, CODE_FOR_spe_evmwhumiaa, "__builtin_spe_evmwhumiaa", SPE_BUILTIN_EVMWHUMIAA },
+ { 0, CODE_FOR_spe_evmwhssfan, "__builtin_spe_evmwhssfan", SPE_BUILTIN_EVMWHSSFAN },
+ { 0, CODE_FOR_spe_evmwhssian, "__builtin_spe_evmwhssian", SPE_BUILTIN_EVMWHSSIAN },
+ { 0, CODE_FOR_spe_evmwhsmfan, "__builtin_spe_evmwhsmfan", SPE_BUILTIN_EVMWHSMFAN },
+ { 0, CODE_FOR_spe_evmwhsmian, "__builtin_spe_evmwhsmian", SPE_BUILTIN_EVMWHSMIAN },
+ { 0, CODE_FOR_spe_evmwhusian, "__builtin_spe_evmwhusian", SPE_BUILTIN_EVMWHUSIAN },
+ { 0, CODE_FOR_spe_evmwhumian, "__builtin_spe_evmwhumian", SPE_BUILTIN_EVMWHUMIAN },
+ { 0, CODE_FOR_spe_evmwhgssfaa, "__builtin_spe_evmwhgssfaa", SPE_BUILTIN_EVMWHGSSFAA },
+ { 0, CODE_FOR_spe_evmwhgsmfaa, "__builtin_spe_evmwhgsmfaa", SPE_BUILTIN_EVMWHGSMFAA },
+ { 0, CODE_FOR_spe_evmwhgsmiaa, "__builtin_spe_evmwhgsmiaa", SPE_BUILTIN_EVMWHGSMIAA },
+ { 0, CODE_FOR_spe_evmwhgumiaa, "__builtin_spe_evmwhgumiaa", SPE_BUILTIN_EVMWHGUMIAA },
+ { 0, CODE_FOR_spe_evmwhgssfan, "__builtin_spe_evmwhgssfan", SPE_BUILTIN_EVMWHGSSFAN },
+ { 0, CODE_FOR_spe_evmwhgsmfan, "__builtin_spe_evmwhgsmfan", SPE_BUILTIN_EVMWHGSMFAN },
+ { 0, CODE_FOR_spe_evmwhgsmian, "__builtin_spe_evmwhgsmian", SPE_BUILTIN_EVMWHGSMIAN },
+ { 0, CODE_FOR_spe_evmwhgumian, "__builtin_spe_evmwhgumian", SPE_BUILTIN_EVMWHGUMIAN },
+ { 0, CODE_FOR_spe_brinc, "__builtin_spe_brinc", SPE_BUILTIN_BRINC },
+
+ /* Place-holder. Leave as last binary SPE builtin. */
+ { 0, CODE_FOR_spe_evxor, "__builtin_spe_evxor", SPE_BUILTIN_EVXOR },
};
/* AltiVec predicates. */
@@ -3470,6 +4063,42 @@ static const struct builtin_description_predicates bdesc_altivec_preds[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpgtub.", "__builtin_altivec_vcmpgtub_p", ALTIVEC_BUILTIN_VCMPGTUB_P }
};
+/* SPE predicates. */
+static struct builtin_description bdesc_spe_predicates[] =
+{
+ /* Place-holder. Leave as first. */
+ { 0, CODE_FOR_spe_evcmpeq, "__builtin_spe_evcmpeq", SPE_BUILTIN_EVCMPEQ },
+ { 0, CODE_FOR_spe_evcmpgts, "__builtin_spe_evcmpgts", SPE_BUILTIN_EVCMPGTS },
+ { 0, CODE_FOR_spe_evcmpgtu, "__builtin_spe_evcmpgtu", SPE_BUILTIN_EVCMPGTU },
+ { 0, CODE_FOR_spe_evcmplts, "__builtin_spe_evcmplts", SPE_BUILTIN_EVCMPLTS },
+ { 0, CODE_FOR_spe_evcmpltu, "__builtin_spe_evcmpltu", SPE_BUILTIN_EVCMPLTU },
+ { 0, CODE_FOR_spe_evfscmpeq, "__builtin_spe_evfscmpeq", SPE_BUILTIN_EVFSCMPEQ },
+ { 0, CODE_FOR_spe_evfscmpgt, "__builtin_spe_evfscmpgt", SPE_BUILTIN_EVFSCMPGT },
+ { 0, CODE_FOR_spe_evfscmplt, "__builtin_spe_evfscmplt", SPE_BUILTIN_EVFSCMPLT },
+ { 0, CODE_FOR_spe_evfststeq, "__builtin_spe_evfststeq", SPE_BUILTIN_EVFSTSTEQ },
+ { 0, CODE_FOR_spe_evfststgt, "__builtin_spe_evfststgt", SPE_BUILTIN_EVFSTSTGT },
+ /* Place-holder. Leave as last. */
+ { 0, CODE_FOR_spe_evfststlt, "__builtin_spe_evfststlt", SPE_BUILTIN_EVFSTSTLT },
+};
+
+/* SPE evsel predicates. */
+static struct builtin_description bdesc_spe_evsel[] =
+{
+ /* Place-holder. Leave as first. */
+ { 0, CODE_FOR_spe_evcmpgts, "__builtin_spe_evsel_gts", SPE_BUILTIN_EVSEL_CMPGTS },
+ { 0, CODE_FOR_spe_evcmpgtu, "__builtin_spe_evsel_gtu", SPE_BUILTIN_EVSEL_CMPGTU },
+ { 0, CODE_FOR_spe_evcmplts, "__builtin_spe_evsel_lts", SPE_BUILTIN_EVSEL_CMPLTS },
+ { 0, CODE_FOR_spe_evcmpltu, "__builtin_spe_evsel_ltu", SPE_BUILTIN_EVSEL_CMPLTU },
+ { 0, CODE_FOR_spe_evcmpeq, "__builtin_spe_evsel_eq", SPE_BUILTIN_EVSEL_CMPEQ },
+ { 0, CODE_FOR_spe_evfscmpgt, "__builtin_spe_evsel_fsgt", SPE_BUILTIN_EVSEL_FSCMPGT },
+ { 0, CODE_FOR_spe_evfscmplt, "__builtin_spe_evsel_fslt", SPE_BUILTIN_EVSEL_FSCMPLT },
+ { 0, CODE_FOR_spe_evfscmpeq, "__builtin_spe_evsel_fseq", SPE_BUILTIN_EVSEL_FSCMPEQ },
+ { 0, CODE_FOR_spe_evfststgt, "__builtin_spe_evsel_fststgt", SPE_BUILTIN_EVSEL_FSTSTGT },
+ { 0, CODE_FOR_spe_evfststlt, "__builtin_spe_evsel_fststlt", SPE_BUILTIN_EVSEL_FSTSTLT },
+ /* Place-holder. Leave as last. */
+ { 0, CODE_FOR_spe_evfststeq, "__builtin_spe_evsel_fststeq", SPE_BUILTIN_EVSEL_FSTSTEQ },
+};
+
/* ABS* opreations. */
static const struct builtin_description bdesc_abs[] =
@@ -3486,7 +4115,7 @@ static const struct builtin_description bdesc_abs[] =
/* Simple unary operations: VECb = foo (unsigned literal) or VECb =
foo (VECa). */
-static const struct builtin_description bdesc_1arg[] =
+static struct builtin_description bdesc_1arg[] =
{
{ MASK_ALTIVEC, CODE_FOR_altivec_vexptefp, "__builtin_altivec_vexptefp", ALTIVEC_BUILTIN_VEXPTEFP },
{ MASK_ALTIVEC, CODE_FOR_altivec_vlogefp, "__builtin_altivec_vlogefp", ALTIVEC_BUILTIN_VLOGEFP },
@@ -3505,10 +4134,46 @@ static const struct builtin_description bdesc_1arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vupklsb, "__builtin_altivec_vupklsb", ALTIVEC_BUILTIN_VUPKLSB },
{ MASK_ALTIVEC, CODE_FOR_altivec_vupklpx, "__builtin_altivec_vupklpx", ALTIVEC_BUILTIN_VUPKLPX },
{ MASK_ALTIVEC, CODE_FOR_altivec_vupklsh, "__builtin_altivec_vupklsh", ALTIVEC_BUILTIN_VUPKLSH },
+
+ /* The SPE unary builtins must start with SPE_BUILTIN_EVABS and
+ end with SPE_BUILTIN_EVSUBFUSIAAW. */
+ { 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
+ { 0, CODE_FOR_spe_evaddsmiaaw, "__builtin_spe_evaddsmiaaw", SPE_BUILTIN_EVADDSMIAAW },
+ { 0, CODE_FOR_spe_evaddssiaaw, "__builtin_spe_evaddssiaaw", SPE_BUILTIN_EVADDSSIAAW },
+ { 0, CODE_FOR_spe_evaddumiaaw, "__builtin_spe_evaddumiaaw", SPE_BUILTIN_EVADDUMIAAW },
+ { 0, CODE_FOR_spe_evaddusiaaw, "__builtin_spe_evaddusiaaw", SPE_BUILTIN_EVADDUSIAAW },
+ { 0, CODE_FOR_spe_evcntlsw, "__builtin_spe_evcntlsw", SPE_BUILTIN_EVCNTLSW },
+ { 0, CODE_FOR_spe_evcntlzw, "__builtin_spe_evcntlzw", SPE_BUILTIN_EVCNTLZW },
+ { 0, CODE_FOR_spe_evextsb, "__builtin_spe_evextsb", SPE_BUILTIN_EVEXTSB },
+ { 0, CODE_FOR_spe_evextsh, "__builtin_spe_evextsh", SPE_BUILTIN_EVEXTSH },
+ { 0, CODE_FOR_spe_evfsabs, "__builtin_spe_evfsabs", SPE_BUILTIN_EVFSABS },
+ { 0, CODE_FOR_spe_evfscfsf, "__builtin_spe_evfscfsf", SPE_BUILTIN_EVFSCFSF },
+ { 0, CODE_FOR_spe_evfscfsi, "__builtin_spe_evfscfsi", SPE_BUILTIN_EVFSCFSI },
+ { 0, CODE_FOR_spe_evfscfuf, "__builtin_spe_evfscfuf", SPE_BUILTIN_EVFSCFUF },
+ { 0, CODE_FOR_spe_evfscfui, "__builtin_spe_evfscfui", SPE_BUILTIN_EVFSCFUI },
+ { 0, CODE_FOR_spe_evfsctsf, "__builtin_spe_evfsctsf", SPE_BUILTIN_EVFSCTSF },
+ { 0, CODE_FOR_spe_evfsctsi, "__builtin_spe_evfsctsi", SPE_BUILTIN_EVFSCTSI },
+ { 0, CODE_FOR_spe_evfsctsiz, "__builtin_spe_evfsctsiz", SPE_BUILTIN_EVFSCTSIZ },
+ { 0, CODE_FOR_spe_evfsctuf, "__builtin_spe_evfsctuf", SPE_BUILTIN_EVFSCTUF },
+ { 0, CODE_FOR_spe_evfsctui, "__builtin_spe_evfsctui", SPE_BUILTIN_EVFSCTUI },
+ { 0, CODE_FOR_spe_evfsctuiz, "__builtin_spe_evfsctuiz", SPE_BUILTIN_EVFSCTUIZ },
+ { 0, CODE_FOR_spe_evfsnabs, "__builtin_spe_evfsnabs", SPE_BUILTIN_EVFSNABS },
+ { 0, CODE_FOR_spe_evfsneg, "__builtin_spe_evfsneg", SPE_BUILTIN_EVFSNEG },
+ { 0, CODE_FOR_spe_evmra, "__builtin_spe_evmra", SPE_BUILTIN_EVMRA },
+ { 0, CODE_FOR_spe_evneg, "__builtin_spe_evneg", SPE_BUILTIN_EVNEG },
+ { 0, CODE_FOR_spe_evrndw, "__builtin_spe_evrndw", SPE_BUILTIN_EVRNDW },
+ { 0, CODE_FOR_spe_evsubfsmiaaw, "__builtin_spe_evsubfsmiaaw", SPE_BUILTIN_EVSUBFSMIAAW },
+ { 0, CODE_FOR_spe_evsubfssiaaw, "__builtin_spe_evsubfssiaaw", SPE_BUILTIN_EVSUBFSSIAAW },
+ { 0, CODE_FOR_spe_evsubfumiaaw, "__builtin_spe_evsubfumiaaw", SPE_BUILTIN_EVSUBFUMIAAW },
+ { 0, CODE_FOR_spe_evsplatfi, "__builtin_spe_evsplatfi", SPE_BUILTIN_EVSPLATFI },
+ { 0, CODE_FOR_spe_evsplati, "__builtin_spe_evsplati", SPE_BUILTIN_EVSPLATI },
+
+ /* Place-holder. Leave as last unary SPE builtin. */
+ { 0, CODE_FOR_spe_evsubfusiaaw, "__builtin_spe_evsubfusiaaw", SPE_BUILTIN_EVSUBFUSIAAW },
};
static rtx
-altivec_expand_unop_builtin (icode, arglist, target)
+rs6000_expand_unop_builtin (icode, arglist, target)
enum insn_code icode;
tree arglist;
rtx target;
@@ -3519,9 +4184,29 @@ altivec_expand_unop_builtin (icode, arglist, target)
enum machine_mode tmode = insn_data[icode].operand[0].mode;
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
+ if (icode == CODE_FOR_nothing)
+ /* Builtin not supported on this processor. */
+ return 0;
+
/* If we got invalid arguments bail out before generating bad rtl. */
if (arg0 == error_mark_node)
- return NULL_RTX;
+ return const0_rtx;
+
+ if (icode == CODE_FOR_altivec_vspltisb
+ || icode == CODE_FOR_altivec_vspltish
+ || icode == CODE_FOR_altivec_vspltisw
+ || icode == CODE_FOR_spe_evsplatfi
+ || icode == CODE_FOR_spe_evsplati)
+ {
+ /* Only allow 5-bit *signed* literals. */
+ if (GET_CODE (op0) != CONST_INT
+ || INTVAL (op0) > 0x1f
+ || INTVAL (op0) < -0x1f)
+ {
+ error ("argument 1 must be a 5-bit signed literal");
+ return const0_rtx;
+ }
+ }
if (target == 0
|| GET_MODE (target) != tmode
@@ -3553,7 +4238,7 @@ altivec_expand_abs_builtin (icode, arglist, target)
/* If we have invalid arguments, bail out before generating bad rtl. */
if (arg0 == error_mark_node)
- return NULL_RTX;
+ return const0_rtx;
if (target == 0
|| GET_MODE (target) != tmode
@@ -3575,7 +4260,7 @@ altivec_expand_abs_builtin (icode, arglist, target)
}
static rtx
-altivec_expand_binop_builtin (icode, arglist, target)
+rs6000_expand_binop_builtin (icode, arglist, target)
enum insn_code icode;
tree arglist;
rtx target;
@@ -3589,9 +4274,46 @@ altivec_expand_binop_builtin (icode, arglist, target)
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
enum machine_mode mode1 = insn_data[icode].operand[2].mode;
+ if (icode == CODE_FOR_nothing)
+ /* Builtin not supported on this processor. */
+ return 0;
+
/* If we got invalid arguments bail out before generating bad rtl. */
if (arg0 == error_mark_node || arg1 == error_mark_node)
- return NULL_RTX;
+ return const0_rtx;
+
+ if (icode == CODE_FOR_altivec_vcfux
+ || icode == CODE_FOR_altivec_vcfsx
+ || icode == CODE_FOR_altivec_vctsxs
+ || icode == CODE_FOR_altivec_vctuxs
+ || icode == CODE_FOR_altivec_vspltb
+ || icode == CODE_FOR_altivec_vsplth
+ || icode == CODE_FOR_altivec_vspltw
+ || icode == CODE_FOR_spe_evaddiw
+ || icode == CODE_FOR_spe_evldd
+ || icode == CODE_FOR_spe_evldh
+ || icode == CODE_FOR_spe_evldw
+ || icode == CODE_FOR_spe_evlhhesplat
+ || icode == CODE_FOR_spe_evlhhossplat
+ || icode == CODE_FOR_spe_evlhhousplat
+ || icode == CODE_FOR_spe_evlwhe
+ || icode == CODE_FOR_spe_evlwhos
+ || icode == CODE_FOR_spe_evlwhou
+ || icode == CODE_FOR_spe_evlwhsplat
+ || icode == CODE_FOR_spe_evlwwsplat
+ || icode == CODE_FOR_spe_evrlwi
+ || icode == CODE_FOR_spe_evslwi
+ || icode == CODE_FOR_spe_evsrwis
+ || icode == CODE_FOR_spe_evsrwiu)
+ {
+ /* Only allow 5-bit unsigned literals. */
+ if (TREE_CODE (arg1) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg1) & ~0x1f)
+ {
+ error ("argument 2 must be a 5-bit unsigned literal");
+ return const0_rtx;
+ }
+ }
if (target == 0
|| GET_MODE (target) != tmode
@@ -3632,7 +4354,7 @@ altivec_expand_predicate_builtin (icode, opcode, arglist, target)
if (TREE_CODE (cr6_form) != INTEGER_CST)
{
error ("argument 1 of __builtin_altivec_predicate must be a constant");
- return NULL_RTX;
+ return const0_rtx;
}
else
cr6_form_int = TREE_INT_CST_LOW (cr6_form);
@@ -3642,7 +4364,7 @@ altivec_expand_predicate_builtin (icode, opcode, arglist, target)
/* If we have invalid arguments, bail out before generating bad rtl. */
if (arg0 == error_mark_node || arg1 == error_mark_node)
- return NULL_RTX;
+ return const0_rtx;
if (target == 0
|| GET_MODE (target) != tmode
@@ -3712,7 +4434,7 @@ altivec_expand_stv_builtin (icode, arglist)
if (arg0 == error_mark_node
|| arg1 == error_mark_node
|| arg2 == error_mark_node)
- return NULL_RTX;
+ return const0_rtx;
if (! (*insn_data[icode].operand[2].predicate) (op0, mode2))
op0 = copy_to_mode_reg (mode2, op0);
@@ -3728,7 +4450,7 @@ altivec_expand_stv_builtin (icode, arglist)
}
static rtx
-altivec_expand_ternop_builtin (icode, arglist, target)
+rs6000_expand_ternop_builtin (icode, arglist, target)
enum insn_code icode;
tree arglist;
rtx target;
@@ -3745,11 +4467,29 @@ altivec_expand_ternop_builtin (icode, arglist, target)
enum machine_mode mode1 = insn_data[icode].operand[2].mode;
enum machine_mode mode2 = insn_data[icode].operand[3].mode;
+ if (icode == CODE_FOR_nothing)
+ /* Builtin not supported on this processor. */
+ return 0;
+
/* If we got invalid arguments bail out before generating bad rtl. */
if (arg0 == error_mark_node
|| arg1 == error_mark_node
|| arg2 == error_mark_node)
- return NULL_RTX;
+ return const0_rtx;
+
+ if (icode == CODE_FOR_altivec_vsldoi_4sf
+ || icode == CODE_FOR_altivec_vsldoi_4si
+ || icode == CODE_FOR_altivec_vsldoi_8hi
+ || icode == CODE_FOR_altivec_vsldoi_16qi)
+ {
+ /* Only allow 4-bit unsigned literals. */
+ if (TREE_CODE (arg2) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg2) & ~0xf)
+ {
+ error ("argument 3 must be a 4-bit unsigned literal");
+ return const0_rtx;
+ }
+ }
if (target == 0
|| GET_MODE (target) != tmode
@@ -3770,184 +4510,214 @@ altivec_expand_ternop_builtin (icode, arglist, target)
return target;
}
+
+/* Expand the lvx builtins. */
static rtx
-altivec_expand_builtin (exp, target)
+altivec_expand_ld_builtin (exp, target, expandedp)
tree exp;
rtx target;
+ bool *expandedp;
{
- struct builtin_description *d;
- struct builtin_description_predicates *dp;
- size_t i;
- enum insn_code icode;
tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
tree arglist = TREE_OPERAND (exp, 1);
- tree arg0, arg1, arg2;
- rtx op0, op1, op2, pat;
- enum machine_mode tmode, mode0, mode1, mode2;
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
-
+ tree arg0;
+ enum machine_mode tmode, mode0;
+ rtx pat, op0;
+ enum insn_code icode;
+
switch (fcode)
{
case ALTIVEC_BUILTIN_LD_INTERNAL_16qi:
icode = CODE_FOR_altivec_lvx_16qi;
- arg0 = TREE_VALUE (arglist);
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- tmode = insn_data[icode].operand[0].mode;
- mode0 = insn_data[icode].operand[1].mode;
-
- if (target == 0
- || GET_MODE (target) != tmode
- || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
-
- if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
- op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
-
- pat = GEN_FCN (icode) (target, op0);
- if (! pat)
- return 0;
- emit_insn (pat);
- return target;
-
+ break;
case ALTIVEC_BUILTIN_LD_INTERNAL_8hi:
icode = CODE_FOR_altivec_lvx_8hi;
- arg0 = TREE_VALUE (arglist);
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- tmode = insn_data[icode].operand[0].mode;
- mode0 = insn_data[icode].operand[1].mode;
+ break;
+ case ALTIVEC_BUILTIN_LD_INTERNAL_4si:
+ icode = CODE_FOR_altivec_lvx_4si;
+ break;
+ case ALTIVEC_BUILTIN_LD_INTERNAL_4sf:
+ icode = CODE_FOR_altivec_lvx_4sf;
+ break;
+ default:
+ *expandedp = false;
+ return NULL_RTX;
+ }
- if (target == 0
- || GET_MODE (target) != tmode
- || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
+ *expandedp = true;
- if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
- op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
+ arg0 = TREE_VALUE (arglist);
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ tmode = insn_data[icode].operand[0].mode;
+ mode0 = insn_data[icode].operand[1].mode;
- pat = GEN_FCN (icode) (target, op0);
- if (! pat)
- return 0;
- emit_insn (pat);
- return target;
+ if (target == 0
+ || GET_MODE (target) != tmode
+ || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+ target = gen_reg_rtx (tmode);
- case ALTIVEC_BUILTIN_LD_INTERNAL_4si:
- icode = CODE_FOR_altivec_lvx_4si;
- arg0 = TREE_VALUE (arglist);
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- tmode = insn_data[icode].operand[0].mode;
- mode0 = insn_data[icode].operand[1].mode;
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
- if (target == 0
- || GET_MODE (target) != tmode
- || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
+ pat = GEN_FCN (icode) (target, op0);
+ if (! pat)
+ return 0;
+ emit_insn (pat);
+ return target;
+}
- if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
- op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
+/* Expand the stvx builtins. */
+static rtx
+altivec_expand_st_builtin (exp, target, expandedp)
+ tree exp;
+ rtx target ATTRIBUTE_UNUSED;
+ bool *expandedp;
+{
+ tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ tree arglist = TREE_OPERAND (exp, 1);
+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+ tree arg0, arg1;
+ enum machine_mode mode0, mode1;
+ rtx pat, op0, op1;
+ enum insn_code icode;
- pat = GEN_FCN (icode) (target, op0);
- if (! pat)
- return 0;
- emit_insn (pat);
- return target;
+ switch (fcode)
+ {
+ case ALTIVEC_BUILTIN_ST_INTERNAL_16qi:
+ icode = CODE_FOR_altivec_stvx_16qi;
+ break;
+ case ALTIVEC_BUILTIN_ST_INTERNAL_8hi:
+ icode = CODE_FOR_altivec_stvx_8hi;
+ break;
+ case ALTIVEC_BUILTIN_ST_INTERNAL_4si:
+ icode = CODE_FOR_altivec_stvx_4si;
+ break;
+ case ALTIVEC_BUILTIN_ST_INTERNAL_4sf:
+ icode = CODE_FOR_altivec_stvx_4sf;
+ break;
+ default:
+ *expandedp = false;
+ return NULL_RTX;
+ }
- case ALTIVEC_BUILTIN_LD_INTERNAL_4sf:
- icode = CODE_FOR_altivec_lvx_4sf;
- arg0 = TREE_VALUE (arglist);
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- tmode = insn_data[icode].operand[0].mode;
- mode0 = insn_data[icode].operand[1].mode;
+ arg0 = TREE_VALUE (arglist);
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ mode0 = insn_data[icode].operand[0].mode;
+ mode1 = insn_data[icode].operand[1].mode;
- if (target == 0
- || GET_MODE (target) != tmode
- || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
+ if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
+ op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
+ if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
+ op1 = copy_to_mode_reg (mode1, op1);
- if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
- op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
+ pat = GEN_FCN (icode) (op0, op1);
+ if (pat)
+ emit_insn (pat);
- pat = GEN_FCN (icode) (target, op0);
- if (! pat)
- return 0;
- emit_insn (pat);
- return target;
+ *expandedp = true;
+ return NULL_RTX;
+}
- case ALTIVEC_BUILTIN_ST_INTERNAL_16qi:
- icode = CODE_FOR_altivec_stvx_16qi;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- mode0 = insn_data[icode].operand[0].mode;
- mode1 = insn_data[icode].operand[1].mode;
+/* Expand the dst builtins. */
+static rtx
+altivec_expand_dst_builtin (exp, target, expandedp)
+ tree exp;
+ rtx target ATTRIBUTE_UNUSED;
+ bool *expandedp;
+{
+ tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ tree arglist = TREE_OPERAND (exp, 1);
+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+ tree arg0, arg1, arg2;
+ enum machine_mode mode0, mode1, mode2;
+ rtx pat, op0, op1, op2;
+ struct builtin_description *d;
+ size_t i;
- if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
- op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
- if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
- op1 = copy_to_mode_reg (mode1, op1);
+ *expandedp = false;
- pat = GEN_FCN (icode) (op0, op1);
- if (pat)
- emit_insn (pat);
- return NULL_RTX;
+ /* Handle DST variants. */
+ d = (struct builtin_description *) bdesc_dst;
+ for (i = 0; i < ARRAY_SIZE (bdesc_dst); i++, d++)
+ if (d->code == fcode)
+ {
+ arg0 = TREE_VALUE (arglist);
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
+ mode0 = insn_data[d->icode].operand[0].mode;
+ mode1 = insn_data[d->icode].operand[1].mode;
+ mode2 = insn_data[d->icode].operand[2].mode;
- case ALTIVEC_BUILTIN_ST_INTERNAL_8hi:
- icode = CODE_FOR_altivec_stvx_8hi;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- mode0 = insn_data[icode].operand[0].mode;
- mode1 = insn_data[icode].operand[1].mode;
+ /* Invalid arguments, bail out before generating bad rtl. */
+ if (arg0 == error_mark_node
+ || arg1 == error_mark_node
+ || arg2 == error_mark_node)
+ return const0_rtx;
- if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
- op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
- if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
- op1 = copy_to_mode_reg (mode1, op1);
+ if (TREE_CODE (arg2) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg2) & ~0x3)
+ {
+ error ("argument to `%s' must be a 2-bit unsigned literal", d->name);
+ return const0_rtx;
+ }
- pat = GEN_FCN (icode) (op0, op1);
- if (pat)
- emit_insn (pat);
- return NULL_RTX;
+ if (! (*insn_data[d->icode].operand[0].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+ if (! (*insn_data[d->icode].operand[1].predicate) (op1, mode1))
+ op1 = copy_to_mode_reg (mode1, op1);
- case ALTIVEC_BUILTIN_ST_INTERNAL_4si:
- icode = CODE_FOR_altivec_stvx_4si;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- mode0 = insn_data[icode].operand[0].mode;
- mode1 = insn_data[icode].operand[1].mode;
+ pat = GEN_FCN (d->icode) (op0, op1, op2);
+ if (pat != 0)
+ emit_insn (pat);
- if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
- op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
- if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
- op1 = copy_to_mode_reg (mode1, op1);
+ *expandedp = true;
+ return NULL_RTX;
+ }
- pat = GEN_FCN (icode) (op0, op1);
- if (pat)
- emit_insn (pat);
- return NULL_RTX;
+ return NULL_RTX;
+}
- case ALTIVEC_BUILTIN_ST_INTERNAL_4sf:
- icode = CODE_FOR_altivec_stvx_4sf;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- mode0 = insn_data[icode].operand[0].mode;
- mode1 = insn_data[icode].operand[1].mode;
+/* Expand the builtin in EXP and store the result in TARGET. Store
+ true in *EXPANDEDP if we found a builtin to expand. */
+static rtx
+altivec_expand_builtin (exp, target, expandedp)
+ tree exp;
+ rtx target;
+ bool *expandedp;
+{
+ struct builtin_description *d;
+ struct builtin_description_predicates *dp;
+ size_t i;
+ enum insn_code icode;
+ tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ tree arglist = TREE_OPERAND (exp, 1);
+ tree arg0;
+ rtx op0, pat;
+ enum machine_mode tmode, mode0;
+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
- if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
- op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
- if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
- op1 = copy_to_mode_reg (mode1, op1);
+ target = altivec_expand_ld_builtin (exp, target, expandedp);
+ if (*expandedp)
+ return target;
- pat = GEN_FCN (icode) (op0, op1);
- if (pat)
- emit_insn (pat);
- return NULL_RTX;
+ target = altivec_expand_st_builtin (exp, target, expandedp);
+ if (*expandedp)
+ return target;
+
+ target = altivec_expand_dst_builtin (exp, target, expandedp);
+ if (*expandedp)
+ return target;
+
+ *expandedp = true;
+ switch (fcode)
+ {
case ALTIVEC_BUILTIN_STVX:
return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx, arglist);
case ALTIVEC_BUILTIN_STVEBX:
@@ -3958,7 +4728,7 @@ altivec_expand_builtin (exp, target)
return altivec_expand_stv_builtin (CODE_FOR_altivec_stvewx, arglist);
case ALTIVEC_BUILTIN_STVXL:
return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl, arglist);
-
+
case ALTIVEC_BUILTIN_MFVSCR:
icode = CODE_FOR_altivec_mfvscr;
tmode = insn_data[icode].operand[0].mode;
@@ -3982,7 +4752,7 @@ altivec_expand_builtin (exp, target)
/* If we got invalid arguments bail out before generating bad rtl. */
if (arg0 == error_mark_node)
- return NULL_RTX;
+ return const0_rtx;
if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
op0 = copy_to_mode_reg (mode0, op0);
@@ -3991,7 +4761,7 @@ altivec_expand_builtin (exp, target)
if (pat)
emit_insn (pat);
return NULL_RTX;
-
+
case ALTIVEC_BUILTIN_DSSALL:
emit_insn (gen_altivec_dssall ());
return NULL_RTX;
@@ -4004,7 +4774,14 @@ altivec_expand_builtin (exp, target)
/* If we got invalid arguments bail out before generating bad rtl. */
if (arg0 == error_mark_node)
- return NULL_RTX;
+ return const0_rtx;
+
+ if (TREE_CODE (arg0) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg0) & ~0x3)
+ {
+ error ("argument to dss must be a 2-bit unsigned literal");
+ return const0_rtx;
+ }
if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
op0 = copy_to_mode_reg (mode0, op0);
@@ -4013,66 +4790,15 @@ altivec_expand_builtin (exp, target)
return NULL_RTX;
}
- /* Handle DST variants. */
- d = (struct builtin_description *) bdesc_dst;
- for (i = 0; i < sizeof (bdesc_dst) / sizeof *d; i++, d++)
- if (d->code == fcode)
- {
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
- mode0 = insn_data[d->icode].operand[0].mode;
- mode1 = insn_data[d->icode].operand[1].mode;
- mode2 = insn_data[d->icode].operand[2].mode;
-
- /* Invalid arguments, bail out before generating bad rtl. */
- if (arg0 == error_mark_node
- || arg1 == error_mark_node
- || arg2 == error_mark_node)
- return NULL_RTX;
-
- if (! (*insn_data[d->icode].operand[0].predicate) (op0, mode0))
- op0 = copy_to_mode_reg (mode0, op0);
- if (! (*insn_data[d->icode].operand[1].predicate) (op1, mode1))
- op1 = copy_to_mode_reg (mode1, op1);
-
- if (GET_CODE (op2) != CONST_INT || INTVAL (op2) > 3)
- {
- error ("argument 3 of `%s' must be a 2-bit literal", d->name);
- return NULL_RTX;
- }
-
- pat = GEN_FCN (d->icode) (op0, op1, op2);
- if (pat != 0)
- emit_insn (pat);
-
- return NULL_RTX;
- }
-
/* Expand abs* operations. */
d = (struct builtin_description *) bdesc_abs;
- for (i = 0; i < sizeof (bdesc_abs) / sizeof *d; i++, d++)
+ for (i = 0; i < ARRAY_SIZE (bdesc_abs); i++, d++)
if (d->code == fcode)
return altivec_expand_abs_builtin (d->icode, arglist, target);
- /* Handle simple unary operations. */
- d = (struct builtin_description *) bdesc_1arg;
- for (i = 0; i < sizeof (bdesc_1arg) / sizeof *d; i++, d++)
- if (d->code == fcode)
- return altivec_expand_unop_builtin (d->icode, arglist, target);
-
- /* Handle simple binary operations. */
- d = (struct builtin_description *) bdesc_2arg;
- for (i = 0; i < sizeof (bdesc_2arg) / sizeof *d; i++, d++)
- if (d->code == fcode)
- return altivec_expand_binop_builtin (d->icode, arglist, target);
-
/* Expand the AltiVec predicates. */
dp = (struct builtin_description_predicates *) bdesc_altivec_preds;
- for (i = 0; i < sizeof (bdesc_altivec_preds) / sizeof *dp; i++, dp++)
+ for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, dp++)
if (dp->code == fcode)
return altivec_expand_predicate_builtin (dp->icode, dp->opcode, arglist, target);
@@ -4080,41 +4806,357 @@ altivec_expand_builtin (exp, target)
switch (fcode)
{
case ALTIVEC_BUILTIN_LVSL:
- return altivec_expand_binop_builtin (CODE_FOR_altivec_lvsl,
+ return rs6000_expand_binop_builtin (CODE_FOR_altivec_lvsl,
arglist, target);
case ALTIVEC_BUILTIN_LVSR:
- return altivec_expand_binop_builtin (CODE_FOR_altivec_lvsr,
- arglist, target);
+ return rs6000_expand_binop_builtin (CODE_FOR_altivec_lvsr,
+ arglist, target);
case ALTIVEC_BUILTIN_LVEBX:
- return altivec_expand_binop_builtin (CODE_FOR_altivec_lvebx,
- arglist, target);
+ return rs6000_expand_binop_builtin (CODE_FOR_altivec_lvebx,
+ arglist, target);
case ALTIVEC_BUILTIN_LVEHX:
- return altivec_expand_binop_builtin (CODE_FOR_altivec_lvehx,
- arglist, target);
+ return rs6000_expand_binop_builtin (CODE_FOR_altivec_lvehx,
+ arglist, target);
case ALTIVEC_BUILTIN_LVEWX:
- return altivec_expand_binop_builtin (CODE_FOR_altivec_lvewx,
- arglist, target);
+ return rs6000_expand_binop_builtin (CODE_FOR_altivec_lvewx,
+ arglist, target);
case ALTIVEC_BUILTIN_LVXL:
- return altivec_expand_binop_builtin (CODE_FOR_altivec_lvxl,
- arglist, target);
+ return rs6000_expand_binop_builtin (CODE_FOR_altivec_lvxl,
+ arglist, target);
case ALTIVEC_BUILTIN_LVX:
- return altivec_expand_binop_builtin (CODE_FOR_altivec_lvx,
- arglist, target);
+ return rs6000_expand_binop_builtin (CODE_FOR_altivec_lvx,
+ arglist, target);
default:
break;
/* Fall through. */
}
- /* Handle simple ternary operations. */
- d = (struct builtin_description *) bdesc_3arg;
- for (i = 0; i < sizeof (bdesc_3arg) / sizeof *d; i++, d++)
+ *expandedp = false;
+ return NULL_RTX;
+}
+
+/* Binops that need to be initialized manually, but can be expanded
+ automagically by rs6000_expand_binop_builtin. */
+static struct builtin_description bdesc_2arg_spe[] =
+{
+ { 0, CODE_FOR_spe_evlddx, "__builtin_spe_evlddx", SPE_BUILTIN_EVLDDX },
+ { 0, CODE_FOR_spe_evldwx, "__builtin_spe_evldwx", SPE_BUILTIN_EVLDWX },
+ { 0, CODE_FOR_spe_evldhx, "__builtin_spe_evldhx", SPE_BUILTIN_EVLDHX },
+ { 0, CODE_FOR_spe_evlwhex, "__builtin_spe_evlwhex", SPE_BUILTIN_EVLWHEX },
+ { 0, CODE_FOR_spe_evlwhoux, "__builtin_spe_evlwhoux", SPE_BUILTIN_EVLWHOUX },
+ { 0, CODE_FOR_spe_evlwhosx, "__builtin_spe_evlwhosx", SPE_BUILTIN_EVLWHOSX },
+ { 0, CODE_FOR_spe_evlwwsplatx, "__builtin_spe_evlwwsplatx", SPE_BUILTIN_EVLWWSPLATX },
+ { 0, CODE_FOR_spe_evlwhsplatx, "__builtin_spe_evlwhsplatx", SPE_BUILTIN_EVLWHSPLATX },
+ { 0, CODE_FOR_spe_evlhhesplatx, "__builtin_spe_evlhhesplatx", SPE_BUILTIN_EVLHHESPLATX },
+ { 0, CODE_FOR_spe_evlhhousplatx, "__builtin_spe_evlhhousplatx", SPE_BUILTIN_EVLHHOUSPLATX },
+ { 0, CODE_FOR_spe_evlhhossplatx, "__builtin_spe_evlhhossplatx", SPE_BUILTIN_EVLHHOSSPLATX },
+ { 0, CODE_FOR_spe_evldd, "__builtin_spe_evldd", SPE_BUILTIN_EVLDD },
+ { 0, CODE_FOR_spe_evldw, "__builtin_spe_evldw", SPE_BUILTIN_EVLDW },
+ { 0, CODE_FOR_spe_evldh, "__builtin_spe_evldh", SPE_BUILTIN_EVLDH },
+ { 0, CODE_FOR_spe_evlwhe, "__builtin_spe_evlwhe", SPE_BUILTIN_EVLWHE },
+ { 0, CODE_FOR_spe_evlwhou, "__builtin_spe_evlwhou", SPE_BUILTIN_EVLWHOU },
+ { 0, CODE_FOR_spe_evlwhos, "__builtin_spe_evlwhos", SPE_BUILTIN_EVLWHOS },
+ { 0, CODE_FOR_spe_evlwwsplat, "__builtin_spe_evlwwsplat", SPE_BUILTIN_EVLWWSPLAT },
+ { 0, CODE_FOR_spe_evlwhsplat, "__builtin_spe_evlwhsplat", SPE_BUILTIN_EVLWHSPLAT },
+ { 0, CODE_FOR_spe_evlhhesplat, "__builtin_spe_evlhhesplat", SPE_BUILTIN_EVLHHESPLAT },
+ { 0, CODE_FOR_spe_evlhhousplat, "__builtin_spe_evlhhousplat", SPE_BUILTIN_EVLHHOUSPLAT },
+ { 0, CODE_FOR_spe_evlhhossplat, "__builtin_spe_evlhhossplat", SPE_BUILTIN_EVLHHOSSPLAT }
+};
+
+/* Expand the builtin in EXP and store the result in TARGET. Store
+ true in *EXPANDEDP if we found a builtin to expand.
+
+ This expands the SPE builtins that are not simple unary and binary
+ operations. */
+static rtx
+spe_expand_builtin (exp, target, expandedp)
+ tree exp;
+ rtx target;
+ bool *expandedp;
+{
+ tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ tree arglist = TREE_OPERAND (exp, 1);
+ tree arg1, arg0;
+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+ enum insn_code icode;
+ enum machine_mode tmode, mode0;
+ rtx pat, op0;
+ struct builtin_description *d;
+ size_t i;
+
+ *expandedp = true;
+
+ /* Syntax check for a 5-bit unsigned immediate. */
+ switch (fcode)
+ {
+ case SPE_BUILTIN_EVSTDD:
+ case SPE_BUILTIN_EVSTDH:
+ case SPE_BUILTIN_EVSTDW:
+ case SPE_BUILTIN_EVSTWHE:
+ case SPE_BUILTIN_EVSTWHO:
+ case SPE_BUILTIN_EVSTWWE:
+ case SPE_BUILTIN_EVSTWWO:
+ arg1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ if (TREE_CODE (arg1) != INTEGER_CST
+ || TREE_INT_CST_LOW (arg1) & ~0x1f)
+ {
+ error ("argument 2 must be a 5-bit unsigned literal");
+ return const0_rtx;
+ }
+ break;
+ default:
+ break;
+ }
+
+ d = (struct builtin_description *) bdesc_2arg_spe;
+ for (i = 0; i < ARRAY_SIZE (bdesc_2arg_spe); ++i, ++d)
if (d->code == fcode)
- return altivec_expand_ternop_builtin (d->icode, arglist, target);
+ return rs6000_expand_binop_builtin (d->icode, arglist, target);
- abort ();
+ d = (struct builtin_description *) bdesc_spe_predicates;
+ for (i = 0; i < ARRAY_SIZE (bdesc_spe_predicates); ++i, ++d)
+ if (d->code == fcode)
+ return spe_expand_predicate_builtin (d->icode, arglist, target);
+
+ d = (struct builtin_description *) bdesc_spe_evsel;
+ for (i = 0; i < ARRAY_SIZE (bdesc_spe_evsel); ++i, ++d)
+ if (d->code == fcode)
+ return spe_expand_evsel_builtin (d->icode, arglist, target);
+
+ switch (fcode)
+ {
+ case SPE_BUILTIN_EVSTDDX:
+ return altivec_expand_stv_builtin (CODE_FOR_spe_evstddx, arglist);
+ case SPE_BUILTIN_EVSTDHX:
+ return altivec_expand_stv_builtin (CODE_FOR_spe_evstdhx, arglist);
+ case SPE_BUILTIN_EVSTDWX:
+ return altivec_expand_stv_builtin (CODE_FOR_spe_evstdwx, arglist);
+ case SPE_BUILTIN_EVSTWHEX:
+ return altivec_expand_stv_builtin (CODE_FOR_spe_evstwhex, arglist);
+ case SPE_BUILTIN_EVSTWHOX:
+ return altivec_expand_stv_builtin (CODE_FOR_spe_evstwhox, arglist);
+ case SPE_BUILTIN_EVSTWWEX:
+ return altivec_expand_stv_builtin (CODE_FOR_spe_evstwwex, arglist);
+ case SPE_BUILTIN_EVSTWWOX:
+ return altivec_expand_stv_builtin (CODE_FOR_spe_evstwwox, arglist);
+ case SPE_BUILTIN_EVSTDD:
+ return altivec_expand_stv_builtin (CODE_FOR_spe_evstdd, arglist);
+ case SPE_BUILTIN_EVSTDH:
+ return altivec_expand_stv_builtin (CODE_FOR_spe_evstdh, arglist);
+ case SPE_BUILTIN_EVSTDW:
+ return altivec_expand_stv_builtin (CODE_FOR_spe_evstdw, arglist);
+ case SPE_BUILTIN_EVSTWHE:
+ return altivec_expand_stv_builtin (CODE_FOR_spe_evstwhe, arglist);
+ case SPE_BUILTIN_EVSTWHO:
+ return altivec_expand_stv_builtin (CODE_FOR_spe_evstwho, arglist);
+ case SPE_BUILTIN_EVSTWWE:
+ return altivec_expand_stv_builtin (CODE_FOR_spe_evstwwe, arglist);
+ case SPE_BUILTIN_EVSTWWO:
+ return altivec_expand_stv_builtin (CODE_FOR_spe_evstwwo, arglist);
+ case SPE_BUILTIN_MFSPEFSCR:
+ icode = CODE_FOR_spe_mfspefscr;
+ tmode = insn_data[icode].operand[0].mode;
+
+ if (target == 0
+ || GET_MODE (target) != tmode
+ || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+ target = gen_reg_rtx (tmode);
+
+ pat = GEN_FCN (icode) (target);
+ if (! pat)
+ return 0;
+ emit_insn (pat);
+ return target;
+ case SPE_BUILTIN_MTSPEFSCR:
+ icode = CODE_FOR_spe_mtspefscr;
+ arg0 = TREE_VALUE (arglist);
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ mode0 = insn_data[icode].operand[0].mode;
+
+ if (arg0 == error_mark_node)
+ return const0_rtx;
+
+ if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ pat = GEN_FCN (icode) (op0);
+ if (pat)
+ emit_insn (pat);
+ return NULL_RTX;
+ default:
+ break;
+ }
+
+ *expandedp = false;
return NULL_RTX;
}
+static rtx
+spe_expand_predicate_builtin (icode, arglist, target)
+ enum insn_code icode;
+ tree arglist;
+ rtx target;
+{
+ rtx pat, scratch, tmp;
+ tree form = TREE_VALUE (arglist);
+ tree arg0 = TREE_VALUE (TREE_CHAIN (arglist));
+ tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
+ enum machine_mode mode1 = insn_data[icode].operand[2].mode;
+ int form_int;
+ enum rtx_code code;
+
+ if (TREE_CODE (form) != INTEGER_CST)
+ {
+ error ("argument 1 of __builtin_spe_predicate must be a constant");
+ return const0_rtx;
+ }
+ else
+ form_int = TREE_INT_CST_LOW (form);
+
+ if (mode0 != mode1)
+ abort ();
+
+ if (arg0 == error_mark_node || arg1 == error_mark_node)
+ return const0_rtx;
+
+ if (target == 0
+ || GET_MODE (target) != SImode
+ || ! (*insn_data[icode].operand[0].predicate) (target, SImode))
+ target = gen_reg_rtx (SImode);
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+ if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
+ op1 = copy_to_mode_reg (mode1, op1);
+
+ scratch = gen_reg_rtx (CCmode);
+
+ pat = GEN_FCN (icode) (scratch, op0, op1);
+ if (! pat)
+ return const0_rtx;
+ emit_insn (pat);
+
+ /* There are 4 variants for each predicate: _any_, _all_, _upper_,
+ _lower_. We use one compare, but look in different bits of the
+ CR for each variant.
+
+ There are 2 elements in each SPE simd type (upper/lower). The CR
+ bits are set as follows:
+
+ BIT0 | BIT 1 | BIT 2 | BIT 3
+ U | L | (U | L) | (U & L)
+
+ So, for an "all" relationship, BIT 3 would be set.
+ For an "any" relationship, BIT 2 would be set. Etc.
+
+ Following traditional nomenclature, these bits map to:
+
+ BIT0 | BIT 1 | BIT 2 | BIT 3
+ LT | GT | EQ | OV
+
+ Later, we will generate rtl to look in the LT/EQ/EQ/OV bits.
+ */
+
+ switch (form_int)
+ {
+ /* All variant. OV bit. */
+ case 0:
+ /* We need to get to the OV bit, which is the ORDERED bit. We
+ could generate (ordered:SI (reg:CC xx) (const_int 0)), but
+ that's ugly and will trigger a validate_condition_mode abort.
+ So let's just use another pattern. */
+ emit_insn (gen_move_from_CR_ov_bit (target, scratch));
+ return target;
+ /* Any variant. EQ bit. */
+ case 1:
+ code = EQ;
+ break;
+ /* Upper variant. LT bit. */
+ case 2:
+ code = LT;
+ break;
+ /* Lower variant. GT bit. */
+ case 3:
+ code = GT;
+ break;
+ default:
+ error ("argument 1 of __builtin_spe_predicate is out of range");
+ return const0_rtx;
+ }
+
+ tmp = gen_rtx_fmt_ee (code, SImode, scratch, const0_rtx);
+ emit_move_insn (target, tmp);
+
+ return target;
+}
+
+/* The evsel builtins look like this:
+
+ e = __builtin_spe_evsel_OP (a, b, c, d);
+
+ and work like this:
+
+ e[upper] = a[upper] *OP* b[upper] ? c[upper] : d[upper];
+ e[lower] = a[lower] *OP* b[lower] ? c[lower] : d[lower];
+*/
+
+static rtx
+spe_expand_evsel_builtin (icode, arglist, target)
+ enum insn_code icode;
+ tree arglist;
+ rtx target;
+{
+ rtx pat, scratch;
+ tree arg0 = TREE_VALUE (arglist);
+ tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ tree arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
+ rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ rtx op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
+ rtx op3 = expand_expr (arg3, NULL_RTX, VOIDmode, 0);
+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
+ enum machine_mode mode1 = insn_data[icode].operand[2].mode;
+
+ if (mode0 != mode1)
+ abort ();
+
+ if (arg0 == error_mark_node || arg1 == error_mark_node
+ || arg2 == error_mark_node || arg3 == error_mark_node)
+ return const0_rtx;
+
+ if (target == 0
+ || GET_MODE (target) != mode0
+ || ! (*insn_data[icode].operand[0].predicate) (target, mode0))
+ target = gen_reg_rtx (mode0);
+
+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+ if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
+ op1 = copy_to_mode_reg (mode0, op1);
+ if (! (*insn_data[icode].operand[1].predicate) (op2, mode1))
+ op2 = copy_to_mode_reg (mode0, op2);
+ if (! (*insn_data[icode].operand[1].predicate) (op3, mode1))
+ op3 = copy_to_mode_reg (mode0, op3);
+
+ /* Generate the compare. */
+ scratch = gen_reg_rtx (CCmode);
+ pat = GEN_FCN (icode) (scratch, op0, op1);
+ if (! pat)
+ return const0_rtx;
+ emit_insn (pat);
+
+ if (mode0 == V2SImode)
+ emit_insn (gen_spe_evsel (target, op2, op3, scratch));
+ else
+ emit_insn (gen_spe_evsel_fs (target, op2, op3, scratch));
+
+ return target;
+}
+
/* Expand an expression EXP that calls a built-in function,
with result going to TARGET if that's convenient
(and in mode MODE if that's convenient).
@@ -4129,487 +5171,695 @@ rs6000_expand_builtin (exp, target, subtarget, mode, ignore)
enum machine_mode mode ATTRIBUTE_UNUSED;
int ignore ATTRIBUTE_UNUSED;
{
+ tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ tree arglist = TREE_OPERAND (exp, 1);
+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+ struct builtin_description *d;
+ size_t i;
+ rtx ret;
+ bool success;
+
if (TARGET_ALTIVEC)
- return altivec_expand_builtin (exp, target);
+ {
+ ret = altivec_expand_builtin (exp, target, &success);
+
+ if (success)
+ return ret;
+ }
+ if (TARGET_SPE)
+ {
+ ret = spe_expand_builtin (exp, target, &success);
+
+ if (success)
+ return ret;
+ }
+
+ if (TARGET_ALTIVEC || TARGET_SPE)
+ {
+ /* Handle simple unary operations. */
+ d = (struct builtin_description *) bdesc_1arg;
+ for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
+ if (d->code == fcode)
+ return rs6000_expand_unop_builtin (d->icode, arglist, target);
+
+ /* Handle simple binary operations. */
+ d = (struct builtin_description *) bdesc_2arg;
+ for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
+ if (d->code == fcode)
+ return rs6000_expand_binop_builtin (d->icode, arglist, target);
+
+ /* Handle simple ternary operations. */
+ d = (struct builtin_description *) bdesc_3arg;
+ for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
+ if (d->code == fcode)
+ return rs6000_expand_ternop_builtin (d->icode, arglist, target);
+ }
abort ();
+ return NULL_RTX;
}
static void
rs6000_init_builtins ()
{
+ if (TARGET_SPE)
+ spe_init_builtins ();
if (TARGET_ALTIVEC)
altivec_init_builtins ();
+ if (TARGET_ALTIVEC || TARGET_SPE)
+ rs6000_common_init_builtins ();
}
+/* Search through a set of builtins and enable the mask bits.
+ DESC is an array of builtins.
+ SIZE is the totaly number of builtins.
+ START is the builtin enum at which to start.
+ END is the builtin enum at which to end. */
static void
-altivec_init_builtins (void)
+enable_mask_for_builtins (desc, size, start, end)
+ struct builtin_description *desc;
+ int size;
+ enum rs6000_builtins start, end;
{
- struct builtin_description *d;
- struct builtin_description_predicates *dp;
- size_t i;
+ int i;
- tree endlink = void_list_node;
+ for (i = 0; i < size; ++i)
+ if (desc[i].code == start)
+ break;
- tree pint_type_node = build_pointer_type (integer_type_node);
- tree pvoid_type_node = build_pointer_type (void_type_node);
- tree pshort_type_node = build_pointer_type (short_integer_type_node);
- tree pchar_type_node = build_pointer_type (char_type_node);
- tree pfloat_type_node = build_pointer_type (float_type_node);
+ if (i == size)
+ return;
- tree v4sf_ftype_v4sf_v4sf_v16qi
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE,
- V16QI_type_node,
- endlink))));
- tree v4si_ftype_v4si_v4si_v16qi
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- tree_cons (NULL_TREE,
- V16QI_type_node,
- endlink))));
- tree v8hi_ftype_v8hi_v8hi_v16qi
- = build_function_type (V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE,
- V16QI_type_node,
- endlink))));
- tree v16qi_ftype_v16qi_v16qi_v16qi
- = build_function_type (V16QI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- tree_cons (NULL_TREE,
- V16QI_type_node,
- endlink))));
+ for (; i < size; ++i)
+ {
+ /* Flip all the bits on. */
+ desc[i].mask = target_flags;
+ if (desc[i].code == end)
+ break;
+ }
+}
- /* V4SI foo (char). */
- tree v4si_ftype_char
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, char_type_node, endlink));
+static void
+spe_init_builtins ()
+{
+ tree endlink = void_list_node;
+ tree puint_type_node = build_pointer_type (unsigned_type_node);
+ tree pushort_type_node = build_pointer_type (short_unsigned_type_node);
+ tree pv2si_type_node = build_pointer_type (V2SI_type_node);
+ struct builtin_description *d;
+ size_t i;
- /* V8HI foo (char). */
- tree v8hi_ftype_char
- = build_function_type (V8HI_type_node,
- tree_cons (NULL_TREE, char_type_node, endlink));
+ tree v2si_ftype_4_v2si
+ = build_function_type
+ (V2SI_type_node,
+ tree_cons (NULL_TREE, V2SI_type_node,
+ tree_cons (NULL_TREE, V2SI_type_node,
+ tree_cons (NULL_TREE, V2SI_type_node,
+ tree_cons (NULL_TREE, V2SI_type_node,
+ endlink)))));
+
+ tree v2sf_ftype_4_v2sf
+ = build_function_type
+ (V2SF_type_node,
+ tree_cons (NULL_TREE, V2SF_type_node,
+ tree_cons (NULL_TREE, V2SF_type_node,
+ tree_cons (NULL_TREE, V2SF_type_node,
+ tree_cons (NULL_TREE, V2SF_type_node,
+ endlink)))));
+
+ tree int_ftype_int_v2si_v2si
+ = build_function_type
+ (integer_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE, V2SI_type_node,
+ tree_cons (NULL_TREE, V2SI_type_node,
+ endlink))));
- /* V16QI foo (char). */
- tree v16qi_ftype_char
- = build_function_type (V16QI_type_node,
- tree_cons (NULL_TREE, char_type_node, endlink));
- /* V4SF foo (V4SF). */
- tree v4sf_ftype_v4sf
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node, endlink));
-
- /* V4SI foo (int *). */
- tree v4si_ftype_pint
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, pint_type_node, endlink));
- /* V8HI foo (short *). */
- tree v8hi_ftype_pshort
- = build_function_type (V8HI_type_node,
- tree_cons (NULL_TREE, pshort_type_node, endlink));
- /* V16QI foo (char *). */
- tree v16qi_ftype_pchar
- = build_function_type (V16QI_type_node,
- tree_cons (NULL_TREE, pchar_type_node, endlink));
- /* V4SF foo (float *). */
- tree v4sf_ftype_pfloat
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, pfloat_type_node, endlink));
-
- /* V8HI foo (V16QI). */
- tree v8hi_ftype_v16qi
- = build_function_type (V8HI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node, endlink));
+ tree int_ftype_int_v2sf_v2sf
+ = build_function_type
+ (integer_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE, V2SF_type_node,
+ tree_cons (NULL_TREE, V2SF_type_node,
+ endlink))));
- /* void foo (void *, int, char/literal). */
- tree void_ftype_pvoid_int_char
+ tree void_ftype_v2si_puint_int
= build_function_type (void_type_node,
- tree_cons (NULL_TREE, pvoid_type_node,
- tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE, V2SI_type_node,
+ tree_cons (NULL_TREE, puint_type_node,
tree_cons (NULL_TREE,
- char_type_node,
+ integer_type_node,
endlink))));
- /* void foo (int *, V4SI). */
- tree void_ftype_pint_v4si
+ tree void_ftype_v2si_puint_char
= build_function_type (void_type_node,
- tree_cons (NULL_TREE, pint_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- endlink)));
- /* void foo (short *, V8HI). */
- tree void_ftype_pshort_v8hi
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, pshort_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- endlink)));
- /* void foo (char *, V16QI). */
- tree void_ftype_pchar_v16qi
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, pchar_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- endlink)));
- /* void foo (float *, V4SF). */
- tree void_ftype_pfloat_v4sf
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, pfloat_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- endlink)));
-
- /* void foo (V4SI). */
- tree void_ftype_v4si
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- endlink));
-
- /* void foo (vint, int, void *). */
- tree void_ftype_v4si_int_pvoid
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE, V2SI_type_node,
+ tree_cons (NULL_TREE, puint_type_node,
tree_cons (NULL_TREE,
- pvoid_type_node,
+ char_type_node,
endlink))));
- /* void foo (vchar, int, void *). */
- tree void_ftype_v16qi_int_pvoid
+ tree void_ftype_v2si_pv2si_int
= build_function_type (void_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE, V2SI_type_node,
+ tree_cons (NULL_TREE, pv2si_type_node,
tree_cons (NULL_TREE,
- pvoid_type_node,
+ integer_type_node,
endlink))));
- /* void foo (vshort, int, void *). */
- tree void_ftype_v8hi_int_pvoid
+ tree void_ftype_v2si_pv2si_char
= build_function_type (void_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE, V2SI_type_node,
+ tree_cons (NULL_TREE, pv2si_type_node,
tree_cons (NULL_TREE,
- pvoid_type_node,
+ char_type_node,
endlink))));
- /* void foo (char). */
- tree void_ftype_qi
+ tree void_ftype_int
= build_function_type (void_type_node,
- tree_cons (NULL_TREE, char_type_node,
- endlink));
+ tree_cons (NULL_TREE, integer_type_node, endlink));
- /* void foo (void). */
- tree void_ftype_void
- = build_function_type (void_type_node, void_list_node);
-
- /* vshort foo (void). */
- tree v8hi_ftype_void
- = build_function_type (V8HI_type_node, void_list_node);
+ tree int_ftype_void
+ = build_function_type (integer_type_node,
+ tree_cons (NULL_TREE, void_type_node, endlink));
- tree v4si_ftype_v4si_v4si
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
+ tree v2si_ftype_pv2si_int
+ = build_function_type (V2SI_type_node,
+ tree_cons (NULL_TREE, pv2si_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
endlink)));
- /* These are for the unsigned 5 bit literals. */
-
- tree v4sf_ftype_v4si_char
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- tree_cons (NULL_TREE, char_type_node,
- endlink)));
- tree v4si_ftype_v4sf_char
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE, char_type_node,
- endlink)));
- tree v4si_ftype_v4si_char
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- tree_cons (NULL_TREE, char_type_node,
- endlink)));
- tree v8hi_ftype_v8hi_char
- = build_function_type (V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE, char_type_node,
+ tree v2si_ftype_puint_int
+ = build_function_type (V2SI_type_node,
+ tree_cons (NULL_TREE, puint_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
endlink)));
- tree v16qi_ftype_v16qi_char
- = build_function_type (V16QI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- tree_cons (NULL_TREE, char_type_node,
+
+ tree v2si_ftype_pushort_int
+ = build_function_type (V2SI_type_node,
+ tree_cons (NULL_TREE, pushort_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
endlink)));
- /* These are for the unsigned 4 bit literals. */
+ /* The initialization of the simple binary and unary builtins is
+ done in rs6000_common_init_builtins, but we have to enable the
+ mask bits here manually because we have run out of `target_flags'
+ bits. We really need to redesign this mask business. */
+
+ enable_mask_for_builtins ((struct builtin_description *) bdesc_2arg,
+ ARRAY_SIZE (bdesc_2arg),
+ SPE_BUILTIN_EVADDW,
+ SPE_BUILTIN_EVXOR);
+ enable_mask_for_builtins ((struct builtin_description *) bdesc_1arg,
+ ARRAY_SIZE (bdesc_1arg),
+ SPE_BUILTIN_EVABS,
+ SPE_BUILTIN_EVSUBFUSIAAW);
+ enable_mask_for_builtins ((struct builtin_description *) bdesc_spe_predicates,
+ ARRAY_SIZE (bdesc_spe_predicates),
+ SPE_BUILTIN_EVCMPEQ,
+ SPE_BUILTIN_EVFSTSTLT);
+ enable_mask_for_builtins ((struct builtin_description *) bdesc_spe_evsel,
+ ARRAY_SIZE (bdesc_spe_evsel),
+ SPE_BUILTIN_EVSEL_CMPGTS,
+ SPE_BUILTIN_EVSEL_FSTSTEQ);
+
+ /* Initialize irregular SPE builtins. */
+
+ def_builtin (target_flags, "__builtin_spe_mtspefscr", void_ftype_int, SPE_BUILTIN_MTSPEFSCR);
+ def_builtin (target_flags, "__builtin_spe_mfspefscr", int_ftype_void, SPE_BUILTIN_MFSPEFSCR);
+ def_builtin (target_flags, "__builtin_spe_evstddx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDDX);
+ def_builtin (target_flags, "__builtin_spe_evstdhx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDHX);
+ def_builtin (target_flags, "__builtin_spe_evstdwx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDWX);
+ def_builtin (target_flags, "__builtin_spe_evstwhex", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWHEX);
+ def_builtin (target_flags, "__builtin_spe_evstwhox", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWHOX);
+ def_builtin (target_flags, "__builtin_spe_evstwwex", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWWEX);
+ def_builtin (target_flags, "__builtin_spe_evstwwox", void_ftype_v2si_puint_int, SPE_BUILTIN_EVSTWWOX);
+ def_builtin (target_flags, "__builtin_spe_evstdd", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDD);
+ def_builtin (target_flags, "__builtin_spe_evstdh", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDH);
+ def_builtin (target_flags, "__builtin_spe_evstdw", void_ftype_v2si_pv2si_char, SPE_BUILTIN_EVSTDW);
+ def_builtin (target_flags, "__builtin_spe_evstwhe", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWHE);
+ def_builtin (target_flags, "__builtin_spe_evstwho", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWHO);
+ def_builtin (target_flags, "__builtin_spe_evstwwe", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWWE);
+ def_builtin (target_flags, "__builtin_spe_evstwwo", void_ftype_v2si_puint_char, SPE_BUILTIN_EVSTWWO);
+
+ /* Loads. */
+ def_builtin (target_flags, "__builtin_spe_evlddx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDDX);
+ def_builtin (target_flags, "__builtin_spe_evldwx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDWX);
+ def_builtin (target_flags, "__builtin_spe_evldhx", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDHX);
+ def_builtin (target_flags, "__builtin_spe_evlwhex", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHEX);
+ def_builtin (target_flags, "__builtin_spe_evlwhoux", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOUX);
+ def_builtin (target_flags, "__builtin_spe_evlwhosx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOSX);
+ def_builtin (target_flags, "__builtin_spe_evlwwsplatx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWWSPLATX);
+ def_builtin (target_flags, "__builtin_spe_evlwhsplatx", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHSPLATX);
+ def_builtin (target_flags, "__builtin_spe_evlhhesplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHESPLATX);
+ def_builtin (target_flags, "__builtin_spe_evlhhousplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOUSPLATX);
+ def_builtin (target_flags, "__builtin_spe_evlhhossplatx", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOSSPLATX);
+ def_builtin (target_flags, "__builtin_spe_evldd", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDD);
+ def_builtin (target_flags, "__builtin_spe_evldw", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDW);
+ def_builtin (target_flags, "__builtin_spe_evldh", v2si_ftype_pv2si_int, SPE_BUILTIN_EVLDH);
+ def_builtin (target_flags, "__builtin_spe_evlhhesplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHESPLAT);
+ def_builtin (target_flags, "__builtin_spe_evlhhossplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOSSPLAT);
+ def_builtin (target_flags, "__builtin_spe_evlhhousplat", v2si_ftype_pushort_int, SPE_BUILTIN_EVLHHOUSPLAT);
+ def_builtin (target_flags, "__builtin_spe_evlwhe", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHE);
+ def_builtin (target_flags, "__builtin_spe_evlwhos", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOS);
+ def_builtin (target_flags, "__builtin_spe_evlwhou", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHOU);
+ def_builtin (target_flags, "__builtin_spe_evlwhsplat", v2si_ftype_puint_int, SPE_BUILTIN_EVLWHSPLAT);
+ def_builtin (target_flags, "__builtin_spe_evlwwsplat", v2si_ftype_puint_int, SPE_BUILTIN_EVLWWSPLAT);
+
+ /* Predicates. */
+ d = (struct builtin_description *) bdesc_spe_predicates;
+ for (i = 0; i < ARRAY_SIZE (bdesc_spe_predicates); ++i, d++)
+ {
+ tree type;
- tree v16qi_ftype_v16qi_v16qi_char
- = build_function_type (V16QI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- tree_cons (NULL_TREE,
- char_type_node,
- endlink))));
+ switch (insn_data[d->icode].operand[1].mode)
+ {
+ case V2SImode:
+ type = int_ftype_int_v2si_v2si;
+ break;
+ case V2SFmode:
+ type = int_ftype_int_v2sf_v2sf;
+ break;
+ default:
+ abort ();
+ }
- tree v8hi_ftype_v8hi_v8hi_char
- = build_function_type (V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE,
- char_type_node,
- endlink))));
+ def_builtin (d->mask, d->name, type, d->code);
+ }
- tree v4si_ftype_v4si_v4si_char
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- tree_cons (NULL_TREE,
- char_type_node,
- endlink))));
+ /* Evsel predicates. */
+ d = (struct builtin_description *) bdesc_spe_evsel;
+ for (i = 0; i < ARRAY_SIZE (bdesc_spe_evsel); ++i, d++)
+ {
+ tree type;
- tree v4sf_ftype_v4sf_v4sf_char
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE,
- char_type_node,
- endlink))));
+ switch (insn_data[d->icode].operand[1].mode)
+ {
+ case V2SImode:
+ type = v2si_ftype_4_v2si;
+ break;
+ case V2SFmode:
+ type = v2sf_ftype_4_v2sf;
+ break;
+ default:
+ abort ();
+ }
- /* End of 4 bit literals. */
+ def_builtin (d->mask, d->name, type, d->code);
+ }
+}
- tree v4sf_ftype_v4sf_v4sf
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- endlink)));
- tree v4sf_ftype_v4sf_v4sf_v4si
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE,
- V4SI_type_node,
- endlink))));
- tree v4sf_ftype_v4sf_v4sf_v4sf
- = build_function_type (V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE,
- V4SF_type_node,
- endlink))));
- tree v4si_ftype_v4si_v4si_v4si
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- tree_cons (NULL_TREE,
- V4SI_type_node,
- endlink))));
+static void
+altivec_init_builtins ()
+{
+ struct builtin_description *d;
+ struct builtin_description_predicates *dp;
+ size_t i;
+ tree pfloat_type_node = build_pointer_type (float_type_node);
+ tree pint_type_node = build_pointer_type (integer_type_node);
+ tree pshort_type_node = build_pointer_type (short_integer_type_node);
+ tree pchar_type_node = build_pointer_type (char_type_node);
- tree v8hi_ftype_v8hi_v8hi
- = build_function_type (V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- endlink)));
- tree v8hi_ftype_v8hi_v8hi_v8hi
- = build_function_type (V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE,
- V8HI_type_node,
- endlink))));
- tree v4si_ftype_v8hi_v8hi_v4si
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE,
- V4SI_type_node,
- endlink))));
- tree v4si_ftype_v16qi_v16qi_v4si
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- tree_cons (NULL_TREE,
- V4SI_type_node,
- endlink))));
-
- tree v16qi_ftype_v16qi_v16qi
- = build_function_type (V16QI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- endlink)));
-
- tree v4si_ftype_v4sf_v4sf
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- endlink)));
+ tree pvoid_type_node = build_pointer_type (void_type_node);
- tree v4si_ftype_v4si
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node, endlink));
+ tree pcfloat_type_node = build_pointer_type (build_qualified_type (float_type_node, TYPE_QUAL_CONST));
+ tree pcint_type_node = build_pointer_type (build_qualified_type (integer_type_node, TYPE_QUAL_CONST));
+ tree pcshort_type_node = build_pointer_type (build_qualified_type (short_integer_type_node, TYPE_QUAL_CONST));
+ tree pcchar_type_node = build_pointer_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST));
- tree v8hi_ftype_v8hi
- = build_function_type (V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node, endlink));
+ tree pcvoid_type_node = build_pointer_type (build_qualified_type (void_type_node, TYPE_QUAL_CONST));
+
+ tree int_ftype_int_v4si_v4si
+ = build_function_type_list (integer_type_node,
+ integer_type_node, V4SI_type_node,
+ V4SI_type_node, NULL_TREE);
+ tree v4sf_ftype_pcfloat
+ = build_function_type_list (V4SF_type_node, pcfloat_type_node, NULL_TREE);
+ tree void_ftype_pfloat_v4sf
+ = build_function_type_list (void_type_node,
+ pfloat_type_node, V4SF_type_node, NULL_TREE);
+ tree v4si_ftype_pcint
+ = build_function_type_list (V4SI_type_node, pcint_type_node, NULL_TREE);
+ tree void_ftype_pint_v4si
+ = build_function_type_list (void_type_node,
+ pint_type_node, V4SI_type_node, NULL_TREE);
+ tree v8hi_ftype_pcshort
+ = build_function_type_list (V8HI_type_node, pcshort_type_node, NULL_TREE);
+ tree void_ftype_pshort_v8hi
+ = build_function_type_list (void_type_node,
+ pshort_type_node, V8HI_type_node, NULL_TREE);
+ tree v16qi_ftype_pcchar
+ = build_function_type_list (V16QI_type_node, pcchar_type_node, NULL_TREE);
+ tree void_ftype_pchar_v16qi
+ = build_function_type_list (void_type_node,
+ pchar_type_node, V16QI_type_node, NULL_TREE);
+ tree void_ftype_v4si
+ = build_function_type_list (void_type_node, V4SI_type_node, NULL_TREE);
+ tree v8hi_ftype_void
+ = build_function_type (V8HI_type_node, void_list_node);
+ tree void_ftype_void
+ = build_function_type (void_type_node, void_list_node);
+ tree void_ftype_qi
+ = build_function_type_list (void_type_node, char_type_node, NULL_TREE);
+
+ tree v16qi_ftype_int_pcvoid
+ = build_function_type_list (V16QI_type_node,
+ integer_type_node, pcvoid_type_node, NULL_TREE);
+ tree v8hi_ftype_int_pcvoid
+ = build_function_type_list (V8HI_type_node,
+ integer_type_node, pcvoid_type_node, NULL_TREE);
+ tree v4si_ftype_int_pcvoid
+ = build_function_type_list (V4SI_type_node,
+ integer_type_node, pcvoid_type_node, NULL_TREE);
+ tree void_ftype_v4si_int_pvoid
+ = build_function_type_list (void_type_node,
+ V4SI_type_node, integer_type_node,
+ pvoid_type_node, NULL_TREE);
+ tree void_ftype_v16qi_int_pvoid
+ = build_function_type_list (void_type_node,
+ V16QI_type_node, integer_type_node,
+ pvoid_type_node, NULL_TREE);
+ tree void_ftype_v8hi_int_pvoid
+ = build_function_type_list (void_type_node,
+ V8HI_type_node, integer_type_node,
+ pvoid_type_node, NULL_TREE);
+ tree int_ftype_int_v8hi_v8hi
+ = build_function_type_list (integer_type_node,
+ integer_type_node, V8HI_type_node,
+ V8HI_type_node, NULL_TREE);
+ tree int_ftype_int_v16qi_v16qi
+ = build_function_type_list (integer_type_node,
+ integer_type_node, V16QI_type_node,
+ V16QI_type_node, NULL_TREE);
+ tree int_ftype_int_v4sf_v4sf
+ = build_function_type_list (integer_type_node,
+ integer_type_node, V4SF_type_node,
+ V4SF_type_node, NULL_TREE);
+ tree v4si_ftype_v4si
+ = build_function_type_list (V4SI_type_node, V4SI_type_node, NULL_TREE);
+ tree v8hi_ftype_v8hi
+ = build_function_type_list (V8HI_type_node, V8HI_type_node, NULL_TREE);
tree v16qi_ftype_v16qi
- = build_function_type (V16QI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node, endlink));
+ = build_function_type_list (V16QI_type_node, V16QI_type_node, NULL_TREE);
+ tree v4sf_ftype_v4sf
+ = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE);
+ tree void_ftype_pcvoid_int_char
+ = build_function_type_list (void_type_node,
+ pcvoid_type_node, integer_type_node,
+ char_type_node, NULL_TREE);
+
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_4sf", v4sf_ftype_pcfloat,
+ ALTIVEC_BUILTIN_LD_INTERNAL_4sf);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_4sf", void_ftype_pfloat_v4sf,
+ ALTIVEC_BUILTIN_ST_INTERNAL_4sf);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_4si", v4si_ftype_pcint,
+ ALTIVEC_BUILTIN_LD_INTERNAL_4si);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_4si", void_ftype_pint_v4si,
+ ALTIVEC_BUILTIN_ST_INTERNAL_4si);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_8hi", v8hi_ftype_pcshort,
+ ALTIVEC_BUILTIN_LD_INTERNAL_8hi);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_8hi", void_ftype_pshort_v8hi,
+ ALTIVEC_BUILTIN_ST_INTERNAL_8hi);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_16qi", v16qi_ftype_pcchar,
+ ALTIVEC_BUILTIN_LD_INTERNAL_16qi);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_16qi", void_ftype_pchar_v16qi,
+ ALTIVEC_BUILTIN_ST_INTERNAL_16qi);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_mtvscr", void_ftype_v4si, ALTIVEC_BUILTIN_MTVSCR);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_mfvscr", v8hi_ftype_void, ALTIVEC_BUILTIN_MFVSCR);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_dssall", void_ftype_void, ALTIVEC_BUILTIN_DSSALL);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_dss", void_ftype_qi, ALTIVEC_BUILTIN_DSS);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvsl", v16qi_ftype_int_pcvoid, ALTIVEC_BUILTIN_LVSL);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvsr", v16qi_ftype_int_pcvoid, ALTIVEC_BUILTIN_LVSR);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvebx", v16qi_ftype_int_pcvoid, ALTIVEC_BUILTIN_LVEBX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvehx", v8hi_ftype_int_pcvoid, ALTIVEC_BUILTIN_LVEHX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvewx", v4si_ftype_int_pcvoid, ALTIVEC_BUILTIN_LVEWX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvxl", v4si_ftype_int_pcvoid, ALTIVEC_BUILTIN_LVXL);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvx", v4si_ftype_int_pcvoid, ALTIVEC_BUILTIN_LVX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvx", void_ftype_v4si_int_pvoid, ALTIVEC_BUILTIN_STVX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvewx", void_ftype_v4si_int_pvoid, ALTIVEC_BUILTIN_STVEWX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvxl", void_ftype_v4si_int_pvoid, ALTIVEC_BUILTIN_STVXL);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvebx", void_ftype_v16qi_int_pvoid, ALTIVEC_BUILTIN_STVEBX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvehx", void_ftype_v8hi_int_pvoid, ALTIVEC_BUILTIN_STVEHX);
- tree v8hi_ftype_v16qi_v16qi
- = build_function_type (V8HI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- endlink)));
+ /* Add the DST variants. */
+ d = (struct builtin_description *) bdesc_dst;
+ for (i = 0; i < ARRAY_SIZE (bdesc_dst); i++, d++)
+ def_builtin (d->mask, d->name, void_ftype_pcvoid_int_char, d->code);
- tree v4si_ftype_v8hi_v8hi
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- endlink)));
+ /* Initialize the predicates. */
+ dp = (struct builtin_description_predicates *) bdesc_altivec_preds;
+ for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, dp++)
+ {
+ enum machine_mode mode1;
+ tree type;
- tree v8hi_ftype_v4si_v4si
- = build_function_type (V8HI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- endlink)));
+ mode1 = insn_data[dp->icode].operand[1].mode;
- tree v16qi_ftype_v8hi_v8hi
- = build_function_type (V16QI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- endlink)));
+ switch (mode1)
+ {
+ case V4SImode:
+ type = int_ftype_int_v4si_v4si;
+ break;
+ case V8HImode:
+ type = int_ftype_int_v8hi_v8hi;
+ break;
+ case V16QImode:
+ type = int_ftype_int_v16qi_v16qi;
+ break;
+ case V4SFmode:
+ type = int_ftype_int_v4sf_v4sf;
+ break;
+ default:
+ abort ();
+ }
+
+ def_builtin (dp->mask, dp->name, type, dp->code);
+ }
- tree v4si_ftype_v16qi_v4si
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- endlink)));
+ /* Initialize the abs* operators. */
+ d = (struct builtin_description *) bdesc_abs;
+ for (i = 0; i < ARRAY_SIZE (bdesc_abs); i++, d++)
+ {
+ enum machine_mode mode0;
+ tree type;
- tree v4si_ftype_v16qi_v16qi
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- endlink)));
+ mode0 = insn_data[d->icode].operand[0].mode;
- tree v4si_ftype_v8hi_v4si
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- endlink)));
+ switch (mode0)
+ {
+ case V4SImode:
+ type = v4si_ftype_v4si;
+ break;
+ case V8HImode:
+ type = v8hi_ftype_v8hi;
+ break;
+ case V16QImode:
+ type = v16qi_ftype_v16qi;
+ break;
+ case V4SFmode:
+ type = v4sf_ftype_v4sf;
+ break;
+ default:
+ abort ();
+ }
+
+ def_builtin (d->mask, d->name, type, d->code);
+ }
+}
- tree v4si_ftype_v8hi
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node, endlink));
+static void
+rs6000_common_init_builtins ()
+{
+ struct builtin_description *d;
+ size_t i;
- tree int_ftype_v4si_v4si
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- endlink)));
+ tree v4sf_ftype_v4sf_v4sf_v16qi
+ = build_function_type_list (V4SF_type_node,
+ V4SF_type_node, V4SF_type_node,
+ V16QI_type_node, NULL_TREE);
+ tree v4si_ftype_v4si_v4si_v16qi
+ = build_function_type_list (V4SI_type_node,
+ V4SI_type_node, V4SI_type_node,
+ V16QI_type_node, NULL_TREE);
+ tree v8hi_ftype_v8hi_v8hi_v16qi
+ = build_function_type_list (V8HI_type_node,
+ V8HI_type_node, V8HI_type_node,
+ V16QI_type_node, NULL_TREE);
+ tree v16qi_ftype_v16qi_v16qi_v16qi
+ = build_function_type_list (V16QI_type_node,
+ V16QI_type_node, V16QI_type_node,
+ V16QI_type_node, NULL_TREE);
+ tree v4si_ftype_char
+ = build_function_type_list (V4SI_type_node, char_type_node, NULL_TREE);
+ tree v8hi_ftype_char
+ = build_function_type_list (V8HI_type_node, char_type_node, NULL_TREE);
+ tree v16qi_ftype_char
+ = build_function_type_list (V16QI_type_node, char_type_node, NULL_TREE);
+ tree v8hi_ftype_v16qi
+ = build_function_type_list (V8HI_type_node, V16QI_type_node, NULL_TREE);
+ tree v4sf_ftype_v4sf
+ = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE);
- tree int_ftype_v4sf_v4sf
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- endlink)));
+ tree v2si_ftype_v2si_v2si
+ = build_function_type_list (V2SI_type_node,
+ V2SI_type_node, V2SI_type_node, NULL_TREE);
- tree int_ftype_v16qi_v16qi
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- endlink)));
+ tree v2sf_ftype_v2sf_v2sf
+ = build_function_type_list (V2SF_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
- tree int_ftype_int_v4si_v4si
- = build_function_type
- (integer_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- tree_cons (NULL_TREE, V4SI_type_node,
- endlink))));
+ tree v2si_ftype_int_int
+ = build_function_type_list (V2SI_type_node,
+ integer_type_node, integer_type_node,
+ NULL_TREE);
- tree int_ftype_int_v4sf_v4sf
- = build_function_type
- (integer_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- tree_cons (NULL_TREE, V4SF_type_node,
- endlink))));
+ tree v2si_ftype_v2si
+ = build_function_type_list (V2SI_type_node, V2SI_type_node, NULL_TREE);
- tree int_ftype_int_v8hi_v8hi
- = build_function_type
- (integer_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- endlink))));
+ tree v2sf_ftype_v2sf
+ = build_function_type_list (V2SF_type_node,
+ V2SF_type_node, NULL_TREE);
+
+ tree v2sf_ftype_v2si
+ = build_function_type_list (V2SF_type_node,
+ V2SI_type_node, NULL_TREE);
- tree int_ftype_int_v16qi_v16qi
- = build_function_type
- (integer_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- tree_cons (NULL_TREE, V16QI_type_node,
- endlink))));
+ tree v2si_ftype_v2sf
+ = build_function_type_list (V2SI_type_node,
+ V2SF_type_node, NULL_TREE);
- tree v16qi_ftype_int_pvoid
- = build_function_type (V16QI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE, pvoid_type_node,
- endlink)));
+ tree v2si_ftype_v2si_char
+ = build_function_type_list (V2SI_type_node,
+ V2SI_type_node, char_type_node, NULL_TREE);
- tree v4si_ftype_int_pvoid
- = build_function_type (V4SI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE, pvoid_type_node,
- endlink)));
+ tree v2si_ftype_int_char
+ = build_function_type_list (V2SI_type_node,
+ integer_type_node, char_type_node, NULL_TREE);
- tree v8hi_ftype_int_pvoid
- = build_function_type (V8HI_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE, pvoid_type_node,
- endlink)));
+ tree v2si_ftype_char
+ = build_function_type_list (V2SI_type_node, char_type_node, NULL_TREE);
- tree int_ftype_v8hi_v8hi
- = build_function_type (integer_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- tree_cons (NULL_TREE, V8HI_type_node,
- endlink)));
+ tree int_ftype_int_int
+ = build_function_type_list (integer_type_node,
+ integer_type_node, integer_type_node,
+ NULL_TREE);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_4sf", v4sf_ftype_pfloat, ALTIVEC_BUILTIN_LD_INTERNAL_4sf);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_4sf", void_ftype_pfloat_v4sf, ALTIVEC_BUILTIN_ST_INTERNAL_4sf);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_4si", v4si_ftype_pint, ALTIVEC_BUILTIN_LD_INTERNAL_4si);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_4si", void_ftype_pint_v4si, ALTIVEC_BUILTIN_ST_INTERNAL_4si);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_8hi", v8hi_ftype_pshort, ALTIVEC_BUILTIN_LD_INTERNAL_8hi);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_8hi", void_ftype_pshort_v8hi, ALTIVEC_BUILTIN_ST_INTERNAL_8hi);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_16qi", v16qi_ftype_pchar, ALTIVEC_BUILTIN_LD_INTERNAL_16qi);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_16qi", void_ftype_pchar_v16qi, ALTIVEC_BUILTIN_ST_INTERNAL_16qi);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_mtvscr", void_ftype_v4si, ALTIVEC_BUILTIN_MTVSCR);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_mfvscr", v8hi_ftype_void, ALTIVEC_BUILTIN_MFVSCR);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_dssall", void_ftype_void, ALTIVEC_BUILTIN_DSSALL);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_dss", void_ftype_qi, ALTIVEC_BUILTIN_DSS);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvsl", v16qi_ftype_int_pvoid, ALTIVEC_BUILTIN_LVSL);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvsr", v16qi_ftype_int_pvoid, ALTIVEC_BUILTIN_LVSR);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvebx", v16qi_ftype_int_pvoid, ALTIVEC_BUILTIN_LVEBX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvehx", v8hi_ftype_int_pvoid, ALTIVEC_BUILTIN_LVEHX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvewx", v4si_ftype_int_pvoid, ALTIVEC_BUILTIN_LVEWX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvxl", v4si_ftype_int_pvoid, ALTIVEC_BUILTIN_LVXL);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvx", v4si_ftype_int_pvoid, ALTIVEC_BUILTIN_LVX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvx", void_ftype_v4si_int_pvoid, ALTIVEC_BUILTIN_STVX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvebx", void_ftype_v16qi_int_pvoid, ALTIVEC_BUILTIN_STVEBX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvehx", void_ftype_v8hi_int_pvoid, ALTIVEC_BUILTIN_STVEHX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvewx", void_ftype_v4si_int_pvoid, ALTIVEC_BUILTIN_STVEWX);
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvxl", void_ftype_v4si_int_pvoid, ALTIVEC_BUILTIN_STVXL);
+ tree v4si_ftype_v4si_v4si
+ = build_function_type_list (V4SI_type_node,
+ V4SI_type_node, V4SI_type_node, NULL_TREE);
+ tree v4sf_ftype_v4si_char
+ = build_function_type_list (V4SF_type_node,
+ V4SI_type_node, char_type_node, NULL_TREE);
+ tree v4si_ftype_v4sf_char
+ = build_function_type_list (V4SI_type_node,
+ V4SF_type_node, char_type_node, NULL_TREE);
+ tree v4si_ftype_v4si_char
+ = build_function_type_list (V4SI_type_node,
+ V4SI_type_node, char_type_node, NULL_TREE);
+ tree v8hi_ftype_v8hi_char
+ = build_function_type_list (V8HI_type_node,
+ V8HI_type_node, char_type_node, NULL_TREE);
+ tree v16qi_ftype_v16qi_char
+ = build_function_type_list (V16QI_type_node,
+ V16QI_type_node, char_type_node, NULL_TREE);
+ tree v16qi_ftype_v16qi_v16qi_char
+ = build_function_type_list (V16QI_type_node,
+ V16QI_type_node, V16QI_type_node,
+ char_type_node, NULL_TREE);
+ tree v8hi_ftype_v8hi_v8hi_char
+ = build_function_type_list (V8HI_type_node,
+ V8HI_type_node, V8HI_type_node,
+ char_type_node, NULL_TREE);
+ tree v4si_ftype_v4si_v4si_char
+ = build_function_type_list (V4SI_type_node,
+ V4SI_type_node, V4SI_type_node,
+ char_type_node, NULL_TREE);
+ tree v4sf_ftype_v4sf_v4sf_char
+ = build_function_type_list (V4SF_type_node,
+ V4SF_type_node, V4SF_type_node,
+ char_type_node, NULL_TREE);
+ tree v4sf_ftype_v4sf_v4sf
+ = build_function_type_list (V4SF_type_node,
+ V4SF_type_node, V4SF_type_node, NULL_TREE);
+ tree v4sf_ftype_v4sf_v4sf_v4si
+ = build_function_type_list (V4SF_type_node,
+ V4SF_type_node, V4SF_type_node,
+ V4SI_type_node, NULL_TREE);
+ tree v4sf_ftype_v4sf_v4sf_v4sf
+ = build_function_type_list (V4SF_type_node,
+ V4SF_type_node, V4SF_type_node,
+ V4SF_type_node, NULL_TREE);
+ tree v4si_ftype_v4si_v4si_v4si
+ = build_function_type_list (V4SI_type_node,
+ V4SI_type_node, V4SI_type_node,
+ V4SI_type_node, NULL_TREE);
+ tree v8hi_ftype_v8hi_v8hi
+ = build_function_type_list (V8HI_type_node,
+ V8HI_type_node, V8HI_type_node, NULL_TREE);
+ tree v8hi_ftype_v8hi_v8hi_v8hi
+ = build_function_type_list (V8HI_type_node,
+ V8HI_type_node, V8HI_type_node,
+ V8HI_type_node, NULL_TREE);
+ tree v4si_ftype_v8hi_v8hi_v4si
+ = build_function_type_list (V4SI_type_node,
+ V8HI_type_node, V8HI_type_node,
+ V4SI_type_node, NULL_TREE);
+ tree v4si_ftype_v16qi_v16qi_v4si
+ = build_function_type_list (V4SI_type_node,
+ V16QI_type_node, V16QI_type_node,
+ V4SI_type_node, NULL_TREE);
+ tree v16qi_ftype_v16qi_v16qi
+ = build_function_type_list (V16QI_type_node,
+ V16QI_type_node, V16QI_type_node, NULL_TREE);
+ tree v4si_ftype_v4sf_v4sf
+ = build_function_type_list (V4SI_type_node,
+ V4SF_type_node, V4SF_type_node, NULL_TREE);
+ tree v8hi_ftype_v16qi_v16qi
+ = build_function_type_list (V8HI_type_node,
+ V16QI_type_node, V16QI_type_node, NULL_TREE);
+ tree v4si_ftype_v8hi_v8hi
+ = build_function_type_list (V4SI_type_node,
+ V8HI_type_node, V8HI_type_node, NULL_TREE);
+ tree v8hi_ftype_v4si_v4si
+ = build_function_type_list (V8HI_type_node,
+ V4SI_type_node, V4SI_type_node, NULL_TREE);
+ tree v16qi_ftype_v8hi_v8hi
+ = build_function_type_list (V16QI_type_node,
+ V8HI_type_node, V8HI_type_node, NULL_TREE);
+ tree v4si_ftype_v16qi_v4si
+ = build_function_type_list (V4SI_type_node,
+ V16QI_type_node, V4SI_type_node, NULL_TREE);
+ tree v4si_ftype_v16qi_v16qi
+ = build_function_type_list (V4SI_type_node,
+ V16QI_type_node, V16QI_type_node, NULL_TREE);
+ tree v4si_ftype_v8hi_v4si
+ = build_function_type_list (V4SI_type_node,
+ V8HI_type_node, V4SI_type_node, NULL_TREE);
+ tree v4si_ftype_v8hi
+ = build_function_type_list (V4SI_type_node, V8HI_type_node, NULL_TREE);
+ tree int_ftype_v4si_v4si
+ = build_function_type_list (integer_type_node,
+ V4SI_type_node, V4SI_type_node, NULL_TREE);
+ tree int_ftype_v4sf_v4sf
+ = build_function_type_list (integer_type_node,
+ V4SF_type_node, V4SF_type_node, NULL_TREE);
+ tree int_ftype_v16qi_v16qi
+ = build_function_type_list (integer_type_node,
+ V16QI_type_node, V16QI_type_node, NULL_TREE);
+ tree int_ftype_v8hi_v8hi
+ = build_function_type_list (integer_type_node,
+ V8HI_type_node, V8HI_type_node, NULL_TREE);
/* Add the simple ternary operators. */
d = (struct builtin_description *) bdesc_3arg;
- for (i = 0; i < sizeof (bdesc_3arg) / sizeof *d; i++, d++)
+ for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
{
enum machine_mode mode0, mode1, mode2, mode3;
tree type;
- if (d->name == 0)
+ if (d->name == 0 || d->icode == CODE_FOR_nothing)
continue;
mode0 = insn_data[d->icode].operand[0].mode;
@@ -4694,49 +5944,14 @@ altivec_init_builtins (void)
def_builtin (d->mask, d->name, type, d->code);
}
- /* Add the DST variants. */
- d = (struct builtin_description *) bdesc_dst;
- for (i = 0; i < sizeof (bdesc_dst) / sizeof *d; i++, d++)
- def_builtin (d->mask, d->name, void_ftype_pvoid_int_char, d->code);
-
- /* Initialize the predicates. */
- dp = (struct builtin_description_predicates *) bdesc_altivec_preds;
- for (i = 0; i < sizeof (bdesc_altivec_preds) / sizeof *dp; i++, dp++)
- {
- enum machine_mode mode1;
- tree type;
-
- mode1 = insn_data[dp->icode].operand[1].mode;
-
- switch (mode1)
- {
- case V4SImode:
- type = int_ftype_int_v4si_v4si;
- break;
- case V8HImode:
- type = int_ftype_int_v8hi_v8hi;
- break;
- case V16QImode:
- type = int_ftype_int_v16qi_v16qi;
- break;
- case V4SFmode:
- type = int_ftype_int_v4sf_v4sf;
- break;
- default:
- abort ();
- }
-
- def_builtin (dp->mask, dp->name, type, dp->code);
- }
-
/* Add the simple binary operators. */
d = (struct builtin_description *) bdesc_2arg;
- for (i = 0; i < sizeof (bdesc_2arg) / sizeof *d; i++, d++)
+ for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
{
enum machine_mode mode0, mode1, mode2;
tree type;
- if (d->name == 0)
+ if (d->name == 0 || d->icode == CODE_FOR_nothing)
continue;
mode0 = insn_data[d->icode].operand[0].mode;
@@ -4760,6 +5975,15 @@ altivec_init_builtins (void)
case V8HImode:
type = v8hi_ftype_v8hi_v8hi;
break;
+ case V2SImode:
+ type = v2si_ftype_v2si_v2si;
+ break;
+ case V2SFmode:
+ type = v2sf_ftype_v2sf_v2sf;
+ break;
+ case SImode:
+ type = int_ftype_int_int;
+ break;
default:
abort ();
}
@@ -4819,6 +6043,15 @@ altivec_init_builtins (void)
else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == QImode)
type = v4si_ftype_v4sf_char;
+ else if (mode0 == V2SImode && mode1 == SImode && mode2 == SImode)
+ type = v2si_ftype_int_int;
+
+ else if (mode0 == V2SImode && mode1 == V2SImode && mode2 == QImode)
+ type = v2si_ftype_v2si_char;
+
+ else if (mode0 == V2SImode && mode1 == SImode && mode2 == QImode)
+ type = v2si_ftype_int_char;
+
/* int, x, x. */
else if (mode0 == SImode)
{
@@ -4847,44 +6080,14 @@ altivec_init_builtins (void)
def_builtin (d->mask, d->name, type, d->code);
}
- /* Initialize the abs* operators. */
- d = (struct builtin_description *) bdesc_abs;
- for (i = 0; i < sizeof (bdesc_abs) / sizeof *d; i++, d++)
- {
- enum machine_mode mode0;
- tree type;
-
- mode0 = insn_data[d->icode].operand[0].mode;
-
- switch (mode0)
- {
- case V4SImode:
- type = v4si_ftype_v4si;
- break;
- case V8HImode:
- type = v8hi_ftype_v8hi;
- break;
- case V16QImode:
- type = v16qi_ftype_v16qi;
- break;
- case V4SFmode:
- type = v4sf_ftype_v4sf;
- break;
- default:
- abort ();
- }
-
- def_builtin (d->mask, d->name, type, d->code);
- }
-
/* Add the simple unary operators. */
d = (struct builtin_description *) bdesc_1arg;
- for (i = 0; i < sizeof (bdesc_1arg) / sizeof *d; i++, d++)
+ for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
{
enum machine_mode mode0, mode1;
tree type;
- if (d->name == 0)
+ if (d->name == 0 || d->icode == CODE_FOR_nothing)
continue;
mode0 = insn_data[d->icode].operand[0].mode;
@@ -4902,6 +6105,16 @@ altivec_init_builtins (void)
type = v8hi_ftype_v16qi;
else if (mode0 == V4SImode && mode1 == V8HImode)
type = v4si_ftype_v8hi;
+ else if (mode0 == V2SImode && mode1 == V2SImode)
+ type = v2si_ftype_v2si;
+ else if (mode0 == V2SFmode && mode1 == V2SFmode)
+ type = v2sf_ftype_v2sf;
+ else if (mode0 == V2SFmode && mode1 == V2SImode)
+ type = v2sf_ftype_v2si;
+ else if (mode0 == V2SImode && mode1 == V2SFmode)
+ type = v2si_ftype_v2sf;
+ else if (mode0 == V2SImode && mode1 == QImode)
+ type = v2si_ftype_char;
else
abort ();
@@ -5550,9 +6763,10 @@ validate_condition_mode (code, mode)
abort ();
/* These should never be generated except for
- flag_unsafe_math_optimizations. */
+ flag_unsafe_math_optimizations and flag_finite_math_only. */
if (mode == CCFPmode
&& ! flag_unsafe_math_optimizations
+ && ! flag_finite_math_only
&& (code == LE || code == GE
|| code == UNEQ || code == LTGT
|| code == UNGT || code == UNLT))
@@ -5603,6 +6817,7 @@ branch_positive_comparison_operator (op, mode)
code = GET_CODE (op);
return (code == EQ || code == LT || code == GT
+ || (TARGET_SPE && TARGET_HARD_FLOAT && !TARGET_FPRS && code == NE)
|| code == LTU || code == GTU
|| code == UNORDERED);
}
@@ -6054,8 +7269,12 @@ ccr_bit (op, scc_p)
switch (code)
{
case NE:
+ if (TARGET_SPE && TARGET_HARD_FLOAT && cc_mode == CCFPmode)
+ return base_bit + 1;
return scc_p ? base_bit + 3 : base_bit + 2;
case EQ:
+ if (TARGET_SPE && TARGET_HARD_FLOAT && cc_mode == CCFPmode)
+ return base_bit + 1;
return base_bit + 2;
case GT: case GTU: case UNLE:
return base_bit + 1;
@@ -6095,29 +7314,93 @@ rs6000_got_register (value)
return pic_offset_table_rtx;
}
-/* Functions to init, mark and free struct machine_function.
- These will be called, via pointer variables,
- from push_function_context and pop_function_context. */
+/* Function to init struct machine_function.
+ This will be called, via a pointer variable,
+ from push_function_context. */
-static void
-rs6000_init_machine_status (p)
- struct function *p;
+static struct machine_function *
+rs6000_init_machine_status ()
{
- p->machine = (machine_function *) xcalloc (1, sizeof (machine_function));
+ return ggc_alloc_cleared (sizeof (machine_function));
}
+
+/* These macros test for integers and extract the low-order bits. */
+#define INT_P(X) \
+((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE) \
+ && GET_MODE (X) == VOIDmode)
-static void
-rs6000_free_machine_status (p)
- struct function *p;
+#define INT_LOWPART(X) \
+ (GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X))
+
+int
+extract_MB (op)
+ rtx op;
{
- if (p->machine == NULL)
- return;
+ int i;
+ unsigned long val = INT_LOWPART (op);
+
+ /* If the high bit is zero, the value is the first 1 bit we find
+ from the left. */
+ if ((val & 0x80000000) == 0)
+ {
+ if ((val & 0xffffffff) == 0)
+ abort ();
- free (p->machine);
- p->machine = NULL;
+ i = 1;
+ while (((val <<= 1) & 0x80000000) == 0)
+ ++i;
+ return i;
+ }
+
+ /* If the high bit is set and the low bit is not, or the mask is all
+ 1's, the value is zero. */
+ if ((val & 1) == 0 || (val & 0xffffffff) == 0xffffffff)
+ return 0;
+
+ /* Otherwise we have a wrap-around mask. Look for the first 0 bit
+ from the right. */
+ i = 31;
+ while (((val >>= 1) & 1) != 0)
+ --i;
+
+ return i;
+}
+
+int
+extract_ME (op)
+ rtx op;
+{
+ int i;
+ unsigned long val = INT_LOWPART (op);
+
+ /* If the low bit is zero, the value is the first 1 bit we find from
+ the right. */
+ if ((val & 1) == 0)
+ {
+ if ((val & 0xffffffff) == 0)
+ abort ();
+
+ i = 30;
+ while (((val >>= 1) & 1) == 0)
+ --i;
+
+ return i;
+ }
+
+ /* If the low bit is set and the high bit is not, or the mask is all
+ 1's, the value is 31. */
+ if ((val & 0x80000000) == 0 || (val & 0xffffffff) == 0xffffffff)
+ return 31;
+
+ /* Otherwise we have a wrap-around mask. Look for the first 0 bit
+ from the left. */
+ i = 0;
+ while (((val <<= 1) & 0x80000000) != 0)
+ ++i;
+
+ return i;
}
-
/* Print an operand. Recognize special options, documented below. */
#if TARGET_ELF
@@ -6136,14 +7419,7 @@ print_operand (file, x, code)
{
int i;
HOST_WIDE_INT val;
-
- /* These macros test for integers and extract the low-order bits. */
-#define INT_P(X) \
-((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE) \
- && GET_MODE (X) == VOIDmode)
-
-#define INT_LOWPART(X) \
- (GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X))
+ unsigned HOST_WIDE_INT uval;
switch (code)
{
@@ -6209,6 +7485,15 @@ print_operand (file, x, code)
fprintf (file, "crnor %d,%d,%d\n\t", base_bit + 3,
base_bit + 2, base_bit + 2);
}
+ else if (TARGET_SPE && TARGET_HARD_FLOAT
+ && GET_CODE (x) == EQ
+ && GET_MODE (XEXP (x, 0)) == CCFPmode)
+ {
+ int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO);
+
+ fprintf (file, "crnor %d,%d,%d\n\t", base_bit + 1,
+ base_bit + 1, base_bit + 1);
+ }
return;
case 'E':
@@ -6239,7 +7524,7 @@ print_operand (file, x, code)
case 'G':
/* X is a constant integer. If it is negative, print "m",
- otherwise print "z". This is to make a aze or ame insn. */
+ otherwise print "z". This is to make an aze or ame insn. */
if (GET_CODE (x) != CONST_INT)
output_operand_lossage ("invalid %%G value");
else if (INTVAL (x) >= 0)
@@ -6319,6 +7604,11 @@ print_operand (file, x, code)
output_operand_lossage ("invalid %%K value");
print_operand_address (file, XEXP (XEXP (x, 0), 0));
fputs ("@l", file);
+ /* For GNU as, there must be a non-alphanumeric character
+ between 'l' and the number. The '-' is added by
+ print_operand() already. */
+ if (INTVAL (XEXP (XEXP (x, 0), 1)) >= 0)
+ fputs ("+", file);
print_operand (file, XEXP (XEXP (x, 0), 1), 0);
}
return;
@@ -6354,34 +7644,7 @@ print_operand (file, x, code)
if (! mask_operand (x, SImode))
output_operand_lossage ("invalid %%m value");
- val = INT_LOWPART (x);
-
- /* If the high bit is set and the low bit is not, the value is zero.
- If the high bit is zero, the value is the first 1 bit we find from
- the left. */
- if ((val & 0x80000000) && ((val & 1) == 0))
- {
- putc ('0', file);
- return;
- }
- else if ((val & 0x80000000) == 0)
- {
- for (i = 1; i < 32; i++)
- if ((val <<= 1) & 0x80000000)
- break;
- fprintf (file, "%d", i);
- return;
- }
-
- /* Otherwise, look for the first 0 bit from the right. The result is its
- number plus 1. We know the low-order bit is one. */
- for (i = 0; i < 32; i++)
- if (((val >>= 1) & 1) == 0)
- break;
-
- /* If we ended in ...01, i would be 0. The correct value is 31, so
- we want 31 - i. */
- fprintf (file, "%d", 31 - i);
+ fprintf (file, "%d", extract_MB (x));
return;
case 'M':
@@ -6389,35 +7652,7 @@ print_operand (file, x, code)
if (! mask_operand (x, SImode))
output_operand_lossage ("invalid %%M value");
- val = INT_LOWPART (x);
-
- /* If the low bit is set and the high bit is not, the value is 31.
- If the low bit is zero, the value is the first 1 bit we find from
- the right. */
- if ((val & 1) && ((val & 0x80000000) == 0))
- {
- fputs ("31", file);
- return;
- }
- else if ((val & 1) == 0)
- {
- for (i = 0; i < 32; i++)
- if ((val >>= 1) & 1)
- break;
-
- /* If we had ....10, i would be 0. The result should be
- 30, so we need 30 - i. */
- fprintf (file, "%d", 30 - i);
- return;
- }
-
- /* Otherwise, look for the first 0 bit from the left. The result is its
- number minus 1. We know the high-order bit is one. */
- for (i = 0; i < 32; i++)
- if (((val <<= 1) & 0x80000000) == 0)
- break;
-
- fprintf (file, "%d", i);
+ fprintf (file, "%d", extract_ME (x));
return;
/* %n outputs the negative of its operand. */
@@ -6513,68 +7748,43 @@ print_operand (file, x, code)
return;
case 'S':
- /* PowerPC64 mask position. All 0's and all 1's are excluded.
+ /* PowerPC64 mask position. All 0's is excluded.
CONST_INT 32-bit mask is considered sign-extended so any
transition must occur within the CONST_INT, not on the boundary. */
if (! mask64_operand (x, DImode))
output_operand_lossage ("invalid %%S value");
- val = INT_LOWPART (x);
+ uval = INT_LOWPART (x);
- if (val & 1) /* Clear Left */
+ if (uval & 1) /* Clear Left */
{
- for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
- if (!((val >>= 1) & 1))
- break;
-
-#if HOST_BITS_PER_WIDE_INT == 32
- if (GET_CODE (x) == CONST_DOUBLE && i == 32)
- {
- val = CONST_DOUBLE_HIGH (x);
-
- if (val == 0)
- --i;
- else
- for (i = 32; i < 64; i++)
- if (!((val >>= 1) & 1))
- break;
- }
-#endif
- /* i = index of last set bit from right
- mask begins at 63 - i from left */
- if (i > 63)
- output_operand_lossage ("%%S computed all 1's mask");
-
- fprintf (file, "%d", 63 - i);
- return;
+ uval &= ((unsigned HOST_WIDE_INT) 1 << 63 << 1) - 1;
+ i = 64;
}
- else /* Clear Right */
+ else /* Clear Right */
{
- for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++)
- if ((val >>= 1) & 1)
- break;
+ uval = ~uval;
+ uval &= ((unsigned HOST_WIDE_INT) 1 << 63 << 1) - 1;
+ i = 63;
+ }
+ while (uval != 0)
+ --i, uval >>= 1;
+ if (i < 0)
+ abort ();
+ fprintf (file, "%d", i);
+ return;
-#if HOST_BITS_PER_WIDE_INT == 32
- if (GET_CODE (x) == CONST_DOUBLE && i == 32)
- {
- val = CONST_DOUBLE_HIGH (x);
+ case 't':
+ /* Like 'J' but get to the OVERFLOW/UNORDERED bit. */
+ if (GET_CODE (x) != REG || GET_MODE (x) != CCmode)
+ abort ();
- if (val == (HOST_WIDE_INT) -1)
- --i;
- else
- for (i = 32; i < 64; i++)
- if ((val >>= 1) & 1)
- break;
- }
-#endif
- /* i = index of last clear bit from right
- mask ends at 62 - i from left */
- if (i > 62)
- output_operand_lossage ("%%S computed all 0's mask");
+ /* Bit 3 is OV bit. */
+ i = 4 * (REGNO (x) - CR0_REGNO) + 3;
- fprintf (file, "%d", 62 - i);
- return;
- }
+ /* If we want bit 31, write a shift count of zero, not 32. */
+ fprintf (file, "%d", i == 31 ? 0 : i + 1);
+ return;
case 'T':
/* Print the symbolic name of a branch target register. */
@@ -6768,7 +7978,7 @@ print_operand (file, x, code)
}
return;
- /* Print AltiVec memory operand. */
+ /* Print AltiVec or SPE memory operand. */
case 'y':
{
rtx tmp;
@@ -6778,6 +7988,30 @@ print_operand (file, x, code)
tmp = XEXP (x, 0);
+ if (TARGET_SPE)
+ {
+ /* Handle [reg]. */
+ if (GET_CODE (tmp) == REG)
+ {
+ fprintf (file, "0(%s)", reg_names[REGNO (tmp)]);
+ break;
+ }
+ /* Handle [reg+UIMM]. */
+ else if (GET_CODE (tmp) == PLUS &&
+ GET_CODE (XEXP (tmp, 1)) == CONST_INT)
+ {
+ int x;
+
+ if (GET_CODE (XEXP (tmp, 0)) != REG)
+ abort ();
+
+ x = INTVAL (XEXP (tmp, 1));
+ fprintf (file, "%d(%s)", x, reg_names[REGNO (XEXP (tmp, 0))]);
+ break;
+ }
+
+ /* Fall through. Must be [reg+reg]. */
+ }
if (GET_CODE (tmp) == REG)
fprintf (file, "0,%s", reg_names[REGNO (tmp)]);
else if (GET_CODE (tmp) == PLUS && GET_CODE (XEXP (tmp, 1)) == REG)
@@ -6909,7 +8143,7 @@ print_operand_address (file, x)
abort ();
}
-/* Target hook for assembling integer objects. The powerpc version has
+/* Target hook for assembling integer objects. The PowerPC version has
to handle fixup entries for relocatable code if RELOCATABLE_NEEDS_FIXUP
is defined. It also needs to handle DI-mode objects on 64-bit
targets. */
@@ -6972,6 +8206,37 @@ rs6000_assemble_integer (x, size, aligned_p)
#endif /* RELOCATABLE_NEEDS_FIXUP */
return default_assemble_integer (x, size, aligned_p);
}
+
+#ifdef HAVE_GAS_HIDDEN
+/* Emit an assembler directive to set symbol visibility for DECL to
+ VISIBILITY_TYPE. */
+
+static void
+rs6000_assemble_visibility (decl, vis)
+ tree decl;
+ int vis;
+{
+ /* Functions need to have their entry point symbol visibility set as
+ well as their descriptor symbol visibility. */
+ if (DEFAULT_ABI == ABI_AIX && TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ static const char * const visibility_types[] = {
+ NULL, "internal", "hidden", "protected"
+ };
+
+ const char *name, *type;
+
+ name = ((* targetm.strip_name_encoding)
+ (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
+ type = visibility_types[vis];
+
+ fprintf (asm_out_file, "\t.%s\t%s\n", type, name);
+ fprintf (asm_out_file, "\t.%s\t.%s\n", type, name);
+ }
+ else
+ default_assemble_visibility (decl, vis);
+}
+#endif
enum rtx_code
rs6000_reverse_condition (mode, code)
@@ -7006,15 +8271,134 @@ rs6000_generate_compare (code)
/* First, the compare. */
compare_result = gen_reg_rtx (comp_mode);
- emit_insn (gen_rtx_SET (VOIDmode, compare_result,
- gen_rtx_COMPARE (comp_mode,
- rs6000_compare_op0,
- rs6000_compare_op1)));
+
+ /* SPE FP compare instructions on the GPRs. Yuck! */
+ if ((TARGET_SPE && TARGET_HARD_FLOAT) && rs6000_compare_fp_p)
+ {
+ rtx cmp, or1, or2, or_result, compare_result2;
+
+ switch (code)
+ {
+ case EQ:
+ case UNEQ:
+ case NE:
+ case LTGT:
+ cmp = flag_unsafe_math_optimizations
+ ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ break;
+ case GT:
+ case GTU:
+ case UNGT:
+ case UNGE:
+ case GE:
+ case GEU:
+ cmp = flag_unsafe_math_optimizations
+ ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ break;
+ case LT:
+ case LTU:
+ case UNLT:
+ case UNLE:
+ case LE:
+ case LEU:
+ cmp = flag_unsafe_math_optimizations
+ ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ break;
+ default:
+ abort ();
+ }
+
+ /* Synthesize LE and GE from LT/GT || EQ. */
+ if (code == LE || code == GE || code == LEU || code == GEU)
+ {
+ /* Synthesize GE/LE frome GT/LT || EQ. */
+
+ emit_insn (cmp);
+
+ switch (code)
+ {
+ case LE: code = LT; break;
+ case GE: code = GT; break;
+ case LEU: code = LT; break;
+ case GEU: code = GT; break;
+ default: abort ();
+ }
+
+ or1 = gen_reg_rtx (SImode);
+ or2 = gen_reg_rtx (SImode);
+ or_result = gen_reg_rtx (CCEQmode);
+ compare_result2 = gen_reg_rtx (CCFPmode);
+
+ /* Do the EQ. */
+ cmp = flag_unsafe_math_optimizations
+ ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0,
+ rs6000_compare_op1);
+ emit_insn (cmp);
+
+ /* The MC8540 FP compare instructions set the CR bits
+ differently than other PPC compare instructions. For
+ that matter, there is no generic test instruction, but a
+ testgt, testlt, and testeq. For a true condition, bit 2
+ is set (x1xx) in the CR. Following the traditional CR
+ values:
+
+ LT GT EQ OV
+ bit3 bit2 bit1 bit0
+
+ ... bit 2 would be a GT CR alias, so later on we
+ look in the GT bits for the branch instructins.
+ However, we must be careful to emit correct RTL in
+ the meantime, so optimizations don't get confused. */
+
+ or1 = gen_rtx (NE, SImode, compare_result, const0_rtx);
+ or2 = gen_rtx (NE, SImode, compare_result2, const0_rtx);
+
+ /* OR them together. */
+ cmp = gen_rtx_SET (VOIDmode, or_result,
+ gen_rtx_COMPARE (CCEQmode,
+ gen_rtx_IOR (SImode, or1, or2),
+ const_true_rtx));
+ compare_result = or_result;
+ code = EQ;
+ }
+ else
+ {
+ /* We only care about 1 bit (x1xx), so map everything to NE to
+ maintain rtl sanity. We'll get to the right bit (x1xx) at
+ code output time. */
+ if (code == NE || code == LTGT)
+ /* Do the inverse here because we have no cmpne
+ instruction. We use the cmpeq instruction and expect
+ to get a 0 instead. */
+ code = EQ;
+ else
+ code = NE;
+ }
+
+ emit_insn (cmp);
+ }
+ else
+ emit_insn (gen_rtx_SET (VOIDmode, compare_result,
+ gen_rtx_COMPARE (comp_mode,
+ rs6000_compare_op0,
+ rs6000_compare_op1)));
/* Some kinds of FP comparisons need an OR operation;
except for flag_unsafe_math_optimizations we don't bother. */
if (rs6000_compare_fp_p
&& ! flag_unsafe_math_optimizations
+ && ! (TARGET_HARD_FLOAT && TARGET_SPE)
&& (code == LE || code == GE
|| code == UNEQ || code == LTGT
|| code == UNGT || code == UNLT))
@@ -7104,7 +8488,7 @@ rs6000_emit_cbranch (code, loc)
condition code register and its mode specifies what kind of
comparison we made.
- REVERSED is non-zero if we should reverse the sense of the comparison.
+ REVERSED is nonzero if we should reverse the sense of the comparison.
INSN is the insn. */
@@ -7142,6 +8526,19 @@ output_cbranch (op, label, reversed, insn)
code = reverse_condition (code);
}
+ if ((TARGET_SPE && TARGET_HARD_FLOAT) && mode == CCFPmode)
+ {
+ /* The efscmp/tst* instructions twiddle bit 2, which maps nicely
+ to the GT bit. */
+ if (code == EQ)
+ /* Opposite of GT. */
+ code = UNLE;
+ else if (code == NE)
+ code = GT;
+ else
+ abort ();
+ }
+
switch (code)
{
/* Not all of these are actually distinct opcodes, but
@@ -7168,21 +8565,30 @@ output_cbranch (op, label, reversed, insn)
/* Maybe we have a guess as to how likely the branch is.
The old mnemonics don't have a way to specify this information. */
+ pred = "";
note = find_reg_note (insn, REG_BR_PROB, NULL_RTX);
if (note != NULL_RTX)
{
/* PROB is the difference from 50%. */
int prob = INTVAL (XEXP (note, 0)) - REG_BR_PROB_BASE / 2;
-
- /* For branches that are very close to 50%, assume not-taken. */
- if (abs (prob) > REG_BR_PROB_BASE / 20
- && ((prob > 0) ^ need_longbranch))
- pred = "+";
- else
- pred = "-";
+ bool always_hint = rs6000_cpu != PROCESSOR_POWER4;
+
+ /* Only hint for highly probable/improbable branches on newer
+ cpus as static prediction overrides processor dynamic
+ prediction. For older cpus we may as well always hint, but
+ assume not taken for branches that are very close to 50% as a
+ mispredicted taken branch is more expensive than a
+ mispredicted not-taken branch. */
+ if (always_hint
+ || abs (prob) > REG_BR_PROB_BASE / 100 * 48)
+ {
+ if (abs (prob) > REG_BR_PROB_BASE / 20
+ && ((prob > 0) ^ need_longbranch))
+ pred = "+";
+ else
+ pred = "-";
+ }
}
- else
- pred = "";
if (label == NULL)
s += sprintf (s, "{b%sr|b%slr%s} ", ccode, ccode, pred);
@@ -7228,7 +8634,10 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond)
rtx temp;
/* These modes should always match. */
- if (GET_MODE (op1) != compare_mode)
+ if (GET_MODE (op1) != compare_mode
+ /* In the isel case however, we can use a compare immediate, so
+ op1 may be a small constant. */
+ && (!TARGET_ISEL || !short_cint_operand (op1, VOIDmode)))
return 0;
if (GET_MODE (true_cond) != result_mode)
return 0;
@@ -7237,10 +8646,12 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond)
/* First, work out if the hardware can do this at all, or
if it's too slow... */
- /* If the comparison is an integer one, since we only have fsel
- it'll be cheaper to use a branch. */
if (! rs6000_compare_fp_p)
- return 0;
+ {
+ if (TARGET_ISEL)
+ return rs6000_emit_int_cmove (dest, op, true_cond, false_cond);
+ return 0;
+ }
/* Eliminate half of the comparisons by switching operands, this
makes the remaining code simpler. */
@@ -7264,11 +8675,11 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond)
/* We're going to try to implement comparions by performing
a subtract, then comparing against zero. Unfortunately,
Inf - Inf is NaN which is not zero, and so if we don't
- know that the the operand is finite and the comparison
+ know that the operand is finite and the comparison
would treat EQ different to UNORDERED, we can't do it. */
if (! flag_unsafe_math_optimizations
&& code != GT && code != UNGE
- && (GET_CODE (op1) != CONST_DOUBLE || target_isinf (c1))
+ && (GET_CODE (op1) != CONST_DOUBLE || real_isinf (&c1))
/* Constructs of the form (a OP b ? a : b) are safe. */
&& ((! rtx_equal_p (op0, false_cond) && ! rtx_equal_p (op1, false_cond))
|| (! rtx_equal_p (op0, true_cond)
@@ -7372,6 +8783,53 @@ rs6000_emit_cmove (dest, op, true_cond, false_cond)
return 1;
}
+/* Same as above, but for ints (isel). */
+
+static int
+rs6000_emit_int_cmove (dest, op, true_cond, false_cond)
+ rtx dest;
+ rtx op;
+ rtx true_cond;
+ rtx false_cond;
+{
+ rtx condition_rtx, cr;
+
+ /* All isel implementations thus far are 32-bits. */
+ if (GET_MODE (rs6000_compare_op0) != SImode)
+ return 0;
+
+ /* We still have to do the compare, because isel doesn't do a
+ compare, it just looks at the CRx bits set by a previous compare
+ instruction. */
+ condition_rtx = rs6000_generate_compare (GET_CODE (op));
+ cr = XEXP (condition_rtx, 0);
+
+ if (GET_MODE (cr) == CCmode)
+ emit_insn (gen_isel_signed (dest, condition_rtx,
+ true_cond, false_cond, cr));
+ else
+ emit_insn (gen_isel_unsigned (dest, condition_rtx,
+ true_cond, false_cond, cr));
+
+ return 1;
+}
+
+const char *
+output_isel (operands)
+ rtx *operands;
+{
+ enum rtx_code code;
+
+ code = GET_CODE (operands[1]);
+ if (code == GE || code == GEU || code == LE || code == LEU || code == NE)
+ {
+ PUT_CODE (operands[1], reverse_condition (code));
+ return "isel %0,%3,%2,%j1";
+ }
+ else
+ return "isel %0,%2,%3,%j1";
+}
+
void
rs6000_emit_minmax (dest, code, op0, op1)
rtx dest;
@@ -7380,12 +8838,19 @@ rs6000_emit_minmax (dest, code, op0, op1)
rtx op1;
{
enum machine_mode mode = GET_MODE (op0);
+ enum rtx_code c;
rtx target;
+
+ if (code == SMAX || code == SMIN)
+ c = GE;
+ else
+ c = GEU;
+
if (code == SMAX || code == UMAX)
- target = emit_conditional_move (dest, GE, op0, op1, mode,
+ target = emit_conditional_move (dest, c, op0, op1, mode,
op0, op1, mode, 0);
else
- target = emit_conditional_move (dest, GE, op0, op1, mode,
+ target = emit_conditional_move (dest, c, op0, op1, mode,
op1, op0, mode, 0);
if (target == NULL_RTX)
abort ();
@@ -7409,13 +8874,14 @@ first_reg_to_save ()
if (regs_ever_live[first_reg]
&& (! call_used_regs[first_reg]
|| (first_reg == RS6000_PIC_OFFSET_TABLE_REGNUM
- && ((DEFAULT_ABI == ABI_V4 && flag_pic == 1)
+ && ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
|| (DEFAULT_ABI == ABI_DARWIN && flag_pic)))))
break;
#if TARGET_MACHO
- if (flag_pic && current_function_uses_pic_offset_table &&
- (first_reg > RS6000_PIC_OFFSET_TABLE_REGNUM))
+ if (flag_pic
+ && current_function_uses_pic_offset_table
+ && first_reg > RS6000_PIC_OFFSET_TABLE_REGNUM)
return RS6000_PIC_OFFSET_TABLE_REGNUM;
#endif
@@ -7583,6 +9049,10 @@ is_altivec_return_reg (reg, xyes)
+---------------------------------------+
| Save area for VRSAVE register (Z) | 8+P+A+V+L+X+W+Y
+---------------------------------------+
+ | SPE: area for 64-bit GP registers |
+ +---------------------------------------+
+ | SPE alignment padding |
+ +---------------------------------------+
| saved CR (C) | 8+P+A+V+L+X+W+Y+Z
+---------------------------------------+
| Save area for GP registers (G) | 8+P+A+V+L+X+W+Y+Z+C
@@ -7638,6 +9108,20 @@ rs6000_stack_info ()
else
info_ptr->gp_size = reg_size * (32 - info_ptr->first_gp_reg_save);
+ /* For the SPE, we have an additional upper 32-bits on each GPR.
+ Ideally we should save the entire 64-bits only when the upper
+ half is used in SIMD instructions. Since we only record
+ registers live (not the size they are used in), this proves
+ difficult because we'd have to traverse the instruction chain at
+ the right time, taking reload into account. This is a real pain,
+ so we opt to save the GPRs in 64-bits always. Anyone overly
+ concerned with frame size can fix this. ;-).
+
+ So... since we save all GPRs (except the SP) in 64-bits, the
+ traditional GP save area will be empty. */
+ if (TARGET_SPE_ABI)
+ info_ptr->gp_size = 0;
+
info_ptr->first_fp_reg_save = first_fp_reg_to_save ();
info_ptr->fp_size = 8 * (64 - info_ptr->first_fp_reg_save);
@@ -7686,7 +9170,9 @@ rs6000_stack_info ()
unsigned int i;
for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; ++i)
continue;
- ehrd_size = i * UNITS_PER_WORD;
+
+ /* SPE saves EH registers in 64-bits. */
+ ehrd_size = i * (TARGET_SPE_ABI ? UNITS_PER_SPE_WORD : UNITS_PER_WORD);
}
else
ehrd_size = 0;
@@ -7699,7 +9185,12 @@ rs6000_stack_info ()
info_ptr->parm_size = RS6000_ALIGN (current_function_outgoing_args_size,
8);
- if (TARGET_ALTIVEC_ABI)
+ if (TARGET_SPE_ABI)
+ info_ptr->spe_gp_size = 8 * (32 - info_ptr->first_gp_reg_save);
+ else
+ info_ptr->spe_gp_size = 0;
+
+ if (TARGET_ALTIVEC_ABI && TARGET_ALTIVEC_VRSAVE)
{
info_ptr->vrsave_mask = compute_vrsave_mask ();
info_ptr->vrsave_size = info_ptr->vrsave_mask ? 4 : 0;
@@ -7754,7 +9245,26 @@ rs6000_stack_info ()
info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size;
info_ptr->cr_save_offset = info_ptr->gp_save_offset - info_ptr->cr_size;
- if (TARGET_ALTIVEC_ABI)
+ if (TARGET_SPE_ABI)
+ {
+ /* Align stack so SPE GPR save area is aligned on a
+ double-word boundary. */
+ if (info_ptr->spe_gp_size != 0)
+ info_ptr->spe_padding_size
+ = 8 - (-info_ptr->cr_save_offset % 8);
+ else
+ info_ptr->spe_padding_size = 0;
+
+ info_ptr->spe_gp_save_offset
+ = info_ptr->cr_save_offset
+ - info_ptr->spe_padding_size
+ - info_ptr->spe_gp_size;
+
+ /* Adjust for SPE case. */
+ info_ptr->toc_save_offset
+ = info_ptr->spe_gp_save_offset - info_ptr->toc_size;
+ }
+ else if (TARGET_ALTIVEC_ABI)
{
info_ptr->vrsave_save_offset
= info_ptr->cr_save_offset - info_ptr->vrsave_size;
@@ -7787,10 +9297,11 @@ rs6000_stack_info ()
+ info_ptr->altivec_size
+ info_ptr->altivec_padding_size
+ info_ptr->vrsave_size
+ + info_ptr->spe_gp_size
+ + info_ptr->spe_padding_size
+ ehrd_size
+ info_ptr->cr_size
+ info_ptr->lr_size
- + info_ptr->vrsave_size
+ info_ptr->toc_size,
(TARGET_ALTIVEC_ABI || ABI_DARWIN)
? 16 : 8);
@@ -7841,6 +9352,9 @@ rs6000_stack_info ()
if (! TARGET_ALTIVEC_ABI || info_ptr->vrsave_mask == 0)
info_ptr->vrsave_save_offset = 0;
+ if (! TARGET_SPE_ABI || info_ptr->spe_gp_size == 0)
+ info_ptr->spe_gp_save_offset = 0;
+
if (! info_ptr->lr_save_p)
info_ptr->lr_save_offset = 0;
@@ -7882,6 +9396,9 @@ debug_stack_info (info)
if (TARGET_ALTIVEC_ABI)
fprintf (stderr, "\tALTIVEC ABI extensions enabled.\n");
+ if (TARGET_SPE_ABI)
+ fprintf (stderr, "\tSPE ABI extensions enabled.\n");
+
if (info->first_gp_reg_save != 32)
fprintf (stderr, "\tfirst_gp_reg_save = %5d\n", info->first_gp_reg_save);
@@ -7920,6 +9437,10 @@ debug_stack_info (info)
fprintf (stderr, "\taltivec_save_offset = %5d\n",
info->altivec_save_offset);
+ if (info->spe_gp_save_offset)
+ fprintf (stderr, "\tspe_gp_save_offset = %5d\n",
+ info->spe_gp_save_offset);
+
if (info->vrsave_save_offset)
fprintf (stderr, "\tvrsave_save_offset = %5d\n",
info->vrsave_save_offset);
@@ -7954,6 +9475,9 @@ debug_stack_info (info)
if (info->gp_size)
fprintf (stderr, "\tgp_size = %5d\n", info->gp_size);
+ if (info->spe_gp_size)
+ fprintf (stderr, "\tspe_gp_size = %5d\n", info->spe_gp_size);
+
if (info->fp_size)
fprintf (stderr, "\tfp_size = %5d\n", info->fp_size);
@@ -7967,6 +9491,10 @@ debug_stack_info (info)
fprintf (stderr, "\taltivec_padding_size= %5d\n",
info->altivec_padding_size);
+ if (info->spe_padding_size)
+ fprintf (stderr, "\tspe_padding_size = %5d\n",
+ info->spe_padding_size);
+
if (info->lr_size)
fprintf (stderr, "\tlr_size = %5d\n", info->lr_size);
@@ -7993,10 +9521,7 @@ rs6000_return_addr (count, frame)
/* Currently we don't optimize very well between prolog and body
code and for PIC code the code can be actually quite bad, so
don't try to be too clever here. */
- if (count != 0
- || flag_pic != 0
- || DEFAULT_ABI == ABI_AIX
- || DEFAULT_ABI == ABI_AIX_NODESC)
+ if (count != 0 || flag_pic != 0)
{
cfun->machine->ra_needs_full_frame = 1;
@@ -8014,25 +9539,92 @@ rs6000_return_addr (count, frame)
return get_hard_reg_initial_val (Pmode, LINK_REGISTER_REGNUM);
}
+/* Say whether a function is a candidate for sibcall handling or not.
+ We do not allow indirect calls to be optimized into sibling calls.
+ Also, we can't do it if there are any vector parameters; there's
+ nowhere to put the VRsave code so it works; note that functions with
+ vector parameters are required to have a prototype, so the argument
+ type info must be available here. (The tail recursion case can work
+ with vector parameters, but there's no way to distinguish here.) */
+int
+function_ok_for_sibcall (fndecl)
+ tree fndecl;
+{
+ tree type;
+ if (fndecl)
+ {
+ if (TARGET_ALTIVEC_VRSAVE)
+ {
+ for (type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+ type; type = TREE_CHAIN (type))
+ {
+ if (TREE_CODE (TREE_VALUE (type)) == VECTOR_TYPE)
+ return 0;
+ }
+ }
+ if (DEFAULT_ABI == ABI_DARWIN
+ || (*targetm.binds_local_p) (fndecl))
+ {
+ tree attr_list = TYPE_ATTRIBUTES (TREE_TYPE (fndecl));
+
+ if (!lookup_attribute ("longcall", attr_list)
+ || lookup_attribute ("shortcall", attr_list))
+ return 1;
+ }
+ }
+ return 0;
+}
+
static int
rs6000_ra_ever_killed ()
{
rtx top;
+ rtx reg;
+ rtx insn;
-#ifdef ASM_OUTPUT_MI_THUNK
- if (current_function_is_thunk)
+ /* Irritatingly, there are two kinds of thunks -- those created with
+ TARGET_ASM_OUTPUT_MI_THUNK and those with DECL_THUNK_P that go
+ through the regular part of the compiler. This is a very hacky
+ way to tell them apart. */
+ if (current_function_is_thunk && !no_new_pseudos)
return 0;
-#endif
- if (!has_hard_reg_initial_val (Pmode, LINK_REGISTER_REGNUM)
- || cfun->machine->ra_needs_full_frame)
- return regs_ever_live[LINK_REGISTER_REGNUM];
+ /* regs_ever_live has LR marked as used if any sibcalls are present,
+ but this should not force saving and restoring in the
+ pro/epilogue. Likewise, reg_set_between_p thinks a sibcall
+ clobbers LR, so that is inappropriate. */
+
+ /* Also, the prologue can generate a store into LR that
+ doesn't really count, like this:
+
+ move LR->R0
+ bcl to set PIC register
+ move LR->R31
+ move R0->LR
+
+ When we're called from the epilogue, we need to avoid counting
+ this as a store. */
+
push_topmost_sequence ();
top = get_insns ();
pop_topmost_sequence ();
+ reg = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
- return reg_set_between_p (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM),
- top, NULL_RTX);
+ for (insn = NEXT_INSN (top); insn != NULL_RTX; insn = NEXT_INSN (insn))
+ {
+ if (INSN_P (insn))
+ {
+ if (FIND_REG_INC_NOTE (insn, reg))
+ return 1;
+ else if (GET_CODE (insn) == CALL_INSN
+ && !SIBLING_CALL_P (insn))
+ return 1;
+ else if (set_of (reg, insn) != NULL_RTX
+ && !prologue_epilogue_contains (insn))
+ return 1;
+ }
+ }
+ return 0;
}
/* Add a REG_MAYBE_DEAD note to the insn. */
@@ -8053,7 +9645,7 @@ void
rs6000_emit_load_toc_table (fromprolog)
int fromprolog;
{
- rtx dest;
+ rtx dest, insn;
dest = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 1)
@@ -8061,8 +9653,12 @@ rs6000_emit_load_toc_table (fromprolog)
rtx temp = (fromprolog
? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
: gen_reg_rtx (Pmode));
- rs6000_maybe_dead (emit_insn (gen_load_toc_v4_pic_si (temp)));
- rs6000_maybe_dead (emit_move_insn (dest, temp));
+ insn = emit_insn (gen_load_toc_v4_pic_si (temp));
+ if (fromprolog)
+ rs6000_maybe_dead (insn);
+ insn = emit_move_insn (dest, temp);
+ if (fromprolog)
+ rs6000_maybe_dead (insn);
}
else if (TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2)
{
@@ -8109,14 +9705,13 @@ rs6000_emit_load_toc_table (fromprolog)
ASM_GENERATE_INTERNAL_LABEL (buf, "LCG", reload_toc_labelno++);
symF = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
- rs6000_maybe_dead (emit_insn (gen_load_toc_v4_PIC_1b (tempLR,
- symF,
- tocsym)));
- rs6000_maybe_dead (emit_move_insn (dest, tempLR));
- rs6000_maybe_dead (emit_move_insn (temp0,
- gen_rtx_MEM (Pmode, dest)));
+ emit_insn (gen_load_toc_v4_PIC_1b (tempLR, symF, tocsym));
+ emit_move_insn (dest, tempLR);
+ emit_move_insn (temp0, gen_rtx_MEM (Pmode, dest));
}
- rs6000_maybe_dead (emit_insn (gen_addsi3 (dest, temp0, dest)));
+ insn = emit_insn (gen_addsi3 (dest, temp0, dest));
+ if (fromprolog)
+ rs6000_maybe_dead (insn);
}
else if (TARGET_ELF && !TARGET_AIX && flag_pic == 0 && TARGET_MINIMAL_TOC)
{
@@ -8126,15 +9721,21 @@ rs6000_emit_load_toc_table (fromprolog)
ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1);
realsym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
- rs6000_maybe_dead (emit_insn (gen_elf_high (dest, realsym)));
- rs6000_maybe_dead (emit_insn (gen_elf_low (dest, dest, realsym)));
+ insn = emit_insn (gen_elf_high (dest, realsym));
+ if (fromprolog)
+ rs6000_maybe_dead (insn);
+ insn = emit_insn (gen_elf_low (dest, dest, realsym));
+ if (fromprolog)
+ rs6000_maybe_dead (insn);
}
else if (DEFAULT_ABI == ABI_AIX)
{
if (TARGET_32BIT)
- rs6000_maybe_dead (emit_insn (gen_load_toc_aix_si (dest)));
+ insn = emit_insn (gen_load_toc_aix_si (dest));
else
- rs6000_maybe_dead (emit_insn (gen_load_toc_aix_di (dest)));
+ insn = emit_insn (gen_load_toc_aix_di (dest));
+ if (fromprolog)
+ rs6000_maybe_dead (insn);
}
else
abort ();
@@ -8273,10 +9874,8 @@ rs6000_emit_eh_toc_restore (stacksize)
bottom_of_stack, stacksize,
NULL_RTX, 1, OPTAB_WIDEN);
- emit_move_insn (tocompare,
- GEN_INT (trunc_int_for_mode (TARGET_32BIT
- ? 0x80410014
- : 0xE8410028, SImode)));
+ emit_move_insn (tocompare, gen_int_mode (TARGET_32BIT ? 0x80410014
+ : 0xE8410028, SImode));
if (insn_after_throw == NULL_RTX)
abort ();
@@ -8460,8 +10059,19 @@ rs6000_frame_related (insn, reg, val, reg2, rreg)
{
rtx real, temp;
+ /* copy_rtx will not make unique copies of registers, so we need to
+ ensure we don't have unwanted sharing here. */
+ if (reg == reg2)
+ reg = gen_raw_REG (GET_MODE (reg), REGNO (reg));
+
+ if (reg == rreg)
+ reg = gen_raw_REG (GET_MODE (reg), REGNO (reg));
+
real = copy_rtx (PATTERN (insn));
+ if (reg2 != NULL_RTX)
+ real = replace_rtx (real, reg2, rreg);
+
real = replace_rtx (real, reg,
gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode,
STACK_POINTER_REGNUM),
@@ -8514,9 +10124,6 @@ rs6000_frame_related (insn, reg, val, reg2, rreg)
else
abort ();
- if (reg2 != NULL_RTX)
- real = replace_rtx (real, reg2, rreg);
-
RTX_FRAME_RELATED_P (insn) = 1;
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
real,
@@ -8585,6 +10192,78 @@ generate_set_vrsave (reg, info, epiloguep)
return insn;
}
+/* Save a register into the frame, and emit RTX_FRAME_RELATED_P notes.
+ Save REGNO into [FRAME_REG + OFFSET] in mode MODE. */
+
+static void
+emit_frame_save (frame_reg, frame_ptr, mode, regno, offset, total_size)
+ rtx frame_reg;
+ rtx frame_ptr;
+ enum machine_mode mode;
+ unsigned int regno;
+ int offset;
+ int total_size;
+{
+ rtx reg, offset_rtx, insn, mem, addr, int_rtx;
+ rtx replacea, replaceb;
+
+ int_rtx = GEN_INT (offset);
+
+ /* Some cases that need register indexed addressing. */
+ if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ || (TARGET_SPE_ABI
+ && SPE_VECTOR_MODE (mode)
+ && !SPE_CONST_OFFSET_OK (offset)))
+ {
+ /* Whomever calls us must make sure r11 is available in the
+ flow path of instructions in the prologue. */
+ offset_rtx = gen_rtx_REG (Pmode, 11);
+ emit_move_insn (offset_rtx, int_rtx);
+
+ replacea = offset_rtx;
+ replaceb = int_rtx;
+ }
+ else
+ {
+ offset_rtx = int_rtx;
+ replacea = NULL_RTX;
+ replaceb = NULL_RTX;
+ }
+
+ reg = gen_rtx_REG (mode, regno);
+ addr = gen_rtx_PLUS (Pmode, frame_reg, offset_rtx);
+ mem = gen_rtx_MEM (mode, addr);
+ set_mem_alias_set (mem, rs6000_sr_alias_set);
+
+ insn = emit_move_insn (mem, reg);
+
+ rs6000_frame_related (insn, frame_ptr, total_size, replacea, replaceb);
+}
+
+/* Emit an offset memory reference suitable for a frame store, while
+ converting to a valid addressing mode. */
+
+static rtx
+gen_frame_mem_offset (mode, reg, offset)
+ enum machine_mode mode;
+ rtx reg;
+ int offset;
+{
+ rtx int_rtx, offset_rtx;
+
+ int_rtx = GEN_INT (offset);
+
+ if (TARGET_SPE_ABI && SPE_VECTOR_MODE (mode))
+ {
+ offset_rtx = gen_rtx_REG (Pmode, FIXED_SCRATCH);
+ emit_move_insn (offset_rtx, int_rtx);
+ }
+ else
+ offset_rtx = int_rtx;
+
+ return gen_rtx_MEM (mode, gen_rtx_PLUS (Pmode, reg, offset_rtx));
+}
+
/* Emit function prologue as insns. */
void
@@ -8602,7 +10281,14 @@ rs6000_emit_prologue ()
int using_store_multiple;
HOST_WIDE_INT sp_offset = 0;
+ if (TARGET_SPE_ABI)
+ {
+ reg_mode = V2SImode;
+ reg_size = 8;
+ }
+
using_store_multiple = (TARGET_MULTIPLE && ! TARGET_POWERPC64
+ && !TARGET_SPE_ABI
&& info->first_gp_reg_save < 31);
saving_FPRs_inline = (info->first_fp_reg_save == 64
|| FP_SAVE_INLINE (info->first_fp_reg_save));
@@ -8712,20 +10398,10 @@ rs6000_emit_prologue ()
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
if ((regs_ever_live[info->first_fp_reg_save+i]
&& ! call_used_regs[info->first_fp_reg_save+i]))
- {
- rtx addr, reg, mem;
- reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
- addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (info->fp_save_offset
- + sp_offset
- + 8 * i));
- mem = gen_rtx_MEM (DFmode, addr);
- set_mem_alias_set (mem, rs6000_sr_alias_set);
-
- insn = emit_move_insn (mem, reg);
- rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
- NULL_RTX, NULL_RTX);
- }
+ emit_frame_save (frame_reg_rtx, frame_ptr_rtx, DFmode,
+ info->first_fp_reg_save + i,
+ info->fp_save_offset + sp_offset + 8 * i,
+ info->total_size);
}
else if (info->first_fp_reg_save != 64)
{
@@ -8765,10 +10441,9 @@ rs6000_emit_prologue ()
the store-multiple instructions. */
if (using_store_multiple)
{
- rtvec p, dwarfp;
+ rtvec p;
int i;
p = rtvec_alloc (32 - info->first_gp_reg_save);
- dwarfp = rtvec_alloc (32 - info->first_gp_reg_save);
for (i = 0; i < 32 - info->first_gp_reg_save; i++)
{
rtx addr, reg, mem;
@@ -8793,21 +10468,50 @@ rs6000_emit_prologue ()
if ((regs_ever_live[info->first_gp_reg_save+i]
&& ! call_used_regs[info->first_gp_reg_save+i])
|| (i+info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
- && ((DEFAULT_ABI == ABI_V4 && flag_pic == 1)
+ && ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
|| (DEFAULT_ABI == ABI_DARWIN && flag_pic))))
{
rtx addr, reg, mem;
reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
- addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (info->gp_save_offset
- + sp_offset
- + reg_size * i));
- mem = gen_rtx_MEM (reg_mode, addr);
- set_mem_alias_set (mem, rs6000_sr_alias_set);
- insn = emit_move_insn (mem, reg);
- rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
- NULL_RTX, NULL_RTX);
+ if (TARGET_SPE_ABI)
+ {
+ int offset = info->spe_gp_save_offset + sp_offset + 8 * i;
+ rtx b;
+
+ if (!SPE_CONST_OFFSET_OK (offset))
+ {
+ b = gen_rtx_REG (Pmode, FIXED_SCRATCH);
+ emit_move_insn (b, GEN_INT (offset));
+ }
+ else
+ b = GEN_INT (offset);
+
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, b);
+ mem = gen_rtx_MEM (V2SImode, addr);
+ set_mem_alias_set (mem, rs6000_sr_alias_set);
+ insn = emit_move_insn (mem, reg);
+
+ if (GET_CODE (b) == CONST_INT)
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ NULL_RTX, NULL_RTX);
+ else
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ b, GEN_INT (offset));
+ }
+ else
+ {
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->gp_save_offset
+ + sp_offset
+ + reg_size * i));
+ mem = gen_rtx_MEM (reg_mode, addr);
+ set_mem_alias_set (mem, rs6000_sr_alias_set);
+
+ insn = emit_move_insn (mem, reg);
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ NULL_RTX, NULL_RTX);
+ }
}
}
@@ -8819,22 +10523,14 @@ rs6000_emit_prologue ()
for (i = 0; ; ++i)
{
- rtx addr, reg, mem;
-
regno = EH_RETURN_DATA_REGNO (i);
if (regno == INVALID_REGNUM)
break;
- reg = gen_rtx_REG (reg_mode, regno);
- addr = plus_constant (frame_reg_rtx,
- info->ehrd_offset + sp_offset
- + reg_size * (int) i);
- mem = gen_rtx_MEM (reg_mode, addr);
- set_mem_alias_set (mem, rs6000_sr_alias_set);
-
- insn = emit_move_insn (mem, reg);
- rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
- NULL_RTX, NULL_RTX);
+ emit_frame_save (frame_reg_rtx, frame_ptr_rtx, reg_mode, regno,
+ info->ehrd_offset + sp_offset
+ + reg_size * (int) i,
+ info->total_size);
}
}
@@ -8889,7 +10585,7 @@ rs6000_emit_prologue ()
/* Set frame pointer, if needed. */
if (frame_pointer_needed)
{
- insn = emit_move_insn (gen_rtx_REG (reg_mode, FRAME_POINTER_REGNUM),
+ insn = emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM),
sp_reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -8917,17 +10613,21 @@ rs6000_emit_prologue ()
gen_rtx_REG (Pmode, 11));
}
+#if TARGET_MACHO
if (DEFAULT_ABI == ABI_DARWIN
&& flag_pic && current_function_uses_pic_offset_table)
{
rtx dest = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
+ char *picbase = machopic_function_base_name ();
+ rtx src = gen_rtx_SYMBOL_REF (Pmode, ggc_alloc_string (picbase, -1));
- rs6000_maybe_dead (emit_insn (gen_load_macho_picbase (dest)));
+ rs6000_maybe_dead (emit_insn (gen_load_macho_picbase (dest, src)));
rs6000_maybe_dead (
emit_move_insn (gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM),
gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)));
}
+#endif
}
/* Write function prologue. */
@@ -9016,8 +10716,15 @@ rs6000_emit_epilogue (sibcall)
int reg_size = TARGET_POWERPC64 ? 8 : 4;
int i;
+ if (TARGET_SPE_ABI)
+ {
+ reg_mode = V2SImode;
+ reg_size = 8;
+ }
+
info = rs6000_stack_info ();
using_load_multiple = (TARGET_MULTIPLE && ! TARGET_POWERPC64
+ && !TARGET_SPE_ABI
&& info->first_gp_reg_save < 31);
restoring_FPRs_inline = (sibcall
|| current_function_calls_eh_return
@@ -9102,9 +10809,8 @@ rs6000_emit_epilogue (sibcall)
/* Get the old lr if we saved it. */
if (info->lr_save_p)
{
- rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (info->lr_save_offset + sp_offset));
- rtx mem = gen_rtx_MEM (Pmode, addr);
+ rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx,
+ info->lr_save_offset + sp_offset);
set_mem_alias_set (mem, rs6000_sr_alias_set);
@@ -9135,16 +10841,15 @@ rs6000_emit_epilogue (sibcall)
for (i = 0; ; ++i)
{
- rtx addr, mem;
+ rtx mem;
regno = EH_RETURN_DATA_REGNO (i);
if (regno == INVALID_REGNUM)
break;
- addr = plus_constant (frame_reg_rtx,
- info->ehrd_offset + sp_offset
- + reg_size * (int) i);
- mem = gen_rtx_MEM (reg_mode, addr);
+ mem = gen_frame_mem_offset (reg_mode, frame_reg_rtx,
+ info->ehrd_offset + sp_offset
+ + reg_size * (int) i);
set_mem_alias_set (mem, rs6000_sr_alias_set);
emit_move_insn (gen_rtx_REG (reg_mode, regno), mem);
@@ -9179,7 +10884,7 @@ rs6000_emit_epilogue (sibcall)
if ((regs_ever_live[info->first_gp_reg_save+i]
&& ! call_used_regs[info->first_gp_reg_save+i])
|| (i+info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
- && ((DEFAULT_ABI == ABI_V4 && flag_pic == 1)
+ && ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
|| (DEFAULT_ABI == ABI_DARWIN && flag_pic))))
{
rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
@@ -9188,11 +10893,28 @@ rs6000_emit_epilogue (sibcall)
+ reg_size * i));
rtx mem = gen_rtx_MEM (reg_mode, addr);
+ /* Restore 64-bit quantities for SPE. */
+ if (TARGET_SPE_ABI)
+ {
+ int offset = info->spe_gp_save_offset + sp_offset + 8 * i;
+ rtx b;
+
+ if (!SPE_CONST_OFFSET_OK (offset))
+ {
+ b = gen_rtx_REG (Pmode, FIXED_SCRATCH);
+ emit_move_insn (b, GEN_INT (offset));
+ }
+ else
+ b = GEN_INT (offset);
+
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, b);
+ mem = gen_rtx_MEM (V2SImode, addr);
+ }
+
set_mem_alias_set (mem, rs6000_sr_alias_set);
emit_move_insn (gen_rtx_REG (reg_mode,
- info->first_gp_reg_save + i),
- mem);
+ info->first_gp_reg_save + i), mem);
}
/* Restore fpr's if we need to do it without calling a function. */
@@ -9350,7 +11072,6 @@ rs6000_output_function_epilogue (file, size)
HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
rs6000_stack_t *info = rs6000_stack_info ();
- int optional_tbtab = (optimize_size || TARGET_ELF) ? 0 : 1;
if (! HAVE_epilogue)
{
@@ -9403,22 +11124,33 @@ rs6000_output_function_epilogue (file, size)
System V.4 Powerpc's (and the embedded ABI derived from it) use a
different traceback table. */
- if (DEFAULT_ABI == ABI_AIX && ! flag_inhibit_size_directive)
+ if (DEFAULT_ABI == ABI_AIX && ! flag_inhibit_size_directive
+ && rs6000_traceback != traceback_none)
{
- const char *fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+ const char *fname = NULL;
const char *language_string = lang_hooks.name;
int fixed_parms = 0, float_parms = 0, parm_info = 0;
int i;
+ int optional_tbtab;
- while (*fname == '.') /* V.4 encodes . in the name */
- fname++;
+ if (rs6000_traceback == traceback_full)
+ optional_tbtab = 1;
+ else if (rs6000_traceback == traceback_part)
+ optional_tbtab = 0;
+ else
+ optional_tbtab = !optimize_size && !TARGET_ELF;
- /* Need label immediately before tbtab, so we can compute its offset
- from the function start. */
- if (*fname == '*')
- ++fname;
- ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LT");
- ASM_OUTPUT_LABEL (file, fname);
+ if (optional_tbtab)
+ {
+ fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+ while (*fname == '.') /* V.4 encodes . in the name */
+ fname++;
+
+ /* Need label immediately before tbtab, so we can compute
+ its offset from the function start. */
+ ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LT");
+ ASM_OUTPUT_LABEL (file, fname);
+ }
/* The .tbtab pseudo-op can only be used for the first eight
expressions, since it can't handle the possibly variable
@@ -9513,7 +11245,7 @@ rs6000_output_function_epilogue (file, size)
if (mode == SFmode)
bits = 0x2;
- else if (mode == DFmode)
+ else if (mode == DFmode || mode == TFmode)
bits = 0x3;
else
abort ();
@@ -9590,6 +11322,8 @@ rs6000_output_function_epilogue (file, size)
/* Omit this list of longs, because there are no CTL anchors. */
/* Length of function name. */
+ if (*fname == '*')
+ ++fname;
fprintf (file, "\t.short %d\n", (int) strlen (fname));
/* Function name. */
@@ -9602,7 +11336,6 @@ rs6000_output_function_epilogue (file, size)
fputs ("\t.align 2\n", file);
}
- return;
}
/* A C compound statement that outputs the assembler code for a thunk
@@ -9637,11 +11370,12 @@ rs6000_output_function_epilogue (file, size)
calls FUNCTION instead of jumping to it. The generic approach does
not support varargs. */
-void
-output_mi_thunk (file, thunk_fndecl, delta, function)
+static void
+rs6000_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
FILE *file;
tree thunk_fndecl ATTRIBUTE_UNUSED;
- int delta;
+ HOST_WIDE_INT delta;
+ HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
tree function;
{
const char *this_reg =
@@ -9659,9 +11393,9 @@ output_mi_thunk (file, thunk_fndecl, delta, function)
if (delta >= -32768 && delta <= 32767)
{
if (! TARGET_NEW_MNEMONICS)
- fprintf (file, "\tcal %s,%d(%s)\n", this_reg, delta, this_reg);
+ fprintf (file, "\tcal %s,%d(%s)\n", this_reg, (int) delta, this_reg);
else
- fprintf (file, "\taddi %s,%s,%d\n", this_reg, this_reg, delta);
+ fprintf (file, "\taddi %s,%s,%d\n", this_reg, this_reg, (int) delta);
}
/* 64-bit constants. If "int" is 32 bits, we'll never hit this abort. */
@@ -9671,7 +11405,7 @@ output_mi_thunk (file, thunk_fndecl, delta, function)
/* Large constants that can be done by one addis instruction. */
else if ((delta & 0xffff) == 0)
asm_fprintf (file, "\t{cau|addis} %s,%s,%d\n", this_reg, this_reg,
- delta >> 16);
+ (int) (delta >> 16));
/* 32-bit constants that can be done by an add and addis instruction. */
else
@@ -9702,6 +11436,7 @@ output_mi_thunk (file, thunk_fndecl, delta, function)
case ABI_V4:
case ABI_AIX_NODESC:
+ case ABI_DARWIN:
prefix = "";
break;
}
@@ -9712,8 +11447,10 @@ output_mi_thunk (file, thunk_fndecl, delta, function)
fname = XSTR (XEXP (DECL_RTL (function), 0), 0);
if (current_file_function_operand (XEXP (DECL_RTL (function), 0), VOIDmode)
- && ! lookup_attribute ("longcall",
- TYPE_ATTRIBUTES (TREE_TYPE (function))))
+ && (! lookup_attribute ("longcall",
+ TYPE_ATTRIBUTES (TREE_TYPE (function)))
+ || lookup_attribute ("shortcall",
+ TYPE_ATTRIBUTES (TREE_TYPE (function)))))
{
fprintf (file, "\tb %s", prefix);
assemble_name (file, fname);
@@ -9745,10 +11482,7 @@ output_mi_thunk (file, thunk_fndecl, delta, function)
}
assemble_name (file, fname);
putc ('\n', file);
- if (TARGET_ELF)
- function_section (current_function_decl);
- else
- text_section ();
+ function_section (current_function_decl);
if (TARGET_MINIMAL_TOC)
asm_fprintf (file, (TARGET_32BIT)
? "\t{l|lwz} %s,%s(%s)\n" : "\tld %s,%s(%s)\n", r12,
@@ -9795,7 +11529,6 @@ output_mi_thunk (file, thunk_fndecl, delta, function)
}
}
}
-
/* A quick summary of the various types of 'constant-pool tables'
under PowerPC:
@@ -9843,20 +11576,34 @@ static unsigned
rs6000_hash_constant (k)
rtx k;
{
- unsigned result = (GET_CODE (k) << 3) ^ GET_MODE (k);
- const char *format = GET_RTX_FORMAT (GET_CODE (k));
- int flen = strlen (format);
- int fidx;
+ enum rtx_code code = GET_CODE (k);
+ enum machine_mode mode = GET_MODE (k);
+ unsigned result = (code << 3) ^ mode;
+ const char *format;
+ int flen, fidx;
- if (GET_CODE (k) == LABEL_REF)
- return result * 1231 + X0INT (XEXP (k, 0), 3);
+ format = GET_RTX_FORMAT (code);
+ flen = strlen (format);
+ fidx = 0;
- if (GET_CODE (k) == CONST_DOUBLE)
- fidx = 1;
- else if (GET_CODE (k) == CODE_LABEL)
- fidx = 3;
- else
- fidx = 0;
+ switch (code)
+ {
+ case LABEL_REF:
+ return result * 1231 + (unsigned) INSN_UID (XEXP (k, 0));
+
+ case CONST_DOUBLE:
+ if (mode != VOIDmode)
+ return real_hash (CONST_DOUBLE_REAL_VALUE (k)) * result;
+ flen = 2;
+ break;
+
+ case CODE_LABEL:
+ fidx = 3;
+ break;
+
+ default:
+ break;
+ }
for (; fidx < flen; fidx++)
switch (format[fidx])
@@ -9893,6 +11640,7 @@ rs6000_hash_constant (k)
default:
abort ();
}
+
return result;
}
@@ -9919,29 +11667,7 @@ toc_hash_eq (h1, h2)
!= ((const struct toc_hash_struct *) h2)->key_mode)
return 0;
- /* Gotcha: One of these const_doubles will be in memory.
- The other may be on the constant-pool chain.
- So rtx_equal_p will think they are different... */
- if (r1 == r2)
- return 1;
- if (GET_CODE (r1) != GET_CODE (r2)
- || GET_MODE (r1) != GET_MODE (r2))
- return 0;
- if (GET_CODE (r1) == CONST_DOUBLE)
- {
- int format_len = strlen (GET_RTX_FORMAT (CONST_DOUBLE));
- int i;
- for (i = 1; i < format_len; i++)
- if (XWINT (r1, i) != XWINT (r2, i))
- return 0;
-
- return 1;
- }
- else if (GET_CODE (r1) == LABEL_REF)
- return (CODE_LABEL_NUMBER (XEXP (r1, 0))
- == CODE_LABEL_NUMBER (XEXP (r2, 0)));
- else
- return rtx_equal_p (r1, r2);
+ return rtx_equal_p (r1, r2);
}
/* Mark the hash table-entry HASH_ENTRY. */
@@ -10071,7 +11797,42 @@ output_toc (file, x, labelno, mode)
/* Handle FP constants specially. Note that if we have a minimal
TOC, things we put here aren't actually in the TOC, so we can allow
FP constants. */
- if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
+ if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == TFmode)
+ {
+ REAL_VALUE_TYPE rv;
+ long k[4];
+
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
+
+ if (TARGET_64BIT)
+ {
+ if (TARGET_MINIMAL_TOC)
+ fputs (DOUBLE_INT_ASM_OP, file);
+ else
+ fprintf (file, "\t.tc FT_%lx_%lx_%lx_%lx[TC],",
+ k[0] & 0xffffffff, k[1] & 0xffffffff,
+ k[2] & 0xffffffff, k[3] & 0xffffffff);
+ fprintf (file, "0x%lx%08lx,0x%lx%08lx\n",
+ k[0] & 0xffffffff, k[1] & 0xffffffff,
+ k[2] & 0xffffffff, k[3] & 0xffffffff);
+ return;
+ }
+ else
+ {
+ if (TARGET_MINIMAL_TOC)
+ fputs ("\t.long ", file);
+ else
+ fprintf (file, "\t.tc FT_%lx_%lx_%lx_%lx[TC],",
+ k[0] & 0xffffffff, k[1] & 0xffffffff,
+ k[2] & 0xffffffff, k[3] & 0xffffffff);
+ fprintf (file, "0x%lx,0x%lx,0x%lx,0x%lx\n",
+ k[0] & 0xffffffff, k[1] & 0xffffffff,
+ k[2] & 0xffffffff, k[3] & 0xffffffff);
+ return;
+ }
+ }
+ else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
{
REAL_VALUE_TYPE rv;
long k[2];
@@ -10232,7 +11993,7 @@ output_toc (file, x, labelno, mode)
else
abort ();
- STRIP_NAME_ENCODING (real_name, name);
+ real_name = (*targetm.strip_name_encoding) (name);
if (TARGET_MINIMAL_TOC)
fputs (TARGET_32BIT ? "\t.long " : DOUBLE_INT_ASM_OP, file);
else
@@ -10368,7 +12129,7 @@ rs6000_gen_section_name (buf, filename, section_desc)
}
len = strlen (after_last_slash) + strlen (section_desc) + 2;
- *buf = (char *) permalloc (len);
+ *buf = (char *) xmalloc (len);
p = *buf;
*p++ = '_';
@@ -10407,7 +12168,7 @@ output_profile_hook (labelno)
rtx fun;
ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
- STRIP_NAME_ENCODING (label_name, ggc_strdup (buf));
+ label_name = (*targetm.strip_name_encoding) (ggc_strdup (buf));
fun = gen_rtx_SYMBOL_REF (Pmode, label_name);
emit_library_call (init_one_libfunc (RS6000_MCOUNT), 0, VOIDmode, 1,
@@ -10546,18 +12307,24 @@ rs6000_adjust_cost (insn, link, dep_insn, cost)
switch (get_attr_type (insn))
{
case TYPE_JMPREG:
- /* Tell the first scheduling pass about the latency between
+ /* Tell the first scheduling pass about the latency between
a mtctr and bctr (and mtlr and br/blr). The first
scheduling pass will not know about this latency since
the mtctr instruction, which has the latency associated
to it, will be generated by reload. */
- return TARGET_POWER ? 5 : 4;
+ return TARGET_POWER ? 5 : 4;
case TYPE_BRANCH:
/* Leave some extra cycles between a compare and its
dependent branch, to inhibit expensive mispredicts. */
- if ((rs6000_cpu_attr == CPU_PPC750
- || rs6000_cpu_attr == CPU_PPC7400
- || rs6000_cpu_attr == CPU_PPC7450)
+ if ((rs6000_cpu_attr == CPU_PPC603
+ || rs6000_cpu_attr == CPU_PPC604
+ || rs6000_cpu_attr == CPU_PPC604E
+ || rs6000_cpu_attr == CPU_PPC620
+ || rs6000_cpu_attr == CPU_PPC630
+ || rs6000_cpu_attr == CPU_PPC750
+ || rs6000_cpu_attr == CPU_PPC7400
+ || rs6000_cpu_attr == CPU_PPC7450
+ || rs6000_cpu_attr == CPU_POWER4)
&& recog_memoized (dep_insn)
&& (INSN_CODE (dep_insn) >= 0)
&& (get_attr_type (dep_insn) == TYPE_COMPARE
@@ -10638,6 +12405,7 @@ rs6000_issue_rate ()
case CPU_PPC604E:
case CPU_PPC620:
case CPU_PPC630:
+ case CPU_POWER4:
return 4;
default:
return 1;
@@ -10730,12 +12498,13 @@ rs6000_initialize_trampoline (addr, fnaddr, cxt)
const struct attribute_spec rs6000_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
- { "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute },
- { NULL, 0, 0, false, false, false, NULL }
+ { "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute },
+ { "shortcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute },
+ { NULL, 0, 0, false, false, false, NULL }
};
-/* Handle a "longcall" attribute; arguments as in struct
- attribute_spec.handler. */
+/* Handle a "longcall" or "shortcall" attribute; arguments as in
+ struct attribute_spec.handler. */
static tree
rs6000_handle_longcall_attribute (node, name, args, flags, no_add_attrs)
@@ -10757,6 +12526,20 @@ rs6000_handle_longcall_attribute (node, name, args, flags, no_add_attrs)
return NULL_TREE;
}
+/* Set longcall attributes on all functions declared when
+ rs6000_default_long_calls is true. */
+static void
+rs6000_set_default_type_attributes (type)
+ tree type;
+{
+ if (rs6000_default_long_calls
+ && (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE))
+ TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("longcall"),
+ NULL_TREE,
+ TYPE_ATTRIBUTES (type));
+}
+
/* Return a reference suitable for calling a function with the
longcall attribute. */
@@ -10785,6 +12568,8 @@ rs6000_longcall_ref (call_ref)
}
+#ifdef USING_ELFOS_H
+
/* 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
@@ -10794,22 +12579,16 @@ rs6000_longcall_ref (call_ref)
Do not define this macro if you put all constants in the read-only
data section. */
-#ifdef USING_ELFOS_H
-
-void
-rs6000_select_rtx_section (mode, x)
+static void
+rs6000_elf_select_rtx_section (mode, x, align)
enum machine_mode mode;
rtx x;
+ unsigned HOST_WIDE_INT align;
{
if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode))
toc_section ();
- else if (flag_pic
- && (GET_CODE (x) == SYMBOL_REF
- || GET_CODE (x) == LABEL_REF
- || GET_CODE (x) == CONST))
- data_section ();
else
- const_section ();
+ default_elf_select_rtx_section (mode, x, align);
}
/* A C statement or statements to switch to the appropriate
@@ -10817,46 +12596,14 @@ rs6000_select_rtx_section (mode, x)
or a constant of some sort. RELOC indicates whether forming
the initial value of DECL requires link-time relocations. */
-void
-rs6000_select_section (decl, reloc)
+static void
+rs6000_elf_select_section (decl, reloc, align)
tree decl;
int reloc;
+ unsigned HOST_WIDE_INT align;
{
- int size = int_size_in_bytes (TREE_TYPE (decl));
- int needs_sdata;
- int readonly;
- static void (* const sec_funcs[4]) PARAMS ((void)) = {
- &const_section,
- &sdata2_section,
- &data_section,
- &sdata_section
- };
-
- needs_sdata = (size > 0
- && size <= g_switch_value
- && rs6000_sdata != SDATA_NONE
- && (rs6000_sdata != SDATA_DATA || TREE_PUBLIC (decl)));
-
- if (TREE_CODE (decl) == STRING_CST)
- readonly = ! flag_writable_strings;
- else if (TREE_CODE (decl) == VAR_DECL)
- readonly = (! ((flag_pic || DEFAULT_ABI == ABI_AIX) && reloc)
- && TREE_READONLY (decl)
- && ! TREE_SIDE_EFFECTS (decl)
- && DECL_INITIAL (decl)
- && DECL_INITIAL (decl) != error_mark_node
- && TREE_CONSTANT (DECL_INITIAL (decl)));
- else if (TREE_CODE (decl) == CONSTRUCTOR)
- readonly = (! ((flag_pic || DEFAULT_ABI == ABI_AIX) && reloc)
- && ! TREE_SIDE_EFFECTS (decl)
- && TREE_CONSTANT (decl));
- else
- readonly = ! ((flag_pic || DEFAULT_ABI == ABI_AIX) && reloc);
-
- if (needs_sdata && rs6000_sdata != SDATA_EABI)
- readonly = 0;
-
- (*sec_funcs[(readonly ? 0 : 2) + (needs_sdata ? 1 : 0)])();
+ default_elf_select_section_1 (decl, reloc, align,
+ flag_pic || DEFAULT_ABI == ABI_AIX);
}
/* A C statement to build up a unique section name, expressed as a
@@ -10865,120 +12612,18 @@ rs6000_select_section (decl, reloc)
link-time relocations. If you do not define this macro, GCC will use
the symbol name prefixed by `.' as the section name. Note - this
macro can now be called for uninitialized data items as well as
- initialised data and functions. */
+ initialized data and functions. */
-void
-rs6000_unique_section (decl, reloc)
+static void
+rs6000_elf_unique_section (decl, reloc)
tree decl;
int reloc;
{
- int len;
- int sec;
- const char *name;
- char *string;
- const char *prefix;
-
- static const char *const prefixes[7][2] =
- {
- { ".rodata.", ".gnu.linkonce.r." },
- { ".sdata2.", ".gnu.linkonce.s2." },
- { ".data.", ".gnu.linkonce.d." },
- { ".sdata.", ".gnu.linkonce.s." },
- { ".bss.", ".gnu.linkonce.b." },
- { ".sbss.", ".gnu.linkonce.sb." },
- { ".text.", ".gnu.linkonce.t." }
- };
-
- if (TREE_CODE (decl) == FUNCTION_DECL)
- sec = 6;
- else
- {
- int readonly;
- int needs_sdata;
- int size;
-
- if (TREE_CODE (decl) == STRING_CST)
- readonly = ! flag_writable_strings;
- else if (TREE_CODE (decl) == VAR_DECL)
- readonly = (! ((flag_pic || DEFAULT_ABI == ABI_AIX) && reloc)
- && TREE_READONLY (decl)
- && ! TREE_SIDE_EFFECTS (decl)
- && TREE_CONSTANT (DECL_INITIAL (decl)));
- else
- readonly = ! ((flag_pic || DEFAULT_ABI == ABI_AIX) && reloc);
-
- size = int_size_in_bytes (TREE_TYPE (decl));
- needs_sdata = (size > 0
- && size <= g_switch_value
- && rs6000_sdata != SDATA_NONE
- && (rs6000_sdata != SDATA_DATA || TREE_PUBLIC (decl)));
-
- if (DECL_INITIAL (decl) == 0
- || DECL_INITIAL (decl) == error_mark_node)
- sec = 4;
- else if (! readonly)
- sec = 2;
- else
- sec = 0;
-
- if (needs_sdata)
- {
- /* .sdata2 is only for EABI. */
- if (sec == 0 && rs6000_sdata != SDATA_EABI)
- sec = 2;
- sec += 1;
- }
- }
-
- STRIP_NAME_ENCODING (name, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
- prefix = prefixes[sec][DECL_ONE_ONLY (decl)];
- len = strlen (name) + strlen (prefix);
- string = alloca (len + 1);
-
- sprintf (string, "%s%s", prefix, name);
-
- DECL_SECTION_NAME (decl) = build_string (len, string);
-}
-
-
-static bool
-rs6000_binds_local_p (exp)
- tree exp;
-{
- bool local_p;
- tree attr;
-
- /* A non-decl is an entry in the constant pool. */
- if (!DECL_P (exp))
- local_p = true;
- /* Static variables are always local. */
- else if (! TREE_PUBLIC (exp))
- local_p = true;
- /* Otherwise, variables defined outside this object may not be local. */
- else if (DECL_EXTERNAL (exp))
- local_p = false;
- /* Linkonce and weak data are never local. */
- else if (DECL_ONE_ONLY (exp) || DECL_WEAK (exp))
- local_p = false;
- /* If PIC, then assume that any global name can be overridden by
- * symbols resolved from other modules. */
- else if (flag_pic || rs6000_flag_pic)
- local_p = false;
- /* Uninitialized COMMON variable may be unified with symbols
- * resolved from other modules. */
- else if (DECL_COMMON (exp)
- && (DECL_INITIAL (exp) == NULL
- || DECL_INITIAL (exp) == error_mark_node))
- local_p = false;
- /* Otherwise we're left with initialized (or non-common) global data
- * which is of necessity defined locally. */
- else
- local_p = true;
-
- return local_p;
+ default_unique_section_1 (decl, reloc,
+ flag_pic || DEFAULT_ABI == ABI_AIX);
}
-
+
/* 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
@@ -10987,14 +12632,18 @@ rs6000_binds_local_p (exp)
the function descriptor name. This saves a lot of overriding code
to read the prefixes. */
-void
-rs6000_encode_section_info (decl)
+static void
+rs6000_elf_encode_section_info (decl, first)
tree decl;
+ int first;
{
+ if (!first)
+ return;
+
if (TREE_CODE (decl) == FUNCTION_DECL)
{
rtx sym_ref = XEXP (DECL_RTL (decl), 0);
- if (rs6000_binds_local_p (decl))
+ if ((*targetm.binds_local_p) (decl))
SYMBOL_REF_FLAG (sym_ref) = 1;
if (DEFAULT_ABI == ABI_AIX)
@@ -11019,7 +12668,7 @@ rs6000_encode_section_info (decl)
const char *name = (char *)0;
int len = 0;
- if (rs6000_binds_local_p (decl))
+ if ((*targetm.binds_local_p) (decl))
SYMBOL_REF_FLAG (sym_ref) = 1;
if (section_name)
@@ -11048,7 +12697,6 @@ rs6000_encode_section_info (decl)
|| (len == sizeof (".PPC.EMB.sbss0") - 1
&& strcmp (name, ".PPC.EMB.sbss0") == 0))))
{
- rtx sym_ref = XEXP (DECL_RTL (decl), 0);
size_t len = strlen (XSTR (sym_ref, 0));
char *str = alloca (len + 2);
@@ -11059,6 +12707,43 @@ rs6000_encode_section_info (decl)
}
}
+static const char *
+rs6000_elf_strip_name_encoding (str)
+ const char *str;
+{
+ while (*str == '*' || *str == '@')
+ str++;
+ return str;
+}
+
+static bool
+rs6000_elf_in_small_data_p (decl)
+ tree decl;
+{
+ if (rs6000_sdata == SDATA_NONE)
+ return false;
+
+ if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl))
+ {
+ const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+ if (strcmp (section, ".sdata") == 0
+ || strcmp (section, ".sdata2") == 0
+ || strcmp (section, ".sbss") == 0)
+ return true;
+ }
+ else
+ {
+ HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
+
+ if (size > 0
+ && size <= g_switch_value
+ && (rs6000_sdata != SDATA_DATA || TREE_PUBLIC (decl)))
+ return true;
+ }
+
+ return false;
+}
+
#endif /* USING_ELFOS_H */
@@ -11106,16 +12791,9 @@ rs6000_fatal_bad_address (op)
static void
rs6000_add_gc_roots ()
{
- ggc_add_rtx_root (&rs6000_compare_op0, 1);
- ggc_add_rtx_root (&rs6000_compare_op1, 1);
-
toc_hash_table = htab_create (1021, toc_hash_function, toc_hash_eq, NULL);
ggc_add_root (&toc_hash_table, 1, sizeof (toc_hash_table),
toc_hash_mark_table);
-
-#if TARGET_MACHO
- machopic_add_gc_roots ();
-#endif
}
#if TARGET_MACHO
@@ -11177,8 +12855,7 @@ output_compiler_stub ()
{
char tmp_buf[256];
char label_buf[256];
- char *label;
- tree tmp_stub, stub;
+ tree stub;
if (!flag_pic)
for (stub = stub_list; stub; stub = TREE_CHAIN (stub))
@@ -11264,7 +12941,7 @@ output_call (insn, call_dest, operand_number)
if (no_previous_def (funname))
{
- int line_number;
+ int line_number = 0;
rtx label_rtx = gen_label_rtx ();
char *label_buf, temp_buf[256];
ASM_GENERATE_INTERNAL_LABEL (temp_buf, "L",
@@ -11324,7 +13001,7 @@ machopic_output_stub (file, symb, stub)
static int label = 0;
/* Lose our funky encoding stuff so it doesn't contaminate the stub. */
- STRIP_NAME_ENCODING (symb, symb);
+ symb = (*targetm.strip_name_encoding) (symb);
label += 1;
@@ -11444,7 +13121,9 @@ rs6000_elf_section_type_flags (decl, name, reloc)
const char *name;
int reloc;
{
- unsigned int flags = default_section_type_flags (decl, name, reloc);
+ unsigned int flags
+ = default_section_type_flags_1 (decl, name, reloc,
+ flag_pic || DEFAULT_ABI == ABI_AIX);
if (TARGET_RELOCATABLE)
flags |= SECTION_WRITE;
@@ -11522,12 +13201,215 @@ rs6000_elf_asm_out_destructor (symbol, priority)
}
#endif
-#ifdef OBJECT_FORMAT_COFF
+#if TARGET_XCOFF
static void
-xcoff_asm_named_section (name, flags)
+rs6000_xcoff_asm_globalize_label (stream, name)
+ FILE *stream;
const char *name;
- unsigned int flags ATTRIBUTE_UNUSED;
{
- fprintf (asm_out_file, "\t.csect %s\n", name);
+ fputs (GLOBAL_ASM_OP, stream);
+ RS6000_OUTPUT_BASENAME (stream, name);
+ putc ('\n', stream);
}
-#endif
+
+static void
+rs6000_xcoff_asm_named_section (name, flags)
+ const char *name;
+ unsigned int flags;
+{
+ int smclass;
+ static const char * const suffix[3] = { "PR", "RO", "RW" };
+
+ if (flags & SECTION_CODE)
+ smclass = 0;
+ else if (flags & SECTION_WRITE)
+ smclass = 2;
+ else
+ smclass = 1;
+
+ fprintf (asm_out_file, "\t.csect %s%s[%s],%u\n",
+ (flags & SECTION_CODE) ? "." : "",
+ name, suffix[smclass], flags & SECTION_ENTSIZE);
+}
+
+static void
+rs6000_xcoff_select_section (decl, reloc, align)
+ tree decl;
+ int reloc;
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+{
+ if (decl_readonly_section_1 (decl, reloc, 1))
+ {
+ if (TREE_PUBLIC (decl))
+ read_only_data_section ();
+ else
+ read_only_private_data_section ();
+ }
+ else
+ {
+ if (TREE_PUBLIC (decl))
+ data_section ();
+ else
+ private_data_section ();
+ }
+}
+
+static void
+rs6000_xcoff_unique_section (decl, reloc)
+ tree decl;
+ int reloc ATTRIBUTE_UNUSED;
+{
+ const char *name;
+
+ /* Use select_section for private and uninitialized data. */
+ if (!TREE_PUBLIC (decl)
+ || DECL_COMMON (decl)
+ || DECL_INITIAL (decl) == NULL_TREE
+ || DECL_INITIAL (decl) == error_mark_node
+ || (flag_zero_initialized_in_bss
+ && initializer_zerop (DECL_INITIAL (decl))))
+ return;
+
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ name = (*targetm.strip_name_encoding) (name);
+ DECL_SECTION_NAME (decl) = build_string (strlen (name), name);
+}
+
+/* Select section for constant in constant pool.
+
+ On RS/6000, all constants are in the private read-only data area.
+ However, if this is being placed in the TOC it must be output as a
+ toc entry. */
+
+static void
+rs6000_xcoff_select_rtx_section (mode, x, align)
+ enum machine_mode mode;
+ rtx x;
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+{
+ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode))
+ toc_section ();
+ else
+ read_only_private_data_section ();
+}
+
+/* Remove any trailing [DS] or the like from the symbol name. */
+
+static const char *
+rs6000_xcoff_strip_name_encoding (name)
+ const char *name;
+{
+ size_t len;
+ if (*name == '*')
+ name++;
+ len = strlen (name);
+ if (name[len - 1] == ']')
+ return ggc_alloc_string (name, len - 4);
+ else
+ return name;
+}
+
+/* Section attributes. AIX is always PIC. */
+
+static unsigned int
+rs6000_xcoff_section_type_flags (decl, name, reloc)
+ tree decl;
+ const char *name;
+ int reloc;
+{
+ unsigned int align;
+ unsigned int flags = default_section_type_flags_1 (decl, name, reloc, 1);
+
+ /* Align to at least UNIT size. */
+ if (flags & SECTION_CODE)
+ align = MIN_UNITS_PER_WORD;
+ else
+ /* Increase alignment of large objects if not already stricter. */
+ align = MAX ((DECL_ALIGN (decl) / BITS_PER_UNIT),
+ int_size_in_bytes (TREE_TYPE (decl)) > MIN_UNITS_PER_WORD
+ ? UNITS_PER_FP_WORD : MIN_UNITS_PER_WORD);
+
+ return flags | (exact_log2 (align) & SECTION_ENTSIZE);
+}
+
+#endif /* TARGET_XCOFF */
+
+/* Note that this is also used for PPC64 Linux. */
+
+static void
+rs6000_xcoff_encode_section_info (decl, first)
+ tree decl;
+ int first ATTRIBUTE_UNUSED;
+{
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && (*targetm.binds_local_p) (decl))
+ SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
+}
+
+/* Cross-module name binding. For AIX and PPC64 Linux, which always are
+ PIC, use private copy of flag_pic. */
+
+static bool
+rs6000_binds_local_p (decl)
+ tree decl;
+{
+ return default_binds_local_p_1 (decl, flag_pic || rs6000_flag_pic);
+}
+
+/* A C expression returning the cost of moving data from a register of class
+ CLASS1 to one of CLASS2. */
+
+int
+rs6000_register_move_cost (mode, from, to)
+ enum machine_mode mode;
+ enum reg_class from, to;
+{
+ /* Moves from/to GENERAL_REGS. */
+ if (reg_classes_intersect_p (to, GENERAL_REGS)
+ || reg_classes_intersect_p (from, GENERAL_REGS))
+ {
+ if (! reg_classes_intersect_p (to, GENERAL_REGS))
+ from = to;
+
+ if (from == FLOAT_REGS || from == ALTIVEC_REGS)
+ return (rs6000_memory_move_cost (mode, from, 0)
+ + rs6000_memory_move_cost (mode, GENERAL_REGS, 0));
+
+/* It's more expensive to move CR_REGS than CR0_REGS because of the shift...*/
+ else if (from == CR_REGS)
+ return 4;
+
+ else
+/* A move will cost one instruction per GPR moved. */
+ return 2 * HARD_REGNO_NREGS (0, mode);
+ }
+
+/* Moving between two similar registers is just one instruction. */
+ else if (reg_classes_intersect_p (to, from))
+ return mode == TFmode ? 4 : 2;
+
+/* Everything else has to go through GENERAL_REGS. */
+ else
+ return (rs6000_register_move_cost (mode, GENERAL_REGS, to)
+ + rs6000_register_move_cost (mode, from, GENERAL_REGS));
+}
+
+/* A C expressions returning the cost of moving data of MODE from a register to
+ or from memory. */
+
+int
+rs6000_memory_move_cost (mode, class, in)
+ enum machine_mode mode;
+ enum reg_class class;
+ int in ATTRIBUTE_UNUSED;
+{
+ if (reg_classes_intersect_p (class, GENERAL_REGS))
+ return 4 * HARD_REGNO_NREGS (0, mode);
+ else if (reg_classes_intersect_p (class, FLOAT_REGS))
+ return 4 * HARD_REGNO_NREGS (32, mode);
+ else if (reg_classes_intersect_p (class, ALTIVEC_REGS))
+ return 4 * HARD_REGNO_NREGS (FIRST_ALTIVEC_REGNO, mode);
+ else
+ return 4 + rs6000_register_move_cost (mode, class, GENERAL_REGS);
+}
+
diff --git a/contrib/gcc/config/rs6000/rs6000.h b/contrib/gcc/config/rs6000/rs6000.h
index 8c77dd5..957fcec 100644
--- a/contrib/gcc/config/rs6000/rs6000.h
+++ b/contrib/gcc/config/rs6000/rs6000.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler, for IBM RS/6000.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GNU CC.
@@ -46,46 +46,6 @@ Boston, MA 02111-1307, USA. */
#define TARGET_CPU_DEFAULT ((char *)0)
#endif
-/* 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: %(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} \
-%{mcpu=rios2: -D_ARCH_PWR2} \
-%{mcpu=rsc: -D_ARCH_PWR} \
-%{mcpu=rsc1: -D_ARCH_PWR} \
-%{mcpu=401: -D_ARCH_PPC} \
-%{mcpu=403: -D_ARCH_PPC} \
-%{mcpu=405: -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=603e: -D_ARCH_PPC} \
-%{mcpu=ec603e: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC} \
-%{mcpu=604e: -D_ARCH_PPC} \
-%{mcpu=620: -D_ARCH_PPC} \
-%{mcpu=740: -D_ARCH_PPC} \
-%{mcpu=7400: -D_ARCH_PPC} \
-%{mcpu=7450: -D_ARCH_PPC} \
-%{mcpu=750: -D_ARCH_PPC} \
-%{mcpu=801: -D_ARCH_PPC} \
-%{mcpu=821: -D_ARCH_PPC} \
-%{mcpu=823: -D_ARCH_PPC} \
-%{mcpu=860: -D_ARCH_PPC} \
-%{maltivec: -D__ALTIVEC__}"
-
/* Common ASM definitions used by ASM_SPEC among the various targets
for handling -mcpu=xxx switches. */
#define ASM_CPU_SPEC \
@@ -98,6 +58,8 @@ Boston, MA 02111-1307, USA. */
%{mcpu=common: -mcom} \
%{mcpu=power: -mpwr} \
%{mcpu=power2: -mpwrx} \
+%{mcpu=power3: -m604} \
+%{mcpu=power4: -mpower4} \
%{mcpu=powerpc: -mppc} \
%{mcpu=rios: -mpwr} \
%{mcpu=rios1: -mpwr} \
@@ -116,6 +78,7 @@ Boston, MA 02111-1307, USA. */
%{mcpu=604: -mppc} \
%{mcpu=604e: -mppc} \
%{mcpu=620: -mppc} \
+%{mcpu=630: -m604} \
%{mcpu=740: -mppc} \
%{mcpu=7400: -mppc} \
%{mcpu=7450: -mppc} \
@@ -124,6 +87,7 @@ Boston, MA 02111-1307, USA. */
%{mcpu=821: -mppc} \
%{mcpu=823: -mppc} \
%{mcpu=860: -mppc} \
+%{mcpu=8540: -me500} \
%{maltivec: -maltivec}"
#define CPP_DEFAULT_SPEC ""
@@ -143,7 +107,6 @@ Boston, MA 02111-1307, USA. */
#define SUBTARGET_EXTRA_SPECS
#define EXTRA_SPECS \
- { "cpp_cpu", CPP_CPU_SPEC }, \
{ "cpp_default", CPP_DEFAULT_SPEC }, \
{ "asm_cpu", ASM_CPU_SPEC }, \
{ "asm_default", ASM_DEFAULT_SPEC }, \
@@ -197,7 +160,7 @@ extern int target_flags;
/* Disable use of FPRs. */
#define MASK_SOFT_FLOAT 0x00000800
-/* Enable load/store multiple, even on powerpc */
+/* Enable load/store multiple, even on PowerPC */
#define MASK_MULTIPLE 0x00001000
#define MASK_MULTIPLE_SET 0x00002000
@@ -395,7 +358,9 @@ enum processor_type
PROCESSOR_PPC630,
PROCESSOR_PPC750,
PROCESSOR_PPC7400,
- PROCESSOR_PPC7450
+ PROCESSOR_PPC7450,
+ PROCESSOR_PPC8540,
+ PROCESSOR_POWER4
};
extern enum processor_type rs6000_cpu;
@@ -427,9 +392,18 @@ extern enum processor_type rs6000_cpu;
{"tune=", &rs6000_select[2].string, \
N_("Schedule code for given CPU") }, \
{"debug=", &rs6000_debug_name, N_("Enable debug output") }, \
+ {"traceback=", &rs6000_traceback_name, \
+ N_("Select full, part, or no traceback table") }, \
{"abi=", &rs6000_abi_string, N_("Specify ABI to use") }, \
{"long-double-", &rs6000_long_double_size_string, \
N_("Specify size of long double (64 or 128 bits)") }, \
+ {"isel=", &rs6000_isel_string, \
+ N_("Specify yes/no if isel instructions should be generated") }, \
+ {"vrsave=", &rs6000_altivec_vrsave_string, \
+ N_("Specify yes/no if VRSAVE instructions should be generated for AltiVec") }, \
+ {"longcall", &rs6000_longcall_switch, \
+ N_("Avoid all range limits on call instructions") }, \
+ {"no-longcall", &rs6000_longcall_switch, "" }, \
SUBTARGET_OPTIONS \
}
@@ -453,14 +427,30 @@ extern int rs6000_debug_arg; /* debug argument handling */
#define TARGET_DEBUG_STACK rs6000_debug_stack
#define TARGET_DEBUG_ARG rs6000_debug_arg
+extern const char *rs6000_traceback_name; /* Type of traceback table. */
+
/* These are separate from target_flags because we've run out of bits
there. */
extern const char *rs6000_long_double_size_string;
extern int rs6000_long_double_type_size;
extern int rs6000_altivec_abi;
+extern int rs6000_spe_abi;
+extern int rs6000_isel;
+extern int rs6000_fprs;
+extern const char *rs6000_isel_string;
+extern const char *rs6000_altivec_vrsave_string;
+extern int rs6000_altivec_vrsave;
+extern const char *rs6000_longcall_switch;
+extern int rs6000_default_long_calls;
#define TARGET_LONG_DOUBLE_128 (rs6000_long_double_type_size == 128)
#define TARGET_ALTIVEC_ABI rs6000_altivec_abi
+#define TARGET_ALTIVEC_VRSAVE rs6000_altivec_vrsave
+
+#define TARGET_SPE_ABI 0
+#define TARGET_SPE 0
+#define TARGET_ISEL 0
+#define TARGET_FPRS 1
/* Sometimes certain combinations of command options do not make sense
on a particular target machine. You can define a macro
@@ -480,11 +470,37 @@ extern int rs6000_altivec_abi;
/* Show we can debug even without a frame pointer. */
#define CAN_DEBUG_WITHOUT_FP
-
-/* target machine storage layout */
-/* Define to support cross compilation to an RS6000 target. */
-#define REAL_ARITHMETIC
+/* Target pragma. */
+#define REGISTER_TARGET_PRAGMAS(PFILE) do { \
+ cpp_register_pragma (PFILE, 0, "longcall", rs6000_pragma_longcall); \
+} while (0)
+
+/* Target #defines. */
+#define TARGET_CPU_CPP_BUILTINS() \
+ rs6000_cpu_cpp_builtins (pfile)
+
+/* This is used by rs6000_cpu_cpp_builtins to indicate the byte order
+ we're compiling for. Some configurations may need to override it. */
+#define RS6000_CPU_CPP_ENDIAN_BUILTINS() \
+ do \
+ { \
+ if (BYTES_BIG_ENDIAN) \
+ { \
+ builtin_define ("__BIG_ENDIAN__"); \
+ builtin_define ("_BIG_ENDIAN"); \
+ builtin_assert ("machine=bigendian"); \
+ } \
+ else \
+ { \
+ builtin_define ("__LITTLE_ENDIAN__"); \
+ builtin_define ("_LITTLE_ENDIAN"); \
+ builtin_assert ("machine=littleendian"); \
+ } \
+ } \
+ while (0)
+
+/* Target machine storage layout. */
/* 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,
@@ -522,21 +538,18 @@ extern int rs6000_altivec_abi;
instructions for them. Might as well be consistent with bits and bytes. */
#define WORDS_BIG_ENDIAN 1
-/* number of bits in an addressable storage unit */
-#define BITS_PER_UNIT 8
-
-/* Width in bits of a "word", which is the contents of a machine register.
- Note that this is not necessarily the width of data type `int';
- if using 16-bit ints on a 68000, this would still be 32.
- But on a machine with 16-bit registers, this would be 16. */
-#define BITS_PER_WORD (! TARGET_POWERPC64 ? 32 : 64)
#define MAX_BITS_PER_WORD 64
/* Width of a word, in units (bytes). */
#define UNITS_PER_WORD (! TARGET_POWERPC64 ? 4 : 8)
+#ifdef IN_LIBGCC2
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+#else
#define MIN_UNITS_PER_WORD 4
+#endif
#define UNITS_PER_FP_WORD 8
#define UNITS_PER_ALTIVEC_WORD 16
+#define UNITS_PER_SPE_WORD 8
/* Type used for ptrdiff_t, as a string used in a declaration. */
#define PTRDIFF_TYPE "int"
@@ -572,12 +585,6 @@ extern int rs6000_altivec_abi;
words. */
#define LONG_LONG_TYPE_SIZE 64
-/* A C expression for the size in bits of the type `char' on the
- target machine. If you don't define this, the default is one
- quarter of a word. (If this would be less than one storage unit,
- it is rounded up to one unit.) */
-#define CHAR_TYPE_SIZE BITS_PER_UNIT
-
/* A C expression for the size in bits of the type `float' on the
target machine. If you don't define this, the default is one
word. */
@@ -627,7 +634,8 @@ extern int rs6000_altivec_abi;
local store. TYPE is the data type, and ALIGN is the alignment
that the object would ordinarily have. */
#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
- ((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : ALIGN)
+ ((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \
+ (TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE) ? 64 : ALIGN)
/* Alignment of field after `int : 0' in a structure. */
#define EMPTY_FIELD_BOUNDARY 32
@@ -635,7 +643,19 @@ extern int rs6000_altivec_abi;
/* Every structure's size must be a multiple of this. */
#define STRUCTURE_SIZE_BOUNDARY 8
-/* A bitfield declared as `int' forces `int' alignment for the struct. */
+/* Return 1 if a structure or array containing FIELD should be
+ accessed using `BLKMODE'.
+
+ For the SPE, simd types are V2SI, and gcc can be tempted to put the
+ entire thing in a DI and use subregs to access the internals.
+ store_bit_field() will force (subreg:DI (reg:V2SI x))'s to the
+ back-end. Because a single GPR can hold a V2SI, but not a DI, the
+ best thing to do is set structs to BLKmode and avoid Severe Tire
+ Damage. */
+#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \
+ (TARGET_SPE && TREE_CODE (TREE_TYPE (FIELD)) == VECTOR_TYPE)
+
+/* A bit-field declared as `int' forces `int' alignment for the struct. */
#define PCC_BITFIELD_TYPE_MATTERS 1
/* Make strings word-aligned so strcpy from constants will be faster.
@@ -649,12 +669,12 @@ extern int rs6000_altivec_abi;
/* Make arrays of chars word-aligned for the same reasons.
Align vectors to 128 bits. */
#define DATA_ALIGNMENT(TYPE, ALIGN) \
- (TREE_CODE (TYPE) == VECTOR_TYPE ? 128 \
+ (TREE_CODE (TYPE) == VECTOR_TYPE ? (TARGET_SPE_ABI ? 64 : 128) \
: TREE_CODE (TYPE) == ARRAY_TYPE \
&& TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
&& (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
-/* Non-zero if move instructions will actually fail to work
+/* Nonzero if move instructions will actually fail to work
when given unaligned data. */
#define STRICT_ALIGNMENT 0
@@ -663,7 +683,8 @@ extern int rs6000_altivec_abi;
emulated in a trap handler. */
#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) \
(STRICT_ALIGNMENT \
- || (((MODE) == SFmode || (MODE) == DFmode || (MODE) == DImode) \
+ || (((MODE) == SFmode || (MODE) == DFmode || (MODE) == TFmode \
+ || (MODE) == DImode) \
&& (ALIGN) < 32))
/* Standard register usage. */
@@ -688,7 +709,7 @@ extern int rs6000_altivec_abi;
a register, in order to work around problems in allocating stack storage
in inline functions. */
-#define FIRST_PSEUDO_REGISTER 110
+#define FIRST_PSEUDO_REGISTER 113
/* This must be included for pre gcc 3.0 glibc compatibility. */
#define PRE_GCC3_DWARF_FRAME_REGISTERS 77
@@ -712,7 +733,8 @@ extern int rs6000_altivec_abi;
/* AltiVec registers. */ \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- 1 \
+ 1, 1 \
+ , 1, 1 \
}
/* 1 for registers not available across function calls.
@@ -731,7 +753,8 @@ extern int rs6000_altivec_abi;
/* AltiVec registers. */ \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- 1 \
+ 1, 1 \
+ , 1, 1 \
}
/* Like `CALL_USED_REGISTERS' except this macro doesn't require that
@@ -749,7 +772,8 @@ extern int rs6000_altivec_abi;
/* AltiVec registers. */ \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- 0 \
+ 0, 0 \
+ , 0, 0 \
}
#define MQ_REGNO 64
@@ -764,6 +788,9 @@ extern int rs6000_altivec_abi;
#define LAST_ALTIVEC_REGNO 108
#define TOTAL_ALTIVEC_REGS (LAST_ALTIVEC_REGNO - FIRST_ALTIVEC_REGNO + 1)
#define VRSAVE_REGNO 109
+#define VSCR_REGNO 110
+#define SPE_ACC_REGNO 111
+#define SPEFSCR_REGNO 112
/* List the order in which to allocate registers. Each register must be
listed once, even those in FIXED_REGISTERS.
@@ -786,7 +813,8 @@ extern int rs6000_altivec_abi;
mq (not saved; best to use it if we can)
ctr (not saved; when we have the choice ctr is better)
lr (saved)
- cr5, r1, r2, ap, xer, vrsave (fixed)
+ cr5, r1, r2, ap, xer, vrsave, vscr (fixed)
+ spe_acc, spefscr (fixed)
AltiVec registers:
v0 - v1 (not saved or used for anything)
@@ -817,7 +845,8 @@ extern int rs6000_altivec_abi;
79, \
96, 95, 94, 93, 92, 91, \
108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, \
- 97, 109 \
+ 97, 109, 110 \
+ , 111, 112 \
}
/* True if register is floating-point. */
@@ -832,6 +861,9 @@ extern int rs6000_altivec_abi;
/* True if register is an integer register. */
#define INT_REGNO_P(N) ((N) <= 31 || (N) == ARG_POINTER_REGNUM)
+/* SPE SIMD registers are just the GPRs. */
+#define SPE_SIMD_REGNO_P(N) ((N) <= 31)
+
/* True if register is the XER register. */
#define XER_REGNO_P(N) ((N) == XER_REGNO)
@@ -843,28 +875,41 @@ extern int rs6000_altivec_abi;
This is ordinarily the length in words of a value of mode MODE
but can be less for certain modes in special long registers.
+ For the SPE, GPRs are 64 bits but only 32 bits are visible in
+ scalar instructions. The upper 32 bits are only available to the
+ SIMD instructions.
+
POWER and PowerPC GPRs hold 32 bits worth;
PowerPC64 GPRs and FPRs point register holds 64 bits worth. */
#define HARD_REGNO_NREGS(REGNO, MODE) \
(FP_REGNO_P (REGNO) \
? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
+ : (SPE_SIMD_REGNO_P (REGNO) && TARGET_SPE && SPE_VECTOR_MODE (MODE)) \
+ ? ((GET_MODE_SIZE (MODE) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD) \
: ALTIVEC_REGNO_P (REGNO) \
? ((GET_MODE_SIZE (MODE) + UNITS_PER_ALTIVEC_WORD - 1) / UNITS_PER_ALTIVEC_WORD) \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
#define ALTIVEC_VECTOR_MODE(MODE) \
- ((MODE) == V16QImode \
- || (MODE) == V8HImode \
- || (MODE) == V4SFmode \
- || (MODE) == V4SImode)
+ ((MODE) == V16QImode \
+ || (MODE) == V8HImode \
+ || (MODE) == V4SFmode \
+ || (MODE) == V4SImode)
+
+#define SPE_VECTOR_MODE(MODE) \
+ ((MODE) == V4HImode \
+ || (MODE) == V2SFmode \
+ || (MODE) == V1DImode \
+ || (MODE) == V2SImode)
/* Define this macro to be nonzero if the port is prepared to handle
insns involving vector mode MODE. At the very least, it must have
move patterns for this mode. */
-#define VECTOR_MODE_SUPPORTED_P(MODE) \
- (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (MODE))
+#define VECTOR_MODE_SUPPORTED_P(MODE) \
+ ((TARGET_SPE && SPE_VECTOR_MODE (MODE)) \
+ || (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (MODE)))
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
For POWER and PowerPC, the GPRs can hold any mode, but the float
@@ -878,10 +923,10 @@ extern int rs6000_altivec_abi;
|| (GET_MODE_CLASS (MODE) == MODE_INT \
&& GET_MODE_SIZE (MODE) == UNITS_PER_FP_WORD)) \
: ALTIVEC_REGNO_P (REGNO) ? ALTIVEC_VECTOR_MODE (MODE) \
+ : SPE_SIMD_REGNO_P (REGNO) && TARGET_SPE && SPE_VECTOR_MODE (MODE) ? 1 \
: CR_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_CC \
: XER_REGNO_P (REGNO) ? (MODE) == PSImode \
- : ! INT_REGNO_P (REGNO) ? (GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) <= UNITS_PER_WORD) \
+ : ! INT_REGNO_P (REGNO) ? GET_MODE_SIZE (MODE) <= UNITS_PER_WORD \
: 1)
/* Value is 1 if it is a good idea to tie two pseudo registers
@@ -904,35 +949,14 @@ extern int rs6000_altivec_abi;
: 1)
/* A C expression returning the cost of moving data from a register of class
- CLASS1 to one of CLASS2.
-
- On the RS/6000, copying between floating-point and fixed-point
- registers is expensive. */
-
-#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
- ((CLASS1) == FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 2 \
- : (CLASS1) == FLOAT_REGS && (CLASS2) != FLOAT_REGS ? 10 \
- : (CLASS1) != FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 10 \
- : (CLASS1) == ALTIVEC_REGS && (CLASS2) != ALTIVEC_REGS ? 20 \
- : (CLASS1) != ALTIVEC_REGS && (CLASS2) == ALTIVEC_REGS ? 20 \
- : (((CLASS1) == SPECIAL_REGS || (CLASS1) == MQ_REGS \
- || (CLASS1) == LINK_REGS || (CLASS1) == CTR_REGS \
- || (CLASS1) == LINK_OR_CTR_REGS) \
- && ((CLASS2) == SPECIAL_REGS || (CLASS2) == MQ_REGS \
- || (CLASS2) == LINK_REGS || (CLASS2) == CTR_REGS \
- || (CLASS2) == LINK_OR_CTR_REGS)) ? 10 \
- : 2)
+ CLASS1 to one of CLASS2. */
-/* A C expressions returning the cost of moving data of MODE from a register to
- or from memory.
+#define REGISTER_MOVE_COST rs6000_register_move_cost
- On the RS/6000, bump this up a bit. */
+/* A C expressions returning the cost of moving data of MODE from a register to
+ or from memory. */
-#define MEMORY_MOVE_COST(MODE, CLASS, IN) \
- ((GET_MODE_CLASS (MODE) == MODE_FLOAT \
- && (rs6000_cpu == PROCESSOR_RIOS1 || rs6000_cpu == PROCESSOR_PPC601) \
- ? 3 : 2) \
- + 4)
+#define MEMORY_MOVE_COST rs6000_memory_move_cost
/* Specify the cost of a branch insn; roughly the number of extra insns that
should be added to avoid a branch.
@@ -942,6 +966,20 @@ extern int rs6000_altivec_abi;
#define BRANCH_COST 3
+
+/* A fixed register used at prologue and epilogue generation to fix
+ addressing modes. The SPE needs heavy addressing fixes at the last
+ minute, and it's best to save a register for it.
+
+ AltiVec also needs fixes, but we've gotten around using r11, which
+ is actually wrong because when use_backchain_to_restore_sp is true,
+ we end up clobbering r11.
+
+ The AltiVec case needs to be fixed. Dunno if we should break ABI
+ compatability and reserve a register for it as well.. */
+
+#define FIXED_SCRATCH (TARGET_SPE ? 14 : 11)
+
/* Define this macro to change register usage conditional on target flags.
Set MQ register fixed (already call_used) if not POWER architecture
(RIOS1, RIOS2, RSC, and PPC601) so that it will not be allocated.
@@ -956,12 +994,16 @@ extern int rs6000_altivec_abi;
if (TARGET_64BIT) \
fixed_regs[13] = call_used_regs[13] \
= call_really_used_regs[13] = 1; \
- if (TARGET_SOFT_FLOAT) \
+ if (TARGET_SOFT_FLOAT || !TARGET_FPRS) \
for (i = 32; i < 64; i++) \
fixed_regs[i] = call_used_regs[i] \
= call_really_used_regs[i] = 1; \
if (DEFAULT_ABI == ABI_V4 \
&& PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM \
+ && flag_pic == 2) \
+ fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1; \
+ if (DEFAULT_ABI == ABI_V4 \
+ && PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM \
&& flag_pic == 1) \
fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] \
= call_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] \
@@ -972,6 +1014,15 @@ extern int rs6000_altivec_abi;
= fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] \
= call_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] \
= call_really_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1; \
+ if (TARGET_ALTIVEC) \
+ global_regs[VSCR_REGNO] = 1; \
+ if (TARGET_SPE) \
+ { \
+ global_regs[SPEFSCR_REGNO] = 1; \
+ fixed_regs[FIXED_SCRATCH] \
+ = call_used_regs[FIXED_SCRATCH] \
+ = call_really_used_regs[FIXED_SCRATCH] = 1; \
+ } \
if (! TARGET_ALTIVEC) \
{ \
for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i) \
@@ -1056,6 +1107,9 @@ enum reg_class
FLOAT_REGS,
ALTIVEC_REGS,
VRSAVE_REGS,
+ VSCR_REGS,
+ SPE_ACC_REGS,
+ SPEFSCR_REGS,
NON_SPECIAL_REGS,
MQ_REGS,
LINK_REGS,
@@ -1083,6 +1137,9 @@ enum reg_class
"FLOAT_REGS", \
"ALTIVEC_REGS", \
"VRSAVE_REGS", \
+ "VSCR_REGS", \
+ "SPE_ACC_REGS", \
+ "SPEFSCR_REGS", \
"NON_SPECIAL_REGS", \
"MQ_REGS", \
"LINK_REGS", \
@@ -1109,6 +1166,9 @@ enum reg_class
{ 0x00000000, 0xffffffff, 0x00000000, 0x00000000 }, /* FLOAT_REGS */ \
{ 0x00000000, 0x00000000, 0xffffe000, 0x00001fff }, /* ALTIVEC_REGS */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00002000 }, /* VRSAVE_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00004000 }, /* VSCR_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00008000 }, /* SPE_ACC_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00010000 }, /* SPEFSCR_REGS */ \
{ 0xffffffff, 0xffffffff, 0x00000008, 0x00000000 }, /* NON_SPECIAL_REGS */ \
{ 0x00000000, 0x00000000, 0x00000001, 0x00000000 }, /* MQ_REGS */ \
{ 0x00000000, 0x00000000, 0x00000002, 0x00000000 }, /* LINK_REGS */ \
@@ -1141,6 +1201,9 @@ enum reg_class
: (REGNO) == ARG_POINTER_REGNUM ? BASE_REGS \
: (REGNO) == XER_REGNO ? XER_REGS \
: (REGNO) == VRSAVE_REGNO ? VRSAVE_REGS \
+ : (REGNO) == VSCR_REGNO ? VRSAVE_REGS \
+ : (REGNO) == SPE_ACC_REGNO ? SPE_ACC_REGS \
+ : (REGNO) == SPEFSCR_REGNO ? SPEFSCR_REGS \
: NO_REGS)
/* The class value for index registers, and the one for base regs. */
@@ -1169,8 +1232,8 @@ enum reg_class
Return 1 if VALUE is in the range specified by C.
`I' is a signed 16-bit constant
- `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
+ `J' is a constant with only the high-order 16 bits nonzero
+ `K' is a constant with only the low-order 16 bits nonzero
`L' is a signed 16-bit constant shifted left 16 bits
`M' is a constant that is greater than 31
`N' is a positive constant that is an exact power of two
@@ -1209,7 +1272,8 @@ enum reg_class
'R' is for AIX TOC entries.
'S' is a constant that can be placed into a 64-bit mask operand
'T' is a constant that can be placed into a 32-bit mask operand
- 'U' is for V.4 small data references. */
+ 'U' is for V.4 small data references.
+ 't' is for AND masks that can be performed by two rldic{l,r} insns. */
#define EXTRA_CONSTRAINT(OP, C) \
((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \
@@ -1218,6 +1282,10 @@ enum reg_class
: (C) == 'T' ? mask_operand (OP, SImode) \
: (C) == 'U' ? (DEFAULT_ABI == ABI_V4 \
&& small_data_operand (OP, GET_MODE (OP))) \
+ : (C) == 't' ? (mask64_2_operand (OP, DImode) \
+ && (fixed_regs[CR0_REGNO] \
+ || !logical_operand (OP, DImode)) \
+ && !mask64_operand (OP, DImode)) \
: 0)
/* Given an rtx X being reloaded into a reg required to be
@@ -1273,16 +1341,16 @@ enum reg_class
? ((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 mode of the object illegally. */
-#define CLASS_CANNOT_CHANGE_MODE FLOAT_REGS
+/* Return a class of registers that cannot change FROM mode to TO mode. */
-/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE. */
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? reg_classes_intersect_p (FLOAT_REGS, CLASS) \
+ : (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1 \
+ ? reg_classes_intersect_p (GENERAL_REGS, CLASS) \
+ : 0)
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
-
/* Stack layout; function entry, exit and calling. */
/* Enumeration to give which calling sequence to use. */
@@ -1315,6 +1383,7 @@ typedef struct rs6000_stack {
int lr_save_offset; /* offset to save LR from initial SP */
int cr_save_offset; /* offset to save CR from initial SP */
int vrsave_save_offset; /* offset to save VRSAVE from initial SP */
+ int spe_gp_save_offset; /* offset to save spe 64-bit gprs */
int toc_save_offset; /* offset to save the TOC pointer */
int varargs_save_offset; /* offset to save the varargs registers */
int ehrd_offset; /* offset to EH return data */
@@ -1332,6 +1401,8 @@ typedef struct rs6000_stack {
int vrsave_size; /* size to hold VRSAVE if not in save_size */
int altivec_padding_size; /* size of altivec alignment padding if
not in save_size */
+ int spe_gp_size; /* size of 64-bit GPR save size for SPE */
+ int spe_padding_size;
int toc_size; /* size to hold TOC if not in save_size */
int total_size; /* total bytes allocated for stack */
} rs6000_stack_t;
@@ -1450,6 +1521,8 @@ typedef struct rs6000_stack {
If the precise function being called is known, FUNC is its FUNCTION_DECL;
otherwise, FUNC is 0.
+ On the SPE, both FPs and vectors are returned in r3.
+
On RS/6000 an integer value is in r3 and a floating-point value is in
fp1, unless -msoft-float. */
@@ -1458,8 +1531,13 @@ typedef struct rs6000_stack {
&& TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
|| POINTER_TYPE_P (VALTYPE) \
? word_mode : TYPE_MODE (VALTYPE), \
- TREE_CODE (VALTYPE) == VECTOR_TYPE ? ALTIVEC_ARG_RETURN \
- : TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_HARD_FLOAT \
+ TREE_CODE (VALTYPE) == VECTOR_TYPE \
+ && TARGET_ALTIVEC ? ALTIVEC_ARG_RETURN \
+ : TREE_CODE (VALTYPE) == REAL_TYPE \
+ && TARGET_SPE_ABI && !TARGET_FPRS \
+ ? GP_ARG_RETURN \
+ : TREE_CODE (VALTYPE) == REAL_TYPE \
+ && TARGET_HARD_FLOAT && TARGET_FPRS \
? FP_ARG_RETURN : GP_ARG_RETURN)
/* Define how to find the value returned by a library function
@@ -1468,7 +1546,7 @@ typedef struct rs6000_stack {
#define LIBCALL_VALUE(MODE) \
gen_rtx_REG (MODE, ALTIVEC_VECTOR_MODE (MODE) ? ALTIVEC_ARG_RETURN \
: GET_MODE_CLASS (MODE) == MODE_FLOAT \
- && TARGET_HARD_FLOAT \
+ && TARGET_HARD_FLOAT && TARGET_FPRS \
? FP_ARG_RETURN : GP_ARG_RETURN)
/* The AIX ABI for the RS/6000 specifies that all structures are
@@ -1481,13 +1559,17 @@ typedef struct rs6000_stack {
default, and -m switches get the final word. See
rs6000_override_options for more details.
+ The PPC32 SVR4 ABI uses IEEE double extended for long double, if 128-bit
+ long double support is enabled. These values are returned in memory.
+
int_size_in_bytes returns -1 for variable size objects, which go in
memory always. The cast to unsigned makes -1 > 8. */
#define RETURN_IN_MEMORY(TYPE) \
- (AGGREGATE_TYPE_P (TYPE) && \
- (TARGET_AIX_STRUCT_RET || \
- (unsigned HOST_WIDEST_INT) int_size_in_bytes (TYPE) > 8))
+ ((AGGREGATE_TYPE_P (TYPE) \
+ && (TARGET_AIX_STRUCT_RET \
+ || (unsigned HOST_WIDE_INT) int_size_in_bytes (TYPE) > 8)) \
+ || (DEFAULT_ABI == ABI_V4 && TYPE_MODE (TYPE) == TFmode))
/* DRAFT_V4_STRUCT_RET defaults off. */
#define DRAFT_V4_STRUCT_RET 0
@@ -1534,29 +1616,30 @@ typedef struct rs6000_stack {
#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 CALL_LIBCALL 0x00000010 /* libcall */
/* 1 if N is a possible register number for a function value
as seen by the caller.
On RS/6000, this is r3, fp1, and v2 (for AltiVec). */
-#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_ARG_RETURN \
- || ((N) == FP_ARG_RETURN) \
- || (TARGET_ALTIVEC && \
- (N) == ALTIVEC_ARG_RETURN))
+#define FUNCTION_VALUE_REGNO_P(N) \
+ ((N) == GP_ARG_RETURN \
+ || ((N) == FP_ARG_RETURN && TARGET_HARD_FLOAT) \
+ || ((N) == ALTIVEC_ARG_RETURN && TARGET_ALTIVEC))
/* 1 if N is a possible register number for function argument passing.
On RS/6000, these are r3-r10 and fp1-fp13.
On AltiVec, v2 - v13 are used for passing vectors. */
#define FUNCTION_ARG_REGNO_P(N) \
- (((unsigned)((N) - GP_ARG_MIN_REG) < (unsigned)(GP_ARG_NUM_REG)) \
- || (TARGET_ALTIVEC && \
- (unsigned)((N) - ALTIVEC_ARG_MIN_REG) < (unsigned)(ALTIVEC_ARG_NUM_REG)) \
- || ((unsigned)((N) - FP_ARG_MIN_REG) < (unsigned)(FP_ARG_NUM_REG)))
-
+ ((unsigned) (N) - GP_ARG_MIN_REG < GP_ARG_NUM_REG \
+ || ((unsigned) (N) - ALTIVEC_ARG_MIN_REG < ALTIVEC_ARG_NUM_REG \
+ && TARGET_ALTIVEC) \
+ || ((unsigned) (N) - FP_ARG_MIN_REG < FP_ARG_NUM_REG \
+ && TARGET_HARD_FLOAT))
/* A C structure for machine-specific, per-function data.
This is added to the cfun structure. */
-typedef struct machine_function
+typedef struct machine_function GTY(())
{
/* Whether a System V.4 varargs area was created. */
int sysv_varargs_p;
@@ -1607,13 +1690,18 @@ typedef struct rs6000_args
For a library call, FNTYPE is 0. */
#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
- init_cumulative_args (&CUM, FNTYPE, LIBNAME, FALSE)
+ init_cumulative_args (&CUM, FNTYPE, LIBNAME, FALSE, FALSE)
/* Similar, but when scanning the definition of a procedure. We always
set NARGS_PROTOTYPE large so we never return an EXPR_LIST. */
#define INIT_CUMULATIVE_INCOMING_ARGS(CUM,FNTYPE,LIBNAME) \
- init_cumulative_args (&CUM, FNTYPE, LIBNAME, TRUE)
+ init_cumulative_args (&CUM, FNTYPE, LIBNAME, TRUE, FALSE)
+
+/* Like INIT_CUMULATIVE_ARGS' but only used for outgoing libcalls. */
+
+#define INIT_CUMULATIVE_LIBCALL_ARGS(CUM, MODE, LIBNAME) \
+ init_cumulative_args (&CUM, NULL_TREE, LIBNAME, FALSE, TRUE)
/* Update the data in CUM to advance over an argument
of mode MODE and data type TYPE.
@@ -1622,13 +1710,13 @@ typedef struct rs6000_args
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
function_arg_advance (&CUM, MODE, TYPE, NAMED)
-/* Non-zero if we can use a floating-point register to pass this arg. */
+/* Nonzero if we can use a floating-point register to pass this arg. */
#define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \
(GET_MODE_CLASS (MODE) == MODE_FLOAT \
&& (CUM).fregno <= FP_ARG_MAX_REG \
- && TARGET_HARD_FLOAT)
+ && TARGET_HARD_FLOAT && TARGET_FPRS)
-/* Non-zero if we can use an AltiVec register to pass this arg. */
+/* Nonzero if we can use an AltiVec register to pass this arg. */
#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE) \
(ALTIVEC_VECTOR_MODE (MODE) \
&& (CUM).vregno <= ALTIVEC_ARG_MAX_REG \
@@ -1712,8 +1800,8 @@ typedef struct rs6000_args
(VALIST) = rs6000_build_va_list ()
/* Implement `va_start' for varargs and stdarg. */
-#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
- rs6000_va_start (stdarg, valist, nextarg)
+#define EXPAND_BUILTIN_VA_START(valist, nextarg) \
+ rs6000_va_start (valist, nextarg)
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
@@ -1731,6 +1819,10 @@ typedef struct rs6000_args
argument is passed depends on whether or not it is a named argument. */
#define STRICT_ARGUMENT_NAMING 1
+/* We do not allow indirect calls to be optimized into sibling calls, nor
+ do we allow calls with vector parameters. */
+#define FUNCTION_OK_FOR_SIBCALL(DECL) function_ok_for_sibcall ((DECL))
+
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
@@ -1741,7 +1833,7 @@ typedef struct rs6000_args
the stack pointer does not matter. No definition is equivalent to
always zero.
- On the RS/6000, this is non-zero because we can restore the stack from
+ On the RS/6000, this is nonzero because we can restore the stack from
its backpointer, which we maintain. */
#define EXIT_IGNORE_STACK 1
@@ -1755,7 +1847,7 @@ typedef struct rs6000_args
|| (TARGET_ALTIVEC && (REGNO) == VRSAVE_REGNO) \
|| (current_function_calls_eh_return \
&& TARGET_AIX \
- && (REGNO) == TOC_REGISTER))
+ && (REGNO) == 2))
/* TRAMPOLINE_TEMPLATE deleted */
@@ -1818,7 +1910,7 @@ typedef struct rs6000_args
{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
- { 30, 30} }
+ { RS6000_PIC_OFFSET_TABLE_REGNUM, RS6000_PIC_OFFSET_TABLE_REGNUM } }
/* Given FROM and TO register numbers, say whether this elimination is allowed.
Frame pointer elimination is automatically handled.
@@ -1829,10 +1921,11 @@ typedef struct rs6000_args
We need r30 if -mminimal-toc was specified, and there are constant pool
references. */
-#define CAN_ELIMINATE(FROM, TO) \
- ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM \
- ? ! frame_pointer_needed \
- : (FROM) == 30 ? ! TARGET_MINIMAL_TOC || TARGET_NO_TOC || get_pool_size () == 0 \
+#define CAN_ELIMINATE(FROM, TO) \
+ ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM \
+ ? ! frame_pointer_needed \
+ : (FROM) == RS6000_PIC_OFFSET_TABLE_REGNUM \
+ ? ! TARGET_MINIMAL_TOC || TARGET_NO_TOC || get_pool_size () == 0 \
: 1)
/* Define the offset between two registers, one to be eliminated, and the other
@@ -1847,7 +1940,7 @@ typedef struct rs6000_args
(OFFSET) = info->total_size; \
else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
(OFFSET) = (info->push_p) ? info->total_size : 0; \
- else if ((FROM) == 30) \
+ else if ((FROM) == RS6000_PIC_OFFSET_TABLE_REGNUM) \
(OFFSET) = 0; \
else \
abort (); \
@@ -1962,6 +2055,9 @@ typedef struct rs6000_args
#define TOC_RELATIVE_EXPR_P(X) (toc_relative_expr_p (X))
+/* SPE offset addressing is limited to 5-bits worth of double words. */
+#define SPE_CONST_OFFSET_OK(x) (((x) & ~0xf8) == 0)
+
#define LEGITIMATE_CONSTANT_POOL_ADDRESS_P(X) \
(TARGET_TOC \
&& GET_CODE (X) == PLUS \
@@ -1986,11 +2082,14 @@ typedef struct rs6000_args
&& LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 0) \
&& (! ALTIVEC_VECTOR_MODE (MODE) \
|| (GET_CODE (XEXP (X,1)) == CONST_INT && INTVAL (XEXP (X,1)) == 0)) \
+ && (! SPE_VECTOR_MODE (MODE) \
+ || (GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && SPE_CONST_OFFSET_OK (INTVAL (XEXP (X, 1))))) \
&& (((MODE) != DFmode && (MODE) != DImode) \
|| (TARGET_32BIT \
? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 4) \
: ! (INTVAL (XEXP (X, 1)) & 3))) \
- && ((MODE) != TImode \
+ && (((MODE) != TFmode && (MODE) != TImode) \
|| (TARGET_32BIT \
? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 12) \
: (LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 8) \
@@ -2013,7 +2112,7 @@ typedef struct rs6000_args
&& ! flag_pic && ! TARGET_TOC \
&& GET_MODE_NUNITS (MODE) == 1 \
&& (GET_MODE_BITSIZE (MODE) <= 32 \
- || (TARGET_HARD_FLOAT && (MODE) == DFmode)) \
+ || (TARGET_HARD_FLOAT && TARGET_FPRS && (MODE) == DFmode)) \
&& GET_CODE (X) == LO_SUM \
&& GET_CODE (XEXP (X, 0)) == REG \
&& INT_REG_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
@@ -2106,7 +2205,7 @@ do { \
#define RS6000_PIC_OFFSET_TABLE_REGNUM 30
#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? RS6000_PIC_OFFSET_TABLE_REGNUM : INVALID_REGNUM)
-#define TOC_REGISTER (TARGET_MINIMAL_TOC ? 30 : 2)
+#define TOC_REGISTER (TARGET_MINIMAL_TOC ? RS6000_PIC_OFFSET_TABLE_REGNUM : 2)
/* Define this macro if the register defined by
`PIC_OFFSET_TABLE_REGNUM' is clobbered by calls. Do not define
@@ -2178,7 +2277,7 @@ do { \
#define MAX_MOVE_MAX 8
/* Nonzero if access to memory by bytes is no faster than for words.
- Also non-zero if doing byte operations (specifically shifts) in registers
+ Also nonzero if doing byte operations (specifically shifts) in registers
is undesirable. */
#define SLOW_BYTE_ACCESS 1
@@ -2259,6 +2358,8 @@ do { \
? COSTS_N_INSNS (2) \
: COSTS_N_INSNS (1)); \
case MULT: \
+ if (optimize_size) \
+ return COSTS_N_INSNS (2); \
switch (rs6000_cpu) \
{ \
case PROCESSOR_RIOS1: \
@@ -2292,6 +2393,7 @@ do { \
: COSTS_N_INSNS (3)); \
case PROCESSOR_PPC403: \
case PROCESSOR_PPC604: \
+ case PROCESSOR_PPC8540: \
return COSTS_N_INSNS (4); \
case PROCESSOR_PPC620: \
case PROCESSOR_PPC630: \
@@ -2300,6 +2402,11 @@ do { \
? COSTS_N_INSNS (5) : COSTS_N_INSNS (7) \
: INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
? COSTS_N_INSNS (3) : COSTS_N_INSNS (4)); \
+ case PROCESSOR_POWER4: \
+ return (GET_CODE (XEXP (X, 1)) != CONST_INT \
+ ? GET_MODE (XEXP (X, 1)) != DImode \
+ ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4) \
+ : COSTS_N_INSNS (2)); \
} \
case DIV: \
case MOD: \
@@ -2334,10 +2441,12 @@ do { \
return COSTS_N_INSNS (20); \
case PROCESSOR_PPC620: \
case PROCESSOR_PPC630: \
+ case PROCESSOR_POWER4: \
return (GET_MODE (XEXP (X, 1)) != DImode \
? COSTS_N_INSNS (21) \
: COSTS_N_INSNS (37)); \
case PROCESSOR_PPC750: \
+ case PROCESSOR_PPC8540: \
case PROCESSOR_PPC7400: \
return COSTS_N_INSNS (19); \
case PROCESSOR_PPC7450: \
@@ -2368,18 +2477,6 @@ do { \
/* #define ADJUST_INSN_LENGTH(X,LENGTH) */
-/* Add any extra modes needed to represent the condition code.
-
- For the RS/6000, we need separate modes when unsigned (logical) comparisons
- are being done and we need a separate mode for floating-point. We also
- use a mode for the case when we are comparing the results of two
- comparisons, as then only the EQ bit is valid in the register. */
-
-#define EXTRA_CC_MODES \
- CC(CCUNSmode, "CCUNS") \
- CC(CCFPmode, "CCFP") \
- CC(CCEQmode, "CCEQ")
-
/* Given a comparison code (EQ, NE, etc.) and the first operand of a
COMPARE, return the mode to be used for the comparison. For
floating-point, CCFPmode should be used. CCUNSmode should be used
@@ -2397,7 +2494,8 @@ do { \
stored from the compare operation. Note that we can't use "rtx" here
since it hasn't been defined! */
-extern struct rtx_def *rs6000_compare_op0, *rs6000_compare_op1;
+extern GTY(()) rtx rs6000_compare_op0;
+extern GTY(()) rtx rs6000_compare_op1;
extern int rs6000_compare_fp_p;
/* Control the assembler format that we output. */
@@ -2633,6 +2731,9 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
&rs6000_reg_names[107][0], /* v30 */ \
&rs6000_reg_names[108][0], /* v31 */ \
&rs6000_reg_names[109][0], /* vrsave */ \
+ &rs6000_reg_names[110][0], /* vscr */ \
+ &rs6000_reg_names[111][0], /* spe_acc */ \
+ &rs6000_reg_names[112][0], /* spefscr */ \
}
/* print-rtl can't handle the above REGISTER_NAMES, so define the
@@ -2641,8 +2742,8 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
#define DEBUG_REGISTER_NAMES \
{ \
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ "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", \
@@ -2651,12 +2752,13 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \
"mq", "lr", "ctr", "ap", \
"cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
- "xer", \
+ "xer", \
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", \
"v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", \
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", \
"v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", \
- "vrsave" \
+ "vrsave", "vscr", \
+ "spe_acc", "spefscr" \
}
/* Table of additional register names to use in user input. */
@@ -2686,7 +2788,8 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
{"v20", 97}, {"v21", 98}, {"v22", 99}, {"v23", 100}, \
{"v24", 101},{"v25", 102},{"v26", 103},{"v27", 104}, \
{"v28", 105},{"v29", 106},{"v30", 107},{"v31", 108}, \
- {"vrsave", 109}, \
+ {"vrsave", 109}, {"vscr", 110}, \
+ {"spe_acc", 111}, {"spefscr", 112}, \
/* no additional names for: mq, lr, ctr, ap */ \
{"cr0", 68}, {"cr1", 69}, {"cr2", 70}, {"cr3", 71}, \
{"cr4", 72}, {"cr5", 73}, {"cr6", 74}, {"cr7", 75}, \
@@ -2787,12 +2890,16 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
{"non_add_cint_operand", {CONST_INT}}, \
{"and_operand", {SUBREG, REG, CONST_INT}}, \
{"and64_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
+ {"and64_2_operand", {SUBREG, REG, CONST_INT}}, \
{"logical_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
{"non_logical_cint_operand", {CONST_INT, CONST_DOUBLE}}, \
{"mask_operand", {CONST_INT}}, \
- {"mask64_operand", {CONST_INT, CONST_DOUBLE}}, \
+ {"mask_operand_wrap", {CONST_INT}}, \
+ {"mask64_operand", {CONST_INT}}, \
+ {"mask64_2_operand", {CONST_INT}}, \
{"count_register_operand", {REG}}, \
{"xer_operand", {REG}}, \
+ {"symbol_ref_operand", {SYMBOL_REF}}, \
{"call_operand", {SYMBOL_REF, REG}}, \
{"current_file_function_operand", {SYMBOL_REF}}, \
{"input_operand", {SUBREG, MEM, REG, CONST_INT, \
@@ -3032,4 +3139,238 @@ enum rs6000_builtins
ALTIVEC_BUILTIN_ABS_V4SF,
ALTIVEC_BUILTIN_ABS_V8HI,
ALTIVEC_BUILTIN_ABS_V16QI
+ /* SPE builtins. */
+ , SPE_BUILTIN_EVADDW,
+ SPE_BUILTIN_EVAND,
+ SPE_BUILTIN_EVANDC,
+ SPE_BUILTIN_EVDIVWS,
+ SPE_BUILTIN_EVDIVWU,
+ SPE_BUILTIN_EVEQV,
+ SPE_BUILTIN_EVFSADD,
+ SPE_BUILTIN_EVFSDIV,
+ SPE_BUILTIN_EVFSMUL,
+ SPE_BUILTIN_EVFSSUB,
+ SPE_BUILTIN_EVLDDX,
+ SPE_BUILTIN_EVLDHX,
+ SPE_BUILTIN_EVLDWX,
+ SPE_BUILTIN_EVLHHESPLATX,
+ SPE_BUILTIN_EVLHHOSSPLATX,
+ SPE_BUILTIN_EVLHHOUSPLATX,
+ SPE_BUILTIN_EVLWHEX,
+ SPE_BUILTIN_EVLWHOSX,
+ SPE_BUILTIN_EVLWHOUX,
+ SPE_BUILTIN_EVLWHSPLATX,
+ SPE_BUILTIN_EVLWWSPLATX,
+ SPE_BUILTIN_EVMERGEHI,
+ SPE_BUILTIN_EVMERGEHILO,
+ SPE_BUILTIN_EVMERGELO,
+ SPE_BUILTIN_EVMERGELOHI,
+ SPE_BUILTIN_EVMHEGSMFAA,
+ SPE_BUILTIN_EVMHEGSMFAN,
+ SPE_BUILTIN_EVMHEGSMIAA,
+ SPE_BUILTIN_EVMHEGSMIAN,
+ SPE_BUILTIN_EVMHEGUMIAA,
+ SPE_BUILTIN_EVMHEGUMIAN,
+ SPE_BUILTIN_EVMHESMF,
+ SPE_BUILTIN_EVMHESMFA,
+ SPE_BUILTIN_EVMHESMFAAW,
+ SPE_BUILTIN_EVMHESMFANW,
+ SPE_BUILTIN_EVMHESMI,
+ SPE_BUILTIN_EVMHESMIA,
+ SPE_BUILTIN_EVMHESMIAAW,
+ SPE_BUILTIN_EVMHESMIANW,
+ SPE_BUILTIN_EVMHESSF,
+ SPE_BUILTIN_EVMHESSFA,
+ SPE_BUILTIN_EVMHESSFAAW,
+ SPE_BUILTIN_EVMHESSFANW,
+ SPE_BUILTIN_EVMHESSIAAW,
+ SPE_BUILTIN_EVMHESSIANW,
+ SPE_BUILTIN_EVMHEUMI,
+ SPE_BUILTIN_EVMHEUMIA,
+ SPE_BUILTIN_EVMHEUMIAAW,
+ SPE_BUILTIN_EVMHEUMIANW,
+ SPE_BUILTIN_EVMHEUSIAAW,
+ SPE_BUILTIN_EVMHEUSIANW,
+ SPE_BUILTIN_EVMHOGSMFAA,
+ SPE_BUILTIN_EVMHOGSMFAN,
+ SPE_BUILTIN_EVMHOGSMIAA,
+ SPE_BUILTIN_EVMHOGSMIAN,
+ SPE_BUILTIN_EVMHOGUMIAA,
+ SPE_BUILTIN_EVMHOGUMIAN,
+ SPE_BUILTIN_EVMHOSMF,
+ SPE_BUILTIN_EVMHOSMFA,
+ SPE_BUILTIN_EVMHOSMFAAW,
+ SPE_BUILTIN_EVMHOSMFANW,
+ SPE_BUILTIN_EVMHOSMI,
+ SPE_BUILTIN_EVMHOSMIA,
+ SPE_BUILTIN_EVMHOSMIAAW,
+ SPE_BUILTIN_EVMHOSMIANW,
+ SPE_BUILTIN_EVMHOSSF,
+ SPE_BUILTIN_EVMHOSSFA,
+ SPE_BUILTIN_EVMHOSSFAAW,
+ SPE_BUILTIN_EVMHOSSFANW,
+ SPE_BUILTIN_EVMHOSSIAAW,
+ SPE_BUILTIN_EVMHOSSIANW,
+ SPE_BUILTIN_EVMHOUMI,
+ SPE_BUILTIN_EVMHOUMIA,
+ SPE_BUILTIN_EVMHOUMIAAW,
+ SPE_BUILTIN_EVMHOUMIANW,
+ SPE_BUILTIN_EVMHOUSIAAW,
+ SPE_BUILTIN_EVMHOUSIANW,
+ SPE_BUILTIN_EVMWHSMF,
+ SPE_BUILTIN_EVMWHSMFA,
+ SPE_BUILTIN_EVMWHSMI,
+ SPE_BUILTIN_EVMWHSMIA,
+ SPE_BUILTIN_EVMWHSSF,
+ SPE_BUILTIN_EVMWHSSFA,
+ SPE_BUILTIN_EVMWHUMI,
+ SPE_BUILTIN_EVMWHUMIA,
+ SPE_BUILTIN_EVMWLSMIAAW,
+ SPE_BUILTIN_EVMWLSMIANW,
+ SPE_BUILTIN_EVMWLSSIAAW,
+ SPE_BUILTIN_EVMWLSSIANW,
+ SPE_BUILTIN_EVMWLUMI,
+ SPE_BUILTIN_EVMWLUMIA,
+ SPE_BUILTIN_EVMWLUMIAAW,
+ SPE_BUILTIN_EVMWLUMIANW,
+ SPE_BUILTIN_EVMWLUSIAAW,
+ SPE_BUILTIN_EVMWLUSIANW,
+ SPE_BUILTIN_EVMWSMF,
+ SPE_BUILTIN_EVMWSMFA,
+ SPE_BUILTIN_EVMWSMFAA,
+ SPE_BUILTIN_EVMWSMFAN,
+ SPE_BUILTIN_EVMWSMI,
+ SPE_BUILTIN_EVMWSMIA,
+ SPE_BUILTIN_EVMWSMIAA,
+ SPE_BUILTIN_EVMWSMIAN,
+ SPE_BUILTIN_EVMWHSSFAA,
+ SPE_BUILTIN_EVMWSSF,
+ SPE_BUILTIN_EVMWSSFA,
+ SPE_BUILTIN_EVMWSSFAA,
+ SPE_BUILTIN_EVMWSSFAN,
+ SPE_BUILTIN_EVMWUMI,
+ SPE_BUILTIN_EVMWUMIA,
+ SPE_BUILTIN_EVMWUMIAA,
+ SPE_BUILTIN_EVMWUMIAN,
+ SPE_BUILTIN_EVNAND,
+ SPE_BUILTIN_EVNOR,
+ SPE_BUILTIN_EVOR,
+ SPE_BUILTIN_EVORC,
+ SPE_BUILTIN_EVRLW,
+ SPE_BUILTIN_EVSLW,
+ SPE_BUILTIN_EVSRWS,
+ SPE_BUILTIN_EVSRWU,
+ SPE_BUILTIN_EVSTDDX,
+ SPE_BUILTIN_EVSTDHX,
+ SPE_BUILTIN_EVSTDWX,
+ SPE_BUILTIN_EVSTWHEX,
+ SPE_BUILTIN_EVSTWHOX,
+ SPE_BUILTIN_EVSTWWEX,
+ SPE_BUILTIN_EVSTWWOX,
+ SPE_BUILTIN_EVSUBFW,
+ SPE_BUILTIN_EVXOR,
+ SPE_BUILTIN_EVABS,
+ SPE_BUILTIN_EVADDSMIAAW,
+ SPE_BUILTIN_EVADDSSIAAW,
+ SPE_BUILTIN_EVADDUMIAAW,
+ SPE_BUILTIN_EVADDUSIAAW,
+ SPE_BUILTIN_EVCNTLSW,
+ SPE_BUILTIN_EVCNTLZW,
+ SPE_BUILTIN_EVEXTSB,
+ SPE_BUILTIN_EVEXTSH,
+ SPE_BUILTIN_EVFSABS,
+ SPE_BUILTIN_EVFSCFSF,
+ SPE_BUILTIN_EVFSCFSI,
+ SPE_BUILTIN_EVFSCFUF,
+ SPE_BUILTIN_EVFSCFUI,
+ SPE_BUILTIN_EVFSCTSF,
+ SPE_BUILTIN_EVFSCTSI,
+ SPE_BUILTIN_EVFSCTSIZ,
+ SPE_BUILTIN_EVFSCTUF,
+ SPE_BUILTIN_EVFSCTUI,
+ SPE_BUILTIN_EVFSCTUIZ,
+ SPE_BUILTIN_EVFSNABS,
+ SPE_BUILTIN_EVFSNEG,
+ SPE_BUILTIN_EVMRA,
+ SPE_BUILTIN_EVNEG,
+ SPE_BUILTIN_EVRNDW,
+ SPE_BUILTIN_EVSUBFSMIAAW,
+ SPE_BUILTIN_EVSUBFSSIAAW,
+ SPE_BUILTIN_EVSUBFUMIAAW,
+ SPE_BUILTIN_EVSUBFUSIAAW,
+ SPE_BUILTIN_EVADDIW,
+ SPE_BUILTIN_EVLDD,
+ SPE_BUILTIN_EVLDH,
+ SPE_BUILTIN_EVLDW,
+ SPE_BUILTIN_EVLHHESPLAT,
+ SPE_BUILTIN_EVLHHOSSPLAT,
+ SPE_BUILTIN_EVLHHOUSPLAT,
+ SPE_BUILTIN_EVLWHE,
+ SPE_BUILTIN_EVLWHOS,
+ SPE_BUILTIN_EVLWHOU,
+ SPE_BUILTIN_EVLWHSPLAT,
+ SPE_BUILTIN_EVLWWSPLAT,
+ SPE_BUILTIN_EVRLWI,
+ SPE_BUILTIN_EVSLWI,
+ SPE_BUILTIN_EVSRWIS,
+ SPE_BUILTIN_EVSRWIU,
+ SPE_BUILTIN_EVSTDD,
+ SPE_BUILTIN_EVSTDH,
+ SPE_BUILTIN_EVSTDW,
+ SPE_BUILTIN_EVSTWHE,
+ SPE_BUILTIN_EVSTWHO,
+ SPE_BUILTIN_EVSTWWE,
+ SPE_BUILTIN_EVSTWWO,
+ SPE_BUILTIN_EVSUBIFW,
+
+ /* Compares. */
+ SPE_BUILTIN_EVCMPEQ,
+ SPE_BUILTIN_EVCMPGTS,
+ SPE_BUILTIN_EVCMPGTU,
+ SPE_BUILTIN_EVCMPLTS,
+ SPE_BUILTIN_EVCMPLTU,
+ SPE_BUILTIN_EVFSCMPEQ,
+ SPE_BUILTIN_EVFSCMPGT,
+ SPE_BUILTIN_EVFSCMPLT,
+ SPE_BUILTIN_EVFSTSTEQ,
+ SPE_BUILTIN_EVFSTSTGT,
+ SPE_BUILTIN_EVFSTSTLT,
+
+ /* EVSEL compares. */
+ SPE_BUILTIN_EVSEL_CMPEQ,
+ SPE_BUILTIN_EVSEL_CMPGTS,
+ SPE_BUILTIN_EVSEL_CMPGTU,
+ SPE_BUILTIN_EVSEL_CMPLTS,
+ SPE_BUILTIN_EVSEL_CMPLTU,
+ SPE_BUILTIN_EVSEL_FSCMPEQ,
+ SPE_BUILTIN_EVSEL_FSCMPGT,
+ SPE_BUILTIN_EVSEL_FSCMPLT,
+ SPE_BUILTIN_EVSEL_FSTSTEQ,
+ SPE_BUILTIN_EVSEL_FSTSTGT,
+ SPE_BUILTIN_EVSEL_FSTSTLT,
+
+ SPE_BUILTIN_EVSPLATFI,
+ SPE_BUILTIN_EVSPLATI,
+ SPE_BUILTIN_EVMWHSSMAA,
+ SPE_BUILTIN_EVMWHSMFAA,
+ SPE_BUILTIN_EVMWHSMIAA,
+ SPE_BUILTIN_EVMWHUSIAA,
+ SPE_BUILTIN_EVMWHUMIAA,
+ SPE_BUILTIN_EVMWHSSFAN,
+ SPE_BUILTIN_EVMWHSSIAN,
+ SPE_BUILTIN_EVMWHSMFAN,
+ SPE_BUILTIN_EVMWHSMIAN,
+ SPE_BUILTIN_EVMWHUSIAN,
+ SPE_BUILTIN_EVMWHUMIAN,
+ SPE_BUILTIN_EVMWHGSSFAA,
+ SPE_BUILTIN_EVMWHGSMFAA,
+ SPE_BUILTIN_EVMWHGSMIAA,
+ SPE_BUILTIN_EVMWHGUMIAA,
+ SPE_BUILTIN_EVMWHGSSFAN,
+ SPE_BUILTIN_EVMWHGSMFAN,
+ SPE_BUILTIN_EVMWHGSMIAN,
+ SPE_BUILTIN_EVMWHGUMIAN,
+ SPE_BUILTIN_MTSPEFSCR,
+ SPE_BUILTIN_MFSPEFSCR,
+ SPE_BUILTIN_BRINC
};
diff --git a/contrib/gcc/config/rs6000/rs6000.md b/contrib/gcc/config/rs6000/rs6000.md
index ec16c19..4c95031 100644
--- a/contrib/gcc/config/rs6000/rs6000.md
+++ b/contrib/gcc/config/rs6000/rs6000.md
@@ -1,6 +1,6 @@
;; Machine description for IBM RISC System 6000 (POWER) for GNU C compiler
;; Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;; 1999, 2000, 2001 Free Software Foundation, Inc.
+;; 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
;; This file is part of GNU CC.
@@ -32,6 +32,8 @@
;; 8 movsi_got
;; 9/v eh_reg_restore
;; 10 fctiwz
+;; 15 load_macho_picbase
+;; 16 macho_correct_pic
;; 19 movesi_from_cr
;; 20 movesi_to_cr
@@ -56,7 +58,7 @@
;; Processor type -- this attribute must exactly match the processor_type
;; enumeration in rs6000.h.
-(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450"
+(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,power4"
(const (symbol_ref "rs6000_cpu_attr")))
; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
@@ -375,42 +377,52 @@
(and (eq_attr "type" "cr_logical")
(eq_attr "cpu" "ppc7450"))
1 1)
+
(define_function_unit "vec_alu2" 2 0
(and (eq_attr "type" "vecsimple")
(eq_attr "cpu" "ppc7450"))
1 2 [(eq_attr "type" "vecsimple")])
+
(define_function_unit "vec_alu2" 2 0
(and (eq_attr "type" "vecsimple")
(eq_attr "cpu" "ppc7450"))
1 1 [(eq_attr "type" "!vecsimple")])
+
(define_function_unit "vec_alu2" 2 0
(and (eq_attr "type" "veccomplex")
(eq_attr "cpu" "ppc7450"))
4 2 [(eq_attr "type" "veccomplex")])
+
(define_function_unit "vec_alu2" 2 0
(and (eq_attr "type" "veccomplex")
(eq_attr "cpu" "ppc7450"))
4 1 [(eq_attr "type" "!veccomplex")])
+
(define_function_unit "vec_alu2" 2 0
(and (eq_attr "type" "veccmp")
(eq_attr "cpu" "ppc7450"))
2 2 [(eq_attr "type" "veccmp")])
+
(define_function_unit "vec_alu2" 2 0
(and (eq_attr "type" "veccmp")
(eq_attr "cpu" "ppc7450"))
2 1 [(eq_attr "type" "!veccmp")])
+
(define_function_unit "vec_alu2" 2 0
(and (eq_attr "type" "vecfloat")
(eq_attr "cpu" "ppc7450"))
4 2 [(eq_attr "type" "vecfloat")])
+
(define_function_unit "vec_alu2" 2 0
(and (eq_attr "type" "vecfloat")
(eq_attr "cpu" "ppc7450"))
4 1 [(eq_attr "type" "!vecfloat")])
+
(define_function_unit "vec_alu2" 2 0
(and (eq_attr "type" "vecperm")
(eq_attr "cpu" "ppc7450"))
2 2 [(eq_attr "type" "vecperm")])
+
(define_function_unit "vec_alu2" 2 0
(and (eq_attr "type" "vecperm")
(eq_attr "cpu" "ppc7450"))
@@ -489,7 +501,7 @@
(define_function_unit "iu" 1 0
(and (eq_attr "type" "compare,delayed_compare")
- (eq_attr "cpu" "rs64a,mpccore,ppc403,ppc405,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630"))
+ (eq_attr "cpu" "rs64a,mpccore,ppc403,ppc405,ppc601,ppc603"))
3 1)
; some extra cycles added by TARGET_SCHED_ADJUST_COST between compare
@@ -533,7 +545,7 @@
; fp compare uses fp unit
(define_function_unit "fpu" 1 0
(and (eq_attr "type" "fpcompare")
- (eq_attr "cpu" "rs64a,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630"))
+ (eq_attr "cpu" "rs64a,ppc601,ppc603,ppc604,ppc604e,ppc620"))
5 1)
(define_function_unit "fpu" 1 0
@@ -699,22 +711,12 @@
; RIOS2 has two symmetric FPUs.
(define_function_unit "fpu2" 2 0
- (and (eq_attr "type" "fp")
- (eq_attr "cpu" "rios2"))
- 2 1)
-
-(define_function_unit "fpu2" 2 0
- (and (eq_attr "type" "fp")
- (eq_attr "cpu" "ppc630"))
- 3 1)
-
-(define_function_unit "fpu2" 2 0
- (and (eq_attr "type" "dmul")
+ (and (eq_attr "type" "fp,dmul")
(eq_attr "cpu" "rios2"))
2 1)
(define_function_unit "fpu2" 2 0
- (and (eq_attr "type" "dmul")
+ (and (eq_attr "type" "fp,dmul")
(eq_attr "cpu" "ppc630"))
3 1)
@@ -748,6 +750,109 @@
(eq_attr "cpu" "ppc630"))
26 26)
+;; Power4
+(define_function_unit "lsu2" 2 0
+ (and (eq_attr "type" "load")
+ (eq_attr "cpu" "power4"))
+ 3 1)
+
+(define_function_unit "lsu2" 2 0
+ (and (eq_attr "type" "fpload")
+ (eq_attr "cpu" "power4"))
+ 5 1)
+
+(define_function_unit "lsu2" 2 0
+ (and (eq_attr "type" "store,fpstore")
+ (eq_attr "cpu" "power4"))
+ 1 1)
+
+(define_function_unit "iu2" 2 0
+ (and (eq_attr "type" "integer")
+ (eq_attr "cpu" "power4"))
+ 2 1)
+
+(define_function_unit "iu2" 2 0
+ (and (eq_attr "type" "lmul")
+ (eq_attr "cpu" "power4"))
+ 7 6)
+
+(define_function_unit "iu2" 2 0
+ (and (eq_attr "type" "imul")
+ (eq_attr "cpu" "power4"))
+ 5 4)
+
+(define_function_unit "iu2" 2 0
+ (and (eq_attr "type" "imul2,imul3")
+ (eq_attr "cpu" "power4"))
+ 4 3)
+
+(define_function_unit "iu2" 2 0
+ (and (eq_attr "type" "idiv")
+ (eq_attr "cpu" "power4"))
+ 36 35)
+
+(define_function_unit "iu2" 2 0
+ (and (eq_attr "type" "ldiv")
+ (eq_attr "cpu" "power4"))
+ 68 67)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "idiv")
+ (eq_attr "cpu" "power4"))
+ 36 35)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "ldiv")
+ (eq_attr "cpu" "power4"))
+ 68 67)
+
+(define_function_unit "iu2" 2 0
+ (and (eq_attr "type" "compare")
+ (eq_attr "cpu" "power4"))
+ 3 1)
+
+(define_function_unit "iu2" 2 0
+ (and (eq_attr "type" "delayed_compare")
+ (eq_attr "cpu" "power4"))
+ 4 1)
+
+(define_function_unit "bpu" 1 0
+ (and (eq_attr "type" "mtjmpr")
+ (eq_attr "cpu" "power4"))
+ 3 1)
+
+(define_function_unit "bpu" 1 0
+ (and (eq_attr "type" "jmpreg,branch")
+ (eq_attr "cpu" "power4"))
+ 2 1)
+
+(define_function_unit "cru" 1 0
+ (and (eq_attr "type" "cr_logical")
+ (eq_attr "cpu" "power4"))
+ 4 1)
+
+(define_function_unit "fpu2" 2 0
+ (and (eq_attr "type" "fp,dmul")
+ (eq_attr "cpu" "power4"))
+ 6 1)
+
+; adjust_cost increases the cost of dependent branches,
+; so shave a few cycles off for fpcompare.
+(define_function_unit "fpu2" 2 0
+ (and (eq_attr "type" "fpcompare")
+ (eq_attr "cpu" "power4"))
+ 5 1)
+
+(define_function_unit "fpu2" 2 0
+ (and (eq_attr "type" "sdiv,ddiv")
+ (eq_attr "cpu" "power4"))
+ 33 28)
+
+(define_function_unit "fpu2" 2 0
+ (and (eq_attr "type" "ssqrt,dsqrt")
+ (eq_attr "cpu" "power4"))
+ 40 35)
+
;; Start with fixed-point load and store insns. Here we put only the more
;; complex forms. Basic data transfer is done later.
@@ -1631,7 +1736,7 @@
? operands[0] : gen_reg_rtx (SImode));
HOST_WIDE_INT val = INTVAL (operands[2]);
- HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+ HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode);
/* The ordering here is important for the prolog expander.
@@ -1740,7 +1845,7 @@
"
{
HOST_WIDE_INT val = INTVAL (operands[2]);
- HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+ HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode);
operands[3] = GEN_INT (rest);
@@ -1936,9 +2041,18 @@
(minus:SI (match_dup 2) (match_dup 1))))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(minus:SI (match_dup 2) (match_dup 3)))]
- "TARGET_POWER"
+ "TARGET_POWER || TARGET_ISEL"
"
-{ operands[3] = gen_reg_rtx (SImode); }")
+{
+ if (TARGET_ISEL)
+ {
+ operands[2] = force_reg (SImode, operands[2]);
+ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]);
+ DONE;
+ }
+
+ operands[3] = gen_reg_rtx (SImode);
+}")
(define_split
[(set (match_operand:SI 0 "gpc_reg_operand" "")
@@ -1961,9 +2075,17 @@
(minus:SI (match_dup 2) (match_dup 1))))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(plus:SI (match_dup 3) (match_dup 1)))]
- "TARGET_POWER"
+ "TARGET_POWER || TARGET_ISEL"
"
-{ operands[3] = gen_reg_rtx (SImode); }")
+{
+ if (TARGET_ISEL)
+ {
+ operands[2] = force_reg (SImode, operands[2]);
+ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]);
+ DONE;
+ }
+ operands[3] = gen_reg_rtx (SImode);
+}")
(define_split
[(set (match_operand:SI 0 "gpc_reg_operand" "")
@@ -1988,9 +2110,14 @@
(minus:SI (match_dup 4) (match_dup 3))))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(minus:SI (match_dup 2) (match_dup 3)))]
- "TARGET_POWER"
+ "TARGET_POWER || TARGET_ISEL"
"
{
+ if (TARGET_ISEL)
+ {
+ rs6000_emit_minmax (operands[0], UMIN, operands[1], operands[2]);
+ DONE;
+ }
operands[3] = gen_reg_rtx (SImode);
operands[4] = gen_reg_rtx (SImode);
operands[5] = GEN_INT (-2147483647 - 1);
@@ -2006,9 +2133,14 @@
(minus:SI (match_dup 4) (match_dup 3))))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(plus:SI (match_dup 3) (match_dup 1)))]
- "TARGET_POWER"
+ "TARGET_POWER || TARGET_ISEL"
"
{
+ if (TARGET_ISEL)
+ {
+ rs6000_emit_minmax (operands[0], UMAX, operands[1], operands[2]);
+ DONE;
+ }
operands[3] = gen_reg_rtx (SImode);
operands[4] = gen_reg_rtx (SImode);
operands[5] = GEN_INT (-2147483647 - 1);
@@ -2107,37 +2239,50 @@
""
"
{
- if (! TARGET_POWER)
+ if (TARGET_ISEL)
+ {
+ emit_insn (gen_abssi2_isel (operands[0], operands[1]));
+ DONE;
+ }
+ else if (! TARGET_POWER)
{
emit_insn (gen_abssi2_nopower (operands[0], operands[1]));
DONE;
}
}")
-(define_insn "abssi2_power"
+(define_insn "*abssi2_power"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(abs:SI (match_operand:SI 1 "gpc_reg_operand" "r")))]
"TARGET_POWER"
"abs %0,%1")
-(define_insn "abssi2_nopower"
+(define_insn_and_split "abssi2_isel"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (abs:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
+ (clobber (match_scratch:SI 2 "=b"))
+ (clobber (match_scratch:CC 3 "=y"))]
+ "TARGET_ISEL"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2) (neg:SI (match_dup 1)))
+ (set (match_dup 3)
+ (compare:CC (match_dup 1)
+ (const_int 0)))
+ (set (match_dup 0)
+ (if_then_else:SI (ge (match_dup 3)
+ (const_int 0))
+ (match_dup 1)
+ (match_dup 2)))]
+ "")
+
+(define_insn_and_split "abssi2_nopower"
[(set (match_operand:SI 0 "gpc_reg_operand" "=&r,r")
- (abs:SI (match_operand:SI 1 "gpc_reg_operand" "r,0")))
+ (abs:SI (match_operand:SI 1 "gpc_reg_operand" "r,0")))
(clobber (match_scratch:SI 2 "=&r,&r"))]
- "! TARGET_POWER"
- "*
-{
- return (TARGET_POWERPC)
- ? \"{srai|srawi} %2,%1,31\;xor %0,%2,%1\;subf %0,%2,%0\"
- : \"{srai|srawi} %2,%1,31\;xor %0,%2,%1\;{sf|subfc} %0,%2,%0\";
-}"
- [(set_attr "length" "12")])
-
-(define_split
- [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (abs:SI (match_operand:SI 1 "gpc_reg_operand" "")))
- (clobber (match_scratch:SI 2 ""))]
- "! TARGET_POWER && reload_completed"
+ "! TARGET_POWER && ! TARGET_ISEL"
+ "#"
+ "&& reload_completed"
[(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))
(set (match_dup 0) (minus:SI (match_dup 0) (match_dup 2)))]
@@ -2149,24 +2294,13 @@
"TARGET_POWER"
"nabs %0,%1")
-(define_insn "*nabs_no_power"
+(define_insn_and_split "*nabs_nopower"
[(set (match_operand:SI 0 "gpc_reg_operand" "=&r,r")
- (neg:SI (abs:SI (match_operand:SI 1 "gpc_reg_operand" "r,0"))))
+ (neg:SI (abs:SI (match_operand:SI 1 "gpc_reg_operand" "r,0"))))
(clobber (match_scratch:SI 2 "=&r,&r"))]
"! TARGET_POWER"
- "*
-{
- return (TARGET_POWERPC)
- ? \"{srai|srawi} %2,%1,31\;xor %0,%2,%1\;subf %0,%0,%2\"
- : \"{srai|srawi} %2,%1,31\;xor %0,%2,%1\;{sf|subfc} %0,%0,%2\";
-}"
- [(set_attr "length" "12")])
-
-(define_split
- [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (neg:SI (abs:SI (match_operand:SI 1 "gpc_reg_operand" ""))))
- (clobber (match_scratch:SI 2 ""))]
- "! TARGET_POWER && reload_completed"
+ "#"
+ "&& reload_completed"
[(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))
(set (match_dup 0) (minus:SI (match_dup 2) (match_dup 0)))]
@@ -2538,7 +2672,7 @@
rtx temp2;
if (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) < 0
+ || INTVAL (operands[2]) <= 0
|| (i = exact_log2 (INTVAL (operands[2]))) < 0)
FAIL;
@@ -2804,7 +2938,7 @@
{andiu.|andis.} %0,%1,%u2")
;; Note to set cr's other than cr0 we do the and immediate and then
-;; the test again -- this avoids a mcrf which on the higher end
+;; the test again -- this avoids a mfcr which on the higher end
;; machines causes an execution serialization
(define_insn "*andsi3_internal2"
@@ -2827,6 +2961,26 @@
[(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
(set_attr "length" "4,4,4,4,8,8,8,8")])
+(define_insn "*andsi3_internal3"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,?y,??y,??y,?y")
+ (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r")
+ (match_operand:SI 2 "and_operand" "r,K,L,T,r,K,L,T"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 3 "=r,r,r,r,r,r,r,r"))
+ (clobber (match_scratch:CC 4 "=X,X,X,X,X,x,x,X"))]
+ "TARGET_POWERPC64"
+ "@
+ #
+ {andil.|andi.} %3,%1,%b2
+ {andiu.|andis.} %3,%1,%u2
+ {rlinm.|rlwinm.} %3,%1,0,%m2,%M2
+ #
+ #
+ #
+ #"
+ [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
+ (set_attr "length" "8,4,4,4,8,8,8,8")])
+
(define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
(compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
@@ -2834,7 +2988,7 @@
(const_int 0)))
(clobber (match_scratch:SI 3 ""))
(clobber (match_scratch:CC 4 ""))]
- "! TARGET_POWERPC64 && reload_completed"
+ "reload_completed"
[(parallel [(set (match_dup 3)
(and:SI (match_dup 1)
(match_dup 2)))
@@ -2844,7 +2998,27 @@
(const_int 0)))]
"")
-(define_insn "*andsi3_internal3"
+;; We don't have a 32 bit "and. rt,ra,rb" for ppc64. cr is set from the
+;; whole 64 bit reg, and we don't know what is in the high 32 bits.
+
+(define_split
+ [(set (match_operand:CC 0 "cc_reg_operand" "")
+ (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
+ (match_operand:SI 2 "gpc_reg_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:SI 3 ""))
+ (clobber (match_scratch:CC 4 ""))]
+ "TARGET_POWERPC64 && reload_completed"
+ [(parallel [(set (match_dup 3)
+ (and:SI (match_dup 1)
+ (match_dup 2)))
+ (clobber (match_dup 4))])
+ (set (match_dup 0)
+ (compare:CC (match_dup 3)
+ (const_int 0)))]
+ "")
+
+(define_insn "*andsi3_internal4"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,?y,??y,??y,?y")
(compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r")
(match_operand:SI 2 "and_operand" "r,K,L,T,r,K,L,T"))
@@ -2866,6 +3040,28 @@
[(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
(set_attr "length" "4,4,4,4,8,8,8,8")])
+(define_insn "*andsi3_internal5"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,?y,??y,??y,?y")
+ (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r")
+ (match_operand:SI 2 "and_operand" "r,K,L,T,r,K,L,T"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r")
+ (and:SI (match_dup 1)
+ (match_dup 2)))
+ (clobber (match_scratch:CC 4 "=X,X,X,X,X,x,x,X"))]
+ "TARGET_POWERPC64"
+ "@
+ #
+ {andil.|andi.} %0,%1,%b2
+ {andiu.|andis.} %0,%1,%u2
+ {rlinm.|rlwinm.} %0,%1,0,%m2,%M2
+ #
+ #
+ #
+ #"
+ [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
+ (set_attr "length" "8,4,4,4,8,8,8,8")])
+
(define_split
[(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
(compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
@@ -2875,7 +3071,7 @@
(and:SI (match_dup 1)
(match_dup 2)))
(clobber (match_scratch:CC 4 ""))]
- "! TARGET_POWERPC64 && reload_completed"
+ "reload_completed"
[(parallel [(set (match_dup 0)
(and:SI (match_dup 1)
(match_dup 2)))
@@ -2885,6 +3081,104 @@
(const_int 0)))]
"")
+(define_split
+ [(set (match_operand:CC 3 "cc_reg_operand" "")
+ (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
+ (match_operand:SI 2 "gpc_reg_operand" ""))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "")
+ (and:SI (match_dup 1)
+ (match_dup 2)))
+ (clobber (match_scratch:CC 4 ""))]
+ "TARGET_POWERPC64 && reload_completed"
+ [(parallel [(set (match_dup 0)
+ (and:SI (match_dup 1)
+ (match_dup 2)))
+ (clobber (match_dup 4))])
+ (set (match_dup 3)
+ (compare:CC (match_dup 0)
+ (const_int 0)))]
+ "")
+
+;; Handle the PowerPC64 rlwinm corner case
+
+(define_insn_and_split "*andsi3_internal6"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (and:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "mask_operand_wrap" "i")))]
+ "TARGET_POWERPC64"
+ "#"
+ "TARGET_POWERPC64"
+ [(set (match_dup 0)
+ (and:SI (rotate:SI (match_dup 1) (match_dup 3))
+ (match_dup 4)))
+ (set (match_dup 0)
+ (rotate:SI (match_dup 0) (match_dup 5)))]
+ "
+{
+ int mb = extract_MB (operands[2]);
+ int me = extract_ME (operands[2]);
+ operands[3] = GEN_INT (me + 1);
+ operands[5] = GEN_INT (32 - (me + 1));
+ operands[4] = GEN_INT (~((HOST_WIDE_INT) -1 << (33 + me - mb)));
+}"
+ [(set_attr "length" "8")])
+
+(define_insn_and_split "*andsi3_internal7"
+ [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
+ (compare:CC (and:SI (match_operand:SI 0 "gpc_reg_operand" "r,r")
+ (match_operand:SI 1 "mask_operand_wrap" "i,i"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 3 "=r,r"))]
+ "TARGET_POWERPC64"
+ "#"
+ "TARGET_POWERPC64"
+ [(parallel [(set (match_dup 2)
+ (compare:CC (and:SI (rotate:SI (match_dup 0) (match_dup 4))
+ (match_dup 5))
+ (const_int 0)))
+ (clobber (match_dup 3))])]
+ "
+{
+ int mb = extract_MB (operands[1]);
+ int me = extract_ME (operands[1]);
+ operands[4] = GEN_INT (me + 1);
+ operands[5] = GEN_INT (~((HOST_WIDE_INT) -1 << (33 + me - mb)));
+}"
+ [(set_attr "type" "delayed_compare,compare")
+ (set_attr "length" "4,8")])
+
+(define_insn_and_split "*andsi3_internal8"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x,??y")
+ (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
+ (match_operand:SI 2 "mask_operand_wrap" "i,i"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+ (and:SI (match_dup 1)
+ (match_dup 2)))]
+ "TARGET_POWERPC64"
+ "#"
+ "TARGET_POWERPC64"
+ [(parallel [(set (match_dup 3)
+ (compare:CC (and:SI (rotate:SI (match_dup 1) (match_dup 4))
+ (match_dup 5))
+ (const_int 0)))
+ (set (match_dup 0)
+ (and:SI (rotate:SI (match_dup 1) (match_dup 4))
+ (match_dup 5)))])
+ (set (match_dup 0)
+ (rotate:SI (match_dup 0) (match_dup 6)))]
+ "
+{
+ int mb = extract_MB (operands[2]);
+ int me = extract_ME (operands[2]);
+ operands[4] = GEN_INT (me + 1);
+ operands[6] = GEN_INT (32 - (me + 1));
+ operands[5] = GEN_INT (~((HOST_WIDE_INT) -1 << (33 + me - mb)));
+}"
+ [(set_attr "type" "delayed_compare,compare")
+ (set_attr "length" "8,12")])
+
(define_expand "iorsi3"
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(ior:SI (match_operand:SI 1 "gpc_reg_operand" "")
@@ -3321,7 +3615,7 @@
#"
[(set_attr "type" "compare")
(set_attr "length" "4,8")])
-
+
(define_split
[(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
(compare:CC
@@ -3341,7 +3635,7 @@
(compare:CC (match_dup 0)
(const_int 0)))]
"")
-
+
;; Rotate and shift insns, in all their variants. These support shifts,
;; field inserts and extracts, and various combinations thereof.
(define_expand "insv"
@@ -3519,7 +3813,7 @@
(match_operand:SI 3 "const_int_operand" "i,i"))
(const_int 0)))
(clobber (match_scratch:SI 4 "=r,r"))]
- "! TARGET_POWERPC64"
+ ""
"*
{
int start = INTVAL (operands[3]) & 31;
@@ -3529,7 +3823,7 @@
if (which_alternative == 1)
return \"#\";
- /* If the bitfield being tested fits in the upper or lower half of a
+ /* If the bit-field being tested fits in the upper or lower half of a
word, it is possible to use andiu. or andil. to test it. This is
useful because the condition register set-use delay is smaller for
andi[ul]. than for rlinm. This doesn't work when the starting bit
@@ -3561,7 +3855,7 @@
(match_operand:SI 3 "const_int_operand" ""))
(const_int 0)))
(clobber (match_scratch:SI 4 ""))]
- "! TARGET_POWERPC64 && reload_completed"
+ "reload_completed"
[(set (match_dup 4)
(zero_extract:SI (match_dup 1) (match_dup 2)
(match_dup 3)))
@@ -3578,7 +3872,7 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(zero_extract:SI (match_dup 1) (match_dup 2) (match_dup 3)))]
- "! TARGET_POWERPC64"
+ ""
"*
{
int start = INTVAL (operands[3]) & 31;
@@ -3588,9 +3882,11 @@
if (which_alternative == 1)
return \"#\";
+ /* Since we are using the output value, we can't ignore any need for
+ a shift. The bit-field must end at the LSB. */
if (start >= 16 && start + size == 32)
{
- operands[3] = GEN_INT ((1 << (32 - start)) - 1);
+ operands[3] = GEN_INT ((1 << size) - 1);
return \"{andil.|andi.} %0,%1,%3\";
}
@@ -3600,7 +3896,7 @@
operands[3] = GEN_INT (start + size);
return \"{rlinm.|rlwinm.} %0,%1,%3,%s2,31\";
}"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "compare")
(set_attr "length" "4,8")])
(define_split
@@ -3611,7 +3907,7 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(zero_extract:SI (match_dup 1) (match_dup 2) (match_dup 3)))]
- "! TARGET_POWERPC64 && reload_completed"
+ "reload_completed"
[(set (match_dup 0)
(zero_extract:SI (match_dup 1) (match_dup 2) (match_dup 3)))
(set (match_dup 4)
@@ -3694,7 +3990,7 @@
(match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
(const_int 0)))
(clobber (match_scratch:SI 3 "=r,r"))]
- "! TARGET_POWERPC64"
+ ""
"@
{rl%I2nm.|rlw%I2nm.} %3,%1,%h2,0xffffffff
#"
@@ -3707,7 +4003,7 @@
(match_operand:SI 2 "reg_or_cint_operand" ""))
(const_int 0)))
(clobber (match_scratch:SI 3 ""))]
- "! TARGET_POWERPC64 && reload_completed"
+ "reload_completed"
[(set (match_dup 3)
(rotate:SI (match_dup 1) (match_dup 2)))
(set (match_dup 0)
@@ -3722,7 +4018,7 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(rotate:SI (match_dup 1) (match_dup 2)))]
- "! TARGET_POWERPC64"
+ ""
"@
{rl%I2nm.|rlw%I2nm.} %0,%1,%h2,0xffffffff
#"
@@ -3736,7 +4032,7 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(rotate:SI (match_dup 1) (match_dup 2)))]
- "! TARGET_POWERPC64 && reload_completed"
+ "reload_completed"
[(set (match_dup 0)
(rotate:SI (match_dup 1) (match_dup 2)))
(set (match_dup 3)
@@ -3748,7 +4044,7 @@
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(and:SI (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "reg_or_cint_operand" "ri"))
- (match_operand:SI 3 "mask_operand" "T")))]
+ (match_operand:SI 3 "mask_operand" "n")))]
""
"{rl%I2nm|rlw%I2nm} %0,%1,%h2,%m3,%M3")
@@ -3757,10 +4053,10 @@
(compare:CC (and:SI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
- (match_operand:SI 3 "mask_operand" "T,T"))
+ (match_operand:SI 3 "mask_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:SI 4 "=r,r"))]
- "! TARGET_POWERPC64"
+ ""
"@
{rl%I2nm.|rlw%I2nm.} %4,%1,%h2,%m3,%M3
#"
@@ -3775,7 +4071,7 @@
(match_operand:SI 3 "mask_operand" ""))
(const_int 0)))
(clobber (match_scratch:SI 4 ""))]
- "! TARGET_POWERPC64 && reload_completed"
+ "reload_completed"
[(set (match_dup 4)
(and:SI (rotate:SI (match_dup 1)
(match_dup 2))
@@ -3790,11 +4086,11 @@
(compare:CC (and:SI
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "reg_or_cint_operand" "ri,ri"))
- (match_operand:SI 3 "mask_operand" "T,T"))
+ (match_operand:SI 3 "mask_operand" "n,n"))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(and:SI (rotate:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "! TARGET_POWERPC64"
+ ""
"@
{rl%I2nm.|rlw%I2nm.} %0,%1,%h2,%m3,%M3
#"
@@ -3810,7 +4106,7 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(and:SI (rotate:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "! TARGET_POWERPC64 && reload_completed"
+ "reload_completed"
[(set (match_dup 0)
(and:SI (rotate:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
(set (match_dup 4)
@@ -4128,7 +4424,7 @@
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(and:SI (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i"))
- (match_operand:SI 3 "mask_operand" "T")))]
+ (match_operand:SI 3 "mask_operand" "n")))]
"includes_lshift_p (operands[2], operands[3])"
"{rlinm|rlwinm} %0,%1,%h2,%m3,%M3")
@@ -4137,10 +4433,10 @@
(compare:CC
(and:SI (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "i,i"))
- (match_operand:SI 3 "mask_operand" "T,T"))
+ (match_operand:SI 3 "mask_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:SI 4 "=r,r"))]
- "! TARGET_POWERPC64 && includes_lshift_p (operands[2], operands[3])"
+ "includes_lshift_p (operands[2], operands[3])"
"@
{rlinm.|rlwinm.} %4,%1,%h2,%m3,%M3
#"
@@ -4155,7 +4451,7 @@
(match_operand:SI 3 "mask_operand" ""))
(const_int 0)))
(clobber (match_scratch:SI 4 ""))]
- "! TARGET_POWERPC64 && includes_lshift_p (operands[2], operands[3]) && reload_completed"
+ "includes_lshift_p (operands[2], operands[3]) && reload_completed"
[(set (match_dup 4)
(and:SI (ashift:SI (match_dup 1) (match_dup 2))
(match_dup 3)))
@@ -4169,11 +4465,11 @@
(compare:CC
(and:SI (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "i,i"))
- (match_operand:SI 3 "mask_operand" "T,T"))
+ (match_operand:SI 3 "mask_operand" "n,n"))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(and:SI (ashift:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "! TARGET_POWERPC64 && includes_lshift_p (operands[2], operands[3])"
+ "includes_lshift_p (operands[2], operands[3])"
"@
{rlinm.|rlwinm.} %0,%1,%h2,%m3,%M3
#"
@@ -4189,7 +4485,7 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(and:SI (ashift:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "! TARGET_POWERPC64 && includes_lshift_p (operands[2], operands[3]) && reload_completed"
+ "includes_lshift_p (operands[2], operands[3]) && reload_completed"
[(set (match_dup 0)
(and:SI (ashift:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
(set (match_dup 4)
@@ -4367,7 +4663,7 @@
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(and:SI (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i"))
- (match_operand:SI 3 "mask_operand" "T")))]
+ (match_operand:SI 3 "mask_operand" "n")))]
"includes_rshift_p (operands[2], operands[3])"
"{rlinm|rlwinm} %0,%1,%s2,%m3,%M3")
@@ -4376,10 +4672,10 @@
(compare:CC
(and:SI (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "i,i"))
- (match_operand:SI 3 "mask_operand" "T,T"))
+ (match_operand:SI 3 "mask_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:SI 4 "=r,r"))]
- "! TARGET_POWERPC64 && includes_rshift_p (operands[2], operands[3])"
+ "includes_rshift_p (operands[2], operands[3])"
"@
{rlinm.|rlwinm.} %4,%1,%s2,%m3,%M3
#"
@@ -4394,7 +4690,7 @@
(match_operand:SI 3 "mask_operand" ""))
(const_int 0)))
(clobber (match_scratch:SI 4 ""))]
- "! TARGET_POWERPC64 && includes_rshift_p (operands[2], operands[3]) && reload_completed"
+ "includes_rshift_p (operands[2], operands[3]) && reload_completed"
[(set (match_dup 4)
(and:SI (lshiftrt:SI (match_dup 1) (match_dup 2))
(match_dup 3)))
@@ -4408,11 +4704,11 @@
(compare:CC
(and:SI (lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "i,i"))
- (match_operand:SI 3 "mask_operand" "T,T"))
+ (match_operand:SI 3 "mask_operand" "n,n"))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
(and:SI (lshiftrt:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "! TARGET_POWERPC64 && includes_rshift_p (operands[2], operands[3])"
+ "includes_rshift_p (operands[2], operands[3])"
"@
{rlinm.|rlwinm.} %0,%1,%s2,%m3,%M3
#"
@@ -4428,7 +4724,7 @@
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(and:SI (lshiftrt:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "! TARGET_POWERPC64 && includes_rshift_p (operands[2], operands[3]) && reload_completed"
+ "includes_rshift_p (operands[2], operands[3]) && reload_completed"
[(set (match_dup 0)
(and:SI (lshiftrt:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
(set (match_dup 4)
@@ -4794,7 +5090,7 @@
(define_insn "extendsfdf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(float_extend:DF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"*
{
if (REGNO (operands[0]) == REGNO (operands[1]))
@@ -4807,35 +5103,47 @@
(define_insn "truncdfsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"frsp %0,%1"
[(set_attr "type" "fp")])
(define_insn "aux_truncdfsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] 0))]
- "! TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS"
"frsp %0,%1"
[(set_attr "type" "fp")])
-(define_insn "negsf2"
+(define_expand "negsf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "")
+ (neg:SF (match_operand:SF 1 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*negsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(neg:SF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"fneg %0,%1"
[(set_attr "type" "fp")])
-(define_insn "abssf2"
+(define_expand "abssf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "")
+ (abs:SF (match_operand:SF 1 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*abssf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(abs:SF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"fabs %0,%1"
[(set_attr "type" "fp")])
(define_insn ""
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(neg:SF (abs:SF (match_operand:SF 1 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"fnabs %0,%1"
[(set_attr "type" "fp")])
@@ -4850,7 +5158,7 @@
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(plus:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS"
"fadds %0,%1,%2"
[(set_attr "type" "fp")])
@@ -4858,7 +5166,7 @@
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(plus:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f")))]
- "! TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS"
"{fa|fadd} %0,%1,%2"
[(set_attr "type" "fp")])
@@ -4873,7 +5181,7 @@
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (match_operand:SF 1 "gpc_reg_operand" "f")
(match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS"
"fsubs %0,%1,%2"
[(set_attr "type" "fp")])
@@ -4881,7 +5189,7 @@
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(minus:SF (match_operand:SF 1 "gpc_reg_operand" "f")
(match_operand:SF 2 "gpc_reg_operand" "f")))]
- "! TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS"
"{fs|fsub} %0,%1,%2"
[(set_attr "type" "fp")])
@@ -4896,7 +5204,7 @@
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS"
"fmuls %0,%1,%2"
[(set_attr "type" "fp")])
@@ -4904,7 +5212,7 @@
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f")))]
- "! TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS"
"{fm|fmul} %0,%1,%2"
[(set_attr "type" "dmul")])
@@ -4919,7 +5227,7 @@
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(div:SF (match_operand:SF 1 "gpc_reg_operand" "f")
(match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS"
"fdivs %0,%1,%2"
[(set_attr "type" "sdiv")])
@@ -4927,7 +5235,7 @@
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(div:SF (match_operand:SF 1 "gpc_reg_operand" "f")
(match_operand:SF 2 "gpc_reg_operand" "f")))]
- "! TARGET_POWERPC && TARGET_HARD_FLOAT"
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS"
"{fd|fdiv} %0,%1,%2"
[(set_attr "type" "ddiv")])
@@ -4936,7 +5244,7 @@
(plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f")))]
- "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
+ "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD"
"fmadds %0,%1,%2,%3"
[(set_attr "type" "fp")])
@@ -4945,7 +5253,7 @@
(plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f")))]
- "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD"
"{fma|fmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
@@ -4954,7 +5262,7 @@
(minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f")))]
- "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
+ "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD"
"fmsubs %0,%1,%2,%3"
[(set_attr "type" "fp")])
@@ -4963,7 +5271,7 @@
(minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f")))]
- "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD"
"{fms|fmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
@@ -4972,7 +5280,18 @@
(neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
+ "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
+ && HONOR_SIGNED_ZEROS (SFmode)"
+ "fnmadds %0,%1,%2,%3"
+ [(set_attr "type" "fp")])
+
+(define_insn ""
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+ (match_operand:SF 3 "gpc_reg_operand" "f")))]
+ "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
+ && ! HONOR_SIGNED_ZEROS (SFmode)"
"fnmadds %0,%1,%2,%3"
[(set_attr "type" "fp")])
@@ -4981,7 +5300,17 @@
(neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD"
+ "{fnma|fnmadd} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")])
+
+(define_insn ""
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
+ (match_operand:SF 2 "gpc_reg_operand" "f"))
+ (match_operand:SF 3 "gpc_reg_operand" "f")))]
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
+ && ! HONOR_SIGNED_ZEROS (SFmode)"
"{fnma|fnmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
@@ -4990,7 +5319,18 @@
(neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
+ "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
+ && HONOR_SIGNED_ZEROS (SFmode)"
+ "fnmsubs %0,%1,%2,%3"
+ [(set_attr "type" "fp")])
+
+(define_insn ""
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (match_operand:SF 3 "gpc_reg_operand" "f")
+ (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))))]
+ "TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
+ && ! HONOR_SIGNED_ZEROS (SFmode)"
"fnmsubs %0,%1,%2,%3"
[(set_attr "type" "fp")])
@@ -4999,27 +5339,37 @@
(neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
(match_operand:SF 2 "gpc_reg_operand" "f"))
(match_operand:SF 3 "gpc_reg_operand" "f"))))]
- "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD"
"{fnms|fnmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
+(define_insn ""
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (minus:SF (match_operand:SF 3 "gpc_reg_operand" "f")
+ (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
+ (match_operand:SF 2 "gpc_reg_operand" "f"))))]
+ "! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
+ && ! HONOR_SIGNED_ZEROS (SFmode)"
+ "{fnms|fnmsub} %0,%1,%2,%3"
+ [(set_attr "type" "fp")])
+
(define_expand "sqrtsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
(sqrt:SF (match_operand:SF 1 "gpc_reg_operand" "")))]
- "(TARGET_PPC_GPOPT || TARGET_POWER2) && TARGET_HARD_FLOAT"
+ "(TARGET_PPC_GPOPT || TARGET_POWER2) && TARGET_HARD_FLOAT && TARGET_FPRS"
"")
(define_insn ""
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(sqrt:SF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "TARGET_PPC_GPOPT && TARGET_HARD_FLOAT"
+ "TARGET_PPC_GPOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
"fsqrts %0,%1"
[(set_attr "type" "ssqrt")])
(define_insn ""
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(sqrt:SF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "TARGET_POWER2 && TARGET_HARD_FLOAT"
+ "TARGET_POWER2 && TARGET_HARD_FLOAT && TARGET_FPRS"
"fsqrt %0,%1"
[(set_attr "type" "dsqrt")])
@@ -5033,7 +5383,7 @@
(match_operand:SF 2 "gpc_reg_operand" ""))
(match_dup 1)
(match_dup 2)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
"{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
(define_expand "minsf3"
@@ -5042,7 +5392,7 @@
(match_operand:SF 2 "gpc_reg_operand" ""))
(match_dup 2)
(match_dup 1)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
"{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
(define_split
@@ -5050,7 +5400,7 @@
(match_operator:SF 3 "min_max_operator"
[(match_operand:SF 1 "gpc_reg_operand" "")
(match_operand:SF 2 "gpc_reg_operand" "")]))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
[(const_int 0)]
"
{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
@@ -5058,12 +5408,60 @@
DONE;
}")
+(define_expand "movsicc"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "")
+ (if_then_else:SI (match_operand 1 "comparison_operator" "")
+ (match_operand:SI 2 "gpc_reg_operand" "")
+ (match_operand:SI 3 "gpc_reg_operand" "")))]
+ "TARGET_ISEL"
+ "
+{
+ if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
+ DONE;
+ else
+ FAIL;
+}")
+
+;; We use the BASE_REGS for the isel input operands because, if rA is
+;; 0, the value of 0 is placed in rD upon truth. Similarly for rB
+;; because we may switch the operands and rB may end up being rA.
+;;
+;; We need 2 patterns: an unsigned and a signed pattern. We could
+;; leave out the mode in operand 4 and use one pattern, but reload can
+;; change the mode underneath our feet and then gets confused trying
+;; to reload the value.
+(define_insn "isel_signed"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (if_then_else:SI
+ (match_operator 1 "comparison_operator"
+ [(match_operand:CC 4 "cc_reg_operand" "y")
+ (const_int 0)])
+ (match_operand:SI 2 "gpc_reg_operand" "b")
+ (match_operand:SI 3 "gpc_reg_operand" "b")))]
+ "TARGET_ISEL"
+ "*
+{ return output_isel (operands); }"
+ [(set_attr "length" "4")])
+
+(define_insn "isel_unsigned"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (if_then_else:SI
+ (match_operator 1 "comparison_operator"
+ [(match_operand:CCUNS 4 "cc_reg_operand" "y")
+ (const_int 0)])
+ (match_operand:SI 2 "gpc_reg_operand" "b")
+ (match_operand:SI 3 "gpc_reg_operand" "b")))]
+ "TARGET_ISEL"
+ "*
+{ return output_isel (operands); }"
+ [(set_attr "length" "4")])
+
(define_expand "movsfcc"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
(if_then_else:SF (match_operand 1 "comparison_operator" "")
(match_operand:SF 2 "gpc_reg_operand" "")
(match_operand:SF 3 "gpc_reg_operand" "")))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
"
{
if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
@@ -5078,7 +5476,7 @@
(match_operand:SF 4 "zero_fp_constant" "F"))
(match_operand:SF 2 "gpc_reg_operand" "f")
(match_operand:SF 3 "gpc_reg_operand" "f")))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
"fsel %0,%1,%2,%3"
[(set_attr "type" "fp")])
@@ -5088,28 +5486,28 @@
(match_operand:DF 4 "zero_fp_constant" "F"))
(match_operand:SF 2 "gpc_reg_operand" "f")
(match_operand:SF 3 "gpc_reg_operand" "f")))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
"fsel %0,%1,%2,%3"
[(set_attr "type" "fp")])
(define_insn "negdf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(neg:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"fneg %0,%1"
[(set_attr "type" "fp")])
(define_insn "absdf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(abs:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"fabs %0,%1"
[(set_attr "type" "fp")])
(define_insn ""
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"fnabs %0,%1"
[(set_attr "type" "fp")])
@@ -5117,7 +5515,7 @@
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(plus:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
(match_operand:DF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"{fa|fadd} %0,%1,%2"
[(set_attr "type" "fp")])
@@ -5125,7 +5523,7 @@
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(minus:DF (match_operand:DF 1 "gpc_reg_operand" "f")
(match_operand:DF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"{fs|fsub} %0,%1,%2"
[(set_attr "type" "fp")])
@@ -5133,7 +5531,7 @@
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
(match_operand:DF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"{fm|fmul} %0,%1,%2"
[(set_attr "type" "dmul")])
@@ -5141,7 +5539,7 @@
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(div:DF (match_operand:DF 1 "gpc_reg_operand" "f")
(match_operand:DF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"{fd|fdiv} %0,%1,%2"
[(set_attr "type" "ddiv")])
@@ -5150,7 +5548,7 @@
(plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
(match_operand:DF 2 "gpc_reg_operand" "f"))
(match_operand:DF 3 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD"
"{fma|fmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
@@ -5159,7 +5557,7 @@
(minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
(match_operand:DF 2 "gpc_reg_operand" "f"))
(match_operand:DF 3 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD"
"{fms|fmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
@@ -5168,7 +5566,18 @@
(neg:DF (plus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
(match_operand:DF 2 "gpc_reg_operand" "f"))
(match_operand:DF 3 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
+ && HONOR_SIGNED_ZEROS (DFmode)"
+ "{fnma|fnmadd} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")])
+
+(define_insn ""
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (minus:DF (mult:DF (neg:DF (match_operand:DF 1 "gpc_reg_operand" "f"))
+ (match_operand:DF 2 "gpc_reg_operand" "f"))
+ (match_operand:DF 3 "gpc_reg_operand" "f")))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
+ && ! HONOR_SIGNED_ZEROS (DFmode)"
"{fnma|fnmadd} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
@@ -5177,14 +5586,25 @@
(neg:DF (minus:DF (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
(match_operand:DF 2 "gpc_reg_operand" "f"))
(match_operand:DF 3 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FUSED_MADD"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
+ && HONOR_SIGNED_ZEROS (DFmode)"
+ "{fnms|fnmsub} %0,%1,%2,%3"
+ [(set_attr "type" "dmul")])
+
+(define_insn ""
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (minus:DF (match_operand:DF 3 "gpc_reg_operand" "f")
+ (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
+ (match_operand:DF 2 "gpc_reg_operand" "f"))))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
+ && ! HONOR_SIGNED_ZEROS (DFmode)"
"{fnms|fnmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
(define_insn "sqrtdf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
- "(TARGET_PPC_GPOPT || TARGET_POWER2) && TARGET_HARD_FLOAT"
+ "(TARGET_PPC_GPOPT || TARGET_POWER2) && TARGET_HARD_FLOAT && TARGET_FPRS"
"fsqrt %0,%1"
[(set_attr "type" "dsqrt")])
@@ -5197,7 +5617,7 @@
(match_operand:DF 2 "gpc_reg_operand" ""))
(match_dup 1)
(match_dup 2)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
"{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
(define_expand "mindf3"
@@ -5206,7 +5626,7 @@
(match_operand:DF 2 "gpc_reg_operand" ""))
(match_dup 2)
(match_dup 1)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
"{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
(define_split
@@ -5214,7 +5634,7 @@
(match_operator:DF 3 "min_max_operator"
[(match_operand:DF 1 "gpc_reg_operand" "")
(match_operand:DF 2 "gpc_reg_operand" "")]))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
[(const_int 0)]
"
{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
@@ -5227,7 +5647,7 @@
(if_then_else:DF (match_operand 1 "comparison_operator" "")
(match_operand:DF 2 "gpc_reg_operand" "")
(match_operand:DF 3 "gpc_reg_operand" "")))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
"
{
if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
@@ -5242,7 +5662,7 @@
(match_operand:DF 4 "zero_fp_constant" "F"))
(match_operand:DF 2 "gpc_reg_operand" "f")
(match_operand:DF 3 "gpc_reg_operand" "f")))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
"fsel %0,%1,%2,%3"
[(set_attr "type" "fp")])
@@ -5258,6 +5678,18 @@
;; Conversions to and from floating-point.
+(define_expand "fixunssfsi2"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "")
+ (unsigned_fix:SI (fix:SF (match_operand:SF 1 "gpc_reg_operand" ""))))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "")
+
+(define_expand "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "")
+ (fix:SI (match_operand:SF 1 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "")
+
; For each of these conversions, there is a define_expand, a define_insn
; with a '#' template, and a define_split (with C code). The idea is
; to allow constant folding with the template of the define_insn,
@@ -5271,7 +5703,7 @@
(clobber (match_dup 4))
(clobber (match_dup 5))
(clobber (match_dup 6))])]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"
{
if (TARGET_POWERPC64)
@@ -5284,7 +5716,7 @@
}
operands[2] = force_reg (SImode, GEN_INT (0x43300000));
- operands[3] = force_reg (DFmode, rs6000_float_const (\"4503601774854144\", DFmode));
+ operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503601774854144\", DFmode));
operands[4] = assign_stack_temp (DFmode, GET_MODE_SIZE (DFmode), 0);
operands[5] = gen_reg_rtx (DFmode);
operands[6] = gen_reg_rtx (SImode);
@@ -5298,7 +5730,7 @@
(clobber (match_operand:DF 4 "memory_operand" "=o"))
(clobber (match_operand:DF 5 "gpc_reg_operand" "=f"))
(clobber (match_operand:SI 6 "gpc_reg_operand" "=r"))]
- "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+ "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
"#"
[(set_attr "length" "24")])
@@ -5310,7 +5742,7 @@
(clobber (match_operand:DF 4 "offsettable_mem_operand" ""))
(clobber (match_operand:DF 5 "gpc_reg_operand" ""))
(clobber (match_operand:SI 6 "gpc_reg_operand" ""))]
- "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+ "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
(use (match_operand:SI 2 "gpc_reg_operand" ""))
@@ -5340,6 +5772,12 @@
DONE;
}")
+(define_expand "floatunssisf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "")
+ (unsigned_float:SF (match_operand:SI 1 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "")
+
(define_expand "floatunssidf2"
[(parallel [(set (match_operand:DF 0 "gpc_reg_operand" "")
(unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
@@ -5347,7 +5785,7 @@
(use (match_dup 3))
(clobber (match_dup 4))
(clobber (match_dup 5))])]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"
{
if (TARGET_POWERPC64)
@@ -5361,7 +5799,7 @@
}
operands[2] = force_reg (SImode, GEN_INT (0x43300000));
- operands[3] = force_reg (DFmode, rs6000_float_const (\"4503599627370496\", DFmode));
+ operands[3] = force_reg (DFmode, CONST_DOUBLE_ATOF (\"4503599627370496\", DFmode));
operands[4] = assign_stack_temp (DFmode, GET_MODE_SIZE (DFmode), 0);
operands[5] = gen_reg_rtx (DFmode);
}")
@@ -5373,7 +5811,7 @@
(use (match_operand:DF 3 "gpc_reg_operand" "f"))
(clobber (match_operand:DF 4 "memory_operand" "=o"))
(clobber (match_operand:DF 5 "gpc_reg_operand" "=f"))]
- "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+ "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
"#"
[(set_attr "length" "20")])
@@ -5384,7 +5822,7 @@
(use (match_operand:DF 3 "gpc_reg_operand" ""))
(clobber (match_operand:DF 4 "offsettable_mem_operand" ""))
(clobber (match_operand:DF 5 "gpc_reg_operand" ""))]
- "! TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+ "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
(use (match_operand:SI 2 "gpc_reg_operand" ""))
@@ -5416,7 +5854,7 @@
(fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))
(clobber (match_dup 2))
(clobber (match_dup 3))])]
- "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT"
+ "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS"
"
{
operands[2] = gen_reg_rtx (DImode);
@@ -5426,9 +5864,9 @@
(define_insn "*fix_truncdfsi2_internal"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(fix:SI (match_operand:DF 1 "gpc_reg_operand" "f")))
- (clobber (match_operand:DI 2 "gpc_reg_operand" "=*f"))
+ (clobber (match_operand:DI 2 "gpc_reg_operand" "=f"))
(clobber (match_operand:DI 3 "memory_operand" "=o"))]
- "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT"
+ "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS"
"#"
[(set_attr "length" "16")])
@@ -5437,7 +5875,7 @@
(fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))
(clobber (match_operand:DI 2 "gpc_reg_operand" ""))
(clobber (match_operand:DI 3 "offsettable_mem_operand" ""))]
- "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT"
+ "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS"
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))
(clobber (match_operand:DI 2 "gpc_reg_operand" ""))
@@ -5464,14 +5902,20 @@
(define_insn "fctiwz"
[(set (match_operand:DI 0 "gpc_reg_operand" "=*f")
(unspec:DI [(fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))] 10))]
- "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT"
+ "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS"
"{fcirz|fctiwz} %0,%1"
[(set_attr "type" "fp")])
+(define_expand "floatsisf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "")
+ (float:SF (match_operand:SI 1 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "")
+
(define_insn "floatdidf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(float:DF (match_operand:DI 1 "gpc_reg_operand" "*f")))]
- "TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+ "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
"fcfid %0,%1"
[(set_attr "type" "fp")])
@@ -5481,7 +5925,7 @@
(clobber (match_operand:DI 2 "memory_operand" "=o"))
(clobber (match_operand:DI 3 "gpc_reg_operand" "=r"))
(clobber (match_operand:DI 4 "gpc_reg_operand" "=f"))]
- "TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+ "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
"#"
""
[(set (match_dup 3) (sign_extend:DI (match_dup 1)))
@@ -5496,7 +5940,7 @@
(clobber (match_operand:DI 2 "memory_operand" "=o"))
(clobber (match_operand:DI 3 "gpc_reg_operand" "=r"))
(clobber (match_operand:DI 4 "gpc_reg_operand" "=f"))]
- "TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+ "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
"#"
""
[(set (match_dup 3) (zero_extend:DI (match_dup 1)))
@@ -5508,9 +5952,72 @@
(define_insn "fix_truncdfdi2"
[(set (match_operand:DI 0 "gpc_reg_operand" "=*f")
(fix:DI (match_operand:DF 1 "gpc_reg_operand" "f")))]
- "TARGET_POWERPC64 && TARGET_HARD_FLOAT"
+ "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
"fctidz %0,%1"
[(set_attr "type" "fp")])
+
+(define_expand "floatdisf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "")
+ (float:SF (match_operand:DI 1 "gpc_reg_operand" "")))]
+ "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "
+{
+ if (!flag_unsafe_math_optimizations)
+ {
+ rtx label = gen_label_rtx ();
+ emit_insn (gen_floatdisf2_internal2 (operands[1], label));
+ emit_label (label);
+ }
+ emit_insn (gen_floatdisf2_internal1 (operands[0], operands[1]));
+ DONE;
+}")
+
+;; This is not IEEE compliant if rounding mode is "round to nearest".
+;; If the DI->DF conversion is inexact, then it's possible to suffer
+;; from double rounding.
+(define_insn_and_split "floatdisf2_internal1"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (float:SF (match_operand:DI 1 "gpc_reg_operand" "*f")))
+ (clobber (match_scratch:DF 2 "=f"))]
+ "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2)
+ (float:DF (match_dup 1)))
+ (set (match_dup 0)
+ (float_truncate:SF (match_dup 2)))]
+ "")
+
+;; Twiddles bits to avoid double rounding.
+;; Bits that might be trucated when converting to DFmode are replaced
+;; by a bit that won't be lost at that stage, but is below the SFmode
+;; rounding position.
+(define_expand "floatdisf2_internal2"
+ [(parallel [(set (match_dup 4)
+ (compare:CC (and:DI (match_operand:DI 0 "" "")
+ (const_int 2047))
+ (const_int 0)))
+ (set (match_dup 2) (and:DI (match_dup 0) (const_int 2047)))
+ (clobber (match_scratch:CC 7 ""))])
+ (set (match_dup 3) (ashiftrt:DI (match_dup 0) (const_int 53)))
+ (set (match_dup 3) (plus:DI (match_dup 3) (const_int 1)))
+ (set (pc) (if_then_else (eq (match_dup 4) (const_int 0))
+ (label_ref (match_operand:DI 1 "" ""))
+ (pc)))
+ (set (match_dup 5) (compare:CCUNS (match_dup 3) (const_int 2)))
+ (set (pc) (if_then_else (ltu (match_dup 5) (const_int 0))
+ (label_ref (match_dup 1))
+ (pc)))
+ (set (match_dup 0) (xor:DI (match_dup 0) (match_dup 2)))
+ (set (match_dup 0) (ior:DI (match_dup 0) (const_int 2048)))]
+ "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "
+{
+ operands[2] = gen_reg_rtx (DImode);
+ operands[3] = gen_reg_rtx (DImode);
+ operands[4] = gen_reg_rtx (CCmode);
+ operands[5] = gen_reg_rtx (CCUNSmode);
+}")
;; Define the DImode operations that can be done in a small number
;; of instructions. The & constraints are to prevent the register
@@ -5838,6 +6345,16 @@
{srai|srawi} %0,%1,31\;{srai|srawi} %L0,%1,%h2
sraiq %0,%1,%h2\;srliq %L0,%L1,%h2"
[(set_attr "length" "8")])
+
+(define_insn "ashrdi3_no_power"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r")
+ (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
+ (match_operand:SI 2 "const_int_operand" "M,i")))]
+ "TARGET_32BIT && !TARGET_POWER"
+ "@
+ {srai|srawi} %0,%1,31\;{srai|srawi} %L0,%1,%h2
+ {sri|srwi} %L0,%L1,%h2\;insrwi %L0,%1,%h2,0\;{srai|srawi} %0,%1,%h2"
+ [(set_attr "length" "8,12")])
;; PowerPC64 DImode operations.
@@ -5861,7 +6378,7 @@
? operands[0] : gen_reg_rtx (DImode));
HOST_WIDE_INT val = INTVAL (operands[2]);
- HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+ HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode);
if (!CONST_OK_FOR_LETTER_P (rest, 'L'))
@@ -5964,7 +6481,7 @@
"
{
HOST_WIDE_INT val = INTVAL (operands[2]);
- HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000);
+ HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode);
operands[4] = GEN_INT (low);
@@ -6119,37 +6636,25 @@
}
}")
-(define_insn "absdi2"
+(define_insn_and_split "absdi2"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
- (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))
+ (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))
(clobber (match_scratch:DI 2 "=&r,&r"))]
"TARGET_POWERPC64"
- "sradi %2,%1,63\;xor %0,%2,%1\;subf %0,%2,%0"
- [(set_attr "length" "12")])
-
-(define_split
- [(set (match_operand:DI 0 "gpc_reg_operand" "")
- (abs:DI (match_operand:DI 1 "gpc_reg_operand" "")))
- (clobber (match_scratch:DI 2 ""))]
- "TARGET_POWERPC64 && reload_completed"
+ "#"
+ "&& reload_completed"
[(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
(set (match_dup 0) (xor:DI (match_dup 2) (match_dup 1)))
(set (match_dup 0) (minus:DI (match_dup 0) (match_dup 2)))]
"")
-(define_insn "*nabsdi2"
+(define_insn_and_split "*nabsdi2"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
- (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0"))))
+ (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0"))))
(clobber (match_scratch:DI 2 "=&r,&r"))]
"TARGET_POWERPC64"
- "sradi %2,%1,63\;xor %0,%2,%1\;subf %0,%0,%2"
- [(set_attr "length" "12")])
-
-(define_split
- [(set (match_operand:DI 0 "gpc_reg_operand" "")
- (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" ""))))
- (clobber (match_scratch:DI 2 ""))]
- "TARGET_POWERPC64 && reload_completed"
+ "#"
+ "&& reload_completed"
[(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
(set (match_dup 0) (xor:DI (match_dup 2) (match_dup 1)))
(set (match_dup 0) (minus:DI (match_dup 2) (match_dup 0)))]
@@ -6445,7 +6950,7 @@
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(and:DI (rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(match_operand:DI 2 "reg_or_cint_operand" "ri"))
- (match_operand:DI 3 "mask64_operand" "S")))]
+ (match_operand:DI 3 "mask64_operand" "n")))]
"TARGET_POWERPC64"
"rld%I2c%B3 %0,%1,%H2,%S3")
@@ -6454,7 +6959,7 @@
(compare:CC (and:DI
(rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
(match_operand:DI 2 "reg_or_cint_operand" "ri,ri"))
- (match_operand:DI 3 "mask64_operand" "S,S"))
+ (match_operand:DI 3 "mask64_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:DI 4 "=r,r"))]
"TARGET_POWERPC64"
@@ -6487,7 +6992,7 @@
(compare:CC (and:DI
(rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
(match_operand:DI 2 "reg_or_cint_operand" "ri,ri"))
- (match_operand:DI 3 "mask64_operand" "S,S"))
+ (match_operand:DI 3 "mask64_operand" "n,n"))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
(and:DI (rotate:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
@@ -6902,7 +7407,7 @@
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i"))
- (match_operand:DI 3 "mask64_operand" "S")))]
+ (match_operand:DI 3 "mask64_operand" "n")))]
"TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
"rldicr %0,%1,%H2,%S3")
@@ -6911,7 +7416,7 @@
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "i,i"))
- (match_operand:DI 3 "mask64_operand" "S,S"))
+ (match_operand:DI 3 "mask64_operand" "n,n"))
(const_int 0)))
(clobber (match_scratch:DI 4 "=r,r"))]
"TARGET_POWERPC64 && includes_rldicr_lshift_p (operands[2], operands[3])"
@@ -6944,7 +7449,7 @@
(compare:CC
(and:DI (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "i,i"))
- (match_operand:DI 3 "mask64_operand" "S,S"))
+ (match_operand:DI 3 "mask64_operand" "n,n"))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
(and:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
@@ -7059,7 +7564,7 @@
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
(match_operand:SI 2 "reg_or_cint_operand" "")))]
- "TARGET_POWERPC64 || TARGET_POWER"
+ ""
"
{
if (TARGET_POWERPC64)
@@ -7069,6 +7574,11 @@
emit_insn (gen_ashrdi3_power (operands[0], operands[1], operands[2]));
DONE;
}
+ else if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
+ {
+ emit_insn (gen_ashrdi3_no_power (operands[0], operands[1], operands[2]));
+ DONE;
+ }
else
FAIL;
}")
@@ -7137,24 +7647,47 @@
"")
(define_insn "anddi3"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
- (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r")
- (match_operand:DI 2 "and64_operand" "?r,S,K,J")))
- (clobber (match_scratch:CC 3 "=X,X,x,x"))]
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r")
+ (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r")
+ (match_operand:DI 2 "and64_2_operand" "?r,S,K,J,t")))
+ (clobber (match_scratch:CC 3 "=X,X,x,x,X"))]
"TARGET_POWERPC64"
"@
and %0,%1,%2
rldic%B2 %0,%1,0,%S2
andi. %0,%1,%b2
- andis. %0,%1,%u2")
+ andis. %0,%1,%u2
+ #"
+ [(set_attr "length" "4,4,4,4,8")])
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "mask64_2_operand" "")))
+ (clobber (match_scratch:CC 3 ""))]
+ "TARGET_POWERPC64
+ && (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
+ && !mask64_operand (operands[2], DImode)"
+ [(set (match_dup 0)
+ (and:DI (rotate:DI (match_dup 1)
+ (match_dup 4))
+ (match_dup 5)))
+ (set (match_dup 0)
+ (and:DI (rotate:DI (match_dup 0)
+ (match_dup 6))
+ (match_dup 7)))]
+ "
+{
+ build_mask64_2_operands (operands[2], &operands[4]);
+}")
(define_insn "*anddi3_internal2"
- [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,?y,?y,??y,??y")
- (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,")
- (match_operand:DI 2 "and64_operand" "r,S,K,J,r,S,K,J"))
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,x,?y,?y,??y,??y,?y")
+ (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
+ (match_operand:DI 2 "and64_2_operand" "r,S,K,J,t,r,S,K,J,t"))
(const_int 0)))
- (clobber (match_scratch:DI 3 "=r,r,r,r,r,r,r,r"))
- (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,x,x"))]
+ (clobber (match_scratch:DI 3 "=r,r,r,r,r,r,r,r,r,r"))
+ (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,x,x,X"))]
"TARGET_POWERPC64"
"@
and. %3,%1,%2
@@ -7164,9 +7697,11 @@
#
#
#
+ #
+ #
#"
- [(set_attr "type" "compare,delayed_compare,compare,compare,compare,delayed_compare,compare,compare")
- (set_attr "length" "4,4,4,4,8,8,8,8")])
+ [(set_attr "type" "compare,delayed_compare,compare,compare,delayed_compare,compare,compare,compare,compare,compare")
+ (set_attr "length" "4,4,4,4,8,8,8,8,8,12")])
(define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
@@ -7185,14 +7720,39 @@
(const_int 0)))]
"")
+(define_split
+ [(set (match_operand:CC 0 "cc_reg_operand" "")
+ (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "mask64_2_operand" ""))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (match_scratch:CC 4 ""))]
+ "TARGET_POWERPC64 && reload_completed
+ && (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
+ && !mask64_operand (operands[2], DImode)"
+ [(set (match_dup 3)
+ (and:DI (rotate:DI (match_dup 1)
+ (match_dup 5))
+ (match_dup 6)))
+ (parallel [(set (match_dup 0)
+ (compare:CC (and:DI (rotate:DI (match_dup 3)
+ (match_dup 7))
+ (match_dup 8))
+ (const_int 0)))
+ (clobber (match_dup 3))])]
+ "
+{
+ build_mask64_2_operands (operands[2], &operands[5]);
+}")
+
(define_insn "*anddi3_internal3"
- [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,?y,?y,??y,??y")
- (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r")
- (match_operand:DI 2 "and64_operand" "r,S,K,J,r,S,K,J"))
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,x,?y,?y,??y,??y,?y")
+ (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
+ (match_operand:DI 2 "and64_2_operand" "r,S,K,J,t,r,S,K,J,t"))
(const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r")
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r,r,r")
(and:DI (match_dup 1) (match_dup 2)))
- (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,x,x"))]
+ (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,x,x,X"))]
"TARGET_POWERPC64"
"@
and. %0,%1,%2
@@ -7202,9 +7762,11 @@
#
#
#
+ #
+ #
#"
- [(set_attr "type" "compare,delayed_compare,compare,compare,compare,delayed_compare,compare,compare")
- (set_attr "length" "4,4,4,4,8,8,8,8")])
+ [(set_attr "type" "compare,delayed_compare,compare,compare,delayed_compare,compare,compare,compare,compare,compare")
+ (set_attr "length" "4,4,4,4,8,8,8,8,8,12")])
(define_split
[(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
@@ -7223,6 +7785,35 @@
(const_int 0)))]
"")
+(define_split
+ [(set (match_operand:CC 3 "cc_reg_operand" "")
+ (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "mask64_2_operand" ""))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "")
+ (and:DI (match_dup 1) (match_dup 2)))
+ (clobber (match_scratch:CC 4 ""))]
+ "TARGET_POWERPC64 && reload_completed
+ && (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
+ && !mask64_operand (operands[2], DImode)"
+ [(set (match_dup 0)
+ (and:DI (rotate:DI (match_dup 1)
+ (match_dup 5))
+ (match_dup 6)))
+ (parallel [(set (match_dup 3)
+ (compare:CC (and:DI (rotate:DI (match_dup 0)
+ (match_dup 7))
+ (match_dup 8))
+ (const_int 0)))
+ (set (match_dup 0)
+ (and:DI (rotate:DI (match_dup 0)
+ (match_dup 7))
+ (match_dup 8)))])]
+ "
+{
+ build_mask64_2_operands (operands[2], &operands[5]);
+}")
+
(define_expand "iordi3"
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(ior:DI (match_operand:DI 1 "gpc_reg_operand" "")
@@ -7622,7 +8213,7 @@
(define_insn "movsi_low"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (mem:SI (lo_sum:SI (match_operand:SI 1 "register_operand" "b")
+ (mem:SI (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
(match_operand 2 "" ""))))]
"TARGET_MACHO && ! TARGET_64BIT"
"{l|lwz} %0,lo16(%2)(%1)"
@@ -7630,7 +8221,7 @@
(set_attr "length" "4")])
(define_insn "movsi_low_st"
- [(set (mem:SI (lo_sum:SI (match_operand:SI 1 "register_operand" "b")
+ [(set (mem:SI (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
(match_operand 2 "" "")))
(match_operand:SI 0 "gpc_reg_operand" "r"))]
"TARGET_MACHO && ! TARGET_64BIT"
@@ -7640,9 +8231,9 @@
(define_insn "movdf_low"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f,!r")
- (mem:DF (lo_sum:SI (match_operand:SI 1 "register_operand" "b,b")
+ (mem:DF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b")
(match_operand 2 "" ""))))]
- "TARGET_MACHO && TARGET_HARD_FLOAT && ! TARGET_64BIT"
+ "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
"*
{
switch (which_alternative)
@@ -7670,19 +8261,19 @@
(set_attr "length" "4,12")])
(define_insn "movdf_low_st"
- [(set (mem:DF (lo_sum:SI (match_operand:SI 1 "register_operand" "b")
+ [(set (mem:DF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
(match_operand 2 "" "")))
(match_operand:DF 0 "gpc_reg_operand" "f"))]
- "TARGET_MACHO && TARGET_HARD_FLOAT && ! TARGET_64BIT"
+ "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
"stfd %0,lo16(%2)(%1)"
[(set_attr "type" "store")
(set_attr "length" "4")])
(define_insn "movsf_low"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f,!r")
- (mem:SF (lo_sum:SI (match_operand:SI 1 "register_operand" "b,b")
+ (mem:SF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b")
(match_operand 2 "" ""))))]
- "TARGET_MACHO && TARGET_HARD_FLOAT && ! TARGET_64BIT"
+ "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
"@
lfs %0,lo16(%2)(%1)
{l|lwz} %0,lo16(%2)(%1)"
@@ -7690,10 +8281,10 @@
(set_attr "length" "4")])
(define_insn "movsf_low_st"
- [(set (mem:SF (lo_sum:SI (match_operand:SI 1 "register_operand" "b,b")
+ [(set (mem:SF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b")
(match_operand 2 "" "")))
(match_operand:SF 0 "gpc_reg_operand" "f,!r"))]
- "TARGET_MACHO && TARGET_HARD_FLOAT && ! TARGET_64BIT"
+ "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
"@
stfs %0,lo16(%2)(%1)
{st|stw} %0,lo16(%2)(%1)"
@@ -7718,7 +8309,7 @@
mt%0 %1
mt%0 %1
mt%0 %1
- cror 0,0,0"
+ {cror 0,0,0|nop}"
[(set_attr "type" "*,*,load,store,*,*,*,*,*,*,mtjmpr,*,*")
(set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4")])
@@ -7736,9 +8327,12 @@
(ior:SI (match_dup 0)
(match_dup 3)))]
"
-{
- operands[2] = GEN_INT (INTVAL (operands[1]) & (~ (HOST_WIDE_INT) 0xffff));
- operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff);
+{ rtx tem = rs6000_emit_set_const (operands[0], SImode, operands[1], 2);
+
+ if (tem == operands[0])
+ DONE;
+ else
+ FAIL;
}")
(define_insn "*movsi_internal2"
@@ -7771,7 +8365,7 @@
""
"{ rs6000_emit_move (operands[0], operands[1], HImode); DONE; }")
-(define_insn ""
+(define_insn "*movhi_internal"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r,r,*q,*c*l,*h")
(match_operand:HI 1 "input_operand" "r,m,r,i,*h,r,r,0"))]
"gpc_reg_operand (operands[0], HImode)
@@ -7784,7 +8378,7 @@
mf%1 %0
mt%0 %1
mt%0 %1
- cror 0,0,0"
+ {cror 0,0,0|nop}"
[(set_attr "type" "*,load,store,*,*,*,mtjmpr,*")])
(define_expand "movqi"
@@ -7793,7 +8387,7 @@
""
"{ rs6000_emit_move (operands[0], operands[1], QImode); DONE; }")
-(define_insn ""
+(define_insn "*movqi_internal"
[(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,r,r,*q,*c*l,*h")
(match_operand:QI 1 "input_operand" "r,m,r,i,*h,r,r,0"))]
"gpc_reg_operand (operands[0], QImode)
@@ -7806,7 +8400,7 @@
mf%1 %0
mt%0 %1
mt%0 %1
- cror 0,0,0"
+ {cror 0,0,0|nop}"
[(set_attr "type" "*,load,store,*,*,*,mtjmpr,*")])
;; Here is how to move condition codes around. When we store CC data in
@@ -7818,9 +8412,9 @@
""
"")
-(define_insn ""
- [(set (match_operand:CC 0 "nonimmediate_operand" "=y,x,y,r,r,r,r,m")
- (match_operand:CC 1 "nonimmediate_operand" "y,r,r,x,y,r,m,r"))]
+(define_insn "*movcc_internal1"
+ [(set (match_operand:CC 0 "nonimmediate_operand" "=y,x,y,r,r,r,cl,q,r,r,m")
+ (match_operand:CC 1 "nonimmediate_operand" "y,r,r,x,y,r,r,r,h,m,r"))]
"register_operand (operands[0], CCmode)
|| register_operand (operands[1], CCmode)"
"@
@@ -7830,10 +8424,13 @@
mfcr %0
mfcr %0\;{rlinm|rlwinm} %0,%0,%f1,0xf0000000
mr %0,%1
+ mt%0 %1
+ mt%0 %1
+ mf%1 %0
{l%U1%X1|lwz%U1%X1} %0,%1
{st%U0%U1|stw%U0%U1} %1,%0"
- [(set_attr "type" "*,*,*,compare,*,*,load,store")
- (set_attr "length" "*,*,12,*,8,*,*,*")])
+ [(set_attr "type" "cr_logical,cr_logical,cr_logical,cr_logical,cr_logical,*,*,mtjmpr,*,load,store")
+ (set_attr "length" "4,4,12,4,8,4,4,4,4,4,4")])
;; For floating-point, we normally deal with the floating-point registers
;; unless -msoft-float is used. The sole exception is that parameter passing
@@ -7868,14 +8465,15 @@
else
operands[2] = gen_lowpart (SImode, operands[0]);
- operands[3] = GEN_INT (trunc_int_for_mode (l, SImode));
+ operands[3] = gen_int_mode (l, SImode);
}")
(define_insn "*movsf_hardfloat"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=!r,!r,m,f,f,m,!r,!r")
- (match_operand:SF 1 "input_operand" "r,m,r,f,m,f,G,Fn"))]
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=!r,!r,m,f,f,m,!cl,!q,!r,!r,!r")
+ (match_operand:SF 1 "input_operand" "r,m,r,f,m,f,r,r,h,G,Fn"))]
"(gpc_reg_operand (operands[0], SFmode)
- || gpc_reg_operand (operands[1], SFmode)) && TARGET_HARD_FLOAT"
+ || gpc_reg_operand (operands[1], SFmode))
+ && (TARGET_HARD_FLOAT && TARGET_FPRS)"
"@
mr %0,%1
{l%U1%X1|lwz%U1%X1} %0,%1
@@ -7883,18 +8481,25 @@
fmr %0,%1
lfs%U1%X1 %0,%1
stfs%U0%X0 %1,%0
+ mt%0 %1
+ mt%0 %1
+ mf%1 %0
#
#"
- [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*")
- (set_attr "length" "4,4,4,4,4,4,4,8")])
+ [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,mtjmpr,*,*,*")
+ (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8")])
(define_insn "*movsf_softfloat"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,r")
- (match_operand:SF 1 "input_operand" "r,m,r,I,L,R,G,Fn"))]
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,cl,q,r,r,m,r,r,r,r,r")
+ (match_operand:SF 1 "input_operand" "r,r,r,h,m,r,I,L,R,G,Fn"))]
"(gpc_reg_operand (operands[0], SFmode)
- || gpc_reg_operand (operands[1], SFmode)) && TARGET_SOFT_FLOAT"
+ || gpc_reg_operand (operands[1], SFmode))
+ && (TARGET_SOFT_FLOAT || !TARGET_FPRS)"
"@
mr %0,%1
+ mt%0 %1
+ mt%0 %1
+ mf%1 %0
{l%U1%X1|lwz%U1%X1} %0,%1
{st%U0%X0|stw%U0%X0} %1,%0
{lil|li} %0,%1
@@ -7902,8 +8507,8 @@
{cal|la} %0,%a1
#
#"
- [(set_attr "type" "*,load,store,*,*,*,*,*")
- (set_attr "length" "4,4,4,4,4,4,4,8")])
+ [(set_attr "type" "*,mtjmpr,*,*,load,store,*,*,*,*,*")
+ (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8")])
(define_expand "movdf"
@@ -7933,7 +8538,7 @@
operands[4] = (value & 0x80000000) ? constm1_rtx : const0_rtx;
#else
operands[4] = GEN_INT (value >> 32);
- operands[1] = GEN_INT ((value & 0x7fffffff) - (value & 0x80000000));
+ operands[1] = GEN_INT (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
#endif
}")
@@ -7958,8 +8563,8 @@
operands[2] = operand_subword (operands[0], endian, 0, DFmode);
operands[3] = operand_subword (operands[0], 1 - endian, 0, DFmode);
- operands[4] = GEN_INT (trunc_int_for_mode (l[endian], SImode));
- operands[5] = GEN_INT (trunc_int_for_mode (l[1 - endian], SImode));
+ operands[4] = gen_int_mode (l[endian], SImode);
+ operands[5] = gen_int_mode (l[1 - endian], SImode);
}")
(define_split
@@ -7984,10 +8589,10 @@
operands[2] = gen_lowpart (DImode, operands[0]);
/* HIGHPART is lower memory address when WORDS_BIG_ENDIAN. */
#if HOST_BITS_PER_WIDE_INT >= 64
- val = ((HOST_WIDE_INT)(unsigned long)l[endian] << 32 |
- ((HOST_WIDE_INT)(unsigned long)l[1 - endian]));
+ val = ((HOST_WIDE_INT)(unsigned long)l[endian] << 32
+ | ((HOST_WIDE_INT)(unsigned long)l[1 - endian]));
- operands[3] = immed_double_const (val, -(val < 0), DImode);
+ operands[3] = gen_int_mode (val, DImode);
#else
operands[3] = immed_double_const (l[1 - endian], l[endian], DImode);
#endif
@@ -8000,9 +8605,9 @@
;; The "??" is a kludge until we can figure out a more reasonable way
;; of handling these non-offsettable values.
(define_insn "*movdf_hardfloat32"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,!r,!r,!r,f,f,m")
- (match_operand:DF 1 "input_operand" "r,m,r,G,H,F,f,m,f"))]
- "! TARGET_POWERPC64 && TARGET_HARD_FLOAT
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,f,f,m,!r,!r,!r")
+ (match_operand:DF 1 "input_operand" "r,m,r,f,m,f,G,H,F"))]
+ "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS
&& (gpc_reg_operand (operands[0], DFmode)
|| gpc_reg_operand (operands[1], DFmode))"
"*
@@ -8078,24 +8683,24 @@
return \"\";
}
case 3:
+ return \"fmr %0,%1\";
case 4:
+ return \"lfd%U1%X1 %0,%1\";
case 5:
- return \"#\";
+ return \"stfd%U0%X0 %1,%0\";
case 6:
- return \"fmr %0,%1\";
case 7:
- return \"lfd%U1%X1 %0,%1\";
case 8:
- return \"stfd%U0%X0 %1,%0\";
+ return \"#\";
}
}"
- [(set_attr "type" "*,load,store,*,*,*,fp,fpload,fpstore")
- (set_attr "length" "8,16,16,8,12,16,*,*,*")])
+ [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*")
+ (set_attr "length" "8,16,16,4,4,4,8,12,16")])
(define_insn "*movdf_softfloat32"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,r,r,r")
(match_operand:DF 1 "input_operand" "r,m,r,G,H,F"))]
- "! TARGET_POWERPC64 && TARGET_SOFT_FLOAT
+ "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
&& (gpc_reg_operand (operands[0], DFmode)
|| gpc_reg_operand (operands[1], DFmode))"
"*
@@ -8134,50 +8739,56 @@
(set_attr "length" "8,8,8,8,12,16")])
(define_insn "*movdf_hardfloat64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,!r,!r,!r,f,f,m")
- (match_operand:DF 1 "input_operand" "r,m,r,G,H,F,f,m,f"))]
- "TARGET_POWERPC64 && TARGET_HARD_FLOAT
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=!r,??r,m,f,f,m,!cl,!r,!r,!r,!r")
+ (match_operand:DF 1 "input_operand" "r,m,r,f,m,f,r,h,G,H,F"))]
+ "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS
&& (gpc_reg_operand (operands[0], DFmode)
|| gpc_reg_operand (operands[1], DFmode))"
"@
mr %0,%1
ld%U1%X1 %0,%1
std%U0%X0 %1,%0
- #
- #
- #
fmr %0,%1
lfd%U1%X1 %0,%1
- stfd%U0%X0 %1,%0"
- [(set_attr "type" "*,load,store,*,*,*,fp,fpload,fpstore")
- (set_attr "length" "4,4,4,8,12,16,4,4,4")])
+ stfd%U0%X0 %1,%0
+ mt%0 %1
+ mf%1 %0
+ #
+ #
+ #"
+ [(set_attr "type" "*,load,store,fp,fpload,fpstore,mtjmpr,*,*,*,*")
+ (set_attr "length" "4,4,4,4,4,4,4,4,8,12,16")])
(define_insn "*movdf_softfloat64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,r,r,r")
- (match_operand:DF 1 "input_operand" "r,m,r,G,H,F"))]
- "TARGET_POWERPC64 && TARGET_SOFT_FLOAT
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=r,cl,r,r,m,r,r,r")
+ (match_operand:DF 1 "input_operand" "r,r,h,m,r,G,H,F"))]
+ "TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
&& (gpc_reg_operand (operands[0], DFmode)
|| gpc_reg_operand (operands[1], DFmode))"
"@
mr %0,%1
+ mt%0 %1
+ mf%1 %0
ld%U1%X1 %0,%1
std%U0%X0 %1,%0
#
#
#"
- [(set_attr "type" "*,load,store,*,*,*")
- (set_attr "length" "*,*,*,8,12,16")])
+ [(set_attr "type" "*,*,*,load,store,*,*,*")
+ (set_attr "length" "4,4,4,4,4,8,12,16")])
(define_expand "movtf"
[(set (match_operand:TF 0 "general_operand" "")
(match_operand:TF 1 "any_operand" ""))]
- "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
+ "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_LONG_DOUBLE_128"
"{ rs6000_emit_move (operands[0], operands[1], TFmode); DONE; }")
(define_insn "*movtf_internal"
[(set (match_operand:TF 0 "nonimmediate_operand" "=f,f,m,!r,!r,!r")
(match_operand:TF 1 "input_operand" "f,m,f,G,H,F"))]
- "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128
+ "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_LONG_DOUBLE_128
&& (gpc_reg_operand (operands[0], TFmode)
|| gpc_reg_operand (operands[1], TFmode))"
"*
@@ -8195,9 +8806,9 @@
else
return \"fmr %0,%1\;fmr %L0,%L1\";
case 1:
- return \"lfd %0,%1\;lfd %L0,%L1\";
+ return \"lfd %0,%1\;lfd %L0,%Y1\";
case 2:
- return \"stfd %1,%0\;stfd %L1,%L0\";
+ return \"stfd %1,%0\;stfd %L1,%Y0\";
case 3:
case 4:
case 5:
@@ -8209,104 +8820,185 @@
(define_split
[(set (match_operand:TF 0 "gpc_reg_operand" "")
- (match_operand:TF 1 "const_double_operand" ""))]
- "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
- [(set (match_dup 3) (match_dup 1))
- (set (match_dup 0)
- (float_extend:TF (match_dup 3)))]
+ (match_operand:TF 1 "easy_fp_constant" ""))]
+ "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_POWERPC64
+ && TARGET_LONG_DOUBLE_128 && reload_completed
+ && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && REGNO (SUBREG_REG (operands[0])) <= 31))"
+ [(set (match_dup 2) (match_dup 6))
+ (set (match_dup 3) (match_dup 7))
+ (set (match_dup 4) (match_dup 8))
+ (set (match_dup 5) (match_dup 9))]
"
{
- operands[2] = operand_subword (operands[1], 0, 0, DFmode);
- operands[3] = gen_reg_rtx (DFmode);
+ long l[4];
+ REAL_VALUE_TYPE rv;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, l);
+
+ operands[2] = operand_subword (operands[0], 0, 0, TFmode);
+ operands[3] = operand_subword (operands[0], 1, 0, TFmode);
+ operands[4] = operand_subword (operands[0], 2, 0, TFmode);
+ operands[5] = operand_subword (operands[0], 3, 0, TFmode);
+ operands[6] = gen_int_mode (l[0], SImode);
+ operands[7] = gen_int_mode (l[1], SImode);
+ operands[8] = gen_int_mode (l[2], SImode);
+ operands[9] = gen_int_mode (l[3], SImode);
}")
-(define_insn_and_split "extenddftf2"
- [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
- (float_extend:TF (match_operand:DF 1 "gpc_reg_operand" "f")))]
- "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
- "#"
- ""
- [(set (match_dup 2) (match_dup 3))]
+(define_split
+ [(set (match_operand:TF 0 "gpc_reg_operand" "")
+ (match_operand:TF 1 "easy_fp_constant" ""))]
+ "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64
+ && TARGET_LONG_DOUBLE_128 && reload_completed
+ && ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && REGNO (SUBREG_REG (operands[0])) <= 31))"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
"
{
- operands[2] = gen_rtx_REG (DFmode, REGNO (operands[0] + 1));
- operands[3] = CONST0_RTX (DFmode);
+ long l[4];
+ REAL_VALUE_TYPE rv;
+ HOST_WIDE_INT val;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, l);
+
+ operands[2] = gen_lowpart (DImode, operands[0]);
+ operands[3] = gen_highpart (DImode, operands[0]);
+#if HOST_BITS_PER_WIDE_INT >= 64
+ val = ((HOST_WIDE_INT)(unsigned long)l[0] << 32
+ | ((HOST_WIDE_INT)(unsigned long)l[1]));
+ operands[4] = gen_int_mode (val, DImode);
+
+ val = ((HOST_WIDE_INT)(unsigned long)l[2] << 32
+ | ((HOST_WIDE_INT)(unsigned long)l[3]));
+ operands[5] = gen_int_mode (val, DImode);
+#else
+ operands[4] = immed_double_const (l[1], l[0], DImode);
+ operands[5] = immed_double_const (l[3], l[2], DImode);
+#endif
}")
-(define_insn_and_split "extendsftf2"
+(define_insn "extenddftf2"
+ [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
+ (float_extend:TF (match_operand:DF 1 "gpc_reg_operand" "f")))]
+ "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_LONG_DOUBLE_128"
+ "*
+{
+ if (REGNO (operands[0]) == REGNO (operands[1]))
+ return \"fsub %L0,%L0,%L0\";
+ else
+ return \"fmr %0,%1\;fsub %L0,%L0,%L0\";
+}"
+ [(set_attr "type" "fp")])
+
+(define_insn "extendsftf2"
[(set (match_operand:TF 0 "gpc_reg_operand" "=f")
(float_extend:TF (match_operand:SF 1 "gpc_reg_operand" "f")))]
- "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
- "#"
- ""
- [(set (match_dup 2) (match_dup 3))]
- "
+ "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_LONG_DOUBLE_128"
+ "*
{
- operands[2] = gen_rtx_REG (SFmode, REGNO (operands[0] + 1));
- operands[3] = CONST0_RTX (SFmode);
-}")
+ if (REGNO (operands[0]) == REGNO (operands[1]))
+ return \"fsub %L0,%L0,%L0\";
+ else
+ return \"fmr %0,%1\;fsub %L0,%L0,%L0\";
+}"
+ [(set_attr "type" "fp")])
(define_insn "trunctfdf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "f")))]
- "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
+ "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_LONG_DOUBLE_128"
"fadd %0,%1,%L1"
[(set_attr "type" "fp")
(set_attr "length" "8")])
(define_insn_and_split "trunctfsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
- (float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "f")))]
- "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
+ (float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "f")))
+ (clobber (match_scratch:DF 2 "=f"))]
+ "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT
+ && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"#"
- ""
+ "&& reload_completed"
[(set (match_dup 2)
(float_truncate:DF (match_dup 1)))
(set (match_dup 0)
(float_truncate:SF (match_dup 2)))]
- "
-{
- operands[2] = gen_reg_rtx (DFmode);
-}")
+ "")
-(define_expand "floatditf2"
+(define_insn_and_split "floatditf2"
+ [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
+ (float:TF (match_operand:DI 1 "gpc_reg_operand" "*f")))
+ (clobber (match_scratch:DF 2 "=f"))]
+ "DEFAULT_ABI == ABI_AIX && TARGET_POWERPC64
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+ "#"
+ "&& reload_completed"
[(set (match_dup 2)
- (float:DF (match_operand:DI 1 "gpc_reg_operand" "")))
- (set (match_operand:TF 0 "gpc_reg_operand" "")
+ (float:DF (match_dup 1)))
+ (set (match_dup 0)
(float_extend:TF (match_dup 2)))]
- "DEFAULT_ABI == ABI_AIX && TARGET_POWERPC64
- && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
- "{ operands[2] = gen_reg_rtx (DFmode); }")
+ "")
-(define_expand "floatsitf2"
+(define_insn_and_split "floatsitf2"
+ [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
+ (float:TF (match_operand:SI 1 "gpc_reg_operand" "r")))
+ (clobber (match_scratch:DF 2 "=f"))]
+ "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_LONG_DOUBLE_128"
+ "#"
+ "&& reload_completed"
[(set (match_dup 2)
- (float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
- (set (match_operand:TF 0 "gpc_reg_operand" "")
+ (float:DF (match_dup 1)))
+ (set (match_dup 0)
(float_extend:TF (match_dup 2)))]
- "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
- "{ operands[2] = gen_reg_rtx (DFmode); }")
+ "")
-(define_expand "fix_trunctfdi2"
- [(set (match_dup 2)
- (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (fix:SI (match_dup 2)))]
+(define_insn_and_split "fix_trunctfdi2"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=*f")
+ (fix:DI (match_operand:TF 1 "gpc_reg_operand" "f")))
+ (clobber (match_scratch:DF 2 "=f"))]
"DEFAULT_ABI == ABI_AIX && TARGET_POWERPC64
- && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
- "{ operands[2] = gen_reg_rtx (DFmode); }")
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2)
+ (float_truncate:DF (match_dup 1)))
+ (set (match_dup 0)
+ (fix:DI (match_dup 2)))]
+ "")
-(define_expand "fix_trunctfsi2"
+(define_insn_and_split "fix_trunctfsi2"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (fix:SI (match_operand:TF 1 "gpc_reg_operand" "f")))
+ (clobber (match_scratch:DF 2 "=f"))]
+ "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_LONG_DOUBLE_128"
+ "#"
+ "&& reload_completed"
[(set (match_dup 2)
- (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
+ (float_truncate:DF (match_dup 1)))
+ (set (match_dup 0)
(fix:SI (match_dup 2)))]
- "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
- "{ operands[2] = gen_reg_rtx (DFmode); }")
+ "")
(define_insn "negtf2"
[(set (match_operand:TF 0 "gpc_reg_operand" "=f")
(neg:TF (match_operand:TF 1 "gpc_reg_operand" "f")))]
- "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
+ "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_LONG_DOUBLE_128"
"*
{
if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
@@ -8320,7 +9012,8 @@
(define_insn "abstf2"
[(set (match_operand:TF 0 "gpc_reg_operand" "=f")
(abs:TF (match_operand:TF 1 "gpc_reg_operand" "f")))]
- "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
+ "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_LONG_DOUBLE_128"
"*
{
if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
@@ -8334,7 +9027,8 @@
(define_insn ""
[(set (match_operand:TF 0 "gpc_reg_operand" "=f")
(neg:TF (abs:TF (match_operand:TF 1 "gpc_reg_operand" "f"))))]
- "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
+ "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_LONG_DOUBLE_128"
"*
{
if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
@@ -8400,7 +9094,7 @@
}
}"
[(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*,*,*")
- (set_attr "length" "8,8,8,*,*,*,8,12,8,12,16")])
+ (set_attr "length" "8,8,8,4,4,4,8,12,8,12,16")])
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
@@ -8419,7 +9113,7 @@
operands[4] = (value & 0x80000000) ? constm1_rtx : const0_rtx;
#else
operands[4] = GEN_INT (value >> 32);
- operands[1] = GEN_INT ((value & 0x7fffffff) - (value & 0x80000000));
+ operands[1] = GEN_INT (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
#endif
}")
@@ -8439,8 +9133,34 @@
operands[5] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
}")
+(define_split
+ [(set (match_operand:TI 0 "gpc_reg_operand" "")
+ (match_operand:TI 1 "const_double_operand" ""))]
+ "TARGET_POWERPC64"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+ "
+{
+ operands[2] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN == 0,
+ TImode);
+ operands[3] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN != 0,
+ TImode);
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
+ operands[5] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
+ }
+ else if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ operands[4] = GEN_INT (- (INTVAL (operands[1]) < 0));
+ operands[5] = operands[1];
+ }
+ else
+ FAIL;
+}")
+
(define_insn "*movdi_internal64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,f,f,m,r,*h,*h")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,?f,f,m,r,*h,*h")
(match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,f,m,f,*h,r,0"))]
"TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], DImode)
@@ -8458,7 +9178,7 @@
stfd%U0%X0 %1,%0
mf%1 %0
mt%0 %1
- cror 0,0,0"
+ {cror 0,0,0|nop}"
[(set_attr "type" "*,load,store,*,*,*,*,fp,fpload,fpstore,*,mtjmpr,*")
(set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4")])
@@ -8615,12 +9335,11 @@
}
}"
[(set_attr "type" "store,store,*,load,load")
- (set_attr "length" "*,16,16,*,16")])
+ (set_attr "length" "4,16,16,4,16")])
(define_insn "*movti_string"
- [(set (match_operand:TI 0 "reg_or_mem_operand" "=m,????r,????r")
- (match_operand:TI 1 "reg_or_mem_operand" "r,r,m"))
- (clobber (match_scratch:SI 2 "=X,X,X"))]
+ [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
+ (match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))]
"TARGET_STRING && ! TARGET_POWER && ! TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
"*
@@ -8631,9 +9350,10 @@
abort ();
case 0:
- return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\;{st|stw} %Y1,%Y0\;{st|stw} %Z1,%Z0\";
-
+ return \"{stsi|stswi} %1,%P0,16\";
case 1:
+ return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\;{st|stw} %Y1,%Y0\;{st|stw} %Z1,%Z0\";
+ case 2:
/* Normally copy registers with lowest numbered register copied first.
But copy in the other order if the first register of the output
is the second, third, or fourth register in the input. */
@@ -8642,7 +9362,13 @@
return \"mr %Z0,%Z1\;mr %Y0,%Y1\;mr %L0,%L1\;mr %0,%1\";
else
return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
- case 2:
+ case 3:
+ /* If the address is not used in the output, we can use lsi. Otherwise,
+ fall through to generating four loads. */
+ if (! reg_overlap_mentioned_p (operands[0], operands[1]))
+ return \"{lsi|lswi} %0,%P1,16\";
+ /* ... fall through ... */
+ case 4:
/* If the address register is the same as the register for the lowest-
addressed word, load it last. Similarly for the next two words.
Otherwise load lowest address to highest. */
@@ -8659,8 +9385,8 @@
return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\";
}
}"
- [(set_attr "type" "store,*,load")
- (set_attr "length" "16,16,16")])
+ [(set_attr "type" "store,store,*,load,load")
+ (set_attr "length" "4,16,16,4,16")])
(define_insn "*movti_ppc64"
[(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m")
@@ -8731,7 +9457,7 @@
for (i = 0; i < count; i++)
XVECEXP (operands[3], 0, i)
= gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, regno + i),
- adjust_address (op1, SImode, i * 4));
+ adjust_address_nv (op1, SImode, i * 4));
}")
(define_insn "*ldmsi8"
@@ -8881,14 +9607,14 @@
op0 = replace_equiv_address (operands[0], to);
XVECEXP (operands[3], 0, 0)
- = gen_rtx_SET (VOIDmode, adjust_address (op0, SImode, 0), operands[1]);
+ = gen_rtx_SET (VOIDmode, adjust_address_nv (op0, SImode, 0), operands[1]);
XVECEXP (operands[3], 0, 1) = gen_rtx_CLOBBER (VOIDmode,
gen_rtx_SCRATCH (SImode));
for (i = 1; i < count; i++)
XVECEXP (operands[3], 0, i + 1)
= gen_rtx_SET (VOIDmode,
- adjust_address (op0, SImode, i * 4),
+ adjust_address_nv (op0, SImode, i * 4),
gen_rtx_REG (SImode, regno + i));
}")
@@ -9426,7 +10152,7 @@
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HARD_FLOAT && TARGET_UPDATE"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_UPDATE"
"@
lfsux %3,%0,%2
lfsu %3,%2(%0)"
@@ -9438,7 +10164,7 @@
(match_operand:SF 3 "gpc_reg_operand" "f,f"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HARD_FLOAT && TARGET_UPDATE"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_UPDATE"
"@
stfsux %3,%0,%2
stfsu %3,%2(%0)"
@@ -9450,7 +10176,7 @@
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_SOFT_FLOAT && TARGET_UPDATE"
+ "(TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_UPDATE"
"@
{lux|lwzux} %3,%0,%2
{lu|lwzu} %3,%2(%0)"
@@ -9462,7 +10188,7 @@
(match_operand:SF 3 "gpc_reg_operand" "r,r"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_SOFT_FLOAT && TARGET_UPDATE"
+ "(TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_UPDATE"
"@
{stux|stwux} %3,%0,%2
{stu|stwu} %3,%2(%0)"
@@ -9474,7 +10200,7 @@
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HARD_FLOAT && TARGET_UPDATE"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_UPDATE"
"@
lfdux %3,%0,%2
lfdu %3,%2(%0)"
@@ -9486,7 +10212,7 @@
(match_operand:DF 3 "gpc_reg_operand" "f,f"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HARD_FLOAT && TARGET_UPDATE"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_UPDATE"
"@
stfdux %3,%0,%2
stfdu %3,%2(%0)"
@@ -9500,7 +10226,7 @@
(set (match_operand:DF 2 "gpc_reg_operand" "=f")
(match_operand:DF 3 "memory_operand" ""))]
"TARGET_POWER2
- && TARGET_HARD_FLOAT
+ && TARGET_HARD_FLOAT && TARGET_FPRS
&& registers_ok_for_quad_peep (operands[0], operands[2])
&& ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
&& addrs_ok_for_quad_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
@@ -9512,7 +10238,7 @@
(set (match_operand:DF 2 "memory_operand" "")
(match_operand:DF 3 "gpc_reg_operand" "f"))]
"TARGET_POWER2
- && TARGET_HARD_FLOAT
+ && TARGET_HARD_FLOAT && TARGET_FPRS
&& registers_ok_for_quad_peep (operands[1], operands[3])
&& ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
&& addrs_ok_for_quad_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
@@ -9697,7 +10423,7 @@
(match_operand:SI 1 "immediate_operand" "s"))
(unspec [(match_dup 1)] 7)]
"TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
- "bl %1\\n%1:"
+ "bcl 20,31,%1\\n%1:"
[(set_attr "type" "branch")
(set_attr "length" "4")])
@@ -9706,13 +10432,13 @@
(match_operand:SI 1 "immediate_operand" "s"))
(unspec [(match_dup 1) (match_operand 2 "immediate_operand" "s")] 6)]
"TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
- "bl %1\\n\\t.long %2-%1+4\\n%1:"
+ "bcl 20,31,%1\\n\\t.long %2-%1+4\\n%1:"
[(set_attr "type" "branch")
(set_attr "length" "8")])
(define_insn "load_toc_v4_PIC_2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "b")
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
(minus:SI (match_operand:SI 2 "immediate_operand" "s")
(match_operand:SI 3 "immediate_operand" "s")))))]
"TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
@@ -9721,30 +10447,53 @@
(define_insn "load_macho_picbase"
[(set (match_operand:SI 0 "register_operand" "=l")
- (unspec:SI [(const_int 0)] 15))]
+ (unspec:SI [(match_operand:SI 1 "immediate_operand" "s")] 15))]
"(DEFAULT_ABI == ABI_DARWIN) && flag_pic"
- "*
-{
-#if TARGET_MACHO
- char *picbase = machopic_function_base_name ();
- operands[1] = gen_rtx_SYMBOL_REF (Pmode, ggc_alloc_string (picbase, -1));
-#endif
- return \"bcl 20,31,%1\\n%1:\";
-}"
+ "bcl 20,31,%1\\n%1:"
[(set_attr "type" "branch")
(set_attr "length" "4")])
+(define_insn "macho_correct_pic"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (plus:SI (match_operand:SI 1 "gpc_reg_operand" "=r")
+ (unspec:SI [(match_operand:SI 2 "immediate_operand" "s")
+ (match_operand:SI 3 "immediate_operand" "s")]
+ 16)))]
+ "DEFAULT_ABI == ABI_DARWIN"
+ "addis %0,%1,ha16(%2-%3)\n\taddi %1,%1,lo16(%2-%3)"
+ [(set_attr "length" "8")])
+
;; If the TOC is shared over a translation unit, as happens with all
;; the kinds of PIC that we support, we need to restore the TOC
;; pointer only when jumping over units of translation.
+;; On Darwin, we need to reload the picbase.
(define_expand "builtin_setjmp_receiver"
[(use (label_ref (match_operand 0 "" "")))]
"(DEFAULT_ABI == ABI_V4 && flag_pic == 1)
- || (TARGET_TOC && TARGET_MINIMAL_TOC)"
+ || (TARGET_TOC && TARGET_MINIMAL_TOC)
+ || (DEFAULT_ABI == ABI_DARWIN && flag_pic)"
"
{
- rs6000_emit_load_toc_table (FALSE);
+#if TARGET_MACHO
+ if (DEFAULT_ABI == ABI_DARWIN)
+ {
+ char *picbase = machopic_function_base_name ();
+ rtx picrtx = gen_rtx_SYMBOL_REF (Pmode, ggc_alloc_string (picbase, -1));
+ rtx picreg = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
+ rtx tmplabrtx;
+ char tmplab[20];
+
+ ASM_GENERATE_INTERNAL_LABEL(tmplab, \"LSJR\",
+ CODE_LABEL_NUMBER (operands[0]));
+ tmplabrtx = gen_rtx_SYMBOL_REF (Pmode, ggc_alloc_string (tmplab, -1));
+
+ emit_insn (gen_load_macho_picbase (picreg, tmplabrtx));
+ emit_insn (gen_macho_correct_pic (picreg, picreg, picrtx, tmplabrtx));
+ }
+ else
+#endif
+ rs6000_emit_load_toc_table (FALSE);
DONE;
}")
@@ -9943,7 +10692,7 @@
}")
;; Call to function in current module. No TOC pointer reload needed.
-;; Operand2 is non-zero if we are using the V.4 calling sequence and
+;; Operand2 is nonzero if we are using the V.4 calling sequence and
;; either the function was not prototyped, or it was prototyped as a
;; variable argument function. It is > 0 if FP registers were passed
;; and < 0 if they were not.
@@ -10029,7 +10778,7 @@
;; Call to function which may be in another module. Restore the TOC
;; pointer (r2) after the call unless this is System V.
-;; Operand2 is non-zero if we are using the V.4 calling sequence and
+;; Operand2 is nonzero if we are using the V.4 calling sequence and
;; either the function was not prototyped, or it was prototyped as a
;; variable argument function. It is > 0 if FP registers were passed
;; and < 0 if they were not.
@@ -10048,7 +10797,7 @@
(set_attr "length" "8")])
(define_insn "*call_nonlocal_aix32"
- [(call (mem:SI (match_operand:SI 0 "call_operand" "s"))
+ [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s"))
(match_operand 1 "" "g"))
(use (match_operand:SI 2 "immediate_operand" "O"))
(clobber (match_scratch:SI 3 "=l"))]
@@ -10073,7 +10822,7 @@
(set_attr "length" "8")])
(define_insn "*call_nonlocal_aix64"
- [(call (mem:SI (match_operand:DI 0 "call_operand" "s"))
+ [(call (mem:SI (match_operand:DI 0 "symbol_ref_operand" "s"))
(match_operand 1 "" "g"))
(use (match_operand:SI 2 "immediate_operand" "O"))
(clobber (match_scratch:SI 3 "=l"))]
@@ -10100,7 +10849,7 @@
(define_insn "*call_value_nonlocal_aix32"
[(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "call_operand" "s"))
+ (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s"))
(match_operand 2 "" "g")))
(use (match_operand:SI 3 "immediate_operand" "O"))
(clobber (match_scratch:SI 4 "=l"))]
@@ -10127,7 +10876,7 @@
(define_insn "*call_value_nonlocal_aix64"
[(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:DI 1 "call_operand" "s"))
+ (call (mem:SI (match_operand:DI 1 "symbol_ref_operand" "s"))
(match_operand 2 "" "g")))
(use (match_operand:SI 3 "immediate_operand" "O"))
(clobber (match_scratch:SI 4 "=l"))]
@@ -10144,68 +10893,89 @@
;; operands[2] is the value FUNCTION_ARG returns for the VOID argument
;; which indicates how to set cr1
-(define_insn "*call_nonlocal_sysv"
- [(call (mem:SI (match_operand:SI 0 "call_operand" "cl,cl,s,s"))
- (match_operand 1 "" "g,g,g,g"))
- (use (match_operand:SI 2 "immediate_operand" "O,n,O,n"))
- (clobber (match_scratch:SI 3 "=l,l,l,l"))]
+(define_insn "*call_indirect_nonlocal_sysv"
+ [(call (mem:SI (match_operand:SI 0 "register_operand" "cl,cl"))
+ (match_operand 1 "" "g,g"))
+ (use (match_operand:SI 2 "immediate_operand" "O,n"))
+ (clobber (match_scratch:SI 3 "=l,l"))]
"DEFAULT_ABI == ABI_AIX_NODESC
|| DEFAULT_ABI == ABI_V4
|| DEFAULT_ABI == ABI_DARWIN"
- "*
{
if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
- output_asm_insn (\"crxor 6,6,6\", operands);
+ output_asm_insn ("crxor 6,6,6", operands);
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
- output_asm_insn (\"creqv 6,6,6\", operands);
+ output_asm_insn ("creqv 6,6,6", operands);
- switch (which_alternative)
- {
- default:
- abort ();
- case 0:
- case 1:
- return \"b%T0l\";
- case 2:
- case 3:
- return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z0@plt\" : \"bl %z0\";
- }
-}"
- [(set_attr "type" "jmpreg,jmpreg,branch,branch")
- (set_attr "length" "4,8,4,8")])
+ return "b%T0l";
+}
+ [(set_attr "type" "jmpreg,jmpreg")
+ (set_attr "length" "4,8")])
-(define_insn "*call_value_nonlocal_sysv"
+(define_insn "*call_nonlocal_sysv"
+ [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s,s"))
+ (match_operand 1 "" "g,g"))
+ (use (match_operand:SI 2 "immediate_operand" "O,n"))
+ (clobber (match_scratch:SI 3 "=l,l"))]
+ "(DEFAULT_ABI == ABI_AIX_NODESC
+ || DEFAULT_ABI == ABI_V4
+ || DEFAULT_ABI == ABI_DARWIN)
+ && (INTVAL (operands[2]) & CALL_LONG) == 0"
+{
+ if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
+ output_asm_insn ("crxor 6,6,6", operands);
+
+ else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
+ output_asm_insn ("creqv 6,6,6", operands);
+
+ return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z0@plt" : "bl %z0";
+}
+ [(set_attr "type" "branch,branch")
+ (set_attr "length" "4,8")])
+
+(define_insn "*call_value_indirect_nonlocal_sysv"
[(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "call_operand" "cl,cl,s,s"))
- (match_operand 2 "" "g,g,g,g")))
- (use (match_operand:SI 3 "immediate_operand" "O,n,O,n"))
- (clobber (match_scratch:SI 4 "=l,l,l,l"))]
+ (call (mem:SI (match_operand:SI 1 "register_operand" "cl,cl"))
+ (match_operand 2 "" "g,g")))
+ (use (match_operand:SI 3 "immediate_operand" "O,n"))
+ (clobber (match_scratch:SI 4 "=l,l"))]
"DEFAULT_ABI == ABI_AIX_NODESC
|| DEFAULT_ABI == ABI_V4
|| DEFAULT_ABI == ABI_DARWIN"
- "*
{
if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
- output_asm_insn (\"crxor 6,6,6\", operands);
+ output_asm_insn ("crxor 6,6,6", operands);
else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
- output_asm_insn (\"creqv 6,6,6\", operands);
+ output_asm_insn ("creqv 6,6,6", operands);
- switch (which_alternative)
- {
- default:
- abort ();
- case 0:
- case 1:
- return \"b%T1l\";
- case 2:
- case 3:
- return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z1@plt\" : \"bl %z1\";
- }
-}"
- [(set_attr "type" "jmpreg,jmpreg,branch,branch")
- (set_attr "length" "4,8,4,8")])
+ return "b%T1l";
+}
+ [(set_attr "type" "jmpreg,jmpreg")
+ (set_attr "length" "4,8")])
+
+(define_insn "*call_value_nonlocal_sysv"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s,s"))
+ (match_operand 2 "" "g,g")))
+ (use (match_operand:SI 3 "immediate_operand" "O,n"))
+ (clobber (match_scratch:SI 4 "=l,l"))]
+ "(DEFAULT_ABI == ABI_AIX_NODESC
+ || DEFAULT_ABI == ABI_V4
+ || DEFAULT_ABI == ABI_DARWIN)
+ && (INTVAL (operands[3]) & CALL_LONG) == 0"
+{
+ if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
+ output_asm_insn ("crxor 6,6,6", operands);
+
+ else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
+ output_asm_insn ("creqv 6,6,6", operands);
+
+ return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z1@plt" : "bl %z1";
+}
+ [(set_attr "type" "branch,branch")
+ (set_attr "length" "4,8")])
;; Call subroutine returning any type.
(define_expand "untyped_call"
@@ -10235,6 +11005,247 @@
DONE;
}")
+;; sibling call patterns
+(define_expand "sibcall"
+ [(parallel [(call (mem:SI (match_operand 0 "address_operand" ""))
+ (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (use (scratch:SI))
+ (return)])]
+ ""
+ "
+{
+#if TARGET_MACHO
+ if (flag_pic)
+ operands[0] = machopic_indirect_call_target (operands[0]);
+#endif
+
+ if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != CONST_INT)
+ abort ();
+
+ operands[0] = XEXP (operands[0], 0);
+
+}")
+
+;; this and similar patterns must be marked as using LR, otherwise
+;; dataflow will try to delete the store into it. This is true
+;; even when the actual reg to jump to is in CTR, when LR was
+;; saved and restored around the PIC-setting BCL.
+(define_insn "*sibcall_local32"
+ [(call (mem:SI (match_operand:SI 0 "current_file_function_operand" "s,s"))
+ (match_operand 1 "" "g,g"))
+ (use (match_operand:SI 2 "immediate_operand" "O,n"))
+ (use (match_scratch:SI 3 "=l,l"))
+ (return)]
+ "(INTVAL (operands[2]) & CALL_LONG) == 0"
+ "*
+{
+ if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
+ output_asm_insn (\"crxor 6,6,6\", operands);
+
+ else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
+ output_asm_insn (\"creqv 6,6,6\", operands);
+
+ return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@local\" : \"b %z0\";
+}"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4,8")])
+
+(define_insn "*sibcall_local64"
+ [(call (mem:SI (match_operand:DI 0 "current_file_function_operand" "s,s"))
+ (match_operand 1 "" "g,g"))
+ (use (match_operand:SI 2 "immediate_operand" "O,n"))
+ (use (match_scratch:SI 3 "=l,l"))
+ (return)]
+ "TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 0"
+ "*
+{
+ if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
+ output_asm_insn (\"crxor 6,6,6\", operands);
+
+ else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
+ output_asm_insn (\"creqv 6,6,6\", operands);
+
+ return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@local\" : \"b %z0\";
+}"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4,8")])
+
+(define_insn "*sibcall_value_local32"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:SI 1 "current_file_function_operand" "s,s"))
+ (match_operand 2 "" "g,g")))
+ (use (match_operand:SI 3 "immediate_operand" "O,n"))
+ (use (match_scratch:SI 4 "=l,l"))
+ (return)]
+ "(INTVAL (operands[3]) & CALL_LONG) == 0"
+ "*
+{
+ if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
+ output_asm_insn (\"crxor 6,6,6\", operands);
+
+ else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
+ output_asm_insn (\"creqv 6,6,6\", operands);
+
+ return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@local\" : \"b %z1\";
+}"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4,8")])
+
+
+(define_insn "*sibcall_value_local64"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s"))
+ (match_operand 2 "" "g,g")))
+ (use (match_operand:SI 3 "immediate_operand" "O,n"))
+ (use (match_scratch:SI 4 "=l,l"))
+ (return)]
+ "TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0"
+ "*
+{
+ if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
+ output_asm_insn (\"crxor 6,6,6\", operands);
+
+ else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
+ output_asm_insn (\"creqv 6,6,6\", operands);
+
+ return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@local\" : \"b %z1\";
+}"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4,8")])
+
+(define_insn "*sibcall_nonlocal_aix32"
+ [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s"))
+ (match_operand 1 "" "g"))
+ (use (match_operand:SI 2 "immediate_operand" "O"))
+ (use (match_scratch:SI 3 "=l"))
+ (return)]
+ "TARGET_32BIT
+ && DEFAULT_ABI == ABI_AIX
+ && (INTVAL (operands[2]) & CALL_LONG) == 0"
+ "b %z0"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_insn "*sibcall_nonlocal_aix64"
+ [(call (mem:SI (match_operand:DI 0 "symbol_ref_operand" "s"))
+ (match_operand 1 "" "g"))
+ (use (match_operand:SI 2 "immediate_operand" "O"))
+ (use (match_scratch:SI 3 "=l"))
+ (return)]
+ "TARGET_64BIT
+ && DEFAULT_ABI == ABI_AIX
+ && (INTVAL (operands[2]) & CALL_LONG) == 0"
+ "b %z0"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_insn "*sibcall_value_nonlocal_aix32"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s"))
+ (match_operand 2 "" "g")))
+ (use (match_operand:SI 3 "immediate_operand" "O"))
+ (use (match_scratch:SI 4 "=l"))
+ (return)]
+ "TARGET_32BIT
+ && DEFAULT_ABI == ABI_AIX
+ && (INTVAL (operands[3]) & CALL_LONG) == 0"
+ "b %z1"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_insn "*sibcall_value_nonlocal_aix64"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:DI 1 "symbol_ref_operand" "s"))
+ (match_operand 2 "" "g")))
+ (use (match_operand:SI 3 "immediate_operand" "O"))
+ (use (match_scratch:SI 4 "=l"))
+ (return)]
+ "TARGET_64BIT
+ && DEFAULT_ABI == ABI_AIX
+ && (INTVAL (operands[3]) & CALL_LONG) == 0"
+ "b %z1"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_insn "*sibcall_nonlocal_sysv"
+ [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s,s"))
+ (match_operand 1 "" ""))
+ (use (match_operand 2 "immediate_operand" "O,n"))
+ (use (match_scratch:SI 3 "=l,l"))
+ (return)]
+ "(DEFAULT_ABI == ABI_DARWIN
+ || DEFAULT_ABI == ABI_V4
+ || DEFAULT_ABI == ABI_AIX_NODESC)
+ && (INTVAL (operands[2]) & CALL_LONG) == 0"
+ "*
+{
+ if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
+ output_asm_insn (\"crxor 6,6,6\", operands);
+
+ else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
+ output_asm_insn (\"creqv 6,6,6\", operands);
+
+ return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@plt\" : \"b %z0\";
+}"
+ [(set_attr "type" "branch,branch")
+ (set_attr "length" "4,8")])
+
+(define_expand "sibcall_value"
+ [(parallel [(set (match_operand 0 "register_operand" "")
+ (call (mem:SI (match_operand 1 "address_operand" ""))
+ (match_operand 2 "" "")))
+ (use (match_operand 3 "" ""))
+ (use (scratch:SI))
+ (return)])]
+ ""
+ "
+{
+#if TARGET_MACHO
+ if (flag_pic)
+ operands[1] = machopic_indirect_call_target (operands[1]);
+#endif
+
+ if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != CONST_INT)
+ abort ();
+
+ operands[1] = XEXP (operands[1], 0);
+
+}")
+
+(define_insn "*sibcall_value_nonlocal_sysv"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s,s"))
+ (match_operand 2 "" "")))
+ (use (match_operand:SI 3 "immediate_operand" "O,n"))
+ (use (match_scratch:SI 4 "=l,l"))
+ (return)]
+ "(DEFAULT_ABI == ABI_DARWIN
+ || DEFAULT_ABI == ABI_V4
+ || DEFAULT_ABI == ABI_AIX_NODESC)
+ && (INTVAL (operands[3]) & CALL_LONG) == 0"
+ "*
+{
+ if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
+ output_asm_insn (\"crxor 6,6,6\", operands);
+
+ else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
+ output_asm_insn (\"creqv 6,6,6\", operands);
+
+ return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@plt\" : \"b %z1\";
+}"
+ [(set_attr "type" "branch,branch")
+ (set_attr "length" "4,8")])
+
+(define_expand "sibcall_epilogue"
+ [(use (const_int 0))]
+ "TARGET_SCHED_PROLOG"
+ "
+{
+ rs6000_emit_epilogue (TRUE);
+ 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.
@@ -10302,7 +11313,7 @@
(define_expand "cmpdf"
[(set (cc0) (compare (match_operand:DF 0 "gpc_reg_operand" "")
(match_operand:DF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"
{
rs6000_compare_op0 = operands[0];
@@ -10314,7 +11325,8 @@
(define_expand "cmptf"
[(set (cc0) (compare (match_operand:TF 0 "gpc_reg_operand" "")
(match_operand:TF 1 "gpc_reg_operand" "")))]
- "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
+ "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT
+ && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"
{
rs6000_compare_op0 = operands[0];
@@ -10549,7 +11561,7 @@
with C to get the sign-extended value. */
HOST_WIDE_INT c = INTVAL (operands[2]);
- HOST_WIDE_INT sextc = (c & 0x7fff) - (c & 0x8000);
+ HOST_WIDE_INT sextc = ((c & 0xffff) ^ 0x8000) - 0x8000;
HOST_WIDE_INT xorv = c ^ sextc;
operands[4] = GEN_INT (xorv);
@@ -10621,7 +11633,7 @@
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "f")
(match_operand:SF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"fcmpu %0,%1,%2"
[(set_attr "type" "fpcompare")])
@@ -10629,7 +11641,7 @@
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "f")
(match_operand:DF 2 "gpc_reg_operand" "f")))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
"fcmpu %0,%1,%2"
[(set_attr "type" "fpcompare")])
@@ -10638,7 +11650,8 @@
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "f")
(match_operand:TF 2 "gpc_reg_operand" "f")))]
- "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
+ "DEFAULT_ABI == ABI_AIX && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_LONG_DOUBLE_128"
"fcmpu %0,%1,%2\;bne %0,$+4\;fcmpu %0,%L1,%L2"
[(set_attr "type" "fpcompare")
(set_attr "length" "12")])
@@ -10657,6 +11670,15 @@
(const_int 0)]))]
""
"%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
+ [(set_attr "type" "cr_logical")
+ (set_attr "length" "12")])
+
+;; Same as above, but get the OV/ORDERED bit.
+(define_insn "move_from_CR_ov_bit"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unspec:SI [(match_operand 1 "cc_reg_operand" "y")] 724))]
+ "TARGET_ISEL"
+ "%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%t1,1"
[(set_attr "length" "12")])
(define_insn ""
@@ -10666,7 +11688,8 @@
(const_int 0)]))]
"TARGET_POWERPC64"
"%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
- [(set_attr "length" "12")])
+ [(set_attr "type" "cr_logical")
+ (set_attr "length" "12")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -10722,7 +11745,8 @@
return \"%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%4,%5,%5\";
}"
- [(set_attr "length" "12")])
+ [(set_attr "type" "cr_logical")
+ (set_attr "length" "12")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -10735,7 +11759,7 @@
(set (match_operand:SI 4 "gpc_reg_operand" "=r,r")
(ashift:SI (match_op_dup 1 [(match_dup 2) (const_int 0)])
(match_dup 3)))]
- "! TARGET_POWERPC64"
+ ""
"*
{
int is_bit = ccr_bit (operands[1], 1);
@@ -10770,7 +11794,7 @@
(set (match_operand:SI 4 "gpc_reg_operand" "")
(ashift:SI (match_op_dup 1 [(match_dup 2) (const_int 0)])
(match_dup 3)))]
- "! TARGET_POWERPC64 && reload_completed"
+ "reload_completed"
[(set (match_dup 4)
(ashift:SI (match_op_dup 1 [(match_dup 2) (const_int 0)])
(match_dup 3)))
@@ -10791,9 +11815,10 @@
(match_operator:SI 4 "scc_comparison_operator"
[(match_operand 5 "cc_reg_operand" "y")
(const_int 0)]))]
- "REGNO (operands[2]) != REGNO (operands[5])"
- "%D1%D4mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
- [(set_attr "length" "20")])
+ "REGNO (operands[2]) != REGNO (operands[5])"
+ "%D1%D4mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
+ [(set_attr "type" "cr_logical")
+ (set_attr "length" "20")])
(define_peephole
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
@@ -10804,9 +11829,10 @@
(match_operator:DI 4 "scc_comparison_operator"
[(match_operand 5 "cc_reg_operand" "y")
(const_int 0)]))]
- "TARGET_POWERPC64 && REGNO (operands[2]) != REGNO (operands[5])"
- "%D1%D4mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
- [(set_attr "length" "20")])
+ "TARGET_POWERPC64 && REGNO (operands[2]) != REGNO (operands[5])"
+ "%D1%D4mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
+ [(set_attr "type" "cr_logical")
+ (set_attr "length" "20")])
;; There are some scc insns that can be done directly, without a compare.
;; These are faster because they don't involve the communications between
@@ -11069,7 +12095,7 @@
(lshiftrt:SI (neg:SI (abs:SI (match_operand:SI 1 "gpc_reg_operand" "r")))
(const_int 31)))
(clobber (match_scratch:SI 2 "=&r"))]
- "! TARGET_POWER && ! TARGET_POWERPC64"
+ "! TARGET_POWER && ! TARGET_POWERPC64 && !TARGET_ISEL"
"{ai|addic} %2,%1,-1\;{sfe|subfe} %0,%2,%1"
[(set_attr "length" "8")])
@@ -11134,9 +12160,9 @@
(clobber (match_scratch:SI 4 ""))]
"! TARGET_POWERPC64 && reload_completed"
[(parallel [(set (match_dup 3)
- (plus:SI (lshiftrt:SI (neg:SI (abs:SI (match_dup 1)))
- (const_int 31))
- (match_dup 2)))
+ (plus:SI (lshiftrt:SI (neg:SI (abs:SI (match_dup 1)))
+ (const_int 31))
+ (match_dup 2)))
(clobber (match_dup 4))])
(set (match_dup 0)
(compare:CC (match_dup 3)
@@ -13028,7 +14054,7 @@
"cc_reg_operand" "y")
(const_int 0)])
(const_int 0)))]
- ""
+ "!TARGET_SPE"
"{crnor %E0,%j1,%j1|crnot %E0,%j1}"
[(set_attr "type" "cr_logical")])
@@ -13282,7 +14308,7 @@
return \"bdz $+8\;b %l0\";
}"
[(set_attr "type" "branch")
- (set_attr "length" "*,12,16")])
+ (set_attr "length" "4,12,16")])
(define_insn "*ctrsi_internal2"
[(set (pc)
@@ -13306,7 +14332,7 @@
return \"{bdn|bdnz} $+8\;b %l0\";
}"
[(set_attr "type" "branch")
- (set_attr "length" "*,12,16")])
+ (set_attr "length" "4,12,16")])
(define_insn "*ctrdi_internal1"
[(set (pc)
@@ -13330,7 +14356,7 @@
return \"bdz $+8\;b %l0\";
}"
[(set_attr "type" "branch")
- (set_attr "length" "*,12,16")])
+ (set_attr "length" "4,12,16")])
(define_insn "*ctrdi_internal2"
[(set (pc)
@@ -13354,7 +14380,7 @@
return \"{bdn|bdnz} $+8\;b %l0\";
}"
[(set_attr "type" "branch")
- (set_attr "length" "*,12,16")])
+ (set_attr "length" "4,12,16")])
;; Similar, but we can use GE since we have a REG_NONNEG.
@@ -13380,7 +14406,7 @@
return \"bdz $+8\;b %l0\";
}"
[(set_attr "type" "branch")
- (set_attr "length" "*,12,16")])
+ (set_attr "length" "4,12,16")])
(define_insn "*ctrsi_internal4"
[(set (pc)
@@ -13404,7 +14430,7 @@
return \"{bdn|bdnz} $+8\;b %l0\";
}"
[(set_attr "type" "branch")
- (set_attr "length" "*,12,16")])
+ (set_attr "length" "4,12,16")])
(define_insn "*ctrdi_internal3"
[(set (pc)
@@ -13428,7 +14454,7 @@
return \"bdz $+8\;b %l0\";
}"
[(set_attr "type" "branch")
- (set_attr "length" "*,12,16")])
+ (set_attr "length" "4,12,16")])
(define_insn "*ctrdi_internal4"
[(set (pc)
@@ -13452,7 +14478,7 @@
return \"{bdn|bdnz} $+8\;b %l0\";
}"
[(set_attr "type" "branch")
- (set_attr "length" "*,12,16")])
+ (set_attr "length" "4,12,16")])
;; Similar but use EQ
@@ -13478,7 +14504,7 @@
return \"{bdn|bdnz} $+8\;b %l0\";
}"
[(set_attr "type" "branch")
- (set_attr "length" "*,12,16")])
+ (set_attr "length" "4,12,16")])
(define_insn "*ctrsi_internal6"
[(set (pc)
@@ -13502,7 +14528,7 @@
return \"bdz $+8\;b %l0\";
}"
[(set_attr "type" "branch")
- (set_attr "length" "*,12,16")])
+ (set_attr "length" "4,12,16")])
(define_insn "*ctrdi_internal5"
[(set (pc)
@@ -13526,7 +14552,7 @@
return \"{bdn|bdnz} $+8\;b %l0\";
}"
[(set_attr "type" "branch")
- (set_attr "length" "*,12,16")])
+ (set_attr "length" "4,12,16")])
(define_insn "*ctrdi_internal6"
[(set (pc)
@@ -13550,7 +14576,7 @@
return \"bdz $+8\;b %l0\";
}"
[(set_attr "type" "branch")
- (set_attr "length" "*,12,16")])
+ (set_attr "length" "4,12,16")])
;; Now the splitters if we could not allocate the CTR register
@@ -13712,7 +14738,8 @@
(unspec:SI [(reg:CC 68) (reg:CC 69) (reg:CC 70) (reg:CC 71)
(reg:CC 72) (reg:CC 73) (reg:CC 74) (reg:CC 75)] 19))]
""
- "mfcr %0")
+ "mfcr %0"
+ [(set_attr "type" "cr_logical")])
(define_insn "*stmw"
[(match_parallel 0 "stmw_operation"
@@ -13763,17 +14790,17 @@
; faster; for instance, on the 601 and 750.
(define_expand "movsi_to_cr_one"
- [(set (match_operand:CC 0 "cc_reg_operand" "=y")
- (unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
- (match_dup 2)] 20))]
- ""
- "operands[2] = GEN_INT (1 << (75 - REGNO (operands[0])));")
+ [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+ (unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
+ (match_dup 2)] 20))]
+ ""
+ "operands[2] = GEN_INT (1 << (75 - REGNO (operands[0])));")
(define_insn "*movsi_to_cr"
- [(match_parallel 0 "mtcrf_operation"
- [(set (match_operand:CC 1 "cc_reg_operand" "=y")
- (unspec:CC [(match_operand:SI 2 "gpc_reg_operand" "r")
- (match_operand 3 "immediate_operand" "n")]
+ [(match_parallel 0 "mtcrf_operation"
+ [(set (match_operand:CC 1 "cc_reg_operand" "=y")
+ (unspec:CC [(match_operand:SI 2 "gpc_reg_operand" "r")
+ (match_operand 3 "immediate_operand" "n")]
20))])]
""
"*
@@ -13784,28 +14811,30 @@
mask |= INTVAL (XVECEXP (SET_SRC (XVECEXP (operands[0], 0, i)), 0, 1));
operands[4] = GEN_INT (mask);
return \"mtcrf %4,%2\";
-}")
+}"
+ [(set_attr "type" "cr_logical")])
(define_insn ""
- [(set (match_operand:CC 0 "cc_reg_operand" "=y")
- (unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand 2 "immediate_operand" "n")] 20))]
- "GET_CODE (operands[0]) == REG
- && CR_REGNO_P (REGNO (operands[0]))
- && GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) == 1 << (75 - REGNO (operands[0]))"
- "mtcrf %R0,%1")
+ [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+ (unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
+ (match_operand 2 "immediate_operand" "n")] 20))]
+ "GET_CODE (operands[0]) == REG
+ && CR_REGNO_P (REGNO (operands[0]))
+ && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == 1 << (75 - REGNO (operands[0]))"
+ "mtcrf %R0,%1"
+ [(set_attr "type" "cr_logical")])
; The load-multiple instructions have similar properties.
; Note that "load_multiple" is a name known to the machine-independent
; code that actually corresponds to the powerpc load-string.
(define_insn "*lmw"
- [(match_parallel 0 "lmw_operation"
- [(set (match_operand:SI 1 "gpc_reg_operand" "=r")
- (match_operand:SI 2 "memory_operand" "m"))])]
- "TARGET_MULTIPLE"
- "{lm|lmw} %1,%2")
+ [(match_parallel 0 "lmw_operation"
+ [(set (match_operand:SI 1 "gpc_reg_operand" "=r")
+ (match_operand:SI 2 "memory_operand" "m"))])]
+ "TARGET_MULTIPLE"
+ "{lm|lmw} %1,%2")
(define_insn "*return_internal_si"
[(return)
@@ -13846,19 +14875,17 @@
; This is used in compiling the unwind routines.
(define_expand "eh_return"
- [(use (match_operand 0 "general_operand" ""))
- (use (match_operand 1 "general_operand" ""))]
+ [(use (match_operand 0 "general_operand" ""))]
""
"
{
#if TARGET_AIX
- rs6000_emit_eh_toc_restore (operands[0]);
+ rs6000_emit_eh_toc_restore (EH_RETURN_STACKADJ_RTX);
#endif
if (TARGET_32BIT)
- emit_insn (gen_eh_set_lr_si (operands[1]));
+ emit_insn (gen_eh_set_lr_si (operands[0]));
else
- emit_insn (gen_eh_set_lr_di (operands[1]));
- emit_move_insn (EH_RETURN_STACKADJ_RTX, operands[0]);
+ emit_insn (gen_eh_set_lr_di (operands[0]));
DONE;
}")
@@ -13921,1850 +14948,6 @@
return INTVAL (operands[1]) ? \"dcbtst %a0\" : \"dcbt %a0\";
}"
[(set_attr "type" "load")])
-
-;; AltiVec patterns
-
-;; Generic LVX load instruction.
-(define_insn "altivec_lvx_4si"
- [(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
- (match_operand:V4SI 1 "memory_operand" "m"))]
- "TARGET_ALTIVEC"
- "lvx %0,%y1"
- [(set_attr "type" "vecload")])
-
-(define_insn "altivec_lvx_8hi"
- [(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
- (match_operand:V8HI 1 "memory_operand" "m"))]
- "TARGET_ALTIVEC"
- "lvx %0,%y1"
- [(set_attr "type" "vecload")])
-
-(define_insn "altivec_lvx_16qi"
- [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
- (match_operand:V16QI 1 "memory_operand" "m"))]
- "TARGET_ALTIVEC"
- "lvx %0,%y1"
- [(set_attr "type" "vecload")])
-
-(define_insn "altivec_lvx_4sf"
- [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
- (match_operand:V4SF 1 "memory_operand" "m"))]
- "TARGET_ALTIVEC"
- "lvx %0,%y1"
- [(set_attr "type" "vecload")])
-
-;; Generic STVX store instruction.
-(define_insn "altivec_stvx_4si"
- [(set (match_operand:V4SI 0 "memory_operand" "=m")
- (match_operand:V4SI 1 "altivec_register_operand" "v"))]
- "TARGET_ALTIVEC"
- "stvx %1,%y0"
- [(set_attr "type" "vecstore")])
-
-(define_insn "altivec_stvx_8hi"
- [(set (match_operand:V8HI 0 "memory_operand" "=m")
- (match_operand:V8HI 1 "altivec_register_operand" "v"))]
- "TARGET_ALTIVEC"
- "stvx %1,%y0"
- [(set_attr "type" "vecstore")])
-
-(define_insn "altivec_stvx_16qi"
- [(set (match_operand:V16QI 0 "memory_operand" "=m")
- (match_operand:V16QI 1 "altivec_register_operand" "v"))]
- "TARGET_ALTIVEC"
- "stvx %1,%y0"
- [(set_attr "type" "vecstore")])
-
-(define_insn "altivec_stvx_4sf"
- [(set (match_operand:V4SF 0 "memory_operand" "=m")
- (match_operand:V4SF 1 "altivec_register_operand" "v"))]
- "TARGET_ALTIVEC"
- "stvx %1,%y0"
- [(set_attr "type" "vecstore")])
-
-;; Vector move instructions.
-(define_expand "movv4si"
- [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
- (match_operand:V4SI 1 "any_operand" ""))]
- "TARGET_ALTIVEC"
- "{ rs6000_emit_move (operands[0], operands[1], V4SImode); DONE; }")
-
-(define_insn "*movv4si_internal"
- [(set (match_operand:V4SI 0 "nonimmediate_operand" "=m,v,v,o,r,r")
- (match_operand:V4SI 1 "input_operand" "v,m,v,r,o,r"))]
- "TARGET_ALTIVEC"
- "@
- stvx %1,%y0
- lvx %0,%y1
- vor %0,%1,%1
- stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
- lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
- mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
- [(set_attr "type" "altivec")
- (set_attr "length" "*,*,*,16,16,16")])
-
-(define_expand "movv8hi"
- [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
- (match_operand:V8HI 1 "any_operand" ""))]
- "TARGET_ALTIVEC"
- "{ rs6000_emit_move (operands[0], operands[1], V8HImode); DONE; }")
-
-(define_insn "*movv8hi_internal1"
- [(set (match_operand:V8HI 0 "nonimmediate_operand" "=m,v,v,o,r,r")
- (match_operand:V8HI 1 "input_operand" "v,m,v,r,o,r"))]
- "TARGET_ALTIVEC"
- "@
- stvx %1,%y0
- lvx %0,%y1
- vor %0,%1,%1
- stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
- lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
- mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
- [(set_attr "type" "altivec")
- (set_attr "length" "*,*,*,16,16,16")])
-
-(define_expand "movv16qi"
- [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
- (match_operand:V16QI 1 "any_operand" ""))]
- "TARGET_ALTIVEC"
- "{ rs6000_emit_move (operands[0], operands[1], V16QImode); DONE; }")
-
-(define_insn "*movv16qi_internal1"
- [(set (match_operand:V16QI 0 "nonimmediate_operand" "=m,v,v,o,r,r")
- (match_operand:V16QI 1 "input_operand" "v,m,v,r,o,r"))]
- "TARGET_ALTIVEC"
- "@
- stvx %1,%y0
- lvx %0,%y1
- vor %0,%1,%1
- stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
- lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
- mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
- [(set_attr "type" "altivec")
- (set_attr "length" "*,*,*,16,16,16")])
-
-(define_expand "movv4sf"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
- (match_operand:V4SF 1 "any_operand" ""))]
- "TARGET_ALTIVEC"
- "{ rs6000_emit_move (operands[0], operands[1], V4SFmode); DONE; }")
-
-(define_insn "*movv4sf_internal1"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=m,v,v,o,r,r")
- (match_operand:V4SF 1 "input_operand" "v,m,v,r,o,r"))]
- "TARGET_ALTIVEC"
- "@
- stvx %1,%y0
- lvx %0,%y1
- vor %0,%1,%1
- stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0
- lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1
- mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1"
- [(set_attr "type" "altivec")
- (set_attr "length" "*,*,*,16,16,16")])
-
-(define_insn "get_vrsave_internal"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(reg:SI 109)] 214))]
- "TARGET_ALTIVEC"
- "*
-{
- if (TARGET_MACHO)
- return \"mtspr 256,%0\";
- else
- return \"mtvrsave %0\";
-}"
- [(set_attr "type" "altivec")])
-
-(define_insn "*set_vrsave_internal"
- [(match_parallel 0 "vrsave_operation"
- [(set (reg:SI 109)
- (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")
- (reg:SI 109)] 30))])]
- "TARGET_ALTIVEC"
- "*
-{
- if (TARGET_MACHO)
- return \"mfspr %1,256\";
- else
- return \"mtvrsave %1\";
-}"
- [(set_attr "type" "altivec")])
-
-;; Vector clears
-(define_insn "*movv4si_const0"
- [(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
- (match_operand:V4SI 1 "zero_constant" ""))]
- "TARGET_ALTIVEC"
- "vxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "*movv4sf_const0"
- [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
- (match_operand:V4SF 1 "zero_constant" ""))]
-
- "TARGET_ALTIVEC"
- "vxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "*movv8hi_const0"
- [(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
- (match_operand:V8HI 1 "zero_constant" ""))]
- "TARGET_ALTIVEC"
- "vxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "*movv16qi_const0"
- [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
- (match_operand:V16QI 1 "zero_constant" ""))]
- "TARGET_ALTIVEC"
- "vxor %0,%0,%0"
- [(set_attr "type" "vecsimple")])
-
-;; Simple binary operations.
-
-(define_insn "addv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (plus:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vaddubm %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "addv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (plus:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vadduhm %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "addv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (plus:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vadduwm %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "addv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (plus:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vaddfp %0,%1,%2"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vaddcuw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 35))]
- "TARGET_ALTIVEC"
- "vaddcuw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vaddubs"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 36))]
- "TARGET_ALTIVEC"
- "vaddubs %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vaddsbs"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 37))]
- "TARGET_ALTIVEC"
- "vaddsbs %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vadduhs"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 38))]
- "TARGET_ALTIVEC"
- "vadduhs %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vaddshs"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 39))]
- "TARGET_ALTIVEC"
- "vaddshs %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vadduws"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 40))]
- "TARGET_ALTIVEC"
- "vadduws %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vaddsws"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 41))]
- "TARGET_ALTIVEC"
- "vaddsws %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "andv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (and:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vand %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vandc"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (and:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (not:V4SI (match_operand:V4SI 2 "register_operand" "v"))))]
- "TARGET_ALTIVEC"
- "vandc %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vavgub"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 44))]
- "TARGET_ALTIVEC"
- "vavgub %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vavgsb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 45))]
- "TARGET_ALTIVEC"
- "vavgsb %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vavguh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 46))]
- "TARGET_ALTIVEC"
- "vavguh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vavgsh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 47))]
- "TARGET_ALTIVEC"
- "vavgsh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vavguw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 48))]
- "TARGET_ALTIVEC"
- "vavguw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vavgsw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 49))]
- "TARGET_ALTIVEC"
- "vavgsw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vcmpbfp"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")] 50))]
- "TARGET_ALTIVEC"
- "vcmpbfp %0,%1,%2"
- [(set_attr "type" "veccmp")])
-
-(define_insn "altivec_vcmpequb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 51))]
- "TARGET_ALTIVEC"
- "vcmpequb %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vcmpequh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 52))]
- "TARGET_ALTIVEC"
- "vcmpequh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vcmpequw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 53))]
- "TARGET_ALTIVEC"
- "vcmpequw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vcmpeqfp"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")] 54))]
- "TARGET_ALTIVEC"
- "vcmpeqfp %0,%1,%2"
- [(set_attr "type" "veccmp")])
-
-(define_insn "altivec_vcmpgefp"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")] 55))]
- "TARGET_ALTIVEC"
- "vcmpgefp %0,%1,%2"
- [(set_attr "type" "veccmp")])
-
-(define_insn "altivec_vcmpgtub"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 56))]
- "TARGET_ALTIVEC"
- "vcmpgtub %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vcmpgtsb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 57))]
- "TARGET_ALTIVEC"
- "vcmpgtsb %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vcmpgtuh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 58))]
- "TARGET_ALTIVEC"
- "vcmpgtuh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vcmpgtsh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 59))]
- "TARGET_ALTIVEC"
- "vcmpgtsh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vcmpgtuw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 60))]
- "TARGET_ALTIVEC"
- "vcmpgtuw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vcmpgtsw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 61))]
- "TARGET_ALTIVEC"
- "vcmpgtsw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vcmpgtfp"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")] 62))]
- "TARGET_ALTIVEC"
- "vcmpgtfp %0,%1,%2"
- [(set_attr "type" "veccmp")])
-
-;; Fused multiply add
-(define_insn "altivec_vmaddfp"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (plus:V4SF (mult:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v"))
- (match_operand:V4SF 3 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vmaddfp %0,%1,%2,%3"
- [(set_attr "type" "vecfloat")])
-
-;; The unspec here is a vec splat of 0. We do multiply as a fused
-;; multiply-add with an add of a 0 vector.
-
-(define_expand "mulv4sf3"
- [(set (match_dup 3) (unspec:V4SF [(const_int 0)] 142))
- (set (match_operand:V4SF 0 "register_operand" "=v")
- (plus:V4SF (mult:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v"))
- (match_dup 3)))]
- "TARGET_ALTIVEC && TARGET_FUSED_MADD"
- "
-{ operands[3] = gen_reg_rtx (V4SFmode); }")
-
-;; Fused multiply subtract
-(define_insn "altivec_vnmsubfp"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (minus:V4SF (mult:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v"))
- (match_operand:V4SF 3 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vnmsubfp %0,%1,%2,%3"
- [(set_attr "type" "vecfloat")])
-
-
-(define_insn "altivec_vmsumubm"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 65))]
- "TARGET_ALTIVEC"
- "vmsumubm %0, %1, %2, %3"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vmsummbm"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 66))]
- "TARGET_ALTIVEC"
- "vmsumubm %0, %1, %2, %3"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vmsumuhm"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 67))]
- "TARGET_ALTIVEC"
- "vmsumuhm %0, %1, %2, %3"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vmsumshm"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 68))]
- "TARGET_ALTIVEC"
- "vmsumshm %0, %1, %2, %3"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vmsumuhs"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 69))]
- "TARGET_ALTIVEC"
- "vmsumuhs %0, %1, %2, %3"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vmsumshs"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 70))]
- "TARGET_ALTIVEC"
- "vmsumshs %0, %1, %2, %3"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "umaxv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (umax:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vmaxub %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "smaxv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (smax:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vmaxsb %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "umaxv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (umax:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vmaxuh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "smaxv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (smax:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vmaxsh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "umaxv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (umax:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vmaxuw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "smaxv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (smax:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vmaxsw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "smaxv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (smax:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vmaxfp %0,%1,%2"
- [(set_attr "type" "veccmp")])
-
-(define_insn "altivec_vmhaddshs"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V8HI 3 "register_operand" "v")] 71))]
- "TARGET_ALTIVEC"
- "vmhaddshs %0, %1, %2, %3"
- [(set_attr "type" "veccomplex")])
-(define_insn "altivec_vmhraddshs"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V8HI 3 "register_operand" "v")] 72))]
- "TARGET_ALTIVEC"
- "vmhraddshs %0, %1, %2, %3"
- [(set_attr "type" "veccomplex")])
-(define_insn "altivec_vmladduhm"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V8HI 3 "register_operand" "v")] 73))]
- "TARGET_ALTIVEC"
- "vmladduhm %0, %1, %2, %3"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vmrghb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (vec_merge:V16QI (vec_select:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (parallel [(const_int 8)
- (const_int 9)
- (const_int 10)
- (const_int 11)
- (const_int 12)
- (const_int 13)
- (const_int 14)
- (const_int 15)
- (const_int 0)
- (const_int 1)
- (const_int 2)
- (const_int 3)
- (const_int 4)
- (const_int 5)
- (const_int 6)
- (const_int 7)]))
- (match_operand:V16QI 2 "register_operand" "v")
- (const_int 255)))]
- "TARGET_ALTIVEC"
- "vmrghb %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vmrghh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (vec_merge:V8HI (vec_select:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (parallel [(const_int 4)
- (const_int 5)
- (const_int 6)
- (const_int 7)
- (const_int 0)
- (const_int 1)
- (const_int 2)
- (const_int 3)]))
- (match_operand:V8HI 2 "register_operand" "v")
- (const_int 15)))]
- "TARGET_ALTIVEC"
- "vmrghh %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vmrghw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (vec_merge:V4SI (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (parallel [(const_int 2)
- (const_int 3)
- (const_int 0)
- (const_int 1)]))
- (match_operand:V4SI 2 "register_operand" "v")
- (const_int 12)))]
- "TARGET_ALTIVEC"
- "vmrghw %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vmrglb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (vec_merge:V16QI (vec_select:V16QI (match_operand:V16QI 2 "register_operand" "v")
- (parallel [(const_int 8)
- (const_int 9)
- (const_int 10)
- (const_int 11)
- (const_int 12)
- (const_int 13)
- (const_int 14)
- (const_int 15)
- (const_int 0)
- (const_int 1)
- (const_int 2)
- (const_int 3)
- (const_int 4)
- (const_int 5)
- (const_int 6)
- (const_int 7)]))
- (match_operand:V16QI 1 "register_operand" "v")
- (const_int 255)))]
- "TARGET_ALTIVEC"
- "vmrglb %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vmrglh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (vec_merge:V8HI (vec_select:V8HI (match_operand:V8HI 2 "register_operand" "v")
- (parallel [(const_int 4)
- (const_int 5)
- (const_int 6)
- (const_int 7)
- (const_int 0)
- (const_int 1)
- (const_int 2)
- (const_int 3)]))
- (match_operand:V8HI 1 "register_operand" "v")
- (const_int 15)))]
- "TARGET_ALTIVEC"
- "vmrglh %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vmrglw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (vec_merge:V4SI (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
- (parallel [(const_int 2)
- (const_int 3)
- (const_int 0)
- (const_int 1)]))
- (match_operand:V4SI 1 "register_operand" "v")
- (const_int 12)))]
- "TARGET_ALTIVEC"
- "vmrglw %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "uminv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (umin:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vminub %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "sminv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (smin:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vminsb %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "uminv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (umin:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vminuh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "sminv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (smin:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vminsh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "uminv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (umin:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vminuw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "sminv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (smin:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vminsw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "sminv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (smin:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vminfp %0,%1,%2"
- [(set_attr "type" "veccmp")])
-
-(define_insn "altivec_vmuleub"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 83))]
- "TARGET_ALTIVEC"
- "vmuleub %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vmulesb"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 84))]
- "TARGET_ALTIVEC"
- "vmulesb %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vmuleuh"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 85))]
- "TARGET_ALTIVEC"
- "vmuleuh %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vmulesh"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 86))]
- "TARGET_ALTIVEC"
- "vmulesh %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vmuloub"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 87))]
- "TARGET_ALTIVEC"
- "vmuloub %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vmulosb"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 88))]
- "TARGET_ALTIVEC"
- "vmulosb %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vmulouh"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 89))]
- "TARGET_ALTIVEC"
- "vmulouh %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vmulosh"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 90))]
- "TARGET_ALTIVEC"
- "vmulosh %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vnor"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (not:V4SI (ior:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v"))))]
- "TARGET_ALTIVEC"
- "vnor %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "iorv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (ior:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vor %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vpkuhum"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 93))]
- "TARGET_ALTIVEC"
- "vpkuhum %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vpkuwum"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 94))]
- "TARGET_ALTIVEC"
- "vpkuwum %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vpkpx"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 95))]
- "TARGET_ALTIVEC"
- "vpkpx %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vpkuhss"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 96))]
- "TARGET_ALTIVEC"
- "vpkuhss %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vpkshss"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 97))]
- "TARGET_ALTIVEC"
- "vpkshss %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vpkuwss"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 98))]
- "TARGET_ALTIVEC"
- "vpkuwss %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vpkswss"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 99))]
- "TARGET_ALTIVEC"
- "vpkswss %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vpkuhus"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 100))]
- "TARGET_ALTIVEC"
- "vpkuhus %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vpkshus"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 101))]
- "TARGET_ALTIVEC"
- "vpkshus %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vpkuwus"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 102))]
- "TARGET_ALTIVEC"
- "vpkuwus %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vpkswus"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 103))]
- "TARGET_ALTIVEC"
- "vpkswus %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vrlb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 104))]
- "TARGET_ALTIVEC"
- "vrlb %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vrlh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 105))]
- "TARGET_ALTIVEC"
- "vrlh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vrlw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 106))]
- "TARGET_ALTIVEC"
- "vrlw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vslb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 107))]
- "TARGET_ALTIVEC"
- "vslb %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vslh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 108))]
- "TARGET_ALTIVEC"
- "vslh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vslw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 109))]
- "TARGET_ALTIVEC"
- "vslw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsl"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 110))]
- "TARGET_ALTIVEC"
- "vsl %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vslo"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 111))]
- "TARGET_ALTIVEC"
- "vslo %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsrb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 112))]
- "TARGET_ALTIVEC"
- "vsrb %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsrh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 113))]
- "TARGET_ALTIVEC"
- "vsrh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsrw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 114))]
- "TARGET_ALTIVEC"
- "vsrw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsrab"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 115))]
- "TARGET_ALTIVEC"
- "vsrab %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsrah"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 116))]
- "TARGET_ALTIVEC"
- "vsrah %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsraw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 117))]
- "TARGET_ALTIVEC"
- "vsraw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsr"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 118))]
- "TARGET_ALTIVEC"
- "vsr %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsro"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 119))]
- "TARGET_ALTIVEC"
- "vsro %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "subv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (minus:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vsububm %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "subv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (minus:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vsubuhm %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "subv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (minus:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vsubuwm %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "subv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (minus:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vsubfp %0,%1,%2"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vsubcuw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 124))]
- "TARGET_ALTIVEC"
- "vsubcuw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsububs"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 125))]
- "TARGET_ALTIVEC"
- "vsububs %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsubsbs"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 126))]
- "TARGET_ALTIVEC"
- "vsubsbs %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsubuhs"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 127))]
- "TARGET_ALTIVEC"
- "vsubuhs %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsubshs"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 128))]
- "TARGET_ALTIVEC"
- "vsubshs %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsubuws"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 129))]
- "TARGET_ALTIVEC"
- "vsubuws %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsubsws"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 130))]
- "TARGET_ALTIVEC"
- "vsubsws %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsum4ubs"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 131))]
- "TARGET_ALTIVEC"
- "vsum4ubs %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vsum4sbs"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 132))]
- "TARGET_ALTIVEC"
- "vsum4sbs %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vsum4shs"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 133))]
- "TARGET_ALTIVEC"
- "vsum4shs %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vsum2sws"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 134))]
- "TARGET_ALTIVEC"
- "vsum2sws %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vsumsws"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 135))]
- "TARGET_ALTIVEC"
- "vsumsws %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "xorv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (xor:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vxor %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vspltb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:QI 2 "immediate_operand" "i")] 136))]
- "TARGET_ALTIVEC"
- "vspltb %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsplth"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:QI 2 "immediate_operand" "i")] 137))]
- "TARGET_ALTIVEC"
- "vsplth %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vspltw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:QI 2 "immediate_operand" "i")] 138))]
- "TARGET_ALTIVEC"
- "vspltw %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vspltisb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:QI 1 "immediate_operand" "i")] 139))]
- "TARGET_ALTIVEC"
- "vspltisb %0, %1"
- [(set_attr "type" "vecsimple")])
-
-
-(define_insn "altivec_vspltish"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:QI 1 "immediate_operand" "i")] 140))]
- "TARGET_ALTIVEC"
- "vspltish %0, %1"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vspltisw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:QI 1 "immediate_operand" "i")] 141))]
- "TARGET_ALTIVEC"
- "vspltisw %0, %1"
- [(set_attr "type" "vecsimple")])
-
-(define_insn ""
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:QI 1 "immediate_operand" "i")] 142))]
- "TARGET_ALTIVEC"
- "vspltisw %0, %1"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "ftruncv4sf2"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (fix:V4SF (match_operand:V4SF 1 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vrfiz %0, %1"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vperm_4si"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")
- (match_operand:V16QI 3 "register_operand" "v")] 144))]
- "TARGET_ALTIVEC"
- "vperm %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vperm_4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")
- (match_operand:V16QI 3 "register_operand" "v")] 145))]
- "TARGET_ALTIVEC"
- "vperm %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vperm_8hi"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V16QI 3 "register_operand" "v")] 146))]
- "TARGET_ALTIVEC"
- "vperm %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vperm_16qi"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")
- (match_operand:V16QI 3 "register_operand" "v")] 147))]
- "TARGET_ALTIVEC"
- "vperm %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vrfip"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 148))]
- "TARGET_ALTIVEC"
- "vrfip %0, %1"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vrfin"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 149))]
- "TARGET_ALTIVEC"
- "vrfin %0, %1"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vrfim"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 150))]
- "TARGET_ALTIVEC"
- "vrfim %0, %1"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vcfux"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:QI 2 "immediate_operand" "i")] 151))]
- "TARGET_ALTIVEC"
- "vcfux %0, %1, %2"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vcfsx"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:QI 2 "immediate_operand" "i")] 152))]
- "TARGET_ALTIVEC"
- "vcfsx %0, %1, %2"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vctuxs"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:QI 2 "immediate_operand" "i")] 153))]
- "TARGET_ALTIVEC"
- "vctuxs %0, %1, %2"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vctsxs"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:QI 2 "immediate_operand" "i")] 154))]
- "TARGET_ALTIVEC"
- "vctsxs %0, %1, %2"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vlogefp"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 155))]
- "TARGET_ALTIVEC"
- "vlogefp %0, %1"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vexptefp"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 156))]
- "TARGET_ALTIVEC"
- "vexptefp %0, %1"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vrsqrtefp"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 157))]
- "TARGET_ALTIVEC"
- "vrsqrtefp %0, %1"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vrefp"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 158))]
- "TARGET_ALTIVEC"
- "vrefp %0, %1"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vsel_4si"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 159))]
- "TARGET_ALTIVEC"
- "vsel %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsel_4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 160))]
- "TARGET_ALTIVEC"
- "vsel %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsel_8hi"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V8HI 3 "register_operand" "v")] 161))]
- "TARGET_ALTIVEC"
- "vsel %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsel_16qi"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")
- (match_operand:V16QI 3 "register_operand" "v")] 162))]
- "TARGET_ALTIVEC"
- "vsel %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsldoi_4si"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")
- (match_operand:QI 3 "immediate_operand" "i")] 163))]
- "TARGET_ALTIVEC"
- "vsldoi %0, %1, %2, %3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsldoi_4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")
- (match_operand:QI 3 "immediate_operand" "i")] 164))]
- "TARGET_ALTIVEC"
- "vsldoi %0, %1, %2, %3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsldoi_8hi"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand:QI 3 "immediate_operand" "i")] 165))]
- "TARGET_ALTIVEC"
- "vsldoi %0, %1, %2, %3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsldoi_16qi"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")
- (match_operand:QI 3 "immediate_operand" "i")] 166))]
- "TARGET_ALTIVEC"
- "vsldoi %0, %1, %2, %3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vupkhsb"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")] 167))]
- "TARGET_ALTIVEC"
- "vupkhsb %0, %1"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vupkhpx"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")] 168))]
- "TARGET_ALTIVEC"
- "vupkhpx %0, %1"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vupkhsh"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")] 169))]
- "TARGET_ALTIVEC"
- "vupkhsh %0, %1"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vupklsb"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")] 170))]
- "TARGET_ALTIVEC"
- "vupklsb %0, %1"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vupklpx"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")] 171))]
- "TARGET_ALTIVEC"
- "vupklpx %0, %1"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vupklsh"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")] 172))]
- "TARGET_ALTIVEC"
- "vupklsh %0, %1"
- [(set_attr "type" "vecperm")])
-
-;; AltiVec predicates.
-
-(define_expand "cr6_test_for_zero"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (eq:SI (reg:CC 74)
- (const_int 0)))]
- "TARGET_ALTIVEC"
- "")
-
-(define_expand "cr6_test_for_zero_reverse"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (eq:SI (reg:CC 74)
- (const_int 0)))
- (set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
- "TARGET_ALTIVEC"
- "")
-(define_expand "cr6_test_for_lt"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lt:SI (reg:CC 74)
- (const_int 0)))]
- "TARGET_ALTIVEC"
- "")
-
-(define_expand "cr6_test_for_lt_reverse"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lt:SI (reg:CC 74)
- (const_int 0)))
- (set (match_dup 0) (minus:SI (const_int 1) (match_dup 0)))]
- "TARGET_ALTIVEC"
- "")
-
-;; We can get away with generating the opcode on the fly (%3 below)
-;; because all the predicates have the same scheduling parameters.
-
-(define_insn "altivec_predicate_v4si"
- [(set (reg:CC 74)
- (unspec:CC [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")
- (match_operand 3 "any_operand" "")] 173))
- (clobber (match_scratch:V4SI 0 "=v"))]
- "TARGET_ALTIVEC"
- "%3 %0,%1,%2"
-[(set_attr "type" "veccmp")])
-
-(define_insn "altivec_predicate_v4sf"
- [(set (reg:CC 74)
- (unspec:CC [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")
- (match_operand 3 "any_operand" "")] 174))
- (clobber (match_scratch:V4SF 0 "=v"))]
- "TARGET_ALTIVEC"
- "%3 %0,%1,%2"
-[(set_attr "type" "veccmp")])
-
-(define_insn "altivec_predicate_v8hi"
- [(set (reg:CC 74)
- (unspec:CC [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand 3 "any_operand" "")] 175))
- (clobber (match_scratch:V8HI 0 "=v"))]
- "TARGET_ALTIVEC"
- "%3 %0,%1,%2"
-[(set_attr "type" "veccmp")])
-
-(define_insn "altivec_predicate_v16qi"
- [(set (reg:CC 74)
- (unspec:CC [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")
- (match_operand 3 "any_operand" "")] 175))
- (clobber (match_scratch:V16QI 0 "=v"))]
- "TARGET_ALTIVEC"
- "%3 %0,%1,%2"
-[(set_attr "type" "veccmp")])
-
-(define_insn "altivec_mtvscr"
- [(unspec [(match_operand:V4SI 0 "register_operand" "v")] 186)]
- "TARGET_ALTIVEC"
- "mtvscr %0"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_mfvscr"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(const_int 0)] 187))]
- "TARGET_ALTIVEC"
- "mfvscr %0"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_dssall"
- [(unspec [(const_int 0)] 188)]
- "TARGET_ALTIVEC"
- "dssall"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_dss"
- [(unspec [(match_operand:QI 0 "immediate_operand" "i")] 189)]
- "TARGET_ALTIVEC"
- "dss %0"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_dst"
- [(unspec [(match_operand:SI 0 "register_operand" "b")
- (match_operand:SI 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i")] 190)]
- "TARGET_ALTIVEC"
- "dst %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_dstt"
- [(unspec [(match_operand:SI 0 "register_operand" "b")
- (match_operand:SI 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i")] 191)]
- "TARGET_ALTIVEC"
- "dstt %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_dstst"
- [(unspec [(match_operand:SI 0 "register_operand" "b")
- (match_operand:SI 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i")] 192)]
- "TARGET_ALTIVEC"
- "dstst %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_dststt"
- [(unspec [(match_operand:SI 0 "register_operand" "b")
- (match_operand:SI 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i")] 193)]
- "TARGET_ALTIVEC"
- "dststt %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_lvsl"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:SI 1 "register_operand" "b")
- (match_operand:SI 2 "register_operand" "r")] 194))]
- "TARGET_ALTIVEC"
- "lvsl %0,%1,%2"
- [(set_attr "type" "vecload")])
-
-(define_insn "altivec_lvsr"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:SI 1 "register_operand" "b")
- (match_operand:SI 2 "register_operand" "r")] 195))]
- "TARGET_ALTIVEC"
- "lvsr %0,%1,%2"
- [(set_attr "type" "vecload")])
-
-;; Parallel some of the LVE* and STV*'s with unspecs because some have
-;; identical rtl but different instructions-- and gcc gets confused.
-
-(define_insn "altivec_lvebx"
- [(parallel
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (mem:V16QI (plus:SI (match_operand:SI 1 "register_operand" "b")
- (match_operand:SI 2 "register_operand" "r"))))
- (unspec [(const_int 0)] 196)])]
- "TARGET_ALTIVEC"
- "lvebx %0,%1,%2"
- [(set_attr "type" "vecload")])
-
-(define_insn "altivec_lvehx"
- [(parallel
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (mem:V8HI
- (and:SI (plus:SI (match_operand:SI 1 "register_operand" "b")
- (match_operand:SI 2 "register_operand" "r"))
- (const_int -2))))
- (unspec [(const_int 0)] 197)])]
- "TARGET_ALTIVEC"
- "lvehx %0,%1,%2"
- [(set_attr "type" "vecload")])
-
-(define_insn "altivec_lvewx"
- [(parallel
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (mem:V4SI
- (and:SI (plus:SI (match_operand:SI 1 "register_operand" "b")
- (match_operand:SI 2 "register_operand" "r"))
- (const_int -4))))
- (unspec [(const_int 0)] 198)])]
- "TARGET_ALTIVEC"
- "lvewx %0,%1,%2"
- [(set_attr "type" "vecload")])
-
-(define_insn "altivec_lvxl"
- [(parallel
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (mem:V4SI (plus:SI (match_operand:SI 1 "register_operand" "b")
- (match_operand:SI 2 "register_operand" "r"))))
- (unspec [(const_int 0)] 213)])]
- "TARGET_ALTIVEC"
- "lvxl %0,%1,%2"
- [(set_attr "type" "vecload")])
-
-(define_insn "altivec_lvx"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (mem:V4SI (plus:SI (match_operand:SI 1 "register_operand" "b")
- (match_operand:SI 2 "register_operand" "r"))))]
- "TARGET_ALTIVEC"
- "lvx %0,%1,%2"
- [(set_attr "type" "vecload")])
-
-(define_insn "altivec_stvx"
- [(parallel
- [(set (mem:V4SI
- (and:SI (plus:SI (match_operand:SI 0 "register_operand" "b")
- (match_operand:SI 1 "register_operand" "r"))
- (const_int -16)))
- (match_operand:V4SI 2 "register_operand" "v"))
- (unspec [(const_int 0)] 201)])]
- "TARGET_ALTIVEC"
- "stvx %2,%0,%1"
- [(set_attr "type" "vecstore")])
-
-(define_insn "altivec_stvxl"
- [(parallel
- [(set (mem:V4SI
- (and:SI (plus:SI (match_operand:SI 0 "register_operand" "b")
- (match_operand:SI 1 "register_operand" "r"))
- (const_int -16)))
- (match_operand:V4SI 2 "register_operand" "v"))
- (unspec [(const_int 0)] 202)])]
- "TARGET_ALTIVEC"
- "stvxl %2,%0,%1"
- [(set_attr "type" "vecstore")])
-
-(define_insn "altivec_stvebx"
- [(parallel
- [(set (mem:V16QI
- (plus:SI (match_operand:SI 0 "register_operand" "b")
- (match_operand:SI 1 "register_operand" "r")))
- (match_operand:V16QI 2 "register_operand" "v"))
- (unspec [(const_int 0)] 203)])]
- "TARGET_ALTIVEC"
- "stvebx %2,%0,%1"
- [(set_attr "type" "vecstore")])
-
-(define_insn "altivec_stvehx"
- [(parallel
- [(set (mem:V8HI
- (and:SI (plus:SI (match_operand:SI 0 "register_operand" "b")
- (match_operand:SI 1 "register_operand" "r"))
- (const_int -2)))
- (match_operand:V8HI 2 "register_operand" "v"))
- (unspec [(const_int 0)] 204)])]
- "TARGET_ALTIVEC"
- "stvehx %2,%0,%1"
- [(set_attr "type" "vecstore")])
-
-(define_insn "altivec_stvewx"
- [(parallel
- [(set (mem:V4SI
- (and:SI (plus:SI (match_operand:SI 0 "register_operand" "b")
- (match_operand:SI 1 "register_operand" "r"))
- (const_int -4)))
- (match_operand:V4SI 2 "register_operand" "v"))
- (unspec [(const_int 0)] 205)])]
- "TARGET_ALTIVEC"
- "stvewx %2,%0,%1"
- [(set_attr "type" "vecstore")])
-
-(define_insn "absv16qi2"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (abs:V16QI (match_operand:V16QI 1 "register_operand" "v")))
- (clobber (match_scratch:V16QI 2 "=v"))
- (clobber (match_scratch:V16QI 3 "=v"))]
- "TARGET_ALTIVEC"
- "vspltisb %2,0\;vsububm %3,%2,%1\;vmaxsb %0,%1,%3"
- [(set_attr "type" "altivec")
- (set_attr "length" "12")])
-
-(define_insn "absv8hi2"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (abs:V8HI (match_operand:V8HI 1 "register_operand" "v")))
- (clobber (match_scratch:V8HI 2 "=v"))
- (clobber (match_scratch:V8HI 3 "=v"))]
- "TARGET_ALTIVEC"
- "vspltisb %2,0\;vsubuhm %3,%2,%1\;vmaxsh %0,%1,%3"
- [(set_attr "type" "altivec")
- (set_attr "length" "12")])
-
-(define_insn "absv4si2"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (abs:V4SI (match_operand:V4SI 1 "register_operand" "v")))
- (clobber (match_scratch:V4SI 2 "=v"))
- (clobber (match_scratch:V4SI 3 "=v"))]
- "TARGET_ALTIVEC"
- "vspltisb %2,0\;vsubuwm %3,%2,%1\;vmaxsw %0,%1,%3"
- [(set_attr "type" "altivec")
- (set_attr "length" "12")])
-
-(define_insn "absv4sf2"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (abs:V4SF (match_operand:V4SF 1 "register_operand" "v")))
- (clobber (match_scratch:V4SF 2 "=v"))
- (clobber (match_scratch:V4SF 3 "=v"))]
- "TARGET_ALTIVEC"
- "vspltisw %2, -1\;vslw %3,%2,%2\;vandc %0,%1,%3"
- [(set_attr "type" "altivec")
- (set_attr "length" "12")])
-
-(define_insn "altivec_abss_v16qi"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")] 210))
- (clobber (match_scratch:V16QI 2 "=v"))
- (clobber (match_scratch:V16QI 3 "=v"))]
- "TARGET_ALTIVEC"
- "vspltisb %2,0\;vsubsbs %3,%2,%1\;vmaxsb %0,%1,%3"
- [(set_attr "type" "altivec")
- (set_attr "length" "12")])
-
-(define_insn "altivec_abss_v8hi"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")] 211))
- (clobber (match_scratch:V8HI 2 "=v"))
- (clobber (match_scratch:V8HI 3 "=v"))]
- "TARGET_ALTIVEC"
- "vspltisb %2,0\;vsubshs %3,%2,%1\;vmaxsh %0,%1,%3"
- [(set_attr "type" "altivec")
- (set_attr "length" "12")])
-
-(define_insn "altivec_abss_v4si"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")] 212))
- (clobber (match_scratch:V4SI 2 "=v"))
- (clobber (match_scratch:V4SI 3 "=v"))]
- "TARGET_ALTIVEC"
- "vspltisb %2,0\;vsubsws %3,%2,%1\;vmaxsw %0,%1,%3"
- [(set_attr "type" "altivec")
- (set_attr "length" "12")])
+(include "altivec.md")
+(include "spe.md")
diff --git a/contrib/gcc/config/rs6000/rtems.h b/contrib/gcc/config/rs6000/rtems.h
index cc8295a..7e75846 100644
--- a/contrib/gcc/config/rs6000/rtems.h
+++ b/contrib/gcc/config/rs6000/rtems.h
@@ -21,9 +21,17 @@ Boston, MA 02111-1307, USA. */
/* Specify predefined symbols in preprocessor. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-DPPC -D__rtems__ -D__USE_INIT_FINI__ \
- -Asystem=rtems -Acpu=powerpc -Amachine=powerpc"
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("PPC"); \
+ builtin_define ("__rtems__"); \
+ builtin_assert ("system=rtems"); \
+ builtin_assert ("cpu=powerpc"); \
+ builtin_assert ("machine=powerpc"); \
+ } \
+ while (0)
#undef CPP_OS_DEFAULT_SPEC
#define CPP_OS_DEFAULT_SPEC "%(cpp_os_rtems)"
diff --git a/contrib/gcc/config/rs6000/spe.h b/contrib/gcc/config/rs6000/spe.h
new file mode 100644
index 0000000..b15dac5
--- /dev/null
+++ b/contrib/gcc/config/rs6000/spe.h
@@ -0,0 +1,1096 @@
+/* PowerPC E500 user include file.
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Contributed by Aldy Hernandez (aldyh@redhat.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you include this header file into source
+ files compiled by GCC, this header file 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. */
+
+#ifndef _SPE_H
+#define _SPE_H
+
+#define __vector __attribute__((vector_size(8)))
+
+typedef int int32_t;
+typedef unsigned uint32_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+
+typedef short __vector __ev64_s16__;
+typedef unsigned short __vector __ev64_u16__;
+typedef int __vector __ev64_s32__;
+typedef unsigned __vector __ev64_u32__;
+typedef long long __vector __ev64_s64__;
+typedef unsigned long long __vector __ev64_u64__;
+typedef float __vector __ev64_fs__;
+typedef int __vector __ev64_opaque__;
+
+#define __v2si __ev64_opaque__
+#define __v2sf __ev64_fs__
+
+#define __ev_addw(a,b) __builtin_spe_evaddw((__v2si) (a), (__v2si) (b))
+#define __ev_addiw(a,b) __builtin_spe_evaddiw ((__v2si) (a), (b))
+#define __ev_subfw(a,b) __builtin_spe_evsubfw ((__v2si) (a), (__v2si) (b))
+#define __ev_subw(a,b) __builtin_spe_evsubfw ((__v2si) (b), (__v2si) (a))
+/* ??? The spe_evsubifw pattern accepts operands reversed, so we need to also
+ reverse them here between the intrinsic and the builtin function. */
+#define __ev_subifw(a,b) __builtin_spe_evsubifw ((__v2si) (b), (a))
+#define __ev_subiw(a,b) __builtin_spe_evsubifw ((__v2si) (a), (b))
+#define __ev_abs(a) __builtin_spe_evabs ((__v2si) (a))
+#define __ev_neg(a) __builtin_spe_evneg ((__v2si) (a))
+#define __ev_extsb(a) __builtin_spe_evextsb ((__v2si) (a))
+#define __ev_extsh(a) __builtin_spe_evextsh ((__v2si) (a))
+#define __ev_and(a,b) __builtin_spe_evand ((__v2si) (a), (__v2si) (b))
+#define __ev_or(a,b) __builtin_spe_evor ((__v2si) (a), (__v2si) (b))
+#define __ev_xor(a,b) __builtin_spe_evxor ((__v2si) (a), (__v2si) (b))
+#define __ev_nand(a,b) __builtin_spe_evnand ((__v2si) (a), (__v2si) (b))
+#define __ev_nor(a,b) __builtin_spe_evnor ((__v2si) (a), (__v2si) (b))
+#define __ev_eqv(a,b) __builtin_spe_eveqv ((__v2si) (a), (__v2si) (b))
+#define __ev_andc(a,b) __builtin_spe_evandc ((__v2si) (a), (__v2si) (b))
+#define __ev_orc(a,b) __builtin_spe_evorc ((__v2si) (a), (__v2si) (b))
+#define __ev_rlw(a,b) __builtin_spe_evrlw ((__v2si) (a), (__v2si) (b))
+#define __ev_rlwi(a,b) __builtin_spe_evrlwi ((__v2si) (a), (b))
+#define __ev_slw(a,b) __builtin_spe_evslw ((__v2si) (a), (__v2si) (b))
+#define __ev_slwi(a,b) __builtin_spe_evslwi ((__v2si) (a), (b))
+#define __ev_srws(a,b) __builtin_spe_evsrws ((__v2si) (a), (__v2si) (b))
+#define __ev_srwu(a,b) __builtin_spe_evsrwu ((__v2si) (a), (__v2si) (b))
+#define __ev_srwis(a,b) __builtin_spe_evsrwis ((__v2si) (a), (b))
+#define __ev_srwiu(a,b) __builtin_spe_evsrwiu ((__v2si) (a), (b))
+#define __ev_cntlzw(a) __builtin_spe_evcntlzw ((__v2si) (a))
+#define __ev_cntlsw(a) __builtin_spe_evcntlsw ((__v2si) (a))
+#define __ev_rndw(a) __builtin_spe_evrndw ((__v2si) (a))
+#define __ev_mergehi(a,b) __builtin_spe_evmergehi ((__v2si) (a), (__v2si) (b))
+#define __ev_mergelo(a,b) __builtin_spe_evmergelo ((__v2si) (a), (__v2si) (b))
+#define __ev_mergelohi(a,b) __builtin_spe_evmergelohi ((__v2si) (a), (__v2si) (b))
+#define __ev_mergehilo(a,b) __builtin_spe_evmergehilo ((__v2si) (a), (__v2si) (b))
+#define __ev_splati(a) __builtin_spe_evsplati ((a))
+#define __ev_splatfi(a) __builtin_spe_evsplatfi ((a))
+#define __ev_divws(a,b) __builtin_spe_evdivws ((__v2si) (a), (__v2si) (b))
+#define __ev_divwu(a,b) __builtin_spe_evdivwu ((__v2si) (a), (__v2si) (b))
+#define __ev_mra(a) __builtin_spe_evmra ((__v2si) (a))
+
+#define __brinc __builtin_spe_brinc
+
+/* Loads. */
+
+#define __ev_lddx(a,b) __builtin_spe_evlddx ((void *)(a), (b))
+#define __ev_ldwx(a,b) __builtin_spe_evldwx ((void *)(a), (b))
+#define __ev_ldhx(a,b) __builtin_spe_evldhx ((void *)(a), (b))
+#define __ev_lwhex(a,b) __builtin_spe_evlwhex ((a), (b))
+#define __ev_lwhoux(a,b) __builtin_spe_evlwhoux ((a), (b))
+#define __ev_lwhosx(a,b) __builtin_spe_evlwhosx ((a), (b))
+#define __ev_lwwsplatx(a,b) __builtin_spe_evlwwsplatx ((a), (b))
+#define __ev_lwhsplatx(a,b) __builtin_spe_evlwhsplatx ((a), (b))
+#define __ev_lhhesplatx(a,b) __builtin_spe_evlhhesplatx ((a), (b))
+#define __ev_lhhousplatx(a,b) __builtin_spe_evlhhousplatx ((a), (b))
+#define __ev_lhhossplatx(a,b) __builtin_spe_evlhhossplatx ((a), (b))
+#define __ev_ldd(a,b) __builtin_spe_evldd ((void *)(a), (b))
+#define __ev_ldw(a,b) __builtin_spe_evldw ((void *)(a), (b))
+#define __ev_ldh(a,b) __builtin_spe_evldh ((void *)(a), (b))
+#define __ev_lwhe(a,b) __builtin_spe_evlwhe ((a), (b))
+#define __ev_lwhou(a,b) __builtin_spe_evlwhou ((a), (b))
+#define __ev_lwhos(a,b) __builtin_spe_evlwhos ((a), (b))
+#define __ev_lwwsplat(a,b) __builtin_spe_evlwwsplat ((a), (b))
+#define __ev_lwhsplat(a,b) __builtin_spe_evlwhsplat ((a), (b))
+#define __ev_lhhesplat(a,b) __builtin_spe_evlhhesplat ((a), (b))
+#define __ev_lhhousplat(a,b) __builtin_spe_evlhhousplat ((a), (b))
+#define __ev_lhhossplat(a,b) __builtin_spe_evlhhossplat ((a), (b))
+
+/* Stores. */
+
+#define __ev_stddx(a,b,c) __builtin_spe_evstddx ((__v2si)(a), (void *)(b), (c))
+#define __ev_stdwx(a,b,c) __builtin_spe_evstdwx ((__v2si)(a), (void *)(b), (c))
+#define __ev_stdhx(a,b,c) __builtin_spe_evstdhx ((__v2si)(a), (void *)(b), (c))
+#define __ev_stwwex(a,b,c) __builtin_spe_evstwwex ((__v2si)(a), (b), (c))
+#define __ev_stwwox(a,b,c) __builtin_spe_evstwwox ((__v2si)(a), (b), (c))
+#define __ev_stwhex(a,b,c) __builtin_spe_evstwhex ((__v2si)(a), (b), (c))
+#define __ev_stwhox(a,b,c) __builtin_spe_evstwhox ((__v2si)(a), (b), (c))
+#define __ev_stdd(a,b,c) __builtin_spe_evstdd ((__v2si)(a), (void *)(b), (c))
+#define __ev_stdw(a,b,c) __builtin_spe_evstdw ((__v2si)(a), (void *)(b), (c))
+#define __ev_stdh(a,b,c) __builtin_spe_evstdh ((__v2si)(a), (void *)(b), (c))
+#define __ev_stwwe(a,b,c) __builtin_spe_evstwwe ((__v2si)(a), (b), (c))
+#define __ev_stwwo(a,b,c) __builtin_spe_evstwwo ((__v2si)(a), (b), (c))
+#define __ev_stwhe(a,b,c) __builtin_spe_evstwhe ((__v2si)(a), (b), (c))
+#define __ev_stwho(a,b,c) __builtin_spe_evstwho ((__v2si)(a), (b), (c))
+
+/* Fixed point complex. */
+
+#define __ev_mhossf(a, b) __builtin_spe_evmhossf ((__v2si) (a), (__v2si) (b))
+#define __ev_mhosmf(a, b) __builtin_spe_evmhosmf ((__v2si) (a), (__v2si) (b))
+#define __ev_mhosmi(a, b) __builtin_spe_evmhosmi ((__v2si) (a), (__v2si) (b))
+#define __ev_mhoumi(a, b) __builtin_spe_evmhoumi ((__v2si) (a), (__v2si) (b))
+#define __ev_mhessf(a, b) __builtin_spe_evmhessf ((__v2si) (a), (__v2si) (b))
+#define __ev_mhesmf(a, b) __builtin_spe_evmhesmf ((__v2si) (a), (__v2si) (b))
+#define __ev_mhesmi(a, b) __builtin_spe_evmhesmi ((__v2si) (a), (__v2si) (b))
+#define __ev_mheumi(a, b) __builtin_spe_evmheumi ((__v2si) (a), (__v2si) (b))
+#define __ev_mhossfa(a, b) __builtin_spe_evmhossfa ((__v2si) (a), (__v2si) (b))
+#define __ev_mhosmfa(a, b) __builtin_spe_evmhosmfa ((__v2si) (a), (__v2si) (b))
+#define __ev_mhosmia(a, b) __builtin_spe_evmhosmia ((__v2si) (a), (__v2si) (b))
+#define __ev_mhoumia(a, b) __builtin_spe_evmhoumia ((__v2si) (a), (__v2si) (b))
+#define __ev_mhessfa(a, b) __builtin_spe_evmhessfa ((__v2si) (a), (__v2si) (b))
+#define __ev_mhesmfa(a, b) __builtin_spe_evmhesmfa ((__v2si) (a), (__v2si) (b))
+#define __ev_mhesmia(a, b) __builtin_spe_evmhesmia ((__v2si) (a), (__v2si) (b))
+#define __ev_mheumia(a, b) __builtin_spe_evmheumia ((__v2si) (a), (__v2si) (b))
+
+#define __ev_mhoumf __ev_mhoumi
+#define __ev_mheumf __ev_mheumi
+#define __ev_mhoumfa __ev_mhoumia
+#define __ev_mheumfa __ev_mheumia
+
+#define __ev_mhossfaaw(a, b) __builtin_spe_evmhossfaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhossiaaw(a, b) __builtin_spe_evmhossiaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhosmfaaw(a, b) __builtin_spe_evmhosmfaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhosmiaaw(a, b) __builtin_spe_evmhosmiaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhousiaaw(a, b) __builtin_spe_evmhousiaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhoumiaaw(a, b) __builtin_spe_evmhoumiaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhessfaaw(a, b) __builtin_spe_evmhessfaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhessiaaw(a, b) __builtin_spe_evmhessiaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhesmfaaw(a, b) __builtin_spe_evmhesmfaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhesmiaaw(a, b) __builtin_spe_evmhesmiaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mheusiaaw(a, b) __builtin_spe_evmheusiaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mheumiaaw(a, b) __builtin_spe_evmheumiaaw ((__v2si) (a), (__v2si) (b))
+
+#define __ev_mhousfaaw __ev_mhousiaaw
+#define __ev_mhoumfaaw __ev_mhoumiaaw
+#define __ev_mheusfaaw __ev_mheusiaaw
+#define __ev_mheumfaaw __ev_mheumiaaw
+
+#define __ev_mhossfanw(a, b) __builtin_spe_evmhossfanw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhossianw(a, b) __builtin_spe_evmhossianw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhosmfanw(a, b) __builtin_spe_evmhosmfanw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhosmianw(a, b) __builtin_spe_evmhosmianw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhousianw(a, b) __builtin_spe_evmhousianw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhoumianw(a, b) __builtin_spe_evmhoumianw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhessfanw(a, b) __builtin_spe_evmhessfanw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhessianw(a, b) __builtin_spe_evmhessianw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhesmfanw(a, b) __builtin_spe_evmhesmfanw ((__v2si) (a), (__v2si) (b))
+#define __ev_mhesmianw(a, b) __builtin_spe_evmhesmianw ((__v2si) (a), (__v2si) (b))
+#define __ev_mheusianw(a, b) __builtin_spe_evmheusianw ((__v2si) (a), (__v2si) (b))
+#define __ev_mheumianw(a, b) __builtin_spe_evmheumianw ((__v2si) (a), (__v2si) (b))
+
+#define __ev_mhousfanw __ev_mhousianw
+#define __ev_mhoumfanw __ev_mhoumianw
+#define __ev_mheusfanw __ev_mheusianw
+#define __ev_mheumfanw __ev_mheumianw
+
+#define __ev_mhogsmfaa(a, b) __builtin_spe_evmhogsmfaa ((__v2si) (a), (__v2si) (b))
+#define __ev_mhogsmiaa(a, b) __builtin_spe_evmhogsmiaa ((__v2si) (a), (__v2si) (b))
+#define __ev_mhogumiaa(a, b) __builtin_spe_evmhogumiaa ((__v2si) (a), (__v2si) (b))
+#define __ev_mhegsmfaa(a, b) __builtin_spe_evmhegsmfaa ((__v2si) (a), (__v2si) (b))
+#define __ev_mhegsmiaa(a, b) __builtin_spe_evmhegsmiaa ((__v2si) (a), (__v2si) (b))
+#define __ev_mhegumiaa(a, b) __builtin_spe_evmhegumiaa ((__v2si) (a), (__v2si) (b))
+
+#define __ev_mhogumfaa __ev_mhogumiaa
+#define __ev_mhegumfaa __ev_mhegumiaa
+
+#define __ev_mhogsmfan(a, b) __builtin_spe_evmhogsmfan ((__v2si) (a), (__v2si) (b))
+#define __ev_mhogsmian(a, b) __builtin_spe_evmhogsmian ((__v2si) (a), (__v2si) (b))
+#define __ev_mhogumian(a, b) __builtin_spe_evmhogumian ((__v2si) (a), (__v2si) (b))
+#define __ev_mhegsmfan(a, b) __builtin_spe_evmhegsmfan ((__v2si) (a), (__v2si) (b))
+#define __ev_mhegsmian(a, b) __builtin_spe_evmhegsmian ((__v2si) (a), (__v2si) (b))
+#define __ev_mhegumian(a, b) __builtin_spe_evmhegumian ((__v2si) (a), (__v2si) (b))
+
+#define __ev_mhogumfan __ev_mhogumian
+#define __ev_mhegumfan __ev_mhegumian
+
+#define __ev_mwhssf(a, b) __builtin_spe_evmwhssf ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhsmf(a, b) __builtin_spe_evmwhsmf ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhsmi(a, b) __builtin_spe_evmwhsmi ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhumi(a, b) __builtin_spe_evmwhumi ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhssfa(a, b) __builtin_spe_evmwhssfa ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhsmfa(a, b) __builtin_spe_evmwhsmfa ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhsmia(a, b) __builtin_spe_evmwhsmia ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhumia(a, b) __builtin_spe_evmwhumia ((__v2si) (a), (__v2si) (b))
+
+#define __ev_mwhumf __ev_mwhumi
+#define __ev_mwhumfa __ev_mwhumia
+
+#define __ev_mwlumi(a, b) __builtin_spe_evmwlumi ((__v2si) (a), (__v2si) (b))
+#define __ev_mwlumia(a, b) __builtin_spe_evmwlumia ((__v2si) (a), (__v2si) (b))
+#define __ev_mwlumiaaw(a, b) __builtin_spe_evmwlumiaaw ((__v2si) (a), (__v2si) (b))
+
+#define __ev_mwlssiaaw(a, b) __builtin_spe_evmwlssiaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwlsmiaaw(a, b) __builtin_spe_evmwlsmiaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwlusiaaw(a, b) __builtin_spe_evmwlusiaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwlusiaaw(a, b) __builtin_spe_evmwlusiaaw ((__v2si) (a), (__v2si) (b))
+
+#define __ev_mwlssianw(a, b) __builtin_spe_evmwlssianw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwlsmianw(a, b) __builtin_spe_evmwlsmianw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwlusianw(a, b) __builtin_spe_evmwlusianw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwlumianw(a, b) __builtin_spe_evmwlumianw ((__v2si) (a), (__v2si) (b))
+
+#define __ev_mwssf(a, b) __builtin_spe_evmwssf ((__v2si) (a), (__v2si) (b))
+#define __ev_mwsmf(a, b) __builtin_spe_evmwsmf ((__v2si) (a), (__v2si) (b))
+#define __ev_mwsmi(a, b) __builtin_spe_evmwsmi ((__v2si) (a), (__v2si) (b))
+#define __ev_mwumi(a, b) __builtin_spe_evmwumi ((__v2si) (a), (__v2si) (b))
+#define __ev_mwssfa(a, b) __builtin_spe_evmwssfa ((__v2si) (a), (__v2si) (b))
+#define __ev_mwsmfa(a, b) __builtin_spe_evmwsmfa ((__v2si) (a), (__v2si) (b))
+#define __ev_mwsmia(a, b) __builtin_spe_evmwsmia ((__v2si) (a), (__v2si) (b))
+#define __ev_mwumia(a, b) __builtin_spe_evmwumia ((__v2si) (a), (__v2si) (b))
+
+#define __ev_mwumf __ev_mwumi
+#define __ev_mwumfa __ev_mwumia
+
+#define __ev_mwssfaa(a, b) __builtin_spe_evmwssfaa ((__v2si) (a), (__v2si) (b))
+#define __ev_mwsmfaa(a, b) __builtin_spe_evmwsmfaa ((__v2si) (a), (__v2si) (b))
+#define __ev_mwsmiaa(a, b) __builtin_spe_evmwsmiaa ((__v2si) (a), (__v2si) (b))
+#define __ev_mwumiaa(a, b) __builtin_spe_evmwumiaa ((__v2si) (a), (__v2si) (b))
+
+#define __ev_mwumfaa __ev_mwumiaa
+
+#define __ev_mwssfan(a, b) __builtin_spe_evmwssfan ((__v2si) (a), (__v2si) (b))
+#define __ev_mwsmfan(a, b) __builtin_spe_evmwsmfan ((__v2si) (a), (__v2si) (b))
+#define __ev_mwsmian(a, b) __builtin_spe_evmwsmian ((__v2si) (a), (__v2si) (b))
+#define __ev_mwumian(a, b) __builtin_spe_evmwumian ((__v2si) (a), (__v2si) (b))
+
+#define __ev_mwumfan __ev_mwumian
+
+#define __ev_addssiaaw(a) __builtin_spe_evaddssiaaw ((__v2si) (a))
+#define __ev_addsmiaaw(a) __builtin_spe_evaddsmiaaw ((__v2si) (a))
+#define __ev_addusiaaw(a) __builtin_spe_evaddusiaaw ((__v2si) (a))
+#define __ev_addumiaaw(a) __builtin_spe_evaddumiaaw ((__v2si) (a))
+
+#define __ev_addusfaaw __ev_addusiaaw
+#define __ev_addumfaaw __ev_addumiaaw
+#define __ev_addsmfaaw __ev_addsmiaaw
+#define __ev_addssfaaw __ev_addssiaaw
+
+#define __ev_subfssiaaw(a) __builtin_spe_evsubfssiaaw ((__v2si) (a))
+#define __ev_subfsmiaaw(a) __builtin_spe_evsubfsmiaaw ((__v2si) (a))
+#define __ev_subfusiaaw(a) __builtin_spe_evsubfusiaaw ((__v2si) (a))
+#define __ev_subfumiaaw(a) __builtin_spe_evsubfumiaaw ((__v2si) (a))
+
+#define __ev_subfusfaaw __ev_subfusiaaw
+#define __ev_subfumfaaw __ev_subfumiaaw
+#define __ev_subfsmfaaw __ev_subfsmiaaw
+#define __ev_subfssfaaw __ev_subfssiaaw
+
+/* Floating Point SIMD Instructions */
+
+/* These all return V2SF, but we need to cast them to V2SI
+ because the SPE expect all functions to be __ev64_opaque__. */
+
+#define __ev_fsabs(a) ((__v2si) __builtin_spe_evfsabs ((__v2sf) (a)))
+#define __ev_fsnabs(a) ((__v2si) __builtin_spe_evfsnabs ((__v2sf) (a)))
+#define __ev_fsneg(a) ((__v2si) __builtin_spe_evfsneg ((__v2sf) (a)))
+#define __ev_fsadd(a, b) ((__v2si) __builtin_spe_evfsadd ((__v2sf) (a), (__v2sf) (b)))
+#define __ev_fssub(a, b) ((__v2si) __builtin_spe_evfssub ((__v2sf) (a), (__v2sf) (b)))
+#define __ev_fsmul(a, b) ((__v2si) __builtin_spe_evfsmul ((__v2sf) (a), (__v2sf) b))
+#define __ev_fsdiv(a, b) ((__v2si) __builtin_spe_evfsdiv ((__v2sf) (a), (__v2sf) b))
+#define __ev_fscfui(a) ((__v2si) __builtin_spe_evfscfui ((__v2si) (a)))
+#define __ev_fscfsi(a) ((__v2si) __builtin_spe_evfscfsi ((__v2sf) (a)))
+#define __ev_fscfuf(a) ((__v2si) __builtin_spe_evfscfuf ((__v2sf) (a)))
+#define __ev_fscfsf(a) ((__v2si) __builtin_spe_evfscfsf ((__v2sf) (a)))
+#define __ev_fsctui(a) ((__v2si) __builtin_spe_evfsctui ((__v2sf) (a)))
+#define __ev_fsctsi(a) ((__v2si) __builtin_spe_evfsctsi ((__v2sf) (a)))
+#define __ev_fsctuf(a) ((__v2si) __builtin_spe_evfsctuf ((__v2sf) (a)))
+#define __ev_fsctsf(a) ((__v2si) __builtin_spe_evfsctsf ((__v2sf) (a)))
+#define __ev_fsctuiz(a) ((__v2si) __builtin_spe_evfsctuiz ((__v2sf) (a)))
+#define __ev_fsctsiz(a) ((__v2si) __builtin_spe_evfsctsiz ((__v2sf) (a)))
+
+/* NOT SUPPORTED IN FIRST e500, support via two instructions: */
+
+#define __ev_mwhusfaaw __ev_mwhusiaaw
+#define __ev_mwhumfaaw __ev_mwhumiaaw
+#define __ev_mwhusfanw __ev_mwhusianw
+#define __ev_mwhumfanw __ev_mwhumianw
+#define __ev_mwhgumfaa __ev_mwhgumiaa
+#define __ev_mwhgumfan __ev_mwhgumian
+
+#define __ev_mwhgssfaa(a, b) __internal_ev_mwhgssfaa ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhgsmfaa(a, b) __internal_ev_mwhgsmfaa ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhgsmiaa(a, b) __internal_ev_mwhgsmiaa ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhgumiaa(a, b) __internal_ev_mwhgumiaa ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhgssfan(a, b) __internal_ev_mwhgssfan ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhgsmfan(a, b) __internal_ev_mwhgsmfan ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhgsmian(a, b) __internal_ev_mwhgsmian ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhgumian(a, b) __internal_ev_mwhgumian ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhssiaaw(a, b) __internal_ev_mwhssiaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhssfaaw(a, b) __internal_ev_mwhssfaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhsmfaaw(a, b) __internal_ev_mwhsmfaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhsmiaaw(a, b) __internal_ev_mwhsmiaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhusiaaw(a, b) __internal_ev_mwhusiaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhumiaaw(a, b) __internal_ev_mwhumiaaw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhssfanw(a, b) __internal_ev_mwhssfanw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhssianw(a, b) __internal_ev_mwhssianw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhsmfanw(a, b) __internal_ev_mwhsmfanw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhsmianw(a, b) __internal_ev_mwhsmianw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhusianw(a, b) __internal_ev_mwhusianw ((__v2si) (a), (__v2si) (b))
+#define __ev_mwhumianw(a, b) __internal_ev_mwhumianw ((__v2si) (a), (__v2si) (b))
+
+static inline __ev64_opaque__
+__internal_ev_mwhssfaaw (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhssf (a, b);
+ return __ev_addssiaaw (t);
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhssiaaw (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhsmi (a, b);
+ return __ev_addssiaaw (t);
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhsmfaaw (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhsmf (a, b);
+ return __ev_addsmiaaw (t);
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhsmiaaw (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhsmi (a, b);
+ return __ev_addsmiaaw (t);
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhusiaaw (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhumi (a, b);
+ return __ev_addusiaaw (t);
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhumiaaw (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhumi (a, b);
+ return __ev_addumiaaw (t);
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhssfanw (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhssf (a, b);
+ return __ev_subfssiaaw (t);
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhssianw (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhsmi (a, b);
+ return __ev_subfssiaaw (t);
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhsmfanw (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhsmf (a, b);
+ return __ev_subfsmiaaw (t);
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhsmianw (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhsmi (a, b);
+ return __ev_subfsmiaaw (t);
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhusianw (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhumi (a, b);
+ return __ev_subfusiaaw (t);
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhumianw (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhumi (a, b);
+ return __ev_subfumiaaw (t);
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhgssfaa (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhssf (a, b);
+ return __ev_mwsmiaa (t, ((__ev64_s32__){1, 1}));
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhgsmfaa (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhsmf (a, b);
+ return __ev_mwsmiaa (t, ((__ev64_s32__){1, 1}));
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhgsmiaa (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhsmi (a, b);
+ return __ev_mwsmiaa (t, ((__ev64_s32__){1, 1}));
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhgumiaa (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhumi (a, b);
+ return __ev_mwumiaa (t, ((__ev64_s32__){1, 1}));
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhgssfan (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhssf (a, b);
+ return __ev_mwsmian (t, ((__ev64_s32__){1, 1}));
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhgsmfan (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhsmf (a, b);
+ return __ev_mwsmian (t, ((__ev64_s32__){1, 1}));
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhgsmian (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhsmi (a, b);
+ return __ev_mwsmian (t, ((__ev64_s32__){1, 1}));
+}
+
+static inline __ev64_opaque__
+__internal_ev_mwhgumian (__ev64_opaque__ a, __ev64_opaque__ b)
+{
+ __ev64_opaque__ t;
+
+ t = __ev_mwhumi (a, b);
+ return __ev_mwumian (t, ((__ev64_s32__){1, 1}));
+}
+
+/* END OF NOT SUPPORTED */
+
+/* __ev_create* functions. */
+
+#define __ev_create_ufix32_u32 __ev_create_u32
+#define __ev_create_sfix32_s32 __ev_create_s32
+
+static inline __ev64_opaque__
+__ev_create_s16 (int16_t a, int16_t b, int16_t c, int16_t d)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ int16_t i[4];
+ } u;
+
+ u.i[0] = a;
+ u.i[1] = b;
+ u.i[2] = c;
+ u.i[3] = d;
+
+ return u.v;
+}
+
+static inline __ev64_opaque__
+__ev_create_u16 (uint16_t a, uint16_t b, uint16_t c, uint16_t d)
+
+{
+ union
+ {
+ __ev64_opaque__ v;
+ uint16_t i[4];
+ } u;
+
+ u.i[0] = a;
+ u.i[1] = b;
+ u.i[2] = c;
+ u.i[3] = d;
+
+ return u.v;
+}
+
+static inline __ev64_opaque__
+__ev_create_s32 (int32_t a, int32_t b)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ int32_t i[2];
+ } u;
+
+ u.i[0] = a;
+ u.i[1] = b;
+
+ return u.v;
+}
+
+static inline __ev64_opaque__
+__ev_create_u32 (uint32_t a, uint32_t b)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ uint32_t i[2];
+ } u;
+
+ u.i[0] = a;
+ u.i[1] = b;
+
+ return u.v;
+}
+
+static inline __ev64_opaque__
+__ev_create_fs (float a, float b)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ float f[2];
+ } u;
+
+ u.f[0] = a;
+ u.f[1] = b;
+
+ return u.v;
+}
+
+static inline __ev64_opaque__
+__ev_create_sfix32_fs (float a, float b)
+{
+ __ev64_opaque__ ev;
+
+ ev = (__ev64_opaque__) __ev_create_fs (a, b);
+ return (__ev64_opaque__) __builtin_spe_evfsctsf ((__v2sf) ev);
+}
+
+static inline __ev64_opaque__
+__ev_create_ufix32_fs (float a, float b)
+{
+ __ev64_opaque__ ev;
+
+ ev = (__ev64_opaque__) __ev_create_fs (a, b);
+ return (__ev64_opaque__) __builtin_spe_evfsctuf ((__v2sf) ev);
+}
+
+static inline __ev64_opaque__
+__ev_create_s64 (int64_t a)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ int64_t i;
+ } u;
+
+ u.i = a;
+ return u.v;
+}
+
+static inline __ev64_opaque__
+__ev_create_u64 (uint64_t a)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ uint64_t i;
+ } u;
+
+ u.i = a;
+ return u.v;
+}
+
+static inline uint64_t
+__ev_convert_u64 (__ev64_opaque__ a)
+{
+ return (uint64_t) a;
+}
+
+static inline int64_t
+__ev_convert_s64 (__ev64_opaque__ a)
+{
+ return (int64_t) a;
+}
+
+/* __ev_get_* functions. */
+
+#define __ev_get_upper_u32(a) __ev_get_u32_internal ((__ev64_opaque__) (a), 0)
+#define __ev_get_lower_u32(a) __ev_get_u32_internal ((__ev64_opaque__) (a), 1)
+#define __ev_get_upper_s32(a) __ev_get_s32_internal ((__ev64_opaque__) (a), 0)
+#define __ev_get_lower_s32(a) __ev_get_s32_internal ((__ev64_opaque__) (a), 1)
+#define __ev_get_upper_fs(a) __ev_get_fs_internal ((__ev64_opaque__) (a), 0)
+#define __ev_get_lower_fs(a) __ev_get_fs_internal ((__ev64_opaque__) (a), 1)
+#define __ev_get_upper_ufix32_u32(a) __ev_get_upper_u32(a)
+#define __ev_get_lower_ufix32_u32(a) __ev_get_lower_u32(a)
+#define __ev_get_upper_sfix32_s32(a) __ev_get_upper_s32(a)
+#define __ev_get_lower_sfix32_s32(a) __ev_get_lower_s32(a)
+#define __ev_get_upper_sfix32_fs(a) __ev_get_sfix32_fs (a, 0)
+#define __ev_get_lower_sfix32_fs(a) __ev_get_sfix32_fs (a, 1)
+#define __ev_get_upper_ufix32_fs(a) __ev_get_ufix32_fs (a, 0)
+#define __ev_get_lower_ufix32_fs(a) __ev_get_ufix32_fs (a, 1)
+
+#define __ev_get_u32(a, b) __ev_get_u32_internal ((__ev64_opaque__) (a), b)
+#define __ev_get_s32(a, b) __ev_get_s32_internal ((__ev64_opaque__) (a), b)
+#define __ev_get_fs(a, b) __ev_get_fs_internal ((__ev64_opaque__) (a), b)
+#define __ev_get_u16(a, b) __ev_get_u16_internal ((__ev64_opaque__) (a), b)
+#define __ev_get_s16(a, b) __ev_get_s16_internal ((__ev64_opaque__) (a), b)
+
+#define __ev_get_ufix32_u32(a, b) __ev_get_u32 (a, b)
+#define __ev_get_sfix32_s32(a, b) __ev_get_s32 (a, b)
+#define __ev_get_ufix32_fs(a, b) __ev_get_ufix32_fs_internal ((__ev64_opaque__)(a), b)
+#define __ev_get_sfix32_fs(a, b) __ev_get_sfix32_fs_internal ((__ev64_opaque__)(a), b)
+
+static inline uint32_t
+__ev_get_u32_internal (__ev64_opaque__ a, uint32_t pos)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ uint32_t i[2];
+ } u;
+
+ u.v = a;
+ return u.i[pos];
+}
+
+static inline int32_t
+__ev_get_s32_internal (__ev64_opaque__ a, uint32_t pos)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ int32_t i[2];
+ } u;
+
+ u.v = a;
+ return u.i[pos];
+}
+
+static inline float
+__ev_get_fs_internal (__ev64_opaque__ a, uint32_t pos)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ float f[2];
+ } u;
+
+ u.v = a;
+ return u.f[pos];
+}
+
+static inline float
+__ev_get_sfix32_fs_internal (__ev64_opaque__ a, uint32_t pos)
+{
+ __ev64_fs__ v;
+
+ v = __builtin_spe_evfscfsf ((__v2sf) a);
+ return __ev_get_fs_internal ((__ev64_opaque__) v, pos);
+}
+
+static inline float
+__ev_get_ufix32_fs_internal (__ev64_opaque__ a, uint32_t pos)
+{
+ __ev64_fs__ v;
+
+ v = __builtin_spe_evfscfuf ((__v2sf) a);
+ return __ev_get_fs_internal ((__ev64_opaque__) v, pos);
+}
+
+static inline uint16_t
+__ev_get_u16_internal (__ev64_opaque__ a, uint32_t pos)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ uint16_t i[4];
+ } u;
+
+ u.v = a;
+ return u.i[pos];
+}
+
+static inline int16_t
+__ev_get_s16_internal (__ev64_opaque__ a, uint32_t pos)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ int16_t i[4];
+ } u;
+
+ u.v = a;
+ return u.i[pos];
+}
+
+/* __ev_set_* functions. */
+
+#define __ev_set_u32(a, b, c) __ev_set_u32_internal ((__ev64_opaque__) a, b, c)
+#define __ev_set_s32(a, b, c) __ev_set_s32_internal ((__ev64_opaque__) a, b, c)
+#define __ev_set_fs(a, b, c) __ev_set_fs_internal ((__ev64_opaque__) a, b, c)
+#define __ev_set_u16(a, b, c) __ev_set_u16_internal ((__ev64_opaque__) a, b, c)
+#define __ev_set_s16(a, b, c) __ev_set_s16_internal ((__ev64_opaque__) a, b, c)
+
+#define __ev_set_ufix32_u32 __ev_set_u32
+#define __ev_set_sfix32_s32 __ev_set_s32
+
+#define __ev_set_sfix32_fs(a, b, c) __ev_set_sfix32_fs_internal ((__ev64_opaque__) (a), b, c)
+#define __ev_set_ufix32_fs(a, b, c) __ev_set_ufix32_fs_internal ((__ev64_opaque__) (a), b, c)
+
+#define __ev_set_upper_u32(a, b) __ev_set_u32 (a, b, 0)
+#define __ev_set_lower_u32(a, b) __ev_set_u32 (a, b, 1)
+#define __ev_set_upper_s32(a, b) __ev_set_s32 (a, b, 0)
+#define __ev_set_lower_s32(a, b) __ev_set_s32 (a, b, 1)
+#define __ev_set_upper_fs(a, b) __ev_set_fs (a, b, 0)
+#define __ev_set_lower_fs(a, b) __ev_set_fs (a, b, 1)
+#define __ev_set_upper_ufix32_u32 __ev_set_upper_u32
+#define __ev_set_lower_ufix32_u32 __ev_set_lower_u32
+#define __ev_set_upper_sfix32_s32 __ev_set_upper_s32
+#define __ev_set_lower_sfix32_s32 __ev_set_lower_s32
+#define __ev_set_upper_sfix32_fs(a, b) __ev_set_sfix32_fs (a, b, 0)
+#define __ev_set_lower_sfix32_fs(a, b) __ev_set_sfix32_fs (a, b, 1)
+#define __ev_set_upper_ufix32_fs(a, b) __ev_set_ufix32_fs (a, b, 0)
+#define __ev_set_lower_ufix32_fs(a, b) __ev_set_ufix32_fs (a, b, 1)
+
+#define __ev_set_acc_vec64(a) __builtin_spe_evmra ((__ev64_opaque__)(a))
+
+static inline __ev64_opaque__
+__ev_set_acc_u64 (uint64_t a)
+{
+ __ev64_opaque__ ev32;
+ ev32 = __ev_create_u64 (a);
+ __ev_mra (ev32);
+ return ev32;
+}
+
+static inline __ev64_opaque__
+__ev_set_acc_s64 (int64_t a)
+{
+ __ev64_opaque__ ev32;
+ ev32 = __ev_create_s64 (a);
+ __ev_mra (ev32);
+ return ev32;
+}
+
+static inline __ev64_opaque__
+__ev_set_u32_internal (__ev64_opaque__ a, uint32_t b, uint32_t pos)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ uint32_t i[2];
+ } u;
+
+ u.v = a;
+ u.i[pos] = b;
+ return u.v;
+}
+
+static inline __ev64_opaque__
+__ev_set_s32_internal (__ev64_opaque__ a, int32_t b, uint32_t pos)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ int32_t i[2];
+ } u;
+
+ u.v = a;
+ u.i[pos] = b;
+ return u.v;
+}
+
+static inline __ev64_opaque__
+__ev_set_fs_internal (__ev64_opaque__ a, float b, uint32_t pos)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ float f[2];
+ } u;
+
+ u.v = a;
+ u.f[pos] = b;
+ return u.v;
+}
+
+static inline __ev64_opaque__
+__ev_set_sfix32_fs_internal (__ev64_opaque__ a, float b, uint32_t pos)
+{
+ __ev64_opaque__ v;
+ float other;
+
+ /* Get other half. */
+ other = __ev_get_fs_internal (a, pos ^ 1);
+
+ /* Make an sfix32 with 'b'. */
+ v = __ev_create_sfix32_fs (b, b);
+
+ /* Set other half to what it used to be. */
+ return __ev_set_fs_internal (v, other, pos ^ 1);
+}
+
+static inline __ev64_opaque__
+__ev_set_ufix32_fs_internal (__ev64_opaque__ a, float b, uint32_t pos)
+{
+ __ev64_opaque__ v;
+ float other;
+
+ /* Get other half. */
+ other = __ev_get_fs_internal (a, pos ^ 1);
+
+ /* Make an ufix32 with 'b'. */
+ v = __ev_create_ufix32_fs (b, b);
+
+ /* Set other half to what it used to be. */
+ return __ev_set_fs_internal (v, other, pos ^ 1);
+}
+
+static inline __ev64_opaque__
+__ev_set_u16_internal (__ev64_opaque__ a, uint16_t b, uint32_t pos)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ uint16_t i[4];
+ } u;
+
+ u.v = a;
+ u.i[pos] = b;
+ return u.v;
+}
+
+static inline __ev64_opaque__
+__ev_set_s16_internal (__ev64_opaque__ a, int16_t b, uint32_t pos)
+{
+ union
+ {
+ __ev64_opaque__ v;
+ int16_t i[4];
+ } u;
+
+ u.v = a;
+ u.i[pos] = b;
+ return u.v;
+}
+
+/* Predicates. */
+
+#define __pred_all 0
+#define __pred_any 1
+#define __pred_upper 2
+#define __pred_lower 3
+
+#define __ev_any_gts(a, b) __builtin_spe_evcmpgts (__pred_any, (__v2si) (a), (__v2si) (b))
+#define __ev_all_gts(a, b) __builtin_spe_evcmpgts (__pred_all, (__v2si) (a), (__v2si) (b))
+#define __ev_upper_gts(a, b) __builtin_spe_evcmpgts (__pred_upper, (__v2si) (a), (__v2si) (b))
+#define __ev_lower_gts(a, b) __builtin_spe_evcmpgts (__pred_lower, (__v2si) (a), (__v2si) (b))
+#define __ev_select_gts(a, b, c, d) ((__v2si) __builtin_spe_evsel_gts ((__v2si) (a), (__v2si) (b), (__v2si) (c), (__v2si) (d)))
+
+#define __ev_any_gtu(a, b) __builtin_spe_evcmpgtu (__pred_any, (__v2si) (a), (__v2si) (b))
+#define __ev_all_gtu(a, b) __builtin_spe_evcmpgtu (__pred_all, (__v2si) (a), (__v2si) (b))
+#define __ev_upper_gtu(a, b) __builtin_spe_evcmpgtu (__pred_upper, (__v2si) (a), (__v2si) (b))
+#define __ev_lower_gtu(a, b) __builtin_spe_evcmpgtu (__pred_lower, (__v2si) (a), (__v2si) (b))
+#define __ev_select_gtu(a, b, c, d) ((__v2si) __builtin_spe_evsel_gtu ((__v2si) (a), (__v2si) (b), (__v2si) (c), (__v2si) (d)))
+
+#define __ev_any_lts(a, b) __builtin_spe_evcmplts (__pred_any, (__v2si) (a), (__v2si) (b))
+#define __ev_all_lts(a, b) __builtin_spe_evcmplts (__pred_all, (__v2si) (a), (__v2si) (b))
+#define __ev_upper_lts(a, b) __builtin_spe_evcmplts (__pred_upper, (__v2si) (a), (__v2si) (b))
+#define __ev_lower_lts(a, b) __builtin_spe_evcmplts (__pred_lower, (__v2si) (a), (__v2si) (b))
+#define __ev_select_lts(a, b, c, d) ((__v2si) __builtin_spe_evsel_lts ((__v2si) (a), (__v2si) (b), (__v2si) (c), (__v2si) (d)))
+
+#define __ev_any_ltu(a, b) __builtin_spe_evcmpltu (__pred_any, (__v2si) (a), (__v2si) (b))
+#define __ev_all_ltu(a, b) __builtin_spe_evcmpltu (__pred_all, (__v2si) (a), (__v2si) (b))
+#define __ev_upper_ltu(a, b) __builtin_spe_evcmpltu (__pred_upper, (__v2si) (a), (__v2si) (b))
+#define __ev_lower_ltu(a, b) __builtin_spe_evcmpltu (__pred_lower, (__v2si) (a), (__v2si) (b))
+#define __ev_select_ltu(a, b, c, d) ((__v2si) __builtin_spe_evsel_ltu ((__v2si) (a), (__v2si) (b), (__v2si) (c), (__v2si) (d)))
+#define __ev_any_eq(a, b) __builtin_spe_evcmpeq (__pred_any, (__v2si) (a), (__v2si) (b))
+#define __ev_all_eq(a, b) __builtin_spe_evcmpeq (__pred_all, (__v2si) (a), (__v2si) (b))
+#define __ev_upper_eq(a, b) __builtin_spe_evcmpeq (__pred_upper, (__v2si) (a), (__v2si) (b))
+#define __ev_lower_eq(a, b) __builtin_spe_evcmpeq (__pred_lower, (__v2si) (a), (__v2si) (b))
+#define __ev_select_eq(a, b, c, d) ((__v2si) __builtin_spe_evsel_eq ((__v2si) (a), (__v2si) (b), (__v2si) (c), (__v2si) (d)))
+
+#define __ev_any_fs_gt(a, b) __builtin_spe_evfscmpgt (__pred_any, (__v2sf) (a), (__v2sf) (b))
+#define __ev_all_fs_gt(a, b) __builtin_spe_evfscmpgt (__pred_all, (__v2sf) (a), (__v2sf) (b))
+#define __ev_upper_fs_gt(a, b) __builtin_spe_evfscmpgt (__pred_upper, (__v2sf) (a), (__v2sf) (b))
+#define __ev_lower_fs_gt(a, b) __builtin_spe_evfscmpgt (__pred_lower, (__v2sf) (a), (__v2sf) (b))
+#define __ev_select_fs_gt(a, b, c, d) ((__v2si) __builtin_spe_evsel_fsgt ((__v2sf) (a), (__v2sf) (b), (__v2sf) (c), (__v2sf) (d)))
+
+#define __ev_any_fs_lt(a, b) __builtin_spe_evfscmplt (__pred_any, (__v2sf) (a), (__v2sf) (b))
+#define __ev_all_fs_lt(a, b) __builtin_spe_evfscmplt (__pred_all, (__v2sf) (a), (__v2sf) (b))
+#define __ev_upper_fs_lt(a, b) __builtin_spe_evfscmplt (__pred_upper, (__v2sf) (a), (__v2sf) (b))
+#define __ev_lower_fs_lt(a, b) __builtin_spe_evfscmplt (__pred_lower, (__v2sf) (a), (__v2sf) (b))
+#define __ev_select_fs_lt(a, b, c, d) ((__v2si) __builtin_spe_evsel_fslt ((__v2sf) (a), (__v2sf) (b), (__v2sf) (c), (__v2sf) (d)))
+
+#define __ev_any_fs_eq(a, b) __builtin_spe_evfscmpeq (__pred_any, (__v2sf) (a), (__v2sf) (b))
+#define __ev_all_fs_eq(a, b) __builtin_spe_evfscmpeq (__pred_all, (__v2sf) (a), (__v2sf) (b))
+#define __ev_upper_fs_eq(a, b) __builtin_spe_evfscmpeq (__pred_upper, (__v2sf) (a), (__v2sf) (b))
+#define __ev_lower_fs_eq(a, b) __builtin_spe_evfscmpeq (__pred_lower, (__v2sf) (a), (__v2sf) (b))
+#define __ev_select_fs_eq(a, b, c, d) ((__v2si) __builtin_spe_evsel_fseq ((__v2sf) (a), (__v2sf) (b), (__v2sf) (c), (__v2sf) (d)))
+
+#define __ev_any_fs_tst_gt(a, b) __builtin_spe_evfststgt (__pred_any, (__v2sf) (a), (__v2sf) (b))
+#define __ev_all_fs_tst_gt(a, b) __builtin_spe_evfststgt (__pred_all, (__v2sf) (a), (__v2sf) (b))
+#define __ev_upper_fs_tst_gt(a, b) __builtin_spe_evfststgt (__pred_upper, (__v2sf) (a), (__v2sf) (b))
+#define __ev_lower_fs_tst_gt(a, b) __builtin_spe_evfststgt (__pred_lower, (__v2sf) (a), (__v2sf) (b))
+#define __ev_select_fs_tst_gt(a, b, c, d) ((__v2si) __builtin_spe_evsel_fststgt ((__v2sf) (a), (__v2sf) (b), (__v2sf) (c), (__v2sf) (d)))
+
+#define __ev_any_fs_tst_lt(a, b) __builtin_spe_evfststlt (__pred_any, (__v2sf) (a), (__v2sf) (b))
+#define __ev_all_fs_tst_lt(a, b) __builtin_spe_evfststlt (__pred_all, (__v2sf) (a), (__v2sf) (b))
+#define __ev_upper_fs_tst_lt(a, b) __builtin_spe_evfststlt (__pred_upper, (__v2sf) (a), (__v2sf) (b))
+#define __ev_lower_fs_tst_lt(a, b) __builtin_spe_evfststlt (__pred_lower, (__v2sf) (a), (__v2sf) (b))
+#define __ev_select_fs_tst_lt(a, b, c, d) ((__v2si) __builtin_spe_evsel_fststlt ((__v2sf) (a), (__v2sf) (b), (__v2sf) (c), (__v2sf) (d)))
+
+#define __ev_any_fs_tst_eq(a, b) __builtin_spe_evfststeq (__pred_any, (__v2sf) (a), (__v2sf) (b))
+#define __ev_all_fs_tst_eq(a, b) __builtin_spe_evfststeq (__pred_all, (__v2sf) (a), (__v2sf) (b))
+#define __ev_upper_fs_tst_eq(a, b) __builtin_spe_evfststeq (__pred_upper, (__v2sf) (a), (__v2sf) (b))
+#define __ev_lower_fs_tst_eq(a, b) __builtin_spe_evfststeq (__pred_lower, (__v2sf) (a), (__v2sf) (b))
+#define __ev_select_fs_tst_eq(a, b, c, d) ((__v2si) __builtin_spe_evsel_fststeq ((__v2sf) (a), (__v2sf) (b), (__v2sf) (c), (__v2sf) (d)))
+
+/* SPEFSCR accesor functions. */
+
+#define __SPEFSCR_SOVH 0x80000000
+#define __SPEFSCR_OVH 0x40000000
+#define __SPEFSCR_FGH 0x20000000
+#define __SPEFSCR_FXH 0x10000000
+#define __SPEFSCR_FINVH 0x08000000
+#define __SPEFSCR_FDBZH 0x04000000
+#define __SPEFSCR_FUNFH 0x02000000
+#define __SPEFSCR_FOVFH 0x01000000
+/* 2 unused bits. */
+#define __SPEFSCR_FINXS 0x00200000
+#define __SPEFSCR_FINVS 0x00100000
+#define __SPEFSCR_FDBZS 0x00080000
+#define __SPEFSCR_FUNFS 0x00040000
+#define __SPEFSCR_FOVFS 0x00020000
+#define __SPEFSCR_MODE 0x00010000
+#define __SPEFSCR_SOV 0x00008000
+#define __SPEFSCR_OV 0x00004000
+#define __SPEFSCR_FG 0x00002000
+#define __SPEFSCR_FX 0x00001000
+#define __SPEFSCR_FINV 0x00000800
+#define __SPEFSCR_FDBZ 0x00000400
+#define __SPEFSCR_FUNF 0x00000200
+#define __SPEFSCR_FOVF 0x00000100
+/* 1 unused bit. */
+#define __SPEFSCR_FINXE 0x00000040
+#define __SPEFSCR_FINVE 0x00000020
+#define __SPEFSCR_FDBZE 0x00000010
+#define __SPEFSCR_FUNFE 0x00000008
+#define __SPEFSCR_FOVFE 0x00000004
+#define __SPEFSCR_FRMC 0x00000003
+
+#define __ev_get_spefscr_sovh() (__builtin_spe_mfspefscr () & __SPEFSCR_SOVH)
+#define __ev_get_spefscr_ovh() (__builtin_spe_mfspefscr () & __SPEFSCR_OVH)
+#define __ev_get_spefscr_fgh() (__builtin_spe_mfspefscr () & __SPEFSCR_FGH)
+#define __ev_get_spefscr_fxh() (__builtin_spe_mfspefscr () & __SPEFSCR_FXH)
+#define __ev_get_spefscr_finvh() (__builtin_spe_mfspefscr () & __SPEFSCR_FINVH)
+#define __ev_get_spefscr_fdbzh() (__builtin_spe_mfspefscr () & __SPEFSCR_FDBZH)
+#define __ev_get_spefscr_funfh() (__builtin_spe_mfspefscr () & __SPEFSCR_FUNFH)
+#define __ev_get_spefscr_fovfh() (__builtin_spe_mfspefscr () & __SPEFSCR_FOVFH)
+#define __ev_get_spefscr_finxs() (__builtin_spe_mfspefscr () & __SPEFSCR_FINXS)
+#define __ev_get_spefscr_finvs() (__builtin_spe_mfspefscr () & __SPEFSCR_FINVS)
+#define __ev_get_spefscr_fdbzs() (__builtin_spe_mfspefscr () & __SPEFSCR_FDBZS)
+#define __ev_get_spefscr_funfs() (__builtin_spe_mfspefscr () & __SPEFSCR_FUNFS)
+#define __ev_get_spefscr_fovfs() (__builtin_spe_mfspefscr () & __SPEFSCR_FOVFS)
+#define __ev_get_spefscr_mode() (__builtin_spe_mfspefscr () & __SPEFSCR_MODE)
+#define __ev_get_spefscr_sov() (__builtin_spe_mfspefscr () & __SPEFSCR_SOV)
+#define __ev_get_spefscr_ov() (__builtin_spe_mfspefscr () & __SPEFSCR_OV)
+#define __ev_get_spefscr_fg() (__builtin_spe_mfspefscr () & __SPEFSCR_FG)
+#define __ev_get_spefscr_fx() (__builtin_spe_mfspefscr () & __SPEFSCR_FX)
+#define __ev_get_spefscr_finv() (__builtin_spe_mfspefscr () & __SPEFSCR_FINV)
+#define __ev_get_spefscr_fdbz() (__builtin_spe_mfspefscr () & __SPEFSCR_FDBZ)
+#define __ev_get_spefscr_funf() (__builtin_spe_mfspefscr () & __SPEFSCR_FUNF)
+#define __ev_get_spefscr_fovf() (__builtin_spe_mfspefscr () & __SPEFSCR_FOVF)
+#define __ev_get_spefscr_finxe() (__builtin_spe_mfspefscr () & __SPEFSCR_FINXE)
+#define __ev_get_spefscr_finve() (__builtin_spe_mfspefscr () & __SPEFSCR_FINVE)
+#define __ev_get_spefscr_fdbze() (__builtin_spe_mfspefscr () & __SPEFSCR_FDBZE)
+#define __ev_get_spefscr_funfe() (__builtin_spe_mfspefscr () & __SPEFSCR_FUNFE)
+#define __ev_get_spefscr_fovfe() (__builtin_spe_mfspefscr () & __SPEFSCR_FOVFE)
+#define __ev_get_spefscr_frmc() (__builtin_spe_mfspefscr () & __SPEFSCR_FRMC)
+
+static inline void
+__ev_clr_spefscr_field (int mask)
+{
+ int i;
+
+ i = __builtin_spe_mfspefscr ();
+ i &= ~mask;
+ __builtin_spe_mtspefscr (i);
+}
+
+#define __ev_clr_spefscr_sovh() __ev_clr_spefscr_field (__SPEFSCR_SOVH)
+#define __ev_clr_spefscr_sov() __ev_clr_spefscr_field (__SPEFSCR_SOV)
+#define __ev_clr_spefscr_finxs() __ev_clr_spefscr_field (__SPEFSCR_FINXS)
+#define __ev_clr_spefscr_finvs() __ev_clr_spefscr_field (__SPEFSCR_FINVS)
+#define __ev_clr_spefscr_fdbzs() __ev_clr_spefscr_field (__SPEFSCR_FDBZS)
+#define __ev_clr_spefscr_funfs() __ev_clr_spefscr_field (__SPEFSCR_FUNFS)
+#define __ev_clr_spefscr_fovfs() __ev_clr_spefscr_field (__SPEFSCR_FOVFS)
+
+/* Set rounding mode:
+ rnd = 0 (nearest)
+ rnd = 1 (zero)
+ rnd = 2 (+inf)
+ rnd = 3 (-inf). */
+
+static inline void
+__ev_set_spefscr_frmc (int rnd)
+{
+ int i;
+
+ i = __builtin_spe_mfspefscr ();
+ i &= ~__SPEFSCR_FRMC;
+ i |= rnd;
+}
+
+#endif /* _SPE_H */
diff --git a/contrib/gcc/config/rs6000/spe.md b/contrib/gcc/config/rs6000/spe.md
new file mode 100644
index 0000000..3413858
--- /dev/null
+++ b/contrib/gcc/config/rs6000/spe.md
@@ -0,0 +1,2488 @@
+;; e500 SPE description
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+;; Contributed by Aldy Hernandez (aldy@quesejoda.com)
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+(define_constants
+ [(SPE_ACC_REGNO 111)
+ (SPEFSCR_REGNO 112)])
+
+(define_insn "*negsf2_gpr"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=r")
+ (neg:SF (match_operand:SF 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "efsneg %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "*abssf2_gpr"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=r")
+ (abs:SF (match_operand:SF 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "efsabs %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "*addsf3_gpr"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=r")
+ (plus:SF (match_operand:SF 1 "gpc_reg_operand" "%r")
+ (match_operand:SF 2 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "efsadd %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+(define_insn "*subsf3_gpr"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=r")
+ (minus:SF (match_operand:SF 1 "gpc_reg_operand" "r")
+ (match_operand:SF 2 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "efssub %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+(define_insn "*mulsf3_gpr"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=r")
+ (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%r")
+ (match_operand:SF 2 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "efsmul %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+(define_insn "*divsf3_gpr"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=r")
+ (div:SF (match_operand:SF 1 "gpc_reg_operand" "r")
+ (match_operand:SF 2 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "efsdiv %0,%1,%2"
+ [(set_attr "type" "fp")])
+
+(define_insn "spe_efsctuiz"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unspec:SI [(match_operand:SF 1 "gpc_reg_operand" "r")] 700))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "efsctuiz %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "spe_fixunssfsi2"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unsigned_fix:SI (fix:SF (match_operand:SF 1 "gpc_reg_operand" "r"))))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "efsctui %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "spe_fix_truncsfsi2"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (fix:SI (match_operand:SF 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "efsctsi %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "spe_floatunssisf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=r")
+ (unsigned_float:SF (match_operand:SI 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "efscfui %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "spe_floatsisf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=r")
+ (float:SF (match_operand:SI 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS"
+ "efscfsi %0,%1"
+ [(set_attr "type" "fp")])
+
+
+;; SPE SIMD instructions
+
+(define_insn "spe_evabs"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (abs:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")))]
+ "TARGET_SPE"
+ "evabs %0,%1"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evandc"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (and:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (not:V2SI (match_operand:V2SI 2 "gpc_reg_operand" "r"))))]
+ "TARGET_SPE"
+ "evandc %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evand"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (and:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")))]
+ "TARGET_SPE"
+ "evand %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+;; Vector compare instructions
+
+(define_insn "spe_evcmpeq"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+ (unspec:CC [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 500))]
+ "TARGET_SPE"
+ "evcmpeq %0,%1,%2"
+ [(set_attr "type" "veccmp")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evcmpgts"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+ (unspec:CC [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 501))]
+ "TARGET_SPE"
+ "evcmpgts %0,%1,%2"
+ [(set_attr "type" "veccmp")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evcmpgtu"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+ (unspec:CC [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 502))]
+ "TARGET_SPE"
+ "evcmpgtu %0,%1,%2"
+ [(set_attr "type" "veccmp")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evcmplts"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+ (unspec:CC [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 503))]
+ "TARGET_SPE"
+ "evcmplts %0,%1,%2"
+ [(set_attr "type" "veccmp")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evcmpltu"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+ (unspec:CC [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 504))]
+ "TARGET_SPE"
+ "evcmpltu %0,%1,%2"
+ [(set_attr "type" "veccmp")
+ (set_attr "length" "4")])
+
+;; Floating point vector compare instructions
+
+(define_insn "spe_evfscmpeq"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+ (unspec:CC [(match_operand:V2SF 1 "gpc_reg_operand" "r")
+ (match_operand:V2SF 2 "gpc_reg_operand" "r")] 538))
+ (clobber (reg:SI SPEFSCR_REGNO))]
+ "TARGET_SPE"
+ "evfscmpeq %0,%1,%2"
+ [(set_attr "type" "veccmp")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfscmpgt"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+ (unspec:CC [(match_operand:V2SF 1 "gpc_reg_operand" "r")
+ (match_operand:V2SF 2 "gpc_reg_operand" "r")] 539))
+ (clobber (reg:SI SPEFSCR_REGNO))]
+ "TARGET_SPE"
+ "evfscmpgt %0,%1,%2"
+ [(set_attr "type" "veccmp")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfscmplt"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+ (unspec:CC [(match_operand:V2SF 1 "gpc_reg_operand" "r")
+ (match_operand:V2SF 2 "gpc_reg_operand" "r")] 540))
+ (clobber (reg:SI SPEFSCR_REGNO))]
+ "TARGET_SPE"
+ "evfscmplt %0,%1,%2"
+ [(set_attr "type" "veccmp")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfststeq"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+ (unspec:CC [(match_operand:V2SF 1 "gpc_reg_operand" "r")
+ (match_operand:V2SF 2 "gpc_reg_operand" "r")] 541))]
+ "TARGET_SPE"
+ "evfststeq %0,%1,%2"
+ [(set_attr "type" "veccmp")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfststgt"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+ (unspec:CC [(match_operand:V2SF 1 "gpc_reg_operand" "r")
+ (match_operand:V2SF 2 "gpc_reg_operand" "r")] 542))]
+ "TARGET_SPE"
+ "evfststgt %0,%1,%2"
+ [(set_attr "type" "veccmp")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfststlt"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+ (unspec:CC [(match_operand:V2SF 1 "gpc_reg_operand" "r")
+ (match_operand:V2SF 2 "gpc_reg_operand" "r")] 543))]
+ "TARGET_SPE"
+ "evfststlt %0,%1,%2"
+ [(set_attr "type" "veccmp")
+ (set_attr "length" "4")])
+
+;; End of vector compare instructions
+
+(define_insn "spe_evcntlsw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")] 505))]
+ "TARGET_SPE"
+ "evcntlsw %0,%1"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evcntlzw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")] 506))]
+ "TARGET_SPE"
+ "evcntlzw %0,%1"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_eveqv"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (not:V2SI (xor:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))))]
+ "TARGET_SPE"
+ "eveqv %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evextsb"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")] 507))]
+ "TARGET_SPE"
+ "evextsb %0,%1"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evextsh"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")] 508))]
+ "TARGET_SPE"
+ "evextsh %0,%1"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlhhesplat"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:QI 2 "immediate_operand" "i"))))
+ (unspec [(const_int 0)] 509)]
+ "TARGET_SPE"
+ "evlhhesplat %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlhhesplatx"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:SI 2 "gpc_reg_operand" "r"))))
+ (unspec [(const_int 0)] 510)]
+ "TARGET_SPE"
+ "evlhhesplatx %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlhhossplat"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:QI 2 "immediate_operand" "i"))))
+ (unspec [(const_int 0)] 511)]
+ "TARGET_SPE"
+ "evlhhossplat %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlhhossplatx"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:SI 2 "gpc_reg_operand" "r"))))
+ (unspec [(const_int 0)] 512)]
+ "TARGET_SPE"
+ "evlhhossplatx %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlhhousplat"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:QI 2 "immediate_operand" "i"))))
+ (unspec [(const_int 0)] 513)]
+ "TARGET_SPE"
+ "evlhhousplat %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlhhousplatx"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:SI 2 "gpc_reg_operand" "r"))))
+ (unspec [(const_int 0)] 514)]
+ "TARGET_SPE"
+ "evlhhousplatx %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlwhsplat"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:QI 2 "immediate_operand" "i"))))
+ (unspec [(const_int 0)] 515)]
+ "TARGET_SPE"
+ "evlwhsplat %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlwhsplatx"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:SI 2 "gpc_reg_operand" "r"))))
+ (unspec [(const_int 0)] 516)]
+ "TARGET_SPE"
+ "evlwhsplatx %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlwwsplat"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:QI 2 "immediate_operand" "i"))))
+ (unspec [(const_int 0)] 517)]
+ "TARGET_SPE"
+ "evlwwsplat %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlwwsplatx"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:SI 2 "gpc_reg_operand" "r"))))
+ (unspec [(const_int 0)] 518)]
+ "TARGET_SPE"
+ "evlwwsplatx %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmergehi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (vec_merge:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (vec_select:V2SI
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (parallel [(const_int 1)
+ (const_int 0)]))
+ (const_int 2)))]
+ "TARGET_SPE"
+ "evmergehi %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmergehilo"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (vec_merge:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (const_int 2)))]
+ "TARGET_SPE"
+ "evmergehilo %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmergelo"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (vec_merge:V2SI (vec_select:V2SI
+ (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (parallel [(const_int 1)
+ (const_int 0)]))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (const_int 2)))]
+ "TARGET_SPE"
+ "evmergelo %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmergelohi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (vec_merge:V2SI (vec_select:V2SI
+ (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (parallel [(const_int 1)
+ (const_int 0)]))
+ (vec_select:V2SI
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (parallel [(const_int 1)
+ (const_int 0)]))
+ (const_int 2)))]
+ "TARGET_SPE"
+ "evmergelohi %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evnand"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (not:V2SI (and:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))))]
+ "TARGET_SPE"
+ "evnand %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evneg"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (neg:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")))]
+ "TARGET_SPE"
+ "evneg %0,%1"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evnor"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (not:V2SI (ior:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))))]
+ "TARGET_SPE"
+ "evnor %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evorc"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (ior:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (not:V2SI (match_operand:V2SI 2 "gpc_reg_operand" "r"))))]
+ "TARGET_SPE"
+ "evorc %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evor"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (ior:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")))]
+ "TARGET_SPE"
+ "evor %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evrlwi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:QI 2 "immediate_operand" "i")] 519))]
+ "TARGET_SPE"
+ "evrlwi %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evrlw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 520))]
+ "TARGET_SPE"
+ "evrlw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evrndw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")] 521))]
+ "TARGET_SPE"
+ "evrndw %0,%1"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evsel"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (match_operand:CC 3 "cc_reg_operand" "y")] 522))]
+ "TARGET_SPE"
+ "evsel %0,%1,%2,%3"
+ [(set_attr "type" "veccmp")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evsel_fs"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
+ (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "r")
+ (match_operand:V2SF 2 "gpc_reg_operand" "r")
+ (match_operand:CC 3 "cc_reg_operand" "y")] 725))]
+ "TARGET_SPE"
+ "evsel %0,%1,%2,%3"
+ [(set_attr "type" "veccmp")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evslwi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:QI 2 "immediate_operand" "i")]
+ 523))]
+ "TARGET_SPE"
+ "evslwi %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evslw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 524))]
+ "TARGET_SPE"
+ "evslw %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evsrwis"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:QI 2 "immediate_operand" "i")]
+ 525))]
+ "TARGET_SPE"
+ "evsrwis %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evsrwiu"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:QI 2 "immediate_operand" "i")]
+ 526))]
+ "TARGET_SPE"
+ "evsrwiu %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evsrws"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 527))]
+ "TARGET_SPE"
+ "evsrws %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evsrwu"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 528))]
+ "TARGET_SPE"
+ "evsrwu %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evxor"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (xor:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")))]
+ "TARGET_SPE"
+ "evxor %0,%1,%2"
+ [(set_attr "type" "vecsimple")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfsabs"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
+ (abs:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "r")))]
+ "TARGET_SPE"
+ "evfsabs %0,%1"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfsadd"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
+ (plus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "r")
+ (match_operand:V2SF 2 "gpc_reg_operand" "r")))
+ (clobber (reg:SI SPEFSCR_REGNO))]
+ "TARGET_SPE"
+ "evfsadd %0,%1,%2"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfscfsf"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
+ (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "r")] 529))]
+ "TARGET_SPE"
+ "evfscfsf %0,%1"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfscfsi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (fix:V2SI (match_operand:V2SF 1 "gpc_reg_operand" "r")))]
+ "TARGET_SPE"
+ "evfscfsi %0,%1"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfscfuf"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
+ (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "r")] 530))]
+ "TARGET_SPE"
+ "evfscfuf %0,%1"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfscfui"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
+ (unspec:V2SF [(match_operand:V2SI 1 "gpc_reg_operand" "r")] 701))]
+ "TARGET_SPE"
+ "evfscfui %0,%1"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfsctsf"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
+ (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "r")] 531))]
+ "TARGET_SPE"
+ "evfsctsf %0,%1"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfsctsi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SF 1 "gpc_reg_operand" "r")] 532))]
+ "TARGET_SPE"
+ "evfsctsi %0,%1"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfsctsiz"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SF 1 "gpc_reg_operand" "r")] 533))]
+ "TARGET_SPE"
+ "evfsctsiz %0,%1"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfsctuf"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
+ (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "r")] 534))]
+ "TARGET_SPE"
+ "evfsctuf %0,%1"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfsctui"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SF 1 "gpc_reg_operand" "r")] 535))]
+ "TARGET_SPE"
+ "evfsctui %0,%1"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfsctuiz"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SF 1 "gpc_reg_operand" "r")] 536))]
+ "TARGET_SPE"
+ "evfsctuiz %0,%1"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfsdiv"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
+ (div:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "r")
+ (match_operand:V2SF 2 "gpc_reg_operand" "r")))
+ (clobber (reg:SI SPEFSCR_REGNO))]
+ "TARGET_SPE"
+ "evfsdiv %0,%1,%2"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfsmul"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
+ (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "r")
+ (match_operand:V2SF 2 "gpc_reg_operand" "r")))
+ (clobber (reg:SI SPEFSCR_REGNO))]
+ "TARGET_SPE"
+ "evfsmul %0,%1,%2"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfsnabs"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
+ (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "r")] 537))]
+ "TARGET_SPE"
+ "evfsnabs %0,%1"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfsneg"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
+ (neg:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "r")))]
+ "TARGET_SPE"
+ "evfsneg %0,%1"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evfssub"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
+ (minus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "r")
+ (match_operand:V2SF 2 "gpc_reg_operand" "r")))
+ (clobber (reg:SI SPEFSCR_REGNO))]
+ "TARGET_SPE"
+ "evfssub %0,%1,%2"
+ [(set_attr "type" "vecfloat")
+ (set_attr "length" "4")])
+
+;; SPE SIMD load instructions.
+
+;; Only the hardware engineer who designed the SPE inderstands the
+;; plethora of load and store instructions ;-). We have no way of
+;; differentiating between them with RTL so use an unspec of const_int 0
+;; to avoid identical RTL.
+
+(define_insn "spe_evldd"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:QI 2 "immediate_operand" "i"))))
+ (unspec [(const_int 0)] 544)]
+ "TARGET_SPE && INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 31"
+ "evldd %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlddx"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:SI 2 "gpc_reg_operand" "r"))))
+ (unspec [(const_int 0)] 545)]
+ "TARGET_SPE"
+ "evlddx %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evldh"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:QI 2 "immediate_operand" "i"))))
+ (unspec [(const_int 0)] 546)]
+ "TARGET_SPE && INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 31"
+ "evldh %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evldhx"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:SI 2 "gpc_reg_operand" "r"))))
+ (unspec [(const_int 0)] 547)]
+ "TARGET_SPE"
+ "evldhx %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evldw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:QI 2 "immediate_operand" "i"))))
+ (unspec [(const_int 0)] 548)]
+ "TARGET_SPE"
+ "evldw %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evldwx"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:SI 2 "gpc_reg_operand" "r"))))
+ (unspec [(const_int 0)] 549)]
+ "TARGET_SPE"
+ "evldwx %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlwhe"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:QI 2 "immediate_operand" "i"))))
+ (unspec [(const_int 0)] 550)]
+ "TARGET_SPE"
+ "evlwhe %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlwhex"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:SI 2 "gpc_reg_operand" "r"))))
+ (unspec [(const_int 0)] 551)]
+ "TARGET_SPE"
+ "evlwhex %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlwhos"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:QI 2 "immediate_operand" "i"))))
+ (unspec [(const_int 0)] 552)]
+ "TARGET_SPE"
+ "evlwhos %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlwhosx"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:SI 2 "gpc_reg_operand" "r"))))
+ (unspec [(const_int 0)] 553)]
+ "TARGET_SPE"
+ "evlwhosx %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlwhou"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:QI 2 "immediate_operand" "i"))))
+ (unspec [(const_int 0)] 554)]
+ "TARGET_SPE"
+ "evlwhou %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evlwhoux"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (mem:V2SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand:SI 2 "gpc_reg_operand" "r"))))
+ (unspec [(const_int 0)] 555)]
+ "TARGET_SPE"
+ "evlwhoux %0,%1,%2"
+ [(set_attr "type" "vecload")
+ (set_attr "length" "4")])
+
+(define_insn "spe_brinc"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "gpc_reg_operand" "r")] 556))]
+ "TARGET_SPE"
+ "brinc %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhegsmfaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 557))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhegsmfaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhegsmfan"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 558))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhegsmfan %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhegsmiaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 559))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhegsmiaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhegsmian"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 560))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhegsmian %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhegumiaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 561))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhegumiaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhegumian"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 562))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhegumian %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhesmfaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 563))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhesmfaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhesmfanw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 564))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhesmfanw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhesmfa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 565))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhesmfa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhesmf"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 566))]
+ "TARGET_SPE"
+ "evmhesmf %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhesmiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 567))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhesmiaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhesmianw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 568))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhesmianw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhesmia"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 569))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhesmia %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhesmi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 570))]
+ "TARGET_SPE"
+ "evmhesmi %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhessfaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 571))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhessfaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhessfanw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 572))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhessfanw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhessfa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 573))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhessfa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhessf"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 574))
+ (clobber (reg:SI SPEFSCR_REGNO))]
+ "TARGET_SPE"
+ "evmhessf %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhessiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 575))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhessiaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhessianw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 576))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhessianw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmheumiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 577))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmheumiaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmheumianw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 578))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmheumianw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmheumia"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 579))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmheumia %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmheumi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 580))]
+ "TARGET_SPE"
+ "evmheumi %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmheusiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 581))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmheusiaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmheusianw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 582))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmheusianw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhogsmfaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 583))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhogsmfaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhogsmfan"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 584))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhogsmfan %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhogsmiaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 585))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhogsmiaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhogsmian"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 586))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhogsmian %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhogumiaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 587))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhogumiaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhogumian"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 588))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhogumian %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhosmfaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 589))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhosmfaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhosmfanw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 590))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhosmfanw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhosmfa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 591))]
+ "TARGET_SPE"
+ "evmhosmfa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhosmf"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 592))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhosmf %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhosmiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 593))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhosmiaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhosmianw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 594))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhosmianw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhosmia"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 595))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhosmia %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhosmi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 596))]
+ "TARGET_SPE"
+ "evmhosmi %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhossfaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 597))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhossfaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhossfanw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 598))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhossfanw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhossfa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 599))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhossfa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhossf"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 600))
+ (clobber (reg:SI SPEFSCR_REGNO))]
+ "TARGET_SPE"
+ "evmhossf %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhossiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 601))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhossiaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhossianw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 602))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhossianw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhoumiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 603))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhoumiaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhoumianw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 604))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhoumianw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhoumia"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 605))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhoumia %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhoumi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 606))]
+ "TARGET_SPE"
+ "evmhoumi %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhousiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 607))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhousiaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmhousianw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 608))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmhousianw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmmlssfa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 609))]
+ "TARGET_SPE"
+ "evmmlssfa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmmlssf"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 610))]
+ "TARGET_SPE"
+ "evmmlssf %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhsmfa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 611))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhsmfa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhsmf"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 612))]
+ "TARGET_SPE"
+ "evmwhsmf %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhsmia"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 613))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhsmia %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhsmi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 614))]
+ "TARGET_SPE"
+ "evmwhsmi %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhssfa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 615))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhssfa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhusian"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 626))]
+ "TARGET_SPE"
+ "evmwhusian %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhssf"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 628))
+ (clobber (reg:SI SPEFSCR_REGNO))]
+ "TARGET_SPE"
+ "evmwhssf %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhumia"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 629))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhumia %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhumi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 630))]
+ "TARGET_SPE"
+ "evmwhumi %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwlsmiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 635))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwlsmiaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwlsmianw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 636))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwlsmianw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwlssiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 641))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwlssiaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwlssianw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 642))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwlssianw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwlumiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 643))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwlumiaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwlumianw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 644))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwlumianw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwlumia"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 645))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwlumia %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwlumi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 646))]
+ "TARGET_SPE"
+ "evmwlumi %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwlusiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 647))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwlusiaaw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwlusianw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 648))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwlusianw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwsmfaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 649))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwsmfaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwsmfan"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 650))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwsmfan %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwsmfa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 651))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwsmfa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwsmf"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 652))]
+ "TARGET_SPE"
+ "evmwsmf %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwsmiaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 653))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwsmiaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwsmian"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 654))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwsmian %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwsmia"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 655))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwsmia %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwsmi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 656))]
+ "TARGET_SPE"
+ "evmwsmi %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwssfaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 657))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwssfaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwssfan"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 658))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwssfan %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwssfa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 659))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwssfa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwssf"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 660))
+ (clobber (reg:SI SPEFSCR_REGNO))]
+ "TARGET_SPE"
+ "evmwssf %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwumiaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 661))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwumiaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwumian"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 662))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwumian %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwumia"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 663))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwumia %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwumi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 664))]
+ "TARGET_SPE"
+ "evmwumi %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evaddw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (plus:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")))]
+ "TARGET_SPE"
+ "evaddw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evaddusiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 673))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evaddusiaaw %0,%1"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evaddumiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 674))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evaddumiaaw %0,%1"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evaddssiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 675))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evaddssiaaw %0,%1"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evaddsmiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 676))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evaddsmiaaw %0,%1"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evaddiw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:QI 2 "immediate_operand" "i")] 677))]
+ "TARGET_SPE"
+ "evaddiw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evsubifw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:QI 2 "immediate_operand" "i")] 678))]
+ "TARGET_SPE"
+ "evsubifw %0,%2,%1"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evsubfw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (minus:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")))]
+ "TARGET_SPE"
+ "evsubfw %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evsubfusiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 679))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evsubfusiaaw %0,%1"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evsubfumiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 680))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evsubfumiaaw %0,%1"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evsubfssiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 681))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evsubfssiaaw %0,%1"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evsubfsmiaaw"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (reg:V2SI SPE_ACC_REGNO)] 682))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evsubfsmiaaw %0,%1"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmra"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (match_operand:V2SI 1 "gpc_reg_operand" "r"))
+ (set (reg:V2SI SPE_ACC_REGNO)
+ (unspec:V2SI [(match_dup 1)] 726))]
+ "TARGET_SPE"
+ "evmra %0,%1"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evdivws"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (div:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")))
+ (clobber (reg:SI SPEFSCR_REGNO))]
+ "TARGET_SPE"
+ "evdivws %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evdivwu"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (udiv:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")))
+ (clobber (reg:SI SPEFSCR_REGNO))]
+ "TARGET_SPE"
+ "evdivwu %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evsplatfi"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:QI 1 "immediate_operand" "i")] 684))]
+ "TARGET_SPE"
+ "evsplatfi %0,%1"
+ [(set_attr "type" "vecperm")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evsplati"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:QI 1 "immediate_operand" "i")] 685))]
+ "TARGET_SPE"
+ "evsplati %0,%1"
+ [(set_attr "type" "vecperm")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evstdd"
+ [(set (mem:V2SI (plus:SI (match_operand:SI 0 "gpc_reg_operand" "b")
+ (match_operand:QI 1 "immediate_operand" "i")))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (unspec [(const_int 0)] 686)]
+ "TARGET_SPE"
+ "evstdd %2,%0,%1"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evstddx"
+ [(set (mem:V2SI (plus:SI (match_operand:SI 0 "gpc_reg_operand" "b")
+ (match_operand:SI 1 "gpc_reg_operand" "r")))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (unspec [(const_int 0)] 687)]
+ "TARGET_SPE"
+ "evstddx %2,%0,%1"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evstdh"
+ [(set (mem:V2SI (plus:SI (match_operand:SI 0 "gpc_reg_operand" "b")
+ (match_operand:QI 1 "immediate_operand" "i")))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (unspec [(const_int 0)] 688)]
+ "TARGET_SPE"
+ "evstdh %2,%0,%1"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evstdhx"
+ [(set (mem:V2SI (plus:SI (match_operand:SI 0 "gpc_reg_operand" "b")
+ (match_operand:SI 1 "gpc_reg_operand" "r")))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (unspec [(const_int 0)] 689)]
+ "TARGET_SPE"
+ "evstdhx %2,%0,%1"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evstdw"
+ [(set (mem:V2SI (plus:SI (match_operand:SI 0 "gpc_reg_operand" "b")
+ (match_operand:QI 1 "immediate_operand" "i")))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (unspec [(const_int 0)] 690)]
+ "TARGET_SPE"
+ "evstdw %2,%0,%1"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evstdwx"
+ [(set (mem:V2SI (plus:SI (match_operand:SI 0 "gpc_reg_operand" "b")
+ (match_operand:SI 1 "gpc_reg_operand" "r")))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (unspec [(const_int 0)] 691)]
+ "TARGET_SPE"
+ "evstdwx %2,%0,%1"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evstwhe"
+ [(set (mem:V2SI (plus:SI (match_operand:SI 0 "gpc_reg_operand" "b")
+ (match_operand:QI 1 "immediate_operand" "i")))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (unspec [(const_int 0)] 692)]
+ "TARGET_SPE"
+ "evstwhe %2,%0,%1"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evstwhex"
+ [(set (mem:V2SI (plus:SI (match_operand:SI 0 "gpc_reg_operand" "b")
+ (match_operand:SI 1 "gpc_reg_operand" "r")))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (unspec [(const_int 0)] 693)]
+ "TARGET_SPE"
+ "evstwhex %2,%0,%1"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evstwho"
+ [(set (mem:V2SI (plus:SI (match_operand:SI 0 "gpc_reg_operand" "b")
+ (match_operand:QI 1 "immediate_operand" "i")))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (unspec [(const_int 0)] 694)]
+ "TARGET_SPE"
+ "evstwho %2,%0,%1"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evstwhox"
+ [(set (mem:V2SI (plus:SI (match_operand:SI 0 "gpc_reg_operand" "b")
+ (match_operand:SI 1 "gpc_reg_operand" "r")))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (unspec [(const_int 0)] 695)]
+ "TARGET_SPE"
+ "evstwhox %2,%0,%1"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evstwwe"
+ [(set (mem:V2SI (plus:SI (match_operand:SI 0 "gpc_reg_operand" "b")
+ (match_operand:QI 1 "immediate_operand" "i")))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (unspec [(const_int 0)] 696)]
+ "TARGET_SPE"
+ "evstwwe %2,%0,%1"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evstwwex"
+ [(set (mem:V2SI (plus:SI (match_operand:SI 0 "gpc_reg_operand" "b")
+ (match_operand:SI 1 "gpc_reg_operand" "r")))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (unspec [(const_int 0)] 697)]
+ "TARGET_SPE"
+ "evstwwex %2,%0,%1"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evstwwo"
+ [(set (mem:V2SI (plus:SI (match_operand:SI 0 "gpc_reg_operand" "b")
+ (match_operand:QI 1 "immediate_operand" "i")))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (unspec [(const_int 0)] 698)]
+ "TARGET_SPE"
+ "evstwwo %2,%0,%1"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evstwwox"
+ [(set (mem:V2SI (plus:SI (match_operand:SI 0 "gpc_reg_operand" "b")
+ (match_operand:SI 1 "gpc_reg_operand" "r")))
+ (match_operand:V2SI 2 "gpc_reg_operand" "r"))
+ (unspec [(const_int 0)] 699)]
+ "TARGET_SPE"
+ "evstwwox %2,%0,%1"
+ [(set_attr "type" "vecstore")
+ (set_attr "length" "4")])
+
+;; SPE vector clears
+
+(define_insn "*movv2si_const0"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (match_operand:V2SI 1 "zero_constant" ""))]
+ "TARGET_SPE"
+ "evxor %0,%0,%0"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*movv2sf_const0"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=r")
+ (match_operand:V2SF 1 "zero_constant" ""))]
+ "TARGET_SPE"
+ "evxor %0,%0,%0"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*movv4hi_const0"
+ [(set (match_operand:V4HI 0 "gpc_reg_operand" "=r")
+ (match_operand:V4HI 1 "zero_constant" ""))]
+ "TARGET_SPE"
+ "evxor %0,%0,%0"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*movv1di_const0"
+ [(set (match_operand:V1DI 0 "gpc_reg_operand" "=r")
+ (match_operand:V1DI 1 "zero_constant" ""))]
+ "TARGET_SPE"
+ "evxor %0,%0,%0"
+ [(set_attr "type" "vecsimple")])
+
+;; Vector move instructions.
+
+(define_expand "movv2si"
+ [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
+ (match_operand:V2SI 1 "any_operand" ""))]
+ "TARGET_SPE"
+ "{ rs6000_emit_move (operands[0], operands[1], V2SImode); DONE; }")
+
+
+(define_insn "*movv2si_internal"
+ [(set (match_operand:V2SI 0 "nonimmediate_operand" "=m,r,r")
+ (match_operand:V2SI 1 "input_operand" "r,m,r"))]
+ "TARGET_SPE"
+ "@
+ evstdd%X0 %1,%y0
+ evldd%X1 %0,%y1
+ evor %0,%1,%1"
+ [(set_attr "type" "vecload")])
+
+(define_expand "movv1di"
+ [(set (match_operand:V1DI 0 "nonimmediate_operand" "")
+ (match_operand:V1DI 1 "any_operand" ""))]
+ "TARGET_SPE"
+ "{ rs6000_emit_move (operands[0], operands[1], V1DImode); DONE; }")
+
+(define_insn "*movv1di_internal"
+ [(set (match_operand:V1DI 0 "nonimmediate_operand" "=m,r,r")
+ (match_operand:V1DI 1 "input_operand" "r,m,r"))]
+ "TARGET_SPE"
+ "@
+ evstdd%X0 %1,%y0
+ evldd%X1 %0,%y1
+ evor %0,%1,%1"
+ [(set_attr "type" "vecload")])
+
+(define_expand "movv4hi"
+ [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
+ (match_operand:V4HI 1 "any_operand" ""))]
+ "TARGET_SPE"
+ "{ rs6000_emit_move (operands[0], operands[1], V4HImode); DONE; }")
+
+(define_insn "*movv4hi_internal"
+ [(set (match_operand:V4HI 0 "nonimmediate_operand" "=m,r,r")
+ (match_operand:V4HI 1 "input_operand" "r,m,r"))]
+ "TARGET_SPE"
+ "@
+ evstdd%X0 %1,%y0
+ evldd%X1 %0,%y1
+ evor %0,%1,%1"
+ [(set_attr "type" "vecload")])
+
+(define_expand "movv2sf"
+ [(set (match_operand:V2SF 0 "nonimmediate_operand" "")
+ (match_operand:V2SF 1 "any_operand" ""))]
+ "TARGET_SPE"
+ "{ rs6000_emit_move (operands[0], operands[1], V2SFmode); DONE; }")
+
+(define_insn "*movv2sf_internal"
+ [(set (match_operand:V2SF 0 "nonimmediate_operand" "=m,r,r")
+ (match_operand:V2SF 1 "input_operand" "r,m,r"))]
+ "TARGET_SPE"
+ "@
+ evstdd%X0 %1,%y0
+ evldd%X1 %0,%y1
+ evor %0,%1,%1"
+ [(set_attr "type" "vecload")])
+
+(define_insn "spe_evmwhssfaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 702))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhssfaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhssmaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 703))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhssmaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhsmfaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 704))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhsmfaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhsmiaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 705))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhsmiaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhusiaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 706))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhusiaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhumiaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 707))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhumiaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhssfan"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 708))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhssfan %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhssian"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 709))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhssian %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhsmfan"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 710))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhsmfan %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhsmian"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 711))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhsmian %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhumian"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 713))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhumian %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhgssfaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 714))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhgssfaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhgsmfaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 715))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhgsmfaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhgsmiaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 716))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhgsmiaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhgumiaa"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 717))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhgumiaa %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhgssfan"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 718))
+ (clobber (reg:SI SPEFSCR_REGNO))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhgssfan %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhgsmfan"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 719))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhgsmfan %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhgsmian"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 720))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhgsmian %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_evmwhgumian"
+ [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
+ (unspec:V2SI [(match_operand:V2SI 1 "gpc_reg_operand" "r")
+ (match_operand:V2SI 2 "gpc_reg_operand" "r")] 721))
+ (clobber (reg:V2SI SPE_ACC_REGNO))]
+ "TARGET_SPE"
+ "evmwhgumian %0,%1,%2"
+ [(set_attr "type" "veccomplex")
+ (set_attr "length" "4")])
+
+(define_insn "spe_mtspefscr"
+ [(set (reg:SI SPEFSCR_REGNO)
+ (unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
+ 722))]
+ "TARGET_SPE"
+ "mtspefscr %0"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "spe_mfspefscr"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(reg:SI SPEFSCR_REGNO)] 723))]
+ "TARGET_SPE"
+ "mfspefscr %0"
+ [(set_attr "type" "vecsimple")])
+
+;; MPC8540 single-precision FP instructions on GPRs.
+;; We have 2 variants for each. One for IEEE compliant math and one
+;; for non IEEE compliant math.
+
+(define_insn "cmpsfeq_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (eq:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+ (match_operand:SF 2 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations"
+ "efscmpeq %0,%1,%2"
+ [(set_attr "type" "fpcompare")])
+
+(define_insn "tstsfeq_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (eq:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+ (match_operand:SF 2 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations"
+ "efststeq %0,%1,%2"
+ [(set_attr "type" "fpcompare")])
+
+(define_insn "cmpsfgt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (gt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+ (match_operand:SF 2 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations"
+ "efscmpgt %0,%1,%2"
+ [(set_attr "type" "fpcompare")])
+
+(define_insn "tstsfgt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (gt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+ (match_operand:SF 2 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations"
+ "efststgt %0,%1,%2"
+ [(set_attr "type" "fpcompare")])
+
+(define_insn "cmpsflt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (lt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+ (match_operand:SF 2 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations"
+ "efscmplt %0,%1,%2"
+ [(set_attr "type" "fpcompare")])
+
+(define_insn "tstsflt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (lt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+ (match_operand:SF 2 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations"
+ "efststlt %0,%1,%2"
+ [(set_attr "type" "fpcompare")])
+
diff --git a/contrib/gcc/config/rs6000/sysv4.h b/contrib/gcc/config/rs6000/sysv4.h
index ecc37ee..3da996f 100644
--- a/contrib/gcc/config/rs6000/sysv4.h
+++ b/contrib/gcc/config/rs6000/sysv4.h
@@ -1,5 +1,5 @@
/* Target definitions for GNU compiler for PowerPC running System V.4
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003
+ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
Contributed by Cygnus Support.
@@ -21,6 +21,9 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+/* Header files should be C++ aware in general. */
+#define NO_IMPLICIT_EXTERN_C
+
/* Yes! We are ELF. */
#define TARGET_OBJECT_FORMAT OBJECT_ELF
@@ -34,10 +37,6 @@ Boston, MA 02111-1307, USA. */
#undef ASM_DEFAULT_SPEC
#define ASM_DEFAULT_SPEC "-mppc"
-/* Override rs6000.h definition. */
-#undef CPP_DEFAULT_SPEC
-#define CPP_DEFAULT_SPEC "-D_ARCH_PPC"
-
/* Small data support types. */
enum rs6000_sdata_type {
SDATA_NONE, /* No small data support. */
@@ -152,6 +151,7 @@ extern int g_switch_set; /* Whether -G xx was passed. */
{ "emb", 0, \
N_("Set the PPC_EMB bit in the ELF flags header") }, \
{ "vxworks", 0, N_("no description yet") }, \
+ { "windiss", 0, N_("Use the WindISS simulator") }, \
{ "shlib", 0, N_("no description yet") }, \
EXTRA_SUBTARGET_SWITCHES \
{ "newlib", 0, N_("no description yet") },
@@ -257,13 +257,16 @@ do { \
rs6000_sdata_name); \
} \
\
- if (rs6000_sdata != SDATA_NONE && DEFAULT_ABI != ABI_V4) \
+ if ((rs6000_sdata != SDATA_NONE && DEFAULT_ABI != ABI_V4) \
+ || (rs6000_sdata == SDATA_EABI && !TARGET_EABI)) \
{ \
rs6000_sdata = SDATA_NONE; \
error ("-msdata=%s and -mcall-%s are incompatible", \
rs6000_sdata_name, rs6000_abi_name); \
} \
\
+ targetm.have_srodata_section = rs6000_sdata == SDATA_EABI; \
+ \
if (TARGET_RELOCATABLE && !TARGET_MINIMAL_TOC) \
{ \
target_flags |= MASK_MINIMAL_TOC; \
@@ -326,7 +329,7 @@ do { \
/* Define this to set the endianness to use in libgcc2.c, which can
not depend on target_flags. */
-#if !defined(_LITTLE_ENDIAN) && !defined(__sun__)
+#if !defined(__LITTLE_ENDIAN__) && !defined(__sun__)
#define LIBGCC2_WORDS_BIG_ENDIAN 1
#else
#define LIBGCC2_WORDS_BIG_ENDIAN 0
@@ -383,10 +386,6 @@ do { \
/* Real stack boundary as mandated by the appropriate ABI. */
#define ABI_STACK_BOUNDARY ((TARGET_EABI && !TARGET_ALTIVEC_ABI) ? 64 : 128)
-/* No data type wants to be aligned rounder than this. */
-#undef BIGGEST_ALIGNMENT
-#define BIGGEST_ALIGNMENT ((TARGET_EABI && !TARGET_ALTIVEC) ? 64 : 128)
-
/* An expression for the alignment of a structure field FIELD if the
alignment computed in the usual way is COMPUTED. */
#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
@@ -433,12 +432,11 @@ do { \
/* Besides the usual ELF sections, we need a toc section. */
/* Override elfos.h definition. */
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const, in_toc, in_sdata, in_sdata2, in_sbss, in_init, in_fini
+#define EXTRA_SECTIONS in_toc, in_sdata, in_sdata2, in_sbss, in_init, in_fini
/* Override elfos.h definition. */
#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
- CONST_SECTION_FUNCTION \
TOC_SECTION_FUNCTION \
SDATA_SECTION_FUNCTION \
SDATA2_SECTION_FUNCTION \
@@ -550,41 +548,14 @@ fini_section () \
} \
}
-/* 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. */
-
-/* Override elfos.h definition. */
-#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE, X, ALIGN) 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. */
-
-/* Override elfos.h definition. */
-#undef SELECT_SECTION
-#define SELECT_SECTION(DECL, RELOC, ALIGN) rs6000_select_section (DECL, RELOC)
+/* Override default elf definitions. */
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION rs6000_elf_select_rtx_section
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION rs6000_elf_select_section
+#define TARGET_ASM_UNIQUE_SECTION rs6000_elf_unique_section
-/* A C statement to build up a unique section name, expressed as a
- STRING_CST node, and assign it to DECL_SECTION_NAME (decl).
- RELOC indicates whether the initial value of EXP requires
- link-time relocations. If you do not define this macro, GCC will use
- the symbol name prefixed by `.' as the section name. Note - this
- macro can now be called for uninitialized data items as well as
- initialised data and functions. */
-
-/* Override elfos.h definition. */
-#undef UNIQUE_SECTION
-#define UNIQUE_SECTION(DECL, RELOC) rs6000_unique_section (DECL, RELOC)
-
-/* Return non-zero if this entry is to be written into the constant pool
+/* Return nonzero 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
@@ -644,18 +615,14 @@ extern int rs6000_pic_labelno;
putc ('\n', FILE); \
} \
\
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
- putc ('\n', FILE); \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
\
if (DEFAULT_ABI == ABI_AIX) \
{ \
const char *desc_name, *orig_name; \
\
- STRIP_NAME_ENCODING (orig_name, NAME); \
+ orig_name = (*targetm.strip_name_encoding) (NAME); \
desc_name = orig_name; \
while (*desc_name == '.') \
desc_name++; \
@@ -674,39 +641,6 @@ extern int rs6000_pic_labelno;
ASM_OUTPUT_LABEL (FILE, NAME); \
} while (0)
-/* 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 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 this' pointer in C++. This is the incoming
- argument *before* the function prologue, e.g. %o0' on a sparc. The
- addition must preserve the values of all other incoming arguments.
-
- After the addition, emit code to jump to FUNCTION, which is a
- FUNCTION_DECL'. This is a direct pure jump, not a call, and does not touch
- the return address. Hence returning from FUNCTION will return to whoever
- called the current thunk'.
-
- The effect must be as if FUNCTION had been called directly with the adjusted
- first argument. This macro is responsible for emitting all of the code for
- a thunk function; FUNCTION_PROLOGUE' and FUNCTION_EPILOGUE' are not
- invoked.
-
- The THUNK_FNDECL is redundant. (DELTA and 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
- FUNCTION instead of jumping to it. The generic approach does not support
- varargs. */
-
-#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
- output_mi_thunk (FILE, THUNK_FNDECL, DELTA, FUNCTION)
-
/* The USER_LABEL_PREFIX stuff is affected by the -fleading-underscore
flag. The LOCAL_LABEL_PREFIX variable is used by dbxelf.h. */
@@ -718,15 +652,8 @@ extern int rs6000_pic_labelno;
#define ASM_OUTPUT_INTERNAL_LABEL_PREFIX(FILE,PREFIX) \
asm_fprintf (FILE, "%L%s", PREFIX)
-#define ASM_OUTPUT_LABEL(FILE,NAME) \
- (assemble_name (FILE, NAME), fputs (":\n", FILE))
-
-/* This is how to output a command to make the user-level label named NAME
- defined for reference from other files. */
-
-#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
- do { fputs ("\t.globl ", FILE); \
- assemble_name (FILE, NAME); putc ('\n', FILE);} while (0)
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.globl "
/* This says how to output assembler code to declare an
uninitialized internal linkage data object. Under SVR4,
@@ -749,11 +676,7 @@ do { \
ASM_OUTPUT_LABEL (FILE, NAME); \
ASM_OUTPUT_SKIP (FILE, SIZE); \
if (!flag_inhibit_size_directive && (SIZE) > 0) \
- { \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, NAME); \
- fprintf (FILE, ",%d\n", SIZE); \
- } \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE); \
} \
else \
{ \
@@ -761,12 +684,12 @@ do { \
assemble_name ((FILE), (NAME)); \
fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \
} \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
} 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)
@@ -781,9 +704,7 @@ do { \
do { \
if (DEFAULT_ABI == ABI_V4) \
asm_fprintf (FILE, \
- (TARGET_32BIT \
- ? "\t{stu|stwu} %s,-16(%s)\n\t{st|stw} %s,12(%s)\n" \
- : "\tstdu %s,-32(%s)\n\tstd %s,24(%s)\n"), \
+ "\t{stu|stwu} %s,-16(%s)\n\t{st|stw} %s,12(%s)\n", \
reg_names[1], reg_names[1], reg_names[REGNO], \
reg_names[1]); \
} while (0)
@@ -795,9 +716,7 @@ do { \
do { \
if (DEFAULT_ABI == ABI_V4) \
asm_fprintf (FILE, \
- (TARGET_32BIT \
- ? "\t{l|lwz} %s,12(%s)\n\t{ai|addic} %s,%s,16\n" \
- : "\tld %s,24(%s)\n\t{ai|addic} %s,%s,32\n"), \
+ "\t{l|lwz} %s,12(%s)\n\t{ai|addic} %s,%s,16\n", \
reg_names[REGNO], reg_names[1], reg_names[1], \
reg_names[1]); \
} while (0)
@@ -832,39 +751,22 @@ extern int fixuplabelno;
/* This is the end of what might become sysv4.h. */
/* Use DWARF 2 debugging information by default. */
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
/* Historically we have also supported stabs debugging. */
-#define DBX_DEBUGGING_INFO
-
-/* 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 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 read the prefixes. */
+#define DBX_DEBUGGING_INFO 1
-#undef ENCODE_SECTION_INFO
-#define ENCODE_SECTION_INFO(DECL) rs6000_encode_section_info (DECL)
+#define TARGET_ENCODE_SECTION_INFO rs6000_elf_encode_section_info
+#define TARGET_STRIP_NAME_ENCODING rs6000_elf_strip_name_encoding
+#define TARGET_IN_SMALL_DATA_P rs6000_elf_in_small_data_p
+#define TARGET_SECTION_TYPE_FLAGS rs6000_elf_section_type_flags
/* The ELF version doesn't encode [DS] or whatever at the end of symbols. */
#define RS6000_OUTPUT_BASENAME(FILE, NAME) \
assemble_name (FILE, NAME)
-/* This macro gets just the user-specified name
- out of the string in a SYMBOL_REF. Discard
- a leading * or @. */
-#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
-do { \
- const char *_name = SYMBOL_NAME; \
- while (*_name == '*' || *_name == '@') \
- _name++; \
- (VAR) = _name; \
-} while (0)
-
/* This is how to output a reference to a user-level label named NAME.
`assemble_name' uses this. */
@@ -893,9 +795,19 @@ do { \
#define TARGET_VERSION fprintf (stderr, " (PowerPC System V.4)");
#endif
-#ifndef CPP_PREDEFINES
-#define CPP_PREDEFINES \
- "-DPPC -Dunix -D__svr4__ -Asystem=unix -Asystem=svr4 -Acpu=powerpc -Amachine=powerpc"
+#ifndef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("PPC"); \
+ builtin_define_std ("unix"); \
+ builtin_define ("__svr4__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=svr4"); \
+ builtin_assert ("cpu=powerpc"); \
+ builtin_assert ("machine=powerpc"); \
+ } \
+ while (0)
#endif
/* Pass various options to the assembler. */
@@ -977,12 +889,14 @@ do { \
%{myellowknife: %(link_start_yellowknife) } \
%{mmvme: %(link_start_mvme) } \
%{msim: %(link_start_sim) } \
+%{mwindiss: %(link_start_windiss) } \
%{mcall-freebsd: %(link_start_freebsd) } \
%{mcall-linux: %(link_start_linux) } \
%{mcall-gnu: %(link_start_gnu) } \
%{mcall-netbsd: %(link_start_netbsd) } \
-%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mcall-linux: %{!mcall-gnu: \
- %{!mcall-netbsd: %{!mcall-freebsd: %(link_start_default) }}}}}}}}"
+%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mwindiss: \
+ %{!mcall-linux: %{!mcall-gnu: %{!mcall-netbsd: \
+ %{!mcall-freebsd: %(link_start_default) }}}}}}}}}"
#define LINK_START_DEFAULT_SPEC ""
@@ -1034,75 +948,37 @@ do { \
%{myellowknife: %(link_os_yellowknife) } \
%{mmvme: %(link_os_mvme) } \
%{msim: %(link_os_sim) } \
+%{mwindiss: %(link_os_windiss) } \
%{mcall-freebsd: %(link_os_freebsd) } \
%{mcall-linux: %(link_os_linux) } \
%{mcall-gnu: %(link_os_gnu) } \
%{mcall-netbsd: %(link_os_netbsd) } \
-%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: %{!mcall-netbsd: %(link_os_default) }}}}}}}}"
+%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mwindiss: \
+ %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: \
+ %{!mcall-netbsd: %(link_os_default) }}}}}}}}}"
#define LINK_OS_DEFAULT_SPEC ""
#define CPP_SYSV_SPEC \
"%{mrelocatable*: -D_RELOCATABLE} \
%{fpic: -D__PIC__=1 -D__pic__=1} \
-%{!fpic: %{fPIC: -D__PIC__=2 -D__pic__=2}} \
-%{mlong-double-128: -D__LONG_DOUBLE_128__=1} \
-%{!mlong-double-64: %(cpp_longdouble_default)} \
-%{mcall-sysv: -D_CALL_SYSV} \
-%{mcall-aix: -D_CALL_AIX} %{mcall-aixdesc: -D_CALL_AIX -D_CALL_AIXDESC} \
-%{!mcall-sysv: %{!mcall-aix: %{!mcall-aixdesc: %(cpp_sysv_default) }}} \
-%{msoft-float: -D_SOFT_FLOAT} \
-%{!msoft-float: %{!mhard-float: \
- %{mcpu=401: -D_SOFT_FLOAT} \
- %{mcpu=403: -D_SOFT_FLOAT} \
- %{mcpu=405: -D_SOFT_FLOAT} \
- %{mcpu=ec603e: -D_SOFT_FLOAT} \
- %{mcpu=801: -D_SOFT_FLOAT} \
- %{mcpu=821: -D_SOFT_FLOAT} \
- %{mcpu=823: -D_SOFT_FLOAT} \
- %{mcpu=860: -D_SOFT_FLOAT} \
- %{!mcpu*: %(cpp_float_default) }}}"
-
-/* Whether floating point is disabled by default. */
-#define CPP_FLOAT_DEFAULT_SPEC ""
-
-/* Whether 'long double' is 128 bits by default. */
-#define CPP_LONGDOUBLE_DEFAULT_SPEC ""
-
-#define CPP_SYSV_DEFAULT_SPEC "-D_CALL_SYSV"
-
-#define CPP_ENDIAN_BIG_SPEC "-D_BIG_ENDIAN -D__BIG_ENDIAN__ -Amachine=bigendian"
-
-#define CPP_ENDIAN_LITTLE_SPEC "-D_LITTLE_ENDIAN -D__LITTLE_ENDIAN__ -Amachine=littleendian"
-
-#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-freebsd: %(cpp_endian_big) } \
- %{mcall-linux: %(cpp_endian_big) } \
- %{mcall-gnu: %(cpp_endian_big) } \
- %{mcall-netbsd: %(cpp_endian_big) } \
- %{mcall-i960-old: %(cpp_endian_little) } \
- %{mcall-aixdesc: %(cpp_endian_big) } \
- %{!mcall-linux: %{!mcall-gnu: %{!mcall-freebsd: %{!mcall-netbsd: %{!mcall-aixdesc: %(cpp_endian_default) }}}}}}}}}"
-
-#define CPP_ENDIAN_DEFAULT_SPEC "%(cpp_endian_big)"
+%{!fpic: %{fPIC: -D__PIC__=2 -D__pic__=2}}"
/* Override rs6000.h definition. */
#undef CPP_SPEC
-#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} %(cpp_sysv) %(cpp_endian) %(cpp_cpu) \
+#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} %(cpp_sysv) \
%{mads: %(cpp_os_ads) } \
%{myellowknife: %(cpp_os_yellowknife) } \
%{mmvme: %(cpp_os_mvme) } \
%{msim: %(cpp_os_sim) } \
+%{mwindiss: %(cpp_os_windiss) } \
%{mcall-freebsd: %(cpp_os_freebsd) } \
%{mcall-linux: %(cpp_os_linux) } \
%{mcall-gnu: %(cpp_os_gnu) } \
%{mcall-netbsd: %(cpp_os_netbsd) } \
-%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: %{!mcall-netbsd: %(cpp_os_default) }}}}}}}}"
+%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mwindiss: \
+ %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: \
+ %{!mcall-netbsd: %(cpp_os_default) }}}}}}}}}"
#define CPP_OS_DEFAULT_SPEC ""
@@ -1113,11 +989,14 @@ do { \
%{myellowknife: %(startfile_yellowknife) } \
%{mmvme: %(startfile_mvme) } \
%{msim: %(startfile_sim) } \
+%{mwindiss: %(startfile_windiss) } \
%{mcall-freebsd: %(startfile_freebsd) } \
%{mcall-linux: %(startfile_linux) } \
%{mcall-gnu: %(startfile_gnu) } \
%{mcall-netbsd: %(startfile_netbsd) } \
-%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: %{!mcall-netbsd: %(startfile_default) }}}}}}}}"
+%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mwindiss: \
+ %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: \
+ %{!mcall-netbsd: %(startfile_default) }}}}}}}}}"
#define STARTFILE_DEFAULT_SPEC ""
@@ -1128,27 +1007,36 @@ do { \
%{myellowknife: %(lib_yellowknife) } \
%{mmvme: %(lib_mvme) } \
%{msim: %(lib_sim) } \
+%{mwindiss: %(lib_windiss) } \
%{mcall-freebsd: %(lib_freebsd) } \
%{mcall-linux: %(lib_linux) } \
%{mcall-gnu: %(lib_gnu) } \
%{mcall-netbsd: %(lib_netbsd) } \
-%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: %{!mcall-netbsd: %(lib_default) }}}}}}}}"
+%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mwindiss: \
+ %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: \
+ %{!mcall-netbsd: %(lib_default) }}}}}}}}}"
#define LIB_DEFAULT_SPEC ""
/* Override svr4.h definition. */
#undef ENDFILE_SPEC
-#define ENDFILE_SPEC "crtsavres.o%s \
-%{mads: %(endfile_ads)} \
-%{myellowknife: %(endfile_yellowknife)} \
-%{mmvme: %(endfile_mvme)} \
-%{msim: %(endfile_sim)} \
-%{mcall-freebsd: %(endfile_freebsd) } \
-%{mcall-linux: %(endfile_linux) } \
-%{mcall-gnu: %(endfile_gnu) } \
-%{mcall-netbsd: %(endfile_netbsd) } \
-%{mvxworks: %(endfile_vxworks) } \
-%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: %{!mcall-netbsd: %{!mvxworks: %(endfile_default) }}}}}}}}}"
+#define ENDFILE_SPEC "\
+%{mads: crtsavres.o%s %(endfile_ads)} \
+%{myellowknife: crtsavres.o%s %(endfile_yellowknife)} \
+%{mmvme: crtsavres.o%s %(endfile_mvme)} \
+%{msim: crtsavres.o%s %(endfile_sim)} \
+%{mwindiss: %(endfile_windiss)} \
+%{mcall-freebsd: crtsavres.o%s %(endfile_freebsd) } \
+%{mcall-linux: crtsavres.o%s %(endfile_linux) } \
+%{mcall-gnu: crtsavres.o%s %(endfile_gnu) } \
+%{mcall-netbsd: crtsavres.o%s %(endfile_netbsd) } \
+%{mvxworks: crtsavres.o%s %(endfile_vxworks) } \
+%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mwindiss: \
+ %{!mcall-freebsd: %{!mcall-linux: %{!mcall-gnu: \
+ %{!mcall-netbsd: %{!mvxworks: %(crtsavres_default) \
+ %(endfile_default) }}}}}}}}}}"
+
+#define CRTSAVRES_DEFAULT_SPEC "crtsavres.o%s"
#define ENDFILE_DEFAULT_SPEC ""
@@ -1207,7 +1095,7 @@ do { \
/* FreeBSD support. */
#define CPP_OS_FREEBSD_SPEC "\
- -D__PPC__ -D__ppc__ -D__PowerPC__ -D__powerpc__ \
+ -D__ELF__ -D__PPC__ -D__ppc__ -D__PowerPC__ -D__powerpc__ \
-Acpu=powerpc -Amachine=powerpc"
#define STARTFILE_FREEBSD_SPEC FBSD_STARTFILE_SPEC
@@ -1216,7 +1104,17 @@ do { \
#define LINK_START_FREEBSD_SPEC ""
#define LINK_OS_FREEBSD_SPEC "\
- %{symbolic:-Bsymbolic}"
+ %{p:%e`-p' not supported; use `-pg' and gprof(1)} \
+ %{Wl,*:%*} \
+ %{v:-V} \
+ %{assert*} %{R*} %{rpath*} %{defsym*} \
+ %{shared:-Bshareable %{h*} %{soname*}} \
+ %{!shared: \
+ %{!static: \
+ %{rdynamic: -export-dynamic} \
+ %{!dynamic-linker: -dynamic-linker /usr/libexec/ld-elf.so.1}} \
+ %{static:-Bstatic}} \
+ %{symbolic:-Bsymbolic}"
/* GNU/Linux support. */
#ifdef USE_GNULIBC_1
@@ -1375,14 +1273,31 @@ ncrtn.o%s"
%{mcpu=823: -DCPU=PPC603} \
%{mcpu=860: -DCPU=PPC603}"
+/* WindISS support. */
+
+#define LIB_WINDISS_SPEC "--start-group -li -lcfp -lwindiss -lram -limpl -limpfp --end-group"
+
+#define CPP_OS_WINDISS_SPEC "\
+-D__rtasim \
+-D__EABI__ \
+-D__ppc \
+%{!msoft-float: -D__hardfp} \
+"
+
+#define STARTFILE_WINDISS_SPEC "crt0.o%s crtbegin.o%s"
+
+#define ENDFILE_WINDISS_SPEC "crtend.o%s"
+
+#define LINK_START_WINDISS_SPEC ""
+
+#define LINK_OS_WINDISS_SPEC ""
+
/* Define any extra SPECS that the compiler needs to generate. */
/* Override rs6000.h definition. */
#undef SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS \
{ "cpp_sysv", CPP_SYSV_SPEC }, \
- { "cpp_sysv_default", CPP_SYSV_DEFAULT_SPEC }, \
- { "cpp_endian_default", CPP_ENDIAN_DEFAULT_SPEC }, \
- { "cpp_endian", CPP_ENDIAN_SPEC }, \
+ { "crtsavres_default", CRTSAVRES_DEFAULT_SPEC }, \
{ "lib_ads", LIB_ADS_SPEC }, \
{ "lib_yellowknife", LIB_YELLOWKNIFE_SPEC }, \
{ "lib_mvme", LIB_MVME_SPEC }, \
@@ -1392,6 +1307,7 @@ ncrtn.o%s"
{ "lib_linux", LIB_LINUX_SPEC }, \
{ "lib_netbsd", LIB_NETBSD_SPEC }, \
{ "lib_vxworks", LIB_VXWORKS_SPEC }, \
+ { "lib_windiss", LIB_WINDISS_SPEC }, \
{ "lib_default", LIB_DEFAULT_SPEC }, \
{ "startfile_ads", STARTFILE_ADS_SPEC }, \
{ "startfile_yellowknife", STARTFILE_YELLOWKNIFE_SPEC }, \
@@ -1402,6 +1318,7 @@ ncrtn.o%s"
{ "startfile_linux", STARTFILE_LINUX_SPEC }, \
{ "startfile_netbsd", STARTFILE_NETBSD_SPEC }, \
{ "startfile_vxworks", STARTFILE_VXWORKS_SPEC }, \
+ { "startfile_windiss", STARTFILE_WINDISS_SPEC }, \
{ "startfile_default", STARTFILE_DEFAULT_SPEC }, \
{ "endfile_ads", ENDFILE_ADS_SPEC }, \
{ "endfile_yellowknife", ENDFILE_YELLOWKNIFE_SPEC }, \
@@ -1412,6 +1329,7 @@ ncrtn.o%s"
{ "endfile_linux", ENDFILE_LINUX_SPEC }, \
{ "endfile_netbsd", ENDFILE_NETBSD_SPEC }, \
{ "endfile_vxworks", ENDFILE_VXWORKS_SPEC }, \
+ { "endfile_windiss", ENDFILE_WINDISS_SPEC }, \
{ "endfile_default", ENDFILE_DEFAULT_SPEC }, \
{ "link_path", LINK_PATH_SPEC }, \
{ "link_shlib", LINK_SHLIB_SPEC }, \
@@ -1426,6 +1344,7 @@ ncrtn.o%s"
{ "link_start_linux", LINK_START_LINUX_SPEC }, \
{ "link_start_netbsd", LINK_START_NETBSD_SPEC }, \
{ "link_start_vxworks", LINK_START_VXWORKS_SPEC }, \
+ { "link_start_windiss", LINK_START_WINDISS_SPEC }, \
{ "link_start_default", LINK_START_DEFAULT_SPEC }, \
{ "link_os", LINK_OS_SPEC }, \
{ "link_os_ads", LINK_OS_ADS_SPEC }, \
@@ -1437,14 +1356,11 @@ ncrtn.o%s"
{ "link_os_gnu", LINK_OS_GNU_SPEC }, \
{ "link_os_netbsd", LINK_OS_NETBSD_SPEC }, \
{ "link_os_vxworks", LINK_OS_VXWORKS_SPEC }, \
+ { "link_os_windiss", LINK_OS_WINDISS_SPEC }, \
{ "link_os_default", LINK_OS_DEFAULT_SPEC }, \
{ "cc1_endian_big", CC1_ENDIAN_BIG_SPEC }, \
{ "cc1_endian_little", CC1_ENDIAN_LITTLE_SPEC }, \
{ "cc1_endian_default", CC1_ENDIAN_DEFAULT_SPEC }, \
- { "cpp_endian_big", CPP_ENDIAN_BIG_SPEC }, \
- { "cpp_endian_little", CPP_ENDIAN_LITTLE_SPEC }, \
- { "cpp_float_default", CPP_FLOAT_DEFAULT_SPEC }, \
- { "cpp_longdouble_default", CPP_LONGDOUBLE_DEFAULT_SPEC }, \
{ "cpp_os_ads", CPP_OS_ADS_SPEC }, \
{ "cpp_os_yellowknife", CPP_OS_YELLOWKNIFE_SPEC }, \
{ "cpp_os_mvme", CPP_OS_MVME_SPEC }, \
@@ -1453,8 +1369,9 @@ ncrtn.o%s"
{ "cpp_os_gnu", CPP_OS_GNU_SPEC }, \
{ "cpp_os_linux", CPP_OS_LINUX_SPEC }, \
{ "cpp_os_netbsd", CPP_OS_NETBSD_SPEC }, \
- { "cpp_os_vxworks", CPP_OS_VXWORKS_SPEC }, \
{ "cpp_os_rtems", CPP_OS_RTEMS_SPEC }, \
+ { "cpp_os_vxworks", CPP_OS_VXWORKS_SPEC }, \
+ { "cpp_os_windiss", CPP_OS_WINDISS_SPEC }, \
{ "cpp_os_default", CPP_OS_DEFAULT_SPEC },
/* Define this macro as a C expression for the initializer of an
@@ -1481,7 +1398,7 @@ ncrtn.o%s"
pack(pop)'. The pack(push,<n>) pragma specifies the maximum
alignment (in bytes) of fields within a structure, in much the
same way as the __aligned__' and __packed__' __attribute__'s
- do. A pack value of zero resets the behaviour to the default.
+ do. A pack value of zero resets the behavior to the default.
Successive invocations of this pragma cause the previous values to
be stacked, so that invocations of #pragma pack(pop)' will return
to the previous value. */
diff --git a/contrib/gcc/config/rs6000/sysv4le.h b/contrib/gcc/config/rs6000/sysv4le.h
index 1c0daea..fda8477 100644
--- a/contrib/gcc/config/rs6000/sysv4le.h
+++ b/contrib/gcc/config/rs6000/sysv4le.h
@@ -23,9 +23,6 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_LITTLE_ENDIAN)
-#undef CPP_ENDIAN_DEFAULT_SPEC
-#define CPP_ENDIAN_DEFAULT_SPEC "%(cpp_endian_little)"
-
#undef CC1_ENDIAN_DEFAULT_SPEC
#define CC1_ENDIAN_DEFAULT_SPEC "%(cc1_endian_little)"
diff --git a/contrib/gcc/config/rs6000/t-aix43 b/contrib/gcc/config/rs6000/t-aix43
index 9bbfe00..a716209 100644
--- a/contrib/gcc/config/rs6000/t-aix43
+++ b/contrib/gcc/config/rs6000/t-aix43
@@ -19,27 +19,24 @@ MULTILIB_OPTIONS = pthread \
MULTILIB_DIRNAMES = pthread \
common power powerpc ppc64
-MULTILIB_MATCHES = mcpu?power=mpower \
- mcpu?power=mrios1 \
+MULTILIB_MATCHES = mcpu?power=mcpu?power \
+ mcpu?power=mcpu?power2 \
+ mcpu?powerpc=mcpu?power3 \
+ mcpu?powerpc=mcpu?power4 \
+ mcpu?powerpc=mcpu?powerpc \
mcpu?power=mcpu?rios1 \
+ mcpu?power=mcpu?rios2 \
mcpu?power=mcpu?rsc \
mcpu?power=mcpu?rsc1 \
- mcpu?power=mpower2 \
- mcpu?power=mrios2 \
- mcpu?power=mcpu?rios2 \
mcpu?powerpc=mcpu?rs64a \
mcpu?powerpc=mcpu?601 \
mcpu?powerpc=mcpu?602 \
mcpu?powerpc=mcpu?603 \
mcpu?powerpc=mcpu?603e \
mcpu?powerpc=mcpu?604 \
+ mcpu?powerpc=mcpu?604e \
mcpu?powerpc=mcpu?620 \
- mcpu?powerpc=mcpu?630 \
- mcpu?powerpc=mcpu?750 \
- mcpu?powerpc=mcpu?403 \
- mcpu?powerpc=mpowerpc \
- mcpu?powerpc=mpowerpc-gpopt \
- mcpu?powerpc=mpowerpc-gfxopt
+ mcpu?powerpc=mcpu?630
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
diff --git a/contrib/gcc/config/rs6000/t-aix52 b/contrib/gcc/config/rs6000/t-aix52
new file mode 100644
index 0000000..bddcdb1
--- /dev/null
+++ b/contrib/gcc/config/rs6000/t-aix52
@@ -0,0 +1,52 @@
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = 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
+
+# Build the libraries for pthread and all of the
+# different processor models
+
+MULTILIB_OPTIONS = pthread maix64
+
+MULTILIB_DIRNAMES = pthread ppc64
+
+MULTILIB_MATCHES =
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+# Build a shared libgcc library.
+SHLIB_EXT = .a
+SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
+ -Wl,-bE:@shlib_map_file@ -o @multilib_dir@/shr.o \
+ @multilib_flags@ @shlib_objs@ -lc \
+ `case @shlib_base_name@ in \
+ *pthread*) echo -L/usr/lib/threads -lpthreads -lc_r /usr/lib/libc.a ;; \
+ *) echo -lc ;; esac` ; \
+ rm -f tmp-@shlib_base_name@.a ; \
+ $(AR_CREATE_FOR_TARGET) tmp-@shlib_base_name@.a @multilib_dir@/shr.o ; \
+ mv tmp-@shlib_base_name@.a @shlib_base_name@.a ; \
+ rm -f @multilib_dir@/shr.o
+# $(slibdir) double quoted to protect it from expansion while building
+# libgcc.mk. We want this delayed until actual install time.
+SHLIB_INSTALL = $(INSTALL_DATA) @shlib_base_name@.a $$(DESTDIR)$$(slibdir)/
+SHLIB_LIBS = -lc `case @shlib_base_name@ in *pthread*) echo -lpthread ;; esac`
+SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
+SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver
+SHLIB_NM_FLAGS = -Bpg -X32_64
+
+# Either 32-bit and 64-bit objects in archives.
+AR_FLAGS_FOR_TARGET = -X32_64
+
+# Compile Ada files with minimal-toc. The primary focus is gnatlib, so
+# that the library does not use nearly the entire TOC of applications
+# until gnatlib is built as a shared library on AIX. Compiling the
+# compiler with -mminimal-toc does not cause any harm.
+T_ADAFLAGS = -mminimal-toc
diff --git a/contrib/gcc/config/rs6000/t-darwin b/contrib/gcc/config/rs6000/t-darwin
index c9c392e..7aca023 100644
--- a/contrib/gcc/config/rs6000/t-darwin
+++ b/contrib/gcc/config/rs6000/t-darwin
@@ -1,33 +1,2 @@
-# Library code must include trampoline support
+# Library code must include trampoline support.
LIB2FUNCS_EXTRA = $(srcdir)/config/rs6000/darwin-tramp.asm
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = 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
-
-darwin.o: $(srcdir)/config/darwin.c $(CONFIG_H) $(SYSTEM_H) $(RTL_BASE_H) \
- $(REGS_H) hard-reg-set.h insn-config.h conditions.h output.h \
- insn-attr.h flags.h $(TREE_H) $(EXPR_H) reload.h \
- function.h $(GGC_H) $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
-
-darwin-c.o: $(srcdir)/config/darwin-c.c $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(C_TREE_H) c-lex.h c-pragma.h toplev.h cpplib.h \
- $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
-
-# Build the libraries for both hard and soft floating point
-
-MULTILIB_OPTIONS = msoft-float
-MULTILIB_DIRNAMES = soft-float
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/contrib/gcc/config/rs6000/t-linux64 b/contrib/gcc/config/rs6000/t-linux64
index 48b6150..af7b44b 100644
--- a/contrib/gcc/config/rs6000/t-linux64
+++ b/contrib/gcc/config/rs6000/t-linux64
@@ -5,6 +5,9 @@ TARGET_LIBGCC2_CFLAGS =
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o \
crtsavres.o
+# These functions are needed for soft-float on powerpc64-linux.
+LIB2FUNCS_EXTRA = $(srcdir)/config/rs6000/ppc64-fp.c
+
# ld provides these functions as needed.
crtsavres.S:
echo >crtsavres.S
diff --git a/contrib/gcc/config/rs6000/t-netbsd b/contrib/gcc/config/rs6000/t-netbsd
new file mode 100644
index 0000000..0cb08e7
--- /dev/null
+++ b/contrib/gcc/config/rs6000/t-netbsd
@@ -0,0 +1,42 @@
+# Support for NetBSD PowerPC ELF targets (SVR4 ABI).
+
+LIB2FUNCS_EXTRA = tramp.S
+
+tramp.S: $(srcdir)/config/rs6000/tramp.asm
+ cat $(srcdir)/config/rs6000/tramp.asm > tramp.S
+
+crtsavres.S: $(srcdir)/config/rs6000/crtsavres.asm
+ cat $(srcdir)/config/rs6000/crtsavres.asm >crtsavres.S
+
+EXTRA_PARTS += crtsavres$(objext)
+
+# It is important that crtbegin.o, etc., aren't surprised by stuff in .sdata.
+CRTSTUFF_T_CFLAGS += -msdata=none
+CRTSTUFF_T_CFLAGS_S += -msdata=none
+
+# Switch synonyms
+MULTILIB_MATCHES_FLOAT = msoft-float=mcpu?401 \
+ msoft-float=mcpu?403 \
+ msoft-float=mcpu?405 \
+ msoft-float=mcpu?ec603e \
+ msoft-float=mcpu?801 \
+ msoft-float=mcpu?821 \
+ msoft-float=mcpu?823 \
+ msoft-float=mcpu?860
+
+MULTILIB_OPTIONS = msoft-float
+MULTILIB_DIRNAMES = soft-float
+MULTILIB_EXTRA_OPTS = fPIC mstrict-align
+MULTILIB_EXCEPTIONS =
+
+MULTILIB_MATCHES = ${MULTILIB_MATCHES_FLOAT}
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+EXTRA_MULTILIB_PARTS = crtbegin$(objext) crtend$(objext) \
+ crtbeginS$(objext) crtendS$(objext) crtbeginT$(objext) \
+ crtsavres$(objext)
+
+$(T)crtsavres$(objext): crtsavres.S
+ $(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) \
+ -c crtsavres.S -o $(T)crtsavres$(objext)
diff --git a/contrib/gcc/config/rs6000/t-ppccomm b/contrib/gcc/config/rs6000/t-ppccomm
index 7570af4..f4fcdce 100644
--- a/contrib/gcc/config/rs6000/t-ppccomm
+++ b/contrib/gcc/config/rs6000/t-ppccomm
@@ -27,6 +27,7 @@ tramp.S: $(srcdir)/config/rs6000/tramp.asm
# Switch synonyms
MULTILIB_MATCHES_FLOAT = msoft-float=mcpu?401 \
msoft-float=mcpu?403 \
+ msoft-float=mcpu?405 \
msoft-float=mcpu?ec603e \
msoft-float=mcpu?801 \
msoft-float=mcpu?821 \
diff --git a/contrib/gcc/config/rs6000/t-ppcendian b/contrib/gcc/config/rs6000/t-ppcendian
new file mode 100644
index 0000000..b6252ee
--- /dev/null
+++ b/contrib/gcc/config/rs6000/t-ppcendian
@@ -0,0 +1,12 @@
+# Multilibs for powerpc embedded ELF targets with altivec.
+
+MULTILIB_OPTIONS = msoft-float \
+ mlittle/mbig
+
+MULTILIB_DIRNAMES = nof \
+ le be
+
+
+MULTILIB_MATCHES = ${MULTILIB_MATCHES_FLOAT} \
+ ${MULTILIB_MATCHES_ENDIAN} \
+ ${MULTILIB_MATCHES_SYSV}
diff --git a/contrib/gcc/config/rs6000/t-rs6000-c-rule b/contrib/gcc/config/rs6000/t-rs6000-c-rule
new file mode 100644
index 0000000..a768fb5
--- /dev/null
+++ b/contrib/gcc/config/rs6000/t-rs6000-c-rule
@@ -0,0 +1,4 @@
+rs6000-c.o: $(srcdir)/config/rs6000/rs6000-c.c \
+ $(srcdir)/config/rs6000/rs6000-protos.h \
+ $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(CPPLIB_H) $(TM_P_H) c-pragma.h errors.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
diff --git a/contrib/gcc/config/rs6000/vxppc.h b/contrib/gcc/config/rs6000/vxppc.h
index b13f6f5..91250a6 100644
--- a/contrib/gcc/config/rs6000/vxppc.h
+++ b/contrib/gcc/config/rs6000/vxppc.h
@@ -39,17 +39,18 @@ Boston, MA 02111-1307, USA. */
#undef LINK_OS_DEFAULT_SPEC
#define LINK_OS_DEFAULT_SPEC "%(link_os_vxworks)"
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "\
--D__vxworks -D__vxworks__ -Asystem=vxworks -Asystem=embedded \
--Acpu=powerpc -Amachine=powerpc"
-
-/* Don't define _LITTLE_ENDIAN or _BIG_ENDIAN */
-#undef CPP_ENDIAN_BIG_SPEC
-#define CPP_ENDIAN_BIG_SPEC "-D__BIG_ENDIAN__ -Amachine=bigendian"
-
-#undef CPP_ENDIAN_LITTLE_SPEC
-#define CPP_ENDIAN_LITTLE_SPEC "-D__LITTLE_ENDIAN__ -Amachine=littleendian"
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__vxworks"); \
+ builtin_define ("__vxworks__"); \
+ builtin_assert ("system=vxworks"); \
+ builtin_assert ("system=embedded"); \
+ builtin_assert ("cpu=powerpc"); \
+ builtin_assert ("machine=powerpc"); \
+ } \
+ while (0)
/* We use stabs-in-elf for debugging */
#undef PREFERRED_DEBUGGING_TYPE
diff --git a/contrib/gcc/config/rs6000/windiss.h b/contrib/gcc/config/rs6000/windiss.h
new file mode 100644
index 0000000..7aacb23
--- /dev/null
+++ b/contrib/gcc/config/rs6000/windiss.h
@@ -0,0 +1,47 @@
+/* Support for GCC on PowerPC using WindISS simulator.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (PowerPC WindISS)");
+
+#undef LIB_DEFAULT_SPEC
+#define LIB_DEFAULT_SPEC "%(lib_windiss)"
+
+#undef STARTFILE_DEFAULT_SPEC
+#define STARTFILE_DEFAULT_SPEC "%(startfile_windiss)"
+
+#undef ENDFILE_DEFAULT_SPEC
+#define ENDFILE_DEFAULT_SPEC "%(endfile_windiss)"
+
+#undef LINK_START_DEFAULT_SPEC
+#define LINK_START_DEFAULT_SPEC "%(link_start_windiss)"
+
+#undef LINK_OS_DEFAULT_SPEC
+#define LINK_OS_DEFAULT_SPEC "%(link_os_windiss)"
+
+#undef CRTSAVRES_DEFAULT_SPEC
+#define CRTSAVRES_DEFAULT_SPEC ""
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "short unsigned int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 16
diff --git a/contrib/gcc/config/rs6000/xcoff.h b/contrib/gcc/config/rs6000/xcoff.h
index a61061a..21d74a9 100644
--- a/contrib/gcc/config/rs6000/xcoff.h
+++ b/contrib/gcc/config/rs6000/xcoff.h
@@ -23,7 +23,7 @@ Boston, MA 02111-1307, USA. */
#define TARGET_OBJECT_FORMAT OBJECT_XCOFF
/* The RS/6000 uses the XCOFF format. */
-#define XCOFF_DEBUGGING_INFO
+#define XCOFF_DEBUGGING_INFO 1
/* Define if the object format being used is COFF or a superset. */
#define OBJECT_FORMAT_COFF
@@ -135,37 +135,7 @@ toc_section () \
#define READONLY_DATA_SECTION read_only_data_section
-/* Select the section for an initialized data object.
-
- On the RS/6000, we have a special section for all variables except those
- that are static. */
-
-#define SELECT_SECTION(EXP,RELOC,ALIGN) \
-{ \
- if ((TREE_CODE (EXP) == STRING_CST \
- && ! flag_writable_strings) \
- || (TREE_CODE_CLASS (TREE_CODE (EXP)) == 'd' \
- && TREE_READONLY (EXP) && ! TREE_THIS_VOLATILE (EXP) \
- && DECL_INITIAL (EXP) \
- && (DECL_INITIAL (EXP) == error_mark_node \
- || TREE_CONSTANT (DECL_INITIAL (EXP))) \
- && ! (RELOC))) \
- { \
- if (TREE_PUBLIC (EXP)) \
- read_only_data_section (); \
- else \
- read_only_private_data_section (); \
- } \
- else \
- { \
- if (TREE_PUBLIC (EXP)) \
- data_section (); \
- else \
- private_data_section (); \
- } \
-}
-
-/* Return non-zero if this entry is to be written into the constant
+/* Return nonzero 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
@@ -189,29 +159,14 @@ toc_section () \
|| (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
&& ! TARGET_NO_FP_IN_TOC)))))
-/* Select section for constant in constant pool.
-
- On RS/6000, all constants are in the private read-only data area.
- However, if this is being placed in the TOC it must be output as a
- toc entry. */
-
-#define SELECT_RTX_SECTION(MODE, X, ALIGN) \
-{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X, MODE)) \
- toc_section (); \
- else \
- read_only_private_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
- call. Do not set this flag if the function is weakly defined. */
-
-#define ENCODE_SECTION_INFO(DECL) \
- if (TREE_CODE (DECL) == FUNCTION_DECL \
- && !TREE_PUBLIC (DECL) \
- && !DECL_WEAK (DECL)) \
- SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;
+#define TARGET_ASM_GLOBALIZE_LABEL rs6000_xcoff_asm_globalize_label
+#define TARGET_ASM_NAMED_SECTION rs6000_xcoff_asm_named_section
+#define TARGET_ASM_SELECT_SECTION rs6000_xcoff_select_section
+#define TARGET_ASM_SELECT_RTX_SECTION rs6000_xcoff_select_rtx_section
+#define TARGET_ASM_UNIQUE_SECTION rs6000_xcoff_unique_section
+#define TARGET_ENCODE_SECTION_INFO rs6000_xcoff_encode_section_info
+#define TARGET_STRIP_NAME_ENCODING rs6000_xcoff_strip_name_encoding
+#define TARGET_SECTION_TYPE_FLAGS rs6000_xcoff_section_type_flags
/* FP save and restore routines. */
#define SAVE_FP_PREFIX "._savef"
@@ -232,13 +187,8 @@ toc_section () \
/* This outputs NAME to FILE up to the first null or '['. */
-#define RS6000_OUTPUT_BASENAME(FILE, NAME) \
- { \
- const char *_p; \
- \
- STRIP_NAME_ENCODING (_p, (NAME)); \
- assemble_name ((FILE), _p); \
- }
+#define RS6000_OUTPUT_BASENAME(FILE, NAME) \
+ assemble_name ((FILE), (*targetm.strip_name_encoding) (NAME))
/* 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. */
@@ -249,31 +199,8 @@ toc_section () \
/* This is how to output a command to make the user-level label named NAME
defined for reference from other files. */
-#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
- do { fputs ("\t.globl ", FILE); \
- RS6000_OUTPUT_BASENAME (FILE, NAME); putc ('\n', FILE);} while (0)
-
-/* Remove any trailing [DS] or the like from the symbol name. */
-
-#define STRIP_NAME_ENCODING(VAR,NAME) \
- do \
- { \
- const char *_name = (NAME); \
- size_t _len; \
- if (*_name == '*') \
- _name++; \
- _len = strlen (_name); \
- if (_name[_len - 1] != ']') \
- (VAR) = _name; \
- else \
- { \
- char *_new_name = (char *) alloca (_len + 1); \
- strcpy (_new_name, _name); \
- _new_name[_len - 4] = '\0'; \
- (VAR) = _new_name; \
- } \
- } \
- while (0)
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.globl "
/* Output at beginning of assembler file.
@@ -296,7 +223,9 @@ toc_section () \
rs6000_gen_section_name (&xcoff_read_only_section_name, \
main_input_filename, ".ro_"); \
\
- fprintf (FILE, "\t.file\t\"%s\"\n", main_input_filename); \
+ fputs ("\t.file\t", FILE); \
+ output_quoted_string (FILE, main_input_filename); \
+ fputc ('\n', FILE); \
if (TARGET_64BIT) \
fputs ("\t.machine\t\"ppc64\"\n", FILE); \
toc_section (); \
@@ -337,7 +266,7 @@ toc_section () \
#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \
{ rtx sym_ref = XEXP (DECL_RTL (DECL), 0); \
- if (!DECL_WEAK (DECL)) \
+ if ((*targetm.binds_local_p) (DECL)) \
SYMBOL_REF_FLAG (sym_ref) = 1; \
if (TREE_PUBLIC (DECL)) \
{ \
@@ -367,7 +296,11 @@ toc_section () \
putc ('.', FILE); \
RS6000_OUTPUT_BASENAME (FILE, NAME); \
fputs (":\n", FILE); \
- if (write_symbols == XCOFF_DEBUG) \
+ if (write_symbols == XCOFF_DEBUG \
+ /* When called before targetm.asm_out.output_mi_thunk, \
+ we won't be emitting the rest of the debug info that \
+ goes along with this, leading to assembler errors. */ \
+ && !(current_function_is_thunk && !no_new_pseudos)) \
xcoffout_declare_function (FILE, DECL, NAME); \
}
@@ -379,17 +312,17 @@ toc_section () \
/* This says how to output an external. */
#undef ASM_OUTPUT_EXTERNAL
-#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
-{ rtx _symref = XEXP (DECL_RTL (DECL), 0); \
- if ((TREE_CODE (DECL) == VAR_DECL \
- || TREE_CODE (DECL) == FUNCTION_DECL) \
- && (NAME)[strlen (NAME) - 1] != ']') \
- { \
- char *_name = (char *) permalloc (strlen (XSTR (_symref, 0)) + 5); \
- strcpy (_name, XSTR (_symref, 0)); \
- strcat (_name, TREE_CODE (DECL) == FUNCTION_DECL ? "[DS]" : "[RW]"); \
- XSTR (_symref, 0) = _name; \
- } \
+#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
+{ rtx _symref = XEXP (DECL_RTL (DECL), 0); \
+ if ((TREE_CODE (DECL) == VAR_DECL \
+ || TREE_CODE (DECL) == FUNCTION_DECL) \
+ && (NAME)[strlen (NAME) - 1] != ']') \
+ { \
+ XSTR (_symref, 0) = concat (XSTR (_symref, 0), \
+ (TREE_CODE (DECL) == FUNCTION_DECL \
+ ? "[DS]" : "[RW]"), \
+ NULL); \
+ } \
}
/* This is how to output an internal numbered label where
@@ -426,19 +359,26 @@ toc_section () \
/* This is how to advance the location counter by SIZE bytes. */
+#define SKIP_ASM_OP "\t.space "
+
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
- fprintf (FILE, "\t.space %d\n", (SIZE))
+ fprintf (FILE, "%s%u\n", SKIP_ASM_OP, (SIZE))
/* This says how to output an assembler line
to define a global common symbol. */
-#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGNMENT) \
- do { fputs ("\t.comm ", (FILE)); \
+#define COMMON_ASM_OP "\t.comm "
+
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
+ do { fputs (COMMON_ASM_OP, (FILE)); \
RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
- if ( (SIZE) > 4) \
- fprintf ((FILE), ",%d,3\n", (SIZE)); \
+ if ((ALIGN) > 32) \
+ fprintf ((FILE), ",%u,%u\n", (SIZE), \
+ exact_log2 ((ALIGN) / BITS_PER_UNIT)); \
+ else if ((SIZE) > 4) \
+ fprintf ((FILE), ",%u,3\n", (SIZE)); \
else \
- fprintf ((FILE), ",%d\n", (SIZE)); \
+ fprintf ((FILE), ",%u\n", (SIZE)); \
} while (0)
/* This says how to output an assembler line
@@ -447,10 +387,12 @@ toc_section () \
alignment after preceding TOC section if it was aligned
for 64-bit mode. */
+#define LOCAL_COMMON_ASM_OP "\t.lcomm "
+
#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
- do { fputs ("\t.lcomm ", (FILE)); \
+ do { fputs (LOCAL_COMMON_ASM_OP, (FILE)); \
RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
- fprintf ((FILE), ",%d,%s\n", (TARGET_32BIT ? (SIZE) : (ROUNDED)), \
+ fprintf ((FILE), ",%u,%s\n", (TARGET_32BIT ? (SIZE) : (ROUNDED)), \
xcoff_bss_section_name); \
} while (0)
@@ -476,25 +418,6 @@ toc_section () \
Align entire section to BIGGEST_ALIGNMENT. */
#define DATA_SECTION_ASM_OP "\t.csect .data[RW],3"
-/* Define unique section name -- functions only. */
-#define UNIQUE_SECTION(DECL,RELOC) \
- do { \
- int len; \
- const char *name; \
- char *string; \
- \
- if (TREE_CODE (DECL) == FUNCTION_DECL) { \
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
- len = strlen (name) + 5; \
- string = alloca (len + 1); \
- sprintf (string, ".%s[PR]", name); \
- DECL_SECTION_NAME (DECL) = build_string (len, string); \
- } \
- } while (0)
-
-/* Switch into a generic section. */
-#define TARGET_ASM_NAMED_SECTION xcoff_asm_named_section
-
/* Define the name of the section to use for the EH language specific
data areas (.gcc_except_table on most other systems). */
#define TARGET_ASM_EXCEPTION_SECTION data_section
diff --git a/contrib/gcc/config/s390/fixdfdi.h b/contrib/gcc/config/s390/fixdfdi.h
index 4f1fb35..1f82a9c 100644
--- a/contrib/gcc/config/s390/fixdfdi.h
+++ b/contrib/gcc/config/s390/fixdfdi.h
@@ -43,6 +43,7 @@ union double_long {
UDItype_x ll;
};
+UDItype_x __fixunsdfdi (double a1);
/* convert double to unsigned int */
UDItype_x
@@ -114,6 +115,8 @@ union double_long {
UDItype_x ll;
};
+DItype_x __fixdfdi (double a1);
+
/* convert double to int */
DItype_x
__fixdfdi (double a1)
@@ -184,6 +187,8 @@ union float_long
USItype_x l;
};
+UDItype_x __fixunssfdi (float a1);
+
/* convert float to unsigned int */
UDItype_x
__fixunssfdi (float a1)
@@ -250,6 +255,8 @@ union float_long
USItype_x l;
};
+DItype_x __fixsfdi (float a1);
+
/* convert double to int */
DItype_x
__fixsfdi (float a1)
diff --git a/contrib/gcc/config/s390/libgcc-glibc.ver b/contrib/gcc/config/s390/libgcc-glibc.ver
index 9a42151..1d9e229 100644
--- a/contrib/gcc/config/s390/libgcc-glibc.ver
+++ b/contrib/gcc/config/s390/libgcc-glibc.ver
@@ -8,6 +8,25 @@
# because GLIBC_2.0 does not exist on this architecture, as the first
# ever glibc release on the platform was GLIBC_2.2.
+%ifndef __s390x__
+%inherit GCC_3.0 GLIBC_2.0
+GLIBC_2.0 {
+ __divdi3
+ __moddi3
+ __udivdi3
+ __umoddi3
+
+ __register_frame
+ __register_frame_table
+ __deregister_frame
+ __register_frame_info
+ __deregister_frame_info
+ __frame_state_for
+ __register_frame_info_table
+}
+%endif
+
+%ifdef __s390x__
%inherit GCC_3.0 GLIBC_2.2
GLIBC_2.2 {
__register_frame
@@ -18,4 +37,5 @@ GLIBC_2.2 {
__frame_state_for
__register_frame_info_table
}
+%endif
diff --git a/contrib/gcc/config/s390/linux.h b/contrib/gcc/config/s390/linux.h
index a0336bf..cbb7710 100644
--- a/contrib/gcc/config/s390/linux.h
+++ b/contrib/gcc/config/s390/linux.h
@@ -50,35 +50,22 @@ Boston, MA 02111-1307, USA. */
/* Target specific preprocessor settings. */
-#define NO_BUILTIN_SIZE_TYPE
-#define NO_BUILTIN_PTRDIFF_TYPE
-
-#define CPP_PREDEFINES \
- "-Dunix -Asystem(unix) -D__gnu_linux__ -Dlinux -Asystem(linux) -D__ELF__ \
- -Acpu(s390) -Amachine(s390) -D__s390__"
-
-#define CPP_ARCH31_SPEC \
- "-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=int"
-#define CPP_ARCH64_SPEC \
- "-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int \
- -D__s390x__ -D__LONG_MAX__=9223372036854775807L"
-
-#ifdef DEFAULT_TARGET_64BIT
-#undef CPP_SPEC
-#define CPP_SPEC "%{m31:%(cpp_arch31)} %{!m31:%(cpp_arch64)}"
-#else
-#undef CPP_SPEC
-#define CPP_SPEC "%{m64:%(cpp_arch64)} %{!m64:%(cpp_arch31)}"
-#endif
-
-
-/* Target specific compiler settings. */
-
-/* ??? -fcaller-saves sometimes doesn't work. Fix this! */
-#undef CC1_SPEC
-#define CC1_SPEC "-fno-caller-saves"
-#undef CC1PLUS_SPEC
-#define CC1PLUS_SPEC "-fno-caller-saves"
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("linux"); \
+ builtin_define_std ("unix"); \
+ builtin_assert ("system=linux"); \
+ builtin_assert ("system=unix"); \
+ builtin_define ("__ELF__"); \
+ builtin_define ("__gnu_linux__"); \
+ if (flag_pic) \
+ { \
+ builtin_define ("__PIC__"); \
+ builtin_define ("__pic__"); \
+ } \
+ } \
+ while (0)
/* Target specific assembler settings. */
@@ -94,6 +81,12 @@ Boston, MA 02111-1307, USA. */
/* Target specific linker settings. */
+#ifdef DEFAULT_TARGET_64BIT
+#define MULTILIB_DEFAULTS { "m64" }
+#else
+#define MULTILIB_DEFAULTS { "m31" }
+#endif
+
#define LINK_ARCH31_SPEC \
"-m elf_s390 \
%{shared:-shared} \
@@ -126,183 +119,86 @@ Boston, MA 02111-1307, USA. */
is an initializer with a subgrouping for each command option. */
#define EXTRA_SPECS \
- { "cpp_arch31", CPP_ARCH31_SPEC }, \
- { "cpp_arch64", CPP_ARCH64_SPEC }, \
{ "link_arch31", LINK_ARCH31_SPEC }, \
{ "link_arch64", LINK_ARCH64_SPEC }, \
-/* Character to start a comment. */
-
-#define ASM_COMMENT_START "#"
-
-
-/* Assembler pseudos to introduce constants of various size. */
-
-#define ASM_DOUBLE "\t.double"
-
-/* The LOCAL_LABEL_PREFIX variable is used by dbxelf.h. */
-#define LOCAL_LABEL_PREFIX "."
-
-/* Prefix for internally generated assembler labels. */
-#define LPREFIX ".L"
-
-
-/* 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. */
-
-#undef ASM_OUTPUT_LABEL
-#define ASM_OUTPUT_LABEL(FILE, NAME) \
- (assemble_name (FILE, NAME), fputs (":\n", FILE))
-
-/* Store in OUTPUT a string (made with alloca) containing
- an assembler-name for a local static variable named NAME.
- LABELNO is an integer which is different for each call. */
-
-#undef ASM_FORMAT_PRIVATE_NAME
-#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
-( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
- sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
-
-
- /* internal macro to output long */
-#define _ASM_OUTPUT_LONG(FILE, VALUE) \
- fprintf (FILE, "\t.long\t0x%lX\n", VALUE);
-
-
-/* This is how to output an element of a case-vector that is absolute. */
-
-#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
- fprintf (FILE, "%s%s%d\n", integer_asm_op (UNITS_PER_WORD, TRUE), \
- LPREFIX, VALUE)
-
-/* This is how to output an element of a case-vector that is relative. */
-
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
- fprintf (FILE, "%s%s%d-%s%d\n", integer_asm_op (UNITS_PER_WORD, TRUE), \
- LPREFIX, VALUE, LPREFIX, REL)
-
-
-
-/* This is how to output an assembler line
- that says to advance the location counter
- to a multiple of 2**LOG bytes. */
-
-#undef ASM_OUTPUT_ALIGN
-#define ASM_OUTPUT_ALIGN(FILE, LOG) \
- if ((LOG)!=0) fprintf ((FILE), "\t.align\t%d\n", 1<<(LOG))
-
-/* This is how to output an assembler line
- that says to advance the location counter by SIZE bytes. */
-
-#undef ASM_OUTPUT_SKIP
-#define ASM_OUTPUT_SKIP(FILE, SIZE) \
- fprintf ((FILE), "\t.set\t.,.+%u\n", (SIZE))
-
-/* This is how to output assembler code to declare an
- uninitialized external linkage data object. */
-
-#undef ASM_OUTPUT_ALIGNED_BSS
-#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
- asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
-
-/* Output before read-only data. */
-
-#define TEXT_SECTION_ASM_OP ".text"
-
-/* Output before writable (initialized) data. */
-
-#define DATA_SECTION_ASM_OP ".data"
-
-/* Output before writable (uninitialized) data. */
-
-#define BSS_SECTION_ASM_OP ".bss"
-
-/* This is how to output a command to make the user-level label named NAME
- defined for reference from other files. */
-
-#define ASM_GLOBALIZE_LABEL(FILE, NAME) \
- (fputs (".globl ", FILE), assemble_name (FILE, NAME), fputs ("\n", FILE))
-
-/* Select section for constant in constant pool.
- We are in the right section.
- undef for 64 bit mode (linux64.h).
- */
-
-#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE, X, ALIGN)
-
-
-/* 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 (TARGET_64BIT) \
- { \
- if (flag_pic) \
- { \
- fprintf (FILE, "\tlarl 1,0f\n"); \
- fprintf (FILE, "\tagf %d,0(1)\n", \
- aggregate_value_p (TREE_TYPE \
- (TREE_TYPE (FUNCTION))) ? 3 :2 ); \
- fprintf (FILE, "\tlarl 1,"); \
- assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
- fprintf (FILE, "@GOTENT\n"); \
- fprintf (FILE, "\tlg 1,0(1)\n"); \
- fprintf (FILE, "\tbr 1\n"); \
- fprintf (FILE, "0:\t.long "); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA)); \
- fprintf (FILE, "\n"); \
- } \
- else \
- { \
- fprintf (FILE, "\tlarl 1,0f\n"); \
- fprintf (FILE, "\tagf %d,0(1)\n", \
- aggregate_value_p (TREE_TYPE \
- (TREE_TYPE (FUNCTION))) ? 3 :2 ); \
- fprintf (FILE, "\tjg "); \
- assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
- fprintf (FILE, "\n"); \
- fprintf (FILE, "0:\t.long "); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA)); \
- fprintf (FILE, "\n"); \
- } \
- } \
- else \
- { \
- if (flag_pic) \
- { \
- fprintf (FILE, "\tbras 1,0f\n"); \
- fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_-.\n"); \
- fprintf (FILE, "\t.long "); \
- assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
- fprintf (FILE, "@GOT\n"); \
- fprintf (FILE, "\t.long "); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA)); \
- fprintf (FILE, "\n"); \
- fprintf (FILE, "0:\tal %d,8(1)\n", \
- aggregate_value_p (TREE_TYPE \
- (TREE_TYPE (FUNCTION))) ? 3 : 2 ); \
- fprintf (FILE, "\tl 0,4(1)\n"); \
- fprintf (FILE, "\tal 1,0(1)\n"); \
- fprintf (FILE, "\talr 1,0\n"); \
- fprintf (FILE, "\tl 1,0(1)\n"); \
- fprintf (FILE, "\tbr 1\n"); \
- } else { \
- fprintf (FILE, "\tbras 1,0f\n"); \
- fprintf (FILE, "\t.long "); \
- assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
- fprintf (FILE, "-.\n"); \
- fprintf (FILE, "\t.long "); \
- fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA)); \
- fprintf (FILE, "\n"); \
- fprintf (FILE, "0:\tal %d,4(1)\n", \
- aggregate_value_p (TREE_TYPE \
- (TREE_TYPE (FUNCTION))) ? 3 : 2 ); \
- fprintf (FILE, "\tal 1,0(1)\n"); \
- fprintf (FILE, "\tbr 1\n"); \
- } \
- } \
-} while (0)
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
+ do { \
+ unsigned char *pc_ = (CONTEXT)->ra; \
+ long new_cfa_; \
+ int i_; \
+ \
+ typedef struct \
+ { \
+ unsigned long psw_mask; \
+ unsigned long psw_addr; \
+ unsigned long gprs[16]; \
+ unsigned int acrs[16]; \
+ unsigned int fpc; \
+ unsigned int __pad; \
+ double fprs[16]; \
+ } __attribute__ ((__aligned__ (8))) sigregs_; \
+ \
+ sigregs_ *regs_; \
+ \
+ /* svc $__NR_sigreturn or svc $__NR_rt_sigreturn */ \
+ if (pc_[0] != 0x0a || (pc_[1] != 119 && pc_[1] != 173)) \
+ break; \
+ \
+ /* New-style RT frame: \
+ retcode + alignment (8 bytes) \
+ siginfo (128 bytes) \
+ ucontext (contains sigregs) */ \
+ if ((CONTEXT)->ra == (CONTEXT)->cfa) \
+ { \
+ struct ucontext_ \
+ { \
+ unsigned long uc_flags; \
+ struct ucontext_ *uc_link; \
+ unsigned long uc_stack[3]; \
+ sigregs_ uc_mcontext; \
+ } *uc_ = (CONTEXT)->cfa + 8 + 128; \
+ \
+ regs_ = &uc_->uc_mcontext; \
+ } \
+ \
+ /* Old-style RT frame and all non-RT frames: \
+ old signal mask (8 bytes) \
+ pointer to sigregs */ \
+ else \
+ { \
+ regs_ = *(sigregs_ **)((CONTEXT)->cfa + 8); \
+ } \
+ \
+ new_cfa_ = regs_->gprs[15] + 16*sizeof(long) + 32; \
+ (FS)->cfa_how = CFA_REG_OFFSET; \
+ (FS)->cfa_reg = 15; \
+ (FS)->cfa_offset = \
+ new_cfa_ - (long) (CONTEXT)->cfa + 16*sizeof(long) + 32; \
+ \
+ for (i_ = 0; i_ < 16; i_++) \
+ { \
+ (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_].loc.offset = \
+ (long)&regs_->gprs[i_] - new_cfa_; \
+ } \
+ for (i_ = 0; i_ < 16; i_++) \
+ { \
+ (FS)->regs.reg[16+i_].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[16+i_].loc.offset = \
+ (long)&regs_->fprs[i_] - new_cfa_; \
+ } \
+ \
+ /* Load return addr from PSW into dummy register 32. */ \
+ (FS)->regs.reg[32].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[32].loc.offset = (long)&regs_->psw_addr - new_cfa_; \
+ (FS)->retaddr_column = 32; \
+ \
+ goto SUCCESS; \
+ } while (0)
#endif
diff --git a/contrib/gcc/config/s390/s390-modes.def b/contrib/gcc/config/s390/s390-modes.def
new file mode 100644
index 0000000..9f9d526
--- /dev/null
+++ b/contrib/gcc/config/s390/s390-modes.def
@@ -0,0 +1,38 @@
+/* Definitions of target machine for GNU compiler, for IBM S/390
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Hartmut Penner (hpenner@de.ibm.com) and
+ Ulrich Weigand (uweigand@de.ibm.com).
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Add any extra modes needed to represent the condition code. */
+
+CC (CCZ)
+CC (CCA)
+CC (CCAP)
+CC (CCAN)
+CC (CCL)
+CC (CCL1)
+CC (CCL2)
+CC (CCU)
+CC (CCUR)
+CC (CCS)
+CC (CCSR)
+CC (CCT)
+CC (CCT1)
+CC (CCT2)
+CC (CCT3)
diff --git a/contrib/gcc/config/s390/s390-protos.h b/contrib/gcc/config/s390/s390-protos.h
index cd4ac10..1f8b144 100644
--- a/contrib/gcc/config/s390/s390-protos.h
+++ b/contrib/gcc/config/s390/s390-protos.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for IBM S/390.
- Copyright (C) 2000 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com)
This file is part of GNU CC.
@@ -24,17 +24,16 @@ Boston, MA 02111-1307, USA. */
extern void optimization_options PARAMS ((int, int));
extern void override_options PARAMS ((void));
extern int s390_arg_frame_offset PARAMS ((void));
-extern void s390_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
-extern void s390_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
extern void s390_emit_prologue PARAMS ((void));
extern void s390_emit_epilogue PARAMS ((void));
extern void s390_function_profiler PARAMS ((FILE *, int));
#ifdef RTX_CODE
+extern int s390_address_cost PARAMS ((rtx));
+extern int q_constraint PARAMS ((rtx));
extern int const0_operand PARAMS ((rtx, enum machine_mode));
extern int consttable_operand PARAMS ((rtx, enum machine_mode));
extern int larl_operand PARAMS ((rtx, enum machine_mode));
-extern int fp_operand PARAMS ((rtx, enum machine_mode));
extern int s_operand PARAMS ((rtx, enum machine_mode));
extern int s_imm_operand PARAMS ((rtx, enum machine_mode));
extern int bras_sym_operand PARAMS ((rtx, enum machine_mode));
@@ -44,12 +43,17 @@ extern int s390_single_hi PARAMS ((rtx, enum machine_mode, int));
extern int s390_extract_hi PARAMS ((rtx, enum machine_mode, int));
extern int s390_single_qi PARAMS ((rtx, enum machine_mode, int));
extern int s390_extract_qi PARAMS ((rtx, enum machine_mode, int));
+extern bool s390_split_ok_p PARAMS ((rtx, rtx, enum machine_mode, int));
+extern int tls_symbolic_operand PARAMS ((rtx));
extern int s390_match_ccmode PARAMS ((rtx, enum machine_mode));
+extern enum machine_mode s390_tm_ccmode PARAMS ((rtx, rtx, int));
extern enum machine_mode s390_select_ccmode PARAMS ((enum rtx_code, rtx, rtx));
extern int symbolic_reference_mentioned_p PARAMS ((rtx));
+extern int tls_symbolic_reference_mentioned_p PARAMS ((rtx));
+extern rtx s390_tls_get_offset PARAMS ((void));
extern int legitimate_la_operand_p PARAMS ((rtx));
-extern rtx legitimize_la_operand PARAMS ((rtx));
+extern int preferred_la_operand_p PARAMS ((rtx));
extern int legitimate_pic_operand_p PARAMS ((rtx));
extern int legitimate_constant_p PARAMS ((rtx));
extern int legitimate_reload_constant_p PARAMS ((rtx));
@@ -58,18 +62,25 @@ extern rtx legitimize_pic_address PARAMS ((rtx, rtx));
extern rtx legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
extern enum reg_class s390_preferred_reload_class PARAMS ((rtx, enum reg_class));
extern enum reg_class s390_secondary_input_reload_class PARAMS ((enum reg_class, enum machine_mode, rtx));
+extern enum reg_class s390_secondary_output_reload_class PARAMS ((enum reg_class, enum machine_mode, rtx));
extern int s390_plus_operand PARAMS ((rtx, enum machine_mode));
extern void s390_expand_plus_operand PARAMS ((rtx, rtx, rtx));
-extern void emit_pic_move PARAMS ((rtx *, enum machine_mode));
+extern void emit_symbolic_move PARAMS ((rtx *));
+extern void s390_load_address PARAMS ((rtx, rtx));
+extern void s390_expand_movstr PARAMS ((rtx, rtx, rtx));
+extern void s390_expand_clrstr PARAMS ((rtx, rtx));
+extern void s390_expand_cmpstr PARAMS ((rtx, rtx, rtx, rtx));
+extern rtx s390_return_addr_rtx PARAMS ((int, rtx));
extern void s390_output_symbolic_const PARAMS ((FILE *, rtx));
extern void print_operand_address PARAMS ((FILE *, rtx));
extern void print_operand PARAMS ((FILE *, rtx, int));
-extern void s390_output_constant_pool PARAMS ((FILE *));
+extern void s390_output_constant_pool PARAMS ((rtx, rtx));
extern void s390_trampoline_template PARAMS ((FILE *));
extern void s390_initialize_trampoline PARAMS ((rtx, rtx, rtx));
extern rtx s390_gen_rtx_const_DI PARAMS ((int, int));
extern rtx s390_simplify_dwarf_addr PARAMS ((rtx));
+extern void s390_machine_dependent_reorg PARAMS ((rtx));
#endif /* RTX_CODE */
#ifdef TREE_CODE
@@ -78,7 +89,7 @@ extern void s390_function_arg_advance PARAMS ((CUMULATIVE_ARGS *, enum machine_m
extern tree s390_build_va_list PARAMS ((void));
#ifdef RTX_CODE
extern rtx s390_function_arg PARAMS ((CUMULATIVE_ARGS *, enum machine_mode, tree, int));
-extern void s390_va_start PARAMS ((int, tree, rtx));
+extern void s390_va_start PARAMS ((tree, rtx));
extern rtx s390_va_arg PARAMS ((tree, tree));
#endif /* RTX_CODE */
#endif /* TREE_CODE */
diff --git a/contrib/gcc/config/s390/s390.c b/contrib/gcc/config/s390/s390.c
index 4c96dce..d6fda65 100644
--- a/contrib/gcc/config/s390/s390.c
+++ b/contrib/gcc/config/s390/s390.c
@@ -1,5 +1,5 @@
/* Subroutines used for code generation on IBM S/390 and zSeries
- Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com) and
Ulrich Weigand (uweigand@de.ibm.com).
@@ -45,11 +45,22 @@ Boston, MA 02111-1307, USA. */
#include "target.h"
#include "target-def.h"
#include "debug.h"
-
+#include "langhooks.h"
+#include "optabs.h"
static bool s390_assemble_integer PARAMS ((rtx, unsigned int, int));
static int s390_adjust_cost PARAMS ((rtx, rtx, rtx, int));
static int s390_adjust_priority PARAMS ((rtx, int));
+static void s390_select_rtx_section PARAMS ((enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT));
+static void s390_encode_section_info PARAMS ((tree, int));
+static const char *s390_strip_name_encoding PARAMS ((const char *));
+static bool s390_cannot_force_const_mem PARAMS ((rtx));
+static void s390_init_builtins PARAMS ((void));
+static rtx s390_expand_builtin PARAMS ((tree, rtx, rtx,
+ enum machine_mode, int));
+static void s390_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+ HOST_WIDE_INT, tree));
#undef TARGET_ASM_ALIGNED_HI_OP
#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
@@ -58,24 +69,43 @@ static int s390_adjust_priority PARAMS ((rtx, int));
#undef TARGET_ASM_INTEGER
#define TARGET_ASM_INTEGER s390_assemble_integer
-#undef TARGET_ASM_FUNCTION_PROLOGUE
-#define TARGET_ASM_FUNCTION_PROLOGUE s390_function_prologue
-
-#undef TARGET_ASM_FUNCTION_EPILOGUE
-#define TARGET_ASM_FUNCTION_EPILOGUE s390_function_epilogue
-
#undef TARGET_ASM_OPEN_PAREN
#define TARGET_ASM_OPEN_PAREN ""
#undef TARGET_ASM_CLOSE_PAREN
#define TARGET_ASM_CLOSE_PAREN ""
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION s390_select_rtx_section
+
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST s390_adjust_cost
#undef TARGET_SCHED_ADJUST_PRIORITY
#define TARGET_SCHED_ADJUST_PRIORITY s390_adjust_priority
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO s390_encode_section_info
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING s390_strip_name_encoding
+
+#ifdef HAVE_AS_TLS
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS true
+#endif
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM s390_cannot_force_const_mem
+
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS s390_init_builtins
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN s390_expand_builtin
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK s390_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
+
struct gcc_target targetm = TARGET_INITIALIZER;
extern int reload_completed;
@@ -83,13 +113,13 @@ extern int reload_completed;
/* The alias set for prologue/epilogue register save/restore. */
static int s390_sr_alias_set = 0;
-/* Function count for creating unique internal labels in a compile unit. */
-int s390_function_count = 0;
-
/* Save information from a "cmpxx" operation until the branch or scc is
emitted. */
rtx s390_compare_op0, s390_compare_op1;
+/* The encoding characters for the four TLS models present in ELF. */
+static char const tls_model_chars[] = " GLil";
+
/* Structure used to hold the components of a S/390 memory
address. A legitimate address on S/390 is of the general
form
@@ -107,19 +137,26 @@ struct s390_address
int pointer;
};
-/* Structure containing information for prologue and epilogue. */
+/* Define the structure for the machine field in struct function. */
-struct s390_frame
+struct machine_function GTY(())
{
- int frame_pointer_p;
- int return_reg_saved_p;
+ /* Label of start of initial literal pool. */
+ rtx literal_pool_label;
+
+ /* Set, if some of the fprs 8-15 need to be saved (64 bit abi). */
int save_fprs_p;
+
+ /* Number of first and last gpr to be saved, restored. */
int first_save_gpr;
int first_restore_gpr;
int last_save_gpr;
- int arg_frame_offset;
+ /* Size of stack frame. */
HOST_WIDE_INT frame_size;
+
+ /* Some local-dynamic TLS symbol name. */
+ const char *some_ld_name;
};
static int s390_match_ccmode_set PARAMS ((rtx, enum machine_mode));
@@ -127,20 +164,29 @@ static int s390_branch_condition_mask PARAMS ((rtx));
static const char *s390_branch_condition_mnemonic PARAMS ((rtx, int));
static int check_mode PARAMS ((rtx, enum machine_mode *));
static int general_s_operand PARAMS ((rtx, enum machine_mode, int));
-static int s390_decompose_address PARAMS ((rtx, struct s390_address *, int));
+static int s390_decompose_address PARAMS ((rtx, struct s390_address *));
+static rtx get_thread_pointer PARAMS ((void));
+static rtx legitimize_tls_address PARAMS ((rtx, rtx));
+static const char *get_some_local_dynamic_name PARAMS ((void));
+static int get_some_local_dynamic_name_1 PARAMS ((rtx *, void *));
static int reg_used_in_mem_p PARAMS ((int, rtx));
static int addr_generation_dependency_p PARAMS ((rtx, rtx));
-static void s390_split_branches PARAMS ((void));
+static int s390_split_branches PARAMS ((rtx, bool *));
static void find_constant_pool_ref PARAMS ((rtx, rtx *));
static void replace_constant_pool_ref PARAMS ((rtx *, rtx, rtx));
-static void s390_chunkify_pool PARAMS ((void));
-static int save_fprs_p PARAMS ((void));
+static int find_base_register_in_addr PARAMS ((struct s390_address *));
+static bool find_base_register_ref PARAMS ((rtx));
+static void replace_base_register_ref PARAMS ((rtx *, rtx));
+static void s390_optimize_prolog PARAMS ((int));
+static bool s390_fixup_clobbered_return_reg PARAMS ((rtx));
static int find_unused_clobbered_reg PARAMS ((void));
-static void s390_frame_info PARAMS ((struct s390_frame *));
+static void s390_frame_info PARAMS ((void));
static rtx save_fpr PARAMS ((rtx, int, int));
static rtx restore_fpr PARAMS ((rtx, int, int));
+static rtx save_gprs PARAMS ((rtx, int, int, int));
+static rtx restore_gprs PARAMS ((rtx, int, int, int));
static int s390_function_arg_size PARAMS ((enum machine_mode, tree));
-
+static struct machine_function * s390_init_machine_status PARAMS ((void));
/* Return true if SET either doesn't set the CC register, or else
the source and destination have matching CC modes and that
@@ -163,19 +209,28 @@ s390_match_ccmode_set (set, req_mode)
switch (set_mode)
{
case CCSmode:
- if (req_mode != CCSmode)
- return 0;
- break;
+ case CCSRmode:
case CCUmode:
- if (req_mode != CCUmode)
- return 0;
- break;
+ case CCURmode:
case CCLmode:
- if (req_mode != CCLmode)
+ case CCL1mode:
+ case CCL2mode:
+ case CCT1mode:
+ case CCT2mode:
+ case CCT3mode:
+ if (req_mode != set_mode)
return 0;
break;
+
case CCZmode:
- if (req_mode != CCSmode && req_mode != CCUmode && req_mode != CCTmode)
+ if (req_mode != CCSmode && req_mode != CCUmode && req_mode != CCTmode
+ && req_mode != CCSRmode && req_mode != CCURmode)
+ return 0;
+ break;
+
+ case CCAPmode:
+ case CCANmode:
+ if (req_mode != CCAmode)
return 0;
break;
@@ -188,7 +243,8 @@ s390_match_ccmode_set (set, req_mode)
/* Return true if every SET in INSN that sets the CC register
has source and destination with matching CC modes and that
- CC mode is at least as constrained as REQ_MODE. */
+ CC mode is at least as constrained as REQ_MODE.
+ If REQ_MODE is VOIDmode, always return false. */
int
s390_match_ccmode (insn, req_mode)
@@ -197,6 +253,10 @@ s390_match_ccmode (insn, req_mode)
{
int i;
+ /* s390_tm_ccmode returns VOIDmode to indicate failure. */
+ if (req_mode == VOIDmode)
+ return 0;
+
if (GET_CODE (PATTERN (insn)) == SET)
return s390_match_ccmode_set (PATTERN (insn), req_mode);
@@ -212,6 +272,45 @@ s390_match_ccmode (insn, req_mode)
return 1;
}
+/* If a test-under-mask instruction can be used to implement
+ (compare (and ... OP1) OP2), return the CC mode required
+ to do that. Otherwise, return VOIDmode.
+ MIXED is true if the instruction can distinguish between
+ CC1 and CC2 for mixed selected bits (TMxx), it is false
+ if the instruction cannot (TM). */
+
+enum machine_mode
+s390_tm_ccmode (op1, op2, mixed)
+ rtx op1;
+ rtx op2;
+ int mixed;
+{
+ int bit0, bit1;
+
+ /* ??? Fixme: should work on CONST_DOUBLE as well. */
+ if (GET_CODE (op1) != CONST_INT || GET_CODE (op2) != CONST_INT)
+ return VOIDmode;
+
+ /* Selected bits all zero: CC0. */
+ if (INTVAL (op2) == 0)
+ return CCTmode;
+
+ /* Selected bits all one: CC3. */
+ if (INTVAL (op2) == INTVAL (op1))
+ return CCT3mode;
+
+ /* Exactly two bits selected, mixed zeroes and ones: CC1 or CC2. */
+ if (mixed)
+ {
+ bit1 = exact_log2 (INTVAL (op2));
+ bit0 = exact_log2 (INTVAL (op1) ^ INTVAL (op2));
+ if (bit0 != -1 && bit1 != -1)
+ return bit0 > bit1 ? CCT1mode : CCT2mode;
+ }
+
+ return VOIDmode;
+}
+
/* Given a comparison code OP (EQ, NE, etc.) and the operands
OP0 and OP1 of a COMPARE, return the mode to be used for the
comparison. */
@@ -226,16 +325,49 @@ s390_select_ccmode (code, op0, op1)
{
case EQ:
case NE:
+ if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op0, 1)), 'K'))
+ return CCAPmode;
if (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
|| GET_CODE (op1) == NEG)
return CCLmode;
+ if (GET_CODE (op0) == AND)
+ {
+ /* Check whether we can potentially do it via TM. */
+ enum machine_mode ccmode;
+ ccmode = s390_tm_ccmode (XEXP (op0, 1), op1, 1);
+ if (ccmode != VOIDmode)
+ {
+ /* Relax CCTmode to CCZmode to allow fall-back to AND
+ if that turns out to be beneficial. */
+ return ccmode == CCTmode ? CCZmode : ccmode;
+ }
+ }
+
+ if (register_operand (op0, HImode)
+ && GET_CODE (op1) == CONST_INT
+ && (INTVAL (op1) == -1 || INTVAL (op1) == 65535))
+ return CCT3mode;
+ if (register_operand (op0, QImode)
+ && GET_CODE (op1) == CONST_INT
+ && (INTVAL (op1) == -1 || INTVAL (op1) == 255))
+ return CCT3mode;
+
return CCZmode;
case LE:
case LT:
case GE:
case GT:
+ if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op0, 1)), 'K'))
+ {
+ if (INTVAL (XEXP((op0), 1)) < 0)
+ return CCANmode;
+ else
+ return CCAPmode;
+ }
case UNORDERED:
case ORDERED:
case UNEQ:
@@ -244,12 +376,29 @@ s390_select_ccmode (code, op0, op1)
case UNGE:
case UNGT:
case LTGT:
+ if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)
+ && GET_CODE (op1) != CONST_INT)
+ return CCSRmode;
return CCSmode;
- case LEU:
case LTU:
case GEU:
+ if (GET_CODE (op0) == PLUS)
+ return CCL1mode;
+
+ if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)
+ && GET_CODE (op1) != CONST_INT)
+ return CCURmode;
+ return CCUmode;
+
+ case LEU:
case GTU:
+ if (GET_CODE (op0) == MINUS)
+ return CCL2mode;
+
+ if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)
+ && GET_CODE (op1) != CONST_INT)
+ return CCURmode;
return CCUmode;
default:
@@ -286,13 +435,61 @@ s390_branch_condition_mask (code)
}
break;
+ case CCT1mode:
+ switch (GET_CODE (code))
+ {
+ case EQ: return CC1;
+ case NE: return CC0 | CC2 | CC3;
+ default:
+ abort ();
+ }
+ break;
+
+ case CCT2mode:
+ switch (GET_CODE (code))
+ {
+ case EQ: return CC2;
+ case NE: return CC0 | CC1 | CC3;
+ default:
+ abort ();
+ }
+ break;
+
+ case CCT3mode:
+ switch (GET_CODE (code))
+ {
+ case EQ: return CC3;
+ case NE: return CC0 | CC1 | CC2;
+ default:
+ abort ();
+ }
+ break;
+
case CCLmode:
switch (GET_CODE (code))
{
case EQ: return CC0 | CC2;
case NE: return CC1 | CC3;
- case UNORDERED: return CC2 | CC3; /* carry */
- case ORDERED: return CC0 | CC1; /* no carry */
+ default:
+ abort ();
+ }
+ break;
+
+ case CCL1mode:
+ switch (GET_CODE (code))
+ {
+ case LTU: return CC2 | CC3; /* carry */
+ case GEU: return CC0 | CC1; /* no carry */
+ default:
+ abort ();
+ }
+ break;
+
+ case CCL2mode:
+ switch (GET_CODE (code))
+ {
+ case GTU: return CC0 | CC1; /* borrow */
+ case LEU: return CC2 | CC3; /* no borrow */
default:
abort ();
}
@@ -312,6 +509,48 @@ s390_branch_condition_mask (code)
}
break;
+ case CCURmode:
+ switch (GET_CODE (code))
+ {
+ case EQ: return CC0;
+ case NE: return CC2 | CC1 | CC3;
+ case LTU: return CC2;
+ case GTU: return CC1;
+ case LEU: return CC0 | CC2;
+ case GEU: return CC0 | CC1;
+ default:
+ abort ();
+ }
+ break;
+
+ case CCAPmode:
+ switch (GET_CODE (code))
+ {
+ case EQ: return CC0;
+ case NE: return CC1 | CC2 | CC3;
+ case LT: return CC1 | CC3;
+ case GT: return CC2;
+ case LE: return CC0 | CC1 | CC3;
+ case GE: return CC0 | CC2;
+ default:
+ abort ();
+ }
+ break;
+
+ case CCANmode:
+ switch (GET_CODE (code))
+ {
+ case EQ: return CC0;
+ case NE: return CC1 | CC2 | CC3;
+ case LT: return CC1;
+ case GT: return CC2 | CC3;
+ case LE: return CC0 | CC1;
+ case GE: return CC0 | CC2 | CC3;
+ default:
+ abort ();
+ }
+ break;
+
case CCSmode:
switch (GET_CODE (code))
{
@@ -332,6 +571,29 @@ s390_branch_condition_mask (code)
default:
abort ();
}
+ break;
+
+ case CCSRmode:
+ switch (GET_CODE (code))
+ {
+ case EQ: return CC0;
+ case NE: return CC2 | CC1 | CC3;
+ case LT: return CC2;
+ case GT: return CC1;
+ case LE: return CC0 | CC2;
+ case GE: return CC0 | CC1;
+ case UNORDERED: return CC3;
+ case ORDERED: return CC0 | CC2 | CC1;
+ case UNEQ: return CC0 | CC3;
+ case UNLT: return CC2 | CC3;
+ case UNGT: return CC1 | CC3;
+ case UNLE: return CC0 | CC2 | CC3;
+ case UNGE: return CC0 | CC1 | CC3;
+ case LTGT: return CC2 | CC1;
+ default:
+ abort ();
+ }
+ break;
default:
abort ();
@@ -347,7 +609,7 @@ s390_branch_condition_mnemonic (code, inv)
rtx code;
int inv;
{
- static const char *mnemonic[16] =
+ static const char *const mnemonic[16] =
{
NULL, "o", "h", "nle",
"l", "nhe", "lh", "ne",
@@ -379,7 +641,7 @@ s390_single_hi (op, mode, def)
{
if (GET_CODE (op) == CONST_INT)
{
- unsigned HOST_WIDE_INT value;
+ unsigned HOST_WIDE_INT value = 0;
int n_parts = GET_MODE_SIZE (mode) / 2;
int i, part = -1;
@@ -405,7 +667,7 @@ s390_single_hi (op, mode, def)
else if (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE (op) == VOIDmode)
{
- unsigned HOST_WIDE_INT value;
+ unsigned HOST_WIDE_INT value = 0;
int n_parts = GET_MODE_SIZE (mode) / 2;
int i, part = -1;
@@ -482,7 +744,7 @@ s390_single_qi (op, mode, def)
{
if (GET_CODE (op) == CONST_INT)
{
- unsigned HOST_WIDE_INT value;
+ unsigned HOST_WIDE_INT value = 0;
int n_parts = GET_MODE_SIZE (mode);
int i, part = -1;
@@ -508,7 +770,7 @@ s390_single_qi (op, mode, def)
else if (GET_CODE (op) == CONST_DOUBLE
&& GET_MODE (op) == VOIDmode)
{
- unsigned HOST_WIDE_INT value;
+ unsigned HOST_WIDE_INT value = 0;
int n_parts = GET_MODE_SIZE (mode);
int i, part = -1;
@@ -572,6 +834,42 @@ s390_extract_qi (op, mode, part)
abort ();
}
+/* Check whether we can (and want to) split a double-word
+ move in mode MODE from SRC to DST into two single-word
+ moves, moving the subword FIRST_SUBWORD first. */
+
+bool
+s390_split_ok_p (dst, src, mode, first_subword)
+ rtx dst;
+ rtx src;
+ enum machine_mode mode;
+ int first_subword;
+{
+ /* Floating point registers cannot be split. */
+ if (FP_REG_P (src) || FP_REG_P (dst))
+ return false;
+
+ /* We don't need to split if operands are directly accessable. */
+ if (s_operand (src, mode) || s_operand (dst, mode))
+ return false;
+
+ /* Non-offsettable memory references cannot be split. */
+ if ((GET_CODE (src) == MEM && !offsettable_memref_p (src))
+ || (GET_CODE (dst) == MEM && !offsettable_memref_p (dst)))
+ return false;
+
+ /* Moving the first subword must not clobber a register
+ needed to move the second subword. */
+ if (register_operand (dst, mode))
+ {
+ rtx subreg = operand_subword (dst, first_subword, 0, mode);
+ if (reg_overlap_mentioned_p (subreg, src))
+ return false;
+ }
+
+ return true;
+}
+
/* Change optimizations to be performed, depending on the
optimization level.
@@ -579,18 +877,19 @@ s390_extract_qi (op, mode, part)
LEVEL is the optimization level specified; 2 if `-O2' is
specified, 1 if `-O' is specified, and 0 if neither is specified.
- SIZE is non-zero if `-Os' is specified and zero otherwise. */
+ SIZE is nonzero if `-Os' is specified and zero otherwise. */
void
optimization_options (level, size)
int level ATTRIBUTE_UNUSED;
int size ATTRIBUTE_UNUSED;
{
-#ifdef HAVE_decrement_and_branch_on_count
- /* When optimizing, enable use of BRCT instruction. */
- if (level >= 1)
- flag_branch_on_count_reg = 1;
-#endif
+ /* ??? There are apparently still problems with -fcaller-saves. */
+ flag_caller_saves = 0;
+
+ /* By default, always emit DWARF-2 unwind info. This allows debugging
+ without maintaining a stack frame back-chain. */
+ flag_asynchronous_unwind_tables = 1;
}
void
@@ -598,12 +897,14 @@ override_options ()
{
/* Acquire a unique set number for our register saves and restores. */
s390_sr_alias_set = new_alias_set ();
-}
+ /* Set up function hooks. */
+ init_machine_status = s390_init_machine_status;
+}
/* Map for smallest class containing reg regno. */
-enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
+const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
{ GENERAL_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
@@ -674,6 +975,8 @@ larl_operand (op, mode)
if (GET_CODE (op) == LABEL_REF)
return 1;
if (GET_CODE (op) == SYMBOL_REF
+ && XSTR (op, 0)[0] != '@'
+ && !tls_symbolic_operand (op)
&& (!flag_pic || SYMBOL_REF_FLAG (op)
|| CONSTANT_POOL_ADDRESS_P (op)))
return 1;
@@ -696,39 +999,27 @@ larl_operand (op, mode)
if (GET_CODE (op) == LABEL_REF)
return 1;
if (GET_CODE (op) == SYMBOL_REF
+ && XSTR (op, 0)[0] != '@'
+ && !tls_symbolic_operand (op)
&& (!flag_pic || SYMBOL_REF_FLAG (op)
|| CONSTANT_POOL_ADDRESS_P (op)))
return 1;
- /* Now we must have a @GOTENT offset or @PLT stub. */
+ /* Now we must have a @GOTENT offset or @PLT stub
+ or an @INDNTPOFF TLS offset. */
if (GET_CODE (op) == UNSPEC
&& XINT (op, 1) == 111)
return 1;
if (GET_CODE (op) == UNSPEC
&& XINT (op, 1) == 113)
return 1;
+ if (GET_CODE (op) == UNSPEC
+ && XINT (op, 1) == UNSPEC_INDNTPOFF)
+ return 1;
return 0;
}
-/* Return true if OP is a valid FP-Register.
- OP is the current operation.
- MODE is the current operation mode. */
-
-int
-fp_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- register enum rtx_code code = GET_CODE (op);
- if (! check_mode (op, &mode))
- return 0;
- if (code == REG && REGNO_OK_FOR_FP_P (REGNO (op)))
- return 1;
- else
- return 0;
-}
-
/* Helper routine to implement s_operand and s_imm_operand.
OP is the current operation.
MODE is the current operation mode.
@@ -777,7 +1068,7 @@ general_s_operand (op, mode, allow_immediate)
case MEM:
if (GET_CODE (XEXP (op, 0)) == ADDRESSOF)
return 1;
- if (s390_decompose_address (XEXP (op, 0), &addr, FALSE)
+ if (s390_decompose_address (XEXP (op, 0), &addr)
&& !addr.indx)
return 1;
break;
@@ -815,6 +1106,41 @@ s_imm_operand (op, mode)
return general_s_operand (op, mode, 1);
}
+/* Return true if OP is a valid operand for a 'Q' constraint.
+ This differs from s_operand in that only memory operands
+ without index register are accepted, nothing else. */
+
+int
+q_constraint (op)
+ register rtx op;
+{
+ struct s390_address addr;
+
+ if (GET_CODE (op) != MEM)
+ return 0;
+
+ if (!s390_decompose_address (XEXP (op, 0), &addr))
+ return 0;
+
+ if (addr.indx)
+ return 0;
+
+ return 1;
+}
+
+/* Return the cost of an address rtx ADDR. */
+
+int
+s390_address_cost (addr)
+ rtx addr;
+{
+ struct s390_address ad;
+ if (!s390_decompose_address (addr, &ad))
+ return 1000;
+
+ return ad.indx? COSTS_N_INSNS (1) + 1 : COSTS_N_INSNS (1);
+}
+
/* Return true if OP is a valid operand for the BRAS instruction.
OP is the current operation.
MODE is the current operation mode. */
@@ -838,6 +1164,23 @@ bras_sym_operand (op, mode)
return 0;
}
+/* If OP is a SYMBOL_REF of a thread-local symbol, return its TLS mode,
+ otherwise return 0. */
+
+int
+tls_symbolic_operand (op)
+ register rtx op;
+{
+ const char *symbol_str;
+
+ if (GET_CODE (op) != SYMBOL_REF)
+ return 0;
+ symbol_str = XSTR (op, 0);
+
+ if (symbol_str[0] != '%')
+ return 0;
+ return strchr (tls_model_chars, symbol_str[1]) - tls_model_chars;
+}
/* Return true if OP is a load multiple operation. It is known to be a
PARALLEL and the first section will be tested.
@@ -997,6 +1340,37 @@ symbolic_reference_mentioned_p (op)
return 0;
}
+/* Return true if OP contains a reference to a thread-local symbol. */
+
+int
+tls_symbolic_reference_mentioned_p (op)
+ rtx op;
+{
+ register const char *fmt;
+ register int i;
+
+ if (GET_CODE (op) == SYMBOL_REF)
+ return tls_symbolic_operand (op);
+
+ fmt = GET_RTX_FORMAT (GET_CODE (op));
+ for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'E')
+ {
+ register int j;
+
+ for (j = XVECLEN (op, i) - 1; j >= 0; j--)
+ if (tls_symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
+ return 1;
+ }
+
+ else if (fmt[i] == 'e' && tls_symbolic_reference_mentioned_p (XEXP (op, i)))
+ return 1;
+ }
+
+ return 0;
+}
+
/* Return true if OP is a legitimate general operand when
generating PIC code. It is given that flag_pic is on
@@ -1011,7 +1385,7 @@ legitimate_pic_operand_p (op)
return 1;
/* Reject everything else; must be handled
- via emit_pic_move. */
+ via emit_symbolic_move. */
return 0;
}
@@ -1026,22 +1400,87 @@ legitimate_constant_p (op)
if (!SYMBOLIC_CONST (op))
return 1;
+ /* Accept immediate LARL operands. */
+ if (TARGET_64BIT && larl_operand (op, VOIDmode))
+ return 1;
+
+ /* Thread-local symbols are never legal constants. This is
+ so that emit_call knows that computing such addresses
+ might require a function call. */
+ if (TLS_SYMBOLIC_CONST (op))
+ return 0;
+
/* In the PIC case, symbolic constants must *not* be
forced into the literal pool. We accept them here,
- so that they will be handled by emit_pic_move. */
+ so that they will be handled by emit_symbolic_move. */
if (flag_pic)
return 1;
- /* Even in the non-PIC case, we can accept immediate
- LARL operands here. */
- if (TARGET_64BIT)
- return larl_operand (op, VOIDmode);
-
/* All remaining non-PIC symbolic constants are
forced into the literal pool. */
return 0;
}
+/* Determine if it's legal to put X into the constant pool. This
+ is not possible if X contains the address of a symbol that is
+ not constant (TLS) or not known at final link time (PIC). */
+
+static bool
+s390_cannot_force_const_mem (x)
+ rtx x;
+{
+ switch (GET_CODE (x))
+ {
+ case CONST_INT:
+ case CONST_DOUBLE:
+ /* Accept all non-symbolic constants. */
+ return false;
+
+ case LABEL_REF:
+ /* Labels are OK iff we are non-PIC. */
+ return flag_pic != 0;
+
+ case SYMBOL_REF:
+ /* 'Naked' TLS symbol references are never OK,
+ non-TLS symbols are OK iff we are non-PIC. */
+ if (tls_symbolic_operand (x))
+ return true;
+ else
+ return flag_pic != 0;
+
+ case CONST:
+ return s390_cannot_force_const_mem (XEXP (x, 0));
+ case PLUS:
+ case MINUS:
+ return s390_cannot_force_const_mem (XEXP (x, 0))
+ || s390_cannot_force_const_mem (XEXP (x, 1));
+
+ case UNSPEC:
+ switch (XINT (x, 1))
+ {
+ /* Only lt-relative or GOT-relative UNSPECs are OK. */
+ case 100:
+ case 104:
+ case 112:
+ case 114:
+ case UNSPEC_TLSGD:
+ case UNSPEC_TLSLDM:
+ case UNSPEC_NTPOFF:
+ case UNSPEC_DTPOFF:
+ case UNSPEC_GOTNTPOFF:
+ case UNSPEC_INDNTPOFF:
+ return false;
+
+ default:
+ return true;
+ }
+ break;
+
+ default:
+ abort ();
+ }
+}
+
/* Returns true if the constant value OP is a legitimate general
operand during and after reload. The difference to
legitimate_constant_p is that this function will not accept
@@ -1067,15 +1506,6 @@ legitimate_reload_constant_p (op)
&& larl_operand (op, VOIDmode))
return 1;
- /* If reload is completed, and we do not already have a
- literal pool, and OP must be forced to the literal
- pool, then something must have gone wrong earlier.
- We *cannot* force the constant any more, because the
- prolog generation already decided we don't need to
- set up the base register. */
- if (reload_completed && !regs_ever_live[BASE_REGISTER])
- abort ();
-
/* Everything else cannot be handled without reload. */
return 0;
}
@@ -1097,23 +1527,14 @@ s390_preferred_reload_class (op, class)
switch (GET_CODE (op))
{
/* Constants we cannot reload must be forced into the
- literal pool. For constants we *could* handle directly,
- it might still be preferable to put them in the pool and
- use a memory-to-memory instruction.
-
- However, try to avoid needlessly allocating a literal
- pool in a routine that wouldn't otherwise need any.
- Heuristically, we assume that 64-bit leaf functions
- typically don't need a literal pool, all others do. */
+ literal pool. */
+
case CONST_DOUBLE:
case CONST_INT:
- if (!legitimate_reload_constant_p (op))
- return NO_REGS;
-
- if (TARGET_64BIT && current_function_is_leaf)
+ if (legitimate_reload_constant_p (op))
return class;
-
- return NO_REGS;
+ else
+ return NO_REGS;
/* If a symbolic constant or a PLUS is reloaded,
it is most likely being used as an address, so
@@ -1153,6 +1574,29 @@ s390_secondary_input_reload_class (class, mode, in)
return NO_REGS;
}
+/* Return the register class of a scratch register needed to
+ store a register of class CLASS in MODE into OUT:
+
+ We need a temporary when storing a double-word to a
+ non-offsettable memory address. */
+
+enum reg_class
+s390_secondary_output_reload_class (class, mode, out)
+ enum reg_class class;
+ enum machine_mode mode;
+ rtx out;
+{
+ if ((TARGET_64BIT ? mode == TImode
+ : (mode == DImode || mode == DFmode))
+ && reg_classes_intersect_p (GENERAL_REGS, class)
+ && GET_CODE (out) == MEM
+ && !offsettable_memref_p (out)
+ && !s_operand (out, VOIDmode))
+ return ADDR_REGS;
+
+ return NO_REGS;
+}
+
/* Return true if OP is a PLUS that is not a legitimate
operand for the LA instruction.
OP is the current operation.
@@ -1180,21 +1624,13 @@ s390_plus_operand (op, mode)
SCRATCH may be used as scratch register. */
void
-s390_expand_plus_operand (target, src, scratch_in)
+s390_expand_plus_operand (target, src, scratch)
register rtx target;
register rtx src;
- register rtx scratch_in;
+ register rtx scratch;
{
- rtx sum1, sum2, scratch;
-
- /* ??? reload apparently does not ensure that the scratch register
- and the target do not overlap. We absolutely require this to be
- the case, however. Therefore the reload_in[sd]i patterns ask for
- a double-sized scratch register, and if one part happens to be
- equal to the target, we use the other one. */
- scratch = gen_rtx_REG (Pmode, REGNO (scratch_in));
- if (rtx_equal_p (scratch, target))
- scratch = gen_rtx_REG (Pmode, REGNO (scratch_in) + 1);
+ rtx sum1, sum2;
+ struct s390_address ad;
/* src must be a PLUS; get its two operands. */
if (GET_CODE (src) != PLUS || GET_MODE (src) != Pmode)
@@ -1205,58 +1641,49 @@ s390_expand_plus_operand (target, src, scratch_in)
float registers occur in an address. */
sum1 = find_replacement (&XEXP (src, 0));
sum2 = find_replacement (&XEXP (src, 1));
+ src = gen_rtx_PLUS (Pmode, sum1, sum2);
- /* If one of the two operands is equal to the target,
- make it the first one. If one is a constant, make
- it the second one. */
- if (rtx_equal_p (target, sum2)
- || GET_CODE (sum1) == CONST_INT)
+ /* If the address is already strictly valid, there's nothing to do. */
+ if (!s390_decompose_address (src, &ad)
+ || (ad.base && !REG_OK_FOR_BASE_STRICT_P (ad.base))
+ || (ad.indx && !REG_OK_FOR_INDEX_STRICT_P (ad.indx)))
{
- rtx tem = sum2;
- sum2 = sum1;
- sum1 = tem;
- }
+ /* Otherwise, one of the operands cannot be an address register;
+ we reload its value into the scratch register. */
+ if (true_regnum (sum1) < 1 || true_regnum (sum1) > 15)
+ {
+ emit_move_insn (scratch, sum1);
+ sum1 = scratch;
+ }
+ if (true_regnum (sum2) < 1 || true_regnum (sum2) > 15)
+ {
+ emit_move_insn (scratch, sum2);
+ sum2 = scratch;
+ }
- /* If the first operand is not an address register,
- we reload it into the target. */
- if (true_regnum (sum1) < 1 || true_regnum (sum1) > 15)
- {
- emit_move_insn (target, sum1);
- sum1 = target;
- }
+ /* According to the way these invalid addresses are generated
+ in reload.c, it should never happen (at least on s390) that
+ *neither* of the PLUS components, after find_replacements
+ was applied, is an address register. */
+ if (sum1 == scratch && sum2 == scratch)
+ {
+ debug_rtx (src);
+ abort ();
+ }
- /* Likewise for the second operand. However, take
- care not to clobber the target if we already used
- it for the first operand. Use the scratch instead.
- Also, allow an immediate offset if it is in range. */
- if ((true_regnum (sum2) < 1 || true_regnum (sum2) > 15)
- && !(GET_CODE (sum2) == CONST_INT
- && INTVAL (sum2) >= 0 && INTVAL (sum2) < 4096))
- {
- if (!rtx_equal_p (target, sum1))
- {
- emit_move_insn (target, sum2);
- sum2 = target;
- }
- else
- {
- emit_move_insn (scratch, sum2);
- sum2 = scratch;
- }
+ src = gen_rtx_PLUS (Pmode, sum1, sum2);
}
/* Emit the LOAD ADDRESS pattern. Note that reload of PLUS
is only ever performed on addresses, so we can mark the
sum as legitimate for LA in any case. */
- src = gen_rtx_PLUS (Pmode, sum1, sum2);
- src = legitimize_la_operand (src);
- emit_insn (gen_rtx_SET (VOIDmode, target, src));
+ s390_load_address (target, src);
}
/* Decompose a RTL expression ADDR for a memory address into
- its components, returned in OUT. The boolean STRICT
- specifies whether strict register checking applies.
+ its components, returned in OUT.
+
Returns 0 if ADDR is not a valid memory address, nonzero
otherwise. If OUT is NULL, don't return the components,
but check for validity only.
@@ -1266,10 +1693,9 @@ s390_expand_plus_operand (target, src, scratch_in)
canonical form so that they will be recognized. */
static int
-s390_decompose_address (addr, out, strict)
+s390_decompose_address (addr, out)
register rtx addr;
struct s390_address *out;
- int strict;
{
rtx base = NULL_RTX;
rtx indx = NULL_RTX;
@@ -1320,6 +1746,22 @@ s390_decompose_address (addr, out, strict)
disp = addr; /* displacement */
+ /* Prefer to use pointer as base, not index. */
+ if (base && indx)
+ {
+ int base_ptr = GET_CODE (base) == UNSPEC
+ || (REG_P (base) && REG_POINTER (base));
+ int indx_ptr = GET_CODE (indx) == UNSPEC
+ || (REG_P (indx) && REG_POINTER (indx));
+
+ if (!base_ptr && indx_ptr)
+ {
+ rtx tmp = base;
+ base = indx;
+ indx = tmp;
+ }
+ }
+
/* Validate base register. */
if (base)
{
@@ -1334,16 +1776,15 @@ s390_decompose_address (addr, out, strict)
if (GET_CODE (base) != REG || GET_MODE (base) != Pmode)
return FALSE;
- if ((strict && ! REG_OK_FOR_BASE_STRICT_P (base))
- || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (base)))
- return FALSE;
-
if (REGNO (base) == BASE_REGISTER
|| REGNO (base) == STACK_POINTER_REGNUM
|| REGNO (base) == FRAME_POINTER_REGNUM
|| ((reload_completed || reload_in_progress)
&& frame_pointer_needed
&& REGNO (base) == HARD_FRAME_POINTER_REGNUM)
+ || REGNO (base) == ARG_POINTER_REGNUM
+ || (REGNO (base) >= FIRST_VIRTUAL_REGISTER
+ && REGNO (base) <= LAST_VIRTUAL_REGISTER)
|| (flag_pic
&& REGNO (base) == PIC_OFFSET_TABLE_REGNUM))
pointer = TRUE;
@@ -1363,16 +1804,15 @@ s390_decompose_address (addr, out, strict)
if (GET_CODE (indx) != REG || GET_MODE (indx) != Pmode)
return FALSE;
- if ((strict && ! REG_OK_FOR_BASE_STRICT_P (indx))
- || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (indx)))
- return FALSE;
-
if (REGNO (indx) == BASE_REGISTER
|| REGNO (indx) == STACK_POINTER_REGNUM
|| REGNO (indx) == FRAME_POINTER_REGNUM
|| ((reload_completed || reload_in_progress)
&& frame_pointer_needed
&& REGNO (indx) == HARD_FRAME_POINTER_REGNUM)
+ || REGNO (indx) == ARG_POINTER_REGNUM
+ || (REGNO (indx) >= FIRST_VIRTUAL_REGISTER
+ && REGNO (indx) <= LAST_VIRTUAL_REGISTER)
|| (flag_pic
&& REGNO (indx) == PIC_OFFSET_TABLE_REGNUM))
pointer = TRUE;
@@ -1384,15 +1824,27 @@ s390_decompose_address (addr, out, strict)
/* Allow integer constant in range. */
if (GET_CODE (disp) == CONST_INT)
{
- if (INTVAL (disp) < 0 || INTVAL (disp) >= 4096)
- return FALSE;
+ /* If the argument pointer is involved, the displacement will change
+ later anyway as the argument pointer gets eliminated. This could
+ make a valid displacement invalid, but it is more likely to make
+ an invalid displacement valid, because we sometimes access the
+ register save area via negative offsets to the arg pointer.
+ Thus we don't check the displacement for validity here. If after
+ elimination the displacement turns out to be invalid after all,
+ this is fixed up by reload in any case. */
+ if (base != arg_pointer_rtx && indx != arg_pointer_rtx)
+ {
+ if (INTVAL (disp) < 0 || INTVAL (disp) >= 4096)
+ return FALSE;
+ }
}
/* In the small-PIC case, the linker converts @GOT12
- offsets to possible displacements. */
+ and @GOTNTPOFF offsets to possible displacements. */
else if (GET_CODE (disp) == CONST
&& GET_CODE (XEXP (disp, 0)) == UNSPEC
- && XINT (XEXP (disp, 0), 1) == 110)
+ && (XINT (XEXP (disp, 0), 1) == 110
+ || XINT (XEXP (disp, 0), 1) == UNSPEC_GOTNTPOFF))
{
if (flag_pic != 1)
return FALSE;
@@ -1442,12 +1894,6 @@ s390_decompose_address (addr, out, strict)
|| !CONSTANT_POOL_ADDRESS_P (disp))
return FALSE;
- /* In 64-bit PIC mode we cannot accept symbolic
- constants in the constant pool. */
- if (TARGET_64BIT && flag_pic
- && SYMBOLIC_CONST (get_pool_constant (disp)))
- return FALSE;
-
/* If we have an offset, make sure it does not
exceed the size of the constant pool entry. */
if (offset && offset >= GET_MODE_SIZE (get_pool_mode (disp)))
@@ -1497,7 +1943,26 @@ legitimate_address_p (mode, addr, strict)
register rtx addr;
int strict;
{
- return s390_decompose_address (addr, NULL, strict);
+ struct s390_address ad;
+ if (!s390_decompose_address (addr, &ad))
+ return FALSE;
+
+ if (strict)
+ {
+ if (ad.base && !REG_OK_FOR_BASE_STRICT_P (ad.base))
+ return FALSE;
+ if (ad.indx && !REG_OK_FOR_INDEX_STRICT_P (ad.indx))
+ return FALSE;
+ }
+ else
+ {
+ if (ad.base && !REG_OK_FOR_BASE_NONSTRICT_P (ad.base))
+ return FALSE;
+ if (ad.indx && !REG_OK_FOR_INDEX_NONSTRICT_P (ad.indx))
+ return FALSE;
+ }
+
+ return TRUE;
}
/* Return 1 if OP is a valid operand for the LA instruction.
@@ -1509,7 +1974,7 @@ legitimate_la_operand_p (op)
register rtx op;
{
struct s390_address addr;
- if (!s390_decompose_address (op, &addr, FALSE))
+ if (!s390_decompose_address (op, &addr))
return FALSE;
if (TARGET_64BIT || addr.pointer)
@@ -1518,30 +1983,43 @@ legitimate_la_operand_p (op)
return FALSE;
}
-/* Return a modified variant of OP that is guaranteed to
- be accepted by legitimate_la_operand_p. */
-
-rtx
-legitimize_la_operand (op)
+/* Return 1 if OP is a valid operand for the LA instruction,
+ and we prefer to use LA over addition to compute it. */
+
+int
+preferred_la_operand_p (op)
register rtx op;
{
struct s390_address addr;
- if (!s390_decompose_address (op, &addr, FALSE))
- abort ();
+ if (!s390_decompose_address (op, &addr))
+ return FALSE;
- if (TARGET_64BIT || addr.pointer)
- return op;
+ if (!TARGET_64BIT && !addr.pointer)
+ return FALSE;
- if (!addr.base)
- abort ();
+ if (addr.pointer)
+ return TRUE;
- op = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr.base), 101);
- if (addr.indx)
- op = gen_rtx_PLUS (Pmode, op, addr.indx);
- if (addr.disp)
- op = gen_rtx_PLUS (Pmode, op, addr.disp);
+ if ((addr.base && REG_P (addr.base) && REG_POINTER (addr.base))
+ || (addr.indx && REG_P (addr.indx) && REG_POINTER (addr.indx)))
+ return TRUE;
- return op;
+ return FALSE;
+}
+
+/* Emit a forced load-address operation to load SRC into DST.
+ This will use the LOAD ADDRESS instruction even in situations
+ where legitimate_la_operand_p (SRC) returns false. */
+
+void
+s390_load_address (dst, src)
+ rtx dst;
+ rtx src;
+{
+ if (TARGET_64BIT)
+ emit_move_insn (dst, src);
+ else
+ emit_insn (gen_force_la_31 (dst, src));
}
/* Return a legitimate reference for ORIG (an address) using the
@@ -1577,7 +2055,7 @@ legitimize_pic_address (orig, reg)
|| CONSTANT_POOL_ADDRESS_P (addr))))
{
/* This is a local symbol. */
- if (TARGET_64BIT)
+ if (TARGET_64BIT && larl_operand (addr, VOIDmode))
{
/* Access local symbols PC-relative via LARL.
This is the same as in the non-PIC case, so it is
@@ -1589,9 +2067,9 @@ legitimize_pic_address (orig, reg)
rtx temp = reg? reg : gen_reg_rtx (Pmode);
- addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, addr), 100);
- addr = gen_rtx_CONST (SImode, addr);
- addr = force_const_mem (SImode, addr);
+ addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 100);
+ addr = gen_rtx_CONST (Pmode, addr);
+ addr = force_const_mem (Pmode, addr);
emit_move_insn (temp, addr);
base = gen_rtx_REG (Pmode, BASE_REGISTER);
@@ -1615,7 +2093,8 @@ legitimize_pic_address (orig, reg)
/* Assume GOT offset < 4k. This is handled the same way
in both 31- and 64-bit code (@GOT12). */
- current_function_uses_pic_offset_table = 1;
+ if (reload_in_progress || reload_completed)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 110);
new = gen_rtx_CONST (Pmode, new);
@@ -1648,11 +2127,12 @@ legitimize_pic_address (orig, reg)
rtx temp = gen_reg_rtx (Pmode);
- current_function_uses_pic_offset_table = 1;
+ if (reload_in_progress || reload_completed)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
- addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, addr), 112);
- addr = gen_rtx_CONST (SImode, addr);
- addr = force_const_mem (SImode, addr);
+ addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 112);
+ addr = gen_rtx_CONST (Pmode, addr);
+ addr = force_const_mem (Pmode, addr);
emit_move_insn (temp, addr);
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
@@ -1678,7 +2158,7 @@ legitimize_pic_address (orig, reg)
case 100:
case 112:
case 114:
- new = force_const_mem (SImode, orig);
+ new = force_const_mem (Pmode, orig);
break;
/* @GOTENT is OK as is. */
@@ -1693,9 +2173,9 @@ legitimize_pic_address (orig, reg)
rtx temp = reg? reg : gen_reg_rtx (Pmode);
addr = XVECEXP (addr, 0, 0);
- addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, addr), 114);
- addr = gen_rtx_CONST (SImode, addr);
- addr = force_const_mem (SImode, addr);
+ addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 114);
+ addr = gen_rtx_CONST (Pmode, addr);
+ addr = force_const_mem (Pmode, addr);
emit_move_insn (temp, addr);
base = gen_rtx_REG (Pmode, BASE_REGISTER);
@@ -1729,7 +2209,7 @@ legitimize_pic_address (orig, reg)
|| CONSTANT_POOL_ADDRESS_P (op0))))
&& GET_CODE (op1) == CONST_INT)
{
- if (TARGET_64BIT)
+ if (TARGET_64BIT && larl_operand (op0, VOIDmode))
{
if (INTVAL (op1) & 1)
{
@@ -1766,10 +2246,10 @@ legitimize_pic_address (orig, reg)
rtx temp = reg? reg : gen_reg_rtx (Pmode);
- addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, op0), 100);
- addr = gen_rtx_PLUS (SImode, addr, op1);
- addr = gen_rtx_CONST (SImode, addr);
- addr = force_const_mem (SImode, addr);
+ addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), 100);
+ addr = gen_rtx_PLUS (Pmode, addr, op1);
+ addr = gen_rtx_CONST (Pmode, addr);
+ addr = force_const_mem (Pmode, addr);
emit_move_insn (temp, addr);
base = gen_rtx_REG (Pmode, BASE_REGISTER);
@@ -1795,7 +2275,7 @@ legitimize_pic_address (orig, reg)
if (XINT (op0, 1) != 100)
abort ();
- new = force_const_mem (SImode, orig);
+ new = force_const_mem (Pmode, orig);
}
/* Otherwise, compute the sum. */
@@ -1825,18 +2305,237 @@ legitimize_pic_address (orig, reg)
return new;
}
+/* Load the thread pointer into a register. */
+
+static rtx
+get_thread_pointer ()
+{
+ rtx tp;
+
+ tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP);
+ tp = force_reg (Pmode, tp);
+ mark_reg_pointer (tp, BITS_PER_WORD);
+
+ return tp;
+}
+
+/* Construct the SYMBOL_REF for the tls_get_offset function. */
+
+static GTY(()) rtx s390_tls_symbol;
+rtx
+s390_tls_get_offset ()
+{
+ if (!s390_tls_symbol)
+ s390_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_offset");
+
+ return s390_tls_symbol;
+}
+
+/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
+ this (thread-local) address. REG may be used as temporary. */
+
+static rtx
+legitimize_tls_address (addr, reg)
+ rtx addr;
+ rtx reg;
+{
+ rtx new, tls_call, temp, base, r2, insn;
+
+ if (GET_CODE (addr) == SYMBOL_REF)
+ switch (tls_symbolic_operand (addr))
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ start_sequence ();
+ r2 = gen_rtx_REG (Pmode, 2);
+ tls_call = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_TLSGD);
+ new = gen_rtx_CONST (Pmode, tls_call);
+ new = force_const_mem (Pmode, new);
+ emit_move_insn (r2, new);
+ emit_call_insn (gen_call_value_tls (r2, tls_call));
+ insn = get_insns ();
+ end_sequence ();
+
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_NTPOFF);
+ temp = gen_reg_rtx (Pmode);
+ emit_libcall_block (insn, temp, r2, new);
+
+ new = gen_rtx_PLUS (Pmode, get_thread_pointer (), temp);
+ if (reg != 0)
+ {
+ s390_load_address (reg, new);
+ new = reg;
+ }
+ break;
+
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ start_sequence ();
+ r2 = gen_rtx_REG (Pmode, 2);
+ tls_call = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TLSLDM);
+ new = gen_rtx_CONST (Pmode, tls_call);
+ new = force_const_mem (Pmode, new);
+ emit_move_insn (r2, new);
+ emit_call_insn (gen_call_value_tls (r2, tls_call));
+ insn = get_insns ();
+ end_sequence ();
+
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TLSLDM_NTPOFF);
+ temp = gen_reg_rtx (Pmode);
+ emit_libcall_block (insn, temp, r2, new);
+
+ new = gen_rtx_PLUS (Pmode, get_thread_pointer (), temp);
+ base = gen_reg_rtx (Pmode);
+ s390_load_address (base, new);
+
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_DTPOFF);
+ new = gen_rtx_CONST (Pmode, new);
+ new = force_const_mem (Pmode, new);
+ temp = gen_reg_rtx (Pmode);
+ emit_move_insn (temp, new);
+
+ new = gen_rtx_PLUS (Pmode, base, temp);
+ if (reg != 0)
+ {
+ s390_load_address (reg, new);
+ new = reg;
+ }
+ break;
+
+ case TLS_MODEL_INITIAL_EXEC:
+ if (flag_pic == 1)
+ {
+ /* Assume GOT offset < 4k. This is handled the same way
+ in both 31- and 64-bit code. */
+
+ if (reload_in_progress || reload_completed)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTNTPOFF);
+ new = gen_rtx_CONST (Pmode, new);
+ new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
+ new = gen_rtx_MEM (Pmode, new);
+ RTX_UNCHANGING_P (new) = 1;
+ temp = gen_reg_rtx (Pmode);
+ emit_move_insn (temp, new);
+ }
+ else if (TARGET_64BIT)
+ {
+ /* If the GOT offset might be >= 4k, we determine the position
+ of the GOT entry via a PC-relative LARL. */
+
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_INDNTPOFF);
+ new = gen_rtx_CONST (Pmode, new);
+ temp = gen_reg_rtx (Pmode);
+ emit_move_insn (temp, new);
+
+ new = gen_rtx_MEM (Pmode, temp);
+ RTX_UNCHANGING_P (new) = 1;
+ temp = gen_reg_rtx (Pmode);
+ emit_move_insn (temp, new);
+ }
+ else if (flag_pic)
+ {
+ /* If the GOT offset might be >= 4k, we have to load it
+ from the literal pool. */
+
+ if (reload_in_progress || reload_completed)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTNTPOFF);
+ new = gen_rtx_CONST (Pmode, new);
+ new = force_const_mem (Pmode, new);
+ temp = gen_reg_rtx (Pmode);
+ emit_move_insn (temp, new);
+
+ new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
+ new = gen_rtx_MEM (Pmode, new);
+ RTX_UNCHANGING_P (new) = 1;
+
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, new, addr), UNSPEC_TLS_LOAD);
+ temp = gen_reg_rtx (Pmode);
+ emit_insn (gen_rtx_SET (Pmode, temp, new));
+ }
+ else
+ {
+ /* In position-dependent code, load the absolute address of
+ the GOT entry from the literal pool. */
+
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_INDNTPOFF);
+ new = gen_rtx_CONST (Pmode, new);
+ new = force_const_mem (Pmode, new);
+ temp = gen_reg_rtx (Pmode);
+ emit_move_insn (temp, new);
+
+ new = temp;
+ new = gen_rtx_MEM (Pmode, new);
+ RTX_UNCHANGING_P (new) = 1;
+
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, new, addr), UNSPEC_TLS_LOAD);
+ temp = gen_reg_rtx (Pmode);
+ emit_insn (gen_rtx_SET (Pmode, temp, new));
+ }
+
+ new = gen_rtx_PLUS (Pmode, get_thread_pointer (), temp);
+ if (reg != 0)
+ {
+ s390_load_address (reg, new);
+ new = reg;
+ }
+ break;
+
+ case TLS_MODEL_LOCAL_EXEC:
+ new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_NTPOFF);
+ new = gen_rtx_CONST (Pmode, new);
+ new = force_const_mem (Pmode, new);
+ temp = gen_reg_rtx (Pmode);
+ emit_move_insn (temp, new);
+
+ new = gen_rtx_PLUS (Pmode, get_thread_pointer (), temp);
+ if (reg != 0)
+ {
+ s390_load_address (reg, new);
+ new = reg;
+ }
+ break;
+
+ default:
+ abort ();
+ }
+
+ else if (GET_CODE (addr) == CONST && GET_CODE (XEXP (addr, 0)) == UNSPEC)
+ {
+ switch (XINT (XEXP (addr, 0), 1))
+ {
+ case UNSPEC_INDNTPOFF:
+ if (TARGET_64BIT)
+ new = addr;
+ else
+ abort ();
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ else
+ abort (); /* for now ... */
+
+ return new;
+}
+
/* Emit insns to move operands[1] into operands[0]. */
void
-emit_pic_move (operands, mode)
+emit_symbolic_move (operands)
rtx *operands;
- enum machine_mode mode ATTRIBUTE_UNUSED;
{
rtx temp = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
- if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
+ if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (Pmode, operands[1]);
- else
+ else if (TLS_SYMBOLIC_CONST (operands[1]))
+ operands[1] = legitimize_tls_address (operands[1], temp);
+ else if (flag_pic)
operands[1] = legitimize_pic_address (operands[1], temp);
}
@@ -1859,7 +2558,14 @@ legitimize_address (x, oldx, mode)
{
rtx constant_term = const0_rtx;
- if (flag_pic)
+ if (TLS_SYMBOLIC_CONST (x))
+ {
+ x = legitimize_tls_address (x, 0);
+
+ if (legitimate_address_p (mode, x, FALSE))
+ return x;
+ }
+ else if (flag_pic)
{
if (SYMBOLIC_CONST (x)
|| (GET_CODE (x) == PLUS
@@ -1873,6 +2579,31 @@ legitimize_address (x, oldx, mode)
x = eliminate_constant_term (x, &constant_term);
+ /* Optimize loading of large displacements by splitting them
+ into the multiple of 4K and the rest; this allows the
+ former to be CSE'd if possible.
+
+ Don't do this if the displacement is added to a register
+ pointing into the stack frame, as the offsets will
+ change later anyway. */
+
+ if (GET_CODE (constant_term) == CONST_INT
+ && (INTVAL (constant_term) < 0
+ || INTVAL (constant_term) >= 4096)
+ && !(REG_P (x) && REGNO_PTR_FRAME_P (REGNO (x))))
+ {
+ HOST_WIDE_INT lower = INTVAL (constant_term) & 0xfff;
+ HOST_WIDE_INT upper = INTVAL (constant_term) ^ lower;
+
+ rtx temp = gen_reg_rtx (Pmode);
+ rtx val = force_operand (GEN_INT (upper), temp);
+ if (val != temp)
+ emit_move_insn (temp, val);
+
+ x = gen_rtx_PLUS (Pmode, x, temp);
+ constant_term = GEN_INT (lower);
+ }
+
if (GET_CODE (x) == PLUS)
{
if (GET_CODE (XEXP (x, 0)) == REG)
@@ -1902,6 +2633,316 @@ legitimize_address (x, oldx, mode)
return x;
}
+/* Emit code to move LEN bytes from DST to SRC. */
+
+void
+s390_expand_movstr (dst, src, len)
+ rtx dst;
+ rtx src;
+ rtx len;
+{
+ rtx (*gen_short) PARAMS ((rtx, rtx, rtx)) =
+ TARGET_64BIT ? gen_movstr_short_64 : gen_movstr_short_31;
+ rtx (*gen_long) PARAMS ((rtx, rtx, rtx, rtx)) =
+ TARGET_64BIT ? gen_movstr_long_64 : gen_movstr_long_31;
+
+
+ if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
+ {
+ if (INTVAL (len) > 0)
+ emit_insn ((*gen_short) (dst, src, GEN_INT (INTVAL (len) - 1)));
+ }
+
+ else if (TARGET_MVCLE)
+ {
+ enum machine_mode double_mode = TARGET_64BIT ? TImode : DImode;
+ enum machine_mode single_mode = TARGET_64BIT ? DImode : SImode;
+ rtx reg0 = gen_reg_rtx (double_mode);
+ rtx reg1 = gen_reg_rtx (double_mode);
+
+ emit_move_insn (gen_highpart (single_mode, reg0),
+ force_operand (XEXP (dst, 0), NULL_RTX));
+ emit_move_insn (gen_highpart (single_mode, reg1),
+ force_operand (XEXP (src, 0), NULL_RTX));
+
+ convert_move (gen_lowpart (single_mode, reg0), len, 1);
+ convert_move (gen_lowpart (single_mode, reg1), len, 1);
+
+ emit_insn ((*gen_long) (reg0, reg1, reg0, reg1));
+ }
+
+ else
+ {
+ rtx dst_addr, src_addr, count, blocks, temp;
+ rtx end_label = gen_label_rtx ();
+ enum machine_mode mode;
+ tree type;
+
+ mode = GET_MODE (len);
+ if (mode == VOIDmode)
+ mode = word_mode;
+
+ type = (*lang_hooks.types.type_for_mode) (mode, 1);
+ if (!type)
+ abort ();
+
+ dst_addr = gen_reg_rtx (Pmode);
+ src_addr = gen_reg_rtx (Pmode);
+ count = gen_reg_rtx (mode);
+ blocks = gen_reg_rtx (mode);
+
+ convert_move (count, len, 1);
+ emit_cmp_and_jump_insns (count, const0_rtx,
+ EQ, NULL_RTX, mode, 1, end_label);
+
+ emit_move_insn (dst_addr, force_operand (XEXP (dst, 0), NULL_RTX));
+ emit_move_insn (src_addr, force_operand (XEXP (src, 0), NULL_RTX));
+ dst = change_address (dst, VOIDmode, dst_addr);
+ src = change_address (src, VOIDmode, src_addr);
+
+ temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1, 0);
+ if (temp != count)
+ emit_move_insn (count, temp);
+
+ temp = expand_binop (mode, ashr_optab, count, GEN_INT (8), blocks, 1, 0);
+ if (temp != blocks)
+ emit_move_insn (blocks, temp);
+
+ expand_start_loop (1);
+ expand_exit_loop_top_cond (0, build (NE_EXPR, type,
+ make_tree (type, blocks),
+ make_tree (type, const0_rtx)));
+
+ emit_insn ((*gen_short) (dst, src, GEN_INT (255)));
+ s390_load_address (dst_addr,
+ gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256)));
+ s390_load_address (src_addr,
+ gen_rtx_PLUS (Pmode, src_addr, GEN_INT (256)));
+
+ temp = expand_binop (mode, add_optab, blocks, constm1_rtx, blocks, 1, 0);
+ if (temp != blocks)
+ emit_move_insn (blocks, temp);
+
+ expand_end_loop ();
+
+ emit_insn ((*gen_short) (dst, src, convert_to_mode (word_mode, count, 1)));
+ emit_label (end_label);
+ }
+}
+
+/* Emit code to clear LEN bytes at DST. */
+
+void
+s390_expand_clrstr (dst, len)
+ rtx dst;
+ rtx len;
+{
+ rtx (*gen_short) PARAMS ((rtx, rtx)) =
+ TARGET_64BIT ? gen_clrstr_short_64 : gen_clrstr_short_31;
+ rtx (*gen_long) PARAMS ((rtx, rtx, rtx)) =
+ TARGET_64BIT ? gen_clrstr_long_64 : gen_clrstr_long_31;
+
+
+ if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
+ {
+ if (INTVAL (len) > 0)
+ emit_insn ((*gen_short) (dst, GEN_INT (INTVAL (len) - 1)));
+ }
+
+ else if (TARGET_MVCLE)
+ {
+ enum machine_mode double_mode = TARGET_64BIT ? TImode : DImode;
+ enum machine_mode single_mode = TARGET_64BIT ? DImode : SImode;
+ rtx reg0 = gen_reg_rtx (double_mode);
+ rtx reg1 = gen_reg_rtx (double_mode);
+
+ emit_move_insn (gen_highpart (single_mode, reg0),
+ force_operand (XEXP (dst, 0), NULL_RTX));
+ convert_move (gen_lowpart (single_mode, reg0), len, 1);
+
+ emit_move_insn (gen_highpart (single_mode, reg1), const0_rtx);
+ emit_move_insn (gen_lowpart (single_mode, reg1), const0_rtx);
+
+ emit_insn ((*gen_long) (reg0, reg1, reg0));
+ }
+
+ else
+ {
+ rtx dst_addr, src_addr, count, blocks, temp;
+ rtx end_label = gen_label_rtx ();
+ enum machine_mode mode;
+ tree type;
+
+ mode = GET_MODE (len);
+ if (mode == VOIDmode)
+ mode = word_mode;
+
+ type = (*lang_hooks.types.type_for_mode) (mode, 1);
+ if (!type)
+ abort ();
+
+ dst_addr = gen_reg_rtx (Pmode);
+ src_addr = gen_reg_rtx (Pmode);
+ count = gen_reg_rtx (mode);
+ blocks = gen_reg_rtx (mode);
+
+ convert_move (count, len, 1);
+ emit_cmp_and_jump_insns (count, const0_rtx,
+ EQ, NULL_RTX, mode, 1, end_label);
+
+ emit_move_insn (dst_addr, force_operand (XEXP (dst, 0), NULL_RTX));
+ dst = change_address (dst, VOIDmode, dst_addr);
+
+ temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1, 0);
+ if (temp != count)
+ emit_move_insn (count, temp);
+
+ temp = expand_binop (mode, ashr_optab, count, GEN_INT (8), blocks, 1, 0);
+ if (temp != blocks)
+ emit_move_insn (blocks, temp);
+
+ expand_start_loop (1);
+ expand_exit_loop_top_cond (0, build (NE_EXPR, type,
+ make_tree (type, blocks),
+ make_tree (type, const0_rtx)));
+
+ emit_insn ((*gen_short) (dst, GEN_INT (255)));
+ s390_load_address (dst_addr,
+ gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256)));
+
+ temp = expand_binop (mode, add_optab, blocks, constm1_rtx, blocks, 1, 0);
+ if (temp != blocks)
+ emit_move_insn (blocks, temp);
+
+ expand_end_loop ();
+
+ emit_insn ((*gen_short) (dst, convert_to_mode (word_mode, count, 1)));
+ emit_label (end_label);
+ }
+}
+
+/* Emit code to compare LEN bytes at OP0 with those at OP1,
+ and return the result in TARGET. */
+
+void
+s390_expand_cmpstr (target, op0, op1, len)
+ rtx target;
+ rtx op0;
+ rtx op1;
+ rtx len;
+{
+ rtx (*gen_short) PARAMS ((rtx, rtx, rtx)) =
+ TARGET_64BIT ? gen_cmpstr_short_64 : gen_cmpstr_short_31;
+ rtx (*gen_long) PARAMS ((rtx, rtx, rtx, rtx)) =
+ TARGET_64BIT ? gen_cmpstr_long_64 : gen_cmpstr_long_31;
+ rtx (*gen_result) PARAMS ((rtx)) =
+ GET_MODE (target) == DImode ? gen_cmpint_di : gen_cmpint_si;
+
+ op0 = protect_from_queue (op0, 0);
+ op1 = protect_from_queue (op1, 0);
+ len = protect_from_queue (len, 0);
+
+ if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
+ {
+ if (INTVAL (len) > 0)
+ {
+ emit_insn ((*gen_short) (op0, op1, GEN_INT (INTVAL (len) - 1)));
+ emit_insn ((*gen_result) (target));
+ }
+ else
+ emit_move_insn (target, const0_rtx);
+ }
+
+ else /* if (TARGET_MVCLE) */
+ {
+ enum machine_mode double_mode = TARGET_64BIT ? TImode : DImode;
+ enum machine_mode single_mode = TARGET_64BIT ? DImode : SImode;
+ rtx reg0 = gen_reg_rtx (double_mode);
+ rtx reg1 = gen_reg_rtx (double_mode);
+
+ emit_move_insn (gen_highpart (single_mode, reg0),
+ force_operand (XEXP (op0, 0), NULL_RTX));
+ emit_move_insn (gen_highpart (single_mode, reg1),
+ force_operand (XEXP (op1, 0), NULL_RTX));
+
+ convert_move (gen_lowpart (single_mode, reg0), len, 1);
+ convert_move (gen_lowpart (single_mode, reg1), len, 1);
+
+ emit_insn ((*gen_long) (reg0, reg1, reg0, reg1));
+ emit_insn ((*gen_result) (target));
+ }
+
+#if 0
+ /* Deactivate for now as profile code cannot cope with
+ CC being live across basic block boundaries. */
+ else
+ {
+ rtx addr0, addr1, count, blocks, temp;
+ rtx end_label = gen_label_rtx ();
+ enum machine_mode mode;
+ tree type;
+
+ mode = GET_MODE (len);
+ if (mode == VOIDmode)
+ mode = word_mode;
+
+ type = (*lang_hooks.types.type_for_mode) (mode, 1);
+ if (!type)
+ abort ();
+
+ addr0 = gen_reg_rtx (Pmode);
+ addr1 = gen_reg_rtx (Pmode);
+ count = gen_reg_rtx (mode);
+ blocks = gen_reg_rtx (mode);
+
+ convert_move (count, len, 1);
+ emit_cmp_and_jump_insns (count, const0_rtx,
+ EQ, NULL_RTX, mode, 1, end_label);
+
+ emit_move_insn (addr0, force_operand (XEXP (op0, 0), NULL_RTX));
+ emit_move_insn (addr1, force_operand (XEXP (op1, 0), NULL_RTX));
+ op0 = change_address (op0, VOIDmode, addr0);
+ op1 = change_address (op1, VOIDmode, addr1);
+
+ temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1, 0);
+ if (temp != count)
+ emit_move_insn (count, temp);
+
+ temp = expand_binop (mode, ashr_optab, count, GEN_INT (8), blocks, 1, 0);
+ if (temp != blocks)
+ emit_move_insn (blocks, temp);
+
+ expand_start_loop (1);
+ expand_exit_loop_top_cond (0, build (NE_EXPR, type,
+ make_tree (type, blocks),
+ make_tree (type, const0_rtx)));
+
+ emit_insn ((*gen_short) (op0, op1, GEN_INT (255)));
+ temp = gen_rtx_NE (VOIDmode, gen_rtx_REG (CCSmode, 33), const0_rtx);
+ temp = gen_rtx_IF_THEN_ELSE (VOIDmode, temp,
+ gen_rtx_LABEL_REF (VOIDmode, end_label), pc_rtx);
+ temp = gen_rtx_SET (VOIDmode, pc_rtx, temp);
+ emit_jump_insn (temp);
+
+ s390_load_address (addr0,
+ gen_rtx_PLUS (Pmode, addr0, GEN_INT (256)));
+ s390_load_address (addr1,
+ gen_rtx_PLUS (Pmode, addr1, GEN_INT (256)));
+
+ temp = expand_binop (mode, add_optab, blocks, constm1_rtx, blocks, 1, 0);
+ if (temp != blocks)
+ emit_move_insn (blocks, temp);
+
+ expand_end_loop ();
+
+ emit_insn ((*gen_short) (op0, op1, convert_to_mode (word_mode, count, 1)));
+ emit_label (end_label);
+
+ emit_insn ((*gen_result) (target));
+ }
+#endif
+}
+
/* In the name of slightly smaller debug output, and to cater to
general assembler losage, recognize various UNSPEC sequences
and turn them back into a direct symbol reference. */
@@ -1940,6 +2981,48 @@ s390_simplify_dwarf_addr (orig_x)
return orig_x;
}
+/* Locate some local-dynamic symbol still in use by this function
+ so that we can print its name in local-dynamic base patterns. */
+
+static const char *
+get_some_local_dynamic_name ()
+{
+ rtx insn;
+
+ if (cfun->machine->some_ld_name)
+ return cfun->machine->some_ld_name;
+
+ for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
+ if (INSN_P (insn)
+ && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
+ return cfun->machine->some_ld_name;
+
+ abort ();
+}
+
+static int
+get_some_local_dynamic_name_1 (px, data)
+ rtx *px;
+ void *data ATTRIBUTE_UNUSED;
+{
+ rtx x = *px;
+
+ if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
+ {
+ x = get_pool_constant (x);
+ return for_each_rtx (&x, get_some_local_dynamic_name_1, 0);
+ }
+
+ if (GET_CODE (x) == SYMBOL_REF
+ && tls_symbolic_operand (x) == TLS_MODEL_LOCAL_DYNAMIC)
+ {
+ cfun->machine->some_ld_name = XSTR (x, 0);
+ return 1;
+ }
+
+ return 0;
+}
+
/* Output symbolic constant X in assembler syntax to
stdio stream FILE. */
@@ -1981,8 +3064,15 @@ s390_output_symbolic_const (file, x)
switch (XINT (x, 1))
{
case 100:
+ case 104:
+ s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "-");
+ s390_output_symbolic_const (file, cfun->machine->literal_pool_label);
+ break;
+ case 105:
+ s390_output_symbolic_const (file, cfun->machine->literal_pool_label);
+ fprintf (file, "-");
s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "-.LT%X", s390_function_count);
break;
case 110:
s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
@@ -2002,7 +3092,32 @@ s390_output_symbolic_const (file, x)
break;
case 114:
s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@PLT-.LT%X", s390_function_count);
+ fprintf (file, "@PLT-");
+ s390_output_symbolic_const (file, cfun->machine->literal_pool_label);
+ break;
+ case UNSPEC_TLSGD:
+ s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@TLSGD");
+ break;
+ case UNSPEC_TLSLDM:
+ assemble_name (file, get_some_local_dynamic_name ());
+ fprintf (file, "@TLSLDM");
+ break;
+ case UNSPEC_DTPOFF:
+ s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@DTPOFF");
+ break;
+ case UNSPEC_NTPOFF:
+ s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@NTPOFF");
+ break;
+ case UNSPEC_GOTNTPOFF:
+ s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@GOTNTPOFF");
+ break;
+ case UNSPEC_INDNTPOFF:
+ s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@INDNTPOFF");
break;
default:
output_operand_lossage ("invalid UNSPEC as operand (2)");
@@ -2026,7 +3141,9 @@ print_operand_address (file, addr)
{
struct s390_address ad;
- if (!s390_decompose_address (addr, &ad, TRUE))
+ if (!s390_decompose_address (addr, &ad)
+ || (ad.base && !REG_OK_FOR_BASE_STRICT_P (ad.base))
+ || (ad.indx && !REG_OK_FOR_INDEX_STRICT_P (ad.indx)))
output_operand_lossage ("Cannot decompose address.");
if (ad.disp)
@@ -2047,6 +3164,7 @@ print_operand_address (file, addr)
'C': print opcode suffix for branch condition.
'D': print opcode suffix for inverse branch condition.
+ 'J': print tls_load/tls_gdcall/tls_ldcall suffix
'O': print only the displacement of a memory reference.
'R': print only the base register of a memory reference.
'N': print the second word of a DImode operand.
@@ -2072,12 +3190,33 @@ print_operand (file, x, code)
fprintf (file, s390_branch_condition_mnemonic (x, TRUE));
return;
+ case 'J':
+ if (GET_CODE (x) == SYMBOL_REF)
+ {
+ fprintf (file, "%s", ":tls_load:");
+ output_addr_const (file, x);
+ }
+ else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSGD)
+ {
+ fprintf (file, "%s", ":tls_gdcall:");
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ }
+ else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSLDM)
+ {
+ fprintf (file, "%s", ":tls_ldcall:");
+ assemble_name (file, get_some_local_dynamic_name ());
+ }
+ else
+ abort ();
+ return;
+
case 'O':
{
struct s390_address ad;
if (GET_CODE (x) != MEM
- || !s390_decompose_address (XEXP (x, 0), &ad, TRUE)
+ || !s390_decompose_address (XEXP (x, 0), &ad)
+ || (ad.base && !REG_OK_FOR_BASE_STRICT_P (ad.base))
|| ad.indx)
abort ();
@@ -2093,7 +3232,8 @@ print_operand (file, x, code)
struct s390_address ad;
if (GET_CODE (x) != MEM
- || !s390_decompose_address (XEXP (x, 0), &ad, TRUE)
+ || !s390_decompose_address (XEXP (x, 0), &ad)
+ || (ad.base && !REG_OK_FOR_BASE_STRICT_P (ad.base))
|| ad.indx)
abort ();
@@ -2248,7 +3388,11 @@ addr_generation_dependency_p (dep_rtx, insn)
if (GET_CODE (dep_rtx) == SET)
{
target = SET_DEST (dep_rtx);
-
+ if (GET_CODE (target) == STRICT_LOW_PART)
+ target = XEXP (target, 0);
+ while (GET_CODE (target) == SUBREG)
+ target = SUBREG_REG (target);
+
if (GET_CODE (target) == REG)
{
int regno = REGNO (target);
@@ -2389,18 +3533,25 @@ s390_adjust_priority (insn, priority)
}
-/* Split all branches that exceed the maximum distance. */
+/* Split all branches that exceed the maximum distance.
+ Returns true if this created a new literal pool entry.
+
+ Code generated by this routine is allowed to use
+ TEMP_REG as temporary scratch register. If this is
+ done, TEMP_USED is set to true. */
-static void
-s390_split_branches (void)
+static int
+s390_split_branches (temp_reg, temp_used)
+ rtx temp_reg;
+ bool *temp_used;
{
- rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
- rtx insn, pat, label, target, jump, tmp;
+ int new_literal = 0;
+ rtx insn, pat, tmp, target;
+ rtx *label;
- /* In 64-bit mode we can jump +- 4GB. */
+ /* We need correct insn addresses. */
- if (TARGET_64BIT)
- return;
+ shorten_branches (get_insns ());
/* Find all branches that exceed 64KB, and split them. */
@@ -2410,61 +3561,66 @@ s390_split_branches (void)
continue;
pat = PATTERN (insn);
- if (GET_CODE (pat) != SET)
+ if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) > 2)
+ pat = XVECEXP (pat, 0, 0);
+ if (GET_CODE (pat) != SET || SET_DEST (pat) != pc_rtx)
continue;
if (GET_CODE (SET_SRC (pat)) == LABEL_REF)
{
- label = SET_SRC (pat);
+ label = &SET_SRC (pat);
}
else if (GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE)
{
if (GET_CODE (XEXP (SET_SRC (pat), 1)) == LABEL_REF)
- label = XEXP (SET_SRC (pat), 1);
+ label = &XEXP (SET_SRC (pat), 1);
else if (GET_CODE (XEXP (SET_SRC (pat), 2)) == LABEL_REF)
- label = XEXP (SET_SRC (pat), 2);
+ label = &XEXP (SET_SRC (pat), 2);
else
continue;
}
else
continue;
- if (get_attr_length (insn) == 4)
+ if (get_attr_length (insn) <= (TARGET_64BIT ? 6 : 4))
continue;
- if (flag_pic)
+ *temp_used = 1;
+
+ if (TARGET_64BIT)
{
- target = gen_rtx_UNSPEC (SImode, gen_rtvec (1, label), 100);
- target = gen_rtx_CONST (SImode, target);
- target = force_const_mem (SImode, target);
- jump = gen_rtx_REG (Pmode, BASE_REGISTER);
- jump = gen_rtx_PLUS (Pmode, jump, temp_reg);
+ tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, *label), insn);
+ INSN_ADDRESSES_NEW (tmp, -1);
+
+ target = temp_reg;
}
- else
+ else if (!flag_pic)
{
- target = force_const_mem (Pmode, label);
- jump = temp_reg;
- }
+ new_literal = 1;
+ tmp = force_const_mem (Pmode, *label);
+ tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, tmp), insn);
+ INSN_ADDRESSES_NEW (tmp, -1);
- if (GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE)
+ target = temp_reg;
+ }
+ else
{
- if (GET_CODE (XEXP (SET_SRC (pat), 1)) == LABEL_REF)
- jump = gen_rtx_IF_THEN_ELSE (VOIDmode, XEXP (SET_SRC (pat), 0),
- jump, pc_rtx);
- else
- jump = gen_rtx_IF_THEN_ELSE (VOIDmode, XEXP (SET_SRC (pat), 0),
- pc_rtx, jump);
+ new_literal = 1;
+ tmp = gen_rtx_UNSPEC (SImode, gen_rtvec (1, *label), 104);
+ tmp = gen_rtx_CONST (SImode, tmp);
+ tmp = force_const_mem (SImode, tmp);
+ tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, tmp), insn);
+ INSN_ADDRESSES_NEW (tmp, -1);
+
+ target = gen_rtx_REG (Pmode, BASE_REGISTER);
+ target = gen_rtx_PLUS (Pmode, target, temp_reg);
}
- tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, target), insn);
- INSN_ADDRESSES_NEW (tmp, -1);
-
- tmp = emit_jump_insn_before (gen_rtx_SET (VOIDmode, pc_rtx, jump), insn);
- INSN_ADDRESSES_NEW (tmp, -1);
-
- remove_insn (insn);
- insn = tmp;
+ if (!validate_change (insn, label, target, 0))
+ abort ();
}
+
+ return new_literal;
}
@@ -2582,6 +3738,153 @@ replace_constant_pool_ref (x, ref, addr)
}
}
+/* Check whether ADDR is an address that uses the base register,
+ without actually constituting a literal pool access. (This happens
+ in 31-bit PIC mode, where the base register is used as anchor for
+ relative addressing of local symbols.)
+
+ Returns 1 if the base register occupies the base slot,
+ returns 2 if the base register occupies the index slot,
+ returns 0 if the address is not of this form. */
+
+static int
+find_base_register_in_addr (addr)
+ struct s390_address *addr;
+{
+ /* If DISP is complex, we might have a literal pool reference. */
+ if (addr->disp && GET_CODE (addr->disp) != CONST_INT)
+ return 0;
+
+ if (addr->base && REG_P (addr->base) && REGNO (addr->base) == BASE_REGISTER)
+ return 1;
+
+ if (addr->indx && REG_P (addr->indx) && REGNO (addr->indx) == BASE_REGISTER)
+ return 2;
+
+ return 0;
+}
+
+/* Return true if X contains an address that uses the base register,
+ without actually constituting a literal pool access. */
+
+static bool
+find_base_register_ref (x)
+ rtx x;
+{
+ bool retv = FALSE;
+ struct s390_address addr;
+ int i, j;
+ const char *fmt;
+
+ /* Addresses can only occur inside a MEM ... */
+ if (GET_CODE (x) == MEM)
+ {
+ if (s390_decompose_address (XEXP (x, 0), &addr)
+ && find_base_register_in_addr (&addr))
+ return TRUE;
+ }
+
+ /* ... or a load-address type pattern. */
+ if (GET_CODE (x) == SET && GET_CODE (SET_DEST (x)) == REG)
+ {
+ if (s390_decompose_address (SET_SRC (x), &addr)
+ && find_base_register_in_addr (&addr))
+ return TRUE;
+ }
+
+ fmt = GET_RTX_FORMAT (GET_CODE (x));
+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+ {
+ retv |= find_base_register_ref (XEXP (x, i));
+ }
+ else if (fmt[i] == 'E')
+ {
+ for (j = 0; j < XVECLEN (x, i); j++)
+ retv |= find_base_register_ref (XVECEXP (x, i, j));
+ }
+ }
+
+ return retv;
+}
+
+/* If X contains an address that uses the base register,
+ without actually constituting a literal pool access,
+ replace the base register with REPL in all such cases.
+
+ Handles both MEMs and load address patterns. */
+
+static void
+replace_base_register_ref (x, repl)
+ rtx *x;
+ rtx repl;
+{
+ struct s390_address addr;
+ rtx new_addr;
+ int i, j, pos;
+ const char *fmt;
+
+ /* Addresses can only occur inside a MEM ... */
+ if (GET_CODE (*x) == MEM)
+ {
+ if (s390_decompose_address (XEXP (*x, 0), &addr)
+ && (pos = find_base_register_in_addr (&addr)))
+ {
+ if (pos == 1)
+ addr.base = repl;
+ else
+ addr.indx = repl;
+
+ new_addr = addr.base;
+ if (addr.indx)
+ new_addr = gen_rtx_PLUS (Pmode, new_addr, addr.indx);
+ if (addr.disp)
+ new_addr = gen_rtx_PLUS (Pmode, new_addr, addr.disp);
+
+ *x = replace_equiv_address (*x, new_addr);
+ return;
+ }
+ }
+
+ /* ... or a load-address type pattern. */
+ if (GET_CODE (*x) == SET && GET_CODE (SET_DEST (*x)) == REG)
+ {
+ if (s390_decompose_address (SET_SRC (*x), &addr)
+ && (pos = find_base_register_in_addr (&addr)))
+ {
+ if (pos == 1)
+ addr.base = repl;
+ else
+ addr.indx = repl;
+
+ new_addr = addr.base;
+ if (addr.indx)
+ new_addr = gen_rtx_PLUS (Pmode, new_addr, addr.indx);
+ if (addr.disp)
+ new_addr = gen_rtx_PLUS (Pmode, new_addr, addr.disp);
+
+ SET_SRC (*x) = new_addr;
+ return;
+ }
+ }
+
+ fmt = GET_RTX_FORMAT (GET_CODE (*x));
+ for (i = GET_RTX_LENGTH (GET_CODE (*x)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+ {
+ replace_base_register_ref (&XEXP (*x, i), repl);
+ }
+ else if (fmt[i] == 'E')
+ {
+ for (j = 0; j < XVECLEN (*x, i); j++)
+ replace_base_register_ref (&XVECEXP (*x, i, j), repl);
+ }
+ }
+}
+
+
/* We keep a list of constants we which we have to add to internal
constant tables in the middle of large functions. */
@@ -2613,17 +3916,26 @@ struct constant_pool
{
struct constant_pool *next;
rtx first_insn;
- rtx last_insn;
+ rtx pool_insn;
+ bitmap insns;
struct constant *constants[NR_C_MODES];
rtx label;
int size;
+ bool anchor;
};
+static struct constant_pool * s390_chunkify_start PARAMS ((rtx, bool *));
+static void s390_chunkify_finish PARAMS ((struct constant_pool *, rtx));
+static void s390_chunkify_cancel PARAMS ((struct constant_pool *));
+
static struct constant_pool *s390_start_pool PARAMS ((struct constant_pool **, rtx));
static void s390_end_pool PARAMS ((struct constant_pool *, rtx));
+static void s390_add_pool_insn PARAMS ((struct constant_pool *, rtx));
static struct constant_pool *s390_find_pool PARAMS ((struct constant_pool *, rtx));
-static rtx s390_add_pool PARAMS ((struct constant_pool *, rtx, enum machine_mode));
+static void s390_add_constant PARAMS ((struct constant_pool *, rtx, enum machine_mode));
+static rtx s390_find_constant PARAMS ((struct constant_pool *, rtx, enum machine_mode));
+static void s390_add_anchor PARAMS ((struct constant_pool *));
static rtx s390_dump_pool PARAMS ((struct constant_pool *));
static void s390_free_pool PARAMS ((struct constant_pool *));
@@ -2645,9 +3957,11 @@ s390_start_pool (pool_list, insn)
pool->label = gen_label_rtx ();
pool->first_insn = insn;
- pool->last_insn = NULL_RTX;
+ pool->pool_insn = NULL_RTX;
+ pool->insns = BITMAP_XMALLOC ();
pool->size = 0;
-
+ pool->anchor = FALSE;
+
for (prev = pool_list; *prev; prev = &(*prev)->next)
;
*prev = pool;
@@ -2655,14 +3969,31 @@ s390_start_pool (pool_list, insn)
return pool;
}
-/* End range of instructions covered by POOL at INSN. */
+/* End range of instructions covered by POOL at INSN and emit
+ placeholder insn representing the pool. */
static void
s390_end_pool (pool, insn)
struct constant_pool *pool;
rtx insn;
{
- pool->last_insn = insn;
+ rtx pool_size = GEN_INT (pool->size + 8 /* alignment slop */);
+
+ if (!insn)
+ insn = get_last_insn ();
+
+ pool->pool_insn = emit_insn_after (gen_pool (pool_size), insn);
+ INSN_ADDRESSES_NEW (pool->pool_insn, -1);
+}
+
+/* Add INSN to the list of insns covered by POOL. */
+
+static void
+s390_add_pool_insn (pool, insn)
+ struct constant_pool *pool;
+ rtx insn;
+{
+ bitmap_set_bit (pool->insns, INSN_UID (insn));
}
/* Return pool out of POOL_LIST that covers INSN. */
@@ -2672,33 +4003,24 @@ s390_find_pool (pool_list, insn)
struct constant_pool *pool_list;
rtx insn;
{
- int addr = INSN_ADDRESSES (INSN_UID (insn));
struct constant_pool *pool;
- if (addr == -1)
- return NULL;
-
for (pool = pool_list; pool; pool = pool->next)
- if (INSN_ADDRESSES (INSN_UID (pool->first_insn)) <= addr
- && (pool->last_insn == NULL_RTX
- || INSN_ADDRESSES (INSN_UID (pool->last_insn)) > addr))
+ if (bitmap_bit_p (pool->insns, INSN_UID (insn)))
break;
return pool;
}
-/* Add constant VAL of mode MODE to the constant pool POOL.
- Return an RTX describing the distance from the start of
- the pool to the location of the new constant. */
+/* Add constant VAL of mode MODE to the constant pool POOL. */
-static rtx
-s390_add_pool (pool, val, mode)
+static void
+s390_add_constant (pool, val, mode)
struct constant_pool *pool;
rtx val;
enum machine_mode mode;
{
struct constant *c;
- rtx offset;
int i;
for (i = 0; i < NR_C_MODES; i++)
@@ -2720,13 +4042,54 @@ s390_add_pool (pool, val, mode)
pool->constants[i] = c;
pool->size += GET_MODE_SIZE (mode);
}
+}
- offset = gen_rtx_MINUS (Pmode, gen_rtx_LABEL_REF (Pmode, c->label),
- gen_rtx_LABEL_REF (Pmode, pool->label));
+/* Find constant VAL of mode MODE in the constant pool POOL.
+ Return an RTX describing the distance from the start of
+ the pool to the location of the new constant. */
+
+static rtx
+s390_find_constant (pool, val, mode)
+ struct constant_pool *pool;
+ rtx val;
+ enum machine_mode mode;
+{
+ struct constant *c;
+ rtx offset;
+ int i;
+
+ for (i = 0; i < NR_C_MODES; i++)
+ if (constant_modes[i] == mode)
+ break;
+ if (i == NR_C_MODES)
+ abort ();
+
+ for (c = pool->constants[i]; c != NULL; c = c->next)
+ if (rtx_equal_p (val, c->value))
+ break;
+
+ if (c == NULL)
+ abort ();
+
+ offset = gen_rtx_MINUS (Pmode, gen_rtx_LABEL_REF (Pmode, c->label),
+ gen_rtx_LABEL_REF (Pmode, pool->label));
offset = gen_rtx_CONST (Pmode, offset);
return offset;
}
+/* Set 'anchor' flag in POOL. */
+
+static void
+s390_add_anchor (pool)
+ struct constant_pool *pool;
+{
+ if (!pool->anchor)
+ {
+ pool->anchor = TRUE;
+ pool->size += 4;
+ }
+}
+
/* Dump out the constants in POOL. */
static rtx
@@ -2737,31 +4100,47 @@ s390_dump_pool (pool)
rtx insn;
int i;
- /* Select location to put literal pool. */
- if (TARGET_64BIT)
- insn = get_last_insn ();
- else
- insn = pool->last_insn? pool->last_insn : get_last_insn ();
-
/* Pool start insn switches to proper section
and guarantees necessary alignment. */
if (TARGET_64BIT)
- insn = emit_insn_after (gen_pool_start_64 (), insn);
+ insn = emit_insn_after (gen_pool_start_64 (), pool->pool_insn);
else
- insn = emit_insn_after (gen_pool_start_31 (), insn);
+ insn = emit_insn_after (gen_pool_start_31 (), pool->pool_insn);
INSN_ADDRESSES_NEW (insn, -1);
insn = emit_label_after (pool->label, insn);
INSN_ADDRESSES_NEW (insn, -1);
+ /* Emit anchor if we need one. */
+ if (pool->anchor)
+ {
+ rtx anchor = gen_rtx_LABEL_REF (VOIDmode, pool->label);
+ anchor = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, anchor), 105);
+ anchor = gen_rtx_CONST (VOIDmode, anchor);
+ insn = emit_insn_after (gen_consttable_si (anchor), insn);
+ INSN_ADDRESSES_NEW (insn, -1);
+ }
+
/* Dump constants in descending alignment requirement order,
ensuring proper alignment for every constant. */
for (i = 0; i < NR_C_MODES; i++)
for (c = pool->constants[i]; c; c = c->next)
{
+ /* Convert 104 unspecs to pool-relative references. */
+ rtx value = c->value;
+ if (GET_CODE (value) == CONST
+ && GET_CODE (XEXP (value, 0)) == UNSPEC
+ && XINT (XEXP (value, 0), 1) == 104
+ && XVECLEN (XEXP (value, 0), 0) == 1)
+ {
+ value = gen_rtx_MINUS (Pmode, XVECEXP (XEXP (value, 0), 0, 0),
+ gen_rtx_LABEL_REF (VOIDmode, pool->label));
+ value = gen_rtx_CONST (VOIDmode, value);
+ }
+
insn = emit_label_after (c->label, insn);
INSN_ADDRESSES_NEW (insn, -1);
- insn = emit_insn_after (gen_consttable[i] (c->value), insn);
+ insn = emit_insn_after (gen_consttable[i] (value), insn);
INSN_ADDRESSES_NEW (insn, -1);
}
@@ -2776,6 +4155,9 @@ s390_dump_pool (pool)
insn = emit_barrier_after (insn);
INSN_ADDRESSES_NEW (insn, -1);
+ /* Remove placeholder insn. */
+ remove_insn (pool->pool_insn);
+
return insn;
}
@@ -2798,57 +4180,86 @@ s390_free_pool (pool)
}
}
+ BITMAP_XFREE (pool->insns);
free (pool);
}
-/* Used in s390.md for branch length calculation. */
-int s390_pool_overflow = 0;
-/* Chunkify the literal pool if required. */
+/* Chunkify the literal pool if required.
+
+ Code generated by this routine is allowed to use
+ TEMP_REG as temporary scratch register. If this is
+ done, TEMP_USED is set to true. */
#define S390_POOL_CHUNK_MIN 0xc00
#define S390_POOL_CHUNK_MAX 0xe00
-static void
-s390_chunkify_pool (void)
+static struct constant_pool *
+s390_chunkify_start (temp_reg, temp_used)
+ rtx temp_reg;
+ bool *temp_used;
{
- rtx base_reg = gen_rtx_REG (Pmode,
- TARGET_64BIT? BASE_REGISTER : RETURN_REGNUM);
+ rtx base_reg = gen_rtx_REG (Pmode, BASE_REGISTER);
struct constant_pool *curr_pool = NULL, *pool_list = NULL;
int extra_size = 0;
bitmap far_labels;
rtx insn;
+ rtx (*gen_reload_base) PARAMS ((rtx, rtx)) =
+ TARGET_64BIT? gen_reload_base_64 : gen_reload_base_31;
+
+
/* Do we need to chunkify the literal pool? */
if (get_pool_size () < S390_POOL_CHUNK_MAX)
- return;
+ return NULL;
+
+ /* We need correct insn addresses. */
+
+ shorten_branches (get_insns ());
/* Scan all insns and move literals to pool chunks.
- Replace all occurrances of literal pool references
- by explicit references to pool chunk entries. */
+ Also, emit anchor reload insns before every insn that uses
+ the literal pool base register as anchor pointer. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
- if (GET_CODE (insn) == INSN)
+ if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
{
- rtx addr, pool_ref = NULL_RTX;
+ rtx pool_ref = NULL_RTX;
find_constant_pool_ref (PATTERN (insn), &pool_ref);
if (pool_ref)
{
if (!curr_pool)
curr_pool = s390_start_pool (&pool_list, insn);
- addr = s390_add_pool (curr_pool, get_pool_constant (pool_ref),
- get_pool_mode (pool_ref));
+ s390_add_constant (curr_pool, get_pool_constant (pool_ref),
+ get_pool_mode (pool_ref));
+ s390_add_pool_insn (curr_pool, insn);
+ }
- addr = gen_rtx_PLUS (Pmode, base_reg, addr);
- replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
- INSN_CODE (insn) = -1;
+ else if (!TARGET_64BIT && flag_pic
+ && find_base_register_ref (PATTERN (insn)))
+ {
+ rtx new = gen_reload_anchor (temp_reg, base_reg);
+ new = emit_insn_before (new, insn);
+ INSN_ADDRESSES_NEW (new, INSN_ADDRESSES (INSN_UID (insn)));
+ extra_size += 8;
+ *temp_used = 1;
+
+ if (!curr_pool)
+ curr_pool = s390_start_pool (&pool_list, new);
+
+ s390_add_anchor (curr_pool);
+ s390_add_pool_insn (curr_pool, insn);
}
}
+ if (GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CODE_LABEL)
+ if (curr_pool)
+ s390_add_pool_insn (curr_pool, insn);
+
if (!curr_pool
|| INSN_ADDRESSES_SIZE () <= (size_t) INSN_UID (insn)
|| INSN_ADDRESSES (INSN_UID (insn)) == -1)
@@ -2859,7 +4270,7 @@ s390_chunkify_pool (void)
if (curr_pool->size < S390_POOL_CHUNK_MAX)
continue;
- s390_end_pool (curr_pool, insn);
+ s390_end_pool (curr_pool, NULL_RTX);
curr_pool = NULL;
}
else
@@ -2872,11 +4283,8 @@ s390_chunkify_pool (void)
Those will have an effect on code size, which we need to
consider here. This calculation makes rather pessimistic
worst-case assumptions. */
- if (GET_CODE (insn) == CODE_LABEL
- || GET_CODE (insn) == JUMP_INSN)
+ if (GET_CODE (insn) == CODE_LABEL)
extra_size += 6;
- else if (GET_CODE (insn) == CALL_INSN)
- extra_size += 4;
if (chunk_size < S390_POOL_CHUNK_MIN
&& curr_pool->size < S390_POOL_CHUNK_MIN)
@@ -2892,12 +4300,22 @@ s390_chunkify_pool (void)
/* ... so if we don't find one in time, create one. */
else if ((chunk_size > S390_POOL_CHUNK_MAX
- || curr_pool->size > S390_POOL_CHUNK_MAX)
- && (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN))
+ || curr_pool->size > S390_POOL_CHUNK_MAX))
{
- int addr = INSN_ADDRESSES (INSN_UID (insn));
rtx label, jump, barrier;
+ /* We can insert the barrier only after a 'real' insn. */
+ if (GET_CODE (insn) != INSN && GET_CODE (insn) != CALL_INSN)
+ continue;
+ if (get_attr_length (insn) == 0)
+ continue;
+
+ /* Don't separate insns created by s390_split_branches. */
+ if (GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == SET
+ && rtx_equal_p (SET_DEST (PATTERN (insn)), temp_reg))
+ continue;
+
label = gen_label_rtx ();
jump = emit_jump_insn_after (gen_jump (label), insn);
barrier = emit_barrier_after (jump);
@@ -2905,8 +4323,8 @@ s390_chunkify_pool (void)
JUMP_LABEL (jump) = label;
LABEL_NUSES (label) = 1;
- INSN_ADDRESSES_NEW (jump, addr+1);
- INSN_ADDRESSES_NEW (barrier, addr+1);
+ INSN_ADDRESSES_NEW (jump, -1);
+ INSN_ADDRESSES_NEW (barrier, -1);
INSN_ADDRESSES_NEW (insn, -1);
s390_end_pool (curr_pool, barrier);
@@ -2916,10 +4334,8 @@ s390_chunkify_pool (void)
}
}
- /* Dump out all literal pools. */
-
- for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
- s390_dump_pool (curr_pool);
+ if (curr_pool)
+ s390_end_pool (curr_pool, NULL_RTX);
/* Find all labels that are branched into
@@ -2953,22 +4369,12 @@ s390_chunkify_pool (void)
else if (GET_CODE (insn) == JUMP_INSN)
{
rtx pat = PATTERN (insn);
+ if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) > 2)
+ pat = XVECEXP (pat, 0, 0);
+
if (GET_CODE (pat) == SET)
{
- rtx label = 0;
-
- if (GET_CODE (SET_SRC (pat)) == LABEL_REF)
- {
- label = XEXP (SET_SRC (pat), 0);
- }
- else if (GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE)
- {
- if (GET_CODE (XEXP (SET_SRC (pat), 1)) == LABEL_REF)
- label = XEXP (XEXP (SET_SRC (pat), 1), 0);
- else if (GET_CODE (XEXP (SET_SRC (pat), 2)) == LABEL_REF)
- label = XEXP (XEXP (SET_SRC (pat), 2), 0);
- }
-
+ rtx label = JUMP_LABEL (insn);
if (label)
{
if (s390_find_pool (pool_list, label)
@@ -3009,19 +4415,11 @@ s390_chunkify_pool (void)
/* Insert base register reload insns before every pool. */
for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
- if (TARGET_64BIT)
- {
- rtx pool_ref = gen_rtx_LABEL_REF (Pmode, curr_pool->label);
- rtx new_insn = gen_rtx_SET (Pmode, base_reg, pool_ref);
- rtx insn = curr_pool->first_insn;
- INSN_ADDRESSES_NEW (emit_insn_before (new_insn, insn), -1);
- }
- else
- {
- rtx new_insn = gen_reload_base (base_reg, curr_pool->label);
- rtx insn = curr_pool->first_insn;
- INSN_ADDRESSES_NEW (emit_insn_before (new_insn, insn), -1);
- }
+ {
+ rtx new_insn = gen_reload_base (base_reg, curr_pool->label);
+ rtx insn = curr_pool->first_insn;
+ INSN_ADDRESSES_NEW (emit_insn_before (new_insn, insn), -1);
+ }
/* Insert base register reload insns at every far label. */
@@ -3032,60 +4430,137 @@ s390_chunkify_pool (void)
struct constant_pool *pool = s390_find_pool (pool_list, insn);
if (pool)
{
- if (TARGET_64BIT)
- {
- rtx pool_ref = gen_rtx_LABEL_REF (Pmode, pool->label);
- rtx new_insn = gen_rtx_SET (Pmode, base_reg, pool_ref);
- INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
- }
- else
- {
- rtx new_insn = gen_reload_base (base_reg, pool->label);
- INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
- }
+ rtx new_insn = gen_reload_base (base_reg, pool->label);
+ INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
}
}
- /* Insert base register reload insns after every call if necessary. */
-
- if (REGNO (base_reg) == RETURN_REGNUM)
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (GET_CODE (insn) == CALL_INSN)
- {
- struct constant_pool *pool = s390_find_pool (pool_list, insn);
- if (pool)
- {
- rtx new_insn = gen_reload_base2 (base_reg, pool->label);
- INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
- }
- }
+
+ BITMAP_XFREE (far_labels);
/* Recompute insn addresses. */
- s390_pool_overflow = 1;
init_insn_lengths ();
shorten_branches (get_insns ());
- s390_pool_overflow = 0;
- /* Insert base register reload insns after far branches. */
+ return pool_list;
+}
- if (!TARGET_64BIT)
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (GET_CODE (insn) == JUMP_INSN
- && GET_CODE (PATTERN (insn)) == SET
- && get_attr_length (insn) >= 12)
- {
- struct constant_pool *pool = s390_find_pool (pool_list, insn);
- if (pool)
+/* POOL_LIST is a chunk list as prepared by s390_chunkify_start.
+ After we have decided to use this list, finish implementing
+ all changes to the current function as required.
+
+ Code generated by this routine is allowed to use
+ TEMP_REG as temporary scratch register. */
+
+static void
+s390_chunkify_finish (pool_list, temp_reg)
+ struct constant_pool *pool_list;
+ rtx temp_reg;
+{
+ rtx base_reg = gen_rtx_REG (Pmode, BASE_REGISTER);
+ struct constant_pool *curr_pool = NULL;
+ rtx insn;
+
+
+ /* Replace all literal pool references. */
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ curr_pool = s390_find_pool (pool_list, insn);
+ if (!curr_pool)
+ continue;
+
+ if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
+ {
+ rtx addr, pool_ref = NULL_RTX;
+ find_constant_pool_ref (PATTERN (insn), &pool_ref);
+ if (pool_ref)
+ {
+ addr = s390_find_constant (curr_pool, get_pool_constant (pool_ref),
+ get_pool_mode (pool_ref));
+ addr = gen_rtx_PLUS (Pmode, base_reg, addr);
+ replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
+ INSN_CODE (insn) = -1;
+ }
+
+ else if (!TARGET_64BIT && flag_pic
+ && find_base_register_ref (PATTERN (insn)))
{
- rtx new_insn = gen_reload_base (base_reg, pool->label);
- INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
+ replace_base_register_ref (&PATTERN (insn), temp_reg);
}
+ }
+ }
+
+ /* Dump out all literal pools. */
+
+ for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
+ s390_dump_pool (curr_pool);
+
+ /* Free pool list. */
+
+ while (pool_list)
+ {
+ struct constant_pool *next = pool_list->next;
+ s390_free_pool (pool_list);
+ pool_list = next;
+ }
+}
+
+/* POOL_LIST is a chunk list as prepared by s390_chunkify_start.
+ We have decided we cannot use this list, so revert all changes
+ to the current function that were done by s390_chunkify_start. */
+
+static void
+s390_chunkify_cancel (pool_list)
+ struct constant_pool *pool_list;
+{
+ struct constant_pool *curr_pool = NULL;
+ rtx insn;
+
+ /* Remove all pool placeholder insns. */
+
+ for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
+ {
+ /* Did we insert an extra barrier? Remove it. */
+ rtx barrier = PREV_INSN (curr_pool->pool_insn);
+ rtx jump = barrier? PREV_INSN (barrier) : NULL_RTX;
+ rtx label = NEXT_INSN (curr_pool->pool_insn);
+
+ if (jump && GET_CODE (jump) == JUMP_INSN
+ && barrier && GET_CODE (barrier) == BARRIER
+ && label && GET_CODE (label) == CODE_LABEL
+ && GET_CODE (PATTERN (jump)) == SET
+ && SET_DEST (PATTERN (jump)) == pc_rtx
+ && GET_CODE (SET_SRC (PATTERN (jump))) == LABEL_REF
+ && XEXP (SET_SRC (PATTERN (jump)), 0) == label)
+ {
+ remove_insn (jump);
+ remove_insn (barrier);
+ remove_insn (label);
}
+ remove_insn (curr_pool->pool_insn);
+ }
- /* Free all memory. */
+ /* Remove all base/anchor register reload insns. */
+
+ for (insn = get_insns (); insn; )
+ {
+ rtx next_insn = NEXT_INSN (insn);
+
+ if (GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == SET
+ && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC
+ && (XINT (SET_SRC (PATTERN (insn)), 1) == 210
+ || XINT (SET_SRC (PATTERN (insn)), 1) == 211))
+ remove_insn (insn);
+
+ insn = next_insn;
+ }
+
+ /* Free pool list. */
while (pool_list)
{
@@ -3093,8 +4568,6 @@ s390_chunkify_pool (void)
s390_free_pool (pool_list);
pool_list = next;
}
-
- BITMAP_XFREE (far_labels);
}
@@ -3108,54 +4581,359 @@ int s390_nr_constants;
/* Output main constant pool to stdio stream FILE. */
void
-s390_output_constant_pool (file)
- FILE *file;
+s390_output_constant_pool (start_label, end_label)
+ rtx start_label;
+ rtx end_label;
{
- /* Output constant pool. */
- if (s390_nr_constants)
+ if (TARGET_64BIT)
{
- if (TARGET_64BIT)
+ readonly_data_section ();
+ ASM_OUTPUT_ALIGN (asm_out_file, 3);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (start_label));
+ }
+ else
+ {
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (start_label));
+ ASM_OUTPUT_ALIGN (asm_out_file, 2);
+ }
+
+ s390_pool_count = 0;
+ output_constant_pool (current_function_name, current_function_decl);
+ s390_pool_count = -1;
+ if (TARGET_64BIT)
+ function_section (current_function_decl);
+ else
+ {
+ ASM_OUTPUT_ALIGN (asm_out_file, 1);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (end_label));
+ }
+}
+
+/* Rework the prolog/epilog to avoid saving/restoring
+ registers unnecessarily. If TEMP_REGNO is nonnegative,
+ it specifies the number of a caller-saved register used
+ as temporary scratch register by code emitted during
+ machine dependent reorg. */
+
+static void
+s390_optimize_prolog (temp_regno)
+ int temp_regno;
+{
+ int save_first, save_last, restore_first, restore_last;
+ int i, j;
+ rtx insn, new_insn, next_insn;
+
+ /* Recompute regs_ever_live data for special registers. */
+ regs_ever_live[BASE_REGISTER] = 0;
+ regs_ever_live[RETURN_REGNUM] = 0;
+ regs_ever_live[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0;
+
+ /* If there is (possibly) any pool entry, we need to
+ load the base register.
+ ??? FIXME: this should be more precise. */
+ if (get_pool_size ())
+ regs_ever_live[BASE_REGISTER] = 1;
+
+ /* In non-leaf functions, the prolog/epilog code relies
+ on RETURN_REGNUM being saved in any case. */
+ if (!current_function_is_leaf)
+ regs_ever_live[RETURN_REGNUM] = 1;
+
+ /* We need to save/restore the temporary register. */
+ if (temp_regno >= 0)
+ regs_ever_live[temp_regno] = 1;
+
+
+ /* Find first and last gpr to be saved. */
+
+ for (i = 6; i < 16; i++)
+ if (regs_ever_live[i])
+ if (!global_regs[i]
+ || i == STACK_POINTER_REGNUM
+ || i == RETURN_REGNUM
+ || i == BASE_REGISTER
+ || (flag_pic && i == (int)PIC_OFFSET_TABLE_REGNUM))
+ break;
+
+ for (j = 15; j > i; j--)
+ if (regs_ever_live[j])
+ if (!global_regs[j]
+ || j == STACK_POINTER_REGNUM
+ || j == RETURN_REGNUM
+ || j == BASE_REGISTER
+ || (flag_pic && j == (int)PIC_OFFSET_TABLE_REGNUM))
+ break;
+
+ if (i == 16)
+ {
+ /* Nothing to save/restore. */
+ save_first = restore_first = -1;
+ save_last = restore_last = -1;
+ }
+ else
+ {
+ /* Save/restore from i to j. */
+ save_first = restore_first = i;
+ save_last = restore_last = j;
+ }
+
+ /* Varargs functions need to save gprs 2 to 6. */
+ if (current_function_stdarg)
+ {
+ save_first = 2;
+ if (save_last < 6)
+ save_last = 6;
+ }
+
+
+ /* If all special registers are in fact used, there's nothing we
+ can do, so no point in walking the insn list. */
+ if (i <= BASE_REGISTER && j >= BASE_REGISTER
+ && i <= RETURN_REGNUM && j >= RETURN_REGNUM)
+ return;
+
+
+ /* Search for prolog/epilog insns and replace them. */
+
+ for (insn = get_insns (); insn; insn = next_insn)
+ {
+ int first, last, off;
+ rtx set, base, offset;
+
+ next_insn = NEXT_INSN (insn);
+
+ if (GET_CODE (insn) != INSN)
+ continue;
+ if (GET_CODE (PATTERN (insn)) != PARALLEL)
+ continue;
+
+ if (store_multiple_operation (PATTERN (insn), VOIDmode))
{
- fprintf (file, "\tlarl\t%s,.LT%X\n", reg_names[BASE_REGISTER],
- s390_function_count);
- readonly_data_section ();
- ASM_OUTPUT_ALIGN (file, 3);
+ set = XVECEXP (PATTERN (insn), 0, 0);
+ first = REGNO (SET_SRC (set));
+ last = first + XVECLEN (PATTERN (insn), 0) - 1;
+ offset = const0_rtx;
+ base = eliminate_constant_term (XEXP (SET_DEST (set), 0), &offset);
+ off = INTVAL (offset) - first * UNITS_PER_WORD;
+
+ if (GET_CODE (base) != REG || off < 0)
+ continue;
+ if (first > BASE_REGISTER && first > RETURN_REGNUM)
+ continue;
+ if (last < BASE_REGISTER && last < RETURN_REGNUM)
+ continue;
+
+ if (save_first != -1)
+ {
+ new_insn = save_gprs (base, off, save_first, save_last);
+ new_insn = emit_insn_before (new_insn, insn);
+ INSN_ADDRESSES_NEW (new_insn, -1);
+ }
+
+ remove_insn (insn);
}
- else
+
+ if (load_multiple_operation (PATTERN (insn), VOIDmode))
{
- fprintf (file, "\tbras\t%s,.LTN%X\n", reg_names[BASE_REGISTER],
- s390_function_count);
+ set = XVECEXP (PATTERN (insn), 0, 0);
+ first = REGNO (SET_DEST (set));
+ last = first + XVECLEN (PATTERN (insn), 0) - 1;
+ offset = const0_rtx;
+ base = eliminate_constant_term (XEXP (SET_SRC (set), 0), &offset);
+ off = INTVAL (offset) - first * UNITS_PER_WORD;
+
+ if (GET_CODE (base) != REG || off < 0)
+ continue;
+ if (first > BASE_REGISTER && first > RETURN_REGNUM)
+ continue;
+ if (last < BASE_REGISTER && last < RETURN_REGNUM)
+ continue;
+
+ if (restore_first != -1)
+ {
+ new_insn = restore_gprs (base, off, restore_first, restore_last);
+ new_insn = emit_insn_before (new_insn, insn);
+ INSN_ADDRESSES_NEW (new_insn, -1);
+ }
+
+ remove_insn (insn);
}
- fprintf (file, ".LT%X:\n", s390_function_count);
+ }
+}
- s390_pool_count = 0;
- output_constant_pool (current_function_name, current_function_decl);
- s390_pool_count = -1;
+/* Check whether any insn in the function makes use of the original
+ value of RETURN_REG (e.g. for __builtin_return_address).
+ If so, insert an insn reloading that value.
- if (TARGET_64BIT)
- function_section (current_function_decl);
+ Return true if any such insn was found. */
+
+static bool
+s390_fixup_clobbered_return_reg (return_reg)
+ rtx return_reg;
+{
+ bool replacement_done = 0;
+ rtx insn;
+
+ /* If we never called __builtin_return_address, register 14
+ might have been used as temp during the prolog; we do
+ not want to touch those uses. */
+ if (!has_hard_reg_initial_val (Pmode, REGNO (return_reg)))
+ return false;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ rtx reg, off, new_insn;
+
+ if (GET_CODE (insn) != INSN)
+ continue;
+ if (!reg_referenced_p (return_reg, PATTERN (insn)))
+ continue;
+ if (GET_CODE (PATTERN (insn)) == PARALLEL
+ && store_multiple_operation (PATTERN (insn), VOIDmode))
+ continue;
+
+ if (frame_pointer_needed)
+ reg = hard_frame_pointer_rtx;
else
- fprintf (file, ".LTN%X:\n", s390_function_count);
+ reg = stack_pointer_rtx;
+
+ off = GEN_INT (cfun->machine->frame_size + REGNO (return_reg) * UNITS_PER_WORD);
+ if (INTVAL (off) >= 4096)
+ {
+ off = force_const_mem (Pmode, off);
+ new_insn = gen_rtx_SET (Pmode, return_reg, off);
+ new_insn = emit_insn_before (new_insn, insn);
+ INSN_ADDRESSES_NEW (new_insn, -1);
+ off = return_reg;
+ }
+
+ new_insn = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, reg, off));
+ new_insn = gen_rtx_SET (Pmode, return_reg, new_insn);
+ new_insn = emit_insn_before (new_insn, insn);
+ INSN_ADDRESSES_NEW (new_insn, -1);
+
+ replacement_done = 1;
}
-}
+ return replacement_done;
+}
-/* Return true if floating point registers need to be saved. */
+/* Perform machine-dependent processing. */
-static int
-save_fprs_p ()
+void
+s390_machine_dependent_reorg (first)
+ rtx first ATTRIBUTE_UNUSED;
{
- int i;
- if (!TARGET_64BIT)
- return 0;
- for (i=24; i<=31; i++)
+ bool fixed_up_clobbered_return_reg = 0;
+ rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
+ bool temp_used = 0;
+
+ /* Make sure all splits have been performed; splits after
+ machine_dependent_reorg might confuse insn length counts. */
+ split_all_insns_noflow ();
+
+
+ /* There are two problematic situations we need to correct:
+
+ - the literal pool might be > 4096 bytes in size, so that
+ some of its elements cannot be directly accessed
+
+ - a branch target might be > 64K away from the branch, so that
+ it is not possible to use a PC-relative instruction.
+
+ To fix those, we split the single literal pool into multiple
+ pool chunks, reloading the pool base register at various
+ points throughout the function to ensure it always points to
+ the pool chunk the following code expects, and / or replace
+ PC-relative branches by absolute branches.
+
+ However, the two problems are interdependent: splitting the
+ literal pool can move a branch further away from its target,
+ causing the 64K limit to overflow, and on the other hand,
+ replacing a PC-relative branch by an absolute branch means
+ we need to put the branch target address into the literal
+ pool, possibly causing it to overflow.
+
+ So, we loop trying to fix up both problems until we manage
+ to satisfy both conditions at the same time. Note that the
+ loop is guaranteed to terminate as every pass of the loop
+ strictly decreases the total number of PC-relative branches
+ in the function. (This is not completely true as there
+ might be branch-over-pool insns introduced by chunkify_start.
+ Those never need to be split however.) */
+
+ for (;;)
{
- if (regs_ever_live[i] == 1)
- return 1;
+ struct constant_pool *pool_list;
+
+ /* Try to chunkify the literal pool. */
+ pool_list = s390_chunkify_start (temp_reg, &temp_used);
+
+ /* Split out-of-range branches. If this has created new
+ literal pool entries, cancel current chunk list and
+ recompute it. */
+ if (s390_split_branches (temp_reg, &temp_used))
+ {
+ if (pool_list)
+ s390_chunkify_cancel (pool_list);
+
+ continue;
+ }
+
+ /* Check whether we have clobbered a use of the return
+ register (e.g. for __builtin_return_address). If so,
+ add insns reloading the register where necessary. */
+ if (temp_used && !fixed_up_clobbered_return_reg
+ && s390_fixup_clobbered_return_reg (temp_reg))
+ {
+ fixed_up_clobbered_return_reg = 1;
+
+ /* The fixup insns might have caused a jump to overflow. */
+ if (pool_list)
+ s390_chunkify_cancel (pool_list);
+
+ continue;
+ }
+
+ /* If we made it up to here, both conditions are satisfied.
+ Finish up pool chunkification if required. */
+ if (pool_list)
+ s390_chunkify_finish (pool_list, temp_reg);
+
+ break;
}
- return 0;
+
+ s390_optimize_prolog (temp_used? RETURN_REGNUM : -1);
}
+
+/* Return an RTL expression representing the value of the return address
+ for the frame COUNT steps up from the current frame. FRAME is the
+ frame pointer of that frame. */
+
+rtx
+s390_return_addr_rtx (count, frame)
+ int count;
+ rtx frame;
+{
+ rtx addr;
+
+ /* For the current frame, we use the initial value of RETURN_REGNUM.
+ This works both in leaf and non-leaf functions. */
+
+ if (count == 0)
+ return get_hard_reg_initial_val (Pmode, RETURN_REGNUM);
+
+ /* For frames farther back, we read the stack slot where the
+ corresponding RETURN_REGNUM value was saved. */
+
+ addr = plus_constant (frame, RETURN_REGNUM * UNITS_PER_WORD);
+ addr = memory_address (Pmode, addr);
+ return gen_rtx_MEM (Pmode, addr);
+}
+
/* Find first call clobbered register unsused in a function.
This could be used as base register in a leaf function
or for holding the return address before epilogue. */
@@ -3173,9 +4951,9 @@ find_unused_clobbered_reg ()
/* Fill FRAME with info about frame of current function. */
static void
-s390_frame_info (frame)
- struct s390_frame *frame;
+s390_frame_info ()
{
+ char gprs_ever_live[16];
int i, j;
HOST_WIDE_INT fsize = get_frame_size ();
@@ -3183,79 +4961,59 @@ s390_frame_info (frame)
fatal_error ("Total size of local variables exceeds architecture limit.");
/* fprs 8 - 15 are caller saved for 64 Bit ABI. */
- frame->save_fprs_p = save_fprs_p ();
+ cfun->machine->save_fprs_p = 0;
+ if (TARGET_64BIT)
+ for (i = 24; i < 32; i++)
+ if (regs_ever_live[i] && !global_regs[i])
+ {
+ cfun->machine->save_fprs_p = 1;
+ break;
+ }
- frame->frame_size = fsize + frame->save_fprs_p * 64;
+ cfun->machine->frame_size = fsize + cfun->machine->save_fprs_p * 64;
/* Does function need to setup frame and save area. */
if (! current_function_is_leaf
- || frame->frame_size > 0
+ || cfun->machine->frame_size > 0
|| current_function_calls_alloca
- || current_function_stdarg
- || current_function_varargs)
- frame->frame_size += STARTING_FRAME_OFFSET;
-
- /* If we need to allocate a frame, the stack pointer is changed. */
+ || current_function_stdarg)
+ cfun->machine->frame_size += STARTING_FRAME_OFFSET;
- if (frame->frame_size > 0)
- regs_ever_live[STACK_POINTER_REGNUM] = 1;
+ /* Find first and last gpr to be saved. Note that at this point,
+ we assume the return register and the base register always
+ need to be saved. This is done because the usage of these
+ register might change even after the prolog was emitted.
+ If it turns out later that we really don't need them, the
+ prolog/epilog code is modified again. */
- /* If the literal pool might overflow, the return register might
- be used as temp literal pointer. */
-
- if (!TARGET_64BIT && get_pool_size () >= S390_POOL_CHUNK_MAX / 2)
- regs_ever_live[RETURN_REGNUM] = 1;
+ for (i = 0; i < 16; i++)
+ gprs_ever_live[i] = regs_ever_live[i] && !global_regs[i];
- /* If there is (possibly) any pool entry, we need to
- load base register. */
-
- if (get_pool_size ()
- || !CONST_OK_FOR_LETTER_P (frame->frame_size, 'K')
- || (!TARGET_64BIT && current_function_uses_pic_offset_table))
- regs_ever_live[BASE_REGISTER] = 1;
-
- /* If we need the GOT pointer, remember to save/restore it. */
-
- if (current_function_uses_pic_offset_table)
- regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
-
- /* Frame pointer needed. */
-
- frame->frame_pointer_p = frame_pointer_needed;
-
- /* Find first and last gpr to be saved. */
+ if (flag_pic)
+ gprs_ever_live[PIC_OFFSET_TABLE_REGNUM] =
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM];
+ gprs_ever_live[BASE_REGISTER] = 1;
+ gprs_ever_live[RETURN_REGNUM] = 1;
+ gprs_ever_live[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0;
for (i = 6; i < 16; i++)
- if (regs_ever_live[i])
+ if (gprs_ever_live[i])
break;
for (j = 15; j > i; j--)
- if (regs_ever_live[j])
+ if (gprs_ever_live[j])
break;
-
- if (i == 16)
- {
- /* Nothing to save / restore. */
- frame->first_save_gpr = -1;
- frame->first_restore_gpr = -1;
- frame->last_save_gpr = -1;
- frame->return_reg_saved_p = 0;
- }
- else
- {
- /* Save / Restore from gpr i to j. */
- frame->first_save_gpr = i;
- frame->first_restore_gpr = i;
- frame->last_save_gpr = j;
- frame->return_reg_saved_p = (j >= RETURN_REGNUM && i <= RETURN_REGNUM);
- }
- if (current_function_stdarg || current_function_varargs)
- {
- /* Varargs function need to save from gpr 2 to gpr 15. */
- frame->first_save_gpr = 2;
- }
+
+ /* Save / Restore from gpr i to j. */
+ cfun->machine->first_save_gpr = i;
+ cfun->machine->first_restore_gpr = i;
+ cfun->machine->last_save_gpr = j;
+
+ /* Varargs functions need to save gprs 2 to 6. */
+ if (current_function_stdarg)
+ cfun->machine->first_save_gpr = 2;
}
/* Return offset between argument pointer and frame pointer
@@ -3264,13 +5022,29 @@ s390_frame_info (frame)
int
s390_arg_frame_offset ()
{
- struct s390_frame frame;
+ HOST_WIDE_INT fsize = get_frame_size ();
+ int save_fprs_p, i;
- /* Compute frame_info. */
+ /* fprs 8 - 15 are caller saved for 64 Bit ABI. */
+ save_fprs_p = 0;
+ if (TARGET_64BIT)
+ for (i = 24; i < 32; i++)
+ if (regs_ever_live[i] && !global_regs[i])
+ {
+ save_fprs_p = 1;
+ break;
+ }
- s390_frame_info (&frame);
+ fsize = fsize + save_fprs_p * 64;
- return frame.frame_size + STACK_POINTER_OFFSET;
+ /* Does function need to setup frame and save area. */
+
+ if (! current_function_is_leaf
+ || fsize > 0
+ || current_function_calls_alloca
+ || current_function_stdarg)
+ fsize += STARTING_FRAME_OFFSET;
+ return fsize + STACK_POINTER_OFFSET;
}
/* Emit insn to save fpr REGNUM at offset OFFSET relative
@@ -3305,30 +5079,118 @@ restore_fpr (base, offset, regnum)
return emit_move_insn (gen_rtx_REG (DFmode, regnum), addr);
}
-/* Output the function prologue assembly code to the
- stdio stream FILE. The local frame size is passed
- in LSIZE. */
+/* Generate insn to save registers FIRST to LAST into
+ the register save area located at offset OFFSET
+ relative to register BASE. */
-void
-s390_function_prologue (file, lsize)
- FILE *file ATTRIBUTE_UNUSED;
- HOST_WIDE_INT lsize ATTRIBUTE_UNUSED;
+static rtx
+save_gprs (base, offset, first, last)
+ rtx base;
+ int offset;
+ int first;
+ int last;
{
- s390_chunkify_pool ();
- s390_split_branches ();
+ rtx addr, insn, note;
+ int i;
+
+ addr = plus_constant (base, offset + first * UNITS_PER_WORD);
+ addr = gen_rtx_MEM (Pmode, addr);
+ set_mem_alias_set (addr, s390_sr_alias_set);
+
+ /* Special-case single register. */
+ if (first == last)
+ {
+ if (TARGET_64BIT)
+ insn = gen_movdi (addr, gen_rtx_REG (Pmode, first));
+ else
+ insn = gen_movsi (addr, gen_rtx_REG (Pmode, first));
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ return insn;
+ }
+
+
+ insn = gen_store_multiple (addr,
+ gen_rtx_REG (Pmode, first),
+ GEN_INT (last - first + 1));
+
+
+ /* We need to set the FRAME_RELATED flag on all SETs
+ inside the store-multiple pattern.
+
+ However, we must not emit DWARF records for registers 2..5
+ if they are stored for use by variable arguments ...
+
+ ??? Unfortunately, it is not enough to simply not the the
+ FRAME_RELATED flags for those SETs, because the first SET
+ of the PARALLEL is always treated as if it had the flag
+ set, even if it does not. Therefore we emit a new pattern
+ without those registers as REG_FRAME_RELATED_EXPR note. */
+
+ if (first >= 6)
+ {
+ rtx pat = PATTERN (insn);
+
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
+ RTX_FRAME_RELATED_P (XVECEXP (pat, 0, i)) = 1;
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else if (last >= 6)
+ {
+ addr = plus_constant (base, offset + 6 * UNITS_PER_WORD);
+ note = gen_store_multiple (gen_rtx_MEM (Pmode, addr),
+ gen_rtx_REG (Pmode, 6),
+ GEN_INT (last - 6 + 1));
+ note = PATTERN (note);
+
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ note, REG_NOTES (insn));
+
+ for (i = 0; i < XVECLEN (note, 0); i++)
+ if (GET_CODE (XVECEXP (note, 0, i)) == SET)
+ RTX_FRAME_RELATED_P (XVECEXP (note, 0, i)) = 1;
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ return insn;
}
-/* Output the function epilogue assembly code to the
- stdio stream FILE. The local frame size is passed
- in LSIZE. */
+/* Generate insn to restore registers FIRST to LAST from
+ the register save area located at offset OFFSET
+ relative to register BASE. */
-void
-s390_function_epilogue (file, lsize)
- FILE *file ATTRIBUTE_UNUSED;
- HOST_WIDE_INT lsize ATTRIBUTE_UNUSED;
+static rtx
+restore_gprs (base, offset, first, last)
+ rtx base;
+ int offset;
+ int first;
+ int last;
{
- current_function_uses_pic_offset_table = 0;
- s390_function_count++;
+ rtx addr, insn;
+
+ addr = plus_constant (base, offset + first * UNITS_PER_WORD);
+ addr = gen_rtx_MEM (Pmode, addr);
+ set_mem_alias_set (addr, s390_sr_alias_set);
+
+ /* Special-case single register. */
+ if (first == last)
+ {
+ if (TARGET_64BIT)
+ insn = gen_movdi (gen_rtx_REG (Pmode, first), addr);
+ else
+ insn = gen_movsi (gen_rtx_REG (Pmode, first), addr);
+
+ return insn;
+ }
+
+ insn = gen_load_multiple (gen_rtx_REG (Pmode, first),
+ addr,
+ GEN_INT (last - first + 1));
+ return insn;
}
/* Expand the prologue into a bunch of separate insns. */
@@ -3336,18 +5198,18 @@ s390_function_epilogue (file, lsize)
void
s390_emit_prologue ()
{
- struct s390_frame frame;
rtx insn, addr;
rtx temp_reg;
+ rtx pool_start_label, pool_end_label;
int i;
/* Compute frame_info. */
- s390_frame_info (&frame);
+ s390_frame_info ();
/* Choose best register to use for temp use within prologue. */
- if (frame.return_reg_saved_p
+ if (!current_function_is_leaf
&& !has_hard_reg_initial_val (Pmode, RETURN_REGNUM)
&& get_pool_size () < S390_POOL_CHUNK_MAX / 2)
temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
@@ -3356,75 +5218,26 @@ s390_emit_prologue ()
/* Save call saved gprs. */
- if (frame.first_save_gpr != -1)
- {
- addr = plus_constant (stack_pointer_rtx,
- frame.first_save_gpr * UNITS_PER_WORD);
- addr = gen_rtx_MEM (Pmode, addr);
- set_mem_alias_set (addr, s390_sr_alias_set);
-
- if (frame.first_save_gpr != frame.last_save_gpr )
- {
- insn = emit_insn (gen_store_multiple (addr,
- gen_rtx_REG (Pmode, frame.first_save_gpr),
- GEN_INT (frame.last_save_gpr
- - frame.first_save_gpr + 1)));
-
- /* We need to set the FRAME_RELATED flag on all SETs
- inside the store-multiple pattern.
+ insn = save_gprs (stack_pointer_rtx, 0,
+ cfun->machine->first_save_gpr, cfun->machine->last_save_gpr);
+ emit_insn (insn);
- However, we must not emit DWARF records for registers 2..5
- if they are stored for use by variable arguments ...
+ /* Dump constant pool and set constant pool register. */
- ??? Unfortunately, it is not enough to simply not the the
- FRAME_RELATED flags for those SETs, because the first SET
- of the PARALLEL is always treated as if it had the flag
- set, even if it does not. Therefore we emit a new pattern
- without those registers as REG_FRAME_RELATED_EXPR note. */
-
- if (frame.first_save_gpr >= 6)
- {
- rtx pat = PATTERN (insn);
-
- for (i = 0; i < XVECLEN (pat, 0); i++)
- if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
- RTX_FRAME_RELATED_P (XVECEXP (pat, 0, i)) = 1;
-
- RTX_FRAME_RELATED_P (insn) = 1;
- }
- else if (frame.last_save_gpr >= 6)
- {
- rtx note, naddr;
- naddr = plus_constant (stack_pointer_rtx, 6 * UNITS_PER_WORD);
- note = gen_store_multiple (gen_rtx_MEM (Pmode, naddr),
- gen_rtx_REG (Pmode, 6),
- GEN_INT (frame.last_save_gpr - 6 + 1));
- REG_NOTES (insn) =
- gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
- note, REG_NOTES (insn));
-
- for (i = 0; i < XVECLEN (note, 0); i++)
- if (GET_CODE (XVECEXP (note, 0, i)) == SET)
- RTX_FRAME_RELATED_P (XVECEXP (note, 0, i)) = 1;
-
- RTX_FRAME_RELATED_P (insn) = 1;
- }
- }
- else
- {
- insn = emit_move_insn (addr,
- gen_rtx_REG (Pmode, frame.first_save_gpr));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
- }
-
- /* Dump constant pool and set constant pool register (13). */
-
- insn = emit_insn (gen_lit ());
+ pool_start_label = gen_label_rtx();
+ pool_end_label = gen_label_rtx();
+ cfun->machine->literal_pool_label = pool_start_label;
+
+ if (TARGET_64BIT)
+ insn = emit_insn (gen_literal_pool_64 (gen_rtx_REG (Pmode, BASE_REGISTER),
+ pool_start_label, pool_end_label));
+ else
+ insn = emit_insn (gen_literal_pool_31 (gen_rtx_REG (Pmode, BASE_REGISTER),
+ pool_start_label, pool_end_label));
/* Save fprs for variable args. */
- if (current_function_stdarg || current_function_varargs)
+ if (current_function_stdarg)
{
/* Save fpr 0 and 2. */
@@ -3445,12 +5258,12 @@ s390_emit_prologue ()
if (!TARGET_64BIT)
{
/* Save fpr 4 and 6. */
- if (regs_ever_live[18])
+ if (regs_ever_live[18] && !global_regs[18])
{
insn = save_fpr (stack_pointer_rtx, STACK_POINTER_OFFSET - 16, 18);
RTX_FRAME_RELATED_P (insn) = 1;
}
- if (regs_ever_live[19])
+ if (regs_ever_live[19] && !global_regs[19])
{
insn = save_fpr (stack_pointer_rtx, STACK_POINTER_OFFSET - 8, 19);
RTX_FRAME_RELATED_P (insn) = 1;
@@ -3459,21 +5272,21 @@ s390_emit_prologue ()
/* Decrement stack pointer. */
- if (frame.frame_size > 0)
+ if (cfun->machine->frame_size > 0)
{
- rtx frame_off = GEN_INT (-frame.frame_size);
+ rtx frame_off = GEN_INT (-cfun->machine->frame_size);
/* Save incoming stack pointer into temp reg. */
- if (TARGET_BACKCHAIN || frame.save_fprs_p)
+ if (TARGET_BACKCHAIN || cfun->machine->save_fprs_p)
{
insn = emit_insn (gen_move_insn (temp_reg, stack_pointer_rtx));
}
/* Substract frame size from stack pointer. */
- frame_off = GEN_INT (-frame.frame_size);
- if (!CONST_OK_FOR_LETTER_P (-frame.frame_size, 'K'))
+ frame_off = GEN_INT (-cfun->machine->frame_size);
+ if (!CONST_OK_FOR_LETTER_P (-cfun->machine->frame_size, 'K'))
frame_off = force_const_mem (Pmode, frame_off);
insn = emit_insn (gen_add2_insn (stack_pointer_rtx, frame_off));
@@ -3482,7 +5295,7 @@ s390_emit_prologue ()
gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
gen_rtx_SET (VOIDmode, stack_pointer_rtx,
gen_rtx_PLUS (Pmode, stack_pointer_rtx,
- GEN_INT (-frame.frame_size))),
+ GEN_INT (-cfun->machine->frame_size))),
REG_NOTES (insn));
/* Set backchain. */
@@ -3493,19 +5306,29 @@ s390_emit_prologue ()
set_mem_alias_set (addr, s390_sr_alias_set);
insn = emit_insn (gen_move_insn (addr, temp_reg));
}
+
+ /* If we support asynchronous exceptions (e.g. for Java),
+ we need to make sure the backchain pointer is set up
+ before any possibly trapping memory access. */
+
+ if (TARGET_BACKCHAIN && flag_non_call_exceptions)
+ {
+ addr = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode));
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, addr));
+ }
}
/* Save fprs 8 - 15 (64 bit ABI). */
- if (frame.save_fprs_p)
+ if (cfun->machine->save_fprs_p)
{
insn = emit_insn (gen_add2_insn (temp_reg, GEN_INT(-64)));
for (i = 24; i < 32; i++)
- if (regs_ever_live[i])
+ if (regs_ever_live[i] && !global_regs[i])
{
rtx addr = plus_constant (stack_pointer_rtx,
- frame.frame_size - 64 + (i-24)*8);
+ cfun->machine->frame_size - 64 + (i-24)*8);
insn = save_fpr (temp_reg, (i-24)*8, i);
RTX_FRAME_RELATED_P (insn) = 1;
@@ -3520,7 +5343,7 @@ s390_emit_prologue ()
/* Set frame pointer, if needed. */
- if (frame.frame_pointer_p)
+ if (frame_pointer_needed)
{
insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
@@ -3528,7 +5351,7 @@ s390_emit_prologue ()
/* Set up got pointer, if needed. */
- if (current_function_uses_pic_offset_table)
+ if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
{
rtx got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
SYMBOL_REF_FLAG (got_symbol) = 1;
@@ -3553,8 +5376,10 @@ s390_emit_prologue ()
REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
REG_NOTES (insn));
- insn = emit_insn (gen_add2_insn (pic_offset_table_rtx,
- gen_rtx_REG (Pmode, BASE_REGISTER)));
+ got_symbol = gen_rtx_REG (Pmode, BASE_REGISTER);
+ got_symbol = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, got_symbol), 101);
+ got_symbol = gen_rtx_PLUS (Pmode, got_symbol, pic_offset_table_rtx);
+ insn = emit_move_insn (pic_offset_table_rtx, got_symbol);
REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
REG_NOTES (insn));
}
@@ -3566,26 +5391,21 @@ s390_emit_prologue ()
void
s390_emit_epilogue ()
{
- struct s390_frame frame;
rtx frame_pointer, return_reg;
- int area_bottom, area_top, offset;
+ int area_bottom, area_top, offset = 0;
rtvec p;
- /* Compute frame_info. */
-
- s390_frame_info (&frame);
-
/* Check whether to use frame or stack pointer for restore. */
- frame_pointer = frame.frame_pointer_p ?
+ frame_pointer = frame_pointer_needed ?
hard_frame_pointer_rtx : stack_pointer_rtx;
/* Compute which parts of the save area we need to access. */
- if (frame.first_restore_gpr != -1)
+ if (cfun->machine->first_restore_gpr != -1)
{
- area_bottom = frame.first_restore_gpr * UNITS_PER_WORD;
- area_top = (frame.last_save_gpr + 1) * UNITS_PER_WORD;
+ area_bottom = cfun->machine->first_restore_gpr * UNITS_PER_WORD;
+ area_top = (cfun->machine->last_save_gpr + 1) * UNITS_PER_WORD;
}
else
{
@@ -3595,7 +5415,7 @@ s390_emit_epilogue ()
if (TARGET_64BIT)
{
- if (frame.save_fprs_p)
+ if (cfun->machine->save_fprs_p)
{
if (area_bottom > -64)
area_bottom = -64;
@@ -3605,14 +5425,14 @@ s390_emit_epilogue ()
}
else
{
- if (regs_ever_live[18])
+ if (regs_ever_live[18] && !global_regs[18])
{
if (area_bottom > STACK_POINTER_OFFSET - 16)
area_bottom = STACK_POINTER_OFFSET - 16;
if (area_top < STACK_POINTER_OFFSET - 8)
area_top = STACK_POINTER_OFFSET - 8;
}
- if (regs_ever_live[19])
+ if (regs_ever_live[19] && !global_regs[19])
{
if (area_bottom > STACK_POINTER_OFFSET - 8)
area_bottom = STACK_POINTER_OFFSET - 8;
@@ -3628,18 +5448,18 @@ s390_emit_epilogue ()
{
/* Nothing to restore. */
}
- else if (frame.frame_size + area_bottom >= 0
- && frame.frame_size + area_top <= 4096)
+ else if (cfun->machine->frame_size + area_bottom >= 0
+ && cfun->machine->frame_size + area_top <= 4096)
{
/* Area is in range. */
- offset = frame.frame_size;
+ offset = cfun->machine->frame_size;
}
else
{
rtx insn, frame_off;
offset = area_bottom < 0 ? -area_bottom : 0;
- frame_off = GEN_INT (frame.frame_size - offset);
+ frame_off = GEN_INT (cfun->machine->frame_size - offset);
if (!CONST_OK_FOR_LETTER_P (INTVAL (frame_off), 'K'))
frame_off = force_const_mem (Pmode, frame_off);
@@ -3653,7 +5473,7 @@ s390_emit_epilogue ()
{
int i;
- if (frame.save_fprs_p)
+ if (cfun->machine->save_fprs_p)
for (i = 24; i < 32; i++)
if (regs_ever_live[i] && !global_regs[i])
restore_fpr (frame_pointer,
@@ -3673,16 +5493,16 @@ s390_emit_epilogue ()
/* Restore call saved gprs. */
- if (frame.first_restore_gpr != -1)
+ if (cfun->machine->first_restore_gpr != -1)
{
- rtx addr;
+ rtx insn, addr;
int i;
/* Check for global register and save them
to stack location from where they get restored. */
- for (i = frame.first_restore_gpr;
- i <= frame.last_save_gpr;
+ for (i = cfun->machine->first_restore_gpr;
+ i <= cfun->machine->last_save_gpr;
i++)
{
/* These registers are special and need to be
@@ -3690,7 +5510,7 @@ s390_emit_epilogue ()
if (i == STACK_POINTER_REGNUM
|| i == RETURN_REGNUM
|| i == BASE_REGISTER
- || (flag_pic && i == PIC_OFFSET_TABLE_REGNUM))
+ || (flag_pic && i == (int)PIC_OFFSET_TABLE_REGNUM))
continue;
if (global_regs[i])
@@ -3706,8 +5526,7 @@ s390_emit_epilogue ()
/* Fetch return address from stack before load multiple,
this will do good for scheduling. */
- if (frame.last_save_gpr >= RETURN_REGNUM
- && frame.first_restore_gpr < RETURN_REGNUM)
+ if (!current_function_is_leaf)
{
int return_regnum = find_unused_clobbered_reg();
if (!return_regnum)
@@ -3727,23 +5546,10 @@ s390_emit_epilogue ()
emit_insn (gen_blockage());
- addr = plus_constant (frame_pointer,
- offset + frame.first_restore_gpr * UNITS_PER_WORD);
- addr = gen_rtx_MEM (Pmode, addr);
- set_mem_alias_set (addr, s390_sr_alias_set);
-
- if (frame.first_restore_gpr != frame.last_save_gpr)
- {
- emit_insn (gen_load_multiple (
- gen_rtx_REG (Pmode, frame.first_restore_gpr),
- addr,
- GEN_INT (frame.last_save_gpr - frame.first_restore_gpr + 1)));
- }
- else
- {
- emit_move_insn (gen_rtx_REG (Pmode, frame.first_restore_gpr),
- addr);
- }
+ insn = restore_gprs (frame_pointer, offset,
+ cfun->machine->first_restore_gpr,
+ cfun->machine->last_save_gpr);
+ emit_insn (insn);
}
/* Return to caller. */
@@ -3906,7 +5712,7 @@ s390_build_va_list ()
{
tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl;
- record = make_lang_type (RECORD_TYPE);
+ record = (*lang_hooks.types.make_type) (RECORD_TYPE);
type_decl =
build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
@@ -3939,9 +5745,8 @@ s390_build_va_list ()
}
/* Implement va_start by filling the va_list structure VALIST.
- STDARG_P is true if implementing __builtin_stdarg_va_start,
- false if implementing __builtin_varargs_va_start. NEXTARG
- points to the first anonymous stack argument.
+ STDARG_P is always true, and ignored.
+ NEXTARG points to the first anonymous stack argument.
The following global variables are used to initialize
the va_list structure:
@@ -3953,8 +5758,7 @@ s390_build_va_list ()
(relative to the virtual arg pointer). */
void
-s390_va_start (stdarg_p, valist, nextarg)
- int stdarg_p;
+s390_va_start (valist, nextarg)
tree valist;
rtx nextarg ATTRIBUTE_UNUSED;
{
@@ -3992,8 +5796,6 @@ s390_va_start (stdarg_p, valist, nextarg)
off = INTVAL (current_function_arg_offset_rtx);
off = off < 0 ? 0 : off;
- if (! stdarg_p)
- off = off > 0 ? off - UNITS_PER_WORD : off;
if (TARGET_DEBUG_ARG)
fprintf (stderr, "va_start: n_gpr = %d, n_fpr = %d off %d\n",
(int)n_gpr, (int)n_fpr, off);
@@ -4200,6 +6002,134 @@ s390_va_arg (valist, type)
}
+/* Builtins. */
+
+enum s390_builtin
+{
+ S390_BUILTIN_THREAD_POINTER,
+ S390_BUILTIN_SET_THREAD_POINTER,
+
+ S390_BUILTIN_max
+};
+
+static unsigned int const code_for_builtin_64[S390_BUILTIN_max] = {
+ CODE_FOR_get_tp_64,
+ CODE_FOR_set_tp_64
+};
+
+static unsigned int const code_for_builtin_31[S390_BUILTIN_max] = {
+ CODE_FOR_get_tp_31,
+ CODE_FOR_set_tp_31
+};
+
+static void
+s390_init_builtins ()
+{
+ tree ftype;
+
+ ftype = build_function_type (ptr_type_node, void_list_node);
+ builtin_function ("__builtin_thread_pointer", ftype,
+ S390_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
+ NULL, NULL_TREE);
+
+ ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
+ builtin_function ("__builtin_set_thread_pointer", ftype,
+ S390_BUILTIN_SET_THREAD_POINTER, BUILT_IN_MD,
+ NULL, NULL_TREE);
+}
+
+/* Expand an expression EXP that calls a built-in function,
+ with result going to TARGET if that's convenient
+ (and in mode MODE if that's convenient).
+ SUBTARGET may be used as the target for computing one of EXP's operands.
+ IGNORE is nonzero if the value is to be ignored. */
+
+static rtx
+s390_expand_builtin (exp, target, subtarget, mode, ignore)
+ tree exp;
+ rtx target;
+ rtx subtarget ATTRIBUTE_UNUSED;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ int ignore ATTRIBUTE_UNUSED;
+{
+#define MAX_ARGS 2
+
+ unsigned int const *code_for_builtin =
+ TARGET_64BIT ? code_for_builtin_64 : code_for_builtin_31;
+
+ tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+ tree arglist = TREE_OPERAND (exp, 1);
+ enum insn_code icode;
+ rtx op[MAX_ARGS], pat;
+ int arity;
+ bool nonvoid;
+
+ if (fcode >= S390_BUILTIN_max)
+ internal_error ("bad builtin fcode");
+ icode = code_for_builtin[fcode];
+ if (icode == 0)
+ internal_error ("bad builtin fcode");
+
+ nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
+
+ for (arglist = TREE_OPERAND (exp, 1), arity = 0;
+ arglist;
+ arglist = TREE_CHAIN (arglist), arity++)
+ {
+ const struct insn_operand_data *insn_op;
+
+ tree arg = TREE_VALUE (arglist);
+ if (arg == error_mark_node)
+ return NULL_RTX;
+ if (arity > MAX_ARGS)
+ return NULL_RTX;
+
+ insn_op = &insn_data[icode].operand[arity + nonvoid];
+
+ op[arity] = expand_expr (arg, NULL_RTX, insn_op->mode, 0);
+
+ if (!(*insn_op->predicate) (op[arity], insn_op->mode))
+ op[arity] = copy_to_mode_reg (insn_op->mode, op[arity]);
+ }
+
+ if (nonvoid)
+ {
+ enum machine_mode tmode = insn_data[icode].operand[0].mode;
+ if (!target
+ || GET_MODE (target) != tmode
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
+ target = gen_reg_rtx (tmode);
+ }
+
+ switch (arity)
+ {
+ case 0:
+ pat = GEN_FCN (icode) (target);
+ break;
+ case 1:
+ if (nonvoid)
+ pat = GEN_FCN (icode) (target, op[0]);
+ else
+ pat = GEN_FCN (icode) (op[0]);
+ break;
+ case 2:
+ pat = GEN_FCN (icode) (target, op[0], op[1]);
+ break;
+ default:
+ abort ();
+ }
+ if (!pat)
+ return NULL_RTX;
+ emit_insn (pat);
+
+ if (nonvoid)
+ return target;
+ else
+ return const0_rtx;
+}
+
+
/* Output assembly code for the trampoline template to
stdio stream FILE.
@@ -4285,7 +6215,7 @@ s390_function_profiler (file, labelno)
rtx op[7];
char label[128];
- sprintf (label, "%sP%d", LPREFIX, labelno);
+ ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
fprintf (file, "# function profiler \n");
@@ -4344,3 +6274,353 @@ s390_function_profiler (file, labelno)
}
}
+/* Select section for constant in constant pool. In 32-bit mode,
+ constants go in the function section; in 64-bit mode in .rodata. */
+
+static void
+s390_select_rtx_section (mode, x, align)
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ rtx x ATTRIBUTE_UNUSED;
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+{
+ if (TARGET_64BIT)
+ readonly_data_section ();
+ else
+ function_section (current_function_decl);
+}
+
+/* Encode symbol attributes (local vs. global, tls model) of a SYMBOL_REF
+ into its name and SYMBOL_REF_FLAG. */
+
+static void
+s390_encode_section_info (decl, first)
+ tree decl;
+ int first ATTRIBUTE_UNUSED;
+{
+ bool local_p = (*targetm.binds_local_p) (decl);
+ rtx rtl, symbol;
+
+ rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl);
+ if (GET_CODE (rtl) != MEM)
+ return;
+ symbol = XEXP (rtl, 0);
+ if (GET_CODE (symbol) != SYMBOL_REF)
+ return;
+
+ /* When using PIC, SYMBOL_REF_FLAG marks non-global symbols
+ that can be accessed directly. */
+ if (flag_pic)
+ SYMBOL_REF_FLAG (symbol) = local_p;
+
+ /* Encode thread-local data with %[GLil] for "global dynamic",
+ "local dynamic", "initial exec" or "local exec" TLS models,
+ respectively. */
+
+ if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
+ {
+ const char *symbol_str = XSTR (symbol, 0);
+ char *newstr;
+ size_t len;
+ enum tls_model kind = decl_tls_model (decl);
+
+ if (!flag_pic)
+ {
+ /* We don't allow non-pic code for shared libraries,
+ so don't generate GD/LD TLS models for non-pic code. */
+ switch (kind)
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ kind = TLS_MODEL_INITIAL_EXEC; break;
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ kind = TLS_MODEL_LOCAL_EXEC; break;
+ default:
+ break;
+ }
+ }
+
+ if (symbol_str[0] == '%')
+ {
+ if (symbol_str[1] == tls_model_chars[kind])
+ return;
+ symbol_str += 2;
+ }
+ len = strlen (symbol_str) + 1;
+ newstr = alloca (len + 2);
+
+ newstr[0] = '%';
+ newstr[1] = tls_model_chars[kind];
+ memcpy (newstr + 2, symbol_str, len);
+
+ XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1);
+ }
+
+ /* If a variable has a forced alignment to < 2 bytes, mark it
+ with '@' to prevent it from being used as LARL operand. */
+
+ else if (TREE_CODE (decl) == VAR_DECL
+ && DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) < 16
+ && XSTR (symbol, 0)[0] != '@')
+ {
+ const char *symbol_str = XSTR (symbol, 0);
+ size_t len = strlen (symbol_str) + 1;
+ char *newstr = alloca (len + 1);
+
+ newstr[0] = '@';
+ memcpy (newstr + 1, symbol_str, len);
+
+ XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 1 - 1);
+ }
+}
+
+/* Undo the above when printing symbol names. */
+
+static const char *
+s390_strip_name_encoding (str)
+ const char *str;
+{
+ if (str[0] == '%')
+ str += 2;
+ if (str[0] == '@')
+ str += 1;
+ if (str[0] == '*')
+ str += 1;
+ return str;
+}
+
+/* Output thunk to FILE that implements a C++ virtual function call (with
+ multiple inheritance) to FUNCTION. The thunk adjusts the this pointer
+ by DELTA, and unless VCALL_OFFSET is zero, applies an additional adjustment
+ stored at VCALL_OFFSET in the vtable whose address is located at offset 0
+ relative to the resulting this pointer. */
+
+static void
+s390_output_mi_thunk (file, thunk, delta, vcall_offset, function)
+ FILE *file;
+ tree thunk ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT delta;
+ HOST_WIDE_INT vcall_offset;
+ tree function;
+{
+ rtx op[10];
+ int nonlocal = 0;
+
+ /* Operand 0 is the target function. */
+ op[0] = XEXP (DECL_RTL (function), 0);
+ if (flag_pic && !SYMBOL_REF_FLAG (op[0]))
+ {
+ nonlocal = 1;
+ op[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[0]),
+ TARGET_64BIT ? 113 : flag_pic == 2 ? 112 : 110);
+ op[0] = gen_rtx_CONST (Pmode, op[0]);
+ }
+
+ /* Operand 1 is the 'this' pointer. */
+ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
+ op[1] = gen_rtx_REG (Pmode, 3);
+ else
+ op[1] = gen_rtx_REG (Pmode, 2);
+
+ /* Operand 2 is the delta. */
+ op[2] = GEN_INT (delta);
+
+ /* Operand 3 is the vcall_offset. */
+ op[3] = GEN_INT (vcall_offset);
+
+ /* Operand 4 is the temporary register. */
+ op[4] = gen_rtx_REG (Pmode, 1);
+
+ /* Operands 5 to 8 can be used as labels. */
+ op[5] = NULL_RTX;
+ op[6] = NULL_RTX;
+ op[7] = NULL_RTX;
+ op[8] = NULL_RTX;
+
+ /* Operand 9 can be used for temporary register. */
+ op[9] = NULL_RTX;
+
+ /* Generate code. */
+ if (TARGET_64BIT)
+ {
+ /* Setup literal pool pointer if required. */
+ if (!CONST_OK_FOR_LETTER_P (delta, 'K')
+ || !CONST_OK_FOR_LETTER_P (vcall_offset, 'K'))
+ {
+ op[5] = gen_label_rtx ();
+ output_asm_insn ("larl\t%4,%5", op);
+ }
+
+ /* Add DELTA to this pointer. */
+ if (delta)
+ {
+ if (CONST_OK_FOR_LETTER_P (delta, 'J'))
+ output_asm_insn ("la\t%1,%2(%1)", op);
+ else if (CONST_OK_FOR_LETTER_P (delta, 'K'))
+ output_asm_insn ("aghi\t%1,%2", op);
+ else
+ {
+ op[6] = gen_label_rtx ();
+ output_asm_insn ("agf\t%1,%6-%5(%4)", op);
+ }
+ }
+
+ /* Perform vcall adjustment. */
+ if (vcall_offset)
+ {
+ if (CONST_OK_FOR_LETTER_P (vcall_offset, 'J'))
+ {
+ output_asm_insn ("lg\t%4,0(%1)", op);
+ output_asm_insn ("ag\t%1,%3(%4)", op);
+ }
+ else if (CONST_OK_FOR_LETTER_P (vcall_offset, 'K'))
+ {
+ output_asm_insn ("lghi\t%4,%3", op);
+ output_asm_insn ("ag\t%4,0(%1)", op);
+ output_asm_insn ("ag\t%1,0(%4)", op);
+ }
+ else
+ {
+ op[7] = gen_label_rtx ();
+ output_asm_insn ("llgf\t%4,%7-%5(%4)", op);
+ output_asm_insn ("ag\t%4,0(%1)", op);
+ output_asm_insn ("ag\t%1,0(%4)", op);
+ }
+ }
+
+ /* Jump to target. */
+ output_asm_insn ("jg\t%0", op);
+
+ /* Output literal pool if required. */
+ if (op[5])
+ {
+ output_asm_insn (".align\t4", op);
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[5]));
+ }
+ if (op[6])
+ {
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[6]));
+ output_asm_insn (".long\t%2", op);
+ }
+ if (op[7])
+ {
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[7]));
+ output_asm_insn (".long\t%3", op);
+ }
+ }
+ else
+ {
+ /* Setup base pointer if required. */
+ if (!vcall_offset
+ || !CONST_OK_FOR_LETTER_P (delta, 'K')
+ || !CONST_OK_FOR_LETTER_P (vcall_offset, 'K'))
+ {
+ op[5] = gen_label_rtx ();
+ output_asm_insn ("basr\t%4,0", op);
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[5]));
+ }
+
+ /* Add DELTA to this pointer. */
+ if (delta)
+ {
+ if (CONST_OK_FOR_LETTER_P (delta, 'J'))
+ output_asm_insn ("la\t%1,%2(%1)", op);
+ else if (CONST_OK_FOR_LETTER_P (delta, 'K'))
+ output_asm_insn ("ahi\t%1,%2", op);
+ else
+ {
+ op[6] = gen_label_rtx ();
+ output_asm_insn ("a\t%1,%6-%5(%4)", op);
+ }
+ }
+
+ /* Perform vcall adjustment. */
+ if (vcall_offset)
+ {
+ if (CONST_OK_FOR_LETTER_P (vcall_offset, 'J'))
+ {
+ output_asm_insn ("lg\t%4,0(%1)", op);
+ output_asm_insn ("a\t%1,%3(%4)", op);
+ }
+ else if (CONST_OK_FOR_LETTER_P (vcall_offset, 'K'))
+ {
+ output_asm_insn ("lhi\t%4,%3", op);
+ output_asm_insn ("a\t%4,0(%1)", op);
+ output_asm_insn ("a\t%1,0(%4)", op);
+ }
+ else
+ {
+ op[7] = gen_label_rtx ();
+ output_asm_insn ("l\t%4,%7-%5(%4)", op);
+ output_asm_insn ("a\t%4,0(%1)", op);
+ output_asm_insn ("a\t%1,0(%4)", op);
+ }
+
+ /* We had to clobber the base pointer register.
+ Re-setup the base pointer (with a different base). */
+ op[5] = gen_label_rtx ();
+ output_asm_insn ("basr\t%4,0", op);
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[5]));
+ }
+
+ /* Jump to target. */
+ op[8] = gen_label_rtx ();
+
+ if (!flag_pic)
+ output_asm_insn ("l\t%4,%8-%5(%4)", op);
+ else if (!nonlocal)
+ output_asm_insn ("a\t%4,%8-%5(%4)", op);
+ /* We cannot call through .plt, since .plt requires %r12 loaded. */
+ else if (flag_pic == 1)
+ {
+ output_asm_insn ("a\t%4,%8-%5(%4)", op);
+ output_asm_insn ("l\t%4,%0(%4)", op);
+ }
+ else if (flag_pic == 2)
+ {
+ op[9] = gen_rtx_REG (Pmode, 0);
+ output_asm_insn ("l\t%9,%8-4-%5(%4)", op);
+ output_asm_insn ("a\t%4,%8-%5(%4)", op);
+ output_asm_insn ("ar\t%4,%9", op);
+ output_asm_insn ("l\t%4,0(%4)", op);
+ }
+
+ output_asm_insn ("br\t%4", op);
+
+ /* Output literal pool. */
+ output_asm_insn (".align\t4", op);
+
+ if (nonlocal && flag_pic == 2)
+ output_asm_insn (".long\t%0", op);
+ if (nonlocal)
+ {
+ op[0] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+ SYMBOL_REF_FLAG (op[0]) = 1;
+ }
+
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[8]));
+ if (!flag_pic)
+ output_asm_insn (".long\t%0", op);
+ else
+ output_asm_insn (".long\t%0-%5", op);
+
+ if (op[6])
+ {
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[6]));
+ output_asm_insn (".long\t%2", op);
+ }
+ if (op[7])
+ {
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[7]));
+ output_asm_insn (".long\t%3", op);
+ }
+ }
+}
+
+/* How to allocate a 'struct machine_function'. */
+
+static struct machine_function *
+s390_init_machine_status ()
+{
+ return ggc_alloc_cleared (sizeof (struct machine_function));
+}
+
+#include "gt-s390.h"
diff --git a/contrib/gcc/config/s390/s390.h b/contrib/gcc/config/s390/s390.h
index f3218e9..c3dad68 100644
--- a/contrib/gcc/config/s390/s390.h
+++ b/contrib/gcc/config/s390/s390.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for IBM S/390
- Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com) and
Ulrich Weigand (uweigand@de.ibm.com).
This file is part of GNU CC.
@@ -22,13 +22,29 @@ Boston, MA 02111-1307, USA. */
#ifndef _S390_H
#define _S390_H
-extern int flag_pic;
+/* Override the __fixdfdi etc. routines when building libgcc2.
+ ??? This should be done in a cleaner way ... */
+#if defined (IN_LIBGCC2) && !defined (__s390x__)
+#include <s390/fixdfdi.h>
+#endif
-/* Run-time compilation parameters selecting different hardware subsets. */
-extern int target_flags;
+/* Run-time target specification. */
-/* Target macros checked at runtime of compiler. */
+/* Target CPU builtins. */
+#define TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_assert ("cpu=s390"); \
+ builtin_assert ("machine=s390"); \
+ builtin_define ("__s390__"); \
+ if (TARGET_64BIT) \
+ builtin_define ("__s390x__"); \
+ } \
+ while (0)
+
+/* Optional target features. */
+extern int target_flags;
#define TARGET_HARD_FLOAT (target_flags & 1)
#define TARGET_SOFT_FLOAT (!(target_flags & 1))
@@ -38,26 +54,22 @@ extern int target_flags;
#define TARGET_64BIT (target_flags & 16)
#define TARGET_MVCLE (target_flags & 32)
+/* ??? Once this actually works, it could be made a runtime option. */
+#define TARGET_IBM_FLOAT 0
+#define TARGET_IEEE_FLOAT 1
+
#ifdef DEFAULT_TARGET_64BIT
#define TARGET_DEFAULT 0x13
-#define TARGET_VERSION fprintf (stderr, " (zSeries)");
#else
#define TARGET_DEFAULT 0x3
-#define TARGET_VERSION fprintf (stderr, " (S/390)");
#endif
-
-/* Macro to define tables used to set the flags. This is a list in braces
- of pairs in braces, each pair being { "NAME", VALUE }
- where VALUE is the bits to set or minus the bits to clear.
- An empty string NAME is used to identify the default VALUE. */
-
#define TARGET_SWITCHES \
{ { "hard-float", 1, N_("Use hardware fp")}, \
{ "soft-float", -1, N_("Don't use hardware fp")}, \
{ "backchain", 2, N_("Set backchain")}, \
{ "no-backchain", -2, N_("Don't set backchain (faster, but debug harder")}, \
- { "small-exec", 4, N_("Use bras for execucable < 64k")}, \
+ { "small-exec", 4, N_("Use bras for executable < 64k")}, \
{ "no-small-exec",-4, N_("Don't use bras")}, \
{ "debug", 8, N_("Additional debug prints")}, \
{ "no-debug", -8, N_("Don't print additional debug prints")}, \
@@ -67,97 +79,50 @@ extern int target_flags;
{ "no-mvcle", -32, N_("mvc&ex")}, \
{ "", TARGET_DEFAULT, 0 } }
-/* Define this to change the optimizations performed by default. */
-#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) optimization_options(LEVEL, SIZE)
+/* Target version string. Overridden by the OS header. */
+#ifdef DEFAULT_TARGET_64BIT
+#define TARGET_VERSION fprintf (stderr, " (zSeries)");
+#else
+#define TARGET_VERSION fprintf (stderr, " (S/390)");
+#endif
-/* 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. */
+/* Hooks to override options. */
+#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) optimization_options(LEVEL, SIZE)
#define OVERRIDE_OPTIONS override_options ()
+/* Frame pointer is not used for debugging. */
+#define CAN_DEBUG_WITHOUT_FP
-/* Defines for REAL_ARITHMETIC. */
-#define IEEE_FLOAT 1
-#define TARGET_IBM_FLOAT 0
-#define TARGET_IEEE_FLOAT 1
-
-/* The current function count for create unique internal labels. */
-
-extern int s390_function_count;
-/* The amount of space used for outgoing arguments. */
+/* In libgcc2, determine target settings as compile-time constants. */
+#ifdef IN_LIBGCC2
+#undef TARGET_64BIT
+#ifdef __s390x__
+#define TARGET_64BIT 1
+#else
+#define TARGET_64BIT 0
+#endif
+#endif
-extern int current_function_outgoing_args_size;
/* Target machine storage layout. */
-/* Define this if most significant bit is lowest numbered in instructions
- that operate on numbered bit-fields. */
-
+/* Everything is big-endian. */
#define BITS_BIG_ENDIAN 1
-
-/* Define this if most significant byte of a word is the lowest numbered. */
-
#define BYTES_BIG_ENDIAN 1
-
-/* Define this if MS word of a multiword is the lowest numbered. */
-
#define WORDS_BIG_ENDIAN 1
-/* Number of bits in an addressable storage unit. */
-
-#define BITS_PER_UNIT 8
-
-/* Width in bits of a "word", which is the contents of a machine register. */
-
-#define BITS_PER_WORD (TARGET_64BIT ? 64 : 32)
-#define MAX_BITS_PER_WORD 64
-
/* Width of a word, in units (bytes). */
-
#define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4)
+#ifndef IN_LIBGCC2
#define MIN_UNITS_PER_WORD 4
+#endif
+#define MAX_BITS_PER_WORD 64
-/* Width in bits of a pointer. See also the macro `Pmode' defined below. */
-
-#define POINTER_SIZE (TARGET_64BIT ? 64 : 32)
-
-/* A C expression for the size in bits of the type `short' on the
- target machine. If you don't define this, the default is half a
- word. (If this would be less than one storage unit, it is
- rounded up to one unit.) */
-#define SHORT_TYPE_SIZE 16
-
-/* 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 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 MAX_LONG_TYPE_SIZE 64
-
-/* A C expression for the size in bits of the type `long long' on the
- target machine. If you don't define this, the default is two
- words. */
-#define LONG_LONG_TYPE_SIZE 64
-
-/* Right now we only support two floating point formats, the
- 32 and 64 bit ieee formats. */
-
-#define FLOAT_TYPE_SIZE 32
-#define DOUBLE_TYPE_SIZE 64
-#define LONG_DOUBLE_TYPE_SIZE 64
-
-/* 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,
- 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. */
+/* Function arguments and return values are promoted to word size. */
+#define PROMOTE_FUNCTION_ARGS
+#define PROMOTE_FUNCTION_RETURN
+#define PROMOTE_FOR_CALL_ONLY
#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
if (INTEGRAL_MODE_P (MODE) && \
@@ -165,109 +130,109 @@ if (INTEGRAL_MODE_P (MODE) && \
(MODE) = Pmode; \
}
-/* Defining PROMOTE_FUNCTION_ARGS eliminates some unnecessary zero/sign
- extensions applied to char/short functions arguments. Defining
- PROMOTE_FUNCTION_RETURN does the same for function returns. */
-
-#define PROMOTE_FUNCTION_ARGS
-#define PROMOTE_FUNCTION_RETURN
-#define PROMOTE_FOR_CALL_ONLY
-
-/* Allocation boundary (in *bits*) for storing pointers in memory. */
-
-#define POINTER_BOUNDARY 32
-
/* Allocation boundary (in *bits*) for storing arguments in argument list. */
-
#define PARM_BOUNDARY (TARGET_64BIT ? 64 : 32)
/* Boundary (in *bits*) on which stack pointer should be aligned. */
-
#define STACK_BOUNDARY 64
/* Allocation boundary (in *bits*) for the code of a function. */
-
#define FUNCTION_BOUNDARY 32
/* There is no point aligning anything to a rounder boundary than this. */
-
#define BIGGEST_ALIGNMENT 64
/* Alignment of field after `int : 0' in a structure. */
-
#define EMPTY_FIELD_BOUNDARY 32
/* Alignment on even addresses for LARL instruction. */
-
#define CONSTANT_ALIGNMENT(EXP, ALIGN) (ALIGN) < 16 ? 16 : (ALIGN)
-
#define DATA_ALIGNMENT(TYPE, ALIGN) (ALIGN) < 16 ? 16 : (ALIGN)
-/* Define this if move instructions will actually fail to work when given
- unaligned data. */
-
+/* Alignment is not required by the hardware. */
#define STRICT_ALIGNMENT 0
-/* real arithmetic */
-
-#define REAL_ARITHMETIC
+/* Mode of stack savearea.
+ FUNCTION is VOIDmode because calling convention maintains SP.
+ BLOCK needs Pmode for SP.
+ NONLOCAL needs twice Pmode to maintain both backchain and SP. */
+#define STACK_SAVEAREA_MODE(LEVEL) \
+ (LEVEL == SAVE_FUNCTION ? VOIDmode \
+ : LEVEL == SAVE_NONLOCAL ? (TARGET_64BIT ? TImode : DImode) : Pmode)
/* Define target floating point format. */
+#define TARGET_FLOAT_FORMAT \
+ (TARGET_IEEE_FLOAT? IEEE_FLOAT_FORMAT : IBM_FLOAT_FORMAT)
-#undef TARGET_FLOAT_FORMAT
-#ifdef IEEE_FLOAT
-#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-#else
-#define TARGET_FLOAT_FORMAT IBM_FLOAT_FORMAT
-#endif
-/* Define if special allocation order desired. */
+/* Type layout. */
-#define REG_ALLOC_ORDER \
-{ 1, 2, 3, 4, 5, 0, 14, 13, 12, 11, 10, 9, 8, 7, 6, \
- 16, 17, 18, 19, 20, 21, 22, 23, \
- 24, 25, 26, 27, 28, 29, 30, 31, \
- 15, 32, 33, 34 }
+/* Sizes in bits of the source language data types. */
+#define SHORT_TYPE_SIZE 16
+#define INT_TYPE_SIZE 32
+#define LONG_TYPE_SIZE (TARGET_64BIT ? 64 : 32)
+#define MAX_LONG_TYPE_SIZE 64
+#define LONG_LONG_TYPE_SIZE 64
+#define FLOAT_TYPE_SIZE 32
+#define DOUBLE_TYPE_SIZE 64
+#define LONG_DOUBLE_TYPE_SIZE 64 /* ??? Should support extended format. */
-/* Standard register usage. */
-
-#define INT_REGNO_P(N) ( (int)(N) >= 0 && (N) < 16 )
-#ifdef IEEE_FLOAT
-#define FLOAT_REGNO_P(N) ( (N) >= 16 && (N) < 32 )
-#else
-#define FLOAT_REGNO_P(N) ( (N) >= 16 && (N) < 20 )
-#endif
-#define CC_REGNO_P(N) ( (N) == 33 )
-
-/* Number of actual hardware registers. The hardware registers are
- assigned numbers for the compiler from 0 to just below
- FIRST_PSEUDO_REGISTER.
- All registers that the compiler knows about must be given numbers,
- even those that are not normally considered general registers.
- For the 390, we give the data registers numbers 0-15,
- and the floating point registers numbers 16-19.
- G5 and following have 16 IEEE floating point register,
- which get numbers 16-31. */
+/* We use "unsigned char" as default. */
+#define DEFAULT_SIGNED_CHAR 0
-#define FIRST_PSEUDO_REGISTER 35
-/* Number of hardware registers that go into the DWARF-2 unwind info.
- If not defined, equals FIRST_PSEUDO_REGISTER. */
+/* Register usage. */
-#define DWARF_FRAME_REGISTERS 34
+/* We have 16 general purpose registers (registers 0-15),
+ and 16 floating point registers (registers 16-31).
+ (On non-IEEE machines, we have only 4 fp registers.)
+
+ Amongst the general purpose registers, some are used
+ for specific purposes:
+ GPR 11: Hard frame pointer (if needed)
+ GPR 12: Global offset table pointer (if needed)
+ GPR 13: Literal pool base register
+ GPR 14: Return address register
+ GPR 15: Stack pointer
+
+ Registers 32-34 are 'fake' hard registers that do not
+ correspond to actual hardware:
+ Reg 32: Argument pointer
+ Reg 33: Condition code
+ Reg 34: Frame pointer */
-/* The following register have a fix usage
- GPR 12: GOT register points to the GOT, setup in prologue,
- GOT contains pointer to variables in shared libraries
- GPR 13: Base register setup in prologue to point to the
- literal table of each function
- GPR 14: Return registers holds the return address
- GPR 15: Stack pointer */
+#define FIRST_PSEUDO_REGISTER 35
+
+/* Standard register usage. */
+#define GENERAL_REGNO_P(N) ((int)(N) >= 0 && (N) < 16)
+#define ADDR_REGNO_P(N) ((N) >= 1 && (N) < 16)
+#define FP_REGNO_P(N) ((N) >= 16 && (N) < (TARGET_IEEE_FLOAT? 32 : 20))
+#define CC_REGNO_P(N) ((N) == 33)
+#define FRAME_REGNO_P(N) ((N) == 32 || (N) == 34)
+
+#define GENERAL_REG_P(X) (REG_P (X) && GENERAL_REGNO_P (REGNO (X)))
+#define ADDR_REG_P(X) (REG_P (X) && ADDR_REGNO_P (REGNO (X)))
+#define FP_REG_P(X) (REG_P (X) && FP_REGNO_P (REGNO (X)))
+#define CC_REG_P(X) (REG_P (X) && CC_REGNO_P (REGNO (X)))
+#define FRAME_REG_P(X) (REG_P (X) && FRAME_REGNO_P (REGNO (X)))
-#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 12 : INVALID_REGNUM)
#define BASE_REGISTER 13
#define RETURN_REGNUM 14
-#define STACK_POINTER_REGNUM 15
+#define CC_REGNUM 33
+
+/* Set up fixed registers and calling convention:
+
+ GPRs 0-5 are always call-clobbered,
+ GPRs 6-15 are always call-saved.
+ GPR 12 is fixed if used as GOT pointer.
+ GPR 13 is always fixed (as literal pool pointer).
+ GPR 14 is always fixed (as return address).
+ GPR 15 is always fixed (as stack pointer).
+ The 'fake' hard registers are call-clobbered and fixed.
+
+ On 31-bit, FPRs 18-19 are call-clobbered;
+ on 64-bit, FPRs 24-31 are call-clobbered.
+ The remaining FPRs are call-saved. */
#define FIXED_REGISTERS \
{ 0, 0, 0, 0, \
@@ -280,12 +245,6 @@ if (INTEGRAL_MODE_P (MODE) && \
0, 0, 0, 0, \
1, 1, 1 }
-/* 1 for registers not available across function calls. These must include
- the FIXED_REGISTERS and also any registers that can be used without being
- saved.
- The latter must include the registers where values are returned
- and the register where structure-value addresses are passed. */
-
#define CALL_USED_REGISTERS \
{ 1, 1, 1, 1, \
1, 1, 0, 0, \
@@ -297,10 +256,6 @@ if (INTEGRAL_MODE_P (MODE) && \
1, 1, 1, 1, \
1, 1, 1 }
-/* Like `CALL_USED_REGISTERS' except this macro doesn't require that
- the entire set of `FIXED_REGISTERS' be included.
- (`CALL_USED_REGISTERS' must be a superset of `FIXED_REGISTERS'). */
-
#define CALL_REALLY_USED_REGISTERS \
{ 1, 1, 1, 1, \
1, 1, 0, 0, \
@@ -312,8 +267,6 @@ if (INTEGRAL_MODE_P (MODE) && \
1, 1, 1, 1, \
1, 1, 1 }
-/* Macro to conditionally modify fixed_regs/call_used_regs. */
-
#define CONDITIONAL_REGISTER_USAGE \
do \
{ \
@@ -336,160 +289,85 @@ do \
} \
} while (0)
-/* The following register have a special usage
- GPR 11: Frame pointer if needed to point to automatic variables.
- GPR 32: In functions with more the 5 args this register
- points to that arguments, it is always eliminated
- with stack- or frame-pointer.
- GPR 33: Condition code 'register' */
-
-#define HARD_FRAME_POINTER_REGNUM 11
-#define FRAME_POINTER_REGNUM 34
-
-#define ARG_POINTER_REGNUM 32
-
-#define CC_REGNUM 33
-
-/* We use the register %r0 to pass the static chain to a nested function.
-
- Note: It is assumed that this register is call-clobbered!
- We can't use any of the function-argument registers either,
- and register 1 is needed by the trampoline code, so we have
- no other choice but using this one ... */
+/* Preferred register allocation order. */
+#define REG_ALLOC_ORDER \
+{ 1, 2, 3, 4, 5, 0, 14, 13, 12, 11, 10, 9, 8, 7, 6, \
+ 16, 17, 18, 19, 20, 21, 22, 23, \
+ 24, 25, 26, 27, 28, 29, 30, 31, \
+ 15, 32, 33, 34 }
-#define STATIC_CHAIN_REGNUM 0
-/* Return number of consecutive hard regs needed starting at reg REGNO
- to hold something of mode MODE.
- This is ordinarily the length in words of a value of mode MODE
- but can be less for certain modes in special long registers. */
+/* Fitting values into registers. */
+
+/* Integer modes <= word size fit into any GPR.
+ Integer modes > word size fit into successive GPRs, starting with
+ an even-numbered register.
+ SImode and DImode fit into FPRs as well.
+
+ Floating point modes <= word size fit into any FPR or GPR.
+ Floating point modes > word size (i.e. DFmode on 32-bit) fit
+ into any FPR, or an even-odd GPR pair.
+
+ Complex floating point modes fit either into two FPRs, or into
+ successive GPRs (again starting with an even number).
+
+ Condition code modes fit only into the CC register. */
#define HARD_REGNO_NREGS(REGNO, MODE) \
- (FLOAT_REGNO_P(REGNO)? \
+ (FP_REGNO_P(REGNO)? \
(GET_MODE_CLASS(MODE) == MODE_COMPLEX_FLOAT ? 2 : 1) : \
- INT_REGNO_P(REGNO)? \
+ GENERAL_REGNO_P(REGNO)? \
((GET_MODE_SIZE(MODE)+UNITS_PER_WORD-1) / UNITS_PER_WORD) : \
1)
-/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
- The gprs can hold QI, HI, SI, SF, DF, SC and DC.
- Even gprs can hold DI.
- The floating point registers can hold DF, SF, DC and SC. */
-
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
- (FLOAT_REGNO_P(REGNO)? \
- (GET_MODE_CLASS(MODE) == MODE_FLOAT || \
- GET_MODE_CLASS(MODE) == MODE_COMPLEX_FLOAT || \
- (MODE) == SImode || (MODE) == DImode) : \
- INT_REGNO_P(REGNO)? \
+ (FP_REGNO_P(REGNO)? \
+ ((MODE) == SImode || (MODE) == DImode || \
+ GET_MODE_CLASS(MODE) == MODE_FLOAT || \
+ GET_MODE_CLASS(MODE) == MODE_COMPLEX_FLOAT) : \
+ GENERAL_REGNO_P(REGNO)? \
(HARD_REGNO_NREGS(REGNO, MODE) == 1 || !((REGNO) & 1)) : \
CC_REGNO_P(REGNO)? \
GET_MODE_CLASS (MODE) == MODE_CC : \
+ FRAME_REGNO_P(REGNO)? \
+ (enum machine_mode) (MODE) == Pmode : \
0)
-/* Value is 1 if it is a good idea to tie two pseudo registers when one has
- mode MODE1 and one has mode MODE2.
- If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
- for any hard reg, then this must be 0 for correct output. */
-
#define MODES_TIEABLE_P(MODE1, MODE2) \
(((MODE1) == SFmode || (MODE1) == DFmode) \
== ((MODE2) == SFmode || (MODE2) == DFmode))
-/* If defined, gives a class of registers that cannot be used as the
- operand of a SUBREG that changes the mode of the object illegally. */
-
-#define CLASS_CANNOT_CHANGE_MODE FP_REGS
-
-/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE. */
-
-#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
-
-/* Define this macro if references to a symbol must be treated
- differently depending on something about the variable or
- function named by the symbol (such as what section it is in).
-
- On s390, if using PIC, mark a SYMBOL_REF for a non-global symbol
- so that we may access it directly in the GOT. */
-
-#define ENCODE_SECTION_INFO(DECL) \
-do \
- { \
- if (flag_pic) \
- { \
- rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
- ? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \
- \
- if (GET_CODE (rtl) == MEM) \
- { \
- SYMBOL_REF_FLAG (XEXP (rtl, 0)) \
- = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
- || ! TREE_PUBLIC (DECL)); \
- } \
- } \
- } \
-while (0)
-
-
-/* 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}, \
- { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
- { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
-
-#define CAN_ELIMINATE(FROM, TO) (1)
-
-#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
-{ if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
- { (OFFSET) = 0; } \
- else if ((FROM) == FRAME_POINTER_REGNUM \
- && (TO) == HARD_FRAME_POINTER_REGNUM) \
- { (OFFSET) = 0; } \
- else if ((FROM) == ARG_POINTER_REGNUM \
- && (TO) == HARD_FRAME_POINTER_REGNUM) \
- { (OFFSET) = s390_arg_frame_offset (); } \
- else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
- { (OFFSET) = s390_arg_frame_offset (); } \
- else \
- abort(); \
-}
-
-#define CAN_DEBUG_WITHOUT_FP
-
-/* Value should be nonzero if functions must have frame pointers.
- Zero means the frame pointer need not be set up (and parms may be
- accessed via the stack pointer) in functions that seem suitable.
- This is computed in `reload', in reload1.c. */
+/* Maximum number of registers to represent a value of mode MODE
+ in a register of class CLASS. */
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((CLASS) == FP_REGS ? \
+ (GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT ? 2 : 1) : \
+ (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-#define FRAME_POINTER_REQUIRED 0
+/* If a 4-byte value is loaded into a FPR, it is placed into the
+ *upper* half of the register, not the lower. Therefore, we
+ cannot use SUBREGs to switch between modes in FP registers. */
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? reg_classes_intersect_p (FP_REGS, CLASS) : 0)
-/* Define the classes of registers for register constraints in the
- machine description. Also define ranges of constants.
-
- One of the classes must always be named ALL_REGS and include all hard regs.
- If there is more than one class, another class must be named NO_REGS
- and contain no registers.
+/* Register classes. */
- The name GENERAL_REGS must be the name of a class (or an alias for
- another name such as ALL_REGS). This is the class of registers
- that is allowed by "g" or "r" in a register constraint.
- Also, registers outside this class are allocated only when
- instructions express preferences for them.
-
- The classes must be numbered in nondecreasing order; that is,
- a larger-numbered class must never be contained completely
- in a smaller-numbered class.
-
- For any two classes, it is very desirable that there be another
- class that represents their union. */
-
-/*#define SMALL_REGISTER_CLASSES 1*/
+/* We use the following register classes:
+ GENERAL_REGS All general purpose registers
+ ADDR_REGS All general purpose registers except %r0
+ (These registers can be used in address generation)
+ FP_REGS All floating point registers
+
+ GENERAL_FP_REGS Union of GENERAL_REGS and FP_REGS
+ ADDR_FP_REGS Union of ADDR_REGS and FP_REGS
+
+ NO_REGS No registers
+ ALL_REGS All registers
+
+ Note that the 'fake' frame pointer and argument pointer registers
+ are included amongst the address registers here. The condition
+ code register is only included in ALL_REGS. */
enum reg_class
{
@@ -497,19 +375,13 @@ enum reg_class
FP_REGS, ADDR_FP_REGS, GENERAL_FP_REGS,
ALL_REGS, LIM_REG_CLASSES
};
-
#define N_REG_CLASSES (int) LIM_REG_CLASSES
-/* Give names of register classes as strings for dump file. */
-
#define REG_CLASS_NAMES \
{ "NO_REGS", "ADDR_REGS", "GENERAL_REGS", \
"FP_REGS", "ADDR_FP_REGS", "GENERAL_FP_REGS", "ALL_REGS" }
-/* Define which registers fit in which classes. This is an initializer for
- a vector of HARD_REG_SET of length N_REG_CLASSES.
- G5 and latter have 16 register and support IEEE floating point operations. */
-
+/* Class -> register mapping. */
#define REG_CLASS_CONTENTS \
{ \
{ 0x00000000, 0x00000000 }, /* NO_REGS */ \
@@ -521,105 +393,102 @@ enum reg_class
{ 0xffffffff, 0x00000007 }, /* ALL_REGS */ \
}
+/* Register -> class mapping. */
+extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
+#define REGNO_REG_CLASS(REGNO) (regclass_map[REGNO])
-/* 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. */
+/* ADDR_REGS can be used as base or index register. */
+#define INDEX_REG_CLASS ADDR_REGS
+#define BASE_REG_CLASS ADDR_REGS
-#define REGNO_REG_CLASS(REGNO) (regclass_map[REGNO])
+/* Check whether REGNO is a hard register of the suitable class
+ or a pseudo register currently allocated to one such. */
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+ (((REGNO) < FIRST_PSEUDO_REGISTER \
+ && REGNO_REG_CLASS ((REGNO)) == ADDR_REGS) \
+ || (reg_renumber[REGNO] > 0 && reg_renumber[REGNO] < 16))
+#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_INDEX_P (REGNO)
-extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER]; /* smalled class containing REGNO */
-/* The class value for index registers, and the one for base regs. */
+/* Given an rtx X being reloaded into a reg required to be in class CLASS,
+ return the class of reg to actually use. */
+#define PREFERRED_RELOAD_CLASS(X, CLASS) \
+ s390_preferred_reload_class ((X), (CLASS))
-#define INDEX_REG_CLASS ADDR_REGS
-#define BASE_REG_CLASS ADDR_REGS
+/* We need a secondary reload when loading a PLUS which is
+ not a valid operand for LOAD ADDRESS. */
+#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \
+ s390_secondary_input_reload_class ((CLASS), (MODE), (IN))
+
+/* We need a secondary reload when storing a double-word
+ to a non-offsettable memory address. */
+#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, OUT) \
+ s390_secondary_output_reload_class ((CLASS), (MODE), (OUT))
-/* Get reg_class from a letter such as appears in the machine description. */
+/* We need secondary memory to move data between GPRs and FPRs. */
+#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
+ ((CLASS1) != (CLASS2) && ((CLASS1) == FP_REGS || (CLASS2) == FP_REGS))
+
+/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on 64bit
+ because the movsi and movsf patterns don't handle r/f moves. */
+#define SECONDARY_MEMORY_NEEDED_MODE(MODE) \
+ (GET_MODE_BITSIZE (MODE) < 32 \
+ ? mode_for_size (32, GET_MODE_CLASS (MODE), 0) \
+ : MODE)
+
+
+/* Define various machine-dependent constraint letters. */
#define REG_CLASS_FROM_LETTER(C) \
((C) == 'a' ? ADDR_REGS : \
(C) == 'd' ? GENERAL_REGS : \
(C) == 'f' ? FP_REGS : NO_REGS)
-/* The letters I, J, K, L and M in a register constraint string can be used
- to stand for particular ranges of immediate operands.
- This macro defines what the ranges are.
- C is the letter, and VALUE is a constant value.
- Return 1 if VALUE is in the range specified by C. */
-
#define CONST_OK_FOR_LETTER_P(VALUE, C) \
((C) == 'I' ? (unsigned long) (VALUE) < 256 : \
(C) == 'J' ? (unsigned long) (VALUE) < 4096 : \
(C) == 'K' ? (VALUE) >= -32768 && (VALUE) < 32768 : \
(C) == 'L' ? (unsigned long) (VALUE) < 65536 : 0)
-/* Similar, but for floating constants, and defining letters G and H.
- Here VALUE is the CONST_DOUBLE rtx itself. */
-
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 1
-/* 'Q' means a memory-reference for a S-type operand. */
-
#define EXTRA_CONSTRAINT(OP, C) \
- ((C) == 'Q' ? s_operand (OP, GET_MODE (OP)) : \
+ ((C) == 'Q' ? q_constraint (OP) : \
(C) == 'S' ? larl_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. */
-
-#define PREFERRED_RELOAD_CLASS(X, CLASS) \
- s390_preferred_reload_class ((X), (CLASS))
-
-/* Return the maximum number of consecutive registers needed to represent
- mode MODE in a register of class CLASS. */
-
-#define CLASS_MAX_NREGS(CLASS, MODE) \
- ((CLASS) == FP_REGS ? \
- (GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT ? 2 : 1) : \
- (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* We need a secondary reload when loading a PLUS which is
- not a valid operand for LOAD ADDRESS. */
-
-#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \
- s390_secondary_input_reload_class ((CLASS), (MODE), (IN))
+#define EXTRA_MEMORY_CONSTRAINT(C) ((C) == 'Q')
-/* If we are copying between FP registers and anything else, we need a memory
- location. */
-#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
- ((CLASS1) != (CLASS2) && ((CLASS1) == FP_REGS || (CLASS2) == FP_REGS))
-
-/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on 64bit
- because the movsi and movsf patterns don't handle r/f moves. */
+/* Stack layout and calling conventions. */
+
+/* Our stack grows from higher to lower addresses. However, local variables
+ are accessed by positive offsets, and function arguments are stored at
+ increasing addresses. */
+#define STACK_GROWS_DOWNWARD
+/* #undef FRAME_GROWS_DOWNWARD */
+/* #undef ARGS_GROW_DOWNWARD */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE) \
- (GET_MODE_BITSIZE (MODE) < 32 \
- ? mode_for_size (32, GET_MODE_CLASS (MODE), 0) \
- : MODE)
+/* The basic stack layout looks like this: the stack pointer points
+ to the register save area for called functions. Above that area
+ is the location to place outgoing arguments. Above those follow
+ dynamic allocations (alloca), and finally the local variables. */
+/* Offset from stack-pointer to first location of outgoing args. */
+#define STACK_POINTER_OFFSET (TARGET_64BIT ? 160 : 96)
-/* A C expression whose value is nonzero if pseudos that have been
- assigned to registers of class CLASS would likely be spilled
- because registers of CLASS are needed for spill registers.
+/* Offset within stack frame to start allocating local variables at. */
+extern int current_function_outgoing_args_size;
+#define STARTING_FRAME_OFFSET \
+ (STACK_POINTER_OFFSET + current_function_outgoing_args_size)
- The default value of this macro returns 1 if CLASS has exactly one
- register and zero otherwise. On most machines, this default
- should be used. Only define this macro to some other expression
- if pseudo allocated by `local-alloc.c' end up in memory because
- their hard registers were needed for spill registers. If this
- macro returns nonzero for those classes, those pseudos will only
- be allocated by `global.c', which knows how to reallocate the
- pseudo to another register. If there would not be another
- register available for reallocation, you should not change the
- definition of this macro since the only effect of such a
- definition would be to slow down register allocation. */
+/* Offset from the stack pointer register to an item dynamically
+ allocated on the stack, e.g., by `alloca'. */
+#define STACK_DYNAMIC_OFFSET(FUNDECL) (STARTING_FRAME_OFFSET)
-/* Stack layout; function entry, exit and calling. */
+/* Offset of first parameter from the argument pointer register value.
+ We have a fake argument pointer register that points directly to
+ the argument area. */
+#define FIRST_PARM_OFFSET(FNDECL) 0
/* The return address of the current frame is retrieved
from the initial value of register RETURN_REGNUM.
@@ -631,108 +500,91 @@ extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER]; /* smalled class cont
plus_constant (arg_pointer_rtx, -STACK_POINTER_OFFSET))
#define RETURN_ADDR_RTX(COUNT, FRAME) \
- ((COUNT) == 0 ? get_hard_reg_initial_val (Pmode, RETURN_REGNUM) : \
- gen_rtx_MEM (Pmode, \
- memory_address (Pmode, \
- plus_constant (DYNAMIC_CHAIN_ADDRESS ((FRAME)), \
- RETURN_REGNUM * UNITS_PER_WORD))))
-
-/* The following macros will turn on dwarf2 exception hndling
- Other code location for this exception handling are
- in s390.md (eh_return insn) and in linux.c in the prologue. */
-
-#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, RETURN_REGNUM)
-
-/* We have 31 bit mode. */
+ s390_return_addr_rtx ((COUNT), DYNAMIC_CHAIN_ADDRESS ((FRAME)))
+/* In 31-bit mode, we need to mask off the high bit of return addresses. */
#define MASK_RETURN_ADDR (TARGET_64BIT ? GEN_INT (-1) : GEN_INT (0x7fffffff))
-/* The offset from the incoming value of %sp to the top of the stack frame
- for the current function. */
+/* Exception handling. */
+
+/* Describe calling conventions for DWARF-2 exception handling. */
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, RETURN_REGNUM)
#define INCOMING_FRAME_SP_OFFSET STACK_POINTER_OFFSET
-
-/* Location, from where return address to load. */
-
#define DWARF_FRAME_RETURN_COLUMN 14
/* Describe how we implement __builtin_eh_return. */
#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 6 : INVALID_REGNUM)
-#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 10)
#define EH_RETURN_HANDLER_RTX \
gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, \
TARGET_64BIT? -48 : -40))
-/* Define this if pushing a word on the stack makes the stack pointer a
- smaller address. */
-
-#define STACK_GROWS_DOWNWARD
-
-/* Define this if the nominal address of the stack frame is at the
- high-address end of the local variables; that is, each additional local
- variable allocated goes at a more negative offset in the frame. */
-
-/* #define FRAME_GROWS_DOWNWARD */
-
-/* Offset from stack-pointer to first location of outgoing args. */
+/* Select a format to encode pointers in exception handling data. */
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
+ (flag_pic \
+ ? ((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4 \
+ : DW_EH_PE_absptr)
-#define STACK_POINTER_OFFSET (TARGET_64BIT ? 160 : 96)
-/* 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. */
+/* Frame registers. */
-#define STARTING_FRAME_OFFSET \
- (STACK_POINTER_OFFSET + current_function_outgoing_args_size)
+#define STACK_POINTER_REGNUM 15
+#define FRAME_POINTER_REGNUM 34
+#define HARD_FRAME_POINTER_REGNUM 11
+#define ARG_POINTER_REGNUM 32
-#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) (DEPTH) = 0
+/* The static chain must be call-clobbered, but not used for
+ function argument passing. As register 1 is clobbered by
+ the trampoline code, we only have one option. */
+#define STATIC_CHAIN_REGNUM 0
-/* If we generate an insn to push BYTES bytes, this says how many the stack
- pointer really advances by. On S/390, we have no push instruction. */
+/* Number of hardware registers that go into the DWARF-2 unwind info.
+ To avoid ABI incompatibility, this number must not change even as
+ 'fake' hard registers are added or removed. */
+#define DWARF_FRAME_REGISTERS 34
-/* #define PUSH_ROUNDING(BYTES) */
-/* Accumulate the outgoing argument count so we can request the right
- DSA size and determine stack offset. */
+/* Frame pointer and argument pointer elimination. */
-#define ACCUMULATE_OUTGOING_ARGS 1
+#define FRAME_POINTER_REQUIRED 0
-/* Offset from the stack pointer register to an item dynamically
- allocated on the stack, e.g., by `alloca'.
+#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) (DEPTH) = 0
- 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) (STARTING_FRAME_OFFSET)
+#define ELIMINABLE_REGS \
+{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
-/* Offset of first parameter from the argument pointer register value.
- On the S/390, we define the argument pointer to the start of the fixed
- area. */
-#define FIRST_PARM_OFFSET(FNDECL) 0
+#define CAN_ELIMINATE(FROM, TO) (1)
-/* Define this if stack space is still allocated for a parameter passed
- in a register. The value is the number of bytes allocated to this
- area. */
-/* #define REG_PARM_STACK_SPACE(FNDECL) 32 */
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+{ if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
+ { (OFFSET) = 0; } \
+ else if ((FROM) == FRAME_POINTER_REGNUM \
+ && (TO) == HARD_FRAME_POINTER_REGNUM) \
+ { (OFFSET) = 0; } \
+ else if ((FROM) == ARG_POINTER_REGNUM \
+ && (TO) == HARD_FRAME_POINTER_REGNUM) \
+ { (OFFSET) = s390_arg_frame_offset (); } \
+ else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
+ { (OFFSET) = s390_arg_frame_offset (); } \
+ else \
+ abort(); \
+}
-/* Define this if the above stack space is to be considered part of the
- space allocated by the caller. */
-/* #define OUTGOING_REG_PARM_STACK_SPACE */
-/* 1 if N is a possible register number for function argument passing.
- On S390, general registers 2 - 6 and floating point register 0 and 2
- are used in this way. */
+/* Stack arguments. */
+
+/* We need current_function_outgoing_args to be valid. */
+#define ACCUMULATE_OUTGOING_ARGS 1
-#define FUNCTION_ARG_REGNO_P(N) (((N) >=2 && (N) <7) || \
- (N) == 16 || (N) == 17)
+/* Return doesn't modify the stack. */
+#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, SIZE) 0
-/* Define a data type for recording info about an argument list during
- the scan of that argument list. This data type should hold all
- necessary information about the function itself and about the args
- processed so far, enough to enable macros such as FUNCTION_ARG to
- determine where the next arg should go. */
+/* Register arguments. */
+
typedef struct s390_arg_structure
{
int gprs; /* gpr so far */
@@ -740,84 +592,30 @@ typedef struct s390_arg_structure
}
CUMULATIVE_ARGS;
-
-/* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to
- a function whose data type is FNTYPE.
- For a library call, FNTYPE is 0. */
-
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, NN) \
((CUM).gprs=0, (CUM).fprs=0)
-/* 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.) */
-
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
s390_function_arg_advance (&CUM, MODE, TYPE, NAMED)
-/* 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. */
-
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
s390_function_arg (&CUM, MODE, TYPE, NAMED)
-/* Define where to expect the arguments of a function. Value is zero, if
- the argument is on the stack, or a hard register in which the argument
- is stored. It is the same like FUNCTION_ARG, except for unnamed args
- That means, that all in case of varargs used, the arguments are expected
- from the stack.
- S/390 has already space on the stack for args coming in registers,
- they are pushed in prologue, if needed. */
-
-
-/* Define the `__builtin_va_list' type. */
-
-#define BUILD_VA_LIST_TYPE(VALIST) \
- (VALIST) = s390_build_va_list ()
-
-/* Implement `va_start' for varargs and stdarg. */
-
-#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
- s390_va_start (stdarg, valist, nextarg)
-
-/* Implement `va_arg'. */
-
-#define EXPAND_BUILTIN_VA_ARG(valist, type) \
- s390_va_arg (valist, type)
-
-/* 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. */
-
-#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
-
-
-/* Define if returning from a function call automatically pops the
- arguments described by the number-of-args field in the call. */
-
-#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, SIZE) 0
-
-
-/* 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 15. */
-
-#define RET_REG(MODE) ((GET_MODE_CLASS (MODE) == MODE_INT \
- || TARGET_SOFT_FLOAT ) ? 2 : 16)
-
-
-/* for structs the address is passed, and the Callee makes a
- copy, only if needed */
-
#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
s390_function_arg_pass_by_reference (MODE, TYPE)
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
-/* Register 2 (and 3) for integral values
- or floating point register 0 (and 2) for fp values are used. */
+/* Arguments can be placed in general registers 2 to 6,
+ or in floating point registers 0 and 2. */
+#define FUNCTION_ARG_REGNO_P(N) (((N) >=2 && (N) <7) || \
+ (N) == 16 || (N) == 17)
+
+/* Scalar return values. */
+
+/* We return scalars in general purpose register 2 for integral values,
+ and floating point register 0 for fp values. */
#define FUNCTION_VALUE(VALTYPE, FUNC) \
gen_rtx_REG ((INTEGRAL_TYPE_P (VALTYPE) \
&& TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
@@ -827,133 +625,77 @@ CUMULATIVE_ARGS;
/* Define how to find the value returned by a library function assuming
the value has mode MODE. */
-
+#define RET_REG(MODE) ((GET_MODE_CLASS (MODE) == MODE_INT \
+ || TARGET_SOFT_FLOAT ) ? 2 : 16)
#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, RET_REG (MODE))
-/* 1 if N is a possible register number for a function value. */
-
+/* Only gpr 2 and fpr 0 are ever used as return registers. */
#define FUNCTION_VALUE_REGNO_P(N) ((N) == 2 || (N) == 16)
+
+/* Aggregate return values. */
+
/* The definition of this macro implies that there are cases where
a scalar value cannot be returned in registers. */
-
#define RETURN_IN_MEMORY(type) \
(TYPE_MODE (type) == BLKmode || \
GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_INT || \
GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT)
-/* Mode of stack savearea.
- FUNCTION is VOIDmode because calling convention maintains SP.
- BLOCK needs Pmode for SP.
- NONLOCAL needs twice Pmode to maintain both backchain and SP. */
-
-#define STACK_SAVEAREA_MODE(LEVEL) \
- (LEVEL == SAVE_FUNCTION ? VOIDmode \
- : LEVEL == SAVE_NONLOCAL ? (TARGET_64BIT ? TImode : DImode) : Pmode)
-
/* Structure value address is passed as invisible first argument (gpr 2). */
-
#define STRUCT_VALUE 0
-/* This macro definition sets up a default value for `main' to return. */
-
-#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node)
-
-/* Length in units of the trampoline for entering a nested function. */
-
-#define TRAMPOLINE_SIZE (TARGET_64BIT ? 36 : 20)
-
-/* Initialize the dynamic part of trampoline. */
-
-#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, CXT) \
- s390_initialize_trampoline ((ADDR), (FNADDR), (CXT))
-/* Template for constant part of trampoline. */
+/* Function entry and exit. */
+
+/* When returning from a function, the stack pointer does not matter. */
+#define EXIT_IGNORE_STACK 1
-#define TRAMPOLINE_TEMPLATE(FILE) \
- s390_trampoline_template (FILE)
-/* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry. */
+/* Profiling. */
#define FUNCTION_PROFILER(FILE, LABELNO) \
- s390_function_profiler ((FILE), ((LABELNO)))
+ s390_function_profiler ((FILE), ((LABELNO)))
#define PROFILE_BEFORE_PROLOGUE 1
-/* Define EXIT_IGNORE_STACK if, when returning from a function, the stack
- pointer does not matter (provided there is a frame pointer). */
-
-#define EXIT_IGNORE_STACK 1
-
-/* Addressing modes, and classification of registers for them. */
-
-/* #define HAVE_POST_INCREMENT */
-/* #define HAVE_POST_DECREMENT */
-/* #define HAVE_PRE_DECREMENT */
-/* #define HAVE_PRE_INCREMENT */
+/* Implementing the varargs macros. */
-/* These assume that REGNO is a hard or pseudo reg number. They give
- nonzero only if REGNO is a hard reg of the suitable class or a pseudo
- reg currently allocated to a suitable hard reg.
- These definitions are NOT overridden anywhere. */
-
-#define REGNO_OK_FOR_INDEX_P(REGNO) \
- (((REGNO) < FIRST_PSEUDO_REGISTER \
- && REGNO_REG_CLASS ((REGNO)) == ADDR_REGS) \
- || (reg_renumber[REGNO] > 0 && reg_renumber[REGNO] < 16))
-
-#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_INDEX_P (REGNO)
+#define BUILD_VA_LIST_TYPE(VALIST) \
+ (VALIST) = s390_build_va_list ()
-#define REGNO_OK_FOR_DATA_P(REGNO) \
- ((REGNO) < 16 || (unsigned) reg_renumber[REGNO] < 16)
+#define EXPAND_BUILTIN_VA_START(valist, nextarg) \
+ s390_va_start (valist, nextarg)
-#define REGNO_OK_FOR_FP_P(REGNO) \
- FLOAT_REGNO_P (REGNO)
+#define EXPAND_BUILTIN_VA_ARG(valist, type) \
+ s390_va_arg (valist, type)
-/* Now macros that check whether X is a register and also,
- strictly, whether it is in a specified class. */
-/* 1 if X is a data register. */
+/* Trampolines for nested functions. */
-#define DATA_REG_P(X) (REG_P (X) && REGNO_OK_FOR_DATA_P (REGNO (X)))
+#define TRAMPOLINE_SIZE (TARGET_64BIT ? 36 : 20)
-/* 1 if X is an fp register. */
+#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, CXT) \
+ s390_initialize_trampoline ((ADDR), (FNADDR), (CXT))
-#define FP_REG_P(X) (REG_P (X) && REGNO_OK_FOR_FP_P (REGNO (X)))
+#define TRAMPOLINE_TEMPLATE(FILE) \
+ s390_trampoline_template (FILE)
-/* 1 if X is an address register. */
-#define ADDRESS_REG_P(X) (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X)))
+/* Library calls. */
+
+/* We should use memcpy, not bcopy. */
+#define TARGET_MEM_FUNCTIONS
-/* Maximum number of registers that can appear in a valid memory address. */
-#define MAX_REGS_PER_ADDRESS 2
+/* Addressing modes, and classification of registers for them. */
/* Recognize any constant value that is a valid address. */
-
#define CONSTANT_ADDRESS_P(X) 0
-#define SYMBOLIC_CONST(X) \
-(GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == LABEL_REF \
- || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
-
-/* General operand is everything except SYMBOL_REF, CONST and CONST_DOUBLE
- they have to be forced to constant pool
- CONST_INT have to be forced into constant pool, if greater than
- 64k. Depending on the insn they have to be force into constant pool
- for smaller value; in this case we have to work with nonimmediate operand. */
-
-#define LEGITIMATE_PIC_OPERAND_P(X) \
- legitimate_pic_operand_p (X)
-
-/* Nonzero if the constant value X is a legitimate general operand.
- It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
-
-#define LEGITIMATE_CONSTANT_P(X) \
- legitimate_constant_p (X)
+/* Maximum number of registers that can appear in a valid memory address. */
+#define MAX_REGS_PER_ADDRESS 2
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx and check
its validity for a certain class. We have two alternate definitions
@@ -966,32 +708,19 @@ CUMULATIVE_ARGS;
Some source files that are used after register allocation
need to be strict. */
-/*
- * Nonzero if X is a hard reg that can be used as an index or if it is
- * a pseudo reg.
- */
-
#define REG_OK_FOR_INDEX_NONSTRICT_P(X) \
((GET_MODE (X) == Pmode) && \
((REGNO (X) >= FIRST_PSEUDO_REGISTER) \
|| REGNO_REG_CLASS (REGNO (X)) == ADDR_REGS))
-/* 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_NONSTRICT_P(X) REG_OK_FOR_INDEX_NONSTRICT_P (X)
-/* Nonzero if X is a hard reg that can be used as an index. */
-
#define REG_OK_FOR_INDEX_STRICT_P(X) \
((GET_MODE (X) == Pmode) && (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_STRICT_P(X) \
((GET_MODE (X) == Pmode) && (REGNO_OK_FOR_BASE_P (REGNO (X))))
-
#ifndef REG_OK_STRICT
#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_NONSTRICT_P(X)
#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_NONSTRICT_P(X)
@@ -1000,15 +729,13 @@ CUMULATIVE_ARGS;
#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P(X)
#endif
+/* S/390 has no mode dependent addresses. */
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression that is a
valid memory address for an instruction.
The MODE argument is the machine mode for the MEM expression
- that wants to use this address.
-
- The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS,
- except for CONSTANT_ADDRESS_P which is actually machine-independent. */
-
+ that wants to use this address. */
#ifdef REG_OK_STRICT
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
{ \
@@ -1023,15 +750,9 @@ CUMULATIVE_ARGS;
}
#endif
-
-/* S/390 has no mode dependent addresses. */
-
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
-
/* Try machine-dependent ways of modifying an illegitimate address
to be legitimate. If we find one, return the new, valid address.
This macro is used in only one place: `memory_address' in explow.c. */
-
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
{ \
(X) = legitimize_address (X, OLDX, MODE); \
@@ -1039,73 +760,35 @@ CUMULATIVE_ARGS;
goto WIN; \
}
-/* Specify the machine mode that this machine uses for the index in the
- tablejump instruction. */
-
-#define CASE_VECTOR_MODE (TARGET_64BIT ? DImode : SImode)
-
-/* Define this if the tablejump instruction expects the table to contain
- offsets from the address of the table.
- Do not define this if the table should contain absolute addresses. */
-
-/* #define CASE_VECTOR_PC_RELATIVE */
-
-/* Load from integral MODE < SI from memory into register makes sign_extend
- or zero_extend
- In our case sign_extension happens for Halfwords, other no extension. */
-
-#define LOAD_EXTEND_OP(MODE) \
-(TARGET_64BIT ? ((MODE) == QImode ? ZERO_EXTEND : \
- (MODE) == HImode ? SIGN_EXTEND : NIL) \
- : ((MODE) == HImode ? SIGN_EXTEND : NIL))
-
-/* Define this if fixuns_trunc is the same as fix_trunc. */
-
-/* #define FIXUNS_TRUNC_LIKE_FIX_TRUNC */
-
-/* We use "unsigned char" as default. */
-
-#define DEFAULT_SIGNED_CHAR 0
-
-/* Max number of bytes we can move from memory to memory in one reasonably
- fast instruction. */
-
-#define MOVE_MAX 256
-
-/* Nonzero if access to memory by bytes is slow and undesirable. */
-
-#define SLOW_BYTE_ACCESS 1
-
-/* Define if shifts truncate the shift count which implies one can omit
- a sign-extension or zero-extension of a shift count. */
-
-/* #define SHIFT_COUNT_TRUNCATED */
-
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
- is done just by pretending it is already truncated. */
-
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
-/* We assume that the store-condition-codes instructions store 0 for false
- and some other value for true. This is the value stored for true. */
-
-/* #define STORE_FLAG_VALUE -1 */
+/* Nonzero if the constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+#define LEGITIMATE_CONSTANT_P(X) \
+ legitimate_constant_p (X)
-/* Don't perform CSE on function addresses. */
+/* Helper macro for s390.c and s390.md to check for symbolic constants. */
+#define SYMBOLIC_CONST(X) \
+(GET_CODE (X) == SYMBOL_REF \
+ || GET_CODE (X) == LABEL_REF \
+ || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
-#define NO_FUNCTION_CSE
+#define TLS_SYMBOLIC_CONST(X) \
+((GET_CODE (X) == SYMBOL_REF && tls_symbolic_operand (X)) \
+ || (GET_CODE (X) == CONST && tls_symbolic_reference_mentioned_p (X)))
-/* 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 ((enum machine_mode) (TARGET_64BIT ? DImode : SImode))
+/* Condition codes. */
-/* A function address in a call instruction is a byte address (for
- indexing purposes) so give the MEM rtx a byte's mode. */
+/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
+ return the mode to be used for the comparison. */
+#define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y))
+
+/* Define the information needed to generate branch and scc insns. This is
+ stored from the compare operation. Note that we can't use "rtx" here
+ since it hasn't been defined! */
+extern struct rtx_def *s390_compare_op0, *s390_compare_op1;
-#define FUNCTION_MODE QImode
+/* Relative costs of operations. */
/* A part of a C `switch' statement that describes the relative costs
of constant RTL expressions. It must contain `case' labels for
@@ -1126,7 +809,6 @@ CUMULATIVE_ARGS;
than a short. Because of that we give an addition of greater
constants a cost of 3 (reload1.c 10096). */
-
#define CONST_COSTS(RTX, CODE, OUTER_CODE) \
case CONST: \
if ((GET_CODE (XEXP (RTX, 0)) == MINUS) && \
@@ -1148,10 +830,7 @@ CUMULATIVE_ARGS;
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. */
+ is contained. */
#define RTX_COSTS(X, CODE, OUTER_CODE) \
case ASHIFT: \
@@ -1164,155 +843,72 @@ CUMULATIVE_ARGS;
case MINUS: \
case NEG: \
case NOT: \
- return 1; \
+ return COSTS_N_INSNS (1); \
case MULT: \
if (GET_MODE (XEXP (X, 0)) == DImode) \
- return 40; \
- else \
- return 7; \
+ return COSTS_N_INSNS (40); \
+ else \
+ return COSTS_N_INSNS (7); \
case DIV: \
case UDIV: \
case MOD: \
case UMOD: \
- return 33;
+ return COSTS_N_INSNS (33);
/* 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.
-
- On s390 symbols are expensive if compiled with fpic
- lifetimes. */
-
-#define ADDRESS_COST(RTX) \
- ((flag_pic && GET_CODE (RTX) == SYMBOL_REF) ? 2 : 1)
+ expression and the `CONST_COSTS' values. */
+#define ADDRESS_COST(RTX) s390_address_cost ((RTX))
/* On s390, copy between fprs and gprs is expensive. */
-
#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
(( ( reg_classes_intersect_p ((CLASS1), GENERAL_REGS) \
&& reg_classes_intersect_p ((CLASS2), FP_REGS)) \
|| ( reg_classes_intersect_p ((CLASS1), FP_REGS) \
&& reg_classes_intersect_p ((CLASS2), GENERAL_REGS))) ? 10 : 1)
-
/* 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. */
-
+ relative to those in `REGISTER_MOVE_COST'. */
#define MEMORY_MOVE_COST(M, C, I) 1
/* 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 1
-/* Add any extra modes needed to represent the condition code. */
-#define EXTRA_CC_MODES \
- CC (CCZmode, "CCZ") \
- CC (CCAmode, "CCA") \
- CC (CCLmode, "CCL") \
- CC (CCUmode, "CCU") \
- CC (CCSmode, "CCS") \
- CC (CCTmode, "CCT")
-
-/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
- return the mode to be used for the comparison. */
-
-#define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y))
-
-
-/* Define the information needed to generate branch and scc insns. This is
- stored from the compare operation. Note that we can't use "rtx" here
- since it hasn't been defined! */
-
-extern struct rtx_def *s390_compare_op0, *s390_compare_op1;
-
-
-/* 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", "%r7", \
- "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", \
- "%f0", "%f2", "%f4", "%f6", "%f1", "%f3", "%f5", "%f7", \
- "%f8", "%f10", "%f12", "%f14", "%f9", "%f11", "%f13", "%f15", \
- "%ap", "%cc", "%fp" \
-}
+/* Nonzero if access to memory by bytes is slow and undesirable. */
+#define SLOW_BYTE_ACCESS 1
-/* implicit call of memcpy, not bcopy */
+/* The maximum number of bytes that a single instruction can move quickly
+ between memory and registers or between two memory locations. */
+#define MOVE_MAX (TARGET_64BIT ? 16 : 8)
+#define MAX_MOVE_MAX 16
-#define TARGET_MEM_FUNCTIONS
+/* Determine whether to use move_by_pieces or block move insn. */
+#define MOVE_BY_PIECES_P(SIZE, ALIGN) \
+ ( (SIZE) == 1 || (SIZE) == 2 || (SIZE) == 4 \
+ || (TARGET_64BIT && (SIZE) == 8) )
-/* Either simplify a location expression, or return the original. */
+/* Determine whether to use clear_by_pieces or block clear insn. */
+#define CLEAR_BY_PIECES_P(SIZE, ALIGN) \
+ ( (SIZE) == 1 || (SIZE) == 2 || (SIZE) == 4 \
+ || (TARGET_64BIT && (SIZE) == 8) )
-#define ASM_SIMPLIFY_DWARF_ADDR(X) \
- s390_simplify_dwarf_addr (X)
-
-/* Print operand X (an rtx) in assembler syntax to file FILE.
- CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
- For `%' followed by punctuation, CODE is the punctuation and X is null. */
-
-#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE)
+/* Don't perform CSE on function addresses. */
+#define NO_FUNCTION_CSE
-#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
+/* Sections. */
-/* Define the codes that are matched by predicates in aux-output.c. */
+/* Output before read-only data. */
+#define TEXT_SECTION_ASM_OP ".text"
-#define PREDICATE_CODES \
- {"s_operand", { SUBREG, MEM }}, \
- {"s_imm_operand", { CONST_INT, CONST_DOUBLE, SUBREG, MEM }}, \
- {"bras_sym_operand",{ SYMBOL_REF, CONST }}, \
- {"larl_operand", { SYMBOL_REF, CONST, CONST_INT, CONST_DOUBLE }}, \
- {"load_multiple_operation", {PARALLEL}}, \
- {"store_multiple_operation", {PARALLEL}}, \
- {"const0_operand", { CONST_INT, CONST_DOUBLE }}, \
- {"consttable_operand", { SYMBOL_REF, LABEL_REF, CONST, \
- CONST_INT, CONST_DOUBLE }}, \
- {"s390_plus_operand", { PLUS }},
+/* Output before writable (initialized) data. */
+#define DATA_SECTION_ASM_OP ".data"
+/* Output before writable (uninitialized) data. */
+#define BSS_SECTION_ASM_OP ".bss"
/* S/390 constant pool breaks the devices in crtstuff.c to control section
in where code resides. We have to write it as asm code. */
@@ -1326,12 +922,97 @@ extern struct rtx_def *s390_compare_op0, *s390_compare_op1;
.previous");
#endif
+
+/* Position independent code. */
+
+extern int flag_pic;
+
+#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 12 : INVALID_REGNUM)
+
+#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)
+
+
+/* Assembler file format. */
+
+/* Character to start a comment. */
+#define ASM_COMMENT_START "#"
+
+/* Declare an uninitialized external linkage data object. */
+#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
+ asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
+
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP ".globl "
+
+/* Advance the location counter to a multiple of 2**LOG bytes. */
+#define ASM_OUTPUT_ALIGN(FILE, LOG) \
+ if ((LOG)) fprintf ((FILE), "\t.align\t%d\n", 1 << (LOG))
+
+/* Advance the location counter by SIZE bytes. */
+#define ASM_OUTPUT_SKIP(FILE, SIZE) \
+ fprintf ((FILE), "\t.set\t.,.+%u\n", (SIZE))
+
+/* Output a reference to a user-level label named NAME. */
+#define ASM_OUTPUT_LABELREF(FILE, NAME) \
+ asm_fprintf ((FILE), "%U%s", (*targetm.strip_name_encoding) (NAME))
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+ ((OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
+
+/* The LOCAL_LABEL_PREFIX variable is used by dbxelf.h. */
+#define LOCAL_LABEL_PREFIX "."
+
+/* Either simplify a location expression, or return the original. */
+#define ASM_SIMPLIFY_DWARF_ADDR(X) \
+ s390_simplify_dwarf_addr (X)
+
+/* 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", "%r7", \
+ "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", \
+ "%f0", "%f2", "%f4", "%f6", "%f1", "%f3", "%f5", "%f7", \
+ "%f8", "%f10", "%f12", "%f14", "%f9", "%f11", "%f13", "%f15", \
+ "%ap", "%cc", "%fp" \
+}
+
+/* Print operand X (an rtx) in assembler syntax to file FILE. */
+#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE)
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
+
+/* Output an element of a case-vector that is absolute. */
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+do { \
+ char buf[32]; \
+ fputs (integer_asm_op (UNITS_PER_WORD, TRUE), (FILE)); \
+ ASM_GENERATE_INTERNAL_LABEL (buf, "L", (VALUE)); \
+ assemble_name ((FILE), buf); \
+ fputc ('\n', (FILE)); \
+} while (0)
+
+/* Output an element of a case-vector that is relative. */
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+do { \
+ char buf[32]; \
+ fputs (integer_asm_op (UNITS_PER_WORD, TRUE), (FILE)); \
+ ASM_GENERATE_INTERNAL_LABEL (buf, "L", (VALUE)); \
+ assemble_name ((FILE), buf); \
+ fputc ('-', (FILE)); \
+ ASM_GENERATE_INTERNAL_LABEL (buf, "L", (REL)); \
+ assemble_name ((FILE), buf); \
+ fputc ('\n', (FILE)); \
+} while (0)
+
+
/* Constant Pool for all symbols operands which are changed with
force_const_mem during insn generation (expand_insn). */
extern int s390_pool_count;
extern int s390_nr_constants;
-extern int s390_pool_overflow;
#define ASM_OUTPUT_POOL_PROLOGUE(FILE, FUNNAME, fndecl, size) \
{ \
@@ -1357,16 +1038,15 @@ extern int s390_pool_overflow;
if (GET_CODE (EXP) != CONST_DOUBLE) \
abort (); \
\
- memcpy ((char *) &u, (char *) &CONST_DOUBLE_LOW (EXP), sizeof u); \
- assemble_real (u.d, MODE, ALIGN); \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, EXP); \
+ assemble_real (r, MODE, ALIGN); \
break; \
\
case MODE_INT: \
case MODE_PARTIAL_INT: \
- if (flag_pic \
- && (GET_CODE (EXP) == CONST \
- || GET_CODE (EXP) == SYMBOL_REF \
- || GET_CODE (EXP) == LABEL_REF )) \
+ if (GET_CODE (EXP) == CONST \
+ || GET_CODE (EXP) == SYMBOL_REF \
+ || GET_CODE (EXP) == LABEL_REF) \
{ \
fputs (integer_asm_op (UNITS_PER_WORD, TRUE), FILE); \
s390_output_symbolic_const (FILE, EXP); \
@@ -1386,4 +1066,54 @@ extern int s390_pool_overflow;
goto WIN; \
}
+
+/* Miscellaneous parameters. */
+
+/* Define the codes that are matched by predicates in aux-output.c. */
+#define PREDICATE_CODES \
+ {"s_operand", { SUBREG, MEM }}, \
+ {"s_imm_operand", { CONST_INT, CONST_DOUBLE, SUBREG, MEM }}, \
+ {"bras_sym_operand",{ SYMBOL_REF, CONST }}, \
+ {"larl_operand", { SYMBOL_REF, CONST, CONST_INT, CONST_DOUBLE }}, \
+ {"load_multiple_operation", {PARALLEL}}, \
+ {"store_multiple_operation", {PARALLEL}}, \
+ {"const0_operand", { CONST_INT, CONST_DOUBLE }}, \
+ {"consttable_operand", { SYMBOL_REF, LABEL_REF, CONST, \
+ CONST_INT, CONST_DOUBLE }}, \
+ {"s390_plus_operand", { PLUS }},
+
+/* Specify the machine mode that this machine uses for the index in the
+ tablejump instruction. */
+#define CASE_VECTOR_MODE (TARGET_64BIT ? DImode : SImode)
+
+/* Load from integral MODE < SI from memory into register makes sign_extend
+ or zero_extend
+ In our case sign_extension happens for Halfwords, other no extension. */
+#define LOAD_EXTEND_OP(MODE) \
+(TARGET_64BIT ? ((MODE) == QImode ? ZERO_EXTEND : \
+ (MODE) == HImode ? SIGN_EXTEND : NIL) \
+ : ((MODE) == HImode ? SIGN_EXTEND : NIL))
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode ((enum machine_mode) (TARGET_64BIT ? DImode : SImode))
+
+/* A function address in a call instruction is a byte address (for
+ indexing purposes) so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE QImode
+
+/* This macro definition sets up a default value for `main' to return. */
+#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node)
+
+/* 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. */
+#define MACHINE_DEPENDENT_REORG(INSN) s390_machine_dependent_reorg (INSN)
+
#endif
diff --git a/contrib/gcc/config/s390/s390.md b/contrib/gcc/config/s390/s390.md
index 2742638..8178516 100644
--- a/contrib/gcc/config/s390/s390.md
+++ b/contrib/gcc/config/s390/s390.md
@@ -1,5 +1,5 @@
;;- Machine description for GNU compiler -- S/390 / zSeries version.
-;; Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
;; Ulrich Weigand (uweigand@de.ibm.com).
;; This file is part of GNU CC.
@@ -44,6 +44,34 @@
;; s_operand -- Matches a valid S operand in a RS, SI or SS type instruction.
;;
+;;
+;; UNSPEC usage
+;;
+
+(define_constants
+ [; TLS relocation specifiers
+ (UNSPEC_TLSGD 500)
+ (UNSPEC_TLSLDM 501)
+ (UNSPEC_NTPOFF 502)
+ (UNSPEC_DTPOFF 503)
+ (UNSPEC_GOTNTPOFF 504)
+ (UNSPEC_INDNTPOFF 505)
+
+ ; TLS support
+ (UNSPEC_TP 510)
+ (UNSPEC_TLSLDM_NTPOFF 511)
+ (UNSPEC_TLS_LOAD 512)
+ ])
+
+;;
+;; UNSPEC_VOLATILE usage
+;;
+
+(define_constants
+ [; TLS support
+ (UNSPECV_SET_TP 500)
+ ])
+
;; Define an insn type attribute. This is used in function unit delay
;; computations.
@@ -191,30 +219,6 @@
DONE;
}")
-;(define_expand "cmphi"
-; [(set (reg:CC 33)
-; (compare:CC (match_operand:HI 0 "register_operand" "")
-; (match_operand:HI 1 "general_operand" "")))]
-; ""
-; "
-;{
-; s390_compare_op0 = operands[0];
-; s390_compare_op1 = operands[1];
-; DONE;
-;}")
-
-;(define_expand "cmpqi"
-; [(set (reg:CC 33)
-; (compare:CC (match_operand:QI 0 "register_operand" "")
-; (match_operand:QI 1 "general_operand" "")))]
-; ""
-; "
-;{
-; s390_compare_op0 = operands[0];
-; s390_compare_op1 = operands[1];
-; DONE;
-;}")
-
(define_expand "cmpdf"
[(set (reg:CC 33)
(compare:CC (match_operand:DF 0 "register_operand" "")
@@ -240,9 +244,9 @@
}")
-; DI instructions
+; Test-under-Mask (zero_extract) instructions
-(define_insn "*cmpdi_tm2"
+(define_insn "*tmdi_ext"
[(set (reg 33)
(compare (zero_extract:DI (match_operand:DI 0 "register_operand" "d")
(match_operand:DI 1 "const_int_operand" "n")
@@ -272,35 +276,63 @@
}"
[(set_attr "op_type" "RI")])
-(define_insn "*cmpdi_tm_reg"
+(define_insn "*tmsi_ext"
[(set (reg 33)
- (compare (and:DI (match_operand:DI 0 "register_operand" "%d")
- (match_operand:DI 1 "immediate_operand" "n"))
+ (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "const_int_operand" "n"))
(const_int 0)))]
- "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT
- && s390_single_hi (operands[1], DImode, 0) >= 0"
+ "s390_match_ccmode(insn, CCTmode)
+ && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
+ && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
+ && (INTVAL (operands[1]) + INTVAL (operands[2]) - 1) >> 4
+ == INTVAL (operands[2]) >> 4"
"*
{
- int part = s390_single_hi (operands[1], DImode, 0);
- operands[1] = GEN_INT (s390_extract_hi (operands[1], DImode, part));
+ int part = INTVAL (operands[2]) >> 4;
+ int block = (1 << INTVAL (operands[1])) - 1;
+ int shift = 16 - INTVAL (operands[1]) - (INTVAL (operands[2]) & 15);
+
+ operands[2] = GEN_INT (block << shift);
switch (part)
{
- case 0: return \"tmhh\\t%0,%x1\";
- case 1: return \"tmhl\\t%0,%x1\";
- case 2: return \"tmlh\\t%0,%x1\";
- case 3: return \"tmll\\t%0,%x1\";
+ case 0: return \"tmh\\t%0,%x2\";
+ case 1: return \"tml\\t%0,%x2\";
default: abort ();
}
}"
[(set_attr "op_type" "RI")])
-(define_insn "*cmpdi_tm_mem"
+(define_insn "*tmqi_ext"
[(set (reg 33)
- (compare (and:DI (match_operand:DI 0 "s_operand" "%Qo")
- (match_operand:DI 1 "immediate_operand" "n"))
+ (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "Q")
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "const_int_operand" "n"))
(const_int 0)))]
- "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT
+ "s390_match_ccmode(insn, CCTmode)
+ && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
+ && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8"
+ "*
+{
+ int block = (1 << INTVAL (operands[1])) - 1;
+ int shift = 8 - INTVAL (operands[1]) - INTVAL (operands[2]);
+
+ operands[2] = GEN_INT (block << shift);
+ return \"tm\\t%0,%b2\";
+}"
+ [(set_attr "op_type" "SI")
+ (set_attr "atype" "mem")])
+
+; Test-under-Mask instructions
+
+(define_insn "*tmdi_mem"
+ [(set (reg 33)
+ (compare (and:DI (match_operand:DI 0 "memory_operand" "Q")
+ (match_operand:DI 1 "immediate_operand" "n"))
+ (match_operand:DI 2 "immediate_operand" "n")))]
+ "TARGET_64BIT
+ && s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
&& s390_single_qi (operands[1], DImode, 0) >= 0"
"*
{
@@ -314,100 +346,84 @@
[(set_attr "op_type" "SI")
(set_attr "atype" "mem")])
-(define_insn "*ltgr"
+(define_insn "*tmsi_mem"
[(set (reg 33)
- (compare (match_operand:DI 0 "register_operand" "d")
- (match_operand:DI 1 "const0_operand" "")))
- (set (match_operand:DI 2 "register_operand" "=d")
- (match_dup 0))]
- "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
- "ltgr\\t%2,%0"
- [(set_attr "op_type" "RRE")])
+ (compare (and:SI (match_operand:SI 0 "memory_operand" "Q")
+ (match_operand:SI 1 "immediate_operand" "n"))
+ (match_operand:SI 2 "immediate_operand" "n")))]
+ "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
+ && s390_single_qi (operands[1], SImode, 0) >= 0"
+ "*
+{
+ int part = s390_single_qi (operands[1], SImode, 0);
+ operands[1] = GEN_INT (s390_extract_qi (operands[1], SImode, part));
-(define_insn "*cmpdi_ccs_0_64"
- [(set (reg 33)
- (compare (match_operand:DI 0 "register_operand" "d")
- (match_operand:DI 1 "const0_operand" "")))]
- "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
- "ltgr\\t%0,%0"
- [(set_attr "op_type" "RRE")])
+ operands[0] = gen_rtx_MEM (QImode,
+ plus_constant (XEXP (operands[0], 0), part));
+ return \"tm\\t%0,%b1\";
+}"
+ [(set_attr "op_type" "SI")
+ (set_attr "atype" "mem")])
-(define_insn "*cmpdi_ccs_0_31"
+(define_insn "*tmhi_mem"
[(set (reg 33)
- (compare (match_operand:DI 0 "register_operand" "d")
- (match_operand:DI 1 "const0_operand" "")))]
- "s390_match_ccmode(insn, CCSmode)"
- "srda\\t%0,0"
- [(set_attr "op_type" "RS")])
+ (compare (and:SI (subreg:SI (match_operand:HI 0 "memory_operand" "Q") 0)
+ (match_operand:SI 1 "immediate_operand" "n"))
+ (match_operand:SI 2 "immediate_operand" "n")))]
+ "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
+ && s390_single_qi (operands[1], HImode, 0) >= 0"
+ "*
+{
+ int part = s390_single_qi (operands[1], HImode, 0);
+ operands[1] = GEN_INT (s390_extract_qi (operands[1], HImode, part));
-(define_insn "*cmpdi_ccs"
- [(set (reg 33)
- (compare (match_operand:DI 0 "register_operand" "d,d,d")
- (match_operand:DI 1 "general_operand" "d,K,m")))]
- "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
- "@
- cgr\\t%0,%1
- cghi\\t%0,%c1
- cg\\t%0,%1"
- [(set_attr "op_type" "RRE,RI,RXE")
- (set_attr "atype" "reg,reg,mem")])
-
-(define_insn "*cmpdi_ccu"
- [(set (reg 33)
- (compare (match_operand:DI 0 "register_operand" "d,d")
- (match_operand:DI 1 "general_operand" "d,m")))]
- "s390_match_ccmode(insn, CCUmode) && TARGET_64BIT"
- "@
- clgr\\t%0,%1
- clg\\t%0,%1"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "atype" "reg,mem")])
+ operands[0] = gen_rtx_MEM (QImode,
+ plus_constant (XEXP (operands[0], 0), part));
+ return \"tm\\t%0,%b1\";
+}"
+ [(set_attr "op_type" "SI")
+ (set_attr "atype" "mem")])
-(define_insn "*cmpdi_ccu_mem"
+(define_insn "*tmqi_mem"
[(set (reg 33)
- (compare (match_operand:DI 0 "s_operand" "oQ")
- (match_operand:DI 1 "s_imm_operand" "oQ")))]
- "s390_match_ccmode(insn, CCUmode)"
- "clc\\t%O0(8,%R0),%1"
- [(set_attr "op_type" "SS")
+ (compare (and:SI (subreg:SI (match_operand:QI 0 "memory_operand" "Q") 0)
+ (match_operand:SI 1 "immediate_operand" "n"))
+ (match_operand:SI 2 "immediate_operand" "n")))]
+ "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))"
+ "tm\\t%0,%b1"
+ [(set_attr "op_type" "SI")
(set_attr "atype" "mem")])
-; SI instructions
-
-(define_insn "*cmpsi_tm2"
+(define_insn "*tmdi_reg"
[(set (reg 33)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))]
- "s390_match_ccmode(insn, CCTmode)
- && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
- && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
- && (INTVAL (operands[1]) + INTVAL (operands[2]) - 1) >> 4
- == INTVAL (operands[2]) >> 4"
+ (compare (and:DI (match_operand:DI 0 "nonimmediate_operand" "d")
+ (match_operand:DI 1 "immediate_operand" "n"))
+ (match_operand:DI 2 "immediate_operand" "n")))]
+ "TARGET_64BIT
+ && s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 1))
+ && s390_single_hi (operands[1], DImode, 0) >= 0"
"*
{
- int part = INTVAL (operands[2]) >> 4;
- int block = (1 << INTVAL (operands[1])) - 1;
- int shift = 16 - INTVAL (operands[1]) - (INTVAL (operands[2]) & 15);
-
- operands[2] = GEN_INT (block << shift);
+ int part = s390_single_hi (operands[1], DImode, 0);
+ operands[1] = GEN_INT (s390_extract_hi (operands[1], DImode, part));
switch (part)
{
- case 0: return \"tmh\\t%0,%x2\";
- case 1: return \"tml\\t%0,%x2\";
+ case 0: return \"tmhh\\t%0,%x1\";
+ case 1: return \"tmhl\\t%0,%x1\";
+ case 2: return \"tmlh\\t%0,%x1\";
+ case 3: return \"tmll\\t%0,%x1\";
default: abort ();
}
}"
[(set_attr "op_type" "RI")])
-(define_insn "*cmpsi_tm_reg"
+(define_insn "*tmsi_reg"
[(set (reg 33)
- (compare (and:SI (match_operand:SI 0 "register_operand" "%d")
+ (compare (and:SI (match_operand:SI 0 "nonimmediate_operand" "d")
(match_operand:SI 1 "immediate_operand" "n"))
- (const_int 0)))]
- "s390_match_ccmode(insn, CCTmode)
+ (match_operand:SI 2 "immediate_operand" "n")))]
+ "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 1))
&& s390_single_hi (operands[1], SImode, 0) >= 0"
"*
{
@@ -423,57 +439,88 @@
}"
[(set_attr "op_type" "RI")])
-(define_insn "*cmpsi_tm_mem"
+(define_insn "*tmhi_full"
[(set (reg 33)
- (compare (and:SI (match_operand:SI 0 "s_operand" "%Qo")
- (match_operand:SI 1 "immediate_operand" "n"))
- (const_int 0)))]
- "s390_match_ccmode(insn, CCTmode)
- && s390_single_qi (operands[1], SImode, 0) >= 0"
- "*
-{
- int part = s390_single_qi (operands[1], SImode, 0);
- operands[1] = GEN_INT (s390_extract_qi (operands[1], SImode, part));
+ (compare (match_operand:HI 0 "register_operand" "d")
+ (match_operand:HI 1 "immediate_operand" "n")))]
+ "s390_match_ccmode (insn, s390_tm_ccmode (GEN_INT (-1), operands[1], 1))"
+ "tml\\t%0,65535"
+ [(set_attr "op_type" "RX")])
+
+(define_insn "*tmqi_full"
+ [(set (reg 33)
+ (compare (match_operand:QI 0 "register_operand" "d")
+ (match_operand:QI 1 "immediate_operand" "n")))]
+ "s390_match_ccmode (insn, s390_tm_ccmode (GEN_INT (-1), operands[1], 1))"
+ "tml\\t%0,255"
+ [(set_attr "op_type" "RI")])
- operands[0] = gen_rtx_MEM (QImode,
- plus_constant (XEXP (operands[0], 0), part));
- return \"tm\\t%0,%b1\";
-}"
- [(set_attr "op_type" "SI")
- (set_attr "atype" "mem")])
-(define_insn "*ltr"
+; Load-and-Test instructions
+
+(define_insn "*tstdi_sign"
[(set (reg 33)
- (compare (match_operand:SI 0 "register_operand" "d")
- (match_operand:SI 1 "const0_operand" "")))
- (set (match_operand:SI 2 "register_operand" "=d")
+ (compare (ashiftrt:DI (ashift:DI (subreg:DI (match_operand:SI 0 "register_operand" "d") 0)
+ (const_int 32)) (const_int 32))
+ (match_operand:DI 1 "const0_operand" "")))
+ (set (match_operand:DI 2 "register_operand" "=d")
+ (sign_extend:DI (match_dup 0)))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
+ "ltgfr\\t%2,%0"
+ [(set_attr "op_type" "RRE")])
+
+(define_insn "*tstdi"
+ [(set (reg 33)
+ (compare (match_operand:DI 0 "register_operand" "d")
+ (match_operand:DI 1 "const0_operand" "")))
+ (set (match_operand:DI 2 "register_operand" "=d")
(match_dup 0))]
- "s390_match_ccmode(insn, CCSmode)"
- "ltr\\t%2,%0"
- [(set_attr "op_type" "RR")])
+ "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
+ "ltgr\\t%2,%0"
+ [(set_attr "op_type" "RRE")])
-(define_insn "*icm15"
+(define_insn "*tstdi_cconly"
[(set (reg 33)
- (compare (match_operand:SI 0 "s_operand" "Qo")
+ (compare (match_operand:DI 0 "register_operand" "d")
+ (match_operand:DI 1 "const0_operand" "")))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
+ "ltgr\\t%0,%0"
+ [(set_attr "op_type" "RRE")])
+
+(define_insn "*tstdi_cconly_31"
+ [(set (reg 33)
+ (compare (match_operand:DI 0 "register_operand" "d")
+ (match_operand:DI 1 "const0_operand" "")))]
+ "s390_match_ccmode(insn, CCSmode) && !TARGET_64BIT"
+ "srda\\t%0,0"
+ [(set_attr "op_type" "RS")])
+
+(define_insn "*tstsi"
+ [(set (reg 33)
+ (compare (match_operand:SI 0 "nonimmediate_operand" "d,Q")
(match_operand:SI 1 "const0_operand" "")))
- (set (match_operand:SI 2 "register_operand" "=d")
+ (set (match_operand:SI 2 "register_operand" "=d,d")
(match_dup 0))]
"s390_match_ccmode(insn, CCSmode)"
- "icm\\t%2,15,%0"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "mem")])
+ "@
+ ltr\\t%2,%0
+ icm\\t%2,15,%0"
+ [(set_attr "op_type" "RR,RS")
+ (set_attr "atype" "reg,mem")])
-(define_insn "*icm15_cconly"
+(define_insn "*tstsi_cconly"
[(set (reg 33)
- (compare (match_operand:SI 0 "s_operand" "Qo")
+ (compare (match_operand:SI 0 "nonimmediate_operand" "d,Q")
(match_operand:SI 1 "const0_operand" "")))
- (clobber (match_scratch:SI 2 "=d"))]
+ (clobber (match_scratch:SI 2 "=X,d"))]
"s390_match_ccmode(insn, CCSmode)"
- "icm\\t%2,15,%0"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "mem")])
+ "@
+ ltr\\t%0,%0
+ icm\\t%2,15,%0"
+ [(set_attr "op_type" "RR,RS")
+ (set_attr "atype" "reg,mem")])
-(define_insn "*cmpsi_ccs_0"
+(define_insn "*tstsi_cconly2"
[(set (reg 33)
(compare (match_operand:SI 0 "register_operand" "d")
(match_operand:SI 1 "const0_operand" "")))]
@@ -481,72 +528,34 @@
"ltr\\t%0,%0"
[(set_attr "op_type" "RR")])
-(define_insn "*cmpsidi_ccs"
- [(set (reg 33)
- (compare (match_operand:SI 0 "register_operand" "d")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))))]
- "s390_match_ccmode(insn, CCSmode)"
- "ch\\t%0,%1"
- [(set_attr "op_type" "RR")
- (set_attr "atype" "mem")])
-
-(define_insn "*cmpsi_ccs"
- [(set (reg 33)
- (compare (match_operand:SI 0 "register_operand" "d,d,d")
- (match_operand:SI 1 "general_operand" "d,K,m")))]
- "s390_match_ccmode(insn, CCSmode)"
- "@
- cr\\t%0,%1
- chi\\t%0,%c1
- c\\t%0,%1"
- [(set_attr "op_type" "RR,RI,RX")
- (set_attr "atype" "reg,reg,mem")])
-
-(define_insn "*cmpsi_ccu"
+(define_insn "*tsthiCCT"
[(set (reg 33)
- (compare (match_operand:SI 0 "register_operand" "d,d")
- (match_operand:SI 1 "general_operand" "d,m")))]
- "s390_match_ccmode(insn, CCUmode)"
+ (compare (match_operand:HI 0 "nonimmediate_operand" "?Q,d")
+ (match_operand:HI 1 "const0_operand" "")))
+ (set (match_operand:HI 2 "register_operand" "=d,0")
+ (match_dup 0))]
+ "s390_match_ccmode(insn, CCTmode)"
"@
- clr\\t%0,%1
- cl\\t%0,%1"
- [(set_attr "op_type" "RR,RX")
- (set_attr "atype" "reg,mem")])
+ icm\\t%2,3,%0
+ tml\\t%0,65535"
+ [(set_attr "op_type" "RS,RI")
+ (set_attr "atype" "mem,reg")])
-(define_insn "*cmpsi_ccu_mem"
+(define_insn "*tsthiCCT_cconly"
[(set (reg 33)
- (compare (match_operand:SI 0 "s_operand" "oQ")
- (match_operand:SI 1 "s_imm_operand" "oQ")))]
- "s390_match_ccmode(insn, CCUmode)"
- "clc\\t%O0(4,%R0),%1"
- [(set_attr "op_type" "SS")
- (set_attr "atype" "mem")])
-
-
-; HI instructions
-
-(define_insn "*cmphi_tm_sub"
- [(set (reg 33)
- (compare (and:SI (subreg:SI (match_operand:HI 0 "s_operand" "%Qo") 0)
- (match_operand:SI 1 "immediate_operand" "n"))
- (const_int 0)))]
- "s390_match_ccmode(insn, CCTmode)
- && s390_single_qi (operands[1], HImode, 0) >= 0"
- "*
-{
- int part = s390_single_qi (operands[1], HImode, 0);
- operands[1] = GEN_INT (s390_extract_qi (operands[1], HImode, part));
-
- operands[0] = gen_rtx_MEM (QImode,
- plus_constant (XEXP (operands[0], 0), part));
- return \"tm\\t%0,%b1\";
-}"
- [(set_attr "op_type" "SI")
- (set_attr "atype" "mem")])
+ (compare (match_operand:HI 0 "nonimmediate_operand" "Q,d")
+ (match_operand:HI 1 "const0_operand" "")))
+ (clobber (match_scratch:HI 2 "=d,X"))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "@
+ icm\\t%2,3,%0
+ tml\\t%0,65535"
+ [(set_attr "op_type" "RS,RI")
+ (set_attr "atype" "mem,reg")])
-(define_insn "*icm3"
+(define_insn "*tsthi"
[(set (reg 33)
- (compare (match_operand:HI 0 "s_operand" "Qo")
+ (compare (match_operand:HI 0 "s_operand" "Q")
(match_operand:HI 1 "const0_operand" "")))
(set (match_operand:HI 2 "register_operand" "=d")
(match_dup 0))]
@@ -555,17 +564,9 @@
[(set_attr "op_type" "RS")
(set_attr "atype" "mem")])
-(define_insn "*cmphi_cct_0"
+(define_insn "*tsthi_cconly"
[(set (reg 33)
- (compare (match_operand:HI 0 "register_operand" "d")
- (match_operand:HI 1 "const0_operand" "")))]
- "s390_match_ccmode(insn, CCTmode)"
- "tml\\t%0,65535"
- [(set_attr "op_type" "RX")])
-
-(define_insn "*cmphi_ccs_0"
- [(set (reg 33)
- (compare (match_operand:HI 0 "s_operand" "Qo")
+ (compare (match_operand:HI 0 "s_operand" "Q")
(match_operand:HI 1 "const0_operand" "")))
(clobber (match_scratch:HI 2 "=d"))]
"s390_match_ccmode(insn, CCSmode)"
@@ -573,141 +574,192 @@
[(set_attr "op_type" "RS")
(set_attr "atype" "mem")])
-(define_insn "*cmphi_ccu"
+(define_insn "*tstqiCCT"
[(set (reg 33)
- (compare (match_operand:HI 0 "register_operand" "d")
- (match_operand:HI 1 "s_imm_operand" "Qo")))]
- "s390_match_ccmode(insn, CCUmode)"
- "clm\\t%0,3,%1"
+ (compare (match_operand:QI 0 "nonimmediate_operand" "?Q,d")
+ (match_operand:QI 1 "const0_operand" "")))
+ (set (match_operand:QI 2 "register_operand" "=d,0")
+ (match_dup 0))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "@
+ icm\\t%2,1,%0
+ tml\\t%0,255"
+ [(set_attr "op_type" "RS,RI")
+ (set_attr "atype" "mem,reg")])
+
+(define_insn "*tstqiCCT_cconly"
+ [(set (reg 33)
+ (compare (match_operand:QI 0 "nonimmediate_operand" "?Q,d")
+ (match_operand:QI 1 "const0_operand" "")))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "@
+ cli\\t%0,0
+ tml\\t%0,255"
+ [(set_attr "op_type" "SI,RI")
+ (set_attr "atype" "mem,reg")])
+
+(define_insn "*tstqi"
+ [(set (reg 33)
+ (compare (match_operand:QI 0 "s_operand" "Q")
+ (match_operand:QI 1 "const0_operand" "")))
+ (set (match_operand:QI 2 "register_operand" "=d")
+ (match_dup 0))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "icm\\t%2,1,%0"
[(set_attr "op_type" "RS")
(set_attr "atype" "mem")])
-(define_insn "*cmphi_ccu_mem"
+(define_insn "*tstqi_cconly"
[(set (reg 33)
- (compare (match_operand:HI 0 "s_operand" "oQ")
- (match_operand:HI 1 "s_imm_operand" "oQ")))]
- "s390_match_ccmode(insn, CCUmode)"
- "clc\\t%O0(2,%R0),%1"
- [(set_attr "op_type" "SS")
+ (compare (match_operand:QI 0 "s_operand" "Q")
+ (match_operand:QI 1 "const0_operand" "")))
+ (clobber (match_scratch:QI 2 "=d"))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "icm\\t%2,1,%0"
+ [(set_attr "op_type" "RS")
(set_attr "atype" "mem")])
-; QI instructions
+; Compare (signed) instructions
-(define_insn "*cmpqi_tm2"
+(define_insn "*cmpdi_ccs_sign"
[(set (reg 33)
- (compare (zero_extract:SI (match_operand:QI 0 "s_operand" "Qo")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))]
- "s390_match_ccmode(insn, CCTmode)
- && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
- && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8"
- "*
-{
- int block = (1 << INTVAL (operands[1])) - 1;
- int shift = 8 - INTVAL (operands[1]) - INTVAL (operands[2]);
-
- operands[2] = GEN_INT (block << shift);
- return \"tm\\t%0,%b2\";
-}"
- [(set_attr "op_type" "SI")
- (set_attr "atype" "mem")])
-
-(define_insn "*cmpqi_tm"
- [(set (reg 33)
- (compare (and:QI (match_operand:QI 0 "nonimmediate_operand" "%d,Q")
- (match_operand:QI 1 "immediate_operand" "n,n"))
- (const_int 0)))]
- "s390_match_ccmode(insn, CCTmode)"
+ (compare (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m"))
+ (match_operand:DI 0 "register_operand" "d,d")))]
+ "s390_match_ccmode(insn, CCSRmode) && TARGET_64BIT"
"@
- tml\\t%0,%b1
- tm\\t%0,%b1"
- [(set_attr "op_type" "RI,SI")
+ cgfr\\t%0,%1
+ cgf\\t%0,%1"
+ [(set_attr "op_type" "RRE,RXE")
(set_attr "atype" "reg,mem")])
-(define_insn "*cmpqi_tm_sub"
+(define_insn "*cmpdi_ccs"
[(set (reg 33)
- (compare (and:SI (subreg:SI (match_operand:QI 0 "s_operand" "%Qo") 0)
- (match_operand:SI 1 "immediate_operand" "n"))
- (const_int 0)))]
- "s390_match_ccmode(insn, CCTmode)"
- "tm\\t%0,%b1"
- [(set_attr "op_type" "SI")
+ (compare (match_operand:DI 0 "register_operand" "d,d,d")
+ (match_operand:DI 1 "general_operand" "d,K,m")))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
+ "@
+ cgr\\t%0,%1
+ cghi\\t%0,%c1
+ cg\\t%0,%1"
+ [(set_attr "op_type" "RRE,RI,RXE")
+ (set_attr "atype" "reg,reg,mem")])
+
+(define_insn "*cmpsi_ccs_sign"
+ [(set (reg 33)
+ (compare (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))
+ (match_operand:SI 0 "register_operand" "d")))]
+ "s390_match_ccmode(insn, CCSRmode)"
+ "ch\\t%0,%1"
+ [(set_attr "op_type" "RX")
(set_attr "atype" "mem")])
-(define_insn "*icm1"
+(define_insn "*cmpsi_ccs"
[(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "Qo")
- (match_operand:QI 1 "const0_operand" "")))
- (set (match_operand:QI 2 "register_operand" "=d")
- (match_dup 0))]
+ (compare (match_operand:SI 0 "register_operand" "d,d,d")
+ (match_operand:SI 1 "general_operand" "d,K,m")))]
"s390_match_ccmode(insn, CCSmode)"
- "icm\\t%2,1,%0"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "mem")])
+ "@
+ cr\\t%0,%1
+ chi\\t%0,%c1
+ c\\t%0,%1"
+ [(set_attr "op_type" "RR,RI,RX")
+ (set_attr "atype" "reg,reg,mem")])
+
-(define_insn "*tm_0"
+; Compare (unsigned) instructions
+
+(define_insn "*cmpdi_ccu_zero"
[(set (reg 33)
- (compare (zero_extend:SI (and:QI (match_operand:QI 0 "s_operand" "Qo")
- (match_operand:QI 1 "immediate_operand" "")))
- (const_int 0)))]
- "s390_match_ccmode(insn, CCTmode) &&
- INTVAL(operands[1]) >= 0 && INTVAL(operands[1]) < 256"
- "tm\\t%0,%1"
- [(set_attr "op_type" "RI")
- (set_attr "atype" "mem")])
+ (compare (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m"))
+ (match_operand:DI 0 "register_operand" "d,d")))]
+ "s390_match_ccmode(insn, CCURmode) && TARGET_64BIT"
+ "@
+ clgfr\\t%0,%1
+ clgf\\t%0,%1"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
-(define_insn "*cmpqi_cct_0"
+(define_insn "*cmpdi_ccu"
[(set (reg 33)
- (compare (match_operand:QI 0 "register_operand" "d")
- (match_operand:QI 1 "const0_operand" "")))]
- "s390_match_ccmode(insn, CCTmode)"
- "tml\\t%0,255"
- [(set_attr "op_type" "RI")])
+ (compare (match_operand:DI 0 "register_operand" "d,d")
+ (match_operand:DI 1 "general_operand" "d,m")))]
+ "s390_match_ccmode(insn, CCUmode) && TARGET_64BIT"
+ "@
+ clgr\\t%0,%1
+ clg\\t%0,%1"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
-(define_insn "*cmpqi_ccs_0"
+(define_insn "*cmpsi_ccu"
[(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "Qo")
- (match_operand:QI 1 "const0_operand" "")))
- (clobber (match_scratch:QI 2 "=d"))]
- "s390_match_ccmode(insn, CCSmode)"
- "icm\\t%2,1,%0"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "mem")])
+ (compare (match_operand:SI 0 "register_operand" "d,d")
+ (match_operand:SI 1 "general_operand" "d,m")))]
+ "s390_match_ccmode(insn, CCUmode)"
+ "@
+ clr\\t%0,%1
+ cl\\t%0,%1"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
-(define_insn "*cmpqi_ccu_0"
+(define_insn "*cmphi_ccu"
[(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "Qo")
- (match_operand:QI 1 "const0_operand" "")))]
+ (compare (match_operand:HI 0 "register_operand" "d")
+ (match_operand:HI 1 "s_imm_operand" "Q")))]
"s390_match_ccmode(insn, CCUmode)"
- "cli\\t%0,0"
- [(set_attr "op_type" "SI")
+ "clm\\t%0,3,%1"
+ [(set_attr "op_type" "RS")
(set_attr "atype" "mem")])
(define_insn "*cmpqi_ccu"
[(set (reg 33)
(compare (match_operand:QI 0 "register_operand" "d")
- (match_operand:QI 1 "s_imm_operand" "Qo")))]
+ (match_operand:QI 1 "s_imm_operand" "Q")))]
"s390_match_ccmode(insn, CCUmode)"
"clm\\t%0,1,%1"
[(set_attr "op_type" "RS")
(set_attr "atype" "mem")])
-(define_insn "*cmpqi_ccu_immed"
+(define_insn "*cli"
[(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "Qo")
- (match_operand:QI 1 "const_int_operand" "n")))]
- "s390_match_ccmode(insn, CCUmode) &&
- INTVAL(operands[1]) >= 0 && INTVAL(operands[1]) < 256"
- "cli\\t%0,%1"
+ (compare (match_operand:QI 0 "memory_operand" "Q")
+ (match_operand:QI 1 "immediate_operand" "n")))]
+ "s390_match_ccmode (insn, CCUmode)"
+ "cli\\t%0,%b1"
[(set_attr "op_type" "SI")
(set_attr "atype" "mem")])
+(define_insn "*cmpdi_ccu_mem"
+ [(set (reg 33)
+ (compare (match_operand:DI 0 "s_operand" "Q")
+ (match_operand:DI 1 "s_imm_operand" "Q")))]
+ "s390_match_ccmode(insn, CCUmode)"
+ "clc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
+(define_insn "*cmpsi_ccu_mem"
+ [(set (reg 33)
+ (compare (match_operand:SI 0 "s_operand" "Q")
+ (match_operand:SI 1 "s_imm_operand" "Q")))]
+ "s390_match_ccmode(insn, CCUmode)"
+ "clc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
+(define_insn "*cmphi_ccu_mem"
+ [(set (reg 33)
+ (compare (match_operand:HI 0 "s_operand" "Q")
+ (match_operand:HI 1 "s_imm_operand" "Q")))]
+ "s390_match_ccmode(insn, CCUmode)"
+ "clc\\t%O0(2,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
(define_insn "*cmpqi_ccu_mem"
[(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "oQ")
- (match_operand:QI 1 "s_imm_operand" "oQ")))]
+ (compare (match_operand:QI 0 "s_operand" "Q")
+ (match_operand:QI 1 "s_imm_operand" "Q")))]
"s390_match_ccmode(insn, CCUmode)"
"clc\\t%O0(1,%R0),%1"
[(set_attr "op_type" "SS")
@@ -804,94 +856,91 @@
; movti instruction pattern(s).
;
-(define_insn "*movti_ss"
- [(set (match_operand:TI 0 "s_operand" "=Qo")
- (match_operand:TI 1 "s_imm_operand" "Qo"))]
- ""
- "mvc\\t%O0(16,%R0),%1"
- [(set_attr "op_type" "SS")
- (set_attr "atype" "mem")])
-
(define_insn "movti"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=d,Q,d,m")
- (match_operand:TI 1 "general_operand" "Q,d,dKm,d"))]
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=d,Q,d,o,Q")
+ (match_operand:TI 1 "general_operand" "Q,d,dKm,d,Q"))]
"TARGET_64BIT"
"@
lmg\\t%0,%N0,%1
stmg\\t%1,%N1,%0
#
- #"
- [(set_attr "op_type" "RSE,RSE,NN,NN")
+ #
+ mvc\\t%O0(16,%R0),%1"
+ [(set_attr "op_type" "RSE,RSE,NN,NN,SS")
(set_attr "atype" "mem")])
(define_split
[(set (match_operand:TI 0 "nonimmediate_operand" "")
(match_operand:TI 1 "general_operand" ""))]
"TARGET_64BIT && reload_completed
- && !s_operand (operands[0], VOIDmode)
- && !s_operand (operands[1], VOIDmode)
- && (register_operand (operands[0], VOIDmode)
- || register_operand (operands[1], VOIDmode))
- && (!register_operand (operands[0], VOIDmode)
- || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, TImode),
- operands[1])
- || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, TImode),
- operands[1]))"
+ && s390_split_ok_p (operands[0], operands[1], TImode, 0)"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
- "
{
- if (!register_operand (operands[0], VOIDmode)
- || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, TImode),
- operands[1]))
- {
- operands[2] = operand_subword (operands[0], 0, 0, TImode);
- operands[3] = operand_subword (operands[0], 1, 0, TImode);
- operands[4] = operand_subword (operands[1], 0, 0, TImode);
- operands[5] = operand_subword (operands[1], 1, 0, TImode);
- }
- else
- {
- operands[2] = operand_subword (operands[0], 1, 0, TImode);
- operands[3] = operand_subword (operands[0], 0, 0, TImode);
- operands[4] = operand_subword (operands[1], 1, 0, TImode);
- operands[5] = operand_subword (operands[1], 0, 0, TImode);
- }
-}")
+ operands[2] = operand_subword (operands[0], 0, 0, TImode);
+ operands[3] = operand_subword (operands[0], 1, 0, TImode);
+ operands[4] = operand_subword (operands[1], 0, 0, TImode);
+ operands[5] = operand_subword (operands[1], 1, 0, TImode);
+})
+
+(define_split
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (match_operand:TI 1 "general_operand" ""))]
+ "TARGET_64BIT && reload_completed
+ && s390_split_ok_p (operands[0], operands[1], TImode, 1)"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+{
+ operands[2] = operand_subword (operands[0], 1, 0, TImode);
+ operands[3] = operand_subword (operands[0], 0, 0, TImode);
+ operands[4] = operand_subword (operands[1], 1, 0, TImode);
+ operands[5] = operand_subword (operands[1], 0, 0, TImode);
+})
(define_split
[(set (match_operand:TI 0 "register_operand" "")
(match_operand:TI 1 "memory_operand" ""))]
"TARGET_64BIT && reload_completed
&& !s_operand (operands[1], VOIDmode)"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 0) (mem:TI (match_dup 2)))]
- "operands[2] = operand_subword (operands[0], 1, 0, TImode);
- operands[3] = legitimize_la_operand (XEXP (operands[1], 0));")
+ [(set (match_dup 0) (match_dup 1))]
+{
+ rtx addr = operand_subword (operands[0], 1, 0, TImode);
+ s390_load_address (addr, XEXP (operands[1], 0));
+ operands[1] = replace_equiv_address (operands[1], addr);
+})
+
+(define_expand "reload_outti"
+ [(parallel [(match_operand:TI 0 "memory_operand" "")
+ (match_operand:TI 1 "register_operand" "d")
+ (match_operand:DI 2 "register_operand" "=&a")])]
+ "TARGET_64BIT"
+{
+ s390_load_address (operands[2], XEXP (operands[0], 0));
+ operands[0] = replace_equiv_address (operands[0], operands[2]);
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+})
;
; movdi instruction pattern(s).
;
-;; If generating PIC code and operands[1] is a symbolic CONST, emit a
-;; move to get the address of the symbolic object from the GOT.
-
(define_expand "movdi"
[(set (match_operand:DI 0 "general_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
"
{
- /* Handle PIC symbolic constants. */
- if (TARGET_64BIT && flag_pic && SYMBOLIC_CONST (operands[1]))
- emit_pic_move (operands, DImode);
+ /* Handle symbolic constants. */
+ if (TARGET_64BIT && SYMBOLIC_CONST (operands[1]))
+ emit_symbolic_move (operands);
/* During and after reload, we need to force constants
to the literal pool ourselves, if necessary. */
if ((reload_in_progress || reload_completed)
&& CONSTANT_P (operands[1])
&& (!legitimate_reload_constant_p (operands[1])
- || fp_operand (operands[0], VOIDmode)))
+ || FP_REG_P (operands[0])))
operands[1] = force_const_mem (DImode, operands[1]);
}")
@@ -901,7 +950,7 @@
"TARGET_64BIT
&& GET_CODE (operands[1]) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K')
- && !fp_operand (operands[0], VOIDmode)"
+ && !FP_REG_P (operands[0])"
"lghi\\t%0,%h1"
[(set_attr "op_type" "RI")
(set_attr "atype" "reg")])
@@ -910,7 +959,7 @@
[(set (match_operand:DI 0 "register_operand" "=d")
(match_operand:DI 1 "immediate_operand" "n"))]
"TARGET_64BIT && s390_single_hi (operands[1], DImode, 0) >= 0
- && !fp_operand (operands[0], VOIDmode)"
+ && !FP_REG_P (operands[0])"
"*
{
int part = s390_single_hi (operands[1], DImode, 0);
@@ -932,23 +981,15 @@
[(set (match_operand:DI 0 "register_operand" "=d")
(match_operand:DI 1 "larl_operand" "X"))]
"TARGET_64BIT
- && !fp_operand (operands[0], VOIDmode)"
+ && !FP_REG_P (operands[0])"
"larl\\t%0,%1"
[(set_attr "op_type" "RIL")
(set_attr "atype" "reg")
(set_attr "type" "la")])
-(define_insn "*movdi_ss"
- [(set (match_operand:DI 0 "s_operand" "=Qo")
- (match_operand:DI 1 "s_imm_operand" "Qo"))]
- ""
- "mvc\\t%O0(8,%R0),%1"
- [(set_attr "op_type" "SS")
- (set_attr "atype" "mem")])
-
(define_insn "*movdi_64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,m,!*f,!*f,!m")
- (match_operand:DI 1 "general_operand" "d,m,d,*f,m,*f"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,m,!*f,!*f,!m,?Q")
+ (match_operand:DI 1 "general_operand" "d,m,d,*f,m,*f,?Q"))]
"TARGET_64BIT"
"@
lgr\\t%0,%1
@@ -956,13 +997,14 @@
stg\\t%1,%0
ldr\\t%0,%1
ld\\t%0,%1
- std\\t%1,%0"
- [(set_attr "op_type" "RRE,RXE,RXE,RR,RX,RX")
- (set_attr "atype" "reg,mem,mem,reg,mem,mem")])
+ std\\t%1,%0
+ mvc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "RRE,RXE,RXE,RR,RX,RX,SS")
+ (set_attr "atype" "reg,mem,mem,reg,mem,mem,mem")])
(define_insn "*movdi_31"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=d,Q,d,m,!*f,!*f,!m")
- (match_operand:DI 1 "general_operand" "Q,d,dKm,d,*f,m,*f"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,Q,d,o,!*f,!*f,!m,Q")
+ (match_operand:DI 1 "general_operand" "Q,d,dKm,d,*f,m,*f,Q"))]
"!TARGET_64BIT"
"@
lm\\t%0,%N0,%1
@@ -971,75 +1013,89 @@
#
ldr\\t%0,%1
ld\\t%0,%1
- std\\t%1,%0"
- [(set_attr "op_type" "RS,RS,NN,NN,RR,RX,RX")
- (set_attr "atype" "mem,mem,*,*,reg,mem,mem")])
+ std\\t%1,%0
+ mvc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "RS,RS,NN,NN,RR,RX,RX,SS")
+ (set_attr "atype" "mem,mem,*,*,reg,mem,mem,mem")])
(define_split
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))]
"!TARGET_64BIT && reload_completed
- && !fp_operand (operands[0], VOIDmode)
- && !fp_operand (operands[1], VOIDmode)
- && !s_operand (operands[0], VOIDmode)
- && !s_operand (operands[1], VOIDmode)
- && (register_operand (operands[0], VOIDmode)
- || register_operand (operands[1], VOIDmode))
- && (!register_operand (operands[0], VOIDmode)
- || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DImode),
- operands[1])
- || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, DImode),
- operands[1]))"
+ && s390_split_ok_p (operands[0], operands[1], DImode, 0)"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
- "
{
- if (!register_operand (operands[0], VOIDmode)
- || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DImode),
- operands[1]))
- {
- operands[2] = operand_subword (operands[0], 0, 0, DImode);
- operands[3] = operand_subword (operands[0], 1, 0, DImode);
- operands[4] = operand_subword (operands[1], 0, 0, DImode);
- operands[5] = operand_subword (operands[1], 1, 0, DImode);
- }
- else
- {
- operands[2] = operand_subword (operands[0], 1, 0, DImode);
- operands[3] = operand_subword (operands[0], 0, 0, DImode);
- operands[4] = operand_subword (operands[1], 1, 0, DImode);
- operands[5] = operand_subword (operands[1], 0, 0, DImode);
- }
-}")
+ operands[2] = operand_subword (operands[0], 0, 0, DImode);
+ operands[3] = operand_subword (operands[0], 1, 0, DImode);
+ operands[4] = operand_subword (operands[1], 0, 0, DImode);
+ operands[5] = operand_subword (operands[1], 1, 0, DImode);
+})
+
+(define_split
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
+ "!TARGET_64BIT && reload_completed
+ && s390_split_ok_p (operands[0], operands[1], DImode, 1)"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+{
+ operands[2] = operand_subword (operands[0], 1, 0, DImode);
+ operands[3] = operand_subword (operands[0], 0, 0, DImode);
+ operands[4] = operand_subword (operands[1], 1, 0, DImode);
+ operands[5] = operand_subword (operands[1], 0, 0, DImode);
+})
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(match_operand:DI 1 "memory_operand" ""))]
"!TARGET_64BIT && reload_completed
- && !fp_operand (operands[0], VOIDmode)
- && !fp_operand (operands[1], VOIDmode)
+ && !FP_REG_P (operands[0])
&& !s_operand (operands[1], VOIDmode)"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 0) (mem:DI (match_dup 2)))]
- "operands[2] = operand_subword (operands[0], 1, 0, DImode);
- operands[3] = legitimize_la_operand (XEXP (operands[1], 0));")
+ [(set (match_dup 0) (match_dup 1))]
+{
+ rtx addr = operand_subword (operands[0], 1, 0, DImode);
+ s390_load_address (addr, XEXP (operands[1], 0));
+ operands[1] = replace_equiv_address (operands[1], addr);
+})
+
+(define_expand "reload_outdi"
+ [(parallel [(match_operand:DI 0 "memory_operand" "")
+ (match_operand:DI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "=&a")])]
+ "!TARGET_64BIT"
+{
+ s390_load_address (operands[2], XEXP (operands[0], 0));
+ operands[0] = replace_equiv_address (operands[0], operands[2]);
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+})
+
+(define_peephole2
+ [(set (match_operand:DI 0 "register_operand" "")
+ (mem:DI (match_operand 1 "address_operand" "")))]
+ "TARGET_64BIT
+ && !FP_REG_P (operands[0])
+ && GET_CODE (operands[1]) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (operands[1])
+ && get_pool_mode (operands[1]) == DImode
+ && legitimate_reload_constant_p (get_pool_constant (operands[1]))"
+ [(set (match_dup 0) (match_dup 2))]
+ "operands[2] = get_pool_constant (operands[1]);")
;
; movsi instruction pattern(s).
;
-;; If generating PIC code and operands[1] is a symbolic CONST, emit a
-;; move to get the address of the symbolic object from the GOT.
-
(define_expand "movsi"
[(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
"
{
- /* Handle PIC symbolic constants. */
- if (!TARGET_64BIT && flag_pic && SYMBOLIC_CONST (operands[1]))
- emit_pic_move (operands, SImode);
+ /* Handle symbolic constants. */
+ if (!TARGET_64BIT && SYMBOLIC_CONST (operands[1]))
+ emit_symbolic_move (operands);
/* expr.c tries to load an effective address using
force_reg. This fails because we don't have a
@@ -1059,7 +1115,7 @@
if ((reload_in_progress || reload_completed)
&& CONSTANT_P (operands[1])
&& (!legitimate_reload_constant_p (operands[1])
- || fp_operand (operands[0], VOIDmode)))
+ || FP_REG_P (operands[0])))
operands[1] = force_const_mem (SImode, operands[1]);
}")
@@ -1068,7 +1124,7 @@
(match_operand:SI 1 "immediate_operand" "K"))]
"GET_CODE (operands[1]) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K')
- && !fp_operand (operands[0], VOIDmode)"
+ && !FP_REG_P (operands[0])"
"lhi\\t%0,%h1"
[(set_attr "op_type" "RI")])
@@ -1076,7 +1132,7 @@
[(set (match_operand:SI 0 "register_operand" "=d")
(match_operand:SI 1 "immediate_operand" "n"))]
"TARGET_64BIT && s390_single_hi (operands[1], SImode, 0) >= 0
- && !fp_operand (operands[0], VOIDmode)"
+ && !FP_REG_P (operands[0])"
"*
{
int part = s390_single_hi (operands[1], SImode, 0);
@@ -1091,17 +1147,9 @@
}"
[(set_attr "op_type" "RI")])
-(define_insn "*movsi_ss"
- [(set (match_operand:SI 0 "s_operand" "=Qo")
- (match_operand:SI 1 "s_imm_operand" "Qo"))]
- ""
- "mvc\\t%O0(4,%R0),%1"
- [(set_attr "op_type" "SS")
- (set_attr "atype" "mem")])
-
(define_insn "*movsi"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,m,!*f,!*f,!m")
- (match_operand:SI 1 "general_operand" "d,m,d,*f,m,*f"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,m,!*f,!*f,!m,?Q")
+ (match_operand:SI 1 "general_operand" "d,m,d,*f,m,*f,?Q"))]
""
"@
lr\\t%0,%1
@@ -1109,62 +1157,94 @@
st\\t%1,%0
ler\\t%0,%1
le\\t%0,%1
- ste\\t%1,%0"
- [(set_attr "op_type" "RR,RX,RX,RR,RX,RX")
- (set_attr "atype" "reg,mem,mem,reg,mem,mem")])
+ ste\\t%1,%0
+ mvc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "RR,RX,RX,RR,RX,RX,SS")
+ (set_attr "atype" "reg,mem,mem,reg,mem,mem,mem")])
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+ (mem:SI (match_operand 1 "address_operand" "")))]
+ "!FP_REG_P (operands[0])
+ && GET_CODE (operands[1]) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (operands[1])
+ && get_pool_mode (operands[1]) == SImode
+ && legitimate_reload_constant_p (get_pool_constant (operands[1]))"
+ [(set (match_dup 0) (match_dup 2))]
+ "operands[2] = get_pool_constant (operands[1]);")
;
; movhi instruction pattern(s).
;
(define_insn "movhi"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m")
- (match_operand:HI 1 "general_operand" "d,n,m,d"))]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,?Q")
+ (match_operand:HI 1 "general_operand" "d,n,m,d,?Q"))]
""
"@
lr\\t%0,%1
lhi\\t%0,%h1
lh\\t%0,%1
- sth\\t%1,%0"
- [(set_attr "op_type" "RR,RI,RX,RX")
- (set_attr "atype" "reg,reg,mem,mem")])
+ sth\\t%1,%0
+ mvc\\t%O0(2,%R0),%1"
+ [(set_attr "op_type" "RR,RI,RX,RX,SS")
+ (set_attr "atype" "reg,reg,mem,mem,mem")])
+(define_peephole2
+ [(set (match_operand:HI 0 "register_operand" "")
+ (mem:HI (match_operand 1 "address_operand" "")))]
+ "GET_CODE (operands[1]) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (operands[1])
+ && get_pool_mode (operands[1]) == HImode
+ && GET_CODE (get_pool_constant (operands[1])) == CONST_INT"
+ [(set (match_dup 0) (match_dup 2))]
+ "operands[2] = get_pool_constant (operands[1]);")
;
; movqi instruction pattern(s).
;
(define_insn "movqi_64"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,Q")
- (match_operand:QI 1 "general_operand" "d,n,m,d,n"))]
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,Q,?Q")
+ (match_operand:QI 1 "general_operand" "d,n,m,d,n,?Q"))]
"TARGET_64BIT"
"@
lr\\t%0,%1
lhi\\t%0,%b1
llgc\\t%0,%1
stc\\t%1,%0
- mvi\\t%0,%b1"
- [(set_attr "op_type" "RR,RI,RXE,RX,SI")
- (set_attr "atype" "reg,reg,mem,mem,mem")])
+ mvi\\t%0,%b1
+ mvc\\t%O0(1,%R0),%1"
+ [(set_attr "op_type" "RR,RI,RXE,RX,SI,SS")
+ (set_attr "atype" "reg,reg,mem,mem,mem,mem")])
(define_insn "movqi"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,Q")
- (match_operand:QI 1 "general_operand" "d,n,m,d,n"))]
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,Q,?Q")
+ (match_operand:QI 1 "general_operand" "d,n,m,d,n,?Q"))]
""
"@
lr\\t%0,%1
lhi\\t%0,%b1
ic\\t%0,%1
stc\\t%1,%0
- mvi\\t%0,%b1"
- [(set_attr "op_type" "RR,RI,RX,RX,SI")
- (set_attr "atype" "reg,reg,mem,mem,mem")])
+ mvi\\t%0,%b1
+ mvc\\t%O0(1,%R0),%1"
+ [(set_attr "op_type" "RR,RI,RX,RX,SI,SS")
+ (set_attr "atype" "reg,reg,mem,mem,mem,mem")])
+(define_peephole2
+ [(set (match_operand:QI 0 "nonimmediate_operand" "")
+ (mem:QI (match_operand 1 "address_operand" "")))]
+ "GET_CODE (operands[1]) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (operands[1])
+ && get_pool_mode (operands[1]) == QImode
+ && GET_CODE (get_pool_constant (operands[1])) == CONST_INT"
+ [(set (match_dup 0) (match_dup 2))]
+ "operands[2] = get_pool_constant (operands[1]);")
;
-; moveqstrictqi instruction pattern(s).
+; movstrictqi instruction pattern(s).
;
(define_insn "*movstrictqi"
@@ -1181,7 +1261,7 @@
(define_insn "*movstricthi"
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
- (match_operand:HI 1 "s_imm_operand" "Qo"))
+ (match_operand:HI 1 "s_imm_operand" "Q"))
(clobber (reg:CC 33))]
""
"icm\\t%0,3,%1"
@@ -1193,7 +1273,7 @@
; movstrictsi instruction pattern(s).
;
-(define_insn "movestrictsi"
+(define_insn "movstrictsi"
[(set (strict_low_part (match_operand:SI 0 "register_operand" "+d,d"))
(match_operand:SI 1 "general_operand" "d,m"))]
"TARGET_64BIT"
@@ -1221,17 +1301,9 @@
operands[1] = force_const_mem (DFmode, operands[1]);
}")
-(define_insn "*movdf_ss"
- [(set (match_operand:DF 0 "s_operand" "=Qo")
- (match_operand:DF 1 "s_imm_operand" "Qo"))]
- ""
- "mvc\\t%O0(8,%R0),%1"
- [(set_attr "op_type" "SS")
- (set_attr "atype" "mem")])
-
(define_insn "*movdf_64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,d,m")
- (match_operand:DF 1 "general_operand" "f,m,f,d,m,d"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,d,m,?Q")
+ (match_operand:DF 1 "general_operand" "f,m,f,d,m,d,?Q"))]
"TARGET_64BIT"
"@
ldr\\t%0,%1
@@ -1239,13 +1311,14 @@
std\\t%1,%0
lgr\\t%0,%1
lg\\t%0,%1
- stg\\t%1,%0"
- [(set_attr "op_type" "RR,RX,RX,RRE,RXE,RXE")
- (set_attr "atype" "reg,mem,mem,reg,mem,mem")])
+ stg\\t%1,%0
+ mvc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "RR,RX,RX,RRE,RXE,RXE,SS")
+ (set_attr "atype" "reg,mem,mem,reg,mem,mem,mem")])
(define_insn "*movdf_31"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,Q,d,m")
- (match_operand:DF 1 "general_operand" "f,m,f,Q,d,dKm,d"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,Q,d,o,Q")
+ (match_operand:DF 1 "general_operand" "f,m,f,Q,d,dKm,d,Q"))]
"!TARGET_64BIT"
"@
ldr\\t%0,%1
@@ -1254,58 +1327,63 @@
lm\\t%0,%N0,%1
stm\\t%1,%N1,%0
#
- #"
- [(set_attr "op_type" "RR,RX,RX,RS,RS,NN,NN")
- (set_attr "atype" "reg,mem,mem,mem,mem,*,*")])
+ #
+ mvc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "RR,RX,RX,RS,RS,NN,NN,SS")
+ (set_attr "atype" "reg,mem,mem,mem,mem,*,*,mem")])
(define_split
[(set (match_operand:DF 0 "nonimmediate_operand" "")
(match_operand:DF 1 "general_operand" ""))]
"!TARGET_64BIT && reload_completed
- && !fp_operand (operands[0], VOIDmode)
- && !fp_operand (operands[1], VOIDmode)
- && !s_operand (operands[0], VOIDmode)
- && !s_operand (operands[1], VOIDmode)
- && (register_operand (operands[0], VOIDmode)
- || register_operand (operands[1], VOIDmode))
- && (!register_operand (operands[0], VOIDmode)
- || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DFmode),
- operands[1])
- || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, DFmode),
- operands[1]))"
+ && s390_split_ok_p (operands[0], operands[1], DFmode, 0)"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
- "
{
- if (!register_operand (operands[0], VOIDmode)
- || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DFmode),
- operands[1]))
- {
- operands[2] = operand_subword (operands[0], 0, 0, DFmode);
- operands[3] = operand_subword (operands[0], 1, 0, DFmode);
- operands[4] = operand_subword (operands[1], 0, 0, DFmode);
- operands[5] = operand_subword (operands[1], 1, 0, DFmode);
- }
- else
- {
- operands[2] = operand_subword (operands[0], 1, 0, DFmode);
- operands[3] = operand_subword (operands[0], 0, 0, DFmode);
- operands[4] = operand_subword (operands[1], 1, 0, DFmode);
- operands[5] = operand_subword (operands[1], 0, 0, DFmode);
- }
-}")
+ operands[2] = operand_subword (operands[0], 0, 0, DFmode);
+ operands[3] = operand_subword (operands[0], 1, 0, DFmode);
+ operands[4] = operand_subword (operands[1], 0, 0, DFmode);
+ operands[5] = operand_subword (operands[1], 1, 0, DFmode);
+})
+
+(define_split
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ "!TARGET_64BIT && reload_completed
+ && s390_split_ok_p (operands[0], operands[1], DFmode, 1)"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+{
+ operands[2] = operand_subword (operands[0], 1, 0, DFmode);
+ operands[3] = operand_subword (operands[0], 0, 0, DFmode);
+ operands[4] = operand_subword (operands[1], 1, 0, DFmode);
+ operands[5] = operand_subword (operands[1], 0, 0, DFmode);
+})
(define_split
[(set (match_operand:DF 0 "register_operand" "")
(match_operand:DF 1 "memory_operand" ""))]
"!TARGET_64BIT && reload_completed
- && !fp_operand (operands[0], VOIDmode)
- && !fp_operand (operands[1], VOIDmode)
+ && !FP_REG_P (operands[0])
&& !s_operand (operands[1], VOIDmode)"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 0) (mem:DI (match_dup 2)))]
- "operands[2] = operand_subword (operands[0], 1, 0, DFmode);
- operands[3] = legitimize_la_operand (XEXP (operands[1], 0));")
+ [(set (match_dup 0) (match_dup 1))]
+{
+ rtx addr = operand_subword (operands[0], 1, 0, DFmode);
+ s390_load_address (addr, XEXP (operands[1], 0));
+ operands[1] = replace_equiv_address (operands[1], addr);
+})
+
+(define_expand "reload_outdf"
+ [(parallel [(match_operand:DF 0 "memory_operand" "")
+ (match_operand:DF 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "=&a")])]
+ "!TARGET_64BIT"
+{
+ s390_load_address (operands[2], XEXP (operands[0], 0));
+ operands[0] = replace_equiv_address (operands[0], operands[2]);
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+})
;
; movsf instruction pattern(s).
@@ -1324,17 +1402,9 @@
operands[1] = force_const_mem (SFmode, operands[1]);
}")
-(define_insn "*movsf_ss"
- [(set (match_operand:SF 0 "s_operand" "=Qo")
- (match_operand:SF 1 "s_imm_operand" "Qo"))]
- ""
- "mvc\\t%O0(4,%R0),%1"
- [(set_attr "op_type" "SS")
- (set_attr "atype" "mem")])
-
(define_insn "*movsf"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,m,d,d,m")
- (match_operand:SF 1 "general_operand" "f,m,f,d,m,d"))]
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,m,d,d,m,?Q")
+ (match_operand:SF 1 "general_operand" "f,m,f,d,m,d,?Q"))]
""
"@
ler\\t%0,%1
@@ -1342,9 +1412,10 @@
ste\\t%1,%0
lr\\t%0,%1
l\\t%0,%1
- st\\t%1,%0"
- [(set_attr "op_type" "RR,RX,RX,RR,RX,RX")
- (set_attr "atype" "reg,mem,mem,reg,mem,mem")])
+ st\\t%1,%0
+ mvc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "RR,RX,RX,RR,RX,RX,SS")
+ (set_attr "atype" "reg,mem,mem,reg,mem,mem,mem")])
;
; load_multiple pattern(s).
@@ -1413,7 +1484,7 @@
(define_insn "*load_multiple_di"
[(match_parallel 0 "load_multiple_operation"
[(set (match_operand:DI 1 "register_operand" "=r")
- (match_operand:DI 2 "s_operand" "oQ"))])]
+ (match_operand:DI 2 "s_operand" "Q"))])]
""
"*
{
@@ -1432,7 +1503,7 @@
(define_insn "*load_multiple_si"
[(match_parallel 0 "load_multiple_operation"
[(set (match_operand:SI 1 "register_operand" "=r")
- (match_operand:SI 2 "s_operand" "oQ"))])]
+ (match_operand:SI 2 "s_operand" "Q"))])]
""
"*
{
@@ -1516,7 +1587,7 @@
(define_insn "*store_multiple_di"
[(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:DI 1 "s_operand" "=oQ")
+ [(set (match_operand:DI 1 "s_operand" "=Q")
(match_operand:DI 2 "register_operand" "r"))])]
""
"*
@@ -1536,7 +1607,7 @@
(define_insn "*store_multiple_si"
[(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:SI 1 "s_operand" "=oQ")
+ [(set (match_operand:SI 1 "s_operand" "=Q")
(match_operand:SI 2 "register_operand" "r"))])]
""
"*
@@ -1558,172 +1629,31 @@
;;
;
-; movstrdi instruction pattern(s).
+; movstrM instruction pattern(s).
;
(define_expand "movstrdi"
- [(set (match_operand:BLK 0 "general_operand" "")
- (match_operand:BLK 1 "general_operand" ""))
- (use (match_operand:DI 2 "general_operand" ""))
- (match_operand 3 "" "")]
- "TARGET_64BIT"
- "
-{
- rtx addr0, addr1;
-
- addr0 = force_operand (XEXP (operands[0], 0), NULL_RTX);
- addr1 = force_operand (XEXP (operands[1], 0), NULL_RTX);
-
- if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) <= 256)
- {
- operands[0] = change_address (operands[0], VOIDmode, addr0);
- operands[1] = change_address (operands[1], VOIDmode, addr1);
- operands[2] = GEN_INT (INTVAL (operands[2]) - 1);
-
- emit_insn (gen_movstrdi_short (operands[0], operands[1], operands[2]));
- DONE;
- }
- else
- {
- if (TARGET_MVCLE)
- {
- /* implementation suggested by Richard Henderson <rth@cygnus.com> */
- rtx reg0 = gen_reg_rtx (TImode);
- rtx reg1 = gen_reg_rtx (TImode);
- rtx len = operands[2];
-
- if (! CONSTANT_P (len))
- len = force_reg (DImode, len);
-
- /* Load up the address+length pairs. */
-
- emit_move_insn (gen_highpart (DImode, reg0), addr0);
- emit_move_insn (gen_lowpart (DImode, reg0), len);
-
- emit_move_insn (gen_highpart (DImode, reg1), addr1);
- emit_move_insn (gen_lowpart (DImode, reg1), len);
-
- /* MOVE */
- emit_insn (gen_movstrdi_64 (reg0, reg1, reg0, reg1));
- DONE;
- }
- else
- {
- rtx label1 = gen_label_rtx ();
- rtx label2 = gen_label_rtx ();
- rtx reg0, reg1, len, blocks;
-
- reg0 = gen_reg_rtx (DImode);
- reg1 = gen_reg_rtx (DImode);
- len = gen_reg_rtx (DImode);
- blocks = gen_reg_rtx (DImode);
-
- emit_move_insn (len, operands[2]);
- emit_insn (gen_cmpdi (len, const0_rtx));
- emit_jump_insn (gen_beq (label1));
- emit_move_insn (reg0, addr0);
- emit_move_insn (reg1, addr1);
- emit_insn (gen_adddi3 (len, len, constm1_rtx));
- emit_insn (gen_ashrdi3 (blocks, len, GEN_INT (8)));
- emit_insn (gen_cmpdi (blocks, const0_rtx));
- emit_jump_insn (gen_beq (label2));
- emit_insn (gen_movstrdi_long (reg0, reg1, reg0, reg1, blocks, blocks));
- emit_label (label2);
- operands[0] = change_address (operands[0], VOIDmode, reg0);
- operands[1] = change_address (operands[1], VOIDmode, reg1);
- emit_insn (gen_movstrdi_short (operands[0], operands[1], len));
- emit_label (label1);
- DONE;
- }
- }
-}")
-
-;
-; movstrsi instruction pattern(s).
-;
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" ""))
+ (use (match_operand:DI 2 "general_operand" ""))
+ (match_operand 3 "" "")]
+ "TARGET_64BIT"
+ "s390_expand_movstr (operands[0], operands[1], operands[2]); DONE;")
(define_expand "movstrsi"
- [(set (match_operand:BLK 0 "general_operand" "")
- (match_operand:BLK 1 "general_operand" ""))
- (use (match_operand:SI 2 "general_operand" ""))
- (match_operand 3 "" "")]
- "!TARGET_64BIT"
- "
-{
- rtx addr0 = force_operand (XEXP (operands[0], 0), NULL_RTX);
- rtx addr1 = force_operand (XEXP (operands[1], 0), NULL_RTX);
-
- if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) <= 256)
- {
- operands[0] = change_address (operands[0], VOIDmode, addr0);
- operands[1] = change_address (operands[1], VOIDmode, addr1);
- operands[2] = GEN_INT (INTVAL (operands[2]) - 1);
-
- emit_insn (gen_movstrsi_short (operands[0], operands[1], operands[2]));
- DONE;
- }
- else
- {
- if (TARGET_MVCLE)
- {
- /* implementation suggested by Richard Henderson <rth@cygnus.com> */
- rtx reg0 = gen_reg_rtx (DImode);
- rtx reg1 = gen_reg_rtx (DImode);
- rtx len = operands[2];
-
-
- if (! CONSTANT_P (len))
- len = force_reg (SImode, len);
-
- /* Load up the address+length pairs. */
-
- emit_move_insn (gen_highpart (SImode, reg0), addr0);
- emit_move_insn (gen_lowpart (SImode, reg0), len);
-
- emit_move_insn (gen_highpart (SImode, reg1), addr1);
- emit_move_insn (gen_lowpart (SImode, reg1), len);
-
- /* MOVE */
- emit_insn (gen_movstrsi_31 (reg0, reg1, reg0, reg1));
- DONE;
- }
- else
- {
- rtx label1 = gen_label_rtx ();
- rtx label2 = gen_label_rtx ();
- rtx reg0, reg1, len, blocks;
-
- reg0 = gen_reg_rtx (SImode);
- reg1 = gen_reg_rtx (SImode);
- len = gen_reg_rtx (SImode);
- blocks = gen_reg_rtx (SImode);
-
- emit_move_insn (len, operands[2]);
- emit_insn (gen_cmpsi (len, const0_rtx));
- emit_jump_insn (gen_beq (label1));
- emit_move_insn (reg0, addr0);
- emit_move_insn (reg1, addr1);
- emit_insn (gen_addsi3 (len, len, constm1_rtx));
- emit_insn (gen_ashrsi3 (blocks, len, GEN_INT (8)));
- emit_insn (gen_cmpsi (blocks, const0_rtx));
- emit_jump_insn (gen_beq (label2));
- emit_insn (gen_movstrsi_long (reg0, reg1, reg0, reg1, blocks, blocks));
- emit_label (label2);
- operands[0] = change_address (operands[0], VOIDmode, reg0);
- operands[1] = change_address (operands[1], VOIDmode, reg1);
- emit_insn (gen_movstrsi_short (operands[0], operands[1], len));
- emit_label (label1);
- DONE;
- }
- }
-}")
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" ""))
+ (use (match_operand:SI 2 "general_operand" ""))
+ (match_operand 3 "" "")]
+ ""
+ "s390_expand_movstr (operands[0], operands[1], operands[2]); DONE;")
; Move a block that is up to 256 bytes in length.
; The block length is taken as (operands[2] % 256) + 1.
-(define_insn "movstrdi_short"
- [(set (match_operand:BLK 0 "s_operand" "=oQ,oQ")
- (match_operand:BLK 1 "s_operand" "oQ,oQ"))
+(define_insn "movstr_short_64"
+ [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
+ (match_operand:BLK 1 "memory_operand" "Q,Q"))
(use (match_operand:DI 2 "nonmemory_operand" "n,a"))
(clobber (match_scratch:DI 3 "=X,&a"))]
"TARGET_64BIT"
@@ -1744,12 +1674,13 @@
}
}"
[(set_attr "op_type" "SS,NN")
+ (set_attr "type" "cs,cs")
(set_attr "atype" "mem,mem")
(set_attr "length" "*,14")])
-(define_insn "movstrsi_short"
- [(set (match_operand:BLK 0 "s_operand" "=oQ,oQ")
- (match_operand:BLK 1 "s_operand" "oQ,oQ"))
+(define_insn "movstr_short_31"
+ [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
+ (match_operand:BLK 1 "memory_operand" "Q,Q"))
(use (match_operand:SI 2 "nonmemory_operand" "n,a"))
(clobber (match_scratch:SI 3 "=X,&a"))]
"!TARGET_64BIT"
@@ -1770,64 +1701,13 @@
}
}"
[(set_attr "op_type" "SS,NN")
+ (set_attr "type" "cs,cs")
(set_attr "atype" "mem,mem")
(set_attr "length" "*,14")])
-; Move a block that is a multiple of 256 bytes in length
+; Move a block of arbitrary length.
-(define_insn "movstrdi_long"
- [(set (match_operand:DI 4 "register_operand" "=d")
- (const_int 0))
- (set (match_operand:DI 0 "register_operand" "=a")
- (plus:DI (match_operand:DI 2 "register_operand" "0")
- (ashift:DI (match_operand:DI 5 "register_operand" "4")
- (const_int 8))))
- (set (match_operand:DI 1 "register_operand" "=a")
- (plus:DI (match_operand:DI 3 "register_operand" "1")
- (ashift:DI (match_dup 5) (const_int 8))))
- (set (mem:BLK (match_dup 2))
- (mem:BLK (match_dup 3)))
- (use (match_dup 5))]
- "TARGET_64BIT"
- "*
-{
- output_asm_insn (\"mvc\\t0(256,%0),0(%1)\", operands);
- output_asm_insn (\"la\\t%0,256(%0)\", operands);
- output_asm_insn (\"la\\t%1,256(%1)\", operands);
- return \"brct\\t%4,.-14\";
-}"
- [(set_attr "op_type" "NN")
- (set_attr "atype" "mem")
- (set_attr "length" "18")])
-
-(define_insn "movstrsi_long"
- [(set (match_operand:SI 4 "register_operand" "=d")
- (const_int 0))
- (set (match_operand:SI 0 "register_operand" "=a")
- (plus:SI (match_operand:SI 2 "register_operand" "0")
- (ashift:SI (match_operand:SI 5 "register_operand" "4")
- (const_int 8))))
- (set (match_operand:SI 1 "register_operand" "=a")
- (plus:SI (match_operand:SI 3 "register_operand" "1")
- (ashift:SI (match_dup 5) (const_int 8))))
- (set (mem:BLK (match_dup 2))
- (mem:BLK (match_dup 3)))
- (use (match_dup 5))]
- "!TARGET_64BIT"
- "*
-{
- output_asm_insn (\"mvc\\t0(256,%0),0(%1)\", operands);
- output_asm_insn (\"la\\t%0,256(%0)\", operands);
- output_asm_insn (\"la\\t%1,256(%1)\", operands);
- return \"brct\\t%4,.-14\";
-}"
- [(set_attr "op_type" "NN")
- (set_attr "atype" "mem")
- (set_attr "length" "18")])
-
-; Move a block that is larger than 255 bytes in length.
-
-(define_insn "movstrdi_64"
+(define_insn "movstr_long_64"
[(set (match_operand:TI 0 "register_operand" "=d")
(ashift:TI (plus:TI (match_operand:TI 2 "register_operand" "0")
(lshiftrt:TI (match_dup 2) (const_int 64)))
@@ -1842,10 +1722,11 @@
"TARGET_64BIT"
"mvcle\\t%0,%1,0\;jo\\t.-4"
[(set_attr "op_type" "NN")
+ (set_attr "type" "vs")
(set_attr "atype" "mem")
(set_attr "length" "8")])
-(define_insn "movstrsi_31"
+(define_insn "movstr_long_31"
[(set (match_operand:DI 0 "register_operand" "=d")
(ashift:DI (plus:DI (match_operand:DI 2 "register_operand" "0")
(lshiftrt:DI (match_dup 2) (const_int 32)))
@@ -1859,112 +1740,93 @@
(clobber (reg:CC 33))]
"!TARGET_64BIT"
"mvcle\\t%0,%1,0\;jo\\t.-4"
- [(set_attr "op_type" "NN")
- (set_attr "atype" "mem")
- (set_attr "length" "8")])
+ [(set_attr "op_type" "NN")
+ (set_attr "type" "vs")
+ (set_attr "atype" "mem")
+ (set_attr "length" "8")])
;
-; clrstrdi instruction pattern(s).
+; clrstrM instruction pattern(s).
;
(define_expand "clrstrdi"
- [(set (match_operand:BLK 0 "general_operand" "")
+ [(set (match_operand:BLK 0 "memory_operand" "")
(const_int 0))
(use (match_operand:DI 1 "general_operand" ""))
(match_operand 2 "" "")]
"TARGET_64BIT"
- "
-{
- rtx addr = force_operand (XEXP (operands[0], 0), NULL_RTX);
-
- operands[0] = change_address (operands[0], VOIDmode, addr);
-
- if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 256)
- {
- emit_insn (gen_clrstrsico (operands[0], operands[1]));
- DONE;
- }
- else
- {
- rtx reg0 = gen_reg_rtx (TImode);
- rtx reg1 = gen_reg_rtx (TImode);
- rtx len = operands[1];
-
- if (! CONSTANT_P (len))
- len = force_reg (DImode, len);
-
- /* Load up the address+length pairs. */
-
- emit_move_insn (gen_highpart (DImode, reg0), addr);
- emit_move_insn (gen_lowpart (DImode, reg0), len);
-
- emit_move_insn (gen_lowpart (DImode, reg1), const0_rtx);
-
- /* Clear! */
- emit_insn (gen_clrstrsi_64 (reg0, reg1, reg0));
- DONE;
- }
-}")
-
-;
-; clrstrsi instruction pattern(s).
-;
+ "s390_expand_clrstr (operands[0], operands[1]); DONE;")
(define_expand "clrstrsi"
- [(set (match_operand:BLK 0 "general_operand" "")
+ [(set (match_operand:BLK 0 "memory_operand" "")
(const_int 0))
(use (match_operand:SI 1 "general_operand" ""))
(match_operand 2 "" "")]
- "!TARGET_64BIT"
- "
-{
- rtx addr = force_operand (XEXP (operands[0], 0), NULL_RTX);
-
- operands[0] = change_address (operands[0], VOIDmode, addr);
-
- if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 256)
- {
- emit_insn (gen_clrstrsico (operands[0], operands[1]));
- DONE;
- }
- else
- {
- rtx reg0 = gen_reg_rtx (DImode);
- rtx reg1 = gen_reg_rtx (DImode);
- rtx len = operands[1];
-
- if (! CONSTANT_P (len))
- len = force_reg (SImode, len);
+ ""
+ "s390_expand_clrstr (operands[0], operands[1]); DONE;")
- /* Load up the address+length pairs. */
+; Clear a block that is up to 256 bytes in length.
+; The block length is taken as (operands[2] % 256) + 1.
- emit_move_insn (gen_highpart (SImode, reg0), addr);
- emit_move_insn (gen_lowpart (SImode, reg0), len);
+(define_insn "clrstr_short_64"
+ [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
+ (const_int 0))
+ (use (match_operand:DI 1 "nonmemory_operand" "n,a"))
+ (clobber (match_scratch:DI 2 "=X,&a"))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return \"xc\\t%O0(%b1+1,%R0),%0\";
- emit_move_insn (gen_lowpart (SImode, reg1), const0_rtx);
-
- /* CLear! */
- emit_insn (gen_clrstrsi_31 (reg0, reg1, reg0));
- DONE;
- }
-}")
+ case 1:
+ output_asm_insn (\"bras\\t%2,.+10\", operands);
+ output_asm_insn (\"xc\\t%O0(1,%R0),%0\", operands);
+ return \"ex\\t%1,0(%2)\";
-; Clear memory with length less than 256 bytes
+ default:
+ abort ();
+ }
+}"
+ [(set_attr "op_type" "SS,NN")
+ (set_attr "type" "cs,cs")
+ (set_attr "atype" "mem,mem")
+ (set_attr "length" "*,14")])
-(define_insn "clrstrsico"
- [(set (match_operand:BLK 0 "s_operand" "=Qo")
+(define_insn "clrstr_short_31"
+ [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
(const_int 0))
- (use (match_operand 1 "immediate_operand" "I"))
+ (use (match_operand:SI 1 "nonmemory_operand" "n,a"))
+ (clobber (match_scratch:SI 2 "=X,&a"))
(clobber (reg:CC 33))]
- ""
- "xc\\t%O0(%1,%R0),%0"
- [(set_attr "op_type" "RS")
- (set_attr "type" "cs")
- (set_attr "atype" "mem")])
+ "!TARGET_64BIT"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return \"xc\\t%O0(%b1+1,%R0),%0\";
+
+ case 1:
+ output_asm_insn (\"bras\\t%2,.+10\", operands);
+ output_asm_insn (\"xc\\t%O0(1,%R0),%0\", operands);
+ return \"ex\\t%1,0(%2)\";
+
+ default:
+ abort ();
+ }
+}"
+ [(set_attr "op_type" "SS,NN")
+ (set_attr "type" "cs,cs")
+ (set_attr "atype" "mem,mem")
+ (set_attr "length" "*,14")])
-; Clear memory with length greater 256 bytes or lenght not constant
+; Clear a block of arbitrary length.
-(define_insn "clrstrsi_64"
+(define_insn "clrstr_long_64"
[(set (match_operand:TI 0 "register_operand" "=d")
(ashift:TI (plus:TI (match_operand:TI 2 "register_operand" "0")
(lshiftrt:TI (match_dup 2) (const_int 64)))
@@ -1980,7 +1842,7 @@
(set_attr "type" "vs")
(set_attr "length" "8")])
-(define_insn "clrstrsi_31"
+(define_insn "clrstr_long_31"
[(set (match_operand:DI 0 "register_operand" "=d")
(ashift:DI (plus:DI (match_operand:DI 2 "register_operand" "0")
(lshiftrt:DI (match_dup 2) (const_int 32)))
@@ -1997,171 +1859,112 @@
(set_attr "length" "8")])
;
-; cmpstrdi instruction pattern(s).
+; cmpstrM instruction pattern(s).
;
(define_expand "cmpstrdi"
- [(set (match_operand:DI 0 "register_operand" "")
- (compare:DI (match_operand:BLK 1 "s_operand" "")
- (match_operand:BLK 2 "s_operand" "") ) )
- (use (match_operand:DI 3 "general_operand" ""))
- (use (match_operand:DI 4 "" ""))]
- "TARGET_64BIT"
- "
-{
- rtx addr0, addr1;
+ [(set (match_operand:DI 0 "register_operand" "")
+ (compare:DI (match_operand:BLK 1 "memory_operand" "")
+ (match_operand:BLK 2 "memory_operand" "") ) )
+ (use (match_operand:DI 3 "general_operand" ""))
+ (use (match_operand:DI 4 "" ""))]
+ "TARGET_64BIT"
+ "s390_expand_cmpstr (operands[0], operands[1],
+ operands[2], operands[3]); DONE;")
- /* for pre/post increment */
- operands[1] = protect_from_queue (operands[1], 0);
- operands[2] = protect_from_queue (operands[2], 0);
- operands[3] = protect_from_queue (operands[3], 0);
+(define_expand "cmpstrsi"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (compare:SI (match_operand:BLK 1 "memory_operand" "")
+ (match_operand:BLK 2 "memory_operand" "") ) )
+ (use (match_operand:SI 3 "general_operand" ""))
+ (use (match_operand:SI 4 "" ""))]
+ ""
+ "s390_expand_cmpstr (operands[0], operands[1],
+ operands[2], operands[3]); DONE;")
- addr0 = force_operand (XEXP (operands[1], 0), NULL_RTX);
- addr1 = force_operand (XEXP (operands[2], 0), NULL_RTX);
+; Compare a block that is up to 256 bytes in length.
+; The block length is taken as (operands[2] % 256) + 1.
- if (GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) < 256)
+(define_insn "cmpstr_short_64"
+ [(set (reg:CCS 33)
+ (compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q")
+ (match_operand:BLK 1 "memory_operand" "Q,Q")))
+ (use (match_operand:DI 2 "nonmemory_operand" "n,a"))
+ (clobber (match_scratch:DI 3 "=X,&a"))]
+ "TARGET_64BIT"
+ "*
+{
+ switch (which_alternative)
{
- if (INTVAL (operands[3]) == 0) {
- emit_move_insn (operands[0], operands[3]);
- DONE;
- }
-
- operands[1] = change_address (operands[1], VOIDmode, addr0);
- operands[2] = change_address (operands[2], VOIDmode, addr1);
-
- emit_insn (gen_cmpstr_const (operands[1], operands[2], operands[3]));
- emit_insn (gen_cmpint_di (operands[0]));
- DONE;
- }
- else
- {
- /* implementation suggested by Richard Henderson <rth@cygnus.com> */
- rtx reg0 = gen_reg_rtx (TImode);
- rtx reg1 = gen_reg_rtx (TImode);
- rtx len = operands[3];
-
- if (! CONSTANT_P (len))
- len = force_reg (DImode, len);
-
- /* Load up the address+length pairs. */
- emit_move_insn (gen_highpart (DImode, reg0), addr0);
- emit_move_insn (gen_lowpart (DImode, reg0), len);
+ case 0:
+ return \"clc\\t%O0(%b2+1,%R0),%1\";
- emit_move_insn (gen_highpart (DImode, reg1), addr1);
- emit_move_insn (gen_lowpart (DImode, reg1), len);
+ case 1:
+ output_asm_insn (\"bras\\t%3,.+10\", operands);
+ output_asm_insn (\"clc\\t%O0(1,%R0),%1\", operands);
+ return \"ex\\t%2,0(%3)\";
- /* Compare! */
- emit_insn (gen_cmpstr_64 (reg0, reg1, reg0, reg1));
- emit_insn (gen_cmpint_di (operands[0]));
- DONE;
+ default:
+ abort ();
}
-}")
-
-;
-; cmpstrsi instruction pattern(s).
-;
+}"
+ [(set_attr "op_type" "SS,NN")
+ (set_attr "type" "cs,cs")
+ (set_attr "atype" "mem,mem")
+ (set_attr "length" "*,14")])
-(define_expand "cmpstrsi"
- [(set (match_operand:SI 0 "register_operand" "")
- (compare:SI (match_operand:BLK 1 "s_operand" "")
- (match_operand:BLK 2 "s_operand" "") ) )
- (use (match_operand:SI 3 "general_operand" ""))
- (use (match_operand:SI 4 "" ""))]
- ""
- "
+(define_insn "cmpstr_short_31"
+ [(set (reg:CCS 33)
+ (compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q")
+ (match_operand:BLK 1 "memory_operand" "Q,Q")))
+ (use (match_operand:SI 2 "nonmemory_operand" "n,a"))
+ (clobber (match_scratch:SI 3 "=X,&a"))]
+ "!TARGET_64BIT"
+ "*
{
- rtx addr0, addr1;
-
- /* for pre/post increment */
- operands[1] = protect_from_queue (operands[1], 0);
- operands[2] = protect_from_queue (operands[2], 0);
- operands[3] = protect_from_queue (operands[3], 0);
-
- addr0 = force_operand (XEXP (operands[1], 0), NULL_RTX);
- addr1 = force_operand (XEXP (operands[2], 0), NULL_RTX);
-
- if (GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) < 256)
+ switch (which_alternative)
{
- if (INTVAL (operands[3]) == 0) {
- emit_move_insn (operands[0], operands[3]);
- DONE;
- }
-
- operands[1] = change_address (operands[1], VOIDmode, addr0);
- operands[2] = change_address (operands[2], VOIDmode, addr1);
-
- emit_insn (gen_cmpstr_const (operands[1], operands[2], operands[3]));
- emit_insn (gen_cmpint_si (operands[0]));
- DONE;
- }
- else
- {
- /* implementation suggested by Richard Henderson <rth@cygnus.com> */
- rtx reg0, reg1;
- rtx len = operands[3];
-
- if (TARGET_64BIT)
- {
- reg0 = gen_reg_rtx (TImode);
- reg1 = gen_reg_rtx (TImode);
- }
- else
- {
- reg0 = gen_reg_rtx (DImode);
- reg1 = gen_reg_rtx (DImode);
- }
-
- /* Load up the address+length pairs. */
- emit_move_insn (gen_highpart (Pmode, reg0), addr0);
- convert_move (gen_lowpart (Pmode, reg0), len, 1);
-
- emit_move_insn (gen_highpart (Pmode, reg1), addr1);
- convert_move (gen_lowpart (Pmode, reg1), len, 1);
+ case 0:
+ return \"clc\\t%O0(%b2+1,%R0),%1\";
- /* Compare! */
- if (TARGET_64BIT)
- emit_insn (gen_cmpstr_64 (reg0, reg1, reg0, reg1));
- else
- emit_insn (gen_cmpstr_31 (reg0, reg1, reg0, reg1));
+ case 1:
+ output_asm_insn (\"bras\\t%3,.+10\", operands);
+ output_asm_insn (\"clc\\t%O0(1,%R0),%1\", operands);
+ return \"ex\\t%2,0(%3)\";
- emit_insn (gen_cmpint_si (operands[0]));
- DONE;
+ default:
+ abort ();
}
-}")
-
-; Compare a block that is less than 256 bytes in length.
-
-(define_insn "cmpstr_const"
- [(set (reg:CCS 33)
- (compare:CCS (match_operand:BLK 0 "s_operand" "oQ")
- (match_operand:BLK 1 "s_operand" "oQ")))
- (use (match_operand 2 "immediate_operand" "I"))]
- "(unsigned) INTVAL (operands[2]) < 256"
- "clc\\t%O0(%c2,%R0),%1"
- [(set_attr "op_type" "SS")
- (set_attr "atype" "mem")
- (set_attr "type" "cs")])
+}"
+ [(set_attr "op_type" "SS,NN")
+ (set_attr "type" "cs,cs")
+ (set_attr "atype" "mem,mem")
+ (set_attr "length" "*,14")])
-; Compare a block that is larger than 255 bytes in length.
+; Compare a block of arbitrary length.
-(define_insn "cmpstr_64"
+(define_insn "cmpstr_long_64"
[(clobber (match_operand:TI 0 "register_operand" "=d"))
(clobber (match_operand:TI 1 "register_operand" "=d"))
(set (reg:CCS 33)
(compare:CCS (mem:BLK (subreg:DI (match_operand:TI 2 "register_operand" "0") 0))
- (mem:BLK (subreg:DI (match_operand:TI 3 "register_operand" "1") 0))))]
+ (mem:BLK (subreg:DI (match_operand:TI 3 "register_operand" "1") 0))))
+ (use (match_dup 2))
+ (use (match_dup 3))]
"TARGET_64BIT"
"clcl\\t%0,%1"
[(set_attr "op_type" "RR")
(set_attr "atype" "mem")
(set_attr "type" "vs")])
-(define_insn "cmpstr_31"
+(define_insn "cmpstr_long_31"
[(clobber (match_operand:DI 0 "register_operand" "=d"))
(clobber (match_operand:DI 1 "register_operand" "=d"))
(set (reg:CCS 33)
(compare:CCS (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "0") 0))
- (mem:BLK (subreg:SI (match_operand:DI 3 "register_operand" "1") 0))))]
+ (mem:BLK (subreg:SI (match_operand:DI 3 "register_operand" "1") 0))))
+ (use (match_dup 2))
+ (use (match_dup 3))]
"!TARGET_64BIT"
"clcl\\t%0,%1"
[(set_attr "op_type" "RR")
@@ -2211,7 +2014,7 @@
(define_insn "*sethighqisi"
[(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(match_operand:QI 1 "s_operand" "Qo")] 10))
+ (unspec:SI [(match_operand:QI 1 "s_operand" "Q")] 10))
(clobber (reg:CC 33))]
""
"icm\\t%0,8,%1"
@@ -2220,7 +2023,7 @@
(define_insn "*sethighhisi"
[(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(match_operand:HI 1 "s_operand" "Qo")] 10))
+ (unspec:SI [(match_operand:HI 1 "s_operand" "Q")] 10))
(clobber (reg:CC 33))]
""
"icm\\t%0,12,%1"
@@ -2229,7 +2032,7 @@
(define_insn "*sethighqidi_64"
[(set (match_operand:DI 0 "register_operand" "=d")
- (unspec:DI [(match_operand:QI 1 "s_operand" "Qo")] 10))
+ (unspec:DI [(match_operand:QI 1 "s_operand" "Q")] 10))
(clobber (reg:CC 33))]
"TARGET_64BIT"
"icmh\\t%0,8,%1"
@@ -2238,20 +2041,23 @@
(define_insn "*sethighqidi_31"
[(set (match_operand:DI 0 "register_operand" "=d")
- (unspec:DI [(match_operand:QI 1 "s_operand" "Qo")] 10))
+ (unspec:DI [(match_operand:QI 1 "s_operand" "Q")] 10))
(clobber (reg:CC 33))]
"!TARGET_64BIT"
"icm\\t%0,8,%1"
[(set_attr "op_type" "RS")
(set_attr "atype" "mem")])
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (zero_extract:SI (match_operand:QI 1 "s_operand" "")
- (match_operand 2 "const_int_operand" "")
- (const_int 0)))]
- "!TARGET_64BIT && !reload_completed
+(define_insn_and_split "*extractqi"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extract:SI (match_operand:QI 1 "s_operand" "Q")
+ (match_operand 2 "const_int_operand" "n")
+ (const_int 0)))
+ (clobber (reg:CC 33))]
+ "!TARGET_64BIT
&& INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 8"
+ "#"
+ "&& reload_completed"
[(parallel
[(set (match_dup 0) (unspec:SI [(match_dup 1)] 10))
(clobber (reg:CC 33))])
@@ -2260,15 +2066,19 @@
{
operands[2] = GEN_INT (32 - INTVAL (operands[2]));
operands[1] = change_address (operands[1], QImode, 0);
-}")
+}"
+ [(set_attr "atype" "mem")])
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (zero_extract:SI (match_operand:QI 1 "s_operand" "")
- (match_operand 2 "const_int_operand" "")
- (const_int 0)))]
- "!TARGET_64BIT && !reload_completed
+(define_insn_and_split "*extracthi"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extract:SI (match_operand:QI 1 "s_operand" "Q")
+ (match_operand 2 "const_int_operand" "n")
+ (const_int 0)))
+ (clobber (reg:CC 33))]
+ "!TARGET_64BIT
&& INTVAL (operands[2]) >= 8 && INTVAL (operands[2]) < 16"
+ "#"
+ "&& reload_completed"
[(parallel
[(set (match_dup 0) (unspec:SI [(match_dup 1)] 10))
(clobber (reg:CC 33))])
@@ -2277,7 +2087,8 @@
{
operands[2] = GEN_INT (32 - INTVAL (operands[2]));
operands[1] = change_address (operands[1], HImode, 0);
-}")
+}"
+ [(set_attr "atype" "mem")])
;
; extendsidi2 instruction pattern(s).
@@ -2566,6 +2377,20 @@
"llgh\\t%0,%1"
[(set_attr "op_type" "RXE")
(set_attr "atype" "mem")])
+
+(define_insn_and_split "*zero_extendhisi2_31"
+ [(set (match_operand:SI 0 "register_operand" "=&d")
+ (zero_extend:SI (match_operand:HI 1 "memory_operand" "Q")))
+ (clobber (reg:CC 33))]
+ "!TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (const_int 0))
+ (parallel
+ [(set (strict_low_part (match_dup 2)) (match_dup 1))
+ (clobber (reg:CC 33))])]
+ "operands[2] = gen_lowpart (HImode, operands[0]);"
+ [(set_attr "atype" "mem")])
;
; zero_extendqisi2 instruction pattern(s).
@@ -2590,6 +2415,17 @@
"llgc\\t%0,%1"
[(set_attr "op_type" "RXE")
(set_attr "atype" "mem")])
+
+(define_insn_and_split "*zero_extendqisi2_31"
+ [(set (match_operand:SI 0 "register_operand" "=&d")
+ (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
+ "!TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (const_int 0))
+ (set (strict_low_part (match_dup 2)) (match_dup 1))]
+ "operands[2] = gen_lowpart (QImode, operands[0]);"
+ [(set_attr "atype" "mem")])
;
; zero_extendqihi2 instruction pattern(s).
@@ -2609,13 +2445,24 @@
(define_insn "*zero_extendqihi2_64"
[(set (match_operand:HI 0 "register_operand" "=d")
- (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))
- (clobber (reg:CC 33))]
+ (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
"TARGET_64BIT"
"llgc\\t%0,%1"
[(set_attr "op_type" "RXE")
(set_attr "atype" "mem")])
+(define_insn_and_split "*zero_extendqihi2_31"
+ [(set (match_operand:HI 0 "register_operand" "=&d")
+ (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
+ "!TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (const_int 0))
+ (set (strict_low_part (match_dup 2)) (match_dup 1))]
+ "operands[2] = gen_lowpart (QImode, operands[0]);"
+ [(set_attr "atype" "mem")])
+
+
;
; fixuns_truncdfdi2 and fix_truncdfsi2 instruction pattern(s).
;
@@ -3062,24 +2909,113 @@
; adddi3 instruction pattern(s).
;
-(define_insn "addaddr_esame"
- [(set (match_operand:DI 0 "register_operand" "=a,a")
- (plus:DI (match_operand:DI 1 "register_operand" "%a,a")
- (match_operand:DI 2 "nonmemory_operand" "J,a")))]
- "TARGET_64BIT && (((REGNO (operands[1]) == STACK_POINTER_REGNUM ) ||
- (REGNO (operands[1]) == BASE_REGISTER)) &&
- (GET_CODE (operands[2]) == REG ||
- CONST_OK_FOR_LETTER_P (INTVAL (operands[2]),'J')))"
+(define_insn "*adddi3_sign"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (plus:DI (sign_extend:DI (match_operand:SI 2 "general_operand" "d,m"))
+ (match_operand:DI 1 "register_operand" "0,0")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
"@
- la\\t%0,%c2(,%1)
- la\\t%0,0(%1,%2)"
- [(set_attr "op_type" "RX")
- (set_attr "atype" "mem")
- (set_attr "type" "la")])
+ agfr\\t%0,%2
+ agf\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*adddi3_zero_cc"
+ [(set (reg 33)
+ (compare (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m"))
+ (match_operand:DI 1 "register_operand" "0,0"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=d,d")
+ (plus:DI (zero_extend:DI (match_dup 2)) (match_dup 1)))]
+ "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
+ "@
+ algfr\\t%0,%2
+ algf\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
-(define_insn "adddi3_64"
+(define_insn "*adddi3_zero_cconly"
+ [(set (reg 33)
+ (compare (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m"))
+ (match_operand:DI 1 "register_operand" "0,0"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=d,d"))]
+ "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
+ "@
+ algfr\\t%0,%2
+ algf\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*adddi3_zero"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m"))
+ (match_operand:DI 1 "register_operand" "0,0")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ algfr\\t%0,%2
+ algf\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*adddi3_imm_cc"
+ [(set (reg 33)
+ (compare (plus:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+ (match_operand:DI 2 "const_int_operand" "K"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=d")
+ (plus:DI (match_dup 1) (match_dup 2)))]
+ "TARGET_64BIT
+ && s390_match_ccmode (insn, CCAmode)
+ && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')"
+ "aghi\\t%0,%h2"
+ [(set_attr "op_type" "RI")
+ (set_attr "atype" "reg")])
+
+(define_insn "*adddi3_cc"
+ [(set (reg 33)
+ (compare (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "d,m"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=d,d")
+ (plus:DI (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
+ "@
+ algr\\t%0,%2
+ alg\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*adddi3_cconly"
+ [(set (reg 33)
+ (compare (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "d,m"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=d,d"))]
+ "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
+ "@
+ algr\\t%0,%2
+ alg\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*adddi3_cconly2"
+ [(set (reg 33)
+ (compare (match_operand:DI 1 "nonimmediate_operand" "%0,0")
+ (neg:SI (match_operand:DI 2 "general_operand" "d,m"))))
+ (clobber (match_scratch:DI 0 "=d,d"))]
+ "s390_match_ccmode(insn, CCLmode) && TARGET_64BIT"
+ "@
+ algr\\t%0,%2
+ alg\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*adddi3_64"
[(set (match_operand:DI 0 "register_operand" "=d,d,d")
- (plus:DI (match_operand:DI 1 "register_operand" "%0,0,0")
+ (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0")
(match_operand:DI 2 "general_operand" "d,K,m") ) )
(clobber (reg:CC 33))]
"TARGET_64BIT"
@@ -3090,51 +3026,47 @@
[(set_attr "op_type" "RRE,RI,RXE")
(set_attr "atype" "reg,reg,mem")])
-(define_insn "adddi3_31"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (plus:DI (match_operand:DI 1 "register_operand" "0,0")
- (match_operand:DI 2 "general_operand" "d,m") ) )
+(define_insn_and_split "*adddi3_31"
+ [(set (match_operand:DI 0 "register_operand" "=&d")
+ (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
+ (match_operand:DI 2 "general_operand" "do") ) )
(clobber (reg:CC 33))]
"!TARGET_64BIT"
- "*
-{
- switch (which_alternative)
- {
- case 0: /* d <- d */
- output_asm_insn (\"ar\\t%0,%2\", operands);
- output_asm_insn (\"alr\\t%N0,%N2\", operands);
- break;
-
- case 1: /* d <- m */
- output_asm_insn (\"a\\t%0,%2\", operands);
- output_asm_insn (\"al\\t%N0,%N2\", operands);
- break;
-
- default:
- abort ();
- }
-
- output_asm_insn (\"brc\\t12,.+8\", operands);
- return \"ahi\\t%0,1\";
-}"
- [(set_attr "op_type" "NN,NN")
- (set_attr "atype" "reg,mem")
- (set_attr "type" "o2,o2")
- (set_attr "length" "12,16")])
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 3) (plus:SI (match_dup 4) (match_dup 5)))
+ (clobber (reg:CC 33))])
+ (parallel
+ [(set (reg:CCL1 33)
+ (compare:CCL1 (plus:SI (match_dup 7) (match_dup 8))
+ (match_dup 7)))
+ (set (match_dup 6) (plus:SI (match_dup 7) (match_dup 8)))])
+ (set (pc)
+ (if_then_else (ltu (reg:CCL1 33) (const_int 0))
+ (pc)
+ (label_ref (match_dup 9))))
+ (parallel
+ [(set (match_dup 3) (plus:SI (match_dup 3) (const_int 1)))
+ (clobber (reg:CC 33))])
+ (match_dup 9)]
+ "operands[3] = operand_subword (operands[0], 0, 0, DImode);
+ operands[4] = operand_subword (operands[1], 0, 0, DImode);
+ operands[5] = operand_subword (operands[2], 0, 0, DImode);
+ operands[6] = operand_subword (operands[0], 1, 0, DImode);
+ operands[7] = operand_subword (operands[1], 1, 0, DImode);
+ operands[8] = operand_subword (operands[2], 1, 0, DImode);
+ operands[9] = gen_label_rtx ();"
+ [(set_attr "op_type" "NN")])
(define_expand "adddi3"
- [(set (match_operand:DI 0 "register_operand" "")
- (plus:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "general_operand" "")))]
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
+ (match_operand:DI 2 "general_operand" "")))
+ (clobber (reg:CC 33))])]
""
- "
-{
- if (TARGET_64BIT)
- emit_insn(gen_adddi3_64 (operands[0],operands[1],operands[2]));
- else
- emit_insn(gen_adddi3_31 (operands[0],operands[1],operands[2]));
- DONE;
-}")
+ "")
(define_insn "*la_64"
[(set (match_operand:DI 0 "register_operand" "=d")
@@ -3145,10 +3077,36 @@
(set_attr "atype" "mem")
(set_attr "type" "la")])
+(define_peephole2
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:QI 1 "address_operand" ""))
+ (clobber (reg:CC 33))])]
+ "TARGET_64BIT
+ && strict_memory_address_p (VOIDmode, operands[1])
+ && preferred_la_operand_p (operands[1])"
+ [(set (match_dup 0) (match_dup 1))]
+ "")
+
+(define_peephole2
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "register_operand" ""))
+ (parallel
+ [(set (match_dup 0)
+ (plus:DI (match_dup 0)
+ (match_operand:DI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC 33))])]
+ "TARGET_64BIT
+ && !reg_overlap_mentioned_p (operands[0], operands[2])
+ && strict_memory_address_p (VOIDmode, gen_rtx_PLUS (DImode, operands[1], operands[2]))
+ && preferred_la_operand_p (gen_rtx_PLUS (DImode, operands[1], operands[2]))"
+ [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))]
+ "")
+
(define_expand "reload_indi"
[(parallel [(match_operand:DI 0 "register_operand" "=a")
(match_operand:DI 1 "s390_plus_operand" "")
- (match_operand:TI 2 "register_operand" "=&a")])]
+ (match_operand:DI 2 "register_operand" "=&a")])]
"TARGET_64BIT"
"
{
@@ -3161,24 +3119,81 @@
; addsi3 instruction pattern(s).
;
-(define_insn "*la_ccclobber"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (match_operand:QI 1 "address_operand" "p"))
- (clobber (reg:CC 33))]
- "legitimate_la_operand_p (operands[1])"
- "la\\t%0,%a1"
- [(set_attr "op_type" "RX")
- (set_attr "atype" "mem")
- (set_attr "type" "la")])
+(define_insn "*addsi3_imm_cc"
+ [(set (reg 33)
+ (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "0")
+ (match_operand:SI 2 "const_int_operand" "K"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode (insn, CCAmode)
+ && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')"
+ "ahi\\t%0,%h2"
+ [(set_attr "op_type" "RI")
+ (set_attr "atype" "reg")])
+
+(define_insn "*addsi3_carry1_cc"
+ [(set (reg 33)
+ (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
+ (match_dup 1)))
+ (set (match_operand:SI 0 "register_operand" "=d,d")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode (insn, CCL1mode)"
+ "@
+ alr\\t%0,%2
+ al\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*addsi3_carry1_cconly"
+ [(set (reg 33)
+ (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
+ (match_dup 1)))
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "s390_match_ccmode (insn, CCL1mode)"
+ "@
+ alr\\t%0,%2
+ al\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*addsi3_carry2_cc"
+ [(set (reg 33)
+ (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
+ (match_dup 2)))
+ (set (match_operand:SI 0 "register_operand" "=d,d")
+ (plus:SI (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode (insn, CCL1mode)"
+ "@
+ alr\\t%0,%2
+ al\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*addsi3_carry2_cconly"
+ [(set (reg 33)
+ (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
+ (match_dup 2)))
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "s390_match_ccmode (insn, CCL1mode)"
+ "@
+ alr\\t%0,%2
+ al\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
(define_insn "*addsi3_cc"
[(set (reg 33)
- (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
- (match_operand:SI 2 "nonimmediate_operand" "d,m"))
+ (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=d,d")
(plus:SI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode(insn, CCLmode)"
+ "s390_match_ccmode (insn, CCLmode)"
"@
alr\\t%0,%2
al\\t%0,%2"
@@ -3187,11 +3202,11 @@
(define_insn "*addsi3_cconly"
[(set (reg 33)
- (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "d,m"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=d,d"))]
- "s390_match_ccmode(insn, CCLmode)"
+ "s390_match_ccmode (insn, CCLmode)"
"@
alr\\t%0,%2
al\\t%0,%2"
@@ -3200,7 +3215,7 @@
(define_insn "*addsi3_cconly2"
[(set (reg 33)
- (compare (match_operand:SI 1 "register_operand" "%0,0")
+ (compare (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(neg:SI (match_operand:SI 2 "general_operand" "d,m"))))
(clobber (match_scratch:SI 0 "=d,d"))]
"s390_match_ccmode(insn, CCLmode)"
@@ -3210,9 +3225,29 @@
[(set_attr "op_type" "RR,RX")
(set_attr "atype" "reg,mem")])
+(define_insn "*addsi3_sign"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (sign_extend:SI (match_operand:HI 2 "memory_operand" "m"))))
+ (clobber (reg:CC 33))]
+ ""
+ "ah\\t%0,%2"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")])
+
+(define_insn "*addsi3_sub"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (match_operand:SI 1 "register_operand" "0")
+ (subreg:SI (match_operand:HI 2 "memory_operand" "m") 0)))
+ (clobber (reg:CC 33))]
+ ""
+ "ah\\t%0,%2"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")])
+
(define_insn "addsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d,d")
- (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0")
+ (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
(match_operand:SI 2 "general_operand" "d,K,m")))
(clobber (reg:CC 33))]
""
@@ -3223,23 +3258,71 @@
[(set_attr "op_type" "RR,RI,RX")
(set_attr "atype" "reg,reg,mem")])
-(define_insn "*addsi3_inv"
- [(set (match_operand:SI 0 "register_operand" "=d,d,d")
- (plus:SI (match_operand:SI 1 "general_operand" "%d,K,m")
- (match_operand:SI 2 "register_operand" "0,0,0")))
+(define_insn "*la_31"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (match_operand:QI 1 "address_operand" "p"))]
+ "!TARGET_64BIT && legitimate_la_operand_p (operands[1])"
+ "la\\t%0,%a1"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")
+ (set_attr "type" "la")])
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:QI 1 "address_operand" ""))
+ (clobber (reg:CC 33))])]
+ "!TARGET_64BIT
+ && strict_memory_address_p (VOIDmode, operands[1])
+ && preferred_la_operand_p (operands[1])"
+ [(set (match_dup 0) (match_dup 1))]
+ "")
+
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "register_operand" ""))
+ (parallel
+ [(set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (match_operand:SI 2 "nonmemory_operand" "")))
+ (clobber (reg:CC 33))])]
+ "!TARGET_64BIT
+ && !reg_overlap_mentioned_p (operands[0], operands[2])
+ && strict_memory_address_p (VOIDmode, gen_rtx_PLUS (SImode, operands[1], operands[2]))
+ && preferred_la_operand_p (gen_rtx_PLUS (SImode, operands[1], operands[2]))"
+ [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))]
+ "")
+
+(define_insn "*la_31_and"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (and:SI (match_operand:QI 1 "address_operand" "p")
+ (const_int 2147483647)))]
+ "!TARGET_64BIT"
+ "la\\t%0,%a1"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")
+ (set_attr "type" "la")])
+
+(define_insn_and_split "*la_31_and_cc"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (and:SI (match_operand:QI 1 "address_operand" "p")
+ (const_int 2147483647)))
(clobber (reg:CC 33))]
+ "!TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (and:SI (match_dup 1) (const_int 2147483647)))]
""
- "@
- ar\\t%0,%1
- ahi\\t%0,%h1
- a\\t%0,%1"
- [(set_attr "op_type" "RR,RI,RX")
- (set_attr "atype" "reg,reg,mem")])
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")
+ (set_attr "type" "la")])
-(define_insn "*la_31"
+(define_insn "force_la_31"
[(set (match_operand:SI 0 "register_operand" "=d")
- (match_operand:QI 1 "address_operand" "p"))]
- "legitimate_la_operand_p (operands[1])"
+ (match_operand:QI 1 "address_operand" "p"))
+ (use (const_int 0))]
+ "!TARGET_64BIT"
"la\\t%0,%a1"
[(set_attr "op_type" "RX")
(set_attr "atype" "mem")
@@ -3248,7 +3331,7 @@
(define_expand "reload_insi"
[(parallel [(match_operand:SI 0 "register_operand" "=a")
(match_operand:SI 1 "s390_plus_operand" "")
- (match_operand:DI 2 "register_operand" "=&a")])]
+ (match_operand:SI 2 "register_operand" "=&a")])]
"!TARGET_64BIT"
"
{
@@ -3258,48 +3341,13 @@
;
-; addhi3 instruction pattern(s).
-;
-
-(define_insn "addhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,d,d")
- (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
- (match_operand:HI 2 "general_operand" "d,K,m")))
- (clobber (reg:CC 33))]
- ""
- "@
- ar\\t%0,%2
- ahi\\t%0,%h2
- ah\\t%0,%2"
- [(set_attr "op_type" "RR,RI,RX")
- (set_attr "atype" "reg,reg,mem")])
-
-
-;
-; addqi3 instruction pattern(s).
-;
-
-(define_insn "addqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,d")
- (plus:QI (match_operand:QI 1 "register_operand" "%0,0")
- (match_operand:QI 2 "general_operand" "a,n")))
- (clobber (reg:CC 33))]
- ""
- "@
- ar\\t%0,%2
- ahi\\t%0,%h2"
- [(set_attr "op_type" "RX,RX")
- (set_attr "atype" "reg,mem")])
-
-
-;
; adddf3 instruction pattern(s).
;
(define_expand "adddf3"
[(parallel
[(set (match_operand:DF 0 "register_operand" "=f,f")
- (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
+ (plus:DF (match_operand:DF 1 "nonimmediate_operand" "%0,0")
(match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))])]
"TARGET_HARD_FLOAT"
@@ -3307,7 +3355,7 @@
(define_insn "*adddf3"
[(set (match_operand:DF 0 "register_operand" "=f,f")
- (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
+ (plus:DF (match_operand:DF 1 "nonimmediate_operand" "%0,0")
(match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
@@ -3319,7 +3367,7 @@
(define_insn "*adddf3_ibm"
[(set (match_operand:DF 0 "register_operand" "=f,f")
- (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
+ (plus:DF (match_operand:DF 1 "nonimmediate_operand" "%0,0")
(match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
@@ -3336,7 +3384,7 @@
(define_expand "addsf3"
[(parallel
[(set (match_operand:SF 0 "register_operand" "=f,f")
- (plus:SF (match_operand:SF 1 "register_operand" "%0,0")
+ (plus:SF (match_operand:SF 1 "nonimmediate_operand" "%0,0")
(match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))])]
"TARGET_HARD_FLOAT"
@@ -3344,7 +3392,7 @@
(define_insn "*addsf3"
[(set (match_operand:SF 0 "register_operand" "=f,f")
- (plus:SF (match_operand:SF 1 "register_operand" "%0,0")
+ (plus:SF (match_operand:SF 1 "nonimmediate_operand" "%0,0")
(match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
@@ -3356,7 +3404,7 @@
(define_insn "*addsf3"
[(set (match_operand:SF 0 "register_operand" "=f,f")
- (plus:SF (match_operand:SF 1 "register_operand" "%0,0")
+ (plus:SF (match_operand:SF 1 "nonimmediate_operand" "%0,0")
(match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
@@ -3375,6 +3423,84 @@
; subdi3 instruction pattern(s).
;
+(define_insn "*subdi3_sign"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (minus:DI (match_operand:DI 1 "register_operand" "0,0")
+ (sign_extend:DI (match_operand:SI 2 "general_operand" "d,m"))))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ sgfr\\t%0,%2
+ sgf\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*subdi3_zero_cc"
+ [(set (reg 33)
+ (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
+ (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m")))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=d,d")
+ (minus:DI (match_dup 1) (zero_extend:DI (match_dup 2))))]
+ "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
+ "@
+ slgfr\\t%0,%2
+ slgf\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*subdi3_zero_cconly"
+ [(set (reg 33)
+ (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
+ (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m")))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=d,d"))]
+ "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
+ "@
+ slgfr\\t%0,%2
+ slgf\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*subdi3_zero"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (minus:DI (match_operand:DI 1 "register_operand" "0,0")
+ (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m"))))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ slgfr\\t%0,%2
+ slgf\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*subdi3_cc"
+ [(set (reg 33)
+ (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
+ (match_operand:DI 2 "general_operand" "d,m"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=d,d")
+ (minus:DI (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode (insn, CCLmode)"
+ "@
+ slgr\\t%0,%2
+ slg\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*subdi3_cconly"
+ [(set (reg 33)
+ (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
+ (match_operand:DI 2 "general_operand" "d,m"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=d,d"))]
+ "s390_match_ccmode (insn, CCLmode)"
+ "@
+ slgr\\t%0,%2
+ slg\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
(define_insn "*subdi3_64"
[(set (match_operand:DI 0 "register_operand" "=d,d")
(minus:DI (match_operand:DI 1 "register_operand" "0,0")
@@ -3387,41 +3513,79 @@
[(set_attr "op_type" "RRE,RRE")
(set_attr "atype" "reg,mem")])
-(define_insn "subdi3"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (minus:DI (match_operand:DI 1 "register_operand" "0,0")
- (match_operand:DI 2 "general_operand" "d,m")))
+(define_insn_and_split "*subdi3_31"
+ [(set (match_operand:DI 0 "register_operand" "=&d")
+ (minus:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "general_operand" "do") ) )
(clobber (reg:CC 33))]
+ "!TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 3) (minus:SI (match_dup 4) (match_dup 5)))
+ (clobber (reg:CC 33))])
+ (parallel
+ [(set (reg:CCL2 33)
+ (compare:CCL2 (minus:SI (match_dup 7) (match_dup 8))
+ (match_dup 7)))
+ (set (match_dup 6) (minus:SI (match_dup 7) (match_dup 8)))])
+ (set (pc)
+ (if_then_else (gtu (reg:CCL2 33) (const_int 0))
+ (pc)
+ (label_ref (match_dup 9))))
+ (parallel
+ [(set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))
+ (clobber (reg:CC 33))])
+ (match_dup 9)]
+ "operands[3] = operand_subword (operands[0], 0, 0, DImode);
+ operands[4] = operand_subword (operands[1], 0, 0, DImode);
+ operands[5] = operand_subword (operands[2], 0, 0, DImode);
+ operands[6] = operand_subword (operands[0], 1, 0, DImode);
+ operands[7] = operand_subword (operands[1], 1, 0, DImode);
+ operands[8] = operand_subword (operands[2], 1, 0, DImode);
+ operands[9] = gen_label_rtx ();"
+ [(set_attr "op_type" "NN")])
+
+(define_expand "subdi3"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (minus:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "general_operand" "")))
+ (clobber (reg:CC 33))])]
""
- "*
-{
- switch (which_alternative)
- {
- case 0: /* d <- d */
- output_asm_insn (\"sr\\t%0,%2\", operands);
- output_asm_insn (\"slr\\t%N0,%N2\", operands);
- break;
- case 1: /* d <- m */
- output_asm_insn (\"s\\t%0,%2\", operands);
- output_asm_insn (\"sl\\t%N0,%N2\", operands);
- break;
-
- default:
- abort ();
- }
-
- output_asm_insn (\"brc\\t11,.+8\", operands);
- return \"ahi\\t%0,-1\";
-}"
- [(set_attr "op_type" "NN,NN")
- (set_attr "atype" "reg,mem")
- (set_attr "type" "other,other")
- (set_attr "length" "12,16")])
+ "")
;
; subsi3 instruction pattern(s).
;
+(define_insn "*subsi3_borrow_cc"
+ [(set (reg 33)
+ (compare (minus:SI (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
+ (match_dup 1)))
+ (set (match_operand:SI 0 "register_operand" "=d,d")
+ (minus:SI (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode(insn, CCL2mode)"
+ "@
+ slr\\t%0,%2
+ sl\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*subsi3_borrow_cconly"
+ [(set (reg 33)
+ (compare (minus:SI (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
+ (match_dup 1)))
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "s390_match_ccmode(insn, CCL2mode)"
+ "@
+ slr\\t%0,%2
+ sl\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
(define_insn "*subsi3_cc"
[(set (reg 33)
(compare (minus:SI (match_operand:SI 1 "register_operand" "0,0")
@@ -3449,6 +3613,26 @@
[(set_attr "op_type" "RR,RX")
(set_attr "atype" "reg,mem")])
+(define_insn "*subsi3_sign"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (minus:SI (match_operand:SI 1 "register_operand" "0")
+ (sign_extend:SI (match_operand:HI 2 "memory_operand" "m"))))
+ (clobber (reg:CC 33))]
+ ""
+ "sh\\t%0,%2"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")])
+
+(define_insn "*subsi3_sub"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (minus:SI (match_operand:SI 1 "register_operand" "0")
+ (subreg:SI (match_operand:HI 2 "memory_operand" "m") 0)))
+ (clobber (reg:CC 33))]
+ ""
+ "sh\\t%0,%2"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")])
+
(define_insn "subsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d")
(minus:SI (match_operand:SI 1 "register_operand" "0,0")
@@ -3461,34 +3645,6 @@
[(set_attr "op_type" "RR,RX")
(set_attr "atype" "reg,mem")])
-;
-; subhi3 instruction pattern(s).
-;
-
-(define_insn "subhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (minus:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "general_operand" "d,m")))
- (clobber (reg:CC 33))]
- ""
- "@
- sr\\t%0,%2
- sh\\t%0,%2"
- [(set_attr "op_type" "RR,RX")
- (set_attr "atype" "reg,mem")])
-
-;
-; subqi3 instruction pattern(s).
-;
-
-(define_insn "subqi3"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (minus:QI (match_operand:QI 1 "register_operand" "0")
- (match_operand:QI 2 "register_operand" "d")))
- (clobber (reg:CC 33))]
- ""
- "sr\\t%0,%2"
- [(set_attr "op_type" "RR")])
;
; subdf3 instruction pattern(s).
@@ -3573,17 +3729,29 @@
; muldi3 instruction pattern(s).
;
+(define_insn "*muldi3_sign"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (mult:DI (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "d,m"))
+ (match_operand:DI 1 "register_operand" "0,0")))]
+ "TARGET_64BIT"
+ "@
+ msgfr\\t%0,%2
+ msgf\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "imul")])
+
+
(define_insn "muldi3"
[(set (match_operand:DI 0 "register_operand" "=d,d,d")
- (mult:DI (match_operand:DI 1 "register_operand" "%0,0,0")
- (match_operand:DI 2 "general_operand" "d,K,m")))
- (clobber (reg:CC 33))]
+ (mult:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0")
+ (match_operand:DI 2 "general_operand" "d,K,m")))]
"TARGET_64BIT"
"@
msgr\\t%0,%2
mghi\\t%0,%h2
msg\\t%0,%2"
- [(set_attr "op_type" "RRE,RI,RX")
+ [(set_attr "op_type" "RRE,RI,RXE")
(set_attr "atype" "reg,reg,mem")
(set_attr "type" "imul")])
@@ -3593,9 +3761,8 @@
(define_insn "mulsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d,d")
- (mult:SI (match_operand:SI 1 "register_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,K,m")))
- (clobber (reg:CC 33))]
+ (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
+ (match_operand:SI 2 "general_operand" "d,K,m")))]
""
"@
msr\\t%0,%2
@@ -3611,7 +3778,7 @@
(define_expand "mulsidi3"
[(set (match_operand:DI 0 "register_operand" "")
- (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" ""))
(sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))))]
"!TARGET_64BIT"
"
@@ -3635,8 +3802,7 @@
(mult:DI (sign_extend:DI
(truncate:SI (match_operand:DI 1 "register_operand" "0,0")))
(sign_extend:DI
- (match_operand:SI 2 "nonimmediate_operand" "d,m"))))
- (clobber (reg:CC 33))]
+ (match_operand:SI 2 "nonimmediate_operand" "d,m"))))]
"!TARGET_64BIT"
"@
mr\\t%0,%2
@@ -3652,7 +3818,7 @@
(define_expand "muldf3"
[(parallel
[(set (match_operand:DF 0 "register_operand" "=f,f")
- (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
+ (mult:DF (match_operand:DF 1 "nonimmediate_operand" "%0,0")
(match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))])]
"TARGET_HARD_FLOAT"
@@ -3660,7 +3826,7 @@
(define_insn "*muldf3"
[(set (match_operand:DF 0 "register_operand" "=f,f")
- (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
+ (mult:DF (match_operand:DF 1 "nonimmediate_operand" "%0,0")
(match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
@@ -3673,7 +3839,7 @@
(define_insn "*muldf3_ibm"
[(set (match_operand:DF 0 "register_operand" "=f,f")
- (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
+ (mult:DF (match_operand:DF 1 "nonimmediate_operand" "%0,0")
(match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
@@ -3691,7 +3857,7 @@
(define_expand "mulsf3"
[(parallel
[(set (match_operand:SF 0 "register_operand" "=f,f")
- (mult:SF (match_operand:SF 1 "register_operand" "%0,0")
+ (mult:SF (match_operand:SF 1 "nonimmediate_operand" "%0,0")
(match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))])]
"TARGET_HARD_FLOAT"
@@ -3699,7 +3865,7 @@
(define_insn "*mulsf3"
[(set (match_operand:SF 0 "register_operand" "=f,f")
- (mult:SF (match_operand:SF 1 "register_operand" "%0,0")
+ (mult:SF (match_operand:SF 1 "nonimmediate_operand" "%0,0")
(match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
@@ -3712,7 +3878,7 @@
(define_insn "*mulsf3_ibm"
[(set (match_operand:SF 0 "register_operand" "=f,f")
- (mult:SF (match_operand:SF 1 "register_operand" "%0,0")
+ (mult:SF (match_operand:SF 1 "nonimmediate_operand" "%0,0")
(match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
@@ -4211,7 +4377,7 @@
(define_insn "*anddi3_cc"
[(set (reg 33)
- (compare (and:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=d,d")
@@ -4225,7 +4391,7 @@
(define_insn "*anddi3_cconly"
[(set (reg 33)
- (compare (and:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m"))
(const_int 0)))
(clobber (match_scratch:DI 0 "=d,d"))]
@@ -4238,7 +4404,7 @@
(define_insn "*anddi3_ni"
[(set (match_operand:DI 0 "register_operand" "=d")
- (and:DI (match_operand:DI 1 "register_operand" "%0")
+ (and:DI (match_operand:DI 1 "nonimmediate_operand" "0")
(match_operand:DI 2 "immediate_operand" "n")))
(clobber (reg:CC 33))]
"TARGET_64BIT && s390_single_hi (operands[2], DImode, -1) >= 0"
@@ -4261,7 +4427,7 @@
(define_insn "anddi3"
[(set (match_operand:DI 0 "register_operand" "=d,d")
- (and:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m")))
(clobber (reg:CC 33))]
"TARGET_64BIT"
@@ -4272,9 +4438,9 @@
(set_attr "atype" "reg,mem")])
(define_insn "*anddi3_ss"
- [(set (match_operand:DI 0 "s_operand" "=Qo")
+ [(set (match_operand:DI 0 "s_operand" "=Q")
(and:DI (match_dup 0)
- (match_operand:DI 1 "s_imm_operand" "Qo")))
+ (match_operand:DI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"nc\\t%O0(8,%R0),%1"
@@ -4282,8 +4448,8 @@
(set_attr "atype" "mem")])
(define_insn "*anddi3_ss_inv"
- [(set (match_operand:DI 0 "s_operand" "=Qo")
- (and:DI (match_operand:DI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:DI 0 "s_operand" "=Q")
+ (and:DI (match_operand:DI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4297,7 +4463,7 @@
(define_insn "*andsi3_cc"
[(set (reg 33)
- (compare (and:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "d,m"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=d,d")
@@ -4311,7 +4477,7 @@
(define_insn "*andsi3_cconly"
[(set (reg 33)
- (compare (and:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "d,m"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=d,d"))]
@@ -4324,7 +4490,7 @@
(define_insn "*andsi3_ni"
[(set (match_operand:SI 0 "register_operand" "=d")
- (and:SI (match_operand:SI 1 "register_operand" "%0")
+ (and:SI (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:SI 2 "immediate_operand" "n")))
(clobber (reg:CC 33))]
"TARGET_64BIT && s390_single_hi (operands[2], SImode, -1) >= 0"
@@ -4345,7 +4511,7 @@
(define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d")
- (and:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "d,m")))
(clobber (reg:CC 33))]
""
@@ -4356,9 +4522,9 @@
(set_attr "atype" "reg,mem")])
(define_insn "*andsi3_ss"
- [(set (match_operand:SI 0 "s_operand" "=Qo")
+ [(set (match_operand:SI 0 "s_operand" "=Q")
(and:SI (match_dup 0)
- (match_operand:SI 1 "s_imm_operand" "Qo")))
+ (match_operand:SI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"nc\\t%O0(4,%R0),%1"
@@ -4366,8 +4532,8 @@
(set_attr "atype" "mem")])
(define_insn "*andsi3_ss_inv"
- [(set (match_operand:SI 0 "s_operand" "=Qo")
- (and:SI (match_operand:SI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:SI 0 "s_operand" "=Q")
+ (and:SI (match_operand:SI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4402,9 +4568,9 @@
(set_attr "atype" "reg")])
(define_insn "*andhi3_ss"
- [(set (match_operand:HI 0 "s_operand" "=Qo")
+ [(set (match_operand:HI 0 "s_operand" "=Q")
(and:HI (match_dup 0)
- (match_operand:HI 1 "s_imm_operand" "Qo")))
+ (match_operand:HI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"nc\\t%O0(2,%R0),%1"
@@ -4412,8 +4578,8 @@
(set_attr "atype" "mem")])
(define_insn "*andhi3_ss_inv"
- [(set (match_operand:HI 0 "s_operand" "=Qo")
- (and:HI (match_operand:HI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:HI 0 "s_operand" "=Q")
+ (and:HI (match_operand:HI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4448,9 +4614,9 @@
(set_attr "atype" "reg")])
(define_insn "*andqi3_ss"
- [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+ [(set (match_operand:QI 0 "s_operand" "=Q,Q")
(and:QI (match_dup 0)
- (match_operand:QI 1 "s_imm_operand" "n,Qo")))
+ (match_operand:QI 1 "s_imm_operand" "n,Q")))
(clobber (reg:CC 33))]
""
"@
@@ -4460,8 +4626,8 @@
(set_attr "atype" "mem")])
(define_insn "*andqi3_ss_inv"
- [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
- (and:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
+ [(set (match_operand:QI 0 "s_operand" "=Q,Q")
+ (and:QI (match_operand:QI 1 "s_imm_operand" "n,Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4482,7 +4648,7 @@
(define_insn "*iordi3_cc"
[(set (reg 33)
- (compare (ior:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=d,d")
@@ -4496,7 +4662,7 @@
(define_insn "*iordi3_cconly"
[(set (reg 33)
- (compare (ior:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m"))
(const_int 0)))
(clobber (match_scratch:DI 0 "=d,d"))]
@@ -4509,7 +4675,7 @@
(define_insn "*iordi3_oi"
[(set (match_operand:DI 0 "register_operand" "=d")
- (ior:DI (match_operand:DI 1 "register_operand" "%0")
+ (ior:DI (match_operand:DI 1 "nonimmediate_operand" "0")
(match_operand:DI 2 "immediate_operand" "n")))
(clobber (reg:CC 33))]
"TARGET_64BIT && s390_single_hi (operands[2], DImode, 0) >= 0"
@@ -4532,7 +4698,7 @@
(define_insn "iordi3"
[(set (match_operand:DI 0 "register_operand" "=d,d")
- (ior:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m")))
(clobber (reg:CC 33))]
"TARGET_64BIT"
@@ -4543,9 +4709,9 @@
(set_attr "atype" "reg,mem")])
(define_insn "*iordi3_ss"
- [(set (match_operand:DI 0 "s_operand" "=Qo")
+ [(set (match_operand:DI 0 "s_operand" "=Q")
(ior:DI (match_dup 0)
- (match_operand:DI 1 "s_imm_operand" "Qo")))
+ (match_operand:DI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"oc\\t%O0(8,%R0),%1"
@@ -4553,8 +4719,8 @@
(set_attr "atype" "mem")])
(define_insn "*iordi3_ss_inv"
- [(set (match_operand:DI 0 "s_operand" "=Qo")
- (ior:DI (match_operand:DI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:DI 0 "s_operand" "=Q")
+ (ior:DI (match_operand:DI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4568,7 +4734,7 @@
(define_insn "*iorsi3_cc"
[(set (reg 33)
- (compare (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "d,m"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=d,d")
@@ -4582,7 +4748,7 @@
(define_insn "*iorsi3_cconly"
[(set (reg 33)
- (compare (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "d,m"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=d,d"))]
@@ -4595,7 +4761,7 @@
(define_insn "*iorsi3_oi"
[(set (match_operand:SI 0 "register_operand" "=d")
- (ior:SI (match_operand:SI 1 "register_operand" "%0")
+ (ior:SI (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:SI 2 "immediate_operand" "n")))
(clobber (reg:CC 33))]
"TARGET_64BIT && s390_single_hi (operands[2], SImode, 0) >= 0"
@@ -4616,7 +4782,7 @@
(define_insn "iorsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d")
- (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "d,m")))
(clobber (reg:CC 33))]
""
@@ -4627,9 +4793,9 @@
(set_attr "atype" "reg,mem")])
(define_insn "*iorsi3_ss"
- [(set (match_operand:SI 0 "s_operand" "=Qo")
+ [(set (match_operand:SI 0 "s_operand" "=Q")
(ior:SI (match_dup 0)
- (match_operand:SI 1 "s_imm_operand" "Qo")))
+ (match_operand:SI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"oc\\t%O0(4,%R0),%1"
@@ -4637,8 +4803,8 @@
(set_attr "atype" "mem")])
(define_insn "*iorsi3_ss_inv"
- [(set (match_operand:SI 0 "s_operand" "=Qo")
- (ior:SI (match_operand:SI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:SI 0 "s_operand" "=Q")
+ (ior:SI (match_operand:SI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4673,9 +4839,9 @@
(set_attr "atype" "reg")])
(define_insn "*iorhi3_ss"
- [(set (match_operand:HI 0 "s_operand" "=Qo")
+ [(set (match_operand:HI 0 "s_operand" "=Q")
(ior:HI (match_dup 0)
- (match_operand:HI 1 "s_imm_operand" "Qo")))
+ (match_operand:HI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"oc\\t%O0(2,%R0),%1"
@@ -4683,8 +4849,8 @@
(set_attr "atype" "mem")])
(define_insn "*iorhi3_ss_inv"
- [(set (match_operand:HI 0 "s_operand" "=Qo")
- (ior:HI (match_operand:HI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:HI 0 "s_operand" "=Q")
+ (ior:HI (match_operand:HI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4719,9 +4885,9 @@
(set_attr "atype" "reg")])
(define_insn "*iorqi3_ss"
- [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+ [(set (match_operand:QI 0 "s_operand" "=Q,Q")
(ior:QI (match_dup 0)
- (match_operand:QI 1 "s_imm_operand" "n,Qo")))
+ (match_operand:QI 1 "s_imm_operand" "n,Q")))
(clobber (reg:CC 33))]
""
"@
@@ -4731,8 +4897,8 @@
(set_attr "atype" "reg,mem")])
(define_insn "*iorqi3_ss_inv"
- [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
- (ior:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
+ [(set (match_operand:QI 0 "s_operand" "=Q,Q")
+ (ior:QI (match_operand:QI 1 "s_imm_operand" "n,Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4753,7 +4919,7 @@
(define_insn "*xordi3_cc"
[(set (reg 33)
- (compare (xor:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=d,d")
@@ -4767,7 +4933,7 @@
(define_insn "*xordi3_cconly"
[(set (reg 33)
- (compare (xor:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m"))
(const_int 0)))
(clobber (match_scratch:DI 0 "=d,d"))]
@@ -4780,7 +4946,7 @@
(define_insn "xordi3"
[(set (match_operand:DI 0 "register_operand" "=d,d")
- (xor:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m")))
(clobber (reg:CC 33))]
"TARGET_64BIT"
@@ -4791,9 +4957,9 @@
(set_attr "atype" "reg,mem")])
(define_insn "*xordi3_ss"
- [(set (match_operand:DI 0 "s_operand" "=Qo")
+ [(set (match_operand:DI 0 "s_operand" "=Q")
(xor:DI (match_dup 0)
- (match_operand:DI 1 "s_imm_operand" "Qo")))
+ (match_operand:DI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"xc\\t%O0(8,%R0),%1"
@@ -4801,8 +4967,8 @@
(set_attr "atype" "mem")])
(define_insn "*xordi3_ss_inv"
- [(set (match_operand:DI 0 "s_operand" "=Qo")
- (xor:DI (match_operand:DI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:DI 0 "s_operand" "=Q")
+ (xor:DI (match_operand:DI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4816,7 +4982,7 @@
(define_insn "*xorsi3_cc"
[(set (reg 33)
- (compare (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "d,m"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=d,d")
@@ -4830,7 +4996,7 @@
(define_insn "*xorsi3_cconly"
[(set (reg 33)
- (compare (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "d,m"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=d,d"))]
@@ -4843,7 +5009,7 @@
(define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d")
- (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
(match_operand:SI 2 "general_operand" "d,m")))
(clobber (reg:CC 33))]
""
@@ -4854,9 +5020,9 @@
(set_attr "atype" "reg,mem")])
(define_insn "*xorsi3_ss"
- [(set (match_operand:SI 0 "s_operand" "=Qo")
+ [(set (match_operand:SI 0 "s_operand" "=Q")
(xor:SI (match_dup 0)
- (match_operand:SI 1 "s_imm_operand" "Qo")))
+ (match_operand:SI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"xc\\t%O0(4,%R0),%1"
@@ -4864,8 +5030,8 @@
(set_attr "atype" "mem")])
(define_insn "*xorsi3_ss_inv"
- [(set (match_operand:SI 0 "s_operand" "=Qo")
- (xor:SI (match_operand:SI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:SI 0 "s_operand" "=Q")
+ (xor:SI (match_operand:SI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4888,9 +5054,9 @@
(set_attr "atype" "reg")])
(define_insn "*xorhi3_ss"
- [(set (match_operand:HI 0 "s_operand" "=Qo")
+ [(set (match_operand:HI 0 "s_operand" "=Q")
(xor:HI (match_dup 0)
- (match_operand:HI 1 "s_imm_operand" "Qo")))
+ (match_operand:HI 1 "s_imm_operand" "Q")))
(clobber (reg:CC 33))]
""
"xc\\t%O0(2,%R0),%1"
@@ -4898,8 +5064,8 @@
(set_attr "atype" "mem")])
(define_insn "*xorhi3_ss_inv"
- [(set (match_operand:HI 0 "s_operand" "=Qo")
- (xor:HI (match_operand:HI 1 "s_imm_operand" "Qo")
+ [(set (match_operand:HI 0 "s_operand" "=Q")
+ (xor:HI (match_operand:HI 1 "s_imm_operand" "Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -4922,9 +5088,9 @@
(set_attr "atype" "reg")])
(define_insn "*xorqi3_ss"
- [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+ [(set (match_operand:QI 0 "s_operand" "=Q,Q")
(xor:QI (match_dup 0)
- (match_operand:QI 1 "s_imm_operand" "n,Qo")))
+ (match_operand:QI 1 "s_imm_operand" "n,Q")))
(clobber (reg:CC 33))]
""
"@
@@ -4934,8 +5100,8 @@
(set_attr "atype" "mem")])
(define_insn "*xorqi3_ss_inv"
- [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
- (xor:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
+ [(set (match_operand:QI 0 "s_operand" "=Q,Q")
+ (xor:QI (match_operand:QI 1 "s_imm_operand" "n,Q")
(match_dup 0)))
(clobber (reg:CC 33))]
""
@@ -5682,9 +5848,6 @@
(const_int 4)
(ne (symbol_ref "TARGET_64BIT") (const_int 0))
(const_int 6)
- (ne (symbol_ref "s390_pool_overflow") (const_int 0))
- (if_then_else (eq (symbol_ref "flag_pic") (const_int 0))
- (const_int 12) (const_int 14))
(eq (symbol_ref "flag_pic") (const_int 0))
(const_int 6)] (const_int 8)))])
@@ -5734,9 +5897,6 @@
(const_int 4)
(ne (symbol_ref "TARGET_64BIT") (const_int 0))
(const_int 6)
- (ne (symbol_ref "s390_pool_overflow") (const_int 0))
- (if_then_else (eq (symbol_ref "flag_pic") (const_int 0))
- (const_int 12) (const_int 14))
(eq (symbol_ref "flag_pic") (const_int 0))
(const_int 6)] (const_int 8)))])
@@ -5759,54 +5919,217 @@
(const_string "RR") (const_string "RX")))
(set_attr "atype" "mem")])
+;;
+;;- Trap instructions.
+;;
+
+(define_insn "trap"
+ [(trap_if (const_int 1) (const_int 0))]
+ ""
+ "j\\t.+2"
+ [(set_attr "op_type" "RX")])
+
+(define_expand "conditional_trap"
+ [(set (match_dup 2) (match_dup 3))
+ (trap_if (match_operator 0 "comparison_operator"
+ [(match_dup 2) (const_int 0)])
+ (match_operand:SI 1 "general_operand" ""))]
+ ""
+ "
+{
+ enum machine_mode ccmode;
+
+ if (operands[1] != const0_rtx) FAIL;
+
+ ccmode = s390_select_ccmode (GET_CODE (operands[0]),
+ s390_compare_op0, s390_compare_op1);
+ operands[2] = gen_rtx_REG (ccmode, 33);
+ operands[3] = gen_rtx_COMPARE (ccmode, s390_compare_op0, s390_compare_op1);
+}")
+
+(define_insn "*trap"
+ [(trap_if (match_operator 0 "comparison_operator" [(reg 33) (const_int 0)])
+ (const_int 0))]
+ ""
+ "j%C0\\t.+2";
+ [(set_attr "op_type" "RX")])
;;
-;;- Subtract one and jump if not zero.
+;;- Loop instructions.
;;
+;; This is all complicated by the fact that since this is a jump insn
+;; we must handle our own output reloads.
+
+(define_expand "doloop_end"
+ [(use (match_operand 0 "" "")) ; loop pseudo
+ (use (match_operand 1 "" "")) ; iterations; zero if unknown
+ (use (match_operand 2 "" "")) ; max iterations
+ (use (match_operand 3 "" "")) ; loop level
+ (use (match_operand 4 "" ""))] ; label
+ ""
+ "
+{
+ if (GET_MODE (operands[0]) == SImode)
+ emit_jump_insn (gen_doloop_si (operands[4], operands[0], operands[0]));
+ else if (GET_MODE (operands[0]) == DImode && TARGET_64BIT)
+ emit_jump_insn (gen_doloop_di (operands[4], operands[0], operands[0]));
+ else
+ FAIL;
-;(define_expand "decrement_and_branch_on_count"
-; [(use (match_operand 0 "register_operand" ""))
-; (use (label_ref (match_operand 1 "" "")))]
-; ""
-; "
-;{
-;/* if (TARGET_64BIT)
-; emit_jump_insn (gen_brctdi (operands[0], operands[1]));
-; else */
-; emit_jump_insn (gen_brctsi (operands[0], operands[1]));
-; DONE;
-;}")
-;
-;(define_insn "brctsi"
-; [(set (pc)
-; (if_then_else
-; (ne (match_operand:SI 0 "register_operand" "+a")
-; (const_int 1))
-; (label_ref (match_operand 1 "" ""))
-; (pc)))
-; (set (match_dup 0)
-; (plus:SI (match_dup 0) (const_int -1)))]
-; ""
-; "brct\\t%0,%l1"
-; [(set_attr "op_type" "RI")
-; (set_attr "type" "branch")]
-;)
-;
-;(define_insn "ibrctsi"
-; [(set (pc)
-; (if_then_else
-; (eq (match_operand:SI 0 "register_operand" "+a")
-; (const_int 1))
-; (pc)
-; (label_ref (match_operand 1 "" ""))))
-; (set (match_dup 0)
-; (plus:SI (match_dup 0) (const_int -1)))]
-; ""
-; "brct\\t%0,%l1"
-; [(set_attr "op_type" "RI")
-; (set_attr "type" "branch")]
-;)
+ DONE;
+}")
+
+(define_insn "doloop_si"
+ [(set (pc)
+ (if_then_else
+ (ne (match_operand:SI 1 "register_operand" "d,d")
+ (const_int 1))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))
+ (set (match_operand:SI 2 "register_operand" "=1,?*m*d")
+ (plus:SI (match_dup 1) (const_int -1)))
+ (clobber (match_scratch:SI 3 "=X,&d"))
+ (clobber (reg:CC 33))]
+ ""
+ "*
+{
+ if (which_alternative != 0)
+ return \"#\";
+ else if (get_attr_length (insn) == 4)
+ return \"brct\\t%1,%l0\";
+ else
+ abort ();
+}"
+ [(set_attr "op_type" "RI")
+ (set (attr "length")
+ (cond [(lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4)
+ (ne (symbol_ref "TARGET_64BIT") (const_int 0))
+ (const_int 10)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 6)] (const_int 8)))])
+
+(define_insn "*doloop_si_long"
+ [(set (pc)
+ (if_then_else
+ (ne (match_operand:SI 1 "register_operand" "d,d")
+ (const_int 1))
+ (match_operand 0 "address_operand" "p,p")
+ (pc)))
+ (set (match_operand:SI 2 "register_operand" "=1,?*m*d")
+ (plus:SI (match_dup 1) (const_int -1)))
+ (clobber (match_scratch:SI 3 "=X,&d"))
+ (clobber (reg:CC 33))]
+ ""
+ "*
+{
+ if (get_attr_op_type (insn) == OP_TYPE_RR)
+ return \"bctr\\t%1,%0\";
+ else
+ return \"bct\\t%1,%a0\";
+}"
+ [(set (attr "op_type")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "RR") (const_string "RX")))
+ (set_attr "atype" "mem")])
+
+(define_split
+ [(set (pc)
+ (if_then_else (ne (match_operand:SI 1 "register_operand" "")
+ (const_int 1))
+ (match_operand 0 "" "")
+ (pc)))
+ (set (match_operand:SI 2 "nonimmediate_operand" "")
+ (plus:SI (match_dup 1) (const_int -1)))
+ (clobber (match_scratch:SI 3 ""))
+ (clobber (reg:CC 33))]
+ "reload_completed
+ && (! REG_P (operands[2])
+ || ! rtx_equal_p (operands[1], operands[2]))"
+ [(set (match_dup 3) (match_dup 1))
+ (parallel [(set (reg:CCAN 33)
+ (compare:CCAN (plus:SI (match_dup 3) (const_int -1))
+ (const_int 0)))
+ (set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))])
+ (set (match_dup 2) (match_dup 3))
+ (set (pc) (if_then_else (ne (reg:CCAN 33) (const_int 0))
+ (match_dup 0)
+ (pc)))]
+ "")
+
+(define_insn "doloop_di"
+ [(set (pc)
+ (if_then_else
+ (ne (match_operand:DI 1 "register_operand" "d,d")
+ (const_int 1))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))
+ (set (match_operand:DI 2 "register_operand" "=1,?*m*r")
+ (plus:DI (match_dup 1) (const_int -1)))
+ (clobber (match_scratch:DI 3 "=X,&d"))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "*
+{
+ if (which_alternative != 0)
+ return \"#\";
+ else if (get_attr_length (insn) == 4)
+ return \"brctg\\t%1,%l0\";
+ else
+ abort ();
+}"
+ [(set_attr "op_type" "RI")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 12)))])
+
+(define_insn "*doloop_di_long"
+ [(set (pc)
+ (if_then_else
+ (ne (match_operand:DI 1 "register_operand" "d,d")
+ (const_int 1))
+ (match_operand 0 "address_operand" "p,p")
+ (pc)))
+ (set (match_operand:DI 2 "register_operand" "=1,?*m*d")
+ (plus:DI (match_dup 1) (const_int -1)))
+ (clobber (match_scratch:DI 3 "=X,&d"))
+ (clobber (reg:CC 33))]
+ ""
+ "*
+{
+ if (get_attr_op_type (insn) == OP_TYPE_RRE)
+ return \"bctgr\\t%1,%0\";
+ else
+ return \"bctg\\t%1,%a0\";
+}"
+ [(set (attr "op_type")
+ (if_then_else (match_operand 0 "register_operand" "")
+ (const_string "RRE") (const_string "RXE")))
+ (set_attr "atype" "mem")])
+(define_split
+ [(set (pc)
+ (if_then_else (ne (match_operand:DI 1 "register_operand" "")
+ (const_int 1))
+ (match_operand 0 "" "")
+ (pc)))
+ (set (match_operand:DI 2 "nonimmediate_operand" "")
+ (plus:DI (match_dup 1) (const_int -1)))
+ (clobber (match_scratch:DI 3 ""))
+ (clobber (reg:CC 33))]
+ "reload_completed
+ && (! REG_P (operands[2])
+ || ! rtx_equal_p (operands[1], operands[2]))"
+ [(set (match_dup 3) (match_dup 1))
+ (parallel [(set (reg:CCAN 33)
+ (compare:CCAN (plus:DI (match_dup 3) (const_int -1))
+ (const_int 0)))
+ (set (match_dup 3) (plus:DI (match_dup 3) (const_int -1)))])
+ (set (match_dup 2) (match_dup 3))
+ (set (pc) (if_then_else (ne (reg:CCAN 33) (const_int 0))
+ (match_dup 0)
+ (pc)))]
+ "")
;;
;;- Unconditional jump instructions.
@@ -5961,7 +6284,8 @@
[(unspec_volatile [(const_int 0)] 0)]
""
""
- [(set_attr "type" "none")])
+ [(set_attr "type" "none")
+ (set_attr "length" "0")])
@@ -6014,10 +6338,7 @@
compiler doesn't know about it, because the PLT glue
code uses it. In 64-bit, this is not necessary. */
if (plt_call && !TARGET_64BIT)
- {
- current_function_uses_pic_offset_table = 1;
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
- }
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
DONE;
}")
@@ -6139,10 +6460,7 @@
compiler doesn't know about it, because the PLT glue
code uses it. In 64-bit, this is not necessary. */
if (plt_call && !TARGET_64BIT)
- {
- current_function_uses_pic_offset_table = 1;
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
- }
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
DONE;
}")
@@ -6218,6 +6536,192 @@
(set_attr "type" "jsr")
(set_attr "atype" "mem")])
+;;
+;;- Thread-local storage support.
+;;
+
+(define_insn "get_tp_64"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=??d,Q")
+ (unspec:DI [(const_int 0)] UNSPEC_TP))]
+ "TARGET_64BIT"
+ "@
+ ear\\t%0,%%a0\;sllg\\t%0,%0,32\;ear\\t%0,%%a1
+ stam\\t%%a0,%%a1,%0"
+ [(set_attr "op_type" "NN,RS")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "o3,*")
+ (set_attr "length" "14,*")])
+
+(define_insn "get_tp_31"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,Q")
+ (unspec:SI [(const_int 0)] UNSPEC_TP))]
+ "!TARGET_64BIT"
+ "@
+ ear\\t%0,%%a0
+ stam\\t%%a0,%%a0,%0"
+ [(set_attr "op_type" "RRE,RS")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "set_tp_64"
+ [(unspec_volatile [(match_operand:DI 0 "general_operand" "??d,Q")] UNSPECV_SET_TP)
+ (clobber (match_scratch:SI 1 "=d,X"))]
+ "TARGET_64BIT"
+ "@
+ sar\\t%%a1,%0\;srlg\\t%1,%0,32\;sar\\t%%a0,%1
+ lam\\t%%a0,%%a1,%0"
+ [(set_attr "op_type" "NN,RS")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "o3,*")
+ (set_attr "length" "14,*")])
+
+(define_insn "set_tp_31"
+ [(unspec_volatile [(match_operand:SI 0 "general_operand" "d,Q")] UNSPECV_SET_TP)]
+ "!TARGET_64BIT"
+ "@
+ sar\\t%%a0,%0
+ lam\\t%%a0,%%a0,%0"
+ [(set_attr "op_type" "RRE,RS")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*tls_load_64"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
+ (match_operand:DI 2 "" "")]
+ UNSPEC_TLS_LOAD))]
+ "TARGET_64BIT"
+ "lg\\t%0,%1%J2"
+ [(set_attr "op_type" "RXE")
+ (set_attr "atype" "mem")])
+
+(define_insn "*tls_load_31"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
+ (match_operand:SI 2 "" "")]
+ UNSPEC_TLS_LOAD))]
+ "!TARGET_64BIT"
+ "l\\t%0,%1%J2"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")])
+
+(define_expand "call_value_tls"
+ [(set (match_operand 0 "" "")
+ (call (const_int 0) (const_int 0)))
+ (use (match_operand 1 "" ""))]
+ ""
+ "
+{
+ rtx insn, sym;
+
+ if (!flag_pic)
+ abort ();
+
+ sym = s390_tls_get_offset ();
+ sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), 113);
+ sym = gen_rtx_CONST (Pmode, sym);
+
+ /* Unless we can use the bras(l) insn, force the
+ routine address into a register. */
+ if (!TARGET_SMALL_EXEC && !TARGET_64BIT)
+ {
+ rtx target = gen_reg_rtx (Pmode);
+ emit_move_insn (target, sym);
+ sym = target;
+ }
+
+ sym = gen_rtx_MEM (QImode, sym);
+
+ /* Emit insn. */
+ insn = emit_call_insn (
+ gen_call_value_tls_exp (operands[0], sym, const0_rtx,
+ gen_rtx_REG (Pmode, RETURN_REGNUM),
+ operands[1]));
+
+ /* The calling convention of __tls_get_offset uses the
+ GOT register implicitly. */
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), operands[0]);
+ CONST_OR_PURE_CALL_P (insn) = 1;
+
+ DONE;
+}")
+
+(define_expand "call_value_tls_exp"
+ [(parallel [(set (match_operand 0 "" "")
+ (call (match_operand 1 "" "")
+ (match_operand 2 "" "")))
+ (clobber (match_operand 3 "" ""))
+ (use (match_operand 4 "" ""))])]
+ ""
+ "")
+
+(define_insn "brasl_tls"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:QI (match_operand:DI 1 "bras_sym_operand" "X"))
+ (match_operand:SI 2 "const_int_operand" "n")))
+ (clobber (match_operand:DI 3 "register_operand" "=r"))
+ (use (match_operand:DI 4 "" ""))]
+ "TARGET_64BIT"
+ "brasl\\t%3,%1%J4"
+ [(set_attr "op_type" "RIL")
+ (set_attr "type" "jsr")])
+
+(define_insn "bras_tls"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:QI (match_operand:SI 1 "bras_sym_operand" "X"))
+ (match_operand:SI 2 "const_int_operand" "n")))
+ (clobber (match_operand:SI 3 "register_operand" "=r"))
+ (use (match_operand:SI 4 "" ""))]
+ "TARGET_SMALL_EXEC"
+ "bras\\t%3,%1%J4"
+ [(set_attr "op_type" "RI")
+ (set_attr "type" "jsr")])
+
+(define_insn "basr_tls_64"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:QI (match_operand:DI 1 "register_operand" "a"))
+ (match_operand:SI 2 "const_int_operand" "n")))
+ (clobber (match_operand:DI 3 "register_operand" "=r"))
+ (use (match_operand:DI 4 "" ""))]
+ "TARGET_64BIT"
+ "basr\\t%3,%1%J4"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "jsr")])
+
+(define_insn "basr_tls_31"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:QI (match_operand:SI 1 "register_operand" "a"))
+ (match_operand:SI 2 "const_int_operand" "n")))
+ (clobber (match_operand:SI 3 "register_operand" "=r"))
+ (use (match_operand:SI 4 "" ""))]
+ "!TARGET_64BIT"
+ "basr\\t%3,%1%J4"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "jsr")
+ (set_attr "atype" "mem")])
+
+(define_insn "bas_tls_64"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:QI (match_operand:QI 1 "address_operand" "p"))
+ (match_operand:SI 2 "const_int_operand" "n")))
+ (clobber (match_operand:DI 3 "register_operand" "=r"))
+ (use (match_operand:DI 4 "" ""))]
+ "TARGET_64BIT"
+ "bas\\t%3,%a1%J4"
+ [(set_attr "op_type" "RX")
+ (set_attr "type" "jsr")
+ (set_attr "atype" "mem")])
+
+(define_insn "bas_tls_31"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:QI (match_operand:QI 1 "address_operand" "p"))
+ (match_operand:SI 2 "const_int_operand" "n")))
+ (clobber (match_operand:SI 3 "register_operand" "=r"))
+ (use (match_operand:SI 4 "" ""))]
+ "!TARGET_64BIT"
+ "bas\\t%3,%a1%J4"
+ [(set_attr "op_type" "RX")
+ (set_attr "type" "jsr")
+ (set_attr "atype" "mem")])
;;
;;- Miscellaneous instructions.
@@ -6505,7 +7009,7 @@
[(set_attr "op_type" "NN")
(set_attr "length" "0")])
-(define_insn "reload_base"
+(define_insn "reload_base_31"
[(set (match_operand:SI 0 "register_operand" "=a")
(unspec:SI [(label_ref (match_operand 1 "" ""))] 210))]
"!TARGET_64BIT"
@@ -6514,15 +7018,29 @@
(set_attr "type" "la")
(set_attr "length" "6")])
-(define_insn "reload_base2"
+(define_insn "reload_base_64"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(label_ref (match_operand 1 "" ""))] 210))]
+ "TARGET_64BIT"
+ "larl\\t%0,%1"
+ [(set_attr "op_type" "RIL")
+ (set_attr "type" "la")])
+
+(define_insn "reload_anchor"
[(set (match_operand:SI 0 "register_operand" "=a")
- (unspec:SI [(label_ref (match_operand 1 "" ""))] 211))]
+ (unspec:SI [(match_operand:SI 1 "register_operand" "a")] 211))]
"!TARGET_64BIT"
- "la\\t%0,%1-.(%0)"
+ "l\\t%0,0(%1)\;la\\t%0,0(%0,%1)"
[(set_attr "op_type" "NN")
(set_attr "type" "la")
- (set_attr "length" "4")])
+ (set_attr "length" "8")])
+(define_insn "pool"
+ [(unspec_volatile [(match_operand 0 "const_int_operand" "n")] 220)]
+ ""
+ "* abort ();"
+ [(set_attr "op_type" "NN")
+ (set (attr "length") (symbol_ref "INTVAL (operands[0])"))])
;;
;; Insns related to generating the function prologue and epilogue.
@@ -6566,162 +7084,44 @@
(set_attr "type" "jsr")
(set_attr "atype" "mem")])
-
-(define_insn "lit"
- [(set (reg 13) (pc))
- (unspec_volatile [(const_int 0)] 200)]
+(define_insn "literal_pool_31"
+ [(unspec_volatile [(const_int 0)] 300)
+ (set (match_operand:SI 0 "register_operand" "=a")
+ (label_ref (match_operand 1 "" "")))
+ (use (label_ref (match_operand 2 "" "")))]
""
- "*
{
- s390_output_constant_pool (asm_out_file);
- return \"\";
-}"
- [(set_attr "op_type" "NN")
- (set_attr "type" "integer")])
-
-
-;;
-;; Peephole optimization patterns.
-;;
-
-(define_peephole
- [(set (match_operand:SI 0 "memory_operand" "m")
- (match_operand:SI 1 "register_operand" "d"))
- (set (match_dup 1)
- (match_dup 0))]
- ""
- "st\\t%1,%0")
-
-(define_peephole
- [(set (match_operand:SI 0 "memory_operand" "m")
- (match_operand:SI 1 "register_operand" "d"))
- (set (match_dup 0)
- (match_dup 1))]
- ""
- "st\\t%1,%0")
-
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "register_operand" ""))
- (parallel
- [(set (match_dup 0)
- (plus:SI (match_dup 0)
- (match_operand:SI 2 "immediate_operand" "")))
- (clobber (reg:CC 33))])]
- "(REGNO (operands[0]) == STACK_POINTER_REGNUM ||
- REGNO (operands[1]) == STACK_POINTER_REGNUM ||
- REGNO (operands[0]) == BASE_REGISTER ||
- REGNO (operands[1]) == BASE_REGISTER) &&
- INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 4096"
- "la\\t%0,%c2(%1)")
-
-;
-; peepholes for fast char instructions
-;
-
-;(define_peephole
-; [(set (match_operand:QI 0 "register_operand" "d")
-; (match_operand:QI 1 "s_operand" "Q"))
-; (set (match_operand:SI 2 "register_operand" "0")
-; (zero_extend:SI (match_dup 0)))]
-; "REGNO(operands[0]) == REGNO(operands[2])"
-; "icm\\t%0,8,%1\;srl\\t%0,24")
-
-;(define_peephole
-; [(set (match_operand:QI 0 "register_operand" "d")
-; (match_operand:QI 1 "s_operand" "Q"))
-; (set (match_operand:SI 2 "register_operand" "0")
-; (sign_extend:SI (match_dup 0)))]
-; "REGNO(operands[0]) == REGNO(operands[2])"
-; "icm\\t%0,8,%1\;sra\\t%0,24")
-
-(define_peephole
- [(set (match_operand:QI 0 "register_operand" "d")
- (match_operand:QI 1 "immediate_operand" "J"))
- (set (match_operand:SI 2 "register_operand" "0" )
- (sign_extend:SI (match_dup 0) ) )]
- "REGNO(operands[0]) == REGNO(operands[2])"
- "lhi\\t%0,%h1")
-
-;
-; peepholes for fast short instructions
-;
-
-;(define_peephole
-; [(set (match_operand:HI 0 "register_operand" "d")
-; (match_operand:HI 1 "s_operand" "Q"))
-; (set (match_operand:SI 2 "register_operand" "0" )
-; (zero_extend:SI (match_dup 0)))]
-; "REGNO(operands[0]) == REGNO(operands[2])"
-; "icm\\t%0,12,%1\;srl\\t%0,16")
-
-(define_peephole
- [(set (match_operand:HI 0 "register_operand" "d")
- (match_operand:HI 1 "memory_operand" "m"))
- (set (match_operand:SI 2 "register_operand" "0" )
- (sign_extend:SI (match_dup 0)))]
- "REGNO(operands[0]) == REGNO(operands[2])"
- "lh\\t%0,%1")
-
-(define_peephole
- [(set (match_operand:HI 0 "register_operand" "d")
- (match_operand:HI 1 "immediate_operand" "K"))
- (set (match_operand:SI 2 "register_operand" "0" )
- (sign_extend:SI (match_dup 0) ) )]
- "REGNO(operands[0]) == REGNO(operands[2])"
- "lhi\\t%0,%h1")
-
-;
-; peepholes for divide instructions
-;
-
-(define_peephole
- [(set (match_operand:DI 0 "register_operand" "d")
- (match_operand:DI 1 "memory_operand" "m"))
- (set (match_dup 0)
- (lshiftrt:DI (match_dup 0)
- (match_operand:SI 2 "immediate_operand" "J")))
- (set (match_dup 0)
- (div:SI (match_dup 0)
- (match_operand:SI 3 "nonimmediate_operand" "g")))
- (set (match_dup 1)
- (match_dup 0))]
- ""
- "*
-{
- output_asm_insn (\"l\\t%0,%1\", operands);
- output_asm_insn (\"srdl\\t%0,%b2\", operands);
-
- if (REG_P (operands[3]))
- output_asm_insn (\"dr\\t%0,%3\", operands);
- else
- output_asm_insn (\"d\\t%0,%3\", operands);
+ if (s390_nr_constants)
+ {
+ output_asm_insn ("bras\\t%0,%2", operands);
+ s390_output_constant_pool (operands[1], operands[2]);
+ }
+ else if (flag_pic)
+ {
+ /* We need the anchor label in any case. */
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (operands[1]));
+ }
- return \"st\\t%N0,%N1\";
-}")
+ return "";
+}
+ [(set_attr "op_type" "NN")
+ (set_attr "type" "la")])
-(define_peephole
- [(set (match_operand:DI 0 "register_operand" "d")
- (match_operand:DI 1 "memory_operand" "m"))
- (set (match_dup 0)
- (lshiftrt:DI (match_dup 0)
- (match_operand:SI 2 "immediate_operand" "J")))
- (set (match_dup 0)
- (mod:SI (match_dup 0)
- (match_operand:SI 3 "nonimmediate_operand" "g")))
- (set (match_dup 1)
- (match_dup 0))]
+(define_insn "literal_pool_64"
+ [(unspec_volatile [(const_int 0)] 300)
+ (set (match_operand:DI 0 "register_operand" "=a")
+ (label_ref (match_operand 1 "" "")))
+ (use (label_ref (match_operand 2 "" "")))]
""
- "*
{
- output_asm_insn (\"l\\t%0,%1\", operands);
- output_asm_insn (\"srdl\\t%0,%b2\", operands);
-
- if (REG_P (operands[3]))
- output_asm_insn (\"dr\\t%0,%3\", operands);
- else
- output_asm_insn (\"d\\t%0,%3\", operands);
-
- return \"st\\t%0,%1\";
-}")
+ if (s390_nr_constants)
+ {
+ output_asm_insn ("larl\\t%0,%1", operands);
+ s390_output_constant_pool (operands[1], operands[2]);
+ }
+ return "";
+}
+ [(set_attr "op_type" "NN")
+ (set_attr "type" "la")])
diff --git a/contrib/gcc/config/s390/t-crtstuff b/contrib/gcc/config/s390/t-crtstuff
new file mode 100644
index 0000000..5572e6b
--- /dev/null
+++ b/contrib/gcc/config/s390/t-crtstuff
@@ -0,0 +1,4 @@
+# crtend*.o cannot be compiled without -fno-asynchronous-unwind-tables,
+# because then __FRAME_END__ might not be the last thing in .eh_frame
+# section.
+CRTSTUFF_T_CFLAGS = -fno-asynchronous-unwind-tables
diff --git a/contrib/gcc/config/s390/t-linux64 b/contrib/gcc/config/s390/t-linux64
index d5a9278..db839c6 100644
--- a/contrib/gcc/config/s390/t-linux64
+++ b/contrib/gcc/config/s390/t-linux64
@@ -1,3 +1,12 @@
+MULTILIB_OPTIONS = m64/m31
+MULTILIB_DIRNAMES = 64 32
+MULTILIB_OSDIRNAMES = ../lib64 ../lib
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
+
# Override t-slibgcc-elf-ver to export some libgcc symbols with
# the symbol versions that glibc used.
SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver $(srcdir)/config/s390/libgcc-glibc.ver
diff --git a/contrib/gcc/config/sol2.h b/contrib/gcc/config/sol2.h
new file mode 100644
index 0000000..c5980fb
--- /dev/null
+++ b/contrib/gcc/config/sol2.h
@@ -0,0 +1,207 @@
+/* Operating system specific defines to be used when targeting GCC for any
+ Solaris 2 system.
+ Copyright 2002 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* We use stabs-in-elf for debugging, because that is what the native
+ toolchain uses. */
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
+/* Solaris 2 (at least as of 2.5.1) uses a 32-bit wchar_t. */
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "long int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE BITS_PER_WORD
+
+/* Solaris 2 uses a wint_t different from the default. This is required
+ by the SCD 2.4.1, p. 6-83, Figure 6-66. */
+#undef WINT_TYPE
+#define WINT_TYPE "long int"
+
+#undef WINT_TYPE_SIZE
+#define WINT_TYPE_SIZE BITS_PER_WORD
+
+#define HANDLE_PRAGMA_REDEFINE_EXTNAME 1
+
+/* ??? Note: in order for -compat-bsd to work fully,
+ we must somehow arrange to fixincludes /usr/ucbinclude
+ and put the result in $(libsubdir)/ucbinclude. */
+
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC "\
+%{pthreads:-D_REENTRANT -D_PTHREADS} \
+%{!pthreads:%{threads:-D_REENTRANT -D_SOLARIS_THREADS}} \
+%{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude} \
+"
+
+/* Names to predefine in the preprocessor for this target machine. */
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("sun"); \
+ builtin_define ("__svr4__"); \
+ builtin_define ("__SVR4"); \
+ builtin_define ("__PRAGMA_REDEFINE_EXTNAME"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=svr4"); \
+ /* For C++ we need to add some additional macro \
+ definitions required by the C++ standard \
+ library. */ \
+ if (c_language == clk_cplusplus) \
+ { \
+ builtin_define ("_XOPEN_SOURCE=500"); \
+ builtin_define ("_LARGEFILE_SOURCE=1"); \
+ builtin_define ("_LARGEFILE64_SOURCE=1"); \
+ builtin_define ("__EXTENSIONS__"); \
+ } \
+ } while (0)
+
+/* The sun bundled assembler doesn't accept -Yd, (and neither does gas).
+ It's safe to pass -s always, even if -g is not used. */
+#undef ASM_SPEC
+#define ASM_SPEC "\
+%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s \
+%{fpic:-K PIC} %{fPIC:-K PIC} \
+%(asm_cpu) \
+"
+
+/* We don't use the standard LIB_SPEC only because we don't yet support c++. */
+#undef LIB_SPEC
+#define LIB_SPEC \
+ "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} \
+ %{!shared:\
+ %{!symbolic:\
+ %{pthreads:-lpthread} \
+ %{!pthreads:%{threads:-lthread}} \
+ %{p|pg:-ldl} -lc}}"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
+
+/* We don't use the standard svr4 STARTFILE_SPEC because it's wrong for us. */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{!shared: \
+ %{!symbolic: \
+ %{p:mcrt1.o%s} \
+ %{!p: \
+ %{pg:gcrt1.o%s gmon.o%s} \
+ %{!pg:crt1.o%s}}}} \
+ crti.o%s %(startfile_arch) \
+ crtbegin.o%s"
+
+#undef STARTFILE_ARCH32_SPEC
+#define STARTFILE_ARCH32_SPEC "%{ansi:values-Xc.o%s} \
+ %{!ansi:values-Xa.o%s}"
+
+#undef STARTFILE_ARCH_SPEC
+#define STARTFILE_ARCH_SPEC STARTFILE_ARCH32_SPEC
+
+#undef LINK_ARCH32_SPEC
+#define LINK_ARCH32_SPEC \
+ "%{G:-G} \
+ %{YP,*} \
+ %{R*} \
+ %{compat-bsd: \
+ %{!YP,*:%{p|pg:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{!p:%{!pg:-Y P,/usr/ucblib:/usr/ccs/lib:/usr/lib}}} \
+ -R /usr/ucblib} \
+ %{!compat-bsd: \
+ %{!YP,*:%{p|pg:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{!p:%{!pg:-Y P,/usr/ccs/lib:/usr/lib}}}}"
+
+#undef LINK_ARCH_SPEC
+#define LINK_ARCH_SPEC LINK_ARCH32_SPEC
+
+/* This should be the same as in svr4.h, except with -R added. */
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%{h*} %{v:-V} \
+ %{b} %{Wl,*:%*} \
+ %{static:-dn -Bstatic} \
+ %{shared:-G -dy %{!mimpure-text:-z text}} \
+ %{symbolic:-Bsymbolic -G -dy -z text} \
+ %(link_arch) \
+ %{Qy:} %{!Qn:-Qy}"
+
+/* This defines which switch letters take arguments.
+ It is as in svr4.h but with -R added. */
+#undef SWITCH_TAKES_ARG
+#define SWITCH_TAKES_ARG(CHAR) \
+ (DEFAULT_SWITCH_TAKES_ARG(CHAR) \
+ || (CHAR) == 'R' \
+ || (CHAR) == 'h' \
+ || (CHAR) == 'z')
+
+#define STDC_0_IN_SYSTEM_HEADERS 1
+
+/*
+ * Attempt to turn on access permissions for the stack.
+ *
+ * This code must be defined when compiling gcc but not when compiling
+ * libgcc2.a, unless we're generating code for 64-bit SPARC
+ *
+ * _SC_STACK_PROT is only defined for post 2.6, but we want this code
+ * to run always. 2.6 can change the stack protection but has no way to
+ * query it.
+ *
+ */
+
+/* This declares mprotect (used in TRANSFER_FROM_TRAMPOLINE) for
+ libgcc2.c. */
+/* We don't want to include this because sys/mman.h is not present on
+ some non-Solaris configurations that use sol2.h. */
+#if 0 /* def L_trampoline */
+#include <sys/mman.h>
+#endif
+
+#define TRANSFER_FROM_TRAMPOLINE \
+ \
+/* #define STACK_PROT_RWX (PROT_READ | PROT_WRITE | PROT_EXEC) */ \
+ \
+static int need_enable_exec_stack; \
+ \
+static void check_enabling(void) __attribute__ ((constructor)); \
+static void check_enabling(void) \
+{ \
+ extern long sysconf(int); \
+ \
+ int prot = (int) sysconf(515 /* _SC_STACK_PROT */); \
+ if (prot != 7 /* STACK_PROT_RWX */) \
+ need_enable_exec_stack = 1; \
+} \
+ \
+extern void __enable_execute_stack (void *); \
+void \
+__enable_execute_stack (addr) \
+ void *addr; \
+{ \
+ if (!need_enable_exec_stack) \
+ return; \
+ else { \
+ long size = getpagesize (); \
+ long mask = ~(size-1); \
+ char *page = (char *) (((long) addr) & mask); \
+ char *end = (char *) ((((long) (addr + TRAMPOLINE_SIZE)) & mask) + size); \
+ \
+ if (mprotect (page, end - page, 7 /* STACK_PROT_RWX */) < 0) \
+ perror ("mprotect of trampoline code"); \
+ } \
+}
diff --git a/contrib/gcc/config/sparc/aout.h b/contrib/gcc/config/sparc/aout.h
index 3a2273f..7532281 100644
--- a/contrib/gcc/config/sparc/aout.h
+++ b/contrib/gcc/config/sparc/aout.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for SPARC using a.out.
- Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1996, 2002 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com).
This file is part of GNU CC.
@@ -37,36 +37,8 @@ Boston, MA 02111-1307, USA. */
(DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \
|| !strcmp (STR, "target") || !strcmp (STR, "assert"))
-/* This is defined differently for v9 in a cover file. */
-#define SELECT_SECTION(T,RELOC,ALIGN) \
-{ \
- if (TREE_CODE (T) == VAR_DECL) \
- { \
- if (TREE_READONLY (T) && ! TREE_SIDE_EFFECTS (T) \
- && DECL_INITIAL (T) \
- && (DECL_INITIAL (T) == error_mark_node \
- || TREE_CONSTANT (DECL_INITIAL (T))) \
- && DECL_ALIGN (T) <= MAX_TEXT_ALIGN \
- && ! (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES))) \
- text_section (); \
- else \
- data_section (); \
- } \
- else if (TREE_CODE (T) == CONSTRUCTOR) \
- { \
- if (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES)) \
- data_section (); \
- } \
- else if (TREE_CODE_CLASS (TREE_CODE (T)) == 'c') \
- { \
- if ((TREE_CODE (T) == STRING_CST && flag_writable_strings) \
- || TYPE_ALIGN (TREE_TYPE (T)) > MAX_TEXT_ALIGN \
- || (flag_pic && ((RELOC) || SUNOS4_SHARED_LIBRARIES))) \
- data_section (); \
- else \
- text_section (); \
- } \
-}
+#define TARGET_ASM_SELECT_SECTION sparc_aout_select_section
+#define TARGET_ASM_SELECT_RTX_SECTION sparc_aout_select_rtx_section
/* Output the label for a function definition. */
diff --git a/contrib/gcc/config/sparc/cypress.md b/contrib/gcc/config/sparc/cypress.md
new file mode 100644
index 0000000..e9bff6d
--- /dev/null
+++ b/contrib/gcc/config/sparc/cypress.md
@@ -0,0 +1,51 @@
+;; Scheduling description for SPARC Cypress.
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU CC.
+;;
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; The Cypress is a pretty simple single-issue processor.
+
+(define_automaton "cypress_0,cypress_1")
+
+(define_cpu_unit "cyp_memory, cyp_fpalu" "cypress_0")
+(define_cpu_unit "cyp_fpmds" "cypress_1")
+
+(define_insn_reservation "cyp_load" 2
+ (and (eq_attr "cpu" "cypress")
+ (eq_attr "type" "load,sload,fpload"))
+ "cyp_memory, nothing")
+
+(define_insn_reservation "cyp_fp_alu" 5
+ (and (eq_attr "cpu" "cypress")
+ (eq_attr "type" "fp,fpmove"))
+ "cyp_fpalu, nothing*3")
+
+(define_insn_reservation "cyp_fp_mult" 7
+ (and (eq_attr "cpu" "cypress")
+ (eq_attr "type" "fpmul"))
+ "cyp_fpmds, nothing*5")
+
+(define_insn_reservation "cyp_fp_div" 37
+ (and (eq_attr "cpu" "cypress")
+ (eq_attr "type" "fpdivs,fpdivd"))
+ "cyp_fpmds, nothing*35")
+
+(define_insn_reservation "cyp_fp_sqrt" 63
+ (and (eq_attr "cpu" "cypress")
+ (eq_attr "type" "fpsqrts,fpsqrtd"))
+ "cyp_fpmds, nothing*61")
diff --git a/contrib/gcc/config/sparc/freebsd.h b/contrib/gcc/config/sparc/freebsd.h
index 59f0777..b2809dd 100644
--- a/contrib/gcc/config/sparc/freebsd.h
+++ b/contrib/gcc/config/sparc/freebsd.h
@@ -1,4 +1,4 @@
-/* Definitions for Sun Sparc64 running FreeBSD using the ELF format
+/* Definitions for Sun SPARC64 running FreeBSD using the ELF format
Copyright (C) 2001, 2002 Free Software Foundation, Inc.
Contributed by David E. O'Brien <obrien@FreeBSD.org> and BSDi.
@@ -22,11 +22,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
Emacs needs to know if the arch is 64 or 32-bits. */
#undef CPP_CPU64_DEFAULT_SPEC
-#define CPP_CPU64_DEFAULT_SPEC "-D__sparc64__ -D__sparc_v9__ -D__arch64__"
+#define CPP_CPU64_DEFAULT_SPEC \
+ "-D__sparc64__ -D__sparc_v9__ -D__sparcv9 -D__sparc__ -D__arch64__"
/* Because we include sparc/sysv4.h. */
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES FBSD_CPP_PREDEFINES
+/* Do not define it here, we now use TARGET_OS_CPP_BUILTINS. */
#define LINK_SPEC "%(link_arch) \
%{!mno-relax:%{!r:-relax}} \
@@ -52,14 +53,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
We use the GCC defaults instead. */
#undef WCHAR_TYPE
-#undef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
-
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
-/* Define for support of TFmode long double and REAL_ARITHMETIC.
- Sparc ABI says that long double is 4 words. */
+/* Define for support of TFmode long double.
+ SPARC ABI says that long double is 4 words. */
#undef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
diff --git a/contrib/gcc/config/sparc/gmon-sol2.c b/contrib/gcc/config/sparc/gmon-sol2.c
index bcb0c06..c577666 100644
--- a/contrib/gcc/config/sparc/gmon-sol2.c
+++ b/contrib/gcc/config/sparc/gmon-sol2.c
@@ -28,7 +28,7 @@
* SUCH DAMAGE.
*/
-/* Mangled into a form that works on Sparc Solaris 2 by Mark Eichin
+/* Mangled into a form that works on SPARC Solaris 2 by Mark Eichin
* for Cygnus Support, July 1992.
*/
@@ -232,7 +232,7 @@ _mcleanup()
}
/*
- * The Sparc stack frame is only held together by the frame pointers
+ * The SPARC stack frame is only held together by the frame pointers
* in the register windows. According to the SVR4 SPARC ABI
* Supplement, Low Level System Information/Operating System
* Interface/Software Trap Types, a type 3 trap will flush all of the
diff --git a/contrib/gcc/config/sparc/hypersparc.md b/contrib/gcc/config/sparc/hypersparc.md
new file mode 100644
index 0000000..d80e51e
--- /dev/null
+++ b/contrib/gcc/config/sparc/hypersparc.md
@@ -0,0 +1,83 @@
+;; Scheduling description for HyperSPARC.
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU CC.
+;;
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; The HyperSPARC is a dual-issue processor. It is not all that fancy.
+
+;; ??? There are some things not modelled. For example, sethi+or
+;; ??? coming right after each other are specifically identified and
+;; ??? dual-issued by the processor. Similarly for sethi+ld[reg+lo].
+;; ??? Actually, to be more precise that rule is sort of modelled now.
+
+(define_automaton "hypersparc_0,hypersparc_1")
+
+;; HyperSPARC/sparclite86x scheduling
+
+(define_cpu_unit "hs_memory,hs_branch,hs_shift,hs_fpalu" "hypersparc_0")
+(define_cpu_unit "hs_fpmds" "hypersparc_1")
+
+(define_insn_reservation "hs_load" 1
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "load,sload,fpload"))
+ "hs_memory")
+
+(define_insn_reservation "hs_store" 2
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "store,fpstore"))
+ "hs_memory, nothing")
+
+(define_insn_reservation "hs_slbranch" 1
+ (and (eq_attr "cpu" "sparclite86x")
+ (eq_attr "type" "branch"))
+ "hs_branch")
+
+(define_insn_reservation "hs_slshift" 1
+ (and (eq_attr "cpu" "sparclite86x")
+ (eq_attr "type" "shift"))
+ "hs_shift")
+
+(define_insn_reservation "hs_fp_alu" 1
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "fp,fpmove,fpcmp"))
+ "hs_fpalu")
+
+(define_insn_reservation "hs_fp_mult" 1
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "fpmul"))
+ "hs_fpmds")
+
+(define_insn_reservation "hs_fp_divs" 8
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "fpdivs"))
+ "hs_fpmds*6, nothing*2")
+
+(define_insn_reservation "hs_fp_divd" 12
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "fpdivd"))
+ "hs_fpmds*10, nothing*2")
+
+(define_insn_reservation "hs_fp_sqrt" 17
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "fpsqrts,fpsqrtd"))
+ "hs_fpmds*15, nothing*2")
+
+(define_insn_reservation "hs_imul" 17
+ (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
+ (eq_attr "type" "imul"))
+ "hs_fpmds*15, nothing*2")
diff --git a/contrib/gcc/config/sparc/lb1spc.asm b/contrib/gcc/config/sparc/lb1spc.asm
index b31f82c..b60bd57 100644
--- a/contrib/gcc/config/sparc/lb1spc.asm
+++ b/contrib/gcc/config/sparc/lb1spc.asm
@@ -1,7 +1,7 @@
/* This is an assembly language implementation of mulsi3, divsi3, and modsi3
for the sparc processor.
- These routines are derived from the Sparc Architecture Manual, version 8,
+ These routines are derived from the SPARC Architecture Manual, version 8,
slightly edited to match the desired calling convention, and also to
optimize them for our purposes. */
@@ -81,7 +81,7 @@ mul_shortway:
#ifdef L_divsi3
/*
- * Division and remainder, from Appendix E of the Sparc Version 8
+ * Division and remainder, from Appendix E of the SPARC Version 8
* Architecture Manual, with fixes from Gordon Irlam.
*/
@@ -197,7 +197,7 @@ ready_to_divide:
nop
be do_single_div
nop
- /* NB: these are commented out in the V8-Sparc manual as well */
+ /* NB: these are commented out in the V8-SPARC manual as well */
/* (I do not understand this) */
! %o5 > %o3: went too far: back up 1 step
! srl %o5, 1, %o5
@@ -544,7 +544,7 @@ divide:
nop
be do_single_div
nop
- /* NB: these are commented out in the V8-Sparc manual as well */
+ /* NB: these are commented out in the V8-SPARC manual as well */
/* (I do not understand this) */
! %o5 > %o3: went too far: back up 1 step
! srl %o5, 1, %o5
diff --git a/contrib/gcc/config/sparc/lb1spl.asm b/contrib/gcc/config/sparc/lb1spl.asm
index 9dda675..973401f 100644
--- a/contrib/gcc/config/sparc/lb1spl.asm
+++ b/contrib/gcc/config/sparc/lb1spl.asm
@@ -1,7 +1,7 @@
/* This is an assembly language implementation of mulsi3, divsi3, and modsi3
for the sparclite processor.
- These routines are all from the Sparclite User's Guide, slightly edited
+ These routines are all from the SPARClite User's Guide, slightly edited
to match the desired calling convention, and also to optimize them. */
#ifdef L_udivsi3
diff --git a/contrib/gcc/config/sparc/linux-aout.h b/contrib/gcc/config/sparc/linux-aout.h
index 41d3877..70b2c79 100644
--- a/contrib/gcc/config/sparc/linux-aout.h
+++ b/contrib/gcc/config/sparc/linux-aout.h
@@ -31,7 +31,7 @@ Boston, MA 02111-1307, USA. */
#endif
/* We need that too. */
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
diff --git a/contrib/gcc/config/sparc/linux.h b/contrib/gcc/config/sparc/linux.h
index b93b46c..ea16b7eed 100644
--- a/contrib/gcc/config/sparc/linux.h
+++ b/contrib/gcc/config/sparc/linux.h
@@ -123,9 +123,9 @@ Boston, MA 02111-1307, USA. */
%{!profile:%{!ggdb:-lc} %{ggdb:-lg}}}"
#else
#define LIB_SPEC \
- "%{shared: -lc} \
- %{!shared: %{mieee-fp:-lieee} %{pthread:-lpthread} \
- %{profile:-lc_p} %{!profile: -lc}}"
+ "%{pthread:-lpthread} \
+ %{shared:-lc} \
+ %{!shared:%{mieee-fp:-lieee} %{profile:-lc_p}%{!profile:-lc}}"
#endif
#else
#define LIB_SPEC \
@@ -230,8 +230,8 @@ do { \
sprintf (LABEL, "*.L%s%ld", PREFIX, (long)(NUM))
-/* Define for support of TFmode long double and REAL_ARITHMETIC.
- Sparc ABI says that long double is 4 words. */
+/* Define for support of TFmode long double.
+ SPARC ABI says that long double is 4 words. */
#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
/* Constant which presents upper bound of the above value. */
diff --git a/contrib/gcc/config/sparc/linux64.h b/contrib/gcc/config/sparc/linux64.h
index c7d8f491..8fd3a1f 100644
--- a/contrib/gcc/config/sparc/linux64.h
+++ b/contrib/gcc/config/sparc/linux64.h
@@ -44,7 +44,6 @@ Boston, MA 02111-1307, USA. */
#undef CPP_ARCH32_SPEC
#define CPP_ARCH32_SPEC "%{mlong-double-128:-D__LONG_DOUBLE_128__} \
--D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int \
-D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc"
#endif
@@ -57,8 +56,7 @@ Boston, MA 02111-1307, USA. */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC \
- "%{!shared: \
- %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\
+ "%{!shared:%{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\
crti.o%s %{static:crtbeginT.o%s}\
%{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
@@ -96,8 +94,8 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
-/* Define for support of TFmode long double and REAL_ARITHMETIC.
- Sparc ABI says that long double is 4 words. */
+/* Define for support of TFmode long double.
+ SPARC ABI says that long double is 4 words. */
#undef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
@@ -126,9 +124,9 @@ Boston, MA 02111-1307, USA. */
#undef LIB_SPEC
#define LIB_SPEC \
- "%{shared: -lc} \
- %{!shared: %{mieee-fp:-lieee} %{pthread:-lpthread} \
- %{profile:-lc_p} %{!profile: -lc}}"
+ "%{pthread:-lpthread} \
+ %{shared:-lc} \
+ %{!shared: %{mieee-fp:-lieee} %{profile:-lc_p}%{!profile:-lc}}"
/* Provide a LINK_SPEC appropriate for GNU/Linux. Here we provide support
for the special GCC options -static and -shared, which allow us to
@@ -259,11 +257,9 @@ Boston, MA 02111-1307, USA. */
/* System V Release 4 uses DWARF debugging info. Buf DWARF1 doesn't do
64-bit anything, so we use DWARF2. */
-#undef DWARF2_DEBUGGING_INFO
#undef DWARF_DEBUGGING_INFO
-#undef DBX_DEBUGGING_INFO
-#define DWARF2_DEBUGGING_INFO
-#define DBX_DEBUGGING_INFO
+#define DWARF2_DEBUGGING_INFO 1
+#define DBX_DEBUGGING_INFO 1
#undef ASM_OUTPUT_ALIGNED_LOCAL
#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
@@ -328,7 +324,7 @@ do { \
/* Handle multilib correctly. */
#if defined(__arch64__)
-/* 64-bit Sparc version */
+/* 64-bit SPARC version */
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
do { \
unsigned int *pc_ = (CONTEXT)->ra; \
@@ -379,7 +375,7 @@ do { \
goto SUCCESS; \
} while (0)
#else
-/* 32-bit Sparc version */
+/* 32-bit SPARC version */
#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
do { \
unsigned int *pc_ = (CONTEXT)->ra; \
diff --git a/contrib/gcc/config/sparc/litecoff.h b/contrib/gcc/config/sparc/litecoff.h
index ad0e1225..91808f5 100644
--- a/contrib/gcc/config/sparc/litecoff.h
+++ b/contrib/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, 1996, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1996, 2000, 2002 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com).
This file is part of GNU CC.
@@ -32,18 +32,6 @@ Boston, MA 02111-1307, USA. */
#undef INIT_SECTION_ASM_OP
-/* A list of other sections which the compiler might be "in" at any
- given time. */
-
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const
-
-/* A list of extra section function definitions. */
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- CONST_SECTION_FUNCTION
-
#undef DO_GLOBAL_CTORS_BODY
#undef DO_GLOBAL_DTORS_BODY
diff --git a/contrib/gcc/config/sparc/liteelf.h b/contrib/gcc/config/sparc/liteelf.h
index 5c93c2d..9b6cbaa 100644
--- a/contrib/gcc/config/sparc/liteelf.h
+++ b/contrib/gcc/config/sparc/liteelf.h
@@ -24,10 +24,8 @@ Boston, MA 02111-1307, USA. */
/* Default to dwarf2 in ELF. */
-#undef DWARF_DEBUGGING_INFO
-#define DWARF_DEBUGGING_INFO
-#undef DWARF2_DEBUGGING_INFO
-#define DWARF2_DEBUGGING_INFO
+#define DWARF_DEBUGGING_INFO 1
+#define DWARF2_DEBUGGING_INFO 1
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
diff --git a/contrib/gcc/config/sparc/lynx.h b/contrib/gcc/config/sparc/lynx.h
index 866612d..805f65f 100644
--- a/contrib/gcc/config/sparc/lynx.h
+++ b/contrib/gcc/config/sparc/lynx.h
@@ -19,7 +19,6 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#undef ASM_OUTPUT_IDENT
-#undef SELECT_RTX_SECTION
#define BSS_SECTION_ASM_OP "\t.section\t\".bss\""
@@ -39,7 +38,7 @@ Boston, MA 02111-1307, USA. */
#undef LINK_SPEC
-/* Sparc version of libc.a has references to libm.a (printf calls pow for
+/* SPARC version of libc.a has references to libm.a (printf calls pow for
instance), so we must always link both. */
#undef LIB_SPEC
diff --git a/contrib/gcc/config/sparc/netbsd-elf.h b/contrib/gcc/config/sparc/netbsd-elf.h
index f141f89..10788f2 100644
--- a/contrib/gcc/config/sparc/netbsd-elf.h
+++ b/contrib/gcc/config/sparc/netbsd-elf.h
@@ -20,38 +20,32 @@ 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_OS_CPP_BUILTINS() \
+ do \
+ { \
+ NETBSD_OS_CPP_BUILTINS_ELF(); \
+ if (TARGET_ARCH64) \
+ { \
+ NETBSD_OS_CPP_BUILTINS_LP64(); \
+ builtin_define ("__sparc64__"); \
+ builtin_define ("__sparc_v9__"); \
+ } \
+ else \
+ builtin_define ("__sparc"); \
+ builtin_define ("__sparc__"); \
+ } \
+ while (0)
+
/* Make sure these are undefined. */
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
+/* Make sure this is undefined. */
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__sparc__ -D__NetBSD__ -D__ELF__ \
--Asystem=unix -Asystem=NetBSD"
-
-/* CPP defines used for 64 bit code. */
-#undef CPP_SUBTARGET_SPEC64
-#define CPP_SUBTARGET_SPEC64 \
- "-D__sparc64__ -D__sparc_v9__ -D_LP64 %{posix:-D_POSIX_SOURCE}"
-
-/* CPP defines used for 32 bit code. */
-#undef CPP_SUBTARGET_SPEC32
-#define CPP_SUBTARGET_SPEC32 "-D__sparc %{posix:-D_POSIX_SOURCE}"
-
-/* CPP_ARCH32_SPEC and CPP_ARCH64_SPEC are wrong from sparc/sparc.h; we
- always want the non-SPARC_BI_ARCH versions, since the SPARC_BI_ARCH
- versions define __SIZE_TYPE__ and __PTRDIFF_TYPE__ incorrectly for
- NetBSD. */
-#undef CPP_ARCH32_SPEC
-#define CPP_ARCH32_SPEC "-D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc"
-
-#undef CPP_ARCH64_SPEC
-#define CPP_ARCH64_SPEC "-D__arch64__ -Acpu=sparc64 -Amachine=sparc64"
-
-/* sparc/sparc.h defines NO_BUILTIN_SIZE_TYPE and NO_BUILTIN_PTRDIFF_TYPE
- if SPARC_BI_ARCH is defined. This is wrong for NetBSD; size_t and
- ptrdiff_t do not change for 32-bit vs. 64-bit. */
-#undef NO_BUILTIN_PTRDIFF_TYPE
-#undef NO_BUILTIN_SIZE_TYPE
+
+/* CPP defines used by all NetBSD targets. */
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC "%(netbsd_cpp_spec)"
/* SIZE_TYPE and PTRDIFF_TYPE are wrong from sparc/sparc.h. */
#undef SIZE_TYPE
@@ -108,6 +102,9 @@ Boston, MA 02111-1307, USA. */
#undef STDC_0_IN_SYSTEM_HEADERS
+/* Attempt to enable execute permissions on the stack. */
+#define TRANSFER_FROM_TRAMPOLINE NETBSD_ENABLE_EXECUTE_STACK
+
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (%s)", TARGET_NAME);
@@ -200,35 +197,22 @@ Boston, MA 02111-1307, USA. */
/* Make sure we use the right output format. Pick a default and then
make sure -m32/-m64 switch to the right one. */
-#define LINK_ARCH32_SPEC \
- "%-m elf32_sparc \
- %{assert*} %{R*} %{V} %{v:%{!V:-V}} \
- %{shared:-shared} \
- %{!shared: \
- -dp \
- %{!nostdlib:%{!r*:%{!e*:-e __start}}} \
- %{!static: \
- -dy %{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /usr/libexec/ld.elf_so}} \
- %{static:-static}}"
-
-#define LINK_ARCH64_SPEC \
- "%-m elf64_sparc \
- %{assert*} %{R*} %{V} %{v:%{!V:-V}} \
- %{shared:-shared} \
- %{!shared: \
- -dp \
- %{!nostdlib:%{!r*:%{!e*:-e __start}}} \
- %{!static: \
- -dy %{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /usr/libexec/ld.elf_so}} \
- %{static:-static}}"
-
-#define LINK_ARCH_SPEC "\
-%{m32:%(link_arch32)} \
-%{m64:%(link_arch64)} \
-%{!m32:%{!m64:%(link_arch_default)}} \
-"
+#define LINK_ARCH32_SPEC "-m elf32_sparc"
+
+#define LINK_ARCH64_SPEC "-m elf64_sparc"
+
+#define LINK_ARCH_SPEC \
+ "%{m32:%(link_arch32)} \
+ %{m64:%(link_arch64)} \
+ %{!m32:%{!m64:%(link_arch_default)}}"
+
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%(link_arch) \
+ %{!mno-relax:%{!r:-relax}} \
+ %(netbsd_link_spec)"
+
+#define NETBSD_ENTRY_POINT "__start"
#if DEFAULT_ARCH32_P
#define LINK_ARCH_DEFAULT_SPEC LINK_ARCH32_SPEC
@@ -243,8 +227,9 @@ Boston, MA 02111-1307, USA. */
{ "link_arch64", LINK_ARCH64_SPEC }, \
{ "link_arch_default", LINK_ARCH_DEFAULT_SPEC }, \
{ "link_arch", LINK_ARCH_SPEC }, \
- { "cpp_subtarget_spec32", CPP_SUBTARGET_SPEC32 }, \
- { "cpp_subtarget_spec64", CPP_SUBTARGET_SPEC64 },
+ { "netbsd_cpp_spec", NETBSD_CPP_SPEC }, \
+ { "netbsd_link_spec", NETBSD_LINK_SPEC_ELF }, \
+ { "netbsd_entry_point", NETBSD_ENTRY_POINT },
/* What extra switches do we need? */
@@ -283,19 +268,6 @@ Boston, MA 02111-1307, USA. */
#define MULTILIB_DEFAULTS { "m64" }
#endif
-#undef CPP_SUBTARGET_SPEC
-#if DEFAULT_ARCH32_P
-#define CPP_SUBTARGET_SPEC \
- "%{m64:%(cpp_subtarget_spec64)}%{!m64:%(cpp_subtarget_spec32)}"
-#else
-#define CPP_SUBTARGET_SPEC \
- "%{!m32:%(cpp_subtarget_spec64)}%{m32:%(cpp_subtarget_spec32)}"
-#endif
-
-/* Restore this from sparc/sparc.h, netbsd.h changes it. */
-#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu) %(cpp_arch) %(cpp_endian) %(cpp_subtarget)"
-
/* Name the port. */
#undef TARGET_NAME
#define TARGET_NAME (DEFAULT_ARCH32_P ? TARGET_NAME32 : TARGET_NAME64)
@@ -317,9 +289,6 @@ Boston, MA 02111-1307, USA. */
#undef CC1_SPEC
#define CC1_SPEC CC1_SPEC64
-#undef CPP_SUBTARGET_SPEC
-#define CPP_SUBTARGET_SPEC CPP_SUBTARGET_SPEC64
-
#undef TARGET_NAME
#define TARGET_NAME TARGET_NAME64
@@ -338,9 +307,6 @@ Boston, MA 02111-1307, USA. */
#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#undef CPP_SUBTARGET_SPEC
-#define CPP_SUBTARGET_SPEC CPP_SUBTARGET_SPEC32
-
#undef CC1_SPEC
#define CC1_SPEC CC1_SPEC32
diff --git a/contrib/gcc/config/sparc/netbsd.h b/contrib/gcc/config/sparc/netbsd.h
index b7b4440..284e288 100644
--- a/contrib/gcc/config/sparc/netbsd.h
+++ b/contrib/gcc/config/sparc/netbsd.h
@@ -1,7 +1,23 @@
-/* Names to predefine in the preprocessor for this target machine. */
-
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ NETBSD_OS_CPP_BUILTINS_AOUT(); \
+ builtin_define_std ("sparc"); \
+ builtin_assert ("cpu=sparc"); \
+ builtin_assert ("machine=sparc"); \
+ } \
+ while (0)
+
+/* Make sure this is undefined. */
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dunix -Dsparc -D__NetBSD__ -Asystem=unix -Asystem=NetBSD -Acpu=sparc -Amachine=sparc"
+
+/* What extra spec entries do we need? */
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "netbsd_cpp_spec", NETBSD_CPP_SPEC },
+
+#undef CPP_SPEC
+#define CPP_SPEC "%(cpp_cpu) %(netbsd_cpp_spec)"
/* Make gcc agree with <machine/ansi.h> */
@@ -13,7 +29,7 @@
/* This is BSD, so it wants DBX format. */
-#define DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
/* This is the char to use for continuation (in case we need to turn
continuation back on). */
@@ -28,3 +44,6 @@
/* Until they use ELF or something that handles dwarf2 unwinds
and initialization stuff better. */
#define DWARF2_UNWIND_INFO 0
+
+/* Attempt to enable execute permissions on the stack. */
+#define TRANSFER_FROM_TRAMPOLINE NETBSD_ENABLE_EXECUTE_STACK
diff --git a/contrib/gcc/config/sparc/openbsd.h b/contrib/gcc/config/sparc/openbsd.h
index dc37284..a4333df 100644
--- a/contrib/gcc/config/sparc/openbsd.h
+++ b/contrib/gcc/config/sparc/openbsd.h
@@ -1,5 +1,5 @@
/* Configuration file for sparc OpenBSD target.
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -43,7 +43,7 @@ Boston, MA 02111-1307, USA. */
/* Specific options for DBX Output. */
/* This is BSD, so it wants DBX format. */
-#define DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
/* This is the char to use for continuation */
#define DBX_CONTIN_CHAR '?'
@@ -63,5 +63,3 @@ Boston, MA 02111-1307, USA. */
#define DWARF2_UNWIND_INFO 0
#undef ASM_PREFERRED_EH_DATA_FORMAT
-
-/* Default sparc.h does already define ASM_OUTPUT_MI_THUNK */
diff --git a/contrib/gcc/config/sparc/pbd.h b/contrib/gcc/config/sparc/pbd.h
index 9d267a5..e7c01c0 100644
--- a/contrib/gcc/config/sparc/pbd.h
+++ b/contrib/gcc/config/sparc/pbd.h
@@ -27,7 +27,7 @@ Boston, MA 02111-1307, USA. */
/* We want DBX format for use with gdb under COFF. */
-#define DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
/* Generate calls to memcpy, memcmp and memset. */
@@ -59,10 +59,6 @@ Boston, MA 02111-1307, USA. */
#define ENDFILE_SPEC "crtn.o%s"
-/* cpp has to support a #sccs directive for the /usr/include files */
-
-#define SCCS_DIRECTIVE
-
/* LINK_SPEC is needed only for SunOS 4. */
#undef LINK_SPEC
diff --git a/contrib/gcc/config/sparc/sol2-bi.h b/contrib/gcc/config/sparc/sol2-bi.h
index e19e888..3f9416d 100644
--- a/contrib/gcc/config/sparc/sol2-bi.h
+++ b/contrib/gcc/config/sparc/sol2-bi.h
@@ -5,9 +5,6 @@
#undef SPARC_DEFAULT_CMODEL
#define SPARC_DEFAULT_CMODEL CM_MEDANY
-#undef LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE 128
-
#define AS_SPARC64_FLAG "-xarch=v9"
#undef ASM_CPU32_DEFAULT_SPEC
@@ -30,15 +27,6 @@
#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG "a"
#endif
-/* The sun bundled assembler doesn't accept -Yd, (and neither does gas).
- It's safe to pass -s always, even if -g is not used. */
-#undef ASM_SPEC
-#define ASM_SPEC "\
-%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s \
-%{fpic:-K PIC} %{fPIC:-K PIC} \
-%(asm_cpu)\
-"
-
#if DEFAULT_ARCH32_P
#define DEF_ARCH32_SPEC(__str) "%{!m64:" __str "}"
#define DEF_ARCH64_SPEC(__str) "%{m64:" __str "}"
@@ -50,17 +38,14 @@
#undef CPP_CPU_SPEC
#define CPP_CPU_SPEC "\
%{mcypress:} \
-%{msparclite:-D__sparclite__} \
-%{mf930:-D__sparclite__} %{mf934:-D__sparclite__} \
+%{msparclite|mf930|mf934:-D__sparclite__} \
%{mv8:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
%{msupersparc:-D__supersparc__ " DEF_ARCH32_SPEC("-D__sparcv8") "} \
-%{mcpu=sparclet:-D__sparclet__} %{mcpu=tsc701:-D__sparclet__} \
-%{mcpu=sparclite:-D__sparclite__} \
-%{mcpu=f930:-D__sparclite__} %{mcpu=f934:-D__sparclite__} \
+%{mcpu=sparclet|mcpu=tsc701:-D__sparclet__} \
+%{mcpu=sparclite|mcpu-f930|mcpu=f934:-D__sparclite__} \
%{mcpu=v8:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
%{mcpu=supersparc:-D__supersparc__ " DEF_ARCH32_SPEC("-D__sparcv8") "} \
-%{mcpu=v9:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
-%{mcpu=ultrasparc:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{mcpu=v9|mcpu=ultrasparc:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \
"
@@ -72,19 +57,6 @@
%{!mcpu*:%(asm_cpu_default)} \
"
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{!shared: \
- %{!symbolic: \
- %{p:mcrt1.o%s} \
- %{!p: \
- %{pg:gcrt1.o%s gmon.o%s} \
- %{!pg:crt1.o%s}}}} \
- crti.o%s \
- %{ansi:values-Xc.o%s} \
- %{!ansi: %{traditional:values-Xt.o%s} \
- %{!traditional:values-Xa.o%s}} \
- crtbegin.o%s"
-
#undef CPP_CPU_DEFAULT_SPEC
#define CPP_CPU_DEFAULT_SPEC \
(DEFAULT_ARCH32_P ? "\
@@ -108,7 +80,6 @@
/* wchar_t is called differently in <wchar.h> for 32 and 64-bit
compilations. This is called for by SCD 2.4.1, p. 6-83, Figure 6-65
(32-bit) and p. 6P-10, Figure 6.38 (64-bit). */
-#define NO_BUILTIN_WCHAR_TYPE
#undef WCHAR_TYPE
#define WCHAR_TYPE (TARGET_ARCH64 ? "int" : "long int")
@@ -119,7 +90,6 @@
/* Same for wint_t. See SCD 2.4.1, p. 6-83, Figure 6-66 (32-bit). There's
no corresponding 64-bit definition, but this is what Solaris 8
<iso/wchar_iso.h> uses. */
-#define NO_BUILTIN_WINT_TYPE
#undef WINT_TYPE
#define WINT_TYPE (TARGET_ARCH64 ? "int" : "long int")
@@ -128,12 +98,10 @@
#define WINT_TYPE_SIZE 32
#undef CPP_ARCH32_SPEC
-#define CPP_ARCH32_SPEC "-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int \
--D__WCHAR_TYPE__=long\\ int -D__WINT_TYPE__=long\\ int \
+#define CPP_ARCH32_SPEC "\
-D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc"
#undef CPP_ARCH64_SPEC
-#define CPP_ARCH64_SPEC "-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int \
--D__WCHAR_TYPE__=int -D__WINT_TYPE__=int \
+#define CPP_ARCH64_SPEC "\
-D__arch64__ -Acpu=sparc64 -Amachine=sparcv9 -D__sparcv9"
#undef CPP_ARCH_SPEC
@@ -157,41 +125,30 @@
#undef SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS \
+ { "startfile_arch", STARTFILE_ARCH_SPEC }, \
{ "link_arch32", LINK_ARCH32_SPEC }, \
{ "link_arch64", LINK_ARCH64_SPEC }, \
{ "link_arch_default", LINK_ARCH_DEFAULT_SPEC }, \
{ "link_arch", LINK_ARCH_SPEC },
-/* This should be the same as in svr4.h, except with -R added. */
-#define LINK_ARCH32_SPEC \
- "%{G:-G} \
- %{YP,*} \
- %{R*} \
- %{compat-bsd: \
- %{!YP,*:%{p:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{pg:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{!p:%{!pg:-Y P,/usr/ucblib:/usr/ccs/lib:/usr/lib}}} \
- -R /usr/ucblib} \
- %{!compat-bsd: \
- %{!YP,*:%{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{pg:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{!p:%{!pg:-Y P,/usr/ccs/lib:/usr/lib}}}}"
-
+/*
+ * This should be the same as in sol2.h, except with "/sparcv9"
+ * appended to the paths and /usr/ccs/lib is no longer necessary
+ */
#define LINK_ARCH64_SPEC \
"%{mcmodel=medlow:-M /usr/lib/ld/sparcv9/map.below4G} \
%{G:-G} \
%{YP,*} \
%{R*} \
%{compat-bsd: \
- %{!YP,*:%{p:-Y P,/usr/ucblib/sparcv9:/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
- %{pg:-Y P,/usr/ucblib/sparcv9:/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
+ %{!YP,*:%{p|pg:-Y P,/usr/ucblib/sparcv9:/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
%{!p:%{!pg:-Y P,/usr/ucblib/sparcv9:/usr/lib/sparcv9}}} \
-R /usr/ucblib} \
%{!compat-bsd: \
- %{!YP,*:%{p:-Y P,/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
- %{pg:-Y P,/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
+ %{!YP,*:%{p|pg:-Y P,/usr/lib/libp/sparcv9:/usr/lib/sparcv9} \
%{!p:%{!pg:-Y P,/usr/lib/sparcv9}}}}"
+#undef LINK_ARCH_SPEC
#define LINK_ARCH_SPEC "\
%{m32:%(link_arch32)} \
%{m64:%(link_arch64)} \
@@ -201,16 +158,6 @@
#define LINK_ARCH_DEFAULT_SPEC \
(DEFAULT_ARCH32_P ? LINK_ARCH32_SPEC : LINK_ARCH64_SPEC)
-#undef LINK_SPEC
-#define LINK_SPEC \
- "%{h*} %{v:-V} \
- %{b} %{Wl,*:%*} \
- %{static:-dn -Bstatic} \
- %{shared:-G -dy %{!mimpure-text:-z text}} \
- %{symbolic:-Bsymbolic -G -dy -z text} \
- %(link_arch) \
- %{Qy:} %{!Qn:-Qy}"
-
#undef CC1_SPEC
#if DEFAULT_ARCH32_P
#define CC1_SPEC "\
diff --git a/contrib/gcc/config/sparc/sol2.h b/contrib/gcc/config/sparc/sol2.h
index 56bfbb7..3026e40 100644
--- a/contrib/gcc/config/sparc/sol2.h
+++ b/contrib/gcc/config/sparc/sol2.h
@@ -23,51 +23,8 @@ Boston, MA 02111-1307, USA. */
/* Supposedly the same as vanilla sparc svr4, except for the stuff below: */
-/* Solaris 2 (at least as of 2.5.1) uses a 32-bit wchar_t. */
-#undef WCHAR_TYPE
-#define WCHAR_TYPE "long int"
-
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE 32
-
-/* Solaris 2 uses a wint_t different from the default. This is required
- by the SCD 2.4.1, p. 6-83, Figure 6-66. */
-#undef WINT_TYPE
-#define WINT_TYPE "long int"
-
-#undef WINT_TYPE_SIZE
-#define WINT_TYPE_SIZE 32
-
-#define HANDLE_PRAGMA_REDEFINE_EXTNAME 1
-
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
-"-Dsparc -Dsun -Dunix -D__svr4__ -D__SVR4 -D__PRAGMA_REDEFINE_EXTNAME \
--Asystem=unix -Asystem=svr4"
-
-#undef CPP_SUBTARGET_SPEC
-#define CPP_SUBTARGET_SPEC "\
-%{pthreads:-D_REENTRANT -D_PTHREADS} \
-%{!pthreads:%{threads:-D_REENTRANT -D_SOLARIS_THREADS}} \
-%{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude} \
-"
-
-/* For C++ we need to add some additional macro definitions required
- by the C++ standard library. */
-#define CPLUSPLUS_CPP_SPEC "\
--D_XOPEN_SOURCE=500 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE=1 \
--D__EXTENSIONS__ \
-%(cpp) \
-"
-
-/* The sun bundled assembler doesn't accept -Yd, (and neither does gas).
- It's safe to pass -s always, even if -g is not used. */
-#undef ASM_SPEC
-#define ASM_SPEC "\
-%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s \
-%{fpic:-K PIC} %{fPIC:-K PIC} \
-%(asm_cpu) \
-"
+#define CPP_PREDEFINES "-Dsparc"
/* This is here rather than in sparc.h because it's not known what
other assemblers will accept. */
@@ -90,6 +47,11 @@ Boston, MA 02111-1307, USA. */
%{!mcpu*:%(asm_cpu_default)} \
"
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "startfile_arch", STARTFILE_ARCH_SPEC }, \
+ { "link_arch", LINK_ARCH_SPEC }
+
/* However it appears that Solaris 2.0 uses the same reg numbering as
the old BSD-style system did. */
@@ -98,11 +60,6 @@ Boston, MA 02111-1307, USA. */
#define DBX_REGISTER_NUMBER(REGNO) \
(TARGET_FLAT && (REGNO) == HARD_FRAME_POINTER_REGNUM ? 31 : REGNO)
-/* We use stabs-in-elf by default, because that is what the native
- toolchain uses. */
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-
/* The Solaris 2 assembler uses .skip, not .zero, so put this back. */
#undef ASM_OUTPUT_SKIP
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
@@ -135,74 +92,12 @@ Boston, MA 02111-1307, USA. */
sprintf ((LABEL), "*.L%s%ld", (PREFIX), (long)(NUM))
-/* We don't use the standard svr4 STARTFILE_SPEC because it's wrong for us.
- We don't use the standard LIB_SPEC only because we don't yet support c++ */
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{!shared: \
- %{!symbolic: \
- %{p:mcrt1.o%s} \
- %{!p: \
- %{pg:gcrt1.o%s gmon.o%s} \
- %{!pg:crt1.o%s}}}} \
- crti.o%s \
- %{ansi:values-Xc.o%s} \
- %{!ansi: \
- %{traditional:values-Xt.o%s} \
- %{!traditional:values-Xa.o%s}} \
- crtbegin.o%s"
-
-/* ??? Note: in order for -compat-bsd to work fully,
- we must somehow arrange to fixincludes /usr/ucbinclude
- and put the result in $(libsubdir)/ucbinclude. */
-
-#undef LIB_SPEC
-#define LIB_SPEC \
- "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} \
- %{!shared:\
- %{!symbolic:\
- %{pthreads:-lpthread} \
- %{!pthreads:%{threads:-lthread}} \
- %{p|pg:-ldl} -lc}}"
#undef ENDFILE_SPEC
#define ENDFILE_SPEC \
"%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
crtend.o%s crtn.o%s"
-/* This should be the same as in svr4.h, except with -R added. */
-#undef LINK_SPEC
-#define LINK_SPEC \
- "%{h*} %{v:-V} \
- %{b} %{Wl,*:%*} \
- %{static:-dn -Bstatic} \
- %{shared:-G -dy %{!mimpure-text:-z text}} \
- %{symbolic:-Bsymbolic -G -dy -z text} \
- %{G:-G} \
- %{YP,*} \
- %{R*} \
- %{compat-bsd: \
- %{!YP,*:%{pg:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{!pg:%{p:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{!p:-Y P,/usr/ucblib:/usr/ccs/lib:/usr/lib}}} \
- -R /usr/ucblib} \
- %{!compat-bsd: \
- %{!YP,*:%{pg:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{!pg:%{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
- %{!p:-Y P,/usr/ccs/lib:/usr/lib}}}} \
- %{Qy:} %{!Qn:-Qy}"
-
-/* This defines which switch letters take arguments.
- It is as in svr4.h but with -R added. */
-
-#undef SWITCH_TAKES_ARG
-#define SWITCH_TAKES_ARG(CHAR) \
- (DEFAULT_SWITCH_TAKES_ARG(CHAR) \
- || (CHAR) == 'R' \
- || (CHAR) == 'h' \
- || (CHAR) == 'x' \
- || (CHAR) == 'z')
-
/* Select a format to encode pointers in exception handling data. CODE
is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
true if the symbol may be affected by dynamic relocations.
@@ -216,15 +111,13 @@ Boston, MA 02111-1307, USA. */
/* ??? This does not work in SunOS 4.x, so it is not enabled in sparc.h.
Instead, it is enabled here, because it does work under Solaris. */
-/* Define for support of TFmode long double and REAL_ARITHMETIC.
- Sparc ABI says that long double is 4 words. */
+/* Define for support of TFmode long double.
+ 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 1
-
#define MULDI3_LIBCALL "__mul64"
#define DIVDI3_LIBCALL "__div64"
#define UDIVDI3_LIBCALL "__udiv64"
@@ -251,56 +144,4 @@ Boston, MA 02111-1307, USA. */
/* Solaris allows 64 bit out and global registers in 32 bit mode.
sparc_override_options will disable V8+ if not generating V9 code. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_FPU + MASK_V8PLUS + MASK_LONG_DOUBLE_128)
-
-/*
- * Attempt to turn on access permissions for the stack.
- *
- * This code must be defined when compiling gcc but not when compiling
- * libgcc2.a, unless we're generating code for 64 bits SPARC
- *
- * _SC_STACK_PROT is only defined for post 2.6, but we want this code
- * to run always. 2.6 can change the stack protection but has no way to
- * query it.
- *
- */
-
-/* This declares mprotect (used in TRANSFER_FROM_TRAMPOLINE) for
- libgcc2.c. */
-/* We don't want to include this because sys/mman.h is not present on
- some non-Solaris configurations that use sol2.h. */
-#if 0 /* def L_trampoline */
-#include <sys/mman.h>
-#endif
-
-#define TRANSFER_FROM_TRAMPOLINE \
-static int need_enable_exec_stack; \
- \
-static void check_enabling(void) __attribute__ ((constructor)); \
-static void check_enabling(void) \
-{ \
- extern long sysconf(int); \
- \
- int prot = (int) sysconf(515 /*_SC_STACK_PROT */); \
- if (prot != 7) \
- need_enable_exec_stack = 1; \
-} \
- \
-extern void __enable_execute_stack (void *); \
-void \
-__enable_execute_stack (addr) \
- void *addr; \
-{ \
- if (!need_enable_exec_stack) \
- return; \
- else { \
- long size = getpagesize (); \
- long mask = ~(size-1); \
- char *page = (char *) (((long) addr) & mask); \
- char *end = (char *) ((((long) (addr + TRAMPOLINE_SIZE)) & mask) + size); \
- \
- /* 7 is PROT_READ | PROT_WRITE | PROT_EXEC */ \
- if (mprotect (page, end - page, 7) < 0) \
- perror ("mprotect of trampoline code"); \
- } \
-}
+#define TARGET_DEFAULT (MASK_V8PLUS + MASK_FPU + MASK_LONG_DOUBLE_128)
diff --git a/contrib/gcc/config/sparc/sol26-sld.h b/contrib/gcc/config/sparc/sol26-sld.h
new file mode 100644
index 0000000..74b5433
--- /dev/null
+++ b/contrib/gcc/config/sparc/sol26-sld.h
@@ -0,0 +1,6 @@
+/* Up through Solaris 2.6, the system linker does not work with DWARF
+ or DWARF2, since it does not have working support for relocations
+ to unaligned data. */
+
+#undef DWARF_DEBUGGING_INFO
+#undef DWARF2_DEBUGGING_INFO
diff --git a/contrib/gcc/config/sparc/sp64-elf.h b/contrib/gcc/config/sparc/sp64-elf.h
index caf944b..18187dc 100644
--- a/contrib/gcc/config/sparc/sp64-elf.h
+++ b/contrib/gcc/config/sparc/sp64-elf.h
@@ -112,7 +112,7 @@ crtbegin.o%s \
GDB doesn't support 64 bit stabs yet and the desired debug format is DWARF
anyway so it is the default. */
-#define DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
diff --git a/contrib/gcc/config/sparc/sp86x-elf.h b/contrib/gcc/config/sparc/sp86x-elf.h
index 42239a9..cb7e8c3 100644
--- a/contrib/gcc/config/sparc/sp86x-elf.h
+++ b/contrib/gcc/config/sparc/sp86x-elf.h
@@ -24,10 +24,8 @@ Boston, MA 02111-1307, USA. */
/* Default to dwarf2 in ELF. */
-#undef DWARF_DEBUGGING_INFO
-#define DWARF_DEBUGGING_INFO
-#undef DWARF2_DEBUGGING_INFO
-#define DWARF2_DEBUGGING_INFO
+#define DWARF_DEBUGGING_INFO 1
+#define DWARF2_DEBUGGING_INFO 1
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
diff --git a/contrib/gcc/config/sparc/sparc-modes.def b/contrib/gcc/config/sparc/sparc-modes.def
new file mode 100644
index 0000000..3ebf9c8
--- /dev/null
+++ b/contrib/gcc/config/sparc/sparc-modes.def
@@ -0,0 +1,42 @@
+/* Definitions of target machine for GNU compiler, for Sun SPARC.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@cygnus.com).
+ 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
+ at Cygnus Support.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Add any extra modes needed to represent the condition code.
+
+ On the SPARC, we have a "no-overflow" mode which is used when an add or
+ subtract insn is used to set the condition code. Different branches are
+ used in this case for some operations.
+
+ We also have two modes to indicate that the relevant condition code is
+ in the floating-point condition code register. One for comparisons which
+ will generate an exception if the result is unordered (CCFPEmode) and
+ one for comparisons which will never trap (CCFPmode).
+
+ CCXmode and CCX_NOOVmode are only used by v9. */
+
+CC (CCX)
+CC (CC_NOOV)
+CC (CCX_NOOV)
+CC (CCFP)
+CC (CCFPE)
+
diff --git a/contrib/gcc/config/sparc/sparc-protos.h b/contrib/gcc/config/sparc/sparc-protos.h
index 7de8940..0aa6e58 100644
--- a/contrib/gcc/config/sparc/sparc-protos.h
+++ b/contrib/gcc/config/sparc/sparc-protos.h
@@ -42,7 +42,7 @@ extern int function_arg_pass_by_reference PARAMS ((const CUMULATIVE_ARGS *,
extern struct rtx_def *sparc_builtin_saveregs PARAMS ((void));
#ifdef RTX_CODE
extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx, int));
-extern void sparc_va_start PARAMS ((int, tree, rtx));
+extern void sparc_va_start PARAMS ((tree, rtx));
#endif
extern struct rtx_def *sparc_va_arg PARAMS ((tree, tree));
extern unsigned long sparc_type_code PARAMS ((tree));
@@ -102,7 +102,6 @@ extern int fp_zero_operand PARAMS ((rtx, enum machine_mode));
extern int reg_or_0_operand PARAMS ((rtx, enum machine_mode));
extern int empty_delay_slot PARAMS ((rtx));
extern int eligible_for_epilogue_delay PARAMS ((rtx, int));
-extern int eligible_for_return_delay PARAMS ((rtx));
extern int eligible_for_sibcall_delay PARAMS ((rtx));
extern int emit_move_sequence PARAMS ((rtx, enum machine_mode));
extern int fp_sethi_p PARAMS ((rtx));
@@ -121,8 +120,7 @@ extern char *sparc_v8plus_shift PARAMS ((rtx *, rtx, const char *));
extern int sparc_check_64 PARAMS ((rtx, rtx));
extern rtx gen_df_reg PARAMS ((rtx, int));
extern int sparc_extra_constraint_check PARAMS ((rtx, int, int));
+extern int sparc_rtx_costs PARAMS ((rtx, enum rtx_code, enum rtx_code));
#endif /* RTX_CODE */
-extern void sparc_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, tree));
-
#endif /* __SPARC_PROTOS_H__ */
diff --git a/contrib/gcc/config/sparc/sparc.c b/contrib/gcc/config/sparc/sparc.c
index c23cbef..7c25bc5 100644
--- a/contrib/gcc/config/sparc/sparc.c
+++ b/contrib/gcc/config/sparc/sparc.c
@@ -1,6 +1,6 @@
/* Subroutines for insn-output.c for Sun SPARC.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002 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.
@@ -80,8 +80,6 @@ rtx sparc_compare_op0, sparc_compare_op1;
sparc_nonflat_function_epilogue. */
bool sparc_emitting_epilogue;
-#ifdef LEAF_REGISTERS
-
/* Vector to say how input registers are mapped to output registers.
HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to
eliminate it. You must use -fomit-frame-pointer to get that. */
@@ -119,8 +117,6 @@ char sparc_leaf_regs[] =
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1};
-#endif
-
/* Name of where we pretend to think the frame pointer points.
Normally, this is "%fp", but if we are in a leaf procedure,
this is "%sp+something". We record "something" separately as it may be
@@ -140,22 +136,13 @@ static int function_arg_slotno PARAMS ((const CUMULATIVE_ARGS *,
static int supersparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
static int hypersparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
-static int ultrasparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
static void sparc_output_addr_vec PARAMS ((rtx));
static void sparc_output_addr_diff_vec PARAMS ((rtx));
static void sparc_output_deferred_case_vectors PARAMS ((void));
-static void sparc_add_gc_roots PARAMS ((void));
-static void mark_ultrasparc_pipeline_state PARAMS ((void *));
static int check_return_regs PARAMS ((rtx));
static int epilogue_renumber PARAMS ((rtx *, int));
static bool sparc_assemble_integer PARAMS ((rtx, unsigned int, int));
-static int ultra_cmove_results_ready_p PARAMS ((rtx));
-static int ultra_fpmode_conflict_exists PARAMS ((enum machine_mode));
-static rtx *ultra_find_type PARAMS ((int, rtx *, int));
-static void ultra_build_types_avail PARAMS ((rtx *, int));
-static void ultra_flush_pipeline PARAMS ((void));
-static void ultra_rescan_pipeline_state PARAMS ((rtx *, int));
static int set_extends PARAMS ((rtx));
static void output_restore_regs PARAMS ((FILE *, int));
static void sparc_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
@@ -169,21 +156,28 @@ static void sparc_nonflat_function_prologue PARAMS ((FILE *, HOST_WIDE_INT,
#ifdef OBJECT_FORMAT_ELF
static void sparc_elf_asm_named_section PARAMS ((const char *, unsigned int));
#endif
-static void ultrasparc_sched_reorder PARAMS ((FILE *, int, rtx *, int));
-static int ultrasparc_variable_issue PARAMS ((rtx));
-static void ultrasparc_sched_init PARAMS ((void));
+static void sparc_aout_select_section PARAMS ((tree, int,
+ unsigned HOST_WIDE_INT))
+ ATTRIBUTE_UNUSED;
+static void sparc_aout_select_rtx_section PARAMS ((enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT))
+ ATTRIBUTE_UNUSED;
static int sparc_adjust_cost PARAMS ((rtx, rtx, rtx, int));
static int sparc_issue_rate PARAMS ((void));
-static int sparc_variable_issue PARAMS ((FILE *, int, rtx, int));
static void sparc_sched_init PARAMS ((FILE *, int, int));
-static int sparc_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));
+static int sparc_use_dfa_pipeline_interface PARAMS ((void));
+static int sparc_use_sched_lookahead PARAMS ((void));
static void emit_soft_tfmode_libcall PARAMS ((const char *, int, rtx *));
static void emit_soft_tfmode_binop PARAMS ((enum rtx_code, rtx *));
static void emit_soft_tfmode_unop PARAMS ((enum rtx_code, rtx *));
static void emit_soft_tfmode_cvt PARAMS ((enum rtx_code, rtx *));
static void emit_hard_tfmode_operation PARAMS ((enum rtx_code, rtx *));
+
+static void sparc_encode_section_info PARAMS ((tree, int));
+static void sparc_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
+ HOST_WIDE_INT, tree));
/* Option handling. */
@@ -237,12 +231,20 @@ enum processor_type sparc_cpu;
#define TARGET_SCHED_ADJUST_COST sparc_adjust_cost
#undef TARGET_SCHED_ISSUE_RATE
#define TARGET_SCHED_ISSUE_RATE sparc_issue_rate
-#undef TARGET_SCHED_VARIABLE_ISSUE
-#define TARGET_SCHED_VARIABLE_ISSUE sparc_variable_issue
#undef TARGET_SCHED_INIT
#define TARGET_SCHED_INIT sparc_sched_init
-#undef TARGET_SCHED_REORDER
-#define TARGET_SCHED_REORDER sparc_sched_reorder
+#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
+#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE sparc_use_dfa_pipeline_interface
+#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
+#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD sparc_use_sched_lookahead
+
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO sparc_encode_section_info
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK sparc_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
struct gcc_target targetm = TARGET_INITIALIZER;
@@ -279,6 +281,7 @@ sparc_override_options ()
{ TARGET_CPU_supersparc, "supersparc" },
{ TARGET_CPU_v9, "v9" },
{ TARGET_CPU_ultrasparc, "ultrasparc" },
+ { TARGET_CPU_ultrasparc3, "ultrasparc3" },
{ 0, 0 }
};
const struct cpu_default *def;
@@ -311,6 +314,9 @@ sparc_override_options ()
/* Although insns using %y are deprecated, it is a clear win on current
ultrasparcs. */
|MASK_DEPRECATED_V8_INSNS},
+ /* TI ultrasparc III */
+ /* ??? Check if %y issue still holds true in ultra3. */
+ { "ultrasparc3", PROCESSOR_ULTRASPARC3, MASK_ISA, MASK_V9|MASK_DEPRECATED_V8_INSNS},
{ 0, 0, 0, 0 }
};
const struct cpu_table *cpu;
@@ -423,7 +429,9 @@ sparc_override_options ()
target_flags &= ~MASK_STACK_BIAS;
/* Supply a default value for align_functions. */
- if (align_functions == 0 && sparc_cpu == PROCESSOR_ULTRASPARC)
+ if (align_functions == 0
+ && (sparc_cpu == PROCESSOR_ULTRASPARC
+ || sparc_cpu == PROCESSOR_ULTRASPARC3))
align_functions = 32;
/* Validate PCC_STRUCT_RETURN. */
@@ -436,9 +444,6 @@ sparc_override_options ()
/* Do various machine dependent initializations. */
sparc_init_modes ();
-
- /* Register global variables with the garbage collector. */
- sparc_add_gc_roots ();
}
/* Miscellaneous utilities. */
@@ -457,7 +462,7 @@ v9_regcmp_p (code)
/* Operand constraints. */
-/* Return non-zero only if OP is a register of mode MODE,
+/* Return nonzero only if OP is a register of mode MODE,
or const0_rtx. */
int
@@ -478,6 +483,16 @@ reg_or_0_operand (op, mode)
return 0;
}
+/* Return nonzero only if OP is const1_rtx. */
+
+int
+const1_operand (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ return op == const1_rtx;
+}
+
/* Nonzero if OP is a floating point value with value 0.0. */
int
@@ -1378,9 +1393,8 @@ sparc_emit_set_const32 (op0, op1)
&& (INTVAL (op1) & 0x80000000) != 0)
emit_insn (gen_rtx_SET
(VOIDmode, temp,
- gen_rtx_CONST_DOUBLE (VOIDmode,
- INTVAL (op1) & ~(HOST_WIDE_INT)0x3ff,
- 0)));
+ immed_double_const (INTVAL (op1) & ~(HOST_WIDE_INT)0x3ff,
+ 0, DImode)));
else
emit_insn (gen_rtx_SET (VOIDmode, temp,
GEN_INT (INTVAL (op1)
@@ -1403,7 +1417,7 @@ sparc_emit_set_const32 (op0, op1)
}
-/* Sparc-v9 code-model support. */
+/* SPARC-v9 code-model support. */
void
sparc_emit_set_symbolic_const64 (op0, op1, temp1)
rtx op0;
@@ -1558,11 +1572,10 @@ static rtx gen_safe_XOR64 PARAMS ((rtx, HOST_WIDE_INT));
#define GEN_INT64(__x) GEN_INT (__x)
#else
#define GEN_HIGHINT64(__x) \
- gen_rtx_CONST_DOUBLE (VOIDmode, (__x) & ~(HOST_WIDE_INT)0x3ff, 0)
+ immed_double_const ((__x) & ~(HOST_WIDE_INT)0x3ff, 0, DImode)
#define GEN_INT64(__x) \
- gen_rtx_CONST_DOUBLE (VOIDmode, (__x) & 0xffffffff, \
- ((__x) & 0x80000000 \
- ? -1 : 0))
+ immed_double_const ((__x) & 0xffffffff, \
+ ((__x) & 0x80000000 ? -1 : 0), DImode)
#endif
/* The optimizer is not to assume anything about exactly
@@ -2132,9 +2145,9 @@ sparc_emit_set_const64 (op0, op1)
negated_const = GEN_INT (((~low_bits) & 0xfffffc00) |
(((HOST_WIDE_INT)((~high_bits) & 0xffffffff))<<32));
#else
- negated_const = gen_rtx_CONST_DOUBLE (DImode,
- (~low_bits) & 0xfffffc00,
- (~high_bits) & 0xffffffff);
+ negated_const = immed_double_const ((~low_bits) & 0xfffffc00,
+ (~high_bits) & 0xffffffff,
+ DImode);
#endif
sparc_emit_set_const64 (temp, negated_const);
}
@@ -3055,17 +3068,6 @@ check_return_regs (x)
}
-/* Return 1 if TRIAL references only in and global registers. */
-int
-eligible_for_return_delay (trial)
- rtx trial;
-{
- if (GET_CODE (PATTERN (trial)) != SET)
- return 0;
-
- return check_return_regs (PATTERN (trial));
-}
-
int
short_branch (uid1, uid2)
int uid1, uid2;
@@ -3079,7 +3081,7 @@ short_branch (uid1, uid2)
return 0;
}
-/* Return non-zero if REG is not used after INSN.
+/* Return nonzero if REG is not used after INSN.
We assume REG is a reload reg, and therefore does
not live past labels or calls or jumps. */
int
@@ -3115,10 +3117,10 @@ reg_unused_after (reg, insn)
}
/* The table we use to reference PIC data. */
-static rtx global_offset_table;
+static GTY(()) rtx global_offset_table;
/* The function we use to get at it. */
-static rtx get_pc_symbol;
+static GTY(()) rtx get_pc_symbol;
static char get_pc_symbol_name[256];
/* Ensure that we are not using patterns that are not OK with PIC. */
@@ -3163,7 +3165,7 @@ pic_address_needs_scratch (x)
/* Legitimize PIC addresses. If the address is already position-independent,
we return ORIG. Newly generated position-independent addresses go into a
- reg. This is REG if non zero, otherwise we allocate register(s) as
+ reg. This is REG if nonzero, otherwise we allocate register(s) as
necessary. */
rtx
@@ -3391,7 +3393,7 @@ mem_min_alignment (mem, desired)
/* Vectors to keep interesting information about registers where it can easily
- be got. We use to use the actual mode value as the bit number, but there
+ be got. We used to use the actual mode value as the bit number, but there
are more than 32 modes now. Instead we use two tables: one indexed by
hard register number, and one indexed by mode. */
@@ -4520,10 +4522,13 @@ function_arg_slotno (cum, mode, type, named, incoming_p, pregno, ppadding)
struct function_arg_record_value_parms
{
- rtx ret;
- int slotno, named, regbase;
- unsigned int nregs;
- int intoffset;
+ rtx ret; /* return expression being built. */
+ int slotno; /* slot number of the argument. */
+ int named; /* whether the argument is named. */
+ int regbase; /* regno of the base register. */
+ int stack; /* 1 if part of the argument is on the stack. */
+ int intoffset; /* offset of the pending integer field. */
+ unsigned int nregs; /* number of words passed in registers. */
};
static void function_arg_record_value_3
@@ -4598,8 +4603,13 @@ function_arg_record_value_1 (type, startbitpos, parms)
this_slotno = parms->slotno + parms->intoffset
/ BITS_PER_WORD;
- intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno);
- intslots = MAX (intslots, 0);
+ if (intslots > 0 && intslots > SPARC_INT_ARG_MAX - this_slotno)
+ {
+ intslots = MAX (0, SPARC_INT_ARG_MAX - this_slotno);
+ /* We need to pass this field on the stack. */
+ parms->stack = 1;
+ }
+
parms->nregs += intslots;
parms->intoffset = -1;
}
@@ -4664,7 +4674,7 @@ function_arg_record_value_3 (bitpos, parms)
{
regno = parms->regbase + this_slotno;
reg = gen_rtx_REG (mode, regno);
- XVECEXP (parms->ret, 0, parms->nregs)
+ XVECEXP (parms->ret, 0, parms->stack + parms->nregs)
= gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (intoffset));
this_slotno += 1;
@@ -4737,7 +4747,7 @@ function_arg_record_value_2 (type, startbitpos, parms)
default: break;
}
reg = gen_rtx_REG (mode, regno);
- XVECEXP (parms->ret, 0, parms->nregs)
+ XVECEXP (parms->ret, 0, parms->stack + parms->nregs)
= gen_rtx_EXPR_LIST (VOIDmode, reg,
GEN_INT (bitpos / BITS_PER_UNIT));
parms->nregs += 1;
@@ -4745,7 +4755,7 @@ function_arg_record_value_2 (type, startbitpos, parms)
{
regno += GET_MODE_SIZE (mode) / 4;
reg = gen_rtx_REG (mode, regno);
- XVECEXP (parms->ret, 0, parms->nregs)
+ XVECEXP (parms->ret, 0, parms->stack + parms->nregs)
= gen_rtx_EXPR_LIST (VOIDmode, reg,
GEN_INT ((bitpos + GET_MODE_BITSIZE (mode))
/ BITS_PER_UNIT));
@@ -4762,8 +4772,19 @@ function_arg_record_value_2 (type, startbitpos, parms)
}
/* Used by function_arg and function_value to implement the complex
- Sparc64 structure calling conventions. */
+ conventions of the 64-bit ABI for passing and returning structures.
+ Return an expression valid as a return value for the two macros
+ FUNCTION_ARG and FUNCTION_VALUE.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ MODE is the argument's machine mode.
+ SLOTNO is the index number of the argument's slot in the parameter array.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis).
+ REGBASE is the regno of the base register for the parameter array. */
+
static rtx
function_arg_record_value (type, mode, slotno, named, regbase)
tree type;
@@ -4778,6 +4799,7 @@ function_arg_record_value (type, mode, slotno, named, regbase)
parms.slotno = slotno;
parms.named = named;
parms.regbase = regbase;
+ parms.stack = 0;
/* Compute how many registers we need. */
parms.nregs = 0;
@@ -4794,8 +4816,12 @@ function_arg_record_value (type, mode, slotno, named, regbase)
intslots = (endbit - startbit) / BITS_PER_WORD;
this_slotno = slotno + parms.intoffset / BITS_PER_WORD;
- intslots = MIN (intslots, SPARC_INT_ARG_MAX - this_slotno);
- intslots = MAX (intslots, 0);
+ if (intslots > 0 && intslots > SPARC_INT_ARG_MAX - this_slotno)
+ {
+ intslots = MAX (0, SPARC_INT_ARG_MAX - this_slotno);
+ /* We need to pass this field on the stack. */
+ parms.stack = 1;
+ }
parms.nregs += intslots;
}
@@ -4825,7 +4851,17 @@ function_arg_record_value (type, mode, slotno, named, regbase)
if (nregs == 0)
abort ();
- parms.ret = gen_rtx_PARALLEL (mode, rtvec_alloc (nregs));
+ parms.ret = gen_rtx_PARALLEL (mode, rtvec_alloc (parms.stack + nregs));
+
+ /* If at least one field must be passed on the stack, generate
+ (parallel [(expr_list (nil) ...) ...]) so that all fields will
+ also be passed on the stack. We can't do much better because the
+ semantics of FUNCTION_ARG_PARTIAL_NREGS doesn't handle the case
+ of structures for which the fields passed exclusively in registers
+ are not at the beginning of the structure. */
+ if (parms.stack)
+ XVECEXP (parms.ret, 0, 0)
+ = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
/* Fill in the entries. */
parms.nregs = 0;
@@ -5249,13 +5285,12 @@ sparc_builtin_saveregs ()
/* Implement `va_start' for varargs and stdarg. */
void
-sparc_va_start (stdarg_p, valist, nextarg)
- int stdarg_p ATTRIBUTE_UNUSED;
+sparc_va_start (valist, nextarg)
tree valist;
rtx nextarg;
{
nextarg = expand_builtin_saveregs ();
- std_expand_builtin_va_start (1, valist, nextarg);
+ std_expand_builtin_va_start (valist, nextarg);
}
/* Implement `va_arg'. */
@@ -5353,7 +5388,8 @@ sparc_va_arg (valist, type)
PUT_MODE (tmp, BLKmode);
set_mem_alias_set (tmp, 0);
- dest_addr = emit_block_move (tmp, addr_rtx, GEN_INT (rsize));
+ dest_addr = emit_block_move (tmp, addr_rtx, GEN_INT (rsize),
+ BLOCK_OP_NORMAL);
if (dest_addr != NULL_RTX)
addr_rtx = dest_addr;
else
@@ -5375,11 +5411,11 @@ sparc_va_arg (valist, type)
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.
+ REVERSED is nonzero if we should reverse the sense of the comparison.
- ANNUL is non-zero if we should generate an annulling branch.
+ ANNUL is nonzero if we should generate an annulling branch.
- NOOP is non-zero if we have to follow this branch by a noop.
+ NOOP is nonzero if we have to follow this branch by a noop.
INSN, if set, is the insn. */
@@ -5808,11 +5844,11 @@ sparc_emit_floatunsdi (operands)
operand number of the reg. OP is the conditional expression. The mode
of REG says what kind of comparison we made.
- REVERSED is non-zero if we should reverse the sense of the comparison.
+ REVERSED is nonzero if we should reverse the sense of the comparison.
- ANNUL is non-zero if we should generate an annulling branch.
+ ANNUL is nonzero if we should generate an annulling branch.
- NOOP is non-zero if we have to follow this branch by a noop. */
+ NOOP is nonzero if we have to follow this branch by a noop. */
char *
output_v9branch (op, dest, reg, label, reversed, annul, noop, insn)
@@ -6462,6 +6498,24 @@ print_operand (file, x, code)
output_address (XEXP (x, 0));
return;
+ case 's':
+ {
+ /* Print a sign-extended 32-bit value. */
+ HOST_WIDE_INT i;
+ if (GET_CODE(x) == CONST_INT)
+ i = INTVAL (x);
+ else if (GET_CODE(x) == CONST_DOUBLE)
+ i = CONST_DOUBLE_LOW (x);
+ else
+ {
+ output_operand_lossage ("invalid %%s operand");
+ return;
+ }
+ i = trunc_int_for_mode (i, SImode);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, i);
+ return;
+ }
+
case 0:
/* Do nothing special. */
break;
@@ -6548,10 +6602,6 @@ sparc_assemble_integer (x, size, aligned_p)
what kind of result this function returns. For non-C types, we pick
the closest C type. */
-#ifndef CHAR_TYPE_SIZE
-#define CHAR_TYPE_SIZE BITS_PER_UNIT
-#endif
-
#ifndef SHORT_TYPE_SIZE
#define SHORT_TYPE_SIZE (BITS_PER_UNIT * 2)
#endif
@@ -6757,7 +6807,8 @@ sparc_initialize_trampoline (tramp, fnaddr, cxt)
/* On UltraSPARC a flush flushes an entire cache line. The trampoline is
aligned on a 16 byte boundary so one flush clears it all. */
emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode, tramp))));
- if (sparc_cpu != PROCESSOR_ULTRASPARC)
+ if (sparc_cpu != PROCESSOR_ULTRASPARC
+ && sparc_cpu != PROCESSOR_ULTRASPARC3)
emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode,
plus_constant (tramp, 8)))));
}
@@ -6795,7 +6846,8 @@ sparc64_initialize_trampoline (tramp, fnaddr, cxt)
emit_move_insn (gen_rtx_MEM (DImode, plus_constant (tramp, 24)), fnaddr);
emit_insn (gen_flushdi (validize_mem (gen_rtx_MEM (DImode, tramp))));
- if (sparc_cpu != PROCESSOR_ULTRASPARC)
+ if (sparc_cpu != PROCESSOR_ULTRASPARC
+ && sparc_cpu != PROCESSOR_ULTRASPARC3)
emit_insn (gen_flushdi (validize_mem (gen_rtx_MEM (DImode, plus_constant (tramp, 8)))));
}
@@ -7648,157 +7700,6 @@ hypersparc_adjust_cost (insn, link, dep_insn, cost)
}
static int
-ultrasparc_adjust_cost (insn, link, dep_insn, cost)
- rtx insn;
- rtx link;
- rtx dep_insn;
- int cost;
-{
- enum attr_type insn_type, dep_type;
- rtx pat = PATTERN(insn);
- rtx dep_pat = PATTERN (dep_insn);
-
- if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
- return cost;
-
- insn_type = get_attr_type (insn);
- dep_type = get_attr_type (dep_insn);
-
- /* Nothing issues in parallel with integer multiplies, so
- mark as zero cost since the scheduler can not do anything
- about it. */
- if (insn_type == TYPE_IMUL || insn_type == TYPE_IDIV)
- return 0;
-
-#define SLOW_FP(dep_type) \
-(dep_type == TYPE_FPSQRTS || dep_type == TYPE_FPSQRTD || \
- dep_type == TYPE_FPDIVS || dep_type == TYPE_FPDIVD)
-
- switch (REG_NOTE_KIND (link))
- {
- case 0:
- /* Data dependency; DEP_INSN writes a register that INSN reads some
- cycles later. */
-
- if (dep_type == TYPE_CMOVE)
- {
- /* Instructions that read the result of conditional moves cannot
- be in the same group or the following group. */
- return cost + 1;
- }
-
- switch (insn_type)
- {
- /* UltraSPARC can dual issue a store and an instruction setting
- the value stored, except for divide and square root. */
- case TYPE_FPSTORE:
- if (! SLOW_FP (dep_type))
- return 0;
- return cost;
-
- case TYPE_STORE:
- if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
- return cost;
-
- if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat)))
- /* The dependency between the two instructions is on the data
- that is being stored. Assume that the address of the store
- is not also dependent. */
- return 0;
- return cost;
-
- case TYPE_LOAD:
- case TYPE_SLOAD:
- case TYPE_FPLOAD:
- /* A load does not return data until at least 11 cycles after
- a store to the same location. 3 cycles are accounted for
- in the load latency; add the other 8 here. */
- if (dep_type == TYPE_STORE || dep_type == TYPE_FPSTORE)
- {
- /* If the addresses are not equal this may be a false
- dependency because pointer aliasing could not be
- determined. Add only 2 cycles in that case. 2 is
- an arbitrary compromise between 8, which would cause
- the scheduler to generate worse code elsewhere to
- compensate for a dependency which might not really
- exist, and 0. */
- if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET
- || GET_CODE (SET_SRC (pat)) != MEM
- || GET_CODE (SET_DEST (dep_pat)) != MEM
- || ! rtx_equal_p (XEXP (SET_SRC (pat), 0),
- XEXP (SET_DEST (dep_pat), 0)))
- return cost + 2;
-
- return cost + 8;
- }
- return cost;
-
- case TYPE_BRANCH:
- /* Compare to branch latency is 0. There is no benefit from
- separating compare and branch. */
- if (dep_type == TYPE_COMPARE)
- return 0;
- /* Floating point compare to branch latency is less than
- compare to conditional move. */
- if (dep_type == TYPE_FPCMP)
- return cost - 1;
- return cost;
-
- case TYPE_FPCMOVE:
- /* FMOVR class instructions can not issue in the same cycle
- or the cycle after an instruction which writes any
- integer register. Model this as cost 2 for dependent
- instructions. */
- if (dep_type == TYPE_IALU
- && cost < 2)
- return 2;
- /* Otherwise check as for integer conditional moves. */
-
- case TYPE_CMOVE:
- /* Conditional moves involving integer registers wait until
- 3 cycles after loads return data. The interlock applies
- to all loads, not just dependent loads, but that is hard
- to model. */
- if (dep_type == TYPE_LOAD || dep_type == TYPE_SLOAD)
- return cost + 3;
- return cost;
-
- default:
- break;
- }
- break;
-
- case REG_DEP_ANTI:
- /* Divide and square root lock destination registers for full latency. */
- if (! SLOW_FP (dep_type))
- return 0;
- break;
-
- case REG_DEP_OUTPUT:
- /* IEU and FPU instruction that have the same destination
- register cannot be grouped together. */
- return cost + 1;
-
- default:
- break;
- }
-
- /* Other costs not accounted for:
- - Single precision floating point loads lock the other half of
- the even/odd register pair.
- - Several hazards associated with ldd/std are ignored because these
- instructions are rarely generated for V9.
- - The floating point pipeline can not have both a single and double
- precision operation active at the same time. Format conversions
- and graphics instructions are given honorary double precision status.
- - call and jmpl are always the first instruction in a group. */
-
- return cost;
-
-#undef SLOW_FP
-}
-
-static int
sparc_adjust_cost(insn, link, dep, cost)
rtx insn;
rtx link;
@@ -7814,792 +7715,63 @@ sparc_adjust_cost(insn, link, dep, cost)
case PROCESSOR_SPARCLITE86X:
cost = hypersparc_adjust_cost (insn, link, dep, cost);
break;
- case PROCESSOR_ULTRASPARC:
- cost = ultrasparc_adjust_cost (insn, link, dep, cost);
- break;
default:
break;
}
return cost;
}
-/* This describes the state of the UltraSPARC pipeline during
- instruction scheduling. */
-
-#define TMASK(__x) ((unsigned)1 << ((int)(__x)))
-#define UMASK(__x) ((unsigned)1 << ((int)(__x)))
-
-enum ultra_code { NONE=0, /* no insn at all */
- IEU0, /* shifts and conditional moves */
- IEU1, /* condition code setting insns, calls+jumps */
- IEUN, /* all other single cycle ieu insns */
- LSU, /* loads and stores */
- CTI, /* branches */
- FPM, /* FPU pipeline 1, multiplies and divides */
- FPA, /* FPU pipeline 2, all other operations */
- SINGLE, /* single issue instructions */
- NUM_ULTRA_CODES };
-
-static enum ultra_code ultra_code_from_mask PARAMS ((int));
-static void ultra_schedule_insn PARAMS ((rtx *, rtx *, int, enum ultra_code));
-
-static const char *const ultra_code_names[NUM_ULTRA_CODES] = {
- "NONE", "IEU0", "IEU1", "IEUN", "LSU", "CTI",
- "FPM", "FPA", "SINGLE" };
-
-struct ultrasparc_pipeline_state {
- /* The insns in this group. */
- rtx group[4];
-
- /* The code for each insn. */
- enum ultra_code codes[4];
-
- /* Which insns in this group have been committed by the
- scheduler. This is how we determine how many more
- can issue this cycle. */
- char commit[4];
-
- /* How many insns in this group. */
- char group_size;
-
- /* Mask of free slots still in this group. */
- char free_slot_mask;
-
- /* The slotter uses the following to determine what other
- insn types can still make their way into this group. */
- char contents [NUM_ULTRA_CODES];
- char num_ieu_insns;
-};
-
-#define ULTRA_NUM_HIST 8
-static struct ultrasparc_pipeline_state ultra_pipe_hist[ULTRA_NUM_HIST];
-static int ultra_cur_hist;
-static int ultra_cycles_elapsed;
-
-#define ultra_pipe (ultra_pipe_hist[ultra_cur_hist])
-
-/* Given TYPE_MASK compute the ultra_code it has. */
-static enum ultra_code
-ultra_code_from_mask (type_mask)
- int type_mask;
-{
- if (type_mask & (TMASK (TYPE_SHIFT) | TMASK (TYPE_CMOVE)))
- return IEU0;
- else if (type_mask & (TMASK (TYPE_COMPARE) |
- TMASK (TYPE_CALL) |
- TMASK (TYPE_SIBCALL) |
- TMASK (TYPE_UNCOND_BRANCH)))
- return IEU1;
- else if (type_mask & TMASK (TYPE_IALU))
- return IEUN;
- else if (type_mask & (TMASK (TYPE_LOAD) | TMASK (TYPE_SLOAD) |
- TMASK (TYPE_STORE) | TMASK (TYPE_FPLOAD) |
- TMASK (TYPE_FPSTORE)))
- return LSU;
- else if (type_mask & (TMASK (TYPE_FPMUL) | TMASK (TYPE_FPDIVS) |
- TMASK (TYPE_FPDIVD) | TMASK (TYPE_FPSQRTS) |
- TMASK (TYPE_FPSQRTD)))
- return FPM;
- else if (type_mask & (TMASK (TYPE_FPMOVE) | TMASK (TYPE_FPCMOVE) |
- TMASK (TYPE_FP) | TMASK (TYPE_FPCMP)))
- return FPA;
- else if (type_mask & TMASK (TYPE_BRANCH))
- return CTI;
-
- return SINGLE;
-}
-
-/* Check INSN (a conditional move) and make sure that it's
- results are available at this cycle. Return 1 if the
- results are in fact ready. */
-static int
-ultra_cmove_results_ready_p (insn)
- rtx insn;
-{
- struct ultrasparc_pipeline_state *up;
- int entry, slot;
-
- /* If this got dispatched in the previous
- group, the results are not ready. */
- entry = (ultra_cur_hist - 1) & (ULTRA_NUM_HIST - 1);
- up = &ultra_pipe_hist[entry];
- slot = 4;
- while (--slot >= 0)
- if (up->group[slot] == insn)
- return 0;
-
- return 1;
-}
-
-/* Walk backwards in pipeline history looking for FPU
- operations which use a mode different than FPMODE and
- will create a stall if an insn using FPMODE were to be
- dispatched this cycle. */
-static int
-ultra_fpmode_conflict_exists (fpmode)
- enum machine_mode fpmode;
-{
- int hist_ent;
- int hist_lim;
-
- hist_ent = (ultra_cur_hist - 1) & (ULTRA_NUM_HIST - 1);
- if (ultra_cycles_elapsed < 4)
- hist_lim = ultra_cycles_elapsed;
- else
- hist_lim = 4;
- while (hist_lim > 0)
- {
- struct ultrasparc_pipeline_state *up = &ultra_pipe_hist[hist_ent];
- int slot = 4;
-
- while (--slot >= 0)
- {
- rtx insn = up->group[slot];
- enum machine_mode this_mode;
- rtx pat;
-
- if (! insn
- || GET_CODE (insn) != INSN
- || (pat = PATTERN (insn)) == 0
- || GET_CODE (pat) != SET)
- continue;
-
- this_mode = GET_MODE (SET_DEST (pat));
- if ((this_mode != SFmode
- && this_mode != DFmode)
- || this_mode == fpmode)
- continue;
-
- /* If it is not FMOV, FABS, FNEG, FDIV, or FSQRT then
- we will get a stall. Loads and stores are independent
- of these rules. */
- if (GET_CODE (SET_SRC (pat)) != ABS
- && GET_CODE (SET_SRC (pat)) != NEG
- && ((TMASK (get_attr_type (insn)) &
- (TMASK (TYPE_FPDIVS) | TMASK (TYPE_FPDIVD) |
- TMASK (TYPE_FPMOVE) | TMASK (TYPE_FPSQRTS) |
- TMASK (TYPE_FPSQRTD) |
- TMASK (TYPE_LOAD) | TMASK (TYPE_STORE))) == 0))
- return 1;
- }
- hist_lim--;
- hist_ent = (hist_ent - 1) & (ULTRA_NUM_HIST - 1);
- }
-
- /* No conflicts, safe to dispatch. */
- return 0;
-}
-
-/* Find an instruction in LIST which has one of the
- type attributes enumerated in TYPE_MASK. START
- says where to begin the search.
-
- NOTE: This scheme depends upon the fact that we
- have less than 32 distinct type attributes. */
-
-static int ultra_types_avail;
-
-static rtx *
-ultra_find_type (type_mask, list, start)
- int type_mask;
- rtx *list;
- int start;
-{
- int i;
-
- /* Short circuit if no such insn exists in the ready
- at the moment. */
- if ((type_mask & ultra_types_avail) == 0)
- return 0;
-
- for (i = start; i >= 0; i--)
- {
- rtx insn = list[i];
-
- if (recog_memoized (insn) >= 0
- && (TMASK(get_attr_type (insn)) & type_mask))
- {
- enum machine_mode fpmode = SFmode;
- rtx pat = 0;
- int slot;
- int check_depend = 0;
- int check_fpmode_conflict = 0;
-
- if (GET_CODE (insn) == INSN
- && (pat = PATTERN(insn)) != 0
- && GET_CODE (pat) == SET
- && !(type_mask & (TMASK (TYPE_STORE) |
- TMASK (TYPE_FPSTORE))))
- {
- check_depend = 1;
- if (GET_MODE (SET_DEST (pat)) == SFmode
- || GET_MODE (SET_DEST (pat)) == DFmode)
- {
- fpmode = GET_MODE (SET_DEST (pat));
- check_fpmode_conflict = 1;
- }
- }
-
- slot = 4;
- while(--slot >= 0)
- {
- rtx slot_insn = ultra_pipe.group[slot];
- rtx slot_pat;
-
- /* Already issued, bad dependency, or FPU
- mode conflict. */
- if (slot_insn != 0
- && (slot_pat = PATTERN (slot_insn)) != 0
- && ((insn == slot_insn)
- || (check_depend == 1
- && GET_CODE (slot_insn) == INSN
- && GET_CODE (slot_pat) == SET
- && ((GET_CODE (SET_DEST (slot_pat)) == REG
- && GET_CODE (SET_SRC (pat)) == REG
- && REGNO (SET_DEST (slot_pat)) ==
- REGNO (SET_SRC (pat)))
- || (GET_CODE (SET_DEST (slot_pat)) == SUBREG
- && GET_CODE (SET_SRC (pat)) == SUBREG
- && REGNO (SUBREG_REG (SET_DEST (slot_pat))) ==
- REGNO (SUBREG_REG (SET_SRC (pat)))
- && SUBREG_BYTE (SET_DEST (slot_pat)) ==
- SUBREG_BYTE (SET_SRC (pat)))))
- || (check_fpmode_conflict == 1
- && GET_CODE (slot_insn) == INSN
- && GET_CODE (slot_pat) == SET
- && (GET_MODE (SET_DEST (slot_pat)) == SFmode
- || GET_MODE (SET_DEST (slot_pat)) == DFmode)
- && GET_MODE (SET_DEST (slot_pat)) != fpmode)))
- goto next;
- }
-
- /* Check for peculiar result availability and dispatch
- interference situations. */
- if (pat != 0
- && ultra_cycles_elapsed > 0)
- {
- rtx link;
-
- for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
- {
- rtx link_insn = XEXP (link, 0);
- if (GET_CODE (link_insn) == INSN
- && recog_memoized (link_insn) >= 0
- && (TMASK (get_attr_type (link_insn)) &
- (TMASK (TYPE_CMOVE) | TMASK (TYPE_FPCMOVE)))
- && ! ultra_cmove_results_ready_p (link_insn))
- goto next;
- }
-
- if (check_fpmode_conflict
- && ultra_fpmode_conflict_exists (fpmode))
- goto next;
- }
-
- return &list[i];
- }
- next:
- ;
- }
- return 0;
-}
-
-static void
-ultra_build_types_avail (ready, n_ready)
- rtx *ready;
- int n_ready;
-{
- int i = n_ready - 1;
-
- ultra_types_avail = 0;
- while(i >= 0)
- {
- rtx insn = ready[i];
-
- if (recog_memoized (insn) >= 0)
- ultra_types_avail |= TMASK (get_attr_type (insn));
-
- i -= 1;
- }
-}
-
-/* Place insn pointed to my IP into the pipeline.
- Make element THIS of READY be that insn if it
- is not already. TYPE indicates the pipeline class
- this insn falls into. */
-static void
-ultra_schedule_insn (ip, ready, this, type)
- rtx *ip;
- rtx *ready;
- int this;
- enum ultra_code type;
-{
- int pipe_slot;
- char mask = ultra_pipe.free_slot_mask;
- rtx temp;
-
- /* Obtain free slot. */
- for (pipe_slot = 0; pipe_slot < 4; pipe_slot++)
- if ((mask & (1 << pipe_slot)) != 0)
- break;
- if (pipe_slot == 4)
- abort ();
-
- /* In it goes, and it hasn't been committed yet. */
- ultra_pipe.group[pipe_slot] = *ip;
- ultra_pipe.codes[pipe_slot] = type;
- ultra_pipe.contents[type] = 1;
- if (UMASK (type) &
- (UMASK (IEUN) | UMASK (IEU0) | UMASK (IEU1)))
- ultra_pipe.num_ieu_insns += 1;
-
- ultra_pipe.free_slot_mask = (mask & ~(1 << pipe_slot));
- ultra_pipe.group_size += 1;
- ultra_pipe.commit[pipe_slot] = 0;
-
- /* Update ready list. */
- temp = *ip;
- while (ip != &ready[this])
- {
- ip[0] = ip[1];
- ++ip;
- }
- *ip = temp;
-}
-
-/* Advance to the next pipeline group. */
-static void
-ultra_flush_pipeline ()
-{
- ultra_cur_hist = (ultra_cur_hist + 1) & (ULTRA_NUM_HIST - 1);
- ultra_cycles_elapsed += 1;
- memset ((char *) &ultra_pipe, 0, sizeof ultra_pipe);
- ultra_pipe.free_slot_mask = 0xf;
-}
-
-/* Init our data structures for this current block. */
-static void
-ultrasparc_sched_init ()
-{
- memset ((char *) ultra_pipe_hist, 0, sizeof ultra_pipe_hist);
- ultra_cur_hist = 0;
- ultra_cycles_elapsed = 0;
- ultra_pipe.free_slot_mask = 0xf;
-}
-
static void
sparc_sched_init (dump, sched_verbose, max_ready)
FILE *dump ATTRIBUTE_UNUSED;
int sched_verbose ATTRIBUTE_UNUSED;
int max_ready ATTRIBUTE_UNUSED;
{
- if (sparc_cpu == PROCESSOR_ULTRASPARC)
- ultrasparc_sched_init ();
}
-/* INSN has been scheduled, update pipeline commit state
- and return how many instructions are still to be
- scheduled in this group. */
static int
-ultrasparc_variable_issue (insn)
- rtx insn;
+sparc_use_dfa_pipeline_interface ()
{
- struct ultrasparc_pipeline_state *up = &ultra_pipe;
- int i, left_to_fire;
-
- left_to_fire = 0;
- for (i = 0; i < 4; i++)
- {
- if (up->group[i] == 0)
- continue;
-
- if (up->group[i] == insn)
- {
- up->commit[i] = 1;
- }
- else if (! up->commit[i])
- left_to_fire++;
- }
-
- return left_to_fire;
+ if ((1 << sparc_cpu) &
+ ((1 << PROCESSOR_ULTRASPARC) | (1 << PROCESSOR_CYPRESS) |
+ (1 << PROCESSOR_SUPERSPARC) | (1 << PROCESSOR_HYPERSPARC) |
+ (1 << PROCESSOR_SPARCLITE86X) | (1 << PROCESSOR_TSC701) |
+ (1 << PROCESSOR_ULTRASPARC3)))
+ return 1;
+ return 0;
}
static int
-sparc_variable_issue (dump, sched_verbose, insn, cim)
- FILE *dump ATTRIBUTE_UNUSED;
- int sched_verbose ATTRIBUTE_UNUSED;
- rtx insn;
- int cim;
-{
- if (sparc_cpu == PROCESSOR_ULTRASPARC)
- return ultrasparc_variable_issue (insn);
- else
- return cim - 1;
-}
-
-/* In actual_hazard_this_instance, we may have yanked some
- instructions from the ready list due to conflict cost
- adjustments. If so, and such an insn was in our pipeline
- group, remove it and update state. */
-static void
-ultra_rescan_pipeline_state (ready, n_ready)
- rtx *ready;
- int n_ready;
-{
- struct ultrasparc_pipeline_state *up = &ultra_pipe;
- int i;
-
- for (i = 0; i < 4; i++)
- {
- rtx insn = up->group[i];
- int j;
-
- if (! insn)
- continue;
-
- /* If it has been committed, then it was removed from
- the ready list because it was actually scheduled,
- and that is not the case we are searching for here. */
- if (up->commit[i] != 0)
- continue;
-
- for (j = n_ready - 1; j >= 0; j--)
- if (ready[j] == insn)
- break;
-
- /* If we didn't find it, toss it. */
- if (j < 0)
- {
- enum ultra_code ucode = up->codes[i];
-
- up->group[i] = 0;
- up->codes[i] = NONE;
- up->contents[ucode] = 0;
- if (UMASK (ucode) &
- (UMASK (IEUN) | UMASK (IEU0) | UMASK (IEU1)))
- up->num_ieu_insns -= 1;
-
- up->free_slot_mask |= (1 << i);
- up->group_size -= 1;
- up->commit[i] = 0;
- }
- }
-}
-
-static void
-ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready)
- FILE *dump;
- int sched_verbose;
- rtx *ready;
- int n_ready;
-{
- struct ultrasparc_pipeline_state *up = &ultra_pipe;
- int i, this_insn;
-
- if (sched_verbose)
- {
- int n;
-
- fprintf (dump, "\n;;\tUltraSPARC Looking at [");
- for (n = n_ready - 1; n >= 0; n--)
- {
- rtx insn = ready[n];
- enum ultra_code ucode;
-
- if (recog_memoized (insn) < 0)
- continue;
- ucode = ultra_code_from_mask (TMASK (get_attr_type (insn)));
- if (n != 0)
- fprintf (dump, "%s(%d) ",
- ultra_code_names[ucode],
- INSN_UID (insn));
- else
- fprintf (dump, "%s(%d)",
- ultra_code_names[ucode],
- INSN_UID (insn));
- }
- fprintf (dump, "]\n");
- }
-
- this_insn = n_ready - 1;
-
- /* Skip over junk we don't understand. */
- while ((this_insn >= 0)
- && recog_memoized (ready[this_insn]) < 0)
- this_insn--;
-
- ultra_build_types_avail (ready, this_insn + 1);
-
- while (this_insn >= 0) {
- int old_group_size = up->group_size;
-
- if (up->group_size != 0)
- {
- int num_committed;
-
- num_committed = (up->commit[0] + up->commit[1] +
- up->commit[2] + up->commit[3]);
- /* If nothing has been commited from our group, or all of
- them have. Clear out the (current cycle's) pipeline
- state and start afresh. */
- if (num_committed == 0
- || num_committed == up->group_size)
- {
- ultra_flush_pipeline ();
- up = &ultra_pipe;
- old_group_size = 0;
- }
- else
- {
- /* OK, some ready list insns got requeued and thus removed
- from the ready list. Account for this fact. */
- ultra_rescan_pipeline_state (ready, n_ready);
-
- /* Something "changed", make this look like a newly
- formed group so the code at the end of the loop
- knows that progress was in fact made. */
- if (up->group_size != old_group_size)
- old_group_size = 0;
- }
- }
-
- if (up->group_size == 0)
- {
- /* If the pipeline is (still) empty and we have any single
- group insns, get them out now as this is a good time. */
- rtx *ip = ultra_find_type ((TMASK (TYPE_RETURN) | TMASK (TYPE_IDIV) |
- TMASK (TYPE_IMUL) | TMASK (TYPE_CMOVE) |
- TMASK (TYPE_MULTI) | TMASK (TYPE_MISC)),
- ready, this_insn);
- if (ip)
- {
- ultra_schedule_insn (ip, ready, this_insn, SINGLE);
- break;
- }
-
- /* If we are not in the process of emptying out the pipe, try to
- obtain an instruction which must be the first in it's group. */
- ip = ultra_find_type ((TMASK (TYPE_CALL) |
- TMASK (TYPE_SIBCALL) |
- TMASK (TYPE_CALL_NO_DELAY_SLOT) |
- TMASK (TYPE_UNCOND_BRANCH)),
- ready, this_insn);
- if (ip)
- {
- ultra_schedule_insn (ip, ready, this_insn, IEU1);
- this_insn--;
- }
- else if ((ip = ultra_find_type ((TMASK (TYPE_FPDIVS) |
- TMASK (TYPE_FPDIVD) |
- TMASK (TYPE_FPSQRTS) |
- TMASK (TYPE_FPSQRTD)),
- ready, this_insn)) != 0)
- {
- ultra_schedule_insn (ip, ready, this_insn, FPM);
- this_insn--;
- }
- }
-
- /* Try to fill the integer pipeline. First, look for an IEU0 specific
- operation. We can't do more IEU operations if the first 3 slots are
- all full or we have dispatched two IEU insns already. */
- if ((up->free_slot_mask & 0x7) != 0
- && up->num_ieu_insns < 2
- && up->contents[IEU0] == 0
- && up->contents[IEUN] == 0)
- {
- rtx *ip = ultra_find_type (TMASK(TYPE_SHIFT), ready, this_insn);
- if (ip)
- {
- ultra_schedule_insn (ip, ready, this_insn, IEU0);
- this_insn--;
- }
- }
-
- /* If we can, try to find an IEU1 specific or an unnamed
- IEU instruction. */
- if ((up->free_slot_mask & 0x7) != 0
- && up->num_ieu_insns < 2)
- {
- rtx *ip = ultra_find_type ((TMASK (TYPE_IALU) |
- (up->contents[IEU1] == 0 ? TMASK (TYPE_COMPARE) : 0)),
- ready, this_insn);
- if (ip)
- {
- rtx insn = *ip;
-
- ultra_schedule_insn (ip, ready, this_insn,
- (!up->contents[IEU1]
- && get_attr_type (insn) == TYPE_COMPARE)
- ? IEU1 : IEUN);
- this_insn--;
- }
- }
-
- /* If only one IEU insn has been found, try to find another unnamed
- IEU operation or an IEU1 specific one. */
- if ((up->free_slot_mask & 0x7) != 0
- && up->num_ieu_insns < 2)
- {
- rtx *ip;
- int tmask = TMASK (TYPE_IALU);
-
- if (!up->contents[IEU1])
- tmask |= TMASK (TYPE_COMPARE);
- ip = ultra_find_type (tmask, ready, this_insn);
- if (ip)
- {
- rtx insn = *ip;
-
- ultra_schedule_insn (ip, ready, this_insn,
- (!up->contents[IEU1]
- && get_attr_type (insn) == TYPE_COMPARE)
- ? IEU1 : IEUN);
- this_insn--;
- }
- }
-
- /* Try for a load or store, but such an insn can only be issued
- if it is within' one of the first 3 slots. */
- if ((up->free_slot_mask & 0x7) != 0
- && up->contents[LSU] == 0)
- {
- rtx *ip = ultra_find_type ((TMASK (TYPE_LOAD) | TMASK (TYPE_SLOAD) |
- TMASK (TYPE_STORE) | TMASK (TYPE_FPLOAD) |
- TMASK (TYPE_FPSTORE)), ready, this_insn);
- if (ip)
- {
- ultra_schedule_insn (ip, ready, this_insn, LSU);
- this_insn--;
- }
- }
-
- /* Now find FPU operations, first FPM class. But not divisions or
- square-roots because those will break the group up. Unlike all
- the previous types, these can go in any slot. */
- if (up->free_slot_mask != 0
- && up->contents[FPM] == 0)
- {
- rtx *ip = ultra_find_type (TMASK (TYPE_FPMUL), ready, this_insn);
- if (ip)
- {
- ultra_schedule_insn (ip, ready, this_insn, FPM);
- this_insn--;
- }
- }
-
- /* Continue on with FPA class if we have not filled the group already. */
- if (up->free_slot_mask != 0
- && up->contents[FPA] == 0)
- {
- rtx *ip = ultra_find_type ((TMASK (TYPE_FPMOVE) | TMASK (TYPE_FPCMOVE) |
- TMASK (TYPE_FP) | TMASK (TYPE_FPCMP)),
- ready, this_insn);
- if (ip)
- {
- ultra_schedule_insn (ip, ready, this_insn, FPA);
- this_insn--;
- }
- }
-
- /* Finally, maybe stick a branch in here. */
- if (up->free_slot_mask != 0
- && up->contents[CTI] == 0)
- {
- rtx *ip = ultra_find_type (TMASK (TYPE_BRANCH), ready, this_insn);
-
- /* Try to slip in a branch only if it is one of the
- next 2 in the ready list. */
- if (ip && ((&ready[this_insn] - ip) < 2))
- {
- ultra_schedule_insn (ip, ready, this_insn, CTI);
- this_insn--;
- }
- }
-
- up->group_size = 0;
- for (i = 0; i < 4; i++)
- if ((up->free_slot_mask & (1 << i)) == 0)
- up->group_size++;
-
- /* See if we made any progress... */
- if (old_group_size != up->group_size)
- break;
-
- /* Clean out the (current cycle's) pipeline state
- and try once more. If we placed no instructions
- into the pipeline at all, it means a real hard
- conflict exists with some earlier issued instruction
- so we must advance to the next cycle to clear it up. */
- if (up->group_size == 0)
- {
- ultra_flush_pipeline ();
- up = &ultra_pipe;
- }
- else
- {
- memset ((char *) &ultra_pipe, 0, sizeof ultra_pipe);
- ultra_pipe.free_slot_mask = 0xf;
- }
- }
-
- if (sched_verbose)
- {
- int n, gsize;
-
- fprintf (dump, ";;\tUltraSPARC Launched [");
- gsize = up->group_size;
- for (n = 0; n < 4; n++)
- {
- rtx insn = up->group[n];
-
- if (! insn)
- continue;
-
- gsize -= 1;
- if (gsize != 0)
- fprintf (dump, "%s(%d) ",
- ultra_code_names[up->codes[n]],
- INSN_UID (insn));
- else
- fprintf (dump, "%s(%d)",
- ultra_code_names[up->codes[n]],
- INSN_UID (insn));
- }
- fprintf (dump, "]\n");
- }
+sparc_use_sched_lookahead ()
+{
+ if (sparc_cpu == PROCESSOR_ULTRASPARC
+ || sparc_cpu == PROCESSOR_ULTRASPARC3)
+ return 4;
+ if ((1 << sparc_cpu) &
+ ((1 << PROCESSOR_SUPERSPARC) | (1 << PROCESSOR_HYPERSPARC) |
+ (1 << PROCESSOR_SPARCLITE86X)))
+ return 3;
+ return 0;
}
static int
-sparc_sched_reorder (dump, sched_verbose, ready, n_readyp, clock)
- FILE *dump;
- int sched_verbose;
- rtx *ready;
- int *n_readyp;
- int clock ATTRIBUTE_UNUSED;
-{
- if (sparc_cpu == PROCESSOR_ULTRASPARC)
- ultrasparc_sched_reorder (dump, sched_verbose, ready, *n_readyp);
- return sparc_issue_rate ();
-}
-
-static int
sparc_issue_rate ()
{
switch (sparc_cpu)
{
- default:
- return 1;
- case PROCESSOR_V9:
+ default:
+ return 1;
+ case PROCESSOR_V9:
/* Assume V9 processors are capable of at least dual-issue. */
return 2;
- case PROCESSOR_SUPERSPARC:
- return 3;
+ case PROCESSOR_SUPERSPARC:
+ return 3;
case PROCESSOR_HYPERSPARC:
case PROCESSOR_SPARCLITE86X:
return 2;
- case PROCESSOR_ULTRASPARC:
- return 4;
+ case PROCESSOR_ULTRASPARC:
+ case PROCESSOR_ULTRASPARC3:
+ return 4;
}
}
@@ -8668,8 +7840,8 @@ set_extends (insn)
}
/* We _ought_ to have only one kind per function, but... */
-static rtx sparc_addr_diff_list;
-static rtx sparc_addr_list;
+static GTY(()) rtx sparc_addr_diff_list;
+static GTY(()) rtx sparc_addr_list;
void
sparc_defer_case_vector (lab, vec, diff)
@@ -8833,6 +8005,8 @@ sparc_check_64 (x, insn)
return 0;
}
+/* Returns assembly code to perform a DImode shift using
+ a 64-bit global or out register on SPARC-V8+. */
char *
sparc_v8plus_shift (operands, insn, opcode)
rtx *operands;
@@ -8841,8 +8015,11 @@ sparc_v8plus_shift (operands, insn, opcode)
{
static char asm_code[60];
- if (GET_CODE (operands[3]) == SCRATCH)
+ /* The scratch register is only required when the destination
+ register is not a 64-bit global or out register. */
+ if (which_alternative != 2)
operands[3] = operands[0];
+
if (GET_CODE (operands[1]) == CONST_INT)
{
output_asm_insn ("mov\t%1, %3", operands);
@@ -8856,6 +8033,7 @@ sparc_v8plus_shift (operands, insn, opcode)
}
strcpy(asm_code, opcode);
+
if (which_alternative != 2)
return strcat (asm_code, "\t%0, %2, %L0\n\tsrlx\t%L0, 32, %H0");
else
@@ -8879,37 +8057,6 @@ sparc_profile_hook (labelno)
emit_library_call (fun, LCT_NORMAL, VOIDmode, 1, lab, Pmode);
}
-/* Mark ARG, which is really a struct ultrasparc_pipline_state *, for
- GC. */
-
-static void
-mark_ultrasparc_pipeline_state (arg)
- void *arg;
-{
- struct ultrasparc_pipeline_state *ups;
- size_t i;
-
- ups = (struct ultrasparc_pipeline_state *) arg;
- for (i = 0; i < sizeof (ups->group) / sizeof (rtx); ++i)
- ggc_mark_rtx (ups->group[i]);
-}
-
-/* Called to register all of our global variables with the garbage
- collector. */
-
-static void
-sparc_add_gc_roots ()
-{
- ggc_add_rtx_root (&sparc_compare_op0, 1);
- ggc_add_rtx_root (&sparc_compare_op1, 1);
- ggc_add_rtx_root (&global_offset_table, 1);
- ggc_add_rtx_root (&get_pc_symbol, 1);
- ggc_add_rtx_root (&sparc_addr_diff_list, 1);
- ggc_add_rtx_root (&sparc_addr_list, 1);
- ggc_add_root (ultra_pipe_hist, ARRAY_SIZE (ultra_pipe_hist),
- sizeof (ultra_pipe_hist[0]), &mark_ultrasparc_pipeline_state);
-}
-
#ifdef OBJECT_FORMAT_ELF
static void
sparc_elf_asm_named_section (name, flags)
@@ -8939,6 +8086,36 @@ sparc_elf_asm_named_section (name, flags)
}
#endif /* OBJECT_FORMAT_ELF */
+/* ??? Similar to the standard section selection, but force reloc-y-ness
+ if SUNOS4_SHARED_LIBRARIES. Unclear why this helps (as opposed to
+ pretending PIC always on), but that's what the old code did. */
+
+static void
+sparc_aout_select_section (t, reloc, align)
+ tree t;
+ int reloc;
+ unsigned HOST_WIDE_INT align;
+{
+ default_select_section (t, reloc | SUNOS4_SHARED_LIBRARIES, align);
+}
+
+/* Use text section for a constant unless we need more alignment than
+ that offers. */
+
+static void
+sparc_aout_select_rtx_section (mode, x, align)
+ enum machine_mode mode;
+ rtx x;
+ unsigned HOST_WIDE_INT align;
+{
+ if (align <= MAX_TEXT_ALIGN
+ && ! (flag_pic && (symbolic_operand (x, mode)
+ || SUNOS4_SHARED_LIBRARIES)))
+ readonly_data_section ();
+ else
+ data_section ();
+}
+
int
sparc_extra_constraint_check (op, c, strict)
rtx op;
@@ -9001,14 +8178,347 @@ sparc_extra_constraint_check (op, c, strict)
return reload_ok_mem;
}
+/* ??? This duplicates information provided to the compiler by the
+ ??? scheduler description. Some day, teach genautomata to output
+ ??? the latencies and then CSE will just use that. */
+
+int
+sparc_rtx_costs (x, code, outer_code)
+ rtx x;
+ enum rtx_code code, outer_code;
+{
+ switch (code)
+ {
+ case PLUS: case MINUS: case ABS: case NEG:
+ case FLOAT: case UNSIGNED_FLOAT:
+ case FIX: case UNSIGNED_FIX:
+ case FLOAT_EXTEND: case FLOAT_TRUNCATE:
+ if (FLOAT_MODE_P (GET_MODE (x)))
+ {
+ switch (sparc_cpu)
+ {
+ case PROCESSOR_ULTRASPARC:
+ case PROCESSOR_ULTRASPARC3:
+ return COSTS_N_INSNS (4);
+
+ case PROCESSOR_SUPERSPARC:
+ return COSTS_N_INSNS (3);
+
+ case PROCESSOR_CYPRESS:
+ return COSTS_N_INSNS (5);
+
+ case PROCESSOR_HYPERSPARC:
+ case PROCESSOR_SPARCLITE86X:
+ default:
+ return COSTS_N_INSNS (1);
+ }
+ }
+
+ return COSTS_N_INSNS (1);
+
+ case SQRT:
+ switch (sparc_cpu)
+ {
+ case PROCESSOR_ULTRASPARC:
+ if (GET_MODE (x) == SFmode)
+ return COSTS_N_INSNS (13);
+ else
+ return COSTS_N_INSNS (23);
+
+ case PROCESSOR_ULTRASPARC3:
+ if (GET_MODE (x) == SFmode)
+ return COSTS_N_INSNS (20);
+ else
+ return COSTS_N_INSNS (29);
+
+ case PROCESSOR_SUPERSPARC:
+ return COSTS_N_INSNS (12);
+
+ case PROCESSOR_CYPRESS:
+ return COSTS_N_INSNS (63);
+
+ case PROCESSOR_HYPERSPARC:
+ case PROCESSOR_SPARCLITE86X:
+ return COSTS_N_INSNS (17);
+
+ default:
+ return COSTS_N_INSNS (30);
+ }
+
+ case COMPARE:
+ if (FLOAT_MODE_P (GET_MODE (x)))
+ {
+ switch (sparc_cpu)
+ {
+ case PROCESSOR_ULTRASPARC:
+ case PROCESSOR_ULTRASPARC3:
+ return COSTS_N_INSNS (1);
+
+ case PROCESSOR_SUPERSPARC:
+ return COSTS_N_INSNS (3);
+
+ case PROCESSOR_CYPRESS:
+ return COSTS_N_INSNS (5);
+
+ case PROCESSOR_HYPERSPARC:
+ case PROCESSOR_SPARCLITE86X:
+ default:
+ return COSTS_N_INSNS (1);
+ }
+ }
+
+ /* ??? Maybe mark integer compares as zero cost on
+ ??? all UltraSPARC processors because the result
+ ??? can be bypassed to a branch in the same group. */
+
+ return COSTS_N_INSNS (1);
+
+ case MULT:
+ if (FLOAT_MODE_P (GET_MODE (x)))
+ {
+ switch (sparc_cpu)
+ {
+ case PROCESSOR_ULTRASPARC:
+ case PROCESSOR_ULTRASPARC3:
+ return COSTS_N_INSNS (4);
+
+ case PROCESSOR_SUPERSPARC:
+ return COSTS_N_INSNS (3);
+
+ case PROCESSOR_CYPRESS:
+ return COSTS_N_INSNS (7);
+
+ case PROCESSOR_HYPERSPARC:
+ case PROCESSOR_SPARCLITE86X:
+ return COSTS_N_INSNS (1);
+
+ default:
+ return COSTS_N_INSNS (5);
+ }
+ }
+
+ /* The latency is actually variable for Ultra-I/II
+ And if one of the inputs have a known constant
+ value, we could calculate this precisely.
+
+ However, for that to be useful we would need to
+ add some machine description changes which would
+ make sure small constants ended up in rs1 of the
+ multiply instruction. This is because the multiply
+ latency is determined by the number of clear (or
+ set if the value is negative) bits starting from
+ the most significant bit of the first input.
+
+ The algorithm for computing num_cycles of a multiply
+ on Ultra-I/II is:
+
+ if (rs1 < 0)
+ highest_bit = highest_clear_bit(rs1);
+ else
+ highest_bit = highest_set_bit(rs1);
+ if (num_bits < 3)
+ highest_bit = 3;
+ num_cycles = 4 + ((highest_bit - 3) / 2);
+
+ If we did that we would have to also consider register
+ allocation issues that would result from forcing such
+ a value into a register.
+
+ There are other similar tricks we could play if we
+ knew, for example, that one input was an array index.
+
+ Since we do not play any such tricks currently the
+ safest thing to do is report the worst case latency. */
+ if (sparc_cpu == PROCESSOR_ULTRASPARC)
+ return (GET_MODE (x) == DImode ?
+ COSTS_N_INSNS (34) : COSTS_N_INSNS (19));
+
+ /* Multiply latency on Ultra-III, fortunately, is constant. */
+ if (sparc_cpu == PROCESSOR_ULTRASPARC3)
+ return COSTS_N_INSNS (6);
+
+ if (sparc_cpu == PROCESSOR_HYPERSPARC
+ || sparc_cpu == PROCESSOR_SPARCLITE86X)
+ return COSTS_N_INSNS (17);
+
+ return (TARGET_HARD_MUL
+ ? COSTS_N_INSNS (5)
+ : COSTS_N_INSNS (25));
+
+ case DIV:
+ case UDIV:
+ case MOD:
+ case UMOD:
+ if (FLOAT_MODE_P (GET_MODE (x)))
+ {
+ switch (sparc_cpu)
+ {
+ case PROCESSOR_ULTRASPARC:
+ if (GET_MODE (x) == SFmode)
+ return COSTS_N_INSNS (13);
+ else
+ return COSTS_N_INSNS (23);
+
+ case PROCESSOR_ULTRASPARC3:
+ if (GET_MODE (x) == SFmode)
+ return COSTS_N_INSNS (17);
+ else
+ return COSTS_N_INSNS (20);
+
+ case PROCESSOR_SUPERSPARC:
+ if (GET_MODE (x) == SFmode)
+ return COSTS_N_INSNS (6);
+ else
+ return COSTS_N_INSNS (9);
+
+ case PROCESSOR_HYPERSPARC:
+ case PROCESSOR_SPARCLITE86X:
+ if (GET_MODE (x) == SFmode)
+ return COSTS_N_INSNS (8);
+ else
+ return COSTS_N_INSNS (12);
+
+ default:
+ return COSTS_N_INSNS (7);
+ }
+ }
+
+ if (sparc_cpu == PROCESSOR_ULTRASPARC)
+ return (GET_MODE (x) == DImode ?
+ COSTS_N_INSNS (68) : COSTS_N_INSNS (37));
+ if (sparc_cpu == PROCESSOR_ULTRASPARC3)
+ return (GET_MODE (x) == DImode ?
+ COSTS_N_INSNS (71) : COSTS_N_INSNS (40));
+ return COSTS_N_INSNS (25);
+
+ case IF_THEN_ELSE:
+ /* Conditional moves. */
+ switch (sparc_cpu)
+ {
+ case PROCESSOR_ULTRASPARC:
+ return COSTS_N_INSNS (2);
+
+ case PROCESSOR_ULTRASPARC3:
+ if (FLOAT_MODE_P (GET_MODE (x)))
+ return COSTS_N_INSNS (3);
+ else
+ return COSTS_N_INSNS (2);
+
+ default:
+ return COSTS_N_INSNS (1);
+ }
+
+ case MEM:
+ /* If outer-code is SIGN/ZERO extension we have to subtract
+ out COSTS_N_INSNS (1) from whatever we return in determining
+ the cost. */
+ switch (sparc_cpu)
+ {
+ case PROCESSOR_ULTRASPARC:
+ if (outer_code == ZERO_EXTEND)
+ return COSTS_N_INSNS (1);
+ else
+ return COSTS_N_INSNS (2);
+
+ case PROCESSOR_ULTRASPARC3:
+ if (outer_code == ZERO_EXTEND)
+ {
+ if (GET_MODE (x) == QImode
+ || GET_MODE (x) == HImode
+ || outer_code == SIGN_EXTEND)
+ return COSTS_N_INSNS (2);
+ else
+ return COSTS_N_INSNS (1);
+ }
+ else
+ {
+ /* This handles sign extension (3 cycles)
+ and everything else (2 cycles). */
+ return COSTS_N_INSNS (2);
+ }
+
+ case PROCESSOR_SUPERSPARC:
+ if (FLOAT_MODE_P (GET_MODE (x))
+ || outer_code == ZERO_EXTEND
+ || outer_code == SIGN_EXTEND)
+ return COSTS_N_INSNS (0);
+ else
+ return COSTS_N_INSNS (1);
+
+ case PROCESSOR_TSC701:
+ if (outer_code == ZERO_EXTEND
+ || outer_code == SIGN_EXTEND)
+ return COSTS_N_INSNS (2);
+ else
+ return COSTS_N_INSNS (3);
+
+ case PROCESSOR_CYPRESS:
+ if (outer_code == ZERO_EXTEND
+ || outer_code == SIGN_EXTEND)
+ return COSTS_N_INSNS (1);
+ else
+ return COSTS_N_INSNS (2);
+
+ case PROCESSOR_HYPERSPARC:
+ case PROCESSOR_SPARCLITE86X:
+ default:
+ if (outer_code == ZERO_EXTEND
+ || outer_code == SIGN_EXTEND)
+ return COSTS_N_INSNS (0);
+ else
+ return COSTS_N_INSNS (1);
+ }
+
+ case CONST_INT:
+ if (INTVAL (x) < 0x1000 && INTVAL (x) >= -0x1000)
+ return 0;
+
+ /* fallthru */
+ case HIGH:
+ return 2;
+
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ return 4;
+
+ case CONST_DOUBLE:
+ if (GET_MODE (x) == DImode)
+ if ((XINT (x, 3) == 0
+ && (unsigned) XINT (x, 2) < 0x1000)
+ || (XINT (x, 3) == -1
+ && XINT (x, 2) < 0
+ && XINT (x, 2) >= -0x1000))
+ return 0;
+ return 8;
+
+ default:
+ abort();
+ };
+}
+
+/* If we are referencing a function make the SYMBOL_REF special. In
+ the Embedded Medium/Anywhere code model, %g4 points to the data
+ segment so we must not add it to function addresses. */
+
+static void
+sparc_encode_section_info (decl, first)
+ tree decl;
+ int first ATTRIBUTE_UNUSED;
+{
+ if (TARGET_CM_EMBMEDANY && TREE_CODE (decl) == FUNCTION_DECL)
+ SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
+}
+
/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
Used for C++ multiple inheritance. */
-void
-sparc_output_mi_thunk (file, thunk_fndecl, delta, function)
+static void
+sparc_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
FILE *file;
tree thunk_fndecl ATTRIBUTE_UNUSED;
HOST_WIDE_INT delta;
+ HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
tree function;
{
rtx this, insn, funexp, delta_rtx, tmp;
@@ -9067,3 +8577,5 @@ sparc_output_mi_thunk (file, thunk_fndecl, delta, function)
reload_completed = 0;
no_new_pseudos = 0;
}
+
+#include "gt-sparc.h"
diff --git a/contrib/gcc/config/sparc/sparc.h b/contrib/gcc/config/sparc/sparc.h
index 2902f06..7c6a7fd 100644
--- a/contrib/gcc/config/sparc/sparc.h
+++ b/contrib/gcc/config/sparc/sparc.h
@@ -107,7 +107,7 @@ extern enum cmodel sparc_cmodel;
/* Values of TARGET_CPU_DEFAULT, set via -D in the Makefile,
and specified by the user via --with-cpu=foo.
This specifies the cpu implementation, not the architecture size. */
-/* Note that TARGET_CPU_v9 is assumed to start the list of 64-bit
+/* Note that TARGET_CPU_v9 is assumed to start the list of 64-bit
capable cpu's. */
#define TARGET_CPU_sparc 0
#define TARGET_CPU_v7 0 /* alias for previous */
@@ -122,9 +122,11 @@ extern enum cmodel sparc_cmodel;
#define TARGET_CPU_sparcv9 7 /* alias */
#define TARGET_CPU_sparc64 7 /* alias */
#define TARGET_CPU_ultrasparc 8
+#define TARGET_CPU_ultrasparc3 9
#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
- || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3
#define CPP_CPU32_DEFAULT_SPEC ""
#define ASM_CPU32_DEFAULT_SPEC ""
@@ -141,6 +143,10 @@ extern enum cmodel sparc_cmodel;
#define CPP_CPU64_DEFAULT_SPEC "-D__sparc_v9__"
#define ASM_CPU64_DEFAULT_SPEC "-Av9a"
#endif
+#if TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3
+#define CPP_CPU64_DEFAULT_SPEC "-D__sparc_v9__"
+#define ASM_CPU64_DEFAULT_SPEC "-Av9b"
+#endif
#else
@@ -181,7 +187,7 @@ extern enum cmodel sparc_cmodel;
#endif
#if !defined(CPP_CPU32_DEFAULT_SPEC) || !defined(CPP_CPU64_DEFAULT_SPEC)
-Unrecognized value in TARGET_CPU_DEFAULT.
+ #error Unrecognized value in TARGET_CPU_DEFAULT.
#endif
#ifdef SPARC_BI_ARCH
@@ -230,6 +236,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
%{mcpu=sparclite86x:-D__sparclite86x__} \
%{mcpu=v9:-D__sparc_v9__} \
%{mcpu=ultrasparc:-D__sparc_v9__} \
+%{mcpu=ultrasparc3:-D__sparc_v9__} \
%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \
"
@@ -239,20 +246,9 @@ Unrecognized value in TARGET_CPU_DEFAULT.
sparc64 in 32 bit environments, so for now we only use `sparc64' in
64 bit environments. */
-#ifdef SPARC_BI_ARCH
-
-#define CPP_ARCH32_SPEC "-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int \
--D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc"
-#define CPP_ARCH64_SPEC "-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int \
--D__arch64__ -Acpu=sparc64 -Amachine=sparc64"
-
-#else
-
#define CPP_ARCH32_SPEC "-D__GCC_NEW_VARARGS__ -Acpu=sparc -Amachine=sparc"
#define CPP_ARCH64_SPEC "-D__arch64__ -Acpu=sparc64 -Amachine=sparc64"
-#endif
-
#define CPP_ARCH_DEFAULT_SPEC \
(DEFAULT_ARCH32_P ? CPP_ARCH32_SPEC : CPP_ARCH64_SPEC)
@@ -296,6 +292,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
%{mv8plus:-Av8plus} \
%{mcpu=v9:-Av9} \
%{mcpu=ultrasparc:%{!mv8plus:-Av9a}} \
+%{mcpu=ultrasparc3:%{!mv8plus:-Av9b}} \
%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(asm_cpu_default)}}}}}}} \
"
@@ -364,10 +361,6 @@ Unrecognized value in TARGET_CPU_DEFAULT.
#define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G %L"
-#ifdef SPARC_BI_ARCH
-#define NO_BUILTIN_PTRDIFF_TYPE
-#define NO_BUILTIN_SIZE_TYPE
-#endif
#define PTRDIFF_TYPE (TARGET_ARCH64 ? "long int" : "int")
#define SIZE_TYPE (TARGET_ARCH64 ? "long unsigned int" : "unsigned int")
@@ -382,7 +375,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
/* Generate DBX debugging information. */
-#define DBX_DEBUGGING_INFO
+#define DBX_DEBUGGING_INFO 1
/* Run-time compilation parameters selecting different hardware subsets. */
@@ -418,7 +411,7 @@ extern int target_flags;
#define MASK_V9 0x40
#define TARGET_V9 (target_flags & MASK_V9)
-/* Non-zero to generate code that uses the instructions deprecated in
+/* Nonzero to generate code that uses the instructions deprecated in
the v9 architecture. This option only applies to v9 systems. */
/* ??? This isn't user selectable yet. It's used to enable such insns
on 32 bit v9 systems and for the moment they're permanently disabled
@@ -430,7 +423,7 @@ extern int target_flags;
#define MASK_ISA \
(MASK_V8 + MASK_SPARCLITE + MASK_SPARCLET + MASK_V9 + MASK_DEPRECATED_V8_INSNS)
-/* Non-zero means don't pass `-assert pure-text' to the linker. */
+/* Nonzero means don't pass `-assert pure-text' to the linker. */
#define MASK_IMPURE_TEXT 0x100
#define TARGET_IMPURE_TEXT (target_flags & MASK_IMPURE_TEXT)
@@ -441,7 +434,7 @@ extern int target_flags;
#define MASK_FLAT 0x200
#define TARGET_FLAT (target_flags & MASK_FLAT)
-/* Nonzero means use the registers that the Sparc ABI reserves for
+/* Nonzero means use the registers that the SPARC ABI reserves for
application software. This must be the default to coincide with the
setting in FIXED_REGISTERS. */
#define MASK_APP_REGS 0x400
@@ -453,7 +446,7 @@ extern int target_flags;
#define MASK_HARD_QUAD 0x800
#define TARGET_HARD_QUAD (target_flags & MASK_HARD_QUAD)
-/* Non-zero on little-endian machines. */
+/* Nonzero on little-endian machines. */
/* ??? Little endian support currently only exists for sparclet-aout and
sparc64-elf configurations. May eventually want to expand the support
to all targets, but for now it's kept local to only those two. */
@@ -474,25 +467,25 @@ extern int target_flags;
/* 0x20000,0x40000 unused */
-/* Non-zero means use a stack bias of 2047. Stack offsets are obtained by
+/* Nonzero means use a stack bias of 2047. Stack offsets are obtained by
adding 2047 to %sp. This option is for v9 only and is the default. */
#define MASK_STACK_BIAS 0x80000
#define TARGET_STACK_BIAS (target_flags & MASK_STACK_BIAS)
/* 0x100000,0x200000 unused */
-/* Non-zero means -m{,no-}fpu was passed on the command line. */
+/* Nonzero means -m{,no-}fpu was passed on the command line. */
#define MASK_FPU_SET 0x400000
#define TARGET_FPU_SET (target_flags & MASK_FPU_SET)
/* Use the UltraSPARC Visual Instruction Set extensions. */
-#define MASK_VIS 0x1000000
+#define MASK_VIS 0x1000000
#define TARGET_VIS (target_flags & MASK_VIS)
/* Compile for Solaris V8+. 32 bit Solaris preserves the high bits of
the current out and global registers and Linux 2.2+ as well. */
#define MASK_V8PLUS 0x2000000
-#define TARGET_V8PLUS (target_flags & MASK_V8PLUS)
+#define TARGET_V8PLUS (target_flags & MASK_V8PLUS)
/* Force a the fastest alignment on structures to take advantage of
faster copies. */
@@ -515,7 +508,7 @@ extern int target_flags;
#define TARGET_HARD_MUL \
(TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET \
- || TARGET_DEPRECATED_V8_INSNS || TARGET_V8PLUS)
+ || TARGET_DEPRECATED_V8_INSNS || TARGET_V8PLUS)
/* Macro to define tables used to set the flags.
@@ -567,15 +560,15 @@ extern int target_flags;
{"cypress", 0, \
N_("Optimize for Cypress processors") }, \
{"sparclite", 0, \
- N_("Optimize for SparcLite processors") }, \
+ N_("Optimize for SPARCLite processors") }, \
{"f930", 0, \
N_("Optimize for F930 processors") }, \
{"f934", 0, \
N_("Optimize for F934 processors") }, \
{"v8", 0, \
- N_("Use V8 Sparc ISA") }, \
+ N_("Use V8 SPARC ISA") }, \
{"supersparc", 0, \
- N_("Optimize for SuperSparc processors") }, \
+ N_("Optimize for SuperSPARC processors") }, \
/* End of deprecated options. */ \
{"ptr64", MASK_PTR64, \
N_("Pointers are 64-bit") }, \
@@ -623,7 +616,8 @@ enum processor_type {
PROCESSOR_SPARCLET,
PROCESSOR_TSC701,
PROCESSOR_V9,
- PROCESSOR_ULTRASPARC
+ PROCESSOR_ULTRASPARC,
+ PROCESSOR_ULTRASPARC3
};
/* This is set from -m{cpu,tune}=xxx. */
@@ -640,7 +634,7 @@ extern enum processor_type sparc_cpu;
{ "tune=", &sparc_select[2].string, \
N_("Schedule code for given CPU") }, \
{ "cmodel=", &sparc_cmodel_string, \
- N_("Use given Sparc code model") }, \
+ N_("Use given SPARC code model") }, \
SUBTARGET_OPTIONS \
}
@@ -660,10 +654,6 @@ extern struct sparc_cpu_select sparc_select[];
/* target machine storage layout */
-/* Define for cross-compilation to a sparc target with no TFmode from a host
- with a different float format (e.g. VAX). */
-#define REAL_ARITHMETIC
-
/* Define this if most significant bit is lowest numbered
in instructions that operate on numbered bit-fields. */
#define BITS_BIG_ENDIAN 1
@@ -683,14 +673,6 @@ extern struct sparc_cpu_select sparc_select[];
#define LIBGCC2_WORDS_BIG_ENDIAN 1
#endif
-/* number of bits in an addressable storage unit */
-#define BITS_PER_UNIT 8
-
-/* Width in bits of a "word", which is the contents of a machine register.
- Note that this is not necessarily the width of data type `int';
- if using 16-bit ints on a 68000, this would still be 32.
- But on a machine with 16-bit registers, this would be 16. */
-#define BITS_PER_WORD (TARGET_ARCH64 ? 64 : 32)
#define MAX_BITS_PER_WORD 64
/* Width of a word, in units (bytes). */
@@ -717,8 +699,8 @@ extern struct sparc_cpu_select sparc_select[];
#if 0
/* ??? This does not work in SunOS 4.x, so it is not enabled here.
Instead, it is enabled in sol2.h, because it does work under Solaris. */
-/* Define for support of TFmode long double and REAL_ARITHMETIC.
- Sparc ABI says that long double is 4 words. */
+/* Define for support of TFmode long double.
+ SPARC ABI says that long double is 4 words. */
#define LONG_DOUBLE_TYPE_SIZE 128
#endif
@@ -789,7 +771,7 @@ if (TARGET_ARCH64 \
/* Every structure's size must be a multiple of this. */
#define STRUCTURE_SIZE_BOUNDARY 8
-/* A bitfield declared as `int' forces `int' alignment for the struct. */
+/* A bit-field declared as `int' forces `int' alignment for the struct. */
#define PCC_BITFIELD_TYPE_MATTERS 1
/* No data type wants to be aligned rounder than this. */
@@ -844,19 +826,6 @@ if (TARGET_ARCH64 \
#ifndef SUNOS4_SHARED_LIBRARIES
#define SUNOS4_SHARED_LIBRARIES 0
#endif
-
-
-/* Use text section for a constant
- unless we need more alignment than that offers. */
-/* This is defined differently for v9 in a cover file. */
-#define SELECT_RTX_SECTION(MODE, X, ALIGN) \
-{ \
- if (GET_MODE_BITSIZE (MODE) <= MAX_TEXT_ALIGN \
- && ! (flag_pic && (symbolic_operand ((X), (MODE)) || SUNOS4_SHARED_LIBRARIES))) \
- text_section (); \
- else \
- data_section (); \
-}
/* Standard register usage. */
@@ -979,7 +948,7 @@ do \
call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
} \
/* If the user has passed -f{fixed,call-{used,saved}}-g5 */ \
- /* then honour it. */ \
+ /* then honor it. */ \
if (TARGET_ARCH32 && fixed_regs[5]) \
fixed_regs[5] = 1; \
else if (TARGET_ARCH64 && fixed_regs[5] == 2) \
@@ -1004,7 +973,7 @@ do \
fixed_regs[regno] = 1; \
} \
/* If the user has passed -f{fixed,call-{used,saved}}-g2 */ \
- /* then honour it. Likewise with g3 and g4. */ \
+ /* then honor it. Likewise with g3 and g4. */ \
if (fixed_regs[2] == 2) \
fixed_regs[2] = ! TARGET_APP_REGS; \
if (fixed_regs[3] == 2) \
@@ -1128,7 +1097,6 @@ extern int sparc_mode_class[];
#define FRAME_POINTER_REQUIRED \
(TARGET_FLAT \
? (current_function_calls_alloca \
- || current_function_varargs \
|| !leaf_function_p ()) \
: ! (leaf_function_p () && only_leaf_regs_used ()))
@@ -1150,7 +1118,7 @@ extern int sparc_mode_class[];
#define DEFAULT_PCC_STRUCT_RETURN -1
-/* Sparc ABI says that quad-precision floats and all structures are returned
+/* SPARC ABI says that quad-precision floats and all structures are returned
in memory.
For v9: unions <= 32 bytes in size are returned in int regs,
structures up to 32 bytes are returned in int and fp regs. */
@@ -1274,18 +1242,33 @@ extern enum reg_class sparc_regno_reg_class[FIRST_PSEUDO_REGISTER];
#define REGNO_REG_CLASS(REGNO) sparc_regno_reg_class[(REGNO)]
-/* This is the order in which to allocate registers normally.
-
- We put %f0/%f1 last among the float registers, so as to make it more
+/* This is the order in which to allocate registers normally.
+
+ We put %f0-%f7 last among the float registers, so as to make it more
likely that a pseudo-register which dies in the float return register
- will get allocated to the float return register, thus saving a move
- instruction at the end of the function. */
+ area will get allocated to the float return register, thus saving a move
+ instruction at the end of the function.
+
+ Similarly for integer return value registers.
+
+ We know in this case that we will not end up with a leaf function.
+
+ The register allocater is given the global and out registers first
+ because these registers are call clobbered and thus less useful to
+ global register allocation.
+
+ Next we list the local and in registers. They are not call clobbered
+ and thus very useful for global register allocation. We list the input
+ registers before the locals so that it is more likely the incoming
+ arguments received in those registers can just stay there and not be
+ reloaded. */
#define REG_ALLOC_ORDER \
-{ 8, 9, 10, 11, 12, 13, 2, 3, \
- 15, 16, 17, 18, 19, 20, 21, 22, \
- 23, 24, 25, 26, 27, 28, 29, 31, \
- 34, 35, 36, 37, 38, 39, /* %f2-%f7 */ \
+{ 1, 2, 3, 4, 5, 6, 7, /* %g1-%g7 */ \
+ 13, 12, 11, 10, 9, 8, /* %o5-%o0 */ \
+ 15, /* %o7 */ \
+ 16, 17, 18, 19, 20, 21, 22, 23, /* %l0-%l7 */ \
+ 29, 28, 27, 26, 25, 24, 31, /* %i5-%i0,%i7 */\
40, 41, 42, 43, 44, 45, 46, 47, /* %f8-%f15 */ \
48, 49, 50, 51, 52, 53, 54, 55, /* %f16-%f23 */ \
56, 57, 58, 59, 60, 61, 62, 63, /* %f24-%f31 */ \
@@ -1293,31 +1276,49 @@ extern enum reg_class sparc_regno_reg_class[FIRST_PSEUDO_REGISTER];
72, 73, 74, 75, 76, 77, 78, 79, /* %f40-%f47 */ \
80, 81, 82, 83, 84, 85, 86, 87, /* %f48-%f55 */ \
88, 89, 90, 91, 92, 93, 94, 95, /* %f56-%f63 */ \
- 32, 33, /* %f0,%f1 */ \
- 96, 97, 98, 99, 100, /* %fcc0-3, %icc */ \
- 1, 4, 5, 6, 7, 0, 14, 30, 101}
+ 39, 38, 37, 36, 35, 34, 33, 32, /* %f7-%f0 */ \
+ 96, 97, 98, 99, /* %fcc0-3 */ \
+ 100, 0, 14, 30, 101} /* %icc, %g0, %o6, %i6, %sfp */
/* This is the order in which to allocate registers for
- leaf functions. If all registers can fit in the "gi" registers,
- then we have the possibility of having a leaf function. */
+ leaf functions. If all registers can fit in the global and
+ output registers, then we have the possibility of having a leaf
+ function.
+
+ The macro actually mentioned the input registers first,
+ because they get renumbered into the output registers once
+ we know really do have a leaf function.
+
+ To be more precise, this register allocation order is used
+ when %o7 is found to not be clobbered right before register
+ allocation. Normally, the reason %o7 would be clobbered is
+ due to a call which could not be transformed into a sibling
+ call.
+
+ As a consequence, it is possible to use the leaf register
+ allocation order and not end up with a leaf function. We will
+ not get suboptimal register allocation in that case because by
+ definition of being potentially leaf, there were no function
+ calls. Therefore, allocation order within the local register
+ window is not critical like it is when we do have function calls. */
#define REG_LEAF_ALLOC_ORDER \
-{ 2, 3, 24, 25, 26, 27, 28, 29, \
- 4, 5, 6, 7, 1, \
- 15, 8, 9, 10, 11, 12, 13, \
- 16, 17, 18, 19, 20, 21, 22, 23, \
- 34, 35, 36, 37, 38, 39, \
- 40, 41, 42, 43, 44, 45, 46, 47, \
- 48, 49, 50, 51, 52, 53, 54, 55, \
- 56, 57, 58, 59, 60, 61, 62, 63, \
- 64, 65, 66, 67, 68, 69, 70, 71, \
- 72, 73, 74, 75, 76, 77, 78, 79, \
- 80, 81, 82, 83, 84, 85, 86, 87, \
- 88, 89, 90, 91, 92, 93, 94, 95, \
- 32, 33, \
- 96, 97, 98, 99, 100, \
- 0, 14, 30, 31, 101}
-
+{ 1, 2, 3, 4, 5, 6, 7, /* %g1-%g7 */ \
+ 29, 28, 27, 26, 25, 24, /* %i5-%i0 */ \
+ 15, /* %o7 */ \
+ 13, 12, 11, 10, 9, 8, /* %o5-%o0 */ \
+ 16, 17, 18, 19, 20, 21, 22, 23, /* %l0-%l7 */ \
+ 40, 41, 42, 43, 44, 45, 46, 47, /* %f8-%f15 */ \
+ 48, 49, 50, 51, 52, 53, 54, 55, /* %f16-%f23 */ \
+ 56, 57, 58, 59, 60, 61, 62, 63, /* %f24-%f31 */ \
+ 64, 65, 66, 67, 68, 69, 70, 71, /* %f32-%f39 */ \
+ 72, 73, 74, 75, 76, 77, 78, 79, /* %f40-%f47 */ \
+ 80, 81, 82, 83, 84, 85, 86, 87, /* %f48-%f55 */ \
+ 88, 89, 90, 91, 92, 93, 94, 95, /* %f56-%f63 */ \
+ 39, 38, 37, 36, 35, 34, 33, 32, /* %f7-%f0 */ \
+ 96, 97, 98, 99, /* %fcc0-3 */ \
+ 100, 0, 14, 30, 31, 101} /* %icc, %g0, %o6, %i6, %i7, %sfp */
+
#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
extern char sparc_leaf_regs[];
@@ -1365,7 +1366,8 @@ extern char leaf_reg_remap[];
`K' is used for constants which can be loaded with a single sethi insn.
`L' is used for the range of constants supported by the movcc insns.
`M' is used for the range of constants supported by the movrcc insns.
- `N' is like K, but for constants wider than 32 bits. */
+ `N' is like K, but for constants wider than 32 bits.
+ `O' is used for the range which is just 4096. */
#define SPARC_SIMM10_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x200 < 0x400)
#define SPARC_SIMM11_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x400 < 0x800)
@@ -1389,6 +1391,7 @@ extern char leaf_reg_remap[];
: (C) == 'L' ? SPARC_SIMM11_P (VALUE) \
: (C) == 'M' ? SPARC_SIMM10_P (VALUE) \
: (C) == 'N' ? SPARC_SETHI_P (VALUE) \
+ : (C) == 'O' ? (VALUE) == 4096 \
: 0)
/* Similar, but for floating constants, and defining letters G and H.
@@ -1397,6 +1400,7 @@ extern char leaf_reg_remap[];
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
((C) == 'G' ? fp_zero_operand (VALUE, GET_MODE (VALUE)) \
: (C) == 'H' ? arith_double_operand (VALUE, DImode) \
+ : (C) == 'O' ? arith_double_4096_operand (VALUE, DImode) \
: 0)
/* Given an rtx X being reloaded into a reg required to be
@@ -1475,7 +1479,7 @@ extern char leaf_reg_remap[];
? GENERAL_REGS \
: NO_REGS)
-/* On SPARC it is not possible to directly move data between
+/* On SPARC it is not possible to directly move data between
GENERAL_REGS and FP_REGS. */
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
(FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2))
@@ -1571,7 +1575,7 @@ extern char leaf_reg_remap[];
/* Definitions for register elimination. */
/* ??? In TARGET_FLAT mode we needn't have a hard frame pointer. */
-
+
#define ELIMINABLE_REGS \
{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM} }
@@ -1722,8 +1726,8 @@ extern char leaf_reg_remap[];
struct sparc_args {
int words; /* number of words passed so far */
- int prototype_p; /* non-zero if a prototype is present */
- int libcall_p; /* non-zero if a library call */
+ int prototype_p; /* nonzero if a prototype is present */
+ int libcall_p; /* nonzero if a library call */
};
#define CUMULATIVE_ARGS struct sparc_args
@@ -1809,13 +1813,14 @@ function_arg_padding ((MODE), (TYPE))
stored from the compare operation. Note that we can't use "rtx" here
since it hasn't been defined! */
-extern struct rtx_def *sparc_compare_op0, *sparc_compare_op1;
+extern GTY(()) rtx sparc_compare_op0;
+extern GTY(()) rtx sparc_compare_op1;
/* Generate the special assembly code needed to tell the assembler whatever
it might need to know about the return value of a function.
- For Sparc assemblers, we need to output a .proc pseudo-op which conveys
+ For SPARC assemblers, we need to output a .proc pseudo-op which conveys
information to the assembler relating to peephole optimization (done in
the assembler). */
@@ -1823,7 +1828,7 @@ extern struct rtx_def *sparc_compare_op0, *sparc_compare_op1;
fprintf ((FILE), "\t.proc\t0%lo\n", sparc_type_code (TREE_TYPE (RESULT)))
/* Output the special assembly code needed to tell the assembler some
- register is used as global register variable.
+ register is used as global register variable.
SPARC 64bit psABI declares registers %g2 and %g3 as application
registers and %g6 and %g7 as OS registers. Any object using them
@@ -1910,8 +1915,8 @@ do { \
#define EXPAND_BUILTIN_SAVEREGS() sparc_builtin_saveregs ()
/* Implement `va_start' for varargs and stdarg. */
-#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
- sparc_va_start (stdarg, valist, nextarg)
+#define EXPAND_BUILTIN_VA_START(valist, nextarg) \
+ sparc_va_start (valist, nextarg)
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
@@ -2203,6 +2208,8 @@ do { \
If you change this, execute "rm explow.o recog.o reload.o". */
+#define SYMBOLIC_CONST(X) symbolic_operand (X, VOIDmode)
+
#define RTX_OK_FOR_BASE_P(X) \
((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
|| (GET_CODE (X) == SUBREG \
@@ -2217,7 +2224,7 @@ do { \
#define RTX_OK_FOR_OFFSET_P(X) \
(GET_CODE (X) == CONST_INT && INTVAL (X) >= -0x1000 && INTVAL (X) < 0x1000 - 8)
-
+
#define RTX_OK_FOR_OLO10_P(X) \
(GET_CODE (X) == CONST_INT && INTVAL (X) >= -0x1000 && INTVAL (X) < 0xc00 - 8)
@@ -2236,6 +2243,8 @@ do { \
&& GET_CODE (op1) != REG \
&& GET_CODE (op1) != LO_SUM \
&& GET_CODE (op1) != MEM \
+ && (! SYMBOLIC_CONST (op1) \
+ || MODE == Pmode) \
&& (GET_CODE (op1) != CONST_INT \
|| SMALL_INT (op1))) \
goto ADDR; \
@@ -2323,6 +2332,34 @@ do { \
else if (GET_CODE (X) == CONST_INT && SMALL_INT (X)) \
goto ADDR; \
}
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for.
+
+ In PIC mode,
+
+ (mem:HI [%l7+a])
+
+ is not equivalent to
+
+ (mem:QI [%l7+a]) (mem:QI [%l7+a+1])
+
+ because [%l7+a+1] is interpreted as the address of (a+1). */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \
+{ \
+ if (flag_pic == 1) \
+ { \
+ if (GET_CODE (ADDR) == PLUS) \
+ { \
+ rtx op0 = XEXP (ADDR, 0); \
+ rtx op1 = XEXP (ADDR, 1); \
+ if (op0 == pic_offset_table_rtx \
+ && SYMBOLIC_CONST (op1)) \
+ goto LABEL; \
+ } \
+ } \
+}
/* Try machine-dependent ways of modifying an illegitimate address
to be legitimate. If we find one, return the new, valid address.
@@ -2371,8 +2408,8 @@ do { \
operand. If we find one, push the reload and jump to WIN. This
macro is used in only one place: `find_reloads_address' in reload.c.
- For Sparc 32, we wish to handle addresses by splitting them into
- HIGH+LO_SUM pairs, retaining the LO_SUM in the memory reference.
+ For SPARC 32, we wish to handle addresses by splitting them into
+ HIGH+LO_SUM pairs, retaining the LO_SUM in the memory reference.
This cuts the number of extra insns by one.
Do nothing when generating PIC code and the address is a
@@ -2400,22 +2437,6 @@ do { \
} \
/* ??? 64-bit reloads. */ \
} while (0)
-
-/* Go to LABEL if ADDR (a legitimate address expression)
- has an effect that depends on the machine mode it is used for.
- On the SPARC this is never true. */
-
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
-
-/* If we are referencing a function make the SYMBOL_REF special.
- In the Embedded Medium/Anywhere code model, %g4 points to the data segment
- so we must not add it to function addresses. */
-
-#define ENCODE_SECTION_INFO(DECL) \
- do { \
- if (TARGET_CM_EMBMEDANY && TREE_CODE (DECL) == FUNCTION_DECL) \
- SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \
- } while (0)
/* Specify the machine mode that this machine uses
for the index in the tablejump instruction. */
@@ -2494,26 +2515,6 @@ do { \
/* Generate calls to memcpy, memcmp and memset. */
#define TARGET_MEM_FUNCTIONS
-/* Add any extra modes needed to represent the condition code.
-
- On the Sparc, we have a "no-overflow" mode which is used when an add or
- subtract insn is used to set the condition code. Different branches are
- used in this case for some operations.
-
- We also have two modes to indicate that the relevant condition code is
- in the floating-point condition code register. One for comparisons which
- will generate an exception if the result is unordered (CCFPEmode) and
- one for comparisons which will never trap (CCFPmode).
-
- CCXmode and CCX_NOOVmode are only used by v9. */
-
-#define EXTRA_CC_MODES \
- CC(CCXmode, "CCX") \
- CC(CC_NOOVmode, "CC_NOOV") \
- CC(CCX_NOOVmode, "CCX_NOOV") \
- CC(CCFPmode, "CCFP") \
- CC(CCFPEmode, "CCFPE")
-
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. For floating-point,
CCFP[E]mode is used. CC_NOOVmode should be used when the first operand
@@ -2521,8 +2522,8 @@ do { \
processing is needed. */
#define SELECT_CC_MODE(OP,X,Y) select_cc_mode ((OP), (X), (Y))
-/* Return non-zero if MODE implies a floating point inequality can be
- reversed. For Sparc this is always true because we have a full
+/* Return nonzero if MODE implies a floating point inequality can be
+ reversed. For SPARC this is always true because we have a full
compliment of ordered and unordered comparisons, but until generic
code knows how to reverse it correctly we keep the old definition. */
#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode && (MODE) != CCFPmode)
@@ -2634,33 +2635,6 @@ do { \
of the libgcc2 functions is used. */
#define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) ((MODE) == TFmode)
-/* Compute the cost of computing a constant rtl expression RTX
- whose rtx-code is CODE. The body of this macro is a portion
- of a switch statement. If the code is computed here,
- return it with a return statement. Otherwise, break from the switch. */
-
-#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
- case CONST_INT: \
- if (INTVAL (RTX) < 0x1000 && INTVAL (RTX) >= -0x1000) \
- return 0; \
- case HIGH: \
- return 2; \
- case CONST: \
- case LABEL_REF: \
- case SYMBOL_REF: \
- return 4; \
- case CONST_DOUBLE: \
- if (GET_MODE (RTX) == DImode) \
- if ((XINT (RTX, 3) == 0 \
- && (unsigned) XINT (RTX, 2) < 0x1000) \
- || (XINT (RTX, 3) == -1 \
- && XINT (RTX, 2) < 0 \
- && XINT (RTX, 2) >= -0x1000)) \
- return 0; \
- return 8;
-
-#define ADDRESS_COST(RTX) 1
-
/* Compute extra cost of moving data between one register class
and another. */
#define GENERAL_OR_I64(C) ((C) == GENERAL_REGS || (C) == I64_REGS)
@@ -2668,7 +2642,8 @@ do { \
(((FP_REG_CLASS_P (CLASS1) && GENERAL_OR_I64 (CLASS2)) \
|| (GENERAL_OR_I64 (CLASS1) && FP_REG_CLASS_P (CLASS2)) \
|| (CLASS1) == FPCC_REGS || (CLASS2) == FPCC_REGS) \
- ? (sparc_cpu == PROCESSOR_ULTRASPARC ? 12 : 6) : 2)
+ ? ((sparc_cpu == PROCESSOR_ULTRASPARC \
+ || sparc_cpu == PROCESSOR_ULTRASPARC3) ? 12 : 6) : 2)
/* Provide the cost of a branch. For pre-v9 processors we use
a value of 3 to take into account the potential annulling of
@@ -2678,48 +2653,48 @@ do { \
On v9 and later, which have branch prediction facilities, we set
it to the depth of the pipeline as that is the cost of a
- mispredicted branch.
-
- ??? Set to 9 when PROCESSOR_ULTRASPARC3 is added */
+ mispredicted branch. */
#define BRANCH_COST \
((sparc_cpu == PROCESSOR_V9 \
|| sparc_cpu == PROCESSOR_ULTRASPARC) \
- ? 7 : 3)
+ ? 7 \
+ : (sparc_cpu == PROCESSOR_ULTRASPARC3 \
+ ? 9 : 3))
+
+/* The cases that RTX_COSTS handles. */
+
+#define RTX_COSTS_CASES \
+case PLUS: case MINUS: case ABS: case NEG: \
+case FLOAT: case UNSIGNED_FLOAT: \
+case FIX: case UNSIGNED_FIX: \
+case FLOAT_EXTEND: case FLOAT_TRUNCATE: \
+case SQRT: \
+case COMPARE: case IF_THEN_ELSE: \
+case MEM: \
+case MULT: case DIV: case UDIV: case MOD: case UMOD: \
+case CONST_INT: case HIGH: case CONST: \
+case LABEL_REF: case SYMBOL_REF: case CONST_DOUBLE:
/* Provide the costs of a rtl expression. This is in the body of a
- switch on CODE. The purpose for the cost of MULT is to encourage
- `synth_mult' to find a synthetic multiply when reasonable.
-
- If we need more than 12 insns to do a multiply, then go out-of-line,
- since the call overhead will be < 10% of the cost of the multiply. */
+ switch on CODE. */
#define RTX_COSTS(X,CODE,OUTER_CODE) \
- case MULT: \
- if (sparc_cpu == PROCESSOR_ULTRASPARC) \
- return (GET_MODE (X) == DImode ? \
- COSTS_N_INSNS (34) : COSTS_N_INSNS (19)); \
- return TARGET_HARD_MUL ? COSTS_N_INSNS (5) : COSTS_N_INSNS (25); \
- case DIV: \
- case UDIV: \
- case MOD: \
- case UMOD: \
- if (sparc_cpu == PROCESSOR_ULTRASPARC) \
- return (GET_MODE (X) == DImode ? \
- COSTS_N_INSNS (68) : COSTS_N_INSNS (37)); \
- return COSTS_N_INSNS (25); \
- /* Make FLOAT and FIX more expensive than CONST_DOUBLE,\
- so that cse will favor the latter. */ \
- case FLOAT: \
- case FIX: \
- return 19;
+ RTX_COSTS_CASES \
+ return sparc_rtx_costs(X,CODE,OUTER_CODE);
+
+#define ADDRESS_COST(RTX) 1
#define PREFETCH_BLOCK \
- ((sparc_cpu == PROCESSOR_ULTRASPARC) ? 64 : 32)
+ ((sparc_cpu == PROCESSOR_ULTRASPARC \
+ || sparc_cpu == PROCESSOR_ULTRASPARC3) \
+ ? 64 : 32)
-/* ??? UltraSPARC-III note: Can set this to 8 for ultra3. */
#define SIMULTANEOUS_PREFETCHES \
- ((sparc_cpu == PROCESSOR_ULTRASPARC) ? 2 : 3)
+ ((sparc_cpu == PROCESSOR_ULTRASPARC) \
+ ? 2 \
+ : (sparc_cpu == PROCESSOR_ULTRASPARC3 \
+ ? 8 : 3))
/* Control the assembler format that we output. */
@@ -2780,17 +2755,11 @@ do { \
guess... */
#define DBX_CONTIN_LENGTH 1000
-/* This is how to output the definition of a user-level label named NAME,
- such as the label on a static function or variable NAME. */
-
-#define ASM_OUTPUT_LABEL(FILE,NAME) \
- do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
-
/* This is how to output a command to make the user-level label named NAME
defined for reference from other files. */
-#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
- do { fputs ("\t.global ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.global "
/* The prefix to add to user-visible assembler symbols. */
@@ -2872,6 +2841,13 @@ do { \
if ((LOG) != 0) \
fprintf (FILE, "\t.align %d\n", (1<<(LOG)))
+/* This is how to output an assembler line that says to advance
+ the location counter to a multiple of 2**LOG bytes using the
+ "nop" instruction as padding. */
+#define ASM_OUTPUT_ALIGN_WITH_NOP(FILE,LOG) \
+ if ((LOG) != 0) \
+ fprintf (FILE, "\t.align %d,0x1000000\n", (1<<(LOG)))
+
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
fprintf (FILE, "\t.skip %u\n", (SIZE))
@@ -2920,11 +2896,6 @@ do { \
#define ASM_OUTPUT_IDENT(FILE, NAME) \
fprintf (FILE, "%s\"%s\"\n", IDENT_ASM_OP, NAME);
-/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
- Used for C++ multiple inheritance. */
-#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
- sparc_output_mi_thunk (FILE, THUNK_FNDECL, DELTA, FUNCTION)
-
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '(' || (CHAR) == '_')
@@ -3017,6 +2988,7 @@ do { \
#define PREDICATE_CODES \
{"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
+{"const1_operand", {CONST_INT}}, \
{"fp_zero_operand", {CONST_DOUBLE}}, \
{"fp_register_operand", {SUBREG, REG}}, \
{"intreg_operand", {SUBREG, REG}}, \
@@ -3065,4 +3037,3 @@ do { \
#define JMP_BUF_SIZE 12
#define DONT_ACCESS_GBLS_AFTER_EPILOGUE (flag_pic)
-
diff --git a/contrib/gcc/config/sparc/sparc.md b/contrib/gcc/config/sparc/sparc.md
index 746dc72..ebe9d2b 100644
--- a/contrib/gcc/config/sparc/sparc.md
+++ b/contrib/gcc/config/sparc/sparc.md
@@ -24,34 +24,30 @@
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
-;; Uses of UNSPEC and UNSPEC_VOLATILE in this file:
-;;
-;; UNSPEC: 0 movsi_{lo_sum,high}_pic
-;; pic_lo_sum_di
-;; pic_sethi_di
-;; 1 update_return
-;; 2 get_pc
-;; 5 movsi_{,lo_sum_,high_}pic_label_ref
-;; 6 seth44
-;; 7 setm44
-;; 8 setl44
-;; 9 sethh
-;; 10 setlm
-;; 11 embmedany_sethi, embmedany_brsum
-;; 13 embmedany_textuhi
-;; 14 embmedany_texthi
-;; 15 embmedany_textulo
-;; 16 embmedany_textlo
-;; 18 sethm
-;; 19 setlo
-;;
-;; UNSPEC_VOLATILE: 0 blockage
-;; 1 flush_register_windows
-;; 2 goto_handler_and_restore
-;; 3 goto_handler_and_restore_v9*
-;; 4 flush
-;; 5 do_builtin_setjmp_setup
-;;
+(define_constants
+ [(UNSPEC_MOVE_PIC 0)
+ (UNSPEC_UPDATE_RETURN 1)
+ (UNSPEC_GET_PC 2)
+ (UNSPEC_MOVE_PIC_LABEL 5)
+ (UNSPEC_SETH44 6)
+ (UNSPEC_SETM44 7)
+ (UNSPEC_SETHH 9)
+ (UNSPEC_SETLM 10)
+ (UNSPEC_EMB_HISUM 11)
+ (UNSPEC_EMB_TEXTUHI 13)
+ (UNSPEC_EMB_TEXTHI 14)
+ (UNSPEC_EMB_TEXTULO 15)
+ (UNSPEC_EMB_SETHM 18)
+ ])
+
+(define_constants
+ [(UNSPECV_BLOCKAGE 0)
+ (UNSPECV_FLUSHW 1)
+ (UNSPECV_GOTO 2)
+ (UNSPECV_GOTO_V9 3)
+ (UNSPECV_FLUSH 4)
+ (UNSPECV_SETJMP 5)
+ ])
;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this
;; a second register class, EXTRA_FP_REGS, exists for the v9 chip. The name
@@ -61,7 +57,17 @@
;; 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,hypersparc,sparclite86x,sparclet,tsc701,v9,ultrasparc"
+(define_attr "cpu"
+ "v7,
+ cypress,
+ v8,
+ supersparc,
+ sparclite,f930,f934,
+ hypersparc,sparclite86x,
+ sparclet,tsc701,
+ v9,
+ ultrasparc,
+ ultrasparc3"
(const (symbol_ref "sparc_cpu_attr")))
;; Attribute for the instruction set.
@@ -82,9 +88,20 @@
;; Insn type.
-;; If you add any new type here, please update ultrasparc_sched_reorder too.
(define_attr "type"
- "ialu,compare,shift,load,sload,store,uncond_branch,branch,call,sibcall,call_no_delay_slot,return,imul,idiv,fpload,fpstore,fp,fpmove,fpcmove,fpcmp,fpmul,fpdivs,fpdivd,fpsqrts,fpsqrtd,cmove,multi,misc"
+ "ialu,compare,shift,
+ load,sload,store,
+ uncond_branch,branch,call,sibcall,call_no_delay_slot,
+ imul,idiv,
+ fpload,fpstore,
+ fp,fpmove,
+ fpcmove,fpcrmove,
+ fpcmp,
+ fpmul,fpdivs,fpdivd,
+ fpsqrts,fpsqrtd,
+ cmove,
+ ialuX,
+ multi,flushw,iflush,trap"
(const_string "ialu"))
;; true if branch/call has empty delay slot and will emit a nop in it
@@ -96,6 +113,12 @@
(define_attr "pic" "false,true"
(symbol_ref "flag_pic != 0"))
+(define_attr "current_function_calls_alloca" "false,true"
+ (symbol_ref "current_function_calls_alloca != 0"))
+
+(define_attr "flat" "false,true"
+ (symbol_ref "TARGET_FLAT != 0"))
+
;; Length (in # of insns).
(define_attr "length" ""
(cond [(eq_attr "type" "uncond_branch,call,sibcall")
@@ -163,6 +186,9 @@
;; FP precision.
(define_attr "fptype" "single,double" (const_string "single"))
+;; UltraSPARC-III integer load type.
+(define_attr "us3load_type" "2cycle,3cycle" (const_string "2cycle"))
+
(define_asm_attributes
[(set_attr "length" "2")
(set_attr "type" "multi")])
@@ -170,7 +196,7 @@
;; Attributes for instruction and branch scheduling
(define_attr "in_call_delay" "false,true"
- (cond [(eq_attr "type" "uncond_branch,branch,call,sibcall,call_no_delay_slot,return,multi")
+ (cond [(eq_attr "type" "uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
(const_string "false")
(eq_attr "type" "load,fpload,store,fpstore")
(if_then_else (eq_attr "length" "1")
@@ -192,21 +218,6 @@
(define_attr "leaf_function" "false,true"
(const (symbol_ref "current_function_uses_only_leaf_regs")))
-(define_attr "eligible_for_return_delay" "false,true"
- (symbol_ref "eligible_for_return_delay (insn)"))
-
-(define_attr "in_return_delay" "false,true"
- (if_then_else (and (and (and (eq_attr "type" "ialu,load,sload,store")
- (eq_attr "length" "1"))
- (eq_attr "leaf_function" "false"))
- (eq_attr "eligible_for_return_delay" "false"))
- (const_string "true")
- (const_string "false")))
-
-(define_delay (and (eq_attr "type" "return")
- (eq_attr "isa" "v9"))
- [(eq_attr "in_return_delay" "true") (nil) (nil)])
-
;; ??? Should implement the notion of predelay slots for floating point
;; branches. This would allow us to remove the nop always inserted before
;; a floating point branch.
@@ -245,344 +256,15 @@
[(eq_attr "in_uncond_branch_delay" "true")
(nil) (nil)])
-;; Function units of the SPARC
-
-;; (define_function_unit {name} {num-units} {n-users} {test}
-;; {ready-delay} {issue-delay} [{conflict-list}])
-
-;; The integer ALU.
-;; (Noted only for documentation; units that take one cycle do not need to
-;; be specified.)
-
-;; On the sparclite, integer multiply takes 1, 3, or 5 cycles depending on
-;; the inputs.
-
-;; ---- cypress CY7C602 scheduling:
-;; Memory with load-delay of 1 (i.e., 2 cycle load).
-
-(define_function_unit "memory" 1 0
- (and (eq_attr "cpu" "cypress")
- (eq_attr "type" "load,sload,fpload"))
- 2 2)
-
-;; SPARC has two floating-point units: the FP ALU,
-;; and the FP MUL/DIV/SQRT unit.
-;; Instruction timings on the CY7C602 are as follows
-;; FABSs 4
-;; FADDs/d 5/5
-;; FCMPs/d 4/4
-;; FDIVs/d 23/37
-;; FMOVs 4
-;; FMULs/d 5/7
-;; FNEGs 4
-;; FSQRTs/d 34/63
-;; FSUBs/d 5/5
-;; FdTOi/s 5/5
-;; FsTOi/d 5/5
-;; FiTOs/d 9/5
-
-;; The CY7C602 can only support 2 fp isnsn simultaneously.
-;; More insns cause the chip to stall.
-
-(define_function_unit "fp_alu" 1 0
- (and (eq_attr "cpu" "cypress")
- (eq_attr "type" "fp,fpmove"))
- 5 5)
-
-(define_function_unit "fp_mds" 1 0
- (and (eq_attr "cpu" "cypress")
- (eq_attr "type" "fpmul"))
- 7 7)
-
-(define_function_unit "fp_mds" 1 0
- (and (eq_attr "cpu" "cypress")
- (eq_attr "type" "fpdivs,fpdivd"))
- 37 37)
-
-(define_function_unit "fp_mds" 1 0
- (and (eq_attr "cpu" "cypress")
- (eq_attr "type" "fpsqrts,fpsqrtd"))
- 63 63)
-
-;; ----- The TMS390Z55 scheduling
-;; The Supersparc can issue 1 - 3 insns per cycle: up to two integer,
-;; one ld/st, one fp.
-;; Memory delivers its result in one cycle to IU, zero cycles to FP
-
-(define_function_unit "memory" 1 0
- (and (eq_attr "cpu" "supersparc")
- (eq_attr "type" "load,sload"))
- 1 1)
-
-(define_function_unit "memory" 1 0
- (and (eq_attr "cpu" "supersparc")
- (eq_attr "type" "fpload"))
- 0 1)
-
-(define_function_unit "memory" 1 0
- (and (eq_attr "cpu" "supersparc")
- (eq_attr "type" "store,fpstore"))
- 1 1)
-
-(define_function_unit "shift" 1 0
- (and (eq_attr "cpu" "supersparc")
- (eq_attr "type" "shift"))
- 1 1)
-
-;; There are only two write ports to the integer register file
-;; A store also uses a write port
-
-(define_function_unit "iwport" 2 0
- (and (eq_attr "cpu" "supersparc")
- (eq_attr "type" "load,sload,store,shift,ialu"))
- 1 1)
-
-;; Timings; throughput/latency
-;; FADD 1/3 add/sub, format conv, compar, abs, neg
-;; FMUL 1/3
-;; FDIVs 4/6
-;; FDIVd 7/9
-;; FSQRTs 6/8
-;; FSQRTd 10/12
-;; IMUL 4/4
-
-(define_function_unit "fp_alu" 1 0
- (and (eq_attr "cpu" "supersparc")
- (eq_attr "type" "fp,fpmove,fpcmp"))
- 3 1)
-
-(define_function_unit "fp_mds" 1 0
- (and (eq_attr "cpu" "supersparc")
- (eq_attr "type" "fpmul"))
- 3 1)
-
-(define_function_unit "fp_mds" 1 0
- (and (eq_attr "cpu" "supersparc")
- (eq_attr "type" "fpdivs"))
- 6 4)
-
-(define_function_unit "fp_mds" 1 0
- (and (eq_attr "cpu" "supersparc")
- (eq_attr "type" "fpdivd"))
- 9 7)
-
-(define_function_unit "fp_mds" 1 0
- (and (eq_attr "cpu" "supersparc")
- (eq_attr "type" "fpsqrts,fpsqrtd"))
- 12 10)
-
-(define_function_unit "fp_mds" 1 0
- (and (eq_attr "cpu" "supersparc")
- (eq_attr "type" "imul"))
- 4 4)
-
-;; ----- hypersparc/sparclite86x scheduling
-;; The Hypersparc can issue 1 - 2 insns per cycle. The dual issue cases are:
-;; L-Ld/St I-Int F-Float B-Branch LI/LF/LB/II/IF/IB/FF/FB
-;; II/FF case is only when loading a 32 bit hi/lo constant
-;; Single issue insns include call, jmpl, u/smul, u/sdiv, lda, sta, fcmp
-;; Memory delivers its result in one cycle to IU
-
-(define_function_unit "memory" 1 0
- (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
- (eq_attr "type" "load,sload,fpload"))
- 1 1)
-
-(define_function_unit "memory" 1 0
- (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
- (eq_attr "type" "store,fpstore"))
- 2 1)
-
-(define_function_unit "sparclite86x_branch" 1 0
- (and (eq_attr "cpu" "sparclite86x")
- (eq_attr "type" "branch"))
- 1 1)
-
-;; integer multiply insns
-(define_function_unit "sparclite86x_shift" 1 0
- (and (eq_attr "cpu" "sparclite86x")
- (eq_attr "type" "shift"))
- 1 1)
-
-(define_function_unit "fp_alu" 1 0
- (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
- (eq_attr "type" "fp,fpmove,fpcmp"))
- 1 1)
-
-(define_function_unit "fp_mds" 1 0
- (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
- (eq_attr "type" "fpmul"))
- 1 1)
-
-(define_function_unit "fp_mds" 1 0
- (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
- (eq_attr "type" "fpdivs"))
- 8 6)
-
-(define_function_unit "fp_mds" 1 0
- (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
- (eq_attr "type" "fpdivd"))
- 12 10)
-
-(define_function_unit "fp_mds" 1 0
- (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
- (eq_attr "type" "fpsqrts,fpsqrtd"))
- 17 15)
-
-(define_function_unit "fp_mds" 1 0
- (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x"))
- (eq_attr "type" "imul"))
- 17 15)
-
-;; ----- sparclet tsc701 scheduling
-;; The tsc701 issues 1 insn per cycle.
-;; Results may be written back out of order.
-
-;; Loads take 2 extra cycles to complete and 4 can be buffered at a time.
-
-(define_function_unit "tsc701_load" 4 1
- (and (eq_attr "cpu" "tsc701")
- (eq_attr "type" "load,sload"))
- 3 1)
-
-;; Stores take 2(?) extra cycles to complete.
-;; It is desirable to not have any memory operation in the following 2 cycles.
-;; (??? or 2 memory ops in the case of std).
-
-(define_function_unit "tsc701_store" 1 0
- (and (eq_attr "cpu" "tsc701")
- (eq_attr "type" "store"))
- 3 3
- [(eq_attr "type" "load,sload,store")])
-
-;; The multiply unit has a latency of 5.
-(define_function_unit "tsc701_mul" 1 0
- (and (eq_attr "cpu" "tsc701")
- (eq_attr "type" "imul"))
- 5 5)
-
-;; ----- The UltraSPARC-1 scheduling
-;; UltraSPARC has two integer units. Shift instructions can only execute
-;; on IE0. Condition code setting instructions, call, and jmpl (including
-;; the ret and retl pseudo-instructions) can only execute on IE1.
-;; Branch on register uses IE1, but branch on condition code does not.
-;; Conditional moves take 2 cycles. No other instruction can issue in the
-;; same cycle as a conditional move.
-;; Multiply and divide take many cycles during which no other instructions
-;; can issue.
-;; Memory delivers its result in two cycles (except for signed loads,
-;; which take one cycle more). One memory instruction can be issued per
-;; cycle.
-
-(define_function_unit "memory" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "load,fpload"))
- 2 1)
-
-(define_function_unit "memory" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "sload"))
- 3 1)
-
-(define_function_unit "memory" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "store,fpstore"))
- 1 1)
-
-(define_function_unit "ieuN" 2 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "ialu,shift,compare,call,sibcall,call_no_delay_slot,uncond_branch"))
- 1 1)
-
-(define_function_unit "ieu0" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "shift"))
- 1 1)
-
-(define_function_unit "ieu0" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "cmove"))
- 2 1)
-
-(define_function_unit "ieu1" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "compare,call,sibcall,call_no_delay_slot,uncond_branch"))
- 1 1)
-
-(define_function_unit "cti" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "branch"))
- 1 1)
-
-;; Timings; throughput/latency
-;; FMOV 1/1 fmov, fabs, fneg
-;; FMOVcc 1/2
-;; FADD 1/3 add/sub, format conv, compar
-;; FMUL 1/3
-;; FDIVs 12/12
-;; FDIVd 22/22
-;; FSQRTs 12/12
-;; FSQRTd 22/22
-;; FCMP takes 1 cycle to branch, 2 cycles to conditional move.
-;;
-;; FDIV{s,d}/FSQRT{s,d} are given their own unit since they only
-;; use the FPM multiplier for final rounding 3 cycles before the
-;; end of their latency and we have no real way to model that.
-;;
-;; ??? This is really bogus because the timings really depend upon
-;; who uses the result. We should record who the user is with
-;; more descriptive 'type' attribute names and account for these
-;; issues in ultrasparc_adjust_cost.
-
-(define_function_unit "fadd" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "fpmove"))
- 1 1)
-
-(define_function_unit "fadd" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "fpcmove"))
- 2 1)
-
-(define_function_unit "fadd" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "fp"))
- 3 1)
-
-(define_function_unit "fadd" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "fpcmp"))
- 2 1)
-
-(define_function_unit "fmul" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "fpmul"))
- 3 1)
-
-(define_function_unit "fadd" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "fpcmove"))
- 2 1)
-
-(define_function_unit "fdiv" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "fpdivs"))
- 12 12)
-
-(define_function_unit "fdiv" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "fpdivd"))
- 22 22)
-
-(define_function_unit "fdiv" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "fpsqrts"))
- 12 12)
-
-(define_function_unit "fdiv" 1 0
- (and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "fpsqrtd"))
- 22 22)
+;; Include SPARC DFA schedulers
+
+(include "cypress.md")
+(include "supersparc.md")
+(include "hypersparc.md")
+(include "sparclet.md")
+(include "ultra1_2.md")
+(include "ultra3.md")
+
;; Compare instructions.
;; This controls RTL generation and register allocation.
@@ -607,24 +289,22 @@
(compare:CC (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "arith_operand" "")))]
""
- "
{
sparc_compare_op0 = operands[0];
sparc_compare_op1 = operands[1];
DONE;
-}")
+})
(define_expand "cmpdi"
[(set (reg:CCX 100)
(compare:CCX (match_operand:DI 0 "register_operand" "")
(match_operand:DI 1 "arith_double_operand" "")))]
"TARGET_ARCH64"
- "
{
sparc_compare_op0 = operands[0];
sparc_compare_op1 = operands[1];
DONE;
-}")
+})
(define_expand "cmpsf"
;; The 96 here isn't ever used by anyone.
@@ -632,12 +312,11 @@
(compare:CCFP (match_operand:SF 0 "register_operand" "")
(match_operand:SF 1 "register_operand" "")))]
"TARGET_FPU"
- "
{
sparc_compare_op0 = operands[0];
sparc_compare_op1 = operands[1];
DONE;
-}")
+})
(define_expand "cmpdf"
;; The 96 here isn't ever used by anyone.
@@ -645,12 +324,11 @@
(compare:CCFP (match_operand:DF 0 "register_operand" "")
(match_operand:DF 1 "register_operand" "")))]
"TARGET_FPU"
- "
{
sparc_compare_op0 = operands[0];
sparc_compare_op1 = operands[1];
DONE;
-}")
+})
(define_expand "cmptf"
;; The 96 here isn't ever used by anyone.
@@ -658,12 +336,11 @@
(compare:CCFP (match_operand:TF 0 "register_operand" "")
(match_operand:TF 1 "register_operand" "")))]
"TARGET_FPU"
- "
{
sparc_compare_op0 = operands[0];
sparc_compare_op1 = operands[1];
DONE;
-}")
+})
;; Now the compare DEFINE_INSNs.
@@ -672,7 +349,7 @@
(compare:CC (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "arith_operand" "rI")))]
""
- "cmp\\t%0, %1"
+ "cmp\t%0, %1"
[(set_attr "type" "compare")])
(define_insn "*cmpdi_sp64"
@@ -680,7 +357,7 @@
(compare:CCX (match_operand:DI 0 "register_operand" "r")
(match_operand:DI 1 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
- "cmp\\t%0, %1"
+ "cmp\t%0, %1"
[(set_attr "type" "compare")])
(define_insn "*cmpsf_fpe"
@@ -688,12 +365,11 @@
(compare:CCFPE (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
- "*
{
if (TARGET_V9)
- return \"fcmpes\\t%0, %1, %2\";
- return \"fcmpes\\t%1, %2\";
-}"
+ return "fcmpes\t%0, %1, %2";
+ return "fcmpes\t%1, %2";
+}
[(set_attr "type" "fpcmp")])
(define_insn "*cmpdf_fpe"
@@ -701,12 +377,11 @@
(compare:CCFPE (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU"
- "*
{
if (TARGET_V9)
- return \"fcmped\\t%0, %1, %2\";
- return \"fcmped\\t%1, %2\";
-}"
+ return "fcmped\t%0, %1, %2";
+ return "fcmped\t%1, %2";
+}
[(set_attr "type" "fpcmp")
(set_attr "fptype" "double")])
@@ -715,12 +390,11 @@
(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\\t%0, %1, %2\";
- return \"fcmpeq\\t%1, %2\";
-}"
+ return "fcmpeq\t%0, %1, %2";
+ return "fcmpeq\t%1, %2";
+}
[(set_attr "type" "fpcmp")])
(define_insn "*cmpsf_fp"
@@ -728,12 +402,11 @@
(compare:CCFP (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
- "*
{
if (TARGET_V9)
- return \"fcmps\\t%0, %1, %2\";
- return \"fcmps\\t%1, %2\";
-}"
+ return "fcmps\t%0, %1, %2";
+ return "fcmps\t%1, %2";
+}
[(set_attr "type" "fpcmp")])
(define_insn "*cmpdf_fp"
@@ -741,12 +414,11 @@
(compare:CCFP (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU"
- "*
{
if (TARGET_V9)
- return \"fcmpd\\t%0, %1, %2\";
- return \"fcmpd\\t%1, %2\";
-}"
+ return "fcmpd\t%0, %1, %2";
+ return "fcmpd\t%1, %2";
+}
[(set_attr "type" "fpcmp")
(set_attr "fptype" "double")])
@@ -755,12 +427,11 @@
(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\\t%0, %1, %2\";
- return \"fcmpq\\t%1, %2\";
-}"
+ return "fcmpq\t%0, %1, %2";
+ return "fcmpq\t%1, %2";
+}
[(set_attr "type" "fpcmp")])
;; Next come the scc insns. For seq, sne, sgeu, and sltu, we can do this
@@ -781,7 +452,7 @@
(eq:SI (match_dup 3) (const_int 0)))
(clobber (reg:CC 100))])]
""
- "{ operands[3] = gen_reg_rtx (SImode); }")
+ { operands[3] = gen_reg_rtx (SImode); })
(define_expand "seqdi_special"
[(set (match_dup 3)
@@ -790,7 +461,7 @@
(set (match_operand:DI 0 "register_operand" "")
(eq:DI (match_dup 3) (const_int 0)))]
"TARGET_ARCH64"
- "{ operands[3] = gen_reg_rtx (DImode); }")
+ { operands[3] = gen_reg_rtx (DImode); })
(define_expand "snesi_special"
[(set (match_dup 3)
@@ -800,7 +471,7 @@
(ne:SI (match_dup 3) (const_int 0)))
(clobber (reg:CC 100))])]
""
- "{ operands[3] = gen_reg_rtx (SImode); }")
+ { operands[3] = gen_reg_rtx (SImode); })
(define_expand "snedi_special"
[(set (match_dup 3)
@@ -809,7 +480,7 @@
(set (match_operand:DI 0 "register_operand" "")
(ne:DI (match_dup 3) (const_int 0)))]
"TARGET_ARCH64"
- "{ operands[3] = gen_reg_rtx (DImode); }")
+ { operands[3] = gen_reg_rtx (DImode); })
(define_expand "seqdi_special_trunc"
[(set (match_dup 3)
@@ -818,7 +489,7 @@
(set (match_operand:SI 0 "register_operand" "")
(eq:SI (match_dup 3) (const_int 0)))]
"TARGET_ARCH64"
- "{ operands[3] = gen_reg_rtx (DImode); }")
+ { operands[3] = gen_reg_rtx (DImode); })
(define_expand "snedi_special_trunc"
[(set (match_dup 3)
@@ -827,7 +498,7 @@
(set (match_operand:SI 0 "register_operand" "")
(ne:SI (match_dup 3) (const_int 0)))]
"TARGET_ARCH64"
- "{ operands[3] = gen_reg_rtx (DImode); }")
+ { operands[3] = gen_reg_rtx (DImode); })
(define_expand "seqsi_special_extend"
[(set (match_dup 3)
@@ -837,7 +508,7 @@
(eq:DI (match_dup 3) (const_int 0)))
(clobber (reg:CC 100))])]
"TARGET_ARCH64"
- "{ operands[3] = gen_reg_rtx (SImode); }")
+ { operands[3] = gen_reg_rtx (SImode); })
(define_expand "snesi_special_extend"
[(set (match_dup 3)
@@ -847,7 +518,7 @@
(ne:DI (match_dup 3) (const_int 0)))
(clobber (reg:CC 100))])]
"TARGET_ARCH64"
- "{ operands[3] = gen_reg_rtx (SImode); }")
+ { operands[3] = gen_reg_rtx (SImode); })
;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
;; However, the code handles both SImode and DImode.
@@ -855,7 +526,6 @@
[(set (match_operand:SI 0 "intreg_operand" "")
(eq:SI (match_dup 1) (const_int 0)))]
""
- "
{
if (GET_MODE (sparc_compare_op0) == SImode)
{
@@ -900,7 +570,7 @@
/* fall through */
}
FAIL;
-}")
+})
;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
;; However, the code handles both SImode and DImode.
@@ -908,7 +578,6 @@
[(set (match_operand:SI 0 "intreg_operand" "")
(ne:SI (match_dup 1) (const_int 0)))]
""
- "
{
if (GET_MODE (sparc_compare_op0) == SImode)
{
@@ -953,13 +622,12 @@
/* fall through */
}
FAIL;
-}")
+})
(define_expand "sgt"
[(set (match_operand:SI 0 "intreg_operand" "")
(gt:SI (match_dup 1) (const_int 0)))]
""
- "
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
@@ -974,13 +642,12 @@
/* fall through */
}
FAIL;
-}")
+})
(define_expand "slt"
[(set (match_operand:SI 0 "intreg_operand" "")
(lt:SI (match_dup 1) (const_int 0)))]
""
- "
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
@@ -995,13 +662,12 @@
/* fall through */
}
FAIL;
-}")
+})
(define_expand "sge"
[(set (match_operand:SI 0 "intreg_operand" "")
(ge:SI (match_dup 1) (const_int 0)))]
""
- "
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
@@ -1016,13 +682,12 @@
/* fall through */
}
FAIL;
-}")
+})
(define_expand "sle"
[(set (match_operand:SI 0 "intreg_operand" "")
(le:SI (match_dup 1) (const_int 0)))]
""
- "
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
@@ -1037,13 +702,12 @@
/* fall through */
}
FAIL;
-}")
+})
(define_expand "sgtu"
[(set (match_operand:SI 0 "intreg_operand" "")
(gtu:SI (match_dup 1) (const_int 0)))]
""
- "
{
if (! TARGET_V9)
{
@@ -1072,13 +736,12 @@
DONE;
}
FAIL;
-}")
+})
(define_expand "sltu"
[(set (match_operand:SI 0 "intreg_operand" "")
(ltu:SI (match_dup 1) (const_int 0)))]
""
- "
{
if (TARGET_V9)
{
@@ -1086,13 +749,12 @@
DONE;
}
operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
-}")
+})
(define_expand "sgeu"
[(set (match_operand:SI 0 "intreg_operand" "")
(geu:SI (match_dup 1) (const_int 0)))]
""
- "
{
if (TARGET_V9)
{
@@ -1100,13 +762,12 @@
DONE;
}
operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
-}")
+})
(define_expand "sleu"
[(set (match_operand:SI 0 "intreg_operand" "")
(leu:SI (match_dup 1) (const_int 0)))]
""
- "
{
if (! TARGET_V9)
{
@@ -1135,7 +796,7 @@
DONE;
}
FAIL;
-}")
+})
;; Now the DEFINE_INSNs for the scc cases.
@@ -1144,263 +805,193 @@
;; them to always use the splitz below so the results can be
;; scheduled.
-(define_insn "*snesi_zero"
+(define_insn_and_split "*snesi_zero"
[(set (match_operand:SI 0 "register_operand" "=r")
(ne:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0)))
(clobber (reg:CC 100))]
""
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (ne:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0)))
- (clobber (reg:CC 100))]
""
[(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
(const_int 0)))
(set (match_dup 0) (ltu:SI (reg:CC 100) (const_int 0)))]
- "")
+ ""
+ [(set_attr "length" "2")])
-(define_insn "*neg_snesi_zero"
+(define_insn_and_split "*neg_snesi_zero"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0))))
(clobber (reg:CC 100))]
""
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0))))
- (clobber (reg:CC 100))]
""
[(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
(const_int 0)))
(set (match_dup 0) (neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
- "")
-
-(define_insn "*snesi_zero_extend"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (ne:DI (match_operand:SI 1 "register_operand" "r")
- (const_int 0)))
- (clobber (reg:CC 100))]
- "TARGET_ARCH64"
- "#"
+ ""
[(set_attr "length" "2")])
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (ne:DI (match_operand:SI 1 "register_operand" "")
+(define_insn_and_split "*snesi_zero_extend"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ne:DI (match_operand:SI 1 "register_operand" "r")
(const_int 0)))
(clobber (reg:CC 100))]
"TARGET_ARCH64"
- [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0) (match_dup 1))
+ "#"
+ "&& 1"
+ [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0)
+ (match_dup 1))
(const_int 0)))
(set (match_dup 0) (zero_extend:DI (plus:SI (plus:SI (const_int 0)
(const_int 0))
(ltu:SI (reg:CC_NOOV 100)
(const_int 0)))))]
- "")
+ ""
+ [(set_attr "length" "2")])
-(define_insn "*snedi_zero"
+(define_insn_and_split "*snedi_zero"
[(set (match_operand:DI 0 "register_operand" "=&r")
- (ne:DI (match_operand:DI 1 "register_operand" "r")
- (const_int 0)))]
+ (ne:DI (match_operand:DI 1 "register_operand" "r")
+ (const_int 0)))]
"TARGET_ARCH64"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (ne:DI (match_operand:DI 1 "register_operand" "")
- (const_int 0)))]
- "TARGET_ARCH64
- && ! reg_overlap_mentioned_p (operands[1], operands[0])"
+ "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
(set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
(const_int 0))
(const_int 1)
(match_dup 0)))]
- "")
+ ""
+ [(set_attr "length" "2")])
-(define_insn "*neg_snedi_zero"
+(define_insn_and_split "*neg_snedi_zero"
[(set (match_operand:DI 0 "register_operand" "=&r")
- (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
- (const_int 0))))]
+ (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
+ (const_int 0))))]
"TARGET_ARCH64"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (neg:DI (ne:DI (match_operand:DI 1 "register_operand" "")
- (const_int 0))))]
- "TARGET_ARCH64
- && ! reg_overlap_mentioned_p (operands[1], operands[0])"
+ "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
(set (match_dup 0) (if_then_else:DI (ne:DI (match_dup 1)
(const_int 0))
(const_int -1)
(match_dup 0)))]
- "")
+ ""
+ [(set_attr "length" "2")])
-(define_insn "*snedi_zero_trunc"
+(define_insn_and_split "*snedi_zero_trunc"
[(set (match_operand:SI 0 "register_operand" "=&r")
- (ne:SI (match_operand:DI 1 "register_operand" "r")
- (const_int 0)))]
+ (ne:SI (match_operand:DI 1 "register_operand" "r")
+ (const_int 0)))]
"TARGET_ARCH64"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (ne:SI (match_operand:DI 1 "register_operand" "")
- (const_int 0)))]
- "TARGET_ARCH64
- && ! reg_overlap_mentioned_p (operands[1], operands[0])"
+ "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
(set (match_dup 0) (if_then_else:SI (ne:DI (match_dup 1)
(const_int 0))
(const_int 1)
(match_dup 0)))]
- "")
+ ""
+ [(set_attr "length" "2")])
-(define_insn "*seqsi_zero"
+(define_insn_and_split "*seqsi_zero"
[(set (match_operand:SI 0 "register_operand" "=r")
(eq:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0)))
(clobber (reg:CC 100))]
""
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (eq:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0)))
- (clobber (reg:CC 100))]
""
[(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
(const_int 0)))
(set (match_dup 0) (geu:SI (reg:CC 100) (const_int 0)))]
- "")
+ ""
+ [(set_attr "length" "2")])
-(define_insn "*neg_seqsi_zero"
+(define_insn_and_split "*neg_seqsi_zero"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0))))
(clobber (reg:CC 100))]
""
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0))))
- (clobber (reg:CC 100))]
""
[(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
(const_int 0)))
(set (match_dup 0) (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
- "")
-
-(define_insn "*seqsi_zero_extend"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (eq:DI (match_operand:SI 1 "register_operand" "r")
- (const_int 0)))
- (clobber (reg:CC 100))]
- "TARGET_ARCH64"
- "#"
+ ""
[(set_attr "length" "2")])
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (eq:DI (match_operand:SI 1 "register_operand" "")
+(define_insn_and_split "*seqsi_zero_extend"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (eq:DI (match_operand:SI 1 "register_operand" "r")
(const_int 0)))
(clobber (reg:CC 100))]
"TARGET_ARCH64"
- [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0) (match_dup 1))
+ "#"
+ "&& 1"
+ [(set (reg:CC_NOOV 100) (compare:CC_NOOV (minus:SI (const_int 0)
+ (match_dup 1))
(const_int 0)))
(set (match_dup 0) (zero_extend:DI (minus:SI (minus:SI (const_int 0)
(const_int -1))
(ltu:SI (reg:CC_NOOV 100)
(const_int 0)))))]
- "")
+ ""
+ [(set_attr "length" "2")])
-(define_insn "*seqdi_zero"
+(define_insn_and_split "*seqdi_zero"
[(set (match_operand:DI 0 "register_operand" "=&r")
- (eq:DI (match_operand:DI 1 "register_operand" "r")
- (const_int 0)))]
+ (eq:DI (match_operand:DI 1 "register_operand" "r")
+ (const_int 0)))]
"TARGET_ARCH64"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (eq:DI (match_operand:DI 1 "register_operand" "")
- (const_int 0)))]
- "TARGET_ARCH64
- && ! reg_overlap_mentioned_p (operands[1], operands[0])"
+ "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
(set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
(const_int 0))
(const_int 1)
(match_dup 0)))]
- "")
+ ""
+ [(set_attr "length" "2")])
-(define_insn "*neg_seqdi_zero"
+(define_insn_and_split "*neg_seqdi_zero"
[(set (match_operand:DI 0 "register_operand" "=&r")
- (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r")
- (const_int 0))))]
+ (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r")
+ (const_int 0))))]
"TARGET_ARCH64"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (neg:DI (eq:DI (match_operand:DI 1 "register_operand" "")
- (const_int 0))))]
- "TARGET_ARCH64
- && ! reg_overlap_mentioned_p (operands[1], operands[0])"
+ "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
(set (match_dup 0) (if_then_else:DI (eq:DI (match_dup 1)
(const_int 0))
(const_int -1)
(match_dup 0)))]
- "")
+ ""
+ [(set_attr "length" "2")])
-(define_insn "*seqdi_zero_trunc"
+(define_insn_and_split "*seqdi_zero_trunc"
[(set (match_operand:SI 0 "register_operand" "=&r")
- (eq:SI (match_operand:DI 1 "register_operand" "r")
- (const_int 0)))]
+ (eq:SI (match_operand:DI 1 "register_operand" "r")
+ (const_int 0)))]
"TARGET_ARCH64"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (eq:SI (match_operand:DI 1 "register_operand" "")
- (const_int 0)))]
- "TARGET_ARCH64
- && ! reg_overlap_mentioned_p (operands[1], operands[0])"
+ "&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
(set (match_dup 0) (if_then_else:SI (eq:DI (match_dup 1)
(const_int 0))
(const_int 1)
(match_dup 0)))]
- "")
+ ""
+ [(set_attr "length" "2")])
;; We can also do (x + (i == 0)) and related, so put them in.
;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
;; versions for v9.
-(define_insn "*x_plus_i_ne_0"
+(define_insn_and_split "*x_plus_i_ne_0"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0))
@@ -1408,22 +999,15 @@
(clobber (reg:CC 100))]
""
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (ne:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0))
- (match_operand:SI 2 "register_operand" "")))
- (clobber (reg:CC 100))]
""
[(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)))]
- "")
+ ""
+ [(set_attr "length" "2")])
-(define_insn "*x_minus_i_ne_0"
+(define_insn_and_split "*x_minus_i_ne_0"
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 2 "register_operand" "r")
(ne:SI (match_operand:SI 1 "register_operand" "r")
@@ -1431,22 +1015,15 @@
(clobber (reg:CC 100))]
""
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_operand:SI 2 "register_operand" "")
- (ne:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0))))
- (clobber (reg:CC 100))]
""
[(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
(const_int 0)))
(set (match_dup 0) (minus:SI (match_dup 2)
(ltu:SI (reg:CC 100) (const_int 0))))]
- "")
+ ""
+ [(set_attr "length" "2")])
-(define_insn "*x_plus_i_eq_0"
+(define_insn_and_split "*x_plus_i_eq_0"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0))
@@ -1454,22 +1031,15 @@
(clobber (reg:CC 100))]
""
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (eq:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0))
- (match_operand:SI 2 "register_operand" "")))
- (clobber (reg:CC 100))]
""
[(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)))]
- "")
+ ""
+ [(set_attr "length" "2")])
-(define_insn "*x_minus_i_eq_0"
+(define_insn_and_split "*x_minus_i_eq_0"
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 2 "register_operand" "r")
(eq:SI (match_operand:SI 1 "register_operand" "r")
@@ -1477,20 +1047,13 @@
(clobber (reg:CC 100))]
""
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_operand:SI 2 "register_operand" "")
- (eq:SI (match_operand:SI 1 "register_operand" "")
- (const_int 0))))
- (clobber (reg:CC 100))]
""
[(set (reg:CC_NOOV 100) (compare:CC_NOOV (neg:SI (match_dup 1))
(const_int 0)))
(set (match_dup 0) (minus:SI (match_dup 2)
(geu:SI (reg:CC 100) (const_int 0))))]
- "")
+ ""
+ [(set_attr "length" "2")])
;; We can also do GEU and LTU directly, but these operate after a compare.
;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
@@ -1500,15 +1063,15 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(ltu:SI (reg:CC 100) (const_int 0)))]
""
- "addx\\t%%g0, 0, %0"
- [(set_attr "type" "misc")])
+ "addx\t%%g0, 0, %0"
+ [(set_attr "type" "ialuX")])
(define_insn "*neg_sltu_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (ltu:SI (reg:CC 100) (const_int 0))))]
""
- "subx\\t%%g0, 0, %0"
- [(set_attr "type" "misc")])
+ "subx\t%%g0, 0, %0"
+ [(set_attr "type" "ialuX")])
;; ??? Combine should canonicalize these next two to the same pattern.
(define_insn "*neg_sltu_minus_x"
@@ -1516,30 +1079,30 @@
(minus:SI (neg:SI (ltu:SI (reg:CC 100) (const_int 0)))
(match_operand:SI 1 "arith_operand" "rI")))]
""
- "subx\\t%%g0, %1, %0"
- [(set_attr "type" "misc")])
+ "subx\t%%g0, %1, %0"
+ [(set_attr "type" "ialuX")])
(define_insn "*neg_sltu_plus_x"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (plus:SI (ltu:SI (reg:CC 100) (const_int 0))
(match_operand:SI 1 "arith_operand" "rI"))))]
""
- "subx\\t%%g0, %1, %0"
- [(set_attr "type" "misc")])
+ "subx\t%%g0, %1, %0"
+ [(set_attr "type" "ialuX")])
(define_insn "*sgeu_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(geu:SI (reg:CC 100) (const_int 0)))]
""
- "subx\\t%%g0, -1, %0"
- [(set_attr "type" "misc")])
+ "subx\t%%g0, -1, %0"
+ [(set_attr "type" "ialuX")])
(define_insn "*neg_sgeu_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
""
- "addx\\t%%g0, -1, %0"
- [(set_attr "type" "misc")])
+ "addx\t%%g0, -1, %0"
+ [(set_attr "type" "ialuX")])
;; We can also do (x + ((unsigned) i >= 0)) and related, so put them in.
;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode
@@ -1550,8 +1113,8 @@
(plus:SI (ltu:SI (reg:CC 100) (const_int 0))
(match_operand:SI 1 "arith_operand" "rI")))]
""
- "addx\\t%%g0, %1, %0"
- [(set_attr "type" "misc")])
+ "addx\t%%g0, %1, %0"
+ [(set_attr "type" "ialuX")])
(define_insn "*sltu_plus_x_plus_y"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1559,16 +1122,16 @@
(plus:SI (match_operand:SI 1 "arith_operand" "%r")
(match_operand:SI 2 "arith_operand" "rI"))))]
""
- "addx\\t%1, %2, %0"
- [(set_attr "type" "misc")])
+ "addx\t%1, %2, %0"
+ [(set_attr "type" "ialuX")])
(define_insn "*x_minus_sltu"
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 1 "register_operand" "r")
(ltu:SI (reg:CC 100) (const_int 0))))]
""
- "subx\\t%1, 0, %0"
- [(set_attr "type" "misc")])
+ "subx\t%1, 0, %0"
+ [(set_attr "type" "ialuX")])
;; ??? Combine should canonicalize these next two to the same pattern.
(define_insn "*x_minus_y_minus_sltu"
@@ -1577,8 +1140,8 @@
(match_operand:SI 2 "arith_operand" "rI"))
(ltu:SI (reg:CC 100) (const_int 0))))]
""
- "subx\\t%r1, %2, %0"
- [(set_attr "type" "misc")])
+ "subx\t%r1, %2, %0"
+ [(set_attr "type" "ialuX")])
(define_insn "*x_minus_sltu_plus_y"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1586,24 +1149,24 @@
(plus:SI (ltu:SI (reg:CC 100) (const_int 0))
(match_operand:SI 2 "arith_operand" "rI"))))]
""
- "subx\\t%r1, %2, %0"
- [(set_attr "type" "misc")])
+ "subx\t%r1, %2, %0"
+ [(set_attr "type" "ialuX")])
(define_insn "*sgeu_plus_x"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (geu:SI (reg:CC 100) (const_int 0))
(match_operand:SI 1 "register_operand" "r")))]
""
- "subx\\t%1, -1, %0"
- [(set_attr "type" "misc")])
+ "subx\t%1, -1, %0"
+ [(set_attr "type" "ialuX")])
(define_insn "*x_minus_sgeu"
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 1 "register_operand" "r")
(geu:SI (reg:CC 100) (const_int 0))))]
""
- "addx\\t%1, -1, %0"
- [(set_attr "type" "misc")])
+ "addx\t%1, -1, %0"
+ [(set_attr "type" "ialuX")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -1634,7 +1197,6 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
{
if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
&& GET_CODE (sparc_compare_op0) == REG
@@ -1650,7 +1212,7 @@
DONE;
}
operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
-}")
+})
(define_expand "bne"
[(set (pc)
@@ -1658,7 +1220,6 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
{
if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
&& GET_CODE (sparc_compare_op0) == REG
@@ -1674,7 +1235,7 @@
DONE;
}
operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
-}")
+})
(define_expand "bgt"
[(set (pc)
@@ -1682,7 +1243,6 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
{
if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
&& GET_CODE (sparc_compare_op0) == REG
@@ -1698,7 +1258,7 @@
DONE;
}
operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
-}")
+})
(define_expand "bgtu"
[(set (pc)
@@ -1706,9 +1266,9 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
-{ operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
-}")
+{
+ operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
+})
(define_expand "blt"
[(set (pc)
@@ -1716,7 +1276,6 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
{
if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
&& GET_CODE (sparc_compare_op0) == REG
@@ -1732,7 +1291,7 @@
DONE;
}
operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
-}")
+})
(define_expand "bltu"
[(set (pc)
@@ -1740,9 +1299,9 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
-{ operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
-}")
+{
+ operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
+})
(define_expand "bge"
[(set (pc)
@@ -1750,7 +1309,6 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
{
if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
&& GET_CODE (sparc_compare_op0) == REG
@@ -1766,7 +1324,7 @@
DONE;
}
operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
-}")
+})
(define_expand "bgeu"
[(set (pc)
@@ -1774,9 +1332,9 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
-{ operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
-}")
+{
+ operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
+})
(define_expand "ble"
[(set (pc)
@@ -1784,7 +1342,6 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
{
if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
&& GET_CODE (sparc_compare_op0) == REG
@@ -1800,7 +1357,7 @@
DONE;
}
operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
-}")
+})
(define_expand "bleu"
[(set (pc)
@@ -1808,9 +1365,9 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
-{ operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
-}")
+{
+ operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
+})
(define_expand "bunordered"
[(set (pc)
@@ -1818,7 +1375,6 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
@@ -1829,7 +1385,7 @@
}
operands[1] = gen_compare_reg (UNORDERED, sparc_compare_op0,
sparc_compare_op1);
-}")
+})
(define_expand "bordered"
[(set (pc)
@@ -1837,7 +1393,6 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
@@ -1847,7 +1402,7 @@
}
operands[1] = gen_compare_reg (ORDERED, sparc_compare_op0,
sparc_compare_op1);
-}")
+})
(define_expand "bungt"
[(set (pc)
@@ -1855,7 +1410,6 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
@@ -1864,7 +1418,7 @@
DONE;
}
operands[1] = gen_compare_reg (UNGT, sparc_compare_op0, sparc_compare_op1);
-}")
+})
(define_expand "bunlt"
[(set (pc)
@@ -1872,7 +1426,6 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
@@ -1881,7 +1434,7 @@
DONE;
}
operands[1] = gen_compare_reg (UNLT, sparc_compare_op0, sparc_compare_op1);
-}")
+})
(define_expand "buneq"
[(set (pc)
@@ -1889,7 +1442,6 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
@@ -1898,7 +1450,7 @@
DONE;
}
operands[1] = gen_compare_reg (UNEQ, sparc_compare_op0, sparc_compare_op1);
-}")
+})
(define_expand "bunge"
[(set (pc)
@@ -1906,7 +1458,6 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
@@ -1915,7 +1466,7 @@
DONE;
}
operands[1] = gen_compare_reg (UNGE, sparc_compare_op0, sparc_compare_op1);
-}")
+})
(define_expand "bunle"
[(set (pc)
@@ -1923,7 +1474,6 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
@@ -1932,7 +1482,7 @@
DONE;
}
operands[1] = gen_compare_reg (UNLE, sparc_compare_op0, sparc_compare_op1);
-}")
+})
(define_expand "bltgt"
[(set (pc)
@@ -1940,7 +1490,6 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "
{
if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
{
@@ -1949,7 +1498,7 @@
DONE;
}
operands[1] = gen_compare_reg (LTGT, sparc_compare_op0, sparc_compare_op1);
-}")
+})
;; Now match both normal and inverted jump.
@@ -1961,12 +1510,11 @@
(label_ref (match_operand 1 "" ""))
(pc)))]
""
- "*
{
return output_cbranch (operands[0], operands[1], 1, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
-}"
+}
[(set_attr "type" "branch")
(set_attr "branch_type" "icc")])
@@ -1978,12 +1526,11 @@
(pc)
(label_ref (match_operand 1 "" ""))))]
""
- "*
{
return output_cbranch (operands[0], operands[1], 1, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
-}"
+}
[(set_attr "type" "branch")
(set_attr "branch_type" "icc")])
@@ -1996,12 +1543,11 @@
(label_ref (match_operand 2 "" ""))
(pc)))]
""
- "*
{
return output_cbranch (operands[1], operands[2], 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
-}"
+}
[(set_attr "type" "branch")
(set_attr "branch_type" "fcc")])
@@ -2014,12 +1560,11 @@
(pc)
(label_ref (match_operand 2 "" ""))))]
""
- "*
{
return output_cbranch (operands[1], operands[2], 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
-}"
+}
[(set_attr "type" "branch")
(set_attr "branch_type" "fcc")])
@@ -2032,12 +1577,11 @@
(label_ref (match_operand 2 "" ""))
(pc)))]
""
- "*
{
return output_cbranch (operands[1], operands[2], 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
-}"
+}
[(set_attr "type" "branch")
(set_attr "branch_type" "fcc")])
@@ -2050,16 +1594,15 @@
(pc)
(label_ref (match_operand 2 "" ""))))]
""
- "*
{
return output_cbranch (operands[1], operands[2], 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
-}"
+}
[(set_attr "type" "branch")
(set_attr "branch_type" "fcc")])
-;; Sparc V9-specific jump insns. None of these are guaranteed to be
+;; SPARC V9-specific jump insns. None of these are guaranteed to be
;; in the architecture.
;; There are no 32 bit brreg insns.
@@ -2073,12 +1616,11 @@
(label_ref (match_operand 2 "" ""))
(pc)))]
"TARGET_ARCH64"
- "*
{
return output_v9branch (operands[0], operands[2], 1, 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
-}"
+}
[(set_attr "type" "branch")
(set_attr "branch_type" "reg")])
@@ -2091,12 +1633,11 @@
(pc)
(label_ref (match_operand 2 "" ""))))]
"TARGET_ARCH64"
- "*
{
return output_v9branch (operands[0], operands[2], 1, 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence, insn);
-}"
+}
[(set_attr "type" "branch")
(set_attr "branch_type" "reg")])
@@ -2105,19 +1646,12 @@
(define_insn "get_pc"
[(clobber (reg:SI 15))
(set (match_operand 0 "register_operand" "=r")
- (unspec [(match_operand 1 "" "") (match_operand 2 "" "")] 2))]
+ (unspec [(match_operand 1 "" "") (match_operand 2 "" "")] UNSPEC_GET_PC))]
"flag_pic && REGNO (operands[0]) == 23"
- "sethi\\t%%hi(%a1-4), %0\\n\\tcall\\t%a2\\n\\tadd\\t%0, %%lo(%a1+4), %0"
+ "sethi\t%%hi(%a1-4), %0\n\tcall\t%a2\n\tadd\t%0, %%lo(%a1+4), %0"
[(set_attr "type" "multi")
(set_attr "length" "3")])
-;; Currently unused...
-;; (define_insn "get_pc_via_rdpc"
-;; [(set (match_operand 0 "register_operand" "=r") (pc))]
-;; "TARGET_V9"
-;; "rd\\t%%pc, %0"
-;; [(set_attr "type" "misc")])
-
;; Move instructions
@@ -2125,7 +1659,6 @@
[(set (match_operand:QI 0 "general_operand" "")
(match_operand:QI 1 "general_operand" ""))]
""
- "
{
/* Working with CONST_INTs is easier, so convert
a double if needed. */
@@ -2170,7 +1703,7 @@
movqi_is_ok:
;
-}")
+})
(define_insn "*movqi_insn"
[(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m")
@@ -2178,16 +1711,16 @@
"(register_operand (operands[0], QImode)
|| reg_or_0_operand (operands[1], QImode))"
"@
- mov\\t%1, %0
- ldub\\t%1, %0
- stb\\t%r1, %0"
- [(set_attr "type" "*,load,store")])
+ mov\t%1, %0
+ ldub\t%1, %0
+ stb\t%r1, %0"
+ [(set_attr "type" "*,load,store")
+ (set_attr "us3load_type" "*,3cycle,*")])
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
- "
{
/* Working with CONST_INTs is easier, so convert
a double if needed. */
@@ -2237,13 +1770,13 @@
}
movhi_is_ok:
;
-}")
+})
(define_insn "*movhi_const64_special"
[(set (match_operand:HI 0 "register_operand" "=r")
(match_operand:HI 1 "const64_high_operand" ""))]
"TARGET_ARCH64"
- "sethi\\t%%hi(%a1), %0")
+ "sethi\t%%hi(%a1), %0")
(define_insn "*movhi_insn"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
@@ -2251,11 +1784,12 @@
"(register_operand (operands[0], HImode)
|| reg_or_0_operand (operands[1], HImode))"
"@
- mov\\t%1, %0
- sethi\\t%%hi(%a1), %0
- lduh\\t%1, %0
- sth\\t%r1, %0"
- [(set_attr "type" "*,*,load,store")])
+ mov\t%1, %0
+ sethi\t%%hi(%a1), %0
+ lduh\t%1, %0
+ sth\t%r1, %0"
+ [(set_attr "type" "*,*,load,store")
+ (set_attr "us3load_type" "*,*,3cycle,*")])
;; We always work with constants here.
(define_insn "*movhi_lo_sum"
@@ -2263,13 +1797,12 @@
(ior:HI (match_operand:HI 1 "arith_operand" "%r")
(match_operand:HI 2 "arith_operand" "I")))]
""
- "or\\t%1, %2, %0")
+ "or\t%1, %2, %0")
(define_expand "movsi"
[(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
- "
{
/* Working with CONST_INTs is easier, so convert
a double if needed. */
@@ -2335,7 +1868,7 @@
}
movsi_is_ok:
;
-}")
+})
;; This is needed to show CSE exactly which bits are set
;; in a 64-bit register by sethi instructions.
@@ -2343,7 +1876,7 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operand:SI 1 "const64_high_operand" ""))]
"TARGET_ARCH64"
- "sethi\\t%%hi(%a1), %0")
+ "sethi\t%%hi(%a1), %0")
(define_insn "*movsi_insn"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,f,r,r,r,f,m,m,d")
@@ -2351,15 +1884,15 @@
"(register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))"
"@
- mov\\t%1, %0
- fmovs\\t%1, %0
- sethi\\t%%hi(%a1), %0
- clr\\t%0
- ld\\t%1, %0
- ld\\t%1, %0
- st\\t%r1, %0
- st\\t%1, %0
- fzeros\\t%0"
+ mov\t%1, %0
+ fmovs\t%1, %0
+ sethi\t%%hi(%a1), %0
+ clr\t%0
+ ld\t%1, %0
+ ld\t%1, %0
+ st\t%r1, %0
+ st\t%1, %0
+ fzeros\t%0"
[(set_attr "type" "*,fpmove,*,*,load,fpload,store,fpstore,fpmove")])
(define_insn "*movsi_lo_sum"
@@ -2367,42 +1900,41 @@
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "immediate_operand" "in")))]
""
- "or\\t%1, %%lo(%a2), %0")
+ "or\t%1, %%lo(%a2), %0")
(define_insn "*movsi_high"
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI (match_operand:SI 1 "immediate_operand" "in")))]
""
- "sethi\\t%%hi(%a1), %0")
+ "sethi\t%%hi(%a1), %0")
;; The next two patterns must wrap the SYMBOL_REF in an UNSPEC
;; so that CSE won't optimize the address computation away.
(define_insn "movsi_lo_sum_pic"
[(set (match_operand:SI 0 "register_operand" "=r")
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
- (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] 0)))]
+ (unspec:SI [(match_operand:SI 2 "immediate_operand" "in")] UNSPEC_MOVE_PIC)))]
"flag_pic"
- "or\\t%1, %%lo(%a2), %0")
+ "or\t%1, %%lo(%a2), %0")
(define_insn "movsi_high_pic"
[(set (match_operand:SI 0 "register_operand" "=r")
- (high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
+ (high:SI (unspec:SI [(match_operand 1 "" "")] UNSPEC_MOVE_PIC)))]
"flag_pic && check_pic (1)"
- "sethi\\t%%hi(%a1), %0")
+ "sethi\t%%hi(%a1), %0")
(define_expand "movsi_pic_label_ref"
[(set (match_dup 3) (high:SI
(unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
- (match_dup 2)] 5)))
+ (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
(set (match_dup 4) (lo_sum:SI (match_dup 3)
- (unspec:SI [(match_dup 1) (match_dup 2)] 5)))
+ (unspec:SI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_dup 5) (match_dup 4)))]
"flag_pic"
- "
{
current_function_uses_pic_offset_table = 1;
- operands[2] = gen_rtx_SYMBOL_REF (Pmode, \"_GLOBAL_OFFSET_TABLE_\");
+ operands[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
if (no_new_pseudos)
{
operands[3] = operands[0];
@@ -2414,29 +1946,28 @@
operands[4] = gen_reg_rtx (SImode);
}
operands[5] = pic_offset_table_rtx;
-}")
+})
(define_insn "*movsi_high_pic_label_ref"
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI
(unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
- (match_operand:SI 2 "" "")] 5)))]
+ (match_operand:SI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
"flag_pic"
- "sethi\\t%%hi(%a2-(%a1-.)), %0")
+ "sethi\t%%hi(%a2-(%a1-.)), %0")
(define_insn "*movsi_lo_sum_pic_label_ref"
[(set (match_operand:SI 0 "register_operand" "=r")
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
(unspec:SI [(match_operand:SI 2 "label_ref_operand" "")
- (match_operand:SI 3 "" "")] 5)))]
+ (match_operand:SI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
"flag_pic"
- "or\\t%1, %%lo(%a3-(%a2-.)), %0")
+ "or\t%1, %%lo(%a3-(%a2-.)), %0")
(define_expand "movdi"
[(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
- "
{
/* Where possible, convert CONST_DOUBLE into a CONST_INT. */
if (GET_CODE (operands[1]) == CONST_DOUBLE
@@ -2515,7 +2046,7 @@
movdi_is_ok:
;
-}")
+})
;; Be careful, fmovd does not exist when !v9.
;; We match MEM moves directly when we have correct even
@@ -2531,31 +2062,30 @@
(define_insn "*movdi_insn_sp32_v9"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?f,?e,?e,?W")
+ "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?e,?e,?W")
(match_operand:DI 1 "input_operand"
- " J,J,U,T,r,o,i,r, f, T, o, f, f, e, W, e"))]
+ " J,J,U,T,r,o,i,r, f, T, o, f, e, W, e"))]
"! TARGET_ARCH64 && TARGET_V9
&& (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
"@
- stx\\t%%g0, %0
+ stx\t%%g0, %0
#
- std\\t%1, %0
- ldd\\t%1, %0
+ std\t%1, %0
+ ldd\t%1, %0
#
#
#
#
- std\\t%1, %0
- ldd\\t%1, %0
- #
+ std\t%1, %0
+ ldd\t%1, %0
#
#
fmovd\\t%1, %0
ldd\\t%1, %0
std\\t%1, %0"
- [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,*,fpmove,fpload,fpstore")
- (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,2,*,*,*")
- (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
+ [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,fpmove,fpload,fpstore")
+ (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,*,*,*")
+ (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
(define_insn "*movdi_insn_sp32"
[(set (match_operand:DI 0 "nonimmediate_operand"
@@ -2567,14 +2097,14 @@
|| register_operand (operands[1], DImode))"
"@
#
- std\\t%1, %0
- ldd\\t%1, %0
+ std\t%1, %0
+ ldd\t%1, %0
#
#
#
#
- std\\t%1, %0
- ldd\\t%1, %0
+ std\t%1, %0
+ ldd\t%1, %0
#
#
#"
@@ -2587,7 +2117,7 @@
(match_operand:DI 1 "const64_operand" ""))]
"(TARGET_ARCH64
&& HOST_BITS_PER_WIDE_INT != 64)"
- "mov\\t%1, %0")
+ "mov\t%1, %0")
;; This is needed to show CSE exactly which bits are set
;; in a 64-bit register by sethi instructions.
@@ -2595,7 +2125,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(match_operand:DI 1 "const64_high_operand" ""))]
"TARGET_ARCH64"
- "sethi\\t%%hi(%a1), %0")
+ "sethi\t%%hi(%a1), %0")
(define_insn "*movdi_insn_sp64_novis"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?W")
@@ -2604,14 +2134,14 @@
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
"@
- mov\\t%1, %0
- sethi\\t%%hi(%a1), %0
- clr\\t%0
- ldx\\t%1, %0
- stx\\t%r1, %0
- fmovd\\t%1, %0
- ldd\\t%1, %0
- std\\t%1, %0"
+ mov\t%1, %0
+ sethi\t%%hi(%a1), %0
+ clr\t%0
+ ldx\t%1, %0
+ stx\t%r1, %0
+ fmovd\t%1, %0
+ ldd\t%1, %0
+ std\t%1, %0"
[(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore")
(set_attr "fptype" "*,*,*,*,*,double,*,*")])
@@ -2622,31 +2152,30 @@
(register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
"@
- mov\\t%1, %0
- sethi\\t%%hi(%a1), %0
- clr\\t%0
- ldx\\t%1, %0
- stx\\t%r1, %0
- fmovd\\t%1, %0
- ldd\\t%1, %0
- std\\t%1, %0
- fzero\\t%0"
+ mov\t%1, %0
+ sethi\t%%hi(%a1), %0
+ clr\t%0
+ ldx\t%1, %0
+ stx\t%r1, %0
+ fmovd\t%1, %0
+ ldd\t%1, %0
+ std\t%1, %0
+ fzero\t%0"
[(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore,fpmove")
(set_attr "fptype" "*,*,*,*,*,double,*,*,double")])
(define_expand "movdi_pic_label_ref"
[(set (match_dup 3) (high:DI
(unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
- (match_dup 2)] 5)))
+ (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
(set (match_dup 4) (lo_sum:DI (match_dup 3)
- (unspec:DI [(match_dup 1) (match_dup 2)] 5)))
+ (unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (match_dup 5) (match_dup 4)))]
"TARGET_ARCH64 && flag_pic"
- "
{
current_function_uses_pic_offset_table = 1;
- operands[2] = gen_rtx_SYMBOL_REF (Pmode, \"_GLOBAL_OFFSET_TABLE_\");
+ operands[2] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
if (no_new_pseudos)
{
operands[3] = operands[0];
@@ -2658,149 +2187,149 @@
operands[4] = gen_reg_rtx (DImode);
}
operands[5] = pic_offset_table_rtx;
-}")
+})
(define_insn "*movdi_high_pic_label_ref"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI
(unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
- (match_operand:DI 2 "" "")] 5)))]
+ (match_operand:DI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
"TARGET_ARCH64 && flag_pic"
- "sethi\\t%%hi(%a2-(%a1-.)), %0")
+ "sethi\t%%hi(%a2-(%a1-.)), %0")
(define_insn "*movdi_lo_sum_pic_label_ref"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(unspec:DI [(match_operand:DI 2 "label_ref_operand" "")
- (match_operand:DI 3 "" "")] 5)))]
+ (match_operand:DI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
"TARGET_ARCH64 && flag_pic"
- "or\\t%1, %%lo(%a3-(%a2-.)), %0")
+ "or\t%1, %%lo(%a3-(%a2-.)), %0")
-;; Sparc-v9 code model support insns. See sparc_emit_set_symbolic_const64
+;; SPARC-v9 code model support insns. See sparc_emit_set_symbolic_const64
;; in sparc.c to see what is going on here... PIC stuff comes first.
(define_insn "movdi_lo_sum_pic"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
- (unspec:DI [(match_operand:DI 2 "immediate_operand" "in")] 0)))]
+ (unspec:DI [(match_operand:DI 2 "immediate_operand" "in")] UNSPEC_MOVE_PIC)))]
"TARGET_ARCH64 && flag_pic"
- "or\\t%1, %%lo(%a2), %0")
+ "or\t%1, %%lo(%a2), %0")
(define_insn "movdi_high_pic"
[(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (unspec:DI [(match_operand 1 "" "")] 0)))]
+ (high:DI (unspec:DI [(match_operand 1 "" "")] UNSPEC_MOVE_PIC)))]
"TARGET_ARCH64 && flag_pic && check_pic (1)"
- "sethi\\t%%hi(%a1), %0")
+ "sethi\t%%hi(%a1), %0")
(define_insn "*sethi_di_medlow_embmedany_pic"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (match_operand:DI 1 "sp64_medium_pic_operand" "")))]
"(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"
- "sethi\\t%%hi(%a1), %0")
+ "sethi\t%%hi(%a1), %0")
(define_insn "*sethi_di_medlow"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (match_operand:DI 1 "symbolic_operand" "")))]
"TARGET_CM_MEDLOW && check_pic (1)"
- "sethi\\t%%hi(%a1), %0")
+ "sethi\t%%hi(%a1), %0")
(define_insn "*losum_di_medlow"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "symbolic_operand" "")))]
"TARGET_CM_MEDLOW"
- "or\\t%1, %%lo(%a2), %0")
+ "or\t%1, %%lo(%a2), %0")
(define_insn "seth44"
[(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] 6)))]
+ (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETH44)))]
"TARGET_CM_MEDMID"
- "sethi\\t%%h44(%a1), %0")
+ "sethi\t%%h44(%a1), %0")
(define_insn "setm44"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
- (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] 7)))]
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_SETM44)))]
"TARGET_CM_MEDMID"
- "or\\t%1, %%m44(%a2), %0")
+ "or\t%1, %%m44(%a2), %0")
(define_insn "setl44"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "symbolic_operand" "")))]
"TARGET_CM_MEDMID"
- "or\\t%1, %%l44(%a2), %0")
+ "or\t%1, %%l44(%a2), %0")
(define_insn "sethh"
[(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] 9)))]
+ (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETHH)))]
"TARGET_CM_MEDANY"
- "sethi\\t%%hh(%a1), %0")
+ "sethi\t%%hh(%a1), %0")
(define_insn "setlm"
[(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] 10)))]
+ (high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETLM)))]
"TARGET_CM_MEDANY"
- "sethi\\t%%lm(%a1), %0")
+ "sethi\t%%lm(%a1), %0")
(define_insn "sethm"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
- (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] 18)))]
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_EMB_SETHM)))]
"TARGET_CM_MEDANY"
- "or\\t%1, %%hm(%a2), %0")
+ "or\t%1, %%hm(%a2), %0")
(define_insn "setlo"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "symbolic_operand" "")))]
"TARGET_CM_MEDANY"
- "or\\t%1, %%lo(%a2), %0")
+ "or\t%1, %%lo(%a2), %0")
(define_insn "embmedany_sethi"
[(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (unspec:DI [(match_operand:DI 1 "data_segment_operand" "")] 11)))]
+ (high:DI (unspec:DI [(match_operand:DI 1 "data_segment_operand" "")] UNSPEC_EMB_HISUM)))]
"TARGET_CM_EMBMEDANY && check_pic (1)"
- "sethi\\t%%hi(%a1), %0")
+ "sethi\t%%hi(%a1), %0")
(define_insn "embmedany_losum"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "data_segment_operand" "")))]
"TARGET_CM_EMBMEDANY"
- "add\\t%1, %%lo(%a2), %0")
+ "add\t%1, %%lo(%a2), %0")
(define_insn "embmedany_brsum"
[(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "register_operand" "r")] 11))]
+ (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_EMB_HISUM))]
"TARGET_CM_EMBMEDANY"
- "add\\t%1, %_, %0")
+ "add\t%1, %_, %0")
(define_insn "embmedany_textuhi"
[(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] 13)))]
+ (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] UNSPEC_EMB_TEXTUHI)))]
"TARGET_CM_EMBMEDANY && check_pic (1)"
- "sethi\\t%%uhi(%a1), %0")
+ "sethi\t%%uhi(%a1), %0")
(define_insn "embmedany_texthi"
[(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] 14)))]
+ (high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] UNSPEC_EMB_TEXTHI)))]
"TARGET_CM_EMBMEDANY && check_pic (1)"
- "sethi\\t%%hi(%a1), %0")
+ "sethi\t%%hi(%a1), %0")
(define_insn "embmedany_textulo"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
- (unspec:DI [(match_operand:DI 2 "text_segment_operand" "")] 15)))]
+ (unspec:DI [(match_operand:DI 2 "text_segment_operand" "")] UNSPEC_EMB_TEXTULO)))]
"TARGET_CM_EMBMEDANY"
- "or\\t%1, %%ulo(%a2), %0")
+ "or\t%1, %%ulo(%a2), %0")
(define_insn "embmedany_textlo"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "text_segment_operand" "")))]
"TARGET_CM_EMBMEDANY"
- "or\\t%1, %%lo(%a2), %0")
+ "or\t%1, %%lo(%a2), %0")
;; Now some patterns to help reload out a bit.
(define_expand "reload_indi"
@@ -2810,11 +2339,10 @@
"(TARGET_CM_MEDANY
|| TARGET_CM_EMBMEDANY)
&& ! flag_pic"
- "
{
sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
DONE;
-}")
+})
(define_expand "reload_outdi"
[(parallel [(match_operand:DI 0 "register_operand" "=r")
@@ -2823,11 +2351,10 @@
"(TARGET_CM_MEDANY
|| TARGET_CM_EMBMEDANY)
&& ! flag_pic"
- "
{
sparc_emit_set_symbolic_const64 (operands[0], operands[1], operands[2]);
DONE;
-}")
+})
;; Split up putting CONSTs and REGs into DI regs when !arch64
(define_split
@@ -2835,7 +2362,6 @@
(match_operand:DI 1 "const_int_operand" ""))]
"! TARGET_ARCH64 && reload_completed"
[(clobber (const_int 0))]
- "
{
#if HOST_BITS_PER_WIDE_INT == 32
emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
@@ -2860,7 +2386,7 @@
emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]), GEN_INT (low)));
#endif
DONE;
-}")
+})
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -2874,7 +2400,6 @@
&& GET_CODE (SUBREG_REG (operands[0])) == REG
&& REGNO (SUBREG_REG (operands[0])) < 32))))"
[(clobber (const_int 0))]
- "
{
emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
GEN_INT (CONST_DOUBLE_HIGH (operands[1]))));
@@ -2894,14 +2419,20 @@
GEN_INT (CONST_DOUBLE_LOW (operands[1]))));
}
DONE;
-}")
+})
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(match_operand:DI 1 "register_operand" ""))]
- "! TARGET_ARCH64 && reload_completed"
+ "reload_completed
+ && (! TARGET_V9
+ || (! TARGET_ARCH64
+ && ((GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) < 32)
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && REGNO (SUBREG_REG (operands[0])) < 32))))"
[(clobber (const_int 0))]
- "
{
rtx set_dest = operands[0];
rtx set_src = operands[1];
@@ -2926,7 +2457,7 @@
emit_insn (gen_movsi (dest2, src2));
}
DONE;
-}")
+})
;; Now handle the cases of memory moves from/to non-even
;; DI mode register pairs.
@@ -2937,7 +2468,6 @@
&& reload_completed
&& sparc_splitdi_legitimate (operands[0], operands[1]))"
[(clobber (const_int 0))]
- "
{
rtx word0 = adjust_address (operands[1], SImode, 0);
rtx word1 = adjust_address (operands[1], SImode, 4);
@@ -2955,7 +2485,7 @@
emit_insn (gen_movsi (low_part, word1));
}
DONE;
-}")
+})
(define_split
[(set (match_operand:DI 0 "memory_operand" "")
@@ -2964,14 +2494,13 @@
&& reload_completed
&& sparc_splitdi_legitimate (operands[1], operands[0]))"
[(clobber (const_int 0))]
- "
{
emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0),
gen_highpart (SImode, operands[1])));
emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4),
gen_lowpart (SImode, operands[1])));
DONE;
-}")
+})
(define_split
[(set (match_operand:DI 0 "memory_operand" "")
@@ -2982,12 +2511,11 @@
&& ! mem_min_alignment (operands[0], 8)))
&& offsettable_memref_p (operands[0])"
[(clobber (const_int 0))]
- "
{
emit_insn (gen_movsi (adjust_address (operands[0], SImode, 0), const0_rtx));
emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4), const0_rtx));
DONE;
-}")
+})
;; Floating point move insns
@@ -2998,7 +2526,6 @@
&& (register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode)
|| fp_zero_operand (operands[1], SFmode))"
- "*
{
if (GET_CODE (operands[1]) == CONST_DOUBLE
&& (which_alternative == 2
@@ -3016,25 +2543,25 @@
switch (which_alternative)
{
case 0:
- return \"fmovs\\t%1, %0\";
+ return "fmovs\t%1, %0";
case 1:
- return \"clr\\t%0\";
+ return "clr\t%0";
case 2:
- return \"sethi\\t%%hi(%a1), %0\";
+ return "sethi\t%%hi(%a1), %0";
case 3:
- return \"mov\\t%1, %0\";
+ return "mov\t%1, %0";
case 4:
- return \"#\";
+ return "#";
case 5:
case 6:
- return \"ld\\t%1, %0\";
+ return "ld\t%1, %0";
case 7:
case 8:
- return \"st\\t%r1, %0\";
+ return "st\t%r1, %0";
default:
abort();
}
-}"
+}
[(set_attr "type" "fpmove,*,*,*,*,load,fpload,fpstore,store")])
(define_insn "*movsf_insn_vis"
@@ -3044,7 +2571,6 @@
&& (register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode)
|| fp_zero_operand (operands[1], SFmode))"
- "*
{
if (GET_CODE (operands[1]) == CONST_DOUBLE
&& (which_alternative == 3
@@ -3062,27 +2588,27 @@
switch (which_alternative)
{
case 0:
- return \"fmovs\\t%1, %0\";
+ return "fmovs\t%1, %0";
case 1:
- return \"fzeros\\t%0\";
+ return "fzeros\t%0";
case 2:
- return \"clr\\t%0\";
+ return "clr\t%0";
case 3:
- return \"sethi\\t%%hi(%a1), %0\";
+ return "sethi\t%%hi(%a1), %0";
case 4:
- return \"mov\\t%1, %0\";
+ return "mov\t%1, %0";
case 5:
- return \"#\";
+ return "#";
case 6:
case 7:
- return \"ld\\t%1, %0\";
+ return "ld\t%1, %0";
case 8:
case 9:
- return \"st\\t%r1, %0\";
+ return "st\t%r1, %0";
default:
abort();
}
-}"
+}
[(set_attr "type" "fpmove,fpmove,*,*,*,*,load,fpload,fpstore,store")])
;; Exactly the same as above, except that all `f' cases are deleted.
@@ -3096,7 +2622,6 @@
&& (register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode)
|| fp_zero_operand (operands[1], SFmode))"
- "*
{
if (GET_CODE (operands[1]) == CONST_DOUBLE
&& (which_alternative == 1
@@ -3114,21 +2639,21 @@
switch (which_alternative)
{
case 0:
- return \"clr\\t%0\";
+ return "clr\t%0";
case 1:
- return \"sethi\\t%%hi(%a1), %0\";
+ return "sethi\t%%hi(%a1), %0";
case 2:
- return \"mov\\t%1, %0\";
+ return "mov\t%1, %0";
case 3:
- return \"#\";
+ return "#";
case 4:
- return \"ld\\t%1, %0\";
+ return "ld\t%1, %0";
case 5:
- return \"st\\t%r1, %0\";
+ return "st\t%r1, %0";
default:
abort();
}
-}"
+}
[(set_attr "type" "*,*,*,*,load,store")])
(define_insn "*movsf_lo_sum"
@@ -3136,7 +2661,6 @@
(lo_sum:SF (match_operand:SF 1 "register_operand" "r")
(match_operand:SF 2 "const_double_operand" "S")))]
"fp_high_losum_p (operands[2])"
- "*
{
REAL_VALUE_TYPE r;
long i;
@@ -3144,14 +2668,13 @@
REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
REAL_VALUE_TO_TARGET_SINGLE (r, i);
operands[2] = GEN_INT (i);
- return \"or\\t%1, %%lo(%a2), %0\";
-}")
+ return "or\t%1, %%lo(%a2), %0";
+})
(define_insn "*movsf_high"
[(set (match_operand:SF 0 "register_operand" "=r")
(high:SF (match_operand:SF 1 "const_double_operand" "S")))]
"fp_high_losum_p (operands[1])"
- "*
{
REAL_VALUE_TYPE r;
long i;
@@ -3159,8 +2682,8 @@
REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
REAL_VALUE_TO_TARGET_SINGLE (r, i);
operands[1] = GEN_INT (i);
- return \"sethi\\t%%hi(%1), %0\";
-}")
+ return "sethi\t%%hi(%1), %0";
+})
(define_split
[(set (match_operand:SF 0 "register_operand" "")
@@ -3175,7 +2698,6 @@
[(set (match_operand:SF 0 "general_operand" "")
(match_operand:SF 1 "general_operand" ""))]
""
- "
{
/* Force SFmode constants into memory. */
if (GET_CODE (operands[0]) == REG
@@ -3232,13 +2754,12 @@
movsf_is_ok:
;
-}")
+})
(define_expand "movdf"
[(set (match_operand:DF 0 "general_operand" "")
(match_operand:DF 1 "general_operand" ""))]
""
- "
{
/* Force DFmode constants into memory. */
if (GET_CODE (operands[0]) == REG
@@ -3296,7 +2817,7 @@
movdf_is_ok:
;
-}")
+})
;; Be careful, fmovd does not exist when !v9.
(define_insn "*movdf_insn_sp32"
@@ -3308,10 +2829,10 @@
|| register_operand (operands[1], DFmode)
|| fp_zero_operand (operands[1], DFmode))"
"@
- ldd\\t%1, %0
- std\\t%1, %0
- ldd\\t%1, %0
- std\\t%1, %0
+ ldd\t%1, %0
+ std\t%1, %0
+ ldd\t%1, %0
+ std\t%1, %0
#
#
#
@@ -3331,8 +2852,8 @@
|| register_operand (operands[1], DFmode)
|| fp_zero_operand (operands[1], DFmode))"
"@
- ldd\\t%1, %0
- std\\t%1, %0
+ ldd\t%1, %0
+ std\t%1, %0
#
#
#"
@@ -3349,9 +2870,9 @@
|| register_operand (operands[1], DFmode)
|| fp_zero_operand (operands[1], DFmode))"
"@
- ldd\\t%1, %0
- std\\t%1, %0
- stx\\t%r1, %0
+ ldd\t%1, %0
+ std\t%1, %0
+ stx\t%r1, %0
#
#"
[(set_attr "type" "load,store,store,*,*")
@@ -3370,12 +2891,12 @@
|| register_operand (operands[1], DFmode)
|| fp_zero_operand (operands[1], DFmode))"
"@
- fmovd\\t%1, %0
- ldd\\t%1, %0
- stx\\t%r1, %0
- std\\t%1, %0
- ldd\\t%1, %0
- std\\t%1, %0
+ fmovd\t%1, %0
+ ldd\t%1, %0
+ stx\t%r1, %0
+ std\t%1, %0
+ ldd\t%1, %0
+ std\t%1, %0
#
#
#"
@@ -3395,13 +2916,13 @@
|| register_operand (operands[1], DFmode)
|| fp_zero_operand (operands[1], DFmode))"
"@
- fzero\\t%0
- fmovd\\t%1, %0
- ldd\\t%1, %0
- stx\\t%r1, %0
- std\\t%1, %0
- ldd\\t%1, %0
- std\\t%1, %0
+ fzero\t%0
+ fmovd\t%1, %0
+ ldd\t%1, %0
+ stx\t%r1, %0
+ std\t%1, %0
+ ldd\t%1, %0
+ std\t%1, %0
#
#
#"
@@ -3421,12 +2942,12 @@
|| register_operand (operands[1], DFmode)
|| fp_zero_operand (operands[1], DFmode))"
"@
- fmovd\\t%1, %0
- ldd\\t%1, %0
- std\\t%1, %0
- mov\\t%r1, %0
- ldx\\t%1, %0
- stx\\t%r1, %0
+ fmovd\t%1, %0
+ ldd\t%1, %0
+ std\t%1, %0
+ mov\t%r1, %0
+ ldx\t%1, %0
+ stx\t%r1, %0
#"
[(set_attr "type" "fpmove,load,store,*,load,store,*")
(set_attr "length" "*,*,*,*,*,*,2")
@@ -3444,13 +2965,13 @@
|| register_operand (operands[1], DFmode)
|| fp_zero_operand (operands[1], DFmode))"
"@
- fzero\\t%0
- fmovd\\t%1, %0
- ldd\\t%1, %0
- std\\t%1, %0
- mov\\t%r1, %0
- ldx\\t%1, %0
- stx\\t%r1, %0
+ fzero\t%0
+ fmovd\t%1, %0
+ ldd\t%1, %0
+ std\t%1, %0
+ mov\t%r1, %0
+ ldx\t%1, %0
+ stx\t%r1, %0
#"
[(set_attr "type" "fpmove,fpmove,load,store,*,load,store,*")
(set_attr "length" "*,*,*,*,*,*,*,2")
@@ -3465,9 +2986,9 @@
|| register_operand (operands[1], DFmode)
|| fp_zero_operand (operands[1], DFmode))"
"@
- mov\\t%1, %0
- ldx\\t%1, %0
- stx\\t%r1, %0"
+ mov\t%1, %0
+ ldx\t%1, %0
+ stx\t%r1, %0"
[(set_attr "type" "*,load,store")])
(define_split
@@ -3479,7 +3000,6 @@
&& ! fp_zero_operand(operands[1], DFmode)
&& reload_completed"
[(clobber (const_int 0))]
- "
{
REAL_VALUE_TYPE r;
long l[2];
@@ -3498,7 +3018,7 @@
emit_insn (gen_movdi (operands[0], GEN_INT (val)));
#else
emit_insn (gen_movdi (operands[0],
- gen_rtx_CONST_DOUBLE (VOIDmode, l[1], l[0])));
+ immed_double_const (l[1], l[0], DImode)));
#endif
}
else
@@ -3522,7 +3042,7 @@
}
}
DONE;
-}")
+})
;; Ok, now the splits to handle all the multi insn and
;; mis-aligned memory address cases.
@@ -3541,7 +3061,6 @@
&& REGNO (SUBREG_REG (operands[0])) < 32))))
&& reload_completed"
[(clobber (const_int 0))]
- "
{
rtx set_dest = operands[0];
rtx set_src = operands[1];
@@ -3566,7 +3085,7 @@
emit_insn (gen_movsf (dest2, src2));
}
DONE;
-}")
+})
(define_split
[(set (match_operand:DF 0 "register_operand" "")
@@ -3577,7 +3096,6 @@
|| ! mem_min_alignment (operands[1], 8))
&& offsettable_memref_p (operands[1])"
[(clobber (const_int 0))]
- "
{
rtx word0 = adjust_address (operands[1], SFmode, 0);
rtx word1 = adjust_address (operands[1], SFmode, 4);
@@ -3597,7 +3115,7 @@
word1));
}
DONE;
-}")
+})
(define_split
[(set (match_operand:DF 0 "memory_operand" "")
@@ -3608,7 +3126,6 @@
|| ! mem_min_alignment (operands[0], 8))
&& offsettable_memref_p (operands[0])"
[(clobber (const_int 0))]
- "
{
rtx word0 = adjust_address (operands[0], SFmode, 0);
rtx word1 = adjust_address (operands[0], SFmode, 4);
@@ -3618,7 +3135,7 @@
emit_insn (gen_movsf (word1,
gen_lowpart (SFmode, operands[1])));
DONE;
-}")
+})
(define_split
[(set (match_operand:DF 0 "memory_operand" "")
@@ -3629,7 +3146,6 @@
&& ! mem_min_alignment (operands[0], 8)))
&& offsettable_memref_p (operands[0])"
[(clobber (const_int 0))]
- "
{
rtx dest1, dest2;
@@ -3639,7 +3155,7 @@
emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode)));
emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode)));
DONE;
-}")
+})
(define_split
[(set (match_operand:DF 0 "register_operand" "")
@@ -3652,7 +3168,6 @@
&& GET_CODE (SUBREG_REG (operands[0])) == REG
&& REGNO (SUBREG_REG (operands[0])) < 32))"
[(clobber (const_int 0))]
- "
{
rtx set_dest = operands[0];
rtx dest1, dest2;
@@ -3662,13 +3177,12 @@
emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode)));
emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode)));
DONE;
-}")
+})
(define_expand "movtf"
[(set (match_operand:TF 0 "general_operand" "")
(match_operand:TF 1 "general_operand" ""))]
""
- "
{
/* Force TFmode constants into memory. */
if (GET_CODE (operands[0]) == REG
@@ -3721,7 +3235,7 @@
movtf_is_ok:
;
-}")
+})
;; Be careful, fmovq and {st,ld}{x,q} do not exist when !arch64 so
;; we must split them all. :-(
@@ -3777,9 +3291,9 @@
|| register_operand (operands[1], TFmode)
|| fp_zero_operand (operands[1], TFmode))"
"@
- fmovq\\t%1, %0
- ldq\\t%1, %0
- stq\\t%1, %0
+ fmovq\t%1, %0
+ ldq\t%1, %0
+ stq\t%1, %0
#
#"
[(set_attr "type" "fpmove,fpload,fpstore,*,*")
@@ -3796,9 +3310,9 @@
|| register_operand (operands[1], TFmode)
|| fp_zero_operand (operands[1], TFmode))"
"@
- fmovq\\t%1, %0
- ldq\\t%1, %0
- stq\\t%1, %0
+ fmovq\t%1, %0
+ ldq\t%1, %0
+ stq\t%1, %0
#
#
#"
@@ -3854,7 +3368,6 @@
&& ! TARGET_HARD_QUAD)
|| ! fp_register_operand (operands[0], TFmode))"
[(clobber (const_int 0))]
- "
{
rtx set_dest = operands[0];
rtx set_src = operands[1];
@@ -3879,14 +3392,13 @@
emit_insn (gen_movdf (dest2, src2));
}
DONE;
-}")
+})
(define_split
[(set (match_operand:TF 0 "nonimmediate_operand" "")
(match_operand:TF 1 "fp_zero_operand" ""))]
"reload_completed"
[(clobber (const_int 0))]
- "
{
rtx set_dest = operands[0];
rtx dest1, dest2;
@@ -3908,7 +3420,7 @@
emit_insn (gen_movdf (dest1, CONST0_RTX (DFmode)));
emit_insn (gen_movdf (dest2, CONST0_RTX (DFmode)));
DONE;
-}")
+})
(define_split
[(set (match_operand:TF 0 "register_operand" "")
@@ -3919,7 +3431,6 @@
|| ! TARGET_HARD_QUAD
|| ! fp_register_operand (operands[0], TFmode)))"
[(clobber (const_int 0))]
- "
{
rtx word0 = adjust_address (operands[1], DFmode, 0);
rtx word1 = adjust_address (operands[1], DFmode, 8);
@@ -3944,7 +3455,7 @@
emit_insn (gen_movdf (dest2, word1));
}
DONE;
-}")
+})
(define_split
[(set (match_operand:TF 0 "memory_operand" "")
@@ -3955,7 +3466,6 @@
|| ! TARGET_HARD_QUAD
|| ! fp_register_operand (operands[1], TFmode)))"
[(clobber (const_int 0))]
- "
{
rtx set_src = operands[1];
@@ -3964,12 +3474,12 @@
emit_insn (gen_movdf (adjust_address (operands[0], DFmode, 8),
gen_df_reg (set_src, 1)));
DONE;
-}")
+})
-;; Sparc V9 conditional move instructions.
+;; SPARC V9 conditional move instructions.
;; We can handle larger constants here for some flavors, but for now we keep
-;; it simple and only allow those constants supported by all flavours.
+;; it simple and only allow those constants supported by all flavors.
;; 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).
@@ -3980,7 +3490,6 @@
(match_operand:QI 2 "arith10_operand" "")
(match_operand:QI 3 "arith10_operand" "")))]
"TARGET_V9"
- "
{
enum rtx_code code = GET_CODE (operands[1]);
@@ -4002,7 +3511,7 @@
sparc_compare_op0, sparc_compare_op1);
operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
}
-}")
+})
(define_expand "movhicc"
[(set (match_operand:HI 0 "register_operand" "")
@@ -4010,7 +3519,6 @@
(match_operand:HI 2 "arith10_operand" "")
(match_operand:HI 3 "arith10_operand" "")))]
"TARGET_V9"
- "
{
enum rtx_code code = GET_CODE (operands[1]);
@@ -4032,7 +3540,7 @@
sparc_compare_op0, sparc_compare_op1);
operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
}
-}")
+})
(define_expand "movsicc"
[(set (match_operand:SI 0 "register_operand" "")
@@ -4040,7 +3548,6 @@
(match_operand:SI 2 "arith10_operand" "")
(match_operand:SI 3 "arith10_operand" "")))]
"TARGET_V9"
- "
{
enum rtx_code code = GET_CODE (operands[1]);
enum machine_mode op0_mode = GET_MODE (sparc_compare_op0);
@@ -4059,7 +3566,7 @@
operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
cc_reg, const0_rtx);
}
-}")
+})
(define_expand "movdicc"
[(set (match_operand:DI 0 "register_operand" "")
@@ -4067,7 +3574,6 @@
(match_operand:DI 2 "arith10_double_operand" "")
(match_operand:DI 3 "arith10_double_operand" "")))]
"TARGET_ARCH64"
- "
{
enum rtx_code code = GET_CODE (operands[1]);
@@ -4086,7 +3592,7 @@
operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
cc_reg, const0_rtx);
}
-}")
+})
(define_expand "movsfcc"
[(set (match_operand:SF 0 "register_operand" "")
@@ -4094,7 +3600,6 @@
(match_operand:SF 2 "register_operand" "")
(match_operand:SF 3 "register_operand" "")))]
"TARGET_V9 && TARGET_FPU"
- "
{
enum rtx_code code = GET_CODE (operands[1]);
@@ -4116,7 +3621,7 @@
sparc_compare_op0, sparc_compare_op1);
operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
}
-}")
+})
(define_expand "movdfcc"
[(set (match_operand:DF 0 "register_operand" "")
@@ -4124,7 +3629,6 @@
(match_operand:DF 2 "register_operand" "")
(match_operand:DF 3 "register_operand" "")))]
"TARGET_V9 && TARGET_FPU"
- "
{
enum rtx_code code = GET_CODE (operands[1]);
@@ -4146,7 +3650,7 @@
sparc_compare_op0, sparc_compare_op1);
operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
}
-}")
+})
(define_expand "movtfcc"
[(set (match_operand:TF 0 "register_operand" "")
@@ -4154,7 +3658,6 @@
(match_operand:TF 2 "register_operand" "")
(match_operand:TF 3 "register_operand" "")))]
"TARGET_V9 && TARGET_FPU"
- "
{
enum rtx_code code = GET_CODE (operands[1]);
@@ -4176,7 +3679,7 @@
sparc_compare_op0, sparc_compare_op1);
operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
}
-}")
+})
;; Conditional move define_insns.
@@ -4189,8 +3692,8 @@
(match_operand:QI 4 "arith11_operand" "0,rL")))]
"TARGET_V9"
"@
- mov%C1\\t%x2, %3, %0
- mov%c1\\t%x2, %4, %0"
+ mov%C1\t%x2, %3, %0
+ mov%c1\t%x2, %4, %0"
[(set_attr "type" "cmove")])
(define_insn "*movhi_cc_sp64"
@@ -4202,8 +3705,8 @@
(match_operand:HI 4 "arith11_operand" "0,rL")))]
"TARGET_V9"
"@
- mov%C1\\t%x2, %3, %0
- mov%c1\\t%x2, %4, %0"
+ mov%C1\t%x2, %3, %0
+ mov%c1\t%x2, %4, %0"
[(set_attr "type" "cmove")])
(define_insn "*movsi_cc_sp64"
@@ -4215,8 +3718,8 @@
(match_operand:SI 4 "arith11_operand" "0,rL")))]
"TARGET_V9"
"@
- mov%C1\\t%x2, %3, %0
- mov%c1\\t%x2, %4, %0"
+ mov%C1\t%x2, %3, %0
+ mov%c1\t%x2, %4, %0"
[(set_attr "type" "cmove")])
;; ??? The constraints of operands 3,4 need work.
@@ -4229,8 +3732,8 @@
(match_operand:DI 4 "arith11_double_operand" "0,rLH")))]
"TARGET_ARCH64"
"@
- mov%C1\\t%x2, %3, %0
- mov%c1\\t%x2, %4, %0"
+ mov%C1\t%x2, %3, %0
+ mov%c1\t%x2, %4, %0"
[(set_attr "type" "cmove")])
(define_insn "*movdi_cc_sp64_trunc"
@@ -4242,8 +3745,8 @@
(match_operand:SI 4 "arith11_double_operand" "0,rLH")))]
"TARGET_ARCH64"
"@
- mov%C1\\t%x2, %3, %0
- mov%c1\\t%x2, %4, %0"
+ mov%C1\t%x2, %3, %0
+ mov%c1\t%x2, %4, %0"
[(set_attr "type" "cmove")])
(define_insn "*movsf_cc_sp64"
@@ -4255,8 +3758,8 @@
(match_operand:SF 4 "register_operand" "0,f")))]
"TARGET_V9 && TARGET_FPU"
"@
- fmovs%C1\\t%x2, %3, %0
- fmovs%c1\\t%x2, %4, %0"
+ fmovs%C1\t%x2, %3, %0
+ fmovs%c1\t%x2, %4, %0"
[(set_attr "type" "fpcmove")])
(define_insn "movdf_cc_sp64"
@@ -4268,8 +3771,8 @@
(match_operand:DF 4 "register_operand" "0,e")))]
"TARGET_V9 && TARGET_FPU"
"@
- fmovd%C1\\t%x2, %3, %0
- fmovd%c1\\t%x2, %4, %0"
+ fmovd%C1\t%x2, %3, %0
+ fmovd%c1\t%x2, %4, %0"
[(set_attr "type" "fpcmove")
(set_attr "fptype" "double")])
@@ -4282,31 +3785,21 @@
(match_operand:TF 4 "register_operand" "0,e")))]
"TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
"@
- fmovq%C1\\t%x2, %3, %0
- fmovq%c1\\t%x2, %4, %0"
+ fmovq%C1\t%x2, %3, %0
+ fmovq%c1\t%x2, %4, %0"
[(set_attr "type" "fpcmove")])
-(define_insn "*movtf_cc_sp64"
+(define_insn_and_split "*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 2 "icc_or_fcc_reg_operand" "X,X")
+ (const_int 0)])
(match_operand:TF 3 "register_operand" "e,0")
(match_operand:TF 4 "register_operand" "0,e")))]
"TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:TF 0 "register_operand" "")
- (if_then_else:TF (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_reg_operand" "")
- (const_int 0)])
- (match_operand:TF 3 "register_operand" "")
- (match_operand:TF 4 "register_operand" "")))]
- "reload_completed && TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
+ "&& reload_completed"
[(clobber (const_int 0))]
- "
{
rtx set_dest = operands[0];
rtx set_srca = operands[3];
@@ -4336,7 +3829,8 @@
emit_insn (gen_movdf_cc_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
}
DONE;
-}")
+}
+ [(set_attr "length" "2")])
(define_insn "*movqi_cc_reg_sp64"
[(set (match_operand:QI 0 "register_operand" "=r,r")
@@ -4347,8 +3841,8 @@
(match_operand:QI 4 "arith10_operand" "0,rM")))]
"TARGET_ARCH64"
"@
- movr%D1\\t%2, %r3, %0
- movr%d1\\t%2, %r4, %0"
+ movr%D1\t%2, %r3, %0
+ movr%d1\t%2, %r4, %0"
[(set_attr "type" "cmove")])
(define_insn "*movhi_cc_reg_sp64"
@@ -4360,8 +3854,8 @@
(match_operand:HI 4 "arith10_operand" "0,rM")))]
"TARGET_ARCH64"
"@
- movr%D1\\t%2, %r3, %0
- movr%d1\\t%2, %r4, %0"
+ movr%D1\t%2, %r3, %0
+ movr%d1\t%2, %r4, %0"
[(set_attr "type" "cmove")])
(define_insn "*movsi_cc_reg_sp64"
@@ -4373,8 +3867,8 @@
(match_operand:SI 4 "arith10_operand" "0,rM")))]
"TARGET_ARCH64"
"@
- movr%D1\\t%2, %r3, %0
- movr%d1\\t%2, %r4, %0"
+ movr%D1\t%2, %r3, %0
+ movr%d1\t%2, %r4, %0"
[(set_attr "type" "cmove")])
;; ??? The constraints of operands 3,4 need work.
@@ -4387,8 +3881,8 @@
(match_operand:DI 4 "arith10_double_operand" "0,rMH")))]
"TARGET_ARCH64"
"@
- movr%D1\\t%2, %r3, %0
- movr%d1\\t%2, %r4, %0"
+ movr%D1\t%2, %r3, %0
+ movr%d1\t%2, %r4, %0"
[(set_attr "type" "cmove")])
(define_insn "*movdi_cc_reg_sp64_trunc"
@@ -4400,8 +3894,8 @@
(match_operand:SI 4 "arith10_double_operand" "0,rMH")))]
"TARGET_ARCH64"
"@
- movr%D1\\t%2, %r3, %0
- movr%d1\\t%2, %r4, %0"
+ movr%D1\t%2, %r3, %0
+ movr%d1\t%2, %r4, %0"
[(set_attr "type" "cmove")])
(define_insn "*movsf_cc_reg_sp64"
@@ -4413,9 +3907,9 @@
(match_operand:SF 4 "register_operand" "0,f")))]
"TARGET_ARCH64 && TARGET_FPU"
"@
- fmovrs%D1\\t%2, %3, %0
- fmovrs%d1\\t%2, %4, %0"
- [(set_attr "type" "fpcmove")])
+ fmovrs%D1\t%2, %3, %0
+ fmovrs%d1\t%2, %4, %0"
+ [(set_attr "type" "fpcrmove")])
(define_insn "movdf_cc_reg_sp64"
[(set (match_operand:DF 0 "register_operand" "=e,e")
@@ -4426,9 +3920,9 @@
(match_operand:DF 4 "register_operand" "0,e")))]
"TARGET_ARCH64 && TARGET_FPU"
"@
- fmovrd%D1\\t%2, %3, %0
- fmovrd%d1\\t%2, %4, %0"
- [(set_attr "type" "fpcmove")
+ fmovrd%D1\t%2, %3, %0
+ fmovrd%d1\t%2, %4, %0"
+ [(set_attr "type" "fpcrmove")
(set_attr "fptype" "double")])
(define_insn "*movtf_cc_reg_hq_sp64"
@@ -4440,11 +3934,11 @@
(match_operand:TF 4 "register_operand" "0,e")))]
"TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
"@
- fmovrq%D1\\t%2, %3, %0
- fmovrq%d1\\t%2, %4, %0"
- [(set_attr "type" "fpcmove")])
+ fmovrq%D1\t%2, %3, %0
+ fmovrq%d1\t%2, %4, %0"
+ [(set_attr "type" "fpcrmove")])
-(define_insn "*movtf_cc_reg_sp64"
+(define_insn_and_split "*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")
@@ -4453,18 +3947,8 @@
(match_operand:TF 4 "register_operand" "0,e")))]
"TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:TF 0 "register_operand" "")
- (if_then_else:TF (match_operator 1 "v9_regcmp_op"
- [(match_operand:DI 2 "register_operand" "")
- (const_int 0)])
- (match_operand:TF 3 "register_operand" "")
- (match_operand:TF 4 "register_operand" "")))]
- "reload_completed && TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
+ "&& reload_completed"
[(clobber (const_int 0))]
- "
{
rtx set_dest = operands[0];
rtx set_srca = operands[3];
@@ -4494,7 +3978,8 @@
emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
}
DONE;
-}")
+}
+ [(set_attr "length" "2")])
;;- zero extension instructions
@@ -4507,7 +3992,6 @@
[(set (match_operand:SI 0 "register_operand" "")
(zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
""
- "
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_16 = GEN_INT (16);
@@ -4525,14 +4009,15 @@
shift_16));
emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
DONE;
-}")
+})
(define_insn "*zero_extendhisi2_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
""
- "lduh\\t%1, %0"
- [(set_attr "type" "load")])
+ "lduh\t%1, %0"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
(define_expand "zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "")
@@ -4545,9 +4030,10 @@
(zero_extend:HI (match_operand:QI 1 "input_operand" "r,m")))]
"GET_CODE (operands[1]) != CONST_INT"
"@
- and\\t%1, 0xff, %0
- ldub\\t%1, %0"
- [(set_attr "type" "*,load")])
+ and\t%1, 0xff, %0
+ ldub\t%1, %0"
+ [(set_attr "type" "*,load")
+ (set_attr "us3load_type" "*,3cycle")])
(define_expand "zero_extendqisi2"
[(set (match_operand:SI 0 "register_operand" "")
@@ -4560,9 +4046,10 @@
(zero_extend:SI (match_operand:QI 1 "input_operand" "r,m")))]
"GET_CODE (operands[1]) != CONST_INT"
"@
- and\\t%1, 0xff, %0
- ldub\\t%1, %0"
- [(set_attr "type" "*,load")])
+ and\t%1, 0xff, %0
+ ldub\t%1, %0"
+ [(set_attr "type" "*,load")
+ (set_attr "us3load_type" "*,3cycle")])
(define_expand "zero_extendqidi2"
[(set (match_operand:DI 0 "register_operand" "")
@@ -4575,15 +4062,15 @@
(zero_extend:DI (match_operand:QI 1 "input_operand" "r,m")))]
"TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
"@
- and\\t%1, 0xff, %0
- ldub\\t%1, %0"
- [(set_attr "type" "*,load")])
+ and\t%1, 0xff, %0
+ ldub\t%1, %0"
+ [(set_attr "type" "*,load")
+ (set_attr "us3load_type" "*,3cycle")])
(define_expand "zero_extendhidi2"
[(set (match_operand:DI 0 "register_operand" "")
(zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
"TARGET_ARCH64"
- "
{
rtx temp = gen_reg_rtx (DImode);
rtx shift_48 = GEN_INT (48);
@@ -4601,14 +4088,15 @@
shift_48));
emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
DONE;
-}")
+})
(define_insn "*zero_extendhidi2_insn"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
"TARGET_ARCH64"
- "lduh\\t%1, %0"
- [(set_attr "type" "load")])
+ "lduh\t%1, %0"
+ [(set_attr "type" "load")
+ (set_attr "us3load_type" "3cycle")])
;; ??? Write truncdisi pattern using sra?
@@ -4624,24 +4112,18 @@
(zero_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
"TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
"@
- srl\\t%1, 0, %0
- lduw\\t%1, %0"
+ srl\t%1, 0, %0
+ lduw\t%1, %0"
[(set_attr "type" "shift,load")])
-(define_insn "*zero_extendsidi2_insn_sp32"
+(define_insn_and_split "*zero_extendsidi2_insn_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
"! TARGET_ARCH64"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
- "! TARGET_ARCH64 && reload_completed"
+ "&& reload_completed"
[(set (match_dup 2) (match_dup 3))
(set (match_dup 4) (match_dup 5))]
- "
{
rtx dest1, dest2;
@@ -4663,7 +4145,8 @@
operands[4] = dest2;
operands[5] = operands[1];
}
-}")
+}
+ [(set_attr "length" "2")])
;; Simplify comparisons of extended values.
@@ -4672,7 +4155,7 @@
(compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
(const_int 0)))]
""
- "andcc\\t%0, 0xff, %%g0"
+ "andcc\t%0, 0xff, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_zero_qi"
@@ -4680,7 +4163,7 @@
(compare:CC (match_operand:QI 0 "register_operand" "r")
(const_int 0)))]
""
- "andcc\\t%0, 0xff, %%g0"
+ "andcc\t%0, 0xff, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_zero_extendqisi2_set"
@@ -4690,7 +4173,7 @@
(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (match_dup 1)))]
""
- "andcc\\t%1, 0xff, %0"
+ "andcc\t%1, 0xff, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_zero_extendqisi2_andcc_set"
@@ -4701,7 +4184,7 @@
(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (subreg:QI (match_dup 1) 0)))]
""
- "andcc\\t%1, 0xff, %0"
+ "andcc\t%1, 0xff, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_zero_extendqidi2"
@@ -4709,7 +4192,7 @@
(compare:CCX (zero_extend:DI (match_operand:QI 0 "register_operand" "r"))
(const_int 0)))]
"TARGET_ARCH64"
- "andcc\\t%0, 0xff, %%g0"
+ "andcc\t%0, 0xff, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_zero_qi_sp64"
@@ -4717,7 +4200,7 @@
(compare:CCX (match_operand:QI 0 "register_operand" "r")
(const_int 0)))]
"TARGET_ARCH64"
- "andcc\\t%0, 0xff, %%g0"
+ "andcc\t%0, 0xff, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_zero_extendqidi2_set"
@@ -4727,7 +4210,7 @@
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (match_dup 1)))]
"TARGET_ARCH64"
- "andcc\\t%1, 0xff, %0"
+ "andcc\t%1, 0xff, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_zero_extendqidi2_andcc_set"
@@ -4738,7 +4221,7 @@
(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (subreg:QI (match_dup 1) 0)))]
"TARGET_ARCH64"
- "andcc\\t%1, 0xff, %0"
+ "andcc\t%1, 0xff, %0"
[(set_attr "type" "compare")])
;; Similarly, handle {SI,DI}->QI mode truncation followed by a compare.
@@ -4748,7 +4231,7 @@
(compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 3)
(const_int 0)))]
""
- "andcc\\t%0, 0xff, %%g0"
+ "andcc\t%0, 0xff, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_siqi_trunc_set"
@@ -4758,7 +4241,7 @@
(set (match_operand:QI 0 "register_operand" "=r")
(subreg:QI (match_dup 1) 3))]
""
- "andcc\\t%1, 0xff, %0"
+ "andcc\t%1, 0xff, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_diqi_trunc"
@@ -4766,7 +4249,7 @@
(compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 7)
(const_int 0)))]
"TARGET_ARCH64"
- "andcc\\t%0, 0xff, %%g0"
+ "andcc\t%0, 0xff, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_diqi_trunc_set"
@@ -4776,7 +4259,7 @@
(set (match_operand:QI 0 "register_operand" "=r")
(subreg:QI (match_dup 1) 7))]
"TARGET_ARCH64"
- "andcc\\t%1, 0xff, %0"
+ "andcc\t%1, 0xff, %0"
[(set_attr "type" "compare")])
;;- sign extension instructions
@@ -4789,7 +4272,6 @@
[(set (match_operand:SI 0 "register_operand" "")
(sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
""
- "
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_16 = GEN_INT (16);
@@ -4807,20 +4289,20 @@
shift_16));
emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
DONE;
-}")
+})
(define_insn "*sign_extendhisi2_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
""
- "ldsh\\t%1, %0"
- [(set_attr "type" "sload")])
+ "ldsh\t%1, %0"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
(define_expand "extendqihi2"
[(set (match_operand:HI 0 "register_operand" "")
(sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
""
- "
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
@@ -4847,20 +4329,20 @@
operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subbyte);
emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
DONE;
-}")
+})
(define_insn "*sign_extendqihi2_insn"
[(set (match_operand:HI 0 "register_operand" "=r")
(sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
""
- "ldsb\\t%1, %0"
- [(set_attr "type" "sload")])
+ "ldsb\t%1, %0"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
(define_expand "extendqisi2"
[(set (match_operand:SI 0 "register_operand" "")
(sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
""
- "
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
@@ -4878,20 +4360,20 @@
shift_24));
emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
DONE;
-}")
+})
(define_insn "*sign_extendqisi2_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
(sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
""
- "ldsb\\t%1, %0"
- [(set_attr "type" "sload")])
+ "ldsb\t%1, %0"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
(define_expand "extendqidi2"
[(set (match_operand:DI 0 "register_operand" "")
(sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
"TARGET_ARCH64"
- "
{
rtx temp = gen_reg_rtx (DImode);
rtx shift_56 = GEN_INT (56);
@@ -4909,20 +4391,20 @@
shift_56));
emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
DONE;
-}")
+})
(define_insn "*sign_extendqidi2_insn"
[(set (match_operand:DI 0 "register_operand" "=r")
(sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
"TARGET_ARCH64"
- "ldsb\\t%1, %0"
- [(set_attr "type" "sload")])
+ "ldsb\t%1, %0"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
(define_expand "extendhidi2"
[(set (match_operand:DI 0 "register_operand" "")
(sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
"TARGET_ARCH64"
- "
{
rtx temp = gen_reg_rtx (DImode);
rtx shift_48 = GEN_INT (48);
@@ -4940,14 +4422,15 @@
shift_48));
emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
DONE;
-}")
+})
(define_insn "*sign_extendhidi2_insn"
[(set (match_operand:DI 0 "register_operand" "=r")
(sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
"TARGET_ARCH64"
- "ldsh\\t%1, %0"
- [(set_attr "type" "sload")])
+ "ldsh\t%1, %0"
+ [(set_attr "type" "sload")
+ (set_attr "us3load_type" "3cycle")])
(define_expand "extendsidi2"
[(set (match_operand:DI 0 "register_operand" "")
@@ -4960,9 +4443,10 @@
(sign_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
"TARGET_ARCH64"
"@
- sra\\t%1, 0, %0
- ldsw\\t%1, %0"
- [(set_attr "type" "shift,sload")])
+ sra\t%1, 0, %0
+ ldsw\t%1, %0"
+ [(set_attr "type" "shift,sload")
+ (set_attr "us3load_type" "*,3cycle")])
;; Special pattern for optimizing bit-field compares. This is needed
;; because combine uses this as a canonical form.
@@ -4978,7 +4462,6 @@
&& INTVAL (operands[2]) > 19)
|| (GET_CODE (operands[2]) == CONST_DOUBLE
&& CONST_DOUBLE_LOW (operands[2]) > 19)"
- "*
{
int len = (GET_CODE (operands[1]) == CONST_INT
? INTVAL (operands[1])
@@ -4990,8 +4473,8 @@
HOST_WIDE_INT mask = ((1 << len) - 1) << pos;
operands[1] = GEN_INT (mask);
- return \"andcc\\t%0, %1, %%g0\";
-}"
+ return "andcc\t%0, %1, %%g0";
+}
[(set_attr "type" "compare")])
(define_insn "*cmp_zero_extract_sp64"
@@ -5006,7 +4489,6 @@
&& INTVAL (operands[2]) > 51)
|| (GET_CODE (operands[2]) == CONST_DOUBLE
&& CONST_DOUBLE_LOW (operands[2]) > 51))"
- "*
{
int len = (GET_CODE (operands[1]) == CONST_INT
? INTVAL (operands[1])
@@ -5018,8 +4500,8 @@
HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
operands[1] = GEN_INT (mask);
- return \"andcc\\t%0, %1, %%g0\";
-}"
+ return "andcc\t%0, %1, %%g0";
+}
[(set_attr "type" "compare")])
;; Conversions between float, double and long double.
@@ -5029,7 +4511,7 @@
(float_extend:DF
(match_operand:SF 1 "register_operand" "f")))]
"TARGET_FPU"
- "fstod\\t%1, %0"
+ "fstod\t%1, %0"
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
@@ -5045,7 +4527,7 @@
(float_extend:TF
(match_operand:SF 1 "register_operand" "f")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fstoq\\t%1, %0"
+ "fstoq\t%1, %0"
[(set_attr "type" "fp")])
(define_expand "extenddftf2"
@@ -5060,7 +4542,7 @@
(float_extend:TF
(match_operand:DF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fdtoq\\t%1, %0"
+ "fdtoq\t%1, %0"
[(set_attr "type" "fp")])
(define_insn "truncdfsf2"
@@ -5068,7 +4550,7 @@
(float_truncate:SF
(match_operand:DF 1 "register_operand" "e")))]
"TARGET_FPU"
- "fdtos\\t%1, %0"
+ "fdtos\t%1, %0"
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
@@ -5084,7 +4566,7 @@
(float_truncate:SF
(match_operand:TF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fqtos\\t%1, %0"
+ "fqtos\t%1, %0"
[(set_attr "type" "fp")])
(define_expand "trunctfdf2"
@@ -5099,7 +4581,7 @@
(float_truncate:DF
(match_operand:TF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fqtod\\t%1, %0"
+ "fqtod\t%1, %0"
[(set_attr "type" "fp")])
;; Conversion between fixed point and floating point.
@@ -5108,7 +4590,7 @@
[(set (match_operand:SF 0 "register_operand" "=f")
(float:SF (match_operand:SI 1 "register_operand" "f")))]
"TARGET_FPU"
- "fitos\\t%1, %0"
+ "fitos\t%1, %0"
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
@@ -5116,7 +4598,7 @@
[(set (match_operand:DF 0 "register_operand" "=e")
(float:DF (match_operand:SI 1 "register_operand" "f")))]
"TARGET_FPU"
- "fitod\\t%1, %0"
+ "fitod\t%1, %0"
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
@@ -5130,7 +4612,7 @@
[(set (match_operand:TF 0 "register_operand" "=e")
(float:TF (match_operand:SI 1 "register_operand" "f")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fitoq\\t%1, %0"
+ "fitoq\t%1, %0"
[(set_attr "type" "fp")])
(define_expand "floatunssitf2"
@@ -5145,7 +4627,7 @@
[(set (match_operand:SF 0 "register_operand" "=f")
(float:SF (match_operand:DI 1 "register_operand" "e")))]
"TARGET_V9 && TARGET_FPU"
- "fxtos\\t%1, %0"
+ "fxtos\t%1, %0"
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
@@ -5159,7 +4641,7 @@
[(set (match_operand:DF 0 "register_operand" "=e")
(float:DF (match_operand:DI 1 "register_operand" "e")))]
"TARGET_V9 && TARGET_FPU"
- "fxtod\\t%1, %0"
+ "fxtod\t%1, %0"
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
@@ -5179,7 +4661,7 @@
[(set (match_operand:TF 0 "register_operand" "=e")
(float:TF (match_operand:DI 1 "register_operand" "e")))]
"TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
- "fxtoq\\t%1, %0"
+ "fxtoq\t%1, %0"
[(set_attr "type" "fp")])
(define_expand "floatunsditf2"
@@ -5195,7 +4677,7 @@
[(set (match_operand:SI 0 "register_operand" "=f")
(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
"TARGET_FPU"
- "fstoi\\t%1, %0"
+ "fstoi\t%1, %0"
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
@@ -5203,7 +4685,7 @@
[(set (match_operand:SI 0 "register_operand" "=f")
(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
"TARGET_FPU"
- "fdtoi\\t%1, %0"
+ "fdtoi\t%1, %0"
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
@@ -5217,7 +4699,7 @@
[(set (match_operand:SI 0 "register_operand" "=f")
(fix:SI (match_operand:TF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fqtoi\\t%1, %0"
+ "fqtoi\t%1, %0"
[(set_attr "type" "fp")])
(define_expand "fixuns_trunctfsi2"
@@ -5232,7 +4714,7 @@
[(set (match_operand:DI 0 "register_operand" "=e")
(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
"TARGET_V9 && TARGET_FPU"
- "fstox\\t%1, %0"
+ "fstox\t%1, %0"
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
@@ -5240,7 +4722,7 @@
[(set (match_operand:DI 0 "register_operand" "=e")
(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
"TARGET_V9 && TARGET_FPU"
- "fdtox\\t%1, %0"
+ "fdtox\t%1, %0"
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
@@ -5254,7 +4736,7 @@
[(set (match_operand:DI 0 "register_operand" "=e")
(fix:DI (match_operand:TF 1 "register_operand" "e")))]
"TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
- "fqtox\\t%1, %0"
+ "fqtox\t%1, %0"
[(set_attr "type" "fp")])
(define_expand "fixuns_trunctfdi2"
@@ -5266,14 +4748,11 @@
;;- arithmetic instructions
(define_expand "adddi3"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
- (match_operand:DI 2 "arith_double_add_operand" "rHI")))]
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "arith_double_add_operand" "")))]
""
- "
{
- HOST_WIDE_INT i;
-
if (! TARGET_ARCH64)
{
emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
@@ -5284,38 +4763,16 @@
gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
DONE;
}
- if (arith_double_4096_operand(operands[2], DImode))
- {
- switch (GET_CODE (operands[1]))
- {
- case CONST_INT: i = INTVAL (operands[1]); break;
- case CONST_DOUBLE: i = CONST_DOUBLE_LOW (operands[1]); break;
- default:
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_MINUS (DImode, operands[1],
- GEN_INT(-4096))));
- DONE;
- }
- emit_insn (gen_movdi (operands[0], GEN_INT (i + 4096)));
- DONE;
- }
-}")
+})
-(define_insn "adddi3_insn_sp32"
+(define_insn_and_split "adddi3_insn_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
(match_operand:DI 2 "arith_double_operand" "rHI")))
(clobber (reg:CC 100))]
"! TARGET_ARCH64"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (plus:DI (match_operand:DI 1 "arith_double_operand" "")
- (match_operand:DI 2 "arith_double_operand" "")))
- (clobber (reg:CC 100))]
- "! TARGET_ARCH64 && reload_completed"
+ "&& reload_completed"
[(parallel [(set (reg:CC_NOOV 100)
(compare:CC_NOOV (plus:SI (match_dup 4)
(match_dup 5))
@@ -5326,7 +4783,6 @@
(plus:SI (plus:SI (match_dup 7)
(match_dup 8))
(ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
- "
{
operands[3] = gen_lowpart (SImode, operands[0]);
operands[4] = gen_lowpart (SImode, operands[1]);
@@ -5344,7 +4800,8 @@
else
#endif
operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
-}")
+}
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -5362,7 +4819,6 @@
(minus:SI (minus:SI (match_dup 7)
(match_dup 8))
(ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
- "
{
operands[3] = gen_lowpart (SImode, operands[0]);
operands[4] = gen_lowpart (SImode, operands[1]);
@@ -5380,7 +4836,7 @@
else
#endif
operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
-}")
+})
;; LTU here means "carry set"
(define_insn "addx"
@@ -5389,29 +4845,24 @@
(match_operand:SI 2 "arith_operand" "rI"))
(ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
""
- "addx\\t%1, %2, %0"
- [(set_attr "type" "misc")])
+ "addx\t%1, %2, %0"
+ [(set_attr "type" "ialuX")])
-(define_insn "*addx_extend_sp32"
+(define_insn_and_split "*addx_extend_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
- (match_operand:SI 2 "arith_operand" "rI"))
+ (zero_extend:DI (plus:SI (plus:SI
+ (match_operand:SI 1 "reg_or_0_operand" "%rJ")
+ (match_operand:SI 2 "arith_operand" "rI"))
(ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
"! TARGET_ARCH64"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "")
- (match_operand:SI 2 "arith_operand" ""))
- (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
- "! TARGET_ARCH64 && reload_completed"
+ "&& reload_completed"
[(set (match_dup 3) (plus:SI (plus:SI (match_dup 1) (match_dup 2))
(ltu:SI (reg:CC_NOOV 100) (const_int 0))))
(set (match_dup 4) (const_int 0))]
"operands[3] = gen_lowpart (SImode, operands[0]);
- operands[4] = gen_highpart_mode (SImode, DImode, operands[1]);")
+ operands[4] = gen_highpart_mode (SImode, DImode, operands[1]);"
+ [(set_attr "length" "2")])
(define_insn "*addx_extend_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -5419,8 +4870,8 @@
(match_operand:SI 2 "arith_operand" "rI"))
(ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
"TARGET_ARCH64"
- "addx\\t%r1, %2, %0"
- [(set_attr "type" "misc")])
+ "addx\t%r1, %2, %0"
+ [(set_attr "type" "ialuX")])
(define_insn "subx"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -5428,8 +4879,8 @@
(match_operand:SI 2 "arith_operand" "rI"))
(ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
""
- "subx\\t%r1, %2, %0"
- [(set_attr "type" "misc")])
+ "subx\t%r1, %2, %0"
+ [(set_attr "type" "ialuX")])
(define_insn "*subx_extend_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -5437,45 +4888,32 @@
(match_operand:SI 2 "arith_operand" "rI"))
(ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
"TARGET_ARCH64"
- "subx\\t%r1, %2, %0"
- [(set_attr "type" "misc")])
+ "subx\t%r1, %2, %0"
+ [(set_attr "type" "ialuX")])
-(define_insn "*subx_extend"
+(define_insn_and_split "*subx_extend"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
(match_operand:SI 2 "arith_operand" "rI"))
(ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
"! TARGET_ARCH64"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "")
- (match_operand:SI 2 "arith_operand" ""))
- (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
- "! TARGET_ARCH64 && reload_completed"
+ "&& reload_completed"
[(set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 2))
(ltu:SI (reg:CC_NOOV 100) (const_int 0))))
(set (match_dup 4) (const_int 0))]
"operands[3] = gen_lowpart (SImode, operands[0]);
- operands[4] = gen_highpart (SImode, operands[0]);")
+ operands[4] = gen_highpart (SImode, operands[0]);"
+ [(set_attr "length" "2")])
-(define_insn ""
+(define_insn_and_split ""
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
(match_operand:DI 2 "register_operand" "r")))
(clobber (reg:CC 100))]
"! TARGET_ARCH64"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
- (match_operand:DI 2 "register_operand" "")))
- (clobber (reg:CC 100))]
- "! TARGET_ARCH64 && reload_completed"
+ "&& reload_completed"
[(parallel [(set (reg:CC_NOOV 100)
(compare:CC_NOOV (plus:SI (match_dup 3) (match_dup 1))
(const_int 0)))
@@ -5486,44 +4924,28 @@
"operands[3] = gen_lowpart (SImode, operands[2]);
operands[4] = gen_highpart (SImode, operands[2]);
operands[5] = gen_lowpart (SImode, operands[0]);
- operands[6] = gen_highpart (SImode, operands[0]);")
+ operands[6] = gen_highpart (SImode, operands[0]);"
+ [(set_attr "length" "2")])
(define_insn "*adddi3_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))]
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (plus:DI (match_operand:DI 1 "register_operand" "%r,r")
+ (match_operand:DI 2 "arith_double_add_operand" "rHI,O")))]
"TARGET_ARCH64"
- "add\\t%1, %2, %0")
-
-(define_expand "addsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,d")
- (plus:SI (match_operand:SI 1 "arith_operand" "%r,d")
- (match_operand:SI 2 "arith_add_operand" "rI,d")))]
- ""
- "
-{
- if (arith_4096_operand(operands[2], SImode))
- {
- if (GET_CODE (operands[1]) == CONST_INT)
- emit_insn (gen_movsi (operands[0],
- GEN_INT (INTVAL (operands[1]) + 4096)));
- else
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_MINUS (SImode, operands[1],
- GEN_INT(-4096))));
- DONE;
- }
-}")
+ "@
+ add\t%1, %2, %0
+ sub\t%1, -%2, %0")
-(define_insn "*addsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,d")
- (plus:SI (match_operand:SI 1 "arith_operand" "%r,d")
- (match_operand:SI 2 "arith_operand" "rI,d")))]
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,d")
+ (plus:SI (match_operand:SI 1 "register_operand" "%r,r,d")
+ (match_operand:SI 2 "arith_add_operand" "rI,O,d")))]
""
"@
- add\\t%1, %2, %0
- fpadd32s\\t%1, %2, %0"
- [(set_attr "type" "*,fp")])
+ add\t%1, %2, %0
+ sub\t%1, -%2, %0
+ fpadd32s\t%1, %2, %0"
+ [(set_attr "type" "*,*,fp")])
(define_insn "*cmp_cc_plus"
[(set (reg:CC_NOOV 100)
@@ -5531,7 +4953,7 @@
(match_operand:SI 1 "arith_operand" "rI"))
(const_int 0)))]
""
- "addcc\\t%0, %1, %%g0"
+ "addcc\t%0, %1, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_plus"
@@ -5540,7 +4962,7 @@
(match_operand:DI 1 "arith_double_operand" "rHI"))
(const_int 0)))]
"TARGET_ARCH64"
- "addcc\\t%0, %1, %%g0"
+ "addcc\t%0, %1, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_plus_set"
@@ -5551,7 +4973,7 @@
(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_dup 1) (match_dup 2)))]
""
- "addcc\\t%1, %2, %0"
+ "addcc\t%1, %2, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_plus_set"
@@ -5562,15 +4984,14 @@
(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_dup 1) (match_dup 2)))]
"TARGET_ARCH64"
- "addcc\\t%1, %2, %0"
+ "addcc\t%1, %2, %0"
[(set_attr "type" "compare")])
(define_expand "subdi3"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (minus:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "arith_double_add_operand" "rHI")))]
+ [(set (match_operand:DI 0 "register_operand" "")
+ (minus:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "arith_double_add_operand" "")))]
""
- "
{
if (! TARGET_ARCH64)
{
@@ -5582,35 +5003,19 @@
gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
DONE;
}
- if (arith_double_4096_operand(operands[2], DImode))
- {
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_PLUS (DImode, operands[1],
- GEN_INT(-4096))));
- DONE;
- }
-}")
+})
-(define_insn "*subdi3_sp32"
+(define_insn_and_split "*subdi3_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
- (minus:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))
+ (minus:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "arith_double_operand" "rHI")))
(clobber (reg:CC 100))]
"! TARGET_ARCH64"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (minus:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "arith_double_operand" "")))
- (clobber (reg:CC 100))]
- "! TARGET_ARCH64
- && reload_completed
+ "&& reload_completed
&& (GET_CODE (operands[2]) == CONST_INT
|| GET_CODE (operands[2]) == CONST_DOUBLE)"
[(clobber (const_int 0))]
- "
{
rtx highp, lowp;
@@ -5636,7 +5041,8 @@
highp));
}
DONE;
-}")
+}
+ [(set_attr "length" "2")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -5646,7 +5052,6 @@
"! TARGET_ARCH64
&& reload_completed"
[(clobber (const_int 0))]
- "
{
emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
gen_lowpart (SImode, operands[1]),
@@ -5655,23 +5060,16 @@
gen_highpart (SImode, operands[1]),
gen_highpart (SImode, operands[2])));
DONE;
-}")
+})
-(define_insn ""
+(define_insn_and_split ""
[(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (match_operand:DI 1 "register_operand" "r")
(zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))
(clobber (reg:CC 100))]
"! TARGET_ARCH64"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (minus:DI (match_operand:DI 1 "register_operand" "")
- (zero_extend:DI (match_operand:SI 2 "register_operand" ""))))
- (clobber (reg:CC 100))]
- "! TARGET_ARCH64 && reload_completed"
+ "&& reload_completed"
[(parallel [(set (reg:CC_NOOV 100)
(compare:CC_NOOV (minus:SI (match_dup 3) (match_dup 2))
(const_int 0)))
@@ -5682,40 +5080,28 @@
"operands[3] = gen_lowpart (SImode, operands[1]);
operands[4] = gen_highpart (SImode, operands[1]);
operands[5] = gen_lowpart (SImode, operands[0]);
- operands[6] = gen_highpart (SImode, operands[0]);")
+ operands[6] = gen_highpart (SImode, operands[0]);"
+ [(set_attr "length" "2")])
(define_insn "*subdi3_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (minus:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))]
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (minus:DI (match_operand:DI 1 "register_operand" "r,r")
+ (match_operand:DI 2 "arith_double_add_operand" "rHI,O")))]
"TARGET_ARCH64"
- "sub\\t%1, %2, %0")
-
-(define_expand "subsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,d")
- (minus:SI (match_operand:SI 1 "register_operand" "r,d")
- (match_operand:SI 2 "arith_add_operand" "rI,d")))]
- ""
- "
-{
- if (arith_4096_operand(operands[2], SImode))
- {
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_PLUS (SImode, operands[1],
- GEN_INT(-4096))));
- DONE;
- }
-}")
+ "@
+ sub\t%1, %2, %0
+ add\t%1, -%2, %0")
-(define_insn "*subsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,d")
- (minus:SI (match_operand:SI 1 "register_operand" "r,d")
- (match_operand:SI 2 "arith_operand" "rI,d")))]
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,d")
+ (minus:SI (match_operand:SI 1 "register_operand" "r,r,d")
+ (match_operand:SI 2 "arith_add_operand" "rI,O,d")))]
""
"@
- sub\\t%1, %2, %0
- fpsub32s\\t%1, %2, %0"
- [(set_attr "type" "*,fp")])
+ sub\t%1, %2, %0
+ add\t%1, -%2, %0
+ fpsub32s\t%1, %2, %0"
+ [(set_attr "type" "*,*,fp")])
(define_insn "*cmp_minus_cc"
[(set (reg:CC_NOOV 100)
@@ -5723,7 +5109,7 @@
(match_operand:SI 1 "arith_operand" "rI"))
(const_int 0)))]
""
- "subcc\\t%r0, %1, %%g0"
+ "subcc\t%r0, %1, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_minus_ccx"
@@ -5732,7 +5118,7 @@
(match_operand:DI 1 "arith_double_operand" "rHI"))
(const_int 0)))]
"TARGET_ARCH64"
- "subcc\\t%0, %1, %%g0"
+ "subcc\t%0, %1, %%g0"
[(set_attr "type" "compare")])
(define_insn "cmp_minus_cc_set"
@@ -5743,7 +5129,7 @@
(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_dup 1) (match_dup 2)))]
""
- "subcc\\t%r1, %2, %0"
+ "subcc\t%r1, %2, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_minus_ccx_set"
@@ -5754,7 +5140,7 @@
(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (match_dup 1) (match_dup 2)))]
"TARGET_ARCH64"
- "subcc\\t%1, %2, %0"
+ "subcc\t%1, %2, %0"
[(set_attr "type" "compare")])
;; Integer Multiply/Divide.
@@ -5767,7 +5153,7 @@
(mult:SI (match_operand:SI 1 "arith_operand" "%r")
(match_operand:SI 2 "arith_operand" "rI")))]
"TARGET_HARD_MUL"
- "smul\\t%1, %2, %0"
+ "smul\t%1, %2, %0"
[(set_attr "type" "imul")])
(define_expand "muldi3"
@@ -5775,21 +5161,20 @@
(mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
(match_operand:DI 2 "arith_double_operand" "rHI")))]
"TARGET_ARCH64 || TARGET_V8PLUS"
- "
{
if (TARGET_V8PLUS)
{
emit_insn (gen_muldi3_v8plus (operands[0], operands[1], operands[2]));
DONE;
}
-}")
+})
(define_insn "*muldi3_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
(match_operand:DI 2 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
- "mulx\\t%1, %2, %0"
+ "mulx\t%1, %2, %0"
[(set_attr "type" "imul")])
;; V8plus wide multiply.
@@ -5801,33 +5186,32 @@
(clobber (match_scratch:SI 3 "=&h,X"))
(clobber (match_scratch:SI 4 "=&h,X"))]
"TARGET_V8PLUS"
- "*
{
if (sparc_check_64 (operands[1], insn) <= 0)
- output_asm_insn (\"srl\\t%L1, 0, %L1\", operands);
+ output_asm_insn ("srl\t%L1, 0, %L1", operands);
if (which_alternative == 1)
- output_asm_insn (\"sllx\\t%H1, 32, %H1\", operands);
+ output_asm_insn ("sllx\t%H1, 32, %H1", operands);
if (GET_CODE (operands[2]) == CONST_INT)
{
if (which_alternative == 1)
- return \"or\\t%L1, %H1, %H1\\n\\tmulx\\t%H1, %2, %L0\;srlx\\t%L0, 32, %H0\";
+ return "or\t%L1, %H1, %H1\n\tmulx\t%H1, %2, %L0\;srlx\t%L0, 32, %H0";
else
- return \"sllx\\t%H1, 32, %3\\n\\tor\\t%L1, %3, %3\\n\\tmulx\\t%3, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0\";
+ return "sllx\t%H1, 32, %3\n\tor\t%L1, %3, %3\n\tmulx\t%3, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0";
}
else if (rtx_equal_p (operands[1], operands[2]))
{
if (which_alternative == 1)
- return \"or\\t%L1, %H1, %H1\\n\\tmulx\\t%H1, %H1, %L0\;srlx\\t%L0, 32, %H0\";
+ return "or\t%L1, %H1, %H1\n\tmulx\t%H1, %H1, %L0\;srlx\t%L0, 32, %H0";
else
- return \"sllx\\t%H1, 32, %3\\n\\tor\\t%L1, %3, %3\\n\\tmulx\\t%3, %3, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0\";
+ return "sllx\t%H1, 32, %3\n\tor\t%L1, %3, %3\n\tmulx\t%3, %3, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0";
}
if (sparc_check_64 (operands[2], insn) <= 0)
- output_asm_insn (\"srl\\t%L2, 0, %L2\", operands);
+ output_asm_insn ("srl\t%L2, 0, %L2", operands);
if (which_alternative == 1)
- return \"or\\t%L1, %H1, %H1\\n\\tsllx\\t%H2, 32, %L1\\n\\tor\\t%L2, %L1, %L1\\n\\tmulx\\t%H1, %L1, %L0\;srlx\\t%L0, 32, %H0\";
+ return "or\t%L1, %H1, %H1\n\tsllx\t%H2, 32, %L1\n\tor\t%L2, %L1, %L1\n\tmulx\t%H1, %L1, %L0\;srlx\t%L0, 32, %H0";
else
- return \"sllx\\t%H1, 32, %3\\n\\tsllx\\t%H2, 32, %4\\n\\tor\\t%L1, %3, %3\\n\\tor\\t%L2, %4, %4\\n\\tmulx\\t%3, %4, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0\";
-}"
+ return "sllx\t%H1, 32, %3\n\tsllx\t%H2, 32, %4\n\tor\t%L1, %3, %3\n\tor\t%L2, %4, %4\n\tmulx\t%3, %4, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0";
+}
[(set_attr "type" "multi")
(set_attr "length" "9,8")])
@@ -5839,7 +5223,7 @@
(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (match_dup 1) (match_dup 2)))]
"TARGET_V8 || TARGET_SPARCLITE || TARGET_DEPRECATED_V8_INSNS"
- "smulcc\\t%1, %2, %0"
+ "smulcc\t%1, %2, %0"
[(set_attr "type" "imul")])
(define_expand "mulsidi3"
@@ -5847,16 +5231,18 @@
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
(sign_extend:DI (match_operand:SI 2 "arith_operand" ""))))]
"TARGET_HARD_MUL"
- "
{
if (CONSTANT_P (operands[2]))
{
if (TARGET_V8PLUS)
emit_insn (gen_const_mulsidi3_v8plus (operands[0], operands[1],
operands[2]));
- else
+ else if (TARGET_ARCH32)
emit_insn (gen_const_mulsidi3_sp32 (operands[0], operands[1],
operands[2]));
+ else
+ emit_insn (gen_const_mulsidi3_sp64 (operands[0], operands[1],
+ operands[2]));
DONE;
}
if (TARGET_V8PLUS)
@@ -5864,7 +5250,7 @@
emit_insn (gen_mulsidi3_v8plus (operands[0], operands[1], operands[2]));
DONE;
}
-}")
+})
;; V9 puts the 64 bit product in a 64 bit register. Only out or global
;; registers can hold 64 bit values in the V8plus environment.
@@ -5876,8 +5262,8 @@
(clobber (match_scratch:SI 3 "=X,&h"))]
"TARGET_V8PLUS"
"@
- smul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
- smul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
+ smul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
+ smul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
[(set_attr "type" "multi")
(set_attr "length" "2,3")])
@@ -5885,12 +5271,12 @@
(define_insn "const_mulsidi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=h,r")
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
- (match_operand:SI 2 "small_int" "I,I")))
+ (match_operand:DI 2 "small_int" "I,I")))
(clobber (match_scratch:SI 3 "=X,&h"))]
"TARGET_V8PLUS"
"@
- smul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
- smul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
+ smul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
+ smul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
[(set_attr "type" "multi")
(set_attr "length" "2,3")])
@@ -5900,10 +5286,11 @@
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
(sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
"TARGET_HARD_MUL32"
- "*
{
- return TARGET_SPARCLET ? \"smuld\\t%1, %2, %L0\" : \"smul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
-}"
+ return TARGET_SPARCLET
+ ? "smuld\t%1, %2, %L0"
+ : "smul\t%1, %2, %L0\n\trd\t%%y, %H0";
+}
[(set (attr "type")
(if_then_else (eq_attr "isa" "sparclet")
(const_string "imul") (const_string "multi")))
@@ -5916,7 +5303,7 @@
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
(sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
"TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
- "smul\\t%1, %2, %0"
+ "smul\t%1, %2, %0"
[(set_attr "type" "imul")])
;; Extra pattern, because sign_extend of a constant isn't valid.
@@ -5925,12 +5312,13 @@
(define_insn "const_mulsidi3_sp32"
[(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")))]
+ (match_operand:DI 2 "small_int" "I")))]
"TARGET_HARD_MUL32"
- "*
{
- return TARGET_SPARCLET ? \"smuld\\t%1, %2, %L0\" : \"smul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
-}"
+ return TARGET_SPARCLET
+ ? "smuld\t%1, %2, %L0"
+ : "smul\t%1, %2, %L0\n\trd\t%%y, %H0";
+}
[(set (attr "type")
(if_then_else (eq_attr "isa" "sparclet")
(const_string "imul") (const_string "multi")))
@@ -5941,9 +5329,9 @@
(define_insn "const_mulsidi3_sp64"
[(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")))]
+ (match_operand:DI 2 "small_int" "I")))]
"TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
- "smul\\t%1, %2, %0"
+ "smul\t%1, %2, %0"
[(set_attr "type" "imul")])
(define_expand "smulsi3_highpart"
@@ -5953,7 +5341,6 @@
(sign_extend:DI (match_operand:SI 2 "arith_operand" "")))
(const_int 32))))]
"TARGET_HARD_MUL && TARGET_ARCH32"
- "
{
if (CONSTANT_P (operands[2]))
{
@@ -5974,7 +5361,7 @@
operands[2], GEN_INT (32)));
DONE;
}
-}")
+})
;; XXX
(define_insn "smulsi3_highpart_v8plus"
@@ -5986,8 +5373,8 @@
(clobber (match_scratch:SI 4 "=X,&h"))]
"TARGET_V8PLUS"
"@
- smul\\t%1, %2, %0\;srlx\\t%0, %3, %0
- smul\\t%1, %2, %4\;srlx\\t%4, %3, %0"
+ smul\t%1, %2, %0\;srlx\t%0, %3, %0
+ smul\t%1, %2, %4\;srlx\t%4, %3, %0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -6004,8 +5391,8 @@
(clobber (match_scratch:SI 4 "=X,&h"))]
"TARGET_V8PLUS"
"@
- smul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
- smul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
+ smul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
+ smul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -6014,13 +5401,13 @@
[(set (match_operand:SI 0 "register_operand" "=h,r")
(truncate:SI
(lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
- (match_operand 2 "small_int" "i,i"))
+ (match_operand:DI 2 "small_int" "i,i"))
(match_operand:SI 3 "const_int_operand" "i,i"))))
(clobber (match_scratch:SI 4 "=X,&h"))]
"TARGET_V8PLUS"
"@
- smul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
- smul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
+ smul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
+ smul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -6032,7 +5419,7 @@
(sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
(const_int 32))))]
"TARGET_HARD_MUL32"
- "smul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
+ "smul\t%1, %2, %%g0\n\trd\t%%y, %0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -6041,10 +5428,10 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(truncate:SI
(lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand:SI 2 "register_operand" "r"))
+ (match_operand:DI 2 "small_int" "i"))
(const_int 32))))]
"TARGET_HARD_MUL32"
- "smul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
+ "smul\t%1, %2, %%g0\n\trd\t%%y, %0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -6053,16 +5440,18 @@
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
(zero_extend:DI (match_operand:SI 2 "uns_arith_operand" ""))))]
"TARGET_HARD_MUL"
- "
{
if (CONSTANT_P (operands[2]))
{
if (TARGET_V8PLUS)
emit_insn (gen_const_umulsidi3_v8plus (operands[0], operands[1],
operands[2]));
- else
+ else if (TARGET_ARCH32)
emit_insn (gen_const_umulsidi3_sp32 (operands[0], operands[1],
operands[2]));
+ else
+ emit_insn (gen_const_umulsidi3_sp64 (operands[0], operands[1],
+ operands[2]));
DONE;
}
if (TARGET_V8PLUS)
@@ -6070,7 +5459,7 @@
emit_insn (gen_umulsidi3_v8plus (operands[0], operands[1], operands[2]));
DONE;
}
-}")
+})
;; XXX
(define_insn "umulsidi3_v8plus"
@@ -6080,8 +5469,8 @@
(clobber (match_scratch:SI 3 "=X,&h"))]
"TARGET_V8PLUS"
"@
- umul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
- umul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
+ umul\t%1, %2, %L0\n\tsrlx\t%L0, 32, %H0
+ umul\t%1, %2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
[(set_attr "type" "multi")
(set_attr "length" "2,3")])
@@ -6091,10 +5480,11 @@
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
(zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
"TARGET_HARD_MUL32"
- "*
{
- return TARGET_SPARCLET ? \"umuld\\t%1, %2, %L0\" : \"umul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
-}"
+ return TARGET_SPARCLET
+ ? "umuld\t%1, %2, %L0"
+ : "umul\t%1, %2, %L0\n\trd\t%%y, %H0";
+}
[(set (attr "type")
(if_then_else (eq_attr "isa" "sparclet")
(const_string "imul") (const_string "multi")))
@@ -6107,7 +5497,7 @@
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
(zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
"TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
- "umul\\t%1, %2, %0"
+ "umul\t%1, %2, %0"
[(set_attr "type" "imul")])
;; Extra pattern, because sign_extend of a constant isn't valid.
@@ -6116,12 +5506,13 @@
(define_insn "const_umulsidi3_sp32"
[(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" "")))]
+ (match_operand:DI 2 "uns_small_int" "")))]
"TARGET_HARD_MUL32"
- "*
{
- return TARGET_SPARCLET ? \"umuld\\t%1, %2, %L0\" : \"umul\\t%1, %2, %L0\\n\\trd\\t%%y, %H0\";
-}"
+ return TARGET_SPARCLET
+ ? "umuld\t%1, %s2, %L0"
+ : "umul\t%1, %s2, %L0\n\trd\t%%y, %H0";
+}
[(set (attr "type")
(if_then_else (eq_attr "isa" "sparclet")
(const_string "imul") (const_string "multi")))
@@ -6132,21 +5523,21 @@
(define_insn "const_umulsidi3_sp64"
[(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" "")))]
+ (match_operand:DI 2 "uns_small_int" "")))]
"TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
- "umul\\t%1, %2, %0"
+ "umul\t%1, %s2, %0"
[(set_attr "type" "imul")])
;; XXX
(define_insn "const_umulsidi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=h,r")
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
- (match_operand:SI 2 "uns_small_int" "")))
+ (match_operand:DI 2 "uns_small_int" "")))
(clobber (match_scratch:SI 3 "=X,h"))]
"TARGET_V8PLUS"
"@
- umul\\t%1, %2, %L0\\n\\tsrlx\\t%L0, 32, %H0
- umul\\t%1, %2, %3\\n\\tsrlx\\t%3, 32, %H0\\n\\tmov\\t%3, %L0"
+ umul\t%1, %s2, %L0\n\tsrlx\t%L0, 32, %H0
+ umul\t%1, %s2, %3\n\tsrlx\t%3, 32, %H0\n\tmov\t%3, %L0"
[(set_attr "type" "multi")
(set_attr "length" "2,3")])
@@ -6157,7 +5548,6 @@
(zero_extend:DI (match_operand:SI 2 "uns_arith_operand" "")))
(const_int 32))))]
"TARGET_HARD_MUL && TARGET_ARCH32"
- "
{
if (CONSTANT_P (operands[2]))
{
@@ -6178,7 +5568,7 @@
operands[2], GEN_INT (32)));
DONE;
}
-}")
+})
;; XXX
(define_insn "umulsi3_highpart_v8plus"
@@ -6190,8 +5580,8 @@
(clobber (match_scratch:SI 4 "=X,h"))]
"TARGET_V8PLUS"
"@
- umul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
- umul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
+ umul\t%1, %2, %0\n\tsrlx\t%0, %3, %0
+ umul\t%1, %2, %4\n\tsrlx\t%4, %3, %0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -6200,13 +5590,13 @@
[(set (match_operand:SI 0 "register_operand" "=h,r")
(truncate:SI
(lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
- (match_operand:SI 2 "uns_small_int" ""))
+ (match_operand:DI 2 "uns_small_int" ""))
(match_operand:SI 3 "const_int_operand" "i,i"))))
(clobber (match_scratch:SI 4 "=X,h"))]
"TARGET_V8PLUS"
"@
- umul\\t%1, %2, %0\\n\\tsrlx\\t%0, %3, %0
- umul\\t%1, %2, %4\\n\\tsrlx\\t%4, %3, %0"
+ umul\t%1, %s2, %0\n\tsrlx\t%0, %3, %0
+ umul\t%1, %s2, %4\n\tsrlx\t%4, %3, %0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -6218,7 +5608,7 @@
(zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
(const_int 32))))]
"TARGET_HARD_MUL32"
- "umul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
+ "umul\t%1, %2, %%g0\n\trd\t%%y, %0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -6227,10 +5617,10 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(truncate:SI
(lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand:SI 2 "uns_small_int" ""))
+ (match_operand:DI 2 "uns_small_int" ""))
(const_int 32))))]
"TARGET_HARD_MUL32"
- "umul\\t%1, %2, %%g0\\n\\trd\\t%%y, %0"
+ "umul\t%1, %s2, %%g0\n\trd\t%%y, %0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -6243,7 +5633,6 @@
(match_operand:SI 2 "input_operand" "rI,m")))
(clobber (match_scratch:SI 3 "=&r,&r"))])]
"TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
- "
{
if (TARGET_ARCH64)
{
@@ -6253,7 +5642,7 @@
operands[3]));
DONE;
}
-}")
+})
(define_insn "divsi3_sp32"
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -6262,19 +5651,18 @@
(clobber (match_scratch:SI 3 "=&r,&r"))]
"(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS)
&& TARGET_ARCH32"
- "*
{
if (which_alternative == 0)
if (TARGET_V9)
- return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tsdiv\\t%1, %2, %0\";
+ return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tsdiv\t%1, %2, %0";
else
- return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tsdiv\\t%1, %2, %0\";
+ return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tnop\n\tnop\n\tnop\n\tsdiv\t%1, %2, %0";
else
if (TARGET_V9)
- return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tld\\t%2, %3\\n\\tsdiv\\t%1, %3, %0\";
+ return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tld\t%2, %3\n\tsdiv\t%1, %3, %0";
else
- return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tld\\t%2, %3\\n\\tnop\\n\\tnop\\n\\tsdiv\\t%1, %3, %0\";
-}"
+ return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tld\t%2, %3\n\tnop\n\tnop\n\tsdiv\t%1, %3, %0";
+}
[(set_attr "type" "multi")
(set (attr "length")
(if_then_else (eq_attr "isa" "v9")
@@ -6286,7 +5674,7 @@
(match_operand:SI 2 "input_operand" "rI")))
(use (match_operand:SI 3 "register_operand" "r"))]
"TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
- "wr\\t%%g0, %3, %%y\\n\\tsdiv\\t%1, %2, %0"
+ "wr\t%%g0, %3, %%y\n\tsdiv\t%1, %2, %0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -6295,7 +5683,7 @@
(div:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
- "sdivx\\t%1, %2, %0"
+ "sdivx\t%1, %2, %0"
[(set_attr "type" "idiv")])
(define_insn "*cmp_sdiv_cc_set"
@@ -6307,13 +5695,12 @@
(div:SI (match_dup 1) (match_dup 2)))
(clobber (match_scratch:SI 3 "=&r"))]
"TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
- "*
{
if (TARGET_V9)
- return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tsdivcc\\t%1, %2, %0\";
+ return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tsdivcc\t%1, %2, %0";
else
- return \"sra\\t%1, 31, %3\\n\\twr\\t%3, 0, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tsdivcc\\t%1, %2, %0\";
-}"
+ return "sra\t%1, 31, %3\n\twr\t%3, 0, %%y\n\tnop\n\tnop\n\tnop\n\tsdivcc\t%1, %2, %0";
+}
[(set_attr "type" "multi")
(set (attr "length")
(if_then_else (eq_attr "isa" "v9")
@@ -6334,19 +5721,18 @@
"(TARGET_V8
|| TARGET_DEPRECATED_V8_INSNS)
&& TARGET_ARCH32"
- "*
{
- output_asm_insn (\"wr\\t%%g0, %%g0, %%y\", operands);
+ output_asm_insn ("wr\t%%g0, %%g0, %%y", operands);
switch (which_alternative)
{
default:
- return \"nop\\n\\tnop\\n\\tnop\\n\\tudiv\\t%1, %2, %0\";
+ return "nop\n\tnop\n\tnop\n\tudiv\t%1, %2, %0";
case 1:
- return \"ld\\t%2, %0\\n\\tnop\\n\\tnop\\n\\tudiv\\t%1, %0, %0\";
+ return "ld\t%2, %0\n\tnop\n\tnop\n\tudiv\t%1, %0, %0";
case 2:
- return \"ld\\t%1, %0\\n\\tnop\\n\\tnop\\n\\tudiv\\t%0, %2, %0\";
+ return "ld\t%1, %0\n\tnop\n\tnop\n\tudiv\t%0, %2, %0";
}
-}"
+}
[(set_attr "type" "multi")
(set_attr "length" "5")])
@@ -6355,7 +5741,7 @@
(udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r")
(match_operand:SI 2 "input_operand" "rI")))]
"TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
- "wr\\t%%g0, 0, %%y\\n\\tudiv\\t%1, %2, %0"
+ "wr\t%%g0, 0, %%y\n\tudiv\t%1, %2, %0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -6364,7 +5750,7 @@
(udiv:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "arith_double_operand" "rHI")))]
"TARGET_ARCH64"
- "udivx\\t%1, %2, %0"
+ "udivx\t%1, %2, %0"
[(set_attr "type" "idiv")])
(define_insn "*cmp_udiv_cc_set"
@@ -6376,13 +5762,12 @@
(udiv:SI (match_dup 1) (match_dup 2)))]
"TARGET_V8
|| TARGET_DEPRECATED_V8_INSNS"
- "*
{
if (TARGET_V9)
- return \"wr\\t%%g0, %%g0, %%y\\n\\tudivcc\\t%1, %2, %0\";
+ return "wr\t%%g0, %%g0, %%y\n\tudivcc\t%1, %2, %0";
else
- return \"wr\\t%%g0, %%g0, %%y\\n\\tnop\\n\\tnop\\n\\tnop\\n\\tudivcc\\t%1, %2, %0\";
-}"
+ return "wr\t%%g0, %%g0, %%y\n\tnop\n\tnop\n\tnop\n\tudivcc\t%1, %2, %0";
+}
[(set_attr "type" "multi")
(set (attr "length")
(if_then_else (eq_attr "isa" "v9")
@@ -6396,7 +5781,7 @@
(match_operand:SI 2 "arith_operand" "rI"))
(match_operand:SI 3 "register_operand" "0")))]
"TARGET_SPARCLET"
- "smac\\t%1, %2, %0"
+ "smac\t%1, %2, %0"
[(set_attr "type" "imul")])
(define_insn "*smacdi"
@@ -6407,7 +5792,7 @@
(match_operand:SI 2 "register_operand" "r")))
(match_operand:DI 3 "register_operand" "0")))]
"TARGET_SPARCLET"
- "smacd\\t%1, %2, %L0"
+ "smacd\t%1, %2, %L0"
[(set_attr "type" "imul")])
(define_insn "*umacdi"
@@ -6418,7 +5803,7 @@
(match_operand:SI 2 "register_operand" "r")))
(match_operand:DI 3 "register_operand" "0")))]
"TARGET_SPARCLET"
- "umacd\\t%1, %2, %L0"
+ "umacd\t%1, %2, %L0"
[(set_attr "type" "imul")])
;;- Boolean instructions
@@ -6439,7 +5824,7 @@
"! TARGET_ARCH64"
"@
#
- fand\\t%1, %2, %0"
+ fand\t%1, %2, %0"
[(set_attr "type" "*,fp")
(set_attr "length" "2,*")
(set_attr "fptype" "double")])
@@ -6450,8 +5835,8 @@
(match_operand:DI 2 "arith_double_operand" "rHI,b")))]
"TARGET_ARCH64"
"@
- and\\t%1, %2, %0
- fand\\t%1, %2, %0"
+ and\t%1, %2, %0
+ fand\t%1, %2, %0"
[(set_attr "type" "*,fp")
(set_attr "fptype" "double")])
@@ -6461,8 +5846,8 @@
(match_operand:SI 2 "arith_operand" "rI,d")))]
""
"@
- and\\t%1, %2, %0
- fands\\t%1, %2, %0"
+ and\t%1, %2, %0
+ fands\t%1, %2, %0"
[(set_attr "type" "*,fp")])
(define_split
@@ -6475,10 +5860,9 @@
&& (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
[(set (match_dup 3) (match_dup 4))
(set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
- "
{
operands[4] = GEN_INT (~INTVAL (operands[2]));
-}")
+})
;; Split DImode logical operations requiring two instructions.
(define_split
@@ -6495,7 +5879,6 @@
&& REGNO (SUBREG_REG (operands[0])) < 32))"
[(set (match_dup 4) (match_op_dup:SI 1 [(match_dup 6) (match_dup 8)]))
(set (match_dup 5) (match_op_dup:SI 1 [(match_dup 7) (match_dup 9)]))]
- "
{
operands[4] = gen_highpart (SImode, operands[0]);
operands[5] = gen_lowpart (SImode, operands[0]);
@@ -6513,26 +5896,17 @@
#endif
operands[8] = gen_highpart_mode (SImode, DImode, operands[3]);
operands[9] = gen_lowpart (SImode, operands[3]);
-}")
+})
-(define_insn "*and_not_di_sp32"
+(define_insn_and_split "*and_not_di_sp32"
[(set (match_operand:DI 0 "register_operand" "=r,b")
(and:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
(match_operand:DI 2 "register_operand" "r,b")))]
"! TARGET_ARCH64"
"@
#
- fandnot1\\t%1, %2, %0"
- [(set_attr "type" "*,fp")
- (set_attr "length" "2,*")
- (set_attr "fptype" "double")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (and:DI (not:DI (match_operand:DI 1 "register_operand" ""))
- (match_operand:DI 2 "register_operand" "")))]
- "! TARGET_ARCH64
- && reload_completed
+ fandnot1\t%1, %2, %0"
+ "&& reload_completed
&& ((GET_CODE (operands[0]) == REG
&& REGNO (operands[0]) < 32)
|| (GET_CODE (operands[0]) == SUBREG
@@ -6545,7 +5919,10 @@
operands[5] = gen_highpart (SImode, operands[2]);
operands[6] = gen_lowpart (SImode, operands[0]);
operands[7] = gen_lowpart (SImode, operands[1]);
- operands[8] = gen_lowpart (SImode, operands[2]);")
+ operands[8] = gen_lowpart (SImode, operands[2]);"
+ [(set_attr "type" "*,fp")
+ (set_attr "length" "2,*")
+ (set_attr "fptype" "double")])
(define_insn "*and_not_di_sp64"
[(set (match_operand:DI 0 "register_operand" "=r,b")
@@ -6553,8 +5930,8 @@
(match_operand:DI 2 "register_operand" "r,b")))]
"TARGET_ARCH64"
"@
- andn\\t%2, %1, %0
- fandnot1\\t%1, %2, %0"
+ andn\t%2, %1, %0
+ fandnot1\t%1, %2, %0"
[(set_attr "type" "*,fp")
(set_attr "fptype" "double")])
@@ -6564,8 +5941,8 @@
(match_operand:SI 2 "register_operand" "r,d")))]
""
"@
- andn\\t%2, %1, %0
- fandnot1s\\t%1, %2, %0"
+ andn\t%2, %1, %0
+ fandnot1s\t%1, %2, %0"
[(set_attr "type" "*,fp")])
(define_expand "iordi3"
@@ -6582,7 +5959,7 @@
"! TARGET_ARCH64"
"@
#
- for\\t%1, %2, %0"
+ for\t%1, %2, %0"
[(set_attr "type" "*,fp")
(set_attr "length" "2,*")
(set_attr "fptype" "double")])
@@ -6593,8 +5970,8 @@
(match_operand:DI 2 "arith_double_operand" "rHI,b")))]
"TARGET_ARCH64"
"@
- or\\t%1, %2, %0
- for\\t%1, %2, %0"
+ or\t%1, %2, %0
+ for\t%1, %2, %0"
[(set_attr "type" "*,fp")
(set_attr "fptype" "double")])
@@ -6604,8 +5981,8 @@
(match_operand:SI 2 "arith_operand" "rI,d")))]
""
"@
- or\\t%1, %2, %0
- fors\\t%1, %2, %0"
+ or\t%1, %2, %0
+ fors\t%1, %2, %0"
[(set_attr "type" "*,fp")])
(define_split
@@ -6618,29 +5995,19 @@
&& (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
[(set (match_dup 3) (match_dup 4))
(set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
- "
{
operands[4] = GEN_INT (~INTVAL (operands[2]));
-}")
+})
-(define_insn "*or_not_di_sp32"
+(define_insn_and_split "*or_not_di_sp32"
[(set (match_operand:DI 0 "register_operand" "=r,b")
(ior:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
(match_operand:DI 2 "register_operand" "r,b")))]
"! TARGET_ARCH64"
"@
#
- fornot1\\t%1, %2, %0"
- [(set_attr "type" "*,fp")
- (set_attr "length" "2,*")
- (set_attr "fptype" "double")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (ior:DI (not:DI (match_operand:DI 1 "register_operand" ""))
- (match_operand:DI 2 "register_operand" "")))]
- "! TARGET_ARCH64
- && reload_completed
+ fornot1\t%1, %2, %0"
+ "&& reload_completed
&& ((GET_CODE (operands[0]) == REG
&& REGNO (operands[0]) < 32)
|| (GET_CODE (operands[0]) == SUBREG
@@ -6653,7 +6020,10 @@
operands[5] = gen_highpart (SImode, operands[2]);
operands[6] = gen_lowpart (SImode, operands[0]);
operands[7] = gen_lowpart (SImode, operands[1]);
- operands[8] = gen_lowpart (SImode, operands[2]);")
+ operands[8] = gen_lowpart (SImode, operands[2]);"
+ [(set_attr "type" "*,fp")
+ (set_attr "length" "2,*")
+ (set_attr "fptype" "double")])
(define_insn "*or_not_di_sp64"
[(set (match_operand:DI 0 "register_operand" "=r,b")
@@ -6661,8 +6031,8 @@
(match_operand:DI 2 "register_operand" "r,b")))]
"TARGET_ARCH64"
"@
- orn\\t%2, %1, %0
- fornot1\\t%1, %2, %0"
+ orn\t%2, %1, %0
+ fornot1\t%1, %2, %0"
[(set_attr "type" "*,fp")
(set_attr "fptype" "double")])
@@ -6672,8 +6042,8 @@
(match_operand:SI 2 "register_operand" "r,d")))]
""
"@
- orn\\t%2, %1, %0
- fornot1s\\t%1, %2, %0"
+ orn\t%2, %1, %0
+ fornot1s\t%1, %2, %0"
[(set_attr "type" "*,fp")])
(define_expand "xordi3"
@@ -6690,7 +6060,7 @@
"! TARGET_ARCH64"
"@
#
- fxor\\t%1, %2, %0"
+ fxor\t%1, %2, %0"
[(set_attr "type" "*,fp")
(set_attr "length" "2,*")
(set_attr "fptype" "double")])
@@ -6701,8 +6071,8 @@
(match_operand:DI 2 "arith_double_operand" "rHI,b")))]
"TARGET_ARCH64"
"@
- xor\\t%r1, %2, %0
- fxor\\t%1, %2, %0"
+ xor\t%r1, %2, %0
+ fxor\t%1, %2, %0"
[(set_attr "type" "*,fp")
(set_attr "fptype" "double")])
@@ -6712,7 +6082,7 @@
(match_operand:DI 2 "const64_operand" "")))]
"(TARGET_ARCH64
&& HOST_BITS_PER_WIDE_INT != 64)"
- "xor\\t%1, %2, %0")
+ "xor\t%1, %2, %0")
(define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=r,d")
@@ -6720,8 +6090,8 @@
(match_operand:SI 2 "arith_operand" "rI,d")))]
""
"@
- xor\\t%r1, %2, %0
- fxors\\t%1, %2, %0"
+ xor\t%r1, %2, %0
+ fxors\t%1, %2, %0"
[(set_attr "type" "*,fp")])
(define_split
@@ -6734,10 +6104,9 @@
&& (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
[(set (match_dup 3) (match_dup 4))
(set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
- "
{
operands[4] = GEN_INT (~INTVAL (operands[2]));
-}")
+})
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -6749,31 +6118,21 @@
&& (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
[(set (match_dup 3) (match_dup 4))
(set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
- "
{
operands[4] = GEN_INT (~INTVAL (operands[2]));
-}")
+})
;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
;; Combine now canonicalizes to the rightmost expression.
-(define_insn "*xor_not_di_sp32"
+(define_insn_and_split "*xor_not_di_sp32"
[(set (match_operand:DI 0 "register_operand" "=r,b")
(not:DI (xor:DI (match_operand:DI 1 "register_operand" "r,b")
(match_operand:DI 2 "register_operand" "r,b"))))]
"! TARGET_ARCH64"
"@
#
- fxnor\\t%1, %2, %0"
- [(set_attr "type" "*,fp")
- (set_attr "length" "2,*")
- (set_attr "fptype" "double")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (not:DI (xor:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "register_operand" ""))))]
- "! TARGET_ARCH64
- && reload_completed
+ fxnor\t%1, %2, %0"
+ "&& reload_completed
&& ((GET_CODE (operands[0]) == REG
&& REGNO (operands[0]) < 32)
|| (GET_CODE (operands[0]) == SUBREG
@@ -6786,7 +6145,10 @@
operands[5] = gen_highpart (SImode, operands[2]);
operands[6] = gen_lowpart (SImode, operands[0]);
operands[7] = gen_lowpart (SImode, operands[1]);
- operands[8] = gen_lowpart (SImode, operands[2]);")
+ operands[8] = gen_lowpart (SImode, operands[2]);"
+ [(set_attr "type" "*,fp")
+ (set_attr "length" "2,*")
+ (set_attr "fptype" "double")])
(define_insn "*xor_not_di_sp64"
[(set (match_operand:DI 0 "register_operand" "=r,b")
@@ -6794,8 +6156,8 @@
(match_operand:DI 2 "arith_double_operand" "rHI,b"))))]
"TARGET_ARCH64"
"@
- xnor\\t%r1, %2, %0
- fxnor\\t%1, %2, %0"
+ xnor\t%r1, %2, %0
+ fxnor\t%1, %2, %0"
[(set_attr "type" "*,fp")
(set_attr "fptype" "double")])
@@ -6805,8 +6167,8 @@
(match_operand:SI 2 "arith_operand" "rI,d"))))]
""
"@
- xnor\\t%r1, %2, %0
- fxnors\\t%1, %2, %0"
+ xnor\t%r1, %2, %0
+ fxnors\t%1, %2, %0"
[(set_attr "type" "*,fp")])
;; These correspond to the above in the case where we also (or only)
@@ -6820,7 +6182,7 @@
(match_operand:SI 1 "arith_operand" "rI")])
(const_int 0)))]
""
- "%A2cc\\t%0, %1, %%g0"
+ "%A2cc\t%0, %1, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_arith_op"
@@ -6831,7 +6193,7 @@
(match_operand:DI 1 "arith_double_operand" "rHI")])
(const_int 0)))]
"TARGET_ARCH64"
- "%A2cc\\t%0, %1, %%g0"
+ "%A2cc\t%0, %1, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_arith_op_set"
@@ -6844,7 +6206,7 @@
(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 4 "cc_arithop" [(match_dup 1) (match_dup 2)]))]
"GET_CODE (operands[3]) == GET_CODE (operands[4])"
- "%A3cc\\t%1, %2, %0"
+ "%A3cc\t%1, %2, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_arith_op_set"
@@ -6857,7 +6219,7 @@
(set (match_operand:DI 0 "register_operand" "=r")
(match_operator:DI 4 "cc_arithop" [(match_dup 1) (match_dup 2)]))]
"TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
- "%A3cc\\t%1, %2, %0"
+ "%A3cc\t%1, %2, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_xor_not"
@@ -6867,7 +6229,7 @@
(match_operand:SI 1 "arith_operand" "rI")))
(const_int 0)))]
""
- "xnorcc\\t%r0, %1, %%g0"
+ "xnorcc\t%r0, %1, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_xor_not"
@@ -6877,7 +6239,7 @@
(match_operand:DI 1 "arith_double_operand" "rHI")))
(const_int 0)))]
"TARGET_ARCH64"
- "xnorcc\\t%r0, %1, %%g0"
+ "xnorcc\t%r0, %1, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_xor_not_set"
@@ -6889,7 +6251,7 @@
(set (match_operand:SI 0 "register_operand" "=r")
(not:SI (xor:SI (match_dup 1) (match_dup 2))))]
""
- "xnorcc\\t%r1, %2, %0"
+ "xnorcc\t%r1, %2, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_xor_not_set"
@@ -6901,7 +6263,7 @@
(set (match_operand:DI 0 "register_operand" "=r")
(not:DI (xor:DI (match_dup 1) (match_dup 2))))]
"TARGET_ARCH64"
- "xnorcc\\t%r1, %2, %0"
+ "xnorcc\t%r1, %2, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_arith_op_not"
@@ -6912,7 +6274,7 @@
(match_operand:SI 1 "reg_or_0_operand" "rJ")])
(const_int 0)))]
""
- "%B2cc\\t%r1, %0, %%g0"
+ "%B2cc\t%r1, %0, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_arith_op_not"
@@ -6923,7 +6285,7 @@
(match_operand:DI 1 "reg_or_0_operand" "rJ")])
(const_int 0)))]
"TARGET_ARCH64"
- "%B2cc\\t%r1, %0, %%g0"
+ "%B2cc\t%r1, %0, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_arith_op_not_set"
@@ -6937,7 +6299,7 @@
(match_operator:SI 4 "cc_arithopn"
[(not:SI (match_dup 1)) (match_dup 2)]))]
"GET_CODE (operands[3]) == GET_CODE (operands[4])"
- "%B3cc\\t%r2, %1, %0"
+ "%B3cc\t%r2, %1, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_arith_op_not_set"
@@ -6951,7 +6313,7 @@
(match_operator:DI 4 "cc_arithopn"
[(not:DI (match_dup 1)) (match_dup 2)]))]
"TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
- "%B3cc\\t%r2, %1, %0"
+ "%B3cc\t%r2, %1, %0"
[(set_attr "type" "compare")])
;; We cannot use the "neg" pseudo insn because the Sun assembler
@@ -6961,7 +6323,6 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_operand:DI 1 "register_operand" "r")))]
""
- "
{
if (! TARGET_ARCH64)
{
@@ -6975,22 +6336,15 @@
SPARC_ICC_REG)))));
DONE;
}
-}")
+})
-(define_insn "*negdi2_sp32"
+(define_insn_and_split "*negdi2_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_operand:DI 1 "register_operand" "r")))
(clobber (reg:CC 100))]
"TARGET_ARCH32"
"#"
- [(set_attr "length" "2")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (neg:DI (match_operand:DI 1 "register_operand" "")))
- (clobber (reg:CC 100))]
- "TARGET_ARCH32
- && reload_completed"
+ "&& reload_completed"
[(parallel [(set (reg:CC_NOOV 100)
(compare:CC_NOOV (minus:SI (const_int 0) (match_dup 5))
(const_int 0)))
@@ -7000,26 +6354,27 @@
"operands[2] = gen_highpart (SImode, operands[0]);
operands[3] = gen_highpart (SImode, operands[1]);
operands[4] = gen_lowpart (SImode, operands[0]);
- operands[5] = gen_lowpart (SImode, operands[1]);")
+ operands[5] = gen_lowpart (SImode, operands[1]);"
+ [(set_attr "length" "2")])
(define_insn "*negdi2_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_operand:DI 1 "register_operand" "r")))]
"TARGET_ARCH64"
- "sub\\t%%g0, %1, %0")
+ "sub\t%%g0, %1, %0")
(define_insn "negsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
""
- "sub\\t%%g0, %1, %0")
+ "sub\t%%g0, %1, %0")
(define_insn "*cmp_cc_neg"
[(set (reg:CC_NOOV 100)
(compare:CC_NOOV (neg:SI (match_operand:SI 0 "arith_operand" "rI"))
(const_int 0)))]
""
- "subcc\\t%%g0, %0, %%g0"
+ "subcc\t%%g0, %0, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_neg"
@@ -7027,7 +6382,7 @@
(compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
(const_int 0)))]
"TARGET_ARCH64"
- "subcc\\t%%g0, %0, %%g0"
+ "subcc\t%%g0, %0, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_set_neg"
@@ -7037,7 +6392,7 @@
(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_dup 1)))]
""
- "subcc\\t%%g0, %1, %0"
+ "subcc\t%%g0, %1, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_set_neg"
@@ -7047,7 +6402,7 @@
(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_dup 1)))]
"TARGET_ARCH64"
- "subcc\\t%%g0, %1, %0"
+ "subcc\t%%g0, %1, %0"
[(set_attr "type" "compare")])
;; We cannot use the "not" pseudo insn because the Sun assembler
@@ -7058,22 +6413,14 @@
""
"")
-(define_insn "*one_cmpldi2_sp32"
+(define_insn_and_split "*one_cmpldi2_sp32"
[(set (match_operand:DI 0 "register_operand" "=r,b")
(not:DI (match_operand:DI 1 "register_operand" "r,b")))]
"! TARGET_ARCH64"
"@
#
- fnot1\\t%1, %0"
- [(set_attr "type" "*,fp")
- (set_attr "length" "2,*")
- (set_attr "fptype" "double")])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (not:DI (match_operand:DI 1 "register_operand" "")))]
- "! TARGET_ARCH64
- && reload_completed
+ fnot1\t%1, %0"
+ "&& reload_completed
&& ((GET_CODE (operands[0]) == REG
&& REGNO (operands[0]) < 32)
|| (GET_CODE (operands[0]) == SUBREG
@@ -7084,15 +6431,18 @@
"operands[2] = gen_highpart (SImode, operands[0]);
operands[3] = gen_highpart (SImode, operands[1]);
operands[4] = gen_lowpart (SImode, operands[0]);
- operands[5] = gen_lowpart (SImode, operands[1]);")
+ operands[5] = gen_lowpart (SImode, operands[1]);"
+ [(set_attr "type" "*,fp")
+ (set_attr "length" "2,*")
+ (set_attr "fptype" "double")])
(define_insn "*one_cmpldi2_sp64"
[(set (match_operand:DI 0 "register_operand" "=r,b")
(not:DI (match_operand:DI 1 "arith_double_operand" "rHI,b")))]
"TARGET_ARCH64"
"@
- xnor\\t%%g0, %1, %0
- fnot1\\t%1, %0"
+ xnor\t%%g0, %1, %0
+ fnot1\t%1, %0"
[(set_attr "type" "*,fp")
(set_attr "fptype" "double")])
@@ -7101,8 +6451,8 @@
(not:SI (match_operand:SI 1 "arith_operand" "rI,d")))]
""
"@
- xnor\\t%%g0, %1, %0
- fnot1s\\t%1, %0"
+ xnor\t%%g0, %1, %0
+ fnot1s\t%1, %0"
[(set_attr "type" "*,fp")])
(define_insn "*cmp_cc_not"
@@ -7110,7 +6460,7 @@
(compare:CC (not:SI (match_operand:SI 0 "arith_operand" "rI"))
(const_int 0)))]
""
- "xnorcc\\t%%g0, %0, %%g0"
+ "xnorcc\t%%g0, %0, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_not"
@@ -7118,7 +6468,7 @@
(compare:CCX (not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
(const_int 0)))]
"TARGET_ARCH64"
- "xnorcc\\t%%g0, %0, %%g0"
+ "xnorcc\t%%g0, %0, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_set_not"
@@ -7128,7 +6478,7 @@
(set (match_operand:SI 0 "register_operand" "=r")
(not:SI (match_dup 1)))]
""
- "xnorcc\\t%%g0, %1, %0"
+ "xnorcc\t%%g0, %1, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_set_not"
@@ -7138,7 +6488,7 @@
(set (match_operand:DI 0 "register_operand" "=r")
(not:DI (match_dup 1)))]
"TARGET_ARCH64"
- "xnorcc\\t%%g0, %1, %0"
+ "xnorcc\t%%g0, %1, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_set"
@@ -7148,7 +6498,7 @@
(compare:CC (match_dup 1)
(const_int 0)))]
""
- "orcc\\t%1, 0, %0"
+ "orcc\t%1, 0, %0"
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_set64"
@@ -7158,7 +6508,7 @@
(compare:CCX (match_dup 1)
(const_int 0)))]
"TARGET_ARCH64"
- "orcc\\t%1, 0, %0"
+ "orcc\t%1, 0, %0"
[(set_attr "type" "compare")])
;; Floating point arithmetic instructions.
@@ -7175,7 +6525,7 @@
(plus:TF (match_operand:TF 1 "register_operand" "e")
(match_operand:TF 2 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "faddq\\t%1, %2, %0"
+ "faddq\t%1, %2, %0"
[(set_attr "type" "fp")])
(define_insn "adddf3"
@@ -7183,7 +6533,7 @@
(plus:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU"
- "faddd\\t%1, %2, %0"
+ "faddd\t%1, %2, %0"
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
@@ -7192,7 +6542,7 @@
(plus:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
- "fadds\\t%1, %2, %0"
+ "fadds\t%1, %2, %0"
[(set_attr "type" "fp")])
(define_expand "subtf3"
@@ -7207,7 +6557,7 @@
(minus:TF (match_operand:TF 1 "register_operand" "e")
(match_operand:TF 2 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fsubq\\t%1, %2, %0"
+ "fsubq\t%1, %2, %0"
[(set_attr "type" "fp")])
(define_insn "subdf3"
@@ -7215,7 +6565,7 @@
(minus:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU"
- "fsubd\\t%1, %2, %0"
+ "fsubd\t%1, %2, %0"
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
@@ -7224,7 +6574,7 @@
(minus:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
- "fsubs\\t%1, %2, %0"
+ "fsubs\t%1, %2, %0"
[(set_attr "type" "fp")])
(define_expand "multf3"
@@ -7239,7 +6589,7 @@
(mult:TF (match_operand:TF 1 "register_operand" "e")
(match_operand:TF 2 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fmulq\\t%1, %2, %0"
+ "fmulq\t%1, %2, %0"
[(set_attr "type" "fpmul")])
(define_insn "muldf3"
@@ -7247,7 +6597,7 @@
(mult:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU"
- "fmuld\\t%1, %2, %0"
+ "fmuld\t%1, %2, %0"
[(set_attr "type" "fpmul")
(set_attr "fptype" "double")])
@@ -7256,7 +6606,7 @@
(mult:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
- "fmuls\\t%1, %2, %0"
+ "fmuls\t%1, %2, %0"
[(set_attr "type" "fpmul")])
(define_insn "*muldf3_extend"
@@ -7264,7 +6614,7 @@
(mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "f"))
(float_extend:DF (match_operand:SF 2 "register_operand" "f"))))]
"(TARGET_V8 || TARGET_V9) && TARGET_FPU"
- "fsmuld\\t%1, %2, %0"
+ "fsmuld\t%1, %2, %0"
[(set_attr "type" "fpmul")
(set_attr "fptype" "double")])
@@ -7273,7 +6623,7 @@
(mult:TF (float_extend:TF (match_operand:DF 1 "register_operand" "e"))
(float_extend:TF (match_operand:DF 2 "register_operand" "e"))))]
"(TARGET_V8 || TARGET_V9) && TARGET_FPU && TARGET_HARD_QUAD"
- "fdmulq\\t%1, %2, %0"
+ "fdmulq\t%1, %2, %0"
[(set_attr "type" "fpmul")])
(define_expand "divtf3"
@@ -7289,7 +6639,7 @@
(div:TF (match_operand:TF 1 "register_operand" "e")
(match_operand:TF 2 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fdivq\\t%1, %2, %0"
+ "fdivq\t%1, %2, %0"
[(set_attr "type" "fpdivd")])
(define_insn "divdf3"
@@ -7297,7 +6647,7 @@
(div:DF (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU"
- "fdivd\\t%1, %2, %0"
+ "fdivd\t%1, %2, %0"
[(set_attr "type" "fpdivd")
(set_attr "fptype" "double")])
@@ -7306,7 +6656,7 @@
(div:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
- "fdivs\\t%1, %2, %0"
+ "fdivs\t%1, %2, %0"
[(set_attr "type" "fpdivs")])
(define_expand "negtf2"
@@ -7315,24 +6665,16 @@
"TARGET_FPU"
"")
-(define_insn "*negtf2_notv9"
+(define_insn_and_split "*negtf2_notv9"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
"TARGET_FPU
&& ! TARGET_V9"
"@
- fnegs\\t%0, %0
+ fnegs\t%0, %0
#"
- [(set_attr "type" "fpmove,*")
- (set_attr "length" "*,2")])
-
-(define_split
- [(set (match_operand:TF 0 "register_operand" "")
- (neg:TF (match_operand:TF 1 "register_operand" "")))]
- "TARGET_FPU
- && ! TARGET_V9
- && reload_completed
+ "&& reload_completed
&& sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
[(set (match_dup 2) (neg:SF (match_dup 3)))
(set (match_dup 4) (match_dup 5))
@@ -7342,33 +6684,29 @@
operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
operands[6] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
- operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);")
+ operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
+ [(set_attr "type" "fpmove,*")
+ (set_attr "length" "*,2")])
-(define_insn "*negtf2_v9"
+(define_insn_and_split "*negtf2_v9"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(neg:TF (match_operand:TF 1 "register_operand" "0,e")))]
; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
"TARGET_FPU && TARGET_V9"
"@
- fnegd\\t%0, %0
+ fnegd\t%0, %0
#"
- [(set_attr "type" "fpmove,*")
- (set_attr "length" "*,2")
- (set_attr "fptype" "double")])
-
-(define_split
- [(set (match_operand:TF 0 "register_operand" "")
- (neg:TF (match_operand:TF 1 "register_operand" "")))]
- "TARGET_FPU
- && TARGET_V9
- && reload_completed
+ "&& reload_completed
&& sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
[(set (match_dup 2) (neg:DF (match_dup 3)))
(set (match_dup 4) (match_dup 5))]
"operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
- operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);")
+ operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
+ [(set_attr "type" "fpmove,*")
+ (set_attr "length" "*,2")
+ (set_attr "fptype" "double")])
(define_expand "negdf2"
[(set (match_operand:DF 0 "register_operand" "")
@@ -7376,35 +6714,29 @@
"TARGET_FPU"
"")
-(define_insn "*negdf2_notv9"
+(define_insn_and_split "*negdf2_notv9"
[(set (match_operand:DF 0 "register_operand" "=e,e")
(neg:DF (match_operand:DF 1 "register_operand" "0,e")))]
"TARGET_FPU && ! TARGET_V9"
"@
- fnegs\\t%0, %0
+ fnegs\t%0, %0
#"
- [(set_attr "type" "fpmove,*")
- (set_attr "length" "*,2")])
-
-(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (neg:DF (match_operand:DF 1 "register_operand" "")))]
- "TARGET_FPU
- && ! TARGET_V9
- && reload_completed
+ "&& reload_completed
&& sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
[(set (match_dup 2) (neg:SF (match_dup 3)))
(set (match_dup 4) (match_dup 5))]
"operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
- operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);")
+ operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);"
+ [(set_attr "type" "fpmove,*")
+ (set_attr "length" "*,2")])
(define_insn "*negdf2_v9"
[(set (match_operand:DF 0 "register_operand" "=e")
(neg:DF (match_operand:DF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_V9"
- "fnegd\\t%1, %0"
+ "fnegd\t%1, %0"
[(set_attr "type" "fpmove")
(set_attr "fptype" "double")])
@@ -7412,7 +6744,7 @@
[(set (match_operand:SF 0 "register_operand" "=f")
(neg:SF (match_operand:SF 1 "register_operand" "f")))]
"TARGET_FPU"
- "fnegs\\t%1, %0"
+ "fnegs\t%1, %0"
[(set_attr "type" "fpmove")])
(define_expand "abstf2"
@@ -7421,23 +6753,15 @@
"TARGET_FPU"
"")
-(define_insn "*abstf2_notv9"
+(define_insn_and_split "*abstf2_notv9"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
; We don't use quad float insns here so we don't need TARGET_HARD_QUAD.
"TARGET_FPU && ! TARGET_V9"
"@
- fabss\\t%0, %0
+ fabss\t%0, %0
#"
- [(set_attr "type" "fpmove,*")
- (set_attr "length" "*,2")])
-
-(define_split
- [(set (match_operand:TF 0 "register_operand" "")
- (abs:TF (match_operand:TF 1 "register_operand" "")))]
- "TARGET_FPU
- && ! TARGET_V9
- && reload_completed
+ "&& reload_completed
&& sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
[(set (match_dup 2) (abs:SF (match_dup 3)))
(set (match_dup 4) (match_dup 5))
@@ -7447,42 +6771,38 @@
operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);
operands[6] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
- operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);")
+ operands[7] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
+ [(set_attr "type" "fpmove,*")
+ (set_attr "length" "*,2")])
(define_insn "*abstf2_hq_v9"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
"TARGET_FPU && TARGET_V9 && TARGET_HARD_QUAD"
"@
- fabsd\\t%0, %0
- fabsq\\t%1, %0"
+ fabsd\t%0, %0
+ fabsq\t%1, %0"
[(set_attr "type" "fpmove")
(set_attr "fptype" "double,*")])
-(define_insn "*abstf2_v9"
+(define_insn_and_split "*abstf2_v9"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(abs:TF (match_operand:TF 1 "register_operand" "0,e")))]
"TARGET_FPU && TARGET_V9 && !TARGET_HARD_QUAD"
"@
- fabsd\\t%0, %0
+ fabsd\t%0, %0
#"
- [(set_attr "type" "fpmove,*")
- (set_attr "length" "*,2")
- (set_attr "fptype" "double,*")])
-
-(define_split
- [(set (match_operand:TF 0 "register_operand" "")
- (abs:TF (match_operand:TF 1 "register_operand" "")))]
- "TARGET_FPU
- && TARGET_V9
- && reload_completed
+ "&& reload_completed
&& sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
[(set (match_dup 2) (abs:DF (match_dup 3)))
(set (match_dup 4) (match_dup 5))]
"operands[2] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]));
operands[3] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]));
operands[4] = gen_rtx_raw_REG (DFmode, REGNO (operands[0]) + 2);
- operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);")
+ operands[5] = gen_rtx_raw_REG (DFmode, REGNO (operands[1]) + 2);"
+ [(set_attr "type" "fpmove,*")
+ (set_attr "length" "*,2")
+ (set_attr "fptype" "double,*")])
(define_expand "absdf2"
[(set (match_operand:DF 0 "register_operand" "")
@@ -7490,35 +6810,29 @@
"TARGET_FPU"
"")
-(define_insn "*absdf2_notv9"
+(define_insn_and_split "*absdf2_notv9"
[(set (match_operand:DF 0 "register_operand" "=e,e")
(abs:DF (match_operand:DF 1 "register_operand" "0,e")))]
"TARGET_FPU && ! TARGET_V9"
"@
- fabss\\t%0, %0
+ fabss\t%0, %0
#"
- [(set_attr "type" "fpmove,*")
- (set_attr "length" "*,2")])
-
-(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (abs:DF (match_operand:DF 1 "register_operand" "")))]
- "TARGET_FPU
- && ! TARGET_V9
- && reload_completed
+ "&& reload_completed
&& sparc_absnegfloat_split_legitimate (operands[0], operands[1])"
[(set (match_dup 2) (abs:SF (match_dup 3)))
(set (match_dup 4) (match_dup 5))]
"operands[2] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]));
operands[3] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]));
operands[4] = gen_rtx_raw_REG (SFmode, REGNO (operands[0]) + 1);
- operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);")
+ operands[5] = gen_rtx_raw_REG (SFmode, REGNO (operands[1]) + 1);"
+ [(set_attr "type" "fpmove,*")
+ (set_attr "length" "*,2")])
(define_insn "*absdf2_v9"
[(set (match_operand:DF 0 "register_operand" "=e")
(abs:DF (match_operand:DF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_V9"
- "fabsd\\t%1, %0"
+ "fabsd\t%1, %0"
[(set_attr "type" "fpmove")
(set_attr "fptype" "double")])
@@ -7526,7 +6840,7 @@
[(set (match_operand:SF 0 "register_operand" "=f")
(abs:SF (match_operand:SF 1 "register_operand" "f")))]
"TARGET_FPU"
- "fabss\\t%1, %0"
+ "fabss\t%1, %0"
[(set_attr "type" "fpmove")])
(define_expand "sqrttf2"
@@ -7539,14 +6853,14 @@
[(set (match_operand:TF 0 "register_operand" "=e")
(sqrt:TF (match_operand:TF 1 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
- "fsqrtq\\t%1, %0"
+ "fsqrtq\t%1, %0"
[(set_attr "type" "fpsqrtd")])
(define_insn "sqrtdf2"
[(set (match_operand:DF 0 "register_operand" "=e")
(sqrt:DF (match_operand:DF 1 "register_operand" "e")))]
"TARGET_FPU"
- "fsqrtd\\t%1, %0"
+ "fsqrtd\t%1, %0"
[(set_attr "type" "fpsqrtd")
(set_attr "fptype" "double")])
@@ -7554,7 +6868,7 @@
[(set (match_operand:SF 0 "register_operand" "=f")
(sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
"TARGET_FPU"
- "fsqrts\\t%1, %0"
+ "fsqrts\t%1, %0"
[(set_attr "type" "fpsqrts")])
;;- arithmetic shift instructions
@@ -7564,31 +6878,20 @@
(ashift:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))]
""
- "*
{
- if (GET_CODE (operands[2]) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
- operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
-
- return \"sll\\t%1, %2, %0\";
-}"
- [(set_attr "type" "shift")])
-
-;; We special case multiplication by two, as add can be done
-;; in both ALUs, while shift only in IEU0 on UltraSPARC.
-(define_insn "*ashlsi3_const1"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ashift:SI (match_operand:SI 1 "register_operand" "r")
- (const_int 1)))]
- ""
- "add\\t%1, %1, %0")
+ if (operands[2] == const1_rtx)
+ return "add\t%1, %1, %0";
+ return "sll\t%1, %2, %0";
+}
+ [(set (attr "type")
+ (if_then_else (match_operand 2 "const1_operand" "")
+ (const_string "ialu") (const_string "shift")))])
(define_expand "ashldi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))]
"TARGET_ARCH64 || TARGET_V8PLUS"
- "
{
if (! TARGET_ARCH64)
{
@@ -7597,31 +6900,21 @@
emit_insn (gen_ashldi3_v8plus (operands[0], operands[1], operands[2]));
DONE;
}
-}")
-
-;; We special case multiplication by two, as add can be done
-;; in both ALUs, while shift only in IEU0 on UltraSPARC.
-(define_insn "*ashldi3_const1"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (ashift:DI (match_operand:DI 1 "register_operand" "r")
- (const_int 1)))]
- "TARGET_ARCH64"
- "add\\t%1, %1, %0")
+})
(define_insn "*ashldi3_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))]
"TARGET_ARCH64"
- "*
{
- if (GET_CODE (operands[2]) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
- operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
-
- return \"sllx\\t%1, %2, %0\";
-}"
- [(set_attr "type" "shift")])
+ if (operands[2] == const1_rtx)
+ return "add\t%1, %1, %0";
+ return "sllx\t%1, %2, %0";
+}
+ [(set (attr "type")
+ (if_then_else (match_operand 2 "const1_operand" "")
+ (const_string "ialu") (const_string "shift")))])
;; XXX UGH!
(define_insn "ashldi3_v8plus"
@@ -7630,7 +6923,7 @@
(match_operand:SI 2 "arith_operand" "rI,rI,rI")))
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
- "*return sparc_v8plus_shift (operands, insn, \"sllx\");"
+ { return sparc_v8plus_shift (operands, insn, "sllx"); }
[(set_attr "type" "multi")
(set_attr "length" "5,5,6")])
@@ -7643,12 +6936,11 @@
; (match_operand:SI 1 "arith_operand" "rI"))
; (const_int -1)))]
; "0 && TARGET_V8PLUS"
-; "*
;{
; if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == REGNO (operands[0]))
-; return \"mov\\t1, %L0\;sllx\\t%L0, %1, %L0\;sub\\t%L0, 1, %L0\;srlx\\t%L0, 32, %H0\";
-; return \"mov\\t1, %H0\;sllx\\t%H0, %1, %L0\;sub\\t%L0, 1, %L0\;srlx\\t%L0, 32, %H0\";
-;}"
+; return "mov\t1, %L0\;sllx\t%L0, %1, %L0\;sub\t%L0, 1, %L0\;srlx\t%L0, 32, %H0";
+; return "mov\t1, %H0\;sllx\t%H0, %1, %L0\;sub\t%L0, 1, %L0\;srlx\t%L0, 32, %H0";
+;}
; [(set_attr "type" "multi")
; (set_attr "length" "4")])
@@ -7658,7 +6950,7 @@
(const_int 1))
(const_int 0)))]
""
- "addcc\\t%0, %0, %%g0"
+ "addcc\t%0, %0, %%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_set_ashift_1"
@@ -7669,7 +6961,7 @@
(set (match_operand:SI 0 "register_operand" "=r")
(ashift:SI (match_dup 1) (const_int 1)))]
""
- "addcc\\t%1, %1, %0"
+ "addcc\t%1, %1, %0"
[(set_attr "type" "compare")])
(define_insn "ashrsi3"
@@ -7677,14 +6969,7 @@
(ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))]
""
- "*
-{
- if (GET_CODE (operands[2]) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
- operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
-
- return \"sra\\t%1, %2, %0\";
-}"
+ "sra\t%1, %2, %0"
[(set_attr "type" "shift")])
(define_insn "*ashrsi3_extend"
@@ -7692,7 +6977,7 @@
(sign_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "r"))))]
"TARGET_ARCH64"
- "sra\\t%1, %2, %0"
+ "sra\t%1, %2, %0"
[(set_attr "type" "shift")])
;; This handles the case as above, but with constant shift instead of
@@ -7709,12 +6994,11 @@
&& !CONST_DOUBLE_HIGH (operands[2])
&& CONST_DOUBLE_LOW (operands[2]) >= 32
&& CONST_DOUBLE_LOW (operands[2]) < 64))"
- "*
{
operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
- return \"sra\\t%1, %2, %0\";
-}"
+ return "sra\t%1, %2, %0";
+}
[(set_attr "type" "shift")])
(define_expand "ashrdi3"
@@ -7722,7 +7006,6 @@
(ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))]
"TARGET_ARCH64 || TARGET_V8PLUS"
- "
{
if (! TARGET_ARCH64)
{
@@ -7731,21 +7014,14 @@
emit_insn (gen_ashrdi3_v8plus (operands[0], operands[1], operands[2]));
DONE;
}
-}")
+})
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
(ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))]
"TARGET_ARCH64"
- "*
-{
- if (GET_CODE (operands[2]) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
- operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
-
- return \"srax\\t%1, %2, %0\";
-}"
+ "srax\t%1, %2, %0"
[(set_attr "type" "shift")])
;; XXX
@@ -7755,7 +7031,7 @@
(match_operand:SI 2 "arith_operand" "rI,rI,rI")))
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
- "*return sparc_v8plus_shift (operands, insn, \"srax\");"
+ { return sparc_v8plus_shift (operands, insn, "srax"); }
[(set_attr "type" "multi")
(set_attr "length" "5,5,6")])
@@ -7764,14 +7040,7 @@
(lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))]
""
- "*
-{
- if (GET_CODE (operands[2]) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
- operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
-
- return \"srl\\t%1, %2, %0\";
-}"
+ "srl\t%1, %2, %0"
[(set_attr "type" "shift")])
;; This handles the case where
@@ -7789,7 +7058,7 @@
|| (HOST_BITS_PER_WIDE_INT >= 64
&& GET_CODE (operands[3]) == CONST_INT
&& (unsigned HOST_WIDE_INT) INTVAL (operands[3]) == 0xffffffff))"
- "srl\\t%1, %2, %0"
+ "srl\t%1, %2, %0"
[(set_attr "type" "shift")])
;; This handles the case where
@@ -7806,12 +7075,11 @@
|| (GET_CODE (operands[2]) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (operands[2]) == 0
&& (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
- "*
{
operands[2] = GEN_INT (32 - INTVAL (operands[2]));
- return \"srl\\t%1, %2, %0\";
-}"
+ return "srl\t%1, %2, %0";
+}
[(set_attr "type" "shift")])
(define_expand "lshrdi3"
@@ -7819,7 +7087,6 @@
(lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))]
"TARGET_ARCH64 || TARGET_V8PLUS"
- "
{
if (! TARGET_ARCH64)
{
@@ -7828,21 +7095,14 @@
emit_insn (gen_lshrdi3_v8plus (operands[0], operands[1], operands[2]));
DONE;
}
-}")
+})
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
(lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))]
"TARGET_ARCH64"
- "*
-{
- if (GET_CODE (operands[2]) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
- operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
-
- return \"srlx\\t%1, %2, %0\";
-}"
+ "srlx\t%1, %2, %0"
[(set_attr "type" "shift")])
;; XXX
@@ -7852,7 +7112,7 @@
(match_operand:SI 2 "arith_operand" "rI,rI,rI")))
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
- "*return sparc_v8plus_shift (operands, insn, \"srlx\");"
+ { return sparc_v8plus_shift (operands, insn, "srlx"); }
[(set_attr "type" "multi")
(set_attr "length" "5,5,6")])
@@ -7867,12 +7127,11 @@
|| (GET_CODE (operands[2]) == CONST_DOUBLE
&& !CONST_DOUBLE_HIGH (operands[2])
&& (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
- "*
{
operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
- return \"srax\\t%1, %2, %0\";
-}"
+ return "srax\t%1, %2, %0";
+}
[(set_attr "type" "shift")])
(define_insn ""
@@ -7886,12 +7145,11 @@
|| (GET_CODE (operands[2]) == CONST_DOUBLE
&& !CONST_DOUBLE_HIGH (operands[2])
&& (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
- "*
{
operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
- return \"srlx\\t%1, %2, %0\";
-}"
+ return "srlx\t%1, %2, %0";
+}
[(set_attr "type" "shift")])
(define_insn ""
@@ -7904,12 +7162,11 @@
&& (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
&& (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
&& (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
- "*
{
operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]));
- return \"srax\\t%1, %2, %0\";
-}"
+ return "srax\t%1, %2, %0";
+}
[(set_attr "type" "shift")])
(define_insn ""
@@ -7922,24 +7179,22 @@
&& (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
&& (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
&& (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
- "*
{
operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]));
- return \"srlx\\t%1, %2, %0\";
-}"
+ return "srlx\t%1, %2, %0";
+}
[(set_attr "type" "shift")])
;; Unconditional and other jump instructions
-;; On the Sparc, by setting the annul bit on an unconditional branch, the
+;; On the SPARC, by setting the annul bit on an unconditional branch, the
;; following insn is never executed. This saves us a nop. Dbx does not
;; handle such branches though, so we only use them when optimizing.
(define_insn "jump"
[(set (pc) (label_ref (match_operand 0 "" "")))]
""
- "*
{
- /* TurboSparc is reported to have problems with
+ /* TurboSPARC is reported to have problems with
with
foo: b,a foo
i.e. an empty loop with the annul bit set. The workaround is to use
@@ -7949,17 +7204,16 @@
if (! TARGET_V9 && flag_delayed_branch
&& (INSN_ADDRESSES (INSN_UID (operands[0]))
== INSN_ADDRESSES (INSN_UID (insn))))
- return \"b\\t%l0%#\";
+ return "b\t%l0%#";
else
- return TARGET_V9 ? \"ba,pt%*\\t%%xcc, %l0%(\" : \"b%*\\t%l0%(\";
-}"
+ return TARGET_V9 ? "ba%*,pt\t%%xcc, %l0%(" : "b%*\t%l0%(";
+}
[(set_attr "type" "uncond_branch")])
(define_expand "tablejump"
[(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
(use (label_ref (match_operand 1 "" "")))])]
""
- "
{
if (GET_MODE (operands[0]) != CASE_VECTOR_MODE)
abort ();
@@ -7977,20 +7231,20 @@
tmp = gen_rtx_PLUS (Pmode, tmp2, tmp);
operands[0] = memory_address (Pmode, tmp);
}
-}")
+})
(define_insn "*tablejump_sp32"
[(set (pc) (match_operand:SI 0 "address_operand" "p"))
(use (label_ref (match_operand 1 "" "")))]
"! TARGET_ARCH64"
- "jmp\\t%a0%#"
+ "jmp\t%a0%#"
[(set_attr "type" "uncond_branch")])
(define_insn "*tablejump_sp64"
[(set (pc) (match_operand:DI 0 "address_operand" "p"))
(use (label_ref (match_operand 1 "" "")))]
"TARGET_ARCH64"
- "jmp\\t%a0%#"
+ "jmp\t%a0%#"
[(set_attr "type" "uncond_branch")])
;; This pattern recognizes the "instruction" that appears in
@@ -7999,7 +7253,7 @@
;(define_insn "*unimp_insn"
; [(match_operand:SI 0 "immediate_operand" "")]
; "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
-; "unimp\\t%0"
+; "unimp\t%0"
; [(set_attr "type" "marker")])
;;- jump to subroutine
@@ -8011,7 +7265,6 @@
;; operands[2] is next_arg_register
;; operands[3] is struct_value_size_rtx.
""
- "
{
rtx fn_rtx, nregs_rtx;
@@ -8085,7 +7338,7 @@
#endif
DONE;
-}")
+})
;; We can't use the same pattern for these two insns, because then registers
;; in the address may not be properly reloaded.
@@ -8096,7 +7349,7 @@
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64"
- "call\\t%a0, %1%#"
+ "call\t%a0, %1%#"
[(set_attr "type" "call")])
(define_insn "*call_symbolic_sp32"
@@ -8105,7 +7358,7 @@
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64"
- "call\\t%a0, %1%#"
+ "call\t%a0, %1%#"
[(set_attr "type" "call")])
(define_insn "*call_address_sp64"
@@ -8114,7 +7367,7 @@
(clobber (reg:DI 15))]
;;- Do not use operand 1 for most machines.
"TARGET_ARCH64"
- "call\\t%a0, %1%#"
+ "call\t%a0, %1%#"
[(set_attr "type" "call")])
(define_insn "*call_symbolic_sp64"
@@ -8123,7 +7376,7 @@
(clobber (reg:DI 15))]
;;- Do not use operand 1 for most machines.
"TARGET_ARCH64"
- "call\\t%a0, %1%#"
+ "call\t%a0, %1%#"
[(set_attr "type" "call")])
;; This is a call that wants a structure value.
@@ -8135,7 +7388,7 @@
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
- "call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
+ "call\t%a0, %1\n\tnop\n\tunimp\t%2"
[(set_attr "type" "call_no_delay_slot")
(set_attr "length" "3")])
@@ -8148,7 +7401,7 @@
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
- "call\\t%a0, %1\\n\\tnop\\n\\tunimp\\t%2"
+ "call\t%a0, %1\n\tnop\n\tunimp\t%2"
[(set_attr "type" "call_no_delay_slot")
(set_attr "length" "3")])
@@ -8161,7 +7414,7 @@
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
- "call\\t%a0, %1\\n\\tnop\\n\\tnop"
+ "call\t%a0, %1\n\tnop\n\tnop"
[(set_attr "type" "call_no_delay_slot")
(set_attr "length" "3")])
@@ -8173,7 +7426,7 @@
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
- "call\\t%a0, %1\\n\\tnop\\n\\tnop"
+ "call\t%a0, %1\n\tnop\n\tnop"
[(set_attr "type" "call_no_delay_slot")
(set_attr "length" "3")])
@@ -8186,7 +7439,6 @@
;; operand 2 is stack_size_rtx
;; operand 3 is next_arg_register
""
- "
{
rtx fn_rtx, nregs_rtx;
rtvec vec;
@@ -8213,7 +7465,7 @@
emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec));
DONE;
-}")
+})
(define_insn "*call_value_address_sp32"
[(set (match_operand 0 "" "=rf")
@@ -8222,7 +7474,7 @@
(clobber (reg:SI 15))]
;;- Do not use operand 2 for most machines.
"! TARGET_ARCH64"
- "call\\t%a1, %2%#"
+ "call\t%a1, %2%#"
[(set_attr "type" "call")])
(define_insn "*call_value_symbolic_sp32"
@@ -8232,7 +7484,7 @@
(clobber (reg:SI 15))]
;;- Do not use operand 2 for most machines.
"! TARGET_ARCH64"
- "call\\t%a1, %2%#"
+ "call\t%a1, %2%#"
[(set_attr "type" "call")])
(define_insn "*call_value_address_sp64"
@@ -8242,7 +7494,7 @@
(clobber (reg:DI 15))]
;;- Do not use operand 2 for most machines.
"TARGET_ARCH64"
- "call\\t%a1, %2%#"
+ "call\t%a1, %2%#"
[(set_attr "type" "call")])
(define_insn "*call_value_symbolic_sp64"
@@ -8252,7 +7504,7 @@
(clobber (reg:DI 15))]
;;- Do not use operand 2 for most machines.
"TARGET_ARCH64"
- "call\\t%a1, %2%#"
+ "call\t%a1, %2%#"
[(set_attr "type" "call")])
(define_expand "untyped_call"
@@ -8261,7 +7513,6 @@
(match_operand 1 "" "")
(match_operand 2 "" "")])]
""
- "
{
int i;
@@ -8282,7 +7533,7 @@
emit_insn (gen_blockage ());
DONE;
-}")
+})
;;- tail calls
(define_expand "sibcall"
@@ -8341,7 +7592,7 @@
;; all of memory. This blocks insns from being moved across this point.
(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] 0)]
+ [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
""
""
[(set_attr "length" "0")])
@@ -8352,7 +7603,6 @@
[(match_operand:BLK 0 "memory_operand" "")
(match_operand 1 "" "")]
""
- "
{
rtx valreg1 = gen_rtx_REG (DImode, 24);
rtx valreg2 = gen_rtx_REG (TARGET_ARCH64 ? TFmode : DFmode, 32);
@@ -8386,16 +7636,16 @@
expand_null_return ();
DONE;
-}")
+})
;; This is a bit of a hack. We're incrementing a fixed register (%i7),
;; and parts of the compiler don't want to believe that the add is needed.
(define_insn "update_return"
[(unspec:SI [(match_operand:SI 0 "register_operand" "r")
- (match_operand:SI 1 "register_operand" "r")] 1)]
+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_UPDATE_RETURN)]
"! TARGET_ARCH64"
- "cmp\\t%1, 0\;be,a\\t.+8\;add\\t%0, 4, %0"
+ "cmp\t%1, 0\;be,a\t.+8\;add\t%0, 4, %0"
[(set_attr "type" "multi")
(set_attr "length" "3")])
@@ -8412,13 +7662,13 @@
(define_insn "*branch_sp32"
[(set (pc) (match_operand:SI 0 "address_operand" "p"))]
"! TARGET_ARCH64"
- "jmp\\t%a0%#"
+ "jmp\t%a0%#"
[(set_attr "type" "uncond_branch")])
(define_insn "*branch_sp64"
[(set (pc) (match_operand:DI 0 "address_operand" "p"))]
"TARGET_ARCH64"
- "jmp\\t%a0%#"
+ "jmp\t%a0%#"
[(set_attr "type" "uncond_branch")])
;; ??? Doesn't work with -mflat.
@@ -8428,7 +7678,6 @@
(match_operand:SI 2 "general_operand" "")
(match_operand:SI 3 "" "")]
""
- "
{
#if 0
rtx chain = operands[0];
@@ -8482,41 +7731,41 @@
emit_jump_insn (gen_goto_handler_and_restore (labreg));
emit_barrier ();
DONE;
-}")
+})
;; Special trap insn to flush register windows.
(define_insn "flush_register_windows"
- [(unspec_volatile [(const_int 0)] 1)]
+ [(unspec_volatile [(const_int 0)] UNSPECV_FLUSHW)]
""
- "* return TARGET_V9 ? \"flushw\" : \"ta\\t3\";"
- [(set_attr "type" "misc")])
+ { return TARGET_V9 ? "flushw" : "ta\t3"; }
+ [(set_attr "type" "flushw")])
(define_insn "goto_handler_and_restore"
- [(unspec_volatile [(match_operand 0 "register_operand" "=r")] 2)]
+ [(unspec_volatile [(match_operand 0 "register_operand" "=r")] UNSPECV_GOTO)]
"GET_MODE (operands[0]) == Pmode"
- "jmp\\t%0+0\\n\\trestore"
+ "jmp\t%0+0\n\trestore"
[(set_attr "type" "multi")
(set_attr "length" "2")])
;;(define_insn "goto_handler_and_restore_v9"
;; [(unspec_volatile [(match_operand:SI 0 "register_operand" "=r,r")
;; (match_operand:SI 1 "register_operand" "=r,r")
-;; (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
+;; (match_operand:SI 2 "const_int_operand" "I,n")] UNSPECV_GOTO_V9)]
;; "TARGET_V9 && ! TARGET_ARCH64"
;; "@
-;; return\\t%0+0\\n\\tmov\\t%2, %Y1
-;; sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
+;; return\t%0+0\n\tmov\t%2, %Y1
+;; sethi\t%%hi(%2), %1\n\treturn\t%0+0\n\tor\t%Y1, %%lo(%2), %Y1"
;; [(set_attr "type" "multi")
;; (set_attr "length" "2,3")])
;;
;;(define_insn "*goto_handler_and_restore_v9_sp64"
;; [(unspec_volatile [(match_operand:DI 0 "register_operand" "=r,r")
;; (match_operand:DI 1 "register_operand" "=r,r")
-;; (match_operand:SI 2 "const_int_operand" "I,n")] 3)]
+;; (match_operand:SI 2 "const_int_operand" "I,n")] UNSPECV_GOTO_V9)]
;; "TARGET_V9 && TARGET_ARCH64"
;; "@
-;; return\\t%0+0\\n\\tmov\\t%2, %Y1
-;; sethi\\t%%hi(%2), %1\\n\\treturn\\t%0+0\\n\\tor\\t%Y1, %%lo(%2), %Y1"
+;; return\t%0+0\n\tmov\t%2, %Y1
+;; sethi\t%%hi(%2), %1\n\treturn\t%0+0\n\tor\t%Y1, %%lo(%2), %Y1"
;; [(set_attr "type" "multi")
;; (set_attr "length" "2,3")])
@@ -8526,47 +7775,42 @@
(define_expand "builtin_setjmp_setup"
[(match_operand 0 "register_operand" "r")]
""
- "
{
emit_insn (gen_do_builtin_setjmp_setup ());
DONE;
-}")
+})
(define_insn "do_builtin_setjmp_setup"
- [(unspec_volatile [(const_int 0)] 5)]
+ [(unspec_volatile [(const_int 0)] UNSPECV_SETJMP)]
""
- "*
{
- if (! current_function_calls_alloca || ! TARGET_V9 || TARGET_FLAT)
- return \"#\";
- fputs (\"\tflushw\n\", asm_out_file);
+ if (! current_function_calls_alloca)
+ return "";
+ if (! TARGET_V9 || TARGET_FLAT)
+ return "\tta\t3\n";
+ fputs ("\tflushw\n", asm_out_file);
if (flag_pic)
- fprintf (asm_out_file, \"\tst%c\t%%l7, [%%sp+%d]\n\",
+ fprintf (asm_out_file, "\tst%c\t%%l7, [%%sp+%d]\n",
TARGET_ARCH64 ? 'x' : 'w',
SPARC_STACK_BIAS + 7 * UNITS_PER_WORD);
- fprintf (asm_out_file, \"\tst%c\t%%fp, [%%sp+%d]\n\",
+ fprintf (asm_out_file, "\tst%c\t%%fp, [%%sp+%d]\n",
TARGET_ARCH64 ? 'x' : 'w',
SPARC_STACK_BIAS + 14 * UNITS_PER_WORD);
- fprintf (asm_out_file, \"\tst%c\t%%i7, [%%sp+%d]\n\",
+ fprintf (asm_out_file, "\tst%c\t%%i7, [%%sp+%d]\n",
TARGET_ARCH64 ? 'x' : 'w',
SPARC_STACK_BIAS + 15 * UNITS_PER_WORD);
- return \"\";
-}"
- [(set_attr "type" "misc")
- (set (attr "length") (if_then_else (eq_attr "pic" "true")
- (const_int 4)
- (const_int 3)))])
-
-(define_split
- [(unspec_volatile [(const_int 0)] 5)]
- "! current_function_calls_alloca || ! TARGET_V9 || TARGET_FLAT"
- [(const_int 0)]
- "
-{
- if (current_function_calls_alloca)
- emit_insn (gen_flush_register_windows ());
- DONE;
-}")
+ return "";
+}
+ [(set_attr "type" "multi")
+ (set (attr "length")
+ (cond [(eq_attr "current_function_calls_alloca" "false")
+ (const_int 0)
+ (eq_attr "flat" "true")
+ (const_int 1)
+ (eq_attr "isa" "!v9")
+ (const_int 1)
+ (eq_attr "pic" "true")
+ (const_int 4)] (const_int 3)))])
;; Pattern for use after a setjmp to store FP and the return register
;; into the stack area.
@@ -8574,28 +7818,25 @@
(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; }")
+ { 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; }")
+ { operands[0] = frame_pointer_rtx; })
;; Special pattern for the FLUSH instruction.
@@ -8605,16 +7846,16 @@
; it on SImode mem values.
(define_insn "flush"
- [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] 3)]
+ [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")] UNSPECV_FLUSH)]
""
- "* return TARGET_V9 ? \"flush\\t%f0\" : \"iflush\\t%f0\";"
- [(set_attr "type" "misc")])
+ { return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0"; }
+ [(set_attr "type" "iflush")])
(define_insn "flushdi"
- [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")] 3)]
+ [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")] UNSPECV_FLUSH)]
""
- "* return TARGET_V9 ? \"flush\\t%f0\" : \"iflush\\t%f0\";"
- [(set_attr "type" "misc")])
+ { return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0"; }
+ [(set_attr "type" "iflush")])
;; find first set.
@@ -8630,17 +7871,16 @@
(ffs:SI (match_operand:SI 1 "register_operand" "r")))
(clobber (match_scratch:SI 2 "=&r"))]
"TARGET_SPARCLITE || TARGET_SPARCLET"
- "*
{
- return \"sub\\t%%g0, %1, %0\;and\\t%0, %1, %0\;scan\\t%0, 0, %0\;mov\\t32, %2\;sub\\t%2, %0, %0\;sra\\t%0, 31, %2\;and\\t%2, 31, %2\;add\\t%2, %0, %0\";
-}"
+ return "sub\t%%g0, %1, %0\;and\t%0, %1, %0\;scan\t%0, 0, %0\;mov\t32, %2\;sub\t%2, %0, %0\;sra\t%0, 31, %2\;and\t%2, 31, %2\;add\t%2, %0, %0";
+}
[(set_attr "type" "multi")
(set_attr "length" "8")])
;; ??? This should be a define expand, so that the extra instruction have
;; a chance of being optimized away.
-;; Disabled because none of the UltraSparcs implement popc. The HAL R1
+;; Disabled because none of the UltraSPARCs implement popc. The HAL R1
;; does, but no one uses that and we don't have a switch for it.
;
;(define_insn "ffsdi2"
@@ -8648,7 +7888,7 @@
; (ffs:DI (match_operand:DI 1 "register_operand" "r")))
; (clobber (match_scratch:DI 2 "=&r"))]
; "TARGET_ARCH64"
-; "neg\\t%1, %2\;xnor\\t%1, %2, %2\;popc\\t%2, %0\;movzr\\t%1, 0, %0"
+; "neg\t%1, %2\;xnor\t%1, %2, %2\;popc\t%2, %0\;movzr\t%1, 0, %0"
; [(set_attr "type" "multi")
; (set_attr "length" "4")])
@@ -8669,7 +7909,7 @@
&& mems_ok_for_ldd_peep (operands[0], operands[1], NULL_RTX)"
[(set (match_dup 0)
(const_int 0))]
- "operands[0] = change_address (operands[0], DImode, NULL);")
+ "operands[0] = widen_memory_access (operands[0], DImode, 0);")
(define_peephole2
[(set (match_operand:SI 0 "memory_operand" "")
@@ -8680,7 +7920,7 @@
&& mems_ok_for_ldd_peep (operands[1], operands[0], NULL_RTX)"
[(set (match_dup 1)
(const_int 0))]
- "operands[1] = change_address (operands[1], DImode, NULL);")
+ "operands[1] = widen_memory_access (operands[1], DImode, 0);")
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
@@ -8691,7 +7931,7 @@
&& mems_ok_for_ldd_peep (operands[1], operands[3], operands[0])"
[(set (match_dup 0)
(match_dup 1))]
- "operands[1] = change_address (operands[1], DImode, NULL);
+ "operands[1] = widen_memory_access (operands[1], DImode, 0);
operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));")
(define_peephole2
@@ -8703,7 +7943,7 @@
&& mems_ok_for_ldd_peep (operands[0], operands[2], NULL_RTX)"
[(set (match_dup 0)
(match_dup 1))]
- "operands[0] = change_address (operands[0], DImode, NULL);
+ "operands[0] = widen_memory_access (operands[0], DImode, 0);
operands[1] = gen_rtx_REG (DImode, REGNO (operands[1]));")
(define_peephole2
@@ -8715,7 +7955,7 @@
&& mems_ok_for_ldd_peep (operands[1], operands[3], operands[0])"
[(set (match_dup 0)
(match_dup 1))]
- "operands[1] = change_address (operands[1], DFmode, NULL);
+ "operands[1] = widen_memory_access (operands[1], DFmode, 0);
operands[0] = gen_rtx_REG (DFmode, REGNO (operands[0]));")
(define_peephole2
@@ -8727,7 +7967,7 @@
&& mems_ok_for_ldd_peep (operands[0], operands[2], NULL_RTX)"
[(set (match_dup 0)
(match_dup 1))]
- "operands[0] = change_address (operands[0], DFmode, NULL);
+ "operands[0] = widen_memory_access (operands[0], DFmode, 0);
operands[1] = gen_rtx_REG (DFmode, REGNO (operands[1]));")
(define_peephole2
@@ -8739,7 +7979,7 @@
&& mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
[(set (match_dup 2)
(match_dup 3))]
- "operands[3] = change_address (operands[3], DImode, NULL);
+ "operands[3] = widen_memory_access (operands[3], DImode, 0);
operands[2] = gen_rtx_REG (DImode, REGNO (operands[2]));")
(define_peephole2
@@ -8751,7 +7991,7 @@
&& mems_ok_for_ldd_peep (operands[2], operands[0], NULL_RTX)"
[(set (match_dup 2)
(match_dup 3))]
- "operands[2] = change_address (operands[2], DImode, NULL);
+ "operands[2] = widen_memory_access (operands[2], DImode, 0);
operands[3] = gen_rtx_REG (DImode, REGNO (operands[3]));
")
@@ -8764,7 +8004,7 @@
&& mems_ok_for_ldd_peep (operands[3], operands[1], operands[0])"
[(set (match_dup 2)
(match_dup 3))]
- "operands[3] = change_address (operands[3], DFmode, NULL);
+ "operands[3] = widen_memory_access (operands[3], DFmode, 0);
operands[2] = gen_rtx_REG (DFmode, REGNO (operands[2]));")
(define_peephole2
@@ -8776,7 +8016,7 @@
&& mems_ok_for_ldd_peep (operands[2], operands[0], NULL_RTX)"
[(set (match_dup 2)
(match_dup 3))]
- "operands[2] = change_address (operands[2], DFmode, NULL);
+ "operands[2] = widen_memory_access (operands[2], DFmode, 0);
operands[3] = gen_rtx_REG (DFmode, REGNO (operands[3]));")
;; Optimize the case of following a reg-reg move with a test
@@ -8822,16 +8062,15 @@
(match_operand:QI 1 "arith_operand" "rI"))
(return)]
"sparc_emitting_epilogue"
- "*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
- return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
+ return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
|| IN_OR_GLOBAL_P (operands[1])))
- return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
+ return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
else
- return \"ret\\n\\trestore %%g0, %1, %Y0\";
-}"
+ return "ret\n\trestore %%g0, %1, %Y0";
+}
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -8840,16 +8079,15 @@
(match_operand:HI 1 "arith_operand" "rI"))
(return)]
"sparc_emitting_epilogue"
- "*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
- return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
+ return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
|| IN_OR_GLOBAL_P (operands[1])))
- return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
+ return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
else
- return \"ret\;restore %%g0, %1, %Y0\";
-}"
+ return "ret\;restore %%g0, %1, %Y0";
+}
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -8858,16 +8096,15 @@
(match_operand:SI 1 "arith_operand" "rI"))
(return)]
"sparc_emitting_epilogue"
- "*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
- return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
+ return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
|| IN_OR_GLOBAL_P (operands[1])))
- return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
+ return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
else
- return \"ret\;restore %%g0, %1, %Y0\";
-}"
+ return "ret\;restore %%g0, %1, %Y0";
+}
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -8876,15 +8113,14 @@
(match_operand:SF 1 "register_operand" "r"))
(return)]
"sparc_emitting_epilogue"
- "*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
- return \"jmp\\t%%i7+12\\n\\trestore %%g0, %1, %Y0\";
+ return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
- return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
+ return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
else
- return \"ret\;restore %%g0, %1, %Y0\";
-}"
+ return "ret\;restore %%g0, %1, %Y0";
+}
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -8893,13 +8129,12 @@
(match_operand:DF 1 "register_operand" "r"))
(return)]
"sparc_emitting_epilogue && TARGET_ARCH64"
- "*
{
if (IN_OR_GLOBAL_P (operands[1]))
- return \"return\\t%%i7+8\\n\\tmov\\t%Y1, %Y0\";
+ return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
else
- return \"ret\;restore %%g0, %1, %Y0\";
-}"
+ return "ret\;restore %%g0, %1, %Y0";
+}
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -8909,18 +8144,17 @@
(match_operand:SI 2 "arith_operand" "rI")))
(return)]
"sparc_emitting_epilogue"
- "*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
- return \"jmp\\t%%i7+12\\n\\trestore %r1, %2, %Y0\";
+ return "jmp\t%%i7+12\n\trestore %r1, %2, %Y0";
/* If operands are global or in registers, can use return */
else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1])
&& (GET_CODE (operands[2]) == CONST_INT
|| IN_OR_GLOBAL_P (operands[2])))
- return \"return\\t%%i7+8\\n\\tadd\\t%Y1, %Y2, %Y0\";
+ return "return\t%%i7+8\n\tadd\t%Y1, %Y2, %Y0";
else
- return \"ret\;restore %r1, %2, %Y0\";
-}"
+ return "ret\;restore %r1, %2, %Y0";
+}
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -8930,16 +8164,15 @@
(match_operand:SI 2 "immediate_operand" "in")))
(return)]
"sparc_emitting_epilogue && ! TARGET_CM_MEDMID"
- "*
{
if (! TARGET_ARCH64 && current_function_returns_struct)
- return \"jmp\\t%%i7+12\\n\\trestore %r1, %%lo(%a2), %Y0\";
+ return "jmp\t%%i7+12\n\trestore %r1, %%lo(%a2), %Y0";
/* If operands are global or in registers, can use return */
else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
- return \"return\\t%%i7+8\\n\\tor\\t%Y1, %%lo(%a2), %Y0\";
+ return "return\t%%i7+8\n\tor\t%Y1, %%lo(%a2), %Y0";
else
- return \"ret\;restore %r1, %%lo(%a2), %Y0\";
-}"
+ return "ret\;restore %r1, %%lo(%a2), %Y0";
+}
[(set_attr "type" "multi")
(set_attr "length" "2")])
@@ -8977,14 +8210,11 @@
(match_operand:SF 0 "register_operand" "f"))
(return)]
"sparc_emitting_epilogue"
- "ret\;fmovs\\t%0, %%f0"
+ "ret\;fmovs\t%0, %%f0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
;; Now peepholes to do a call followed by a jump.
-;; Do not match this on V9 and later processors, which have a call-return
-;; stack as this corrupts it and causes the code to run slower not faster.
-;; There are not TARGET_ARCH64 patterns because that implies TARGET_V9.
(define_peephole
[(parallel [(set (match_operand 0 "" "")
@@ -8992,20 +8222,22 @@
(match_operand 2 "" "")))
(clobber (reg:SI 15))])
(set (pc) (label_ref (match_operand 3 "" "")))]
- "! TARGET_V9
- && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
- && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))"
- "call\\t%a1, %2\\n\\tadd\\t%%o7, (%l3-.-4), %%o7")
+ "short_branch (INSN_UID (insn), INSN_UID (operands[3]))
+ && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))
+ && sparc_cpu != PROCESSOR_ULTRASPARC
+ && sparc_cpu != PROCESSOR_ULTRASPARC3"
+ "call\t%a1, %2\n\tadd\t%%o7, (%l3-.-4), %%o7")
(define_peephole
[(parallel [(call (mem:SI (match_operand:SI 0 "call_operand_address" "ps"))
(match_operand 1 "" ""))
(clobber (reg:SI 15))])
(set (pc) (label_ref (match_operand 2 "" "")))]
- "! TARGET_V9
- && short_branch (INSN_UID (insn), INSN_UID (operands[2]))
- && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))"
- "call\\t%a0, %1\\n\\tadd\\t%%o7, (%l2-.-4), %%o7")
+ "short_branch (INSN_UID (insn), INSN_UID (operands[2]))
+ && (USING_SJLJ_EXCEPTIONS || ! can_throw_internal (ins1))
+ && sparc_cpu != PROCESSOR_ULTRASPARC
+ && sparc_cpu != PROCESSOR_ULTRASPARC3"
+ "call\t%a0, %1\n\tadd\t%%o7, (%l2-.-4), %%o7")
;; ??? UltraSPARC-III note: A memory operation loading into the floating point register
;; ??? file, if it hits the prefetch cache, has a chance to dual-issue with other memory
@@ -9016,14 +8248,13 @@
(match_operand 1 "const_int_operand" "")
(match_operand 2 "const_int_operand" "")]
"TARGET_V9"
- "
{
if (TARGET_ARCH64)
emit_insn (gen_prefetch_64 (operands[0], operands[1], operands[2]));
else
emit_insn (gen_prefetch_32 (operands[0], operands[1], operands[2]));
DONE;
-}")
+})
(define_insn "prefetch_64"
[(prefetch (match_operand:DI 0 "address_operand" "p")
@@ -9033,12 +8264,12 @@
{
static const char * const prefetch_instr[2][2] = {
{
- "prefetch\\t[%a0], 1", /* no locality: prefetch for one read */
- "prefetch\\t[%a0], 0", /* medium to high locality: prefetch for several reads */
+ "prefetch\t[%a0], 1", /* no locality: prefetch for one read */
+ "prefetch\t[%a0], 0", /* medium to high locality: prefetch for several reads */
},
{
- "prefetch\\t[%a0], 3", /* no locality: prefetch for one write */
- "prefetch\\t[%a0], 2", /* medium to high locality: prefetch for several writes */
+ "prefetch\t[%a0], 3", /* no locality: prefetch for one write */
+ "prefetch\t[%a0], 2", /* medium to high locality: prefetch for several writes */
}
};
int read_or_write = INTVAL (operands[1]);
@@ -9060,12 +8291,12 @@
{
static const char * const prefetch_instr[2][2] = {
{
- "prefetch\\t[%a0], 1", /* no locality: prefetch for one read */
- "prefetch\\t[%a0], 0", /* medium to high locality: prefetch for several reads */
+ "prefetch\t[%a0], 1", /* no locality: prefetch for one read */
+ "prefetch\t[%a0], 0", /* medium to high locality: prefetch for several reads */
},
{
- "prefetch\\t[%a0], 3", /* no locality: prefetch for one write */
- "prefetch\\t[%a0], 2", /* medium to high locality: prefetch for several writes */
+ "prefetch\t[%a0], 3", /* no locality: prefetch for one write */
+ "prefetch\t[%a0], 2", /* medium to high locality: prefetch for several writes */
}
};
int read_or_write = INTVAL (operands[1]);
@@ -9082,11 +8313,10 @@
(define_expand "prologue"
[(const_int 1)]
"flag_pic && current_function_uses_pic_offset_table"
- "
{
load_pic_register ();
DONE;
-}")
+})
;; We need to reload %l7 for -mflat -fpic,
;; otherwise %l7 should be preserved simply
@@ -9094,27 +8324,25 @@
(define_expand "exception_receiver"
[(const_int 0)]
"TARGET_FLAT && flag_pic"
- "
{
load_pic_register ();
DONE;
-}")
+})
;; Likewise
(define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0 "" ""))]
"TARGET_FLAT && flag_pic"
- "
{
load_pic_register ();
DONE;
-}")
+})
(define_insn "trap"
[(trap_if (const_int 1) (const_int 5))]
""
- "ta\\t5"
- [(set_attr "type" "misc")])
+ "ta\t5"
+ [(set_attr "type" "trap")])
(define_expand "conditional_trap"
[(trap_if (match_operator 0 "noov_compare_op"
@@ -9129,12 +8357,12 @@
[(trap_if (match_operator 0 "noov_compare_op" [(reg:CC 100) (const_int 0)])
(match_operand:SI 1 "arith_operand" "rM"))]
""
- "t%C0\\t%1"
- [(set_attr "type" "misc")])
+ "t%C0\t%1"
+ [(set_attr "type" "trap")])
(define_insn ""
[(trap_if (match_operator 0 "noov_compare_op" [(reg:CCX 100) (const_int 0)])
(match_operand:SI 1 "arith_operand" "rM"))]
"TARGET_V9"
- "t%C0\\t%%xcc, %1"
- [(set_attr "type" "misc")])
+ "t%C0\t%%xcc, %1"
+ [(set_attr "type" "trap")])
diff --git a/contrib/gcc/config/sparc/sparclet.md b/contrib/gcc/config/sparc/sparclet.md
new file mode 100644
index 0000000..080090c
--- /dev/null
+++ b/contrib/gcc/config/sparc/sparclet.md
@@ -0,0 +1,44 @@
+;; Scheduling description for SPARClet.
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU CC.
+;;
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; The SPARClet is a single-issue processor.
+
+(define_automaton "sparclet")
+
+(define_cpu_unit "sl_load0,sl_load1,sl_load2,sl_load3" "sparclet")
+(define_cpu_unit "sl_store,sl_imul" "sparclet")
+
+(define_reservation "sl_load_any" "(sl_load0 | sl_load1 | sl_load2 | sl_load3)")
+(define_reservation "sl_load_all" "(sl_load0 + sl_load1 + sl_load2 + sl_load3)")
+
+(define_insn_reservation "sl_ld" 3
+ (and (eq_attr "cpu" "tsc701")
+ (eq_attr "type" "load,sload"))
+ "sl_load_any, sl_load_any, sl_load_any")
+
+(define_insn_reservation "sl_st" 3
+ (and (eq_attr "cpu" "tsc701")
+ (eq_attr "type" "store"))
+ "(sl_store+sl_load_all)*3")
+
+(define_insn_reservation "sl_imul" 5
+ (and (eq_attr "cpu" "tsc701")
+ (eq_attr "type" "imul"))
+ "sl_imul*5")
diff --git a/contrib/gcc/config/sparc/sunos4.h b/contrib/gcc/config/sparc/sunos4.h
index e5b2dcc..513251c 100644
--- a/contrib/gcc/config/sparc/sunos4.h
+++ b/contrib/gcc/config/sparc/sunos4.h
@@ -41,6 +41,8 @@ Boston, MA 02111-1307, USA. */
/* SunOS has on_exit instead of atexit. */
/* The man page says it returns int. */
+#ifdef IN_LIBGCC2
extern int on_exit PARAMS ((void *, void *));
+#endif
#define ON_EXIT(FUNC) on_exit ((FUNC), 0)
#define NEED_ATEXIT
diff --git a/contrib/gcc/config/sparc/supersparc.md b/contrib/gcc/config/sparc/supersparc.md
new file mode 100644
index 0000000..ea32886
--- /dev/null
+++ b/contrib/gcc/config/sparc/supersparc.md
@@ -0,0 +1,93 @@
+;; Scheduling description for SuperSPARC.
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU CC.
+;;
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; The SuperSPARC is a tri-issue, which was considered quite parallel
+;; at the time it was released. Much like UltraSPARC-I and UltraSPARC-II
+;; there are two integer units but only one of them may take shifts.
+;;
+;; ??? If SuperSPARC has the same slotting rules as ultrasparc for these
+;; ??? shifts, we should model that.
+
+(define_automaton "supersparc_0,supersparc_1")
+
+(define_cpu_unit "ss_memory, ss_shift, ss_iwport0, ss_iwport1" "supersparc_0")
+(define_cpu_unit "ss_fpalu" "supersparc_0")
+(define_cpu_unit "ss_fpmds" "supersparc_1")
+
+(define_reservation "ss_iwport" "(ss_iwport0 | ss_iwport1)")
+
+(define_insn_reservation "ss_iuload" 1
+ (and (eq_attr "cpu" "supersparc")
+ (eq_attr "type" "load,sload"))
+ "ss_memory")
+
+;; Ok, fpu loads deliver the result in zero cycles. But we
+;; have to show the ss_memory reservation somehow, thus...
+(define_insn_reservation "ss_fpload" 0
+ (and (eq_attr "cpu" "supersparc")
+ (eq_attr "type" "fpload"))
+ "ss_memory")
+
+(define_bypass 0 "ss_fpload" "ss_fp_alu,ss_fp_mult,ss_fp_divs,ss_fp_divd,ss_fp_sqrt")
+
+(define_insn_reservation "ss_store" 1
+ (and (eq_attr "cpu" "supersparc")
+ (eq_attr "type" "store,fpstore"))
+ "ss_memory")
+
+(define_insn_reservation "ss_ialu_shift" 1
+ (and (eq_attr "cpu" "supersparc")
+ (eq_attr "type" "shift"))
+ "ss_shift + ss_iwport")
+
+(define_insn_reservation "ss_ialu_any" 1
+ (and (eq_attr "cpu" "supersparc")
+ (eq_attr "type" "load,sload,store,shift,ialu"))
+ "ss_iwport")
+
+(define_insn_reservation "ss_fp_alu" 3
+ (and (eq_attr "cpu" "supersparc")
+ (eq_attr "type" "fp,fpmove,fpcmp"))
+ "ss_fpalu, nothing*2")
+
+(define_insn_reservation "ss_fp_mult" 3
+ (and (eq_attr "cpu" "supersparc")
+ (eq_attr "type" "fpmul"))
+ "ss_fpmds, nothing*2")
+
+(define_insn_reservation "ss_fp_divs" 6
+ (and (eq_attr "cpu" "supersparc")
+ (eq_attr "type" "fpdivs"))
+ "ss_fpmds*4, nothing*2")
+
+(define_insn_reservation "ss_fp_divd" 9
+ (and (eq_attr "cpu" "supersparc")
+ (eq_attr "type" "fpdivd"))
+ "ss_fpmds*7, nothing*2")
+
+(define_insn_reservation "ss_fp_sqrt" 12
+ (and (eq_attr "cpu" "supersparc")
+ (eq_attr "type" "fpsqrts,fpsqrtd"))
+ "ss_fpmds*10, nothing*2")
+
+(define_insn_reservation "ss_imul" 4
+ (and (eq_attr "cpu" "supersparc")
+ (eq_attr "type" "imul"))
+ "ss_fpmds*4")
diff --git a/contrib/gcc/config/sparc/sysv4.h b/contrib/gcc/config/sparc/sysv4.h
index a4c7f91..f304d6b 100644
--- a/contrib/gcc/config/sparc/sysv4.h
+++ b/contrib/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, 1996, 1997, 1998, 2000
+/* Target definitions for GNU compiler for SPARC running System V.4
+ Copyright (C) 1991, 1992, 1995, 1996, 1997, 1998, 2000, 2002
Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@monkeys.com).
@@ -36,11 +36,11 @@ Boston, MA 02111-1307, USA. */
/* Undefined some symbols which are defined in "svr4.h" but which are
appropriate only for typical svr4 systems, but not for the specific
- case of svr4 running on a Sparc. */
+ case of svr4 running on a SPARC. */
#undef INIT_SECTION_ASM_OP
#undef FINI_SECTION_ASM_OP
-#undef CONST_SECTION_ASM_OP
+#undef READONLY_DATA_SECTION_ASM_OP
#undef TYPE_OPERAND_FMT
#undef PUSHSECTION_FORMAT
#undef STRING_ASM_OP
@@ -49,7 +49,7 @@ Boston, MA 02111-1307, USA. */
#undef SET_ASM_OP /* Has no equivalent. See ASM_OUTPUT_DEF below. */
/* Provide a set of pre-definitions and pre-assertions appropriate for
- the Sparc running svr4. __svr4__ is our extension. */
+ the SPARC running svr4. __svr4__ is our extension. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES \
@@ -68,20 +68,10 @@ Boston, MA 02111-1307, USA. */
"%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
%{fpic:-K PIC} %{fPIC:-K PIC} %(asm_cpu)"
-/* Must use data section for relocatable constants when pic. */
-#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE,RTX,ALIGN) \
-{ \
- if (flag_pic && symbolic_operand ((RTX), (MODE))) \
- data_section (); \
- else \
- const_section (); \
-}
-
-/* Define the names of various pseudo-op used by the Sparc/svr4 assembler.
+/* Define the names of various pseudo-op used by the SPARC/svr4 assembler.
Note that many of these are different from the typical pseudo-ops used
by most svr4 assemblers. That is probably due to a (misguided?) attempt
- to keep the Sparc/svr4 assembler somewhat compatible with the Sparc/SunOS
+ to keep the SPARC/svr4 assembler somewhat compatible with the SPARC/SunOS
assembler. */
#define STRING_ASM_OP "\t.asciz\t"
@@ -91,12 +81,12 @@ Boston, MA 02111-1307, USA. */
#define POPSECTION_ASM_OP "\t.popsection"
/* This is the format used to print the second operand of a .type pseudo-op
- for the Sparc/svr4 assembler. */
+ for the SPARC/svr4 assembler. */
#define TYPE_OPERAND_FMT "#%s"
/* This is the format used to print a .pushsection pseudo-op (and its operand)
- for the Sparc/svr4 assembler. */
+ for the SPARC/svr4 assembler. */
#define PUSHSECTION_FORMAT "%s\"%s\"\n"
@@ -118,9 +108,9 @@ do { ASM_OUTPUT_ALIGN ((FILE), Pmode == SImode ? 2 : 3); \
fprintf (FILE, "\n"); \
} while (0)
-/* Define how the Sparc registers should be numbered for Dwarf output.
+/* Define how the SPARC registers should be numbered for Dwarf output.
The numbering provided here should be compatible with the native
- svr4 SDB debugger in the Sparc/svr4 reference port. The numbering
+ svr4 SDB debugger in the SPARC/svr4 reference port. The numbering
is as follows:
Assembly name gcc internal regno Dwarf regno
@@ -143,7 +133,7 @@ do { ASM_OUTPUT_ALIGN ((FILE), Pmode == SImode ? 2 : 3); \
#define TEXT_SECTION_ASM_OP "\t.section\t\".text\""
#define DATA_SECTION_ASM_OP "\t.section\t\".data\""
#define BSS_SECTION_ASM_OP "\t.section\t\".bss\""
-#define CONST_SECTION_ASM_OP "\t.section\t\".rodata\""
+#define READONLY_DATA_SECTION_ASM_OP "\t.section\t\".rodata\""
#define INIT_SECTION_ASM_OP "\t.section\t\".init\""
#define FINI_SECTION_ASM_OP "\t.section\t\".fini\""
diff --git a/contrib/gcc/config/sparc/ultra1_2.md b/contrib/gcc/config/sparc/ultra1_2.md
new file mode 100644
index 0000000..2194be7
--- /dev/null
+++ b/contrib/gcc/config/sparc/ultra1_2.md
@@ -0,0 +1,252 @@
+;; Scheduling description for UltraSPARC-I/II.
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU CC.
+;;
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; UltraSPARC-I and II are quad-issue processors. Interesting features
+;; to note:
+;;
+;; - Buffered loads, they can queue waiting for the actual data until
+;; an instruction actually tries to reference the destination register
+;; as an input
+;; - Two integer units. Only one of them can do shifts, and the other
+;; is the only one which may do condition code setting instructions.
+;; Complicating things further, a shift may go only into the first
+;; slot in a dispatched group. And if you have a non-condition code
+;; setting instruction and one that does set the condition codes. The
+;; former must be issued first in order for both of them to issue.
+;; - Stores can issue before the value being stored is available. As long
+;; as the input data becomes ready before the store is to move out of the
+;; store buffer, it will not cause a stall.
+;; - Branches may issue in the same cycle as an instruction setting the
+;; condition codes being tested by that branch. This does not apply
+;; to floating point, only integer.
+
+(define_automaton "ultrasparc_0,ultrasparc_1")
+
+(define_cpu_unit "us1_fdivider,us1_fpm" "ultrasparc_0");
+(define_cpu_unit "us1_fpa,us1_load_writeback" "ultrasparc_1")
+(define_cpu_unit "us1_fps_0,us1_fps_1,us1_fpd_0,us1_fpd_1" "ultrasparc_1")
+(define_cpu_unit "us1_slot0,us1_slot1,us1_slot2,us1_slot3" "ultrasparc_1")
+(define_cpu_unit "us1_ieu0,us1_ieu1,us1_cti,us1_lsu" "ultrasparc_1")
+
+(define_reservation "us1_slot012" "(us1_slot0 | us1_slot1 | us1_slot2)")
+(define_reservation "us1_slotany" "(us1_slot0 | us1_slot1 | us1_slot2 | us1_slot3)")
+(define_reservation "us1_single_issue" "us1_slot0 + us1_slot1 + us1_slot2 + us1_slot3")
+
+(define_reservation "us1_fp_single" "(us1_fps_0 | us1_fps_1)")
+(define_reservation "us1_fp_double" "(us1_fpd_0 | us1_fpd_1)")
+
+;; This is a simplified representation of the issue at hand.
+;; For most cases, going from one FP precision type insn to another
+;; just breaks up the insn group. However for some cases, such
+;; a situation causes the second insn to stall 2 more cycles.
+(exclusion_set "us1_fps_0,us1_fps_1" "us1_fpd_0,us1_fpd_1")
+
+;; If we have to schedule an ieu1 specific instruction and we want
+;; to reserve the ieu0 unit as well, we must reserve it first. So for
+;; example we could not schedule this sequence:
+;; COMPARE IEU1
+;; IALU IEU0
+;; but we could schedule them together like this:
+;; IALU IEU0
+;; COMPARE IEU1
+;; This basically requires that ieu0 is reserved before ieu1 when
+;; it is required that both be reserved.
+(absence_set "us1_ieu0" "us1_ieu1")
+
+;; This defines the slotting order. Most IEU instructions can only
+;; execute in the first three slots, FPU and branches can go into
+;; any slot. We represent instructions which "break the group"
+;; as requiring reservation of us1_slot0.
+(absence_set "us1_slot0" "us1_slot1,us1_slot2,us1_slot3")
+(absence_set "us1_slot1" "us1_slot2,us1_slot3")
+(absence_set "us1_slot2" "us1_slot3")
+
+(define_insn_reservation "us1_single" 1
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "multi,flushw,iflush,trap"))
+ "us1_single_issue")
+
+(define_insn_reservation "us1_simple_ieuN" 1
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "ialu"))
+ "(us1_ieu0 | us1_ieu1) + us1_slot012")
+
+(define_insn_reservation "us1_simple_ieu0" 1
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "shift"))
+ "us1_ieu0 + us1_slot012")
+
+(define_insn_reservation "us1_simple_ieu1" 1
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "compare"))
+ "us1_ieu1 + us1_slot012")
+
+(define_insn_reservation "us1_ialuX" 1
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "ialuX"))
+ "us1_single_issue")
+
+(define_insn_reservation "us1_cmove" 2
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "cmove"))
+ "us1_single_issue, nothing")
+
+(define_insn_reservation "us1_imul" 1
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "imul"))
+ "us1_single_issue")
+
+(define_insn_reservation "us1_idiv" 1
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "idiv"))
+ "us1_single_issue")
+
+;; For loads, the "delayed return mode" behavior of the chip
+;; is represented using the us1_load_writeback resource.
+(define_insn_reservation "us1_load" 2
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "load,fpload"))
+ "us1_lsu + us1_slot012, us1_load_writeback")
+
+(define_insn_reservation "us1_load_signed" 3
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "sload"))
+ "us1_lsu + us1_slot012, nothing, us1_load_writeback")
+
+(define_insn_reservation "us1_store" 1
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "store,fpstore"))
+ "us1_lsu + us1_slot012")
+
+(define_insn_reservation "us1_branch" 1
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "branch"))
+ "us1_cti + us1_slotany")
+
+(define_insn_reservation "us1_call_jmpl" 1
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "call,sibcall,call_no_delay_slot,uncond_branch"))
+ "us1_cti + us1_ieu1 + us1_slot0")
+
+(define_insn_reservation "us1_fmov_single" 1
+ (and (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fpmove"))
+ (eq_attr "fptype" "single"))
+ "us1_fpa + us1_fp_single + us1_slotany")
+
+(define_insn_reservation "us1_fmov_double" 1
+ (and (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fpmove"))
+ (eq_attr "fptype" "double"))
+ "us1_fpa + us1_fp_double + us1_slotany")
+
+(define_insn_reservation "us1_fcmov_single" 2
+ (and (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fpcmove,fpcrmove"))
+ (eq_attr "fptype" "single"))
+ "us1_fpa + us1_fp_single + us1_slotany, nothing")
+
+(define_insn_reservation "us1_fcmov_double" 2
+ (and (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fpcmove,fpcrmove"))
+ (eq_attr "fptype" "double"))
+ "us1_fpa + us1_fp_double + us1_slotany, nothing")
+
+(define_insn_reservation "us1_faddsub_single" 4
+ (and (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fp"))
+ (eq_attr "fptype" "single"))
+ "us1_fpa + us1_fp_single + us1_slotany, nothing*3")
+
+(define_insn_reservation "us1_faddsub_double" 4
+ (and (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fp"))
+ (eq_attr "fptype" "double"))
+ "us1_fpa + us1_fp_double + us1_slotany, nothing*3")
+
+(define_insn_reservation "us1_fpcmp_single" 1
+ (and (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fpcmp"))
+ (eq_attr "fptype" "single"))
+ "us1_fpa + us1_fp_single + us1_slotany")
+
+(define_insn_reservation "us1_fpcmp_double" 1
+ (and (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fpcmp"))
+ (eq_attr "fptype" "double"))
+ "us1_fpa + us1_fp_double + us1_slotany")
+
+(define_insn_reservation "us1_fmult_single" 4
+ (and (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fpmul"))
+ (eq_attr "fptype" "single"))
+ "us1_fpm + us1_fp_single + us1_slotany, nothing*3")
+
+(define_insn_reservation "us1_fmult_double" 4
+ (and (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fpmul"))
+ (eq_attr "fptype" "double"))
+ "us1_fpm + us1_fp_double + us1_slotany, nothing*3")
+
+;; This is actually in theory dangerous, because it is possible
+;; for the chip to prematurely dispatch the dependent instruction
+;; in the G stage, resulting in a 9 cycle stall. However I have never
+;; been able to trigger this case myself even with hand written code,
+;; so it must require some rare complicated pipeline state.
+(define_bypass 3
+ "us1_faddsub_single,us1_faddsub_double,us1_fmult_single,us1_fmult_double"
+ "us1_faddsub_single,us1_faddsub_double,us1_fmult_single,us1_fmult_double")
+
+;; Floating point divide and square root use the multiplier unit
+;; for final rounding 3 cycles before the divide/sqrt is complete.
+
+(define_insn_reservation "us1_fdivs"
+ 13
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fpdivs,fpsqrts"))
+ "(us1_fpm + us1_fdivider + us1_slot0), us1_fdivider*8, (us1_fpm + us1_fdivider), us1_fdivider*2"
+ )
+
+(define_bypass
+ 12
+ "us1_fdivs"
+ "us1_faddsub_single,us1_faddsub_double,us1_fmult_single,us1_fmult_double")
+
+(define_insn_reservation "us1_fdivd"
+ 23
+ (and (eq_attr "cpu" "ultrasparc")
+ (eq_attr "type" "fpdivd,fpsqrtd"))
+ "(us1_fpm + us1_fdivider + us1_slot0), us1_fdivider*18, (us1_fpm + us1_fdivider), us1_fdivider*2"
+ )
+(define_bypass
+ 22
+ "us1_fdivd"
+ "us1_faddsub_single,us1_faddsub_double,us1_fmult_single,us1_fmult_double")
+
+;; Any store may multi issue with the insn creating the source
+;; data as long as that creating insn is not an FPU div/sqrt.
+;; We need a special guard function because this bypass does
+;; not apply to the address inputs of the store.
+(define_bypass 0 "us1_simple_ieuN,us1_simple_ieu1,us1_simple_ieu0,us1_faddsub_single,us1_faddsub_double,us1_fmov_single,us1_fmov_double,us1_fcmov_single,us1_fcmov_double,us1_fmult_single,us1_fmult_double" "us1_store"
+ "store_data_bypass_p")
+
+;; An integer branch may execute in the same cycle as the compare
+;; creating the condition codes.
+(define_bypass 0 "us1_simple_ieu1" "us1_branch")
diff --git a/contrib/gcc/config/sparc/ultra3.md b/contrib/gcc/config/sparc/ultra3.md
new file mode 100644
index 0000000..cebc9f2
--- /dev/null
+++ b/contrib/gcc/config/sparc/ultra3.md
@@ -0,0 +1,169 @@
+;; Scheduling description for UltraSPARC-III.
+;; Copyright (C) 2002 Free Software Foundation, Inc.
+;;
+;; This file is part of GNU CC.
+;;
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; UltraSPARC-III is a quad-issue processor.
+;;
+;; It is also a much simpler beast than Ultra-I/II, no silly
+;; slotting rules and both integer units are fully symmetric.
+;; It does still have single-issue instructions though.
+
+(define_automaton "ultrasparc3_0,ultrasparc3_1")
+
+(define_cpu_unit "us3_ms,us3_br,us3_fpm" "ultrasparc3_0")
+(define_cpu_unit "us3_a0,us3_a1,us3_slot0,\
+ us3_slot1,us3_slot2,us3_slot3,us3_fpa" "ultrasparc3_1")
+(define_cpu_unit "us3_load_writeback" "ultrasparc3_1")
+
+(define_reservation "us3_slotany" "(us3_slot0 | us3_slot1 | us3_slot2 | us3_slot3)")
+(define_reservation "us3_single_issue" "us3_slot0 + us3_slot1 + us3_slot2 + us3_slot3")
+(define_reservation "us3_ax" "(us3_a0 | us3_a1)")
+
+(define_insn_reservation "us3_single" 1
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "multi,flushw,iflush,trap"))
+ "us3_single_issue")
+
+(define_insn_reservation "us3_integer" 1
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "ialu,shift,compare"))
+ "us3_ax + us3_slotany")
+
+(define_insn_reservation "us3_ialuX" 5
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "ialu,shift,compare"))
+ "us3_single_issue*4, nothing")
+
+(define_insn_reservation "us3_cmove" 2
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "cmove"))
+ "us3_ms + us3_br + us3_slotany, nothing")
+
+;; ??? Not entirely accurate.
+;; ??? It can run from 6 to 9 cycles. The first cycle the MS pipe
+;; ??? is needed, and the instruction group is broken right after
+;; ??? the imul. Then 'helper' instructions are generated to perform
+;; ??? each further stage of the multiplication, each such 'helper' is
+;; ??? single group. So, the reservation aspect is represented accurately
+;; ??? here, but the variable cycles are not.
+;; ??? Currently I have no idea how to determine the variability, but once
+;; ??? known we can simply add a define_bypass or similar to model it.
+(define_insn_reservation "us3_imul" 7
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "imul"))
+ "us3_ms + us3_slotany, us3_single_issue*4, nothing*2")
+
+(define_insn_reservation "us3_idiv" 72
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "idiv"))
+ "us3_ms + us3_slotany, us3_single_issue*69, nothing*2")
+
+;; UltraSPARC-III has a similar load delay as UltraSPARC-I/II except
+;; that all loads except 32-bit/64-bit unsigned loads take the extra
+;; delay for sign/zero extension.
+(define_insn_reservation "us3_2cycle_load" 2
+ (and (eq_attr "cpu" "ultrasparc3")
+ (and (eq_attr "type" "load,fpload")
+ (eq_attr "us3load_type" "2cycle")))
+ "us3_ms + us3_slotany, us3_load_writeback")
+
+(define_insn_reservation "us3_load_delayed" 3
+ (and (eq_attr "cpu" "ultrasparc3")
+ (and (eq_attr "type" "load,sload")
+ (eq_attr "us3load_type" "3cycle")))
+ "us3_ms + us3_slotany, nothing, us3_load_writeback")
+
+(define_insn_reservation "us3_store" 1
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "store,fpstore"))
+ "us3_ms + us3_slotany")
+
+(define_insn_reservation "us3_branch" 1
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "branch"))
+ "us3_br + us3_slotany")
+
+(define_insn_reservation "us3_call_jmpl" 1
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "call,sibcall,call_no_delay_slot,uncond_branch"))
+ "us3_br + us3_ms + us3_slotany")
+
+(define_insn_reservation "us3_fmov" 3
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "fpmove"))
+ "us3_fpa + us3_slotany, nothing*2")
+
+(define_insn_reservation "us3_fcmov" 3
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "fpcmove"))
+ "us3_fpa + us3_br + us3_slotany, nothing*2")
+
+(define_insn_reservation "us3_fcrmov" 3
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "fpcrmove"))
+ "us3_fpa + us3_ms + us3_slotany, nothing*2")
+
+(define_insn_reservation "us3_faddsub" 4
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "fp"))
+ "us3_fpa + us3_slotany, nothing*3")
+
+(define_insn_reservation "us3_fpcmp" 5
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "fpcmp"))
+ "us3_fpa + us3_slotany, nothing*4")
+
+(define_insn_reservation "us3_fmult" 4
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "fpmul"))
+ "us3_fpm + us3_slotany, nothing*3")
+
+(define_insn_reservation "us3_fdivs" 17
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "fpdivs"))
+ "(us3_fpm + us3_slotany), us3_fpm*14, nothing*2")
+
+(define_insn_reservation "us3_fsqrts" 20
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "fpsqrts"))
+ "(us3_fpm + us3_slotany), us3_fpm*17, nothing*2")
+
+(define_insn_reservation "us3_fdivd" 20
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "fpdivd"))
+ "(us3_fpm + us3_slotany), us3_fpm*17, nothing*2")
+
+(define_insn_reservation "us3_fsqrtd" 29
+ (and (eq_attr "cpu" "ultrasparc3")
+ (eq_attr "type" "fpsqrtd"))
+ "(us3_fpm + us3_slotany), us3_fpm*26, nothing*2")
+
+;; Any store may multi issue with the insn creating the source
+;; data as long as that creating insn is not an FPU div/sqrt.
+;; We need a special guard function because this bypass does
+;; not apply to the address inputs of the store.
+(define_bypass 0 "us3_integer,us3_faddsub,us3_fmov,us3_fcmov,us3_fmult" "us3_store"
+ "store_data_bypass_p")
+
+;; An integer branch may execute in the same cycle as the compare
+;; creating the condition codes.
+(define_bypass 0 "us3_integer" "us3_branch")
+
+;; If FMOVfcc is user of FPCMP, latency is only 1 cycle.
+(define_bypass 1 "us3_fpcmp" "us3_fcmov")
diff --git a/contrib/gcc/config/sparc/vxsim.h b/contrib/gcc/config/sparc/vxsim.h
index c821e82..c9c3569 100644
--- a/contrib/gcc/config/sparc/vxsim.h
+++ b/contrib/gcc/config/sparc/vxsim.h
@@ -131,6 +131,6 @@ do { \
/* ??? This does not work in SunOS 4.x, so it is not enabled in sparc.h.
Instead, it is enabled here, because it does work under Solaris. */
-/* Define for support of TFmode long double and REAL_ARITHMETIC.
- Sparc ABI says that long double is 4 words. */
+/* Define for support of TFmode long double.
+ SPARC ABI says that long double is 4 words. */
#define LONG_DOUBLE_TYPE_SIZE 64
diff --git a/contrib/gcc/config/sparc/vxsparc64.h b/contrib/gcc/config/sparc/vxsparc64.h
index 358f2c0..1da8b7f 100644
--- a/contrib/gcc/config/sparc/vxsparc64.h
+++ b/contrib/gcc/config/sparc/vxsparc64.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler.
- 64-bit VxWorks Sparc version.
+ 64-bit VxWorks SPARC version.
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -44,7 +44,7 @@ Boston, MA 02111-1307, USA. */
#define NO_DOT_IN_LABEL
/* Enable #pragma pack(n) */
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
/* We use stabs for debugging */
#undef PREFERRED_DEBUGGING_TYPE
diff --git a/contrib/gcc/config/svr3.h b/contrib/gcc/config/svr3.h
index 4de6f52..e559c5c 100644
--- a/contrib/gcc/config/svr3.h
+++ b/contrib/gcc/config/svr3.h
@@ -1,6 +1,6 @@
/* Operating system specific defines to be used when targeting GCC for
generic System V Release 3 system.
- Copyright (C) 1991, 1996, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1996, 2000, 2002 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@monkeys.com).
This file is part of GNU CC.
@@ -113,10 +113,6 @@ Boston, MA 02111-1307, USA.
#define LINK_SPEC "%{T*} %{z:-lm}"
#endif
-/* Allow #sccs in preprocessor. */
-
-#define SCCS_DIRECTIVE
-
/* Output #ident as a .ident. */
#undef ASM_OUTPUT_IDENT
@@ -133,7 +129,7 @@ Boston, MA 02111-1307, USA.
/* System V Release 3 uses COFF debugging info. */
-#define SDB_DEBUGGING_INFO
+#define SDB_DEBUGGING_INFO 1
/* We don't want to output DBX debugging information. */
@@ -188,16 +184,7 @@ Boston, MA 02111-1307, USA.
#undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX "."
-/* Support const sections and the ctors and dtors sections for g++.
- Note that there appears to be two different ways to support const
- sections at the moment. You can either #define the symbol
- READONLY_DATA_SECTION (giving it some code which switches to the
- readonly data section) or else you can #define the symbols
- EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
- SELECT_RTX_SECTION. We do both here just to be on the safe side.
- However, use of the const section is turned off by default
- unless the specific tm.h file turns it on by defining
- USE_CONST_SECTION as 1. */
+/* Support const sections and the ctors and dtors sections for g++. */
/* Define a few machine-specific details of the implementation of
constructors.
@@ -208,11 +195,8 @@ Boston, MA 02111-1307, USA.
Define TARGET_ASM_CONSTRUCTOR to push the address of the constructor. */
-#define USE_CONST_SECTION 0
-
#define INIT_SECTION_ASM_OP "\t.section\t.init"
#define FINI_SECTION_ASM_OP "\t.section .fini,\"x\""
-#define CONST_SECTION_ASM_OP "\t.section\t.rodata, \"x\""
#define DTORS_SECTION_ASM_OP FINI_SECTION_ASM_OP
/* CTOR_LIST_BEGIN and CTOR_LIST_END are machine-dependent
@@ -243,14 +227,11 @@ do { \
#endif /* STACK_GROWS_DOWNWARD */
-/* Add extra sections .rodata, .init and .fini. */
-
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const, in_init, in_fini
+#define EXTRA_SECTIONS in_init, in_fini
#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
- CONST_SECTION_FUNCTION \
INIT_SECTION_FUNCTION \
FINI_SECTION_FUNCTION
@@ -275,57 +256,3 @@ fini_section () \
in_section = in_fini; \
} \
}
-
-#define READONLY_DATA_SECTION() const_section ()
-
-#define CONST_SECTION_FUNCTION \
-void \
-const_section () \
-{ \
- if (!USE_CONST_SECTION) \
- text_section(); \
- else if (in_section != in_const) \
- { \
- fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
- in_section = in_const; \
- } \
-}
-
-/* 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,ALIGN) \
-{ \
- if (TREE_CODE (DECL) == STRING_CST) \
- { \
- if (! flag_writable_strings) \
- const_section (); \
- else \
- data_section (); \
- } \
- else if (TREE_CODE (DECL) == VAR_DECL) \
- { \
- if ((0 && RELOC) /* should be (flag_pic && RELOC) */ \
- || !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
- || !DECL_INITIAL (DECL) \
- || (DECL_INITIAL (DECL) != error_mark_node \
- && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \
- data_section (); \
- else \
- const_section (); \
- } \
- else \
- const_section (); \
-}
-
-/* A C statement or statements to switch to the appropriate
- section for output of RTX in mode MODE. RTX is some kind
- of constant in RTL. The argument MODE is redundant except
- in the case of a `const_int' rtx. Currently, these always
- go into the const section. */
-
-#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE,RTX,ALIGN) const_section()
diff --git a/contrib/gcc/config/svr4.h b/contrib/gcc/config/svr4.h
index 5f74453..bc6a3b8 100644
--- a/contrib/gcc/config/svr4.h
+++ b/contrib/gcc/config/svr4.h
@@ -173,16 +173,15 @@ Boston, MA 02111-1307, USA.
%{Qy:} %{!Qn:-Qy}"
#endif
-/* Gcc automatically adds in one of the files /usr/ccs/lib/values-Xc.o,
- /usr/ccs/lib/values-Xa.o, or /usr/ccs/lib/values-Xt.o for each final
- 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. */
+/* Gcc automatically adds in one of the files /usr/ccs/lib/values-Xc.o
+ or /usr/ccs/lib/values-Xa.o for each final link step (depending
+ upon the other gcc options selected, such as -ansi). These files
+ each contain one (initialized) copy of a special variable called
+ `_lib_version'. Each one of these files has `_lib_version' initialized
+ to a different (enum) value. The SVR4 library routines query the
+ value of `_lib_version' at run to decide how they should behave.
+ Specifically, they decide (based upon the value of `_lib_version')
+ if they will act in a strictly ANSI conforming manner or not. */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "%{!shared: \
@@ -190,15 +189,9 @@ Boston, MA 02111-1307, USA.
%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}}}\
%{pg:gcrti.o%s}%{!pg:crti.o%s} \
%{ansi:values-Xc.o%s} \
- %{!ansi: \
- %{traditional:values-Xt.o%s} \
- %{!traditional:values-Xa.o%s}} \
+ %{!ansi:values-Xa.o%s} \
crtbegin.o%s"
-/* Allow #sccs in preprocessor. */
-
-#define SCCS_DIRECTIVE
-
/* The numbers used to denote specific machine registers in the System V
Release 4 DWARF debugging information are quite likely to be totally
different from the numbers used in BSD stabs debugging information
diff --git a/contrib/gcc/config/t-darwin b/contrib/gcc/config/t-darwin
new file mode 100644
index 0000000..7fe5e93
--- /dev/null
+++ b/contrib/gcc/config/t-darwin
@@ -0,0 +1,22 @@
+darwin.o: $(srcdir)/config/darwin.c $(CONFIG_H) $(SYSTEM_H) $(RTL_BASE_H) \
+ $(REGS_H) hard-reg-set.h insn-config.h conditions.h output.h \
+ insn-attr.h flags.h $(TREE_H) $(EXPR_H) reload.h \
+ function.h $(GGC_H) $(TM_P_H) gt-darwin.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+
+darwin-c.o: $(srcdir)/config/darwin-c.c $(CONFIG_H) $(SYSTEM_H) \
+ $(TREE_H) $(C_TREE_H) c-pragma.h toplev.h cpplib.h $(TM_P_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+
+gt-darwin.h : s-gtype ; @true
+
+# Explain how to build crt2.o
+$(T)crt2$(objext): $(srcdir)/config/darwin-crt2.c $(GCC_PASSES) \
+ $(TCONFIG_H) tsystem.h
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) \
+ -c $(srcdir)/config/darwin-crt2.c -o $(T)crt2$(objext)
+
+# Use unwind-dw2-fde-darwin
+LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-darwin.c \
+ $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
+LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.c
diff --git a/contrib/gcc/config/t-libc-ok b/contrib/gcc/config/t-libc-ok
index 9b0fb38..4dae812 100644
--- a/contrib/gcc/config/t-libc-ok
+++ b/contrib/gcc/config/t-libc-ok
@@ -1 +1 @@
-CRTSTUFF_T_FLAGS_S=-fPIC
+CRTSTUFF_T_CFLAGS_S=-fPIC
diff --git a/contrib/gcc/config/t-linux b/contrib/gcc/config/t-linux
index 570135a..61bce29 100644
--- a/contrib/gcc/config/t-linux
+++ b/contrib/gcc/config/t-linux
@@ -2,7 +2,7 @@
STMP_FIXPROTO =
# Compile crtbeginS.o and crtendS.o with pic.
-CRTSTUFF_T_CFLAGS_S = -fPIC
+CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
# Compile libgcc2.a with pic.
TARGET_LIBGCC2_CFLAGS = -fPIC
@@ -12,5 +12,5 @@ SHLIB_MAPFILES += $(srcdir)/config/libgcc-glibc.ver
# Use unwind-dw2-fde-glibc
LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-glibc.c \
- $(srcdir)/unwind-sjlj.c
+ $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.c
diff --git a/contrib/gcc/config/t-linux-gnulibc1 b/contrib/gcc/config/t-linux-gnulibc1
index 56a4715..52effd5 100644
--- a/contrib/gcc/config/t-linux-gnulibc1
+++ b/contrib/gcc/config/t-linux-gnulibc1
@@ -3,5 +3,5 @@ T_CFLAGS = -DUSE_GNULIBC_1
# Use unwind-dw2-fde
LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
- $(srcdir)/unwind-sjlj.c
+ $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h
diff --git a/contrib/gcc/config/t-netbsd b/contrib/gcc/config/t-netbsd
index d284b3e..fa2a488 100644
--- a/contrib/gcc/config/t-netbsd
+++ b/contrib/gcc/config/t-netbsd
@@ -1,2 +1,5 @@
# Don't run fixproto
STMP_FIXPROTO =
+
+# Always build crtstuff with PIC.
+CRTSTUFF_T_CFLAGS = -fPIC
diff --git a/contrib/gcc/configure b/contrib/gcc/configure
index 89d3372..5f00c79 100755
--- a/contrib/gcc/configure
+++ b/contrib/gcc/configure
@@ -34,10 +34,15 @@ ac_help="$ac_help
--enable-checking[=LIST]
enable expensive run-time checks. With LIST,
enable only specific categories of checks.
- Categories are: misc,tree,rtl,gc,gcac; default
- is misc,tree,gc"
+ Categories are: misc,tree,rtl,rtlflag,gc,gcac;
+ default is misc,tree,gc,rtlflag"
ac_help="$ac_help
- --disable-cpp don't provide a user-visible C preprocessor"
+ --enable-coverage[=LEVEL]
+ enable compiler\'s code coverage collection.
+ Use to measure compiler performance and locate
+ unused parts of the compiler. With LEVEL, specificy
+ optimization. Values are opt, noopt,
+ default is noopt"
ac_help="$ac_help
--with-cpp-install-dir=DIR
install the user visible C preprocessor in DIR
@@ -59,6 +64,8 @@ ac_help="$ac_help
ac_help="$ac_help
--with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib"
ac_help="$ac_help
+ --enable-initfini-array use .init_array/.fini_array sections"
+ac_help="$ac_help
--enable-nls use Native Language Support (default)"
ac_help="$ac_help
--with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib"
@@ -87,6 +94,8 @@ ac_help="$ac_help
--enable-sjlj-exceptions
arrange to use setjmp/longjmp exception handling"
ac_help="$ac_help
+ --enable-libunwind-exceptions force use libunwind for exceptions"
+ac_help="$ac_help
--enable-version-specific-runtime-libs
specify that runtime libraries should be
installed in a compiler-specific directory"
@@ -109,7 +118,6 @@ program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
-sitefile=
srcdir=
target=NONE
verbose=
@@ -224,7 +232,6 @@ Configuration:
--help print this message
--no-create do not create output files
--quiet, --silent do not print \`checking...' messages
- --site-file=FILE use FILE as the site file
--version print the version of autoconf that created configure
Directory and file names:
--prefix=PREFIX install architecture-independent files in PREFIX
@@ -395,11 +402,6 @@ EOF
-site=* | --site=* | --sit=*)
site="$ac_optarg" ;;
- -site-file | --site-file | --site-fil | --site-fi | --site-f)
- ac_prev=sitefile ;;
- -site-file=* | --site-file=* | --site-fil=* | --site-fi=* | --site-f=*)
- sitefile="$ac_optarg" ;;
-
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
@@ -565,16 +567,12 @@ fi
srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
# Prefer explicitly selected file to automatically selected ones.
-if test -z "$sitefile"; then
- if test -z "$CONFIG_SITE"; then
- if test "x$prefix" != xNONE; then
- CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
- else
- CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
- fi
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
-else
- CONFIG_SITE="$sitefile"
fi
for ac_site_file in $CONFIG_SITE; do
if test -r "$ac_site_file"; then
@@ -629,7 +627,7 @@ copy=cp
# - two terminals occur directly after each other
# - the path contains an element with a dot in it
echo $ac_n "checking LIBRARY_PATH variable""... $ac_c" 1>&6
-echo "configure:633: checking LIBRARY_PATH variable" >&5
+echo "configure:631: checking LIBRARY_PATH variable" >&5
case ${LIBRARY_PATH} in
[:\;]* | *[:\;] | *[:\;][:\;]* | *[:\;]. | .[:\;]*| . | *[:\;].[:\;]* )
library_path_setting="contains current directory"
@@ -654,7 +652,7 @@ fi
# - two terminals occur directly after each other
# - the path contains an element with a dot in it
echo $ac_n "checking GCC_EXEC_PREFIX variable""... $ac_c" 1>&6
-echo "configure:658: checking GCC_EXEC_PREFIX variable" >&5
+echo "configure:656: checking GCC_EXEC_PREFIX variable" >&5
case ${GCC_EXEC_PREFIX} in
[:\;]* | *[:\;] | *[:\;][:\;]* | *[:\;]. | .[:\;]*| . | *[:\;].[:\;]* )
gcc_exec_prefix_setting="contains current directory"
@@ -793,206 +791,6 @@ if test x${gcc_gxx_include_dir} = x; then
fi
fi
-# Determine whether or not multilibs are enabled.
-# Check whether --enable-multilib or --disable-multilib was given.
-if test "${enable_multilib+set}" = set; then
- enableval="$enable_multilib"
- :
-else
- enable_multilib=yes
-fi
-
-
-
-# Enable expensive internal checks
-# Check whether --enable-checking or --disable-checking was given.
-if test "${enable_checking+set}" = set; then
- enableval="$enable_checking"
- ac_checking=
-ac_tree_checking=
-ac_rtl_checking=
-ac_gc_checking=
-ac_gc_always_collect=
-case "${enableval}" in
-yes) ac_checking=1 ; ac_tree_checking=1 ; ac_gc_checking=1 ;;
-no) ;;
-*) IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="$IFS,"
- set fnord $enableval; shift
- IFS="$ac_save_IFS"
- for check
- do
- case $check in
- misc) ac_checking=1 ;;
- tree) ac_tree_checking=1 ;;
- rtl) ac_rtl_checking=1 ;;
- gc) ac_gc_checking=1 ;;
- gcac) ac_gc_always_collect=1 ;;
- *) { echo "configure: error: unknown check category $check" 1>&2; exit 1; } ;;
- esac
- done
- ;;
-esac
-
-fi
-
-if test x$ac_checking != x ; then
- cat >> confdefs.h <<\EOF
-#define ENABLE_CHECKING 1
-EOF
-
-fi
-if test x$ac_tree_checking != x ; then
- cat >> confdefs.h <<\EOF
-#define ENABLE_TREE_CHECKING 1
-EOF
-
-fi
-if test x$ac_rtl_checking != x ; then
- cat >> confdefs.h <<\EOF
-#define ENABLE_RTL_CHECKING 1
-EOF
-
-fi
-if test x$ac_gc_checking != x ; then
- cat >> confdefs.h <<\EOF
-#define ENABLE_GC_CHECKING 1
-EOF
-
-fi
-if test x$ac_gc_always_collect != x ; then
- cat >> confdefs.h <<\EOF
-#define ENABLE_GC_ALWAYS_COLLECT 1
-EOF
-
-fi
-
-
-# Check whether --enable-cpp or --disable-cpp was given.
-if test "${enable_cpp+set}" = set; then
- enableval="$enable_cpp"
- :
-else
- enable_cpp=yes
-fi
-
-
-# Check whether --with-cpp_install_dir or --without-cpp_install_dir was given.
-if test "${with_cpp_install_dir+set}" = set; then
- withval="$with_cpp_install_dir"
- if test x$withval = xyes; then
- { echo "configure: error: option --with-cpp-install-dir requires an argument" 1>&2; exit 1; }
-elif test x$withval != xno; then
- cpp_install_dir=$withval
-fi
-fi
-
-
-# Enable __cxa_atexit for C++.
-# Check whether --enable-__cxa_atexit or --disable-__cxa_atexit was given.
-if test "${enable___cxa_atexit+set}" = set; then
- enableval="$enable___cxa_atexit"
- :
-fi
-
-if test x$enable___cxa_atexit = xyes; then
- cat >> confdefs.h <<\EOF
-#define DEFAULT_USE_CXA_ATEXIT 1
-EOF
-
-fi
-
-# Enable Multibyte Characters for C/C++
-# Check whether --enable-c-mbchar or --disable-c-mbchar was given.
-if test "${enable_c_mbchar+set}" = set; then
- enableval="$enable_c_mbchar"
- if test x$enable_c_mbchar != xno; then
- cat >> confdefs.h <<\EOF
-#define MULTIBYTE_CHARS 1
-EOF
-
-fi
-fi
-
-
-# Enable threads
-# Pass with no value to take the default
-# Pass with a value to specify a thread package
-# Check whether --enable-threads or --disable-threads was given.
-if test "${enable_threads+set}" = set; then
- enableval="$enable_threads"
- :
-else
- enable_threads=''
-fi
-
-
-enable_threads_flag=$enable_threads
-# Check if a valid thread package
-case x${enable_threads_flag} in
- x | xno)
- # No threads
- target_thread_file='single'
- ;;
- xyes)
- # default
- target_thread_file=''
- ;;
- xdecosf1 | xirix | xmach | xos2 | xposix | xpthreads | xsingle | \
- xsolaris | xwin32 | xdce | xrtems| xvxworks | xaix)
- target_thread_file=$enable_threads_flag
- ;;
- *)
- echo "$enable_threads is an unknown thread package" 1>&2
- exit 1
- ;;
-esac
-
-# Check whether --enable-objc-gc or --disable-objc-gc was given.
-if test "${enable_objc_gc+set}" = set; then
- enableval="$enable_objc_gc"
- if test x$enable_objc_gc = xno; then
- objc_boehm_gc=''
-else
- objc_boehm_gc=1
-fi
-else
- objc_boehm_gc=''
-fi
-
-
-# Check whether --with-dwarf2 or --without-dwarf2 was given.
-if test "${with_dwarf2+set}" = set; then
- withval="$with_dwarf2"
- dwarf2="$with_dwarf2"
-else
- dwarf2=no
-fi
-
-
-# Check whether --enable-shared or --disable-shared was given.
-if test "${enable_shared+set}" = set; then
- enableval="$enable_shared"
-
- case $enable_shared in
- yes | no) ;;
- *)
- enable_shared=no
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
- for pkg in $enableval; do
- if test "X$pkg" = "Xgcc" || test "X$pkg" = "Xlibgcc"; then
- enable_shared=yes
- fi
- done
- IFS="$ac_save_ifs"
- ;;
- esac
-
-else
- enable_shared=yes
-fi
-
-
-
# Determine the host, build, and target systems
ac_aux_dir=
for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
@@ -1041,7 +839,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
fi
echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:1045: checking host system type" >&5
+echo "configure:843: checking host system type" >&5
host_alias=$host
case "$host_alias" in
@@ -1062,7 +860,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$host" 1>&6
echo $ac_n "checking target system type""... $ac_c" 1>&6
-echo "configure:1066: checking target system type" >&5
+echo "configure:864: checking target system type" >&5
target_alias=$target
case "$target_alias" in
@@ -1080,7 +878,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$target" 1>&6
echo $ac_n "checking build system type""... $ac_c" 1>&6
-echo "configure:1084: checking build system type" >&5
+echo "configure:882: checking build system type" >&5
build_alias=$build
case "$build_alias" in
@@ -1128,7 +926,7 @@ test "$program_transform_name" = "" && program_transform_name="s,x,x,"
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1132: checking for $ac_word" >&5
+echo "configure:930: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1158,7 +956,7 @@ if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1162: checking for $ac_word" >&5
+echo "configure:960: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1209,7 +1007,7 @@ fi
# Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1213: checking for $ac_word" >&5
+echo "configure:1011: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1241,7 +1039,7 @@ fi
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:1245: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:1043: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -1252,12 +1050,12 @@ cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext << EOF
-#line 1256 "configure"
+#line 1054 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
-if { (eval echo configure:1261: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1059: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
@@ -1283,12 +1081,12 @@ if test $ac_cv_prog_cc_works = no; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:1287: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:1085: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:1292: checking whether we are using GNU C" >&5
+echo "configure:1090: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1297,7 +1095,7 @@ else
yes;
#endif
EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1301: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1099: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
@@ -1316,7 +1114,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:1320: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:1118: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1349,10 +1147,10 @@ fi
if test "x$CC" != xcc; then
echo $ac_n "checking whether $CC and cc understand -c and -o together""... $ac_c" 1>&6
-echo "configure:1353: checking whether $CC and cc understand -c and -o together" >&5
+echo "configure:1151: checking whether $CC and cc understand -c and -o together" >&5
else
echo $ac_n "checking whether cc understands -c and -o together""... $ac_c" 1>&6
-echo "configure:1356: checking whether cc understands -c and -o together" >&5
+echo "configure:1154: checking whether cc understands -c and -o together" >&5
fi
set dummy $CC; ac_cc="`echo $2 |
sed -e 's/[^a-zA-Z0-9_]/_/g' -e 's/^[0-9]/_/'`"
@@ -1364,16 +1162,16 @@ else
# We do the test twice because some compilers refuse to overwrite an
# existing .o file with -o, though they will create one.
ac_try='${CC-cc} -c conftest.c -o conftest.o 1>&5'
-if { (eval echo configure:1368: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } &&
- test -f conftest.o && { (eval echo configure:1369: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; };
+if { (eval echo configure:1166: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } &&
+ test -f conftest.o && { (eval echo configure:1167: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; };
then
eval ac_cv_prog_cc_${ac_cc}_c_o=yes
if test "x$CC" != xcc; then
# Test first that cc exists at all.
- if { ac_try='cc -c conftest.c 1>&5'; { (eval echo configure:1374: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then
+ if { ac_try='cc -c conftest.c 1>&5'; { (eval echo configure:1172: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then
ac_try='cc -c conftest.c -o conftest.o 1>&5'
- if { (eval echo configure:1376: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } &&
- test -f conftest.o && { (eval echo configure:1377: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; };
+ if { (eval echo configure:1174: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } &&
+ test -f conftest.o && { (eval echo configure:1175: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; };
then
# cc works too.
:
@@ -1419,7 +1217,7 @@ fi
# Extract the first word of "${ac_tool_prefix}gnatbind", so it can be a program name with args.
set dummy ${ac_tool_prefix}gnatbind; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1423: checking for $ac_word" >&5
+echo "configure:1221: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_GNATBIND'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1451,7 +1249,7 @@ if test -n "$ac_tool_prefix"; then
# Extract the first word of "gnatbind", so it can be a program name with args.
set dummy gnatbind; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1455: checking for $ac_word" >&5
+echo "configure:1253: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_GNATBIND'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1484,7 +1282,7 @@ fi
fi
echo $ac_n "checking for compiler driver that understands Ada""... $ac_c" 1>&6
-echo "configure:1488: checking for compiler driver that understands Ada" >&5
+echo "configure:1286: checking for compiler driver that understands Ada" >&5
if eval "test \"`echo '$''{'gcc_cv_prog_adac'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1493,10 +1291,7 @@ procedure conftest is begin null; end conftest;
EOF
gcc_cv_prog_adac=no
# Have to do ac_tool_prefix and user overrides by hand.
-user_adac=$ADAC
-user_cc=$CC
-for cand in ${ac_tool_prefix}$user_adac $user_adac \
- ${ac_tool_prefix}$user_cc $user_cc \
+for cand in ${ADAC+"$ADAC"} ${CC+"$CC"} \
${ac_tool_prefix}gcc gcc \
${ac_tool_prefix}cc cc \
${ac_tool_prefix}gnatgcc gnatgcc \
@@ -1529,21 +1324,21 @@ fi
echo $ac_n "checking whether ${CC-cc} accepts -Wno-long-long""... $ac_c" 1>&6
-echo "configure:1533: checking whether ${CC-cc} accepts -Wno-long-long" >&5
+echo "configure:1328: checking whether ${CC-cc} accepts -Wno-long-long" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_no_long_long'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
save_CFLAGS="$CFLAGS"
CFLAGS="-Wno-long-long"
cat > conftest.$ac_ext <<EOF
-#line 1540 "configure"
+#line 1335 "configure"
#include "confdefs.h"
int main() {
; return 0; }
EOF
-if { (eval echo configure:1547: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1342: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_prog_cc_no_long_long=yes
else
@@ -1560,7 +1355,7 @@ echo "$ac_t""$ac_cv_prog_cc_no_long_long" 1>&6
if test x$have_gnat != xno ; then
echo $ac_n "checking whether ${ADAC} accepts -Wno-long-long""... $ac_c" 1>&6
-echo "configure:1564: checking whether ${ADAC} accepts -Wno-long-long" >&5
+echo "configure:1359: checking whether ${ADAC} accepts -Wno-long-long" >&5
if eval "test \"`echo '$''{'ac_cv_prog_adac_no_long_long'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1588,7 +1383,7 @@ fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:1592: checking how to run the C preprocessor" >&5
+echo "configure:1387: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
@@ -1603,13 +1398,13 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
-#line 1607 "configure"
+#line 1402 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1613: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1408: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -1620,13 +1415,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
-#line 1624 "configure"
+#line 1419 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1630: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1425: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -1637,13 +1432,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -nologo -E"
cat > conftest.$ac_ext <<EOF
-#line 1641 "configure"
+#line 1436 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1647: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1442: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -1668,21 +1463,21 @@ fi
echo "$ac_t""$CPP" 1>&6
echo $ac_n "checking for inline""... $ac_c" 1>&6
-echo "configure:1672: checking for inline" >&5
+echo "configure:1467: checking for inline" >&5
if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_c_inline=no
for ac_kw in inline __inline__ __inline; do
cat > conftest.$ac_ext <<EOF
-#line 1679 "configure"
+#line 1474 "configure"
#include "confdefs.h"
int main() {
} $ac_kw foo() {
; return 0; }
EOF
-if { (eval echo configure:1686: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1481: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_inline=$ac_kw; break
else
@@ -1708,19 +1503,19 @@ EOF
esac
echo $ac_n "checking for volatile""... $ac_c" 1>&6
-echo "configure:1712: checking for volatile" >&5
+echo "configure:1507: checking for volatile" >&5
if eval "test \"`echo '$''{'gcc_cv_c_volatile'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1717 "configure"
+#line 1512 "configure"
#include "confdefs.h"
int main() {
volatile int foo;
; return 0; }
EOF
-if { (eval echo configure:1724: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1519: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gcc_cv_c_volatile=yes
else
@@ -1742,7 +1537,7 @@ fi
echo $ac_n "checking for long double""... $ac_c" 1>&6
-echo "configure:1746: checking for long double" >&5
+echo "configure:1541: checking for long double" >&5
if eval "test \"`echo '$''{'gcc_cv_c_long_double'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1750,7 +1545,7 @@ else
gcc_cv_c_long_double=yes
else
cat > conftest.$ac_ext <<EOF
-#line 1754 "configure"
+#line 1549 "configure"
#include "confdefs.h"
int main() {
@@ -1760,7 +1555,7 @@ long double foo = 0.0;
switch (0) case 0: case (sizeof(long double) >= sizeof(double)):;
; return 0; }
EOF
-if { (eval echo configure:1764: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1559: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gcc_cv_c_long_double=yes
else
@@ -1782,19 +1577,19 @@ EOF
fi
echo $ac_n "checking for long long int""... $ac_c" 1>&6
-echo "configure:1786: checking for long long int" >&5
+echo "configure:1581: checking for long long int" >&5
if eval "test \"`echo '$''{'ac_cv_c_long_long'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1791 "configure"
+#line 1586 "configure"
#include "confdefs.h"
int main() {
long long int i;
; return 0; }
EOF
-if { (eval echo configure:1798: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1593: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_long_long=yes
else
@@ -1814,19 +1609,19 @@ EOF
fi
echo $ac_n "checking for __int64""... $ac_c" 1>&6
-echo "configure:1818: checking for __int64" >&5
+echo "configure:1613: checking for __int64" >&5
if eval "test \"`echo '$''{'ac_cv_c___int64'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1823 "configure"
+#line 1618 "configure"
#include "confdefs.h"
int main() {
__int64 i;
; return 0; }
EOF
-if { (eval echo configure:1830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1625: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c___int64=yes
else
@@ -1847,19 +1642,19 @@ EOF
fi
echo $ac_n "checking for built-in _Bool""... $ac_c" 1>&6
-echo "configure:1851: checking for built-in _Bool" >&5
+echo "configure:1646: checking for built-in _Bool" >&5
if eval "test \"`echo '$''{'gcc_cv_c__bool'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1856 "configure"
+#line 1651 "configure"
#include "confdefs.h"
int main() {
_Bool foo;
; return 0; }
EOF
-if { (eval echo configure:1863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1658: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gcc_cv_c__bool=yes
else
@@ -1883,13 +1678,13 @@ fi
# sizeof(char) is 1 by definition.
echo $ac_n "checking size of short""... $ac_c" 1>&6
-echo "configure:1887: checking size of short" >&5
+echo "configure:1682: checking size of short" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
-#line 1893 "configure"
+#line 1688 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
@@ -1899,7 +1694,7 @@ int main() {
switch (0) case 0: case (sizeof (short) == $ac_size):;
; return 0; }
EOF
-if { (eval echo configure:1903: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1698: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_short=$ac_size
else
@@ -1922,13 +1717,13 @@ EOF
echo $ac_n "checking size of int""... $ac_c" 1>&6
-echo "configure:1926: checking size of int" >&5
+echo "configure:1721: checking size of int" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
-#line 1932 "configure"
+#line 1727 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
@@ -1938,7 +1733,7 @@ int main() {
switch (0) case 0: case (sizeof (int) == $ac_size):;
; return 0; }
EOF
-if { (eval echo configure:1942: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1737: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_int=$ac_size
else
@@ -1961,13 +1756,13 @@ EOF
echo $ac_n "checking size of long""... $ac_c" 1>&6
-echo "configure:1965: checking size of long" >&5
+echo "configure:1760: checking size of long" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
-#line 1971 "configure"
+#line 1766 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
@@ -1977,7 +1772,7 @@ int main() {
switch (0) case 0: case (sizeof (long) == $ac_size):;
; return 0; }
EOF
-if { (eval echo configure:1981: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1776: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_long=$ac_size
else
@@ -2001,13 +1796,13 @@ EOF
if test $ac_cv_c_long_long = yes; then
echo $ac_n "checking size of long long""... $ac_c" 1>&6
-echo "configure:2005: checking size of long long" >&5
+echo "configure:1800: checking size of long long" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
-#line 2011 "configure"
+#line 1806 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
@@ -2017,7 +1812,7 @@ int main() {
switch (0) case 0: case (sizeof (long long) == $ac_size):;
; return 0; }
EOF
-if { (eval echo configure:2021: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1816: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof_long_long=$ac_size
else
@@ -2042,13 +1837,13 @@ EOF
fi
if test $ac_cv_c___int64 = yes; then
echo $ac_n "checking size of __int64""... $ac_c" 1>&6
-echo "configure:2046: checking size of __int64" >&5
+echo "configure:1841: checking size of __int64" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof___int64'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence.
cat > conftest.$ac_ext <<EOF
-#line 2052 "configure"
+#line 1847 "configure"
#include "confdefs.h"
#include "confdefs.h"
#include <sys/types.h>
@@ -2058,7 +1853,7 @@ int main() {
switch (0) case 0: case (sizeof (__int64) == $ac_size):;
; return 0; }
EOF
-if { (eval echo configure:2062: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1857: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_sizeof___int64=$ac_size
else
@@ -2083,12 +1878,12 @@ EOF
fi
echo $ac_n "checking execution character set""... $ac_c" 1>&6
-echo "configure:2087: checking execution character set" >&5
+echo "configure:1882: checking execution character set" >&5
if eval "test \"`echo '$''{'ac_cv_c_charset'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2092 "configure"
+#line 1887 "configure"
#include "confdefs.h"
#if '\n' == 0x0A && ' ' == 0x20 && '0' == 0x30 \
&& 'A' == 0x41 && 'a' == 0x61 && '!' == 0x21
@@ -2104,7 +1899,7 @@ rm -f conftest*
if test x${ac_cv_c_charset+set} != xset; then
cat > conftest.$ac_ext <<EOF
-#line 2108 "configure"
+#line 1903 "configure"
#include "confdefs.h"
#if '\n' == 0x15 && ' ' == 0x40 && '0' == 0xF0 \
&& 'A' == 0xC1 && 'a' == 0x81 && '!' == 0x5A
@@ -2143,6 +1938,314 @@ if test "x$GCC" = "xyes"; then
fi
+# Determine whether or not multilibs are enabled.
+# Check whether --enable-multilib or --disable-multilib was given.
+if test "${enable_multilib+set}" = set; then
+ enableval="$enable_multilib"
+ :
+else
+ enable_multilib=yes
+fi
+
+
+
+# Enable expensive internal checks
+# Check whether --enable-checking or --disable-checking was given.
+if test "${enable_checking+set}" = set; then
+ enableval="$enable_checking"
+ ac_checking=
+ac_tree_checking=
+ac_rtl_checking=
+ac_rtlflag_checking=
+ac_gc_checking=
+ac_gc_always_collect=
+case "${enableval}" in
+yes) ac_checking=1 ; ac_tree_checking=1 ; ac_gc_checking=1 ;
+ ac_rtlflag_checking=1 ;;
+no) ;;
+*) IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="$IFS,"
+ set fnord $enableval; shift
+ IFS="$ac_save_IFS"
+ for check
+ do
+ case $check in
+ misc) ac_checking=1 ;;
+ tree) ac_tree_checking=1 ;;
+ rtlflag) ac_rtlflag_checking=1 ;;
+ rtl) ac_rtl_checking=1 ;;
+ gc) ac_gc_checking=1 ;;
+ gcac) ac_gc_always_collect=1 ;;
+ valgrind) ac_checking_valgrind=1 ;;
+ *) { echo "configure: error: unknown check category $check" 1>&2; exit 1; } ;;
+ esac
+ done
+ ;;
+esac
+
+fi
+
+nocommon_flag=""
+if test x$ac_checking != x ; then
+ cat >> confdefs.h <<\EOF
+#define ENABLE_CHECKING 1
+EOF
+
+ nocommon_flag=-fno-common
+fi
+
+if test x$ac_tree_checking != x ; then
+ cat >> confdefs.h <<\EOF
+#define ENABLE_TREE_CHECKING 1
+EOF
+
+fi
+if test x$ac_rtl_checking != x ; then
+ cat >> confdefs.h <<\EOF
+#define ENABLE_RTL_CHECKING 1
+EOF
+
+fi
+if test x$ac_rtlflag_checking != x ; then
+ cat >> confdefs.h <<\EOF
+#define ENABLE_RTL_FLAG_CHECKING 1
+EOF
+
+fi
+if test x$ac_gc_checking != x ; then
+ cat >> confdefs.h <<\EOF
+#define ENABLE_GC_CHECKING 1
+EOF
+
+fi
+if test x$ac_gc_always_collect != x ; then
+ cat >> confdefs.h <<\EOF
+#define ENABLE_GC_ALWAYS_COLLECT 1
+EOF
+
+fi
+valgrind_path_defines=
+valgrind_command=
+if test x$ac_checking_valgrind != x ; then
+ # It is certainly possible that there's valgrind but no valgrind.h.
+ # GCC relies on making annotations so we must have both.
+ ac_safe=`echo "valgrind.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for valgrind.h""... $ac_c" 1>&6
+echo "configure:2034: checking for valgrind.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2039 "configure"
+#include "confdefs.h"
+#include <valgrind.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2044: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ have_valgrind_h=yes
+else
+ echo "$ac_t""no" 1>&6
+have_valgrind_h=no
+fi
+
+ # Extract the first word of "valgrind", so it can be a program name with args.
+set dummy valgrind; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2069: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_valgrind_path'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$valgrind_path" in
+ /*)
+ ac_cv_path_valgrind_path="$valgrind_path" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if $ac_dir/$ac_word --version | grep valgrind- >/dev/null 2>&1; then
+ ac_cv_path_valgrind_path="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+valgrind_path="$ac_cv_path_valgrind_path"
+if test -n "$valgrind_path"; then
+ echo "$ac_t""$valgrind_path" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test "x$valgrind_path" = "x" || test $have_valgrind_h = no; then
+ { echo "configure: error: *** Can't find both valgrind and valgrind.h" 1>&2; exit 1; }
+ fi
+ valgrind_path_defines=-DVALGRIND_PATH='\"'$valgrind_path'\"'
+ valgrind_command="$valgrind_path -q"
+ cat >> confdefs.h <<\EOF
+#define ENABLE_VALGRIND_CHECKING 1
+EOF
+
+fi
+
+
+
+# Enable code coverage collection
+# Check whether --enable-coverage or --disable-coverage was given.
+if test "${enable_coverage+set}" = set; then
+ enableval="$enable_coverage"
+ case "${enableval}" in
+yes|noopt)
+ coverage_flags="-fprofile-arcs -ftest-coverage -O0"
+ ;;
+opt)
+ coverage_flags="-fprofile-arcs -ftest-coverage -O2"
+ ;;
+*)
+ { echo "configure: error: unknown coverage setting $enableval" 1>&2; exit 1; }
+ ;;
+esac
+else
+ coverage_flags=""
+fi
+
+
+
+# Check whether --with-cpp_install_dir or --without-cpp_install_dir was given.
+if test "${with_cpp_install_dir+set}" = set; then
+ withval="$with_cpp_install_dir"
+ if test x$withval = xyes; then
+ { echo "configure: error: option --with-cpp-install-dir requires an argument" 1>&2; exit 1; }
+elif test x$withval != xno; then
+ cpp_install_dir=$withval
+fi
+fi
+
+
+# Enable __cxa_atexit for C++.
+# Check whether --enable-__cxa_atexit or --disable-__cxa_atexit was given.
+if test "${enable___cxa_atexit+set}" = set; then
+ enableval="$enable___cxa_atexit"
+ :
+fi
+
+if test x$enable___cxa_atexit = xyes; then
+ cat >> confdefs.h <<\EOF
+#define DEFAULT_USE_CXA_ATEXIT 1
+EOF
+
+fi
+
+# Enable Multibyte Characters for C/C++
+# Check whether --enable-c-mbchar or --disable-c-mbchar was given.
+if test "${enable_c_mbchar+set}" = set; then
+ enableval="$enable_c_mbchar"
+ if test x$enable_c_mbchar != xno; then
+ cat >> confdefs.h <<\EOF
+#define MULTIBYTE_CHARS 1
+EOF
+
+fi
+fi
+
+
+# Enable threads
+# Pass with no value to take the default
+# Pass with a value to specify a thread package
+# Check whether --enable-threads or --disable-threads was given.
+if test "${enable_threads+set}" = set; then
+ enableval="$enable_threads"
+ :
+else
+ enable_threads=''
+fi
+
+
+enable_threads_flag=$enable_threads
+# Check if a valid thread package
+case x${enable_threads_flag} in
+ x | xno)
+ # No threads
+ target_thread_file='single'
+ ;;
+ xyes)
+ # default
+ target_thread_file=''
+ ;;
+ xdecosf1 | xirix | xmach | xos2 | xposix | xpthreads | xsingle | \
+ xsolaris | xwin32 | xdce | xrtems| xvxworks | xaix)
+ target_thread_file=$enable_threads_flag
+ ;;
+ *)
+ echo "$enable_threads is an unknown thread package" 1>&2
+ exit 1
+ ;;
+esac
+
+# Check whether --enable-objc-gc or --disable-objc-gc was given.
+if test "${enable_objc_gc+set}" = set; then
+ enableval="$enable_objc_gc"
+ if test x$enable_objc_gc = xno; then
+ objc_boehm_gc=''
+else
+ objc_boehm_gc=1
+fi
+else
+ objc_boehm_gc=''
+fi
+
+
+# Check whether --with-dwarf2 or --without-dwarf2 was given.
+if test "${with_dwarf2+set}" = set; then
+ withval="$with_dwarf2"
+ dwarf2="$with_dwarf2"
+else
+ dwarf2=no
+fi
+
+
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+
+ case $enable_shared in
+ yes | no) ;;
+ *)
+ enable_shared=no
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "Xgcc" || test "X$pkg" = "Xlibgcc"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+ esac
+
+else
+ enable_shared=yes
+fi
+
+
+
# Stage specific cflags for build.
stage1_cflags=
case $build in
@@ -2165,7 +2268,7 @@ esac
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:2169: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:2272: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -2193,7 +2296,7 @@ fi
echo $ac_n "checking whether a default assembler was specified""... $ac_c" 1>&6
-echo "configure:2197: checking whether a default assembler was specified" >&5
+echo "configure:2300: checking whether a default assembler was specified" >&5
if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then
if test x"$gas_flag" = x"no"; then
echo "$ac_t""yes ($DEFAULT_ASSEMBLER)" 1>&6
@@ -2205,7 +2308,7 @@ else
fi
echo $ac_n "checking whether a default linker was specified""... $ac_c" 1>&6
-echo "configure:2209: checking whether a default linker was specified" >&5
+echo "configure:2312: checking whether a default linker was specified" >&5
if test x"${DEFAULT_LINKER+set}" = x"set"; then
if test x"$gnu_ld_flag" = x"no"; then
echo "$ac_t""yes ($DEFAULT_LINKER)" 1>&6
@@ -2217,12 +2320,12 @@ else
fi
echo $ac_n "checking for GNU C library""... $ac_c" 1>&6
-echo "configure:2221: checking for GNU C library" >&5
+echo "configure:2324: checking for GNU C library" >&5
if eval "test \"`echo '$''{'gcc_cv_glibc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2226 "configure"
+#line 2329 "configure"
#include "confdefs.h"
#include <features.h>
int main() {
@@ -2232,7 +2335,7 @@ int main() {
#endif
; return 0; }
EOF
-if { (eval echo configure:2236: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2339: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gcc_cv_glibc=yes
else
@@ -2258,7 +2361,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2262: checking for $ac_word" >&5
+echo "configure:2365: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2288,7 +2391,7 @@ test -n "$AWK" && break
done
echo $ac_n "checking whether ln works""... $ac_c" 1>&6
-echo "configure:2292: checking whether ln works" >&5
+echo "configure:2395: checking whether ln works" >&5
if eval "test \"`echo '$''{'gcc_cv_prog_LN'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2320,7 +2423,7 @@ else
fi
echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
-echo "configure:2324: checking whether ln -s works" >&5
+echo "configure:2427: checking whether ln -s works" >&5
if eval "test \"`echo '$''{'gcc_cv_prog_LN_S'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2354,7 +2457,7 @@ fi
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2358: checking for $ac_word" >&5
+echo "configure:2461: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2392,7 +2495,7 @@ fi
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:2396: checking for a BSD compatible install" >&5
+echo "configure:2499: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -2443,12 +2546,12 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:2447: checking for ANSI C header files" >&5
+echo "configure:2550: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2452 "configure"
+#line 2555 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
@@ -2456,7 +2559,7 @@ else
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2460: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2563: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -2473,7 +2576,7 @@ rm -f conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 2477 "configure"
+#line 2580 "configure"
#include "confdefs.h"
#include <string.h>
EOF
@@ -2491,7 +2594,7 @@ fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 2495 "configure"
+#line 2598 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
@@ -2512,7 +2615,7 @@ if test "$cross_compiling" = yes; then
:
else
cat > conftest.$ac_ext <<EOF
-#line 2516 "configure"
+#line 2619 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -2523,7 +2626,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }
EOF
-if { (eval echo configure:2527: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2630: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
@@ -2547,12 +2650,12 @@ EOF
fi
echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
-echo "configure:2551: checking whether time.h and sys/time.h may both be included" >&5
+echo "configure:2654: checking whether time.h and sys/time.h may both be included" >&5
if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2556 "configure"
+#line 2659 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/time.h>
@@ -2561,7 +2664,7 @@ int main() {
struct tm *tp;
; return 0; }
EOF
-if { (eval echo configure:2565: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2668: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_time=yes
else
@@ -2582,19 +2685,19 @@ EOF
fi
echo $ac_n "checking for working stdbool.h""... $ac_c" 1>&6
-echo "configure:2586: checking for working stdbool.h" >&5
+echo "configure:2689: checking for working stdbool.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdbool_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2591 "configure"
+#line 2694 "configure"
#include "confdefs.h"
#include <stdbool.h>
int main() {
bool foo = false;
; return 0; }
EOF
-if { (eval echo configure:2598: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2701: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_stdbool_h=yes
else
@@ -2615,12 +2718,12 @@ EOF
fi
echo $ac_n "checking whether string.h and strings.h may both be included""... $ac_c" 1>&6
-echo "configure:2619: checking whether string.h and strings.h may both be included" >&5
+echo "configure:2722: checking whether string.h and strings.h may both be included" >&5
if eval "test \"`echo '$''{'gcc_cv_header_string'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2624 "configure"
+#line 2727 "configure"
#include "confdefs.h"
#include <string.h>
#include <strings.h>
@@ -2628,7 +2731,7 @@ int main() {
; return 0; }
EOF
-if { (eval echo configure:2632: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2735: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gcc_cv_header_string=yes
else
@@ -2649,12 +2752,12 @@ EOF
fi
echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
-echo "configure:2653: checking for sys/wait.h that is POSIX.1 compatible" >&5
+echo "configure:2756: checking for sys/wait.h that is POSIX.1 compatible" >&5
if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2658 "configure"
+#line 2761 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/wait.h>
@@ -2670,7 +2773,7 @@ wait (&s);
s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
; return 0; }
EOF
-if { (eval echo configure:2674: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_sys_wait_h=yes
else
@@ -2691,23 +2794,23 @@ EOF
fi
for ac_hdr in limits.h stddef.h string.h strings.h stdlib.h time.h \
- fcntl.h unistd.h sys/file.h sys/time.h \
+ fcntl.h unistd.h sys/file.h sys/time.h sys/mman.h \
sys/resource.h sys/param.h sys/times.h sys/stat.h \
direct.h malloc.h langinfo.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2701: checking for $ac_hdr" >&5
+echo "configure:2804: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2706 "configure"
+#line 2809 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2711: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2814: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -2737,17 +2840,17 @@ done
# Check for thread headers.
ac_safe=`echo "thread.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for thread.h""... $ac_c" 1>&6
-echo "configure:2741: checking for thread.h" >&5
+echo "configure:2844: checking for thread.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2746 "configure"
+#line 2849 "configure"
#include "confdefs.h"
#include <thread.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2751: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2854: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -2771,17 +2874,17 @@ fi
ac_safe=`echo "pthread.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for pthread.h""... $ac_c" 1>&6
-echo "configure:2775: checking for pthread.h" >&5
+echo "configure:2878: checking for pthread.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2780 "configure"
+#line 2883 "configure"
#include "confdefs.h"
#include <pthread.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2785: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2888: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -2806,12 +2909,12 @@ fi
# These tests can't be done till we know if we have limits.h.
echo $ac_n "checking for CHAR_BIT""... $ac_c" 1>&6
-echo "configure:2810: checking for CHAR_BIT" >&5
+echo "configure:2913: checking for CHAR_BIT" >&5
if eval "test \"`echo '$''{'gcc_cv_decl_char_bit'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2815 "configure"
+#line 2918 "configure"
#include "confdefs.h"
#ifdef HAVE_LIMITS_H
#include <limits.h>
@@ -2836,7 +2939,7 @@ fi
echo "$ac_t""$gcc_cv_decl_char_bit" 1>&6
if test $gcc_cv_decl_char_bit = no; then
echo $ac_n "checking number of bits in a byte""... $ac_c" 1>&6
-echo "configure:2840: checking number of bits in a byte" >&5
+echo "configure:2943: checking number of bits in a byte" >&5
if eval "test \"`echo '$''{'gcc_cv_c_nbby'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2844,7 +2947,7 @@ else
gcc_cv_c_nbby=
while test $i -lt 65; do
cat > conftest.$ac_ext <<EOF
-#line 2848 "configure"
+#line 2951 "configure"
#include "confdefs.h"
int main() {
@@ -2854,7 +2957,7 @@ switch(0) {
; }
; return 0; }
EOF
-if { (eval echo configure:2858: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2961: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gcc_cv_c_nbby=$i; break
else
@@ -2879,7 +2982,7 @@ EOF
fi
fi
echo $ac_n "checking byte ordering""... $ac_c" 1>&6
-echo "configure:2883: checking byte ordering" >&5
+echo "configure:2986: checking byte ordering" >&5
if eval "test \"`echo '$''{'ac_cv_c_compile_endian'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2893,7 +2996,7 @@ ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$a
cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext <<EOF
-#line 2897 "configure"
+#line 3000 "configure"
#include "confdefs.h"
#ifdef HAVE_LIMITS_H
@@ -2913,7 +3016,7 @@ cat > conftest.$ac_ext <<EOF
'X', '\n'
};
EOF
-if { (eval echo configure:2917: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3020: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
od -c conftest.o |
sed 's/^[0-7]*[ ]*/ /
s/\*/./g
@@ -2952,7 +3055,7 @@ EOF
fi
echo $ac_n "checking floating point format""... $ac_c" 1>&6
-echo "configure:2956: checking floating point format" >&5
+echo "configure:3059: checking floating point format" >&5
if eval "test \"`echo '$''{'ac_cv_c_float_format'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -2965,7 +3068,7 @@ ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$a
cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext <<EOF
-#line 2969 "configure"
+#line 3072 "configure"
#include "confdefs.h"
/* This will not work unless sizeof(double) == 8. */
extern char sizeof_double_must_be_8 [sizeof(double) == 8 ? 1 : -1];
@@ -2987,7 +3090,7 @@ struct possibility table [] =
C(-5.22995989424860458374e+10) /* IBMHEXFP - s/390 format, EBCDIC */
};
EOF
-if { (eval echo configure:2991: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3094: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
od -c conftest.o |
sed 's/^[0-7]*[ ]*/ /
s/\*/./g
@@ -3076,7 +3179,7 @@ fi
# Extract the first word of "mktemp", so it can be a program name with args.
set dummy mktemp; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3080: checking for $ac_word" >&5
+echo "configure:3183: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_have_mktemp_command'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3115,7 +3218,7 @@ else
# Extract the first word of "makeinfo", so it can be a program name with args.
set dummy makeinfo; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3119: checking for $ac_word" >&5
+echo "configure:3222: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_MAKEINFO'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3144,16 +3247,16 @@ fi
if test -n "$MAKEINFO"; then
# Found it, now check the version.
echo $ac_n "checking for modern makeinfo""... $ac_c" 1>&6
-echo "configure:3148: checking for modern makeinfo" >&5
+echo "configure:3251: checking for modern makeinfo" >&5
if eval "test \"`echo '$''{'gcc_cv_prog_makeinfo_modern'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_prog_version=`$MAKEINFO --version 2>&1 |
sed -n 's/^.*GNU texinfo.* \([0-9][0-9.]*\).*$/\1/p'`
- echo "configure:3154: version of makeinfo is $ac_prog_version" >&5
+ echo "configure:3257: version of makeinfo is $ac_prog_version" >&5
case $ac_prog_version in
'') gcc_cv_prog_makeinfo_modern=no;;
- 4.[1-9]*)
+ 4.[2-9]*)
gcc_cv_prog_makeinfo_modern=yes;;
*) gcc_cv_prog_makeinfo_modern=no;;
esac
@@ -3178,7 +3281,7 @@ fi
# Is pod2man recent enough to regenerate manpages?
echo $ac_n "checking for recent Pod::Man""... $ac_c" 1>&6
-echo "configure:3182: checking for recent Pod::Man" >&5
+echo "configure:3285: checking for recent Pod::Man" >&5
if (perl -e 'use 1.10 Pod::Man') >/dev/null 2>&1; then
echo "$ac_t""yes" 1>&6
GENERATED_MANPAGES=generated-manpages
@@ -3194,7 +3297,7 @@ else
# Extract the first word of "flex", so it can be a program name with args.
set dummy flex; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3198: checking for $ac_word" >&5
+echo "configure:3301: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_FLEX'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3211,7 +3314,7 @@ else
fi
done
IFS="$ac_save_ifs"
- test -z "$ac_cv_prog_FLEX" && ac_cv_prog_FLEX="false"
+ test -z "$ac_cv_prog_FLEX" && ac_cv_prog_FLEX="${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing flex"
fi
fi
FLEX="$ac_cv_prog_FLEX"
@@ -3231,7 +3334,7 @@ else
# Extract the first word of "bison", so it can be a program name with args.
set dummy bison; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3235: checking for $ac_word" >&5
+echo "configure:3338: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_BISON'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3248,7 +3351,7 @@ else
fi
done
IFS="$ac_save_ifs"
- test -z "$ac_cv_prog_BISON" && ac_cv_prog_BISON="false"
+ test -z "$ac_cv_prog_BISON" && ac_cv_prog_BISON="${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing bison"
fi
fi
BISON="$ac_cv_prog_BISON"
@@ -3263,7 +3366,7 @@ fi
# These libraries may be used by collect2.
# We may need a special search path to get them linked.
echo $ac_n "checking for collect2 libraries""... $ac_c" 1>&6
-echo "configure:3267: checking for collect2 libraries" >&5
+echo "configure:3370: checking for collect2 libraries" >&5
if eval "test \"`echo '$''{'gcc_cv_collect2_libs'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3274,7 +3377,7 @@ for libs in '' -lld -lmld \
do
LIBS="$libs"
cat > conftest.$ac_ext <<EOF
-#line 3278 "configure"
+#line 3381 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -3285,7 +3388,7 @@ int main() {
ldopen()
; return 0; }
EOF
-if { (eval echo configure:3289: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3392: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
gcc_cv_collect2_libs="$libs"; break
else
@@ -3311,14 +3414,14 @@ save_LIBS="$LIBS"
LIBS=
echo $ac_n "checking for library containing exc_resume""... $ac_c" 1>&6
-echo "configure:3315: checking for library containing exc_resume" >&5
+echo "configure:3418: checking for library containing exc_resume" >&5
if eval "test \"`echo '$''{'ac_cv_search_exc_resume'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_func_search_save_LIBS="$LIBS"
ac_cv_search_exc_resume="no"
cat > conftest.$ac_ext <<EOF
-#line 3322 "configure"
+#line 3425 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -3329,7 +3432,7 @@ int main() {
exc_resume()
; return 0; }
EOF
-if { (eval echo configure:3333: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3436: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_search_exc_resume="none required"
else
@@ -3340,7 +3443,7 @@ rm -f conftest*
test "$ac_cv_search_exc_resume" = "no" && for i in exc; do
LIBS="-l$i $ac_func_search_save_LIBS"
cat > conftest.$ac_ext <<EOF
-#line 3344 "configure"
+#line 3447 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -3351,7 +3454,7 @@ int main() {
exc_resume()
; return 0; }
EOF
-if { (eval echo configure:3355: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3458: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_search_exc_resume="-l$i"
break
@@ -3375,17 +3478,87 @@ GNAT_LIBEXC="$LIBS"
LIBS="$save_LIBS"
+# Some systems put ldexp and frexp in libm instead of libc; assume
+# they're both in the same place. jcf-dump needs them.
+save_LIBS="$LIBS"
+LIBS=
+
+echo $ac_n "checking for library containing ldexp""... $ac_c" 1>&6
+echo "configure:3488: checking for library containing ldexp" >&5
+if eval "test \"`echo '$''{'ac_cv_search_ldexp'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_func_search_save_LIBS="$LIBS"
+ac_cv_search_ldexp="no"
+cat > conftest.$ac_ext <<EOF
+#line 3495 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char ldexp();
+
+int main() {
+ldexp()
+; return 0; }
+EOF
+if { (eval echo configure:3506: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_search_ldexp="none required"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+test "$ac_cv_search_ldexp" = "no" && for i in m; do
+LIBS="-l$i $ac_func_search_save_LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3517 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char ldexp();
+
+int main() {
+ldexp()
+; return 0; }
+EOF
+if { (eval echo configure:3528: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ ac_cv_search_ldexp="-l$i"
+break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+LIBS="$ac_func_search_save_LIBS"
+fi
+
+echo "$ac_t""$ac_cv_search_ldexp" 1>&6
+if test "$ac_cv_search_ldexp" != "no"; then
+ test "$ac_cv_search_ldexp" = "none required" || LIBS="$ac_cv_search_ldexp $LIBS"
+
+else :
+
+fi
+LDEXP_LIB="$LIBS"
+LIBS="$save_LIBS"
+
+
# See if the stage1 system preprocessor understands the ANSI C
# preprocessor stringification operator. (Used by symcat.h.)
echo $ac_n "checking for preprocessor stringizing operator""... $ac_c" 1>&6
-echo "configure:3384: checking for preprocessor stringizing operator" >&5
+echo "configure:3557: checking for preprocessor stringizing operator" >&5
if eval "test \"`echo '$''{'ac_cv_c_stringize'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3389 "configure"
+#line 3562 "configure"
#include "confdefs.h"
#define x(y) #y
@@ -3418,12 +3591,12 @@ echo "$ac_t""${ac_cv_c_stringize}" 1>&6
# Use <inttypes.h> only if it exists,
# doesn't clash with <sys/types.h>, and declares intmax_t.
echo $ac_n "checking for inttypes.h""... $ac_c" 1>&6
-echo "configure:3422: checking for inttypes.h" >&5
+echo "configure:3595: checking for inttypes.h" >&5
if eval "test \"`echo '$''{'gcc_cv_header_inttypes_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3427 "configure"
+#line 3600 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <inttypes.h>
@@ -3431,7 +3604,7 @@ int main() {
intmax_t i = -1;
; return 0; }
EOF
-if { (eval echo configure:3435: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3608: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gcc_cv_header_inttypes_h=yes
else
@@ -3454,15 +3627,16 @@ fi
for ac_func in times clock dup2 kill getrlimit setrlimit atoll atoq \
sysconf strsignal putc_unlocked fputc_unlocked fputs_unlocked \
- fwrite_unlocked fprintf_unlocked getrusage nl_langinfo lstat
+ fwrite_unlocked fprintf_unlocked getrusage nl_langinfo lstat \
+ scandir alphasort gettimeofday mmap
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3461: checking for $ac_func" >&5
+echo "configure:3635: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3466 "configure"
+#line 3640 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -3485,7 +3659,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:3489: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3663: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -3511,12 +3685,12 @@ done
echo $ac_n "checking for ssize_t""... $ac_c" 1>&6
-echo "configure:3515: checking for ssize_t" >&5
+echo "configure:3689: checking for ssize_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_ssize_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3520 "configure"
+#line 3694 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -3547,12 +3721,12 @@ fi
# Try to determine the array type of the second argument of getgroups
# for the target system (int or gid_t).
echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
-echo "configure:3551: checking for uid_t in sys/types.h" >&5
+echo "configure:3725: checking for uid_t in sys/types.h" >&5
if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3556 "configure"
+#line 3730 "configure"
#include "confdefs.h"
#include <sys/types.h>
EOF
@@ -3581,7 +3755,7 @@ EOF
fi
echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6
-echo "configure:3585: checking type of array argument to getgroups" >&5
+echo "configure:3759: checking type of array argument to getgroups" >&5
if eval "test \"`echo '$''{'ac_cv_type_getgroups'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3589,7 +3763,7 @@ else
ac_cv_type_getgroups=cross
else
cat > conftest.$ac_ext <<EOF
-#line 3593 "configure"
+#line 3767 "configure"
#include "confdefs.h"
/* Thanks to Mike Rendell for this test. */
@@ -3614,7 +3788,7 @@ main()
}
EOF
-if { (eval echo configure:3618: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3792: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_type_getgroups=gid_t
else
@@ -3628,7 +3802,7 @@ fi
if test $ac_cv_type_getgroups = cross; then
cat > conftest.$ac_ext <<EOF
-#line 3632 "configure"
+#line 3806 "configure"
#include "confdefs.h"
#include <unistd.h>
EOF
@@ -3669,7 +3843,7 @@ fi
echo $ac_n "checking whether the printf functions support %p""... $ac_c" 1>&6
-echo "configure:3673: checking whether the printf functions support %p" >&5
+echo "configure:3847: checking whether the printf functions support %p" >&5
if eval "test \"`echo '$''{'gcc_cv_func_printf_ptr'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -3677,7 +3851,7 @@ else
gcc_cv_func_printf_ptr=no
else
cat > conftest.$ac_ext <<EOF
-#line 3681 "configure"
+#line 3855 "configure"
#include "confdefs.h"
#include <stdio.h>
@@ -3690,7 +3864,7 @@ int main()
return (p != q);
}
EOF
-if { (eval echo configure:3694: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3868: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
gcc_cv_func_printf_ptr=yes
else
@@ -3713,6 +3887,135 @@ EOF
fi
+if test $ac_cv_header_sys_mman_h != yes \
+ || test $ac_cv_func_mmap != yes; then
+ gcc_cv_func_mmap_file=no
+ gcc_cv_func_mmap_dev_zero=no
+ gcc_cv_func_mmap_anon=no
+else
+ echo $ac_n "checking whether read-only mmap of a plain file works""... $ac_c" 1>&6
+echo "configure:3898: checking whether read-only mmap of a plain file works" >&5
+if eval "test \"`echo '$''{'gcc_cv_func_mmap_file'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # Add a system to this blacklist if
+ # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
+ # memory area containing the same data that you'd get if you applied
+ # read() to the same fd. The only system known to have a problem here
+ # is VMS, where text files have record structure.
+ case "$host_os" in
+ vms*)
+ gcc_cv_func_mmap_file=no ;;
+ *)
+ gcc_cv_func_mmap_file=yes;;
+ esac
+fi
+
+echo "$ac_t""$gcc_cv_func_mmap_file" 1>&6
+ echo $ac_n "checking whether mmap from /dev/zero works""... $ac_c" 1>&6
+echo "configure:3917: checking whether mmap from /dev/zero works" >&5
+if eval "test \"`echo '$''{'gcc_cv_func_mmap_dev_zero'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # Add a system to this blacklist if it has mmap() but /dev/zero
+ # does not exist, or if mmapping /dev/zero does not give anonymous
+ # zeroed pages with both the following properties:
+ # 1. If you map N consecutive pages in with one call, and then
+ # unmap any subset of those pages, the pages that were not
+ # explicitly unmapped remain accessible.
+ # 2. If you map two adjacent blocks of memory and then unmap them
+ # both at once, they must both go away.
+ # Systems known to be in this category are Windows (all variants),
+ # VMS, and Darwin.
+ case "$host_os" in
+ vms* | cygwin* | pe | mingw* | darwin*)
+ gcc_cv_func_mmap_dev_zero=no ;;
+ *)
+ gcc_cv_func_mmap_dev_zero=yes;;
+ esac
+fi
+
+echo "$ac_t""$gcc_cv_func_mmap_dev_zero" 1>&6
+
+ # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
+ echo $ac_n "checking for MAP_ANON(YMOUS)""... $ac_c" 1>&6
+echo "configure:3943: checking for MAP_ANON(YMOUS)" >&5
+if eval "test \"`echo '$''{'gcc_cv_decl_map_anon'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3948 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+int main() {
+int n = MAP_ANONYMOUS;
+; return 0; }
+EOF
+if { (eval echo configure:3962: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ gcc_cv_decl_map_anon=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ gcc_cv_decl_map_anon=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$gcc_cv_decl_map_anon" 1>&6
+
+ if test $gcc_cv_decl_map_anon = no; then
+ gcc_cv_func_mmap_anon=no
+ else
+ echo $ac_n "checking whether mmap with MAP_ANON(YMOUS) works""... $ac_c" 1>&6
+echo "configure:3980: checking whether mmap with MAP_ANON(YMOUS) works" >&5
+if eval "test \"`echo '$''{'gcc_cv_func_mmap_anon'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # Add a system to this blacklist if it has mmap() and MAP_ANON or
+ # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
+ # doesn't give anonymous zeroed pages with the same properties listed
+ # above for use of /dev/zero.
+ # Systems known to be in this category are Windows, VMS, and SCO Unix.
+ case "$host_os" in
+ vms* | cygwin* | pe | mingw* | sco* | udk* )
+ gcc_cv_func_mmap_anon=no ;;
+ *)
+ gcc_cv_func_mmap_anon=yes;;
+ esac
+fi
+
+echo "$ac_t""$gcc_cv_func_mmap_anon" 1>&6
+ fi
+fi
+
+if test $gcc_cv_func_mmap_file = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MMAP_FILE 1
+EOF
+
+fi
+if test $gcc_cv_func_mmap_dev_zero = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MMAP_DEV_ZERO 1
+EOF
+
+fi
+if test $gcc_cv_func_mmap_anon = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MMAP_ANON 1
+EOF
+
+fi
+
case "${host}" in
*-*-uwin*)
@@ -3728,12 +4031,12 @@ case "${host}" in
;;
esac
echo $ac_n "checking for pid_t""... $ac_c" 1>&6
-echo "configure:3732: checking for pid_t" >&5
+echo "configure:4035: checking for pid_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3737 "configure"
+#line 4040 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -3762,17 +4065,17 @@ fi
ac_safe=`echo "vfork.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for vfork.h""... $ac_c" 1>&6
-echo "configure:3766: checking for vfork.h" >&5
+echo "configure:4069: checking for vfork.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3771 "configure"
+#line 4074 "configure"
#include "confdefs.h"
#include <vfork.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:3776: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4079: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -3797,18 +4100,18 @@ else
fi
echo $ac_n "checking for working vfork""... $ac_c" 1>&6
-echo "configure:3801: checking for working vfork" >&5
+echo "configure:4104: checking for working vfork" >&5
if eval "test \"`echo '$''{'ac_cv_func_vfork_works'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test "$cross_compiling" = yes; then
echo $ac_n "checking for vfork""... $ac_c" 1>&6
-echo "configure:3807: checking for vfork" >&5
+echo "configure:4110: checking for vfork" >&5
if eval "test \"`echo '$''{'ac_cv_func_vfork'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3812 "configure"
+#line 4115 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char vfork(); below. */
@@ -3831,7 +4134,7 @@ vfork();
; return 0; }
EOF
-if { (eval echo configure:3835: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4138: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_vfork=yes"
else
@@ -3853,7 +4156,7 @@ fi
ac_cv_func_vfork_works=$ac_cv_func_vfork
else
cat > conftest.$ac_ext <<EOF
-#line 3857 "configure"
+#line 4160 "configure"
#include "confdefs.h"
/* Thanks to Paul Eggert for this test. */
#include <stdio.h>
@@ -3948,7 +4251,7 @@ main() {
}
}
EOF
-if { (eval echo configure:3952: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4255: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_func_vfork_works=yes
else
@@ -3970,472 +4273,6 @@ EOF
fi
-for ac_func in getpagesize
-do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3977: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 3982 "configure"
-#include "confdefs.h"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-$ac_func();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:4005: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-fi
-done
-
-# The test program for the next two tests is the same except for one
-# set of ifdefs.
-cat >ct-mmap.inc <<'EOF'
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <setjmp.h>
-#include <stdio.h>
-
-#if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
-# define MAP_ANONYMOUS MAP_ANON
-#endif
-
-/* This mess was copied from the GNU getpagesize.h. */
-#ifndef HAVE_GETPAGESIZE
-# ifdef HAVE_UNISTD_H
-# include <unistd.h>
-# endif
-
-/* Assume that all systems that can run configure have sys/param.h. */
-# ifndef HAVE_SYS_PARAM_H
-# define HAVE_SYS_PARAM_H 1
-# endif
-
-# ifdef _SC_PAGESIZE
-# define getpagesize() sysconf(_SC_PAGESIZE)
-# else /* no _SC_PAGESIZE */
-# ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-# ifdef EXEC_PAGESIZE
-# define getpagesize() EXEC_PAGESIZE
-# else /* no EXEC_PAGESIZE */
-# ifdef NBPG
-# define getpagesize() NBPG * CLSIZE
-# ifndef CLSIZE
-# define CLSIZE 1
-# endif /* no CLSIZE */
-# else /* no NBPG */
-# ifdef NBPC
-# define getpagesize() NBPC
-# else /* no NBPC */
-# ifdef PAGESIZE
-# define getpagesize() PAGESIZE
-# endif /* PAGESIZE */
-# endif /* no NBPC */
-# endif /* no NBPG */
-# endif /* no EXEC_PAGESIZE */
-# else /* no HAVE_SYS_PARAM_H */
-# define getpagesize() 8192 /* punt totally */
-# endif /* no HAVE_SYS_PARAM_H */
-# endif /* no _SC_PAGESIZE */
-
-#endif /* no HAVE_GETPAGESIZE */
-
-#ifndef MAP_FAILED
-# define MAP_FAILED -1
-#endif
-
-#undef perror_exit
-#define perror_exit(str, val) \
- do { perror(str); exit(val); } while (0)
-
-/* Some versions of cygwin mmap require that munmap is called with the
- same parameters as mmap. GCC expects that this is not the case.
- Test for various forms of this problem. Warning - icky signal games. */
-
-static sigset_t unblock_sigsegv;
-static jmp_buf r;
-static size_t pg;
-static int devzero;
-
-static char *
-anonmap (size)
- size_t size;
-{
-#ifdef USE_MAP_ANON
- return (char *) mmap (0, size, PROT_READ|PROT_WRITE,
- MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
-#else
- return (char *) mmap (0, size, PROT_READ|PROT_WRITE,
- MAP_PRIVATE, devzero, 0);
-#endif
-}
-
-static void
-sigsegv (unused)
- int unused;
-{
- sigprocmask (SIG_UNBLOCK, &unblock_sigsegv, 0);
- longjmp (r, 1);
-}
-
-/* Basic functionality test. */
-void
-test_0 ()
-{
- char *x = anonmap (pg);
- if (x == (char *) MAP_FAILED)
- perror_exit("test 0 mmap", 2);
-
- *(int *)x += 1;
-
- if (munmap(x, pg) < 0)
- perror_exit("test 0 munmap", 3);
-}
-
-/* 1. If we map a 2-page region and unmap its second page, the first page
- must remain. */
-static void
-test_1 ()
-{
- char *x = anonmap (pg * 2);
- if (x == (char *)MAP_FAILED)
- perror_exit ("test 1 mmap", 4);
-
- signal (SIGSEGV, sigsegv);
- if (setjmp (r))
- perror_exit ("test 1 fault", 5);
-
- x[0] = 1;
- x[pg] = 1;
-
- if (munmap (x + pg, pg) < 0)
- perror_exit ("test 1 munmap 1", 6);
- x[0] = 2;
-
- if (setjmp (r) == 0)
- {
- x[pg] = 1;
- perror_exit ("test 1 no fault", 7);
- }
- if (munmap (x, pg) < 0)
- perror_exit ("test 1 munmap 2", 8);
-}
-
-/* 2. If we map a 2-page region and unmap its first page, the second
- page must remain. */
-static void
-test_2 ()
-{
- char *x = anonmap (pg * 2);
- if (x == (char *)MAP_FAILED)
- perror_exit ("test 2 mmap", 9);
-
- signal (SIGSEGV, sigsegv);
- if (setjmp (r))
- perror_exit ("test 2 fault", 10);
-
- x[0] = 1;
- x[pg] = 1;
-
- if (munmap (x, pg) < 0)
- perror_exit ("test 2 munmap 1", 11);
-
- x[pg] = 2;
-
- if (setjmp (r) == 0)
- {
- x[0] = 1;
- perror_exit ("test 2 no fault", 12);
- }
-
- if (munmap (x+pg, pg) < 0)
- perror_exit ("test 2 munmap 2", 13);
-}
-
-/* 3. If we map two adjacent 1-page regions and unmap them both with
- one munmap, both must go away.
-
- Getting two adjacent 1-page regions with two mmap calls is slightly
- tricky. All OS's tested skip over already-allocated blocks; therefore
- we have been careful to unmap all allocated regions in previous tests.
- HP/UX allocates pages backward in memory. No OS has yet been observed
- to be so perverse as to leave unmapped space between consecutive calls
- to mmap. */
-
-static void
-test_3 ()
-{
- char *x, *y, *z;
-
- x = anonmap (pg);
- if (x == (char *)MAP_FAILED)
- perror_exit ("test 3 mmap 1", 14);
- y = anonmap (pg);
- if (y == (char *)MAP_FAILED)
- perror_exit ("test 3 mmap 2", 15);
-
- if (y != x + pg)
- {
- if (y == x - pg)
- z = y, y = x, x = z;
- else
- {
- fprintf (stderr, "test 3 nonconsecutive pages - %lx, %lx\n",
- (unsigned long)x, (unsigned long)y);
- exit (16);
- }
- }
-
- signal (SIGSEGV, sigsegv);
- if (setjmp (r))
- perror_exit ("test 3 fault", 17);
-
- x[0] = 1;
- y[0] = 1;
-
- if (munmap (x, pg*2) < 0)
- perror_exit ("test 3 munmap", 18);
-
- if (setjmp (r) == 0)
- {
- x[0] = 1;
- perror_exit ("test 3 no fault 1", 19);
- }
-
- signal (SIGSEGV, sigsegv);
- if (setjmp (r) == 0)
- {
- y[0] = 1;
- perror_exit ("test 3 no fault 2", 20);
- }
-}
-
-int
-main ()
-{
- sigemptyset (&unblock_sigsegv);
- sigaddset (&unblock_sigsegv, SIGSEGV);
- pg = getpagesize ();
-#ifndef USE_MAP_ANON
- devzero = open ("/dev/zero", O_RDWR);
- if (devzero < 0)
- perror_exit ("open /dev/zero", 1);
-#endif
-
- test_0();
- test_1();
- test_2();
- test_3();
-
- exit(0);
-}
-EOF
-
-echo $ac_n "checking for working mmap from /dev/zero""... $ac_c" 1>&6
-echo "configure:4276: checking for working mmap from /dev/zero" >&5
-if eval "test \"`echo '$''{'ac_cv_func_mmap_dev_zero'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- # If this is not cygwin, and /dev/zero is a character device, it's probably
- # safe to assume it works.
- case "$host_os" in
- cygwin* | win32 | pe | mingw* ) ac_cv_func_mmap_dev_zero=buggy ;;
- * ) if test -c /dev/zero
- then ac_cv_func_mmap_dev_zero=yes
- else ac_cv_func_mmap_dev_zero=no
- fi ;;
- esac
-else
- cat > conftest.$ac_ext <<EOF
-#line 4292 "configure"
-#include "confdefs.h"
-#include "ct-mmap.inc"
-EOF
-if { (eval echo configure:4296: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
- ac_cv_func_mmap_dev_zero=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- if test $? -lt 4
- then ac_cv_func_mmap_dev_zero=no
- else ac_cv_func_mmap_dev_zero=buggy
- fi
-fi
-rm -fr conftest*
-fi
-
-
-fi
-
-echo "$ac_t""$ac_cv_func_mmap_dev_zero" 1>&6
-if test $ac_cv_func_mmap_dev_zero = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_MMAP_DEV_ZERO 1
-EOF
-
-fi
-
-echo $ac_n "checking for working mmap with MAP_ANON(YMOUS)""... $ac_c" 1>&6
-echo "configure:4323: checking for working mmap with MAP_ANON(YMOUS)" >&5
-if eval "test \"`echo '$''{'ac_cv_func_mmap_anon'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- # Unlike /dev/zero, it is not safe to assume MAP_ANON(YMOUS) works
- # just because it's there. Some SCO Un*xen define it but don't implement it.
- ac_cv_func_mmap_anon=no
-else
- cat > conftest.$ac_ext <<EOF
-#line 4333 "configure"
-#include "confdefs.h"
-#define USE_MAP_ANON
-#include "ct-mmap.inc"
-EOF
-if { (eval echo configure:4338: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
- ac_cv_func_mmap_anon=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- if test $? -lt 4
- then ac_cv_func_mmap_anon=no
- else ac_cv_func_mmap_anon=buggy
- fi
-fi
-rm -fr conftest*
-fi
-
-
-fi
-
-echo "$ac_t""$ac_cv_func_mmap_anon" 1>&6
-if test $ac_cv_func_mmap_anon = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_MMAP_ANON 1
-EOF
-
-fi
-rm -f ct-mmap.inc
-
-echo $ac_n "checking for working mmap of a file""... $ac_c" 1>&6
-echo "configure:4366: checking for working mmap of a file" >&5
-if eval "test \"`echo '$''{'ac_cv_func_mmap_file'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- # Create a file one thousand bytes long.
-for i in 1 2 3 4 5 6 7 8 9 0
-do for j in 1 2 3 4 5 6 7 8 9 0
-do echo $i $j xxxxx
-done
-done > conftestdata$$
-
-if test "$cross_compiling" = yes; then
- ac_cv_func_mmap_file=no
-else
- cat > conftest.$ac_ext <<EOF
-#line 4381 "configure"
-#include "confdefs.h"
-
-/* Test by Zack Weinberg. Modified from MMAP_ANYWHERE test by
- Richard Henderson and Alexandre Oliva.
- Check whether read-only mmap of a plain file works. */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-
-int main()
-{
- char *x;
- int fd;
- struct stat st;
-
- fd = open("conftestdata$$", O_RDONLY);
- if (fd < 0)
- exit(1);
-
- if (fstat (fd, &st))
- exit(2);
-
- x = (char*)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (x == (char *) -1)
- exit(3);
-
- if (x[0] != '1' || x[1] != ' ' || x[2] != '1' || x[3] != ' ')
- exit(4);
-
- if (munmap(x, st.st_size) < 0)
- exit(5);
-
- exit(0);
-}
-EOF
-if { (eval echo configure:4418: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
- ac_cv_func_mmap_file=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_func_mmap_file=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$ac_cv_func_mmap_file" 1>&6
-if test $ac_cv_func_mmap_file = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_MMAP_FILE 1
-EOF
-
-fi
-
@@ -4453,7 +4290,7 @@ fi
echo $ac_n "checking for iconv""... $ac_c" 1>&6
-echo "configure:4457: checking for iconv" >&5
+echo "configure:4294: checking for iconv" >&5
if eval "test \"`echo '$''{'am_cv_func_iconv'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -4461,7 +4298,7 @@ else
am_cv_func_iconv="no, consider installing GNU libiconv"
am_cv_lib_iconv=no
cat > conftest.$ac_ext <<EOF
-#line 4465 "configure"
+#line 4302 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <iconv.h>
@@ -4471,7 +4308,7 @@ iconv_t cd = iconv_open("","");
iconv_close(cd);
; return 0; }
EOF
-if { (eval echo configure:4475: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4312: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
am_cv_func_iconv=yes
else
@@ -4483,7 +4320,7 @@ rm -f conftest*
am_save_LIBS="$LIBS"
LIBS="$LIBS $am_cv_libiconv_ldpath -liconv"
cat > conftest.$ac_ext <<EOF
-#line 4487 "configure"
+#line 4324 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <iconv.h>
@@ -4493,7 +4330,7 @@ iconv_t cd = iconv_open("","");
iconv_close(cd);
; return 0; }
EOF
-if { (eval echo configure:4497: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4334: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
am_cv_lib_iconv=yes
am_cv_func_iconv=yes
@@ -4514,13 +4351,13 @@ echo "$ac_t""$am_cv_func_iconv" 1>&6
EOF
echo $ac_n "checking for iconv declaration""... $ac_c" 1>&6
-echo "configure:4518: checking for iconv declaration" >&5
+echo "configure:4355: checking for iconv declaration" >&5
if eval "test \"`echo '$''{'am_cv_proto_iconv'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4524 "configure"
+#line 4361 "configure"
#include "confdefs.h"
#include <stdlib.h>
@@ -4539,7 +4376,7 @@ int main() {
; return 0; }
EOF
-if { (eval echo configure:4543: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4380: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
am_cv_proto_iconv_arg1=""
else
@@ -4572,17 +4409,17 @@ saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -I${srcdir} -I${srcdir}/../include"
for ac_func in getenv atol sbrk abort atof getcwd getwd \
strsignal putc_unlocked fputs_unlocked fwrite_unlocked \
- fprintf_unlocked strstr errno \
+ fprintf_unlocked strstr errno vasprintf \
malloc realloc calloc free basename getopt clock
do
ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
echo $ac_n "checking whether $ac_func is declared""... $ac_c" 1>&6
-echo "configure:4581: checking whether $ac_func is declared" >&5
+echo "configure:4418: checking whether $ac_func is declared" >&5
if eval "test \"`echo '$''{'gcc_cv_have_decl_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4586 "configure"
+#line 4423 "configure"
#include "confdefs.h"
#undef $ac_tr_decl
#define $ac_tr_decl 1
@@ -4596,7 +4433,7 @@ char *(*pfn) = (char *(*)) $ac_func ;
#endif
; return 0; }
EOF
-if { (eval echo configure:4600: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4437: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "gcc_cv_have_decl_$ac_func=yes"
else
@@ -4666,6 +4503,9 @@ EOF
cat >> confdefs.h <<\EOF
#define HAVE_DECL_ERRNO 1
EOF
+ cat >> confdefs.h <<\EOF
+#define HAVE_DECL_VASPRINTF 1
+EOF
\
cat >> confdefs.h <<\EOF
#define HAVE_DECL_MALLOC 1
@@ -4695,12 +4535,12 @@ for ac_func in getrlimit setrlimit getrusage
do
ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
echo $ac_n "checking whether $ac_func is declared""... $ac_c" 1>&6
-echo "configure:4699: checking whether $ac_func is declared" >&5
+echo "configure:4539: checking whether $ac_func is declared" >&5
if eval "test \"`echo '$''{'gcc_cv_have_decl_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4704 "configure"
+#line 4544 "configure"
#include "confdefs.h"
#undef $ac_tr_decl
#define $ac_tr_decl 1
@@ -4718,7 +4558,7 @@ char *(*pfn) = (char *(*)) $ac_func ;
#endif
; return 0; }
EOF
-if { (eval echo configure:4722: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4562: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "gcc_cv_have_decl_$ac_func=yes"
else
@@ -4756,16 +4596,43 @@ EOF
fi
+cat > conftest.$ac_ext <<EOF
+#line 4601 "configure"
+#include "confdefs.h"
+
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+int main() {
+rlim_t l = 0;
+; return 0; }
+EOF
+if { (eval echo configure:4614: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define rlim_t long
+EOF
+
+fi
+rm -f conftest*
+
for ac_func in times
do
ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
echo $ac_n "checking whether $ac_func is declared""... $ac_c" 1>&6
-echo "configure:4764: checking whether $ac_func is declared" >&5
+echo "configure:4631: checking whether $ac_func is declared" >&5
if eval "test \"`echo '$''{'gcc_cv_have_decl_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4769 "configure"
+#line 4636 "configure"
#include "confdefs.h"
#undef $ac_tr_decl
#define $ac_tr_decl 1
@@ -4783,7 +4650,7 @@ char *(*pfn) = (char *(*)) $ac_func ;
#endif
; return 0; }
EOF
-if { (eval echo configure:4787: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4654: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "gcc_cv_have_decl_$ac_func=yes"
else
@@ -4817,13 +4684,13 @@ fi
# More time-related stuff.
echo $ac_n "checking for struct tms""... $ac_c" 1>&6
-echo "configure:4821: checking for struct tms" >&5
+echo "configure:4688: checking for struct tms" >&5
if eval "test \"`echo '$''{'ac_cv_struct_tms'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4827 "configure"
+#line 4694 "configure"
#include "confdefs.h"
#include "ansidecl.h"
@@ -4836,7 +4703,7 @@ int main() {
struct tms tms;
; return 0; }
EOF
-if { (eval echo configure:4840: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4707: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_struct_tms=yes
else
@@ -4859,13 +4726,13 @@ fi
# use gcc_cv_* here because this doesn't match the behavior of AC_CHECK_TYPE.
# revisit after autoconf 2.50.
echo $ac_n "checking for clock_t""... $ac_c" 1>&6
-echo "configure:4863: checking for clock_t" >&5
+echo "configure:4730: checking for clock_t" >&5
if eval "test \"`echo '$''{'gcc_cv_type_clock_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4869 "configure"
+#line 4736 "configure"
#include "confdefs.h"
#include "ansidecl.h"
@@ -4875,7 +4742,7 @@ int main() {
clock_t x;
; return 0; }
EOF
-if { (eval echo configure:4879: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4746: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gcc_cv_type_clock_t=yes
else
@@ -4895,17 +4762,57 @@ EOF
fi
+# Check whether --enable-initfini-array or --disable-initfini-array was given.
+if test "${enable_initfini_array+set}" = set; then
+ enableval="$enable_initfini_array"
+ gcc_cv_initfinit_array=$enableval
+else
+ echo $ac_n "checking for .preinit_array/.init_array/.fini_array support""... $ac_c" 1>&6
+echo "configure:4772: checking for .preinit_array/.init_array/.fini_array support" >&5
+if eval "test \"`echo '$''{'gcc_cv_initfinit_array'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+static int x = -1;
+int main (void) { return x; }
+int foo (void) { x = 0; }
+int (*fp) (void) __attribute__ ((section (".init_array"))) = foo;
+EOF
+ if { ac_try='${CC-cc} -o conftest conftest.c 1>&AS_MESSAGE_LOG_FD'; { (eval echo configure:4782: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }
+ then
+ if ./conftest; then
+ gcc_cv_initfinit_array=yes
+ else
+ gcc_cv_initfinit_array=no
+ fi
+ else
+ gcc_cv_initfinit_array=no
+ fi
+ rm -f conftest*
+fi
+
+echo "$ac_t""$gcc_cv_initfinit_array" 1>&6
+
+ if test $gcc_cv_initfinit_array = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_INITFINI_ARRAY 1
+EOF
+
+ fi
+fi
+
+
# Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
CFLAGS="$saved_CFLAGS"
# mkdir takes a single argument on some systems.
echo $ac_n "checking if mkdir takes one argument""... $ac_c" 1>&6
-echo "configure:4904: checking if mkdir takes one argument" >&5
+echo "configure:4811: checking if mkdir takes one argument" >&5
if eval "test \"`echo '$''{'gcc_cv_mkdir_takes_one_arg'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 4909 "configure"
+#line 4816 "configure"
#include "confdefs.h"
#include <sys/types.h>
@@ -4922,7 +4829,7 @@ int main() {
mkdir ("foo", 0);
; return 0; }
EOF
-if { (eval echo configure:4926: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4833: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gcc_cv_mkdir_takes_one_arg=no
else
@@ -4949,6 +4856,7 @@ objext='.o'
+target_gtfiles=
build_xm_file=
build_xm_defines=
build_install_headers_dir=install-headers-tar
@@ -4990,21 +4898,6 @@ if test x"$dwarf2" = xyes
then tm_file="$tm_file tm-dwarf2.h"
fi
-if test x$float_format = x
-then float_format=i64
-fi
-
-if test $float_format = none
-then float_h_file=Makefile.in
-else float_h_file=float-$float_format.h
-fi
-
-# Handle cpp installation.
-if test x$enable_cpp != xno
-then
- tmake_file="$tmake_file t-install-cpp"
-fi
-
# Say what files are being used for the output code and MD file.
echo "Using \`$srcdir/config/$out_file' for machine-specific logic."
echo "Using \`$srcdir/config/$md_file' as machine description file."
@@ -5092,6 +4985,20 @@ if test x$thread_file = x; then
fi
fi
+# Look for a file containing extra machine modes.
+if test -n "$extra_modes" && test -f $srcdir/config/$extra_modes; then
+ extra_modes_file='$(srcdir)'/config/${extra_modes}
+
+ cat >> confdefs.h <<EOF
+#define EXTRA_MODES_FILE "$extra_modes"
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define EXTRA_CC_MODES 1
+EOF
+
+fi
+
# auto-host.h is the file containing items generated by autoconf and is
# the first file included by config.h.
# If host=build, it is correct to have hconfig include auto-host.h
@@ -5126,7 +5033,7 @@ else
cd ..
rm -rf $tempdir
build_auto=auto-build.h
- FORBUILD=../$build
+ FORBUILD=../$build_alias
fi
@@ -5190,14 +5097,14 @@ fi
echo $ac_n "checking for library containing strerror""... $ac_c" 1>&6
-echo "configure:5194: checking for library containing strerror" >&5
+echo "configure:5101: checking for library containing strerror" >&5
if eval "test \"`echo '$''{'ac_cv_search_strerror'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_func_search_save_LIBS="$LIBS"
ac_cv_search_strerror="no"
cat > conftest.$ac_ext <<EOF
-#line 5201 "configure"
+#line 5108 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -5208,7 +5115,7 @@ int main() {
strerror()
; return 0; }
EOF
-if { (eval echo configure:5212: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5119: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_search_strerror="none required"
else
@@ -5219,7 +5126,7 @@ rm -f conftest*
test "$ac_cv_search_strerror" = "no" && for i in cposix; do
LIBS="-l$i $ac_func_search_save_LIBS"
cat > conftest.$ac_ext <<EOF
-#line 5223 "configure"
+#line 5130 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -5230,7 +5137,7 @@ int main() {
strerror()
; return 0; }
EOF
-if { (eval echo configure:5234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5141: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_search_strerror="-l$i"
break
@@ -5253,12 +5160,12 @@ fi
echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:5257: checking for working const" >&5
+echo "configure:5164: checking for working const" >&5
if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5262 "configure"
+#line 5169 "configure"
#include "confdefs.h"
int main() {
@@ -5307,7 +5214,7 @@ ccp = (char const *const *) p;
; return 0; }
EOF
-if { (eval echo configure:5311: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5218: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_const=yes
else
@@ -5328,12 +5235,12 @@ EOF
fi
echo $ac_n "checking for off_t""... $ac_c" 1>&6
-echo "configure:5332: checking for off_t" >&5
+echo "configure:5239: checking for off_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5337 "configure"
+#line 5244 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -5361,12 +5268,12 @@ EOF
fi
echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:5365: checking for size_t" >&5
+echo "configure:5272: checking for size_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5370 "configure"
+#line 5277 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -5396,19 +5303,19 @@ fi
# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
# for constant arguments. Useless!
echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
-echo "configure:5400: checking for working alloca.h" >&5
+echo "configure:5307: checking for working alloca.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5405 "configure"
+#line 5312 "configure"
#include "confdefs.h"
#include <alloca.h>
int main() {
char *p = alloca(2 * sizeof(int));
; return 0; }
EOF
-if { (eval echo configure:5412: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5319: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_header_alloca_h=yes
else
@@ -5429,12 +5336,12 @@ EOF
fi
echo $ac_n "checking for alloca""... $ac_c" 1>&6
-echo "configure:5433: checking for alloca" >&5
+echo "configure:5340: checking for alloca" >&5
if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5438 "configure"
+#line 5345 "configure"
#include "confdefs.h"
#ifdef __GNUC__
@@ -5462,7 +5369,7 @@ int main() {
char *p = (char *) alloca(1);
; return 0; }
EOF
-if { (eval echo configure:5466: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5373: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_func_alloca_works=yes
else
@@ -5494,12 +5401,12 @@ EOF
echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
-echo "configure:5498: checking whether alloca needs Cray hooks" >&5
+echo "configure:5405: checking whether alloca needs Cray hooks" >&5
if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5503 "configure"
+#line 5410 "configure"
#include "confdefs.h"
#if defined(CRAY) && ! defined(CRAY2)
webecray
@@ -5524,12 +5431,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6
if test $ac_cv_os_cray = yes; then
for ac_func in _getb67 GETB67 getb67; do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5528: checking for $ac_func" >&5
+echo "configure:5435: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5533 "configure"
+#line 5440 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -5552,7 +5459,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:5556: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5463: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -5579,7 +5486,7 @@ done
fi
echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
-echo "configure:5583: checking stack direction for C alloca" >&5
+echo "configure:5490: checking stack direction for C alloca" >&5
if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -5587,7 +5494,7 @@ else
ac_cv_c_stack_direction=0
else
cat > conftest.$ac_ext <<EOF
-#line 5591 "configure"
+#line 5498 "configure"
#include "confdefs.h"
find_stack_direction ()
{
@@ -5606,7 +5513,7 @@ main ()
exit (find_stack_direction() < 0);
}
EOF
-if { (eval echo configure:5610: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:5517: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_stack_direction=1
else
@@ -5629,12 +5536,12 @@ fi
echo $ac_n "checking whether we are using the GNU C Library 2.1 or newer""... $ac_c" 1>&6
-echo "configure:5633: checking whether we are using the GNU C Library 2.1 or newer" >&5
+echo "configure:5540: checking whether we are using the GNU C Library 2.1 or newer" >&5
if eval "test \"`echo '$''{'ac_cv_gnu_library_2_1'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5638 "configure"
+#line 5545 "configure"
#include "confdefs.h"
#include <features.h>
@@ -5670,17 +5577,17 @@ stdlib.h string.h unistd.h sys/param.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:5674: checking for $ac_hdr" >&5
+echo "configure:5581: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5679 "configure"
+#line 5586 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:5684: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:5591: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -5711,12 +5618,12 @@ getgid getuid mempcpy munmap putenv setenv setlocale stpcpy strchr strcasecmp \
strdup strtoul tsearch __argz_count __argz_stringify __argz_next
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5715: checking for $ac_func" >&5
+echo "configure:5622: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5720 "configure"
+#line 5627 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -5739,7 +5646,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:5743: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5650: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -5780,7 +5687,7 @@ fi
echo $ac_n "checking for iconv""... $ac_c" 1>&6
-echo "configure:5784: checking for iconv" >&5
+echo "configure:5691: checking for iconv" >&5
if eval "test \"`echo '$''{'am_cv_func_iconv'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -5788,7 +5695,7 @@ else
am_cv_func_iconv="no, consider installing GNU libiconv"
am_cv_lib_iconv=no
cat > conftest.$ac_ext <<EOF
-#line 5792 "configure"
+#line 5699 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <iconv.h>
@@ -5798,7 +5705,7 @@ iconv_t cd = iconv_open("","");
iconv_close(cd);
; return 0; }
EOF
-if { (eval echo configure:5802: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
am_cv_func_iconv=yes
else
@@ -5810,7 +5717,7 @@ rm -f conftest*
am_save_LIBS="$LIBS"
LIBS="$LIBS $am_cv_libiconv_ldpath -liconv"
cat > conftest.$ac_ext <<EOF
-#line 5814 "configure"
+#line 5721 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <iconv.h>
@@ -5820,7 +5727,7 @@ iconv_t cd = iconv_open("","");
iconv_close(cd);
; return 0; }
EOF
-if { (eval echo configure:5824: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5731: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
am_cv_lib_iconv=yes
am_cv_func_iconv=yes
@@ -5841,13 +5748,13 @@ echo "$ac_t""$am_cv_func_iconv" 1>&6
EOF
echo $ac_n "checking for iconv declaration""... $ac_c" 1>&6
-echo "configure:5845: checking for iconv declaration" >&5
+echo "configure:5752: checking for iconv declaration" >&5
if eval "test \"`echo '$''{'am_cv_proto_iconv'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5851 "configure"
+#line 5758 "configure"
#include "confdefs.h"
#include <stdlib.h>
@@ -5866,7 +5773,7 @@ int main() {
; return 0; }
EOF
-if { (eval echo configure:5870: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:5777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
am_cv_proto_iconv_arg1=""
else
@@ -5895,19 +5802,19 @@ EOF
echo $ac_n "checking for nl_langinfo and CODESET""... $ac_c" 1>&6
-echo "configure:5899: checking for nl_langinfo and CODESET" >&5
+echo "configure:5806: checking for nl_langinfo and CODESET" >&5
if eval "test \"`echo '$''{'am_cv_langinfo_codeset'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5904 "configure"
+#line 5811 "configure"
#include "confdefs.h"
#include <langinfo.h>
int main() {
char* cs = nl_langinfo(CODESET);
; return 0; }
EOF
-if { (eval echo configure:5911: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5818: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
am_cv_langinfo_codeset=yes
else
@@ -5930,19 +5837,19 @@ EOF
if test $ac_cv_header_locale_h = yes; then
echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6
-echo "configure:5934: checking for LC_MESSAGES" >&5
+echo "configure:5841: checking for LC_MESSAGES" >&5
if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 5939 "configure"
+#line 5846 "configure"
#include "confdefs.h"
#include <locale.h>
int main() {
return LC_MESSAGES
; return 0; }
EOF
-if { (eval echo configure:5946: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5853: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
am_cv_val_LC_MESSAGES=yes
else
@@ -5963,7 +5870,7 @@ EOF
fi
fi
echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6
-echo "configure:5967: checking whether NLS is requested" >&5
+echo "configure:5874: checking whether NLS is requested" >&5
# Check whether --enable-nls or --disable-nls was given.
if test "${enable_nls+set}" = set; then
enableval="$enable_nls"
@@ -5986,7 +5893,7 @@ fi
EOF
echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6
-echo "configure:5990: checking whether included gettext is requested" >&5
+echo "configure:5897: checking whether included gettext is requested" >&5
# Check whether --with-included-gettext or --without-included-gettext was given.
if test "${with_included_gettext+set}" = set; then
withval="$with_included_gettext"
@@ -6006,17 +5913,17 @@ fi
ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for libintl.h""... $ac_c" 1>&6
-echo "configure:6010: checking for libintl.h" >&5
+echo "configure:5917: checking for libintl.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 6015 "configure"
+#line 5922 "configure"
#include "confdefs.h"
#include <libintl.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:6020: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:5927: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -6037,12 +5944,12 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
EOF
echo $ac_n "checking for GNU gettext in libc""... $ac_c" 1>&6
-echo "configure:6041: checking for GNU gettext in libc" >&5
+echo "configure:5948: checking for GNU gettext in libc" >&5
if eval "test \"`echo '$''{'gt_cv_func_gnugettext1_libc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 6046 "configure"
+#line 5953 "configure"
#include "confdefs.h"
#include <libintl.h>
extern int _nl_msg_cat_cntr;
@@ -6051,7 +5958,7 @@ bindtextdomain ("", "");
return (int) gettext ("") + _nl_msg_cat_cntr
; return 0; }
EOF
-if { (eval echo configure:6055: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5962: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
gt_cv_func_gnugettext1_libc=yes
else
@@ -6067,14 +5974,14 @@ echo "$ac_t""$gt_cv_func_gnugettext1_libc" 1>&6
if test "$gt_cv_func_gnugettext1_libc" != "yes"; then
echo $ac_n "checking for GNU gettext in libintl""... $ac_c" 1>&6
-echo "configure:6071: checking for GNU gettext in libintl" >&5
+echo "configure:5978: checking for GNU gettext in libintl" >&5
if eval "test \"`echo '$''{'gt_cv_func_gnugettext1_libintl'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
gt_save_LIBS="$LIBS"
LIBS="$LIBS -lintl $LIBICONV"
cat > conftest.$ac_ext <<EOF
-#line 6078 "configure"
+#line 5985 "configure"
#include "confdefs.h"
#include <libintl.h>
extern int _nl_msg_cat_cntr;
@@ -6083,7 +5990,7 @@ bindtextdomain ("", "");
return (int) gettext ("") + _nl_msg_cat_cntr
; return 0; }
EOF
-if { (eval echo configure:6087: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5994: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
gt_cv_func_gnugettext1_libintl=yes
else
@@ -6116,12 +6023,12 @@ EOF
for ac_func in dcgettext
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6120: checking for $ac_func" >&5
+echo "configure:6027: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 6125 "configure"
+#line 6032 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -6144,7 +6051,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:6148: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6055: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -6173,7 +6080,7 @@ done
# Extract the first word of "msgfmt", so it can be a program name with args.
set dummy msgfmt; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:6177: checking for $ac_word" >&5
+echo "configure:6084: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -6207,7 +6114,7 @@ fi
# Extract the first word of "gmsgfmt", so it can be a program name with args.
set dummy gmsgfmt; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:6211: checking for $ac_word" >&5
+echo "configure:6118: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -6244,7 +6151,7 @@ fi
# Extract the first word of "xgettext", so it can be a program name with args.
set dummy xgettext; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:6248: checking for $ac_word" >&5
+echo "configure:6155: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -6294,7 +6201,7 @@ fi
# Extract the first word of "msgfmt", so it can be a program name with args.
set dummy msgfmt; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:6298: checking for $ac_word" >&5
+echo "configure:6205: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -6328,7 +6235,7 @@ fi
# Extract the first word of "gmsgfmt", so it can be a program name with args.
set dummy gmsgfmt; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:6332: checking for $ac_word" >&5
+echo "configure:6239: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -6364,7 +6271,7 @@ fi
# Extract the first word of "xgettext", so it can be a program name with args.
set dummy xgettext; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:6368: checking for $ac_word" >&5
+echo "configure:6275: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -6436,7 +6343,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:6440: checking for $ac_word" >&5
+echo "configure:6347: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_INTLBISON'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -6469,7 +6376,7 @@ done
ac_verc_fail=yes
else
echo $ac_n "checking version of bison""... $ac_c" 1>&6
-echo "configure:6473: checking version of bison" >&5
+echo "configure:6380: checking version of bison" >&5
ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'`
case $ac_prog_version in
'') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
@@ -6514,7 +6421,7 @@ EOF
if test "x$CATOBJEXT" != x; then
echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6
-echo "configure:6518: checking for catalogs to be installed" >&5
+echo "configure:6425: checking for catalogs to be installed" >&5
# Look for .po and .gmo files in the source directory.
CATALOGS=
XLINGUAS=
@@ -6572,7 +6479,7 @@ fi
case $host_os in
win32 | pe | cygwin* | mingw32* | uwin*)
echo $ac_n "checking whether windows registry support is requested""... $ac_c" 1>&6
-echo "configure:6576: checking whether windows registry support is requested" >&5
+echo "configure:6483: checking whether windows registry support is requested" >&5
if test "x$enable_win32_registry" != xno; then
cat >> confdefs.h <<\EOF
#define ENABLE_WIN32_REGISTRY 1
@@ -6581,14 +6488,14 @@ EOF
echo "$ac_t""yes" 1>&6
echo $ac_n "checking for library containing RegOpenKeyExA""... $ac_c" 1>&6
-echo "configure:6585: checking for library containing RegOpenKeyExA" >&5
+echo "configure:6492: checking for library containing RegOpenKeyExA" >&5
if eval "test \"`echo '$''{'ac_cv_search_RegOpenKeyExA'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_func_search_save_LIBS="$LIBS"
ac_cv_search_RegOpenKeyExA="no"
cat > conftest.$ac_ext <<EOF
-#line 6592 "configure"
+#line 6499 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -6599,7 +6506,7 @@ int main() {
RegOpenKeyExA()
; return 0; }
EOF
-if { (eval echo configure:6603: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6510: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_search_RegOpenKeyExA="none required"
else
@@ -6610,7 +6517,7 @@ rm -f conftest*
test "$ac_cv_search_RegOpenKeyExA" = "no" && for i in advapi32; do
LIBS="-l$i $ac_func_search_save_LIBS"
cat > conftest.$ac_ext <<EOF
-#line 6614 "configure"
+#line 6521 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -6621,7 +6528,7 @@ int main() {
RegOpenKeyExA()
; return 0; }
EOF
-if { (eval echo configure:6625: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6532: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_search_RegOpenKeyExA="-l$i"
break
@@ -6663,7 +6570,7 @@ esac
if test "x$enable_win32_registry" != xno; then
echo $ac_n "checking registry key on windows hosts""... $ac_c" 1>&6
-echo "configure:6667: checking registry key on windows hosts" >&5
+echo "configure:6574: checking registry key on windows hosts" >&5
cat >> confdefs.h <<EOF
#define WIN32_REGISTRY_KEY "$gcc_cv_win32_registry_key"
EOF
@@ -6674,9 +6581,9 @@ fi
esac
# Get an absolute path to the GCC top-level source directory
-holddir=`pwd`
+holddir=`${PWDCMD-pwd}`
cd $srcdir
-topdir=`pwd`
+topdir=`${PWDCMD-pwd}`
cd $holddir
# Conditionalize the makefile for this host machine.
@@ -6738,7 +6645,7 @@ for f in $tm_file; do
ansidecl.h )
tm_file_list="${tm_file_list} \$(srcdir)/../include/ansidecl.h" ;;
defaults.h )
- tm_file_list="${tm_file_list} $f" ;;
+ tm_file_list="${tm_file_list} \$(srcdir)/$f" ;;
*) tm_file_list="${tm_file_list} \$(srcdir)/config/$f" ;;
esac
done
@@ -6753,8 +6660,10 @@ for f in $host_xm_file; do
case $f in
ansidecl.h )
host_xm_file_list="${host_xm_file_list} \$(srcdir)/../include/ansidecl.h" ;;
- auto-host.h | defaults.h )
+ auto-host.h )
host_xm_file_list="${host_xm_file_list} $f" ;;
+ defaults.h )
+ host_xm_file_list="${host_xm_file_list} \$(srcdir)/$f" ;;
*) host_xm_file_list="${host_xm_file_list} \$(srcdir)/config/$f" ;;
esac
done
@@ -6764,8 +6673,10 @@ for f in $build_xm_file; do
case $f in
ansidecl.h )
build_xm_file_list="${build_xm_file_list} \$(srcdir)/../include/ansidecl.h" ;;
- auto-build.h | auto-host.h | defaults.h )
+ auto-build.h | auto-host.h )
build_xm_file_list="${build_xm_file_list} $f" ;;
+ defaults.h )
+ host_xm_file_list="${host_xm_file_list} \$(srcdir)/$f" ;;
*) build_xm_file_list="${build_xm_file_list} \$(srcdir)/config/$f" ;;
esac
done
@@ -6780,6 +6691,11 @@ then
CROSS="-DCROSS_COMPILE"
ALL=all.cross
SYSTEM_HEADER_DIR='$(CROSS_SYSTEM_HEADER_DIR)'
+ case "$host","$target" in
+ i?86-*-*,x86_64-*-* \
+ | powerpc*-*-*,powerpc64*-*-*)
+ CROSS="$CROSS -DNATIVE_CROSS" ;;
+ esac
fi
# If this is a cross-compiler that does not
@@ -6806,8 +6722,8 @@ fi
# FIXME.
# These are the normal (build=host) settings:
-HOST_PREFIX=
-HOST_PREFIX_1=ignore-
+BUILD_PREFIX=
+BUILD_PREFIX_1=ignore-
HOST_CC='$(CC)'
HOST_CFLAGS='$(ALL_CFLAGS)'
@@ -6817,8 +6733,8 @@ STMP_FIXPROTO=stmp-fixproto
# And these apply if build != host.
if test x$build != x$host
then
- HOST_PREFIX=build-
- HOST_PREFIX_1=build-
+ BUILD_PREFIX=build-
+ BUILD_PREFIX_1=build-
HOST_CC='$(CC_FOR_BUILD)'
HOST_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD) $(XCFLAGS)'
@@ -6868,7 +6784,7 @@ fi
# Figure out what assembler we will be using.
echo $ac_n "checking what assembler to use""... $ac_c" 1>&6
-echo "configure:6872: checking what assembler to use" >&5
+echo "configure:6788: checking what assembler to use" >&5
gcc_cv_as=
gcc_cv_gas_major_version=
gcc_cv_gas_minor_version=
@@ -6962,7 +6878,7 @@ fi
# Figure out what linker we will be using.
echo $ac_n "checking what linker to use""... $ac_c" 1>&6
-echo "configure:6966: checking what linker to use" >&5
+echo "configure:6882: checking what linker to use" >&5
gcc_cv_ld=
gcc_cv_gld_major_version=
gcc_cv_gld_minor_version=
@@ -7055,7 +6971,7 @@ fi
# Figure out what nm we will be using.
echo $ac_n "checking what nm to use""... $ac_c" 1>&6
-echo "configure:7059: checking what nm to use" >&5
+echo "configure:6975: checking what nm to use" >&5
if test -x nm$host_exeext; then
gcc_cv_nm=./nm$host_exeext
elif test "x$program_prefix" != xNONE; then
@@ -7067,7 +6983,7 @@ echo "$ac_t""$gcc_cv_nm" 1>&6
# Figure out what objdump we will be using.
echo $ac_n "checking what objdump to use""... $ac_c" 1>&6
-echo "configure:7071: checking what objdump to use" >&5
+echo "configure:6987: checking what objdump to use" >&5
if test -x objdump$host_exeext; then
gcc_cv_objdump=./objdump$host_exeext
elif test "x$program_prefix" != xNONE; then
@@ -7079,7 +6995,7 @@ echo "$ac_t""$gcc_cv_objdump" 1>&6
# Figure out what assembler alignment features are present.
echo $ac_n "checking assembler alignment features""... $ac_c" 1>&6
-echo "configure:7083: checking assembler alignment features" >&5
+echo "configure:6999: checking assembler alignment features" >&5
gcc_cv_as_alignment_features=none
if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
# Gas version 2.6 and later support for .balign and .p2align.
@@ -7127,7 +7043,7 @@ fi
echo "$ac_t""$gcc_cv_as_alignment_features" 1>&6
echo $ac_n "checking assembler subsection support""... $ac_c" 1>&6
-echo "configure:7131: checking assembler subsection support" >&5
+echo "configure:7047: checking assembler subsection support" >&5
gcc_cv_as_subsections=no
if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 9 -o "$gcc_cv_gas_major_version" -gt 2 && grep 'obj_format = elf' ../gas/Makefile > /dev/null; then
@@ -7167,7 +7083,7 @@ fi
echo "$ac_t""$gcc_cv_as_subsections" 1>&6
echo $ac_n "checking assembler weak support""... $ac_c" 1>&6
-echo "configure:7171: checking assembler weak support" >&5
+echo "configure:7087: checking assembler weak support" >&5
gcc_cv_as_weak=no
if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 2 -o "$gcc_cv_gas_major_version" -gt 2; then
@@ -7190,7 +7106,7 @@ fi
echo "$ac_t""$gcc_cv_as_weak" 1>&6
echo $ac_n "checking assembler hidden support""... $ac_c" 1>&6
-echo "configure:7194: checking assembler hidden support" >&5
+echo "configure:7110: checking assembler hidden support" >&5
gcc_cv_as_hidden=no
if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
if test "$gcc_cv_gas_major_version" -eq 2 \
@@ -7211,13 +7127,13 @@ elif test x$gcc_cv_as != x; then
fi
rm -f conftest.s conftest.o conftest.nm1 conftest.nm2
- # GNU LD versions before 2.12.1 have buggy support for STV_HIDDEN.
+ # GNU LD versions before 2.12.1 have buggy support for STV_HIDDEN.
# This is irritatingly difficult to feature test for. Look for
# the date string after the version number.
ld_ver=`$gcc_cv_ld --version 2>/dev/null | head -1`
if echo "$ld_ver" | grep GNU > /dev/null; then
- ld_vers=`echo $ld_ver | sed -n 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*\(\|\.[0-9][0-9]*\(\|\.[0-9][0-9]*\)\)\)\([ ].*\|\)$,\1,p'`
- ld_date=`echo $ld_ver | sed -n 's,^.*\([2-9][0-9][0-9][0-9]\)[-]*\([01][0-9]\)[-]*\([0-3][0-9]\).*$,\1\2\3,p'`
+ ld_vers=`echo $ld_ver | sed -n 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*\(\|\.[0-9][0-9]*\(\|\.[0-9][0-9]*\)\)\)\([ ].*\|\)$,\1,p'`
+ ld_date=`echo $ld_ver | sed -n 's,^.*\([2-9][0-9][0-9][0-9]\)[-]*\([01][0-9]\)[-]*\([0-3][0-9]\).*$,\1\2\3,p'`
if test 0"$ld_date" -lt 20020404; then
if test -n "$ld_date"; then
# If there was date string, but was earlier than 2002-04-04, fail
@@ -7242,7 +7158,6 @@ elif test x$gcc_cv_as != x; then
fi
fi
fi
-
if test x"$gcc_cv_as_hidden" = xyes; then
cat >> confdefs.h <<\EOF
#define HAVE_GAS_HIDDEN 1
@@ -7251,10 +7166,23 @@ EOF
fi
echo "$ac_t""$gcc_cv_as_hidden" 1>&6
libgcc_visibility=$gcc_cv_as_hidden
+case "$target" in
+ mips-sgi-irix6*)
+ if test x"$gnu_ld_flag" = x"no"; then
+ # Even if using gas with .hidden support, the resulting object files
+ # cannot be linked with the IRIX 6 O32 linker. With the N32 and
+ # N64 linkers, the problem is that the linker refuses to accept
+ # -call_shared (passed by default to the linker) and -r (used to
+ # link the object file generated without .hidden directives with
+ # one that hides symbols), so we also lose.
+ libgcc_visibility=no
+ fi
+ ;;
+esac
echo $ac_n "checking assembler leb128 support""... $ac_c" 1>&6
-echo "configure:7258: checking assembler leb128 support" >&5
+echo "configure:7186: checking assembler leb128 support" >&5
gcc_cv_as_leb128=no
if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 11 -o "$gcc_cv_gas_major_version" -gt 2 && grep 'obj_format = elf' ../gas/Makefile > /dev/null; then
@@ -7299,7 +7227,7 @@ fi
echo "$ac_t""$gcc_cv_as_leb128" 1>&6
echo $ac_n "checking assembler eh_frame optimization""... $ac_c" 1>&6
-echo "configure:7303: checking assembler eh_frame optimization" >&5
+echo "configure:7231: checking assembler eh_frame optimization" >&5
gcc_cv_as_eh_frame=no
if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 12 -o "$gcc_cv_gas_major_version" -gt 2 && grep 'obj_format = elf' ../gas/Makefile > /dev/null; then
@@ -7380,7 +7308,7 @@ fi
echo "$ac_t""$gcc_cv_as_eh_frame" 1>&6
echo $ac_n "checking assembler section merging support""... $ac_c" 1>&6
-echo "configure:7384: checking assembler section merging support" >&5
+echo "configure:7312: checking assembler section merging support" >&5
gcc_cv_as_shf_merge=no
if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 12 -o "$gcc_cv_gas_major_version" -gt 2 && grep 'obj_format = elf' ../gas/Makefile > /dev/null; then
@@ -7402,11 +7330,151 @@ EOF
fi
echo "$ac_t""$gcc_cv_as_shf_merge" 1>&6
+echo $ac_n "checking assembler thread-local storage support""... $ac_c" 1>&6
+echo "configure:7335: checking assembler thread-local storage support" >&5
+gcc_cv_as_tls=no
+conftest_s=
+tls_first_major=
+tls_first_minor=
+case "$target" in
+ alpha*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ ldq $27,__tls_get_addr($29) !literal!1
+ lda $16,foo($29) !tlsgd!1
+ jsr $26,($27),__tls_get_addr !lituse_tlsgd!1
+ ldq $27,__tls_get_addr($29) !literal!2
+ lda $16,foo($29) !tlsldm!2
+ jsr $26,($27),__tls_get_addr !lituse_tlsldm!2
+ ldq $1,foo($29) !gotdtprel
+ ldah $2,foo($29) !dtprelhi
+ lda $3,foo($2) !dtprello
+ lda $4,foo($29) !dtprel
+ ldq $1,foo($29) !gottprel
+ ldah $2,foo($29) !tprelhi
+ lda $3,foo($2) !tprello
+ lda $4,foo($29) !tprel'
+ tls_first_major=2
+ tls_first_minor=13
+ ;;
+ i[34567]86-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ movl %gs:0, %eax
+ leal foo@TLSGD(,%ebx,1), %eax
+ leal foo@TLSLDM(%ebx), %eax
+ leal foo@DTPOFF(%eax), %edx
+ movl foo@GOTTPOFF(%ebx), %eax
+ subl foo@GOTTPOFF(%ebx), %eax
+ addl foo@GOTNTPOFF(%ebx), %eax
+ movl foo@INDNTPOFF, %eax
+ movl $foo@TPOFF, %eax
+ subl $foo@TPOFF, %eax
+ leal foo@NTPOFF(%ecx), %eax'
+ tls_first_major=2
+ tls_first_minor=14
+ ;;
+ x86_64-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ movq %fs:0, %rax
+ leaq foo@TLSGD(%rip), %rdi
+ leaq foo@TLSLD(%rip), %rdi
+ leaq foo@DTPOFF(%rax), %rdx
+ movq foo@GOTTPOFF(%rip), %rax
+ movq $foo@TPOFF, %rax'
+ tls_first_major=2
+ tls_first_minor=14
+ ;;
+ ia64-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: data8 25
+ .text
+ addl r16 = @ltoff(@dtpmod(foo#)), gp
+ addl r17 = @ltoff(@dtprel(foo#)), gp
+ addl r18 = @ltoff(@tprel(foo#)), gp
+ addl r19 = @dtprel(foo#), gp
+ adds r21 = @dtprel(foo#), r13
+ movl r23 = @dtprel(foo#)
+ addl r20 = @tprel(foo#), gp
+ adds r22 = @tprel(foo#), r13
+ movl r24 = @tprel(foo#)'
+ tls_first_major=2
+ tls_first_minor=13
+ ;;
+ s390-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ .long foo@TLSGD
+ .long foo@TLSLDM
+ .long foo@DTPOFF
+ .long foo@NTPOFF
+ .long foo@GOTNTPOFF
+ .long foo@INDNTPOFF
+ l %r1,foo@GOTNTPOFF(%r12)
+ l %r1,0(%r1):tls_load:foo
+ bas %r14,0(%r1,%r13):tls_gdcall:foo
+ bas %r14,0(%r1,%r13):tls_ldcall:foo'
+ tls_first_major=2
+ tls_first_minor=14
+ ;;
+ s390x-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ .quad foo@TLSGD
+ .quad foo@TLSLDM
+ .quad foo@DTPOFF
+ .quad foo@NTPOFF
+ .quad foo@GOTNTPOFF
+ lg %r1,foo@GOTNTPOFF(%r12)
+ larl %r1,foo@INDNTPOFF
+ brasl %r14,__tls_get_offset@PLT:tls_gdcall:foo
+ brasl %r14,__tls_get_offset@PLT:tls_ldcall:foo'
+ tls_first_major=2
+ tls_first_minor=14
+ ;;
+esac
+if test -z "$tls_first_major"; then
+ :
+elif test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x
+then
+ if test "$gcc_cv_gas_major_version" -eq "$tls_first_major" \
+ -a "$gcc_cv_gas_minor_version" -ge "$tls_first_minor" \
+ -o "$gcc_cv_gas_major_version" -gt "$tls_first_major"; then
+ gcc_cv_as_tls=yes
+ fi
+elif test x$gcc_cv_as != x; then
+ echo "$conftest_s" > conftest.s
+ if $gcc_cv_as --fatal-warnings -o conftest.o conftest.s > /dev/null 2>&1
+ then
+ gcc_cv_as_tls=yes
+ fi
+ rm -f conftest.s conftest.o
+fi
+if test "$gcc_cv_as_tls" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_AS_TLS 1
+EOF
+
+fi
+echo "$ac_t""$gcc_cv_as_tls" 1>&6
+
case "$target" in
# All TARGET_ABI_OSF targets.
alpha*-*-osf* | alpha*-*-linux* | alpha*-*-*bsd*)
echo $ac_n "checking assembler supports explicit relocations""... $ac_c" 1>&6
-echo "configure:7410: checking assembler supports explicit relocations" >&5
+echo "configure:7478: checking assembler supports explicit relocations" >&5
if eval "test \"`echo '$''{'gcc_cv_as_explicit_relocs'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -7456,7 +7524,7 @@ EOF
;;
sparc*-*-*)
echo $ac_n "checking assembler .register pseudo-op support""... $ac_c" 1>&6
-echo "configure:7460: checking assembler .register pseudo-op support" >&5
+echo "configure:7528: checking assembler .register pseudo-op support" >&5
if eval "test \"`echo '$''{'gcc_cv_as_register_pseudo_op'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -7484,7 +7552,7 @@ EOF
fi
echo $ac_n "checking assembler supports -relax""... $ac_c" 1>&6
-echo "configure:7488: checking assembler supports -relax" >&5
+echo "configure:7556: checking assembler supports -relax" >&5
if eval "test \"`echo '$''{'gcc_cv_as_relax_opt'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -7512,7 +7580,7 @@ EOF
fi
echo $ac_n "checking assembler and linker support unaligned pc related relocs""... $ac_c" 1>&6
-echo "configure:7516: checking assembler and linker support unaligned pc related relocs" >&5
+echo "configure:7584: checking assembler and linker support unaligned pc related relocs" >&5
if eval "test \"`echo '$''{'gcc_cv_as_sparc_ua_pcrel'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -7539,7 +7607,7 @@ EOF
fi
echo $ac_n "checking assembler and linker support unaligned pc related relocs against hidden symbols""... $ac_c" 1>&6
-echo "configure:7543: checking assembler and linker support unaligned pc related relocs against hidden symbols" >&5
+echo "configure:7611: checking assembler and linker support unaligned pc related relocs against hidden symbols" >&5
if eval "test \"`echo '$''{'gcc_cv_as_sparc_ua_pcrel_hidden'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -7579,7 +7647,7 @@ EOF
fi
echo $ac_n "checking for assembler offsetable %lo() support""... $ac_c" 1>&6
-echo "configure:7584: checking for assembler offsetable %lo() support" >&5
+echo "configure:7651: checking for assembler offsetable %lo() support" >&5
if eval "test \"`echo '$''{'gcc_cv_as_offsetable_lo10'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -7618,7 +7686,7 @@ EOF
i[34567]86-*-* | x86_64-*-*)
echo $ac_n "checking assembler instructions""... $ac_c" 1>&6
-echo "configure:7624: checking assembler instructions" >&5
+echo "configure:7690: checking assembler instructions" >&5
gcc_cv_as_instructions=
if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 9 -o "$gcc_cv_gas_major_version" -gt 2; then
@@ -7645,7 +7713,7 @@ EOF
echo "$ac_t""$gcc_cv_as_instructions" 1>&6
echo $ac_n "checking assembler GOTOFF in data directives""... $ac_c" 1>&6
-echo "configure:7651: checking assembler GOTOFF in data directives" >&5
+echo "configure:7717: checking assembler GOTOFF in data directives" >&5
gcc_cv_as_gotoff_in_data=no
if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x
then
@@ -7672,10 +7740,52 @@ EOF
echo "$ac_t""$gcc_cv_as_gotoff_in_data" 1>&6
;;
+
+ ia64*-*-*)
+ echo $ac_n "checking assembler supports ltoffx and ldxmov""... $ac_c" 1>&6
+echo "configure:7747: checking assembler supports ltoffx and ldxmov" >&5
+if eval "test \"`echo '$''{'gcc_cv_as_ltoffx_ldxmov_relocs'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ gcc_cv_as_ltoffx_ldxmov_relocs=unknown
+ if test x$gcc_cv_gas_major_version != x \
+ -a x$gcc_cv_gas_minor_version != x
+ then
+ if test "$gcc_cv_gas_major_version" -eq 2 \
+ -a "$gcc_cv_gas_minor_version" -ge 14 \
+ -o "$gcc_cv_gas_major_version" -gt 2; then
+ gcc_cv_as_ltoffx_ldxmov_relocs=yes
+ fi
+ elif test x$gcc_cv_as != x; then
+ cat > conftest.s << 'EOF'
+ .text
+ addl r15 = @ltoffx(x#), gp
+ ;;
+ ld8.mov r16 = [r15], x#
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ gcc_cv_as_ltoffx_ldxmov_relocs=yes
+ else
+ gcc_cv_as_ltoffx_ldxmov_relocs=no
+ fi
+ rm -f conftest.s conftest.o
+ fi
+
+fi
+
+echo "$ac_t""$gcc_cv_as_ltoffx_ldxmov_relocs" 1>&6
+ if test "x$gcc_cv_as_ltoffx_ldxmov_relocs" = xyes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_AS_LTOFFX_LDXMOV_RELOCS 1
+EOF
+
+ fi
+ ;;
esac
echo $ac_n "checking assembler dwarf2 debug_line support""... $ac_c" 1>&6
-echo "configure:7681: checking assembler dwarf2 debug_line support" >&5
+echo "configure:7789: checking assembler dwarf2 debug_line support" >&5
gcc_cv_as_dwarf2_debug_line=no
# ??? Not all targets support dwarf2 debug_line, even within a version
# of gas. Moreover, we need to emit a valid instruction to trigger any
@@ -7684,7 +7794,8 @@ gcc_cv_as_dwarf2_debug_line=no
# ??? Once 2.11 is released, probably need to add first known working
# version to the per-target configury.
case "$target" in
- i?86*-*-* | mips*-*-* | alpha*-*-* | powerpc*-*-* | sparc*-*-* | m68*-*-* | x86_64*-*-*)
+ i?86*-*-* | mips*-*-* | alpha*-*-* | powerpc*-*-* | sparc*-*-* | m68*-*-* \
+ | x86_64*-*-* | hppa*-*-* | arm*-*-* | strongarm*-*-* | xscale*-*-*)
insn="nop"
;;
ia64*-*-*)
@@ -7731,7 +7842,7 @@ fi
echo "$ac_t""$gcc_cv_as_dwarf2_debug_line" 1>&6
echo $ac_n "checking assembler --gdwarf2 support""... $ac_c" 1>&6
-echo "configure:7737: checking assembler --gdwarf2 support" >&5
+echo "configure:7846: checking assembler --gdwarf2 support" >&5
gcc_cv_as_gdwarf2_flag=no
if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x;
then
@@ -7740,7 +7851,7 @@ then
-o "$gcc_cv_gas_major_version" -gt 2 \
&& grep 'obj_format = elf' ../gas/Makefile > /dev/null \
&& test x"$insn" != x ; then
- gcc_cv_as_gdwarf2_debug_flag="yes"
+ gcc_cv_as_gdwarf2_flag="yes"
fi
elif test x$gcc_cv_as != x -a x"$insn" != x ; then
echo '' > conftest.s
@@ -7760,7 +7871,7 @@ fi
echo "$ac_t""$gcc_cv_as_gdwarf2_flag" 1>&6
echo $ac_n "checking assembler --gstabs support""... $ac_c" 1>&6
-echo "configure:7766: checking assembler --gstabs support" >&5
+echo "configure:7875: checking assembler --gstabs support" >&5
gcc_cv_as_gstabs_flag=no
if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x;
then
@@ -7769,13 +7880,20 @@ then
-o "$gcc_cv_gas_major_version" -gt 2 \
&& grep 'obj_format = elf' ../gas/Makefile > /dev/null \
&& test x"$insn" != x ; then
- gcc_cv_as_gstabs_debug_flag="yes"
+ gcc_cv_as_gstabs_flag="yes"
fi
elif test x$gcc_cv_as != x -a x"$insn" != x ; then
echo '' > conftest.s
# ??? This fails with non-gnu grep.
if $gcc_cv_as --gstabs -o conftest.o conftest.s > /dev/null 2>&1 ; then
gcc_cv_as_gstabs_flag="yes"
+ # The native Solaris 9/Intel assembler doesn't understand --gstabs
+ # and warns about it, but still exits successfully. So check for
+ # this.
+ if $gcc_cv_as --gstabs -o conftest.o conftest.s 2>&1 | \
+ grep -i warning > /dev/null ; then
+ gcc_cv_as_gstabs_flag="no"
+ fi
fi
rm -f conftest.s conftest.o
fi
@@ -7787,8 +7905,46 @@ EOF
fi
echo "$ac_t""$gcc_cv_as_gstabs_flag" 1>&6
+echo $ac_n "checking linker read-only and read-write section mixing""... $ac_c" 1>&6
+echo "configure:7910: checking linker read-only and read-write section mixing" >&5
+gcc_cv_ld_ro_rw_mix=unknown
+if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 10 -o "$gcc_cv_gld_major_version" -gt 2 && grep 'EMUL = elf' ../ld/Makefile > /dev/null; then
+ gcc_cv_ld_ro_rw_mix=read-write
+ fi
+elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then
+ echo '.section myfoosect, "a"' > conftest1.s
+ echo '.section myfoosect, "aw"' > conftest2.s
+ echo '.byte 1' >> conftest2.s
+ echo '.section myfoosect, "a"' > conftest3.s
+ echo '.byte 0' >> conftest3.s
+ if $gcc_cv_as -o conftest1.o conftest1.s > /dev/null 2>&1 \
+ && $gcc_cv_as -o conftest2.o conftest2.s > /dev/null 2>&1 \
+ && $gcc_cv_as -o conftest3.o conftest3.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -shared -o conftest1.so conftest1.o \
+ conftest2.o conftest3.o > /dev/null 2>&1; then
+ gcc_cv_ld_ro_rw_mix=`$gcc_cv_objdump -h conftest1.so \
+ | sed -e '/myfoosect/!d' -e N`
+ if echo "$gcc_cv_ld_ro_rw_mix" | grep CONTENTS > /dev/null; then
+ if echo "$gcc_cv_ld_ro_rw_mix" | grep READONLY > /dev/null; then
+ gcc_cv_ld_ro_rw_mix=read-only
+ else
+ gcc_cv_ld_ro_rw_mix=read-write
+ fi
+ fi
+ fi
+ rm -f conftest.* conftest[123].*
+fi
+if test x$gcc_cv_ld_ro_rw_mix = xread-write; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_LD_RO_RW_SECTION_MIXING 1
+EOF
+
+fi
+echo "$ac_t""$gcc_cv_ld_ro_rw_mix" 1>&6
+
echo $ac_n "checking linker PT_GNU_EH_FRAME support""... $ac_c" 1>&6
-echo "configure:7794: checking linker PT_GNU_EH_FRAME support" >&5
+echo "configure:7948: checking linker PT_GNU_EH_FRAME support" >&5
gcc_cv_ld_eh_frame_hdr=no
if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then
if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 12 -o "$gcc_cv_gld_major_version" -gt 2 && grep 'EMUL = elf' ../ld/Makefile > /dev/null; then
@@ -7800,97 +7956,48 @@ elif test x$gcc_cv_ld != x; then
gcc_cv_ld_eh_frame_hdr=yes
fi
fi
-echo "$ac_t""$gcc_cv_ld_eh_frame_hdr" 1>&6
if test x"$gcc_cv_ld_eh_frame_hdr" = xyes; then
- echo $ac_n "checking whether linker eh_frame optimizations work properly""... $ac_c" 1>&6
-echo "configure:7809: checking whether linker eh_frame optimizations work properly" >&5
- gcc_cv_ld_eh_frame_hdr_works=no
- if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then
- if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 13 -o "$gcc_cv_gld_major_version" -gt 2 && grep 'EMUL = elf' ../ld/Makefile > /dev/null; then
- gcc_cv_ld_eh_frame_hdr_works=yes
- fi
- elif test x$gcc_cv_ld != x; then
- for gcc_WS in 4 8; do
- cat > conftest.s <<EOF
- .text
-.LFB1: .skip 64
-.LFE1:
-.LFB2: .skip 64
-.LFE2:
-.LFB3: .skip 64
-.LFE3:
- .section .eh_frame,"aw",@progbits
-.Lframe1:
- .4byte .LECIE1-.LSCIE1
-.LSCIE1:
- .4byte 0x0
- .byte 0x1
- .ascii "zR\0"
- .uleb128 0x1
- .sleb128 -4
- .byte 0x8
- .uleb128 0x1
- .byte 0x50
- .byte 0xc
- .uleb128 0x4
- .uleb128 0x4
- .byte 0x88
- .uleb128 0x1
- .balign ${gcc_WS}
-.LECIE1:
-.LSFDE1:
- .4byte .LEFDE1-.LASFDE1
-.LASFDE1:
- .4byte .LASFDE1-.Lframe1
- .${gcc_WS}byte .LFB1
- .${gcc_WS}byte .LFE1-.LFB1
- .uleb128 0x0
- .balign ${gcc_WS}
-.LEFDE1:
-.LSFDE2:
- .4byte .LEFDE2-.LASFDE2
-.LASFDE2:
- .4byte .LASFDE2-.Lframe1
- .${gcc_WS}byte .LFB2
- .${gcc_WS}byte .LFE2-.LFB2
- .uleb128 0x0
- .balign ${gcc_WS}
-.LEFDE2:
-.LSFDE3:
- .4byte .LEFDE3-.LASFDE3
-.LASFDE3:
- .4byte .LASFDE3-.Lframe1
- .${gcc_WS}byte .LFB3
- .${gcc_WS}byte .LFE3-.LFB3
- .uleb128 0x0
- .balign ${gcc_WS}
-.LEFDE3:
- .4byte 0
-EOF
- if ($gcc_cv_as -o conftest.o conftest.s; exit $?) 1>&5 2>&1; then
- if ($gcc_cv_ld --eh-frame-hdr -shared -o conftest.so conftest.o; exit $?) 1>&5 2>&1; then
- if $gcc_cv_objdump -h conftest.so 2>&5 \
- | grep 'eh_frame_hdr[ ]*0*[01][048cC][ ]' 1>&5 2>&1; then
- gcc_cv_ld_eh_frame_hdr_works=yes; break
- else
- $gcc_cv_objdump -h conftest.so 2>/dev/null | grep eh_frame_hdr 1>&5 2>&1
- fi
- fi
- fi
- rm -f conftest.*
- done
- fi
- echo "$ac_t""$gcc_cv_ld_eh_frame_hdr_works" 1>&6
-fi
-if test x"$gcc_cv_ld_eh_frame_hdr" = xyes \
- && test x"$gcc_cv_ld_eh_frame_hdr_works" = xyes; then
cat >> confdefs.h <<\EOF
#define HAVE_LD_EH_FRAME_HDR 1
EOF
fi
+echo "$ac_t""$gcc_cv_ld_eh_frame_hdr" 1>&6
-if test "$prefix" != "/usr" && test "$prefix" != "/usr/local" ; then
+# Miscellaneous target-specific checks.
+case "$target" in
+ mips*-*-*)
+ echo $ac_n "checking whether libgloss uses STARTUP directives consistently""... $ac_c" 1>&6
+echo "configure:7972: checking whether libgloss uses STARTUP directives consistently" >&5
+ gcc_cv_mips_libgloss_startup=no
+ gcc_cv_libgloss_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/libgloss
+ if test "x$exec_prefix" = xNONE; then
+ if test "x$prefix" = xNONE; then
+ test_prefix=/usr/local
+ else
+ test_prefix=$prefix
+ fi
+ else
+ test_prefix=$exec_prefix
+ fi
+ for f in $gcc_cv_libgloss_srcdir/mips/idt.ld $test_prefix/$target_alias/lib/idt.ld
+ do
+ if grep '^STARTUP' $f > /dev/null 2>&1; then
+ gcc_cv_mips_libgloss_startup=yes
+ break
+ fi
+ done
+ if test x"$gcc_cv_mips_libgloss_startup" = xyes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MIPS_LIBGLOSS_STARTUP_DIRECTIVES 1
+EOF
+
+ fi
+ echo "$ac_t""$gcc_cv_mips_libgloss_startup" 1>&6
+ ;;
+esac
+
+if test "$prefix" != "/usr" && test "x$prefix" != "x$local_prefix" ; then
cat >> confdefs.h <<EOF
#define PREFIX_INCLUDE_DIR "$prefix/include"
EOF
@@ -7911,8 +8018,8 @@ if test x"${enable_languages+set}" != xset; then
enable_languages=all
fi
else
- if test x"${enable_languages}" = x ||
- test x"${enable_languages}" = xyes;
+ if test x"${enable_languages}" = x \
+ || test x"${enable_languages}" = xyes;
then
{ echo "configure: error: --enable-languages needs at least one language argument" 1>&2; exit 1; }
fi
@@ -7950,6 +8057,8 @@ do
esac
done
+expected_languages=`echo ,${enable_languages}, | sed -e 's:,: :g' -e 's: *: :g' -e 's: *: :g' -e 's:^ ::' -e 's: $::'`
+found_languages=
subdirs=
for lang in ${srcdir}/*/config-lang.in ..
do
@@ -7973,6 +8082,7 @@ do
*,all,*) add_this_lang=yes ;;
*) add_this_lang=no ;;
esac
+ found_languages="${found_languages} ${lang_alias}"
if test x"${add_this_lang}" = xyes; then
case $lang in
${srcdir}/ada/config-lang.in)
@@ -7989,6 +8099,35 @@ do
esac
done
+missing_languages=
+for expected_language in ${expected_languages} ..
+do
+ if test "${expected_language}" != ..; then
+ missing_language="${expected_language}"
+ if test "${expected_language}" = "c" \
+ || test "${expected_language}" = "all"; then
+ missing_language=
+ fi
+ for found_language in ${found_languages} ..
+ do
+ if test "${found_language}" != ..; then
+ if test "${expected_language}" = "${found_language}"; then
+ missing_language=
+ fi
+ fi
+ done
+ if test "x${missing_language}" != x; then
+ missing_languages="${missing_languages} ${missing_language}"
+ fi
+ fi
+done
+
+if test "x$missing_languages" != x; then
+ { echo "configure: error:
+The following requested languages were not found:${missing_languages}
+The following languages were available: c${found_languages}" 1>&2; exit 1; }
+fi
+
# Make gthr-default.h if we have a thread file.
gthread_flags=
if test $thread_file != single; then
@@ -8033,7 +8172,7 @@ fi
echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
-echo "configure:8039: checking whether to enable maintainer-specific portions of Makefiles" >&5
+echo "configure:8176: checking whether to enable maintainer-specific portions of Makefiles" >&5
# Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
if test "${enable_maintainer_mode+set}" = set; then
enableval="$enable_maintainer_mode"
@@ -8063,6 +8202,22 @@ EOF
fi
+# Use libunwind based exception handling.
+# Check whether --enable-libunwind-exceptions or --disable-libunwind-exceptions was given.
+if test "${enable_libunwind_exceptions+set}" = set; then
+ enableval="$enable_libunwind_exceptions"
+ use_libunwind_exceptions=$enableval
+else
+ use_libunwind_exceptions=no
+fi
+
+if test x"$use_libunwind_exceptions" = xyes; then
+ cat >> confdefs.h <<\EOF
+#define USE_LIBUNWIND_EXCEPTIONS 1
+EOF
+
+fi
+
# Make empty files to contain the specs and options for each language.
# Then add #include lines to for a compiler that has specs and/or options.
@@ -8088,9 +8243,14 @@ all_languages=
all_boot_languages=
all_compilers=
all_stagestuff=
-all_outputs='Makefile intl/Makefile fixinc/Makefile gccbug mklibgcc'
+all_outputs='Makefile intl/Makefile fixinc/Makefile gccbug mklibgcc mkheaders'
# List of language makefile fragments.
all_lang_makefiles=
+# Files for gengtype
+all_gtfiles="$target_gtfiles"
+# Files for gengtype with language
+all_gtfiles_files_langs=
+all_gtfiles_files_files=
# Add the language fragments.
# Languages are added via two mechanisms. Some information must be
@@ -8111,6 +8271,7 @@ do
compilers=
stagestuff=
outputs=
+ gtfiles=
. ${srcdir}/$s/config-lang.in
if test "x$language" = x
then
@@ -8129,9 +8290,32 @@ do
all_compilers="$all_compilers $compilers"
all_stagestuff="$all_stagestuff $stagestuff"
all_outputs="$all_outputs $outputs"
+ all_gtfiles="$all_gtfiles $gtfiles"
+ for f in .. $gtfiles
+ do
+ if test $f != ".."
+ then
+ all_gtfiles_files_langs="$all_gtfiles_files_langs ${s} "
+ all_gtfiles_files_files="$all_gtfiles_files_files ${f} "
+ fi
+ done
fi
done
+# Pick up gtfiles for c
+gtfiles=
+s="c"
+. ${srcdir}/c-config-lang.in
+all_gtfiles="$all_gtfiles $gtfiles"
+for f in .. $gtfiles
+do
+ if test $f != ".."
+ then
+ all_gtfiles_files_langs="$all_gtfiles_files_langs ${s} "
+ all_gtfiles_files_files="$all_gtfiles_files_files ${f} "
+ fi
+done
+
check_languages=
for language in .. $all_languages
do
@@ -8254,8 +8438,7 @@ fi
-# Nothing to do for FLOAT_H, float_format already handled.
-objdir=`pwd`
+objdir=`${PWDCMD-pwd}`
# Process the language and host/target makefile fragments.
@@ -8325,6 +8508,11 @@ ${CONFIG_SHELL-/bin/sh} $srcdir/configure.frag $srcdir "$subdirs" "$dep_host_xma
+
+
+
+
+
# Echo that links are built
if test x$host = x$target
then
@@ -8493,8 +8681,6 @@ s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g
-s%@enable_multilib@%$enable_multilib%g
-s%@enable_shared@%$enable_shared%g
s%@host@%$host%g
s%@host_alias@%$host_alias%g
s%@host_cpu@%$host_cpu%g
@@ -8518,6 +8704,13 @@ s%@ADAC@%$ADAC%g
s%@strict1_warn@%$strict1_warn%g
s%@CPP@%$CPP%g
s%@warn_cflags@%$warn_cflags%g
+s%@enable_multilib@%$enable_multilib%g
+s%@nocommon_flag@%$nocommon_flag%g
+s%@valgrind_path@%$valgrind_path%g
+s%@valgrind_path_defines@%$valgrind_path_defines%g
+s%@valgrind_command@%$valgrind_command%g
+s%@coverage_flags@%$coverage_flags%g
+s%@enable_shared@%$enable_shared%g
s%@stage1_cflags@%$stage1_cflags%g
s%@SET_MAKE@%$SET_MAKE%g
s%@AWK@%$AWK%g
@@ -8535,10 +8728,13 @@ s%@FLEX@%$FLEX%g
s%@BISON@%$BISON%g
s%@COLLECT2_LIBS@%$COLLECT2_LIBS%g
s%@GNAT_LIBEXC@%$GNAT_LIBEXC%g
+s%@LDEXP_LIB@%$LDEXP_LIB%g
s%@TARGET_GETGROUPS_T@%$TARGET_GETGROUPS_T%g
s%@LIBICONV@%$LIBICONV%g
+s%@gcc_cv_initfinit_array@%$gcc_cv_initfinit_array%g
s%@manext@%$manext%g
s%@objext@%$objext%g
+s%@extra_modes_file@%$extra_modes_file%g
s%@FORBUILD@%$FORBUILD%g
s%@PACKAGE@%$PACKAGE%g
s%@VERSION@%$VERSION%g
@@ -8566,8 +8762,8 @@ s%@CROSS@%$CROSS%g
s%@ALL@%$ALL%g
s%@SYSTEM_HEADER_DIR@%$SYSTEM_HEADER_DIR%g
s%@inhibit_libc@%$inhibit_libc%g
-s%@HOST_PREFIX@%$HOST_PREFIX%g
-s%@HOST_PREFIX_1@%$HOST_PREFIX_1%g
+s%@BUILD_PREFIX@%$BUILD_PREFIX%g
+s%@BUILD_PREFIX_1@%$BUILD_PREFIX_1%g
s%@HOST_CC@%$HOST_CC%g
s%@HOST_CFLAGS@%$HOST_CFLAGS%g
s%@STMP_FIXINC@%$STMP_FIXINC%g
@@ -8586,8 +8782,12 @@ s%@dollar@%$dollar%g
s%@slibdir@%$slibdir%g
s%@objdir@%$objdir%g
s%@subdirs@%$subdirs%g
+s%@srcdir@%$srcdir%g
s%@all_boot_languages@%$all_boot_languages%g
s%@all_compilers@%$all_compilers%g
+s%@all_gtfiles@%$all_gtfiles%g
+s%@all_gtfiles_files_langs@%$all_gtfiles_files_langs%g
+s%@all_gtfiles_files_files@%$all_gtfiles_files_files%g
s%@all_lang_makefiles@%$all_lang_makefiles%g
s%@all_languages@%$all_languages%g
s%@all_stagestuff@%$all_stagestuff%g
@@ -8634,6 +8834,7 @@ s%@symbolic_link@%$symbolic_link%g
s%@thread_file@%$thread_file%g
s%@tm_file_list@%$tm_file_list%g
s%@tm_file@%$tm_file%g
+s%@tm_defines@%$tm_defines%g
s%@tm_p_file_list@%$tm_p_file_list%g
s%@tm_p_file@%$tm_p_file%g
s%@xm_file@%$xm_file%g
@@ -8902,7 +9103,7 @@ esac
if test "$symbolic_link" = "ln -s"; then
for d in .. ${subdirs} fixinc ; do
if test $d != ..; then
- STARTDIR=`pwd`
+ STARTDIR=`${PWDCMD-pwd}`
cd $d
for t in stage1 stage2 stage3 stage4 include
do
diff --git a/contrib/gcc/configure.in b/contrib/gcc/configure.in
index d9a0d29..07a9b93 100644
--- a/contrib/gcc/configure.in
+++ b/contrib/gcc/configure.in
@@ -1,7 +1,8 @@
# configure.in for GCC
# Process this file with autoconf to generate a configuration script.
-# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+# Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003
+# Free Software Foundation, Inc.
#This file is part of GCC.
@@ -176,6 +177,88 @@ changequote([, ])dnl
fi
fi
+# Determine the host, build, and target systems
+AC_CANONICAL_SYSTEM
+
+# Set program_transform_name
+AC_ARG_PROGRAM
+
+# Find the native compiler
+AC_PROG_CC
+AC_PROG_CC_C_O
+# autoconf is lame and doesn't give us any substitution variable for this.
+if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" = no"; then
+ NO_MINUS_C_MINUS_O=yes
+else
+ OUTPUT_OPTION='-o $@'
+fi
+AC_SUBST(NO_MINUS_C_MINUS_O)
+AC_SUBST(OUTPUT_OPTION)
+
+# See if GNAT has been installed
+gcc_AC_PROG_GNAT
+
+AC_CACHE_CHECK(whether ${CC-cc} accepts -Wno-long-long,
+ac_cv_prog_cc_no_long_long,
+[save_CFLAGS="$CFLAGS"
+CFLAGS="-Wno-long-long"
+AC_TRY_COMPILE(,,ac_cv_prog_cc_no_long_long=yes,
+ ac_cv_prog_cc_no_long_long=no)
+CFLAGS="$save_CFLAGS"])
+
+if test x$have_gnat != xno ; then
+AC_CACHE_CHECK(whether ${ADAC} accepts -Wno-long-long,
+ac_cv_prog_adac_no_long_long,
+[cat >conftest.adb <<EOF
+procedure conftest is begin null; end conftest;
+EOF
+if $ADAC -Wno-long-long -c conftest.adb 1>&5 2>&5 ; then
+ ac_cv_prog_adac_no_long_long=yes
+else
+ ac_cv_prog_adac_no_long_long=no
+fi
+rm -f conftest*])
+else
+ ac_cv_prog_adac_no_long_long=yes
+fi
+
+strict1_warn=
+if test $ac_cv_prog_cc_no_long_long = yes && \
+ test $ac_cv_prog_adac_no_long_long = yes ; then
+ strict1_warn="-pedantic -Wno-long-long"
+fi
+AC_SUBST(strict1_warn)
+
+AC_PROG_CPP
+AC_C_INLINE
+gcc_AC_C_VOLATILE
+
+gcc_AC_C_LONG_DOUBLE
+gcc_AC_C_LONG_LONG
+gcc_AC_C__BOOL
+
+# sizeof(char) is 1 by definition.
+gcc_AC_COMPILE_CHECK_SIZEOF(short)
+gcc_AC_COMPILE_CHECK_SIZEOF(int)
+gcc_AC_COMPILE_CHECK_SIZEOF(long)
+if test $ac_cv_c_long_long = yes; then
+ gcc_AC_COMPILE_CHECK_SIZEOF(long long)
+fi
+if test $ac_cv_c___int64 = yes; then
+ gcc_AC_COMPILE_CHECK_SIZEOF(__int64)
+fi
+
+gcc_AC_C_CHARSET
+
+# If the native compiler is GCC, we can enable warnings even in stage1.
+# That's useful for people building cross-compilers, or just running a
+# quick `make'.
+warn_cflags=
+if test "x$GCC" = "xyes"; then
+ warn_cflags='$(GCC_WARN_CFLAGS)'
+fi
+AC_SUBST(warn_cflags)
+
# Determine whether or not multilibs are enabled.
AC_ARG_ENABLE(multilib,
[ --enable-multilib enable library support for multiple ABIs],
@@ -187,15 +270,17 @@ AC_ARG_ENABLE(checking,
[ --enable-checking[=LIST]
enable expensive run-time checks. With LIST,
enable only specific categories of checks.
- Categories are: misc,tree,rtl,gc,gcac; default
- is misc,tree,gc],
+ Categories are: misc,tree,rtl,rtlflag,gc,gcac;
+ default is misc,tree,gc,rtlflag],
[ac_checking=
ac_tree_checking=
ac_rtl_checking=
+ac_rtlflag_checking=
ac_gc_checking=
ac_gc_always_collect=
case "${enableval}" in
-yes) ac_checking=1 ; ac_tree_checking=1 ; ac_gc_checking=1 ;;
+yes) ac_checking=1 ; ac_tree_checking=1 ; ac_gc_checking=1 ;
+ ac_rtlflag_checking=1 ;;
no) ;;
*) IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="$IFS,"
set fnord $enableval; shift
@@ -205,9 +290,11 @@ no) ;;
case $check in
misc) ac_checking=1 ;;
tree) ac_tree_checking=1 ;;
+ rtlflag) ac_rtlflag_checking=1 ;;
rtl) ac_rtl_checking=1 ;;
gc) ac_gc_checking=1 ;;
gcac) ac_gc_always_collect=1 ;;
+ valgrind) ac_checking_valgrind=1 ;;
*) AC_MSG_ERROR(unknown check category $check) ;;
esac
done
@@ -215,11 +302,14 @@ no) ;;
esac
],
[])
+nocommon_flag=""
if test x$ac_checking != x ; then
AC_DEFINE(ENABLE_CHECKING, 1,
[Define if you want more run-time sanity checks. This one gets a grab
bag of miscellaneous but relatively cheap checks.])
+ nocommon_flag=-fno-common
fi
+AC_SUBST(nocommon_flag)
if test x$ac_tree_checking != x ; then
AC_DEFINE(ENABLE_TREE_CHECKING, 1,
[Define if you want all operations on trees (the basic data
@@ -232,6 +322,12 @@ if test x$ac_rtl_checking != x ; then
of the optimizer and back end) to be checked for dynamic type safety
at runtime. This is quite expensive.])
fi
+if test x$ac_rtlflag_checking != x ; then
+ AC_DEFINE(ENABLE_RTL_FLAG_CHECKING, 1,
+[Define if you want RTL flag accesses to be checked against the RTL
+ codes that are supported for each access macro. This is relatively
+ cheap.])
+fi
if test x$ac_gc_checking != x ; then
AC_DEFINE(ENABLE_GC_CHECKING, 1,
[Define if you want the garbage collector to do object poisoning and
@@ -243,11 +339,47 @@ if test x$ac_gc_always_collect != x ; then
paranoid mode, validating the entire heap and collecting garbage at
every opportunity. This is extremely expensive.])
fi
-
-
-AC_ARG_ENABLE(cpp,
-[ --disable-cpp don't provide a user-visible C preprocessor],
-[], [enable_cpp=yes])
+valgrind_path_defines=
+valgrind_command=
+if test x$ac_checking_valgrind != x ; then
+ # It is certainly possible that there's valgrind but no valgrind.h.
+ # GCC relies on making annotations so we must have both.
+ AC_CHECK_HEADER(valgrind.h, have_valgrind_h=yes, have_valgrind_h=no)
+ AM_PATH_PROG_WITH_TEST(valgrind_path, valgrind,
+ [$ac_dir/$ac_word --version | grep valgrind- >/dev/null 2>&1])
+ if test "x$valgrind_path" = "x" || test $have_valgrind_h = no; then
+ AC_MSG_ERROR([*** Can't find both valgrind and valgrind.h])
+ fi
+ valgrind_path_defines=-DVALGRIND_PATH='\"'$valgrind_path'\"'
+ valgrind_command="$valgrind_path -q"
+ AC_DEFINE(ENABLE_VALGRIND_CHECKING, 1,
+[Define if you want to run subprograms and generated programs
+ through valgrind (a memory checker). This is extremely expensive.])
+fi
+AC_SUBST(valgrind_path_defines)
+AC_SUBST(valgrind_command)
+
+# Enable code coverage collection
+AC_ARG_ENABLE(coverage,
+[ --enable-coverage[=LEVEL]
+ enable compiler\'s code coverage collection.
+ Use to measure compiler performance and locate
+ unused parts of the compiler. With LEVEL, specificy
+ optimization. Values are opt, noopt,
+ default is noopt],
+[case "${enableval}" in
+yes|noopt)
+ coverage_flags="-fprofile-arcs -ftest-coverage -O0"
+ ;;
+opt)
+ coverage_flags="-fprofile-arcs -ftest-coverage -O2"
+ ;;
+*)
+ AC_MSG_ERROR(unknown coverage setting $enableval)
+ ;;
+esac],
+[coverage_flags=""])
+AC_SUBST(coverage_flags)
AC_ARG_WITH(cpp_install_dir,
[ --with-cpp-install-dir=DIR
@@ -343,88 +475,6 @@ AC_ARG_ENABLE(shared,
], [enable_shared=yes])
AC_SUBST(enable_shared)
-# Determine the host, build, and target systems
-AC_CANONICAL_SYSTEM
-
-# Set program_transform_name
-AC_ARG_PROGRAM
-
-# Find the native compiler
-AC_PROG_CC
-AC_PROG_CC_C_O
-# autoconf is lame and doesn't give us any substitution variable for this.
-if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" = no"; then
- NO_MINUS_C_MINUS_O=yes
-else
- OUTPUT_OPTION='-o $@'
-fi
-AC_SUBST(NO_MINUS_C_MINUS_O)
-AC_SUBST(OUTPUT_OPTION)
-
-# See if GNAT has been installed
-gcc_AC_PROG_GNAT
-
-AC_CACHE_CHECK(whether ${CC-cc} accepts -Wno-long-long,
-ac_cv_prog_cc_no_long_long,
-[save_CFLAGS="$CFLAGS"
-CFLAGS="-Wno-long-long"
-AC_TRY_COMPILE(,,ac_cv_prog_cc_no_long_long=yes,
- ac_cv_prog_cc_no_long_long=no)
-CFLAGS="$save_CFLAGS"])
-
-if test x$have_gnat != xno ; then
-AC_CACHE_CHECK(whether ${ADAC} accepts -Wno-long-long,
-ac_cv_prog_adac_no_long_long,
-[cat >conftest.adb <<EOF
-procedure conftest is begin null; end conftest;
-EOF
-if $ADAC -Wno-long-long -c conftest.adb 1>&5 2>&5 ; then
- ac_cv_prog_adac_no_long_long=yes
-else
- ac_cv_prog_adac_no_long_long=no
-fi
-rm -f conftest*])
-else
- ac_cv_prog_adac_no_long_long=yes
-fi
-
-strict1_warn=
-if test $ac_cv_prog_cc_no_long_long = yes && \
- test $ac_cv_prog_adac_no_long_long = yes ; then
- strict1_warn="-pedantic -Wno-long-long"
-fi
-AC_SUBST(strict1_warn)
-
-AC_PROG_CPP
-AC_C_INLINE
-gcc_AC_C_VOLATILE
-
-gcc_AC_C_LONG_DOUBLE
-gcc_AC_C_LONG_LONG
-gcc_AC_C__BOOL
-
-# sizeof(char) is 1 by definition.
-gcc_AC_COMPILE_CHECK_SIZEOF(short)
-gcc_AC_COMPILE_CHECK_SIZEOF(int)
-gcc_AC_COMPILE_CHECK_SIZEOF(long)
-if test $ac_cv_c_long_long = yes; then
- gcc_AC_COMPILE_CHECK_SIZEOF(long long)
-fi
-if test $ac_cv_c___int64 = yes; then
- gcc_AC_COMPILE_CHECK_SIZEOF(__int64)
-fi
-
-gcc_AC_C_CHARSET
-
-# If the native compiler is GCC, we can enable warnings even in stage1.
-# That's useful for people building cross-compilers, or just running a
-# quick `make'.
-warn_cflags=
-if test "x$GCC" = "xyes"; then
- warn_cflags='$(GCC_WARN_CFLAGS)'
-fi
-AC_SUBST(warn_cflags)
-
# Stage specific cflags for build.
stage1_cflags=
case $build in
@@ -497,7 +547,7 @@ gcc_AC_HEADER_STDBOOL
gcc_AC_HEADER_STRING
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(limits.h stddef.h string.h strings.h stdlib.h time.h \
- fcntl.h unistd.h sys/file.h sys/time.h \
+ fcntl.h unistd.h sys/file.h sys/time.h sys/mman.h \
sys/resource.h sys/param.h sys/times.h sys/stat.h \
direct.h malloc.h langinfo.h)
@@ -523,7 +573,7 @@ else
# that we can use it.
gcc_AC_CHECK_PROG_VER(MAKEINFO, makeinfo, --version,
[GNU texinfo.* \([0-9][0-9.]*\)],
- [4.[1-9]*])
+ [4.[2-9]*])
fi
if test $gcc_cv_prog_makeinfo_modern = no; then
@@ -551,7 +601,7 @@ dnl LEXLIB is not useful in gcc.
if test -f $srcdir/../flex/skel.c; then
FLEX='$(objdir)/../flex/flex'
else
- AC_CHECK_PROG(FLEX, flex, flex, false)
+ AC_CHECK_PROG(FLEX, flex, flex, ${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing flex)
fi
# Bison?
@@ -559,7 +609,7 @@ fi
if test -f $srcdir/../bison/bison.simple; then
BISON='$(objdir)/../bison/bison -L $(srcdir)/../bison/'
else
- AC_CHECK_PROG(BISON, bison, bison, false)
+ AC_CHECK_PROG(BISON, bison, bison, ${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing bison)
fi
# These libraries may be used by collect2.
@@ -591,6 +641,15 @@ GNAT_LIBEXC="$LIBS"
LIBS="$save_LIBS"
AC_SUBST(GNAT_LIBEXC)
+# Some systems put ldexp and frexp in libm instead of libc; assume
+# they're both in the same place. jcf-dump needs them.
+save_LIBS="$LIBS"
+LIBS=
+AC_SEARCH_LIBS(ldexp, m)
+LDEXP_LIB="$LIBS"
+LIBS="$save_LIBS"
+AC_SUBST(LDEXP_LIB)
+
# See if the stage1 system preprocessor understands the ANSI C
# preprocessor stringification operator. (Used by symcat.h.)
AC_C_STRINGIZE
@@ -616,7 +675,8 @@ dnl gcc_AC_C_ENUM_BF_UNSIGNED
AC_CHECK_FUNCS(times clock dup2 kill getrlimit setrlimit atoll atoq \
sysconf strsignal putc_unlocked fputc_unlocked fputs_unlocked \
- fwrite_unlocked fprintf_unlocked getrusage nl_langinfo lstat)
+ fwrite_unlocked fprintf_unlocked getrusage nl_langinfo lstat \
+ scandir alphasort gettimeofday mmap)
AC_CHECK_TYPE(ssize_t, int)
@@ -641,6 +701,7 @@ fi
AC_SUBST(TARGET_GETGROUPS_T)
gcc_AC_FUNC_PRINTF_PTR
+gcc_AC_FUNC_MMAP_BLACKLIST
case "${host}" in
*-*-uwin*)
@@ -656,8 +717,6 @@ case "${host}" in
;;
esac
AC_FUNC_VFORK
-AC_FUNC_MMAP_ANYWHERE
-AC_FUNC_MMAP_FILE
AM_ICONV
@@ -666,7 +725,7 @@ saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -I${srcdir} -I${srcdir}/../include"
gcc_AC_CHECK_DECLS(getenv atol sbrk abort atof getcwd getwd \
strsignal putc_unlocked fputs_unlocked fwrite_unlocked \
- fprintf_unlocked strstr errno \
+ fprintf_unlocked strstr errno vasprintf \
malloc realloc calloc free basename getopt clock, , ,[
#include "ansidecl.h"
#include "system.h"])
@@ -679,6 +738,15 @@ gcc_AC_CHECK_DECLS(getrlimit setrlimit getrusage, , ,[
#endif
])
+AC_TRY_COMPILE([
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+],[rlim_t l = 0;],,[AC_DEFINE([rlim_t],[long],
+[Define to \`long' if <sys/resource.h> doesn't define.])])
+
gcc_AC_CHECK_DECLS(times, , ,[
#include "ansidecl.h"
#include "system.h"
@@ -713,6 +781,10 @@ if test $gcc_cv_type_clock_t = yes; then
[Define if <time.h> defines clock_t.])
fi
+AC_ARG_ENABLE(initfini-array,
+ [ --enable-initfini-array use .init_array/.fini_array sections],
+ gcc_cv_initfinit_array=$enableval, [gcc_AC_INITFINI_ARRAY])
+
# Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
CFLAGS="$saved_CFLAGS"
@@ -725,6 +797,7 @@ objext='.o'
AC_SUBST(manext)
AC_SUBST(objext)
+target_gtfiles=
build_xm_file=
build_xm_defines=
build_install_headers_dir=install-headers-tar
@@ -766,21 +839,6 @@ if test x"$dwarf2" = xyes
then tm_file="$tm_file tm-dwarf2.h"
fi
-if test x$float_format = x
-then float_format=i64
-fi
-
-if test $float_format = none
-then float_h_file=Makefile.in
-else float_h_file=float-$float_format.h
-fi
-
-# Handle cpp installation.
-if test x$enable_cpp != xno
-then
- tmake_file="$tmake_file t-install-cpp"
-fi
-
# Say what files are being used for the output code and MD file.
echo "Using \`$srcdir/config/$out_file' for machine-specific logic."
echo "Using \`$srcdir/config/$md_file' as machine description file."
@@ -868,6 +926,18 @@ if test x$thread_file = x; then
fi
fi
+# Look for a file containing extra machine modes.
+if test -n "$extra_modes" && test -f $srcdir/config/$extra_modes; then
+ extra_modes_file='$(srcdir)'/config/${extra_modes}
+ AC_SUBST(extra_modes_file)
+ AC_DEFINE_UNQUOTED(EXTRA_MODES_FILE, "$extra_modes",
+ [Define to the name of a file containing a list of extra machine modes
+ for this architecture.])
+ AC_DEFINE(EXTRA_CC_MODES, 1,
+ [Define if the target architecture needs extra machine modes to represent
+ the results of comparisons.])
+fi
+
# auto-host.h is the file containing items generated by autoconf and is
# the first file included by config.h.
# If host=build, it is correct to have hconfig include auto-host.h
@@ -902,7 +972,7 @@ else
cd ..
rm -rf $tempdir
build_auto=auto-build.h
- FORBUILD=../$build
+ FORBUILD=../$build_alias
fi
AC_SUBST(FORBUILD)
@@ -1010,9 +1080,9 @@ fi
esac
# Get an absolute path to the GCC top-level source directory
-holddir=`pwd`
+holddir=`${PWDCMD-pwd}`
cd $srcdir
-topdir=`pwd`
+topdir=`${PWDCMD-pwd}`
cd $holddir
# Conditionalize the makefile for this host machine.
@@ -1074,7 +1144,7 @@ for f in $tm_file; do
ansidecl.h )
tm_file_list="${tm_file_list} \$(srcdir)/../include/ansidecl.h" ;;
defaults.h )
- tm_file_list="${tm_file_list} $f" ;;
+ tm_file_list="${tm_file_list} \$(srcdir)/$f" ;;
*) tm_file_list="${tm_file_list} \$(srcdir)/config/$f" ;;
esac
done
@@ -1089,8 +1159,10 @@ for f in $host_xm_file; do
case $f in
ansidecl.h )
host_xm_file_list="${host_xm_file_list} \$(srcdir)/../include/ansidecl.h" ;;
- auto-host.h | defaults.h )
+ auto-host.h )
host_xm_file_list="${host_xm_file_list} $f" ;;
+ defaults.h )
+ host_xm_file_list="${host_xm_file_list} \$(srcdir)/$f" ;;
*) host_xm_file_list="${host_xm_file_list} \$(srcdir)/config/$f" ;;
esac
done
@@ -1100,8 +1172,10 @@ for f in $build_xm_file; do
case $f in
ansidecl.h )
build_xm_file_list="${build_xm_file_list} \$(srcdir)/../include/ansidecl.h" ;;
- auto-build.h | auto-host.h | defaults.h )
+ auto-build.h | auto-host.h )
build_xm_file_list="${build_xm_file_list} $f" ;;
+ defaults.h )
+ host_xm_file_list="${host_xm_file_list} \$(srcdir)/$f" ;;
*) build_xm_file_list="${build_xm_file_list} \$(srcdir)/config/$f" ;;
esac
done
@@ -1116,6 +1190,11 @@ then
CROSS="-DCROSS_COMPILE"
ALL=all.cross
SYSTEM_HEADER_DIR='$(CROSS_SYSTEM_HEADER_DIR)'
+ case "$host","$target" in
+ i?86-*-*,x86_64-*-* \
+ | powerpc*-*-*,powerpc64*-*-*)
+ CROSS="$CROSS -DNATIVE_CROSS" ;;
+ esac
fi
# If this is a cross-compiler that does not
@@ -1142,8 +1221,8 @@ AC_SUBST(inhibit_libc)
# FIXME.
# These are the normal (build=host) settings:
-HOST_PREFIX= AC_SUBST(HOST_PREFIX)
-HOST_PREFIX_1=ignore- AC_SUBST(HOST_PREFIX_1)
+BUILD_PREFIX= AC_SUBST(BUILD_PREFIX)
+BUILD_PREFIX_1=ignore- AC_SUBST(BUILD_PREFIX_1)
HOST_CC='$(CC)' AC_SUBST(HOST_CC)
HOST_CFLAGS='$(ALL_CFLAGS)' AC_SUBST(HOST_CFLAGS)
@@ -1153,8 +1232,8 @@ STMP_FIXPROTO=stmp-fixproto AC_SUBST(STMP_FIXPROTO)
# And these apply if build != host.
if test x$build != x$host
then
- HOST_PREFIX=build-
- HOST_PREFIX_1=build-
+ BUILD_PREFIX=build-
+ BUILD_PREFIX_1=build-
HOST_CC='$(CC_FOR_BUILD)'
HOST_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD) $(XCFLAGS)'
@@ -1531,14 +1610,14 @@ elif test x$gcc_cv_as != x; then
fi
rm -f conftest.s conftest.o conftest.nm1 conftest.nm2
- # GNU LD versions before 2.12.1 have buggy support for STV_HIDDEN.
+ # GNU LD versions before 2.12.1 have buggy support for STV_HIDDEN.
# This is irritatingly difficult to feature test for. Look for
# the date string after the version number.
ld_ver=`$gcc_cv_ld --version 2>/dev/null | head -1`
if echo "$ld_ver" | grep GNU > /dev/null; then
changequote(,)dnl
- ld_vers=`echo $ld_ver | sed -n 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*\(\|\.[0-9][0-9]*\(\|\.[0-9][0-9]*\)\)\)\([ ].*\|\)$,\1,p'`
- ld_date=`echo $ld_ver | sed -n 's,^.*\([2-9][0-9][0-9][0-9]\)[-]*\([01][0-9]\)[-]*\([0-3][0-9]\).*$,\1\2\3,p'`
+ ld_vers=`echo $ld_ver | sed -n 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*\(\|\.[0-9][0-9]*\(\|\.[0-9][0-9]*\)\)\)\([ ].*\|\)$,\1,p'`
+ ld_date=`echo $ld_ver | sed -n 's,^.*\([2-9][0-9][0-9][0-9]\)[-]*\([01][0-9]\)[-]*\([0-3][0-9]\).*$,\1\2\3,p'`
if test 0"$ld_date" -lt 20020404; then
if test -n "$ld_date"; then
# If there was date string, but was earlier than 2002-04-04, fail
@@ -1564,13 +1643,25 @@ changequote(,)dnl
changequote([,])dnl
fi
fi
-
if test x"$gcc_cv_as_hidden" = xyes; then
AC_DEFINE(HAVE_GAS_HIDDEN, 1,
[Define if your assembler supports .hidden.])
fi
AC_MSG_RESULT($gcc_cv_as_hidden)
libgcc_visibility=$gcc_cv_as_hidden
+case "$target" in
+ mips-sgi-irix6*)
+ if test x"$gnu_ld_flag" = x"no"; then
+ # Even if using gas with .hidden support, the resulting object files
+ # cannot be linked with the IRIX 6 O32 linker. With the N32 and
+ # N64 linkers, the problem is that the linker refuses to accept
+ # -call_shared (passed by default to the linker) and -r (used to
+ # link the object file generated without .hidden directives with
+ # one that hides symbols), so we also lose.
+ libgcc_visibility=no
+ fi
+ ;;
+esac
AC_SUBST(libgcc_visibility)
AC_MSG_CHECKING(assembler leb128 support)
@@ -1715,6 +1806,145 @@ if test x"$gcc_cv_as_shf_merge" = xyes; then
fi
AC_MSG_RESULT($gcc_cv_as_shf_merge)
+AC_MSG_CHECKING(assembler thread-local storage support)
+gcc_cv_as_tls=no
+conftest_s=
+tls_first_major=
+tls_first_minor=
+case "$target" in
+changequote(,)dnl
+ alpha*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ ldq $27,__tls_get_addr($29) !literal!1
+ lda $16,foo($29) !tlsgd!1
+ jsr $26,($27),__tls_get_addr !lituse_tlsgd!1
+ ldq $27,__tls_get_addr($29) !literal!2
+ lda $16,foo($29) !tlsldm!2
+ jsr $26,($27),__tls_get_addr !lituse_tlsldm!2
+ ldq $1,foo($29) !gotdtprel
+ ldah $2,foo($29) !dtprelhi
+ lda $3,foo($2) !dtprello
+ lda $4,foo($29) !dtprel
+ ldq $1,foo($29) !gottprel
+ ldah $2,foo($29) !tprelhi
+ lda $3,foo($2) !tprello
+ lda $4,foo($29) !tprel'
+ tls_first_major=2
+ tls_first_minor=13
+ ;;
+ i[34567]86-*-*)
+changequote([,])dnl
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ movl %gs:0, %eax
+ leal foo@TLSGD(,%ebx,1), %eax
+ leal foo@TLSLDM(%ebx), %eax
+ leal foo@DTPOFF(%eax), %edx
+ movl foo@GOTTPOFF(%ebx), %eax
+ subl foo@GOTTPOFF(%ebx), %eax
+ addl foo@GOTNTPOFF(%ebx), %eax
+ movl foo@INDNTPOFF, %eax
+ movl $foo@TPOFF, %eax
+ subl $foo@TPOFF, %eax
+ leal foo@NTPOFF(%ecx), %eax'
+ tls_first_major=2
+ tls_first_minor=14
+ ;;
+ x86_64-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ movq %fs:0, %rax
+ leaq foo@TLSGD(%rip), %rdi
+ leaq foo@TLSLD(%rip), %rdi
+ leaq foo@DTPOFF(%rax), %rdx
+ movq foo@GOTTPOFF(%rip), %rax
+ movq $foo@TPOFF, %rax'
+ tls_first_major=2
+ tls_first_minor=14
+ ;;
+ ia64-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: data8 25
+ .text
+ addl r16 = @ltoff(@dtpmod(foo#)), gp
+ addl r17 = @ltoff(@dtprel(foo#)), gp
+ addl r18 = @ltoff(@tprel(foo#)), gp
+ addl r19 = @dtprel(foo#), gp
+ adds r21 = @dtprel(foo#), r13
+ movl r23 = @dtprel(foo#)
+ addl r20 = @tprel(foo#), gp
+ adds r22 = @tprel(foo#), r13
+ movl r24 = @tprel(foo#)'
+ tls_first_major=2
+ tls_first_minor=13
+ ;;
+ s390-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ .long foo@TLSGD
+ .long foo@TLSLDM
+ .long foo@DTPOFF
+ .long foo@NTPOFF
+ .long foo@GOTNTPOFF
+ .long foo@INDNTPOFF
+ l %r1,foo@GOTNTPOFF(%r12)
+ l %r1,0(%r1):tls_load:foo
+ bas %r14,0(%r1,%r13):tls_gdcall:foo
+ bas %r14,0(%r1,%r13):tls_ldcall:foo'
+ tls_first_major=2
+ tls_first_minor=14
+ ;;
+ s390x-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ .quad foo@TLSGD
+ .quad foo@TLSLDM
+ .quad foo@DTPOFF
+ .quad foo@NTPOFF
+ .quad foo@GOTNTPOFF
+ lg %r1,foo@GOTNTPOFF(%r12)
+ larl %r1,foo@INDNTPOFF
+ brasl %r14,__tls_get_offset@PLT:tls_gdcall:foo
+ brasl %r14,__tls_get_offset@PLT:tls_ldcall:foo'
+ tls_first_major=2
+ tls_first_minor=14
+ ;;
+esac
+if test -z "$tls_first_major"; then
+ :
+elif test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x
+then
+ if test "$gcc_cv_gas_major_version" -eq "$tls_first_major" \
+ -a "$gcc_cv_gas_minor_version" -ge "$tls_first_minor" \
+ -o "$gcc_cv_gas_major_version" -gt "$tls_first_major"; then
+ gcc_cv_as_tls=yes
+ fi
+elif test x$gcc_cv_as != x; then
+ echo "$conftest_s" > conftest.s
+ if $gcc_cv_as --fatal-warnings -o conftest.o conftest.s > /dev/null 2>&1
+ then
+ gcc_cv_as_tls=yes
+ fi
+ rm -f conftest.s conftest.o
+fi
+if test "$gcc_cv_as_tls" = yes; then
+ AC_DEFINE(HAVE_AS_TLS, 1,
+ [Define if your assembler supports thread-local storage.])
+fi
+AC_MSG_RESULT($gcc_cv_as_tls)
+
case "$target" in
# All TARGET_ABI_OSF targets.
alpha*-*-osf* | alpha*-*-linux* | alpha*-*-*bsd*)
@@ -1927,6 +2157,41 @@ EOF
[Define true if the assembler supports '.long foo@GOTOFF'.])
AC_MSG_RESULT($gcc_cv_as_gotoff_in_data)
;;
+
+ ia64*-*-*)
+ AC_CACHE_CHECK([assembler supports ltoffx and ldxmov],
+ gcc_cv_as_ltoffx_ldxmov_relocs, [
+ gcc_cv_as_ltoffx_ldxmov_relocs=unknown
+ if test x$gcc_cv_gas_major_version != x \
+ -a x$gcc_cv_gas_minor_version != x
+ then
+ if test "$gcc_cv_gas_major_version" -eq 2 \
+ -a "$gcc_cv_gas_minor_version" -ge 14 \
+ -o "$gcc_cv_gas_major_version" -gt 2; then
+ gcc_cv_as_ltoffx_ldxmov_relocs=yes
+ fi
+ elif test x$gcc_cv_as != x; then
+ cat > conftest.s << 'EOF'
+changequote(,)dnl
+ .text
+ addl r15 = @ltoffx(x#), gp
+ ;;
+ ld8.mov r16 = [r15], x#
+EOF
+changequote([,])dnl
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ gcc_cv_as_ltoffx_ldxmov_relocs=yes
+ else
+ gcc_cv_as_ltoffx_ldxmov_relocs=no
+ fi
+ rm -f conftest.s conftest.o
+ fi
+ ])
+ if test "x$gcc_cv_as_ltoffx_ldxmov_relocs" = xyes; then
+ AC_DEFINE(HAVE_AS_LTOFFX_LDXMOV_RELOCS, 1,
+ [Define if your assembler supports ltoffx and ldxmov relocations.])
+ fi
+ ;;
esac
AC_MSG_CHECKING(assembler dwarf2 debug_line support)
@@ -1938,7 +2203,8 @@ gcc_cv_as_dwarf2_debug_line=no
# ??? Once 2.11 is released, probably need to add first known working
# version to the per-target configury.
case "$target" in
- i?86*-*-* | mips*-*-* | alpha*-*-* | powerpc*-*-* | sparc*-*-* | m68*-*-* | x86_64*-*-*)
+ i?86*-*-* | mips*-*-* | alpha*-*-* | powerpc*-*-* | sparc*-*-* | m68*-*-* \
+ | x86_64*-*-* | hppa*-*-* | arm*-*-* | strongarm*-*-* | xscale*-*-*)
insn="nop"
;;
ia64*-*-*)
@@ -1992,7 +2258,7 @@ then
-o "$gcc_cv_gas_major_version" -gt 2 \
&& grep 'obj_format = elf' ../gas/Makefile > /dev/null \
&& test x"$insn" != x ; then
- gcc_cv_as_gdwarf2_debug_flag="yes"
+ gcc_cv_as_gdwarf2_flag="yes"
fi
elif test x$gcc_cv_as != x -a x"$insn" != x ; then
echo '' > conftest.s
@@ -2018,13 +2284,20 @@ then
-o "$gcc_cv_gas_major_version" -gt 2 \
&& grep 'obj_format = elf' ../gas/Makefile > /dev/null \
&& test x"$insn" != x ; then
- gcc_cv_as_gstabs_debug_flag="yes"
+ gcc_cv_as_gstabs_flag="yes"
fi
elif test x$gcc_cv_as != x -a x"$insn" != x ; then
echo '' > conftest.s
# ??? This fails with non-gnu grep.
if $gcc_cv_as --gstabs -o conftest.o conftest.s > /dev/null 2>&1 ; then
gcc_cv_as_gstabs_flag="yes"
+ # The native Solaris 9/Intel assembler doesn't understand --gstabs
+ # and warns about it, but still exits successfully. So check for
+ # this.
+ if $gcc_cv_as --gstabs -o conftest.o conftest.s 2>&1 | \
+ grep -i warning > /dev/null ; then
+ gcc_cv_as_gstabs_flag="no"
+ fi
fi
rm -f conftest.s conftest.o
fi
@@ -2034,6 +2307,44 @@ if test x"$gcc_cv_as_gstabs_flag" = xyes; then
fi
AC_MSG_RESULT($gcc_cv_as_gstabs_flag)
+AC_MSG_CHECKING(linker read-only and read-write section mixing)
+gcc_cv_ld_ro_rw_mix=unknown
+if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 10 -o "$gcc_cv_gld_major_version" -gt 2 && grep 'EMUL = elf' ../ld/Makefile > /dev/null; then
+ gcc_cv_ld_ro_rw_mix=read-write
+ fi
+elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then
+ echo '.section myfoosect, "a"' > conftest1.s
+ echo '.section myfoosect, "aw"' > conftest2.s
+ echo '.byte 1' >> conftest2.s
+ echo '.section myfoosect, "a"' > conftest3.s
+ echo '.byte 0' >> conftest3.s
+ if $gcc_cv_as -o conftest1.o conftest1.s > /dev/null 2>&1 \
+ && $gcc_cv_as -o conftest2.o conftest2.s > /dev/null 2>&1 \
+ && $gcc_cv_as -o conftest3.o conftest3.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -shared -o conftest1.so conftest1.o \
+ conftest2.o conftest3.o > /dev/null 2>&1; then
+ gcc_cv_ld_ro_rw_mix=`$gcc_cv_objdump -h conftest1.so \
+ | sed -e '/myfoosect/!d' -e N`
+ if echo "$gcc_cv_ld_ro_rw_mix" | grep CONTENTS > /dev/null; then
+ if echo "$gcc_cv_ld_ro_rw_mix" | grep READONLY > /dev/null; then
+ gcc_cv_ld_ro_rw_mix=read-only
+ else
+ gcc_cv_ld_ro_rw_mix=read-write
+ fi
+ fi
+ fi
+changequote(,)dnl
+ rm -f conftest.* conftest[123].*
+changequote([,])dnl
+fi
+if test x$gcc_cv_ld_ro_rw_mix = xread-write; then
+ AC_DEFINE(HAVE_LD_RO_RW_SECTION_MIXING, 1,
+ [Define if your linker links a mix of read-only
+ and read-write sections into a read-write section.])
+fi
+AC_MSG_RESULT($gcc_cv_ld_ro_rw_mix)
+
AC_MSG_CHECKING(linker PT_GNU_EH_FRAME support)
gcc_cv_ld_eh_frame_hdr=no
if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then
@@ -2046,96 +2357,43 @@ elif test x$gcc_cv_ld != x; then
gcc_cv_ld_eh_frame_hdr=yes
fi
fi
-AC_MSG_RESULT($gcc_cv_ld_eh_frame_hdr)
if test x"$gcc_cv_ld_eh_frame_hdr" = xyes; then
- AC_MSG_CHECKING(whether linker eh_frame optimizations work properly)
- gcc_cv_ld_eh_frame_hdr_works=no
- if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then
- if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 13 -o "$gcc_cv_gld_major_version" -gt 2 && grep 'EMUL = elf' ../ld/Makefile > /dev/null; then
- gcc_cv_ld_eh_frame_hdr_works=yes
- fi
- elif test x$gcc_cv_ld != x; then
- for gcc_WS in 4 8; do
- cat > conftest.s <<EOF
- .text
-.LFB1: .skip 64
-.LFE1:
-.LFB2: .skip 64
-.LFE2:
-.LFB3: .skip 64
-.LFE3:
- .section .eh_frame,"aw",@progbits
-.Lframe1:
- .4byte .LECIE1-.LSCIE1
-.LSCIE1:
- .4byte 0x0
- .byte 0x1
- .ascii "zR\0"
- .uleb128 0x1
- .sleb128 -4
- .byte 0x8
- .uleb128 0x1
- .byte 0x50
- .byte 0xc
- .uleb128 0x4
- .uleb128 0x4
- .byte 0x88
- .uleb128 0x1
- .balign ${gcc_WS}
-.LECIE1:
-.LSFDE1:
- .4byte .LEFDE1-.LASFDE1
-.LASFDE1:
- .4byte .LASFDE1-.Lframe1
- .${gcc_WS}byte .LFB1
- .${gcc_WS}byte .LFE1-.LFB1
- .uleb128 0x0
- .balign ${gcc_WS}
-.LEFDE1:
-.LSFDE2:
- .4byte .LEFDE2-.LASFDE2
-.LASFDE2:
- .4byte .LASFDE2-.Lframe1
- .${gcc_WS}byte .LFB2
- .${gcc_WS}byte .LFE2-.LFB2
- .uleb128 0x0
- .balign ${gcc_WS}
-.LEFDE2:
-.LSFDE3:
- .4byte .LEFDE3-.LASFDE3
-.LASFDE3:
- .4byte .LASFDE3-.Lframe1
- .${gcc_WS}byte .LFB3
- .${gcc_WS}byte .LFE3-.LFB3
- .uleb128 0x0
- .balign ${gcc_WS}
-.LEFDE3:
- .4byte 0
-EOF
- if ($gcc_cv_as -o conftest.o conftest.s; exit $?) 1>&AC_FD_CC 2>&1; then
- if ($gcc_cv_ld --eh-frame-hdr -shared -o conftest.so conftest.o; exit $?) 1>&AC_FD_CC 2>&1; then
-changequote(,)dnl
- if $gcc_cv_objdump -h conftest.so 2>&AC_FD_CC \
- | grep 'eh_frame_hdr[ ]*0*[01][048cC][ ]' 1>&AC_FD_CC 2>&1; then
- gcc_cv_ld_eh_frame_hdr_works=yes; break
- else
- $gcc_cv_objdump -h conftest.so 2>/dev/null | grep eh_frame_hdr 1>&AC_FD_CC 2>&1
- fi
-changequote([,])dnl
- fi
- fi
- rm -f conftest.*
- done
- fi
- AC_MSG_RESULT($gcc_cv_ld_eh_frame_hdr_works)
-fi
-if test x"$gcc_cv_ld_eh_frame_hdr" = xyes \
- && test x"$gcc_cv_ld_eh_frame_hdr_works" = xyes; then
AC_DEFINE(HAVE_LD_EH_FRAME_HDR, 1,
[Define if your linker supports --eh-frame-hdr option.])
fi
+AC_MSG_RESULT($gcc_cv_ld_eh_frame_hdr)
+
+# Miscellaneous target-specific checks.
+case "$target" in
+ mips*-*-*)
+ AC_MSG_CHECKING(whether libgloss uses STARTUP directives consistently)
+ gcc_cv_mips_libgloss_startup=no
+ gcc_cv_libgloss_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/libgloss
+ if test "x$exec_prefix" = xNONE; then
+ if test "x$prefix" = xNONE; then
+ test_prefix=/usr/local
+ else
+ test_prefix=$prefix
+ fi
+ else
+ test_prefix=$exec_prefix
+ fi
+ for f in $gcc_cv_libgloss_srcdir/mips/idt.ld $test_prefix/$target_alias/lib/idt.ld
+ do
+ if grep '^STARTUP' $f > /dev/null 2>&1; then
+ gcc_cv_mips_libgloss_startup=yes
+ break
+ fi
+ done
+ if test x"$gcc_cv_mips_libgloss_startup" = xyes; then
+ AC_DEFINE(HAVE_MIPS_LIBGLOSS_STARTUP_DIRECTIVES, 1,
+ [Define if your MIPS libgloss linker scripts consistently include STARTUP directives.])
+ fi
+ AC_MSG_RESULT($gcc_cv_mips_libgloss_startup)
+ ;;
+esac
-if test "$prefix" != "/usr" && test "$prefix" != "/usr/local" ; then
+if test "$prefix" != "/usr" && test "x$prefix" != "x$local_prefix" ; then
AC_DEFINE_UNQUOTED(PREFIX_INCLUDE_DIR, "$prefix/include")
fi
@@ -2153,8 +2411,8 @@ if test x"${enable_languages+set}" != xset; then
enable_languages=all
fi
else
- if test x"${enable_languages}" = x ||
- test x"${enable_languages}" = xyes;
+ if test x"${enable_languages}" = x \
+ || test x"${enable_languages}" = xyes;
then
AC_MSG_ERROR([--enable-languages needs at least one language argument])
fi
@@ -2194,6 +2452,8 @@ changequote([,])dnl
esac
done
+expected_languages=`echo ,${enable_languages}, | sed -e 's:,: :g' -e 's: *: :g' -e 's: *: :g' -e 's:^ ::' -e 's: $::'`
+found_languages=
subdirs=
for lang in ${srcdir}/*/config-lang.in ..
do
@@ -2218,6 +2478,7 @@ changequote(,)dnl
*,all,*) add_this_lang=yes ;;
*) add_this_lang=no ;;
esac
+ found_languages="${found_languages} ${lang_alias}"
if test x"${add_this_lang}" = xyes; then
case $lang in
${srcdir}/ada/config-lang.in)
@@ -2235,6 +2496,35 @@ changequote([,])dnl
esac
done
+missing_languages=
+for expected_language in ${expected_languages} ..
+do
+ if test "${expected_language}" != ..; then
+ missing_language="${expected_language}"
+ if test "${expected_language}" = "c" \
+ || test "${expected_language}" = "all"; then
+ missing_language=
+ fi
+ for found_language in ${found_languages} ..
+ do
+ if test "${found_language}" != ..; then
+ if test "${expected_language}" = "${found_language}"; then
+ missing_language=
+ fi
+ fi
+ done
+ if test "x${missing_language}" != x; then
+ missing_languages="${missing_languages} ${missing_language}"
+ fi
+ fi
+done
+
+if test "x$missing_languages" != x; then
+ AC_MSG_ERROR([
+The following requested languages were not found:${missing_languages}
+The following languages were available: c${found_languages}])
+fi
+
# Make gthr-default.h if we have a thread file.
gthread_flags=
if test $thread_file != single; then
@@ -2299,6 +2589,16 @@ AC_ARG_ENABLE(sjlj-exceptions,
AC_DEFINE_UNQUOTED(CONFIG_SJLJ_EXCEPTIONS, $sjlj,
[Define 0/1 to force the choice for exception handling model.])])
+# Use libunwind based exception handling.
+AC_ARG_ENABLE(libunwind-exceptions,
+[ --enable-libunwind-exceptions force use libunwind for exceptions],
+use_libunwind_exceptions=$enableval,
+use_libunwind_exceptions=no)
+if test x"$use_libunwind_exceptions" = xyes; then
+ AC_DEFINE(USE_LIBUNWIND_EXCEPTIONS, 1,
+ [Define if gcc should use -lunwind.])
+fi
+
# Make empty files to contain the specs and options for each language.
# Then add #include lines to for a compiler that has specs and/or options.
@@ -2324,9 +2624,14 @@ all_languages=
all_boot_languages=
all_compilers=
all_stagestuff=
-all_outputs='Makefile intl/Makefile fixinc/Makefile gccbug mklibgcc'
+all_outputs='Makefile intl/Makefile fixinc/Makefile gccbug mklibgcc mkheaders'
# List of language makefile fragments.
all_lang_makefiles=
+# Files for gengtype
+all_gtfiles="$target_gtfiles"
+# Files for gengtype with language
+all_gtfiles_files_langs=
+all_gtfiles_files_files=
# Add the language fragments.
# Languages are added via two mechanisms. Some information must be
@@ -2347,6 +2652,7 @@ do
compilers=
stagestuff=
outputs=
+ gtfiles=
. ${srcdir}/$s/config-lang.in
if test "x$language" = x
then
@@ -2365,9 +2671,32 @@ do
all_compilers="$all_compilers $compilers"
all_stagestuff="$all_stagestuff $stagestuff"
all_outputs="$all_outputs $outputs"
+ all_gtfiles="$all_gtfiles $gtfiles"
+ for f in .. $gtfiles
+ do
+ if test $f != ".."
+ then
+ all_gtfiles_files_langs="$all_gtfiles_files_langs ${s} "
+ all_gtfiles_files_files="$all_gtfiles_files_files ${f} "
+ fi
+ done
fi
done
+# Pick up gtfiles for c
+gtfiles=
+s="c"
+. ${srcdir}/c-config-lang.in
+all_gtfiles="$all_gtfiles $gtfiles"
+for f in .. $gtfiles
+do
+ if test $f != ".."
+ then
+ all_gtfiles_files_langs="$all_gtfiles_files_langs ${s} "
+ all_gtfiles_files_files="$all_gtfiles_files_files ${f} "
+ fi
+done
+
check_languages=
for language in .. $all_languages
do
@@ -2486,8 +2815,7 @@ else
fi)
AC_SUBST(slibdir)
-# Nothing to do for FLOAT_H, float_format already handled.
-objdir=`pwd`
+objdir=`${PWDCMD-pwd}`
AC_SUBST(objdir)
# Process the language and host/target makefile fragments.
@@ -2495,8 +2823,12 @@ ${CONFIG_SHELL-/bin/sh} $srcdir/configure.frag $srcdir "$subdirs" "$dep_host_xma
# Substitute configuration variables
AC_SUBST(subdirs)
+AC_SUBST(srcdir)
AC_SUBST(all_boot_languages)
AC_SUBST(all_compilers)
+AC_SUBST(all_gtfiles)
+AC_SUBST(all_gtfiles_files_langs)
+AC_SUBST(all_gtfiles_files_files)
AC_SUBST(all_lang_makefiles)
AC_SUBST(all_languages)
AC_SUBST(all_stagestuff)
@@ -2543,6 +2875,7 @@ AC_SUBST(symbolic_link)
AC_SUBST(thread_file)
AC_SUBST(tm_file_list)
AC_SUBST(tm_file)
+AC_SUBST(tm_defines)
AC_SUBST(tm_p_file_list)
AC_SUBST(tm_p_file)
AC_SUBST(xm_file)
@@ -2608,7 +2941,7 @@ esac
if test "$symbolic_link" = "ln -s"; then
for d in .. ${subdirs} fixinc ; do
if test $d != ..; then
- STARTDIR=`pwd`
+ STARTDIR=`${PWDCMD-pwd}`
cd $d
for t in stage1 stage2 stage3 stage4 include
do
diff --git a/contrib/gcc/conflict.c b/contrib/gcc/conflict.c
index d1fb129..a6d7554 100644
--- a/contrib/gcc/conflict.c
+++ b/contrib/gcc/conflict.c
@@ -33,10 +33,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "hard-reg-set.h"
#include "basic-block.h"
-/* Use malloc to allocate obstack chunks. */
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
/* A register conflict graph is an undirected graph containing nodes
for some or all of the regs used in a function. Arcs represent
conflicts, i.e. two nodes are connected by an arc if there is a
@@ -116,7 +112,7 @@ struct conflict_graph_def
R1 and R2. R1 is assumed to be smaller or equal to R2. */
#define CONFLICT_HASH_FN(R1, R2) ((R2) * ((R2) - 1) / 2 + (R1))
-static unsigned arc_hash PARAMS ((const void *));
+static hashval_t arc_hash PARAMS ((const void *));
static int arc_eq PARAMS ((const void *, const void *));
static int print_conflict PARAMS ((int, int, void *));
static void mark_reg PARAMS ((rtx, rtx, void *));
@@ -124,7 +120,7 @@ static void mark_reg PARAMS ((rtx, rtx, void *));
/* Callback function to compute the hash value of an arc. Uses
current_graph to locate the graph to which the arc belongs. */
-static unsigned
+static hashval_t
arc_hash (arcp)
const void *arcp;
{
@@ -187,7 +183,7 @@ conflict_graph_delete (graph)
}
/* Adds a conflict to GRAPH between regs REG1 and REG2, which must be
- distinct. Returns non-zero, unless the conflict is already present
+ distinct. Returns nonzero, unless the conflict is already present
in GRAPH, in which case it does nothing and returns zero. */
int
@@ -236,7 +232,7 @@ conflict_graph_add (graph, reg1, reg2)
return 1;
}
-/* Returns non-zero if a conflict exists in GRAPH between regs REG1
+/* Returns nonzero if a conflict exists in GRAPH between regs REG1
and REG2. */
int
@@ -447,19 +443,18 @@ conflict_graph_compute (regs, p)
regset regs;
partition p;
{
- int b;
conflict_graph graph = conflict_graph_new (max_reg_num ());
regset_head live_head;
regset live = &live_head;
regset_head born_head;
regset born = &born_head;
+ basic_block bb;
INIT_REG_SET (live);
INIT_REG_SET (born);
- for (b = n_basic_blocks; --b >= 0; )
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block bb = BASIC_BLOCK (b);
rtx insn;
rtx head;
diff --git a/contrib/gcc/convert.c b/contrib/gcc/convert.c
index 156c2cf..e440e35 100644
--- a/contrib/gcc/convert.c
+++ b/contrib/gcc/convert.c
@@ -29,6 +29,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "flags.h"
#include "convert.h"
#include "toplev.h"
+#include "langhooks.h"
/* Convert EXPR to some pointer or reference type TYPE.
@@ -61,7 +62,8 @@ convert_to_pointer (type, expr)
return
convert_to_pointer (type,
- convert (type_for_size (POINTER_SIZE, 0), expr));
+ convert ((*lang_hooks.types.type_for_size)
+ (POINTER_SIZE, 0), expr));
default:
error ("cannot convert to a pointer type");
@@ -138,8 +140,8 @@ convert_to_integer (type, expr)
if (integer_zerop (expr))
expr = integer_zero_node;
else
- expr = fold (build1 (CONVERT_EXPR,
- type_for_size (POINTER_SIZE, 0), expr));
+ expr = fold (build1 (CONVERT_EXPR, (*lang_hooks.types.type_for_size)
+ (POINTER_SIZE, 0), expr));
return convert_to_integer (type, expr);
@@ -189,8 +191,8 @@ convert_to_integer (type, expr)
else if (TREE_CODE (type) == ENUMERAL_TYPE
|| outprec != GET_MODE_BITSIZE (TYPE_MODE (type)))
return build1 (NOP_EXPR, type,
- convert (type_for_mode (TYPE_MODE (type),
- TREE_UNSIGNED (type)),
+ convert ((*lang_hooks.types.type_for_mode)
+ (TYPE_MODE (type), TREE_UNSIGNED (type)),
expr));
/* Here detect when we can distribute the truncation down past some
@@ -302,8 +304,8 @@ convert_to_integer (type, expr)
/* Can't do arithmetic in enumeral types
so use an integer type that will hold the values. */
if (TREE_CODE (typex) == ENUMERAL_TYPE)
- typex = type_for_size (TYPE_PRECISION (typex),
- TREE_UNSIGNED (typex));
+ typex = (*lang_hooks.types.type_for_size)
+ (TYPE_PRECISION (typex), TREE_UNSIGNED (typex));
/* But now perhaps TYPEX is as wide as INPREC.
In that case, do nothing special here.
@@ -313,16 +315,25 @@ convert_to_integer (type, expr)
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa.
Exception: if both of the original operands were
- unsigned then we can safely do the work as unsigned;
- if we are distributing through a LSHIFT_EXPR, we must
- do the work as unsigned to avoid a signed overflow.
+ unsigned then we can safely do the work as unsigned.
+ Exception: shift operations take their type solely
+ from the first argument.
+ Exception: the LSHIFT_EXPR case above requires that
+ we perform this operation unsigned lest we produce
+ signed-overflow undefinedness.
And we may need to do it as unsigned
if we truncate to the original size. */
- typex = ((TREE_UNSIGNED (TREE_TYPE (expr))
- || (TREE_UNSIGNED (TREE_TYPE (arg0))
- && TREE_UNSIGNED (TREE_TYPE (arg1)))
- || ex_form == LSHIFT_EXPR)
- ? unsigned_type (typex) : signed_type (typex));
+ if (TREE_UNSIGNED (TREE_TYPE (expr))
+ || (TREE_UNSIGNED (TREE_TYPE (arg0))
+ && (TREE_UNSIGNED (TREE_TYPE (arg1))
+ || ex_form == LSHIFT_EXPR
+ || ex_form == RSHIFT_EXPR
+ || ex_form == LROTATE_EXPR
+ || ex_form == RROTATE_EXPR))
+ || ex_form == LSHIFT_EXPR)
+ typex = (*lang_hooks.types.unsigned_type) (typex);
+ else
+ typex = (*lang_hooks.types.signed_type) (typex);
return convert (type,
fold (build (ex_form, typex,
convert (typex, arg0),
@@ -343,8 +354,8 @@ convert_to_integer (type, expr)
/* Can't do arithmetic in enumeral types
so use an integer type that will hold the values. */
if (TREE_CODE (typex) == ENUMERAL_TYPE)
- typex = type_for_size (TYPE_PRECISION (typex),
- TREE_UNSIGNED (typex));
+ typex = (*lang_hooks.types.type_for_size)
+ (TYPE_PRECISION (typex), TREE_UNSIGNED (typex));
/* But now perhaps TYPEX is as wide as INPREC.
In that case, do nothing special here.
@@ -353,8 +364,10 @@ convert_to_integer (type, expr)
{
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa. */
- typex = (TREE_UNSIGNED (TREE_TYPE (expr))
- ? unsigned_type (typex) : signed_type (typex));
+ if (TREE_UNSIGNED (TREE_TYPE (expr)))
+ typex = (*lang_hooks.types.unsigned_type) (typex);
+ else
+ typex = (*lang_hooks.types.signed_type) (typex);
return convert (type,
fold (build1 (ex_form, typex,
convert (typex,
@@ -363,6 +376,12 @@ convert_to_integer (type, expr)
}
case NOP_EXPR:
+ /* Don't introduce a
+ "can't convert between vector values of different size" error. */
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == VECTOR_TYPE
+ && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (expr, 0))))
+ != GET_MODE_SIZE (TYPE_MODE (type))))
+ break;
/* If truncating after truncating, might as well do all at once.
If truncating after extending, we may get rid of wasted work. */
return convert (type, get_unwidened (TREE_OPERAND (expr, 0), type));
diff --git a/contrib/gcc/cp-demangle.c b/contrib/gcc/cp-demangle.c
index 162aafc..5dcce55 100644
--- a/contrib/gcc/cp-demangle.c
+++ b/contrib/gcc/cp-demangle.c
@@ -51,6 +51,8 @@
#include <string.h>
#endif
+#include <ctype.h>
+
#include "ansidecl.h"
#include "libiberty.h"
#include "dyn-string.h"
@@ -833,8 +835,8 @@ demangling_new (name, style)
return NULL;
}
dm->style = style;
- dm->is_constructor = 0;
- dm->is_destructor = 0;
+ dm->is_constructor = (enum gnu_v3_ctor_kinds) 0;
+ dm->is_destructor = (enum gnu_v3_dtor_kinds) 0;
return dm;
}
@@ -972,7 +974,7 @@ demangle_char (dm, c)
else
{
if (error_message == NULL)
- error_message = strdup ("Expected ?");
+ error_message = (char *) strdup ("Expected ?");
error_message[9] = c;
return error_message;
}
@@ -1466,9 +1468,45 @@ demangle_identifier (dm, length, identifier)
while (length-- > 0)
{
+ int ch;
if (end_of_name_p (dm))
return "Unexpected end of name in <identifier>.";
- if (!dyn_string_append_char (identifier, next_char (dm)))
+ ch = next_char (dm);
+
+ /* Handle extended Unicode characters. We encode them as __U{hex}_,
+ where {hex} omits leading 0's. For instance, '$' is encoded as
+ "__U24_". */
+ if (ch == '_'
+ && peek_char (dm) == '_'
+ && peek_char_next (dm) == 'U')
+ {
+ char buf[10];
+ int pos = 0;
+ advance_char (dm); advance_char (dm); length -= 2;
+ while (length-- > 0)
+ {
+ ch = next_char (dm);
+ if (!isxdigit (ch))
+ break;
+ buf[pos++] = ch;
+ }
+ if (ch != '_' || length < 0)
+ return STATUS_ERROR;
+ if (pos == 0)
+ {
+ /* __U_ just means __U. */
+ if (!dyn_string_append_cstr (identifier, "__U"))
+ return STATUS_ALLOCATION_FAILED;
+ continue;
+ }
+ else
+ {
+ buf[pos] = '\0';
+ ch = strtol (buf, 0, 16);
+ }
+ }
+
+ if (!dyn_string_append_char (identifier, ch))
return STATUS_ALLOCATION_FAILED;
}
@@ -3360,7 +3398,7 @@ demangle_substitution (dm, template_p)
}
else
{
- RETURN_IF_ERROR (result_add (dm, "std::basic_istream<char, std::char_traints<char> >"));
+ RETURN_IF_ERROR (result_add (dm, "std::basic_istream<char, std::char_traits<char> >"));
new_last_source_name = "basic_istream";
}
*template_p = 0;
@@ -3880,6 +3918,7 @@ java_demangle_v3 (mangled)
#endif /* IN_LIBGCC2 || IN_GLIBCPP_V3 */
+#ifndef IN_GLIBCPP_V3
/* Demangle NAME in the G++ V3 ABI demangling style, and return either
zero, indicating that some error occurred, or a demangling_t
holding the results. */
@@ -3917,7 +3956,6 @@ demangle_v3_with_details (name)
}
-#ifndef IN_GLIBCPP_V3
/* Return non-zero iff NAME is the mangled form of a constructor name
in the G++ V3 ABI demangling style. Specifically, return:
- '1' if NAME is a complete object constructor,
@@ -3936,7 +3974,7 @@ is_gnu_v3_mangled_ctor (name)
return result;
}
else
- return 0;
+ return (enum gnu_v3_ctor_kinds) 0;
}
@@ -3958,7 +3996,7 @@ is_gnu_v3_mangled_dtor (name)
return result;
}
else
- return 0;
+ return (enum gnu_v3_dtor_kinds) 0;
}
#endif /* IN_GLIBCPP_V3 */
diff --git a/contrib/gcc/cp/ChangeLog b/contrib/gcc/cp/ChangeLog
index 2fd119a..58bd155 100644
--- a/contrib/gcc/cp/ChangeLog
+++ b/contrib/gcc/cp/ChangeLog
@@ -1,20 +1,1173 @@
-2003-02-05 Release Manager
+2003-07-09 Mark Mitchell <mark@codesourcery.com>
- * GCC 3.2.2 Released.
+ PR c++/10032
+ * decl.c (cxx_init_decl_processing): With -pedantic, pedwarns are
+ still errors.
-2003-02-03 Mark Mitchell <mark@codesourcery.com>
+ PR c++/10527
+ * error.c (decl_to_string): Do not print default argument
+ expressions.
+
+2003-07-10 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/10849
+ * decl2.c (handle_class_head_apparent_template): New function.
+ * cp-tree.h (handle_class_head_apparent_template): Add declaration.
+ * parse.y (class_head_defn): Use it.
+ * search.c (type_access_control): Revert my 2003-05-25 change.
+
+2003-07-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/11236
+ * cvt.c (convert_to_void): Treat an overloaded function like
+ "((void) 0)" after issuing a diagnostic.
+
+ PR c++/11345
+ * search.c (lookup_base_r): Remove is_non_public and
+ within_current_scope parameters. Remove other dead code.
+ (lookup_base): Adjust call to lookup_base_r.
+ (adjust_result_of_qualified_name_lookup): Improve comment.
+ * semantics.c (finish_call_expr): Use maybe_dummy_object.
+
+2003-07-05 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/11431
+ * typeck.c (build_static_cast): Check for reference conversions
+ earlier.
+
+2003-07-01 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/6949
+ * decl2.c (grokfield): Create TEMPLATE_DECLs for methods in local
+ classes.
+
+2003-07-01 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (resolve_scoped_fn_name): Return error_mark_node for
+ erroneous cases.
+
+ PR c++/11137
+ * decl2.c (generate_ctor_or_dtor_function): Tolerate a
+ non-existant ssdf_decls array.
+ (finish_file): Call generator_ctor_or_dtor_function when there are
+ static constructors or destructors and no other static
+ initializations.
+
+ PR c++/11149
+ * call.c (resolve_scoped_fn_name): Check that the qualifying scope
+ is a class type.
+
+2003-07-01 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9559
+ * decl2.c (grokfield): Do not build NOP_EXPRs around the
+ error_mark_node.
+
+2003-06-30 Giovanni Bajo <giovannibajo@libero.it>
+
+ * mangle.c (write_expression): Exit gracefully when trying to
+ mangle a CALL_EXPR.
+
+2003-06-30 Giovanni Bajo <giovannibajo@libero.it>
+
+ PR c++/11106
+ * error.c (dump_decl): Call dump_decl to dump the DECL_NAME for a
+ USING_DECL, instead of print_tree_identifier.
+
+2003-06-27 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10468
+ * pt.c (tsubst): Handle qualified TYPEOF_TYPEs correctly.
+
+ PR c++/10796
+ * decl.c (finish_enum): Implement DR377.
+
+ * decl.c (cp_finish_decl): Don't make variables with reference
+ type readonly while they are being initialized.
+
+2003-06-26 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/11332
+ * typeck.c (build_static_cast): Avoid returning expressions with
+ reference type.
+
+2003-06-25 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10990
+ * search.c (lookup_base_r): Rely on accessible_p, rather than
+ trying to emulate that logic here.
+
+ PR c++/10931
+ * call.c (convert_like): Pass issue_conversion_warnings.
+ (convert_like_with_context): Likewise.
+ (convert_like_real): Add issue_conversion_warnings parameter.
+ (perform_direct_initialization_if_possible): New function.
+ * cp-tree.h (perform_direct_initialization_if_possible): Declare it.
+ * typeck.c (check_for_casting_away_constness): New function.
+ (build_static_cast): Rewrite.
- PR C++/7129
- * operators.def: Add <?= and >?=.
+2003-06-23 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/5754
+ * parse.y (structsp): Improve error handling of invalid nested
+ template classes.
+
+2003-06-23 Jakub Jelinek <jakub@redhat.com>
+
+ * mangle.c: Include ggc.h, gt-cp-mangle.h.
+ (mangle_conv_op_name_for_type): Use htab_create_ggc instead of
+ htab_create.
+ * config-lang.in (gtfiles): Add cp/mangle.c.
+ * Make-lang.in (gt-cp-mangle.h): Depend on s-gtype.
+ (cp/mangle.o): Depend on gt-cp-mangle.h.
+
+2003-06-23 Jakub Jelinek <jakub@redhat.com>
+
+ * mangle.c (hash_type): val is the TREE_LIST itself, not a pointer
+ to it.
+
+2003-06-21 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ PR c++/10784
+ * call.c (joust): Warn about choosing conversion sequence only if
+ -Wconversion.
-2003-01-28 Christian Cornelssen <ccorn@cs.tu-berlin.de>
+2003-06-21 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ PR c++/10864
+ * call.c (op_error): Tidy.
+ * error.c (dump_expr): Properly format 'T()' when T is an
+ aggregate type.
+
+2003-06-21 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ PR c++/10915
+ * decl.c (grok_op_properties): Warn possible confusing conversion
+ only if -Wconversion.
+
+2003-06-20 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10845
+ * pt.c (try_class_unification): Correct handling of member class
+ templates.
+
+2003-06-19 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10939
+ * Make-lang.in (decl.o): Depend on input.h.
+ * decl.c (input.h): Include it.
+ (cp_finish_decl): Revert previous change:
+ 2003-06-19 Mark Mitchell <mark@codesourcery.com>
+ * decl.c (cp_finish_decl): Remove support for RESULT_DECLs.
+ Don't check building_stmt_tree.
+ * pt.c (tsubst_decl): Do not try to substitute into non-dependent
+ functions.
+
+ PR c++/9649
+ * cp-tree.h (pushdecl_class_level): Change prototype.
+ (push_class_level_binding): Likewise.
+ * decl.c (add_binding): Reject duplicate static data members.
+ (pushdecl_class_level): Return a value indicating whether or not
+ the binding was valid.
+ (push_class_level_binding): Likewise.
+ * semantics.c (finish_member_declaration): Don't keep invalid
+ declarations.
+
+2003-06-19 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/11041
+ * call.c (initialize_reference): Do not use cp_finish_decl to emit
+ temporary variables.
+ * cp-tree.h (static_aggregates): Declare.
+ (pushdecl_top_level_and_finish): Likewise.
+ * decl.c (pushdecl_top_level_1): New function.
+ (pushdecl_top_level): Use it.
+ (pushdecl_top_level_and_finish): New function.
+ (initialize_local_var): Remove redundant code.
+ (cp_finish_decl): Remove support for RESULT_DECLs. Don't check
+ building_stmt_tree.
+ * decl.h (static_aggregates): Remove.
+ * decl2.c (get_guard): Use pushdecl_top_level_and_finish.
+ * rtti.c (get_tinfo_decl): Use pushdecl_top_level_and_finish.
+ (tinfo_base_init): Likewise.
+
+2003-06-19 Matt Austern <austern@apple.com>
+
+ PR c++/11228
+ * init.c (build_zero_init): Assert that number of array elements
+ is an integer constant.
+ (build_default_init) Don't use build_zero_init for arrays with
+ variable number of elements.
+
+2003-06-17 Mark Mitchell <mark@codesourcery.com>
+
+ * mangle.c (mangle_conv_op_name_for_type): Correct sprintf format
+ string again.
+
+2003-06-17 Mark Mitchell <mark@codesourcery.com>
+
+ * mangle.c (mangle_conv_op_name_for_type): Correct sprintf format
+ string.
+
+2003-06-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/10929
+ * decl.c (grokfndecl): Don't mark a function inline for
+ -finline-functions if it isn't defined.
+
+2003-06-17 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10712
+ * class.c (handle_using_decl): Robustify.
+
+ PR c++/11105
+ * cp-tree.h (DECL_CONV_FN_TYPE): New method.
+ * decl.c (lookup_name_real): Backport conversion operator code
+ from mainline.
+ * mangle.c (struct globals): Remove internal_mangling_p.
+ (write_unqualified_name): Use DECL_CONV_FN_TYPE.
+ (write_template_parm): Don't write out the level number.
+ (conv_type_names): New variable.
+ (hash_type): New function.
+ (compare_type): Likewise.
+ (mangle_conv_op_name_for_type): Don't try to mangle conversion
+ operator names.
+ * search.c (lookup_conversion_operator): New function.
+ (lookup_fnfields_1): Use it.
+
+2003-06-12 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10635
+ * typeck.c (build_c_cast): Check that the destination type is
+ complete.
+
+2003-06-10 Jason Merrill <jason@redhat.com>
+
+ PR c++/10968
+ * pt.c (mark_decl_instantiated): Clear DECL_COMDAT.
+
+2003-06-09 Zack Weinberg <zack@codesourcery.com>
+
+ PR 8861
+ * mangle.c (write_real_cst): New function. Implement
+ ABI-compliant mangling of floating-point literals when
+ -fabi-version>=2; provide backward compatibility with 3.3 when
+ -fabi-version=1 (with warning). Clarify commentary.
+ (write_template_arg_literal): Use write_real_cst.
+
+2003-06-08 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/11039
+ * decl2.c (handle_class_head): Remove implicitness in typename
+ appeared as elaborated type specifier in declaration.
+
+2003-06-03 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/10940
+ * pt.c (check_explicit_specialization): Check for 'static'
+ earlier.
+
+2003-05-31 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/10956
+ * pt.c (instantiate_decl): Don't use full template arguments if
+ we are dealing with specializations.
+
+2003-05-29 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * decl.c (ENABLE_CHECKING_SCOPES): New macro.
+ (binding_depth): Unconditionally define.
+ (is_class_level): Likewise.
+ (indent): Likewise. Take an indenting parameter.
+ (push_binding_level): Remove conditional definittion.
+ (pop_binding_level): Likewise.
+ (suspend_binding_level): Likewise.
+ (resume_binding_level): Likewise.
+ (pushlevel): Likewise.
+ (pushlevel_class): Likewise.
+ (poplevel_class): Likewise.
+ (pop_everything): Likewise.
+
+2003-05-27 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * decl.c (global_scope_p): New macro.
+ (pop_binding_level): Use it.
+ (suspend_binding_level): Likewise.
+ (global_bindings_p): Likewise.
+ (print_other_binding_stack): Likewise.
+ (print_binding_stack): Likewise.
+ (maybe_push_to_top_level): Likewise.
+ (pushdecl_namespace_level): Likewise.
+ (start_decl): Likewise.
+ (cp_finish_decl): Likewise.
+ (start_function): Likewise.
+ (cxx_init_decl_processing): Don't refer to global_binding_level.
+ (global_binding_level): Remove.
+
+2003-05-25 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/10849
+ * search.c (type_access_control): Don't check access when
+ processing_specialization.
+
+2003-05-23 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/10682
+ * pt.c (instantiate_class_template): Use DECL_ARTIFICIAL to
+ check for implicitly created typedef to an enum.
+
+2003-05-20 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * decl.c (free_binding_entry): Fix thinko.
+
+2003-05-19 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * cp-tree.h (struct binding_entry_s): New datatype.
+ (binding_table): Declare.
+ (binding_entry): Likewise.
+ (bt_foreach_proc): Likewise.
+ (binding_table_foreach): Likewise.
+ (binding_table_find): Likewise.
+ (cxx_remember_type_decls): Likewise.
+ (CLASSTYPE_TAGS): Remove.
+ (CLASSTYPE_NESTED_UDTS): New macro.
+ (struct lang_type_class): Remove tags field. Add nested_types.
+ * decl.c (ENTRY_INDEX): New macro.
+ (free_binding_entry): New free list.
+ (binding_entry_make): New function.
+ (binding_entry_free): Likewise.
+ (struct binding_table_s): New datatype.
+ (SCOPE_DEFAULT_HT_SIZE): New macro.
+ (CLASS_SCOPE_HT_SIZE): Likewise.
+ (NAMESPACE_ORDINARY_HT_SIZE): Likewise.
+ (NAMESPACE_STD_HT_SIZE): Likewise.
+ (GLOBAL_SCOPE_HT_SIZE): Likewise.
+ (binding_table_construct): New function.
+ (binding_table_free): Likewise.
+ (binding_table_new): Likewise.
+ (binding_table_expand): Likewise.
+ (binding_table_insert): Likewise.
+ (binding_table_find): Likewise.
+ (binding_table_find_anon_type): Likewise.
+ (binding_table_reverse_maybe_remap): Likewise.
+ (binding_table_remove_anonymous_types): Likewise.
+ (binding_table_foreach): Likewise.
+ (struct cp_binding_level): Remove tags field. Add type_decls.
+ (pop_binding_level): Free binding_entries if possible.
+ (kept_level_p): Tidy.
+ (poplevel): Remove unused variable tags.
+ (bt_print_entry): New function.
+ (print_binding_level): Use it.
+ (push_namespace): Construct binding table.
+ (maybe_process_template_type_declaration): Tidy.
+ (pushtag): Likewise.
+ (clear_anon_tags): Likewise.
+ (cxx_remember_type_decls): New function.
+ (lookup_tag): Tidy.
+ (lookup_tag_reverse): Likewise.
+ (cxx_init_decl_processing): Construct binding_table for the global
+ scope.
+ (store_parm_decls): Remove pointless code.
+ (gettags): Remove.
+ (storetags): Likewise.
+ * class.c (unreverse_member_declarations): Don't touch
+ CLASSTYPE_TAGS.
+ (pushclass): Remember CLASSTYPE_NESTED_UTDS.
+ * pt.c (instantiate_class_template): Remove reference to
+ CLASSTYPE_TAGS. Remeber CLASSTYPE_NESTED_UTDS.
+ (bt_instantiate_type_proc): New function.
+ (do_type_instantiation): Use it.
+ * search.c (lookup_field_r): Use binding_table_find.
+ * semantics.c (begin_class_definition): Remove reference to
+ CLASSTYPE_TAGS. Nullify CLASSTYPE_NESTED_UTDS.
+
+2003-05-15 Jason Merrill <jason@redhat.com>
+
+ PR c++/5388
+ * call.c (conditional_conversion): Don't consider implicit
+ conversions if T2 is a base of T1.
+ * cp-tree.h (DERIVED_FROM_P, UNIQUELY_DERIVED_FROM_P): Make boolean.
+ (ACCESSIBLY_UNIQUELY_DERIVED_P, PUBLICLY_UNIQUELY_DERIVED_P): Likewise.
+
+ PR c++/10661
+ * pt.c (instantiate_class_template): Also instantiate our
+ enclosing class.
+
+2003-05-13 Release Manager
+
+ * GCC 3.3 Released.
+
+2003-05-02 Richard Henderson <rth@redhat.com>
+
+ PR c++/10570
+ * cfns.gperf: Comment out POSIX thread cancellation points,
+ plus abort and raise.
+ * cfns.h: Regenerate.
+
+2003-05-01 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (comdat_linkage): Don't externalize explicit
+ instantiations.
+
+2003-04-29 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10551
+ * pt.c (mark_decl_instantiated): Defer all explicit instantiations
+ that have not yet been written out.
+
+ PR c++/10549
+ * class.c (layout_class_type): Mark overlong bitfields as having
+ the maximum size permitted by their type, after layout.
+
+2003-04-29 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10527
+ * error.c (dump_expr): Correctly handling of NEW_EXPR.4
+
+2003-04-29 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ * lang-options.h: Fix typo.
+
+2003-04-29 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10515
+ * cp-tree.h (lookup_field_1): Declare it.
+ * search.c (lookup_field_1): Make it public.
+ * decl.c (reshape_init): Handle designated initializers.
+
+2003-04-29 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (maybe_commonize_var): Further tweak support for systems
+ without weak symbols.
+
+2003-04-27 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (maybe_commonize_var): Fix thinko in last patch.
+
+ PR c++/10506
+ * method.c (use_thunk): Decrement immediate_size_expand.
+
+ PR c++/10503
+ * cp-tree.h (DECL_VAR_MARKED_P): New macro.
+ (DECL_MAYBE_TEMPLATE): Remove.
+ * class.c (fixed_type_or_null): Avoid infinite recursion.
+
+2003-04-27 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (maybe_commonize_var): Make the code match the comments.
+ * pt.c (instantiate_decl): Move call to import_export_decl.
+
+2003-04-25 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (finish_file): Don't call import_export_decl for
+ functions that are not defined.
+ (handle_class_head): Robustify.
+ * pt.c (instantiate_decl): Do not call cp_finish_decl for
+ variables that are not defined.
+
+2003-04-23 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10471
+ * call.c (build_cxx_call): Robustify.
+
+2003-04-23 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10451
+ * decl.c (grokdeclarator): Correct logic for "mutable" errors.
+
+2003-04-22 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10446
+ * search.c (lookup_fnfields_1): Handle empty slots in the method
+ vector.
+
+2003-04-22 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10428
+ * decl.c (check_elaborated_type_specifier): New function, split
+ out from ...
+ (xref_tag): ... here. Use the new function in more places.
+
+2003-04-21 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_over_call): Use build_cxx_call.
+ (build_cxx_call): New method, split out of build_over_call.
+ * cp-tree.h (language_function): Add can_throw.
+ (build_cxx_call): Declare it.
+ * decl.c (finish_function): If a function does not contain any
+ calls to functions that can throw an exception, indicate that
+ fact.
+ * decl2.c (mark_used): Do not defer the instantiation of
+ functions, if the current function does not throw.
+ * optimize.c (maybe_clone_body): Copy TREE_NOTHROW to the clones.
+ * pt.c (instantiate_decl): Make sure import_export_decl is called
+ before emitting things.
+ * rtti.c (throw_bad_cast): Use build_cxx_call.
+ (build_dynamic_cast_1): Likewise.
+ * typeck.c (build_function_call): Likewise.
+
+2003-04-21 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/9881
+ * typeck.c (build_unary_op): Fold all COMPONENT_REF addr
+ expressions. Reverts my 2002-08-08 patch.
+
+2003-04-20 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/10405
+ * search.c (lookup_field_1): Final scan goes backwards for
+ types, forwards for non-types.
+
+2003-04-15 Jason Merrill <jason@redhat.com>
+
+ * decl2.c (mark_used): Don't instantiate anything if
+ skip_evaluation.
+
+2003-04-15 Mark Mitchell <mark@codesourcery.com>
+
+ * init.c (build_new_1): Use nullexp instead of null_node to avoid
+ unwanted macro expansion.
+
+2003-04-14 Ziemowit Laski <zlaski@apple.com>
+
+ * tree.c (build_cplus_array_type_1): Do not call
+ uses_template_parms() on a NULL index_type.
+
+2003-04-14 Andreas Schwab <schwab@suse.de>
+
+ * init.c (build_new_1): Test use_cookie instead of cookie_size to
+ avoid code-gen bug on ia64.
+
+2003-04-13 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10300
+ * init.c (build_new_1): Correct logic for checking whether the
+ return value from the allocation function was zero.
+
+2003-03-31 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/10278
+ * spew.c (yyerror): Avoid crashing at all costs.
+
+2003-03-31 Jason Merrill <jason@redhat.com>
+
+ PR java/10145
+ * class.c (check_field_decl): Don't set DECL_ALIGN.
+
+2003-03-30 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/7647
+ * search.c (lookup_field_1): Add want_type parameter.
+ (lookup_field_r): Adjust call to lookup_field_1.
+
+2003-03-28 Jason Merrill <jason@redhat.com>
+
+ PR c++/10245
+ * cvt.c (force_rvalue): New fn.
+ * call.c (build_conditional_expr): Use it.
+ * cp-tree.h: Declare it.
+
+2003-03-28 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/10047
+ * decl2.c (finish_file): Don't warn about explicitly instantiated
+ inline decls.
+
+2003-03-27 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/10158
+ * spew.c (snarf_method):Set DECL_INITIALIZED_IN_CLASS for
+ members.
+ * pt.c (instantiate_decl): Only reduce the template args for
+ friends that are not defined in class.
+
+2003-03-24 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/9898, PR c++/383, DR 322
+ * pt.c (maybe_adjust_types_for_deduction) [DEDUCE_CONV]: Look
+ through reference types on both PARM and ARG.
+
+ PR c++/10199
+ * call.c (build_method_call): Deal with LOOKUP_EXPR.
+ * semantics.c (finish_object_call_expr): Use build_method_call
+ when in a template decl.
+
+2003-03-23 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/7086
+ * semantics.c (genrtl_named_return_value): Adjust calls to
+ put_var_into_stack.
+ * typeck.c (cxx_mark_addressable): Likewise.
+
+2003-03-20 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/6412
+ * cp/decl2.c (arg_assoc_class): Correct check for namespace-scope
+ friends.
+ * cp/pt.c (instantiate_class_template): Fix formatting.
+
+2003-03-19 Jason Merrill <jason@redhat.com>
+
+ PR c++/8316, c++/9315, c++/10136
+ * call.c (joust): Improve wording.
+
+2003-03-18 Roger Sayle <roger@eyesopen.com>
+
+ PR c++/10031
+ * decl.c (duplicate_decls): Use the new type when prototyping
+ anticipated decls, even when the types match. This defines the
+ exception list for the built-in function.
+
+2003-03-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/10091
+ * typeck.c (build_class_member_access_expr): Compare
+ TYPE_MAIN_VARIANTs.
+
+ * decl.c (finish_function): Don't skip a block.
+
+ PR c++/9993
+ * decl.c (finish_function): Only allow the NRVO to use variables
+ declared at function scope.
+
+2003-03-17 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/9629
+ * cp-tree.h (struct language_function): Add in_base_initializer.
+ (in_base_initializer): define it.
+ (expand_member_init): Remove INIT param.
+ * init.c (expand_member_init): Remove INIT param, return the member.
+ (emit_mem_initializers): Set in_base_initializer.
+ * class.c (build_base_path): Check in_base_initializer.
+ * parse.y (begin_member_init): New reduction.
+ (member_init): Use it.
+ * pt.c (tsubst_initializer_list): Set in_base_initializer.
+
+2003-03-15 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/6440
+ * pt.c (maybe_process_partial_specialization): Handle
+ member class template when enclosing class template is
+ explicit specialized.
+ (most_general_template): Stop looking when DECL is already
+ specialized.
+
+2003-03-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/9420
+ * search.c (lookup_conversions): Call complete_type here.
+ * call.c (implicit_conversion): Not here.
+
+2003-03-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/9336
+ * decl2.c (lookup_arg_dependent): Handle error_mark_node.
+
+2003-03-13 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (do_nonmember_using_decl): Correct handling of
+ simultaneous type/non-type bindings.
+
+2003-03-13 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (initialize_reference): Remove bogus assertion.
+ * decl.c (build_ptrmemfunc_type): Revert change of 2003-03-09.
+
+2003-03-12 Andrew Lewycky <andrew@mxc.ca>
+
+ PR c++/7050
+ * expr.c (cxx_expand_expr): Return const0_rtx for throw
+ expressions.
+
+2003-03-11 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9474
+ * decl2.c (do_nonmember_using_decl): Do not call duplicate decls
+ to merge old and new declarations.
+
+2003-03-11 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9924
+ * decl2.c (do_nonmember_using_decl): Ignore anticipated builtins.
+
+2003-03-11 Jason Merrill <jason@redhat.com>
+
+ PR c++/9820
+ * search.c (lookup_member): Fix handling of functions in a class
+ being defined.
+
+2003-03-11 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/8700
+ * call.c (print_z_candidates): Avoid printing duplicates.
+
+2003-03-11 Jason Merrill <jason@redhat.com>
+
+ PR c++/8660
+ * decl2.c (check_classfn): A member template only matches a
+ member template.
+
+2003-03-10 Devang Patel <dpatel@apple.com>
+
+ PR c++/9394
+ * g++spec.c (lang_specific_driver): Use DEFAULT_WORD_SWITCH_TAKES_ARG.
+
+2003-03-10 Jason Merrill <jason@redhat.com>
+
+ PR c++/9798
+ * decl.c (push_using_directive): Push before recursing.
+
+ PR c++/9868
+ * call.c (resolve_scoped_fn_name): Handle the case of a function
+ pointer member.
+ * init.c (build_offset_ref): Handle getting a FIELD_DECL for NAME.
+
+ * decl2.c (build_offset_ref_call_from_tree): Only mess with 'this'
+ argument in the pointer-to-member case.
+
+2003-03-09 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9373
+ * cp-lang.c (cxx_get_alias_set): Use alias set zero for
+ pointers to member functions.
+
+ PR c++/8534
+ * decl.c (build_ptrmemfunc_type): Do not allow default arugments
+ in pointer-to-member-function types.
+
+2003-03-09 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9912
+ * cp-tree.h (is_ancestor): New function.
+ * decl2.c (is_namespace_ancestor): Rename to ...
+ (is_ancestor): ... this.
+ (namespace_ancestor): Use it.
+ (set_decl_namespace): Likewise.
+ (handle_class_head): Check for invalid class definitions.
+
+2003-03-10 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ Compile-time improvement: 2/n.
+ * cp-tree.h (struct cxx_binding): New datatype;
+ (struct lang_identifier): Use it.
+ (LOCAL_BINDING_P): Adjust definition.
+ (INHERITED_VALUE_BINDING_P): Likewise.
+ (BINDING_SCOPE): Likewise.
+ (BINDING_HAS_LEVEL_P): Likewise.
+ (BINDING_VALUE): Likewise.
+ (BINDING_TYPE): Likewise.
+ (IDENTIFIER_VALUE): Likewise.
+ (struct tree_binding): Remove.
+ (TS_CP_BINDING): Likewise.
+ ((union lang_tree_node): Remove field "binding".
+ (cxx_binding_clear): New macro.
+ (binding_for_name): Adjust return type.
+ (qualified_lookup_using_namespace): Adjust prototype.
+ (lookup_using_namespace): Adjust prototype.
+ (cxx_scope_find_binding_for_name): Declare.
+ * cp-tree.def: Remove CPLUS_BINDING definition.
+ * parse.y (parse_scoped_id): Don't type-abuse of 'id'. Allocate
+ temporary cxx_binding on stack. Simplify.
+ * decl.c (push_binding): Adjust local variable type.
+ (add_binding): Likewise.
+ (push_class_binding): Likewise.
+ (pop_binding): Likewise.
+ (poplevel): Likewise.
+ (poplevel_class): Likewise.
+ (free_bindings): Adjust type.
+ (find_binding): Adjust return type, add a third parameter. Remove
+ non-useful assertion now that we use static typing.
+ (cxx_scope_find_binding_for_name): New function.
+ (binding_for_name): Use it. Adjust local variable type. Simplify.
+ (namespace_binding): Simplify.
+ (set_namespace_binding): Likewise.
+ (set_identifier_type_value_with_scope): Adjust local variable type.
+ (lookup_tag): Don't type-abuse of local variable 'old'.
+ (lookup_namespace_name): Likewise. Allocate binding on stack.
+ (select_decl): Adjust prototype.
+ (unqualified_namespace_lookup): Allocate binding on stack.
+ Don't type-abuse of local variable 'val'.
+ (lookup_name_real): Likewise.
+ (maybe_inject_for_scope_var): Adjust local variable type.
+ (cp_tree_node_structure): Remove CPLUS_BINDING case label.
+ (namespace_binding): Adjust logic, simplify.
+ (BINDING_LEVEL): Adjust definition.
+ (push_class_level_binding): Adjust local variable type.
+ (struct cxx_saved_binding): Adjust field 'binding' type.
+ * decl2.c (ambiguous_decl): Adjust prototype.
+ (lookup_using_namespace): Adjust local variable type.
+ (qualified_lookup_using_namespace): Catch type error and correct
+ ensueing logic error.
+ (do_nonmember_using_decl): Adjust local variable type. Allocate
+ temporary cxx_binding on stack.
+ (do_toplevel_using_decl): Adjust local variable type.
+ * ptree.c (cxx_print_cxx_binding): New function.
+ (cxx_print_identifier): Use it.
+ (cxx_print_xnode): Delete CPLUS_BINDING case label.
+
+2003-03-09 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/9970
+ * decl.c (duplicate_decls): Only copy DECL_THUNKS for virtual
+ functions.
+
+2003-03-07 Matt Austern <austern@apple.com>
+
+ * cp-tree.h (struct lang_type_class): add field for key method
+ (cp_global_trees): rename dynamic_classes to keyed_classes
+ (key_method): add definition
+ * class.c (finish_struct_1): compute class's key method, and add
+ the class to keyed_classes list if there is no key method.
+ * decl.c (finish_function): add class to keyed_classes list if we
+ see a definition of the class's key method.
+ * pt.c (instantiate_class_template): add template specialization
+ of a dynamic class to keyed_classes list.
+ * decl2.c (key_method): remove
+ (finish_file): iterate only through keyed_classes list when
+ deciding whether to emit vtables, remove class from its list after
+ we do the emission.
+
+2003-03-08 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9809
+ * call.c (add_function_candidate): Skip builtin fuctions that have
+ not yet been declared.
+
+2003-03-07 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (reference_binding): Remove REF_IS_VAR parameter.
+ (implicit_conversion): Adjust call to reference_binding.
+ (make_temporary_var_for_ref_to_type): Add TYPE parameter.
+ (initialize_reference): Adjust handling for references bound to
+ rvalues.
+ * cp-tree.h (make_temporary_var_for_ref_to_temp): Change
+ prototype.
+ (real_non_cast_lvalue_p): New method.
+ * cvt.c (build_up_reference): Adjust use of
+ make_temporary_var_for_ref_to_temp.
+ * tree.c (real_non_cast_lvalue_p): New method.
+
+2003-03-06 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (merge_conversion_sequences): New function.
+ (build_conv): Set ICS_USER_FLAG for USER_CONVs.
+ (convert_class_to_reference): Correct handling of second
+ standard conversion sequence in a user-defined conversion
+ sequence.
+ (build_user_type_conversion_1): Use merge_conversion_sequences.
+ * cp-tree.def: Add comments for CONV nodes.
+
+2003-03-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9965
+ * call.c (reference_binding): Add ref_is_var parameter.
+ (implicit_conversion): Adjust call to reference_binding.
+ (initialize_reference): Likewise.
+
+ PR c++/9400
+ * decl.c (pushdecl): Don't check for shadowing of DECL_ARTIFICIAL
+ PARM_DECLs.
+
+2003-03-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9791
+ * class.c (get_basefndecls): Use lookup_fnfields_1.
+
+2003-03-02 Matt Austern <austern@apple.com>
+
+ * decl.c (cp_binding_level): Add static_decls varray member.
+ (add_decl_to_level): Add static/inline namespace scope
+ declarations to static_decls array.
+ (wrapup_global_for_namespace): Pass static_decls only, instead of
+ all decls, to wrapup_global_declarations/check_global_declarations.
+ (push_namespace): Initialize static_decls for ordinary namespaces.
+ (cxx_init_decl_processing): Initialize static_decls for global
+ namespace.
+
+2003-03-05 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (end_of_class): Correct thinko.
+
+2003-03-04 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * cp-tree.h (cxx_saved_binding): Declare.
+ (struct saved_scope): Adjust type of field 'old_binding'.
+ * decl.c (cxx_saved_binding_make): New macro.
+ (struct cxx_saved_binding): Define.
+ (store_bindings): Adjust prototype. Use cxx_saved_binding to save
+ C++ bindings.
+ (maybe_push_to_top_level): Adjust local variable type.
+ (pop_from_top_level): Likewise.
+
+2003-03-03 Jason Merrill <jason@redhat.com>
+
+ * decl.c (finish_enum): Do set the type in a template. Simplify.
+ * pt.c (tsubst_enum, tsubst_copy): Revert last patch.
+
+2003-03-03 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9878
+ * call.c (convert_class_to_reference): Correct conversion
+ sequences.
+ (reference_binding): Add ref_bound_directly_to_rvalue_p parameter.
+ (implicit_conversion): Adjust call to reference_binding.
+ (add_candidate): Change type of candidates parameter.
+ (add_function_candidate): Likewise.
+ (add_conv_candidate): Likewise.
+ (build_builtin_candidate): Likewise.
+ (add_builtin_candidate): Likewise.
+ (add_builtin_candidates): Likewise.
+ (add_template_candidate_real): Likewise.
+ (add_template_candidate): Likewise.
+ (add_template_conv_candidate): Likewise.
+ (build_user_type_conversion_1): Adjust accordingly.
+ (build_object_call): Likewise.
+ (build_conditional_expr): Likewise.
+ (add_candidates): Likewise.
+ (build_new_op): Likewise.
+ (convert_like_real): Use USER_CONV_CAND. Use build_nop.
+ (build_new_method_call): Adjust calls to add_function_candidate.
+ (make_temporary_var_for_ref_to_temp): New function.
+ (initialize_reference): Add decl parameter.
+ * class.c (build_rtti_vtbl_entries): Use build_address and
+ build_nop.
+ * cp-tree.h (initialize_reference): Change prototype.
+ (make_temporary_var_for_ref_to_temp): New function.
+ (build_type_conversion): Change prototype.
+ (build_address): New function.
+ (build_nop): Likewise.
+ * cvt.c (cp_convert_to_pointer): Adjust call to
+ build_type_conversion. Avoid indicating redundant NOP_EXPRs.
+ Use build_nop.
+ (convert_to_pointer_force): Use build_nop.
+ (build_up_reference): Use make_temporary_var_for_ref_to_temp.
+ (convert_to_reference): Adjust call to build_type_conversion.
+ (ocp_convert): Likewise.
+ (build_type_conversion): Remove for_sure parameter.
+ * decl.c (grok_reference_init): Use initialize_reference.
+ * typeck.c (build_address): New function.
+ (build_nop): Likewise.
+ (build_unary_op): Use them.
+ (build_ptrmemfunc): Tidy slightly.
+ (convert_for_initialization): Adjust call to
+ initialize_reference.
+ * typeck2.c (store_init_value): Remove #if 0'd code.
+
+2003-03-02 Ashif Harji <asharji@uwaterloo.ca>
+
+ * lang-specs.h (default_compilers): Add -no-integrated-cpp flag to
+ invoke an external cpp during compilation.
+
+2003-02-28 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9892
+ * pt.c (instantiate_decl): Clear DECL_RTL for a VAR_DECL when
+ instantiating it.
+
+2003-02-28 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9879
+ * cp-tree.h (build_zero_init): Add parameter.
+ * decl.c (cp_finish_decl): Adjust call.
+ * init.c (build_zero_init): Add nelts parameter. Adjust recursive
+ calls.
+ (build_default_init): Add nelts parameter. Adjust calls to
+ build_zero_init.
+ (build_new_1): Adjust call to build_default_init.
+ * typeck2.c (process_init_constructor): Adjust call to build_zero_init.
+
+2003-02-27 Devang Patel <dpatel@apple.com>
+
+ * decl.c (finish_enum): Merge two 'for' loops. Copy value node if required.
+ Postpone enum setting for template decls.
+ (build_enumerator): Delay copying value node until finish_enum (). Remove
+ #if 0'ed code.
+ * pt.c (tsubst_enum): Set TREE_TYPE and copy value node.
+ (tsubst_copy): Add check for enum type.
+
+
+2003-02-25 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9829
+ * decl.c (grokdeclarator): Handle SCOPE_REFs whose second argument
+ is a NAMESPACE_DECL.
+
+2003-02-24 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * decl.c (add_binding): Time TV_NAME_LOOKUP.
+ (push_class_binding): Likewise.
+ (set_namespace_binding): Likewise.
+
+2003-02-24 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/9602
+ * typeck2.c (abstract_virtuals_error): Don't check when we
+ are processing a template.
+
+2003-02-23 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/7982
+ * decl.c (warn_about_implicit_typename_lookup): Handle TYPEOF_TYPE.
+
+2003-02-21 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9749
+ * decl.c (grokdeclarator): Do not allow parameters with variably
+ modified types.
+
+ PR c++/9727
+ * decl2.c (push_scope): Don't pushclass for non-class types.
+ (pop_scope): Don't popclass either.
+
+ PR c++/8906
+ * decl.c (lookup_name_real): Use IMPLICIT_TYPENAME_P.
+ * decl2.c (handle_class_head): Check it.
+
+ PR c++/8724
+ * call.c (build_method_call): Make sure that the type destroyed in
+ an explicit destructor call is complete.
+
+2003-02-20 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9729
+ * mangle.c (mangle_conv_op_name_for_type): Issue an error message
+ when the G++ 3.2 ABI prevents correct compilation.
+
+2003-02-18 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9704
+ * class.c (layout_class_type): In the 3.2 ABI, take into account
+ trailing bit fields when computing CLASSTYPE_SIZE_UNIT.
+
+2003-02-18 Matt Austern <austern@apple.com>
+
+ * cp/cp-lang.c: Change lang hooks so that final_write_globals does
+ nothing for C++.
+ * cp/decl.c (wrapup_globals_for_namespace): Remove special
+ handling of global namespace.
+
+2003-02-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/9623
+ * decl.c (reshape_init): Don't mess with initializer labels.
+
+2003-02-18 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/9459
+ * error.c (dump_type_prefix): Handle TYPEOF_TYPE.
+ (dump_type_suffix): Likewise.
+
+2003-02-17 Michael Elizabeth Chastain <mec@shout.net>
+
+ PR debug/9717
+ * class.c (build_base_field): Mark fields for base classes with
+ DECL_IGNORED_P.
+
+2003-02-13 Andrew Pinski <pinskia@physics.uc.edu>
+
+ * decl.c: (define_label): Fix warning for return 0 instead of NULL.
+
+2003-02-13 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * Make-lang.in (cp/decl2.o): Add dependency on timevar.h
+ * decl2.c: Include "timevar.h".
+ (namespace_ancestor): Time name lookup.
+ (add_using_namespace): Likewise.
+ (lookup_using_namespace): Likewise.
+ (qualified_lookup_using_namespace): Likewise.
+ (decl_namespace): Likewise.
+ (lookup_arg_dependent): Likewise.
+ * lex.c (do_identifier): Likewise.
+ (do_scoped_id): Likewise.
+ * pt.c (lookup_template_class): Likewise.
+
+2003-02-12 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * decl.c (define_label): Don't forget to pop TV_NAME_LOOKUP.
+
+2003-02-11 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ * decl.c: Include "timevar.h".
+ (poplevel): Time name lookup.
+ (find_binding): Likewise.
+ (push_namespace): Likewise.
+ (pop_nested_namespace): Likewise.
+ (store_bindings): Likewise.
+ (maybe_push_to_top_level): Likewise.
+ (pop_from_top_level): Likewise.
+ (push_local_name): Likewise.
+ (pushtag): Likewise.
+ (pushdecl): Likewise.
+ (pushdecl_with_scope): Likewise.
+ (pushdecl_namespace_level): Likewise.
+ (pushdecl_top_level): Likewise.
+ (pushdecl_class_level): Likewise.
+ (push_class_level_binding): Likewise.
+ (push_using_decl): Likewise.
+ (push_using_directive): Likewise.
+ (push_overloaded_decl): Likewise.
+ (lookup_label): Likewise.
+ (define_label): Likewise.
+ (lookup_tag): Likewise.
+ (lookup_tag_reverse): Likewise.
+ (lookup_namespace_name): Likewise.
+ (select_decl): Likewise.
+ (unqualified_namespace_lookup): Likewise.
+ (lookup_name_real): Likewise.
+ (lookup_name_current_level): Likewise.
+ (lookup_type_current_level): Likewise.
+ (maybe_inject_for_scope_var): Likewise.
+ (xref_tag): Likewise.
+
+ * Make-lang.in (cp/decl.o): Add dependency on timevar.h
+
+2003-02-03 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/7129
+ * operators.def: Add <?= and >?=.
+
+2003-01-31 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/8849
+ * error.c (dump_expr): Handle BASELINK.
+ * pt.c (resolve_overloaded_unification): Handle FUNCTION_DECL.
+
+2003-01-31 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/9453
+ * friend.c (is_friend): Always accept when SUPPLICANT is still
+ a TEMPLATE_DECL.
+ * pt.c (push_access_scope_real): Call push_to_top_level for
+ function in namespace scope.
+ (push_access_scope): Remove ARGS argument, all caller adjusted.
+ (pop_access_scope): Call pop_from_top_level for function in
+ namespace scope.
+ (regenerate_decl_from_template): Use push_access_scope_real.
+
+2003-01-29 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/9437
+ * pt.c (unify): Don't unify '*T' with 'U C::*'.
+
+2003-01-27 Jeffrey D. Oldham <oldham@codesourcery.com>
+
+ PR c++/47
+ * cp-tree.h (lookup_nested_field): Add declaration.
+ * decl.c (lookup_name_real): Call lookup_nested_field.
+ * search.c (lookup_nested_field): Add function.
+
+2003-01-26 Christian Cornelssen <ccorn@cs.tu-berlin.de>
* Make-lang.in (c++.install-common, c++.install-man)
- (c++.uninstall): Prepend $(DESTDIR) to destination paths
- in all (un)installation commands.
+ (c++.uninstall): Prepend $(DESTDIR) to destination paths in
+ all (un)installation commands.
(c++.install-common): Rewrite $(LN) commands to support
DESTDIR with "ln" as well as with "ln -s".
+2003-01-24 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * decl2.c (check_classfn): Fix uninitialized warning.
+
2003-01-22 Mark Mitchell <mark@codesourcery.com>
PR c++/9328
@@ -22,20 +1175,145 @@
function; it doesn't make sense to try to print its type.
* semantics.c (finish_typeof): Issue errors about invalid uses.
-2003-01-21 Jeffrey D. Oldham <oldham@codesourcery.com>
+2003-01-22 Josef Zlomek <zlomekj@suse.cz>
- PR c++/47
- * cp-tree.h (lookup_nested_field): Add declaration.
- * decl.c (lookup_name_real): Call lookup_nested_field.
- * search.c (lookup_nested_field): Add function.
+ PR/9386, PR/8801
+ 2002-12-27 Mark Mitchell <mark@codesourcery.com>
+ * typeck.c (build_class_member_access_expr): Fix anonymous union
+ handling.
+
+2003-01-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/9167, c++/9358
+ * decl.c (require_complete_types_for_parms): Also update DECL_ARG_TYPE.
+
+2003-01-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/9342
+ * call.c (build_conditional_expr): Always do lvalue-rvalue
+ conversion.
+
+2003-01-16 Jason Merrill <jason@redhat.com>
+
+ PR c++/8564
+ * init.c (build_vec_init): Re-add maxindex parm.
+ (perform_member_init, build_aggr_init): Pass it.
+ (build_new_1): Pass it. Use an incomplete array type for full_type.
+ * typeck.c (build_modify_expr): Pass it.
+ * cp-tree.h: Adjust.
+
+2003-01-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/8748
+ * class.c (build_base_path): Take the address before calling save_expr.
+
+ * call.c (build_user_type_conversion_1): Do set ICS_BAD_FLAG if
+ all the ambiguous conversions are bad.
+
+ * class.c (maybe_warn_about_overly_private_class): Don't stop
+ searching when we find a nonprivate method.
+
+2003-01-09 Jakub Jelinek <jakub@redhat.com>
+
+ * decl.c (start_decl): Only check DECL_THREAD_LOCAL for VAR_DECLs.
+
+2003-01-09 Jakub Jelinek <jakub@redhat.com>
+
+ * decl.c (start_decl): Don't set DECL_COMMON for __thread variables.
+
+2003-01-07 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/9030
+ * decl.c (make_typename_type): Check access only when tf_error.
+ (make_unbound_class_template): Likewise.
+ * pt.c (saved_access_scope): New variable.
+ (push_access_scope_real): New function.
+ (push_access_scope): Likewise.
+ (pop_access_scope): Likewise.
+ (tsubst_default_argument): Use them.
+ (instantiate_template): Likewise.
+ (regenerate_decl_from_template): Likewise.
+ (instantiate_decl): Likewise.
+ (get_mostly_instantiated_function_type): Likewise.
+
+2003-01-06 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9165
+ * decl2.c (build_cleanup): Mark the object as used.
+
+2003-01-03 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/45, c++/3784
+ * tree.c (cp_tree_equal, TEMPLATE_PARM_INDEX): The types must be
+ the same too.
+
+2002-12-30 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/9054
+ * class.c (layout_class_type): Set DECL_CONTEXT of type for base.
+ * dump.c (cp_dump_tree, RECORD_TYPE): Deal with type for base types.
2002-12-26 Nathan Sidwell <nathan@codesourcery.com>
- PR c++/8503
- Remove DR 295 implementation.
- * pt.c (check_cv_quals_for_unify): Disable function & method cases.
- * tree.c (cp_build_qualified_type_real): Likewise. Don't warn
- about ignoring volatile qualifiers.
+ PR c++/4803
+ * decl2.c (mark_used): Defer inline functions.
+ (finish_file): Merge deferred_fns loops. Check all used
+ inline functions have a definition.
+ * method.c (make_thunk): Thunks are not inline.
+
+ PR c++/5116, c++/764
+ * call.c (build_new_op): Make sure template class operands are
+ instantiated.
+
+2002-12-24 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR C++/7964
+ * cp-tree.h (resolve_scoped_fn_name): Prototype.
+ * call.c (resolve_scoped_fn_name): New function. Deal with
+ more template expansion. Broken out of ...
+ * parse.y (parse_finish_call_expr): ... here. Call it.
+ * decl2.c (build_expr_from_tree, CALL_EXPR): Use
+ resolve_scoped_fn_name and build_call_from_tree.
+
+ PR c++/9053
+ * decl.c (duplicate_decls): Templates may be disambiguated by
+ return type.
+
+ PR c++/8702
+ * decl2.c (check_classfn): Use lookup_fnfield_1. List all
+ conversion operators on failure.
+
+2002-12-22 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/8572
+ * cp-tree.h (grokoptypename): Add SCOPE parameter.
+ * decl2.c (grokoptypename): Add SCOPE parameter. tsubst the type
+ if in a template scope.
+ * parse.y (unoperator): Return the scope.
+ (operator_name): Adjust grokoptypename call.
+
+2002-12-22 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ * cp-tree.h (make_unbound_class_template): Use tsubst_flags_t.
+ * decl.c (make_unbound_class_template): Adjust. Check for tf_error.
+ * pt.c (tsubst) [OFFSET_TYPE]: Check for tf_error.
+
+2002-12-18 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/8099
+ * friend.c (make_friend_class): Allow partial specialization
+ when declaration is not a template friend.
+
+2002-12-18 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/3663
+ * pt.c (lookup_template_class): Copy TREE_PRIVATE and
+ TREE_PROTECTED to created decl nodes.
+
+2002-12-18 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (build_base_field): Do not set DECL_PACKED on the
+ FIELD_DECL.
2002-12-18 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
@@ -49,46 +1327,94 @@
* pt.c (convert_template_argument): Fix type or template template
parameter decision logic.
-2002-12-13 Joe Buck <jbuck@synopsys.com>
-
- * parse.y (class_head_defn): Set CLASSTYPE_DECLARED_CLASS for
- anonymous structs.
-
2002-12-13 Gabriel Dos Reis <gdr@integrable-solutions.net>
-
- PR C++/8031
+
+ PR C++/8031
* cvt.c (convert_to_pointer_force): Don't try comparing against
erronous type.
+2002-12-13 Geoffrey Keating <geoffk@apple.com>
+
+ * cp-tree.h: Have the multiple-include guards around
+ the entire file.
+
2002-12-10 Mark Mitchell <mark@codesourcery.com>
PR c++/8372
* pt.c (tsubst_copy): Handle destructor names more correctly.
+2002-12-10 Matt Austern <austern@apple.com>
+
+ * cp-tree.h: get rid of needs_virtual_reinit bit.
+
+2002-12-09 Mark Mitchell <mark@codesourcery.com>
+
+ * NEWS: Document removal of in-class initialization extension for
+ static data members of non-arithmetic, non-enumeration type.
+ * decl.c (check_static_variable_definition): Do not allow that
+ extension.
+ * decl2.c (grokfield): Do not call digest_init when processing
+ templates.
+
2002-12-05 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* error.c (dump_expr): Fix format specifier warning.
+2002-12-04 Geoffrey Keating <geoffk@apple.com>
+
+ * class.c (finish_struct_1): Correct comment.
+ * cp-tree.c (DECL_SORTED_FIELDS): Likewise.
+
2002-12-04 Gabriel Dos Reis <gdr@integrable-solutions.net>
PR C++/8799
* error.c (dump_expr): Don't ever try to dump a non-existent
- expression.
+ expression.
+
+2002-12-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/8674
+ * call.c (build_over_call): Check specifically for TARGET_EXPR
+ when eliding.
+
+ PR c++/8461, c++/8625
+ * call.c (convert_for_arg_passing): Don't mess with error_mark_node.
+ (cp_convert_parm_for_inlining): Remove.
+ * cp-lang.c (LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING):
+ Remove.
+ * cp-tree.h (ADDR_IS_INVISIREF): Remove.
+ * except.c (stabilize_throw_expr): Remove ADDR_IS_INVISIREF code.
+
+ * call.c (build_user_type_conversion_1): Don't set ICS_BAD_FLAG on
+ an ambiguous conversion.
+
+2002-12-03 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/8688
+ * decl.c (reshape_init): Handle erroneous initializers.
2002-12-02 Mark Mitchell <mark@codesourcery.com>
+ PR c++/8720
+ * spew.c (remove_last_token): Make sure that last_chunk is set
+ correctly.
+
PR c++/8615
* error.c (dump_expr): Handle character constants with
TREE_OVERFLOW set.
+2002-12-02 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ DR 180
+ * decl.c (grokdeclarator): Require class-key for all friend class.
+ Output the correct type and context in the error message.
+
2002-12-01 Mark Mitchell <mark@codesourcery.com>
PR c++/5919
* pt.c (unify): Use variably_modified_type_p to test validity of
template argument types.
-2002-12-01 Mark Mitchell <mark@codesourcery.com>
-
PR c++/8727
* cp-tree.h (lang_type_class): Add typeinfo_var.
(CLASSTYPE_TYPEINFO_VAR): New macro.
@@ -106,41 +1432,204 @@
c_size_type_node.
* decl2.c (coerce_new_type): Likewise.
* except.c (do_allocate_exception): Likewise.
- * typeck.c (c_sizeof): Likewise.
- (c_sizeof_nowarn): Likewise.
2002-11-30 Mark Mitchell <mark@codesourcery.com>
+ PR c++/8227
+ * decl.c (layout_var_decl): Deal gracefully with erroneous types.
+ (check_initializer): Validate the type of the initialized
+ variable, even if the initializer is absent.
+ * typeck.c (cp_type_quals): Deal gracefully with erroneous types.
+
PR c++/8214
* typeck.c (convert_for_assignment): Do not use
decl_constant_value on the operand.
-2002-11-19 Release Manager
+ PR c++/8511
+ * pt.c (instantiate_decl): Handle template friends defined outside
+ of the class correctly.
+
+2002-11-29 Joe Buck <jbuck@synopsys.com>
- * GCC 3.2.1 Released.
+ * parse.y (class_head_defn): Set CLASSTYPE_DECLARED_CLASS for
+ anonymous structs.
-2002-11-19 Release Manager
+2002-11-29 Mark Mitchell <mark@codesourcery.com>
- * GCC 3.2.1 Released.
+ * class.c (walk_subobject_offsets): Recur on binfos as well as on
+ types.
+ (layout_nonempty_base_or_field): Pass it a binfo when processing a
+ base class.
+ (layout_empty_base): Likewise.
+ (build_base_field): Likewise.
-2002-11-18 Release Manager
+2002-11-27 Mark Mitchell <mark@codesourcery.com>
- * GCC 3.2.1 Released.
+ * class.c (build_base_field): Make sure we get the canonical base
+ when descending through primary bases.
-2002-11-11 Nathan Sidwell <nathan@codesourcery.com>
+2002-11-26 Geoffrey Keating <geoffk@apple.com>
- PR c++/7788
- * rtti.c (unemitted_tinfo_decl_p): Check it has a field.
+ * decl.c (check_initializer): Don't error on initialisation of
+ a scalar with a brace-enclosed expression.
+
+2002-11-26 Nathan Sidwell <nathan@codesourcery.com>
-2002-11-02 Zack Weinberg <zack@codesourcery.com>
+ * cp-tree.h (DECL_LANG_FLAG_4): Document more uses.
+ (template_parms_equal): Remove prototype.
+ * typeck.c (buuld_indirect_ref): Reformat.
+
+2002-11-25 Mark Mitchell <mark@codesourcery.com>
+
+ * tree.c (cp_build_qualified_type_real): Correct handling of
+ array types.
+ * class.c (walk_subobject_offsets): Fix thinko.
+ (build_base_field): Record offsets of empty bases in primary
+ virtual bases.
+ (layout_class_type): Record offsets of empty bases in fields.
+
+ * search.c (is_subobject_of_p_1): Fix thinko.
+ (lookup_field_queue_p): Likewise.
+
+2002-11-24 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (layout_class_type): Reuse tail padding when laying out
+ virtual bases.
+
+2002-11-22 Mark Mitchell <mark@codesourcery.com>
+
+ * rtti.c (qualifier_flags): Fix thinko.
+
+2002-11-21 Glen Nakamura <glen@imodulo.com>
+
+ PR c++/8342
+ * typeck.c (get_member_function_from_ptrfunc): Make sure that a
+ SAVE_EXPR for instance_ptr doesn't get evaluated first inside one
+ of the branches of a COND_EXPR.
+
+2002-11-19 Mark Mitchell <mark@codesourcery.com>
+
+ * pt.c (for_each_template_parm): Free allocated memory.
+ * search.c (is_subobject_of_p_1): New function.
+ (is_subobject_of_p): Avoid walking virtual bases multiple times.
+
+2002-11-19 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * g++spec.c (lang_specific_spec_functions): New.
+
+2002-11-15 Kazu Hirata <kazu@cs.umass.edu>
+
+ * ChangeLog: Follow spelling conventions.
+ * class.c: Likewise.
+ * decl2.c: Likewise.
+
+2002-11-14 Zack Weinberg <zack@codesourcery.com>
+
+ * search.c (dfs_push_decls): Do not try to reorder elements
+ 3..n of method_vec if method_vec has only two elements.
+ Reverse order of two tests to avoid accessing unallocated
+ memory.
+
+2002-11-14 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (dfs_find_final_overrider): Adjust so that the most
+ derived object is a binfo, rather than a class type.
+ (find_final_overrider): Likewise.
+ (add_vcall_offset_vtbl_entries_1): Simplify accordingly.
+ (add_vcall_offset): Likewise.
+
+2002-11-09 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/8389
+ * pt.c (instantiate_template): Push class scope for member
+ functions.
+ (get_mostly_instantiated_function_type): Likewise. Don't call
+ tsubst on context. Remove CONTEXTP and TPARMSP parameters.
+ * cp-tree.h (get_mostly_instantiated_function_type): Adjust.
+ * mangle.c (write_encoding, write_unqualified_name): Adjust.
+
+2002-11-07 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (add_vcall_offset_vtbl_entries_1): Correct ordering of
+ vcall offfsets. Split out ...
+ (add_vcall_offset): ... new function.
+
+ PR c++/8338
+ * pt.c (for_each_template_parm): Add htab parameter.
+ (process_partial_specialization): Adjust call.
+ (push_template_decl_real): Likewise.
+ (pair_fn_data): Add visited.
+ (for_each_template_parm_r): Avoid walking duplicates more than
+ once.
+ (uses_template_parms): Adjust call to for_each_template_parm.
+
+2002-11-07 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (add_implicitly_declared_members): Put implicitly
+ declared functions at the end of TYPE_METHODs when -fabi-version
+ is at least 2.
+
+2002-11-05 Geoffrey Keating <geoffk@apple.com>
+
+ * decl2.c (finish_file): Correct spelling.
+
+2002-11-03 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_special_member_call): Do not try to lookup VTTs by
+ name.
+ * class.c (vtbl_init_data): Add generate_vcall_entries.
+ (get_vtable_decl): Do not look up virtual tables by name.
+ (copy_virtuals): Do not use BV_USE_VCALL_INDEX_P.
+ (set_primary_base): Do not set CLASSTYPE_RTTI.
+ (determine_primary_base): Likewise.
+ (get_matching_virtual): Remove.
+ (get_vcall_index): New function.
+ (update_vtable_entry_for_fn): Do not try to use virtual thunks
+ when they are not required. Assign vcall indices at this point.
+ (finish_struct_1): Do not set CLASSTYPE_NEEDS_VIRTUAL_REINIT.
+ Do update dynamic_classes.
+ (build_vtt): Do not add VTTs to the symbol table.
+ (build_ctor_vtbl_group): Likewise.
+ (build_vtbl_initializer): Simplify handling of vcall indices.
+ (build_vcall_offset_vtbl_entries): Pretend to build vcall offsets
+ for the most derived class.
+ (add_vcall_offset_vtbl_entries_1): But do not actually add them to
+ the vtable.
+ * cp-tree.h (dynamic_classes): New macro.
+ (lang_type_class): Remove rtti. Add vtables. Add vcall_indices.
+ (CLASSTYPE_RTTI): Remove.
+ (CLASSTYPE_NEEDS_VIRTUAL_REINIT): Remove.
+ (CLASSTYPE_VCALL_INDICES): New macro.
+ (CLASSTYPE_VTABLES): Likewise.
+ (BV_USE_VCALL_INDEX_P): Remove.
+ (build_vtable_path): Remove.
+ * decl2.c (finish_vtable_vardecl): Remove.
+ (key_method): Remove #if 0'd code.
+ (finish_vtable_vardecl): Rename to ...
+ (maybe_emit_vtables): ... this.
+ (finish_file): Use it.
+ * search.c (look_for_overrides_here): Update comment.
+
+2002-11-01 Zack Weinberg <zack@codesourcery.com>
PR c/7353 redux
* decl2.c (grokfield): Reject TYPE_DECLs with initializers.
-2002-11-01 Gabriel Dos Reis <gdr@integrable-solutions.net>
+2002-10-30 Jason Merrill <jason@redhat.com>
- PR C++/2521
- * typeck.c (build_x_unary_op): Handle pointer-to-member.
+ PR c++/8186
+ * cp-tree.h (ADDR_IS_INVISIREF): New macro.
+ * call.c (convert_for_arg_passing): Set it.
+ * except.c (stabilize_throw_expr): Recurse for such an arg.
+
+2002-10-31 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (lang_decl_flags): Remove init_priority.
+ (lang_decl): Add delta.
+ (GLOBAL_INIT_PRIORITY): Remove.
+ (THUNK_DELTA): Revise definition.
+ * decl2.c (start_objects): Don't set GLOBAL_INIT_PRIORITY.
+ * dump.c (cp_dump_tree): Don't dump it.
2002-10-30 Mark Mitchell <mark@codesourcery.com>
@@ -150,6 +1639,25 @@
PR c++/8149
* decl.c (make_typename_type): Issue errors about invalid results.
+2002-10-30 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ Core issue 287, PR c++/7639
+ * cp-tree.h (lang_type_class): Add decl_list field.
+ (CLASSTYPE_DECL_LIST): New macro.
+ (maybe_add_class_template_decl_list): Add declaration.
+ * class.c (duplicate_tag_error): Initialize CLASSTYPE_DECL_LIST.
+ (unreverse_member_declarations): Reverse CLASSTYPE_DECL_LIST.
+ (maybe_add_class_template_decl_list): New function.
+ (add_implicitly_declared_members): Use it.
+ * decl.c (maybe_process_template_type_declaration): Likewise.
+ (pushtag): Likewise.
+ * friend.c (add_friend): Likewise.
+ (make_friend_class): Likewise.
+ * semantics.c (finish_member_declaration): Likewise.
+ (begin_class_definition): Initialize CLASSTYPE_DECL_LIST.
+ * pt.c (instantiate_class_template): Use CLASSTYPE_DECL_LIST
+ to process members and friends in the order of declaration.
+
2002-10-29 Mark Mitchell <mark@codesourcery.com>
PR c++/8287
@@ -157,28 +1665,45 @@
when returning from a destructor here.
(finish_function_body): Rather than here.
- * semantics.c (finish_alignof): Call complete_type before calling
- c_alignof.
- * decl2.c (build_expr_from_tree): Use
- finish_sizeof/finish_alignof.
-
-2002-10-10 Jim Wilson <wilson@redhat.com>
-
- * decl.c (duplicate_decls): Don't call decl_attributes.
-
2002-10-25 Zack Weinberg <zack@codesourcery.com>
- PR middle-end/6994
- * cp-lang.c (cp_var_mod_type_p): New: C++ hook for
- variably_modified_type_p.
- * cp-tree.h: Remove prototype of variably_modified_type_p.
- * tree.c (variably_modified_type_p): Remove; now implemented
- in language-independent code.
-
PR c++/7266
* decl.c (grokdeclarator): Check that TREE_OPERAND 0 of a
SCOPE_REF is not null before dereferencing it.
+2002-10-25 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_over_call): Use DECL_CONTEXT, not
+ DECL_VIRTUAL_CONTEXT.
+ * class.c (modify_vtable_entry): Don't mess with
+ DECL_VIRTUAL_CONTEXT.
+ (set_vindex): Remove.
+ (set_primary_base): Remove vfuns_p parameter.
+ (determine_primary_base): Likewise.
+ (modify_all_vtables): Likewise.
+ (layout_class_type): Likewise. Adjust calls to other functions
+ accordingly.
+ (finish_struct_1): Adjust calls to modified functions. Set
+ DECL_VINDEX here.
+ * cp-tree.h (lang_type_class): Remove vsize.
+ (CLASSTYPE_VSIZE): Remove.
+ (lang_decl): Remove thunks.
+ (DECL_THUNKS): Adjust.
+ (DECL_VIRTUAL_CONTEXT): Remove.
+ (duplicate_decls): Don't copy it.
+ * pt.c (build_template_decl): Don't set it.
+ (tsubst_decl): Likewise.
+ * typeck.c (expand_ptrmemfunc_cst): Don't use it.
+
+ * class.c (build_vtbl_initializer): Don't use build_vtable_entry.
+ (build_vtable_entry): Remove.
+ * cp-tree.h (BINFO_VIRTUALS): Expand documentation.
+ (lang_decl): Add thunks.
+ (DECL_THUNKS): New macro.
+ * decl.c (duplicate_decls): Copy it.
+ * method.c (make_thunk): Simplify, and add thunks to DECL_THUNKS.
+ * semantics.c (emit_associated_thunks): Simplify.
+
2002-10-24 David Edelsohn <edelsohn@gnu.org>
PR c++/7228
@@ -191,14 +1716,19 @@
* typeck2.c (process_init_constructor): Remove redundant check for
existence of lang_type structure.
+2002-10-24 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (end_of_base): New method.
+ (end_of_class): Use it. Check indirect virtual bases.
+
+ * class.c (check_field_decls): Fix typo.
+
2002-10-23 Mark Mitchell <mark@codesourcery.com>
PR c++/8067
* decl.c (maybe_inject_for_scope_var): Ignore __FUNCTION__ and
related variables.
-2002-10-23 Mark Mitchell <mark@codesourcery.com>
-
PR c++/7679
* spew.c (next_token): Do not return an endless stream of
END_OF_SAVED_INPUT tokens.
@@ -206,24 +1736,39 @@
the cached token stream.
(snarf_defarg): Likewise.
+2002-10-23 Zack Weinberg <zack@codesourcery.com>
+
+ * cp-lang.c (cp_var_mod_type_p): New: C++ hook for
+ variably_modified_type_p.
+ * cp-tree.h: Remove prototype of variably_modified_type_p.
+ * tree.c (variably_modified_type_p): Remove; now implemented
+ in language-independent code.
+
2002-10-22 Mark Mitchell <mark@codesourcery.com>
PR c++/6579
* spew.c (snarf_parenthesized_expression): New function.
(snarf_block): Use it.
-2002-10-21 Matthias Klose <doko@debian.org>
+2002-10-22 Richard Henderson <rth@redhat.com>
- * Backport, without whitespace change:
- 2002-06-19 Akim Demaille <akim@epita.fr>
- * parse.y (TYPENAME): Rename as tTYPENAME to avoid the clash with
- decl.h's TYPENAME.
- * spew.c, lex.c: Adjust.
- * parse.y (explicit_instantiation): Add empty action to override
- the default $$ = $1 where it introduces a type clash.
+ * method.c (use_thunk): Always compute vcall_value; assert that
+ it is not zero. Use can_output_mi_thunk; use output_mi_thunk
+ for vcall thunks as well.
2002-10-21 Mark Mitchell <mark@codesourcery.com>
+ * class.c (empty_base_at_nonzero_offset_p): New function.
+ (layout_nonempty_base_or_field): Do not check for conflicts when
+ laying out a virtual base using the GCC 3.2 ABI.
+ (build_base_field): Correct checking for presence of empty classes
+ at nonzero offsets when clearing CLASSTYPE_NEARLY_EMPTY_P.
+
+ * class.c (include_empty_classes): Use normalize_rli.
+ (layout_class_type): Likewise.
+
+ * decl.c (reshape_init): Tweak handling of character arrays.
+
PR c++/8218
* cp-tree.h (lang_type_class): Add contains_empty_class_p.
(CLASSTYPE_CONTAINS_EMPTY_CLASS_P): New macro.
@@ -233,55 +1778,145 @@
(finish_struct_1): Initialize it.
(walk_subobject_offsets): Use it to prune searches.
+2002-10-20 Mark Mitchell <mark@codesourcery.com>
+
+ * method.c (use_thunk): Compute the vcall index as a HOST_WIDE_INT.
+ * optimize.c (optimize_function): Replace ASM_OUTPUT_MI_THUNK with
+ TARGET_ASM_OUTPUT_MI_THUNK in comments.
+
2002-10-18 Zack Weinberg <zack@codesourcery.com>
* decl.c (start_decl): Point users of the old initialized-
typedef extension at __typeof__.
-2002-10-18 Nathan Sidwell <nathan@codesourcery.com>
+2002-10-18 Mark Mitchell <mark@codesourcery.com>
+
+ * Make-lang.in (method.o): Depend on TARGET_H.
+ * method.c (target.h): Include it.
+ (use_thunk): Use target hooks. Use vcall thunks, if available.
+
+2002-10-18 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (base_derived_from): Make sure return value is a bool.
+
+2002-10-18 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (find_final_overrider_data_s): Remove overriding_fn and
+ overriding_base.
+ (dfs_base_derived_from): New function.
+ (base_derived_from): Likewise.
+ (dfs_find_final_overrider): Use base_derived_from.
+ (find_final_overrider): Adjust.
+
+2002-10-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/8080
+ * semantics.c (finish_for_cond, finish_while_cond): Don't mess
+ with condition decls in a template.
+
+2002-10-17 Nathan Sidwell <nathan@codesourcery.com>
- PR c++/7676
* class.c (add_method): Compare template parms too.
2002-10-17 Mark Mitchell <mark@codesourcery.com>
- * mangle.c (globals): Add entity and need_abi_warning.
- (write_prefix): Likewise.
- (write_template_prefix): Likewise.
- (start_mangling): Add entity parameter.
- (finish_mangling): Warn about names whose mangling will change.
- (mangle_decl_string): Adjust.
- (mangle_type_string): Likewise.
- (mangle_special_for_type): Likewise.
- (mangle_ctor_vtbl_for_type): Likewise.
- (mangle_thunk): Likewise.
- (mangle_guard_variable): Likewise.
- (mangle_ref_init_variable): Likewise.
-
PR c++/7584
* class.c (handle_using_decl): Allow the declaration used to be
from an ambiguous base.
+ * pt.c (convert_template_argument): Revert this change:
+ 2002-10-16 Mark Mitchell <mark@codesourcery.com>
+ * pt.c (convert_template_argument): Do not fold non-type
+ template rguments when inside a template.
+
+ * init.c (expand_default_init): Handle brace-enclosed initializers
+ correctly.
+
2002-10-16 Mark Mitchell <mark@codesourcery.com>
+ * mangle.c (write_expression): Correct handling of enumeration
+ constants.
+ (write_template_arg): Likewise.
+ * pt.c (convert_template_argument): Do not fold non-type template
+ arguments when inside a template.
+
PR c++/7478
* cvt.c (convert_to_reference): Allow references as the incoming
type.
- PR c++/8134
- * tree.c (zero_init_p): Always return 1.
+2002-10-16 Mark Mitchell <mark@codesourcery.com>
PR c++/7524
* method.c (do_build_assign_ref): Use cp_build_qualified_type, not
build_qualified_type.
+2002-10-15 Richard Henderson <rth@redhat.com>
+
+ * error.c (dump_expr): Use real_to_decimal directly, and with
+ the new arguments.
+
+2002-10-15 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (reshape_init): Fix typo.
+
+ * cp-tree.h (operator_name_info_t): Add arity.
+ * lex.c (init_operators): Initialize it.
+ * mangle.c (write_conversion_operator_name): New function.
+ (write_unqualified_name): Use it.
+ (write_template_args): Accept template arguments as a TREE_LIST.
+ (write_expression): Adjust handling of qualified names to match
+ specification.
+
+2002-10-15 Jason Merrill <jason@redhat.com>
+
+ * call.c (call_builtin_trap): New fn.
+ (convert_arg_to_ellipsis): Use it. Downgrade error to warning.
+ (build_call): Don't set current_function_returns_abnormally outside
+ a function.
+
2002-10-14 Mark Mitchell <mark@codesourcery.com>
+ * class.c (check_field_decls): Remove empty_p parameter. Instead,
+ clear CLASSTYPE_EMPTY_P.
+ (build_base_field): Likewise.
+ (build_base_fields): Likewise.
+ (check_bases_and_members): Likewise.
+ (create_vtbl_ptr): Likewise.
+ (layout_class_type): Likewise. Ensure that empty classes have
+ size zero when used as base classes in the 3.2 ABI.
+ (finish_struct_1): Initialize CLASSTYPE_EMPTY_P and
+ CLASSTYPE_NEARLY_EMPTY_P. Adjust calls to avoid passing empty_p
+ parameter.
+ (is_empty_class): Correct definition when using post-3.2 ABI.
+ * cp-tree.h (lang_type_class): Add empty_p.
+ (CLASSTYPE_EMPTY_P): New macro.
+
+2002-10-12 Nathan Sidwell <nathan@codesourcery.com>
+
+ * init.c (build_delete): Do not apply save_expr for arrays.
+ (build_vec_delete): Likewise.
+
+2002-10-14 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (layout_var_decl): Call layout_decl even for variables
+ whose type is an array with unspecified bounds.
+
PR c++/7176
* lex.c (do_identifier): Add another option for the parsing
parameter.
* parse.y (do_id): Use it.
+2002-10-11 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ PRs C++/6803, C++/7721 and C++/7803
+ * decl.c (grokdeclarator): Gracefully handle template-name as
+ decl-specifier.
+
+2002-10-11 Jason Molenda <jmolenda@apple.com>
+
+ * init.c (build_field_list): Provide uses_unions_p with a default
+ value.
+
2002-10-11 Mark Mitchell <mark@codesourcery.com>
PR c++/5661
@@ -292,16 +1927,44 @@
types as template arguments.
* tree.c (variably_modified_type_p): New function.
-2002-10-11 Jason Molenda <jmolenda@apple.com>
+ * NEWS: Document removal of "new X = ..." extension.
+ * class.c (initialize_array): Set TREE_HAS_CONSTRUCTOR on
+ brace-enclosed initializers.
+ * cp-tree.h (CP_AGGREGATE_TYPE_P): New macro.
+ (initialize_local_var): Remove declaration.
+ (expand_static_init): Likewise.
+ * decl.c (next_initializable_field): New function.
+ (reshape_init): Likewise.
+ (check_initializer): Use them. Build dynamic initializer for
+ aggregates here too.
+ (initialize_local_var): Simplify, and incorporate cleanup
+ insertion code as well.
+ (destroy_local_var): Remove.
+ (cp_finish_decl): Tidy.
+ (expand_static_init): Fold checks for whether or not a variable
+ needs initialization into this function. Simplify.
+ * decl2.c (do_static_initialization): Simplify.
+ * init.c (build_init): Do not set TREE_SIDE_EFFECTS when it will
+ be done for us automatically.
+ (expand_default_init): Handle brace-enclosed initializers
+ correctly.
+ (expand_aggr_init_1): Remove RTL-generation code.
+ (build_vec_init): Remove "new X = ..." support.
+ * parse.y (new_initializer): Likewise.
+ * rtti.c (get_pseudo_ti_init): Set TREE_HAS_CONSTRUCTOR on
+ brace-enclosed initializer.
+ (create_pseudo_type_info): Likewise.
+ * typeck2.c (store_init_value): Don't try to handle digest_init
+ being called more than once.
+ (digest_init): Tidy handling of brace-enclosed initializers.
- * init.c (build_field_list): Provide uses_unions_p with a default
- value.
+2002-10-10 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-10-10 Gabriel Dos Reis <gdr@integrable-solutions.net>
+ * decl.c (typename_hash): Use htab_hash_pointer.
- PRs C++/6803, C++/7721 and C++/7803
- * decl.c (grokdeclarator): Gracefully handle template-name as
- decl-specifier.
+2002-10-10 Jim Wilson <wilson@redhat.com>
+
+ * decl.c (duplicate_decls): Don't call decl_attributes.
2002-10-09 Zack Weinberg <zack@codesourcery.com>
@@ -311,6 +1974,10 @@
(cp_finish_decl): Remove special case for TYPE_DECL with initializer.
(grokdeclarator): Remove redundant error for 'typedef foo = bar'.
+2002-10-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * decl2.c (prune_vtable_vardecl): Delete unused function.
+
2002-10-03 Mark Mitchell <mark@codesourcery.com>
PR c++/7754
@@ -322,23 +1989,17 @@
2002-10-07 Richard Henderson <rth@redhat.com>
- * decl2.c: Complete reversion of c++/7754.
+ * decl2.c, pt.c: Revert c++/7754 fix.
-2002-10-06 Roger Sayle <roger@eyesopen.com>
-
- PR optimization/6627
- * cp/cp-tree.h (enum ptrmemfunc_vbit_where_t): Delete definition
- from here, and move it to tree.h.
- * cp/decl.c (cxx_init_decl_processing): If storing the vbit
- in function pointers, ensure that force_align_functions_log
- is atleast one.
+2002-10-05 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
-2002-10-04 H.J. Lu (hjl@gnu.org)
+ PR c++/7804
+ * error.c (dump_expr) [REAL_CST]: Output in decimal format.
- * pt.c (tsubst_decl, case VAR_DECL): Back out the last change.
- (tsubst_expr, case DECL_STMT): Likewise.
+2002-10-03 Mark Mitchell <mark@codesourcery.com>
-2002-10-02 Mark Mitchell <mark@codesourcery.com>
+ PR c++/7931
+ * pt.c (for_each_template_parm_r): Handle BASELINKs.
PR c++/7754
* decl2.c (finish_anon_union): Do not expand anonymous unions when
@@ -347,54 +2008,644 @@
type. Call layout_decl.
(tsubst_expr, case DECL_STMT): Handle anonymous unions.
+2002-10-03 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/8006
+ * mangle.c (CLASSTYPE_TEMPLATE_ID_P): Handle instances of template
+ template parameters.
+ (globals): Add entity and need_abi_warning.
+ (decl_is_template_id): Use TYPE_TEMPLATE_INFO, not
+ CLASSTYPE_TEMPLATE_INFO.
+ (is_std_substitution): Use CLASSTYPE_TI_TEMPLATE, not
+ TYPE_TI_TEMPLATE.
+ (write_prefix): Handle typename types correctly.
+ (write_template_prefix): Handle template template parameters
+ correctly.
+ (start_mangling): Add entity parameter.
+ (finish_mangling): Warn about names whose mangling will change.
+ (mangle_decl_string): Adjust.
+ (mangle_type_string): Likewise.
+ (mangle_special_for_type): Likewise.
+ (mangle_ctor_vtbl_for_type): Likewise.
+ (mangle_thunk): Likewise.
+ (mangle_guard_variable): Likewise.
+ (mangle_ref_init_variable): Likewise.
+
2002-10-02 Mark Mitchell <mark@codesourcery.com>
PR c++/7188.
- * init.c (expand_member_init): Allow a FIELD_DECL to be passed in
- directly.
- * pt.c (tsubst_initializer_list): Use expand_member_init.
+ * cp-tree.def (CTOR_INITIALIZER): Use one slot, not two.
+ * cp-tree.h (emit_base_init): Rename to ....
+ (emit_mem_initializers): ... this.
+ (expand_member_init): Change prototype.
+ * init.c (perform_member_init): Compute explicit, rather than
+ requiring it as a parameter.
+ (sort_member_init): Rename to ...
+ (sort_mem_initializers): ... this. Process bases and data members
+ together.
+ (sort_base_init): Remove.
+ (emit_base_init): Rename to ...
+ (emit_mem_initializers): ... this.
+ (expand_aggr_vbase_init_1): Remove.
+ (construct_virtual_bases): Rename to ...
+ (construct_virtual_base): ... this.
+ (expand_member_init): Rework handling of base initializers.
+ * method.c (do_build_copy_constructor): Use
+ finish_mem_initializers.
+ * parse.y (member_init): Adjust calls to expand_member_init.
+ * pt.c (tsubst_expr): Simplify CTOR_INITIALIZER case.
+ (tsubst_initializer_list): Use expand_member_init.
+ * semantics.c (finish_mem_intiailizers): Simplify.
+
+2002-10-02 Matt Austern <austern@apple.com>
+ * decl.c (walk_vtables_r): Fixed typo that caused result to
+ never get a nonzero value.
+
+2002-10-02 Roger Sayle <roger@eyesopen.com>
+
+ PR optimization/6627
+ * cp-tree.h (enum ptrmemfunc_vbit_where_t): Delete definition
+ from here, and move it to tree.h.
+ * decl.c (cxx_init_decl_processing): If storing the vbit
+ in function pointers, ensure that force_align_functions_log
+ is atleast one.
+
+2002-10-02 Matt Austern <austern@apple.com>
+
+ * class.c (check_field_decls): Changed warning about const member
+ variables so that it doesn't get issued for a class aggregate.
+
+2002-10-01 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (cp_finish_decl): Make sure array types are laid out,
+ even if the array bounds are unknown.
+
+2002-10-01 Steve Ellcey <sje@cup.hp.com>
+
+ * class.c (build_vtbl_initializer): Change build_c_cast
+ to build1.
+
+2002-10-01 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (cp_finish_decl): Make sure array types are laid out,
+ even if the array bounds are unknown.
+
+ * decl.c (cp_finish_decl): Correct check for dynamic
+ initialization of thread-local storage.
+
+2002-09-30 Nathan Sidwell <nathan@codesourcery.com>
+
+ * tree.c (really_overloaded_fn): TEMPLATE_ID_EXPRs are also
+ overloaded.
+
+2002-09-30 Steve Ellcey <sje@cup.hp.com>
+
+ * class.c (build_vtbl_initializer): Add cast.
+ (add_vcall_offset_vtbl_entries_1):
+ Use TARGET_VTABLE_DATA_ENTRY_DISTANCE for offset.
+
+2002-09-30 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (walk_subobject_offsets): Correct the calculation of
+ offsets for virtual bases. Correct the counting of array
+ elements.
+ (layout_nonempty_base_or_field): Simplify. Correct the
+ calculation of offsets to be propagated through the binfo
+ hierarchy.
+ (build_base_field): Avoid creating a FIELD_DECL for empty bases.
+ Add the FIELD_DECL to TYPE_FIELDS.
+ (build_base_fields): Adjust accordingly.
+ (layout_virtual_bases): Use build_base_field.
+ (end_of_class): Return a tree, not an integer.
+ (warn_about_ambiguous_direct_bases): Rename to ...
+ (warn_about_ambiguous_bases): ... this.
+ (include_empty_classes): New function.
+ (layout_class_type): Create an alternative version of the type to
+ be used when as a base class type. Do not call
+ finish_record_layout until we are done laying out the class.
+ * cp-tree.h (lang_type_class): Remove size, size_unit. Add
+ as_base.
+ (CLASSTYPE_SIZE): Reimplement.
+ (CLASSTYPE_SIZE_UNIT): Likewise.
+ (CLASSTYPE_ALIGN): Likweise.
+ (CLASSTYPE_USER_ALIGN): Likewise.
+ (CLASSTYPE_AS_BASE): New macro.
+ (DECL_INITIALIZED_P): Likewise.
+ (extract_init): Remove prototype.
+ (build_forced_zero_init): Rename to ...
+ (build_zero_init): ... this.
+ (force_store_init_value): Remove.
+ * decl.c (obscure_complex_init): Remove.
+ (duplicate_decls): Copy DECL_INITIALIZED_P.
+ (check_initializer): Do not leave junk in DECL_INITIAL.
+ (cp_finish_decl): Handle zero-initialization of entities with
+ static storage duration.
+ * expr.c (extract_init): Remove.
+ * init.c (build_forced_zero_init): Remove.
+ (build_zero_init): New function.
+ (build_default_init): Use it.
+ (build_field_list): Skip FIELD_DECLs for base subobjects.
+ (push_base_cleanups): Likewise.
+ * method.c (do_build_assign_ref): Likewise.
+ (synthesize_exception_spec): Likewise.
+ * pt.c (tsubst_decl): Clear DECL_INITIALIZED_P.
+ (regenerate_decl_from_template): To not set DECL_INITIAL for a
+ static data member whose initialization took place in its class.
+ (instantiate_decl): Do not pass an initializer to cp_finish_decl
+ in that situation.
+ * search.c (dfs_push_decls): Skip FIELD_DECLs for base subobjects.
+ (dfs_unuse_fields): Likewise.
+ * tree.c (pod_type_p): Handle error_mark_node.
+ (zero_init_p): Likewise.
+ * typeck.c (lookup_anon_field): Skip FIELD_DECLs for base
+ subobjects.
+ * typeck2.c (store_init_value): Remove #if 0'd code.
+ (force_store_init_value): Remove.
+ (process_init_constructor): Use build_zero_init.
+
+2002-09-29 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/7788
+ * rtti.c (unemitted_tinfo_decl_p): Check it has a field.
+
+2002-09-29 Kazu Hirata <kazu@cs.umass.edu>
+
+ * cp-tree.h: Fix comment typos.
+ * decl.c: Likewise.
+ * pt.c: Likewise.
+
+2002-09-25 Mark Mitchell <mark@codesourcery.com>
+
+ * cp/class.c (contains_empty_class_p): New method.
+ (walk_subobject_offsets): Correct computation of field offset.
+ (layout_empty_base): Correct placement of emtpy base classes.
+ (layout_class_type): Warn about ABI changes.
+
+2002-09-23 Mark Mitchell <mark@codesourcery.com>
+
+ * cp/class.c (layout_virtual_bases): Do not round the size of the
+ type to a multiple of the alignment before laying out virtual bases.
+ (layout_class_type): Correct handling of bit-fields that are wider
+ than their type inside unions. Round the size of the type to a
+ even number of bytes when computing the size without virtual
+ bases.
+ * cp/cp-tree.h (abi_version_at_least): New macro.
+
+2002-09-21 Kazu Hirata <kazu@cs.umass.edu>
+
+ * ChangeLog: Follow spelling conventions.
+ * ChangeLog.2: Likewise.
+ * call.c: Likewise.
+ * class.c: Likewise.
+ * cp-tree.h: Likewise.
+ * cvt.c: Likewise.
+ * decl.c: Likewise.
+ * decl2.c: Likewise.
+ * except.c: Likewise.
+ * friend.c: Likewise.
+ * g++spec.c: Likewise.
+ * init.c: Likewise.
+ * lex.c: Likewise.
+ * mangle.c: Likewise.
+ * method.c: Likewise.
+ * operators.def: Likewise.
+ * optimize.c: Likewise.
+ * pt.c: Likewise.
+ * rtti.c: Likewise.
+ * search.c: Likewise.
+ * semantics.c: Likewise.
+ * spew.c: Likewise.
+ * tree.c: Likewise.
+ * typeck.c: Likewise.
+
+2002-09-18 Devang Patel <dpatel@apple.com>
+
+ * cp/cp-tree.h: New prototype for walk_vtabls().
+ * cp/decl.c (walk_vtables_r): New function.
+ (struct cp_binding_level): Add new members, namespaces,
+ names_size and vtables.
+ (add_decl_to_level): Add decl in namespaces or vtables
+ chain, if conditions match.
+ (walk_vtables): New function.
+ (walk_namespaces_r): Travers separate namespace chain
+ for namespace decls.
+ (wrapup_globals_for_namespace): Use names_size instead
+ of list_length().
+ * cp/decl2.c (finish_file): Use walk_vtables() instead of
+ walk_globals() to walk vtable decls.
+
+2002-09-18 Nathan Sidwell <nathan@codesourcery.com>
+
+ * decl.c (grokdeclarator): Use assert, not internal_error. Don't
+ ICE with invalid pointers & references.
+
+2002-09-17 Zack Weinberg <zack@codesourcery.com>
+
+ * Make-lang.in: Remove all references to the demangler.
+ * cxxfilt.c: Moved to binutils.
+
+2002-09-16 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/7718
+ * pt.c (tsubst_decl): Remove assert.
+
+ Remove DR 295 implementation.
+ * pt.c (check_cv_quals_for_unify): Disable function & method cases.
+ * tree.c (cp_build_qualified_type_real): Likewise. Don't warn
+ about ignoring volatile qualifiers.
+
+ * search.c (lookup_member): Correct documentation.
+
+2002-09-16 Geoffrey Keating <geoffk@apple.com>
+
+ * cp-tree.h (union lang_tree_node): Add chain_next option.
+
+2002-09-16 Nathan Sidwell <nathan@codesourcery.com>
+
+ * parse.y (parse_finish_call_expr): Check lookup_member result.
+
+ PR c++/7015
+ * semantic.c (finish_asm_stmt): Fix operand/output_operands
+ thinko.
+ * typeck.c (c_expand_asm_operands): Protect from error_mark_node.
+
+2002-09-15 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/7919
+ * call.c (build_over_call): Convert this pointer for fns found by
+ using decls.
+
+2002-09-15 Kazu Hirata <kazu@cs.umass.edu>
+
+ * ChangeLog: Follow spelling conventions.
+ * ChangeLog.1: Likewise.
+
+2002-09-14 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/7768
+ * pt.c (build_template_decl): Copy DECL_DESTRUCTOR_P.
+
+2002-09-14 Kazu Hirata <kazu@cs.umass.edu>
+
+ * error.c: Fix comment formatting.
+ * except.c: Likewise.
+ * expr.c: Likewise.
+ * friend.c: Likewise.
+ * g++spec.c: Likewise.
+ * init.c: Likewise.
+ * lex.c: Likewise.
+ * mangle.c: Likewise.
+ * method.c: Likewise.
+ * optimize.c: Likewise.
+ * pt.c: Likewise.
+ * rtti.c: Likewise.
+ * search.c: Likewise.
+ * semantics.c: Likewise.
+ * spew.c: Likewise.
+ * tree.c: Likewise.
+ * typeck.c: Likewise.
+ * typeck2.c: Likewise.
+
+2002-09-13 Matt Austern <austern@apple.com>
+
+ PR C++/7828
+ * cp/cp-tree.h, cp/tree.c: New function non_cast_lvalue_p.
+ * cp/call.c: Change call-by-const-reference mechanism to use
+ non_cast_lvalue_p when deciding whether the create a temporary.
+ We need a temporary when passing, e.g. (long) x by const ref.
+
+2002-09-13 Nathan Sidwell <nathan@codesourcery.com>
+
+ * pt.c (unify, ARRAY_TYPE): Element type can be more qualified.
+
+2002-09-13 Kazu Hirata <kazu@cs.umass.edu>
+
+ * decl.c: Fix comment formatting.
+ * decl2.c: Likewise.
+
+2002-09-12 Kazu Hirata <kazu@cs.umass.edu>
+
+ * call.c: Fix comment formatting.
+ * class.c: Likewise.
+ * cp-lang.c: Likewise.
+ * cp-tree.h: Likewise.
+ * cvt.c: Likewise.
+
+2002-09-11 Zack Weinberg <zack@codesourcery.com>
+
+ * Make-lang.in: Build cp/cxxfilt.o from $(srcdir)/cp/cxxfilt.c,
+ and c++filt from cxxfilt.o + version.o + $(LIBDEPS).
+ * cxxfilt.c: New file: split from libiberty/cplus-dem.c, with
+ minor adjustments (use version_string, eliminate yet another
+ duplicate of xmalloc)
+
+2002-09-08 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cp-tree.h (require_complete_eh_spec_types): Add prototype.
+
+2002-09-05 Jason Merrill <jason@redhat.com>
+
+ * typeck2.c (add_exception_specifier): Only pedwarn for an
+ incomplete type.
+ (require_complete_eh_spec_types): New fn.
+ (cxx_incomplete_type_diagnostic): Also support pedwarning.
+ * typeck.c (complete_type_or_diagnostic): Likewise.
+ * call.c (build_call): Call require_complete_eh_spec_types.
+ * rtti.c (get_pseudo_ti_desc): Give an error rather than aborting
+ on an incomplete type.
2002-09-04 Jakub Jelinek <jakub@redhat.com>
* decl.c (start_cleanup_fn): Clear interface_only before
start_function, restore it afterwards.
-2002-09-01 Alexandre Oliva <aoliva@redhat.com>
+2002-08-31 Jason Merrill <jason@redhat.com>
- * parse.y (sizeof, alignof, typeof): New non-terminals to
- increment skip_evaluation. Replace terminals with them and
- decrement skip_evaluation at the end of rules using them.
- * decl2.c (mark_used): Don't assemble_external if
- skipping evaluation.
+ * cp-lang.c (cp_expr_size): Allow initialization from a
+ CONSTRUCTOR.
-2002-08-31 Jason Merrill <jason@redhat.com>
+2002-08-30 Richard Henderson <rth@redhat.com>
- * cp-lang.c (cp_expr_size): Don't abort.
+ PR opt/7515
+ * tree.c: Include target.h.
+ (cp_cannot_inline_tree_fn): Don't auto-inline functions that
+ don't bind locally.
+ * Makefile.in (tree.o): Update.
2002-08-27 Mark Mitchell <mark@codesourcery.com>
- * cp-tree.h (warn_abi): Declare it.
- * decl.c (warn_abi): Define it.
- (cxx_decode_option): Set it.
* class.c (layout_virtual_bases): Warn about bugs in G++ that
result in incorrect object layouts.
(layout_class_type): Likewise.
+2002-08-24 Matt Austern <austern@apple.com>
+
+ * tree.c (lvalue_p_1): Add argument for whether casts of lvalues
+ are allowable.
+ (real_lvalue_p): Update caller.
+ (lvalue_p): Ditto.
+ (non_cast_lvalue_or_else): New.
+ * tree.h: Declare it.
+ * typeck.c (build_unary_op): Use non_cast_lvalue_or_else.
+
+2002-08-22 Mark Mitchell <mark@codesourcery.com>
+
+ * typeck.c (build_class_member_access_expr): Handle COMPOUND_EXPR
+ and COND_EXPR specially; fix error message output.
+
2002-08-22 Jason Merrill <jason@redhat.com>
- PR c++/5607
- * search.c (check_final_overrider): No longer static.
- * class.c (update_vtable_entry_for_fn): Call it.
- * cp-tree.h: Adjust.
+ * pt.c (tsubst_expr): RETURN_EXPR is now RETURN_STMT_EXPR.
+ * semantics.c (nullify_returns_r): Likewise.
- * cp-lang.c (LANG_HOOKS_EXPR_SIZE): Define.
- (cp_expr_size): New fn.
- * call.c (convert_arg_to_ellipsis): Promote non-POD warning to error.
- * typeck.c (build_modify_expr): Don't use save_expr on an lvalue.
+2002-08-17 Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+ Fix PR/7621
+ * typeck.c (finish_class_member_access_expr): Diagnose cases where
+ name lookup finds nothing.
+
+2002-08-15 Jason Merrill <jason@redhat.com>
+
+ * semantics.c (finish_then_clause): Remove redundant assignment.
+ (finish_if_stmt, begin_switch_stmt, finish_switch_stmt): Move the
+ extra binding level outside the if/switch statement.
+ (finish_while_cond, finish_for_cond): Rewrite complex condition
+ into the loop body.
+
+2002-08-15 Alexandre Oliva <aoliva@redhat.com>
+
+ * parse.y (sizeof, alignof, typeof): New non-terminals to
+ increment skip_evaluation. Replace terminals with them and
+ decrement skip_evaluation at the end of rules using them.
+ * decl2.c (mark_used): Don't assemble_external if
+ skipping evaluation.
+
+2002-08-15 Gabriel Dos Reis <gdr@nerim.net>
+
+ Fix PR/7504
+ * parse.y (parse_finish_call_expr): Handle incomplete
+ type used to name a scope.
+
+2002-08-15 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/7598
+ * typeck.c (build_unary_op): Fold offsetof idiom. Fixes
+ regression caused by my 2002-08-08 patch.
+
+2002-08-13 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (pushdecl_class_level): Honor requests to bind names to
+ OVERLOADs.
+
+2002-08-11 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * decl2.c (build_call_from_tree): Fix uninitialized variable.
+ * parse.y (parse_finish_call_expr): Likewise.
+ * repo.c (old_args, old_dir, old_main): Const-ify.
+
+2002-08-11 Gabriel Dos Reis <gdr@nerim.net>
+
+ * decl.c (duplicate_decls): Replace DECL_SOURCE_FILE +
+ DECL_SOURCE_LINE with DECL_SOURCE_LOCATION.
+ * optimize.c (maybe_clone_body): Likewise.
+ * pt.c (tsubst_enum): Likewise.
+ (lookup_template_class): Likewise.
+ * tree.c (cp_copy_res_decl_for_inlining): Likewise.
+
+2002-08-10 Neil Booth <neil@daikokuya.co.uk>
+
+ * lang-specs.h: Remove -ansi.
+
+2002-08-10 Nathan Sidwell <nathan@codesourcery.com>
+
+ * tree.c (maybe_dummy_object): Replace // with /* */
+
+2002-08-09 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (standard_conversion): Use build_ptrmem_type.
+ * cp-tree.h (build_ptrmem_type): New function.
+ (adjust_result_of_qualified_name_lookup): Likewise.
+ * decl.c (grokvardecl): Do not look for OFFSET_TYPEs to indicate
+ static data members.
+ (build_ptrmem_type): New function.
+ (grokdeclarator): Do not use build_offset_type when encountering a
+ qualified name.
+ * parse.y (parse_finish_call_expr): Use
+ adjust_result_of_qualified_name_lookup.
+ * search.c (adjust_result_of_qualified_name_lookup): New function.
+ * typeck.c (qualify_type_recursive): Use TYPE_PTRMEM_* rather than
+ accessing OFFSET_TYPEs directly.
+
+2002-08-08 Mike Stump <mrs@apple.com>
+
+ * call.c (add_builtin_candidate): legal -> valid, illegal -> invalid.
+ (type_decays_to): Likewise.
+ * class.c (find_final_overrider): Likewise.
+ (maybe_note_name_used_in_class): Likewise.
+ * decl.c (current_tmpl_spec_kind): Likewise.
+ (add_binding): Likewise.
+ (push_class_binding): Likewise.
+ (duplicate_decls): Likewise.
+ (layout_var_decl): Likewise.
+ (grokfndecl): Likewise.
+ (grokdeclarator): Likewise.
+ (check_default_argument): Likewise.
+ * decl2.c (handle_class_head): Likewise.
+ * error.c (dump_template_decl): Likewise.
+ * init.c (build_offset_ref): Likewise.
+ * pt.c (check_specialization_scope): Likewise.
+ (determine_specialization): Likewise.
+ (check_explicit_specialization): Likewise.
+ (maybe_check_template_type): Likewise.
+ (process_partial_specialization): Likewise.
+ (check_default_tmpl_args): Likewise.
+ (push_template_decl_real): Likewise.
+ (convert_template_argument): Likewise.
+ (try_class_unification): Likewise.
+ (get_bindings_real): Likewise.
+ (do_decl_instantiation): Likewise.
+ * semantics.c (begin_function_definition): Likewise.
+ (finish_member_declaration): Likewise.
+ (check_multiple_declarators): Likewise.
+ * typeck.c (comp_array_types): Likewise.
+ (comptypes): Likewise.
+ (expr_sizeof): Likewise.
+ (build_binary_op): Likewise.
+ (dubious_conversion_warnings): Likewise.
+ (check_return_expr): Likewise.
+
+2002-08-08 Mark Mitchell <mark@codesourcery.com>
+
+ * typeck.c (build_class_member_access_expr): Do not return
+ error_mark_node when no error has occurred.
+
+2002-08-08 Nathan Sidwell <nathan@codesourcery.com>
+
+ * typeck.c (build_component_addr): Remove.
+ (build_unary_op): Just check it's not a bitfield, and then build
+ an ADDR_EXPR.
+
+2002-08-08 Nathan Sidwell <nathan@codesourcery.com>
+
+ * class.c (convert_to_base): Correct check for error_mark_node.
+ (create_vtable_ptr): Remove unused VFUNS_P parm.
+
+2002-08-08 Nathan Sidwell <nathan@codesourcery.com>
+
+ * cp/Make-lang.in (c++.mostlyclean): Remove coverage files.
+
+2002-08-07 Mark Mitchell <mark@codesourcery.com>
+
+ Rework build_component_ref.
+ * call.c (build_vfield_ref): Do not go through build_component_ref.
+ (build_field_call): Use build_class_member_access_expr.
+ (build_user_type_conversion_1): Use BASELINK_FUNCTIONS.
+ (build_object_call): Likewise.
+ * class.c (convert_to_base): New function.
+ (type_requires_array_cookie): Use BASELINK_FUNCTIONS.
+ (instantiate_type): Handle BASELINKs.
+ * cp-tree.def (BASELINK): New tree code.
+ * cp-tree.h (BASELINK_P): Reimplement.
+ (SET_BASELINK_P): Remove.
+ (BASELINK_BINFO): Reimplement.
+ (BASELINK_FUNCTIONS): Likewise.
+ (BASELINK_ACCESS_BINFO): Likewise.
+ (BASELINK_OPTYPE): Likewise.
+ (convert_to_base): New function.
+ (name_p): Likewise.
+ (build_object_ref): Remove.
+ (build_component_ref_1): Likewise.
+ (build_component_ref): Likewise.
+ (build_x_component_ref): Likewise.
+ (build_class_member_access_expr): New function.
+ (finish_class_member_access_expr): Likewise.
+ (build_ptrmemfunc_access_expr): Likewise.
+ * decl.c (grokdeclarator): Handle BASELINKs.
+ * decl2. (build_expr_from_tree): Handle COMPONENT_REFs by using
+ finish_class_member_access_expr.
+ (arg_assoc): Handle BASELINKs.
+ (do_class_using_decl): Likewise.
+ * error.c (dump_decl): Likewise.
+ (dump_expr): Use build_ptrmemfunc_access_expr.
+ * except.c (dtor_nothrow): Use CLASSTYPE_DESTRUCTORS to find
+ destructors.
+ (build_throw): Use BASELINK_FUNCTIONS.
+ * init.c (perform_member_init): Use
+ build_class_member_access_expr.
+ (build_offset_ref): Handle BASELINKs. Use
+ build_class_member_access_expr.
+ * method.c (hack_identifier): Likewise.
+ * parse.y (do_id): Use BASELINK, not TREE_LIST.
+ (primary): Remove uses of build_object_ref.
+ * pt.c (lookup_template_function): Handle BASELINKs.
+ (resolve_overloaded_unification): Likewise.
+ * search.c (build_baselink): Build a BASELINK, not a TREE_LIST.
+ (lookup_field): Use BASELINK, not TREE_LIST.
+ (lookup_fnfiels): Likewise.
+ (setup_class_bindings): Likewise.
+ * semantics.c (finish_object_call_expr): Do not use
+ build_method_call when we already know what function is being
+ called.
+ * spew.c (identifier_type): Use BASELINK, not TREE_LIST.
+ * tree.c (really_overloaded_fn): Use OVL_CHAIN for OVERLOADs, not
+ TREE_CHAIN.
+ (name_p): New function.
+ * typeck.c (build_object_ref): Remove.
+ (build_component_ref_1): Likewise.
+ (build_x_component_ref): Likewise.
+ (build_class_member_access_expr): New function.
+ (finish_class_member_access_expr): Likewise.
+ (build_ptrmemfunc_access_expr): Likewise.
+ (get_member_function_from_ptrfunc): Use
+ build_ptrmemfunc_access_expr.
+ (build_binary_op): Likewise.
+ (build_unary_op): Likewise.
+ (build_ptrmemfunc): Likewise.
+ (pfn_from_ptrmemfunc): Likewise.
+ * typeck2.c (build_m_component_ref): Adjust comment.
+
+2002-08-07 Neil Booth <neil@daikokuya.co.uk>
+
+ * Make-lang.in (CXX_C_OBJS): Update.
+ * cp-lang.c (LANG_HOOKS_DECODE_OPTION): Use c_common_decode_option.
+ * cp-tree.h (cxx_decode_option): Remove.
+ * decl2.c (compare_options, lang_f_options, unsupported_options,
+ cxx_decode_option): Remove.
+
+2002-08-06 Gabriel Dos Reis <gdr@nerim.net>
+
+ * typeck.c (build_x_unary_op): Handle pointer-to-member.
-2002-08-14 Release Manager
+2002-08-05 Geoffrey Keating <geoffk@redhat.com>
- * GCC 3.2 Released.
+ * class.c: Don't include obstack.h.
+ (popclass):
+ * decl2.c: Delete bogus comment.
+ * error.c: Don't include obstack.h.
+ * except.c: Likewise.
+ (dump_type): Correct comment.
+ * method.c: Don't include obstack.h.
+ * tree.c: Likewise.
+
+2002-08-04 Gabriel Dos Reis <gdr@nerim.net>
+
+ Fix PR/2213
+ * cvt.c (cp_convert_to_pointer): Reject conversions from integral
+ expressions to pointer-to-data-member of pointer-to-member-functions.
+
+2002-08-04 Geoffrey Keating <geoffk@redhat.com>
+
+ * cvt.c (ocp_convert): Delete obsolete code.
+ * parse.y (permanent_obstack): Delete declaration.
+ * pt.c (permanent_obstack): Delete declaration.
+ * repo.c (permanent_obstack): Delete declaration.
+ (open_repo_file): Use xmalloc instead of permanent_obstack.
+ (init_repo): Use xstrdup instead of permanent_obstack.
+
+2002-08-04 Nathan Sidwell <nathan@codesourcery.com>
+
+ * cp-tree.h (VF_DERIVED_VALUE): Remove.
+ * class.c (finish_struct_1): Use VF_BINFO_VALUE not VF_DERIVED_VALUE.
2002-08-03 Nathan Sidwell <nathan@codesourcery.com>
@@ -409,82 +2660,284 @@
(layout_class_type): Take single list of virtuals. Adjust.
(finish_struct_1): Keep virtuals on single list. Adjust.
+2002-08-02 Mark Mitchell <mark@codesourcery.com>
+
+ * init.c (build_member_call): Use build_new_method_call, not
+ build_method_call.
+
+2002-08-02 Krister Walfridsson <cato@df.lth.se>
+
+ * Make-lang.in (spew.o, lex.o, pt.o): Add path to parse.h dependencies.
+
+2002-08-02 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_method_call): Issue a more helpful error message
+ about ambiguous method names.
+
+2002-08-02 Nathan Sidwell <nathan@codesourcery.com>
+
+ * tree.c (build_shared_int_cst): Make cache file scope, and
+ GTY it.
+
+2002-08-02 Jason Merrill <jason@redhat.com>
+
+ * cp-lang.c (LANG_HOOKS_EXPR_SIZE): Define.
+ (cp_expr_size): New fn.
+ * call.c (build_over_call): Lose empty class hackery.
+ (convert_arg_to_ellipsis): Promote non-POD warning to error.
+ * typeck.c (build_modify_expr): Don't use save_expr on an lvalue.
+
+ * semantics.c (expand_body): Do tree optimization in the function
+ context, too.
+
+2002-08-01 Neil Booth <neil@daikokuya.co.uk>
+
+ * cp-tree.h: Move all warning and flag declarations to c-common.h.
+ * decl.c: Move all warning and flag variables to c-common.c.
+ * decl2.c: Move all warning and flag variables to c-common.c.
+ * lex.c (flag_digraphs): Remove.
+ (warn_traditional): Now in c-common.c.
+
+2002-07-31 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_field_call): Do not look up the field by name.
+ (build_method_call): Simplify.
+ (struct z_candidate): Add access_path and conversion_path. Remove
+ basetype_path.
+ (convert_class_to_reference): Adjust use of
+ add_function_candidate.
+ (add_candidate): Add conversion_path argument.
+ (add_function_candidate): Use it.
+ (add_conv_dndidate): Likewise.
+ (build_builtin_candidate): Likewise.
+ (add_template_candidate_real): Add conversion_path argument.
+ (add_template_conv_candidate): Likewise.
+ (add_template_candidate): Likewise.
+ (build_user_type_conversion_1): Use it.
+ (build_new_function_call): Remove name lookup code. Adjust use of
+ add_template_candidate and add_function_candidate.
+ (build_new_op): Likewise.
+ (convert_like_real): Use build_special_member_call.
+ (build_over_call): Use cand->conversion_path.
+ (build_special_member_call): New method.
+ (build_new_method_call): Remove name lookup code.
+ * cp-tree.def (OFFSET_REF): Update documentation.
+ (TEMPLATE_ID_EXPR): Likewise.
+ * cp-tree.h (BASELINK_ACCESS_BINFO): New macro.
+ (BASELINK_OPTYPE): Likewise.
+ (build_new_method_call): Adjust prototype.
+ (build_special_member_call): New method.
+ (build_baselink): New method.
+ (build_offset_ref_call_from_tree): Likewise.
+ (build_call_from_tree): Likewise.
+ (finish_qualified_call_expr): Remove.
+ (finish_call_expr): Adjust prototype.
+ (build_x_function_call): Remove.
+ * cvt.c (ocp_convert): Use build_special_member_call.
+ * decl2.c (reparse_absdcl_as_expr): Use finish_call_expr.
+ (build_expr_from_tree): Adjust handling for TEMPLATE_ID_EXPR and
+ CALL_EXPR.
+ (build_offset_ref_call_from_tree): New function.
+ (build_call_from_tree): Likewise.
+ * init.c (expand_cleanup): Use build_special_member_call.
+ (expand_default_init): Likewise.
+ (build_member_call): Use finish_call_expr.
+ (build_new_1): Use build_special_member_call.
+ (push_base_cleanups): Likewise.
+ * method.c (do_build_assign_ref): Likewise.
+ * parse.y (template_id): Do not pass a COMPONENT_REF to
+ lookup_template_function.
+ (primary): Use parse_finish_call_epxr, not finish_call_expr.
+ (parse_finish_call_expr): New function.
+ * pt.c (lookup_template_function): Add assertions.
+ * search.c (lookup_base): Allow T to be a binfo.
+ (build_baselink): New function.
+ (lookup_member): Use it.
+ * semantics.c (finish_call_expr): Do not do name lookup.
+ (finish_object_call_expr): Remove #if 0'd code.
+ (finish_qualified_call_expr): Remove.
+ * typeck.c (build_x_function_call): Remove.
+ (build_static_case): Use build_special_member_call.
+ * typeck2.c (build_functional_cast): Likewise.
+
2002-07-30 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
* lang-specs.h: Remove __GXX_ABI_VERSION, moved to gcc.c.
-2002-07-17 Scott Snyder <snyder@fnal.gov>
+2002-07-30 Gabriel Dos Reis <gdr@nerim.net>
- PR c++/7320
- * rtti.c (get_tinfo_decl): Set DECL_COMDAT.
+ * cp-tree.h (VF_DERIVED_VALUE): Restore from previous deletion.
-2002-07-05 Nathan Sidwell <nathan@codesourcery.com>
+2002-07-30 Nathan Sidwell <nathan@codesourcery.com>
- Repair damage on weak-impared targets caused by my previous patch.
- * cp-tree.h (import_export_tinfo): Add parameter.
- * decl2.c (import_export_tinfo): Add parameter, post adjust
- DECL_COMDAT.
- * rtti.c (emit_tinfo_decl): DECL_COMDAT is (nearly) always setup by
- import_export_tinfo.
+ * cp-tree.h (CLASSTYPE_VFIELDS, VF_*, BV_*): Add more
+ documentation.
-2002-06-30 Nathan Sidwell <nathan@codesourcery.com>
+2002-07-29 Alan Modra <amodra@bigpond.net.au>
- * cp-tree.h (CPTI_TINFO_DECL_TYPE): Replace with ...
- (CPTI_TYPE_INFO_PTR_TYPE): ... this.
- (tinfo_decl_type): Replace with ...
- (type_info_ptr_type): ... this.
- (import_export_tinfo): Declare.
- (tinfo_decl_p): Rename to ...
- (unemitted_tinfo_decl_p): ... this.
- * decl2.c (import_export_decl): Break out tinfo handling into ...
- (import_export_tinfo): ... here. New function.
- (finish_file): Adjust.
- * rtti.c (TINFO_REAL_NAME): New macro.
- (init_rtti_processing): Create the tinfo types.
- (get_tinfo_decl_dynamic): Use type_info_ptr_type, get_tinfo_ptr.
- (get_tinfo_decl): Adjust.
- (get_tinfo_ptr): New function.
- (get_type_id): Use it.
- (tinfo_base_init): Create vtable decl here, if it doesn't exist.
- (ptr_initializer): Use get_tinfo_ptr.
- (ptm_initializer): Likewise.
- (synthesize_tinfo_var): Break into ...
- (get_pseudo_ti_init): ... this. Just create the initializer.
- (get_pseudo_ti_desc): .. and this.
- (create_real_tinfo_var): Remove.
- (create_pseudo_type_info): Don't create the vtable decl here.
- (get_vmi_pseudo_type_info): Remove.
- (create_tinfo_types): Adjust.
- (tinfo_decl_p): Rename to ...
- (unemitted_tinfo_decl_p): ... here. Adjust.
- (emit_tinfo_decl): Adjust. Create the initializer.
+ * cp-tree.h: Comment typo fix.
-2002-06-14 Jason Merrill <jason@redhat.com>
+2002-07-29 Richard Earnshaw <rearnsha@arm.com>
- C++ ABI changes.
- * class.c (build_base_field): Set DECL_PACKED.
- (layout_class_type): Don't use tail padding of PODs.
- * mangle.c (write_unqualified_name): Fix template conversion op
- mangling.
+ * spew.c (space_for_token): Allocate zeroed memory for a new token
+ chunk.
-2002-05-18 Jason Merrill <jason@redhat.com>
+2002-07-27 Roger Sayle <roger@eyesopen.com>
- PR c++/6611
- * decl2.c (import_export_decl): If we clear
- DECL_NOT_REALLY_EXTERN, make sure DECL_EXTERNAL is set.
+ * decl.c (builtin_function_1): No need to explicitly mark
+ BUILT_IN_RETURN and BUILT_IN_EH_RETURN as noreturn.
-2002-05-14 Jason Merrill <jason@redhat.com>
+2002-07-27 Roger Sayle <roger@eyesopen.com>
- * rtti.c (get_tinfo_decl): Don't call comdat_linkage.
- Do set DECL_COMDAT.
- (synthesize_tinfo_var): Take the public decl.
- (create_real_tinfo_var): Likewise. Check DECL_COMDAT.
- (emit_tinfo_decl): Adjust. Call import_export_decl.
- * decl2.c (import_export_decl): Simplify tinfo decl handling.
+ * decl2.c (cxx_decode_option): Support -fno-builtin-foo.
+
+2002-07-26 Jason Merrill <jason@redhat.com>
+
+ * call.c (build_over_call): Likewise.
+ (cp_convert_parm_for_inlining): New fn.
+ (convert_for_arg_passing): New fn.
+ (convert_default_arg, build_over_call): Use it.
+ (type_passed_as): New fn.
+ * pt.c (tsubst_decl): Use it.
+ * decl2.c (cp_build_parm_decl): New fn.
+ (build_artificial_parm): Use it.
+ (start_static_storage_duration_function): Likewise.
+ * decl.c (start_cleanup_fn, grokdeclarater): Likewise.
+ (grokparms): Don't mess with DECL_ARG_TYPE.
+ * typeck.c (convert_arguments): Use convert_for_arg_passing.
+ * cp-lang.c (LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING):
+ Define.
+ * cp-tree.h: Declare new fns.
+
+2002-07-26 Neil Booth <neil@daikokuya.co.uk>
+
+ * cp-tree.h (flag_operator_names): Remove.
+ * decl2.c (flag_operator_names): Remove.
+ (lang_f_options): Remove operator-names.
+ * lex.c (D_OPNAME): Remove.
+ (reswords): Remove operator names.
+ (rid_to_yy): Remove operator names.
+ (init_reswords): No need to handle D_OPNAME.
+ * spew.c (read_process_identifier): There are no operator
+ names.
+
+2002-07-26 Jason Merrill <jason@redhat.com>
+
+ * dump.c (cp_dump_tree): Call c_dump_tree.
+ * Make-lang.in (CXX_C_OBJS): Add c-dump.o.
+
+2002-07-25 Neil Booth <neil@daikokuya.co.uk>
+
+ * error.c (print_whitespace): Remove.
+ * g++spec.c (LIBUNWIND): Move.
+ * mangle.c (mangled_position, write_signed_number): Remove.
+
+2002-07-25 Neil Booth <neil@daikokuya.co.uk>
+
+ * decl2.c (cxx_decode_option): Similarly.
+
+2002-07-25 Gabriel Dos Reis <gdr@nerim.net>
+
+ * cp-tree.h (cxx_sizeof_nowarn): Now a macro.
+ (cxx_sizeof_or_alignof_type): Take a third argument.
+ (cxx_sizeof): Adjust definition.
+ (cxx_alignof): Likewise.
+ * init.c (build_delete): Use cxx_sizeof_nowarn to reflect reality.
+ * typeck.c (cxx_sizeof_or_alignof_type): Take a third argument for
+ complaining.
+ (c_sizeof_nowarn): Remove definition.
+ (build_unary_op): Use cxx_sizeof_nowarn.
+
+2002-07-24 Geoffrey Keating <geoffk@redhat.com>
+
+ * tree.c (cp_build_qualified_type_real): When copying
+ pointer-to-method types, unshare the record that holds
+ the cached pointer-to-member-function type.
+
+2002-07-23 Neil Booth <neil@daikokuya.co.uk>
+
+ * cp-tree.h (FILE_FUNCTION_PREFIX_LEN): Remove.
+
+2002-07-23 Gabriel Dos Reis <gdr@nerim.net>
+
+ Fix PR/7363:
+ * typeck.c (cxx_sizeof_or_alignof_type): New function.
+ (c_sizeof): Remove definition.
+ (expr_sizeof): Use cxx_sizeof.
+ * decl2.c (build_expr_from_tree): Use cxx_sizeof_or_alignof_type.
+ * decl.c (finish_destructor_body): Use cxx_sizeof.
+ * semantics.c (finish_alignof): Likewise.
+ (finish_alignof): Use cxx_alignof.
+ * cp-tree.h (cxx_sizeof, cxx_alignof): New macros.
+ (cxx_sizeof_or_alignof_type): Declare.
+ (my_friendly_assert): Move to ../c-common.h.
+
+2002-07-23 Neil Booth <neil@daikokuya.co.uk>
+
+ * class.c, method.c, pt.c, search.c: Don't define obstack macros.
+
+2002-07-22 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/7347, c++/7348
+ * cp-tree.h (tsubst_flags_t): Add tf_parsing.
+ * decl.c (make_typename_type): Use it.
+ (make_unbound_class_template): Likewise.
+ (lookup_name_real): Don't call type_access_control if scope is
+ template parameter dependent.
+ * parse.y (template_arg): Call make_unbound_class_template with
+ tf_parsing set.
+ (nest_name_specifier): Call make_typename_type with tf_parsing set.
+ (typename_sub0): Likewise.
+ (typename_sub1): Likewise.
+ (instantiate_decl): Push class scope.
+ * pt.c (regenerate_decl_from_template): Call pushclass and popclass
+ for both static variable and member function template.
+ (instantiate_decl) Call pushclass and popclass when tsubst'ing type
+ and arguments.
+ * search.c (type_access_control): Do type access for TEMPLATE_DECL
+ too.
-2002-07-25 Release Manager
+2002-07-20 Roger Sayle <roger@eyesopen.com>
- * GCC 3.1.1 Released.
+ * decl2.c (cxx_decode_option): Simplify -fhandle-exceptions
+ test by using positive_option. Make whitespace consistent.
+
+2002-07-20 Gabriel Dos Reis <gdr@nerim.net>
+
+ * spew.c (struct unparsed_test): Replace 'filename' and 'lineno'
+ members with 'locus'. Adjust use throughout.
+ (struct feed): Likewise.
+ (alloc_unparsed_test): Change prototype, take a 'const location_t *'.
+ Adjust use.
+ (snarf_defarg): Use error(), not error_with_file_and_line().
+
+2002-07-19 Chris Demetriou <cgd@broadcom.com>
+
+ * lang-specs.h (@c++): Include "%2" (cc1plus_spec) wherever
+ cpp_options is included.
+
+2002-07-17 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/2862, c++/2863
+ * pt.c (determine_specialization): Compare the length of
+ TYPE_ARG_TYPES. Tidy.
+
+2002-07-17 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/3797
+ * decl.c (duplicate_decls): Don't propagate inlining parameters from
+ olddecl to newdecl when newdecl is a specialization of the
+ instantiation olddecl.
+
+2002-07-17 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ PR c++/4802, c++/5387
+ * decl.c (make_typename_type): Use enforce_access.
+
+2002-07-17 Scott Snyder <snyder@fnal.gov>
+
+ PR c++/7320
+ * rtti.c (get_tinfo_decl): Set DECL_COMDAT.
2002-07-12 Mark Mitchell <mark@codesourcery.com>
@@ -501,21 +2954,77 @@
* tree.c (cp_copy_res_decl_for_inlining): Also copy
TREE_ADDRESSABLE.
+2002-07-10 Graham Stott <graham.stott@btinternet.com>
+
+ * pt.c (template_parm_this_level_p, push_template_decl_real):
+ Pass depth as int pointer.
+
+2002-07-11 Tim Josling <tej@melbpc.org.au>
+
+ Remove front end hard coding from gengtype.c.
+
+ * config-lang.in (gtfiles): Add files needed for this front end.
+
+2002-07-10 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (unqualified_name_lookup_error): Declare it.
+ (begin_function_definition): Adjust prototype.
+ * lex.c (unqualified_name_lookup_error): New function, split out
+ from ...
+ (do_identifier): ... here.
+ * parse.y (parse_begin_function_definition): New function.
+ (fn.def1): Use it.
+ * semantics.c (begin_function_definition): Accept decl-specifiers
+ and attributes as separate parameters.
+
2002-07-10 Jason Merrill <jason@redhat.com>
PR c++/6255
* decl.c (lookup_name_real): Build a new TYPENAME_TYPE rather than
modifying the old one.
+2002-07-09 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (constructor_name_p): Declare it.
+ (check_template_template_default_arg): Likewise.
+ * class.c (handle_using_decl): Use constructor_name_p.
+ * decl.c (grokdeclarator): Likewise.
+ * decl2.c (constructor_name_p): Define it.
+ * init.c (build_member_call): Use constructor_name_p.
+ * parse.y (template_parm): Use check_template_template_default_arg.
+ * pt.c (check_explicit_specialization): Use constructor_name_p.
+ * semantics.c (check_template_template_default_arg): New function.
+
2002-07-08 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* pt.c (can_complete_type_without_circularity): Add static to
function definition.
-2002-07-05 Jim Wilson <wilson@redhat.com>
+2002-07-08 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (have_extern_spec): Declare it
+ * decl.c (have_extern_spec): Define it.
+ (start_decl): Eliminate use of used_extern_spec.
+ (start_function): Likewise.
+ * parse.y (have_extern_spec): Remove declaration.
+ (used_extern_spec): Likewise.
+ (frob_specs): Eliminate use of used_extern_spec.
+ (.hush_warning): Likewise.
+
+2002-07-07 Mark Mitchell <mark@codesourcery.com>
+
+ * Make-lang.in (cp/parse.o): Depend on decl.h.
+ * cp-tree.h (do_decl_instantiation): Change prototype.
+ * parse.y: Include decl.h.
+ (parse_decl_instantiation): New function.
+ (explicit_instantiation): Use it.
+ * pt.c (do_decl_instantiation): Accept a DECL, not a DECLARATOR
+ and DECLSPECS.
- * decl.c (mark_named_label_lists): Add missing & in call to
- mark_binding_level.
+2002-07-07 Roger Sayle <roger@eyesopen.com>
+
+ * error.c (dump_function_name): Use DECL_TEMPLATE_RESULT for
+ constructor and destructor tests when passed a TEMPLATE_DECL.
2002-07-05 Jason Merrill <jason@redhat.com>
@@ -525,11 +3034,14 @@
PR optimization/7145
* tree.c (cp_copy_res_decl_for_inlining): Also copy DECL_INITIAL.
-2002-05-18 Jason Merrill <jason@redhat.com>
+2002-07-05 Nathan Sidwell <nathan@codesourcery.com>
- PR c++/6611
- * decl2.c (import_export_decl): If we clear
- DECL_NOT_REALLY_EXTERN, make sure DECL_EXTERNAL is set.
+ Repair damage on weak-impared targets caused by my previous patch.
+ * cp-tree.h (import_export_tinfo): Add parameter.
+ * decl2.c (import_export_tinfo): Add parameter, post adjust
+ DECL_COMDAT.
+ * rtti.c (emit_tinfo_decl): DECL_COMDAT is (nearly) always setup by
+ import_export_tinfo.
2002-07-03 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
@@ -539,13 +3051,22 @@
(build_vec_init): Flatten multi-dimensional array during cleanup.
(build_vec_delete_1): Abort if the type of each element is array.
+2002-07-03 Graham Stott <graham.stott@btinternet.com>
+
+ * pt.c (instantiate_class_template): Fix typo.
+
+2002-07-02 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ * typeck2.c (cxx_incomplete_type_diagnostic): Fix typo caused
+ by CVS conflict in my last patch.
+
2002-07-02 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/6716
* pt.c (can_complete_type_without_circularity): New function.
(instantiate_class_template): Use it.
- * typeck2.c (incomplete_type_error): Improve error message
- due to incomplete fields.
+ * typeck2.c (cxx_incomplete_type_diagnostic): Improve error
+ message due to incomplete fields.
2002-07-01 Mark Mitchell <mark@codesourcery.com>
@@ -554,23 +3075,137 @@
applied to a type.
* operators.def: Remove stale comment.
+2002-06-30 Nathan Sidwell <nathan@codesourcery.com>
+
+ * cp-tree.h (CPTI_TINFO_DECL_TYPE): Replace with ...
+ (CPTI_TYPE_INFO_PTR_TYPE): ... this.
+ (tinfo_decl_type): Replace with ...
+ (type_info_ptr_type): ... this.
+ (import_export_tinfo): Declare.
+ (tinfo_decl_p): Rename to ...
+ (unemitted_tinfo_decl_p): ... this.
+ * decl2.c (import_export_decl): Break out tinfo handling into ...
+ (import_export_tinfo): ... here. New function.
+ (finish_file): Adjust.
+ * rtti.c (TINFO_REAL_NAME): New macro.
+ (init_rtti_processing): Create the tinfo types.
+ (get_tinfo_decl_dynamic): Use type_info_ptr_type, get_tinfo_ptr.
+ (get_tinfo_decl): Adjust.
+ (get_tinfo_ptr): New function.
+ (get_type_id): Use it.
+ (tinfo_base_init): Create vtable decl here, if it doesn't exist.
+ (ptr_initializer): Use get_tinfo_ptr.
+ (ptm_initializer): Likewise.
+ (synthesize_tinfo_var): Break into ...
+ (get_pseudo_ti_init): ... this. Just create the initializer.
+ (get_pseudo_ti_desc): .. and this.
+ (create_real_tinfo_var): Remove.
+ (create_pseudo_type_info): Don't create the vtable decl here.
+ (get_vmi_pseudo_type_info): Remove.
+ (create_tinfo_types): Adjust.
+ (tinfo_decl_p): Rename to ...
+ (unemitted_tinfo_decl_p): ... here. Adjust.
+ (emit_tinfo_decl): Adjust. Create the initializer.
+
2002-06-27 Mark Mitchell <mark@codesourcery.com>
PR c++/6695
* pt.c (tsubst_friend_class): Substitute into the context of the
friend before using it.
+2002-06-26 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (xref_tag): Change prototype.
+ (handle_class_head): Likewise.
+ (build_x_component_ref): Likewise.
+ * decl.c (cxx_init_decl_processing): Adjust call to xref_tag.
+ (xref_tag): Take attributes as a separate parameter.
+ (xref_tag_from_type): Adjust call to xref_tag.
+ * decl2.c (build_expr_from_tree): Adjust call to
+ build_x_component_ref.
+ (handle_class_head): Take attributes as a separate parameter.
+ * parse.y (parse_xref_tag): New function.
+ (parse_handle_class_head): Likewise.
+ (primary): Use parse_xref_tag.
+ (class_head_decl): Use parse_handle_class_head.
+ (class_head_defn): Likewise.
+ * rtti.c (init_rtti_processing): Adjust call to xref_tag.
+ (build_dynamic_cast_1): Likewise.
+ (create_pseudo_type_info): Likewise.
+ (emit_support_tinfos): Likewise.
+ * typeck.c (build_object_ref): Adjust call to
+ build_x_component_ref.
+ (build_x_component_ref): Remove protect parameter.
+
+2002-06-25 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_op_delete_call): Use BASELINK_FUNCTIONS.
+ * class.c (handle_using_decl): Likewise.
+ (instantiate_type): Likewise.
+ * cp-tree.h (BASELINK_FUNCTIONS): New macro.
+ (xref_basetypes): Change prototype.
+ (begin_mem_initializers): New function.
+ (get_overloaded_fn): Likewise.
+ * decl.c (xref_basetypes): Simplify.
+ * error.c (dump_expr): Use BASELINK_FUNCTIONS.
+ * init.c (build_offset_ref): Likewise.
+ * parse.y (base_init): Use begin_mem_initializers().
+ (structsp): Adjust call to xref_basetypes.
+ * pt.c (determine_specialization): Use BASELINK_FUNCTIONS.
+ (instantiate_class_template): Adjust call to xref_basetypes.
+ * semantics.c (begin_mem_initializers): New function.
+ * tree.c (is_overloaded_fn): Use BASELINK_FUNCTIONS.
+ (really_overlaoded_fn): Likewise.
+ (get_overloaded_fn): New function.'
+ (get_first_fn): USe BASELINK_FUNCTIONS.
+
+2002-06-24 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (SCALAR_TYPE_P): New macro.
+ (check_for_out_of_scope_variable): New function.
+ (at_class_scope_p): Likewise.
+ (finish_fname): Likewise.
+ * class.c (finish_struct): Use at_function_scope_p.
+ * decl.c (check_for_out_of_scope_variable): New function, split
+ out from do_identifier.
+ (finish_enum): Use at_function_scope_p.
+ * lex.c (do_identifier): Use check_for_out_of_scope_variable.
+ * parse.y (VAR_FUNC_NAME): Give it <ttype>. Use finish_fname.
+ (primary): Use at_function_scope_p.
+ * search.c (at_class_scope_p): New function.
+ * semantics.c (finish_fname): Likewise.
+ (check_multiple_declarators): Use at_function_scope_p.
+
+2002-06-23 Mark Mitchell <mark@codesourcery.com>
+
+ * parse.y (parse_scoped_id): New function.
+ (primary): Use it.
+ * cp-tree.h (do_scoped_id): Adjust declaration.
+ * lex.c (do_scoped_id): Remove call to yylex.
+ * decl2.c (build_expr_from_tree): Adjust use of do_scoped_id.
+ * typeck2.c (add_exception_specifier): Use tree_cons, rather than
+ expanding it inline.
+
2002-06-23 Matt Thomas <matt@3am-software.com>
* decl.c (finish_function): Change "#ifdef VMS_TARGET" to
"#if VMS_TARGET".
+2002-06-21 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * mangle.c (integer_type_codes): Const-ify.
+
2002-06-20 Richard Henderson <rth@redhat.com>
PR c++/6747
* typeck.c (mark_addressable): Don't test TREE_ADDRESSABLE early.
Call put_var_into_stack.
+2002-06-20 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * spew.c (remove_last_token): Use ARRAY_SIZE in lieu of explicit
+ array size calculation.
+
2002-06-20 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/6892
@@ -583,22 +3218,349 @@
BOUND_TEMPLATE_TEMPLATE_PARM if appeared as a default template
argument.
+2002-06-19 Akim Demaille <akim@epita.fr>
+
+ * parse.y (TYPENAME): Rename as tTYPENAME to avoid the clash with
+ decl.h's TYPENAME.
+ * spew.c, lex.c: Adjust.
+ * parse.y (explicit_instantiation): Add empty action to override
+ the default $$ = $1 where it introduces a type clash.
+
+2002-06-14 Jason Merrill <jason@redhat.com>
+
+ * semantics.c (begin_for_stmt): Push the 'for' scope before
+ adding the FOR_STMT.
+
+ C++ ABI changes.
+ * class.c (build_base_field): Set DECL_PACKED.
+ (layout_class_type): Don't use tail padding of PODs.
+ * mangle.c (write_unqualified_name): Fix template conversion op
+ mangling.
+
2002-06-16 Richard Henderson <rth@redhat.com>
PR opt/6793
* tree.c (cp_cannot_inline_tree_fn): Don't short-circuit test
after template instantiation.
+2002-06-16 Richard Henderson <rth@redhat.com>
+
+ * cp-tree.h, decl2.c (flag_ms_extensions): Move to c-common.
+
+2002-06-15 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * cp-tree.h (compiler_error): Remove declaration.
+ * lex.c (compiler_error): Remove definition.
+
+2002-06-14 Steve Ellcey <sje@cup.hp.com>
+
+ * g++spec.c (LIBUNWIND): New.
+ (lang_specific_driver): Add it if USE_UNWIND_EXCEPTIONS is set.
+
+2002-06-13 Jessica Han <jessica@cup.hp.com>
+
+ * class.c (build_vtable): Use TARGET_VTABLE_ENTRY_ALIGN.
+ (build_vtbl_initializer): Honor TARGET_VTABLE_DATA_ENTRY_DISTANCE.
+ (build_vbase_offset_vtbl_entries): Likewise.
+ * rtti.c (build_headof): Likewise.
+ (get_tinfo_decl_dynamic): Likewise.
+ (create_pseudo_type_info): Likewise.
+
+2002-06-12 Stan Shebs <shebs@apple.com>
+
+ * mpw-config.in: Remove file, no longer used.
+ * mpw-make.sed: Ditto.
+
+2002-06-07 Zack Weinberg <zack@codesourcery.com>
+
+ * decl2.c: Update call to cpp_handle_option.
+
2002-06-07 H.J. Lu (hjl@gnu.org)
* decl2.c (flag_use_cxa_atexit): Set to DEFAULT_USE_CXA_ATEXIT.
+2002-06-06 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * error.c (cp_error_at): Fix typo.
+
+2002-06-04 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * error.c (cp_diagnostic_starter): Adjust call.
+ (maybe_print_instantiation_context): Change prototype to take a
+ 'diagnostic_info *'.
+ (print_instantiation_full_context): Likewise.
+ (print_instantiation_partial_context): Likewise.
+ (cp_diagnostic_starter): Likewise.
+ (cp_diagnostic_finalizer): Likewise.
+ (cp_print_error_function): Likewise.
+ (cp_printer): Take a secondary parameter as a 'text_info *'.
+ Remove output_state savings. Adjust calls.
+
+2002-06-03 Geoffrey Keating <geoffk@redhat.com>
+
+ * pt.c (inline_parm_levels): Mark for GC.
+
+ * mangle.c (start_mangling): Allocate G.substitutions here...
+ (init_mangle): ... rather than here.
+ (finish_mangling): Clear the varray pointer when done with it.
+ * spew.c (yylexstring): Don't use VARRAY_FREE.
+ * search.c (bfs_walk): Don't use VARRAY_FREE.
+ * decl2.c (pending_statics): Use gengtype to mark.
+ (deferred_fns): Likewise.
+ (ssdf_decls): Likewise.
+ (init_decl2): Delete.
+ * decl.c (pop_from_top_level): Don't use VARRAY_FREE.
+ (cxx_init_decl_processing): Don't call init_decl2.
+ (cxx_pop_function_context): Don't use VARRAY_FREE.
+ * cp-tree.h (struct saved_scope): No need for special marking
+ of varrays.
+ (struct language_function): Likewise.
+ (local_classes): Use gengtype to mark.
+ (init_decl2): Delete prototype.
+ * class.c (init_class_processing): Don't use
+ ggc_add_tree_varray_root.
+ (build_vtbl_initializer): Don't use VARRAY_FREE.
+
+ * decl.c (typename_compare): Don't use same_type_p.
+
+ * decl.c: Include hashtab.h instead of hash.h.
+ (typename_hash): Update to use htab_h.
+ (typename_compare): Likewise.
+ (typename_htab): Use gengtype to mark.
+ (build_typename_type): Update to use htab_h.
+ * Make-lang.in (cp/decl.o): Use HASHTAB_H instead of hash.h.
+
+ * Make-lang.in (gt-cp-tree.h): New rule.
+ (cp/tree.o): Depend on gt-cp-tree.h.
+ * config-lang.in (gtfiles): Add cp/tree.c.
+ * tree.c: Include gt-cp-tree.h.
+ (list_hash_table): Use gengtype to mark.
+ (init_tree): Use gengtype to mark trees.
+
+ * Make-lang.in (cp/decl.o): Add debug.h dependency.
+ * call.c (struct z_candidate): Use gengtype.
+ (USER_CONV_CAND): Use WRAPPER_ZC.
+ (convert_class_to_reference): Use build_zc_wrapper.
+ (build_type_conversion_1): Likewise.
+ (build_over_call): Use WRAPPER_ZC.
+ (add_warning): Use build_zc_wrapper.
+ * cp-lang.c (LANG_HOOKS_MARK_TREE): Delete.
+ * cp-tree.h (struct lang_identifier): Use gengtype.
+ (struct template_parm_index_s): Likewise.
+ (struct ptrmem_cst): Likewise.
+ (struct tree_binding): Likewise.
+ (struct tree_overload): Likewise.
+ (struct tree_srcloc): Likewise.
+ (struct tree_wrapper): Likewise. Also modify to have a pointer
+ to struct z_candidate rather than void.
+ (enum cp_tree_node_structure_enum): New.
+ (union lang_tree_node): New.
+ (cxx_mark_tree): Delete prototype.
+ (cp_tree_node_structure): New prototype.
+ (build_ptr_wrapper): Delete prototype.
+ (build_int_wrapper): Delete prototype.
+ (build_zc_wrapper): New prototype.
+ * decl.c: Include debug.h
+ (cxx_mark_tree): Delete.
+ (cp_tree_node_structure): New.
+ * tree.c (build_ptr_wrapper): Delete.
+ (build_int_wrapper): Delete.
+ (build_zc_wrapper): New.
+
+ * cp-tree.h [! ENABLE_TREE_CHECKING] (LANG_TYPE_PTRMEM_CHECK):
+ Correct typo. Patch from k_fukui@highway.ne.jp.
+
+ * semantics.c (current_stmt_tree): Update for change to
+ struct language_function.
+ (finish_mem_initializers): Likewise.
+ * decl.c (cxx_init_decl_processing): Don't set mark_lang_status.
+ * cp-tree.h (struct language_function): Rename from
+ cp_language_function. Change all uses.
+ (cp_function_chain): Don't need to cast.
+
+ * class.c (duplicate_tag_error): Reset discriminator.
+ (check_bases_and_members): Update for data structure changes.
+ * cp-tree.h (struct lang_id2): Use gengtype.
+ (flagged_type_tree): Likewise.
+ (SET_LANG_ID): Use GGC on struct lang_id2.
+ (struct cp_language_function): Use gengtype. Remove field
+ 'x_vcalls_possible_p'.
+ (current_vcalls_possible_p): Delete.
+ (struct lang_type_header): New.
+ (struct lang_type_class): Rename from struct lang_type. Include
+ struct lang_type_header.
+ (struct lang_type_ptrmem): New.
+ (struct lang_type): New.
+ (LANG_TYPE_CLASS_CHECK): New. Use it in all the appropriate macros.
+ (LANG_TYPE_PTRMEM_CHECK): New. Use it in all the appropriate macros.
+ (TYPE_SET_PTRMEMFUNC_TYPE): Set discriminator, update for changes.
+ (struct lang_decl_flags): Use gengtype. Add discriminators.
+ (struct lang_decl): Use gengtype. Add and use discriminators.
+ Update the macros that reference moved fields.
+ (LANG_DECL_U2_CHECK): New function. Use it when appropriate.
+ (SET_DECL_THUNK_P): Set discriminator too.
+ (clear_inline_text_obstack): Delete prototype.
+ (finish_inline_definitions): Delete prototype.
+ (mark_pending_inlines): Delete prototype.
+ (lang_check_failed): New prototype.
+ * decl.c (struct named_label_use_list): Use gengtype.
+ (struct named_label_list): Likewise.
+ (mark_binding_level): Delete.
+ (mark_named_label_lists): Delete.
+ (push_local_name): Set discriminator on DECL_LANG_SPECIFIC.
+ (cxx_init_decl_processing): Use generated marker routine.
+ (begin_destructor_body): Delete dead set to
+ current_vcalls_possible_p.
+ (mark_lang_function): Delete.
+ (mark_cp_function_context): Delete.
+ (lang_mark_tree): Use generated marker routines.
+ * decl2.c (start_objects): Set discriminator when setting
+ GLOBAL_INIT_PRIORITY.
+ * lex.c (retrofit_lang_decl): Set discriminators.
+ (copy_lang_type): Update for changes to lang_type structure.
+ (cp_make_lang_type): Set discriminator.
+ * parse.y: Use gengtype on YYLVAL. Don't use dots in identifiers.
+ * search.c: Include ggc.h.
+ * semantics.c (anon_aggr_type_p): Use the macro, don't hand-code it.
+ (finish_inline_definitions): Delete.
+ * spew.c (struct token): Use gengtype.
+ (struct token_chunk): New.
+ (struct unparsed_text): Use gengtype. Store tokens in chunks.
+ (struct feed): Use gengtype.
+ (feed_obstack): Delete.
+ (feed): Mark as GC root.
+ (pending_inlines): Mark as GC root.
+ (pending_inlines_tail): Likewise.
+ (processing_these_inlines): Likewise.
+ (token_obstack): Make static.
+ (first_token): Likewise.
+ (init_spew): Don't initialize deleted things; use gengtype for roots.
+ (clear_inline_text_obstack): Delete.
+ (feed_input): Use GC for struct feed. Update for changes to
+ struct unparsed_text.
+ (mark_pending_inlines): Delete.
+ (next_token): Rename from add_token. Change all callers. Update
+ for changes to struct unparsed_text.
+ (space_for_token): New.
+ (remove_last_token): New.
+ (alloc_unparsed_text): New.
+ (snarf_block): Take an unparsed_text. Update for changes to struct
+ unparsed_text.
+ (snarf_method): Update for changes to struct unparsed_text.
+ (snarf_defarg): Update for changes to struct unparsed_text.
+ * tree.c (lang_check_failed): New.
+
+ * Make-lang.in (gt-cp-call.h gt-cp-decl2.h gt-cp-parse.h
+ gt-cp-pt.h gt-cp-repo.h gt-cp-spew.h): New rules.
+ (cp/spew.o): Add dependency on gt-<filename>.h.
+ (cp/decl2.o): Add dependency on gt-<filename>.h.
+ (cp/call.o): Add dependency on gt-<filename>.h.
+ (cp/pt.o): Add dependency on gt-<filename>.h.
+ (cp/repo.o): Add dependency on gt-<filename>.h.
+ (cp/parse.o): Add dependency on gt-<filename>.h.
+ * call.c: Use gengtype for roots.
+ * config-lang.in (gtfiles): Add cp-tree.h decl.h lex.h call.c
+ decl2.c parse.y pt.c repo.c spew.c.
+ * cp-tree.h: Use gengtype for roots.
+ (struct saved_scope): Use GGC, gengtype.
+ (cp_parse_init): Delete prototype.
+ (init_pt): Delete prototype.
+ * decl.c: Use gengtype for roots.
+ (mark_saved_scope): Delete.
+ (cxx_init_decl_processing): Don't call deleted initilisation
+ routines.
+ (signed_size_zero_node): Delete, unused.
+ * decl.h: Use gengtype for roots.
+ * decl2.c: Use gengtype for roots.
+ * lex.h: Use gengtype for roots.
+ * parse.y: Use gengtype for roots.
+ (cp_parse_init): Delete.
+ * pt.c: Use gengtype for roots.
+ (init_pt): Delete.
+ * repo.c: Use gengtype for roots.
+ * spew.c: Use gengtype for roots.
+
+ * Make-lang.in: Allow for filename changes. Add gtype-cp.h.
+ (cp/decl.o): Add dependency on gtype-cp.h.
+ * decl.c: Remove use of add_deletable_root, use GTY marker instead.
+ Include gtype-cp.h. Allow for filename changes.
+
+ * Make-lang.in (cp/gt-decl.h): Generate using gengtype.
+ (cp/decl.o): Add cp/gt-decl.h dependency.
+ * config-lang.in (gtfiles): New.
+ * tree.h: Rename struct binding_level to struct cp_binding_level.
+ * decl.c: Rename struct binding_level to struct cp_binding_level.
+ Include cp/gt-decl.h.
+ (struct cp_binding_level): Use gengtype.
+ (make_binding_level): Use GGC on struct cp_binding_level.
+ (mark_binding_level): Use gt_ggc_m_cp_binding_level.
+ (cxx_init_decl_processing): Mark free_binding_level as
+ deletable.
+
+ * decl.c (mark_cp_function_context): Update calling sequence.
+
+ * decl.c (start_function): Don't free 'struct
+ cp_language_function'.
+ (pop_cp_function_context): Likewise.
+ (save_function_data): Allocate it using GC.
+ * semantics.c (genrtl_start_function): Don't free 'struct
+ cp_language_function'.
+
+2002-05-31 Matthew Woodcraft <mattheww@chiark.greenend.org.uk>
+
+ * lang-specs.h: Use cpp_debug_options.
+
+2002-05-28 Zack Weinberg <zack@codesourcery.com>
+
+ * mangle.c, tree.c: Include real.h.
+ * Make-lang.in: Update dependency lists.
+
+2002-05-25 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * lex.c: Don't include c-lex.h.
+ * parse.y, spew.c: Don't include c-lex.h; include c-pragma.h.
+
2002-05-23 Neil Booth <neil@daikokuya.demon.co.uk>
+ * spew.c (yyungetc, snarf_block): Remove indent_level handling.
+
+2002-05-22 Richard Henderson <rth@redhat.com>
+
+ * decl.c (obscure_complex_init): Check for VAR_DECL
+ before using DECL_THREAD_LOCAL.
+
+2002-05-22 Richard Henderson <rth@redhat.com>
+
+ * decl.c (check_tag_decl): Handle RID_THREAD.
+ (obscure_complex_init): Reject run-time init of tls.
+ (grokvardecl, grokdeclarator): Handle RID_THREAD.
+ * lex.c (reswords): Add __thread.
+ (rid_to_yy): Map RID_THREAD to SCSPEC.
+
+2002-05-22 Neil Booth <neil@daikokuya.demon.co.uk>
+
* cp-lang.c (LANG_HOOKS_POST_OPTIONS): Use c_common_post_options.
* cp-tree.h (cxx_post_options): Kill.
* cp-lex.c (cxx_post_options): Kill.
+2002-05-21 Richard Henderson <rth@redhat.com>
+
+ * lex.c (rid_to_yy): Add RID_THREAD.
+
+2002-05-21 Alexandre Oliva <aoliva@redhat.com>
+
+ * init.c (build_vec_init): Test for trivial copy-assignment when
+ copy-assigning arrays.
+
+2002-05-20 Andreas Jaeger <aj@suse.de>
+
+ * init.c (build_default_init): Remove unused variable.
+
+2002-05-20 Alexandre Oliva <aoliva@redhat.com>
+
+ * call.c (any_strictly_viable): New.
+ (build_new_op): Use it for COMPOUND_EXPR and ADDR_EXPRs.
+
2002-05-19 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* error.c (dump_type) [TYPEOF_TYPE]: Fix parenthesis printing.
@@ -610,11 +3572,47 @@
instantiation after explicit specialization.
(do_type_instantiation): Likewise.
-2002-05-09 Jason Merrill <jason@redhat.com>
+2002-05-19 Alexandre Oliva <aoliva@redhat.com>
+
+ * cp-tree.h (complete_type_or_diagnostic): Changed prototype,
+ renamed from...
+ (complete_type_or_else): ... this. Redefined as macro.
+ (cxx_incomplete_type_diagnostic): Declare.
+ (cxx_incomplete_type_error): Define as macro.
+ * init.c (build_delete): Warn about incomplete types other than
+ void, and use the built-in operator delete for them.
+ * typeck.c (complete_type_or_diagnostic): Renamed from
+ complete_type_or_else. Added warn_only argument, passed to...
+ * typeck2.c (cxx_incomplete_type_diagnostic): ... this. Print
+ warnings or errors depending on new warn_only argument. Renamed
+ from...
+ (cxx_incomplete_type_error): ... this. New implementation in
+ terms of cxx_incomplete_type_diagnostic.
- * pt.c (tsubst_expr) [ASM_STMT]: Copy ASM_INPUT_P.
+2002-05-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/6611
+ * decl2.c (import_export_decl): If we clear
+ DECL_NOT_REALLY_EXTERN, make sure DECL_EXTERNAL is set.
+
+2002-05-15 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
-2002-05-15 Alexandre Oliva <aoliva@redhat.com>
+ PR c++/6620
+ * pt.c (verify_class_unification): Don't check if PARM is template
+ parameter dependent. Simplify.
+ (unify) [TEMPLATE_PARM_INDEX]: Handle when ARG is a template
+ parameter dependent expression.
+
+2002-05-14 Jason Merrill <jason@redhat.com>
+
+ * rtti.c (get_tinfo_decl): Don't call comdat_linkage.
+ Do set DECL_COMDAT.
+ (synthesize_tinfo_var): Take the public decl.
+ (create_real_tinfo_var): Likewise. Check DECL_COMDAT.
+ (emit_tinfo_decl): Adjust. Call import_export_decl.
+ * decl2.c (import_export_decl): Simplify tinfo decl handling.
+
+2002-05-14 Alexandre Oliva <aoliva@redhat.com>
* cp-tree.h (struct lang_type): Added non_zero_init.
(CLASSTYPE_NON_ZERO_INIT_P): New macro.
@@ -633,28 +3631,49 @@
(process_init_constructor): Create non-trivial zero-initializers
for array members and class fields.
-2002-05-14 Release Manager
+2002-05-14 Neil Booth <neil@daikokuya.demon.co.uk>
- * GCC 3.1 Released.
+ * lang-specs.h: Remove redundant -lang-c++.
-2002-05-03 Jason Merrill <jason@redhat.com>
+2002-05-13 Jason Merrill <jason@redhat.com>
- * decl.c (BOOL_TYPE_SIZE): Move default to defaults.h.
+ * class.c (build_vtbl_ref_1): Use fixed_type_or_null.
+ (fixed_type_or_null): See through reference vars.
+ (build_base_path): Vtable contents are constant.
+ * typeck.c (get_member_function_from_ptrfunc): Likewise.
-2002-05-02 Mark Mitchell <mark@codesourcery.com>
+2002-05-12 Jason Merrill <jason@redhat.com>
- * init.c (perform_base_cleanups): Correct order of base class
- cleanups.
+ * cp-lang.c (ok_to_generate_alias_set_for_type): Backend-created
+ structs are safe.
-2002-05-01 Mark Mitchell <mark@codesourcery.com>
+2002-05-09 Neil Booth <neil@daikokuya.demon.co.uk>
- PR c++/6527
- * init.c (perform_base_cleanups): Emit cleanups in reverse order
- of construction.
+ * cp-tree.h (flag_ansi): Remove.
+ * decl2.c (flag_ansi): Remove.
+ (cxx_decode_option): Set flag_iso and flag_undef.
-2002-05-01 Gabriel Dos Reis <gdr@codesourcery.com>
+2002-05-09 Jason Merrill <jason@redhat.com>
- * error.c (dump_type): Be careful about implicit typenames.
+ * typeck.c (get_member_function_from_ptrfunc): Reorganize.
+ Use subtraction rather than a bitmask to get the index.
+ * cvt.c (cp_convert_to_pointer): Bail on an error_mark_node.
+
+ * pt.c (tsubst_expr) [ASM_STMT]: Copy ASM_INPUT_P.
+
+2002-05-07 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Make-lang.in (decl2.o): Update.
+ * cp-tree.h (warn_multichar): Remove.
+ * decl2.c: Include c-common.h.
+ (warn_multichar): Remove.
+
+2002-05-03 Jason Merrill <jason@redhat.com>
+
+ * tree.c (build_cplus_array_type): Only const and volatile get
+ special handling.
+
+ * decl.c (BOOL_TYPE_SIZE): Move default to defaults.h.
2002-04-30 Mark Mitchell <mark@codesourcery.com>
@@ -700,22 +3719,69 @@
PR c/6343
* decl.c (duplicate_decls): Call merge_weak.
+2002-04-26 Richard Henderson <rth@redhat.com>
+
+ * parse.y (malloced_yyss, malloced_yyvs): New.
+ (yyoverflow): Re-add. Set them.
+ (free_parser_stacks): New.
+
2002-04-26 Mark Mitchell <mark@codesourcery.com>
- PR c++/6479
+ PR c++/6497
* method.c (do_build_assign_ref): Pass a derivation to
build_method_call when calling base class assignment operators.
-2002-04-24 Mark Mitchell <mark@codesourcery.com>
+2002-04-26 Richard Henderson <rth@redhat.com>
+
+ * parse.y (yyoverflow): Revert.
- * mangle.c (write_type): Don't use TYPE_MAIN_VARIANT when writing
- out an array type.
- (write_CV_qualifiers_for_type): Use TYPE_QUALS, not cp_type_quals,
- to determine qualifiers.
+2002-04-26 Richard Henderson <rth@redhat.com>
+ PR c/3581
+ * parse.y (string): Remove. Update all uses to use STRING
+ instead, and not call combine_strings.
+ * rtti.c (tinfo_name): Use fix_string_type.
+ * semantics.c (finish_asm_stmt): Don't call combine_strings.
+ * spew.c (yylexstring): New.
+ (read_token): Use it.
+
+2002-04-25 Richard Henderson <rth@redhat.com>
+
+ PR c/2161
+ * parse.y (yyoverflow): New.
+
+2002-04-25 Jason Merrill <jason@redhat.com>
+
+ PR c++/5607
+ * search.c (check_final_overrider): No longer static.
+ * class.c (update_vtable_entry_for_fn): Call it.
+ * cp-tree.h: Adjust.
+
+2002-04-25 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_SET_YYDEBUG): Remove.
+ * cp-tree.h (cxx_set_yydebug): Die.
+ * lex.c (YYDEBUG): Get from c-lex.h.
+ (cxx_set_yydebug): Remove.
+ * parse.y: Include c-lex.h.
+ (YYDEBUG): Get from c-lex.h.
+
+2002-04-24 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/6438.
* cvt.c (convert_to_void): Don't unconditionally make COND_EXPRs
void.
+2002-04-24 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE,
+ LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE, LANG_HOOKS_ATTRIBUTE_TABLE):
+ Redefine.
+ * cp-tree.h (cp_attribute_table): Rename.
+ * decl.c (lang_attribute_table): Remove declaration.
+ (cxx_init_decl_processing): Don't set it.
+ * tree.c (cp_attribute_table): Rename.
+
2002-04-24 Jason Merrill <jason@redhat.com>
PR c++/6331
@@ -729,15 +3795,6 @@
* decl.c (make_rtl_for_nonlocal_decl): Don't mess with #pragma i/i
stuff for comdats.
-2002-04-23 Jason Merrill <jason@redhat.com>
-
- PR c++/5504 - but re-breaks c++/411
- * init.c (push_base_cleanups): Rename to perform_base_cleanups.
- Expand base cleanups now rather than pushing them.
- * decl.c (begin_destructor_body): Don't call push_base_cleanups.
- (finish_destructor_body): Call perform_base_cleanups.
- * cp-tree.h: Adjust prototype.
-
2002-04-23 Jakub Jelinek <jakub@redhat.com>
* parse.y (check_class_key): Allow KEY to be union/enum/struct/class
@@ -758,6 +3815,36 @@
* typeck.c (merge_types): Remember the cv-qualification of pointer
types when merging them.
+2002-04-20 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_FUNCTION_INIT,
+ LANG_HOOKS_FUNCTION_FREE, LANG_HOOKS_FUNCTION_MARK): Redefine.
+ * cp-tree.h (cxx_push_function_context, cxx_pop_function_context,
+ cxx_mark_function_context): New.
+ * decl.c (push_cp_function_context, pop_cp_function_context,
+ mark_cp_function_context): Rename for consistency.
+ (cxx_init_decl_processing): Don't set old hooks.
+
+2002-04-19 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * call.c (convert_type_from_ellipsis): Rename, update.
+ * cp-lang.c (LANG_HOOKS_TYPE_PROMOTES_TO): Redefine.
+ * cp-tree.h (convert_type_from_ellipsis): Rename.
+ * decl.c (cxx_init_decl_processing): Don't set hook.
+
+2002-04-18 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * call.c (build_new_method_call): Update.
+ * cp-lang.c (LANG_HOOKS_INCOMPLETE_TYPE_ERROR): Redefine.
+ * cp-tree.h (cxx_incomplete_type_error): New.
+ * decl.c (grokdeclarator, grokparms): Update.
+ * decl2.c (check_classfn): Update.
+ * pt.c (tsubst): Update.
+ * typeck.c (complete_type_or_else, expr_sizeof,
+ decay_conversion): Update.
+ * typeck2.c (incomplete_type_error): Rename.
+ (add_exception_specifier): Update.
+
2002-04-18 Jason Merrill <jason@redhat.com>
PR c++/5658
@@ -782,25 +3869,47 @@
* decl.c (register_dtor_fn): Pass the address of dso_handle, not
dso_handle itself, to __cxa_atexit.
+2002-04-15 Gabriel Dos Reis <gdr@merlin.codesourcery.com>
+
+ * error.c (cxx_print_error_function): Adjust call to macros.
+
2002-04-14 Jakub Jelinek <jakub@redhat.com>
* class.c (layout_virtual_bases): Do all dsize computation on trees.
+2002-04-14 Jason Merrill <jason@redhat.com>
+
+ * typeck.c (get_member_function_from_ptrfunc): Don't do
+ gratuitious division and multiplication on
+ ptrmemfunc_vbit_in_delta targets.
+
2002-04-12 Mark Mitchell <mark@codesourcery.com>
PR c++/5373.
* semantics.c (finish_expr_stmt): Remember the type of the
expression before any conversions are performed.
+2002-04-12 Mark Mitchell <mark@codesourcery.com>
+
PR c++/5189.
* call.c (add_template_candidate_real): Do not treat member
templates as copy constructors.
+2002-04-12 Mark Mitchell <mark@codesourcery.com>
+
* decl.c (duplicate_decls): Do not copy the RTL for a variable
declaration if the old variable had an incomplete type and the new
variable does not.
(complete_vars): Do not call layout_decl for completed variables.
+2002-04-12 Richard Sandiford <rsandifo@redhat.com>
+
+ * decl.c (duplicate_decls): Don't try to unify an implicit typedef
+ with an explicit one.
+ (follow_tag_typedef): New.
+ (lookup_tag): Use it to extract the tag of an explicit typedef.
+ (xref_tag): Likewise.
+
2002-04-11 Andrew Haley <aph@redhat.com>
* typeck.c (type_after_usual_arithmetic_conversions):
@@ -810,14 +3919,6 @@
if neither operand is one of the standard types, return the type
of the first operand.
-2002-04-12 Richard Sandiford <rsandifo@redhat.com>
-
- * decl.c (duplicate_decls): Don't try to unify an implicit typedef
- with an explicit one.
- (follow_tag_typedef): New.
- (lookup_tag): Use it to extract the tag of an explicit typedef.
- (xref_tag): Likewise.
-
2002-04-10 Nathan Sidwell <nathan@codesourcery.com>
PR c++/5507
@@ -829,6 +3930,9 @@
* semantics.c (genrtl_start_function): Don't free
DECL_SAVED_FUNCTION_DATA for inline functions.
+ * init.c (build_member_call): For now, don't convert to
+ intermediate base if it would cause an error.
+
2002-04-08 Paolo Carlini <pcarlini@unitus.it>
* parse.y (namespace_qualifier, maybe_identifier,
@@ -866,15 +3970,45 @@
* error.c (dump_expr) [CONVERT_EXPR]: Make sure TREE_TYPE (t) is
set before checking it.
+ PR c++/525
+ * init.c (build_member_call): Use build_scoped_ref.
+ (resolve_offset_ref): Likewise.
+ * call.c (build_scoped_method_call): Likewise.
+ * tree.c (maybe_dummy_object): Kludge around current_class_type being
+ wrong.
+ * typeck2.c (build_scoped_ref): Return the binfo via binfo_p parm.
+ * cp-tree.h: Adjust.
+
+ * init.c (push_base_cleanups): Just use build_scoped_method_call.
+
PR c++/6179
* method.c (implicitly_declare_fn): Pass unqualified type to
synthesize_exception_spec.
-2002-04-03 Jason Merrill <jason@redhat.com>
+2002-04-04 Neil Booth <neil@daikokuya.demon.co.uk>
- PR c++/525
- * init.c (build_member_call): Convert to intermediate base even
- with -pedantic.
+ * cp-lang.c (LANG_HOOKS_TRUTHVALUE_CONVERSION): Redefine.
+ * cvt.c: Update comment.
+ * init.c (expand_cleanup_for_base): Update.
+ * semantics.c (finish_parenthesized_expr): Update.
+ * typeck.c (cp_truthvalue_conversion): Update.
+
+2002-04-04 Jason Merrill <jason@redhat.com>
+
+ * semantics.c (finish_eh_cleanup): New fn.
+ * cp-tree.h: Add prototype.
+ * init.c (perform_member_init, expand_cleanup_for_base): Use
+ finish_eh_cleanup.
+ * cp-tree.def (SUBOBJECT, CTOR_STMT): Remove.
+ * cp-tree.h: Remove references.
+ * decl.c (begin_constructor_body, end_constructor_body): Likewise.
+ * dump.c (cp_dump_tree): Likewise.
+ * pt.c (tsubst_expr): Likewise.
+ * semantics.c (genrtl_ctor_stmt, genrtl_subobject): Remove.
+ (cp_expand_stmt): Remove handling of CTOR_STMT and SUBOBJECT.
+ * tree.c (cp_statement_code_p): Likewise.
+
+ * init.c (build_new_1): Set CLEANUP_EH_ONLY on deleting cleanup.
PR c++/5636
* semantics.c (nullify_returns_r): Just set CLEANUP_EH_ONLY on
@@ -885,12 +4019,38 @@
specifiers.
[METHOD_TYPE]: Use same code as FUNCTION_TYPE.
+2002-04-03 Richard Henderson <rth@redhat.com>
+
+ * cp-lang.c (cxx_warn_unused_global_decl): New.
+ (LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL): New.
+
+2002-04-03 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_SET_DECL_ASSEMBLER_NAME): Redefine.
+ * tree.c (init_tree): Don't set hook.
+
2002-04-03 Roger Sayle <roger@eyesopen.com>
PR c++/5998:
* decl.c (duplicate_decls): Don't mess with assembler names when
redeclaring builtin functions as static.
+2002-04-01 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * call.c (build_addr_func): Update.
+ * class.c (resolve_address_of_overloaded_function): Update.
+ * cp-lang.c (LANG_HOOKS_MARK_ADDRESSABLE): Redefine.
+ * cp-tree.h (cxx_mark_addressable): New.
+ * decl.c (register_dtor_fn, cxx_maybe_build_cleanup): Update.
+ * decl2.c (build_cleanup): Update.
+ * except.c (build_throw): Update.
+ * init.c (resolve_offset_ref): Update.
+ * pt.c (convert_nontype_argument): Update.
+ * semantics.c (finish_asm_stmt, simplify_affr_init_exprs_r): Update.
+ * typeck.c (decay_conversion, build_array_ref, build_unary_op,
+ unary_complex_lvalue): Update.
+ (mark_addressable): Rename.
+
2002-04-01 Roger Sayle <roger@eyesopen.com>
PR c++/5998:
@@ -898,6 +4058,40 @@
when) overwriting a built-in function. Don't use COPY_DECL_RTL,
but follow the SET_DECL_RTL idiom used elsewhere in the function.
+2002-04-01 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_SIGNED_TYPE, LANG_HOOKS_UNSIGNED_TYPE,
+ LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE): New.
+ * decl.c (grokdeclarator): Update.
+ * mangle.c (write_integer_cst): Update.
+ * typeck.c (build_binary_op): Update.
+
+2002-03-31 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_UNSAFE_FOR_REEVAL): Redefine.
+ * lex.c (cxx_init): Don't set hook.
+
+2002-03-31 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Make-lang.in (error.o): Update.
+ * cp-lang.c (LANG_HOOKS_PRINT_ERROR_FUNCTION): Redefine.
+ * cp-tree.h (struct diagnostic_context): Predeclare.
+ (cxx_print_error_function): New.
+ * error.c: Include langhooks-def.h.
+ (lang_print_error_function): Rename. Update.
+ (init_error): Don't set hook.
+
+2002-03-29 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_TYPE_FOR_MODE, LANG_HOOKS_TYPE_FOR_SIZE):
+ Redefine.
+ * cvt.c (cp_convert_to_pointer, type_promotes_to): Use new hooks.
+ * decl.c (finish_enum): Similarly.
+ * error.c (dump_type): Similarly.
+ * lex.c (cxx_init): Similarly.
+ * mangle.c (write_builtin_type): Similarly.
+ * typeck.c (comptypes): Similarly.
+
2002-03-28 Roger Sayle <roger@eyesopen.com>
PR c++/5998:
@@ -921,18 +4115,48 @@
* lex.c (do_scoped_id): Fail to find an identifier in the global
namespace if its still anticipated.
+2002-03-29 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_MAKE_TYPE): Redefine.
+ * cp-tree.h (cp_make_lang_type): Rename.
+ * lex.c (cp_make_lang_type): Rename.
+ (make_aggr_type): Update.
+ * tree.c (init_tree): Don't set make_lang_type_fn.
+
2002-03-29 Jakub Jelinek <jakub@redhat.com>
PR c++/6073
* class.c (finish_struct_1): Update static field's DECL_MODE even
if its type is a variant of t.
+2002-03-27 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES): Redefine.
+ * cp-tree.h (cxx_insert_default_attributes): New.
+ * decl.c (insert_default_attributes): Rename.
+
2002-03-27 Mark Mitchell <mark@codesourcery.com>
PR c++/4884
* call.c (build_op_delete_call): Allow for the fact the placement
may be a COMPOUND_EXPR.
+2002-03-27 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_EXPAND_EXPR): Redefine.
+ * cp-tree.h (init_cplus_expand): Remove.
+ (cxx_expand_expr): New.
+ * expr.c (cplus_expand_expr): Rename cxx_expand_expr,
+ fix prototype.
+ (init_cplus_expand): Remove.
+ * lex.c (cxx_init): Don't call init_cplus_expand.
+
+2002-03-26 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/4884.
+ * init.c (build_new_1): Allow for the fact the result of
+ build_function_call may be a COMPOUND_EXPR.
+
2002-03-26 Nathan Sidwell <nathan@codesourcery.com>
PR c++/5682
@@ -945,27 +4169,68 @@
(dfs_unmarked_real_bases_queue_p): Just get the canonical binfo.
(dfs_marked_real_bases_queue_p): Likewise.
-2002-03-26 Mark Mitchell <mark@codesourcery.com>
+2002-03-26 Neil Booth <neil@daikokuya.demon.co.uk>
- PR c++/4884
- * init.c (build_new_1): Allow for the fact the result of
- build_function_call may be a COMPOUND_EXPR.
+ * cp-lang.c (LANG_HOOKS_MARK_TREE): Redefine.
+ * cp-tree.h (cxx_mark_tree): New.
+ * decl.c (lang_mark_tree): Rename cxx_mark_tree.
+
+2002-03-25 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-tree.h (cxx_maybe_build_cleanup): New.
+ * decl.c (destroy_local_var, hack_incomplete_structures): Update.
+ (maybe_build_cleanup): Rename cxx_maybe_build_cleanup.
+ * tree.c (build_target_expr): Update.
+ * cp-lang.c (LANG_HOOKS_MAYBE_BUILD_CLEANUP): Redefine.
+
+2002-03-24 Neil Booth <neil@daikokuya.demon.co.uk>
-2002-03-25 Jakub Jelinek <jakub@redhat.com>
+ * decl2.c (cxx_decode_option): Handle -E.
+ * lang-specs.h (default_compilers): Preprocess with cc1plus.
+ * lex.c (cxx_init): Exit quickly if c_common_init returns NULL.
+
+2002-03-23 Jakub Jelinek <jakub@redhat.com>
PR c++/6037
* decl.c (start_enum): Don't set TREE_ADDRESSABLE on TREE_LIST node.
+2002-03-23 Gabriel Dos Reis <gdr@merlin.codesourcery.com>
+
+ * error.c (dump_type): Be careful about implicit typenames.
+
+2002-03-21 Gabriel Dos Reis <gdr@merlin.codesourcery.com>
+
+ PR C++/3656
+ * semantics.c (finish_base_specifier): Handle erronous base
+ classes.
+
+2002-03-22 Zack Weinberg <zack@codesourcery.com>
+
+ * error.c: Always use REAL_VALUE_TO_DECIMAL; don't test
+ REAL_IS_NOT_DOUBLE.
+
2002-03-22 Jeff Knaggs <jknaggs@redhat.com>
- * typeck.c (expand_ptrmemfunc_cst): Scale idx down to an index
- into the vtable_entry array regardless of
+ * typeck.c (get_member_function_from_ptrfunc): Scale idx down to
+ an index into the vtable_entry array regardless of
TARGET_PTRMEMFUNC_VBIT_LOCATION.
2002-03-21 Aldy Hernandez <aldyh@redhat.com>
* tree.c (cp_cannot_inline_tree_fn): Same.
+2002-03-21 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-tree.h (pushdecl, pushlevel, poplevel, set_block,
+ insert_block, getdecls, global_bindings_p): New.
+
+2002-03-20 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/4361
+ * mangle.c (struct globals) Add internal_mangling_p member.
+ (write_template_param): Do internal mangling, if needed.
+ (mangle_conv_op_name_for_type): Request internal mangling.
+
2002-03-20 Jason Merrill <jason@redhat.com>
PR c++/2136
@@ -977,6 +4242,15 @@
PR c++/5118
* class.c (get_vfield_name): Use the constructor_name.
+2002-03-20 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_DECL_PRINTABLE_NAME): Redefine.
+ * cp-tree.h (lang_printable_name): Rename.
+ * error.c (lang_decl_name): Use new hook.
+ * lex.c (cxx_init): Remove old hook.
+ * pt.c (tsubst_decl): Use new hook.
+ * tree.c (lang_printable_name): Rename.
+
2002-03-18 Eric Botcazou <ebotcazou@multimania.com>
PR c++/3882
@@ -984,11 +4258,6 @@
(tsubst_expr) [DECL_STMT]: ...here. And substitute the initializer
only after recording the declaration.
-2002-03-18 Ashif Harji <asharji@uwaterloo.ca>
-
- * lang-specs.h (compiler default_compilers): Add
- -no-integrated-cpp flag to invoke an external cpp.
-
2002-03-18 Jason Merrill <jason@redhat.com>
PR c++/2039
@@ -1019,17 +4288,43 @@
* class.c (build_base_path): Virtual base layout is fixed in
in-charge [cd]tors.
+2002-03-17 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_PARSE_FILE): Redefine.
+ * parse.y (yyparse): Remove macro.
+
+2002-03-17 Jason Merrill <jason@redhat.com>
+
PR c++/5757
* init.c (build_new_1): Pass the right pointer to op delete.
-2002-03-15 Richard Henderson <rth@redhat.com>
+2002-03-16 Nathan Sidwell <nathan@codesourcery.com>
- * init.c (build_new_1): Use size_binop instead of cp_build_binary_op.
+ PR c++/4361
+ * cp-tree.h (CLASSTYPE_METHOD_VEC): Document where templated
+ conversion operators go.
+ (struct lang_decl_flags): Add template_conv_p and unused
+ bitfields.
+ (DECL_TEMPLATE_CONV_FN_P): New macro.
+ * call.c (build_user_type_conversion_1): Don't check second type
+ conversion of overload set first.
+ * class.c (add_method): Make sure templated conversion operators
+ all end up on slot 2.
+ * lex.c (do_identifier): A conversion operator token might be
+ satisfied by a templated conversion operator.
+ * pt.c (check_explicit_specialization): Use
+ CLASSTYPE_FIRST_CONVERSION_SLOT.
+ (template_parm_this_level_p): New function.
+ (push_template_decl_real): Determine DECL_TEMPLATE_CONV_FN_P.
+ * search.c (lookup_fnfields_1): Template conversions will be on
+ the first slot.
+ * typeck.c (build_component_ref): Preserve the type of an
+ conversion operator name on the overload type.
+ (build_x_function_call): Retrieve the conversion operator name.
2002-03-15 Richard Henderson <rth@redhat.com>
- * decl.c (finish_function): Reapply accidentally reverted
- 2002-02-28 patch.
+ * init.c (build_new_1): Use size_binop instead of cp_build_binary_op.
2002-03-15 Mark Mitchell <mark@codesourcery.com>
@@ -1041,12 +4336,6 @@
* semantics.c (cp_expand_stmt): Likewise.
* cp/tree.c (cp_statement_code_p): Likewise.
-2002-03-15 Richard Henderson <rth@redhat.com>
-
- * decl.c: Include c-pragma.h.
- (start_decl, start_function): Invoke maybe_apply_pragma_weak.
- * Make-lang.in: Update dependencies.
-
2002-03-15 Jason Merrill <jason@redhat.com>
PR c++/5857
@@ -1064,6 +4353,12 @@
variables.
* decl2.c (maybe_make_one_only): Also mark the decl as needed.
+2002-03-14 Richard Henderson <rth@redhat.com>
+
+ * decl.c: Include c-pragma.h.
+ (start_decl, start_function): Invoke maybe_apply_pragma_weak.
+ * Make-lang.in: Update dependencies.
+
2002-03-14 Jakub Jelinek <jakub@redhat.com>
PR c++/5908
@@ -1075,6 +4370,24 @@
* mangle.c (write_builtin_type): Handle 128-bit integers even if
they are not a standard integer type.
+2002-03-12 Richard Sandiford <rsandifo@redhat.com>
+
+ * cp-tree.h (init_init_processing): Remove declaration.
+ * init.c (BI_header_type, init_init_processing): Remove old ABI stuff.
+ * decl.c (cxx_init_decl_processing): Don't call init_init_processing.
+
+2002-03-12 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cp-lang.c (tree_code_type, tree_code_length, tree_code_name):
+ Define.
+ * decl.c (duplicate_decls): Use TREE_CODE_LENGTH, not
+ tree_code_length.
+ * lex.c (cplus_tree_code_type, cplus_tree_code_length,
+ cplus_tree_code_name): Delete.
+ (cxx_init): Don't call add_c_tree_codes, instead set
+ lang_unsafe_for_reeval. Don't try to copy into the various
+ tree_code arrays.
+
2002-03-12 Nathan Sidwell <nathan@codesourcery.com>
PR c++/5659
@@ -1102,11 +4415,35 @@
* typeck.c (build_static_cast): Compare non-qualified types
with pointer to member conversions.
+2002-03-11 Dan Nicolaescu <dann@ics.uci.edu>
+ Daniel Berlin <dan@dberlin.org>
+
+ * cp-lang.c (ok_to_generate_alias_set_for_type): New function.
+ (cxx_get_alias_set): Use it.
+
+2002-03-10 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cp-tree.h (stabilize_expr): Prototype.
+
2002-03-08 Craig Rodrigues <rodrigc@gcc.gnu.org>
* cp-tree.h (CLEAR_BINFO_MARKED): Make both parts of
conditional return void.
+2002-03-08 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-lang.c (LANG_HOOKS_UNSAVE): Redefine.
+ * cp-tree.h (cxx_unsave): New.
+ * tree.c (cp_unsave): Rename cxx_unsave, update prototype.
+ (init_tree): Update.
+
+2002-03-03 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * decl.c (cxx_init_decl_processing): Use ARRAY_SIZE in lieu of
+ explicit sizeof/sizeof.
+ * decl2.c (cxx_decode_option): Likewise.
+ * lex.c (init_reswords, REDUCE_LENGTH, TOKEN_LENGTH): Likewise.
+
2002-03-02 Nathan Sidwell <nathan@codesourcery.com>
PR c++/775
@@ -1122,13 +4459,22 @@
2002-03-01 Phil Edwards <pme@gcc.gnu.org>
- * cp-tree.h (build_init): Remove prototype.
-
-2002-03-01 Phil Edwards <pme@gcc.gnu.org>
-
* cp-tree.h: Require __GNUC__ to be #defined.
(build_init): Add missing prototype.
+2002-03-01 Jason Merrill <jason@redhat.com>
+
+ * except.c: Don't include decl.h or obstack.h. Do include
+ tree-inline.h.
+ (build_throw): Destroy temporaries from the thrown
+ expression before calling __cxa_throw. Construct a thrown
+ temporary directly into the exception object.
+ (stabilize_throw_expr): New function.
+ (wrap_cleanups_r): New function.
+ * tree.c (stabilize_expr): New function.
+ * init.c (build_init): New function.
+ * Make-lang.in (cp/except.o): Adjust .h deps.
+
2002-02-28 Jason Merrill <jason@redhat.com>
* search.c (lookup_base_r): Don't clear is_non_public just because
@@ -1137,6 +4483,21 @@
* decl.c (finish_function): Only warn about missing return
statement with -Wreturn-type.
+2002-02-28 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * class.c (build_clone): Update.
+ * cp-lang.c (LANG_HOOKS_DUP_LANG_SPECIFIC_DECL): Redefine.
+ * cp-tree.h (cxx_dup_lang_specific_decl): New.
+ * lex.c (copy_lang_decl): Rename cxx_dup_lang_specific_decl.
+ (copy_decl): Update.
+ * method.c (make_thunk): Update.
+
+2002-02-27 Zack Weinberg <zack@codesourcery.com>
+
+ * decl2.c: Delete traditional-mode-related code copied from
+ the C front end but not used, or used only to permit the
+ compiler to link.
+
2002-02-24 Craig Rodrigues <rodrigc@gcc.gnu.org>
PR c++/4093
@@ -1166,7 +4527,7 @@
* pt.c (convert_template_argument): Adjust make_typename_type
return value.
(tsubst): Adjust cp_build_qualified_type_real calls.
- (check_cv_quals_for_unify): Cope with alowing bad qualifications
+ (check_cv_quals_for_unify): Cope with allowing bad qualifications
on template type parms.
(instantiate_decl): Recheck substitutions to give warnings on bad
qualifications.
@@ -2301,7 +5662,7 @@ Tue Nov 27 09:03:47 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* search.c (get_vbase_1): Remove.
(get_vbase): Remove.
(convert_pointer_to_vbase): Remove.
- (lookup_base_recursive): New function.
+ (lookup_base_r): New function.
(lookup_base): New function.
* typeck.c (require_complete_type): Use lookup_base &
build_base_path instead of convert_pointer_to.
@@ -3144,7 +6505,7 @@ Fri Sep 21 08:16:19 2001 J"orn Rennecke <amylaar@redhat.com>
PR c++/3621
* spew.c (yylex): Only copy the token's lineno, if it is
- non-zero.
+ nonzero.
2001-07-26 Nathan Sidwell <nathan@codesourcery.com>
@@ -3235,7 +6596,7 @@ Fri Sep 21 08:16:19 2001 J"orn Rennecke <amylaar@redhat.com>
2001-07-23 Graham Stott <grahams@redhat.com>
- * cp/class.c (type_requires_array_cookie): Fix use of uninitialised
+ * cp/class.c (type_requires_array_cookie): Fix use of uninitialized
variable has_two_argument_delete_p.
2001-07-21 Nathan Sidwell <nathan@codesourcery.com>
@@ -3282,7 +6643,7 @@ Fri Sep 21 08:16:19 2001 J"orn Rennecke <amylaar@redhat.com>
2001-07-20 Nathan Sidwell <nathan@codesourcery.com>
Remove old-abi remnants. Remove comments about old abi
- behaviour. Remove references to 'new-abi' in comments.
+ behavior. Remove references to 'new-abi' in comments.
* cp-tree.h: Adjust comments.
(vbase_offsets_in_vtable_p): Delete.
(vcall_offsets_in_vtable_p): Delete.
@@ -4484,7 +7845,7 @@ Thu Apr 5 16:54:29 2001 J"orn Rennecke <amylaar@redhat.com>
(maybe_commonize_var): Allow inlining functions even if they have
static local variables, use comdat_linkage for them if flag_weak.
(check_initializer): Call obscure_complex_init if
- grok_reference_init returned non-zero.
+ grok_reference_init returned nonzero.
(save_function_data): Clear x_local_names.
(pop_cp_function_context): Free x_local_names.
(mark_inlined_fns): Remove.
@@ -5731,7 +9092,7 @@ Sun Feb 4 15:52:44 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
(cp_make_fname_decl): Use size_int, not build_int_2.
(push_inline_template_parms_recursive): Likewise.
(end_template_parm_list): Likewise.
- (for_each_tempalte_parm): Do not use walk_tree_without_duplicates.
+ (for_each_template_parm): Do not use walk_tree_without_duplicates.
(tsubst_template_parms): Use size_int, not build_int_2.
(tsubst): Likewise.
* rtti.c (get_vmi_pseudo_type_info): Likewise.
@@ -6223,7 +9584,7 @@ Thu Nov 23 02:16:47 2000 J"orn Rennecke <amylaar@redhat.com>
2000-11-17 Nathan Sidwell <nathan@codesourcery.com>
- * typeck2.c (incomplete_type_error): Reorganise to avoid
+ * typeck2.c (incomplete_type_error): Reorganize to avoid
excessive diagnostics.
2000-11-16 Zack Weinberg <zack@wolery.stanford.edu>
@@ -11631,7 +14992,7 @@ Sun Feb 27 16:40:33 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
(add_method): Used functions are hidden by local functions.
(check_bases_and_members): Handle using-decls before finalizing
CLASSTYPE_METHOD_VEC.
- * call.c (add_function_candidate): Add ctype parm; if non-zero,
+ * call.c (add_function_candidate): Add ctype parm; if nonzero,
override the type of 'this' accordingly.
(add_template_candidate, add_template_candidate_real): Add ctype parm.
(convert_class_to_reference, build_user_type_conversion_1,
diff --git a/contrib/gcc/cp/ChangeLog.1 b/contrib/gcc/cp/ChangeLog.1
index b411f18..4b4afd3 100644
--- a/contrib/gcc/cp/ChangeLog.1
+++ b/contrib/gcc/cp/ChangeLog.1
@@ -5729,7 +5729,7 @@ Tue May 17 13:34:46 1994 Jason Merrill <jason@deneb.cygnus.com>
Mon May 16 23:04:01 1994 Stephen R. van den Berg <berg@pool.informatik.rwth-aachen.de>
* cp/typeck.c (common_type): Attribute merging.
- (comp_types): Utilise COMP_TYPE_ATTRIBUTES macro.
+ (comp_types): Utilize COMP_TYPE_ATTRIBUTES macro.
* cp/parse.y: Revamp attribute parsing.
@@ -6168,7 +6168,7 @@ Wed May 4 11:19:45 1994 Jason Merrill <jason@deneb.cygnus.com>
Tue May 3 16:02:53 1994 Per Bothner <bothner@kalessin.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
+ * class.c (build_vtable_entry): The address 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
diff --git a/contrib/gcc/cp/ChangeLog.2 b/contrib/gcc/cp/ChangeLog.2
index 179d6d7..26dc387 100644
--- a/contrib/gcc/cp/ChangeLog.2
+++ b/contrib/gcc/cp/ChangeLog.2
@@ -1264,7 +1264,7 @@ Wed Oct 13 22:01:35 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
1999-10-06 Brendan Kehoe <brendan@cygnus.com>
- * decl.c (grokdeclarator): Only warn about non-zero arrays if
+ * decl.c (grokdeclarator): Only warn about nonzero arrays if
!in_system_header (linux socketbits.h can give this for
__cmsg_data, which is using a GNU extension).
@@ -19205,7 +19205,7 @@ Mon Mar 4 22:38:39 1996 Gerald Baumgartner <gb@alexander.cs.purdue.edu>
* 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.
+ grabbed 2 words at a time on a SPARC.
Tue Mar 5 10:21:01 1996 Jason Merrill <jason@yorick.cygnus.com>
diff --git a/contrib/gcc/cp/Make-lang.in b/contrib/gcc/cp/Make-lang.in
index aef2d35..afeb7ab 100644
--- a/contrib/gcc/cp/Make-lang.in
+++ b/contrib/gcc/cp/Make-lang.in
@@ -40,17 +40,12 @@
# Actual names to use when installing a native compiler.
CXX_INSTALL_NAME = `echo c++|sed '$(program_transform_name)'`
GXX_INSTALL_NAME = `echo g++|sed '$(program_transform_name)'`
-DEMANGLER_INSTALL_NAME = `echo c++filt|sed '$(program_transform_name)'`
CXX_TARGET_INSTALL_NAME = $(target_alias)-`echo c++|sed '$(program_transform_name)'`
GXX_TARGET_INSTALL_NAME = $(target_alias)-`echo g++|sed '$(program_transform_name)'`
# Actual names to use when installing a cross-compiler.
CXX_CROSS_NAME = `echo c++|sed '$(program_transform_cross_name)'`
GXX_CROSS_NAME = `echo g++|sed '$(program_transform_cross_name)'`
-DEMANGLER_CROSS_NAME = `echo c++filt|sed '$(program_transform_cross_name)'`
-
-# The name to use for the demangler program.
-DEMANGLER_PROG = c++filt$(exeext)
#
# Define the names for selecting c++ in LANGUAGES.
@@ -81,22 +76,10 @@ g++-cross$(exeext): g++$(exeext)
-rm -f g++-cross$(exeext)
cp g++$(exeext) g++-cross$(exeext)
-# The demangler.
-cxxmain.o: $(srcdir)/../libiberty/cplus-dem.c $(DEMANGLE_H) $(CONFIG_H)
- rm -f cxxmain.c
- $(LN_S) $(srcdir)/../libiberty/cplus-dem.c cxxmain.c
- $(CC) -c -DMAIN $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- -DVERSION=\"$(version)\" cxxmain.c
-
-# Apparently OpenVM needs the -o to be at the beginning of the link line.
-$(DEMANGLER_PROG): cxxmain.o underscore.o $(LIBDEPS)
- $(CC) -o $@ $(ALL_CFLAGS) $(LDFLAGS) \
- cxxmain.o underscore.o $(LIBS)
-
# The compiler itself.
# Shared with C front end:
CXX_C_OBJS = attribs.o c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o \
- $(CXX_TARGET_OBJS)
+ c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o
# Language-specific object files.
CXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
@@ -131,13 +114,17 @@ $(srcdir)/cp/parse.c: $(srcdir)/cp/parse.y
false ; \
fi
+gtype-cp.h gt-cp-call.h gt-cp-decl.h gt-cp-decl2.h : s-gtype; @true
+gt-cp-parse.h gt-cp-pt.h gt-cp-repo.h gt-cp-spew.h : s-gtype; @true
+gt-cp-tree.h gt-cp-mangle.h : s-gtype; @true
+
#
# Build hooks:
c++.all.build: g++$(exeext)
-c++.all.cross: g++-cross$(exeext) $(DEMANGLER_PROG)
+c++.all.cross: g++-cross$(exeext)
c++.start.encap: g++$(exeext)
-c++.rest.encap: $(DEMANGLER_PROG)
+c++.rest.encap:
c++.info:
c++.dvi:
@@ -182,17 +169,6 @@ c++.install-common: installdirs
( cd $(DESTDIR)$(bindir) && \
$(LN) $(CXX_INSTALL_NAME)$(exeext) $(CXX_TARGET_INSTALL_NAME)$(exeext) ); \
fi ; \
- if [ x$(DEMANGLER_PROG) != x ] && [ -x "$(DEMANGLER_PROG)" ]; then \
- if [ -f g++-cross$(exeext) ] ; then \
- rm -f $(DESTDIR)$(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext); \
- $(INSTALL_PROGRAM) $(DEMANGLER_PROG) $(DESTDIR)$(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext); \
- chmod a+x $(DESTDIR)$(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext); \
- else \
- rm -f $(DESTDIR)$(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext); \
- $(INSTALL_PROGRAM) $(DEMANGLER_PROG) $(DESTDIR)$(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext); \
- chmod a+x $(DESTDIR)$(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext); \
- fi ; \
- fi ; \
fi
c++.install-info:
@@ -215,8 +191,6 @@ c++.uninstall:
-rm -rf $(DESTDIR)$(bindir)/$(CXX_CROSS_NAME)$(exeext)
-rm -rf $(DESTDIR)$(bindir)/$(GXX_INSTALL_NAME)$(exeext)
-rm -rf $(DESTDIR)$(bindir)/$(GXX_CROSS_NAME)$(exeext)
- -rm -rf $(DESTDIR)$(bindir)/$(DEMANGLER_INSTALL_NAME)$(exeext)
- -rm -rf $(DESTDIR)$(bindir)/$(DEMANGLER_CROSS_NAME)$(exeext)
-rm -rf $(DESTDIR)$(man1dir)/$(GXX_INSTALL_NAME)$(man1ext)
-rm -rf $(DESTDIR)$(man1dir)/$(GXX_CROSS_NAME)$(man1ext)
#
@@ -225,7 +199,8 @@ c++.uninstall:
# We just have to delete files specific to us.
c++.mostlyclean:
- -rm -f cp/*$(objext) $(DEMANGLER_PROG)
+ -rm -f cp/*$(objext)
+ -rm -f cp/*$(coverageexts)
c++.clean:
c++.distclean:
-rm -f cp/config.status cp/Makefile
@@ -252,53 +227,58 @@ CXX_TREE_H = $(TREE_H) cp/cp-tree.h c-common.h cp/cp-tree.def c-common.def \
function.h varray.h $(SYSTEM_H) $(CONFIG_H) $(TARGET_H) \
$(srcdir)/../include/hashtab.h $(srcdir)/../include/splay-tree.h
-cp/spew.o: cp/spew.c $(CXX_TREE_H) cp/parse.h flags.h cp/lex.h toplev.h
-cp/lex.o: cp/lex.c $(CXX_TREE_H) cp/parse.h flags.h cp/lex.h c-pragma.h \
- toplev.h output.h mbchar.h $(GGC_H) input.h diagnostic.h cp/operators.def \
- $(TM_P_H)
+cp/spew.o: cp/spew.c $(CXX_TREE_H) $(srcdir)/cp/parse.h flags.h cp/lex.h \
+ toplev.h gt-cp-spew.h
+cp/lex.o: cp/lex.c $(CXX_TREE_H) $(srcdir)/cp/parse.h flags.h cp/lex.h \
+ c-pragma.h toplev.h output.h mbchar.h $(GGC_H) input.h diagnostic.h \
+ cp/operators.def $(TM_P_H)
cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) toplev.h langhooks.h $(LANGHOOKS_DEF_H) \
c-common.h
cp/decl.o: cp/decl.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h stack.h \
- output.h $(EXPR_H) except.h toplev.h hash.h $(GGC_H) $(RTL_H) \
- cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h c-pragma.h
+ output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(GGC_H) $(RTL_H) \
+ cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h c-pragma.h \
+ debug.h gt-cp-decl.h gtype-cp.h timevar.h input.h
cp/decl2.o: cp/decl2.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \
- output.h except.h toplev.h $(GGC_H) $(RTL_H)
+ output.h except.h toplev.h $(GGC_H) $(RTL_H) c-common.h gt-cp-decl2.h \
+ timevar.h
cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) flags.h toplev.h output.h $(TM_P_H) \
diagnostic.h
cp/typeck.o: cp/typeck.c $(CXX_TREE_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
diagnostic.h
cp/class.o: cp/class.c $(CXX_TREE_H) flags.h toplev.h $(RTL_H) $(TARGET_H)
cp/call.o: cp/call.c $(CXX_TREE_H) flags.h toplev.h $(RTL_H) $(EXPR_H) \
- $(GGC_H) diagnostic.h
+ $(GGC_H) diagnostic.h gt-cp-call.h
cp/friend.o: cp/friend.c $(CXX_TREE_H) flags.h $(RTL_H) toplev.h $(EXPR_H)
cp/init.o: cp/init.c $(CXX_TREE_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
$(GGC_H) except.h
cp/method.o: cp/method.c $(CXX_TREE_H) toplev.h $(GGC_H) $(RTL_H) $(EXPR_H) \
- $(TM_P_H)
+ $(TM_P_H) $(TARGET_H)
cp/cvt.o: cp/cvt.c $(CXX_TREE_H) cp/decl.h flags.h toplev.h convert.h
cp/search.o: cp/search.c $(CXX_TREE_H) stack.h flags.h toplev.h $(RTL_H)
cp/tree.o: cp/tree.c $(CXX_TREE_H) flags.h toplev.h $(GGC_H) $(RTL_H) \
- insn-config.h integrate.h tree-inline.h
+ insn-config.h integrate.h tree-inline.h real.h gt-cp-tree.h $(TARGET_H)
cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(SYSTEM_H)
cp/rtti.o: cp/rtti.c $(CXX_TREE_H) flags.h toplev.h
cp/except.o: cp/except.c $(CXX_TREE_H) flags.h $(RTL_H) except.h toplev.h \
- cp/cfns.h $(EXPR_H) libfuncs.h cp/decl.h $(OBSTACK_H)
+ cp/cfns.h $(EXPR_H) libfuncs.h tree-inline.h
cp/expr.o: cp/expr.c $(CXX_TREE_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \
except.h $(TM_P_H)
-cp/pt.o: cp/pt.c $(CXX_TREE_H) cp/decl.h cp/parse.h cp/lex.h toplev.h \
- $(GGC_H) $(RTL_H) except.h tree-inline.h
-cp/error.o: cp/error.c $(CXX_TREE_H) toplev.h diagnostic.h flags.h real.h
-cp/repo.o: cp/repo.c $(CXX_TREE_H) toplev.h $(GGC_H) diagnostic.h
+cp/pt.o: cp/pt.c $(CXX_TREE_H) cp/decl.h $(srcdir)/cp/parse.h cp/lex.h \
+ toplev.h $(GGC_H) $(RTL_H) except.h tree-inline.h gt-cp-pt.h
+cp/error.o: cp/error.c $(CXX_TREE_H) toplev.h diagnostic.h flags.h real.h \
+ $(LANGHOOKS_DEF_H)
+cp/repo.o: cp/repo.c $(CXX_TREE_H) toplev.h $(GGC_H) diagnostic.h \
+ gt-cp-repo.h
cp/semantics.o: cp/semantics.c $(CXX_TREE_H) cp/lex.h except.h toplev.h \
flags.h $(GGC_H) debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \
tree-inline.h
cp/dump.o: cp/dump.c $(CXX_TREE_H) tree-dump.h
cp/optimize.o: cp/optimize.c $(CXX_TREE_H) rtl.h integrate.h insn-config.h \
input.h $(PARAMS_H) debug.h tree-inline.h
-cp/mangle.o: cp/mangle.c $(CXX_TREE_H) toplev.h
+cp/mangle.o: cp/mangle.c $(CXX_TREE_H) toplev.h real.h gt-cp-mangle.h $(TM_P_H)
cp/parse.o: cp/parse.c $(CXX_TREE_H) flags.h cp/lex.h except.h output.h \
- $(SYSTEM_H) toplev.h $(GGC_H)
+ cp/decl.h $(SYSTEM_H) toplev.h $(GGC_H) gt-cp-parse.h
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
$(srcdir)/cp/parse.c $(OUTPUT_OPTION)
#
diff --git a/contrib/gcc/cp/NEWS b/contrib/gcc/cp/NEWS
index 97d4cd8..36720c6 100644
--- a/contrib/gcc/cp/NEWS
+++ b/contrib/gcc/cp/NEWS
@@ -1,4 +1,6 @@
-*** Changes in GCC 3.2.2:
+*** Changes in GCC 3.3:
+
+* The "new X = 3" extension has been removed; you must now use "new X(3)".
* G++ no longer allows in-class initializations of static data members
that do not have arithmetic or enumeration type. For example:
diff --git a/contrib/gcc/cp/call.c b/contrib/gcc/cp/call.c
index c8dcaf0..ac7aeb8 100644
--- a/contrib/gcc/cp/call.c
+++ b/contrib/gcc/cp/call.c
@@ -1,6 +1,6 @@
/* Functions related to invoking methods and overloaded functions.
- Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003,
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) and
modified by Brendan Kehoe (brendan@cygnus.com).
@@ -38,20 +38,20 @@ Boston, MA 02111-1307, USA. */
extern int inhibit_warnings;
-static tree build_new_method_call PARAMS ((tree, tree, tree, tree, int));
-
-static tree build_field_call PARAMS ((tree, tree, tree, tree));
+static tree build_field_call PARAMS ((tree, tree, tree));
static struct z_candidate * tourney PARAMS ((struct z_candidate *));
static int equal_functions PARAMS ((tree, tree));
static int joust PARAMS ((struct z_candidate *, struct z_candidate *, int));
static int compare_ics PARAMS ((tree, tree));
static tree build_over_call PARAMS ((struct z_candidate *, tree, int));
static tree build_java_interface_fn_ref PARAMS ((tree, tree));
-#define convert_like(CONV, EXPR) \
- convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0)
-#define convert_like_with_context(CONV, EXPR, FN, ARGNO) \
- convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0)
-static tree convert_like_real PARAMS ((tree, tree, tree, int, int));
+#define convert_like(CONV, EXPR) \
+ convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0, \
+ /*issue_conversion_warnings=*/true)
+#define convert_like_with_context(CONV, EXPR, FN, ARGNO) \
+ convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0, \
+ /*issue_conversion_warnings=*/true)
+static tree convert_like_real (tree, tree, tree, int, int, bool);
static void op_error PARAMS ((enum tree_code, enum tree_code, tree, tree,
tree, const char *));
static tree build_object_call PARAMS ((tree, tree));
@@ -62,38 +62,39 @@ static void print_z_candidates PARAMS ((struct z_candidate *));
static tree build_this PARAMS ((tree));
static struct z_candidate * splice_viable PARAMS ((struct z_candidate *));
static int any_viable PARAMS ((struct z_candidate *));
+static int any_strictly_viable PARAMS ((struct z_candidate *));
static struct z_candidate * add_template_candidate
- PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, int,
- unification_kind_t));
+ PARAMS ((struct z_candidate **, tree, tree, tree, tree, tree,
+ tree, tree, int, unification_kind_t));
static struct z_candidate * add_template_candidate_real
- PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, int,
- tree, unification_kind_t));
+ PARAMS ((struct z_candidate **, tree, tree, tree, tree, tree,
+ tree, tree, int, tree, unification_kind_t));
static struct z_candidate * add_template_conv_candidate
- PARAMS ((struct z_candidate *, tree, tree, tree, tree));
-static struct z_candidate * add_builtin_candidates
- PARAMS ((struct z_candidate *, enum tree_code, enum tree_code,
+ PARAMS ((struct z_candidate **, tree, tree, tree, tree, tree, tree));
+static void add_builtin_candidates
+ PARAMS ((struct z_candidate **, enum tree_code, enum tree_code,
tree, tree *, int));
-static struct z_candidate * add_builtin_candidate
- PARAMS ((struct z_candidate *, enum tree_code, enum tree_code,
+static void add_builtin_candidate
+ PARAMS ((struct z_candidate **, enum tree_code, enum tree_code,
tree, tree, tree, tree *, tree *, int));
static int is_complete PARAMS ((tree));
-static struct z_candidate * build_builtin_candidate
- PARAMS ((struct z_candidate *, tree, tree, tree, tree *, tree *,
+static void build_builtin_candidate
+ PARAMS ((struct z_candidate **, tree, tree, tree, tree *, tree *,
int));
static struct z_candidate * add_conv_candidate
- PARAMS ((struct z_candidate *, tree, tree, tree));
+ PARAMS ((struct z_candidate **, tree, tree, tree, tree, tree));
static struct z_candidate * add_function_candidate
- PARAMS ((struct z_candidate *, tree, tree, tree, int));
+ (struct z_candidate **, tree, tree, tree, tree, tree, int);
static tree implicit_conversion PARAMS ((tree, tree, tree, int));
static tree standard_conversion PARAMS ((tree, tree, tree));
-static tree reference_binding PARAMS ((tree, tree, tree, int));
+static tree reference_binding (tree, tree, tree, int);
static tree non_reference PARAMS ((tree));
static tree build_conv PARAMS ((enum tree_code, tree, tree));
static int is_subseq PARAMS ((tree, tree));
static tree maybe_handle_ref_bind PARAMS ((tree*));
static void maybe_handle_implicit_object PARAMS ((tree*));
-static struct z_candidate * add_candidate PARAMS ((struct z_candidate *,
- tree, tree, int));
+static struct z_candidate *add_candidate
+ (struct z_candidate **, tree, tree, tree, tree, int);
static tree source_type PARAMS ((tree));
static void add_warning PARAMS ((struct z_candidate *, struct z_candidate *));
static int reference_related_p PARAMS ((tree, tree));
@@ -102,56 +103,46 @@ static tree convert_class_to_reference PARAMS ((tree, tree, tree));
static tree direct_reference_binding PARAMS ((tree, tree));
static int promoted_arithmetic_type_p PARAMS ((tree));
static tree conditional_conversion PARAMS ((tree, tree));
+static tree call_builtin_trap PARAMS ((void));
+static tree merge_conversion_sequences (tree, tree);
tree
build_vfield_ref (datum, type)
tree datum, type;
{
- tree rval;
-
if (datum == error_mark_node)
return error_mark_node;
if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
datum = convert_from_reference (datum);
- if (! TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type))
- rval = build (COMPONENT_REF, TREE_TYPE (TYPE_VFIELD (type)),
- datum, TYPE_VFIELD (type));
- else
- rval = build_component_ref (datum, DECL_NAME (TYPE_VFIELD (type)), NULL_TREE, 0);
+ if (TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type)
+ && !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type))
+ datum = convert_to_base (datum, type, /*check_access=*/false);
- return rval;
+ return build (COMPONENT_REF, TREE_TYPE (TYPE_VFIELD (type)),
+ datum, TYPE_VFIELD (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;
+build_field_call (tree instance_ptr, tree decl, tree parms)
{
- tree field, instance;
-
- if (IDENTIFIER_CTOR_OR_DTOR_P (name))
- return NULL_TREE;
-
- /* Speed up the common case. */
- if (instance_ptr == current_class_ptr
- && IDENTIFIER_CLASS_VALUE (name) == NULL_TREE)
- return NULL_TREE;
-
- field = lookup_field (basetype_path, name, 1, 0);
+ tree instance;
- if (field == error_mark_node || field == NULL_TREE)
- return field;
+ if (decl == error_mark_node || decl == NULL_TREE)
+ return decl;
- if (TREE_CODE (field) == FIELD_DECL || TREE_CODE (field) == VAR_DECL)
+ if (TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL)
{
/* If it's a field, try overloading operator (),
or calling if the field is a pointer-to-function. */
instance = build_indirect_ref (instance_ptr, NULL);
- instance = build_component_ref_1 (instance, field, 0);
+ instance = build_class_member_access_expr (instance, decl,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false);
if (instance == error_mark_node)
return error_mark_node;
@@ -298,27 +289,10 @@ build_scoped_method_call (exp, basetype, name, parms)
return error_mark_node;
}
- if (! binfo)
- {
- binfo = lookup_base (type, basetype, ba_check, NULL);
- if (binfo == error_mark_node)
- return error_mark_node;
- if (! binfo)
- error_not_base_type (basetype, type);
- }
+ decl = build_scoped_ref (exp, basetype, &binfo);
if (binfo)
{
- if (TREE_CODE (exp) == INDIRECT_REF)
- {
- decl = build_base_path (PLUS_EXPR,
- build_unary_op (ADDR_EXPR, exp, 0),
- binfo, 1);
- decl = build_indirect_ref (decl, NULL);
- }
- else
- decl = build_scoped_ref (exp, basetype);
-
/* Call to a destructor. */
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
@@ -355,7 +329,7 @@ build_addr_func (function)
type = build_pointer_type (type);
- if (mark_addressable (function) == 0)
+ if (!cxx_mark_addressable (function))
return error_mark_node;
addr = build1 (ADDR_EXPR, type, function);
@@ -386,6 +360,7 @@ build_call (function, parms)
tree tmp;
tree decl;
tree result_type;
+ tree fntype;
function = build_addr_func (function);
@@ -395,7 +370,8 @@ build_call (function, parms)
return error_mark_node;
}
- result_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (function)));
+ fntype = TREE_TYPE (TREE_TYPE (function));
+ result_type = TREE_TYPE (fntype);
if (TREE_CODE (function) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
@@ -408,11 +384,12 @@ build_call (function, parms)
nothrow = ((decl && TREE_NOTHROW (decl))
|| TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function))));
- if (decl && TREE_THIS_VOLATILE (decl))
+ if (decl && TREE_THIS_VOLATILE (decl) && cfun)
current_function_returns_abnormally = 1;
if (decl && TREE_DEPRECATED (decl))
warn_deprecated_use (decl);
+ require_complete_eh_spec_types (fntype, decl);
if (decl && DECL_CONSTRUCTOR_P (decl))
is_constructor = 1;
@@ -492,7 +469,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
tree instance, name, parms, basetype_path;
int flags;
{
- tree basetype, instance_ptr;
+ tree fn;
+ tree object_type;
+ tree template_args = NULL_TREE;
+ bool has_template_args = false;
#ifdef GATHER_STATISTICS
n_build_method_call++;
@@ -501,7 +481,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (instance == error_mark_node
|| name == error_mark_node
|| parms == error_mark_node
- || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node))
+ || (instance && TREE_TYPE (instance) == error_mark_node))
return error_mark_node;
if (processing_template_decl)
@@ -524,39 +504,111 @@ build_method_call (instance, name, parms, basetype_path, flags)
return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
}
+ if (TREE_CODE (instance) == OFFSET_REF)
+ instance = resolve_offset_ref (instance);
+ if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
+ instance = convert_from_reference (instance);
+ object_type = TREE_TYPE (instance);
+
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
+ tree instance_ptr;
+
if (parms)
error ("destructors take no parameters");
- basetype = TREE_TYPE (instance);
- if (TREE_CODE (basetype) == REFERENCE_TYPE)
- basetype = TREE_TYPE (basetype);
- if (! check_dtor_name (basetype, name))
+ if (! check_dtor_name (object_type, name))
error
("destructor name `~%T' does not match type `%T' of expression",
- TREE_OPERAND (name, 0), basetype);
+ TREE_OPERAND (name, 0), object_type);
- if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype)))
+ /* The destructor type must be complete. */
+ object_type = complete_type_or_else (object_type, NULL_TREE);
+ if (!object_type || object_type == error_mark_node)
+ return error_mark_node;
+
+ if (! TYPE_HAS_DESTRUCTOR (object_type))
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),
+ return build_delete (build_pointer_type (object_type),
instance_ptr, sfk_complete_destructor,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
}
- return build_new_method_call (instance, name, parms, basetype_path, flags);
+ if (!CLASS_TYPE_P (object_type))
+ {
+ if ((flags & LOOKUP_COMPLAIN)
+ && TREE_TYPE (instance) != error_mark_node)
+ error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
+ name, instance, object_type);
+ return error_mark_node;
+ }
+
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ {
+ template_args = TREE_OPERAND (name, 1);
+ has_template_args = true;
+ name = TREE_OPERAND (name, 0);
+ }
+ if (TREE_CODE (name) == OVERLOAD)
+ name = DECL_NAME (get_first_fn (name));
+ else if (TREE_CODE (name) == LOOKUP_EXPR)
+ name = TREE_OPERAND (name, 0);
+ else if (DECL_P (name))
+ name = DECL_NAME (name);
+ if (has_template_args)
+ fn = lookup_fnfields (object_type, name, /*protect=*/2);
+ else
+ fn = lookup_member (object_type, name, /*protect=*/2, /*want_type=*/0);
+
+ if (fn && TREE_CODE (fn) == TREE_LIST && !BASELINK_P (fn))
+ {
+ error ("request for member `%D' is ambiguous", name);
+ print_candidates (fn);
+ return error_mark_node;
+ }
+
+ /* If the name could not be found, issue an error. */
+ if (!fn)
+ {
+ unqualified_name_lookup_error (name);
+ return error_mark_node;
+ }
+
+ if (BASELINK_P (fn) && has_template_args)
+ BASELINK_FUNCTIONS (fn)
+ = build_nt (TEMPLATE_ID_EXPR,
+ BASELINK_FUNCTIONS (fn),
+ template_args);
+ if (BASELINK_P (fn) && basetype_path)
+ BASELINK_ACCESS_BINFO (fn) = basetype_path;
+
+ return build_new_method_call (instance, fn, parms,
+ /*conversion_path=*/NULL_TREE, flags);
}
/* New overloading code. */
-struct z_candidate {
+struct z_candidate GTY(()) {
+ /* The FUNCTION_DECL that will be called if this candidate is
+ selected by overload resolution. */
tree fn;
tree convs;
tree second_conv;
int viable;
- tree basetype_path;
+ /* If FN is a member function, the binfo indicating the path used to
+ qualify the name of FN at the call site. This path is used to
+ determine whether or not FN is accessible if it is selected by
+ overload resolution. The DECL_CONTEXT of FN will always be a
+ (possibly improper) base of this binfo. */
+ tree access_path;
+ /* If FN is a non-static member function, the binfo indicating the
+ subobject to which the `this' pointer should be converted if FN
+ is selected by overload resolution. The type pointed to the by
+ the `this' pointer must correspond to the most derived class
+ indicated by the CONVERSION_PATH. */
+ tree conversion_path;
tree template;
tree warnings;
struct z_candidate *next;
@@ -588,8 +640,7 @@ struct z_candidate {
should be created to hold the result of the conversion. */
#define NEED_TEMPORARY_P(NODE) TREE_LANG_FLAG_4 (NODE)
-#define USER_CONV_CAND(NODE) \
- ((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1)))
+#define USER_CONV_CAND(NODE) WRAPPER_ZC (TREE_OPERAND (NODE, 1))
#define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn)
int
@@ -607,8 +658,8 @@ null_ptr_cst_p (t)
}
-/* Returns non-zero if PARMLIST consists of only default parms and/or
- ellipsis. */
+/* Returns nonzero if PARMLIST consists of only default parms and/or
+ ellipsis. */
int
sufficient_parms_p (parmlist)
@@ -654,7 +705,7 @@ build_conv (code, type, from)
break;
}
ICS_STD_RANK (t) = rank;
- ICS_USER_FLAG (t) = ICS_USER_FLAG (from);
+ ICS_USER_FLAG (t) = (code == USER_CONV || ICS_USER_FLAG (from));
ICS_BAD_FLAG (t) = ICS_BAD_FLAG (from);
return t;
}
@@ -801,8 +852,7 @@ standard_conversion (to, from, expr)
(TREE_TYPE (TREE_TYPE (from)),
TREE_TYPE (TREE_TYPE (to)))))
{
- from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from)));
- from = build_pointer_type (from);
+ from = build_ptrmem_type (tbase, TREE_TYPE (TREE_TYPE (from)));
conv = build_conv (PMEM_CONV, from, conv);
}
}
@@ -899,7 +949,7 @@ standard_conversion (to, from, expr)
return conv;
}
-/* Returns non-zero if T1 is reference-related to T2. */
+/* Returns nonzero if T1 is reference-related to T2. */
static int
reference_related_p (t1, t2)
@@ -919,7 +969,7 @@ reference_related_p (t1, t2)
&& DERIVED_FROM_P (t1, t2)));
}
-/* Returns non-zero if T1 is reference-compatible with T2. */
+/* Returns nonzero if T1 is reference-compatible with T2. */
static int
reference_compatible_p (t1, t2)
@@ -947,9 +997,14 @@ convert_class_to_reference (t, s, expr)
tree conversions;
tree arglist;
tree conv;
+ tree reference_type;
struct z_candidate *candidates;
struct z_candidate *cand;
+ conversions = lookup_conversions (s);
+ if (!conversions)
+ return NULL_TREE;
+
/* [over.match.ref]
Assuming that "cv1 T" is the underlying type of the reference
@@ -975,10 +1030,10 @@ convert_class_to_reference (t, s, expr)
arglist = build_int_2 (0, 0);
TREE_TYPE (arglist) = build_pointer_type (s);
arglist = build_tree_list (NULL_TREE, arglist);
-
- for (conversions = lookup_conversions (s);
- conversions;
- conversions = TREE_CHAIN (conversions))
+
+ reference_type = build_reference_type (t);
+
+ while (conversions)
{
tree fns = TREE_VALUE (conversions);
@@ -986,43 +1041,58 @@ convert_class_to_reference (t, s, expr)
{
tree f = OVL_CURRENT (fns);
tree t2 = TREE_TYPE (TREE_TYPE (f));
- struct z_candidate *old_candidates = candidates;
+
+ cand = NULL;
/* If this is a template function, try to get an exact
match. */
if (TREE_CODE (f) == TEMPLATE_DECL)
{
- candidates
- = add_template_candidate (candidates,
- f, s,
- NULL_TREE,
- arglist,
- build_reference_type (t),
- LOOKUP_NORMAL,
- DEDUCE_CONV);
+ cand = add_template_candidate (&candidates,
+ f, s,
+ NULL_TREE,
+ arglist,
+ reference_type,
+ TYPE_BINFO (s),
+ TREE_PURPOSE (conversions),
+ LOOKUP_NORMAL,
+ DEDUCE_CONV);
- if (candidates != old_candidates)
+ if (cand)
{
/* Now, see if the conversion function really returns
an lvalue of the appropriate type. From the
point of view of unification, simply returning an
rvalue of the right type is good enough. */
- f = candidates->fn;
+ f = cand->fn;
t2 = TREE_TYPE (TREE_TYPE (f));
if (TREE_CODE (t2) != REFERENCE_TYPE
|| !reference_compatible_p (t, TREE_TYPE (t2)))
- candidates = candidates->next;
+ {
+ candidates = candidates->next;
+ cand = NULL;
+ }
}
}
else if (TREE_CODE (t2) == REFERENCE_TYPE
&& reference_compatible_p (t, TREE_TYPE (t2)))
- candidates
- = add_function_candidate (candidates, f, s, arglist,
- LOOKUP_NORMAL);
-
- if (candidates != old_candidates)
- candidates->basetype_path = TYPE_BINFO (s);
+ cand = add_function_candidate (&candidates, f, s, arglist,
+ TYPE_BINFO (s),
+ TREE_PURPOSE (conversions),
+ LOOKUP_NORMAL);
+
+ if (cand)
+ /* Build a standard conversion sequence indicating the
+ binding from the reference type returned by the
+ function to the desired REFERENCE_TYPE. */
+ cand->second_conv
+ = (direct_reference_binding
+ (reference_type,
+ build1 (IDENTITY_CONV,
+ TREE_TYPE (TREE_TYPE (TREE_TYPE (cand->fn))),
+ NULL_TREE)));
}
+ conversions = TREE_CHAIN (conversions);
}
/* If none of the conversion functions worked out, let our caller
@@ -1035,16 +1105,21 @@ convert_class_to_reference (t, s, expr)
if (!cand)
return NULL_TREE;
- conv = build1 (IDENTITY_CONV, s, expr);
- conv = build_conv (USER_CONV, TREE_TYPE (TREE_TYPE (cand->fn)),
- conv);
- TREE_OPERAND (conv, 1) = build_ptr_wrapper (cand);
- ICS_USER_FLAG (conv) = 1;
+ /* Build a user-defined conversion sequence representing the
+ conversion. */
+ conv = build_conv (USER_CONV,
+ TREE_TYPE (TREE_TYPE (cand->fn)),
+ build1 (IDENTITY_CONV, TREE_TYPE (expr), expr));
+ TREE_OPERAND (conv, 1) = build_zc_wrapper (cand);
+
+ /* Merge it with the standard conversion sequence from the
+ conversion function's return type to the desired type. */
+ cand->second_conv = merge_conversion_sequences (conv, cand->second_conv);
+
if (cand->viable == -1)
ICS_BAD_FLAG (conv) = 1;
- cand->second_conv = conv;
- return conv;
+ return cand->second_conv;
}
/* A reference of the indicated TYPE is being bound directly to the
@@ -1056,7 +1131,13 @@ direct_reference_binding (type, conv)
tree type;
tree conv;
{
- tree t = TREE_TYPE (type);
+ tree t;
+
+ my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 20030306);
+ my_friendly_assert (TREE_CODE (TREE_TYPE (conv)) != REFERENCE_TYPE,
+ 20030306);
+
+ t = TREE_TYPE (type);
/* [over.ics.rank]
@@ -1093,9 +1174,7 @@ direct_reference_binding (type, conv)
the conversion returned. */
static tree
-reference_binding (rto, rfrom, expr, flags)
- tree rto, rfrom, expr;
- int flags;
+reference_binding (tree rto, tree rfrom, tree expr, int flags)
{
tree conv = NULL_TREE;
tree to = TREE_TYPE (rto);
@@ -1173,7 +1252,7 @@ reference_binding (rto, rfrom, expr, flags)
in the second case. */
conv = convert_class_to_reference (to, from, expr);
if (conv)
- return direct_reference_binding (rto, conv);
+ return conv;
}
/* From this point on, we conceptually need temporaries, even if we
@@ -1207,11 +1286,13 @@ reference_binding (rto, rfrom, expr, flags)
-- The reference is bound to the object represented by the rvalue
or to a sub-object within that object.
- In this case, the implicit conversion sequence is supposed to be
- same as we would obtain by generating a temporary. Fortunately,
- if the types are reference compatible, then this is either an
- identity conversion or the derived-to-base conversion, just as
- for direct binding. */
+ -- ...
+
+ We use the first alternative. The implicit conversion sequence
+ is supposed to be same as we would obtain by generating a
+ temporary. Fortunately, if the types are reference compatible,
+ then this is either an identity conversion or the derived-to-base
+ conversion, just as for direct binding. */
if (CLASS_TYPE_P (from) && compatible_p)
{
conv = build1 (IDENTITY_CONV, from, expr);
@@ -1251,7 +1332,6 @@ implicit_conversion (to, from, expr, flags)
int flags;
{
tree conv;
- struct z_candidate *cand;
/* Resolve expressions like `A::p' that we thought might become
pointers-to-members. */
@@ -1265,11 +1345,6 @@ implicit_conversion (to, from, expr, flags)
|| expr == error_mark_node)
return NULL_TREE;
- /* Make sure both the FROM and TO types are complete so that
- user-defined conversions are available. */
- complete_type (from);
- complete_type (to);
-
if (TREE_CODE (to) == REFERENCE_TYPE)
conv = reference_binding (to, from, expr, flags);
else
@@ -1282,6 +1357,8 @@ implicit_conversion (to, from, expr, flags)
|| IS_AGGR_TYPE (to))
&& (flags & LOOKUP_NO_CONVERSION) == 0)
{
+ struct z_candidate *cand;
+
cand = build_user_type_conversion_1
(to, expr, LOOKUP_ONLYCONVERTING);
if (cand)
@@ -1299,18 +1376,20 @@ implicit_conversion (to, from, expr, flags)
functions. */
static struct z_candidate *
-add_candidate (candidates, fn, convs, viable)
- struct z_candidate *candidates;
- tree fn, convs;
- int viable;
+add_candidate (struct z_candidate **candidates,
+ tree fn, tree convs, tree access_path, tree
+ conversion_path, int viable)
{
struct z_candidate *cand
= (struct z_candidate *) ggc_alloc_cleared (sizeof (struct z_candidate));
cand->fn = fn;
cand->convs = convs;
+ cand->access_path = access_path;
+ cand->conversion_path = conversion_path;
cand->viable = viable;
- cand->next = candidates;
+ cand->next = *candidates;
+ *candidates = cand;
return cand;
}
@@ -1323,10 +1402,10 @@ add_candidate (candidates, fn, convs, viable)
comes from for purposes of overload resolution. */
static struct z_candidate *
-add_function_candidate (candidates, fn, ctype, arglist, flags)
- struct z_candidate *candidates;
- tree fn, ctype, arglist;
- int flags;
+add_function_candidate (struct z_candidate **candidates,
+ tree fn, tree ctype, tree arglist,
+ tree access_path, tree conversion_path,
+ int flags)
{
tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
int i, len;
@@ -1334,6 +1413,11 @@ add_function_candidate (candidates, fn, ctype, arglist, flags)
tree parmnode, argnode;
int viable = 1;
+ /* Built-in functions that haven't been declared don't really
+ exist. */
+ if (DECL_ANTICIPATED (fn))
+ return NULL;
+
/* The `this', `in_chrg' and VTT arguments to constructors are not
considered in overload resolution. */
if (DECL_CONSTRUCTOR_P (fn))
@@ -1438,7 +1522,8 @@ add_function_candidate (candidates, fn, ctype, arglist, flags)
}
out:
- return add_candidate (candidates, fn, convs, viable);
+ return add_candidate (candidates, fn, convs, access_path,
+ conversion_path, viable);
}
/* Create an overload candidate for the conversion function FN which will
@@ -1453,9 +1538,12 @@ add_function_candidate (candidates, fn, ctype, arglist, flags)
instead of the function. */
static struct z_candidate *
-add_conv_candidate (candidates, fn, obj, arglist)
- struct z_candidate *candidates;
+add_conv_candidate (candidates, fn, obj, arglist, access_path,
+ conversion_path)
+ struct z_candidate **candidates;
tree fn, obj, arglist;
+ tree access_path;
+ tree conversion_path;
{
tree totype = TREE_TYPE (TREE_TYPE (fn));
int i, len, viable, flags;
@@ -1473,8 +1561,8 @@ add_conv_candidate (candidates, fn, obj, arglist)
flags = LOOKUP_NORMAL;
/* Don't bother looking up the same type twice. */
- if (candidates && candidates->fn == totype)
- return candidates;
+ if (*candidates && (*candidates)->fn == totype)
+ return NULL;
for (i = 0; i < len; ++i)
{
@@ -1515,13 +1603,14 @@ add_conv_candidate (candidates, fn, obj, arglist)
if (!sufficient_parms_p (parmnode))
viable = 0;
- return add_candidate (candidates, totype, convs, viable);
+ return add_candidate (candidates, totype, convs, access_path,
+ conversion_path, viable);
}
-static struct z_candidate *
+static void
build_builtin_candidate (candidates, fnname, type1, type2,
args, argtypes, flags)
- struct z_candidate *candidates;
+ struct z_candidate **candidates;
tree fnname, type1, type2, *args, *argtypes;
int flags;
@@ -1564,7 +1653,10 @@ build_builtin_candidate (candidates, fnname, type1, type2,
viable = 0;
}
- return add_candidate (candidates, fnname, convs, viable);
+ add_candidate (candidates, fnname, convs,
+ /*access_path=*/NULL_TREE,
+ /*conversion_path=*/NULL_TREE,
+ viable);
}
static int
@@ -1574,7 +1666,7 @@ is_complete (t)
return COMPLETE_TYPE_P (complete_type (t));
}
-/* Returns non-zero if TYPE is a promoted arithmetic type. */
+/* Returns nonzero if TYPE is a promoted arithmetic type. */
static int
promoted_arithmetic_type_p (type)
@@ -1602,10 +1694,10 @@ promoted_arithmetic_type_p (type)
of which TYPE1 and TYPE2 are, we add both candidates
CODE (TYPE1, TYPE1) and CODE (TYPE2, TYPE2). */
-static struct z_candidate *
+static void
add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
args, argtypes, flags)
- struct z_candidate *candidates;
+ struct z_candidate **candidates;
enum tree_code code, code2;
tree fnname, type1, type2, *args, *argtypes;
int flags;
@@ -1645,7 +1737,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case POSTDECREMENT_EXPR:
case PREDECREMENT_EXPR:
if (TREE_CODE (type1) == BOOLEAN_TYPE)
- return candidates;
+ return;
case POSTINCREMENT_EXPR:
case PREINCREMENT_EXPR:
if (ARITHMETIC_TYPE_P (type1) || TYPE_PTROB_P (type1))
@@ -1653,7 +1745,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
type1 = build_reference_type (type1);
break;
}
- return candidates;
+ return;
/* 7 For every cv-qualified or cv-unqualified complete object type T, there
exist candidate operator functions of the form
@@ -1669,7 +1761,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
&& (TYPE_PTROB_P (type1)
|| TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE))
break;
- return candidates;
+ return;
/* 9 For every type T, there exist candidate operator functions of the form
T* operator+(T*);
@@ -1686,7 +1778,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case NEGATE_EXPR:
if (ARITHMETIC_TYPE_P (type1))
break;
- return candidates;
+ return;
/* 11For every promoted integral type T, there exist candidate operator
functions of the form
@@ -1695,7 +1787,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case BIT_NOT_EXPR:
if (INTEGRAL_TYPE_P (type1))
break;
- return candidates;
+ return;
/* 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
@@ -1718,7 +1810,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
|| is_complete (TREE_TYPE (TREE_TYPE (type2)))))
break;
}
- return candidates;
+ return;
/* 13For every pair of promoted arithmetic types L and R, there exist can-
didate operator functions of the form
@@ -1774,7 +1866,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case TRUNC_DIV_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
- return candidates;
+ return;
case EQ_EXPR:
case NE_EXPR:
@@ -1816,7 +1908,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
type1 = type2;
break;
}
- return candidates;
+ return;
case PLUS_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
@@ -1832,7 +1924,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
type2 = ptrdiff_type_node;
break;
}
- return candidates;
+ return;
/* 18For every pair of promoted integral types L and R, there exist candi-
date operator functions of the form
@@ -1853,7 +1945,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case RSHIFT_EXPR:
if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
break;
- return candidates;
+ return;
/* 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
@@ -1905,7 +1997,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case TRUNC_DIV_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
- return candidates;
+ return;
case TRUNC_MOD_EXPR:
case BIT_AND_EXPR:
@@ -1915,7 +2007,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case RSHIFT_EXPR:
if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
break;
- return candidates;
+ return;
case NOP_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
@@ -1930,7 +2022,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
type2 = type1;
break;
}
- return candidates;
+ return;
default:
abort ();
@@ -1965,16 +2057,13 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
|| !(TREE_CODE (type2) == POINTER_TYPE
|| TYPE_PTRMEM_P (type2)
|| TYPE_PTRMEMFUNC_P (type2)))
- return candidates;
+ return;
/* We don't check that the two types are the same; the logic
below will actually create two candidates; one in which both
parameter types are TYPE1, and one in which both parameter
types are TYPE2. */
- break;
-
- /* These arguments do not make for a legal overloaded operator. */
- return candidates;
+ break;
default:
abort ();
@@ -1991,13 +2080,14 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
|| IS_AGGR_TYPE (type1)
|| TREE_CODE (type1) == ENUMERAL_TYPE))
{
- candidates = build_builtin_candidate
+ build_builtin_candidate
(candidates, fnname, type1, type1, args, argtypes, flags);
- return build_builtin_candidate
+ build_builtin_candidate
(candidates, fnname, type2, type2, args, argtypes, flags);
+ return;
}
- return build_builtin_candidate
+ build_builtin_candidate
(candidates, fnname, type1, type2, args, argtypes, flags);
}
@@ -2023,11 +2113,11 @@ type_decays_to (type)
Here we generate a superset of the possible candidates for this particular
case. That is a subset of the full set the standard defines, plus some
other cases which the standard disallows. add_builtin_candidate will
- filter out the illegal set. */
+ filter out the invalid set. */
-static struct z_candidate *
+static void
add_builtin_candidates (candidates, code, code2, fnname, args, flags)
- struct z_candidate *candidates;
+ struct z_candidate **candidates;
enum tree_code code, code2;
tree fnname, *args;
int flags;
@@ -2070,20 +2160,22 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
bool operator||(bool, bool); */
case TRUTH_NOT_EXPR:
- return build_builtin_candidate
+ build_builtin_candidate
(candidates, fnname, boolean_type_node,
NULL_TREE, args, argtypes, flags);
+ return;
case TRUTH_ORIF_EXPR:
case TRUTH_ANDIF_EXPR:
- return build_builtin_candidate
+ build_builtin_candidate
(candidates, fnname, boolean_type_node,
boolean_type_node, args, argtypes, flags);
+ return;
case ADDR_EXPR:
case COMPOUND_EXPR:
case COMPONENT_REF:
- return candidates;
+ return;
case COND_EXPR:
case EQ_EXPR:
@@ -2110,7 +2202,7 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
tree convs;
if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR)
- return candidates;
+ return;
convs = lookup_conversions (argtypes[i]);
@@ -2125,7 +2217,7 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
}
else if (! convs)
- return candidates;
+ return;
for (; convs; convs = TREE_CHAIN (convs))
{
@@ -2177,16 +2269,16 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
{
if (types[1])
for (type = types[1]; type; type = TREE_CHAIN (type))
- candidates = add_builtin_candidate
+ add_builtin_candidate
(candidates, code, code2, fnname, TREE_VALUE (types[0]),
TREE_VALUE (type), args, argtypes, flags);
else
- candidates = add_builtin_candidate
+ add_builtin_candidate
(candidates, code, code2, fnname, TREE_VALUE (types[0]),
NULL_TREE, args, argtypes, flags);
}
- return candidates;
+ return;
}
@@ -2202,10 +2294,12 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
static struct z_candidate*
add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
- arglist, return_type, flags,
- obj, strict)
- struct z_candidate *candidates;
+ arglist, return_type, access_path,
+ conversion_path, flags, obj, strict)
+ struct z_candidate **candidates;
tree tmpl, ctype, explicit_targs, arglist, return_type;
+ tree access_path;
+ tree conversion_path;
int flags;
tree obj;
unification_kind_t strict;
@@ -2232,11 +2326,11 @@ add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
return_type, strict, -1);
if (i != 0)
- return candidates;
+ return NULL;
fn = instantiate_template (tmpl, targs);
if (fn == error_mark_node)
- return candidates;
+ return NULL;
/* In [class.copy]:
@@ -2265,15 +2359,17 @@ add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),
ctype))
- return candidates;
+ return NULL;
}
if (obj != NULL_TREE)
/* Aha, this is a conversion function. */
- cand = add_conv_candidate (candidates, fn, obj, arglist);
+ cand = add_conv_candidate (candidates, fn, obj, access_path,
+ conversion_path, arglist);
else
cand = add_function_candidate (candidates, fn, ctype,
- arglist, flags);
+ arglist, access_path,
+ conversion_path, flags);
if (DECL_TI_TEMPLATE (fn) != tmpl)
/* This situation can occur if a member template of a template
class is specialized. Then, instantiate_template might return
@@ -2302,27 +2398,35 @@ add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
static struct z_candidate *
add_template_candidate (candidates, tmpl, ctype, explicit_targs,
- arglist, return_type, flags, strict)
- struct z_candidate *candidates;
+ arglist, return_type, access_path,
+ conversion_path, flags, strict)
+ struct z_candidate **candidates;
tree tmpl, ctype, explicit_targs, arglist, return_type;
+ tree access_path;
+ tree conversion_path;
int flags;
unification_kind_t strict;
{
return
add_template_candidate_real (candidates, tmpl, ctype,
- explicit_targs, arglist, return_type, flags,
- NULL_TREE, strict);
+ explicit_targs, arglist, return_type,
+ access_path, conversion_path,
+ flags, NULL_TREE, strict);
}
static struct z_candidate *
-add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
- struct z_candidate *candidates;
+add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type,
+ access_path, conversion_path)
+ struct z_candidate **candidates;
tree tmpl, obj, arglist, return_type;
+ tree access_path;
+ tree conversion_path;
{
return
add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
- arglist, return_type, 0, obj, DEDUCE_CONV);
+ arglist, return_type, access_path,
+ conversion_path, 0, obj, DEDUCE_CONV);
}
@@ -2336,6 +2440,16 @@ any_viable (cands)
return 0;
}
+static int
+any_strictly_viable (cands)
+ struct z_candidate *cands;
+{
+ for (; cands; cands = cands->next)
+ if (cands->viable == 1)
+ return 1;
+ return 0;
+}
+
static struct z_candidate *
splice_viable (cands)
struct z_candidate *cands;
@@ -2361,11 +2475,51 @@ build_this (obj)
return build_unary_op (ADDR_EXPR, obj, 0);
}
+/* Returns true iff functions are equivalent. Equivalent functions are
+ not '==' only if one is a function-local extern function or if
+ both are extern "C". */
+
+static inline int
+equal_functions (fn1, fn2)
+ tree fn1;
+ tree fn2;
+{
+ if (DECL_LOCAL_FUNCTION_P (fn1) || DECL_LOCAL_FUNCTION_P (fn2)
+ || DECL_EXTERN_C_FUNCTION_P (fn1))
+ return decls_match (fn1, fn2);
+ return fn1 == fn2;
+}
+
static void
-print_z_candidates (candidates)
- struct z_candidate *candidates;
+print_z_candidates (struct z_candidate *candidates)
{
- const char *str = "candidates are:";
+ const char *str;
+ struct z_candidate *cand1;
+ struct z_candidate **cand2;
+
+ /* There may be duplicates in the set of candidates. We put off
+ checking this condition as long as possible, since we have no way
+ to eliminate duplicates from a set of functions in less than n^2
+ time. Now we are about to emit an error message, so it is more
+ permissible to go slowly. */
+ for (cand1 = candidates; cand1; cand1 = cand1->next)
+ {
+ tree fn = cand1->fn;
+ /* Skip builtin candidates and conversion functions. */
+ if (TREE_CODE (fn) != FUNCTION_DECL)
+ continue;
+ cand2 = &cand1->next;
+ while (*cand2)
+ {
+ if (TREE_CODE ((*cand2)->fn) == FUNCTION_DECL
+ && equal_functions (fn, (*cand2)->fn))
+ *cand2 = (*cand2)->next;
+ else
+ cand2 = &(*cand2)->next;
+ }
+ }
+
+ str = "candidates are:";
for (; candidates; candidates = candidates->next)
{
if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
@@ -2392,6 +2546,35 @@ print_z_candidates (candidates)
}
}
+/* USER_SEQ is a user-defined conversion sequence, beginning with a
+ USER_CONV. STD_SEQ is the standard conversion sequence applied to
+ the result of the conversion function to convert it to the final
+ desired type. Merge the the two sequences into a single sequence,
+ and return the merged sequence. */
+
+static tree
+merge_conversion_sequences (tree user_seq, tree std_seq)
+{
+ tree *t;
+
+ my_friendly_assert (TREE_CODE (user_seq) == USER_CONV,
+ 20030306);
+
+ /* Find the end of the second conversion sequence. */
+ t = &(std_seq);
+ while (TREE_CODE (*t) != IDENTITY_CONV)
+ t = &TREE_OPERAND (*t, 0);
+
+ /* Replace the identity conversion with the user conversion
+ sequence. */
+ *t = user_seq;
+
+ /* The entire sequence is a user-conversion sequence. */
+ ICS_USER_FLAG (std_seq) = 1;
+
+ return std_seq;
+}
+
/* 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].
@@ -2405,9 +2588,8 @@ build_user_type_conversion_1 (totype, expr, flags)
{
struct z_candidate *candidates, *cand;
tree fromtype = TREE_TYPE (expr);
- tree ctors = NULL_TREE, convs = NULL_TREE, *p;
+ tree ctors = NULL_TREE, convs = NULL_TREE;
tree args = NULL_TREE;
- tree templates = NULL_TREE;
/* We represent conversion within a hierarchy using RVALUE_CONV and
BASE_CONV, as specified by [over.best.ics]; these become plain
@@ -2430,7 +2612,7 @@ build_user_type_conversion_1 (totype, expr, flags)
{
tree t;
- ctors = TREE_VALUE (ctors);
+ ctors = BASELINK_FUNCTIONS (ctors);
t = build_int_2 (0, 0);
TREE_TYPE (t) = build_pointer_type (totype);
@@ -2449,22 +2631,20 @@ build_user_type_conversion_1 (totype, expr, flags)
continue;
if (TREE_CODE (ctor) == TEMPLATE_DECL)
- {
- templates = tree_cons (NULL_TREE, ctor, templates);
- candidates =
- add_template_candidate (candidates, ctor, totype,
- NULL_TREE, args, NULL_TREE, flags,
- DEDUCE_CALL);
- }
+ cand = add_template_candidate (&candidates, ctor, totype,
+ NULL_TREE, args, NULL_TREE,
+ TYPE_BINFO (totype),
+ TYPE_BINFO (totype),
+ flags,
+ DEDUCE_CALL);
else
- candidates = add_function_candidate (candidates, ctor, totype,
- args, flags);
+ cand = add_function_candidate (&candidates, ctor, totype,
+ args, TYPE_BINFO (totype),
+ TYPE_BINFO (totype),
+ flags);
- if (candidates)
- {
- candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
- candidates->basetype_path = TYPE_BINFO (totype);
- }
+ if (cand)
+ cand->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
}
if (convs)
@@ -2472,9 +2652,9 @@ build_user_type_conversion_1 (totype, expr, flags)
for (; convs; convs = TREE_CHAIN (convs))
{
- tree fns = TREE_VALUE (convs);
+ tree fns;
+ tree conversion_path = TREE_PURPOSE (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
@@ -2482,73 +2662,50 @@ build_user_type_conversion_1 (totype, expr, flags)
look for a temporary binding. */
if (TREE_CODE (totype) == REFERENCE_TYPE)
convflags |= LOOKUP_NO_TEMP_BIND;
+
+ for (fns = TREE_VALUE (convs); fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+
+ /* [over.match.funcs] For conversion functions, the function
+ is considered to be a member of the class of the implicit
+ object argument for the purpose of defining the type of
+ the implicit object parameter.
- if (TREE_CODE (OVL_CURRENT (fns)) != TEMPLATE_DECL)
- ics = implicit_conversion
- (totype, TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))), 0, convflags);
- else
- /* We can't compute this yet. */
- ics = error_mark_node;
+ So we pass fromtype as CTYPE to add_*_candidate. */
- if (TREE_CODE (totype) == REFERENCE_TYPE && ics && ICS_BAD_FLAG (ics))
- /* ignore the near match. */;
- else if (ics)
- for (; fns; fns = OVL_NEXT (fns))
- {
- tree fn = OVL_CURRENT (fns);
- struct z_candidate *old_candidates = candidates;
-
- /* [over.match.funcs] For conversion functions, the function is
- considered to be a member of the class of the implicit object
- argument for the purpose of defining the type of the implicit
- object parameter.
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ cand = add_template_candidate (&candidates, fn, fromtype, NULL_TREE,
+ args, totype,
+ TYPE_BINFO (fromtype),
+ conversion_path,
+ flags,
+ DEDUCE_CONV);
+ else
+ cand = add_function_candidate (&candidates, fn, fromtype,
+ args,
+ TYPE_BINFO (fromtype),
+ conversion_path,
+ flags);
- So we pass fromtype as CTYPE to add_*_candidate. */
+ if (cand)
+ {
+ tree ics = implicit_conversion
+ (totype, TREE_TYPE (TREE_TYPE (cand->fn)),
+ 0, convflags);
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- {
- templates = tree_cons (NULL_TREE, fn, templates);
- candidates =
- add_template_candidate (candidates, fn, fromtype, NULL_TREE,
- args, totype, flags,
- DEDUCE_CONV);
- }
- else
- candidates = add_function_candidate (candidates, fn, fromtype,
- args, flags);
-
- if (candidates != old_candidates)
- {
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- ics = implicit_conversion
- (totype, TREE_TYPE (TREE_TYPE (candidates->fn)),
- 0, convflags);
-
- candidates->second_conv = ics;
- candidates->basetype_path = TYPE_BINFO (fromtype);
-
- if (ics == NULL_TREE)
- candidates->viable = 0;
- else if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
- candidates->viable = -1;
- }
- }
+ cand->second_conv = ics;
+
+ if (ics == NULL_TREE)
+ cand->viable = 0;
+ else if (cand->viable == 1 && ICS_BAD_FLAG (ics))
+ cand->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
- error ("no viable candidates");
- }
-#endif
-
- return 0;
- }
+ return 0;
candidates = splice_viable (candidates);
cand = tourney (candidates);
@@ -2565,23 +2722,29 @@ build_user_type_conversion_1 (totype, expr, flags)
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;
+ if (!any_strictly_viable (candidates))
+ ICS_BAD_FLAG (cand->second_conv) = 1;
+ /* If there are viable candidates, don't set ICS_BAD_FLAG; an
+ ambiguous conversion is no worse than another user-defined
+ conversion. */
return cand;
}
- for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; )
- p = &(TREE_OPERAND (*p, 0));
-
- *p = build
+ /* Build the user conversion sequence. */
+ convs = build_conv
(USER_CONV,
(DECL_CONSTRUCTOR_P (cand->fn)
? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))),
- expr, build_ptr_wrapper (cand));
-
- ICS_USER_FLAG (cand->second_conv) = ICS_USER_FLAG (*p) = 1;
+ build1 (IDENTITY_CONV, TREE_TYPE (expr), expr));
+ TREE_OPERAND (convs, 1) = build_zc_wrapper (cand);
+
+ /* Combine it with the second conversion sequence. */
+ cand->second_conv = merge_conversion_sequences (convs,
+ cand->second_conv);
+
if (cand->viable == -1)
- ICS_BAD_FLAG (cand->second_conv) = ICS_BAD_FLAG (*p) = 1;
+ ICS_BAD_FLAG (cand->second_conv) = 1;
return cand;
}
@@ -2603,6 +2766,78 @@ build_user_type_conversion (totype, expr, flags)
return NULL_TREE;
}
+/* Find the possibly overloaded set of functions corresponding to a
+ call of the form SCOPE::NAME (...). NAME might be a
+ TEMPLATE_ID_EXPR, OVERLOAD, _DECL, IDENTIFIER_NODE or LOOKUP_EXPR. */
+
+tree
+resolve_scoped_fn_name (tree scope, tree name)
+{
+ tree fn;
+ tree template_args = NULL_TREE;
+ bool is_template_id = TREE_CODE (name) == TEMPLATE_ID_EXPR;
+
+ if (is_template_id)
+ {
+ template_args = TREE_OPERAND (name, 1);
+ name = TREE_OPERAND (name, 0);
+ }
+ if (TREE_CODE (name) == OVERLOAD)
+ name = DECL_NAME (get_first_fn (name));
+ else if (TREE_CODE (name) == LOOKUP_EXPR)
+ name = TREE_OPERAND (name, 0);
+
+ if (TREE_CODE (scope) == NAMESPACE_DECL)
+ fn = lookup_namespace_name (scope, name);
+ else if (!CLASS_TYPE_P (scope))
+ {
+ error ("`%T' is not a class type", scope);
+ return error_mark_node;
+ }
+ else
+ {
+ if (!TYPE_BEING_DEFINED (scope)
+ && !COMPLETE_TYPE_P (complete_type (scope)))
+ {
+ error ("incomplete type '%T' cannot be used to name a scope",
+ scope);
+ return error_mark_node;
+ }
+
+ if (BASELINK_P (name))
+ fn = name;
+ else
+ fn = lookup_member (scope, name, /*protect=*/1, /*prefer_type=*/0);
+ if (fn && current_class_type)
+ fn = (adjust_result_of_qualified_name_lookup
+ (fn, scope, current_class_type));
+
+ /* It might be the name of a function pointer member. */
+ if (fn && TREE_CODE (fn) == FIELD_DECL)
+ fn = resolve_offset_ref (build_offset_ref (scope, fn));
+ }
+
+ if (!fn)
+ {
+ error ("'%D' has no member named '%E'", scope, name);
+ return error_mark_node;
+ }
+ if (is_template_id)
+ {
+ tree fns = fn;
+
+ if (BASELINK_P (fn))
+ fns = BASELINK_FUNCTIONS (fns);
+ fns = build_nt (TEMPLATE_ID_EXPR, fns, template_args);
+ if (BASELINK_P (fn))
+ BASELINK_FUNCTIONS (fn) = fns;
+ else
+ fn = fns;
+ }
+
+ return fn;
+}
+
/* Do any initial processing on the arguments to a function call. */
static tree
@@ -2628,6 +2863,9 @@ resolve_args (args)
}
return args;
}
+
+/* Return an expression for a call to FN (a namespace-scope function)
+ with the ARGS. */
tree
build_new_function_call (fn, args)
@@ -2637,6 +2875,15 @@ build_new_function_call (fn, args)
tree explicit_targs = NULL_TREE;
int template_only = 0;
+ /* Check FN and ARGS. */
+ my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL
+ || TREE_CODE (fn) == TEMPLATE_DECL
+ || TREE_CODE (fn) == OVERLOAD
+ || TREE_CODE (fn) == TEMPLATE_ID_EXPR,
+ 20020712);
+ my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST,
+ 20020712);
+
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
{
explicit_targs = TREE_OPERAND (fn, 1);
@@ -2644,30 +2891,30 @@ build_new_function_call (fn, args)
template_only = 1;
}
- if (really_overloaded_fn (fn))
+ if (really_overloaded_fn (fn)
+ || TREE_CODE (fn) == TEMPLATE_DECL)
{
tree t1;
- tree templates = NULL_TREE;
args = resolve_args (args);
if (args == error_mark_node)
return error_mark_node;
- for (t1 = fn; t1; t1 = OVL_CHAIN (t1))
+ for (t1 = fn; t1; t1 = OVL_NEXT (t1))
{
- tree t = OVL_FUNCTION (t1);
+ tree t = OVL_CURRENT (t1);
if (TREE_CODE (t) == TEMPLATE_DECL)
- {
- templates = tree_cons (NULL_TREE, t, templates);
- candidates = add_template_candidate
- (candidates, t, NULL_TREE, explicit_targs, args, NULL_TREE,
- LOOKUP_NORMAL, DEDUCE_CALL);
- }
+ add_template_candidate
+ (&candidates, t, NULL_TREE, explicit_targs, args,
+ NULL_TREE,
+ /*access_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE,
+ LOOKUP_NORMAL, DEDUCE_CALL);
else if (! template_only)
- candidates = add_function_candidate
- (candidates, t, NULL_TREE, args, LOOKUP_NORMAL);
+ add_function_candidate
+ (&candidates, t, NULL_TREE, args, /*access_path=*/NULL_TREE,
+ /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL);
}
if (! any_viable (candidates))
@@ -2675,7 +2922,7 @@ build_new_function_call (fn, args)
if (candidates && ! candidates->next)
return build_function_call (candidates->fn, args);
error ("no matching function for call to `%D(%A)'",
- DECL_NAME (OVL_FUNCTION (fn)), args);
+ DECL_NAME (OVL_CURRENT (fn)), args);
if (candidates)
print_z_candidates (candidates);
return error_mark_node;
@@ -2694,7 +2941,7 @@ build_new_function_call (fn, args)
return build_over_call (cand, args, LOOKUP_NORMAL);
}
- /* This is not really overloaded. */
+ /* This is not really overloaded. */
fn = OVL_CURRENT (fn);
return build_function_call (fn, args);
@@ -2727,25 +2974,22 @@ build_object_call (obj, args)
if (fns)
{
- tree base = BINFO_TYPE (TREE_PURPOSE (fns));
+ tree base = BINFO_TYPE (BASELINK_BINFO (fns));
mem_args = tree_cons (NULL_TREE, build_this (obj), args);
- for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
+ for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
- {
- candidates
- = add_template_candidate (candidates, fn, base, NULL_TREE,
- mem_args, NULL_TREE,
- LOOKUP_NORMAL, DEDUCE_CALL);
- }
+ add_template_candidate (&candidates, fn, base, NULL_TREE,
+ mem_args, NULL_TREE,
+ TYPE_BINFO (type),
+ TYPE_BINFO (type),
+ LOOKUP_NORMAL, DEDUCE_CALL);
else
- candidates = add_function_candidate
- (candidates, fn, base, mem_args, LOOKUP_NORMAL);
-
- if (candidates)
- candidates->basetype_path = TYPE_BINFO (type);
+ add_function_candidate
+ (&candidates, fn, base, mem_args, TYPE_BINFO (type),
+ TYPE_BINFO (type), LOOKUP_NORMAL);
}
}
@@ -2767,15 +3011,14 @@ build_object_call (obj, args)
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
- {
- candidates = add_template_conv_candidate (candidates,
- fn,
- obj,
- args,
- totype);
- }
+ add_template_conv_candidate
+ (&candidates, fn, obj, args, totype,
+ /*access_path=*/NULL_TREE,
+ /*conversion_path=*/NULL_TREE);
else
- candidates = add_conv_candidate (candidates, fn, obj, args);
+ add_conv_candidate (&candidates, fn, obj, args,
+ /*conversion_path=*/NULL_TREE,
+ /*access_path=*/NULL_TREE);
}
}
@@ -2826,23 +3069,27 @@ op_error (code, code2, arg1, arg2, arg3, problem)
switch (code)
{
case COND_EXPR:
- error ("%s for `%T ? %T : %T' operator", problem,
- error_type (arg1), error_type (arg2), error_type (arg3));
+ error ("%s for ternary 'operator?:' in '%E ? %E : %E'",
+ problem, arg1, arg2, arg3);
break;
+
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
- error ("%s for `%T %s' operator", problem, error_type (arg1), opname);
+ error ("%s for 'operator%s' in '%E%s'", problem, opname, arg1, opname);
break;
+
case ARRAY_REF:
- error ("%s for `%T [%T]' operator", problem,
- error_type (arg1), error_type (arg2));
+ error ("%s for 'operator[]' in '%E[%E]'", problem, arg1, arg2);
break;
+
default:
if (arg2)
- error ("%s for `%T %s %T' operator", problem,
- error_type (arg1), opname, error_type (arg2));
+ error ("%s for 'operator%s' in '%E %s %E'",
+ problem, opname, arg1, opname, arg2);
else
- error ("%s for `%s %T' operator", problem, opname, error_type (arg1));
+ error ("%s for 'operator%s' in '%s%E'",
+ problem, opname, opname, arg1);
+ break;
}
}
@@ -2857,6 +3104,7 @@ conditional_conversion (e1, e2)
tree t1 = non_reference (TREE_TYPE (e1));
tree t2 = non_reference (TREE_TYPE (e2));
tree conv;
+ bool good_base;
/* [expr.cond]
@@ -2885,10 +3133,9 @@ conditional_conversion (e1, e2)
changed to an rvalue of type T2 that still refers to the original
source class object (or the appropriate subobject thereof). */
if (CLASS_TYPE_P (t1) && CLASS_TYPE_P (t2)
- && same_or_base_type_p (TYPE_MAIN_VARIANT (t2),
- TYPE_MAIN_VARIANT (t1)))
+ && ((good_base = DERIVED_FROM_P (t2, t1)) || DERIVED_FROM_P (t1, t2)))
{
- if (at_least_as_qualified_p (t2, t1))
+ if (good_base && at_least_as_qualified_p (t2, t1))
{
conv = build1 (IDENTITY_CONV, t1, e1);
if (!same_type_p (TYPE_MAIN_VARIANT (t1),
@@ -2899,19 +3146,17 @@ conditional_conversion (e1, e2)
else
return NULL_TREE;
}
+ else
+ /* [expr.cond]
- /* [expr.cond]
-
- E1 can be converted to match E2 if E1 can be implicitly converted
- to the type that expression E2 would have if E2 were converted to
- an rvalue (or the type it has, if E2 is an rvalue). */
- return implicit_conversion (t2, t1, e1, LOOKUP_NORMAL);
+ Otherwise: E1 can be converted to match E2 if E1 can be implicitly
+ converted to the type that expression E2 would have if E2 were
+ converted to an rvalue (or the type it has, if E2 is an rvalue). */
+ return implicit_conversion (t2, t1, e1, LOOKUP_NORMAL);
}
/* Implement [expr.cond]. ARG1, ARG2, and ARG3 are the three
- arguments to the conditional expression. By the time this function
- is called, any suitable candidate functions are included in
- CANDIDATES. */
+ arguments to the conditional expression. */
tree
build_conditional_expr (arg1, arg2, arg3)
@@ -2984,7 +3229,7 @@ build_conditional_expr (arg1, arg2, arg3)
type of the other and is an rvalue.
--Both the second and the third operands have type void; the
- result is of type void and is an rvalue. */
+ result is of type void and is an rvalue. */
if ((TREE_CODE (arg2) == THROW_EXPR)
^ (TREE_CODE (arg3) == THROW_EXPR))
result_type = ((TREE_CODE (arg2) == THROW_EXPR)
@@ -3085,12 +3330,12 @@ build_conditional_expr (arg1, arg2, arg3)
args[0] = arg2;
args[1] = arg3;
args[2] = arg1;
- candidates = add_builtin_candidates (candidates,
- COND_EXPR,
- NOP_EXPR,
- ansi_opname (COND_EXPR),
- args,
- LOOKUP_NORMAL);
+ add_builtin_candidates (&candidates,
+ COND_EXPR,
+ NOP_EXPR,
+ ansi_opname (COND_EXPR),
+ args,
+ LOOKUP_NORMAL);
/* [expr.cond]
@@ -3138,18 +3383,10 @@ build_conditional_expr (arg1, arg2, arg3)
We use ocp_convert rather than build_user_type_conversion because the
latter returns NULL_TREE on failure, while the former gives an error. */
- if (IS_AGGR_TYPE (TREE_TYPE (arg2)) && real_lvalue_p (arg2))
- arg2 = ocp_convert (TREE_TYPE (arg2), arg2,
- CONV_IMPLICIT|CONV_FORCE_TEMP, LOOKUP_NORMAL);
- else
- arg2 = decay_conversion (arg2);
+ arg2 = force_rvalue (arg2);
arg2_type = TREE_TYPE (arg2);
- if (IS_AGGR_TYPE (TREE_TYPE (arg3)) && real_lvalue_p (arg3))
- arg3 = ocp_convert (TREE_TYPE (arg3), arg3,
- CONV_IMPLICIT|CONV_FORCE_TEMP, LOOKUP_NORMAL);
- else
- arg3 = decay_conversion (arg3);
+ arg3 = force_rvalue (arg3);
arg3_type = TREE_TYPE (arg3);
if (arg2 == error_mark_node || arg3 == error_mark_node)
@@ -3206,7 +3443,7 @@ build_conditional_expr (arg1, arg2, arg3)
qualification conversions (_conv.qual_) are performed to bring
them to a common type, whose cv-qualification shall match the
cv-qualification of either the second or the third operand.
- The result is of the common type. */
+ The result is of the common type. */
else if ((null_ptr_cst_p (arg2)
&& (TYPE_PTR_P (arg3_type) || TYPE_PTRMEM_P (arg3_type)
|| TYPE_PTRMEMFUNC_P (arg3_type)))
@@ -3255,8 +3492,8 @@ build_new_op (code, flags, arg1, arg2, arg3)
struct z_candidate *candidates = 0, *cand;
tree fns, mem_arglist = NULL_TREE, arglist, fnname;
enum tree_code code2 = NOP_EXPR;
- tree templates = NULL_TREE;
tree conv;
+ bool viable_candidates;
if (arg1 == error_mark_node
|| arg2 == error_mark_node
@@ -3283,6 +3520,10 @@ build_new_op (code, flags, arg1, arg2, arg3)
if (TREE_CODE (arg1) == OFFSET_REF)
arg1 = resolve_offset_ref (arg1);
arg1 = convert_from_reference (arg1);
+ if (CLASS_TYPE_P (TREE_TYPE (arg1))
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg1)))
+ /* Make sure the template type is instantiated now. */
+ instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)));
switch (code)
{
@@ -3290,7 +3531,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
case VEC_NEW_EXPR:
case VEC_DELETE_EXPR:
case DELETE_EXPR:
- /* Use build_op_new_call and build_op_delete_call instead. */
+ /* Use build_op_new_call and build_op_delete_call instead. */
abort ();
case CALL_EXPR:
@@ -3305,12 +3546,18 @@ build_new_op (code, flags, arg1, arg2, arg3)
if (TREE_CODE (arg2) == OFFSET_REF)
arg2 = resolve_offset_ref (arg2);
arg2 = convert_from_reference (arg2);
+ if (CLASS_TYPE_P (TREE_TYPE (arg2))
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg2)))
+ instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg2)));
}
if (arg3)
{
if (TREE_CODE (arg3) == OFFSET_REF)
arg3 = resolve_offset_ref (arg3);
arg3 = convert_from_reference (arg3);
+ if (CLASS_TYPE_P (TREE_TYPE (arg3))
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg3)))
+ instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg3)));
}
if (code == COND_EXPR)
@@ -3344,16 +3591,17 @@ build_new_op (code, flags, arg1, arg2, arg3)
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
- {
- templates = tree_cons (NULL_TREE, fn, templates);
- candidates
- = add_template_candidate (candidates, fn, NULL_TREE, NULL_TREE,
- arglist, TREE_TYPE (fnname),
- flags, DEDUCE_CALL);
- }
+ add_template_candidate (&candidates, fn, NULL_TREE, NULL_TREE,
+ arglist, TREE_TYPE (fnname),
+ /*access_path=*/NULL_TREE,
+ /*conversion_path=*/NULL_TREE,
+ flags, DEDUCE_CALL);
else
- candidates = add_function_candidate (candidates, fn, NULL_TREE,
- arglist, flags);
+ add_function_candidate (&candidates, fn, NULL_TREE,
+ arglist,
+ /*access_path=*/NULL_TREE,
+ /*conversion_path=*/NULL_TREE,
+ flags);
}
if (IS_AGGR_TYPE (TREE_TYPE (arg1)))
@@ -3367,12 +3615,14 @@ build_new_op (code, flags, arg1, arg2, arg3)
if (fns)
{
- tree basetype = BINFO_TYPE (TREE_PURPOSE (fns));
+ tree conversion_path = BASELINK_BINFO (fns);
+
mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
- for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
+ for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
tree this_arglist;
+ tree access_path = TYPE_BINFO (TREE_TYPE (arg1));
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
this_arglist = mem_arglist;
@@ -3380,20 +3630,17 @@ build_new_op (code, flags, arg1, arg2, arg3)
this_arglist = arglist;
if (TREE_CODE (fn) == TEMPLATE_DECL)
- {
- /* A member template. */
- templates = tree_cons (NULL_TREE, fn, templates);
- candidates
- = add_template_candidate (candidates, fn, basetype, NULL_TREE,
- this_arglist, TREE_TYPE (fnname),
- flags, DEDUCE_CALL);
- }
+ /* A member template. */
+ add_template_candidate (&candidates, fn,
+ BINFO_TYPE (conversion_path),
+ NULL_TREE,
+ this_arglist, TREE_TYPE (fnname),
+ access_path, conversion_path,
+ flags, DEDUCE_CALL);
else
- candidates = add_function_candidate
- (candidates, fn, basetype, this_arglist, flags);
-
- if (candidates)
- candidates->basetype_path = TYPE_BINFO (TREE_TYPE (arg1));
+ add_function_candidate
+ (&candidates, fn, BINFO_TYPE (conversion_path), this_arglist,
+ access_path, conversion_path, flags);
}
}
@@ -3417,11 +3664,28 @@ build_new_op (code, flags, arg1, arg2, arg3)
args[2] = NULL_TREE;
}
- candidates = add_builtin_candidates
- (candidates, code, code2, fnname, args, flags);
+ add_builtin_candidates (&candidates, code, code2, fnname, args, flags);
}
- if (! any_viable (candidates))
+ switch (code)
+ {
+ case COMPOUND_EXPR:
+ case ADDR_EXPR:
+ /* For these, the built-in candidates set is empty
+ [over.match.oper]/3. We don't want non-strict matches
+ because exact matches are always possible with built-in
+ operators. The built-in candidate set for COMPONENT_REF
+ would be empty too, but since there are no such built-in
+ operators, we accept non-strict matches for them. */
+ viable_candidates = any_strictly_viable (candidates);
+ break;
+
+ default:
+ viable_candidates = any_viable (candidates);
+ break;
+ }
+
+ if (! viable_candidates)
{
switch (code)
{
@@ -3656,10 +3920,10 @@ build_op_delete_call (code, addr, size, flags, placement)
tree alloc_fn;
tree call_expr;
- /* Find the allocation function that is being called. */
+ /* Find the allocation function that is being called. */
call_expr = placement;
/* Sometimes we have a COMPOUND_EXPR, rather than a simple
- CALL_EXPR. */
+ CALL_EXPR. */
while (TREE_CODE (call_expr) == COMPOUND_EXPR)
call_expr = TREE_OPERAND (call_expr, 1);
/* Extract the function. */
@@ -3698,7 +3962,7 @@ build_op_delete_call (code, addr, size, flags, placement)
/* Go through the `operator delete' functions looking for one
with a matching type. */
- for (fn = BASELINK_P (fns) ? TREE_VALUE (fns) : fns;
+ for (fn = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns;
fn;
fn = OVL_NEXT (fn))
{
@@ -3776,18 +4040,17 @@ enforce_access (basetype_path, decl)
return 1;
}
-/* Perform the conversions in CONVS on the expression EXPR.
- FN and ARGNUM are used for diagnostics. ARGNUM is zero based, -1
- indicates the `this' argument of a method. INNER is non-zero when
+/* Perform the conversions in CONVS on the expression EXPR. FN and
+ ARGNUM are used for diagnostics. ARGNUM is zero based, -1
+ indicates the `this' argument of a method. INNER is nonzero when
being called to continue a conversion chain. It is negative when a
- reference binding will be applied, positive otherwise. */
+ reference binding will be applied, positive otherwise. If
+ ISSUE_CONVERSION_WARNINGS is true, warnings about suspicious
+ conversions will be emitted if appropriate. */
static tree
-convert_like_real (convs, expr, fn, argnum, inner)
- tree convs, expr;
- tree fn;
- int argnum;
- int inner;
+convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,
+ bool issue_conversion_warnings)
{
int savew, savee;
@@ -3803,11 +4066,13 @@ convert_like_real (convs, expr, fn, argnum, inner)
{
if (TREE_CODE (t) == USER_CONV || !ICS_BAD_FLAG (t))
{
- expr = convert_like_real (t, expr, fn, argnum, 1);
+ expr = convert_like_real (t, expr, fn, argnum, 1,
+ /*issue_conversion_warnings=*/false);
break;
}
else if (TREE_CODE (t) == AMBIG_CONV)
- return convert_like_real (t, expr, fn, argnum, 1);
+ return convert_like_real (t, expr, fn, argnum, 1,
+ /*issue_conversion_warnings=*/false);
else if (TREE_CODE (t) == IDENTITY_CONV)
break;
}
@@ -3817,15 +4082,14 @@ convert_like_real (convs, expr, fn, argnum, inner)
return cp_convert (totype, expr);
}
- if (!inner)
+ if (issue_conversion_warnings)
expr = dubious_conversion_warnings
(totype, expr, "argument", fn, argnum);
switch (TREE_CODE (convs))
{
case USER_CONV:
{
- struct z_candidate *cand
- = WRAPPER_PTR (TREE_OPERAND (convs, 1));
+ struct z_candidate *cand = USER_CONV_CAND (convs);
tree convfn = cand->fn;
tree args;
@@ -3863,7 +4127,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
&& (inner >= 0 || !lvalue_p (expr)))
{
savew = warningcount, savee = errorcount;
- expr = build_new_method_call
+ expr = build_special_member_call
(NULL_TREE, complete_ctor_identifier,
build_tree_list (NULL_TREE, expr), TYPE_BINFO (totype),
/* Core issue 84, now a DR, says that we don't allow UDCs
@@ -3910,7 +4174,8 @@ convert_like_real (convs, expr, fn, argnum, inner)
};
expr = convert_like_real (TREE_OPERAND (convs, 0), expr, fn, argnum,
- TREE_CODE (convs) == REF_BIND ? -1 : 1);
+ TREE_CODE (convs) == REF_BIND ? -1 : 1,
+ /*issue_conversion_warnings=*/false);
if (expr == error_mark_node)
return error_mark_node;
@@ -3945,10 +4210,10 @@ convert_like_real (convs, expr, fn, argnum, inner)
type is the same class as, or a derived class of, the class of the
destination [is treated as direct-initialization]. [dcl.init] */
savew = warningcount, savee = errorcount;
- expr = build_new_method_call (NULL_TREE, complete_ctor_identifier,
- build_tree_list (NULL_TREE, expr),
- TYPE_BINFO (totype),
- LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING);
+ expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+ build_tree_list (NULL_TREE, expr),
+ TYPE_BINFO (totype),
+ LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING);
if (fn)
{
if (warningcount > savew)
@@ -3963,7 +4228,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
tree ref_type = totype;
/* If necessary, create a temporary. */
- if (NEED_TEMPORARY_P (convs) || !lvalue_p (expr))
+ if (NEED_TEMPORARY_P (convs) || !non_cast_lvalue_p (expr))
{
tree type = TREE_TYPE (TREE_OPERAND (convs, 0));
expr = build_target_expr_with_type (expr, type);
@@ -3981,9 +4246,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
expr = cp_convert (build_pointer_type (TREE_TYPE (ref_type)),
expr);
/* Convert the pointer to the desired reference type. */
- expr = build1 (NOP_EXPR, ref_type, expr);
-
- return expr;
+ return build_nop (ref_type, expr);
}
case LVALUE_CONV:
@@ -4001,6 +4264,22 @@ convert_like_real (convs, expr, fn, argnum, inner)
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
}
+/* Build a call to __builtin_trap which can be used in an expression. */
+
+static tree
+call_builtin_trap ()
+{
+ tree fn = get_identifier ("__builtin_trap");
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
+ else
+ abort ();
+
+ fn = build_call (fn, NULL_TREE);
+ fn = build (COMPOUND_EXPR, integer_type_node, fn, integer_zero_node);
+ return fn;
+}
+
/* ARG is being passed to a varargs function. Perform any conversions
required. Array/function to pointer decay must have already happened.
Return the converted value. */
@@ -4022,12 +4301,13 @@ convert_arg_to_ellipsis (arg)
if (arg != error_mark_node && ! pod_type_p (TREE_TYPE (arg)))
{
- /* Undefined behaviour [expr.call] 5.2.2/7. We used to just warn
+ /* Undefined behavior [expr.call] 5.2.2/7. We used to just warn
here and do a bitwise copy, but now cp_expr_size will abort if we
try to do that. */
- error ("cannot pass objects of non-POD type `%#T' through `...'",
- TREE_TYPE (arg));
- arg = error_mark_node;
+ warning ("cannot pass objects of non-POD type `%#T' through `...'; \
+call will abort at runtime",
+ TREE_TYPE (arg));
+ arg = call_builtin_trap ();
}
return arg;
@@ -4050,7 +4330,7 @@ build_x_va_arg (expr, type)
if (! pod_type_p (type))
{
- /* Undefined behaviour [expr.call] 5.2.2/7. */
+ /* Undefined behavior [expr.call] 5.2.2/7. */
warning ("cannot receive objects of non-POD type `%#T' through `...'",
type);
}
@@ -4058,24 +4338,27 @@ build_x_va_arg (expr, type)
return build_va_arg (expr, type);
}
-/* TYPE has been given to va_arg. Apply the default conversions which would
- have happened when passed via ellipsis. Return the promoted type, or
- NULL_TREE, if there is no change. */
+/* TYPE has been given to va_arg. Apply the default conversions which
+ would have happened when passed via ellipsis. Return the promoted
+ type, or the passed type if there is no change. */
tree
-convert_type_from_ellipsis (type)
+cxx_type_promotes_to (type)
tree type;
{
tree promote;
-
+
if (TREE_CODE (type) == ARRAY_TYPE)
- promote = build_pointer_type (TREE_TYPE (type));
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- promote = build_pointer_type (type);
- else
- promote = type_promotes_to (type);
+ return build_pointer_type (TREE_TYPE (type));
+
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ return build_pointer_type (type);
+
+ promote = type_promotes_to (type);
+ if (same_type_p (type, promote))
+ promote = type;
- return same_type_p (type, promote) ? NULL_TREE : promote;
+ return promote;
}
/* ARG is a default argument expression being passed to a parameter of
@@ -4128,15 +4411,48 @@ convert_default_arg (type, arg, fn, parmnum)
arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
"default argument", fn, parmnum);
- if (PROMOTE_PROTOTYPES
- && INTEGRAL_TYPE_P (type)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- arg = default_conversion (arg);
+ arg = convert_for_arg_passing (type, arg);
}
return arg;
}
+/* Returns the type which will really be used for passing an argument of
+ type TYPE. */
+
+tree
+type_passed_as (type)
+ tree type;
+{
+ /* Pass classes with copy ctors by invisible reference. */
+ if (TREE_ADDRESSABLE (type))
+ type = build_reference_type (type);
+ else if (PROMOTE_PROTOTYPES
+ && INTEGRAL_TYPE_P (type)
+ && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+ type = integer_type_node;
+
+ return type;
+}
+
+/* Actually perform the appropriate conversion. */
+
+tree
+convert_for_arg_passing (type, val)
+ tree type, val;
+{
+ if (val == error_mark_node)
+ ;
+ /* Pass classes with copy ctors by invisible reference. */
+ else if (TREE_ADDRESSABLE (type))
+ val = build1 (ADDR_EXPR, build_reference_type (type), val);
+ else if (PROMOTE_PROTOTYPES
+ && INTEGRAL_TYPE_P (type)
+ && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+ val = default_conversion (val);
+ return val;
+}
+
/* Subroutine of the various build_*_call functions. Overload resolution
has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a
@@ -4159,10 +4475,10 @@ build_over_call (cand, args, flags)
/* Give any warnings we noticed during overload resolution. */
if (cand->warnings)
for (val = cand->warnings; val; val = TREE_CHAIN (val))
- joust (cand, WRAPPER_PTR (TREE_VALUE (val)), 1);
+ joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);
if (DECL_FUNCTION_MEMBER_P (fn))
- enforce_access (cand->basetype_path, fn);
+ enforce_access (cand->access_path, fn);
if (args && TREE_CODE (args) != TREE_LIST)
args = build_tree_list (NULL_TREE, args);
@@ -4191,7 +4507,9 @@ build_over_call (cand, args, flags)
{
tree parmtype = TREE_VALUE (parm);
tree argtype = TREE_TYPE (TREE_VALUE (arg));
- tree t;
+ tree converted_arg;
+ tree base_binfo;
+
if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i)))
pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers",
TREE_TYPE (argtype), fn);
@@ -4203,10 +4521,22 @@ build_over_call (cand, args, flags)
So we can assume that anything passed as 'this' is non-null, and
optimize accordingly. */
my_friendly_assert (TREE_CODE (parmtype) == POINTER_TYPE, 19990811);
- t = lookup_base (TREE_TYPE (TREE_TYPE (TREE_VALUE (arg))),
- TREE_TYPE (parmtype), ba_ignore, NULL);
- t = build_base_path (PLUS_EXPR, TREE_VALUE (arg), t, 1);
- converted_args = tree_cons (NULL_TREE, t, converted_args);
+ /* Convert to the base in which the function was declared. */
+ my_friendly_assert (cand->conversion_path != NULL_TREE, 20020730);
+ converted_arg = build_base_path (PLUS_EXPR,
+ TREE_VALUE (arg),
+ cand->conversion_path,
+ 1);
+ /* If fn was found by a using declaration, the conversion path
+ will be to the derived class, not the base declaring fn. We
+ must convert from derived to base. */
+ base_binfo = lookup_base (TREE_TYPE (TREE_TYPE (converted_arg)),
+ TREE_TYPE (parmtype), ba_ignore, NULL);
+
+ converted_arg = build_base_path (PLUS_EXPR, converted_arg,
+ base_binfo, 1);
+
+ converted_args = tree_cons (NULL_TREE, converted_arg, converted_args);
parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg);
++i;
@@ -4222,10 +4552,7 @@ build_over_call (cand, args, flags)
val = convert_like_with_context
(conv, TREE_VALUE (arg), fn, i - is_method);
- if (PROMOTE_PROTOTYPES
- && INTEGRAL_TYPE_P (type)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- val = default_conversion (val);
+ val = convert_for_arg_passing (type, val);
converted_args = tree_cons (NULL_TREE, val, converted_args);
}
@@ -4296,20 +4623,13 @@ build_over_call (cand, args, flags)
temp or an INIT_EXPR otherwise. */
if (integer_zerop (TREE_VALUE (args)))
{
- if (! real_lvalue_p (arg))
+ if (TREE_CODE (arg) == TARGET_EXPR)
return arg;
else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
return build_target_expr_with_type (arg, DECL_CONTEXT (fn));
}
- else if ((!real_lvalue_p (arg)
- || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
- /* Empty classes have padding which can be hidden
- inside an (empty) base of the class. This must not
- be touched as it might overlay things. When the
- gcc core learns about empty classes, we can treat it
- like other classes. */
- && !(is_empty_class (DECL_CONTEXT (fn))
- && TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))))
+ else if (TREE_CODE (arg) == TARGET_EXPR
+ || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
{
tree address;
tree to = stabilize_reference
@@ -4331,24 +4651,7 @@ build_over_call (cand, args, flags)
(build_indirect_ref (TREE_VALUE (converted_args), 0));
arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
- if (is_empty_class (TREE_TYPE (to)))
- {
- TREE_USED (arg) = 1;
-
- val = build (COMPOUND_EXPR, DECL_CONTEXT (fn), arg, to);
- /* Even though the assignment may not actually result in any
- code being generated, we do not want to warn about the
- assignment having no effect. That would be confusing to
- users who may be performing the assignment as part of a
- generic algorithm, for example.
-
- Ideally, the notions of having side-effects and of being
- useless would be orthogonal. */
- TREE_SIDE_EFFECTS (val) = 1;
- TREE_NO_UNUSED_WARNING (val) = 1;
- }
- else
- val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
+ val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
return val;
}
@@ -4358,7 +4661,7 @@ build_over_call (cand, args, flags)
{
tree t, *p = &TREE_VALUE (converted_args);
tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)),
- DECL_VIRTUAL_CONTEXT (fn),
+ DECL_CONTEXT (fn),
ba_any, NULL);
my_friendly_assert (binfo && binfo != error_mark_node, 20010730);
@@ -4377,10 +4680,22 @@ build_over_call (cand, args, flags)
else
fn = build_addr_func (fn);
+ return build_cxx_call (fn, args, converted_args);
+}
+
+/* Build and return a call to FN, using the the CONVERTED_ARGS. ARGS
+ gives the original form of the arguments. This function performs
+ no overload resolution, conversion, or other high-level
+ operations. */
+
+tree
+build_cxx_call(tree fn, tree args, tree converted_args)
+{
+ tree fndecl;
+
/* Recognize certain built-in functions so we can make tree-codes
other than CALL_EXPR. We do this when it enables fold-const.c
to do something useful. */
-
if (TREE_CODE (fn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_BUILT_IN (TREE_OPERAND (fn, 0)))
@@ -4391,20 +4706,32 @@ build_over_call (cand, args, flags)
return exp;
}
- /* Some built-in function calls will be evaluated at
- compile-time in fold (). */
- fn = fold (build_call (fn, converted_args));
+ fn = build_call (fn, converted_args);
+
+ /* If this call might throw an exception, note that fact. */
+ fndecl = get_callee_fndecl (fn);
+ if ((!fndecl || !TREE_NOTHROW (fndecl))
+ && at_function_scope_p ()
+ && cfun)
+ cp_function_chain->can_throw = 1;
+
+ /* Some built-in function calls will be evaluated at compile-time in
+ fold (). */
+ fn = fold (fn);
+
if (VOID_TYPE_P (TREE_TYPE (fn)))
return fn;
+
fn = require_complete_type (fn);
if (fn == error_mark_node)
return error_mark_node;
+
if (IS_AGGR_TYPE (TREE_TYPE (fn)))
fn = build_cplus_new (TREE_TYPE (fn), fn);
return convert_from_reference (fn);
}
-static tree java_iface_lookup_fn;
+static GTY(()) tree java_iface_lookup_fn;
/* Make an expression which yields the address of the Java interface
method FN. This is achieved by generating a call to libjava's
@@ -4428,16 +4755,15 @@ build_java_interface_fn_ref (fn, instance)
java_iface_lookup_fn
= builtin_function ("_Jv_LookupInterfaceMethodIdx",
build_function_type (ptr_type_node, t),
- 0, NOT_BUILT_IN, NULL);
- ggc_add_tree_root (&java_iface_lookup_fn, 1);
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
}
/* Look up the pointer to the runtime java.lang.Class object for `instance'.
- This is the first entry in the vtable. */
+ This is the first entry in the vtable. */
klass_ref = build_vtbl_ref (build_indirect_ref (instance, 0),
integer_zero_node);
- /* Get the java.lang.Class pointer for the interface being called. */
+ /* Get the java.lang.Class pointer for the interface being called. */
iface = DECL_CONTEXT (fn);
iface_ref = lookup_field (iface, get_identifier ("class$"), 0, 0);
if (!iface_ref || TREE_CODE (iface_ref) != VAR_DECL
@@ -4449,7 +4775,7 @@ build_java_interface_fn_ref (fn, instance)
}
iface_ref = build1 (ADDR_EXPR, build_pointer_type (iface), iface_ref);
- /* Determine the itable index of FN. */
+ /* Determine the itable index of FN. */
i = 1;
for (method = TYPE_METHODS (iface); method; method = TREE_CHAIN (method))
{
@@ -4493,143 +4819,190 @@ in_charge_arg_for_name (name)
return NULL_TREE;
}
-static tree
-build_new_method_call (instance, name, args, basetype_path, flags)
- tree instance, name, args, basetype_path;
- int flags;
+/* Build a call to a constructor, destructor, or an assignment
+ operator for INSTANCE, an expression with class type. NAME
+ indicates the special member function to call; ARGS are the
+ arguments. BINFO indicates the base of INSTANCE that is to be
+ passed as the `this' parameter to the member function called.
+
+ FLAGS are the LOOKUP_* flags to use when processing the call.
+
+ If NAME indicates a complete object constructor, INSTANCE may be
+ NULL_TREE. In this case, the caller will call build_cplus_new to
+ store the newly constructed object into a VAR_DECL. */
+
+tree
+build_special_member_call (tree instance, tree name, tree args,
+ tree binfo, int flags)
+{
+ tree fns;
+ /* The type of the subobject to be constructed or destroyed. */
+ tree class_type;
+
+ my_friendly_assert (name == complete_ctor_identifier
+ || name == base_ctor_identifier
+ || name == complete_dtor_identifier
+ || name == base_dtor_identifier
+ || name == deleting_dtor_identifier
+ || name == ansi_assopname (NOP_EXPR),
+ 20020712);
+ my_friendly_assert (binfo != NULL_TREE, 20020712);
+
+ class_type = BINFO_TYPE (binfo);
+
+ /* Handle the special case where INSTANCE is NULL_TREE. */
+ if (name == complete_ctor_identifier && !instance)
+ {
+ instance = build_int_2 (0, 0);
+ TREE_TYPE (instance) = build_pointer_type (class_type);
+ instance = build1 (INDIRECT_REF, class_type, instance);
+ }
+ else if (name == complete_dtor_identifier
+ || name == base_dtor_identifier
+ || name == deleting_dtor_identifier)
+ my_friendly_assert (args == NULL_TREE, 20020712);
+
+ my_friendly_assert (instance != NULL_TREE, 20020712);
+
+ /* Resolve the name. */
+ if (!complete_type_or_else (BINFO_TYPE (binfo), NULL_TREE))
+ return error_mark_node;
+
+ fns = lookup_fnfields (binfo, name, 1);
+
+ /* When making a call to a constructor or destructor for a subobject
+ that uses virtual base classes, pass down a pointer to a VTT for
+ the subobject. */
+ if ((name == base_ctor_identifier
+ || name == base_dtor_identifier)
+ && TYPE_USES_VIRTUAL_BASECLASSES (class_type))
+ {
+ tree vtt;
+ tree sub_vtt;
+
+ /* If the current function is a complete object constructor
+ or destructor, then we fetch the VTT directly.
+ Otherwise, we look it up using the VTT we were given. */
+ vtt = TREE_CHAIN (CLASSTYPE_VTABLES (current_class_type));
+ vtt = decay_conversion (vtt);
+ vtt = build (COND_EXPR, TREE_TYPE (vtt),
+ build (EQ_EXPR, boolean_type_node,
+ current_in_charge_parm, integer_zero_node),
+ current_vtt_parm,
+ vtt);
+ if (TREE_VIA_VIRTUAL (binfo))
+ binfo = binfo_for_vbase (class_type, current_class_type);
+ my_friendly_assert (BINFO_SUBVTT_INDEX (binfo), 20010110);
+ sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt,
+ BINFO_SUBVTT_INDEX (binfo));
+
+ args = tree_cons (NULL_TREE, sub_vtt, args);
+ }
+
+ return build_new_method_call (instance, fns, args, binfo, flags);
+}
+
+/* Build a call to "INSTANCE.FN (ARGS)". */
+
+tree
+build_new_method_call (tree instance, tree fns, tree args,
+ tree conversion_path, int flags)
{
struct z_candidate *candidates = 0, *cand;
tree explicit_targs = NULL_TREE;
- tree basetype, mem_args = NULL_TREE, fns, instance_ptr;
- tree pretty_name;
+ tree basetype = NULL_TREE;
+ tree access_binfo;
+ tree optype;
+ tree mem_args = NULL_TREE, instance_ptr;
+ tree name, pretty_name;
tree user_args;
- tree templates = NULL_TREE;
tree call;
int template_only = 0;
- if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
- {
- explicit_targs = TREE_OPERAND (name, 1);
- name = TREE_OPERAND (name, 0);
- if (DECL_P (name))
- name = DECL_NAME (name);
- else
- {
- if (TREE_CODE (name) == COMPONENT_REF)
- name = TREE_OPERAND (name, 1);
- if (TREE_CODE (name) == OVERLOAD)
- name = DECL_NAME (OVL_CURRENT (name));
- }
+ my_friendly_assert (instance != NULL_TREE, 20020729);
- template_only = 1;
- }
+ if (instance == error_mark_node || fns == error_mark_node
+ || args == error_mark_node)
+ return error_mark_node;
+ /* Process the argument list. */
user_args = 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 = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
+ instance_ptr = build_this (instance);
+
+ if (!BASELINK_P (fns))
{
- 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 = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
+ call = build_field_call (instance_ptr, fns, args);
+ if (call)
+ return call;
+ error ("call to non-function `%D'", fns);
+ return error_mark_node;
+ }
- /* XXX this should be handled before we get here. */
- if (! IS_AGGR_TYPE (basetype))
- {
- if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node)
- error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
- name, instance, basetype);
+ if (!conversion_path)
+ conversion_path = BASELINK_BINFO (fns);
+ access_binfo = BASELINK_ACCESS_BINFO (fns);
+ optype = BASELINK_OPTYPE (fns);
+ fns = BASELINK_FUNCTIONS (fns);
- return error_mark_node;
- }
+ if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
+ {
+ explicit_targs = TREE_OPERAND (fns, 1);
+ fns = TREE_OPERAND (fns, 0);
+ template_only = 1;
}
- if (basetype_path == NULL_TREE)
- basetype_path = TYPE_BINFO (basetype);
+ my_friendly_assert (TREE_CODE (fns) == FUNCTION_DECL
+ || TREE_CODE (fns) == TEMPLATE_DECL
+ || TREE_CODE (fns) == OVERLOAD,
+ 20020712);
- if (instance)
+ /* XXX this should be handled before we get here. */
+ if (! IS_AGGR_TYPE (basetype))
{
- instance_ptr = build_this (instance);
+ if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node)
+ error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
+ fns, instance, basetype);
- if (! template_only)
- {
- /* 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);
+ return error_mark_node;
}
- /* Callers should explicitly indicate whether they want to construct
- the complete object or just the part without virtual bases. */
- my_friendly_assert (name != ctor_identifier, 20000408);
- /* Similarly for destructors. */
- my_friendly_assert (name != dtor_identifier, 20000408);
+ name = DECL_NAME (get_first_fn (fns));
if (IDENTIFIER_CTOR_OR_DTOR_P (name))
{
- int constructor_p;
-
- constructor_p = (name == complete_ctor_identifier
- || name == base_ctor_identifier);
- pretty_name = (constructor_p
- ? constructor_name (basetype) : dtor_identifier);
-
- /* If we're a call to a constructor or destructor for a
- subobject that uses virtual base classes, then we need to
- pass down a pointer to a VTT for the subobject. */
- if ((name == base_ctor_identifier
- || name == base_dtor_identifier)
- && TYPE_USES_VIRTUAL_BASECLASSES (basetype))
- {
- tree vtt;
- tree sub_vtt;
- tree basebinfo = basetype_path;
-
- /* If the current function is a complete object constructor
- or destructor, then we fetch the VTT directly.
- Otherwise, we look it up using the VTT we were given. */
- vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type));
- vtt = decay_conversion (vtt);
- vtt = build (COND_EXPR, TREE_TYPE (vtt),
- build (EQ_EXPR, boolean_type_node,
- current_in_charge_parm, integer_zero_node),
- current_vtt_parm,
- vtt);
- if (TREE_VIA_VIRTUAL (basebinfo))
- basebinfo = binfo_for_vbase (basetype, current_class_type);
- my_friendly_assert (BINFO_SUBVTT_INDEX (basebinfo), 20010110);
- sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt,
- BINFO_SUBVTT_INDEX (basebinfo));
-
- args = tree_cons (NULL_TREE, sub_vtt, args);
- }
+ /* Callers should explicitly indicate whether they want to construct
+ the complete object or just the part without virtual bases. */
+ my_friendly_assert (name != ctor_identifier, 20000408);
+ /* Similarly for destructors. */
+ my_friendly_assert (name != dtor_identifier, 20000408);
+
+ if (name == complete_ctor_identifier
+ || name == base_ctor_identifier)
+ pretty_name = constructor_name (basetype);
+ else
+ pretty_name = dtor_identifier;
}
else
pretty_name = name;
- fns = lookup_fnfields (basetype_path, name, 1);
-
- if (fns == error_mark_node)
- return error_mark_node;
if (fns)
{
- tree base = BINFO_TYPE (TREE_PURPOSE (fns));
- tree fn = TREE_VALUE (fns);
+ tree fn;
+ tree class_type = (conversion_path
+ ? BINFO_TYPE (conversion_path)
+ : NULL_TREE);
+
mem_args = tree_cons (NULL_TREE, instance_ptr, args);
- for (; fn; fn = OVL_NEXT (fn))
+ for (fn = fns; fn; fn = OVL_NEXT (fn))
{
tree t = OVL_CURRENT (fn);
tree this_arglist;
@@ -4645,20 +5018,22 @@ build_new_method_call (instance, name, args, basetype_path, flags)
this_arglist = args;
if (TREE_CODE (t) == TEMPLATE_DECL)
- {
- /* A member template. */
- templates = tree_cons (NULL_TREE, t, templates);
- candidates =
- add_template_candidate (candidates, t, base, explicit_targs,
- this_arglist,
- TREE_TYPE (name), flags, DEDUCE_CALL);
- }
+ /* A member template. */
+ add_template_candidate (&candidates, t,
+ class_type,
+ explicit_targs,
+ this_arglist, optype,
+ access_binfo,
+ conversion_path,
+ flags,
+ DEDUCE_CALL);
else if (! template_only)
- candidates = add_function_candidate (candidates, t, base,
- this_arglist, flags);
-
- if (candidates)
- candidates->basetype_path = basetype_path;
+ add_function_candidate (&candidates, t,
+ class_type,
+ this_arglist,
+ access_binfo,
+ conversion_path,
+ flags);
}
}
@@ -4668,7 +5043,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE;
if (!COMPLETE_TYPE_P (basetype))
- incomplete_type_error (instance_ptr, basetype);
+ cxx_incomplete_type_error (instance_ptr, basetype);
else
error ("no matching function for call to `%T::%D(%A)%#V'",
basetype, pretty_name, user_args,
@@ -4713,16 +5088,16 @@ build_new_method_call (instance, name, args, basetype_path, flags)
else
{
call = build_over_call (cand, args, flags);
- /* Do evaluate the object parameter in a call to a static member
- function. */
- if (TREE_SIDE_EFFECTS (instance))
+ /* In an expression of the form `a->f()' where `f' turns out to
+ be a static member function, `a' is none-the-less evaluated. */
+ if (instance && TREE_SIDE_EFFECTS (instance))
call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
}
return call;
}
-/* Returns non-zero iff standard conversion sequence ICS1 is a proper
+/* Returns nonzero iff standard conversion sequence ICS1 is a proper
subsequence of ICS2. */
static int
@@ -4762,7 +5137,7 @@ is_subseq (ics1, ics2)
}
}
-/* Returns non-zero iff DERIVED is derived from BASE. The inputs may
+/* Returns nonzero iff DERIVED is derived from BASE. The inputs may
be any _TYPE nodes. */
int
@@ -4860,7 +5235,7 @@ compare_ics (ics1, ics2)
tree deref_to_type2 = NULL_TREE;
int rank1, rank2;
- /* REF_BINDING is non-zero if the result of the conversion sequence
+ /* REF_BINDING is nonzero if the result of the conversion sequence
is a reference type. In that case TARGET_TYPE is the
type referred to by the reference. */
tree target_type1;
@@ -5206,25 +5581,10 @@ add_warning (winner, loser)
struct z_candidate *winner, *loser;
{
winner->warnings = tree_cons (NULL_TREE,
- build_ptr_wrapper (loser),
+ build_zc_wrapper (loser),
winner->warnings);
}
-/* Returns true iff functions are equivalent. Equivalent functions are
- not '==' only if one is a function-local extern function or if
- both are extern "C". */
-
-static inline int
-equal_functions (fn1, fn2)
- tree fn1;
- tree fn2;
-{
- if (DECL_LOCAL_FUNCTION_P (fn1) || DECL_LOCAL_FUNCTION_P (fn2)
- || DECL_EXTERN_C_FUNCTION_P (fn1))
- return decls_match (fn1, fn2);
- return fn1 == fn2;
-}
-
/* Compare two candidates for overloading as described in
[over.match.best]. Return values:
@@ -5359,7 +5719,7 @@ joust (cand1, cand2, warn)
&& TREE_CODE (convn) == QUAL_CONV)
/* Don't complain about `operator char *()' beating
`operator const char *() const'. */;
- else if (warn)
+ else if (warn && warn_conversion)
{
tree source = source_type (TREE_VEC_ELT (w->convs, 0));
if (! DECL_CONSTRUCTOR_P (w->fn))
@@ -5488,11 +5848,9 @@ tweak:
if (winner)
{
if (warn)
- {
- pedwarn ("choosing `%D' over `%D'", w->fn, l->fn);
- pedwarn (
-" because worst conversion for the former is better than worst conversion for the latter");
- }
+ pedwarn ("ISO C++ says that `%D' and `%D' are ambiguous \
+even though the worst conversion for the former is better than the worst \
+conversion for the latter", w->fn, l->fn);
else
add_warning (w, l);
return winner;
@@ -5559,7 +5917,7 @@ tourney (candidates)
return champ;
}
-/* Returns non-zero if things of type FROM can be converted to TO. */
+/* Returns nonzero if things of type FROM can be converted to TO. */
int
can_convert (to, from)
@@ -5568,7 +5926,7 @@ can_convert (to, from)
return can_convert_arg (to, from, NULL_TREE);
}
-/* Returns non-zero if ARG (of type FROM) can be converted to TO. */
+/* Returns nonzero if ARG (of type FROM) can be converted to TO. */
int
can_convert_arg (to, from, arg)
@@ -5614,17 +5972,81 @@ perform_implicit_conversion (type, expr)
return convert_like (conv, expr);
}
+/* Convert EXPR to TYPE (as a direct-initialization) if that is
+ permitted. If the conversion is valid, the converted expression is
+ returned. Otherwise, NULL_TREE is returned. */
+
+tree
+perform_direct_initialization_if_possible (tree type, tree expr)
+{
+ tree conv;
+
+ if (type == error_mark_node || error_operand_p (expr))
+ return error_mark_node;
+ conv = implicit_conversion (type, TREE_TYPE (expr), expr,
+ LOOKUP_NORMAL);
+ if (!conv || ICS_BAD_FLAG (conv))
+ return NULL_TREE;
+ return convert_like_real (conv, expr, NULL_TREE, 0, 0,
+ /*issue_conversion_warnings=*/false);
+}
+
+/* DECL is a VAR_DECL whose type is a REFERENCE_TYPE. The reference
+ is being bound to a temporary. Create and return a new VAR_DECL
+ with the indicated TYPE; this variable will store the value to
+ which the reference is bound. */
+
+tree
+make_temporary_var_for_ref_to_temp (tree decl, tree type)
+{
+ tree var;
+
+ /* Create the variable. */
+ var = build_decl (VAR_DECL, NULL_TREE, type);
+ DECL_ARTIFICIAL (var) = 1;
+ TREE_USED (var) = 1;
+
+ /* Register the variable. */
+ if (TREE_STATIC (decl))
+ {
+ /* Namespace-scope or local static; give it a mangled name. */
+ tree name;
+
+ TREE_STATIC (var) = 1;
+ name = mangle_ref_init_variable (decl);
+ DECL_NAME (var) = name;
+ SET_DECL_ASSEMBLER_NAME (var, name);
+ var = pushdecl_top_level (var);
+ }
+ else
+ {
+ /* Create a new cleanup level if necessary. */
+ maybe_push_cleanup_level (type);
+ /* Don't push unnamed temps. Do set DECL_CONTEXT, though. */
+ DECL_CONTEXT (var) = current_function_decl;
+ }
+
+ return var;
+}
+
/* Convert EXPR to the indicated reference TYPE, in a way suitable for
- initializing a variable of that TYPE. Return the converted
- expression. */
+ initializing a variable of that TYPE. If DECL is non-NULL, it is
+ the VAR_DECL being initialized with the EXPR. (In that case, the
+ type of DECL will be TYPE.)
+
+ Return the converted expression. */
tree
-initialize_reference (type, expr)
+initialize_reference (type, expr, decl)
tree type;
tree expr;
+ tree decl;
{
tree conv;
+ if (type == error_mark_node || error_operand_p (expr))
+ return error_mark_node;
+
conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL);
if (!conv || ICS_BAD_FLAG (conv))
{
@@ -5632,5 +6054,101 @@ initialize_reference (type, expr)
return error_mark_node;
}
+ /* If DECL is non-NULL, then this special rule applies:
+
+ [class.temporary]
+
+ The temporary to which the reference is bound or the temporary
+ that is the complete object to which the reference is bound
+ persists for the lifetime of the reference.
+
+ The temporaries created during the evaluation of the expression
+ initializing the reference, except the temporary to which the
+ reference is bound, are destroyed at the end of the
+ full-expression in which they are created.
+
+ In that case, we store the converted expression into a new
+ VAR_DECL in a new scope.
+
+ However, we want to be careful not to create temporaries when
+ they are not required. For example, given:
+
+ struct B {};
+ struct D : public B {};
+ D f();
+ const B& b = f();
+
+ there is no need to copy the return value from "f"; we can just
+ extend its lifetime. Similarly, given:
+
+ struct S {};
+ struct T { operator S(); };
+ T t;
+ const S& s = t;
+
+ we can extend the lifetime of the return value of the conversion
+ operator. */
+ my_friendly_assert (TREE_CODE (conv) == REF_BIND, 20030302);
+ if (decl)
+ {
+ tree var;
+ tree base_conv_type;
+
+ /* Skip over the REF_BIND. */
+ conv = TREE_OPERAND (conv, 0);
+ /* If the next conversion is a BASE_CONV, skip that too -- but
+ remember that the conversion was required. */
+ if (TREE_CODE (conv) == BASE_CONV && !NEED_TEMPORARY_P (conv))
+ {
+ base_conv_type = TREE_TYPE (conv);
+ conv = TREE_OPERAND (conv, 0);
+ }
+ else
+ base_conv_type = NULL_TREE;
+ /* Perform the remainder of the conversion. */
+ expr = convert_like (conv, expr);
+ if (!real_non_cast_lvalue_p (expr))
+ {
+ tree init;
+ tree type;
+
+ /* Create the temporary variable. */
+ type = TREE_TYPE (expr);
+ var = make_temporary_var_for_ref_to_temp (decl, type);
+ layout_decl (var, 0);
+ if (at_function_scope_p ())
+ {
+ tree cleanup;
+
+ add_decl_stmt (var);
+ cleanup = cxx_maybe_build_cleanup (var);
+ if (cleanup)
+ finish_decl_cleanup (var, cleanup);
+ }
+ else
+ {
+ rest_of_decl_compilation (var, NULL, /*toplev=*/1, at_eof);
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ static_aggregates = tree_cons (NULL_TREE, var,
+ static_aggregates);
+ }
+ init = build (INIT_EXPR, type, var, expr);
+ /* Use its address to initialize the reference variable. */
+ expr = build_address (var);
+ expr = build (COMPOUND_EXPR, TREE_TYPE (expr), init, expr);
+ }
+ else
+ /* Take the address of EXPR. */
+ expr = build_unary_op (ADDR_EXPR, expr, 0);
+ /* If a BASE_CONV was required, perform it now. */
+ if (base_conv_type)
+ expr = (perform_implicit_conversion
+ (build_pointer_type (base_conv_type), expr));
+ return build_nop (type, expr);
+ }
+
+ /* Perform the conversion. */
return convert_like (conv, expr);
}
+
+#include "gt-cp-call.h"
diff --git a/contrib/gcc/cp/cfns.gperf b/contrib/gcc/cp/cfns.gperf
index 0d1e71b..e0e9f23 100644
--- a/contrib/gcc/cp/cfns.gperf
+++ b/contrib/gcc/cp/cfns.gperf
@@ -16,9 +16,9 @@ const char * libc_name_p PARAMS ((const char *, unsigned int));
# exception, unless it calls a program-supplied function that
# throws an exception.
#
-# bsearch and qsort are commented out because they can call such functions.
+# Specific functions are commented out for the reason noted in each case.
#
-abort
+# abort -- synchronous exception from SIGABRT handler
abs
acos
asctime
@@ -29,7 +29,7 @@ atexit
atof
atoi
atol
-#bsearch
+#bsearch -- calls user function which may throw exception
btowc
calloc
ceil
@@ -43,41 +43,41 @@ div
exit
exp
fabs
-fclose
+#fclose -- POSIX thread cancellation point
feof
ferror
-fflush
-fgetc
-fgetpos
-fgets
-fgetwc
-fgetws
+#fflush -- POSIX thread cancellation point
+#fgetc -- POSIX thread cancellation point
+#fgetpos -- POSIX thread cancellation point
+#fgets -- POSIX thread cancellation point
+#fgetwc -- POSIX thread cancellation point
+#fgetws -- POSIX thread cancellation point
floor
fmod
-fopen
-fprintf
-fputc
-fputs
-fputwc
-fputws
-fread
+#fopen -- POSIX thread cancellation point
+#fprintf -- POSIX thread cancellation point
+#fputc -- POSIX thread cancellation point
+#fputs -- POSIX thread cancellation point
+#fputwc -- POSIX thread cancellation point
+#fputws -- POSIX thread cancellation point
+#fread -- POSIX thread cancellation point
free
-freopen
+#freopen -- POSIX thread cancellation point
frexp
-fscanf
+#fscanf -- POSIX thread cancellation point
fseek
-fsetpos
-ftell
+#fsetpos -- POSIX thread cancellation point
+#ftell -- POSIX thread cancellation point
fwide
-fwprintf
-fwrite
-fwscanf
-getc
-getchar
+#fwprintf -- POSIX thread cancellation point
+#fwrite -- POSIX thread cancellation point
+#fwscanf -- POSIX thread cancellation point
+#getc -- POSIX thread cancellation point
+#getchar -- POSIX thread cancellation point
getenv
-gets
-getwc
-getwchar
+#gets -- POSIX thread cancellation point
+#getwc -- POSIX thread cancellation point
+#getwchar -- POSIX thread cancellation point
gmtime
isalnum
isalpha
@@ -125,22 +125,22 @@ memmove
memset
mktime
modf
-perror
+#perror -- POSIX thread cancellation point
pow
-printf
-putc
-putchar
-puts
-putwc
-putwchar
-#qsort
-raise
+#printf -- POSIX thread cancellation point
+#putc -- POSIX thread cancellation point
+#putchar -- POSIX thread cancellation point
+#puts -- POSIX thread cancellation point
+#putwc -- POSIX thread cancellation point
+#putwchar -- POSIX thread cancellation point
+#qsort -- calls user function which may throw exception
+#raise -- synchronous exception from signal handler
rand
realloc
-remove
-rename
-rewind
-scanf
+#remove -- POSIX thread cancellation point
+#rename -- POSIX thread cancellation point
+#rewind -- POSIX thread cancellation point
+#scanf -- POSIX thread cancellation point
setbuf
setlocale
setvbuf
@@ -157,7 +157,7 @@ strcmp
strcoll
strcpy
strcspn
-strerror
+#strerror -- POSIX thread cancellation point
strftime
strlen
strncat
@@ -174,25 +174,25 @@ strtoul
strxfrm
swprintf
swscanf
-system
+#system -- POSIX thread cancellation point
tan
tanh
time
-tmpfile
-tmpnam
+#tmpfile -- POSIX thread cancellation point
+#tmpnam -- POSIX thread cancellation point
tolower
toupper
towctrans
towlower
towupper
-ungetc
-ungetwc
-vfprintf
-vfwprintf
-vprintf
+#ungetc -- POSIX thread cancellation point
+#ungetwc -- POSIX thread cancellation point
+#vfprintf -- POSIX thread cancellation point
+#vfwprintf -- POSIX thread cancellation point
+#vprintf -- POSIX thread cancellation point
vsprintf
vswprintf
-vwprintf
+#vwprintf -- POSIX thread cancellation point
wcrtomb
wcscat
wcschr
@@ -225,5 +225,5 @@ wmemcmp
wmemcpy
wmemmove
wmemset
-wprintf
-wscanf
+#wprintf -- POSIX thread cancellation point
+#wscanf -- POSIX thread cancellation point
diff --git a/contrib/gcc/cp/class.c b/contrib/gcc/cp/class.c
index 2ac4e30..82eede5 100644
--- a/contrib/gcc/cp/class.c
+++ b/contrib/gcc/cp/class.c
@@ -35,10 +35,6 @@ Boston, MA 02111-1307, USA. */
#include "lex.h"
#include "target.h"
-#include "obstack.h"
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
/* The number of nested classes being processed. If we are not in the
scope of any class, this is zero. */
@@ -91,6 +87,9 @@ typedef struct vtbl_init_data_s
/* Nonzero if we are building the initializer for a construction
vtable. */
int ctor_vtbl_p;
+ /* True when adding vcall offset entries to the vtable. False when
+ merely computing the indices. */
+ bool generate_vcall_entries;
} vtbl_init_data;
/* The type of a function passed to walk_subobject_offsets. */
@@ -107,7 +106,6 @@ varray_type local_classes;
static tree get_vfield_name PARAMS ((tree));
static void finish_struct_anon PARAMS ((tree));
-static tree build_vtable_entry PARAMS ((tree, tree, tree));
static tree get_vtable_name PARAMS ((tree));
static tree get_basefndecls PARAMS ((tree, tree));
static int build_primary_vtable PARAMS ((tree, tree));
@@ -119,16 +117,15 @@ static void delete_duplicate_fields PARAMS ((tree));
static void finish_struct_bits PARAMS ((tree));
static int alter_access PARAMS ((tree, tree, tree));
static void handle_using_decl PARAMS ((tree, tree));
-static int strictly_overrides PARAMS ((tree, tree));
static void check_for_override PARAMS ((tree, tree));
static tree dfs_modify_vtables PARAMS ((tree, void *));
-static tree modify_all_vtables PARAMS ((tree, int *, tree));
-static void determine_primary_base PARAMS ((tree, int *));
+static tree modify_all_vtables PARAMS ((tree, tree));
+static void determine_primary_base PARAMS ((tree));
static void finish_struct_methods PARAMS ((tree));
static void maybe_warn_about_overly_private_class PARAMS ((tree));
static int field_decl_cmp PARAMS ((const tree *, const tree *));
static int method_name_cmp PARAMS ((const tree *, const tree *));
-static tree add_implicitly_declared_members PARAMS ((tree, int, int, int));
+static void add_implicitly_declared_members PARAMS ((tree, int, int, int));
static tree fixed_type_or_null PARAMS ((tree, int *, int *));
static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
int, int, tree));
@@ -138,29 +135,28 @@ static tree build_vtbl_initializer PARAMS ((tree, tree, tree, tree, int *));
static int count_fields PARAMS ((tree));
static int add_fields_to_vec PARAMS ((tree, tree, int));
static void check_bitfield_decl PARAMS ((tree));
-static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
-static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *,
- int *));
-static bool build_base_field PARAMS ((record_layout_info, tree, int *,
- splay_tree, tree));
-static bool build_base_fields PARAMS ((record_layout_info, int *,
- splay_tree, tree));
+static void check_field_decl (tree, tree, int *, int *, int *, int *);
+static void check_field_decls (tree, tree *, int *, int *, int *);
+static tree *build_base_field (record_layout_info, tree, splay_tree, tree *);
+static void build_base_fields (record_layout_info, splay_tree, tree *);
static void check_methods PARAMS ((tree));
static void remove_zero_width_bit_fields PARAMS ((tree));
static void check_bases PARAMS ((tree, int *, int *, int *));
-static void check_bases_and_members PARAMS ((tree, int *));
-static tree create_vtable_ptr PARAMS ((tree, int *, int *, tree *));
-static void layout_class_type PARAMS ((tree, int *, int *, tree *));
+static void check_bases_and_members (tree);
+static tree create_vtable_ptr (tree, tree *);
+static void include_empty_classes (record_layout_info);
+static void layout_class_type (tree, tree *);
static void fixup_pending_inline PARAMS ((tree));
static void fixup_inline_methods PARAMS ((tree));
-static void set_primary_base PARAMS ((tree, tree, int *));
+static void set_primary_base PARAMS ((tree, tree));
static void propagate_binfo_offsets PARAMS ((tree, tree, tree));
-static void layout_virtual_bases PARAMS ((tree, splay_tree));
+static void layout_virtual_bases (record_layout_info, splay_tree);
static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *));
static void add_vcall_offset_vtbl_entries_1 PARAMS ((tree, vtbl_init_data *));
static void build_vcall_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
+static void add_vcall_offset (tree, tree, vtbl_init_data *);
static void layout_vtable_decl PARAMS ((tree, int));
static tree dfs_find_final_overrider PARAMS ((tree, void *));
static tree find_final_overrider PARAMS ((tree, tree, tree));
@@ -175,14 +171,12 @@ static tree build_vtable PARAMS ((tree, tree, tree));
static void initialize_vtable PARAMS ((tree, tree));
static void initialize_array PARAMS ((tree, tree));
static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
- tree, tree,
- splay_tree, tree));
-static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
+ tree, tree, splay_tree));
+static tree end_of_class PARAMS ((tree, int));
static bool layout_empty_base PARAMS ((tree, tree, splay_tree, tree));
static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
tree));
-static void set_vindex PARAMS ((tree, int *));
static void build_rtti_vtbl_entries PARAMS ((tree, vtbl_init_data *));
static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
vtbl_init_data *));
@@ -212,8 +206,14 @@ static void record_subobject_offsets PARAMS ((tree, tree, splay_tree, int));
static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int));
static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
splay_tree_key k2));
-static void warn_about_ambiguous_direct_bases PARAMS ((tree));
+static void warn_about_ambiguous_bases PARAMS ((tree));
static bool type_requires_array_cookie PARAMS ((tree));
+static bool contains_empty_class_p (tree);
+static tree dfs_base_derived_from (tree, void *);
+static bool base_derived_from (tree, tree);
+static int empty_base_at_nonzero_offset_p (tree, tree, splay_tree);
+static tree end_of_base (tree);
+static tree get_vcall_index (tree, tree);
/* Macros for dfs walking during vtt construction. See
dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
@@ -288,13 +288,15 @@ build_base_path (code, expr, binfo, nonnull)
return error_mark_node;
}
+ if (!want_pointer)
+ /* This must happen before the call to save_expr. */
+ expr = build_unary_op (ADDR_EXPR, expr, 0);
+
fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
if (fixed_type_p <= 0 && TREE_SIDE_EFFECTS (expr))
expr = save_expr (expr);
- if (!want_pointer)
- expr = build_unary_op (ADDR_EXPR, expr, 0);
- else if (!nonnull)
+ if (want_pointer && !nonnull)
null_test = build (EQ_EXPR, boolean_type_node, expr, integer_zero_node);
offset = BINFO_OFFSET (binfo);
@@ -304,8 +306,27 @@ build_base_path (code, expr, binfo, nonnull)
/* Going via virtual base V_BINFO. We need the static offset
from V_BINFO to BINFO, and the dynamic offset from D_BINFO to
V_BINFO. That offset is an entry in D_BINFO's vtable. */
- tree v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
- TREE_TYPE (TREE_TYPE (expr)));
+ tree v_offset;
+
+ if (fixed_type_p < 0 && in_base_initializer)
+ {
+ /* In a base member initializer, we cannot rely on
+ the vtable being set up. We have to use the vtt_parm. */
+ tree derived = v_binfo;
+
+ while (BINFO_INHERITANCE_CHAIN (derived))
+ derived = BINFO_INHERITANCE_CHAIN (derived);
+
+ v_offset = build (PLUS_EXPR, TREE_TYPE (current_vtt_parm),
+ current_vtt_parm, BINFO_VPTR_INDEX (derived));
+
+ v_offset = build1 (INDIRECT_REF,
+ TREE_TYPE (TYPE_VFIELD (BINFO_TYPE (derived))),
+ v_offset);
+ }
+ else
+ v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
+ TREE_TYPE (TREE_TYPE (expr)));
v_binfo = binfo_for_vbase (BINFO_TYPE (v_binfo), BINFO_TYPE (d_binfo));
@@ -315,7 +336,8 @@ build_base_path (code, expr, binfo, nonnull)
build_pointer_type (ptrdiff_type_node),
v_offset);
v_offset = build_indirect_ref (v_offset, NULL);
-
+ TREE_CONSTANT (v_offset) = 1;
+
offset = cp_convert (ptrdiff_type_node,
size_diffop (offset, BINFO_OFFSET (v_binfo)));
@@ -361,6 +383,24 @@ build_base_path (code, expr, binfo, nonnull)
return expr;
}
+/* Convert OBJECT to the base TYPE. If CHECK_ACCESS is true, an error
+ message is emitted if TYPE is inaccessible. OBJECT is assumed to
+ be non-NULL. */
+
+tree
+convert_to_base (tree object, tree type, bool check_access)
+{
+ tree binfo;
+
+ binfo = lookup_base (TREE_TYPE (object), type,
+ check_access ? ba_check : ba_ignore,
+ NULL);
+ if (!binfo || binfo == error_mark_node)
+ return error_mark_node;
+
+ return build_base_path (PLUS_EXPR, object, binfo, /*nonnull=*/1);
+}
+
/* Virtual function things. */
@@ -400,75 +440,36 @@ static tree
build_vtbl_ref_1 (instance, idx)
tree instance, idx;
{
- tree vtbl, aref;
- tree basetype = TREE_TYPE (instance);
+ tree aref;
+ tree vtbl = NULL_TREE;
+
+ /* Try to figure out what a reference refers to, and
+ access its virtual function table directly. */
+
+ int cdtorp = 0;
+ tree fixed_type = fixed_type_or_null (instance, NULL, &cdtorp);
+ tree basetype = TREE_TYPE (instance);
if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype);
- if (instance == current_class_ref)
- vtbl = build_vfield_ref (instance, basetype);
- else
+ if (fixed_type && !cdtorp)
{
- if (optimize)
- {
- /* Try to figure out what a reference refers to, and
- access its virtual function table directly. */
- tree ref = NULL_TREE;
-
- if (TREE_CODE (instance) == INDIRECT_REF
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (instance, 0))) == REFERENCE_TYPE)
- ref = TREE_OPERAND (instance, 0);
- else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
- ref = instance;
-
- if (ref && TREE_CODE (ref) == VAR_DECL
- && DECL_INITIAL (ref))
- {
- tree init = DECL_INITIAL (ref);
-
- while (TREE_CODE (init) == NOP_EXPR
- || TREE_CODE (init) == NON_LVALUE_EXPR)
- init = TREE_OPERAND (init, 0);
- if (TREE_CODE (init) == ADDR_EXPR)
- {
- init = TREE_OPERAND (init, 0);
- if (IS_AGGR_TYPE (TREE_TYPE (init))
- && (TREE_CODE (init) == PARM_DECL
- || TREE_CODE (init) == VAR_DECL))
- instance = init;
- }
- }
- }
+ tree binfo = lookup_base (fixed_type, basetype,
+ ba_ignore|ba_quiet, NULL);
+ if (binfo)
+ vtbl = BINFO_VTABLE (binfo);
+ }
- if (IS_AGGR_TYPE (TREE_TYPE (instance))
- && (TREE_CODE (instance) == RESULT_DECL
- || TREE_CODE (instance) == PARM_DECL
- || TREE_CODE (instance) == VAR_DECL))
- {
- vtbl = TYPE_BINFO_VTABLE (basetype);
- /* Knowing the dynamic type of INSTANCE we can easily obtain
- the correct vtable entry. We resolve this back to be in
- terms of the primary vtable. */
- if (TREE_CODE (vtbl) == PLUS_EXPR)
- {
- idx = fold (build (PLUS_EXPR,
- TREE_TYPE (idx),
- idx,
- build (EXACT_DIV_EXPR,
- TREE_TYPE (idx),
- TREE_OPERAND (vtbl, 1),
- TYPE_SIZE_UNIT (vtable_entry_type))));
- vtbl = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
- }
- }
- else
- vtbl = build_vfield_ref (instance, basetype);
+ if (!vtbl)
+ {
+ vtbl = build_vfield_ref (instance, basetype);
}
assemble_external (vtbl);
aref = build_array_ref (vtbl, idx);
+ TREE_CONSTANT (aref) = 1;
return aref;
}
@@ -547,6 +548,8 @@ build_vtable (class_type, name, vtable_type)
TREE_STATIC (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_VIRTUAL_P (decl) = 1;
+ DECL_ALIGN (decl) = TARGET_VTABLE_ENTRY_ALIGN;
+
import_export_vtable (decl, class_type, 0);
return decl;
@@ -554,7 +557,7 @@ build_vtable (class_type, name, vtable_type)
/* Get the VAR_DECL of the vtable for TYPE. TYPE need not be polymorphic,
or even complete. If this does not exist, create it. If COMPLETE is
- non-zero, then complete the definition of it -- that will render it
+ nonzero, then complete the definition of it -- that will render it
impossible to actually build the vtable, but is useful to get at those
which are known to exist in the runtime. */
@@ -563,21 +566,14 @@ get_vtable_decl (type, complete)
tree type;
int complete;
{
- tree name = get_vtable_name (type);
- tree decl = IDENTIFIER_GLOBAL_VALUE (name);
-
- if (decl)
- {
- my_friendly_assert (TREE_CODE (decl) == VAR_DECL
- && DECL_VIRTUAL_P (decl), 20000118);
- return decl;
- }
-
- decl = build_vtable (type, name, void_type_node);
- decl = pushdecl_top_level (decl);
- my_friendly_assert (IDENTIFIER_GLOBAL_VALUE (name) == decl,
- 20000517);
+ tree decl;
+
+ if (CLASSTYPE_VTABLES (type))
+ return CLASSTYPE_VTABLES (type);
+ decl = build_vtable (type, get_vtable_name (type), void_type_node);
+ CLASSTYPE_VTABLES (type) = decl;
+
/* At one time the vtable info was grabbed 2 words at a time. This
fails on sparc unless you have 8-byte alignment. (tiemann) */
DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
@@ -604,10 +600,7 @@ copy_virtuals (binfo)
copies = copy_list (BINFO_VIRTUALS (binfo));
for (t = copies; t; t = TREE_CHAIN (t))
- {
- BV_VCALL_INDEX (t) = NULL_TREE;
- BV_USE_VCALL_INDEX_P (t) = 0;
- }
+ BV_VCALL_INDEX (t) = NULL_TREE;
return copies;
}
@@ -615,7 +608,7 @@ copy_virtuals (binfo)
/* Build the primary virtual function table for 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. Returns a non-zero value if a new vtable is actually
+ list. Returns a nonzero value if a new vtable is actually
created. */
static int
@@ -667,7 +660,7 @@ build_primary_vtable (binfo, type)
FOR_TYPE is the most derived type which caused this table to
be needed.
- Returns non-zero if we haven't met BINFO before.
+ Returns nonzero if we haven't met BINFO before.
The order in which vtables are built (by calling this function) for
an object must remain the same, otherwise a binary incompatibility
@@ -698,7 +691,7 @@ build_secondary_vtable (binfo, for_type)
}
/* Create a new vtable for BINFO which is the hierarchy dominated by
- T. Return non-zero if we actually created a new vtable. */
+ T. Return nonzero if we actually created a new vtable. */
static int
make_new_vtable (t, binfo)
@@ -760,37 +753,9 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
BV_DELTA (v) = delta;
BV_VCALL_INDEX (v) = NULL_TREE;
BV_FN (v) = fndecl;
-
- /* Now assign virtual dispatch information, if unset. We can
- dispatch this through any overridden base function.
-
- FIXME this can choose a secondary vtable if the primary is not
- also lexically first, leading to useless conversions.
- In the V3 ABI, there's no reason for DECL_VIRTUAL_CONTEXT to
- ever be different from DECL_CONTEXT. */
- if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
- {
- DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
- DECL_VIRTUAL_CONTEXT (fndecl) = DECL_VIRTUAL_CONTEXT (base_fndecl);
- }
}
}
-/* Set DECL_VINDEX for DECL. VINDEX_P is the number of virtual
- functions present in the vtable so far. */
-
-static void
-set_vindex (decl, vfuns_p)
- tree decl;
- int *vfuns_p;
-{
- int vindex;
-
- vindex = *vfuns_p;
- *vfuns_p += (TARGET_VTABLE_USES_DESCRIPTORS
- ? TARGET_VTABLE_USES_DESCRIPTORS : 1);
- DECL_VINDEX (decl) = build_shared_int_cst (vindex);
-}
/* Add method METHOD to class TYPE. If ERROR_P is true, we are adding
the method after the class has already been defined because a
@@ -807,6 +772,8 @@ add_method (type, method, error_p)
int len;
int slot;
tree method_vec;
+ int template_conv_p = (TREE_CODE (method) == TEMPLATE_DECL
+ && DECL_TEMPLATE_CONV_FN_P (method));
if (!CLASSTYPE_METHOD_VEC (type))
/* Make a new method vector. We start with 8 entries. We must
@@ -831,14 +798,36 @@ add_method (type, method, error_p)
slot = CLASSTYPE_DESTRUCTOR_SLOT;
else
{
+ int have_template_convs_p = 0;
+
/* See if we already have an entry with this name. */
for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
- if (!TREE_VEC_ELT (method_vec, slot)
- || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec,
- slot)))
- == DECL_NAME (method)))
- break;
-
+ {
+ tree m = TREE_VEC_ELT (method_vec, slot);
+
+ if (!m)
+ break;
+ m = OVL_CURRENT (m);
+
+ if (template_conv_p)
+ {
+ have_template_convs_p = (TREE_CODE (m) == TEMPLATE_DECL
+ && DECL_TEMPLATE_CONV_FN_P (m));
+
+ /* If we need to move things up, see if there's
+ space. */
+ if (!have_template_convs_p)
+ {
+ slot = len - 1;
+ if (TREE_VEC_ELT (method_vec, slot))
+ slot++;
+ }
+ break;
+ }
+ if (DECL_NAME (m) == DECL_NAME (method))
+ break;
+ }
+
if (slot == len)
{
/* We need a bigger method vector. */
@@ -871,22 +860,27 @@ add_method (type, method, error_p)
slide some of the vector elements up. In theory, this
makes this algorithm O(N^2) but we don't expect many
conversion operators. */
- for (slot = 2; slot < len; ++slot)
- {
- tree fn = TREE_VEC_ELT (method_vec, slot);
+ if (template_conv_p)
+ slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ else
+ for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
+ {
+ tree fn = TREE_VEC_ELT (method_vec, slot);
- if (!fn)
- /* There are no more entries in the vector, so we
- can insert the new conversion operator here. */
- break;
+ if (!fn)
+ /* There are no more entries in the vector, so we
+ can insert the new conversion operator here. */
+ break;
- if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
- /* We can insert the new function right at the
- SLOTth position. */
- break;
- }
-
- if (!TREE_VEC_ELT (method_vec, slot))
+ if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
+ /* We can insert the new function right at the
+ SLOTth position. */
+ break;
+ }
+
+ if (template_conv_p && have_template_convs_p)
+ /*OK*/;
+ else if (!TREE_VEC_ELT (method_vec, slot))
/* There is nothing in the Ith slot, so we can avoid
moving anything. */
;
@@ -985,7 +979,7 @@ add_method (type, method, error_p)
TREE_VEC_ELT (method_vec, slot)
= build_overload (method, TREE_VEC_ELT (method_vec, slot));
- /* Add the new binding. */
+ /* Add the new binding. */
if (!DECL_CONSTRUCTOR_P (method)
&& !DECL_DESTRUCTOR_P (method))
push_class_level_binding (DECL_NAME (method),
@@ -1157,6 +1151,9 @@ handle_using_decl (using_decl, t)
tree flist = NULL_TREE;
tree old_value;
+ if (ctype == error_mark_node)
+ return;
+
binfo = lookup_base (t, ctype, ba_any, NULL);
if (! binfo)
{
@@ -1164,14 +1161,12 @@ handle_using_decl (using_decl, t)
return;
}
- if (name == constructor_name (ctype)
- || name == constructor_name_full (ctype))
+ if (constructor_name_p (name, ctype))
{
cp_error_at ("`%D' names constructor", using_decl);
return;
}
- if (name == constructor_name (t)
- || name == constructor_name_full (t))
+ if (constructor_name_p (name, t))
{
cp_error_at ("`%D' invalid in `%T'", using_decl, t);
return;
@@ -1186,8 +1181,8 @@ handle_using_decl (using_decl, t)
}
if (BASELINK_P (fdecl))
- /* Ignore base type this came from. */
- fdecl = TREE_VALUE (fdecl);
+ /* Ignore base type this came from. */
+ fdecl = BASELINK_FUNCTIONS (fdecl);
old_value = IDENTIFIER_CLASS_VALUE (name);
if (old_value)
@@ -1319,7 +1314,7 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
}
if (TREE_VIA_VIRTUAL (base_binfo))
- /* A virtual base does not effect nearly emptiness. */
+ /* A virtual base does not effect nearly emptiness. */
;
else if (CLASSTYPE_NEARLY_EMPTY_P (basetype))
{
@@ -1328,7 +1323,7 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
derived class is not nearly empty either. */
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
else
- /* Remember we've seen one. */
+ /* Remember we've seen one. */
seen_non_virtual_nearly_empty_base_p = 1;
}
else if (!is_empty_class (basetype))
@@ -1477,7 +1472,7 @@ mark_primary_virtual_base (base_binfo, type)
/* If BINFO is an unmarked virtual binfo for a class with a primary virtual
base, then BINFO has no primary base in this graph. Called from
- mark_primary_bases. DATA is the most derived type. */
+ mark_primary_bases. DATA is the most derived type. */
static tree dfs_unshared_virtual_bases (binfo, data)
tree binfo;
@@ -1510,11 +1505,11 @@ static tree dfs_unshared_virtual_bases (binfo, data)
if (binfo != TYPE_BINFO (t))
/* The vtable fields will have been copied when duplicating the
base binfos. That information is bogus, make sure we don't try
- and use it. */
+ and use it. */
BINFO_VTABLE (binfo) = NULL_TREE;
/* If this is a virtual primary base, make sure its offset matches
- that which it is primary for. */
+ that which it is primary for. */
if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo) &&
binfo_for_vbase (BINFO_TYPE (binfo), t) == binfo)
{
@@ -1543,7 +1538,7 @@ mark_primary_bases (type)
tree base_binfo;
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
- /* Not a dynamic base. */
+ /* Not a dynamic base. */
continue;
base_binfo = get_primary_binfo (binfo);
@@ -1572,10 +1567,9 @@ mark_primary_bases (type)
/* Make the BINFO the primary base of T. */
static void
-set_primary_base (t, binfo, vfuns_p)
+set_primary_base (t, binfo)
tree t;
tree binfo;
- int *vfuns_p;
{
tree basetype;
@@ -1584,16 +1578,13 @@ set_primary_base (t, binfo, vfuns_p)
TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
- CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
- *vfuns_p = CLASSTYPE_VSIZE (basetype);
}
/* Determine the primary class for T. */
static void
-determine_primary_base (t, vfuns_p)
+determine_primary_base (t)
tree t;
- int *vfuns_p;
{
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
tree vbases;
@@ -1612,12 +1603,6 @@ determine_primary_base (t, vfuns_p)
if (TYPE_CONTAINS_VPTR_P (basetype))
{
- /* Even a virtual baseclass can contain our RTTI
- information. But, we prefer a non-virtual polymorphic
- baseclass. */
- if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
-
/* We prefer a non-virtual base, although a virtual one will
do. */
if (TREE_VIA_VIRTUAL (base_binfo))
@@ -1625,7 +1610,7 @@ determine_primary_base (t, vfuns_p)
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
- set_primary_base (t, base_binfo, vfuns_p);
+ set_primary_base (t, base_binfo);
CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
}
else
@@ -1727,7 +1712,7 @@ determine_primary_base (t, vfuns_p)
/* If we've got a primary base, use it. */
if (candidate)
{
- set_primary_base (t, candidate, vfuns_p);
+ set_primary_base (t, candidate);
CLASSTYPE_VFIELDS (t)
= copy_list (CLASSTYPE_VFIELDS (BINFO_TYPE (candidate)));
}
@@ -1871,7 +1856,7 @@ maybe_warn_about_overly_private_class (t)
return;
has_nonprivate_method = 1;
- break;
+ /* Keep searching for a static member function. */
}
else if (!DECL_CONSTRUCTOR_P (fn) && !DECL_DESTRUCTOR_P (fn))
has_member_fn = 1;
@@ -2113,12 +2098,14 @@ duplicate_tag_error (t)
memset ((char *) TYPE_LANG_SPECIFIC (t), 0, sizeof (struct lang_type));
BINFO_BASETYPES(binfo) = NULL_TREE;
+ TYPE_LANG_SPECIFIC (t)->u.h.is_lang_type_class = 1;
TYPE_BINFO (t) = binfo;
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
TYPE_REDEFINED (t) = 1;
CLASSTYPE_TEMPLATE_INFO (t) = template_info;
CLASSTYPE_USE_TEMPLATE (t) = use_template;
+ CLASSTYPE_DECL_LIST (t) = NULL_TREE;
}
TYPE_SIZE (t) = NULL_TREE;
TYPE_MODE (t) = VOIDmode;
@@ -2164,7 +2151,7 @@ layout_vtable_decl (binfo, n)
layout_decl (vtable, 0);
/* At one time the vtable info was grabbed 2 words at a time. This
- fails on Sparc unless you have 8-byte alignment. */
+ fails on SPARC unless you have 8-byte alignment. */
DECL_ALIGN (vtable) = MAX (TYPE_ALIGN (double_type_node),
DECL_ALIGN (vtable));
}
@@ -2202,6 +2189,29 @@ same_signature_p (fndecl, base_fndecl)
return 0;
}
+/* Called from base_derived_from via dfs_walk. */
+
+static tree
+dfs_base_derived_from (tree binfo, void *data)
+{
+ tree base = (tree) data;
+
+ if (same_type_p (TREE_TYPE (base), TREE_TYPE (binfo))
+ && tree_int_cst_equal (BINFO_OFFSET (base), BINFO_OFFSET (binfo)))
+ return error_mark_node;
+
+ return NULL_TREE;
+}
+
+/* Returns TRUE if DERIVED is a binfo containing the binfo BASE as a
+ subobject. */
+
+static bool
+base_derived_from (tree derived, tree base)
+{
+ return dfs_walk (derived, dfs_base_derived_from, NULL, base) != NULL_TREE;
+}
+
typedef struct find_final_overrider_data_s {
/* The function for which we are trying to find a final overrider. */
tree fn;
@@ -2209,14 +2219,8 @@ typedef struct find_final_overrider_data_s {
tree declaring_base;
/* The most derived class in the hierarchy. */
tree most_derived_type;
- /* The final overriding function. */
- tree overriding_fn;
- /* The functions that we thought might be final overriders, but
- aren't. */
+ /* The candidate overriders. */
tree candidates;
- /* The BINFO for the class in which the final overriding function
- appears. */
- tree overriding_base;
} find_final_overrider_data;
/* Called from find_final_overrider via dfs_walk. */
@@ -2240,119 +2244,46 @@ dfs_find_final_overrider (binfo, data)
method = NULL_TREE;
/* We've found a path to the declaring base. Walk down the path
looking for an overrider for FN. */
- for (path = reverse_path (binfo);
- path;
- path = TREE_CHAIN (path))
+ path = reverse_path (binfo);
+ while (!same_type_p (BINFO_TYPE (TREE_VALUE (path)),
+ ffod->most_derived_type))
+ path = TREE_CHAIN (path);
+ while (path)
{
method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)),
ffod->fn);
if (method)
- break;
+ {
+ path = TREE_VALUE (path);
+ break;
+ }
+
+ path = TREE_CHAIN (path);
}
/* If we found an overrider, record the overriding function, and
the base from which it came. */
if (path)
{
- tree base;
-
- /* Assume the path is non-virtual. See if there are any
- virtual bases from (but not including) the overrider up
- to and including the base where the function is
- defined. */
- for (base = TREE_CHAIN (path); base; base = TREE_CHAIN (base))
- if (TREE_VIA_VIRTUAL (TREE_VALUE (base)))
- {
- base = ffod->declaring_base;
- break;
- }
+ tree *candidate;
- /* If we didn't already have an overrider, or any
- candidates, then this function is the best candidate so
- far. */
- if (!ffod->overriding_fn && !ffod->candidates)
- {
- ffod->overriding_fn = method;
- ffod->overriding_base = TREE_VALUE (path);
- }
- else if (ffod->overriding_fn)
+ /* Remove any candidates overridden by this new function. */
+ candidate = &ffod->candidates;
+ while (*candidate)
{
- /* We had a best overrider; let's see how this compares. */
-
- if (ffod->overriding_fn == method
- && (tree_int_cst_equal
- (BINFO_OFFSET (TREE_VALUE (path)),
- BINFO_OFFSET (ffod->overriding_base))))
- /* We found the same overrider we already have, and in the
- same place; it's still the best. */;
- else if (strictly_overrides (ffod->overriding_fn, method))
- /* The old function overrides this function; it's still the
- best. */;
- else if (strictly_overrides (method, ffod->overriding_fn))
- {
- /* The new function overrides the old; it's now the
- best. */
- ffod->overriding_fn = method;
- ffod->overriding_base = TREE_VALUE (path);
- }
+ /* If *CANDIDATE overrides METHOD, then METHOD
+ cannot override anything else on the list. */
+ if (base_derived_from (TREE_VALUE (*candidate), path))
+ return NULL_TREE;
+ /* If METHOD overrides *CANDIDATE, remove *CANDIDATE. */
+ if (base_derived_from (path, TREE_VALUE (*candidate)))
+ *candidate = TREE_CHAIN (*candidate);
else
- {
- /* Ambiguous. */
- ffod->candidates
- = build_tree_list (NULL_TREE,
- ffod->overriding_fn);
- if (method != ffod->overriding_fn)
- ffod->candidates
- = tree_cons (NULL_TREE, method, ffod->candidates);
- ffod->overriding_fn = NULL_TREE;
- ffod->overriding_base = NULL_TREE;
- }
+ candidate = &TREE_CHAIN (*candidate);
}
- else
- {
- /* We had a list of ambiguous overrides; let's see how this
- new one compares. */
-
- tree candidates;
- bool incomparable = false;
-
- /* If there were previous candidates, and this function
- overrides all of them, then it is the new best
- candidate. */
- for (candidates = ffod->candidates;
- candidates;
- candidates = TREE_CHAIN (candidates))
- {
- /* If the candidate overrides the METHOD, then we
- needn't worry about it any further. */
- if (strictly_overrides (TREE_VALUE (candidates),
- method))
- {
- method = NULL_TREE;
- break;
- }
-
- /* If the METHOD doesn't override the candidate,
- then it is incomporable. */
- if (!strictly_overrides (method,
- TREE_VALUE (candidates)))
- incomparable = true;
- }
- /* If METHOD overrode all the candidates, then it is the
- new best candidate. */
- if (!candidates && !incomparable)
- {
- ffod->overriding_fn = method;
- ffod->overriding_base = TREE_VALUE (path);
- ffod->candidates = NULL_TREE;
- }
- /* If METHOD didn't override all the candidates, then it
- is another candidate. */
- else if (method && incomparable)
- ffod->candidates
- = tree_cons (NULL_TREE, method, ffod->candidates);
- }
+ /* Add the new function. */
+ ffod->candidates = tree_cons (method, path, ffod->candidates);
}
}
@@ -2361,18 +2292,18 @@ dfs_find_final_overrider (binfo, data)
/* Returns a TREE_LIST whose TREE_PURPOSE is the final overrider for
FN and whose TREE_VALUE is the binfo for the base where the
- overriding occurs. BINFO (in the hierarchy dominated by T) is the
- base object in which FN is declared. */
+ overriding occurs. BINFO (in the hierarchy dominated by the binfo
+ DERIVED) is the base object in which FN is declared. */
static tree
-find_final_overrider (t, binfo, fn)
- tree t;
+find_final_overrider (derived, binfo, fn)
+ tree derived;
tree binfo;
tree fn;
{
find_final_overrider_data ffod;
- /* Getting this right is a little tricky. This is legal:
+ /* Getting this right is a little tricky. This is valid:
struct S { virtual void f (); };
struct T { virtual void f (); };
@@ -2392,41 +2323,42 @@ find_final_overrider (t, binfo, fn)
different overriders along any two, then there is a problem. */
ffod.fn = fn;
ffod.declaring_base = binfo;
- ffod.most_derived_type = t;
- ffod.overriding_fn = NULL_TREE;
- ffod.overriding_base = NULL_TREE;
+ ffod.most_derived_type = BINFO_TYPE (derived);
ffod.candidates = NULL_TREE;
- dfs_walk (TYPE_BINFO (t),
+ dfs_walk (derived,
dfs_find_final_overrider,
NULL,
&ffod);
/* If there was no winner, issue an error message. */
- if (!ffod.overriding_fn)
+ if (!ffod.candidates || TREE_CHAIN (ffod.candidates))
{
- error ("no unique final overrider for `%D' in `%T'", fn, t);
+ error ("no unique final overrider for `%D' in `%T'", fn,
+ BINFO_TYPE (derived));
return error_mark_node;
}
- return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
+ return ffod.candidates;
}
-/* Returns the function from the BINFO_VIRTUALS entry in T which matches
- the signature of FUNCTION_DECL FN, or NULL_TREE if none. In other words,
- the function that the slot in T's primary vtable points to. */
+/* Return the index of the vcall offset for FN when TYPE is used as a
+ virtual base. */
-static tree get_matching_virtual PARAMS ((tree, tree));
static tree
-get_matching_virtual (t, fn)
- tree t, fn;
+get_vcall_index (tree fn, tree type)
{
- tree f;
+ tree v;
- for (f = BINFO_VIRTUALS (TYPE_BINFO (t)); f; f = TREE_CHAIN (f))
- if (same_signature_p (BV_FN (f), fn))
- return BV_FN (f);
- return NULL_TREE;
+ for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v))
+ if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v)))
+ || same_signature_p (fn, TREE_PURPOSE (v)))
+ break;
+
+ /* There should always be an appropriate index. */
+ my_friendly_assert (v, 20021103);
+
+ return TREE_VALUE (v);
}
/* Update an entry in the vtable for BINFO, which is in the hierarchy
@@ -2462,7 +2394,7 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
first_defn = b;
/* Find the final overrider. */
- overrider = find_final_overrider (t, b, fn);
+ overrider = find_final_overrider (TYPE_BINFO (t), b, fn);
if (overrider == error_mark_node)
return;
@@ -2494,7 +2426,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
/* Compute the constant adjustment to the `this' pointer. The
`this' pointer, when this function is called, will point at BINFO
(or one of its primary bases, which are at the same offset). */
-
if (virtual_base)
/* The `this' pointer needs to be adjusted from the declaration to
the nearest virtual base. */
@@ -2507,36 +2438,11 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
will be zero, as it will be a primary base. */
delta = size_zero_node;
else
- {
- /* The `this' pointer needs to be adjusted from pointing to
- BINFO to pointing at the base where the final overrider
- appears. */
- delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
- BINFO_OFFSET (binfo));
-
- if (! integer_zerop (delta))
- {
- /* We'll need a thunk. But if we have a (perhaps formerly)
- primary virtual base, we have a vcall slot for this function,
- so we can use it rather than create a non-virtual thunk. */
-
- b = get_primary_binfo (first_defn);
- for (; b; b = get_primary_binfo (b))
- {
- tree f = get_matching_virtual (BINFO_TYPE (b), fn);
- if (!f)
- /* b doesn't have this function; no suitable vbase. */
- break;
- if (TREE_VIA_VIRTUAL (b))
- {
- /* Found one; we can treat ourselves as a virtual base. */
- virtual_base = binfo;
- delta = size_zero_node;
- break;
- }
- }
- }
- }
+ /* The `this' pointer needs to be adjusted from pointing to
+ BINFO to pointing at the base where the final overrider
+ appears. */
+ delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
+ BINFO_OFFSET (binfo));
modify_vtable_entry (t,
binfo,
@@ -2545,7 +2451,9 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
virtuals);
if (virtual_base)
- BV_USE_VCALL_INDEX_P (*virtuals) = 1;
+ BV_VCALL_INDEX (*virtuals)
+ = get_vcall_index (TREE_PURPOSE (overrider),
+ BINFO_TYPE (virtual_base));
}
/* Called from modify_all_vtables via dfs_walk. */
@@ -2600,9 +2508,8 @@ dfs_modify_vtables (binfo, data)
should therefore be appended to the end of the vtable for T. */
static tree
-modify_all_vtables (t, vfuns_p, virtuals)
+modify_all_vtables (t, virtuals)
tree t;
- int *vfuns_p;
tree virtuals;
{
tree binfo = TYPE_BINFO (t);
@@ -2626,12 +2533,6 @@ modify_all_vtables (t, vfuns_p, virtuals)
if (!value_member (fn, BINFO_VIRTUALS (binfo))
|| DECL_VINDEX (fn) == error_mark_node)
{
- /* Set the vtable index. */
- set_vindex (fn, vfuns_p);
- /* We don't need to convert to a base class when calling
- this function. */
- DECL_VIRTUAL_CONTEXT (fn) = t;
-
/* We don't need to adjust the `this' pointer when
calling this function. */
BV_DELTA (*fnsp) = integer_zero_node;
@@ -2644,26 +2545,8 @@ modify_all_vtables (t, vfuns_p, virtuals)
/* We've already got an entry for this function. Skip it. */
*fnsp = TREE_CHAIN (*fnsp);
}
-
- return virtuals;
-}
-
-/* Here, we already know that they match in every respect.
- All we have to check is where they had their declarations.
- Return non-zero iff FNDECL1 is declared in a class which has a
- proper base class containing FNDECL2. We don't care about
- ambiguity or accessibility. */
-
-static int
-strictly_overrides (fndecl1, fndecl2)
- tree fndecl1, fndecl2;
-{
- base_kind kind;
-
- return (lookup_base (DECL_CONTEXT (fndecl1), DECL_CONTEXT (fndecl2),
- ba_ignore | ba_quiet, &kind)
- && kind != bk_same_type);
+ return virtuals;
}
/* Get the base virtual function declarations in T that have the
@@ -2678,11 +2561,19 @@ get_basefndecls (name, t)
int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
int i;
- for (methods = TYPE_METHODS (t); methods; methods = TREE_CHAIN (methods))
- if (TREE_CODE (methods) == FUNCTION_DECL
- && DECL_VINDEX (methods) != NULL_TREE
- && DECL_NAME (methods) == name)
- base_fndecls = tree_cons (NULL_TREE, methods, base_fndecls);
+ /* Find virtual functions in T with the indicated NAME. */
+ i = lookup_fnfields_1 (t, name);
+ if (i != -1)
+ for (methods = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), i);
+ methods;
+ methods = OVL_NEXT (methods))
+ {
+ tree method = OVL_CURRENT (methods);
+
+ if (TREE_CODE (method) == FUNCTION_DECL
+ && DECL_VINDEX (method))
+ base_fndecls = tree_cons (NULL_TREE, method, base_fndecls);
+ }
if (base_fndecls)
return base_fndecls;
@@ -2762,11 +2653,11 @@ warn_hidden (t)
base_fndecls);
}
- /* If there are no functions to hide, continue. */
+ /* If there are no functions to hide, continue. */
if (!base_fndecls)
continue;
- /* Remove any overridden functions. */
+ /* Remove any overridden functions. */
for (fns = TREE_VEC_ELT (method_vec, i); fns; fns = OVL_NEXT (fns))
{
fndecl = OVL_CURRENT (fns);
@@ -2857,6 +2748,29 @@ finish_struct_anon (t)
}
}
+/* Add T to CLASSTYPE_DECL_LIST of current_class_type which
+ will be used later during class template instantiation.
+ When FRIEND_P is zero, T can be a static member data (VAR_DECL),
+ a non-static member data (FIELD_DECL), a member function
+ (FUNCTION_DECL), a nested type (RECORD_TYPE, ENUM_TYPE),
+ a typedef (TYPE_DECL) or a member class template (TEMPLATE_DECL)
+ When FRIEND_P is nonzero, T is either a friend class
+ (RECORD_TYPE, TEMPLATE_DECL) or a friend function
+ (FUNCTION_DECL, TEMPLATE_DECL). */
+
+void
+maybe_add_class_template_decl_list (type, t, friend_p)
+ tree type;
+ tree t;
+ int friend_p;
+{
+ /* Save some memory by not creating TREE_LIST if TYPE is not template. */
+ if (CLASSTYPE_TEMPLATE_INFO (type))
+ CLASSTYPE_DECL_LIST (type)
+ = tree_cons (friend_p ? NULL_TREE : type,
+ t, CLASSTYPE_DECL_LIST (type));
+}
+
/* Create default constructors, assignment operators, and so forth for
the type indicated by T, if they are needed.
CANT_HAVE_DEFAULT_CTOR, CANT_HAVE_CONST_CTOR, and
@@ -2866,7 +2780,7 @@ finish_struct_anon (t)
reference, respectively. If a virtual destructor is created, its
DECL is returned; otherwise the return value is NULL_TREE. */
-static tree
+static void
add_implicitly_declared_members (t, cant_have_default_ctor,
cant_have_const_cctor,
cant_have_const_assignment)
@@ -2937,13 +2851,27 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
/* Now, hook all of the new functions on to TYPE_METHODS,
and add them to the CLASSTYPE_METHOD_VEC. */
for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f))
- add_method (t, *f, /*error_p=*/0);
- *f = TYPE_METHODS (t);
- TYPE_METHODS (t) = implicit_fns;
+ {
+ add_method (t, *f, /*error_p=*/0);
+ maybe_add_class_template_decl_list (current_class_type, *f, /*friend_p=*/0);
+ }
+ if (abi_version_at_least (2))
+ /* G++ 3.2 put the implicit destructor at the *beginning* of the
+ list, which cause the destructor to be emitted in an incorrect
+ location in the vtable. */
+ TYPE_METHODS (t) = chainon (TYPE_METHODS (t), implicit_fns);
+ else
+ {
+ if (warn_abi && virtual_dtor)
+ warning ("vtable layout for class `%T' may not be ABI-compliant "
+ "and may change in a future version of GCC due to implicit "
+ "virtual destructor",
+ t);
+ *f = TYPE_METHODS (t);
+ TYPE_METHODS (t) = implicit_fns;
+ }
--adding_implicit_members;
-
- return virtual_dtor;
}
/* Subroutine of finish_struct_1. Recursively count the number of fields
@@ -3165,15 +3093,6 @@ check_field_decl (field, t, cant_have_const_ctor,
cp_error_at ("multiple fields in union `%T' initialized");
*any_default_members = 1;
}
-
- /* Non-bit-fields are aligned for their type, except packed fields
- which require only BITS_PER_UNIT alignment. */
- DECL_ALIGN (field) = MAX (DECL_ALIGN (field),
- (DECL_PACKED (field)
- ? BITS_PER_UNIT
- : TYPE_ALIGN (TREE_TYPE (field))));
- if (! DECL_PACKED (field))
- DECL_USER_ALIGN (field) |= TYPE_USER_ALIGN (TREE_TYPE (field));
}
/* Check the data members (both static and non-static), class-scoped
@@ -3206,15 +3125,10 @@ check_field_decl (field, t, cant_have_const_ctor,
fields can be added by adding to this chain. */
static void
-check_field_decls (t, access_decls, empty_p,
- cant_have_default_ctor_p, cant_have_const_ctor_p,
- no_const_asn_ref_p)
- tree t;
- tree *access_decls;
- int *empty_p;
- int *cant_have_default_ctor_p;
- int *cant_have_const_ctor_p;
- int *no_const_asn_ref_p;
+check_field_decls (tree t, tree *access_decls,
+ int *cant_have_default_ctor_p,
+ int *cant_have_const_ctor_p,
+ int *no_const_asn_ref_p)
{
tree *field;
tree *next;
@@ -3252,12 +3166,12 @@ check_field_decls (t, access_decls, empty_p,
tree element_type;
/* The class is non-empty. */
- *empty_p = 0;
+ CLASSTYPE_EMPTY_P (t) = 0;
/* The class is not even nearly empty. */
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
/* If one of the data members contains an empty class,
so does T. */
- element_type = strip_array_types (type);
+ element_type = strip_array_types (type);
if (CLASS_TYPE_P (element_type)
&& CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type))
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 1;
@@ -3351,7 +3265,8 @@ check_field_decls (t, access_decls, empty_p,
*cant_have_default_ctor_p = 1;
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
- if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
+ if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t)
+ && extra_warnings)
cp_warning_at ("non-static reference `%#D' in class without a constructor", x);
}
@@ -3385,7 +3300,8 @@ check_field_decls (t, access_decls, empty_p,
*cant_have_default_ctor_p = 1;
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
- if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
+ if (! TYPE_HAS_CONSTRUCTOR (t) && CLASSTYPE_NON_AGGREGATE (t)
+ && extra_warnings)
cp_warning_at ("non-static const member `%#D' in class without a constructor", x);
}
/* A field that is pseudo-const makes the structure likewise. */
@@ -3469,7 +3385,7 @@ record_subobject_offset (type, offset, offsets)
return 0;
}
-/* Returns non-zero if TYPE is an empty class type and there is
+/* Returns nonzero if TYPE is an empty class type and there is
already an entry in OFFSETS for the same TYPE as the same OFFSET. */
static int
@@ -3498,13 +3414,13 @@ check_subobject_offset (type, offset, offsets)
/* Walk through all the subobjects of TYPE (located at OFFSET). Call
F for every subobject, passing it the type, offset, and table of
- OFFSETS. If VBASES_P is non-zero, then even virtual non-primary
- bases should be traversed; otherwise, they are ignored.
+ OFFSETS. If VBASES_P is one, then virtual non-primary bases should
+ be traversed.
If MAX_OFFSET is non-NULL, then subobjects with an offset greater
than MAX_OFFSET will not be walked.
- If F returns a non-zero value, the traversal ceases, and that value
+ If F returns a nonzero value, the traversal ceases, and that value
is returned. Otherwise, returns zero. */
static int
@@ -3517,15 +3433,24 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
int vbases_p;
{
int r = 0;
+ tree type_binfo = NULL_TREE;
/* If this OFFSET is bigger than the MAX_OFFSET, then we should
stop. */
if (max_offset && INT_CST_LT (max_offset, offset))
return 0;
+ if (!TYPE_P (type))
+ {
+ if (abi_version_at_least (2))
+ type_binfo = type;
+ type = BINFO_TYPE (type);
+ }
+
if (CLASS_TYPE_P (type))
{
tree field;
+ tree binfo;
int i;
/* Avoid recursing into objects that are not interesting. */
@@ -3538,36 +3463,119 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
return r;
/* Iterate through the direct base classes of TYPE. */
- for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
+ if (!type_binfo)
+ type_binfo = TYPE_BINFO (type);
+ for (i = 0; i < BINFO_N_BASETYPES (type_binfo); ++i)
{
- tree binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
+ tree binfo_offset;
+
+ binfo = BINFO_BASETYPE (type_binfo, i);
+
+ if (abi_version_at_least (2)
+ && TREE_VIA_VIRTUAL (binfo))
+ continue;
if (!vbases_p
&& TREE_VIA_VIRTUAL (binfo)
&& !BINFO_PRIMARY_P (binfo))
continue;
- r = walk_subobject_offsets (BINFO_TYPE (binfo),
+ if (!abi_version_at_least (2))
+ binfo_offset = size_binop (PLUS_EXPR,
+ offset,
+ BINFO_OFFSET (binfo));
+ else
+ {
+ tree orig_binfo;
+ /* We cannot rely on BINFO_OFFSET being set for the base
+ class yet, but the offsets for direct non-virtual
+ bases can be calculated by going back to the TYPE. */
+ orig_binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
+ binfo_offset = size_binop (PLUS_EXPR,
+ offset,
+ BINFO_OFFSET (orig_binfo));
+ }
+
+ r = walk_subobject_offsets (binfo,
f,
- size_binop (PLUS_EXPR,
- offset,
- BINFO_OFFSET (binfo)),
+ binfo_offset,
offsets,
max_offset,
- vbases_p);
+ (abi_version_at_least (2)
+ ? /*vbases_p=*/0 : vbases_p));
if (r)
return r;
}
+ if (abi_version_at_least (2))
+ {
+ tree vbase;
+
+ /* Iterate through the virtual base classes of TYPE. In G++
+ 3.2, we included virtual bases in the direct base class
+ loop above, which results in incorrect results; the
+ correct offsets for virtual bases are only known when
+ working with the most derived type. */
+ if (vbases_p)
+ for (vbase = CLASSTYPE_VBASECLASSES (type);
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ {
+ binfo = TREE_VALUE (vbase);
+ r = walk_subobject_offsets (binfo,
+ f,
+ size_binop (PLUS_EXPR,
+ offset,
+ BINFO_OFFSET (binfo)),
+ offsets,
+ max_offset,
+ /*vbases_p=*/0);
+ if (r)
+ return r;
+ }
+ else
+ {
+ /* We still have to walk the primary base, if it is
+ virtual. (If it is non-virtual, then it was walked
+ above.) */
+ vbase = get_primary_binfo (type_binfo);
+ if (vbase && TREE_VIA_VIRTUAL (vbase))
+ {
+ tree derived = type_binfo;
+ while (BINFO_INHERITANCE_CHAIN (derived))
+ derived = BINFO_INHERITANCE_CHAIN (derived);
+ derived = TREE_TYPE (derived);
+ vbase = binfo_for_vbase (TREE_TYPE (vbase), derived);
+
+ if (BINFO_PRIMARY_BASE_OF (vbase) == type_binfo)
+ {
+ r = (walk_subobject_offsets
+ (vbase, f, offset,
+ offsets, max_offset, /*vbases_p=*/0));
+ if (r)
+ return r;
+ }
+ }
+ }
+ }
+
/* Iterate through the fields of TYPE. */
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- if (TREE_CODE (field) == FIELD_DECL)
+ if (TREE_CODE (field) == FIELD_DECL && !DECL_ARTIFICIAL (field))
{
+ tree field_offset;
+
+ if (abi_version_at_least (2))
+ field_offset = byte_position (field);
+ else
+ /* In G++ 3.2, DECL_FIELD_OFFSET was used. */
+ field_offset = DECL_FIELD_OFFSET (field);
+
r = walk_subobject_offsets (TREE_TYPE (field),
f,
size_binop (PLUS_EXPR,
offset,
- DECL_FIELD_OFFSET (field)),
+ field_offset),
offsets,
max_offset,
/*vbases_p=*/1);
@@ -3587,8 +3595,11 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
return 0;
/* Step through each of the elements in the array. */
- for (index = size_zero_node;
- INT_CST_LT (index, TYPE_MAX_VALUE (domain));
+ for (index = size_zero_node;
+ /* G++ 3.2 had an off-by-one error here. */
+ (abi_version_at_least (2)
+ ? !INT_CST_LT (TYPE_MAX_VALUE (domain), index)
+ : INT_CST_LT (index, TYPE_MAX_VALUE (domain)));
index = size_binop (PLUS_EXPR, index, size_one_node))
{
r = walk_subobject_offsets (TREE_TYPE (type),
@@ -3613,7 +3624,7 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
}
/* Record all of the empty subobjects of TYPE (located at OFFSET) in
- OFFSETS. If VBASES_P is non-zero, virtual bases of TYPE are
+ OFFSETS. If VBASES_P is nonzero, virtual bases of TYPE are
examined. */
static void
@@ -3627,8 +3638,8 @@ record_subobject_offsets (type, offset, offsets, vbases_p)
offsets, /*max_offset=*/NULL_TREE, vbases_p);
}
-/* Returns non-zero if any of the empty subobjects of TYPE (located at
- OFFSET) conflict with entries in OFFSETS. If VBASES_P is non-zero,
+/* Returns nonzero if any of the empty subobjects of TYPE (located at
+ OFFSET) conflict with entries in OFFSETS. If VBASES_P is nonzero,
virtual bases of TYPE are examined. */
static int
@@ -3656,22 +3667,34 @@ layout_conflict_p (type, offset, offsets, vbases_p)
/* DECL is a FIELD_DECL corresponding either to a base subobject of a
non-static data member of the type indicated by RLI. BINFO is the
binfo corresponding to the base subobject, OFFSETS maps offsets to
- types already located at those offsets. T is the most derived
- type. This function determines the position of the DECL. */
+ types already located at those offsets. This function determines
+ the position of the DECL. */
static void
-layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
- record_layout_info rli;
- tree decl;
- tree binfo;
- splay_tree offsets;
- tree t;
+layout_nonempty_base_or_field (record_layout_info rli,
+ tree decl,
+ tree binfo,
+ splay_tree offsets)
{
+ tree t = rli->t;
tree offset = NULL_TREE;
- tree type = TREE_TYPE (decl);
- /* If we are laying out a base class, rather than a field, then
- DECL_ARTIFICIAL will be set on the FIELD_DECL. */
- int field_p = !DECL_ARTIFICIAL (decl);
+ bool field_p;
+ tree type;
+
+ if (binfo)
+ {
+ /* For the purposes of determining layout conflicts, we want to
+ use the class type of BINFO; TREE_TYPE (DECL) will be the
+ CLASSTYPE_AS_BASE version, which does not contain entries for
+ zero-sized bases. */
+ type = TREE_TYPE (binfo);
+ field_p = false;
+ }
+ else
+ {
+ type = TREE_TYPE (decl);
+ field_p = true;
+ }
/* Try to place the field. It may take more than one try if we have
a hard time placing the field without putting two objects of the
@@ -3696,13 +3719,15 @@ layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
offset zero -- its S component would be at the same address
as the S we already allocated. So, we have to skip ahead.
Since all data members, including those whose type is an
- empty class, have non-zero size, any overlap can happen only
+ empty class, have nonzero size, any overlap can happen only
with a direct or indirect base-class -- it can't happen with
a data member. */
- if (layout_conflict_p (TREE_TYPE (decl),
- offset,
- offsets,
- field_p))
+ /* G++ 3.2 did not check for overlaps when placing a non-empty
+ virtual base. */
+ if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo))
+ break;
+ if (layout_conflict_p (field_p ? type : binfo, offset,
+ offsets, field_p))
{
/* Strip off the size allocated to this field. That puts us
at the first place we could have put the field with
@@ -3725,15 +3750,32 @@ layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
/* Now that we know where it will be placed, update its
BINFO_OFFSET. */
if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
+ /* Indirect virtual bases may have a nonzero BINFO_OFFSET at
+ this point because their BINFO_OFFSET is copied from another
+ hierarchy. Therefore, we may not need to add the entire
+ OFFSET. */
propagate_binfo_offsets (binfo,
- convert (ssizetype, offset), t);
+ size_diffop (convert (ssizetype, offset),
+ convert (ssizetype,
+ BINFO_OFFSET (binfo))),
+ t);
+}
+
+/* Returns true if TYPE is empty and OFFSET is nonzero. */
+
+static int
+empty_base_at_nonzero_offset_p (tree type,
+ tree offset,
+ splay_tree offsets ATTRIBUTE_UNUSED)
+{
+ return is_empty_class (type) && !integer_zerop (offset);
}
/* Layout the empty base BINFO. EOC indicates the byte currently just
past the end of the class, and should be correctly aligned for a
class of the type indicated by BINFO; OFFSETS gives the offsets of
the empty bases allocated so far. T is the most derived
- type. Return non-zero iff we added it at the end. */
+ type. Return nonzero iff we added it at the end. */
static bool
layout_empty_base (binfo, eoc, offsets, t)
@@ -3745,14 +3787,21 @@ layout_empty_base (binfo, eoc, offsets, t)
tree alignment;
tree basetype = BINFO_TYPE (binfo);
bool atend = false;
-
+
/* This routine should only be used for empty classes. */
my_friendly_assert (is_empty_class (basetype), 20000321);
alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype));
+
+ if (abi_version_at_least (2))
+ BINFO_OFFSET (binfo) = size_zero_node;
+ if (warn_abi && !integer_zerop (BINFO_OFFSET (binfo)))
+ warning ("offset of empty base `%T' may not be ABI-compliant and may"
+ "change in a future version of GCC",
+ BINFO_TYPE (binfo));
/* This is an empty base class. We first try to put it at offset
zero. */
- if (layout_conflict_p (BINFO_TYPE (binfo),
+ if (layout_conflict_p (binfo,
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0))
@@ -3763,7 +3812,7 @@ layout_empty_base (binfo, eoc, offsets, t)
propagate_binfo_offsets (binfo, convert (ssizetype, eoc), t);
while (1)
{
- if (!layout_conflict_p (BINFO_TYPE (binfo),
+ if (!layout_conflict_p (binfo,
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0))
@@ -3777,103 +3826,141 @@ layout_empty_base (binfo, eoc, offsets, t)
return atend;
}
-/* Build a FIELD_DECL for the base given by BINFO in the class
- indicated by RLI. If the new object is non-empty, clear *EMPTY_P.
- *BASE_ALIGN is a running maximum of the alignments of any base
- class. OFFSETS gives the location of empty base subobjects. T is
- the most derived type. Return non-zero if the new object cannot be
- nearly-empty. */
+/* Layout the the base given by BINFO in the class indicated by RLI.
+ *BASE_ALIGN is a running maximum of the alignments of
+ any base class. OFFSETS gives the location of empty base
+ subobjects. T is the most derived type. Return nonzero if the new
+ object cannot be nearly-empty. A new FIELD_DECL is inserted at
+ *NEXT_FIELD, unless BINFO is for an empty base class.
-static bool
-build_base_field (rli, binfo, empty_p, offsets, t)
- record_layout_info rli;
- tree binfo;
- int *empty_p;
- splay_tree offsets;
- tree t;
+ Returns the location at which the next field should be inserted. */
+
+static tree *
+build_base_field (record_layout_info rli, tree binfo,
+ splay_tree offsets, tree *next_field)
{
+ tree t = rli->t;
tree basetype = BINFO_TYPE (binfo);
- tree decl;
- bool atend = false;
if (!COMPLETE_TYPE_P (basetype))
/* This error is now reported in xref_tag, thus giving better
location information. */
- return atend;
+ return next_field;
- decl = build_decl (FIELD_DECL, NULL_TREE, basetype);
- DECL_ARTIFICIAL (decl) = 1;
- DECL_FIELD_CONTEXT (decl) = rli->t;
- DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
- DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
- DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
- DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
- /* Tell the backend not to round up to TYPE_ALIGN. */
- DECL_PACKED (decl) = 1;
-
- if (!integer_zerop (DECL_SIZE (decl)))
+ /* Place the base class. */
+ if (!is_empty_class (basetype))
{
+ tree decl;
+
/* The containing class is non-empty because it has a non-empty
base class. */
- *empty_p = 0;
+ CLASSTYPE_EMPTY_P (t) = 0;
+
+ /* Create the FIELD_DECL. */
+ decl = build_decl (FIELD_DECL, NULL_TREE, CLASSTYPE_AS_BASE (basetype));
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_FIELD_CONTEXT (decl) = t;
+ DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
+ DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
+ DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
+ DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
+ DECL_IGNORED_P (decl) = 1;
/* Try to place the field. It may take more than one try if we
have a hard time placing the field without putting two
objects of the same type at the same address. */
- layout_nonempty_base_or_field (rli, decl, binfo, offsets, t);
+ layout_nonempty_base_or_field (rli, decl, binfo, offsets);
+ /* Add the new FIELD_DECL to the list of fields for T. */
+ TREE_CHAIN (decl) = *next_field;
+ *next_field = decl;
+ next_field = &TREE_CHAIN (decl);
}
else
{
- unsigned HOST_WIDE_INT eoc;
+ tree eoc;
+ bool atend;
/* On some platforms (ARM), even empty classes will not be
byte-aligned. */
- eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
- eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl);
- atend |= layout_empty_base (binfo, size_int (eoc), offsets, t);
+ eoc = round_up (rli_size_unit_so_far (rli),
+ CLASSTYPE_ALIGN_UNIT (basetype));
+ atend = layout_empty_base (binfo, eoc, offsets, t);
+ /* A nearly-empty class "has no proper base class that is empty,
+ not morally virtual, and at an offset other than zero." */
+ if (!TREE_VIA_VIRTUAL (binfo) && CLASSTYPE_NEARLY_EMPTY_P (t))
+ {
+ if (atend)
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+ /* The check above (used in G++ 3.2) is insufficient because
+ an empty class placed at offset zero might itself have an
+ empty base at a nonzero offset. */
+ else if (walk_subobject_offsets (basetype,
+ empty_base_at_nonzero_offset_p,
+ size_zero_node,
+ /*offsets=*/NULL,
+ /*max_offset=*/NULL_TREE,
+ /*vbases_p=*/true))
+ {
+ if (abi_version_at_least (2))
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+ else if (warn_abi)
+ warning ("class `%T' will be considered nearly empty in a "
+ "future version of GCC", t);
+ }
+ }
+
+ /* We do not create a FIELD_DECL for empty base classes because
+ it might overlap some other field. We want to be able to
+ create CONSTRUCTORs for the class by iterating over the
+ FIELD_DECLs, and the back end does not handle overlapping
+ FIELD_DECLs. */
+
+ /* An empty virtual base causes a class to be non-empty
+ -- but in that case we do not need to clear CLASSTYPE_EMPTY_P
+ here because that was already done when the virtual table
+ pointer was created. */
}
/* Record the offsets of BINFO and its base subobjects. */
- record_subobject_offsets (BINFO_TYPE (binfo),
+ record_subobject_offsets (binfo,
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0);
- return atend;
+
+ return next_field;
}
/* Layout all of the non-virtual base classes. Record empty
- subobjects in OFFSETS. T is the most derived type. Return
- non-zero if the type cannot be nearly empty. */
+ subobjects in OFFSETS. T is the most derived type. Return nonzero
+ if the type cannot be nearly empty. The fields created
+ corresponding to the base classes will be inserted at
+ *NEXT_FIELD. */
-static bool
-build_base_fields (rli, empty_p, offsets, t)
- record_layout_info rli;
- int *empty_p;
- splay_tree offsets;
- tree t;
+static void
+build_base_fields (record_layout_info rli,
+ splay_tree offsets, tree *next_field)
{
/* Chain to hold all the new FIELD_DECLs which stand in for base class
subobjects. */
- tree rec = rli->t;
- int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
+ tree t = rli->t;
+ int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
int i;
- bool atend = 0;
/* The primary base class is always allocated first. */
- if (CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
- build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec),
- empty_p, offsets, t);
+ if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
+ next_field = build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (t),
+ offsets, next_field);
/* Now allocate the rest of the bases. */
for (i = 0; i < n_baseclasses; ++i)
{
tree base_binfo;
- base_binfo = BINFO_BASETYPE (TYPE_BINFO (rec), i);
+ base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
/* The primary base was already allocated above, so we don't
need to allocate it again here. */
- if (base_binfo == CLASSTYPE_PRIMARY_BINFO (rec))
+ if (base_binfo == CLASSTYPE_PRIMARY_BINFO (t))
continue;
/* A primary virtual base class is allocated just like any other
@@ -3883,9 +3970,9 @@ build_base_fields (rli, empty_p, offsets, t)
&& !BINFO_PRIMARY_P (base_binfo))
continue;
- atend |= build_base_field (rli, base_binfo, empty_p, offsets, t);
+ next_field = build_base_field (rli, base_binfo,
+ offsets, next_field);
}
- return atend;
}
/* Go through the TYPE_METHODS of T issuing any appropriate
@@ -4013,7 +4100,7 @@ build_clone (fn, name)
for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms))
{
DECL_CONTEXT (parms) = clone;
- copy_lang_decl (parms);
+ cxx_dup_lang_specific_decl (parms);
}
}
@@ -4043,7 +4130,7 @@ build_clone (fn, name)
}
/* Produce declarations for all appropriate clones of FN. If
- UPDATE_METHOD_VEC_P is non-zero, the clones are added to the
+ UPDATE_METHOD_VEC_P is nonzero, the clones are added to the
CLASTYPE_METHOD_VEC as well. */
void
@@ -4105,7 +4192,7 @@ clone_function_decl (fn, update_method_vec_p)
declared. An out-of-class definition can specify additional default
arguments. As it is the clones that are involved in overload
resolution, we must propagate the information from the DECL to its
- clones. */
+ clones. */
void
adjust_clone_args (decl)
@@ -4122,7 +4209,7 @@ adjust_clone_args (decl)
clone_parms = orig_clone_parms;
- /* Skip the 'this' parameter. */
+ /* Skip the 'this' parameter. */
orig_clone_parms = TREE_CHAIN (orig_clone_parms);
orig_decl_parms = TREE_CHAIN (orig_decl_parms);
@@ -4145,7 +4232,7 @@ adjust_clone_args (decl)
if (TREE_PURPOSE (decl_parms) && !TREE_PURPOSE (clone_parms))
{
/* A default parameter has been added. Adjust the
- clone's parameters. */
+ clone's parameters. */
tree exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone));
tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone));
tree type;
@@ -4244,7 +4331,7 @@ type_requires_array_cookie (type)
if (!fns || fns == error_mark_node)
return false;
/* Loop through all of the functions. */
- for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
+ for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
{
tree fn;
tree second_parm;
@@ -4274,9 +4361,7 @@ type_requires_array_cookie (type)
level: i.e., independently of the ABI in use. */
static void
-check_bases_and_members (t, empty_p)
- tree t;
- int *empty_p;
+check_bases_and_members (tree t)
{
/* Nonzero if we are not allowed to generate a default constructor
for this case. */
@@ -4295,17 +4380,12 @@ check_bases_and_members (t, empty_p)
cant_have_const_ctor = 0;
no_const_asn_ref = 0;
- /* Assume that the class is nearly empty; we'll clear this flag if
- it turns out not to be nearly empty. */
- CLASSTYPE_NEARLY_EMPTY_P (t) = 1;
- CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 0;
-
- /* Check all the base-classes. */
+ /* Check all the base-classes. */
check_bases (t, &cant_have_default_ctor, &cant_have_const_ctor,
&no_const_asn_ref);
/* Check all the data member declarations. */
- check_field_decls (t, &access_decls, empty_p,
+ check_field_decls (t, &access_decls,
&cant_have_default_ctor,
&cant_have_const_ctor,
&no_const_asn_ref);
@@ -4356,7 +4436,7 @@ check_bases_and_members (t, empty_p)
/* Figure out whether or not we will need a cookie when dynamically
allocating an array of this type. */
- TYPE_LANG_SPECIFIC (t)->vec_new_uses_cookie
+ TYPE_LANG_SPECIFIC (t)->u.c.vec_new_uses_cookie
= type_requires_array_cookie (t);
}
@@ -4368,10 +4448,8 @@ check_bases_and_members (t, empty_p)
on VIRTUALS_P. */
static tree
-create_vtable_ptr (t, empty_p, vfuns_p, virtuals_p)
+create_vtable_ptr (t, virtuals_p)
tree t;
- int *empty_p;
- int *vfuns_p;
tree *virtuals_p;
{
tree fn;
@@ -4429,7 +4507,7 @@ create_vtable_ptr (t, empty_p, vfuns_p, virtuals_p)
TYPE_VFIELD (t) = field;
/* This class is non-empty. */
- *empty_p = 0;
+ CLASSTYPE_EMPTY_P (t) = 0;
if (CLASSTYPE_N_BASECLASSES (t))
/* If there were any baseclasses, they can't possibly be at
@@ -4578,33 +4656,41 @@ dfs_set_offset_for_unshared_vbases (binfo, data)
return NULL_TREE;
}
-/* Set BINFO_OFFSET for all of the virtual bases for T. Update
+/* Set BINFO_OFFSET for all of the virtual bases for RLI->T. Update
TYPE_ALIGN and TYPE_SIZE for T. OFFSETS gives the location of
empty subobjects of T. */
static void
-layout_virtual_bases (t, offsets)
- tree t;
- splay_tree offsets;
+layout_virtual_bases (record_layout_info rli, splay_tree offsets)
{
- tree vbases, dsize;
- unsigned HOST_WIDE_INT eoc;
+ tree vbases;
+ tree t = rli->t;
bool first_vbase = true;
+ tree *next_field;
if (CLASSTYPE_N_BASECLASSES (t) == 0)
return;
+ if (!abi_version_at_least(2))
+ {
+ /* In G++ 3.2, we incorrectly rounded the size before laying out
+ the virtual bases. */
+ finish_record_layout (rli, /*free_p=*/false);
#ifdef STRUCTURE_SIZE_BOUNDARY
- /* Packed structures don't need to have minimum size. */
- if (! TYPE_PACKED (t))
- TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY);
+ /* Packed structures don't need to have minimum size. */
+ if (! TYPE_PACKED (t))
+ TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY);
#endif
+ rli->offset = TYPE_SIZE_UNIT (t);
+ rli->bitpos = bitsize_zero_node;
+ rli->record_align = TYPE_ALIGN (t);
+ }
- /* DSIZE is the size of the class without the virtual bases. */
- dsize = TYPE_SIZE (t);
-
- /* Make every class have alignment of at least one. */
- TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
+ /* Find the last field. The artificial fields created for virtual
+ bases will go after the last extant field to date. */
+ next_field = &TYPE_FIELDS (t);
+ while (*next_field)
+ next_field = &TREE_CHAIN (*next_field);
/* Go through the virtual bases, allocating space for each virtual
base that is not already a primary base class. These are
@@ -4622,45 +4708,12 @@ layout_virtual_bases (t, offsets)
if (!BINFO_PRIMARY_P (vbase))
{
+ tree basetype = TREE_TYPE (vbase);
+
/* This virtual base is not a primary base of any class in the
hierarchy, so we have to add space for it. */
- tree basetype, usize;
- unsigned int desired_align;
-
- basetype = BINFO_TYPE (vbase);
-
- desired_align = CLASSTYPE_ALIGN (basetype);
- TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
-
- /* Add padding so that we can put the virtual base class at an
- appropriately aligned offset. */
- dsize = round_up (dsize, desired_align);
- usize = size_binop (CEIL_DIV_EXPR, dsize, bitsize_unit_node);
-
- /* We try to squish empty virtual bases in just like
- ordinary empty bases. */
- if (is_empty_class (basetype))
- layout_empty_base (vbase,
- convert (sizetype, usize),
- offsets, t);
- else
- {
- tree offset;
-
- offset = convert (ssizetype, usize);
- offset = size_diffop (offset,
- convert (ssizetype,
- BINFO_OFFSET (vbase)));
-
- /* And compute the offset of the virtual base. */
- propagate_binfo_offsets (vbase, offset, t);
- /* Every virtual baseclass takes a least a UNIT, so that
- we can take it's address and get something different
- for each base. */
- dsize = size_binop (PLUS_EXPR, dsize,
- size_binop (MAX_EXPR, bitsize_unit_node,
- CLASSTYPE_SIZE (basetype)));
- }
+ next_field = build_base_field (rli, vbase,
+ offsets, next_field);
/* If the first virtual base might have been placed at a
lower address, had we started from CLASSTYPE_SIZE, rather
@@ -4671,20 +4724,15 @@ layout_virtual_bases (t, offsets)
the results which is not particularly tractable. */
if (warn_abi
&& first_vbase
- && tree_int_cst_lt (size_binop (CEIL_DIV_EXPR,
- round_up (CLASSTYPE_SIZE (t),
- desired_align),
- bitsize_unit_node),
- BINFO_OFFSET (vbase)))
+ && (tree_int_cst_lt
+ (size_binop (CEIL_DIV_EXPR,
+ round_up (CLASSTYPE_SIZE (t),
+ CLASSTYPE_ALIGN (basetype)),
+ bitsize_unit_node),
+ BINFO_OFFSET (vbase))))
warning ("offset of virtual base `%T' is not ABI-compliant and may change in a future version of GCC",
basetype);
- /* Keep track of the offsets assigned to this virtual base. */
- record_subobject_offsets (BINFO_TYPE (vbase),
- BINFO_OFFSET (vbase),
- offsets,
- /*vbases_p=*/0);
-
first_vbase = false;
}
}
@@ -4695,80 +4743,70 @@ layout_virtual_bases (t, offsets)
in lookup_base depend on the BINFO_OFFSETs being set
correctly. */
dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
+}
- /* If we had empty base classes that protruded beyond the end of the
- class, we didn't update DSIZE above; we were hoping to overlay
- multiple such bases at the same location. */
- eoc = end_of_class (t, /*include_virtuals_p=*/1);
- dsize = size_binop (MAX_EXPR, dsize, bitsize_int (eoc * BITS_PER_UNIT));
+/* Returns the offset of the byte just past the end of the base class
+ BINFO. */
- /* Now, make sure that the total size of the type is a multiple of
- its alignment. */
- dsize = round_up (dsize, TYPE_ALIGN (t));
- TYPE_SIZE (t) = dsize;
- TYPE_SIZE_UNIT (t) = convert (sizetype,
- size_binop (CEIL_DIV_EXPR, TYPE_SIZE (t),
- bitsize_unit_node));
+static tree
+end_of_base (tree binfo)
+{
+ tree size;
- /* Check for ambiguous virtual bases. */
- if (extra_warnings)
- for (vbases = CLASSTYPE_VBASECLASSES (t);
- vbases;
- vbases = TREE_CHAIN (vbases))
- {
- tree basetype = BINFO_TYPE (TREE_VALUE (vbases));
-
- if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
- warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
- basetype, t);
- }
+ if (is_empty_class (BINFO_TYPE (binfo)))
+ /* An empty class has zero CLASSTYPE_SIZE_UNIT, but we need to
+ allocate some space for it. It cannot have virtual bases, so
+ TYPE_SIZE_UNIT is fine. */
+ size = TYPE_SIZE_UNIT (BINFO_TYPE (binfo));
+ else
+ size = CLASSTYPE_SIZE_UNIT (BINFO_TYPE (binfo));
+
+ return size_binop (PLUS_EXPR, BINFO_OFFSET (binfo), size);
}
/* Returns the offset of the byte just past the end of the base class
with the highest offset in T. If INCLUDE_VIRTUALS_P is zero, then
only non-virtual bases are included. */
-static unsigned HOST_WIDE_INT
+static tree
end_of_class (t, include_virtuals_p)
tree t;
int include_virtuals_p;
{
- unsigned HOST_WIDE_INT result = 0;
+ tree result = size_zero_node;
+ tree binfo;
+ tree offset;
int i;
for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
{
- tree base_binfo;
- tree offset;
- tree size;
- unsigned HOST_WIDE_INT end_of_base;
-
- base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
+ binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
if (!include_virtuals_p
- && TREE_VIA_VIRTUAL (base_binfo)
- && !BINFO_PRIMARY_P (base_binfo))
+ && TREE_VIA_VIRTUAL (binfo)
+ && BINFO_PRIMARY_BASE_OF (binfo) != TYPE_BINFO (t))
continue;
- if (is_empty_class (BINFO_TYPE (base_binfo)))
- /* An empty class has zero CLASSTYPE_SIZE_UNIT, but we need to
- allocate some space for it. It cannot have virtual bases,
- so TYPE_SIZE_UNIT is fine. */
- size = TYPE_SIZE_UNIT (BINFO_TYPE (base_binfo));
- else
- size = CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo));
- offset = size_binop (PLUS_EXPR,
- BINFO_OFFSET (base_binfo),
- size);
- end_of_base = tree_low_cst (offset, /*pos=*/1);
- if (end_of_base > result)
- result = end_of_base;
+ offset = end_of_base (binfo);
+ if (INT_CST_LT_UNSIGNED (result, offset))
+ result = offset;
}
+ /* G++ 3.2 did not check indirect virtual bases. */
+ if (abi_version_at_least (2) && include_virtuals_p)
+ for (binfo = CLASSTYPE_VBASECLASSES (t);
+ binfo;
+ binfo = TREE_CHAIN (binfo))
+ {
+ offset = end_of_base (TREE_VALUE (binfo));
+ if (INT_CST_LT_UNSIGNED (result, offset))
+ result = offset;
+ }
+
return result;
}
-/* Warn about direct bases of T that are inaccessible because they are
+/* Warn about bases of T that are inaccessible because they are
ambiguous. For example:
struct S {};
@@ -4779,19 +4817,35 @@ end_of_class (t, include_virtuals_p)
subobjects of U. */
static void
-warn_about_ambiguous_direct_bases (t)
+warn_about_ambiguous_bases (t)
tree t;
{
int i;
+ tree vbases;
+ tree basetype;
+ /* Check direct bases. */
for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
{
- tree basetype = TYPE_BINFO_BASETYPE (t, i);
+ basetype = TYPE_BINFO_BASETYPE (t, i);
if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
- basetype, t);
+ basetype, t);
}
+
+ /* Check for ambiguous virtual bases. */
+ if (extra_warnings)
+ for (vbases = CLASSTYPE_VBASECLASSES (t);
+ vbases;
+ vbases = TREE_CHAIN (vbases))
+ {
+ basetype = BINFO_TYPE (TREE_VALUE (vbases));
+
+ if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
+ warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
+ basetype, t);
+ }
}
/* Compare two INTEGER_CSTs K1 and K2. */
@@ -4804,27 +4858,59 @@ splay_tree_compare_integer_csts (k1, k2)
return tree_int_cst_compare ((tree) k1, (tree) k2);
}
+/* Increase the size indicated in RLI to account for empty classes
+ that are "off the end" of the class. */
+
+static void
+include_empty_classes (record_layout_info rli)
+{
+ tree eoc;
+ tree rli_size;
+
+ /* It might be the case that we grew the class to allocate a
+ zero-sized base class. That won't be reflected in RLI, yet,
+ because we are willing to overlay multiple bases at the same
+ offset. However, now we need to make sure that RLI is big enough
+ to reflect the entire class. */
+ eoc = end_of_class (rli->t,
+ CLASSTYPE_AS_BASE (rli->t) != NULL_TREE);
+ rli_size = rli_size_unit_so_far (rli);
+ if (TREE_CODE (rli_size) == INTEGER_CST
+ && INT_CST_LT_UNSIGNED (rli_size, eoc))
+ {
+ rli->bitpos = round_up (rli->bitpos, BITS_PER_UNIT);
+ rli->bitpos
+ = size_binop (PLUS_EXPR,
+ rli->bitpos,
+ size_binop (MULT_EXPR,
+ convert (bitsizetype,
+ size_binop (MINUS_EXPR,
+ eoc, rli_size)),
+ bitsize_int (BITS_PER_UNIT)));
+ normalize_rli (rli);
+ }
+}
+
/* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T. Calculate
BINFO_OFFSETs for all of the base-classes. Position the vtable
- pointer. Accumulate declared virtual functions on VIRTUALS_P. */
+ pointer. Accumulate declared virtual functions on VIRTUALS_P. */
static void
-layout_class_type (t, empty_p, vfuns_p, virtuals_p)
- tree t;
- int *empty_p;
- int *vfuns_p;
- tree *virtuals_p;
+layout_class_type (tree t, tree *virtuals_p)
{
tree non_static_data_members;
tree field;
tree vptr;
record_layout_info rli;
- unsigned HOST_WIDE_INT eoc;
/* Maps offsets (represented as INTEGER_CSTs) to a TREE_LIST of
types that appear at that offset. */
splay_tree empty_base_offsets;
/* True if the last field layed out was a bit-field. */
bool last_field_was_bitfield = false;
+ /* The location at which the next field should be inserted. */
+ tree *next_field;
+ /* T, as a base class. */
+ tree base_t;
/* Keep track of the first non-static data member. */
non_static_data_members = TYPE_FIELDS (t);
@@ -4834,23 +4920,26 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
/* If possible, we reuse the virtual function table pointer from one
of our base classes. */
- determine_primary_base (t, vfuns_p);
+ determine_primary_base (t);
/* Create a pointer to our virtual function table. */
- vptr = create_vtable_ptr (t, empty_p, vfuns_p, virtuals_p);
+ vptr = create_vtable_ptr (t, virtuals_p);
/* The vptr is always the first thing in the class. */
if (vptr)
{
- TYPE_FIELDS (t) = chainon (vptr, TYPE_FIELDS (t));
+ TREE_CHAIN (vptr) = TYPE_FIELDS (t);
+ TYPE_FIELDS (t) = vptr;
+ next_field = &TREE_CHAIN (vptr);
place_field (rli, vptr);
}
+ else
+ next_field = &TYPE_FIELDS (t);
/* Build FIELD_DECLs for all of the non-virtual base-types. */
empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts,
NULL, NULL);
- if (build_base_fields (rli, empty_p, empty_base_offsets, t))
- CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+ build_base_fields (rli, empty_base_offsets, next_field);
/* Layout the non-static data members. */
for (field = non_static_data_members; field; field = TREE_CHAIN (field))
@@ -4902,17 +4991,44 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
field. We have to back up by one to find the largest
type that fits. */
integer_type = integer_types[itk - 1];
- padding = size_binop (MINUS_EXPR, DECL_SIZE (field),
- TYPE_SIZE (integer_type));
+
+ if (abi_version_at_least (2) && TREE_CODE (t) == UNION_TYPE)
+ /* In a union, the padding field must have the full width
+ of the bit-field; all fields start at offset zero. */
+ padding = DECL_SIZE (field);
+ else
+ {
+ if (warn_abi && TREE_CODE (t) == UNION_TYPE)
+ warning ("size assigned to `%T' may not be "
+ "ABI-compliant and may change in a future "
+ "version of GCC",
+ t);
+ padding = size_binop (MINUS_EXPR, DECL_SIZE (field),
+ TYPE_SIZE (integer_type));
+ }
DECL_SIZE (field) = TYPE_SIZE (integer_type);
DECL_ALIGN (field) = TYPE_ALIGN (integer_type);
DECL_USER_ALIGN (field) = TYPE_USER_ALIGN (integer_type);
+ layout_nonempty_base_or_field (rli, field, NULL_TREE,
+ empty_base_offsets);
+ /* Now that layout has been performed, set the size of the
+ field to the size of its declared type; the rest of the
+ field is effectively invisible. */
+ DECL_SIZE (field) = TYPE_SIZE (type);
}
else
- padding = NULL_TREE;
+ {
+ padding = NULL_TREE;
+ layout_nonempty_base_or_field (rli, field, NULL_TREE,
+ empty_base_offsets);
+ }
- layout_nonempty_base_or_field (rli, field, NULL_TREE,
- empty_base_offsets, t);
+ /* Remember the location of any empty classes in FIELD. */
+ if (abi_version_at_least (2))
+ record_subobject_offsets (TREE_TYPE (field),
+ byte_position(field),
+ empty_base_offsets,
+ /*vbases_p=*/1);
/* If a bit-field does not immediately follow another bit-field,
and yet it starts in the middle of a byte, we have failed to
@@ -4926,6 +5042,17 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
cp_warning_at ("offset of `%D' is not ABI-compliant and may change in a future version of GCC",
field);
+ /* G++ used to use DECL_FIELD_OFFSET as if it were the byte
+ offset of the field. */
+ if (warn_abi
+ && !tree_int_cst_equal (DECL_FIELD_OFFSET (field),
+ byte_position (field))
+ && contains_empty_class_p (TREE_TYPE (field)))
+ cp_warning_at ("`%D' contains empty classes which may cause base "
+ "classes to be placed at different locations in a "
+ "future version of GCC",
+ field);
+
/* If we needed additional padding after this field, add it
now. */
if (padding)
@@ -4941,73 +5068,102 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
DECL_USER_ALIGN (padding_field) = 0;
layout_nonempty_base_or_field (rli, padding_field,
NULL_TREE,
- empty_base_offsets, t);
+ empty_base_offsets);
}
last_field_was_bitfield = DECL_C_BIT_FIELD (field);
}
- /* It might be the case that we grew the class to allocate a
- zero-sized base class. That won't be reflected in RLI, yet,
- because we are willing to overlay multiple bases at the same
- offset. However, now we need to make sure that RLI is big enough
- to reflect the entire class. */
- eoc = end_of_class (t, /*include_virtuals_p=*/0);
- if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST
- && compare_tree_int (rli_size_unit_so_far (rli), eoc) < 0)
- {
- rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc));
- rli->bitpos = bitsize_zero_node;
- }
-
- /* We make all structures have at least one element, so that they
- have non-zero size. The class may be empty even if it has
- basetypes. Therefore, we add the fake field after all the other
- fields; if there are already FIELD_DECLs on the list, their
- offsets will not be disturbed. */
- if (!eoc && *empty_p)
+ if (abi_version_at_least (2) && !integer_zerop (rli->bitpos))
{
- tree padding;
-
- padding = build_decl (FIELD_DECL, NULL_TREE, char_type_node);
- place_field (rli, padding);
+ /* Make sure that we are on a byte boundary so that the size of
+ the class without virtual bases will always be a round number
+ of bytes. */
+ rli->bitpos = round_up (rli->bitpos, BITS_PER_UNIT);
+ normalize_rli (rli);
}
- /* Let the back-end lay out the type. Note that at this point we
- have only included non-virtual base-classes; we will lay out the
- virtual base classes later. So, the TYPE_SIZE/TYPE_ALIGN after
- this call are not necessarily correct; they are just the size and
- alignment when no virtual base clases are used. */
- finish_record_layout (rli);
+ /* G++ 3.2 does not allow virtual bases to be overlaid with tail
+ padding. */
+ if (!abi_version_at_least (2))
+ include_empty_classes(rli);
/* Delete all zero-width bit-fields from the list of fields. Now
that the type is laid out they are no longer important. */
remove_zero_width_bit_fields (t);
- /* Remember the size and alignment of the class before adding
- the virtual bases. */
- if (*empty_p)
- {
- CLASSTYPE_SIZE (t) = bitsize_zero_node;
- CLASSTYPE_SIZE_UNIT (t) = size_zero_node;
- }
- /* If this is a POD, we can't reuse its tail padding. */
- else if (!CLASSTYPE_NON_POD_P (t))
+ /* Create the version of T used for virtual bases. We do not use
+ make_aggr_type for this version; this is an artificial type. For
+ a POD type, we just reuse T. */
+ if (CLASSTYPE_NON_POD_P (t) || CLASSTYPE_EMPTY_P (t))
{
- CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
- CLASSTYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (t);
+ base_t = make_node (TREE_CODE (t));
+
+ /* Set the size and alignment for the new type. In G++ 3.2, all
+ empty classes were considered to have size zero when used as
+ base classes. */
+ if (!abi_version_at_least (2) && CLASSTYPE_EMPTY_P (t))
+ {
+ TYPE_SIZE (base_t) = bitsize_zero_node;
+ TYPE_SIZE_UNIT (base_t) = size_zero_node;
+ if (warn_abi && !integer_zerop (rli_size_unit_so_far (rli)))
+ warning ("layout of classes derived from empty class `%T' "
+ "may change in a future version of GCC",
+ t);
+ }
+ else
+ {
+ tree eoc;
+
+ /* If the ABI version is not at least two, and the last
+ field was a bit-field, RLI may not be on a byte
+ boundary. In particular, rli_size_unit_so_far might
+ indicate the last complete byte, while rli_size_so_far
+ indicates the total number of bits used. Therefore,
+ rli_size_so_far, rather than rli_size_unit_so_far, is
+ used to compute TYPE_SIZE_UNIT. */
+ eoc = end_of_class (t, /*include_virtuals_p=*/0);
+ TYPE_SIZE_UNIT (base_t)
+ = size_binop (MAX_EXPR,
+ convert (sizetype,
+ size_binop (CEIL_DIV_EXPR,
+ rli_size_so_far (rli),
+ bitsize_int (BITS_PER_UNIT))),
+ eoc);
+ TYPE_SIZE (base_t)
+ = size_binop (MAX_EXPR,
+ rli_size_so_far (rli),
+ size_binop (MULT_EXPR,
+ convert (bitsizetype, eoc),
+ bitsize_int (BITS_PER_UNIT)));
+ }
+ TYPE_ALIGN (base_t) = rli->record_align;
+ TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);
+
+ /* Copy the fields from T. */
+ next_field = &TYPE_FIELDS (base_t);
+ for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL)
+ {
+ *next_field = build_decl (FIELD_DECL,
+ DECL_NAME (field),
+ TREE_TYPE (field));
+ DECL_CONTEXT (*next_field) = base_t;
+ DECL_FIELD_OFFSET (*next_field) = DECL_FIELD_OFFSET (field);
+ DECL_FIELD_BIT_OFFSET (*next_field)
+ = DECL_FIELD_BIT_OFFSET (field);
+ next_field = &TREE_CHAIN (*next_field);
+ }
+
+ /* Record the base version of the type. */
+ CLASSTYPE_AS_BASE (t) = base_t;
+ TYPE_CONTEXT (base_t) = t;
}
else
- {
- CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
- CLASSTYPE_SIZE_UNIT (t) = TYPE_BINFO_SIZE_UNIT (t);
- }
-
- CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t);
- CLASSTYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (t);
+ CLASSTYPE_AS_BASE (t) = t;
/* Every empty class contains an empty class. */
- if (*empty_p)
+ if (CLASSTYPE_EMPTY_P (t))
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 1;
/* Set the TYPE_DECL for this type to contain the right
@@ -5019,54 +5175,63 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
around. We must get these done before we try to lay out the
virtual function table. As a side-effect, this will remove the
base subobject fields. */
- layout_virtual_bases (t, empty_base_offsets);
+ layout_virtual_bases (rli, empty_base_offsets);
- /* Warn about direct bases that can't be talked about due to
- ambiguity. */
- warn_about_ambiguous_direct_bases (t);
+ /* Make sure that empty classes are reflected in RLI at this
+ point. */
+ include_empty_classes(rli);
+
+ /* Make sure not to create any structures with zero size. */
+ if (integer_zerop (rli_size_unit_so_far (rli)) && CLASSTYPE_EMPTY_P (t))
+ place_field (rli,
+ build_decl (FIELD_DECL, NULL_TREE, char_type_node));
+
+ /* Let the back-end lay out the type. */
+ finish_record_layout (rli, /*free_p=*/true);
+
+ /* Warn about bases that can't be talked about due to ambiguity. */
+ warn_about_ambiguous_bases (t);
/* Clean up. */
splay_tree_delete (empty_base_offsets);
}
-/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
- (or C++ class declaration).
+/* Returns the virtual function with which the vtable for TYPE is
+ emitted, or NULL_TREE if that heuristic is not applicable to TYPE. */
+
+static tree
+key_method (tree type)
+{
+ tree method;
- For C++, we must handle the building of derived classes.
- Also, C++ allows static class members. The way that this is
- handled is to keep the field name where it is (as the DECL_NAME
- of the field), and place the overloaded decl in the bit position
- of the field. layout_record and layout_union will know about this.
+ if (TYPE_FOR_JAVA (type)
+ || processing_template_decl
+ || CLASSTYPE_TEMPLATE_INSTANTIATION (type)
+ || CLASSTYPE_INTERFACE_KNOWN (type))
+ return NULL_TREE;
- More C++ hair: inline functions have text in their
- DECL_PENDING_INLINE_INFO nodes which must somehow be parsed into
- meaningful tree structure. After the struct has been laid out, set
- things up so that this can happen.
+ for (method = TYPE_METHODS (type); method != NULL_TREE;
+ method = TREE_CHAIN (method))
+ if (DECL_VINDEX (method) != NULL_TREE
+ && ! DECL_DECLARED_INLINE_P (method)
+ && ! DECL_PURE_VIRTUAL_P (method))
+ return method;
- And still more: virtual functions. In the case of single inheritance,
- when a new virtual function is seen which redefines a virtual function
- from the base class, the new virtual function is placed into
- the virtual function table at exactly the same address that
- it had in the base class. When this is extended to multiple
- inheritance, the same thing happens, except that multiple virtual
- function tables must be maintained. The first virtual function
- table is treated in exactly the same way as in the case of single
- inheritance. Additional virtual function tables have different
- DELTAs, which tell how to adjust `this' to point to the right thing.
+ return NULL_TREE;
+}
- ATTRIBUTES is the set of decl attributes to be applied, if any. */
+/* Perform processing required when the definition of T (a class type)
+ is complete. */
void
finish_struct_1 (t)
tree t;
{
tree x;
- int vfuns;
- /* A TREE_LIST. The TREE_VALUE of each node is a FUNCTION_DECL. */
+ /* A TREE_LIST. The TREE_VALUE of each node is a FUNCTION_DECL. */
tree virtuals = NULL_TREE;
int n_fields = 0;
tree vfield;
- int empty = 1;
if (COMPLETE_TYPE_P (t))
{
@@ -5083,17 +5248,32 @@ finish_struct_1 (t)
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
- vfuns = 0;
- CLASSTYPE_RTTI (t) = NULL_TREE;
fixup_inline_methods (t);
+ /* Make assumptions about the class; we'll reset the flags if
+ necessary. */
+ CLASSTYPE_EMPTY_P (t) = 1;
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 1;
+ CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 0;
+
/* Do end-of-class semantic processing: checking the validity of the
bases and members and add implicitly generated methods. */
- check_bases_and_members (t, &empty);
+ check_bases_and_members (t);
+
+ /* Find the key method */
+ if (TYPE_CONTAINS_VPTR_P (t))
+ {
+ CLASSTYPE_KEY_METHOD (t) = key_method (t);
+
+ /* If a polymorphic class has no key method, we may emit the vtable
+ in every translation unit where the class definition appears. */
+ if (CLASSTYPE_KEY_METHOD (t) == NULL_TREE)
+ keyed_classes = tree_cons (NULL_TREE, t, keyed_classes);
+ }
/* Layout the class itself. */
- layout_class_type (t, &empty, &vfuns, &virtuals);
+ layout_class_type (t, &virtuals);
/* Make sure that we get our own copy of the vfield FIELD_DECL. */
vfield = TYPE_VFIELD (t);
@@ -5104,7 +5284,7 @@ finish_struct_1 (t)
my_friendly_assert (same_type_p (DECL_FIELD_CONTEXT (vfield),
BINFO_TYPE (primary)),
20010726);
- /* The vtable better be at the start. */
+ /* The vtable better be at the start. */
my_friendly_assert (integer_zerop (DECL_FIELD_OFFSET (vfield)),
20010726);
my_friendly_assert (integer_zerop (BINFO_OFFSET (primary)),
@@ -5117,7 +5297,7 @@ finish_struct_1 (t)
else
my_friendly_assert (!vfield || DECL_FIELD_CONTEXT (vfield) == t, 20010726);
- virtuals = modify_all_vtables (t, &vfuns, nreverse (virtuals));
+ virtuals = modify_all_vtables (t, nreverse (virtuals));
/* If we created a new vtbl pointer for this class, add it to the
list. */
@@ -5135,28 +5315,13 @@ finish_struct_1 (t)
/* Here we know enough to change the type of our virtual
function table, but we will wait until later this function. */
build_primary_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);
-
- /* If this type has basetypes with constructors, then those
- constructors might clobber the virtual function table. But
- they don't if the derived class shares the exact vtable of the base
- class. */
- CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
- }
- /* If we didn't need a new vtable, see if we should copy one from
- the base. */
- else if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- {
- tree binfo = CLASSTYPE_PRIMARY_BINFO (t);
-
- /* If this class uses a different vtable than its primary base
- then when we will need to initialize our vptr after the base
- class constructor runs. */
- if (TYPE_BINFO_VTABLE (t) != BINFO_VTABLE (binfo))
- CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
}
if (TYPE_CONTAINS_VPTR_P (t))
{
+ int vindex;
+ tree fn;
+
if (TYPE_BINFO_VTABLE (t))
my_friendly_assert (DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)),
20000116);
@@ -5164,9 +5329,17 @@ finish_struct_1 (t)
my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE,
20000116);
- CLASSTYPE_VSIZE (t) = vfuns;
/* Add entries for virtual functions introduced by this class. */
TYPE_BINFO_VIRTUALS (t) = chainon (TYPE_BINFO_VIRTUALS (t), virtuals);
+
+ /* Set DECL_VINDEX for all functions declared in this class. */
+ for (vindex = 0, fn = BINFO_VIRTUALS (TYPE_BINFO (t));
+ fn;
+ fn = TREE_CHAIN (fn),
+ vindex += (TARGET_VTABLE_USES_DESCRIPTORS
+ ? TARGET_VTABLE_USES_DESCRIPTORS : 1))
+ if (TREE_CODE (DECL_VINDEX (BV_FN (fn))) != INTEGER_CST)
+ DECL_VINDEX (BV_FN (fn)) = build_shared_int_cst (vindex);
}
finish_struct_bits (t);
@@ -5181,8 +5354,7 @@ finish_struct_1 (t)
/* Done with FIELDS...now decide whether to sort these for
faster lookups later.
- The C front-end only does this when n_fields > 15. We use
- a smaller number because most searches fail (succeeding
+ We use a small number because most searches fail (succeeding
ultimately as the search bores through the inheritance
hierarchy), and we want this failure to occur quickly. */
@@ -5202,15 +5374,13 @@ finish_struct_1 (t)
{
tree vfields = CLASSTYPE_VFIELDS (t);
- while (vfields)
- {
- /* Mark the fact that constructor for T
- could affect anybody inheriting from T
- who wants to initialize vtables for VFIELDS's type. */
- if (VF_DERIVED_VALUE (vfields))
- TREE_ADDRESSABLE (vfields) = 1;
- vfields = TREE_CHAIN (vfields);
- }
+ for (vfields = CLASSTYPE_VFIELDS (t);
+ vfields; vfields = TREE_CHAIN (vfields))
+ /* Mark the fact that constructor for T could affect anybody
+ inheriting from T who wants to initialize vtables for
+ VFIELDS's type. */
+ if (VF_BINFO_VALUE (vfields))
+ TREE_ADDRESSABLE (vfields) = 1;
}
/* Make the rtl for any new vtables we have created, and unmark
@@ -5248,10 +5418,10 @@ unreverse_member_declarations (t)
tree prev;
tree x;
- /* The TYPE_FIELDS, TYPE_METHODS, and CLASSTYPE_TAGS are all in
- reverse order. Put them in declaration order now. */
+ /* The following lists are all in reverse order. Put them in
+ declaration order now. */
TYPE_METHODS (t) = nreverse (TYPE_METHODS (t));
- CLASSTYPE_TAGS (t) = nreverse (CLASSTYPE_TAGS (t));
+ CLASSTYPE_DECL_LIST (t) = nreverse (CLASSTYPE_DECL_LIST (t));
/* Actually, for the TYPE_FIELDS, only the non TYPE_DECLs are in
reverse order, so we can't just use nreverse. */
@@ -5308,12 +5478,8 @@ finish_struct (t, attributes)
else
error ("trying to finish struct, but kicked out due to previous parse errors");
- if (processing_template_decl)
- {
- tree scope = current_scope ();
- if (scope && TREE_CODE (scope) == FUNCTION_DECL)
- add_stmt (build_min (TAG_DEFN, t));
- }
+ if (processing_template_decl && at_function_scope_p ())
+ add_stmt (build_min (TAG_DEFN, t));
return t;
}
@@ -5370,7 +5536,7 @@ fixed_type_or_null (instance, nonnull, cdtorp)
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
if (TREE_CODE (TREE_OPERAND (instance, 1)) == INTEGER_CST)
/* Propagate nonnull. */
- fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
return NULL_TREE;
case NOP_EXPR:
@@ -5397,6 +5563,7 @@ fixed_type_or_null (instance, nonnull, cdtorp)
/* fall through... */
case TARGET_EXPR:
case PARM_DECL:
+ case RESULT_DECL:
if (IS_AGGR_TYPE (TREE_TYPE (instance)))
{
if (nonnull)
@@ -5408,7 +5575,7 @@ fixed_type_or_null (instance, nonnull, cdtorp)
if (nonnull)
*nonnull = 1;
- /* if we're in a ctor or dtor, we know our type. */
+ /* if we're in a ctor or dtor, we know our type. */
if (DECL_LANG_SPECIFIC (current_function_decl)
&& (DECL_CONSTRUCTOR_P (current_function_decl)
|| DECL_DESTRUCTOR_P (current_function_decl)))
@@ -5423,6 +5590,21 @@ fixed_type_or_null (instance, nonnull, cdtorp)
/* Reference variables should be references to objects. */
if (nonnull)
*nonnull = 1;
+
+ /* DECL_VAR_MARKED_P is used to prevent recursion; a
+ variable's initializer may refer to the variable
+ itself. */
+ if (TREE_CODE (instance) == VAR_DECL
+ && DECL_INITIAL (instance)
+ && !DECL_VAR_MARKED_P (instance))
+ {
+ tree type;
+ DECL_VAR_MARKED_P (instance) = 1;
+ type = fixed_type_or_null (DECL_INITIAL (instance),
+ nonnull, cdtorp);
+ DECL_VAR_MARKED_P (instance) = 0;
+ return type;
+ }
}
return NULL_TREE;
@@ -5431,7 +5613,7 @@ fixed_type_or_null (instance, nonnull, cdtorp)
}
}
-/* Return non-zero if the dynamic type of INSTANCE is known, and
+/* Return nonzero if the dynamic type of INSTANCE is known, and
equivalent to the static type. We also handle the case where
INSTANCE is really a pointer. Return negative if this is a
ctor/dtor. There the dynamic type is known, but this might not be
@@ -5473,7 +5655,6 @@ init_class_processing ()
= (class_stack_node_t) xmalloc (current_class_stack_size
* sizeof (struct class_stack_node));
VARRAY_TREE_INIT (local_classes, 8, "local_classes");
- ggc_add_tree_varray_root (&local_classes, 1);
access_default_node = build_int_2 (0, 0);
access_public_node = build_int_2 (ak_public, 0);
@@ -5601,7 +5782,7 @@ pushclass (type, modify)
unuse_fields (type);
}
- storetags (CLASSTYPE_TAGS (type));
+ cxx_remember_type_decls (CLASSTYPE_NESTED_UDTS (type));
}
}
@@ -5630,8 +5811,6 @@ void
popclass ()
{
poplevel_class ();
- /* Since poplevel_class does the popping of class decls nowadays,
- this really only frees the obstack used for these decls. */
pop_class_decls ();
current_class_depth--;
@@ -5748,7 +5927,7 @@ push_lang_context (name)
/* DECL_IGNORED_P is initially set for these types, to avoid clutter.
(See record_builtin_java_type in decl.c.) However, that causes
incorrect debug entries if these types are actually used.
- So we re-enable debug output after extern "Java". */
+ So we re-enable debug output after extern "Java". */
DECL_IGNORED_P (TYPE_NAME (java_byte_type_node)) = 0;
DECL_IGNORED_P (TYPE_NAME (java_short_type_node)) = 0;
DECL_IGNORED_P (TYPE_NAME (java_int_type_node)) = 0;
@@ -5780,7 +5959,7 @@ pop_lang_context ()
/* Given an OVERLOAD and a TARGET_TYPE, return the function that
matches the TARGET_TYPE. If there is no satisfactory match, return
error_mark_node, and issue an error message if COMPLAIN is
- non-zero. Permit pointers to member function if PTRMEM is non-zero.
+ nonzero. Permit pointers to member function if PTRMEM is nonzero.
If TEMPLATE_ONLY, the name of the overloaded function
was a template-id, and EXPLICIT_TARGS are the explicitly provided
template arguments. */
@@ -6045,7 +6224,7 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
/* The target must be a REFERENCE_TYPE. Above, build_unary_op
will mark the function as addressed, but here we must do it
explicitly. */
- mark_addressable (fn);
+ cxx_mark_addressable (fn);
return fn;
}
@@ -6090,6 +6269,9 @@ instantiate_type (lhstype, rhs, flags)
return error_mark_node;
}
+ if (TREE_CODE (rhs) == BASELINK)
+ rhs = BASELINK_FUNCTIONS (rhs);
+
/* We don't overwrite rhs if it is an overloaded function.
Copying it would destroy the tree link. */
if (TREE_CODE (rhs) != OVERLOAD)
@@ -6136,7 +6318,7 @@ instantiate_type (lhstype, rhs, flags)
case OFFSET_REF:
rhs = TREE_OPERAND (rhs, 1);
if (BASELINK_P (rhs))
- return instantiate_type (lhstype, TREE_VALUE (rhs),
+ return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs),
flags | allow_ptrmem);
/* This can happen if we are forming a pointer-to-member for a
@@ -6169,10 +6351,10 @@ instantiate_type (lhstype, rhs, flags)
/*explicit_targs=*/NULL_TREE);
case TREE_LIST:
- /* Now we should have a baselink. */
+ /* Now we should have a baselink. */
my_friendly_assert (BASELINK_P (rhs), 990412);
- return instantiate_type (lhstype, TREE_VALUE (rhs), flags);
+ return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs), flags);
case CALL_EXPR:
/* This is too hard for now. */
@@ -6377,7 +6559,38 @@ is_empty_class (type)
if (! IS_AGGR_TYPE (type))
return 0;
- return integer_zerop (CLASSTYPE_SIZE (type));
+ /* In G++ 3.2, whether or not a class was empty was determined by
+ looking at its size. */
+ if (abi_version_at_least (2))
+ return CLASSTYPE_EMPTY_P (type);
+ else
+ return integer_zerop (CLASSTYPE_SIZE (type));
+}
+
+/* Returns true if TYPE contains an empty class. */
+
+static bool
+contains_empty_class_p (tree type)
+{
+ if (is_empty_class (type))
+ return true;
+ if (CLASS_TYPE_P (type))
+ {
+ tree field;
+ int i;
+
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
+ if (contains_empty_class_p (TYPE_BINFO_BASETYPE (type, i)))
+ return true;
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL
+ && !DECL_ARTIFICIAL (field)
+ && is_empty_class (TREE_TYPE (field)))
+ return true;
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ return contains_empty_class_p (TREE_TYPE (type));
+ return false;
}
/* Find the enclosing class of the given NODE. NODE can be a *_DECL or
@@ -6456,7 +6669,7 @@ maybe_note_name_used_in_class (name, decl)
}
/* Note that NAME was declared (as DECL) in the current class. Check
- to see that the declaration is legal. */
+ to see that the declaration is valid. */
void
note_name_declared_in_class (name, decl)
@@ -6511,7 +6724,7 @@ get_vtbl_decl_for_binfo (binfo)
/* Called from get_primary_binfo via dfs_walk. DATA is a TREE_LIST
who's TREE_PURPOSE is the TYPE of the required primary base and
- who's TREE_VALUE is a list of candidate binfos that we fill in. */
+ who's TREE_VALUE is a list of candidate binfos that we fill in. */
static tree
dfs_get_primary_binfo (binfo, data)
@@ -6618,7 +6831,7 @@ get_primary_binfo (binfo)
return result;
}
-/* If INDENTED_P is zero, indent to INDENT. Return non-zero. */
+/* If INDENTED_P is zero, indent to INDENT. Return nonzero. */
static int
maybe_indent_hierarchy (stream, indent, indented_p)
@@ -6908,6 +7121,7 @@ initialize_array (decl, inits)
context = DECL_CONTEXT (decl);
DECL_CONTEXT (decl) = NULL_TREE;
DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
+ TREE_HAS_CONSTRUCTOR (DECL_INITIAL (decl)) = 1;
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
DECL_CONTEXT (decl) = context;
}
@@ -6949,8 +7163,10 @@ build_vtt (t)
/* Now, build the VTT object itself. */
vtt = build_vtable (t, get_vtt_name (t), type);
- pushdecl_top_level (vtt);
initialize_array (vtt, inits);
+ /* Add the VTT to the vtables list. */
+ TREE_CHAIN (vtt) = TREE_CHAIN (CLASSTYPE_VTABLES (t));
+ TREE_CHAIN (CLASSTYPE_VTABLES (t)) = vtt;
dump_vtt (t, vtt);
}
@@ -6985,7 +7201,7 @@ get_original_base (base_binfo, binfo)
/* When building a secondary VTT, BINFO_VTABLE is set to a TREE_LIST with
PURPOSE the RTTI_BINFO, VALUE the real vtable pointer for this binfo,
and CHAIN the vtable pointer for this binfo after construction is
- complete. VALUE can also be another BINFO, in which case we recurse. */
+ complete. VALUE can also be another BINFO, in which case we recurse. */
static tree
binfo_ctor_vtable (binfo)
@@ -7176,7 +7392,7 @@ dfs_build_secondary_vptr_vtt_inits (binfo, data)
{
/* It's a primary virtual base, and this is not the construction
vtable. Find the base this is primary of in the inheritance graph,
- and use that base's vtable now. */
+ and use that base's vtable now. */
while (BINFO_PRIMARY_BASE_OF (binfo))
binfo = BINFO_PRIMARY_BASE_OF (binfo);
}
@@ -7285,7 +7501,7 @@ build_ctor_vtbl_group (binfo, t)
TREE_TYPE (vtbl) = type;
/* Initialize the construction vtable. */
- pushdecl_top_level (vtbl);
+ CLASSTYPE_VTABLES (t) = chainon (CLASSTYPE_VTABLES (t), vtbl);
initialize_array (vtbl, inits);
dump_vtable (t, binfo, vtbl);
}
@@ -7315,7 +7531,7 @@ accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits)
BINFO_TYPE (orig_binfo)),
20000517);
- /* If it doesn't have a vptr, we don't do anything. */
+ /* If it doesn't have a vptr, we don't do anything. */
if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo)))
return;
@@ -7502,8 +7718,9 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
vid.last_init = &vid.inits;
vid.primary_vtbl_p = (binfo == TYPE_BINFO (t));
vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
+ vid.generate_vcall_entries = true;
/* The first vbase or vcall offset is at index -3 in the vtable. */
- vid.index = ssize_int (-3);
+ vid.index = ssize_int (-3 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
/* Add entries to the vtable for RTTI. */
build_rtti_vtbl_entries (binfo, &vid);
@@ -7514,8 +7731,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
VARRAY_TREE_INIT (vid.fns, 32, "fns");
/* Add the vcall and vbase offset entries. */
build_vcall_and_vbase_vtbl_entries (binfo, &vid);
- /* Clean up. */
- VARRAY_FREE (vid.fns);
/* Clear BINFO_VTABLE_PATH_MARKED; it's set by
build_vbase_offset_vtbl_entries. */
for (vbase = CLASSTYPE_VBASECLASSES (t);
@@ -7523,6 +7738,25 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
vbase = TREE_CHAIN (vbase))
CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase));
+ /* If the target requires padding between data entries, add that now. */
+ if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1)
+ {
+ tree cur, *prev;
+
+ for (prev = &vid.inits; (cur = *prev); prev = &TREE_CHAIN (cur))
+ {
+ tree add = cur;
+ int i;
+
+ for (i = 1; i < TARGET_VTABLE_DATA_ENTRY_DISTANCE; ++i)
+ add = tree_cons (NULL_TREE,
+ build1 (NOP_EXPR, vtable_entry_type,
+ null_pointer_node),
+ add);
+ *prev = add;
+ }
+ }
+
if (non_fn_entries_p)
*non_fn_entries_p = list_length (vid.inits);
@@ -7534,7 +7768,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
tree delta;
tree vcall_index;
tree fn;
- tree pfn;
tree init = NULL_TREE;
fn = BV_FN (v);
@@ -7569,14 +7802,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
/* Pull the offset for `this', and the function to call, out of
the list. */
delta = BV_DELTA (v);
-
- if (BV_USE_VCALL_INDEX_P (v))
- {
- vcall_index = BV_VCALL_INDEX (v);
- my_friendly_assert (vcall_index != NULL_TREE, 20000621);
- }
- else
- vcall_index = NULL_TREE;
+ vcall_index = BV_VCALL_INDEX (v);
my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
@@ -7585,15 +7811,13 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
So, we replace these functions with __pure_virtual. */
if (DECL_PURE_VIRTUAL_P (fn))
fn = abort_fndecl;
-
+ else if (!integer_zerop (delta) || vcall_index)
+ fn = make_thunk (fn, delta, vcall_index);
/* Take the address of the function, considering it to be of an
appropriate generic type. */
- pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
+ init = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
/* The address of a function can't change. */
- TREE_CONSTANT (pfn) = 1;
-
- /* Enter it in the vtable. */
- init = build_vtable_entry (delta, vcall_index, pfn);
+ TREE_CONSTANT (init) = 1;
}
/* And add it to the chain of initializers. */
@@ -7740,7 +7964,8 @@ build_vbase_offset_vtbl_entries (binfo, vid)
}
/* The next vbase will come at a more negative offset. */
- vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
+ vid->index = size_binop (MINUS_EXPR, vid->index,
+ ssize_int (TARGET_VTABLE_DATA_ENTRY_DISTANCE));
/* The initializer is the delta from BINFO to this virtual base.
The vbase offsets go in reverse inheritance-graph order, and
@@ -7766,31 +7991,37 @@ build_vcall_offset_vtbl_entries (binfo, vid)
tree binfo;
vtbl_init_data *vid;
{
- /* We only need these entries if this base is a virtual base. */
- if (!TREE_VIA_VIRTUAL (binfo))
- return;
-
- /* We need a vcall offset for each of the virtual functions in this
- vtable. For example:
+ /* We only need these entries if this base is a virtual base. We
+ compute the indices -- but do not add to the vtable -- when
+ building the main vtable for a class. */
+ if (TREE_VIA_VIRTUAL (binfo) || binfo == TYPE_BINFO (vid->derived))
+ {
+ /* We need a vcall offset for each of the virtual functions in this
+ vtable. For example:
- class A { virtual void f (); };
- class B1 : virtual public A { virtual void f (); };
- class B2 : virtual public A { virtual void f (); };
- class C: public B1, public B2 { virtual void f (); };
+ class A { virtual void f (); };
+ class B1 : virtual public A { virtual void f (); };
+ class B2 : virtual public A { virtual void f (); };
+ class C: public B1, public B2 { virtual void f (); };
- A C object has a primary base of B1, which has a primary base of A. A
- C also has a secondary base of B2, which no longer has a primary base
- of A. So the B2-in-C construction vtable needs a secondary vtable for
- A, which will adjust the A* to a B2* to call f. We have no way of
- knowing what (or even whether) this offset will be when we define B2,
- so we store this "vcall offset" in the A sub-vtable and look it up in
- a "virtual thunk" for B2::f.
+ A C object has a primary base of B1, which has a primary base of A. A
+ C also has a secondary base of B2, which no longer has a primary base
+ of A. So the B2-in-C construction vtable needs a secondary vtable for
+ A, which will adjust the A* to a B2* to call f. We have no way of
+ knowing what (or even whether) this offset will be when we define B2,
+ so we store this "vcall offset" in the A sub-vtable and look it up in
+ a "virtual thunk" for B2::f.
- We need entries for all the functions in our primary vtable and
- in our non-virtual bases' secondary vtables. */
- vid->vbase = binfo;
- /* Now, walk through the non-virtual bases, adding vcall offsets. */
- add_vcall_offset_vtbl_entries_r (binfo, vid);
+ We need entries for all the functions in our primary vtable and
+ in our non-virtual bases' secondary vtables. */
+ vid->vbase = binfo;
+ /* If we are just computing the vcall indices -- but do not need
+ the actual entries -- not that. */
+ if (!TREE_VIA_VIRTUAL (binfo))
+ vid->generate_vcall_entries = false;
+ /* Now, walk through the non-virtual bases, adding vcall offsets. */
+ add_vcall_offset_vtbl_entries_r (binfo, vid);
+ }
}
/* Build vcall offsets, starting with those for BINFO. */
@@ -7836,136 +8067,154 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
tree binfo;
vtbl_init_data* vid;
{
- tree derived_virtuals;
- tree base_virtuals;
- tree orig_virtuals;
- tree binfo_inits;
- /* If BINFO is a primary base, the most derived class which has BINFO as
- a primary base; otherwise, just BINFO. */
- tree non_primary_binfo;
-
- binfo_inits = NULL_TREE;
-
- /* We might be a primary base class. Go up the inheritance hierarchy
- until we find the most derived class of which we are a primary base:
- it is the BINFO_VIRTUALS there that we need to consider. */
- non_primary_binfo = binfo;
- while (BINFO_INHERITANCE_CHAIN (non_primary_binfo))
+ /* Make entries for the rest of the virtuals. */
+ if (abi_version_at_least (2))
{
- tree b;
+ tree orig_fn;
- /* If we have reached a virtual base, then it must be vid->vbase,
- because we ignore other virtual bases in
- add_vcall_offset_vtbl_entries_r. In turn, it must be a primary
- base (possibly multi-level) of vid->binfo, or we wouldn't
- have called build_vcall_and_vbase_vtbl_entries for it. But it
- might be a lost primary, so just skip down to vid->binfo. */
- if (TREE_VIA_VIRTUAL (non_primary_binfo))
+ /* The ABI requires that the methods be processed in declaration
+ order. G++ 3.2 used the order in the vtable. */
+ for (orig_fn = TYPE_METHODS (BINFO_TYPE (binfo));
+ orig_fn;
+ orig_fn = TREE_CHAIN (orig_fn))
+ if (DECL_VINDEX (orig_fn))
+ add_vcall_offset (orig_fn, binfo, vid);
+ }
+ else
+ {
+ tree derived_virtuals;
+ tree base_virtuals;
+ tree orig_virtuals;
+ /* If BINFO is a primary base, the most derived class which has
+ BINFO as a primary base; otherwise, just BINFO. */
+ tree non_primary_binfo;
+
+ /* We might be a primary base class. Go up the inheritance hierarchy
+ until we find the most derived class of which we are a primary base:
+ it is the BINFO_VIRTUALS there that we need to consider. */
+ non_primary_binfo = binfo;
+ while (BINFO_INHERITANCE_CHAIN (non_primary_binfo))
{
- if (non_primary_binfo != vid->vbase)
- abort ();
- non_primary_binfo = vid->binfo;
- break;
+ tree b;
+
+ /* If we have reached a virtual base, then it must be vid->vbase,
+ because we ignore other virtual bases in
+ add_vcall_offset_vtbl_entries_r. In turn, it must be a primary
+ base (possibly multi-level) of vid->binfo, or we wouldn't
+ have called build_vcall_and_vbase_vtbl_entries for it. But it
+ might be a lost primary, so just skip down to vid->binfo. */
+ if (TREE_VIA_VIRTUAL (non_primary_binfo))
+ {
+ if (non_primary_binfo != vid->vbase)
+ abort ();
+ non_primary_binfo = vid->binfo;
+ break;
+ }
+
+ b = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
+ if (get_primary_binfo (b) != non_primary_binfo)
+ break;
+ non_primary_binfo = b;
}
- b = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
- if (get_primary_binfo (b) != non_primary_binfo)
- break;
- non_primary_binfo = b;
+ if (vid->ctor_vtbl_p)
+ /* For a ctor vtable we need the equivalent binfo within the hierarchy
+ where rtti_binfo is the most derived type. */
+ non_primary_binfo = get_original_base
+ (non_primary_binfo, TYPE_BINFO (BINFO_TYPE (vid->rtti_binfo)));
+
+ for (base_virtuals = BINFO_VIRTUALS (binfo),
+ derived_virtuals = BINFO_VIRTUALS (non_primary_binfo),
+ orig_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
+ base_virtuals;
+ base_virtuals = TREE_CHAIN (base_virtuals),
+ derived_virtuals = TREE_CHAIN (derived_virtuals),
+ orig_virtuals = TREE_CHAIN (orig_virtuals))
+ {
+ tree orig_fn;
+
+ /* Find the declaration that originally caused this function to
+ be present in BINFO_TYPE (binfo). */
+ orig_fn = BV_FN (orig_virtuals);
+
+ /* When processing BINFO, we only want to generate vcall slots for
+ function slots introduced in BINFO. So don't try to generate
+ one if the function isn't even defined in BINFO. */
+ if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo)))
+ continue;
+
+ add_vcall_offset (orig_fn, binfo, vid);
+ }
}
+}
- if (vid->ctor_vtbl_p)
- /* For a ctor vtable we need the equivalent binfo within the hierarchy
- where rtti_binfo is the most derived type. */
- non_primary_binfo = get_original_base
- (non_primary_binfo, TYPE_BINFO (BINFO_TYPE (vid->rtti_binfo)));
+/* Add a vcall offset entry for ORIG_FN to the vtable. */
- /* Make entries for the rest of the virtuals. */
- for (base_virtuals = BINFO_VIRTUALS (binfo),
- derived_virtuals = BINFO_VIRTUALS (non_primary_binfo),
- orig_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
- base_virtuals;
- base_virtuals = TREE_CHAIN (base_virtuals),
- derived_virtuals = TREE_CHAIN (derived_virtuals),
- orig_virtuals = TREE_CHAIN (orig_virtuals))
+static void
+add_vcall_offset (tree orig_fn, tree binfo, vtbl_init_data *vid)
+{
+ size_t i;
+ tree vcall_offset;
+
+ /* If there is already an entry for a function with the same
+ signature as FN, then we do not need a second vcall offset.
+ Check the list of functions already present in the derived
+ class vtable. */
+ for (i = 0; i < VARRAY_ACTIVE_SIZE (vid->fns); ++i)
{
- tree orig_fn;
- tree fn;
- tree base;
- tree base_binfo;
- size_t i;
- tree vcall_offset;
+ tree derived_entry;
- /* Find the declaration that originally caused this function to
- be present in BINFO_TYPE (binfo). */
- orig_fn = BV_FN (orig_virtuals);
+ derived_entry = VARRAY_TREE (vid->fns, i);
+ if (same_signature_p (derived_entry, orig_fn)
+ /* We only use one vcall offset for virtual destructors,
+ even though there are two virtual table entries. */
+ || (DECL_DESTRUCTOR_P (derived_entry)
+ && DECL_DESTRUCTOR_P (orig_fn)))
+ return;
+ }
- /* When processing BINFO, we only want to generate vcall slots for
- function slots introduced in BINFO. So don't try to generate
- one if the function isn't even defined in BINFO. */
- if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo)))
- continue;
+ /* If we are building these vcall offsets as part of building
+ the vtable for the most derived class, remember the vcall
+ offset. */
+ if (vid->binfo == TYPE_BINFO (vid->derived))
+ CLASSTYPE_VCALL_INDICES (vid->derived)
+ = tree_cons (orig_fn, vid->index,
+ CLASSTYPE_VCALL_INDICES (vid->derived));
- /* Find the overriding function. */
- fn = BV_FN (derived_virtuals);
+ /* The next vcall offset will be found at a more negative
+ offset. */
+ vid->index = size_binop (MINUS_EXPR, vid->index,
+ ssize_int (TARGET_VTABLE_DATA_ENTRY_DISTANCE));
+
+ /* Keep track of this function. */
+ VARRAY_PUSH_TREE (vid->fns, orig_fn);
- /* If there is already an entry for a function with the same
- signature as FN, then we do not need a second vcall offset.
- Check the list of functions already present in the derived
- class vtable. */
- for (i = 0; i < VARRAY_ACTIVE_SIZE (vid->fns); ++i)
+ if (vid->generate_vcall_entries)
+ {
+ tree base;
+ tree fn;
+
+ /* Find the overriding function. */
+ fn = find_final_overrider (vid->rtti_binfo, binfo, orig_fn);
+ if (fn == error_mark_node)
+ vcall_offset = build1 (NOP_EXPR, vtable_entry_type,
+ integer_zero_node);
+ else
{
- tree derived_entry;
-
- derived_entry = VARRAY_TREE (vid->fns, i);
- if (same_signature_p (BV_FN (derived_entry), fn)
- /* We only use one vcall offset for virtual destructors,
- even though there are two virtual table entries. */
- || (DECL_DESTRUCTOR_P (BV_FN (derived_entry))
- && DECL_DESTRUCTOR_P (fn)))
- {
- if (!vid->ctor_vtbl_p)
- BV_VCALL_INDEX (derived_virtuals)
- = BV_VCALL_INDEX (derived_entry);
- break;
- }
+ base = TREE_VALUE (fn);
+
+ /* The vbase we're working on is a primary base of
+ vid->binfo. But it might be a lost primary, so its
+ BINFO_OFFSET might be wrong, so we just use the
+ BINFO_OFFSET from vid->binfo. */
+ vcall_offset = size_diffop (BINFO_OFFSET (base),
+ BINFO_OFFSET (vid->binfo));
+ vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
+ vcall_offset));
}
- if (i != VARRAY_ACTIVE_SIZE (vid->fns))
- continue;
-
- /* The FN comes from BASE. So, we must calculate the adjustment from
- vid->vbase to BASE. We can just look for BASE in the complete
- object because we are converting from a virtual base, so if there
- were multiple copies, there would not be a unique final overrider
- and vid->derived would be ill-formed. */
- base = DECL_CONTEXT (fn);
- base_binfo = lookup_base (vid->derived, base, ba_any, NULL);
-
- /* Compute the vcall offset. */
- /* As mentioned above, the vbase we're working on is a primary base of
- vid->binfo. But it might be a lost primary, so its BINFO_OFFSET
- might be wrong, so we just use the BINFO_OFFSET from vid->binfo. */
- vcall_offset = BINFO_OFFSET (vid->binfo);
- vcall_offset = size_diffop (BINFO_OFFSET (base_binfo),
- vcall_offset);
- vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
- vcall_offset));
-
+ /* Add the intiailizer to the vtable. */
*vid->last_init = build_tree_list (NULL_TREE, vcall_offset);
vid->last_init = &TREE_CHAIN (*vid->last_init);
-
- /* Keep track of the vtable index where this vcall offset can be
- found. For a construction vtable, we already made this
- annotation when we built the original vtable. */
- if (!vid->ctor_vtbl_p)
- BV_VCALL_INDEX (derived_virtuals) = vid->index;
-
- /* The next vcall offset will be found at a more negative
- offset. */
- vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
-
- /* Keep track of this function. */
- VARRAY_PUSH_TREE (vid->fns, derived_virtuals);
}
}
@@ -8004,52 +8253,20 @@ build_rtti_vtbl_entries (binfo, vid)
/* The second entry is the address of the typeinfo object. */
if (flag_rtti)
- decl = build_unary_op (ADDR_EXPR, get_tinfo_decl (t), 0);
+ decl = build_address (get_tinfo_decl (t));
else
decl = integer_zero_node;
/* Convert the declaration to a type that can be stored in the
vtable. */
- init = build1 (NOP_EXPR, vfunc_ptr_type_node, decl);
- TREE_CONSTANT (init) = 1;
+ init = build_nop (vfunc_ptr_type_node, decl);
*vid->last_init = build_tree_list (NULL_TREE, init);
vid->last_init = &TREE_CHAIN (*vid->last_init);
/* Add the offset-to-top entry. It comes earlier in the vtable that
the the typeinfo entry. Convert the offset to look like a
function pointer, so that we can put it in the vtable. */
- init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
- TREE_CONSTANT (init) = 1;
+ init = build_nop (vfunc_ptr_type_node, offset);
*vid->last_init = build_tree_list (NULL_TREE, init);
vid->last_init = &TREE_CHAIN (*vid->last_init);
}
-
-/* Build an entry in the virtual function table. DELTA is the offset
- for the `this' pointer. VCALL_INDEX is the vtable index containing
- the vcall offset; NULL_TREE if none. ENTRY is the virtual function
- table entry itself. It's TREE_TYPE must be VFUNC_PTR_TYPE_NODE,
- but it may not actually be a virtual function table pointer. (For
- example, it might be the address of the RTTI object, under the new
- ABI.) */
-
-static tree
-build_vtable_entry (delta, vcall_index, entry)
- tree delta;
- tree vcall_index;
- tree entry;
-{
- tree fn = TREE_OPERAND (entry, 0);
-
- if ((!integer_zerop (delta) || vcall_index != NULL_TREE)
- && fn != abort_fndecl)
- {
- entry = make_thunk (entry, delta, vcall_index);
- entry = build1 (ADDR_EXPR, vtable_entry_type, entry);
- TREE_READONLY (entry) = 1;
- TREE_CONSTANT (entry) = 1;
- }
-#ifdef GATHER_STATISTICS
- n_vtable_entries += 1;
-#endif
- return entry;
-}
diff --git a/contrib/gcc/cp/config-lang.in b/contrib/gcc/cp/config-lang.in
index c07408d..b8feb03 100644
--- a/contrib/gcc/cp/config-lang.in
+++ b/contrib/gcc/cp/config-lang.in
@@ -33,3 +33,5 @@ compilers="cc1plus\$(exeext)"
stagestuff="g++\$(exeext) g++-cross\$(exeext) cc1plus\$(exeext)"
target_libs="${libstdcxx_version} target-gperf"
+
+gtfiles="\$(srcdir)/cp/mangle.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/lex.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/parse.y \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/spew.c \$(srcdir)/cp/tree.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c"
diff --git a/contrib/gcc/cp/cp-lang.c b/contrib/gcc/cp/cp-lang.c
index 1464ef6..0d8a4e3 100644
--- a/contrib/gcc/cp/cp-lang.c
+++ b/contrib/gcc/cp/cp-lang.c
@@ -28,9 +28,11 @@ Boston, MA 02111-1307, USA. */
#include "langhooks.h"
#include "langhooks-def.h"
-static HOST_WIDE_INT cxx_get_alias_set PARAMS ((tree));
-static tree cp_expr_size PARAMS ((tree));
-static bool cp_var_mod_type_p PARAMS ((tree));
+static HOST_WIDE_INT cxx_get_alias_set PARAMS ((tree));
+static bool ok_to_generate_alias_set_for_type PARAMS ((tree));
+static bool cxx_warn_unused_global_decl PARAMS ((tree));
+static tree cp_expr_size PARAMS ((tree));
+static bool cp_var_mod_type_p PARAMS ((tree));
#undef LANG_HOOKS_NAME
#define LANG_HOOKS_NAME "GNU C++"
@@ -43,15 +45,35 @@ static bool cp_var_mod_type_p PARAMS ((tree));
#undef LANG_HOOKS_INIT_OPTIONS
#define LANG_HOOKS_INIT_OPTIONS cxx_init_options
#undef LANG_HOOKS_DECODE_OPTION
-#define LANG_HOOKS_DECODE_OPTION cxx_decode_option
+#define LANG_HOOKS_DECODE_OPTION c_common_decode_option
#undef LANG_HOOKS_POST_OPTIONS
#define LANG_HOOKS_POST_OPTIONS c_common_post_options
#undef LANG_HOOKS_GET_ALIAS_SET
#define LANG_HOOKS_GET_ALIAS_SET cxx_get_alias_set
#undef LANG_HOOKS_EXPAND_CONSTANT
#define LANG_HOOKS_EXPAND_CONSTANT cplus_expand_constant
+#undef LANG_HOOKS_EXPAND_EXPR
+#define LANG_HOOKS_EXPAND_EXPR cxx_expand_expr
#undef LANG_HOOKS_SAFE_FROM_P
#define LANG_HOOKS_SAFE_FROM_P c_safe_from_p
+#undef LANG_HOOKS_PARSE_FILE
+#define LANG_HOOKS_PARSE_FILE c_common_parse_file
+#undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL
+#define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL cxx_dup_lang_specific_decl
+#undef LANG_HOOKS_UNSAVE_EXPR_NOW
+#define LANG_HOOKS_UNSAVE_EXPR_NOW cxx_unsave_expr_now
+#undef LANG_HOOKS_MAYBE_BUILD_CLEANUP
+#define LANG_HOOKS_MAYBE_BUILD_CLEANUP cxx_maybe_build_cleanup
+#undef LANG_HOOKS_TRUTHVALUE_CONVERSION
+#define LANG_HOOKS_TRUTHVALUE_CONVERSION c_common_truthvalue_conversion
+#undef LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES
+#define LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES cxx_insert_default_attributes
+#undef LANG_HOOKS_UNSAFE_FOR_REEVAL
+#define LANG_HOOKS_UNSAFE_FOR_REEVAL c_common_unsafe_for_reeval
+#undef LANG_HOOKS_SET_DECL_ASSEMBLER_NAME
+#define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME mangle_decl
+#undef LANG_HOOKS_MARK_ADDRESSABLE
+#define LANG_HOOKS_MARK_ADDRESSABLE cxx_mark_addressable
#undef LANG_HOOKS_PRINT_STATISTICS
#define LANG_HOOKS_PRINT_STATISTICS cxx_print_statistics
#undef LANG_HOOKS_PRINT_XNODE
@@ -62,8 +84,28 @@ static bool cp_var_mod_type_p PARAMS ((tree));
#define LANG_HOOKS_PRINT_TYPE cxx_print_type
#undef LANG_HOOKS_PRINT_IDENTIFIER
#define LANG_HOOKS_PRINT_IDENTIFIER cxx_print_identifier
-#undef LANG_HOOKS_SET_YYDEBUG
-#define LANG_HOOKS_SET_YYDEBUG cxx_set_yydebug
+#undef LANG_HOOKS_DECL_PRINTABLE_NAME
+#define LANG_HOOKS_DECL_PRINTABLE_NAME cxx_printable_name
+#undef LANG_HOOKS_PRINT_ERROR_FUNCTION
+#define LANG_HOOKS_PRINT_ERROR_FUNCTION cxx_print_error_function
+#undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL
+#define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL cxx_warn_unused_global_decl
+#undef LANG_HOOKS_WRITE_GLOBALS
+#define LANG_HOOKS_WRITE_GLOBALS lhd_do_nothing
+
+
+#undef LANG_HOOKS_FUNCTION_INIT
+#define LANG_HOOKS_FUNCTION_INIT cxx_push_function_context
+#undef LANG_HOOKS_FUNCTION_FINAL
+#define LANG_HOOKS_FUNCTION_FINAL cxx_pop_function_context
+
+/* Attribute hooks. */
+#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
+#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
+#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table
+#undef LANG_HOOKS_ATTRIBUTE_TABLE
+#define LANG_HOOKS_ATTRIBUTE_TABLE cxx_attribute_table
#undef LANG_HOOKS_TREE_INLINING_WALK_SUBTREES
#define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES \
@@ -98,23 +140,158 @@ static bool cp_var_mod_type_p PARAMS ((tree));
#undef LANG_HOOKS_EXPR_SIZE
#define LANG_HOOKS_EXPR_SIZE cp_expr_size
+#undef LANG_HOOKS_MAKE_TYPE
+#define LANG_HOOKS_MAKE_TYPE cxx_make_type
+#undef LANG_HOOKS_TYPE_FOR_MODE
+#define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode
+#undef LANG_HOOKS_TYPE_FOR_SIZE
+#define LANG_HOOKS_TYPE_FOR_SIZE c_common_type_for_size
+#undef LANG_HOOKS_SIGNED_TYPE
+#define LANG_HOOKS_SIGNED_TYPE c_common_signed_type
+#undef LANG_HOOKS_UNSIGNED_TYPE
+#define LANG_HOOKS_UNSIGNED_TYPE c_common_unsigned_type
+#undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
+#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE c_common_signed_or_unsigned_type
+#undef LANG_HOOKS_INCOMPLETE_TYPE_ERROR
+#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR cxx_incomplete_type_error
+#undef LANG_HOOKS_TYPE_PROMOTES_TO
+#define LANG_HOOKS_TYPE_PROMOTES_TO cxx_type_promotes_to
+
/* Each front end provides its own hooks, for toplev.c. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+/* Tree code classes. */
+
+#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
+
+const char tree_code_type[] = {
+#include "tree.def"
+ 'x',
+#include "c-common.def"
+ 'x',
+#include "cp-tree.def"
+};
+#undef DEFTREECODE
+
+/* Table indexed by tree code giving number of expression
+ operands beyond the fixed part of the node structure.
+ Not used for types or decls. */
+
+#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
+
+const unsigned char tree_code_length[] = {
+#include "tree.def"
+ 0,
+#include "c-common.def"
+ 0,
+#include "cp-tree.def"
+};
+#undef DEFTREECODE
+
+/* Names of tree components.
+ Used for printing out the tree and error messages. */
+#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
+
+const char *const tree_code_name[] = {
+#include "tree.def"
+ "@@dummy",
+#include "c-common.def"
+ "@@dummy",
+#include "cp-tree.def"
+};
+#undef DEFTREECODE
+
+/* Check if a C++ type is safe for aliasing.
+ Return TRUE if T safe for aliasing FALSE otherwise. */
+
+static bool
+ok_to_generate_alias_set_for_type (t)
+ tree t;
+{
+ if (TYPE_PTRMEMFUNC_P (t))
+ return true;
+ if (AGGREGATE_TYPE_P (t))
+ {
+ if ((TREE_CODE (t) == RECORD_TYPE) || (TREE_CODE (t) == UNION_TYPE))
+ {
+ tree fields;
+ /* Backend-created structs are safe. */
+ if (! CLASS_TYPE_P (t))
+ return true;
+ /* PODs are safe. */
+ if (! CLASSTYPE_NON_POD_P(t))
+ return true;
+ /* Classes with virtual baseclasses are not. */
+ if (TYPE_USES_VIRTUAL_BASECLASSES (t))
+ return false;
+ /* Recursively check the base classes. */
+ if (TYPE_BINFO (t) != NULL && TYPE_BINFO_BASETYPES (t) != NULL)
+ {
+ int i;
+ for (i = 0; i < TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t)); i++)
+ {
+ tree binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
+ if (!ok_to_generate_alias_set_for_type (BINFO_TYPE (binfo)))
+ return false;
+ }
+ }
+ /* Check all the fields. */
+ for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
+ {
+ if (TREE_CODE (fields) != FIELD_DECL)
+ continue;
+ if (! ok_to_generate_alias_set_for_type (TREE_TYPE (fields)))
+ return false;
+ }
+ return true;
+ }
+ else if (TREE_CODE (t) == ARRAY_TYPE)
+ return ok_to_generate_alias_set_for_type (TREE_TYPE (t));
+ else
+ /* This should never happen, we dealt with all the aggregate
+ types that can appear in C++ above. */
+ abort ();
+ }
+ else
+ return true;
+}
+
/* Special routine to get the alias set for C++. */
static HOST_WIDE_INT
cxx_get_alias_set (t)
tree t;
{
- /* It's not yet safe to use alias sets for classes in C++ because
- the TYPE_FIELDs list for a class doesn't mention base classes. */
- if (AGGREGATE_TYPE_P (t))
+ if (/* It's not yet safe to use alias sets for some classes in C++. */
+ !ok_to_generate_alias_set_for_type (t)
+ /* Nor is it safe to use alias sets for pointers-to-member
+ functions, due to the fact that there may be more than one
+ RECORD_TYPE type corresponding to the same pointer-to-member
+ type. */
+ || TYPE_PTRMEMFUNC_P (t))
return 0;
return c_common_get_alias_set (t);
}
+/* Called from check_global_declarations. */
+
+static bool
+cxx_warn_unused_global_decl (decl)
+ tree decl;
+{
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
+ return false;
+ if (DECL_IN_SYSTEM_HEADER (decl))
+ return false;
+
+ /* Const variables take the place of #defines in C++. */
+ if (TREE_CODE (decl) == VAR_DECL && TREE_READONLY (decl))
+ return false;
+
+ return true;
+}
+
/* Langhook for expr_size: Tell the backend that the value of an expression
of non-POD class type does not include any tail padding; a derived class
might have allocated something there. */
@@ -125,8 +302,16 @@ cp_expr_size (exp)
{
if (CLASS_TYPE_P (TREE_TYPE (exp)))
{
- /* This would be wrong for a type with virtual bases, but they should
- not get here. */
+ /* The backend should not be interested in the size of an expression
+ of a type with both of these set; all copies of such types must go
+ through a constructor or assignment op. */
+ if (TYPE_HAS_COMPLEX_INIT_REF (TREE_TYPE (exp))
+ && TYPE_HAS_COMPLEX_ASSIGN_REF (TREE_TYPE (exp))
+ /* But storing a CONSTRUCTOR isn't a copy. */
+ && TREE_CODE (exp) != CONSTRUCTOR)
+ abort ();
+ /* This would be wrong for a type with virtual bases, but they are
+ caught by the abort above. */
return CLASSTYPE_SIZE_UNIT (TREE_TYPE (exp));
}
else
diff --git a/contrib/gcc/cp/cp-tree.def b/contrib/gcc/cp/cp-tree.def
index 3854525..cee19ab 100644
--- a/contrib/gcc/cp/cp-tree.def
+++ b/contrib/gcc/cp/cp-tree.def
@@ -23,11 +23,25 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Reference to the contents of an offset
- (a value whose type is an OFFSET_TYPE).
- Operand 0 is the object within which the offset is taken.
- Operand 1 is the offset. The language independent OFFSET_REF
- just won't work for us. */
+/* An OFFSET_REF is used in two situations:
+
+ 1. An expression of the form `A::m' where `A' is a class and `m' is
+ a non-static data member. In this case, operand 0 will be a
+ TYPE (corresponding to `A') and operand 1 will be a FIELD_DECL
+ (corresponding to `m'.
+
+ The expression is a pointer-to-member if its address is taken,
+ but simply denotes a member of the object if its address isnot
+ taken. In the latter case, resolve_offset_ref is used to
+ convert it to a representation of the member referred to by the
+ OFFSET_REF.
+
+ 2. An expression of the form `x.*p'. In this case, operand 0 will
+ be an expression corresponding to `x' and operand 1 will be an
+ expression with pointer-to-member type.
+
+ OFFSET_REFs are only used during the parsing phase; once semantic
+ analysis has taken place they are eliminated. */
DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2)
/* A pointer-to-member constant. For a pointer-to-member constant
@@ -75,6 +89,20 @@ DEFTREECODE (THROW_EXPR, "throw_expr", 'e', 1)
these to avoid actually creating instances of the empty classes. */
DEFTREECODE (EMPTY_CLASS_EXPR, "empty_class_expr", 'e', 0)
+/* A reference to a member function or member functions from a base
+ class. BASELINK_FUNCTIONS gives the FUNCTION_DECL,
+ TEMPLATE_DECL, OVERLOAD, or TEMPLATE_ID_EXPR corresponding to the
+ functions. BASELINK_BINFO gives the base from which the functions
+ come, i.e., the base to which the `this' pointer must be converted
+ before the functions are called. BASELINK_ACCESS_BINFO gives the
+ base used to name the functions.
+
+ A BASELINK is an expression; the TREE_TYPE of the BASELINK gives
+ the type of the expression. This type is either a FUNCTION_TYPE,
+ METHOD_TYPE, or `unknown_type_node' indicating that the function is
+ overloaded. */
+DEFTREECODE (BASELINK, "baselink", 'e', 3)
+
/* Template definition. The following fields have the specified uses,
although there are other macros in cp-tree.h that should be used for
accessing this data.
@@ -186,14 +214,10 @@ DEFTREECODE (DEFAULT_ARG, "default_arg", 'x', 2)
The second is the TREE_LIST or TREE_VEC of explicitly specified
arguments. The template will be a FUNCTION_DECL, TEMPLATE_DECL, or
an OVERLOAD. If the template-id refers to a member template, the
- template may be an IDENTIFIER_NODE. */
+ template may be an IDENTIFIER_NODE. In an uninstantiated template,
+ the template may be a LOOKUP_EXPR. */
DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2)
-/* An association between name and entity. Parameters are the scope
- and the (non-type) value. TREE_TYPE indicates the type bound to
- the name. */
-DEFTREECODE (CPLUS_BINDING, "binding", 'x', 2)
-
/* A list-like node for chaining overloading candidates. TREE_TYPE is
the original name, and the parameter is the FUNCTION_DECL. */
DEFTREECODE (OVERLOAD, "overload", 'x', 1)
@@ -220,19 +244,9 @@ DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", 'e', 2)
DEFTREECODE (TYPEID_EXPR, "typeid_expr", 'e', 1)
DEFTREECODE (PSEUDO_DTOR_EXPR, "pseudo_dtor_expr", 'e', 3)
-/* A SUBOBJECT statement marks the point at which a sub-object is
- fully constructed. After this point, the SUBOBJECT_CLEANUP must be
- run if an exception is thrown before the end of the enclosing
- function. */
-DEFTREECODE (SUBOBJECT, "subobject", 'e', 1)
-/* An CTOR_STMT marks the beginning (if CTOR_BEGIN_P holds) or end of
- a constructor (if CTOR_END_P) holds. At the end of a constructor,
- the cleanups associated with any SUBOBJECT_CLEANUPS need no longer
- be run. */
-DEFTREECODE (CTOR_STMT, "ctor_stmt", 'e', 0)
/* CTOR_INITIALIZER is a placeholder in template code for a call to
setup_vtbl_pointer (and appears in all functions, not just ctors). */
-DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2)
+DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 1)
DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
DEFTREECODE (TRY_BLOCK, "try_block", 'e', 2)
DEFTREECODE (EH_SPEC_BLOCK, "eh_spec_block", 'e', 2)
@@ -248,7 +262,13 @@ DEFTREECODE (MUST_NOT_THROW_EXPR, "must_not_throw_expr", 'e', 1)
DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
-/* And some codes for expressing conversions for overload resolution. */
+/* The following codes are used to represent implicit conversion
+ sequences, in the sense of [over.best.ics]. The conversion
+ sequences are connected through their first operands, with the
+ first conversion to be performed at the end of the chain.
+
+ The innermost conversion (i.e, the one at the end of the chain) is
+ always an IDENTITY_CONV, corresponding to the identity conversion. */
DEFTREECODE (IDENTITY_CONV, "identity_conv", 'e', 1)
DEFTREECODE (LVALUE_CONV, "lvalue_conv", 'e', 1)
diff --git a/contrib/gcc/cp/cp-tree.h b/contrib/gcc/cp/cp-tree.h
index a2c0db1..bfeec9b 100644
--- a/contrib/gcc/cp/cp-tree.h
+++ b/contrib/gcc/cp/cp-tree.h
@@ -20,20 +20,22 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#ifndef GCC_CP_TREE_H
+#define GCC_CP_TREE_H
+
#include "function.h"
#include "hashtab.h"
#include "splay-tree.h"
#include "varray.h"
-#ifndef GCC_CP_TREE_H
-#define GCC_CP_TREE_H
-
#ifndef __GNUC__
#error "You should be using 'make bootstrap' -- see installation instructions"
#endif
#include "c-common.h"
+struct diagnostic_context;
+
/* Usage of TREE_LANG_FLAG_?:
0: BINFO_MARKED (BINFO nodes).
IDENTIFIER_MARKED (IDENTIFIER_NODEs)
@@ -41,12 +43,9 @@ Boston, MA 02111-1307, USA. */
DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR).
LOOKUP_EXPR_GLOBAL (in LOOKUP_EXPR).
TREE_INDIRECT_USING (in NAMESPACE_DECL).
- LOCAL_BINDING_P (in CPLUS_BINDING)
ICS_USER_FLAG (in _CONV)
CLEANUP_P (in TRY_BLOCK)
AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
- CTOR_BEGIN_P (in CTOR_STMT)
- BV_USE_VCALL_INDEX_P (in the BINFO_VIRTUALS TREE_LIST)
PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
PARMLIST_ELLIPSIS_P (in PARMLIST)
1: IDENTIFIER_VIRTUAL_P.
@@ -55,14 +54,12 @@ Boston, MA 02111-1307, USA. */
DELETE_EXPR_USE_VEC (in DELETE_EXPR).
(TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (in _TYPE).
- INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
- BASELINK_P (in TREE_LIST)
ICS_ELLIPSIS_FLAG (in _CONV)
BINFO_ACCESS (in BINFO)
+ DECL_INITIALIZED_P (in VAR_DECL)
2: IDENTIFIER_OPNAME_P.
- TYPE_POLYMORHPIC_P (in _TYPE)
+ TYPE_POLYMORPHIC_P (in _TYPE)
ICS_THIS_FLAG (in _CONV)
- BINDING_HAS_LEVEL_P (in CPLUS_BINDING)
BINFO_LOST_PRIMARY_P (in BINFO)
TREE_PARMLIST (in TREE_LIST)
3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
@@ -96,11 +93,11 @@ Boston, MA 02111-1307, USA. */
DECL_MUTABLE_P (in FIELD_DECL)
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
- DECL_C_BITFIELD (in FIELD_DECL)
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
3: DECL_IN_AGGR_P.
- 4: DECL_C_BIT_FIELD
+ 4: DECL_C_BIT_FIELD (in a FIELD_DECL)
+ DECL_VAR_MARKED_P (in a VAR_DECL)
5: DECL_INTERFACE_KNOWN.
6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL).
7: DECL_DEAD_FOR_LOCAL (in VAR_DECL).
@@ -121,16 +118,18 @@ Boston, MA 02111-1307, USA. */
For a FUNCTION_TYPE or METHOD_TYPE, this is TYPE_RAISES_EXCEPTIONS
BINFO_VIRTUALS
- For a binfo, this is a TREE_LIST. The BV_DELTA of each node
- gives the amount by which to adjust the `this' pointer when
- calling the function. If the method is an overriden version of a
- base class method, then it is assumed that, prior to adjustment,
- the this pointer points to an object of the base class.
+ For a binfo, this is a TREE_LIST. There is an entry for each
+ virtual function declared either in BINFO or its direct and
+ indirect primary bases.
+
+ The BV_DELTA of each node gives the amount by which to adjust the
+ `this' pointer when calling the function. If the method is an
+ overriden version of a base class method, then it is assumed
+ that, prior to adjustment, the this pointer points to an object
+ of the base class.
The BV_VCALL_INDEX of each node, if non-NULL, gives the vtable
- index of the vcall offset for this entry. If
- BV_USE_VCALL_INDEX_P then the corresponding vtable entry should
- use a virtual thunk, as opposed to an ordinary thunk.
+ index of the vcall offset for this entry.
The BV_FN is the declaration for the virtual function itself.
@@ -153,7 +152,7 @@ Boston, MA 02111-1307, USA. */
the virtual function this one overrides, and whose TREE_CHAIN is
the old DECL_VINDEX. */
-/* Language-specific tree checkers. */
+/* Language-specific tree checkers. */
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
@@ -212,31 +211,70 @@ Boston, MA 02111-1307, USA. */
#endif
+/* Returns TRUE if generated code should match ABI version N or
+ greater is in use. */
+
+#define abi_version_at_least(N) \
+ (flag_abi_version == 0 || flag_abi_version >= (N))
+
-/* ABI control. */
+/* Datatype used to temporarily save C++ bindings (for implicit
+ instantiations purposes and like). Implemented in decl.c. */
+typedef struct cxx_saved_binding cxx_saved_binding;
-/* Nonzero to use __cxa_atexit, rather than atexit, to register
- destructors for local statics and global objects. */
+/* Datatype that represents binding established by a declaration between
+ a name and a C++ entity. */
+typedef struct cxx_binding cxx_binding;
-extern int flag_use_cxa_atexit;
+/* (GC-)allocate a cxx_binding object. */
+#define cxx_binding_make() (ggc_alloc (sizeof (cxx_binding)))
-/* Nonzero means generate 'rtti' that give run-time type information. */
+/* Zero out a cxx_binding pointed to by B. */
+#define cxx_binding_clear(B) memset ((B), 0, sizeof (cxx_binding))
-extern int flag_rtti;
+struct cxx_binding GTY(())
+{
+ /* Link to chain together various bindings for this name. */
+ cxx_binding *previous;
+ /* The non-type entity this name is bound to. */
+ tree value;
+ /* The type entity this name is bound to. */
+ tree type;
+ union tree_binding_u {
+ tree GTY ((tag ("0"))) scope;
+ struct cp_binding_level * GTY ((tag ("1"))) level;
+ } GTY ((desc ("%0.has_level"))) scope;
+ unsigned has_level : 1;
+ unsigned value_is_inherited : 1;
+ unsigned is_local : 1;
+};
-/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
- objects. */
+/* The type of dictionary used to map names to types declared at
+ a given scope. */
+typedef struct binding_table_s *binding_table;
+typedef struct binding_entry_s *binding_entry;
-extern int flag_huge_objects;
+/* The type of a routine repeatedly called by binding_table_foreach. */
+typedef void (*bt_foreach_proc) (binding_entry, void *);
+struct binding_entry_s GTY(())
+{
+ binding_entry chain;
+ tree name;
+ tree type;
+};
+
+extern void binding_table_foreach (binding_table, bt_foreach_proc, void *);
+extern binding_entry binding_table_find (binding_table, tree);
+extern void cxx_remember_type_decls (binding_table);
/* Language-dependent contents of an identifier. */
-struct lang_identifier
+struct lang_identifier GTY(())
{
- struct c_common_identifier ignore;
- tree namespace_bindings;
- tree bindings;
+ struct c_common_identifier c_common;
+ cxx_binding *namespace_bindings;
+ cxx_binding *bindings;
tree class_value;
tree class_template_info;
struct lang_id2 *x;
@@ -254,20 +292,21 @@ extern const short rid_to_yy[RID_MAX];
#define LANG_IDENTIFIER_CAST(NODE) \
((struct lang_identifier*)IDENTIFIER_NODE_CHECK (NODE))
-struct lang_id2
+struct lang_id2 GTY(())
{
- tree label_value, implicit_decl;
+ tree label_value;
+ tree implicit_decl;
tree error_locus;
};
-typedef struct
+typedef struct flagged_type_tree_s GTY(())
{
tree t;
int new_type_flag;
tree lookups;
} flagged_type_tree;
-typedef struct
+typedef struct template_parm_index_s GTY(())
{
struct tree_common common;
HOST_WIDE_INT index;
@@ -276,41 +315,40 @@ typedef struct
tree decl;
} template_parm_index;
-typedef struct ptrmem_cst
+struct ptrmem_cst GTY(())
{
struct tree_common common;
/* This isn't used, but the middle-end expects all constants to have
this field. */
rtx rtl;
tree member;
-}* ptrmem_cst_t;
+};
+typedef struct ptrmem_cst * ptrmem_cst_t;
/* Nonzero if this binding is for a local scope, as opposed to a class
or namespace scope. */
-#define LOCAL_BINDING_P(NODE) TREE_LANG_FLAG_0 (NODE)
+#define LOCAL_BINDING_P(NODE) ((NODE)->is_local)
/* Nonzero if BINDING_VALUE is from a base class of the class which is
currently being defined. */
-#define INHERITED_VALUE_BINDING_P(NODE) TREE_LANG_FLAG_1 (NODE)
+#define INHERITED_VALUE_BINDING_P(NODE) ((NODE)->value_is_inherited)
/* For a binding between a name and an entity at a non-local scope,
defines the scope where the binding is declared. (Either a class
_TYPE node, or a NAMESPACE_DECL.) This macro should be used only
for namespace-level bindings; on the IDENTIFIER_BINDING list
BINDING_LEVEL is used instead. */
-#define BINDING_SCOPE(NODE) \
- (((struct tree_binding*)CPLUS_BINDING_CHECK (NODE))->scope.scope)
+#define BINDING_SCOPE(NODE) ((NODE)->scope.scope)
/* Nonzero if NODE has BINDING_LEVEL, rather than BINDING_SCOPE. */
-#define BINDING_HAS_LEVEL_P(NODE) TREE_LANG_FLAG_2 (NODE)
+#define BINDING_HAS_LEVEL_P(NODE) ((NODE)->has_level)
/* This is the declaration bound to the name. Possible values:
variable, overloaded function, namespace, template, enumerator. */
-#define BINDING_VALUE(NODE) \
- (((struct tree_binding*)CPLUS_BINDING_CHECK (NODE))->value)
+#define BINDING_VALUE(NODE) ((NODE)->value)
/* If name is bound to a type, this is the type (struct, union, enum). */
-#define BINDING_TYPE(NODE) TREE_TYPE (NODE)
+#define BINDING_TYPE(NODE) ((NODE)->type)
#define IDENTIFIER_GLOBAL_VALUE(NODE) \
namespace_binding ((NODE), global_namespace)
@@ -333,71 +371,71 @@ typedef struct ptrmem_cst
#define same_type_ignoring_top_level_qualifiers_p(TYPE1, TYPE2) \
same_type_p (TYPE_MAIN_VARIANT (TYPE1), TYPE_MAIN_VARIANT (TYPE2))
-/* Non-zero if we are presently building a statement tree, rather
+/* Nonzero if we are presently building a statement tree, rather
than expanding each statement as we encounter it. */
#define building_stmt_tree() (last_tree != NULL_TREE)
-/* Returns non-zero iff NODE is a declaration for the global function
+/* Returns nonzero iff NODE is a declaration for the global function
`main'. */
#define DECL_MAIN_P(NODE) \
(DECL_EXTERN_C_FUNCTION_P (NODE) \
&& DECL_NAME (NODE) != NULL_TREE \
&& MAIN_NAME_P (DECL_NAME (NODE)))
-
-struct tree_binding
-{
- struct tree_common common;
- union {
- tree scope;
- struct binding_level *level;
- } scope;
- tree value;
-};
-
-/* The overloaded FUNCTION_DECL. */
+/* The overloaded FUNCTION_DECL. */
#define OVL_FUNCTION(NODE) \
(((struct tree_overload*)OVERLOAD_CHECK (NODE))->function)
#define OVL_CHAIN(NODE) TREE_CHAIN (NODE)
-/* Polymorphic access to FUNCTION and CHAIN. */
+/* Polymorphic access to FUNCTION and CHAIN. */
#define OVL_CURRENT(NODE) \
((TREE_CODE (NODE) == OVERLOAD) ? OVL_FUNCTION (NODE) : (NODE))
#define OVL_NEXT(NODE) \
((TREE_CODE (NODE) == OVERLOAD) ? TREE_CHAIN (NODE) : NULL_TREE)
/* If set, this was imported in a using declaration.
This is not to confuse with being used somewhere, which
- is not important for this node. */
+ is not important for this node. */
#define OVL_USED(NODE) TREE_USED (NODE)
-struct tree_overload
+struct tree_overload GTY(())
{
struct tree_common common;
tree function;
};
-/* A `baselink' is a TREE_LIST whose TREE_PURPOSE is a BINFO
- indicating a particular base class, and whose TREE_VALUE is a
- (possibly overloaded) function from that base class. */
+/* Returns true iff NODE is a BASELINK. */
#define BASELINK_P(NODE) \
- (TREE_CODE (NODE) == TREE_LIST && TREE_LANG_FLAG_1 (NODE))
-#define SET_BASELINK_P(NODE) \
- (TREE_LANG_FLAG_1 (NODE) = 1)
-
-#define WRAPPER_PTR(NODE) (((struct tree_wrapper*)WRAPPER_CHECK (NODE))->u.ptr)
-#define WRAPPER_INT(NODE) (((struct tree_wrapper*)WRAPPER_CHECK (NODE))->u.i)
-
-struct tree_wrapper
+ (TREE_CODE (NODE) == BASELINK)
+/* The BINFO indicating the base from which the BASELINK_FUNCTIONS came. */
+#define BASELINK_BINFO(NODE) \
+ (TREE_OPERAND (BASELINK_CHECK (NODE), 0))
+/* The functions referred to by the BASELINK; either a FUNCTION_DECL,
+ a TEMPLATE_DECL, an OVERLOAD, or a TEMPLATE_ID_EXPR. */
+#define BASELINK_FUNCTIONS(NODE) \
+ (TREE_OPERAND (BASELINK_CHECK (NODE), 1))
+/* The BINFO in which the search for the functions indicated by this baselink
+ began. This base is used to determine the accessibility of functions
+ selected by overload resolution. */
+#define BASELINK_ACCESS_BINFO(NODE) \
+ (TREE_OPERAND (BASELINK_CHECK (NODE), 2))
+/* For a type-conversion operator, the BASELINK_OPTYPE indicates the type
+ to which the conversion should occur. This value is important if
+ the BASELINK_FUNCTIONS include a template conversion operator --
+ the BASELINK_OPTYPE can be used to determine what type the user
+ requested. */
+#define BASELINK_OPTYPE(NODE) \
+ (TREE_CHAIN (BASELINK_CHECK (NODE)))
+
+#define WRAPPER_ZC(NODE) (((struct tree_wrapper*)WRAPPER_CHECK (NODE))->z_c)
+
+struct tree_wrapper GTY(())
{
struct tree_common common;
- union {
- void *ptr;
- int i;
- } u;
+ struct z_candidate *z_c;
};
#define SRCLOC_FILE(NODE) (((struct tree_srcloc*)SRCLOC_CHECK (NODE))->filename)
#define SRCLOC_LINE(NODE) (((struct tree_srcloc*)SRCLOC_CHECK (NODE))->linenum)
-struct tree_srcloc
+struct tree_srcloc GTY(())
{
struct tree_common common;
const char *filename;
@@ -411,8 +449,8 @@ struct tree_srcloc
#define IDENTIFIER_TEMPLATE(NODE) \
(LANG_IDENTIFIER_CAST (NODE)->class_template_info)
-/* The IDENTIFIER_BINDING is the innermost CPLUS_BINDING for the
- identifier. It's TREE_CHAIN is the next outermost binding. Each
+/* The IDENTIFIER_BINDING is the innermost cxx_binding for the
+ identifier. It's PREVIOUS is the next outermost binding. Each
BINDING_VALUE is a DECL for the associated declaration. Thus,
name lookup consists simply of pulling off the node at the front
of the list (modulo oddities for looking up the names of types,
@@ -424,9 +462,7 @@ struct tree_srcloc
/* The IDENTIFIER_VALUE is the value of the IDENTIFIER_BINDING, or
NULL_TREE if there is no binding. */
#define IDENTIFIER_VALUE(NODE) \
- (IDENTIFIER_BINDING (NODE) \
- ? BINDING_VALUE (IDENTIFIER_BINDING (NODE)) \
- : NULL_TREE)
+ (IDENTIFIER_BINDING (NODE) ? BINDING_VALUE (IDENTIFIER_BINDING (NODE)) : 0)
/* If IDENTIFIER_CLASS_VALUE is set, then NODE is bound in the current
class, and IDENTIFIER_CLASS_VALUE is the value binding. This is
@@ -439,7 +475,7 @@ struct tree_srcloc
/* TREE_TYPE only indicates on local and class scope the current
type. For namespace scope, the presence of a type in any namespace
is indicated with global_type_node, and the real type behind must
- be found through lookup. */
+ be found through lookup. */
#define IDENTIFIER_TYPE_VALUE(NODE) identifier_type_value (NODE)
#define REAL_IDENTIFIER_TYPE_VALUE(NODE) TREE_TYPE (NODE)
#define SET_IDENTIFIER_TYPE_VALUE(NODE,TYPE) (TREE_TYPE (NODE) = (TYPE))
@@ -449,10 +485,10 @@ struct tree_srcloc
(LANG_IDENTIFIER_CAST (NODE)->x \
? LANG_IDENTIFIER_CAST (NODE)->x->NAME : 0)
-#define SET_LANG_ID(NODE, VALUE, NAME) \
- (LANG_IDENTIFIER_CAST (NODE)->x == 0 \
- ? LANG_IDENTIFIER_CAST (NODE)->x \
- = (struct lang_id2 *)perm_calloc (1, sizeof (struct lang_id2)) : 0, \
+#define SET_LANG_ID(NODE, VALUE, NAME) \
+ (LANG_IDENTIFIER_CAST (NODE)->x == 0 \
+ ? LANG_IDENTIFIER_CAST (NODE)->x \
+ = (struct lang_id2 *)ggc_alloc_cleared (sizeof (struct lang_id2)) : 0, \
LANG_IDENTIFIER_CAST (NODE)->x->NAME = (VALUE))
#define IDENTIFIER_LABEL_VALUE(NODE) \
@@ -494,11 +530,35 @@ struct tree_srcloc
/* Store a value in that field. */
#define C_SET_EXP_ORIGINAL_CODE(EXP, CODE) \
(TREE_COMPLEXITY (EXP) = (int)(CODE))
-
-/* If non-zero, a VAR_DECL whose cleanup will cause a throw to the
- next exception handler. */
-extern tree exception_throw_decl;
+enum cp_tree_node_structure_enum {
+ TS_CP_COMMON,
+ TS_CP_GENERIC,
+ TS_CP_IDENTIFIER,
+ TS_CP_TPI,
+ TS_CP_PTRMEM,
+ TS_CP_OVERLOAD,
+ TS_CP_WRAPPER,
+ TS_CP_SRCLOC,
+ LAST_TS_CP_ENUM
+};
+
+/* The resulting tree type. */
+union lang_tree_node GTY((desc ("cp_tree_node_structure (&%h)"),
+ chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
+{
+ struct tree_common GTY ((tag ("TS_CP_COMMON"))) common;
+ union tree_node GTY ((tag ("TS_CP_GENERIC"),
+ desc ("tree_node_structure (&%h)"))) generic;
+ struct template_parm_index_s GTY ((tag ("TS_CP_TPI"))) tpi;
+ struct ptrmem_cst GTY ((tag ("TS_CP_PTRMEM"))) ptrmem;
+ struct tree_overload GTY ((tag ("TS_CP_OVERLOAD"))) overload;
+ struct tree_wrapper GTY ((tag ("TS_CP_WRAPPER"))) wrapper;
+ struct tree_srcloc GTY ((tag ("TS_CP_SRCLOC"))) srcloc;
+ struct lang_identifier GTY ((tag ("TS_CP_IDENTIFIER"))) identifier;
+};
+
+
enum cp_tree_index
{
CPTI_JAVA_BYTE_TYPE,
@@ -582,10 +642,12 @@ enum cp_tree_index
CPTI_DSO_HANDLE,
CPTI_DCAST,
+ CPTI_KEYED_CLASSES,
+
CPTI_MAX
};
-extern tree cp_global_trees[CPTI_MAX];
+extern GTY(()) tree cp_global_trees[CPTI_MAX];
#define java_byte_type_node cp_global_trees[CPTI_JAVA_BYTE_TYPE]
#define java_short_type_node cp_global_trees[CPTI_JAVA_SHORT_TYPE]
@@ -687,7 +749,7 @@ extern tree cp_global_trees[CPTI_MAX];
/* The node for `__null'. */
#define null_node cp_global_trees[CPTI_NULL]
-/* If non-NULL, a POINTER_TYPE equivalent to (java::lang::Class*). */
+/* If non-NULL, a POINTER_TYPE equivalent to (java::lang::Class*). */
#define jclass_node cp_global_trees[CPTI_JCLASS]
/* The declaration for `std::terminate'. */
@@ -712,11 +774,16 @@ extern tree cp_global_trees[CPTI_MAX];
destructors. */
#define vtt_parm_type cp_global_trees[CPTI_VTT_PARM_TYPE]
+/* A TREE_LIST of the dynamic classes whose vtables may have to be
+ emitted in this translation unit. */
+
+#define keyed_classes cp_global_trees[CPTI_KEYED_CLASSES]
+
/* Global state. */
-struct saved_scope
+struct saved_scope GTY(())
{
- tree old_bindings;
+ cxx_saved_binding *old_bindings;
tree old_namespace;
tree decl_ns_list;
tree class_name;
@@ -739,8 +806,8 @@ struct saved_scope
struct stmt_tree_s x_stmt_tree;
- struct binding_level *class_bindings;
- struct binding_level *bindings;
+ struct cp_binding_level *class_bindings;
+ struct cp_binding_level *bindings;
struct saved_scope *prev;
};
@@ -749,7 +816,7 @@ struct saved_scope
#define current_namespace scope_chain->old_namespace
-/* The stack for namespaces of current declarations. */
+/* The stack for namespaces of current declarations. */
#define decl_namespace_list scope_chain->decl_ns_list
@@ -797,15 +864,15 @@ struct saved_scope
#define type_lookups scope_chain->lookups
-extern struct saved_scope *scope_chain;
+extern GTY(()) struct saved_scope *scope_chain;
struct unparsed_text;
/* Global state pertinent to the current function. */
-struct cp_language_function
+struct language_function GTY(())
{
- struct language_function base;
+ struct c_language_function base;
tree x_dtor_label;
tree x_current_class_ptr;
@@ -815,17 +882,19 @@ struct cp_language_function
tree x_vtt_parm;
tree x_return_value;
- tree *x_vcalls_possible_p;
-
int returns_value;
int returns_null;
int returns_abnormally;
int in_function_try_handler;
+ int in_base_initializer;
int x_expanding_p;
+ /* True if this function can throw an exception. */
+ bool can_throw : 1;
+
struct named_label_use_list *x_named_label_uses;
struct named_label_list *x_named_labels;
- struct binding_level *bindings;
+ struct cp_binding_level *bindings;
varray_type x_local_names;
const char *cannot_inline;
@@ -834,8 +903,7 @@ struct cp_language_function
/* The current C++-specific per-function global variables. */
-#define cp_function_chain \
- ((struct cp_language_function *) (cfun->language))
+#define cp_function_chain (cfun->language)
/* In a destructor, the point at which all derived class destroying
has been done, just before any base class destroying will be done. */
@@ -866,12 +934,6 @@ struct cp_language_function
#define current_vtt_parm cp_function_chain->x_vtt_parm
-/* In destructors, this is a pointer to a condition in an
- if-statement. If the pointed-to value is boolean_true_node, then
- there may be virtual function calls in this destructor. */
-
-#define current_vcalls_possible_p cp_function_chain->x_vcalls_possible_p
-
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
@@ -888,17 +950,20 @@ struct cp_language_function
#define current_function_returns_abnormally \
cp_function_chain->returns_abnormally
-/* Non-zero if we should generate RTL for functions that we process.
+/* Nonzero if we should generate RTL for functions that we process.
When this is zero, we just accumulate tree structure, without
interacting with the back end. */
#define expanding_p cp_function_chain->x_expanding_p
-/* Non-zero if we are in the semantic analysis phase for the current
+/* Nonzero if we are in the semantic analysis phase for the current
function. */
#define doing_semantic_analysis_p() (!expanding_p)
+/* Non-zero if we are processing a base initializer. Zero elsewhere. */
+#define in_base_initializer cp_function_chain->in_base_initializer
+
#define in_function_try_handler cp_function_chain->in_function_try_handler
/* Expression always returned from function, or error_mark_node
@@ -907,112 +972,18 @@ struct cp_language_function
#define current_function_return_value \
(cp_function_chain->x_return_value)
-extern tree global_namespace;
+extern GTY(()) tree global_namespace;
#define ansi_opname(CODE) \
(operator_name_info[(int) (CODE)].identifier)
#define ansi_assopname(CODE) \
(assignment_operator_name_info[(int) (CODE)].identifier)
-/* Nonzero means `$' can be in an identifier. */
-
-extern int dollars_in_ident;
-
-/* Nonzero means don't recognize the keyword `asm'. */
-
-extern int flag_no_asm;
-
-/* Nonzero means don't recognize any extended keywords. */
-
-extern int flag_no_gnu_keywords;
-
-/* Nonzero means recognize the named operators from C++98. */
-
-extern int flag_operator_names;
-
-/* For environments where you can use GNU binutils (as, ld in particular). */
+/* True if NODE is an erroneous expression. */
-extern int flag_gnu_binutils;
-
-/* Nonzero means warn about things that will change when compiling
- with an ABI-compliant compiler. */
-
-extern int warn_abi;
-
-/* Nonzero means warn about implicit declarations. */
-
-extern int warn_implicit;
-
-/* Nonzero means warn when all ctors or dtors are private, and the class
- has no friends. */
-
-extern int warn_ctor_dtor_privacy;
-
-/* Nonzero means warn about deprecated conversion from string constant to
- `char *'. */
-
-extern int warn_write_strings;
-
-/* Nonzero means warn about multiple (redundant) decls for the same single
- variable or function. */
-
-extern int warn_redundant_decls;
-
-/* Warn if initializer is not completely bracketed. */
-
-extern int warn_missing_braces;
-
-/* Warn about comparison of signed and unsigned values. */
-
-extern int warn_sign_compare;
-
-/* Warn about testing equality of floating point numbers. */
-
-extern int warn_float_equal;
-
-/* Warn about a subscript that has type char. */
-
-extern int warn_char_subscripts;
-
-/* Nonzero means warn about pointer casts that can drop a type qualifier
- from the pointer target type. */
-
-extern int warn_cast_qual;
-
-/* Nonzero means warn about non virtual destructors in classes that have
- 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 an old-style cast is used. */
-
-extern int warn_old_style_cast;
-
-/* Non-zero means warn when the compiler will reorder code. */
-
-extern int warn_reorder;
-
-/* Non-zero means warn about deprecated features. */
-
-extern int warn_deprecated;
-
-/* Nonzero means to treat bitfields as unsigned unless they say `signed'. */
-
-extern int flag_signed_bitfields;
+#define error_operand_p(NODE) \
+ ((NODE) == error_mark_node \
+ || ((NODE) && TREE_TYPE ((NODE)) == error_mark_node))
/* INTERFACE_ONLY nonzero means that we are in an "interface"
section of the compiler. INTERFACE_UNKNOWN nonzero means
@@ -1020,52 +991,6 @@ extern int flag_signed_bitfields;
is zero and INTERFACE_ONLY is zero, it means that we are responsible
for exporting definitions that others might need. */
extern int interface_only, interface_unknown;
-
-/* Nonzero means we should attempt to elide constructors when possible. */
-
-extern int flag_elide_constructors;
-
-/* Nonzero means enable obscure standard features and disable GNU
- extensions that might cause standard-compliant code to be
- miscompiled. */
-
-extern int flag_ansi;
-
-/* Nonzero means that member functions defined in class scope are
- inline by default. */
-
-extern int flag_default_inline;
-
-/* Nonzero means generate separate instantiation control files and juggle
- them at link time. */
-extern int flag_use_repository;
-
-/* Nonzero if we want to issue diagnostics that the standard says are not
- required. */
-extern int flag_optional_diags;
-
-/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */
-extern int flag_vtable_gc;
-
-/* Nonzero means make the default pedwarns warnings instead of errors.
- The value of this flag is ignored if -pedantic is specified. */
-extern int flag_permissive;
-
-/* Nonzero means to implement standard semantics for exception
- specifications, calling unexpected if an exception is thrown that
- doesn't match the specification. Zero means to treat them as
- assertions and optimize accordingly, but not check them. */
-extern int flag_enforce_eh_specs;
-
-/* Nonzero if we want to obey access control semantics. */
-
-extern int flag_access_control;
-
-/* Nonzero if we want to check the return value of new and avoid calling
- constructors if it is a null pointer. */
-
-extern int flag_check_new;
-
/* C++ language-specific tree codes. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
@@ -1130,7 +1055,7 @@ enum languages { lang_c, lang_cplusplus, lang_java };
/* In a *_TYPE, nonzero means a built-in type. */
#define TYPE_BUILT_IN(NODE) TYPE_LANG_FLAG_6 (NODE)
-/* True if this a "Java" type, defined in 'extern "Java"'. */
+/* True if this a "Java" type, defined in 'extern "Java"'. */
#define TYPE_FOR_JAVA(NODE) TYPE_LANG_FLAG_3 (NODE)
/* Nonzero if this type is const-qualified. */
@@ -1173,19 +1098,36 @@ enum languages { lang_c, lang_cplusplus, lang_java };
/* Nonzero iff TYPE is derived from PARENT. Ignores accessibility and
ambiguity issues. */
#define DERIVED_FROM_P(PARENT, TYPE) \
- lookup_base ((TYPE), PARENT, ba_any, NULL)
+ (lookup_base ((TYPE), PARENT, ba_any, NULL) != NULL_TREE)
/* Nonzero iff TYPE is uniquely derived from PARENT. Ignores
accessibility. */
#define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) \
- lookup_base ((TYPE), (PARENT), ba_ignore | ba_quiet, NULL)
+ (lookup_base ((TYPE), (PARENT), ba_ignore | ba_quiet, NULL) != NULL_TREE)
/* Nonzero iff TYPE is accessible in the current scope and uniquely
derived from PARENT. */
#define ACCESSIBLY_UNIQUELY_DERIVED_P(PARENT, TYPE) \
- lookup_base ((TYPE), (PARENT), ba_check | ba_quiet, NULL)
+ (lookup_base ((TYPE), (PARENT), ba_check | ba_quiet, NULL) != NULL_TREE)
/* Nonzero iff TYPE is publicly & uniquely derived from PARENT. */
#define PUBLICLY_UNIQUELY_DERIVED_P(PARENT, TYPE) \
- lookup_base ((TYPE), (PARENT), ba_not_special | ba_quiet, NULL)
+ (lookup_base ((TYPE), (PARENT), ba_not_special | ba_quiet, NULL) \
+ != NULL_TREE)
+/* This is a few header flags for 'struct lang_type'. Actually,
+ all but the first are used only for lang_type_class; they
+ are put in this structure to save space. */
+struct lang_type_header GTY(())
+{
+ unsigned is_lang_type_class : 1;
+
+ unsigned has_type_conversion : 1;
+ unsigned has_init_ref : 1;
+ unsigned has_default_ctor : 1;
+ unsigned uses_multiple_inheritance : 1;
+ unsigned const_needs_init : 1;
+ unsigned ref_needs_init : 1;
+ unsigned has_const_assign_ref : 1;
+};
+
/* This structure provides additional information above and beyond
what is provide in the ordinary tree_type. In the past, we used it
for the types of class types, template parameters types, typename
@@ -1199,19 +1141,12 @@ enum languages { lang_c, lang_cplusplus, lang_java };
many (i.e., thousands) of classes can easily be generated.
Therefore, we should endeavor to keep the size of this structure to
a minimum. */
-struct lang_type
+struct lang_type_class GTY(())
{
+ struct lang_type_header h;
+
unsigned char align;
- unsigned has_type_conversion : 1;
- unsigned has_init_ref : 1;
- unsigned has_default_ctor : 1;
- unsigned uses_multiple_inheritance : 1;
- unsigned const_needs_init : 1;
- unsigned ref_needs_init : 1;
- unsigned has_const_assign_ref : 1;
- unsigned anon_aggr : 1;
-
unsigned has_mutable : 1;
unsigned com_interface : 1;
unsigned non_pod_class : 1;
@@ -1227,7 +1162,6 @@ struct lang_type
unsigned has_arrow_overloaded : 1;
unsigned interface_only : 1;
unsigned interface_unknown : 1;
- unsigned needs_virtual_reinit : 1;
unsigned marks: 6;
unsigned vec_new_uses_cookie : 1;
@@ -1250,7 +1184,9 @@ struct lang_type
unsigned is_partial_instantiation : 1;
unsigned java_interface : 1;
+ unsigned anon_aggr : 1;
unsigned non_zero_init : 1;
+ unsigned empty_p : 1;
unsigned contains_empty_class_p : 1;
/* When adding a flag here, consider whether or not it ought to
@@ -1260,31 +1196,69 @@ struct lang_type
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
- unsigned dummy : 6;
-
- int vsize;
+ unsigned dummy : 5;
tree primary_base;
tree vfields;
+ tree vcall_indices;
+ tree vtables;
tree typeinfo_var;
tree vbases;
- tree tags;
- tree size;
- tree size_unit;
+ binding_table nested_udts;
+ tree as_base;
tree pure_virtuals;
tree friend_classes;
- tree rtti;
tree methods;
+ tree key_method;
+ tree decl_list;
tree template_info;
tree befriending_classes;
};
+struct lang_type_ptrmem GTY(())
+{
+ struct lang_type_header h;
+ tree record;
+};
+
+struct lang_type GTY(())
+{
+ union lang_type_u
+ {
+ struct lang_type_header GTY((tag ("2"))) h;
+ struct lang_type_class GTY((tag ("1"))) c;
+ struct lang_type_ptrmem GTY((tag ("0"))) ptrmem;
+ } GTY((desc ("%h.h.is_lang_type_class"))) u;
+};
+
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+
+#define LANG_TYPE_CLASS_CHECK(NODE) \
+({ struct lang_type *lt = TYPE_LANG_SPECIFIC (NODE); \
+ if (! lt->u.h.is_lang_type_class) \
+ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
+ &lt->u.c; })
+
+#define LANG_TYPE_PTRMEM_CHECK(NODE) \
+({ struct lang_type *lt = TYPE_LANG_SPECIFIC (NODE); \
+ if (lt->u.h.is_lang_type_class) \
+ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
+ &lt->u.ptrmem; })
+
+#else
+
+#define LANG_TYPE_CLASS_CHECK(NODE) (&TYPE_LANG_SPECIFIC (NODE)->u.c)
+#define LANG_TYPE_PTRMEM_CHECK(NODE) (&TYPE_LANG_SPECIFIC (NODE)->u.ptrmem)
+
+#endif /* ENABLE_TREE_CHECKING */
+
/* Indicates whether or not (and how) a template was expanded for this class.
0=no information yet/non-template class
1=implicit template instantiation
2=explicit template specialization
3=explicit template instantiation */
-#define CLASSTYPE_USE_TEMPLATE(NODE) (TYPE_LANG_SPECIFIC (NODE)->use_template)
+#define CLASSTYPE_USE_TEMPLATE(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->use_template)
/* Fields used for storing information before the class is defined.
After the class is defined, these fields hold other information. */
@@ -1293,79 +1267,93 @@ struct lang_type
#define CLASSTYPE_INLINE_FRIENDS(NODE) CLASSTYPE_PURE_VIRTUALS (NODE)
/* Nonzero for _CLASSTYPE means that operator delete is defined. */
-#define TYPE_GETS_DELETE(NODE) (TYPE_LANG_SPECIFIC (NODE)->gets_delete)
+#define TYPE_GETS_DELETE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->gets_delete)
#define TYPE_GETS_REG_DELETE(NODE) (TYPE_GETS_DELETE (NODE) & 1)
/* Nonzero if `new NODE[x]' should cause the allocation of extra
storage to indicate how many array elements are in use. */
#define TYPE_VEC_NEW_USES_COOKIE(NODE) \
(CLASS_TYPE_P (NODE) \
- && TYPE_LANG_SPECIFIC (NODE)->vec_new_uses_cookie)
+ && LANG_TYPE_CLASS_CHECK (NODE)->vec_new_uses_cookie)
/* Nonzero means that this _CLASSTYPE node defines ways of converting
itself to other types. */
#define TYPE_HAS_CONVERSION(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_type_conversion)
+ (LANG_TYPE_CLASS_CHECK (NODE)->h.has_type_conversion)
/* Nonzero means that this _CLASSTYPE node overloads operator=(X&). */
-#define TYPE_HAS_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_assign_ref)
+#define TYPE_HAS_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_assign_ref)
#define TYPE_HAS_CONST_ASSIGN_REF(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_const_assign_ref)
+ (LANG_TYPE_CLASS_CHECK (NODE)->h.has_const_assign_ref)
/* Nonzero means that this _CLASSTYPE node has an X(X&) constructor. */
-#define TYPE_HAS_INIT_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_init_ref)
+#define TYPE_HAS_INIT_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->h.has_init_ref)
#define TYPE_HAS_CONST_INIT_REF(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_const_init_ref)
+ (LANG_TYPE_CLASS_CHECK (NODE)->has_const_init_ref)
/* Nonzero if this class defines an overloaded operator new. (An
operator new [] doesn't count.) */
#define TYPE_HAS_NEW_OPERATOR(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_new)
+ (LANG_TYPE_CLASS_CHECK (NODE)->has_new)
/* Nonzero if this class defines an overloaded operator new[]. */
#define TYPE_HAS_ARRAY_NEW_OPERATOR(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_array_new)
+ (LANG_TYPE_CLASS_CHECK (NODE)->has_array_new)
/* Nonzero means that this type is being defined. I.e., the left brace
starting the definition of this type has been seen. */
-#define TYPE_BEING_DEFINED(NODE) (TYPE_LANG_SPECIFIC (NODE)->being_defined)
+#define TYPE_BEING_DEFINED(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->being_defined)
/* Nonzero means that this type has been redefined. In this case, if
convenient, don't reprocess any methods that appear in its redefinition. */
-#define TYPE_REDEFINED(NODE) (TYPE_LANG_SPECIFIC (NODE)->redefined)
-
-/* The is the basetype that contains NODE's rtti. */
-#define CLASSTYPE_RTTI(NODE) (TYPE_LANG_SPECIFIC (NODE)->rtti)
+#define TYPE_REDEFINED(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->redefined)
/* Nonzero means that this _CLASSTYPE node overloads operator(). */
#define TYPE_OVERLOADS_CALL_EXPR(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_call_overloaded)
+ (LANG_TYPE_CLASS_CHECK (NODE)->has_call_overloaded)
/* Nonzero means that this _CLASSTYPE node overloads operator[]. */
#define TYPE_OVERLOADS_ARRAY_REF(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_array_ref_overloaded)
+ (LANG_TYPE_CLASS_CHECK (NODE)->has_array_ref_overloaded)
/* Nonzero means that this _CLASSTYPE node overloads operator->. */
#define TYPE_OVERLOADS_ARROW(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_arrow_overloaded)
+ (LANG_TYPE_CLASS_CHECK (NODE)->has_arrow_overloaded)
/* Nonzero means that this _CLASSTYPE (or one of its ancestors) uses
multiple inheritance. If this is 0 for the root of a type
hierarchy, then we can use more efficient search techniques. */
#define TYPE_USES_MULTIPLE_INHERITANCE(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->uses_multiple_inheritance)
+ (LANG_TYPE_CLASS_CHECK (NODE)->h.uses_multiple_inheritance)
/* Nonzero means that this _CLASSTYPE (or one of its ancestors) uses
virtual base classes. If this is 0 for the root of a type
hierarchy, then we can use more efficient search techniques. */
#define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3 (NODE))
+/* The member function with which the vtable will be emitted:
+ the first noninline non-pure-virtual member function. NULL_TREE
+ if there is no key function or if this is a class template */
+#define CLASSTYPE_KEY_METHOD(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->key_method)
+
/* Vector member functions defined in this class. Each element is
either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD. All
functions with the same name end up in the same slot. The first
two elements are for constructors, and destructors, respectively.
- Any conversion operators are next, followed by ordinary member
- functions. There may be empty entries at the end of the vector. */
-#define CLASSTYPE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC (NODE)->methods)
+ All template conversion operators to innermost template dependent
+ types are overloaded on the next slot, if they exist. Note, the
+ names for these functions will not all be the same. The
+ non-template conversion operators & templated conversions to
+ non-innermost template types are next, followed by ordinary member
+ functions. There may be empty entries at the end of the vector.
+ The conversion operators are unsorted. The ordinary member
+ functions are sorted, once the class is complete. */
+#define CLASSTYPE_METHOD_VEC(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->methods)
+
+/* For class templates, this is a TREE_LIST of all member data,
+ functions, types, and friends in the order of declaration.
+ The TREE_PURPOSE of each TREE_LIST is NULL_TREE for a friend,
+ and the RECORD_TYPE for the class template otherwise. */
+#define CLASSTYPE_DECL_LIST(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->decl_list)
/* The slot in the CLASSTYPE_METHOD_VEC where constructors go. */
#define CLASSTYPE_CONSTRUCTOR_SLOT 0
@@ -1391,19 +1379,19 @@ struct lang_type
/* Get the value of the Nth mark bit. */
#define CLASSTYPE_MARKED_N(NODE, N) \
- (((CLASS_TYPE_P (NODE) ? TYPE_LANG_SPECIFIC (NODE)->marks \
+ (((CLASS_TYPE_P (NODE) ? LANG_TYPE_CLASS_CHECK (NODE)->marks \
: ((unsigned) TYPE_ALIAS_SET (NODE))) & (1 << (N))) != 0)
/* Set the Nth mark bit. */
#define SET_CLASSTYPE_MARKED_N(NODE, N) \
(CLASS_TYPE_P (NODE) \
- ? (void) (TYPE_LANG_SPECIFIC (NODE)->marks |= (1 << (N))) \
+ ? (void) (LANG_TYPE_CLASS_CHECK (NODE)->marks |= (1 << (N))) \
: (void) (TYPE_ALIAS_SET (NODE) |= (1 << (N))))
/* Clear the Nth mark bit. */
#define CLEAR_CLASSTYPE_MARKED_N(NODE, N) \
(CLASS_TYPE_P (NODE) \
- ? (void) (TYPE_LANG_SPECIFIC (NODE)->marks &= ~(1 << (N))) \
+ ? (void) (LANG_TYPE_CLASS_CHECK (NODE)->marks &= ~(1 << (N))) \
: (void) (TYPE_ALIAS_SET (NODE) &= ~(1 << (N))))
/* Get the value of the mark bits. */
@@ -1428,11 +1416,12 @@ struct lang_type
#define SET_CLASSTYPE_MARKED6(NODE) SET_CLASSTYPE_MARKED_N (NODE, 5)
#define CLEAR_CLASSTYPE_MARKED6(NODE) CLEAR_CLASSTYPE_MARKED_N (NODE, 5)
-/* A list of the nested tag-types (class, struct, union, or enum)
- found within this class. The TREE_PURPOSE of each node is the name
- of the type; the TREE_VALUE is the type itself. This list includes
+/* A binding_table of the nested tag-types (class, struct, union, or enum)
+ found within this class. The ENTRY->name of each node is the name
+ of the type; the ENTRY->type is the type itself. This table includes
nested member class templates. */
-#define CLASSTYPE_TAGS(NODE) (TYPE_LANG_SPECIFIC (NODE)->tags)
+#define CLASSTYPE_NESTED_UDTS(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->nested_udts)
/* Nonzero if NODE has a primary base class, i.e., a base class with
which it shares the virtual function table pointer. */
@@ -1443,11 +1432,7 @@ struct lang_type
the base class which contains the virtual function table pointer
for this class. */
#define CLASSTYPE_PRIMARY_BINFO(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->primary_base)
-
-/* The number of virtual functions present in this class' virtual
- function table. */
-#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC (NODE)->vsize)
+ (LANG_TYPE_CLASS_CHECK (NODE)->primary_base)
/* A chain of BINFOs for the direct and indirect virtual base classes
that this type uses in a post-order depth-first left-to-right
@@ -1457,7 +1442,7 @@ struct lang_type
list are all "real"; they are the same BINFOs that will be
encountered when using dfs_unmarked_real_bases_queue_p and related
functions. */
-#define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC (NODE)->vbases)
+#define CLASSTYPE_VBASECLASSES(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->vbases)
/* For a non-virtual BINFO, the BINFO itself; for a virtual BINFO, the
binfo_for_vbase. C is the most derived class for the hierarchy
@@ -1471,95 +1456,98 @@ struct lang_type
#define CLASSTYPE_N_BASECLASSES(NODE) \
(BINFO_N_BASETYPES (TYPE_BINFO (NODE)))
+/* The type corresponding to NODE when NODE is used as a base class,
+ i.e., NODE without virtual base classes. */
+
+#define CLASSTYPE_AS_BASE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->as_base)
+
/* These are the size and alignment of the type without its virtual
base classes, for when we use this type as a base itself. */
-#define CLASSTYPE_SIZE(NODE) (TYPE_LANG_SPECIFIC (NODE)->size)
-#define CLASSTYPE_SIZE_UNIT(NODE) (TYPE_LANG_SPECIFIC (NODE)->size_unit)
-#define CLASSTYPE_ALIGN(NODE) (TYPE_LANG_SPECIFIC (NODE)->align)
-#define CLASSTYPE_USER_ALIGN(NODE) (TYPE_LANG_SPECIFIC (NODE)->user_align)
+#define CLASSTYPE_SIZE(NODE) TYPE_SIZE (CLASSTYPE_AS_BASE (NODE))
+#define CLASSTYPE_SIZE_UNIT(NODE) TYPE_SIZE_UNIT (CLASSTYPE_AS_BASE (NODE))
+#define CLASSTYPE_ALIGN(NODE) TYPE_ALIGN (CLASSTYPE_AS_BASE (NODE))
+#define CLASSTYPE_USER_ALIGN(NODE) TYPE_USER_ALIGN (CLASSTYPE_AS_BASE (NODE))
/* The alignment of NODE, without its virtual bases, in bytes. */
#define CLASSTYPE_ALIGN_UNIT(NODE) \
(CLASSTYPE_ALIGN (NODE) / BITS_PER_UNIT)
/* True if this a Java interface type, declared with
- '__attribute__ ((java_interface))'. */
-#define TYPE_JAVA_INTERFACE(NODE) (TYPE_LANG_SPECIFIC (NODE)->java_interface)
+ '__attribute__ ((java_interface))'. */
+#define TYPE_JAVA_INTERFACE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->java_interface)
/* A cons list of virtual functions which cannot be inherited by
derived classes. When deriving from this type, the derived
class must provide its own definition for each of these functions. */
-#define CLASSTYPE_PURE_VIRTUALS(NODE) (TYPE_LANG_SPECIFIC (NODE)->pure_virtuals)
+#define CLASSTYPE_PURE_VIRTUALS(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->pure_virtuals)
/* Nonzero means that this aggr type has been `closed' by a semicolon. */
-#define CLASSTYPE_GOT_SEMICOLON(NODE) (TYPE_LANG_SPECIFIC (NODE)->got_semicolon)
-
-/* Nonzero means that the main virtual function table pointer needs to be
- set because base constructors have placed the wrong value there.
- If this is zero, it means that they placed the right value there,
- and there is no need to change it. */
-#define CLASSTYPE_NEEDS_VIRTUAL_REINIT(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->needs_virtual_reinit)
+#define CLASSTYPE_GOT_SEMICOLON(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->got_semicolon)
/* Nonzero means that this type has an X() constructor. */
#define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->has_default_ctor)
+ (LANG_TYPE_CLASS_CHECK (NODE)->h.has_default_ctor)
/* Nonzero means that this type contains a mutable member */
-#define CLASSTYPE_HAS_MUTABLE(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_mutable)
+#define CLASSTYPE_HAS_MUTABLE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_mutable)
#define TYPE_HAS_MUTABLE_P(NODE) (cp_has_mutable_p (NODE))
/* Nonzero means that this class type is a non-POD class. */
-#define CLASSTYPE_NON_POD_P(NODE) (TYPE_LANG_SPECIFIC (NODE)->non_pod_class)
+#define CLASSTYPE_NON_POD_P(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->non_pod_class)
/* Nonzero means that this class contains pod types whose default
initialization is not a zero initialization (namely, pointers to
data members). */
-#define CLASSTYPE_NON_ZERO_INIT_P(NODE) (TYPE_LANG_SPECIFIC (NODE)->non_zero_init)
+#define CLASSTYPE_NON_ZERO_INIT_P(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->non_zero_init)
+
+/* Nonzero if this class is "empty" in the sense of the C++ ABI. */
+#define CLASSTYPE_EMPTY_P(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->empty_p)
/* Nonzero if this class is "nearly empty", i.e., contains only a
virtual function table pointer. */
#define CLASSTYPE_NEARLY_EMPTY_P(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->nearly_empty_p)
+ (LANG_TYPE_CLASS_CHECK (NODE)->nearly_empty_p)
/* Nonzero if this class contains an empty subobject. */
#define CLASSTYPE_CONTAINS_EMPTY_CLASS_P(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->contains_empty_class_p)
+ (LANG_TYPE_CLASS_CHECK (NODE)->contains_empty_class_p)
/* A list of class types of which this type is a friend. The
TREE_VALUE is normally a TYPE, but will be a TEMPLATE_DECL in the
case of a template friend. */
#define CLASSTYPE_FRIEND_CLASSES(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->friend_classes)
+ (LANG_TYPE_CLASS_CHECK (NODE)->friend_classes)
/* A list of the classes which grant friendship to this class. */
#define CLASSTYPE_BEFRIENDING_CLASSES(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->befriending_classes)
+ (LANG_TYPE_CLASS_CHECK (NODE)->befriending_classes)
/* Say whether this node was declared as a "class" or a "struct". */
#define CLASSTYPE_DECLARED_CLASS(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->declared_class)
+ (LANG_TYPE_CLASS_CHECK (NODE)->declared_class)
/* Nonzero if this class has const members
which have no specified initialization. */
#define CLASSTYPE_READONLY_FIELDS_NEED_INIT(NODE) \
(TYPE_LANG_SPECIFIC (NODE) \
- ? TYPE_LANG_SPECIFIC (NODE)->const_needs_init : 0)
+ ? LANG_TYPE_CLASS_CHECK (NODE)->h.const_needs_init : 0)
#define SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT(NODE, VALUE) \
- (TYPE_LANG_SPECIFIC (NODE)->const_needs_init = (VALUE))
+ (LANG_TYPE_CLASS_CHECK (NODE)->h.const_needs_init = (VALUE))
/* Nonzero if this class has ref members
which have no specified initialization. */
#define CLASSTYPE_REF_FIELDS_NEED_INIT(NODE) \
(TYPE_LANG_SPECIFIC (NODE) \
- ? TYPE_LANG_SPECIFIC (NODE)->ref_needs_init : 0)
+ ? LANG_TYPE_CLASS_CHECK (NODE)->h.ref_needs_init : 0)
#define SET_CLASSTYPE_REF_FIELDS_NEED_INIT(NODE, VALUE) \
- (TYPE_LANG_SPECIFIC (NODE)->ref_needs_init = (VALUE))
+ (LANG_TYPE_CLASS_CHECK (NODE)->h.ref_needs_init = (VALUE))
/* Nonzero if this class is included from a header file which employs
`#pragma interface', and it is not included in its implementation file. */
#define CLASSTYPE_INTERFACE_ONLY(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->interface_only)
+ (LANG_TYPE_CLASS_CHECK (NODE)->interface_only)
/* True if we have already determined whether or not vtables, VTTs,
typeinfo, and other similar per-class data should be emitted in
@@ -1567,21 +1555,21 @@ struct lang_type
these items should be emitted; it only indicates that we know one
way or the other. */
#define CLASSTYPE_INTERFACE_KNOWN(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->interface_unknown == 0)
+ (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown == 0)
/* The opposite of CLASSTYPE_INTERFANCE_KNOWN. */
#define CLASSTYPE_INTERFACE_UNKNOWN(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->interface_unknown)
+ (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown)
#define SET_CLASSTYPE_INTERFACE_UNKNOWN_X(NODE,X) \
- (TYPE_LANG_SPECIFIC (NODE)->interface_unknown = !!(X))
+ (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown = !!(X))
#define SET_CLASSTYPE_INTERFACE_UNKNOWN(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->interface_unknown = 1)
+ (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown = 1)
#define SET_CLASSTYPE_INTERFACE_KNOWN(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->interface_unknown = 0)
+ (LANG_TYPE_CLASS_CHECK (NODE)->interface_unknown = 0)
/* Nonzero if a _DECL node requires us to output debug info for this class. */
#define CLASSTYPE_DEBUG_REQUESTED(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->debug_requested)
+ (LANG_TYPE_CLASS_CHECK (NODE)->debug_requested)
/* Additional macros for inheritance information. */
@@ -1687,45 +1675,60 @@ struct lang_type
/* Used by various search routines. */
#define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
+/* A TREE_LIST of the vcall indices associated with the class NODE.
+ The TREE_PURPOSE of each node is a FUNCTION_DECL for a virtual
+ function. The TREE_VALUE is the index into the virtual table where
+ the vcall offset for that function is stored, when NODE is a
+ virtual base. */
+#define CLASSTYPE_VCALL_INDICES(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->vcall_indices)
+
+/* The various vtables for the class NODE. The primary vtable will be
+ first, followed by the construction vtables and VTT, if any. */
+#define CLASSTYPE_VTABLES(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->vtables)
+
/* The std::type_info variable representing this class, or NULL if no
such variable has been created. This field is only set for the
TYPE_MAIN_VARIANT of the class. */
#define CLASSTYPE_TYPEINFO_VAR(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->typeinfo_var)
+ (LANG_TYPE_CLASS_CHECK (NODE)->typeinfo_var)
/* Accessor macros for the vfield slots in structures. */
-/* The virtual function pointer fields that this type contains. For a
- vfield defined just for this class, or from a primary base, the
- TREE_PURPOSE is NULL. Otherwise, the TREE_PURPOSE is the BINFO for
- the class containing the vfield. The TREE_VALUE is the class where
- the vfield was first defined. */
-#define CLASSTYPE_VFIELDS(NODE) (TYPE_LANG_SPECIFIC (NODE)->vfields)
-
-/* Get the assoc info that caused this vfield to exist. */
+/* List of virtual table fields that this type contains (both the primary
+ and secondaries). The TREE_VALUE is the class type where the vtable
+ field was introduced. For a vtable field inherited from the primary
+ base, or introduced by this class, the TREE_PURPOSE is NULL. For
+ other vtable fields (those from non-primary bases), the
+ TREE_PURPOSE is the BINFO of the base through which the vtable was
+ inherited. */
+#define CLASSTYPE_VFIELDS(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->vfields)
+
+/* Get the BINFO that introduced this vtable into the hierarchy (will
+ be NULL for those created at this level, or from a primary
+ hierarchy). */
#define VF_BINFO_VALUE(NODE) TREE_PURPOSE (NODE)
-/* Get that same information as a _TYPE. */
+/* Get the TYPE that introduced this vtable into the hierarchy (always
+ non-NULL). */
#define VF_BASETYPE_VALUE(NODE) TREE_VALUE (NODE)
-/* Get the value of the top-most type dominating the non-`normal' vfields. */
-#define VF_DERIVED_VALUE(NODE) \
- (VF_BINFO_VALUE (NODE) ? BINFO_TYPE (VF_BINFO_VALUE (NODE)) : NULL_TREE)
+/* Accessor macros for the BINFO_VIRTUALS list. */
/* The number of bytes by which to adjust the `this' pointer when
- calling this virtual function. */
+ calling this virtual function. Subtract this value from the this
+ pointer. Always non-NULL, might be constant zero though. */
#define BV_DELTA(NODE) (TREE_PURPOSE (NODE))
/* If non-NULL, the vtable index at which to find the vcall offset
- when calling this virtual function. */
+ when calling this virtual function. Add the value at that vtable
+ index to the this pointer. */
#define BV_VCALL_INDEX(NODE) (TREE_TYPE (NODE))
/* The function to call. */
#define BV_FN(NODE) (TREE_VALUE (NODE))
-/* Nonzero if we should use a virtual thunk for this entry. */
-#define BV_USE_VCALL_INDEX_P(NODE) \
- (TREE_LANG_FLAG_0 (NODE))
/* Nonzero for TREE_LIST node means that this list of things
is a list of parameters, as opposed to a list of expressions. */
@@ -1760,7 +1763,7 @@ struct lang_type
|| TREE_CODE (NODE) == FIELD_DECL \
|| TREE_CODE (NODE) == USING_DECL))
-struct lang_decl_flags
+struct lang_decl_flags GTY(())
{
struct c_lang_decl base;
@@ -1781,66 +1784,93 @@ struct lang_decl_flags
unsigned not_really_extern : 1;
unsigned needs_final_overrider : 1;
unsigned initialized_in_class : 1;
- unsigned pending_inline_p : 1;
+ unsigned assignment_operator_p : 1;
unsigned global_ctor_p : 1;
unsigned global_dtor_p : 1;
- unsigned assignment_operator_p : 1;
unsigned anticipated_p : 1;
- /* Four unused bits. */
+ unsigned template_conv_p : 1;
+ unsigned u1sel : 1;
+ unsigned u2sel : 1;
+ unsigned can_be_full : 1;
+ unsigned unused : 1; /* One unused bit. */
- union {
+ union lang_decl_u {
/* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
is DECL_TEMPLATE_INFO. */
- tree template_info;
+ tree GTY ((tag ("0"))) template_info;
/* In a NAMESPACE_DECL, this is NAMESPACE_LEVEL. */
- struct binding_level *level;
- } u;
+ struct cp_binding_level * GTY ((tag ("1"))) level;
+ } GTY ((desc ("%1.u1sel"))) u;
- union {
+ union lang_decl_u2 {
/* This is DECL_ACCESS. */
- tree access;
+ tree GTY ((tag ("0"))) access;
/* For VAR_DECL in function, this is DECL_DISCRIMINATOR. */
int discriminator;
- /* In a namespace-scope FUNCTION_DECL, this is
- GLOBAL_INIT_PRIORITY. */
- int init_priority;
-
/* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
THUNK_VCALL_OFFSET. */
- tree vcall_offset;
- } u2;
+ tree GTY((tag ("2"))) vcall_offset;
+ } GTY ((desc ("%1.u2sel"))) u2;
};
-struct lang_decl
+struct lang_decl GTY(())
{
struct lang_decl_flags decl_flags;
- tree befriending_classes;
+ union lang_decl_u4
+ {
+ struct full_lang_decl
+ {
+ tree befriending_classes;
+
+ /* For a non-virtual FUNCTION_DECL, this is
+ DECL_FRIEND_CONTEXT. For a virtual FUNCTION_DECL for which
+ DECL_THUNK_P does not hold, this is DECL_THUNKS. */
+ tree context;
+
+ /* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION. */
+ tree cloned_function;
+
+ /* In a FUNCTION_DECL for which THUNK_P holds, this is
+ THUNK_DELTA. */
+ HOST_WIDE_INT delta;
+
+ /* In an overloaded operator, this is the value of
+ DECL_OVERLOADED_OPERATOR_P. */
+ enum tree_code operator_code;
+
+ unsigned u3sel : 1;
+ unsigned pending_inline_p : 1;
+
+ union lang_decl_u3
+ {
+ tree GTY ((tag ("0"))) sorted_fields;
+ struct unparsed_text * GTY ((tag ("2"))) pending_inline_info;
+ struct language_function * GTY ((tag ("1")))
+ saved_language_function;
+ } GTY ((desc ("%1.u3sel + %1.pending_inline_p"))) u;
+ } GTY ((tag ("1"))) f;
+ } GTY ((desc ("%1.decl_flags.can_be_full"))) u;
+};
- /* For a virtual FUNCTION_DECL, this is DECL_VIRTUAL_CONTEXT. For a
- non-virtual FUNCTION_DECL, this is DECL_FRIEND_CONTEXT. */
- tree context;
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
- /* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION. */
- tree cloned_function;
+#define LANG_DECL_U2_CHECK(NODE, TF) \
+({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
+ if (lt->decl_flags.u2sel != TF) \
+ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
+ &lt->decl_flags.u2; })
- union
- {
- tree sorted_fields;
- struct unparsed_text *pending_inline_info;
- struct cp_language_function *saved_language_function;
- } u;
-
- union {
- /* In an overloaded operator, this is the value of
- DECL_OVERLOADED_OPERATOR_P. */
- enum tree_code operator_code;
- } u2;
-};
+#else
+
+#define LANG_DECL_U2_CHECK(NODE, TF) \
+ (&DECL_LANG_SPECIFIC (NODE)->decl_flags.u2)
+
+#endif /* ENABLE_TREE_CHECKING */
#define DEFARG_POINTER(NODE) (DEFAULT_ARG_CHECK (NODE)->identifier.id.str)
@@ -1857,7 +1887,7 @@ struct lang_decl
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL))) \
|| (flag_syntax_only && TREE_USED (DECL)))
-/* Non-zero iff DECL is memory-based. The DECL_RTL of
+/* 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
@@ -1949,7 +1979,7 @@ struct lang_decl
/* If DECL_CLONED_FUNCTION_P holds, this is the function that was
cloned. */
#define DECL_CLONED_FUNCTION(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->cloned_function)
+ (DECL_LANG_SPECIFIC (NODE)->u.f.cloned_function)
/* Nonzero if NODE has DECL_DISCRIMINATOR and not DECL_ACCESS. */
#define DECL_DISCRIMINATOR_P(NODE) \
@@ -1957,27 +1987,37 @@ struct lang_decl
&& DECL_FUNCTION_SCOPE_P (NODE))
/* Discriminator for name mangling. */
-#define DECL_DISCRIMINATOR(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->decl_flags.u2.discriminator)
+#define DECL_DISCRIMINATOR(NODE) (LANG_DECL_U2_CHECK (NODE, 1)->discriminator)
-/* Non-zero if the VTT parm has been added to NODE. */
+/* Nonzero if the VTT parm has been added to NODE. */
#define DECL_HAS_VTT_PARM_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.has_vtt_parm_p)
-/* Non-zero if NODE is a FUNCTION_DECL for which a VTT parameter is
+/* Nonzero if NODE is a FUNCTION_DECL for which a VTT parameter is
required. */
#define DECL_NEEDS_VTT_PARM_P(NODE) \
(TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (NODE)) \
&& (DECL_BASE_CONSTRUCTOR_P (NODE) \
|| DECL_BASE_DESTRUCTOR_P (NODE)))
-/* Non-zero if NODE is a user-defined conversion operator. */
+/* Nonzero if NODE is a user-defined conversion operator. */
#define DECL_CONV_FN_P(NODE) \
(IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)))
+/* If FN is a conversion operator, the type to which it converts.
+ Otherwise, NULL_TREE. */
+#define DECL_CONV_FN_TYPE(FN) \
+ (DECL_CONV_FN_P (FN) ? TREE_TYPE (DECL_NAME (FN)) : NULL_TREE)
+
+/* Nonzero if NODE, which is a TEMPLATE_DECL, is a template
+ conversion operator to a type dependent on the innermost template
+ args. */
+#define DECL_TEMPLATE_CONV_FN_P(NODE) \
+ (DECL_LANG_SPECIFIC (NODE)->decl_flags.template_conv_p)
+
/* Set the overloaded operator code for NODE to CODE. */
#define SET_OVERLOADED_OPERATOR_CODE(NODE, CODE) \
- (DECL_LANG_SPECIFIC (NODE)->u2.operator_code = (CODE))
+ (DECL_LANG_SPECIFIC (NODE)->u.f.operator_code = (CODE))
/* If NODE is an overloaded operator, then this returns the TREE_CODE
associcated with the overloaded operator.
@@ -1988,9 +2028,9 @@ struct lang_decl
to test whether or not NODE is an overloaded operator. */
#define DECL_OVERLOADED_OPERATOR_P(NODE) \
(IDENTIFIER_OPNAME_P (DECL_NAME (NODE)) \
- ? DECL_LANG_SPECIFIC (NODE)->u2.operator_code : ERROR_MARK)
+ ? DECL_LANG_SPECIFIC (NODE)->u.f.operator_code : ERROR_MARK)
-/* Non-zero if NODE is an assignment operator. */
+/* Nonzero if NODE is an assignment operator. */
#define DECL_ASSIGNMENT_OPERATOR_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.assignment_operator_p)
@@ -2011,8 +2051,14 @@ struct lang_decl
should be allocated. */
#define DECL_IN_AGGR_P(NODE) (DECL_LANG_FLAG_3 (NODE))
+/* Nonzero for a VAR_DECL means that the variable's initialization has
+ been processed. */
+#define DECL_INITIALIZED_P(NODE) \
+ (TREE_LANG_FLAG_1 (VAR_DECL_CHECK (NODE)))
+
/* Nonzero if the DECL was initialized in the class definition itself,
- rather than outside the class. */
+ rather than outside the class. This is used for both static member
+ VAR_DECLS, and FUNTION_DECLS that are defined in the class. */
#define DECL_INITIALIZED_IN_CLASS_P(DECL) \
(DECL_LANG_SPECIFIC (DECL)->decl_flags.initialized_in_class)
@@ -2023,7 +2069,7 @@ struct lang_decl
/* A TREE_LIST of the types which have befriended this FUNCTION_DECL. */
#define DECL_BEFRIENDING_CLASSES(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->befriending_classes)
+ (DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes)
/* Nonzero for FUNCTION_DECL means that this decl is a static
member function. */
@@ -2079,6 +2125,11 @@ struct lang_decl
#define DECL_NEEDS_FINAL_OVERRIDER_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.needs_final_overrider)
+/* The thunks associated with NODE, a FUNCTION_DECL that is not itself
+ a thunk. */
+#define DECL_THUNKS(NODE) \
+ (DECL_LANG_SPECIFIC (NODE)->u.f.context)
+
/* Nonzero if NODE is a thunk, rather than an ordinary function. */
#define DECL_THUNK_P(NODE) \
(TREE_CODE (NODE) == FUNCTION_DECL \
@@ -2097,8 +2148,9 @@ struct lang_decl
(DECL_NON_THUNK_FUNCTION_P (NODE) && DECL_EXTERN_C_P (NODE))
/* Set DECL_THUNK_P for node. */
-#define SET_DECL_THUNK_P(NODE) \
- (DECL_LANG_FLAG_7 (NODE) = 1)
+#define SET_DECL_THUNK_P(NODE) \
+ (DECL_LANG_FLAG_7 (NODE) = 1, \
+ DECL_LANG_SPECIFIC (NODE)->u.f.u3sel = 1)
/* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a
template function. */
@@ -2106,7 +2158,7 @@ struct lang_decl
(TREE_LANG_FLAG_0 (NODE))
/* The _TYPE context in which this _DECL appears. This field holds the
- class where a virtual function instance is actually defined. */
+ class where a virtual function instance is actually defined. */
#define DECL_CLASS_CONTEXT(NODE) \
(DECL_CLASS_SCOPE_P (NODE) ? DECL_CONTEXT (NODE) : NULL_TREE)
@@ -2118,23 +2170,18 @@ struct lang_decl
the DECL_FRIEND_CONTEXT for `f' will be `S'. */
#define DECL_FRIEND_CONTEXT(NODE) \
((DECL_FRIEND_P (NODE) && !DECL_FUNCTION_MEMBER_P (NODE)) \
- ? DECL_LANG_SPECIFIC (NODE)->context \
+ ? DECL_LANG_SPECIFIC (NODE)->u.f.context \
: NULL_TREE)
/* Set the DECL_FRIEND_CONTEXT for NODE to CONTEXT. */
#define SET_DECL_FRIEND_CONTEXT(NODE, CONTEXT) \
- (DECL_LANG_SPECIFIC (NODE)->context = (CONTEXT))
+ (DECL_LANG_SPECIFIC (NODE)->u.f.context = (CONTEXT))
-/* NULL_TREE in DECL_CONTEXT represents the global namespace. */
+/* NULL_TREE in DECL_CONTEXT represents the global namespace. */
#define CP_DECL_CONTEXT(NODE) \
(DECL_CONTEXT (NODE) ? DECL_CONTEXT (NODE) : global_namespace)
#define FROB_CONTEXT(NODE) ((NODE) == global_namespace ? NULL_TREE : (NODE))
-/* For a virtual function, the base where we find its vtable entry.
- For a non-virtual function, the base where it is defined. */
-#define DECL_VIRTUAL_CONTEXT(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->context)
-
/* 1 iff NODE has namespace scope, including the global namespace. */
#define DECL_NAMESPACE_SCOPE_P(NODE) \
(!DECL_TEMPLATE_PARM_P (NODE) \
@@ -2155,11 +2202,11 @@ struct lang_decl
/* For a NAMESPACE_DECL: the list of using namespace directives
The PURPOSE is the used namespace, the value is the namespace
- that is the common ancestor. */
+ that is the common ancestor. */
#define DECL_NAMESPACE_USING(NODE) DECL_VINDEX (NAMESPACE_DECL_CHECK (NODE))
/* In a NAMESPACE_DECL, the DECL_INITIAL is used to record all users
- of a namespace, to record the transitive closure of using namespace. */
+ of a namespace, to record the transitive closure of using namespace. */
#define DECL_NAMESPACE_USERS(NODE) DECL_INITIAL (NAMESPACE_DECL_CHECK (NODE))
/* In a NAMESPACE_DECL, points to the original namespace if this is
@@ -2169,7 +2216,7 @@ struct lang_decl
#define ORIGINAL_NAMESPACE(NODE) \
(DECL_NAMESPACE_ALIAS (NODE) ? DECL_NAMESPACE_ALIAS (NODE) : (NODE))
-/* Non-zero if NODE is the std namespace. */
+/* Nonzero if NODE is the std namespace. */
#define DECL_NAMESPACE_STD_P(NODE) \
(TREE_CODE (NODE) == NAMESPACE_DECL \
&& CP_DECL_CONTEXT (NODE) == global_namespace \
@@ -2192,17 +2239,17 @@ struct lang_decl
the class definition. We have saved away the text of the function,
but have not yet processed it. */
#define DECL_PENDING_INLINE_P(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->decl_flags.pending_inline_p)
+ (DECL_LANG_SPECIFIC (NODE)->u.f.pending_inline_p)
/* If DECL_PENDING_INLINE_P holds, this is the saved text of the
function. */
#define DECL_PENDING_INLINE_INFO(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->u.pending_inline_info)
+ (DECL_LANG_SPECIFIC (NODE)->u.f.u.pending_inline_info)
-/* For a TYPE_DECL: if this function has many fields, we'll sort them
- and put them into a TREE_VEC. */
+/* For a TYPE_DECL: if this structure has many fields, we'll sort them
+ and put them into a TREE_VEC. */
#define DECL_SORTED_FIELDS(NODE) \
- (DECL_LANG_SPECIFIC (TYPE_DECL_CHECK (NODE))->u.sorted_fields)
+ (DECL_LANG_SPECIFIC (TYPE_DECL_CHECK (NODE))->u.f.u.sorted_fields)
/* True if on the deferred_fns (see decl2.c) list. */
#define DECL_DEFERRED_FN(DECL) \
@@ -2214,9 +2261,15 @@ struct lang_decl
(DECL_LANG_SPECIFIC (VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK (NODE)) \
->decl_flags.u.template_info)
+/* For a VAR_DECL, indicates that the variable has been processed.
+ This flag is set and unset throughout the code; it is always
+ used for a temporary purpose. */
+#define DECL_VAR_MARKED_P(NODE) \
+ (DECL_LANG_FLAG_4 (VAR_DECL_CHECK (NODE)))
+
/* Template information for a RECORD_TYPE or UNION_TYPE. */
#define CLASSTYPE_TEMPLATE_INFO(NODE) \
- (TYPE_LANG_SPECIFIC (RECORD_OR_UNION_TYPE_CHECK (NODE))->template_info)
+ (LANG_TYPE_CLASS_CHECK (RECORD_OR_UNION_TYPE_CHECK (NODE))->template_info)
/* Template information for an ENUMERAL_TYPE. Although an enumeration may
not be a primary template, it may be declared within the scope of a
@@ -2226,7 +2279,7 @@ struct lang_decl
/* Template information for a template template parameter. */
#define TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO(NODE) \
- (TYPE_LANG_SPECIFIC (BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK (NODE)) \
+ (LANG_TYPE_CLASS_CHECK (BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK (NODE)) \
->template_info)
/* Template information for an ENUMERAL_, RECORD_, or UNION_TYPE. */
@@ -2262,7 +2315,7 @@ struct lang_decl
only one level of arguments, but which is a TREE_VEC containing as
its only entry the TREE_VEC for that level. */
-/* Non-zero if the template arguments is actually a vector of vectors,
+/* Nonzero if the template arguments is actually a vector of vectors,
rather than just a vector. */
#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \
((NODE) != NULL_TREE \
@@ -2279,7 +2332,7 @@ struct lang_decl
#define TMPL_ARGS_DEPTH(NODE) \
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS (NODE) ? TREE_VEC_LENGTH (NODE) : 1)
-/* The LEVELth level of the template ARGS. The outermost level of of
+/* The LEVELth level of the template ARGS. The outermost level of
args is level 1, not level 0. */
#define TMPL_ARGS_LEVEL(ARGS, LEVEL) \
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS (ARGS) \
@@ -2364,8 +2417,9 @@ struct lang_decl
#define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE)
/* In a FUNCTION_DECL, the saved language-specific per-function data. */
-#define DECL_SAVED_FUNCTION_DATA(NODE) \
- (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE))->u.saved_language_function)
+#define DECL_SAVED_FUNCTION_DATA(NODE) \
+ (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE)) \
+ ->u.f.u.saved_language_function)
#define NEW_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE)
#define DELETE_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE)
@@ -2423,8 +2477,6 @@ struct lang_decl
(TYPE_POLYMORPHIC_P (NODE) \
|| TYPE_USES_VIRTUAL_BASECLASSES (NODE))
-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. */
#define DECL_DEAD_FOR_LOCAL(NODE) DECL_LANG_FLAG_7 (VAR_DECL_CHECK (NODE))
@@ -2446,7 +2498,7 @@ extern int flag_new_for_scope;
/* Record whether a typedef for type `int' was actually `signed int'. */
#define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP)
-/* Returns non-zero if DECL has external linkage, as specified by the
+/* Returns nonzero if DECL has external linkage, as specified by the
language standard. (This predicate may hold even when the
corresponding entity is not actually given external linkage in the
object file; see decl_linkage for details.) */
@@ -2467,6 +2519,10 @@ extern int flag_new_for_scope;
(TREE_CODE (TYPE) == BOOLEAN_TYPE \
|| TREE_CODE (TYPE) == INTEGER_TYPE)
+/* Returns true if TYPE is an integral or enumeration name. */
+#define INTEGRAL_OR_ENUMERATION_TYPE_P(TYPE) \
+ (CP_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == ENUMERAL_TYPE)
+
/* [basic.fundamental]
Integral and floating types are collectively called arithmetic
@@ -2474,8 +2530,29 @@ extern int flag_new_for_scope;
#define ARITHMETIC_TYPE_P(TYPE) \
(CP_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == REAL_TYPE)
-/* Nonzero for _TYPE means that the _TYPE defines
- at least one constructor. */
+/* [basic.types]
+
+ Arithmetic types, enumeration types, pointer types, and
+ pointer-to-member types, are collectively called scalar types. */
+#define SCALAR_TYPE_P(TYPE) \
+ (ARITHMETIC_TYPE_P (TYPE) \
+ || TREE_CODE (TYPE) == ENUMERAL_TYPE \
+ || TYPE_PTR_P (TYPE) \
+ || TYPE_PTRMEM_P (TYPE) \
+ || TYPE_PTRMEMFUNC_P (TYPE))
+
+/* [dcl.init.aggr]
+
+ An aggregate is an array or a class with no user-declared
+ constructors, no private or protected non-static data members, no
+ base classes, and no virtual functions. */
+#define CP_AGGREGATE_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == ARRAY_TYPE \
+ || (CLASS_TYPE_P (TYPE) \
+ && !CLASSTYPE_NON_AGGREGATE (TYPE)))
+
+/* Nonzero for a class type means that the class type has a
+ user-declared constructor. */
#define TYPE_HAS_CONSTRUCTOR(NODE) (TYPE_LANG_FLAG_1 (NODE))
/* When appearing in an INDIRECT_REF, it means that the tree structure
@@ -2504,15 +2581,15 @@ extern int flag_new_for_scope;
/* Nonzero means that an object of this type can not be initialized using
an initializer list. */
#define CLASSTYPE_NON_AGGREGATE(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->non_aggregate)
+ (LANG_TYPE_CLASS_CHECK (NODE)->non_aggregate)
#define TYPE_NON_AGGREGATE_CLASS(NODE) \
(IS_AGGR_TYPE (NODE) && CLASSTYPE_NON_AGGREGATE (NODE))
/* Nonzero if there is a user-defined X::op=(x&) for this class. */
-#define TYPE_HAS_REAL_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_real_assign_ref)
-#define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_complex_assign_ref)
-#define TYPE_HAS_ABSTRACT_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_abstract_assign_ref)
-#define TYPE_HAS_COMPLEX_INIT_REF(NODE) (TYPE_LANG_SPECIFIC (NODE)->has_complex_init_ref)
+#define TYPE_HAS_REAL_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_real_assign_ref)
+#define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_assign_ref)
+#define TYPE_HAS_ABSTRACT_ASSIGN_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_abstract_assign_ref)
+#define TYPE_HAS_COMPLEX_INIT_REF(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_init_ref)
/* Nonzero if TYPE has a trivial destructor. From [class.dtor]:
@@ -2571,7 +2648,7 @@ extern int flag_new_for_scope;
&& TYPE_PTRMEMFUNC_FLAG (NODE))
#define TYPE_PTRMEMFUNC_FLAG(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->ptrmemfunc_flag)
+ (LANG_TYPE_CLASS_CHECK (NODE)->ptrmemfunc_flag)
/* Indicates when overload resolution may resolve to a pointer to
member function. [expr.unary.op]/3 */
@@ -2590,9 +2667,17 @@ extern int flag_new_for_scope;
/* These are use to manipulate the canonical RECORD_TYPE from the
hashed POINTER_TYPE, and can only be used on the POINTER_TYPE. */
#define TYPE_GET_PTRMEMFUNC_TYPE(NODE) \
- ((tree)TYPE_LANG_SPECIFIC (NODE))
-#define TYPE_SET_PTRMEMFUNC_TYPE(NODE, VALUE) \
- (TYPE_LANG_SPECIFIC (NODE) = ((struct lang_type *)(void*)(VALUE)))
+ (TYPE_LANG_SPECIFIC (NODE) ? LANG_TYPE_PTRMEM_CHECK (NODE)->record : NULL)
+#define TYPE_SET_PTRMEMFUNC_TYPE(NODE, VALUE) \
+ do { \
+ if (TYPE_LANG_SPECIFIC (NODE) == NULL) \
+ { \
+ TYPE_LANG_SPECIFIC (NODE) = \
+ ggc_alloc_cleared (sizeof (struct lang_type_ptrmem)); \
+ TYPE_LANG_SPECIFIC (NODE)->u.ptrmem.h.is_lang_type_class = 0; \
+ } \
+ TYPE_LANG_SPECIFIC (NODE)->u.ptrmem.record = (VALUE); \
+ } while (0)
/* Returns the pfn field from a TYPE_PTRMEMFUNC_P. */
#define PFN_FROM_PTRMEMFUNC(NODE) pfn_from_ptrmemfunc ((NODE))
@@ -2637,9 +2722,9 @@ extern int flag_new_for_scope;
flag for this because "A union for which objects or pointers are
declared is not an anonymous union" [class.union]. */
#define ANON_AGGR_TYPE_P(NODE) \
- (CLASS_TYPE_P (NODE) && TYPE_LANG_SPECIFIC (NODE)->anon_aggr)
+ (CLASS_TYPE_P (NODE) && LANG_TYPE_CLASS_CHECK (NODE)->anon_aggr)
#define SET_ANON_AGGR_TYPE_P(NODE) \
- (TYPE_LANG_SPECIFIC (NODE)->anon_aggr = 1)
+ (LANG_TYPE_CLASS_CHECK (NODE)->anon_aggr = 1)
/* Nonzero if TYPE is an anonymous union type. */
#define ANON_UNION_TYPE_P(NODE) \
@@ -2649,7 +2734,7 @@ extern int flag_new_for_scope;
/* Define fields and accessors for nodes representing declared names. */
-#define TYPE_WAS_ANONYMOUS(NODE) (TYPE_LANG_SPECIFIC (NODE)->was_anonymous)
+#define TYPE_WAS_ANONYMOUS(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->was_anonymous)
/* C++: all of these are overloaded! These apply only to TYPE_DECLs. */
@@ -2674,7 +2759,7 @@ extern int flag_new_for_scope;
For example, if a member that would normally be public in a
derived class is made protected, then the derived class and the
protected_access_node will appear in the DECL_ACCESS for the node. */
-#define DECL_ACCESS(NODE) (DECL_LANG_SPECIFIC (NODE)->decl_flags.u2.access)
+#define DECL_ACCESS(NODE) (LANG_DECL_U2_CHECK (NODE, 0)->access)
/* Nonzero if the FUNCTION_DECL is a global constructor. */
#define DECL_GLOBAL_CTOR_P(NODE) \
@@ -2684,13 +2769,6 @@ extern int flag_new_for_scope;
#define DECL_GLOBAL_DTOR_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.global_dtor_p)
-/* If DECL_GLOBAL_CTOR_P or DECL_GLOBAL_DTOR_P holds, this macro
- returns the initialization priority for the function. Constructors
- with lower numbers should be run first. Destructors should be run
- in the reverse order of constructors. */
-#define GLOBAL_INIT_PRIORITY(NODE) \
- (DECL_LANG_SPECIFIC (NODE)->decl_flags.u2.init_priority)
-
/* Accessor macros for C++ template decl nodes. */
/* The DECL_TEMPLATE_PARMS are a list. The TREE_PURPOSE of each node
@@ -2819,7 +2897,7 @@ extern int flag_new_for_scope;
#define DECL_PRIMARY_TEMPLATE(NODE) \
(TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (NODE)))
-/* Returns non-zero if NODE is a primary template. */
+/* Returns nonzero if NODE is a primary template. */
#define PRIMARY_TEMPLATE_P(NODE) (DECL_PRIMARY_TEMPLATE (NODE) == (NODE))
#define CLASSTYPE_TEMPLATE_LEVEL(NODE) \
@@ -2858,7 +2936,7 @@ extern int flag_new_for_scope;
#define SET_CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE (NODE) = 3)
-/* Non-zero if DECL is a friend function which is an instantiation
+/* Nonzero if DECL is a friend function which is an instantiation
from the point of view of the compiler, but not from the point of
view of the language. For example given:
template <class T> struct S { friend void f(T) {}; };
@@ -2868,21 +2946,18 @@ extern int flag_new_for_scope;
#define DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION(DECL) \
(DECL_TEMPLATE_INFO (DECL) && !DECL_USE_TEMPLATE (DECL))
-/* Non-zero if TYPE is a partial instantiation of a template class,
+/* Nonzero if TYPE is a partial instantiation of a template class,
i.e., an instantiation whose instantiation arguments involve
template types. */
#define PARTIAL_INSTANTIATION_P(TYPE) \
- (TYPE_LANG_SPECIFIC (TYPE)->is_partial_instantiation)
+ (LANG_TYPE_CLASS_CHECK (TYPE)->is_partial_instantiation)
-/* Non-zero iff we are currently processing a declaration for an
+/* Nonzero iff we are currently processing a declaration for an
entity with its own template parameter list, and which is not a
full specialization. */
#define PROCESSING_REAL_TEMPLATE_DECL_P() \
(processing_template_decl > template_class_depth (current_class_type))
-/* This function may be a guiding decl for a template. */
-#define DECL_MAYBE_TEMPLATE(NODE) DECL_LANG_FLAG_4 (NODE)
-
/* Nonzero if this VAR_DECL or FUNCTION_DECL has already been
instantiated, i.e. its definition has been generated from the
pattern given in the the template. */
@@ -2930,14 +3005,15 @@ extern int flag_new_for_scope;
/* An integer indicating how many bytes should be subtracted from the
`this' pointer when this function is called. */
-#define THUNK_DELTA(DECL) (DECL_CHECK (DECL)->decl.u1.i)
+#define THUNK_DELTA(DECL) \
+ (DECL_LANG_SPECIFIC (DECL)->u.f.delta)
/* A tree indicating how many bytes should be subtracted from the
vtable for the `this' pointer to find the vcall offset. (The vptr
is always located at offset zero from the f `this' pointer.) If
NULL, then there is no vcall offset. */
#define THUNK_VCALL_OFFSET(DECL) \
- (DECL_LANG_SPECIFIC (DECL)->decl_flags.u2.vcall_offset)
+ (LANG_DECL_U2_CHECK (DECL, 0)->vcall_offset)
/* These macros provide convenient access to the various _STMT nodes
created when parsing template declarations. */
@@ -2954,15 +3030,6 @@ extern int flag_new_for_scope;
#define HANDLER_PARMS(NODE) TREE_OPERAND (HANDLER_CHECK (NODE), 0)
#define HANDLER_BODY(NODE) TREE_OPERAND (HANDLER_CHECK (NODE), 1)
#define HANDLER_TYPE(NODE) TREE_TYPE (HANDLER_CHECK (NODE))
-#define SUBOBJECT_CLEANUP(NODE) TREE_OPERAND (SUBOBJECT_CHECK (NODE), 0)
-
-/* Nonzero if this CTOR_STMT is for the beginning of a constructor. */
-#define CTOR_BEGIN_P(NODE) \
- (TREE_LANG_FLAG_0 (CTOR_STMT_CHECK (NODE)))
-
-/* Nonzero if this CTOR_STMT is for the end of a constructor. */
-#define CTOR_END_P(NODE) \
- (!CTOR_BEGIN_P (NODE))
/* The parameters for a call-declarator. */
#define CALL_DECLARATOR_PARMS(NODE) \
@@ -3075,23 +3142,25 @@ typedef enum tsubst_flags_t {
tf_ignore_bad_quals = 1 << 3, /* ignore bad cvr qualifiers */
tf_keep_type_decl = 1 << 4, /* retain typedef type decls
(make_typename_type use) */
- tf_ptrmem_ok = 1 << 5 /* pointers to member ok (internal
+ tf_ptrmem_ok = 1 << 5, /* pointers to member ok (internal
instantiate_type use) */
+ tf_parsing = 1 << 6 /* called from parser
+ (make_typename_type use) */
} tsubst_flags_t;
-/* The kind of checking we can do looking in a class hierarchy. */
+/* The kind of checking we can do looking in a class hierarchy. */
typedef enum base_access {
ba_any = 0, /* Do not check access, allow an ambiguous base,
prefer a non-virtual base */
ba_ignore = 1, /* Do not check access */
ba_check = 2, /* Check access */
ba_not_special = 3, /* Do not consider special privilege
- current_class_type might give. */
+ current_class_type might give. */
ba_quiet = 4, /* Do not issue error messages (bit mask). */
} base_access;
/* The kind of base we can find, looking in a class hierarchy.
- Values <0 indicate we failed. */
+ Values <0 indicate we failed. */
typedef enum base_kind {
bk_inaccessible = -3, /* The base is inaccessible */
bk_ambig = -2, /* The base is ambiguous */
@@ -3100,33 +3169,17 @@ typedef enum base_kind {
bk_proper_base = 1, /* It is a proper base */
bk_via_virtual = 2 /* It is a proper base, but via a virtual
path. This might not be the canonical
- binfo. */
+ binfo. */
} base_kind;
-/* Nonzero means allow Microsoft extensions without a pedwarn. */
-extern int flag_ms_extensions;
-
-/* Non-zero means warn in function declared in derived class has the
- same name as a virtual in the base class, but fails to match the
- type signature of any virtual function in the base class. */
-extern int warn_overloaded_virtual;
-
-/* Nonzero means warn about use of multicharacter literals. */
-extern int warn_multichar;
-
/* Set by add_implicitly_declared_members() to keep those members from
being flagged as deprecated or reported as using deprecated
types. */
extern int adding_implicit_members;
-/* Non-zero means warn if a non-templatized friend function is
- declared in a templatized class. This behavior is warned about with
- flag_guiding_decls in do_friend. */
-extern int warn_nontemplate_friend;
-
/* in decl{2}.c */
/* A node that is a list (length 1) of error_mark_nodes. */
-extern tree error_mark_list;
+extern GTY(()) tree error_mark_list;
/* Node for "pointer to (virtual) function".
This may be distinct from ptr_type_node so gdb can distinguish them. */
@@ -3134,9 +3187,10 @@ extern tree error_mark_list;
/* For building calls to `delete'. */
-extern tree integer_two_node, integer_three_node;
+extern GTY(()) tree integer_two_node;
+extern GTY(()) tree integer_three_node;
-extern tree anonymous_namespace_name;
+extern GTY(()) tree anonymous_namespace_name;
/* The number of function bodies which we are currently processing.
(Zero if we are at namespace scope, one inside the body of a
@@ -3167,13 +3221,9 @@ typedef enum unification_kind_t {
extern int current_class_depth;
-/* Points to the name of that function. May not be the DECL_NAME
- of CURRENT_FUNCTION_DECL due to overloading */
-extern tree original_function_name;
-
/* An array of all local classes present in this translation unit, in
declaration order. */
-extern varray_type local_classes;
+extern GTY(()) varray_type local_classes;
/* Here's where we control how name mangling takes place. */
@@ -3261,7 +3311,6 @@ extern varray_type local_classes;
#endif /* NO_DOLLAR_IN_LABEL */
#define THIS_NAME "this"
-#define FILE_FUNCTION_PREFIX_LEN 9
#define CTOR_NAME "__ct"
#define DTOR_NAME "__dt"
@@ -3294,7 +3343,7 @@ extern varray_type local_classes;
&& IDENTIFIER_POINTER (ID_NODE)[1] == '_')
#endif /* !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL) */
-/* Returns non-zero iff NODE is a declaration for the global function
+/* Returns nonzero iff NODE is a declaration for the global function
`main'. */
#define DECL_MAIN_P(NODE) \
(DECL_EXTERN_C_FUNCTION_P (NODE) \
@@ -3302,39 +3351,20 @@ extern varray_type local_classes;
&& MAIN_NAME_P (DECL_NAME (NODE)))
-/* Things for handling inline functions. */
-
-/* Nonzero means do emit exported implementations of functions even if
- they can be inlined. */
-
-extern int flag_implement_inlines;
-
-/* Nonzero means templates obey #pragma interface and implementation. */
-
-extern int flag_external_templates;
-
-/* Nonzero means templates are emitted where they are instantiated. */
-
-extern int flag_alt_external_templates;
-
-/* Nonzero means implicit template instantiations are emitted. */
-
-extern int flag_implicit_templates;
-
-/* 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 flag_weak;
-
/* Nonzero if we're done parsing and into end-of-file activities. */
extern int at_eof;
+/* A list of namespace-scope objects which have constructors or
+ destructors which reside in the global scope. The decl is stored
+ in the TREE_VALUE slot and the initializer is stored in the
+ TREE_PURPOSE slot. */
+extern GTY(()) tree static_aggregates;
+
/* Functions called along with real static constructors and destructors. */
-extern tree static_ctors;
-extern tree static_dtors;
+extern GTY(()) tree static_ctors;
+extern GTY(()) tree static_dtors;
enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
@@ -3444,7 +3474,7 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
type is derived from the pointed to
by the first. */
#define COMPARE_RELAXED 2 /* Like COMPARE_DERIVED, but in
- reverse. Also treat enmeration
+ reverse. Also treat enumeration
types as the same as integer types
of the same width. */
#define COMPARE_REDECLARATION 4 /* The comparsion is being done when
@@ -3547,6 +3577,8 @@ typedef struct operator_name_info_t
const char *name;
/* The mangled name of the operator. */
const char *mangled_name;
+ /* The arity of the operator. */
+ int arity;
} operator_name_info_t;
/* A mapping from tree codes to operator name information. */
@@ -3567,8 +3599,11 @@ extern tree build_method_call PARAMS ((tree, tree, tree, tree, int));
extern int null_ptr_cst_p PARAMS ((tree));
extern int sufficient_parms_p PARAMS ((tree));
extern tree type_decays_to PARAMS ((tree));
+extern tree resolve_scoped_fn_name PARAMS ((tree, tree));
extern tree build_user_type_conversion PARAMS ((tree, tree, int));
extern tree build_new_function_call PARAMS ((tree, tree));
+extern tree build_new_method_call (tree, tree, tree, tree, int);
+extern tree build_special_member_call (tree, tree, tree, tree, int);
extern tree build_new_op PARAMS ((enum tree_code, int, tree, tree, tree));
extern tree build_op_delete_call PARAMS ((enum tree_code, tree, tree, int, tree));
extern int can_convert PARAMS ((tree, tree));
@@ -3578,15 +3613,20 @@ extern int enforce_access PARAMS ((tree, tree));
extern tree convert_default_arg PARAMS ((tree, tree, tree, int));
extern tree convert_arg_to_ellipsis PARAMS ((tree));
extern tree build_x_va_arg PARAMS ((tree, tree));
-extern tree convert_type_from_ellipsis PARAMS ((tree));
+extern tree cxx_type_promotes_to PARAMS ((tree));
+extern tree type_passed_as PARAMS ((tree));
+extern tree convert_for_arg_passing PARAMS ((tree, tree));
+extern tree cp_convert_parm_for_inlining PARAMS ((tree, tree, tree));
extern int is_properly_derived_from PARAMS ((tree, tree));
-extern tree initialize_reference PARAMS ((tree, tree));
+extern tree initialize_reference PARAMS ((tree, tree, tree));
+extern tree make_temporary_var_for_ref_to_temp (tree, tree);
extern tree strip_top_quals PARAMS ((tree));
extern tree perform_implicit_conversion PARAMS ((tree, tree));
+extern tree perform_direct_initialization_if_possible (tree, tree);
/* in class.c */
extern tree build_base_path PARAMS ((enum tree_code, tree, tree, int));
-extern tree build_vbase_path PARAMS ((enum tree_code, tree, tree, tree, int));
+extern tree convert_to_base (tree, tree, bool);
extern tree build_vtbl_ref PARAMS ((tree, tree));
extern tree build_vfn_ref PARAMS ((tree, tree));
extern tree get_vtable_decl PARAMS ((tree, int));
@@ -3613,10 +3653,12 @@ extern void cxx_print_xnode PARAMS ((FILE *, tree, int));
extern void cxx_print_decl PARAMS ((FILE *, tree, int));
extern void cxx_print_type PARAMS ((FILE *, tree, int));
extern void cxx_print_identifier PARAMS ((FILE *, tree, int));
-extern void cxx_set_yydebug PARAMS ((int));
+extern void cxx_print_error_function PARAMS ((struct diagnostic_context *,
+ const char *));
extern void build_self_reference PARAMS ((void));
extern int same_signature_p PARAMS ((tree, tree));
extern void warn_hidden PARAMS ((tree));
+extern void maybe_add_class_template_decl_list PARAMS ((tree, tree, int));
extern tree get_enclosing_class PARAMS ((tree));
int is_base_of_enclosing_class PARAMS ((tree, tree));
extern void unreverse_member_declarations PARAMS ((tree));
@@ -3625,6 +3667,7 @@ extern void maybe_note_name_used_in_class PARAMS ((tree, tree));
extern void note_name_declared_in_class PARAMS ((tree, tree));
extern tree get_vtbl_decl_for_binfo PARAMS ((tree));
extern tree in_charge_arg_for_name PARAMS ((tree));
+extern tree build_cxx_call PARAMS ((tree, tree, tree));
extern tree get_vtt_name PARAMS ((tree));
extern tree get_primary_binfo PARAMS ((tree));
@@ -3632,11 +3675,12 @@ extern tree get_primary_binfo PARAMS ((tree));
extern tree convert_to_reference PARAMS ((tree, tree, int, int, tree));
extern tree convert_from_reference PARAMS ((tree));
extern tree convert_lvalue PARAMS ((tree, tree));
+extern tree force_rvalue PARAMS ((tree));
extern tree ocp_convert PARAMS ((tree, tree, int, int));
extern tree cp_convert PARAMS ((tree, tree));
extern tree convert_to_void PARAMS ((tree, const char */*implicit context*/));
extern tree convert_force PARAMS ((tree, tree, int));
-extern tree build_type_conversion PARAMS ((tree, tree, int));
+extern tree build_type_conversion PARAMS ((tree, tree));
extern tree build_expr_type_conversion PARAMS ((int, tree, int));
extern tree type_promotes_to PARAMS ((tree));
extern tree perform_qualification_conversions PARAMS ((tree, tree));
@@ -3644,12 +3688,25 @@ extern void clone_function_decl PARAMS ((tree, int));
extern void adjust_clone_args PARAMS ((tree));
/* decl.c */
-/* resume_binding_level */
+extern int global_bindings_p PARAMS ((void));
+extern int kept_level_p PARAMS ((void));
+extern tree getdecls PARAMS ((void));
+extern void pushlevel PARAMS ((int));
+extern tree poplevel PARAMS ((int,int, int));
+extern void insert_block PARAMS ((tree));
+extern void set_block PARAMS ((tree));
+extern tree pushdecl PARAMS ((tree));
extern void cxx_init_decl_processing PARAMS ((void));
+enum cp_tree_node_structure_enum cp_tree_node_structure
+ PARAMS ((union lang_tree_node *));
+extern void cxx_insert_default_attributes PARAMS ((tree));
+extern bool cxx_mark_addressable PARAMS ((tree));
+extern void cxx_push_function_context PARAMS ((struct function *));
+extern void cxx_pop_function_context PARAMS ((struct function *));
+extern void cxx_mark_function_context PARAMS ((struct function *));
extern int toplevel_bindings_p PARAMS ((void));
extern int namespace_bindings_p PARAMS ((void));
extern void keep_next_level PARAMS ((int));
-extern int kept_level_p PARAMS ((void));
extern int template_parm_scope_p PARAMS ((void));
extern void set_class_shadows PARAMS ((tree));
extern void maybe_push_cleanup_level PARAMS ((tree));
@@ -3658,13 +3715,13 @@ extern void finish_scope PARAMS ((void));
extern void note_level_for_for PARAMS ((void));
extern void note_level_for_try PARAMS ((void));
extern void note_level_for_catch PARAMS ((void));
-extern void resume_level PARAMS ((struct binding_level *));
+extern void resume_level PARAMS ((struct cp_binding_level *));
extern void delete_block PARAMS ((tree));
extern void add_block_current_level PARAMS ((tree));
extern void pushlevel_class PARAMS ((void));
extern void poplevel_class PARAMS ((void));
extern void print_binding_stack PARAMS ((void));
-extern void print_binding_level PARAMS ((struct binding_level *));
+extern void print_binding_level PARAMS ((struct cp_binding_level *));
extern void push_namespace PARAMS ((tree));
extern void pop_namespace PARAMS ((void));
extern void push_nested_namespace PARAMS ((tree));
@@ -3683,23 +3740,24 @@ extern void clear_anon_tags PARAMS ((void));
extern int decls_match PARAMS ((tree, tree));
extern int duplicate_decls PARAMS ((tree, tree));
extern tree pushdecl_top_level PARAMS ((tree));
-extern void pushdecl_class_level PARAMS ((tree));
+extern tree pushdecl_top_level_and_finish (tree, tree);
+extern bool pushdecl_class_level (tree);
extern tree pushdecl_namespace_level PARAMS ((tree));
extern tree push_using_decl PARAMS ((tree, tree));
extern tree push_using_directive PARAMS ((tree));
-extern void push_class_level_binding PARAMS ((tree, tree));
+extern bool push_class_level_binding (tree, tree);
extern tree implicitly_declare PARAMS ((tree));
extern tree declare_local_label PARAMS ((tree));
extern tree define_label PARAMS ((const char *, int, tree));
extern void check_goto PARAMS ((tree));
extern void define_case_label PARAMS ((void));
-extern tree binding_for_name PARAMS ((tree, tree));
+extern cxx_binding *binding_for_name (tree, tree);
extern tree namespace_binding PARAMS ((tree, tree));
extern void set_namespace_binding PARAMS ((tree, tree, tree));
extern tree lookup_namespace_name PARAMS ((tree, tree));
extern tree build_typename_type PARAMS ((tree, tree, tree, tree));
extern tree make_typename_type PARAMS ((tree, tree, tsubst_flags_t));
-extern tree make_unbound_class_template PARAMS ((tree, tree, int));
+extern tree make_unbound_class_template PARAMS ((tree, tree, tsubst_flags_t));
extern tree lookup_name_nonclass PARAMS ((tree));
extern tree lookup_function_nonclass PARAMS ((tree, tree));
extern tree lookup_name PARAMS ((tree, int));
@@ -3709,9 +3767,11 @@ extern tree lookup_name_namespace_only PARAMS ((tree));
extern void begin_only_namespace_names PARAMS ((void));
extern void end_only_namespace_names PARAMS ((void));
extern tree namespace_ancestor PARAMS ((tree, tree));
+extern bool is_ancestor (tree, tree);
extern tree unqualified_namespace_lookup PARAMS ((tree, int, tree *));
-extern int lookup_using_namespace PARAMS ((tree, tree, tree, tree, int, tree *));
-extern int qualified_lookup_using_namespace PARAMS ((tree, tree, tree, int));
+extern tree check_for_out_of_scope_variable (tree);
+extern bool lookup_using_namespace (tree, cxx_binding *, tree, tree, int, tree *);
+extern bool qualified_lookup_using_namespace (tree, tree, cxx_binding *, int);
extern tree build_library_fn PARAMS ((tree, tree));
extern tree build_library_fn_ptr PARAMS ((const char *, tree));
extern tree build_cp_library_fn_ptr PARAMS ((const char *, tree));
@@ -3727,20 +3787,19 @@ extern void start_decl_1 PARAMS ((tree));
extern void cp_finish_decl PARAMS ((tree, tree, tree, int));
extern void finish_decl PARAMS ((tree, tree, tree));
extern void maybe_inject_for_scope_var PARAMS ((tree));
-extern void initialize_local_var PARAMS ((tree, tree, int));
-extern void expand_static_init PARAMS ((tree, tree));
extern tree start_handler_parms PARAMS ((tree, tree));
extern int complete_array_type PARAMS ((tree, tree, int));
extern tree build_ptrmemfunc_type PARAMS ((tree));
+extern tree build_ptrmem_type (tree, tree);
/* the grokdeclarator prototype is in decl.h */
extern int parmlist_is_exprlist PARAMS ((tree));
extern int copy_fn_p PARAMS ((tree));
extern void grok_special_member_properties PARAMS ((tree));
extern int grok_ctor_properties PARAMS ((tree, tree));
extern void grok_op_properties PARAMS ((tree, int));
-extern tree xref_tag PARAMS ((tree, tree, int));
+extern tree xref_tag (enum tag_types, tree, tree, bool);
extern tree xref_tag_from_type PARAMS ((tree, tree, int));
-extern void xref_basetypes PARAMS ((tree, tree, tree, tree));
+extern void xref_basetypes PARAMS ((tree, tree));
extern tree start_enum PARAMS ((tree));
extern void finish_enum PARAMS ((tree));
extern void build_enumerator PARAMS ((tree, tree, tree));
@@ -3753,7 +3812,7 @@ extern tree finish_method PARAMS ((tree));
extern void maybe_register_incomplete_var PARAMS ((tree));
extern void complete_vars PARAMS ((tree));
extern void finish_stmt PARAMS ((void));
-extern void print_other_binding_stack PARAMS ((struct binding_level *));
+extern void print_other_binding_stack PARAMS ((struct cp_binding_level *));
extern void revert_static_member_fn PARAMS ((tree));
extern void fixup_anonymous_aggr PARAMS ((tree));
extern int check_static_variable_definition PARAMS ((tree, tree));
@@ -3772,6 +3831,9 @@ typedef int (*walk_globals_fn) PARAMS ((tree *, void *));
extern int walk_globals PARAMS ((walk_globals_pred,
walk_globals_fn,
void *));
+extern int walk_vtables PARAMS ((walk_globals_pred,
+ walk_globals_fn,
+ void *));
typedef int (*walk_namespaces_fn) PARAMS ((tree, void *));
extern int walk_namespaces PARAMS ((walk_namespaces_fn,
void *));
@@ -3785,12 +3847,12 @@ extern int nonstatic_local_decl_p PARAMS ((tree));
extern tree declare_global_var PARAMS ((tree, tree));
extern void register_dtor_fn PARAMS ((tree));
extern tmpl_spec_kind current_tmpl_spec_kind PARAMS ((int));
+extern cxx_binding *cxx_scope_find_binding_for_name (tree, tree);
extern tree cp_fname_init PARAMS ((const char *));
+extern bool have_extern_spec;
/* in decl2.c */
-extern void init_decl2 PARAMS ((void));
extern int check_java_method PARAMS ((tree));
-extern int cxx_decode_option PARAMS ((int, char **));
extern int grok_method_quals PARAMS ((tree, tree, tree));
extern void warn_if_unknown_interface PARAMS ((tree));
extern void grok_x_components PARAMS ((tree));
@@ -3804,10 +3866,11 @@ extern void check_member_template PARAMS ((tree));
extern tree grokfield PARAMS ((tree, tree, tree, tree, tree));
extern tree grokbitfield PARAMS ((tree, tree, tree));
extern tree groktypefield PARAMS ((tree, tree));
-extern tree grokoptypename PARAMS ((tree, tree));
+extern tree grokoptypename PARAMS ((tree, tree, tree));
extern void cplus_decl_attributes PARAMS ((tree *, tree, int));
extern tree constructor_name_full PARAMS ((tree));
extern tree constructor_name PARAMS ((tree));
+extern bool constructor_name_p (tree, tree);
extern void defer_fn PARAMS ((tree));
extern void finish_anon_union PARAMS ((tree));
extern tree finish_table PARAMS ((tree, tree, tree, int));
@@ -3824,6 +3887,8 @@ extern void finish_file PARAMS ((void));
extern tree reparse_absdcl_as_expr PARAMS ((tree, tree));
extern tree reparse_absdcl_as_casts PARAMS ((tree, tree));
extern tree build_expr_from_tree PARAMS ((tree));
+extern tree build_offset_ref_call_from_tree (tree, tree);
+extern tree build_call_from_tree (tree, tree, bool);
extern tree reparse_decl_as_expr PARAMS ((tree, tree));
extern tree finish_decl_parsing PARAMS ((tree));
extern void set_decl_namespace PARAMS ((tree, tree, int));
@@ -3839,17 +3904,16 @@ extern tree do_class_using_decl PARAMS ((tree));
extern void do_using_directive PARAMS ((tree));
extern void check_default_args PARAMS ((tree));
extern void mark_used PARAMS ((tree));
-extern tree handle_class_head PARAMS ((tree, tree, tree, int, int *));
+extern tree handle_class_head (enum tag_types, tree, tree, tree, int, int *);
+extern tree handle_class_head_apparent_template (tree, int *);
extern tree lookup_arg_dependent PARAMS ((tree, tree, tree));
extern void finish_static_data_member_decl PARAMS ((tree, tree, tree, int));
+extern tree cp_build_parm_decl PARAMS ((tree, tree));
extern tree build_artificial_parm PARAMS ((tree, tree));
extern tree get_guard PARAMS ((tree));
extern tree get_guard_cond PARAMS ((tree));
extern tree set_guard PARAMS ((tree));
-/* in parse.y */
-extern void cp_parse_init PARAMS ((void));
-
extern void cp_error_at PARAMS ((const char *msgid, ...));
extern void cp_warning_at PARAMS ((const char *msgid, ...));
extern void cp_pedwarn_at PARAMS ((const char *msgid, ...));
@@ -3889,8 +3953,9 @@ extern void check_handlers PARAMS ((tree));
extern void choose_personality_routine PARAMS ((enum languages));
/* in expr.c */
-extern void init_cplus_expand PARAMS ((void));
-extern int extract_init PARAMS ((tree, tree));
+extern rtx cxx_expand_expr PARAMS ((tree, rtx,
+ enum machine_mode,
+ int));
extern tree cplus_expand_constant PARAMS ((tree));
/* friend.c */
@@ -3900,22 +3965,22 @@ extern void add_friend PARAMS ((tree, tree));
extern tree do_friend PARAMS ((tree, tree, tree, tree, tree, enum overload_flags, tree, int));
/* in init.c */
-extern void init_init_processing PARAMS ((void));
-extern void emit_base_init PARAMS ((tree, tree));
-extern tree expand_member_init PARAMS ((tree, tree, tree));
+extern tree expand_member_init (tree);
+extern void emit_mem_initializers (tree);
extern tree build_aggr_init PARAMS ((tree, tree, int));
+extern tree build_init PARAMS ((tree, tree, int));
extern int is_aggr_type PARAMS ((tree, int));
extern tree get_aggr_from_typedef PARAMS ((tree, int));
extern tree get_type_value PARAMS ((tree));
-extern tree build_forced_zero_init PARAMS ((tree));
+extern tree build_zero_init (tree, tree, bool);
extern tree build_member_call PARAMS ((tree, tree, tree));
extern tree build_offset_ref PARAMS ((tree, tree));
extern tree resolve_offset_ref PARAMS ((tree));
extern tree build_new PARAMS ((tree, tree, tree, int));
-extern tree build_vec_init PARAMS ((tree, tree, int));
+extern tree build_vec_init PARAMS ((tree, tree, tree, int));
extern tree build_x_delete PARAMS ((tree, int, tree));
extern tree build_delete PARAMS ((tree, tree, special_function_kind, int, int));
-extern void perform_base_cleanups PARAMS ((void));
+extern void push_base_cleanups PARAMS ((void));
extern tree build_vbase_delete PARAMS ((tree, tree));
extern tree build_vec_delete PARAMS ((tree, tree, special_function_kind, int));
extern tree create_temporary_var PARAMS ((tree));
@@ -3927,6 +3992,7 @@ extern tree build_java_class_ref PARAMS ((tree));
/* in input.c */
/* in lex.c */
+extern void cxx_dup_lang_specific_decl PARAMS ((tree));
extern tree make_pointer_declarator PARAMS ((tree, tree));
extern tree make_reference_declarator PARAMS ((tree, tree));
extern tree make_call_declarator PARAMS ((tree, tree, tree, tree));
@@ -3943,19 +4009,17 @@ extern void note_got_semicolon PARAMS ((tree));
extern void note_list_got_semicolon PARAMS ((tree));
extern void do_pending_lang_change PARAMS ((void));
extern void see_typename PARAMS ((void));
+extern void unqualified_name_lookup_error PARAMS ((tree));
extern tree do_identifier PARAMS ((tree, int, tree));
-extern tree do_scoped_id PARAMS ((tree, int));
+extern tree do_scoped_id PARAMS ((tree, tree));
extern tree identifier_typedecl_value PARAMS ((tree));
extern tree build_lang_decl PARAMS ((enum tree_code, tree, tree));
extern void retrofit_lang_decl PARAMS ((tree));
extern tree copy_decl PARAMS ((tree));
extern tree copy_type PARAMS ((tree));
-extern tree cp_make_lang_type PARAMS ((enum tree_code));
+extern tree cxx_make_type PARAMS ((enum tree_code));
extern tree make_aggr_type PARAMS ((enum tree_code));
-extern void compiler_error PARAMS ((const char *, ...))
- ATTRIBUTE_PRINTF_1;
extern void yyerror PARAMS ((const char *));
-extern void clear_inline_text_obstack PARAMS ((void));
extern void yyhook PARAMS ((int));
extern int cp_type_qual_from_rid PARAMS ((tree));
extern const char *cxx_init PARAMS ((const char *));
@@ -3979,7 +4043,6 @@ extern int calls_setjmp_p PARAMS ((tree));
extern int maybe_clone_body PARAMS ((tree));
/* in pt.c */
-extern void init_pt PARAMS ((void));
extern void check_template_shadow PARAMS ((tree));
extern tree get_innermost_template_args PARAMS ((tree, int));
extern tree tsubst PARAMS ((tree, tree, tsubst_flags_t, tree));
@@ -4012,7 +4075,7 @@ extern tree tinst_for_decl PARAMS ((void));
extern void mark_decl_instantiated PARAMS ((tree, int));
extern int more_specialized PARAMS ((tree, tree, int, int));
extern void mark_class_instantiated PARAMS ((tree, int));
-extern void do_decl_instantiation PARAMS ((tree, tree, tree));
+extern void do_decl_instantiation (tree, tree);
extern void do_type_instantiation PARAMS ((tree, tree, tsubst_flags_t));
extern tree instantiate_decl PARAMS ((tree, int));
extern tree get_bindings PARAMS ((tree, tree, tree));
@@ -4020,7 +4083,6 @@ extern int push_tinst_level PARAMS ((tree));
extern void pop_tinst_level PARAMS ((void));
extern int more_specialized_class PARAMS ((tree, tree));
extern int is_member_template PARAMS ((tree));
-extern int template_parms_equal PARAMS ((tree, tree));
extern int comp_template_parms PARAMS ((tree, tree));
extern int template_class_depth PARAMS ((tree));
extern int is_specialization_of PARAMS ((tree, tree));
@@ -4032,7 +4094,7 @@ extern void print_candidates PARAMS ((tree));
extern int instantiate_pending_templates PARAMS ((void));
extern tree tsubst_default_argument PARAMS ((tree, tree, tree));
extern tree most_general_template PARAMS ((tree));
-extern tree get_mostly_instantiated_function_type PARAMS ((tree, tree *, tree *));
+extern tree get_mostly_instantiated_function_type PARAMS ((tree));
extern int problematic_instantiation_changed PARAMS ((void));
extern void record_last_problematic_instantiation PARAMS ((void));
extern tree current_instantiation PARAMS ((void));
@@ -4061,6 +4123,7 @@ extern tree get_vbase PARAMS ((tree, tree));
extern tree get_dynamic_cast_base_type PARAMS ((tree, tree));
extern void type_access_control PARAMS ((tree, tree));
extern int accessible_p PARAMS ((tree, tree));
+extern tree lookup_field_1 (tree, tree, bool);
extern tree lookup_field PARAMS ((tree, tree, int, int));
extern tree lookup_nested_field PARAMS ((tree, int));
extern int lookup_fnfields_1 PARAMS ((tree, tree));
@@ -4079,6 +4142,7 @@ extern void init_search_processing PARAMS ((void));
extern void reinit_search_statistics PARAMS ((void));
extern tree current_scope PARAMS ((void));
extern int at_function_scope_p PARAMS ((void));
+extern bool at_class_scope_p (void);
extern tree context_for_name_lookup PARAMS ((tree));
extern tree lookup_conversions PARAMS ((tree));
extern tree binfo_for_vtable PARAMS ((tree));
@@ -4105,7 +4169,9 @@ extern tree unmarked_vtable_pathp PARAMS ((tree, void *));
extern tree find_vbase_instance PARAMS ((tree, tree));
extern tree binfo_for_vbase PARAMS ((tree, tree));
extern tree binfo_via_virtual PARAMS ((tree, tree));
-
+extern tree build_baselink (tree, tree, tree, tree);
+extern tree adjust_result_of_qualified_name_lookup
+ (tree, tree, tree);
/* in semantics.c */
extern void init_cp_semantics PARAMS ((void));
extern tree finish_expr_stmt PARAMS ((tree));
@@ -4157,19 +4223,19 @@ extern void finish_subobject PARAMS ((tree));
extern tree finish_parenthesized_expr PARAMS ((tree));
extern tree begin_stmt_expr PARAMS ((void));
extern tree finish_stmt_expr PARAMS ((tree));
-extern tree finish_call_expr PARAMS ((tree, tree, int));
+extern tree finish_call_expr (tree, tree, bool);
extern tree finish_increment_expr PARAMS ((tree, enum tree_code));
extern tree finish_this_expr PARAMS ((void));
extern tree finish_object_call_expr PARAMS ((tree, tree, tree));
extern tree finish_qualified_object_call_expr PARAMS ((tree, tree, tree));
extern tree finish_pseudo_destructor_call_expr PARAMS ((tree, tree, tree));
-extern tree finish_qualified_call_expr PARAMS ((tree, tree));
extern tree finish_unary_op_expr PARAMS ((enum tree_code, tree));
extern tree finish_id_expr PARAMS ((tree));
+extern tree finish_fname (tree);
extern void save_type_access_control PARAMS ((tree));
extern void reset_type_access_control PARAMS ((void));
extern void decl_type_access_control PARAMS ((tree));
-extern int begin_function_definition PARAMS ((tree, tree));
+extern int begin_function_definition (tree, tree, tree);
extern tree begin_constructor_declarator PARAMS ((tree, tree));
extern tree finish_declarator PARAMS ((tree, tree, tree, tree, int));
extern void finish_translation_unit PARAMS ((void));
@@ -4180,7 +4246,6 @@ extern tree begin_class_definition PARAMS ((tree));
extern tree finish_class_definition PARAMS ((tree, tree, int, int));
extern void finish_default_args PARAMS ((void));
extern void begin_inline_definitions PARAMS ((void));
-extern void finish_inline_definitions PARAMS ((void));
extern tree finish_member_class_template PARAMS ((tree));
extern void finish_template_decl PARAMS ((tree));
extern tree finish_template_type PARAMS ((tree, tree, int));
@@ -4192,21 +4257,22 @@ extern tree finish_typeof PARAMS ((tree));
extern tree finish_sizeof PARAMS ((tree));
extern tree finish_alignof PARAMS ((tree));
extern void finish_decl_cleanup PARAMS ((tree, tree));
+extern void finish_eh_cleanup PARAMS ((tree));
extern void finish_named_return_value PARAMS ((tree, tree));
extern void expand_body PARAMS ((tree));
extern tree nullify_returns_r PARAMS ((tree *, int *, void *));
extern void do_pushlevel PARAMS ((void));
extern tree do_poplevel PARAMS ((void));
+extern void begin_mem_initializers (void);
extern void finish_mem_initializers PARAMS ((tree));
extern void setup_vtbl_ptr PARAMS ((tree, tree));
extern void clear_out_block PARAMS ((void));
extern tree begin_global_stmt_expr PARAMS ((void));
extern tree finish_global_stmt_expr PARAMS ((tree));
-
+extern tree check_template_template_default_arg (tree);
/* in spew.c */
extern void init_spew PARAMS ((void));
-extern void mark_pending_inlines PARAMS ((PTR));
extern int peekyylex PARAMS ((void));
extern tree arbitrate_lookup PARAMS ((tree, tree, tree));
extern tree frob_opname PARAMS ((tree));
@@ -4219,6 +4285,11 @@ extern void replace_defarg PARAMS ((tree, tree));
extern void end_input PARAMS ((void));
/* in tree.c */
+extern void lang_check_failed PARAMS ((const char *, int,
+ const char *));
+extern tree stabilize_expr PARAMS ((tree, tree *));
+extern tree cxx_unsave_expr_now PARAMS ((tree));
+extern tree cxx_maybe_build_cleanup PARAMS ((tree));
extern void init_tree PARAMS ((void));
extern int pod_type_p PARAMS ((tree));
extern int zero_init_p PARAMS ((tree));
@@ -4226,7 +4297,11 @@ extern tree canonical_type_variant PARAMS ((tree));
extern void unshare_base_binfos PARAMS ((tree));
extern int member_p PARAMS ((tree));
extern cp_lvalue_kind real_lvalue_p PARAMS ((tree));
-extern tree build_min PARAMS ((enum tree_code, tree, ...));
+extern cp_lvalue_kind real_non_cast_lvalue_p (tree);
+extern int non_cast_lvalue_p PARAMS ((tree));
+extern int non_cast_lvalue_or_else PARAMS ((tree, const char *));
+extern tree build_min PARAMS ((enum tree_code, tree,
+ ...));
extern tree build_min_nt PARAMS ((enum tree_code, ...));
extern tree build_cplus_new PARAMS ((tree, tree));
extern tree get_target_expr PARAMS ((tree));
@@ -4241,6 +4316,7 @@ extern tree make_binfo PARAMS ((tree, tree, tree, tree));
extern tree reverse_path PARAMS ((tree));
extern int count_functions PARAMS ((tree));
extern int is_overloaded_fn PARAMS ((tree));
+extern tree get_overloaded_fn PARAMS ((tree));
extern tree get_first_fn PARAMS ((tree));
extern int bound_pmf_p PARAMS ((tree));
extern tree ovl_cons PARAMS ((tree, tree));
@@ -4248,7 +4324,7 @@ extern tree build_overload PARAMS ((tree, tree));
extern tree function_arg_chain PARAMS ((tree));
extern int promotes_to_aggr_type PARAMS ((tree, enum tree_code));
extern int is_aggr_type_2 PARAMS ((tree, tree));
-extern const char *lang_printable_name PARAMS ((tree, int));
+extern const char *cxx_printable_name PARAMS ((tree, int));
extern tree build_exception_variant PARAMS ((tree, tree));
extern tree bind_template_template_parm PARAMS ((tree, tree));
extern tree array_type_nelts_total PARAMS ((tree));
@@ -4259,8 +4335,7 @@ extern tree vec_binfo_member PARAMS ((tree, tree));
extern tree decl_namespace_context PARAMS ((tree));
extern tree lvalue_type PARAMS ((tree));
extern tree error_type PARAMS ((tree));
-extern tree build_ptr_wrapper PARAMS ((void *));
-extern tree build_int_wrapper PARAMS ((int));
+extern tree build_zc_wrapper PARAMS ((struct z_candidate *));
extern tree build_srcloc_here PARAMS ((void));
extern int varargs_function_p PARAMS ((tree));
extern int really_overloaded_fn PARAMS ((tree));
@@ -4270,13 +4345,14 @@ extern void debug_binfo PARAMS ((tree));
extern tree build_dummy_object PARAMS ((tree));
extern tree maybe_dummy_object PARAMS ((tree, tree *));
extern int is_dummy_object PARAMS ((tree));
-extern const struct attribute_spec cp_attribute_table[];
+extern const struct attribute_spec cxx_attribute_table[];
extern tree make_ptrmem_cst PARAMS ((tree, tree));
extern tree cp_build_qualified_type_real PARAMS ((tree, int, tsubst_flags_t));
#define cp_build_qualified_type(TYPE, QUALS) \
cp_build_qualified_type_real ((TYPE), (QUALS), tf_error | tf_warning)
extern tree build_shared_int_cst PARAMS ((int));
extern special_function_kind special_function_p PARAMS ((tree));
+extern bool name_p (tree);
extern int count_trees PARAMS ((tree));
extern int char_type_p PARAMS ((tree));
extern void verify_stmt_tree PARAMS ((tree));
@@ -4300,7 +4376,8 @@ extern tree condition_conversion PARAMS ((tree));
extern tree target_type PARAMS ((tree));
extern tree require_complete_type PARAMS ((tree));
extern tree complete_type PARAMS ((tree));
-extern tree complete_type_or_else PARAMS ((tree, tree));
+extern tree complete_type_or_diagnostic PARAMS ((tree, tree, int));
+#define complete_type_or_else(T,V) (complete_type_or_diagnostic ((T), (V), 0))
extern int type_unknown_p PARAMS ((tree));
extern tree commonparms PARAMS ((tree, tree));
extern tree original_type PARAMS ((tree));
@@ -4311,17 +4388,15 @@ extern int compparms PARAMS ((tree, tree));
extern int comp_cv_qualification PARAMS ((tree, tree));
extern int comp_cv_qual_signature PARAMS ((tree, tree));
extern tree expr_sizeof PARAMS ((tree));
-extern tree c_sizeof_nowarn PARAMS ((tree));
+extern tree cxx_sizeof_or_alignof_type PARAMS ((tree, enum tree_code, int));
+#define cxx_sizeof_nowarn(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, false)
extern tree inline_conversion PARAMS ((tree));
extern tree decay_conversion PARAMS ((tree));
-extern tree build_object_ref PARAMS ((tree, tree, tree));
-extern tree build_component_ref_1 PARAMS ((tree, tree, int));
-extern tree build_component_ref PARAMS ((tree, tree, tree, int));
-extern tree build_x_component_ref PARAMS ((tree, tree, tree, int));
+extern tree build_class_member_access_expr (tree, tree, tree, bool);
+extern tree finish_class_member_access_expr (tree, tree);
extern tree build_x_indirect_ref PARAMS ((tree, const char *));
extern tree build_indirect_ref PARAMS ((tree, const char *));
extern tree build_array_ref PARAMS ((tree, tree));
-extern tree build_x_function_call PARAMS ((tree, tree, tree));
extern tree get_member_function_from_ptrfunc PARAMS ((tree *, tree));
extern tree build_function_call_real PARAMS ((tree, tree, int, int));
extern tree build_function_call_maybe PARAMS ((tree, tree));
@@ -4357,20 +4432,27 @@ extern tree merge_types PARAMS ((tree, tree));
extern tree check_return_expr PARAMS ((tree));
#define cp_build_binary_op(code, arg1, arg2) \
build_binary_op(code, arg1, arg2, 1)
+#define cxx_sizeof(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, true)
+#define cxx_alignof(T) cxx_sizeof_or_alignof_type (T, ALIGNOF_EXPR, true)
+extern tree build_ptrmemfunc_access_expr (tree, tree);
+extern tree build_address (tree);
+extern tree build_nop (tree, tree);
/* in typeck2.c */
+extern void require_complete_eh_spec_types PARAMS ((tree, tree));
+extern void cxx_incomplete_type_diagnostic PARAMS ((tree, tree, int));
+#undef cxx_incomplete_type_error
+extern void cxx_incomplete_type_error PARAMS ((tree, tree));
+#define cxx_incomplete_type_error(V,T) \
+ (cxx_incomplete_type_diagnostic ((V), (T), 0))
extern tree error_not_base_type PARAMS ((tree, tree));
extern tree binfo_or_else PARAMS ((tree, tree));
extern void readonly_error PARAMS ((tree, const char *, int));
extern int abstract_virtuals_error PARAMS ((tree, tree));
-#define my_friendly_assert(EXP, N) (void) \
- (((EXP) == 0) ? (fancy_abort (__FILE__, __LINE__, __FUNCTION__), 0) : 0)
-
-extern tree force_store_init_value PARAMS ((tree, tree));
extern tree store_init_value PARAMS ((tree, tree));
extern tree digest_init PARAMS ((tree, tree, tree *));
-extern tree build_scoped_ref PARAMS ((tree, tree));
+extern tree build_scoped_ref PARAMS ((tree, tree, tree *));
extern tree build_x_arrow PARAMS ((tree));
extern tree build_m_component_ref PARAMS ((tree, tree));
extern tree build_functional_cast PARAMS ((tree, tree));
diff --git a/contrib/gcc/cp/cvt.c b/contrib/gcc/cp/cvt.c
index 1603a2a..75a6a3a 100644
--- a/contrib/gcc/cp/cvt.c
+++ b/contrib/gcc/cp/cvt.c
@@ -52,7 +52,7 @@ static void warn_ref_binding PARAMS ((tree, tree, tree));
narrowing is always done with a NOP_EXPR:
In convert.c, convert_to_integer.
In c-typeck.c, build_binary_op_nodefault (boolean ops),
- and truthvalue_conversion.
+ and c_common_truthvalue_conversion.
In expr.c: expand_expr, for operands of a MULT_EXPR.
In fold-const.c: fold.
In tree.c: get_narrower and get_unwidened.
@@ -90,7 +90,7 @@ cp_convert_to_pointer (type, expr, force)
return error_mark_node;
}
- rval = build_type_conversion (type, expr, 1);
+ rval = build_type_conversion (type, expr);
if (rval)
{
if (rval == error_mark_node)
@@ -130,6 +130,9 @@ cp_convert_to_pointer (type, expr, force)
intype = TREE_TYPE (expr);
}
+ if (expr == error_mark_node)
+ return error_mark_node;
+
form = TREE_CODE (intype);
if (POINTER_TYPE_P (intype))
@@ -145,31 +148,33 @@ cp_convert_to_pointer (type, expr, force)
{
enum tree_code code = PLUS_EXPR;
tree binfo;
-
- /* Try derived to base conversion. */
- binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type),
- ba_check, NULL);
- if (!binfo)
+ tree intype_class;
+ tree type_class;
+ bool same_p;
+
+ intype_class = TREE_TYPE (intype);
+ type_class = TREE_TYPE (type);
+
+ same_p = same_type_p (TYPE_MAIN_VARIANT (intype_class),
+ TYPE_MAIN_VARIANT (type_class));
+ binfo = NULL_TREE;
+ /* Try derived to base conversion. */
+ if (!same_p)
+ binfo = lookup_base (intype_class, type_class, ba_check, NULL);
+ if (!same_p && !binfo)
{
- /* Try base to derived conversion. */
- binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
- ba_check, NULL);
+ /* Try base to derived conversion. */
+ binfo = lookup_base (type_class, intype_class, ba_check, NULL);
code = MINUS_EXPR;
}
if (binfo == error_mark_node)
return error_mark_node;
- if (binfo)
+ if (binfo || same_p)
{
- expr = build_base_path (code, expr, binfo, 0);
- /* Add any qualifier conversions. */
- if (!same_type_p (TREE_TYPE (TREE_TYPE (expr)),
- TREE_TYPE (type)))
- {
- expr = build1 (NOP_EXPR, type, expr);
- TREE_CONSTANT (expr) =
- TREE_CONSTANT (TREE_OPERAND (expr, 0));
- }
- return expr;
+ if (binfo)
+ expr = build_base_path (code, expr, binfo, 0);
+ /* Add any qualifier conversions. */
+ return build_nop (type, expr);
}
}
@@ -222,9 +227,7 @@ cp_convert_to_pointer (type, expr, force)
return error_mark_node;
}
- rval = build1 (NOP_EXPR, type, expr);
- TREE_CONSTANT (rval) = TREE_CONSTANT (expr);
- return rval;
+ return build_nop (type, expr);
}
else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
@@ -253,12 +256,18 @@ cp_convert_to_pointer (type, expr, force)
force_fit_type (expr, 0);
return expr;
}
+ else if ((TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
+ && INTEGRAL_CODE_P (form))
+ {
+ error ("invalid conversion from '%T' to '%T'", intype, type);
+ return error_mark_node;
+ }
if (INTEGRAL_CODE_P (form))
{
if (TYPE_PRECISION (intype) == POINTER_SIZE)
return build1 (CONVERT_EXPR, type, expr);
- expr = cp_convert (type_for_size (POINTER_SIZE, 0), expr);
+ expr = cp_convert (c_common_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)))
@@ -313,19 +322,14 @@ convert_to_pointer_force (type, expr)
if (binfo)
{
expr = build_base_path (code, expr, binfo, 0);
- if (expr == error_mark_node)
- return error_mark_node;
- /* Add any qualifier conversions. */
+ if (expr == error_mark_node)
+ return error_mark_node;
+ /* Add any qualifier conversions. */
if (!same_type_p (TREE_TYPE (TREE_TYPE (expr)),
TREE_TYPE (type)))
- {
- expr = build1 (NOP_EXPR, type, expr);
- TREE_CONSTANT (expr) =
- TREE_CONSTANT (TREE_OPERAND (expr, 0));
- }
+ expr = build_nop (type, expr);
return expr;
}
-
}
}
@@ -348,7 +352,6 @@ build_up_reference (type, arg, flags, decl)
tree rval;
tree argtype = TREE_TYPE (arg);
tree target_type = TREE_TYPE (type);
- tree stmt_expr = NULL_TREE;
my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187);
@@ -358,25 +361,7 @@ build_up_reference (type, arg, flags, decl)
here because it needs to live as long as DECL. */
tree targ = arg;
- arg = build_decl (VAR_DECL, NULL_TREE, argtype);
- DECL_ARTIFICIAL (arg) = 1;
- TREE_USED (arg) = 1;
- TREE_STATIC (arg) = TREE_STATIC (decl);
-
- if (TREE_STATIC (decl))
- {
- /* Namespace-scope or local static; give it a mangled name. */
- tree name = mangle_ref_init_variable (decl);
- DECL_NAME (arg) = name;
- SET_DECL_ASSEMBLER_NAME (arg, name);
- arg = pushdecl_top_level (arg);
- }
- else
- {
- /* Automatic; make sure we handle the cleanup properly. */
- maybe_push_cleanup_level (argtype);
- arg = pushdecl (arg);
- }
+ arg = make_temporary_var_for_ref_to_temp (decl, TREE_TYPE (arg));
/* Process the initializer for the declaration. */
DECL_INITIAL (arg) = targ;
@@ -409,16 +394,7 @@ build_up_reference (type, arg, flags, decl)
else
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));
-
- /* If we created and initialized a new temporary variable, add the
- representation of that initialization to the RVAL. */
- if (stmt_expr)
- rval = build (COMPOUND_EXPR, TREE_TYPE (rval), stmt_expr, rval);
-
- /* And return the result. */
- return rval;
+ return build_nop (type, rval);
}
/* Subroutine of convert_to_reference. REFTYPE is the target reference type.
@@ -500,7 +476,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
/* Look for a user-defined conversion to lvalue that we can use. */
rval_as_conversion
- = build_type_conversion (reftype, expr, 1);
+ = build_type_conversion (reftype, expr);
if (rval_as_conversion && rval_as_conversion != error_mark_node
&& real_lvalue_p (rval_as_conversion))
@@ -609,6 +585,21 @@ convert_lvalue (totype, expr)
NULL_TREE);
return convert_from_reference (expr);
}
+
+/* Really perform an lvalue-to-rvalue conversion, including copying an
+ argument of class type into a temporary. */
+
+tree
+force_rvalue (tree expr)
+{
+ if (IS_AGGR_TYPE (TREE_TYPE (expr)) && TREE_CODE (expr) != TARGET_EXPR)
+ expr = ocp_convert (TREE_TYPE (expr), expr,
+ CONV_IMPLICIT|CONV_FORCE_TEMP, LOOKUP_NORMAL);
+ else
+ expr = decay_conversion (expr);
+
+ return expr;
+}
/* C++ conversions, preference to static cast conversions. */
@@ -697,7 +688,7 @@ ocp_convert (type, expr, convtype, flags)
if (IS_AGGR_TYPE (intype))
{
tree rval;
- rval = build_type_conversion (type, e, 1);
+ rval = build_type_conversion (type, e);
if (rval)
return rval;
if (flags & LOOKUP_COMPLAIN)
@@ -733,7 +724,7 @@ ocp_convert (type, expr, convtype, flags)
if (IS_AGGR_TYPE (TREE_TYPE (e)))
{
tree rval;
- rval = build_type_conversion (type, e, 1);
+ rval = build_type_conversion (type, e);
if (rval)
return rval;
else
@@ -776,22 +767,14 @@ ocp_convert (type, expr, convtype, flags)
the target with the temp (see [dcl.init]). */
ctor = build_user_type_conversion (type, ctor, flags);
else
- ctor = build_method_call (NULL_TREE,
- complete_ctor_identifier,
- build_tree_list (NULL_TREE, ctor),
- TYPE_BINFO (type), flags);
+ ctor = build_special_member_call (NULL_TREE,
+ complete_ctor_identifier,
+ build_tree_list (NULL_TREE, ctor),
+ TYPE_BINFO (type), flags);
if (ctor)
return build_cplus_new (type, ctor);
}
- /* If TYPE or TREE_TYPE (E) is not on the permanent_obstack,
- then it won't be hashed and hence compare as not equal,
- even when it is. */
- if (code == ARRAY_TYPE
- && TREE_TYPE (TREE_TYPE (e)) == TREE_TYPE (type)
- && index_type_equal (TYPE_DOMAIN (TREE_TYPE (e)), TYPE_DOMAIN (type)))
- return e;
-
if (flags & LOOKUP_COMPLAIN)
error ("conversion from `%T' to non-scalar type `%T' requested",
TREE_TYPE (expr), type);
@@ -864,7 +847,7 @@ convert_to_void (expr, implicit)
case NON_LVALUE_EXPR:
case NOP_EXPR:
- /* These have already decayed to rvalue. */
+ /* These have already decayed to rvalue. */
break;
case CALL_EXPR: /* we have a special meaning for volatile void fn() */
@@ -1021,26 +1004,18 @@ convert_force (type, expr, convtype)
allowed (references private members, etc).
If no conversion exists, NULL_TREE is returned.
- If (FOR_SURE & 1) is non-zero, then we allow this type conversion
- to take place immediately. Otherwise, we build a SAVE_EXPR
- which can be evaluated if the results are ever needed.
-
- Changes to this functions should be mirrored in user_harshness.
-
FIXME: Ambiguity checking is wrong. Should choose one by the implicit
object parameter, or by the second standard conversion sequence if
that doesn't do it. This will probably wait for an overloading rewrite.
(jason 8/9/95) */
tree
-build_type_conversion (xtype, expr, for_sure)
+build_type_conversion (xtype, expr)
tree xtype, expr;
- int for_sure;
{
/* C++: check to see if we can convert this aggregate type
into the required type. */
- return build_user_type_conversion
- (xtype, expr, for_sure ? LOOKUP_NORMAL : 0);
+ return build_user_type_conversion (xtype, expr, LOOKUP_NORMAL);
}
/* Convert the given EXPR to one of a group of types suitable for use in an
@@ -1186,10 +1161,10 @@ type_promotes_to (type)
{
int precision = MAX (TYPE_PRECISION (type),
TYPE_PRECISION (integer_type_node));
- tree totype = type_for_size (precision, 0);
+ tree totype = c_common_type_for_size (precision, 0);
if (TREE_UNSIGNED (type)
&& ! int_fits_type_p (TYPE_MAX_VALUE (type), totype))
- type = type_for_size (precision, 1);
+ type = c_common_type_for_size (precision, 1);
else
type = totype;
}
diff --git a/contrib/gcc/cp/decl.c b/contrib/gcc/cp/decl.c
index 5c891a5..be31ac2 100644
--- a/contrib/gcc/cp/decl.c
+++ b/contrib/gcc/cp/decl.c
@@ -41,34 +41,34 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "except.h"
#include "toplev.h"
-#include "../hash.h"
+#include "hashtab.h"
#include "ggc.h"
#include "tm_p.h"
#include "target.h"
#include "c-common.h"
#include "c-pragma.h"
#include "diagnostic.h"
-
-extern const struct attribute_spec *lang_attribute_table;
+#include "debug.h"
+#include "timevar.h"
+#include "input.h"
static tree grokparms PARAMS ((tree));
static const char *redeclaration_error_message PARAMS ((tree, tree));
-static void push_binding_level PARAMS ((struct binding_level *, int,
+static void push_binding_level PARAMS ((struct cp_binding_level *, int,
int));
static void pop_binding_level PARAMS ((void));
static void suspend_binding_level PARAMS ((void));
-static void resume_binding_level PARAMS ((struct binding_level *));
-static struct binding_level *make_binding_level PARAMS ((void));
+static void resume_binding_level PARAMS ((struct cp_binding_level *));
+static struct cp_binding_level *make_binding_level PARAMS ((void));
static void declare_namespace_level PARAMS ((void));
static int decl_jump_unsafe PARAMS ((tree));
static void storedecls PARAMS ((tree));
static void require_complete_types_for_parms PARAMS ((tree));
static int ambi_op_p PARAMS ((enum tree_code));
static int unary_op_p PARAMS ((enum tree_code));
-static tree store_bindings PARAMS ((tree, tree));
+static cxx_saved_binding *store_bindings (tree, cxx_saved_binding *);
static tree lookup_tag_reverse PARAMS ((tree, tree));
-static tree obscure_complex_init PARAMS ((tree, tree));
static tree lookup_name_real PARAMS ((tree, int, int, int));
static void push_local_name PARAMS ((tree));
static void warn_extern_redeclared_static PARAMS ((tree, tree));
@@ -79,60 +79,54 @@ static tree grokfndecl PARAMS ((tree, tree, tree, tree, int,
static tree grokvardecl PARAMS ((tree, tree, RID_BIT_TYPE *, int, int, tree));
static tree follow_tag_typedef PARAMS ((tree));
static tree lookup_tag PARAMS ((enum tree_code, tree,
- struct binding_level *, int));
+ struct cp_binding_level *, int));
static void set_identifier_type_value_with_scope
- PARAMS ((tree, tree, struct binding_level *));
+ PARAMS ((tree, tree, struct cp_binding_level *));
static void record_unknown_type PARAMS ((tree, const char *));
static tree builtin_function_1 PARAMS ((const char *, tree, tree, int,
- enum built_in_class, const char *));
+ enum built_in_class, const char *,
+ tree));
static tree build_library_fn_1 PARAMS ((tree, enum tree_code, tree));
static int member_function_or_else PARAMS ((tree, tree, enum overload_flags));
static void bad_specifiers PARAMS ((tree, const char *, int, int, int, int,
int));
-static tree maybe_process_template_type_declaration PARAMS ((tree, int, struct binding_level*));
+static tree maybe_process_template_type_declaration PARAMS ((tree, int, struct cp_binding_level*));
static void check_for_uninitialized_const_var PARAMS ((tree));
-static unsigned long typename_hash PARAMS ((hash_table_key));
-static bool typename_compare PARAMS ((hash_table_key, hash_table_key));
-static void push_binding PARAMS ((tree, tree, struct binding_level*));
+static hashval_t typename_hash PARAMS ((const void *));
+static int typename_compare PARAMS ((const void *, const void *));
+static void push_binding PARAMS ((tree, tree, struct cp_binding_level*));
static int add_binding PARAMS ((tree, tree));
static void pop_binding PARAMS ((tree, tree));
static tree local_variable_p_walkfn PARAMS ((tree *, int *, void *));
-static tree find_binding PARAMS ((tree, tree));
-static tree select_decl PARAMS ((tree, int));
+static cxx_binding *find_binding (tree, tree, cxx_binding *);
+static tree select_decl (cxx_binding *, int);
static int lookup_flags PARAMS ((int, int));
static tree qualify_lookup PARAMS ((tree, int));
static tree record_builtin_java_type PARAMS ((const char *, int));
static const char *tag_name PARAMS ((enum tag_types code));
static void find_class_binding_level PARAMS ((void));
-static struct binding_level *innermost_nonclass_level PARAMS ((void));
+static struct cp_binding_level *innermost_nonclass_level PARAMS ((void));
static void warn_about_implicit_typename_lookup PARAMS ((tree, tree));
static int walk_namespaces_r PARAMS ((tree, walk_namespaces_fn, void *));
static int walk_globals_r PARAMS ((tree, void *));
-static void add_decl_to_level PARAMS ((tree, struct binding_level *));
+static int walk_vtables_r PARAMS ((tree, void*));
+static void add_decl_to_level PARAMS ((tree, struct cp_binding_level *));
static tree make_label_decl PARAMS ((tree, int));
static void use_label PARAMS ((tree));
-static void check_previous_goto_1 PARAMS ((tree, struct binding_level *, tree,
+static void check_previous_goto_1 PARAMS ((tree, struct cp_binding_level *, tree,
const char *, int));
static void check_previous_goto PARAMS ((struct named_label_use_list *));
-static void check_switch_goto PARAMS ((struct binding_level *));
+static void check_switch_goto PARAMS ((struct cp_binding_level *));
static void check_previous_gotos PARAMS ((tree));
static void pop_label PARAMS ((tree, tree));
static void pop_labels PARAMS ((tree));
static void maybe_deduce_size_from_array_init PARAMS ((tree, tree));
static void layout_var_decl PARAMS ((tree));
static void maybe_commonize_var PARAMS ((tree));
-static tree check_initializer PARAMS ((tree, tree));
+static tree check_initializer (tree, tree, int);
static void make_rtl_for_nonlocal_decl PARAMS ((tree, tree, const char *));
-static void push_cp_function_context PARAMS ((struct function *));
-static void pop_cp_function_context PARAMS ((struct function *));
-static void mark_binding_level PARAMS ((void *));
-static void mark_named_label_lists PARAMS ((void *, void *));
-static void mark_cp_function_context PARAMS ((struct function *));
-static void mark_saved_scope PARAMS ((void *));
-static void mark_lang_function PARAMS ((struct cp_language_function *));
static void save_function_data PARAMS ((tree));
static void check_function_type PARAMS ((tree, tree));
-static void destroy_local_var PARAMS ((tree));
static void begin_constructor_body PARAMS ((void));
static void finish_constructor_body PARAMS ((void));
static void begin_destructor_body PARAMS ((void));
@@ -150,10 +144,10 @@ static tree push_cp_library_fn PARAMS ((enum tree_code, tree));
static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree));
static void store_parm_decls PARAMS ((tree));
static int cp_missing_noreturn_ok_p PARAMS ((tree));
-
-#if defined (DEBUG_CP_BINDING_LEVELS)
-static void indent PARAMS ((void));
-#endif
+static void initialize_local_var (tree, tree);
+static void expand_static_init (tree, tree);
+static tree next_initializable_field (tree);
+static tree reshape_init (tree, tree *);
/* Erroneous argument lists can use this *IFF* they do not modify it. */
tree error_mark_list;
@@ -208,17 +202,17 @@ tree cp_global_trees[CPTI_MAX];
/* Indicates that there is a type value in some namespace, although
that is not necessarily in scope at the moment. */
-static tree global_type_node;
+static GTY(()) tree global_type_node;
-/* Expect only namespace names now. */
+/* Expect only namespace names now. */
static int only_namespace_names;
/* Used only for jumps to as-yet undefined labels, since jumps to
defined labels can have their validity checked immediately. */
-struct named_label_use_list
+struct named_label_use_list GTY(())
{
- struct binding_level *binding_level;
+ struct cp_binding_level *binding_level;
tree names_in_scope;
tree label_decl;
const char *filename_o_goto;
@@ -249,9 +243,9 @@ tree last_function_parms;
we can clear out their names' definitions at the end of the
function, and so we can check the validity of jumps to these labels. */
-struct named_label_list
+struct named_label_list GTY(())
{
- struct binding_level *binding_level;
+ struct cp_binding_level *binding_level;
tree names_in_scope;
tree old_value;
tree label_decl;
@@ -262,36 +256,7 @@ struct named_label_list
};
#define named_labels cp_function_chain->x_named_labels
-
-/* Nonzero means use the ISO C94 dialect of C. */
-
-int flag_isoc94;
-
-/* Nonzero means use the ISO C99 dialect of C. */
-
-int flag_isoc99;
-
-/* Nonzero means we are a hosted implementation for code shared with C. */
-
-int flag_hosted = 1;
-
-/* Nonzero means add default format_arg attributes for functions not
- in ISO C. */
-
-int flag_noniso_default_format_attributes = 1;
-
-/* Nonzero if we want to conserve space in the .o files. We do this
- by putting uninitialized data and runtime initialized data into
- .common instead of .data at the expense of not flagging multiple
- definitions. */
-extern int flag_conserve_space;
-/* C and C++ flags are in decl2.c. */
-
-/* A expression of value 0 with the same precision as a sizetype
- node, but signed. */
-tree signed_size_zero_node;
-
/* The name of the anonymous namespace, throughout this translation
unit. */
tree anonymous_namespace_name;
@@ -317,7 +282,254 @@ static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
being flagged as deprecated or reported as using deprecated
types. */
int adding_implicit_members = 0;
+
+/* True if a declaration with an `extern' linkage specifier is being
+ processed. */
+bool have_extern_spec;
+
+/* Compute the chain index of a binding_entry given the HASH value of its
+ name and the total COUNT of chains. COUNT is assumed to be a power
+ of 2. */
+#define ENTRY_INDEX(HASH, COUNT) (((HASH) >> 3) & ((COUNT) - 1))
+
+/* A free list of "binding_entry"s awaiting for re-use. */
+static GTY((deletable(""))) binding_entry free_binding_entry;
+
+/* Create a binding_entry object for (NAME, TYPE). */
+static inline binding_entry
+binding_entry_make (tree name, tree type)
+{
+ binding_entry entry;
+
+ if (free_binding_entry)
+ {
+ entry = free_binding_entry;
+ free_binding_entry = entry->chain;
+ }
+ else
+ entry = ggc_alloc (sizeof (struct binding_entry_s));
+
+ entry->name = name;
+ entry->type = type;
+
+ return entry;
+}
+
+/* Put ENTRY back on the free list. */
+static inline void
+binding_entry_free (binding_entry entry)
+{
+ entry->chain = free_binding_entry;
+ free_binding_entry = entry;
+}
+
+/* The datatype used to implement the mapping from names to types at
+ a given scope. */
+struct binding_table_s GTY(())
+{
+ /* Array of chains of "binding_entry"s */
+ binding_entry * GTY((length ("%h.chain_count"))) chain;
+
+ /* The number of chains in this table. This is the length of the
+ the member "chaiin" considered as an array. */
+ size_t chain_count;
+
+ /* Number of "binding_entry"s in this table. */
+ size_t entry_count;
+};
+
+/* These macros indicate the initial chains count for binding_table. */
+#define SCOPE_DEFAULT_HT_SIZE (1 << 3)
+#define CLASS_SCOPE_HT_SIZE (1 << 3)
+#define NAMESPACE_ORDINARY_HT_SIZE (1 << 5)
+#define NAMESPACE_STD_HT_SIZE (1 << 8)
+#define GLOBAL_SCOPE_HT_SIZE (1 << 8)
+
+/* Construct TABLE with an initial CHAIN_COUNT. */
+static inline void
+binding_table_construct (binding_table table, size_t chain_count)
+{
+ table->chain_count = chain_count;
+ table->entry_count = 0;
+ table->chain = ggc_alloc_cleared
+ (table->chain_count * sizeof (binding_entry));
+}
+
+/* Free TABLE by making its entries ready for reuse. */
+static inline void
+binding_table_free (binding_table table)
+{
+ size_t i;
+ if (table == NULL)
+ return;
+
+ for (i = 0; i < table->chain_count; ++i)
+ {
+ while (table->chain[i] != NULL)
+ {
+ binding_entry entry = table->chain[i];
+ table->chain[i] = entry->chain;
+ binding_entry_free (entry);
+ }
+ }
+ table->entry_count = 0;
+}
+
+/* Allocate a table with CHAIN_COUNT, assumed to be a power of two. */
+static inline binding_table
+binding_table_new (size_t chain_count)
+{
+ binding_table table = ggc_alloc (sizeof (struct binding_table_s));
+ binding_table_construct (table, chain_count);
+ return table;
+}
+
+/* Expand TABLE to twice its current chain_count. */
+static void
+binding_table_expand (binding_table table)
+{
+ const size_t old_chain_count = table->chain_count;
+ const size_t old_entry_count = table->entry_count;
+ const size_t new_chain_count = 2 * old_chain_count;
+ binding_entry *old_chains = table->chain;
+ size_t i;
+
+ binding_table_construct (table, new_chain_count);
+ for (i = 0; i < old_chain_count; ++i)
+ {
+ binding_entry entry = old_chains[i];
+ for (; entry != NULL; entry = old_chains[i])
+ {
+ const unsigned int hash = IDENTIFIER_HASH_VALUE (entry->name);
+ const size_t j = ENTRY_INDEX (hash, new_chain_count);
+
+ old_chains[i] = entry->chain;
+ entry->chain = table->chain[j];
+ table->chain[j] = entry;
+ }
+ }
+ table->entry_count = old_entry_count;
+}
+
+/* Insert a binding for NAME to TYPe into TABLE. */
+static inline void
+binding_table_insert (binding_table table, tree name, tree type)
+{
+ const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
+ const size_t i = ENTRY_INDEX (hash, table->chain_count);
+ binding_entry entry = binding_entry_make (name, type);
+
+ entry->chain = table->chain[i];
+ table->chain[i] = entry;
+ ++table->entry_count;
+
+ if (3 * table->chain_count < 5 * table->entry_count)
+ binding_table_expand (table);
+}
+
+/* Return the binding_entry, if any, that maps NAME. */
+binding_entry
+binding_table_find (binding_table table, tree name)
+{
+ const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
+ binding_entry entry = table->chain[ENTRY_INDEX (hash, table->chain_count)];
+
+ while (entry != NULL && entry->name != name)
+ entry = entry->chain;
+
+ return entry;
+}
+
+/* Return the binding_entry, if any, that maps name to an anonymous type. */
+static inline tree
+binding_table_find_anon_type (binding_table table, tree name)
+{
+ const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
+ binding_entry entry = table->chain[ENTRY_INDEX (hash, table->chain_count)];
+
+ while (entry != NULL && TYPE_IDENTIFIER (entry->type) != name)
+ entry = entry->chain;
+
+ return entry ? entry->type : NULL;
+}
+
+/* Return the binding_entry, if any, that has TYPE as target. If NAME
+ is non-null, then set the domain and rehash that entry. */
+static inline binding_entry
+binding_table_reverse_maybe_remap (binding_table table, tree type, tree name)
+{
+ const size_t chain_count = table->chain_count;
+ binding_entry entry = NULL;
+ binding_entry *p;
+ size_t i;
+
+ for (i = 0; i < chain_count && entry == NULL; ++i)
+ {
+ p = &table->chain[i];
+ while (*p != NULL && entry == NULL)
+ if ((*p)->type == type)
+ entry = *p;
+ else
+ p = &(*p)->chain;
+ }
+
+ if (entry != NULL && name != NULL && entry->name != name)
+ {
+ /* Remove the bucket from the previous chain. */
+ *p = (*p)->chain;
+
+ /* Remap the name type to type. */
+ i = ENTRY_INDEX (IDENTIFIER_HASH_VALUE (name), chain_count);
+ entry->chain = table->chain[i];
+ entry->name = name;
+ table->chain[i] = entry;
+ }
+
+ return entry;
+}
+
+/* Remove from TABLE all entries that map to anonymous enums or
+ class-types. */
+static void
+binding_table_remove_anonymous_types (binding_table table)
+{
+ const size_t chain_count = table->chain_count;
+ size_t i;
+
+ for (i = 0; i < chain_count; ++i)
+ {
+ binding_entry *p = &table->chain[i];
+
+ while (*p != NULL)
+ if (ANON_AGGRNAME_P ((*p)->name))
+ {
+ binding_entry e = *p;
+ *p = (*p)->chain;
+ --table->entry_count;
+ binding_entry_free (e);
+ }
+ else
+ p = &(*p)->chain;
+ }
+}
+
+/* Apply PROC -- with DATA -- to all entries in TABLE. */
+void
+binding_table_foreach (binding_table table, bt_foreach_proc proc, void *data)
+{
+ const size_t chain_count = table->chain_count;
+ size_t i;
+
+ for (i = 0; i < chain_count; ++i)
+ {
+ binding_entry entry = table->chain[i];
+ for (; entry != NULL; entry = entry->chain)
+ proc (entry, data);
+ }
+}
+
+
/* For each binding contour we allocate a binding_level structure
which records the names defined in that contour.
Contours include:
@@ -342,7 +554,7 @@ int adding_implicit_members = 0;
/* Note that the information in the `names' component of the global contour
is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
-struct binding_level
+struct cp_binding_level GTY(())
{
/* A chain of _DECL nodes for all variables, constants, functions,
and typedef types. These are in the reverse of the order
@@ -350,21 +562,26 @@ struct binding_level
are wrapped in TREE_LISTs; the TREE_VALUE is the OVERLOAD. */
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.
+ /* Count of elements in names chain. */
+ size_t names_size;
+
+ /* A chain of NAMESPACE_DECL nodes. */
+ tree namespaces;
+
+ /* An array of static functions and variables (for namespaces only) */
+ varray_type static_decls;
- C++: the TREE_VALUE nodes can be simple types for
- component_bindings. */
- tree tags;
+ /* A chain of VTABLE_DECL nodes. */
+ tree vtables;
- /* A list of USING_DECL nodes. */
+ /* A dictionary for looking up enums or class-types names. */
+ binding_table type_decls;
+
+ /* A list of USING_DECL nodes. */
tree usings;
/* A list of used namespaces. PURPOSE is the namespace,
- VALUE the common ancestor with this binding_level's namespace. */
+ VALUE the common ancestor with this binding_level's namespace. */
tree using_directives;
/* If this binding level is the binding level for a class, then
@@ -392,7 +609,7 @@ struct binding_level
tree this_class;
/* The binding level which this one is contained in (inherits from). */
- struct binding_level *level_chain;
+ struct cp_binding_level *level_chain;
/* List of VAR_DECLS saved from a previous for statement.
These would be dead in ISO-conforming code, but might
@@ -443,13 +660,15 @@ struct binding_level
/* Three bits left for this word. */
-#if defined(DEBUG_CP_BINDING_LEVELS)
/* Binding depth at which this level began. */
unsigned binding_depth;
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
};
-#define NULL_BINDING_LEVEL ((struct binding_level *) NULL)
+#define NULL_BINDING_LEVEL ((struct cp_binding_level *) NULL)
+
+/* True if SCOPE designates the global scope binding contour. */
+#define global_scope_p(SCOPE) \
+ ((SCOPE) == NAMESPACE_LEVEL (global_namespace))
/* The binding level currently in effect. */
@@ -464,13 +683,7 @@ struct binding_level
/* A chain of binding_level structures awaiting reuse. */
-static struct binding_level *free_binding_level;
-
-/* The outermost binding level, for names of file scope.
- This is created when the compiler is started and exists
- through the entire run. */
-
-static struct binding_level *global_binding_level;
+static GTY((deletable (""))) struct cp_binding_level *free_binding_level;
/* Nonzero means unconditionally make a BLOCK for the next level pushed. */
@@ -480,46 +693,52 @@ static int keep_next_level_flag;
UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type. At the
time the VAR_DECL was declared, the type was incomplete. */
-static tree incomplete_vars;
+static GTY(()) tree incomplete_vars;
+
+#ifndef ENABLE_SCOPE_CHECKING
+# define ENABLE_SCOPE_CHECKING 0
+#else
+# define ENABLE_SCOPE_CHECKING 1
+#endif
-#if defined(DEBUG_CP_BINDING_LEVELS)
-static int binding_depth = 0;
+static unsigned binding_depth = 0;
static int is_class_level = 0;
static void
-indent ()
+indent (unsigned depth)
{
- register unsigned i;
+ unsigned i;
- for (i = 0; i < binding_depth*2; i++)
+ for (i = 0; i < depth * 2; i++)
putc (' ', stderr);
}
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
-static tree pushdecl_with_scope PARAMS ((tree, struct binding_level *));
+static tree pushdecl_with_scope PARAMS ((tree, struct cp_binding_level *));
static void
push_binding_level (newlevel, tag_transparent, keep)
- struct binding_level *newlevel;
+ struct cp_binding_level *newlevel;
int tag_transparent, keep;
{
/* Add this level to the front of the chain (stack) of levels that
are active. */
- memset ((char*) newlevel, 0, sizeof (struct binding_level));
+ memset ((char*) newlevel, 0, sizeof (struct cp_binding_level));
newlevel->level_chain = current_binding_level;
current_binding_level = newlevel;
newlevel->tag_transparent = tag_transparent;
newlevel->more_cleanups_ok = 1;
newlevel->keep = keep;
-#if defined(DEBUG_CP_BINDING_LEVELS)
- newlevel->binding_depth = binding_depth;
- indent ();
- fprintf (stderr, "push %s level 0x%08x line %d\n",
- (is_class_level) ? "class" : "block", newlevel, lineno);
- is_class_level = 0;
- binding_depth++;
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
+ if (ENABLE_SCOPE_CHECKING)
+ {
+ newlevel->binding_depth = binding_depth;
+ indent (binding_depth);
+ verbatim ("push %s level %p line %d\n",
+ (is_class_level) ? "class" : "block",
+ (void *) newlevel, lineno);
+ is_class_level = 0;
+ binding_depth++;
+ }
}
/* Find the innermost enclosing class scope, and reset
@@ -528,7 +747,7 @@ push_binding_level (newlevel, tag_transparent, keep)
static void
find_class_binding_level ()
{
- struct binding_level *level = current_binding_level;
+ struct cp_binding_level *level = current_binding_level;
while (level && level->parm_flag != 2)
level = level->level_chain;
@@ -541,34 +760,34 @@ find_class_binding_level ()
static void
pop_binding_level ()
{
- if (global_binding_level)
+ if (NAMESPACE_LEVEL (global_namespace))
+ /* Cannot pop a level, if there are none left to pop. */
+ my_friendly_assert (!global_scope_p (current_binding_level), 20030527);
+ /* Pop the current level, and free the structure for reuse. */
+ if (ENABLE_SCOPE_CHECKING)
{
- /* Cannot pop a level, if there are none left to pop. */
- if (current_binding_level == global_binding_level)
- abort ();
+ indent (--binding_depth);
+ verbatim ("pop %s level %p line %d\n",
+ (is_class_level) ? "class" : "block",
+ (void *) current_binding_level, lineno);
+ if (is_class_level != (current_binding_level == class_binding_level))
+ {
+ indent (binding_depth);
+ verbatim ("XXX is_class_level != (current_binding_level "
+ "== class_binding_level)\n");
+ }
+ is_class_level = 0;
}
- /* Pop the current level, and free the structure for reuse. */
-#if defined(DEBUG_CP_BINDING_LEVELS)
- binding_depth--;
- indent ();
- fprintf (stderr, "pop %s level 0x%08x line %d\n",
- (is_class_level) ? "class" : "block",
- current_binding_level, lineno);
- if (is_class_level != (current_binding_level == class_binding_level))
- {
- 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;
+ register struct cp_binding_level *level = current_binding_level;
current_binding_level = current_binding_level->level_chain;
level->level_chain = free_binding_level;
-#if 0 /* defined(DEBUG_CP_BINDING_LEVELS) */
- if (level->binding_depth != binding_depth)
- abort ();
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
+ if (level->parm_flag != 2)
+ binding_table_free (level->type_decls);
+ else
+ level->type_decls = NULL;
+ my_friendly_assert (!ENABLE_SCOPE_CHECKING
+ || level->binding_depth == binding_depth, 20030529);
free_binding_level = level;
find_class_binding_level ();
}
@@ -580,58 +799,56 @@ suspend_binding_level ()
if (class_binding_level)
current_binding_level = class_binding_level;
- if (global_binding_level)
+ if (NAMESPACE_LEVEL (global_namespace))
+ my_friendly_assert (!global_scope_p (current_binding_level), 20030527);
+ /* Suspend the current level. */
+ if (ENABLE_SCOPE_CHECKING)
{
- /* Cannot suspend a level, if there are none left to suspend. */
- if (current_binding_level == global_binding_level)
- abort ();
+ indent (--binding_depth);
+ verbatim("suspend %s level %p line %d\n",
+ (is_class_level) ? "class" : "block",
+ (void *) current_binding_level, lineno);
+ if (is_class_level != (current_binding_level == class_binding_level))
+ {
+ indent (binding_depth);
+ verbatim ("XXX is_class_level != (current_binding_level "
+ "== class_binding_level)\n");
+ }
+ is_class_level = 0;
}
- /* Suspend the current level. */
-#if defined(DEBUG_CP_BINDING_LEVELS)
- binding_depth--;
- indent ();
- fprintf (stderr, "suspend %s level 0x%08x line %d\n",
- (is_class_level) ? "class" : "block",
- current_binding_level, lineno);
- if (is_class_level != (current_binding_level == class_binding_level))
- {
- indent ();
- fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
- }
- is_class_level = 0;
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
current_binding_level = current_binding_level->level_chain;
find_class_binding_level ();
}
static void
resume_binding_level (b)
- struct binding_level *b;
+ struct cp_binding_level *b;
{
/* Resuming binding levels is meant only for namespaces,
- and those cannot nest into classes. */
+ and those cannot nest into classes. */
my_friendly_assert(!class_binding_level, 386);
/* Also, resuming a non-directly nested namespace is a no-no. */
my_friendly_assert(b->level_chain == current_binding_level, 386);
current_binding_level = b;
-#if defined(DEBUG_CP_BINDING_LEVELS)
- b->binding_depth = binding_depth;
- indent ();
- fprintf (stderr, "resume %s level 0x%08x line %d\n",
- (is_class_level) ? "class" : "block", b, lineno);
- is_class_level = 0;
- binding_depth++;
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
+ if (ENABLE_SCOPE_CHECKING)
+ {
+ b->binding_depth = binding_depth;
+ indent (binding_depth);
+ verbatim ("resume %s level %p line %d\n",
+ (is_class_level) ? "class" : "block", (void *) b, lineno);
+ is_class_level = 0;
+ binding_depth++;
+ }
}
-/* Create a new `struct binding_level'. */
+/* Create a new `struct cp_binding_level'. */
static
-struct binding_level *
+struct cp_binding_level *
make_binding_level ()
{
/* NOSTRICT */
- return (struct binding_level *) xmalloc (sizeof (struct binding_level));
+ return (struct cp_binding_level *) ggc_alloc (sizeof (struct cp_binding_level));
}
/* Nonzero if we are currently in the global binding level. */
@@ -639,15 +856,15 @@ make_binding_level ()
int
global_bindings_p ()
{
- return current_binding_level == global_binding_level;
+ return global_scope_p (current_binding_level);
}
/* Return the innermost binding level that is not for a class scope. */
-static struct binding_level *
+static struct cp_binding_level *
innermost_nonclass_level ()
{
- struct binding_level *b;
+ struct cp_binding_level *b;
b = current_binding_level;
while (b->parm_flag == 2)
@@ -665,7 +882,7 @@ innermost_nonclass_level ()
int
toplevel_bindings_p ()
{
- struct binding_level *b = innermost_nonclass_level ();
+ struct cp_binding_level *b = innermost_nonclass_level ();
return b->namespace_p || b->template_parms_p;
}
@@ -677,12 +894,12 @@ toplevel_bindings_p ()
int
namespace_bindings_p ()
{
- struct binding_level *b = innermost_nonclass_level ();
+ struct cp_binding_level *b = innermost_nonclass_level ();
return b->namespace_p;
}
-/* If KEEP is non-zero, make a BLOCK node for the next binding level,
+/* If KEEP is nonzero, make a BLOCK node for the next binding level,
unconditionally. Otherwise, use the normal logic to decide whether
or not to create a BLOCK. */
@@ -701,7 +918,7 @@ kept_level_p ()
return (current_binding_level->blocks != NULL_TREE
|| current_binding_level->keep
|| current_binding_level->names != NULL_TREE
- || (current_binding_level->tags != NULL_TREE
+ || (current_binding_level->type_decls != NULL
&& !current_binding_level->tag_transparent));
}
@@ -711,7 +928,7 @@ declare_namespace_level ()
current_binding_level->namespace_p = 1;
}
-/* Returns non-zero if this scope was created to store template
+/* Returns nonzero if this scope was created to store template
parameters. */
int
@@ -731,7 +948,7 @@ current_tmpl_spec_kind (n_class_scopes)
int n_template_parm_scopes = 0;
int seen_specialization_p = 0;
int innermost_specialization_p = 0;
- struct binding_level *b;
+ struct cp_binding_level *b;
/* Scan through the template parameter scopes. */
for (b = current_binding_level; b->template_parms_p; b = b->level_chain)
@@ -742,7 +959,7 @@ current_tmpl_spec_kind (n_class_scopes)
template <class T> template <> ...
- which is always illegal since [temp.expl.spec] forbids the
+ which is always invalid since [temp.expl.spec] forbids the
specialization of a class member template if the enclosing
class templates are not explicitly specialized as well. */
if (b->template_spec_p)
@@ -779,7 +996,7 @@ current_tmpl_spec_kind (n_class_scopes)
template <class T> void R<T>::S<T>::f(int);
- This is illegal; there needs to be one set of template
+ This is invalid; there needs to be one set of template
parameters for each class. */
return tsk_insufficient_parms;
else if (n_template_parm_scopes == n_class_scopes)
@@ -824,17 +1041,13 @@ void
pushlevel (tag_transparent)
int tag_transparent;
{
- struct binding_level *newlevel;
+ struct cp_binding_level *newlevel;
if (cfun && !doing_semantic_analysis_p ())
return;
/* Reuse or create a struct for this binding level. */
-#if defined(DEBUG_CP_BINDING_LEVELS)
- if (0)
-#else /* !defined(DEBUG_CP_BINDING_LEVELS) */
- if (free_binding_level)
-#endif /* !defined(DEBUG_CP_BINDING_LEVELS) */
+ if (!ENABLE_SCOPE_CHECKING && free_binding_level)
{
newlevel = free_binding_level;
free_binding_level = free_binding_level->level_chain;
@@ -919,14 +1132,12 @@ note_level_for_catch ()
}
/* For a binding between a name and an entity at a block scope,
- this is the `struct binding_level' for the block. */
-#define BINDING_LEVEL(NODE) \
- (((struct tree_binding*)(NODE))->scope.level)
+ this is the `struct cp_binding_level' for the block. */
+#define BINDING_LEVEL(NODE) ((NODE)->scope.level)
-/* A free list of CPLUS_BINDING nodes, connected by their
- TREE_CHAINs. */
+/* A free list of "cxx_binding"s, connected by their PREVIOUS. */
-static tree free_bindings;
+static GTY((deletable (""))) cxx_binding *free_bindings;
/* Make DECL the innermost binding for ID. The LEVEL is the binding
level at which this declaration is being bound. */
@@ -935,17 +1146,17 @@ static void
push_binding (id, decl, level)
tree id;
tree decl;
- struct binding_level* level;
+ struct cp_binding_level* level;
{
- tree binding;
+ cxx_binding *binding;
if (free_bindings)
{
binding = free_bindings;
- free_bindings = TREE_CHAIN (binding);
+ free_bindings = binding->previous;
}
else
- binding = make_node (CPLUS_BINDING);
+ binding = cxx_binding_make ();
/* Now, fill in the binding information. */
BINDING_VALUE (binding) = decl;
@@ -956,7 +1167,7 @@ push_binding (id, decl, level)
BINDING_HAS_LEVEL_P (binding) = 1;
/* And put it on the front of the list of bindings for ID. */
- TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
+ binding->previous = IDENTIFIER_BINDING (id);
IDENTIFIER_BINDING (id) = binding;
}
@@ -965,15 +1176,16 @@ push_binding (id, decl, level)
stat' hack whereby a non-typedef class-name or enum-name can be
bound at the same level as some other kind of entity. It's the
responsibility of the caller to check that inserting this name is
- legal here. Returns nonzero if the new binding was successful. */
+ valid here. Returns nonzero if the new binding was successful. */
static int
add_binding (id, decl)
tree id;
tree decl;
{
- tree binding = IDENTIFIER_BINDING (id);
+ cxx_binding *binding = IDENTIFIER_BINDING (id);
int ok = 1;
+ timevar_push (TV_NAME_LOOKUP);
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
/* The new name is the type name. */
BINDING_TYPE (binding) = decl;
@@ -1013,11 +1225,18 @@ add_binding (id, decl)
type to which it already refers. */
ok = 0;
/* There can be two block-scope declarations of the same variable,
- so long as they are `extern' declarations. */
+ so long as they are `extern' declarations. However, there cannot
+ be two declarations of the same static data member:
+
+ [class.mem]
+
+ A member shall not be declared twice in the
+ member-specification. */
else if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (BINDING_VALUE (binding)) == VAR_DECL
&& DECL_EXTERNAL (decl)
- && DECL_EXTERNAL (BINDING_VALUE (binding)))
+ && DECL_EXTERNAL (BINDING_VALUE (binding))
+ && !DECL_CLASS_SCOPE_P (decl))
{
duplicate_decls (decl, BINDING_VALUE (binding));
ok = 0;
@@ -1030,7 +1249,7 @@ add_binding (id, decl)
ok = 0;
}
- return ok;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ok);
}
/* Add DECL to the list of things declared in B. */
@@ -1038,12 +1257,34 @@ add_binding (id, decl)
static void
add_decl_to_level (decl, b)
tree decl;
- struct binding_level *b;
+ struct cp_binding_level *b;
{
- /* We build up the list in reverse order, and reverse it later if
- necessary. */
- TREE_CHAIN (decl) = b->names;
- b->names = decl;
+ if (TREE_CODE (decl) == NAMESPACE_DECL
+ && !DECL_NAMESPACE_ALIAS (decl))
+ {
+ TREE_CHAIN (decl) = b->namespaces;
+ b->namespaces = decl;
+ }
+ else if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
+ {
+ TREE_CHAIN (decl) = b->vtables;
+ b->vtables = decl;
+ }
+ else
+ {
+ /* We build up the list in reverse order, and reverse it later if
+ necessary. */
+ TREE_CHAIN (decl) = b->names;
+ b->names = decl;
+ b->names_size++;
+
+ /* If appropriate, add decl to separate list of statics */
+ if (b->namespace_p)
+ if ((TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && (!TREE_PUBLIC (decl) || DECL_DECLARED_INLINE_P (decl))))
+ VARRAY_PUSH_TREE (b->static_decls, decl);
+ }
}
/* Bind DECL to ID in the current_binding_level, assumed to be a local
@@ -1057,7 +1298,7 @@ push_local_binding (id, decl, flags)
tree decl;
int flags;
{
- struct binding_level *b;
+ struct cp_binding_level *b;
/* Skip over any local classes. This makes sense if we call
push_local_binding with a friend decl of a local class. */
@@ -1098,11 +1339,12 @@ push_class_binding (id, decl)
tree decl;
{
int result = 1;
- tree binding = IDENTIFIER_BINDING (id);
+ cxx_binding *binding = IDENTIFIER_BINDING (id);
tree context;
+ timevar_push (TV_NAME_LOOKUP);
/* Note that we declared this value so that we can issue an error if
- this an illegal redeclaration of a name already used for some
+ this is an invalid redeclaration of a name already used for some
other purpose. */
note_name_declared_in_class (id, decl);
@@ -1152,7 +1394,7 @@ push_class_binding (id, decl)
in this class. */
INHERITED_VALUE_BINDING_P (binding) = 1;
- return result;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result);
}
/* Remove the binding for DECL which should be the innermost binding
@@ -1163,7 +1405,7 @@ pop_binding (id, decl)
tree id;
tree decl;
{
- tree binding;
+ cxx_binding *binding;
if (id == NULL_TREE)
/* It's easiest to write the loops that call this function without
@@ -1175,7 +1417,7 @@ pop_binding (id, decl)
binding = IDENTIFIER_BINDING (id);
/* The name should be bound. */
- my_friendly_assert (binding != NULL_TREE, 0);
+ my_friendly_assert (binding != NULL, 0);
/* The DECL will be either the ordinary binding or the type
binding for this identifier. Remove that binding. */
@@ -1190,10 +1432,10 @@ pop_binding (id, decl)
{
/* We're completely done with the innermost binding for this
identifier. Unhook it from the list of bindings. */
- IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
+ IDENTIFIER_BINDING (id) = binding->previous;
/* Add it to the free list. */
- TREE_CHAIN (binding) = free_bindings;
+ binding->previous = free_bindings;
free_bindings = binding;
/* Clear the BINDING_LEVEL so the garbage collector doesn't walk
@@ -1276,21 +1518,21 @@ poplevel (keep, reverse, functionbody)
tree decls;
int tmp = functionbody;
int real_functionbody;
- tree tags;
tree subblocks;
tree block = NULL_TREE;
tree decl;
int leaving_for_scope;
+ timevar_push (TV_NAME_LOOKUP);
+
if (cfun && !doing_semantic_analysis_p ())
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
my_friendly_assert (current_binding_level->parm_flag != 2,
19990916);
real_functionbody = (current_binding_level->keep == 2
? ((functionbody = 0), tmp) : functionbody);
- tags = functionbody >= 0 ? current_binding_level->tags : 0;
subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
my_friendly_assert (!current_binding_level->class_shadowed,
@@ -1308,7 +1550,7 @@ poplevel (keep, reverse, functionbody)
under constraints of next binding contour. */
if (cfun && !functionbody)
{
- struct binding_level *level_chain;
+ struct cp_binding_level *level_chain;
level_chain = current_binding_level->level_chain;
if (level_chain)
{
@@ -1410,8 +1652,8 @@ poplevel (keep, reverse, functionbody)
if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
&& DECL_NAME (link))
{
- tree outer_binding
- = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (link)));
+ cxx_binding *outer_binding
+ = IDENTIFIER_BINDING (DECL_NAME (link))->previous;
tree ns_binding;
if (!outer_binding)
@@ -1466,7 +1708,7 @@ poplevel (keep, reverse, functionbody)
current_binding_level->level_chain->
dead_vars_from_for);
- /* Although we don't pop the CPLUS_BINDING, we do clear
+ /* Although we don't pop the cxx_binding, we do clear
its BINDING_LEVEL since the level is going away now. */
BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link)))
= 0;
@@ -1574,7 +1816,7 @@ poplevel (keep, reverse, functionbody)
block = poplevel (keep, reverse, functionbody);
}
- return block;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
}
/* Delete the node BLOCK from the current binding level.
@@ -1631,14 +1873,10 @@ set_block (block)
void
pushlevel_class ()
{
- register struct binding_level *newlevel;
+ register struct cp_binding_level *newlevel;
/* Reuse or create a struct for this binding level. */
-#if defined(DEBUG_CP_BINDING_LEVELS)
- if (0)
-#else /* !defined(DEBUG_CP_BINDING_LEVELS) */
- if (free_binding_level)
-#endif /* !defined(DEBUG_CP_BINDING_LEVELS) */
+ if (!ENABLE_SCOPE_CHECKING && free_binding_level)
{
newlevel = free_binding_level;
free_binding_level = free_binding_level->level_chain;
@@ -1646,9 +1884,8 @@ pushlevel_class ()
else
newlevel = make_binding_level ();
-#if defined(DEBUG_CP_BINDING_LEVELS)
- is_class_level = 1;
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
+ if (ENABLE_SCOPE_CHECKING)
+ is_class_level = 1;
push_binding_level (newlevel, 0, 0);
@@ -1662,9 +1899,11 @@ pushlevel_class ()
void
poplevel_class ()
{
- register struct binding_level *level = class_binding_level;
+ register struct cp_binding_level *level = class_binding_level;
tree shadowed;
+ timevar_push (TV_NAME_LOOKUP);
+
my_friendly_assert (level != 0, 354);
/* If we're leaving a toplevel class, don't bother to do the setting
@@ -1674,7 +1913,7 @@ poplevel_class ()
next time we're entering a class scope, it is the same class. */
if (current_class_depth != 1)
{
- struct binding_level* b;
+ struct cp_binding_level* b;
/* Clear out our IDENTIFIER_CLASS_VALUEs. */
for (shadowed = level->class_shadowed;
@@ -1693,15 +1932,15 @@ poplevel_class ()
shadowed;
shadowed = TREE_CHAIN (shadowed))
{
- tree t;
+ cxx_binding *binding;
- t = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
- while (t && BINDING_LEVEL (t) != b)
- t = TREE_CHAIN (t);
+ binding = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
+ while (binding && BINDING_LEVEL (binding) != b)
+ binding = binding->previous;
- if (t)
+ if (binding)
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed))
- = BINDING_VALUE (t);
+ = BINDING_VALUE (binding);
}
}
else
@@ -1724,11 +1963,12 @@ poplevel_class ()
/* Now, pop out of the binding level which we created up in the
`pushlevel_class' routine. */
-#if defined(DEBUG_CP_BINDING_LEVELS)
- is_class_level = 1;
-#endif /* defined(DEBUG_CP_BINDING_LEVELS) */
+ if (ENABLE_SCOPE_CHECKING)
+ is_class_level = 1;
pop_binding_level ();
+
+ timevar_pop (TV_NAME_LOOKUP);
}
/* We are entering the scope of a class. Clear IDENTIFIER_CLASS_VALUE
@@ -1748,7 +1988,7 @@ clear_identifier_class_values ()
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
}
-/* Returns non-zero if T is a virtual function table. */
+/* Returns nonzero if T is a virtual function table. */
int
vtable_decl_p (t, data)
@@ -1758,7 +1998,7 @@ vtable_decl_p (t, data)
return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));
}
-/* Returns non-zero if T is a TYPE_DECL for a type with virtual
+/* Returns nonzero if T is a TYPE_DECL for a type with virtual
functions. */
int
@@ -1780,6 +2020,50 @@ cp_namespace_decls (ns)
return NAMESPACE_LEVEL (ns)->names;
}
+struct walk_globals_data {
+ walk_globals_pred p;
+ walk_globals_fn f;
+ void *data;
+};
+
+/* Walk the vtable declarations in NAMESPACE. Whenever one is found
+ for which P returns nonzero, call F with its address. If any call
+ to F returns a nonzero value, return a nonzero value. */
+
+static int
+walk_vtables_r (namespace, data)
+ tree namespace;
+ void *data;
+{
+ struct walk_globals_data* wgd = (struct walk_globals_data *) data;
+ walk_globals_fn f = wgd->f;
+ void *d = wgd->data;
+ tree decl = NAMESPACE_LEVEL (namespace)->vtables;
+ int result = 0;
+
+ for (; decl ; decl = TREE_CHAIN (decl))
+ result |= (*f) (&decl, d);
+
+ return result;
+}
+
+/* Walk the vtable declarations. Whenever one is found for which P
+ returns nonzero, call F with its address. If any call to F
+ returns a nonzero value, return a nonzero value. */
+int
+walk_vtables (p, f, data)
+ walk_globals_pred p;
+ walk_globals_fn f;
+ void *data;
+{
+ struct walk_globals_data wgd;
+ wgd.p = p;
+ wgd.f = f;
+ wgd.data = data;
+
+ return walk_namespaces (walk_vtables_r, &wgd);
+}
+
/* Walk all the namespaces contained NAMESPACE, including NAMESPACE
itself, calling F for each. The DATA is passed to F as well. */
@@ -1789,22 +2073,13 @@ walk_namespaces_r (namespace, f, data)
walk_namespaces_fn f;
void *data;
{
- tree current;
int result = 0;
+ tree current = NAMESPACE_LEVEL (namespace)->namespaces;
result |= (*f) (namespace, data);
- for (current = cp_namespace_decls (namespace);
- current;
- current = TREE_CHAIN (current))
- {
- if (TREE_CODE (current) != NAMESPACE_DECL
- || DECL_NAMESPACE_ALIAS (current))
- continue;
-
- /* We found a namespace. */
- result |= walk_namespaces_r (current, f, data);
- }
+ for (; current; current = TREE_CHAIN (current))
+ result |= walk_namespaces_r (current, f, data);
return result;
}
@@ -1820,15 +2095,9 @@ walk_namespaces (f, data)
return walk_namespaces_r (global_namespace, f, data);
}
-struct walk_globals_data {
- walk_globals_pred p;
- walk_globals_fn f;
- void *data;
-};
-
/* Walk the global declarations in NAMESPACE. Whenever one is found
- for which P returns non-zero, call F with its address. If any call
- to F returns a non-zero value, return a non-zero value. */
+ for which P returns nonzero, call F with its address. If any call
+ to F returns a nonzero value, return a nonzero value. */
static int
walk_globals_r (namespace, data)
@@ -1861,8 +2130,8 @@ walk_globals_r (namespace, data)
}
/* Walk the global declarations. Whenever one is found for which P
- returns non-zero, call F with its address. If any call to F
- returns a non-zero value, return a non-zero value. */
+ returns nonzero, call F with its address. If any call to F
+ returns a nonzero value, return a nonzero value. */
int
walk_globals (p, f, data)
@@ -1887,106 +2156,68 @@ wrapup_globals_for_namespace (namespace, data)
tree namespace;
void *data;
{
- tree globals = cp_namespace_decls (namespace);
- int len = list_length (globals);
- tree *vec = (tree *) alloca (sizeof (tree) * len);
- int i;
- int result;
- tree decl;
+ struct cp_binding_level *level = NAMESPACE_LEVEL (namespace);
+ varray_type statics = level->static_decls;
+ tree *vec = &VARRAY_TREE (statics, 0);
+ int len = VARRAY_ACTIVE_SIZE (statics);
int last_time = (data != 0);
- if (last_time && namespace == global_namespace)
- /* Let compile_file handle the global namespace. */
- return 0;
-
- /* Process the decls in reverse order--earliest first.
- Put them into VEC from back to front, then take out from front. */
- for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
- vec[len - i - 1] = decl;
-
if (last_time)
{
check_global_declarations (vec, len);
return 0;
}
- /* Temporarily mark vtables as external. That prevents
- wrapup_global_declarations from writing them out; we must process
- them ourselves in finish_vtable_vardecl. */
- for (i = 0; i < len; ++i)
- if (vtable_decl_p (vec[i], /*data=*/0) && !DECL_EXTERNAL (vec[i]))
- {
- DECL_NOT_REALLY_EXTERN (vec[i]) = 1;
- DECL_EXTERNAL (vec[i]) = 1;
- }
-
/* Write out any globals that need to be output. */
- result = wrapup_global_declarations (vec, len);
-
- /* Undo the hack to DECL_EXTERNAL above. */
- for (i = 0; i < len; ++i)
- if (vtable_decl_p (vec[i], /*data=*/0)
- && DECL_NOT_REALLY_EXTERN (vec[i]))
- {
- DECL_NOT_REALLY_EXTERN (vec[i]) = 0;
- DECL_EXTERNAL (vec[i]) = 0;
- }
-
- return result;
+ return wrapup_global_declarations (vec, len);
}
-/* Mark ARG (which is really a struct binding_level **) for GC. */
+/* For debugging. */
+static int no_print_functions = 0;
+static int no_print_builtins = 0;
+/* Called from print_binding_level through binding_table_foreach to
+ print the content of binding ENTRY. DATA is a pointer to line offset
+ marker. */
static void
-mark_binding_level (arg)
- void *arg;
+bt_print_entry (binding_entry entry, void *data)
{
- struct binding_level *lvl = *(struct binding_level **)arg;
+ int *p = (int *) data;
+ int len;
- for (; lvl; lvl = lvl->level_chain)
- {
- ggc_mark_tree (lvl->names);
- ggc_mark_tree (lvl->tags);
- ggc_mark_tree (lvl->usings);
- ggc_mark_tree (lvl->using_directives);
- ggc_mark_tree (lvl->class_shadowed);
- ggc_mark_tree (lvl->type_shadowed);
- ggc_mark_tree (lvl->shadowed_labels);
- ggc_mark_tree (lvl->blocks);
- ggc_mark_tree (lvl->this_class);
- ggc_mark_tree (lvl->dead_vars_from_for);
- }
-}
+ if (entry->name == NULL)
+ len = 3;
+ else if (entry->name == TYPE_IDENTIFIER (entry->type))
+ len = 2;
+ else
+ len = 4;
-static void
-mark_named_label_lists (labs, uses)
- void *labs;
- void *uses;
-{
- struct named_label_list *l = *(struct named_label_list **)labs;
- struct named_label_use_list *u = *(struct named_label_use_list **)uses;
+ *p += len;
- for (; l; l = l->next)
+ if (*p > 5)
{
- ggc_mark (l);
- mark_binding_level (&l->binding_level);
- ggc_mark_tree (l->old_value);
- ggc_mark_tree (l->label_decl);
- ggc_mark_tree (l->bad_decls);
+ fprintf (stderr, "\n\t");
+ *p = len;
+ }
+ if (entry->name == NULL)
+ {
+ print_node_brief (stderr, "<unnamed-typedef", entry->type, 0);
+ fprintf (stderr, ">");
+ }
+ else if (entry->name == TYPE_IDENTIFIER (entry->type))
+ print_node_brief (stderr, "", entry->type, 0);
+ else
+ {
+ print_node_brief (stderr, "<typedef", entry->name, 0);
+ print_node_brief (stderr, "", entry->type, 0);
+ fprintf (stderr, ">");
}
-
- for (; u; u = u->next)
- ggc_mark (u);
}
-
-/* For debugging. */
-static int no_print_functions = 0;
-static int no_print_builtins = 0;
void
print_binding_level (lvl)
- struct binding_level *lvl;
+ struct cp_binding_level *lvl;
{
tree t;
int i = 0, len;
@@ -2030,38 +2261,11 @@ print_binding_level (lvl)
if (i)
fprintf (stderr, "\n");
}
- if (lvl->tags)
+ if (lvl->type_decls)
{
fprintf (stderr, " tags:\t");
i = 0;
- for (t = lvl->tags; t; t = TREE_CHAIN (t))
- {
- if (TREE_PURPOSE (t) == NULL_TREE)
- len = 3;
- else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t)))
- len = 2;
- else
- len = 4;
- i += len;
- if (i > 5)
- {
- fprintf (stderr, "\n\t");
- i = len;
- }
- if (TREE_PURPOSE (t) == NULL_TREE)
- {
- print_node_brief (stderr, "<unnamed-typedef", TREE_VALUE (t), 0);
- fprintf (stderr, ">");
- }
- else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t)))
- print_node_brief (stderr, "", TREE_VALUE (t), 0);
- else
- {
- print_node_brief (stderr, "<typedef", TREE_PURPOSE (t), 0);
- print_node_brief (stderr, "", TREE_VALUE (t), 0);
- fprintf (stderr, ">");
- }
- }
+ binding_table_foreach (lvl->type_decls, bt_print_entry, &i);
if (i)
fprintf (stderr, "\n");
}
@@ -2087,10 +2291,10 @@ print_binding_level (lvl)
void
print_other_binding_stack (stack)
- struct binding_level *stack;
+ struct cp_binding_level *stack;
{
- struct binding_level *level;
- for (level = stack; level != global_binding_level; level = level->level_chain)
+ struct cp_binding_level *level;
+ for (level = stack; !global_scope_p (level); level = level->level_chain)
{
fprintf (stderr, "binding level ");
fprintf (stderr, HOST_PTR_PRINTF, level);
@@ -2102,13 +2306,14 @@ print_other_binding_stack (stack)
void
print_binding_stack ()
{
- struct binding_level *b;
+ struct cp_binding_level *b;
fprintf (stderr, "current_binding_level=");
fprintf (stderr, HOST_PTR_PRINTF, current_binding_level);
fprintf (stderr, "\nclass_binding_level=");
fprintf (stderr, HOST_PTR_PRINTF, class_binding_level);
- fprintf (stderr, "\nglobal_binding_level=");
- fprintf (stderr, HOST_PTR_PRINTF, global_binding_level);
+ fprintf (stderr, "\nNAMESPACE_LEVEL (global_namespace)=");
+ fprintf (stderr, HOST_PTR_PRINTF,
+ (void *) NAMESPACE_LEVEL (global_namespace));
fprintf (stderr, "\n");
if (class_binding_level)
{
@@ -2124,104 +2329,95 @@ print_binding_stack ()
b = current_binding_level;
print_other_binding_stack (b);
fprintf (stderr, "global:\n");
- print_binding_level (global_binding_level);
+ print_binding_level (NAMESPACE_LEVEL (global_namespace));
}
-/* Namespace binding access routines: The namespace_bindings field of
- the identifier is polymorphic, with three possible values:
- NULL_TREE, a list of CPLUS_BINDINGS, or any other tree_node
- indicating the BINDING_VALUE of global_namespace. */
+/* Namespace binding access routines. */
/* Check whether the a binding for the name to scope is known.
- Assumes that the bindings of the name are already a list
- of bindings. Returns the binding found, or NULL_TREE. */
+ Returns the binding found, or NULL. */
-static tree
-find_binding (name, scope)
- tree name;
- tree scope;
+static inline cxx_binding *
+find_binding (tree name, tree scope, cxx_binding *front)
{
- tree iter, prev = NULL_TREE;
+ cxx_binding *iter;
+ cxx_binding *prev = NULL;
- scope = ORIGINAL_NAMESPACE (scope);
+ timevar_push (TV_NAME_LOOKUP);
- for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name); iter;
- iter = TREE_CHAIN (iter))
+ for (iter = front; iter; iter = iter->previous)
{
- my_friendly_assert (TREE_CODE (iter) == CPLUS_BINDING, 374);
if (BINDING_SCOPE (iter) == scope)
{
/* Move binding found to the front of the list, so
- subsequent lookups will find it faster. */
+ subsequent lookups will find it faster. */
if (prev)
{
- TREE_CHAIN (prev) = TREE_CHAIN (iter);
- TREE_CHAIN (iter) = IDENTIFIER_NAMESPACE_BINDINGS (name);
+ prev->previous = iter->previous;
+ iter->previous = front;
IDENTIFIER_NAMESPACE_BINDINGS (name) = iter;
}
- return iter;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, iter);
}
prev = iter;
}
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL);
+}
+
+/* Return the binding for NAME in SCOPE, if any. Otherwise, return NULL. */
+cxx_binding *
+cxx_scope_find_binding_for_name (tree scope, tree name)
+{
+ cxx_binding *b = IDENTIFIER_NAMESPACE_BINDINGS (name);
+ if (b)
+ {
+ scope = ORIGINAL_NAMESPACE (scope);
+ /* Fold-in case where NAME is used only once. */
+ if (scope == BINDING_SCOPE (b) && b->previous == NULL)
+ return b;
+ return find_binding (name, scope, b);
+ }
+ return b;
}
-/* Always returns a binding for name in scope. If the
- namespace_bindings is not a list, convert it to one first.
- If no binding is found, make a new one. */
-tree
-binding_for_name (name, scope)
- tree name;
- tree scope;
+/* Always returns a binding for name in scope.
+ If no binding is found, make a new one. */
+
+cxx_binding *
+binding_for_name (tree name, tree scope)
{
- tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- tree result;
+ cxx_binding *result;
scope = ORIGINAL_NAMESPACE (scope);
-
- if (b && TREE_CODE (b) != CPLUS_BINDING)
- {
- /* Get rid of optimization for global scope. */
- IDENTIFIER_NAMESPACE_BINDINGS (name) = NULL_TREE;
- BINDING_VALUE (binding_for_name (name, global_namespace)) = b;
- b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- }
- if (b && (result = find_binding (name, scope)))
+ result = cxx_scope_find_binding_for_name (scope, name);
+ if (result)
return result;
- /* Not found, make a new one. */
- result = make_node (CPLUS_BINDING);
- TREE_CHAIN (result) = b;
- IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
- BINDING_SCOPE (result) = scope;
+ /* Not found, make a new one. */
+ result = cxx_binding_make ();
+ result->previous = IDENTIFIER_NAMESPACE_BINDINGS (name);
BINDING_TYPE (result) = NULL_TREE;
BINDING_VALUE (result) = NULL_TREE;
+ BINDING_SCOPE (result) = scope;
+ result->is_local = false;
+ result->value_is_inherited = false;
+ result->has_level = false;
+ IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
return result;
}
-/* Return the binding value for name in scope, considering that
- namespace_binding may or may not be a list of CPLUS_BINDINGS. */
+/* Return the binding value for name in scope. */
tree
-namespace_binding (name, scope)
- tree name;
- tree scope;
+namespace_binding (tree name, tree scope)
{
- tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- if (b == NULL_TREE)
- return NULL_TREE;
- if (scope == NULL_TREE)
- scope = global_namespace;
- if (TREE_CODE (b) != CPLUS_BINDING)
- return (scope == global_namespace) ? b : NULL_TREE;
- name = find_binding (name,scope);
- if (name == NULL_TREE)
- return name;
- return BINDING_VALUE (name);
+ cxx_binding *b =
+ cxx_scope_find_binding_for_name (scope ? scope : global_namespace, name);
+
+ return b ? b->value : NULL_TREE;
}
-/* Set the binding value for name in scope. If modifying the binding
- of global_namespace is attempted, try to optimize it. */
+/* Set the binding value for name in scope. */
void
set_namespace_binding (name, scope, val)
@@ -2229,22 +2425,15 @@ set_namespace_binding (name, scope, val)
tree scope;
tree val;
{
- tree b;
+ cxx_binding *b;
+ timevar_push (TV_NAME_LOOKUP);
if (scope == NULL_TREE)
scope = global_namespace;
- if (scope == global_namespace)
- {
- b = IDENTIFIER_NAMESPACE_BINDINGS (name);
- if (b == NULL_TREE || TREE_CODE (b) != CPLUS_BINDING)
- {
- IDENTIFIER_NAMESPACE_BINDINGS (name) = val;
- return;
- }
- }
b = binding_for_name (name, scope);
BINDING_VALUE (b) = val;
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we
@@ -2258,9 +2447,12 @@ push_namespace (name)
int need_new = 1;
int implicit_use = 0;
int global = 0;
+
+ timevar_push (TV_NAME_LOOKUP);
+
if (!global_namespace)
{
- /* This must be ::. */
+ /* This must be ::. */
my_friendly_assert (name == get_identifier ("::"), 377);
global = 1;
}
@@ -2279,7 +2471,7 @@ push_namespace (name)
}
else
{
- /* Check whether this is an extended namespace definition. */
+ /* Check whether this is an extended namespace definition. */
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d != NULL_TREE && TREE_CODE (d) == NAMESPACE_DECL)
{
@@ -2295,7 +2487,7 @@ push_namespace (name)
if (need_new)
{
- /* Make a new namespace, binding the name to it. */
+ /* Make a new namespace, binding the name to it. */
d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
/* The global namespace is not pushed, and the global binding
level is set elsewhere. */
@@ -2306,6 +2498,13 @@ push_namespace (name)
pushlevel (0);
declare_namespace_level ();
NAMESPACE_LEVEL (d) = current_binding_level;
+ current_binding_level->type_decls =
+ binding_table_new (name == std_identifier
+ ? NAMESPACE_STD_HT_SIZE
+ : NAMESPACE_ORDINARY_HT_SIZE);
+ VARRAY_TREE_INIT (current_binding_level->static_decls,
+ name != std_identifier ? 10 : 200,
+ "Static declarations");
}
}
else
@@ -2313,8 +2512,10 @@ push_namespace (name)
if (implicit_use)
do_using_directive (d);
- /* Enter the name space. */
+ /* Enter the name space. */
current_namespace = d;
+
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Pop from the scope of the current namespace. */
@@ -2351,6 +2552,7 @@ void
pop_nested_namespace (ns)
tree ns;
{
+ timevar_push (TV_NAME_LOOKUP);
while (ns != global_namespace)
{
pop_namespace ();
@@ -2358,9 +2560,26 @@ pop_nested_namespace (ns)
}
pop_from_top_level ();
+ timevar_pop (TV_NAME_LOOKUP);
}
+/* Allocate storage for saving a C++ binding. */
+#define cxx_saved_binding_make() \
+ (ggc_alloc (sizeof (cxx_saved_binding)))
+
+struct cxx_saved_binding GTY(())
+{
+ /* Link that chains saved C++ bindings for a given name into a stack. */
+ cxx_saved_binding *previous;
+ /* The name of the current binding. */
+ tree identifier;
+ /* The binding we're saving. */
+ cxx_binding *binding;
+ tree class_value;
+ tree real_type_value;
+};
+
/* Subroutines for reverting temporarily to top-level for instantiation
of templates and such. We actually need to clear out the class- and
local-value slots of all identifiers, so that only the global values
@@ -2368,48 +2587,18 @@ pop_nested_namespace (ns)
scope isn't enough, because more binding levels may be pushed. */
struct saved_scope *scope_chain;
-/* Mark ARG (which is really a struct saved_scope **) for GC. */
-
-static void
-mark_saved_scope (arg)
- void *arg;
-{
- struct saved_scope *t = *(struct saved_scope **)arg;
- while (t)
- {
- mark_binding_level (&t->class_bindings);
- ggc_mark_tree (t->old_bindings);
- ggc_mark_tree (t->old_namespace);
- ggc_mark_tree (t->decl_ns_list);
- ggc_mark_tree (t->class_name);
- ggc_mark_tree (t->class_type);
- ggc_mark_tree (t->access_specifier);
- ggc_mark_tree (t->function_decl);
- if (t->lang_base)
- ggc_mark_tree_varray (t->lang_base);
- ggc_mark_tree (t->lang_name);
- ggc_mark_tree (t->template_parms);
- ggc_mark_tree (t->x_previous_class_type);
- ggc_mark_tree (t->x_previous_class_values);
- ggc_mark_tree (t->x_saved_tree);
- ggc_mark_tree (t->lookups);
-
- mark_stmt_tree (&t->x_stmt_tree);
- mark_binding_level (&t->bindings);
- t = t->prev;
- }
-}
-
-static tree
-store_bindings (names, old_bindings)
- tree names, old_bindings;
+static cxx_saved_binding *
+store_bindings (tree names, cxx_saved_binding *old_bindings)
{
tree t;
- tree search_bindings = old_bindings;
+ cxx_saved_binding *search_bindings = old_bindings;
+ timevar_push (TV_NAME_LOOKUP);
for (t = names; t; t = TREE_CHAIN (t))
{
- tree binding, t1, id;
+ tree id;
+ cxx_saved_binding *saved;
+ cxx_saved_binding *t1;
if (TREE_CODE (t) == TREE_LIST)
id = TREE_PURPOSE (t);
@@ -2423,24 +2612,24 @@ store_bindings (names, old_bindings)
|| !(IDENTIFIER_BINDING (id) || IDENTIFIER_CLASS_VALUE (id)))
continue;
- for (t1 = search_bindings; t1; t1 = TREE_CHAIN (t1))
- if (TREE_VEC_ELT (t1, 0) == id)
+ for (t1 = search_bindings; t1; t1 = t1->previous)
+ if (t1->identifier == id)
goto skip_it;
my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
- binding = make_tree_vec (4);
- TREE_VEC_ELT (binding, 0) = id;
- TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id);
- TREE_VEC_ELT (binding, 2) = IDENTIFIER_BINDING (id);
- TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
- IDENTIFIER_BINDING (id) = NULL_TREE;
+ saved = cxx_saved_binding_make ();
+ saved->previous = old_bindings;
+ saved->identifier = id;
+ saved->binding = IDENTIFIER_BINDING (id);
+ saved->class_value = IDENTIFIER_CLASS_VALUE (id);;
+ saved->real_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
+ IDENTIFIER_BINDING (id) = NULL;
IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
- TREE_CHAIN (binding) = old_bindings;
- old_bindings = binding;
+ old_bindings = saved;
skip_it:
;
}
- return old_bindings;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old_bindings);
}
void
@@ -2448,11 +2637,13 @@ maybe_push_to_top_level (pseudo)
int pseudo;
{
struct saved_scope *s;
- struct binding_level *b;
- tree old_bindings;
+ struct cp_binding_level *b;
+ cxx_saved_binding *old_bindings;
int need_pop;
- s = (struct saved_scope *) xcalloc (1, sizeof (struct saved_scope));
+ timevar_push (TV_NAME_LOOKUP);
+
+ s = (struct saved_scope *) ggc_alloc_cleared (sizeof (struct saved_scope));
b = scope_chain ? current_binding_level : 0;
@@ -2465,11 +2656,11 @@ maybe_push_to_top_level (pseudo)
else
need_pop = 0;
- old_bindings = NULL_TREE;
+ old_bindings = NULL;
if (scope_chain && previous_class_type)
old_bindings = store_bindings (previous_class_values, old_bindings);
- /* Have to include global_binding_level, because class-level decls
+ /* Have to include the global scope, because class-scope decls
aren't listed anywhere useful. */
for (; b; b = b->level_chain)
{
@@ -2479,7 +2670,7 @@ maybe_push_to_top_level (pseudo)
inserted into namespace level, finish_file wouldn't find them
when doing pending instantiations. Therefore, don't stop at
namespace level, but continue until :: . */
- if (b == global_binding_level || (pseudo && b->template_parms_p))
+ if (global_scope_p (b) || (pseudo && b->template_parms_p))
break;
old_bindings = store_bindings (b->names, old_bindings);
@@ -2504,6 +2695,7 @@ maybe_push_to_top_level (pseudo)
VARRAY_TREE_INIT (current_lang_base, 10, "current_lang_base");
current_lang_name = lang_name_cplusplus;
current_namespace = global_namespace;
+ timevar_pop (TV_NAME_LOOKUP);
}
void
@@ -2516,22 +2708,24 @@ void
pop_from_top_level ()
{
struct saved_scope *s = scope_chain;
- tree t;
+ cxx_saved_binding *saved;
+
+ timevar_push (TV_NAME_LOOKUP);
/* Clear out class-level bindings cache. */
if (previous_class_type)
invalidate_class_lookup_cache ();
- VARRAY_FREE (current_lang_base);
+ current_lang_base = 0;
scope_chain = s->prev;
- for (t = s->old_bindings; t; t = TREE_CHAIN (t))
+ for (saved = s->old_bindings; saved; saved = saved->previous)
{
- tree id = TREE_VEC_ELT (t, 0);
+ tree id = saved->identifier;
- SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
- IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2);
- IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
+ IDENTIFIER_BINDING (id) = saved->binding;
+ IDENTIFIER_CLASS_VALUE (id) = saved->class_value;
+ SET_IDENTIFIER_TYPE_VALUE (id, saved->real_type_value);
}
/* If we were in the middle of compiling a function, restore our
@@ -2541,7 +2735,7 @@ pop_from_top_level ()
current_function_decl = s->function_decl;
last_function_parms = s->last_parms;
- free (s);
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Push a definition of struct, union or enum tag "name".
@@ -2561,21 +2755,21 @@ static void
set_identifier_type_value_with_scope (id, type, b)
tree id;
tree type;
- struct binding_level *b;
+ struct cp_binding_level *b;
{
if (!b->namespace_p)
{
/* Shadow the marker, not the real thing, so that the marker
- gets restored later. */
+ gets restored later. */
tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
b->type_shadowed
= tree_cons (id, old_type_value, b->type_shadowed);
}
else
{
- tree binding = binding_for_name (id, current_namespace);
+ cxx_binding *binding = binding_for_name (id, current_namespace);
BINDING_TYPE (binding) = type;
- /* Store marker instead of real type. */
+ /* Store marker instead of real type. */
type = global_type_node;
}
SET_IDENTIFIER_TYPE_VALUE (id, type);
@@ -2591,24 +2785,25 @@ set_identifier_type_value (id, type)
set_identifier_type_value_with_scope (id, type, current_binding_level);
}
-/* Return the type associated with id. */
+/* Return the type associated with id. */
tree
identifier_type_value (id)
tree id;
{
- /* There is no type with that name, anywhere. */
+ timevar_push (TV_NAME_LOOKUP);
+ /* There is no type with that name, anywhere. */
if (REAL_IDENTIFIER_TYPE_VALUE (id) == NULL_TREE)
- return NULL_TREE;
- /* This is not the type marker, but the real thing. */
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+ /* This is not the type marker, but the real thing. */
if (REAL_IDENTIFIER_TYPE_VALUE (id) != global_type_node)
- return REAL_IDENTIFIER_TYPE_VALUE (id);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, REAL_IDENTIFIER_TYPE_VALUE (id));
/* Have to search for it. It must be on the global level, now.
- Ask lookup_name not to return non-types. */
+ Ask lookup_name not to return non-types. */
id = lookup_name_real (id, 2, 1, 0);
if (id)
- return TREE_TYPE (id);
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_TYPE (id));
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* Pop off extraneous binding levels left over due to syntax errors.
@@ -2618,9 +2813,8 @@ identifier_type_value (id)
void
pop_everything ()
{
-#ifdef DEBUG_CP_BINDING_LEVELS
- fprintf (stderr, "XXX entering pop_everything ()\n");
-#endif
+ if (ENABLE_SCOPE_CHECKING)
+ verbatim ("XXX entering pop_everything ()\n");
while (!toplevel_bindings_p ())
{
if (current_binding_level->parm_flag == 2)
@@ -2628,14 +2822,13 @@ pop_everything ()
else
poplevel (0, 0, 0);
}
-#ifdef DEBUG_CP_BINDING_LEVELS
- fprintf (stderr, "XXX leaving pop_everything ()\n");
-#endif
+ if (ENABLE_SCOPE_CHECKING)
+ verbatim ("XXX leaving pop_everything ()\n");
}
/* The type TYPE is being declared. If it is a class template, or a
specialization of a class template, do any processing required and
- perform error-checking. If IS_FRIEND is non-zero, this TYPE is
+ perform error-checking. If IS_FRIEND is nonzero, this TYPE is
being declared a friend. B is the binding level at which this TYPE
should be bound.
@@ -2646,7 +2839,7 @@ static tree
maybe_process_template_type_declaration (type, globalize, b)
tree type;
int globalize;
- struct binding_level* b;
+ struct cp_binding_level* b;
{
tree decl = TYPE_NAME (type);
@@ -2688,10 +2881,17 @@ maybe_process_template_type_declaration (type, globalize, b)
/* Put this tag on the list of tags for the class, since
that won't happen below because B is not the class
binding level, but is instead the pseudo-global level. */
- b->level_chain->tags =
- tree_cons (name, type, b->level_chain->tags);
+ if (b->level_chain->type_decls == NULL)
+ b->level_chain->type_decls =
+ binding_table_new (SCOPE_DEFAULT_HT_SIZE);
+ binding_table_insert (b->level_chain->type_decls, name, type);
if (!COMPLETE_TYPE_P (current_class_type))
- CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
+ {
+ maybe_add_class_template_decl_list (current_class_type,
+ type, /*friend_p=*/0);
+ CLASSTYPE_NESTED_UDTS (current_class_type) =
+ b->level_chain->type_decls;
+ }
}
}
}
@@ -2731,6 +2931,8 @@ push_local_name (decl)
size_t i, nelts;
tree t, name;
+ timevar_push (TV_NAME_LOOKUP);
+
if (!local_names)
VARRAY_TREE_INIT (local_names, 8, "local_names");
@@ -2744,17 +2946,19 @@ push_local_name (decl)
{
if (!DECL_LANG_SPECIFIC (decl))
retrofit_lang_decl (decl);
+ DECL_LANG_SPECIFIC (decl)->decl_flags.u2sel = 1;
if (DECL_LANG_SPECIFIC (t))
DECL_DISCRIMINATOR (decl) = DECL_DISCRIMINATOR (t) + 1;
else
DECL_DISCRIMINATOR (decl) = 1;
VARRAY_TREE (local_names, i) = decl;
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
}
}
VARRAY_PUSH_TREE (local_names, decl);
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Push a tag name NAME for struct/class/union/enum type TYPE.
@@ -2767,7 +2971,9 @@ pushtag (name, type, globalize)
tree name, type;
int globalize;
{
- register struct binding_level *b;
+ register struct cp_binding_level *b;
+
+ timevar_push (TV_NAME_LOOKUP);
b = current_binding_level;
while (b->tag_transparent
@@ -2776,11 +2982,13 @@ pushtag (name, type, globalize)
/* We may be defining a new type in the initializer
of a static member variable. We allow this when
not pedantic, and it is particularly useful for
- type punning via an anonymous union. */
+ type punning via an anonymous union. */
|| COMPLETE_TYPE_P (b->this_class))))
b = b->level_chain;
- b->tags = tree_cons (name, type, b->tags);
+ if (b->type_decls == NULL)
+ b->type_decls = binding_table_new (SCOPE_DEFAULT_HT_SIZE);
+ binding_table_insert (b->type_decls, name, type);
if (name)
{
@@ -2854,7 +3062,11 @@ pushtag (name, type, globalize)
if (b->parm_flag == 2)
{
if (!COMPLETE_TYPE_P (current_class_type))
- CLASSTYPE_TAGS (current_class_type) = b->tags;
+ {
+ maybe_add_class_template_decl_list (current_class_type,
+ type, /*friend_p=*/0);
+ CLASSTYPE_NESTED_UDTS (current_class_type) = b->type_decls;
+ }
}
}
@@ -2874,6 +3086,8 @@ pushtag (name, type, globalize)
tree d = build_decl (TYPE_DECL, NULL_TREE, type);
TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b);
}
+
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Counter used to create anonymous type names. */
@@ -2898,8 +3112,7 @@ make_anon_name ()
void
clear_anon_tags ()
{
- register struct binding_level *b;
- register tree tags;
+ register struct cp_binding_level *b;
static int last_cnt = 0;
/* Fast out if no new anon names were declared. */
@@ -2909,17 +3122,8 @@ clear_anon_tags ()
b = current_binding_level;
while (b->tag_transparent)
b = b->level_chain;
- tags = b->tags;
- while (tags)
- {
- /* A NULL purpose means we have already processed all tags
- from here to the end of the list. */
- if (TREE_PURPOSE (tags) == NULL_TREE)
- break;
- if (ANON_AGGRNAME_P (TREE_PURPOSE (tags)))
- TREE_PURPOSE (tags) = NULL_TREE;
- tags = TREE_CHAIN (tags);
- }
+ if (b->type_decls != NULL)
+ binding_table_remove_anonymous_types (b->type_decls);
last_cnt = anon_cnt;
}
@@ -3135,7 +3339,7 @@ duplicate_decls (newdecl, olddecl)
}
}
- /* Check for redeclaration and other discrepancies. */
+ /* Check for redeclaration and other discrepancies. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl))
{
@@ -3200,6 +3404,10 @@ duplicate_decls (newdecl, olddecl)
/* Replace the old RTL to avoid problems with inlining. */
SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
}
+ /* Even if the types match, prefer the new declarations type
+ for anitipated built-ins, for exception lists, etc... */
+ else if (DECL_ANTICIPATED (olddecl))
+ TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl))
{
@@ -3275,7 +3483,11 @@ duplicate_decls (newdecl, olddecl)
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))))
&& comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
- DECL_TEMPLATE_PARMS (olddecl)))
+ DECL_TEMPLATE_PARMS (olddecl))
+ /* Template functions can be disambiguated by
+ return type. */
+ && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
+ TREE_TYPE (TREE_TYPE (olddecl))))
{
error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
@@ -3323,7 +3535,7 @@ duplicate_decls (newdecl, olddecl)
specialization, and the other is an instantiation of the same
template, that we do not exit at this point. That situation
can occur if we instantiate a template class, and then
- specialize one of its methods. This situation is legal, but
+ specialize one of its methods. This situation is valid, but
the declarations must be merged in the usual way. */
return 0;
else if (TREE_CODE (newdecl) == FUNCTION_DECL
@@ -3337,7 +3549,7 @@ duplicate_decls (newdecl, olddecl)
else if (TREE_CODE (newdecl) == NAMESPACE_DECL
&& DECL_NAMESPACE_ALIAS (newdecl)
&& DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))
- /* Redeclaration of namespace alias, ignore it. */
+ /* Redeclaration of namespace alias, ignore it. */
return 1;
else
{
@@ -3447,12 +3659,8 @@ duplicate_decls (newdecl, olddecl)
definition. */
if (DECL_VINDEX (olddecl))
DECL_VINDEX (newdecl) = DECL_VINDEX (olddecl);
- if (DECL_VIRTUAL_CONTEXT (olddecl))
- DECL_VIRTUAL_CONTEXT (newdecl) = DECL_VIRTUAL_CONTEXT (olddecl);
if (DECL_CONTEXT (olddecl))
DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
- if (DECL_PENDING_INLINE_INFO (newdecl) == 0)
- DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl);
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
DECL_PURE_VIRTUAL_P (newdecl) |= DECL_PURE_VIRTUAL_P (olddecl);
@@ -3469,9 +3677,9 @@ duplicate_decls (newdecl, olddecl)
definition. */
if (warn_redundant_decls && ! DECL_ARTIFICIAL (olddecl)
&& !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE)
- /* Don't warn about extern decl followed by definition. */
+ /* Don't warn about extern decl followed by definition. */
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
- /* Don't warn about friends, let add_friend take care of it. */
+ /* Don't warn about friends, let add_friend take care of it. */
&& ! (DECL_FRIEND_P (newdecl) || DECL_FRIEND_P (olddecl)))
{
warning ("redundant redeclaration of `%D' in same scope", newdecl);
@@ -3487,12 +3695,9 @@ duplicate_decls (newdecl, olddecl)
if (newtype != error_mark_node && oldtype != error_mark_node
&& TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype))
- {
- CLASSTYPE_VSIZE (newtype) = CLASSTYPE_VSIZE (oldtype);
- CLASSTYPE_FRIEND_CLASSES (newtype)
- = CLASSTYPE_FRIEND_CLASSES (oldtype);
- }
-
+ CLASSTYPE_FRIEND_CLASSES (newtype)
+ = CLASSTYPE_FRIEND_CLASSES (oldtype);
+\
DECL_ORIGINAL_TYPE (newdecl) = DECL_ORIGINAL_TYPE (olddecl);
}
@@ -3513,12 +3718,9 @@ duplicate_decls (newdecl, olddecl)
if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE
&& DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE)
{
- DECL_SOURCE_LINE (olddecl)
- = DECL_SOURCE_LINE (DECL_TEMPLATE_RESULT (olddecl))
- = DECL_SOURCE_LINE (newdecl);
- DECL_SOURCE_FILE (olddecl)
- = DECL_SOURCE_FILE (DECL_TEMPLATE_RESULT (olddecl))
- = DECL_SOURCE_FILE (newdecl);
+ DECL_SOURCE_LOCATION (olddecl)
+ = DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
+ = DECL_SOURCE_LOCATION (newdecl);
}
return 1;
@@ -3539,7 +3741,11 @@ duplicate_decls (newdecl, olddecl)
newtype = oldtype;
if (TREE_CODE (newdecl) == VAR_DECL)
- DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
+ {
+ DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
+ DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
+ }
+
/* Do this after calling `merge_types' so that default
parameters don't confuse us. */
else if (TREE_CODE (newdecl) == FUNCTION_DECL
@@ -3589,8 +3795,7 @@ duplicate_decls (newdecl, olddecl)
&& DECL_INITIAL (olddecl) != NULL_TREE)
{
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
- DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
- DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
+ DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
if (CAN_HAVE_FULL_LANG_DECL_P (newdecl)
&& DECL_LANG_SPECIFIC (newdecl)
&& DECL_LANG_SPECIFIC (olddecl))
@@ -3658,7 +3863,8 @@ duplicate_decls (newdecl, olddecl)
/* Don't really know how much of the language-specific
values we should copy from old to new. */
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
- DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
+ DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 =
+ DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2;
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
DECL_INITIALIZED_IN_CLASS_P (newdecl)
@@ -3668,9 +3874,15 @@ duplicate_decls (newdecl, olddecl)
/* Only functions have DECL_BEFRIENDING_CLASSES. */
if (TREE_CODE (newdecl) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (newdecl))
- DECL_BEFRIENDING_CLASSES (newdecl)
- = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
- DECL_BEFRIENDING_CLASSES (olddecl));
+ {
+ DECL_BEFRIENDING_CLASSES (newdecl)
+ = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
+ DECL_BEFRIENDING_CLASSES (olddecl));
+ /* DECL_THUNKS is only valid for virtual functions,
+ otherwise it is a DECL_FRIEND_CONTEXT. */
+ if (DECL_VIRTUAL_P (newdecl))
+ DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl);
+ }
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -3697,17 +3909,26 @@ duplicate_decls (newdecl, olddecl)
olddecl);
SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
+
+ /* [temp.expl.spec/14] We don't inline explicit specialization
+ just because the primary template says so. */
}
- DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
+ else
+ {
+ if (DECL_PENDING_INLINE_INFO (newdecl) == 0)
+ DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
+
+ DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
- /* If either decl says `inline', this fn is inline, unless its
- definition was passed already. */
- if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
- DECL_INLINE (olddecl) = 1;
- DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+ /* If either decl says `inline', this fn is inline, unless
+ its definition was passed already. */
+ if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
+ DECL_INLINE (olddecl) = 1;
+ DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
- DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
- = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
+ DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
+ = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
+ }
/* Preserve abstractness on cloned [cd]tors. */
DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl);
@@ -3807,7 +4028,7 @@ duplicate_decls (newdecl, olddecl)
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl) - sizeof (struct tree_common)
- + tree_code_length [(int)TREE_CODE (newdecl)] * sizeof (char *));
+ + TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
}
DECL_UID (olddecl) = olddecl_uid;
@@ -3837,6 +4058,8 @@ pushdecl (x)
register tree name;
int need_new_binding;
+ timevar_push (TV_NAME_LOOKUP);
+
/* We shouldn't be calling pushdecl when we're generating RTL for a
function that we already did semantic analysis on previously. */
my_friendly_assert (!cfun || doing_semantic_analysis_p (),
@@ -3960,12 +4183,12 @@ pushdecl (x)
/* Check for duplicate params. */
if (duplicate_decls (x, t))
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if ((DECL_EXTERN_C_FUNCTION_P (x)
|| DECL_FUNCTION_TEMPLATE_P (x))
&& is_overloaded_fn (t))
- /* Don't do anything just yet. */;
+ /* Don't do anything just yet. */;
else if (t == wchar_decl_node)
{
if (pedantic && ! DECL_IN_SYSTEM_HEADER (x))
@@ -3973,12 +4196,12 @@ pushdecl (x)
TREE_TYPE (x));
/* Throw away the redeclaration. */
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (TREE_CODE (t) != TREE_CODE (x))
{
if (duplicate_decls (x, t))
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (duplicate_decls (x, t))
{
@@ -3987,7 +4210,7 @@ pushdecl (x)
else if (TREE_CODE (t) == FUNCTION_DECL)
check_default_args (t);
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (DECL_MAIN_P (x))
{
@@ -4001,7 +4224,7 @@ pushdecl (x)
error ("as `%D'", x);
/* We don't try to push this declaration since that
causes a crash. */
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
}
@@ -4019,7 +4242,7 @@ pushdecl (x)
{
t = push_overloaded_decl (x, PUSH_LOCAL);
if (t != x)
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
if (!namespace_bindings_p ())
/* We do not need to create a binding for this name;
push_overloaded_decl will have already done so if
@@ -4031,12 +4254,12 @@ pushdecl (x)
t = push_overloaded_decl (x, PUSH_GLOBAL);
if (t == x)
add_decl_to_level (x, NAMESPACE_LEVEL (CP_DECL_CONTEXT (t)));
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
/* If declaring a type as a typedef, copy the type (unless we're
at line 0), and install this TYPE_DECL as the new type's typedef
- name. See the extensive comment in ../c-decl.c (pushdecl). */
+ name. See the extensive comment in ../c-decl.c (pushdecl). */
if (TREE_CODE (x) == TYPE_DECL)
{
tree type = TREE_TYPE (x);
@@ -4206,7 +4429,9 @@ pushdecl (x)
if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x)
/* Inline decls shadow nothing. */
&& !DECL_FROM_INLINE (x)
- && TREE_CODE (oldlocal) == PARM_DECL)
+ && TREE_CODE (oldlocal) == PARM_DECL
+ /* Don't check the `this' parameter. */
+ && !DECL_ARTIFICIAL (oldlocal))
{
bool err = false;
@@ -4216,7 +4441,7 @@ pushdecl (x)
{
/* Go to where the parms should be and see if we find
them there. */
- struct binding_level *b = current_binding_level->level_chain;
+ struct cp_binding_level *b = current_binding_level->level_chain;
/* ARM $8.3 */
if (b->parm_flag == 1)
@@ -4266,7 +4491,7 @@ pushdecl (x)
? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))
: current_binding_level);
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
/* Same as pushdecl, but define X in binding-level LEVEL. We rely on the
@@ -4275,11 +4500,13 @@ pushdecl (x)
static tree
pushdecl_with_scope (x, level)
tree x;
- struct binding_level *level;
+ struct cp_binding_level *level;
{
- register struct binding_level *b;
+ register struct cp_binding_level *b;
tree function_decl = current_function_decl;
+ timevar_push (TV_NAME_LOOKUP);
+
current_function_decl = NULL_TREE;
if (level->parm_flag == 2)
{
@@ -4296,7 +4523,7 @@ pushdecl_with_scope (x, level)
current_binding_level = b;
}
current_function_decl = function_decl;
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
/* Like pushdecl, only it places X in the current namespace,
@@ -4306,9 +4533,10 @@ tree
pushdecl_namespace_level (x)
tree x;
{
- register struct binding_level *b = current_binding_level;
+ register struct cp_binding_level *b = current_binding_level;
register tree t;
+ timevar_push (TV_NAME_LOOKUP);
t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
/* Now, the type_shadowed stack may screw us. Munge it so it does
@@ -4318,7 +4546,7 @@ pushdecl_namespace_level (x)
tree name = DECL_NAME (x);
tree newval;
tree *ptr = (tree *)0;
- for (; b != global_binding_level; b = b->level_chain)
+ for (; !global_scope_p (b); b = b->level_chain)
{
tree shadowed = b->type_shadowed;
for (; shadowed; shadowed = TREE_CHAIN (shadowed))
@@ -4342,51 +4570,83 @@ pushdecl_namespace_level (x)
*ptr = newval;
}
}
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
-/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL,
- if appropriate. */
+/* Like pushdecl, only it places X in the global scope if appropriate.
+ Calls cp_finish_decl to register the variable, initializing it with
+ *INIT, if INIT is non-NULL. */
-tree
-pushdecl_top_level (x)
- tree x;
+static tree
+pushdecl_top_level_1 (tree x, tree *init)
{
+ timevar_push (TV_NAME_LOOKUP);
push_to_top_level ();
x = pushdecl_namespace_level (x);
+ if (init)
+ cp_finish_decl (x, *init, NULL_TREE, 0);
pop_from_top_level ();
- return x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
+}
+
+/* Like pushdecl, only it places X in the global scope if appropriate. */
+
+tree
+pushdecl_top_level (tree x)
+{
+ return pushdecl_top_level_1 (x, NULL);
+}
+
+/* Like pushdecl, only it places X in the global scope if
+ appropriate. Calls cp_finish_decl to register the variable,
+ initializing it with INIT. */
+
+tree
+pushdecl_top_level_and_finish (tree x, tree init)
+{
+ return pushdecl_top_level_1 (x, &init);
}
/* Make the declaration of X appear in CLASS scope. */
-void
+bool
pushdecl_class_level (x)
tree x;
{
- /* Don't use DECL_ASSEMBLER_NAME here! Everything that looks in class
- scope looks for the pre-mangled name. */
- register tree name;
+ tree name;
+ bool is_valid = true;
+ timevar_push (TV_NAME_LOOKUP);
+ /* Get the name of X. */
if (TREE_CODE (x) == OVERLOAD)
- x = OVL_CURRENT (x);
- name = DECL_NAME (x);
+ name = DECL_NAME (get_first_fn (x));
+ else
+ name = DECL_NAME (x);
if (name)
{
- push_class_level_binding (name, x);
+ is_valid = push_class_level_binding (name, x);
if (TREE_CODE (x) == TYPE_DECL)
set_identifier_type_value (name, TREE_TYPE (x));
}
else if (ANON_AGGR_TYPE_P (TREE_TYPE (x)))
{
+ /* If X is an anonymous aggregate, all of its members are
+ treated as if they were members of the class containing the
+ aggregate, for naming purposes. */
tree f;
- for (f = TYPE_FIELDS (TREE_TYPE (x));
- f;
- f = TREE_CHAIN (f))
- pushdecl_class_level (f);
+ for (f = TYPE_FIELDS (TREE_TYPE (x)); f; f = TREE_CHAIN (f))
+ {
+ push_srcloc (DECL_SOURCE_FILE (f), DECL_SOURCE_LINE (f));
+ if (!pushdecl_class_level (f))
+ is_valid = false;
+ pop_srcloc ();
+ }
}
+ timevar_pop (TV_NAME_LOOKUP);
+
+ return is_valid;
}
/* Enter DECL into the symbol table, if that's appropriate. Returns
@@ -4405,7 +4665,7 @@ maybe_push_decl (decl)
|| (TREE_CODE (decl) != PARM_DECL
&& DECL_CONTEXT (decl) != NULL_TREE
/* Definitions of namespace members outside their namespace are
- possible. */
+ possible. */
&& TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
|| (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
|| TREE_CODE (type) == UNKNOWN_TYPE
@@ -4419,19 +4679,19 @@ maybe_push_decl (decl)
return pushdecl (decl);
}
-/* Make the declaration(s) of X appear in CLASS scope
- under the name NAME. */
+/* Make the declaration(s) of X appear in CLASS scope under the name
+ NAME. Returns true if the binding is valid. */
-void
-push_class_level_binding (name, x)
- tree name;
- tree x;
+bool
+push_class_level_binding (tree name, tree x)
{
- tree binding;
+ cxx_binding *binding;
+
+ timevar_push (TV_NAME_LOOKUP);
/* The class_binding_level will be NULL if x is a template
parameter name in a member template. */
if (!class_binding_level)
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
/* Make sure that this new member does not have the same name
as a template parameter. */
@@ -4481,7 +4741,7 @@ push_class_level_binding (name, x)
INHERITED_VALUE_BINDING_P (binding) = 0;
TREE_TYPE (shadow) = x;
IDENTIFIER_CLASS_VALUE (name) = x;
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
}
}
@@ -4495,7 +4755,10 @@ push_class_level_binding (name, x)
/* Record the value we are binding NAME to so that we can know
what to pop later. */
TREE_TYPE (class_binding_level->class_shadowed) = x;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
}
+
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false);
}
/* Insert another USING_DECL into the current binding level, returning
@@ -4510,18 +4773,21 @@ push_using_decl (scope, name)
{
tree decl;
+ timevar_push (TV_NAME_LOOKUP);
+
my_friendly_assert (TREE_CODE (scope) == NAMESPACE_DECL, 383);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 384);
for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl))
if (DECL_INITIAL (decl) == scope && DECL_NAME (decl) == name)
break;
if (decl)
- return namespace_bindings_p () ? decl : NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+ namespace_bindings_p () ? decl : NULL_TREE);
decl = build_lang_decl (USING_DECL, name, void_type_node);
DECL_INITIAL (decl) = scope;
TREE_CHAIN (decl) = current_binding_level->usings;
current_binding_level->usings = decl;
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* Add namespace to using_directives. Return NULL_TREE if nothing was
@@ -4535,19 +4801,22 @@ push_using_directive (used)
tree ud = current_binding_level->using_directives;
tree iter, ancestor;
- /* Check if we already have this. */
- if (purpose_member (used, ud) != NULL_TREE)
- return NULL_TREE;
+ timevar_push (TV_NAME_LOOKUP);
- /* Recursively add all namespaces used. */
- for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
- push_using_directive (TREE_PURPOSE (iter));
+ /* Check if we already have this. */
+ if (purpose_member (used, ud) != NULL_TREE)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
ancestor = namespace_ancestor (current_decl_namespace (), used);
ud = current_binding_level->using_directives;
ud = tree_cons (used, ancestor, ud);
current_binding_level->using_directives = ud;
- return ud;
+
+ /* Recursively add all namespaces used. */
+ for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
+ push_using_directive (TREE_PURPOSE (iter));
+
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ud);
}
/* DECL is a FUNCTION_DECL for a non-member function, which may have
@@ -4579,6 +4848,8 @@ push_overloaded_decl (decl, flags)
tree new_binding;
int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
+ timevar_push (TV_NAME_LOOKUP);
+
if (doing_global)
old = namespace_binding (name, DECL_CONTEXT (decl));
else
@@ -4611,7 +4882,7 @@ push_overloaded_decl (decl, flags)
decl, fn);
if (duplicate_decls (decl, fn))
- return fn;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn);
}
}
else if (old == error_mark_node)
@@ -4621,7 +4892,7 @@ push_overloaded_decl (decl, flags)
{
cp_error_at ("previous non-function declaration `%#D'", old);
error ("conflicts with function declaration `%#D'", decl);
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
}
@@ -4667,10 +4938,10 @@ push_overloaded_decl (decl, flags)
*d = tree_cons (NULL_TREE, new_binding,
TREE_CHAIN (*d));
- /* And update the CPLUS_BINDING node. */
+ /* And update the cxx_binding node. */
BINDING_VALUE (IDENTIFIER_BINDING (name))
= new_binding;
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* We should always find a previous binding in this case. */
@@ -4681,7 +4952,7 @@ push_overloaded_decl (decl, flags)
push_local_binding (name, new_binding, flags);
}
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* Generate an implicit declaration for identifier FUNCTIONID
@@ -4747,7 +5018,7 @@ redeclaration_error_message (newdecl, olddecl)
return 0;
/* If both functions come from different namespaces, this is not
- a redeclaration - this is a conflict with a used function. */
+ a redeclaration - this is a conflict with a used function. */
if (DECL_NAMESPACE_SCOPE_P (olddecl)
&& DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl))
return "`%D' conflicts with used function";
@@ -4865,18 +5136,20 @@ lookup_label (id)
tree decl;
struct named_label_list *ent;
+ timevar_push (TV_NAME_LOOKUP);
+
/* You can't use labels at global scope. */
if (current_function_decl == NULL_TREE)
{
error ("label `%s' referenced outside of any function",
IDENTIFIER_POINTER (id));
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* See if we've already got this label. */
decl = IDENTIFIER_LABEL_VALUE (id);
if (decl != NULL_TREE && DECL_CONTEXT (decl) == current_function_decl)
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
/* Record this label on the list of labels used in this function.
We do this before calling make_label_decl so that we get the
@@ -4893,7 +5166,7 @@ lookup_label (id)
/* Now fill in the information we didn't have before. */
ent->label_decl = decl;
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
/* Declare a local label named ID. */
@@ -4949,14 +5222,14 @@ decl_jump_unsafe (decl)
static void
check_previous_goto_1 (decl, level, names, file, line)
tree decl;
- struct binding_level *level;
+ struct cp_binding_level *level;
tree names;
const char *file;
int line;
{
int identified = 0;
int saw_eh = 0;
- struct binding_level *b = current_binding_level;
+ struct cp_binding_level *b = current_binding_level;
for (; b; b = b->level_chain)
{
tree new_decls = b->names;
@@ -5023,7 +5296,7 @@ check_previous_goto (use)
static void
check_switch_goto (level)
- struct binding_level *level;
+ struct cp_binding_level *level;
{
check_previous_goto_1 (NULL_TREE, level, level->names, NULL, 0);
}
@@ -5125,7 +5398,9 @@ define_label (filename, line, name)
{
tree decl = lookup_label (name);
struct named_label_list *ent;
- register struct binding_level *p;
+ register struct cp_binding_level *p;
+
+ timevar_push (TV_NAME_LOOKUP);
for (ent = named_labels; ent; ent = ent->next)
if (ent->label_decl == decl)
@@ -5142,7 +5417,7 @@ define_label (filename, line, name)
if (DECL_INITIAL (decl) != NULL_TREE)
{
error ("duplicate label `%D'", decl);
- return 0;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
else
{
@@ -5157,13 +5432,14 @@ define_label (filename, line, name)
ent->binding_level = current_binding_level;
}
check_previous_gotos (decl);
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
+ timevar_pop (TV_NAME_LOOKUP);
}
struct cp_switch
{
- struct binding_level *level;
+ struct cp_binding_level *level;
struct cp_switch *next;
/* The SWITCH_STMT being built. */
tree switch_stmt;
@@ -5219,7 +5495,7 @@ finish_case_label (low_value, high_value)
tree high_value;
{
tree cond, r;
- register struct binding_level *p;
+ register struct cp_binding_level *p;
if (! switch_stack)
{
@@ -5273,14 +5549,6 @@ getdecls ()
return current_binding_level->names;
}
-/* Return the list of type-tags (for structs, etc) of the current level. */
-
-tree
-gettags ()
-{
- return current_binding_level->tags;
-}
-
/* Store the list of declarations of the current level.
This is done for the parameter declarations of a function being defined,
after they are modified in the light of any missing parameters. */
@@ -5292,14 +5560,15 @@ storedecls (decls)
current_binding_level->names = decls;
}
-/* Similarly, store the list of tags of the current level. */
-
+/* Set the current binding TABLE for type declarations.. This is a
+ temporary workaround of the fact that the data structure classtypes
+ does not currently carry its allocated cxx_scope structure. */
void
-storetags (tags)
- tree tags;
+cxx_remember_type_decls (binding_table table)
{
- current_binding_level->tags = tags;
+ current_binding_level->type_decls = table;
}
+
/* Return the type that should be used when TYPE's name is preceded
by a tag such as 'struct' or 'union', or null if the name cannot
@@ -5357,41 +5626,48 @@ static tree
lookup_tag (form, name, binding_level, thislevel_only)
enum tree_code form;
tree name;
- struct binding_level *binding_level;
+ struct cp_binding_level *binding_level;
int thislevel_only;
{
- register struct binding_level *level;
- /* Non-zero if, we should look past a template parameter level, even
+ register struct cp_binding_level *level;
+ /* Nonzero if, we should look past a template parameter level, even
if THISLEVEL_ONLY. */
int allow_template_parms_p = 1;
+ bool type_is_anonymous = ANON_AGGRNAME_P (name);
+
+ timevar_push (TV_NAME_LOOKUP);
for (level = binding_level; level; level = level->level_chain)
{
register tree tail;
- if (ANON_AGGRNAME_P (name))
- for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
- {
- /* There's no need for error checking here, because
- anon names are unique throughout the compilation. */
- if (TYPE_IDENTIFIER (TREE_VALUE (tail)) == name)
- return TREE_VALUE (tail);
- }
+ if (type_is_anonymous && level->type_decls != NULL)
+ {
+ tree type = binding_table_find_anon_type (level->type_decls, name);
+ /* There's no need for error checking here, because
+ anon names are unique throughout the compilation. */
+ if (type != NULL)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type);
+ }
else if (level->namespace_p)
- /* Do namespace lookup. */
+ /* Do namespace lookup. */
for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
{
- tree old = binding_for_name (name, tail);
+ cxx_binding *binding =
+ cxx_scope_find_binding_for_name (tail, name);
+ tree old;
/* If we just skipped past a template parameter level,
even though THISLEVEL_ONLY, and we find a template
class declaration, then we use the _TYPE node for the
template. See the example below. */
if (thislevel_only && !allow_template_parms_p
- && old && BINDING_VALUE (old)
- && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (old)))
- old = TREE_TYPE (BINDING_VALUE (old));
- else
- old = BINDING_TYPE (old);
+ && binding && BINDING_VALUE (binding)
+ && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (binding)))
+ old = TREE_TYPE (BINDING_VALUE (binding));
+ else if (binding)
+ old = BINDING_TYPE (binding);
+ else
+ old = NULL;
if (old)
{
@@ -5400,36 +5676,36 @@ lookup_tag (form, name, binding_level, thislevel_only)
if the typedef doesn't refer to a taggable type. */
old = follow_tag_typedef (old);
if (!old)
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
if (TREE_CODE (old) != form
&& (form == ENUMERAL_TYPE
|| TREE_CODE (old) == ENUMERAL_TYPE))
{
error ("`%#D' redeclared as %C", old, form);
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
- return old;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old);
}
if (thislevel_only || tail == global_namespace)
- return NULL_TREE;
- }
- else
- for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
- {
- if (TREE_PURPOSE (tail) == name)
- {
- enum tree_code code = TREE_CODE (TREE_VALUE (tail));
-
- if (code != form
- && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE))
- {
- /* Definition isn't the kind we were looking for. */
- error ("`%#D' redeclared as %C", TREE_VALUE (tail), form);
- return NULL_TREE;
- }
- return TREE_VALUE (tail);
- }
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
+ else if (level->type_decls != NULL)
+ {
+ binding_entry entry = binding_table_find (level->type_decls, name);
+ if (entry != NULL)
+ {
+ enum tree_code code = TREE_CODE (entry->type);
+
+ if (code != form
+ && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE))
+ {
+ /* Definition isn't the kind we were looking for. */
+ error ("`%#D' redeclared as %C", entry->type, form);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+ }
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->type);
+ }
+ }
if (thislevel_only && ! level->tag_transparent)
{
if (level->template_parms_p && allow_template_parms_p)
@@ -5444,15 +5720,15 @@ lookup_tag (form, name, binding_level, thislevel_only)
are in the pseudo-global level created for the
template parameters, rather than the (surrounding)
namespace level. Thus, we keep going one more level,
- even though THISLEVEL_ONLY is non-zero. */
+ even though THISLEVEL_ONLY is nonzero. */
allow_template_parms_p = 0;
continue;
}
else
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
}
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
#if 0
@@ -5468,7 +5744,7 @@ set_current_level_tags_transparency (tags_transparent)
Otherwise return 0. However, the value can never be 0
in the cases in which this is used.
- C++: If NAME is non-zero, this is the new name to install. This is
+ C++: If NAME is nonzero, this is the new name to install. This is
done when replacing anonymous tags with real tag names. */
static tree
@@ -5476,22 +5752,19 @@ lookup_tag_reverse (type, name)
tree type;
tree name;
{
- register struct binding_level *level;
+ register struct cp_binding_level *level;
+
+ timevar_push (TV_NAME_LOOKUP);
for (level = current_binding_level; level; level = level->level_chain)
{
- register tree tail;
- for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
- {
- if (TREE_VALUE (tail) == type)
- {
- if (name)
- TREE_PURPOSE (tail) = name;
- return TREE_PURPOSE (tail);
- }
- }
+ binding_entry entry = level->type_decls == NULL
+ ? NULL
+ : binding_table_reverse_maybe_remap (level->type_decls, type, name);
+ if (entry)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->name);
}
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* Look up NAME in the NAMESPACE. */
@@ -5502,18 +5775,21 @@ lookup_namespace_name (namespace, name)
{
tree val;
tree template_id = NULL_TREE;
+ cxx_binding binding;
+
+ timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
if (TREE_CODE (name) == NAMESPACE_DECL)
- /* This happens for A::B<int> when B is a namespace. */
- return name;
+ /* This happens for A::B<int> when B is a namespace. */
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, name);
else if (TREE_CODE (name) == TEMPLATE_DECL)
{
/* This happens for A::B where B is a template, and there are no
template arguments. */
error ("invalid use of `%D'", name);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
namespace = ORIGINAL_NAMESPACE (namespace);
@@ -5530,13 +5806,13 @@ lookup_namespace_name (namespace, name)
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
- val = make_node (CPLUS_BINDING);
- if (!qualified_lookup_using_namespace (name, namespace, val, 0))
- return error_mark_node;
+ cxx_binding_clear (&binding);
+ if (!qualified_lookup_using_namespace (name, namespace, &binding, 0))
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- if (BINDING_VALUE (val))
+ if (binding.value)
{
- val = BINDING_VALUE (val);
+ val = binding.value;
if (template_id)
{
@@ -5555,7 +5831,7 @@ lookup_namespace_name (namespace, name)
{
error ("`%D::%D' is not a template",
namespace, name);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
}
@@ -5567,35 +5843,34 @@ lookup_namespace_name (namespace, name)
if (!val || !DECL_P(val)
|| !DECL_LANG_SPECIFIC(val)
|| !DECL_ANTICIPATED (val))
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
error ("`%D' undeclared in namespace `%D'", name, namespace);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
/* Hash a TYPENAME_TYPE. K is really of type `tree'. */
-static unsigned long
+static hashval_t
typename_hash (k)
- hash_table_key k;
+ const void * k;
{
- unsigned long hash;
- tree t;
+ hashval_t hash;
+ tree t = (tree) k;
- t = (tree) k;
- hash = (((unsigned long) TYPE_CONTEXT (t))
- ^ ((unsigned long) DECL_NAME (TYPE_NAME (t))));
+ hash = (htab_hash_pointer (TYPE_CONTEXT (t))
+ ^ htab_hash_pointer (DECL_NAME (TYPE_NAME (t))));
return hash;
}
/* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */
-static bool
+static int
typename_compare (k1, k2)
- hash_table_key k1;
- hash_table_key k2;
+ const void * k1;
+ const void * k2;
{
tree t1;
tree t2;
@@ -5608,7 +5883,7 @@ typename_compare (k1, k2)
d2 = TYPE_NAME (t2);
return (DECL_NAME (d1) == DECL_NAME (d2)
- && same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2))
+ && TYPE_CONTEXT (t1) == TYPE_CONTEXT (t2)
&& ((TREE_TYPE (t1) != NULL_TREE)
== (TREE_TYPE (t2) != NULL_TREE))
&& same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
@@ -5623,6 +5898,8 @@ typename_compare (k1, k2)
Returns the new TYPENAME_TYPE. */
+static GTY ((param_is (union tree_node))) htab_t typename_htab;
+
tree
build_typename_type (context, name, fullname, base_type)
tree context;
@@ -5632,16 +5909,12 @@ build_typename_type (context, name, fullname, base_type)
{
tree t;
tree d;
- struct hash_entry *e;
-
- static struct hash_table ht;
+ PTR *e;
- if (!ht.table)
+ if (typename_htab == NULL)
{
- static struct hash_table *h = &ht;
-
- hash_table_init (&ht, &hash_newfunc, &typename_hash, &typename_compare);
- ggc_add_tree_hash_table_root (&h, 1);
+ typename_htab = htab_create_ggc (61, &typename_hash,
+ &typename_compare, NULL);
}
/* Build the TYPENAME_TYPE. */
@@ -5658,12 +5931,11 @@ build_typename_type (context, name, fullname, base_type)
DECL_ARTIFICIAL (d) = 1;
/* See if we already have this type. */
- e = hash_lookup (&ht, t, /*create=*/false, /*copy=*/0);
- if (e)
- t = (tree) e->key;
+ e = htab_find_slot (typename_htab, t, INSERT);
+ if (*e)
+ t = (tree) *e;
else
- /* Insert the type into the table. */
- hash_lookup (&ht, t, /*create=*/true, /*copy=*/0);
+ *e = t;
return t;
}
@@ -5739,6 +6011,14 @@ make_typename_type (context, name, complain)
return error_mark_node;
}
+ if (complain & tf_error)
+ {
+ if (complain & tf_parsing)
+ type_access_control (context, tmpl);
+ else
+ enforce_access (context, tmpl);
+ }
+
return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1),
NULL_TREE, context,
@@ -5765,6 +6045,15 @@ make_typename_type (context, name, complain)
error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
+
+ if (complain & tf_error)
+ {
+ if (complain & tf_parsing)
+ type_access_control (context, t);
+ else
+ enforce_access (context, t);
+ }
+
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
if (IMPLICIT_TYPENAME_P (t))
@@ -5792,7 +6081,6 @@ make_typename_type (context, name, complain)
return error_mark_node;
}
-
return build_typename_type (context, name, fullname, NULL_TREE);
}
@@ -5805,7 +6093,7 @@ make_typename_type (context, name, complain)
tree
make_unbound_class_template (context, name, complain)
tree context, name;
- int complain;
+ tsubst_flags_t complain;
{
tree t;
tree d;
@@ -5827,13 +6115,18 @@ make_unbound_class_template (context, name, complain)
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
- if (complain)
+ if (complain & tf_error)
error ("no class template named `%#T' in `%#T'", name, context);
return error_mark_node;
}
- if (!enforce_access (context, tmpl))
- return error_mark_node;
+ if (complain & tf_error)
+ {
+ if (complain & tf_parsing)
+ type_access_control (context, tmpl);
+ else
+ enforce_access (context, tmpl);
+ }
return tmpl;
}
@@ -5853,22 +6146,23 @@ make_unbound_class_template (context, name, complain)
return t;
}
-/* Select the right _DECL from multiple choices. */
+/* Select the right _DECL from multiple choices. */
static tree
-select_decl (binding, flags)
- tree binding;
- int flags;
+select_decl (cxx_binding *binding, int flags)
{
tree val;
+
+ timevar_push (TV_NAME_LOOKUP);
+
val = BINDING_VALUE (binding);
if (LOOKUP_NAMESPACES_ONLY (flags))
{
- /* We are not interested in types. */
+ /* We are not interested in types. */
if (val && TREE_CODE (val) == NAMESPACE_DECL)
- return val;
- return NULL_TREE;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
/* If we could have a type and
@@ -5877,13 +6171,13 @@ select_decl (binding, flags)
&& (!val || ((flags & LOOKUP_PREFER_TYPES)
&& TREE_CODE (val) != TYPE_DECL)))
val = TYPE_STUB_DECL (BINDING_TYPE (binding));
- /* Don't return non-types if we really prefer types. */
+ /* Don't return non-types if we really prefer types. */
else if (val && LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL
&& (TREE_CODE (val) != TEMPLATE_DECL
|| !DECL_CLASS_TEMPLATE_P (val)))
val = NULL_TREE;
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
/* Unscoped lookup of a global: iterate over current namespaces,
@@ -5896,65 +6190,65 @@ unqualified_namespace_lookup (name, flags, spacesp)
int flags;
tree *spacesp;
{
- tree b = make_node (CPLUS_BINDING);
tree initial = current_decl_namespace ();
tree scope = initial;
tree siter;
- struct binding_level *level;
+ struct cp_binding_level *level;
tree val = NULL_TREE;
+ cxx_binding binding;
+ timevar_push (TV_NAME_LOOKUP);
+ cxx_binding_clear (&binding);
if (spacesp)
*spacesp = NULL_TREE;
for (; !val; scope = CP_DECL_CONTEXT (scope))
{
+ cxx_binding *b;
if (spacesp)
*spacesp = tree_cons (scope, NULL_TREE, *spacesp);
- val = binding_for_name (name, scope);
+ b = cxx_scope_find_binding_for_name (scope, name);
/* Ignore anticipated built-in functions. */
- if (val && BINDING_VALUE (val)
- && DECL_P (BINDING_VALUE (val))
- && DECL_LANG_SPECIFIC (BINDING_VALUE (val))
- && DECL_ANTICIPATED (BINDING_VALUE (val)))
- {
- BINDING_VALUE (b) = NULL_TREE;
- BINDING_TYPE (b) = NULL_TREE;
- }
- else
+ if (b && BINDING_VALUE (b) && DECL_P (BINDING_VALUE (b))
+ && DECL_LANG_SPECIFIC (BINDING_VALUE (b))
+ && DECL_ANTICIPATED (BINDING_VALUE (b)))
+ /* Keep binding cleared. */;
+ else if (b)
{
- /* Initialize binding for this context. */
- BINDING_VALUE (b) = BINDING_VALUE (val);
- BINDING_TYPE (b) = BINDING_TYPE (val);
+ /* Initialize binding for this context. */
+ binding.value = BINDING_VALUE (b);
+ binding.type = BINDING_TYPE (b);
}
- /* Add all _DECLs seen through local using-directives. */
+ /* Add all _DECLs seen through local using-directives. */
for (level = current_binding_level;
!level->namespace_p;
level = level->level_chain)
- if (!lookup_using_namespace (name, b, level->using_directives,
+ if (!lookup_using_namespace (name, &binding, level->using_directives,
scope, flags, spacesp))
- /* Give up because of error. */
- return error_mark_node;
+ /* Give up because of error. */
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- /* Add all _DECLs seen through global using-directives. */
- /* XXX local and global using lists should work equally. */
+ /* Add all _DECLs seen through global using-directives. */
+ /* XXX local and global using lists should work equally. */
siter = initial;
while (1)
{
- if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
+ if (!lookup_using_namespace (name, &binding,
+ DECL_NAMESPACE_USING (siter),
scope, flags, spacesp))
- /* Give up because of error. */
- return error_mark_node;
+ /* Give up because of error. */
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
if (siter == scope) break;
siter = CP_DECL_CONTEXT (siter);
}
- val = select_decl (b, flags);
+ val = select_decl (&binding, flags);
if (scope == global_namespace)
break;
}
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
/* Combine prefer_type and namespaces_only into flags. */
@@ -6006,6 +6300,7 @@ warn_about_implicit_typename_lookup (typename, binding)
tree name = DECL_NAME (typename);
if (! (TREE_CODE (binding) == TEMPLATE_DECL
+ && CLASS_TYPE_P (subtype)
&& CLASSTYPE_TEMPLATE_INFO (subtype)
&& CLASSTYPE_TI_TEMPLATE (subtype) == binding)
&& ! (TREE_CODE (binding) == TYPE_DECL
@@ -6020,6 +6315,65 @@ warn_about_implicit_typename_lookup (typename, binding)
}
}
+/* Check to see whether or not DECL is a variable that would have been
+ in scope under the ARM, but is not in scope under the ANSI/ISO
+ standard. If so, issue an error message. If name lookup would
+ work in both cases, but return a different result, this function
+ returns the result of ANSI/ISO lookup. Otherwise, it returns
+ DECL. */
+
+tree
+check_for_out_of_scope_variable (tree decl)
+{
+ tree shadowed;
+
+ /* We only care about out of scope variables. */
+ if (!(TREE_CODE (decl) == VAR_DECL && DECL_DEAD_FOR_LOCAL (decl)))
+ return decl;
+
+ shadowed = DECL_SHADOWED_FOR_VAR (decl);
+ while (shadowed != NULL_TREE && TREE_CODE (shadowed) == VAR_DECL
+ && DECL_DEAD_FOR_LOCAL (shadowed))
+ shadowed = DECL_SHADOWED_FOR_VAR (shadowed);
+ if (!shadowed)
+ shadowed = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (decl));
+ if (shadowed)
+ {
+ if (!DECL_ERROR_REPORTED (decl))
+ {
+ warning ("name lookup of `%D' changed",
+ DECL_NAME (decl));
+ cp_warning_at (" matches this `%D' under ISO standard rules",
+ shadowed);
+ cp_warning_at (" matches this `%D' under old rules", decl);
+ DECL_ERROR_REPORTED (decl) = 1;
+ }
+ return shadowed;
+ }
+
+ /* If we have already complained about this declaration, there's no
+ need to do it again. */
+ if (DECL_ERROR_REPORTED (decl))
+ return decl;
+
+ DECL_ERROR_REPORTED (decl) = 1;
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+ {
+ error ("name lookup of `%D' changed for new ISO `for' scoping",
+ DECL_NAME (decl));
+ cp_error_at (" cannot use obsolete binding at `%D' because it has a destructor", decl);
+ return error_mark_node;
+ }
+ else
+ {
+ pedwarn ("name lookup of `%D' changed for new ISO `for' scoping",
+ DECL_NAME (decl));
+ cp_pedwarn_at (" using obsolete binding at `%D'", decl);
+ }
+
+ return decl;
+}
+
/* 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
@@ -6031,7 +6385,7 @@ warn_about_implicit_typename_lookup (typename, binding)
If PREFER_TYPE is -2, we're being called from yylex(). (UGLY)
Otherwise we prefer non-TYPE_DECLs.
- If NONCLASS is non-zero, we don't look for the NAME in class scope,
+ If NONCLASS is nonzero, we don't look for the NAME in class scope,
using IDENTIFIER_CLASS_VALUE. */
static tree
@@ -6045,8 +6399,11 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
tree from_obj = NULL_TREE;
int flags;
int val_is_implicit_typename = 0;
+ cxx_binding *iter;
- /* Hack: copy flag set by parser, if set. */
+ timevar_push (TV_NAME_LOOKUP);
+
+ /* Hack: copy flag set by parser, if set. */
if (only_namespace_names)
namespaces_only = 1;
@@ -6059,7 +6416,7 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
prefer_type = looking_for_typename;
flags = lookup_flags (prefer_type, namespaces_only);
- /* If the next thing is '<', class templates are types. */
+ /* If the next thing is '<', class templates are types. */
if (looking_for_template)
flags |= LOOKUP_TEMPLATES_EXPECTED;
@@ -6071,8 +6428,8 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
if (type)
{
if (type == error_mark_node)
- return error_mark_node;
- if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+ if (IMPLICIT_TYPENAME_P (type))
type = TREE_TYPE (type);
if (TYPE_P (type))
@@ -6082,11 +6439,12 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
type = global_namespace;
if (TREE_CODE (type) == NAMESPACE_DECL)
{
- val = make_node (CPLUS_BINDING);
+ cxx_binding b;
+ cxx_binding_clear (&b);
flags |= LOOKUP_COMPLAIN;
- if (!qualified_lookup_using_namespace (name, type, val, flags))
- return NULL_TREE;
- val = select_decl (val, flags);
+ if (!qualified_lookup_using_namespace (name, type, &b, flags))
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+ val = select_decl (&b, flags);
}
else if (! IS_AGGR_TYPE (type)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
@@ -6099,7 +6457,8 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
else
{
val = lookup_member (type, name, 0, prefer_type);
- type_access_control (type, val);
+ if (!uses_template_parms (type))
+ type_access_control (type, val);
/* Restore the containing TYPENAME_TYPE if we looked
through it before. */
@@ -6129,36 +6488,65 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
else
{
flags = lookup_flags (prefer_type, namespaces_only);
- /* If we're not parsing, we need to complain. */
+ /* If we're not parsing, we need to complain. */
flags |= LOOKUP_COMPLAIN;
}
+ /* Conversion operators are handled specially because ordinary
+ unqualified name lookup will not find template conversion
+ operators. */
+ if (IDENTIFIER_TYPENAME_P (name))
+ {
+ struct cp_binding_level *level;
+
+ for (level = current_binding_level;
+ level && !level->namespace_p;
+ level = level->level_chain)
+ {
+ tree class_type;
+ tree operators;
+
+ /* A conversion operator can only be declared in a class
+ scope. */
+ if (level->parm_flag != 2)
+ continue;
+
+ /* Lookup the conversion operator in the class. */
+ class_type = level->this_class;
+ operators = lookup_fnfields (class_type, name, /*protect=*/0);
+ if (operators)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, operators);
+ }
+
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+ }
+
/* First, look in non-namespace scopes. */
if (current_class_type == NULL_TREE)
nonclass = 1;
- for (t = IDENTIFIER_BINDING (name); t; t = TREE_CHAIN (t))
+ for (iter = IDENTIFIER_BINDING (name); iter; iter = iter->previous)
{
tree binding;
- if (!LOCAL_BINDING_P (t) && nonclass)
+ if (!LOCAL_BINDING_P (iter) && nonclass)
/* We're not looking for class-scoped bindings, so keep going. */
continue;
/* If this is the kind of thing we're looking for, we're done. */
- if (qualify_lookup (BINDING_VALUE (t), flags))
- binding = BINDING_VALUE (t);
+ if (qualify_lookup (BINDING_VALUE (iter), flags))
+ binding = BINDING_VALUE (iter);
else if ((flags & LOOKUP_PREFER_TYPES)
- && qualify_lookup (BINDING_TYPE (t), flags))
- binding = BINDING_TYPE (t);
+ && qualify_lookup (BINDING_TYPE (iter), flags))
+ binding = BINDING_TYPE (iter);
else
binding = NULL_TREE;
/* Handle access control on types from enclosing or base classes. */
if (binding && ! yylex
- && BINDING_LEVEL (t) && BINDING_LEVEL (t)->parm_flag == 2)
- type_access_control (BINDING_LEVEL (t)->this_class, binding);
+ && BINDING_LEVEL (iter) && BINDING_LEVEL (iter)->parm_flag == 2)
+ type_access_control (BINDING_LEVEL (iter)->this_class, binding);
if (binding
&& (!val || !IMPLICIT_TYPENAME_TYPE_DECL_P (binding)))
@@ -6217,7 +6605,7 @@ does not match lookup in the current scope (`%#D')",
else if (from_obj)
val = from_obj;
- return val;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
tree
@@ -6258,9 +6646,11 @@ tree
lookup_name_current_level (name)
tree name;
{
- struct binding_level *b;
+ struct cp_binding_level *b;
tree t = NULL_TREE;
+ timevar_push (TV_NAME_LOOKUP);
+
b = current_binding_level;
while (b->parm_flag == 2)
b = b->level_chain;
@@ -6279,7 +6669,7 @@ lookup_name_current_level (name)
while (1)
{
if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
- return IDENTIFIER_VALUE (name);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, IDENTIFIER_VALUE (name));
if (b->keep == 2)
b = b->level_chain;
@@ -6288,7 +6678,7 @@ lookup_name_current_level (name)
}
}
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
/* Like lookup_name_current_level, but for types. */
@@ -6298,17 +6688,20 @@ lookup_type_current_level (name)
tree name;
{
register tree t = NULL_TREE;
+
+ timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (! current_binding_level->namespace_p, 980716);
if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE
&& REAL_IDENTIFIER_TYPE_VALUE (name) != global_type_node)
{
- struct binding_level *b = current_binding_level;
+ struct cp_binding_level *b = current_binding_level;
while (1)
{
if (purpose_member (name, b->type_shadowed))
- return REAL_IDENTIFIER_TYPE_VALUE (name);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+ REAL_IDENTIFIER_TYPE_VALUE (name));
if (b->keep == 2)
b = b->level_chain;
else
@@ -6316,7 +6709,7 @@ lookup_type_current_level (name)
}
}
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
void
@@ -6357,7 +6750,7 @@ record_builtin_type (rid_index, name, type)
tdecl = pushdecl (build_decl (TYPE_DECL, tname, type));
set_identifier_type_value (tname, NULL_TREE);
if ((int) rid_index < (int) RID_MAX)
- /* Built-in types live in the global namespace. */
+ /* Built-in types live in the global namespace. */
SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl);
}
if (rname != NULL_TREE)
@@ -6389,12 +6782,12 @@ record_builtin_java_type (name, size)
if (size > 0)
type = make_signed_type (size);
else if (size > -32)
- { /* "__java_char" or ""__java_boolean". */
+ { /* "__java_char" or ""__java_boolean". */
type = make_unsigned_type (-size);
/*if (size == -1) TREE_SET_CODE (type, BOOLEAN_TYPE);*/
}
else
- { /* "__java_float" or ""__java_double". */
+ { /* "__java_float" or ""__java_double". */
type = make_node (REAL_TYPE);
TYPE_PRECISION (type) = - size;
layout_type (type);
@@ -6404,14 +6797,14 @@ record_builtin_java_type (name, size)
/* Suppress generate debug symbol entries for these types,
since for normal C++ they are just clutter.
- However, push_lang_context undoes this if extern "Java" is seen. */
+ However, push_lang_context undoes this if extern "Java" is seen. */
DECL_IGNORED_P (decl) = 1;
TYPE_FOR_JAVA (type) = 1;
return type;
}
-/* Push a type into the namespace so that the back-ends ignore it. */
+/* Push a type into the namespace so that the back-ends ignore it. */
static void
record_unknown_type (type, name)
@@ -6437,7 +6830,7 @@ typedef struct predefined_identifier
const char *const name;
/* The place where the IDENTIFIER_NODE should be stored. */
tree *const node;
- /* Non-zero if this is the name of a constructor or destructor. */
+ /* Nonzero if this is the name of a constructor or destructor. */
const int ctor_or_dtor_p;
} predefined_identifier;
@@ -6494,26 +6887,19 @@ cxx_init_decl_processing ()
initialize_predefined_identifiers ();
/* Fill in back-end hooks. */
- init_lang_status = &push_cp_function_context;
- free_lang_status = &pop_cp_function_context;
- mark_lang_status = &mark_cp_function_context;
lang_missing_noreturn_ok_p = &cp_missing_noreturn_ok_p;
- cp_parse_init ();
- init_decl2 ();
- init_pt ();
-
/* Create the global variables. */
push_to_top_level ();
- /* Enter the global namespace. */
+ /* Enter the global namespace. */
my_friendly_assert (global_namespace == NULL_TREE, 375);
push_namespace (get_identifier ("::"));
global_namespace = current_namespace;
current_lang_name = NULL_TREE;
/* Adjust various flags based on command-line settings. */
- if (! flag_permissive && ! pedantic)
+ if (!flag_permissive)
flag_pedantic_errors = 1;
if (!flag_no_inline)
{
@@ -6546,18 +6932,20 @@ cxx_init_decl_processing ()
/* Make the binding_level structure for global names. */
pushlevel (0);
- global_binding_level = current_binding_level;
+ current_binding_level->type_decls = binding_table_new (GLOBAL_SCOPE_HT_SIZE);
/* The global level is the namespace level of ::. */
- NAMESPACE_LEVEL (global_namespace) = global_binding_level;
+ NAMESPACE_LEVEL (global_namespace) = current_binding_level;
declare_namespace_level ();
+ VARRAY_TREE_INIT (current_binding_level->static_decls,
+ 200,
+ "Static declarations");
+
/* Create the `std' namespace. */
push_namespace (std_identifier);
std_node = current_namespace;
pop_namespace ();
- lang_attribute_table = cp_attribute_table;
-
c_common_nodes_and_builtins ();
java_byte_type_node = record_builtin_java_type ("__java_byte", 8);
@@ -6585,9 +6973,6 @@ cxx_init_decl_processing ()
boolean_true_node = build_int_2 (1, 0);
TREE_TYPE (boolean_true_node) = boolean_type_node;
- signed_size_zero_node = build_int_2 (0, 0);
- TREE_TYPE (signed_size_zero_node) = make_signed_type (TYPE_PRECISION (sizetype));
-
empty_except_spec = build_tree_list (NULL_TREE, NULL_TREE);
#if 0
@@ -6598,8 +6983,6 @@ cxx_init_decl_processing ()
vtable_index_type = ptrdiff_type_node;
vtt_parm_type = build_pointer_type (const_ptr_type_node);
- lang_type_promotes_to = convert_type_from_ellipsis;
-
void_ftype = build_function_type (void_type_node, void_list_node);
void_ftype_ptr = build_function_type (void_type_node,
tree_cons (NULL_TREE,
@@ -6657,8 +7040,9 @@ cxx_init_decl_processing ()
tree ptr_ftype_sizetype;
push_namespace (std_identifier);
- bad_alloc_type_node = xref_tag
- (class_type_node, get_identifier ("bad_alloc"), 1);
+ bad_alloc_type_node
+ = xref_tag (class_type, get_identifier ("bad_alloc"),
+ /*attributes=*/NULL_TREE, 1);
pop_namespace ();
ptr_ftype_sizetype
= build_function_type (ptr_type_node,
@@ -6680,7 +7064,6 @@ cxx_init_decl_processing ()
/* Perform other language dependent initializations. */
init_class_processing ();
- init_init_processing ();
init_search_processing ();
init_rtti_processing ();
@@ -6700,41 +7083,11 @@ cxx_init_decl_processing ()
say -fwritable-strings? */
if (flag_writable_strings)
flag_const_strings = 0;
-
- /* Add GC roots for all of our global variables. */
- ggc_add_tree_root (c_global_trees, sizeof c_global_trees / sizeof(tree));
- ggc_add_tree_root (cp_global_trees, sizeof cp_global_trees / sizeof(tree));
- ggc_add_tree_root (&integer_three_node, 1);
- ggc_add_tree_root (&integer_two_node, 1);
- ggc_add_tree_root (&signed_size_zero_node, 1);
- ggc_add_tree_root (&size_one_node, 1);
- ggc_add_tree_root (&size_zero_node, 1);
- ggc_add_root (&global_binding_level, 1, sizeof global_binding_level,
- mark_binding_level);
- ggc_add_root (&scope_chain, 1, sizeof scope_chain, &mark_saved_scope);
- ggc_add_tree_root (&static_ctors, 1);
- ggc_add_tree_root (&static_dtors, 1);
- ggc_add_tree_root (&lastiddecl, 1);
-
- ggc_add_tree_root (&last_function_parms, 1);
- ggc_add_tree_root (&error_mark_list, 1);
-
- ggc_add_tree_root (&global_namespace, 1);
- ggc_add_tree_root (&global_type_node, 1);
- ggc_add_tree_root (&anonymous_namespace_name, 1);
-
- ggc_add_tree_root (&got_object, 1);
- ggc_add_tree_root (&got_scope, 1);
-
- ggc_add_tree_root (&current_lang_name, 1);
- ggc_add_tree_root (&static_aggregates, 1);
- ggc_add_tree_root (&free_bindings, 1);
- ggc_add_tree_root (&incomplete_vars, 1);
}
/* Generate an initializer for a function naming variable from
NAME. NAME may be NULL, in which case we generate a special
- ERROR_MARK node which should be replaced later. */
+ ERROR_MARK node which should be replaced later. */
tree
cp_fname_init (name)
@@ -6759,7 +7112,7 @@ cp_fname_init (name)
TREE_TYPE (init) = type;
else
/* We don't know the value until instantiation time. Make
- something which will be digested now, but replaced later. */
+ something which will be digested now, but replaced later. */
init = build (ERROR_MARK, type);
return init;
@@ -6781,7 +7134,7 @@ cp_make_fname_decl (id, type_dep)
tree init = cp_fname_init (name);
tree decl = build_decl (VAR_DECL, id, TREE_TYPE (init));
- /* As we don't push the decl here, we must set the context. */
+ /* As we don't push the decl here, we must set the context. */
DECL_CONTEXT (decl) = current_function_decl;
DECL_PRETTY_FUNCTION_P (decl) = type_dep;
@@ -6805,26 +7158,25 @@ cp_make_fname_decl (id, type_dep)
See tree.h for possible values.
If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME,
- the name to be called if we can't opencode the function. */
+ the name to be called if we can't opencode the function.
+ If ATTRS is nonzero, use that for the function's attribute
+ list. */
static tree
-builtin_function_1 (name, type, context, code, class, libname)
+builtin_function_1 (name, type, context, code, class, libname, attrs)
const char *name;
tree type;
tree context;
int code;
enum built_in_class class;
const char *libname;
+ tree attrs;
{
tree decl = build_library_fn_1 (get_identifier (name), ERROR_MARK, type);
DECL_BUILT_IN_CLASS (decl) = class;
DECL_FUNCTION_CODE (decl) = code;
DECL_CONTEXT (decl) = context;
- /* The return builtins leave the current function. */
- if (code == BUILT_IN_RETURN || code == BUILT_IN_EH_RETURN)
- TREE_THIS_VOLATILE (decl) = 1;
-
pushdecl (decl);
/* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME,
@@ -6840,7 +7192,10 @@ builtin_function_1 (name, type, context, code, class, libname)
DECL_ANTICIPATED (decl) = 1;
/* Possibly apply some default attributes to this built-in function. */
- decl_attributes (&decl, NULL_TREE, 0);
+ if (attrs)
+ decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
+ else
+ decl_attributes (&decl, NULL_TREE, 0);
return decl;
}
@@ -6856,26 +7211,31 @@ builtin_function_1 (name, type, context, code, class, libname)
See tree.h for possible values.
If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME,
- the name to be called if we can't opencode the function. */
+ the name to be called if we can't opencode the function.
+
+ If ATTRS is nonzero, use that for the function's attribute
+ list. */
tree
-builtin_function (name, type, code, class, libname)
+builtin_function (name, type, code, class, libname, attrs)
const char *name;
tree type;
int code;
enum built_in_class class;
const char *libname;
+ tree attrs;
{
/* All builtins that don't begin with an '_' should additionally
go in the 'std' namespace. */
if (name[0] != '_')
{
push_namespace (std_identifier);
- builtin_function_1 (name, type, std_node, code, class, libname);
+ builtin_function_1 (name, type, std_node, code, class, libname, attrs);
pop_namespace ();
}
- return builtin_function_1 (name, type, NULL_TREE, code, class, libname);
+ return builtin_function_1 (name, type, NULL_TREE, code,
+ class, libname, attrs);
}
/* Generate a FUNCTION_DECL with the typical flags for a runtime library
@@ -7002,7 +7362,7 @@ push_throw_library_fn (name, type)
attributes. */
void
-insert_default_attributes (decl)
+cxx_insert_default_attributes (decl)
tree decl;
{
if (!DECL_EXTERN_C_FUNCTION_P (decl))
@@ -7140,7 +7500,8 @@ check_tag_decl (declspecs)
|| value == ridpointers[(int) RID_VIRTUAL]
|| value == ridpointers[(int) RID_CONST]
|| value == ridpointers[(int) RID_VOLATILE]
- || value == ridpointers[(int) RID_EXPLICIT])
+ || value == ridpointers[(int) RID_EXPLICIT]
+ || value == ridpointers[(int) RID_THREAD])
ob_modifier = value;
}
@@ -7280,8 +7641,6 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
tree decl;
register tree type, tem;
tree context;
- extern int have_extern_spec;
- extern int used_extern_spec;
#if 0
/* See code below that used this. */
@@ -7289,11 +7648,11 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
#endif
/* This should only be done once on the top most decl. */
- if (have_extern_spec && !used_extern_spec)
+ if (have_extern_spec)
{
declspecs = tree_cons (NULL_TREE, get_identifier ("extern"),
declspecs);
- used_extern_spec = 1;
+ have_extern_spec = false;
}
/* An object declared as __attribute__((deprecated)) suppresses
@@ -7322,11 +7681,11 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
&& context != current_namespace && TREE_CODE (decl) == VAR_DECL)
{
/* When parsing the initializer, lookup should use the object's
- namespace. */
+ namespace. */
push_decl_namespace (context);
}
- /* We are only interested in class contexts, later. */
+ /* We are only interested in class contexts, later. */
if (context && TREE_CODE (context) == NAMESPACE_DECL)
context = NULL_TREE;
@@ -7370,7 +7729,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
cplus_decl_attributes (&decl, attributes, 0);
/* If #pragma weak was used, mark the decl weak now. */
- if (current_binding_level == global_binding_level)
+ if (global_scope_p (current_binding_level))
maybe_apply_pragma_weak (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
@@ -7449,7 +7808,9 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
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);
+ DECL_COMMON (tem) = ((TREE_CODE (tem) != VAR_DECL
+ || !DECL_THREAD_LOCAL (tem))
+ && (flag_conserve_space || ! TREE_PUBLIC (tem)));
#endif
if (! processing_template_decl)
@@ -7577,10 +7938,7 @@ grok_reference_init (decl, type, init)
DECL_INITIAL for local references (instead assigning to them
explicitly); we need to allow the temporary to be initialized
first. */
- tmp = convert_to_reference
- (type, init, CONV_IMPLICIT,
- LOOKUP_ONLYCONVERTING|LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND,
- decl);
+ tmp = initialize_reference (type, init, decl);
if (tmp == error_mark_node)
return NULL_TREE;
@@ -7598,39 +7956,6 @@ grok_reference_init (decl, type, init)
return NULL_TREE;
}
-/* Fill in DECL_INITIAL with some magical value to prevent expand_decl from
- mucking with forces it does not comprehend (i.e. initialization with a
- constructor). If we are at global scope and won't go into COMMON, fill
- it in with a dummy CONSTRUCTOR to force the variable into .data;
- otherwise we can use error_mark_node. */
-
-static tree
-obscure_complex_init (decl, init)
- tree decl, init;
-{
- if (! flag_no_inline && TREE_STATIC (decl))
- {
- if (extract_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
- {
- if (zero_init_p (TREE_TYPE (decl)))
- DECL_INITIAL (decl) = error_mark_node;
- /* Otherwise, force_store_init_value will have already stored a
- zero-init initializer in DECL_INITIAL, that should be
- retained. */
- }
-
- return init;
-}
-
/* When parsing `int a[] = {1, 2};' we don't know the size of the
array until we finish parsing the initializer. If that's the
situation we're in, update DECL accordingly. */
@@ -7691,11 +8016,16 @@ layout_var_decl (decl)
/* If we haven't already layed out this declaration, do so now.
Note that we must not call complete type for an external object
because it's type might involve templates that we are not
- supposed to isntantiate yet. (And it's perfectly legal to say
+ supposed to isntantiate yet. (And it's perfectly valid to say
`extern X x' for some incomplete type `X'.) */
if (!DECL_EXTERNAL (decl))
complete_type (type);
- if (!DECL_SIZE (decl) && COMPLETE_TYPE_P (type))
+ if (!DECL_SIZE (decl)
+ && TREE_TYPE (decl) != error_mark_node
+ && (COMPLETE_TYPE_P (type)
+ || (TREE_CODE (type) == ARRAY_TYPE
+ && !TYPE_DOMAIN (type)
+ && COMPLETE_TYPE_P (TREE_TYPE (type)))))
layout_decl (decl, 0);
if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE)
@@ -7748,40 +8078,43 @@ maybe_commonize_var (decl)
if (TREE_STATIC (decl)
/* Don't mess with __FUNCTION__. */
&& ! DECL_ARTIFICIAL (decl)
- && current_function_decl
- && DECL_CONTEXT (decl) == current_function_decl
- && (DECL_DECLARED_INLINE_P (current_function_decl)
- || DECL_TEMPLATE_INSTANTIATION (current_function_decl))
- && TREE_PUBLIC (current_function_decl))
- {
- /* If flag_weak, we don't need to mess with this, as we can just
- make the function weak, and let it refer to its unique local
- copy. This works because we don't allow the function to be
- inlined. */
- if (! flag_weak)
- {
- if (DECL_INTERFACE_KNOWN (current_function_decl))
- {
- TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = DECL_EXTERNAL (current_function_decl);
- }
- else if (DECL_INITIAL (decl) == NULL_TREE
- || DECL_INITIAL (decl) == error_mark_node)
+ && DECL_FUNCTION_SCOPE_P (decl)
+ /* Unfortunately, import_export_decl has not always been called
+ before the function is processed, so we cannot simply check
+ DECL_COMDAT. */
+ && (DECL_COMDAT (DECL_CONTEXT (decl))
+ || ((DECL_DECLARED_INLINE_P (DECL_CONTEXT (decl))
+ || DECL_TEMPLATE_INSTANTIATION (DECL_CONTEXT (decl)))
+ && TREE_PUBLIC (DECL_CONTEXT (decl)))))
+ {
+ if (flag_weak)
+ {
+ /* With weak symbols, we simply make the variable COMDAT;
+ that will cause copies in multiple translations units to
+ be merged. */
+ comdat_linkage (decl);
+ }
+ else
+ {
+ if (DECL_INITIAL (decl) == NULL_TREE
+ || DECL_INITIAL (decl) == error_mark_node)
{
+ /* Without weak symbols, we can use COMMON to merge
+ uninitialized variables. */
TREE_PUBLIC (decl) = 1;
DECL_COMMON (decl) = 1;
}
- /* else we lose. We can only do this if we can use common,
- which we can't if it has been initialized. */
-
- if (!TREE_PUBLIC (decl))
+ else
{
+ /* While for initialized variables, we must use internal
+ linkage -- which means that multiple copies will not
+ be merged. */
+ TREE_PUBLIC (decl) = 0;
+ DECL_COMMON (decl) = 0;
cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
cp_warning_at (" you can work around this by removing the initializer", decl);
}
}
- else
- comdat_linkage (decl);
}
else if (DECL_LANG_SPECIFIC (decl) && DECL_COMDAT (decl))
/* Set it up again; we might have set DECL_INITIAL since the last
@@ -7808,53 +8141,277 @@ check_for_uninitialized_const_var (decl)
error ("uninitialized const `%D'", decl);
}
-/* Verify INIT (the initializer for DECL), and record the
- initialization in DECL_INITIAL, if appropriate. Returns a new
- value for INIT. */
+/* FIELD is a FIELD_DECL or NULL. In the former case, the value
+ returned is the next FIELD_DECL (possibly FIELD itself) that can be
+ initialized. If there are no more such fields, the return value
+ will be NULL. */
static tree
-check_initializer (decl, init)
- tree decl;
- tree init;
+next_initializable_field (tree field)
{
- tree type;
+ while (field
+ && (TREE_CODE (field) != FIELD_DECL
+ || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
+ || DECL_ARTIFICIAL (field)))
+ field = TREE_CHAIN (field);
- if (TREE_CODE (decl) == FIELD_DECL)
- return init;
+ return field;
+}
- type = TREE_TYPE (decl);
+/* Undo the brace-elision allowed by [dcl.init.aggr] in a
+ brace-enclosed aggregate initializer.
- /* If `start_decl' didn't like having an initialization, ignore it now. */
- if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
- init = NULL_TREE;
+ *INITP is one of a list of initializers describing a brace-enclosed
+ initializer for an entity of the indicated aggregate TYPE. It may
+ not presently match the shape of the TYPE; for example:
+
+ struct S { int a; int b; };
+ struct S a[] = { 1, 2, 3, 4 };
- /* Check the initializer. */
- if (init)
+ Here *INITP will point to TREE_LIST of four elements, rather than a
+ list of two elements, each itself a list of two elements. This
+ routine transforms INIT from the former form into the latter. The
+ revised initializer is returned. */
+
+static tree
+reshape_init (tree type, tree *initp)
+{
+ tree inits;
+ tree old_init;
+ tree old_init_value;
+ tree new_init;
+ bool brace_enclosed_p;
+
+ old_init = *initp;
+ old_init_value = (TREE_CODE (*initp) == TREE_LIST
+ ? TREE_VALUE (*initp) : old_init);
+
+ /* For some parse errors, OLD_INIT_VALUE may be NULL. */
+ if (!old_init_value)
{
- /* Things that are going to be initialized need to have complete
- type. */
- TREE_TYPE (decl) = type = complete_type (TREE_TYPE (decl));
+ my_friendly_assert (TREE_CODE (old_init) == TREE_LIST, 20021202);
+ TREE_VALUE (old_init) = error_mark_node;
+ return old_init;
+ }
- if (type == error_mark_node)
- /* We will have already complained. */
- init = NULL_TREE;
- else if (COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
- {
- error ("variable-sized object `%D' may not be initialized", decl);
- init = NULL_TREE;
- }
- else if (TREE_CODE (type) == ARRAY_TYPE
- && !COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
+ /* If the initializer is brace-enclosed, pull initializers from the
+ enclosed elements. Advance past the brace-enclosed initializer
+ now. */
+ if (TREE_CODE (old_init_value) == CONSTRUCTOR
+ && TREE_HAS_CONSTRUCTOR (old_init_value))
+ {
+ *initp = TREE_CHAIN (old_init);
+ TREE_CHAIN (old_init) = NULL_TREE;
+ inits = CONSTRUCTOR_ELTS (old_init_value);
+ initp = &inits;
+ brace_enclosed_p = true;
+ }
+ else
+ {
+ inits = NULL_TREE;
+ brace_enclosed_p = false;
+ }
+
+ /* A non-aggregate type is always initialized with a single
+ initializer. */
+ if (!CP_AGGREGATE_TYPE_P (type))
+ {
+ *initp = TREE_CHAIN (old_init);
+ TREE_CHAIN (old_init) = NULL_TREE;
+ /* It is invalid to initialize a non-aggregate type with a
+ brace-enclosed initializer. */
+ if (brace_enclosed_p)
+ {
+ error ("brace-enclosed initializer used to initialize `%T'",
+ type);
+ if (TREE_CODE (old_init) == TREE_LIST)
+ TREE_VALUE (old_init) = error_mark_node;
+ else
+ old_init = error_mark_node;
+ }
+
+ return old_init;
+ }
+
+ /* [dcl.init.aggr]
+
+ All implicit type conversions (clause _conv_) are considered when
+ initializing the aggregate member with an initializer from an
+ initializer-list. If the initializer can initialize a member,
+ the member is initialized. Otherwise, if the member is itself a
+ non-empty subaggregate, brace elision is assumed and the
+ initializer is considered for the initialization of the first
+ member of the subaggregate. */
+ if (CLASS_TYPE_P (type)
+ && !brace_enclosed_p
+ && can_convert_arg (type, TREE_TYPE (old_init_value), old_init_value))
+ {
+ *initp = TREE_CHAIN (old_init);
+ TREE_CHAIN (old_init) = NULL_TREE;
+ return old_init;
+ }
+
+ if (TREE_CODE (old_init_value) == STRING_CST
+ && TREE_CODE (type) == ARRAY_TYPE
+ && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))))
+ {
+ /* [dcl.init.string]
+
+ A char array (whether plain char, signed char, or unsigned char)
+ can be initialized by a string-literal (optionally enclosed in
+ braces); a wchar_t array can be initialized by a wide
+ string-literal (optionally enclosed in braces). */
+ new_init = old_init;
+ /* Move past the initializer. */
+ *initp = TREE_CHAIN (old_init);
+ TREE_CHAIN (old_init) = NULL_TREE;
+ }
+ else
+ {
+ /* Build a CONSTRUCTOR to hold the contents of the aggregate. */
+ new_init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ TREE_HAS_CONSTRUCTOR (new_init) = 1;
+
+ if (CLASS_TYPE_P (type))
{
- error ("elements of array `%#D' have incomplete type", decl);
- init = NULL_TREE;
+ tree field;
+
+ field = next_initializable_field (TYPE_FIELDS (type));
+
+ if (!field)
+ {
+ /* [dcl.init.aggr]
+
+ An initializer for an aggregate member that is an
+ empty class shall have the form of an empty
+ initializer-list {}. */
+ if (!brace_enclosed_p)
+ error ("initializer for `%T' must be brace-enclosed",
+ type);
+ }
+ else
+ {
+ /* Loop through the initializable fields, gathering
+ initializers. */
+ while (*initp)
+ {
+ tree field_init;
+
+ /* Handle designated initializers, as an extension. */
+ if (TREE_PURPOSE (*initp))
+ {
+ if (pedantic)
+ pedwarn ("ISO C++ does not allow designated initializers");
+ field = lookup_field_1 (type, TREE_PURPOSE (*initp),
+ /*want_type=*/false);
+ if (!field || TREE_CODE (field) != FIELD_DECL)
+ error ("`%T' has no non-static data member named `%D'",
+ type, TREE_PURPOSE (*initp));
+ }
+ if (!field)
+ break;
+
+ field_init = reshape_init (TREE_TYPE (field), initp);
+ TREE_CHAIN (field_init) = CONSTRUCTOR_ELTS (new_init);
+ CONSTRUCTOR_ELTS (new_init) = field_init;
+ /* [dcl.init.aggr]
+
+ When a union is initialized with a brace-enclosed
+ initializer, the braces shall only contain an
+ initializer for the first member of the union. */
+ if (TREE_CODE (type) == UNION_TYPE)
+ break;
+ field = next_initializable_field (TREE_CHAIN (field));
+ }
+ }
}
- else if (TREE_CODE (type) != ARRAY_TYPE && !COMPLETE_TYPE_P (type))
+ else if (TREE_CODE (type) == ARRAY_TYPE)
{
- error ("`%D' has incomplete type", decl);
- TREE_TYPE (decl) = error_mark_node;
- init = NULL_TREE;
+ tree index;
+ tree max_index;
+
+ /* If the bound of the array is known, take no more initializers
+ than are allowed. */
+ max_index = (TYPE_DOMAIN (type)
+ ? array_type_nelts (type) : NULL_TREE);
+ /* Loop through the array elements, gathering initializers. */
+ for (index = size_zero_node;
+ *initp && (!max_index || !tree_int_cst_lt (max_index, index));
+ index = size_binop (PLUS_EXPR, index, size_one_node))
+ {
+ tree element_init;
+
+ element_init = reshape_init (TREE_TYPE (type), initp);
+ TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
+ CONSTRUCTOR_ELTS (new_init) = element_init;
+ if (TREE_PURPOSE (element_init))
+ index = TREE_PURPOSE (element_init);
+ }
}
+ else
+ abort ();
+
+ /* The initializers were placed in reverse order in the
+ CONSTRUCTOR. */
+ CONSTRUCTOR_ELTS (new_init) = nreverse (CONSTRUCTOR_ELTS (new_init));
+
+ if (TREE_CODE (old_init) == TREE_LIST)
+ new_init = build_tree_list (TREE_PURPOSE (old_init), new_init);
+ }
+
+ /* If this was a brace-enclosed initializer and all of the
+ initializers were not used up, there is a problem. */
+ if (brace_enclosed_p && *initp)
+ error ("too many initializers for `%T'", type);
+
+ return new_init;
+}
+
+/* Verify INIT (the initializer for DECL), and record the
+ initialization in DECL_INITIAL, if appropriate.
+
+ If the return value is non-NULL, it is an expression that must be
+ evaluated dynamically to initialize DECL. */
+
+static tree
+check_initializer (tree decl, tree init, int flags)
+{
+ tree type = TREE_TYPE (decl);
+
+ /* If `start_decl' didn't like having an initialization, ignore it now. */
+ if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
+ init = NULL_TREE;
+
+ /* If an initializer is present, DECL_INITIAL has been
+ error_mark_node, to indicate that an as-of-yet unevaluated
+ initialization will occur. From now on, DECL_INITIAL reflects
+ the static initialization -- if any -- of DECL. */
+ DECL_INITIAL (decl) = NULL_TREE;
+
+ /* Things that are going to be initialized need to have complete
+ type. */
+ TREE_TYPE (decl) = type = complete_type (TREE_TYPE (decl));
+
+ if (type == error_mark_node)
+ /* We will have already complained. */
+ init = NULL_TREE;
+ else if (init && COMPLETE_TYPE_P (type)
+ && !TREE_CONSTANT (TYPE_SIZE (type)))
+ {
+ error ("variable-sized object `%D' may not be initialized", decl);
+ init = NULL_TREE;
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE
+ && !COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
+ {
+ error ("elements of array `%#D' have incomplete type", decl);
+ init = NULL_TREE;
+ }
+ else if (TREE_CODE (type) != ARRAY_TYPE && !COMPLETE_TYPE_P (type))
+ {
+ error ("`%D' has incomplete type", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ init = NULL_TREE;
}
if (TREE_CODE (decl) == CONST_DECL)
@@ -7867,37 +8424,64 @@ check_initializer (decl, init)
init = NULL_TREE;
}
else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
- {
- init = grok_reference_init (decl, type, init);
- if (init)
- init = obscure_complex_init (decl, init);
- }
- else if (!DECL_EXTERNAL (decl) && !zero_init_p (type))
- {
- force_store_init_value (decl, build_forced_zero_init (type));
-
- if (init)
- goto process_init;
- }
+ init = grok_reference_init (decl, type, init);
else if (init)
{
- process_init:
+ if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
+ {
+ /* [dcl.init] paragraph 13,
+ If T is a scalar type, then a declaration of the form
+ T x = { a };
+ is equivalent to
+ T x = a;
+
+ reshape_init will complain about the extra braces,
+ and doesn't do anything useful in the case where TYPE is
+ scalar, so just don't call it. */
+ if (CP_AGGREGATE_TYPE_P (type))
+ init = reshape_init (type, &init);
+ }
+
+ /* If DECL has an array type without a specific bound, deduce the
+ array size from the initializer. */
+ maybe_deduce_size_from_array_init (decl, init);
+ type = TREE_TYPE (decl);
+ if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
+ TREE_TYPE (init) = type;
+
if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
{
if (TREE_CODE (type) == ARRAY_TYPE)
- init = digest_init (type, init, (tree *) 0);
+ goto initialize_aggr;
else if (TREE_CODE (init) == CONSTRUCTOR
&& TREE_HAS_CONSTRUCTOR (init))
{
if (TYPE_NON_AGGREGATE_CLASS (type))
{
error ("`%D' must be initialized by constructor, not by `{...}'",
- decl);
+ decl);
init = error_mark_node;
}
else
goto dont_use_constructor;
}
+ else
+ {
+ int saved_stmts_are_full_exprs_p;
+
+ initialize_aggr:
+ saved_stmts_are_full_exprs_p = 0;
+ if (building_stmt_tree ())
+ {
+ saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
+ current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+ }
+ init = build_aggr_init (decl, init, flags);
+ if (building_stmt_tree ())
+ current_stmt_tree ()->stmts_are_full_exprs_p =
+ saved_stmts_are_full_exprs_p;
+ return init;
+ }
}
else
{
@@ -7905,37 +8489,29 @@ check_initializer (decl, init)
if (TREE_CODE (init) != TREE_VEC)
init = store_init_value (decl, init);
}
-
- if (init)
- /* We must hide the initializer so that expand_decl
- won't try to do something it does not understand. */
- init = obscure_complex_init (decl, init);
}
else if (DECL_EXTERNAL (decl))
;
- else if (TYPE_P (type)
- && (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
+ else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
+ goto initialize_aggr;
+ else if (IS_AGGR_TYPE (type))
{
tree core_type = strip_array_types (type);
- if (! TYPE_NEEDS_CONSTRUCTING (core_type))
- {
- if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
- error ("structure `%D' with uninitialized const members", decl);
- if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
- error ("structure `%D' with uninitialized reference members",
- decl);
- }
+ if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
+ error ("structure `%D' with uninitialized const members", decl);
+ if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
+ error ("structure `%D' with uninitialized reference members",
+ decl);
check_for_uninitialized_const_var (decl);
-
- if (COMPLETE_TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
- init = obscure_complex_init (decl, NULL_TREE);
-
}
else
check_for_uninitialized_const_var (decl);
+ if (init && init != error_mark_node)
+ init = build (INIT_EXPR, type, decl, init);
+
return init;
}
@@ -8033,18 +8609,20 @@ void
maybe_inject_for_scope_var (decl)
tree decl;
{
+ timevar_push (TV_NAME_LOOKUP);
+
if (!DECL_NAME (decl))
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
/* Declarations of __FUNCTION__ and its ilk appear magically when
the variable is first used. If that happens to be inside a
for-loop, we don't want to do anything special. */
if (DECL_PRETTY_FUNCTION_P (decl))
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
if (current_binding_level->is_for_scope)
{
- struct binding_level *outer
+ struct cp_binding_level *outer
= current_binding_level->level_chain;
/* Check to see if the same name is already bound at the outer
@@ -8056,8 +8634,8 @@ maybe_inject_for_scope_var (decl)
Otherwise, we need to preserve the temp slot for decl to last
into the outer binding level. */
- tree outer_binding
- = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
+ cxx_binding *outer_binding
+ = IDENTIFIER_BINDING (DECL_NAME (decl))->previous;
if (outer_binding && BINDING_LEVEL (outer_binding) == outer
&& (TREE_CODE (BINDING_VALUE (outer_binding))
@@ -8071,39 +8649,32 @@ maybe_inject_for_scope_var (decl)
else if (DECL_IN_MEMORY_P (decl))
preserve_temp_slots (DECL_RTL (decl));
}
+
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Generate code to initialize DECL (a local variable). */
-void
-initialize_local_var (decl, init, flags)
+static void
+initialize_local_var (decl, init)
tree decl;
tree init;
- int flags;
{
tree type = TREE_TYPE (decl);
+ tree cleanup;
- /* If the type is bogus, don't bother initializing the variable. */
- if (type == error_mark_node)
- return;
+ my_friendly_assert (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == RESULT_DECL,
+ 20021010);
+ my_friendly_assert (!TREE_STATIC (decl), 20021010);
- if (DECL_SIZE (decl) == NULL_TREE && !TREE_STATIC (decl))
+ if (DECL_SIZE (decl) == NULL_TREE)
{
/* If we used it already as memory, it must stay in memory. */
DECL_INITIAL (decl) = NULL_TREE;
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
}
- /* Local statics are handled differently from ordinary automatic
- variables. */
- if (TREE_STATIC (decl))
- {
- if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
- || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
- expand_static_init (decl, init);
- return;
- }
-
if (DECL_SIZE (decl) && type != error_mark_node)
{
int already_used;
@@ -8111,14 +8682,15 @@ initialize_local_var (decl, init, flags)
/* Compute and store the initial value. */
already_used = TREE_USED (decl) || TREE_USED (type);
- if (init || TYPE_NEEDS_CONSTRUCTING (type))
+ /* Perform the initialization. */
+ if (init)
{
int saved_stmts_are_full_exprs_p;
my_friendly_assert (building_stmt_tree (), 20000906);
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
- finish_expr_stmt (build_aggr_init (decl, init, flags));
+ finish_expr_stmt (init);
current_stmt_tree ()->stmts_are_full_exprs_p =
saved_stmts_are_full_exprs_p;
}
@@ -8137,37 +8709,9 @@ initialize_local_var (decl, init, flags)
else if (already_used)
TREE_USED (decl) = 1;
}
-}
-
-/* Generate code to destroy DECL (a local variable). */
-
-static void
-destroy_local_var (decl)
- tree decl;
-{
- tree type = TREE_TYPE (decl);
- tree cleanup;
-
- /* Only variables get cleaned up. */
- if (TREE_CODE (decl) != VAR_DECL)
- return;
-
- /* And only things with destructors need cleaning up. */
- if (type == error_mark_node
- || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
- return;
-
- if (TREE_CODE (decl) == VAR_DECL &&
- (DECL_EXTERNAL (decl) || TREE_STATIC (decl)))
- /* We don't clean up things that aren't defined in this
- translation unit, or that need a static cleanup. The latter
- are handled by finish_file. */
- return;
-
- /* Compute the cleanup. */
- cleanup = maybe_build_cleanup (decl);
- /* Record the cleanup required for this declaration. */
+ /* Generate a cleanup, if necessary. */
+ cleanup = cxx_maybe_build_cleanup (decl);
if (DECL_SIZE (decl) && cleanup)
finish_decl_cleanup (decl, cleanup);
}
@@ -8202,7 +8746,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
}
/* If a name was specified, get the string. */
- if (current_binding_level == global_binding_level)
+ if (global_scope_p (current_binding_level))
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
@@ -8226,7 +8770,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
&& DECL_CONTEXT (decl) != current_namespace
&& init)
{
- /* Leave the namespace of the object. */
+ /* Leave the namespace of the object. */
pop_decl_namespace ();
}
@@ -8281,7 +8825,8 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
ttype = target_type (type);
if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl)
- && TYPE_NEEDS_CONSTRUCTING (type))
+ && (TYPE_NEEDS_CONSTRUCTING (type)
+ || TREE_CODE (type) == REFERENCE_TYPE))
{
/* Currently, GNU C++ puts constants in text space, making them
impossible to initialize. In the future, one would hope for
@@ -8299,10 +8844,59 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
make_decl_rtl (decl, asmspec);
}
-
- /* Deduce size of array from initialization, if not already known. */
- init = check_initializer (decl, init);
- maybe_deduce_size_from_array_init (decl, init);
+ else if (TREE_CODE (decl) == RESULT_DECL)
+ init = check_initializer (decl, init, flags);
+ else if (TREE_CODE (decl) == VAR_DECL)
+ {
+ /* Only PODs can have thread-local storage. Other types may require
+ various kinds of non-trivial initialization. */
+ if (DECL_THREAD_LOCAL (decl) && !pod_type_p (TREE_TYPE (decl)))
+ error ("`%D' cannot be thread-local because it has non-POD type `%T'",
+ decl, TREE_TYPE (decl));
+ /* Convert the initializer to the type of DECL, if we have not
+ already initialized DECL. */
+ if (!DECL_INITIALIZED_P (decl)
+ /* If !DECL_EXTERNAL then DECL is being defined. In the
+ case of a static data member initialized inside the
+ class-specifier, there can be an initializer even if DECL
+ is *not* defined. */
+ && (!DECL_EXTERNAL (decl) || init))
+ {
+ init = check_initializer (decl, init, flags);
+ /* Thread-local storage cannot be dynamically initialized. */
+ if (DECL_THREAD_LOCAL (decl) && init)
+ {
+ error ("`%D' is thread-local and so cannot be dynamically "
+ "initialized", decl);
+ init = NULL_TREE;
+ }
+ /* Handle:
+
+ [dcl.init]
+
+ The memory occupied by any object of static storage
+ duration is zero-initialized at program startup before
+ any other initialization takes place.
+
+ We cannot create an appropriate initializer until after
+ the type of DECL is finalized. If DECL_INITIAL is set,
+ then the DECL is statically initialized, and any
+ necessary zero-initialization has already been performed. */
+ if (TREE_STATIC (decl) && !DECL_INITIAL (decl))
+ DECL_INITIAL (decl) = build_zero_init (TREE_TYPE (decl),
+ /*nelts=*/NULL_TREE,
+ /*static_storage_p=*/true);
+ /* Remember that the initialization for this variable has
+ taken place. */
+ DECL_INITIALIZED_P (decl) = 1;
+ }
+ /* If the variable has an array type, lay out the type, even if
+ there is no initializer. It is valid to index through the
+ array, and we must get TYPE_ALIGN set correctly on the array
+ type. */
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ layout_type (type);
+ }
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_STMT for a
@@ -8333,7 +8927,9 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
else
abstract_virtuals_error (decl, strip_array_types (type));
- if (TREE_CODE (decl) == FUNCTION_DECL)
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_TYPE (decl) == error_mark_node)
+ /* No initialization required. */
;
else if (DECL_EXTERNAL (decl)
&& ! (DECL_LANG_SPECIFIC (decl)
@@ -8342,35 +8938,25 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
if (init)
DECL_INITIAL (decl) = init;
}
- else if (TREE_CODE (CP_DECL_CONTEXT (decl)) == FUNCTION_DECL)
+ else
{
- /* This is a local declaration. */
- if (doing_semantic_analysis_p ())
- maybe_inject_for_scope_var (decl);
- /* Initialize the local variable. But, if we're building a
- statement-tree, we'll do the initialization when we
- expand the tree. */
- if (processing_template_decl)
- {
- if (init || DECL_INITIAL (decl) == error_mark_node)
- DECL_INITIAL (decl) = init;
- }
- else
+ /* A variable definition. */
+ if (DECL_FUNCTION_SCOPE_P (decl))
{
- /* If we're not building RTL, then we need to do so
- now. */
- my_friendly_assert (building_stmt_tree (), 20000906);
- /* Initialize the variable. */
- initialize_local_var (decl, init, flags);
- /* Clean up the variable. */
- destroy_local_var (decl);
+ /* This is a local declaration. */
+ if (doing_semantic_analysis_p ())
+ maybe_inject_for_scope_var (decl);
+ /* Initialize the local variable. */
+ if (processing_template_decl)
+ {
+ if (init || DECL_INITIAL (decl) == error_mark_node)
+ DECL_INITIAL (decl) = init;
+ }
+ else if (!TREE_STATIC (decl))
+ initialize_local_var (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_HAS_NONTRIVIAL_DESTRUCTOR (type))
+
+ if (TREE_STATIC (decl))
expand_static_init (decl, init);
}
finish_end0:
@@ -8438,7 +9024,7 @@ declare_global_var (name, type)
}
/* Returns a pointer to the `atexit' function. Note that if
- FLAG_USE_CXA_ATEXIT is non-zero, then this will actually be the new
+ FLAG_USE_CXA_ATEXIT is nonzero, then this will actually be the new
`__cxa_atexit' function specified in the IA64 C++ ABI. */
static tree
@@ -8567,9 +9153,8 @@ start_cleanup_fn ()
{
tree parmdecl;
- parmdecl = build_decl (PARM_DECL, NULL_TREE, ptr_type_node);
+ parmdecl = cp_build_parm_decl (NULL_TREE, ptr_type_node);
DECL_CONTEXT (parmdecl) = fndecl;
- DECL_ARG_TYPE (parmdecl) = ptr_type_node;
TREE_USED (parmdecl) = 1;
DECL_ARGUMENTS (fndecl) = parmdecl;
}
@@ -8636,7 +9221,7 @@ register_dtor_fn (decl)
end_cleanup_fn ();
/* Call atexit with the cleanup function. */
- mark_addressable (cleanup);
+ cxx_mark_addressable (cleanup);
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
if (flag_use_cxa_atexit)
{
@@ -8651,12 +9236,27 @@ register_dtor_fn (decl)
finish_expr_stmt (build_function_call (get_atexit_node (), args));
}
-void
+/* DECL is a VAR_DECL with static storage duration. INIT, if present,
+ is its initializer. Generate code to handle the construction
+ and destruction of DECL. */
+
+static void
expand_static_init (decl, init)
tree decl;
tree init;
{
- tree oldstatic = value_member (decl, static_aggregates);
+ tree oldstatic;
+
+ my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20021010);
+ my_friendly_assert (TREE_STATIC (decl), 20021010);
+
+ /* Some variables require no initialization. */
+ if (!init
+ && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
+ && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+ return;
+
+ oldstatic = value_member (decl, static_aggregates);
if (oldstatic)
{
@@ -8706,15 +9306,7 @@ expand_static_init (decl, init)
then_clause = begin_compound_stmt (/*has_no_scope=*/0);
/* Do the initialization itself. */
- if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
- || (init && TREE_CODE (init) == TREE_LIST))
- assignment = build_aggr_init (decl, init, 0);
- else if (init)
- /* The initialization we're doing here is just a bitwise
- copy. */
- assignment = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
- else
- assignment = NULL_TREE;
+ assignment = init ? init : NULL_TREE;
/* Once the assignment is complete, set TEMP to 1. Since the
construction of the static object is complete at this point,
@@ -8954,7 +9546,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
type = build_exception_variant (type, raises);
decl = build_lang_decl (FUNCTION_DECL, declarator, type);
- /* Propagate volatile out from type to decl. */
+ /* Propagate volatile out from type to decl. */
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
@@ -9045,13 +9637,19 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
DECL_NOT_REALLY_EXTERN (decl) = 1;
}
+ DID_INLINE_FUNC (decl) = 0;
/* If the declaration was declared inline, mark it as such. */
if (inlinep)
DECL_DECLARED_INLINE_P (decl) = 1;
/* We inline functions that are explicitly declared inline, or, when
the user explicitly asks us to, all functions. */
- if (DECL_DECLARED_INLINE_P (decl) || flag_inline_trees == 2)
+ if (DECL_DECLARED_INLINE_P (decl))
DECL_INLINE (decl) = 1;
+ if (flag_inline_trees == 2 && !DECL_INLINE (decl) && funcdef_flag)
+ {
+ DID_INLINE_FUNC (decl) = 1;
+ DECL_INLINE (decl) = 1;
+ }
DECL_EXTERNAL (decl) = 1;
if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
@@ -9105,7 +9703,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
/* Due to bison parser ickiness, we will have already looked
up an operator_name or PFUNCNAME within the current class
(see template_id in parse.y). If the current class contains
- such a name, we'll get a COMPONENT_REF here. Undo that. */
+ such a name, we'll get a COMPONENT_REF here. Undo that. */
my_friendly_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
== current_class_type, 20001120);
@@ -9197,7 +9795,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
decl = DECL_TEMPLATE_RESULT (decl);
/* Attempt to merge the declarations. This can fail, in
- the case of some illegal specialization declarations. */
+ the case of some invalid specialization declarations. */
if (!duplicate_decls (decl, old_decl))
error ("no `%#D' member function declared in class `%T'",
decl, ctype);
@@ -9217,64 +9815,68 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
return decl;
}
+/* Create a VAR_DECL named NAME with the indicated TYPE.
+
+ If SCOPE is non-NULL, it is the class type or namespace containing
+ the variable. If SCOPE is NULL, the variable should is created in
+ the innermost enclosings scope. */
+
static tree
-grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
+grokvardecl (type, name, specbits_in, initialized, constp, scope)
tree type;
- tree declarator;
+ tree name;
RID_BIT_TYPE *specbits_in;
int initialized;
int constp;
- tree in_namespace;
+ tree scope;
{
tree decl;
RID_BIT_TYPE specbits;
+ my_friendly_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE,
+ 20020808);
+
specbits = *specbits_in;
- if (TREE_CODE (type) == OFFSET_TYPE)
+ /* Compute the scope in which to place the variable. */
+ if (!scope)
{
- /* If you declare a static member so that it
- can be initialized, the code will reach here. */
- tree basetype = TYPE_OFFSET_BASETYPE (type);
- type = TREE_TYPE (type);
- decl = build_lang_decl (VAR_DECL, declarator, type);
- DECL_CONTEXT (decl) = basetype;
- }
+ /* An explicit "extern" specifier indicates a namespace-scope
+ variable. */
+ if (RIDBIT_SETP (RID_EXTERN, specbits))
+ scope = current_namespace;
+ else if (!at_function_scope_p ())
+ {
+ scope = current_scope ();
+ if (!scope)
+ scope = current_namespace;
+ }
+ }
+
+ if (scope
+ && (/* If the variable is a namespace-scope variable declared in a
+ template, we need DECL_LANG_SPECIFIC. */
+ (TREE_CODE (scope) == NAMESPACE_DECL && processing_template_decl)
+ /* Similarly for namespace-scope variables with language linkage
+ other than C++. */
+ || (TREE_CODE (scope) == NAMESPACE_DECL
+ && current_lang_name != lang_name_cplusplus)
+ /* Similarly for static data members. */
+ || TYPE_P (scope)))
+ decl = build_lang_decl (VAR_DECL, name, type);
else
- {
- tree context;
+ decl = build_decl (VAR_DECL, name, type);
- if (in_namespace)
- context = in_namespace;
- else if (namespace_bindings_p () || RIDBIT_SETP (RID_EXTERN, specbits))
- context = current_namespace;
- else
- context = NULL_TREE;
-
- /* For namespace-scope variables, declared in a template, we
- need the full lang_decl. The same is true for
- namespace-scope variables that do not have C++ language
- linkage. */
- if (context
- && (processing_template_decl
- || current_lang_name != lang_name_cplusplus))
- decl = build_lang_decl (VAR_DECL, declarator, type);
- else
- decl = build_decl (VAR_DECL, declarator, type);
-
- if (context)
- set_decl_namespace (decl, context, 0);
-
- context = DECL_CONTEXT (decl);
- if (declarator && context && current_lang_name != lang_name_c)
- /* We can't mangle lazily here because we don't have any
- way to recover whether or not a variable was `extern
- "C"' later. */
- mangle_decl (decl);
- }
+ if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
+ set_decl_namespace (decl, scope, 0);
+ else
+ DECL_CONTEXT (decl) = scope;
- if (in_namespace)
- set_decl_namespace (decl, in_namespace, 0);
+ if (name && scope && current_lang_name != lang_name_c)
+ /* We can't mangle lazily here because we don't have any
+ way to recover whether or not a variable was `extern
+ "C"' later. */
+ mangle_decl (decl);
if (RIDBIT_SETP (RID_EXTERN, specbits))
{
@@ -9305,6 +9907,16 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
+ if (RIDBIT_SETP (RID_THREAD, specbits))
+ {
+ if (targetm.have_tls)
+ DECL_THREAD_LOCAL (decl) = 1;
+ else
+ /* A mere warning is sure to result in improper semantics
+ at runtime. Don't bother to allow this to compile. */
+ error ("thread-local storage not supported for this target");
+ }
+
if (TREE_PUBLIC (decl))
{
/* [basic.link]: A name with no linkage (notably, the name of a class
@@ -9330,8 +9942,7 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
TYPE, which is a POINTER_TYPE to a METHOD_TYPE. */
tree
-build_ptrmemfunc_type (type)
- tree type;
+build_ptrmemfunc_type (tree type)
{
tree fields[4];
tree t;
@@ -9390,6 +10001,14 @@ build_ptrmemfunc_type (type)
return t;
}
+/* Create and return a pointer to data member type. */
+
+tree
+build_ptrmem_type (tree class_type, tree member_type)
+{
+ return build_pointer_type (build_offset_type (class_type, member_type));
+}
+
/* DECL is a VAR_DECL defined in-class, whose TYPE is also given.
Check to see that the definition is valid. Issue appropriate error
messages. Return 1 if the definition is particularly bad, or 0
@@ -9458,7 +10077,7 @@ compute_array_index_type (name, size)
size, integer_one_node));
}
- /* The size might be the result of a cast. */
+ /* The size might be the result of a cast. */
STRIP_TYPE_NOPS (size);
/* It might be a const variable or enumeration constant. */
@@ -9863,7 +10482,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
break;
case ADDR_EXPR: /* C++ reference declaration */
- /* Fall through. */
+ /* Fall through. */
case ARRAY_REF:
case INDIRECT_REF:
ctype = NULL_TREE;
@@ -9881,6 +10500,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree attributes;
+ if (decl_context != NORMAL)
+ {
+ error ("variable declaration is not allowed here");
+ return error_mark_node;
+ }
+
*next = TREE_OPERAND (decl, 0);
init = CALL_DECLARATOR_PARMS (decl);
@@ -9905,7 +10530,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
else
error ("invalid declarator");
- return 0;
+ return NULL_TREE;
}
innermost_code = TREE_CODE (decl);
if (decl_context == FIELD && ctype == NULL_TREE)
@@ -9913,10 +10538,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
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)))))
+ && constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 0)),
+ ctype)))
TREE_OPERAND (decl, 0) = constructor_name (ctype);
next = &TREE_OPERAND (decl, 0);
decl = *next;
@@ -9947,7 +10570,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
dname = DECL_NAME (get_first_fn (dname));
}
}
- /* Fall through. */
+ /* Fall through. */
case IDENTIFIER_NODE:
if (TREE_CODE (decl) == IDENTIFIER_NODE)
@@ -10022,11 +10645,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
ctype = cname;
}
+ /* If the parser sees something like "void a::b" where
+ "a::b" is a namespace, it will build a SCOPE_REF with
+ a NAMESPACE_DECL, rather than an IDENTIFIER_NODE, as
+ the second operand. Since the SCOPE_REF is being
+ used as a declarator, we recover from that here. */
+ if (TREE_CODE (TREE_OPERAND (decl, 1)) == NAMESPACE_DECL)
+ TREE_OPERAND (decl, 1) = DECL_NAME (TREE_OPERAND (decl, 1));
+
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))))
+ && constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 1)),
+ ctype))
TREE_OPERAND (decl, 1) = constructor_name (ctype);
next = &TREE_OPERAND (decl, 1);
decl = *next;
@@ -10040,8 +10669,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
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)))
+ && constructor_name_p (TREE_OPERAND (decl, 0),
+ ctype))
{
sfk = sfk_destructor;
ctor_return_type = ctype;
@@ -10075,18 +10704,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
next = 0;
break;
+ case BASELINK:
+ next = &BASELINK_FUNCTIONS (decl);
+ break;
+
case TEMPLATE_DECL:
/* Sometimes, we see a template-name used as part of a
decl-specifier like in
- std::allocator alloc;
- Handle that gracefully. */
- error ("invalid use of template-name '%E' in a declarator",
- decl);
+ std::allocator alloc;
+ Handle that gracefully. */
+ error ("invalid use of template-name '%E' in a declarator", decl);
return error_mark_node;
break;
-
+
default:
- internal_error ("`%D' as declarator", decl);
+ my_friendly_assert (0, 20020917);
}
}
}
@@ -10121,7 +10753,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (decl_context == NORMAL && !toplevel_bindings_p ())
{
- struct binding_level *b = current_binding_level;
+ struct cp_binding_level *b = current_binding_level;
current_binding_level = b->level_chain;
if (current_binding_level != 0 && toplevel_bindings_p ())
decl_context = PARM;
@@ -10217,10 +10849,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
}
else if (RIDBIT_SETP (i, specbits))
pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
+
+ /* Diagnose "__thread extern". Recall that this list
+ is in the reverse order seen in the text. */
+ if (i == (int)RID_THREAD)
+ {
+ if (RIDBIT_SETP (RID_EXTERN, specbits))
+ error ("`__thread' before `extern'");
+ if (RIDBIT_SETP (RID_STATIC, specbits))
+ error ("`__thread' before `static'");
+ }
+
if (i == (int)RID_EXTERN
&& TREE_PURPOSE (spec) == error_mark_node)
/* This extern was part of a language linkage. */
extern_langp = 1;
+
RIDBIT_SET (i, specbits);
goto found;
}
@@ -10429,7 +11073,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
else if (type == char_type_node)
type = unsigned_char_type_node;
else if (typedef_decl)
- type = unsigned_type (type);
+ type = c_common_unsigned_type (type);
else
type = unsigned_type_node;
}
@@ -10517,6 +11161,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
if (RIDBIT_SETP (RID_STATIC, specbits)) nclasses++;
if (RIDBIT_SETP (RID_EXTERN, specbits) && !extern_langp) nclasses++;
+ if (RIDBIT_SETP (RID_THREAD, specbits)) nclasses++;
if (decl_context == PARM && nclasses > 0)
error ("storage class specifiers invalid in parameter declarations");
if (RIDBIT_SETP (RID_TYPEDEF, specbits))
@@ -10548,6 +11193,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
+ /* "static __thread" and "extern __thread" are allowed. */
+ if (nclasses == 2
+ && RIDBIT_SETP (RID_THREAD, specbits)
+ && (RIDBIT_SETP (RID_EXTERN, specbits)
+ || RIDBIT_SETP (RID_STATIC, specbits)))
+ nclasses = 1;
+
if (nclasses > 1)
error ("multiple storage classes in declaration of `%s'", name);
else if (decl_context != NORMAL && nclasses > 0)
@@ -10603,6 +11255,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
RIDBIT_RESET (RID_REGISTER, specbits);
RIDBIT_RESET (RID_AUTO, specbits);
RIDBIT_RESET (RID_EXTERN, specbits);
+ RIDBIT_RESET (RID_THREAD, specbits);
}
}
else if (RIDBIT_SETP (RID_EXTERN, specbits) && initialized && !funcdef_flag)
@@ -10625,13 +11278,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (RIDBIT_SETP (RID_AUTO, specbits))
error ("top-level declaration of `%s' specifies `auto'", name);
}
+ else if (RIDBIT_SETP (RID_THREAD, specbits)
+ && !RIDBIT_SETP (RID_EXTERN, specbits)
+ && !RIDBIT_SETP (RID_STATIC, specbits))
+ {
+ error ("function-scope `%s' implicitly auto and declared `__thread'",
+ name);
+ RIDBIT_RESET (RID_THREAD, specbits);
+ }
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). */
+ the declared identifier (or NULL_TREE, in an abstract declarator). */
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
&& TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
@@ -10923,21 +11584,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (TREE_CODE (type) == REFERENCE_TYPE)
{
- error ("cannot declare %s to references",
- TREE_CODE (declarator) == ADDR_EXPR
- ? "references" : "pointers");
- declarator = TREE_OPERAND (declarator, 0);
- continue;
- }
-
- if (TREE_CODE (type) == OFFSET_TYPE
- && (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE
- || TREE_CODE (TREE_TYPE (type)) == REFERENCE_TYPE))
- {
- error ("cannot declare pointer to `%#T' member",
- TREE_TYPE (type));
+ error (TREE_CODE (declarator) == ADDR_EXPR
+ ? "cannot declare reference to `%#T'"
+ : "cannot declare pointer to `%#T'", type);
type = TREE_TYPE (type);
}
+ else if (VOID_TYPE_P (type)
+ && (ctype || TREE_CODE (declarator) == ADDR_EXPR))
+ error (ctype ? "cannot declare pointer to `%#T' member"
+ : "cannot declare reference to `%#T'", type);
/* Merge any constancy or volatility into the target type
for the pointer. */
@@ -10948,13 +11603,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (TREE_CODE (declarator) == ADDR_EXPR)
{
- if (TREE_CODE (type) == VOID_TYPE)
- error ("invalid type: `void &'");
- else
+ if (!VOID_TYPE_P (type))
type = build_reference_type (type);
}
else if (TREE_CODE (type) == METHOD_TYPE)
type = build_ptrmemfunc_type (build_pointer_type (type));
+ else if (ctype)
+ type = build_ptrmem_type (ctype, type);
else
type = build_pointer_type (type);
@@ -11027,7 +11682,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* This needs to be here, in case we are called
multiple times. */ ;
else if (TREE_COMPLEXITY (declarator) == -1)
- /* Namespace member. */
+ /* Namespace member. */
pop_decl_namespace ();
else if (friendp && (TREE_COMPLEXITY (declarator) < 2))
/* Don't fall out into global scope. Hides real bug? --eichin */ ;
@@ -11141,11 +11796,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
ctype, name, current_class_type);
return void_type_node;
}
- type = build_offset_type (ctype, type);
}
else
{
- incomplete_type_error (NULL_TREE, ctype);
+ cxx_incomplete_type_error (NULL_TREE, ctype);
return error_mark_node;
}
@@ -11160,14 +11814,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (declarator && TREE_CODE (declarator) == CALL_EXPR)
/* In this case, we will deal with it later. */
;
- else
- {
- if (TREE_CODE (type) == FUNCTION_TYPE)
- type = build_cplus_method_type (ctype, TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
- else
- type = build_offset_type (ctype, type);
- }
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ type = build_cplus_method_type (ctype, TREE_TYPE (type),
+ TYPE_ARG_TYPES (type));
}
}
break;
@@ -11176,6 +11825,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
declarator = TREE_OPERAND (declarator, 0);
break;
+ case BASELINK:
+ declarator = BASELINK_FUNCTIONS (declarator);
+ break;
+
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
@@ -11213,11 +11866,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type = error_mark_node;
}
- if (decl_context == FIELD
+ if ((decl_context == FIELD || decl_context == PARM)
&& !processing_template_decl
&& variably_modified_type_p (type))
{
- error ("data member may not have variably modified type `%T'", type);
+ if (decl_context == FIELD)
+ error ("data member may not have variably modified type `%T'", type);
+ else
+ error ("parameter may not have variably modified type `%T'", type);
type = error_mark_node;
}
@@ -11231,7 +11887,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
- if (current_class_name == NULL_TREE || decl_context == PARM || friendp)
+ if (decl_context != FIELD || friendp)
{
error ("non-member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
@@ -11384,7 +12040,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
for (args = TYPE_ARG_TYPES (type); args; args = TREE_CHAIN (args))
{
- tree decl = build_decl (PARM_DECL, NULL_TREE, TREE_VALUE (args));
+ tree decl = cp_build_parm_decl (NULL_TREE, TREE_VALUE (args));
TREE_CHAIN (decl) = decls;
decls = decl;
@@ -11417,22 +12073,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
inlinep = 0;
}
- /* Until core issue 180 is resolved, allow 'friend typename A::B'.
- But don't allow implicit typenames except with a class-key. */
- if (!current_aggr && (TREE_CODE (type) != TYPENAME_TYPE
- || IMPLICIT_TYPENAME_P (type)))
+ if (!current_aggr)
{
+ /* Don't allow friend declaration without a class-key. */
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
- pedwarn ("template parameters cannot be friends");
+ pedwarn ("template parameters cannot be friends");
else if (TREE_CODE (type) == TYPENAME_TYPE)
- pedwarn ("\
-friend declaration requires class-key, i.e. `friend class %T::%T'",
- constructor_name (current_class_type),
- TYPE_IDENTIFIER (type));
+ pedwarn ("friend declaration requires class-key, "
+ "i.e. `friend class %T::%D'",
+ TYPE_CONTEXT (type), TYPENAME_TYPE_FULLNAME (type));
else
- pedwarn ("\
-friend declaration requires class-key, i.e. `friend %#T'",
- type);
+ pedwarn ("friend declaration requires class-key, "
+ "i.e. `friend %#T'",
+ type);
}
/* Only try to do this stuff if we didn't already give up. */
@@ -11528,17 +12181,10 @@ friend declaration requires class-key, i.e. `friend %#T'",
if (decl_context == PARM)
{
- decl = build_decl (PARM_DECL, declarator, type);
+ decl = cp_build_parm_decl (declarator, type);
bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
-
- /* Compute the type actually passed in the parmlist,
- for the case where there is no prototype.
- (For example, shorts and chars are passed as ints.)
- When there is a prototype, this is overridden later. */
-
- DECL_ARG_TYPE (decl) = type_promotes_to (type);
}
else if (decl_context == FIELD)
{
@@ -11818,6 +12464,8 @@ friend declaration requires class-key, i.e. `friend %#T'",
error ("storage class `auto' invalid for function `%s'", name);
else if (RIDBIT_SETP (RID_REGISTER, specbits))
error ("storage class `register' invalid for function `%s'", name);
+ else if (RIDBIT_SETP (RID_THREAD, specbits))
+ error ("storage class `__thread' invalid for function `%s'", name);
/* Function declaration not at top level.
Storage classes other than `extern' are not allowed
@@ -11860,23 +12508,23 @@ friend declaration requires class-key, i.e. `friend %#T'",
if (staticp == 1)
{
- int illegal_static = 0;
+ int invalid_static = 0;
/* Don't allow a static member function in a class, and forbid
declaring main to be static. */
if (TREE_CODE (type) == METHOD_TYPE)
{
pedwarn ("cannot declare member function `%D' to have static linkage", decl);
- illegal_static = 1;
+ invalid_static = 1;
}
else if (current_function_decl)
{
/* FIXME need arm citation */
error ("cannot declare static function inside another function");
- illegal_static = 1;
+ invalid_static = 1;
}
- if (illegal_static)
+ if (invalid_static)
{
staticp = 0;
RIDBIT_RESET (RID_STATIC, specbits);
@@ -11891,7 +12539,7 @@ friend declaration requires class-key, i.e. `friend %#T'",
decl = grokvardecl (type, declarator, &specbits,
initialized,
(type_quals & TYPE_QUAL_CONST) != 0,
- in_namespace);
+ ctype ? ctype : in_namespace);
bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@@ -11983,13 +12631,16 @@ require_complete_types_for_parms (parms)
/* grokparms will have already issued an error */
TREE_TYPE (parms) = error_mark_node;
else if (complete_type_or_else (TREE_TYPE (parms), parms))
- layout_decl (parms, 0);
+ {
+ layout_decl (parms, 0);
+ DECL_ARG_TYPE (parms) = type_passed_as (TREE_TYPE (parms));
+ }
else
TREE_TYPE (parms) = error_mark_node;
}
}
-/* Returns non-zero if T is a local variable. */
+/* Returns nonzero if T is a local variable. */
int
local_variable_p (t)
@@ -12007,7 +12658,7 @@ local_variable_p (t)
return 0;
}
-/* Returns non-zero if T is an automatic local variable or a label.
+/* Returns nonzero if T is an automatic local variable or a label.
(These are the declarations that need to be remapped when the code
containing them is duplicated.) */
@@ -12034,7 +12685,7 @@ local_variable_p_walkfn (tp, walk_subtrees, data)
}
/* Check that ARG, which is a default-argument expression for a
- parameter DECL, is legal. Returns ARG, or ERROR_MARK_NODE, if
+ parameter DECL, is valid. Returns ARG, or ERROR_MARK_NODE, if
something goes wrong. DECL may also be a _TYPE node, rather than a
DECL, if there is no DECL available. */
@@ -12173,7 +12824,7 @@ grokparms (first_parm)
&& !DECL_NAME (decl) && !result && !chain && !ellipsis)
/* this is a parmlist of `(void)', which is ok. */
break;
- incomplete_type_error (decl, type);
+ cxx_incomplete_type_error (decl, type);
/* It's not a good idea to actually create parameters of
type `void'; other parts of the compiler assume that a
void type terminates the parameter list. */
@@ -12199,7 +12850,7 @@ grokparms (first_parm)
TREE_TYPE (decl) = type;
}
else if (abstract_virtuals_error (decl, type))
- any_error = 1; /* Seems like a good idea. */
+ any_error = 1; /* Seems like a good idea. */
else if (POINTER_TYPE_P (type))
{
/* [dcl.fct]/6, parameter types cannot contain pointers
@@ -12222,11 +12873,6 @@ grokparms (first_parm)
decl, ptr ? "pointer" : "reference", t);
}
- DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
- if (PROMOTE_PROTOTYPES
- && INTEGRAL_TYPE_P (type)
- && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (decl) = integer_type_node;
if (!any_error && init)
init = check_default_argument (decl, init);
else
@@ -12262,7 +12908,7 @@ grokparms (first_parm)
first parameter is a reference to non-const qualified T.
This function can be used as a predicate. Positive values indicate
- a copy constructor and non-zero values indicate a copy assignment
+ a copy constructor and nonzero values indicate a copy assignment
operator. */
int
@@ -12567,7 +13213,7 @@ grok_op_properties (decl, friendp)
}
if (operator_code == CALL_EXPR)
- return; /* No restrictions on args. */
+ return; /* No restrictions on args. */
if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
{
@@ -12590,7 +13236,7 @@ grok_op_properties (decl, friendp)
&& DERIVED_FROM_P (t, current_class_type))
what = "a base class";
- if (what)
+ if (what && warn_conversion)
warning ("conversion to %s%s will never use a type conversion operator",
ref ? "a reference to " : "", what);
}
@@ -12771,6 +13417,38 @@ tag_name (code)
}
}
+/* Name lookup in an elaborated-type-specifier (after the keyword
+ indicated by TAG_CODE) has found TYPE. If the
+ elaborated-type-specifier is invalid, issue a diagnostic and return
+ error_mark_node; otherwise, return TYPE itself. */
+
+static tree
+check_elaborated_type_specifier (enum tag_types tag_code,
+ tree type)
+{
+ tree t;
+
+ t = follow_tag_typedef (type);
+
+ /* [dcl.type.elab] If the identifier resolves to a typedef-name or a
+ template type-parameter, the elaborated-type-specifier is
+ ill-formed. */
+ if (!t)
+ {
+ error ("using typedef-name `%D' after `%s'",
+ TYPE_NAME (type), tag_name (tag_code));
+ t = error_mark_node;
+ }
+ else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+ {
+ error ("using template type parameter `%T' after `%s'",
+ type, tag_name (tag_code));
+ t = error_mark_node;
+ }
+
+ return t;
+}
+
/* Get the struct, enum or union (CODE says which) with tag NAME.
Define the tag as a forward-reference if it is not defined.
@@ -12782,29 +13460,16 @@ tag_name (code)
scope.) */
tree
-xref_tag (code_type_node, name, globalize)
- tree code_type_node;
- tree name;
- int globalize;
+xref_tag (enum tag_types tag_code, tree name, tree attributes,
+ bool globalize)
{
- enum tag_types tag_code;
enum tree_code code;
register tree ref, t;
- struct binding_level *b = current_binding_level;
- tree attributes = NULL_TREE;
+ struct cp_binding_level *b = current_binding_level;
tree context = NULL_TREE;
- /* If we are called from the parser, code_type_node will sometimes be a
- TREE_LIST. This indicates that the user wrote
- "class __attribute__ ((foo)) bar". Extract the attributes so we can
- use them later. */
- if (TREE_CODE (code_type_node) == TREE_LIST)
- {
- attributes = TREE_PURPOSE (code_type_node);
- code_type_node = TREE_VALUE (code_type_node);
- }
+ timevar_push (TV_NAME_LOOKUP);
- tag_code = (enum tag_types) tree_low_cst (code_type_node, 1);
switch (tag_code)
{
case record_type:
@@ -12846,7 +13511,7 @@ xref_tag (code_type_node, name, globalize)
TYPE_IDENTIFIER (t));
/* We need to remove the class scope binding for the
- TYPENAME_TYPE as otherwise poplevel_class gets confused. */
+ TYPENAME_TYPE as otherwise poplevel_class gets confused. */
for (shadowed = b->class_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
@@ -12871,20 +13536,9 @@ xref_tag (code_type_node, name, globalize)
{
if (t)
{
- ref = follow_tag_typedef (t);
-
- /* [dcl.type.elab] If the identifier resolves to a
- typedef-name or a template type-parameter, the
- elaborated-type-specifier is ill-formed. */
- if (!ref)
- {
- pedwarn ("using typedef-name `%D' after `%s'",
- TYPE_NAME (t), tag_name (tag_code));
- ref = t;
- }
- else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
- error ("using template type parameter `%T' after `%s'",
- t, tag_name (tag_code));
+ ref = check_elaborated_type_specifier (tag_code, t);
+ if (ref == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
else
ref = lookup_tag (code, name, b, 0);
@@ -12903,9 +13557,15 @@ xref_tag (code_type_node, name, globalize)
template, so we want this type. */
ref = DECL_TEMPLATE_RESULT (ref);
- if (ref && TREE_CODE (ref) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (ref)) == code)
- ref = TREE_TYPE (ref);
+ if (ref && TREE_CODE (ref) == TYPE_DECL)
+ {
+ ref = check_elaborated_type_specifier (tag_code,
+ TREE_TYPE (ref));
+ if (ref == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+ if (ref && TREE_CODE (ref) != code)
+ ref = NULL_TREE;
+ }
else
ref = NULL_TREE;
}
@@ -12914,7 +13574,7 @@ xref_tag (code_type_node, name, globalize)
&& template_class_depth (current_class_type)
&& PROCESSING_REAL_TEMPLATE_DECL_P ())
{
- /* Since GLOBALIZE is non-zero, we are not looking at a
+ /* Since GLOBALIZE is nonzero, we are not looking at a
definition of this tag. Since, in addition, we are currently
processing a (member) template declaration of a template
class, we must be very careful; consider:
@@ -12986,14 +13646,14 @@ xref_tag (code_type_node, name, globalize)
}
else
{
- struct binding_level *old_b = class_binding_level;
+ struct cp_binding_level *old_b = class_binding_level;
ref = make_aggr_type (code);
TYPE_CONTEXT (ref) = context;
#ifdef NONNESTED_CLASSES
/* Class types don't nest the way enums do. */
- class_binding_level = (struct binding_level *)0;
+ class_binding_level = (struct cp_binding_level *)0;
#endif
pushtag (name, ref, globalize);
class_binding_level = old_b;
@@ -13007,7 +13667,7 @@ xref_tag (code_type_node, name, globalize)
TYPE_ATTRIBUTES (ref) = attributes;
- return ref;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ref);
}
tree
@@ -13015,18 +13675,17 @@ xref_tag_from_type (old, id, globalize)
tree old, id;
int globalize;
{
- tree code_type_node;
+ enum tag_types tag_kind;
if (TREE_CODE (old) == RECORD_TYPE)
- code_type_node = (CLASSTYPE_DECLARED_CLASS (old)
- ? class_type_node : record_type_node);
+ tag_kind = (CLASSTYPE_DECLARED_CLASS (old) ? class_type : record_type);
else
- code_type_node = union_type_node;
+ tag_kind = union_type;
if (id == NULL_TREE)
id = TYPE_IDENTIFIER (old);
- return xref_tag (code_type_node, id, globalize);
+ return xref_tag (tag_kind, id, /*attributes=*/NULL_TREE, globalize);
}
/* REF is a type (named NAME), for which we have just seen some
@@ -13036,9 +13695,7 @@ xref_tag_from_type (old, id, globalize)
struct, or union. */
void
-xref_basetypes (code_type_node, name, ref, binfo)
- tree code_type_node;
- tree name ATTRIBUTE_UNUSED;
+xref_basetypes (ref, binfo)
tree ref;
tree binfo;
{
@@ -13050,21 +13707,14 @@ xref_basetypes (code_type_node, name, ref, binfo)
int i, len;
enum tag_types tag_code;
- /* If we are called from the parser, code_type_node will sometimes be a
- TREE_LIST. This indicates that the user wrote
- "class __attribute__ ((foo)) bar". Extract the attributes so that
- tree_low_cst doesn't crash. */
- if (TREE_CODE (code_type_node) == TREE_LIST)
- code_type_node = TREE_VALUE (code_type_node);
-
- tag_code = (enum tag_types) tree_low_cst (code_type_node, 1);
-
- if (tag_code == union_type)
+ if (TREE_CODE (ref) == UNION_TYPE)
{
error ("derived union `%T' invalid", ref);
return;
}
+ tag_code = (CLASSTYPE_DECLARED_CLASS (ref) ? class_type : record_type);
+
len = list_length (binfo);
/* First, make sure that any templates in base-classes are
@@ -13225,7 +13875,7 @@ start_enum (name)
tree name;
{
register tree enumtype = NULL_TREE;
- struct binding_level *b = current_binding_level;
+ struct cp_binding_level *b = current_binding_level;
/* If this is the real definition for a previous forward reference,
fill in the contents in the same object that used to be the
@@ -13270,47 +13920,56 @@ finish_enum (enumtype)
/* We built up the VALUES in reverse order. */
TYPE_VALUES (enumtype) = nreverse (TYPE_VALUES (enumtype));
- /* [dcl.enum]
-
- Following the closing brace of an enum-specifier, each
- enumerator has the type of its enumeration. Prior to the
- closing brace, the type of each enumerator is the type of
- its initializing value. */
- for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
- TREE_TYPE (TREE_VALUE (pair)) = enumtype;
-
- /* For a enum defined in a template, all further processing is
- postponed until the template is instantiated. */
+ /* For an enum defined in a template, just set the type of the values;
+ all further processing is postponed until the template is
+ instantiated. We need to set the type so that tsubst of a CONST_DECL
+ works. */
if (processing_template_decl)
{
- tree scope = current_scope ();
- if (scope && TREE_CODE (scope) == FUNCTION_DECL)
+ for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
+ TREE_TYPE (TREE_VALUE (pair)) = enumtype;
+ if (at_function_scope_p ())
add_stmt (build_min (TAG_DEFN, enumtype));
-
-
return;
}
- /* Figure out what the minimum and maximum values of the enumerators
- are. */
if (TYPE_VALUES (enumtype))
{
minnode = maxnode = NULL_TREE;
- for (pair = TYPE_VALUES (enumtype);
- pair;
- pair = TREE_CHAIN (pair))
+ for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
{
- tree value;
+ tree decl = TREE_VALUE (pair);
+ tree value = DECL_INITIAL (decl);
- value = DECL_INITIAL (TREE_VALUE (pair));
+ /* [dcl.enum]: Following the closing brace of an enum-specifier,
+ each enumerator has the type of its enumeration. Prior to the
+ closing brace, the type of each enumerator is the type of its
+ initializing value. */
+ TREE_TYPE (decl) = enumtype;
+ /* Figure out what the minimum and maximum values of the
+ enumerators are. */
if (!minnode)
minnode = maxnode = value;
else if (tree_int_cst_lt (maxnode, value))
maxnode = value;
else if (tree_int_cst_lt (value, minnode))
minnode = value;
+
+ /* Set the TREE_TYPE for the values as well. That's so that when
+ we call decl_constant_value we get an entity of the right type
+ (but with the constant value). But first make a copy so we
+ don't clobber shared INTEGER_CSTs. */
+ if (TREE_TYPE (value) != enumtype)
+ {
+ value = DECL_INITIAL (decl) = copy_node (value);
+ TREE_TYPE (value) = enumtype;
+ }
+
+ /* In addition, transform the TYPE_VALUES list to contain the
+ values, rather than the CONST_DECLs for them. */
+ TREE_VALUE (pair) = value;
}
}
else
@@ -13325,36 +13984,36 @@ finish_enum (enumtype)
highprec = min_precision (maxnode, unsignedp);
precision = MAX (lowprec, highprec);
- /* Set the TREE_TYPE for the values as well. That's so that when we
- call decl_constant_value we get an entity of the right type (but
- with the constant value). In addition, transform the TYPE_VALUES
- list to contain the values, rather than the CONST_DECLs for them. */
- for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
+ /* DR 377
+
+ IF no integral type can represent all the enumerator values, the
+ enumeration is ill-formed. */
+ if (precision > TYPE_PRECISION (long_long_integer_type_node))
{
- tree value = DECL_INITIAL (TREE_VALUE (pair));
-
- TREE_TYPE (value) = enumtype;
- TREE_VALUE (pair) = value;
+ error ("no integral type can represent all of the enumerator values "
+ "for `%T'", enumtype);
+ precision = TYPE_PRECISION (long_long_integer_type_node);
}
- /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */
- TYPE_SIZE (enumtype) = NULL_TREE;
+ /* Compute the minium and maximum values for the type, the size of
+ the type, and so forth. */
TYPE_PRECISION (enumtype) = precision;
+ TYPE_SIZE (enumtype) = NULL_TREE;
if (unsignedp)
fixup_unsigned_type (enumtype);
else
fixup_signed_type (enumtype);
- if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node)))
- /* Use the width of the narrowest normal C type which is wide
- enough. */
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size
- (precision, 1));
- else
- TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
-
- TYPE_SIZE (enumtype) = NULL_TREE;
- layout_type (enumtype);
+ /* We use "int" or "unsigned int" as the underlying type, unless all
+ the values will not fit or the user has requested that we try to
+ use shorter types where possible. */
+ if (precision < TYPE_PRECISION (integer_type_node)
+ && !flag_short_enums)
+ {
+ TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
+ TYPE_SIZE (enumtype) = NULL_TREE;
+ layout_type (enumtype);
+ }
/* Fix up all variant types of this enum type. */
for (t = TYPE_MAIN_VARIANT (enumtype); t; t = TYPE_NEXT_VARIANT (t))
@@ -13388,7 +14047,6 @@ build_enumerator (name, value, enumtype)
tree decl;
tree context;
tree type;
- tree values;
/* Remove no-op casts from the value. */
if (value)
@@ -13420,7 +14078,7 @@ build_enumerator (name, value, enumtype)
if (TYPE_VALUES (enumtype))
{
- /* The next value is the previous value ... */
+ /* The next value is the previous value ... */
prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
/* ... plus one. */
value = cp_build_binary_op (PLUS_EXPR,
@@ -13435,26 +14093,9 @@ build_enumerator (name, value, enumtype)
}
/* Remove no-op casts from the value. */
- if (value)
- STRIP_TYPE_NOPS (value);
-#if 0
- /* To fix MAX_VAL enum consts. (bkoz) */
- TREE_TYPE (value) = integer_type_node;
-#endif
+ STRIP_TYPE_NOPS (value);
}
- /* We always have to copy here; not all INTEGER_CSTs are unshared.
- Even in other cases, we will later (in finish_enum) be setting
- the type of VALUE. But, we don't need to make a copy if this
- VALUE is one of the enumeration constants for this same
- enumeration type. */
- for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
- if (TREE_VALUE (values) == value)
- break;
- /* If we didn't break out of the loop, then we do need a copy. */
- if (!values && value)
- value = copy_node (value);
-
/* C++ associates enums with global, function, or class declarations. */
context = current_scope ();
@@ -13470,7 +14111,7 @@ build_enumerator (name, value, enumtype)
initializing value.
In finish_enum we will reset the type. Of course, if we're
- processing a template, there may be no value. */
+ processing a template, there may be no value. */
type = value ? TREE_TYPE (value) : NULL_TREE;
if (context && context == current_class_type)
@@ -13569,10 +14210,8 @@ start_function (declspecs, declarator, attrs, flags)
tree ctype = NULL_TREE;
tree fntype;
tree restype;
- extern int have_extern_spec;
- extern int used_extern_spec;
int doing_friend = 0;
- struct binding_level *bl;
+ struct cp_binding_level *bl;
tree current_function_parms;
/* Sanity check. */
@@ -13580,10 +14219,10 @@ start_function (declspecs, declarator, attrs, flags)
my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
/* This should only be done once on the top most decl. */
- if (have_extern_spec && !used_extern_spec)
+ if (have_extern_spec)
{
declspecs = tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);
- used_extern_spec = 1;
+ have_extern_spec = false;
}
if (flags & SF_PRE_PARSED)
@@ -13622,7 +14261,7 @@ start_function (declspecs, declarator, attrs, flags)
cplus_decl_attributes (&decl1, attrs, 0);
/* If #pragma weak was used, mark the decl weak now. */
- if (current_binding_level == global_binding_level)
+ if (global_scope_p (current_binding_level))
maybe_apply_pragma_weak (decl1);
fntype = TREE_TYPE (decl1);
@@ -13781,7 +14420,7 @@ start_function (declspecs, declarator, attrs, flags)
decl1 = pushdecl (decl1);
else
{
- /* We need to set the DECL_CONTEXT. */
+ /* We need to set the DECL_CONTEXT. */
if (!DECL_CONTEXT (decl1) && DECL_TEMPLATE_INFO (decl1))
DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1));
/* And make sure we have enough default args. */
@@ -13796,12 +14435,8 @@ start_function (declspecs, declarator, attrs, flags)
/* If we are (erroneously) defining a function that we have already
defined before, wipe out what we knew before. */
- if (!DECL_PENDING_INLINE_P (decl1)
- && DECL_SAVED_FUNCTION_DATA (decl1))
- {
- free (DECL_SAVED_FUNCTION_DATA (decl1));
- DECL_SAVED_FUNCTION_DATA (decl1) = NULL;
- }
+ if (!DECL_PENDING_INLINE_P (decl1))
+ DECL_SAVED_FUNCTION_DATA (decl1) = NULL;
if (ctype && !doing_friend && !DECL_STATIC_FUNCTION_P (decl1))
{
@@ -13983,7 +14618,6 @@ store_parm_decls (current_function_parms)
function. This is all and only the PARM_DECLs that were
pushed into scope by the loop above. */
DECL_ARGUMENTS (fndecl) = getdecls ();
- storetags (gettags ());
}
else
DECL_ARGUMENTS (fndecl) = NULL_TREE;
@@ -14010,7 +14644,7 @@ static void
save_function_data (decl)
tree decl;
{
- struct cp_language_function *f;
+ struct language_function *f;
/* Save the language-specific per-function data so that we can
get it back when we really expand this function. */
@@ -14018,9 +14652,9 @@ save_function_data (decl)
19990908);
/* Make a copy. */
- f = ((struct cp_language_function *)
- xmalloc (sizeof (struct cp_language_function)));
- memcpy (f, cp_function_chain, sizeof (struct cp_language_function));
+ f = ((struct language_function *)
+ ggc_alloc (sizeof (struct language_function)));
+ memcpy (f, cp_function_chain, sizeof (struct language_function));
DECL_SAVED_FUNCTION_DATA (decl) = f;
/* Clear out the bits we don't need. */
@@ -14050,9 +14684,6 @@ save_function_data (decl)
static void
begin_constructor_body ()
{
- tree ctor_stmt = build_stmt (CTOR_STMT);
- CTOR_BEGIN_P (ctor_stmt) = 1;
- add_stmt (ctor_stmt);
}
/* Add a note to mark the end of the main body of the constructor. This is
@@ -14062,12 +14693,6 @@ begin_constructor_body ()
static void
finish_constructor_body ()
{
- /* Mark the end of the cleanups for a partially constructed object.
-
- ??? These should really be handled automatically by closing the block,
- as with the destructor cleanups; the only difference is that these are
- only run if an exception is thrown. */
- add_stmt (build_stmt (CTOR_STMT));
}
/* Do all the processing for the beginning of a destructor; set up the
@@ -14100,7 +14725,6 @@ begin_destructor_body ()
appropriately, so we just assume that we always need to
initialize the vtables.) */
finish_if_stmt_cond (boolean_true_node, if_stmt);
- current_vcalls_possible_p = &IF_COND (if_stmt);
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
@@ -14112,6 +14736,10 @@ begin_destructor_body ()
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
finish_then_clause (if_stmt);
finish_if_stmt ();
+
+ /* And insert cleanups for our bases and members so that they
+ will be properly destroyed if we throw. */
+ push_base_cleanups ();
}
/* At the end of every destructor we generate code to delete the object if
@@ -14126,14 +14754,11 @@ finish_destructor_body ()
and member cleanups will be run when the function returns. */
add_stmt (build_stmt (LABEL_STMT, dtor_label));
- /* And perform cleanups for our bases and members. */
- perform_base_cleanups ();
-
/* In a virtual destructor, we must call delete. */
if (DECL_VIRTUAL_P (current_function_decl))
{
tree if_stmt;
- tree virtual_size = c_sizeof (current_class_type);
+ tree virtual_size = cxx_sizeof (current_class_type);
/* [class.dtor]
@@ -14236,6 +14861,15 @@ finish_function (flags)
if (fndecl == NULL_TREE)
return error_mark_node;
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
+ && DECL_VIRTUAL_P (fndecl)
+ && !processing_template_decl)
+ {
+ tree fnclass = DECL_CONTEXT (fndecl);
+ if (fndecl == CLASSTYPE_KEY_METHOD (fnclass))
+ keyed_classes = tree_cons (NULL_TREE, fnclass, keyed_classes);
+ }
+
nested = function_depth > 1;
fntype = TREE_TYPE (fndecl);
@@ -14273,6 +14907,12 @@ finish_function (flags)
/* If we're saving up tree structure, tie off the function now. */
finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+ /* If this function can't throw any exceptions, remember that. */
+ if (!processing_template_decl
+ && !cp_function_chain->can_throw
+ && !flag_non_call_exceptions)
+ TREE_NOTHROW (fndecl) = 1;
+
/* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into
this function's blocks. */
@@ -14307,11 +14947,20 @@ finish_function (flags)
if (current_function_return_value)
{
tree r = current_function_return_value;
- /* This is only worth doing for fns that return in memory--and
- simpler, since we don't have to worry about promoted modes. */
+ tree outer;
+
if (r != error_mark_node
- && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
+ /* This is only worth doing for fns that return in memory--and
+ simpler, since we don't have to worry about promoted modes. */
+ && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl)))
+ /* Only allow this for variables declared in the outer scope of
+ the function so we know that their lifetime always ends with a
+ return; see g++.dg/opt/nrv6.C. We could be more flexible if
+ we were to do this optimization in tree-ssa. */
+ && (outer = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl)),
+ chain_member (r, BLOCK_VARS (outer))))
{
+
DECL_ALIGN (r) = DECL_ALIGN (DECL_RESULT (fndecl));
walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
nullify_returns_r, r);
@@ -14369,7 +15018,7 @@ finish_function (flags)
free_after_compilation (cfun);
cfun = NULL;
- /* If this is a in-class inline definition, we may have to pop the
+ /* If this is an in-class inline definition, we may have to pop the
bindings for the template parameters that we added in
maybe_begin_member_template_processing when start_function was
called. */
@@ -14386,7 +15035,7 @@ finish_function (flags)
if (! nested)
/* Let the error reporting routines know that we're outside a
function. For a nested function, this value is used in
- pop_cp_function_context and then reset via pop_function_context. */
+ cxx_pop_function_context and then reset via pop_function_context. */
current_function_decl = NULL_TREE;
return fndecl;
@@ -14451,6 +15100,7 @@ start_method (declspecs, declarator, attrlist)
DECL_DECLARED_INLINE_P (fndecl) = 1;
+ DID_INLINE_FUNC (fndecl) = 0;
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
@@ -14598,7 +15248,7 @@ complete_vars (type)
here. */
tree
-maybe_build_cleanup (decl)
+cxx_maybe_build_cleanup (decl)
tree decl;
{
tree type = TREE_TYPE (decl);
@@ -14612,7 +15262,7 @@ maybe_build_cleanup (decl)
rval = decl;
else
{
- mark_addressable (decl);
+ cxx_mark_addressable (decl);
rval = build_unary_op (ADDR_EXPR, decl, 0);
}
@@ -14675,14 +15325,14 @@ revert_static_member_fn (decl)
/* Initialize the variables used during compilation of a C++
function. */
-static void
-push_cp_function_context (f)
+void
+cxx_push_function_context (f)
struct function *f;
{
- struct cp_language_function *p
- = ((struct cp_language_function *)
- xcalloc (1, sizeof (struct cp_language_function)));
- f->language = (struct language_function *) p;
+ struct language_function *p
+ = ((struct language_function *)
+ ggc_alloc_cleared (sizeof (struct language_function)));
+ f->language = p;
/* It takes an explicit call to expand_body to generate RTL for a
function. */
@@ -14696,141 +15346,30 @@ push_cp_function_context (f)
/* Free the language-specific parts of F, now that we've finished
compiling the function. */
-static void
-pop_cp_function_context (f)
+void
+cxx_pop_function_context (f)
struct function *f;
{
- if (f->language)
- {
- struct cp_language_function *cp =
- (struct cp_language_function *) f->language;
- if (cp->x_local_names)
- VARRAY_FREE (cp->x_local_names);
- free (f->language);
- }
f->language = 0;
}
-/* Mark P for GC. */
+/* Return which tree structure is used by T, or TS_CP_GENERIC if T is
+ one of the language-independent trees. */
-static void
-mark_lang_function (p)
- struct cp_language_function *p;
+enum cp_tree_node_structure_enum
+cp_tree_node_structure (t)
+ union lang_tree_node *t;
{
- if (!p)
- return;
-
- mark_c_language_function (&p->base);
-
- ggc_mark_tree (p->x_dtor_label);
- ggc_mark_tree (p->x_current_class_ptr);
- ggc_mark_tree (p->x_current_class_ref);
- ggc_mark_tree (p->x_eh_spec_block);
- ggc_mark_tree_varray (p->x_local_names);
-
- mark_named_label_lists (&p->x_named_labels, &p->x_named_label_uses);
- mark_binding_level (&p->bindings);
- mark_pending_inlines (&p->unparsed_inlines);
-}
-
-/* Mark the language-specific data in F for GC. */
-
-static void
-mark_cp_function_context (f)
- struct function *f;
-{
- mark_lang_function ((struct cp_language_function *) f->language);
-}
-
-void
-lang_mark_tree (t)
- tree t;
-{
- enum tree_code code = TREE_CODE (t);
- if (code == IDENTIFIER_NODE)
- {
- struct lang_identifier *li = (struct lang_identifier *) t;
- struct lang_id2 *li2 = li->x;
- ggc_mark_tree (li->namespace_bindings);
- ggc_mark_tree (li->bindings);
- ggc_mark_tree (li->class_value);
- ggc_mark_tree (li->class_template_info);
-
- if (li2)
- {
- ggc_mark_tree (li2->label_value);
- ggc_mark_tree (li2->implicit_decl);
- ggc_mark_tree (li2->error_locus);
- }
- }
- else if (code == CPLUS_BINDING)
+ switch (TREE_CODE (&t->generic))
{
- if (BINDING_HAS_LEVEL_P (t))
- mark_binding_level (&BINDING_LEVEL (t));
- else
- ggc_mark_tree (BINDING_SCOPE (t));
- ggc_mark_tree (BINDING_VALUE (t));
- }
- else if (code == OVERLOAD)
- ggc_mark_tree (OVL_FUNCTION (t));
- else if (code == TEMPLATE_PARM_INDEX)
- ggc_mark_tree (TEMPLATE_PARM_DECL (t));
- else if (TREE_CODE_CLASS (code) == 'd')
- {
- struct lang_decl *ld = DECL_LANG_SPECIFIC (t);
-
- if (ld)
- {
- ggc_mark (ld);
- c_mark_lang_decl (&ld->decl_flags.base);
- if (!DECL_GLOBAL_CTOR_P (t)
- && !DECL_GLOBAL_DTOR_P (t)
- && !DECL_THUNK_P (t)
- && !DECL_DISCRIMINATOR_P (t))
- ggc_mark_tree (ld->decl_flags.u2.access);
- else if (DECL_THUNK_P (t))
- ggc_mark_tree (ld->decl_flags.u2.vcall_offset);
- if (TREE_CODE (t) != NAMESPACE_DECL)
- ggc_mark_tree (ld->decl_flags.u.template_info);
- else
- mark_binding_level (&NAMESPACE_LEVEL (t));
- if (CAN_HAVE_FULL_LANG_DECL_P (t))
- {
- ggc_mark_tree (ld->befriending_classes);
- ggc_mark_tree (ld->context);
- ggc_mark_tree (ld->cloned_function);
- if (TREE_CODE (t) == TYPE_DECL)
- ggc_mark_tree (ld->u.sorted_fields);
- else if (TREE_CODE (t) == FUNCTION_DECL
- && !DECL_PENDING_INLINE_P (t))
- mark_lang_function (DECL_SAVED_FUNCTION_DATA (t));
- }
- }
- }
- else if (TREE_CODE_CLASS (code) == 't')
- {
- struct lang_type *lt = TYPE_LANG_SPECIFIC (t);
-
- if (lt && !(TREE_CODE (t) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE))
- {
- ggc_mark (lt);
- ggc_mark_tree (lt->primary_base);
- ggc_mark_tree (lt->vfields);
- ggc_mark_tree (lt->vbases);
- ggc_mark_tree (lt->tags);
- ggc_mark_tree (lt->size);
- ggc_mark_tree (lt->pure_virtuals);
- ggc_mark_tree (lt->friend_classes);
- ggc_mark_tree (lt->rtti);
- ggc_mark_tree (lt->methods);
- ggc_mark_tree (lt->template_info);
- ggc_mark_tree (lt->befriending_classes);
- }
- else if (lt)
- /* In the case of pointer-to-member function types, the
- TYPE_LANG_SPECIFIC is really just a tree. */
- ggc_mark_tree ((tree) lt);
+ case DEFAULT_ARG: return TS_CP_IDENTIFIER;
+ case IDENTIFIER_NODE: return TS_CP_IDENTIFIER;
+ case OVERLOAD: return TS_CP_OVERLOAD;
+ case TEMPLATE_PARM_INDEX: return TS_CP_TPI;
+ case PTRMEM_CST: return TS_CP_PTRMEM;
+ case WRAPPER: return TS_CP_WRAPPER;
+ case SRCLOC: return TS_CP_SRCLOC;
+ default: return TS_CP_GENERIC;
}
}
@@ -14860,3 +15399,6 @@ cp_missing_noreturn_ok_p (decl)
/* A missing noreturn is ok for the `main' function. */
return DECL_MAIN_P (decl);
}
+
+#include "gt-cp-decl.h"
+#include "gtype-cp.h"
diff --git a/contrib/gcc/cp/decl.h b/contrib/gcc/cp/decl.h
index 2316f06..2b917a4 100644
--- a/contrib/gcc/cp/decl.h
+++ b/contrib/gcc/cp/decl.h
@@ -36,13 +36,7 @@ extern tree grokdeclarator PARAMS ((tree, tree, enum decl_context, int,
/* Parsing a function declarator leaves a list of parameter names
or a chain or parameter decls here. */
-extern tree last_function_parms;
-
-/* A list of objects which have constructors or destructors
- which reside in the global scope. The decl is stored in
- the TREE_VALUE slot and the initializer is stored
- in the TREE_PURPOSE slot. */
-extern tree static_aggregates;
+extern GTY(()) tree last_function_parms;
#ifdef DEBUG_CP_BINDING_LEVELS
/* Purely for debugging purposes. */
diff --git a/contrib/gcc/cp/decl2.c b/contrib/gcc/cp/decl2.c
index 1dbaaf4..452f9ad 100644
--- a/contrib/gcc/cp/decl2.c
+++ b/contrib/gcc/cp/decl2.c
@@ -1,6 +1,6 @@
/* Process declarations and variables for C compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -44,26 +44,26 @@ Boston, MA 02111-1307, USA. */
#include "timevar.h"
#include "cpplib.h"
#include "target.h"
+#include "c-common.h"
+#include "timevar.h"
extern cpp_reader *parse_in;
/* This structure contains information about the initializations
and/or destructions required for a particular priority level. */
typedef struct priority_info_s {
- /* Non-zero if there have been any initializations at this priority
+ /* Nonzero if there have been any initializations at this priority
throughout the translation unit. */
int initializations_p;
- /* Non-zero if there have been any destructions at this priority
+ /* Nonzero if there have been any destructions at this priority
throughout the translation unit. */
int destructions_p;
} *priority_info;
static void mark_vtable_entries PARAMS ((tree));
static void grok_function_init PARAMS ((tree, tree));
-static int finish_vtable_vardecl PARAMS ((tree *, void *));
-static int prune_vtable_vardecl PARAMS ((tree *, void *));
-static int is_namespace_ancestor PARAMS ((tree, tree));
+static int maybe_emit_vtables (tree);
static void add_using_namespace PARAMS ((tree, tree, int));
-static tree ambiguous_decl PARAMS ((tree, tree, tree,int));
+static cxx_binding *ambiguous_decl (tree, cxx_binding *, cxx_binding *,int);
static tree build_anon_union_vars PARAMS ((tree, tree*, int, int));
static int acceptable_java_type PARAMS ((tree));
static void output_vtable_inherit PARAMS ((tree));
@@ -84,23 +84,21 @@ static void finish_static_initialization_or_destruction PARAMS ((tree));
static void generate_ctor_or_dtor_function PARAMS ((int, int));
static int generate_ctor_and_dtor_functions_for_priority
PARAMS ((splay_tree_node, void *));
-static tree prune_vars_needing_no_initialization PARAMS ((tree));
+static tree prune_vars_needing_no_initialization PARAMS ((tree *));
static void write_out_vars PARAMS ((tree));
static void import_export_class PARAMS ((tree));
-static tree key_method PARAMS ((tree));
-static int compare_options PARAMS ((const PTR, const PTR));
static tree get_guard_bits PARAMS ((tree));
/* A list of static class variables. This is needed, because a
static class variable can be declared inside the class without
an initializer, and then initialized, statically, outside the class. */
-static varray_type pending_statics;
+static GTY(()) varray_type pending_statics;
#define pending_statics_used \
(pending_statics ? pending_statics->elements_used : 0)
/* A list of functions which were declared inline, but which we
may need to emit outline anyway. */
-static varray_type deferred_fns;
+static GTY(()) varray_type deferred_fns;
#define deferred_fns_used \
(deferred_fns ? deferred_fns->elements_used : 0)
@@ -117,623 +115,10 @@ int at_eof;
tree static_ctors;
tree static_dtors;
-/* The :: namespace. */
+/* The :: namespace. */
tree global_namespace;
-/* C (and C++) language-specific option variables. */
-
-/* Nonzero means don't recognize the keyword `asm'. */
-
-int flag_no_asm;
-
-/* Nonzero means don't recognize any extension keywords. */
-
-int flag_no_gnu_keywords;
-
-/* Nonzero means do some things the same way PCC does. Only provided so
- the compiler will link. */
-
-int flag_traditional;
-
-/* Nonzero means to treat bitfields as unsigned unless they say `signed'. */
-
-int flag_signed_bitfields = 1;
-
-/* Nonzero means enable obscure standard features and disable GNU
- extensions that might cause standard-compliant code to be
- miscompiled. */
-
-int flag_ansi;
-
-/* Nonzero means do emit exported implementations of functions even if
- they can be inlined. */
-
-int flag_implement_inlines = 1;
-
-/* Nonzero means do emit exported implementations of templates, instead of
- multiple static copies in each file that needs a definition. */
-
-int flag_external_templates;
-
-/* Nonzero means that the decision to emit or not emit the implementation of a
- template depends on where the template is instantiated, rather than where
- it is defined. */
-
-int flag_alt_external_templates;
-
-/* Nonzero means that implicit instantiations will be emitted if needed. */
-
-int flag_implicit_templates = 1;
-
-/* Nonzero means that implicit instantiations of inline templates will be
- emitted if needed, even if instantiations of non-inline templates
- aren't. */
-
-int flag_implicit_inline_templates = 1;
-
-/* Nonzero means warn about things that will change when compiling
- with an ABI-compliant compiler. */
-
-int warn_abi = 0;
-
-/* Nonzero means warn about implicit declarations. */
-
-int warn_implicit = 1;
-
-/* Nonzero means warn about usage of long long when `-pedantic'. */
-
-int warn_long_long = 1;
-
-/* Nonzero means warn when all ctors or dtors are private, and the class
- has no friends. */
-
-int warn_ctor_dtor_privacy = 1;
-
-/* Nonzero means generate separate instantiation control files and juggle
- them at link time. */
-
-int flag_use_repository;
-
-/* Nonzero if we want to issue diagnostics that the standard says are not
- required. */
-
-int flag_optional_diags = 1;
-
-/* Nonzero means give string constants the type `const char *', as mandated
- by the standard. */
-
-int flag_const_strings = 1;
-
-/* Nonzero means warn about deprecated conversion from string constant to
- `char *'. */
-
-int warn_write_strings;
-
-/* Nonzero means warn about pointer casts that can drop a type qualifier
- from the pointer target type. */
-
-int warn_cast_qual;
-
-/* Nonzero means warn about sizeof(function) or addition/subtraction
- of function pointers. */
-
-int warn_pointer_arith = 1;
-
-/* Nonzero means warn for any function def without prototype decl. */
-
-int warn_missing_prototypes;
-
-/* Nonzero means warn about multiple (redundant) decls for the same single
- variable or function. */
-
-int warn_redundant_decls;
-
-/* Warn if initializer is not completely bracketed. */
-
-int warn_missing_braces;
-
-/* Warn about comparison of signed and unsigned values. */
-
-int warn_sign_compare;
-
-/* Warn about testing equality of floating point numbers. */
-
-int warn_float_equal = 0;
-
-/* Warn about functions which might be candidates for format attributes. */
-
-int warn_missing_format_attribute;
-
-/* Warn about a subscript that has type char. */
-
-int warn_char_subscripts;
-
-/* Warn if a type conversion is done that might have confusing results. */
-
-int warn_conversion;
-
-/* Warn if adding () is suggested. */
-
-int warn_parentheses;
-
-/* Non-zero means warn in function declared in derived class has the
- same name as a virtual in the base class, but fails to match the
- type signature of any virtual function in the base class. */
-
-int warn_overloaded_virtual;
-
-/* Non-zero means warn when declaring a class that has a non virtual
- destructor, when it really ought to have a virtual one. */
-
-int warn_nonvdtor;
-
-/* Non-zero means warn when the compiler will reorder code. */
-
-int warn_reorder;
-
-/* Non-zero means warn when synthesis behavior differs from Cfront's. */
-
-int warn_synth;
-
-/* Non-zero means warn when we convert a pointer to member function
- into a pointer to (void or function). */
-
-int warn_pmf2ptr = 1;
-
-/* Nonzero means warn about violation of some Effective C++ style rules. */
-
-int warn_ecpp;
-
-/* Nonzero means warn where overload resolution chooses a promotion from
- unsigned to signed over a conversion to an unsigned of the same size. */
-
-int warn_sign_promo;
-
-/* Nonzero means warn when an old-style cast is used. */
-
-int warn_old_style_cast;
-
-/* Warn about #pragma directives that are not recognised. */
-
-int warn_unknown_pragmas; /* Tri state variable. */
-
-/* Nonzero means warn about use of multicharacter literals. */
-
-int warn_multichar = 1;
-
-/* Nonzero means warn when non-templatized friend functions are
- declared within a template */
-
-int warn_nontemplate_friend = 1;
-
-/* Nonzero means complain about deprecated features. */
-
-int warn_deprecated = 1;
-
-/* Nonzero means `$' can be in an identifier. */
-
-#ifndef DOLLARS_IN_IDENTIFIERS
-#define DOLLARS_IN_IDENTIFIERS 1
-#endif
-int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
-
-/* Nonzero means allow Microsoft extensions without a pedwarn. */
-
-int flag_ms_extensions;
-
-/* C++ specific flags. */
-
-/* Nonzero means we should attempt to elide constructors when possible. */
-
-int flag_elide_constructors = 1;
-
-/* Nonzero means that member functions defined in class scope are
- inline by default. */
-
-int flag_default_inline = 1;
-
-/* Controls whether compiler generates 'type descriptor' that give
- run-time type information. */
-
-int flag_rtti = 1;
-
-/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
- objects. */
-
-int flag_huge_objects;
-
-/* Nonzero if we want to conserve space in the .o files. We do this
- by putting uninitialized data and runtime initialized data into
- .common instead of .data at the expense of not flagging multiple
- definitions. */
-
-int flag_conserve_space;
-
-/* Nonzero if we want to obey access control semantics. */
-
-int flag_access_control = 1;
-
-/* Nonzero if we want to understand the operator names, i.e. 'bitand'. */
-
-int flag_operator_names = 1;
-
-/* Nonzero if we want to check the return value of new and avoid calling
- constructors if it is a null pointer. */
-
-int flag_check_new;
-
-/* Nonzero if we want the new ISO rules for pushing a new scope for `for'
- initialization variables.
- 0: Old rules, set by -fno-for-scope.
- 2: New ISO rules, set by -ffor-scope.
- 1: Try to implement new ISO rules, but with backup compatibility
- (and warnings). This is the default, for now. */
-
-int flag_new_for_scope = 1;
-
-/* Nonzero if we want to emit defined symbols with common-like linkage as
- weak symbols where possible, in order to conform to C++ semantics.
- Otherwise, emit them as local symbols. */
-
-int flag_weak = 1;
-
-/* Nonzero to use __cxa_atexit, rather than atexit, to register
- destructors for local statics and global objects. */
-
-int flag_use_cxa_atexit = DEFAULT_USE_CXA_ATEXIT;
-
-/* Maximum template instantiation depth. This limit is rather
- arbitrary, but it exists to limit the time it takes to notice
- infinite template instantiations. */
-
-int max_tinst_depth = 500;
-
-/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */
-
-int flag_vtable_gc;
-
-/* Nonzero means make the default pedwarns warnings instead of errors.
- The value of this flag is ignored if -pedantic is specified. */
-
-int flag_permissive;
-
-/* Nonzero means to implement standard semantics for exception
- specifications, calling unexpected if an exception is thrown that
- doesn't match the specification. Zero means to treat them as
- assertions and optimize accordingly, but not check them. */
-
-int flag_enforce_eh_specs = 1;
-
-/* Table of language-dependent -f options.
- STRING is the option name. VARIABLE is the address of the variable.
- ON_VALUE is the value to store in VARIABLE
- if `-fSTRING' is seen as an option.
- (If `-fno-STRING' is seen as an option, the opposite value is stored.) */
-
-static const struct { const char *const string; int *const variable; const int on_value;}
-lang_f_options[] =
-{
- /* C/C++ options. */
- {"signed-char", &flag_signed_char, 1},
- {"unsigned-char", &flag_signed_char, 0},
- {"signed-bitfields", &flag_signed_bitfields, 1},
- {"unsigned-bitfields", &flag_signed_bitfields, 0},
- {"short-enums", &flag_short_enums, 1},
- {"short-double", &flag_short_double, 1},
- {"short-wchar", &flag_short_wchar, 1},
- {"asm", &flag_no_asm, 0},
- {"builtin", &flag_no_builtin, 0},
-
- /* C++-only options. */
- {"access-control", &flag_access_control, 1},
- {"check-new", &flag_check_new, 1},
- {"conserve-space", &flag_conserve_space, 1},
- {"const-strings", &flag_const_strings, 1},
- {"default-inline", &flag_default_inline, 1},
- {"dollars-in-identifiers", &dollars_in_ident, 1},
- {"elide-constructors", &flag_elide_constructors, 1},
- {"enforce-eh-specs", &flag_enforce_eh_specs, 1},
- {"external-templates", &flag_external_templates, 1},
- {"for-scope", &flag_new_for_scope, 2},
- {"gnu-keywords", &flag_no_gnu_keywords, 0},
- {"handle-exceptions", &flag_exceptions, 1},
- {"implement-inlines", &flag_implement_inlines, 1},
- {"implicit-inline-templates", &flag_implicit_inline_templates, 1},
- {"implicit-templates", &flag_implicit_templates, 1},
- {"ms-extensions", &flag_ms_extensions, 1},
- {"nonansi-builtins", &flag_no_nonansi_builtin, 0},
- {"operator-names", &flag_operator_names, 1},
- {"optional-diags", &flag_optional_diags, 1},
- {"permissive", &flag_permissive, 1},
- {"repo", &flag_use_repository, 1},
- {"rtti", &flag_rtti, 1},
- {"stats", &flag_detailed_statistics, 1},
- {"vtable-gc", &flag_vtable_gc, 1},
- {"use-cxa-atexit", &flag_use_cxa_atexit, 1},
- {"weak", &flag_weak, 1}
-};
-
-/* The list of `-f' options that we no longer support. The `-f'
- prefix is not given in this table. The `-fno-' variants are not
- listed here. This table must be kept in alphabetical order. */
-static const char * const unsupported_options[] = {
- "all-virtual",
- "cond-mismatch",
- "enum-int-equiv",
- "guiding-decls",
- "honor-std",
- "huge-objects",
- "labels-ok",
- "new-abi",
- "nonnull-objects",
- "squangle",
- "strict-prototype",
- "this-is-variable",
- "vtable-thunks",
- "xref"
-};
-
-/* Compare two option strings, pointed two by P1 and P2, for use with
- bsearch. */
-
-static int
-compare_options (p1, p2)
- const PTR p1;
- const PTR p2;
-{
- return strcmp (*((const char *const *) p1), *((const char *const *) p2));
-}
-
-/* Decode the string P as a language-specific option.
- Return the number of strings consumed for a valid option.
- Otherwise return 0. Should not complain if it does not
- recognise the option. */
-
-int
-cxx_decode_option (argc, argv)
- int argc;
- char **argv;
-{
- int strings_processed;
- const char *p = argv[0];
-
- strings_processed = cpp_handle_option (parse_in, argc, argv, 0);
-
- if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
- /* ignore */;
- else if (p[0] == '-' && p[1] == 'f')
- {
- /* Some kind of -f option.
- P's value is the option sans `-f'.
- Search for it in the table of options. */
- const char *option_value = NULL;
- const char *positive_option;
- size_t j;
-
- p += 2;
- /* Try special -f options. */
-
- /* See if this is one of the options no longer supported. We
- used to support these options, so we continue to accept them,
- with a warning. */
- if (strncmp (p, "no-", strlen ("no-")) == 0)
- positive_option = p + strlen ("no-");
- else
- positive_option = p;
-
- /* If the option is present, issue a warning. Indicate to our
- caller that the option was processed successfully. */
- if (bsearch (&positive_option,
- unsupported_options,
- (sizeof (unsupported_options)
- / sizeof (unsupported_options[0])),
- sizeof (unsupported_options[0]),
- compare_options))
- {
- warning ("-f%s is no longer supported", p);
- return 1;
- }
-
- if (!strcmp (p, "handle-exceptions")
- || !strcmp (p, "no-handle-exceptions"))
- warning ("-fhandle-exceptions has been renamed to -fexceptions (and is now on by default)");
- else if (! strcmp (p, "alt-external-templates"))
- {
- flag_external_templates = 1;
- flag_alt_external_templates = 1;
- cp_deprecated ("-falt-external-templates");
- }
- else if (! strcmp (p, "no-alt-external-templates"))
- flag_alt_external_templates = 0;
- else if (!strcmp (p, "repo"))
- {
- flag_use_repository = 1;
- flag_implicit_templates = 0;
- }
- else if (!strcmp (p, "external-templates"))
- {
- flag_external_templates = 1;
- cp_deprecated ("-fexternal-templates");
- }
- else if ((option_value
- = skip_leading_substring (p, "template-depth-")))
- max_tinst_depth
- = read_integral_parameter (option_value, p - 2, max_tinst_depth);
- else if ((option_value
- = skip_leading_substring (p, "name-mangling-version-")))
- {
- warning ("-fname-mangling-version is no longer supported");
- return 1;
- }
- else if (dump_switch_p (p))
- ;
- else
- {
- int found = 0;
-
- for (j = 0;
- !found && j < (sizeof (lang_f_options)
- / sizeof (lang_f_options[0]));
- j++)
- {
- if (!strcmp (p, lang_f_options[j].string))
- {
- *lang_f_options[j].variable = lang_f_options[j].on_value;
- /* A goto here would be cleaner,
- but breaks the VAX pcc. */
- found = 1;
- }
- else if (p[0] == 'n' && p[1] == 'o' && p[2] == '-'
- && ! strcmp (p+3, lang_f_options[j].string))
- {
- *lang_f_options[j].variable = ! lang_f_options[j].on_value;
- found = 1;
- }
- }
-
- return found;
- }
- }
- else if (p[0] == '-' && p[1] == 'W')
- {
- int setting = 1;
-
- /* The -W options control the warning behavior of the compiler. */
- p += 2;
-
- if (p[0] == 'n' && p[1] == 'o' && p[2] == '-')
- setting = 0, p += 3;
-
- if (!strcmp (p, "abi"))
- warn_abi = setting;
- else if (!strcmp (p, "implicit"))
- warn_implicit = setting;
- else if (!strcmp (p, "long-long"))
- warn_long_long = setting;
- else if (!strcmp (p, "return-type"))
- warn_return_type = setting;
- else if (!strcmp (p, "ctor-dtor-privacy"))
- warn_ctor_dtor_privacy = setting;
- else if (!strcmp (p, "write-strings"))
- warn_write_strings = setting;
- else if (!strcmp (p, "cast-qual"))
- warn_cast_qual = setting;
- else if (!strcmp (p, "char-subscripts"))
- warn_char_subscripts = setting;
- else if (!strcmp (p, "pointer-arith"))
- warn_pointer_arith = setting;
- else if (!strcmp (p, "missing-prototypes"))
- warn_missing_prototypes = setting;
- else if (!strcmp (p, "strict-prototypes"))
- {
- if (setting == 0)
- warning ("-Wno-strict-prototypes is not supported in C++");
- }
- else if (!strcmp (p, "redundant-decls"))
- warn_redundant_decls = setting;
- else if (!strcmp (p, "missing-braces"))
- warn_missing_braces = setting;
- else if (!strcmp (p, "sign-compare"))
- warn_sign_compare = setting;
- else if (!strcmp (p, "float-equal"))
- warn_float_equal = setting;
- else if (!strcmp (p, "format"))
- set_Wformat (setting);
- else if (!strcmp (p, "format=2"))
- set_Wformat (2);
- else if (!strcmp (p, "format-y2k"))
- warn_format_y2k = setting;
- else if (!strcmp (p, "format-extra-args"))
- warn_format_extra_args = setting;
- else if (!strcmp (p, "format-nonliteral"))
- warn_format_nonliteral = setting;
- else if (!strcmp (p, "format-security"))
- warn_format_security = setting;
- else if (!strcmp (p, "missing-format-attribute"))
- warn_missing_format_attribute = setting;
- else if (!strcmp (p, "conversion"))
- warn_conversion = setting;
- else if (!strcmp (p, "parentheses"))
- warn_parentheses = setting;
- else if (!strcmp (p, "non-virtual-dtor"))
- warn_nonvdtor = setting;
- else if (!strcmp (p, "reorder"))
- warn_reorder = setting;
- else if (!strcmp (p, "synth"))
- warn_synth = setting;
- else if (!strcmp (p, "pmf-conversions"))
- warn_pmf2ptr = setting;
- else if (!strcmp (p, "effc++"))
- warn_ecpp = setting;
- else if (!strcmp (p, "sign-promo"))
- warn_sign_promo = setting;
- else if (!strcmp (p, "old-style-cast"))
- warn_old_style_cast = setting;
- else if (!strcmp (p, "overloaded-virtual"))
- warn_overloaded_virtual = setting;
- else if (!strcmp (p, "multichar"))
- warn_multichar = setting;
- else if (!strcmp (p, "unknown-pragmas"))
- /* Set to greater than 1, so that even unknown pragmas in
- system headers will be warned about. */
- warn_unknown_pragmas = setting * 2;
- else if (!strcmp (p, "non-template-friend"))
- warn_nontemplate_friend = setting;
- else if (!strcmp (p, "deprecated"))
- warn_deprecated = setting;
- else if (!strcmp (p, "comment"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "comments"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "trigraphs"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "import"))
- ; /* cpp handles this one. */
- else if (!strcmp (p, "all"))
- {
- warn_return_type = setting;
- set_Wunused (setting);
- warn_implicit = setting;
- warn_switch = setting;
- set_Wformat (setting);
- warn_parentheses = setting;
- warn_missing_braces = setting;
- warn_sign_compare = setting;
- warn_multichar = setting;
- /* We save the value of warn_uninitialized, since if they put
- -Wuninitialized on the command line, we need to generate a
- warning about not using it without also specifying -O. */
- if (warn_uninitialized != 1)
- warn_uninitialized = (setting ? 2 : 0);
- /* Only warn about unknown pragmas that are not in system
- headers. */
- warn_unknown_pragmas = 1;
-
- /* C++-specific warnings. */
- warn_ctor_dtor_privacy = setting;
- warn_nonvdtor = setting;
- warn_reorder = setting;
- warn_nontemplate_friend = setting;
- }
- else return strings_processed;
- }
- else if (!strcmp (p, "-ansi"))
- flag_no_nonansi_builtin = 1, flag_ansi = 1,
- flag_noniso_default_format_attributes = 0, flag_no_gnu_keywords = 1;
-#ifdef SPEW_DEBUG
- /* Undocumented, only ever used when you're invoking cc1plus by hand, since
- it's probably safe to assume no sane person would ever want to use this
- under normal circumstances. */
- else if (!strcmp (p, "-spew-debug"))
- spew_debug = 1;
-#endif
- else
- return strings_processed;
-
- return 1;
-}
-
/* Incorporate `const' and `volatile' qualifiers for member functions.
FUNCTION is a TYPE_DECL or a FUNCTION_DECL.
QUALS is a list of qualifiers. Returns any explicit
@@ -836,6 +221,19 @@ grok_x_components (specs)
finish_member_declaration (build_decl (FIELD_DECL, NULL_TREE, t));
}
+/* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE
+ appropriately. */
+
+tree
+cp_build_parm_decl (name, type)
+ tree name;
+ tree type;
+{
+ tree parm = build_decl (PARM_DECL, name, type);
+ DECL_ARG_TYPE (parm) = type_passed_as (type);
+ return parm;
+}
+
/* Returns a PARM_DECL for a parameter of the indicated TYPE, with the
indicated NAME. */
@@ -844,14 +242,11 @@ build_artificial_parm (name, type)
tree name;
tree type;
{
- tree parm;
-
- parm = build_decl (PARM_DECL, name, type);
+ tree parm = cp_build_parm_decl (name, type);
DECL_ARTIFICIAL (parm) = 1;
/* All our artificial parms are implicitly `const'; they cannot be
assigned to. */
TREE_READONLY (parm) = 1;
- DECL_ARG_TYPE (parm) = type;
return parm;
}
@@ -1139,7 +534,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
return error_mark_node;
}
- /* Deleting ptr to void is undefined behaviour [expr.delete/3]. */
+ /* Deleting ptr to void is undefined behavior [expr.delete/3]. */
if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
{
warning ("deleting `%T' is undefined", type);
@@ -1183,7 +578,7 @@ check_member_template (tmpl)
if (current_function_decl)
/* 14.5.2.2 [temp.mem]
- A local class shall not have member templates. */
+ A local class shall not have member templates. */
error ("invalid declaration of member template `%#D' in local class",
decl);
@@ -1206,7 +601,7 @@ check_member_template (tmpl)
error ("template declaration of `%#D'", decl);
}
-/* Return true iff TYPE is a valid Java parameter or return type. */
+/* Return true iff TYPE is a valid Java parameter or return type. */
static int
acceptable_java_type (type)
@@ -1278,11 +673,8 @@ tree
check_classfn (ctype, function)
tree ctype, function;
{
- tree fn_name = DECL_NAME (function);
- tree fndecl, fndecls;
- tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
- tree *methods = 0;
- tree *end = 0;
+ int ix;
+ int is_template;
if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL
@@ -1299,81 +691,99 @@ check_classfn (ctype, function)
reason we should, either. We let our callers know we didn't
find the method, but we don't complain. */
return NULL_TREE;
-
- if (method_vec != 0)
+
+ /* OK, is this a definition of a member template? */
+ is_template = (TREE_CODE (function) == TEMPLATE_DECL
+ || (processing_template_decl - template_class_depth (ctype)));
+
+ ix = lookup_fnfields_1 (complete_type (ctype),
+ DECL_CONSTRUCTOR_P (function) ? ctor_identifier :
+ DECL_DESTRUCTOR_P (function) ? dtor_identifier :
+ DECL_NAME (function));
+
+ if (ix >= 0)
{
- methods = &TREE_VEC_ELT (method_vec, 0);
- end = TREE_VEC_END (method_vec);
-
- /* First suss out ctors and dtors. */
- if (*methods && fn_name == DECL_NAME (OVL_CURRENT (*methods))
- && DECL_CONSTRUCTOR_P (function))
- goto got_it;
- if (*++methods && fn_name == DECL_NAME (OVL_CURRENT (*methods))
- && DECL_DESTRUCTOR_P (function))
- goto got_it;
-
- while (++methods != end && *methods)
+ tree methods = CLASSTYPE_METHOD_VEC (ctype);
+ tree fndecls, fndecl = 0;
+ bool is_conv_op;
+ const char *format = NULL;
+
+ for (fndecls = TREE_VEC_ELT (methods, ix);
+ fndecls; fndecls = OVL_NEXT (fndecls))
{
- fndecl = *methods;
- if (fn_name == DECL_NAME (OVL_CURRENT (*methods)))
+ tree p1, p2;
+
+ fndecl = OVL_CURRENT (fndecls);
+ p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
+ p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+
+ /* We cannot simply call decls_match because this doesn't
+ work for static member functions that are pretending to
+ be methods, and because the name may have been changed by
+ asm("new_name"). */
+
+ /* Get rid of the this parameter on functions that become
+ static. */
+ if (DECL_STATIC_FUNCTION_P (fndecl)
+ && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
+ p1 = TREE_CHAIN (p1);
+
+ /* A member template definition only matches a member template
+ declaration. */
+ if (is_template != (TREE_CODE (fndecl) == TEMPLATE_DECL))
+ continue;
+
+ if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
+ TREE_TYPE (TREE_TYPE (fndecl)))
+ && compparms (p1, p2)
+ && (DECL_TEMPLATE_SPECIALIZATION (function)
+ == DECL_TEMPLATE_SPECIALIZATION (fndecl))
+ && (!DECL_TEMPLATE_SPECIALIZATION (function)
+ || (DECL_TI_TEMPLATE (function)
+ == DECL_TI_TEMPLATE (fndecl))))
+ return fndecl;
+ }
+ error ("prototype for `%#D' does not match any in class `%T'",
+ function, ctype);
+ is_conv_op = DECL_CONV_FN_P (fndecl);
+
+ if (is_conv_op)
+ ix = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ fndecls = TREE_VEC_ELT (methods, ix);
+ while (fndecls)
+ {
+ fndecl = OVL_CURRENT (fndecls);
+ fndecls = OVL_NEXT (fndecls);
+
+ if (!fndecls && is_conv_op)
{
- got_it:
- for (fndecls = *methods; fndecls != NULL_TREE;
- fndecls = OVL_NEXT (fndecls))
+ if (TREE_VEC_LENGTH (methods) > ix)
{
- fndecl = OVL_CURRENT (fndecls);
-
- /* We cannot simply call decls_match because this
- doesn't work for static member functions that are
- pretending to be methods, and because the name
- may have been changed by asm("new_name"). */
- if (DECL_NAME (function) == DECL_NAME (fndecl))
+ ix++;
+ fndecls = TREE_VEC_ELT (methods, ix);
+ if (!DECL_CONV_FN_P (OVL_CURRENT (fndecls)))
{
- tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
- tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
-
- /* Get rid of the this parameter on functions that become
- static. */
- if (DECL_STATIC_FUNCTION_P (fndecl)
- && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
- p1 = TREE_CHAIN (p1);
-
- if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
- TREE_TYPE (TREE_TYPE (fndecl)))
- && compparms (p1, p2)
- && (DECL_TEMPLATE_SPECIALIZATION (function)
- == DECL_TEMPLATE_SPECIALIZATION (fndecl))
- && (!DECL_TEMPLATE_SPECIALIZATION (function)
- || (DECL_TI_TEMPLATE (function)
- == DECL_TI_TEMPLATE (fndecl))))
- return fndecl;
+ fndecls = NULL_TREE;
+ is_conv_op = false;
}
}
- break; /* loser */
+ else
+ is_conv_op = false;
}
+ if (format)
+ format = " %#D";
+ else if (fndecls)
+ format = "candidates are: %#D";
+ else
+ format = "candidate is: %#D";
+ cp_error_at (format, fndecl);
}
}
-
- if (methods != end && *methods)
- {
- tree fndecl = *methods;
- error ("prototype for `%#D' does not match any in class `%T'",
- function, ctype);
- cp_error_at ("candidate%s: %+#D", OVL_NEXT (fndecl) ? "s are" : " is",
- OVL_CURRENT (fndecl));
- while (fndecl = OVL_NEXT (fndecl), fndecl)
- cp_error_at (" %#D", OVL_CURRENT(fndecl));
- }
+ else if (!COMPLETE_TYPE_P (ctype))
+ cxx_incomplete_type_error (function, ctype);
else
- {
- methods = 0;
- if (!COMPLETE_TYPE_P (ctype))
- incomplete_type_error (function, ctype);
- else
- error ("no `%#D' member function declared in class `%T'",
- function, ctype);
- }
+ error ("no `%#D' member function declared in class `%T'",
+ function, ctype);
/* If we did not find the method in the class, add it to avoid
spurious errors (unless the CTYPE is not yet defined, in which
@@ -1592,12 +1002,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
init = decl_constant_value (init);
else if (TREE_CODE (init) == CONSTRUCTOR)
init = digest_init (TREE_TYPE (value), init, (tree *)0);
- if (init == error_mark_node)
- /* We must make this look different than `error_mark_node'
- because `decl_const_value' would mis-interpret it
- as only meaning that this VAR_DECL is defined. */
- init = build1 (NOP_EXPR, TREE_TYPE (value), init);
- else if (! TREE_CONSTANT (init))
+ if (init != error_mark_node && ! TREE_CONSTANT (init))
{
/* We can allow references to things that are effectively
static, since references are initialized with the
@@ -1614,7 +1019,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
}
}
- if (processing_template_decl && ! current_function_decl
+ if (processing_template_decl
&& (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL))
value = push_template_decl (value);
@@ -1722,11 +1127,29 @@ grokbitfield (declarator, declspecs, width)
return value;
}
+/* Convert a conversion operator name to an identifier. SCOPE is the
+ scope of the conversion operator, if explicit. */
+
tree
-grokoptypename (declspecs, declarator)
+grokoptypename (declspecs, declarator, scope)
tree declspecs, declarator;
+ tree scope;
{
tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL);
+
+ /* Resolve any TYPENAME_TYPEs that refer to SCOPE, before mangling
+ the name, so that we mangle the right thing. */
+ if (scope && current_template_parms
+ && uses_template_parms (t)
+ && uses_template_parms (scope))
+ {
+ tree args = current_template_args ();
+
+ push_scope (scope);
+ t = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
+ pop_scope (scope);
+ }
+
return mangle_conv_op_name_for_type (t);
}
@@ -1845,6 +1268,16 @@ constructor_name (thing)
return thing;
return t;
}
+
+/* Returns TRUE if NAME is the name for the constructor for TYPE. */
+
+bool
+constructor_name_p (tree name, tree type)
+{
+ return (name == constructor_name (type)
+ || name == constructor_name_full (type));
+}
+
/* Defer the compilation of the FN until the end of compilation. */
@@ -1971,7 +1404,7 @@ finish_anon_union (anon_union_decl)
int static_p = TREE_STATIC (anon_union_decl);
int external_p = DECL_EXTERNAL (anon_union_decl);
- /* The VAR_DECL's context is the same as the TYPE's context. */
+ /* The VAR_DECL's context is the same as the TYPE's context. */
DECL_CONTEXT (anon_union_decl) = DECL_CONTEXT (TYPE_NAME (type));
if (TYPE_FIELDS (type) == NULL_TREE)
@@ -2191,7 +1624,7 @@ comdat_linkage (decl)
DECL_COMMON (decl) = 1;
DECL_INITIAL (decl) = error_mark_node;
}
- else
+ else if (!DECL_EXPLICIT_INSTANTIATION (decl))
{
/* We can't do anything useful; leave vars for explicit
instantiation. */
@@ -2217,7 +1650,7 @@ maybe_make_one_only (decl)
one. However, that's not actually the case in SVR4; a strong definition
after a weak one is an error. Also, not making explicit
instantiations one_only means that we can end up with two copies of
- some template instantiations. */
+ some template instantiations. */
if (! flag_weak)
return;
@@ -2236,34 +1669,6 @@ maybe_make_one_only (decl)
}
}
-/* Returns the virtual function with which the vtable for TYPE is
- emitted, or NULL_TREE if that heuristic is not applicable to TYPE. */
-
-static tree
-key_method (type)
- tree type;
-{
- tree method;
-
- if (TYPE_FOR_JAVA (type)
- || CLASSTYPE_TEMPLATE_INSTANTIATION (type)
- || CLASSTYPE_INTERFACE_KNOWN (type))
- return NULL_TREE;
-
- for (method = TYPE_METHODS (type); method != NULL_TREE;
- method = TREE_CHAIN (method))
- if (DECL_VINDEX (method) != NULL_TREE
- && ! DECL_DECLARED_INLINE_P (method)
- && (! DECL_PURE_VIRTUAL_P (method)
-#if 0
- /* This would be nice, but we didn't think of it in time. */
- || DECL_DESTRUCTOR_P (method)
-#endif
- ))
- return method;
-
- return NULL_TREE;
-}
/* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL,
based on TYPE and other static flags.
@@ -2297,7 +1702,7 @@ import_export_vtable (decl, type, final)
functions in our class, or if we come from a template. */
int found = (CLASSTYPE_TEMPLATE_INSTANTIATION (type)
- || key_method (type));
+ || CLASSTYPE_KEY_METHOD (type) != NULL_TREE);
if (final || ! found)
{
@@ -2357,7 +1762,7 @@ import_export_class (ctype)
if (import_export == 0
&& TYPE_POLYMORPHIC_P (ctype))
{
- tree method = key_method (ctype);
+ tree method = CLASSTYPE_KEY_METHOD (ctype);
if (method)
import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1);
}
@@ -2401,28 +1806,52 @@ output_vtable_inherit (vars)
assemble_vtable_inherit (child_rtx, parent_rtx);
}
+/* If necessary, write out the vtables for the dynamic class CTYPE.
+ Returns nonzero if any vtables were emitted. */
+
static int
-finish_vtable_vardecl (t, data)
- tree *t;
- void *data ATTRIBUTE_UNUSED;
+maybe_emit_vtables (tree ctype)
{
- tree vars = *t;
- tree ctype = DECL_CONTEXT (vars);
+ tree vtbl;
+ tree primary_vtbl;
+
+ /* If the vtables for this class have already been emitted there is
+ nothing more to do. */
+ primary_vtbl = CLASSTYPE_VTABLES (ctype);
+ if (TREE_ASM_WRITTEN (primary_vtbl))
+ return 0;
+ /* Ignore dummy vtables made by get_vtable_decl. */
+ if (TREE_TYPE (primary_vtbl) == void_type_node)
+ return 0;
+
import_export_class (ctype);
- import_export_vtable (vars, ctype, 1);
+ import_export_vtable (primary_vtbl, ctype, 1);
- if (! DECL_EXTERNAL (vars)
- && DECL_NEEDED_P (vars)
- && ! TREE_ASM_WRITTEN (vars))
+ /* See if any of the vtables are needed. */
+ for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
+ if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl))
+ break;
+
+ if (!vtbl)
+ {
+ /* If the references to this class' vtables are optimized away,
+ still emit the appropriate debugging information. See
+ dfs_debug_mark. */
+ if (DECL_COMDAT (primary_vtbl)
+ && CLASSTYPE_DEBUG_REQUESTED (ctype))
+ note_debug_info_needed (ctype);
+ return 0;
+ }
+
+ /* The ABI requires that we emit all of the vtables if we emit any
+ of them. */
+ for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
{
- if (TREE_TYPE (vars) == void_type_node)
- /* It is a dummy vtable made by get_vtable_decl. Ignore it. */
- return 0;
-
/* Write it out. */
- mark_vtable_entries (vars);
- if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
- store_init_value (vars, DECL_INITIAL (vars));
+ import_export_vtable (vtbl, ctype, 1);
+ mark_vtable_entries (vtbl);
+ if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
+ store_init_value (vtbl, DECL_INITIAL (vtbl));
if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
{
@@ -2447,45 +1876,28 @@ finish_vtable_vardecl (t, data)
`S' get written (which would solve the problem) but that would
require more intrusive changes to the g++ front end. */
- DECL_IGNORED_P (vars) = 1;
+ DECL_IGNORED_P (vtbl) = 1;
}
/* Always make vtables weak. */
if (flag_weak)
- comdat_linkage (vars);
+ comdat_linkage (vtbl);
- rest_of_decl_compilation (vars, NULL, 1, 1);
+ rest_of_decl_compilation (vtbl, NULL, 1, 1);
if (flag_vtable_gc)
- output_vtable_inherit (vars);
+ output_vtable_inherit (vtbl);
/* Because we're only doing syntax-checking, we'll never end up
actually marking the variable as written. */
if (flag_syntax_only)
- TREE_ASM_WRITTEN (vars) = 1;
-
- /* Since we're writing out the vtable here, also write the debug
- info. */
- note_debug_info_needed (ctype);
-
- return 1;
+ TREE_ASM_WRITTEN (vtbl) = 1;
}
- /* If the references to this class' vtables were optimized away, still
- emit the appropriate debugging information. See dfs_debug_mark. */
- if (DECL_COMDAT (vars)
- && CLASSTYPE_DEBUG_REQUESTED (ctype))
- note_debug_info_needed (ctype);
+ /* Since we're writing out the vtable here, also write the debug
+ info. */
+ note_debug_info_needed (ctype);
- return 0;
-}
-
-static int
-prune_vtable_vardecl (t, data)
- tree *t;
- void *data ATTRIBUTE_UNUSED;
-{
- *t = TREE_CHAIN (*t);
return 1;
}
@@ -2556,7 +1968,7 @@ import_export_decl (decl)
}
/* Here, we only decide whether or not the tinfo node should be
- emitted with the vtable. IS_IN_LIBRARY is non-zero iff the
+ emitted with the vtable. IS_IN_LIBRARY is nonzero iff the
typeinfo for TYPE should be in the runtime library. */
void
@@ -2587,7 +1999,7 @@ import_export_tinfo (decl, type, is_in_library)
DECL_COMDAT (decl) = 1;
}
- /* Now override some cases. */
+ /* Now override some cases. */
if (flag_weak)
DECL_COMDAT (decl) = 1;
else if (is_in_library)
@@ -2596,6 +2008,10 @@ import_export_tinfo (decl, type, is_in_library)
DECL_INTERFACE_KNOWN (decl) = 1;
}
+/* Return an expression that performs the destruction of DECL, which
+ must be a VAR_DECL whose type has a non-trivial destructor, or is
+ an array whose (innermost) elements have a non-trivial destructor. */
+
tree
build_cleanup (decl)
tree decl;
@@ -2603,11 +2019,19 @@ build_cleanup (decl)
tree temp;
tree type = TREE_TYPE (decl);
+ /* This function should only be called for declarations that really
+ require cleanups. */
+ my_friendly_assert (!TYPE_HAS_TRIVIAL_DESTRUCTOR (type), 20030106);
+
+ /* Treat all objects with destructors as used; the destructor may do
+ something substantive. */
+ mark_used (decl);
+
if (TREE_CODE (type) == ARRAY_TYPE)
temp = decl;
else
{
- mark_addressable (decl);
+ cxx_mark_addressable (decl);
temp = build1 (ADDR_EXPR, build_pointer_type (type), decl);
}
temp = build_delete (TREE_TYPE (temp), temp,
@@ -2637,7 +2061,7 @@ get_guard (decl)
guard_type = long_long_integer_type_node;
guard = build_decl (VAR_DECL, sname, guard_type);
- /* The guard should have the same linkage as what it guards. */
+ /* The guard should have the same linkage as what it guards. */
TREE_PUBLIC (guard) = TREE_PUBLIC (decl);
TREE_STATIC (guard) = TREE_STATIC (decl);
DECL_COMMON (guard) = DECL_COMMON (decl);
@@ -2647,8 +2071,7 @@ get_guard (decl)
DECL_ARTIFICIAL (guard) = 1;
TREE_USED (guard) = 1;
- pushdecl_top_level (guard);
- cp_finish_decl (guard, NULL_TREE, NULL_TREE, 0);
+ pushdecl_top_level_and_finish (guard, NULL_TREE);
}
return guard;
}
@@ -2754,7 +2177,7 @@ start_objects (method_type, initp)
DECL_GLOBAL_CTOR_P (current_function_decl) = 1;
else
DECL_GLOBAL_DTOR_P (current_function_decl) = 1;
- GLOBAL_INIT_PRIORITY (current_function_decl) = initp;
+ DECL_LANG_SPECIFIC (current_function_decl)->decl_flags.u2sel = 1;
body = begin_compound_stmt (/*has_no_scope=*/0);
@@ -2810,17 +2233,17 @@ finish_objects (method_type, initp, body)
#define SSDF_IDENTIFIER "__static_initialization_and_destruction"
/* The declaration for the __INITIALIZE_P argument. */
-static tree initialize_p_decl;
+static GTY(()) tree initialize_p_decl;
/* The declaration for the __PRIORITY argument. */
-static tree priority_decl;
+static GTY(()) tree priority_decl;
/* The declaration for the static storage duration function. */
-static tree ssdf_decl;
+static GTY(()) tree ssdf_decl;
/* All the static storage duration functions created in this
translation unit. */
-static varray_type ssdf_decls;
+static GTY(()) varray_type ssdf_decls;
/* A map from priority levels to information about that priority
level. There may be many such levels, so efficient lookup is
@@ -2831,7 +2254,7 @@ static splay_tree priority_info_map;
initialization and destruction of objects with static storage
duration. The function generated takes two parameters of type
`int': __INITIALIZE_P and __PRIORITY. If __INITIALIZE_P is
- non-zero, it performs initializations. Otherwise, it performs
+ nonzero, it performs initializations. Otherwise, it performs
destructions. It only performs those initializations or
destructions with the indicated __PRIORITY. The generated function
returns no value.
@@ -2880,7 +2303,7 @@ start_static_storage_duration_function ()
VARRAY_TREE_INIT (ssdf_decls, 32, "ssdf_decls");
/* Take this opportunity to initialize the map from priority
- numbers to information about that priority level. */
+ numbers to information about that priority level. */
priority_info_map = splay_tree_new (splay_tree_compare_ints,
/*delete_key_fn=*/0,
/*delete_value_fn=*/
@@ -2896,16 +2319,13 @@ start_static_storage_duration_function ()
VARRAY_PUSH_TREE (ssdf_decls, ssdf_decl);
/* Create the argument list. */
- initialize_p_decl = build_decl (PARM_DECL,
- get_identifier (INITIALIZE_P_IDENTIFIER),
- integer_type_node);
+ initialize_p_decl = cp_build_parm_decl
+ (get_identifier (INITIALIZE_P_IDENTIFIER), integer_type_node);
DECL_CONTEXT (initialize_p_decl) = ssdf_decl;
- DECL_ARG_TYPE (initialize_p_decl) = integer_type_node;
TREE_USED (initialize_p_decl) = 1;
- priority_decl = build_decl (PARM_DECL, get_identifier (PRIORITY_IDENTIFIER),
- integer_type_node);
+ priority_decl = cp_build_parm_decl
+ (get_identifier (PRIORITY_IDENTIFIER), integer_type_node);
DECL_CONTEXT (priority_decl) = ssdf_decl;
- DECL_ARG_TYPE (priority_decl) = integer_type_node;
TREE_USED (priority_decl) = 1;
TREE_CHAIN (initialize_p_decl) = priority_decl;
@@ -2981,7 +2401,7 @@ get_priority_info (priority)
}
/* Set up to handle the initialization or destruction of DECL. If
- INITP is non-zero, we are initializing the variable. Otherwise, we
+ INITP is nonzero, we are initializing the variable. Otherwise, we
are destroying it. */
static tree
@@ -3121,34 +2541,24 @@ finish_static_initialization_or_destruction (guard_if_stmt)
DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
}
-/* Generate code to do the static initialization of DECL. The
- initialization is INIT. If DECL may be initialized more than once
- in different object files, GUARD is the guard variable to
- check. PRIORITY is the priority for the initialization. */
+/* Generate code to do the initialization of DECL, a VAR_DECL with
+ static storage duration. The initialization is INIT. */
static void
do_static_initialization (decl, init)
tree decl;
tree init;
{
- tree expr;
tree guard_if_stmt;
/* Set up for the initialization. */
guard_if_stmt
= start_static_initialization_or_destruction (decl,
/*initp=*/1);
-
- /* Do the initialization itself. */
- if (IS_AGGR_TYPE (TREE_TYPE (decl))
- || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
- expr = build_aggr_init (decl, init, 0);
- else
- {
- expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
- TREE_SIDE_EFFECTS (expr) = 1;
- }
- finish_expr_stmt (expr);
+
+ /* Perform the initialization. */
+ if (init)
+ finish_expr_stmt (init);
/* If we're using __cxa_atexit, register a a function that calls the
destructor for the object. */
@@ -3180,7 +2590,7 @@ do_static_destruction (decl)
/* Actually do the destruction. */
guard_if_stmt = start_static_initialization_or_destruction (decl,
- /*initp=*/0);
+ /*initp=*/0);
finish_expr_stmt (build_cleanup (decl));
finish_static_initialization_or_destruction (guard_if_stmt);
}
@@ -3195,21 +2605,23 @@ do_static_destruction (decl)
static tree
prune_vars_needing_no_initialization (vars)
- tree vars;
+ tree *vars;
{
- tree var;
- tree result;
+ tree *var = vars;
+ tree result = NULL_TREE;
- for (var = vars, result = NULL_TREE;
- var;
- var = TREE_CHAIN (var))
+ while (*var)
{
- tree decl = TREE_VALUE (var);
- tree init = TREE_PURPOSE (var);
+ tree t = *var;
+ tree decl = TREE_VALUE (t);
+ tree init = TREE_PURPOSE (t);
/* Deal gracefully with error. */
if (decl == error_mark_node)
- continue;
+ {
+ var = &TREE_CHAIN (t);
+ continue;
+ }
/* The only things that can be initialized are variables. */
my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 19990420);
@@ -3217,17 +2629,25 @@ prune_vars_needing_no_initialization (vars)
/* If this object is not defined, we don't need to do anything
here. */
if (DECL_EXTERNAL (decl))
- continue;
+ {
+ var = &TREE_CHAIN (t);
+ continue;
+ }
/* Also, if the initializer already contains errors, we can bail
out now. */
if (init && TREE_CODE (init) == TREE_LIST
&& value_member (error_mark_node, init))
- continue;
+ {
+ var = &TREE_CHAIN (t);
+ continue;
+ }
/* This variable is going to need initialization and/or
finalization, so we add it to the list. */
- result = tree_cons (init, decl, result);
+ *var = TREE_CHAIN (t);
+ TREE_CHAIN (t) = result;
+ result = t;
}
return result;
@@ -3273,15 +2693,16 @@ generate_ctor_or_dtor_function (constructor_p, priority)
/* Call the static storage duration function with appropriate
arguments. */
- for (i = 0; i < ssdf_decls->elements_used; ++i)
- {
- arguments = tree_cons (NULL_TREE, build_int_2 (priority, 0),
- NULL_TREE);
- arguments = tree_cons (NULL_TREE, build_int_2 (constructor_p, 0),
- arguments);
- finish_expr_stmt (build_function_call (VARRAY_TREE (ssdf_decls, i),
- arguments));
- }
+ if (ssdf_decls)
+ for (i = 0; i < ssdf_decls->elements_used; ++i)
+ {
+ arguments = tree_cons (NULL_TREE, build_int_2 (priority, 0),
+ NULL_TREE);
+ arguments = tree_cons (NULL_TREE, build_int_2 (constructor_p, 0),
+ arguments);
+ finish_expr_stmt (build_function_call (VARRAY_TREE (ssdf_decls, i),
+ arguments));
+ }
/* If we're generating code for the DEFAULT_INIT_PRIORITY, throw in
calls to any functions marked with attributes indicating that
@@ -3289,7 +2710,7 @@ generate_ctor_or_dtor_function (constructor_p, priority)
if (priority == DEFAULT_INIT_PRIORITY)
{
tree fns;
-
+
for (fns = constructor_p ? static_ctors : static_dtors;
fns;
fns = TREE_CHAIN (fns))
@@ -3364,7 +2785,7 @@ finish_file ()
All of these may cause others to be needed. For example,
instantiating one function may cause another to be needed, and
- generating the intiailzer for an object may cause templates to be
+ generating the initializer for an object may cause templates to be
instantiated, etc., etc. */
timevar_push (TV_VARCONST);
@@ -3373,6 +2794,8 @@ finish_file ()
do
{
+ tree t;
+
reconsider = 0;
/* If there are templates that we've put off instantiating, do
@@ -3380,12 +2803,36 @@ finish_file ()
instantiate_pending_templates ();
/* Write out virtual tables as required. Note that writing out
- the virtual table for a template class may cause the
- instantiation of members of that class. */
- if (walk_globals (vtable_decl_p,
- finish_vtable_vardecl,
- /*data=*/0))
- reconsider = 1;
+ the virtual table for a template class may cause the
+ instantiation of members of that class. If we write out
+ vtables then we remove the class from our list so we don't
+ have to look at it again. */
+
+ while (keyed_classes != NULL_TREE
+ && maybe_emit_vtables (TREE_VALUE (keyed_classes)))
+ {
+ reconsider = 1;
+ keyed_classes = TREE_CHAIN (keyed_classes);
+ }
+
+ t = keyed_classes;
+ if (t != NULL_TREE)
+ {
+ tree next = TREE_CHAIN (t);
+
+ while (next)
+ {
+ if (maybe_emit_vtables (TREE_VALUE (next)))
+ {
+ reconsider = 1;
+ TREE_CHAIN (t) = TREE_CHAIN (next);
+ }
+ else
+ t = next;
+
+ next = TREE_CHAIN (t);
+ }
+ }
/* Write out needed type info variables. Writing out one variable
might cause others to be needed. */
@@ -3397,8 +2844,7 @@ finish_file ()
aggregates added during the initialization of these will be
initialized in the correct order when we next come around the
loop. */
- vars = prune_vars_needing_no_initialization (static_aggregates);
- static_aggregates = NULL_TREE;
+ vars = prune_vars_needing_no_initialization (&static_aggregates);
if (vars)
{
@@ -3446,12 +2892,11 @@ finish_file ()
reconsider = 1;
}
- /* Go through the various inline functions, and see if any need
- synthesizing. */
for (i = 0; i < deferred_fns_used; ++i)
{
tree decl = VARRAY_TREE (deferred_fns, i);
- import_export_decl (decl);
+
+ /* Does it need synthesizing? */
if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
&& TREE_USED (decl)
&& (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl)))
@@ -3466,30 +2911,32 @@ finish_file ()
pop_from_top_level ();
reconsider = 1;
}
- }
- /* We lie to the back-end, pretending that some functions are
- not defined when they really are. This keeps these functions
- from being put out unnecessarily. But, we must stop lying
- when the functions are referenced, or if they are not comdat
- since they need to be put out now.
- This is done in a separate for cycle, because if some deferred
- function is contained in another deferred function later in
- deferred_fns varray, rest_of_compilation would skip this
- function and we really cannot expand the same function twice. */
- for (i = 0; i < deferred_fns_used; ++i)
- {
- tree decl = VARRAY_TREE (deferred_fns, i);
-
+ /* If the function has no body, avoid calling
+ import_export_decl. On a system without weak symbols,
+ calling import_export_decl will make an inline template
+ instantiation "static", which will result in errors about
+ the use of undefined functions if there is no body for
+ the function. */
+ if (!DECL_SAVED_TREE (decl))
+ continue;
+
+ import_export_decl (decl);
+
+ /* We lie to the back-end, pretending that some functions
+ are not defined when they really are. This keeps these
+ functions from being put out unnecessarily. But, we must
+ stop lying when the functions are referenced, or if they
+ are not comdat since they need to be put out now. This
+ is done in a separate for cycle, because if some deferred
+ function is contained in another deferred function later
+ in deferred_fns varray, rest_of_compilation would skip
+ this function and we really cannot expand the same
+ function twice. */
if (DECL_NOT_REALLY_EXTERN (decl)
&& DECL_INITIAL (decl)
&& DECL_NEEDED_P (decl))
DECL_EXTERNAL (decl) = 0;
- }
-
- for (i = 0; i < deferred_fns_used; ++i)
- {
- tree decl = VARRAY_TREE (deferred_fns, i);
/* If we're going to need to write this function out, and
there's already a body for it, create RTL for it now.
@@ -3545,6 +2992,20 @@ finish_file ()
}
while (reconsider);
+ /* All used inline functions must have a definition at this point. */
+ for (i = 0; i < deferred_fns_used; ++i)
+ {
+ tree decl = VARRAY_TREE (deferred_fns, i);
+
+ if (TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl)
+ && !(TREE_ASM_WRITTEN (decl) || DECL_SAVED_TREE (decl)
+ /* An explicit instantiation can be used to specify
+ that the body is in another unit. It will have
+ already verified there was a definition. */
+ || DECL_EXPLICIT_INSTANTIATION (decl)))
+ cp_warning_at ("inline function `%D' used but never defined", decl);
+ }
+
/* We give C linkage to static constructors and destructors. */
push_lang_context (lang_name_c);
@@ -3554,6 +3015,15 @@ finish_file ()
splay_tree_foreach (priority_info_map,
generate_ctor_and_dtor_functions_for_priority,
/*data=*/0);
+ else
+ {
+ if (static_ctors)
+ generate_ctor_or_dtor_function (/*constructor_p=*/true,
+ DEFAULT_INIT_PRIORITY);
+ if (static_dtors)
+ generate_ctor_or_dtor_function (/*constructor_p=*/false,
+ DEFAULT_INIT_PRIORITY);
+ }
/* We're done with the splay-tree now. */
if (priority_info_map)
@@ -3563,13 +3033,6 @@ finish_file ()
linkage now. */
pop_lang_context ();
- /* Now delete from the chain of variables all virtual function tables.
- We output them all ourselves, because each will be treated
- specially. We don't do this if we're just doing semantic
- analysis, and not code-generation. */
- if (!flag_syntax_only)
- walk_globals (vtable_decl_p, prune_vtable_vardecl, /*data=*/0);
-
/* Now, issue warnings about static, but not defined, functions,
etc., and emit debugging information. */
walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider);
@@ -3580,7 +3043,7 @@ finish_file ()
finish_repo ();
/* The entire file is now complete. If requested, dump everything
- to a file. */
+ to a file. */
{
int flags;
FILE *stream = dump_begin (TDI_all, &flags);
@@ -3621,14 +3084,7 @@ reparse_absdcl_as_expr (type, decl)
/* recurse */
decl = reparse_absdcl_as_expr (type, TREE_OPERAND (decl, 0));
- decl = build_x_function_call (decl, NULL_TREE, current_class_ref);
-
- if (TREE_CODE (decl) == CALL_EXPR
- && (! TREE_TYPE (decl)
- || TREE_CODE (TREE_TYPE (decl)) != VOID_TYPE))
- decl = require_complete_type (decl);
-
- return decl;
+ return finish_call_expr (decl, NULL_TREE, /*disallow_virtual=*/false);
}
/* This is something of the form `int ((int)(int)(int)1)' that has turned
@@ -3681,7 +3137,8 @@ reparse_absdcl_as_casts (decl, expr)
return expr;
}
-/* Given plain tree nodes for an expression, build up the full semantics. */
+/* T is the parse tree for an expression. Return the expression after
+ performing semantic analysis. */
tree
build_expr_from_tree (t)
@@ -3697,14 +3154,37 @@ build_expr_from_tree (t)
case LOOKUP_EXPR:
if (LOOKUP_EXPR_GLOBAL (t))
- return do_scoped_id (TREE_OPERAND (t, 0), 0);
+ {
+ tree token = TREE_OPERAND (t, 0);
+ return do_scoped_id (token, IDENTIFIER_GLOBAL_VALUE (token));
+ }
else
return do_identifier (TREE_OPERAND (t, 0), 0, NULL_TREE);
case TEMPLATE_ID_EXPR:
- return (lookup_template_function
- (build_expr_from_tree (TREE_OPERAND (t, 0)),
- build_expr_from_tree (TREE_OPERAND (t, 1))));
+ {
+ tree template;
+ tree args;
+ tree object;
+
+ template = build_expr_from_tree (TREE_OPERAND (t, 0));
+ args = build_expr_from_tree (TREE_OPERAND (t, 1));
+
+ if (TREE_CODE (template) == COMPONENT_REF)
+ {
+ object = TREE_OPERAND (template, 0);
+ template = TREE_OPERAND (template, 1);
+ }
+ else
+ object = NULL_TREE;
+
+ template = lookup_template_function (template, args);
+ if (object)
+ return build (COMPONENT_REF, TREE_TYPE (template),
+ object, template);
+ else
+ return template;
+ }
case INDIRECT_REF:
return build_x_indirect_ref
@@ -3803,8 +3283,10 @@ build_expr_from_tree (t)
case ALIGNOF_EXPR:
{
tree r = build_expr_from_tree (TREE_OPERAND (t, 0));
- return (TREE_CODE (t) == SIZEOF_EXPR
- ? finish_sizeof (r) : finish_alignof (r));
+ if (!TYPE_P (r))
+ return TREE_CODE (t) == SIZEOF_EXPR ? expr_sizeof (r) : c_alignof_expr (r);
+ else
+ return cxx_sizeof_or_alignof_type (r, TREE_CODE (t), true);
}
case MODOP_EXPR:
@@ -3884,16 +3366,18 @@ build_expr_from_tree (t)
{
tree ref = TREE_OPERAND (t, 0);
tree name = TREE_OPERAND (ref, 1);
+ tree fn, scope, args;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = build_nt (TEMPLATE_ID_EXPR,
TREE_OPERAND (name, 0),
build_expr_from_tree (TREE_OPERAND (name, 1)));
-
- return build_member_call
- (build_expr_from_tree (TREE_OPERAND (ref, 0)),
- name,
- build_expr_from_tree (TREE_OPERAND (t, 1)));
+
+ scope = build_expr_from_tree (TREE_OPERAND (ref, 0));
+ args = build_expr_from_tree (TREE_OPERAND (t, 1));
+ fn = resolve_scoped_fn_name (scope, name);
+
+ return build_call_from_tree (fn, args, 1);
}
else
{
@@ -3906,13 +3390,22 @@ build_expr_from_tree (t)
&& (!current_class_type
|| !lookup_member (current_class_type, id, 0, 0)))
{
- /* Do Koenig lookup if there are no class members. */
+ /* Do Koenig lookup if there are no class members. */
name = do_identifier (id, 0, args);
}
else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
- || ! really_overloaded_fn (name))
+ || ! really_overloaded_fn (name))
name = build_expr_from_tree (name);
- return build_x_function_call (name, args, current_class_ref);
+
+ if (TREE_CODE (name) == OFFSET_REF)
+ return build_offset_ref_call_from_tree (name, args);
+ if (TREE_CODE (name) == COMPONENT_REF)
+ return finish_object_call_expr (TREE_OPERAND (name, 1),
+ TREE_OPERAND (name, 0),
+ args);
+ name = convert_from_reference (name);
+ return build_call_from_tree (name, args,
+ /*disallow_virtual=*/false);
}
case COND_EXPR:
@@ -3949,18 +3442,8 @@ build_expr_from_tree (t)
case COMPONENT_REF:
{
tree object = build_expr_from_tree (TREE_OPERAND (t, 0));
- tree field = TREE_OPERAND (t, 1);
-
- /* We use a COMPONENT_REF to indicate things of the form `x.b'
- and `x.A::b'. We must distinguish between those cases
- here. */
- if (TREE_CODE (field) == SCOPE_REF)
- return build_object_ref (object,
- TREE_OPERAND (field, 0),
- TREE_OPERAND (field, 1));
- else
- return build_x_component_ref (object, field,
- NULL_TREE, 1);
+ return finish_class_member_access_expr (object,
+ TREE_OPERAND (t, 1));
}
case THROW_EXPR:
@@ -4018,6 +3501,108 @@ build_expr_from_tree (t)
}
}
+/* FN is an OFFSET_REF indicating the function to call in parse-tree
+ form; it has not yet been semantically analyzed. ARGS are the
+ arguments to the function. They have already been semantically
+ analzyed. */
+
+tree
+build_offset_ref_call_from_tree (tree fn, tree args)
+{
+ tree object_addr;
+
+ my_friendly_assert (TREE_CODE (fn) == OFFSET_REF, 20020725);
+
+ /* A qualified name corresponding to a non-static member
+ function or a pointer-to-member is represented as an
+ OFFSET_REF.
+
+ For both of these function calls, FN will be an OFFSET_REF.
+
+ struct A { void f(); };
+ void A::f() { (A::f) (); }
+
+ struct B { void g(); };
+ void (B::*p)();
+ void B::g() { (this->*p)(); } */
+
+ /* This code is not really correct (for example, it does not
+ handle the case that `A::f' is overloaded), but it is
+ historically how we have handled this situation. */
+ if (TREE_CODE (TREE_OPERAND (fn, 1)) == FIELD_DECL)
+ fn = resolve_offset_ref (fn);
+ else
+ {
+ object_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (fn, 0), 0);
+ fn = TREE_OPERAND (fn, 1);
+ fn = get_member_function_from_ptrfunc (&object_addr, fn);
+ args = tree_cons (NULL_TREE, object_addr, args);
+ }
+ return build_function_call (fn, args);
+}
+
+/* FN indicates the function to call. Name resolution has been
+ performed on FN. ARGS are the arguments to the function. They
+ have already been semantically analyzed. DISALLOW_VIRTUAL is true
+ if the function call should be determined at compile time, even if
+ FN is virtual. */
+
+tree
+build_call_from_tree (tree fn, tree args, bool disallow_virtual)
+{
+ tree template_args;
+ tree template_id;
+ tree f;
+
+ /* Check to see that name lookup has already been performed. */
+ my_friendly_assert (TREE_CODE (fn) != OFFSET_REF, 20020725);
+ my_friendly_assert (TREE_CODE (fn) != SCOPE_REF, 20020725);
+
+ /* In the future all of this should be eliminated. Instead,
+ name-lookup for a member function should simply return a
+ baselink, instead of a FUNCTION_DECL, TEMPLATE_DECL, or
+ TEMPLATE_ID_EXPR. */
+
+ if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+ {
+ template_id = fn;
+ template_args = TREE_OPERAND (fn, 1);
+ fn = TREE_OPERAND (fn, 0);
+ }
+ else
+ {
+ template_id = NULL_TREE;
+ template_args = NULL_TREE;
+ }
+
+ f = (TREE_CODE (fn) == OVERLOAD) ? get_first_fn (fn) : fn;
+ /* Make sure we have a baselink (rather than simply a
+ FUNCTION_DECL) for a member function. */
+ if (current_class_type
+ && ((TREE_CODE (f) == FUNCTION_DECL
+ && DECL_FUNCTION_MEMBER_P (f))
+ || (DECL_FUNCTION_TEMPLATE_P (f)
+ && DECL_FUNCTION_MEMBER_P (f))))
+ {
+ f = lookup_member (current_class_type, DECL_NAME (f),
+ /*protect=*/1, /*want_type=*/0);
+ if (f)
+ fn = f;
+ }
+
+ if (template_id)
+ {
+ if (BASELINK_P (fn))
+ BASELINK_FUNCTIONS (fn) = build_nt (TEMPLATE_ID_EXPR,
+ BASELINK_FUNCTIONS (fn),
+ template_args);
+ else
+ fn = template_id;
+ }
+
+ return finish_call_expr (fn, args, disallow_virtual);
+}
+
/* This is something of the form `int (*a)++' that has turned out to be an
expr. It was only converted into parse nodes, so we need to go through
and build up the semantics. Most of the work is done by
@@ -4076,32 +3661,51 @@ finish_decl_parsing (decl)
}
}
-/* Return 1 if root encloses child. */
+/* Returns true if ROOT (a namespace, class, or function) encloses
+ CHILD. CHILD may be either a class type or a namespace. */
-static int
-is_namespace_ancestor (root, child)
- tree root, child;
+bool
+is_ancestor (tree root, tree child)
{
- if (root == child)
- return 1;
+ my_friendly_assert ((TREE_CODE (root) == NAMESPACE_DECL
+ || TREE_CODE (root) == FUNCTION_DECL
+ || CLASS_TYPE_P (root)), 20030307);
+ my_friendly_assert ((TREE_CODE (child) == NAMESPACE_DECL
+ || TREE_CODE (root) == FUNCTION_DECL
+ || CLASS_TYPE_P (child)),
+ 20030307);
+
+ /* The global namespace encloses everything. */
if (root == global_namespace)
- return 1;
- if (child == global_namespace)
- return 0;
- return is_namespace_ancestor (root, CP_DECL_CONTEXT (child));
+ return true;
+
+ while (true)
+ {
+ /* If we've run out of scopes, stop. */
+ if (!child)
+ return false;
+ /* If we've reached the ROOT, it encloses CHILD. */
+ if (root == child)
+ return true;
+ /* Go out one level. */
+ if (TYPE_P (child))
+ child = TYPE_NAME (child);
+ child = DECL_CONTEXT (child);
+ }
}
-
/* Return the namespace that is the common ancestor
- of two given namespaces. */
+ of two given namespaces. */
tree
namespace_ancestor (ns1, ns2)
tree ns1, ns2;
{
- if (is_namespace_ancestor (ns1, ns2))
- return ns1;
- return namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2);
+ timevar_push (TV_NAME_LOOKUP);
+ if (is_ancestor (ns1, ns2))
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ns1);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+ namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2));
}
/* Insert used into the using list of user. Set indirect_flag if this
@@ -4114,40 +3718,42 @@ add_using_namespace (user, used, indirect)
int indirect;
{
tree t;
- /* Using oneself is a no-op. */
+ timevar_push (TV_NAME_LOOKUP);
+ /* Using oneself is a no-op. */
if (user == used)
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380);
my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380);
- /* Check if we already have this. */
+ /* Check if we already have this. */
t = purpose_member (used, DECL_NAMESPACE_USING (user));
if (t != NULL_TREE)
{
if (!indirect)
- /* Promote to direct usage. */
+ /* Promote to direct usage. */
TREE_INDIRECT_USING (t) = 0;
- return;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
}
- /* Add used to the user's using list. */
+ /* Add used to the user's using list. */
DECL_NAMESPACE_USING (user)
= tree_cons (used, namespace_ancestor (user, used),
DECL_NAMESPACE_USING (user));
TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect;
- /* Add user to the used's users list. */
+ /* Add user to the used's users list. */
DECL_NAMESPACE_USERS (used)
= tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
- /* Recursively add all namespaces used. */
+ /* Recursively add all namespaces used. */
for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))
/* indirect usage */
add_using_namespace (user, TREE_PURPOSE (t), 1);
- /* Tell everyone using us about the new used namespaces. */
+ /* Tell everyone using us about the new used namespaces. */
for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t))
add_using_namespace (TREE_PURPOSE (t), used, 1);
+ timevar_pop (TV_NAME_LOOKUP);
}
/* Combines two sets of overloaded functions into an OVERLOAD chain, removing
@@ -4196,23 +3802,19 @@ merge_functions (s1, s2)
XXX In what way should I treat extern declarations?
XXX I don't want to repeat the entire duplicate_decls here */
-static tree
-ambiguous_decl (name, old, new, flags)
- tree name;
- tree old;
- tree new;
- int flags;
+static cxx_binding *
+ambiguous_decl (tree name, cxx_binding *old, cxx_binding *new, int flags)
{
tree val, type;
- my_friendly_assert (old != NULL_TREE, 393);
- /* Copy the value. */
+ my_friendly_assert (old != NULL, 393);
+ /* Copy the value. */
val = BINDING_VALUE (new);
if (val)
switch (TREE_CODE (val))
{
case TEMPLATE_DECL:
/* If we expect types or namespaces, and not templates,
- or this is not a template class. */
+ or this is not a template class. */
if (LOOKUP_QUALIFIERS_ONLY (flags)
&& !DECL_CLASS_TEMPLATE_P (val))
val = NULL_TREE;
@@ -4247,7 +3849,7 @@ ambiguous_decl (name, old, new, flags)
}
else
{
- /* Some declarations are functions, some are not. */
+ /* Some declarations are functions, some are not. */
if (flags & LOOKUP_COMPLAIN)
{
/* If we've already given this error for this lookup,
@@ -4264,7 +3866,7 @@ ambiguous_decl (name, old, new, flags)
BINDING_VALUE (old) = error_mark_node;
}
}
- /* ... and copy the type. */
+ /* ... and copy the type. */
type = BINDING_TYPE (new);
if (LOOKUP_NAMESPACES_ONLY (flags))
type = NULL_TREE;
@@ -4287,60 +3889,64 @@ ambiguous_decl (name, old, new, flags)
We are currently looking for names in namespace SCOPE, so we
look through USINGS for using-directives of namespaces
which have SCOPE as a common ancestor with the current scope.
- Returns zero on errors. */
+ Returns zero on errors. */
-int
-lookup_using_namespace (name, val, usings, scope, flags, spacesp)
- tree name, val, usings, scope;
- int flags;
- tree *spacesp;
+bool
+lookup_using_namespace (tree name, cxx_binding *val, tree usings,
+ tree scope, int flags, tree *spacesp)
{
tree iter;
- tree val1;
+ cxx_binding *val1;
+ timevar_push (TV_NAME_LOOKUP);
/* Iterate over all used namespaces in current, searching for using
- directives of scope. */
+ directives of scope. */
for (iter = usings; iter; iter = TREE_CHAIN (iter))
if (TREE_VALUE (iter) == scope)
{
if (spacesp)
*spacesp = tree_cons (TREE_PURPOSE (iter), NULL_TREE,
*spacesp);
- val1 = binding_for_name (name, TREE_PURPOSE (iter));
- /* Resolve ambiguities. */
- val = ambiguous_decl (name, val, val1, flags);
+ val1 = cxx_scope_find_binding_for_name (TREE_PURPOSE (iter), name);
+ /* Resolve possible ambiguities. */
+ if (val1)
+ val = ambiguous_decl (name, val, val1, flags);
}
- return BINDING_VALUE (val) != error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+ BINDING_VALUE (val) != error_mark_node);
}
/* [namespace.qual]
Accepts the NAME to lookup and its qualifying SCOPE.
- Returns the name/type pair found into the CPLUS_BINDING RESULT,
- or 0 on error. */
+ Returns the name/type pair found into the cxx_binding *RESULT,
+ or 0 on error. */
-int
-qualified_lookup_using_namespace (name, scope, result, flags)
- tree name;
- tree scope;
- tree result;
- int flags;
+bool
+qualified_lookup_using_namespace (tree name, tree scope, cxx_binding *result,
+ int flags)
{
- /* Maintain a list of namespaces visited... */
+ /* Maintain a list of namespaces visited... */
tree seen = NULL_TREE;
- /* ... and a list of namespace yet to see. */
+ /* ... and a list of namespace yet to see. */
tree todo = NULL_TREE;
tree usings;
+ timevar_push (TV_NAME_LOOKUP);
/* Look through namespace aliases. */
scope = ORIGINAL_NAMESPACE (scope);
- while (scope && (result != error_mark_node))
+ while (scope && result->value != error_mark_node)
{
- seen = tree_cons (scope, NULL_TREE, seen);
- result = ambiguous_decl (name, result,
- binding_for_name (name, scope), flags);
+ cxx_binding *b = cxx_scope_find_binding_for_name (scope, name);
+ /* Record SCOPE and resolve declaration ambiguities if NAME was
+ bound in SCOPE. */
+ if (b)
+ {
+ seen = tree_cons (scope, NULL_TREE, seen);
+ result = ambiguous_decl (name, result, b, flags);
+ }
if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
- /* Consider using directives. */
+ /* Consider using directives. */
for (usings = DECL_NAMESPACE_USING (scope); usings;
usings = TREE_CHAIN (usings))
- /* If this was a real directive, and we have not seen it. */
+ /* If this was a real directive, and we have not seen it. */
if (!TREE_INDIRECT_USING (usings)
&& !purpose_member (TREE_PURPOSE (usings), seen))
todo = tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
@@ -4350,15 +3956,15 @@ qualified_lookup_using_namespace (name, scope, result, flags)
todo = TREE_CHAIN (todo);
}
else
- scope = NULL_TREE; /* If there never was a todo list. */
+ scope = NULL_TREE; /* If there never was a todo list. */
}
- return result != error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result->value != error_mark_node);
}
/* [namespace.memdef]/2 */
/* Set the context of a declaration to scope. Complain if we are not
- outside scope. */
+ outside scope. */
void
set_decl_namespace (decl, scope, friendp)
@@ -4368,20 +3974,20 @@ set_decl_namespace (decl, scope, friendp)
{
tree old;
- /* Get rid of namespace aliases. */
+ /* Get rid of namespace aliases. */
scope = ORIGINAL_NAMESPACE (scope);
/* It is ok for friends to be qualified in parallel space. */
- if (!friendp && !is_namespace_ancestor (current_namespace, scope))
+ if (!friendp && !is_ancestor (current_namespace, scope))
error ("declaration of `%D' not in a namespace surrounding `%D'",
decl, scope);
DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
if (scope != current_namespace)
{
- /* See whether this has been declared in the namespace. */
+ /* See whether this has been declared in the namespace. */
old = namespace_binding (DECL_NAME (decl), scope);
if (!old)
- /* No old declaration at all. */
+ /* No old declaration at all. */
goto complain;
/* A template can be explicitly specialized in any namespace. */
if (processing_explicit_instantiation)
@@ -4391,7 +3997,7 @@ set_decl_namespace (decl, scope, friendp)
since it can't check for the correct constness at this
point. pushdecl will find those errors later. */
return;
- /* Since decl is a function, old should contain a function decl. */
+ /* Since decl is a function, old should contain a function decl. */
if (!is_overloaded_fn (old))
goto complain;
if (processing_template_decl || processing_specialization)
@@ -4411,34 +4017,35 @@ set_decl_namespace (decl, scope, friendp)
decl, scope);
}
-/* Compute the namespace where a declaration is defined. */
+/* Compute the namespace where a declaration is defined. */
static tree
decl_namespace (decl)
tree decl;
{
+ timevar_push (TV_NAME_LOOKUP);
if (TYPE_P (decl))
decl = TYPE_STUB_DECL (decl);
while (DECL_CONTEXT (decl))
{
decl = DECL_CONTEXT (decl);
if (TREE_CODE (decl) == NAMESPACE_DECL)
- return decl;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
if (TYPE_P (decl))
decl = TYPE_STUB_DECL (decl);
my_friendly_assert (DECL_P (decl), 390);
}
- return global_namespace;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, global_namespace);
}
-/* Return the namespace where the current declaration is declared. */
+/* Return the namespace where the current declaration is declared. */
tree
current_decl_namespace ()
{
tree result;
- /* If we have been pushed into a different namespace, use it. */
+ /* If we have been pushed into a different namespace, use it. */
if (decl_namespace_list)
return TREE_PURPOSE (decl_namespace_list);
@@ -4451,7 +4058,7 @@ current_decl_namespace ()
return result;
}
-/* Temporarily set the namespace for the current declaration. */
+/* Temporarily set the namespace for the current declaration. */
void
push_decl_namespace (decl)
@@ -4469,7 +4076,7 @@ pop_decl_namespace ()
decl_namespace_list = TREE_CHAIN (decl_namespace_list);
}
-/* Enter a class or namespace scope. */
+/* Enter a class or namespace scope. */
void
push_scope (t)
@@ -4477,11 +4084,11 @@ push_scope (t)
{
if (TREE_CODE (t) == NAMESPACE_DECL)
push_decl_namespace (t);
- else
+ else if (CLASS_TYPE_P (t))
pushclass (t, 2);
}
-/* Leave scope pushed by push_scope. */
+/* Leave scope pushed by push_scope. */
void
pop_scope (t)
@@ -4489,13 +4096,12 @@ pop_scope (t)
{
if (TREE_CODE (t) == NAMESPACE_DECL)
pop_decl_namespace ();
- else
+ else if (CLASS_TYPE_P (t))
popclass ();
}
/* [basic.lookup.koenig] */
-/* A non-zero return value in the functions below indicates an error.
- All nodes allocated in the procedure are on the scratch obstack. */
+/* A nonzero return value in the functions below indicates an error. */
struct arg_lookup
{
@@ -4528,7 +4134,7 @@ add_function (k, fn)
total number of functions being compared, which should usually be the
case. */
- /* We must find only functions, or exactly one non-function. */
+ /* We must find only functions, or exactly one non-function. */
if (!k->functions)
k->functions = fn;
else if (is_overloaded_fn (k->functions) && is_overloaded_fn (fn))
@@ -4642,21 +4248,21 @@ arg_assoc_class (k, type)
if (arg_assoc_namespace (k, context))
return 1;
- /* Process baseclasses. */
+ /* Process baseclasses. */
for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); i++)
if (arg_assoc_class (k, TYPE_BINFO_BASETYPE (type, i)))
return 1;
- /* Process friends. */
+ /* Process friends. */
for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
list = TREE_CHAIN (list))
if (k->name == TREE_PURPOSE (list))
for (friends = TREE_VALUE (list); friends;
friends = TREE_CHAIN (friends))
/* Only interested in global functions with potentially hidden
- (i.e. unqualified) declarations. */
+ (i.e. unqualified) declarations. */
if (TREE_PURPOSE (friends) == error_mark_node && TREE_VALUE (friends)
- && decl_namespace (TREE_VALUE (friends)) == context)
+ && CP_DECL_CONTEXT (TREE_VALUE (friends)) == context)
if (add_function (k, TREE_VALUE (friends)))
return 1;
@@ -4701,7 +4307,7 @@ arg_assoc_type (k, type)
case ENUMERAL_TYPE:
return arg_assoc_namespace (k, decl_namespace (TYPE_MAIN_DECL (type)));
case OFFSET_TYPE:
- /* Pointer to member: associate class type and value type. */
+ /* Pointer to member: associate class type and value type. */
if (arg_assoc_type (k, TYPE_OFFSET_BASETYPE (type)))
return 1;
return arg_assoc_type (k, TREE_TYPE (type));
@@ -4709,10 +4315,10 @@ arg_assoc_type (k, type)
/* The basetype is referenced in the first arg type, so just
fall through. */
case FUNCTION_TYPE:
- /* Associate the parameter types. */
+ /* Associate the parameter types. */
if (arg_assoc_args (k, TYPE_ARG_TYPES (type)))
return 1;
- /* Associate the return type. */
+ /* Associate the return type. */
return arg_assoc_type (k, TREE_TYPE (type));
case TEMPLATE_TYPE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
@@ -4766,6 +4372,8 @@ arg_assoc (k, n)
n = TREE_OPERAND (n, 1);
while (TREE_CODE (n) == TREE_LIST)
n = TREE_VALUE (n);
+ if (TREE_CODE (n) == BASELINK)
+ n = BASELINK_FUNCTIONS (n);
if (TREE_CODE (n) == FUNCTION_DECL)
return arg_assoc_type (k, TREE_TYPE (n));
@@ -4819,7 +4427,7 @@ arg_assoc (k, n)
}
/* Performs Koenig lookup depending on arguments, where fns
- are the functions found in normal lookup. */
+ are the functions found in normal lookup. */
tree
lookup_arg_dependent (name, fns, args)
@@ -4830,6 +4438,10 @@ lookup_arg_dependent (name, fns, args)
struct arg_lookup k;
tree fn = NULL_TREE;
+ if (fns == error_mark_node)
+ fns = NULL_TREE;
+
+ timevar_push (TV_NAME_LOOKUP);
k.name = name;
k.functions = fns;
k.classes = NULL_TREE;
@@ -4844,10 +4456,10 @@ lookup_arg_dependent (name, fns, args)
unqualified_namespace_lookup (name, 0, &k.namespaces);
arg_assoc_args (&k, args);
- return k.functions;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, k.functions);
}
-/* Process a namespace-alias declaration. */
+/* Process a namespace-alias declaration. */
void
do_namespace_alias (alias, namespace)
@@ -4855,21 +4467,21 @@ do_namespace_alias (alias, namespace)
{
if (TREE_CODE (namespace) != NAMESPACE_DECL)
{
- /* The parser did not find it, so it's not there. */
+ /* The parser did not find it, so it's not there. */
error ("unknown namespace `%D'", namespace);
return;
}
namespace = ORIGINAL_NAMESPACE (namespace);
- /* Build the alias. */
+ /* Build the alias. */
alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node);
DECL_NAMESPACE_ALIAS (alias) = namespace;
pushdecl (alias);
}
/* Check a non-member using-declaration. Return the name and scope
- being used, and the USING_DECL, or NULL_TREE on failure. */
+ being used, and the USING_DECL, or NULL_TREE on failure. */
static tree
validate_nonmember_using_decl (decl, scope, name)
@@ -4922,11 +4534,11 @@ validate_nonmember_using_decl (decl, scope, name)
abort ();
if (DECL_P (*name))
*name = DECL_NAME (*name);
- /* Make a USING_DECL. */
+ /* Make a USING_DECL. */
return push_using_decl (*scope, *name);
}
-/* Process local and global using-declarations. */
+/* Process local and global using-declarations. */
static void
do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
@@ -4934,33 +4546,34 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
tree oldval, oldtype;
tree *newval, *newtype;
{
- tree decls;
+ cxx_binding decls;
*newval = *newtype = NULL_TREE;
- decls = make_node (CPLUS_BINDING);
- if (!qualified_lookup_using_namespace (name, scope, decls, 0))
+ cxx_binding_clear (&decls);
+ if (!qualified_lookup_using_namespace (name, scope, &decls, 0))
/* Lookup error */
return;
- if (!BINDING_VALUE (decls) && !BINDING_TYPE (decls))
+ if (!decls.value && !decls.type)
{
error ("`%D' not declared", name);
return;
}
- /* Check for using functions. */
- if (BINDING_VALUE (decls) && is_overloaded_fn (BINDING_VALUE (decls)))
+ /* Check for using functions. */
+ if (decls.value && is_overloaded_fn (decls.value))
{
tree tmp, tmp1;
if (oldval && !is_overloaded_fn (oldval))
{
- duplicate_decls (OVL_CURRENT (BINDING_VALUE (decls)), oldval);
+ if (!DECL_IMPLICIT_TYPEDEF_P (oldval))
+ error ("`%D' is already declared in this scope", name);
oldval = NULL_TREE;
}
*newval = oldval;
- for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp))
+ for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp))
{
tree new_fn = OVL_CURRENT (tmp);
@@ -4982,21 +4595,27 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
{
- /* If this using declaration introduces a function
- recognized as a built-in, no longer mark it as
- anticipated in this scope. */
- if (DECL_ANTICIPATED (old_fn))
- {
- DECL_ANTICIPATED (old_fn) = 0;
- break;
- }
-
/* There was already a non-using declaration in
this scope with the same parameter types. If both
are the same extern "C" functions, that's ok. */
- if (!decls_match (new_fn, old_fn))
- error ("`%D' is already declared in this scope", name);
- break;
+ if (decls_match (new_fn, old_fn))
+ {
+ /* If the OLD_FN was a builtin, there is now a
+ real declaration. */
+ if (DECL_ANTICIPATED (old_fn))
+ DECL_ANTICIPATED (old_fn) = 0;
+ break;
+ }
+ else if (!DECL_ANTICIPATED (old_fn))
+ {
+ /* If the OLD_FN was really declared, the
+ declarations don't match. */
+ error ("`%D' is already declared in this scope", name);
+ break;
+ }
+
+ /* If the OLD_FN was not really there, just ignore
+ it and keep going. */
}
}
@@ -5014,13 +4633,13 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
}
else
{
- *newval = BINDING_VALUE (decls);
- if (oldval)
- duplicate_decls (*newval, oldval);
+ *newval = decls.value;
+ if (oldval && !decls_match (*newval, oldval))
+ error ("`%D' is already declared in this scope", name);
}
- *newtype = BINDING_TYPE (decls);
- if (oldtype && *newtype && oldtype != *newtype)
+ *newtype = decls.type;
+ if (oldtype && *newtype && !same_type_p (oldtype, *newtype))
{
error ("using declaration `%D' introduced ambiguous type `%T'",
name, oldtype);
@@ -5028,19 +4647,22 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
}
}
-/* Process a using-declaration not appearing in class or local scope. */
+/* Process a using-declaration not appearing in class or local scope. */
void
do_toplevel_using_decl (decl)
tree decl;
{
- tree scope, name, binding;
+ tree scope, name;
tree oldval, oldtype, newval, newtype;
+ cxx_binding *binding;
decl = validate_nonmember_using_decl (decl, &scope, &name);
if (decl == NULL_TREE)
return;
-
+
+ /* A multiple using-declaration is valid, so we call binding_for_name,
+ not just cxx_binding_make. */
binding = binding_for_name (name, current_namespace);
oldval = BINDING_VALUE (binding);
@@ -5048,7 +4670,7 @@ do_toplevel_using_decl (decl)
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
- /* Copy declarations found. */
+ /* Copy declarations found. */
if (newval)
BINDING_VALUE (binding) = newval;
if (newtype)
@@ -5130,6 +4752,13 @@ do_class_using_decl (decl)
}
if (TREE_CODE (name) == TYPE_DECL || TREE_CODE (name) == TEMPLATE_DECL)
name = DECL_NAME (name);
+ else if (BASELINK_P (name))
+ {
+ name = BASELINK_FUNCTIONS (name);
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ name = TREE_OPERAND (name, 0);
+ name = DECL_NAME (get_first_fn (name));
+ }
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
@@ -5138,7 +4767,7 @@ do_class_using_decl (decl)
return value;
}
-/* Process a using-directive. */
+/* Process a using-directive. */
void
do_using_directive (namespace)
@@ -5152,7 +4781,7 @@ do_using_directive (namespace)
namespace = TREE_OPERAND (namespace, 1);
if (TREE_CODE (namespace) == IDENTIFIER_NODE)
{
- /* Lookup in lexer did not find a namespace. */
+ /* Lookup in lexer did not find a namespace. */
if (!processing_template_decl)
error ("namespace `%T' undeclared", namespace);
return;
@@ -5195,10 +4824,15 @@ mark_used (decl)
tree decl;
{
TREE_USED (decl) = 1;
- if (processing_template_decl)
+ if (processing_template_decl || skip_evaluation)
return;
- if (!skip_evaluation)
- assemble_external (decl);
+
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
+ && !TREE_ASM_WRITTEN (decl))
+ /* Remember it, so we can check it was defined. */
+ defer_fn (decl);
+
+ assemble_external (decl);
/* Is it a synthesized method that needs to be synthesized? */
if (TREE_CODE (decl) == FUNCTION_DECL
@@ -5222,21 +4856,48 @@ mark_used (decl)
&& DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
&& (!DECL_EXPLICIT_INSTANTIATION (decl)
|| (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))))
- instantiate_decl (decl, /*defer_ok=*/1);
+ {
+ bool defer;
+
+ /* Normally, we put off instantiating functions in order to
+ improve compile times. Maintaining a stack of active
+ functions is expensive, and the inliner knows to
+ instantiate any functions it might need.
+
+ However, if instantiating this function might help us mark
+ the current function TREE_NOTHROW, we go ahead and
+ instantiate it now. */
+ defer = (!flag_exceptions
+ || TREE_CODE (decl) != FUNCTION_DECL
+ /* If the called function can't throw, we don't need to
+ generate its body to find that out. */
+ || TREE_NOTHROW (decl)
+ || !cfun
+ /* If we already know the current function can't throw,
+ then we don't need to work hard to prove it. */
+ || TREE_NOTHROW (current_function_decl)
+ /* If we already know that the current function *can*
+ throw, there's no point in gathering more
+ information. */
+ || cp_function_chain->can_throw);
+
+ instantiate_decl (decl, defer);
+ }
}
/* Helper function for class_head_decl and class_head_defn
nonterminals. AGGR is the class, union or struct tag. SCOPE is the
explicit scope used (NULL for no scope resolution). ID is the
name. DEFN_P is true, if this is a definition of the class and
- NEW_TYPE_P is set to non-zero, if we push into the scope containing
+ NEW_TYPE_P is set to nonzero, if we push into the scope containing
the to be defined aggregate.
Return a TYPE_DECL for the type declared by ID in SCOPE. */
tree
-handle_class_head (aggr, scope, id, defn_p, new_type_p)
- tree aggr, scope, id;
+handle_class_head (tag_kind, scope, id, attributes, defn_p, new_type_p)
+ enum tag_types tag_kind;
+ tree scope, id, attributes;
int defn_p;
int *new_type_p;
{
@@ -5286,7 +4947,10 @@ handle_class_head (aggr, scope, id, defn_p, new_type_p)
if (!decl)
{
- decl = TYPE_MAIN_DECL (xref_tag (aggr, id, !defn_p));
+ decl = xref_tag (tag_kind, id, attributes, !defn_p);
+ if (decl == error_mark_node)
+ return error_mark_node;
+ decl = TYPE_MAIN_DECL (decl);
xrefd_p = true;
}
@@ -5319,6 +4983,18 @@ handle_class_head (aggr, scope, id, defn_p, new_type_p)
is different to the current scope. */
tree context = CP_DECL_CONTEXT (decl);
+ if (IMPLICIT_TYPENAME_P (context))
+ context = TREE_TYPE (context);
+
+ /* If that scope does not contain the scope in which the
+ class was originally declared, the program is invalid. */
+ if (current && !is_ancestor (current, context))
+ {
+ error ("declaration of `%D' in `%D' which does not "
+ "enclose `%D'", decl, current, CP_DECL_CONTEXT (decl));
+ return NULL_TREE;
+ }
+
*new_type_p = (current != context
&& TREE_CODE (context) != TEMPLATE_TYPE_PARM
&& TREE_CODE (context) != BOUND_TEMPLATE_TEMPLATE_PARM);
@@ -5326,27 +5002,79 @@ handle_class_head (aggr, scope, id, defn_p, new_type_p)
push_scope (context);
if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
- /* It is legal to define a class with a different class key,
+ /* It is valid to define a class with a different class key,
and this changes the default member access. */
CLASSTYPE_DECLARED_CLASS (TREE_TYPE (decl))
- = aggr == class_type_node;
+ = (tag_kind == class_type);
if (!xrefd_p && PROCESSING_REAL_TEMPLATE_DECL_P ())
decl = push_template_decl (decl);
}
+ else
+ {
+ /* For elaborated type specifier in declaration like
+
+ class A::B *a;
+
+ we get an implicit typename here. Let's remove its
+ implicitness so that we don't issue any implicit
+ typename warning later. Note that when defn_p is true,
+ implicitness is still required by begin_class_definition. */
+ if (IMPLICIT_TYPENAME_P (type))
+ decl = TYPE_STUB_DECL (build_typename_type (TYPE_CONTEXT (type),
+ TYPE_IDENTIFIER (type),
+ TYPENAME_TYPE_FULLNAME (type),
+ NULL_TREE));
+ }
return decl;
}
-/* Initialize decl2.c. */
+/* Like handle_class_head but for a definition of a class specialization.
+ DECL is a TYPE_DECL node representing the class. NEW_TYPE_P is set to
+ nonzero, if we push into the scope containing the to be defined
+ aggregate.
-void
-init_decl2 ()
+ Return a TYPE_DECL for the type declared by ID in SCOPE. */
+
+tree
+handle_class_head_apparent_template (decl, new_type_p)
+ tree decl;
+ int *new_type_p;
{
- ggc_add_tree_varray_root (&deferred_fns, 1);
- ggc_add_tree_varray_root (&pending_statics, 1);
- ggc_add_tree_varray_root (&ssdf_decls, 1);
- ggc_add_tree_root (&ssdf_decl, 1);
- ggc_add_tree_root (&priority_decl, 1);
- ggc_add_tree_root (&initialize_p_decl, 1);
+ tree context;
+ tree current;
+
+ if (decl == error_mark_node)
+ return decl;
+
+ current = current_scope ();
+ if (current == NULL_TREE)
+ current = current_namespace;
+
+ *new_type_p = 0;
+
+ /* For a definition, we want to enter the containing scope
+ before looking up any base classes etc. Only do so, if this
+ is different to the current scope. */
+ context = CP_DECL_CONTEXT (decl);
+
+ if (IMPLICIT_TYPENAME_P (context))
+ context = TREE_TYPE (context);
+
+ *new_type_p = (current != context
+ && TREE_CODE (context) != TEMPLATE_TYPE_PARM
+ && TREE_CODE (context) != BOUND_TEMPLATE_TEMPLATE_PARM);
+ if (*new_type_p)
+ push_scope (context);
+
+ if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+ /* We might be specializing a template with a different
+ class-key. */
+ CLASSTYPE_DECLARED_CLASS (TREE_TYPE (decl))
+ = (current_aggr == class_type_node);
+
+ return decl;
}
+
+#include "gt-cp-decl2.h"
diff --git a/contrib/gcc/cp/dump.c b/contrib/gcc/cp/dump.c
index 6dd60ba..39e72dc 100644
--- a/contrib/gcc/cp/dump.c
+++ b/contrib/gcc/cp/dump.c
@@ -48,8 +48,7 @@ dump_access (di, t)
}
/* Dump a representation of the specific operator for an overloaded
- operator associated with node t.
-*/
+ operator associated with node t. */
static void
dump_op (di, t)
@@ -264,6 +263,14 @@ cp_dump_tree (dump_info, t)
return 1;
}
+ /* Is it a type used as a base? */
+ if (TYPE_CONTEXT (t) && TREE_CODE (TYPE_CONTEXT (t)) == TREE_CODE (t)
+ && CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t)
+ {
+ dump_child ("bfld", TYPE_CONTEXT (t));
+ return 1;
+ }
+
dump_child ("vfld", TYPE_VFIELD (t));
if (CLASSTYPE_TEMPLATE_SPECIALIZATION(t))
dump_string(di, "spec");
@@ -324,7 +331,6 @@ cp_dump_tree (dump_info, t)
dump_string (di, "global init");
if (DECL_GLOBAL_DTOR_P (t))
dump_string (di, "global fini");
- dump_int (di, "prio", GLOBAL_INIT_PRIORITY (t));
}
if (DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t))
dump_string (di, "pseudo tmpl");
@@ -390,15 +396,6 @@ cp_dump_tree (dump_info, t)
dump_child ("decl", TREE_OPERAND (t, 2));
break;
- case CTOR_STMT:
- dump_stmt (di, t);
- if (CTOR_BEGIN_P (t))
- dump_string (di, "begn");
- else
- dump_string (di, "end");
- dump_next_stmt (di, t);
- break;
-
case HANDLER:
dump_stmt (di, t);
dump_child ("parm", HANDLER_PARMS (t));
@@ -412,12 +409,6 @@ cp_dump_tree (dump_info, t)
dump_next_stmt (di, t);
break;
- case SUBOBJECT:
- dump_stmt (di, t);
- dump_child ("clnp", TREE_OPERAND (t, 0));
- dump_next_stmt (di, t);
- break;
-
case USING_STMT:
dump_stmt (di, t);
dump_child ("nmsp", USING_STMT_NAMESPACE (t));
@@ -428,6 +419,5 @@ cp_dump_tree (dump_info, t)
break;
}
- return 0;
+ return c_dump_tree (di, t);
}
-
diff --git a/contrib/gcc/cp/error.c b/contrib/gcc/cp/error.c
index a0217ae..804c918 100644
--- a/contrib/gcc/cp/error.c
+++ b/contrib/gcc/cp/error.c
@@ -24,10 +24,10 @@ Boston, MA 02111-1307, USA. */
#include "tree.h"
#include "cp-tree.h"
#include "real.h"
-#include "obstack.h"
#include "toplev.h"
#include "flags.h"
#include "diagnostic.h"
+#include "langhooks-def.h"
enum pad { none, before, after };
@@ -44,11 +44,6 @@ enum pad { none, before, after };
print_non_consecutive_character ((BUFFER), '<')
#define print_template_argument_list_end(BUFFER) \
print_non_consecutive_character ((BUFFER), '>')
-#define print_whitespace(BUFFER, TFI) \
- do { \
- output_add_space (BUFFER); \
- put_whitespace (TFI) = none; \
- } while (0)
#define print_tree_identifier(BUFFER, TID) \
output_add_string ((BUFFER), IDENTIFIER_POINTER (TID))
#define print_identifier(BUFFER, ID) output_add_string ((BUFFER), (ID))
@@ -104,20 +99,19 @@ static void dump_scope PARAMS ((tree, int));
static void dump_template_parms PARAMS ((tree, int, int));
static const char *function_category PARAMS ((tree));
-static void lang_print_error_function PARAMS ((diagnostic_context *,
- const char *));
-static void maybe_print_instantiation_context PARAMS ((output_buffer *));
-static void print_instantiation_full_context PARAMS ((output_buffer *));
-static void print_instantiation_partial_context PARAMS ((output_buffer *, tree,
+static void maybe_print_instantiation_context PARAMS ((diagnostic_context *));
+static void print_instantiation_full_context PARAMS ((diagnostic_context *));
+static void print_instantiation_partial_context PARAMS ((diagnostic_context *,
+ tree,
const char *, int));
-static void cp_diagnostic_starter PARAMS ((output_buffer *,
- diagnostic_context *));
-static void cp_diagnostic_finalizer PARAMS ((output_buffer *,
- diagnostic_context *));
-static void cp_print_error_function PARAMS ((output_buffer *,
- diagnostic_context *));
-
-static int cp_printer PARAMS ((output_buffer *));
+static void cp_diagnostic_starter PARAMS ((diagnostic_context *,
+ diagnostic_info *));
+static void cp_diagnostic_finalizer PARAMS ((diagnostic_context *,
+ diagnostic_info *));
+static void cp_print_error_function PARAMS ((diagnostic_context *,
+ diagnostic_info *));
+
+static bool cp_printer PARAMS ((output_buffer *, text_info *));
static void print_non_consecutive_character PARAMS ((output_buffer *, int));
static void print_integer PARAMS ((output_buffer *, HOST_WIDE_INT));
static tree locate_error PARAMS ((const char *, va_list));
@@ -125,7 +119,6 @@ static tree locate_error PARAMS ((const char *, va_list));
void
init_error ()
{
- print_error_function = lang_print_error_function;
diagnostic_starter (global_dc) = cp_diagnostic_starter;
diagnostic_finalizer (global_dc) = cp_diagnostic_finalizer;
diagnostic_format_decoder (global_dc) = cp_printer;
@@ -322,8 +315,8 @@ dump_template_bindings (parms, args)
}
}
-/* Dump into the obstack a human-readable equivalent of TYPE. FLAGS
- controls the format. */
+/* Dump a human-readable equivalent of TYPE. FLAGS controls the
+ format. */
static void
dump_type (t, flags)
@@ -387,7 +380,7 @@ dump_type (t, flags)
which has no name and is not very useful for diagnostics. So
look up the equivalent C type and print its name. */
tree elt = TREE_TYPE (t);
- elt = type_for_mode (TYPE_MODE (elt), TREE_UNSIGNED (elt));
+ elt = c_common_type_for_mode (TYPE_MODE (elt), TREE_UNSIGNED (elt));
dump_type (elt, flags);
}
break;
@@ -417,7 +410,7 @@ dump_type (t, flags)
break;
case TEMPLATE_TEMPLATE_PARM:
- /* For parameters inside template signature. */
+ /* For parameters inside template signature. */
if (TYPE_IDENTIFIER (t))
print_tree_identifier (scratch_buffer, TYPE_IDENTIFIER (t));
else
@@ -459,7 +452,7 @@ dump_type (t, flags)
break;
}
case TYPENAME_TYPE:
- if (IMPLICIT_TYPENAME_P (t))
+ if (!IMPLICIT_TYPENAME_P (t))
output_add_string (scratch_buffer, "typename ");
dump_typename (t, flags);
break;
@@ -479,7 +472,7 @@ dump_type (t, flags)
default:
sorry_for_unsupported_tree (t);
- /* Fall through to error. */
+ /* Fall through to error. */
case ERROR_MARK:
print_identifier (scratch_buffer, "<type error>");
@@ -692,6 +685,7 @@ dump_type_prefix (t, flags)
case TYPENAME_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
+ case TYPEOF_TYPE:
dump_type (t, flags);
padding = before;
break;
@@ -788,6 +782,7 @@ dump_type_suffix (t, flags)
case TYPENAME_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
+ case TYPEOF_TYPE:
break;
default:
@@ -855,7 +850,7 @@ dump_decl (t, flags)
{
if ((flags & TFF_DECL_SPECIFIERS)
&& TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
- /* Say `class T' not just `T'. */
+ /* Say `class T' not just `T'. */
output_add_string (scratch_buffer, "class ");
dump_type (TREE_TYPE (t), flags);
@@ -1013,7 +1008,11 @@ dump_decl (t, flags)
output_add_string (scratch_buffer, "using ");
dump_type (DECL_INITIAL (t), flags);
print_scope_operator (scratch_buffer);
- print_tree_identifier (scratch_buffer, DECL_NAME (t));
+ dump_decl (DECL_NAME (t), flags);
+ break;
+
+ case BASELINK:
+ dump_decl (BASELINK_FUNCTIONS (t), flags);
break;
default:
@@ -1065,7 +1064,7 @@ dump_template_decl (t, flags)
nreverse(orig_parms);
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
- /* Say `template<arg> class TT' not just `template<arg> TT'. */
+ /* Say `template<arg> class TT' not just `template<arg> TT'. */
output_add_string (scratch_buffer, "class ");
}
@@ -1085,7 +1084,7 @@ dump_template_decl (t, flags)
dump_function_decl (t, flags | TFF_TEMPLATE_NAME);
break;
default:
- /* This case can occur with some illegal code. */
+ /* This case can occur with some invalid code. */
dump_type (TREE_TYPE (t),
(flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
| (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0));
@@ -1095,7 +1094,7 @@ dump_template_decl (t, flags)
/* Pretty print a function decl. There are several ways we want to print a
function declaration. The TFF_ bits in FLAGS tells us how to behave.
As error can only apply the '#' flag once to give 0 and 1 for V, there
- is %D which doesn't print the throw specs, and %F which does. */
+ is %D which doesn't print the throw specs, and %F which does. */
static void
dump_function_decl (t, flags)
@@ -1189,7 +1188,7 @@ dump_function_decl (t, flags)
/* Print a parameter list. If this is for a member function, the
member object ptr (and any other hidden args) should have
- already been removed. */
+ already been removed. */
static void
dump_parameters (parmtypes, flags)
@@ -1223,7 +1222,7 @@ dump_parameters (parmtypes, flags)
print_right_paren (scratch_buffer);
}
-/* Print an exception specification. T is the exception specification. */
+/* Print an exception specification. T is the exception specification. */
static void
dump_exception_spec (t, flags)
@@ -1256,6 +1255,9 @@ dump_function_name (t, flags)
{
tree name = DECL_NAME (t);
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ t = DECL_TEMPLATE_RESULT (t);
+
/* Don't let the user see __comp_ctor et al. */
if (DECL_CONSTRUCTOR_P (t)
|| DECL_DESTRUCTOR_P (t))
@@ -1436,16 +1438,16 @@ dump_expr_list (l, flags)
}
}
-/* Print out an expression E under control of FLAGS. */
+/* Print out an expression E under control of FLAGS. */
static void
dump_expr (t, flags)
tree t;
int flags;
{
- if (t == 0)
- return;
-
+ if (t == 0)
+ return;
+
switch (TREE_CODE (t))
{
case VAR_DECL:
@@ -1534,17 +1536,8 @@ dump_expr (t, flags)
break;
case REAL_CST:
-#ifndef REAL_IS_NOT_DOUBLE
- sprintf (digit_buffer, "%g", TREE_REAL_CST (t));
-#else
- {
- const unsigned char *p = (const unsigned char *) &TREE_REAL_CST (t);
- size_t i;
- strcpy (digit_buffer, "0x");
- for (i = 0; i < sizeof TREE_REAL_CST (t); i++)
- sprintf (digit_buffer + 2 + 2*i, "%02x", *p++);
- }
-#endif
+ real_to_decimal (digit_buffer, &TREE_REAL_CST (t),
+ sizeof (digit_buffer), 0, 1);
output_add_string (scratch_buffer, digit_buffer);
break;
@@ -1657,6 +1650,7 @@ dump_expr (t, flags)
case NEW_EXPR:
{
tree type = TREE_OPERAND (t, 1);
+ tree init = TREE_OPERAND (t, 2);
if (NEW_EXPR_USE_GLOBAL (t))
print_scope_operator (scratch_buffer);
output_add_string (scratch_buffer, "new ");
@@ -1673,10 +1667,17 @@ dump_expr (t, flags)
TREE_OPERAND (type, 1),
integer_one_node))));
dump_type (type, flags);
- if (TREE_OPERAND (t, 2))
+ if (init)
{
print_left_paren (scratch_buffer);
- dump_expr_list (TREE_OPERAND (t, 2), flags);
+ if (TREE_CODE (init) == TREE_LIST)
+ dump_expr_list (init, flags);
+ else if (init == void_zero_node)
+ /* This representation indicates an empty initializer,
+ e.g.: "new int()". */
+ ;
+ else
+ dump_expr (init, flags);
print_right_paren (scratch_buffer);
}
}
@@ -1860,7 +1861,7 @@ dump_expr (t, flags)
case CONSTRUCTOR:
if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
{
- tree idx = build_component_ref (t, pfn_identifier, NULL_TREE, 0);
+ tree idx = build_ptrmemfunc_access_expr (t, pfn_identifier);
if (integer_zerop (idx))
{
@@ -1898,9 +1899,19 @@ dump_expr (t, flags)
}
}
}
- output_add_character (scratch_buffer, '{');
- dump_expr_list (CONSTRUCTOR_ELTS (t), flags);
- output_add_character (scratch_buffer, '}');
+ /* We've gotten an rvalue of the form 'T()'. */
+ else if (TREE_TYPE (t))
+ {
+ dump_type (TREE_TYPE (t), flags);
+ print_left_paren (scratch_buffer);
+ print_right_paren (scratch_buffer);
+ }
+ else
+ {
+ output_add_character (scratch_buffer, '{');
+ dump_expr_list (CONSTRUCTOR_ELTS (t), flags);
+ output_add_character (scratch_buffer, '}');
+ }
break;
case OFFSET_REF:
@@ -1913,7 +1924,8 @@ dump_expr (t, flags)
/* A::f */
dump_expr (t, flags | TFF_EXPR_IN_PARENS);
else if (BASELINK_P (t))
- dump_expr (OVL_CURRENT (TREE_VALUE (t)), flags | TFF_EXPR_IN_PARENS);
+ dump_expr (OVL_CURRENT (BASELINK_FUNCTIONS (t)),
+ flags | TFF_EXPR_IN_PARENS);
else
dump_decl (t, flags);
}
@@ -2056,6 +2068,10 @@ dump_expr (t, flags)
output_add_string (scratch_buffer, ") break; ");
break;
+ case BASELINK:
+ print_tree_identifier (scratch_buffer, DECL_NAME (get_first_fn (t)));
+ break;
+
case TREE_LIST:
if (TREE_VALUE (t) && TREE_CODE (TREE_VALUE (t)) == FUNCTION_DECL)
{
@@ -2159,7 +2175,7 @@ context_as_string (context, flags)
return output_finalize_message (scratch_buffer);
}
-/* Generate the three forms of printable names for lang_printable_name. */
+/* Generate the three forms of printable names for cxx_printable_name. */
const char *
lang_decl_name (decl, v)
@@ -2238,7 +2254,7 @@ decl_to_string (decl, verbose)
|| TREE_CODE (decl) == UNION_TYPE || TREE_CODE (decl) == ENUMERAL_TYPE)
flags = TFF_CLASS_KEY_OR_ENUM;
if (verbose)
- flags |= TFF_DECL_SPECIFIERS | TFF_FUNCTION_DEFAULT_ARGUMENTS;
+ flags |= TFF_DECL_SPECIFIERS;
else if (TREE_CODE (decl) == FUNCTION_DECL)
flags |= TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE;
flags |= TFF_TEMPLATE_HEADER;
@@ -2405,70 +2421,63 @@ cv_to_string (p, v)
return output_finalize_message (scratch_buffer);
}
-static void
-lang_print_error_function (context, file)
+/* Langhook for print_error_function. */
+void
+cxx_print_error_function (context, file)
diagnostic_context *context;
const char *file;
{
- output_state os;
-
- default_print_error_function (context, file);
- os = output_buffer_state (context);
- output_set_prefix ((output_buffer *)context, file);
- maybe_print_instantiation_context ((output_buffer *)context);
- output_buffer_state (context) = os;
+ lhd_print_error_function (context, file);
+ output_set_prefix (&context->buffer, file);
+ maybe_print_instantiation_context (context);
}
static void
-cp_diagnostic_starter (buffer, dc)
- output_buffer *buffer;
- diagnostic_context *dc;
+cp_diagnostic_starter (context, diagnostic)
+ diagnostic_context *context;
+ diagnostic_info *diagnostic;
{
- report_problematic_module (buffer);
- cp_print_error_function (buffer, dc);
- maybe_print_instantiation_context (buffer);
- output_set_prefix (buffer,
- context_as_prefix (diagnostic_file_location (dc),
- diagnostic_line_location (dc),
- diagnostic_is_warning (dc)));
+ diagnostic_report_current_module (context);
+ cp_print_error_function (context, diagnostic);
+ maybe_print_instantiation_context (context);
+ output_set_prefix (&context->buffer, diagnostic_build_prefix (diagnostic));
}
static void
-cp_diagnostic_finalizer (buffer, dc)
- output_buffer *buffer;
- diagnostic_context *dc __attribute__ ((__unused__));
+cp_diagnostic_finalizer (context, diagnostic)
+ diagnostic_context *context;
+ diagnostic_info *diagnostic __attribute__((unused));
{
- output_destroy_prefix (buffer);
+ output_destroy_prefix (&context->buffer);
}
/* Print current function onto BUFFER, in the process of reporting
a diagnostic message. Called from cp_diagnostic_starter. */
static void
-cp_print_error_function (buffer, dc)
- output_buffer *buffer;
- diagnostic_context *dc;
+cp_print_error_function (context, diagnostic)
+ diagnostic_context *context;
+ diagnostic_info *diagnostic;
{
- if (error_function_changed ())
+ if (diagnostic_last_function_changed (context))
{
- char *prefix = diagnostic_file_location (dc)
- ? file_name_as_prefix (diagnostic_file_location (dc))
+ const char *old_prefix = output_prefix (&context->buffer);
+ char *new_prefix = diagnostic->location.file
+ ? file_name_as_prefix (diagnostic->location.file)
: NULL;
- output_state os;
- os = output_buffer_state (buffer);
- output_set_prefix (buffer, prefix);
+ output_set_prefix (&context->buffer, new_prefix);
if (current_function_decl == NULL)
- output_add_string (buffer, "At global scope:");
+ output_add_string (&context->buffer, "At global scope:");
else
- output_printf
- (buffer, "In %s `%s':", function_category (current_function_decl),
- (*decl_printable_name) (current_function_decl, 2));
- output_add_newline (buffer);
-
- record_last_error_function ();
- output_destroy_prefix (buffer);
- output_buffer_state (buffer) = os;
+ output_printf (&context->buffer, "In %s `%s':",
+ function_category (current_function_decl),
+ cxx_printable_name (current_function_decl, 2));
+ output_add_newline (&context->buffer);
+
+ diagnostic_set_last_function (context);
+ output_destroy_prefix (&context->buffer);
+ context->buffer.state.prefix = old_prefix;
}
}
@@ -2497,8 +2506,8 @@ function_category (fn)
/* Report the full context of a current template instantiation,
onto BUFFER. */
static void
-print_instantiation_full_context (buffer)
- output_buffer *buffer;
+print_instantiation_full_context (context)
+ diagnostic_context *context;
{
tree p = current_instantiation ();
int line = lineno;
@@ -2517,7 +2526,8 @@ print_instantiation_full_context (buffer)
if (current_function_decl == TINST_DECL (p))
/* Avoid redundancy with the the "In function" line. */;
else
- output_verbatim (buffer, "%s: In instantiation of `%s':\n", file,
+ output_verbatim (&context->buffer,
+ "%s: In instantiation of `%s':\n", file,
decl_as_string (TINST_DECL (p),
TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
@@ -2527,13 +2537,13 @@ print_instantiation_full_context (buffer)
}
}
- print_instantiation_partial_context (buffer, p, file, line);
+ print_instantiation_partial_context (context, p, file, line);
}
/* Same as above but less verbose. */
static void
-print_instantiation_partial_context (buffer, t, file, line)
- output_buffer *buffer;
+print_instantiation_partial_context (context, t, file, line)
+ diagnostic_context *context;
tree t;
const char *file;
int line;
@@ -2541,24 +2551,24 @@ print_instantiation_partial_context (buffer, t, file, line)
for (; t; t = TREE_CHAIN (t))
{
output_verbatim
- (buffer, "%s:%d: instantiated from `%s'\n", file, line,
+ (&context->buffer, "%s:%d: instantiated from `%s'\n", file, line,
decl_as_string (TINST_DECL (t), TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
line = TINST_LINE (t);
file = TINST_FILE (t);
}
- output_verbatim (buffer, "%s:%d: instantiated from here\n", file, line);
+ output_verbatim (&context->buffer, "%s:%d: instantiated from here\n", file, line);
}
/* Called from cp_thing to print the template context for an error. */
static void
-maybe_print_instantiation_context (buffer)
- output_buffer *buffer;
+maybe_print_instantiation_context (context)
+ diagnostic_context *context;
{
if (!problematic_instantiation_changed () || current_instantiation () == 0)
return;
record_last_problematic_instantiation ();
- print_instantiation_full_context (buffer);
+ print_instantiation_full_context (context);
}
/* Report the bare minimum context of a template instantiation. */
@@ -2566,8 +2576,8 @@ void
print_instantiation_context ()
{
print_instantiation_partial_context
- (diagnostic_buffer, current_instantiation (), input_filename, lineno);
- flush_diagnostic_buffer ();
+ (global_dc, current_instantiation (), input_filename, lineno);
+ diagnostic_flush_buffer (global_dc);
}
/* Called from output_format -- during diagnostic message processing --
@@ -2583,26 +2593,27 @@ print_instantiation_context ()
%Q assignment operator.
%T type.
%V cv-qualifier. */
-static int
-cp_printer (buffer)
+static bool
+cp_printer (buffer, text)
output_buffer *buffer;
+ text_info *text;
{
int verbose = 0;
const char *result;
-#define next_tree va_arg (output_buffer_format_args (buffer), tree)
-#define next_tcode va_arg (output_buffer_format_args (buffer), enum tree_code)
-#define next_lang va_arg (output_buffer_format_args (buffer), enum languages)
-#define next_int va_arg (output_buffer_format_args (buffer), int)
-
- if (*output_buffer_text_cursor (buffer) == '+')
- ++output_buffer_text_cursor (buffer);
- if (*output_buffer_text_cursor (buffer) == '#')
+#define next_tree va_arg (*text->args_ptr, tree)
+#define next_tcode va_arg (*text->args_ptr, enum tree_code)
+#define next_lang va_arg (*text->args_ptr, enum languages)
+#define next_int va_arg (*text->args_ptr, int)
+
+ if (*text->format_spec == '+')
+ ++text->format_spec;
+ if (*text->format_spec == '#')
{
verbose = 1;
- ++output_buffer_text_cursor (buffer);
+ ++text->format_spec;
}
- switch (*output_buffer_text_cursor (buffer))
+ switch (*text->format_spec)
{
case 'A': result = args_to_string (next_tree, verbose); break;
case 'C': result = code_to_string (next_tcode, verbose); break;
@@ -2617,11 +2628,11 @@ cp_printer (buffer)
case 'V': result = cv_to_string (next_tree, verbose); break;
default:
- return 0;
+ return false;
}
output_add_string (buffer, result);
- return 1;
+ return true;
#undef next_tree
#undef next_tcode
#undef next_lang
@@ -2715,7 +2726,7 @@ void
cp_error_at VPARAMS ((const char *msgid, ...))
{
tree here;
- diagnostic_context dc;
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
@@ -2725,10 +2736,9 @@ cp_error_at VPARAMS ((const char *msgid, ...))
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
- set_diagnostic_context (&dc, msgid, &ap,
- cp_file_of (here),
- cp_line_of (here), /* warning = */ 0);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, msgid, &ap,
+ cp_file_of (here), cp_line_of (here), DK_ERROR);
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
}
@@ -2736,7 +2746,7 @@ void
cp_warning_at VPARAMS ((const char *msgid, ...))
{
tree here;
- diagnostic_context dc;
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
@@ -2746,10 +2756,9 @@ cp_warning_at VPARAMS ((const char *msgid, ...))
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
- set_diagnostic_context (&dc, msgid, &ap,
- cp_file_of (here),
- cp_line_of (here), /* warning = */ 1);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, msgid, &ap,
+ cp_file_of (here), cp_line_of (here), DK_WARNING);
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
}
@@ -2757,7 +2766,7 @@ void
cp_pedwarn_at VPARAMS ((const char *msgid, ...))
{
tree here;
- diagnostic_context dc;
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
@@ -2767,10 +2776,9 @@ cp_pedwarn_at VPARAMS ((const char *msgid, ...))
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
- set_diagnostic_context (&dc, msgid, &ap,
- cp_file_of (here),
- cp_line_of (here),
- /* warning = */ !flag_pedantic_errors);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, msgid, &ap,
+ cp_file_of (here), cp_line_of (here),
+ pedantic_error_kind());
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
}
diff --git a/contrib/gcc/cp/except.c b/contrib/gcc/cp/except.c
index 5de9f4c..747cc1a 100644
--- a/contrib/gcc/cp/except.c
+++ b/contrib/gcc/cp/except.c
@@ -31,10 +31,10 @@ Boston, MA 02111-1307, USA. */
#include "libfuncs.h"
#include "cp-tree.h"
#include "flags.h"
-#include "obstack.h"
#include "output.h"
#include "except.h"
#include "toplev.h"
+#include "tree-inline.h"
static void push_eh_cleanup PARAMS ((tree));
static tree prepare_eh_type PARAMS ((tree));
@@ -46,15 +46,14 @@ static void push_eh_cleanup PARAMS ((tree));
static bool decl_is_java_type PARAMS ((tree decl, int err));
static void initialize_handler_parm PARAMS ((tree, tree));
static tree do_allocate_exception PARAMS ((tree));
+static tree stabilize_throw_expr PARAMS ((tree, tree *));
+static tree wrap_cleanups_r PARAMS ((tree *, int *, void *));
static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree));
static bool is_admissible_throw_operand PARAMS ((tree));
static int can_convert_eh PARAMS ((tree, tree));
static void check_handlers_1 PARAMS ((tree, tree));
static tree cp_protect_cleanup_actions PARAMS ((void));
-#include "decl.h"
-#include "obstack.h"
-
/* Sets up all the global eh stuff that needs to be initialized at the
start of compilation. */
@@ -118,7 +117,7 @@ prepare_eh_type (type)
}
/* Build the address of a typeinfo decl for use in the runtime
- matching field of the exception model. */
+ matching field of the exception model. */
static tree
build_eh_type_type (type)
@@ -175,17 +174,13 @@ static int
dtor_nothrow (type)
tree type;
{
- tree fn;
-
if (type == NULL_TREE)
return 0;
if (! TYPE_HAS_DESTRUCTOR (type))
return 1;
- fn = lookup_member (type, dtor_identifier, 0, 0);
- fn = TREE_VALUE (fn);
- return TREE_NOTHROW (fn);
+ return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
}
/* Build up a call to __cxa_end_catch, to destroy the exception object
@@ -518,7 +513,7 @@ do_allocate_exception (type)
#if 0
/* Call __cxa_free_exception from a cleanup. This is never invoked
- directly. */
+ directly, but see the comment for stabilize_throw_expr. */
static tree
do_free_exception (ptr)
@@ -540,6 +535,92 @@ do_free_exception (ptr)
}
#endif
+/* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR.
+ Called from build_throw via walk_tree_without_duplicates. */
+
+static tree
+wrap_cleanups_r (tp, walk_subtrees, data)
+ tree *tp;
+ int *walk_subtrees ATTRIBUTE_UNUSED;
+ void *data ATTRIBUTE_UNUSED;
+{
+ tree exp = *tp;
+ tree cleanup;
+
+ /* Don't walk into types. */
+ if (TYPE_P (exp))
+ {
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+ if (TREE_CODE (exp) != TARGET_EXPR)
+ return NULL_TREE;
+
+ cleanup = TARGET_EXPR_CLEANUP (exp);
+ if (cleanup)
+ {
+ cleanup = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (cleanup), cleanup);
+ TARGET_EXPR_CLEANUP (exp) = cleanup;
+ }
+
+ /* Keep iterating. */
+ return NULL_TREE;
+}
+
+/* Like stabilize_expr, but specifically for a thrown expression. When
+ throwing a temporary class object, we want to construct it directly into
+ the thrown exception, so we look past the TARGET_EXPR and stabilize the
+ arguments of the call instead.
+
+ The case where EXP is a call to a function returning a class is a bit of
+ a grey area in the standard; it's unclear whether or not it should be
+ allowed to throw. I'm going to say no, as that allows us to optimize
+ this case without worrying about deallocating the exception object if it
+ does. The alternatives would be either not optimizing this case, or
+ wrapping the initialization in a TRY_CATCH_EXPR to call do_free_exception
+ rather than in a MUST_NOT_THROW_EXPR, for this case only. */
+
+static tree
+stabilize_throw_expr (exp, initp)
+ tree exp;
+ tree *initp;
+{
+ tree init_expr;
+
+ if (TREE_CODE (exp) == TARGET_EXPR
+ && TREE_CODE (TARGET_EXPR_INITIAL (exp)) == AGGR_INIT_EXPR
+ && flag_elide_constructors)
+ {
+ tree aggr_init = AGGR_INIT_EXPR_CHECK (TARGET_EXPR_INITIAL (exp));
+ tree args = TREE_OPERAND (aggr_init, 1);
+ tree newargs = NULL_TREE;
+ tree *p = &newargs;
+
+ init_expr = void_zero_node;
+ for (; args; args = TREE_CHAIN (args))
+ {
+ tree arg = TREE_VALUE (args);
+ tree arg_init_expr;
+
+ arg = stabilize_expr (arg, &arg_init_expr);
+
+ if (TREE_SIDE_EFFECTS (arg_init_expr))
+ init_expr = build (COMPOUND_EXPR, void_type_node, init_expr,
+ arg_init_expr);
+ *p = tree_cons (NULL_TREE, arg, NULL_TREE);
+ p = &TREE_CHAIN (*p);
+ }
+ TREE_OPERAND (aggr_init, 1) = newargs;
+ }
+ else
+ {
+ exp = stabilize_expr (exp, &init_expr);
+ }
+
+ *initp = init_expr;
+ return exp;
+}
+
/* Build a throw expression. */
tree
@@ -585,10 +666,9 @@ build_throw (exp)
{
tree throw_type;
tree cleanup;
- tree stmt_expr;
- tree compound_stmt;
tree object, ptr;
tree tmp;
+ tree temp_expr, allocate_expr;
fn = get_identifier ("__cxa_throw");
if (IDENTIFIER_GLOBAL_VALUE (fn))
@@ -614,8 +694,6 @@ build_throw (exp)
fn = push_throw_library_fn (fn, tmp);
}
- begin_init_stmts (&stmt_expr, &compound_stmt);
-
/* throw expression */
/* First, decay it. */
exp = decay_conversion (exp);
@@ -633,37 +711,40 @@ build_throw (exp)
the call to __cxa_allocate_exception first (which doesn't
matter, since it can't throw). */
- my_friendly_assert (stmts_are_full_exprs_p () == 1, 19990926);
-
- /* Store the throw expression into a temp. This can be less
- efficient than storing it into the allocated space directly, but
- if we allocated the space first we would have to deal with
- cleaning it up if evaluating this expression throws. */
- if (TREE_SIDE_EFFECTS (exp))
- {
- tmp = create_temporary_var (TREE_TYPE (exp));
- DECL_INITIAL (tmp) = exp;
- cp_finish_decl (tmp, exp, NULL_TREE, LOOKUP_ONLYCONVERTING);
- exp = tmp;
- }
+ /* Pre-evaluate the thrown expression first, since if we allocated
+ the space first we would have to deal with cleaning it up if
+ evaluating this expression throws. */
+ exp = stabilize_throw_expr (exp, &temp_expr);
/* Allocate the space for the exception. */
- ptr = create_temporary_var (ptr_type_node);
- DECL_REGISTER (ptr) = 1;
- cp_finish_decl (ptr, NULL_TREE, NULL_TREE, LOOKUP_ONLYCONVERTING);
- tmp = do_allocate_exception (TREE_TYPE (exp));
- tmp = build_modify_expr (ptr, INIT_EXPR, tmp);
- finish_expr_stmt (tmp);
-
+ allocate_expr = do_allocate_exception (TREE_TYPE (exp));
+ allocate_expr = get_target_expr (allocate_expr);
+ ptr = TARGET_EXPR_SLOT (allocate_expr);
object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr);
object = build_indirect_ref (object, NULL);
- exp = build_modify_expr (object, INIT_EXPR, exp);
+ /* And initialize the exception object. */
+ exp = build_init (object, exp, LOOKUP_ONLYCONVERTING);
if (exp == error_mark_node)
- error (" in thrown expression");
+ {
+ error (" in thrown expression");
+ return error_mark_node;
+ }
exp = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (exp), exp);
- finish_expr_stmt (exp);
+ /* Prepend the allocation. */
+ exp = build (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
+ if (temp_expr != void_zero_node)
+ {
+ /* Prepend the calculation of the throw expression. Also, force
+ any cleanups from the expression to be evaluated here so that
+ we don't have to do them during unwinding. But first wrap
+ them in MUST_NOT_THROW_EXPR, since they are run after the
+ exception object is initialized. */
+ walk_tree_without_duplicates (&temp_expr, wrap_cleanups_r, 0);
+ exp = build (COMPOUND_EXPR, TREE_TYPE (exp), temp_expr, exp);
+ exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
+ }
throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
@@ -671,9 +752,9 @@ build_throw (exp)
{
cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
complete_dtor_identifier, 0);
- cleanup = TREE_VALUE (cleanup);
+ cleanup = BASELINK_FUNCTIONS (cleanup);
mark_used (cleanup);
- mark_addressable (cleanup);
+ cxx_mark_addressable (cleanup);
/* Pretend it's a normal function. */
cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
}
@@ -686,13 +767,11 @@ build_throw (exp)
tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE);
tmp = tree_cons (NULL_TREE, throw_type, tmp);
tmp = tree_cons (NULL_TREE, ptr, tmp);
- tmp = build_function_call (fn, tmp);
-
/* ??? Indicate that this function call throws throw_type. */
+ tmp = build_function_call (fn, tmp);
- finish_expr_stmt (tmp);
-
- exp = finish_init_stmts (stmt_expr, compound_stmt);
+ /* Tack on the initialization stuff. */
+ exp = build (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
}
else
{
@@ -708,6 +787,8 @@ build_throw (exp)
(fn, build_function_type (void_type_node, void_list_node));
}
+ /* ??? Indicate that this function call allows exceptions of the type
+ of the enclosing catch block (if known). */
exp = build_function_call (fn, NULL_TREE);
}
@@ -718,7 +799,7 @@ build_throw (exp)
/* Make sure TYPE is complete, pointer to complete, reference to
complete, or pointer to cv void. Issue diagnostic on failure.
- Return the zero on failure and non-zero on success. FROM can be
+ Return the zero on failure and nonzero on success. FROM can be
the expr or decl from whence TYPE came, if available. */
static int
diff --git a/contrib/gcc/cp/expr.c b/contrib/gcc/cp/expr.c
index 34f779e..cc9dae9 100644
--- a/contrib/gcc/cp/expr.c
+++ b/contrib/gcc/cp/expr.c
@@ -32,9 +32,6 @@ Boston, MA 02111-1307, USA. */
#include "except.h"
#include "tm_p.h"
-static rtx cplus_expand_expr PARAMS ((tree, rtx, enum machine_mode,
- enum expand_modifier));
-
/* Hook used by output_constant to expand language-specific
constants. */
@@ -79,12 +76,12 @@ cplus_expand_constant (cst)
/* Hook used by expand_expr to expand language-specific tree codes. */
-static rtx
-cplus_expand_expr (exp, target, tmode, modifier)
+rtx
+cxx_expand_expr (exp, target, tmode, modifier)
tree exp;
rtx target;
enum machine_mode tmode;
- enum expand_modifier modifier;
+ int modifier; /* Actually an enum expand_modifier. */
{
tree type = TREE_TYPE (exp);
register enum machine_mode mode = TYPE_MODE (type);
@@ -105,13 +102,13 @@ cplus_expand_expr (exp, target, tmode, modifier)
target, tmode, modifier);
case OFFSET_REF:
- /* Offset refs should not make it through to here. */
+ /* Offset refs should not make it through to here. */
abort ();
return const0_rtx;
case THROW_EXPR:
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
- return NULL;
+ return const0_rtx;
case MUST_NOT_THROW_EXPR:
expand_eh_region_start ();
@@ -130,17 +127,3 @@ cplus_expand_expr (exp, target, tmode, modifier)
/* NOTREACHED */
return NULL;
}
-
-void
-init_cplus_expand ()
-{
- lang_expand_expr = cplus_expand_expr;
-}
-
-int
-extract_init (decl, init)
- tree decl ATTRIBUTE_UNUSED, init ATTRIBUTE_UNUSED;
-{
- return 0;
-}
-
diff --git a/contrib/gcc/cp/friend.c b/contrib/gcc/cp/friend.c
index 441be67..9280a09 100644
--- a/contrib/gcc/cp/friend.c
+++ b/contrib/gcc/cp/friend.c
@@ -30,7 +30,7 @@ Boston, MA 02111-1307, USA. */
/* Friend data structures are described in cp-tree.h. */
-/* Returns non-zero if SUPPLICANT is a friend of TYPE. */
+/* Returns nonzero if SUPPLICANT is a friend of TYPE. */
int
is_friend (type, supplicant)
@@ -64,6 +64,10 @@ is_friend (type, supplicant)
if (supplicant == TREE_VALUE (friends))
return 1;
+ /* We haven't completed the instantiation yet. */
+ if (TREE_CODE (supplicant) == TEMPLATE_DECL)
+ return 1;
+
/* Temporarily, we are more lenient to deal with
nested friend functions, for which there can be
more than one FUNCTION_DECL, despite being the
@@ -114,7 +118,7 @@ is_friend (type, supplicant)
else
context = NULL_TREE;
- /* A namespace is not friend to anybody. */
+ /* A namespace is not friend to anybody. */
if (context && TREE_CODE (context) == NAMESPACE_DECL)
context = NULL_TREE;
@@ -159,6 +163,9 @@ add_friend (type, decl)
return;
}
}
+
+ maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
+
TREE_VALUE (list) = tree_cons (error_mark_node, decl,
TREE_VALUE (list));
return;
@@ -166,6 +173,8 @@ add_friend (type, decl)
list = TREE_CHAIN (list);
}
+ maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
+
DECL_FRIENDLIST (typedecl)
= tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
DECL_FRIENDLIST (typedecl));
@@ -198,24 +207,25 @@ make_friend_class (type, friend_type)
return;
}
- if (CLASS_TYPE_P (friend_type)
- && CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)
- && uses_template_parms (friend_type))
- {
- /* [temp.friend]
-
- Friend declarations shall not declare partial
- specializations. */
- error ("partial specialization `%T' declared `friend'",
- friend_type);
- return;
- }
-
if (processing_template_decl > template_class_depth (type))
/* If the TYPE is a template then it makes sense for it to be
friends with itself; this means that each instantiation is
friends with all other instantiations. */
- is_template_friend = 1;
+ {
+ if (CLASS_TYPE_P (friend_type)
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)
+ && uses_template_parms (friend_type))
+ {
+ /* [temp.friend]
+ Friend declarations shall not declare partial
+ specializations. */
+ error ("partial specialization `%T' declared `friend'",
+ friend_type);
+ return;
+ }
+
+ is_template_friend = 1;
+ }
else if (same_type_p (type, friend_type))
{
pedwarn ("class `%T' is implicitly friends with itself",
@@ -230,7 +240,7 @@ make_friend_class (type, friend_type)
A friend of a class or class template can be a function or
class template, a specialization of a function template or
class template, or an ordinary (nontemplate) function or
- class. */
+ class. */
if (!is_template_friend)
;/* ok */
else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
@@ -267,6 +277,8 @@ make_friend_class (type, friend_type)
TREE_VALUE (classes), type);
else
{
+ maybe_add_class_template_decl_list (type, friend_type, /*friend_p=*/1);
+
CLASSTYPE_FRIEND_CLASSES (type)
= tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
if (is_template_friend)
@@ -396,14 +408,14 @@ do_friend (ctype, declarator, decl, parmdecls, attrlist,
/* This must be a local class, so pushdecl will be ok, and
insert an unqualified friend into the local scope
(rather than the containing namespace scope, which the
- next choice will do). */
+ next choice will do). */
decl = pushdecl (decl);
else
{
/* We can't use pushdecl, as we might be in a template
class specialization, and pushdecl will insert an
unqualified friend decl into the template parameter
- scope, rather than the namespace containing it. */
+ scope, rather than the namespace containing it. */
tree ns = decl_namespace_context (decl);
push_nested_namespace (ns);
diff --git a/contrib/gcc/cp/g++spec.c b/contrib/gcc/cp/g++spec.c
index c0e5c73..af30f1c 100644
--- a/contrib/gcc/cp/g++spec.c
+++ b/contrib/gcc/cp/g++spec.c
@@ -51,10 +51,10 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
{
int i, j;
- /* If non-zero, the user gave us the `-p' or `-pg' flag. */
+ /* If nonzero, the user gave us the `-p' or `-pg' flag. */
int saw_profile_flag = 0;
- /* If non-zero, the user gave us the `-v' flag. */
+ /* If nonzero, the user gave us the `-v' flag. */
int saw_verbose_flag = 0;
/* This will be 0 if we encounter a situation where we should not
@@ -73,7 +73,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
/* The new argument list will be contained in this. */
const char **arglist;
- /* Non-zero if we saw a `-xfoo' language specification on the
+ /* Nonzero if we saw a `-xfoo' language specification on the
command line. Used to avoid adding our own -xc++ if the user
already gave a language for the file. */
int saw_speclang = 0;
@@ -178,6 +178,8 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
else if (strcmp (argv[i], "-static-libgcc") == 0
|| strcmp (argv[i], "-static") == 0)
shared_libgcc = 0;
+ else if (DEFAULT_WORD_SWITCH_TAKES_ARG (&argv[i][1]))
+ i++;
else
/* Pass other options through. */
continue;
@@ -272,6 +274,13 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
{
arglist[j++] = saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX;
added_libraries++;
+#ifdef USE_LIBUNWIND_EXCEPTIONS
+# ifndef LIBUNWIND
+# define LIBUNWIND "-lunwind"
+# endif
+ arglist[j++] = LIBUNWIND;
+ added_libraries++;
+#endif
}
if (saw_math)
arglist[j++] = saw_math;
@@ -292,11 +301,17 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
*in_added_libraries = added_libraries;
}
-/* Called before linking. Returns 0 on success and -1 on failure. */
-int lang_specific_pre_link () /* Not used for C++. */
+/* Called before linking. Returns 0 on success and -1 on failure. */
+int lang_specific_pre_link () /* Not used for C++. */
{
return 0;
}
-/* Number of extra output files that lang_specific_pre_link may generate. */
-int lang_specific_extra_outfiles = 0; /* Not used for C++. */
+/* Number of extra output files that lang_specific_pre_link may generate. */
+int lang_specific_extra_outfiles = 0; /* Not used for C++. */
+
+/* Table of language-specific spec functions. */
+const struct spec_function lang_specific_spec_functions[] =
+{
+ { 0, 0 }
+};
diff --git a/contrib/gcc/cp/init.c b/contrib/gcc/cp/init.c
index 1e08908..279e3b1 100644
--- a/contrib/gcc/cp/init.c
+++ b/contrib/gcc/cp/init.c
@@ -1,6 +1,6 @@
/* Handle initialization things in C++.
Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -34,48 +34,26 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "ggc.h"
-static void expand_aggr_vbase_init_1 PARAMS ((tree, tree, tree, tree));
-static void construct_virtual_bases PARAMS ((tree, tree, tree, tree, tree));
+static void construct_virtual_base (tree, tree);
static void expand_aggr_init_1 PARAMS ((tree, tree, tree, tree, int));
static void expand_default_init PARAMS ((tree, tree, tree, tree, int));
static tree build_vec_delete_1 PARAMS ((tree, tree, tree, special_function_kind, int));
-static void perform_member_init PARAMS ((tree, tree, int));
-static void sort_base_init PARAMS ((tree, tree, tree *, tree *));
+static void perform_member_init (tree, tree);
static tree build_builtin_delete_call PARAMS ((tree));
static int member_init_ok_or_else PARAMS ((tree, tree, tree));
static void expand_virtual_init PARAMS ((tree, tree));
-static tree sort_member_init PARAMS ((tree, tree));
+static tree sort_mem_initializers (tree, tree);
static tree initializing_context PARAMS ((tree));
static void expand_cleanup_for_base PARAMS ((tree, tree));
static tree get_temp_regvar PARAMS ((tree, tree));
static tree dfs_initialize_vtbl_ptrs PARAMS ((tree, void *));
-static tree build_default_init PARAMS ((tree));
+static tree build_default_init PARAMS ((tree, tree));
static tree build_new_1 PARAMS ((tree));
static tree get_cookie_size PARAMS ((tree));
static tree build_dtor_call PARAMS ((tree, special_function_kind, int));
static tree build_field_list PARAMS ((tree, tree, int *));
static tree build_vtbl_address PARAMS ((tree));
-/* Set up local variable for this file. MUST BE CALLED AFTER
- INIT_DECL_PROCESSING. */
-
-static tree BI_header_type;
-
-void init_init_processing ()
-{
- tree fields[1];
-
- /* Define the structure that holds header information for
- arrays allocated via operator new. */
- BI_header_type = make_aggr_type (RECORD_TYPE);
- fields[0] = build_decl (FIELD_DECL, nelts_identifier, sizetype);
-
- finish_builtin_type (BI_header_type, "__new_cookie", fields,
- 0, double_type_node);
-
- ggc_add_tree_root (&BI_header_type, 1);
-}
-
/* We are about to generate some complex initialization code.
Conceptually, it is all a single expression. However, we may want
to include conditionals, loops, and other such statement-level
@@ -167,7 +145,7 @@ initialize_vtbl_ptrs (addr)
list = build_tree_list (type, addr);
/* Walk through the hierarchy, initializing the vptr in each base
- class. We do these in pre-order because can't find the virtual
+ class. We do these in pre-order because we can't find the virtual
bases for a class until we've initialized the vtbl for that
class. */
dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs,
@@ -176,86 +154,194 @@ initialize_vtbl_ptrs (addr)
dfs_marked_real_bases_queue_p, type);
}
-/* Types containing pointers to data members cannot be
- zero-initialized with zeros, because the NULL value for such
- pointers is -1.
-
- TYPE is a type that requires such zero initialization. The
- returned value is the initializer. */
+/* Return an expression for the zero-initialization of an object with
+ type T. This expression will either be a constant (in the case
+ that T is a scalar), or a CONSTRUCTOR (in the case that T is an
+ aggregate). In either case, the value can be used as DECL_INITIAL
+ for a decl of the indicated TYPE; it is a valid static initializer.
+ If NELTS is non-NULL, and TYPE is an ARRAY_TYPE, NELTS is the
+ number of elements in the array. If STATIC_STORAGE_P is TRUE,
+ initializers are only generated for entities for which
+ zero-initialization does not simply mean filling the storage with
+ zero bytes. */
tree
-build_forced_zero_init (type)
- tree type;
+build_zero_init (tree type, tree nelts, bool static_storage_p)
{
- tree init = NULL;
+ tree init = NULL_TREE;
+
+ /* [dcl.init]
+
+ To zero-initialization storage for an object of type T means:
+
+ -- if T is a scalar type, the storage is set to the value of zero
+ converted to T.
+
+ -- if T is a non-union class type, the storage for each nonstatic
+ data member and each base-class subobject is zero-initialized.
+
+ -- if T is a union type, the storage for its first data member is
+ zero-initialized.
+
+ -- if T is an array type, the storage for each element is
+ zero-initialized.
- if (AGGREGATE_TYPE_P (type) && !TYPE_PTRMEMFUNC_P (type))
+ -- if T is a reference type, no initialization is performed. */
+
+ my_friendly_assert (nelts == NULL_TREE || TREE_CODE (nelts) == INTEGER_CST,
+ 20030618);
+
+ if (type == error_mark_node)
+ ;
+ else if (static_storage_p && zero_init_p (type))
+ /* In order to save space, we do not explicitly build initializers
+ for items that do not need them. GCC's semantics are that
+ items with static storage duration that are not otherwise
+ initialized are initialized to zero. */
+ ;
+ else if (SCALAR_TYPE_P (type))
+ init = convert (type, integer_zero_node);
+ else if (CLASS_TYPE_P (type))
+ {
+ tree field;
+ tree inits;
+
+ /* Build a constructor to contain the initializations. */
+ init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ /* Iterate over the fields, building initializations. */
+ inits = NULL_TREE;
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ /* Note that for class types there will be FIELD_DECLs
+ corresponding to base classes as well. Thus, iterating
+ over TYPE_FIELDs will result in correct initialization of
+ all of the subobjects. */
+ if (static_storage_p && !zero_init_p (TREE_TYPE (field)))
+ inits = tree_cons (field,
+ build_zero_init (TREE_TYPE (field),
+ /*nelts=*/NULL_TREE,
+ static_storage_p),
+ inits);
+
+ /* For unions, only the first field is initialized. */
+ if (TREE_CODE (type) == UNION_TYPE)
+ break;
+ }
+ CONSTRUCTOR_ELTS (init) = nreverse (inits);
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
{
- /* This is a default initialization of an aggregate, but not one of
- non-POD class type. We cleverly notice that the initialization
- rules in such a case are the same as for initialization with an
- empty brace-initialization list. */
- init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE);
+ tree index;
+ tree max_index;
+ tree inits;
+
+ /* Build a constructor to contain the initializations. */
+ init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ /* Iterate over the array elements, building initializations. */
+ inits = NULL_TREE;
+ max_index = nelts ? nelts : array_type_nelts (type);
+ my_friendly_assert (TREE_CODE (max_index) == INTEGER_CST, 20030618);
+
+ for (index = size_zero_node;
+ !tree_int_cst_lt (max_index, index);
+ index = size_binop (PLUS_EXPR, index, size_one_node))
+ inits = tree_cons (index,
+ build_zero_init (TREE_TYPE (type),
+ /*nelts=*/NULL_TREE,
+ static_storage_p),
+ inits);
+ CONSTRUCTOR_ELTS (init) = nreverse (inits);
}
else if (TREE_CODE (type) == REFERENCE_TYPE)
- /* --if T is a reference type, no initialization is performed. */
- return NULL_TREE;
+ ;
else
- {
- init = integer_zero_node;
-
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- /* We must make enumeral types the right type. */
- init = fold (build1 (NOP_EXPR, type, init));
- }
+ abort ();
- init = digest_init (type, init, 0);
+ /* In all cases, the initializer is a constant. */
+ if (init)
+ TREE_CONSTANT (init) = 1;
return init;
}
-/* [dcl.init]:
+/* Build an expression for the default-initialization of an object of
+ the indicated TYPE. If NELTS is non-NULL, and TYPE is an
+ ARRAY_TYPE, NELTS is the number of elements in the array. If
+ initialization of TYPE requires calling constructors, this function
+ returns NULL_TREE; the caller is responsible for arranging for the
+ constructors to be called. */
- To default-initialize an object of type T means:
+static tree
+build_default_init (type, nelts)
+ tree type;
+ tree nelts;
+{
+ /* [dcl.init]:
- --if T is a non-POD class type (clause _class_), the default construc-
- tor for T is called (and the initialization is ill-formed if T has
- no accessible default constructor);
+ To default-initialize an object of type T means:
- --if T is an array type, each element is default-initialized;
+ --if T is a non-POD class type (clause _class_), the default construc-
+ tor for T is called (and the initialization is ill-formed if T has
+ no accessible default constructor);
- --otherwise, the storage for the object is zero-initialized.
+ --if T is an array type, each element is default-initialized;
- A program that calls for default-initialization of an entity of refer-
- ence type is ill-formed. */
+ --otherwise, the storage for the object is zero-initialized.
-static tree
-build_default_init (type)
- tree type;
-{
- tree init = NULL_TREE;
+ A program that calls for default-initialization of an entity of refer-
+ ence type is ill-formed. */
- if (TYPE_NEEDS_CONSTRUCTING (type))
- /* Other code will handle running the default constructor. We can't do
- anything with a CONSTRUCTOR for arrays here, as that would imply
- copy-initialization. */
- return NULL_TREE;
+ /* If TYPE_NEEDS_CONSTRUCTING is true, the caller is responsible for
+ performing the initialization. This is confusing in that some
+ non-PODs do not have TYPE_NEEDS_CONSTRUCTING set. (For example,
+ a class with a pointer-to-data member as a non-static data member
+ does not have TYPE_NEEDS_CONSTRUCTING set.) Therefore, we end up
+ passing non-PODs to build_zero_init below, which is contrary to
+ the semantics quoted above from [dcl.init].
- return build_forced_zero_init (type);
+ It happens, however, that the behavior of the constructor the
+ standard says we should have generated would be precisely the
+ same as that obtained by calling build_zero_init below, so things
+ work out OK. */
+ if (TYPE_NEEDS_CONSTRUCTING (type)
+ || (nelts && TREE_CODE (nelts) != INTEGER_CST))
+ return NULL_TREE;
+
+ /* At this point, TYPE is either a POD class type, an array of POD
+ classes, or something even more inoccuous. */
+ return build_zero_init (type, nelts, /*static_storage_p=*/false);
}
-/* Subroutine of emit_base_init. */
+/* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of
+ arguments. If TREE_LIST is void_type_node, an empty initializer
+ list was given; if NULL_TREE no initializer was given. */
static void
-perform_member_init (member, init, explicit)
- tree member, init;
- int explicit;
+perform_member_init (tree member, tree init)
{
tree decl;
tree type = TREE_TYPE (member);
+ bool explicit;
+
+ explicit = (init != NULL_TREE);
- decl = build_component_ref (current_class_ref, member, NULL_TREE, explicit);
+ /* Effective C++ rule 12 requires that all data members be
+ initialized. */
+ if (warn_ecpp && !explicit && TREE_CODE (type) != ARRAY_TYPE)
+ warning ("`%D' should be initialized in the member initialization "
+ "list",
+ member);
+ if (init == void_type_node)
+ init = NULL_TREE;
+
+ /* Get an lvalue for the data member. */
+ decl = build_class_member_access_expr (current_class_ref, member,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/true);
if (decl == error_mark_node)
return;
@@ -273,11 +359,6 @@ perform_member_init (member, init, explicit)
else if (TYPE_NEEDS_CONSTRUCTING (type)
|| (init && TYPE_HAS_CONSTRUCTOR (type)))
{
- /* Since `init' is already a TREE_LIST on the 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);
-
if (explicit
&& TREE_CODE (type) == ARRAY_TYPE
&& init != NULL_TREE
@@ -285,7 +366,8 @@ perform_member_init (member, init, explicit)
&& TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE)
{
/* Initialization of one array from another. */
- finish_expr_stmt (build_vec_init (decl, TREE_VALUE (init), 1));
+ finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init),
+ /* from_array=*/1));
}
else
finish_expr_stmt (build_aggr_init (decl, init, 0));
@@ -296,7 +378,7 @@ perform_member_init (member, init, explicit)
{
if (explicit)
{
- init = build_default_init (type);
+ init = build_default_init (type, /*nelts=*/NULL_TREE);
if (TREE_CODE (type) == REFERENCE_TYPE)
warning
("default-initialization of `%#D', which has reference type",
@@ -327,13 +409,14 @@ perform_member_init (member, init, explicit)
{
tree expr;
- expr = build_component_ref (current_class_ref, member, NULL_TREE,
- explicit);
+ expr = build_class_member_access_expr (current_class_ref, member,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false);
expr = build_delete (type, expr, sfk_complete_destructor,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
if (expr != error_mark_node)
- finish_subobject (expr);
+ finish_eh_cleanup (expr);
}
}
@@ -357,7 +440,7 @@ build_field_list (t, list, uses_unions_p)
for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
{
/* Skip CONST_DECLs for enumeration constants and so forth. */
- if (TREE_CODE (fields) != FIELD_DECL)
+ if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
/* Keep track of whether or not any fields are unions. */
@@ -384,79 +467,107 @@ build_field_list (t, list, uses_unions_p)
return list;
}
-/* The MEMBER_INIT_LIST is a TREE_LIST. The TREE_PURPOSE of each list
- gives a FIELD_DECL in T that needs initialization. The TREE_VALUE
- gives the initializer, or list of initializer arguments. Sort the
- MEMBER_INIT_LIST, returning a version that contains the same
- information but in the order that the fields should actually be
- initialized. Perform error-checking in the process. */
+/* The MEM_INITS are a TREE_LIST. The TREE_PURPOSE of each list gives
+ a FIELD_DECL or BINFO in T that needs initialization. The
+ TREE_VALUE gives the initializer, or list of initializer arguments.
+
+ Return a TREE_LIST containing all of the initializations required
+ for T, in the order in which they should be performed. The output
+ list has the same format as the input. */
static tree
-sort_member_init (t, member_init_list)
- tree t;
- tree member_init_list;
+sort_mem_initializers (tree t, tree mem_inits)
{
- tree init_list;
- tree last_field;
tree init;
+ tree base;
+ tree sorted_inits;
+ tree next_subobject;
+ int i;
int uses_unions_p;
- /* Build up a list of the various fields, in sorted order. */
- init_list = nreverse (build_field_list (t, NULL_TREE, &uses_unions_p));
-
- /* Go through the explicit initializers, adding them to the
- INIT_LIST. */
- last_field = init_list;
- for (init = member_init_list; init; init = TREE_CHAIN (init))
- {
- tree f;
- tree initialized_field;
-
- initialized_field = TREE_PURPOSE (init);
- my_friendly_assert (TREE_CODE (initialized_field) == FIELD_DECL,
- 20000516);
-
- /* If the explicit initializers are in sorted order, then the
- INITIALIZED_FIELD will be for a field following the
- LAST_FIELD. */
- for (f = last_field; f; f = TREE_CHAIN (f))
- if (TREE_PURPOSE (f) == initialized_field)
+ /* Build up a list of initializations. The TREE_PURPOSE of entry
+ will be the subobject (a FIELD_DECL or BINFO) to initialize. The
+ TREE_VALUE will be the constructor arguments, or NULL if no
+ explicit initialization was provided. */
+ sorted_inits = NULL_TREE;
+ /* Process the virtual bases. */
+ for (base = CLASSTYPE_VBASECLASSES (t); base; base = TREE_CHAIN (base))
+ sorted_inits = tree_cons (TREE_VALUE (base), NULL_TREE, sorted_inits);
+ /* Process the direct bases. */
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
+ {
+ base = BINFO_BASETYPE (TYPE_BINFO (t), i);
+ if (!TREE_VIA_VIRTUAL (base))
+ sorted_inits = tree_cons (base, NULL_TREE, sorted_inits);
+ }
+ /* Process the non-static data members. */
+ sorted_inits = build_field_list (t, sorted_inits, &uses_unions_p);
+ /* Reverse the entire list of initializations, so that they are in
+ the order that they will actually be performed. */
+ sorted_inits = nreverse (sorted_inits);
+
+ /* If the user presented the initializers in an order different from
+ that in which they will actually occur, we issue a warning. Keep
+ track of the next subobject which can be explicitly initialized
+ without issuing a warning. */
+ next_subobject = sorted_inits;
+
+ /* Go through the explicit initializers, filling in TREE_PURPOSE in
+ the SORTED_INITS. */
+ for (init = mem_inits; init; init = TREE_CHAIN (init))
+ {
+ tree subobject;
+ tree subobject_init;
+
+ subobject = TREE_PURPOSE (init);
+
+ /* If the explicit initializers are in sorted order, then
+ SUBOBJECT will be NEXT_SUBOBJECT, or something following
+ it. */
+ for (subobject_init = next_subobject;
+ subobject_init;
+ subobject_init = TREE_CHAIN (subobject_init))
+ if (TREE_PURPOSE (subobject_init) == subobject)
break;
- /* Give a warning, if appropriate. */
- if (warn_reorder && !f)
+ /* Issue a warning if the explicit initializer order does not
+ match that which will actually occur. */
+ if (warn_reorder && !subobject_init)
{
- cp_warning_at ("member initializers for `%#D'",
- TREE_PURPOSE (last_field));
- cp_warning_at (" and `%#D'", initialized_field);
- warning (" will be re-ordered to match declaration order");
+ if (TREE_CODE (TREE_PURPOSE (next_subobject)) == FIELD_DECL)
+ cp_warning_at ("`%D' will be initialized after",
+ TREE_PURPOSE (next_subobject));
+ else
+ warning ("base `%T' will be initialized after",
+ TREE_PURPOSE (next_subobject));
+ if (TREE_CODE (subobject) == FIELD_DECL)
+ cp_warning_at (" `%#D'", subobject);
+ else
+ warning (" base `%T'", subobject);
}
- /* Look again, from the beginning of the list. We must find the
- field on this loop. */
- if (!f)
+ /* Look again, from the beginning of the list. */
+ if (!subobject_init)
{
- f = init_list;
- while (TREE_PURPOSE (f) != initialized_field)
- f = TREE_CHAIN (f);
+ subobject_init = sorted_inits;
+ while (TREE_PURPOSE (subobject_init) != subobject)
+ subobject_init = TREE_CHAIN (subobject_init);
}
-
- /* If there was already an explicit initializer for this field,
- issue an error. */
- if (TREE_TYPE (f))
- error ("multiple initializations given for member `%D'",
- initialized_field);
- else
+
+ /* It is invalid to initialize the same subobject more than
+ once. */
+ if (TREE_VALUE (subobject_init))
{
- /* Mark the field as explicitly initialized. */
- TREE_TYPE (f) = error_mark_node;
- /* And insert the initializer. */
- TREE_VALUE (f) = TREE_VALUE (init);
+ if (TREE_CODE (subobject) == FIELD_DECL)
+ error ("multiple initializations given for `%D'", subobject);
+ else
+ error ("multiple initializations given for base `%T'",
+ subobject);
}
- /* Remember the location of the last explicitly initialized
- field. */
- last_field = f;
+ /* Record the initialization. */
+ TREE_VALUE (subobject_init) = TREE_VALUE (init);
+ next_subobject = subobject_init;
}
/* [class.base.init]
@@ -466,15 +577,16 @@ sort_member_init (t, member_init_list)
anonymous unions), the ctor-initializer is ill-formed. */
if (uses_unions_p)
{
- last_field = NULL_TREE;
- for (init = init_list; init; init = TREE_CHAIN (init))
+ tree last_field = NULL_TREE;
+ for (init = sorted_inits; init; init = TREE_CHAIN (init))
{
tree field;
tree field_type;
int done;
- /* Skip uninitialized members. */
- if (!TREE_TYPE (init))
+ /* Skip uninitialized members and base classes. */
+ if (!TREE_VALUE (init)
+ || TREE_CODE (TREE_PURPOSE (init)) != FIELD_DECL)
continue;
/* See if this field is a member of a union, or a member of a
structure contained in a union, etc. */
@@ -541,231 +653,76 @@ sort_member_init (t, member_init_list)
}
}
- return init_list;
+ return sorted_inits;
}
-/* Like sort_member_init, but used for initializers of base classes.
- *RBASE_PTR is filled in with the initializers for non-virtual bases;
- vbase_ptr gets the virtual bases. */
-
-static void
-sort_base_init (t, base_init_list, rbase_ptr, vbase_ptr)
- tree t;
- tree base_init_list;
- tree *rbase_ptr, *vbase_ptr;
-{
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
- int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- int i;
- tree x;
- tree last;
-
- /* For warn_reorder. */
- int last_pos = 0;
- tree last_base = NULL_TREE;
-
- tree rbases = NULL_TREE;
- tree vbases = NULL_TREE;
-
- /* First walk through and splice out vbase and invalid initializers.
- Also replace types with binfos. */
-
- last = tree_cons (NULL_TREE, NULL_TREE, base_init_list);
- for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x))
- {
- tree basetype = TREE_PURPOSE (x);
- tree binfo = (TREE_CODE (basetype) == TREE_VEC
- ? basetype : binfo_or_else (basetype, t));
-
- if (binfo == NULL_TREE)
- /* BASETYPE might be an inaccessible direct base (because it
- is also an indirect base). */
- continue;
-
- if (TREE_VIA_VIRTUAL (binfo))
- {
- /* Virtual base classes are special cases. Their
- initializers are recorded with this constructor, and they
- are used when this constructor is the top-level
- constructor called. */
- tree v = binfo_for_vbase (BINFO_TYPE (binfo), t);
- vbases = tree_cons (v, TREE_VALUE (x), vbases);
- }
- else
- {
- /* Otherwise, it must be an immediate base class. */
- my_friendly_assert
- (same_type_p (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
- t), 20011113);
-
- TREE_PURPOSE (x) = binfo;
- TREE_CHAIN (last) = x;
- last = x;
- }
- }
- TREE_CHAIN (last) = NULL_TREE;
-
- /* Now walk through our regular bases and make sure they're initialized. */
-
- for (i = 0; i < n_baseclasses; ++i)
- {
- /* The base for which we're currently initializing. */
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- /* The initializer for BASE_BINFO. */
- tree init;
- int pos;
-
- if (TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- /* We haven't found the BASE_BINFO yet. */
- init = NULL_TREE;
- /* Loop through all the explicitly initialized bases, looking
- for an appropriate initializer. */
- for (x = base_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos)
- {
- tree binfo = TREE_PURPOSE (x);
-
- if (binfo == base_binfo && !init)
- {
- if (warn_reorder)
- {
- if (pos < last_pos)
- {
- cp_warning_at ("base initializers for `%#T'", last_base);
- cp_warning_at (" and `%#T'", BINFO_TYPE (binfo));
- warning (" will be re-ordered to match inheritance order");
- }
- last_pos = pos;
- last_base = BINFO_TYPE (binfo);
- }
-
- /* Make sure we won't try to work on this init again. */
- TREE_PURPOSE (x) = NULL_TREE;
- init = build_tree_list (binfo, TREE_VALUE (x));
- }
- else if (binfo == base_binfo)
- {
- error ("base class `%T' already initialized",
- BINFO_TYPE (binfo));
- break;
- }
- }
-
- /* If we didn't find BASE_BINFO in the list, create a dummy entry
- so the two lists (RBASES and the list of bases) will be
- symmetrical. */
- if (!init)
- init = build_tree_list (NULL_TREE, NULL_TREE);
- rbases = chainon (rbases, init);
- }
-
- *rbase_ptr = rbases;
- *vbase_ptr = vbases;
-}
-
-/* Perform whatever initializations have yet to be done on the base
- class, and non-static data members, of the CURRENT_CLASS_TYPE.
- These actions are given by the BASE_INIT_LIST and MEM_INIT_LIST,
- respectively.
-
- If there is a need for a call to a constructor, we must surround
- that call with a pushlevel/poplevel pair, since we are technically
- at the PARM level of scope. */
+/* Initialize all bases and members of CURRENT_CLASS_TYPE. MEM_INITS
+ is a TREE_LIST giving the explicit mem-initializer-list for the
+ constructor. The TREE_PURPOSE of each entry is a subobject (a
+ FIELD_DECL or a BINFO) of the CURRENT_CLASS_TYPE. The TREE_VALUE
+ is a TREE_LIST giving the arguments to the constructor or
+ void_type_node for an empty list of arguments. */
void
-emit_base_init (mem_init_list, base_init_list)
- tree mem_init_list;
- tree base_init_list;
+emit_mem_initializers (tree mem_inits)
{
- tree member;
- tree rbase_init_list, vbase_init_list;
- tree t = current_class_type;
- tree t_binfo = TYPE_BINFO (t);
- tree binfos = BINFO_BASETYPES (t_binfo);
- int i;
- int n_baseclasses = BINFO_N_BASETYPES (t_binfo);
-
- mem_init_list = sort_member_init (t, mem_init_list);
- sort_base_init (t, base_init_list, &rbase_init_list, &vbase_init_list);
-
- /* First, initialize the virtual base classes, if we are
- constructing the most-derived object. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (t))
- {
- tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
- construct_virtual_bases (t, current_class_ref, current_class_ptr,
- vbase_init_list, first_arg);
- }
-
- /* Now, perform initialization of non-virtual base classes. */
- for (i = 0; i < n_baseclasses; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree init = void_list_node;
+ /* Sort the mem-initializers into the order in which the
+ initializations should be performed. */
+ mem_inits = sort_mem_initializers (current_class_type, mem_inits);
- if (TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo,
- 999);
-
- if (TREE_PURPOSE (rbase_init_list))
- init = TREE_VALUE (rbase_init_list);
- else if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo)))
- {
- init = NULL_TREE;
- if (extra_warnings
- && DECL_COPY_CONSTRUCTOR_P (current_function_decl))
- warning ("base class `%#T' should be explicitly initialized in the copy constructor",
- BINFO_TYPE (base_binfo));
- }
-
- if (init != void_list_node)
+ in_base_initializer = 1;
+
+ /* Initialize base classes. */
+ while (mem_inits
+ && TREE_CODE (TREE_PURPOSE (mem_inits)) != FIELD_DECL)
+ {
+ tree subobject = TREE_PURPOSE (mem_inits);
+ tree arguments = TREE_VALUE (mem_inits);
+
+ /* If these initializations are taking place in a copy
+ constructor, the base class should probably be explicitly
+ initialized. */
+ if (extra_warnings && !arguments
+ && DECL_COPY_CONSTRUCTOR_P (current_function_decl)
+ && TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (subobject)))
+ warning ("base class `%#T' should be explicitly initialized in the "
+ "copy constructor",
+ BINFO_TYPE (subobject));
+
+ /* If an explicit -- but empty -- initializer list was present,
+ treat it just like default initialization at this point. */
+ if (arguments == void_type_node)
+ arguments = NULL_TREE;
+
+ /* Initialize the base. */
+ if (TREE_VIA_VIRTUAL (subobject))
+ construct_virtual_base (subobject, arguments);
+ else
{
- member = build_base_path (PLUS_EXPR, current_class_ptr,
- base_binfo, 1);
- expand_aggr_init_1 (base_binfo, NULL_TREE,
- build_indirect_ref (member, NULL), init,
+ tree base_addr;
+
+ base_addr = build_base_path (PLUS_EXPR, current_class_ptr,
+ subobject, 1);
+ expand_aggr_init_1 (subobject, NULL_TREE,
+ build_indirect_ref (base_addr, NULL),
+ arguments,
LOOKUP_NORMAL);
+ expand_cleanup_for_base (subobject, NULL_TREE);
}
- expand_cleanup_for_base (base_binfo, NULL_TREE);
- rbase_init_list = TREE_CHAIN (rbase_init_list);
+ mem_inits = TREE_CHAIN (mem_inits);
}
+ in_base_initializer = 0;
- /* Initialize the vtable pointers for the class. */
+ /* Initialize the vptrs. */
initialize_vtbl_ptrs (current_class_ptr);
-
- while (mem_init_list)
+
+ /* Initialize the data members. */
+ while (mem_inits)
{
- tree init;
- tree member;
- int from_init_list;
-
- member = TREE_PURPOSE (mem_init_list);
-
- /* See if we had a user-specified member initialization. */
- if (TREE_TYPE (mem_init_list))
- {
- init = TREE_VALUE (mem_init_list);
- from_init_list = 1;
- }
- else
- {
- 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)
- warning ("`%D' should be initialized in the member initialization list", member);
- }
-
- perform_member_init (member, init, from_init_list);
- mem_init_list = TREE_CHAIN (mem_init_list);
+ perform_member_init (TREE_PURPOSE (mem_inits),
+ TREE_VALUE (mem_inits));
+ mem_inits = TREE_CHAIN (mem_inits);
}
}
@@ -862,7 +819,7 @@ expand_virtual_init (binfo, decl)
/* If an exception is thrown in a constructor, those base classes already
constructed must be destroyed. This function creates the cleanup
for BINFO, which has just been constructed. If FLAG is non-NULL,
- it is a DECL which is non-zero when this base needs to be
+ it is a DECL which is nonzero when this base needs to be
destroyed. */
static void
@@ -876,99 +833,70 @@ expand_cleanup_for_base (binfo, flag)
return;
/* Call the destructor. */
- expr = (build_scoped_method_call
- (current_class_ref, binfo, base_dtor_identifier, NULL_TREE));
+ expr = build_special_member_call (current_class_ref,
+ base_dtor_identifier,
+ NULL_TREE,
+ binfo,
+ LOOKUP_NORMAL | LOOKUP_NONVIRTUAL);
if (flag)
expr = fold (build (COND_EXPR, void_type_node,
- truthvalue_conversion (flag),
+ c_common_truthvalue_conversion (flag),
expr, integer_zero_node));
- finish_subobject (expr);
+ finish_eh_cleanup (expr);
}
-/* Subroutine of `expand_aggr_vbase_init'.
- BINFO is the binfo of the type that is being initialized.
- INIT_LIST is the list of initializers for the virtual baseclass. */
+/* Construct the virtual base-class VBASE passing the ARGUMENTS to its
+ constructor. */
static void
-expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
- tree binfo, exp, addr, init_list;
+construct_virtual_base (tree vbase, tree arguments)
{
- tree init = purpose_member (binfo, init_list);
- tree ref = build_indirect_ref (addr, NULL);
-
- if (init)
- init = TREE_VALUE (init);
- /* Call constructors, but don't set up vtables. */
- expand_aggr_init_1 (binfo, exp, ref, init, LOOKUP_COMPLAIN);
-}
-
-/* Construct the virtual base-classes of THIS_REF (whose address is
- THIS_PTR). The object has the indicated TYPE. The construction
- actually takes place only if FLAG is non-zero. INIT_LIST is list
- of initializations for constructors to perform. */
-
-static void
-construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
- tree type;
- tree this_ref;
- tree this_ptr;
- tree init_list;
- tree flag;
-{
- tree vbases;
-
- /* If there are no virtual baseclasses, we shouldn't even be here. */
- my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621);
-
- /* Now, run through the baseclasses, initializing each. */
- for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
- vbases = TREE_CHAIN (vbases))
- {
- tree inner_if_stmt;
- tree compound_stmt;
- tree exp;
- tree vbase;
-
- /* If there are virtual base classes with destructors, we need to
- emit cleanups to destroy them if an exception is thrown during
- the construction process. These exception regions (i.e., the
- period during which the cleanups must occur) begin from the time
- the construction is complete to the end of the function. If we
- create a conditional block in which to initialize the
- base-classes, then the cleanup region for the virtual base begins
- inside a block, and ends outside of that block. This situation
- confuses the sjlj exception-handling code. Therefore, we do not
- create a single conditional block, but one for each
- initialization. (That way the cleanup regions always begin
- in the outer block.) We trust the back-end to figure out
- that the FLAG will not change across initializations, and
- avoid doing multiple tests. */
- inner_if_stmt = begin_if_stmt ();
- finish_if_stmt_cond (flag, inner_if_stmt);
- compound_stmt = begin_compound_stmt (/*has_no_scope=*/1);
-
- /* Compute the location of the virtual base. If we're
- constructing virtual bases, then we must be the most derived
- class. Therefore, we don't have to look up the virtual base;
- we already know where it is. */
- vbase = TREE_VALUE (vbases);
- exp = build (PLUS_EXPR,
- TREE_TYPE (this_ptr),
- this_ptr,
- fold (build1 (NOP_EXPR, TREE_TYPE (this_ptr),
- BINFO_OFFSET (vbase))));
- exp = build1 (NOP_EXPR,
- build_pointer_type (BINFO_TYPE (vbase)),
- exp);
-
- expand_aggr_vbase_init_1 (vbase, this_ref, exp, init_list);
- finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
- finish_then_clause (inner_if_stmt);
- finish_if_stmt ();
-
- expand_cleanup_for_base (vbase, flag);
- }
+ tree inner_if_stmt;
+ tree compound_stmt;
+ tree exp;
+ tree flag;
+
+ /* If there are virtual base classes with destructors, we need to
+ emit cleanups to destroy them if an exception is thrown during
+ the construction process. These exception regions (i.e., the
+ period during which the cleanups must occur) begin from the time
+ the construction is complete to the end of the function. If we
+ create a conditional block in which to initialize the
+ base-classes, then the cleanup region for the virtual base begins
+ inside a block, and ends outside of that block. This situation
+ confuses the sjlj exception-handling code. Therefore, we do not
+ create a single conditional block, but one for each
+ initialization. (That way the cleanup regions always begin
+ in the outer block.) We trust the back-end to figure out
+ that the FLAG will not change across initializations, and
+ avoid doing multiple tests. */
+ flag = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
+ inner_if_stmt = begin_if_stmt ();
+ finish_if_stmt_cond (flag, inner_if_stmt);
+ compound_stmt = begin_compound_stmt (/*has_no_scope=*/1);
+
+ /* Compute the location of the virtual base. If we're
+ constructing virtual bases, then we must be the most derived
+ class. Therefore, we don't have to look up the virtual base;
+ we already know where it is. */
+ exp = build (PLUS_EXPR,
+ TREE_TYPE (current_class_ptr),
+ current_class_ptr,
+ fold (build1 (NOP_EXPR, TREE_TYPE (current_class_ptr),
+ BINFO_OFFSET (vbase))));
+ exp = build1 (NOP_EXPR,
+ build_pointer_type (BINFO_TYPE (vbase)),
+ exp);
+ exp = build1 (INDIRECT_REF, BINFO_TYPE (vbase), exp);
+
+ expand_aggr_init_1 (vbase, current_class_ref, exp,
+ arguments, LOOKUP_COMPLAIN);
+ finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
+ finish_then_clause (inner_if_stmt);
+ finish_if_stmt ();
+
+ expand_cleanup_for_base (vbase, flag);
}
/* Find the context in which this FIELD can be initialized. */
@@ -1017,46 +945,40 @@ member_init_ok_or_else (field, type, member_name)
return 1;
}
-/* EXP is an expression of aggregate type. NAME is an IDENTIFIER_NODE
- which names a field, or it is a _TYPE node or TYPE_DECL which names
- a base for that type. INIT is a parameter list for that field's or
- base's constructor. Check the validity of NAME, and return a
- TREE_LIST of the base _TYPE or FIELD_DECL and the INIT. EXP is used
- only to get its type. If NAME is invalid, return NULL_TREE and
- issue a diagnostic.
+/* NAME is a FIELD_DECL, an IDENTIFIER_NODE which names a field, or it
+ is a _TYPE node or TYPE_DECL which names a base for that type.
+ Check the validity of NAME, and return either the base _TYPE, base
+ binfo, or the FIELD_DECL of the member. If NAME is invalid, return
+ NULL_TREE and issue a diagnostic.
An old style unnamed direct single base construction is permitted,
where NAME is NULL. */
tree
-expand_member_init (exp, name, init)
- tree exp, name, init;
+expand_member_init (tree name)
{
- tree basetype = NULL_TREE, field;
- tree type;
+ tree basetype;
+ tree field;
- if (exp == NULL_TREE)
+ if (!current_class_ref)
return NULL_TREE;
- type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
- my_friendly_assert (IS_AGGR_TYPE (type), 20011113);
-
if (!name)
{
/* This is an obsolete unnamed base class initializer. The
parser will already have warned about its use. */
- switch (CLASSTYPE_N_BASECLASSES (type))
+ switch (CLASSTYPE_N_BASECLASSES (current_class_type))
{
case 0:
error ("unnamed initializer for `%T', which has no base classes",
- type);
+ current_class_type);
return NULL_TREE;
case 1:
- basetype = TYPE_BINFO_BASETYPE (type, 0);
+ basetype = TYPE_BINFO_BASETYPE (current_class_type, 0);
break;
default:
error ("unnamed initializer for `%T', which uses multiple inheritance",
- type);
+ current_class_type);
return NULL_TREE;
}
}
@@ -1067,47 +989,52 @@ expand_member_init (exp, name, init)
}
else if (TREE_CODE (name) == TYPE_DECL)
basetype = TYPE_MAIN_VARIANT (TREE_TYPE (name));
-
- my_friendly_assert (init != NULL_TREE, 0);
-
- if (init == void_type_node)
- init = NULL_TREE;
+ else
+ basetype = NULL_TREE;
if (basetype)
{
+ tree binfo;
+
if (current_template_parms)
- ;
- else if (vec_binfo_member (basetype, TYPE_BINFO_BASETYPES (type)))
- /* A direct base. */;
- else if (binfo_for_vbase (basetype, type))
- /* A virtual base. */;
- else
+ return basetype;
+
+ binfo = lookup_base (current_class_type, basetype,
+ ba_ignore, NULL);
+ if (binfo)
{
- if (TYPE_USES_VIRTUAL_BASECLASSES (type))
+ if (TREE_VIA_VIRTUAL (binfo))
+ binfo = binfo_for_vbase (basetype, current_class_type);
+ else if (BINFO_INHERITANCE_CHAIN (binfo)
+ != TYPE_BINFO (current_class_type))
+ binfo = NULL_TREE;
+ }
+ if (!binfo)
+ {
+ if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
error ("type `%D' is not a direct or virtual base of `%T'",
- name, type);
+ name, current_class_type);
else
error ("type `%D' is not a direct base of `%T'",
- name, type);
+ name, current_class_type);
return NULL_TREE;
}
- init = build_tree_list (basetype, init);
+ if (binfo)
+ return binfo;
}
else
{
if (TREE_CODE (name) == IDENTIFIER_NODE)
- field = lookup_field (type, name, 1, 0);
+ field = lookup_field (current_class_type, name, 1, 0);
else
field = name;
- if (! member_init_ok_or_else (field, type, name))
- return NULL_TREE;
-
- init = build_tree_list (field, init);
+ if (member_init_ok_or_else (field, current_class_type, name))
+ return field;
}
- return init;
+ return NULL_TREE;
}
/* This is like `expand_member_init', only it stores one aggregate
@@ -1131,8 +1058,6 @@ expand_member_init (exp, name, init)
The virtual function table pointer cannot be set up here, because
we do not really know its type.
- Virtual baseclass pointers are also set up here.
-
This never calls operator=().
When initializing, nothing is CONST.
@@ -1191,7 +1116,7 @@ build_aggr_init (exp, init, flags)
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
- stmt_expr = build_vec_init (exp, init,
+ stmt_expr = build_vec_init (exp, NULL_TREE, init,
init && same_type_p (TREE_TYPE (init),
TREE_TYPE (exp)));
TREE_READONLY (exp) = was_const;
@@ -1221,6 +1146,24 @@ build_aggr_init (exp, init, flags)
return stmt_expr;
}
+/* Like build_aggr_init, but not just for aggregates. */
+
+tree
+build_init (decl, init, flags)
+ tree decl, init;
+ int flags;
+{
+ tree expr;
+
+ if (IS_AGGR_TYPE (TREE_TYPE (decl))
+ || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+ expr = build_aggr_init (decl, init, flags);
+ else
+ expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
+
+ return expr;
+}
+
static void
expand_default_init (binfo, true_exp, exp, init, flags)
tree binfo;
@@ -1253,10 +1196,13 @@ expand_default_init (binfo, true_exp, exp, init, flags)
to run a new constructor; and catching an exception, where we
have already built up the constructor call so we could wrap it
in an exception region. */;
- else if (TREE_CODE (init) == CONSTRUCTOR)
- /* A brace-enclosed initializer has whatever type is
- required. There's no need to convert it. */
- ;
+ else if (TREE_CODE (init) == CONSTRUCTOR
+ && TREE_HAS_CONSTRUCTOR (init))
+ {
+ /* A brace-enclosed initializer for an aggregate. */
+ my_friendly_assert (CP_AGGREGATE_TYPE_P (type), 20021016);
+ init = digest_init (type, init, (tree *)NULL);
+ }
else
init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
@@ -1289,7 +1235,7 @@ expand_default_init (binfo, true_exp, exp, init, flags)
else
ctor_name = base_ctor_identifier;
- rval = build_method_call (exp, ctor_name, parms, binfo, flags);
+ rval = build_special_member_call (exp, ctor_name, parms, binfo, flags);
if (TREE_SIDE_EFFECTS (rval))
{
if (building_stmt_tree ())
@@ -1329,6 +1275,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, flags)
tree type = TREE_TYPE (exp);
my_friendly_assert (init != error_mark_node && type != error_mark_node, 211);
+ my_friendly_assert (building_stmt_tree (), 20021010);
/* Use a function returning the desired type to initialize EXP for us.
If the function is a constructor, and its first argument is
@@ -1343,12 +1290,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, flags)
/* If store_init_value returns NULL_TREE, the INIT has been
record in the DECL_INITIAL for EXP. That means there's
nothing more we have to do. */
- if (!store_init_value (exp, init))
- {
- if (!building_stmt_tree ())
- expand_decl_init (exp);
- }
- else
+ if (store_init_value (exp, init))
finish_expr_stmt (build (INIT_EXPR, type, exp, init));
return;
}
@@ -1438,6 +1380,7 @@ build_member_call (type, name, parmlist)
{
tree t;
tree method_name;
+ tree fns;
int dtor = 0;
tree basetype_path, decl;
@@ -1458,15 +1401,16 @@ build_member_call (type, name, parmlist)
TREE_OPERAND (name, 0) = method_name;
}
my_friendly_assert (is_overloaded_fn (method_name), 980519);
- return build_x_function_call (name, parmlist, current_class_ref);
+ return finish_call_expr (name, parmlist, /*disallow_virtual=*/true);
}
if (DECL_P (name))
name = DECL_NAME (name);
if (TREE_CODE (type) == NAMESPACE_DECL)
- return build_x_function_call (lookup_namespace_name (type, name),
- parmlist, current_class_ref);
+ return finish_call_expr (lookup_namespace_name (type, name),
+ parmlist,
+ /*disallow_virtual=*/true);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
@@ -1493,10 +1437,9 @@ build_member_call (type, name, parmlist)
{
tree ns = lookup_name (type, 0);
if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
- {
- return build_x_function_call (build_offset_ref (type, name),
- parmlist, current_class_ref);
- }
+ return finish_call_expr (lookup_namespace_name (ns, name),
+ parmlist,
+ /*disallow_virtual=*/true);
}
if (type == NULL_TREE || ! is_aggr_type (type, 1))
@@ -1515,30 +1458,34 @@ build_member_call (type, name, parmlist)
decl = maybe_dummy_object (type, &basetype_path);
+ fns = lookup_fnfields (basetype_path, method_name, 0);
+ if (fns)
+ {
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ BASELINK_FUNCTIONS (fns) = build_nt (TEMPLATE_ID_EXPR,
+ BASELINK_FUNCTIONS (fns),
+ TREE_OPERAND (name, 1));
+ return build_new_method_call (decl, fns, parmlist,
+ /*conversion_path=*/NULL_TREE,
+ LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
+ }
+
/* Convert 'this' to the specified type to disambiguate conversion
to the function's context. */
if (decl == current_class_ref
+ /* ??? this is wrong, but if this conversion is invalid we need to
+ defer it until we know whether we are calling a static or
+ non-static member function. Be conservative for now. */
&& ACCESSIBLY_UNIQUELY_DERIVED_P (type, current_class_type))
{
- tree olddecl = current_class_ptr;
- tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));
- if (oldtype != type)
- {
- tree newtype = build_qualified_type (type, TYPE_QUALS (oldtype));
- decl = convert_force (build_pointer_type (newtype), olddecl, 0);
- decl = build_indirect_ref (decl, NULL);
- }
+ basetype_path = NULL_TREE;
+ decl = build_scoped_ref (decl, type, &basetype_path);
+ if (decl == error_mark_node)
+ return error_mark_node;
}
- if (method_name == constructor_name (type)
- || method_name == constructor_name_full (type))
+ if (constructor_name_p (method_name, type))
return build_functional_cast (type, parmlist);
- if (lookup_fnfields (basetype_path, method_name, 0))
- return build_method_call (decl,
- TREE_CODE (name) == TEMPLATE_ID_EXPR
- ? name : method_name,
- parmlist, basetype_path,
- LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
if (TREE_CODE (name) == IDENTIFIER_NODE
&& ((t = lookup_field (TYPE_BINFO (type), name, 1, 0))))
{
@@ -1667,17 +1614,22 @@ build_offset_ref (type, name)
decl = maybe_dummy_object (type, &basebinfo);
- member = lookup_member (basebinfo, name, 1, 0);
-
- if (member == error_mark_node)
- return error_mark_node;
+ if (BASELINK_P (name) || DECL_P (name))
+ member = name;
+ else
+ {
+ member = lookup_member (basebinfo, name, 1, 0);
+
+ if (member == error_mark_node)
+ return error_mark_node;
+ }
/* A lot of this logic is now handled in lookup_member. */
if (member && BASELINK_P (member))
{
/* Go from the TREE_BASELINK to the member function info. */
tree fnfields = member;
- t = TREE_VALUE (fnfields);
+ t = BASELINK_FUNCTIONS (fnfields);
if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
{
@@ -1702,7 +1654,7 @@ build_offset_ref (type, name)
return t;
}
- if (!really_overloaded_fn (t))
+ if (TREE_CODE (t) != TEMPLATE_ID_EXPR && !really_overloaded_fn (t))
{
/* Get rid of a potential OVERLOAD around it */
t = OVL_CURRENT (t);
@@ -1748,7 +1700,7 @@ build_offset_ref (type, name)
if (TREE_CODE (t) == FIELD_DECL && DECL_C_BIT_FIELD (t))
{
- error ("illegal pointer to bit-field `%D'", t);
+ error ("invalid pointer to bit-field `%D'", t);
return error_mark_node;
}
@@ -1814,7 +1766,7 @@ resolve_offset_ref (exp)
|| TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE)
{
/* These were static members. */
- if (mark_addressable (member) == 0)
+ if (!cxx_mark_addressable (member))
return error_mark_node;
return member;
}
@@ -1837,7 +1789,7 @@ resolve_offset_ref (exp)
if (TREE_CODE (member) == FIELD_DECL
&& (base == current_class_ref || is_dummy_object (base)))
{
- tree binfo = TYPE_BINFO (current_class_type);
+ tree binfo = NULL_TREE;
/* Try to get to basetype from 'this'; if that doesn't work,
nothing will. */
@@ -1845,15 +1797,11 @@ resolve_offset_ref (exp)
/* First convert to the intermediate base specified, if appropriate. */
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
- {
- binfo = binfo_or_else (TYPE_OFFSET_BASETYPE (type),
- current_class_type);
- if (!binfo)
- return error_mark_node;
- base = build_base_path (PLUS_EXPR, base, binfo, 1);
- }
+ base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type), &binfo);
- return build_component_ref (base, member, binfo, 1);
+ return build_class_member_access_expr (base, member,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false);
}
/* Ensure that we have an object. */
@@ -2122,7 +2070,7 @@ build_new (placement, decl, init, use_global_new)
return rval;
}
-/* Given a Java class, return a decl for the corresponding java.lang.Class. */
+/* Given a Java class, return a decl for the corresponding java.lang.Class. */
tree
build_java_class_ref (type)
@@ -2205,6 +2153,7 @@ build_new_1 (exp)
tree placement, init;
tree type, true_type, size, rval, t;
tree full_type;
+ tree outer_nelts = NULL_TREE;
tree nelts = NULL_TREE;
tree alloc_call, alloc_expr, alloc_node;
tree alloc_fn;
@@ -2234,12 +2183,11 @@ build_new_1 (exp)
if (TREE_CODE (type) == ARRAY_REF)
{
has_array = 1;
- nelts = TREE_OPERAND (type, 1);
+ nelts = outer_nelts = TREE_OPERAND (type, 1);
type = TREE_OPERAND (type, 0);
- full_type = cp_build_binary_op (MINUS_EXPR, nelts, integer_one_node);
- full_type = build_index_type (full_type);
- full_type = build_cplus_array_type (type, full_type);
+ /* Use an incomplete array type to avoid VLA headaches. */
+ full_type = build_cplus_array_type (type, NULL_TREE);
}
else
full_type = type;
@@ -2341,7 +2289,8 @@ build_new_1 (exp)
args));
else
alloc_call = build_method_call (build_dummy_object (true_type),
- fnname, args, NULL_TREE,
+ fnname, args,
+ TYPE_BINFO (true_type),
LOOKUP_NORMAL);
}
@@ -2423,17 +2372,21 @@ build_new_1 (exp)
init_expr = build_indirect_ref (alloc_node, NULL);
if (init == void_zero_node)
- init = build_default_init (full_type);
+ init = build_default_init (full_type, nelts);
else if (init && pedantic && has_array)
pedwarn ("ISO C++ forbids initialization in array new");
if (has_array)
- init_expr = build_vec_init (init_expr, init, 0);
+ init_expr
+ = build_vec_init (init_expr,
+ cp_build_binary_op (MINUS_EXPR, outer_nelts,
+ integer_one_node),
+ init, /*from_array=*/0);
else if (TYPE_NEEDS_CONSTRUCTING (type))
- init_expr = build_method_call (init_expr,
- complete_ctor_identifier,
- init, TYPE_BINFO (true_type),
- LOOKUP_NORMAL);
+ init_expr = build_special_member_call (init_expr,
+ complete_ctor_identifier,
+ init, TYPE_BINFO (true_type),
+ LOOKUP_NORMAL);
else
{
/* We are processing something like `new int (10)', which
@@ -2509,16 +2462,20 @@ build_new_1 (exp)
constructor, that would fix the nesting problem and we could
do away with this complexity. But that would complicate other
things; in particular, it would make it difficult to bail out
- if the allocation function returns null. */
+ if the allocation function returns null. Er, no, it wouldn't;
+ we just don't run the constructor. The standard says it's
+ unspecified whether or not the args are evaluated. */
if (cleanup)
{
tree end, sentry, begin;
begin = get_target_expr (boolean_true_node);
- sentry = TREE_OPERAND (begin, 0);
+ CLEANUP_EH_ONLY (begin) = 1;
+
+ sentry = TARGET_EXPR_SLOT (begin);
- TREE_OPERAND (begin, 2)
+ TARGET_EXPR_CLEANUP (begin)
= build (COND_EXPR, void_type_node, sentry,
cleanup, void_zero_node);
@@ -2552,8 +2509,12 @@ build_new_1 (exp)
{
if (check_new)
{
- tree ifexp = cp_build_binary_op (NE_EXPR, alloc_node,
- integer_zero_node);
+ tree nullexp;
+ tree ifexp;
+
+ nullexp = convert (TREE_TYPE (alloc_node),
+ use_cookie ? cookie_size : size_zero_node);
+ ifexp = cp_build_binary_op (NE_EXPR, alloc_node, nullexp);
rval = build_conditional_expr (ifexp, rval, alloc_node);
}
@@ -2748,6 +2709,9 @@ get_temp_regvar (type, init)
initialization of a vector of aggregate types.
BASE is a reference to the vector, of ARRAY_TYPE.
+ MAXINDEX is the maximum index of the array (one less than the
+ number of elements). It is only used if
+ TYPE_DOMAIN (TREE_TYPE (BASE)) == NULL_TREE.
INIT is the (possibly NULL) initializer.
FROM_ARRAY is 0 if we should init everything with INIT
@@ -2758,8 +2722,8 @@ get_temp_regvar (type, init)
but use assignment instead of initialization. */
tree
-build_vec_init (base, init, from_array)
- tree base, init;
+build_vec_init (base, maxindex, init, from_array)
+ tree base, init, maxindex;
int from_array;
{
tree rval;
@@ -2779,16 +2743,17 @@ build_vec_init (base, init, from_array)
tree try_block = NULL_TREE;
tree try_body = NULL_TREE;
int num_initialized_elts = 0;
- tree maxindex = array_type_nelts (TREE_TYPE (base));
- if (maxindex == error_mark_node)
+ if (TYPE_DOMAIN (atype))
+ maxindex = array_type_nelts (atype);
+
+ if (maxindex == NULL_TREE || maxindex == error_mark_node)
return error_mark_node;
- /* For g++.ext/arrnew.C. */
- if (init && TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == NULL_TREE)
- init = digest_init (atype, init, 0);
-
- if (init && !TYPE_NEEDS_CONSTRUCTING (type)
+ if (init
+ && (from_array == 2
+ ? (!CLASS_TYPE_P (type) || !TYPE_HAS_COMPLEX_ASSIGN_REF (type))
+ : !TYPE_NEEDS_CONSTRUCTING (type))
&& ((TREE_CODE (init) == CONSTRUCTOR
/* Don't do this if the CONSTRUCTOR might contain something
that might throw and require us to clean up. */
@@ -2801,7 +2766,6 @@ build_vec_init (base, init, from_array)
store_constructor will handle the semantics for us. */
stmt_expr = build (INIT_EXPR, atype, base, init);
- TREE_SIDE_EFFECTS (stmt_expr) = 1;
return stmt_expr;
}
@@ -2973,7 +2937,7 @@ build_vec_init (base, init, from_array)
sorry
("cannot initialize multi-dimensional array with initializer");
elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
- 0, 0);
+ 0, 0, 0);
}
else
elt_init = build_aggr_init (build1 (INDIRECT_REF, type, base),
@@ -3098,7 +3062,8 @@ build_dtor_call (exp, dtor_kind, flags)
default:
abort ();
}
- return build_method_call (exp, name, NULL_TREE, NULL_TREE, flags);
+ return build_method_call (exp, name, NULL_TREE,
+ TYPE_BINFO (TREE_TYPE (exp)), flags);
}
/* Generate a call to a destructor. TYPE is the type to cast ADDR to.
@@ -3132,11 +3097,18 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
if (TREE_CODE (type) == POINTER_TYPE)
{
type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- if (!VOID_TYPE_P (type) && !complete_type_or_else (type, addr))
- return error_mark_node;
if (TREE_CODE (type) == ARRAY_TYPE)
goto handle_array;
- if (! IS_AGGR_TYPE (type))
+
+ if (VOID_TYPE_P (type)
+ /* We don't want to warn about delete of void*, only other
+ incomplete types. Deleting other incomplete types
+ invokes undefined behavior, but it is not ill-formed, so
+ compile to something that would even do The Right Thing
+ (TM) should the type have a trivial dtor and no delete
+ operator. */
+ || !complete_type_or_diagnostic (type, addr, 1)
+ || !IS_AGGR_TYPE (type))
{
/* Call the builtin operator delete. */
return build_builtin_delete_call (addr);
@@ -3150,8 +3122,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
else if (TREE_CODE (type) == ARRAY_TYPE)
{
handle_array:
- if (TREE_SIDE_EFFECTS (addr))
- addr = save_expr (addr);
+
if (TYPE_DOMAIN (type) == NULL_TREE)
{
error ("unknown array size in delete");
@@ -3180,7 +3151,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
return void_zero_node;
return build_op_delete_call
- (DELETE_EXPR, addr, c_sizeof_nowarn (type),
+ (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL),
NULL_TREE);
}
@@ -3198,7 +3169,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
{
/* We will use ADDR multiple times so we must save it. */
addr = save_expr (addr);
- /* Delete the object. */
+ /* Delete the object. */
do_delete = build_builtin_delete_call (addr);
/* Otherwise, treat this like a complete object destructor
call. */
@@ -3215,7 +3186,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
/* Build the call. */
do_delete = build_op_delete_call (DELETE_EXPR,
addr,
- c_sizeof_nowarn (type),
+ cxx_sizeof_nowarn (type),
LOOKUP_NORMAL,
NULL_TREE);
/* Call the complete object destructor. */
@@ -3226,7 +3197,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
{
/* Make sure we have access to the member op delete, even though
we'll actually be calling it from the destructor. */
- build_op_delete_call (DELETE_EXPR, addr, c_sizeof_nowarn (type),
+ build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
LOOKUP_NORMAL, NULL_TREE);
}
@@ -3250,65 +3221,18 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
}
}
-/* At the end of a destructor, call the destructors for our base classes
- and members.
+/* At the beginning of a destructor, push cleanups that will call the
+ destructors for our base classes and members.
- Called from finish_destructor_body. */
+ Called from begin_destructor_body. */
void
-perform_base_cleanups ()
+push_base_cleanups ()
{
tree binfos;
int i, n_baseclasses;
tree member;
tree expr;
- tree member_destructions = NULL;
- tree vbase_destructions = NULL;
-
- for (member = TYPE_FIELDS (current_class_type); member;
- member = TREE_CHAIN (member))
- {
- if (TREE_CODE (member) != FIELD_DECL)
- continue;
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
- {
- tree this_member = (build_component_ref
- (current_class_ref, member,
- NULL_TREE, 0));
- tree this_type = TREE_TYPE (member);
- expr = build_delete (this_type, this_member,
- sfk_complete_destructor,
- LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
- 0);
- if (!member_destructions)
- member_destructions = expr;
- else
- member_destructions = build (COMPOUND_EXPR,
- TREE_TYPE (member_destructions),
- expr,
- member_destructions);
- }
- }
- if (member_destructions)
- finish_expr_stmt (member_destructions);
-
- binfos = BINFO_BASETYPES (TYPE_BINFO (current_class_type));
- n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
-
- /* Take care of the remaining baseclasses. */
- for (i = n_baseclasses - 1; i >= 0; i--)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
- || TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- expr = build_scoped_method_call (current_class_ref, base_binfo,
- base_dtor_identifier,
- NULL_TREE);
-
- finish_expr_stmt (expr);
- }
/* Run destructors for all virtual baseclasses. */
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
@@ -3330,35 +3254,56 @@ perform_base_cleanups ()
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
{
- tree base_ptr_type = build_pointer_type (base_type);
- expr = current_class_ptr;
-
- /* Convert to the basetype here, as we know the layout is
- fixed. What is more, if we let build_method_call do it,
- it will use the vtable, which may have been clobbered
- by the deletion of our primary base. */
-
- expr = build1 (NOP_EXPR, base_ptr_type, expr);
- expr = build (PLUS_EXPR, base_ptr_type, expr,
- BINFO_OFFSET (vbase));
- expr = build_indirect_ref (expr, NULL);
- expr = build_method_call (expr, base_dtor_identifier,
- NULL_TREE, vbase,
- LOOKUP_NORMAL);
+ expr = build_special_member_call (current_class_ref,
+ base_dtor_identifier,
+ NULL_TREE,
+ vbase,
+ (LOOKUP_NORMAL
+ | LOOKUP_NONVIRTUAL));
expr = build (COND_EXPR, void_type_node, cond,
expr, void_zero_node);
- if (!vbase_destructions)
- vbase_destructions = expr;
- else
- vbase_destructions = build (COMPOUND_EXPR,
- TREE_TYPE (vbase_destructions),
- expr,
- vbase_destructions);
+ finish_decl_cleanup (NULL_TREE, expr);
}
}
}
- if (vbase_destructions)
- finish_expr_stmt (vbase_destructions);
+
+ binfos = BINFO_BASETYPES (TYPE_BINFO (current_class_type));
+ n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
+
+ /* Take care of the remaining baseclasses. */
+ for (i = 0; i < n_baseclasses; i++)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+ if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
+ || TREE_VIA_VIRTUAL (base_binfo))
+ continue;
+
+ expr = build_special_member_call (current_class_ref,
+ base_dtor_identifier,
+ NULL_TREE, base_binfo,
+ LOOKUP_NORMAL | LOOKUP_NONVIRTUAL);
+ finish_decl_cleanup (NULL_TREE, expr);
+ }
+
+ for (member = TYPE_FIELDS (current_class_type); member;
+ member = TREE_CHAIN (member))
+ {
+ if (TREE_CODE (member) != FIELD_DECL || DECL_ARTIFICIAL (member))
+ continue;
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
+ {
+ tree this_member = (build_class_member_access_expr
+ (current_class_ref, member,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false));
+ tree this_type = TREE_TYPE (member);
+ expr = build_delete (this_type, this_member,
+ sfk_complete_destructor,
+ LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
+ 0);
+ finish_decl_cleanup (NULL_TREE, expr);
+ }
+ }
}
/* For type TYPE, delete the virtual baseclass objects of DECL. */
@@ -3419,15 +3364,13 @@ build_vec_delete (base, maxindex, auto_delete_vec, use_global_delete)
base = stabilize_reference (base);
- /* Since we can use base many times, save_expr it. */
- if (TREE_SIDE_EFFECTS (base))
- base = save_expr (base);
-
if (TREE_CODE (type) == POINTER_TYPE)
{
/* Step back one from start of vector, and read dimension. */
tree cookie_addr;
+ if (TREE_SIDE_EFFECTS (base))
+ base = save_expr (base);
type = strip_array_types (TREE_TYPE (type));
cookie_addr = build (MINUS_EXPR,
build_pointer_type (sizetype),
@@ -3441,6 +3384,8 @@ build_vec_delete (base, maxindex, auto_delete_vec, use_global_delete)
maxindex = array_type_nelts_total (type);
type = strip_array_types (type);
base = build_unary_op (ADDR_EXPR, base, 1);
+ if (TREE_SIDE_EFFECTS (base))
+ base = save_expr (base);
}
else
{
diff --git a/contrib/gcc/cp/lang-options.h b/contrib/gcc/cp/lang-options.h
index 10daa40..d4748be 100644
--- a/contrib/gcc/cp/lang-options.h
+++ b/contrib/gcc/cp/lang-options.h
@@ -72,10 +72,10 @@ DEFINE_LANG_NAME ("C++")
N_("Export functions even if they can be inlined") },
{ "-fimplicit-templates", "" },
{ "-fno-implicit-templates",
- N_("Only emit explicit template instatiations") },
+ N_("Only emit explicit template instantiations") },
{ "-fimplicit-inline-templates", "" },
{ "-fno-implicit-inline-templates",
- N_("Only emit explicit instatiations of inline templates") },
+ N_("Only emit explicit instantiations of inline templates") },
{ "-finit-priority", "" },
{ "-fno-init-priority", "" },
{ "-fmemoize-lookups", "" },
diff --git a/contrib/gcc/cp/lang-specs.h b/contrib/gcc/cp/lang-specs.h
index a2bdf90..f7de6d4 100644
--- a/contrib/gcc/cp/lang-specs.h
+++ b/contrib/gcc/cp/lang-specs.h
@@ -33,27 +33,14 @@ Boston, MA 02111-1307, USA. */
{".c++", "@c++", 0},
{".C", "@c++", 0},
{"@c++",
- /* cc1plus has an integrated ISO C preprocessor. We should invoke
- the external preprocessor if -save-temps is given. */
- "%{E|M|MM:cpp0 -lang-c++ %{!no-gcc:-D__GNUG__=%v1}\
- %{!Wno-deprecated:-D__DEPRECATED}\
- %{!fno-exceptions:-D__EXCEPTIONS}\
- %{ansi:-D__STRICT_ANSI__ -trigraphs -$} %(cpp_options)}\
+ "%{E|M|MM:cc1plus -E %{!no-gcc:-D__GNUG__=%v1}\
+ %(cpp_options) %2 %(cpp_debug_options)}\
%{!E:%{!M:%{!MM:\
- %{save-temps|no-integrated-cpp:cpp0 -lang-c++ \
- %{!no-gcc:-D__GNUG__=%v1}\
- %{!Wno-deprecated:-D__DEPRECATED}\
- %{!fno-exceptions:-D__EXCEPTIONS}\
- %{ansi:-D__STRICT_ANSI__ -trigraphs -$}\
- %(cpp_options) %{save-temps:%b.ii} %{!save-temps:%g.ii} \n}\
+ %{save-temps|no-integrated-cpp:cc1plus -E %{!no-gcc:-D__GNUG__=%v1}\
+ %(cpp_options) %2 %{save-temps:%b.ii} %{!save-temps:%g.ii} \n}\
cc1plus %{save-temps|no-integrated-cpp:-fpreprocessed %{save-temps:%b.ii} %{!save-temps:%g.ii}}\
- %{!save-temps:%{!no-integrated-cpp:%(cpp_unique_options)\
- %{!no-gcc:-D__GNUG__=%v1} \
- %{!Wno-deprecated:-D__DEPRECATED}\
- %{!fno-exceptions:-D__EXCEPTIONS}\
- %{ansi:-D__STRICT_ANSI__}}}\
- %{ansi:-trigraphs -$}\
- %(cc1_options) %2 %{+e1*}\
+ %{!save-temps:%{!no-integrated-cpp:%(cpp_unique_options) %{!no-gcc:-D__GNUG__=%v1}}}\
+ %(cc1_options) %2 %{+e1*}\
%{!fsyntax-only:%(invoke_as)}}}}",
CPLUSPLUS_CPP_SPEC},
{".ii", "@c++-cpp-output", 0},
diff --git a/contrib/gcc/cp/lex.c b/contrib/gcc/cp/lex.c
index c40469c..6660c84 100644
--- a/contrib/gcc/cp/lex.c
+++ b/contrib/gcc/cp/lex.c
@@ -23,16 +23,12 @@ Boston, MA 02111-1307, USA. */
/* This file is the lexical analyzer for GNU C++. */
-/* Cause the `yydebug' variable to be defined. */
-#define YYDEBUG 1
-
#include "config.h"
#include "system.h"
#include "input.h"
#include "tree.h"
#include "cp-tree.h"
#include "cpplib.h"
-#include "c-lex.h"
#include "lex.h"
#include "parse.h"
#include "flags.h"
@@ -85,11 +81,6 @@ extern int yychar; /* the lookahead symbol */
extern YYSTYPE yylval; /* the semantic value of the */
/* lookahead symbol */
-/* These flags are used by c-lex.c. In C++, they're always off and on,
- respectively. */
-int warn_traditional = 0;
-int flag_digraphs = 1;
-
/* the declaration found for the last IDENTIFIER token read in. yylex
must look this up to detect typedefs, which get token type
tTYPENAME, so it is left around in case the identifier is not a
@@ -206,37 +197,6 @@ int interface_only; /* whether or not current file is only for
int interface_unknown; /* whether or not we know this class
to behave according to #pragma interface. */
-/* Tree code classes. */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
-
-static const char cplus_tree_code_type[] = {
- 'x',
-#include "cp-tree.def"
-};
-#undef DEFTREECODE
-
-/* Table indexed by tree code giving number of expression
- operands beyond the fixed part of the node structure.
- Not used for types or decls. */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
-
-static const int cplus_tree_code_length[] = {
- 0,
-#include "cp-tree.def"
-};
-#undef DEFTREECODE
-
-/* Names of tree components.
- Used for printing out the tree and error messages. */
-#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
-
-static const char *const cplus_tree_code_name[] = {
- "@@dummy",
-#include "cp-tree.def"
-};
-#undef DEFTREECODE
/* Initialization before switch parsing. */
void
@@ -303,7 +263,8 @@ init_operators ()
: &operator_name_info[(int) CODE]); \
oni->identifier = identifier; \
oni->name = NAME; \
- oni->mangled_name = MANGLING;
+ oni->mangled_name = MANGLING; \
+ oni->arity = ARITY;
#include "operators.def"
#undef DEF_OPERATOR
@@ -363,7 +324,6 @@ struct resword
_true_. */
#define D_EXT 0x01 /* GCC extension */
#define D_ASM 0x02 /* in C99, but has a switch to turn it off */
-#define D_OPNAME 0x04 /* operator names */
CONSTRAINT(ridbits_fit, RID_LAST_MODIFIER < sizeof(unsigned long) * CHAR_BIT);
@@ -397,23 +357,19 @@ static const struct resword reswords[] =
{ "__restrict__", RID_RESTRICT, 0 },
{ "__signed", RID_SIGNED, 0 },
{ "__signed__", RID_SIGNED, 0 },
+ { "__thread", RID_THREAD, 0 },
{ "__typeof", RID_TYPEOF, 0 },
{ "__typeof__", RID_TYPEOF, 0 },
{ "__volatile", RID_VOLATILE, 0 },
{ "__volatile__", RID_VOLATILE, 0 },
{ "asm", RID_ASM, D_ASM },
- { "and", RID_AND, D_OPNAME },
- { "and_eq", RID_AND_EQ, D_OPNAME },
{ "auto", RID_AUTO, 0 },
- { "bitand", RID_BITAND, D_OPNAME },
- { "bitor", RID_BITOR, D_OPNAME },
{ "bool", RID_BOOL, 0 },
{ "break", RID_BREAK, 0 },
{ "case", RID_CASE, 0 },
{ "catch", RID_CATCH, 0 },
{ "char", RID_CHAR, 0 },
{ "class", RID_CLASS, 0 },
- { "compl", RID_COMPL, D_OPNAME },
{ "const", RID_CONST, 0 },
{ "const_cast", RID_CONSTCAST, 0 },
{ "continue", RID_CONTINUE, 0 },
@@ -439,11 +395,7 @@ static const struct resword reswords[] =
{ "mutable", RID_MUTABLE, 0 },
{ "namespace", RID_NAMESPACE, 0 },
{ "new", RID_NEW, 0 },
- { "not", RID_NOT, D_OPNAME },
- { "not_eq", RID_NOT_EQ, D_OPNAME },
{ "operator", RID_OPERATOR, 0 },
- { "or", RID_OR, D_OPNAME },
- { "or_eq", RID_OR_EQ, D_OPNAME },
{ "private", RID_PRIVATE, 0 },
{ "protected", RID_PROTECTED, 0 },
{ "public", RID_PUBLIC, 0 },
@@ -474,11 +426,8 @@ static const struct resword reswords[] =
{ "volatile", RID_VOLATILE, 0 },
{ "wchar_t", RID_WCHAR, 0 },
{ "while", RID_WHILE, 0 },
- { "xor", RID_XOR, D_OPNAME },
- { "xor_eq", RID_XOR_EQ, D_OPNAME },
};
-#define N_reswords (sizeof reswords / sizeof (struct resword))
/* Table mapping from RID_* constants to yacc token numbers.
Unfortunately we have to have entries for all the keywords in all
@@ -503,6 +452,7 @@ const short rid_to_yy[RID_MAX] =
/* RID_BOUNDED */ 0,
/* RID_UNBOUNDED */ 0,
/* RID_COMPLEX */ TYPESPEC,
+ /* RID_THREAD */ SCSPEC,
/* C++ */
/* RID_FRIEND */ SCSPEC,
@@ -591,20 +541,7 @@ const short rid_to_yy[RID_MAX] =
/* RID_REINTCAST */ REINTERPRET_CAST,
/* RID_STATCAST */ STATIC_CAST,
- /* alternate spellings */
- /* RID_AND */ ANDAND,
- /* RID_AND_EQ */ ASSIGN,
- /* RID_NOT */ '!',
- /* RID_NOT_EQ */ EQCOMPARE,
- /* RID_OR */ OROR,
- /* RID_OR_EQ */ ASSIGN,
- /* RID_XOR */ '^',
- /* RID_XOR_EQ */ ASSIGN,
- /* RID_BITAND */ '&',
- /* RID_BITOR */ '|',
- /* RID_COMPL */ '~',
-
- /* Objective C */
+ /* Objective-C */
/* RID_ID */ 0,
/* RID_AT_ENCODE */ 0,
/* RID_AT_END */ 0,
@@ -625,15 +562,14 @@ init_reswords ()
{
unsigned int i;
tree id;
- int mask = ((flag_operator_names ? 0 : D_OPNAME)
- | (flag_no_asm ? D_ASM : 0)
+ int mask = ((flag_no_asm ? D_ASM : 0)
| (flag_no_gnu_keywords ? D_EXT : 0));
/* It is not necessary to register ridpointers as a GC root, because
all the trees it points to are permanently interned in the
get_identifier hash anyway. */
ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
- for (i = 0; i < N_reswords; i++)
+ for (i = 0; i < ARRAY_SIZE (reswords); i++)
{
id = get_identifier (reswords[i].word);
C_RID_CODE (id) = reswords[i].rid;
@@ -668,27 +604,12 @@ const char *
cxx_init (filename)
const char *filename;
{
- decl_printable_name = lang_printable_name;
input_filename = "<internal>";
init_reswords ();
init_spew ();
init_tree ();
- init_cplus_expand ();
init_cp_semantics ();
-
- add_c_tree_codes ();
-
- memcpy (tree_code_type + (int) LAST_C_TREE_CODE,
- cplus_tree_code_type,
- (int)LAST_CPLUS_TREE_CODE - (int)LAST_C_TREE_CODE);
- memcpy (tree_code_length + (int) LAST_C_TREE_CODE,
- cplus_tree_code_length,
- (LAST_CPLUS_TREE_CODE - (int)LAST_C_TREE_CODE) * sizeof (int));
- memcpy (tree_code_name + (int) LAST_C_TREE_CODE,
- cplus_tree_code_name,
- (LAST_CPLUS_TREE_CODE - (int)LAST_C_TREE_CODE) * sizeof (char *));
-
init_operators ();
init_method ();
init_error ();
@@ -715,13 +636,15 @@ cxx_init (filename)
/* Create the built-in __null node. */
null_node = build_int_2 (0, 0);
- TREE_TYPE (null_node) = type_for_size (POINTER_SIZE, 0);
+ TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
ridpointers[RID_NULL] = null_node;
token_count = init_cpp_parse ();
interface_unknown = 1;
filename = c_common_init (filename);
+ if (filename == NULL)
+ return NULL;
init_cp_pragma ();
@@ -806,8 +729,8 @@ static int *reduce_count;
int *token_count;
#if 0
-#define REDUCE_LENGTH (sizeof (yyr2) / sizeof (yyr2[0]))
-#define TOKEN_LENGTH (256 + sizeof (yytname) / sizeof (yytname[0]))
+#define REDUCE_LENGTH ARRAY_SIZE (yyr2)
+#define TOKEN_LENGTH (256 + ARRAY_SIZE (yytname))
#endif
#ifdef GATHER_STATISTICS
@@ -885,22 +808,6 @@ print_parse_statistics ()
#endif
}
-/* Sets the value of the 'yydebug' variable to VALUE.
- This is a function so we don't have to have YYDEBUG defined
- in order to build the compiler. */
-
-void
-cxx_set_yydebug (value)
- int value;
-{
-#if YYDEBUG != 0
- extern int yydebug;
- yydebug = value;
-#else
- warning ("YYDEBUG not defined");
-#endif
-}
-
/* Helper function to load global variables with interface
information. */
@@ -1167,7 +1074,7 @@ do_pending_lang_change ()
pop_lang_context ();
}
-/* Return true if d is in a global scope. */
+/* Return true if d is in a global scope. */
static int
is_global (d)
@@ -1188,6 +1095,40 @@ is_global (d)
}
}
+/* Issue an error message indicating that the lookup of NAME (an
+ IDENTIFIER_NODE) failed. */
+
+void
+unqualified_name_lookup_error (tree name)
+{
+ if (IDENTIFIER_OPNAME_P (name))
+ {
+ if (name != ansi_opname (ERROR_MARK))
+ error ("`%D' not defined", name);
+ }
+ else if (current_function_decl == 0)
+ error ("`%D' was not declared in this scope", name);
+ else
+ {
+ if (IDENTIFIER_NAMESPACE_VALUE (name) != error_mark_node
+ || IDENTIFIER_ERROR_LOCUS (name) != current_function_decl)
+ {
+ static int undeclared_variable_notice;
+
+ error ("`%D' undeclared (first use this function)", name);
+
+ if (! undeclared_variable_notice)
+ {
+ error ("(Each undeclared identifier is reported only once for each function it appears in.)");
+ undeclared_variable_notice = 1;
+ }
+ }
+ /* Prevent repeated error messages. */
+ SET_IDENTIFIER_NAMESPACE_VALUE (name, error_mark_node);
+ SET_IDENTIFIER_ERROR_LOCUS (name, current_function_decl);
+ }
+}
+
tree
do_identifier (token, parsing, args)
register tree token;
@@ -1197,6 +1138,7 @@ do_identifier (token, parsing, args)
register tree id;
int lexing = (parsing == 1 || parsing == 3);
+ timevar_push (TV_NAME_LOOKUP);
if (! lexing)
id = lookup_name (token, 0);
else
@@ -1227,86 +1169,27 @@ do_identifier (token, parsing, args)
being used as a declarator. So we call it again to get the error
message. */
id = lookup_name (token, 0);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (!id || (TREE_CODE (id) == FUNCTION_DECL
&& DECL_ANTICIPATED (id)))
{
if (current_template_parms)
- return build_min_nt (LOOKUP_EXPR, token);
- else if (IDENTIFIER_OPNAME_P (token))
- {
- if (token != ansi_opname (ERROR_MARK))
- error ("`%D' not defined", token);
- id = error_mark_node;
- }
- else if (current_function_decl == 0)
- {
- error ("`%D' was not declared in this scope", token);
- id = error_mark_node;
- }
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+ build_min_nt (LOOKUP_EXPR, token));
+ else if (IDENTIFIER_TYPENAME_P (token))
+ /* A templated conversion operator might exist. */
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, token);
else
{
- if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node
- || IDENTIFIER_ERROR_LOCUS (token) != current_function_decl)
- {
- static int undeclared_variable_notice;
-
- error ("`%D' undeclared (first use this function)", token);
-
- if (! undeclared_variable_notice)
- {
- error ("(Each undeclared identifier is reported only once for each function it appears in.)");
- undeclared_variable_notice = 1;
- }
- }
- id = error_mark_node;
- /* Prevent repeated error messages. */
- SET_IDENTIFIER_NAMESPACE_VALUE (token, error_mark_node);
- SET_IDENTIFIER_ERROR_LOCUS (token, current_function_decl);
+ unqualified_name_lookup_error (token);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
}
- if (TREE_CODE (id) == VAR_DECL && DECL_DEAD_FOR_LOCAL (id))
- {
- tree shadowed = DECL_SHADOWED_FOR_VAR (id);
- while (shadowed != NULL_TREE && TREE_CODE (shadowed) == VAR_DECL
- && DECL_DEAD_FOR_LOCAL (shadowed))
- shadowed = DECL_SHADOWED_FOR_VAR (shadowed);
- if (!shadowed)
- shadowed = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (id));
- if (shadowed)
- {
- if (!DECL_ERROR_REPORTED (id))
- {
- warning ("name lookup of `%s' changed",
- IDENTIFIER_POINTER (token));
- cp_warning_at (" matches this `%D' under ISO standard rules",
- shadowed);
- cp_warning_at (" matches this `%D' under old rules", id);
- DECL_ERROR_REPORTED (id) = 1;
- }
- id = shadowed;
- }
- else if (!DECL_ERROR_REPORTED (id))
- {
- DECL_ERROR_REPORTED (id) = 1;
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (id)))
- {
- error ("name lookup of `%s' changed for new ISO `for' scoping",
- IDENTIFIER_POINTER (token));
- cp_error_at (" cannot use obsolete binding at `%D' because it has a destructor", id);
- id = error_mark_node;
- }
- else
- {
- pedwarn ("name lookup of `%s' changed for new ISO `for' scoping",
- IDENTIFIER_POINTER (token));
- cp_pedwarn_at (" using obsolete binding at `%D'", id);
- }
- }
- }
+ id = check_for_out_of_scope_variable (id);
+
/* TREE_USED is set in `hack_identifier'. */
if (TREE_CODE (id) == CONST_DECL)
{
@@ -1337,28 +1220,15 @@ do_identifier (token, parsing, args)
|| TREE_CODE (id) == USING_DECL))
id = build_min_nt (LOOKUP_EXPR, token);
- return id;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, id);
}
tree
-do_scoped_id (token, parsing)
+do_scoped_id (token, id)
tree token;
- int parsing;
+ tree id;
{
- tree id;
- /* during parsing, this is ::name. Otherwise, it is black magic. */
- if (parsing)
- {
- id = make_node (CPLUS_BINDING);
- if (!qualified_lookup_using_namespace (token, global_namespace, id, 0))
- id = NULL_TREE;
- else
- id = BINDING_VALUE (id);
- }
- else
- id = IDENTIFIER_GLOBAL_VALUE (token);
- if (parsing && yychar == YYEMPTY)
- yychar = yylex ();
+ timevar_push (TV_NAME_LOOKUP);
if (!id || (TREE_CODE (id) == FUNCTION_DECL
&& DECL_ANTICIPATED (id)))
{
@@ -1366,7 +1236,7 @@ do_scoped_id (token, parsing)
{
id = build_min_nt (LOOKUP_EXPR, token);
LOOKUP_EXPR_GLOBAL (id) = 1;
- return id;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, id);
}
if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node)
error ("`::%D' undeclared (first use here)", token);
@@ -1397,11 +1267,11 @@ do_scoped_id (token, parsing)
{
id = build_min_nt (LOOKUP_EXPR, token);
LOOKUP_EXPR_GLOBAL (id) = 1;
- return id;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, id);
}
/* else just use the decl */
}
- return convert_from_reference (id);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, convert_from_reference (id));
}
tree
@@ -1495,6 +1365,12 @@ retrofit_lang_decl (t)
ld = (struct lang_decl *) ggc_alloc_cleared (size);
+ ld->decl_flags.can_be_full = CAN_HAVE_FULL_LANG_DECL_P (t) ? 1 : 0;
+ ld->decl_flags.u1sel = TREE_CODE (t) == NAMESPACE_DECL ? 1 : 0;
+ ld->decl_flags.u2sel = 0;
+ if (ld->decl_flags.can_be_full)
+ ld->u.f.u3sel = TREE_CODE (t) == FUNCTION_DECL ? 1 : 0;
+
DECL_LANG_SPECIFIC (t) = ld;
if (current_lang_name == lang_name_cplusplus)
SET_DECL_LANGUAGE (t, lang_cplusplus);
@@ -1511,7 +1387,7 @@ retrofit_lang_decl (t)
}
void
-copy_lang_decl (node)
+cxx_dup_lang_specific_decl (node)
tree node;
{
int size;
@@ -1543,7 +1419,7 @@ copy_decl (decl)
tree copy;
copy = copy_node (decl);
- copy_lang_decl (copy);
+ cxx_dup_lang_specific_decl (copy);
return copy;
}
@@ -1559,7 +1435,10 @@ copy_lang_type (node)
if (! TYPE_LANG_SPECIFIC (node))
return;
- size = sizeof (struct lang_type);
+ if (TYPE_LANG_SPECIFIC (node)->u.h.is_lang_type_class)
+ size = sizeof (struct lang_type);
+ else
+ size = sizeof (struct lang_type_ptrmem);
lt = (struct lang_type *) ggc_alloc (size);
memcpy (lt, TYPE_LANG_SPECIFIC (node), size);
TYPE_LANG_SPECIFIC (node) = lt;
@@ -1584,7 +1463,7 @@ copy_type (type)
}
tree
-cp_make_lang_type (code)
+cxx_make_type (code)
enum tree_code code;
{
register tree t = make_node (code);
@@ -1599,6 +1478,7 @@ cp_make_lang_type (code)
ggc_alloc_cleared (sizeof (struct lang_type)));
TYPE_LANG_SPECIFIC (t) = pi;
+ pi->u.c.h.is_lang_type_class = 1;
#ifdef GATHER_STATISTICS
tree_node_counts[(int)lang_type] += 1;
@@ -1639,7 +1519,7 @@ tree
make_aggr_type (code)
enum tree_code code;
{
- tree t = cp_make_lang_type (code);
+ tree t = cxx_make_type (code);
if (IS_AGGR_TYPE_CODE (code))
SET_IS_AGGR_TYPE (t, 1);
@@ -1647,20 +1527,6 @@ make_aggr_type (code)
return t;
}
-void
-compiler_error VPARAMS ((const char *msg, ...))
-{
- char buf[1024];
-
- VA_OPEN (ap, msg);
- VA_FIXEDARG (ap, const char *, msg);
-
- vsprintf (buf, msg, ap);
- VA_CLOSE (ap);
-
- error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
-}
-
/* Return the type-qualifier corresponding to the identifier given by
RID. */
diff --git a/contrib/gcc/cp/lex.h b/contrib/gcc/cp/lex.h
index 9f868337..15de168 100644
--- a/contrib/gcc/cp/lex.h
+++ b/contrib/gcc/cp/lex.h
@@ -68,15 +68,15 @@ typedef unsigned long RID_BIT_TYPE; /* assumed at least 32 bits */
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
used in a context which makes it a reference to a variable. */
-extern tree lastiddecl;
+extern GTY(()) tree lastiddecl;
/* Back-door communication channel to the lexer. */
extern int looking_for_typename;
extern int looking_for_template;
/* Tell the lexer where to look for names. */
-extern tree got_scope;
-extern tree got_object;
+extern GTY(()) tree got_scope;
+extern GTY(()) tree got_object;
/* Pending language change.
Positive is push count, negative is pop count. */
diff --git a/contrib/gcc/cp/mangle.c b/contrib/gcc/cp/mangle.c
index 10f2b62..7180648 100644
--- a/contrib/gcc/cp/mangle.c
+++ b/contrib/gcc/cp/mangle.c
@@ -1,5 +1,5 @@
/* Name mangling for the 3.0 C++ ABI.
- Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Written by Alex Samuel <sameul@codesourcery.com>
This file is part of GNU CC.
@@ -50,10 +50,13 @@
#include "config.h"
#include "system.h"
#include "tree.h"
+#include "tm_p.h"
#include "cp-tree.h"
+#include "real.h"
#include "obstack.h"
#include "toplev.h"
#include "varray.h"
+#include "ggc.h"
/* Debugging support. */
@@ -74,15 +77,16 @@
# define MANGLE_TRACE_TREE(FN, NODE)
#endif
-/* Non-zero if NODE is a class template-id. We can't rely on
+/* Nonzero if NODE is a class template-id. We can't rely on
CLASSTYPE_USE_TEMPLATE here because of tricky bugs in the parser
that hard to distinguish A<T> from A, where A<T> is the type as
instantiated outside of the template, and A is the type used
without parameters inside the template. */
-#define CLASSTYPE_TEMPLATE_ID_P(NODE) \
- (TYPE_LANG_SPECIFIC (NODE) != NULL \
- && CLASSTYPE_TEMPLATE_INFO (NODE) != NULL \
- && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))
+#define CLASSTYPE_TEMPLATE_ID_P(NODE) \
+ (TYPE_LANG_SPECIFIC (NODE) != NULL \
+ && (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM \
+ || (CLASSTYPE_TEMPLATE_INFO (NODE) != NULL \
+ && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))))
/* Things we only need one of. This module is not reentrant. */
static struct globals
@@ -122,7 +126,7 @@ static tree subst_identifiers[SUBID_MAX];
/* Single-letter codes for builtin integer types, defined in
<builtin-type>. These are indexed by integer_type_kind values. */
-static char
+static const char
integer_type_codes[itk_none] =
{
'c', /* itk_char */
@@ -159,11 +163,13 @@ static void write_nested_name PARAMS ((tree));
static void write_prefix PARAMS ((tree));
static void write_template_prefix PARAMS ((tree));
static void write_unqualified_name PARAMS ((tree));
+static void write_conversion_operator_name (tree);
static void write_source_name PARAMS ((tree));
static int hwint_to_ascii PARAMS ((unsigned HOST_WIDE_INT, unsigned int, char *, unsigned));
static void write_number PARAMS ((unsigned HOST_WIDE_INT, int,
unsigned int));
static void write_integer_cst PARAMS ((tree));
+static void write_real_cst PARAMS ((tree));
static void write_identifier PARAMS ((const char *));
static void write_special_name_constructor PARAMS ((tree));
static void write_special_name_destructor PARAMS ((tree));
@@ -193,11 +199,11 @@ static const char *mangle_decl_string PARAMS ((tree));
/* Control functions. */
-static inline void start_mangling PARAMS ((tree));
-static inline const char *finish_mangling PARAMS ((bool));
+static inline void start_mangling (tree);
+static inline const char *finish_mangling (bool);
static tree mangle_special_for_type PARAMS ((tree, const char *));
-/* Foreign language functions. */
+/* Foreign language functions. */
static void write_java_integer_type_codes PARAMS ((tree));
@@ -206,7 +212,7 @@ static void write_java_integer_type_codes PARAMS ((tree));
#define write_char(CHAR) \
obstack_1grow (&G.name_obstack, (CHAR))
-/* Append a sized buffer to the end of the mangled representation. */
+/* Append a sized buffer to the end of the mangled representation. */
#define write_chars(CHAR, LEN) \
obstack_grow (&G.name_obstack, (CHAR), (LEN))
@@ -215,12 +221,7 @@ static void write_java_integer_type_codes PARAMS ((tree));
#define write_string(STRING) \
obstack_grow (&G.name_obstack, (STRING), strlen (STRING))
-/* Return the position at which the next character will be appended to
- the mangled representation. */
-#define mangled_position() \
- obstack_object_size (&G.name_obstack)
-
-/* Non-zero if NODE1 and NODE2 are both TREE_LIST nodes and have the
+/* Nonzero if NODE1 and NODE2 are both TREE_LIST nodes and have the
same purpose (context, which may be a type) and value (template
decl). See write_template_prefix for more information on what this
is used for. */
@@ -232,15 +233,11 @@ static void write_java_integer_type_codes PARAMS ((tree));
|| TREE_PURPOSE (NODE1) == TREE_PURPOSE (NODE2)) \
&& TREE_VALUE (NODE1) == TREE_VALUE (NODE2))
-/* Write out a signed quantity in base 10. */
-#define write_signed_number(NUMBER) \
- write_number ((NUMBER), /*unsigned_p=*/0, 10)
-
/* Write out an unsigned quantity in base 10. */
#define write_unsigned_number(NUMBER) \
write_number ((NUMBER), /*unsigned_p=*/1, 10)
-/* If DECL is a template instance, return non-zero and, if
+/* If DECL is a template instance, return nonzero and, if
TEMPLATE_INFO is non-NULL, set *TEMPLATE_INFO to its template info.
Otherwise return zero. */
@@ -260,7 +257,7 @@ decl_is_template_id (decl, template_info)
if (template_info != NULL)
/* For a templated TYPE_DECL, the template info is hanging
off the type. */
- *template_info = CLASSTYPE_TEMPLATE_INFO (type);
+ *template_info = TYPE_TEMPLATE_INFO (type);
return 1;
}
}
@@ -380,7 +377,7 @@ add_substitution (node)
dump_substitution_candidates ();
}
-/* Helper function for find_substitution. Returns non-zero if NODE,
+/* Helper function for find_substitution. Returns nonzero if NODE,
which may be a decl or a CLASS_TYPE, is a template-id with template
name of substitution_index[INDEX] in the ::std namespace. */
@@ -408,12 +405,12 @@ is_std_substitution (node, index)
return (DECL_NAMESPACE_STD_P (CP_DECL_CONTEXT (decl))
&& TYPE_LANG_SPECIFIC (type)
- && CLASSTYPE_TEMPLATE_INFO (type)
- && (DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
+ && TYPE_TEMPLATE_INFO (type)
+ && (DECL_NAME (TYPE_TI_TEMPLATE (type))
== subst_identifiers[index]));
}
-/* Helper function for find_substitution. Returns non-zero if NODE,
+/* Helper function for find_substitution. Returns nonzero if NODE,
which may be a decl or a CLASS_TYPE, is the template-id
::std::identifier<char>, where identifier is
substitution_index[INDEX]. */
@@ -473,7 +470,7 @@ is_std_substitution_char (node, index)
candidates for entities appearing earlier in the same mangling
If a substitution is found, write its mangled representation and
- return non-zero. If none is found, just return zero. */
+ return nonzero. If none is found, just return zero. */
static int
find_substitution (node)
@@ -585,7 +582,7 @@ find_substitution (node)
}
/* Now check the list of available substitutions for this mangling
- operation. */
+ operation. */
for (i = 0; i < size; ++i)
{
tree candidate = VARRAY_TREE (G.substitutions, i);
@@ -657,7 +654,7 @@ write_encoding (decl)
tree fn_type;
if (decl_is_template_id (decl, NULL))
- fn_type = get_mostly_instantiated_function_type (decl, NULL, NULL);
+ fn_type = get_mostly_instantiated_function_type (decl);
else
fn_type = TREE_TYPE (decl);
@@ -675,7 +672,7 @@ write_encoding (decl)
::= <nested-name>
::= <local-name>
- If IGNORE_LOCAL_SCOPE is non-zero, this production of <name> is
+ If IGNORE_LOCAL_SCOPE is nonzero, this production of <name> is
called from <local-name>, which mangles the enclosing scope
elsewhere and then uses this function to mangle just the part
underneath the function scope. So don't use the <local-name>
@@ -847,7 +844,8 @@ write_nested_name (decl)
write_char ('E');
}
-/* <prefix> ::= <prefix> <unqualified-name>>
+/* <prefix> ::= <prefix> <unqualified-name>
+ ::= <template-param>
::= <template-prefix> <template-args>
::= # empty
::= <substitution> */
@@ -870,7 +868,6 @@ write_prefix (node)
return;
if (DECL_P (node))
- /* Node is a decl. */
{
/* If this is a function decl, that means we've hit function
scope, so this prefix must be for a local name. In this
@@ -884,18 +881,22 @@ write_prefix (node)
decl_is_template_id (decl, &template_info);
}
else
- /* Node is a type. */
{
+ /* Node is a type. */
decl = TYPE_NAME (node);
if (CLASSTYPE_TEMPLATE_ID_P (node))
- template_info = CLASSTYPE_TEMPLATE_INFO (node);
+ template_info = TYPE_TEMPLATE_INFO (node);
}
/* In G++ 3.2, the name of the template parameter was used. */
- if (TREE_CODE (node) == TEMPLATE_TYPE_PARM)
+ if (TREE_CODE (node) == TEMPLATE_TYPE_PARM
+ && !abi_version_at_least (2))
G.need_abi_warning = true;
- if (template_info != NULL)
+ if (TREE_CODE (node) == TEMPLATE_TYPE_PARM
+ && abi_version_at_least (2))
+ write_template_param (node);
+ else if (template_info != NULL)
/* Templated. */
{
write_template_prefix (decl);
@@ -912,6 +913,7 @@ write_prefix (node)
}
/* <template-prefix> ::= <prefix> <template component>
+ ::= <template-param>
::= <substitution> */
static void
@@ -931,7 +933,7 @@ write_template_prefix (node)
if (decl_is_template_id (decl, &template_info))
template = TI_TEMPLATE (template_info);
else if (CLASSTYPE_TEMPLATE_ID_P (type))
- template = CLASSTYPE_TI_TEMPLATE (type);
+ template = TYPE_TI_TEMPLATE (type);
else
/* Oops, not a template. */
abort ();
@@ -967,11 +969,18 @@ write_template_prefix (node)
return;
/* In G++ 3.2, the name of the template template parameter was used. */
- if (TREE_CODE (TREE_TYPE (template)) == TEMPLATE_TEMPLATE_PARM)
+ if (TREE_CODE (TREE_TYPE (template)) == TEMPLATE_TEMPLATE_PARM
+ && !abi_version_at_least (2))
G.need_abi_warning = true;
- write_prefix (context);
- write_unqualified_name (decl);
+ if (TREE_CODE (TREE_TYPE (template)) == TEMPLATE_TEMPLATE_PARM
+ && abi_version_at_least (2))
+ write_template_param (TREE_TYPE (template));
+ else
+ {
+ write_prefix (context);
+ write_unqualified_name (decl);
+ }
add_substitution (substitution);
}
@@ -1000,14 +1009,12 @@ write_unqualified_name (decl)
tree type;
if (decl_is_template_id (decl, NULL))
{
- tree fn_type = get_mostly_instantiated_function_type (decl, NULL,
- NULL);
+ tree fn_type = get_mostly_instantiated_function_type (decl);
type = TREE_TYPE (fn_type);
}
else
- type = TREE_TYPE (DECL_NAME (decl));
- write_string ("cv");
- write_type (type);
+ type = DECL_CONV_FN_TYPE (decl);
+ write_conversion_operator_name (type);
}
else if (DECL_OVERLOADED_OPERATOR_P (decl))
{
@@ -1023,6 +1030,15 @@ write_unqualified_name (decl)
write_source_name (DECL_NAME (decl));
}
+/* Write the unqualified-name for a conversion operator to TYPE. */
+
+static void
+write_conversion_operator_name (tree type)
+{
+ write_string ("cv");
+ write_type (type);
+}
+
/* Non-termial <source-name>. IDENTIFIER is an IDENTIFIER_NODE.
<source-name> ::= </length/ number> <identifier> */
@@ -1098,7 +1114,7 @@ write_number (number, unsigned_p, base)
/* Write out an integral CST in decimal. Most numbers are small, and
representable in a HOST_WIDE_INT. Occasionally we'll have numbers
- bigger than that, which we must deal with. */
+ bigger than that, which we must deal with. */
static inline void
write_integer_cst (cst)
@@ -1109,7 +1125,7 @@ write_integer_cst (cst)
if (TREE_INT_CST_HIGH (cst) + (sign < 0))
{
/* A bignum. We do this in chunks, each of which fits in a
- HOST_WIDE_INT. */
+ HOST_WIDE_INT. */
char buffer[sizeof (HOST_WIDE_INT) * 8 * 2];
unsigned HOST_WIDE_INT chunk;
unsigned chunk_digits;
@@ -1119,18 +1135,18 @@ write_integer_cst (cst)
int done;
/* HOST_WIDE_INT must be at least 32 bits, so 10^9 is
- representable. */
+ representable. */
chunk = 1000000000;
chunk_digits = 9;
if (sizeof (HOST_WIDE_INT) >= 8)
{
- /* It is at least 64 bits, so 10^18 is representable. */
+ /* It is at least 64 bits, so 10^18 is representable. */
chunk_digits = 18;
chunk *= chunk;
}
- type = signed_or_unsigned_type (1, TREE_TYPE (cst));
+ type = c_common_signed_or_unsigned_type (1, TREE_TYPE (cst));
base = build_int_2 (chunk, 0);
n = build_int_2 (TREE_INT_CST_LOW (cst), TREE_INT_CST_HIGH (cst));
TREE_TYPE (n) = TREE_TYPE (base) = type;
@@ -1171,6 +1187,72 @@ write_integer_cst (cst)
}
}
+/* Write out a floating-point literal.
+
+ "Floating-point literals are encoded using the bit pattern of the
+ target processor's internal representation of that number, as a
+ fixed-length lowercase hexadecimal string, high-order bytes first
+ (even if the target processor would store low-order bytes first).
+ The "n" prefix is not used for floating-point literals; the sign
+ bit is encoded with the rest of the number.
+
+ Here are some examples, assuming the IEEE standard representation
+ for floating point numbers. (Spaces are for readability, not
+ part of the encoding.)
+
+ 1.0f Lf 3f80 0000 E
+ -1.0f Lf bf80 0000 E
+ 1.17549435e-38f Lf 0080 0000 E
+ 1.40129846e-45f Lf 0000 0001 E
+ 0.0f Lf 0000 0000 E"
+
+ Caller is responsible for the Lx and the E. */
+static void
+write_real_cst (value)
+ tree value;
+{
+ if (abi_version_at_least (2))
+ {
+ long target_real[4]; /* largest supported float */
+ char buffer[9]; /* eight hex digits in a 32-bit number */
+ int i, limit, dir;
+
+ tree type = TREE_TYPE (value);
+ int words = GET_MODE_BITSIZE (TYPE_MODE (type)) / 32;
+
+ real_to_target (target_real, &TREE_REAL_CST (value),
+ TYPE_MODE (type));
+
+ /* The value in target_real is in the target word order,
+ so we must write it out backward if that happens to be
+ little-endian. write_number cannot be used, it will
+ produce uppercase. */
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ i = 0, limit = words, dir = 1;
+ else
+ i = words - 1, limit = -1, dir = -1;
+
+ for (; i != limit; i += dir)
+ {
+ sprintf (buffer, "%08lx", target_real[i]);
+ write_chars (buffer, 8);
+ }
+ }
+ else
+ {
+ /* In G++ 3.3 and before the REAL_VALUE_TYPE was written out
+ literally. Note that compatibility with 3.2 is impossible,
+ because the old floating-point emulator used a different
+ format for REAL_VALUE_TYPE. */
+ size_t i;
+ for (i = 0; i < sizeof (TREE_REAL_CST (value)); ++i)
+ write_number (((unsigned char *) &TREE_REAL_CST (value))[i],
+ /*unsigned_p*/ 1,
+ /*base*/ 16);
+ G.need_abi_warning = 1;
+ }
+}
+
/* Non-terminal <identifier>.
<identifier> ::= </unqualified source code identifier> */
@@ -1293,7 +1375,7 @@ static void
write_discriminator (discriminator)
int discriminator;
{
- /* If discriminator is zero, don't write anything. Otherwise... */
+ /* If discriminator is zero, don't write anything. Otherwise... */
if (discriminator > 0)
{
write_char ('_');
@@ -1359,7 +1441,7 @@ static void
write_type (type)
tree type;
{
- /* This gets set to non-zero if TYPE turns out to be a (possibly
+ /* This gets set to nonzero if TYPE turns out to be a (possibly
CV-qualified) builtin type. */
int is_builtin_type = 0;
@@ -1584,7 +1666,8 @@ write_builtin_type (type)
if (itk == itk_none)
{
- tree t = type_for_mode (TYPE_MODE (type), TREE_UNSIGNED (type));
+ tree t = c_common_type_for_mode (TYPE_MODE (type),
+ TREE_UNSIGNED (type));
if (type == t)
{
if (TYPE_PRECISION (type) == 128)
@@ -1662,7 +1745,7 @@ write_function_type (type)
}
/* Non-terminal <bare-function-type>. TYPE is a FUNCTION_TYPE or
- METHOD_TYPE. If INCLUDE_RETURN_TYPE is non-zero, the return value
+ METHOD_TYPE. If INCLUDE_RETURN_TYPE is nonzero, the return value
is mangled before the parameter types. If non-NULL, DECL is
FUNCTION_DECL for the function whose type is being emitted.
@@ -1687,7 +1770,7 @@ write_bare_function_type (type, include_return_type_p, decl)
}
/* Write the mangled representation of a method parameter list of
- types given in PARM_TYPES. If METHOD_P is non-zero, the function is
+ types given in PARM_TYPES. If METHOD_P is nonzero, the function is
considered a non-static method, and the this parameter is omitted.
If non-NULL, DECL is the FUNCTION_DECL for the function whose
parameters are being emitted. */
@@ -1769,24 +1852,37 @@ static void
write_template_args (args)
tree args;
{
- int i;
- int length = TREE_VEC_LENGTH (args);
-
MANGLE_TRACE_TREE ("template-args", args);
- my_friendly_assert (length > 0, 20000422);
+ write_char ('I');
+
+ if (TREE_CODE (args) == TREE_VEC)
+ {
+ int i;
+ int length = TREE_VEC_LENGTH (args);
+ my_friendly_assert (length > 0, 20000422);
- if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+ if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+ {
+ /* We have nested template args. We want the innermost template
+ argument list. */
+ args = TREE_VEC_ELT (args, length - 1);
+ length = TREE_VEC_LENGTH (args);
+ }
+ for (i = 0; i < length; ++i)
+ write_template_arg (TREE_VEC_ELT (args, i));
+ }
+ else
{
- /* We have nested template args. We want the innermost template
- argument list. */
- args = TREE_VEC_ELT (args, length - 1);
- length = TREE_VEC_LENGTH (args);
+ my_friendly_assert (TREE_CODE (args) == TREE_LIST, 20021014);
+
+ while (args)
+ {
+ write_template_arg (TREE_VALUE (args));
+ args = TREE_CHAIN (args);
+ }
}
- write_char ('I');
- for (i = 0; i < length; ++i)
- write_template_arg (TREE_VEC_ELT (args, i));
write_char ('E');
}
@@ -1796,7 +1892,9 @@ write_template_args (args)
<expr-primary> ::= <template-param>
::= L <type> <value number> E # literal
- ::= L <mangled-name> E # external name */
+ ::= L <mangled-name> E # external name
+ ::= sr <type> <unqualified-name>
+ ::= sr <type> <unqualified-name> <template-args> */
static void
write_expression (expr)
@@ -1827,14 +1925,15 @@ write_expression (expr)
code = TREE_CODE (expr);
}
- /* Handle template parameters. */
+ /* Handle template parameters. */
if (code == TEMPLATE_TYPE_PARM
|| code == TEMPLATE_TEMPLATE_PARM
|| code == BOUND_TEMPLATE_TEMPLATE_PARM
|| code == TEMPLATE_PARM_INDEX)
write_template_param (expr);
/* Handle literals. */
- else if (TREE_CODE_CLASS (code) == 'c')
+ else if (TREE_CODE_CLASS (code) == 'c'
+ || (abi_version_at_least (2) && code == CONST_DECL))
write_template_arg_literal (expr);
else if (DECL_P (expr))
{
@@ -1852,6 +1951,75 @@ write_expression (expr)
write_string ("st");
write_type (TREE_OPERAND (expr, 0));
}
+ else if (abi_version_at_least (2) && TREE_CODE (expr) == SCOPE_REF)
+ {
+ tree scope = TREE_OPERAND (expr, 0);
+ tree member = TREE_OPERAND (expr, 1);
+
+ /* If the MEMBER is a real declaration, then the qualifying
+ scope was not dependent. Ideally, we would not have a
+ SCOPE_REF in those cases, but sometimes we do. If the second
+ argument is a DECL, then the name must not have been
+ dependent. */
+ if (DECL_P (member))
+ write_expression (member);
+ else
+ {
+ tree template_args;
+
+ write_string ("sr");
+ write_type (scope);
+ /* If MEMBER is a template-id, separate the template
+ from the arguments. */
+ if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
+ {
+ template_args = TREE_OPERAND (member, 1);
+ member = TREE_OPERAND (member, 0);
+ if (TREE_CODE (member) == LOOKUP_EXPR)
+ member = TREE_OPERAND (member, 0);
+ }
+ else
+ template_args = NULL_TREE;
+ /* Write out the name of the MEMBER. */
+ if (IDENTIFIER_TYPENAME_P (member))
+ write_conversion_operator_name (TREE_TYPE (member));
+ else if (IDENTIFIER_OPNAME_P (member))
+ {
+ int i;
+ const char *mangled_name = NULL;
+
+ /* Unfortunately, there is no easy way to go from the
+ name of the operator back to the corresponding tree
+ code. */
+ for (i = 0; i < LAST_CPLUS_TREE_CODE; ++i)
+ if (operator_name_info[i].identifier == member)
+ {
+ /* The ABI says that we prefer binary operator
+ names to unary operator names. */
+ if (operator_name_info[i].arity == 2)
+ {
+ mangled_name = operator_name_info[i].mangled_name;
+ break;
+ }
+ else if (!mangled_name)
+ mangled_name = operator_name_info[i].mangled_name;
+ }
+ else if (assignment_operator_name_info[i].identifier
+ == member)
+ {
+ mangled_name
+ = assignment_operator_name_info[i].mangled_name;
+ break;
+ }
+ write_string (mangled_name);
+ }
+ else
+ write_source_name (member);
+ /* Write out the template arguments. */
+ if (template_args)
+ write_template_args (template_args);
+ }
+ }
else
{
int i;
@@ -1873,12 +2041,16 @@ write_expression (expr)
code = TREE_CODE (expr);
}
-
+
/* If it wasn't any of those, recursively expand the expression. */
write_string (operator_name_info[(int) code].mangled_name);
switch (code)
{
+ case CALL_EXPR:
+ sorry ("call_expr cannot be mangled due to a defect in the C++ ABI");
+ break;
+
case CAST_EXPR:
write_type (TREE_TYPE (expr));
write_expression (TREE_VALUE (TREE_OPERAND (expr, 0)));
@@ -1917,11 +2089,7 @@ write_expression (expr)
"Literal arguments, e.g. "A<42L>", are encoded with their type
and value. Negative integer values are preceded with "n"; for
example, "A<-42L>" becomes "1AILln42EE". The bool value false is
- encoded as 0, true as 1. If floating-point arguments are accepted
- as an extension, their values should be encoded using a
- fixed-length lowercase hexadecimal string corresponding to the
- internal representation (IEEE on IA-64), high-order bytes first,
- without leading zeroes. For example: "Lfbff000000E" is -1.0f." */
+ encoded as 0, true as 1." */
static void
write_template_arg_literal (value)
@@ -1948,24 +2116,7 @@ write_template_arg_literal (value)
write_integer_cst (value);
}
else if (TREE_CODE (value) == REAL_CST)
- {
-#ifdef CROSS_COMPILE
- static int explained;
-
- if (!explained)
- {
- sorry ("real-valued template parameters when cross-compiling");
- explained = 1;
- }
-#else
- size_t i;
- for (i = 0; i < sizeof (TREE_REAL_CST (value)); ++i)
- write_number (((unsigned char *)
- &TREE_REAL_CST (value))[i],
- /*unsigned_p=*/1,
- 16);
-#endif
- }
+ write_real_cst (value);
else
abort ();
@@ -2005,6 +2156,9 @@ write_template_arg (node)
else if (code == TEMPLATE_DECL)
/* A template appearing as a template arg is a template template arg. */
write_template_template_arg (node);
+ else if ((TREE_CODE_CLASS (code) == 'c' && code != PTRMEM_CST)
+ || (abi_version_at_least (2) && code == CONST_DECL))
+ write_template_arg_literal (node);
else if (DECL_P (node))
{
/* G++ 3.2 incorrectly mangled non-type template arguments of
@@ -2016,8 +2170,6 @@ write_template_arg (node)
write_encoding (node);
write_char ('E');
}
- else if (TREE_CODE_CLASS (code) == 'c' && code != PTRMEM_CST)
- write_template_arg_literal (node);
else
{
/* Template arguments may be expressions. */
@@ -2098,13 +2250,22 @@ write_pointer_to_member_type (type)
TEMPLATE_TEMPLATE_PARM, BOUND_TEMPLATE_TEMPLATE_PARM or a
TEMPLATE_PARM_INDEX.
- <template-param> ::= T </parameter/ number> _ */
+ <template-param> ::= T </parameter/ number> _
+
+ If we are internally mangling then we distinguish level and, for
+ non-type parms, type too. The mangling appends
+
+ </level/ number> _ </non-type type/ type> _
+
+ This is used by mangle_conv_op_name_for_type. */
static void
write_template_param (parm)
tree parm;
{
int parm_index;
+ int parm_level;
+ tree parm_type = NULL_TREE;
MANGLE_TRACE_TREE ("template-parm", parm);
@@ -2114,10 +2275,13 @@ write_template_param (parm)
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
parm_index = TEMPLATE_TYPE_IDX (parm);
+ parm_level = TEMPLATE_TYPE_LEVEL (parm);
break;
case TEMPLATE_PARM_INDEX:
parm_index = TEMPLATE_PARM_IDX (parm);
+ parm_level = TEMPLATE_PARM_LEVEL (parm);
+ parm_type = TREE_TYPE (TEMPLATE_PARM_DECL (parm));
break;
default:
@@ -2177,17 +2341,20 @@ write_substitution (seq_id)
write_char ('_');
}
-/* Start mangling a new name or type. */
+/* Start mangling ENTITY. */
static inline void
start_mangling (tree entity)
{
G.entity = entity;
G.need_abi_warning = false;
+ VARRAY_TREE_INIT (G.substitutions, 1, "mangling substitutions");
obstack_free (&G.name_obstack, obstack_base (&G.name_obstack));
}
-/* Done with mangling. Return the generated mangled name. */
+/* Done with mangling. Return the generated mangled name. If WARN is
+ true, and the name of G.entity will be mangled differently in a
+ future version of the ABI, issue a warning. */
static inline const char *
finish_mangling (bool warn)
@@ -2198,7 +2365,7 @@ finish_mangling (bool warn)
G.entity);
/* Clear all the substitutions. */
- VARRAY_POP_ALL (G.substitutions);
+ G.substitutions = 0;
/* Null-terminate the string. */
write_char ('\0');
@@ -2212,7 +2379,6 @@ void
init_mangle ()
{
gcc_obstack_init (&G.name_obstack);
- VARRAY_TREE_INIT (G.substitutions, 1, "mangling substitutions");
/* Cache these identifiers for quick comparison when checking for
standard substitutions. */
@@ -2454,24 +2620,53 @@ mangle_thunk (fn_decl, offset, vcall_offset)
return get_identifier (result);
}
+/* This hash table maps TYPEs to the IDENTIFIER for a conversion
+ operator to TYPE. The nodes are TREE_LISTs whose TREE_PURPOSE is
+ the TYPE and whose TREE_VALUE is the IDENTIFIER. */
+
+static GTY ((param_is (union tree_node))) htab_t conv_type_names;
+
+/* Hash a node (VAL1) in the table. */
+
+static hashval_t
+hash_type (const void *val)
+{
+ return htab_hash_pointer (TREE_PURPOSE ((tree) val));
+}
+
+/* Compare VAL1 (a node in the table) with VAL2 (a TYPE). */
+
+static int
+compare_type (const void *val1, const void *val2)
+{
+ return TREE_PURPOSE ((tree) val1) == (tree) val2;
+}
+
/* Return an identifier for the mangled unqualified name for a
conversion operator to TYPE. This mangling is not specified by the
ABI spec; it is only used internally. */
-
+
tree
-mangle_conv_op_name_for_type (type)
- tree type;
+mangle_conv_op_name_for_type (const tree type)
{
+ void **slot;
tree identifier;
-
- /* Build the mangling for TYPE. */
- const char *mangled_type = mangle_type_string (type);
- /* Allocate a temporary buffer for the complete name. */
- char *op_name = concat ("operator ", mangled_type, NULL);
- /* Find or create an identifier. */
- identifier = get_identifier (op_name);
- /* Done with the temporary buffer. */
- free (op_name);
+ char buffer[64];
+
+ if (conv_type_names == NULL)
+ conv_type_names = htab_create_ggc (31, &hash_type, &compare_type, NULL);
+
+ slot = htab_find_slot_with_hash (conv_type_names, type,
+ htab_hash_pointer (type), INSERT);
+ if (*slot)
+ return TREE_VALUE ((tree) *slot);
+
+ /* Create a unique name corresponding to TYPE. */
+ sprintf (buffer, "operator %lu",
+ (unsigned long) htab_elements (conv_type_names));
+ identifier = get_identifier (buffer);
+ *slot = build_tree_list (type, identifier);
+
/* Set bits on the identifier so we know later it's a conversion. */
IDENTIFIER_OPNAME_P (identifier) = 1;
IDENTIFIER_TYPENAME_P (identifier) = 1;
@@ -2539,3 +2734,4 @@ write_java_integer_type_codes (type)
abort ();
}
+#include "gt-cp-mangle.h"
diff --git a/contrib/gcc/cp/method.c b/contrib/gcc/cp/method.c
index 5bb555d..16682af 100644
--- a/contrib/gcc/cp/method.c
+++ b/contrib/gcc/cp/method.c
@@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "tree.h"
#include "cp-tree.h"
-#include "obstack.h"
#include "rtl.h"
#include "expr.h"
#include "output.h"
@@ -35,6 +34,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "ggc.h"
#include "tm_p.h"
+#include "target.h"
/* Various flags to control the mangling process. */
@@ -54,9 +54,6 @@ enum mangling_flags
typedef enum mangling_flags mangling_flags;
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
static void do_build_assign_ref PARAMS ((tree));
static void do_build_copy_constructor PARAMS ((tree));
static tree synthesize_exception_spec PARAMS ((tree, tree (*) (tree, void *), void *));
@@ -165,12 +162,26 @@ hack_identifier (value, name)
return error_mark_node;
}
TREE_USED (current_class_ptr) = 1;
+ if (processing_template_decl)
+ value = build_min_nt (COMPONENT_REF, current_class_ref, name);
+ else
+ {
+ tree access_type = current_class_type;
+
+ while (!DERIVED_FROM_P (context_for_name_lookup (value),
+ access_type))
+ {
+ access_type = TYPE_CONTEXT (access_type);
+ while (DECL_P (access_type))
+ access_type = DECL_CONTEXT (access_type);
+ }
- /* 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;
- value = build_component_ref (current_class_ref, name, NULL_TREE, 1);
+ enforce_access (access_type, value);
+ value
+ = build_class_member_access_expr (current_class_ref, value,
+ /*access_path=*/NULL_TREE,
+ /*preserve_reference=*/false);
+ }
}
else if ((TREE_CODE (value) == FUNCTION_DECL
&& DECL_FUNCTION_MEMBER_P (value))
@@ -183,7 +194,7 @@ hack_identifier (value, name)
value = OVL_CURRENT (value);
decl = maybe_dummy_object (DECL_CONTEXT (value), 0);
- value = build_component_ref (decl, name, NULL_TREE, 1);
+ value = finish_class_member_access_expr (decl, name);
}
else if (really_overloaded_fn (value))
;
@@ -267,10 +278,11 @@ make_thunk (function, delta, vcall_index)
{
tree thunk_id;
tree thunk;
- tree func_decl;
tree vcall_offset;
HOST_WIDE_INT d;
+ my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 20021025);
+
/* Scale the VCALL_INDEX to be in terms of bytes. */
if (vcall_index)
vcall_offset
@@ -283,64 +295,66 @@ make_thunk (function, delta, vcall_index)
d = tree_low_cst (delta, 0);
- if (TREE_CODE (function) != ADDR_EXPR)
- abort ();
- func_decl = TREE_OPERAND (function, 0);
- if (TREE_CODE (func_decl) != FUNCTION_DECL)
- abort ();
+ /* See if we already have the thunk in question. */
+ for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
+ if (THUNK_DELTA (thunk) == d
+ && ((THUNK_VCALL_OFFSET (thunk) != NULL_TREE)
+ == (vcall_offset != NULL_TREE))
+ && (THUNK_VCALL_OFFSET (thunk)
+ ? tree_int_cst_equal (THUNK_VCALL_OFFSET (thunk),
+ vcall_offset)
+ : true))
+ return thunk;
+
+ /* All thunks must be created before FUNCTION is actually emitted;
+ the ABI requires that all thunks be emitted together with the
+ function to which they transfer control. */
+ my_friendly_assert (!TREE_ASM_WRITTEN (function), 20021025);
+
+ thunk_id = mangle_thunk (function, delta, vcall_offset);
+ thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (function));
+ DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
+ cxx_dup_lang_specific_decl (function);
+ SET_DECL_ASSEMBLER_NAME (thunk, thunk_id);
+ DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
+ TREE_READONLY (thunk) = TREE_READONLY (function);
+ TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
+ TREE_PUBLIC (thunk) = TREE_PUBLIC (function);
+ if (flag_weak)
+ comdat_linkage (thunk);
+ SET_DECL_THUNK_P (thunk);
+ DECL_INITIAL (thunk) = build1 (ADDR_EXPR, vfunc_ptr_type_node, function);
+ THUNK_DELTA (thunk) = d;
+ THUNK_VCALL_OFFSET (thunk) = vcall_offset;
+ /* The thunk itself is not a constructor or destructor, even if
+ the thing it is thunking to is. */
+ DECL_INTERFACE_KNOWN (thunk) = 1;
+ DECL_NOT_REALLY_EXTERN (thunk) = 1;
+ DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
+ DECL_DESTRUCTOR_P (thunk) = 0;
+ DECL_CONSTRUCTOR_P (thunk) = 0;
+ /* And neither is it a clone. */
+ DECL_CLONED_FUNCTION (thunk) = NULL_TREE;
+ DECL_EXTERNAL (thunk) = 1;
+ DECL_ARTIFICIAL (thunk) = 1;
+ /* Even if this thunk is a member of a local class, we don't
+ need a static chain. */
+ DECL_NO_STATIC_CHAIN (thunk) = 1;
+ /* The THUNK is not a pending inline, even if the FUNCTION is. */
+ DECL_PENDING_INLINE_P (thunk) = 0;
+ DECL_INLINE (thunk) = 0;
+ DECL_DECLARED_INLINE_P (thunk) = 0;
+ /* Nor has it been deferred. */
+ DECL_DEFERRED_FN (thunk) = 0;
+ /* Add it to the list of thunks associated with FUNCTION. */
+ TREE_CHAIN (thunk) = DECL_THUNKS (function);
+ DECL_THUNKS (function) = thunk;
- thunk_id = mangle_thunk (TREE_OPERAND (function, 0),
- delta, vcall_offset);
- thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id);
- if (thunk && !DECL_THUNK_P (thunk))
- {
- error ("implementation-reserved name `%D' used", thunk_id);
- thunk = NULL_TREE;
- SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk);
- }
- if (thunk == NULL_TREE)
- {
- thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl));
- DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (func_decl);
- copy_lang_decl (func_decl);
- SET_DECL_ASSEMBLER_NAME (thunk, thunk_id);
- DECL_CONTEXT (thunk) = DECL_CONTEXT (func_decl);
- TREE_READONLY (thunk) = TREE_READONLY (func_decl);
- TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl);
- TREE_PUBLIC (thunk) = TREE_PUBLIC (func_decl);
- if (flag_weak)
- comdat_linkage (thunk);
- SET_DECL_THUNK_P (thunk);
- DECL_INITIAL (thunk) = function;
- THUNK_DELTA (thunk) = d;
- THUNK_VCALL_OFFSET (thunk) = vcall_offset;
- /* The thunk itself is not a constructor or destructor, even if
- the thing it is thunking to is. */
- DECL_INTERFACE_KNOWN (thunk) = 1;
- DECL_NOT_REALLY_EXTERN (thunk) = 1;
- DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
- DECL_DESTRUCTOR_P (thunk) = 0;
- DECL_CONSTRUCTOR_P (thunk) = 0;
- /* And neither is it a clone. */
- DECL_CLONED_FUNCTION (thunk) = NULL_TREE;
- DECL_EXTERNAL (thunk) = 1;
- DECL_ARTIFICIAL (thunk) = 1;
- /* Even if this thunk is a member of a local class, we don't
- need a static chain. */
- DECL_NO_STATIC_CHAIN (thunk) = 1;
- /* The THUNK is not a pending inline, even if the FUNC_DECL is. */
- DECL_PENDING_INLINE_P (thunk) = 0;
- /* Nor has it been deferred. */
- DECL_DEFERRED_FN (thunk) = 0;
- /* So that finish_file can write out any thunks that need to be: */
- pushdecl_top_level (thunk);
- SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk);
- }
return thunk;
}
/* Emit the definition of a C++ multiple inheritance vtable thunk. If
- EMIT_P is non-zero, the thunk is emitted immediately. */
+ EMIT_P is nonzero, the thunk is emitted immediately. */
void
use_thunk (thunk_fndecl, emit_p)
@@ -350,7 +364,7 @@ use_thunk (thunk_fndecl, emit_p)
tree fnaddr;
tree function;
tree vcall_offset;
- HOST_WIDE_INT delta;
+ HOST_WIDE_INT delta, vcall_value;
if (TREE_ASM_WRITTEN (thunk_fndecl))
return;
@@ -376,6 +390,17 @@ use_thunk (thunk_fndecl, emit_p)
delta = THUNK_DELTA (thunk_fndecl);
vcall_offset = THUNK_VCALL_OFFSET (thunk_fndecl);
+ if (vcall_offset)
+ {
+ vcall_value = tree_low_cst (vcall_offset, /*pos=*/0);
+
+ /* It is expected that a value of zero means no vcall. */
+ if (!vcall_value)
+ abort ();
+ }
+ else
+ vcall_value = 0;
+
/* And, if we need to emit the thunk, it's used. */
mark_used (thunk_fndecl);
/* This thunk is actually defined. */
@@ -398,8 +423,8 @@ use_thunk (thunk_fndecl, emit_p)
BLOCK_VARS (DECL_INITIAL (thunk_fndecl))
= DECL_ARGUMENTS (thunk_fndecl);
-#ifdef ASM_OUTPUT_MI_THUNK
- if (!vcall_offset)
+ if (targetm.asm_out.can_output_mi_thunk (thunk_fndecl, delta,
+ vcall_value, function))
{
const char *fnname;
current_function_decl = thunk_fndecl;
@@ -409,18 +434,23 @@ use_thunk (thunk_fndecl, emit_p)
init_function_start (thunk_fndecl, input_filename, lineno);
current_function_is_thunk = 1;
assemble_start_function (thunk_fndecl, fnname);
- ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
+
+ targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, delta,
+ vcall_value, function);
+
assemble_end_function (thunk_fndecl, fnname);
current_function_decl = 0;
cfun = 0;
+ /* Because init_function_start increments this, we must
+ decrement it. */
+ immediate_size_expand--;
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
}
else
-#endif /* 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. */
+ /* If we don't have the necessary code 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;
@@ -526,7 +556,6 @@ do_build_copy_constructor (fndecl)
int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);
tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
tree member_init_list = NULL_TREE;
- tree base_init_list = NULL_TREE;
int cvquals = cp_type_quals (TREE_TYPE (parm));
int i;
@@ -540,10 +569,12 @@ do_build_copy_constructor (fndecl)
{
tree binfo = TREE_VALUE (t);
- base_init_list = tree_cons (binfo,
- build_base_path (PLUS_EXPR, parm,
- binfo, 1),
- base_init_list);
+ member_init_list
+ = tree_cons (binfo,
+ build_tree_list (NULL_TREE,
+ build_base_path (PLUS_EXPR, parm,
+ binfo, 1)),
+ member_init_list);
}
for (i = 0; i < n_bases; ++i)
@@ -552,10 +583,12 @@ do_build_copy_constructor (fndecl)
if (TREE_VIA_VIRTUAL (binfo))
continue;
- base_init_list = tree_cons (binfo,
- build_base_path (PLUS_EXPR, parm,
- binfo, 1),
- base_init_list);
+ member_init_list
+ = tree_cons (binfo,
+ build_tree_list (NULL_TREE,
+ build_base_path (PLUS_EXPR, parm,
+ binfo, 1)),
+ member_init_list);
}
for (; fields; fields = TREE_CHAIN (fields))
@@ -599,9 +632,7 @@ do_build_copy_constructor (fndecl)
member_init_list
= tree_cons (field, init, member_init_list);
}
- member_init_list = nreverse (member_init_list);
- base_init_list = nreverse (base_init_list);
- emit_base_init (member_init_list, base_init_list);
+ finish_mem_initializers (member_init_list);
}
}
@@ -626,33 +657,39 @@ do_build_assign_ref (fndecl)
}
else
{
- tree fields = TYPE_FIELDS (current_class_type);
- int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);
- tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
+ tree fields;
int cvquals = cp_type_quals (TREE_TYPE (parm));
int i;
- for (i = 0; i < n_bases; ++i)
+ /* Assign to each of thedirect base classes. */
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (current_class_type); ++i)
{
- /* We must deal with the binfo's directly as a direct base
- might be inaccessible due to ambiguity. */
- tree binfo = TREE_VEC_ELT (binfos, i);
- tree src = build_base_path (PLUS_EXPR, parm, binfo, 1);
- tree dst = build_base_path (PLUS_EXPR, current_class_ref, binfo, 1);
-
- tree expr = build_method_call (dst,
- ansi_assopname (NOP_EXPR),
- build_tree_list (NULL_TREE, src),
- binfo,
- LOOKUP_NORMAL | LOOKUP_NONVIRTUAL);
- finish_expr_stmt (expr);
+ tree binfo;
+ tree converted_parm;
+
+ binfo = BINFO_BASETYPE (TYPE_BINFO (current_class_type), i);
+ /* We must convert PARM directly to the base class
+ explicitly since the base class may be ambiguous. */
+ converted_parm = build_base_path (PLUS_EXPR, parm, binfo, 1);
+ /* Call the base class assignment operator. */
+ finish_expr_stmt
+ (build_special_member_call (current_class_ref,
+ ansi_assopname (NOP_EXPR),
+ build_tree_list (NULL_TREE,
+ converted_parm),
+ binfo,
+ LOOKUP_NORMAL | LOOKUP_NONVIRTUAL));
}
- for (; fields; fields = TREE_CHAIN (fields))
+
+ /* Assign to each of the non-static data members. */
+ for (fields = TYPE_FIELDS (current_class_type);
+ fields;
+ fields = TREE_CHAIN (fields))
{
tree comp, init, t;
tree field = fields;
- if (TREE_CODE (field) != FIELD_DECL)
+ if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
if (CP_TYPE_CONST_P (TREE_TYPE (field)))
@@ -733,7 +770,7 @@ synthesize_method (fndecl)
during the generation of the implicit body points at the place
where the attempt to generate the function occurs, giving the
user a hint as to why we are attempting to generate the
- function. */
+ function. */
DECL_SOURCE_LINE (fndecl) = lineno;
DECL_SOURCE_FILE (fndecl) = input_filename;
@@ -808,7 +845,7 @@ synthesize_exception_spec (type, extractor, client)
tree type = TREE_TYPE (fields);
tree fn;
- if (TREE_CODE (fields) != FIELD_DECL)
+ if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
diff --git a/contrib/gcc/cp/operators.def b/contrib/gcc/cp/operators.def
index 05a5a39..42e4a47 100644
--- a/contrib/gcc/cp/operators.def
+++ b/contrib/gcc/cp/operators.def
@@ -5,7 +5,7 @@
non-overloadable operators (like the `?:' ternary operator).
Writtey by Mark Mitchell <mark@codesourcery.com>
- Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -54,7 +54,7 @@ Boston, MA 02111-1307, USA. */
ASSN_P
- A boolean value. If non-zero, this is an assignment operator.
+ A boolean value. If nonzero, this is an assignment operator.
Before including this file, you should define DEFOPERATOR
to take these arguments.
diff --git a/contrib/gcc/cp/optimize.c b/contrib/gcc/cp/optimize.c
index ac51cda..654d4cd 100644
--- a/contrib/gcc/cp/optimize.c
+++ b/contrib/gcc/cp/optimize.c
@@ -1,5 +1,5 @@
/* Perform optimizations on tree structure.
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Written by Mark Michell (mark@codesourcery.com).
This file is part of GNU CC.
@@ -41,7 +41,7 @@ static tree calls_setjmp_r PARAMS ((tree *, int *, void *));
static void update_cloned_parm PARAMS ((tree, tree));
static void dump_function PARAMS ((enum tree_dump_index, tree));
-/* Optimize the body of FN. */
+/* Optimize the body of FN. */
void
optimize_function (fn)
@@ -64,7 +64,7 @@ optimize_function (fn)
/* We do not inline thunks, as (a) the backend tries to optimize
the call to the thunkee, (b) tree based inlining breaks that
optimization, (c) virtual functions are rarely inlineable,
- and (d) ASM_OUTPUT_MI_THUNK is there to DTRT anyway. */
+ and (d) TARGET_ASM_OUTPUT_MI_THUNK is there to DTRT anyway. */
&& !DECL_THUNK_P (fn))
{
optimize_inline_calls (fn);
@@ -93,9 +93,9 @@ calls_setjmp_r (tp, walk_subtrees, data)
return setjmp_call_p (*tp) ? *tp : NULL_TREE;
}
-/* Returns non-zero if FN calls `setjmp' or some other function that
+/* Returns nonzero if FN calls `setjmp' or some other function that
can return more than once. This function is conservative; it may
- occasionally return a non-zero value even when FN does not actually
+ occasionally return a nonzero value even when FN does not actually
call `setjmp'. */
int
@@ -119,22 +119,21 @@ update_cloned_parm (parm, cloned_parm)
{
DECL_ABSTRACT_ORIGIN (cloned_parm) = parm;
- /* We may have taken its address. */
+ /* We may have taken its address. */
TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm);
- /* The definition might have different constness. */
+ /* The definition might have different constness. */
TREE_READONLY (cloned_parm) = TREE_READONLY (parm);
TREE_USED (cloned_parm) = TREE_USED (parm);
- /* The name may have changed from the declaration. */
+ /* The name may have changed from the declaration. */
DECL_NAME (cloned_parm) = DECL_NAME (parm);
- DECL_SOURCE_FILE (cloned_parm) = DECL_SOURCE_FILE (parm);
- DECL_SOURCE_LINE (cloned_parm) = DECL_SOURCE_LINE (parm);
+ DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
}
/* FN is a function that has a complete body. Clone the body as
- necessary. Returns non-zero if there's no longer any need to
+ necessary. Returns nonzero if there's no longer any need to
process the main body. */
int
@@ -164,9 +163,9 @@ maybe_clone_body (fn)
splay_tree decl_map;
/* Update CLONE's source position information to match FN's. */
- DECL_SOURCE_FILE (clone) = DECL_SOURCE_FILE (fn);
- DECL_SOURCE_LINE (clone) = DECL_SOURCE_LINE (fn);
+ DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
DECL_INLINE (clone) = DECL_INLINE (fn);
+ DID_INLINE_FUNC (clone) = DID_INLINE_FUNC (fn);
DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
DECL_COMDAT (clone) = DECL_COMDAT (fn);
DECL_WEAK (clone) = DECL_WEAK (fn);
@@ -178,7 +177,7 @@ maybe_clone_body (fn)
DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
- /* Adjust the parameter names and locations. */
+ /* Adjust the parameter names and locations. */
parm = DECL_ARGUMENTS (fn);
clone_parm = DECL_ARGUMENTS (clone);
/* Update the `this' parameter, which is always first. */
@@ -196,7 +195,7 @@ maybe_clone_body (fn)
{
/* Update this parameter. */
update_cloned_parm (parm, clone_parm);
- /* We should only give unused information for one clone. */
+ /* We should only give unused information for one clone. */
if (!first)
TREE_USED (clone_parm) = 1;
}
@@ -266,6 +265,9 @@ maybe_clone_body (fn)
/* Clean up. */
splay_tree_delete (decl_map);
+ /* The clone can throw iff the original function can throw. */
+ cp_function_chain->can_throw = !TREE_NOTHROW (fn);
+
/* Now, expand this function into RTL, if appropriate. */
finish_function (0);
BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
@@ -277,7 +279,7 @@ maybe_clone_body (fn)
return 1;
}
-/* Dump FUNCTION_DECL FN as tree dump PHASE. */
+/* Dump FUNCTION_DECL FN as tree dump PHASE. */
static void
dump_function (phase, fn)
diff --git a/contrib/gcc/cp/parse.y b/contrib/gcc/cp/parse.y
index e929ebe..46e5021 100644
--- a/contrib/gcc/cp/parse.y
+++ b/contrib/gcc/cp/parse.y
@@ -28,9 +28,6 @@ Boston, MA 02111-1307, USA. */
is given. Keep this in mind when reading the actions. */
%{
-/* Cause the `yydebug' variable to be defined. */
-#define YYDEBUG 1
-
#include "config.h"
#include "system.h"
@@ -39,17 +36,59 @@ Boston, MA 02111-1307, USA. */
#include "input.h"
#include "flags.h"
#include "cp-tree.h"
+#include "decl.h"
#include "lex.h"
+#include "c-pragma.h" /* For YYDEBUG definition. */
#include "output.h"
#include "except.h"
#include "toplev.h"
#include "ggc.h"
-extern struct obstack permanent_obstack;
-
/* Like YYERROR but do call yyerror. */
#define YYERROR1 { yyerror ("syntax error"); YYERROR; }
+/* Like the default stack expander, except (1) use realloc when possible,
+ (2) impose no hard maxiumum on stack size, (3) REALLY do not use alloca.
+
+ Irritatingly, YYSTYPE is defined after this %{ %} block, so we cannot
+ give malloced_yyvs its proper type. This is ok since all we need from
+ it is to be able to free it. */
+
+static short *malloced_yyss;
+static void *malloced_yyvs;
+
+#define yyoverflow(MSG, SS, SSSIZE, VS, VSSIZE, YYSSZ) \
+do { \
+ size_t newsize; \
+ short *newss; \
+ YYSTYPE *newvs; \
+ newsize = *(YYSSZ) *= 2; \
+ if (malloced_yyss) \
+ { \
+ newss = (short *) \
+ really_call_realloc (*(SS), newsize * sizeof (short)); \
+ newvs = (YYSTYPE *) \
+ really_call_realloc (*(VS), newsize * sizeof (YYSTYPE)); \
+ } \
+ else \
+ { \
+ newss = (short *) really_call_malloc (newsize * sizeof (short)); \
+ newvs = (YYSTYPE *) really_call_malloc (newsize * sizeof (YYSTYPE)); \
+ if (newss) \
+ memcpy (newss, *(SS), (SSSIZE)); \
+ if (newvs) \
+ memcpy (newvs, *(VS), (VSSIZE)); \
+ } \
+ if (!newss || !newvs) \
+ { \
+ yyerror (MSG); \
+ return 2; \
+ } \
+ *(SS) = newss; \
+ *(VS) = newvs; \
+ malloced_yyss = newss; \
+ malloced_yyvs = (void *) newvs; \
+} while (0)
#define OP0(NODE) (TREE_OPERAND (NODE, 0))
#define OP1(NODE) (TREE_OPERAND (NODE, 1))
@@ -57,26 +96,22 @@ extern struct obstack permanent_obstack;
error message if the user supplies an empty conditional expression. */
static const char *cond_stmt_keyword;
-/* Nonzero if we have an `extern "C"' acting as an extern specifier. */
-int have_extern_spec;
-int used_extern_spec;
-
/* List of types and structure classes of the current declaration. */
-static tree current_declspecs;
+static GTY(()) tree current_declspecs;
/* List of prefix attributes in effect.
Prefix attributes are parsed by the reserved_declspecs and declmods
rules. They create a list that contains *both* declspecs and attrs. */
/* ??? 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 GTY(()) tree prefix_attributes;
/* When defining an enumeration, this is the type of the enumeration. */
-static tree current_enum_type;
+static GTY(()) tree current_enum_type;
/* When parsing a conversion operator name, this is the scope of the
operator itself. */
-static tree saved_scopes;
+static GTY(()) tree saved_scopes;
static tree empty_parms PARAMS ((void));
static tree parse_decl0 PARAMS ((tree, tree, tree, tree, int));
@@ -89,6 +124,12 @@ static tree parse_bitfield PARAMS ((tree, tree, tree));
static tree parse_method PARAMS ((tree, tree, tree));
static void frob_specs PARAMS ((tree, tree));
static void check_class_key PARAMS ((tree, tree));
+static tree parse_scoped_id PARAMS ((tree));
+static tree parse_xref_tag (tree, tree, int);
+static tree parse_handle_class_head (tree, tree, tree, int, int *);
+static void parse_decl_instantiation (tree, tree, tree);
+static int parse_begin_function_definition (tree, tree);
+static tree parse_finish_call_expr (tree, tree, int);
/* Cons up an empty parameter list. */
static inline tree
@@ -97,7 +138,7 @@ empty_parms ()
tree parms;
#ifndef NO_IMPLICIT_EXTERN_C
- if (in_system_header && current_class_type == NULL
+ if (in_system_header && current_class_type == NULL
&& current_lang_name == lang_name_c)
parms = NULL_TREE;
else
@@ -118,18 +159,18 @@ frob_specs (specs_attrs, lookups)
if (current_declspecs
&& TREE_CODE (current_declspecs) != TREE_LIST)
current_declspecs = build_tree_list (NULL_TREE, current_declspecs);
- if (have_extern_spec && !used_extern_spec)
+ if (have_extern_spec)
{
/* We have to indicate that there is an "extern", but that it
was part of a language specifier. For instance,
-
+
extern "C" typedef int (*Ptr) ();
is well formed. */
current_declspecs = tree_cons (error_mark_node,
- get_identifier ("extern"),
+ get_identifier ("extern"),
current_declspecs);
- used_extern_spec = 1;
+ have_extern_spec = false;
}
}
@@ -222,26 +263,15 @@ check_class_key (key, aggr)
: key == record_type_node ? "struct" : "class", aggr);
}
-void
-cp_parse_init ()
-{
- ggc_add_tree_root (&current_declspecs, 1);
- ggc_add_tree_root (&prefix_attributes, 1);
- ggc_add_tree_root (&current_enum_type, 1);
- ggc_add_tree_root (&saved_scopes, 1);
-}
-
-/* Rename the "yyparse" function so that we can override it elsewhere. */
-#define yyparse yyparse_1
%}
%start program
-%union {
- long itype;
- tree ttype;
- char *strtype;
- enum tree_code code;
+%union { GTY(())
+ long itype;
+ tree ttype;
+ char *strtype;
+ enum tree_code code;
flagged_type_tree ftype;
struct unparsed_text *pi;
}
@@ -277,7 +307,7 @@ cp_parse_init ()
/* __func__, __FUNCTION__ or __PRETTY_FUNCTION__.
yylval contains an IDENTIFIER_NODE which indicates which one. */
-%token VAR_FUNC_NAME
+%token <ttype> VAR_FUNC_NAME
/* String constants in raw form.
yylval is a STRING_CST node. */
@@ -349,14 +379,14 @@ cp_parse_init ()
%type <ttype> PFUNCNAME maybe_identifier
%type <ttype> paren_expr_or_null nontrivial_exprlist SELFNAME
%type <ttype> expr_no_commas expr_no_comma_rangle
-%type <ttype> cast_expr unary_expr primary string STRING
-%type <ttype> reserved_declspecs boolean.literal
+%type <ttype> cast_expr unary_expr primary STRING
+%type <ttype> reserved_declspecs boolean_literal
%type <ttype> reserved_typespecquals
%type <ttype> SCSPEC TYPESPEC CV_QUALIFIER maybe_cv_qualifier
%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
+%type <ttype> any_word unoperator
%type <itype> save_lineno
%type <ttype> simple_stmt simple_if
@@ -366,14 +396,14 @@ cp_parse_init ()
%type <ttype> after_type_declarator_intern
%type <ttype> direct_notype_declarator direct_after_type_declarator
%type <itype> components notype_components
-%type <ttype> component_decl component_decl_1
+%type <ttype> component_decl component_decl_1
%type <ttype> component_declarator component_declarator0
%type <ttype> notype_component_declarator notype_component_declarator0
%type <ttype> after_type_component_declarator after_type_component_declarator0
%type <ttype> absdcl cv_qualifiers
%type <ttype> direct_abstract_declarator conversion_declarator
%type <ttype> new_declarator direct_new_declarator
-%type <ttype> xexpr parmlist parms bad_parm
+%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 expr_or_declarator_intern
@@ -382,7 +412,7 @@ cp_parse_init ()
%type <ttype> template_id do_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> complex_parmlist parms_comma
+%type <ttype> complex_parmlist parms_comma
%type <ttype> namespace_qualifier namespace_using_decl
%type <ftype> type_id new_type_id typed_typespecs typespec typed_declspecs
@@ -396,22 +426,22 @@ cp_parse_init ()
%token <ttype> PTYPENAME
%token <ttype> EXTERN_LANG_STRING ALL
%token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
-%token <pi> PRE_PARSED_FUNCTION_DECL
+%token <pi> PRE_PARSED_FUNCTION_DECL
%type <ttype> component_constructor_declarator
-%type <ttype> fn.def2 return_id constructor_declarator
-%type <ttype> .begin_function_body
+%type <ttype> fn_def2 return_id constructor_declarator
+%type <ttype> begin_function_body_
%type <ttype> class_head class_head_apparent_template
%type <ftype> class_head_decl class_head_defn
%type <ttype> base_class_list
%type <ttype> base_class_access_list
-%type <ttype> base_class maybe_base_class_list base_class.1
+%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
%type <ttype> object aggr
%type <itype> new delete
/* %type <ttype> primary_no_id */
%type <ttype> maybe_parmlist
-%type <ttype> member_init
+%type <ttype> begin_member_init member_init
%type <ftype> member_init_list
%type <ttype> template_parm_header template_spec_header template_header
%type <ttype> template_parm_list template_parm
@@ -432,7 +462,7 @@ cp_parse_init ()
%token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN
%type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN
%type <ttype> handler_args
-%type <ttype> self_template_type .finish_template_type
+%type <ttype> self_template_type finish_template_type_
%token NSNAME
%type <ttype> NSNAME
@@ -476,12 +506,11 @@ extdefs_opt:
;
.hush_warning:
- { have_extern_spec = 1;
- used_extern_spec = 0;
+ { have_extern_spec = true;
$<ttype>$ = NULL_TREE; }
;
.warning_ok:
- { have_extern_spec = 0; }
+ { have_extern_spec = false; }
;
extension:
@@ -514,9 +543,8 @@ extdef:
{ do_pending_inlines (); }
| template_def
{ do_pending_inlines (); }
- | asm_keyword '(' string ')' ';'
- { if (TREE_CHAIN ($3)) $3 = combine_strings ($3);
- assemble_asm ($3); }
+ | asm_keyword '(' STRING ')' ';'
+ { assemble_asm ($3); }
| extern_lang_string '{' extdefs_opt '}'
{ pop_lang_context (); }
| extern_lang_string .hush_warning fndef .warning_ok eat_saved_input
@@ -540,7 +568,7 @@ extdef:
;
namespace_alias:
- NAMESPACE identifier '='
+ NAMESPACE identifier '='
{ begin_only_namespace_names (); }
any_id ';'
{
@@ -627,7 +655,7 @@ template_parm_header:
template_spec_header:
TEMPLATE '<' '>'
- { begin_specialization();
+ { begin_specialization();
$$ = NULL_TREE; }
;
@@ -682,14 +710,7 @@ template_parm:
{ $$ = build_tree_list (NULL_TREE, $1); }
| template_template_parm '=' template_arg
{
- if (TREE_CODE ($3) != TEMPLATE_DECL
- && TREE_CODE ($3) != TEMPLATE_TEMPLATE_PARM
- && TREE_CODE ($3) != TYPE_DECL
- && TREE_CODE ($3) != UNBOUND_CLASS_TEMPLATE)
- {
- error ("invalid default template argument");
- $3 = error_mark_node;
- }
+ $3 = check_template_template_default_arg ($3);
$$ = build_tree_list ($3, $1);
}
;
@@ -778,9 +799,9 @@ eat_saved_input:
mem-initializer-list, so we open one there and suppress the one that
actually corresponds to the curly braces. */
function_body:
- .begin_function_body ctor_initializer_opt save_lineno '{'
+ begin_function_body_ ctor_initializer_opt save_lineno '{'
{ $<ttype>$ = begin_compound_stmt (/*has_no_scope=*/1); }
- compstmtend
+ compstmtend
{
STMT_LINENO ($<ttype>5) = $3;
finish_compound_stmt (/*has_no_scope=*/1, $<ttype>5);
@@ -798,15 +819,15 @@ fndef:
;
constructor_declarator:
- nested_name_specifier SELFNAME '('
+ nested_name_specifier SELFNAME '('
{ $$ = begin_constructor_declarator ($1, $2); }
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
- { $$ = begin_constructor_declarator ($1, $2);
+ { $$ = begin_constructor_declarator ($1, $2);
$$ = make_call_declarator ($$, empty_parms (), $4, $5);
}
- | global_scope nested_name_specifier SELFNAME '('
+ | global_scope nested_name_specifier SELFNAME '('
{ $$ = begin_constructor_declarator ($2, $3); }
parmlist ')' cv_qualifiers exception_specification_opt
{ $$ = make_call_declarator ($<ttype>5, $6, $8, $9); }
@@ -814,7 +835,7 @@ constructor_declarator:
{ $$ = begin_constructor_declarator ($2, $3);
$$ = make_call_declarator ($$, empty_parms (), $5, $6);
}
- | nested_name_specifier self_template_type '('
+ | nested_name_specifier self_template_type '('
{ $$ = begin_constructor_declarator ($1, $2); }
parmlist ')' cv_qualifiers exception_specification_opt
{ $$ = make_call_declarator ($<ttype>4, $5, $7, $8); }
@@ -822,12 +843,12 @@ constructor_declarator:
{ $$ = begin_constructor_declarator ($1, $2);
$$ = make_call_declarator ($$, empty_parms (), $4, $5);
}
- | global_scope nested_name_specifier self_template_type '('
+ | global_scope nested_name_specifier self_template_type '('
{ $$ = begin_constructor_declarator ($2, $3); }
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
- { $$ = begin_constructor_declarator ($2, $3);
+ { $$ = begin_constructor_declarator ($2, $3);
$$ = make_call_declarator ($$, empty_parms (), $5, $6);
}
;
@@ -835,19 +856,19 @@ constructor_declarator:
fn.def1:
typed_declspecs declarator
{ check_for_new_type ("return type", $1);
- if (!begin_function_definition ($1.t, $2))
+ if (!parse_begin_function_definition ($1.t, $2))
YYERROR1; }
| declmods notype_declarator
- { if (!begin_function_definition ($1.t, $2))
+ { if (!parse_begin_function_definition ($1.t, $2))
YYERROR1; }
| notype_declarator
- { if (!begin_function_definition (NULL_TREE, $1))
+ { if (!parse_begin_function_definition (NULL_TREE, $1))
YYERROR1; }
| declmods constructor_declarator
- { if (!begin_function_definition ($1.t, $2))
+ { if (!parse_begin_function_definition ($1.t, $2))
YYERROR1; }
| constructor_declarator
- { if (!begin_function_definition (NULL_TREE, $1))
+ { if (!parse_begin_function_definition (NULL_TREE, $1))
YYERROR1; }
;
@@ -872,7 +893,7 @@ component_constructor_declarator:
/* more C++ complexity. See component_decl for a comment on the
reduce/reduce conflict introduced by these rules. */
-fn.def2:
+fn_def2:
declmods component_constructor_declarator
{ $$ = parse_method ($2, $1.t, $1.lookups);
rest_of_mdef:
@@ -882,19 +903,19 @@ fn.def2:
yychar = YYLEX;
snarf_method ($$); }
| component_constructor_declarator
- { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
+ { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
goto rest_of_mdef; }
| typed_declspecs declarator
{ $$ = parse_method ($2, $1.t, $1.lookups); goto rest_of_mdef;}
| declmods notype_declarator
{ $$ = parse_method ($2, $1.t, $1.lookups); goto rest_of_mdef;}
| notype_declarator
- { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
+ { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
goto rest_of_mdef; }
| declmods constructor_declarator
{ $$ = parse_method ($2, $1.t, $1.lookups); goto rest_of_mdef;}
| constructor_declarator
- { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
+ { $$ = parse_method ($1, NULL_TREE, NULL_TREE);
goto rest_of_mdef; }
;
@@ -915,18 +936,15 @@ return_init:
;
base_init:
- ':' member_init_list
+ ':' { begin_mem_initializers (); } member_init_list
{
- if (! DECL_CONSTRUCTOR_P (current_function_decl))
- error ("only constructors take base initializers");
- else if ($2.new_type_flag == 0)
+ if ($3.new_type_flag == 0)
error ("no base or member initializers given following ':'");
-
- finish_mem_initializers ($2.t);
+ finish_mem_initializers ($3.t);
}
;
-.begin_function_body:
+begin_function_body_:
/* empty */
{
$$ = begin_function_body ();
@@ -935,20 +953,20 @@ base_init:
member_init_list:
/* empty */
- {
- $$.new_type_flag = 0;
- $$.t = NULL_TREE;
+ {
+ $$.new_type_flag = 0;
+ $$.t = NULL_TREE;
}
| member_init
- {
- $$.new_type_flag = 1;
- $$.t = $1;
+ {
+ $$.new_type_flag = 1;
+ $$.t = $1;
}
| member_init_list ',' member_init
- {
- if ($3)
+ {
+ if ($3)
{
- $$.new_type_flag = 1;
+ $$.new_type_flag = 1;
TREE_CHAIN ($3) = $1.t;
$$.t = $3;
}
@@ -958,38 +976,35 @@ member_init_list:
| member_init_list error
;
-member_init:
- '(' nonnull_exprlist ')'
+begin_member_init:
+ /* empty */
{
- if (current_class_name)
+ if (current_class_name)
pedwarn ("anachronistic old style base class initializer");
- $$ = expand_member_init (current_class_ref, NULL_TREE, $2);
+ $$ = expand_member_init (NULL_TREE);
+ in_base_initializer = $$ && !DECL_P ($$);
}
- | LEFT_RIGHT
- {
- if (current_class_name)
- pedwarn ("anachronistic old style base class initializer");
- $$ = expand_member_init (current_class_ref,
- NULL_TREE,
- void_type_node);
- }
- | notype_identifier '(' nonnull_exprlist ')'
- { $$ = expand_member_init (current_class_ref, $1, $3); }
- | notype_identifier LEFT_RIGHT
- { $$ = 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, $1, $3); }
- | typename_sub LEFT_RIGHT
- { $$ = expand_member_init (current_class_ref, $1,
- void_type_node); }
+ | notype_identifier
+ { $$ = expand_member_init ($1);
+ in_base_initializer = $$ && !DECL_P ($$); }
+ | nonnested_type
+ { $$ = expand_member_init ($1);
+ in_base_initializer = $$ && !DECL_P ($$); }
+ | typename_sub
+ { $$ = expand_member_init ($1);
+ in_base_initializer = $$ && !DECL_P ($$); }
+ ;
+
+member_init:
+ begin_member_init '(' nonnull_exprlist ')'
+ { in_base_initializer = 0;
+ $$ = $1 ? build_tree_list ($1, $3) : NULL_TREE; }
+ | begin_member_init LEFT_RIGHT
+ { in_base_initializer = 0;
+ $$ = $1 ? build_tree_list ($1, void_type_node) : NULL_TREE; }
| error
- { $$ = NULL_TREE; }
+ { in_base_initializer = 0;
+ $$ = NULL_TREE; }
;
identifier:
@@ -1002,7 +1017,7 @@ identifier:
notype_identifier:
IDENTIFIER
- | PTYPENAME
+ | PTYPENAME
| NSNAME %prec EMPTY
;
@@ -1019,40 +1034,40 @@ explicit_instantiation:
end_explicit_instantiation
| TEMPLATE begin_explicit_instantiation typed_declspecs declarator
{ tree specs = strip_attrs ($3.t);
- do_decl_instantiation (specs, $4, NULL_TREE); }
+ parse_decl_instantiation (specs, $4, NULL_TREE); }
end_explicit_instantiation
| TEMPLATE begin_explicit_instantiation notype_declarator
- { do_decl_instantiation (NULL_TREE, $3, NULL_TREE); }
+ { parse_decl_instantiation (NULL_TREE, $3, NULL_TREE); }
end_explicit_instantiation
| TEMPLATE begin_explicit_instantiation constructor_declarator
- { do_decl_instantiation (NULL_TREE, $3, NULL_TREE); }
+ { parse_decl_instantiation (NULL_TREE, $3, NULL_TREE); }
end_explicit_instantiation
| SCSPEC TEMPLATE begin_explicit_instantiation typespec ';'
{ do_type_instantiation ($4.t, $1, 1);
yyungetc (';', 1); }
end_explicit_instantiation
{}
- | SCSPEC TEMPLATE begin_explicit_instantiation typed_declspecs
+ | SCSPEC TEMPLATE begin_explicit_instantiation typed_declspecs
declarator
{ tree specs = strip_attrs ($4.t);
- do_decl_instantiation (specs, $5, $1); }
+ parse_decl_instantiation (specs, $5, $1); }
end_explicit_instantiation
{}
| SCSPEC TEMPLATE begin_explicit_instantiation notype_declarator
- { do_decl_instantiation (NULL_TREE, $4, $1); }
+ { parse_decl_instantiation (NULL_TREE, $4, $1); }
end_explicit_instantiation
{}
| SCSPEC TEMPLATE begin_explicit_instantiation constructor_declarator
- { do_decl_instantiation (NULL_TREE, $4, $1); }
+ { parse_decl_instantiation (NULL_TREE, $4, $1); }
end_explicit_instantiation
{}
;
-begin_explicit_instantiation:
+begin_explicit_instantiation:
{ begin_explicit_instantiation(); }
;
-end_explicit_instantiation:
+end_explicit_instantiation:
{ end_explicit_instantiation(); }
;
@@ -1062,10 +1077,10 @@ end_explicit_instantiation:
template_type:
PTYPENAME '<' template_arg_list_opt template_close_bracket
- .finish_template_type
+ finish_template_type_
{ $$ = $5; }
| tTYPENAME '<' template_arg_list_opt template_close_bracket
- .finish_template_type
+ finish_template_type_
{ $$ = $5; }
| self_template_type
;
@@ -1073,29 +1088,29 @@ template_type:
apparent_template_type:
template_type
| identifier '<' template_arg_list_opt '>'
- .finish_template_type
+ finish_template_type_
{ $$ = $5; }
;
self_template_type:
SELFNAME '<' template_arg_list_opt template_close_bracket
- .finish_template_type
+ finish_template_type_
{ $$ = $5; }
;
-.finish_template_type:
- {
+finish_template_type_:
+ {
if (yychar == YYEMPTY)
yychar = YYLEX;
- $$ = finish_template_type ($<ttype>-3, $<ttype>-1,
+ $$ = finish_template_type ($<ttype>-3, $<ttype>-1,
yychar == SCOPE);
}
;
template_close_bracket:
'>'
- | RSHIFT
+ | RSHIFT
{
/* Handle `Class<Class<Type>>' without space in the `>>' */
pedwarn ("`>>' should be `> >' in template class name");
@@ -1140,7 +1155,7 @@ template_arg:
$$ = error_mark_node;
}
else
- $$ = make_unbound_class_template ($1, $3, 1);
+ $$ = make_unbound_class_template ($1, $3, tf_error | tf_parsing);
}
;
@@ -1206,11 +1221,11 @@ condition:
$<ttype>$ = parse_decl ($<ttype>2, $4, 1);
}
init
- {
+ {
parse_end_decl ($<ttype>6, $7, $4);
- $$ = convert_from_reference ($<ttype>6);
+ $$ = convert_from_reference ($<ttype>6);
if (TREE_CODE (TREE_TYPE ($$)) == ARRAY_TYPE)
- error ("definition of array `%#D' in condition", $$);
+ error ("definition of array `%#D' in condition", $$);
}
| expr
;
@@ -1224,10 +1239,10 @@ compstmtend:
nontrivial_exprlist:
expr_no_commas ',' expr_no_commas
- { $$ = tree_cons (NULL_TREE, $$,
+ { $$ = tree_cons (NULL_TREE, $$,
build_tree_list (NULL_TREE, $3)); }
| expr_no_commas ',' error
- { $$ = tree_cons (NULL_TREE, $$,
+ { $$ = tree_cons (NULL_TREE, $$,
build_tree_list (NULL_TREE, error_mark_node)); }
| nontrivial_exprlist ',' expr_no_commas
{ chainon ($$, build_tree_list (NULL_TREE, $3)); }
@@ -1270,37 +1285,37 @@ unary_expr:
{ $$ = finish_alignof ($2);
skip_evaluation--; }
| alignof '(' type_id ')' %prec HYPERUNARY
- { $$ = finish_alignof (groktypename ($3.t));
+ { $$ = finish_alignof (groktypename ($3.t));
check_for_new_type ("alignof", $3);
skip_evaluation--; }
/* 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.t, NULL_TREE, $1);
+ { $$ = 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.t, $3, $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);
+ { $$ = 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.t, $4, $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);
+ NULL_TREE, $1);
check_for_new_type ("new", $3); }
| new '(' type_id ')' new_initializer
- { $$ = build_new (NULL_TREE, groktypename($3.t), $5, $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);
+ { $$ = 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.t), $6, $1);
+ { $$ = build_new ($2, groktypename($4.t), $6, $1);
check_for_new_type ("new", $4); }
| delete cast_expr %prec UNARY
@@ -1337,21 +1352,12 @@ new_initializer:
error ("`%T' is not a valid expression", $2.t);
$$ = error_mark_node;
}
- /* GNU extension so people can use initializer lists. Note that
- this alters the meaning of `new int = 1', which was previously
- syntactically valid but semantically invalid.
- This feature is now deprecated and will be removed in a future
- release. */
| '=' init
{
- if (pedantic)
- pedwarn ("ISO C++ forbids initialization of new expression with `='");
- cp_deprecated ("new initializer lists extension");
- if (TREE_CODE ($2) != TREE_LIST
- && TREE_CODE ($2) != CONSTRUCTOR)
- $$ = build_tree_list (NULL_TREE, $2);
- else
- $$ = $2;
+ /* This was previously allowed as an extension, but
+ was removed in G++ 3.3. */
+ error ("initialization of new expression with `='");
+ $$ = error_mark_node;
}
;
@@ -1362,7 +1368,7 @@ regcast_or_absdcl:
$$ = make_call_declarator (NULL_TREE, $2.t, NULL_TREE, NULL_TREE);
check_for_new_type ("cast", $2); }
| regcast_or_absdcl '(' type_id ')' %prec EMPTY
- { $3.t = finish_parmlist (build_tree_list (NULL_TREE, $3.t), 0);
+ { $3.t = finish_parmlist (build_tree_list (NULL_TREE, $3.t), 0);
$$ = make_call_declarator ($$, $3.t, NULL_TREE, NULL_TREE);
check_for_new_type ("cast", $3); }
;
@@ -1372,9 +1378,9 @@ cast_expr:
| regcast_or_absdcl unary_expr %prec UNARY
{ $$ = reparse_absdcl_as_casts ($$, $2); }
| regcast_or_absdcl '{' initlist maybecomma '}' %prec UNARY
- {
+ {
tree init = build_nt (CONSTRUCTOR, NULL_TREE,
- nreverse ($3));
+ nreverse ($3));
if (pedantic)
pedwarn ("ISO C++ forbids compound literals");
/* Indicate that this was a C99 compound literal. */
@@ -1506,11 +1512,11 @@ notype_unqualified_id:
do_id:
{
- /* If lastiddecl is a TREE_LIST, it's a baselink, which
- means that we're in an expression like S::f<int>, so
- don't do_identifier; we only do that for unqualified
+ /* If lastiddecl is a BASELINK we're in an
+ expression like S::f<int>, so don't
+ do_identifier; we only do that for unqualified
identifiers. */
- if (!lastiddecl || TREE_CODE (lastiddecl) != TREE_LIST)
+ if (!lastiddecl || !BASELINK_P (lastiddecl))
$$ = do_identifier ($<ttype>-1, 3, NULL_TREE);
else
$$ = $<ttype>-1;
@@ -1518,10 +1524,20 @@ do_id:
;
template_id:
- PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
- { $$ = lookup_template_function ($3, $4); }
+ PFUNCNAME '<' do_id template_arg_list_opt template_close_bracket
+ {
+ tree template_name = $3;
+ if (TREE_CODE (template_name) == COMPONENT_REF)
+ template_name = TREE_OPERAND (template_name, 1);
+ $$ = lookup_template_function (template_name, $4);
+ }
| operator_name '<' do_id template_arg_list_opt template_close_bracket
- { $$ = lookup_template_function ($3, $4); }
+ {
+ tree template_name = $3;
+ if (TREE_CODE (template_name) == COMPONENT_REF)
+ template_name = TREE_OPERAND (template_name, 1);
+ $$ = lookup_template_function (template_name, $4);
+ }
;
object_template_id:
@@ -1529,7 +1545,7 @@ object_template_id:
{ $$ = lookup_template_function ($2, $4); }
| TEMPLATE PFUNCNAME '<' template_arg_list_opt template_close_bracket
{ $$ = lookup_template_function ($2, $4); }
- | TEMPLATE operator_name '<' template_arg_list_opt
+ | TEMPLATE operator_name '<' template_arg_list_opt
template_close_bracket
{ $$ = lookup_template_function ($2, $4); }
;
@@ -1566,7 +1582,7 @@ notype_template_declarator:
| NSNAME '<' template_arg_list template_close_bracket
{ $$ = lookup_template_function ($1, $3); }
;
-
+
direct_notype_declarator:
complex_direct_notype_declarator
/* This precedence declaration is to prefer this reduce
@@ -1582,15 +1598,15 @@ primary:
{
if (TREE_CODE ($1) == BIT_NOT_EXPR)
$$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($1, 0));
- else
+ else
$$ = finish_id_expr ($1);
- }
+ }
| CONSTANT
- | boolean.literal
- | string
+ | boolean_literal
+ | STRING
{
- $$ = combine_strings ($$);
- /* combine_strings doesn't set up TYPE_MAIN_VARIANT of
+ $$ = fix_string_type ($$);
+ /* fix_string_type doesn't set up TYPE_MAIN_VARIANT of
a const array the way we want, so fix it. */
if (flag_const_strings)
TREE_TYPE ($$) = build_cplus_array_type
@@ -1598,11 +1614,7 @@ primary:
TYPE_DOMAIN (TREE_TYPE ($$)));
}
| VAR_FUNC_NAME
- {
- $$ = fname_decl (C_RID_CODE ($$), $$);
- if (processing_template_decl)
- $$ = build_min_nt (LOOKUP_EXPR, DECL_NAME ($$));
- }
+ { $$ = finish_fname ($1); }
| '(' expr ')'
{ $$ = finish_parenthesized_expr ($2); }
| '(' expr_or_declarator_intern ')'
@@ -1611,15 +1623,14 @@ primary:
| '(' error ')'
{ $$ = error_mark_node; }
| '('
- { tree scope = current_scope ();
- if (!scope || TREE_CODE (scope) != FUNCTION_DECL)
+ { if (!at_function_scope_p ())
{
error ("braced-group within expression allowed only inside a function");
YYERROR;
}
if (pedantic)
- pedwarn ("ISO C++ forbids braced-groups within expressions");
- $<ttype>$ = begin_stmt_expr ();
+ pedwarn ("ISO C++ forbids braced-groups within expressions");
+ $<ttype>$ = begin_stmt_expr ();
}
compstmt_or_stmtexpr ')'
{ $$ = finish_stmt_expr ($<ttype>2); }
@@ -1627,13 +1638,13 @@ primary:
We could store lastiddecl in $1 to avoid another lookup,
but that would result in many additional reduce/reduce conflicts. */
| notype_unqualified_id '(' nonnull_exprlist ')'
- { $$ = finish_call_expr ($1, $3, 1); }
+ { $$ = parse_finish_call_expr ($1, $3, 1); }
| notype_unqualified_id LEFT_RIGHT
- { $$ = finish_call_expr ($1, NULL_TREE, 1); }
+ { $$ = parse_finish_call_expr ($1, NULL_TREE, 1); }
| primary '(' nonnull_exprlist ')'
- { $$ = finish_call_expr ($1, $3, 0); }
+ { $$ = parse_finish_call_expr ($1, $3, 0); }
| primary LEFT_RIGHT
- { $$ = finish_call_expr ($1, NULL_TREE, 0); }
+ { $$ = parse_finish_call_expr ($1, NULL_TREE, 0); }
| VA_ARG '(' expr_no_commas ',' type_id ')'
{ $$ = build_x_va_arg ($3, groktypename ($5.t));
check_for_new_type ("__builtin_va_arg", $5); }
@@ -1681,38 +1692,33 @@ primary:
check_for_new_type ("typeid", $3);
$$ = get_typeid (type); }
| global_scope IDENTIFIER
- { $$ = do_scoped_id ($2, 1); }
+ { $$ = parse_scoped_id ($2); }
| global_scope template_id
{ $$ = $2; }
| global_scope operator_name
{
got_scope = NULL_TREE;
if (TREE_CODE ($2) == IDENTIFIER_NODE)
- $$ = do_scoped_id ($2, 1);
+ $$ = parse_scoped_id ($2);
else
$$ = $2;
}
| overqualified_id %prec HYPERUNARY
{ $$ = build_offset_ref (OP0 ($$), OP1 ($$)); }
| overqualified_id '(' nonnull_exprlist ')'
- { $$ = finish_qualified_call_expr ($1, $3); }
+ { $$ = parse_finish_call_expr ($1, $3, 0); }
| overqualified_id LEFT_RIGHT
- { $$ = finish_qualified_call_expr ($1, NULL_TREE); }
+ { $$ = parse_finish_call_expr ($1, NULL_TREE, 0); }
| object object_template_id %prec UNARY
- {
- $$ = build_x_component_ref ($$, $2, NULL_TREE, 1);
- }
+ { $$ = finish_class_member_access_expr ($$, $2); }
| object object_template_id '(' nonnull_exprlist ')'
{ $$ = finish_object_call_expr ($2, $1, $4); }
| object object_template_id LEFT_RIGHT
{ $$ = finish_object_call_expr ($2, $1, NULL_TREE); }
| object unqualified_id %prec UNARY
- { $$ = build_x_component_ref ($$, $2, NULL_TREE, 1); }
+ { $$ = finish_class_member_access_expr ($$, $2); }
| object overqualified_id %prec UNARY
- { if (processing_template_decl)
- $$ = build_min_nt (COMPONENT_REF, $1, $2);
- else
- $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
+ { $$ = finish_class_member_access_expr ($1, $2); }
| object unqualified_id '(' nonnull_exprlist ')'
{ $$ = finish_object_call_expr ($2, $1, $4); }
| object unqualified_id LEFT_RIGHT
@@ -1784,20 +1790,13 @@ delete:
{ got_scope = NULL_TREE; $$ = 1; }
;
-boolean.literal:
+boolean_literal:
CXX_TRUE
{ $$ = boolean_true_node; }
| CXX_FALSE
{ $$ = boolean_false_node; }
;
-/* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */
-string:
- STRING
- | string STRING
- { $$ = chainon ($$, $2); }
- ;
-
nodecls:
/* empty */
{
@@ -1811,7 +1810,7 @@ object:
{ got_object = TREE_TYPE ($$); }
| primary POINTSAT
{
- $$ = build_x_arrow ($$);
+ $$ = build_x_arrow ($$);
got_object = TREE_TYPE ($$);
}
;
@@ -1860,20 +1859,20 @@ fcast_or_absdcl:
/* ISO type-id (8.1) */
type_id:
typed_typespecs absdcl
- { $$.t = build_tree_list ($1.t, $2);
+ { $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| nonempty_cv_qualifiers absdcl
- { $$.t = build_tree_list ($1.t, $2);
+ { $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| typespec absdcl
{ $$.t = build_tree_list (build_tree_list (NULL_TREE, $1.t),
- $2);
+ $2);
$$.new_type_flag = $1.new_type_flag; }
| typed_typespecs %prec EMPTY
{ $$.t = build_tree_list ($1.t, NULL_TREE);
$$.new_type_flag = $1.new_type_flag; }
| nonempty_cv_qualifiers %prec EMPTY
- { $$.t = build_tree_list ($1.t, NULL_TREE);
+ { $$.t = build_tree_list ($1.t, NULL_TREE);
$$.new_type_flag = $1.new_type_flag; }
;
@@ -1891,23 +1890,23 @@ typed_declspecs:
typed_declspecs1:
declmods typespec
- { $$.t = tree_cons (NULL_TREE, $2.t, $1.t);
+ { $$.t = tree_cons (NULL_TREE, $2.t, $1.t);
$$.new_type_flag = $2.new_type_flag; }
| typespec reserved_declspecs %prec HYPERUNARY
- { $$.t = tree_cons (NULL_TREE, $1.t, $2);
+ { $$.t = tree_cons (NULL_TREE, $1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| typespec reserved_typespecquals reserved_declspecs
- { $$.t = tree_cons (NULL_TREE, $1.t, chainon ($2, $3));
+ { $$.t = tree_cons (NULL_TREE, $1.t, chainon ($2, $3));
$$.new_type_flag = $1.new_type_flag; }
| declmods typespec reserved_declspecs
- { $$.t = tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
+ { $$.t = tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
$$.new_type_flag = $2.new_type_flag; }
| declmods typespec reserved_typespecquals
- { $$.t = tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
+ { $$.t = tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
$$.new_type_flag = $2.new_type_flag; }
| declmods typespec reserved_typespecquals reserved_declspecs
{ $$.t = tree_cons (NULL_TREE, $2.t,
- chainon ($3, chainon ($4, $1.t)));
+ chainon ($3, chainon ($4, $1.t)));
$$.new_type_flag = $2.new_type_flag; }
;
@@ -1973,16 +1972,16 @@ declmods:
typed_typespecs:
typespec %prec EMPTY
- { $$.t = build_tree_list (NULL_TREE, $1.t);
+ { $$.t = build_tree_list (NULL_TREE, $1.t);
$$.new_type_flag = $1.new_type_flag; }
| nonempty_cv_qualifiers typespec
- { $$.t = tree_cons (NULL_TREE, $2.t, $1.t);
+ { $$.t = tree_cons (NULL_TREE, $2.t, $1.t);
$$.new_type_flag = $2.new_type_flag; }
| typespec reserved_typespecquals
- { $$.t = tree_cons (NULL_TREE, $1.t, $2);
+ { $$.t = tree_cons (NULL_TREE, $1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| nonempty_cv_qualifiers typespec reserved_typespecquals
- { $$.t = tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
+ { $$.t = tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
$$.new_type_flag = $2.new_type_flag; }
;
@@ -2091,8 +2090,8 @@ nomods_initdecls:
maybeasm:
/* empty */
{ $$ = NULL_TREE; }
- | asm_keyword '(' string ')'
- { if (TREE_CHAIN ($3)) $3 = combine_strings ($3); $$ = $3; }
+ | asm_keyword '(' STRING ')'
+ { $$ = $3; }
;
initdcl:
@@ -2119,7 +2118,7 @@ initdcl0_innards:
{ $<ttype>$ = parse_decl0 ($<ttype>-1, $<ftype>-2.t,
$<ftype>-2.lookups, $1, 1); }
/* Note how the declaration of the variable is in effect
- while its init is parsed! */
+ while its init is parsed! */
init
{ parse_end_decl ($<ttype>3, $4, $<ttype>0); }
| maybe_attribute
@@ -2127,7 +2126,7 @@ initdcl0_innards:
$<ftype>-2.lookups, $1, 0);
parse_end_decl (d, NULL_TREE, $<ttype>0); }
;
-
+
initdcl0:
declarator maybeasm initdcl0_innards
{}
@@ -2137,15 +2136,15 @@ notype_initdcl0:
notype_declarator maybeasm initdcl0_innards
{}
;
-
+
nomods_initdcl0:
notype_declarator maybeasm
{ /* Set things up as initdcl0_innards expects. */
$<ttype>$ = $2;
- $2 = $1;
+ $2 = $1;
$<ftype>1.t = NULL_TREE;
$<ftype>1.lookups = NULL_TREE; }
- initdcl0_innards
+ initdcl0_innards
{}
| constructor_declarator maybeasm maybe_attribute
{ tree d = parse_decl0 ($1, NULL_TREE, NULL_TREE, $3, 0);
@@ -2160,7 +2159,7 @@ maybe_attribute:
| attributes
{ $$ = $1; }
;
-
+
attributes:
attribute
{ $$ = $1; }
@@ -2179,7 +2178,7 @@ attribute_list:
| attribute_list ',' attrib
{ $$ = chainon ($1, $3); }
;
-
+
attrib:
/* empty */
{ $$ = NULL_TREE; }
@@ -2259,13 +2258,13 @@ pending_inline:
process_next_inline ($1);
}
| PRE_PARSED_FUNCTION_DECL maybe_return_init function_try_block
- {
- expand_body (finish_function (2));
+ {
+ expand_body (finish_function (2));
process_next_inline ($1);
}
| PRE_PARSED_FUNCTION_DECL maybe_return_init error
- {
- finish_function (2);
+ {
+ finish_function (2);
process_next_inline ($1); }
;
@@ -2311,14 +2310,14 @@ structsp:
current_enum_type = $<ttype>3;
check_for_missing_semicolon ($$.t); }
| ENUM identifier
- { $$.t = xref_tag (enum_type_node, $2, 1);
+ { $$.t = parse_xref_tag (enum_type_node, $2, 1);
$$.new_type_flag = 0; }
| ENUM complex_type_name
- { $$.t = xref_tag (enum_type_node, $2, 1);
+ { $$.t = parse_xref_tag (enum_type_node, $2, 1);
$$.new_type_flag = 0; }
| TYPENAME_KEYWORD typename_sub
{ $$.t = $2;
- $$.new_type_flag = 0;
+ $$.new_type_flag = 0;
if (!processing_template_decl)
pedwarn ("using `typename' outside of template"); }
/* C++ extensions, merged with C to avoid shift/reduce conflicts */
@@ -2327,20 +2326,28 @@ structsp:
if ($2 && $1.t != error_mark_node)
{
tree type = TREE_TYPE ($1.t);
-
+
if (TREE_CODE (type) == TYPENAME_TYPE)
- /* In a definition of a member class template,
- we will get here with an implicit typename,
- a TYPENAME_TYPE with a type. */
- type = TREE_TYPE (type);
+ {
+ if (IMPLICIT_TYPENAME_P (type))
+ /* In a definition of a member class template,
+ we will get here with an implicit typename,
+ a TYPENAME_TYPE with a type. */
+ type = TREE_TYPE (type);
+ else
+ {
+ error ("qualified name does not name a class");
+ type = error_mark_node;
+ }
+ }
maybe_process_partial_specialization (type);
- xref_basetypes (current_aggr, $1.t, type, $2);
+ xref_basetypes (type, $2);
}
- $1.t = begin_class_definition (TREE_TYPE ($1.t));
+ $1.t = begin_class_definition (TREE_TYPE ($1.t));
check_class_key (current_aggr, $1.t);
current_aggr = NULL_TREE; }
opt.component_decl_list '}' maybe_attribute
- {
+ {
int semi;
tree t;
@@ -2364,9 +2371,8 @@ structsp:
}
pending_inlines
{
- finish_inline_definitions ();
$$.t = $<ttype>8;
- $$.new_type_flag = 1;
+ $$.new_type_flag = 1;
}
| class_head_decl
{
@@ -2427,18 +2433,18 @@ class_head:
class_head_apparent_template:
aggr apparent_template_type
- {
- current_aggr = $1;
+ {
+ current_aggr = $1;
$$ = $2;
}
| aggr nested_name_specifier apparent_template_type
- {
- current_aggr = $1;
+ {
+ current_aggr = $1;
$$ = $3;
}
| aggr global_scope nested_name_specifier apparent_template_type
- {
- current_aggr = $1;
+ {
+ current_aggr = $1;
$$ = $4;
}
;
@@ -2446,14 +2452,15 @@ class_head_apparent_template:
class_head_decl:
class_head %prec EMPTY
{
- $$.t = handle_class_head (current_aggr,
- TREE_PURPOSE ($1), TREE_VALUE ($1),
- 0, &$$.new_type_flag);
+ $$.t = parse_handle_class_head (current_aggr,
+ TREE_PURPOSE ($1),
+ TREE_VALUE ($1),
+ 0, &$$.new_type_flag);
}
| aggr identifier_defn %prec EMPTY
{
current_aggr = $1;
- $$.t = TYPE_MAIN_DECL (xref_tag (current_aggr, $2, 0));
+ $$.t = TYPE_MAIN_DECL (parse_xref_tag (current_aggr, $2, 0));
$$.new_type_flag = 1;
}
| class_head_apparent_template %prec EMPTY
@@ -2467,59 +2474,54 @@ class_head_defn:
class_head '{'
{
yyungetc ('{', 1);
- $$.t = handle_class_head (current_aggr,
- TREE_PURPOSE ($1), TREE_VALUE ($1),
- 1, &$$.new_type_flag);
+ $$.t = parse_handle_class_head (current_aggr,
+ TREE_PURPOSE ($1),
+ TREE_VALUE ($1),
+ 1,
+ &$$.new_type_flag);
}
| class_head ':'
{
yyungetc (':', 1);
- $$.t = handle_class_head (current_aggr,
- TREE_PURPOSE ($1), TREE_VALUE ($1),
- 1, &$$.new_type_flag);
+ $$.t = parse_handle_class_head (current_aggr,
+ TREE_PURPOSE ($1),
+ TREE_VALUE ($1),
+ 1, &$$.new_type_flag);
}
| class_head_apparent_template '{'
{
yyungetc ('{', 1);
- $$.t = $1;
- $$.new_type_flag = 0;
- if (TREE_CODE (TREE_TYPE ($1)) == RECORD_TYPE)
- /* We might be specializing a template with a different
- class-key. */
- CLASSTYPE_DECLARED_CLASS (TREE_TYPE ($1))
- = (current_aggr == class_type_node);
+ $$.t = handle_class_head_apparent_template
+ ($1, &$$.new_type_flag);
}
| class_head_apparent_template ':'
{
yyungetc (':', 1);
- $$.t = $1;
- $$.new_type_flag = 0;
- if (TREE_CODE (TREE_TYPE ($1)) == RECORD_TYPE)
- /* We might be specializing a template with a different
- class-key. */
- CLASSTYPE_DECLARED_CLASS (TREE_TYPE ($1))
- = (current_aggr == class_type_node);
+ $$.t = handle_class_head_apparent_template
+ ($1, &$$.new_type_flag);
}
| aggr identifier_defn '{'
{
yyungetc ('{', 1);
current_aggr = $1;
- $$.t = handle_class_head (current_aggr,
- NULL_TREE, $2,
- 1, &$$.new_type_flag);
+ $$.t = parse_handle_class_head (current_aggr,
+ NULL_TREE, $2,
+ 1, &$$.new_type_flag);
}
| aggr identifier_defn ':'
{
yyungetc (':', 1);
current_aggr = $1;
- $$.t = handle_class_head (current_aggr,
- NULL_TREE, $2,
- 1, &$$.new_type_flag);
+ $$.t = parse_handle_class_head (current_aggr,
+ NULL_TREE, $2,
+ 1, &$$.new_type_flag);
}
| aggr '{'
{
current_aggr = $1;
- $$.t = TYPE_MAIN_DECL (xref_tag ($1, make_anon_name (), 0));
+ $$.t = TYPE_MAIN_DECL (parse_xref_tag ($1,
+ make_anon_name (),
+ 0));
$$.new_type_flag = 0;
CLASSTYPE_DECLARED_CLASS (TREE_TYPE ($$.t))
= $1 == class_type_node;
@@ -2544,13 +2546,13 @@ base_class_list:
;
base_class:
- base_class.1
+ base_class_1
{ $$ = finish_base_specifier (access_default_node, $1); }
- | base_class_access_list see_typename base_class.1
+ | base_class_access_list see_typename base_class_1
{ $$ = finish_base_specifier ($1, $3); }
;
-base_class.1:
+base_class_1:
typename_sub
{ if (!TYPE_P ($$))
$$ = error_mark_node; }
@@ -2592,7 +2594,7 @@ base_class_access_list:
opt.component_decl_list:
| component_decl_list
| opt.component_decl_list access_specifier component_decl_list
- | opt.component_decl_list access_specifier
+ | opt.component_decl_list access_specifier
;
access_specifier:
@@ -2606,13 +2608,13 @@ access_specifier:
ARM $9.2 says that the semicolon is optional, and therefore allowed. */
component_decl_list:
component_decl
- {
+ {
finish_member_declaration ($1);
current_aggr = NULL_TREE;
reset_type_access_control ();
}
| component_decl_list component_decl
- {
+ {
finish_member_declaration ($2);
current_aggr = NULL_TREE;
reset_type_access_control ();
@@ -2626,13 +2628,13 @@ component_decl:
yyungetc ('}', 0); }
/* C++: handle constructors, destructors and inline functions */
/* note that INLINE is like a TYPESPEC */
- | fn.def2 ':' /* base_init compstmt */
+ | fn_def2 ':' /* base_init compstmt */
{ $$ = finish_method ($$); }
- | fn.def2 TRY /* base_init compstmt */
+ | fn_def2 TRY /* base_init compstmt */
{ $$ = finish_method ($$); }
- | fn.def2 RETURN_KEYWORD /* base_init compstmt */
+ | fn_def2 RETURN_KEYWORD /* base_init compstmt */
{ $$ = finish_method ($$); }
- | fn.def2 '{' /* nodecls compstmt */
+ | fn_def2 '{' /* nodecls compstmt */
{ $$ = finish_method ($$); }
| ';'
{ $$ = NULL_TREE; }
@@ -2640,7 +2642,7 @@ component_decl:
{ $$ = $2;
pedantic = $1; }
| template_header component_decl
- {
+ {
if ($2)
$$ = finish_member_template_decl ($2);
else
@@ -2650,8 +2652,8 @@ component_decl:
finish_template_decl ($1);
}
| template_header typed_declspecs ';'
- {
- $$ = finish_member_class_template ($2.t);
+ {
+ $$ = finish_member_class_template ($2.t);
finish_template_decl ($1);
}
| bad_decl
@@ -2684,10 +2686,10 @@ component_decl_1:
$$ = NULL_TREE;
}
| declmods notype_components
- {
+ {
if (!$2)
grok_x_components ($1.t);
- $$ = NULL_TREE;
+ $$ = NULL_TREE;
}
| notype_declarator maybeasm maybe_attribute maybe_init
{ $$ = grokfield ($$, NULL_TREE, $4, $2, $3); }
@@ -2723,14 +2725,14 @@ components:
/* empty: possibly anonymous */
{ $$ = 0; }
| component_declarator0
- {
+ {
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
$1 = finish_member_template_decl ($1);
- finish_member_declaration ($1);
+ finish_member_declaration ($1);
$$ = 1;
}
| components ',' component_declarator
- {
+ {
check_multiple_declarators ();
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
$3 = finish_member_template_decl ($3);
@@ -2743,18 +2745,18 @@ notype_components:
/* empty: possibly anonymous */
{ $$ = 0; }
| notype_component_declarator0
- {
+ {
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
$1 = finish_member_template_decl ($1);
finish_member_declaration ($1);
$$ = 1;
}
| notype_components ',' notype_component_declarator
- {
+ {
check_multiple_declarators ();
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
$3 = finish_member_template_decl ($3);
- finish_member_declaration ($3);
+ finish_member_declaration ($3);
$$ = 2;
}
;
@@ -2833,10 +2835,10 @@ enumerator:
/* ISO new-type-id (5.3.4) */
new_type_id:
type_specifier_seq new_declarator
- { $$.t = build_tree_list ($1.t, $2);
+ { $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| type_specifier_seq %prec EMPTY
- { $$.t = build_tree_list ($1.t, NULL_TREE);
+ { $$.t = build_tree_list ($1.t, NULL_TREE);
$$.new_type_flag = $1.new_type_flag; }
/* GNU extension to allow arrays of arbitrary types with
non-constant dimension. */
@@ -2862,13 +2864,13 @@ nonempty_cv_qualifiers:
{ $$.t = hash_tree_cons (NULL_TREE, $1, NULL_TREE);
$$.new_type_flag = 0; }
| nonempty_cv_qualifiers CV_QUALIFIER
- { $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
+ { $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
$$.new_type_flag = $1.new_type_flag; }
| attributes %prec EMPTY
- { $$.t = hash_tree_cons ($1, NULL_TREE, NULL_TREE);
+ { $$.t = hash_tree_cons ($1, NULL_TREE, NULL_TREE);
$$.new_type_flag = 0; }
| nonempty_cv_qualifiers attributes %prec EMPTY
- { $$.t = hash_tree_cons ($2, NULL_TREE, $1.t);
+ { $$.t = hash_tree_cons ($2, NULL_TREE, $1.t);
$$.new_type_flag = $1.new_type_flag; }
;
@@ -2977,7 +2979,7 @@ notype_declarator_intern:
$$ = tree_cons ($1, $2, NULL_TREE);
}
;
-
+
notype_declarator:
'*' nonempty_cv_qualifiers notype_declarator_intern %prec UNARY
{ $$ = make_pointer_declarator ($2.t, $3); }
@@ -3025,7 +3027,7 @@ complex_direct_notype_declarator:
{ enter_scope_of ($2); $$ = $2;}
| global_scope notype_unqualified_id
{ $$ = build_nt (SCOPE_REF, global_namespace, $2);
- enter_scope_of ($$);
+ enter_scope_of ($$);
}
| nested_name_specifier notype_template_declarator
{ got_scope = NULL_TREE;
@@ -3078,15 +3080,15 @@ nested_name_specifier:
| nested_name_specifier nested_name_specifier_1
{ $$ = $2; }
| nested_name_specifier TEMPLATE explicit_template_type SCOPE
- { got_scope = $$
- = make_typename_type ($1, $3, tf_error); }
+ { got_scope = $$
+ = make_typename_type ($1, $3, tf_error | tf_parsing); }
/* Error handling per Core 125. */
| nested_name_specifier IDENTIFIER SCOPE
- { got_scope = $$
- = make_typename_type ($1, $2, tf_error); }
+ { got_scope = $$
+ = make_typename_type ($1, $2, tf_error | tf_parsing); }
| nested_name_specifier PTYPENAME SCOPE
- { got_scope = $$
- = make_typename_type ($1, $2, tf_error); }
+ { got_scope = $$
+ = make_typename_type ($1, $2, tf_error | tf_parsing); }
;
/* Why the @#$%^& do type_name and notype_identifier need to be expanded
@@ -3128,7 +3130,7 @@ typename_sub0:
typename_sub1 identifier %prec EMPTY
{
if (TYPE_P ($1))
- $$ = make_typename_type ($1, $2, tf_error);
+ $$ = make_typename_type ($1, $2, tf_error | tf_parsing);
else if (TREE_CODE ($2) == IDENTIFIER_NODE)
error ("`%T' is not a class or namespace", $2);
else
@@ -3141,9 +3143,9 @@ typename_sub0:
| typename_sub1 template_type %prec EMPTY
{ $$ = TREE_TYPE ($2); }
| typename_sub1 explicit_template_type %prec EMPTY
- { $$ = make_typename_type ($1, $2, tf_error); }
+ { $$ = make_typename_type ($1, $2, tf_error | tf_parsing); }
| typename_sub1 TEMPLATE explicit_template_type %prec EMPTY
- { $$ = make_typename_type ($1, $3, tf_error); }
+ { $$ = make_typename_type ($1, $3, tf_error | tf_parsing); }
;
typename_sub1:
@@ -3157,7 +3159,7 @@ typename_sub1:
| typename_sub1 typename_sub2
{
if (TYPE_P ($1))
- $$ = make_typename_type ($1, $2, tf_error);
+ $$ = make_typename_type ($1, $2, tf_error | tf_parsing);
else if (TREE_CODE ($2) == IDENTIFIER_NODE)
error ("`%T' is not a class or namespace", $2);
else
@@ -3168,11 +3170,11 @@ typename_sub1:
}
}
| typename_sub1 explicit_template_type SCOPE
- { got_scope = $$
- = make_typename_type ($1, $2, tf_error); }
+ { got_scope = $$
+ = make_typename_type ($1, $2, tf_error | tf_parsing); }
| typename_sub1 TEMPLATE explicit_template_type SCOPE
- { got_scope = $$
- = make_typename_type ($1, $3, tf_error); }
+ { got_scope = $$
+ = make_typename_type ($1, $3, tf_error | tf_parsing); }
;
/* This needs to return a TYPE_DECL for simple names so that we don't
@@ -3279,7 +3281,7 @@ absdcl_intern:
$$ = tree_cons ($1, $2, NULL_TREE);
}
;
-
+
/* ISO abstract-declarator (8.1) */
absdcl:
'*' nonempty_cv_qualifiers absdcl_intern
@@ -3365,7 +3367,7 @@ label_decls:
label_decl:
LABEL identifiers_or_typenames ';'
- {
+ {
while ($2)
{
finish_label_decl (TREE_VALUE ($2));
@@ -3377,7 +3379,7 @@ label_decl:
compstmt_or_stmtexpr:
save_lineno '{'
{ $<ttype>$ = begin_compound_stmt (0); }
- compstmtend
+ compstmtend
{ STMT_LINENO ($<ttype>3) = $1;
finish_compound_stmt (0, $<ttype>3); }
;
@@ -3400,9 +3402,9 @@ simple_if:
implicitly_scoped_stmt:
compstmt
- |
+ |
{ $<ttype>$ = begin_compound_stmt (0); }
- save_lineno simple_stmt
+ save_lineno simple_stmt
{ STMT_LINENO ($<ttype>1) = $2;
if ($3) STMT_LINENO ($3) = $2;
finish_compound_stmt (0, $<ttype>1); }
@@ -3423,9 +3425,9 @@ simple_stmt:
| simple_if ELSE
{ begin_else_clause (); }
implicitly_scoped_stmt
- {
+ {
$$ = $1;
- finish_else_clause ($1);
+ finish_else_clause ($1);
finish_if_stmt ();
}
| simple_if %prec IF
@@ -3462,7 +3464,7 @@ simple_stmt:
implicitly_scoped_stmt
{ $$ = $<ttype>2;
finish_for_stmt ($<ttype>2); }
- | SWITCH
+ | SWITCH
{ $<ttype>$ = begin_switch_stmt (); }
'(' condition ')'
{ finish_switch_cond ($4, $<ttype>2); }
@@ -3489,31 +3491,31 @@ simple_stmt:
{ $$ = finish_return_stmt (NULL_TREE); }
| RETURN_KEYWORD expr ';'
{ $$ = finish_return_stmt ($2); }
- | asm_keyword maybe_cv_qualifier '(' string ')' ';'
+ | asm_keyword maybe_cv_qualifier '(' STRING ')' ';'
{ $$ = finish_asm_stmt ($2, $4, NULL_TREE, NULL_TREE,
NULL_TREE);
ASM_INPUT_P ($$) = 1; }
/* This is the case with just output operands. */
- | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ')' ';'
+ | asm_keyword maybe_cv_qualifier '(' STRING ':' asm_operands ')' ';'
{ $$ = finish_asm_stmt ($2, $4, $6, NULL_TREE, NULL_TREE); }
/* This is the case with input operands as well. */
- | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':'
+ | asm_keyword maybe_cv_qualifier '(' STRING ':' asm_operands ':'
asm_operands ')' ';'
{ $$ = finish_asm_stmt ($2, $4, $6, $8, NULL_TREE); }
- | asm_keyword maybe_cv_qualifier '(' string SCOPE asm_operands ')' ';'
+ | asm_keyword maybe_cv_qualifier '(' STRING SCOPE asm_operands ')' ';'
{ $$ = finish_asm_stmt ($2, $4, NULL_TREE, $6, NULL_TREE); }
/* This is the case with clobbered registers as well. */
- | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':'
+ | asm_keyword maybe_cv_qualifier '(' STRING ':' asm_operands ':'
asm_operands ':' asm_clobbers ')' ';'
{ $$ = finish_asm_stmt ($2, $4, $6, $8, $10); }
- | asm_keyword maybe_cv_qualifier '(' string SCOPE asm_operands ':'
+ | asm_keyword maybe_cv_qualifier '(' STRING SCOPE asm_operands ':'
asm_clobbers ')' ';'
{ $$ = finish_asm_stmt ($2, $4, NULL_TREE, $6, $8); }
- | asm_keyword maybe_cv_qualifier '(' string ':' asm_operands SCOPE
+ | asm_keyword maybe_cv_qualifier '(' STRING ':' asm_operands SCOPE
asm_clobbers ')' ';'
{ $$ = finish_asm_stmt ($2, $4, $6, NULL_TREE, $8); }
| GOTO '*' expr ';'
- {
+ {
if (pedantic)
pedwarn ("ISO C++ forbids computed gotos");
$$ = finish_goto_stmt ($3);
@@ -3604,7 +3606,7 @@ handler_args:
expand_start_catch_block ($2.t, $3); }
This allows reference parameters... */
| '(' parm ')'
- {
+ {
check_for_new_type ("inside exception declarations", $2);
$$ = start_handler_parms (TREE_PURPOSE ($2.t),
TREE_VALUE ($2.t));
@@ -3666,14 +3668,16 @@ asm_operand:
STRING '(' expr ')'
{ $$ = build_tree_list (build_tree_list (NULL_TREE, $1), $3); }
| '[' identifier ']' STRING '(' expr ')'
- { $$ = build_tree_list (build_tree_list ($2, $4), $6); }
+ { $2 = build_string (IDENTIFIER_LENGTH ($2),
+ IDENTIFIER_POINTER ($2));
+ $$ = build_tree_list (build_tree_list ($2, $4), $6); }
;
asm_clobbers:
- string
- { $$ = tree_cons (NULL_TREE, combine_strings ($1), NULL_TREE);}
- | asm_clobbers ',' string
- { $$ = tree_cons (NULL_TREE, combine_strings ($3), $1); }
+ STRING
+ { $$ = tree_cons (NULL_TREE, $1, NULL_TREE);}
+ | asm_clobbers ',' STRING
+ { $$ = tree_cons (NULL_TREE, $3, $1); }
;
/* This is what appears inside the parens in a function declarator.
@@ -3705,7 +3709,7 @@ complex_parmlist:
{ $$ = finish_parmlist ($1, 1); }
| type_id ELLIPSIS
{ $$ = finish_parmlist (build_tree_list (NULL_TREE,
- $1.t), 1); }
+ $1.t), 1); }
| ELLIPSIS
{ $$ = finish_parmlist (NULL_TREE, 1); }
| parms ':'
@@ -3725,7 +3729,7 @@ complex_parmlist:
parenthesis. */
yyerror ("possibly missing ')'");
$$ = finish_parmlist (build_tree_list (NULL_TREE,
- $1.t), 0);
+ $1.t), 0);
yyungetc (':', 0);
yychar = ')';
}
@@ -3777,20 +3781,20 @@ named_parm:
{ $$.new_type_flag = $1.new_type_flag;
$$.t = build_tree_list ($1.t, $2); }
| typed_typespecs declarator
- { $$.t = build_tree_list ($1.t, $2);
+ { $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| typespec declarator
{ $$.t = build_tree_list (build_tree_list (NULL_TREE, $1.t),
- $2);
+ $2);
$$.new_type_flag = $1.new_type_flag; }
| typed_declspecs1 absdcl
{ $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = $1.new_type_flag; }
| typed_declspecs1 %prec EMPTY
- { $$.t = build_tree_list ($1.t, NULL_TREE);
+ { $$.t = build_tree_list ($1.t, NULL_TREE);
$$.new_type_flag = $1.new_type_flag; }
| declmods notype_declarator
- { $$.t = build_tree_list ($1.t, $2);
+ { $$.t = build_tree_list ($1.t, $2);
$$.new_type_flag = 0; }
;
@@ -3912,6 +3916,7 @@ unoperator:
got_object = TREE_VALUE (saved_scopes);
looking_for_typename = TREE_LANG_FLAG_0 (saved_scopes);
saved_scopes = TREE_CHAIN (saved_scopes);
+ $$ = got_scope;
}
;
@@ -3983,7 +3988,7 @@ operator_name:
| operator DELETE '[' ']' unoperator
{ $$ = frob_opname (ansi_opname (VEC_DELETE_EXPR)); }
| operator type_specifier_seq conversion_declarator unoperator
- { $$ = frob_opname (grokoptypename ($2.t, $3)); }
+ { $$ = frob_opname (grokoptypename ($2.t, $3, $4)); }
| operator error unoperator
{ $$ = frob_opname (ansi_opname (ERROR_MARK)); }
;
@@ -4005,5 +4010,211 @@ debug_yytranslate (value)
{
return yytname[YYTRANSLATE (value)];
}
-
#endif
+
+/* Free malloced parser stacks if necessary. */
+
+void
+free_parser_stacks ()
+{
+ if (malloced_yyss)
+ {
+ free (malloced_yyss);
+ free (malloced_yyvs);
+ }
+}
+
+/* Return the value corresponding to TOKEN in the global scope. */
+
+static tree
+parse_scoped_id (token)
+ tree token;
+{
+ cxx_binding binding;
+
+ cxx_binding_clear (&binding);
+ if (!qualified_lookup_using_namespace (token, global_namespace, &binding, 0))
+ binding.value = NULL;
+ if (yychar == YYEMPTY)
+ yychar = yylex();
+
+ return do_scoped_id (token, binding.value);
+}
+
+/* AGGR may be either a type node (like class_type_node) or a
+ TREE_LIST whose TREE_PURPOSE is a list of attributes and whose
+ TREE_VALUE is a type node. Set *TAG_KIND and *ATTRIBUTES to
+ represent the information encoded. */
+
+static void
+parse_split_aggr (tree aggr, enum tag_types *tag_kind, tree *attributes)
+{
+ if (TREE_CODE (aggr) == TREE_LIST)
+ {
+ *attributes = TREE_PURPOSE (aggr);
+ aggr = TREE_VALUE (aggr);
+ }
+ else
+ *attributes = NULL_TREE;
+ *tag_kind = (enum tag_types) tree_low_cst (aggr, 1);
+}
+
+/* Like xref_tag, except that the AGGR may be either a type node (like
+ class_type_node) or a TREE_LIST whose TREE_PURPOSE is a list of
+ attributes and whose TREE_VALUE is a type node. */
+
+static tree
+parse_xref_tag (tree aggr, tree name, int globalize)
+{
+ tree attributes;
+ enum tag_types tag_kind;
+ parse_split_aggr (aggr, &tag_kind, &attributes);
+ return xref_tag (tag_kind, name, attributes, globalize);
+}
+
+/* Like handle_class_head, but AGGR may be as for parse_xref_tag. */
+
+static tree
+parse_handle_class_head (tree aggr, tree scope, tree id,
+ int defn_p, int *new_type_p)
+{
+ tree attributes;
+ enum tag_types tag_kind;
+ parse_split_aggr (aggr, &tag_kind, &attributes);
+ return handle_class_head (tag_kind, scope, id, attributes,
+ defn_p, new_type_p);
+}
+
+/* Like do_decl_instantiation, but the declarator has not yet been
+ parsed. */
+
+static void
+parse_decl_instantiation (tree declspecs, tree declarator, tree storage)
+{
+ tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL);
+ do_decl_instantiation (decl, storage);
+}
+
+/* Like begin_function_definition, but SPECS_ATTRS is a combined list
+ containing both a decl-specifier-seq and attributes. */
+
+static int
+parse_begin_function_definition (tree specs_attrs, tree declarator)
+{
+ tree specs;
+ tree attrs;
+
+ split_specs_attrs (specs_attrs, &specs, &attrs);
+ return begin_function_definition (specs, attrs, declarator);
+}
+
+/* Like finish_call_expr, but the name for FN has not yet been
+ resolved. */
+
+static tree
+parse_finish_call_expr (tree fn, tree args, int koenig)
+{
+ bool disallow_virtual;
+
+ if (TREE_CODE (fn) == OFFSET_REF)
+ return build_offset_ref_call_from_tree (fn, args);
+
+ if (TREE_CODE (fn) == SCOPE_REF)
+ {
+ tree scope = TREE_OPERAND (fn, 0);
+ tree name = TREE_OPERAND (fn, 1);
+
+ if (scope == error_mark_node || name == error_mark_node)
+ return error_mark_node;
+ if (!processing_template_decl)
+ fn = resolve_scoped_fn_name (scope, name);
+ disallow_virtual = true;
+ }
+ else
+ disallow_virtual = false;
+
+ if (koenig && TREE_CODE (fn) == IDENTIFIER_NODE)
+ {
+ tree f;
+
+ /* Do the Koenig lookup. */
+ fn = do_identifier (fn, 2, args);
+ /* If name lookup didn't find any matching declarations, we've
+ got an unbound identifier. */
+ if (TREE_CODE (fn) == IDENTIFIER_NODE)
+ {
+ /* For some reason, do_identifier does not resolve
+ conversion operator names if the only matches would be
+ template conversion operators. So, we do it here. */
+ if (IDENTIFIER_TYPENAME_P (fn) && current_class_type)
+ {
+ f = lookup_member (current_class_type, fn,
+ /*protect=*/1, /*want_type=*/0);
+ if (f)
+ return finish_call_expr (f, args,
+ /*disallow_virtual=*/false);
+ }
+ /* If the name still could not be resolved, then the program
+ is ill-formed. */
+ if (TREE_CODE (fn) == IDENTIFIER_NODE)
+ {
+ unqualified_name_lookup_error (fn);
+ return error_mark_node;
+ }
+ }
+ else if (TREE_CODE (fn) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (fn)
+ || TREE_CODE (fn) == OVERLOAD)
+ {
+ tree scope = DECL_CONTEXT (get_first_fn (fn));
+ if (scope && TYPE_P (scope))
+ {
+ tree access_scope;
+
+ if (DERIVED_FROM_P (scope, current_class_type)
+ && current_class_ref)
+ {
+ fn = build_baselink (lookup_base (current_class_type,
+ scope,
+ ba_any,
+ NULL),
+ TYPE_BINFO (current_class_type),
+ fn,
+ /*optype=*/NULL_TREE);
+ return finish_object_call_expr (fn,
+ current_class_ref,
+ args);
+ }
+
+
+ access_scope = current_class_type;
+ while (!DERIVED_FROM_P (scope, access_scope))
+ {
+ access_scope = TYPE_CONTEXT (access_scope);
+ while (DECL_P (access_scope))
+ access_scope = DECL_CONTEXT (access_scope);
+ }
+
+ fn = build_baselink (NULL_TREE,
+ TYPE_BINFO (access_scope),
+ fn,
+ /*optype=*/NULL_TREE);
+ }
+ }
+ }
+
+ if (TREE_CODE (fn) == COMPONENT_REF)
+ /* If the parser sees `(x->y)(bar)' we get here because the
+ parentheses confuse the parser. Treat this like
+ `x->y(bar)'. */
+ return finish_object_call_expr (TREE_OPERAND (fn, 1),
+ TREE_OPERAND (fn, 0),
+ args);
+
+ if (processing_template_decl)
+ return build_nt (CALL_EXPR, fn, args, NULL_TREE);
+
+ return build_call_from_tree (fn, args, disallow_virtual);
+}
+
+#include "gt-cp-parse.h"
diff --git a/contrib/gcc/cp/pt.c b/contrib/gcc/cp/pt.c
index b751ad4..22f93bf 100644
--- a/contrib/gcc/cp/pt.c
+++ b/contrib/gcc/cp/pt.c
@@ -47,35 +47,32 @@ Boston, MA 02111-1307, USA. */
returning an int. */
typedef int (*tree_fn_t) PARAMS ((tree, void*));
-extern struct obstack permanent_obstack;
-
/* The PENDING_TEMPLATES is a TREE_LIST of templates whose
instantiations have been deferred, either because their definitions
were not yet available, or because we were putting off doing the
work. The TREE_PURPOSE of each entry is a SRCLOC indicating where
- the instantiate request occurred; the TREE_VALUE is a either a DECL
+ the instantiate request occurred; the TREE_VALUE is either a DECL
(for a function or static data member), or a TYPE (for a class)
indicating what we are hoping to instantiate. */
-static tree pending_templates;
+static GTY(()) tree pending_templates;
static tree last_pending_template;
int processing_template_parmlist;
static int template_header_count;
-static tree saved_trees;
-static varray_type inline_parm_levels;
+static GTY(()) tree saved_trees;
+static GTY(()) varray_type inline_parm_levels;
static size_t inline_parm_levels_used;
-static tree current_tinst_level;
+static GTY(()) tree current_tinst_level;
+
+static GTY(()) tree saved_access_scope;
/* A map from local variable declarations in the body of the template
presently being instantiated to the corresponding instantiated
local variables. */
static htab_t local_specializations;
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
#define UNIFY_ALLOW_NONE 0
#define UNIFY_ALLOW_MORE_CV_QUAL 1
#define UNIFY_ALLOW_LESS_CV_QUAL 2
@@ -92,6 +89,9 @@ static htab_t local_specializations;
#define GTB_IGNORE_TYPE 2 /* We don't need to try to unify the current
type with the desired type. */
+static void push_access_scope_real PARAMS ((tree, tree, tree));
+static void push_access_scope PARAMS ((tree));
+static void pop_access_scope PARAMS ((tree));
static int resolve_overloaded_unification PARAMS ((tree, tree, tree, tree,
unification_kind_t, int));
static int try_one_overload PARAMS ((tree, tree, tree, tree, tree,
@@ -120,7 +120,7 @@ static tree convert_nontype_argument PARAMS ((tree, tree));
static tree convert_template_argument PARAMS ((tree, tree, tree,
tsubst_flags_t, int, tree));
static tree get_bindings_overload PARAMS ((tree, tree, tree));
-static int for_each_template_parm PARAMS ((tree, tree_fn_t, void*));
+static int for_each_template_parm PARAMS ((tree, tree_fn_t, void*, htab_t));
static tree build_template_parm_index PARAMS ((int, int, int, tree, tree));
static int inline_needs_template_parms PARAMS ((tree));
static void push_inline_template_parms_recursive PARAMS ((tree, int));
@@ -132,6 +132,7 @@ static int unregister_specialization PARAMS ((tree, tree));
static tree reduce_template_parm_level PARAMS ((tree, tree, int));
static tree build_template_decl PARAMS ((tree, tree));
static int mark_template_parm PARAMS ((tree, void *));
+static int template_parm_this_level_p PARAMS ((tree, void *));
static tree tsubst_friend_function PARAMS ((tree, tree));
static tree tsubst_friend_class PARAMS ((tree, tree));
static int can_complete_type_without_circularity PARAMS ((tree));
@@ -170,14 +171,85 @@ static tree copy_default_args_to_explicit_spec_1 PARAMS ((tree, tree));
static void copy_default_args_to_explicit_spec PARAMS ((tree));
static int invalid_nontype_parm_type_p PARAMS ((tree, tsubst_flags_t));
-/* Called once to initialize pt.c. */
+/* Make the current scope suitable for access checking when we are
+ processing T. T can be FUNCTION_DECL for instantiated function
+ template, TEMPLATE_DECL for uninstantiated one, or VAR_DECL for
+ static member variable (need by instantiate_decl). ARGS is the
+ template argument for TEMPLATE_DECL. If CONTEXT is not NULL_TREE,
+ this is used instead of the context of T. */
+
+void
+push_access_scope_real (t, args, context)
+ tree t, args, context;
+{
+ if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+ {
+ /* When we are processing specialization `foo<Outer>' for code like
+
+ template <class U> typename U::Inner foo ();
+ class Outer {
+ struct Inner {};
+ friend Outer::Inner foo<Outer> ();
+ };
+
+ `T' is a TEMPLATE_DECL, but `Outer' is only a friend of one of
+ its specialization. We can get the FUNCTION_DECL with the right
+ information because this specialization has already been
+ registered by the friend declaration above. */
+
+ if (DECL_FUNCTION_TEMPLATE_P (t) && args)
+ {
+ tree full_args = tsubst_template_arg_vector
+ (DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t)), args, tf_none);
+ tree spec = NULL_TREE;
+ if (full_args != error_mark_node)
+ spec = retrieve_specialization (t, full_args);
+ if (spec)
+ t = spec;
+ }
+ }
+
+ if (!context)
+ context = DECL_CONTEXT (t);
+ if (context && TYPE_P (context))
+ push_nested_class (context, 2);
+ else
+ push_to_top_level ();
+
+ if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+ {
+ saved_access_scope = tree_cons
+ (NULL_TREE, current_function_decl, saved_access_scope);
+ current_function_decl = t;
+ }
+}
+
+/* Like push_access_scope_real, but always uses DECL_CONTEXT. */
+
+void
+push_access_scope (t)
+ tree t;
+{
+ push_access_scope_real (t, NULL_TREE, NULL_TREE);
+}
+
+/* Restore the scope set up by push_access_scope. T is the node we
+ are processing. */
void
-init_pt ()
+pop_access_scope (t)
+ tree t;
{
- ggc_add_tree_root (&pending_templates, 1);
- ggc_add_tree_root (&saved_trees, 1);
- ggc_add_tree_root (&current_tinst_level, 1);
+ if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+ {
+ current_function_decl = TREE_VALUE (saved_access_scope);
+ saved_access_scope = TREE_CHAIN (saved_access_scope);
+ }
+
+ if (DECL_CLASS_SCOPE_P (t))
+ pop_nested_class ();
+ else
+ pop_from_top_level ();
}
/* Do any processing required when DECL (a member template declaration
@@ -395,7 +467,7 @@ maybe_begin_member_template_processing (decl)
++inline_parm_levels_used;
}
-/* Undo the effects of begin_member_template_processing. */
+/* Undo the effects of begin_member_template_processing. */
void
maybe_end_member_template_processing ()
@@ -416,7 +488,7 @@ maybe_end_member_template_processing ()
}
}
-/* Returns non-zero iff T is a member template function. We must be
+/* Returns nonzero iff T is a member template function. We must be
careful as in
template <class T> class C { void f(); }
@@ -453,7 +525,7 @@ is_member_template (t)
}
#if 0 /* UNUSED */
-/* Returns non-zero iff T is a member template class. See
+/* Returns nonzero iff T is a member template class. See
is_member_template for a description of what precisely constitutes
a member template. */
@@ -599,7 +671,7 @@ begin_template_parm_list ()
}
/* This routine is called when a specialization is declared. If it is
- illegal to declare a specialization here, an error is reported. */
+ invalid to declare a specialization here, an error is reported. */
static void
check_specialization_scope ()
@@ -631,7 +703,7 @@ check_specialization_scope ()
error ("enclosing class templates are not explicitly specialized");
}
-/* We've just seen template <>. */
+/* We've just seen template <>. */
void
begin_specialization ()
@@ -652,7 +724,7 @@ end_specialization ()
}
/* Any template <>'s that we have seen thus far are not referring to a
- function specialization. */
+ function specialization. */
void
reset_specialization ()
@@ -661,7 +733,7 @@ reset_specialization ()
template_header_count = 0;
}
-/* We've just seen a template header. If SPECIALIZATION is non-zero,
+/* We've just seen a template header. If SPECIALIZATION is nonzero,
it was of the form template <>. */
static void
@@ -695,8 +767,22 @@ void
maybe_process_partial_specialization (type)
tree type;
{
- if (IS_AGGR_TYPE (type) && CLASSTYPE_USE_TEMPLATE (type))
+ /* TYPE maybe an ERROR_MARK_NODE. */
+ tree context = TYPE_P (type) ? TYPE_CONTEXT (type) : NULL_TREE;
+
+ if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
{
+ /* This is for ordinary explicit specialization and partial
+ specialization of a template class such as:
+
+ template <> class C<int>;
+
+ or:
+
+ template <class T> class C<T*>;
+
+ Make sure that `C<int>' and `C<T*>' are implicit instantiations. */
+
if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
@@ -714,6 +800,62 @@ maybe_process_partial_specialization (type)
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
error ("specialization of `%T' after instantiation", type);
}
+ else if (CLASS_TYPE_P (type)
+ && !CLASSTYPE_USE_TEMPLATE (type)
+ && CLASSTYPE_TEMPLATE_INFO (type)
+ && context && CLASS_TYPE_P (context)
+ && CLASSTYPE_TEMPLATE_INFO (context))
+ {
+ /* This is for an explicit specialization of member class
+ template according to [temp.expl.spec/18]:
+
+ template <> template <class U> class C<int>::D;
+
+ The context `C<int>' must be an implicit instantiation.
+ Otherwise this is just a member class template declared
+ earlier like:
+
+ template <> class C<int> { template <class U> class D; };
+ template <> template <class U> class C<int>::D;
+
+ In the first case, `C<int>::D' is a specialization of `C<T>::D'
+ while in the second case, `C<int>::D' is a primary template
+ and `C<T>::D' may not exist. */
+
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION (context)
+ && !COMPLETE_TYPE_P (type))
+ {
+ tree t;
+
+ if (current_namespace
+ != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
+ {
+ pedwarn ("specializing `%#T' in different namespace", type);
+ cp_pedwarn_at (" from definition of `%#D'",
+ CLASSTYPE_TI_TEMPLATE (type));
+ }
+
+ /* Check for invalid specialization after instantiation:
+
+ template <> template <> class C<int>::D<int>;
+ template <> template <class U> class C<int>::D; */
+
+ for (t = DECL_TEMPLATE_INSTANTIATIONS
+ (most_general_template (CLASSTYPE_TI_TEMPLATE (type)));
+ t; t = TREE_CHAIN (t))
+ if (TREE_VALUE (t) != type
+ && TYPE_CONTEXT (TREE_VALUE (t)) == context)
+ error ("specialization `%T' after instantiation `%T'",
+ type, TREE_VALUE (t));
+
+ /* Mark TYPE as a specialization. And as a result, we only
+ have one level of template argument for the innermost
+ class template. */
+ SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
+ CLASSTYPE_TI_ARGS (type)
+ = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
+ }
+ }
else if (processing_specialization)
error ("explicit specialization of non-template `%T'", type);
}
@@ -758,7 +900,7 @@ retrieve_local_specialization (tmpl)
return (tree) htab_find (local_specializations, tmpl);
}
-/* Returns non-zero iff DECL is a specialization of TMPL. */
+/* Returns nonzero iff DECL is a specialization of TMPL. */
int
is_specialization_of (decl, tmpl)
@@ -961,7 +1103,7 @@ print_candidates (fns)
NULL_TREE if none is available. In that case, the functions in
TEMPLATE_ID are non-members.
- If NEED_MEMBER_TEMPLATE is non-zero the function is known to be a
+ If NEED_MEMBER_TEMPLATE is nonzero the function is known to be a
specialization of a member template.
The template args (those explicitly specified and those deduced)
@@ -995,9 +1137,9 @@ determine_specialization (template_id, decl, targs_out,
if (fns == error_mark_node)
return error_mark_node;
- /* Check for baselinks. */
+ /* Check for baselinks. */
if (BASELINK_P (fns))
- fns = TREE_VALUE (fns);
+ fns = BASELINK_FUNCTIONS (fns);
if (!is_overloaded_fn (fns))
{
@@ -1007,28 +1149,58 @@ determine_specialization (template_id, decl, targs_out,
for (; fns; fns = OVL_NEXT (fns))
{
- tree tmpl;
-
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
- /* DECL might be a specialization of FN. */
- tmpl = fn;
+ {
+ tree decl_arg_types;
+
+ /* DECL might be a specialization of FN. */
+
+ /* Adjust the type of DECL in case FN is a static member. */
+ decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ if (DECL_STATIC_FUNCTION_P (fn)
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ decl_arg_types = TREE_CHAIN (decl_arg_types);
+
+ /* Check that the number of function parameters matches.
+ For example,
+ template <class T> void f(int i = 0);
+ template <> void f<int>();
+ The specialization f<int> is invalid but is not caught
+ by get_bindings below. */
+
+ if (list_length (TYPE_ARG_TYPES (TREE_TYPE (fn)))
+ != list_length (decl_arg_types))
+ continue;
+
+ /* See whether this function might be a specialization of this
+ template. */
+ targs = get_bindings (fn, decl, explicit_targs);
+
+ if (!targs)
+ /* We cannot deduce template arguments that when used to
+ specialize TMPL will produce DECL. */
+ continue;
+
+ /* Save this template, and the arguments deduced. */
+ templates = tree_cons (targs, fn, templates);
+ }
else if (need_member_template)
/* FN is an ordinary member function, and we need a
specialization of a member template. */
- continue;
+ ;
else if (TREE_CODE (fn) != FUNCTION_DECL)
/* We can get IDENTIFIER_NODEs here in certain erroneous
cases. */
- continue;
+ ;
else if (!DECL_FUNCTION_MEMBER_P (fn))
/* This is just an ordinary non-member function. Nothing can
be a specialization of that. */
- continue;
+ ;
else if (DECL_ARTIFICIAL (fn))
/* Cannot specialize functions that are created implicitly. */
- continue;
+ ;
else
{
tree decl_arg_types;
@@ -1064,21 +1236,7 @@ determine_specialization (template_id, decl, targs_out,
decl_arg_types))
/* They match! */
candidates = tree_cons (NULL_TREE, fn, candidates);
-
- continue;
}
-
- /* See whether this function might be a specialization of this
- template. */
- targs = get_bindings (tmpl, decl, explicit_targs);
-
- if (!targs)
- /* We cannot deduce template arguments that when used to
- specialize TMPL will produce DECL. */
- continue;
-
- /* Save this template, and the arguments deduced. */
- templates = tree_cons (targs, tmpl, templates);
}
if (templates && TREE_CHAIN (templates))
@@ -1108,7 +1266,7 @@ determine_specialization (template_id, decl, targs_out,
template.
So, we do use the partial ordering rules, at least for now.
- This extension can only serve to make illegal programs legal,
+ This extension can only serve to make invalid programs valid,
so it's safe. And, there is strong anecdotal evidence that
the committee intended the partial ordering rules to apply;
the EDG front-end has that behavior, and John Spicer claims
@@ -1139,7 +1297,7 @@ determine_specialization (template_id, decl, targs_out,
return error_mark_node;
}
- /* We have one, and exactly one, match. */
+ /* We have one, and exactly one, match. */
if (candidates)
{
/* It was a specialization of an ordinary member function in a
@@ -1313,7 +1471,7 @@ copy_default_args_to_explicit_spec (decl)
template <> void S<int>::f();
the TEMPLATE_COUNT would be 0. (Note that this declaration is
- illegal; there should be no template <>.)
+ invalid; there should be no template <>.)
If the function is a specialization, it is marked as such via
DECL_TEMPLATE_SPECIALIZATION. Furthermore, its DECL_TEMPLATE_INFO
@@ -1414,7 +1572,7 @@ check_explicit_specialization (declarator, decl, template_count, flags)
template <class T> struct S { void f(); };
void S<int>::f() {} // Missing template <>
- That used to be legal C++. */
+ That used to be valid C++. */
if (pedantic)
pedwarn
("explicit specialization not preceded by `template <>'");
@@ -1496,13 +1654,13 @@ check_explicit_specialization (declarator, decl, template_count, flags)
if (ctype != NULL_TREE && TYPE_BEING_DEFINED (ctype))
{
if (!explicit_instantiation)
- /* A specialization in class scope. This is illegal,
+ /* A specialization in class scope. This is invalid,
but the error will already have been flagged by
check_specialization_scope. */
return error_mark_node;
else
{
- /* It's not legal to write an explicit instantiation in
+ /* It's not valid to write an explicit instantiation in
class scope, e.g.:
class C { template void f(); }
@@ -1512,7 +1670,7 @@ check_explicit_specialization (declarator, decl, template_count, flags)
template class C { void f(); };
- (which is illegal) we can get here. The error will be
+ (which is invalid) we can get here. The error will be
issued later. */
;
}
@@ -1538,8 +1696,7 @@ check_explicit_specialization (declarator, decl, template_count, flags)
tree fns = NULL_TREE;
int idx;
- if (name == constructor_name (ctype)
- || name == constructor_name_full (ctype))
+ if (constructor_name_p (name, ctype))
{
int is_constructor = DECL_CONSTRUCTOR_P (decl);
@@ -1580,7 +1737,8 @@ check_explicit_specialization (declarator, decl, template_count, flags)
methods = CLASSTYPE_METHOD_VEC (ctype);
if (methods)
- for (idx = 2; idx < TREE_VEC_LENGTH (methods); ++idx)
+ for (idx = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ idx < TREE_VEC_LENGTH (methods); ++idx)
{
tree ovl = TREE_VEC_ELT (methods, idx);
@@ -1653,6 +1811,18 @@ check_explicit_specialization (declarator, decl, template_count, flags)
return instantiate_template (tmpl, targs);
}
+ /* If we thought that the DECL was a member function, but it
+ turns out to be specializing a static member function,
+ make DECL a static member function as well. We also have
+ to adjust last_function_parms to avoid confusing
+ start_function later. */
+ if (DECL_STATIC_FUNCTION_P (tmpl)
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+ {
+ revert_static_member_fn (decl);
+ last_function_parms = TREE_CHAIN (last_function_parms);
+ }
+
/* If this is a specialization of a member template of a
template class. In we want to return the TEMPLATE_DECL,
not the specialization of it. */
@@ -1663,16 +1833,6 @@ check_explicit_specialization (declarator, decl, template_count, flags)
return tmpl;
}
- /* If we thought that the DECL was a member function, but it
- turns out to be specializing a static member function,
- make DECL a static member function as well. */
- if (DECL_STATIC_FUNCTION_P (tmpl)
- && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
- {
- revert_static_member_fn (decl);
- last_function_parms = TREE_CHAIN (last_function_parms);
- }
-
/* Set up the DECL_TEMPLATE_INFO for DECL. */
DECL_TEMPLATE_INFO (decl) = tree_cons (tmpl, targs, NULL_TREE);
@@ -1732,7 +1892,7 @@ maybe_check_template_type (type)
struct I {};
};
- is illegal, but:
+ is invalid, but:
template <class T> struct S {
template <class U> struct I;
@@ -2104,10 +2264,9 @@ build_template_decl (decl, parms)
DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
if (DECL_LANG_SPECIFIC (decl))
{
- if (CAN_HAVE_FULL_LANG_DECL_P (decl))
- DECL_VIRTUAL_CONTEXT (tmpl) = DECL_VIRTUAL_CONTEXT (decl);
DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl);
DECL_CONSTRUCTOR_P (tmpl) = DECL_CONSTRUCTOR_P (decl);
+ DECL_DESTRUCTOR_P (tmpl) = DECL_DESTRUCTOR_P (decl);
DECL_NONCONVERTING_P (tmpl) = DECL_NONCONVERTING_P (decl);
DECL_ASSIGNMENT_OPERATOR_P (tmpl) = DECL_ASSIGNMENT_OPERATOR_P (decl);
if (DECL_OVERLOADED_OPERATOR_P (decl))
@@ -2129,12 +2288,12 @@ struct template_parm_data
int current_arg;
/* An array whose size is the number of template parameters. The
- elements are non-zero if the parameter has been used in any one
+ elements are nonzero if the parameter has been used in any one
of the arguments processed so far. */
int* parms;
/* An array whose size is the number of template arguments. The
- elements are non-zero if the argument makes use of template
+ elements are nonzero if the argument makes use of template
parameters of this level. */
int* arg_uses_template_parms;
};
@@ -2218,7 +2377,7 @@ process_partial_specialization (decl)
struct S2<T>;
};
- The S2<T> declaration is actually illegal; it is a
+ The S2<T> declaration is actually invalid; it is a
full-specialization. Of course,
template <class U>
@@ -2236,7 +2395,8 @@ process_partial_specialization (decl)
tpd.current_arg = i;
for_each_template_parm (TREE_VEC_ELT (inner_args, i),
&mark_template_parm,
- &tpd);
+ &tpd,
+ NULL);
}
for (i = 0; i < ntparms; ++i)
if (tpd.parms[i] == 0)
@@ -2317,7 +2477,8 @@ process_partial_specialization (decl)
memset ((PTR) tpd2.parms, 0, sizeof (int) * nargs);
for_each_template_parm (type,
&mark_template_parm,
- &tpd2);
+ &tpd2,
+ NULL);
if (tpd2.arg_uses_template_parms [i])
{
@@ -2352,8 +2513,8 @@ process_partial_specialization (decl)
/* Check that a template declaration's use of default arguments is not
invalid. Here, PARMS are the template parameters. IS_PRIMARY is
- non-zero if DECL is the thing declared by a primary template.
- IS_PARTIAL is non-zero if DECL is a partial specialization. */
+ nonzero if DECL is the thing declared by a primary template.
+ IS_PARTIAL is nonzero if DECL is a partial specialization. */
static void
check_default_tmpl_args (decl, parms, is_primary, is_partial)
@@ -2457,7 +2618,7 @@ check_default_tmpl_args (decl, parms, is_primary, is_partial)
/* If we're inside a class definition, there's no need to
examine the parameters to the class itself. On the one
hand, they will be checked when the class is defined, and,
- on the other, default arguments are legal in things like:
+ on the other, default arguments are valid in things like:
template <class T = double>
struct S { template <class U> void f(U); };
Here the default argument for `S' has no bearing on the
@@ -2497,12 +2658,32 @@ check_default_tmpl_args (decl, parms, is_primary, is_partial)
}
}
+/* Worker for push_template_decl_real, called via
+ for_each_template_parm. DATA is really an int, indicating the
+ level of the parameters we are interested in. If T is a template
+ parameter of that level, return nonzero. */
+
+static int
+template_parm_this_level_p (t, data)
+ tree t;
+ void *data;
+{
+ int this_level = *(int *)data;
+ int level;
+
+ if (TREE_CODE (t) == TEMPLATE_PARM_INDEX)
+ level = TEMPLATE_PARM_LEVEL (t);
+ else
+ level = TEMPLATE_TYPE_LEVEL (t);
+ return level == this_level;
+}
+
/* Creates a TEMPLATE_DECL for the indicated DECL using the template
parameters given by current_template_args, or reuses a
previously existing one, if appropriate. Returns the DECL, or an
equivalent one, if it is replaced via a call to duplicate_decls.
- If IS_FRIEND is non-zero, DECL is a friend declaration. */
+ If IS_FRIEND is nonzero, DECL is a friend declaration. */
tree
push_template_decl_real (decl, is_friend)
@@ -2593,7 +2774,7 @@ push_template_decl_real (decl, is_friend)
{
/* Since a template declaration already existed for this
class-type, we must be redeclaring it here. Make sure
- that the redeclaration is legal. */
+ that the redeclaration is valid. */
redeclare_class_template (TREE_TYPE (decl),
current_template_parms);
/* We don't need to create a new TEMPLATE_DECL; just use the
@@ -2609,7 +2790,7 @@ push_template_decl_real (decl, is_friend)
&& DECL_TEMPLATE_SPECIALIZATION (decl))
{
/* A specialization of a member template of a template
- class. */
+ class. */
SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
DECL_TEMPLATE_INFO (tmpl) = DECL_TEMPLATE_INFO (decl);
DECL_TEMPLATE_INFO (decl) = NULL_TREE;
@@ -2719,7 +2900,22 @@ push_template_decl_real (decl, is_friend)
tmpl = pushdecl_namespace_level (tmpl);
if (primary)
- DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
+ {
+ DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
+ if (DECL_CONV_FN_P (tmpl))
+ {
+ int depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
+
+ /* It is a conversion operator. See if the type converted to
+ depends on innermost template operands. */
+
+ if (for_each_template_parm (TREE_TYPE (TREE_TYPE (tmpl)),
+ template_parm_this_level_p,
+ &depth,
+ NULL))
+ DECL_TEMPLATE_CONV_FN_P (tmpl) = 1;
+ }
+ }
info = tree_cons (tmpl, args, NULL_TREE);
@@ -2962,7 +3158,7 @@ convert_nontype_argument (type, expr)
case ENUMERAL_TYPE:
/* For a non-type template-parameter of integral or enumeration
type, integral promotions (_conv.prom_) and integral
- conversions (_conv.integral_) are applied. */
+ conversions (_conv.integral_) are applied. */
if (!INTEGRAL_TYPE_P (expr_type))
return error_mark_node;
@@ -3120,7 +3316,7 @@ convert_nontype_argument (type, expr)
return error_mark_node;
}
- mark_addressable (expr);
+ cxx_mark_addressable (expr);
return build1 (ADDR_EXPR, type, expr);
}
break;
@@ -3287,7 +3483,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
{
/* The template argument was the name of some
member function. That's usually
- illegal, but static members are OK. In any
+ invalid, but static members are OK. In any
case, grab the underlying fields/functions
and issue an error later if required. */
arg = TREE_VALUE (arg);
@@ -3458,7 +3654,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
extension, since deciding whether or not these
conversions can occur is part of determining which
function template to call, or whether a given explicit
- argument specification is legal. */
+ argument specification is valid. */
val = convert_nontype_argument (t, arg);
else
val = arg;
@@ -3480,7 +3676,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
messages are issued even if COMPLAIN is zero; for instance, if a
template argument is composed from a local class.
- If REQUIRE_ALL_ARGUMENTS is non-zero, all arguments must be
+ If REQUIRE_ALL_ARGUMENTS is nonzero, all arguments must be
provided in ARGLIST, or else trailing parameters must have default
values. If REQUIRE_ALL_ARGUMENTS is zero, we will attempt argument
deduction for any unspecified trailing arguments. */
@@ -3781,9 +3977,9 @@ add_pending_template (d)
}
-/* 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. */
+/* Return a TEMPLATE_ID_EXPR corresponding to the indicated FNS and
+ ARGLIST. Valid choices for FNS are given in the cp-tree.def
+ documentation for TEMPLATE_ID_EXPR. */
tree
lookup_template_function (fns, arglist)
@@ -3791,20 +3987,36 @@ lookup_template_function (fns, arglist)
{
tree type;
+ if (fns == error_mark_node || arglist == error_mark_node)
+ return error_mark_node;
+
if (fns == NULL_TREE)
{
error ("non-template used as template");
return error_mark_node;
}
+ my_friendly_assert (TREE_CODE (fns) == TEMPLATE_DECL
+ || TREE_CODE (fns) == OVERLOAD
+ || BASELINK_P (fns)
+ || TREE_CODE (fns) == IDENTIFIER_NODE
+ || TREE_CODE (fns) == LOOKUP_EXPR,
+ 20020730);
+
+ if (BASELINK_P (fns))
+ {
+ BASELINK_FUNCTIONS (fns) = build (TEMPLATE_ID_EXPR,
+ unknown_type_node,
+ BASELINK_FUNCTIONS (fns),
+ arglist);
+ return fns;
+ }
+
type = TREE_TYPE (fns);
if (TREE_CODE (fns) == OVERLOAD || !type)
type = unknown_type_node;
-
- if (processing_template_decl)
- return build_min (TEMPLATE_ID_EXPR, type, fns, arglist);
- else
- return build (TEMPLATE_ID_EXPR, type, fns, arglist);
+
+ return build (TEMPLATE_ID_EXPR, type, fns, arglist);
}
/* Within the scope of a template class S<T>, the name S gets bound
@@ -3837,7 +4049,7 @@ maybe_get_template_decl_from_type_decl (decl)
IN_DECL, if non-NULL, is the template declaration we are trying to
instantiate.
- If ENTERING_SCOPE is non-zero, we are about to enter the scope of
+ If ENTERING_SCOPE is nonzero, we are about to enter the scope of
the class we are looking up.
Issue error and warning messages under control of COMPLAIN.
@@ -3857,6 +4069,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
tree template = NULL_TREE, parmlist;
tree t;
+ timevar_push (TV_NAME_LOOKUP);
if (TREE_CODE (d1) == IDENTIFIER_NODE)
{
if (IDENTIFIER_VALUE (d1)
@@ -3912,7 +4125,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
{
if (complain & tf_error)
error ("`%T' is not a template", d1);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (TREE_CODE (template) != TEMPLATE_DECL
@@ -3928,7 +4141,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
if (in_decl)
cp_error_at ("for template declaration `%D'", in_decl);
}
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
@@ -3963,10 +4176,10 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
arglist2 = coerce_template_parms (parmlist, arglist, template,
complain, /*require_all_args=*/1);
if (arglist2 == error_mark_node)
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
parm = bind_template_template_parm (TREE_TYPE (template), arglist2);
- return parm;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, parm);
}
else
{
@@ -4053,7 +4266,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
if (arglist == error_mark_node)
/* We were unable to bind the arguments. */
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
/* In the scope of a template class, explicit references to the
template class refer to the type of the template, not any
@@ -4090,7 +4303,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
}
}
if (found)
- return found;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
for (tp = &DECL_TEMPLATE_INSTANTIATIONS (template);
*tp;
@@ -4106,7 +4319,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
= DECL_TEMPLATE_INSTANTIATIONS (template);
DECL_TEMPLATE_INSTANTIATIONS (template) = found;
- return TREE_VALUE (found);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_VALUE (found));
}
/* This type is a "partial instantiation" if any of the template
@@ -4122,7 +4335,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
found = xref_tag_from_type (TREE_TYPE (template),
DECL_NAME (template),
/*globalize=*/1);
- return found;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
}
context = tsubst (DECL_CONTEXT (template), arglist,
@@ -4168,14 +4381,17 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
type_decl = create_implicit_typedef (DECL_NAME (template), t);
DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
TYPE_STUB_DECL (t) = type_decl;
- DECL_SOURCE_FILE (type_decl)
- = DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
- DECL_SOURCE_LINE (type_decl)
- = DECL_SOURCE_LINE (TYPE_STUB_DECL (template_type));
+ DECL_SOURCE_LOCATION (type_decl)
+ = DECL_SOURCE_LOCATION (TYPE_STUB_DECL (template_type));
}
else
type_decl = TYPE_NAME (t);
+ TREE_PRIVATE (type_decl)
+ = TREE_PRIVATE (TYPE_STUB_DECL (template_type));
+ TREE_PROTECTED (type_decl)
+ = TREE_PROTECTED (TYPE_STUB_DECL (template_type));
+
/* Set up the template information. We have to figure out which
template is the immediate parent if this is a full
instantiation. */
@@ -4275,14 +4491,16 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
code that generates debugging information will crash. */
DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
+ timevar_pop (TV_NAME_LOOKUP);
}
struct pair_fn_data
{
tree_fn_t fn;
void *data;
+ htab_t visited;
};
/* Called from for_each_template_parm via walk_tree. */
@@ -4297,9 +4515,20 @@ for_each_template_parm_r (tp, walk_subtrees, d)
struct pair_fn_data *pfd = (struct pair_fn_data *) d;
tree_fn_t fn = pfd->fn;
void *data = pfd->data;
-
+ void **slot;
+
+ /* If we have already visited this tree, there's no need to walk
+ subtrees. Otherwise, add it to the visited table. */
+ slot = htab_find_slot (pfd->visited, *tp, INSERT);
+ if (*slot)
+ {
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ }
+ *slot = *tp;
+
if (TYPE_P (t)
- && for_each_template_parm (TYPE_CONTEXT (t), fn, data))
+ && for_each_template_parm (TYPE_CONTEXT (t), fn, data, pfd->visited))
return error_mark_node;
switch (TREE_CODE (t))
@@ -4314,20 +4543,21 @@ for_each_template_parm_r (tp, walk_subtrees, d)
if (!TYPE_TEMPLATE_INFO (t))
*walk_subtrees = 0;
else if (for_each_template_parm (TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
- fn, data))
+ fn, data, pfd->visited))
return error_mark_node;
break;
case METHOD_TYPE:
/* Since we're not going to walk subtrees, we have to do this
explicitly here. */
- if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data))
+ if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data,
+ pfd->visited))
return error_mark_node;
/* Fall through. */
case FUNCTION_TYPE:
/* Check the return type. */
- if (for_each_template_parm (TREE_TYPE (t), fn, data))
+ if (for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited))
return error_mark_node;
/* Check the parameter types. Since default arguments are not
@@ -4340,7 +4570,8 @@ for_each_template_parm_r (tp, walk_subtrees, d)
tree parm;
for (parm = TYPE_ARG_TYPES (t); parm; parm = TREE_CHAIN (parm))
- if (for_each_template_parm (TREE_VALUE (parm), fn, data))
+ if (for_each_template_parm (TREE_VALUE (parm), fn, data,
+ pfd->visited))
return error_mark_node;
/* Since we've already handled the TYPE_ARG_TYPES, we don't
@@ -4352,20 +4583,22 @@ for_each_template_parm_r (tp, walk_subtrees, d)
case FUNCTION_DECL:
case VAR_DECL:
if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
- && for_each_template_parm (DECL_TI_ARGS (t), fn, data))
+ && for_each_template_parm (DECL_TI_ARGS (t), fn, data,
+ pfd->visited))
return error_mark_node;
/* Fall through. */
case CONST_DECL:
case PARM_DECL:
if (DECL_CONTEXT (t)
- && for_each_template_parm (DECL_CONTEXT (t), fn, data))
+ && for_each_template_parm (DECL_CONTEXT (t), fn, data,
+ pfd->visited))
return error_mark_node;
break;
case BOUND_TEMPLATE_TEMPLATE_PARM:
/* Record template parameters such as `T' inside `TT<T>'. */
- if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data))
+ if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data, pfd->visited))
return error_mark_node;
/* Fall through. */
@@ -4381,7 +4614,7 @@ for_each_template_parm_r (tp, walk_subtrees, d)
case TEMPLATE_DECL:
/* A template template parameter is encountered */
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)
- && for_each_template_parm (TREE_TYPE (t), fn, data))
+ && for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited))
return error_mark_node;
/* Already substituted template template parameter */
@@ -4389,14 +4622,17 @@ for_each_template_parm_r (tp, walk_subtrees, d)
break;
case TYPENAME_TYPE:
- if (!fn || for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), fn, data))
+ if (!fn
+ || for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), fn,
+ data, pfd->visited))
return error_mark_node;
break;
case CONSTRUCTOR:
if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))
&& for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE
- (TREE_TYPE (t)), fn, data))
+ (TREE_TYPE (t)), fn, data,
+ pfd->visited))
return error_mark_node;
break;
@@ -4423,6 +4659,16 @@ for_each_template_parm_r (tp, walk_subtrees, d)
return error_mark_node;
break;
+ case BASELINK:
+ /* If we do not handle this case specially, we end up walking
+ the BINFO hierarchy, which is circular, and therefore
+ confuses walk_tree. */
+ *walk_subtrees = 0;
+ if (for_each_template_parm (BASELINK_FUNCTIONS (*tp), fn, data,
+ pfd->visited))
+ return error_mark_node;
+ break;
+
default:
break;
}
@@ -4434,19 +4680,21 @@ for_each_template_parm_r (tp, walk_subtrees, d)
/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM,
BOUND_TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX in T,
call FN with the parameter and the DATA.
- If FN returns non-zero, the iteration is terminated, and
+ If FN returns nonzero, the iteration is terminated, and
for_each_template_parm returns 1. Otherwise, the iteration
- continues. If FN never returns a non-zero value, the value
+ continues. If FN never returns a nonzero value, the value
returned by for_each_template_parm is 0. If FN is NULL, it is
considered to be the function which always returns 1. */
static int
-for_each_template_parm (t, fn, data)
+for_each_template_parm (t, fn, data, visited)
tree t;
tree_fn_t fn;
void* data;
+ htab_t visited;
{
struct pair_fn_data pfd;
+ int result;
/* Set up. */
pfd.fn = fn;
@@ -4455,18 +4703,30 @@ for_each_template_parm (t, fn, data)
/* Walk the tree. (Conceptually, we would like to walk without
duplicates, but for_each_template_parm_r recursively calls
for_each_template_parm, so we would need to reorganize a fair
- bit to use walk_tree_without_duplicates.) */
- return walk_tree (&t,
- for_each_template_parm_r,
- &pfd,
- NULL) != NULL_TREE;
+ bit to use walk_tree_without_duplicates, so we keep our own
+ visited list.) */
+ if (visited)
+ pfd.visited = visited;
+ else
+ pfd.visited = htab_create (37, htab_hash_pointer, htab_eq_pointer,
+ NULL);
+ result = walk_tree (&t,
+ for_each_template_parm_r,
+ &pfd,
+ NULL) != NULL_TREE;
+
+ /* Clean up. */
+ if (!visited)
+ htab_delete (pfd.visited);
+
+ return result;
}
int
uses_template_parms (t)
tree t;
{
- return for_each_template_parm (t, 0, 0);
+ return for_each_template_parm (t, 0, 0, NULL);
}
static int tinst_depth;
@@ -4681,7 +4941,7 @@ tsubst_friend_function (decl, args)
/* Inside pushdecl_namespace_level, we will push into the
current namespace. However, the friend function should go
- into the namespace of the template. */
+ into the namespace of the template. */
ns = decl_namespace_context (new_friend);
push_nested_namespace (ns);
old_decl = pushdecl_namespace_level (new_friend);
@@ -4912,7 +5172,7 @@ tree
instantiate_class_template (type)
tree type;
{
- tree template, args, pattern, t;
+ tree template, args, pattern, t, member;
tree typedecl;
if (type == error_mark_node)
@@ -5007,7 +5267,8 @@ instantiate_class_template (type)
TYPE_BINFO_BASETYPES (type) = TYPE_BINFO_BASETYPES (pattern);
TYPE_FIELDS (type) = TYPE_FIELDS (pattern);
TYPE_METHODS (type) = TYPE_METHODS (pattern);
- CLASSTYPE_TAGS (type) = CLASSTYPE_TAGS (pattern);
+ CLASSTYPE_DECL_LIST (type) = CLASSTYPE_DECL_LIST (pattern);
+ CLASSTYPE_NESTED_UDTS (type) = CLASSTYPE_NESTED_UDTS (pattern);
CLASSTYPE_VBASECLASSES (type) = CLASSTYPE_VBASECLASSES (pattern);
/* Pretend that the type is complete, so that we will look
@@ -5028,7 +5289,7 @@ instantiate_class_template (type)
if (t)
{
- /* This TYPE is actually a instantiation of of a partial
+ /* This TYPE is actually an instantiation of a partial
specialization. We replace the innermost set of ARGS with
the arguments appropriate for substitution. For example,
given:
@@ -5101,6 +5362,10 @@ instantiate_class_template (type)
if (ANON_AGGR_TYPE_P (pattern))
SET_ANON_AGGR_TYPE_P (type);
+ if (DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (pattern)))
+ /* First instantiate our enclosing class. */
+ complete_type (TYPE_CONTEXT (type));
+
if (TYPE_BINFO_BASETYPES (pattern))
{
tree base_list = NULL_TREE;
@@ -5150,13 +5415,7 @@ instantiate_class_template (type)
/* Now call xref_basetypes to set up all the base-class
information. */
- xref_basetypes (TREE_CODE (pattern) == RECORD_TYPE
- ? (CLASSTYPE_DECLARED_CLASS (pattern)
- ? class_type_node : record_type_node)
- : union_type_node,
- DECL_NAME (TYPE_NAME (pattern)),
- type,
- base_list);
+ xref_basetypes (type, base_list);
}
/* Now that our base classes are set up, enter the scope of the
@@ -5166,175 +5425,170 @@ instantiate_class_template (type)
class. */
pushclass (type, 1);
- for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t))
+ /* Now members are processed in the order of declaration. */
+ for (member = CLASSTYPE_DECL_LIST (pattern); member; member = TREE_CHAIN (member))
{
- tree tag = TREE_VALUE (t);
- tree name = TYPE_IDENTIFIER (tag);
- tree newtag;
+ tree t = TREE_VALUE (member);
- newtag = tsubst (tag, args, tf_error, NULL_TREE);
- my_friendly_assert (newtag != error_mark_node, 20010206);
- if (TREE_CODE (newtag) != ENUMERAL_TYPE)
+ if (TREE_PURPOSE (member))
{
- if (TYPE_LANG_SPECIFIC (tag) && CLASSTYPE_IS_TEMPLATE (tag))
- /* Unfortunately, lookup_template_class sets
- CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
- instantiation (i.e., for the type of a member template
- class nested within a template class.) This behavior is
- required for maybe_process_partial_specialization to work
- correctly, but is not accurate in this case; the TAG is not
- an instantiation of anything. (The corresponding
- TEMPLATE_DECL is an instantiation, but the TYPE is not.) */
- CLASSTYPE_USE_TEMPLATE (newtag) = 0;
-
- /* Now, we call pushtag to put this NEWTAG into the scope of
- TYPE. We first set up the IDENTIFIER_TYPE_VALUE to avoid
- pushtag calling push_template_decl. We don't have to do
- this for enums because it will already have been done in
- tsubst_enum. */
- if (name)
- SET_IDENTIFIER_TYPE_VALUE (name, newtag);
- pushtag (name, newtag, /*globalize=*/0);
- }
- }
-
- /* Don't replace enum constants here. */
- for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
- if (TREE_CODE (t) != CONST_DECL)
- {
- tree r;
+ if (TYPE_P (t))
+ {
+ /* Build new CLASSTYPE_NESTED_UDTS. */
- /* The the file and line for this declaration, to assist in
- error message reporting. Since we called push_tinst_level
- above, we don't need to restore these. */
- lineno = DECL_SOURCE_LINE (t);
- input_filename = DECL_SOURCE_FILE (t);
+ tree tag = t;
+ tree name = TYPE_IDENTIFIER (tag);
+ tree newtag;
- r = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
- if (TREE_CODE (r) == VAR_DECL)
- {
- tree init;
+ newtag = tsubst (tag, args, tf_error, NULL_TREE);
+ my_friendly_assert (newtag != error_mark_node, 20010206);
+ if (TREE_CODE (newtag) != ENUMERAL_TYPE)
+ {
+ if (TYPE_LANG_SPECIFIC (tag) && CLASSTYPE_IS_TEMPLATE (tag))
+ /* Unfortunately, lookup_template_class sets
+ CLASSTYPE_IMPLICIT_INSTANTIATION for a partial
+ instantiation (i.e., for the type of a member template
+ class nested within a template class.) This behavior is
+ required for maybe_process_partial_specialization to work
+ correctly, but is not accurate in this case; the TAG is not
+ an instantiation of anything. (The corresponding
+ TEMPLATE_DECL is an instantiation, but the TYPE is not.) */
+ CLASSTYPE_USE_TEMPLATE (newtag) = 0;
+
+ /* Now, we call pushtag to put this NEWTAG into the scope of
+ TYPE. We first set up the IDENTIFIER_TYPE_VALUE to avoid
+ pushtag calling push_template_decl. We don't have to do
+ this for enums because it will already have been done in
+ tsubst_enum. */
+ if (name)
+ SET_IDENTIFIER_TYPE_VALUE (name, newtag);
+ pushtag (name, newtag, /*globalize=*/0);
+ }
+ }
+ else if (TREE_CODE (t) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (t))
+ {
+ /* Build new TYPE_METHODS. */
- if (DECL_INITIALIZED_IN_CLASS_P (r))
- init = tsubst_expr (DECL_INITIAL (t), args,
- tf_error | tf_warning, NULL_TREE);
- else
- init = NULL_TREE;
+ tree r = tsubst (t, args, tf_error, NULL_TREE);
+ set_current_access_from_decl (r);
+ grok_special_member_properties (r);
+ finish_member_declaration (r);
+ }
+ else
+ {
+ /* Build new TYPE_FIELDS. */
- finish_static_data_member_decl (r, init,
- /*asmspec_tree=*/NULL_TREE,
- /*flags=*/0);
+ if (TREE_CODE (t) != CONST_DECL)
+ {
+ tree r;
- if (DECL_INITIALIZED_IN_CLASS_P (r))
- check_static_variable_definition (r, TREE_TYPE (r));
- }
- else if (TREE_CODE (r) == FIELD_DECL)
- {
- /* Determine whether R has a valid type and can be
- completed later. If R is invalid, then it is replaced
- by error_mark_node so that it will not be added to
- TYPE_FIELDS. */
- tree rtype = TREE_TYPE (r);
- if (!can_complete_type_without_circularity (rtype))
- {
- incomplete_type_error (r, rtype);
- r = error_mark_node;
- }
- }
+ /* The the file and line for this declaration, to assist
+ in error message reporting. Since we called
+ push_tinst_level above, we don't need to restore these. */
+ lineno = DECL_SOURCE_LINE (t);
+ input_filename = DECL_SOURCE_FILE (t);
- /* R will have a TREE_CHAIN if and only if it has already been
- processed by finish_member_declaration. This can happen
- if, for example, it is a TYPE_DECL for a class-scoped
- ENUMERAL_TYPE; such a thing will already have been added to
- the field list by tsubst_enum above. */
- if (!TREE_CHAIN (r))
- {
- set_current_access_from_decl (r);
- finish_member_declaration (r);
- }
- }
+ r = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
+ if (TREE_CODE (r) == VAR_DECL)
+ {
+ tree init;
- /* Set up the list (TYPE_METHODS) and vector (CLASSTYPE_METHOD_VEC)
- for this instantiation. */
- for (t = TYPE_METHODS (pattern); t; t = TREE_CHAIN (t))
- {
- tree r = tsubst (t, args, tf_error, NULL_TREE);
- set_current_access_from_decl (r);
- grok_special_member_properties (r);
- finish_member_declaration (r);
- }
+ if (DECL_INITIALIZED_IN_CLASS_P (r))
+ init = tsubst_expr (DECL_INITIAL (t), args,
+ tf_error | tf_warning, NULL_TREE);
+ else
+ init = NULL_TREE;
- /* Construct the DECL_FRIENDLIST for the new class type. */
- typedecl = TYPE_MAIN_DECL (type);
- for (t = DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern));
- t != NULL_TREE;
- t = TREE_CHAIN (t))
- {
- tree friends;
-
- for (friends = TREE_VALUE (t);
- friends != NULL_TREE;
- friends = TREE_CHAIN (friends))
- if (TREE_PURPOSE (friends) == error_mark_node)
- add_friend (type,
- tsubst_friend_function (TREE_VALUE (friends),
- args));
- else
- abort ();
- }
+ finish_static_data_member_decl (r, init,
+ /*asmspec_tree=*/NULL_TREE,
+ /*flags=*/0);
- for (t = CLASSTYPE_FRIEND_CLASSES (pattern);
- t != NULL_TREE;
- t = TREE_CHAIN (t))
- {
- tree friend_type = TREE_VALUE (t);
- tree new_friend_type;
+ if (DECL_INITIALIZED_IN_CLASS_P (r))
+ check_static_variable_definition (r, TREE_TYPE (r));
+ }
+ else if (TREE_CODE (r) == FIELD_DECL)
+ {
+ /* Determine whether R has a valid type and can be
+ completed later. If R is invalid, then it is
+ replaced by error_mark_node so that it will not be
+ added to TYPE_FIELDS. */
+ tree rtype = TREE_TYPE (r);
+ if (can_complete_type_without_circularity (rtype))
+ complete_type (rtype);
+
+ if (!COMPLETE_TYPE_P (rtype))
+ {
+ cxx_incomplete_type_error (r, rtype);
+ r = error_mark_node;
+ }
+ }
- if (TREE_CODE (friend_type) == TEMPLATE_DECL)
- new_friend_type = tsubst_friend_class (friend_type, args);
- else if (uses_template_parms (friend_type))
- new_friend_type = tsubst (friend_type, args,
- tf_error | tf_warning, NULL_TREE);
- else
- {
- tree ns = decl_namespace_context (TYPE_MAIN_DECL (friend_type));
-
- /* The call to xref_tag_from_type does injection for friend
- classes. */
- push_nested_namespace (ns);
- new_friend_type =
- xref_tag_from_type (friend_type, NULL_TREE, 1);
- pop_nested_namespace (ns);
+ /* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
+ such a thing will already have been added to the field
+ list by tsubst_enum in finish_member_declaration in the
+ CLASSTYPE_NESTED_UDTS case above. */
+ if (!(TREE_CODE (r) == TYPE_DECL
+ && TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE
+ && DECL_ARTIFICIAL (r)))
+ {
+ set_current_access_from_decl (r);
+ finish_member_declaration (r);
+ }
+ }
+ }
}
+ else
+ {
+ if (TYPE_P (t) || DECL_CLASS_TEMPLATE_P (t))
+ {
+ /* Build new CLASSTYPE_FRIEND_CLASSES. */
+
+ tree friend_type = t;
+ tree new_friend_type;
- if (TREE_CODE (friend_type) == TEMPLATE_DECL)
- /* Trick make_friend_class into realizing that the friend
- we're adding is a template, not an ordinary class. It's
- important that we use make_friend_class since it will
- perform some error-checking and output cross-reference
- information. */
- ++processing_template_decl;
+ if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+ new_friend_type = tsubst_friend_class (friend_type, args);
+ else if (uses_template_parms (friend_type))
+ new_friend_type = tsubst (friend_type, args,
+ tf_error | tf_warning, NULL_TREE);
+ else
+ {
+ tree ns = decl_namespace_context (TYPE_MAIN_DECL (friend_type));
+
+ /* The call to xref_tag_from_type does injection for friend
+ classes. */
+ push_nested_namespace (ns);
+ new_friend_type =
+ xref_tag_from_type (friend_type, NULL_TREE, 1);
+ pop_nested_namespace (ns);
+ }
- if (new_friend_type != error_mark_node)
- make_friend_class (type, new_friend_type);
+ if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+ /* Trick make_friend_class into realizing that the friend
+ we're adding is a template, not an ordinary class. It's
+ important that we use make_friend_class since it will
+ perform some error-checking and output cross-reference
+ information. */
+ ++processing_template_decl;
- if (TREE_CODE (friend_type) == TEMPLATE_DECL)
- --processing_template_decl;
- }
+ if (new_friend_type != error_mark_node)
+ make_friend_class (type, new_friend_type);
- /* Now that TYPE_FIELDS and TYPE_METHODS are set up. We can
- instantiate templates used by this class. */
- for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
- if (TREE_CODE (t) == FIELD_DECL)
- {
- TREE_TYPE (t) = complete_type (TREE_TYPE (t));
- require_complete_type (t);
- }
+ if (TREE_CODE (friend_type) == TEMPLATE_DECL)
+ --processing_template_decl;
+ }
+ else
+ /* Build new DECL_FRIENDLIST. */
+ add_friend (type, tsubst_friend_function (t, args));
+ }
+ }
/* Set the file and line number information to whatever is given for
the class itself. This puts error messages involving generated
implicit functions at a predictable point, and the same point
that would be used for non-template classes. */
+ typedecl = TYPE_MAIN_DECL (type);
lineno = DECL_SOURCE_LINE (typedecl);
input_filename = DECL_SOURCE_FILE (typedecl);
@@ -5362,6 +5616,9 @@ instantiate_class_template (type)
pop_from_top_level ();
pop_tinst_level ();
+ if (TYPE_CONTAINS_VPTR_P (type))
+ keyed_classes = tree_cons (NULL_TREE, type, keyed_classes);
+
return type;
}
@@ -5506,7 +5763,7 @@ tsubst_template_parms (parms, args, complain)
/* Substitute the ARGS into the indicated aggregate (or enumeration)
type T. If T is not an aggregate or enumeration type, it is
handled as if by tsubst. IN_DECL is as for tsubst. If
- ENTERING_SCOPE is non-zero, T is the context for a template which
+ ENTERING_SCOPE is nonzero, T is the context for a template which
we are presently tsubst'ing. Return the substituted value. */
static tree
@@ -5592,15 +5849,19 @@ tsubst_default_argument (fn, type, arg)
};
we must be careful to do name lookup in the scope of S<T>,
- rather than in the current class. */
- if (DECL_CLASS_SCOPE_P (fn))
- pushclass (DECL_CONTEXT (fn), 2);
+ rather than in the current class.
+
+ ??? current_class_type affects a lot more than name lookup. This is
+ very fragile. Fortunately, it will go away when we do 2-phase name
+ binding properly. */
+
+ /* FN is already the desired FUNCTION_DECL. */
+ push_access_scope (fn);
arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
tf_error | tf_warning, NULL_TREE);
- if (DECL_CLASS_SCOPE_P (fn))
- popclass ();
+ pop_access_scope (fn);
/* Make sure the default argument is reasonable. */
arg = check_default_argument (type, arg);
@@ -5650,8 +5911,6 @@ tsubst_decl (t, args, type, complain)
tree r = NULL_TREE;
tree in_decl = t;
- my_friendly_assert (complain & tf_error, 20011214);
-
/* Set the filename and linenumber to improve error-reporting. */
saved_lineno = lineno;
saved_filename = input_filename;
@@ -5716,10 +5975,6 @@ tsubst_decl (t, args, type, complain)
= tsubst_aggr_type (DECL_CONTEXT (t), args,
complain, in_decl,
/*entering_scope=*/1);
- DECL_VIRTUAL_CONTEXT (r)
- = tsubst_aggr_type (DECL_VIRTUAL_CONTEXT (t), args,
- complain, in_decl,
- /*entering_scope=*/1);
DECL_TEMPLATE_INFO (r) = build_tree_list (t, args);
if (TREE_CODE (decl) == TYPE_DECL)
@@ -5746,7 +6001,7 @@ tsubst_decl (t, args, type, complain)
/* The template parameters for this new template are all the
template parameters for the old template, except the
- outermost level of parameters. */
+ outermost level of parameters. */
DECL_TEMPLATE_PARMS (r)
= tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,
complain);
@@ -5782,6 +6037,10 @@ tsubst_decl (t, args, type, complain)
{
tree spec;
+ /* If T is not dependent, just return it. */
+ if (!uses_template_parms (DECL_TI_ARGS (t)))
+ return t;
+
/* Calculate the most general template of which R is a
specialization, and the complete set of arguments used to
specialize R. */
@@ -5890,10 +6149,6 @@ tsubst_decl (t, args, type, complain)
SET_DECL_RTL (r, NULL_RTX);
DECL_CONTEXT (r) = ctx;
- DECL_VIRTUAL_CONTEXT (r)
- = tsubst_aggr_type (DECL_VIRTUAL_CONTEXT (t), args,
- complain, t,
- /*entering_scope=*/1);
if (member && DECL_CONV_FN_P (r))
/* Type-conversion operator. Reconstruct the name, in
@@ -5981,7 +6236,7 @@ tsubst_decl (t, args, type, complain)
r = copy_node (t);
if (DECL_TEMPLATE_PARM_P (t))
SET_DECL_TEMPLATE_PARM_P (r);
-
+
TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (cp_type_quals (type), r);
@@ -5992,10 +6247,9 @@ tsubst_decl (t, args, type, complain)
complain, in_decl);
DECL_CONTEXT (r) = NULL_TREE;
- if (!DECL_TEMPLATE_PARM_P (r) && PROMOTE_PROTOTYPES
- && INTEGRAL_TYPE_P (type)
- && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (r) = integer_type_node;
+
+ if (!DECL_TEMPLATE_PARM_P (r))
+ DECL_ARG_TYPE (r) = type_passed_as (type);
if (TREE_CHAIN (t))
TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args,
complain, TREE_CHAIN (t));
@@ -6102,7 +6356,10 @@ tsubst_decl (t, args, type, complain)
/* Even if the original location is out of scope, the newly
substituted one is not. */
if (TREE_CODE (r) == VAR_DECL)
- DECL_DEAD_FOR_LOCAL (r) = 0;
+ {
+ DECL_DEAD_FOR_LOCAL (r) = 0;
+ DECL_INITIALIZED_P (r) = 0;
+ }
if (!local_p)
{
@@ -6703,7 +6960,7 @@ tsubst (t, args, complain, in_decl)
}
if (TREE_CODE (type) == REFERENCE_TYPE)
{
- if (complain)
+ if (complain & tf_error)
error ("creating pointer to member reference type `%T'", type);
return error_mark_node;
@@ -6736,7 +6993,7 @@ tsubst (t, args, complain, in_decl)
if (fntype == error_mark_node)
return error_mark_node;
- /* Substitue the exception specification. */
+ /* Substitue the exception specification. */
raises = TYPE_RAISES_EXCEPTIONS (t);
if (raises)
{
@@ -6843,7 +7100,7 @@ tsubst (t, args, complain, in_decl)
if (!COMPLETE_TYPE_P (ctx))
{
if (complain & tf_error)
- incomplete_type_error (NULL_TREE, ctx);
+ cxx_incomplete_type_error (NULL_TREE, ctx);
return error_mark_node;
}
}
@@ -6931,7 +7188,10 @@ tsubst (t, args, complain, in_decl)
if (e1 == error_mark_node)
return error_mark_node;
- return TREE_TYPE (e1);
+ return cp_build_qualified_type_real (TREE_TYPE (e1),
+ cp_type_quals (t)
+ | cp_type_quals (TREE_TYPE (e1)),
+ complain);
}
default:
@@ -7330,22 +7590,14 @@ tsubst_expr (t, args, complain, in_decl)
break;
case CTOR_INITIALIZER:
- {
- tree member_init_list;
- tree base_init_list;
-
- prep_stmt (t);
- member_init_list
- = tsubst_initializer_list (TREE_OPERAND (t, 0), args);
- base_init_list
- = tsubst_initializer_list (TREE_OPERAND (t, 1), args);
- emit_base_init (member_init_list, base_init_list);
- break;
- }
+ prep_stmt (t);
+ finish_mem_initializers (tsubst_initializer_list
+ (TREE_OPERAND (t, 0), args));
+ break;
case RETURN_STMT:
prep_stmt (t);
- finish_return_stmt (tsubst_expr (RETURN_EXPR (t),
+ finish_return_stmt (tsubst_expr (RETURN_STMT_EXPR (t),
args, complain, in_decl));
break;
@@ -7405,7 +7657,7 @@ tsubst_expr (t, args, complain, in_decl)
/* For __PRETTY_FUNCTION__ we have to adjust the
initializer. */
const char *const name
- = (*decl_printable_name) (current_function_decl, 2);
+ = cxx_printable_name (current_function_decl, 2);
init = cp_fname_init (name);
TREE_TYPE (decl) = TREE_TYPE (init);
}
@@ -7417,7 +7669,7 @@ tsubst_expr (t, args, complain, in_decl)
}
/* A DECL_STMT can also be used as an expression, in the condition
- clause of a if/for/while construct. If we aren't followed by
+ clause of an if/for/while construct. If we aren't followed by
another statement, return our decl. */
if (TREE_CHAIN (t) == NULL_TREE)
return decl;
@@ -7632,10 +7884,6 @@ tsubst_expr (t, args, complain, in_decl)
tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
break;
- case CTOR_STMT:
- add_stmt (copy_node (t));
- break;
-
default:
abort ();
}
@@ -7667,7 +7915,7 @@ instantiate_template (tmpl, targ_ptr)
tree spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), targ_ptr);
tree clone;
- /* Look for the clone. */
+ /* Look for the clone. */
for (clone = TREE_CHAIN (spec);
clone && DECL_CLONED_FUNCTION_P (clone);
clone = TREE_CHAIN (clone))
@@ -7716,9 +7964,19 @@ instantiate_template (tmpl, targ_ptr)
}
}
+ /* Make sure that we can see identifiers, and compute access
+ correctly. The desired FUNCTION_DECL for FNDECL may or may not be
+ created earlier. Let push_access_scope_real figure that out. */
+ push_access_scope_real
+ (gen_tmpl, targ_ptr, tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr,
+ tf_error, gen_tmpl));
+
/* substitute template parameters */
fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
targ_ptr, tf_error, gen_tmpl);
+
+ pop_access_scope (gen_tmpl);
+
/* The DECL_TI_TEMPLATE should always be the immediate parent
template, not the most general template. */
DECL_TI_TEMPLATE (fndecl) = tmpl;
@@ -7789,7 +8047,7 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type,
int result;
my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
-
+
fntype = TREE_TYPE (fn);
if (explicit_targs)
{
@@ -7967,6 +8225,12 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
*parm = TREE_TYPE (*parm);
result |= UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
}
+
+ /* DR 322. For conversion deduction, remove a reference type on parm
+ too (which has been swapped into ARG). */
+ if (strict == DEDUCE_CONV && TREE_CODE (*arg) == REFERENCE_TYPE)
+ *arg = TREE_TYPE (*arg);
+
return result;
}
@@ -7995,8 +8259,7 @@ type_unification_real (tparms, targs, xparms, xargs, subr,
my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
my_friendly_assert (xparms == NULL_TREE
|| TREE_CODE (xparms) == TREE_LIST, 290);
- /* ARGS could be NULL (via a call from parse.y to
- build_x_function_call). */
+ /* ARGS could be NULL. */
if (xargs)
my_friendly_assert (TREE_CODE (xargs) == TREE_LIST, 291);
my_friendly_assert (ntparms > 0, 292);
@@ -8173,8 +8436,8 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
arg = TREE_OPERAND (arg, 1);
/* Strip baselink information. */
- while (TREE_CODE (arg) == TREE_LIST)
- arg = TREE_VALUE (arg);
+ if (BASELINK_P (arg))
+ arg = BASELINK_FUNCTIONS (arg);
if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
{
@@ -8205,7 +8468,8 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
}
}
}
- else if (TREE_CODE (arg) == OVERLOAD)
+ else if (TREE_CODE (arg) == OVERLOAD
+ || TREE_CODE (arg) == FUNCTION_DECL)
{
for (; arg; arg = OVL_NEXT (arg))
{
@@ -8332,29 +8596,12 @@ static int
verify_class_unification (targs, parms, args)
tree targs, parms, args;
{
- int i;
- int nparms = TREE_VEC_LENGTH (parms);
- tree new_parms = tsubst (parms, add_outermost_template_args (args, targs),
- tf_none, NULL_TREE);
- if (new_parms == error_mark_node)
+ parms = tsubst (parms, add_outermost_template_args (args, targs),
+ tf_none, NULL_TREE);
+ if (parms == error_mark_node)
return 1;
- args = INNERMOST_TEMPLATE_ARGS (args);
-
- for (i = 0; i < nparms; i++)
- {
- tree parm = TREE_VEC_ELT (new_parms, i);
- tree arg = TREE_VEC_ELT (args, i);
-
- /* In case we are deducing from a function argument of a function
- templates, some parameters may not be deduced yet. So we
- make sure that only fully substituted elements of PARM are
- compared below. */
-
- if (!uses_template_parms (parm) && !template_args_equal (parm, arg))
- return 1;
- }
- return 0;
+ return !comp_template_args (parms, INNERMOST_TEMPLATE_ARGS (args));
}
/* PARM is a template class (perhaps with unbound template
@@ -8372,7 +8619,8 @@ try_class_unification (tparms, targs, parm, arg)
tree copy_of_targs;
if (!CLASSTYPE_TEMPLATE_INFO (arg)
- || CLASSTYPE_TI_TEMPLATE (arg) != CLASSTYPE_TI_TEMPLATE (parm))
+ || (most_general_template (CLASSTYPE_TI_TEMPLATE (arg))
+ != most_general_template (CLASSTYPE_TI_TEMPLATE (parm))))
return NULL_TREE;
/* We need to make a new template argument vector for the call to
@@ -8401,7 +8649,7 @@ try_class_unification (tparms, targs, parm, arg)
Now, by the time we consider the unification involving `s2', we
already know that we must have `f<0, 0, 0>'. But, even though
- `S<0, 1, 2>' is derived from `S<0, 0, 0>', the code is not legal
+ `S<0, 1, 2>' is derived from `S<0, 0, 0>', the code is invalid
because there are two ways to unify base classes of S<0, 1, 2>
with S<I, I, I>. If we kept the already deduced knowledge, we
would reject the possibility I=1. */
@@ -8543,7 +8791,7 @@ template_decl_level (decl)
/* Decide whether ARG can be unified with PARM, considering only the
cv-qualifiers of each type, given STRICT as documented for unify.
- Returns non-zero iff the unification is OK on that basis.*/
+ Returns nonzero iff the unification is OK on that basis.*/
static int
check_cv_quals_for_unify (strict, arg, parm)
@@ -8763,6 +9011,12 @@ unify (tparms, targs, parm, arg, strict)
}
else
{
+ /* If ARG is an offset type, we're trying to unify '*T' with
+ 'U C::*', which is ill-formed. See the comment in the
+ POINTER_TYPE case about this ugliness. */
+ if (TREE_CODE (arg) == OFFSET_TYPE)
+ return 1;
+
/* If PARM is `const T' and ARG is only `int', we don't have
a match unless we are allowing additional qualification.
If ARG is `const int' and PARM is just `T' that's OK;
@@ -8831,8 +9085,12 @@ unify (tparms, targs, parm, arg, strict)
deduced from an array bound may be of any integral type.
The non-type parameter might use already deduced type parameters. */
tparm = tsubst (TREE_TYPE (parm), targs, 0, NULL_TREE);
- if (same_type_p (TREE_TYPE (arg), tparm))
- /* OK */;
+ if (!TREE_TYPE (arg))
+ /* Template-parameter dependent expression. Just accept it for now.
+ It will later be processed in convert_template_argument. */
+ ;
+ else if (same_type_p (TREE_TYPE (arg), tparm))
+ /* OK */;
else if ((strict & UNIFY_ALLOW_INTEGER)
&& (TREE_CODE (tparm) == INTEGER_TYPE
|| TREE_CODE (tparm) == BOOLEAN_TYPE))
@@ -8872,7 +9130,7 @@ unify (tparms, targs, parm, arg, strict)
{
/* Avoid getting confused about cv-quals; don't recurse here.
Pointers to members should really be just OFFSET_TYPE, not
- this two-level nonsense... */
+ this two-level nonsense... */
parm = TREE_TYPE (parm);
arg = TREE_TYPE (arg);
@@ -8900,7 +9158,7 @@ unify (tparms, targs, parm, arg, strict)
TYPE_DOMAIN (arg), UNIFY_ALLOW_NONE) != 0)
return 1;
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
- UNIFY_ALLOW_NONE);
+ strict & UNIFY_ALLOW_MORE_CV_QUAL);
case REAL_TYPE:
case COMPLEX_TYPE:
@@ -9117,11 +9375,6 @@ mark_decl_instantiated (result, extern_p)
tree result;
int extern_p;
{
- if (TREE_CODE (result) != FUNCTION_DECL)
- /* The TREE_PUBLIC flag for function declarations will have been
- set correctly by tsubst. */
- TREE_PUBLIC (result) = 1;
-
/* We used to set this unconditionally; we moved that to
do_decl_instantiation so it wouldn't get set on members of
explicit class template instantiations. But we still need to set
@@ -9130,6 +9383,19 @@ mark_decl_instantiated (result, extern_p)
if (extern_p)
SET_DECL_EXPLICIT_INSTANTIATION (result);
+ /* If this entity has already been written out, it's too late to
+ make any modifications. */
+ if (TREE_ASM_WRITTEN (result))
+ return;
+
+ if (TREE_CODE (result) != FUNCTION_DECL)
+ /* The TREE_PUBLIC flag for function declarations will have been
+ set correctly by tsubst. */
+ TREE_PUBLIC (result) = 1;
+
+ /* This might have been set by an earlier implicit instantiation. */
+ DECL_COMDAT (result) = 0;
+
if (! extern_p)
{
DECL_INTERFACE_KNOWN (result) = 1;
@@ -9143,7 +9409,8 @@ mark_decl_instantiated (result, extern_p)
else if (TREE_PUBLIC (result))
maybe_make_one_only (result);
}
- else if (TREE_CODE (result) == FUNCTION_DECL)
+
+ if (TREE_CODE (result) == FUNCTION_DECL)
defer_fn (result);
}
@@ -9234,7 +9501,7 @@ get_bindings_real (fn, decl, explicit_args, check_rettype, deduce, len)
if (DECL_TEMPLATE_INFO (decl))
tmpl = DECL_TI_TEMPLATE (decl);
else
- /* We can get here for some illegal specializations. */
+ /* We can get here for some invalid specializations. */
return NULL_TREE;
converted_args
@@ -9434,6 +9701,10 @@ most_general_template (decl)
if (TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL)
break;
+ if (CLASS_TYPE_P (TREE_TYPE (decl))
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+ break;
+
/* Stop if we run into an explicitly specialized class template. */
if (!DECL_NAMESPACE_SCOPE_P (decl)
&& DECL_CONTEXT (decl)
@@ -9505,13 +9776,11 @@ most_specialized_class (tmpl, args)
return champ;
}
-/* called from the parser. */
+/* Explicitly instantiate DECL. */
void
-do_decl_instantiation (declspecs, declarator, storage)
- tree declspecs, declarator, storage;
+do_decl_instantiation (tree decl, tree storage)
{
- tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL);
tree result = NULL_TREE;
int extern_p = 0;
@@ -9550,7 +9819,7 @@ do_decl_instantiation (declspecs, declarator, storage)
result = decl;
/* Check for various error cases. Note that if the explicit
- instantiation is legal the RESULT will currently be marked as an
+ instantiation is valid the RESULT will currently be marked as an
*implicit* instantiation; DECL_EXPLICIT_INSTANTIATION is not set
until we get here. */
@@ -9635,9 +9904,21 @@ mark_class_instantiated (t, extern_p)
}
}
+/* Called from do_type_instantiation through binding_table_foreach to
+ do recursive instantiation for the type bound in ENTRY. */
+static void
+bt_instantiate_type_proc (binding_entry entry, void *data)
+{
+ tree storage = *(tree *) data;
+
+ if (IS_AGGR_TYPE (entry->type)
+ && !uses_template_parms (CLASSTYPE_TI_ARGS (entry->type)))
+ do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0);
+}
+
/* Perform an explicit instantiation of template class T. STORAGE, if
non-null, is the RID for extern, inline or static. COMPLAIN is
- non-zero if this is called from the parser, zero if called recursively,
+ nonzero if this is called from the parser, zero if called recursively,
since the standard is unclear (as detailed below). */
void
@@ -9775,10 +10056,9 @@ do_type_instantiation (t, storage, complain)
instantiate_decl (tmp, /*defer_ok=*/1);
}
- for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
- if (IS_AGGR_TYPE (TREE_VALUE (tmp))
- && !uses_template_parms (CLASSTYPE_TI_ARGS (TREE_VALUE (tmp))))
- do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage, 0);
+ if (CLASSTYPE_NESTED_UDTS (t))
+ binding_table_foreach (CLASSTYPE_NESTED_UDTS (t),
+ bt_instantiate_type_proc, &storage);
}
}
@@ -9825,6 +10105,7 @@ regenerate_decl_from_template (decl, tmpl)
instantiation of a specialization, which it isn't: it's a full
instantiation. */
gen_tmpl = most_general_template (tmpl);
+ push_access_scope_real (gen_tmpl, args, DECL_CONTEXT (decl));
unregistered = unregister_specialization (decl, gen_tmpl);
/* If the DECL was not unregistered then something peculiar is
@@ -9832,11 +10113,6 @@ regenerate_decl_from_template (decl, tmpl)
register_specialization for it. */
my_friendly_assert (unregistered, 0);
- if (TREE_CODE (decl) == VAR_DECL)
- /* Make sure that we can see identifiers, and compute access
- correctly, for the class members used in the declaration of
- this static variable. */
- pushclass (DECL_CONTEXT (decl), 2);
/* Do the substitution to get the new declaration. */
new_decl = tsubst (code_pattern, args, tf_error, NULL_TREE);
@@ -9844,11 +10120,10 @@ regenerate_decl_from_template (decl, tmpl)
if (TREE_CODE (decl) == VAR_DECL)
{
/* Set up DECL_INITIAL, since tsubst doesn't. */
- DECL_INITIAL (new_decl) =
- tsubst_expr (DECL_INITIAL (code_pattern), args,
- tf_error, DECL_TI_TEMPLATE (decl));
- /* Pop the class context we pushed above. */
- popclass ();
+ if (!DECL_INITIALIZED_IN_CLASS_P (decl))
+ DECL_INITIAL (new_decl) =
+ tsubst_expr (DECL_INITIAL (code_pattern), args,
+ tf_error, DECL_TI_TEMPLATE (decl));
}
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
@@ -9859,6 +10134,8 @@ regenerate_decl_from_template (decl, tmpl)
DECL_INITIAL (decl) = NULL_TREE;
}
+ pop_access_scope (decl);
+
/* The immediate parent of the new template is still whatever it was
before, even though tsubst sets DECL_TI_TEMPLATE up as the most
general template. We also reset the DECL_ASSEMBLER_NAME since
@@ -9879,7 +10156,7 @@ regenerate_decl_from_template (decl, tmpl)
}
/* Produce the definition of D, a _DECL generated from a template. If
- DEFER_OK is non-zero, then we don't have to actually do the
+ DEFER_OK is nonzero, then we don't have to actually do the
instantiation now; we just have to do it sometime. */
tree
@@ -9888,7 +10165,8 @@ instantiate_decl (d, defer_ok)
int defer_ok;
{
tree tmpl = DECL_TI_TEMPLATE (d);
- tree args = DECL_TI_ARGS (d);
+ tree gen_args;
+ tree args;
tree td;
tree code_pattern;
tree spec;
@@ -9903,6 +10181,9 @@ instantiate_decl (d, defer_ok)
my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
|| TREE_CODE (d) == VAR_DECL, 0);
+ if (TREE_CODE (d) == VAR_DECL)
+ defer_ok = 0;
+
/* Don't instantiate cloned functions. Instead, instantiate the
functions they cloned. */
if (TREE_CODE (d) == FUNCTION_DECL && DECL_CLONED_FUNCTION_P (d))
@@ -9922,7 +10203,8 @@ instantiate_decl (d, defer_ok)
specializations, so we must explicitly check
DECL_TEMPLATE_SPECIALIZATION. */
gen_tmpl = most_general_template (tmpl);
- spec = retrieve_specialization (gen_tmpl, args);
+ gen_args = DECL_TI_ARGS (d);
+ spec = retrieve_specialization (gen_tmpl, gen_args);
if (spec != NULL_TREE && DECL_TEMPLATE_SPECIALIZATION (spec))
return spec;
@@ -9983,6 +10265,16 @@ instantiate_decl (d, defer_ok)
code_pattern = DECL_TEMPLATE_RESULT (td);
+ if ((DECL_NAMESPACE_SCOPE_P (d) && !DECL_INITIALIZED_IN_CLASS_P (d))
+ || DECL_TEMPLATE_SPECIALIZATION (td))
+ /* In the case of a friend template whose definition is provided
+ outside the class, we may have too many arguments. Drop the
+ ones we don't need. The same is true for specializations. */
+ args = get_innermost_template_args
+ (gen_args, TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (td)));
+ else
+ args = gen_args;
+
if (TREE_CODE (d) == FUNCTION_DECL)
pattern_defined = (DECL_SAVED_TREE (code_pattern) != NULL_TREE);
else
@@ -10040,18 +10332,25 @@ instantiate_decl (d, defer_ok)
tree gen = DECL_TEMPLATE_RESULT (gen_tmpl);
tree type = TREE_TYPE (gen);
+ /* Make sure that we can see identifiers, and compute access
+ correctly. D is already the target FUNCTION_DECL with the
+ right context. */
+ push_access_scope (d);
+
if (TREE_CODE (gen) == FUNCTION_DECL)
{
- tsubst (DECL_ARGUMENTS (gen), args, tf_error | tf_warning, d);
- tsubst (TYPE_RAISES_EXCEPTIONS (type), args,
+ tsubst (DECL_ARGUMENTS (gen), gen_args, tf_error | tf_warning, d);
+ tsubst (TYPE_RAISES_EXCEPTIONS (type), gen_args,
tf_error | tf_warning, d);
/* Don't simply tsubst the function type, as that will give
duplicate warnings about poor parameter qualifications.
The function arguments are the same as the decl_arguments
- without the top level cv qualifiers. */
+ without the top level cv qualifiers. */
type = TREE_TYPE (type);
}
- tsubst (type, args, tf_error | tf_warning, d);
+ tsubst (type, gen_args, tf_error | tf_warning, d);
+
+ pop_access_scope (d);
}
if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d)
@@ -10092,15 +10391,10 @@ instantiate_decl (d, defer_ok)
if (need_push)
push_to_top_level ();
- /* We're now committed to instantiating this template. Mark it as
- instantiated so that recursive calls to instantiate_decl do not
- try to instantiate it again. */
- DECL_TEMPLATE_INSTANTIATED (d) = 1;
-
/* Regenerate the declaration in case the template has been modified
by a subsequent redeclaration. */
regenerate_decl_from_template (d, td);
-
+
/* We already set the file and line above. Reset them now in case
they changed as a result of calling regenerate_decl_from_template. */
lineno = DECL_SOURCE_LINE (d);
@@ -10108,20 +10402,52 @@ instantiate_decl (d, defer_ok)
if (TREE_CODE (d) == VAR_DECL)
{
+ /* Clear out DECL_RTL; whatever was there before may not be right
+ since we've reset the type of the declaration. */
+ SET_DECL_RTL (d, NULL_RTX);
+
DECL_IN_AGGR_P (d) = 0;
- if (DECL_INTERFACE_KNOWN (d))
- DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
+ import_export_decl (d);
+ DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
+
+ if (DECL_EXTERNAL (d))
+ {
+ /* The fact that this code is executing indicates that:
+
+ (1) D is a template static data member, for which a
+ definition is available.
+
+ (2) An implicit or explicit instantiation has occured.
+
+ (3) We are not going to emit a definition of the static
+ data member at this time.
+
+ This situation is peculiar, but it occurs on platforms
+ without weak symbols when performing an implicit
+ instantiation. There, we cannot implicitly instantiate a
+ defined static data member in more than one translation
+ unit, so import_export_decl marks the declaration as
+ external; we must rely on explicit instantiation. */
+ }
else
{
- DECL_EXTERNAL (d) = 1;
- DECL_NOT_REALLY_EXTERN (d) = 1;
+ /* Mark D as instantiated so that recursive calls to
+ instantiate_decl do not try to instantiate it again. */
+ DECL_TEMPLATE_INSTANTIATED (d) = 1;
+ cp_finish_decl (d,
+ (!DECL_INITIALIZED_IN_CLASS_P (d)
+ ? DECL_INITIAL (d) : NULL_TREE),
+ NULL_TREE, 0);
}
- cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0);
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{
htab_t saved_local_specializations;
+ /* Mark D as instantiated so that recursive calls to
+ instantiate_decl do not try to instantiate it again. */
+ DECL_TEMPLATE_INSTANTIATED (d) = 1;
+
/* Save away the current list, in case we are instantiating one
template from within the body of another. */
saved_local_specializations = local_specializations;
@@ -10133,6 +10459,7 @@ instantiate_decl (d, defer_ok)
NULL);
/* Set up context. */
+ import_export_decl (d);
start_function (NULL_TREE, d, NULL_TREE, SF_PRE_PARSED);
/* Substitute into the body of the function. */
@@ -10144,7 +10471,8 @@ instantiate_decl (d, defer_ok)
local_specializations = saved_local_specializations;
/* Finish the function. */
- expand_body (finish_function (0));
+ d = finish_function (0);
+ expand_body (d);
}
/* We're not deferring instantiation any more. */
@@ -10260,8 +10588,7 @@ static tree
tsubst_initializer_list (t, argvec)
tree t, argvec;
{
- tree first = NULL_TREE;
- tree *p = &first;
+ tree inits = NULL_TREE;
for (; t; t = TREE_CHAIN (t))
{
@@ -10271,23 +10598,30 @@ tsubst_initializer_list (t, argvec)
decl = tsubst_copy (TREE_PURPOSE (t), argvec, tf_error | tf_warning,
NULL_TREE);
+ decl = expand_member_init (decl);
+ if (decl && !DECL_P (decl))
+ in_base_initializer = 1;
+
init = tsubst_expr (TREE_VALUE (t), argvec, tf_error | tf_warning,
NULL_TREE);
-
if (!init)
;
else if (TREE_CODE (init) == TREE_LIST)
for (val = init; val; val = TREE_CHAIN (val))
TREE_VALUE (val) = convert_from_reference (TREE_VALUE (val));
- else
+ else if (init != void_type_node)
init = convert_from_reference (init);
- *p = expand_member_init (current_class_ref, decl,
- init ? init : void_type_node);
- if (*p)
- p = &TREE_CHAIN (*p);
+ in_base_initializer = 0;
+
+ if (decl)
+ {
+ init = build_tree_list (decl, init);
+ TREE_CHAIN (init) = inits;
+ inits = init;
+ }
}
- return first;
+ return inits;
}
/* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */
@@ -10334,25 +10668,19 @@ tsubst_enum (tag, newtag, args)
}
finish_enum (newtag);
- DECL_SOURCE_LINE (TYPE_NAME (newtag)) = DECL_SOURCE_LINE (TYPE_NAME (tag));
- DECL_SOURCE_FILE (TYPE_NAME (newtag)) = DECL_SOURCE_FILE (TYPE_NAME (tag));
+ DECL_SOURCE_LOCATION (TYPE_NAME (newtag))
+ = DECL_SOURCE_LOCATION (TYPE_NAME (tag));
}
/* DECL is a FUNCTION_DECL that is a template specialization. Return
its type -- but without substituting the innermost set of template
arguments. So, innermost set of template parameters will appear in
- the type. If CONTEXTP is non-NULL, then the partially substituted
- DECL_CONTEXT (if any) will also be filled in. Similarly, TPARMSP
- will be filled in with the substituted template parameters, if it
- is non-NULL. */
+ the type. */
tree
-get_mostly_instantiated_function_type (decl, contextp, tparmsp)
+get_mostly_instantiated_function_type (decl)
tree decl;
- tree *contextp;
- tree *tparmsp;
{
- tree context = NULL_TREE;
tree fn_type;
tree tmpl;
tree targs;
@@ -10369,8 +10697,6 @@ get_mostly_instantiated_function_type (decl, contextp, tparmsp)
my_friendly_assert (parm_depth == TMPL_ARGS_DEPTH (targs), 0);
fn_type = TREE_TYPE (tmpl);
- if (DECL_STATIC_FUNCTION_P (decl))
- context = DECL_CONTEXT (decl);
if (parm_depth == 1)
/* No substitution is necessary. */
@@ -10390,11 +10716,16 @@ get_mostly_instantiated_function_type (decl, contextp, tparmsp)
TMPL_ARGS_DEPTH (targs),
make_tree_vec (DECL_NTPARMS (tmpl)));
+ /* Make sure that we can see identifiers, and compute access
+ correctly. We can just use the context of DECL for the
+ partial substitution here. It depends only on outer template
+ parameters, regardless of whether the innermost level is
+ specialized or not. */
+ push_access_scope (decl);
+
/* Now, do the (partial) substitution to figure out the
appropriate function type. */
fn_type = tsubst (fn_type, partial_args, tf_error, NULL_TREE);
- if (DECL_STATIC_FUNCTION_P (decl))
- context = tsubst (context, partial_args, tf_error, NULL_TREE);
/* Substitute into the template parameters to obtain the real
innermost set of parameters. This step is important if the
@@ -10402,12 +10733,9 @@ get_mostly_instantiated_function_type (decl, contextp, tparmsp)
parameters whose types depend on outer template parameters. */
TREE_VEC_LENGTH (partial_args)--;
tparms = tsubst_template_parms (tparms, partial_args, tf_error);
- }
- if (contextp)
- *contextp = context;
- if (tparmsp)
- *tparmsp = tparms;
+ pop_access_scope (decl);
+ }
return fn_type;
}
@@ -10434,7 +10762,7 @@ current_instantiation ()
}
/* [temp.param] Check that template non-type parm TYPE is of an allowable
- type. Return zero for ok, non-zero for disallowed. Issue error and
+ type. Return zero for ok, nonzero for disallowed. Issue error and
warning messages under control of COMPLAIN. */
static int
@@ -10460,3 +10788,5 @@ invalid_nontype_parm_type_p (type, complain)
type);
return 1;
}
+
+#include "gt-cp-pt.h"
diff --git a/contrib/gcc/cp/ptree.c b/contrib/gcc/cp/ptree.c
index f40e412..6a7b26c 100644
--- a/contrib/gcc/cp/ptree.c
+++ b/contrib/gcc/cp/ptree.c
@@ -157,15 +157,23 @@ cxx_print_type (file, node, indent)
}
}
+static void
+cxx_print_binding (FILE *stream, cxx_binding *binding, const char *prefix)
+{
+ fprintf (stream, "%s <", prefix);
+ fprintf (stream, HOST_PTR_PRINTF, (char *) binding);
+ fprintf (stream, ">");
+}
+
void
cxx_print_identifier (file, node, indent)
FILE *file;
tree node;
int indent;
{
- print_node (file, "bindings", IDENTIFIER_NAMESPACE_BINDINGS (node), indent + 4);
+ cxx_print_binding (file, IDENTIFIER_NAMESPACE_BINDINGS (node), "bindings");
print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4);
- print_node (file, "local bindings", IDENTIFIER_BINDING (node), indent + 4);
+ cxx_print_binding (file, IDENTIFIER_BINDING (node), "local bindings");
print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
@@ -180,12 +188,6 @@ cxx_print_xnode (file, node, indent)
{
switch (TREE_CODE (node))
{
- case CPLUS_BINDING:
- fprintf (file, " scope ");
- fprintf (file, HOST_PTR_PRINTF, BINDING_SCOPE (node));
- print_node (file, "value", BINDING_VALUE (node), indent+4);
- print_node (file, "chain", TREE_CHAIN (node), indent+4);
- break;
case OVERLOAD:
print_node (file, "function", OVL_FUNCTION (node), indent+4);
print_node (file, "chain", TREE_CHAIN (node), indent+4);
diff --git a/contrib/gcc/cp/repo.c b/contrib/gcc/cp/repo.c
index fe2eb62..64c6ec87 100644
--- a/contrib/gcc/cp/repo.c
+++ b/contrib/gcc/cp/repo.c
@@ -42,15 +42,14 @@ static void open_repo_file PARAMS ((const char *));
static char *afgets PARAMS ((FILE *));
static void reopen_repo_file_for_write PARAMS ((void));
-static tree pending_repo;
-static tree original_repo;
+static GTY(()) tree pending_repo;
+static GTY(()) tree original_repo;
static char *repo_name;
static FILE *repo_file;
-static char *old_args, *old_dir, *old_main;
+static const char *old_args, *old_dir, *old_main;
static struct obstack temporary_obstack;
-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))
@@ -292,8 +291,9 @@ open_repo_file (filename)
if (! p)
p = s + strlen (s);
- obstack_grow (&permanent_obstack, s, p - s);
- repo_name = obstack_copy0 (&permanent_obstack, ".rpo", 4);
+ repo_name = xmalloc (p - s + 5);
+ memcpy (repo_name, s, p - s);
+ memcpy (repo_name + (p - s), ".rpo", 5);
repo_file = fopen (repo_name, "r");
}
@@ -320,8 +320,6 @@ init_repo (filename)
if (! flag_use_repository)
return;
- ggc_add_tree_root (&pending_repo, 1);
- ggc_add_tree_root (&original_repo, 1);
gcc_obstack_init (&temporary_obstack);
open_repo_file (filename);
@@ -334,16 +332,13 @@ init_repo (filename)
switch (buf[0])
{
case 'A':
- old_args = obstack_copy0 (&permanent_obstack, buf + 2,
- strlen (buf + 2));
+ old_args = ggc_strdup (buf + 2);
break;
case 'D':
- old_dir = obstack_copy0 (&permanent_obstack, buf + 2,
- strlen (buf + 2));
+ old_dir = ggc_strdup (buf + 2);
break;
case 'M':
- old_main = obstack_copy0 (&permanent_obstack, buf + 2,
- strlen (buf + 2));
+ old_main = ggc_strdup (buf + 2);
break;
case 'C':
case 'O':
@@ -458,3 +453,5 @@ finish_repo ()
if (repo_file)
fclose (repo_file);
}
+
+#include "gt-cp-repo.h"
diff --git a/contrib/gcc/cp/rtti.c b/contrib/gcc/cp/rtti.c
index fbb37fe..7b4a248 100644
--- a/contrib/gcc/cp/rtti.c
+++ b/contrib/gcc/cp/rtti.c
@@ -62,13 +62,13 @@ Boston, MA 02111-1307, USA. */
/* Accessors for the type_info objects. We need to remember several things
about each of the type_info types. The global tree nodes such as
bltn_desc_type_node are TREE_LISTs, and these macros are used to access
- the required information. */
-/* The RECORD_TYPE of a type_info derived class. */
+ the required information. */
+/* The RECORD_TYPE of a type_info derived class. */
#define TINFO_PSEUDO_TYPE(NODE) TREE_TYPE (NODE)
/* The VAR_DECL of the vtable for the type_info derived class.
- This is only filled in at the end of the translation. */
+ This is only filled in at the end of the translation. */
#define TINFO_VTABLE_DECL(NODE) TREE_VALUE (NODE)
-/* The IDENTIFIER_NODE naming the real class. */
+/* The IDENTIFIER_NODE naming the real class. */
#define TINFO_REAL_NAME(NODE) TREE_PURPOSE (NODE)
static tree build_headof PARAMS((tree));
@@ -109,8 +109,9 @@ void
init_rtti_processing ()
{
push_namespace (std_identifier);
- type_info_type_node = xref_tag
- (class_type_node, get_identifier ("type_info"), 1);
+ type_info_type_node
+ = xref_tag (class_type, get_identifier ("type_info"),
+ /*attributes=*/NULL_TREE, 1);
pop_namespace ();
type_info_ptr_type =
build_pointer_type
@@ -142,7 +143,7 @@ build_headof (exp)
exp = save_expr (exp);
/* The offset-to-top field is at index -2 from the vptr. */
- index = build_int_2 (-2, -1);
+ index = build_int_2 (-2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE, -1);
offset = build_vtbl_ref (build_indirect_ref (exp, NULL), index);
@@ -166,7 +167,7 @@ throw_bad_cast ()
fn = push_throw_library_fn (fn, build_function_type (ptr_type_node,
void_list_node));
- return build_call (fn, NULL_TREE);
+ return build_cxx_call (fn, NULL_TREE, NULL_TREE);
}
static tree
@@ -182,7 +183,7 @@ throw_bad_typeid ()
fn = push_throw_library_fn (fn, t);
}
- return build_call (fn, NULL_TREE);
+ return build_cxx_call (fn, NULL_TREE, NULL_TREE);
}
/* Return a pointer to type_info function associated with the expression EXP.
@@ -221,7 +222,7 @@ get_tinfo_decl_dynamic (exp)
tree index;
/* The RTTI information is at index -1. */
- index = integer_minus_one_node;
+ index = build_int_2 (-1 * TARGET_VTABLE_DATA_ENTRY_DISTANCE, -1);
t = build_vtbl_ref (exp, index);
TREE_TYPE (t) = type_info_ptr_type;
return t;
@@ -298,7 +299,7 @@ tinfo_name (type)
tree name_string;
name = mangle_type_string (type);
- name_string = combine_strings (build_string (strlen (name) + 1, name));
+ name_string = fix_string_type (build_string (strlen (name) + 1, name));
return name_string;
}
@@ -351,9 +352,8 @@ get_tinfo_decl (type)
DECL_EXTERNAL (d) = 1;
SET_DECL_ASSEMBLER_NAME (d, name);
DECL_COMDAT (d) = 1;
- cp_finish_decl (d, NULL_TREE, NULL_TREE, 0);
- pushdecl_top_level (d);
+ pushdecl_top_level_and_finish (d, NULL_TREE);
if (CLASS_TYPE_P (type))
CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d;
@@ -633,8 +633,9 @@ build_dynamic_cast_1 (type, expr)
const char *name;
push_nested_namespace (ns);
- tinfo_ptr = xref_tag (class_type_node,
+ tinfo_ptr = xref_tag (class_type,
get_identifier ("__class_type_info"),
+ /*attributes=*/NULL_TREE,
1);
tinfo_ptr = build_pointer_type
@@ -651,7 +652,7 @@ build_dynamic_cast_1 (type, expr)
pop_nested_namespace (ns);
dynamic_cast_node = dcast_fn;
}
- result = build_call (dcast_fn, elems);
+ result = build_cxx_call (dcast_fn, elems, elems);
if (tc == REFERENCE_TYPE)
{
@@ -695,8 +696,7 @@ qualifier_flags (type)
tree type;
{
int flags = 0;
- /* we want the qualifiers on this type, not any array core, it might have */
- int quals = TYPE_QUALS (type);
+ int quals = cp_type_quals (type);
if (quals & TYPE_QUAL_CONST)
flags |= 1;
@@ -707,7 +707,7 @@ qualifier_flags (type)
return flags;
}
-/* Return non-zero, if the pointer chain TYPE ends at an incomplete type, or
+/* Return nonzero, if the pointer chain TYPE ends at an incomplete type, or
contains a pointer to member of an incomplete class. */
static int
@@ -767,8 +767,7 @@ tinfo_base_init (desc, target)
SET_DECL_ASSEMBLER_NAME (name_decl,
mangle_typeinfo_string_for_type (target));
DECL_INITIAL (name_decl) = name_string;
- cp_finish_decl (name_decl, name_string, NULL_TREE, 0);
- pushdecl_top_level (name_decl);
+ pushdecl_top_level_and_finish (name_decl, name_string);
}
vtable_ptr = TINFO_VTABLE_DECL (desc);
@@ -777,9 +776,10 @@ tinfo_base_init (desc, target)
tree real_type;
push_nested_namespace (abi_node);
- real_type = xref_tag (class_type_node, TINFO_REAL_NAME (desc), 1);
+ real_type = xref_tag (class_type, TINFO_REAL_NAME (desc),
+ /*attributes=*/NULL_TREE, 1);
pop_nested_namespace (abi_node);
-
+
if (!COMPLETE_TYPE_P (real_type))
{
/* We never saw a definition of this type, so we need to
@@ -796,7 +796,7 @@ tinfo_base_init (desc, target)
vtable_ptr = build
(PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr,
size_binop (MULT_EXPR,
- size_int (2),
+ size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE),
TYPE_SIZE_UNIT (vtable_entry_type)));
TREE_CONSTANT (vtable_ptr) = 1;
@@ -932,7 +932,7 @@ dfs_class_hint_mark (binfo, data)
return NULL_TREE;
};
-/* Clear the base's dfs marks, after searching for duplicate bases. */
+/* Clear the base's dfs marks, after searching for duplicate bases. */
static tree
dfs_class_hint_unmark (binfo, data)
@@ -986,7 +986,7 @@ class_initializer (desc, target, trail)
return init;
}
-/* Returns non-zero if the typeinfo for type should be placed in
+/* Returns nonzero if the typeinfo for type should be placed in
the runtime library. */
static int
@@ -1015,7 +1015,7 @@ typeinfo_in_lib_p (type)
}
/* Generate the initializer for the type info describing
- TYPE. VAR_DESC is a . NON_PUBLIC_P is set non-zero, if the VAR_DECL
+ TYPE. VAR_DESC is a . NON_PUBLIC_P is set nonzero, if the VAR_DECL
should not be exported from this object file. This should only be
called at the end of translation, when we know that no further
types will be completed. */
@@ -1105,15 +1105,17 @@ get_pseudo_ti_init (type, var_desc, non_public_p)
base_init = tree_cons (NULL_TREE, offset, base_init);
base_init = tree_cons (NULL_TREE, tinfo, base_init);
base_init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, base_init);
+ TREE_HAS_CONSTRUCTOR (base_init) = 1;
base_inits = tree_cons (NULL_TREE, base_init, base_inits);
}
base_inits = build (CONSTRUCTOR,
NULL_TREE, NULL_TREE, base_inits);
+ TREE_HAS_CONSTRUCTOR (base_inits) = 1;
base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE);
/* Prepend the number of bases. */
base_inits = tree_cons (NULL_TREE,
build_int_2 (nbases, 0), base_inits);
- /* Prepend the hint flags. */
+ /* Prepend the hint flags. */
base_inits = tree_cons (NULL_TREE,
build_int_2 (hint, 0), base_inits);
@@ -1155,24 +1157,24 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
VA_FIXEDARG (ap, const char *, real_name);
VA_FIXEDARG (ap, int, ident);
- /* Generate the pseudo type name. */
+ /* Generate the pseudo type name. */
pseudo_name = (char *)alloca (strlen (real_name) + 30);
strcpy (pseudo_name, real_name);
strcat (pseudo_name, "_pseudo");
if (ident)
sprintf (pseudo_name + strlen (pseudo_name), "%d", ident);
- /* First field is the pseudo type_info base class. */
+ /* First field is the pseudo type_info base class. */
fields[0] = build_decl (FIELD_DECL, NULL_TREE, ti_desc_type_node);
/* Now add the derived fields. */
for (ix = 0; (field_decl = va_arg (ap, tree));)
fields[++ix] = field_decl;
- /* Create the pseudo type. */
+ /* Create the pseudo type. */
pseudo_type = make_aggr_type (RECORD_TYPE);
finish_builtin_type (pseudo_type, pseudo_name, fields, ix, ptr_type_node);
- TYPE_HAS_CONSTRUCTOR (pseudo_type) = 1;
+ CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;
result = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
TINFO_REAL_NAME (result) = get_identifier (real_name);
@@ -1207,7 +1209,8 @@ get_pseudo_ti_desc (type)
return ptm_desc_type_node;
else if (!COMPLETE_TYPE_P (type))
{
- my_friendly_assert (at_eof, 20020609);
+ if (!at_eof)
+ cxx_incomplete_type_error (NULL_TREE, type);
return class_desc_type_node;
}
else if (!CLASSTYPE_N_BASECLASSES (type))
@@ -1222,7 +1225,7 @@ get_pseudo_ti_desc (type)
&& TREE_PUBLIC (base_binfo)
&& !TREE_VIA_VIRTUAL (base_binfo)
&& integer_zerop (BINFO_OFFSET (base_binfo)))
- /* single non-virtual public. */
+ /* single non-virtual public. */
return si_class_desc_type_node;
else
{
@@ -1295,7 +1298,7 @@ create_tinfo_types ()
("__fundamental_type_info", 0,
NULL);
- /* Array, function and enum type_info. No additional fields. */
+ /* Array, function and enum type_info. No additional fields. */
ary_desc_type_node = create_pseudo_type_info
("__array_type_info", 0,
NULL);
@@ -1319,7 +1322,7 @@ create_tinfo_types ()
NULL);
/* Base class internal helper. Pointer to base type, offset to base,
- flags. */
+ flags. */
{
tree fields[2];
@@ -1331,12 +1334,12 @@ create_tinfo_types ()
TYPE_HAS_CONSTRUCTOR (base_desc_type_node) = 1;
}
- /* General hierarchy is created as necessary in this vector. */
+ /* General hierarchy is created as necessary in this vector. */
vmi_class_desc_type_node = make_tree_vec (10);
/* Pointer type_info. Adds two fields, qualification mask
and pointer to the pointed to type. This is really a descendant of
- __pbase_type_info. */
+ __pbase_type_info. */
ptr_desc_type_node = create_pseudo_type_info
("__pointer_type_info", 0,
build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
@@ -1382,8 +1385,10 @@ emit_support_tinfos ()
tree bltn_type, dtor;
push_nested_namespace (abi_node);
- bltn_type = xref_tag (class_type_node,
- get_identifier ("__fundamental_type_info"), 1);
+ bltn_type = xref_tag (class_type,
+ get_identifier ("__fundamental_type_info"),
+ /*attributes=*/NULL_TREE,
+ 1);
pop_nested_namespace (abi_node);
if (!COMPLETE_TYPE_P (bltn_type))
return;
@@ -1413,7 +1418,7 @@ emit_support_tinfos ()
}
}
-/* Return non-zero, iff T is a type_info variable which has not had a
+/* Return nonzero, iff T is a type_info variable which has not had a
definition emitted for it. */
int
@@ -1470,7 +1475,7 @@ emit_tinfo_decl (decl_ptr, data)
DECL_INITIAL (decl) = var_init;
cp_finish_decl (decl, var_init, NULL_TREE, 0);
- /* cp_finish_decl will have dealt with linkage. */
+ /* cp_finish_decl will have dealt with linkage. */
/* Say we've dealt with it. */
TREE_TYPE (DECL_NAME (decl)) = NULL_TREE;
diff --git a/contrib/gcc/cp/search.c b/contrib/gcc/cp/search.c
index 38f4634..7a82796 100644
--- a/contrib/gcc/cp/search.c
+++ b/contrib/gcc/cp/search.c
@@ -31,11 +31,8 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "rtl.h"
#include "output.h"
+#include "ggc.h"
#include "toplev.h"
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
#include "stack.h"
/* Obstack used for remembering decision points of breadth-first. */
@@ -83,12 +80,12 @@ struct vbase_info
tree inits;
};
-static tree lookup_field_1 PARAMS ((tree, tree));
static int is_subobject_of_p PARAMS ((tree, tree, tree));
+static int is_subobject_of_p_1 PARAMS ((tree, tree, tree));
static tree dfs_check_overlap PARAMS ((tree, void *));
static tree dfs_no_overlap_yet PARAMS ((tree, void *));
static base_kind lookup_base_r
- PARAMS ((tree, tree, base_access, int, int, int, tree *));
+ PARAMS ((tree, tree, base_access, int, tree *));
static int dynamic_cast_base_recurse PARAMS ((tree, tree, int, tree *));
static tree marked_pushdecls_p PARAMS ((tree, void *));
static tree unmarked_pushdecls_p PARAMS ((tree, void *));
@@ -167,12 +164,8 @@ static int n_contexts_saved;
/* Worker for lookup_base. BINFO is the binfo we are searching at,
BASE is the RECORD_TYPE we are searching for. ACCESS is the
- required access checks. WITHIN_CURRENT_SCOPE, IS_NON_PUBLIC and
- IS_VIRTUAL indicate how BINFO was reached from the start of the
- search. WITHIN_CURRENT_SCOPE is true if we met the current scope,
- or friend thereof (this allows us to determine whether a protected
- base is accessible or not). IS_NON_PUBLIC indicates whether BINFO
- is accessible and IS_VIRTUAL indicates if it is morally virtual.
+ required access checks. IS_VIRTUAL indicates if BINFO is morally
+ virtual.
If BINFO is of the required type, then *BINFO_PTR is examined to
compare with any other instance of BASE we might have already
@@ -182,12 +175,9 @@ static int n_contexts_saved;
Otherwise BINFO's bases are searched. */
static base_kind
-lookup_base_r (binfo, base, access, within_current_scope,
- is_non_public, is_virtual, binfo_ptr)
+lookup_base_r (binfo, base, access, is_virtual, binfo_ptr)
tree binfo, base;
base_access access;
- int within_current_scope;
- int is_non_public; /* inside a non-public part */
int is_virtual; /* inside a virtual part */
tree *binfo_ptr;
{
@@ -195,24 +185,13 @@ lookup_base_r (binfo, base, access, within_current_scope,
tree bases;
base_kind found = bk_not_base;
- if (access == ba_check
- && !within_current_scope
- && is_friend (BINFO_TYPE (binfo), current_scope ()))
- {
- /* Do not clear is_non_public here. If A is a private base of B, A
- is not allowed to convert a B* to an A*. */
- within_current_scope = 1;
- }
-
if (same_type_p (BINFO_TYPE (binfo), base))
{
/* We have found a base. Check against what we have found
- already. */
+ already. */
found = bk_same_type;
if (is_virtual)
found = bk_via_virtual;
- if (is_non_public)
- found = bk_inaccessible;
if (!*binfo_ptr)
*binfo_ptr = binfo;
@@ -237,29 +216,11 @@ lookup_base_r (binfo, base, access, within_current_scope,
for (i = TREE_VEC_LENGTH (bases); i--;)
{
tree base_binfo = TREE_VEC_ELT (bases, i);
- int this_non_public = is_non_public;
- int this_virtual = is_virtual;
base_kind bk;
- if (access <= ba_ignore)
- ; /* no change */
- else if (TREE_VIA_PUBLIC (base_binfo))
- ; /* no change */
- else if (access == ba_not_special)
- this_non_public = 1;
- else if (TREE_VIA_PROTECTED (base_binfo) && within_current_scope)
- ; /* no change */
- else if (is_friend (BINFO_TYPE (binfo), current_scope ()))
- ; /* no change */
- else
- this_non_public = 1;
-
- if (TREE_VIA_VIRTUAL (base_binfo))
- this_virtual = 1;
-
bk = lookup_base_r (base_binfo, base,
- access, within_current_scope,
- this_non_public, this_virtual,
+ access,
+ is_virtual || TREE_VIA_VIRTUAL (base_binfo),
binfo_ptr);
switch (bk)
@@ -270,14 +231,6 @@ lookup_base_r (binfo, base, access, within_current_scope,
found = bk;
break;
- case bk_inaccessible:
- if (found == bk_not_base)
- found = bk;
- my_friendly_assert (found == bk_via_virtual
- || found == bk_inaccessible, 20010723);
-
- break;
-
case bk_same_type:
bk = bk_proper_base;
/* FALLTHROUGH */
@@ -293,6 +246,9 @@ lookup_base_r (binfo, base, access, within_current_scope,
case bk_not_base:
break;
+
+ default:
+ abort ();
}
}
return found;
@@ -303,8 +259,10 @@ lookup_base_r (binfo, base, access, within_current_scope,
canonical). If KIND_PTR is non-NULL, fill with information about
what kind of base we discovered.
- If ba_quiet bit is set in ACCESS, then do not issue an error, and
- return NULL_TREE for failure. */
+ If the base is inaccessible, or ambiguous, and the ba_quiet bit is
+ not set in ACCESS, then an error is issued and error_mark_node is
+ returned. If the ba_quiet bit is set, then no error is issued and
+ NULL_TREE is returned. */
tree
lookup_base (t, base, access, kind_ptr)
@@ -312,7 +270,8 @@ lookup_base (t, base, access, kind_ptr)
base_access access;
base_kind *kind_ptr;
{
- tree binfo = NULL; /* The binfo we've found so far. */
+ tree binfo = NULL; /* The binfo we've found so far. */
+ tree t_binfo = NULL;
base_kind bk;
if (t == error_mark_node || base == error_mark_node)
@@ -321,39 +280,78 @@ lookup_base (t, base, access, kind_ptr)
*kind_ptr = bk_not_base;
return error_mark_node;
}
- my_friendly_assert (TYPE_P (t) && TYPE_P (base), 20011127);
+ my_friendly_assert (TYPE_P (base), 20011127);
+ if (!TYPE_P (t))
+ {
+ t_binfo = t;
+ t = BINFO_TYPE (t);
+ }
+ else
+ t_binfo = TYPE_BINFO (t);
+
/* Ensure that the types are instantiated. */
t = complete_type (TYPE_MAIN_VARIANT (t));
base = complete_type (TYPE_MAIN_VARIANT (base));
- bk = lookup_base_r (TYPE_BINFO (t), base, access & ~ba_quiet,
- 0, 0, 0, &binfo);
+ bk = lookup_base_r (t_binfo, base, access, 0, &binfo);
+
+ /* Check that the base is unambiguous and accessible. */
+ if (access != ba_any)
+ switch (bk)
+ {
+ case bk_not_base:
+ break;
+
+ case bk_ambig:
+ binfo = NULL_TREE;
+ if (!(access & ba_quiet))
+ {
+ error ("`%T' is an ambiguous base of `%T'", base, t);
+ binfo = error_mark_node;
+ }
+ break;
+
+ default:
+ if (access != ba_ignore
+ /* If BASE is incomplete, then BASE and TYPE are probably
+ the same, in which case BASE is accessible. If they
+ are not the same, then TYPE is invalid. In that case,
+ there's no need to issue another error here, and
+ there's no implicit typedef to use in the code that
+ follows, so we skip the check. */
+ && COMPLETE_TYPE_P (base))
+ {
+ tree decl;
+
+ /* [class.access.base]
+
+ A base class is said to be accessible if an invented public
+ member of the base class is accessible. */
+ /* Rather than inventing a public member, we use the implicit
+ public typedef created in the scope of every class. */
+ decl = TYPE_FIELDS (base);
+ while (TREE_CODE (decl) != TYPE_DECL
+ || !DECL_ARTIFICIAL (decl)
+ || DECL_NAME (decl) != constructor_name (base))
+ decl = TREE_CHAIN (decl);
+ while (ANON_AGGR_TYPE_P (t))
+ t = TYPE_CONTEXT (t);
+ if (!accessible_p (t, decl))
+ {
+ if (!(access & ba_quiet))
+ {
+ error ("`%T' is an inaccessible base of `%T'", base, t);
+ binfo = error_mark_node;
+ }
+ else
+ binfo = NULL_TREE;
+ bk = bk_inaccessible;
+ }
+ }
+ break;
+ }
- switch (bk)
- {
- case bk_inaccessible:
- binfo = NULL_TREE;
- if (!(access & ba_quiet))
- {
- error ("`%T' is an inaccessible base of `%T'", base, t);
- binfo = error_mark_node;
- }
- break;
- case bk_ambig:
- if (access != ba_any)
- {
- binfo = NULL_TREE;
- if (!(access & ba_quiet))
- {
- error ("`%T' is an ambiguous base of `%T'", base, t);
- binfo = error_mark_node;
- }
- }
- break;
- default:;
- }
-
if (kind_ptr)
*kind_ptr = bk;
@@ -444,9 +442,8 @@ get_dynamic_cast_base_type (subtype, target)
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;
+tree
+lookup_field_1 (tree type, tree name, bool want_type)
{
register tree field;
@@ -483,14 +480,28 @@ lookup_field_1 (type, name)
lo = i + 1;
else
{
+ field = NULL_TREE;
+
/* We might have a nested class and a field with the
same name; we sorted them appropriately via
- field_decl_cmp, so just look for the last field with
- this name. */
- while (i + 1 < hi
- && DECL_NAME (fields[i+1]) == name)
- ++i;
- return fields[i];
+ field_decl_cmp, so just look for the first or last
+ field with this name. */
+ if (want_type)
+ {
+ do
+ field = fields[i--];
+ while (i >= lo && DECL_NAME (fields[i]) == name);
+ if (TREE_CODE (field) != TYPE_DECL
+ && !DECL_CLASS_TEMPLATE_P (field))
+ field = NULL_TREE;
+ }
+ else
+ {
+ do
+ field = fields[i++];
+ while (i < hi && DECL_NAME (fields[i]) == name);
+ }
+ return field;
}
}
return NULL_TREE;
@@ -501,7 +512,7 @@ lookup_field_1 (type, name)
#ifdef GATHER_STATISTICS
n_calls_lookup_field_1++;
#endif /* GATHER_STATISTICS */
- while (field)
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
#ifdef GATHER_STATISTICS
n_fields_searched++;
@@ -510,7 +521,7 @@ lookup_field_1 (type, name)
if (DECL_NAME (field) == NULL_TREE
&& ANON_AGGR_TYPE_P (TREE_TYPE (field)))
{
- tree temp = lookup_field_1 (TREE_TYPE (field), name);
+ tree temp = lookup_field_1 (TREE_TYPE (field), name, want_type);
if (temp)
return temp;
}
@@ -520,10 +531,13 @@ lookup_field_1 (type, name)
to return a USING_DECL, and the rest of the compiler can't
handle it. Once the class is defined, these are purged
from TYPE_FIELDS anyhow; see handle_using_decl. */
- ;
- else if (DECL_NAME (field) == name)
+ continue;
+
+ if (DECL_NAME (field) == name
+ && (!want_type
+ || TREE_CODE (field) == TYPE_DECL
+ || DECL_CLASS_TEMPLATE_P (field)))
return field;
- field = TREE_CHAIN (field);
}
/* Not found. */
if (name == vptr_identifier)
@@ -569,7 +583,7 @@ current_scope ()
return current_class_type;
}
-/* Returns non-zero if we are currently in a function scope. Note
+/* Returns nonzero if we are currently in a function scope. Note
that this function returns zero if we are within a local class, but
not within a member function body of the local class. */
@@ -580,6 +594,15 @@ at_function_scope_p ()
return cs && TREE_CODE (cs) == FUNCTION_DECL;
}
+/* Returns true if the innermost active scope is a class scope. */
+
+bool
+at_class_scope_p ()
+{
+ tree cs = current_scope ();
+ return cs && TYPE_P (cs);
+}
+
/* Return the scope of DECL, as appropriate when doing name-lookup. */
tree
@@ -845,7 +868,7 @@ dfs_accessible_p (binfo, data)
return NULL_TREE;
}
-/* Returns non-zero if it is OK to access DECL through an object
+/* Returns nonzero if it is OK to access DECL through an object
indiated by BINFO in the context of DERIVED. */
static int
@@ -908,7 +931,7 @@ protected_accessible_p (decl, derived, binfo)
return 1;
}
-/* Returns non-zero if SCOPE is a friend of a type which would be able
+/* Returns nonzero if SCOPE is a friend of a type which would be able
to access DECL through the object indicated by BINFO. */
static int
@@ -961,8 +984,8 @@ friend_accessible_p (scope, decl, binfo)
return 0;
}
-/* Perform access control on TYPE_DECL VAL, which was looked up in TYPE.
- This is fairly complex, so here's the design:
+/* Perform access control on TYPE_DECL or TEMPLATE_DECL VAL, which was
+ looked up in TYPE. This is fairly complex, so here's the design:
The lang_extdef nonterminal sets type_lookups to NULL_TREE before we
start to process a top-level declaration.
@@ -985,7 +1008,8 @@ void
type_access_control (type, val)
tree type, val;
{
- if (val == NULL_TREE || TREE_CODE (val) != TYPE_DECL
+ if (val == NULL_TREE
+ || (TREE_CODE (val) != TEMPLATE_DECL && TREE_CODE (val) != TYPE_DECL)
|| ! DECL_CLASS_SCOPE_P (val))
return;
@@ -996,7 +1020,7 @@ type_access_control (type, val)
}
/* DECL is a declaration from a base class of TYPE, which was the
- class used to name DECL. Return non-zero if, in the current
+ class used to name DECL. Return nonzero if, in the current
context, DECL is accessible. If TYPE is actually a BINFO node,
then we can tell in what context the access is occurring by looking
at the most derived class along the path indicated by BINFO. */
@@ -1010,7 +1034,7 @@ accessible_p (type, decl)
tree binfo;
tree t;
- /* Non-zero if it's OK to access DECL if it has protected
+ /* Nonzero if it's OK to access DECL if it has protected
accessibility in TYPE. */
int protected_ok = 0;
@@ -1081,13 +1105,11 @@ accessible_p (type, decl)
return t != NULL_TREE;
}
-/* Routine to see if the sub-object denoted by the binfo PARENT can be
- found as a base class and sub-object of the object denoted by
- BINFO. MOST_DERIVED is the most derived type of the hierarchy being
- searched. */
+/* Recursive helper funciton for is_subobject_of_p; see that routine
+ for documentation of the parameters. */
static int
-is_subobject_of_p (parent, binfo, most_derived)
+is_subobject_of_p_1 (parent, binfo, most_derived)
tree parent, binfo, most_derived;
{
tree binfos;
@@ -1099,23 +1121,54 @@ is_subobject_of_p (parent, binfo, most_derived)
binfos = BINFO_BASETYPES (binfo);
n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- /* Iterate the base types. */
+ /* Iterate through the base types. */
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (!CLASS_TYPE_P (TREE_TYPE (base_binfo)))
+ tree base_type;
+
+ base_type = TREE_TYPE (base_binfo);
+ if (!CLASS_TYPE_P (base_type))
/* If we see a TEMPLATE_TYPE_PARM, or some such, as a base
class there's no way to descend into it. */
continue;
- if (is_subobject_of_p (parent,
- CANONICAL_BINFO (base_binfo, most_derived),
- most_derived))
+ /* Avoid walking into the same virtual base more than once. */
+ if (TREE_VIA_VIRTUAL (base_binfo))
+ {
+ if (CLASSTYPE_MARKED4 (base_type))
+ continue;
+ SET_CLASSTYPE_MARKED4 (base_type);
+ base_binfo = binfo_for_vbase (base_type, most_derived);
+ }
+
+ if (is_subobject_of_p_1 (parent, base_binfo, most_derived))
return 1;
}
return 0;
}
+/* Routine to see if the sub-object denoted by the binfo PARENT can be
+ found as a base class and sub-object of the object denoted by
+ BINFO. MOST_DERIVED is the most derived type of the hierarchy being
+ searched. */
+
+static int
+is_subobject_of_p (tree parent, tree binfo, tree most_derived)
+{
+ int result;
+ tree vbase;
+
+ result = is_subobject_of_p_1 (parent, binfo, most_derived);
+ /* Clear the mark bits on virtual bases. */
+ for (vbase = CLASSTYPE_VBASECLASSES (most_derived);
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ CLEAR_CLASSTYPE_MARKED4 (TREE_TYPE (TREE_VALUE (vbase)));
+
+ return result;
+}
+
struct lookup_field_info {
/* The type in which we're looking. */
tree type;
@@ -1128,15 +1181,15 @@ struct lookup_field_info {
/* If non-NULL, the lookup was ambiguous, and this is a list of the
candidates. */
tree ambiguous;
- /* If non-zero, we are looking for types, not data members. */
+ /* If nonzero, we are looking for types, not data members. */
int want_type;
- /* If non-zero, RVAL was found by looking through a dependent base. */
+ /* If nonzero, RVAL was found by looking through a dependent base. */
int from_dep_base_p;
/* If something went wrong, a message indicating what. */
const char *errstr;
};
-/* Returns non-zero if BINFO is not hidden by the value found by the
+/* Returns nonzero if BINFO is not hidden by the value found by the
lookup so far. If BINFO is hidden, then there's no need to look in
it. DATA is really a struct lookup_field_info. Called from
lookup_field via breadth_first_search. */
@@ -1154,11 +1207,12 @@ lookup_field_queue_p (binfo, data)
/* If this base class is hidden by the best-known value so far, we
don't need to look. */
+ binfo = CANONICAL_BINFO (binfo, lfi->type);
if (!lfi->from_dep_base_p && lfi->rval_binfo
&& is_subobject_of_p (binfo, lfi->rval_binfo, lfi->type))
return NULL_TREE;
- return CANONICAL_BINFO (binfo, lfi->type);
+ return binfo;
}
/* Within the scope of a template class, you can refer to the to the
@@ -1167,7 +1221,7 @@ lookup_field_queue_p (binfo, data)
template <typename T> struct S { S* sp; }
- Returns non-zero if DECL is such a declaration in a class TYPE. */
+ Returns nonzero if DECL is such a declaration in a class TYPE. */
static int
template_self_reference_p (type, decl)
@@ -1239,7 +1293,7 @@ lookup_field_r (binfo, data)
if (!nval)
/* Look for a data member or type. */
- nval = lookup_field_1 (type, lfi->name);
+ nval = lookup_field_1 (type, lfi->name, lfi->want_type);
/* If there is no declaration with the indicated name in this type,
then there's nothing to do. */
@@ -1264,11 +1318,12 @@ lookup_field_r (binfo, data)
}
else
nval = NULL_TREE;
- if (!nval)
+ if (!nval && CLASSTYPE_NESTED_UDTS (type) != NULL)
{
- nval = purpose_member (lfi->name, CLASSTYPE_TAGS (type));
- if (nval)
- nval = TYPE_MAIN_DECL (TREE_VALUE (nval));
+ binding_entry e = binding_table_find (CLASSTYPE_NESTED_UDTS (type),
+ lfi->name);
+ if (e != NULL)
+ nval = TYPE_MAIN_DECL (e->type);
else
return NULL_TREE;
}
@@ -1354,16 +1409,44 @@ lookup_field_r (binfo, data)
return NULL_TREE;
}
+/* Return a "baselink" which BASELINK_BINFO, BASELINK_ACCESS_BINFO,
+ BASELINK_FUNCTIONS, and BASELINK_OPTYPE set to BINFO, ACCESS_BINFO,
+ FUNCTIONS, and OPTYPE respectively. */
+
+tree
+build_baselink (tree binfo, tree access_binfo, tree functions, tree optype)
+{
+ tree baselink;
+
+ my_friendly_assert (TREE_CODE (functions) == FUNCTION_DECL
+ || TREE_CODE (functions) == TEMPLATE_DECL
+ || TREE_CODE (functions) == TEMPLATE_ID_EXPR
+ || TREE_CODE (functions) == OVERLOAD,
+ 20020730);
+ my_friendly_assert (!optype || TYPE_P (optype), 20020730);
+ my_friendly_assert (TREE_TYPE (functions), 20020805);
+
+ baselink = build (BASELINK, TREE_TYPE (functions), NULL_TREE,
+ NULL_TREE, NULL_TREE);
+ BASELINK_BINFO (baselink) = binfo;
+ BASELINK_ACCESS_BINFO (baselink) = access_binfo;
+ BASELINK_FUNCTIONS (baselink) = functions;
+ BASELINK_OPTYPE (baselink) = optype;
+
+ return baselink;
+}
+
/* Look for a member named NAME in an inheritance lattice dominated by
- XBASETYPE. If PROTECT is 0 or two, we do not check access. If it is
- 1, we enforce accessibility. If PROTECT is zero, then, for an
- ambiguous lookup, we return NULL. If PROTECT is 1, we issue an
- error message. If PROTECT is 2, we return a TREE_LIST whose
- TREE_TYPE is error_mark_node and whose TREE_VALUEs are the list of
- ambiguous candidates.
+ XBASETYPE. If PROTECT is 0 or two, we do not check access. If it
+ is 1, we enforce accessibility. If PROTECT is zero, then, for an
+ ambiguous lookup, we return NULL. If PROTECT is 1, we issue error
+ messages about inaccessible or ambiguous lookup. If PROTECT is 2,
+ we return a TREE_LIST whose TREE_TYPE is error_mark_node and whose
+ TREE_VALUEs are the list of ambiguous candidates.
+
+ WANT_TYPE is 1 when we should only return TYPE_DECLs.
- WANT_TYPE is 1 when we should only return TYPE_DECLs, if no
- TYPE_DECL can be found return NULL_TREE. */
+ If nothing can be found return NULL_TREE and do not issue an error. */
tree
lookup_member (xbasetype, name, protect, want_type)
@@ -1387,7 +1470,7 @@ lookup_member (xbasetype, name, protect, want_type)
&& IDENTIFIER_CLASS_VALUE (name))
{
tree field = IDENTIFIER_CLASS_VALUE (name);
- if (TREE_CODE (field) != FUNCTION_DECL
+ if (! is_overloaded_fn (field)
&& ! (want_type && TREE_CODE (field) != TYPE_DECL))
/* We're in the scope of this class, and the value has already
been looked up. Just return the cached value. */
@@ -1463,19 +1546,9 @@ lookup_member (xbasetype, name, protect, want_type)
TREE_TYPE (rval)));
if (rval && is_overloaded_fn (rval))
- {
- /* Note that the binfo we put in the baselink is the binfo where
- we found the functions, which we need for overload
- resolution, but which should not be passed to enforce_access;
- rather, enforce_access wants a binfo which refers to the
- scope in which we started looking for the function. This
- will generally be the binfo passed into this function as
- xbasetype. */
-
- rval = tree_cons (rval_binfo, rval, NULL_TREE);
- SET_BASELINK_P (rval);
- }
-
+ rval = build_baselink (rval_binfo, basetype_path, rval,
+ (IDENTIFIER_TYPENAME_P (name)
+ ? TREE_TYPE (name): NULL_TREE));
return rval;
}
@@ -1490,7 +1563,7 @@ lookup_field (xbasetype, name, protect, want_type)
tree rval = lookup_member (xbasetype, name, protect, want_type);
/* Ignore functions. */
- if (rval && TREE_CODE (rval) == TREE_LIST)
+ if (rval && BASELINK_P (rval))
return NULL_TREE;
return rval;
@@ -1507,7 +1580,7 @@ lookup_fnfields (xbasetype, name, protect)
tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/0);
/* Ignore non-functions. */
- if (rval && TREE_CODE (rval) != TREE_LIST)
+ if (rval && !BASELINK_P (rval))
return NULL_TREE;
return rval;
@@ -1577,100 +1650,192 @@ lookup_nested_field (name, complain)
return id;
}
+/* Return the index in the CLASSTYPE_METHOD_VEC for CLASS_TYPE
+ corresponding to "operator TYPE ()", or -1 if there is no such
+ operator. Only CLASS_TYPE itself is searched; this routine does
+ not scan the base classes of CLASS_TYPE. */
+
+static int
+lookup_conversion_operator (tree class_type, tree type)
+{
+ int pass;
+ int i;
+
+ tree methods = CLASSTYPE_METHOD_VEC (class_type);
+
+ for (pass = 0; pass < 2; ++pass)
+ for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ i < TREE_VEC_LENGTH (methods);
+ ++i)
+ {
+ tree fn = TREE_VEC_ELT (methods, i);
+ /* The size of the vector may have some unused slots at the
+ end. */
+ if (!fn)
+ break;
+
+ /* All the conversion operators come near the beginning of the
+ class. Therefore, if FN is not a conversion operator, there
+ is no matching conversion operator in CLASS_TYPE. */
+ fn = OVL_CURRENT (fn);
+ if (!DECL_CONV_FN_P (fn))
+ break;
+
+ if (pass == 0)
+ {
+ /* On the first pass we only consider exact matches. If
+ the types match, this slot is the one where the right
+ conversion operators can be found. */
+ if (TREE_CODE (fn) != TEMPLATE_DECL
+ && same_type_p (DECL_CONV_FN_TYPE (fn), type))
+ return i;
+ }
+ else
+ {
+ /* On the second pass we look for template conversion
+ operators. It may be possible to instantiate the
+ template to get the type desired. All of the template
+ conversion operators share a slot. By looking for
+ templates second we ensure that specializations are
+ preferred over templates. */
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ return i;
+ }
+ }
+
+ return -1;
+}
+
/* 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. */
int
-lookup_fnfields_1 (type, name)
- tree type, name;
+lookup_fnfields_1 (tree type, tree name)
{
- tree method_vec
- = CLASS_TYPE_P (type) ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE;
+ tree method_vec;
+ tree *methods;
+ tree tmp;
+ int i;
+ int len;
- if (method_vec != 0)
- {
- register int i;
- register tree *methods = &TREE_VEC_ELT (method_vec, 0);
- int len = TREE_VEC_LENGTH (method_vec);
- tree tmp;
+ if (!CLASS_TYPE_P (type))
+ return -1;
+
+ method_vec = CLASSTYPE_METHOD_VEC (type);
+
+ if (!method_vec)
+ return -1;
+
+ methods = &TREE_VEC_ELT (method_vec, 0);
+ len = TREE_VEC_LENGTH (method_vec);
#ifdef GATHER_STATISTICS
- n_calls_lookup_fnfields_1++;
+ n_calls_lookup_fnfields_1++;
#endif /* GATHER_STATISTICS */
- /* Constructors are first... */
- if (name == ctor_identifier)
- return (methods[CLASSTYPE_CONSTRUCTOR_SLOT]
- ? CLASSTYPE_CONSTRUCTOR_SLOT : -1);
- /* and destructors are second. */
- if (name == dtor_identifier)
- return (methods[CLASSTYPE_DESTRUCTOR_SLOT]
- ? CLASSTYPE_DESTRUCTOR_SLOT : -1);
-
- for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
- i < len && methods[i];
- ++i)
+ /* Constructors are first... */
+ if (name == ctor_identifier)
+ return (methods[CLASSTYPE_CONSTRUCTOR_SLOT]
+ ? CLASSTYPE_CONSTRUCTOR_SLOT : -1);
+ /* and destructors are second. */
+ if (name == dtor_identifier)
+ return (methods[CLASSTYPE_DESTRUCTOR_SLOT]
+ ? CLASSTYPE_DESTRUCTOR_SLOT : -1);
+ if (IDENTIFIER_TYPENAME_P (name))
+ return lookup_conversion_operator (type, TREE_TYPE (name));
+
+ /* Skip the conversion operators. */
+ i = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ while (i < len && methods[i] && DECL_CONV_FN_P (OVL_CURRENT (methods[i])))
+ i++;
+
+ /* If the type is complete, use binary search. */
+ if (COMPLETE_TYPE_P (type))
+ {
+ int lo = i;
+ int hi = len;
+
+ while (lo < hi)
{
+ i = (lo + hi) / 2;
+
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
#endif /* GATHER_STATISTICS */
- tmp = OVL_CURRENT (methods[i]);
- if (DECL_NAME (tmp) == name)
+ tmp = methods[i];
+ /* This slot may be empty; we allocate more slots than we
+ need. In that case, the entry we're looking for is
+ closer to the beginning of the list. */
+ if (tmp)
+ tmp = DECL_NAME (OVL_CURRENT (tmp));
+ if (!tmp || tmp > name)
+ hi = i;
+ else if (tmp < name)
+ lo = i + 1;
+ else
return i;
+ }
+ }
+ else
+ for (; i < len && methods[i]; ++i)
+ {
+#ifdef GATHER_STATISTICS
+ n_outer_fields_searched++;
+#endif /* GATHER_STATISTICS */
- /* If the type is complete and we're past the conversion ops,
- switch to binary search. */
- if (! DECL_CONV_FN_P (tmp)
- && COMPLETE_TYPE_P (type))
- {
- int lo = i + 1, hi = len;
+ tmp = OVL_CURRENT (methods[i]);
+ if (DECL_NAME (tmp) == name)
+ return i;
+ }
- while (lo < hi)
- {
- i = (lo + hi) / 2;
+ return -1;
+}
-#ifdef GATHER_STATISTICS
- n_outer_fields_searched++;
-#endif /* GATHER_STATISTICS */
+/* DECL is the result of a qualified name lookup. QUALIFYING_CLASS
+ was the class used to qualify the name. CONTEXT_CLASS is the class
+ corresponding to the object in which DECL will be used. Return a
+ possibly modified version of DECL that takes into account the
+ CONTEXT_CLASS.
- tmp = DECL_NAME (OVL_CURRENT (methods[i]));
+ In particular, consider an expression like `B::m' in the context of
+ a derived class `D'. If `B::m' has been resolved to a BASELINK,
+ then the most derived class indicated by the BASELINK_BINFO will be
+ `B', not `D'. This function makes that adjustment. */
- if (tmp > name)
- hi = i;
- else if (tmp < name)
- lo = i + 1;
- else
- return i;
- }
- break;
- }
- }
+tree
+adjust_result_of_qualified_name_lookup (tree decl,
+ tree qualifying_class,
+ tree context_class)
+{
+ my_friendly_assert (CLASS_TYPE_P (qualifying_class), 20020808);
+ my_friendly_assert (CLASS_TYPE_P (context_class), 20020808);
- /* 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 (IDENTIFIER_TYPENAME_P (name))
+ if (BASELINK_P (decl)
+ && DERIVED_FROM_P (qualifying_class, context_class))
+ {
+ tree base;
+
+ /* Look for the QUALIFYING_CLASS as a base of the CONTEXT_CLASS.
+ Because we do not yet know which function will be chosen by
+ overload resolution, we cannot yet check either accessibility
+ or ambiguity -- in either case, the choice of a static member
+ function might make the usage valid. */
+ base = lookup_base (context_class, qualifying_class,
+ ba_ignore | ba_quiet, NULL);
+ if (base)
{
- for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
- i < len && methods[i];
- ++i)
- {
- tmp = OVL_CURRENT (methods[i]);
- if (! DECL_CONV_FN_P (tmp))
- {
- /* Since all conversion operators come first, we know
- there is no such operator. */
- break;
- }
- else if (TREE_CODE (tmp) == TEMPLATE_DECL)
- return i;
- }
+ BASELINK_ACCESS_BINFO (decl) = base;
+ BASELINK_BINFO (decl)
+ = lookup_base (base, BINFO_TYPE (BASELINK_BINFO (decl)),
+ ba_ignore | ba_quiet,
+ NULL);
}
}
- return -1;
+ return decl;
}
+
/* Walk the class hierarchy dominated by TYPE. FN is called for each
type in the hierarchy, in a breadth-first preorder traversal.
@@ -1678,7 +1843,7 @@ lookup_fnfields_1 (type, name)
returned and the walk is terminated. At each node, FN is passed a
BINFO indicating the path from the curently visited base-class to
TYPE. Before each base-class is walked QFN is called. If the
- value returned is non-zero, the base-class is walked; otherwise it
+ value returned is nonzero, the base-class is walked; otherwise it
is not. If QFN is NULL, it is treated as a function which always
returns 1. Both FN and QFN are passed the DATA whenever they are
called. */
@@ -1739,9 +1904,6 @@ bfs_walk (binfo, fn, qfn, data)
}
}
- /* Clean up. */
- VARRAY_FREE (bfs_bases);
-
return rval;
}
@@ -1918,7 +2080,7 @@ check_final_overrider (overrider, basefn)
virtual functions in TYPE's hierarchy which FNDECL overrides.
We do not look in TYPE itself, only its bases.
- Returns non-zero, if we find any. Set FNDECL's DECL_VIRTUAL_P, if we
+ Returns nonzero, if we find any. Set FNDECL's DECL_VIRTUAL_P, if we
find that it overrides anything.
We check that every function which is overridden, is correctly
@@ -1944,9 +2106,8 @@ look_for_overrides (type, fndecl)
return found;
}
-/* Look in TYPE for virtual functions with the same signature as FNDECL.
- This differs from get_matching_virtual in that it will only return
- a function from TYPE. */
+/* Look in TYPE for virtual functions with the same signature as
+ FNDECL. */
tree
look_for_overrides_here (type, fndecl)
@@ -1985,7 +2146,7 @@ look_for_overrides_here (type, fndecl)
}
/* Look in TYPE for virtual functions overridden by FNDECL. Check both
- TYPE itself and its bases. */
+ TYPE itself and its bases. */
static int
look_for_overrides_r (type, fndecl)
@@ -2473,7 +2634,7 @@ setup_class_bindings (name, type_binding_p)
{
if (BASELINK_P (value_binding))
/* NAME is some overloaded functions. */
- value_binding = TREE_VALUE (value_binding);
+ value_binding = BASELINK_FUNCTIONS (value_binding);
pushdecl_class_level (value_binding);
}
}
@@ -2525,7 +2686,8 @@ dfs_push_decls (binfo, data)
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
if (DECL_NAME (fields)
&& TREE_CODE (fields) != TYPE_DECL
- && TREE_CODE (fields) != USING_DECL)
+ && TREE_CODE (fields) != USING_DECL
+ && !DECL_ARTIFICIAL (fields))
setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
else if (TREE_CODE (fields) == FIELD_DECL
&& ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
@@ -2533,7 +2695,8 @@ dfs_push_decls (binfo, data)
method_vec = (CLASS_TYPE_P (type)
? CLASSTYPE_METHOD_VEC (type) : NULL_TREE);
- if (method_vec)
+
+ if (method_vec && TREE_VEC_LENGTH (method_vec) >= 3)
{
tree *methods;
tree *end;
@@ -2542,7 +2705,7 @@ dfs_push_decls (binfo, data)
end = TREE_VEC_END (method_vec);
for (methods = &TREE_VEC_ELT (method_vec, 2);
- *methods && methods != end;
+ methods < end && *methods;
methods++)
setup_class_bindings (DECL_NAME (OVL_CURRENT (*methods)),
/*type_binding_p=*/0);
@@ -2586,7 +2749,7 @@ dfs_unuse_fields (binfo, data)
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
{
- if (TREE_CODE (fields) != FIELD_DECL)
+ if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
TREE_USED (fields) = 0;
@@ -2693,8 +2856,8 @@ lookup_conversions (type)
tree t;
tree conversions = NULL_TREE;
- if (COMPLETE_TYPE_P (type))
- bfs_walk (TYPE_BINFO (type), add_conversions, 0, &conversions);
+ complete_type (type);
+ bfs_walk (TYPE_BINFO (type), add_conversions, 0, &conversions);
for (t = conversions; t; t = TREE_CHAIN (t))
IDENTIFIER_MARKED (DECL_NAME (OVL_CURRENT (TREE_VALUE (t)))) = 0;
@@ -2785,7 +2948,7 @@ binfo_for_vtable (var)
}
/* If no secondary base classes matched, return the primary base, if
- there is one. */
+ there is one. */
if (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (main_binfo)))
return get_primary_binfo (main_binfo);
diff --git a/contrib/gcc/cp/semantics.c b/contrib/gcc/cp/semantics.c
index a6f9afb..110eb3a 100644
--- a/contrib/gcc/cp/semantics.c
+++ b/contrib/gcc/cp/semantics.c
@@ -56,8 +56,6 @@ static void emit_associated_thunks PARAMS ((tree));
static void genrtl_try_block PARAMS ((tree));
static void genrtl_eh_spec_block PARAMS ((tree));
static void genrtl_handler PARAMS ((tree));
-static void genrtl_ctor_stmt PARAMS ((tree));
-static void genrtl_subobject PARAMS ((tree));
static void genrtl_named_return_value PARAMS ((void));
static void cp_expand_stmt PARAMS ((tree));
static void genrtl_start_function PARAMS ((tree));
@@ -81,7 +79,7 @@ static tree clear_decl_rtl PARAMS ((tree *, int *, void *));
(SUBSTMT) = (COND); \
} while (0)
-/* Returns non-zero if the current statement is a full expression,
+/* Returns nonzero if the current statement is a full expression,
i.e. temporaries created during that statement should be destroyed
at the end of the statement. */
@@ -99,7 +97,7 @@ stmt_tree
current_stmt_tree ()
{
return (cfun
- ? &cfun->language->x_stmt_tree
+ ? &cfun->language->base.x_stmt_tree
: &scope_chain->x_stmt_tree);
}
@@ -111,7 +109,7 @@ int
anon_aggr_type_p (node)
tree node;
{
- return (CLASS_TYPE_P (node) && TYPE_LANG_SPECIFIC(node)->anon_aggr);
+ return ANON_AGGR_TYPE_P (node);
}
/* Finish a scope. */
@@ -268,7 +266,6 @@ finish_then_clause (if_stmt)
tree if_stmt;
{
RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
- last_tree = if_stmt;
return if_stmt;
}
@@ -294,21 +291,8 @@ finish_else_clause (if_stmt)
void
finish_if_stmt ()
{
- do_poplevel ();
finish_stmt ();
-}
-
-void
-clear_out_block ()
-{
- /* If COND wasn't a declaration, clear out the
- block we made for it and start a new one here so the
- optimization in expand_end_loop will work. */
- if (getdecls () == NULL_TREE)
- {
- do_poplevel ();
- do_pushlevel ();
- }
+ do_poplevel ();
}
/* Begin a while-statement. Returns a newly created WHILE_STMT if
@@ -333,8 +317,29 @@ finish_while_stmt_cond (cond, while_stmt)
tree while_stmt;
{
cond = maybe_convert_cond (cond);
- FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt));
- clear_out_block ();
+ if (processing_template_decl)
+ /* Don't mess with condition decls in a template. */
+ FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt));
+ else if (getdecls () == NULL_TREE)
+ /* It was a simple condition; install it. */
+ WHILE_COND (while_stmt) = cond;
+ else
+ {
+ /* If there was a declaration in the condition, we can't leave it
+ there; transform
+ while (A x = 42) { }
+ to
+ while (true) { A x = 42; if (!x) break; } */
+ tree if_stmt;
+ WHILE_COND (while_stmt) = boolean_true_node;
+
+ if_stmt = begin_if_stmt ();
+ cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
+ finish_if_stmt_cond (cond, if_stmt);
+ finish_break_stmt ();
+ finish_then_clause (if_stmt);
+ finish_if_stmt ();
+ }
}
/* Finish a while-statement, which may be given by WHILE_STMT. */
@@ -419,12 +424,12 @@ begin_for_stmt ()
r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
NEW_FOR_SCOPE_P (r) = flag_new_for_scope > 0;
- add_stmt (r);
if (NEW_FOR_SCOPE_P (r))
{
do_pushlevel ();
note_level_for_for ();
}
+ add_stmt (r);
return r;
}
@@ -450,8 +455,29 @@ finish_for_cond (cond, for_stmt)
tree for_stmt;
{
cond = maybe_convert_cond (cond);
- FINISH_COND (cond, for_stmt, FOR_COND (for_stmt));
- clear_out_block ();
+ if (processing_template_decl)
+ /* Don't mess with condition decls in a template. */
+ FINISH_COND (cond, for_stmt, FOR_COND (for_stmt));
+ else if (getdecls () == NULL_TREE)
+ /* It was a simple condition; install it. */
+ FOR_COND (for_stmt) = cond;
+ else
+ {
+ /* If there was a declaration in the condition, we can't leave it
+ there; transform
+ for (; A x = 42;) { }
+ to
+ for (;;) { A x = 42; if (!x) break; } */
+ tree if_stmt;
+ FOR_COND (for_stmt) = NULL_TREE;
+
+ if_stmt = begin_if_stmt ();
+ cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
+ finish_if_stmt_cond (cond, if_stmt);
+ finish_break_stmt ();
+ finish_then_clause (if_stmt);
+ finish_if_stmt ();
+ }
}
/* Finish the increment-EXPRESSION in a for-statement, which may be
@@ -504,9 +530,9 @@ tree
begin_switch_stmt ()
{
tree r;
+ do_pushlevel ();
r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
add_stmt (r);
- do_pushlevel ();
return r;
}
@@ -562,11 +588,11 @@ finish_switch_stmt (switch_stmt)
{
RECHAIN_STMTS (switch_stmt, SWITCH_BODY (switch_stmt));
pop_switch ();
- do_poplevel ();
finish_stmt ();
+ do_poplevel ();
}
-/* Generate the RTL for T, which is a TRY_BLOCK. */
+/* Generate the RTL for T, which is a TRY_BLOCK. */
static void
genrtl_try_block (t)
@@ -603,7 +629,7 @@ genrtl_try_block (t)
}
}
-/* Generate the RTL for T, which is an EH_SPEC_BLOCK. */
+/* Generate the RTL for T, which is an EH_SPEC_BLOCK. */
static void
genrtl_eh_spec_block (t)
@@ -712,7 +738,7 @@ finish_function_handler_sequence (try_block)
check_handlers (TRY_HANDLERS (try_block));
}
-/* Generate the RTL for T, which is a HANDLER. */
+/* Generate the RTL for T, which is a HANDLER. */
static void
genrtl_handler (t)
@@ -781,22 +807,7 @@ finish_handler (handler)
RECHAIN_STMTS (handler, HANDLER_BODY (handler));
}
-/* Generate the RTL for T, which is a CTOR_STMT. */
-
-static void
-genrtl_ctor_stmt (t)
- tree t;
-{
- if (CTOR_BEGIN_P (t))
- begin_protect_partials ();
- else
- /* After this point, any exceptions will cause the
- destructor to be executed, so we no longer need to worry
- about destroying the various subobjects ourselves. */
- end_protect_partials ();
-}
-
-/* Begin a compound-statement. If HAS_NO_SCOPE is non-zero, the
+/* Begin a compound-statement. If HAS_NO_SCOPE is nonzero, the
compound-statement does not define a scope. Returns a new
COMPOUND_STMT if appropriate. */
@@ -835,7 +846,7 @@ begin_compound_stmt (has_no_scope)
}
/* Finish a compound-statement, which may be given by COMPOUND_STMT.
- If HAS_NO_SCOPE is non-zero, the compound statement does not define
+ If HAS_NO_SCOPE is nonzero, the compound statement does not define
a scope. */
tree
@@ -880,9 +891,6 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
tree r;
tree t;
- if (TREE_CHAIN (string))
- string = combine_strings (string);
-
if (cv_qualifier != NULL_TREE
&& cv_qualifier != ridpointers[(int) RID_VOLATILE])
{
@@ -927,7 +935,7 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
tree operand;
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
- operand = TREE_VALUE (output_operands);
+ operand = TREE_VALUE (t);
if (!parse_output_constraint (&constraint,
i, ninputs, noutputs,
@@ -948,7 +956,7 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
DECL_RTL for the OPERAND -- which we don't have at this
point. */
if (!allows_reg && DECL_P (operand))
- mark_addressable (operand);
+ cxx_mark_addressable (operand);
}
}
@@ -980,38 +988,28 @@ finish_label_decl (name)
add_decl_stmt (decl);
}
-/* Generate the RTL for a SUBOBJECT. */
-
-static void
-genrtl_subobject (cleanup)
- tree cleanup;
-{
- add_partial_entry (cleanup);
-}
-
-/* We're in a constructor, and have just constructed a a subobject of
- *THIS. CLEANUP is code to run if an exception is thrown before the
- end of the current function is reached. */
+/* When DECL goes out of scope, make sure that CLEANUP is executed. */
void
-finish_subobject (cleanup)
+finish_decl_cleanup (decl, cleanup)
+ tree decl;
tree cleanup;
{
- tree r = build_stmt (SUBOBJECT, cleanup);
- add_stmt (r);
+ add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
}
-/* When DECL goes out of scope, make sure that CLEANUP is executed. */
+/* If the current scope exits with an exception, run CLEANUP. */
-void
-finish_decl_cleanup (decl, cleanup)
- tree decl;
+void
+finish_eh_cleanup (cleanup)
tree cleanup;
{
- add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
+ tree r = build_stmt (CLEANUP_STMT, NULL_TREE, cleanup);
+ CLEANUP_EH_ONLY (r) = 1;
+ add_stmt (r);
}
-/* Generate the RTL for a RETURN_INIT. */
+/* Generate the RTL for a RETURN_INIT. */
static void
genrtl_named_return_value ()
@@ -1031,7 +1029,7 @@ genrtl_named_return_value ()
the return value. */
SET_DECL_RTL (decl, gen_reg_rtx (GET_MODE (DECL_RTL (decl))));
if (TREE_ADDRESSABLE (decl))
- put_var_into_stack (decl);
+ put_var_into_stack (decl, /*rescan=*/true);
}
emit_local_var (decl);
@@ -1093,67 +1091,30 @@ finish_named_return_value (return_id, init)
DECL_UNINLINABLE (current_function_decl) = 1;
}
-/* The INIT_LIST is a list of mem-initializers, in the order they were
- written by the user. The TREE_VALUE of each node is a list of
- initializers for a particular subobject. The TREE_PURPOSE is a
- FIELD_DECL is the initializer is for a non-static data member, and
- a class type if the initializer is for a base class. */
+/* Begin processing a mem-initializer-list. */
void
-finish_mem_initializers (init_list)
- tree init_list;
+begin_mem_initializers ()
{
- tree member_init_list;
- tree base_init_list;
- tree last_base_warned_about;
- tree next;
- tree init;
+ if (! DECL_CONSTRUCTOR_P (current_function_decl))
+ error ("only constructors take base initializers");
+}
- member_init_list = NULL_TREE;
- base_init_list = NULL_TREE;
- last_base_warned_about = NULL_TREE;
+/* The MEM_INITS is a list of mem-initializers, in reverse of the
+ order they were written by the user. Each node is as for
+ emit_mem_initializers. */
- for (init = init_list; init; init = next)
- {
- next = TREE_CHAIN (init);
- if (TREE_CODE (TREE_PURPOSE (init)) == FIELD_DECL)
- {
- TREE_CHAIN (init) = member_init_list;
- member_init_list = init;
-
- /* We're running through the initializers from right to left
- as we process them here. So, if we see a data member
- initializer after we see a base initializer, that
- actually means that the base initializer preceded the
- data member initializer. */
- if (warn_reorder && last_base_warned_about != base_init_list)
- {
- tree base;
-
- for (base = base_init_list;
- base != last_base_warned_about;
- base = TREE_CHAIN (base))
- {
- warning ("base initializer for `%T'",
- TREE_PURPOSE (base));
- warning (" will be re-ordered to precede member initializations");
- }
-
- last_base_warned_about = base_init_list;
- }
- }
- else
- {
- TREE_CHAIN (init) = base_init_list;
- base_init_list = init;
- }
- }
+void
+finish_mem_initializers (tree mem_inits)
+{
+ /* Reorder the MEM_INITS so that they are in the order they appeared
+ in the source program. */
+ mem_inits = nreverse (mem_inits);
if (processing_template_decl)
- add_stmt (build_min_nt (CTOR_INITIALIZER,
- member_init_list, base_init_list));
+ add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
else
- emit_base_init (member_init_list, base_init_list);
+ emit_mem_initializers (mem_inits);
}
/* Returns the stack of SCOPE_STMTs for the current function. */
@@ -1161,7 +1122,7 @@ finish_mem_initializers (init_list)
tree *
current_scope_stmt_stack ()
{
- return &cfun->language->x_scope_stmt_stack;
+ return &cfun->language->base.x_scope_stmt_stack;
}
/* Finish a parenthesized expression EXPR. */
@@ -1171,7 +1132,7 @@ finish_parenthesized_expr (expr)
tree expr;
{
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expr))))
- /* This inhibits warnings in truthvalue_conversion. */
+ /* This inhibits warnings in c_common_truthvalue_conversion. */
C_SET_EXP_ORIGINAL_CODE (expr, ERROR_MARK);
if (TREE_CODE (expr) == OFFSET_REF)
@@ -1263,32 +1224,87 @@ finish_stmt_expr (rtl_expr)
return result;
}
-/* Finish a call to FN with ARGS. Returns a representation of the
- call. */
+/* Generate an expression for `FN (ARGS)'.
+
+ If DISALLOW_VIRTUAL is true, the call to FN will be not generated
+ as a virtual call, even if FN is virtual. (This flag is set when
+ encountering an expression where the function name is explicitly
+ qualified. For example a call to `X::f' never generates a virtual
+ call.)
+
+ Returns code for the call. */
tree
-finish_call_expr (fn, args, koenig)
- tree fn;
- tree args;
- int koenig;
+finish_call_expr (tree fn, tree args, bool disallow_virtual)
{
- tree result;
+ if (fn == error_mark_node || args == error_mark_node)
+ return error_mark_node;
+
+ if (processing_template_decl)
+ return build_nt (CALL_EXPR, fn, args, NULL_TREE);
- if (koenig)
+ /* ARGS should be a list of arguments. */
+ my_friendly_assert (!args || TREE_CODE (args) == TREE_LIST,
+ 20020712);
+
+ if (BASELINK_P (fn))
{
- if (TREE_CODE (fn) == BIT_NOT_EXPR)
- fn = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND (fn, 0));
- else if (TREE_CODE (fn) != TEMPLATE_ID_EXPR)
- fn = do_identifier (fn, 2, args);
- }
- result = build_x_function_call (fn, args, current_class_ref);
+ tree object;
+
+ /* A call to a member function. From [over.call.func]:
+
+ If the keyword this is in scope and refers to the class of
+ that member function, or a derived class thereof, then the
+ function call is transformed into a qualified function call
+ using (*this) as the postfix-expression to the left of the
+ . operator.... [Otherwise] a contrived object of type T
+ becomes the implied object argument.
+
+ This paragraph is unclear about this situation:
+
+ struct A { void f(); };
+ struct B : public A {};
+ struct C : public A { void g() { B::f(); }};
+
+ In particular, for `B::f', this paragraph does not make clear
+ whether "the class of that member function" refers to `A' or
+ to `B'. We believe it refers to `B'. */
+ if (current_class_type
+ && DERIVED_FROM_P (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
+ current_class_type)
+ && current_class_ref)
+ object = maybe_dummy_object (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
+ NULL);
+ else
+ {
+ tree representative_fn;
- if (TREE_CODE (result) == CALL_EXPR
- && (! TREE_TYPE (result)
- || TREE_CODE (TREE_TYPE (result)) != VOID_TYPE))
- result = require_complete_type (result);
+ representative_fn = BASELINK_FUNCTIONS (fn);
+ if (TREE_CODE (representative_fn) == TEMPLATE_ID_EXPR)
+ representative_fn = TREE_OPERAND (representative_fn, 0);
+ representative_fn = get_first_fn (representative_fn);
+ object = build_dummy_object (DECL_CONTEXT (representative_fn));
+ }
- return result;
+ return build_new_method_call (object, fn, args, NULL_TREE,
+ (disallow_virtual
+ ? LOOKUP_NONVIRTUAL : 0));
+ }
+ else if (is_overloaded_fn (fn))
+ /* A call to a namespace-scope function. */
+ return build_new_function_call (fn, args);
+ else if (CLASS_TYPE_P (TREE_TYPE (fn)))
+ {
+ /* If the "function" is really an object of class type, it might
+ have an overloaded `operator ()'. */
+ tree result;
+ result = build_opfncall (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
+ if (result)
+ return result;
+ }
+
+ /* A call where the function is unknown. */
+ return build_function_call (fn, args);
}
/* Finish a call to a postfix increment or decrement or EXPR. (Which
@@ -1348,14 +1364,6 @@ finish_object_call_expr (fn, object, args)
tree object;
tree args;
{
-#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. */
-
- tree real_fn = build_component_ref (object, fn, NULL_TREE, 1);
- return finish_call_expr (real_fn, args);
-#else
if (DECL_DECLARES_TYPE_P (fn))
{
if (processing_template_decl)
@@ -1374,9 +1382,11 @@ finish_object_call_expr (fn, object, args)
return error_mark_node;
}
}
-
- return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
-#endif
+
+ if (processing_template_decl || name_p (fn))
+ return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
+ else
+ return build_new_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
}
/* Finish a qualified member function call using OBJECT and ARGS as
@@ -1417,22 +1427,6 @@ finish_pseudo_destructor_call_expr (object, scope, destructor)
return cp_convert (void_type_node, object);
}
-/* Finish a call to a globally qualified member function FN using
- ARGS. Returns an expression for the call. */
-
-tree
-finish_qualified_call_expr (fn, args)
- tree fn;
- tree args;
-{
- if (processing_template_decl)
- return build_min_nt (CALL_EXPR, fn, args, NULL_TREE);
- else
- return build_member_call (TREE_OPERAND (fn, 0),
- TREE_OPERAND (fn, 1),
- args);
-}
-
/* Finish an expression of the form CODE EXPR. */
tree
@@ -1467,6 +1461,20 @@ finish_id_expr (expr)
return expr;
}
+/* Return the declaration for the function-name variable indicated by
+ ID. */
+
+tree
+finish_fname (tree id)
+{
+ tree decl;
+
+ decl = fname_decl (C_RID_CODE (id), id);
+ if (processing_template_decl)
+ decl = build_min_nt (LOOKUP_EXPR, DECL_NAME (decl));
+ return decl;
+}
+
static tree current_type_lookups;
/* Perform deferred access control for types used in the type of a
@@ -1524,20 +1532,17 @@ reset_type_access_control ()
current_type_lookups = NULL_TREE;
}
-/* Begin a function definition declared with DECL_SPECS and
- DECLARATOR. Returns non-zero if the function-declaration is
- legal. */
+/* Begin a function definition declared with DECL_SPECS, ATTRIBUTES,
+ and DECLARATOR. Returns nonzero if the function-declaration is
+ valid. */
int
-begin_function_definition (decl_specs, declarator)
+begin_function_definition (decl_specs, attributes, declarator)
tree decl_specs;
+ tree attributes;
tree declarator;
{
- tree specs;
- tree attrs;
-
- split_specs_attrs (decl_specs, &specs, &attrs);
- if (!start_function (specs, declarator, attrs, SF_DEFAULT))
+ if (!start_function (decl_specs, declarator, attributes, SF_DEFAULT))
return 0;
deferred_type_access_control ();
@@ -1589,7 +1594,7 @@ finish_translation_unit ()
while (current_namespace != global_namespace)
pop_namespace ();
- /* Do file scope __FUNCTION__ et al. */
+ /* Do file scope __FUNCTION__ et al. */
finish_fname_decls ();
finish_file ();
@@ -1632,8 +1637,27 @@ finish_template_template_parm (aggr, identifier)
return finish_template_type_parm (aggr, tmpl);
}
+/* ARGUMENT is the default-argument value for a template template
+ parameter. If ARGUMENT is invalid, issue error messages and return
+ the ERROR_MARK_NODE. Otherwise, ARGUMENT itself is returned. */
+
+tree
+check_template_template_default_arg (tree argument)
+{
+ if (TREE_CODE (argument) != TEMPLATE_DECL
+ && TREE_CODE (argument) != TEMPLATE_TEMPLATE_PARM
+ && TREE_CODE (argument) != TYPE_DECL
+ && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
+ {
+ error ("invalid default template argument");
+ return error_mark_node;
+ }
+
+ return argument;
+}
+
/* Finish a parameter list, indicated by PARMS. If ELLIPSIS is
- non-zero, the parameter list was terminated by a `...'. */
+ nonzero, the parameter list was terminated by a `...'. */
tree
finish_parmlist (parms, ellipsis)
@@ -1661,7 +1685,7 @@ begin_class_definition (t)
if (t == error_mark_node)
return error_mark_node;
- /* Check the bases are accessible. */
+ /* Check the bases are accessible. */
decl_type_access_control (TYPE_NAME (t));
reset_type_access_control ();
@@ -1731,7 +1755,8 @@ begin_class_definition (t)
TYPE_BINFO_BASETYPES (t) = NULL_TREE;
TYPE_FIELDS (t) = NULL_TREE;
TYPE_METHODS (t) = NULL_TREE;
- CLASSTYPE_TAGS (t) = NULL_TREE;
+ CLASSTYPE_DECL_LIST (t) = NULL_TREE;
+ CLASSTYPE_NESTED_UDTS (t) = NULL;
CLASSTYPE_VBASECLASSES (t) = NULL_TREE;
TYPE_SIZE (t) = NULL_TREE;
}
@@ -1824,8 +1849,12 @@ finish_member_declaration (decl)
TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
TYPE_METHODS (current_class_type) = decl;
+
+ maybe_add_class_template_decl_list (current_class_type, decl,
+ /*friend_p=*/0);
}
- else
+ /* Enter the DECL into the scope of the class. */
+ else if (TREE_CODE (decl) == USING_DECL || pushdecl_class_level (decl))
{
/* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields
go at the beginning. The reason is that lookup_field_1
@@ -1836,7 +1865,7 @@ finish_member_declaration (decl)
struct S { enum E { }; int E } s;
s.E = 3;
- is legal. In addition, the FIELD_DECLs must be maintained in
+ is valid. In addition, the FIELD_DECLs must be maintained in
declaration order so that class layout works as expected.
However, we don't need that order until class layout, so we
save a little time by putting FIELD_DECLs on in reverse order
@@ -1853,9 +1882,8 @@ finish_member_declaration (decl)
TYPE_FIELDS (current_class_type) = decl;
}
- /* Enter the DECL into the scope of the class. */
- if (TREE_CODE (decl) != USING_DECL)
- pushdecl_class_level (decl);
+ maybe_add_class_template_decl_list (current_class_type, decl,
+ /*friend_p=*/0);
}
}
@@ -1912,16 +1940,6 @@ begin_inline_definitions ()
do_pending_inlines ();
}
-/* Finish processing the inline function definitions cached during the
- processing of a class definition. */
-
-void
-finish_inline_definitions ()
-{
- if (current_class_type == NULL_TREE)
- clear_inline_text_obstack ();
-}
-
/* Finish processing the declaration of a member class template
TYPES whose template parameters are given by PARMS. */
@@ -1969,7 +1987,7 @@ finish_template_decl (parms)
/* Finish processing a template-id (which names a type) of the form
NAME < ARGS >. Return the TYPE_DECL for the type named by the
- template-id. If ENTERING_SCOPE is non-zero we are about to enter
+ template-id. If ENTERING_SCOPE is nonzero we are about to enter
the scope of template-id indicated. */
tree
@@ -2030,7 +2048,12 @@ finish_base_specifier (access_specifier, base_class)
{
tree result;
- if (! is_aggr_type (base_class, 1))
+ if (base_class == error_mark_node)
+ {
+ error ("invalid base-class specification");
+ result = NULL_TREE;
+ }
+ else if (! is_aggr_type (base_class, 1))
result = NULL_TREE;
else
{
@@ -2058,11 +2081,9 @@ check_multiple_declarators ()
contain at most one declarator.
We don't just use PROCESSING_TEMPLATE_DECL for the first
- condition since that would disallow the perfectly legal code,
+ condition since that would disallow the perfectly valid code,
like `template <class T> struct S { int i, j; };'. */
- tree scope = current_scope ();
-
- if (scope && TREE_CODE (scope) == FUNCTION_DECL)
+ if (at_function_scope_p ())
/* It's OK to write `template <class T> void f() { int i, j;}'. */
return;
@@ -2112,7 +2133,7 @@ finish_sizeof (t)
if (processing_template_decl)
return build_min_nt (SIZEOF_EXPR, t);
- return TYPE_P (t) ? c_sizeof (t) : expr_sizeof (t);
+ return TYPE_P (t) ? cxx_sizeof (t) : expr_sizeof (t);
}
/* Implement the __alignof keyword: Return the minimum required
@@ -2125,7 +2146,7 @@ finish_alignof (t)
if (processing_template_decl)
return build_min_nt (ALIGNOF_EXPR, t);
- return TYPE_P (t) ? c_alignof (complete_type (t)) : c_alignof_expr (t);
+ return TYPE_P (t) ? cxx_alignof (t) : c_alignof_expr (t);
}
/* Generate RTL for the statement T, and its substatements, and any
@@ -2137,10 +2158,6 @@ cp_expand_stmt (t)
{
switch (TREE_CODE (t))
{
- case CTOR_STMT:
- genrtl_ctor_stmt (t);
- break;
-
case TRY_BLOCK:
genrtl_try_block (t);
break;
@@ -2153,10 +2170,6 @@ cp_expand_stmt (t)
genrtl_handler (t);
break;
- case SUBOBJECT:
- genrtl_subobject (SUBOBJECT_CLEANUP (t));
- break;
-
case RETURN_INIT:
genrtl_named_return_value ();
break;
@@ -2211,7 +2224,7 @@ simplify_aggr_init_exprs_r (tp, walk_subtrees, data)
{
/* Replace the first argument with the address of the third
argument to the AGGR_INIT_EXPR. */
- mark_addressable (slot);
+ cxx_mark_addressable (slot);
args = tree_cons (NULL_TREE,
build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (slot)),
@@ -2271,35 +2284,9 @@ emit_associated_thunks (fn)
enabling you to output all the thunks with the function itself. */
if (DECL_VIRTUAL_P (fn))
{
- tree binfo;
- tree v;
-
- for (binfo = TYPE_BINFO (DECL_CONTEXT (fn));
- binfo;
- binfo = TREE_CHAIN (binfo))
- for (v = BINFO_VIRTUALS (binfo); v; v = TREE_CHAIN (v))
- if (BV_FN (v) == fn
- && (!integer_zerop (BV_DELTA (v))
- || BV_USE_VCALL_INDEX_P (v)))
- {
- tree thunk;
- tree vcall_index;
-
- if (BV_USE_VCALL_INDEX_P (v))
- {
- vcall_index = BV_VCALL_INDEX (v);
- my_friendly_assert (vcall_index != NULL_TREE, 20000621);
- }
- else
- vcall_index = NULL_TREE;
-
- thunk = make_thunk (build1 (ADDR_EXPR,
- vfunc_ptr_type_node,
- fn),
- BV_DELTA (v),
- vcall_index);
- use_thunk (thunk, /*emit_p=*/1);
- }
+ tree thunk;
+ for (thunk = DECL_THUNKS (fn); thunk; thunk = TREE_CHAIN (thunk))
+ use_thunk (thunk, /*emit_p=*/1);
}
}
@@ -2311,6 +2298,7 @@ expand_body (fn)
{
int saved_lineno;
const char *saved_input_filename;
+ tree saved_function;
/* When the parser calls us after finishing the body of a template
function, we don't really want to expand the body. When we're
@@ -2388,21 +2376,23 @@ expand_body (fn)
if (DECL_EXTERNAL (fn))
return;
- timevar_push (TV_INTEGRATION);
-
- /* Optimize the body of the function before expanding it. */
- optimize_function (fn);
-
- timevar_pop (TV_INTEGRATION);
- timevar_push (TV_EXPAND);
-
/* Save the current file name and line number. When we expand the
body of the function, we'll set LINENO and INPUT_FILENAME so that
error-mesages come out in the right places. */
saved_lineno = lineno;
saved_input_filename = input_filename;
+ saved_function = current_function_decl;
lineno = DECL_SOURCE_LINE (fn);
input_filename = DECL_SOURCE_FILE (fn);
+ current_function_decl = fn;
+
+ timevar_push (TV_INTEGRATION);
+
+ /* Optimize the body of the function before expanding it. */
+ optimize_function (fn);
+
+ timevar_pop (TV_INTEGRATION);
+ timevar_push (TV_EXPAND);
genrtl_start_function (fn);
current_function_is_thunk = DECL_THUNK_P (fn);
@@ -2435,6 +2425,7 @@ expand_body (fn)
DECL_SAVED_TREE (fn) = NULL_TREE;
/* And restore the current source position. */
+ current_function_decl = saved_function;
lineno = saved_lineno;
input_filename = saved_input_filename;
extract_interface_info ();
@@ -2462,7 +2453,7 @@ nullify_returns_r (tp, walk_subtrees, data)
if (TYPE_P (*tp))
*walk_subtrees = 0;
else if (TREE_CODE (*tp) == RETURN_STMT)
- RETURN_EXPR (*tp) = NULL_TREE;
+ RETURN_STMT_EXPR (*tp) = NULL_TREE;
else if (TREE_CODE (*tp) == CLEANUP_STMT
&& CLEANUP_DECL (*tp) == nrv)
CLEANUP_EH_ONLY (*tp) = 1;
@@ -2516,10 +2507,7 @@ genrtl_start_function (fn)
function; we need the named return value info for
cp_copy_res_decl_for_inlining. */
if (! DECL_INLINE (fn))
- {
- free (DECL_SAVED_FUNCTION_DATA (fn));
- DECL_SAVED_FUNCTION_DATA (fn) = NULL;
- }
+ DECL_SAVED_FUNCTION_DATA (fn) = NULL;
}
/* Keep track of how many functions we're presently expanding. */
diff --git a/contrib/gcc/cp/spew.c b/contrib/gcc/cp/spew.c
index 278a99a..5bd3fdf 100644
--- a/contrib/gcc/cp/spew.c
+++ b/contrib/gcc/cp/spew.c
@@ -29,7 +29,7 @@ Boston, MA 02111-1307, USA. */
#include "tree.h"
#include "cp-tree.h"
#include "cpplib.h"
-#include "c-lex.h"
+#include "c-pragma.h"
#include "lex.h"
#include "parse.h"
#include "flags.h"
@@ -50,12 +50,12 @@ Boston, MA 02111-1307, USA. */
backtracking. */
/* fifo of tokens recognized and available to parser. */
-struct token
+struct token GTY(())
{
/* The values for YYCHAR will fit in a short. */
short yychar;
unsigned int lineno;
- YYSTYPE yylval;
+ YYSTYPE GTY ((desc ("%1.yychar"))) yylval;
};
/* Since inline methods can refer to text which has not yet been seen,
@@ -68,64 +68,82 @@ struct token
This function's FUNCTION_DECL will have a bit set in its common so
that we know to watch out for it. */
-struct unparsed_text
+#define TOKEN_CHUNK_SIZE 20
+struct token_chunk GTY(())
+{
+ struct token_chunk *next;
+ struct token toks[TOKEN_CHUNK_SIZE];
+};
+
+struct unparsed_text GTY(())
{
struct unparsed_text *next; /* process this one next */
tree decl; /* associated declaration */
- const char *filename; /* name of file we were processing */
- int lineno; /* line number we got the text from */
+ location_t locus; /* location we got the text from */
int interface; /* remembering interface_unknown and interface_only */
- struct token *pos; /* current position, when rescanning */
- struct token *limit; /* end of saved text */
+ struct token_chunk * tokens; /* Start of the token list. */
+
+ struct token_chunk *last_chunk; /* End of the token list. */
+ short last_pos; /* Number of tokens used in the last chunk of
+ TOKENS. */
+
+ short cur_pos; /* Current token in 'cur_chunk', when rescanning. */
+ struct token_chunk *cur_chunk; /* Current chunk, when rescanning. */
};
/* Stack of state saved off when we return to an inline method or
default argument that has been stored for later parsing. */
-struct feed
+struct feed GTY(())
{
struct unparsed_text *input;
- const char *filename;
- int lineno;
+ location_t locus;
int yychar;
- YYSTYPE yylval;
+ YYSTYPE GTY ((desc ("%1.yychar"))) yylval;
int first_token;
- struct obstack token_obstack;
+ struct obstack GTY ((skip (""))) token_obstack;
struct feed *next;
-};
+};
-static struct obstack feed_obstack;
-static struct feed *feed;
+static GTY(()) struct feed *feed;
static SPEW_INLINE void do_aggr PARAMS ((void));
static SPEW_INLINE int identifier_type PARAMS ((tree));
static void scan_tokens PARAMS ((int));
static void feed_defarg PARAMS ((tree));
static void finish_defarg PARAMS ((void));
+static void yylexstring PARAMS ((struct token *));
static int read_token PARAMS ((struct token *));
static SPEW_INLINE int num_tokens PARAMS ((void));
static SPEW_INLINE struct token *nth_token PARAMS ((int));
-static SPEW_INLINE int add_token PARAMS ((struct token *));
+static SPEW_INLINE int next_token PARAMS ((struct token *));
static SPEW_INLINE int shift_token PARAMS ((void));
static SPEW_INLINE void push_token PARAMS ((struct token *));
static SPEW_INLINE void consume_token PARAMS ((void));
static SPEW_INLINE int read_process_identifier PARAMS ((YYSTYPE *));
static SPEW_INLINE void feed_input PARAMS ((struct unparsed_text *));
-static SPEW_INLINE void snarf_block PARAMS ((const char *, int));
+static SPEW_INLINE struct token * space_for_token
+ PARAMS ((struct unparsed_text *t));
+static SPEW_INLINE struct token * remove_last_token
+ PARAMS ((struct unparsed_text *t));
+static struct unparsed_text * alloc_unparsed_text
+ PARAMS ((const location_t *, tree decl, int interface));
+
+static void snarf_block PARAMS ((struct unparsed_text *t));
static tree snarf_defarg PARAMS ((void));
-static void snarf_parenthesized_expression PARAMS ((const char *, int));
+static void snarf_parenthesized_expression (struct unparsed_text *);
static int frob_id PARAMS ((int, int, tree *));
/* The list of inline functions being held off until we reach the end of
the current class declaration. */
-static struct unparsed_text *pending_inlines;
-static struct unparsed_text *pending_inlines_tail;
+static GTY(()) struct unparsed_text *pending_inlines;
+static GTY(()) struct unparsed_text *pending_inlines_tail;
/* The list of previously-deferred inline functions currently being parsed.
This exists solely to be a GC root. */
-static struct unparsed_text *processing_these_inlines;
+static GTY(()) struct unparsed_text *processing_these_inlines;
static void begin_parsing_inclass_inline PARAMS ((struct unparsed_text *));
@@ -152,52 +170,33 @@ extern int yychar; /* the lookahead symbol */
extern YYSTYPE yylval; /* the semantic value of the */
/* lookahead symbol */
/* The token fifo lives in this obstack. */
-struct obstack token_obstack;
-int first_token;
-
-/* Sometimes we need to save tokens for later parsing. If so, they are
- stored on this obstack. */
-struct obstack inline_text_obstack;
-char *inline_text_firstobj;
+static struct obstack token_obstack;
+static int first_token;
/* When we see a default argument in a method declaration, we snarf it as
text using snarf_defarg. When we get up to namespace scope, we then go
through and parse all of them using do_pending_defargs. Since yacc
parsers are not reentrant, we retain defargs state in these two
variables so that subsequent calls to do_pending_defargs can resume
- where the previous call left off. DEFARG_FNS is a tree_list where
+ where the previous call left off. DEFARG_FNS is a tree_list where
the TREE_TYPE is the current_class_type, TREE_VALUE is the FUNCTION_DECL,
and TREE_PURPOSE is the list unprocessed dependent functions. */
-static tree defarg_fns; /* list of functions with unprocessed defargs */
-static tree defarg_parm; /* current default parameter */
-static tree defarg_depfns; /* list of unprocessed fns met during current fn. */
-static tree defarg_fnsdone; /* list of fns with circular defargs */
+/* list of functions with unprocessed defargs */
+static GTY(()) tree defarg_fns;
+/* current default parameter */
+static GTY(()) tree defarg_parm;
+/* list of unprocessed fns met during current fn. */
+static GTY(()) tree defarg_depfns;
+/* list of fns with circular defargs */
+static GTY(()) tree defarg_fnsdone;
/* Initialize obstacks. Called once, from cxx_init. */
void
init_spew ()
{
- gcc_obstack_init (&inline_text_obstack);
- inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
gcc_obstack_init (&token_obstack);
- gcc_obstack_init (&feed_obstack);
- ggc_add_tree_root (&defarg_fns, 1);
- ggc_add_tree_root (&defarg_parm, 1);
- ggc_add_tree_root (&defarg_depfns, 1);
- ggc_add_tree_root (&defarg_fnsdone, 1);
-
- ggc_add_root (&pending_inlines, 1, sizeof (struct unparsed_text *),
- mark_pending_inlines);
- ggc_add_root (&processing_these_inlines, 1, sizeof (struct unparsed_text *),
- mark_pending_inlines);
-}
-
-void
-clear_inline_text_obstack ()
-{
- obstack_free (&inline_text_obstack, inline_text_firstobj);
}
/* Subroutine of read_token. */
@@ -209,23 +208,8 @@ read_process_identifier (pyylval)
if (C_IS_RESERVED_WORD (id))
{
- /* Possibly replace the IDENTIFIER_NODE with a magic cookie.
- Can't put yylval.code numbers in ridpointers[]. Bleah. */
-
- switch (C_RID_CODE (id))
- {
- case RID_BITAND: pyylval->code = BIT_AND_EXPR; return '&';
- case RID_AND_EQ: pyylval->code = BIT_AND_EXPR; return ASSIGN;
- case RID_BITOR: pyylval->code = BIT_IOR_EXPR; return '|';
- case RID_OR_EQ: pyylval->code = BIT_IOR_EXPR; return ASSIGN;
- case RID_XOR: pyylval->code = BIT_XOR_EXPR; return '^';
- case RID_XOR_EQ: pyylval->code = BIT_XOR_EXPR; return ASSIGN;
- case RID_NOT_EQ: pyylval->code = NE_EXPR; return EQCOMPARE;
-
- default:
- pyylval->ttype = ridpointers[C_RID_CODE (id)];
- return C_RID_YYCODE (id);
- }
+ pyylval->ttype = ridpointers[C_RID_CODE (id)];
+ return C_RID_YYCODE (id);
}
/* Make sure that user does not collide with our internal naming
@@ -244,6 +228,41 @@ read_process_identifier (pyylval)
return IDENTIFIER;
}
+/* Concatenate strings before returning them to the parser. This isn't quite
+ as good as having it done in the lexer, but it's better than nothing. */
+
+static void
+yylexstring (t)
+ struct token *t;
+{
+ enum cpp_ttype next_type;
+ tree next;
+
+ next_type = c_lex (&next);
+ if (next_type == CPP_STRING || next_type == CPP_WSTRING)
+ {
+ varray_type strings;
+
+ VARRAY_TREE_INIT (strings, 32, "strings");
+ VARRAY_PUSH_TREE (strings, t->yylval.ttype);
+
+ do
+ {
+ VARRAY_PUSH_TREE (strings, next);
+ next_type = c_lex (&next);
+ }
+ while (next_type == CPP_STRING || next_type == CPP_WSTRING);
+
+ t->yylval.ttype = combine_strings (strings);
+ last_token_id = t->yylval.ttype;
+ }
+
+ /* We will have always read one token too many. */
+ _cpp_backup_tokens (parse_in, 1);
+
+ t->yychar = STRING;
+}
+
/* Read the next token from the input file. The token is written into
T, and its type number is returned. */
static int
@@ -325,7 +344,7 @@ read_token (t)
case CPP_EOF:
t->yychar = 0;
break;
-
+
case CPP_NAME:
t->yychar = read_process_identifier (&t->yylval);
break;
@@ -338,7 +357,7 @@ read_token (t)
case CPP_STRING:
case CPP_WSTRING:
- t->yychar = STRING;
+ yylexstring (t);
break;
default:
@@ -360,28 +379,28 @@ feed_input (input)
abort ();
#endif
- f = obstack_alloc (&feed_obstack, sizeof (struct feed));
+ f = ggc_alloc (sizeof (struct feed));
- /* The token list starts just after the struct unparsed_text in memory. */
- input->pos = (struct token *) (input + 1);
+ input->cur_chunk = input->tokens;
+ input->cur_pos = 0;
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\tfeeding %s:%d [%d tokens]\n",
- input->filename, input->lineno, input->limit - input->pos);
+ input->locus.file, input->locus.line, input->limit - input->pos);
#endif
f->input = input;
- f->filename = input_filename;
- f->lineno = lineno;
+ f->locus.file = input_filename;
+ f->locus.line = lineno;
f->yychar = yychar;
f->yylval = yylval;
f->first_token = first_token;
f->token_obstack = token_obstack;
f->next = feed;
- input_filename = input->filename;
- lineno = input->lineno;
+ input_filename = input->locus.file;
+ lineno = input->locus.line;
yychar = YYEMPTY;
yylval.ttype = NULL_TREE;
first_token = 0;
@@ -394,8 +413,8 @@ end_input ()
{
struct feed *f = feed;
- input_filename = f->filename;
- lineno = f->lineno;
+ input_filename = f->locus.file;
+ lineno = f->locus.line;
yychar = f->yychar;
yylval = f->yylval;
first_token = f->first_token;
@@ -403,48 +422,12 @@ end_input ()
token_obstack = f->token_obstack;
feed = f->next;
- obstack_free (&feed_obstack, f);
-
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\treturning to %s:%d\n", input_filename, lineno);
#endif
}
-/* GC callback to mark memory pointed to by the pending inline queue. */
-void
-mark_pending_inlines (pi)
- PTR pi;
-{
- struct unparsed_text *up = * (struct unparsed_text **)pi;
-
- while (up)
- {
- struct token *t = (struct token *) (up + 1);
- struct token *l = up->limit;
-
- while (t < l)
- {
- /* Some of the possible values for yychar use yylval.code
- instead of yylval.ttype. We only have to worry about
- yychars that could have been returned by read_token. */
- switch (t->yychar)
- {
- case '+': case '-': case '*': case '/':
- case '%': case '&': case '|': case '^':
- case '>': case '<': case LSHIFT: case RSHIFT:
- case ASSIGN: case MIN_MAX: case EQCOMPARE: case ARITHCOMPARE:
- t++;
- continue;
- }
- if (t->yylval.ttype)
- ggc_mark_tree (t->yylval.ttype);
- t++;
- }
- up = up->next;
- }
-}
-
/* Token queue management. */
/* Return the number of tokens available on the fifo. */
@@ -474,16 +457,24 @@ static const struct token Tpad = { EMPTY, 0 UNION_INIT_ZERO };
/* Copy the next token into T and return its value. */
static SPEW_INLINE int
-add_token (t)
+next_token (t)
struct token *t;
{
if (!feed)
return read_token (t);
- if (feed->input->pos < feed->input->limit)
+ if (feed->input->cur_chunk != feed->input->last_chunk
+ || feed->input->cur_pos != feed->input->last_pos)
{
- memcpy (t, feed->input->pos, sizeof (struct token));
- return (feed->input->pos++)->yychar;
+ if (feed->input->cur_pos == TOKEN_CHUNK_SIZE)
+ {
+ feed->input->cur_chunk = feed->input->cur_chunk->next;
+ feed->input->cur_pos = 0;
+ }
+ memcpy (t, feed->input->cur_chunk->toks + feed->input->cur_pos,
+ sizeof (struct token));
+ feed->input->cur_pos++;
+ return t->yychar;
}
return 0;
@@ -495,7 +486,7 @@ shift_token ()
{
size_t point = obstack_object_size (&token_obstack);
obstack_blank (&token_obstack, sizeof (struct token));
- return add_token ((struct token *) (obstack_base (&token_obstack) + point));
+ return next_token ((struct token *) (obstack_base (&token_obstack) + point));
}
/* Consume the next token out of the fifo. */
@@ -572,7 +563,7 @@ scan_tokens (n)
goto pad_tokens;
}
return;
-
+
pad_tokens:
while (num_tokens () <= n)
obstack_grow (&token_obstack, &Tpad, sizeof (struct token));
@@ -598,17 +589,17 @@ identifier_type (decl)
{
if (TREE_CODE (DECL_TEMPLATE_RESULT (decl)) == TYPE_DECL)
return PTYPENAME;
- else if (looking_for_template)
+ else if (looking_for_template)
return PFUNCNAME;
}
if (looking_for_template && really_overloaded_fn (decl))
{
/* See through a baselink. */
- if (TREE_CODE (decl) == TREE_LIST)
- decl = TREE_VALUE (decl);
+ if (TREE_CODE (decl) == BASELINK)
+ decl = BASELINK_FUNCTIONS (decl);
for (t = decl; t != NULL_TREE; t = OVL_CHAIN (t))
- if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t)))
+ if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t)))
return PFUNCNAME;
}
if (TREE_CODE (decl) == NAMESPACE_DECL)
@@ -642,7 +633,7 @@ static SPEW_INLINE void
do_aggr ()
{
int yc1, yc2;
-
+
scan_tokens (2);
yc1 = nth_token (1)->yychar;
if (yc1 != tTYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME)
@@ -672,12 +663,12 @@ do_aggr ()
default:
abort ();
}
-}
+}
void
see_typename ()
{
- /* Only types expected, not even namespaces. */
+ /* Only types expected, not even namespaces. */
looking_for_typename = 2;
if (yychar < 0)
if ((yychar = yylex ()) < 0) yychar = 0;
@@ -732,7 +723,7 @@ yylex ()
{
case EMPTY:
/* This is a lexical no-op. */
-#ifdef SPEW_DEBUG
+#ifdef SPEW_DEBUG
if (spew_debug)
debug_yychar (yychr);
#endif
@@ -751,7 +742,7 @@ yylex ()
case IDENTIFIER:
{
int peek;
-
+
scan_tokens (1);
peek = nth_token (1)->yychar;
yychr = frob_id (yychr, peek, &nth_token (0)->yylval.ttype);
@@ -763,7 +754,7 @@ yylex ()
case PTYPENAME:
case PTYPENAME_DEFN:
/* If we see a SCOPE next, restore the old value.
- Otherwise, we got what we want. */
+ Otherwise, we got what we want. */
looking_for_typename = old_looking_for_typename;
looking_for_template = 0;
break;
@@ -824,13 +815,13 @@ yylex ()
yychar = yychr;
{
struct token *tok = nth_token (0);
-
+
yylval = tok->yylval;
if (tok->lineno)
lineno = tok->lineno;
}
-#ifdef SPEW_DEBUG
+#ifdef SPEW_DEBUG
if (spew_debug)
debug_yychar (yychr);
#endif
@@ -841,7 +832,7 @@ yylex ()
}
/* Unget character CH from the input stream.
- If RESCAN is non-zero, then we want to `see' this
+ If RESCAN is nonzero, then we want to `see' this
character as the next input token. */
void
@@ -854,13 +845,6 @@ yyungetc (ch, rescan)
{
struct token fake;
- /* If we're putting back a brace, undo the change in indent_level
- from the first time we saw it. */
- if (ch == '{')
- indent_level--;
- else if (ch == '}')
- indent_level++;
-
fake.yychar = ch;
fake.yylval.ttype = 0;
fake.lineno = lineno;
@@ -883,7 +867,7 @@ frob_id (yyc, peek, idp)
{
tree trrr;
int old_looking_for_typename = 0;
-
+
if (peek == SCOPE)
{
/* Don't interfere with the setting from an 'aggr' prefix. */
@@ -903,7 +887,7 @@ frob_id (yyc, peek, idp)
case NSNAME:
case PTYPENAME:
/* If this got special lookup, remember it. In these
- cases, we know it can't be a declarator-id. */
+ cases, we know it can't be a declarator-id. */
if (got_scope || got_object)
*idp = trrr;
/* FALLTHROUGH */
@@ -1030,35 +1014,80 @@ process_next_inline (i)
extract_interface_info ();
}
}
+
+/* Create a new token at the end of the token list in T. */
+static SPEW_INLINE struct token *
+space_for_token (t)
+ struct unparsed_text *t;
+{
+ if (t->last_pos != TOKEN_CHUNK_SIZE)
+ return t->last_chunk->toks + (t->last_pos++);
+ t->last_chunk->next = ggc_alloc_cleared (sizeof (*t->last_chunk->next));
+ t->last_chunk = t->last_chunk->next;
+ t->last_chunk->next = NULL;
+
+ t->last_pos = 1;
+ return t->last_chunk->toks;
+}
+
+/* Shrink the token list in T by one token. */
+static SPEW_INLINE struct token *
+remove_last_token (t)
+ struct unparsed_text *t;
+{
+ struct token *result = t->last_chunk->toks + t->last_pos - 1;
+ if (t->last_pos == 0)
+ abort ();
+ t->last_pos--;
+ if (t->last_pos == 0 && t->last_chunk != t->tokens)
+ {
+ struct token_chunk *c;
+ c = t->tokens;
+ while (c->next != t->last_chunk)
+ c = c->next;
+ c->next = NULL;
+ t->last_chunk = c;
+ t->last_pos = ARRAY_SIZE (c->toks);
+ }
+ return result;
+}
+
+/* Allocate an 'unparsed_text' structure, ready to use space_for_token. */
+static struct unparsed_text *
+alloc_unparsed_text (locus, decl, interface)
+ const location_t *locus;
+ tree decl;
+ int interface;
+{
+ struct unparsed_text *r;
+ r = ggc_alloc_cleared (sizeof (*r));
+ r->decl = decl;
+ r->locus = *locus;
+ r->interface = interface;
+ r->tokens = r->last_chunk = ggc_alloc_cleared (sizeof (*r->tokens));
+ return r;
+}
/* Accumulate the tokens that make up a parenthesized expression in T,
having already read the opening parenthesis. */
static void
-snarf_parenthesized_expression (starting_file, starting_line)
- const char *starting_file;
- int starting_line;
+snarf_parenthesized_expression (struct unparsed_text *t)
{
int yyc;
int level = 1;
while (1)
{
- size_t point;
-
- point = obstack_object_size (&inline_text_obstack);
- obstack_blank (&inline_text_obstack, sizeof (struct token));
- yyc = add_token ((struct token *)
- (obstack_base (&inline_text_obstack) + point));
+ yyc = next_token (space_for_token (t));
if (yyc == '(')
++level;
else if (yyc == ')' && --level == 0)
break;
else if (yyc == 0)
{
- error_with_file_and_line (starting_file, starting_line,
- "end of file read inside definition");
+ error ("%Hend of file read inside definition", &t->locus);
break;
}
}
@@ -1066,22 +1095,19 @@ snarf_parenthesized_expression (starting_file, starting_line)
/* Subroutine of snarf_method, deals with actual absorption of the block. */
-static SPEW_INLINE void
-snarf_block (starting_file, starting_line)
- const char *starting_file;
- int starting_line;
+static void
+snarf_block (t)
+ struct unparsed_text *t;
{
int blev = 1;
int look_for_semicolon = 0;
int look_for_lbrac = 0;
int look_for_catch = 0;
int yyc;
- struct token tmp;
- size_t point;
+ struct token *current;
if (yychar == '{')
- /* We incremented indent_level in yylex; undo that. */
- indent_level--;
+ ;
else if (yychar == '=')
look_for_semicolon = 1;
else if (yychar == ':' || yychar == RETURN_KEYWORD || yychar == TRY)
@@ -1095,17 +1121,14 @@ snarf_block (starting_file, starting_line)
yyerror ("parse error in method specification");
/* The current token is the first one to be recorded. */
- tmp.yychar = yychar;
- tmp.yylval = yylval;
- tmp.lineno = lineno;
- obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
+ current = space_for_token (t);
+ current->yychar = yychar;
+ current->yylval = yylval;
+ current->lineno = lineno;
for (;;)
{
- point = obstack_object_size (&inline_text_obstack);
- obstack_blank (&inline_text_obstack, sizeof (struct token));
- yyc = add_token ((struct token *)
- (obstack_base (&inline_text_obstack) + point));
+ yyc = next_token (space_for_token (t));
if (yyc == '{')
{
@@ -1119,39 +1142,40 @@ snarf_block (starting_file, starting_line)
{
if (!look_for_catch)
break;
-
- if (add_token (&tmp) != CATCH)
+
+ if (next_token (space_for_token (t)) != CATCH)
{
- push_token (&tmp);
+ push_token (remove_last_token (t));
break;
}
look_for_lbrac = 1;
- obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
}
}
else if (yyc == ';')
{
if (look_for_lbrac)
{
+ struct token *fake;
+
error ("function body for constructor missing");
/* fake a { } to avoid further errors */
- tmp.yylval.ttype = 0;
- tmp.yychar = '{';
- obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
- tmp.yychar = '}';
- obstack_grow (&inline_text_obstack, &tmp, sizeof (struct token));
+ fake = space_for_token (t);
+ fake->yylval.ttype = 0;
+ fake->yychar = '{';
+ fake = space_for_token (t);
+ fake->yylval.ttype = 0;
+ fake->yychar = '}';
break;
}
else if (look_for_semicolon && blev == 0)
break;
}
else if (yyc == '(' && blev == 0)
- snarf_parenthesized_expression (starting_file, starting_line);
+ snarf_parenthesized_expression (t);
else if (yyc == 0)
{
- error_with_file_and_line (starting_file, starting_line,
- "end of file read inside definition");
+ error ("%Hend of file read inside definition", &t->locus);
break;
}
}
@@ -1163,60 +1187,43 @@ void
snarf_method (decl)
tree decl;
{
- int starting_lineno = lineno;
- const char *starting_filename = input_filename;
- size_t len;
- int i;
-
struct unparsed_text *meth;
+ location_t starting;
+ starting.file = input_filename;
+ starting.line = lineno;
- /* Leave room for the header, then absorb the block. */
- obstack_blank (&inline_text_obstack, sizeof (struct unparsed_text));
- snarf_block (starting_filename, starting_lineno);
+ meth = alloc_unparsed_text (&starting, decl, (interface_unknown ? 1
+ : (interface_only ? 0 : 2)));
+
+ snarf_block (meth);
/* Add three END_OF_SAVED_INPUT tokens. We used to provide an
infinite stream of END_OF_SAVED_INPUT tokens -- but that can
cause the compiler to get stuck in an infinite loop when
encountering invalid code. We need more than one because the
parser sometimes peeks ahead several tokens. */
- for (i = 0; i < 3; ++i)
- {
- size_t point = obstack_object_size (&inline_text_obstack);
- obstack_blank (&inline_text_obstack, sizeof (struct token));
- memcpy ((struct token *)
- (obstack_base (&inline_text_obstack) + point),
- &Teosi,
- sizeof (struct token));
- }
-
- len = obstack_object_size (&inline_text_obstack);
- meth = (struct unparsed_text *) obstack_finish (&inline_text_obstack);
+ memcpy (space_for_token (meth), &Teosi, sizeof (struct token));
+ memcpy (space_for_token (meth), &Teosi, sizeof (struct token));
+ memcpy (space_for_token (meth), &Teosi, sizeof (struct token));
/* Happens when we get two declarations of the same function in the
same scope. */
if (decl == void_type_node
|| (current_class_type && TYPE_REDEFINED (current_class_type)))
- {
- obstack_free (&inline_text_obstack, (char *)meth);
- return;
- }
-
- meth->decl = decl;
- meth->filename = starting_filename;
- meth->lineno = starting_lineno;
- meth->limit = (struct token *) ((char *)meth + len);
- meth->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
- meth->next = 0;
+ return;
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\tsaved method of %d tokens from %s:%d\n",
- meth->limit - (struct token *) (meth + 1),
- starting_filename, starting_lineno);
+ meth->limit, starting.file, starting.line);
#endif
DECL_PENDING_INLINE_INFO (decl) = meth;
DECL_PENDING_INLINE_P (decl) = 1;
+ /* We need to know that this was defined in the class, so that
+ friend templates are handled correctly. */
+ DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
+
if (pending_inlines_tail)
pending_inlines_tail->next = meth;
else
@@ -1224,30 +1231,25 @@ snarf_method (decl)
pending_inlines_tail = meth;
}
-/* Consume a no-commas expression - a default argument - and save it
- on the inline_text_obstack. */
+/* Consume a no-commas expression - a default argument - and return
+ a DEFAULT_ARG tree node. */
static tree
snarf_defarg ()
{
- int starting_lineno = lineno;
- const char *starting_filename = input_filename;
int yyc;
int plev = 0;
- size_t point;
- size_t len;
struct unparsed_text *buf;
- int i;
tree arg;
+ location_t starting;
+ starting.file = input_filename;
+ starting.line = lineno;
- obstack_blank (&inline_text_obstack, sizeof (struct unparsed_text));
+ buf = alloc_unparsed_text (&starting, 0, 0);
for (;;)
{
- point = obstack_object_size (&inline_text_obstack);
- obstack_blank (&inline_text_obstack, sizeof (struct token));
- yyc = add_token ((struct token *)
- (obstack_base (&inline_text_obstack) + point));
+ yyc = next_token (space_for_token (buf));
if (plev <= 0 && (yyc == ')' || yyc == ','))
break;
@@ -1257,46 +1259,27 @@ snarf_defarg ()
--plev;
else if (yyc == 0)
{
- error_with_file_and_line (starting_filename, starting_lineno,
- "end of file read inside default argument");
+ error ("%Hend of file read inside default argument", &starting);
goto done;
}
}
/* Unget the last token. */
- push_token ((struct token *) (obstack_base (&inline_text_obstack) + point));
- /* This is the documented way to shrink a growing obstack block. */
- obstack_blank (&inline_text_obstack, - (int) sizeof (struct token));
+ push_token (remove_last_token (buf));
/* Add three END_OF_SAVED_INPUT tokens. We used to provide an
infinite stream of END_OF_SAVED_INPUT tokens -- but that can
cause the compiler to get stuck in an infinite loop when
encountering invalid code. We need more than one because the
parser sometimes peeks ahead several tokens. */
- for (i = 0; i < 3; ++i)
- {
- point = obstack_object_size (&inline_text_obstack);
- obstack_blank (&inline_text_obstack, sizeof (struct token));
- memcpy ((struct token *)
- (obstack_base (&inline_text_obstack) + point),
- &Teosi,
- sizeof (struct token));
- }
+ memcpy (space_for_token (buf), &Teosi, sizeof (struct token));
+ memcpy (space_for_token (buf), &Teosi, sizeof (struct token));
+ memcpy (space_for_token (buf), &Teosi, sizeof (struct token));
done:
- len = obstack_object_size (&inline_text_obstack);
- buf = (struct unparsed_text *) obstack_finish (&inline_text_obstack);
-
- buf->decl = 0;
- buf->filename = starting_filename;
- buf->lineno = starting_lineno;
- buf->limit = (struct token *) ((char *)buf + len);
- buf->next = 0;
-
#ifdef SPEW_DEBUG
if (spew_debug)
fprintf (stderr, "\tsaved defarg of %d tokens from %s:%d\n",
- buf->limit - (struct token *) (buf + 1),
- starting_filename, starting_lineno);
+ buf->limit, starting.file, starting.line);
#endif
arg = make_node (DEFAULT_ARG);
@@ -1328,7 +1311,7 @@ add_defarg_fn (decl)
TREE_VALUE (defarg_fns) = decl;
else
{
- defarg_fns = tree_cons (NULL_TREE, decl, defarg_fns);
+ defarg_fns = tree_cons (NULL_TREE, decl, defarg_fns);
TREE_TYPE (defarg_fns) = current_class_type;
}
}
@@ -1357,7 +1340,7 @@ finish_defarg ()
error ("parse error at end of saved function text");
end_input ();
-}
+}
/* Main function for deferred parsing of default arguments. Called from
the parser. */
@@ -1371,7 +1354,7 @@ do_pending_defargs ()
for (; defarg_fns;)
{
tree current = defarg_fns;
-
+
tree defarg_fn = TREE_VALUE (defarg_fns);
if (defarg_parm == NULL_TREE)
{
@@ -1411,7 +1394,7 @@ do_pending_defargs ()
poplevel (0, 0, 0);
pop_nested_class ();
-
+
defarg_fns = TREE_CHAIN (defarg_fns);
if (defarg_depfns)
{
@@ -1419,8 +1402,8 @@ do_pending_defargs ()
of defarg_fns. We will need to reprocess this function, and
check for circular dependencies. */
tree a, b;
-
- for (a = defarg_depfns, b = TREE_PURPOSE (current); a && b;
+
+ for (a = defarg_depfns, b = TREE_PURPOSE (current); a && b;
a = TREE_CHAIN (a), b = TREE_CHAIN (b))
if (TREE_VALUE (a) != TREE_VALUE (b))
goto different;
@@ -1436,8 +1419,8 @@ do_pending_defargs ()
cp_warning_at ("circular dependency in default args of `%#D'", defarg_fn);
/* No need to say what else is dependent, as they will be
picked up in another pass. */
-
- /* Immediately repeat, but marked so that we break the loop. */
+
+ /* Immediately repeat, but marked so that we break the loop. */
defarg_fns = current;
TREE_PURPOSE (current) = error_mark_node;
}
@@ -1449,7 +1432,7 @@ do_pending_defargs ()
}
/* After parsing all the default arguments, we must clear any that remain,
- which will be part of a circular dependency. */
+ which will be part of a circular dependency. */
void
done_pending_defargs ()
{
@@ -1457,7 +1440,7 @@ done_pending_defargs ()
{
tree fn = TREE_VALUE (defarg_fnsdone);
tree parms;
-
+
if (TREE_CODE (fn) == FUNCTION_DECL)
parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
else
@@ -1504,7 +1487,7 @@ replace_defarg (arg, init)
}
}
-#ifdef SPEW_DEBUG
+#ifdef SPEW_DEBUG
/* debug_yychar takes a yychar (token number) value and prints its name. */
static void
@@ -1542,12 +1525,17 @@ yyerror (msgid)
error ("%s at end of input", string);
else if (last_token == CPP_CHAR || last_token == CPP_WCHAR)
{
- unsigned int val = TREE_INT_CST_LOW (yylval.ttype);
- const char *const ell = (last_token == CPP_CHAR) ? "" : "L";
- if (val <= UCHAR_MAX && ISGRAPH (val))
- error ("%s before %s'%c'", string, ell, val);
+ if (yylval.ttype && TREE_CODE (yylval.ttype) == INTEGER_CST)
+ {
+ unsigned int val = TREE_INT_CST_LOW (yylval.ttype);
+ const char *const ell = (last_token == CPP_CHAR) ? "" : "L";
+ if (val <= UCHAR_MAX && ISGRAPH (val))
+ error ("%s before %s'%c'", string, ell, val);
+ else
+ error ("%s before %s'\\x%x'", string, ell, val);
+ }
else
- error ("%s before %s'\\x%x'", string, ell, val);
+ error ("%s", string);
}
else if (last_token == CPP_STRING
|| last_token == CPP_WSTRING)
@@ -1566,3 +1554,5 @@ yyerror (msgid)
else
error ("%s before `%s' token", string, NAME (last_token));
}
+
+#include "gt-cp-spew.h"
diff --git a/contrib/gcc/cp/tree.c b/contrib/gcc/cp/tree.c
index cdfa49c..ce6137e 100644
--- a/contrib/gcc/cp/tree.c
+++ b/contrib/gcc/cp/tree.c
@@ -22,16 +22,17 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
-#include "obstack.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
+#include "real.h"
#include "rtl.h"
#include "toplev.h"
#include "ggc.h"
#include "insn-config.h"
#include "integrate.h"
#include "tree-inline.h"
+#include "target.h"
static tree bot_manip PARAMS ((tree *, int *, void *));
static tree bot_replace PARAMS ((tree *, int *, void *));
@@ -39,12 +40,11 @@ static tree build_cplus_array_type_1 PARAMS ((tree, tree));
static int list_hash_eq PARAMS ((const void *, const void *));
static hashval_t list_hash_pieces PARAMS ((tree, tree, tree));
static hashval_t list_hash PARAMS ((const void *));
-static cp_lvalue_kind lvalue_p_1 PARAMS ((tree, int));
+static cp_lvalue_kind lvalue_p_1 PARAMS ((tree, int, int));
static tree no_linkage_helper PARAMS ((tree *, int *, void *));
static tree build_srcloc PARAMS ((const char *, int));
static tree mark_local_for_remap_r PARAMS ((tree *, int *, void *));
static tree cp_unsave_r PARAMS ((tree *, int *, void *));
-static void cp_unsave PARAMS ((tree *));
static tree build_target_expr PARAMS ((tree, tree));
static tree count_trees_r PARAMS ((tree *, int *, void *));
static tree verify_stmt_tree_r PARAMS ((tree *, int *, void *));
@@ -57,12 +57,13 @@ static tree handle_init_priority_attribute PARAMS ((tree *, tree, tree, int, boo
/* If REF is an lvalue, returns the kind of lvalue that REF is.
Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
- non-zero, rvalues of class type are considered lvalues. */
+ nonzero, rvalues of class type are considered lvalues. */
static cp_lvalue_kind
-lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
+lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue)
tree ref;
int treat_class_rvalues_as_lvalues;
+ int allow_cast_as_lvalue;
{
cp_lvalue_kind op1_lvalue_kind = clk_none;
cp_lvalue_kind op2_lvalue_kind = clk_none;
@@ -85,16 +86,28 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
case WITH_CLEANUP_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
- /* This shouldn't be here, but there are lots of places in the compiler
- that are sloppy about tacking on NOP_EXPRs to the same type when
- no actual conversion is happening. */
- case NOP_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
+
+ case NOP_EXPR:
+ /* If expression doesn't change the type, we consider it as an
+ lvalue even when cast_as_lvalue extension isn't selected.
+ That's because parts of the compiler are alleged to be sloppy
+ about sticking in NOP_EXPR node for no good reason. */
+ if (allow_cast_as_lvalue ||
+ same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ref)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (ref, 0)))))
+ return lvalue_p_1 (TREE_OPERAND (ref, 0),
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
+ else
+ return clk_none;
case COMPONENT_REF:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
if (op1_lvalue_kind
/* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
situations. */
@@ -135,16 +148,20 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
case MAX_EXPR:
case MIN_EXPR:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
break;
case COND_EXPR:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
break;
case MODIFY_EXPR:
@@ -152,7 +169,8 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
case COMPOUND_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
+ treat_class_rvalues_as_lvalues,
+ allow_cast_as_lvalue);
case TARGET_EXPR:
return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
@@ -197,7 +215,19 @@ cp_lvalue_kind
real_lvalue_p (ref)
tree ref;
{
- return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);
+ return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/ 0, /*cast*/ 1);
+}
+
+/* Returns the kind of lvalue that REF is, in the sense of
+ [basic.lval]. This function should really be named lvalue_p; it
+ computes the C++ definition of lvalue. */
+
+cp_lvalue_kind
+real_non_cast_lvalue_p (tree ref)
+{
+ return lvalue_p_1 (ref,
+ /*treat_class_rvalues_as_lvalues=*/0,
+ /*allow_cast_as_lvalue=*/0);
}
/* This differs from real_lvalue_p in that class rvalues are
@@ -208,7 +238,15 @@ lvalue_p (ref)
tree ref;
{
return
- (lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1) != clk_none);
+ (lvalue_p_1 (ref, /*class rvalue ok*/ 1, /*cast*/ 1) != clk_none);
+}
+
+int
+non_cast_lvalue_p (ref)
+ tree ref;
+{
+ return
+ (lvalue_p_1 (ref, /*class rvalue ok*/ 1, /*cast*/ 0) != clk_none);
}
/* Return nonzero if REF is an lvalue valid for this language;
@@ -219,7 +257,20 @@ lvalue_or_else (ref, string)
tree ref;
const char *string;
{
- int win = lvalue_p (ref);
+ int ret = lvalue_p_1 (ref, /* class rvalue ok */ 1, /* cast ok */ 1);
+ int win = (ret != clk_none);
+ if (! win)
+ error ("non-lvalue in %s", string);
+ return win;
+}
+
+int
+non_cast_lvalue_or_else (ref, string)
+ tree ref;
+ const char *string;
+{
+ int ret = lvalue_p_1 (ref, /* class rvalue ok */ 1, /* cast ok */ 0);
+ int win = (ret != clk_none);
if (! win)
error ("non-lvalue in %s", string);
return win;
@@ -235,7 +286,7 @@ build_target_expr (decl, value)
tree t;
t = build (TARGET_EXPR, TREE_TYPE (decl), decl, value,
- maybe_build_cleanup (decl), NULL_TREE);
+ cxx_maybe_build_cleanup (decl), NULL_TREE);
/* We always set TREE_SIDE_EFFECTS so that expand_expr does not
ignore the TARGET_EXPR. If there really turn out to be no
side-effects, then the optimizer should be able to get rid of
@@ -293,7 +344,7 @@ build_cplus_new (type, init)
return rval;
}
-/* Buidl a TARGET_EXPR using INIT to initialize a new temporary of the
+/* Build a TARGET_EXPR using INIT to initialize a new temporary of the
indicated TYPE. */
tree
@@ -471,7 +522,7 @@ build_cplus_array_type_1 (elt_type, index_type)
&& index_type && TYPE_MAX_VALUE (index_type)
&& TREE_CODE (TYPE_MAX_VALUE (index_type)) != INTEGER_CST)
|| uses_template_parms (elt_type)
- || uses_template_parms (index_type))
+ || (index_type && uses_template_parms (index_type)))
{
t = make_node (ARRAY_TYPE);
TREE_TYPE (t) = elt_type;
@@ -496,14 +547,16 @@ build_cplus_array_type (elt_type, index_type)
{
tree t;
int type_quals = cp_type_quals (elt_type);
+ int cv_quals = type_quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
+ int other_quals = type_quals & ~(TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
- if (type_quals != TYPE_UNQUALIFIED)
- elt_type = cp_build_qualified_type (elt_type, TYPE_UNQUALIFIED);
+ if (cv_quals)
+ elt_type = cp_build_qualified_type (elt_type, other_quals);
t = build_cplus_array_type_1 (elt_type, index_type);
- if (type_quals != TYPE_UNQUALIFIED)
- t = cp_build_qualified_type (t, type_quals);
+ if (cv_quals)
+ t = cp_build_qualified_type (t, cv_quals);
return t;
}
@@ -610,9 +663,12 @@ cp_build_qualified_type_real (type, type_quals, complain)
return error_mark_node;
/* See if we already have an identically qualified type. */
- t = get_qualified_type (type, type_quals);
-
- /* If we didn't already have it, create it now. */
+ for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+ if (cp_type_quals (t) == type_quals
+ && TYPE_NAME (t) == TYPE_NAME (type)
+ && TYPE_CONTEXT (t) == TYPE_CONTEXT (type))
+ break;
+
if (!t)
{
/* Make a new array type, just like the old one, but with the
@@ -651,13 +707,13 @@ cp_build_qualified_type_real (type, type_quals, complain)
result = build_qualified_type (type, type_quals);
/* If this was a pointer-to-method type, and we just made a copy,
- then we need to clear the cached associated
- pointer-to-member-function type; it is not valid for the new
- type. */
+ then we need to unshare the record that holds the cached
+ pointer-to-member-function type, because these will be distinct
+ between the unqualified and qualified types. */
if (result != type
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
- TYPE_SET_PTRMEMFUNC_TYPE (result, NULL_TREE);
+ TYPE_LANG_SPECIFIC (result) = NULL;
return result;
}
@@ -717,7 +773,7 @@ unshare_base_binfos (binfo)
While all these live in the same table, they are completely independent,
and the hash code is computed differently for each of these. */
-static htab_t list_hash_table;
+static GTY ((param_is (union tree_node))) htab_t list_hash_table;
struct list_proxy
{
@@ -955,7 +1011,7 @@ is_overloaded_fn (x)
if (TREE_CODE (x) == OFFSET_REF)
x = TREE_OPERAND (x, 1);
if (BASELINK_P (x))
- x = TREE_VALUE (x);
+ x = BASELINK_FUNCTIONS (x);
return (TREE_CODE (x) == FUNCTION_DECL
|| TREE_CODE (x) == TEMPLATE_ID_EXPR
|| DECL_FUNCTION_TEMPLATE_P (x)
@@ -970,10 +1026,25 @@ really_overloaded_fn (x)
if (TREE_CODE (x) == OFFSET_REF)
x = TREE_OPERAND (x, 1);
if (BASELINK_P (x))
- x = TREE_VALUE (x);
- return (TREE_CODE (x) == OVERLOAD
- && (TREE_CHAIN (x) != NULL_TREE
- || DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (x))));
+ x = BASELINK_FUNCTIONS (x);
+
+ return ((TREE_CODE (x) == OVERLOAD && OVL_CHAIN (x))
+ || DECL_FUNCTION_TEMPLATE_P (OVL_CURRENT (x))
+ || TREE_CODE (x) == TEMPLATE_ID_EXPR);
+}
+
+/* Return the OVERLOAD or FUNCTION_DECL inside FNS. FNS can be an
+ OVERLOAD, FUNCTION_DECL, TEMPLATE_ID_EXPR, or baselink. */
+
+tree
+get_overloaded_fn (fns)
+ tree fns;
+{
+ if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
+ fns = TREE_OPERAND (fns, 0);
+ if (BASELINK_P (fns))
+ fns = BASELINK_FUNCTIONS (fns);
+ return fns;
}
tree
@@ -981,9 +1052,9 @@ get_first_fn (from)
tree from;
{
my_friendly_assert (is_overloaded_fn (from), 9);
- /* A baselink is also considered an overloaded function. */
+ /* A baselink is also considered an overloaded function. */
if (BASELINK_P (from))
- from = TREE_VALUE (from);
+ from = BASELINK_FUNCTIONS (from);
return OVL_CURRENT (from);
}
@@ -998,7 +1069,7 @@ bound_pmf_p (t)
&& TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (t, 1))));
}
-/* Return a new OVL node, concatenating it with the old one. */
+/* Return a new OVL node, concatenating it with the old one. */
tree
ovl_cons (decl, chain)
@@ -1037,7 +1108,7 @@ is_aggr_type_2 (t1, t2)
return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2);
}
-/* Returns non-zero if CODE is the code for a statement. */
+/* Returns nonzero if CODE is the code for a statement. */
int
cp_statement_code_p (code)
@@ -1045,8 +1116,6 @@ cp_statement_code_p (code)
{
switch (code)
{
- case SUBOBJECT:
- case CTOR_STMT:
case CTOR_INITIALIZER:
case RETURN_INIT:
case TRY_BLOCK:
@@ -1064,7 +1133,7 @@ cp_statement_code_p (code)
#define PRINT_RING_SIZE 4
const char *
-lang_printable_name (decl, v)
+cxx_printable_name (decl, v)
tree decl;
int v;
{
@@ -1500,19 +1569,19 @@ build_min VPARAMS ((enum tree_code code, tree tt, ...))
same node; therefore, callers should never modify the node
returned. */
+static GTY(()) tree shared_int_cache[256];
+
tree
build_shared_int_cst (i)
int i;
{
- static tree cache[256];
-
if (i >= 256)
return build_int_2 (i, 0);
- if (!cache[i])
- cache[i] = build_int_2 (i, 0);
+ if (!shared_int_cache[i])
+ shared_int_cache[i] = build_int_2 (i, 0);
- return cache[i];
+ return shared_int_cache[i];
}
tree
@@ -1680,8 +1749,10 @@ cp_tree_equal (t1, t2)
return 0;
case TEMPLATE_PARM_INDEX:
- return TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
- && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2);
+ return (TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
+ && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2)
+ && same_type_p (TREE_TYPE (TEMPLATE_PARM_DECL (t1)),
+ TREE_TYPE (TEMPLATE_PARM_DECL (t2))));
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
@@ -1729,25 +1800,15 @@ cp_tree_equal (t1, t2)
return -1;
}
-/* Build a wrapper around some pointer PTR so we can use it as a tree. */
+/* Build a wrapper around a 'struct z_candidate' so we can use it as a
+ tree. */
tree
-build_ptr_wrapper (ptr)
- void *ptr;
+build_zc_wrapper (ptr)
+ struct z_candidate *ptr;
{
tree t = make_node (WRAPPER);
- WRAPPER_PTR (t) = ptr;
- return t;
-}
-
-/* Build a wrapper around some integer I so we can use it as a tree. */
-
-tree
-build_int_wrapper (i)
- int i;
-{
- tree t = make_node (WRAPPER);
- WRAPPER_INT (t) = i;
+ WRAPPER_ZC (t) = ptr;
return t;
}
@@ -1861,7 +1922,12 @@ maybe_dummy_object (type, binfop)
if (binfop)
*binfop = binfo;
- if (current_class_ref && context == current_class_type)
+ if (current_class_ref && context == current_class_type
+ /* Kludge: Make sure that current_class_type is actually
+ correct. It might not be if we're in the middle of
+ tsubst_default_argument. */
+ && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)),
+ current_class_type))
decl = current_class_ref;
else
decl = build_dummy_object (context);
@@ -1889,6 +1955,8 @@ pod_type_p (t)
{
t = strip_array_types (t);
+ if (t == error_mark_node)
+ return 1;
if (INTEGRAL_TYPE_P (t))
return 1; /* integral, character or enumeral type */
if (FLOAT_TYPE_P (t))
@@ -1912,24 +1980,27 @@ pod_type_p (t)
int
zero_init_p (t)
- tree t ATTRIBUTE_UNUSED;
+ tree t;
{
- /* This is not a correct implementation of this function. As a
- result, pointers-to-members will not be correctly
- zero-initialized.
+ t = strip_array_types (t);
+
+ if (t == error_mark_node)
+ return 1;
- However, using a correct implementation of this function results
- in many other failures. Correcting these other failures required
- a major infrastructure improvement, which was undertaken in the
- GCC 3.3 source base.
+ /* NULL pointers to data members are initialized with -1. */
+ if (TYPE_PTRMEM_P (t))
+ return 0;
+
+ /* Classes that contain types that can't be zero-initialized, cannot
+ be zero-initialized themselves. */
+ if (CLASS_TYPE_P (t) && CLASSTYPE_NON_ZERO_INIT_P (t))
+ return 0;
- In order to reduce risk, these changes were not ported to the GCC
- 3.2 source base. */
return 1;
}
/* Table of valid C++ attributes. */
-const struct attribute_spec cp_attribute_table[] =
+const struct attribute_spec cxx_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
{ "java_interface", 0, 0, false, false, false, handle_java_interface_attribute },
@@ -2031,7 +2102,7 @@ handle_init_priority_attribute (node, name, args, flags, no_add_attrs)
/* Static objects in functions are initialized the
first time control passes through that
function. This is not precise enough to pin down an
- init_priority value, so don't allow it. */
+ init_priority value, so don't allow it. */
|| current_function_decl)
{
error ("can only use `%s' attribute on file-scope definitions of objects of class type",
@@ -2181,6 +2252,14 @@ cp_cannot_inline_tree_fn (fnp)
return 1;
}
+ /* Don't auto-inline anything that might not be bound within
+ this unit of translation. */
+ if (!DECL_DECLARED_INLINE_P (fn) && !(*targetm.binds_local_p) (fn))
+ {
+ DECL_UNINLINABLE (fn) = 1;
+ return 1;
+ }
+
if (varargs_function_p (fn))
{
DECL_UNINLINABLE (fn) = 1;
@@ -2290,8 +2369,7 @@ cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
position so we can get reasonable debugging information, and
register the return variable as its equivalent. */
DECL_NAME (var) = DECL_NAME (nrv);
- DECL_SOURCE_FILE (var) = DECL_SOURCE_FILE (nrv);
- DECL_SOURCE_LINE (var) = DECL_SOURCE_LINE (nrv);
+ DECL_SOURCE_LOCATION (var) = DECL_SOURCE_LOCATION (nrv);
DECL_ABSTRACT_ORIGIN (var) = DECL_ORIGIN (nrv);
/* Don't lose initialization info. */
DECL_INITIAL (var) = DECL_INITIAL (nrv);
@@ -2307,7 +2385,7 @@ cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_,
return var;
}
-/* Record that we're about to start inlining FN, and return non-zero if
+/* Record that we're about to start inlining FN, and return nonzero if
that's OK. Used for lang_hooks.tree_inlining.start_inlining. */
int
@@ -2336,14 +2414,8 @@ cp_end_inlining (fn)
void
init_tree ()
{
- make_lang_type_fn = cp_make_lang_type;
- lang_unsave = cp_unsave;
lang_statement_code_p = cp_statement_code_p;
- lang_set_decl_assembler_name = mangle_decl;
- list_hash_table = htab_create (31, list_hash, list_hash_eq, NULL);
- ggc_add_root (&list_hash_table, 1,
- sizeof (list_hash_table),
- mark_tree_hashtable);
+ list_hash_table = htab_create_ggc (31, list_hash, list_hash_eq, NULL);
}
/* Called via walk_tree. If *TP points to a DECL_STMT for a local
@@ -2429,12 +2501,11 @@ cp_unsave_r (tp, walk_subtrees, data)
return NULL_TREE;
}
-/* Called by unsave_expr_now whenever an expression (*TP) needs to be
- unsaved. */
+/* Called whenever an expression needs to be unsaved. */
-static void
-cp_unsave (tp)
- tree *tp;
+tree
+cxx_unsave_expr_now (tp)
+ tree tp;
{
splay_tree st;
@@ -2443,18 +2514,20 @@ cp_unsave (tp)
st = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
/* Walk the tree once figuring out what needs to be remapped. */
- walk_tree (tp, mark_local_for_remap_r, st, NULL);
+ walk_tree (&tp, mark_local_for_remap_r, st, NULL);
/* Walk the tree again, copying, remapping, and unsaving. */
- walk_tree (tp, cp_unsave_r, st, NULL);
+ walk_tree (&tp, cp_unsave_r, st, NULL);
/* Clean up. */
splay_tree_delete (st);
+
+ return tp;
}
/* Returns the kind of special function that DECL (a FUNCTION_DECL)
- is. Note that this sfk_none is zero, so this function can be used
- as a predicate to test whether or not DECL is a special function. */
+ is. Note that sfk_none is zero, so this function can be used as a
+ predicate to test whether or not DECL is a special function. */
special_function_kind
special_function_p (decl)
@@ -2483,7 +2556,23 @@ special_function_p (decl)
return sfk_none;
}
-/* Returns non-zero if TYPE is a character type, including wchar_t. */
+/* Returns true if and only if NODE is a name, i.e., a node created
+ by the parser when processing an id-expression. */
+
+bool
+name_p (tree node)
+{
+ if (TREE_CODE (node) == TEMPLATE_ID_EXPR)
+ node = TREE_OPERAND (node, 0);
+ return (/* An ordinary unqualified name. */
+ TREE_CODE (node) == IDENTIFIER_NODE
+ /* A destructor name. */
+ || TREE_CODE (node) == BIT_NOT_EXPR
+ /* A qualified name. */
+ || TREE_CODE (node) == SCOPE_REF);
+}
+
+/* Returns nonzero if TYPE is a character type, including wchar_t. */
int
char_type_p (type)
@@ -2537,3 +2626,53 @@ decl_linkage (decl)
/* Everything else has internal linkage. */
return lk_internal;
}
+
+/* EXP is an expression that we want to pre-evaluate. Returns via INITP an
+ expression to perform the pre-evaluation, and returns directly an
+ expression to use the precalculated result. */
+
+tree
+stabilize_expr (exp, initp)
+ tree exp;
+ tree *initp;
+{
+ tree init_expr;
+
+ if (!TREE_SIDE_EFFECTS (exp))
+ {
+ init_expr = void_zero_node;
+ }
+ else if (!real_lvalue_p (exp)
+ || !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (exp)))
+ {
+ init_expr = get_target_expr (exp);
+ exp = TARGET_EXPR_SLOT (init_expr);
+ }
+ else
+ {
+ exp = build_unary_op (ADDR_EXPR, exp, 1);
+ init_expr = get_target_expr (exp);
+ exp = TARGET_EXPR_SLOT (init_expr);
+ exp = build_indirect_ref (exp, 0);
+ }
+
+ *initp = init_expr;
+ return exp;
+}
+
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+/* Complain that some language-specific thing hanging off a tree
+ node has been accessed improperly. */
+
+void
+lang_check_failed (file, line, function)
+ const char *file;
+ int line;
+ const char *function;
+{
+ internal_error ("lang_* check: failed in %s, at %s:%d",
+ function, trim_filename (file), line);
+}
+#endif /* ENABLE_TREE_CHECKING */
+
+#include "gt-cp-tree.h"
diff --git a/contrib/gcc/cp/typeck.c b/contrib/gcc/cp/typeck.c
index 82867eb..c161e11 100644
--- a/contrib/gcc/cp/typeck.c
+++ b/contrib/gcc/cp/typeck.c
@@ -57,7 +57,6 @@ static int comp_array_types PARAMS ((int (*) (tree, tree, int), tree,
static tree common_base_type PARAMS ((tree, tree));
static tree lookup_anon_field PARAMS ((tree, tree));
static tree pointer_diff PARAMS ((tree, tree, tree));
-static tree build_component_addr PARAMS ((tree, tree));
static tree qualify_type_recursive PARAMS ((tree, tree));
static tree get_delta_difference PARAMS ((tree, tree, int));
static int comp_cv_target_types PARAMS ((tree, tree, int));
@@ -156,14 +155,16 @@ complete_type (type)
return type;
}
-/* Like complete_type, but issue an error if the TYPE cannot be
- completed. VALUE is used for informative diagnostics.
+/* Like complete_type, but issue an error if the TYPE cannot be completed.
+ VALUE is used for informative diagnostics. DIAG_TYPE indicates the type
+ of diagnostic: 0 for an error, 1 for a warning, 2 for a pedwarn.
Returns NULL_TREE if the type cannot be made complete. */
tree
-complete_type_or_else (type, value)
+complete_type_or_diagnostic (type, value, diag_type)
tree type;
tree value;
+ int diag_type;
{
type = complete_type (type);
if (type == error_mark_node)
@@ -171,7 +172,7 @@ complete_type_or_else (type, value)
return NULL_TREE;
else if (!COMPLETE_TYPE_P (type))
{
- incomplete_type_error (value, type);
+ cxx_incomplete_type_diagnostic (value, type, diag_type);
return NULL_TREE;
}
else
@@ -202,28 +203,33 @@ qualify_type_recursive (t1, t2)
if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2))
|| (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2)))
{
- tree tt1 = TREE_TYPE (t1);
- tree tt2 = TREE_TYPE (t2);
+ tree tt1;
+ tree tt2;
tree b1;
int type_quals;
tree tgt;
tree attributes = (*targetm.merge_type_attributes) (t1, t2);
- if (TREE_CODE (tt1) == OFFSET_TYPE)
+ if (TYPE_PTRMEM_P (t1))
{
- b1 = TYPE_OFFSET_BASETYPE (tt1);
- tt1 = TREE_TYPE (tt1);
- tt2 = TREE_TYPE (tt2);
+ b1 = TYPE_PTRMEM_CLASS_TYPE (t1);
+ tt1 = TYPE_PTRMEM_POINTED_TO_TYPE (t1);
+ tt2 = TYPE_PTRMEM_POINTED_TO_TYPE (t2);
}
else
- b1 = NULL_TREE;
+ {
+ b1 = NULL_TREE;
+ tt1 = TREE_TYPE (t1);
+ tt2 = TREE_TYPE (t2);
+ }
type_quals = (cp_type_quals (tt1) | cp_type_quals (tt2));
tgt = qualify_type_recursive (tt1, tt2);
tgt = cp_build_qualified_type (tgt, type_quals);
if (b1)
- tgt = build_offset_type (b1, tgt);
- t1 = build_pointer_type (tgt);
+ t1 = build_ptrmem_type (b1, tgt);
+ else
+ t1 = build_pointer_type (tgt);
t1 = build_type_attribute_variant (t1, attributes);
}
return t1;
@@ -485,7 +491,7 @@ composite_pointer_type (t1, t2, arg1, arg2, location)
return t1;
/* Deal with pointer-to-member functions in the same way as we deal
- with pointers to functions. */
+ with pointers to functions. */
if (TYPE_PTRMEMFUNC_P (t1))
t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
if (TYPE_PTRMEMFUNC_P (t2))
@@ -777,7 +783,7 @@ comp_except_types (a, b, exact)
}
/* Return 1 if TYPE1 and TYPE2 are equivalent exception specifiers.
- If EXACT is 0, T2 can be a subset of T1 (according to 15.4/7),
+ If EXACT is 0, T2 can be stricter than T1 (according to 15.4/7),
otherwise it must be exact. Exception lists are unordered, but
we've already filtered out duplicates. Most lists will be in order,
we should try to make use of that. */
@@ -794,13 +800,13 @@ comp_except_specs (t1, t2, exact)
if (t1 == t2)
return 1;
- if (t1 == NULL_TREE) /* T1 is ... */
+ if (t1 == NULL_TREE) /* T1 is ... */
return t2 == NULL_TREE || !exact;
if (!TREE_VALUE (t1)) /* t1 is EMPTY */
return t2 != NULL_TREE && !TREE_VALUE (t2);
- if (t2 == NULL_TREE) /* T2 is ... */
+ if (t2 == NULL_TREE) /* T2 is ... */
return 0;
- if (TREE_VALUE(t1) && !TREE_VALUE (t2)) /* T2 is EMPTY, T1 is not */
+ if (TREE_VALUE (t1) && !TREE_VALUE (t2)) /* T2 is EMPTY, T1 is not */
return !exact;
/* Neither set is ... or EMPTY, make sure each part of T2 is in T1.
@@ -856,7 +862,7 @@ comp_array_types (cmp, t1, t2, strict)
return 1;
/* If one of the arrays is dimensionless, and the other has a
- dimension, they are of different types. However, it is legal to
+ dimension, they are of different types. However, it is valid to
write:
extern int a[];
@@ -896,7 +902,7 @@ comptypes (t1, t2, strict)
extern int (*i)[];
int (*i)[8];
- is not legal, for example. */
+ is invalid, for example. */
strict &= ~COMPARE_REDECLARATION;
/* Suppress errors caused by previously reported errors */
@@ -924,9 +930,9 @@ comptypes (t1, t2, strict)
/* Treat an enum type as the unsigned integer type of the same width. */
if (TREE_CODE (t1) == ENUMERAL_TYPE)
- t1 = type_for_size (TYPE_PRECISION (t1), 1);
+ t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1);
if (TREE_CODE (t2) == ENUMERAL_TYPE)
- t2 = type_for_size (TYPE_PRECISION (t2), 1);
+ t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1);
if (t1 == t2)
return 1;
@@ -1484,73 +1490,44 @@ comp_target_parms (parms1, parms2)
return warn_contravariance ? -1 : 1;
}
-/* Compute the value of the `sizeof' operator. */
-
tree
-c_sizeof (type)
+cxx_sizeof_or_alignof_type (type, op, complain)
tree type;
+ enum tree_code op;
+ int complain;
{
- enum tree_code code = TREE_CODE (type);
- tree size;
+ enum tree_code type_code;
+ tree value;
+ const char *op_name;
+ my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
if (processing_template_decl)
- return build_min_nt (SIZEOF_EXPR, type);
+ return build_min_nt (op, type);
+
+ op_name = operator_name_info[(int) op].name;
+
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+ type_code = TREE_CODE (type);
- if (code == FUNCTION_TYPE)
- {
- if (pedantic || warn_pointer_arith)
- pedwarn ("ISO C++ forbids applying `sizeof' to a function type");
- size = size_one_node;
- }
- else if (code == METHOD_TYPE)
+ if (type_code == METHOD_TYPE)
{
- if (pedantic || warn_pointer_arith)
- pedwarn ("ISO C++ forbids applying `sizeof' to a member function");
- size = size_one_node;
+ if (complain && (pedantic || warn_pointer_arith))
+ pedwarn ("invalid application of `%s' to a member function", op_name);
+ value = size_one_node;
}
- else if (code == VOID_TYPE)
+ else if (type_code == OFFSET_TYPE)
{
- if (pedantic || warn_pointer_arith)
- pedwarn ("ISO C++ forbids applying `sizeof' to type `void' which is an incomplete type");
- size = size_one_node;
+ if (complain)
+ error ("invalid application of `%s' to non-static member", op_name);
+ value = size_zero_node;
}
- else if (code == ERROR_MARK)
- size = size_one_node;
else
- {
- /* ARM $5.3.2: ``When applied to a reference, the result is the
- size of the referenced object.'' */
- if (code == REFERENCE_TYPE)
- type = TREE_TYPE (type);
+ value = c_sizeof_or_alignof_type (complete_type (type), op, complain);
- if (code == OFFSET_TYPE)
- {
- error ("`sizeof' applied to non-static member");
- size = size_zero_node;
- }
- else if (!COMPLETE_TYPE_P (complete_type (type)))
- {
- error ("`sizeof' applied to incomplete type `%T'", type);
- size = size_zero_node;
- }
- else
- /* Convert in case a char is more than one unit. */
- size = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
- size_int (TYPE_PRECISION (char_type_node)
- / BITS_PER_UNIT));
- }
-
- /* SIZE will have an integer type with TYPE_IS_SIZETYPE set.
- TYPE_IS_SIZETYPE means that certain things (like overflow) will
- never happen. However, this node should really have type
- `size_t', which is just a typedef for an ordinary integer type. */
- size = fold (build1 (NOP_EXPR, size_type_node, size));
- my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (size)),
- 20001021);
- return size;
+ return value;
}
-
tree
expr_sizeof (e)
tree e;
@@ -1568,10 +1545,10 @@ expr_sizeof (e)
}
else if (type_unknown_p (e))
{
- incomplete_type_error (e, TREE_TYPE (e));
+ cxx_incomplete_type_error (e, TREE_TYPE (e));
return c_sizeof (char_type_node);
}
- /* It's illegal to say `sizeof (X::i)' for `i' a non-static data
+ /* It's invalid to say `sizeof (X::i)' for `i' a non-static data
member unless you're in a non-static member of X. So hand off to
resolve_offset_ref. [expr.prim] */
else if (TREE_CODE (e) == OFFSET_REF)
@@ -1580,44 +1557,9 @@ expr_sizeof (e)
if (e == error_mark_node)
return e;
- return c_sizeof (TREE_TYPE (e));
+ return cxx_sizeof (TREE_TYPE (e));
}
-tree
-c_sizeof_nowarn (type)
- tree type;
-{
- enum tree_code code = TREE_CODE (type);
- tree size;
-
- if (code == FUNCTION_TYPE
- || code == METHOD_TYPE
- || code == VOID_TYPE
- || code == ERROR_MARK)
- size = size_one_node;
- else
- {
- if (code == REFERENCE_TYPE)
- type = TREE_TYPE (type);
-
- if (!COMPLETE_TYPE_P (type))
- size = size_zero_node;
- else
- /* Convert in case a char is more than one unit. */
- size = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
- size_int (TYPE_PRECISION (char_type_node)
- / BITS_PER_UNIT));
- }
-
- /* SIZE will have an integer type with TYPE_IS_SIZETYPE set.
- TYPE_IS_SIZETYPE means that certain things (like overflow) will
- never happen. However, this node should really have type
- `size_t', which is just a typedef for an ordinary integer type. */
- size = fold (build1 (NOP_EXPR, size_type_node, size));
- my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (size)),
- 20001021);
- return size;
-}
/* Perform the array-to-pointer and function-to-pointer conversions
for EXP.
@@ -1650,7 +1592,7 @@ decay_conversion (exp)
if (type_unknown_p (exp))
{
- incomplete_type_error (exp, TREE_TYPE (exp));
+ cxx_incomplete_type_error (exp, TREE_TYPE (exp));
return error_mark_node;
}
@@ -1723,7 +1665,7 @@ decay_conversion (exp)
is not the target type of the type of the ADDR_EXPR itself.
Question is, can this lossage be avoided? */
adr = build1 (ADDR_EXPR, ptrtype, exp);
- if (mark_addressable (exp) == 0)
+ if (!cxx_mark_addressable (exp))
return error_mark_node;
TREE_CONSTANT (adr) = staticp (exp);
TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */
@@ -1820,46 +1762,6 @@ string_conv_p (totype, exp, warn)
return 1;
}
-
-tree
-build_object_ref (datum, basetype, field)
- tree datum, basetype, field;
-{
- tree dtype;
- if (datum == error_mark_node)
- return error_mark_node;
-
- dtype = TREE_TYPE (datum);
- if (TREE_CODE (dtype) == REFERENCE_TYPE)
- dtype = TREE_TYPE (dtype);
- if (! IS_AGGR_TYPE_CODE (TREE_CODE (dtype)))
- {
- error ("request for member `%T::%D' in expression of non-aggregate type `%T'",
- basetype, field, dtype);
- return error_mark_node;
- }
- else if (is_aggr_type (basetype, 1))
- {
- tree binfo = binfo_or_else (basetype, dtype);
- if (binfo)
- 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, 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;
-{
- return convert_from_reference
- (build_component_ref (datum, field, NULL_TREE, protect));
-}
/* 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
@@ -1909,7 +1811,7 @@ lookup_anon_field (t, type)
{
if (TREE_STATIC (field))
continue;
- if (TREE_CODE (field) != FIELD_DECL)
+ if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
/* If we find it directly, return the field. */
@@ -1931,333 +1833,448 @@ lookup_anon_field (t, type)
return NULL_TREE;
}
-/* 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. */
+/* Build an expression representing OBJECT.MEMBER. OBJECT is an
+ expression; MEMBER is a DECL or baselink. If ACCESS_PATH is
+ non-NULL, it indicates the path to the base used to name MEMBER.
+ If PRESERVE_REFERENCE is true, the expression returned will have
+ REFERENCE_TYPE if the MEMBER does. Otherwise, the expression
+ returned will have the type referred to by the reference.
+
+ This function does not perform access control; that is either done
+ earlier by the parser when the name of MEMBER is resolved to MEMBER
+ itself, or later when overload resolution selects one of the
+ functions indicated by MEMBER. */
tree
-build_component_ref (datum, component, basetype_path, protect)
- tree datum, component, basetype_path;
- int protect;
+build_class_member_access_expr (tree object, tree member,
+ tree access_path, bool preserve_reference)
{
- register tree basetype;
- register enum tree_code code;
- register tree field = NULL;
- register tree ref;
- tree field_type;
- int type_quals;
- tree old_datum;
- tree old_basetype;
+ tree object_type;
+ tree member_scope;
+ tree result = NULL_TREE;
- if (processing_template_decl)
- return build_min_nt (COMPONENT_REF, datum, component);
-
- if (datum == error_mark_node
- || TREE_TYPE (datum) == error_mark_node)
+ if (object == error_mark_node || member == error_mark_node)
return error_mark_node;
- /* BASETYPE holds the type of the class containing the COMPONENT. */
- basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
-
- /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference
- inside it. */
- switch (TREE_CODE (datum))
+ my_friendly_assert (DECL_P (member) || BASELINK_P (member),
+ 20020801);
+
+ /* Transform `(a, b).x' into `a, b.x' and `(a ? b : c).x' into
+ `a ? b.x : c.x'. These transformations should not really be
+ necessary, but they are. */
+ if (TREE_CODE (object) == COMPOUND_EXPR)
+ {
+ result = build_class_member_access_expr (TREE_OPERAND (object, 1),
+ member, access_path,
+ preserve_reference);
+ return build (COMPOUND_EXPR, TREE_TYPE (result),
+ TREE_OPERAND (object, 0), result);
+ }
+ else if (TREE_CODE (object) == COND_EXPR)
+ return (build_conditional_expr
+ (TREE_OPERAND (object, 0),
+ build_class_member_access_expr (TREE_OPERAND (object, 1),
+ member, access_path,
+ preserve_reference),
+ build_class_member_access_expr (TREE_OPERAND (object, 2),
+ member, access_path,
+ preserve_reference)));
+
+ /* [expr.ref]
+
+ The type of the first expression shall be "class object" (of a
+ complete type). */
+ object_type = TREE_TYPE (object);
+ if (!complete_type_or_else (object_type, object))
+ return error_mark_node;
+ if (!CLASS_TYPE_P (object_type))
{
- case COMPOUND_EXPR:
- {
- tree value = build_component_ref (TREE_OPERAND (datum, 1), component,
- basetype_path, protect);
- return build (COMPOUND_EXPR, TREE_TYPE (value),
- TREE_OPERAND (datum, 0), value);
- }
- case COND_EXPR:
- return build_conditional_expr
- (TREE_OPERAND (datum, 0),
- build_component_ref (TREE_OPERAND (datum, 1), component,
- basetype_path, protect),
- build_component_ref (TREE_OPERAND (datum, 2), component,
- basetype_path, protect));
-
- case TEMPLATE_DECL:
- error ("invalid use of `%D'", datum);
- datum = error_mark_node;
- break;
-
- default:
- break;
+ error ("request for member `%D' in `%E', which is of non-class type `%T'",
+ member, object, object_type);
+ return error_mark_node;
}
- code = TREE_CODE (basetype);
-
- if (code == REFERENCE_TYPE)
+ /* The standard does not seem to actually say that MEMBER must be a
+ member of OBJECT_TYPE. However, that is clearly what is
+ intended. */
+ if (DECL_P (member))
{
- datum = convert_from_reference (datum);
- basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
- code = TREE_CODE (basetype);
+ member_scope = DECL_CLASS_CONTEXT (member);
+ mark_used (member);
+ if (TREE_DEPRECATED (member))
+ warn_deprecated_use (member);
}
- if (TREE_CODE (datum) == OFFSET_REF)
- {
- datum = resolve_offset_ref (datum);
- basetype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
- code = TREE_CODE (basetype);
+ else
+ member_scope = BINFO_TYPE (BASELINK_BINFO (member));
+ /* If MEMBER is from an anonymous aggregate, MEMBER_SCOPE will
+ presently be the anonymous union. Go outwards until we find a
+ type related to OBJECT_TYPE. */
+ while (ANON_AGGR_TYPE_P (member_scope)
+ && !same_type_ignoring_top_level_qualifiers_p (member_scope,
+ object_type))
+ member_scope = TYPE_CONTEXT (member_scope);
+ if (!member_scope || !DERIVED_FROM_P (member_scope, object_type))
+ {
+ error ("`%D' is not a member of `%T'", member, object_type);
+ return error_mark_node;
}
- /* First, see if there is a field or component with name COMPONENT. */
- if (TREE_CODE (component) == TREE_LIST)
+ /* In [expr.ref], there is an explicit list of the valid choices for
+ MEMBER. We check for each of those cases here. */
+ if (TREE_CODE (member) == VAR_DECL)
{
- /* I could not trigger this code. MvL */
- abort ();
-#ifdef DEAD
- my_friendly_assert (!(TREE_CHAIN (component) == NULL_TREE
- && DECL_CHAIN (TREE_VALUE (component)) == NULL_TREE), 309);
-#endif
- return build (COMPONENT_REF, TREE_TYPE (component), datum, component);
+ /* A static data member. */
+ result = member;
+ /* If OBJECT has side-effects, they are supposed to occur. */
+ if (TREE_SIDE_EFFECTS (object))
+ result = build (COMPOUND_EXPR, TREE_TYPE (result), object, result);
}
-
- if (! IS_AGGR_TYPE_CODE (code))
+ else if (TREE_CODE (member) == FIELD_DECL)
{
- if (code != ERROR_MARK)
- error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
- component, datum, basetype);
- return error_mark_node;
- }
+ /* A non-static data member. */
+ bool null_object_p;
+ int type_quals;
+ tree member_type;
- if (!complete_type_or_else (basetype, datum))
- return error_mark_node;
+ null_object_p = (TREE_CODE (object) == INDIRECT_REF
+ && integer_zerop (TREE_OPERAND (object, 0)));
- if (TREE_CODE (component) == BIT_NOT_EXPR)
- {
- if (TYPE_IDENTIFIER (basetype) != TREE_OPERAND (component, 0))
+ /* Convert OBJECT to the type of MEMBER. */
+ if (!same_type_p (TYPE_MAIN_VARIANT (object_type),
+ TYPE_MAIN_VARIANT (member_scope)))
{
- error ("destructor specifier `%T::~%T' must have matching names",
- basetype, TREE_OPERAND (component, 0));
- return error_mark_node;
+ tree binfo;
+ base_kind kind;
+
+ binfo = lookup_base (access_path ? access_path : object_type,
+ member_scope, ba_ignore, &kind);
+ if (binfo == error_mark_node)
+ return error_mark_node;
+
+ /* It is invalid to try to get to a virtual base of a
+ NULL object. The most common cause is invalid use of
+ offsetof macro. */
+ if (null_object_p && kind == bk_via_virtual)
+ {
+ error ("invalid access to non-static data member `%D' of NULL object",
+ member);
+ error ("(perhaps the `offsetof' macro was used incorrectly)");
+ return error_mark_node;
+ }
+
+ /* Convert to the base. */
+ object = build_base_path (PLUS_EXPR, object, binfo,
+ /*nonnull=*/1);
+ /* If we found the base successfully then we should be able
+ to convert to it successfully. */
+ my_friendly_assert (object != error_mark_node,
+ 20020801);
}
- if (! TYPE_HAS_DESTRUCTOR (basetype))
+
+ /* Complain about other invalid uses of offsetof, even though they will
+ give the right answer. Note that we complain whether or not they
+ actually used the offsetof macro, since there's no way to know at this
+ point. So we just give a warning, instead of a pedwarn. */
+ if (null_object_p && CLASSTYPE_NON_POD_P (object_type))
{
- error ("type `%T' has no destructor", basetype);
- return error_mark_node;
+ warning ("invalid access to non-static data member `%D' of NULL object",
+ member);
+ warning ("(perhaps the `offsetof' macro was used incorrectly)");
+ }
+
+ /* If MEMBER is from an anonymous aggregate, we have converted
+ OBJECT so that it refers to the class containing the
+ anonymous union. Generate a reference to the anonymous union
+ itself, and recur to find MEMBER. */
+ if (ANON_AGGR_TYPE_P (DECL_CONTEXT (member))
+ /* When this code is called from build_field_call, the
+ object already has the type of the anonymous union.
+ That is because the COMPONENT_REF was already
+ constructed, and was then disassembled before calling
+ build_field_call. After the function-call code is
+ cleaned up, this waste can be eliminated. */
+ && (!same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (object), DECL_CONTEXT (member))))
+ {
+ tree anonymous_union;
+
+ anonymous_union = lookup_anon_field (TREE_TYPE (object),
+ DECL_CONTEXT (member));
+ object = build_class_member_access_expr (object,
+ anonymous_union,
+ /*access_path=*/NULL_TREE,
+ preserve_reference);
}
- return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1);
- }
- /* Look up component name in the structure type definition. */
- if (TYPE_VFIELD (basetype)
- && DECL_NAME (TYPE_VFIELD (basetype)) == component)
- /* Special-case this because if we use normal lookups in an ambiguous
- hierarchy, the compiler will abort (because vptr lookups are
- not supposed to be ambiguous. */
- field = TYPE_VFIELD (basetype);
- else if (TREE_CODE (component) == FIELD_DECL)
- field = component;
- else if (TREE_CODE (component) == TYPE_DECL)
+ /* Compute the type of the field, as described in [expr.ref]. */
+ type_quals = TYPE_UNQUALIFIED;
+ member_type = TREE_TYPE (member);
+ if (TREE_CODE (member_type) != REFERENCE_TYPE)
+ {
+ type_quals = (cp_type_quals (member_type)
+ | cp_type_quals (object_type));
+
+ /* A field is const (volatile) if the enclosing object, or the
+ field itself, is const (volatile). But, a mutable field is
+ not const, even within a const object. */
+ if (DECL_MUTABLE_P (member))
+ type_quals &= ~TYPE_QUAL_CONST;
+ member_type = cp_build_qualified_type (member_type, type_quals);
+ }
+
+ result = fold (build (COMPONENT_REF, member_type, object, member));
+
+ /* Mark the expression const or volatile, as appropriate. Even
+ though we've dealt with the type above, we still have to mark the
+ expression itself. */
+ if (type_quals & TYPE_QUAL_CONST)
+ TREE_READONLY (result) = 1;
+ else if (type_quals & TYPE_QUAL_VOLATILE)
+ TREE_THIS_VOLATILE (result) = 1;
+ }
+ else if (BASELINK_P (member))
{
- error ("invalid use of type decl `%#D' as expression", component);
- return error_mark_node;
+ /* The member is a (possibly overloaded) member function. */
+ tree functions;
+
+ /* If the MEMBER is exactly one static member function, then we
+ know the type of the expression. Otherwise, we must wait
+ until overload resolution has been performed. */
+ functions = BASELINK_FUNCTIONS (member);
+ if (TREE_CODE (functions) == FUNCTION_DECL
+ && DECL_STATIC_FUNCTION_P (functions))
+ {
+ /* A static member function. */
+ result = functions;
+ mark_used (result);
+ /* If OBJECT has side-effects, they are supposed to occur. */
+ if (TREE_SIDE_EFFECTS (object))
+ result = build (COMPOUND_EXPR, TREE_TYPE (result),
+ object, result);
+ }
+ else
+ /* Note that we do not convert OBJECT to the BASELINK_BINFO
+ base. That will happen when the function is called. */
+ result = build (COMPONENT_REF, unknown_type_node, object, member);
}
- else if (TREE_CODE (component) == TEMPLATE_DECL)
+ else if (TREE_CODE (member) == CONST_DECL)
{
- error ("invalid use of template `%#D' as expression", component);
- return error_mark_node;
+ /* The member is an enumerator. */
+ result = member;
+ /* If OBJECT has side-effects, they are supposed to occur. */
+ if (TREE_SIDE_EFFECTS (object))
+ result = build (COMPOUND_EXPR, TREE_TYPE (result),
+ object, result);
}
else
{
- tree name = component;
-
- if (TREE_CODE (component) == TEMPLATE_ID_EXPR)
- name = TREE_OPERAND (component, 0);
- else if (TREE_CODE (component) == VAR_DECL)
- name = DECL_NAME (component);
- if (TREE_CODE (component) == NAMESPACE_DECL)
- /* Source is in error, but produce a sensible diagnostic. */
- name = DECL_NAME (component);
- if (basetype_path == NULL_TREE)
- basetype_path = TYPE_BINFO (basetype);
- field = lookup_field (basetype_path, name,
- protect && !VFIELD_NAME_P (name), 0);
- if (field == error_mark_node)
- return error_mark_node;
+ error ("invalid use of `%D'", member);
+ return error_mark_node;
+ }
- if (field == NULL_TREE)
- {
- /* 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, name, 1);
- if (fndecls == error_mark_node)
- return error_mark_node;
- if (fndecls)
- {
- /* If the function is unique and static, we can resolve it
- now. Otherwise, we have to wait and see what context it is
- used in; a component_ref involving a non-static member
- function can only be used in a call (expr.ref). */
+ if (!preserve_reference)
+ /* [expr.ref]
+
+ If E2 is declared to have type "reference to T", then ... the
+ type of E1.E2 is T. */
+ result = convert_from_reference (result);
- if (TREE_CHAIN (fndecls) == NULL_TREE
- && TREE_CODE (TREE_VALUE (fndecls)) == FUNCTION_DECL)
- {
- if (DECL_STATIC_FUNCTION_P (TREE_VALUE (fndecls)))
- {
- tree fndecl = TREE_VALUE (fndecls);
- enforce_access (basetype_path, fndecl);
- mark_used (fndecl);
- return fndecl;
- }
- else
- {
- /* A unique non-static member function. Other parts
- of the compiler expect something with
- unknown_type_node to be really overloaded, so
- let's oblige. */
- TREE_VALUE (fndecls)
- = ovl_cons (TREE_VALUE (fndecls), NULL_TREE);
- }
- }
+ return result;
+}
- fndecls = TREE_VALUE (fndecls);
-
- if (TREE_CODE (component) == TEMPLATE_ID_EXPR)
- fndecls = build_nt (TEMPLATE_ID_EXPR,
- fndecls, TREE_OPERAND (component, 1));
-
- ref = build (COMPONENT_REF, unknown_type_node,
- datum, fndecls);
- return ref;
- }
+/* This function is called by the parser to process a class member
+ access expression of the form OBJECT.NAME. NAME is a node used by
+ the parser to represent a name; it is not yet a DECL. It may,
+ however, be a BASELINK where the BASELINK_FUNCTIONS is a
+ TEMPLATE_ID_EXPR. Templates must be looked up by the parser, and
+ there is no reason to do the lookup twice, so the parser keeps the
+ BASELINK. */
- error ("`%#T' has no member named `%D'", basetype, name);
- return error_mark_node;
- }
- else if (TREE_TYPE (field) == error_mark_node)
- return error_mark_node;
+tree
+finish_class_member_access_expr (tree object, tree name)
+{
+ tree object_type;
+ tree member;
+ tree access_path = NULL_TREE;
- if (TREE_CODE (field) != FIELD_DECL)
- {
- if (TREE_CODE (field) == TYPE_DECL)
- pedwarn ("invalid use of type decl `%#D' as expression", field);
- else if (DECL_RTL (field) != 0)
- mark_used (field);
- else
- TREE_USED (field) = 1;
+ if (object == error_mark_node || name == error_mark_node)
+ return error_mark_node;
- /* Do evaluate the object when accessing a static member. */
- if (TREE_SIDE_EFFECTS (datum))
- field = build (COMPOUND_EXPR, TREE_TYPE (field), datum, field);
+ if (processing_template_decl)
+ return build_min_nt (COMPONENT_REF, object, name);
+
+ if (TREE_CODE (object) == OFFSET_REF)
+ object = resolve_offset_ref (object);
- return field;
- }
+ object_type = TREE_TYPE (object);
+ if (TREE_CODE (object_type) == REFERENCE_TYPE)
+ {
+ object = convert_from_reference (object);
+ object_type = TREE_TYPE (object);
}
- if (TREE_DEPRECATED (field))
- warn_deprecated_use (field);
+ /* [expr.ref]
- old_datum = datum;
- old_basetype = basetype;
+ The type of the first expression shall be "class object" (of a
+ complete type). */
+ if (!complete_type_or_else (object_type, object))
+ return error_mark_node;
+ if (!CLASS_TYPE_P (object_type))
+ {
+ error ("request for member `%D' in `%E', which is of non-class type `%T'",
+ name, object, object_type);
+ return error_mark_node;
+ }
- /* 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)
+ if (BASELINK_P (name))
+ {
+ /* A member function that has already been looked up. */
+ my_friendly_assert ((TREE_CODE (BASELINK_FUNCTIONS (name))
+ == TEMPLATE_ID_EXPR),
+ 20020805);
+ member = name;
+ }
+ else
{
- tree context = DECL_FIELD_CONTEXT (field);
- tree base = context;
- while (!same_type_p (base, basetype) && TYPE_NAME (base)
- && ANON_AGGR_TYPE_P (base))
- base = TYPE_CONTEXT (base);
+ bool is_template_id = false;
+ tree template_args = NULL_TREE;
- /* Handle base classes here... */
- if (base != basetype && TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype))
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
- base_kind kind;
- tree binfo = lookup_base (TREE_TYPE (datum), base, ba_check, &kind);
+ is_template_id = true;
+ template_args = TREE_OPERAND (name, 1);
+ name = TREE_OPERAND (name, 0);
+ }
- /* Complain about use of offsetof which will break. */
- if (TREE_CODE (datum) == INDIRECT_REF
- && integer_zerop (TREE_OPERAND (datum, 0))
- && kind == bk_via_virtual)
+ if (TREE_CODE (name) == SCOPE_REF)
+ {
+ tree scope;
+
+ /* A qualified name. The qualifying class or namespace `S' has
+ already been looked up; it is either a TYPE or a
+ NAMESPACE_DECL. The member name is either an IDENTIFIER_NODE
+ or a BIT_NOT_EXPR. */
+ scope = TREE_OPERAND (name, 0);
+ name = TREE_OPERAND (name, 1);
+ my_friendly_assert ((CLASS_TYPE_P (scope)
+ || TREE_CODE (scope) == NAMESPACE_DECL),
+ 20020804);
+ my_friendly_assert ((TREE_CODE (name) == IDENTIFIER_NODE
+ || TREE_CODE (name) == BIT_NOT_EXPR),
+ 20020804);
+
+ /* If SCOPE is a namespace, then the qualified name does not
+ name a member of OBJECT_TYPE. */
+ if (TREE_CODE (scope) == NAMESPACE_DECL)
+ {
+ error ("`%D::%D' is not a member of `%T'",
+ scope, name, object_type);
+ return error_mark_node;
+ }
+
+ /* Find the base of OBJECT_TYPE corresponding to SCOPE. */
+ access_path = lookup_base (object_type, scope, ba_check, NULL);
+ if (!access_path || access_path == error_mark_node)
+ return error_mark_node;
+
+ /* Look up the member. */
+ member = lookup_member (access_path, name, /*protect=*/1,
+ /*want_type=*/0);
+ if (member == NULL_TREE)
{
- error ("\
-invalid offsetof from non-POD type `%#T'; use pointer to member instead",
- basetype);
+ error ("'%D' has no member named '%E'", object_type, name);
return error_mark_node;
}
- datum = build_base_path (PLUS_EXPR, datum, binfo, 1);
- if (datum == error_mark_node)
+ else if (member == error_mark_node)
return error_mark_node;
}
- basetype = base;
-
- /* Handle things from anon unions here... */
- if (TYPE_NAME (context) && ANON_AGGR_TYPE_P (context))
+ else if (TREE_CODE (name) == BIT_NOT_EXPR)
+ {
+ /* A destructor. */
+ if (TYPE_IDENTIFIER (object_type) != TREE_OPERAND (name, 0))
+ {
+ error ("destructor specifier `%T::~%T' must have matching names",
+ object_type, TREE_OPERAND (name, 0));
+ return error_mark_node;
+ }
+ if (! TYPE_HAS_DESTRUCTOR (object_type))
+ {
+ error ("type `%T' has no destructor", object_type);
+ return error_mark_node;
+ }
+ member = CLASSTYPE_DESTRUCTORS (object_type);
+ }
+ else if (TREE_CODE (name) == IDENTIFIER_NODE)
{
- 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);
+ /* An unqualified name. */
+ member = lookup_member (object_type, name, /*protect=*/1,
+ /*want_type=*/0);
+ if (member == NULL_TREE)
+ {
+ error ("'%D' has no member named '%E'", object_type, name);
+ return error_mark_node;
+ }
+ else if (member == error_mark_node)
+ return error_mark_node;
+ }
+ else
+ {
+ /* The YACC parser sometimes gives us things that are not names.
+ These always indicate errors. The recursive-descent parser
+ does not do this, so this code can go away once that parser
+ replaces the YACC parser. */
+ error ("invalid use of `%D'", name);
+ return error_mark_node;
+ }
+
+ if (is_template_id)
+ {
+ tree template = member;
+
+ if (BASELINK_P (template))
+ BASELINK_FUNCTIONS (template)
+ = build_nt (TEMPLATE_ID_EXPR,
+ BASELINK_FUNCTIONS (template),
+ template_args);
+ else
+ {
+ error ("`%D' is not a member template function", name);
+ return error_mark_node;
+ }
}
}
- /* Complain about other invalid uses of offsetof, even though they will
- give the right answer. Note that we complain whether or not they
- actually used the offsetof macro, since there's no way to know at this
- point. So we just give a warning, instead of a pedwarn. */
- if (protect
- && CLASSTYPE_NON_POD_P (old_basetype)
- && TREE_CODE (old_datum) == INDIRECT_REF
- && integer_zerop (TREE_OPERAND (old_datum, 0)))
- warning ("\
-invalid offsetof from non-POD type `%#T'; use pointer to member instead",
- basetype);
-
- /* Compute the type of the field, as described in [expr.ref]. */
- type_quals = TYPE_UNQUALIFIED;
- field_type = TREE_TYPE (field);
- if (TREE_CODE (field_type) == REFERENCE_TYPE)
- /* The standard says that the type of the result should be the
- type referred to by the reference. But for now, at least, we
- do the conversion from reference type later. */
- ;
- else
- {
- type_quals = (cp_type_quals (field_type)
- | cp_type_quals (TREE_TYPE (datum)));
-
- /* A field is const (volatile) if the enclosing object, or the
- field itself, is const (volatile). But, a mutable field is
- not const, even within a const object. */
- if (DECL_MUTABLE_P (field))
- type_quals &= ~TYPE_QUAL_CONST;
- field_type = cp_build_qualified_type (field_type, type_quals);
- }
-
- ref = fold (build (COMPONENT_REF, field_type, datum, field));
-
- /* Mark the expression const or volatile, as appropriate. Even
- though we've dealt with the type above, we still have to mark the
- expression itself. */
- if (type_quals & TYPE_QUAL_CONST)
- TREE_READONLY (ref) = 1;
- else if (type_quals & TYPE_QUAL_VOLATILE)
- TREE_THIS_VOLATILE (ref) = 1;
-
- return ref;
+ return build_class_member_access_expr (object, member, access_path,
+ /*preserve_reference=*/false);
}
-/* Variant of build_component_ref for use in expressions, which should
- never have REFERENCE_TYPE. */
+/* Return an expression for the MEMBER_NAME field in the internal
+ representation of PTRMEM, a pointer-to-member function. (Each
+ pointer-to-member function type gets its own RECORD_TYPE so it is
+ more convenient to access the fields by name than by FIELD_DECL.)
+ This routine converts the NAME to a FIELD_DECL and then creates the
+ node for the complete expression. */
tree
-build_x_component_ref (datum, component, basetype_path, protect)
- tree datum, component, basetype_path;
- int protect;
+build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
{
- tree t = build_component_ref (datum, component, basetype_path, protect);
-
- if (! processing_template_decl)
- t = convert_from_reference (t);
-
- return t;
+ tree ptrmem_type;
+ tree member;
+ tree member_type;
+
+ /* This code is a stripped down version of
+ build_class_member_access_expr. It does not work to use that
+ routine directly because it expects the object to be of class
+ type. */
+ ptrmem_type = TREE_TYPE (ptrmem);
+ my_friendly_assert (TYPE_PTRMEMFUNC_P (ptrmem_type), 20020804);
+ member = lookup_member (ptrmem_type, member_name, /*protect=*/0,
+ /*want_type=*/0);
+ member_type = cp_build_qualified_type (TREE_TYPE (member),
+ cp_type_quals (ptrmem_type));
+ return fold (build (COMPONENT_REF, member_type, ptrmem, member));
}
-
+
/* Given an expression PTR for a pointer, return an expression
for the value pointed to.
ERRORSTRING is the name of the operator to appear in error messages.
@@ -2319,8 +2336,8 @@ build_indirect_ref (ptr, errorstring)
return error_mark_node;
}
else if (TREE_CODE (pointer) == ADDR_EXPR
- && !flag_volatile
- && same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0))))
+ && !flag_volatile
+ && same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0))))
/* The POINTER was something like `&x'. We simplify `*&x' to
`x'. */
return TREE_OPERAND (pointer, 0);
@@ -2434,7 +2451,7 @@ build_array_ref (array, idx)
&& (TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))))
!= INTEGER_CST)))
{
- if (mark_addressable (array) == 0)
+ if (!cxx_mark_addressable (array))
return error_mark_node;
}
@@ -2446,7 +2463,7 @@ build_array_ref (array, idx)
&& TYPE_VALUES (TREE_TYPE (array))
&& ! int_fits_type_p (idx, TYPE_VALUES (TREE_TYPE (array))))
{
- if (mark_addressable (array) == 0)
+ if (!cxx_mark_addressable (array))
return error_mark_node;
}
@@ -2509,306 +2526,15 @@ 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. 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
- be. If the list of methods comes from a class, then it will be
- a list of lists (where each element is associated with the class
- that produced it), otherwise it will be a simple list (for
- functions overloaded in global scope).
-
- In the first case, TREE_VALUE (function) is the head of one of those
- lists, and TREE_PURPOSE is the name of the function.
-
- In the second case, TREE_PURPOSE (function) is the function's
- name directly.
-
- DECL is the class instance variable, usually CURRENT_CLASS_REF.
-
- When calling a TEMPLATE_DECL, we don't require a complete return
- type. */
-
-tree
-build_x_function_call (function, params, decl)
- tree function, params, decl;
-{
- tree type;
- tree template_id = NULL_TREE;
- int is_method;
-
- if (function == error_mark_node)
- return error_mark_node;
-
- if (processing_template_decl)
- return build_min_nt (CALL_EXPR, function, params, NULL_TREE);
-
- /* Save explicit template arguments if found */
- if (TREE_CODE (function) == TEMPLATE_ID_EXPR)
- {
- template_id = function;
- function = TREE_OPERAND (function, 0);
- }
-
- 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);
- if (TREE_CODE (function) == OVERLOAD)
- function = OVL_FUNCTION (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);
- }
-
- if (TREE_CODE (function) == OFFSET_REF
- && TREE_CODE (type) != METHOD_TYPE)
- function = resolve_offset_ref (function);
-
- if ((TREE_CODE (function) == FUNCTION_DECL
- && DECL_STATIC_FUNCTION_P (function))
- || (DECL_FUNCTION_TEMPLATE_P (function)
- && DECL_STATIC_FUNCTION_P (DECL_TEMPLATE_RESULT (function))))
- return build_member_call (DECL_CONTEXT (function),
- template_id
- ? template_id : DECL_NAME (function),
- params);
-
- is_method = ((TREE_CODE (function) == TREE_LIST
- && current_class_type != NULL_TREE
- && (IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (function))
- == function))
- || (TREE_CODE (function) == OVERLOAD
- && DECL_FUNCTION_MEMBER_P (OVL_CURRENT (function)))
- || TREE_CODE (function) == IDENTIFIER_NODE
- || TREE_CODE (type) == METHOD_TYPE
- || TYPE_PTRMEMFUNC_P (type));
-
- /* A friend template. Make it look like a toplevel declaration. */
- if (! is_method && TREE_CODE (function) == TEMPLATE_DECL)
- function = ovl_cons (function, NULL_TREE);
-
- /* Handle methods, friends, and overloaded functions, respectively. */
- if (is_method)
- {
- tree basetype = NULL_TREE;
-
- if (TREE_CODE (function) == OVERLOAD)
- function = OVL_CURRENT (function);
-
- if (TREE_CODE (function) == FUNCTION_DECL
- || DECL_FUNCTION_TEMPLATE_P (function))
- {
- basetype = DECL_CONTEXT (function);
-
- if (DECL_NAME (function))
- function = DECL_NAME (function);
- else
- function = TYPE_IDENTIFIER (DECL_CONTEXT (function));
- }
- else if (TREE_CODE (function) == TREE_LIST)
- {
- my_friendly_assert (TREE_CODE (TREE_VALUE (function))
- == FUNCTION_DECL, 312);
- basetype = DECL_CONTEXT (TREE_VALUE (function));
- function = TREE_PURPOSE (function);
- }
- else if (TREE_CODE (function) != IDENTIFIER_NODE)
- {
- if (TREE_CODE (function) == OFFSET_REF)
- {
- if (TREE_OPERAND (function, 0))
- decl = TREE_OPERAND (function, 0);
- }
- /* Call via a pointer to member function. */
- if (decl == NULL_TREE)
- {
- error ("pointer to member function called, but not in class scope");
- return error_mark_node;
- }
- /* What other type of POINTER_TYPE could this be? */
- if (TREE_CODE (TREE_TYPE (function)) != POINTER_TYPE
- && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (function))
- && TREE_CODE (function) != OFFSET_REF)
- function = build (OFFSET_REF, TREE_TYPE (type), NULL_TREE,
- function);
- goto do_x_function;
- }
-
- /* this is an abbreviated method call.
- 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)
- {
- error ("object missing in call to method `%D'", function);
- return error_mark_node;
- }
- /* Yow: call from a static member function. */
- decl = build_dummy_object (current_class_type);
- }
-
- /* Put back explicit template arguments, if any. */
- if (template_id)
- function = template_id;
- return build_method_call (decl, function, params,
- NULL_TREE, LOOKUP_NORMAL);
- }
- else if (TREE_CODE (function) == COMPONENT_REF
- && type == unknown_type_node)
- {
- /* Undo what we did in build_component_ref. */
- decl = TREE_OPERAND (function, 0);
- function = TREE_OPERAND (function, 1);
-
- if (TREE_CODE (function) == TEMPLATE_ID_EXPR)
- {
- my_friendly_assert (!template_id, 20011228);
-
- template_id = function;
- }
- else
- {
- function = DECL_NAME (OVL_CURRENT (function));
-
- if (template_id)
- {
- TREE_OPERAND (template_id, 0) = function;
- function = template_id;
- }
- }
-
- return build_method_call (decl, function, params,
- NULL_TREE, LOOKUP_NORMAL);
- }
- else if (really_overloaded_fn (function))
- {
- if (OVL_FUNCTION (function) == NULL_TREE)
- {
- error ("function `%D' declared overloaded, but no definitions appear with which to resolve it?!?",
- TREE_PURPOSE (function));
- return error_mark_node;
- }
- else
- {
- /* Put back explicit template arguments, if any. */
- if (template_id)
- function = template_id;
- return build_new_function_call (function, params);
- }
- }
- else
- /* Remove a potential OVERLOAD around it */
- function = OVL_CURRENT (function);
-
- do_x_function:
- if (TREE_CODE (function) == OFFSET_REF)
- {
- /* If the component is a data element (or a virtual function), we play
- games here to make things work. */
- tree decl_addr;
-
- if (TREE_OPERAND (function, 0))
- decl = TREE_OPERAND (function, 0);
- else
- decl = current_class_ref;
-
- decl_addr = build_unary_op (ADDR_EXPR, decl, 0);
-
- /* Sigh. OFFSET_REFs are being used for too many things.
- They're being used both for -> and ->*, and we want to resolve
- the -> cases here, but leave the ->*. We could use
- resolve_offset_ref for those, too, but it would call
- get_member_function_from_ptrfunc and decl_addr wouldn't get
- updated properly. Nasty. */
- if (TREE_CODE (TREE_OPERAND (function, 1)) == FIELD_DECL)
- function = resolve_offset_ref (function);
- else
- function = TREE_OPERAND (function, 1);
-
- function = get_member_function_from_ptrfunc (&decl_addr, function);
- params = tree_cons (NULL_TREE, decl_addr, params);
- return build_function_call (function, params);
- }
-
- type = TREE_TYPE (function);
- if (type != error_mark_node)
- {
- if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
-
- if (IS_AGGR_TYPE (type))
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, function, params, NULL_TREE);
- }
-
- if (is_method)
- {
- tree fntype = TREE_TYPE (function);
- tree ctypeptr = NULL_TREE;
-
- /* Explicitly named method? */
- if (TREE_CODE (function) == FUNCTION_DECL)
- ctypeptr = build_pointer_type (DECL_CLASS_CONTEXT (function));
- /* Expression with ptr-to-method type? It could either be a plain
- usage, or it might be a case where the ptr-to-method is being
- passed in as an argument. */
- else if (TYPE_PTRMEMFUNC_P (fntype))
- {
- tree rec = TYPE_METHOD_BASETYPE (TREE_TYPE
- (TYPE_PTRMEMFUNC_FN_TYPE (fntype)));
- ctypeptr = build_pointer_type (rec);
- }
- /* Unexpected node type? */
- else
- abort ();
- if (decl == NULL_TREE)
- {
- if (current_function_decl
- && DECL_STATIC_FUNCTION_P (current_function_decl))
- error ("invalid call to member function needing `this' in static member function scope");
- else
- error ("pointer to member function called, but not in class scope");
- return error_mark_node;
- }
- if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE
- && ! TYPE_PTRMEMFUNC_P (TREE_TYPE (decl)))
- {
- tree binfo = lookup_base (TREE_TYPE (decl), TREE_TYPE (ctypeptr),
- ba_check, NULL);
-
- decl = build_unary_op (ADDR_EXPR, decl, 0);
- decl = build_base_path (PLUS_EXPR, decl, binfo, 1);
- }
- else
- decl = build_c_cast (ctypeptr, decl);
- params = tree_cons (NULL_TREE, decl, params);
- }
-
- return build_function_call (function, params);
-}
-
/* Resolve a pointer to member function. INSTANCE is the object
- instance to use, if the member points to a virtual member. */
+ instance to use, if the member points to a virtual member.
+
+ This used to avoid checking for virtual functions if basetype
+ has no virtual functions, according to an earlier ANSI draft.
+ With the final ISO C++ rules, such an optimization is
+ incorrect: A pointer to a derived member can be static_cast
+ to pointer-to-base-member, as long as the dynamic object
+ later has the right member. */
tree
get_member_function_from_ptrfunc (instance_ptrptr, function)
@@ -2820,92 +2546,79 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
- tree fntype, idx, e1, delta, delta2, e2, e3, vtbl;
- tree instance, basetype;
+ tree idx, delta, e1, e2, e3, vtbl, basetype;
+ tree fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
tree instance_ptr = *instance_ptrptr;
-
- if (instance_ptr == error_mark_node
- && TREE_CODE (function) == PTRMEM_CST)
+ tree instance_save_expr = 0;
+ if (instance_ptr == error_mark_node)
{
- /* Extracting the function address from a pmf is only
- allowed with -Wno-pmf-conversions. It only works for
- pmf constants. */
- e1 = build_addr_func (PTRMEM_CST_MEMBER (function));
- e1 = convert (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function)), e1);
- return e1;
+ if (TREE_CODE (function) == PTRMEM_CST)
+ {
+ /* Extracting the function address from a pmf is only
+ allowed with -Wno-pmf-conversions. It only works for
+ pmf constants. */
+ e1 = build_addr_func (PTRMEM_CST_MEMBER (function));
+ e1 = convert (fntype, e1);
+ return e1;
+ }
+ else
+ {
+ error ("object missing in use of `%E'", function);
+ return error_mark_node;
+ }
}
if (TREE_SIDE_EFFECTS (instance_ptr))
- instance_ptr = save_expr (instance_ptr);
+ instance_ptr = instance_save_expr = save_expr (instance_ptr);
if (TREE_SIDE_EFFECTS (function))
function = save_expr (function);
- fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
- basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
-
- /* Convert down to the right base, before using the instance. */
- instance = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)), basetype,
- ba_check, NULL);
- instance = build_base_path (PLUS_EXPR, instance_ptr, instance, 1);
- if (instance == error_mark_node && instance_ptr != error_mark_node)
- return instance;
-
+ /* Start by extracting all the information from the PMF itself. */
e3 = PFN_FROM_PTRMEMFUNC (function);
-
- vtbl = build1 (NOP_EXPR, build_pointer_type (ptr_type_node), instance);
- TREE_CONSTANT (vtbl) = TREE_CONSTANT (instance);
-
- delta = cp_convert (ptrdiff_type_node,
- build_component_ref (function, delta_identifier,
- NULL_TREE, 0));
-
- /* This used to avoid checking for virtual functions if basetype
- has no virtual functions, according to an earlier ANSI draft.
- With the final ISO C++ rules, such an optimization is
- incorrect: A pointer to a derived member can be static_cast
- to pointer-to-base-member, as long as the dynamic object
- later has the right member. */
-
- /* 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 = cp_build_binary_op (TRUNC_DIV_EXPR,
- build1 (NOP_EXPR, vtable_index_type, e3),
- TYPE_SIZE_UNIT (vtable_entry_type));
+ delta = build_ptrmemfunc_access_expr (function, delta_identifier);
+ idx = build1 (NOP_EXPR, vtable_index_type, e3);
switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
{
case ptrmemfunc_vbit_in_pfn:
- e1 = cp_build_binary_op (BIT_AND_EXPR,
- build1 (NOP_EXPR, vtable_index_type, e3),
- integer_one_node);
+ e1 = cp_build_binary_op (BIT_AND_EXPR, idx, integer_one_node);
+ idx = cp_build_binary_op (MINUS_EXPR, idx, integer_one_node);
break;
case ptrmemfunc_vbit_in_delta:
- e1 = cp_build_binary_op (BIT_AND_EXPR,
- delta, integer_one_node);
- delta = cp_build_binary_op (RSHIFT_EXPR,
- build1 (NOP_EXPR, vtable_index_type,
- delta),
- integer_one_node);
+ e1 = cp_build_binary_op (BIT_AND_EXPR, delta, integer_one_node);
+ delta = cp_build_binary_op (RSHIFT_EXPR, delta, integer_one_node);
break;
default:
abort ();
}
- /* DELTA2 is the amount by which to adjust the `this' pointer
- to find the vtbl. */
- delta2 = delta;
- vtbl = build
- (PLUS_EXPR,
- build_pointer_type (build_pointer_type (vtable_entry_type)),
- vtbl, cp_convert (ptrdiff_type_node, delta2));
+ /* Convert down to the right base before using the instance. First
+ use the type... */
+ basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
+ basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
+ basetype, ba_check, NULL);
+ instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype, 1);
+ if (instance_ptr == error_mark_node)
+ return error_mark_node;
+ /* ...and then the delta in the PMF. */
+ instance_ptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
+ instance_ptr, delta);
+
+ /* Hand back the adjusted 'this' argument to our caller. */
+ *instance_ptrptr = instance_ptr;
+
+ /* Next extract the vtable pointer from the object. */
+ vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node),
+ instance_ptr);
vtbl = build_indirect_ref (vtbl, NULL);
- e2 = build_array_ref (vtbl, idx);
+
+ /* Finally, extract the function pointer from the vtable. */
+ e2 = fold (build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, idx));
+ e2 = build_indirect_ref (e2, NULL);
+ TREE_CONSTANT (e2) = 1;
/* When using function descriptors, the address of the
vtable entry is treated as a function pointer. */
@@ -2918,17 +2631,9 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
/* Make sure this doesn't get evaluated first inside one of the
branches of the COND_EXPR. */
- if (TREE_CODE (instance_ptr) == SAVE_EXPR)
+ if (instance_save_expr)
e1 = build (COMPOUND_EXPR, TREE_TYPE (e1),
- instance_ptr, e1);
-
- *instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
- instance_ptr, delta);
-
- if (instance_ptr == error_mark_node
- && TREE_CODE (e1) != ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (e1, 0)) != FUNCTION_DECL)
- error ("object missing in `%E'", function);
+ instance_save_expr, e1);
function = e1;
}
@@ -2941,7 +2646,6 @@ build_function_call_real (function, params, require_complete, flags)
int require_complete, flags;
{
register tree fntype, fndecl;
- register tree value_type;
register tree coerced_params;
tree result;
tree name = NULL_TREE, assembler_name = NULL_TREE;
@@ -3046,20 +2750,7 @@ build_function_call_real (function, params, require_complete, flags)
return result;
}
- /* Some built-in function calls will be evaluated at
- compile-time in fold (). */
- result = fold (build_call (function, coerced_params));
- value_type = TREE_TYPE (result);
-
- if (require_complete)
- {
- if (TREE_CODE (value_type) == VOID_TYPE)
- 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);
+ return build_cxx_call (function, params, coerced_params);
}
tree
@@ -3176,11 +2867,7 @@ convert_arguments (typelist, values, fndecl, flags)
parmval = convert_for_initialization
(NULL_TREE, type, val, flags,
"argument passing", fndecl, i);
- if (PROMOTE_PROTOTYPES
- && INTEGRAL_TYPE_P (type)
- && (TYPE_PRECISION (type)
- < TYPE_PRECISION (integer_type_node)))
- parmval = default_conversion (parmval);
+ parmval = convert_for_arg_passing (type, parmval);
}
if (parmval == error_mark_node)
@@ -3590,7 +3277,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
}
else if (TYPE_PTRMEMFUNC_P (type0) && null_ptr_cst_p (op1))
{
- op0 = build_component_ref (op0, pfn_identifier, NULL_TREE, 0);
+ op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier);
op1 = cp_convert (TREE_TYPE (op0), integer_zero_node);
result_type = TREE_TYPE (op0);
}
@@ -3624,10 +3311,10 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
DELTA field is unspecified. */
pfn0 = pfn_from_ptrmemfunc (op0);
pfn1 = pfn_from_ptrmemfunc (op1);
- delta0 = build_component_ref (op0, delta_identifier,
- NULL_TREE, 0);
- delta1 = build_component_ref (op1, delta_identifier,
- NULL_TREE, 0);
+ delta0 = build_ptrmemfunc_access_expr (op0,
+ delta_identifier);
+ delta1 = build_ptrmemfunc_access_expr (op1,
+ delta_identifier);
e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1);
e2 = cp_build_binary_op (EQ_EXPR,
pfn0,
@@ -3765,24 +3452,22 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
== TYPE_PRECISION (TREE_TYPE (arg0)))
&& unsigned0 == unsigned1
&& (unsigned0 || !uns))
- result_type
- = signed_or_unsigned_type (unsigned0,
- common_type (TREE_TYPE (arg0),
- TREE_TYPE (arg1)));
+ result_type = c_common_signed_or_unsigned_type
+ (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
else if (TREE_CODE (arg0) == INTEGER_CST
&& (unsigned1 || !uns)
&& (TYPE_PRECISION (TREE_TYPE (arg1))
< TYPE_PRECISION (result_type))
- && (type = signed_or_unsigned_type (unsigned1,
- TREE_TYPE (arg1)),
+ && (type = c_common_signed_or_unsigned_type
+ (unsigned1, TREE_TYPE (arg1)),
int_fits_type_p (arg0, type)))
result_type = type;
else if (TREE_CODE (arg1) == INTEGER_CST
&& (unsigned0 || !uns)
&& (TYPE_PRECISION (TREE_TYPE (arg0))
< TYPE_PRECISION (result_type))
- && (type = signed_or_unsigned_type (unsigned0,
- TREE_TYPE (arg0)),
+ && (type = c_common_signed_or_unsigned_type
+ (unsigned0, TREE_TYPE (arg0)),
int_fits_type_p (arg1, type)))
result_type = type;
}
@@ -3817,8 +3502,8 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
{
/* Do an unsigned shift if the operand was zero-extended. */
result_type
- = signed_or_unsigned_type (unsigned_arg,
- TREE_TYPE (arg0));
+ = c_common_signed_or_unsigned_type (unsigned_arg,
+ TREE_TYPE (arg0));
/* Convert value-to-be-shifted to that type. */
if (TREE_TYPE (op0) != result_type)
op0 = cp_convert (result_type, op0);
@@ -3891,11 +3576,11 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
not use the most significant bit of result_type. */
else if ((resultcode == EQ_EXPR || resultcode == NE_EXPR)
&& ((op0_signed && TREE_CODE (orig_op1) == INTEGER_CST
- && int_fits_type_p (orig_op1,
- signed_type (result_type)))
+ && int_fits_type_p (orig_op1, c_common_signed_type
+ (result_type)))
|| (op1_signed && TREE_CODE (orig_op0) == INTEGER_CST
- && int_fits_type_p (orig_op0,
- signed_type (result_type)))))
+ && int_fits_type_p (orig_op0, c_common_signed_type
+ (result_type)))))
/* OK */;
else
warning ("comparison between signed and unsigned integer expressions");
@@ -3968,7 +3653,7 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
return error_mark_node;
}
- /* Issue warnings about peculiar, but legal, uses of NULL. */
+ /* Issue warnings about peculiar, but valid, uses of NULL. */
if (/* It's reasonable to use pointer values as operands of &&
and ||, so NULL is no exception. */
!(code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
@@ -4089,50 +3774,6 @@ pointer_diff (op0, op1, ptrtype)
return folded;
}
-/* Handle the case of taking the address of a COMPONENT_REF.
- Called by `build_unary_op'.
-
- ARG is the COMPONENT_REF whose address we want.
- ARGTYPE is the pointer type that this address should have. */
-
-static tree
-build_component_addr (arg, argtype)
- tree arg, argtype;
-{
- tree field = TREE_OPERAND (arg, 1);
- tree basetype = decl_type_context (field);
- tree rval = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
-
- my_friendly_assert (TREE_CODE (field) == FIELD_DECL, 981018);
-
- if (DECL_C_BIT_FIELD (field))
- {
- error ("attempt to take address of bit-field structure member `%D'",
- field);
- return error_mark_node;
- }
-
- if (TREE_CODE (field) == FIELD_DECL
- && TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype))
- {
- /* Can't convert directly to ARGTYPE, since that
- may have the same pointer type as one of our
- baseclasses. */
- tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (rval)), basetype,
- ba_check, NULL);
-
- rval = build_base_path (PLUS_EXPR, rval, binfo, 1);
- rval = build1 (NOP_EXPR, argtype, rval);
- TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
- }
- else
- /* This conversion is harmless. */
- rval = convert_force (argtype, rval, 0);
-
- return fold (build (PLUS_EXPR, argtype, rval,
- cp_convert (argtype, byte_position (field))));
-}
-
/* Construct and perhaps optimize a tree representation
for a unary operation. CODE, a tree_code, specifies the operation
and XARG is the operand. */
@@ -4212,8 +3853,9 @@ build_x_unary_op (code, xarg)
return exp;
}
-/* Like truthvalue_conversion, but handle pointer-to-member constants, where
- a null value is represented by an INTEGER_CST of -1. */
+/* Like c_common_truthvalue_conversion, but handle pointer-to-member
+ constants, where a null value is represented by an INTEGER_CST of
+ -1. */
tree
cp_truthvalue_conversion (expr)
@@ -4223,7 +3865,7 @@ cp_truthvalue_conversion (expr)
if (TYPE_PTRMEM_P (type))
return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);
else
- return truthvalue_conversion (expr);
+ return c_common_truthvalue_conversion (expr);
}
/* Just like cp_truthvalue_conversion, but we want a CLEANUP_POINT_EXPR. */
@@ -4241,7 +3883,45 @@ condition_conversion (expr)
t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
return t;
}
-
+
+/* Return an ADDR_EXPR giving the address of T. This function
+ attempts no optimizations or simplifications; it is a low-level
+ primitive. */
+
+tree
+build_address (tree t)
+{
+ tree addr;
+
+ if (error_operand_p (t) || !cxx_mark_addressable (t))
+ return error_mark_node;
+
+ addr = build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (t)),
+ t);
+ if (staticp (t))
+ TREE_CONSTANT (addr) = 1;
+
+ return addr;
+}
+
+/* Return a NOP_EXPR converting EXPR to TYPE. */
+
+tree
+build_nop (tree type, tree expr)
+{
+ tree nop;
+
+ if (type == error_mark_node || error_operand_p (expr))
+ return expr;
+
+ nop = build1 (NOP_EXPR, type, expr);
+ if (TREE_CONSTANT (expr))
+ TREE_CONSTANT (nop) = 1;
+
+ return nop;
+}
+
/* C++: Must handle pointers to members.
Perhaps type instantiation should be extended to handle conversion
@@ -4428,7 +4108,7 @@ build_unary_op (code, xarg, noconvert)
((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
? "increment" : "decrement"), argtype);
- inc = c_sizeof_nowarn (TREE_TYPE (argtype));
+ inc = cxx_sizeof_nowarn (TREE_TYPE (argtype));
}
else
inc = integer_one_node;
@@ -4543,7 +4223,7 @@ build_unary_op (code, xarg, noconvert)
/* For &x[y], return x+y */
if (TREE_CODE (arg) == ARRAY_REF)
{
- if (mark_addressable (TREE_OPERAND (arg, 0)) == 0)
+ if (!cxx_mark_addressable (TREE_OPERAND (arg, 0)))
return error_mark_node;
return cp_build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1));
@@ -4563,7 +4243,7 @@ build_unary_op (code, xarg, noconvert)
}
if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
- && OVL_NEXT (TREE_OPERAND (arg, 1)) == NULL_TREE)
+ && !really_overloaded_fn (TREE_OPERAND (arg, 1)))
{
/* They're trying to take the address of a unique non-static
member function. This is ill-formed (except in MS-land),
@@ -4576,7 +4256,7 @@ build_unary_op (code, xarg, noconvert)
a useful error here. */
tree base = TREE_TYPE (TREE_OPERAND (arg, 0));
- tree name = DECL_NAME (OVL_CURRENT (TREE_OPERAND (arg, 1)));
+ tree name = DECL_NAME (get_first_fn (TREE_OPERAND (arg, 1)));
if (! flag_ms_extensions)
{
@@ -4625,27 +4305,40 @@ build_unary_op (code, xarg, noconvert)
is an error. */
else if (TREE_CODE (argtype) != FUNCTION_TYPE
&& TREE_CODE (argtype) != METHOD_TYPE
- && !lvalue_or_else (arg, "unary `&'"))
+ && !non_cast_lvalue_or_else (arg, "unary `&'"))
return error_mark_node;
if (argtype != error_mark_node)
argtype = build_pointer_type (argtype);
- if (mark_addressable (arg) == 0)
- return error_mark_node;
-
{
tree addr;
- if (TREE_CODE (arg) == COMPONENT_REF)
- addr = build_component_addr (arg, argtype);
+ if (TREE_CODE (arg) != COMPONENT_REF)
+ addr = build_address (arg);
+ else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
+ {
+ error ("attempt to take address of bit-field structure member `%D'",
+ TREE_OPERAND (arg, 1));
+ return error_mark_node;
+ }
else
- addr = build1 (ADDR_EXPR, argtype, arg);
-
- /* Address of a static or external variable or
- function counts as a constant */
- if (staticp (arg))
- TREE_CONSTANT (addr) = 1;
+ {
+ /* Unfortunately we cannot just build an address
+ expression here, because we would not handle
+ address-constant-expressions or offsetof correctly. */
+ tree field = TREE_OPERAND (arg, 1);
+ tree rval = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0);
+ tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (rval)),
+ decl_type_context (field),
+ ba_check, NULL);
+
+ rval = build_base_path (PLUS_EXPR, rval, binfo, 1);
+ rval = build1 (NOP_EXPR, argtype, rval);
+ TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
+ addr = fold (build (PLUS_EXPR, argtype, rval,
+ cp_convert (argtype, byte_position (field))));
+ }
if (TREE_CODE (argtype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
@@ -4778,9 +4471,7 @@ unary_complex_lvalue (code, arg)
return error_mark_node;
}
- type = build_offset_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t));
- type = build_pointer_type (type);
-
+ type = build_ptrmem_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t));
t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
return t;
}
@@ -4815,12 +4506,12 @@ unary_complex_lvalue (code, arg)
/* Mark EXP saying that we need to be able to take the
address of it; it should not be allocated in a register.
- Value is 1 if successful.
+ Value is true if successful.
C++: we do not allow `current_class_ptr' to be addressable. */
-int
-mark_addressable (exp)
+bool
+cxx_mark_addressable (exp)
tree exp;
{
register tree x = exp;
@@ -4841,7 +4532,7 @@ mark_addressable (exp)
{
error ("cannot take the address of `this', which is an rvalue expression");
TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */
- return 1;
+ return true;
}
/* FALLTHRU */
@@ -4861,25 +4552,25 @@ mark_addressable (exp)
warning ("address requested for `%D', which is declared `register'",
x);
TREE_ADDRESSABLE (x) = 1;
- put_var_into_stack (x);
- return 1;
+ put_var_into_stack (x, /*rescan=*/true);
+ return true;
case FUNCTION_DECL:
TREE_ADDRESSABLE (x) = 1;
TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
- return 1;
+ return true;
case CONSTRUCTOR:
TREE_ADDRESSABLE (x) = 1;
- return 1;
+ return true;
case TARGET_EXPR:
TREE_ADDRESSABLE (x) = 1;
- mark_addressable (TREE_OPERAND (x, 0));
- return 1;
+ cxx_mark_addressable (TREE_OPERAND (x, 0));
+ return true;
default:
- return 1;
+ return true;
}
}
@@ -4919,7 +4610,7 @@ build_x_compound_expr (list)
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
{
- /* FIXME: This test should be in the implicit cast to void of the LHS. */
+ /* FIXME: This test should be in the implicit cast to void of the LHS. */
/* the left-hand operand of a comma expression is like an expression
statement: we should warn if it doesn't have any side-effects,
unless it was explicitly cast to (void). */
@@ -4978,12 +4669,25 @@ build_compound_expr (list)
return build (COMPOUND_EXPR, TREE_TYPE (rest), first, rest);
}
+/* Issue an error message if casting from SRC_TYPE to DEST_TYPE casts
+ away constness. */
+
+static void
+check_for_casting_away_constness (tree src_type, tree dest_type)
+{
+ if (casts_away_constness (src_type, dest_type))
+ error ("static_cast from type `%T' to type `%T' casts away constness",
+ src_type, dest_type);
+}
+
+/* Return an expression representing static_cast<TYPE>(EXPR). */
+
tree
build_static_cast (type, expr)
tree type, expr;
{
tree intype;
- int ok;
+ tree result;
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
@@ -5004,89 +4708,162 @@ build_static_cast (type, expr)
&& TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
expr = TREE_OPERAND (expr, 0);
- if (TREE_CODE (type) == VOID_TYPE)
- {
- expr = convert_to_void (expr, /*implicit=*/NULL);
- return expr;
+ intype = TREE_TYPE (expr);
+
+ /* [expr.static.cast]
+
+ An lvalue of type "cv1 B", where B is a class type, can be cast
+ to type "reference to cv2 D", where D is a class derived (clause
+ _class.derived_) from B, if a valid standard conversion from
+ "pointer to D" to "pointer to B" exists (_conv.ptr_), cv2 is the
+ same cv-qualification as, or greater cv-qualification than, cv1,
+ and B is not a virtual base class of D. */
+ /* We check this case before checking the validity of "TYPE t =
+ EXPR;" below because for this case:
+
+ struct B {};
+ struct D : public B { D(const B&); };
+ extern B& b;
+ void f() { static_cast<const D&>(b); }
+
+ we want to avoid constructing a new D. The standard is not
+ completely clear about this issue, but our interpretation is
+ consistent with other compilers. */
+ if (TREE_CODE (type) == REFERENCE_TYPE
+ && CLASS_TYPE_P (TREE_TYPE (type))
+ && CLASS_TYPE_P (intype)
+ && real_non_cast_lvalue_p (expr)
+ && DERIVED_FROM_P (intype, TREE_TYPE (type))
+ && can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)),
+ build_pointer_type (TYPE_MAIN_VARIANT
+ (TREE_TYPE (type))))
+ && at_least_as_qualified_p (TREE_TYPE (type), intype))
+ {
+ /* At this point we have checked all of the conditions except
+ that B is not a virtual base class of D. That will be
+ checked by build_base_path. */
+ tree base = lookup_base (TREE_TYPE (type), intype, ba_any, NULL);
+
+ /* Convert from B* to D*. */
+ expr = build_base_path (MINUS_EXPR, build_address (expr),
+ base, /*nonnull=*/false);
+ /* Convert the pointer to a reference -- but then remember that
+ there are no expressions with reference type in C++. */
+ return convert_from_reference (build_nop (type, expr));
}
- if (TREE_CODE (type) == REFERENCE_TYPE)
- return (convert_from_reference
- (convert_to_reference (type, expr, CONV_STATIC|CONV_IMPLICIT,
- LOOKUP_COMPLAIN, NULL_TREE)));
+ /* [expr.static.cast]
- if (IS_AGGR_TYPE (type))
- return build_cplus_new (type, (build_method_call
- (NULL_TREE, complete_ctor_identifier,
- build_tree_list (NULL_TREE, expr),
- TYPE_BINFO (type), LOOKUP_NORMAL)));
+ An expression e can be explicitly converted to a type T using a
+ static_cast of the form static_cast<T>(e) if the declaration T
+ t(e);" is well-formed, for some invented temporary variable
+ t. */
+ result = perform_direct_initialization_if_possible (type, expr);
+ if (result)
+ return convert_from_reference (result);
- intype = TREE_TYPE (expr);
+ /* [expr.static.cast]
- /* FIXME handle casting to array type. */
+ Any expression can be explicitly converted to type cv void. */
+ if (TREE_CODE (type) == VOID_TYPE)
+ return convert_to_void (expr, /*implicit=*/NULL);
- ok = 0;
- if (IS_AGGR_TYPE (intype)
- ? can_convert_arg (type, intype, expr)
- : can_convert_arg (strip_all_pointer_quals (type),
- strip_all_pointer_quals (intype), expr))
- /* This is a standard conversion. */
- ok = 1;
- else if (TYPE_PTROB_P (type) && TYPE_PTROB_P (intype))
- {
- /* They're pointers to objects. They must be aggregates that
- are related non-virtually. */
- base_kind kind;
-
- if (IS_AGGR_TYPE (TREE_TYPE (type)) && IS_AGGR_TYPE (TREE_TYPE (intype))
- && lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
- ba_ignore | ba_quiet, &kind)
- && kind != bk_via_virtual)
- ok = 1;
- }
- else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
- {
- /* They're pointers to members. The pointed to objects must be
- the same (ignoring CV qualifiers), and the containing classes
- must be related non-virtually. */
- base_kind kind;
-
- if (same_type_p
- (strip_all_pointer_quals (TREE_TYPE (TREE_TYPE (type))),
- strip_all_pointer_quals (TREE_TYPE (TREE_TYPE (intype))))
- && (lookup_base (TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)),
- TYPE_OFFSET_BASETYPE (TREE_TYPE (type)),
- ba_ignore | ba_quiet, &kind))
- && kind != bk_via_virtual)
- ok = 1;
- }
- else if (TREE_CODE (intype) != BOOLEAN_TYPE
- && TREE_CODE (type) != ARRAY_TYPE
- && TREE_CODE (type) != FUNCTION_TYPE
- && can_convert (intype, strip_all_pointer_quals (type)))
- ok = 1;
- else if (TREE_CODE (intype) == ENUMERAL_TYPE
- && TREE_CODE (type) == ENUMERAL_TYPE)
- /* DR 128: "A value of integral _or enumeration_ type can be explicitly
- converted to an enumeration type."
- The integral to enumeration will be accepted by the previous clause.
- We need to explicitly check for enumeration to enumeration. */
- ok = 1;
+ /* [expr.static.cast]
+ The inverse of any standard conversion sequence (clause _conv_),
+ other than the lvalue-to-rvalue (_conv.lval_), array-to-pointer
+ (_conv.array_), function-to-pointer (_conv.func_), and boolean
+ (_conv.bool_) conversions, can be performed explicitly using
+ static_cast subject to the restriction that the explicit
+ conversion does not cast away constness (_expr.const.cast_), and
+ the following additional rules for specific cases: */
+ /* For reference, the conversions not excluded are: integral
+ promotions, floating point promotion, integral conversions,
+ floating point conversions, floating-integral conversions,
+ pointer conversions, and pointer to member conversions. */
+ if ((ARITHMETIC_TYPE_P (type) && ARITHMETIC_TYPE_P (intype))
+ /* DR 128
+
+ A value of integral _or enumeration_ type can be explicitly
+ converted to an enumeration type. */
+ || (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+ && INTEGRAL_OR_ENUMERATION_TYPE_P (intype)))
+ /* Really, build_c_cast should defer to this function rather
+ than the other way around. */
+ return build_c_cast (type, expr);
+ if (TYPE_PTR_P (type) && TYPE_PTR_P (intype)
+ && CLASS_TYPE_P (TREE_TYPE (type))
+ && CLASS_TYPE_P (TREE_TYPE (intype))
+ && can_convert (build_pointer_type (TYPE_MAIN_VARIANT
+ (TREE_TYPE (intype))),
+ build_pointer_type (TYPE_MAIN_VARIANT
+ (TREE_TYPE (type)))))
+ {
+ tree base;
+
+ check_for_casting_away_constness (intype, type);
+ base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
+ ba_check | ba_quiet, NULL);
+ return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
+ }
+ if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+ || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
+ {
+ tree c1;
+ tree c2;
+ tree t1;
+ tree t2;
+
+ c1 = TYPE_PTRMEM_CLASS_TYPE (intype);
+ c2 = TYPE_PTRMEM_CLASS_TYPE (type);
+
+ if (TYPE_PTRMEM_P (type))
+ {
+ t1 = (build_ptrmem_type
+ (c1,
+ TYPE_MAIN_VARIANT (TYPE_PTRMEM_POINTED_TO_TYPE (intype))));
+ t2 = (build_ptrmem_type
+ (c2,
+ TYPE_MAIN_VARIANT (TYPE_PTRMEM_POINTED_TO_TYPE (type))));
+ }
+ else
+ {
+ t1 = intype;
+ t2 = type;
+ }
+ if (can_convert (t1, t2))
+ {
+ check_for_casting_away_constness (intype, type);
+ if (TYPE_PTRMEM_P (type))
+ {
+ if (TREE_CODE (expr) == PTRMEM_CST)
+ expr = cplus_expand_constant (expr);
+ expr = cp_build_binary_op (PLUS_EXPR,
+ cp_convert (ptrdiff_type_node, expr),
+ get_delta_difference (c1, c2,
+ /*force=*/1));
+ return build_nop (type, expr);
+ }
+ else
+ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr,
+ /*force=*/1);
+ }
+ }
+
/* [expr.static.cast]
- The static_cast operator shall not be used to cast away
- constness. */
- if (ok && casts_away_constness (intype, type))
+ An rvalue of type "pointer to cv void" can be explicitly
+ converted to a pointer to object type. A value of type pointer
+ to object converted to "pointer to cv void" and back to the
+ original pointer type will have its original value. */
+ if (TREE_CODE (intype) == POINTER_TYPE
+ && VOID_TYPE_P (TREE_TYPE (intype))
+ && TYPE_PTROB_P (type))
{
- error ("static_cast from type `%T' to type `%T' casts away constness",
- intype, type);
- return error_mark_node;
+ check_for_casting_away_constness (intype, type);
+ return build_nop (type, expr);
}
- if (ok)
- return build_c_cast (type, expr);
-
error ("invalid static_cast from type `%T' to type `%T'", intype, type);
return error_mark_node;
}
@@ -5310,6 +5087,10 @@ build_c_cast (type, expr)
value = convert_to_void (value, /*implicit=*/NULL);
return value;
}
+
+ if (!complete_type_or_else (type, NULL_TREE))
+ return error_mark_node;
+
/* Convert functions and arrays to pointers and
convert references to their expanded types,
but don't convert any other types. If, however, we are
@@ -5468,11 +5249,9 @@ build_modify_expr (lhs, modifycode, rhs)
except that the RHS goes through a save-expr
so the code to compute it is only emitted once. */
tree cond;
+ tree preeval = NULL_TREE;
- if (lvalue_p (rhs))
- rhs = stabilize_reference (rhs);
- else
- rhs = save_expr (rhs);
+ rhs = stabilize_expr (rhs, &preeval);
/* Check this here to avoid odd errors when trying to convert
a throw to the type of the COND_EXPR. */
@@ -5492,10 +5271,7 @@ build_modify_expr (lhs, modifycode, rhs)
return cond;
/* Make sure the code to compute the rhs comes out
before the split. */
- return build (COMPOUND_EXPR, TREE_TYPE (lhs),
- /* Cast to void to suppress warning
- from warn_if_unused_value. */
- cp_convert (void_type_node, rhs), cond);
+ return build (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond);
}
case OFFSET_REF:
@@ -5522,9 +5298,10 @@ build_modify_expr (lhs, modifycode, rhs)
/* Do the default thing */;
else
{
- result = build_method_call (lhs, complete_ctor_identifier,
- build_tree_list (NULL_TREE, rhs),
- TYPE_BINFO (lhstype), LOOKUP_NORMAL);
+ result = build_special_member_call (lhs, complete_ctor_identifier,
+ build_tree_list (NULL_TREE, rhs),
+ TYPE_BINFO (lhstype),
+ LOOKUP_NORMAL);
if (result == NULL_TREE)
return error_mark_node;
return result;
@@ -5693,7 +5470,7 @@ build_modify_expr (lhs, modifycode, rhs)
from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
? 1 + (modifycode != INIT_EXPR): 0;
- return build_vec_init (lhs, newrhs, from_array);
+ return build_vec_init (lhs, NULL_TREE, newrhs, from_array);
}
if (modifycode == INIT_EXPR)
@@ -5850,7 +5627,7 @@ get_delta_difference (from, to, force)
if (virt_binfo)
{
- /* This is a reinterpret cast, we choose to do nothing. */
+ /* This is a reinterpret cast, we choose to do nothing. */
warning ("pointer to member cast via virtual base `%T' of `%T'",
BINFO_TYPE (virt_binfo),
BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
@@ -5868,7 +5645,7 @@ get_delta_difference (from, to, force)
virt_binfo = binfo_from_vbase (binfo);
if (virt_binfo)
{
- /* This is a reinterpret cast, we choose to do nothing. */
+ /* This is a reinterpret cast, we choose to do nothing. */
if (force)
warning ("pointer to member cast via virtual base `%T' of `%T'",
BINFO_TYPE (virt_binfo),
@@ -5920,7 +5697,7 @@ build_ptrmemfunc1 (type, delta, pfn)
as a value in expressions. TYPE is the POINTER to METHOD_TYPE we
want to be.
- If FORCE is non-zero, then force this conversion, even if
+ If FORCE is nonzero, then force this conversion, even if
we would rather not do it. Usually set when using an explicit
cast.
@@ -5932,11 +5709,17 @@ build_ptrmemfunc (type, pfn, force)
int force;
{
tree fn;
- tree pfn_type = TREE_TYPE (pfn);
- tree to_type = build_ptrmemfunc_type (type);
+ tree pfn_type;
+ tree to_type;
+
+ if (error_operand_p (pfn))
+ return error_mark_node;
+
+ pfn_type = TREE_TYPE (pfn);
+ to_type = build_ptrmemfunc_type (type);
/* Handle multiple conversions of pointer to member functions. */
- if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn)))
+ if (TYPE_PTRMEMFUNC_P (pfn_type))
{
tree delta = NULL_TREE;
tree npfn = NULL_TREE;
@@ -5971,8 +5754,8 @@ build_ptrmemfunc (type, pfn, force)
expand_ptrmemfunc_cst (pfn, &delta, &npfn);
else
{
- npfn = build_component_ref (pfn, pfn_identifier, NULL_TREE, 0);
- delta = build_component_ref (pfn, delta_identifier, NULL_TREE, 0);
+ npfn = build_ptrmemfunc_access_expr (pfn, pfn_identifier);
+ delta = build_ptrmemfunc_access_expr (pfn, delta_identifier);
}
/* Just adjust the DELTA field. */
@@ -6035,7 +5818,7 @@ expand_ptrmemfunc_cst (cst, delta, pfn)
/* If we're dealing with a virtual function, we have to adjust 'this'
again, to point to the base which provides the vtable entry for
fn; the call will do the opposite adjustment. */
- tree orig_class = DECL_VIRTUAL_CONTEXT (fn);
+ tree orig_class = DECL_CONTEXT (fn);
tree binfo = binfo_or_else (orig_class, fn_class);
*delta = fold (build (PLUS_EXPR, TREE_TYPE (*delta),
*delta, BINFO_OFFSET (binfo)));
@@ -6087,7 +5870,7 @@ pfn_from_ptrmemfunc (t)
return pfn;
}
- return build_component_ref (t, pfn_identifier, NULL_TREE, 0);
+ return build_ptrmemfunc_access_expr (t, pfn_identifier);
}
/* Expression EXPR is about to be implicitly converted to TYPE. Warn
@@ -6105,7 +5888,7 @@ dubious_conversion_warnings (type, expr, errtype, fndecl, parmnum)
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
- /* Issue warnings about peculiar, but legal, uses of NULL. */
+ /* Issue warnings about peculiar, but valid, uses of NULL. */
if (ARITHMETIC_TYPE_P (type) && expr == null_node)
{
if (fndecl)
@@ -6243,7 +6026,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
}
/* Convert RHS to be of type TYPE.
- If EXP is non-zero, it is the target of the initialization.
+ If EXP is nonzero, it is the target of the initialization.
ERRTYPE is a string to use in error messages.
Two major differences between the behavior of
@@ -6317,7 +6100,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (fndecl)
savew = warningcount, savee = errorcount;
- rhs = initialize_reference (type, rhs);
+ rhs = initialize_reference (type, rhs, /*decl=*/NULL_TREE);
if (fndecl)
{
if (warningcount > savew)
@@ -6393,9 +6176,10 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
else
{
tree type = TREE_TYPE (o[i]);
- if (CP_TYPE_CONST_P (type)
- || (IS_AGGR_TYPE_CODE (TREE_CODE (type))
- && C_TYPE_FIELDS_READONLY (type)))
+ if (type != error_mark_node
+ && (CP_TYPE_CONST_P (type)
+ || (IS_AGGR_TYPE_CODE (TREE_CODE (type))
+ && C_TYPE_FIELDS_READONLY (type))))
readonly_error (o[i], "modification by `asm'", 1);
}
}
@@ -6465,7 +6249,7 @@ maybe_warn_about_returning_address_of_local (retval)
}
}
-/* Check that returning RETVAL from the current function is legal.
+/* Check that returning RETVAL from the current function is valid.
Return an expression explicitly showing all conversions required to
change RETVAL into the function return type, and to assign it to
the DECL_RESULT for the function. */
@@ -6497,7 +6281,7 @@ check_return_expr (retval)
{
if (in_function_try_handler)
/* If a return statement appears in a handler of the
- function-try-block of a constructor, the program is ill-formed. */
+ function-try-block of a constructor, the program is ill-formed. */
error ("cannot return from a handler of a function-try-block of a constructor");
else if (retval)
/* You can't return a value from a constructor. */
@@ -6618,7 +6402,7 @@ check_return_expr (retval)
/* First convert the value to the function's return type, then
to the type of return value's location to handle the
- case that functype is smaller than the valtype. */
+ case that functype is smaller than the valtype. */
retval = convert_for_initialization
(NULL_TREE, functype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
"return", NULL_TREE, 0);
@@ -6645,9 +6429,9 @@ check_return_expr (retval)
}
-/* Returns non-zero if the pointer-type FROM can be converted to the
+/* Returns nonzero if the pointer-type FROM can be converted to the
pointer-type TO via a qualification conversion. If CONSTP is -1,
- then we return non-zero if the pointers are similar, and the
+ then we return nonzero if the pointers are similar, and the
cv-qualification signature of FROM is a proper subset of that of TO.
If CONSTP is positive, then all outer pointers have been
@@ -6808,10 +6592,12 @@ cp_type_quals (type)
tree type;
{
type = strip_array_types (type);
+ if (type == error_mark_node)
+ return TYPE_UNQUALIFIED;
return TYPE_QUALS (type);
}
-/* Returns non-zero if the TYPE contains a mutable member */
+/* Returns nonzero if the TYPE contains a mutable member */
int
cp_has_mutable_p (type)
@@ -6884,7 +6670,7 @@ casts_away_constness_r (t1, t2)
*t2 = cp_build_qualified_type (*t2, quals2);
}
-/* Returns non-zero if casting from TYPE1 to TYPE2 casts away
+/* Returns nonzero if casting from TYPE1 to TYPE2 casts away
constness. */
static int
diff --git a/contrib/gcc/cp/typeck2.c b/contrib/gcc/cp/typeck2.c
index f8e612b..0e70e2b 100644
--- a/contrib/gcc/cp/typeck2.c
+++ b/contrib/gcc/cp/typeck2.c
@@ -133,6 +133,12 @@ abstract_virtuals_error (decl, type)
tree u;
tree tu;
+ if (processing_template_decl)
+ /* If we are processing a template, TYPE may be a template
+ class where CLASSTYPE_PURE_VIRTUALS always contains
+ inline friends. */
+ return 0;
+
if (!CLASS_TYPE_P (type) || !CLASSTYPE_PURE_VIRTUALS (type))
return 0;
@@ -182,14 +188,35 @@ abstract_virtuals_error (decl, type)
/* Print an error message for invalid use of an incomplete type.
VALUE is the expression that was used (or 0 if that isn't known)
- and TYPE is the type that was invalid. */
+ and TYPE is the type that was invalid. DIAG_TYPE indicates the
+ type of diagnostic: 0 for an error, 1 for a warning, 2 for a
+ pedwarn. */
void
-incomplete_type_error (value, type)
+cxx_incomplete_type_diagnostic (value, type, diag_type)
tree value;
tree type;
+ int diag_type;
{
int decl = 0;
+ void (*p_msg) PARAMS ((const char *, ...));
+ void (*p_msg_at) PARAMS ((const char *, ...));
+
+ if (diag_type == 1)
+ {
+ p_msg = warning;
+ p_msg_at = cp_warning_at;
+ }
+ else if (diag_type == 2)
+ {
+ p_msg = pedwarn;
+ p_msg_at = cp_pedwarn_at;
+ }
+ else
+ {
+ p_msg = error;
+ p_msg_at = cp_error_at;
+ }
/* Avoid duplicate error message. */
if (TREE_CODE (type) == ERROR_MARK)
@@ -199,7 +226,7 @@ incomplete_type_error (value, type)
|| TREE_CODE (value) == PARM_DECL
|| TREE_CODE (value) == FIELD_DECL))
{
- cp_error_at ("`%D' has incomplete type", value);
+ (*p_msg_at) ("`%D' has incomplete type", value);
decl = 1;
}
retry:
@@ -211,15 +238,15 @@ retry:
case UNION_TYPE:
case ENUMERAL_TYPE:
if (!decl)
- error ("invalid use of undefined type `%#T'", type);
+ (*p_msg) ("invalid use of undefined type `%#T'", type);
if (!TYPE_TEMPLATE_INFO (type))
- cp_error_at ("forward declaration of `%#T'", type);
+ (*p_msg_at) ("forward declaration of `%#T'", type);
else
- cp_error_at ("declaration of `%#T'", type);
+ (*p_msg_at) ("declaration of `%#T'", type);
break;
case VOID_TYPE:
- error ("invalid use of `%T'", type);
+ (*p_msg) ("invalid use of `%T'", type);
break;
case ARRAY_TYPE:
@@ -228,27 +255,27 @@ retry:
type = TREE_TYPE (type);
goto retry;
}
- error ("invalid use of array with unspecified bounds");
+ (*p_msg) ("invalid use of array with unspecified bounds");
break;
case OFFSET_TYPE:
bad_member:
- error ("invalid use of member (did you forget the `&' ?)");
+ (*p_msg) ("invalid use of member (did you forget the `&' ?)");
break;
case TEMPLATE_TYPE_PARM:
- error ("invalid use of template type parameter");
+ (*p_msg) ("invalid use of template type parameter");
break;
case UNKNOWN_TYPE:
if (value && TREE_CODE (value) == COMPONENT_REF)
goto bad_member;
else if (value && TREE_CODE (value) == ADDR_EXPR)
- error ("address of overloaded function with no contextual type information");
+ (*p_msg) ("address of overloaded function with no contextual type information");
else if (value && TREE_CODE (value) == OVERLOAD)
- error ("overloaded function with no contextual type information");
+ (*p_msg) ("overloaded function with no contextual type information");
else
- error ("insufficient contextual information to determine type");
+ (*p_msg) ("insufficient contextual information to determine type");
break;
default:
@@ -256,6 +283,17 @@ retry:
}
}
+/* Backward-compatibility interface to incomplete_type_diagnostic;
+ required by ../tree.c. */
+#undef cxx_incomplete_type_error
+void
+cxx_incomplete_type_error (value, type)
+ tree value;
+ tree type;
+{
+ cxx_incomplete_type_diagnostic (value, type, 0);
+}
+
/* Perform appropriate conversions on the initial value of a variable,
store it in the declaration DECL,
@@ -288,12 +326,6 @@ store_init_value (decl, init)
if (TREE_CODE (type) == ERROR_MARK)
return NULL_TREE;
-#if 0
- /* This breaks arrays, and should not have any effect for other decls. */
- /* Take care of C++ business up here. */
- type = TYPE_MAIN_VARIANT (type);
-#endif
-
if (IS_AGGR_TYPE (type))
{
if (! TYPE_HAS_TRIVIAL_INIT_REF (type)
@@ -305,35 +337,6 @@ store_init_value (decl, init)
error ("constructor syntax used, but no constructor declared for type `%T'", type);
init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (init));
}
-#if 0
- if (TREE_CODE (init) == CONSTRUCTOR)
- {
- tree field;
-
- /* Check that we're really an aggregate as ARM 8.4.1 defines it. */
- if (CLASSTYPE_N_BASECLASSES (type))
- cp_error_at ("initializer list construction invalid for derived class object `%D'", decl);
- if (CLASSTYPE_VTBL_PTR (type))
- cp_error_at ("initializer list construction invalid for polymorphic class object `%D'", decl);
- if (TYPE_NEEDS_CONSTRUCTING (type))
- {
- cp_error_at ("initializer list construction invalid for `%D'", decl);
- error ("due to the presence of a constructor");
- }
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- if (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);
- }
- for (field = TYPE_METHODS (type); field; field = TREE_CHAIN (field))
- if (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);
- }
- }
-#endif
}
else if (TREE_CODE (init) == TREE_LIST
&& TREE_TYPE (init) != unknown_type_node)
@@ -370,15 +373,8 @@ store_init_value (decl, init)
/* End of special C++ code. */
- /* We might have already run this bracketed initializer through
- digest_init. Don't do so again. */
- if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init)
- && TREE_TYPE (init)
- && TYPE_MAIN_VARIANT (TREE_TYPE (init)) == TYPE_MAIN_VARIANT (type))
- value = init;
- else
- /* Digest the specified initializer into an expression. */
- value = digest_init (type, init, (tree *) 0);
+ /* Digest the specified initializer into an expression. */
+ value = digest_init (type, init, (tree *) 0);
/* Store the expression if valid; else report error. */
@@ -391,32 +387,8 @@ store_init_value (decl, init)
return value;
else if (TREE_STATIC (decl)
&& (! TREE_CONSTANT (value)
- || ! initializer_constant_valid_p (value, TREE_TYPE (value))
-#if 0
- /* A STATIC PUBLIC int variable doesn't have to be
- run time inited when doing pic. (mrs) */
- /* Since ctors and dtors are the only things that can
- reference vtables, and they are always written down
- the vtable definition, we can leave the
- vtables in initialized data space.
- However, other initialized data cannot be initialized
- this way. Instead a global file-level initializer
- must do the job. */
- || (flag_pic && !DECL_VIRTUAL_P (decl) && TREE_PUBLIC (decl))
-#endif
- ))
-
+ || ! initializer_constant_valid_p (value, TREE_TYPE (value))))
return value;
-#if 0 /* No, that's C. jason 9/19/94 */
- else
- {
- if (pedantic && TREE_CODE (value) == CONSTRUCTOR)
- {
- if (! TREE_CONSTANT (value) || ! TREE_STATIC (value))
- pedwarn ("ISO C++ forbids non-constant aggregate initializer expressions");
- }
- }
-#endif
/* Store the VALUE in DECL_INITIAL. If we're building a
statement-tree we will actually expand the initialization later
@@ -425,27 +397,6 @@ store_init_value (decl, init)
return NULL_TREE;
}
-/* Same as store_init_value, but used for known-to-be-valid static
- initializers. Used to introduce a static initializer even in data
- structures that may require dynamic initialization. */
-
-tree
-force_store_init_value (decl, init)
- tree decl, init;
-{
- tree type = TREE_TYPE (decl);
- int needs_constructing = TYPE_NEEDS_CONSTRUCTING (type);
-
- TYPE_NEEDS_CONSTRUCTING (type) = 0;
-
- init = store_init_value (decl, init);
- if (init)
- abort ();
-
- TYPE_NEEDS_CONSTRUCTING (type) = needs_constructing;
-
- return init;
-}
/* Digest the parser output INIT as an initializer for type TYPE.
Return a C expression of type TYPE to represent the initial value.
@@ -463,8 +414,7 @@ digest_init (type, init, tail)
enum tree_code code = TREE_CODE (type);
tree element = NULL_TREE;
tree old_tail_contents = NULL_TREE;
- /* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR
- tree node which has no TREE_TYPE. */
+ /* Nonzero if INIT is a braced grouping. */
int raw_constructor;
/* By default, assume we use one element from a list.
@@ -482,7 +432,7 @@ digest_init (type, init, tail)
if (TREE_CODE (init) == ERROR_MARK)
/* __PRETTY_FUNCTION__'s initializer is a bogus expression inside
- a template function. This gets substituted during instantiation. */
+ a template function. This gets substituted during instantiation. */
return init;
/* We must strip the outermost array type when completing the type,
@@ -495,10 +445,8 @@ digest_init (type, init, tail)
if (TREE_CODE (init) == NON_LVALUE_EXPR)
init = TREE_OPERAND (init, 0);
- if (TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == type)
- return init;
-
- raw_constructor = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0;
+ raw_constructor = (TREE_CODE (init) == CONSTRUCTOR
+ && TREE_HAS_CONSTRUCTOR (init));
if (raw_constructor
&& CONSTRUCTOR_ELTS (init) != 0
@@ -759,7 +707,9 @@ process_init_constructor (type, init, elts)
next1 = digest_init (TREE_TYPE (type), next1, 0);
}
else if (! zero_init_p (TREE_TYPE (type)))
- next1 = build_forced_zero_init (TREE_TYPE (type));
+ next1 = build_zero_init (TREE_TYPE (type),
+ /*nelts=*/NULL_TREE,
+ /*static_storage_p=*/false);
else
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
@@ -808,7 +758,7 @@ process_init_constructor (type, init, elts)
continue;
}
- if (TREE_CODE (field) != FIELD_DECL)
+ if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
if (tail)
@@ -876,7 +826,9 @@ process_init_constructor (type, init, elts)
warning ("missing initializer for member `%D'", field);
if (! zero_init_p (TREE_TYPE (field)))
- next1 = build_forced_zero_init (TREE_TYPE (field));
+ next1 = build_zero_init (TREE_TYPE (field),
+ /*nelts=*/NULL_TREE,
+ /*static_storage_p=*/false);
else
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
@@ -900,8 +852,7 @@ 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
- || TREE_CODE (field) != FIELD_DECL))
+ while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL))
field = TREE_CHAIN (field);
/* If this element specifies a field, initialize via that field. */
@@ -986,7 +937,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 type specified in BASETYPE. For example, given the
+ that value to the base specified in BASETYPE. For example, given the
hierarchy
class L { int ii; };
@@ -1007,29 +958,36 @@ process_init_constructor (type, init, elts)
I used to think that this was nonconformant, that the standard specified
that first we look up ii in A, then convert x to an L& and pull out the
ii part. But in fact, it does say that we convert x to an A&; A here
- is known as the "naming class". (jason 2000-12-19) */
+ is known as the "naming class". (jason 2000-12-19)
+
+ BINFO_P points to a variable initialized either to NULL_TREE or to the
+ binfo for the specific base subobject we want to convert to. */
tree
-build_scoped_ref (datum, basetype)
+build_scoped_ref (datum, basetype, binfo_p)
tree datum;
tree basetype;
+ tree *binfo_p;
{
- tree ref;
tree binfo;
if (datum == error_mark_node)
return error_mark_node;
- binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL);
+ if (*binfo_p)
+ binfo = *binfo_p;
+ else
+ binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL);
- if (binfo == error_mark_node)
- return error_mark_node;
- if (!binfo)
- return error_not_base_type (TREE_TYPE (datum), basetype);
-
- ref = build_unary_op (ADDR_EXPR, datum, 0);
- ref = build_base_path (PLUS_EXPR, ref, binfo, 1);
+ if (!binfo || binfo == error_mark_node)
+ {
+ *binfo_p = NULL_TREE;
+ if (!binfo)
+ error_not_base_type (basetype, TREE_TYPE (datum));
+ return error_mark_node;
+ }
- return build_indirect_ref (ref, "(compiler error in build_scoped_ref)");
+ *binfo_p = binfo;
+ return build_base_path (PLUS_EXPR, datum, binfo, 1);
}
/* Build a reference to an object specified by the C++ `->' operator.
@@ -1164,8 +1122,8 @@ build_m_component_ref (datum, component)
| cp_type_quals (TREE_TYPE (datum)));
/* There's no such thing as a mutable pointer-to-member, so
- we don't need to deal with that here like we do in
- build_component_ref. */
+ things are not as complex as they are for references to
+ non-static data members. */
field_type = cp_build_qualified_type (field_type, type_quals);
}
}
@@ -1277,8 +1235,8 @@ build_functional_cast (exp, parms)
return get_target_expr (exp);
}
- exp = build_method_call (NULL_TREE, complete_ctor_identifier, parms,
- TYPE_BINFO (type), LOOKUP_NORMAL);
+ exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, parms,
+ TYPE_BINFO (type), LOOKUP_NORMAL);
if (exp == error_mark_node)
return error_mark_node;
@@ -1313,6 +1271,7 @@ add_exception_specifier (list, spec, complain)
int ok;
tree core = spec;
int is_ptr;
+ int diag_type = -1; /* none */
if (spec == error_mark_node)
return list;
@@ -1334,7 +1293,15 @@ add_exception_specifier (list, spec, complain)
else if (processing_template_decl)
ok = 1;
else
- ok = COMPLETE_TYPE_P (complete_type (core));
+ {
+ ok = 1;
+ /* 15.4/1 says that types in an exception specifier must be complete,
+ but it seems more reasonable to only require this on definitions
+ and calls. So just give a pedwarn at this point; we will give an
+ error later if we hit one of those two cases. */
+ if (!COMPLETE_TYPE_P (complete_type (core)))
+ diag_type = 2; /* pedwarn */
+ }
if (ok)
{
@@ -1344,19 +1311,19 @@ add_exception_specifier (list, spec, complain)
if (same_type_p (TREE_VALUE (probe), spec))
break;
if (!probe)
- {
- spec = build_tree_list (NULL_TREE, spec);
- TREE_CHAIN (spec) = list;
- list = spec;
- }
+ list = tree_cons (NULL_TREE, spec, list);
}
- else if (complain)
- incomplete_type_error (NULL_TREE, core);
+ else
+ diag_type = 0; /* error */
+
+ if (diag_type >= 0 && complain)
+ cxx_incomplete_type_diagnostic (NULL_TREE, core, diag_type);
+
return list;
}
/* Combine the two exceptions specifier lists LIST and ADD, and return
- their union. */
+ their union. */
tree
merge_exception_specifiers (list, add)
@@ -1390,3 +1357,34 @@ merge_exception_specifiers (list, add)
}
return list;
}
+
+/* Subroutine of build_call. Ensure that each of the types in the
+ exception specification is complete. Technically, 15.4/1 says that
+ they need to be complete when we see a declaration of the function,
+ but we should be able to get away with only requiring this when the
+ function is defined or called. See also add_exception_specifier. */
+
+void
+require_complete_eh_spec_types (fntype, decl)
+ tree fntype, decl;
+{
+ tree raises;
+ /* Don't complain about calls to op new. */
+ if (decl && DECL_ARTIFICIAL (decl))
+ return;
+ for (raises = TYPE_RAISES_EXCEPTIONS (fntype); raises;
+ raises = TREE_CHAIN (raises))
+ {
+ tree type = TREE_VALUE (raises);
+ if (type && !COMPLETE_TYPE_P (type))
+ {
+ if (decl)
+ error
+ ("call to function `%D' which throws incomplete type `%#T'",
+ decl, type);
+ else
+ error ("call to function which throws incomplete type `%#T'",
+ decl);
+ }
+ }
+}
diff --git a/contrib/gcc/cplus-dem.c b/contrib/gcc/cplus-dem.c
index 203e30d..199f767 100644
--- a/contrib/gcc/cplus-dem.c
+++ b/contrib/gcc/cplus-dem.c
@@ -11,6 +11,15 @@ modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
+In addition to the permissions in the GNU Library General Public
+License, the Free Software Foundation gives you unlimited permission
+to link the compiled version of this file into combinations with other
+programs, and to distribute those combinations without any restriction
+coming from the use of this file. (The Library Public License
+restrictions do apply in other respects; for example, they cover
+modification of the file, and distribution when not linked into a
+combined executable.)
+
Libiberty is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
@@ -305,8 +314,6 @@ const struct demangler_engine libiberty_demanglers[] =
};
#define STRING_EMPTY(str) ((str) -> b == (str) -> p)
-#define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
- string_prepend(str, " ");}
#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
string_append(str, " ");}
#define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
@@ -516,7 +523,7 @@ recursively_demangle PARAMS ((struct work_stuff *, const char **, string *,
int));
static void
-grow_vect PARAMS ((void **, size_t *, size_t, int));
+grow_vect PARAMS ((char **, size_t *, size_t, int));
/* Translate count to integer, consuming tokens in the process.
Conversion terminates on the first non-digit character.
@@ -938,7 +945,7 @@ cplus_demangle (mangled, options)
static void
grow_vect (old_vect, size, min_size, element_size)
- void **old_vect;
+ char **old_vect;
size_t *size;
size_t min_size;
int element_size;
@@ -948,7 +955,7 @@ grow_vect (old_vect, size, min_size, element_size)
*size *= 2;
if (*size < min_size)
*size = min_size;
- *old_vect = xrealloc (*old_vect, *size * element_size);
+ *old_vect = (void *) xrealloc (*old_vect, *size * element_size);
}
}
@@ -971,8 +978,7 @@ ada_demangle (mangled, option)
char *demangled = NULL;
int at_start_name;
int changed;
- char *demangling_buffer = NULL;
- size_t demangling_buffer_size = 0;
+ size_t demangled_size = 0;
changed = 0;
@@ -1000,10 +1006,9 @@ ada_demangle (mangled, option)
}
/* Make demangled big enough for possible expansion by operator name. */
- grow_vect ((void **) &(demangling_buffer),
- &demangling_buffer_size, 2 * len0 + 1,
+ grow_vect (&demangled,
+ &demangled_size, 2 * len0 + 1,
sizeof (char));
- demangled = demangling_buffer;
if (ISDIGIT ((unsigned char) mangled[len0 - 1])) {
for (i = len0 - 2; i >= 0 && ISDIGIT ((unsigned char) mangled[i]); i -= 1)
@@ -1053,10 +1058,10 @@ ada_demangle (mangled, option)
return demangled;
Suppress:
- grow_vect ((void **) &(demangling_buffer),
- &demangling_buffer_size, strlen (mangled) + 3,
+ grow_vect (&demangled,
+ &demangled_size, strlen (mangled) + 3,
sizeof (char));
- demangled = demangling_buffer;
+
if (mangled[0] == '<')
strcpy (demangled, mangled);
else
@@ -1208,7 +1213,7 @@ work_stuff_copy_to_from (to, from)
if (from->ntmpl_args)
to->tmpl_argvec
- = xmalloc (from->ntmpl_args * sizeof (to->tmpl_argvec[0]));
+ = (char **) xmalloc (from->ntmpl_args * sizeof (to->tmpl_argvec[0]));
for (i = 0; i < from->ntmpl_args; i++)
{
@@ -4880,337 +4885,3 @@ string_append_template_idx (s, idx)
sprintf(buf, "T%d", idx);
string_append (s, buf);
}
-
-/* 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. */
-
-#ifdef MAIN
-
-#include "getopt.h"
-
-static const char *program_name;
-static const char *program_version = VERSION;
-static int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE;
-
-static void demangle_it PARAMS ((char *));
-static void usage PARAMS ((FILE *, int)) ATTRIBUTE_NORETURN;
-static void fatal PARAMS ((const char *)) ATTRIBUTE_NORETURN;
-static void print_demangler_list PARAMS ((FILE *));
-
-static void
-demangle_it (mangled_name)
- char *mangled_name;
-{
- char *result;
-
- /* For command line args, also try to demangle type encodings. */
- result = cplus_demangle (mangled_name, flags | DMGL_TYPES);
- if (result == NULL)
- {
- printf ("%s\n", mangled_name);
- }
- else
- {
- printf ("%s\n", result);
- free (result);
- }
-}
-
-static void
-print_demangler_list (stream)
- FILE *stream;
-{
- const struct demangler_engine *demangler;
-
- fprintf (stream, "{%s", libiberty_demanglers->demangling_style_name);
-
- for (demangler = libiberty_demanglers + 1;
- demangler->demangling_style != unknown_demangling;
- ++demangler)
- fprintf (stream, ",%s", demangler->demangling_style_name);
-
- fprintf (stream, "}");
-}
-
-static void
-usage (stream, status)
- FILE *stream;
- int status;
-{
- fprintf (stream, "\
-Usage: %s [-_] [-n] [--strip-underscores] [--no-strip-underscores] \n",
- program_name);
-
- fprintf (stream, "\
- [-s ");
- print_demangler_list (stream);
- fprintf (stream, "]\n");
-
- fprintf (stream, "\
- [--format ");
- print_demangler_list (stream);
- fprintf (stream, "]\n");
-
- fprintf (stream, "\
- [--help] [--version] [arg...]\n");
- exit (status);
-}
-
-#define MBUF_SIZE 32767
-char mbuffer[MBUF_SIZE];
-
-/* Defined in the automatically-generated underscore.c. */
-extern int prepends_underscore;
-
-int strip_underscore = 0;
-
-static const struct option long_options[] = {
- {"strip-underscores", no_argument, 0, '_'},
- {"format", required_argument, 0, 's'},
- {"help", no_argument, 0, 'h'},
- {"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.");
-}
-
-
-static const char *
-standard_symbol_characters PARAMS ((void));
-
-static const char *
-hp_symbol_characters PARAMS ((void));
-
-static const char *
-gnu_v3_symbol_characters PARAMS ((void));
-
-/* Return the string of non-alnum characters that may occur
- as a valid symbol component, in the standard assembler symbol
- syntax. */
-
-static const char *
-standard_symbol_characters ()
-{
- return "_$.";
-}
-
-
-/* Return the string of non-alnum characters that may occur
- as a valid symbol name component in an HP object file.
-
- Note that, since HP's compiler generates object code straight from
- C++ source, without going through an assembler, its mangled
- identifiers can use all sorts of characters that no assembler would
- tolerate, so the alphabet this function creates is a little odd.
- Here are some sample mangled identifiers offered by HP:
-
- typeid*__XT24AddressIndExpClassMember_
- [Vftptr]key:__dt__32OrdinaryCompareIndExpClassMemberFv
- __ct__Q2_9Elf64_Dyn18{unnamed.union.#1}Fv
-
- This still seems really weird to me, since nowhere else in this
- file is there anything to recognize curly brackets, parens, etc.
- I've talked with Srikanth <srikanth@cup.hp.com>, and he assures me
- this is right, but I still strongly suspect that there's a
- misunderstanding here.
-
- If we decide it's better for c++filt to use HP's assembler syntax
- to scrape identifiers out of its input, here's the definition of
- the symbol name syntax from the HP assembler manual:
-
- Symbols are composed of uppercase and lowercase letters, decimal
- digits, dollar symbol, period (.), ampersand (&), pound sign(#) and
- underscore (_). A symbol can begin with a letter, digit underscore or
- dollar sign. If a symbol begins with a digit, it must contain a
- non-digit character.
-
- So have fun. */
-static const char *
-hp_symbol_characters ()
-{
- return "_$.<>#,*&[]:(){}";
-}
-
-
-/* Return the string of non-alnum characters that may occur
- as a valid symbol component in the GNU C++ V3 ABI mangling
- scheme. */
-
-static const char *
-gnu_v3_symbol_characters ()
-{
- return "_$.";
-}
-
-
-extern int main PARAMS ((int, char **));
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- char *result;
- int c;
- const char *valid_symbols;
- enum demangling_styles style = auto_demangling;
-
- program_name = argv[0];
-
- strip_underscore = prepends_underscore;
-
- while ((c = getopt_long (argc, argv, "_ns:", 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 (C++ demangler), version %s\n", program_name, program_version);
- return (0);
- case '_':
- strip_underscore = 1;
- break;
- case 's':
- {
- style = cplus_demangle_name_to_style (optarg);
- if (style == unknown_demangling)
- {
- fprintf (stderr, "%s: unknown demangling style `%s'\n",
- program_name, optarg);
- return (1);
- }
- else
- cplus_demangle_set_style (style);
- }
- break;
- }
- }
-
- if (optind < argc)
- {
- for ( ; optind < argc; optind++)
- {
- demangle_it (argv[optind]);
- }
- }
- else
- {
- switch (current_demangling_style)
- {
- case gnu_demangling:
- case lucid_demangling:
- case arm_demangling:
- case java_demangling:
- case edg_demangling:
- case gnat_demangling:
- case auto_demangling:
- valid_symbols = standard_symbol_characters ();
- break;
- case hp_demangling:
- valid_symbols = hp_symbol_characters ();
- break;
- case gnu_v3_demangling:
- valid_symbols = gnu_v3_symbol_characters ();
- break;
- default:
- /* Folks should explicitly indicate the appropriate alphabet for
- each demangling. Providing a default would allow the
- question to go unconsidered. */
- abort ();
- }
-
- for (;;)
- {
- int i = 0;
- c = getchar ();
- /* Try to read a label. */
- while (c != EOF && (ISALNUM (c) || strchr (valid_symbols, c)))
- {
- if (i >= MBUF_SIZE-1)
- break;
- mbuffer[i++] = c;
- c = getchar ();
- }
- if (i > 0)
- {
- int skip_first = 0;
-
- if (mbuffer[0] == '.' || mbuffer[0] == '$')
- ++skip_first;
- if (strip_underscore && mbuffer[skip_first] == '_')
- ++skip_first;
-
- if (skip_first > i)
- skip_first = i;
-
- mbuffer[i] = 0;
- flags |= (int) style;
- result = cplus_demangle (mbuffer + skip_first, flags);
- if (result)
- {
- if (mbuffer[0] == '.')
- putc ('.', stdout);
- fputs (result, stdout);
- free (result);
- }
- else
- fputs (mbuffer, stdout);
-
- fflush (stdout);
- }
- if (c == EOF)
- break;
- putchar (c);
- fflush (stdout);
- }
- }
-
- return (0);
-}
-
-static void
-fatal (str)
- const char *str;
-{
- fprintf (stderr, "%s: %s\n", program_name, str);
- exit (1);
-}
-
-PTR
-xmalloc (size)
- size_t size;
-{
- register PTR value = (PTR) malloc (size);
- if (value == 0)
- fatal ("virtual memory exhausted");
- return value;
-}
-
-PTR
-xrealloc (ptr, size)
- PTR ptr;
- size_t size;
-{
- register PTR value = (PTR) realloc (ptr, size);
- if (value == 0)
- fatal ("virtual memory exhausted");
- return value;
-}
-#endif /* main */
diff --git a/contrib/gcc/cppdefault.h b/contrib/gcc/cppdefault.h
index cda691d..40a8609 100644
--- a/contrib/gcc/cppdefault.h
+++ b/contrib/gcc/cppdefault.h
@@ -42,48 +42,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#undef CROSS_INCLUDE_DIR
#endif
-/* We let tm.h override the types used here, to handle trivial differences
- such as the choice of unsigned int or long unsigned int for size_t.
- When machines start needing nontrivial differences in the size type,
- it would be best to do something here to figure out automatically
- from other information what type to use. */
-
-/* The string value for __SIZE_TYPE__. */
-
-#ifndef SIZE_TYPE
-#define SIZE_TYPE "long unsigned int"
-#endif
-
-/* The string value for __PTRDIFF_TYPE__. */
-
-#ifndef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-#endif
-
-/* The string value for __WCHAR_TYPE__. */
-
-#ifndef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-#endif
-
-/* The string value for __WINT_TYPE__. */
-
-#ifndef WINT_TYPE
-#define WINT_TYPE "unsigned int"
-#endif
-
-/* The string value for __USER_LABEL_PREFIX__ */
-
-#ifndef USER_LABEL_PREFIX
-#define USER_LABEL_PREFIX ""
-#endif
-
-/* The string value for __REGISTER_PREFIX__ */
-
-#ifndef REGISTER_PREFIX
-#define REGISTER_PREFIX ""
-#endif
-
/* This is the default list of directories to search for include files.
It may be overridden by the various -I and -ixxx options.
diff --git a/contrib/gcc/cpperror.c b/contrib/gcc/cpperror.c
index 375dc2b..360bc8c 100644
--- a/contrib/gcc/cpperror.c
+++ b/contrib/gcc/cpperror.c
@@ -31,32 +31,21 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static void print_location PARAMS ((cpp_reader *, unsigned int, unsigned int));
-/* Don't remove the blank before do, as otherwise the exgettext
- script will mistake this as a function definition */
-#define v_message(msgid, ap) \
- do { vfprintf (stderr, _(msgid), ap); putc ('\n', stderr); } while (0)
-
/* Print the logical file location (LINE, COL) in preparation for a
- diagnostic. Outputs the #include chain if it has changed. */
+ diagnostic. Outputs the #include chain if it has changed. A line
+ of zero suppresses the include stack, and outputs the program name
+ instead. */
static void
print_location (pfile, line, col)
cpp_reader *pfile;
unsigned int line, col;
{
- cpp_buffer *buffer = pfile->buffer;
-
- if (!buffer)
+ if (!pfile->buffer || line == 0)
fprintf (stderr, "%s: ", progname);
else
{
const struct line_map *map;
- if (line == 0)
- {
- line = pfile->cur_token[-1].line;
- col = pfile->cur_token[-1].col;
- }
-
map = lookup_line (&pfile->line_maps, line);
print_containing_files (&pfile->line_maps, map);
@@ -75,226 +64,129 @@ print_location (pfile, line, col)
}
}
-/* Set up for an error message: print the file and line, bump the error
+/* Set up for a diagnostic: print the file and line, bump the error
counter, etc. LINE is the logical line number; zero means to print
- at the location of the previously lexed token, which tends to be the
- correct place by default. Returns 0 if the error has been suppressed. */
+ at the location of the previously lexed token, which tends to be
+ the correct place by default. Returns 0 if the error has been
+ suppressed. */
int
_cpp_begin_message (pfile, code, line, column)
cpp_reader *pfile;
- enum error_type code;
+ int code;
unsigned int line, column;
{
- int is_warning = 0;
+ int level = DL_EXTRACT (code);
- switch (code)
+ switch (level)
{
- case PEDWARN:
- case WARNING:
+ case DL_WARNING:
+ case DL_PEDWARN:
if (CPP_IN_SYSTEM_HEADER (pfile)
&& ! CPP_OPTION (pfile, warn_system_headers))
return 0;
- case WARNING_SYSHDR:
+ /* Fall through. */
+
+ case DL_WARNING_SYSHDR:
if (CPP_OPTION (pfile, warnings_are_errors)
- || (code == PEDWARN && CPP_OPTION (pfile, pedantic_errors)))
+ || (level == DL_PEDWARN && CPP_OPTION (pfile, pedantic_errors)))
{
if (CPP_OPTION (pfile, inhibit_errors))
return 0;
- if (pfile->errors < CPP_FATAL_LIMIT)
- pfile->errors++;
- }
- else
- {
- if (CPP_OPTION (pfile, inhibit_warnings))
- return 0;
- is_warning = 1;
+ level = DL_ERROR;
+ pfile->errors++;
}
+ else if (CPP_OPTION (pfile, inhibit_warnings))
+ return 0;
break;
-
- case ERROR:
+
+ case DL_ERROR:
if (CPP_OPTION (pfile, inhibit_errors))
return 0;
- if (pfile->errors < CPP_FATAL_LIMIT)
- pfile->errors++;
- break;
- /* Fatal errors cannot be inhibited. */
- case FATAL:
- pfile->errors = CPP_FATAL_LIMIT;
- break;
- case ICE:
- fprintf (stderr, _("internal error: "));
- pfile->errors = CPP_FATAL_LIMIT;
+ /* ICEs cannot be inhibited. */
+ case DL_ICE:
+ pfile->errors++;
break;
}
print_location (pfile, line, column);
- if (is_warning)
+ if (DL_WARNING_P (level))
fputs (_("warning: "), stderr);
+ else if (level == DL_ICE)
+ fputs (_("internal error: "), stderr);
return 1;
}
-/* Exported interface. */
-
-/* For reporting internal errors. Prints "internal error: " for you,
- otherwise identical to cpp_fatal. */
-void
-cpp_ice VPARAMS ((cpp_reader *pfile, const char *msgid, ...))
-{
- VA_OPEN (ap, msgid);
- VA_FIXEDARG (ap, cpp_reader *, pfile);
- VA_FIXEDARG (ap, const char *, msgid);
-
- if (_cpp_begin_message (pfile, ICE, 0, 0))
- v_message (msgid, ap);
-
- VA_CLOSE (ap);
-}
-
-/* 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
-cpp_fatal VPARAMS ((cpp_reader *pfile, const char *msgid, ...))
-{
- VA_OPEN (ap, msgid);
- VA_FIXEDARG (ap, cpp_reader *, pfile);
- VA_FIXEDARG (ap, const char *, msgid);
-
- if (_cpp_begin_message (pfile, FATAL, 0, 0))
- v_message (msgid, ap);
+/* Don't remove the blank before do, as otherwise the exgettext
+ script will mistake this as a function definition */
+#define v_message(msgid, ap) \
+ do { vfprintf (stderr, _(msgid), ap); putc ('\n', stderr); } while (0)
- VA_CLOSE (ap);
-}
+/* Exported interface. */
/* Print an error at the location of the previously lexed token. */
void
-cpp_error VPARAMS ((cpp_reader * pfile, const char *msgid, ...))
+cpp_error VPARAMS ((cpp_reader * pfile, int level, const char *msgid, ...))
{
- VA_OPEN (ap, msgid);
- VA_FIXEDARG (ap, cpp_reader *, pfile);
- VA_FIXEDARG (ap, const char *, msgid);
-
- if (_cpp_begin_message (pfile, ERROR, 0, 0))
- v_message (msgid, ap);
-
- VA_CLOSE (ap);
-}
+ unsigned int line, column;
-/* Print an error at a specific location. */
-void
-cpp_error_with_line VPARAMS ((cpp_reader *pfile, int line, int column,
- const char *msgid, ...))
-{
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, cpp_reader *, pfile);
- VA_FIXEDARG (ap, int, line);
- VA_FIXEDARG (ap, int, column);
+ VA_FIXEDARG (ap, int, level);
VA_FIXEDARG (ap, const char *, msgid);
- if (_cpp_begin_message (pfile, ERROR, line, column))
- v_message (msgid, ap);
-
- VA_CLOSE (ap);
-}
-
-/* Error including a message from `errno'. */
-void
-cpp_error_from_errno (pfile, name)
- cpp_reader *pfile;
- const char *name;
-{
- cpp_error (pfile, "%s: %s", name, xstrerror (errno));
-}
-
-/* Print a warning at the location of the previously lexed token. */
-void
-cpp_warning VPARAMS ((cpp_reader * pfile, const char *msgid, ...))
-{
- VA_OPEN (ap, msgid);
- VA_FIXEDARG (ap, cpp_reader *, pfile);
- VA_FIXEDARG (ap, const char *, msgid);
-
- if (_cpp_begin_message (pfile, WARNING, 0, 0))
- v_message (msgid, ap);
-
- VA_CLOSE (ap);
-}
-
-/* Print a warning at a specific location. */
-void
-cpp_warning_with_line VPARAMS ((cpp_reader * pfile, int line, int column,
- const char *msgid, ...))
-{
- VA_OPEN (ap, msgid);
- VA_FIXEDARG (ap, cpp_reader *, pfile);
- VA_FIXEDARG (ap, int, line);
- VA_FIXEDARG (ap, int, column);
- VA_FIXEDARG (ap, const char *, msgid);
-
- if (_cpp_begin_message (pfile, WARNING, line, column))
- v_message (msgid, ap);
-
- VA_CLOSE (ap);
-}
-
-/* Pedwarn at the location of the previously lexed token. */
-void
-cpp_pedwarn VPARAMS ((cpp_reader * pfile, const char *msgid, ...))
-{
- VA_OPEN (ap, msgid);
- VA_FIXEDARG (ap, cpp_reader *, pfile);
- VA_FIXEDARG (ap, const char *, msgid);
+ if (pfile->buffer)
+ {
+ if (CPP_OPTION (pfile, traditional))
+ {
+ if (pfile->state.in_directive)
+ line = pfile->directive_line;
+ else
+ line = pfile->line;
+ column = 0;
+ }
+ else
+ {
+ line = pfile->cur_token[-1].line;
+ column = pfile->cur_token[-1].col;
+ }
+ }
+ else
+ line = column = 0;
- if (_cpp_begin_message (pfile, PEDWARN, 0, 0))
+ if (_cpp_begin_message (pfile, level, line, column))
v_message (msgid, ap);
VA_CLOSE (ap);
}
-/* Pedwarn at a specific location. */
+/* Print an error at a specific location. */
void
-cpp_pedwarn_with_line VPARAMS ((cpp_reader * pfile, int line, int column,
- const char *msgid, ...))
+cpp_error_with_line VPARAMS ((cpp_reader *pfile, int level,
+ unsigned int line, unsigned int column,
+ const char *msgid, ...))
{
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, cpp_reader *, pfile);
- VA_FIXEDARG (ap, int, line);
- VA_FIXEDARG (ap, int, column);
+ VA_FIXEDARG (ap, int, level);
+ VA_FIXEDARG (ap, unsigned int, line);
+ VA_FIXEDARG (ap, unsigned int, column);
VA_FIXEDARG (ap, const char *, msgid);
- if (_cpp_begin_message (pfile, PEDWARN, line, column))
+ if (_cpp_begin_message (pfile, level, line, column))
v_message (msgid, ap);
VA_CLOSE (ap);
}
-/* Print an error message not associated with the translation unit. */
-void
-cpp_notice VPARAMS ((cpp_reader *pfile, const char *msgid, ...))
-{
- VA_OPEN (ap, msgid);
- VA_FIXEDARG (ap, cpp_reader *, pfile);
- VA_FIXEDARG (ap, const char *, msgid);
-
- if (pfile->errors < CPP_FATAL_LIMIT)
- pfile->errors++;
-
- v_message (msgid, ap);
-
- VA_CLOSE (ap);
-}
-
-/* Print an error message originating from ERRNO and not associated
- with the translation unit. */
void
-cpp_notice_from_errno (pfile, name)
+cpp_errno (pfile, level, msgid)
cpp_reader *pfile;
- const char *name;
+ int level;
+ const char *msgid;
{
- if (name[0] == '\0')
- name = "stdout";
- cpp_notice (pfile, "%s: %s", name, xstrerror (errno));
+ if (msgid[0] == '\0')
+ msgid = _("stdout");
+
+ cpp_error (pfile, level, "%s: %s", msgid, xstrerror (errno));
}
diff --git a/contrib/gcc/cppexp.c b/contrib/gcc/cppexp.c
index 1d4cecc..7f576f2 100644
--- a/contrib/gcc/cppexp.c
+++ b/contrib/gcc/cppexp.c
@@ -23,197 +23,445 @@ Boston, MA 02111-1307, USA. */
#include "cpplib.h"
#include "cpphash.h"
-/* Yield nonzero if adding two numbers with A's and B's signs can yield a
- number with SUM's sign, where A, B, and SUM are all C integers. */
-#define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0)
-
-static void integer_overflow PARAMS ((cpp_reader *));
-static HOST_WIDEST_INT left_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT,
- unsigned int,
- unsigned HOST_WIDEST_INT));
-static HOST_WIDEST_INT right_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT,
- unsigned int,
- unsigned HOST_WIDEST_INT));
-static struct op parse_number PARAMS ((cpp_reader *, const cpp_token *));
-static struct op parse_defined PARAMS ((cpp_reader *));
-static struct op lex PARAMS ((cpp_reader *, int));
-static const unsigned char *op_as_text PARAMS ((cpp_reader *, enum cpp_ttype));
+#define PART_PRECISION (sizeof (cpp_num_part) * CHAR_BIT)
+#define HALF_MASK (~(cpp_num_part) 0 >> (PART_PRECISION / 2))
+#define LOW_PART(num_part) (num_part & HALF_MASK)
+#define HIGH_PART(num_part) (num_part >> (PART_PRECISION / 2))
struct op
{
+ const cpp_token *token; /* The token forming op (for diagnostics). */
+ cpp_num value; /* The value logically "right" of op. */
enum cpp_ttype op;
- U_CHAR prio; /* Priority of op. */
- U_CHAR flags;
- U_CHAR unsignedp; /* True if value should be treated as unsigned. */
- HOST_WIDEST_INT value; /* The value logically "right" of op. */
};
-/* There is no "error" token, but we can't get comments in #if, so we can
- abuse that token type. */
-#define CPP_ERROR CPP_COMMENT
+/* Some simple utility routines on double integers. */
+#define num_zerop(num) ((num.low | num.high) == 0)
+#define num_eq(num1, num2) (num1.low == num2.low && num1.high == num2.high)
+static bool num_positive PARAMS ((cpp_num, size_t));
+static bool num_greater_eq PARAMS ((cpp_num, cpp_num, size_t));
+static cpp_num num_trim PARAMS ((cpp_num, size_t));
+static cpp_num num_part_mul PARAMS ((cpp_num_part, cpp_num_part));
+
+static cpp_num num_unary_op PARAMS ((cpp_reader *, cpp_num, enum cpp_ttype));
+static cpp_num num_binary_op PARAMS ((cpp_reader *, cpp_num, cpp_num,
+ enum cpp_ttype));
+static cpp_num num_negate PARAMS ((cpp_num, size_t));
+static cpp_num num_bitwise_op PARAMS ((cpp_reader *, cpp_num, cpp_num,
+ enum cpp_ttype));
+static cpp_num num_inequality_op PARAMS ((cpp_reader *, cpp_num, cpp_num,
+ enum cpp_ttype));
+static cpp_num num_equality_op PARAMS ((cpp_reader *, cpp_num, cpp_num,
+ enum cpp_ttype));
+static cpp_num num_mul PARAMS ((cpp_reader *, cpp_num, cpp_num));
+static cpp_num num_div_op PARAMS ((cpp_reader *, cpp_num, cpp_num,
+ enum cpp_ttype));
+static cpp_num num_lshift PARAMS ((cpp_num, size_t, size_t));
+static cpp_num num_rshift PARAMS ((cpp_num, size_t, size_t));
+
+static cpp_num append_digit PARAMS ((cpp_num, int, int, size_t));
+static cpp_num parse_defined PARAMS ((cpp_reader *));
+static cpp_num eval_token PARAMS ((cpp_reader *, const cpp_token *));
+static struct op *reduce PARAMS ((cpp_reader *, struct op *, enum cpp_ttype));
+static unsigned int interpret_float_suffix PARAMS ((const uchar *, size_t));
+static unsigned int interpret_int_suffix PARAMS ((const uchar *, size_t));
+static void check_promotion PARAMS ((cpp_reader *, const struct op *));
+
+/* Token type abuse to create unary plus and minus operators. */
+#define CPP_UPLUS (CPP_LAST_CPP_OP + 1)
+#define CPP_UMINUS (CPP_LAST_CPP_OP + 2)
/* With -O2, gcc appears to produce nice code, moving the error
message load and subsequent jump completely out of the main path. */
-#define CPP_ICE(msgid) \
- do { cpp_ice (pfile, msgid); goto syntax_error; } while(0)
#define SYNTAX_ERROR(msgid) \
- do { cpp_error (pfile, msgid); goto syntax_error; } while(0)
+ do { cpp_error (pfile, DL_ERROR, msgid); goto syntax_error; } while(0)
#define SYNTAX_ERROR2(msgid, arg) \
- do { cpp_error (pfile, msgid, arg); goto syntax_error; } while(0)
+ do { cpp_error (pfile, DL_ERROR, msgid, arg); goto syntax_error; } while(0)
+
+/* Subroutine of cpp_classify_number. S points to a float suffix of
+ length LEN, possibly zero. Returns 0 for an invalid suffix, or a
+ flag vector describing the suffix. */
+static unsigned int
+interpret_float_suffix (s, len)
+ const uchar *s;
+ size_t len;
+{
+ size_t f = 0, l = 0, i = 0;
+
+ while (len--)
+ switch (s[len])
+ {
+ case 'f': case 'F': f++; break;
+ case 'l': case 'L': l++; break;
+ case 'i': case 'I':
+ case 'j': case 'J': i++; break;
+ default:
+ return 0;
+ }
+
+ if (f + l > 1 || i > 1)
+ return 0;
+
+ return ((i ? CPP_N_IMAGINARY : 0)
+ | (f ? CPP_N_SMALL :
+ l ? CPP_N_LARGE : CPP_N_MEDIUM));
+}
-struct suffix
+/* Subroutine of cpp_classify_number. S points to an integer suffix
+ of length LEN, possibly zero. Returns 0 for an invalid suffix, or a
+ flag vector describing the suffix. */
+static unsigned int
+interpret_int_suffix (s, len)
+ const uchar *s;
+ size_t len;
{
- const unsigned char s[4];
- const unsigned char u;
- const unsigned char l;
-};
+ size_t u, l, i;
-static const struct suffix vsuf_1[] = {
- { "u", 1, 0 }, { "U", 1, 0 },
- { "l", 0, 1 }, { "L", 0, 1 }
-};
+ u = l = i = 0;
-static const struct suffix vsuf_2[] = {
- { "ul", 1, 1 }, { "UL", 1, 1 }, { "uL", 1, 1 }, { "Ul", 1, 1 },
- { "lu", 1, 1 }, { "LU", 1, 1 }, { "Lu", 1, 1 }, { "lU", 1, 1 },
- { "ll", 0, 2 }, { "LL", 0, 2 }
-};
+ while (len--)
+ switch (s[len])
+ {
+ case 'u': case 'U': u++; break;
+ case 'i': case 'I':
+ case 'j': case 'J': i++; break;
+ case 'l': case 'L': l++;
+ /* If there are two Ls, they must be adjacent and the same case. */
+ if (l == 2 && s[len] != s[len + 1])
+ return 0;
+ break;
+ default:
+ return 0;
+ }
-static const struct suffix vsuf_3[] = {
- { "ull", 1, 2 }, { "ULL", 1, 2 }, { "uLL", 1, 2 }, { "Ull", 1, 2 },
- { "llu", 1, 2 }, { "LLU", 1, 2 }, { "LLu", 1, 2 }, { "llU", 1, 2 }
-};
-#define Nsuff(tab) (sizeof tab / sizeof (struct suffix))
+ if (l > 2 || u > 1 || i > 1)
+ return 0;
-/* Parse and convert what is presumably an integer in TOK. Accepts
- decimal, hex, or octal with or without size suffixes. Returned op
- is CPP_ERROR on error, otherwise it is a CPP_NUMBER. */
-static struct op
-parse_number (pfile, tok)
+ return ((i ? CPP_N_IMAGINARY : 0)
+ | (u ? CPP_N_UNSIGNED : 0)
+ | ((l == 0) ? CPP_N_SMALL
+ : (l == 1) ? CPP_N_MEDIUM : CPP_N_LARGE));
+}
+
+/* Categorize numeric constants according to their field (integer,
+ floating point, or invalid), radix (decimal, octal, hexadecimal),
+ and type suffixes. */
+unsigned int
+cpp_classify_number (pfile, token)
cpp_reader *pfile;
- const cpp_token *tok;
+ const cpp_token *token;
{
- struct op op;
- const U_CHAR *start = tok->val.str.text;
- const U_CHAR *end = start + tok->val.str.len;
- const U_CHAR *p = start;
- int c = 0, i, nsuff;
- unsigned HOST_WIDEST_INT n = 0, nd, MAX_over_base;
- int base = 10;
- int overflow = 0;
- int digit, largest_digit = 0;
- const struct suffix *sufftab;
+ const uchar *str = token->val.str.text;
+ const uchar *limit;
+ unsigned int max_digit, result, radix;
+ enum {NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON} float_flag;
+
+ /* If the lexer has done its job, length one can only be a single
+ digit. Fast-path this very common case. */
+ if (token->val.str.len == 1)
+ return CPP_N_INTEGER | CPP_N_SMALL | CPP_N_DECIMAL;
+
+ limit = str + token->val.str.len;
+ float_flag = NOT_FLOAT;
+ max_digit = 0;
+ radix = 10;
+
+ /* First, interpret the radix. */
+ if (*str == '0')
+ {
+ radix = 8;
+ str++;
- op.unsignedp = 0;
+ /* Require at least one hex digit to classify it as hex. */
+ if ((*str == 'x' || *str == 'X') && ISXDIGIT (str[1]))
+ {
+ radix = 16;
+ str++;
+ }
+ }
- if (p[0] == '0')
+ /* Now scan for a well-formed integer or float. */
+ for (;;)
{
- if (end - start >= 3 && (p[1] == 'x' || p[1] == 'X'))
+ unsigned int c = *str++;
+
+ if (ISDIGIT (c) || (ISXDIGIT (c) && radix == 16))
{
- p += 2;
- base = 16;
+ c = hex_value (c);
+ if (c > max_digit)
+ max_digit = c;
+ }
+ else if (c == '.')
+ {
+ if (float_flag == NOT_FLOAT)
+ float_flag = AFTER_POINT;
+ else
+ SYNTAX_ERROR ("too many decimal points in number");
+ }
+ else if ((radix <= 10 && (c == 'e' || c == 'E'))
+ || (radix == 16 && (c == 'p' || c == 'P')))
+ {
+ float_flag = AFTER_EXPON;
+ break;
}
else
{
- p += 1;
- base = 8;
+ /* Start of suffix. */
+ str--;
+ break;
}
}
- /* Some buggy compilers (e.g. MPW C) seem to need both casts. */
- MAX_over_base = (((unsigned HOST_WIDEST_INT) -1)
- / ((unsigned HOST_WIDEST_INT) base));
+ if (float_flag != NOT_FLOAT && radix == 8)
+ radix = 10;
- for(; p < end; p++)
+ if (max_digit >= radix)
+ SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit);
+
+ if (float_flag != NOT_FLOAT)
{
- c = *p;
+ if (radix == 16 && CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, c99))
+ cpp_error (pfile, DL_PEDWARN,
+ "use of C99 hexadecimal floating constant");
- if (ISDIGIT (c)
- || (base == 16 && ISXDIGIT (c)))
- digit = hex_value (c);
- else
- break;
+ if (float_flag == AFTER_EXPON)
+ {
+ if (*str == '+' || *str == '-')
+ str++;
- if (largest_digit < digit)
- largest_digit = digit;
- nd = n * base + digit;
- overflow |= MAX_over_base < n || nd < n;
- n = nd;
- }
-
- if (p < end)
- {
- /* Check for a floating point constant. Note that float constants
- with an exponent or suffix but no decimal point are technically
- invalid (C99 6.4.4.2) but accepted elsewhere. */
- if ((c == '.' || c == 'F' || c == 'f')
- || (base == 10 && (c == 'E' || c == 'e')
- && p+1 < end && (p[1] == '+' || p[1] == '-'))
- || (base == 16 && (c == 'P' || c == 'p')
- && p+1 < end && (p[1] == '+' || p[1] == '-')))
- SYNTAX_ERROR ("floating point numbers are not valid in #if");
-
- /* Determine the suffix. l means long, and u means unsigned.
- See the suffix tables, above. */
- switch (end - p)
- {
- case 1: sufftab = vsuf_1; nsuff = Nsuff(vsuf_1); break;
- case 2: sufftab = vsuf_2; nsuff = Nsuff(vsuf_2); break;
- case 3: sufftab = vsuf_3; nsuff = Nsuff(vsuf_3); break;
- default: goto invalid_suffix;
- }
-
- for (i = 0; i < nsuff; i++)
- if (memcmp (p, sufftab[i].s, end - p) == 0)
- break;
- if (i == nsuff)
- goto invalid_suffix;
- op.unsignedp = sufftab[i].u;
+ /* Exponent is decimal, even if string is a hex float. */
+ if (!ISDIGIT (*str))
+ SYNTAX_ERROR ("exponent has no digits");
+
+ do
+ str++;
+ while (ISDIGIT (*str));
+ }
+ else if (radix == 16)
+ SYNTAX_ERROR ("hexadecimal floating constants require an exponent");
+
+ result = interpret_float_suffix (str, limit - str);
+ if (result == 0)
+ {
+ cpp_error (pfile, DL_ERROR,
+ "invalid suffix \"%.*s\" on floating constant",
+ (int) (limit - str), str);
+ return CPP_N_INVALID;
+ }
- if (CPP_WTRADITIONAL (pfile)
- && sufftab[i].u
+ /* Traditional C didn't accept any floating suffixes. */
+ if (limit != str
+ && CPP_WTRADITIONAL (pfile)
&& ! cpp_sys_macro_p (pfile))
- cpp_warning (pfile, "traditional C rejects the `U' suffix");
- if (sufftab[i].l == 2 && CPP_OPTION (pfile, pedantic)
- && ! CPP_OPTION (pfile, c99))
- cpp_pedwarn (pfile, "too many 'l' suffixes in integer constant");
+ cpp_error (pfile, DL_WARNING,
+ "traditional C rejects the \"%.*s\" suffix",
+ (int) (limit - str), str);
+
+ result |= CPP_N_FLOATING;
}
-
- if (base <= largest_digit)
- cpp_pedwarn (pfile, "integer constant contains digits beyond the radix");
+ else
+ {
+ result = interpret_int_suffix (str, limit - str);
+ if (result == 0)
+ {
+ cpp_error (pfile, DL_ERROR,
+ "invalid suffix \"%.*s\" on integer constant",
+ (int) (limit - str), str);
+ return CPP_N_INVALID;
+ }
- if (overflow)
- cpp_pedwarn (pfile, "integer constant out of range");
+ /* Traditional C only accepted the 'L' suffix.
+ Suppress warning about 'LL' with -Wno-long-long. */
+ if (CPP_WTRADITIONAL (pfile) && ! cpp_sys_macro_p (pfile))
+ {
+ int u_or_i = (result & (CPP_N_UNSIGNED|CPP_N_IMAGINARY));
+ int large = (result & CPP_N_WIDTH) == CPP_N_LARGE;
- /* If too big to be signed, consider it unsigned. */
- else if ((HOST_WIDEST_INT) n < 0 && ! op.unsignedp)
- {
- if (base == 10)
- cpp_warning (pfile, "integer constant is so large that it is unsigned");
- op.unsignedp = 1;
+ if (u_or_i || (large && CPP_OPTION (pfile, warn_long_long)))
+ cpp_error (pfile, DL_WARNING,
+ "traditional C rejects the \"%.*s\" suffix",
+ (int) (limit - str), str);
+ }
+
+ if ((result & CPP_N_WIDTH) == CPP_N_LARGE
+ && ! CPP_OPTION (pfile, c99)
+ && CPP_OPTION (pfile, warn_long_long))
+ cpp_error (pfile, DL_PEDWARN, "use of C99 long long integer constant");
+
+ result |= CPP_N_INTEGER;
}
- op.value = n;
- op.op = CPP_NUMBER;
- return op;
+ if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
+ cpp_error (pfile, DL_PEDWARN, "imaginary constants are a GCC extension");
+
+ if (radix == 10)
+ result |= CPP_N_DECIMAL;
+ else if (radix == 16)
+ result |= CPP_N_HEX;
+ else
+ result |= CPP_N_OCTAL;
+
+ return result;
- invalid_suffix:
- cpp_error (pfile, "invalid suffix '%.*s' on integer constant",
- (int) (end - p), p);
syntax_error:
- op.op = CPP_ERROR;
- return op;
+ return CPP_N_INVALID;
+}
+
+/* cpp_interpret_integer converts an integer constant into a cpp_num,
+ of precision options->precision.
+
+ We do not provide any interface for decimal->float conversion,
+ because the preprocessor doesn't need it and the floating point
+ handling in GCC proper is too ugly to speak of. */
+cpp_num
+cpp_interpret_integer (pfile, token, type)
+ cpp_reader *pfile;
+ const cpp_token *token;
+ unsigned int type;
+{
+ const uchar *p, *end;
+ cpp_num result;
+
+ result.low = 0;
+ result.high = 0;
+ result.unsignedp = !!(type & CPP_N_UNSIGNED);
+ result.overflow = false;
+
+ p = token->val.str.text;
+ end = p + token->val.str.len;
+
+ /* Common case of a single digit. */
+ if (token->val.str.len == 1)
+ result.low = p[0] - '0';
+ else
+ {
+ cpp_num_part max;
+ size_t precision = CPP_OPTION (pfile, precision);
+ unsigned int base = 10, c = 0;
+ bool overflow = false;
+
+ if ((type & CPP_N_RADIX) == CPP_N_OCTAL)
+ {
+ base = 8;
+ p++;
+ }
+ else if ((type & CPP_N_RADIX) == CPP_N_HEX)
+ {
+ base = 16;
+ p += 2;
+ }
+
+ /* We can add a digit to numbers strictly less than this without
+ needing the precision and slowness of double integers. */
+ max = ~(cpp_num_part) 0;
+ if (precision < PART_PRECISION)
+ max >>= PART_PRECISION - precision;
+ max = (max - base + 1) / base + 1;
+
+ for (; p < end; p++)
+ {
+ c = *p;
+
+ if (ISDIGIT (c) || (base == 16 && ISXDIGIT (c)))
+ c = hex_value (c);
+ else
+ break;
+
+ /* Strict inequality for when max is set to zero. */
+ if (result.low < max)
+ result.low = result.low * base + c;
+ else
+ {
+ result = append_digit (result, c, base, precision);
+ overflow |= result.overflow;
+ max = 0;
+ }
+ }
+
+ if (overflow)
+ cpp_error (pfile, DL_PEDWARN,
+ "integer constant is too large for its type");
+ /* If too big to be signed, consider it unsigned. Only warn for
+ decimal numbers. Traditional numbers were always signed (but
+ we still honor an explicit U suffix); but we only have
+ traditional semantics in directives. */
+ else if (!result.unsignedp
+ && !(CPP_OPTION (pfile, traditional)
+ && pfile->state.in_directive)
+ && !num_positive (result, precision))
+ {
+ if (base == 10)
+ cpp_error (pfile, DL_WARNING,
+ "integer constant is so large that it is unsigned");
+ result.unsignedp = true;
+ }
+ }
+
+ return result;
+}
+
+/* Append DIGIT to NUM, a number of PRECISION bits being read in base
+ BASE. */
+static cpp_num
+append_digit (num, digit, base, precision)
+ cpp_num num;
+ int digit, base;
+ size_t precision;
+{
+ cpp_num result;
+ unsigned int shift = 3 + (base == 16);
+ bool overflow;
+ cpp_num_part add_high, add_low;
+
+ /* Multiply by 8 or 16. Catching this overflow here means we don't
+ need to worry about add_high overflowing. */
+ overflow = !!(num.high >> (PART_PRECISION - shift));
+ result.high = num.high << shift;
+ result.low = num.low << shift;
+ result.high |= num.low >> (PART_PRECISION - shift);
+
+ if (base == 10)
+ {
+ add_low = num.low << 1;
+ add_high = (num.high << 1) + (num.low >> (PART_PRECISION - 1));
+ }
+ else
+ add_high = add_low = 0;
+
+ if (add_low + digit < add_low)
+ add_high++;
+ add_low += digit;
+
+ if (result.low + add_low < result.low)
+ add_high++;
+ if (result.high + add_high < result.high)
+ overflow = true;
+
+ result.low += add_low;
+ result.high += add_high;
+
+ /* The above code catches overflow of a cpp_num type. This catches
+ overflow of the (possibly shorter) target precision. */
+ num.low = result.low;
+ num.high = result.high;
+ result = num_trim (result, precision);
+ if (!num_eq (result, num))
+ overflow = true;
+
+ result.unsignedp = num.unsignedp;
+ result.overflow = overflow;
+ return result;
}
/* Handle meeting "defined" in a preprocessor expression. */
-static struct op
+static cpp_num
parse_defined (pfile)
cpp_reader *pfile;
{
+ cpp_num result;
int paren = 0;
cpp_hashnode *node = 0;
const cpp_token *token;
- struct op op;
cpp_context *initial_context = pfile->context;
/* Don't expand macros. */
@@ -231,36 +479,34 @@ parse_defined (pfile)
node = token->val.node;
if (paren && cpp_get_token (pfile)->type != CPP_CLOSE_PAREN)
{
- cpp_error (pfile, "missing ')' after \"defined\"");
+ cpp_error (pfile, DL_ERROR, "missing ')' after \"defined\"");
node = 0;
}
}
else
{
- cpp_error (pfile, "operator \"defined\" requires an identifier");
+ cpp_error (pfile, DL_ERROR,
+ "operator \"defined\" requires an identifier");
if (token->flags & NAMED_OP)
{
cpp_token op;
op.flags = 0;
op.type = token->type;
- cpp_error (pfile,
+ cpp_error (pfile, DL_ERROR,
"(\"%s\" is an alternative token for \"%s\" in C++)",
cpp_token_as_text (pfile, token),
cpp_token_as_text (pfile, &op));
}
}
- if (!node)
- op.op = CPP_ERROR;
- else
+ if (node)
{
if (pfile->context != initial_context)
- cpp_warning (pfile, "this use of \"defined\" may not be portable");
+ cpp_error (pfile, DL_WARNING,
+ "this use of \"defined\" may not be portable");
- op.value = node->type == NT_MACRO;
- op.unsignedp = 0;
- op.op = CPP_NUMBER;
+ _cpp_mark_macro_used (node);
/* A possible controlling macro of the form #if !defined ().
_cpp_parse_expr checks there was no other junk on the line. */
@@ -268,49 +514,69 @@ parse_defined (pfile)
}
pfile->state.prevent_expansion--;
- return op;
+
+ result.unsignedp = false;
+ result.high = 0;
+ result.overflow = false;
+ result.low = node && node->type == NT_MACRO;
+ return result;
}
-/* Read a token. The returned type is CPP_NUMBER for a valid number
- (an interpreted preprocessing number or character constant, or the
- result of the "defined" or "#" operators), CPP_ERROR on error,
- CPP_EOF, or the type of an operator token. */
-static struct op
-lex (pfile, skip_evaluation)
+/* Convert a token into a CPP_NUMBER (an interpreted preprocessing
+ number or character constant, or the result of the "defined" or "#"
+ operators). */
+static cpp_num
+eval_token (pfile, token)
cpp_reader *pfile;
- int skip_evaluation;
+ const cpp_token *token;
{
- struct op op;
- const cpp_token *token = cpp_get_token (pfile);
+ cpp_num result;
+ unsigned int temp;
+ int unsignedp = 0;
switch (token->type)
{
case CPP_NUMBER:
- return parse_number (pfile, token);
+ temp = cpp_classify_number (pfile, token);
+ switch (temp & CPP_N_CATEGORY)
+ {
+ case CPP_N_FLOATING:
+ cpp_error (pfile, DL_ERROR,
+ "floating constant in preprocessor expression");
+ break;
+ case CPP_N_INTEGER:
+ if (!(temp & CPP_N_IMAGINARY))
+ return cpp_interpret_integer (pfile, token, temp);
+ cpp_error (pfile, DL_ERROR,
+ "imaginary number in preprocessor expression");
+ break;
+
+ case CPP_N_INVALID:
+ /* Error already issued. */
+ break;
+ }
+ result.high = result.low = 0;
+ break;
- case CPP_CHAR:
case CPP_WCHAR:
+ case CPP_CHAR:
{
- unsigned int chars_seen;
-
- if (token->type == CPP_CHAR)
- op.unsignedp = 0;
- else
- op.unsignedp = WCHAR_UNSIGNED;
- op.op = CPP_NUMBER;
- op.value = cpp_interpret_charconst (pfile, token, 1, 0, &chars_seen);
- return op;
- }
-
- case CPP_STRING:
- case CPP_WSTRING:
- SYNTAX_ERROR ("string constants are not valid in #if");
+ cppchar_t cc = cpp_interpret_charconst (pfile, token,
+ &temp, &unsignedp);
- case CPP_OTHER:
- if (ISGRAPH (token->val.c))
- SYNTAX_ERROR2 ("invalid character '%c' in #if", token->val.c);
- else
- SYNTAX_ERROR2 ("invalid character '\\%03o' in #if", token->val.c);
+ result.high = 0;
+ result.low = cc;
+ /* Sign-extend the result if necessary. */
+ if (!unsignedp && (cppchar_signed_t) cc < 0)
+ {
+ if (PART_PRECISION > BITS_PER_CPPCHAR_T)
+ result.low |= ~(~(cpp_num_part) 0
+ >> (PART_PRECISION - BITS_PER_CPPCHAR_T));
+ result.high = ~(cpp_num_part) 0;
+ result = num_trim (result, CPP_OPTION (pfile, precision));
+ }
+ }
+ break;
case CPP_NAME:
if (token->val.node == pfile->spec_nodes.n_defined)
@@ -319,571 +585,1021 @@ lex (pfile, skip_evaluation)
&& (token->val.node == pfile->spec_nodes.n_true
|| token->val.node == pfile->spec_nodes.n_false))
{
- op.op = CPP_NUMBER;
- op.unsignedp = 0;
- op.value = (token->val.node == pfile->spec_nodes.n_true);
+ result.high = 0;
+ result.low = (token->val.node == pfile->spec_nodes.n_true);
/* Warn about use of true or false in #if when pedantic
and stdbool.h has not been included. */
if (CPP_PEDANTIC (pfile)
&& ! cpp_defined (pfile, DSC("__bool_true_false_are_defined")))
- cpp_pedwarn (pfile, "ISO C++ does not permit \"%s\" in #if",
- NODE_NAME (token->val.node));
- return op;
+ cpp_error (pfile, DL_PEDWARN,
+ "ISO C++ does not permit \"%s\" in #if",
+ NODE_NAME (token->val.node));
}
else
{
- op.op = CPP_NUMBER;
- op.unsignedp = 0;
- op.value = 0;
-
- if (CPP_OPTION (pfile, warn_undef) && !skip_evaluation)
- cpp_warning (pfile, "\"%s\" is not defined",
- NODE_NAME (token->val.node));
- return op;
- }
-
- case CPP_HASH:
- {
- int temp;
-
- op.op = CPP_NUMBER;
- if (_cpp_test_assertion (pfile, &temp))
- op.op = CPP_ERROR;
- op.unsignedp = 0;
- op.value = temp;
- return op;
- }
-
- default:
- if (((int) token->type > (int) CPP_EQ
- && (int) token->type < (int) CPP_PLUS_EQ)
- || token->type == CPP_EOF)
- {
- op.op = token->type;
- return op;
+ result.high = 0;
+ result.low = 0;
+ if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval)
+ cpp_error (pfile, DL_WARNING, "\"%s\" is not defined",
+ NODE_NAME (token->val.node));
}
+ break;
- SYNTAX_ERROR2 ("\"%s\" is not valid in #if expressions",
- cpp_token_as_text (pfile, token));
- }
-
- syntax_error:
- op.op = CPP_ERROR;
- return op;
-}
-
-/* Warn if appropriate on overflow. */
-static void
-integer_overflow (pfile)
- cpp_reader *pfile;
-{
- if (CPP_PEDANTIC (pfile))
- cpp_pedwarn (pfile, "integer overflow in preprocessor expression");
-}
-
-/* Handle shifting A left by B bits. UNSIGNEDP is non-zero if A is
- unsigned. */
-static HOST_WIDEST_INT
-left_shift (pfile, a, unsignedp, b)
- cpp_reader *pfile;
- HOST_WIDEST_INT a;
- unsigned int unsignedp;
- unsigned HOST_WIDEST_INT b;
-{
- if (b >= HOST_BITS_PER_WIDEST_INT)
- {
- if (! unsignedp && a != 0)
- integer_overflow (pfile);
- return 0;
+ default: /* CPP_HASH */
+ _cpp_test_assertion (pfile, &temp);
+ result.high = 0;
+ result.low = temp;
}
- else if (unsignedp)
- return (unsigned HOST_WIDEST_INT) a << b;
- else
- {
- HOST_WIDEST_INT l = a << b;
- if (l >> b != a)
- integer_overflow (pfile);
- return l;
- }
-}
-/* Handle shifting A right by B bits. UNSIGNEDP is non-zero if A is
- unsigned. */
-static HOST_WIDEST_INT
-right_shift (pfile, a, unsignedp, b)
- cpp_reader *pfile ATTRIBUTE_UNUSED;
- HOST_WIDEST_INT a;
- unsigned int unsignedp;
- unsigned HOST_WIDEST_INT b;
-{
- if (b >= HOST_BITS_PER_WIDEST_INT)
- return unsignedp ? 0 : a >> (HOST_BITS_PER_WIDEST_INT - 1);
- else if (unsignedp)
- return (unsigned HOST_WIDEST_INT) a >> b;
- else
- return a >> b;
+ result.unsignedp = !!unsignedp;
+ result.overflow = false;
+ return result;
}
/* Operator precedence and flags table.
After an operator is returned from the lexer, if it has priority less
-than or equal to the operator on the top of the stack, we reduce the
-stack by one operator and repeat the test. Since equal priorities
-reduce, this is naturally left-associative.
-
-We handle right-associative operators by clearing the lower bit of all
-left-associative operators, and setting it for right-associative ones.
-After the reduction phase of a new operator, just before it is pushed
-onto the stack, its RIGHT_ASSOC bit is cleared. The effect is that
-during the reduction phase, the current right-associative operator has
-a priority one greater than any other operator of otherwise equal
-precedence that has been pushed on the top of the stack. This avoids
-a reduction pass, and effectively makes the logic right-associative.
+than the operator on the top of the stack, we reduce the stack by one
+operator and repeat the test. Since equal priorities do not reduce,
+this is naturally right-associative.
+
+We handle left-associative operators by decrementing the priority of
+just-lexed operators by one, but retaining the priority of operators
+already on the stack.
The remaining cases are '(' and ')'. We handle '(' by skipping the
reduction phase completely. ')' is given lower priority than
everything else, including '(', effectively forcing a reduction of the
-parenthesised expression. If there is no matching '(', the stack will
-be reduced all the way to the beginning, exiting the parser in the
-same way as the ultra-low priority end-of-expression dummy operator.
-The exit code checks to see if the operator that caused it is ')', and
-if so outputs an appropriate error message.
-
-The parser assumes all shifted operators require a right operand
-unless the flag NO_R_OPERAND is set, and similarly for NO_L_OPERAND.
-These semantics are automatically checked, any extra semantics need to
-be handled with operator-specific code. */
-
-#define FLAG_BITS 8
-#define FLAG_MASK ((1 << FLAG_BITS) - 1)
-#define PRIO_SHIFT (FLAG_BITS + 1)
-#define EXTRACT_PRIO(CNST) ((CNST) >> FLAG_BITS)
-#define EXTRACT_FLAGS(CNST) ((CNST) & FLAG_MASK)
-
-/* Flags. */
-#define HAVE_VALUE (1 << 0)
-#define NO_L_OPERAND (1 << 1)
-#define NO_R_OPERAND (1 << 2)
-#define SHORT_CIRCUIT (1 << 3)
-
-/* Priority and flag combinations. */
-#define RIGHT_ASSOC (1 << FLAG_BITS)
-#define FORCE_REDUCE_PRIO (0 << PRIO_SHIFT)
-#define CLOSE_PAREN_PRIO (1 << PRIO_SHIFT)
-#define OPEN_PAREN_PRIO ((2 << PRIO_SHIFT) | NO_L_OPERAND)
-#define COMMA_PRIO (3 << PRIO_SHIFT)
-#define COND_PRIO ((4 << PRIO_SHIFT) | RIGHT_ASSOC | SHORT_CIRCUIT)
-#define COLON_PRIO ((5 << PRIO_SHIFT) | SHORT_CIRCUIT)
-#define OROR_PRIO ((6 << PRIO_SHIFT) | SHORT_CIRCUIT)
-#define ANDAND_PRIO ((7 << PRIO_SHIFT) | SHORT_CIRCUIT)
-#define OR_PRIO (8 << PRIO_SHIFT)
-#define XOR_PRIO (9 << PRIO_SHIFT)
-#define AND_PRIO (10 << PRIO_SHIFT)
-#define MINMAX_PRIO (11 << PRIO_SHIFT)
-#define EQUAL_PRIO (12 << PRIO_SHIFT)
-#define LESS_PRIO (13 << PRIO_SHIFT)
-#define SHIFT_PRIO (14 << PRIO_SHIFT)
-#define PLUS_PRIO (15 << PRIO_SHIFT)
-#define MUL_PRIO (16 << PRIO_SHIFT)
-#define UNARY_PRIO ((17 << PRIO_SHIFT) | RIGHT_ASSOC | NO_L_OPERAND)
+parenthesised expression. If there is a matching '(', the routine
+reduce() exits immediately. If the normal exit route sees a ')', then
+there cannot have been a matching '(' and an error message is output.
+
+The parser assumes all shifted operators require a left operand unless
+the flag NO_L_OPERAND is set. These semantics are automatic; any
+extra semantics need to be handled with operator-specific code. */
+
+/* Flags. If CHECK_PROMOTION, we warn if the effective sign of an
+ operand changes because of integer promotions. */
+#define NO_L_OPERAND (1 << 0)
+#define LEFT_ASSOC (1 << 1)
+#define CHECK_PROMOTION (1 << 2)
/* Operator to priority map. Must be in the same order as the first
N entries of enum cpp_ttype. */
-static const short
-op_to_prio[] =
+static const struct operator
{
- /* EQ */ 0, /* dummy entry - can't happen */
- /* NOT */ UNARY_PRIO,
- /* GREATER */ LESS_PRIO,
- /* LESS */ LESS_PRIO,
- /* PLUS */ UNARY_PRIO, /* note these two can be unary */
- /* MINUS */ UNARY_PRIO, /* or binary */
- /* MULT */ MUL_PRIO,
- /* DIV */ MUL_PRIO,
- /* MOD */ MUL_PRIO,
- /* AND */ AND_PRIO,
- /* OR */ OR_PRIO,
- /* XOR */ XOR_PRIO,
- /* RSHIFT */ SHIFT_PRIO,
- /* LSHIFT */ SHIFT_PRIO,
- /* MIN */ MINMAX_PRIO, /* C++ specific */
- /* MAX */ MINMAX_PRIO, /* extensions */
-
- /* COMPL */ UNARY_PRIO,
- /* AND_AND */ ANDAND_PRIO,
- /* OR_OR */ OROR_PRIO,
- /* QUERY */ COND_PRIO,
- /* COLON */ COLON_PRIO,
- /* COMMA */ COMMA_PRIO,
- /* OPEN_PAREN */ OPEN_PAREN_PRIO,
- /* CLOSE_PAREN */ CLOSE_PAREN_PRIO,
- /* EQ_EQ */ EQUAL_PRIO,
- /* NOT_EQ */ EQUAL_PRIO,
- /* GREATER_EQ */ LESS_PRIO,
- /* LESS_EQ */ LESS_PRIO
+ uchar prio;
+ uchar flags;
+} optab[] =
+{
+ /* EQ */ {0, 0}, /* Shouldn't happen. */
+ /* NOT */ {16, NO_L_OPERAND},
+ /* GREATER */ {12, LEFT_ASSOC | CHECK_PROMOTION},
+ /* LESS */ {12, LEFT_ASSOC | CHECK_PROMOTION},
+ /* PLUS */ {14, LEFT_ASSOC | CHECK_PROMOTION},
+ /* MINUS */ {14, LEFT_ASSOC | CHECK_PROMOTION},
+ /* MULT */ {15, LEFT_ASSOC | CHECK_PROMOTION},
+ /* DIV */ {15, LEFT_ASSOC | CHECK_PROMOTION},
+ /* MOD */ {15, LEFT_ASSOC | CHECK_PROMOTION},
+ /* AND */ {9, LEFT_ASSOC | CHECK_PROMOTION},
+ /* OR */ {7, LEFT_ASSOC | CHECK_PROMOTION},
+ /* XOR */ {8, LEFT_ASSOC | CHECK_PROMOTION},
+ /* RSHIFT */ {13, LEFT_ASSOC},
+ /* LSHIFT */ {13, LEFT_ASSOC},
+
+ /* MIN */ {10, LEFT_ASSOC | CHECK_PROMOTION},
+ /* MAX */ {10, LEFT_ASSOC | CHECK_PROMOTION},
+
+ /* COMPL */ {16, NO_L_OPERAND},
+ /* AND_AND */ {6, LEFT_ASSOC},
+ /* OR_OR */ {5, LEFT_ASSOC},
+ /* QUERY */ {3, 0},
+ /* COLON */ {4, LEFT_ASSOC | CHECK_PROMOTION},
+ /* COMMA */ {2, LEFT_ASSOC},
+ /* OPEN_PAREN */ {1, NO_L_OPERAND},
+ /* CLOSE_PAREN */ {0, 0},
+ /* EOF */ {0, 0},
+ /* EQ_EQ */ {11, LEFT_ASSOC},
+ /* NOT_EQ */ {11, LEFT_ASSOC},
+ /* GREATER_EQ */ {12, LEFT_ASSOC | CHECK_PROMOTION},
+ /* LESS_EQ */ {12, LEFT_ASSOC | CHECK_PROMOTION},
+ /* UPLUS */ {16, NO_L_OPERAND},
+ /* UMINUS */ {16, NO_L_OPERAND}
};
-#define COMPARE(OP) \
- top->unsignedp = 0; \
- top->value = (unsigned1 | unsigned2) \
- ? (unsigned HOST_WIDEST_INT) v1 OP (unsigned HOST_WIDEST_INT) v2 \
- : (v1 OP v2)
-#define EQUALITY(OP) \
- top->value = v1 OP v2; \
- top->unsignedp = 0;
-#define BITWISE(OP) \
- top->value = v1 OP v2; \
- top->unsignedp = unsigned1 | unsigned2;
-#define MINMAX(OP) \
- top->value = (v1 OP v2) ? v1 : v2; \
- top->unsignedp = unsigned1 | unsigned2;
-#define UNARY(OP) \
- top->value = OP v2; \
- top->unsignedp = unsigned2; \
- top->flags |= HAVE_VALUE;
-#define SHIFT(PSH, MSH) \
- if (skip_evaluation) \
- break; \
- top->unsignedp = unsigned1; \
- if (v2 < 0 && ! unsigned2) \
- top->value = MSH (pfile, v1, unsigned1, -v2); \
- else \
- top->value = PSH (pfile, v1, unsigned1, v2);
-
/* Parse and evaluate a C expression, reading from PFILE.
- Returns the truth value of the expression. */
-int
+ Returns the truth value of the expression.
+
+ The implementation is an operator precedence parser, i.e. a
+ bottom-up parser, using a stack for not-yet-reduced tokens.
+
+ The stack base is op_stack, and the current stack pointer is 'top'.
+ There is a stack element for each operator (only), and the most
+ recently pushed operator is 'top->op'. An operand (value) is
+ stored in the 'value' field of the stack element of the operator
+ that precedes it. */
+bool
_cpp_parse_expr (pfile)
cpp_reader *pfile;
{
- /* The implementation is an operator precedence parser, i.e. a
- bottom-up parser, using a stack for not-yet-reduced tokens.
-
- The stack base is 'stack', and the current stack pointer is 'top'.
- There is a stack element for each operator (only),
- and the most recently pushed operator is 'top->op'.
- An operand (value) is stored in the 'value' field of the stack
- element of the operator that precedes it.
- In that case the 'flags' field has the HAVE_VALUE flag set. */
-
-#define INIT_STACK_SIZE 20
- struct op init_stack[INIT_STACK_SIZE];
- struct op *stack = init_stack;
- struct op *limit = stack + INIT_STACK_SIZE;
- struct op *top = stack + 1;
- int skip_evaluation = 0;
- int result;
- unsigned int lex_count, saw_leading_not;
+ struct op *top = pfile->op_stack;
+ unsigned int lex_count;
+ bool saw_leading_not, want_value = true;
+
+ pfile->state.skip_eval = 0;
/* Set up detection of #if ! defined(). */
pfile->mi_ind_cmacro = 0;
- saw_leading_not = 0;
+ saw_leading_not = false;
lex_count = 0;
- /* We've finished when we try to reduce this. */
+ /* Lowest priority operator prevents further reductions. */
top->op = CPP_EOF;
- /* Nifty way to catch missing '('. */
- top->prio = EXTRACT_PRIO(CLOSE_PAREN_PRIO);
- /* Avoid missing right operand checks. */
- top->flags = NO_R_OPERAND;
for (;;)
{
- unsigned int prio;
- unsigned int flags;
struct op op;
- /* Read a token */
- op = lex (pfile, skip_evaluation);
lex_count++;
+ op.token = cpp_get_token (pfile);
+ op.op = op.token->type;
- /* If the token is an operand, push its value and get next
- token. If it is an operator, get its priority and flags, and
- try to reduce the expression on the stack. */
switch (op.op)
{
- case CPP_ERROR:
- goto syntax_error;
- push_immediate:
+ /* These tokens convert into values. */
case CPP_NUMBER:
- /* Push a value onto the stack. */
- if (top->flags & HAVE_VALUE)
- SYNTAX_ERROR ("missing binary operator");
- top->value = op.value;
- top->unsignedp = op.unsignedp;
- top->flags |= HAVE_VALUE;
+ case CPP_CHAR:
+ case CPP_WCHAR:
+ case CPP_NAME:
+ case CPP_HASH:
+ if (!want_value)
+ SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
+ cpp_token_as_text (pfile, op.token));
+ want_value = false;
+ top->value = eval_token (pfile, op.token);
continue;
- case CPP_EOF: prio = FORCE_REDUCE_PRIO; break;
-
case CPP_NOT:
saw_leading_not = lex_count == 1;
- prio = op_to_prio[op.op];
break;
case CPP_PLUS:
- case CPP_MINUS: prio = PLUS_PRIO; if (top->flags & HAVE_VALUE) break;
- /* else unary; fall through */
- default: prio = op_to_prio[op.op]; break;
- }
-
- /* Separate the operator's code into priority and flags. */
- flags = EXTRACT_FLAGS(prio);
- prio = EXTRACT_PRIO(prio);
- if (prio == EXTRACT_PRIO(OPEN_PAREN_PRIO))
- goto skip_reduction;
-
- /* Check for reductions. Then push the operator. */
- while (prio <= top->prio)
- {
- HOST_WIDEST_INT v1, v2;
- unsigned int unsigned1, unsigned2;
-
- /* Most operators that can appear on the stack require a
- right operand. Check this before trying to reduce. */
- if ((top->flags & (HAVE_VALUE | NO_R_OPERAND)) == 0)
+ if (want_value)
+ op.op = CPP_UPLUS;
+ break;
+ case CPP_MINUS:
+ if (want_value)
+ op.op = CPP_UMINUS;
+ break;
+ case CPP_OTHER:
+ if (ISGRAPH (op.token->val.c))
+ SYNTAX_ERROR2 ("invalid character '%c' in #if", op.token->val.c);
+ else
+ SYNTAX_ERROR2 ("invalid character '\\%03o' in #if",
+ op.token->val.c);
+
+ default:
+ if ((int) op.op <= (int) CPP_EQ || (int) op.op >= (int) CPP_PLUS_EQ)
+ SYNTAX_ERROR2 ("token \"%s\" is not valid in preprocessor expressions",
+ cpp_token_as_text (pfile, op.token));
+ break;
+ }
+
+ /* Check we have a value or operator as appropriate. */
+ if (optab[op.op].flags & NO_L_OPERAND)
+ {
+ if (!want_value)
+ SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
+ cpp_token_as_text (pfile, op.token));
+ }
+ else if (want_value)
+ {
+ /* Ordering here is subtle and intended to favor the
+ missing parenthesis diagnostics over alternatives. */
+ if (op.op == CPP_CLOSE_PAREN)
{
if (top->op == CPP_OPEN_PAREN)
SYNTAX_ERROR ("void expression between '(' and ')'");
- else
- SYNTAX_ERROR2 ("operator '%s' has no right operand",
- op_as_text (pfile, top->op));
}
+ else if (top->op == CPP_EOF)
+ SYNTAX_ERROR ("#if with no expression");
+ if (top->op != CPP_EOF && top->op != CPP_OPEN_PAREN)
+ SYNTAX_ERROR2 ("operator '%s' has no right operand",
+ cpp_token_as_text (pfile, top->token));
+ }
+
+ top = reduce (pfile, top, op.op);
+ if (!top)
+ goto syntax_error;
+
+ if (op.op == CPP_EOF)
+ break;
+
+ switch (op.op)
+ {
+ case CPP_CLOSE_PAREN:
+ continue;
+ case CPP_OR_OR:
+ if (!num_zerop (top->value))
+ pfile->state.skip_eval++;
+ break;
+ case CPP_AND_AND:
+ case CPP_QUERY:
+ if (num_zerop (top->value))
+ pfile->state.skip_eval++;
+ break;
+ case CPP_COLON:
+ if (top->op != CPP_QUERY)
+ SYNTAX_ERROR (" ':' without preceding '?'");
+ if (!num_zerop (top[-1].value)) /* Was '?' condition true? */
+ pfile->state.skip_eval++;
+ else
+ pfile->state.skip_eval--;
+ default:
+ break;
+ }
+
+ want_value = true;
+
+ /* Check for and handle stack overflow. */
+ if (++top == pfile->op_limit)
+ top = _cpp_expand_op_stack (pfile);
+
+ top->op = op.op;
+ top->token = op.token;
+ }
+
+ /* The controlling macro expression is only valid if we called lex 3
+ times: <!> <defined expression> and <EOF>. push_conditional ()
+ checks that we are at top-of-file. */
+ if (pfile->mi_ind_cmacro && !(saw_leading_not && lex_count == 3))
+ pfile->mi_ind_cmacro = 0;
+
+ if (top != pfile->op_stack)
+ {
+ cpp_error (pfile, DL_ICE, "unbalanced stack in #if");
+ syntax_error:
+ return false; /* Return false on syntax error. */
+ }
+
+ return !num_zerop (top->value);
+}
+
+/* Reduce the operator / value stack if possible, in preparation for
+ pushing operator OP. Returns NULL on error, otherwise the top of
+ the stack. */
+static struct op *
+reduce (pfile, top, op)
+ cpp_reader *pfile;
+ struct op *top;
+ enum cpp_ttype op;
+{
+ unsigned int prio;
- unsigned2 = top->unsignedp, v2 = top->value;
+ if (top->op <= CPP_EQ || top->op > CPP_LAST_CPP_OP + 2)
+ {
+ bad_op:
+ cpp_error (pfile, DL_ICE, "impossible operator '%u'", top->op);
+ return 0;
+ }
+
+ if (op == CPP_OPEN_PAREN)
+ return top;
+
+ /* Decrement the priority of left-associative operators to force a
+ reduction with operators of otherwise equal priority. */
+ prio = optab[op].prio - ((optab[op].flags & LEFT_ASSOC) != 0);
+ while (prio < optab[top->op].prio)
+ {
+ if (CPP_OPTION (pfile, warn_num_sign_change)
+ && optab[top->op].flags & CHECK_PROMOTION)
+ check_promotion (pfile, top);
+
+ switch (top->op)
+ {
+ case CPP_UPLUS:
+ case CPP_UMINUS:
+ case CPP_NOT:
+ case CPP_COMPL:
+ top[-1].value = num_unary_op (pfile, top->value, top->op);
+ break;
+
+ case CPP_PLUS:
+ case CPP_MINUS:
+ case CPP_RSHIFT:
+ case CPP_LSHIFT:
+ case CPP_MIN:
+ case CPP_MAX:
+ case CPP_COMMA:
+ top[-1].value = num_binary_op (pfile, top[-1].value,
+ top->value, top->op);
+ break;
+
+ case CPP_GREATER:
+ case CPP_LESS:
+ case CPP_GREATER_EQ:
+ case CPP_LESS_EQ:
+ top[-1].value
+ = num_inequality_op (pfile, top[-1].value, top->value, top->op);
+ break;
+
+ case CPP_EQ_EQ:
+ case CPP_NOT_EQ:
+ top[-1].value
+ = num_equality_op (pfile, top[-1].value, top->value, top->op);
+ break;
+
+ case CPP_AND:
+ case CPP_OR:
+ case CPP_XOR:
+ top[-1].value
+ = num_bitwise_op (pfile, top[-1].value, top->value, top->op);
+ break;
+
+ case CPP_MULT:
+ top[-1].value = num_mul (pfile, top[-1].value, top->value);
+ break;
+
+ case CPP_DIV:
+ case CPP_MOD:
+ top[-1].value = num_div_op (pfile, top[-1].value,
+ top->value, top->op);
+ break;
+
+ case CPP_OR_OR:
+ top--;
+ if (!num_zerop (top->value))
+ pfile->state.skip_eval--;
+ top->value.low = (!num_zerop (top->value)
+ || !num_zerop (top[1].value));
+ top->value.high = 0;
+ top->value.unsignedp = false;
+ top->value.overflow = false;
+ continue;
+
+ case CPP_AND_AND:
top--;
- unsigned1 = top->unsignedp, v1 = top->value;
+ if (num_zerop (top->value))
+ pfile->state.skip_eval--;
+ top->value.low = (!num_zerop (top->value)
+ && !num_zerop (top[1].value));
+ top->value.high = 0;
+ top->value.unsignedp = false;
+ top->value.overflow = false;
+ continue;
- /* Now set top->value = (top[1].op)(v1, v2); */
- switch (top[1].op)
+ case CPP_OPEN_PAREN:
+ if (op != CPP_CLOSE_PAREN)
{
- default:
- cpp_ice (pfile, "impossible operator '%s'",
- op_as_text (pfile, top[1].op));
- goto syntax_error;
-
- case CPP_NOT: UNARY(!); break;
- case CPP_COMPL: UNARY(~); break;
- case CPP_LESS: COMPARE(<); break;
- case CPP_GREATER: COMPARE(>); break;
- case CPP_LESS_EQ: COMPARE(<=); break;
- case CPP_GREATER_EQ: COMPARE(>=); break;
- case CPP_EQ_EQ: EQUALITY(==); break;
- case CPP_NOT_EQ: EQUALITY(!=); break;
- case CPP_AND: BITWISE(&); break;
- case CPP_XOR: BITWISE(^); break;
- case CPP_OR: BITWISE(|); break;
- case CPP_LSHIFT: SHIFT(left_shift, right_shift); break;
- case CPP_RSHIFT: SHIFT(right_shift, left_shift); break;
- case CPP_MIN: MINMAX(<); break;
- case CPP_MAX: MINMAX(>); break;
-
- case CPP_PLUS:
- if (!(top->flags & HAVE_VALUE))
- {
- /* Can't use UNARY(+) because K+R C did not have unary
- plus. Can't use UNARY() because some compilers object
- to the empty argument. */
- top->value = v2;
- top->unsignedp = unsigned2;
- top->flags |= HAVE_VALUE;
-
- if (CPP_WTRADITIONAL (pfile))
- cpp_warning (pfile,
- "traditional C rejects the unary plus operator");
- }
- else
- {
- top->value = v1 + v2;
- top->unsignedp = unsigned1 | unsigned2;
- if (! top->unsignedp && ! skip_evaluation
- && ! possible_sum_sign (v1, v2, top->value))
- integer_overflow (pfile);
- }
- break;
- case CPP_MINUS:
- if (!(top->flags & HAVE_VALUE))
- {
- UNARY(-);
- if (!skip_evaluation && (top->value & v2) < 0 && !unsigned2)
- integer_overflow (pfile);
- }
- else
- { /* Binary '-' */
- top->value = v1 - v2;
- top->unsignedp = unsigned1 | unsigned2;
- if (! top->unsignedp && ! skip_evaluation
- && ! possible_sum_sign (top->value, v2, v1))
- integer_overflow (pfile);
- }
- break;
- case CPP_MULT:
- top->unsignedp = unsigned1 | unsigned2;
- if (top->unsignedp)
- top->value = (unsigned HOST_WIDEST_INT) v1 * v2;
- else if (!skip_evaluation)
- {
- top->value = v1 * v2;
- if (v1 && (top->value / v1 != v2
- || (top->value & v1 & v2) < 0))
- integer_overflow (pfile);
- }
- break;
- case CPP_DIV:
- case CPP_MOD:
- if (skip_evaluation)
- break;
- if (v2 == 0)
- SYNTAX_ERROR ("division by zero in #if");
- top->unsignedp = unsigned1 | unsigned2;
- if (top[1].op == CPP_DIV)
- {
- if (top->unsignedp)
- top->value = (unsigned HOST_WIDEST_INT) v1 / v2;
- else
- {
- top->value = v1 / v2;
- if ((top->value & v1 & v2) < 0)
- integer_overflow (pfile);
- }
- }
- else
- {
- if (top->unsignedp)
- top->value = (unsigned HOST_WIDEST_INT) v1 % v2;
- else
- top->value = v1 % v2;
- }
- break;
-
- case CPP_OR_OR:
- top->value = v1 || v2;
- top->unsignedp = 0;
- if (v1) skip_evaluation--;
- break;
- case CPP_AND_AND:
- top->value = v1 && v2;
- top->unsignedp = 0;
- if (!v1) skip_evaluation--;
- break;
- case CPP_COMMA:
- if (CPP_PEDANTIC (pfile))
- cpp_pedwarn (pfile, "comma operator in operand of #if");
- top->value = v2;
- top->unsignedp = unsigned2;
- break;
- case CPP_QUERY:
- SYNTAX_ERROR ("syntax error '?' without following ':'");
- case CPP_COLON:
- if (top[0].op != CPP_QUERY)
- SYNTAX_ERROR ("syntax error ':' without preceding '?'");
- top--;
- if (top->value) skip_evaluation--;
- top->value = top->value ? v1 : v2;
- top->unsignedp = unsigned1 | unsigned2;
- break;
- case CPP_OPEN_PAREN:
- if (op.op != CPP_CLOSE_PAREN)
- SYNTAX_ERROR ("missing ')' in expression");
- op.value = v2;
- op.unsignedp = unsigned2;
- goto push_immediate;
- case CPP_EOF:
- /* Reducing this dummy operator indicates we've finished. */
- if (op.op == CPP_CLOSE_PAREN)
- SYNTAX_ERROR ("missing '(' in expression");
- goto done;
+ cpp_error (pfile, DL_ERROR, "missing ')' in expression");
+ return 0;
}
+ top--;
+ top->value = top[1].value;
+ return top;
+
+ case CPP_COLON:
+ top -= 2;
+ if (!num_zerop (top->value))
+ {
+ pfile->state.skip_eval--;
+ top->value = top[1].value;
+ }
+ else
+ top->value = top[2].value;
+ top->value.unsignedp = (top[1].value.unsignedp
+ || top[2].value.unsignedp);
+ continue;
+
+ case CPP_QUERY:
+ cpp_error (pfile, DL_ERROR, "'?' without following ':'");
+ return 0;
+
+ default:
+ goto bad_op;
}
- /* Handle short-circuit evaluations. */
- if (flags & SHORT_CIRCUIT)
- switch (op.op)
- {
- case CPP_OR_OR: if (top->value) skip_evaluation++; break;
- case CPP_AND_AND:
- case CPP_QUERY: if (!top->value) skip_evaluation++; break;
- case CPP_COLON:
- if (top[-1].value) /* Was '?' condition true? */
- skip_evaluation++;
- else
- skip_evaluation--;
- default:
- break;
- }
+ top--;
+ if (top->value.overflow && !pfile->state.skip_eval)
+ cpp_error (pfile, DL_PEDWARN,
+ "integer overflow in preprocessor expression");
+ }
+
+ if (op == CPP_CLOSE_PAREN)
+ {
+ cpp_error (pfile, DL_ERROR, "missing '(' in expression");
+ return 0;
+ }
+
+ return top;
+}
+
+/* Returns the position of the old top of stack after expansion. */
+struct op *
+_cpp_expand_op_stack (pfile)
+ cpp_reader *pfile;
+{
+ size_t old_size = (size_t) (pfile->op_limit - pfile->op_stack);
+ size_t new_size = old_size * 2 + 20;
+
+ pfile->op_stack = (struct op *) xrealloc (pfile->op_stack,
+ new_size * sizeof (struct op));
+ pfile->op_limit = pfile->op_stack + new_size;
+
+ return pfile->op_stack + old_size;
+}
+
+/* Emits a warning if the effective sign of either operand of OP
+ changes because of integer promotions. */
+static void
+check_promotion (pfile, op)
+ cpp_reader *pfile;
+ const struct op *op;
+{
+ if (op->value.unsignedp == op[-1].value.unsignedp)
+ return;
+
+ if (op->value.unsignedp)
+ {
+ if (!num_positive (op[-1].value, CPP_OPTION (pfile, precision)))
+ cpp_error (pfile, DL_WARNING,
+ "the left operand of \"%s\" changes sign when promoted",
+ cpp_token_as_text (pfile, op->token));
+ }
+ else if (!num_positive (op->value, CPP_OPTION (pfile, precision)))
+ cpp_error (pfile, DL_WARNING,
+ "the right operand of \"%s\" changes sign when promoted",
+ cpp_token_as_text (pfile, op->token));
+}
+
+/* Clears the unused high order bits of the number pointed to by PNUM. */
+static cpp_num
+num_trim (num, precision)
+ cpp_num num;
+ size_t precision;
+{
+ if (precision > PART_PRECISION)
+ {
+ precision -= PART_PRECISION;
+ if (precision < PART_PRECISION)
+ num.high &= ((cpp_num_part) 1 << precision) - 1;
+ }
+ else
+ {
+ if (precision < PART_PRECISION)
+ num.low &= ((cpp_num_part) 1 << precision) - 1;
+ num.high = 0;
+ }
+
+ return num;
+}
+
+/* True iff A (presumed signed) >= 0. */
+static bool
+num_positive (num, precision)
+ cpp_num num;
+ size_t precision;
+{
+ if (precision > PART_PRECISION)
+ {
+ precision -= PART_PRECISION;
+ return (num.high & (cpp_num_part) 1 << (precision - 1)) == 0;
+ }
+
+ return (num.low & (cpp_num_part) 1 << (precision - 1)) == 0;
+}
+
+/* Sign extend a number, with PRECISION significant bits and all
+ others assumed clear, to fill out a cpp_num structure. */
+cpp_num
+cpp_num_sign_extend (num, precision)
+ cpp_num num;
+ size_t precision;
+{
+ if (!num.unsignedp)
+ {
+ if (precision > PART_PRECISION)
+ {
+ precision -= PART_PRECISION;
+ if (precision < PART_PRECISION
+ && (num.high & (cpp_num_part) 1 << (precision - 1)))
+ num.high |= ~(~(cpp_num_part) 0 >> (PART_PRECISION - precision));
+ }
+ else if (num.low & (cpp_num_part) 1 << (precision - 1))
+ {
+ if (precision < PART_PRECISION)
+ num.low |= ~(~(cpp_num_part) 0 >> (PART_PRECISION - precision));
+ num.high = ~(cpp_num_part) 0;
+ }
+ }
+
+ return num;
+}
+
+/* Returns the negative of NUM. */
+static cpp_num
+num_negate (num, precision)
+ cpp_num num;
+ size_t precision;
+{
+ cpp_num copy;
+
+ copy = num;
+ num.high = ~num.high;
+ num.low = ~num.low;
+ if (++num.low == 0)
+ num.high++;
+ num = num_trim (num, precision);
+ num.overflow = (!num.unsignedp && num_eq (num, copy) && !num_zerop (num));
+
+ return num;
+}
+
+/* Returns true if A >= B. */
+static bool
+num_greater_eq (pa, pb, precision)
+ cpp_num pa, pb;
+ size_t precision;
+{
+ bool unsignedp;
+
+ unsignedp = pa.unsignedp || pb.unsignedp;
+
+ if (!unsignedp)
+ {
+ /* Both numbers have signed type. If they are of different
+ sign, the answer is the sign of A. */
+ unsignedp = num_positive (pa, precision);
+
+ if (unsignedp != num_positive (pb, precision))
+ return unsignedp;
+
+ /* Otherwise we can do an unsigned comparison. */
+ }
+
+ return (pa.high > pb.high) || (pa.high == pb.high && pa.low >= pb.low);
+}
+
+/* Returns LHS OP RHS, where OP is a bit-wise operation. */
+static cpp_num
+num_bitwise_op (pfile, lhs, rhs, op)
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
+ cpp_num lhs, rhs;
+ enum cpp_ttype op;
+{
+ lhs.overflow = false;
+ lhs.unsignedp = lhs.unsignedp || rhs.unsignedp;
+
+ /* As excess precision is zeroed, there is no need to num_trim () as
+ these operations cannot introduce a set bit there. */
+ if (op == CPP_AND)
+ {
+ lhs.low &= rhs.low;
+ lhs.high &= rhs.high;
+ }
+ else if (op == CPP_OR)
+ {
+ lhs.low |= rhs.low;
+ lhs.high |= rhs.high;
+ }
+ else
+ {
+ lhs.low ^= rhs.low;
+ lhs.high ^= rhs.high;
+ }
+
+ return lhs;
+}
+
+/* Returns LHS OP RHS, where OP is an inequality. */
+static cpp_num
+num_inequality_op (pfile, lhs, rhs, op)
+ cpp_reader *pfile;
+ cpp_num lhs, rhs;
+ enum cpp_ttype op;
+{
+ bool gte = num_greater_eq (lhs, rhs, CPP_OPTION (pfile, precision));
+
+ if (op == CPP_GREATER_EQ)
+ lhs.low = gte;
+ else if (op == CPP_LESS)
+ lhs.low = !gte;
+ else if (op == CPP_GREATER)
+ lhs.low = gte && !num_eq (lhs, rhs);
+ else /* CPP_LESS_EQ. */
+ lhs.low = !gte || num_eq (lhs, rhs);
+
+ lhs.high = 0;
+ lhs.overflow = false;
+ lhs.unsignedp = false;
+ return lhs;
+}
+
+/* Returns LHS OP RHS, where OP is == or !=. */
+static cpp_num
+num_equality_op (pfile, lhs, rhs, op)
+ cpp_reader *pfile ATTRIBUTE_UNUSED;
+ cpp_num lhs, rhs;
+ enum cpp_ttype op;
+{
+ /* Work around a 3.0.4 bug; see PR 6950. */
+ bool eq = num_eq (lhs, rhs);
+ if (op == CPP_NOT_EQ)
+ eq = !eq;
+ lhs.low = eq;
+ lhs.high = 0;
+ lhs.overflow = false;
+ lhs.unsignedp = false;
+ return lhs;
+}
+
+/* Shift NUM, of width PRECISION, right by N bits. */
+static cpp_num
+num_rshift (num, precision, n)
+ cpp_num num;
+ size_t precision, n;
+{
+ cpp_num_part sign_mask;
+
+ if (num.unsignedp || num_positive (num, precision))
+ sign_mask = 0;
+ else
+ sign_mask = ~(cpp_num_part) 0;
+
+ if (n >= precision)
+ num.high = num.low = sign_mask;
+ else
+ {
+ /* Sign-extend. */
+ if (precision < PART_PRECISION)
+ num.high = sign_mask, num.low |= sign_mask << precision;
+ else if (precision < 2 * PART_PRECISION)
+ num.high |= sign_mask << (precision - PART_PRECISION);
+
+ if (n >= PART_PRECISION)
+ {
+ n -= PART_PRECISION;
+ num.low = num.high;
+ num.high = sign_mask;
+ }
- skip_reduction:
- /* Check we have a left operand iff we need one. */
- if (flags & NO_L_OPERAND)
+ if (n)
{
- if (top->flags & HAVE_VALUE)
- SYNTAX_ERROR2 ("missing binary operator before '%s'",
- op_as_text (pfile, op.op));
+ num.low = (num.low >> n) | (num.high << (PART_PRECISION - n));
+ num.high = (num.high >> n) | (sign_mask << (PART_PRECISION - n));
}
+ }
+
+ num = num_trim (num, precision);
+ num.overflow = false;
+ return num;
+}
+
+/* Shift NUM, of width PRECISION, left by N bits. */
+static cpp_num
+num_lshift (num, precision, n)
+ cpp_num num;
+ size_t precision, n;
+{
+ if (n >= precision)
+ {
+ num.overflow = !num.unsignedp && !num_zerop (num);
+ num.high = num.low = 0;
+ }
+ else
+ {
+ cpp_num orig, maybe_orig;
+ size_t m = n;
+
+ orig = num;
+ if (m >= PART_PRECISION)
+ {
+ m -= PART_PRECISION;
+ num.high = num.low;
+ num.low = 0;
+ }
+ if (m)
+ {
+ num.high = (num.high << m) | (num.low >> (PART_PRECISION - m));
+ num.low <<= m;
+ }
+ num = num_trim (num, precision);
+
+ if (num.unsignedp)
+ num.overflow = false;
else
{
- if (!(top->flags & HAVE_VALUE))
- SYNTAX_ERROR2 ("operator '%s' has no left operand",
- op_as_text (pfile, op.op));
+ maybe_orig = num_rshift (num, precision, n);
+ num.overflow = !num_eq (orig, maybe_orig);
}
+ }
- /* Check for and handle stack overflow. */
- top++;
- if (top == limit)
- {
- struct op *new_stack;
- int old_size = (char *) limit - (char *) stack;
- int new_size = 2 * old_size;
- if (stack != init_stack)
- new_stack = (struct op *) xrealloc (stack, new_size);
+ return num;
+}
+
+/* The four unary operators: +, -, ! and ~. */
+static cpp_num
+num_unary_op (pfile, num, op)
+ cpp_reader *pfile;
+ cpp_num num;
+ enum cpp_ttype op;
+{
+ switch (op)
+ {
+ case CPP_UPLUS:
+ if (CPP_WTRADITIONAL (pfile) && !pfile->state.skip_eval)
+ cpp_error (pfile, DL_WARNING,
+ "traditional C rejects the unary plus operator");
+ num.overflow = false;
+ break;
+
+ case CPP_UMINUS:
+ num = num_negate (num, CPP_OPTION (pfile, precision));
+ break;
+
+ case CPP_COMPL:
+ num.high = ~num.high;
+ num.low = ~num.low;
+ num = num_trim (num, CPP_OPTION (pfile, precision));
+ num.overflow = false;
+ break;
+
+ default: /* case CPP_NOT: */
+ num.low = num_zerop (num);
+ num.high = 0;
+ num.overflow = false;
+ num.unsignedp = false;
+ break;
+ }
+
+ return num;
+}
+
+/* The various binary operators. */
+static cpp_num
+num_binary_op (pfile, lhs, rhs, op)
+ cpp_reader *pfile;
+ cpp_num lhs, rhs;
+ enum cpp_ttype op;
+{
+ cpp_num result;
+ size_t precision = CPP_OPTION (pfile, precision);
+ bool gte;
+ size_t n;
+
+ switch (op)
+ {
+ /* Shifts. */
+ case CPP_LSHIFT:
+ case CPP_RSHIFT:
+ if (!rhs.unsignedp && !num_positive (rhs, precision))
+ {
+ /* A negative shift is a positive shift the other way. */
+ if (op == CPP_LSHIFT)
+ op = CPP_RSHIFT;
else
- {
- new_stack = (struct op *) xmalloc (new_size);
- memcpy (new_stack, stack, old_size);
- }
- stack = new_stack;
- top = (struct op *) ((char *) new_stack + old_size);
- limit = (struct op *) ((char *) new_stack + new_size);
+ op = CPP_LSHIFT;
+ rhs = num_negate (rhs, precision);
}
-
- top->flags = flags;
- top->prio = prio & ~EXTRACT_PRIO(RIGHT_ASSOC);
- top->op = op.op;
+ if (rhs.high)
+ n = ~0; /* Maximal. */
+ else
+ n = rhs.low;
+ if (op == CPP_LSHIFT)
+ lhs = num_lshift (lhs, precision, n);
+ else
+ lhs = num_rshift (lhs, precision, n);
+ break;
+
+ /* Min / Max. */
+ case CPP_MIN:
+ case CPP_MAX:
+ {
+ bool unsignedp = lhs.unsignedp || rhs.unsignedp;
+
+ gte = num_greater_eq (lhs, rhs, precision);
+ if (op == CPP_MIN)
+ gte = !gte;
+ if (!gte)
+ lhs = rhs;
+ lhs.unsignedp = unsignedp;
+ }
+ break;
+
+ /* Arithmetic. */
+ case CPP_MINUS:
+ rhs = num_negate (rhs, precision);
+ case CPP_PLUS:
+ result.low = lhs.low + rhs.low;
+ result.high = lhs.high + rhs.high;
+ if (result.low < lhs.low)
+ result.high++;
+
+ result = num_trim (result, precision);
+ result.unsignedp = lhs.unsignedp || rhs.unsignedp;
+ if (result.unsignedp)
+ result.overflow = false;
+ else
+ {
+ bool lhsp = num_positive (lhs, precision);
+ result.overflow = (lhsp == num_positive (rhs, precision)
+ && lhsp != num_positive (result, precision));
+ }
+ return result;
+
+ /* Comma. */
+ default: /* case CPP_COMMA: */
+ if (CPP_PEDANTIC (pfile) && !pfile->state.skip_eval)
+ cpp_error (pfile, DL_PEDWARN,
+ "comma operator in operand of #if");
+ lhs = rhs;
+ break;
}
- done:
- /* The controlling macro expression is only valid if we called lex 3
- times: <!> <defined expression> and <EOF>. push_conditional ()
- checks that we are at top-of-file. */
- if (pfile->mi_ind_cmacro && !(saw_leading_not && lex_count == 3))
- pfile->mi_ind_cmacro = 0;
+ return lhs;
+}
+
+/* Multiplies two unsigned cpp_num_parts to give a cpp_num. This
+ cannot overflow. */
+static cpp_num
+num_part_mul (lhs, rhs)
+ cpp_num_part lhs, rhs;
+{
+ cpp_num result;
+ cpp_num_part middle[2], temp;
+
+ result.low = LOW_PART (lhs) * LOW_PART (rhs);
+ result.high = HIGH_PART (lhs) * HIGH_PART (rhs);
+
+ middle[0] = LOW_PART (lhs) * HIGH_PART (rhs);
+ middle[1] = HIGH_PART (lhs) * LOW_PART (rhs);
- result = (top[1].value != 0);
+ temp = result.low;
+ result.low += LOW_PART (middle[0]) << (PART_PRECISION / 2);
+ if (result.low < temp)
+ result.high++;
- if (top != stack)
- CPP_ICE ("unbalanced stack in #if");
- else if (!(top[1].flags & HAVE_VALUE))
+ temp = result.low;
+ result.low += LOW_PART (middle[1]) << (PART_PRECISION / 2);
+ if (result.low < temp)
+ result.high++;
+
+ result.high += HIGH_PART (middle[0]);
+ result.high += HIGH_PART (middle[1]);
+ result.unsignedp = 1;
+
+ return result;
+}
+
+/* Multiply two preprocessing numbers. */
+static cpp_num
+num_mul (pfile, lhs, rhs)
+ cpp_reader *pfile;
+ cpp_num lhs, rhs;
+{
+ cpp_num result, temp;
+ bool unsignedp = lhs.unsignedp || rhs.unsignedp;
+ bool overflow, negate = false;
+ size_t precision = CPP_OPTION (pfile, precision);
+
+ /* Prepare for unsigned multiplication. */
+ if (!unsignedp)
{
- SYNTAX_ERROR ("#if with no expression");
- syntax_error:
- result = 0; /* Return 0 on syntax error. */
+ if (!num_positive (lhs, precision))
+ negate = !negate, lhs = num_negate (lhs, precision);
+ if (!num_positive (rhs, precision))
+ negate = !negate, rhs = num_negate (rhs, precision);
}
- /* Free dynamic stack if we allocated one. */
- if (stack != init_stack)
- free (stack);
+ overflow = lhs.high && rhs.high;
+ result = num_part_mul (lhs.low, rhs.low);
+
+ temp = num_part_mul (lhs.high, rhs.low);
+ result.high += temp.low;
+ if (temp.high)
+ overflow = true;
+
+ temp = num_part_mul (lhs.low, rhs.high);
+ result.high += temp.low;
+ if (temp.high)
+ overflow = true;
+
+ temp.low = result.low, temp.high = result.high;
+ result = num_trim (result, precision);
+ if (!num_eq (result, temp))
+ overflow = true;
+
+ if (negate)
+ result = num_negate (result, precision);
+
+ if (unsignedp)
+ result.overflow = false;
+ else
+ result.overflow = overflow || (num_positive (result, precision) ^ !negate
+ && !num_zerop (result));
+ result.unsignedp = unsignedp;
+
return result;
}
-/* Output OP as text for diagnostics. */
-static const unsigned char *
-op_as_text (pfile, op)
+/* Divide two preprocessing numbers, returning the answer or the
+ remainder depending upon OP. */
+static cpp_num
+num_div_op (pfile, lhs, rhs, op)
cpp_reader *pfile;
+ cpp_num lhs, rhs;
enum cpp_ttype op;
{
- cpp_token token;
+ cpp_num result, sub;
+ cpp_num_part mask;
+ bool unsignedp = lhs.unsignedp || rhs.unsignedp;
+ bool negate = false, lhs_neg = false;
+ size_t i, precision = CPP_OPTION (pfile, precision);
+
+ /* Prepare for unsigned division. */
+ if (!unsignedp)
+ {
+ if (!num_positive (lhs, precision))
+ negate = !negate, lhs_neg = true, lhs = num_negate (lhs, precision);
+ if (!num_positive (rhs, precision))
+ negate = !negate, rhs = num_negate (rhs, precision);
+ }
+
+ /* Find the high bit. */
+ if (rhs.high)
+ {
+ i = precision - 1;
+ mask = (cpp_num_part) 1 << (i - PART_PRECISION);
+ for (; ; i--, mask >>= 1)
+ if (rhs.high & mask)
+ break;
+ }
+ else if (rhs.low)
+ {
+ if (precision > PART_PRECISION)
+ i = precision - PART_PRECISION - 1;
+ else
+ i = precision - 1;
+ mask = (cpp_num_part) 1 << i;
+ for (; ; i--, mask >>= 1)
+ if (rhs.low & mask)
+ break;
+ }
+ else
+ {
+ if (!pfile->state.skip_eval)
+ cpp_error (pfile, DL_ERROR, "division by zero in #if");
+ return lhs;
+ }
+
+ /* First nonzero bit of RHS is bit I. Do naive division by
+ shifting the RHS fully left, and subtracting from LHS if LHS is
+ at least as big, and then repeating but with one less shift.
+ This is not very efficient, but is easy to understand. */
+
+ rhs.unsignedp = true;
+ lhs.unsignedp = true;
+ i = precision - i - 1;
+ sub = num_lshift (rhs, precision, i);
+
+ result.high = result.low = 0;
+ for (;;)
+ {
+ if (num_greater_eq (lhs, sub, precision))
+ {
+ lhs = num_binary_op (pfile, lhs, sub, CPP_MINUS);
+ if (i >= PART_PRECISION)
+ result.high |= (cpp_num_part) 1 << (i - PART_PRECISION);
+ else
+ result.low |= (cpp_num_part) 1 << i;
+ }
+ if (i-- == 0)
+ break;
+ sub.low = (sub.low >> 1) | (sub.high << (PART_PRECISION - 1));
+ sub.high >>= 1;
+ }
+
+ /* We divide so that the remainder has the sign of the LHS. */
+ if (op == CPP_DIV)
+ {
+ result.unsignedp = unsignedp;
+ if (unsignedp)
+ result.overflow = false;
+ else
+ {
+ if (negate)
+ result = num_negate (result, precision);
+ result.overflow = num_positive (result, precision) ^ !negate;
+ }
+
+ return result;
+ }
+
+ /* CPP_MOD. */
+ lhs.unsignedp = unsignedp;
+ lhs.overflow = false;
+ if (lhs_neg)
+ lhs = num_negate (lhs, precision);
- token.type = op;
- token.flags = 0;
- return cpp_token_as_text (pfile, &token);
+ return lhs;
}
diff --git a/contrib/gcc/cppfiles.c b/contrib/gcc/cppfiles.c
index cad35c2..2e11912 100644
--- a/contrib/gcc/cppfiles.c
+++ b/contrib/gcc/cppfiles.c
@@ -27,6 +27,12 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "intl.h"
#include "mkdeps.h"
#include "splay-tree.h"
+#ifdef ENABLE_VALGRIND_CHECKING
+#include <valgrind.h>
+#else
+/* Avoid #ifdef:s when we can help it. */
+#define VALGRIND_DISCARD(x)
+#endif
#ifdef HAVE_MMAP_FILE
# include <sys/mman.h>
@@ -77,8 +83,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#undef strcmp
/* This structure is used for the table of all includes. */
-struct include_file
-{
+struct include_file {
const char *name; /* actual path name of file */
const cpp_hashnode *cmacro; /* macro, if any, preventing reinclusion. */
const struct search_path *foundhere;
@@ -106,7 +111,7 @@ struct include_file
included again. If it's NEVER_REREAD, the file is never to be
included again. Otherwise it is a macro hashnode, and the file is
to be included again if the macro is defined. */
-#define NEVER_REREAD ((const cpp_hashnode *)-1)
+#define NEVER_REREAD ((const cpp_hashnode *) -1)
#define DO_NOT_REREAD(inc) \
((inc)->cmacro && ((inc)->cmacro == NEVER_REREAD \
|| (inc)->cmacro->type == NT_MACRO))
@@ -168,7 +173,7 @@ static void
destroy_node (v)
splay_tree_value v;
{
- struct include_file *f = (struct include_file *)v;
+ struct include_file *f = (struct include_file *) v;
if (f)
{
@@ -250,7 +255,7 @@ open_file (pfile, filename)
/* Don't reopen an idempotent file. */
if (DO_NOT_REREAD (file))
return file;
-
+
/* Don't reopen one which is already loaded. */
if (file->buffer != NULL)
return file;
@@ -270,7 +275,15 @@ open_file (pfile, filename)
Special case: the empty string is translated to stdin. */
if (filename[0] == '\0')
- file->fd = 0;
+ {
+ file->fd = 0;
+#ifdef __DJGPP__
+ /* For DJGPP redirected input is opened in text mode. Change it
+ to binary mode. */
+ if (! isatty (file->fd))
+ setmode (file->fd, O_BINARY);
+#endif
+ }
else
file->fd = open (file->name, O_RDONLY | O_NOCTTY | O_BINARY, 0666);
@@ -311,9 +324,9 @@ stack_include_file (pfile, inc)
(inc->foundhere ? inc->foundhere->sysp : 0));
/* Add the file to the dependencies on its first inclusion. */
- if (CPP_OPTION (pfile, print_deps) > !!sysp && !inc->include_count)
+ if (CPP_OPTION (pfile, deps.style) > !!sysp && !inc->include_count)
{
- if (pfile->buffer || CPP_OPTION (pfile, deps_ignore_main_file) == 0)
+ if (pfile->buffer || CPP_OPTION (pfile, deps.ignore_main_file) == 0)
deps_add_dep (pfile->deps, inc->name);
}
@@ -345,7 +358,7 @@ stack_include_file (pfile, inc)
fp->inc = inc;
fp->inc->refcnt++;
- /* Initialise controlling macro state. */
+ /* Initialize controlling macro state. */
pfile->mi_valid = true;
pfile->mi_cmacro = 0;
@@ -378,7 +391,7 @@ read_include_file (pfile, inc)
struct include_file *inc;
{
ssize_t size, offset, count;
- U_CHAR *buf;
+ uchar *buf;
#if MMAP_THRESHOLD
static int pagesize = -1;
#endif
@@ -395,7 +408,7 @@ read_include_file (pfile, inc)
does not bite us. */
if (inc->st.st_size > INTTYPE_MAXIMUM (ssize_t))
{
- cpp_error (pfile, "%s is too large", inc->name);
+ cpp_error (pfile, DL_ERROR, "%s is too large", inc->name);
goto fail;
}
size = inc->st.st_size;
@@ -407,15 +420,20 @@ read_include_file (pfile, inc)
if (SHOULD_MMAP (size, pagesize))
{
- buf = (U_CHAR *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0);
- if (buf == (U_CHAR *)-1)
+ buf = (uchar *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0);
+ if (buf == (uchar *) -1)
goto perror_fail;
+
+ /* We must tell Valgrind that the byte at buf[size] is actually
+ readable. Discard the handle to avoid handle leak. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_READABLE (buf + size, 1));
+
inc->mapped = 1;
}
else
#endif
{
- buf = (U_CHAR *) xmalloc (size + 1);
+ buf = (uchar *) xmalloc (size + 1);
offset = 0;
while (offset < size)
{
@@ -425,8 +443,8 @@ read_include_file (pfile, inc)
if (count == 0)
{
if (!STAT_SIZE_TOO_BIG (inc->st))
- cpp_warning
- (pfile, "%s is shorter than expected", inc->name);
+ cpp_error (pfile, DL_WARNING,
+ "%s is shorter than expected", inc->name);
size = offset;
buf = xrealloc (buf, size + 1);
inc->st.st_size = size;
@@ -440,7 +458,7 @@ read_include_file (pfile, inc)
}
else if (S_ISBLK (inc->st.st_mode))
{
- cpp_error (pfile, "%s is a block device", inc->name);
+ cpp_error (pfile, DL_ERROR, "%s is a block device", inc->name);
goto fail;
}
else
@@ -450,7 +468,7 @@ read_include_file (pfile, inc)
bigger than the majority of C source files. */
size = 8 * 1024;
- buf = (U_CHAR *) xmalloc (size + 1);
+ buf = (uchar *) xmalloc (size + 1);
offset = 0;
while ((count = read (inc->fd, buf + offset, size - offset)) > 0)
{
@@ -476,7 +494,7 @@ read_include_file (pfile, inc)
return 0;
perror_fail:
- cpp_error_from_errno (pfile, inc->name);
+ cpp_errno (pfile, DL_ERROR, inc->name);
fail:
return 1;
}
@@ -490,7 +508,14 @@ purge_cache (inc)
{
#if MMAP_THRESHOLD
if (inc->mapped)
- munmap ((PTR) inc->buffer, inc->st.st_size);
+ {
+ /* Undo the previous annotation for the
+ known-zero-byte-after-mmap. Discard the handle to avoid
+ handle leak. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (inc->buffer
+ + inc->st.st_size, 1));
+ munmap ((PTR) inc->buffer, inc->st.st_size);
+ }
else
#endif
free ((PTR) inc->buffer);
@@ -515,7 +540,7 @@ cpp_included (pfile, fname)
nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) fname);
return (nd && nd->value);
}
-
+
/* Search directory path for the file. */
name = (char *) alloca (strlen (fname) + pfile->max_include_len + 2);
for (path = CPP_OPTION (pfile, quote_include); path; path = path->next)
@@ -566,7 +591,8 @@ find_include_file (pfile, header, type)
if (path == NULL)
{
- cpp_error (pfile, "no include path in which to find %s", fname);
+ cpp_error (pfile, DL_ERROR, "no include path in which to find %s",
+ fname);
return NO_INCLUDE_PATH;
}
@@ -633,7 +659,7 @@ report_missing_guard (n, b)
void *b;
{
struct include_file *f = (struct include_file *) n->value;
- int *bannerp = (int *)b;
+ int *bannerp = (int *) b;
if (f && f->cmacro == 0 && f->include_count == 1)
{
@@ -649,7 +675,7 @@ report_missing_guard (n, b)
}
/* Create a dependency for file FNAME, or issue an error message as
- appropriate. ANGLE_BRACKETS is non-zero if the file was bracketed
+ appropriate. ANGLE_BRACKETS is nonzero if the file was bracketed
like <..>. */
static void
handle_missing_header (pfile, fname, angle_brackets)
@@ -657,43 +683,19 @@ handle_missing_header (pfile, fname, angle_brackets)
const char *fname;
int angle_brackets;
{
- int print_dep = CPP_PRINT_DEPS(pfile) > (angle_brackets || pfile->map->sysp);
-
- if (CPP_OPTION (pfile, print_deps_missing_files) && print_dep)
- {
- if (!angle_brackets || IS_ABSOLUTE_PATHNAME (fname))
- deps_add_dep (pfile->deps, fname);
- else
- {
- /* If requested as a system header, assume it belongs in
- the first system header directory. */
- struct search_path *ptr = CPP_OPTION (pfile, bracket_include);
- char *p;
- int len = 0, fname_len = strlen (fname);
-
- if (ptr)
- len = ptr->len;
+ bool print_dep
+ = CPP_OPTION (pfile, deps.style) > (angle_brackets || pfile->map->sysp);
- p = (char *) alloca (len + fname_len + 2);
- if (len)
- {
- memcpy (p, ptr->name, len);
- p[len++] = '/';
- }
- memcpy (p + len, fname, fname_len + 1);
- deps_add_dep (pfile->deps, p);
- }
- }
+ if (CPP_OPTION (pfile, deps.missing_files) && print_dep)
+ deps_add_dep (pfile->deps, fname);
/* If -M was specified, then don't count this as an error, because
we can still produce correct output. Otherwise, we can't produce
correct output, because there may be dependencies we need inside
the missing file, and we don't know what directory this missing
- file exists in. FIXME: Use a future cpp_diagnostic_with_errno ()
- for both of these cases. */
- else if (CPP_PRINT_DEPS (pfile) && ! print_dep)
- cpp_warning (pfile, "%s: %s", fname, xstrerror (errno));
+ file exists in. */
else
- cpp_error_from_errno (pfile, fname);
+ cpp_errno (pfile, CPP_OPTION (pfile, deps.style) && ! print_dep
+ ? DL_WARNING: DL_ERROR, fname);
}
/* Handles #include-family directives (distinguished by TYPE),
@@ -731,7 +733,7 @@ _cpp_compare_file_date (pfile, header)
const cpp_token *header;
{
struct include_file *inc = find_include_file (pfile, header, 0);
-
+
if (inc == NULL || inc == NO_INCLUDE_PATH)
return -1;
@@ -740,7 +742,7 @@ _cpp_compare_file_date (pfile, header)
close (inc->fd);
inc->fd = -1;
}
-
+
return inc->st.st_mtime > pfile->buffer->inc->st.st_mtime;
}
@@ -757,7 +759,7 @@ _cpp_read_file (pfile, fname)
if (f == NULL)
{
- cpp_error_from_errno (pfile, fname);
+ cpp_errno (pfile, DL_ERROR, fname);
return false;
}
@@ -765,14 +767,12 @@ _cpp_read_file (pfile, fname)
}
/* Do appropriate cleanup when a file INC's buffer is popped off the
- input stack. Push the next -include file, if any remain. */
-bool
+ input stack. */
+void
_cpp_pop_file_buffer (pfile, inc)
cpp_reader *pfile;
struct include_file *inc;
{
- bool pushed = false;
-
/* Record the inclusion-preventing macro, which could be NULL
meaning no controlling macro. */
if (pfile->mi_valid && inc->cmacro == NULL)
@@ -784,18 +784,6 @@ _cpp_pop_file_buffer (pfile, inc)
inc->refcnt--;
if (inc->refcnt == 0 && DO_NOT_REREAD (inc))
purge_cache (inc);
-
- /* Don't generate a callback for popping the main file. */
- if (pfile->buffer)
- {
- _cpp_do_file_change (pfile, LC_LEAVE, 0, 0, 0);
-
- /* Finally, push the next -included file, if any. */
- if (!pfile->buffer->prev)
- pushed = _cpp_push_next_buffer (pfile);
- }
-
- return pushed;
}
/* Returns the first place in the include chain to start searching for
@@ -859,8 +847,7 @@ search_from (pfile, type)
such as DOS. The format of the file name map file is just a series
of lines with two tokens on each line. The first token is the name
to map, and the second token is the actual name to use. */
-struct file_name_map
-{
+struct file_name_map {
struct file_name_map *map_next;
char *map_from;
char *map_to;
@@ -880,10 +867,10 @@ read_filename_string (ch, f)
len = 20;
set = alloc = xmalloc (len + 1);
- if (! is_space(ch))
+ if (! is_space (ch))
{
*set++ = ch;
- while ((ch = getc (f)) != EOF && ! is_space(ch))
+ while ((ch = getc (f)) != EOF && ! is_space (ch))
{
if (set - alloc == len)
{
@@ -900,8 +887,7 @@ read_filename_string (ch, f)
}
/* This structure holds a linked list of file name maps, one per directory. */
-struct file_name_map_list
-{
+struct file_name_map_list {
struct file_name_map_list *map_list_next;
char *map_list_name;
struct file_name_map *map_list_map;
@@ -941,17 +927,16 @@ read_name_map (pfile, dirname)
if (f)
{
int ch;
- int dirlen = strlen (dirname);
while ((ch = getc (f)) != EOF)
{
char *from, *to;
struct file_name_map *ptr;
- if (is_space(ch))
+ if (is_space (ch))
continue;
from = read_filename_string (ch, f);
- while ((ch = getc (f)) != EOF && is_hspace(ch))
+ while ((ch = getc (f)) != EOF && is_hspace (ch))
;
to = read_filename_string (ch, f);
@@ -964,12 +949,9 @@ read_name_map (pfile, dirname)
ptr->map_to = to;
else
{
- ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
- strcpy (ptr->map_to, dirname);
- ptr->map_to[dirlen] = '/';
- strcpy (ptr->map_to + dirlen + 1, to);
+ ptr->map_to = concat (dirname, "/", to, NULL);
free (to);
- }
+ }
ptr->map_next = map_list_ptr->map_list_map;
map_list_ptr->map_list_map = ptr;
@@ -980,13 +962,13 @@ read_name_map (pfile, dirname)
}
fclose (f);
}
-
+
/* Add this information to the cache. */
map_list_ptr->map_list_next = CPP_OPTION (pfile, map_list);
CPP_OPTION (pfile, map_list) = map_list_ptr;
return map_list_ptr->map_list_map;
-}
+}
/* Remap an unsimplified path NAME based on the file_name_map (if any)
for LOC. */
@@ -1011,10 +993,10 @@ remap_filename (pfile, name, loc)
if (! loc->name_map)
return name;
}
-
+
/* This works since NAME has not been simplified yet. */
from = name + loc->len + 1;
-
+
for (map = loc->name_map; map; map = map->map_next)
if (!strcmp (map->map_from, from))
return map->map_to;
@@ -1029,13 +1011,13 @@ remap_filename (pfile, name, loc)
/* We know p != name as absolute paths don't call remap_filename. */
if (p == name)
- cpp_ice (pfile, "absolute file name in remap_filename");
+ cpp_error (pfile, DL_ICE, "absolute file name in remap_filename");
dir = (char *) alloca (p - name + 1);
memcpy (dir, name, p - name);
dir[p - name] = '\0';
from = p + 1;
-
+
for (map = read_name_map (pfile, dir); map; map = map->map_next)
if (! strcmp (map->map_from, from))
return map->map_to;
@@ -1085,7 +1067,7 @@ remove_component_p (path)
nonzero if an error occurred when using stat () or lstat (). */
char *
_cpp_simplify_pathname (path)
- char *path;
+ char *path;
{
#ifndef VMS
char *from, *to;
@@ -1101,7 +1083,7 @@ _cpp_simplify_pathname (path)
/* Convert all backslashes to slashes. */
for (from = path; *from; from++)
if (*from == '\\') *from = '/';
-
+
/* Skip over leading drive letter if present. */
if (ISALPHA (path[0]) && path[1] == ':')
from = to = &path[2];
@@ -1110,7 +1092,7 @@ _cpp_simplify_pathname (path)
#else
from = to = path;
#endif
-
+
/* Remove redundant leading /s. */
if (*from == '/')
{
@@ -1185,7 +1167,7 @@ _cpp_simplify_pathname (path)
if (move_base)
base = to;
}
-
+
/* Change the empty string to "." so that it is not treated as stdin.
Null terminate. */
if (to == path)
diff --git a/contrib/gcc/cpphash.c b/contrib/gcc/cpphash.c
index 69e1a23..98d51be 100644
--- a/contrib/gcc/cpphash.c
+++ b/contrib/gcc/cpphash.c
@@ -37,7 +37,7 @@ alloc_node (table)
hash_table *table;
{
cpp_hashnode *node;
-
+
node = (cpp_hashnode *) obstack_alloc (&table->pfile->hash_ob,
sizeof (cpp_hashnode));
memset ((PTR) node, 0, sizeof (cpp_hashnode));
@@ -72,7 +72,6 @@ _cpp_init_hashtable (pfile, table)
s->n_defined = cpp_lookup (pfile, DSC("defined"));
s->n_true = cpp_lookup (pfile, DSC("true"));
s->n_false = cpp_lookup (pfile, DSC("false"));
- s->n__STRICT_ANSI__ = cpp_lookup (pfile, DSC("__STRICT_ANSI__"));
s->n__VA_ARGS__ = cpp_lookup (pfile, DSC("__VA_ARGS__"));
s->n__VA_ARGS__->flags |= NODE_DIAGNOSTIC;
}
diff --git a/contrib/gcc/cpphash.h b/contrib/gcc/cpphash.h
index 03de93f..a8e0b87 100644
--- a/contrib/gcc/cpphash.h
+++ b/contrib/gcc/cpphash.h
@@ -26,6 +26,13 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "hashtable.h"
struct directive; /* Deliberately incomplete. */
+struct pending_option;
+struct op;
+
+typedef unsigned char uchar;
+#define U (const uchar *) /* Intended use: U"string" */
+
+#define BITS_PER_CPPCHAR_T (CHAR_BIT * sizeof (cppchar_t))
/* Test if a sign is valid within a preprocessing number. */
#define VALID_SIGN(c, prevc) \
@@ -43,6 +50,63 @@ struct directive; /* Deliberately incomplete. */
efficiency, and partly to limit runaway recursion. */
#define CPP_STACK_MAX 200
+/* Host alignment handling. */
+struct dummy
+{
+ char c;
+ union
+ {
+ double d;
+ int *p;
+ } u;
+};
+
+#define DEFAULT_ALIGNMENT offsetof (struct dummy, u)
+#define CPP_ALIGN2(size, align) (((size) + ((align) - 1)) & ~((align) - 1))
+#define CPP_ALIGN(size) CPP_ALIGN2 (size, DEFAULT_ALIGNMENT)
+
+/* Each macro definition is recorded in a cpp_macro structure.
+ Variadic macros cannot occur with traditional cpp. */
+struct cpp_macro
+{
+ /* Parameters, if any. */
+ cpp_hashnode **params;
+
+ /* Replacement tokens (ISO) or replacement text (traditional). See
+ comment at top of cpptrad.c for how traditional function-like
+ macros are encoded. */
+ union
+ {
+ cpp_token *tokens;
+ const uchar *text;
+ } exp;
+
+ /* Definition line number. */
+ unsigned int line;
+
+ /* Number of tokens in expansion, or bytes for traditional macros. */
+ unsigned int count;
+
+ /* Number of parameters. */
+ unsigned short paramc;
+
+ /* If a function-like macro. */
+ unsigned int fun_like : 1;
+
+ /* If a variadic macro. */
+ unsigned int variadic : 1;
+
+ /* If macro defined in system header. */
+ unsigned int syshdr : 1;
+
+ /* Nonzero if it has been expanded or had its existence tested. */
+ unsigned int used : 1;
+};
+
+#define _cpp_mark_macro_used(NODE) do { \
+ if ((NODE)->type == NT_MACRO && !((NODE)->flags & NODE_BUILTIN)) \
+ (NODE)->value.macro->used = 1; } while (0)
+
/* A generic memory buffer, and operations on it. */
typedef struct _cpp_buff _cpp_buff;
struct _cpp_buff
@@ -77,7 +141,7 @@ struct search_path
of an earlier directory on the search path. */
ino_t ino;
dev_t dev;
- /* Non-zero if it is a system include directory. */
+ /* Nonzero if it is a system include directory. */
int sysp;
/* Mapping of file names for this directory. Only used on MS-DOS
and related platforms. */
@@ -101,16 +165,36 @@ struct tokenrun
cpp_token *base, *limit;
};
+/* Accessor macros for struct cpp_context. */
+#define FIRST(c) ((c)->u.iso.first)
+#define LAST(c) ((c)->u.iso.last)
+#define CUR(c) ((c)->u.trad.cur)
+#define RLIMIT(c) ((c)->u.trad.rlimit)
+
typedef struct cpp_context cpp_context;
struct cpp_context
{
/* Doubly-linked list. */
cpp_context *next, *prev;
- /* Contexts other than the base context are contiguous tokens.
- e.g. macro expansions, expanded argument tokens. */
- union utoken first;
- union utoken last;
+ union
+ {
+ /* For ISO macro expansion. Contexts other than the base context
+ are contiguous tokens. e.g. macro expansions, expanded
+ argument tokens. */
+ struct
+ {
+ union utoken first;
+ union utoken last;
+ } iso;
+
+ /* For traditional macro expansion. */
+ struct
+ {
+ const uchar *cur;
+ const uchar *rlimit;
+ } trad;
+ } u;
/* If non-NULL, a buffer used for storage related to this context.
When the context is popped, the buffer is released. */
@@ -128,12 +212,20 @@ struct lexer_state
/* Nonzero if first token on line is CPP_HASH. */
unsigned char in_directive;
+ /* Nonzero if in a directive that will handle padding tokens itself.
+ #include needs this to avoid problems with computed include and
+ spacing between tokens. */
+ unsigned char directive_wants_padding;
+
/* True if we are skipping a failed conditional group. */
unsigned char skipping;
/* Nonzero if in a directive that takes angle-bracketed headers. */
unsigned char angled_headers;
+ /* Nonzero if in a #if or #elif directive. */
+ unsigned char in_expression;
+
/* Nonzero to save comments. Turned off if discard_comments, and in
all directives apart from #define. */
unsigned char save_comments;
@@ -148,10 +240,13 @@ struct lexer_state
unsigned char poisoned_ok;
/* Nonzero to prevent macro expansion. */
- unsigned char prevent_expansion;
+ unsigned char prevent_expansion;
/* Nonzero when parsing arguments to a function-like macro. */
unsigned char parsing_args;
+
+ /* Nonzero to skip evaluating part of an expression. */
+ unsigned int skip_eval;
};
/* Special nodes - identifiers with predefined significance. */
@@ -160,10 +255,21 @@ struct spec_nodes
cpp_hashnode *n_defined; /* defined operator */
cpp_hashnode *n_true; /* C++ keyword true */
cpp_hashnode *n_false; /* C++ keyword false */
- cpp_hashnode *n__STRICT_ANSI__; /* STDC_0_IN_SYSTEM_HEADERS */
cpp_hashnode *n__VA_ARGS__; /* C99 vararg macros */
};
+/* Encapsulates state used to convert a stream of tokens into a text
+ file. */
+struct printer
+{
+ FILE *outf; /* Stream to write to. */
+ const struct line_map *map; /* Logical to physical line mappings. */
+ const cpp_token *prev; /* Previous token. */
+ const cpp_token *source; /* Source token for spacing. */
+ unsigned int line; /* Line currently being written. */
+ unsigned char printed; /* Nonzero if something output at line. */
+};
+
/* Represents the contents of a file cpplib has read in. */
struct cpp_buffer
{
@@ -217,6 +323,9 @@ struct cpp_buffer
/* The directory of the this buffer's file. Its NAME member is not
allocated, so we don't need to worry about freeing it. */
struct search_path dir;
+
+ /* Used for buffer overlays by cpptrad.c. */
+ const uchar *saved_cur, *saved_rlimit;
};
/* A cpp_reader encapsulates the "state" of a pre-processor run.
@@ -227,6 +336,9 @@ struct cpp_reader
/* Top of buffer stack. */
cpp_buffer *buffer;
+ /* Overlaid buffer (can be different after processing #include). */
+ cpp_buffer *overlaid_buffer;
+
/* Lexer state. */
struct lexer_state state;
@@ -250,6 +362,11 @@ struct cpp_reader
/* If in_directive, the directive if known. */
const struct directive *directive;
+ /* The next -include-d file; NULL if they all are done. If it
+ points to NULL, the last one is in progress, and
+ _cpp_maybe_push_include_file has yet to restore the line map. */
+ struct pending_option **next_include_file;
+
/* Multiple inlcude optimisation. */
const cpp_hashnode *mi_cmacro;
const cpp_hashnode *mi_ind_cmacro;
@@ -260,17 +377,12 @@ struct cpp_reader
tokenrun base_run, *cur_run;
unsigned int lookaheads;
- /* Non-zero prevents the lexer from re-using the token runs. */
+ /* Nonzero prevents the lexer from re-using the token runs. */
unsigned int keep_tokens;
/* Error counter for exit code. */
unsigned int errors;
- /* Line and column where a newline was first seen in a string
- constant (multi-line strings). */
- unsigned int mls_line;
- unsigned int mls_col;
-
/* Buffer to hold macro definition string. */
unsigned char *macro_buffer;
unsigned int macro_buffer_len;
@@ -282,15 +394,18 @@ struct cpp_reader
for include files. (Altered as we get more of them.) */
unsigned int max_include_len;
- /* Date and time tokens. Calculated together if either is requested. */
- cpp_token date;
- cpp_token time;
+ /* Macros on or after this line are warned about if unused. */
+ unsigned int first_unused_line;
+
+ /* Date and time text. Calculated together if either is requested. */
+ const uchar *date;
+ const uchar *time;
/* EOF token, and a token forcing paste avoidance. */
cpp_token avoid_paste;
cpp_token eof;
- /* Opaque handle to the dependencies of mkdeps.c. Used by -M etc. */
+ /* Opaque handle to the dependencies of mkdeps.c. */
struct deps *deps;
/* Obstack holding all macro hash nodes. This never shrinks.
@@ -308,9 +423,12 @@ struct cpp_reader
/* Call backs. */
struct cpp_callbacks cb;
- /* Identifier hash table. */
+ /* Identifier hash table. */
struct ht *hash_table;
+ /* Expression parser stack. */
+ struct op *op_stack, *op_limit;
+
/* User visible options. */
struct cpp_options opts;
@@ -318,12 +436,24 @@ struct cpp_reader
preprocessor. */
struct spec_nodes spec_nodes;
- /* Whether to print our version number. Done this way so
- we don't get it twice for -v -version. */
- unsigned char print_version;
+ /* Used when doing preprocessed output. */
+ struct printer print;
/* Whether cpplib owns the hashtable. */
unsigned char our_hashtable;
+
+ /* Traditional preprocessing output buffer (a logical line). */
+ struct
+ {
+ uchar *base;
+ uchar *limit;
+ uchar *cur;
+ unsigned int first_line;
+ } out;
+
+ /* Used to save the original line number during traditional
+ preprocessing. */
+ unsigned int saved_line;
};
/* Character classes. Based on the more primitive macros in safe-ctype.h.
@@ -355,21 +485,29 @@ extern unsigned char _cpp_trigraph_map[UCHAR_MAX + 1];
/* Macros. */
-#define CPP_PRINT_DEPS(PFILE) CPP_OPTION (PFILE, print_deps)
#define CPP_IN_SYSTEM_HEADER(PFILE) ((PFILE)->map && (PFILE)->map->sysp)
#define CPP_PEDANTIC(PF) CPP_OPTION (PF, pedantic)
#define CPP_WTRADITIONAL(PF) CPP_OPTION (PF, warn_traditional)
/* In cpperror.c */
-enum error_type { WARNING = 0, WARNING_SYSHDR, PEDWARN, ERROR, FATAL, ICE };
-extern int _cpp_begin_message PARAMS ((cpp_reader *, enum error_type,
+extern int _cpp_begin_message PARAMS ((cpp_reader *, int,
unsigned int, unsigned int));
/* In cppmacro.c */
extern void _cpp_free_definition PARAMS ((cpp_hashnode *));
-extern int _cpp_create_definition PARAMS ((cpp_reader *, cpp_hashnode *));
+extern bool _cpp_create_definition PARAMS ((cpp_reader *, cpp_hashnode *));
extern void _cpp_pop_context PARAMS ((cpp_reader *));
-
+extern void _cpp_push_text_context PARAMS ((cpp_reader *, cpp_hashnode *,
+ const uchar *, size_t));
+extern bool _cpp_save_parameter PARAMS ((cpp_reader *, cpp_macro *,
+ cpp_hashnode *));
+extern bool _cpp_arguments_ok PARAMS ((cpp_reader *, cpp_macro *,
+ const cpp_hashnode *,
+ unsigned int));
+extern const uchar *_cpp_builtin_macro_text PARAMS ((cpp_reader *,
+ cpp_hashnode *));
+int _cpp_warn_if_unused_macro PARAMS ((cpp_reader *, cpp_hashnode *,
+ void *));
/* In cpphash.c */
extern void _cpp_init_hashtable PARAMS ((cpp_reader *, hash_table *));
extern void _cpp_destroy_hashtable PARAMS ((cpp_reader *));
@@ -387,11 +525,12 @@ extern int _cpp_compare_file_date PARAMS ((cpp_reader *,
extern void _cpp_report_missing_guards PARAMS ((cpp_reader *));
extern void _cpp_init_includes PARAMS ((cpp_reader *));
extern void _cpp_cleanup_includes PARAMS ((cpp_reader *));
-extern bool _cpp_pop_file_buffer PARAMS ((cpp_reader *,
+extern void _cpp_pop_file_buffer PARAMS ((cpp_reader *,
struct include_file *));
/* In cppexp.c */
-extern int _cpp_parse_expr PARAMS ((cpp_reader *));
+extern bool _cpp_parse_expr PARAMS ((cpp_reader *));
+extern struct op *_cpp_expand_op_stack PARAMS ((cpp_reader *));
/* In cpplex.c */
extern cpp_token *_cpp_temp_token PARAMS ((cpp_reader *));
@@ -402,10 +541,10 @@ extern int _cpp_equiv_tokens PARAMS ((const cpp_token *,
extern void _cpp_init_tokenrun PARAMS ((tokenrun *, unsigned int));
/* In cppinit.c. */
-extern bool _cpp_push_next_buffer PARAMS ((cpp_reader *));
+extern void _cpp_maybe_push_include_file PARAMS ((cpp_reader *));
/* In cpplib.c */
-extern int _cpp_test_assertion PARAMS ((cpp_reader *, int *));
+extern int _cpp_test_assertion PARAMS ((cpp_reader *, unsigned int *));
extern int _cpp_handle_directive PARAMS ((cpp_reader *, int));
extern void _cpp_define_builtin PARAMS ((cpp_reader *, const char *));
extern void _cpp_do__Pragma PARAMS ((cpp_reader *));
@@ -416,8 +555,19 @@ extern void _cpp_do_file_change PARAMS ((cpp_reader *, enum lc_reason,
unsigned int, unsigned int));
extern void _cpp_pop_buffer PARAMS ((cpp_reader *));
+/* In cpptrad.c. */
+extern bool _cpp_read_logical_line_trad PARAMS ((cpp_reader *));
+extern void _cpp_overlay_buffer PARAMS ((cpp_reader *pfile, const uchar *,
+ size_t));
+extern void _cpp_remove_overlay PARAMS ((cpp_reader *));
+extern bool _cpp_create_trad_definition PARAMS ((cpp_reader *, cpp_macro *));
+extern bool _cpp_expansions_different_trad PARAMS ((const cpp_macro *,
+ const cpp_macro *));
+extern uchar *_cpp_copy_replacement_text PARAMS ((const cpp_macro *, uchar *));
+extern size_t _cpp_replacement_text_len PARAMS ((const cpp_macro *));
+
/* Utility routines and macros. */
-#define DSC(str) (const U_CHAR *)str, sizeof str - 1
+#define DSC(str) (const uchar *)str, sizeof str - 1
#define xnew(T) (T *) xmalloc (sizeof(T))
#define xcnew(T) (T *) xcalloc (1, sizeof(T))
#define xnewvec(T, N) (T *) xmalloc (sizeof(T) * (N))
@@ -426,27 +576,24 @@ extern void _cpp_pop_buffer PARAMS ((cpp_reader *));
/* These are inline functions instead of macros so we can get type
checking. */
-typedef unsigned char U_CHAR;
-#define U (const U_CHAR *) /* Intended use: U"string" */
-
-static inline int ustrcmp PARAMS ((const U_CHAR *, const U_CHAR *));
-static inline int ustrncmp PARAMS ((const U_CHAR *, const U_CHAR *,
+static inline int ustrcmp PARAMS ((const uchar *, const uchar *));
+static inline int ustrncmp PARAMS ((const uchar *, const uchar *,
size_t));
-static inline size_t ustrlen PARAMS ((const U_CHAR *));
-static inline U_CHAR *uxstrdup PARAMS ((const U_CHAR *));
-static inline U_CHAR *ustrchr PARAMS ((const U_CHAR *, int));
-static inline int ufputs PARAMS ((const U_CHAR *, FILE *));
+static inline size_t ustrlen PARAMS ((const uchar *));
+static inline uchar *uxstrdup PARAMS ((const uchar *));
+static inline uchar *ustrchr PARAMS ((const uchar *, int));
+static inline int ufputs PARAMS ((const uchar *, FILE *));
static inline int
ustrcmp (s1, s2)
- const U_CHAR *s1, *s2;
+ const uchar *s1, *s2;
{
return strcmp ((const char *)s1, (const char *)s2);
}
static inline int
ustrncmp (s1, s2, n)
- const U_CHAR *s1, *s2;
+ const uchar *s1, *s2;
size_t n;
{
return strncmp ((const char *)s1, (const char *)s2, n);
@@ -454,29 +601,29 @@ ustrncmp (s1, s2, n)
static inline size_t
ustrlen (s1)
- const U_CHAR *s1;
+ const uchar *s1;
{
return strlen ((const char *)s1);
}
-static inline U_CHAR *
+static inline uchar *
uxstrdup (s1)
- const U_CHAR *s1;
+ const uchar *s1;
{
- return (U_CHAR *) xstrdup ((const char *)s1);
+ return (uchar *) xstrdup ((const char *)s1);
}
-static inline U_CHAR *
+static inline uchar *
ustrchr (s1, c)
- const U_CHAR *s1;
+ const uchar *s1;
int c;
{
- return (U_CHAR *) strchr ((const char *)s1, c);
+ return (uchar *) strchr ((const char *)s1, c);
}
static inline int
ufputs (s, f)
- const U_CHAR *s;
+ const uchar *s;
FILE *f;
{
return fputs ((const char *)s, f);
diff --git a/contrib/gcc/cppinit.c b/contrib/gcc/cppinit.c
index c7d5041..d8e622b 100644
--- a/contrib/gcc/cppinit.c
+++ b/contrib/gcc/cppinit.c
@@ -25,16 +25,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "cpphash.h"
#include "prefix.h"
#include "intl.h"
-#include "version.h"
#include "mkdeps.h"
#include "cppdefault.h"
-#include "except.h" /* for USING_SJLJ_EXCEPTIONS */
-
-/* Predefined symbols, built-in macros, and the default include path. */
-
-#ifndef GET_ENV_PATH_LIST
-#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
-#endif
/* Windows does not natively support inodes, and neither does MSDOS.
Cygwin's emulation can generate non-unique inodes, so don't use it.
@@ -94,7 +86,6 @@ struct cpp_pending
} while (0)
#endif
-static void print_help PARAMS ((void));
static void path_include PARAMS ((cpp_reader *,
char *, int));
static void init_library PARAMS ((void));
@@ -114,15 +105,13 @@ static void merge_include_chains PARAMS ((cpp_reader *));
static bool push_include PARAMS ((cpp_reader *,
struct pending_option *));
static void free_chain PARAMS ((struct pending_option *));
-static void set_lang PARAMS ((cpp_reader *, enum c_lang));
-static void init_dependency_output PARAMS ((cpp_reader *));
static void init_standard_includes PARAMS ((cpp_reader *));
static void read_original_filename PARAMS ((cpp_reader *));
static void new_pending_directive PARAMS ((struct cpp_pending *,
const char *,
cl_directive_handler));
-static void output_deps PARAMS ((cpp_reader *));
static int parse_option PARAMS ((const char *));
+static void post_options PARAMS ((cpp_reader *));
/* Fourth argument to append_include_chain: chain to use.
Note it's never asked to append to the quote chain. */
@@ -135,14 +124,14 @@ enum { BRACKET = 0, SYSTEM, AFTER };
#define init_trigraph_map() /* Nothing. */
#define TRIGRAPH_MAP \
-__extension__ const U_CHAR _cpp_trigraph_map[UCHAR_MAX + 1] = {
+__extension__ const uchar _cpp_trigraph_map[UCHAR_MAX + 1] = {
#define END };
#define s(p, v) [p] = v,
#else
-#define TRIGRAPH_MAP U_CHAR _cpp_trigraph_map[UCHAR_MAX + 1] = { 0 }; \
+#define TRIGRAPH_MAP uchar _cpp_trigraph_map[UCHAR_MAX + 1] = { 0 }; \
static void init_trigraph_map PARAMS ((void)) { \
unsigned char *x = _cpp_trigraph_map;
@@ -205,14 +194,14 @@ path_include (pfile, list, path)
/* Append DIR to include path PATH. DIR must be allocated on the
heap; this routine takes responsibility for freeing it. CXX_AWARE
- is non-zero if the header contains extern "C" guards for C++,
+ is nonzero if the header contains extern "C" guards for C++,
otherwise it is zero. */
static void
append_include_chain (pfile, dir, path, cxx_aware)
cpp_reader *pfile;
char *dir;
int path;
- int cxx_aware ATTRIBUTE_UNUSED;
+ int cxx_aware;
{
struct cpp_pending *pend = CPP_OPTION (pfile, pending);
struct search_path *new;
@@ -230,7 +219,7 @@ append_include_chain (pfile, dir, path, cxx_aware)
{
/* Dirs that don't exist are silently ignored. */
if (errno != ENOENT)
- cpp_notice_from_errno (pfile, dir);
+ cpp_errno (pfile, DL_ERROR, dir);
else if (CPP_OPTION (pfile, verbose))
fprintf (stderr, _("ignoring nonexistent directory \"%s\"\n"), dir);
free (dir);
@@ -239,7 +228,7 @@ append_include_chain (pfile, dir, path, cxx_aware)
if (!S_ISDIR (st.st_mode))
{
- cpp_notice (pfile, "%s: Not a directory", dir);
+ cpp_error_with_line (pfile, DL_ERROR, 0, 0, "%s: Not a directory", dir);
free (dir);
return;
}
@@ -257,11 +246,7 @@ append_include_chain (pfile, dir, path, cxx_aware)
include files since these two lists are really just a concatenation
of one "system" list. */
if (path == SYSTEM || path == AFTER)
-#ifdef NO_IMPLICIT_EXTERN_C
- new->sysp = 1;
-#else
new->sysp = cxx_aware ? 1 : 2;
-#endif
else
new->sysp = 0;
new->name_map = NULL;
@@ -308,9 +293,9 @@ remove_dup_dir (pfile, prev, head_ptr)
}
/* Remove duplicate non-system directories for which there is an equivalent
- system directory later in the chain. The range for removal is between
+ system directory latter in the chain. The range for removal is between
*HEAD_PTR and END. Returns the directory before END, or NULL if none.
- This algorithm is quadratic in the number of system directories, which is
+ This algorithm is quadratic in the number system directories, which is
acceptable since there aren't usually that many of them. */
static struct search_path *
remove_dup_nonsys_dirs (pfile, head_ptr, end)
@@ -365,7 +350,7 @@ remove_dup_dirs (pfile, head_ptr)
for (cur = *head_ptr; cur; cur = cur->next)
{
for (other = *head_ptr; other != cur; other = other->next)
- if (INO_T_EQ (cur->ino, other->ino) && cur->dev == other->dev)
+ if (INO_T_EQ (cur->ino, other->ino) && cur->dev == other->dev)
{
cur = remove_dup_dir (pfile, prev, head_ptr);
break;
@@ -445,7 +430,6 @@ merge_include_chains (pfile)
struct lang_flags
{
char c99;
- char objc;
char cplusplus;
char extended_numbers;
char std;
@@ -456,31 +440,28 @@ struct lang_flags
/* ??? Enable $ in identifiers in assembly? */
static const struct lang_flags lang_defaults[] =
-{ /* c99 objc c++ xnum std dollar c++comm digr */
- /* GNUC89 */ { 0, 0, 0, 1, 0, 1, 1, 1 },
- /* GNUC99 */ { 1, 0, 0, 1, 0, 1, 1, 1 },
- /* STDC89 */ { 0, 0, 0, 0, 1, 0, 0, 0 },
- /* STDC94 */ { 0, 0, 0, 0, 1, 0, 0, 1 },
- /* STDC99 */ { 1, 0, 0, 1, 1, 0, 1, 1 },
- /* GNUCXX */ { 0, 0, 1, 1, 0, 1, 1, 1 },
- /* CXX98 */ { 0, 0, 1, 1, 1, 0, 1, 1 },
- /* OBJC */ { 0, 1, 0, 1, 0, 1, 1, 1 },
- /* OBJCXX */ { 0, 1, 1, 1, 0, 1, 1, 1 },
- /* ASM */ { 0, 0, 0, 1, 0, 0, 1, 0 }
+{ /* c99 c++ xnum std dollar c++comm digr */
+ /* GNUC89 */ { 0, 0, 1, 0, 1, 1, 1 },
+ /* GNUC99 */ { 1, 0, 1, 0, 1, 1, 1 },
+ /* STDC89 */ { 0, 0, 0, 1, 0, 0, 0 },
+ /* STDC94 */ { 0, 0, 0, 1, 0, 0, 1 },
+ /* STDC99 */ { 1, 0, 1, 1, 0, 1, 1 },
+ /* GNUCXX */ { 0, 1, 1, 0, 1, 1, 1 },
+ /* CXX98 */ { 0, 1, 1, 1, 0, 1, 1 },
+ /* ASM */ { 0, 0, 1, 0, 0, 1, 0 }
};
/* Sets internal flags correctly for a given language. */
-static void
-set_lang (pfile, lang)
+void
+cpp_set_lang (pfile, lang)
cpp_reader *pfile;
enum c_lang lang;
{
const struct lang_flags *l = &lang_defaults[(int) lang];
-
+
CPP_OPTION (pfile, lang) = lang;
CPP_OPTION (pfile, c99) = l->c99;
- CPP_OPTION (pfile, objc) = l->objc;
CPP_OPTION (pfile, cplusplus) = l->cplusplus;
CPP_OPTION (pfile, extended_numbers) = l->extended_numbers;
CPP_OPTION (pfile, std) = l->std;
@@ -534,31 +515,35 @@ cpp_create_reader (lang)
{
cpp_reader *pfile;
- /* Initialise this instance of the library if it hasn't been already. */
+ /* Initialize this instance of the library if it hasn't been already. */
init_library ();
pfile = (cpp_reader *) xcalloc (1, sizeof (cpp_reader));
- set_lang (pfile, lang);
+ cpp_set_lang (pfile, lang);
CPP_OPTION (pfile, warn_import) = 1;
+ CPP_OPTION (pfile, warn_multichar) = 1;
CPP_OPTION (pfile, discard_comments) = 1;
+ CPP_OPTION (pfile, discard_comments_in_macro_exp) = 1;
CPP_OPTION (pfile, show_column) = 1;
CPP_OPTION (pfile, tabstop) = 8;
CPP_OPTION (pfile, operator_names) = 1;
-#if DEFAULT_SIGNED_CHAR
- CPP_OPTION (pfile, signed_char) = 1;
-#else
- CPP_OPTION (pfile, signed_char) = 0;
-#endif
+ CPP_OPTION (pfile, warn_endif_labels) = 1;
+ CPP_OPTION (pfile, warn_long_long) = !CPP_OPTION (pfile, c99);
CPP_OPTION (pfile, pending) =
(struct cpp_pending *) xcalloc (1, sizeof (struct cpp_pending));
- /* It's simplest to just create this struct whether or not it will
- be needed. */
- pfile->deps = deps_init ();
+ /* Default CPP arithmetic to something sensible for the host for the
+ benefit of dumb users like fix-header. */
+ CPP_OPTION (pfile, precision) = CHAR_BIT * sizeof (long);
+ CPP_OPTION (pfile, char_precision) = CHAR_BIT;
+ CPP_OPTION (pfile, wchar_precision) = CHAR_BIT * sizeof (int);
+ CPP_OPTION (pfile, int_precision) = CHAR_BIT * sizeof (int);
+ CPP_OPTION (pfile, unsigned_char) = 0;
+ CPP_OPTION (pfile, unsigned_wchar) = 1;
- /* Initialise the line map. Start at logical line 1, so we can use
+ /* Initialize the line map. Start at logical line 1, so we can use
a line number of zero for special states. */
init_line_maps (&pfile->line_maps);
pfile->line = 1;
@@ -567,7 +552,6 @@ cpp_create_reader (lang)
pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
/* Set up static tokens. */
- pfile->date.type = CPP_EOF;
pfile->avoid_paste.type = CPP_PADDING;
pfile->avoid_paste.val.source = NULL;
pfile->eof.type = CPP_EOF;
@@ -578,7 +562,7 @@ cpp_create_reader (lang)
pfile->cur_run = &pfile->base_run;
pfile->cur_token = pfile->base_run.base;
- /* Initialise the base context. */
+ /* Initialize the base context. */
pfile->context = &pfile->base_context;
pfile->base_context.macro = 0;
pfile->base_context.prev = pfile->base_context.next = 0;
@@ -587,7 +571,10 @@ cpp_create_reader (lang)
pfile->a_buff = _cpp_get_buff (pfile, 0);
pfile->u_buff = _cpp_get_buff (pfile, 0);
- /* Initialise the buffer obstack. */
+ /* The expression parser stack. */
+ _cpp_expand_op_stack (pfile);
+
+ /* Initialize the buffer obstack. */
gcc_obstack_init (&pfile->buffer_ob);
_cpp_init_includes (pfile);
@@ -596,19 +583,25 @@ cpp_create_reader (lang)
}
/* Free resources used by PFILE. Accessing PFILE after this function
- returns leads to undefined behaviour. Returns the error count. */
-int
+ returns leads to undefined behavior. Returns the error count. */
+void
cpp_destroy (pfile)
cpp_reader *pfile;
{
- int result;
struct search_path *dir, *dirn;
cpp_context *context, *contextn;
tokenrun *run, *runn;
+ free_chain (CPP_OPTION (pfile, pending)->include_head);
+ free (CPP_OPTION (pfile, pending));
+ free (pfile->op_stack);
+
while (CPP_BUFFER (pfile) != NULL)
_cpp_pop_buffer (pfile);
+ if (pfile->out.base)
+ free (pfile->out.base);
+
if (pfile->macro_buffer)
{
free ((PTR) pfile->macro_buffer);
@@ -616,7 +609,8 @@ cpp_destroy (pfile)
pfile->macro_buffer_len = 0;
}
- deps_free (pfile->deps);
+ if (pfile->deps)
+ deps_free (pfile->deps);
obstack_free (&pfile->buffer_ob, 0);
_cpp_destroy_hashtable (pfile);
@@ -648,40 +642,31 @@ cpp_destroy (pfile)
}
free_line_maps (&pfile->line_maps);
-
- result = pfile->errors;
free (pfile);
-
- return result;
}
-
/* This structure defines one built-in identifier. A node will be
- entered in the hash table under the name NAME, with value VALUE (if
- any). If flags has OPERATOR, the node's operator field is used; if
- flags has BUILTIN the node's builtin field is used. Macros that are
- known at build time should not be flagged BUILTIN, as then they do
- not appear in macro dumps with e.g. -dM or -dD.
-
- Two values are not compile time constants, so we tag
- them in the FLAGS field instead:
- VERS value is the global version_string, quoted
- ULP value is the global user_label_prefix */
+ entered in the hash table under the name NAME, with value VALUE.
+
+ There are two tables of these. builtin_array holds all the
+ "builtin" macros: these are handled by builtin_macro() in
+ cppmacro.c. Builtin is somewhat of a misnomer -- the property of
+ interest is that these macros require special code to compute their
+ expansions. The value is a "builtin_type" enumerator.
+
+ operator_array holds the C++ named operators. These are keywords
+ which act as aliases for punctuators. In C++, they cannot be
+ altered through #define, and #if recognizes them as operators. In
+ C, these are not entered into the hash table at all (but see
+ <iso646.h>). The value is a token-type enumerator. */
struct builtin
{
- const U_CHAR *name;
- const char *value;
- unsigned char builtin;
- unsigned short flags;
+ const uchar *name;
unsigned short len;
+ unsigned short value;
};
-#define VERS 0x01
-#define ULP 0x02
-#define BUILTIN 0x08
-#define B(n, t) { U n, 0, t, BUILTIN, sizeof n - 1 }
-#define C(n, v) { U n, v, 0, 0, sizeof n - 1 }
-#define X(n, f) { U n, 0, 0, f, sizeof n - 1 }
+#define B(n, t) { DSC(n), t }
static const struct builtin builtin_array[] =
{
B("__TIME__", BT_TIME),
@@ -690,51 +675,14 @@ static const struct builtin builtin_array[] =
B("__BASE_FILE__", BT_BASE_FILE),
B("__LINE__", BT_SPECLINE),
B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL),
+ /* Keep builtins not used for -traditional-cpp at the end, and
+ update init_builtins() if any more are added. */
B("_Pragma", BT_PRAGMA),
-
- X("__VERSION__", VERS),
- X("__USER_LABEL_PREFIX__", ULP),
- C("__REGISTER_PREFIX__", REGISTER_PREFIX),
- C("__HAVE_BUILTIN_SETJMP__", "1"),
-#if USING_SJLJ_EXCEPTIONS
- /* libgcc needs to know this. */
- C("__USING_SJLJ_EXCEPTIONS__","1"),
-#endif
-#ifndef NO_BUILTIN_SIZE_TYPE
- C("__SIZE_TYPE__", SIZE_TYPE),
-#endif
-#ifndef NO_BUILTIN_PTRDIFF_TYPE
- C("__PTRDIFF_TYPE__", PTRDIFF_TYPE),
-#endif
-#ifndef NO_BUILTIN_WCHAR_TYPE
- C("__WCHAR_TYPE__", WCHAR_TYPE),
-#endif
-#ifndef NO_BUILTIN_WINT_TYPE
- C("__WINT_TYPE__", WINT_TYPE),
-#endif
-#ifdef STDC_0_IN_SYSTEM_HEADERS
B("__STDC__", BT_STDC),
-#else
- C("__STDC__", "1"),
-#endif
};
-#undef B
-#undef C
-#undef X
-#define builtin_array_end \
- builtin_array + sizeof(builtin_array)/sizeof(struct builtin)
-
-/* Named operators known to the preprocessor. These cannot be
- #defined and always have their stated meaning. They are treated
- like normal identifiers except for the type code and the meaning.
- Most of them are only for C++ (but see iso646.h). */
-#define B(n, t) { DSC(n), t }
-static const struct named_op
+
+static const struct builtin operator_array[] =
{
- const U_CHAR *name;
- unsigned int len;
- enum cpp_ttype value;
-} operator_array[] = {
B("and", CPP_AND_AND),
B("and_eq", CPP_AND_EQ),
B("bitand", CPP_AND),
@@ -754,7 +702,7 @@ static void
mark_named_operators (pfile)
cpp_reader *pfile;
{
- const struct named_op *b;
+ const struct builtin *b;
for (b = operator_array;
b < (operator_array + ARRAY_SIZE (operator_array));
@@ -773,74 +721,34 @@ init_builtins (pfile)
cpp_reader *pfile;
{
const struct builtin *b;
+ size_t n = ARRAY_SIZE (builtin_array);
- for(b = builtin_array; b < builtin_array_end; b++)
- {
- if (b->flags & BUILTIN)
- {
- cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
- hp->type = NT_MACRO;
- hp->flags |= NODE_BUILTIN | NODE_WARN;
- hp->value.builtin = b->builtin;
- }
- else /* A standard macro of some kind. */
- {
- const char *val;
- char *str;
-
- if (b->flags & VERS)
- {
- /* Allocate enough space for 'name "value"\n\0'. */
- str = alloca (b->len + strlen (version_string) + 5);
- sprintf (str, "%s \"%s\"\n", b->name, version_string);
- }
- else
- {
- if (b->flags & ULP)
- val = CPP_OPTION (pfile, user_label_prefix);
- else
- val = b->value;
+ if (CPP_OPTION (pfile, traditional))
+ n -= 2;
- /* Allocate enough space for "name value\n\0". */
- str = alloca (b->len + strlen (val) + 3);
- sprintf(str, "%s %s\n", b->name, val);
- }
-
- _cpp_define_builtin (pfile, str);
- }
- }
-
- if (CPP_OPTION (pfile, cplusplus))
+ for(b = builtin_array; b < builtin_array + n; b++)
{
- _cpp_define_builtin (pfile, "__cplusplus 1");
- if (SUPPORTS_ONE_ONLY)
- _cpp_define_builtin (pfile, "__GXX_WEAK__ 1");
- else
- _cpp_define_builtin (pfile, "__GXX_WEAK__ 0");
+ cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
+ hp->type = NT_MACRO;
+ hp->flags |= NODE_BUILTIN | NODE_WARN;
+ hp->value.builtin = b->value;
}
- if (CPP_OPTION (pfile, objc))
- _cpp_define_builtin (pfile, "__OBJC__ 1");
- if (CPP_OPTION (pfile, lang) == CLK_STDC94)
+ if (CPP_OPTION (pfile, cplusplus))
+ _cpp_define_builtin (pfile, "__cplusplus 1");
+ else if (CPP_OPTION (pfile, lang) == CLK_ASM)
+ _cpp_define_builtin (pfile, "__ASSEMBLER__ 1");
+ else if (CPP_OPTION (pfile, lang) == CLK_STDC94)
_cpp_define_builtin (pfile, "__STDC_VERSION__ 199409L");
else if (CPP_OPTION (pfile, c99))
_cpp_define_builtin (pfile, "__STDC_VERSION__ 199901L");
- if (CPP_OPTION (pfile, signed_char) == 0)
- _cpp_define_builtin (pfile, "__CHAR_UNSIGNED__ 1");
+ if (CPP_OPTION (pfile, objc))
+ _cpp_define_builtin (pfile, "__OBJC__ 1");
- if (CPP_OPTION (pfile, lang) == CLK_STDC89
- || CPP_OPTION (pfile, lang) == CLK_STDC94
- || CPP_OPTION (pfile, lang) == CLK_STDC99)
- _cpp_define_builtin (pfile, "__STRICT_ANSI__ 1");
- else if (CPP_OPTION (pfile, lang) == CLK_ASM)
- _cpp_define_builtin (pfile, "__ASSEMBLER__ 1");
+ if (pfile->cb.register_builtins)
+ (*pfile->cb.register_builtins) (pfile);
}
-#undef BUILTIN
-#undef OPERATOR
-#undef VERS
-#undef ULP
-#undef builtin_array_end
/* And another subroutine. This one sets up the standard include path. */
static void
@@ -857,23 +765,23 @@ init_standard_includes (pfile)
etc. specify an additional list of directories to be searched as
if specified with -isystem, for the language indicated. */
- GET_ENV_PATH_LIST (path, "CPATH");
+ GET_ENVIRONMENT (path, "CPATH");
if (path != 0 && *path != 0)
path_include (pfile, path, BRACKET);
switch ((CPP_OPTION (pfile, objc) << 1) + CPP_OPTION (pfile, cplusplus))
{
case 0:
- GET_ENV_PATH_LIST (path, "C_INCLUDE_PATH");
+ GET_ENVIRONMENT (path, "C_INCLUDE_PATH");
break;
case 1:
- GET_ENV_PATH_LIST (path, "CPLUS_INCLUDE_PATH");
+ GET_ENVIRONMENT (path, "CPLUS_INCLUDE_PATH");
break;
case 2:
- GET_ENV_PATH_LIST (path, "OBJC_INCLUDE_PATH");
+ GET_ENVIRONMENT (path, "OBJC_INCLUDE_PATH");
break;
case 3:
- GET_ENV_PATH_LIST (path, "OBJCPLUS_INCLUDE_PATH");
+ GET_ENVIRONMENT (path, "OBJCPLUS_INCLUDE_PATH");
break;
}
if (path != 0 && *path != 0)
@@ -932,7 +840,7 @@ init_standard_includes (pfile)
}
/* Pushes a command line -imacro and -include file indicated by P onto
- the buffer stack. Returns non-zero if successful. */
+ the buffer stack. Returns nonzero if successful. */
static bool
push_include (pfile, p)
cpp_reader *pfile;
@@ -966,6 +874,72 @@ free_chain (head)
}
}
+/* Sanity-checks are dependent on command-line options, so it is
+ called as a subroutine of cpp_read_main_file (). */
+#if ENABLE_CHECKING
+static void sanity_checks PARAMS ((cpp_reader *));
+static void sanity_checks (pfile)
+ cpp_reader *pfile;
+{
+ cppchar_t test = 0;
+ size_t max_precision = 2 * CHAR_BIT * sizeof (cpp_num_part);
+
+ /* Sanity checks for assumptions about CPP arithmetic and target
+ type precisions made by cpplib. */
+ test--;
+ if (test < 1)
+ cpp_error (pfile, DL_ICE, "cppchar_t must be an unsigned type");
+
+ if (CPP_OPTION (pfile, precision) > max_precision)
+ cpp_error (pfile, DL_ICE,
+ "preprocessor arithmetic has maximum precision of %lu bits; target requires %lu bits",
+ (unsigned long) max_precision,
+ (unsigned long) CPP_OPTION (pfile, precision));
+
+ if (CPP_OPTION (pfile, precision) < CPP_OPTION (pfile, int_precision))
+ cpp_error (pfile, DL_ICE,
+ "CPP arithmetic must be at least as precise as a target int");
+
+ if (CPP_OPTION (pfile, char_precision) < 8)
+ cpp_error (pfile, DL_ICE, "target char is less than 8 bits wide");
+
+ if (CPP_OPTION (pfile, wchar_precision) < CPP_OPTION (pfile, char_precision))
+ cpp_error (pfile, DL_ICE,
+ "target wchar_t is narrower than target char");
+
+ if (CPP_OPTION (pfile, int_precision) < CPP_OPTION (pfile, char_precision))
+ cpp_error (pfile, DL_ICE,
+ "target int is narrower than target char");
+
+ /* This is assumed in eval_token() and could be fixed if necessary. */
+ if (sizeof (cppchar_t) > sizeof (cpp_num_part))
+ cpp_error (pfile, DL_ICE, "CPP half-integer narrower than CPP character");
+
+ if (CPP_OPTION (pfile, wchar_precision) > BITS_PER_CPPCHAR_T)
+ cpp_error (pfile, DL_ICE,
+ "CPP on this host cannot handle wide character constants over %lu bits, but the target requires %lu bits",
+ (unsigned long) BITS_PER_CPPCHAR_T,
+ (unsigned long) CPP_OPTION (pfile, wchar_precision));
+}
+#else
+# define sanity_checks(PFILE)
+#endif
+
+/* Add a dependency target. Can be called any number of times before
+ cpp_read_main_file(). If no targets have been added before
+ cpp_read_main_file(), then the default target is used. */
+void
+cpp_add_dependency_target (pfile, target, quote)
+ cpp_reader *pfile;
+ const char *target;
+ int quote;
+{
+ if (!pfile->deps)
+ pfile->deps = deps_init ();
+
+ deps_add_target (pfile->deps, target, quote);
+}
+
/* This is called after options have been parsed, and partially
processed. Setup for processing input from the file named FNAME,
or stdin if it is the empty string. Return the original filename
@@ -976,6 +950,10 @@ cpp_read_main_file (pfile, fname, table)
const char *fname;
hash_table *table;
{
+ sanity_checks (pfile);
+
+ post_options (pfile);
+
/* The front ends don't set up the hash table until they have
finished processing the command line options, so initializing the
hashtable is deferred until now. */
@@ -1001,17 +979,22 @@ cpp_read_main_file (pfile, fname, table)
fprintf (stderr, _("End of search list.\n"));
}
- if (CPP_OPTION (pfile, print_deps))
- /* Set the default target (if there is none already). */
- deps_add_default_target (pfile->deps, fname);
+ if (CPP_OPTION (pfile, deps.style) != DEPS_NONE)
+ {
+ if (!pfile->deps)
+ pfile->deps = deps_init ();
+
+ /* Set the default target (if there is none already). */
+ deps_add_default_target (pfile->deps, fname);
+ }
/* Open the main input file. */
if (!_cpp_read_file (pfile, fname))
return NULL;
- /* Set this after cpp_post_options so the client can change the
- option if it wishes, and after stacking the main file so we don't
- trace the main file. */
+ /* Set this here so the client can change the option if it wishes,
+ and after stacking the main file so we don't trace the main
+ file. */
pfile->line_maps.trace_includes = CPP_OPTION (pfile, print_include_names);
/* For foo.i, read the original filename foo.c now, for the benefit
@@ -1069,116 +1052,71 @@ cpp_finish_options (pfile)
{
struct pending_option *p;
+ /* Prevent -Wunused-macros with command-line redefinitions. */
+ pfile->first_unused_line = (unsigned int) -1;
_cpp_do_file_change (pfile, LC_RENAME, _("<built-in>"), 1, 0);
init_builtins (pfile);
_cpp_do_file_change (pfile, LC_RENAME, _("<command line>"), 1, 0);
for (p = CPP_OPTION (pfile, pending)->directive_head; p; p = p->next)
(*p->handler) (pfile, p->arg);
- /* Scan -imacros files after command line defines, but before
- files given with -include. */
- while ((p = CPP_OPTION (pfile, pending)->imacros_head) != NULL)
- {
- if (push_include (pfile, p))
- {
- pfile->buffer->return_at_eof = true;
- cpp_scan_nooutput (pfile);
- }
- CPP_OPTION (pfile, pending)->imacros_head = p->next;
- free (p);
- }
+ /* Scan -imacros files after -D, -U, but before -include.
+ pfile->next_include_file is NULL, so _cpp_pop_buffer does not
+ push -include files. */
+ for (p = CPP_OPTION (pfile, pending)->imacros_head; p; p = p->next)
+ if (push_include (pfile, p))
+ cpp_scan_nooutput (pfile);
+
+ pfile->next_include_file = &CPP_OPTION (pfile, pending)->include_head;
+ _cpp_maybe_push_include_file (pfile);
}
+ pfile->first_unused_line = pfile->line;
+
+ free_chain (CPP_OPTION (pfile, pending)->imacros_head);
free_chain (CPP_OPTION (pfile, pending)->directive_head);
- _cpp_push_next_buffer (pfile);
}
-/* Called to push the next buffer on the stack given by -include. If
- there are none, free the pending structure and restore the line map
- for the main file. */
-bool
-_cpp_push_next_buffer (pfile)
+/* Push the next buffer on the stack given by -include, if any. */
+void
+_cpp_maybe_push_include_file (pfile)
cpp_reader *pfile;
{
- bool pushed = false;
-
- /* This is't pretty; we'd rather not be relying on this as a boolean
- for reverting the line map. Further, we only free the chains in
- this conditional, so an early call to cpp_finish / cpp_destroy
- will leak that memory. */
- if (CPP_OPTION (pfile, pending)
- && CPP_OPTION (pfile, pending)->imacros_head == NULL)
+ if (pfile->next_include_file)
{
- while (!pushed)
- {
- struct pending_option *p = CPP_OPTION (pfile, pending)->include_head;
+ struct pending_option *head = *pfile->next_include_file;
- if (p == NULL)
- break;
- if (! CPP_OPTION (pfile, preprocessed))
- pushed = push_include (pfile, p);
- CPP_OPTION (pfile, pending)->include_head = p->next;
- free (p);
- }
+ while (head && !push_include (pfile, head))
+ head = head->next;
- if (!pushed)
+ if (head)
+ pfile->next_include_file = &head->next;
+ else
{
- free (CPP_OPTION (pfile, pending));
- CPP_OPTION (pfile, pending) = NULL;
-
- /* Restore the line map for the main file. */
- if (! CPP_OPTION (pfile, preprocessed))
- _cpp_do_file_change (pfile, LC_RENAME,
- pfile->line_maps.maps[0].to_file, 1, 0);
+ /* All done; restore the line map from <command line>. */
+ _cpp_do_file_change (pfile, LC_RENAME,
+ pfile->line_maps.maps[0].to_file, 1, 0);
+ /* Don't come back here again. */
+ pfile->next_include_file = NULL;
}
}
-
- return pushed;
}
-/* Use mkdeps.c to output dependency information. */
-static void
-output_deps (pfile)
+/* This is called at the end of preprocessing. It pops the last
+ buffer and writes dependency output, and returns the number of
+ errors.
+
+ Maybe it should also reset state, such that you could call
+ cpp_start_read with a new filename to restart processing. */
+int
+cpp_finish (pfile, deps_stream)
cpp_reader *pfile;
+ FILE *deps_stream;
{
- /* Stream on which to print the dependency information. */
- FILE *deps_stream = 0;
- const char *const deps_mode =
- CPP_OPTION (pfile, print_deps_append) ? "a" : "w";
+ /* Warn about unused macros before popping the final buffer. */
+ if (CPP_OPTION (pfile, warn_unused_macros))
+ cpp_forall_identifiers (pfile, _cpp_warn_if_unused_macro, NULL);
- if (CPP_OPTION (pfile, deps_file)[0] == '\0')
- deps_stream = stdout;
- else
- {
- deps_stream = fopen (CPP_OPTION (pfile, deps_file), deps_mode);
- if (deps_stream == 0)
- {
- cpp_notice_from_errno (pfile, CPP_OPTION (pfile, deps_file));
- return;
- }
- }
-
- deps_write (pfile->deps, deps_stream, 72);
-
- if (CPP_OPTION (pfile, deps_phony_targets))
- deps_phony_targets (pfile->deps, deps_stream);
-
- /* Don't close stdout. */
- if (deps_stream != stdout)
- {
- if (ferror (deps_stream) || fclose (deps_stream) != 0)
- cpp_fatal (pfile, "I/O error on output");
- }
-}
-
-/* This is called at the end of preprocessing. It pops the
- last buffer and writes dependency output. It should also
- clear macro definitions, such that you could call cpp_start_read
- with a new filename to restart processing. */
-void
-cpp_finish (pfile)
- cpp_reader *pfile;
-{
/* cpplex.c leaves the final buffer on the stack. This it so that
it returns an unending stream of CPP_EOFs to the client. If we
popped the buffer, we'd dereference a NULL buffer pointer and
@@ -1187,13 +1125,21 @@ cpp_finish (pfile)
while (pfile->buffer)
_cpp_pop_buffer (pfile);
- /* Don't write the deps file if preprocessing has failed. */
- if (CPP_OPTION (pfile, print_deps) && pfile->errors == 0)
- output_deps (pfile);
+ /* Don't write the deps file if there are errors. */
+ if (CPP_OPTION (pfile, deps.style) != DEPS_NONE
+ && deps_stream && pfile->errors == 0)
+ {
+ deps_write (pfile->deps, deps_stream, 72);
+
+ if (CPP_OPTION (pfile, deps.phony_targets))
+ deps_phony_targets (pfile->deps, deps_stream);
+ }
/* Report on headers that could use multiple include guards. */
if (CPP_OPTION (pfile, print_include_names))
_cpp_report_missing_guards (pfile);
+
+ return pfile->errors;
}
/* Add a directive to be handled later in the initialization phase. */
@@ -1215,86 +1161,26 @@ new_pending_directive (pend, text, handler)
/* Irix6 "cc -n32" and OSF4 cc have problems with char foo[] = ("string");
I.e. a const string initializer with parens around it. That is
what N_("string") resolves to, so we make no_* be macros instead. */
-#define no_arg N_("argument missing after %s")
#define no_ass N_("assertion missing after %s")
#define no_dir N_("directory name missing after %s")
#define no_fil N_("file name missing after %s")
#define no_mac N_("macro name missing after %s")
#define no_pth N_("path name missing after %s")
-#define no_num N_("number missing after %s")
-#define no_tgt N_("target missing after %s")
/* This is the list of all command line options, with the leading
"-" removed. It must be sorted in ASCII collating order. */
#define COMMAND_LINE_OPTIONS \
- DEF_OPT("$", 0, OPT_dollar) \
- DEF_OPT("+", 0, OPT_plus) \
- DEF_OPT("-help", 0, OPT__help) \
- DEF_OPT("-target-help", 0, OPT_target__help) \
- DEF_OPT("-version", 0, OPT__version) \
DEF_OPT("A", no_ass, OPT_A) \
- DEF_OPT("C", 0, OPT_C) \
DEF_OPT("D", no_mac, OPT_D) \
- DEF_OPT("H", 0, OPT_H) \
DEF_OPT("I", no_dir, OPT_I) \
- DEF_OPT("M", 0, OPT_M) \
- DEF_OPT("MD", no_fil, OPT_MD) \
- DEF_OPT("MF", no_fil, OPT_MF) \
- DEF_OPT("MG", 0, OPT_MG) \
- DEF_OPT("MM", 0, OPT_MM) \
- DEF_OPT("MMD", no_fil, OPT_MMD) \
- DEF_OPT("MP", 0, OPT_MP) \
- DEF_OPT("MQ", no_tgt, OPT_MQ) \
- DEF_OPT("MT", no_tgt, OPT_MT) \
- DEF_OPT("P", 0, OPT_P) \
DEF_OPT("U", no_mac, OPT_U) \
- DEF_OPT("W", no_arg, OPT_W) /* arg optional */ \
- DEF_OPT("d", no_arg, OPT_d) \
- DEF_OPT("fleading-underscore", 0, OPT_fleading_underscore) \
- DEF_OPT("fno-leading-underscore", 0, OPT_fno_leading_underscore) \
- DEF_OPT("fno-operator-names", 0, OPT_fno_operator_names) \
- DEF_OPT("fno-preprocessed", 0, OPT_fno_preprocessed) \
- DEF_OPT("fno-show-column", 0, OPT_fno_show_column) \
- DEF_OPT("fpreprocessed", 0, OPT_fpreprocessed) \
- DEF_OPT("fshow-column", 0, OPT_fshow_column) \
- DEF_OPT("fsigned-char", 0, OPT_fsigned_char) \
- DEF_OPT("ftabstop=", no_num, OPT_ftabstop) \
- DEF_OPT("funsigned-char", 0, OPT_funsigned_char) \
- DEF_OPT("h", 0, OPT_h) \
DEF_OPT("idirafter", no_dir, OPT_idirafter) \
DEF_OPT("imacros", no_fil, OPT_imacros) \
DEF_OPT("include", no_fil, OPT_include) \
DEF_OPT("iprefix", no_pth, OPT_iprefix) \
DEF_OPT("isystem", no_dir, OPT_isystem) \
DEF_OPT("iwithprefix", no_dir, OPT_iwithprefix) \
- DEF_OPT("iwithprefixbefore", no_dir, OPT_iwithprefixbefore) \
- DEF_OPT("lang-asm", 0, OPT_lang_asm) \
- DEF_OPT("lang-c", 0, OPT_lang_c) \
- DEF_OPT("lang-c++", 0, OPT_lang_cplusplus) \
- DEF_OPT("lang-c89", 0, OPT_lang_c89) \
- DEF_OPT("lang-objc", 0, OPT_lang_objc) \
- DEF_OPT("lang-objc++", 0, OPT_lang_objcplusplus) \
- DEF_OPT("nostdinc", 0, OPT_nostdinc) \
- DEF_OPT("nostdinc++", 0, OPT_nostdincplusplus) \
- DEF_OPT("o", no_fil, OPT_o) \
- DEF_OPT("pedantic", 0, OPT_pedantic) \
- DEF_OPT("pedantic-errors", 0, OPT_pedantic_errors) \
- DEF_OPT("remap", 0, OPT_remap) \
- DEF_OPT("std=c++98", 0, OPT_std_cplusplus98) \
- DEF_OPT("std=c89", 0, OPT_std_c89) \
- DEF_OPT("std=c99", 0, OPT_std_c99) \
- DEF_OPT("std=c9x", 0, OPT_std_c9x) \
- DEF_OPT("std=gnu89", 0, OPT_std_gnu89) \
- DEF_OPT("std=gnu99", 0, OPT_std_gnu99) \
- DEF_OPT("std=gnu9x", 0, OPT_std_gnu9x) \
- DEF_OPT("std=iso9899:1990", 0, OPT_std_iso9899_1990) \
- DEF_OPT("std=iso9899:199409", 0, OPT_std_iso9899_199409) \
- DEF_OPT("std=iso9899:1999", 0, OPT_std_iso9899_1999) \
- DEF_OPT("std=iso9899:199x", 0, OPT_std_iso9899_199x) \
- DEF_OPT("trigraphs", 0, OPT_trigraphs) \
- DEF_OPT("v", 0, OPT_v) \
- DEF_OPT("version", 0, OPT_version) \
- DEF_OPT("w", 0, OPT_w)
+ DEF_OPT("iwithprefixbefore", no_dir, OPT_iwithprefixbefore)
#define DEF_OPT(text, msg, code) code,
enum opt_code
@@ -1328,10 +1214,7 @@ static const struct cl_option cl_options[] =
command-line matches. Returns its index in the option array,
negative on failure. Complications arise since some options can be
suffixed with an argument, and multiple complete matches can occur,
- e.g. -iwithprefix and -iwithprefixbefore. Moreover, we need to
- accept options beginning with -W that we do not recognise, but not
- to swallow any subsequent command line argument; this is handled as
- special cases in cpp_handle_option. */
+ e.g. -pedantic and -pedantic-errors. */
static int
parse_option (input)
const char *input;
@@ -1390,30 +1273,16 @@ parse_option (input)
/* Handle one command-line option in (argc, argv).
Can be called multiple times, to handle multiple sets of options.
- If ignore is non-zero, this will ignore unrecognized -W* options.
Returns number of strings consumed. */
int
-cpp_handle_option (pfile, argc, argv, ignore)
+cpp_handle_option (pfile, argc, argv)
cpp_reader *pfile;
int argc;
char **argv;
- int ignore;
{
int i = 0;
struct cpp_pending *pend = CPP_OPTION (pfile, pending);
- /* Interpret "-" or a non-option as a file name. */
- if (argv[i][0] != '-' || argv[i][1] == '\0')
- {
- if (CPP_OPTION (pfile, in_fname) == NULL)
- CPP_OPTION (pfile, in_fname) = argv[i];
- else if (CPP_OPTION (pfile, out_fname) == NULL)
- CPP_OPTION (pfile, out_fname) = argv[i];
- else
- cpp_fatal (pfile, "too many filenames. Type %s --help for usage info",
- progname);
- }
- else
{
enum opt_code opt_code;
int opt_index;
@@ -1428,16 +1297,13 @@ cpp_handle_option (pfile, argc, argv, ignore)
if (cl_options[opt_index].msg)
{
arg = &argv[i][cl_options[opt_index].opt_len + 1];
-
- /* Yuk. Special case for -W as it must not swallow
- up any following argument. If this becomes common, add
- another field to the cl_options table. */
- if (arg[0] == '\0' && opt_code != OPT_W)
+ if (arg[0] == '\0')
{
arg = argv[++i];
if (!arg)
{
- cpp_fatal (pfile, cl_options[opt_index].msg, argv[i - 1]);
+ cpp_error (pfile, DL_ERROR,
+ cl_options[opt_index].msg, argv[i - 1]);
return argc;
}
}
@@ -1447,245 +1313,18 @@ cpp_handle_option (pfile, argc, argv, ignore)
{
case N_OPTS: /* Shut GCC up. */
break;
- case OPT_fleading_underscore:
- CPP_OPTION (pfile, user_label_prefix) = "_";
- break;
- case OPT_fno_leading_underscore:
- CPP_OPTION (pfile, user_label_prefix) = "";
- break;
- case OPT_fno_operator_names:
- CPP_OPTION (pfile, operator_names) = 0;
- break;
- case OPT_fpreprocessed:
- CPP_OPTION (pfile, preprocessed) = 1;
- break;
- case OPT_fno_preprocessed:
- CPP_OPTION (pfile, preprocessed) = 0;
- break;
- case OPT_fshow_column:
- CPP_OPTION (pfile, show_column) = 1;
- break;
- case OPT_fno_show_column:
- CPP_OPTION (pfile, show_column) = 0;
- break;
- case OPT_fsigned_char:
- CPP_OPTION (pfile, signed_char) = 1;
- break;
- case OPT_funsigned_char:
- CPP_OPTION (pfile, signed_char) = 0;
- break;
- case OPT_ftabstop:
- /* Silently ignore empty string, non-longs and silly values. */
- if (arg[0] != '\0')
- {
- char *endptr;
- long tabstop = strtol (arg, &endptr, 10);
- if (*endptr == '\0' && tabstop >= 1 && tabstop <= 100)
- CPP_OPTION (pfile, tabstop) = tabstop;
- }
- break;
- case OPT_w:
- CPP_OPTION (pfile, inhibit_warnings) = 1;
- break;
- case OPT_h:
- case OPT__help:
- print_help ();
- CPP_OPTION (pfile, help_only) = 1;
- break;
- case OPT_target__help:
- /* Print if any target specific options. cpplib has none, but
- make sure help_only gets set. */
- CPP_OPTION (pfile, help_only) = 1;
- break;
-
- /* --version inhibits compilation, -version doesn't. -v means
- verbose and -version. Historical reasons, don't ask. */
- case OPT__version:
- CPP_OPTION (pfile, help_only) = 1;
- pfile->print_version = 1;
- break;
- case OPT_v:
- CPP_OPTION (pfile, verbose) = 1;
- pfile->print_version = 1;
- break;
- case OPT_version:
- pfile->print_version = 1;
- break;
- case OPT_C:
- CPP_OPTION (pfile, discard_comments) = 0;
- break;
- case OPT_P:
- CPP_OPTION (pfile, no_line_commands) = 1;
- break;
- case OPT_dollar: /* Don't include $ in identifiers. */
- CPP_OPTION (pfile, dollars_in_ident) = 0;
- break;
- case OPT_H:
- CPP_OPTION (pfile, print_include_names) = 1;
- break;
case OPT_D:
new_pending_directive (pend, arg, cpp_define);
break;
- case OPT_pedantic_errors:
- CPP_OPTION (pfile, pedantic_errors) = 1;
- /* fall through */
- case OPT_pedantic:
- CPP_OPTION (pfile, pedantic) = 1;
- break;
- case OPT_trigraphs:
- CPP_OPTION (pfile, trigraphs) = 1;
- break;
- case OPT_plus:
- CPP_OPTION (pfile, cplusplus) = 1;
- CPP_OPTION (pfile, cplusplus_comments) = 1;
- break;
- case OPT_remap:
- CPP_OPTION (pfile, remap) = 1;
- break;
case OPT_iprefix:
CPP_OPTION (pfile, include_prefix) = arg;
CPP_OPTION (pfile, include_prefix_len) = strlen (arg);
break;
- case OPT_lang_c:
- set_lang (pfile, CLK_GNUC89);
- break;
- case OPT_lang_cplusplus:
- set_lang (pfile, CLK_GNUCXX);
- break;
- case OPT_lang_objc:
- set_lang (pfile, CLK_OBJC);
- break;
- case OPT_lang_objcplusplus:
- set_lang (pfile, CLK_OBJCXX);
- break;
- case OPT_lang_asm:
- set_lang (pfile, CLK_ASM);
- break;
- case OPT_std_cplusplus98:
- set_lang (pfile, CLK_CXX98);
- break;
- case OPT_std_gnu89:
- set_lang (pfile, CLK_GNUC89);
- break;
- case OPT_std_gnu9x:
- case OPT_std_gnu99:
- set_lang (pfile, CLK_GNUC99);
- break;
- case OPT_std_iso9899_199409:
- set_lang (pfile, CLK_STDC94);
- break;
- case OPT_std_iso9899_1990:
- case OPT_std_c89:
- case OPT_lang_c89:
- set_lang (pfile, CLK_STDC89);
- break;
- case OPT_std_iso9899_199x:
- case OPT_std_iso9899_1999:
- case OPT_std_c9x:
- case OPT_std_c99:
- set_lang (pfile, CLK_STDC99);
- break;
- case OPT_nostdinc:
- /* -nostdinc causes no default include directories.
- You must specify all include-file directories with -I. */
- CPP_OPTION (pfile, no_standard_includes) = 1;
- break;
- case OPT_nostdincplusplus:
- /* -nostdinc++ causes no default C++-specific include directories. */
- CPP_OPTION (pfile, no_standard_cplusplus_includes) = 1;
- break;
- case OPT_o:
- if (CPP_OPTION (pfile, out_fname) == NULL)
- CPP_OPTION (pfile, out_fname) = arg;
- else
- {
- cpp_fatal (pfile, "output filename specified twice");
- return argc;
- }
- break;
- case OPT_d:
- /* Args to -d specify what parts of macros to dump.
- Silently ignore unrecognised options; they may
- be aimed at the compiler proper. */
- {
- char c;
-
- while ((c = *arg++) != '\0')
- switch (c)
- {
- case 'M':
- CPP_OPTION (pfile, dump_macros) = dump_only;
- break;
- case 'N':
- CPP_OPTION (pfile, dump_macros) = dump_names;
- break;
- case 'D':
- CPP_OPTION (pfile, dump_macros) = dump_definitions;
- break;
- case 'I':
- CPP_OPTION (pfile, dump_includes) = 1;
- break;
- }
- }
- break;
-
- case OPT_MG:
- CPP_OPTION (pfile, print_deps_missing_files) = 1;
- break;
- case OPT_M:
- /* When doing dependencies with -M or -MM, suppress normal
- preprocessed output, but still do -dM etc. as software
- depends on this. Preprocessed output occurs if -MD, -MMD
- or environment var dependency generation is used. */
- CPP_OPTION (pfile, print_deps) = 2;
- CPP_OPTION (pfile, no_output) = 1;
- break;
- case OPT_MM:
- CPP_OPTION (pfile, print_deps) = 1;
- CPP_OPTION (pfile, no_output) = 1;
- break;
- case OPT_MF:
- CPP_OPTION (pfile, deps_file) = arg;
- break;
- case OPT_MP:
- CPP_OPTION (pfile, deps_phony_targets) = 1;
- break;
- case OPT_MQ:
- case OPT_MT:
- /* Add a target. -MQ quotes for Make. */
- deps_add_target (pfile->deps, arg, opt_code == OPT_MQ);
- break;
-
- case OPT_MD:
- CPP_OPTION (pfile, print_deps) = 2;
- CPP_OPTION (pfile, deps_file) = arg;
- break;
- case OPT_MMD:
- CPP_OPTION (pfile, print_deps) = 1;
- CPP_OPTION (pfile, deps_file) = arg;
- break;
case OPT_A:
if (arg[0] == '-')
- {
- /* -A with an argument beginning with '-' acts as
- #unassert on whatever immediately follows the '-'.
- If "-" is the whole argument, we eliminate all
- predefined macros and assertions, including those
- that were specified earlier on the command line.
- That way we can get rid of any that were passed
- automatically in from GCC. */
-
- if (arg[1] == '\0')
- {
- free_chain (pend->directive_head);
- pend->directive_head = NULL;
- pend->directive_tail = NULL;
- }
- else
- new_pending_directive (pend, arg + 1, cpp_unassert);
- }
+ new_pending_directive (pend, arg + 1, cpp_unassert);
else
new_pending_directive (pend, arg, cpp_assert);
break;
@@ -1694,7 +1333,7 @@ cpp_handle_option (pfile, argc, argv, ignore)
break;
case OPT_I: /* Add directory to path for includes. */
if (!strcmp (arg, "-"))
- {
+ {
/* -I- means:
Use the preceding -I directories for #include "..."
but not #include <...>.
@@ -1711,11 +1350,11 @@ cpp_handle_option (pfile, argc, argv, ignore)
}
else
{
- cpp_fatal (pfile, "-I- specified twice");
+ cpp_error (pfile, DL_ERROR, "-I- specified twice");
return argc;
}
- }
- else
+ }
+ else
append_include_chain (pfile, xstrdup (arg), BRACKET, 0);
break;
case OPT_isystem:
@@ -1774,49 +1413,7 @@ cpp_handle_option (pfile, argc, argv, ignore)
/* Add directory to end of path for includes. */
append_include_chain (pfile, xstrdup (arg), AFTER, 0);
break;
- case OPT_W:
- /* Silently ignore unrecognised options. */
- if (!strcmp (argv[i], "-Wall"))
- {
- CPP_OPTION (pfile, warn_trigraphs) = 1;
- CPP_OPTION (pfile, warn_comments) = 1;
- }
- else if (!strcmp (argv[i], "-Wtraditional"))
- CPP_OPTION (pfile, warn_traditional) = 1;
- else if (!strcmp (argv[i], "-Wtrigraphs"))
- CPP_OPTION (pfile, warn_trigraphs) = 1;
- else if (!strcmp (argv[i], "-Wcomment"))
- CPP_OPTION (pfile, warn_comments) = 1;
- else if (!strcmp (argv[i], "-Wcomments"))
- CPP_OPTION (pfile, warn_comments) = 1;
- else if (!strcmp (argv[i], "-Wundef"))
- CPP_OPTION (pfile, warn_undef) = 1;
- else if (!strcmp (argv[i], "-Wimport"))
- CPP_OPTION (pfile, warn_import) = 1;
- else if (!strcmp (argv[i], "-Werror"))
- CPP_OPTION (pfile, warnings_are_errors) = 1;
- else if (!strcmp (argv[i], "-Wsystem-headers"))
- CPP_OPTION (pfile, warn_system_headers) = 1;
- else if (!strcmp (argv[i], "-Wno-traditional"))
- CPP_OPTION (pfile, warn_traditional) = 0;
- else if (!strcmp (argv[i], "-Wno-trigraphs"))
- CPP_OPTION (pfile, warn_trigraphs) = 0;
- else if (!strcmp (argv[i], "-Wno-comment"))
- CPP_OPTION (pfile, warn_comments) = 0;
- else if (!strcmp (argv[i], "-Wno-comments"))
- CPP_OPTION (pfile, warn_comments) = 0;
- else if (!strcmp (argv[i], "-Wno-undef"))
- CPP_OPTION (pfile, warn_undef) = 0;
- else if (!strcmp (argv[i], "-Wno-import"))
- CPP_OPTION (pfile, warn_import) = 0;
- else if (!strcmp (argv[i], "-Wno-error"))
- CPP_OPTION (pfile, warnings_are_errors) = 0;
- else if (!strcmp (argv[i], "-Wno-system-headers"))
- CPP_OPTION (pfile, warn_system_headers) = 0;
- else if (! ignore)
- return i;
- break;
- }
+ }
}
return i + 1;
}
@@ -1836,7 +1433,7 @@ cpp_handle_options (pfile, argc, argv)
for (i = 0; i < argc; i += strings_processed)
{
- strings_processed = cpp_handle_option (pfile, argc - i, argv + i, 1);
+ strings_processed = cpp_handle_option (pfile, argc - i, argv + i);
if (strings_processed == 0)
break;
}
@@ -1844,227 +1441,23 @@ cpp_handle_options (pfile, argc, argv)
return i;
}
-/* Extra processing when all options are parsed, after all calls to
- cpp_handle_option[s]. Consistency checks etc. */
-void
-cpp_post_options (pfile)
+static void
+post_options (pfile)
cpp_reader *pfile;
{
- if (pfile->print_version)
- {
- fprintf (stderr, _("GNU CPP version %s (cpplib)"), version_string);
-#ifdef TARGET_VERSION
- TARGET_VERSION;
-#endif
- fputc ('\n', stderr);
- }
-
- /* Canonicalize in_fname and out_fname. We guarantee they are not
- NULL, and that the empty string represents stdin / stdout. */
- if (CPP_OPTION (pfile, in_fname) == NULL
- || !strcmp (CPP_OPTION (pfile, in_fname), "-"))
- CPP_OPTION (pfile, in_fname) = "";
-
- if (CPP_OPTION (pfile, out_fname) == NULL
- || !strcmp (CPP_OPTION (pfile, out_fname), "-"))
- CPP_OPTION (pfile, out_fname) = "";
-
/* -Wtraditional is not useful in C++ mode. */
if (CPP_OPTION (pfile, cplusplus))
CPP_OPTION (pfile, warn_traditional) = 0;
- /* Set this if it hasn't been set already. */
- if (CPP_OPTION (pfile, user_label_prefix) == NULL)
- CPP_OPTION (pfile, user_label_prefix) = USER_LABEL_PREFIX;
-
/* Permanently disable macro expansion if we are rescanning
- preprocessed text. */
+ preprocessed text. Read preprocesed source in ISO mode. */
if (CPP_OPTION (pfile, preprocessed))
- pfile->state.prevent_expansion = 1;
-
- /* -dM makes no normal output. This is set here so that -dM -dD
- works as expected. */
- if (CPP_OPTION (pfile, dump_macros) == dump_only)
- CPP_OPTION (pfile, no_output) = 1;
-
- /* Disable -dD, -dN and -dI if we should make no normal output
- (such as with -M). Allow -M -dM since some software relies on
- this. */
- if (CPP_OPTION (pfile, no_output))
{
- if (CPP_OPTION (pfile, dump_macros) != dump_only)
- CPP_OPTION (pfile, dump_macros) = dump_none;
- CPP_OPTION (pfile, dump_includes) = 0;
+ pfile->state.prevent_expansion = 1;
+ CPP_OPTION (pfile, traditional) = 0;
}
- /* We need to do this after option processing and before
- cpp_start_read, as cppmain.c relies on the options->no_output to
- set its callbacks correctly before calling cpp_start_read. */
- init_dependency_output (pfile);
-
- /* After checking the environment variables, check if -M or -MM has
- not been specified, but other -M options have. */
- if (CPP_OPTION (pfile, print_deps) == 0 &&
- (CPP_OPTION (pfile, print_deps_missing_files)
- || CPP_OPTION (pfile, deps_file)
- || CPP_OPTION (pfile, deps_phony_targets)))
- cpp_fatal (pfile, "you must additionally specify either -M or -MM");
-}
-
-/* Set up dependency-file output. On exit, if print_deps is non-zero
- then deps_file is not NULL; stdout is the empty string. */
-static void
-init_dependency_output (pfile)
- cpp_reader *pfile;
-{
- char *spec, *s, *output_file;
-
- /* Either of two environment variables can specify output of deps.
- Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET",
- where OUTPUT_FILE is the file to write deps info to
- and DEPS_TARGET is the target to mention in the deps. */
-
- if (CPP_OPTION (pfile, print_deps) == 0)
- {
- spec = getenv ("DEPENDENCIES_OUTPUT");
- if (spec)
- CPP_OPTION (pfile, print_deps) = 1;
- else
- {
- spec = getenv ("SUNPRO_DEPENDENCIES");
- if (spec)
- {
- CPP_OPTION (pfile, print_deps) = 2;
- CPP_OPTION (pfile, deps_ignore_main_file) = 1;
- }
- else
- return;
- }
-
- /* Find the space before the DEPS_TARGET, if there is one. */
- s = strchr (spec, ' ');
- if (s)
- {
- /* Let the caller perform MAKE quoting. */
- deps_add_target (pfile->deps, s + 1, 0);
- output_file = (char *) xmalloc (s - spec + 1);
- memcpy (output_file, spec, s - spec);
- output_file[s - spec] = 0;
- }
- else
- output_file = spec;
-
- /* Command line -MF overrides environment variables and default. */
- if (CPP_OPTION (pfile, deps_file) == 0)
- CPP_OPTION (pfile, deps_file) = output_file;
-
- CPP_OPTION (pfile, print_deps_append) = 1;
- }
- else if (CPP_OPTION (pfile, deps_file) == 0)
- /* If -M or -MM was seen without -MF, default output to wherever
- was specified with -o. out_fname is non-NULL here. */
- CPP_OPTION (pfile, deps_file) = CPP_OPTION (pfile, out_fname);
-}
-
-/* Handle --help output. */
-static void
-print_help ()
-{
- /* To keep the lines from getting too long for some compilers, limit
- to about 500 characters (6 lines) per chunk. */
- fputs (_("\
-Switches:\n\
- -include <file> Include the contents of <file> before other files\n\
- -imacros <file> Accept definition of macros in <file>\n\
- -iprefix <path> Specify <path> as a prefix for next two options\n\
- -iwithprefix <dir> Add <dir> to the end of the system include path\n\
- -iwithprefixbefore <dir> Add <dir> to the end of the main include path\n\
- -isystem <dir> Add <dir> to the start of the system include path\n\
-"), stdout);
- fputs (_("\
- -idirafter <dir> Add <dir> to the end of the system include path\n\
- -I <dir> Add <dir> to the end of the main include path\n\
- -I- Fine-grained include path control; see info docs\n\
- -nostdinc Do not search system include directories\n\
- (dirs specified with -isystem will still be used)\n\
- -nostdinc++ Do not search system include directories for C++\n\
- -o <file> Put output into <file>\n\
-"), stdout);
- fputs (_("\
- -pedantic Issue all warnings demanded by strict ISO C\n\
- -pedantic-errors Issue -pedantic warnings as errors instead\n\
- -trigraphs Support ISO C trigraphs\n\
- -lang-c Assume that the input sources are in C\n\
- -lang-c89 Assume that the input sources are in C89\n\
-"), stdout);
- fputs (_("\
- -lang-c++ Assume that the input sources are in C++\n\
- -lang-objc Assume that the input sources are in ObjectiveC\n\
- -lang-objc++ Assume that the input sources are in ObjectiveC++\n\
- -lang-asm Assume that the input sources are in assembler\n\
-"), stdout);
- fputs (_("\
- -std=<std name> Specify the conformance standard; one of:\n\
- gnu89, gnu99, c89, c99, iso9899:1990,\n\
- iso9899:199409, iso9899:1999\n\
- -+ Allow parsing of C++ style features\n\
- -w Inhibit warning messages\n\
- -Wtrigraphs Warn if trigraphs are encountered\n\
- -Wno-trigraphs Do not warn about trigraphs\n\
- -Wcomment{s} Warn if one comment starts inside another\n\
-"), stdout);
- fputs (_("\
- -Wno-comment{s} Do not warn about comments\n\
- -Wtraditional Warn about features not present in traditional C\n\
- -Wno-traditional Do not warn about traditional C\n\
- -Wundef Warn if an undefined macro is used by #if\n\
- -Wno-undef Do not warn about testing undefined macros\n\
- -Wimport Warn about the use of the #import directive\n\
-"), stdout);
- fputs (_("\
- -Wno-import Do not warn about the use of #import\n\
- -Werror Treat all warnings as errors\n\
- -Wno-error Do not treat warnings as errors\n\
- -Wsystem-headers Do not suppress warnings from system headers\n\
- -Wno-system-headers Suppress warnings from system headers\n\
- -Wall Enable all preprocessor warnings\n\
-"), stdout);
- fputs (_("\
- -M Generate make dependencies\n\
- -MM As -M, but ignore system header files\n\
- -MD Generate make dependencies and compile\n\
- -MMD As -MD, but ignore system header files\n\
- -MF <file> Write dependency output to the given file\n\
- -MG Treat missing header file as generated files\n\
-"), stdout);
- fputs (_("\
- -MP Generate phony targets for all headers\n\
- -MQ <target> Add a MAKE-quoted target\n\
- -MT <target> Add an unquoted target\n\
-"), stdout);
- fputs (_("\
- -D<macro> Define a <macro> with string '1' as its value\n\
- -D<macro>=<val> Define a <macro> with <val> as its value\n\
- -A<question>=<answer> Assert the <answer> to <question>\n\
- -A-<question>=<answer> Disable the <answer> to <question>\n\
- -U<macro> Undefine <macro> \n\
- -v Display the version number\n\
-"), stdout);
- fputs (_("\
- -H Print the name of header files as they are used\n\
- -C Do not discard comments\n\
- -dM Display a list of macro definitions active at end\n\
- -dD Preserve macro definitions in output\n\
- -dN As -dD except that only the names are preserved\n\
- -dI Include #include directives in the output\n\
-"), stdout);
- fputs (_("\
- -fpreprocessed Treat the input file as already preprocessed\n\
- -ftabstop=<number> Distance between tab stops for column reporting\n\
- -P Do not generate #line directives\n\
- -$ Do not allow '$' in identifiers\n\
- -remap Remap file names when including files\n\
- --version Display version information\n\
- -h or --help Display this information\n\
-"), stdout);
+ /* Traditional CPP does not accurately track column information. */
+ if (CPP_OPTION (pfile, traditional))
+ CPP_OPTION (pfile, show_column) = 0;
}
diff --git a/contrib/gcc/cpplex.c b/contrib/gcc/cpplex.c
index eea6a9e..7db6b24 100644
--- a/contrib/gcc/cpplex.c
+++ b/contrib/gcc/cpplex.c
@@ -25,13 +25,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "cpplib.h"
#include "cpphash.h"
-/* MULTIBYTE_CHARS support only works for native compilers.
- ??? Ideally what we want is to model widechar support after
- the current floating point support. */
-#ifdef CROSS_COMPILE
-#undef MULTIBYTE_CHARS
-#endif
-
#ifdef MULTIBYTE_CHARS
#include "mbchar.h"
#include <locale.h>
@@ -77,17 +70,18 @@ static int skip_line_comment PARAMS ((cpp_reader *));
static void adjust_column PARAMS ((cpp_reader *));
static int skip_whitespace PARAMS ((cpp_reader *, cppchar_t));
static cpp_hashnode *parse_identifier PARAMS ((cpp_reader *));
-static cpp_hashnode *parse_identifier_slow PARAMS ((cpp_reader *,
- const U_CHAR *));
-static void parse_number PARAMS ((cpp_reader *, cpp_string *, cppchar_t, int));
-static int unescaped_terminator_p PARAMS ((cpp_reader *, const U_CHAR *));
+static uchar *parse_slow PARAMS ((cpp_reader *, const uchar *, int,
+ unsigned int *));
+static void parse_number PARAMS ((cpp_reader *, cpp_string *, int));
+static int unescaped_terminator_p PARAMS ((cpp_reader *, const uchar *));
static void parse_string PARAMS ((cpp_reader *, cpp_token *, cppchar_t));
-static void unterminated PARAMS ((cpp_reader *, int));
static bool trigraph_p PARAMS ((cpp_reader *));
-static void save_comment PARAMS ((cpp_reader *, cpp_token *, const U_CHAR *));
+static void save_comment PARAMS ((cpp_reader *, cpp_token *, const uchar *,
+ cppchar_t));
+static bool continue_after_nul PARAMS ((cpp_reader *));
static int name_p PARAMS ((cpp_reader *, const cpp_string *));
static int maybe_read_ucs PARAMS ((cpp_reader *, const unsigned char **,
- const unsigned char *, unsigned int *));
+ const unsigned char *, cppchar_t *));
static tokenrun *next_tokenrun PARAMS ((tokenrun *));
static unsigned int hex_digit_value PARAMS ((unsigned int));
@@ -105,7 +99,7 @@ cpp_ideq (token, string)
if (token->type != CPP_NAME)
return 0;
- return !ustrcmp (NODE_NAME (token->val.node), (const U_CHAR *) string);
+ return !ustrcmp (NODE_NAME (token->val.node), (const uchar *) string);
}
/* Call when meeting a newline, assumed to be in buffer->cur[-1].
@@ -118,7 +112,7 @@ handle_newline (pfile)
cpp_buffer *buffer = pfile->buffer;
/* Handle CR-LF and LF-CR. Most other implementations (e.g. java)
- only accept CR-LF; maybe we should fall back to that behaviour? */
+ only accept CR-LF; maybe we should fall back to that behavior? */
if (buffer->cur[-1] + buffer->cur[0] == '\r' + '\n')
buffer->cur++;
@@ -132,7 +126,7 @@ handle_newline (pfile)
the second '?'.
Warn if necessary, and returns true if the sequence forms a
- trigraph and the trigraph should be honoured. */
+ trigraph and the trigraph should be honored. */
static bool
trigraph_p (pfile)
cpp_reader *pfile;
@@ -150,16 +144,17 @@ trigraph_p (pfile)
if (CPP_OPTION (pfile, warn_trigraphs) && !pfile->state.lexing_comment)
{
if (accept)
- cpp_warning_with_line (pfile, pfile->line, CPP_BUF_COL (buffer) - 1,
- "trigraph ??%c converted to %c",
- (int) from_char,
- (int) _cpp_trigraph_map[from_char]);
+ cpp_error_with_line (pfile, DL_WARNING,
+ pfile->line, CPP_BUF_COL (buffer) - 1,
+ "trigraph ??%c converted to %c",
+ (int) from_char,
+ (int) _cpp_trigraph_map[from_char]);
else if (buffer->cur != buffer->last_Wtrigraphs)
{
buffer->last_Wtrigraphs = buffer->cur;
- cpp_warning_with_line (pfile, pfile->line,
- CPP_BUF_COL (buffer) - 1,
- "trigraph ??%c ignored", (int) from_char);
+ cpp_error_with_line (pfile, DL_WARNING,
+ pfile->line, CPP_BUF_COL (buffer) - 1,
+ "trigraph ??%c ignored", (int) from_char);
}
}
@@ -215,13 +210,15 @@ skip_escaped_newlines (pfile)
if (saved_cur != buffer->cur - 1
&& !pfile->state.lexing_comment)
- cpp_warning (pfile, "backslash and newline separated by space");
+ cpp_error (pfile, DL_WARNING,
+ "backslash and newline separated by space");
handle_newline (pfile);
buffer->backup_to = buffer->cur;
if (buffer->cur == buffer->rlimit)
{
- cpp_pedwarn (pfile, "backslash-newline at end of file");
+ cpp_error (pfile, DL_PEDWARN,
+ "backslash-newline at end of file");
next = EOF;
}
else
@@ -250,12 +247,12 @@ get_effective_char (pfile)
if (__builtin_expect (next == '?' || next == '\\', 0))
next = skip_escaped_newlines (pfile);
- return next;
+ return next;
}
/* Skip a C-style block comment. We find the end of the comment by
seeing if an asterisk is before every '/' we encounter. Returns
- non-zero if comment terminated by EOF, zero otherwise. */
+ nonzero if comment terminated by EOF, zero otherwise. */
static int
skip_block_comment (pfile)
cpp_reader *pfile;
@@ -285,9 +282,9 @@ skip_block_comment (pfile)
Don't bother to get it right across escaped newlines. */
if (CPP_OPTION (pfile, warn_comments)
&& buffer->cur[0] == '*' && buffer->cur[1] != '/')
- cpp_warning_with_line (pfile,
- pfile->line, CPP_BUF_COL (buffer),
- "\"/*\" within comment");
+ cpp_error_with_line (pfile, DL_WARNING,
+ pfile->line, CPP_BUF_COL (buffer),
+ "\"/*\" within comment");
}
else if (is_vspace (c))
handle_newline (pfile);
@@ -300,7 +297,7 @@ skip_block_comment (pfile)
}
/* Skip a C++ line comment, leaving buffer->cur pointing to the
- terminating newline. Handles escaped newlines. Returns non-zero
+ terminating newline. Handles escaped newlines. Returns nonzero
if a multiline comment. */
static int
skip_line_comment (pfile)
@@ -309,14 +306,39 @@ skip_line_comment (pfile)
cpp_buffer *buffer = pfile->buffer;
unsigned int orig_line = pfile->line;
cppchar_t c;
+#ifdef MULTIBYTE_CHARS
+ wchar_t wc;
+ int char_len;
+#endif
pfile->state.lexing_comment = 1;
+#ifdef MULTIBYTE_CHARS
+ /* Reset multibyte conversion state. */
+ (void) local_mbtowc (NULL, NULL, 0);
+#endif
do
{
if (buffer->cur == buffer->rlimit)
goto at_eof;
+#ifdef MULTIBYTE_CHARS
+ char_len = local_mbtowc (&wc, (const char *) buffer->cur,
+ buffer->rlimit - buffer->cur);
+ if (char_len == -1)
+ {
+ cpp_error (pfile, DL_WARNING,
+ "ignoring invalid multibyte character");
+ char_len = 1;
+ c = *buffer->cur++;
+ }
+ else
+ {
+ buffer->cur += char_len;
+ c = wc;
+ }
+#else
c = *buffer->cur++;
+#endif
if (c == '?' || c == '\\')
c = skip_escaped_newlines (pfile);
}
@@ -370,15 +392,15 @@ skip_whitespace (pfile, c)
return 0;
if (!warned)
{
- cpp_warning (pfile, "null character(s) ignored");
+ cpp_error (pfile, DL_WARNING, "null character(s) ignored");
warned = 1;
}
}
else if (pfile->state.in_directive && CPP_PEDANTIC (pfile))
- cpp_pedwarn_with_line (pfile, pfile->line,
- CPP_BUF_COL (buffer),
- "%s in preprocessing directive",
- c == '\f' ? "form feed" : "vertical tab");
+ cpp_error_with_line (pfile, DL_PEDWARN, pfile->line,
+ CPP_BUF_COL (buffer),
+ "%s in preprocessing directive",
+ c == '\f' ? "form feed" : "vertical tab");
c = *buffer->cur++;
}
@@ -402,7 +424,7 @@ name_p (pfile, string)
if (!is_idchar (string->text[i]))
return 0;
- return 1;
+ return 1;
}
/* Parse an identifier, skipping embedded backslash-newlines. This is
@@ -412,13 +434,13 @@ name_p (pfile, string)
seen:unseen identifiers in normal code; the distribution is
Poisson-like). Second most common case is a new identifier, not
split and no dollar sign. The other possibilities are rare and
- have been relegated to parse_identifier_slow. */
+ have been relegated to parse_slow. */
static cpp_hashnode *
parse_identifier (pfile)
cpp_reader *pfile;
{
cpp_hashnode *result;
- const U_CHAR *cur;
+ const uchar *cur, *base;
/* Fast-path loop. Skim over a normal identifier.
N.B. ISIDNUM does not include $. */
@@ -428,13 +450,19 @@ parse_identifier (pfile)
/* Check for slow-path cases. */
if (*cur == '?' || *cur == '\\' || *cur == '$')
- result = parse_identifier_slow (pfile, cur);
+ {
+ unsigned int len;
+
+ base = parse_slow (pfile, cur, 0, &len);
+ result = (cpp_hashnode *)
+ ht_lookup (pfile->hash_table, base, len, HT_ALLOCED);
+ }
else
{
- const U_CHAR *base = pfile->buffer->cur - 1;
+ base = pfile->buffer->cur - 1;
+ pfile->buffer->cur = cur;
result = (cpp_hashnode *)
ht_lookup (pfile->hash_table, base, cur - base, HT_ALLOC);
- pfile->buffer->cur = cur;
}
/* Rarely, identifiers require diagnostics when lexed.
@@ -444,59 +472,78 @@ parse_identifier (pfile)
{
/* It is allowed to poison the same identifier twice. */
if ((result->flags & NODE_POISONED) && !pfile->state.poisoned_ok)
- cpp_error (pfile, "attempt to use poisoned \"%s\"",
+ cpp_error (pfile, DL_ERROR, "attempt to use poisoned \"%s\"",
NODE_NAME (result));
/* Constraint 6.10.3.5: __VA_ARGS__ should only appear in the
replacement list of a variadic macro. */
if (result == pfile->spec_nodes.n__VA_ARGS__
&& !pfile->state.va_args_ok)
- cpp_pedwarn (pfile,
+ cpp_error (pfile, DL_PEDWARN,
"__VA_ARGS__ can only appear in the expansion of a C99 variadic macro");
}
return result;
}
-/* Slow path. This handles identifiers which have been split, and
- identifiers which contain dollar signs. The part of the identifier
- from PFILE->buffer->cur-1 to CUR has already been scanned. */
-static cpp_hashnode *
-parse_identifier_slow (pfile, cur)
+/* Slow path. This handles numbers and identifiers which have been
+ split, or contain dollar signs. The part of the token from
+ PFILE->buffer->cur-1 to CUR has already been scanned. NUMBER_P is
+ 1 if it's a number, and 2 if it has a leading period. Returns a
+ pointer to the token's NUL-terminated spelling in permanent
+ storage, and sets PLEN to its length. */
+static uchar *
+parse_slow (pfile, cur, number_p, plen)
cpp_reader *pfile;
- const U_CHAR *cur;
+ const uchar *cur;
+ int number_p;
+ unsigned int *plen;
{
cpp_buffer *buffer = pfile->buffer;
- const U_CHAR *base = buffer->cur - 1;
+ const uchar *base = buffer->cur - 1;
struct obstack *stack = &pfile->hash_table->stack;
- unsigned int c, saw_dollar = 0, len;
+ unsigned int c, prevc, saw_dollar = 0;
+
+ /* Place any leading period. */
+ if (number_p == 2)
+ obstack_1grow (stack, '.');
/* Copy the part of the token which is known to be okay. */
obstack_grow (stack, base, cur - base);
/* Now process the part which isn't. We are looking at one of
'$', '\\', or '?' on entry to this loop. */
+ prevc = cur[-1];
c = *cur++;
buffer->cur = cur;
- do
+ for (;;)
{
- while (is_idchar (c))
- {
- obstack_1grow (stack, c);
+ /* Potential escaped newline? */
+ buffer->backup_to = buffer->cur - 1;
+ if (c == '?' || c == '\\')
+ c = skip_escaped_newlines (pfile);
- if (c == '$')
- saw_dollar++;
+ if (!is_idchar (c))
+ {
+ if (!number_p)
+ break;
+ if (c != '.' && !VALID_SIGN (c, prevc))
+ break;
+ }
- c = *buffer->cur++;
- }
+ /* Handle normal identifier characters in this loop. */
+ do
+ {
+ prevc = c;
+ obstack_1grow (stack, c);
- /* Potential escaped newline? */
- buffer->backup_to = buffer->cur - 1;
- if (c != '?' && c != '\\')
- break;
- c = skip_escaped_newlines (pfile);
+ if (c == '$')
+ saw_dollar++;
+
+ c = *buffer->cur++;
+ }
+ while (is_idchar (c));
}
- while (is_idchar (c));
/* Step back over the unwanted char. */
BACKUP ();
@@ -505,94 +552,48 @@ parse_identifier_slow (pfile, cur)
accepted as an extension. Don't warn about it in skipped
conditional blocks. */
if (saw_dollar && CPP_PEDANTIC (pfile) && ! pfile->state.skipping)
- cpp_pedwarn (pfile, "'$' character(s) in identifier");
+ cpp_error (pfile, DL_PEDWARN, "'$' character(s) in identifier or number");
- /* Identifiers are null-terminated. */
- len = obstack_object_size (stack);
+ /* Identifiers and numbers are null-terminated. */
+ *plen = obstack_object_size (stack);
obstack_1grow (stack, '\0');
-
- return (cpp_hashnode *)
- ht_lookup (pfile->hash_table, obstack_finish (stack), len, HT_ALLOCED);
+ return obstack_finish (stack);
}
/* Parse a number, beginning with character C, skipping embedded
- backslash-newlines. LEADING_PERIOD is non-zero if there was a "."
+ backslash-newlines. LEADING_PERIOD is nonzero if there was a "."
before C. Place the result in NUMBER. */
static void
-parse_number (pfile, number, c, leading_period)
+parse_number (pfile, number, leading_period)
cpp_reader *pfile;
cpp_string *number;
- cppchar_t c;
int leading_period;
{
- cpp_buffer *buffer = pfile->buffer;
- unsigned char *dest, *limit;
+ const uchar *cur;
- dest = BUFF_FRONT (pfile->u_buff);
- limit = BUFF_LIMIT (pfile->u_buff);
+ /* Fast-path loop. Skim over a normal number.
+ N.B. ISIDNUM does not include $. */
+ cur = pfile->buffer->cur;
+ while (ISIDNUM (*cur) || *cur == '.' || VALID_SIGN (*cur, cur[-1]))
+ cur++;
- /* Place a leading period. */
- if (leading_period)
- {
- if (dest == limit)
- {
- _cpp_extend_buff (pfile, &pfile->u_buff, 1);
- dest = BUFF_FRONT (pfile->u_buff);
- limit = BUFF_LIMIT (pfile->u_buff);
- }
- *dest++ = '.';
- }
-
- do
+ /* Check for slow-path cases. */
+ if (*cur == '?' || *cur == '\\' || *cur == '$')
+ number->text = parse_slow (pfile, cur, 1 + leading_period, &number->len);
+ else
{
- do
- {
- /* Need room for terminating null. */
- if ((size_t) (limit - dest) < 2)
- {
- size_t len_so_far = dest - BUFF_FRONT (pfile->u_buff);
- _cpp_extend_buff (pfile, &pfile->u_buff, 2);
- dest = BUFF_FRONT (pfile->u_buff) + len_so_far;
- limit = BUFF_LIMIT (pfile->u_buff);
- }
- *dest++ = c;
-
- c = *buffer->cur++;
- }
- while (is_numchar (c) || c == '.' || VALID_SIGN (c, dest[-1]));
-
- /* Potential escaped newline? */
- buffer->backup_to = buffer->cur - 1;
- if (c != '?' && c != '\\')
- break;
- c = skip_escaped_newlines (pfile);
- }
- while (is_numchar (c) || c == '.' || VALID_SIGN (c, dest[-1]));
-
- /* Step back over the unwanted char. */
- BACKUP ();
-
- /* Null-terminate the number. */
- *dest = '\0';
+ const uchar *base = pfile->buffer->cur - 1;
+ uchar *dest;
- number->text = BUFF_FRONT (pfile->u_buff);
- number->len = dest - number->text;
- BUFF_FRONT (pfile->u_buff) = dest + 1;
-}
+ number->len = cur - base + leading_period;
+ dest = _cpp_unaligned_alloc (pfile, number->len + 1);
+ dest[number->len] = '\0';
+ number->text = dest;
-/* Subroutine of parse_string. Emits error for unterminated strings. */
-static void
-unterminated (pfile, term)
- cpp_reader *pfile;
- int term;
-{
- cpp_error (pfile, "missing terminating %c character", term);
-
- if (term == '\"' && pfile->mls_line && pfile->mls_line != pfile->line)
- {
- cpp_error_with_line (pfile, pfile->mls_line, pfile->mls_col,
- "possible start of unterminated string literal");
- pfile->mls_line = 0;
+ if (leading_period)
+ *dest++ = '.';
+ memcpy (dest, base, cur - base);
+ pfile->buffer->cur = cur;
}
}
@@ -622,7 +623,6 @@ unescaped_terminator_p (pfile, dest)
name. Handles embedded trigraphs and escaped newlines. The stored
string is guaranteed NUL-terminated, but it is not guaranteed that
this is the first NUL since embedded NULs are preserved.
- Multi-line strings are allowed, but they are deprecated.
When this function returns, buffer->cur points to the next
character to be processed. */
@@ -635,11 +635,19 @@ parse_string (pfile, token, terminator)
cpp_buffer *buffer = pfile->buffer;
unsigned char *dest, *limit;
cppchar_t c;
- bool warned_nulls = false, warned_multi = false;
+ bool warned_nulls = false;
+#ifdef MULTIBYTE_CHARS
+ wchar_t wc;
+ int char_len;
+#endif
dest = BUFF_FRONT (pfile->u_buff);
limit = BUFF_LIMIT (pfile->u_buff);
+#ifdef MULTIBYTE_CHARS
+ /* Reset multibyte conversion state. */
+ (void) local_mbtowc (NULL, NULL, 0);
+#endif
for (;;)
{
/* We need room for another char, possibly the terminating NUL. */
@@ -651,8 +659,26 @@ parse_string (pfile, token, terminator)
limit = BUFF_LIMIT (pfile->u_buff);
}
- /* Handle trigraphs, escaped newlines etc. */
+#ifdef MULTIBYTE_CHARS
+ char_len = local_mbtowc (&wc, (const char *) buffer->cur,
+ buffer->rlimit - buffer->cur);
+ if (char_len == -1)
+ {
+ cpp_error (pfile, DL_WARNING,
+ "ignoring invalid multibyte character");
+ char_len = 1;
+ c = *buffer->cur++;
+ }
+ else
+ {
+ buffer->cur += char_len;
+ c = wc;
+ }
+#else
c = *buffer->cur++;
+#endif
+
+ /* Handle trigraphs, escaped newlines etc. */
if (c == '?' || c == '\\')
c = skip_escaped_newlines (pfile);
@@ -663,57 +689,37 @@ parse_string (pfile, token, terminator)
}
else if (is_vspace (c))
{
- /* In assembly language, silently terminate string and
- character literals at end of line. This is a kludge
- around not knowing where comments are. */
- if (CPP_OPTION (pfile, lang) == CLK_ASM && terminator != '>')
- {
- buffer->cur--;
- break;
- }
-
- /* Character constants and header names may not extend over
- multiple lines. In Standard C, neither may strings.
- Unfortunately, we accept multiline strings as an
- extension, except in #include family directives. */
- if (terminator != '"' || pfile->state.angled_headers)
- {
- unterminated (pfile, terminator);
- buffer->cur--;
- break;
- }
-
- if (!warned_multi)
- {
- warned_multi = true;
- cpp_pedwarn (pfile, "multi-line string literals are deprecated");
- }
-
- if (pfile->mls_line == 0)
- {
- pfile->mls_line = token->line;
- pfile->mls_col = token->col;
- }
-
- handle_newline (pfile);
- c = '\n';
+ /* No string literal may extend over multiple lines. In
+ assembly language, suppress the error except for <>
+ includes. This is a kludge around not knowing where
+ comments are. */
+ unterminated:
+ if (CPP_OPTION (pfile, lang) != CLK_ASM || terminator == '>')
+ cpp_error (pfile, DL_ERROR, "missing terminating %c character",
+ (int) terminator);
+ buffer->cur--;
+ break;
}
else if (c == '\0')
{
if (buffer->cur - 1 == buffer->rlimit)
- {
- unterminated (pfile, terminator);
- buffer->cur--;
- break;
- }
+ goto unterminated;
if (!warned_nulls)
{
warned_nulls = true;
- cpp_warning (pfile, "null character(s) preserved in literal");
+ cpp_error (pfile, DL_WARNING,
+ "null character(s) preserved in literal");
}
}
-
- *dest++ = c;
+#ifdef MULTIBYTE_CHARS
+ if (char_len > 1)
+ {
+ for ( ; char_len > 0; --char_len)
+ *dest++ = (*buffer->cur - char_len);
+ }
+ else
+#endif
+ *dest++ = c;
}
*dest = '\0';
@@ -725,28 +731,46 @@ parse_string (pfile, token, terminator)
/* The stored comment includes the comment start and any terminator. */
static void
-save_comment (pfile, token, from)
+save_comment (pfile, token, from, type)
cpp_reader *pfile;
cpp_token *token;
const unsigned char *from;
+ cppchar_t type;
{
unsigned char *buffer;
- unsigned int len;
-
+ unsigned int len, clen;
+
len = pfile->buffer->cur - from + 1; /* + 1 for the initial '/'. */
/* C++ comments probably (not definitely) have moved past a new
line, which we don't want to save in the comment. */
if (is_vspace (pfile->buffer->cur[-1]))
len--;
- buffer = _cpp_unaligned_alloc (pfile, len);
-
+
+ /* If we are currently in a directive, then we need to store all
+ C++ comments as C comments internally, and so we need to
+ allocate a little extra space in that case.
+
+ Note that the only time we encounter a directive here is
+ when we are saving comments in a "#define". */
+ clen = (pfile->state.in_directive && type == '/') ? len + 2 : len;
+
+ buffer = _cpp_unaligned_alloc (pfile, clen);
+
token->type = CPP_COMMENT;
- token->val.str.len = len;
+ token->val.str.len = clen;
token->val.str.text = buffer;
buffer[0] = '/';
memcpy (buffer + 1, from, len - 1);
+
+ /* Finish conversion to a C comment, if necessary. */
+ if (pfile->state.in_directive && type == '/')
+ {
+ buffer[1] = '*';
+ buffer[clen - 2] = '*';
+ buffer[clen - 1] = '/';
+ }
}
/* Allocate COUNT tokens for RUN. */
@@ -828,7 +852,10 @@ _cpp_lex_token (pfile)
/* Is this a directive. If _cpp_handle_directive returns
false, it is an assembler #. */
if (result->type == CPP_HASH
- && !pfile->state.parsing_args
+ /* 6.10.3 p 11: Directives in a list of macro arguments
+ gives undefined behavior. This implementation
+ handles the directive as normal. */
+ && pfile->state.parsing_args != 1
&& _cpp_handle_directive (pfile, result->flags & PREV_WHITE))
continue;
if (pfile->cb.line_change && !pfile->state.skipping)
@@ -851,6 +878,57 @@ _cpp_lex_token (pfile)
return result;
}
+/* A NUL terminates the current buffer. For ISO preprocessing this is
+ EOF, but for traditional preprocessing it indicates we need a line
+ refill. Returns TRUE to continue preprocessing a new buffer, FALSE
+ to return a CPP_EOF to the caller. */
+static bool
+continue_after_nul (pfile)
+ cpp_reader *pfile;
+{
+ cpp_buffer *buffer = pfile->buffer;
+ bool more = false;
+
+ buffer->saved_flags = BOL;
+ if (CPP_OPTION (pfile, traditional))
+ {
+ if (pfile->state.in_directive)
+ return false;
+
+ _cpp_remove_overlay (pfile);
+ more = _cpp_read_logical_line_trad (pfile);
+ _cpp_overlay_buffer (pfile, pfile->out.base,
+ pfile->out.cur - pfile->out.base);
+ pfile->line = pfile->out.first_line;
+ }
+ else
+ {
+ /* Stop parsing arguments with a CPP_EOF. When we finally come
+ back here, do the work of popping the buffer. */
+ if (!pfile->state.parsing_args)
+ {
+ if (buffer->cur != buffer->line_base)
+ {
+ /* Non-empty files should end in a newline. Don't warn
+ for command line and _Pragma buffers. */
+ if (!buffer->from_stage3)
+ cpp_error (pfile, DL_PEDWARN, "no newline at end of file");
+ handle_newline (pfile);
+ }
+
+ /* Similarly, finish an in-progress directive with CPP_EOF
+ before popping the buffer. */
+ if (!pfile->state.in_directive && buffer->prev)
+ {
+ more = !buffer->return_at_eof;
+ _cpp_pop_buffer (pfile);
+ }
+ }
+ }
+
+ return more;
+}
+
#define IF_NEXT_IS(CHAR, THEN_TYPE, ELSE_TYPE) \
do { \
if (get_effective_char (pfile) == CHAR) \
@@ -901,30 +979,10 @@ _cpp_lex_direct (pfile)
if (skip_whitespace (pfile, c))
goto skipped_white;
- /* EOF. */
+ /* End of buffer. */
buffer->cur--;
- buffer->saved_flags = BOL;
- if (!pfile->state.parsing_args && !pfile->state.in_directive)
- {
- if (buffer->cur != buffer->line_base)
- {
- /* Non-empty files should end in a newline. Don't warn
- for command line and _Pragma buffers. */
- if (!buffer->from_stage3)
- cpp_pedwarn (pfile, "no newline at end of file");
- handle_newline (pfile);
- }
-
- /* Don't pop the last buffer. */
- if (buffer->prev)
- {
- unsigned char stop = buffer->return_at_eof;
-
- _cpp_pop_buffer (pfile);
- if (!stop)
- goto fresh_line;
- }
- }
+ if (continue_after_nul (pfile))
+ goto fresh_line;
result->type = CPP_EOF;
break;
@@ -975,24 +1033,24 @@ _cpp_lex_direct (pfile)
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
result->type = CPP_NUMBER;
- parse_number (pfile, &result->val.str, c, 0);
+ parse_number (pfile, &result->val.str, 0);
break;
case 'L':
/* 'L' may introduce wide characters or strings. */
- {
- const unsigned char *pos = buffer->cur;
+ {
+ const unsigned char *pos = buffer->cur;
- c = get_effective_char (pfile);
- if (c == '\'' || c == '"')
- {
- result->type = (c == '"' ? CPP_WSTRING: CPP_WCHAR);
- parse_string (pfile, result, c);
- break;
- }
- buffer->cur = pos;
- }
- /* Fall through. */
+ c = get_effective_char (pfile);
+ if (c == '\'' || c == '"')
+ {
+ result->type = (c == '"' ? CPP_WSTRING: CPP_WCHAR);
+ parse_string (pfile, result, c);
+ break;
+ }
+ buffer->cur = pos;
+ }
+ /* Fall through. */
start_ident:
case '_':
@@ -1031,7 +1089,7 @@ _cpp_lex_direct (pfile)
if (c == '*')
{
if (skip_block_comment (pfile))
- cpp_error (pfile, "unterminated comment");
+ cpp_error (pfile, DL_ERROR, "unterminated comment");
}
else if (c == '/' && (CPP_OPTION (pfile, cplusplus_comments)
|| CPP_IN_SYSTEM_HEADER (pfile)))
@@ -1041,15 +1099,15 @@ _cpp_lex_direct (pfile)
if (CPP_OPTION (pfile, lang) == CLK_GNUC89 && CPP_PEDANTIC (pfile)
&& ! buffer->warned_cplusplus_comments)
{
- cpp_pedwarn (pfile,
- "C++ style comments are not allowed in ISO C89");
- cpp_pedwarn (pfile,
- "(this will be reported only once per input file)");
+ cpp_error (pfile, DL_PEDWARN,
+ "C++ style comments are not allowed in ISO C90");
+ cpp_error (pfile, DL_PEDWARN,
+ "(this will be reported only once per input file)");
buffer->warned_cplusplus_comments = 1;
}
if (skip_line_comment (pfile) && CPP_OPTION (pfile, warn_comments))
- cpp_warning (pfile, "multi-line comment");
+ cpp_error (pfile, DL_WARNING, "multi-line comment");
}
else if (c == '=')
{
@@ -1070,7 +1128,7 @@ _cpp_lex_direct (pfile)
}
/* Save the comment as a token in its own right. */
- save_comment (pfile, result, comment_start);
+ save_comment (pfile, result, comment_start, c);
break;
case '<':
@@ -1168,7 +1226,7 @@ _cpp_lex_direct (pfile)
else if (ISDIGIT (c))
{
result->type = CPP_NUMBER;
- parse_number (pfile, &result->val.str, c, 1);
+ parse_number (pfile, &result->val.str, 1);
}
else if (c == '*' && CPP_OPTION (pfile, cplusplus))
result->type = CPP_DOT_STAR;
@@ -1225,7 +1283,7 @@ _cpp_lex_direct (pfile)
result->type = CPP_AND;
}
break;
-
+
case '|':
c = get_effective_char (pfile);
if (c == '|')
@@ -1271,7 +1329,7 @@ _cpp_lex_direct (pfile)
case '}': result->type = CPP_CLOSE_BRACE; break;
case ';': result->type = CPP_SEMICOLON; break;
- /* @ is a punctuator in Objective C. */
+ /* @ is a punctuator in Objective-C. */
case '@': result->type = CPP_ATSIGN; break;
case '$':
@@ -1332,7 +1390,7 @@ cpp_spell_token (pfile, token, buffer)
goto spell_ident;
else
spelling = TOKEN_NAME (token);
-
+
while ((c = *spelling++) != '\0')
*buffer++ = c;
}
@@ -1364,7 +1422,8 @@ cpp_spell_token (pfile, token, buffer)
case CPP_WCHAR: left = '\''; right = '\''; tag = 'L'; break;
case CPP_HEADER_NAME: left = '<'; right = '>'; tag = '\0'; break;
default:
- cpp_ice (pfile, "unknown string token %s\n", TOKEN_NAME (token));
+ cpp_error (pfile, DL_ICE, "unknown string token %s\n",
+ TOKEN_NAME (token));
return buffer;
}
if (tag) *buffer++ = tag;
@@ -1376,7 +1435,7 @@ cpp_spell_token (pfile, token, buffer)
break;
case SPELL_NONE:
- cpp_ice (pfile, "unspellable token %s", TOKEN_NAME (token));
+ cpp_error (pfile, DL_ICE, "unspellable token %s", TOKEN_NAME (token));
break;
}
@@ -1621,7 +1680,7 @@ maybe_read_ucs (pfile, pstr, limit, pc)
cpp_reader *pfile;
const unsigned char **pstr;
const unsigned char *limit;
- unsigned int *pc;
+ cppchar_t *pc;
{
const unsigned char *p = *pstr;
unsigned int code = 0;
@@ -1632,13 +1691,14 @@ maybe_read_ucs (pfile, pstr, limit, pc)
return 1;
if (CPP_WTRADITIONAL (pfile))
- cpp_warning (pfile, "the meaning of '\\%c' varies with -traditional", c);
+ cpp_error (pfile, DL_WARNING,
+ "the meaning of '\\%c' is different in traditional C", c);
length = (c == 'u' ? 4: 8);
if ((size_t) (limit - p) < length)
{
- cpp_error (pfile, "incomplete universal-character-name");
+ cpp_error (pfile, DL_ERROR, "incomplete universal-character-name");
/* Skip to the end to avoid more diagnostics. */
p = limit;
}
@@ -1651,7 +1711,7 @@ maybe_read_ucs (pfile, pstr, limit, pc)
code = (code << 4) + hex_digit_value (c);
else
{
- cpp_error (pfile,
+ cpp_error (pfile, DL_ERROR,
"non-hex digit '%c' in universal-character-name", c);
/* We shouldn't skip in case there are multibyte chars. */
break;
@@ -1660,7 +1720,7 @@ maybe_read_ucs (pfile, pstr, limit, pc)
}
#ifdef TARGET_EBCDIC
- cpp_error (pfile, "universal-character-name on EBCDIC target");
+ cpp_error (pfile, DL_ERROR, "universal-character-name on EBCDIC target");
code = 0x3f; /* EBCDIC invalid character */
#else
/* True extended characters are OK. */
@@ -1674,7 +1734,7 @@ maybe_read_ucs (pfile, pstr, limit, pc)
;
/* Don't give another error if one occurred above. */
else if (length == 0)
- cpp_error (pfile, "universal-character-name out of range");
+ cpp_error (pfile, DL_ERROR, "universal-character-name out of range");
#endif
*pstr = p;
@@ -1682,25 +1742,33 @@ maybe_read_ucs (pfile, pstr, limit, pc)
return 0;
}
-/* Interpret an escape sequence, and return its value. PSTR points to
- the input pointer, which is just after the backslash. LIMIT is how
- much text we have. MASK is a bitmask for the precision for the
- destination type (char or wchar_t). TRADITIONAL, if true, does not
- interpret escapes that did not exist in traditional C.
-
- Handles all relevant diagnostics. */
-unsigned int
-cpp_parse_escape (pfile, pstr, limit, mask, traditional)
+/* Returns the value of an escape sequence, truncated to the correct
+ target precision. PSTR points to the input pointer, which is just
+ after the backslash. LIMIT is how much text we have. WIDE is true
+ if the escape sequence is part of a wide character constant or
+ string literal. Handles all relevant diagnostics. */
+cppchar_t
+cpp_parse_escape (pfile, pstr, limit, wide)
cpp_reader *pfile;
const unsigned char **pstr;
const unsigned char *limit;
- unsigned HOST_WIDE_INT mask;
- int traditional;
+ int wide;
{
int unknown = 0;
const unsigned char *str = *pstr;
- unsigned int c = *str++;
+ cppchar_t c, mask;
+ unsigned int width;
+
+ if (wide)
+ width = CPP_OPTION (pfile, wchar_precision);
+ else
+ width = CPP_OPTION (pfile, char_precision);
+ if (width < BITS_PER_CPPCHAR_T)
+ mask = ((cppchar_t) 1 << width) - 1;
+ else
+ mask = ~0;
+ c = *str++;
switch (c)
{
case '\\': case '\'': case '"': case '?': break;
@@ -1719,58 +1787,61 @@ cpp_parse_escape (pfile, pstr, limit, mask, traditional)
case 'a':
if (CPP_WTRADITIONAL (pfile))
- cpp_warning (pfile, "the meaning of '\\a' varies with -traditional");
- if (!traditional)
- c = TARGET_BELL;
+ cpp_error (pfile, DL_WARNING,
+ "the meaning of '\\a' is different in traditional C");
+ c = TARGET_BELL;
break;
case 'e': case 'E':
if (CPP_PEDANTIC (pfile))
- cpp_pedwarn (pfile, "non-ISO-standard escape sequence, '\\%c'", c);
+ cpp_error (pfile, DL_PEDWARN,
+ "non-ISO-standard escape sequence, '\\%c'", (int) c);
c = TARGET_ESC;
break;
-
+
case 'u': case 'U':
unknown = maybe_read_ucs (pfile, &str, limit, &c);
break;
case 'x':
if (CPP_WTRADITIONAL (pfile))
- cpp_warning (pfile, "the meaning of '\\x' varies with -traditional");
+ cpp_error (pfile, DL_WARNING,
+ "the meaning of '\\x' is different in traditional C");
- if (!traditional)
- {
- unsigned int i = 0, overflow = 0;
- int digits_found = 0;
+ {
+ cppchar_t i = 0, overflow = 0;
+ int digits_found = 0;
- while (str < limit)
- {
- c = *str;
- if (! ISXDIGIT (c))
- break;
- str++;
- overflow |= i ^ (i << 4 >> 4);
- i = (i << 4) + hex_digit_value (c);
- digits_found = 1;
- }
+ while (str < limit)
+ {
+ c = *str;
+ if (! ISXDIGIT (c))
+ break;
+ str++;
+ overflow |= i ^ (i << 4 >> 4);
+ i = (i << 4) + hex_digit_value (c);
+ digits_found = 1;
+ }
- if (!digits_found)
- cpp_error (pfile, "\\x used with no following hex digits");
+ if (!digits_found)
+ cpp_error (pfile, DL_ERROR,
+ "\\x used with no following hex digits");
- if (overflow | (i != (i & mask)))
- {
- cpp_pedwarn (pfile, "hex escape sequence out of range");
- i &= mask;
- }
- c = i;
- }
+ if (overflow | (i != (i & mask)))
+ {
+ cpp_error (pfile, DL_PEDWARN,
+ "hex escape sequence out of range");
+ i &= mask;
+ }
+ c = i;
+ }
break;
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
{
- unsigned int i = c - '0';
- int count = 0;
+ size_t count = 0;
+ cppchar_t i = c - '0';
while (str < limit && ++count < 3)
{
@@ -1783,7 +1854,8 @@ cpp_parse_escape (pfile, pstr, limit, mask, traditional)
if (i != (i & mask))
{
- cpp_pedwarn (pfile, "octal escape sequence out of range");
+ cpp_error (pfile, DL_PEDWARN,
+ "octal escape sequence out of range");
i &= mask;
}
c = i;
@@ -1798,45 +1870,40 @@ cpp_parse_escape (pfile, pstr, limit, mask, traditional)
if (unknown)
{
if (ISGRAPH (c))
- cpp_pedwarn (pfile, "unknown escape sequence '\\%c'", c);
+ cpp_error (pfile, DL_PEDWARN,
+ "unknown escape sequence '\\%c'", (int) c);
else
- cpp_pedwarn (pfile, "unknown escape sequence: '\\%03o'", c);
+ cpp_error (pfile, DL_PEDWARN,
+ "unknown escape sequence: '\\%03o'", (int) c);
}
if (c > mask)
- cpp_pedwarn (pfile, "escape sequence out of range for character");
+ {
+ cpp_error (pfile, DL_PEDWARN, "escape sequence out of range for its type");
+ c &= mask;
+ }
*pstr = str;
return c;
}
-#ifndef MAX_CHAR_TYPE_SIZE
-#define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE
-#endif
-
-#ifndef MAX_WCHAR_TYPE_SIZE
-#define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
-#endif
-
/* Interpret a (possibly wide) character constant in TOKEN.
- WARN_MULTI warns about multi-character charconsts, if not
- TRADITIONAL. TRADITIONAL also indicates not to interpret escapes
- that did not exist in traditional C. PCHARS_SEEN points to a
- variable that is filled in with the number of characters seen. */
-HOST_WIDE_INT
-cpp_interpret_charconst (pfile, token, warn_multi, traditional, pchars_seen)
+ WARN_MULTI warns about multi-character charconsts. PCHARS_SEEN
+ points to a variable that is filled in with the number of
+ characters seen, and UNSIGNEDP to a variable that indicates whether
+ the result has signed type. */
+cppchar_t
+cpp_interpret_charconst (pfile, token, pchars_seen, unsignedp)
cpp_reader *pfile;
const cpp_token *token;
- int warn_multi;
- int traditional;
unsigned int *pchars_seen;
+ int *unsignedp;
{
const unsigned char *str = token->val.str.text;
const unsigned char *limit = str + token->val.str.len;
unsigned int chars_seen = 0;
- unsigned int width, max_chars, c;
- unsigned HOST_WIDE_INT mask;
- HOST_WIDE_INT result = 0;
+ size_t width, max_chars;
+ cppchar_t c, mask, result = 0;
bool unsigned_p;
#ifdef MULTIBYTE_CHARS
@@ -1846,20 +1913,21 @@ cpp_interpret_charconst (pfile, token, warn_multi, traditional, pchars_seen)
/* Width in bits. */
if (token->type == CPP_CHAR)
{
- width = MAX_CHAR_TYPE_SIZE;
- unsigned_p = CPP_OPTION (pfile, signed_char) == 0;
+ width = CPP_OPTION (pfile, char_precision);
+ max_chars = CPP_OPTION (pfile, int_precision) / width;
+ unsigned_p = CPP_OPTION (pfile, unsigned_char);
}
else
{
- width = MAX_WCHAR_TYPE_SIZE;
- unsigned_p = WCHAR_UNSIGNED;
+ width = CPP_OPTION (pfile, wchar_precision);
+ max_chars = 1;
+ unsigned_p = CPP_OPTION (pfile, unsigned_wchar);
}
- if (width < HOST_BITS_PER_WIDE_INT)
- mask = ((unsigned HOST_WIDE_INT) 1 << width) - 1;
+ if (width < BITS_PER_CPPCHAR_T)
+ mask = ((cppchar_t) 1 << width) - 1;
else
mask = ~0;
- max_chars = HOST_BITS_PER_WIDE_INT / width;
while (str < limit)
{
@@ -1870,7 +1938,8 @@ cpp_interpret_charconst (pfile, token, warn_multi, traditional, pchars_seen)
char_len = local_mbtowc (&wc, str, limit - str);
if (char_len == -1)
{
- cpp_warning (pfile, "ignoring invalid multibyte character");
+ cpp_error (pfile, DL_WARNING,
+ "ignoring invalid multibyte character");
c = *str++;
}
else
@@ -1883,46 +1952,56 @@ cpp_interpret_charconst (pfile, token, warn_multi, traditional, pchars_seen)
#endif
if (c == '\\')
- c = cpp_parse_escape (pfile, &str, limit, mask, traditional);
+ c = cpp_parse_escape (pfile, &str, limit, token->type == CPP_WCHAR);
#ifdef MAP_CHARACTER
if (ISPRINT (c))
c = MAP_CHARACTER (c);
#endif
-
- /* Merge character into result; ignore excess chars. */
- if (++chars_seen <= max_chars)
- {
- if (width < HOST_BITS_PER_WIDE_INT)
- result = (result << width) | (c & mask);
- else
- result = c;
- }
+
+ chars_seen++;
+
+ /* Truncate the character, scale the result and merge the two. */
+ c &= mask;
+ if (width < BITS_PER_CPPCHAR_T)
+ result = (result << width) | c;
+ else
+ result = c;
}
if (chars_seen == 0)
- cpp_error (pfile, "empty character constant");
- else if (chars_seen > max_chars)
+ cpp_error (pfile, DL_ERROR, "empty character constant");
+ else if (chars_seen > 1)
{
- chars_seen = max_chars;
- cpp_warning (pfile, "character constant too long");
+ /* Multichar charconsts are of type int and therefore signed. */
+ unsigned_p = 0;
+
+ if (chars_seen > max_chars)
+ {
+ chars_seen = max_chars;
+ cpp_error (pfile, DL_WARNING,
+ "character constant too long for its type");
+ }
+ else if (CPP_OPTION (pfile, warn_multichar))
+ cpp_error (pfile, DL_WARNING, "multi-character character constant");
}
- else if (chars_seen > 1 && !traditional && warn_multi)
- cpp_warning (pfile, "multi-character character constant");
- /* If relevant type is signed, sign-extend the constant. */
- if (chars_seen)
+ /* Sign-extend or truncate the constant to cppchar_t. The value is
+ in WIDTH bits, but for multi-char charconsts it's value is the
+ full target type's width. */
+ if (chars_seen > 1)
+ width *= max_chars;
+ if (width < BITS_PER_CPPCHAR_T)
{
- unsigned int nbits = chars_seen * width;
-
- mask = (unsigned HOST_WIDE_INT) ~0 >> (HOST_BITS_PER_WIDE_INT - nbits);
- if (unsigned_p || ((result >> (nbits - 1)) & 1) == 0)
+ mask = ((cppchar_t) 1 << width) - 1;
+ if (unsigned_p || !(result & (1 << (width - 1))))
result &= mask;
else
result |= ~mask;
}
*pchars_seen = chars_seen;
+ *unsignedp = unsigned_p;
return result;
}
@@ -1941,19 +2020,6 @@ cpp_interpret_charconst (pfile, token, warn_multi, traditional, pchars_seen)
#error BUFF_SIZE_UPPER_BOUND must be at least as large as MIN_BUFF_SIZE!
#endif
-struct dummy
-{
- char c;
- union
- {
- double d;
- int *p;
- } u;
-};
-
-#define DEFAULT_ALIGNMENT (offsetof (struct dummy, u))
-#define CPP_ALIGN(size, align) (((size) + ((align) - 1)) & ~((align) - 1))
-
/* Create a new allocation buffer. Place the control block at the end
of the buffer, so that buffer overflows will cause immediate chaos. */
static _cpp_buff *
@@ -1965,7 +2031,7 @@ new_buff (len)
if (len < MIN_BUFF_SIZE)
len = MIN_BUFF_SIZE;
- len = CPP_ALIGN (len, DEFAULT_ALIGNMENT);
+ len = CPP_ALIGN (len);
base = xmalloc (len + sizeof (_cpp_buff));
result = (_cpp_buff *) (base + len);
diff --git a/contrib/gcc/cpplib.c b/contrib/gcc/cpplib.c
index 0f0063b..818451d 100644
--- a/contrib/gcc/cpplib.c
+++ b/contrib/gcc/cpplib.c
@@ -70,11 +70,14 @@ struct pragma_entry
conditional; IF_COND an opening conditional. INCL means to treat
"..." and <...> as q-char and h-char sequences respectively. IN_I
means this directive should be handled even if -fpreprocessed is in
- effect (these are the directives with callback hooks). */
+ effect (these are the directives with callback hooks).
+
+ EXPAND is set on directives that are always macro-expanded. */
#define COND (1 << 0)
#define IF_COND (1 << 1)
#define INCL (1 << 2)
#define IN_I (1 << 3)
+#define EXPAND (1 << 4)
/* Defines one #-directive, including how to handle it. */
typedef void (*directive_handler) PARAMS ((cpp_reader *));
@@ -82,7 +85,7 @@ typedef struct directive directive;
struct directive
{
directive_handler handler; /* Function to handle directive. */
- const U_CHAR *name; /* Name of directive. */
+ const uchar *name; /* Name of directive. */
unsigned short length; /* Length of name. */
unsigned char origin; /* Origin of directive. */
unsigned char flags; /* Flags describing this directive. */
@@ -93,6 +96,7 @@ struct directive
static void skip_rest_of_line PARAMS ((cpp_reader *));
static void check_eol PARAMS ((cpp_reader *));
static void start_directive PARAMS ((cpp_reader *));
+static void prepare_directive_trad PARAMS ((cpp_reader *));
static void end_directive PARAMS ((cpp_reader *, int));
static void directive_diagnostics
PARAMS ((cpp_reader *, const directive *, int));
@@ -103,11 +107,11 @@ static const cpp_token *parse_include PARAMS ((cpp_reader *));
static void push_conditional PARAMS ((cpp_reader *, int, int,
const cpp_hashnode *));
static unsigned int read_flag PARAMS ((cpp_reader *, unsigned int));
-static U_CHAR *dequote_string PARAMS ((cpp_reader *, const U_CHAR *,
+static uchar *dequote_string PARAMS ((cpp_reader *, const uchar *,
unsigned int));
-static int strtoul_for_line PARAMS ((const U_CHAR *, unsigned int,
+static int strtoul_for_line PARAMS ((const uchar *, unsigned int,
unsigned long *));
-static void do_diagnostic PARAMS ((cpp_reader *, enum error_type, int));
+static void do_diagnostic PARAMS ((cpp_reader *, int, int));
static cpp_hashnode *lex_macro_node PARAMS ((cpp_reader *));
static void do_include_common PARAMS ((cpp_reader *, enum include_type));
static struct pragma_entry *lookup_pragma_entry
@@ -141,31 +145,24 @@ static void handle_assertion PARAMS ((cpp_reader *, const char *, int));
#define DIRECTIVE_TABLE \
D(define, T_DEFINE = 0, KANDR, IN_I) /* 270554 */ \
-D(include, T_INCLUDE, KANDR, INCL) /* 52262 */ \
+D(include, T_INCLUDE, KANDR, INCL | EXPAND) /* 52262 */ \
D(endif, T_ENDIF, KANDR, COND) /* 45855 */ \
D(ifdef, T_IFDEF, KANDR, COND | IF_COND) /* 22000 */ \
-D(if, T_IF, KANDR, COND | IF_COND) /* 18162 */ \
+D(if, T_IF, KANDR, COND | IF_COND | EXPAND) /* 18162 */ \
D(else, T_ELSE, KANDR, COND) /* 9863 */ \
D(ifndef, T_IFNDEF, KANDR, COND | IF_COND) /* 9675 */ \
D(undef, T_UNDEF, KANDR, IN_I) /* 4837 */ \
-D(line, T_LINE, KANDR, 0) /* 2465 */ \
-D(elif, T_ELIF, STDC89, COND) /* 610 */ \
+D(line, T_LINE, KANDR, EXPAND) /* 2465 */ \
+D(elif, T_ELIF, STDC89, COND | EXPAND) /* 610 */ \
D(error, T_ERROR, STDC89, 0) /* 475 */ \
D(pragma, T_PRAGMA, STDC89, IN_I) /* 195 */ \
D(warning, T_WARNING, EXTENSION, 0) /* 22 */ \
-D(include_next, T_INCLUDE_NEXT, EXTENSION, INCL) /* 19 */ \
+D(include_next, T_INCLUDE_NEXT, EXTENSION, INCL | EXPAND) /* 19 */ \
D(ident, T_IDENT, EXTENSION, IN_I) /* 11 */ \
-D(import, T_IMPORT, EXTENSION, INCL) /* 0 ObjC */ \
+D(import, T_IMPORT, EXTENSION, INCL | EXPAND) /* 0 ObjC */ \
D(assert, T_ASSERT, EXTENSION, 0) /* 0 SVR4 */ \
D(unassert, T_UNASSERT, EXTENSION, 0) /* 0 SVR4 */ \
-SCCS_ENTRY /* 0 SVR4? */
-
-/* #sccs is not always recognized. */
-#ifdef SCCS_DIRECTIVE
-# define SCCS_ENTRY D(sccs, T_SCCS, EXTENSION, 0)
-#else
-# define SCCS_ENTRY /* nothing */
-#endif
+D(sccs, T_SCCS, EXTENSION, 0) /* 0 SVR4? */
/* Use the table to generate a series of prototypes, an enum for the
directive names, and an array of directive handlers. */
@@ -185,7 +182,7 @@ enum
/* Don't invoke CONCAT2 with any whitespace or K&R cc will fail. */
#define D(name, t, origin, flags) \
-{ CONCAT2(do_,name), (const U_CHAR *) STRINGX(name), \
+{ CONCAT2(do_,name), (const uchar *) STRINGX(name), \
sizeof STRINGX(name) - 1, origin, flags },
static const directive dtable[] =
{
@@ -225,8 +222,8 @@ check_eol (pfile)
cpp_reader *pfile;
{
if (! SEEN_EOL () && _cpp_lex_token (pfile)->type != CPP_EOF)
- cpp_pedwarn (pfile, "extra tokens at end of #%s directive",
- pfile->directive->name);
+ cpp_error (pfile, DL_PEDWARN, "extra tokens at end of #%s directive",
+ pfile->directive->name);
}
/* Called when entering a directive, _Pragma or command-line directive. */
@@ -248,8 +245,16 @@ end_directive (pfile, skip_line)
cpp_reader *pfile;
int skip_line;
{
+ if (CPP_OPTION (pfile, traditional))
+ {
+ /* Revert change of prepare_directive_trad. */
+ pfile->state.prevent_expansion--;
+
+ if (pfile->directive != &dtable[T_DEFINE])
+ _cpp_remove_overlay (pfile);
+ }
/* We don't skip for an assembler #. */
- if (skip_line)
+ else if (skip_line)
{
skip_rest_of_line (pfile);
if (!pfile->keep_tokens)
@@ -262,11 +267,40 @@ end_directive (pfile, skip_line)
/* Restore state. */
pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
pfile->state.in_directive = 0;
+ pfile->state.in_expression = 0;
pfile->state.angled_headers = 0;
pfile->directive = 0;
}
-/* Output diagnostics for a directive DIR. INDENTED is non-zero if
+/* Prepare to handle the directive in pfile->directive. */
+static void
+prepare_directive_trad (pfile)
+ cpp_reader *pfile;
+{
+ if (pfile->directive != &dtable[T_DEFINE])
+ {
+ bool no_expand = (pfile->directive
+ && ! (pfile->directive->flags & EXPAND));
+ bool was_skipping = pfile->state.skipping;
+
+ pfile->state.skipping = false;
+ pfile->state.in_expression = (pfile->directive == &dtable[T_IF]
+ || pfile->directive == &dtable[T_ELIF]);
+ if (no_expand)
+ pfile->state.prevent_expansion++;
+ _cpp_read_logical_line_trad (pfile);
+ if (no_expand)
+ pfile->state.prevent_expansion--;
+ pfile->state.skipping = was_skipping;
+ _cpp_overlay_buffer (pfile, pfile->out.base,
+ pfile->out.cur - pfile->out.base);
+ }
+
+ /* Stop ISO C from expanding anything. */
+ pfile->state.prevent_expansion++;
+}
+
+/* Output diagnostics for a directive DIR. INDENTED is nonzero if
the '#' was indented. */
static void
directive_diagnostics (pfile, dir, indented)
@@ -278,7 +312,7 @@ directive_diagnostics (pfile, dir, indented)
if (CPP_PEDANTIC (pfile)
&& ! pfile->state.skipping
&& dir->origin == EXTENSION)
- cpp_pedwarn (pfile, "#%s is a GCC extension", dir->name);
+ cpp_error (pfile, DL_PEDWARN, "#%s is a GCC extension", dir->name);
/* Traditionally, a directive is ignored unless its # is in
column 1. Therefore in code intended to work with K+R
@@ -289,22 +323,23 @@ directive_diagnostics (pfile, dir, indented)
if (CPP_WTRADITIONAL (pfile))
{
if (dir == &dtable[T_ELIF])
- cpp_warning (pfile, "suggest not using #elif in traditional C");
+ cpp_error (pfile, DL_WARNING,
+ "suggest not using #elif in traditional C");
else if (indented && dir->origin == KANDR)
- cpp_warning (pfile,
- "traditional C ignores #%s with the # indented",
- dir->name);
+ cpp_error (pfile, DL_WARNING,
+ "traditional C ignores #%s with the # indented",
+ dir->name);
else if (!indented && dir->origin != KANDR)
- cpp_warning (pfile,
- "suggest hiding #%s from traditional C with an indented #",
- dir->name);
+ cpp_error (pfile, DL_WARNING,
+ "suggest hiding #%s from traditional C with an indented #",
+ dir->name);
}
}
-/* Check if we have a known directive. INDENTED is non-zero if the
+/* Check if we have a known directive. INDENTED is nonzero if the
'#' of the directive was indented. This function is in this file
to save unnecessarily exporting dtable etc. to cpplex.c. Returns
- non-zero if the line of tokens has been handled, zero if we should
+ nonzero if the line of tokens has been handled, zero if we should
continue processing the line. */
int
_cpp_handle_directive (pfile, indented)
@@ -313,8 +348,17 @@ _cpp_handle_directive (pfile, indented)
{
const directive *dir = 0;
const cpp_token *dname;
+ bool was_parsing_args = pfile->state.parsing_args;
int skip = 1;
+ if (was_parsing_args)
+ {
+ if (CPP_OPTION (pfile, pedantic))
+ cpp_error (pfile, DL_PEDWARN,
+ "embedding a directive within macro arguments is not portable");
+ pfile->state.parsing_args = 0;
+ pfile->state.prevent_expansion = 0;
+ }
start_directive (pfile);
dname = _cpp_lex_token (pfile);
@@ -323,14 +367,15 @@ _cpp_handle_directive (pfile, indented)
if (dname->val.node->directive_index)
dir = &dtable[dname->val.node->directive_index - 1];
}
- /* We do not recognise the # followed by a number extension in
+ /* We do not recognize the # followed by a number extension in
assembler code. */
else if (dname->type == CPP_NUMBER && CPP_OPTION (pfile, lang) != CLK_ASM)
{
dir = &linemarker_dir;
if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, preprocessed)
&& ! pfile->state.skipping)
- cpp_pedwarn (pfile, "style of line directive is a GCC extension");
+ cpp_error (pfile, DL_PEDWARN,
+ "style of line directive is a GCC extension");
}
if (dir)
@@ -362,6 +407,7 @@ _cpp_handle_directive (pfile, indented)
skipping or not, we should lex angle-bracketed headers
correctly, and maybe output some diagnostics. */
pfile->state.angled_headers = dir->flags & INCL;
+ pfile->state.directive_wants_padding = dir->flags & INCL;
if (! CPP_OPTION (pfile, preprocessed))
directive_diagnostics (pfile, dir, indented);
if (pfile->state.skipping && !(dir->flags & COND))
@@ -379,19 +425,27 @@ _cpp_handle_directive (pfile, indented)
if (CPP_OPTION (pfile, lang) == CLK_ASM)
skip = 0;
else if (!pfile->state.skipping)
- cpp_error (pfile, "invalid preprocessing directive #%s",
+ cpp_error (pfile, DL_ERROR, "invalid preprocessing directive #%s",
cpp_token_as_text (pfile, dname));
}
+ pfile->directive = dir;
+ if (CPP_OPTION (pfile, traditional))
+ prepare_directive_trad (pfile);
+
if (dir)
- {
- pfile->directive = dir;
- (*pfile->directive->handler) (pfile);
- }
+ (*pfile->directive->handler) (pfile);
else if (skip == 0)
_cpp_backup_tokens (pfile, 1);
end_directive (pfile, skip);
+ if (was_parsing_args)
+ {
+ /* Restore state when within macro args. */
+ pfile->state.parsing_args = 2;
+ pfile->state.prevent_expansion = 1;
+ pfile->buffer->saved_flags |= PREV_WHITE;
+ }
return skip;
}
@@ -404,7 +458,7 @@ run_directive (pfile, dir_no, buf, count)
const char *buf;
size_t count;
{
- cpp_push_buffer (pfile, (const U_CHAR *) buf, count,
+ cpp_push_buffer (pfile, (const uchar *) buf, count,
/* from_stage3 */ true, 1);
/* Disgusting hack. */
if (dir_no == T_PRAGMA)
@@ -413,6 +467,8 @@ run_directive (pfile, dir_no, buf, count)
/* We don't want a leading # to be interpreted as a directive. */
pfile->buffer->saved_flags = 0;
pfile->directive = &dtable[dir_no];
+ if (CPP_OPTION (pfile, traditional))
+ prepare_directive_trad (pfile);
(void) (*pfile->directive->handler) (pfile);
end_directive (pfile, 1);
if (dir_no == T_PRAGMA)
@@ -426,7 +482,6 @@ static cpp_hashnode *
lex_macro_node (pfile)
cpp_reader *pfile;
{
- cpp_hashnode *node;
const cpp_token *token = _cpp_lex_token (pfile);
/* The token immediately after #define must be an identifier. That
@@ -436,33 +491,27 @@ lex_macro_node (pfile)
Finally, the identifier may not have been poisoned. (In that case
the lexer has issued the error message for us.) */
- if (token->type != CPP_NAME)
+ if (token->type == CPP_NAME)
{
- if (token->type == CPP_EOF)
- cpp_error (pfile, "no macro name given in #%s directive",
- pfile->directive->name);
- else if (token->flags & NAMED_OP)
- cpp_error (pfile,
- "\"%s\" cannot be used as a macro name as it is an operator in C++",
- NODE_NAME (token->val.node));
- else
- cpp_error (pfile, "macro names must be identifiers");
-
- return 0;
- }
-
- node = token->val.node;
- if (node->flags & NODE_POISONED)
- return 0;
+ cpp_hashnode *node = token->val.node;
- if (node == pfile->spec_nodes.n_defined)
- {
- cpp_error (pfile, "\"%s\" cannot be used as a macro name",
- NODE_NAME (node));
- return 0;
+ if (node == pfile->spec_nodes.n_defined)
+ cpp_error (pfile, DL_ERROR,
+ "\"defined\" cannot be used as a macro name");
+ else if (! (node->flags & NODE_POISONED))
+ return node;
}
+ else if (token->flags & NAMED_OP)
+ cpp_error (pfile, DL_ERROR,
+ "\"%s\" cannot be used as a macro name as it is an operator in C++",
+ NODE_NAME (token->val.node));
+ else if (token->type == CPP_EOF)
+ cpp_error (pfile, DL_ERROR, "no macro name given in #%s directive",
+ pfile->directive->name);
+ else
+ cpp_error (pfile, DL_ERROR, "macro names must be identifiers");
- return node;
+ return NULL;
}
/* Process a #define directive. Most work is done in cppmacro.c. */
@@ -474,6 +523,11 @@ do_define (pfile)
if (node)
{
+ /* If we have been requested to expand comments into macros,
+ then re-enable saving of comments. */
+ pfile->state.save_comments =
+ ! CPP_OPTION (pfile, discard_comments_in_macro_exp);
+
if (_cpp_create_definition (pfile, node))
if (pfile->cb.define)
(*pfile->cb.define) (pfile, pfile->directive_line, node);
@@ -485,7 +539,7 @@ static void
do_undef (pfile)
cpp_reader *pfile;
{
- cpp_hashnode *node = lex_macro_node (pfile);
+ cpp_hashnode *node = lex_macro_node (pfile);
/* 6.10.3.5 paragraph 2: [#undef] is ignored if the specified identifier
is not currently defined as a macro name. */
@@ -495,7 +549,10 @@ do_undef (pfile)
(*pfile->cb.undef) (pfile, pfile->directive_line, node);
if (node->flags & NODE_WARN)
- cpp_warning (pfile, "undefining \"%s\"", NODE_NAME (node));
+ cpp_error (pfile, DL_WARNING, "undefining \"%s\"", NODE_NAME (node));
+
+ if (CPP_OPTION (pfile, warn_unused_macros))
+ _cpp_warn_if_unused_macro (pfile, node, NULL);
_cpp_free_definition (node);
}
@@ -519,7 +576,7 @@ glue_header_name (pfile)
buffer = (unsigned char *) xmalloc (capacity);
for (;;)
{
- token = cpp_get_token (pfile);
+ token = get_token_no_padding (pfile);
if (token->type == CPP_GREATER || token->type == CPP_EOF)
break;
@@ -538,7 +595,7 @@ glue_header_name (pfile)
}
if (token->type == CPP_EOF)
- cpp_error (pfile, "missing terminating > character");
+ cpp_error (pfile, DL_ERROR, "missing terminating > character");
else
{
unsigned char *token_mem = _cpp_unaligned_alloc (pfile, total_len + 1);
@@ -571,12 +628,13 @@ parse_include (pfile)
dir = pfile->directive->name;
/* Allow macro expansion. */
- header = cpp_get_token (pfile);
+ header = get_token_no_padding (pfile);
if (header->type != CPP_STRING && header->type != CPP_HEADER_NAME)
{
if (header->type != CPP_LESS)
{
- cpp_error (pfile, "#%s expects \"FILENAME\" or <FILENAME>", dir);
+ cpp_error (pfile, DL_ERROR,
+ "#%s expects \"FILENAME\" or <FILENAME>", dir);
return NULL;
}
@@ -587,7 +645,7 @@ parse_include (pfile)
if (header->val.str.len == 0)
{
- cpp_error (pfile, "empty file name in #%s", dir);
+ cpp_error (pfile, DL_ERROR, "empty file name in #%s", dir);
return NULL;
}
@@ -606,13 +664,13 @@ do_include_common (pfile, type)
use the normal search logic. */
if (type == IT_INCLUDE_NEXT && ! pfile->buffer->prev)
{
- cpp_warning (pfile, "#include_next in primary source file");
+ cpp_error (pfile, DL_WARNING, "#include_next in primary source file");
type = IT_INCLUDE;
}
else if (type == IT_IMPORT && CPP_OPTION (pfile, warn_import))
{
CPP_OPTION (pfile, warn_import) = 0;
- cpp_warning (pfile,
+ cpp_error (pfile, DL_WARNING,
"#import is obsolete, use an #ifndef wrapper in the header file");
}
@@ -621,7 +679,7 @@ do_include_common (pfile, type)
{
/* Prevent #include recursion. */
if (pfile->line_maps.depth >= CPP_STACK_MAX)
- cpp_fatal (pfile, "#include nested too deeply");
+ cpp_error (pfile, DL_ERROR, "#include nested too deeply");
else
{
check_eol (pfile);
@@ -630,7 +688,6 @@ do_include_common (pfile, type)
if (pfile->cb.include)
(*pfile->cb.include) (pfile, pfile->directive_line,
pfile->directive->name, header);
-
_cpp_execute_include (pfile, header, type);
}
}
@@ -679,7 +736,7 @@ read_flag (pfile, last)
}
if (token->type != CPP_EOF)
- cpp_error (pfile, "invalid flag \"%s\" in line directive",
+ cpp_error (pfile, DL_ERROR, "invalid flag \"%s\" in line directive",
cpp_token_as_text (pfile, token));
return 0;
}
@@ -687,32 +744,24 @@ read_flag (pfile, last)
/* Subroutine of do_line and do_linemarker. Returns a version of STR
which has a NUL terminator and all escape sequences converted to
their equivalents. Temporary, hopefully. */
-static U_CHAR *
+static uchar *
dequote_string (pfile, str, len)
cpp_reader *pfile;
- const U_CHAR *str;
+ const uchar *str;
unsigned int len;
{
- U_CHAR *result = _cpp_unaligned_alloc (pfile, len + 1);
- U_CHAR *dst = result;
- const U_CHAR *limit = str + len;
- unsigned int c;
- unsigned HOST_WIDE_INT mask;
+ uchar *result = _cpp_unaligned_alloc (pfile, len + 1);
+ uchar *dst = result;
+ const uchar *limit = str + len;
+ cppchar_t c;
- /* We need the mask to match the host's 'unsigned char', not the
- target's. */
- if (CHAR_BIT < HOST_BITS_PER_WIDE_INT)
- mask = ((unsigned HOST_WIDE_INT) 1 << CHAR_BIT) - 1;
- else
- mask = ~(unsigned HOST_WIDE_INT)0;
-
while (str < limit)
{
c = *str++;
if (c != '\\')
*dst++ = c;
else
- *dst++ = cpp_parse_escape (pfile, (const U_CHAR **)&str, limit, mask, 0);
+ *dst++ = cpp_parse_escape (pfile, &str, limit, 0);
}
*dst++ = '\0';
return result;
@@ -723,12 +772,12 @@ dequote_string (pfile, str, len)
number was well-formed, 1 if not. Temporary, hopefully. */
static int
strtoul_for_line (str, len, nump)
- const U_CHAR *str;
+ const uchar *str;
unsigned int len;
unsigned long *nump;
{
unsigned long reg = 0;
- U_CHAR c;
+ uchar c;
while (len--)
{
c = *str++;
@@ -761,13 +810,14 @@ do_line (pfile)
|| strtoul_for_line (token->val.str.text, token->val.str.len,
&new_lineno))
{
- cpp_error (pfile, "\"%s\" after #line is not a positive integer",
+ cpp_error (pfile, DL_ERROR,
+ "\"%s\" after #line is not a positive integer",
cpp_token_as_text (pfile, token));
return;
- }
+ }
if (CPP_PEDANTIC (pfile) && (new_lineno == 0 || new_lineno > cap))
- cpp_pedwarn (pfile, "line number out of range");
+ cpp_error (pfile, DL_PEDWARN, "line number out of range");
token = cpp_get_token (pfile);
if (token->type == CPP_STRING)
@@ -778,7 +828,7 @@ do_line (pfile)
}
else if (token->type != CPP_EOF)
{
- cpp_error (pfile, "\"%s\" is not a valid filename",
+ cpp_error (pfile, DL_ERROR, "\"%s\" is not a valid filename",
cpp_token_as_text (pfile, token));
return;
}
@@ -813,10 +863,10 @@ do_linemarker (pfile)
|| strtoul_for_line (token->val.str.text, token->val.str.len,
&new_lineno))
{
- cpp_error (pfile, "\"%s\" after # is not a positive integer",
+ cpp_error (pfile, DL_ERROR, "\"%s\" after # is not a positive integer",
cpp_token_as_text (pfile, token));
return;
- }
+ }
token = cpp_get_token (pfile);
if (token->type == CPP_STRING)
@@ -849,7 +899,7 @@ do_linemarker (pfile)
}
else if (token->type != CPP_EOF)
{
- cpp_error (pfile, "\"%s\" is not a valid filename",
+ cpp_error (pfile, DL_ERROR, "\"%s\" is not a valid filename",
cpp_token_as_text (pfile, token));
return;
}
@@ -882,10 +932,12 @@ _cpp_do_file_change (pfile, reason, to_file, file_line, sysp)
static void
do_diagnostic (pfile, code, print_dir)
cpp_reader *pfile;
- enum error_type code;
+ int code;
int print_dir;
{
- if (_cpp_begin_message (pfile, code, 0, 0))
+ if (_cpp_begin_message (pfile, code,
+ pfile->cur_token[-1].line,
+ pfile->cur_token[-1].col))
{
if (print_dir)
fprintf (stderr, "#%s ", pfile->directive->name);
@@ -899,7 +951,7 @@ static void
do_error (pfile)
cpp_reader *pfile;
{
- do_diagnostic (pfile, ERROR, 1);
+ do_diagnostic (pfile, DL_ERROR, 1);
}
static void
@@ -907,7 +959,7 @@ do_warning (pfile)
cpp_reader *pfile;
{
/* We want #warning diagnostics to be emitted in system headers too. */
- do_diagnostic (pfile, WARNING_SYSHDR, 1);
+ do_diagnostic (pfile, DL_WARNING_SYSHDR, 1);
}
/* Report program identification. */
@@ -918,7 +970,7 @@ do_ident (pfile)
const cpp_token *str = cpp_get_token (pfile);
if (str->type != CPP_STRING)
- cpp_error (pfile, "invalid #ident directive");
+ cpp_error (pfile, DL_ERROR, "invalid #ident directive");
else if (pfile->cb.ident)
(*pfile->cb.ident) (pfile, pfile->directive_line, &str->val.str);
@@ -1005,13 +1057,14 @@ cpp_register_pragma (pfile, space, name, handler)
{
if (entry->is_nspace)
clash:
- cpp_ice (pfile,
+ cpp_error (pfile, DL_ICE,
"registering \"%s\" as both a pragma and a pragma namespace",
NODE_NAME (node));
else if (space)
- cpp_ice (pfile, "#pragma %s %s is already registered", space, name);
+ cpp_error (pfile, DL_ICE, "#pragma %s %s is already registered",
+ space, name);
else
- cpp_ice (pfile, "#pragma %s is already registered", name);
+ cpp_error (pfile, DL_ICE, "#pragma %s is already registered", name);
}
else
insert_pragma_entry (pfile, chain, node, handler);
@@ -1023,7 +1076,6 @@ _cpp_init_internal_pragmas (pfile)
cpp_reader *pfile;
{
/* Pragmas in the global namespace. */
- cpp_register_pragma (pfile, 0, "poison", do_pragma_poison);
cpp_register_pragma (pfile, 0, "once", do_pragma_once);
/* New GCC-specific pragmas should be put in the GCC namespace. */
@@ -1086,18 +1138,18 @@ static void
do_pragma_once (pfile)
cpp_reader *pfile;
{
- cpp_warning (pfile, "#pragma once is obsolete");
-
+ cpp_error (pfile, DL_WARNING, "#pragma once is obsolete");
+
if (pfile->buffer->prev == NULL)
- cpp_warning (pfile, "#pragma once in main file");
+ cpp_error (pfile, DL_WARNING, "#pragma once in main file");
else
_cpp_never_reread (pfile->buffer->inc);
check_eol (pfile);
}
-/* Handle #pragma poison, to poison one or more identifiers so that
- the lexer produces a hard error for each subsequent usage. */
+/* Handle #pragma GCC poison, to poison one or more identifiers so
+ that the lexer produces a hard error for each subsequent usage. */
static void
do_pragma_poison (pfile)
cpp_reader *pfile;
@@ -1113,7 +1165,7 @@ do_pragma_poison (pfile)
break;
if (tok->type != CPP_NAME)
{
- cpp_error (pfile, "invalid #pragma GCC poison directive");
+ cpp_error (pfile, DL_ERROR, "invalid #pragma GCC poison directive");
break;
}
@@ -1122,7 +1174,8 @@ do_pragma_poison (pfile)
continue;
if (hp->type == NT_MACRO)
- cpp_warning (pfile, "poisoning existing macro \"%s\"", NODE_NAME (hp));
+ cpp_error (pfile, DL_WARNING, "poisoning existing macro \"%s\"",
+ NODE_NAME (hp));
_cpp_free_definition (hp);
hp->flags |= NODE_POISONED | NODE_DIAGNOSTIC;
}
@@ -1142,7 +1195,8 @@ do_pragma_system_header (pfile)
cpp_buffer *buffer = pfile->buffer;
if (buffer->prev == 0)
- cpp_warning (pfile, "#pragma system_header ignored outside include file");
+ cpp_error (pfile, DL_WARNING,
+ "#pragma system_header ignored outside include file");
else
{
check_eol (pfile);
@@ -1160,23 +1214,23 @@ do_pragma_dependency (pfile)
{
const cpp_token *header;
int ordering;
-
+
header = parse_include (pfile);
if (!header)
return;
ordering = _cpp_compare_file_date (pfile, header);
if (ordering < 0)
- cpp_warning (pfile, "cannot find source %s",
- cpp_token_as_text (pfile, header));
+ cpp_error (pfile, DL_WARNING, "cannot find source %s",
+ cpp_token_as_text (pfile, header));
else if (ordering > 0)
{
- cpp_warning (pfile, "current file is older than %s",
- cpp_token_as_text (pfile, header));
+ cpp_error (pfile, DL_WARNING, "current file is older than %s",
+ cpp_token_as_text (pfile, header));
if (cpp_get_token (pfile)->type != CPP_EOF)
{
_cpp_backup_tokens (pfile, 1);
- do_diagnostic (pfile, WARNING, 0);
+ do_diagnostic (pfile, DL_WARNING, 0);
}
}
}
@@ -1256,6 +1310,7 @@ destringize_and_run (pfile, in)
pfile->context = saved_context;
pfile->cur_token = saved_cur_token;
pfile->cur_run = saved_cur_run;
+ pfile->line--;
}
/* See above comment. For the moment, we'd like
@@ -1264,11 +1319,11 @@ destringize_and_run (pfile, in)
to be output as
- token1
- # 7 "file.c"
- #pragma foo
- # 7 "file.c"
- token2
+ token1
+ # 7 "file.c"
+ #pragma foo
+ # 7 "file.c"
+ token2
Getting the line markers is a little tricky. */
if (pfile->cb.line_change)
@@ -1285,17 +1340,16 @@ _cpp_do__Pragma (pfile)
if (string)
destringize_and_run (pfile, &string->val.str);
else
- cpp_error (pfile, "_Pragma takes a parenthesized string literal");
+ cpp_error (pfile, DL_ERROR,
+ "_Pragma takes a parenthesized string literal");
}
-/* Just ignore #sccs, on systems where we define it at all. */
-#ifdef SCCS_DIRECTIVE
+/* Just ignore #sccs on all systems. */
static void
do_sccs (pfile)
cpp_reader *pfile ATTRIBUTE_UNUSED;
{
}
-#endif
/* Handle #ifdef. */
static void
@@ -1309,10 +1363,11 @@ do_ifdef (pfile)
const cpp_hashnode *node = lex_macro_node (pfile);
if (node)
- skip = node->type != NT_MACRO;
-
- if (node)
- check_eol (pfile);
+ {
+ skip = node->type != NT_MACRO;
+ _cpp_mark_macro_used (node);
+ check_eol (pfile);
+ }
}
push_conditional (pfile, skip, T_IFDEF, 0);
@@ -1329,11 +1384,13 @@ do_ifndef (pfile)
if (! pfile->state.skipping)
{
node = lex_macro_node (pfile);
- if (node)
- skip = node->type == NT_MACRO;
if (node)
- check_eol (pfile);
+ {
+ skip = node->type == NT_MACRO;
+ _cpp_mark_macro_used (node);
+ check_eol (pfile);
+ }
}
push_conditional (pfile, skip, T_IFNDEF, node);
@@ -1351,7 +1408,7 @@ do_if (pfile)
int skip = 1;
if (! pfile->state.skipping)
- skip = _cpp_parse_expr (pfile) == 0;
+ skip = _cpp_parse_expr (pfile) == false;
push_conditional (pfile, skip, T_IF, pfile->mi_ind_cmacro);
}
@@ -1367,13 +1424,13 @@ do_else (pfile)
struct if_stack *ifs = buffer->if_stack;
if (ifs == NULL)
- cpp_error (pfile, "#else without #if");
+ cpp_error (pfile, DL_ERROR, "#else without #if");
else
{
if (ifs->type == T_ELSE)
{
- cpp_error (pfile, "#else after #else");
- cpp_error_with_line (pfile, ifs->line, 0,
+ cpp_error (pfile, DL_ERROR, "#else after #else");
+ cpp_error_with_line (pfile, DL_ERROR, ifs->line, 0,
"the conditional began here");
}
ifs->type = T_ELSE;
@@ -1386,7 +1443,7 @@ do_else (pfile)
ifs->mi_cmacro = 0;
/* Only check EOL if was not originally skipping. */
- if (!ifs->was_skipping)
+ if (!ifs->was_skipping && CPP_OPTION (pfile, warn_endif_labels))
check_eol (pfile);
}
}
@@ -1401,13 +1458,13 @@ do_elif (pfile)
struct if_stack *ifs = buffer->if_stack;
if (ifs == NULL)
- cpp_error (pfile, "#elif without #if");
+ cpp_error (pfile, DL_ERROR, "#elif without #if");
else
{
if (ifs->type == T_ELSE)
{
- cpp_error (pfile, "#elif after #else");
- cpp_error_with_line (pfile, ifs->line, 0,
+ cpp_error (pfile, DL_ERROR, "#elif after #else");
+ cpp_error_with_line (pfile, DL_ERROR, ifs->line, 0,
"the conditional began here");
}
ifs->type = T_ELIF;
@@ -1437,11 +1494,11 @@ do_endif (pfile)
struct if_stack *ifs = buffer->if_stack;
if (ifs == NULL)
- cpp_error (pfile, "#endif without #if");
+ cpp_error (pfile, DL_ERROR, "#endif without #if");
else
{
/* Only check EOL if was not originally skipping. */
- if (!ifs->was_skipping)
+ if (!ifs->was_skipping && CPP_OPTION (pfile, warn_endif_labels))
check_eol (pfile);
/* If potential control macro, we go back outside again. */
@@ -1520,7 +1577,7 @@ parse_answer (pfile, answerp, type)
if (type == T_UNASSERT && paren->type == CPP_EOF)
return 0;
- cpp_error (pfile, "missing '(' after predicate");
+ cpp_error (pfile, DL_ERROR, "missing '(' after predicate");
return 1;
}
@@ -1535,7 +1592,7 @@ parse_answer (pfile, answerp, type)
if (token->type == CPP_EOF)
{
- cpp_error (pfile, "missing ')' to complete answer");
+ cpp_error (pfile, DL_ERROR, "missing ')' to complete answer");
return 1;
}
@@ -1555,7 +1612,7 @@ parse_answer (pfile, answerp, type)
if (acount == 0)
{
- cpp_error (pfile, "predicate's answer is empty");
+ cpp_error (pfile, DL_ERROR, "predicate's answer is empty");
return 1;
}
@@ -1585,9 +1642,9 @@ parse_assertion (pfile, answerp, type)
*answerp = 0;
predicate = cpp_get_token (pfile);
if (predicate->type == CPP_EOF)
- cpp_error (pfile, "assertion without predicate");
+ cpp_error (pfile, DL_ERROR, "assertion without predicate");
else if (predicate->type != CPP_NAME)
- cpp_error (pfile, "predicate must be an identifier");
+ cpp_error (pfile, DL_ERROR, "predicate must be an identifier");
else if (parse_answer (pfile, answerp, type) == 0)
{
unsigned int len = NODE_LEN (predicate->val.node);
@@ -1632,20 +1689,27 @@ find_answer (node, candidate)
}
/* Test an assertion within a preprocessor conditional. Returns
- non-zero on failure, zero on success. On success, the result of
- the test is written into VALUE. */
+ nonzero on failure, zero on success. On success, the result of
+ the test is written into VALUE, otherwise the value 0. */
int
_cpp_test_assertion (pfile, value)
cpp_reader *pfile;
- int *value;
+ unsigned int *value;
{
struct answer *answer;
cpp_hashnode *node;
node = parse_assertion (pfile, &answer, T_IF);
+
+ /* For recovery, an erroneous assertion expression is handled as a
+ failing assertion. */
+ *value = 0;
+
if (node)
*value = (node->type == NT_ASSERTION &&
(answer == 0 || *find_answer (node, answer) != 0));
+ else if (pfile->cur_token[-1].type == CPP_EOF)
+ _cpp_backup_tokens (pfile, 1);
/* We don't commit the memory for the answer - it's temporary only. */
return node == 0;
@@ -1658,7 +1722,7 @@ do_assert (pfile)
{
struct answer *new_answer;
cpp_hashnode *node;
-
+
node = parse_assertion (pfile, &new_answer, T_ASSERT);
if (node)
{
@@ -1669,7 +1733,8 @@ do_assert (pfile)
{
if (*find_answer (node, new_answer))
{
- cpp_warning (pfile, "\"%s\" re-asserted", NODE_NAME (node) + 1);
+ cpp_error (pfile, DL_WARNING, "\"%s\" re-asserted",
+ NODE_NAME (node) + 1);
return;
}
new_answer->next = node->value.answers;
@@ -1691,7 +1756,7 @@ do_unassert (pfile)
{
cpp_hashnode *node;
struct answer *answer;
-
+
node = parse_assertion (pfile, &answer, T_UNASSERT);
/* It isn't an error to #unassert something that isn't asserted. */
if (node && node->type == NT_ASSERTION)
@@ -1732,7 +1797,7 @@ cpp_define (pfile, str)
char *buf, *p;
size_t count;
- /* Copy the entire option so we can modify it.
+ /* Copy the entire option so we can modify it.
Change the first "=" in the string to a space. If there is none,
tack " 1" on the end. */
@@ -1787,7 +1852,7 @@ cpp_unassert (pfile, str)
const char *str;
{
handle_assertion (pfile, str, T_UNASSERT);
-}
+}
/* Common code for cpp_assert (-A) and cpp_unassert (-A-). */
static void
@@ -1862,7 +1927,7 @@ cpp_set_callbacks (pfile, cb)
cpp_buffer *
cpp_push_buffer (pfile, buffer, len, from_stage3, return_at_eof)
cpp_reader *pfile;
- const U_CHAR *buffer;
+ const uchar *buffer;
size_t len;
int from_stage3;
int return_at_eof;
@@ -1874,7 +1939,7 @@ cpp_push_buffer (pfile, buffer, len, from_stage3, return_at_eof)
new->line_base = new->buf = new->cur = buffer;
new->rlimit = buffer + len;
- new->from_stage3 = from_stage3;
+ new->from_stage3 = from_stage3 || CPP_OPTION (pfile, traditional);
new->prev = pfile->buffer;
new->return_at_eof = return_at_eof;
new->saved_flags = BOL;
@@ -1884,37 +1949,50 @@ cpp_push_buffer (pfile, buffer, len, from_stage3, return_at_eof)
return new;
}
-/* If called from do_line, pops a single buffer. Otherwise pops all
- buffers until a real file is reached. Generates appropriate
- call-backs. */
+/* Pops a single buffer, with a file change call-back if appropriate.
+ Then pushes the next -include file, if any remain. */
void
_cpp_pop_buffer (pfile)
cpp_reader *pfile;
{
cpp_buffer *buffer = pfile->buffer;
+ struct include_file *inc = buffer->inc;
struct if_stack *ifs;
- bool pushed = false;
/* Walk back up the conditional stack till we reach its level at
entry to this file, issuing error messages. */
for (ifs = buffer->if_stack; ifs; ifs = ifs->next)
- cpp_error_with_line (pfile, ifs->line, 0,
+ cpp_error_with_line (pfile, DL_ERROR, ifs->line, 0,
"unterminated #%s", dtable[ifs->type].name);
/* In case of a missing #endif. */
pfile->state.skipping = 0;
- /* Update the reader's buffer before _cpp_do_file_change. */
+ /* _cpp_do_file_change expects pfile->buffer to be the new one. */
pfile->buffer = buffer->prev;
- if (buffer->inc)
- pushed = _cpp_pop_file_buffer (pfile, buffer->inc);
+ /* Free the buffer object now; we may want to push a new buffer
+ in _cpp_push_next_include_file. */
+ obstack_free (&pfile->buffer_ob, buffer);
+
+ if (inc)
+ {
+ _cpp_pop_file_buffer (pfile, inc);
+
+ /* Don't generate a callback for popping the main file. */
+ if (pfile->buffer)
+ {
+ _cpp_do_file_change (pfile, LC_LEAVE, 0, 0, 0);
- if (!pushed)
- obstack_free (&pfile->buffer_ob, buffer);
+ /* If this is the main file, there may be some -include
+ files left to push. */
+ if (!pfile->buffer->prev)
+ _cpp_maybe_push_include_file (pfile);
+ }
+ }
}
-/* Enter all recognised directives in the hash table. */
+/* Enter all recognized directives in the hash table. */
void
_cpp_init_directives (pfile)
cpp_reader *pfile;
diff --git a/contrib/gcc/cpplib.h b/contrib/gcc/cpplib.h
index c21ada0..7b3a54a 100644
--- a/contrib/gcc/cpplib.h
+++ b/contrib/gcc/cpplib.h
@@ -46,9 +46,9 @@ typedef struct cpp_callbacks cpp_callbacks;
struct answer;
struct file_name_map_list;
-/* The first two groups, apart from '=', can appear in preprocessor
- expressions. This allows a lookup table to be implemented in
- _cpp_parse_expr.
+/* The first three groups, apart from '=', can appear in preprocessor
+ expressions (+= and -= are used to indicate unary + and - resp.).
+ This allows a lookup table to be implemented in _cpp_parse_expr.
The first group, to CPP_LAST_EQ, can be immediately followed by an
'='. The lexer needs operators ending in '=', like ">>=", to be in
@@ -58,6 +58,7 @@ struct file_name_map_list;
#define CPP_LAST_EQ CPP_MAX
#define CPP_FIRST_DIGRAPH CPP_HASH
#define CPP_LAST_PUNCTUATOR CPP_DOT_STAR
+#define CPP_LAST_CPP_OP CPP_LESS_EQ
#define TTYPE_TABLE \
OP(CPP_EQ = 0, "=") \
@@ -85,13 +86,16 @@ struct file_name_map_list;
OP(CPP_COMMA, ",") /* grouping */ \
OP(CPP_OPEN_PAREN, "(") \
OP(CPP_CLOSE_PAREN, ")") \
+ TK(CPP_EOF, SPELL_NONE) \
OP(CPP_EQ_EQ, "==") /* compare */ \
OP(CPP_NOT_EQ, "!=") \
OP(CPP_GREATER_EQ, ">=") \
OP(CPP_LESS_EQ, "<=") \
\
+ /* These two are unary + / - in preprocessor expressions. */ \
OP(CPP_PLUS_EQ, "+=") /* math */ \
OP(CPP_MINUS_EQ, "-=") \
+\
OP(CPP_MULT_EQ, "*=") \
OP(CPP_DIV_EQ, "/=") \
OP(CPP_MOD_EQ, "%=") \
@@ -119,7 +123,7 @@ struct file_name_map_list;
OP(CPP_SCOPE, "::") \
OP(CPP_DEREF_STAR, "->*") \
OP(CPP_DOT_STAR, ".*") \
- OP(CPP_ATSIGN, "@") /* used in Objective C */ \
+ OP(CPP_ATSIGN, "@") /* used in Objective-C */ \
\
TK(CPP_NAME, SPELL_IDENT) /* word */ \
TK(CPP_NUMBER, SPELL_NUMBER) /* 34_be+ta */ \
@@ -135,8 +139,7 @@ struct file_name_map_list;
TK(CPP_COMMENT, SPELL_NUMBER) /* Only if output comments. */ \
/* SPELL_NUMBER happens to DTRT. */ \
TK(CPP_MACRO_ARG, SPELL_NONE) /* Macro argument. */ \
- TK(CPP_PADDING, SPELL_NONE) /* Whitespace for cpp0. */ \
- TK(CPP_EOF, SPELL_NONE) /* End of line or file. */
+ TK(CPP_PADDING, SPELL_NONE) /* Whitespace for cpp0. */
#define OP(e, s) e,
#define TK(e, s) e,
@@ -150,7 +153,7 @@ enum cpp_ttype
/* C language kind, used when calling cpp_reader_init. */
enum c_lang {CLK_GNUC89 = 0, CLK_GNUC99, CLK_STDC89, CLK_STDC94, CLK_STDC99,
- CLK_GNUCXX, CLK_CXX98, CLK_OBJC, CLK_OBJCXX, CLK_ASM};
+ CLK_GNUCXX, CLK_CXX98, CLK_ASM};
/* Payload of a NUMBER, STRING, CHAR or COMMENT token. */
struct cpp_string
@@ -187,9 +190,23 @@ struct cpp_token
} val;
};
-/* A standalone character. We may want to make it unsigned for the
- same reason we use unsigned char - to avoid signedness issues. */
-typedef int cppchar_t;
+/* A type wide enough to hold any multibyte source character.
+ cpplib's character constant interpreter requires an unsigned type.
+ Also, a typedef for the signed equivalent. */
+#ifndef MAX_WCHAR_TYPE_SIZE
+# define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
+#endif
+#if CHAR_BIT * SIZEOF_INT >= MAX_WCHAR_TYPE_SIZE
+# define CPPCHAR_SIGNED_T int
+#else
+# if CHAR_BIT * SIZEOF_LONG >= MAX_WCHAR_TYPE_SIZE || !HAVE_LONG_LONG
+# define CPPCHAR_SIGNED_T long
+# else
+# define CPPCHAR_SIGNED_T long long
+# endif
+#endif
+typedef unsigned CPPCHAR_SIGNED_T cppchar_t;
+typedef CPPCHAR_SIGNED_T cppchar_signed_t;
/* Values for opts.dump_macros.
dump_only means inhibit output of the preprocessed text
@@ -204,20 +221,12 @@ enum { dump_none = 0, dump_only, dump_names, dump_definitions };
carries all the options visible to the command line. */
struct cpp_options
{
- /* Name of input and output files. */
- const char *in_fname;
- const char *out_fname;
-
/* Characters between tab stops. */
unsigned int tabstop;
/* Pending options - -D, -U, -A, -I, -ixxx. */
struct cpp_pending *pending;
- /* File name which deps are being written to. This is 0 if deps are
- being written to stdout. */
- const char *deps_file;
-
/* Search paths for include files. */
struct search_path *quote_include; /* "" */
struct search_path *bracket_include; /* <> */
@@ -231,30 +240,29 @@ struct cpp_options
const char *include_prefix;
unsigned int include_prefix_len;
- /* -fleading_underscore sets this to "_". */
- const char *user_label_prefix;
-
/* The language we're preprocessing. */
enum c_lang lang;
/* Non-0 means -v, so print the full set of include dirs. */
unsigned char verbose;
- /* Nonzero means chars are signed. */
- unsigned char signed_char;
-
/* Nonzero means use extra default include directories for C++. */
unsigned char cplusplus;
/* Nonzero means handle cplusplus style comments */
unsigned char cplusplus_comments;
- /* Nonzero means handle #import, for objective C. */
+ /* Nonzero means define __OBJC__, treat @ as a special token, and
+ use the OBJC[PLUS]_INCLUDE_PATH environment variable. */
unsigned char objc;
/* Nonzero means don't copy comments into the output file. */
unsigned char discard_comments;
+ /* Nonzero means don't copy comments into the output file during
+ macro expansion. */
+ unsigned char discard_comments_in_macro_exp;
+
/* Nonzero means process the ISO trigraph sequences. */
unsigned char trigraphs;
@@ -264,24 +272,6 @@ struct cpp_options
/* Nonzero means to allow hexadecimal floats and LL suffixes. */
unsigned char extended_numbers;
- /* Nonzero means print the names of included files rather than the
- preprocessed output. 1 means just the #include "...", 2 means
- #include <...> as well. */
- unsigned char print_deps;
-
- /* Nonzero if phony targets are created for each header. */
- unsigned char deps_phony_targets;
-
- /* Nonzero if missing .h files in -M output are assumed to be
- generated files and not errors. */
- unsigned char print_deps_missing_files;
-
- /* If true, fopen (deps_file, "a") else fopen (deps_file, "w"). */
- unsigned char print_deps_append;
-
- /* If true, no dependency is generated on the main file. */
- unsigned char deps_ignore_main_file;
-
/* Nonzero means print names of header files (-H). */
unsigned char print_include_names;
@@ -307,10 +297,23 @@ struct cpp_options
/* Nonzero means warn if #import is used. */
unsigned char warn_import;
+ /* Nonzero means warn about multicharacter charconsts. */
+ unsigned char warn_multichar;
+
/* Nonzero means warn about various incompatibilities with
traditional C. */
unsigned char warn_traditional;
+ /* Nonzero means warn about long long numeric constants. */
+ unsigned char warn_long_long;
+
+ /* Nonzero means warn about text after an #endif (or #else). */
+ unsigned char warn_endif_labels;
+
+ /* Nonzero means warn about implicit sign changes owing to integer
+ promotions. */
+ unsigned char warn_num_sign_change;
+
/* Nonzero means turn warnings into errors. */
unsigned char warnings_are_errors;
@@ -335,10 +338,13 @@ struct cpp_options
/* Nonzero means warn if undefined identifiers are evaluated in an #if. */
unsigned char warn_undef;
+ /* Nonzero means warn of unused macros from the main file. */
+ unsigned char warn_unused_macros;
+
/* Nonzero for the 1999 C Standard, including corrigenda and amendments. */
unsigned char c99;
- /* Nonzero if conforming to some particular standard. */
+ /* Nonzero if we are conforming to a specific C or C++ standard. */
unsigned char std;
/* Nonzero means give all the error messages the ANSI standard requires. */
@@ -366,10 +372,37 @@ struct cpp_options
/* Nonzero means handle C++ alternate operator names. */
unsigned char operator_names;
- /* True if --help, --version or --target-help appeared in the
- options. Stand-alone CPP should then bail out after option
- parsing; drivers might want to continue printing help. */
- unsigned char help_only;
+ /* True for traditional preprocessing. */
+ unsigned char traditional;
+
+ /* Dependency generation. */
+ struct
+ {
+ /* Style of header dependencies to generate. */
+ enum {DEPS_NONE = 0, DEPS_USER, DEPS_SYSTEM } style;
+
+ /* Assume missing files are generated files. */
+ bool missing_files;
+
+ /* Generate phony targets for each dependency apart from the first
+ one. */
+ bool phony_targets;
+
+ /* If true, no dependency is generated on the main file. */
+ bool ignore_main_file;
+ } deps;
+
+ /* Target-specific features set by the front end or client. */
+
+ /* Precision for target CPP arithmetic, target characters, target
+ ints and target wide characters, respectively. */
+ size_t precision, char_precision, int_precision, wchar_precision;
+
+ /* True means chars (wide chars) are unsigned. */
+ bool unsigned_char, unsigned_wchar;
+
+ /* Nonzero means __STDC__ should have the value 0 in system headers. */
+ unsigned char stdc_0_in_system_headers;
};
/* Call backs. */
@@ -384,12 +417,11 @@ struct cpp_callbacks
void (*undef) PARAMS ((cpp_reader *, unsigned int, cpp_hashnode *));
void (*ident) PARAMS ((cpp_reader *, unsigned int, const cpp_string *));
void (*def_pragma) PARAMS ((cpp_reader *, unsigned int));
+ /* Called when the client has a chance to properly register
+ built-ins with cpp_define() and cpp_assert(). */
+ void (*register_builtins) PARAMS ((cpp_reader *));
};
-#define CPP_FATAL_LIMIT 1000
-/* True if we have seen a "fatal" error. */
-#define CPP_FATAL_ERRORS(PFILE) (cpp_errors (PFILE) >= CPP_FATAL_LIMIT)
-
/* Name under which this program was invoked. */
extern const char *progname;
@@ -463,6 +495,18 @@ struct cpp_hashnode
/* Call this first to get a handle to pass to other functions. */
extern cpp_reader *cpp_create_reader PARAMS ((enum c_lang));
+/* Call this to change the selected language standard (e.g. because of
+ command line options). */
+extern void cpp_set_lang PARAMS ((cpp_reader *, enum c_lang));
+
+/* Add a dependency TARGET. Quote it for "make" if QUOTE. Can be
+ called any number of times before cpp_read_main_file(). If no
+ targets have been added before cpp_read_main_file(), then the
+ default target is used. */
+extern void cpp_add_dependency_target PARAMS ((cpp_reader *,
+ const char * target,
+ int quote));
+
/* Call these to get pointers to the options and callback structures
for a given reader. These pointers are good until you call
cpp_finish on that reader. You can either edit the callbacks
@@ -476,14 +520,10 @@ extern void cpp_set_callbacks PARAMS ((cpp_reader *, cpp_callbacks *));
/* Now call cpp_handle_option[s] to handle 1[or more] switches. The
return value is the number of arguments used. If
cpp_handle_options returns without using all arguments, it couldn't
- understand the next switch. When there are no switches left, you
- must call cpp_post_options before calling cpp_read_main_file. Only
- after cpp_post_options are the contents of the cpp_options
- structure reliable. Options processing is not completed until you
- call cpp_finish_options. */
+ understand the next switch. Options processing is not completed
+ until you call cpp_finish_options. */
extern int cpp_handle_options PARAMS ((cpp_reader *, int, char **));
-extern int cpp_handle_option PARAMS ((cpp_reader *, int, char **, int));
-extern void cpp_post_options PARAMS ((cpp_reader *));
+extern int cpp_handle_option PARAMS ((cpp_reader *, int, char **));
/* This function reads the file, but does not start preprocessing. It
returns the name of the original file; this is the same as the
@@ -492,7 +532,7 @@ extern void cpp_post_options PARAMS ((cpp_reader *));
too. If there was an error opening the file, it returns NULL.
If you want cpplib to manage its own hashtable, pass in a NULL
- pointer. Otherise you should pass in an initialised hash table
+ pointer. Otherise you should pass in an initialized hash table
that cpplib will share; this technique is used by the C front
ends. */
extern const char *cpp_read_main_file PARAMS ((cpp_reader *, const char *,
@@ -505,10 +545,17 @@ extern const char *cpp_read_main_file PARAMS ((cpp_reader *, const char *,
from cpp_read_main_file, before they get debug callbacks. */
extern void cpp_finish_options PARAMS ((cpp_reader *));
+/* Call this to finish preprocessing. If you requested dependency
+ generation, pass an open stream to write the information to,
+ otherwise NULL. It is your responsibility to close the stream.
+
+ Returns cpp_errors (pfile). */
+extern int cpp_finish PARAMS ((cpp_reader *, FILE *deps_stream));
+
/* Call this to release the handle at the end of preprocessing. Any
use of the handle after this function returns is invalid. Returns
cpp_errors (pfile). */
-extern int cpp_destroy PARAMS ((cpp_reader *));
+extern void cpp_destroy PARAMS ((cpp_reader *));
/* Error count. */
extern unsigned int cpp_errors PARAMS ((cpp_reader *));
@@ -522,7 +569,6 @@ extern void cpp_register_pragma PARAMS ((cpp_reader *,
const char *, const char *,
void (*) PARAMS ((cpp_reader *))));
-extern void cpp_finish PARAMS ((cpp_reader *));
extern int cpp_avoid_paste PARAMS ((cpp_reader *, const cpp_token *,
const cpp_token *));
extern const cpp_token *cpp_get_token PARAMS ((cpp_reader *));
@@ -531,10 +577,12 @@ extern const unsigned char *cpp_macro_definition PARAMS ((cpp_reader *,
extern void _cpp_backup_tokens PARAMS ((cpp_reader *, unsigned int));
/* Evaluate a CPP_CHAR or CPP_WCHAR token. */
-extern HOST_WIDE_INT
+extern cppchar_t
cpp_interpret_charconst PARAMS ((cpp_reader *, const cpp_token *,
- int, int, unsigned int *));
+ unsigned int *, int *));
+/* Used to register builtins during the register_builtins callback.
+ The text is the same as the command line argument. */
extern void cpp_define PARAMS ((cpp_reader *, const char *));
extern void cpp_assert PARAMS ((cpp_reader *, const char *));
extern void cpp_undef PARAMS ((cpp_reader *, const char *));
@@ -545,32 +593,95 @@ extern cpp_buffer *cpp_push_buffer PARAMS ((cpp_reader *,
int, int));
extern int cpp_defined PARAMS ((cpp_reader *, const unsigned char *, int));
+/* A preprocessing number. Code assumes that any unused high bits of
+ the double integer are set to zero. */
+typedef unsigned HOST_WIDE_INT cpp_num_part;
+typedef struct cpp_num cpp_num;
+struct cpp_num
+{
+ cpp_num_part high;
+ cpp_num_part low;
+ bool unsignedp; /* True if value should be treated as unsigned. */
+ bool overflow; /* True if the most recent calculation overflowed. */
+};
+
+/* cpplib provides two interfaces for interpretation of preprocessing
+ numbers.
+
+ cpp_classify_number categorizes numeric constants according to
+ their field (integer, floating point, or invalid), radix (decimal,
+ octal, hexadecimal), and type suffixes. */
+
+#define CPP_N_CATEGORY 0x000F
+#define CPP_N_INVALID 0x0000
+#define CPP_N_INTEGER 0x0001
+#define CPP_N_FLOATING 0x0002
+
+#define CPP_N_WIDTH 0x00F0
+#define CPP_N_SMALL 0x0010 /* int, float. */
+#define CPP_N_MEDIUM 0x0020 /* long, double. */
+#define CPP_N_LARGE 0x0040 /* long long, long double. */
+
+#define CPP_N_RADIX 0x0F00
+#define CPP_N_DECIMAL 0x0100
+#define CPP_N_HEX 0x0200
+#define CPP_N_OCTAL 0x0400
+
+#define CPP_N_UNSIGNED 0x1000 /* Properties. */
+#define CPP_N_IMAGINARY 0x2000
+
+/* Classify a CPP_NUMBER token. The return value is a combination of
+ the flags from the above sets. */
+extern unsigned cpp_classify_number PARAMS ((cpp_reader *, const cpp_token *));
+
+/* Evaluate a token classified as category CPP_N_INTEGER. */
+extern cpp_num cpp_interpret_integer PARAMS ((cpp_reader *, const cpp_token *,
+ unsigned int type));
+
+/* Sign extend a number, with PRECISION significant bits and all
+ others assumed clear, to fill out a cpp_num structure. */
+cpp_num cpp_num_sign_extend PARAMS ((cpp_num, size_t));
+
+/* Diagnostic levels. To get a dianostic without associating a
+ position in the translation unit with it, use cpp_error_with_line
+ with a line number of zero. */
+
+/* Warning, an error with -Werror. */
+#define DL_WARNING 0x00
+/* Same as DL_WARNING, except it is not suppressed in system headers. */
+#define DL_WARNING_SYSHDR 0x01
+/* Warning, an error with -pedantic-errors or -Werror. */
+#define DL_PEDWARN 0x02
+/* An error. */
+#define DL_ERROR 0x03
+/* An internal consistency check failed. Prints "internal error: ",
+ otherwise the same as DL_ERROR. */
+#define DL_ICE 0x04
+/* Extracts a diagnostic level from an int. */
+#define DL_EXTRACT(l) (l & 0xf)
+/* Nonzero if a diagnostic level is one of the warnings. */
+#define DL_WARNING_P(l) (DL_EXTRACT (l) >= DL_WARNING \
+ && DL_EXTRACT (l) <= DL_PEDWARN)
+
/* N.B. The error-message-printer prototypes have not been nicely
formatted because exgettext needs to see 'msgid' on the same line
as the name of the function in order to work properly. Only the
string argument gets a name in an effort to keep the lines from
getting ridiculously oversized. */
-extern void cpp_ice PARAMS ((cpp_reader *, const char *msgid, ...))
- ATTRIBUTE_PRINTF_2;
-extern void cpp_fatal PARAMS ((cpp_reader *, const char *msgid, ...))
- ATTRIBUTE_PRINTF_2;
-extern void cpp_error PARAMS ((cpp_reader *, const char *msgid, ...))
- ATTRIBUTE_PRINTF_2;
-extern void cpp_warning PARAMS ((cpp_reader *, const char *msgid, ...))
- ATTRIBUTE_PRINTF_2;
-extern void cpp_pedwarn PARAMS ((cpp_reader *, const char *msgid, ...))
- ATTRIBUTE_PRINTF_2;
-extern void cpp_notice PARAMS ((cpp_reader *, const char *msgid, ...))
- ATTRIBUTE_PRINTF_2;
-extern void cpp_error_with_line PARAMS ((cpp_reader *, int, int, const char *msgid, ...))
- ATTRIBUTE_PRINTF_4;
-extern void cpp_warning_with_line PARAMS ((cpp_reader *, int, int, const char *msgid, ...))
- ATTRIBUTE_PRINTF_4;
-extern void cpp_pedwarn_with_line PARAMS ((cpp_reader *, int, int, const char *msgid, ...))
- ATTRIBUTE_PRINTF_4;
-extern void cpp_error_from_errno PARAMS ((cpp_reader *, const char *));
-extern void cpp_notice_from_errno PARAMS ((cpp_reader *, const char *));
+/* Output a diagnostic of some kind. */
+extern void cpp_error PARAMS ((cpp_reader *, int, const char *msgid, ...))
+ ATTRIBUTE_PRINTF_3;
+
+/* Output a diagnostic of severity LEVEL, with "MSG: " preceding the
+ error string of errno. No location is printed. */
+extern void cpp_errno PARAMS ((cpp_reader *, int level, const char *msg));
+
+/* Same as cpp_error, except additionally specifies a position as a
+ (translation unit) physical line and physical column. If the line is
+ zero, then no location is printed. */
+extern void cpp_error_with_line PARAMS ((cpp_reader *, int, unsigned, unsigned, const char *msgid, ...))
+ ATTRIBUTE_PRINTF_5;
/* In cpplex.c */
extern int cpp_ideq PARAMS ((const cpp_token *,
@@ -578,10 +689,15 @@ extern int cpp_ideq PARAMS ((const cpp_token *,
extern void cpp_output_line PARAMS ((cpp_reader *, FILE *));
extern void cpp_output_token PARAMS ((const cpp_token *, FILE *));
extern const char *cpp_type2name PARAMS ((enum cpp_ttype));
-extern unsigned int cpp_parse_escape PARAMS ((cpp_reader *,
- const unsigned char **,
- const unsigned char *,
- unsigned HOST_WIDE_INT, int));
+/* Returns the value of an escape sequence, truncated to the correct
+ target precision. PSTR points to the input pointer, which is just
+ after the backslash. LIMIT is how much text we have. WIDE is true
+ if the escape sequence is part of a wide character constant or
+ string literal. Handles all relevant diagnostics. */
+extern cppchar_t cpp_parse_escape PARAMS ((cpp_reader *,
+ const unsigned char ** pstr,
+ const unsigned char *limit,
+ int wide));
/* In cpphash.c */
@@ -606,6 +722,9 @@ extern unsigned char *cpp_quote_string PARAMS ((unsigned char *,
extern int cpp_included PARAMS ((cpp_reader *, const char *));
extern void cpp_make_system_header PARAMS ((cpp_reader *, int, int));
+/* In cppmain.c */
+extern void cpp_preprocess_file PARAMS ((cpp_reader *, const char *, FILE *));
+
#ifdef __cplusplus
}
#endif
diff --git a/contrib/gcc/cppmacro.c b/contrib/gcc/cppmacro.c
index 70e52fd..b97fe81 100644
--- a/contrib/gcc/cppmacro.c
+++ b/contrib/gcc/cppmacro.c
@@ -28,18 +28,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "cpplib.h"
#include "cpphash.h"
-struct cpp_macro
-{
- cpp_hashnode **params; /* Parameters, if any. */
- cpp_token *expansion; /* First token of replacement list. */
- unsigned int line; /* Starting line number. */
- unsigned int count; /* Number of tokens in expansion. */
- unsigned short paramc; /* Number of parameters. */
- unsigned int fun_like : 1; /* If a function-like macro. */
- unsigned int variadic : 1; /* If a variadic macro. */
- unsigned int syshdr : 1; /* If macro defined in system header. */
-};
-
typedef struct macro_arg macro_arg;
struct macro_arg
{
@@ -64,28 +52,51 @@ static cpp_context *next_context PARAMS ((cpp_reader *));
static const cpp_token *padding_token
PARAMS ((cpp_reader *, const cpp_token *));
static void expand_arg PARAMS ((cpp_reader *, macro_arg *));
-static const cpp_token *new_string_token PARAMS ((cpp_reader *, U_CHAR *,
+static const cpp_token *new_string_token PARAMS ((cpp_reader *, uchar *,
unsigned int));
-static const cpp_token *new_number_token PARAMS ((cpp_reader *, unsigned int));
static const cpp_token *stringify_arg PARAMS ((cpp_reader *, macro_arg *));
static void paste_all_tokens PARAMS ((cpp_reader *, const cpp_token *));
static bool paste_tokens PARAMS ((cpp_reader *, const cpp_token **,
const cpp_token *));
-static void replace_args PARAMS ((cpp_reader *, cpp_hashnode *, macro_arg *));
+static void replace_args PARAMS ((cpp_reader *, cpp_hashnode *, cpp_macro *,
+ macro_arg *));
static _cpp_buff *funlike_invocation_p PARAMS ((cpp_reader *, cpp_hashnode *));
+static bool create_iso_definition PARAMS ((cpp_reader *, cpp_macro *));
/* #define directive parsing and handling. */
static cpp_token *alloc_expansion_token PARAMS ((cpp_reader *, cpp_macro *));
static cpp_token *lex_expansion_token PARAMS ((cpp_reader *, cpp_macro *));
-static int warn_of_redefinition PARAMS ((const cpp_hashnode *,
- const cpp_macro *));
-static int save_parameter PARAMS ((cpp_reader *, cpp_macro *, cpp_hashnode *));
-static int parse_params PARAMS ((cpp_reader *, cpp_macro *));
+static bool warn_of_redefinition PARAMS ((cpp_reader *, const cpp_hashnode *,
+ const cpp_macro *));
+static bool parse_params PARAMS ((cpp_reader *, cpp_macro *));
static void check_trad_stringification PARAMS ((cpp_reader *,
const cpp_macro *,
const cpp_string *));
+/* Emits a warning if NODE is a macro defined in the main file that
+ has not been used. */
+int
+_cpp_warn_if_unused_macro (pfile, node, v)
+ cpp_reader *pfile;
+ cpp_hashnode *node;
+ void *v ATTRIBUTE_UNUSED;
+{
+ if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
+ {
+ cpp_macro *macro = node->value.macro;
+
+ if (!macro->used
+ /* Skip front-end built-ins and command line macros. */
+ && macro->line >= pfile->first_unused_line
+ && MAIN_FILE_P (lookup_line (&pfile->line_maps, macro->line)))
+ cpp_error_with_line (pfile, DL_WARNING, macro->line, 0,
+ "macro \"%s\" is not used", NODE_NAME (node));
+ }
+
+ return 1;
+}
+
/* Allocates and returns a CPP_STRING token, containing TEXT of length
LEN, after null-terminating it. TEXT must be in permanent storage. */
static const cpp_token *
@@ -104,24 +115,6 @@ new_string_token (pfile, text, len)
return token;
}
-/* Allocates and returns a CPP_NUMBER token evaluating to NUMBER. */
-static const cpp_token *
-new_number_token (pfile, number)
- cpp_reader *pfile;
- unsigned int number;
-{
- cpp_token *token = _cpp_temp_token (pfile);
- /* 21 bytes holds all NUL-terminated unsigned 64-bit numbers. */
- unsigned char *buf = _cpp_unaligned_alloc (pfile, 21);
-
- sprintf ((char *) buf, "%u", number);
- token->type = CPP_NUMBER;
- token->val.str.text = buf;
- token->val.str.len = ustrlen (buf);
- token->flags = 0;
- return token;
-}
-
static const char * const monthnames[] =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
@@ -132,25 +125,27 @@ static const char * const monthnames[] =
on the context stack. Also handles _Pragma, for which no new token
is created. Returns 1 if it generates a new token context, 0 to
return the token to the caller. */
-static int
-builtin_macro (pfile, node)
+const uchar *
+_cpp_builtin_macro_text (pfile, node)
cpp_reader *pfile;
cpp_hashnode *node;
{
- const cpp_token *result;
+ const uchar *result = NULL;
+ unsigned int number = 1;
switch (node->value.builtin)
{
default:
- cpp_ice (pfile, "invalid built-in macro \"%s\"", NODE_NAME (node));
- return 0;
+ cpp_error (pfile, DL_ICE, "invalid built-in macro \"%s\"",
+ NODE_NAME (node));
+ break;
case BT_FILE:
case BT_BASE_FILE:
{
unsigned int len;
const char *name;
- U_CHAR *buf;
+ uchar *buf;
const struct line_map *map = pfile->map;
if (node->value.builtin == BT_BASE_FILE)
@@ -159,10 +154,12 @@ builtin_macro (pfile, node)
name = map->to_file;
len = strlen (name);
- buf = _cpp_unaligned_alloc (pfile, len * 4 + 1);
- len = cpp_quote_string (buf, (const unsigned char *) name, len) - buf;
-
- result = new_string_token (pfile, buf, len);
+ buf = _cpp_unaligned_alloc (pfile, len * 4 + 3);
+ result = buf;
+ *buf = '"';
+ buf = cpp_quote_string (buf + 1, (const unsigned char *) name, len);
+ *buf++ = '"';
+ *buf = '\0';
}
break;
@@ -170,61 +167,107 @@ builtin_macro (pfile, node)
/* The line map depth counts the primary source as level 1, but
historically __INCLUDE_DEPTH__ has called the primary source
level 0. */
- result = new_number_token (pfile, pfile->line_maps.depth - 1);
+ number = pfile->line_maps.depth - 1;
break;
case BT_SPECLINE:
/* If __LINE__ is embedded in a macro, it must expand to the
line of the macro's invocation, not its definition.
Otherwise things like assert() will not work properly. */
- result = new_number_token (pfile,
- SOURCE_LINE (pfile->map,
- pfile->cur_token[-1].line));
+ if (CPP_OPTION (pfile, traditional))
+ number = pfile->line;
+ else
+ number = pfile->cur_token[-1].line;
+ number = SOURCE_LINE (pfile->map, number);
break;
+ /* __STDC__ has the value 1 under normal circumstances.
+ However, if (a) we are in a system header, (b) the option
+ stdc_0_in_system_headers is true (set by target config), and
+ (c) we are not in strictly conforming mode, then it has the
+ value 0. */
case BT_STDC:
{
- int stdc = (!CPP_IN_SYSTEM_HEADER (pfile)
- || pfile->spec_nodes.n__STRICT_ANSI__->type != NT_VOID);
- result = new_number_token (pfile, stdc);
+ if (CPP_IN_SYSTEM_HEADER (pfile)
+ && CPP_OPTION (pfile, stdc_0_in_system_headers)
+ && !CPP_OPTION (pfile,std))
+ number = 0;
+ else
+ number = 1;
}
break;
case BT_DATE:
case BT_TIME:
- if (pfile->date.type == CPP_EOF)
+ if (pfile->date == NULL)
{
/* Allocate __DATE__ and __TIME__ strings from permanent
storage. We only do this once, and don't generate them
at init time, because time() and localtime() are very
slow on some systems. */
- time_t tt = time (NULL);
- struct tm *tb = localtime (&tt);
-
- pfile->date.val.str.text =
- _cpp_unaligned_alloc (pfile, sizeof ("Oct 11 1347"));
- pfile->date.val.str.len = sizeof ("Oct 11 1347") - 1;
- pfile->date.type = CPP_STRING;
- pfile->date.flags = 0;
- sprintf ((char *) pfile->date.val.str.text, "%s %2d %4d",
- monthnames[tb->tm_mon], tb->tm_mday, tb->tm_year + 1900);
-
- pfile->time.val.str.text =
- _cpp_unaligned_alloc (pfile, sizeof ("12:34:56"));
- pfile->time.val.str.len = sizeof ("12:34:56") - 1;
- pfile->time.type = CPP_STRING;
- pfile->time.flags = 0;
- sprintf ((char *) pfile->time.val.str.text, "%02d:%02d:%02d",
- tb->tm_hour, tb->tm_min, tb->tm_sec);
+ time_t tt;
+ struct tm *tb = NULL;
+
+ /* (time_t) -1 is a legitimate value for "number of seconds
+ since the Epoch", so we have to do a little dance to
+ distinguish that from a genuine error. */
+ errno = 0;
+ tt = time(NULL);
+ if (tt != (time_t)-1 || errno == 0)
+ tb = localtime (&tt);
+
+ if (tb)
+ {
+ pfile->date = _cpp_unaligned_alloc (pfile,
+ sizeof ("\"Oct 11 1347\""));
+ sprintf ((char *) pfile->date, "\"%s %2d %4d\"",
+ monthnames[tb->tm_mon], tb->tm_mday, tb->tm_year + 1900);
+
+ pfile->time = _cpp_unaligned_alloc (pfile,
+ sizeof ("\"12:34:56\""));
+ sprintf ((char *) pfile->time, "\"%02d:%02d:%02d\"",
+ tb->tm_hour, tb->tm_min, tb->tm_sec);
+ }
+ else
+ {
+ cpp_errno (pfile, DL_WARNING,
+ "could not determine date and time");
+
+ pfile->date = U"\"??? ?? ????\"";
+ pfile->time = U"\"??:??:??\"";
+ }
}
if (node->value.builtin == BT_DATE)
- result = &pfile->date;
+ result = pfile->date;
else
- result = &pfile->time;
+ result = pfile->time;
break;
+ }
+
+ if (result == NULL)
+ {
+ /* 21 bytes holds all NUL-terminated unsigned 64-bit numbers. */
+ result = _cpp_unaligned_alloc (pfile, 21);
+ sprintf ((char *) result, "%u", number);
+ }
+
+ return result;
+}
+
+/* Convert builtin macros like __FILE__ to a token and push it on the
+ context stack. Also handles _Pragma, for which no new token is
+ created. Returns 1 if it generates a new token context, 0 to
+ return the token to the caller. */
+static int
+builtin_macro (pfile, node)
+ cpp_reader *pfile;
+ cpp_hashnode *node;
+{
+ const uchar *buf;
- case BT_PRAGMA:
+ if (node->value.builtin == BT_PRAGMA)
+ {
/* Don't interpret _Pragma within directives. The standard is
not clear on this, but to me this makes most sense. */
if (pfile->state.in_directive)
@@ -234,7 +277,24 @@ builtin_macro (pfile, node)
return 1;
}
- push_token_context (pfile, NULL, result, 1);
+ buf = _cpp_builtin_macro_text (pfile, node);
+
+ cpp_push_buffer (pfile, buf, ustrlen (buf), /* from_stage3 */ true, 1);
+
+ /* Tweak the column number the lexer will report. */
+ pfile->buffer->col_adjust = pfile->cur_token[-1].col - 1;
+
+ /* We don't want a leading # to be interpreted as a directive. */
+ pfile->buffer->saved_flags = 0;
+
+ /* Set pfile->cur_token as required by _cpp_lex_direct. */
+ pfile->cur_token = _cpp_temp_token (pfile);
+ push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1);
+ if (pfile->buffer->cur != pfile->buffer->rlimit)
+ cpp_error (pfile, DL_ICE, "invalid built-in macro \"%s\"",
+ NODE_NAME (node));
+ _cpp_pop_buffer (pfile);
+
return 1;
}
@@ -242,15 +302,15 @@ builtin_macro (pfile, node)
backslashes and double quotes. Non-printable characters are
converted to octal. DEST must be of sufficient size. Returns
a pointer to the end of the string. */
-U_CHAR *
+uchar *
cpp_quote_string (dest, src, len)
- U_CHAR *dest;
- const U_CHAR *src;
+ uchar *dest;
+ const uchar *src;
unsigned int len;
{
while (len--)
{
- U_CHAR c = *src++;
+ uchar c = *src++;
if (c == '\\' || c == '"')
{
@@ -343,7 +403,8 @@ stringify_arg (pfile, arg)
/* Ignore the final \ of invalid string literals. */
if (backslash_count & 1)
{
- cpp_warning (pfile, "invalid string literal, ignoring final '\\'");
+ cpp_error (pfile, DL_WARNING,
+ "invalid string literal, ignoring final '\\'");
dest--;
}
@@ -359,7 +420,7 @@ stringify_arg (pfile, arg)
return new_string_token (pfile, dest - len, len);
}
-/* Try to paste two tokens. On success, return non-zero. In any
+/* Try to paste two tokens. On success, return nonzero. In any
case, PLHS is updated to point to the pasted token, which is
guaranteed to not have the PASTE_LEFT flag set. */
static bool
@@ -381,8 +442,7 @@ paste_tokens (pfile, plhs, rhs)
It is simpler to insert a space here, rather than modifying the
lexer to ignore comments in some circumstances. Simply returning
false doesn't work, since we want to clear the PASTE_LEFT flag. */
- if (lhs->type == CPP_DIV
- && (rhs->type == CPP_MULT || rhs->type == CPP_DIV))
+ if (lhs->type == CPP_DIV && rhs->type != CPP_EQ)
*end++ = ' ';
end = cpp_spell_token (pfile, rhs, end);
*end = '\0';
@@ -427,9 +487,9 @@ paste_all_tokens (pfile, lhs)
inserted. In either case, the constraints to #define
guarantee we have at least one more token. */
if (context->direct_p)
- rhs = context->first.token++;
+ rhs = FIRST (context).token++;
else
- rhs = *context->first.ptoken++;
+ rhs = *FIRST (context).ptoken++;
if (rhs->type == CPP_PADDING)
abort ();
@@ -438,12 +498,12 @@ paste_all_tokens (pfile, lhs)
{
_cpp_backup_tokens (pfile, 1);
- /* Mandatory warning for all apart from assembler. */
+ /* Mandatory error for all apart from assembler. */
if (CPP_OPTION (pfile, lang) != CLK_ASM)
- cpp_warning (pfile,
+ cpp_error (pfile, DL_ERROR,
"pasting \"%s\" and \"%s\" does not give a valid preprocessing token",
- cpp_token_as_text (pfile, lhs),
- cpp_token_as_text (pfile, rhs));
+ cpp_token_as_text (pfile, lhs),
+ cpp_token_as_text (pfile, rhs));
break;
}
}
@@ -453,6 +513,52 @@ paste_all_tokens (pfile, lhs)
push_token_context (pfile, NULL, lhs, 1);
}
+/* Returns TRUE if the number of arguments ARGC supplied in an
+ invocation of the MACRO referenced by NODE is valid. An empty
+ invocation to a macro with no parameters should pass ARGC as zero.
+
+ Note that MACRO cannot necessarily be deduced from NODE, in case
+ NODE was redefined whilst collecting arguments. */
+bool
+_cpp_arguments_ok (pfile, macro, node, argc)
+ cpp_reader *pfile;
+ cpp_macro *macro;
+ const cpp_hashnode *node;
+ unsigned int argc;
+{
+ if (argc == macro->paramc)
+ return true;
+
+ if (argc < macro->paramc)
+ {
+ /* As an extension, a rest argument is allowed to not appear in
+ the invocation at all.
+ e.g. #define debug(format, args...) something
+ debug("string");
+
+ This is exactly the same as if there had been an empty rest
+ argument - debug("string", ). */
+
+ if (argc + 1 == macro->paramc && macro->variadic)
+ {
+ if (CPP_PEDANTIC (pfile) && ! macro->syshdr)
+ cpp_error (pfile, DL_PEDWARN,
+ "ISO C99 requires rest arguments to be used");
+ return true;
+ }
+
+ cpp_error (pfile, DL_ERROR,
+ "macro \"%s\" requires %u arguments, but only %u given",
+ NODE_NAME (node), macro->paramc, argc);
+ }
+ else
+ cpp_error (pfile, DL_ERROR,
+ "macro \"%s\" passed %u arguments, but takes just %u",
+ NODE_NAME (node), argc, macro->paramc);
+
+ return false;
+}
+
/* Reads and returns the arguments to a function-like macro
invocation. Assumes the opening parenthesis has been processed.
If there is an error, emits an appropriate diagnostic and returns
@@ -468,7 +574,6 @@ collect_args (pfile, node)
macro_arg *args, *arg;
const cpp_token *token;
unsigned int argc;
- bool error = false;
macro = node->value.macro;
if (macro->paramc)
@@ -550,90 +655,43 @@ collect_args (pfile, node)
arg++;
}
}
- while (token->type != CPP_CLOSE_PAREN
- && token->type != CPP_EOF
- && token->type != CPP_HASH);
+ while (token->type != CPP_CLOSE_PAREN && token->type != CPP_EOF);
- if (token->type == CPP_EOF || token->type == CPP_HASH)
+ if (token->type == CPP_EOF)
{
- bool step_back = false;
-
- /* 6.10.3 paragraph 11: If there are sequences of preprocessing
- tokens within the list of arguments that would otherwise act
- as preprocessing directives, the behavior is undefined.
-
- This implementation will report a hard error, terminate the
- macro invocation, and proceed to process the directive. */
- if (token->type == CPP_HASH)
- {
- cpp_error (pfile,
- "directives may not be used inside a macro argument");
- step_back = true;
- }
- else
- step_back = (pfile->context->prev || pfile->state.in_directive);
-
/* We still need the CPP_EOF to end directives, and to end
pre-expansion of a macro argument. Step back is not
unconditional, since we don't want to return a CPP_EOF to our
callers at the end of an -include-d file. */
- if (step_back)
+ if (pfile->context->prev || pfile->state.in_directive)
_cpp_backup_tokens (pfile, 1);
- cpp_error (pfile, "unterminated argument list invoking macro \"%s\"",
+ cpp_error (pfile, DL_ERROR,
+ "unterminated argument list invoking macro \"%s\"",
NODE_NAME (node));
- error = true;
- }
- else if (argc < macro->paramc)
- {
- /* As an extension, a rest argument is allowed to not appear in
- the invocation at all.
- e.g. #define debug(format, args...) something
- debug("string");
-
- This is exactly the same as if there had been an empty rest
- argument - debug("string", ). */
-
- if (argc + 1 == macro->paramc && macro->variadic)
- {
- if (CPP_PEDANTIC (pfile) && ! macro->syshdr)
- cpp_pedwarn (pfile, "ISO C99 requires rest arguments to be used");
- }
- else
- {
- cpp_error (pfile,
- "macro \"%s\" requires %u arguments, but only %u given",
- NODE_NAME (node), macro->paramc, argc);
- error = true;
- }
}
- else if (argc > macro->paramc)
+ else
{
- /* Empty argument to a macro taking no arguments is OK. */
- if (argc != 1 || arg->count)
+ /* A single empty argument is counted as no argument. */
+ if (argc == 1 && macro->paramc == 0 && args[0].count == 0)
+ argc = 0;
+ if (_cpp_arguments_ok (pfile, macro, node, argc))
{
- cpp_error (pfile,
- "macro \"%s\" passed %u arguments, but takes just %u",
- NODE_NAME (node), argc, macro->paramc);
- error = true;
+ /* GCC has special semantics for , ## b where b is a varargs
+ parameter: we remove the comma if b was omitted entirely.
+ If b was merely an empty argument, the comma is retained.
+ If the macro takes just one (varargs) parameter, then we
+ retain the comma only if we are standards conforming.
+
+ If FIRST is NULL replace_args () swallows the comma. */
+ if (macro->variadic && (argc < macro->paramc
+ || (argc == 1 && args[0].count == 0
+ && !CPP_OPTION (pfile, std))))
+ args[macro->paramc - 1].first = NULL;
+ return base_buff;
}
}
- if (!error)
- {
- /* GCC has special semantics for , ## b where b is a varargs
- parameter: we remove the comma if b was omitted entirely.
- If b was merely an empty argument, the comma is retained.
- If the macro takes just one (varargs) parameter, then we
- retain the comma only if we are standards conforming.
-
- If FIRST is NULL replace_args () swallows the comma. */
- if (macro->variadic && (argc < macro->paramc
- || (argc == 1 && args[0].count == 0
- && !CPP_OPTION (pfile, std))))
- args[macro->paramc - 1].first = NULL;
- return base_buff;
- }
-
+ /* An error occurred. */
_cpp_release_buff (pfile, base_buff);
return NULL;
}
@@ -714,23 +772,25 @@ enter_macro_context (pfile, node)
if (buff == NULL)
{
if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr)
- cpp_warning (pfile,
+ cpp_error (pfile, DL_WARNING,
"function-like macro \"%s\" must be used with arguments in traditional C",
- NODE_NAME (node));
+ NODE_NAME (node));
return 0;
}
- if (node->value.macro->paramc > 0)
- replace_args (pfile, node, (macro_arg *) buff->base);
+ if (macro->paramc > 0)
+ replace_args (pfile, node, macro, (macro_arg *) buff->base);
_cpp_release_buff (pfile, buff);
}
/* Disable the macro within its expansion. */
node->flags |= NODE_DISABLED;
+ macro->used = 1;
+
if (macro->paramc == 0)
- push_token_context (pfile, node, macro->expansion, macro->count);
+ push_token_context (pfile, node, macro->exp.tokens, macro->count);
return 1;
}
@@ -744,9 +804,10 @@ enter_macro_context (pfile, node)
Expand each argument before replacing, unless it is operated upon
by the # or ## operators. */
static void
-replace_args (pfile, node, args)
+replace_args (pfile, node, macro, args)
cpp_reader *pfile;
cpp_hashnode *node;
+ cpp_macro *macro;
macro_arg *args;
{
unsigned int i, total;
@@ -754,17 +815,15 @@ replace_args (pfile, node, args)
const cpp_token **dest, **first;
macro_arg *arg;
_cpp_buff *buff;
- cpp_macro *macro;
/* First, fully macro-expand arguments, calculating the number of
tokens in the final expansion as we go. The ordering of the if
statements below is subtle; we must handle stringification before
pasting. */
- macro = node->value.macro;
total = macro->count;
- limit = macro->expansion + macro->count;
+ limit = macro->exp.tokens + macro->count;
- for (src = macro->expansion; src < limit; src++)
+ for (src = macro->exp.tokens; src < limit; src++)
if (src->type == CPP_MACRO_ARG)
{
/* Leading and trailing padding tokens. */
@@ -780,7 +839,7 @@ replace_args (pfile, node, args)
arg->stringified = stringify_arg (pfile, arg);
}
else if ((src->flags & PASTE_LEFT)
- || (src > macro->expansion && (src[-1].flags & PASTE_LEFT)))
+ || (src > macro->exp.tokens && (src[-1].flags & PASTE_LEFT)))
total += arg->count - 1;
else
{
@@ -796,7 +855,7 @@ replace_args (pfile, node, args)
first = (const cpp_token **) buff->base;
dest = first;
- for (src = macro->expansion; src < limit; src++)
+ for (src = macro->exp.tokens; src < limit; src++)
{
unsigned int count;
const cpp_token **from, **paste_flag;
@@ -813,7 +872,7 @@ replace_args (pfile, node, args)
count = 1, from = &arg->stringified;
else if (src->flags & PASTE_LEFT)
count = arg->count, from = arg->first;
- else if (src != macro->expansion && (src[-1].flags & PASTE_LEFT))
+ else if (src != macro->exp.tokens && (src[-1].flags & PASTE_LEFT))
{
count = arg->count, from = arg->first;
if (dest != first)
@@ -838,8 +897,8 @@ replace_args (pfile, node, args)
count = arg->expanded_count, from = arg->expanded;
/* Padding on the left of an argument (unless RHS of ##). */
- if (!pfile->state.in_directive
- && src != macro->expansion && !(src[-1].flags & PASTE_LEFT))
+ if ((!pfile->state.in_directive || pfile->state.directive_wants_padding)
+ && src != macro->exp.tokens && !(src[-1].flags & PASTE_LEFT))
*dest++ = padding_token (pfile, src);
if (count)
@@ -927,8 +986,8 @@ push_ptoken_context (pfile, macro, buff, first, count)
context->direct_p = false;
context->macro = macro;
context->buff = buff;
- context->first.ptoken = first;
- context->last.ptoken = first + count;
+ FIRST (context).ptoken = first;
+ LAST (context).ptoken = first + count;
}
/* Push a list of tokens. */
@@ -944,8 +1003,26 @@ push_token_context (pfile, macro, first, count)
context->direct_p = true;
context->macro = macro;
context->buff = NULL;
- context->first.token = first;
- context->last.token = first + count;
+ FIRST (context).token = first;
+ LAST (context).token = first + count;
+}
+
+/* Push a traditional macro's replacement text. */
+void
+_cpp_push_text_context (pfile, macro, start, len)
+ cpp_reader *pfile;
+ cpp_hashnode *macro;
+ const uchar *start;
+ size_t len;
+{
+ cpp_context *context = next_context (pfile);
+
+ context->direct_p = true;
+ context->macro = macro;
+ context->buff = NULL;
+ CUR (context) = start;
+ RLIMIT (context) = start + len;
+ macro->flags |= NODE_DISABLED;
}
/* Expand an argument ARG before replacing parameters in a
@@ -960,10 +1037,15 @@ expand_arg (pfile, arg)
macro_arg *arg;
{
unsigned int capacity;
+ bool saved_warn_trad;
if (arg->count == 0)
return;
+ /* Don't warn about funlike macros when pre-expanding. */
+ saved_warn_trad = CPP_WTRADITIONAL (pfile);
+ CPP_WTRADITIONAL (pfile) = 0;
+
/* Loop, reading in the arguments. */
capacity = 256;
arg->expanded = (const cpp_token **)
@@ -990,6 +1072,8 @@ expand_arg (pfile, arg)
}
_cpp_pop_context (pfile);
+
+ CPP_WTRADITIONAL (pfile) = saved_warn_trad;
}
/* Pop the current context off the stack, re-enabling the macro if the
@@ -1035,12 +1119,12 @@ cpp_get_token (pfile)
/* Context->prev == 0 <=> base context. */
if (!context->prev)
result = _cpp_lex_token (pfile);
- else if (context->first.token != context->last.token)
+ else if (FIRST (context).token != LAST (context).token)
{
if (context->direct_p)
- result = context->first.token++;
+ result = FIRST (context).token++;
else
- result = *context->first.ptoken++;
+ result = *FIRST (context).ptoken++;
if (result->flags & PASTE_LEFT)
{
@@ -1058,6 +1142,9 @@ cpp_get_token (pfile)
return &pfile->avoid_paste;
}
+ if (pfile->state.in_directive && result->type == CPP_COMMENT)
+ continue;
+
if (result->type != CPP_NAME)
break;
@@ -1065,7 +1152,7 @@ cpp_get_token (pfile)
if (node->type != NT_MACRO || (result->flags & NO_EXPAND))
break;
-
+
if (!(node->flags & NODE_DISABLED))
{
if (!pfile->state.prevent_expansion
@@ -1105,14 +1192,22 @@ cpp_sys_macro_p (pfile)
return node && node->value.macro && node->value.macro->syshdr;
}
-/* Read each token in, until EOF. Directives are transparently
- processed. */
+/* Read each token in, until end of the current file. Directives are
+ transparently processed. */
void
cpp_scan_nooutput (pfile)
cpp_reader *pfile;
{
- while (cpp_get_token (pfile)->type != CPP_EOF)
- ;
+ /* Request a CPP_EOF token at the end of this file, rather than
+ transparently continuing with the including file. */
+ pfile->buffer->return_at_eof = true;
+
+ if (CPP_OPTION (pfile, traditional))
+ while (_cpp_read_logical_line_trad (pfile))
+ ;
+ else
+ while (cpp_get_token (pfile)->type != CPP_EOF)
+ ;
}
/* Step back one (or more) tokens. Can only step mack more than 1 if
@@ -1142,17 +1237,18 @@ _cpp_backup_tokens (pfile, count)
if (count != 1)
abort ();
if (pfile->context->direct_p)
- pfile->context->first.token--;
+ FIRST (pfile->context).token--;
else
- pfile->context->first.ptoken--;
+ FIRST (pfile->context).ptoken--;
}
}
/* #define directive parsing and handling. */
-/* Returns non-zero if a macro redefinition warning is required. */
-static int
-warn_of_redefinition (node, macro2)
+/* Returns nonzero if a macro redefinition warning is required. */
+static bool
+warn_of_redefinition (pfile, node, macro2)
+ cpp_reader *pfile;
const cpp_hashnode *node;
const cpp_macro *macro2;
{
@@ -1161,30 +1257,36 @@ warn_of_redefinition (node, macro2)
/* Some redefinitions need to be warned about regardless. */
if (node->flags & NODE_WARN)
- return 1;
+ return true;
/* Redefinition of a macro is allowed if and only if the old and new
definitions are the same. (6.10.3 paragraph 2). */
macro1 = node->value.macro;
- /* The quick failures. */
- if (macro1->count != macro2->count
- || macro1->paramc != macro2->paramc
+ /* Don't check count here as it can be different in valid
+ traditional redefinitions with just whitespace differences. */
+ if (macro1->paramc != macro2->paramc
|| macro1->fun_like != macro2->fun_like
|| macro1->variadic != macro2->variadic)
- return 1;
-
- /* Check each token. */
- for (i = 0; i < macro1->count; i++)
- if (! _cpp_equiv_tokens (&macro1->expansion[i], &macro2->expansion[i]))
- return 1;
+ return true;
/* Check parameter spellings. */
for (i = 0; i < macro1->paramc; i++)
if (macro1->params[i] != macro2->params[i])
- return 1;
+ return true;
+
+ /* Check the replacement text or tokens. */
+ if (CPP_OPTION (pfile, traditional))
+ return _cpp_expansions_different_trad (macro1, macro2);
+
+ if (macro1->count != macro2->count)
+ return true;
+
+ for (i = 0; i < macro1->count; i++)
+ if (!_cpp_equiv_tokens (&macro1->exp.tokens[i], &macro2->exp.tokens[i]))
+ return true;
- return 0;
+ return false;
}
/* Free the definition of hashnode H. */
@@ -1199,9 +1301,9 @@ _cpp_free_definition (h)
}
/* Save parameter NODE to the parameter list of macro MACRO. Returns
- zero on success, non-zero if the parameter is a duplicate. */
-static int
-save_parameter (pfile, macro, node)
+ zero on success, nonzero if the parameter is a duplicate. */
+bool
+_cpp_save_parameter (pfile, macro, node)
cpp_reader *pfile;
cpp_macro *macro;
cpp_hashnode *node;
@@ -1209,8 +1311,9 @@ save_parameter (pfile, macro, node)
/* Constraint 6.10.3.6 - duplicate parameter names. */
if (node->arg_index)
{
- cpp_error (pfile, "duplicate macro parameter \"%s\"", NODE_NAME (node));
- return 1;
+ cpp_error (pfile, DL_ERROR, "duplicate macro parameter \"%s\"",
+ NODE_NAME (node));
+ return true;
}
if (BUFF_ROOM (pfile->a_buff)
@@ -1219,11 +1322,12 @@ save_parameter (pfile, macro, node)
((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[macro->paramc++] = node;
node->arg_index = macro->paramc;
- return 0;
+ return false;
}
-/* Check the syntax of the parameters in a MACRO definition. */
-static int
+/* Check the syntax of the parameters in a MACRO definition. Returns
+ false if an error occurs. */
+static bool
parse_params (pfile, macro)
cpp_reader *pfile;
cpp_macro *macro;
@@ -1237,32 +1341,40 @@ parse_params (pfile, macro)
switch (token->type)
{
default:
- cpp_error (pfile, "\"%s\" may not appear in macro parameter list",
+ /* Allow/ignore comments in parameter lists if we are
+ preserving comments in macro expansions. */
+ if (token->type == CPP_COMMENT
+ && ! CPP_OPTION (pfile, discard_comments_in_macro_exp))
+ continue;
+
+ cpp_error (pfile, DL_ERROR,
+ "\"%s\" may not appear in macro parameter list",
cpp_token_as_text (pfile, token));
- return 0;
+ return false;
case CPP_NAME:
if (prev_ident)
{
- cpp_error (pfile, "macro parameters must be comma-separated");
- return 0;
+ cpp_error (pfile, DL_ERROR,
+ "macro parameters must be comma-separated");
+ return false;
}
prev_ident = 1;
- if (save_parameter (pfile, macro, token->val.node))
- return 0;
+ if (_cpp_save_parameter (pfile, macro, token->val.node))
+ return false;
continue;
case CPP_CLOSE_PAREN:
if (prev_ident || macro->paramc == 0)
- return 1;
+ return true;
/* Fall through to pick up the error. */
case CPP_COMMA:
if (!prev_ident)
{
- cpp_error (pfile, "parameter name missing");
- return 0;
+ cpp_error (pfile, DL_ERROR, "parameter name missing");
+ return false;
}
prev_ident = 0;
continue;
@@ -1271,24 +1383,26 @@ parse_params (pfile, macro)
macro->variadic = 1;
if (!prev_ident)
{
- save_parameter (pfile, macro, pfile->spec_nodes.n__VA_ARGS__);
+ _cpp_save_parameter (pfile, macro,
+ pfile->spec_nodes.n__VA_ARGS__);
pfile->state.va_args_ok = 1;
if (! CPP_OPTION (pfile, c99) && CPP_OPTION (pfile, pedantic))
- cpp_pedwarn (pfile,
- "anonymous variadic macros were introduced in C99");
+ cpp_error (pfile, DL_PEDWARN,
+ "anonymous variadic macros were introduced in C99");
}
else if (CPP_OPTION (pfile, pedantic))
- cpp_pedwarn (pfile, "ISO C does not permit named variadic macros");
+ cpp_error (pfile, DL_PEDWARN,
+ "ISO C does not permit named variadic macros");
/* We're at the end, and just expect a closing parenthesis. */
token = _cpp_lex_token (pfile);
if (token->type == CPP_CLOSE_PAREN)
- return 1;
+ return true;
/* Fall through. */
case CPP_EOF:
- cpp_error (pfile, "missing ')' in macro parameter list");
- return 0;
+ cpp_error (pfile, DL_ERROR, "missing ')' in macro parameter list");
+ return false;
}
}
}
@@ -1330,24 +1444,13 @@ lex_expansion_token (pfile, macro)
return token;
}
-/* Parse a macro and save its expansion. Returns non-zero on success. */
-int
-_cpp_create_definition (pfile, node)
+static bool
+create_iso_definition (pfile, macro)
cpp_reader *pfile;
- cpp_hashnode *node;
+ cpp_macro *macro;
{
- cpp_macro *macro;
- cpp_token *token, *saved_cur_token;
+ cpp_token *token;
const cpp_token *ctoken;
- unsigned int i, ok = 1;
-
- macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro));
- macro->line = pfile->directive_line;
- macro->params = 0;
- macro->paramc = 0;
- macro->variadic = 0;
- macro->count = 0;
- macro->fun_like = 0;
/* Get the first token of the expansion (or the '(' of a
function-like macro). */
@@ -1355,19 +1458,18 @@ _cpp_create_definition (pfile, node)
if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE))
{
- ok = parse_params (pfile, macro);
+ bool ok = parse_params (pfile, macro);
macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
if (!ok)
- goto cleanup2;
+ return false;
/* Success. Commit the parameter array. */
- BUFF_FRONT (pfile->a_buff) = (U_CHAR *) &macro->params[macro->paramc];
+ BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc];
macro->fun_like = 1;
}
else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE))
- cpp_pedwarn (pfile, "ISO C requires whitespace after the macro name");
-
- saved_cur_token = pfile->cur_token;
+ cpp_error (pfile, DL_PEDWARN,
+ "ISO C requires whitespace after the macro name");
if (macro->fun_like)
token = lex_expansion_token (pfile, macro);
@@ -1394,9 +1496,9 @@ _cpp_create_definition (pfile, node)
/* Let assembler get away with murder. */
else if (CPP_OPTION (pfile, lang) != CLK_ASM)
{
- ok = 0;
- cpp_error (pfile, "'#' is not followed by a macro parameter");
- goto cleanup1;
+ cpp_error (pfile, DL_ERROR,
+ "'#' is not followed by a macro parameter");
+ return false;
}
}
@@ -1413,10 +1515,9 @@ _cpp_create_definition (pfile, node)
if (macro->count == 0 || token->type == CPP_EOF)
{
- ok = 0;
- cpp_error (pfile,
+ cpp_error (pfile, DL_ERROR,
"'##' cannot appear at either end of a macro expansion");
- goto cleanup1;
+ return false;
}
token[-1].flags |= PASTE_LEFT;
@@ -1425,62 +1526,96 @@ _cpp_create_definition (pfile, node)
token = lex_expansion_token (pfile, macro);
}
- macro->expansion = (cpp_token *) BUFF_FRONT (pfile->a_buff);
+ macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff);
/* Don't count the CPP_EOF. */
macro->count--;
/* Clear whitespace on first token for warn_of_redefinition(). */
if (macro->count)
- macro->expansion[0].flags &= ~PREV_WHITE;
+ macro->exp.tokens[0].flags &= ~PREV_WHITE;
/* Commit the memory. */
- BUFF_FRONT (pfile->a_buff) = (U_CHAR *) &macro->expansion[macro->count];
+ BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->exp.tokens[macro->count];
- /* Implement the macro-defined-to-itself optimisation. */
- if (macro->count == 1 && !macro->fun_like
- && macro->expansion[0].type == CPP_NAME
- && macro->expansion[0].val.node == node)
- node->flags |= NODE_DISABLED;
+ return true;
+}
+
+/* Parse a macro and save its expansion. Returns nonzero on success. */
+bool
+_cpp_create_definition (pfile, node)
+ cpp_reader *pfile;
+ cpp_hashnode *node;
+{
+ cpp_macro *macro;
+ unsigned int i;
+ bool ok;
+ macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro));
+ macro->line = pfile->directive_line;
+ macro->params = 0;
+ macro->paramc = 0;
+ macro->variadic = 0;
+ macro->used = 0;
+ macro->count = 0;
+ macro->fun_like = 0;
/* To suppress some diagnostics. */
macro->syshdr = pfile->map->sysp != 0;
- if (node->type != NT_VOID)
+ if (CPP_OPTION (pfile, traditional))
+ ok = _cpp_create_trad_definition (pfile, macro);
+ else
+ {
+ cpp_token *saved_cur_token = pfile->cur_token;
+
+ ok = create_iso_definition (pfile, macro);
+
+ /* Restore lexer position because of games lex_expansion_token()
+ plays lexing the macro. We set the type for SEEN_EOL() in
+ cpplib.c.
+
+ Longer term we should lex the whole line before coming here,
+ and just copy the expansion. */
+ saved_cur_token[-1].type = pfile->cur_token[-1].type;
+ pfile->cur_token = saved_cur_token;
+
+ /* Stop the lexer accepting __VA_ARGS__. */
+ pfile->state.va_args_ok = 0;
+ }
+
+ /* Clear the fast argument lookup indices. */
+ for (i = macro->paramc; i-- > 0; )
+ macro->params[i]->arg_index = 0;
+
+ if (!ok)
+ return ok;
+
+ if (node->type == NT_MACRO)
{
- if (warn_of_redefinition (node, macro))
+ if (CPP_OPTION (pfile, warn_unused_macros))
+ _cpp_warn_if_unused_macro (pfile, node, NULL);
+
+ if (warn_of_redefinition (pfile, node, macro))
{
- cpp_pedwarn_with_line (pfile, pfile->directive_line, 0,
- "\"%s\" redefined", NODE_NAME (node));
+ cpp_error_with_line (pfile, DL_PEDWARN, pfile->directive_line, 0,
+ "\"%s\" redefined", NODE_NAME (node));
if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
- cpp_pedwarn_with_line (pfile, node->value.macro->line, 0,
- "this is the location of the previous definition");
+ cpp_error_with_line (pfile, DL_PEDWARN,
+ node->value.macro->line, 0,
+ "this is the location of the previous definition");
}
- _cpp_free_definition (node);
}
+ if (node->type != NT_VOID)
+ _cpp_free_definition (node);
+
/* Enter definition in hash table. */
node->type = NT_MACRO;
node->value.macro = macro;
if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_")))
node->flags |= NODE_WARN;
- cleanup1:
-
- /* Set type for SEEN_EOL() in cpplib.c, restore the lexer position. */
- saved_cur_token[-1].type = pfile->cur_token[-1].type;
- pfile->cur_token = saved_cur_token;
-
- cleanup2:
-
- /* Stop the lexer accepting __VA_ARGS__. */
- pfile->state.va_args_ok = 0;
-
- /* Clear the fast argument lookup indices. */
- for (i = macro->paramc; i-- > 0; )
- macro->params[i]->arg_index = 0;
-
return ok;
}
@@ -1493,8 +1628,8 @@ check_trad_stringification (pfile, macro, string)
const cpp_string *string;
{
unsigned int i, len;
- const U_CHAR *p, *q, *limit = string->text + string->len;
-
+ const uchar *p, *q, *limit = string->text + string->len;
+
/* Loop over the string. */
for (p = string->text; p < limit; p = q)
{
@@ -1518,9 +1653,9 @@ check_trad_stringification (pfile, macro, string)
if (NODE_LEN (node) == len
&& !memcmp (p, NODE_NAME (node), len))
{
- cpp_warning (pfile,
- "macro argument \"%s\" would be stringified with -traditional",
- NODE_NAME (node));
+ cpp_error (pfile, DL_WARNING,
+ "macro argument \"%s\" would be stringified in traditional C",
+ NODE_NAME (node));
break;
}
}
@@ -1543,7 +1678,8 @@ cpp_macro_definition (pfile, node)
if (node->type != NT_MACRO || (node->flags & NODE_BUILTIN))
{
- cpp_ice (pfile, "invalid hash type %d in cpp_macro_definition", node->type);
+ cpp_error (pfile, DL_ICE,
+ "invalid hash type %d in cpp_macro_definition", node->type);
return 0;
}
@@ -1557,23 +1693,28 @@ cpp_macro_definition (pfile, node)
len += NODE_LEN (macro->params[i]) + 1; /* "," */
}
- for (i = 0; i < macro->count; i++)
+ if (CPP_OPTION (pfile, traditional))
+ len += _cpp_replacement_text_len (macro);
+ else
{
- cpp_token *token = &macro->expansion[i];
+ for (i = 0; i < macro->count; i++)
+ {
+ cpp_token *token = &macro->exp.tokens[i];
- if (token->type == CPP_MACRO_ARG)
- len += NODE_LEN (macro->params[token->val.arg_no - 1]);
- else
- len += cpp_token_len (token); /* Includes room for ' '. */
- if (token->flags & STRINGIFY_ARG)
- len++; /* "#" */
- if (token->flags & PASTE_LEFT)
- len += 3; /* " ##" */
+ if (token->type == CPP_MACRO_ARG)
+ len += NODE_LEN (macro->params[token->val.arg_no - 1]);
+ else
+ len += cpp_token_len (token); /* Includes room for ' '. */
+ if (token->flags & STRINGIFY_ARG)
+ len++; /* "#" */
+ if (token->flags & PASTE_LEFT)
+ len += 3; /* " ##" */
+ }
}
if (len > pfile->macro_buffer_len)
{
- pfile->macro_buffer = (U_CHAR *) xrealloc (pfile->macro_buffer, len);
+ pfile->macro_buffer = (uchar *) xrealloc (pfile->macro_buffer, len);
pfile->macro_buffer_len = len;
}
@@ -1597,9 +1738,9 @@ cpp_macro_definition (pfile, node)
}
if (i + 1 < macro->paramc)
- /* Don't emit a space after the comma here; we're trying
- to emit a Dwarf-friendly definition, and the Dwarf spec
- forbids spaces in the argument list. */
+ /* Don't emit a space after the comma here; we're trying
+ to emit a Dwarf-friendly definition, and the Dwarf spec
+ forbids spaces in the argument list. */
*buffer++ = ',';
else if (macro->variadic)
*buffer++ = '.', *buffer++ = '.', *buffer++ = '.';
@@ -1611,12 +1752,14 @@ cpp_macro_definition (pfile, node)
definition is the empty string. */
*buffer++ = ' ';
+ if (CPP_OPTION (pfile, traditional))
+ buffer = _cpp_copy_replacement_text (macro, buffer);
+ else if (macro->count)
/* Expansion tokens. */
- if (macro->count)
{
for (i = 0; i < macro->count; i++)
{
- cpp_token *token = &macro->expansion[i];
+ cpp_token *token = &macro->exp.tokens[i];
if (token->flags & PREV_WHITE)
*buffer++ = ' ';
diff --git a/contrib/gcc/cppmain.c b/contrib/gcc/cppmain.c
index b8757c7..9d8d42c 100644
--- a/contrib/gcc/cppmain.c
+++ b/contrib/gcc/cppmain.c
@@ -1,4 +1,4 @@
-/* CPP main program, using CPP Library.
+/* Preprocess only, using cpplib.
Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by Per Bothner, 1994-95.
@@ -24,33 +24,21 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "config.h"
#include "system.h"
#include "cpplib.h"
-#include "intl.h"
+#include "cpphash.h"
-/* Encapsulates state used to convert the stream of tokens coming from
- cpp_get_token back into a text file. */
-struct printer
-{
- FILE *outf; /* Stream to write to. */
- const struct line_map *map; /* Logical to physical line mappings. */
- const cpp_token *prev; /* Previous token. */
- const cpp_token *source; /* Source token for spacing. */
- unsigned int line; /* Line currently being written. */
- unsigned char printed; /* Nonzero if something output at line. */
-};
-
-int main PARAMS ((int, char **));
-static void general_init PARAMS ((const char *));
-static void do_preprocessing PARAMS ((int, char **));
-static void setup_callbacks PARAMS ((void));
+static void setup_callbacks PARAMS ((cpp_reader *));
/* General output routines. */
static void scan_translation_unit PARAMS ((cpp_reader *));
-static void check_multiline_token PARAMS ((const cpp_string *));
+static void scan_translation_unit_trad PARAMS ((cpp_reader *));
+static void account_for_newlines PARAMS ((cpp_reader *, const uchar *,
+ size_t));
static int dump_macro PARAMS ((cpp_reader *, cpp_hashnode *, void *));
-static void print_line PARAMS ((const struct line_map *, unsigned int,
- const char *));
-static void maybe_print_line PARAMS ((const struct line_map *, unsigned int));
+static void print_line PARAMS ((cpp_reader *, const struct line_map *,
+ unsigned int, const char *));
+static void maybe_print_line PARAMS ((cpp_reader *, const struct line_map *,
+ unsigned int));
/* Callback routines for the parser. Most of these are active only
in specific modes. */
@@ -64,130 +52,59 @@ static void cb_ident PARAMS ((cpp_reader *, unsigned int,
static void cb_file_change PARAMS ((cpp_reader *, const struct line_map *));
static void cb_def_pragma PARAMS ((cpp_reader *, unsigned int));
-const char *progname; /* Needs to be global. */
-static cpp_reader *pfile; /* An opaque handle. */
-static cpp_options *options; /* Options of pfile. */
-static struct printer print;
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- general_init (argv[0]);
-
- /* Construct a reader with default language GNU C89. */
- pfile = cpp_create_reader (CLK_GNUC89);
- options = cpp_get_options (pfile);
-
- do_preprocessing (argc, argv);
-
- if (cpp_destroy (pfile))
- return FATAL_EXIT_CODE;
-
- return SUCCESS_EXIT_CODE;
-}
-
-/* Store the program name, and set the locale. */
-static void
-general_init (argv0)
- const char *argv0;
-{
- progname = argv0 + strlen (argv0);
-
- while (progname != argv0 && ! IS_DIR_SEPARATOR (progname[-1]))
- --progname;
-
- xmalloc_set_program_name (progname);
-
- hex_init ();
- gcc_init_libintl ();
-}
-
-/* Handle switches, preprocess and output. */
-static void
-do_preprocessing (argc, argv)
- int argc;
- char **argv;
+/* Preprocess and output. */
+void
+cpp_preprocess_file (pfile, in_fname, out_stream)
+ cpp_reader *pfile;
+ const char *in_fname;
+ FILE *out_stream;
{
- int argi = 1; /* Next argument to handle. */
-
- argi += cpp_handle_options (pfile, argc - argi , argv + argi);
- if (CPP_FATAL_ERRORS (pfile))
- return;
-
- if (argi < argc)
- {
- cpp_fatal (pfile, "invalid option %s", argv[argi]);
- return;
- }
-
- cpp_post_options (pfile);
- if (CPP_FATAL_ERRORS (pfile))
- return;
-
- /* If cpp_handle_options saw --help or --version on the command
- line, it will have set pfile->help_only to indicate this. Exit
- successfully. [The library does not exit itself, because
- e.g. cc1 needs to print its own --help message at this point.] */
- if (options->help_only)
- return;
-
/* Initialize the printer structure. Setting print.line to -1 here
is a trick to guarantee that the first token of the file will
cause a linemarker to be output by maybe_print_line. */
- print.line = (unsigned int) -1;
- print.printed = 0;
- print.prev = 0;
- print.map = 0;
-
- /* Open the output now. We must do so even if no_output is on,
- because there may be other output than from the actual
- preprocessing (e.g. from -dM). */
- if (options->out_fname[0] == '\0')
- print.outf = stdout;
- else
- {
- print.outf = fopen (options->out_fname, "w");
- if (print.outf == NULL)
- {
- cpp_notice_from_errno (pfile, options->out_fname);
- return;
- }
- }
+ pfile->print.line = (unsigned int) -1;
+ pfile->print.printed = 0;
+ pfile->print.prev = 0;
+ pfile->print.map = 0;
+ pfile->print.outf = out_stream;
- setup_callbacks ();
+ setup_callbacks (pfile);
- if (cpp_read_main_file (pfile, options->in_fname, NULL))
+ if (cpp_read_main_file (pfile, in_fname, NULL))
{
+ cpp_options *options = &pfile->opts;
cpp_finish_options (pfile);
/* A successful cpp_read_main_file guarantees that we can call
cpp_scan_nooutput or cpp_get_token next. */
if (options->no_output)
- cpp_scan_nooutput (pfile);
+ {
+ /* Scan -included buffers, then the main file. */
+ while (pfile->buffer->prev)
+ cpp_scan_nooutput (pfile);
+ cpp_scan_nooutput (pfile);
+ }
+ else if (options->traditional)
+ scan_translation_unit_trad (pfile);
else
scan_translation_unit (pfile);
/* -dM command line option. Should this be in cpp_finish? */
if (options->dump_macros == dump_only)
cpp_forall_identifiers (pfile, dump_macro, NULL);
-
- cpp_finish (pfile);
}
/* Flush any pending output. */
- if (print.printed)
- putc ('\n', print.outf);
-
- if (ferror (print.outf) || fclose (print.outf))
- cpp_notice_from_errno (pfile, options->out_fname);
+ if (pfile->print.printed)
+ putc ('\n', pfile->print.outf);
}
/* Set up the callbacks as appropriate. */
static void
-setup_callbacks ()
+setup_callbacks (pfile)
+ cpp_reader *pfile;
{
+ cpp_options *options = &pfile->opts;
cpp_callbacks *cb = cpp_get_callbacks (pfile);
if (! options->no_output)
@@ -223,7 +140,7 @@ scan_translation_unit (pfile)
{
bool avoid_paste = false;
- print.source = NULL;
+ pfile->print.source = NULL;
for (;;)
{
const cpp_token *token = cpp_get_token (pfile);
@@ -231,10 +148,10 @@ scan_translation_unit (pfile)
if (token->type == CPP_PADDING)
{
avoid_paste = true;
- if (print.source == NULL
- || (!(print.source->flags & PREV_WHITE)
+ if (pfile->print.source == NULL
+ || (!(pfile->print.source->flags & PREV_WHITE)
&& token->val.source == NULL))
- print.source = token->val.source;
+ pfile->print.source = token->val.source;
continue;
}
@@ -244,101 +161,120 @@ scan_translation_unit (pfile)
/* Subtle logic to output a space if and only if necessary. */
if (avoid_paste)
{
- if (print.source == NULL)
- print.source = token;
- if (print.source->flags & PREV_WHITE
- || (print.prev && cpp_avoid_paste (pfile, print.prev, token))
- || (print.prev == NULL && token->type == CPP_HASH))
- putc (' ', print.outf);
+ if (pfile->print.source == NULL)
+ pfile->print.source = token;
+ if (pfile->print.source->flags & PREV_WHITE
+ || (pfile->print.prev
+ && cpp_avoid_paste (pfile, pfile->print.prev, token))
+ || (pfile->print.prev == NULL && token->type == CPP_HASH))
+ putc (' ', pfile->print.outf);
}
else if (token->flags & PREV_WHITE)
- putc (' ', print.outf);
+ putc (' ', pfile->print.outf);
avoid_paste = false;
- print.source = NULL;
- print.prev = token;
- cpp_output_token (token, print.outf);
+ pfile->print.source = NULL;
+ pfile->print.prev = token;
+ cpp_output_token (token, pfile->print.outf);
- if (token->type == CPP_STRING || token->type == CPP_WSTRING
- || token->type == CPP_COMMENT)
- check_multiline_token (&token->val.str);
+ if (token->type == CPP_COMMENT)
+ account_for_newlines (pfile, token->val.str.text, token->val.str.len);
}
}
-/* Adjust print.line for newlines embedded in tokens. */
+/* Adjust pfile->print.line for newlines embedded in output. */
static void
-check_multiline_token (str)
- const cpp_string *str;
+account_for_newlines (pfile, str, len)
+ cpp_reader *pfile;
+ const uchar *str;
+ size_t len;
{
- unsigned int i;
+ while (len--)
+ if (*str++ == '\n')
+ pfile->print.line++;
+}
- for (i = 0; i < str->len; i++)
- if (str->text[i] == '\n')
- print.line++;
+/* Writes out a traditionally preprocessed file. */
+static void
+scan_translation_unit_trad (pfile)
+ cpp_reader *pfile;
+{
+ while (_cpp_read_logical_line_trad (pfile))
+ {
+ size_t len = pfile->out.cur - pfile->out.base;
+ maybe_print_line (pfile, pfile->print.map, pfile->out.first_line);
+ fwrite (pfile->out.base, 1, len, pfile->print.outf);
+ pfile->print.printed = 1;
+ if (!CPP_OPTION (pfile, discard_comments))
+ account_for_newlines (pfile, pfile->out.base, len);
+ }
}
/* If the token read on logical line LINE needs to be output on a
different line to the current one, output the required newlines or
a line marker, and return 1. Otherwise return 0. */
static void
-maybe_print_line (map, line)
+maybe_print_line (pfile, map, line)
+ cpp_reader *pfile;
const struct line_map *map;
unsigned int line;
{
/* End the previous line of text. */
- if (print.printed)
+ if (pfile->print.printed)
{
- putc ('\n', print.outf);
- print.line++;
- print.printed = 0;
+ putc ('\n', pfile->print.outf);
+ pfile->print.line++;
+ pfile->print.printed = 0;
}
- if (line >= print.line && line < print.line + 8)
+ if (line >= pfile->print.line && line < pfile->print.line + 8)
{
- while (line > print.line)
+ while (line > pfile->print.line)
{
- putc ('\n', print.outf);
- print.line++;
+ putc ('\n', pfile->print.outf);
+ pfile->print.line++;
}
}
else
- print_line (map, line, "");
+ print_line (pfile, map, line, "");
}
/* Output a line marker for logical line LINE. Special flags are "1"
or "2" indicating entering or leaving a file. */
static void
-print_line (map, line, special_flags)
+print_line (pfile, map, line, special_flags)
+ cpp_reader *pfile;
const struct line_map *map;
unsigned int line;
const char *special_flags;
{
/* End any previous line of text. */
- if (print.printed)
- putc ('\n', print.outf);
- print.printed = 0;
+ if (pfile->print.printed)
+ putc ('\n', pfile->print.outf);
+ pfile->print.printed = 0;
- print.line = line;
- if (! options->no_line_commands)
+ pfile->print.line = line;
+ if (! CPP_OPTION (pfile, no_line_commands))
{
size_t to_file_len = strlen (map->to_file);
unsigned char *to_file_quoted = alloca (to_file_len * 4 + 1);
unsigned char *p;
-
+
/* cpp_quote_string does not nul-terminate, so we have to do it
ourselves. */
p = cpp_quote_string (to_file_quoted,
(unsigned char *)map->to_file, to_file_len);
*p = '\0';
- fprintf (print.outf, "# %u \"%s\"%s",
- SOURCE_LINE (map, print.line), to_file_quoted, special_flags);
+ fprintf (pfile->print.outf, "# %u \"%s\"%s",
+ SOURCE_LINE (map, pfile->print.line),
+ to_file_quoted, special_flags);
if (map->sysp == 2)
- fputs (" 3 4", print.outf);
+ fputs (" 3 4", pfile->print.outf);
else if (map->sysp == 1)
- fputs (" 3", print.outf);
+ fputs (" 3", pfile->print.outf);
- putc ('\n', print.outf);
+ putc ('\n', pfile->print.outf);
}
}
@@ -346,41 +282,44 @@ print_line (map, line, special_flags)
of the line, and at end of file will be CPP_EOF. */
static void
cb_line_change (pfile, token, parsing_args)
- cpp_reader *pfile ATTRIBUTE_UNUSED;
+ cpp_reader *pfile;
const cpp_token *token;
int parsing_args;
{
if (token->type == CPP_EOF || parsing_args)
return;
- maybe_print_line (print.map, token->line);
- print.printed = 1;
- print.prev = 0;
- print.source = 0;
+ maybe_print_line (pfile, pfile->print.map, token->line);
+ pfile->print.prev = 0;
+ pfile->print.source = 0;
/* Supply enough spaces to put this token in its original column,
one space per column greater than 2, since scan_translation_unit
will provide a space if PREV_WHITE. Don't bother trying to
reconstruct tabs; we can't get it right in general, and nothing
ought to care. Some things do care; the fault lies with them. */
- if (token->col > 2)
+ if (!CPP_OPTION (pfile, traditional))
{
- unsigned int spaces = token->col - 2;
+ pfile->print.printed = 1;
+ if (token->col > 2)
+ {
+ unsigned int spaces = token->col - 2;
- while (spaces--)
- putc (' ', print.outf);
+ while (spaces--)
+ putc (' ', pfile->print.outf);
+ }
}
}
static void
cb_ident (pfile, line, str)
- cpp_reader *pfile ATTRIBUTE_UNUSED;
+ cpp_reader *pfile;
unsigned int line;
const cpp_string * str;
{
- maybe_print_line (print.map, line);
- fprintf (print.outf, "#ident \"%s\"\n", str->text);
- print.line++;
+ maybe_print_line (pfile, pfile->print.map, line);
+ fprintf (pfile->print.outf, "#ident \"%s\"\n", str->text);
+ pfile->print.line++;
}
static void
@@ -389,28 +328,29 @@ cb_define (pfile, line, node)
unsigned int line;
cpp_hashnode *node;
{
- maybe_print_line (print.map, line);
- fputs ("#define ", print.outf);
+ maybe_print_line (pfile, pfile->print.map, line);
+ fputs ("#define ", pfile->print.outf);
/* -dD command line option. */
- if (options->dump_macros == dump_definitions)
- fputs ((const char *) cpp_macro_definition (pfile, node), print.outf);
+ if (CPP_OPTION (pfile, dump_macros) == dump_definitions)
+ fputs ((const char *) cpp_macro_definition (pfile, node),
+ pfile->print.outf);
else
- fputs ((const char *) NODE_NAME (node), print.outf);
+ fputs ((const char *) NODE_NAME (node), pfile->print.outf);
- putc ('\n', print.outf);
- print.line++;
+ putc ('\n', pfile->print.outf);
+ pfile->print.line++;
}
static void
cb_undef (pfile, line, node)
- cpp_reader *pfile ATTRIBUTE_UNUSED;
+ cpp_reader *pfile;
unsigned int line;
cpp_hashnode *node;
{
- maybe_print_line (print.map, line);
- fprintf (print.outf, "#undef %s\n", NODE_NAME (node));
- print.line++;
+ maybe_print_line (pfile, pfile->print.map, line);
+ fprintf (pfile->print.outf, "#undef %s\n", NODE_NAME (node));
+ pfile->print.line++;
}
static void
@@ -420,43 +360,44 @@ cb_include (pfile, line, dir, header)
const unsigned char *dir;
const cpp_token *header;
{
- maybe_print_line (print.map, line);
- fprintf (print.outf, "#%s %s\n", dir, cpp_token_as_text (pfile, header));
- print.line++;
+ maybe_print_line (pfile, pfile->print.map, line);
+ fprintf (pfile->print.outf, "#%s %s\n", dir,
+ cpp_token_as_text (pfile, header));
+ pfile->print.line++;
}
/* The file name, line number or system header flags have changed, as
- described in MAP. From this point on, the old print.map might be
+ described in MAP. From this point on, the old pfile->print.map might be
pointing to freed memory, and so must not be dereferenced. */
static void
cb_file_change (pfile, map)
- cpp_reader *pfile ATTRIBUTE_UNUSED;
+ cpp_reader *pfile;
const struct line_map *map;
{
const char *flags = "";
/* First time? */
- if (print.map == NULL)
+ if (pfile->print.map == NULL)
{
/* Avoid printing foo.i when the main file is foo.c. */
- if (!options->preprocessed)
- print_line (map, map->from_line, flags);
+ if (!CPP_OPTION (pfile, preprocessed))
+ print_line (pfile, map, map->from_line, flags);
}
else
{
/* Bring current file to correct line when entering a new file. */
if (map->reason == LC_ENTER)
- maybe_print_line (map - 1, map->from_line - 1);
+ maybe_print_line (pfile, map - 1, map->from_line - 1);
if (map->reason == LC_ENTER)
flags = " 1";
else if (map->reason == LC_LEAVE)
flags = " 2";
- print_line (map, map->from_line, flags);
+ print_line (pfile, map, map->from_line, flags);
}
- print.map = map;
+ pfile->print.map = map;
}
/* Copy a #pragma directive to the preprocessed output. */
@@ -465,10 +406,10 @@ cb_def_pragma (pfile, line)
cpp_reader *pfile;
unsigned int line;
{
- maybe_print_line (print.map, line);
- fputs ("#pragma ", print.outf);
- cpp_output_line (pfile, print.outf);
- print.line++;
+ maybe_print_line (pfile, pfile->print.map, line);
+ fputs ("#pragma ", pfile->print.outf);
+ cpp_output_line (pfile, pfile->print.outf);
+ pfile->print.line++;
}
/* Dump out the hash table. */
@@ -480,10 +421,11 @@ dump_macro (pfile, node, v)
{
if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
{
- fputs ("#define ", print.outf);
- fputs ((const char *) cpp_macro_definition (pfile, node), print.outf);
- putc ('\n', print.outf);
- print.line++;
+ fputs ("#define ", pfile->print.outf);
+ fputs ((const char *) cpp_macro_definition (pfile, node),
+ pfile->print.outf);
+ putc ('\n', pfile->print.outf);
+ pfile->print.line++;
}
return 1;
diff --git a/contrib/gcc/cppspec.c b/contrib/gcc/cppspec.c
index 5f787d6..d5b49d0 100644
--- a/contrib/gcc/cppspec.c
+++ b/contrib/gcc/cppspec.c
@@ -29,32 +29,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
assume the user knows what they're doing. If no explicit input is
mentioned, it will read stdin. */
-/* Snarfed from gcc.c: */
-
-/* This defines which switch letters take arguments. */
-
-#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
- ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
- || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
- || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
- || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \
- || (CHAR) == 'B' || (CHAR) == 'b')
-
#ifndef SWITCH_TAKES_ARG
#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
#endif
-/* This defines which multi-letter switches take arguments. */
-
-#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR) \
- (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \
- || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \
- || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
- || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
- || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
- || !strcmp (STR, "isystem") || !strcmp (STR, "specs") \
- || !strcmp (STR, "MF") || !strcmp (STR, "MT") || !strcmp (STR, "MQ"))
-
#ifndef WORD_SWITCH_TAKES_ARG
#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
#endif
@@ -90,7 +68,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
/* Have we seen an input file? */
int seen_input = 0;
-
+
/* Positions to insert -xc, -xassembler-with-cpp, and -o, if necessary.
0 means unnecessary. */
int lang_c_here = 0;
@@ -99,7 +77,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
/* Do we need to fix up an input file with an unrecognized suffix? */
int need_fixups = 1;
-
+
int i, j, quote = 0;
const char **new_argv;
int new_argc;
@@ -117,7 +95,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
quote = 0;
continue;
}
-
+
if (argv[i][0] == '-')
{
if (argv[i][1] == '\0')
@@ -228,7 +206,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
new_argv[j] = NULL;
*in_argc = new_argc;
*in_argv = new_argv;
-}
+}
/* Called before linking. Returns 0 on success and -1 on failure. */
int lang_specific_pre_link ()
@@ -238,3 +216,9 @@ int lang_specific_pre_link ()
/* Number of extra output files that lang_specific_pre_link may generate. */
int lang_specific_extra_outfiles = 0; /* Not used for cpp. */
+
+/* Table of language-specific spec functions. */
+const struct spec_function lang_specific_spec_functions[] =
+{
+ { 0, 0 }
+};
diff --git a/contrib/gcc/cpptrad.c b/contrib/gcc/cpptrad.c
new file mode 100644
index 0000000..5c66659
--- /dev/null
+++ b/contrib/gcc/cpptrad.c
@@ -0,0 +1,1216 @@
+/* CPP Library - traditional lexical analysis and macro expansion.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Neil Booth, May 2002
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "cpplib.h"
+#include "cpphash.h"
+
+/* The replacement text of a function-like macro is stored as a
+ contiguous sequence of aligned blocks, each representing the text
+ between subsequent parameters.
+
+ Each block comprises the text between its surrounding parameters,
+ the length of that text, and the one-based index of the following
+ parameter. The final block in the replacement text is easily
+ recognizable as it has an argument index of zero. */
+
+struct block
+{
+ unsigned int text_len;
+ unsigned short arg_index;
+ uchar text[1];
+};
+
+#define BLOCK_HEADER_LEN offsetof (struct block, text)
+#define BLOCK_LEN(TEXT_LEN) CPP_ALIGN (BLOCK_HEADER_LEN + (TEXT_LEN))
+
+/* Structure holding information about a function-like macro
+ invocation. */
+struct fun_macro
+{
+ /* Memory buffer holding the trad_arg array. */
+ _cpp_buff *buff;
+
+ /* An array of size the number of macro parameters + 1, containing
+ the offsets of the start of each macro argument in the output
+ buffer. The argument continues until the character before the
+ start of the next one. */
+ size_t *args;
+
+ /* The hashnode of the macro. */
+ cpp_hashnode *node;
+
+ /* The offset of the macro name in the output buffer. */
+ size_t offset;
+
+ /* The line the macro name appeared on. */
+ unsigned int line;
+
+ /* Zero-based index of argument being currently lexed. */
+ unsigned int argc;
+};
+
+/* Lexing state. It is mostly used to prevent macro expansion. */
+enum ls {ls_none = 0, /* Normal state. */
+ ls_fun_open, /* When looking for '('. */
+ ls_fun_close, /* When looking for ')'. */
+ ls_defined, /* After defined. */
+ ls_defined_close, /* Looking for ')' of defined(). */
+ ls_hash, /* After # in preprocessor conditional. */
+ ls_predicate, /* After the predicate, maybe paren? */
+ ls_answer}; /* In answer to predicate. */
+
+/* Lexing TODO: Maybe handle space in escaped newlines. Stop cpplex.c
+ from recognizing comments and directives during its lexing pass. */
+
+static const uchar *handle_newline PARAMS ((cpp_reader *, const uchar *));
+static const uchar *skip_escaped_newlines PARAMS ((cpp_reader *,
+ const uchar *));
+static const uchar *skip_whitespace PARAMS ((cpp_reader *, const uchar *,
+ int));
+static cpp_hashnode *lex_identifier PARAMS ((cpp_reader *, const uchar *));
+static const uchar *copy_comment PARAMS ((cpp_reader *, const uchar *, int));
+static void scan_out_logical_line PARAMS ((cpp_reader *pfile, cpp_macro *));
+static void check_output_buffer PARAMS ((cpp_reader *, size_t));
+static void push_replacement_text PARAMS ((cpp_reader *, cpp_hashnode *));
+static bool scan_parameters PARAMS ((cpp_reader *, cpp_macro *));
+static bool recursive_macro PARAMS ((cpp_reader *, cpp_hashnode *));
+static void save_replacement_text PARAMS ((cpp_reader *, cpp_macro *,
+ unsigned int));
+static void maybe_start_funlike PARAMS ((cpp_reader *, cpp_hashnode *,
+ const uchar *, struct fun_macro *));
+static void save_argument PARAMS ((struct fun_macro *, size_t));
+static void replace_args_and_push PARAMS ((cpp_reader *, struct fun_macro *));
+static size_t canonicalize_text PARAMS ((uchar *, const uchar *, size_t,
+ uchar *));
+
+/* Ensures we have N bytes' space in the output buffer, and
+ reallocates it if not. */
+static void
+check_output_buffer (pfile, n)
+ cpp_reader *pfile;
+ size_t n;
+{
+ /* We might need two bytes to terminate an unterminated comment, and
+ one more to terminate the line with a NUL. */
+ n += 2 + 1;
+
+ if (n > (size_t) (pfile->out.limit - pfile->out.cur))
+ {
+ size_t size = pfile->out.cur - pfile->out.base;
+ size_t new_size = (size + n) * 3 / 2;
+
+ pfile->out.base
+ = (uchar *) xrealloc (pfile->out.base, new_size);
+ pfile->out.limit = pfile->out.base + new_size;
+ pfile->out.cur = pfile->out.base + size;
+ }
+}
+
+/* To be called whenever a newline character is encountered in the
+ input file, at CUR. Handles DOS, Mac and Unix ends of line, and
+ increments pfile->line.
+
+ Returns a pointer the character after the newline sequence. */
+static const uchar *
+handle_newline (pfile, cur)
+ cpp_reader *pfile;
+ const uchar *cur;
+{
+ pfile->line++;
+ if (cur[0] + cur[1] == '\r' + '\n')
+ cur++;
+ return cur + 1;
+}
+
+/* CUR points to any character in the current context, not necessarily
+ a backslash. Advances CUR until all escaped newlines are skipped,
+ and returns the new position without updating the context.
+
+ Warns if a file buffer ends in an escaped newline. */
+static const uchar *
+skip_escaped_newlines (pfile, cur)
+ cpp_reader *pfile;
+ const uchar *cur;
+{
+ const uchar *orig_cur = cur;
+
+ while (*cur == '\\' && is_vspace (cur[1]))
+ cur = handle_newline (pfile, cur + 1);
+
+ if (cur != orig_cur && cur == RLIMIT (pfile->context) && pfile->buffer->inc)
+ cpp_error (pfile, DL_PEDWARN, "backslash-newline at end of file");
+
+ return cur;
+}
+
+/* CUR points to the asterisk introducing a comment in the current
+ context. IN_DEFINE is true if we are in the replacement text of a
+ macro.
+
+ The asterisk and following comment is copied to the buffer pointed
+ to by pfile->out.cur, which must be of sufficient size.
+ Unterminated comments are diagnosed, and correctly terminated in
+ the output. pfile->out.cur is updated depending upon IN_DEFINE,
+ -C, -CC and pfile->state.in_directive.
+
+ Returns a pointer to the first character after the comment in the
+ input buffer. */
+static const uchar *
+copy_comment (pfile, cur, in_define)
+ cpp_reader *pfile;
+ const uchar *cur;
+ int in_define;
+{
+ unsigned int from_line = pfile->line;
+ const uchar *limit = RLIMIT (pfile->context);
+ uchar *out = pfile->out.cur;
+
+ do
+ {
+ unsigned int c = *cur++;
+ *out++ = c;
+
+ if (c == '/')
+ {
+ /* An immediate slash does not terminate the comment. */
+ if (out[-2] == '*' && out - 2 > pfile->out.cur)
+ goto done;
+
+ if (*cur == '*' && cur[1] != '/'
+ && CPP_OPTION (pfile, warn_comments))
+ cpp_error_with_line (pfile, DL_WARNING, pfile->line, 0,
+ "\"/*\" within comment");
+ }
+ else if (is_vspace (c))
+ {
+ cur = handle_newline (pfile, cur - 1);
+ /* Canonicalize newline sequences and skip escaped ones. */
+ if (out[-2] == '\\')
+ out -= 2;
+ else
+ out[-1] = '\n';
+ }
+ }
+ while (cur < limit);
+
+ cpp_error_with_line (pfile, DL_ERROR, from_line, 0, "unterminated comment");
+ *out++ = '*';
+ *out++ = '/';
+
+ done:
+ /* Comments in directives become spaces so that tokens are properly
+ separated when the ISO preprocessor re-lexes the line. The
+ exception is #define. */
+ if (pfile->state.in_directive)
+ {
+ if (in_define)
+ {
+ if (CPP_OPTION (pfile, discard_comments_in_macro_exp))
+ pfile->out.cur--;
+ else
+ pfile->out.cur = out;
+ }
+ else
+ pfile->out.cur[-1] = ' ';
+ }
+ else if (CPP_OPTION (pfile, discard_comments))
+ pfile->out.cur--;
+ else
+ pfile->out.cur = out;
+
+ return cur;
+}
+
+/* CUR points to any character in the input buffer. Skips over all
+ contiguous horizontal white space and NULs, including comments if
+ SKIP_COMMENTS, until reaching the first non-horizontal-whitespace
+ character or the end of the current context. Escaped newlines are
+ removed.
+
+ The whitespace is copied verbatim to the output buffer, except that
+ comments are handled as described in copy_comment().
+ pfile->out.cur is updated.
+
+ Returns a pointer to the first character after the whitespace in
+ the input buffer. */
+static const uchar *
+skip_whitespace (pfile, cur, skip_comments)
+ cpp_reader *pfile;
+ const uchar *cur;
+ int skip_comments;
+{
+ uchar *out = pfile->out.cur;
+
+ for (;;)
+ {
+ unsigned int c = *cur++;
+ *out++ = c;
+
+ if (is_nvspace (c) && c)
+ continue;
+
+ if (!c && cur - 1 != RLIMIT (pfile->context))
+ continue;
+
+ if (c == '/' && skip_comments)
+ {
+ const uchar *tmp = skip_escaped_newlines (pfile, cur);
+ if (*tmp == '*')
+ {
+ pfile->out.cur = out;
+ cur = copy_comment (pfile, tmp, false /* in_define */);
+ out = pfile->out.cur;
+ continue;
+ }
+ }
+
+ out--;
+ if (c == '\\' && is_vspace (*cur))
+ {
+ cur = skip_escaped_newlines (pfile, cur - 1);
+ continue;
+ }
+
+ break;
+ }
+
+ pfile->out.cur = out;
+ return cur - 1;
+}
+
+/* Lexes and outputs an identifier starting at CUR, which is assumed
+ to point to a valid first character of an identifier. Returns
+ the hashnode, and updates out.cur. */
+static cpp_hashnode *
+lex_identifier (pfile, cur)
+ cpp_reader *pfile;
+ const uchar *cur;
+{
+ size_t len;
+ uchar *out = pfile->out.cur;
+ cpp_hashnode *result;
+
+ do
+ {
+ do
+ *out++ = *cur++;
+ while (is_numchar (*cur));
+ cur = skip_escaped_newlines (pfile, cur);
+ }
+ while (is_numchar (*cur));
+
+ CUR (pfile->context) = cur;
+ len = out - pfile->out.cur;
+ result = (cpp_hashnode *) ht_lookup (pfile->hash_table, pfile->out.cur,
+ len, HT_ALLOC);
+ pfile->out.cur = out;
+ return result;
+}
+
+/* Overlays the true file buffer temporarily with text of length LEN
+ starting at START. The true buffer is restored upon calling
+ restore_buff(). */
+void
+_cpp_overlay_buffer (pfile, start, len)
+ cpp_reader *pfile;
+ const uchar *start;
+ size_t len;
+{
+ cpp_buffer *buffer = pfile->buffer;
+
+ pfile->overlaid_buffer = buffer;
+ buffer->saved_cur = buffer->cur;
+ buffer->saved_rlimit = buffer->rlimit;
+
+ buffer->cur = start;
+ buffer->rlimit = start + len;
+
+ pfile->saved_line = pfile->line;
+}
+
+/* Restores a buffer overlaid by _cpp_overlay_buffer(). */
+void
+_cpp_remove_overlay (pfile)
+ cpp_reader *pfile;
+{
+ cpp_buffer *buffer = pfile->overlaid_buffer;
+
+ buffer->cur = buffer->saved_cur;
+ buffer->rlimit = buffer->saved_rlimit;
+
+ pfile->line = pfile->saved_line;
+}
+
+/* Reads a logical line into the output buffer. Returns TRUE if there
+ is more text left in the buffer. */
+bool
+_cpp_read_logical_line_trad (pfile)
+ cpp_reader *pfile;
+{
+ do
+ {
+ if (pfile->buffer->cur == pfile->buffer->rlimit)
+ {
+ bool stop = true;
+
+ /* Don't pop the last buffer. */
+ if (pfile->buffer->prev)
+ {
+ stop = pfile->buffer->return_at_eof;
+ _cpp_pop_buffer (pfile);
+ }
+
+ if (stop)
+ return false;
+ }
+
+ scan_out_logical_line (pfile, NULL);
+ }
+ while (pfile->state.skipping);
+
+ return true;
+}
+
+/* Set up state for finding the opening '(' of a function-like
+ macro. */
+static void
+maybe_start_funlike (pfile, node, start, macro)
+ cpp_reader *pfile;
+ cpp_hashnode *node;
+ const uchar *start;
+ struct fun_macro *macro;
+{
+ unsigned int n = node->value.macro->paramc + 1;
+
+ if (macro->buff)
+ _cpp_release_buff (pfile, macro->buff);
+ macro->buff = _cpp_get_buff (pfile, n * sizeof (size_t));
+ macro->args = (size_t *) BUFF_FRONT (macro->buff);
+ macro->node = node;
+ macro->offset = start - pfile->out.base;
+ macro->argc = 0;
+}
+
+/* Save the OFFSET of the start of the next argument to MACRO. */
+static void
+save_argument (macro, offset)
+ struct fun_macro *macro;
+ size_t offset;
+{
+ macro->argc++;
+ if (macro->argc <= macro->node->value.macro->paramc)
+ macro->args[macro->argc] = offset;
+}
+
+/* Copies the next logical line in the current buffer (starting at
+ buffer->cur) to the output buffer. The output is guaranteed to
+ terminate with a NUL character. buffer->cur is updated.
+
+ If MACRO is non-NULL, then we are scanning the replacement list of
+ MACRO, and we call save_replacement_text() every time we meet an
+ argument. */
+static void
+scan_out_logical_line (pfile, macro)
+ cpp_reader *pfile;
+ cpp_macro *macro;
+{
+ cpp_context *context;
+ const uchar *cur;
+ uchar *out;
+ struct fun_macro fmacro;
+ unsigned int c, paren_depth = 0, quote;
+ enum ls lex_state = ls_none;
+ bool header_ok;
+
+ fmacro.buff = NULL;
+
+ start_logical_line:
+ quote = 0;
+ header_ok = pfile->state.angled_headers;
+ CUR (pfile->context) = pfile->buffer->cur;
+ RLIMIT (pfile->context) = pfile->buffer->rlimit;
+ pfile->out.cur = pfile->out.base;
+ pfile->out.first_line = pfile->line;
+ new_context:
+ context = pfile->context;
+ cur = CUR (context);
+ check_output_buffer (pfile, RLIMIT (context) - cur);
+ out = pfile->out.cur;
+
+ for (;;)
+ {
+ c = *cur++;
+ *out++ = c;
+
+ /* Whitespace should "continue" out of the switch,
+ non-whitespace should "break" out of it. */
+ switch (c)
+ {
+ case ' ':
+ case '\t':
+ case '\f':
+ case '\v':
+ continue;
+
+ case '\0':
+ if (cur - 1 != RLIMIT (context))
+ continue;
+
+ /* If this is a macro's expansion, pop it. */
+ if (context->prev)
+ {
+ pfile->out.cur = out - 1;
+ _cpp_pop_context (pfile);
+ goto new_context;
+ }
+
+ /* Premature end of file. Fake a new line. */
+ cur--;
+ if (!pfile->buffer->from_stage3)
+ cpp_error (pfile, DL_PEDWARN, "no newline at end of file");
+ pfile->line++;
+ goto done;
+
+ case '\r': case '\n':
+ cur = handle_newline (pfile, cur - 1);
+ if ((lex_state == ls_fun_open || lex_state == ls_fun_close)
+ && !pfile->state.in_directive)
+ {
+ /* Newlines in arguments become a space, but we don't
+ clear any in-progress quote. */
+ if (lex_state == ls_fun_close)
+ out[-1] = ' ';
+ continue;
+ }
+ goto done;
+
+ case '<':
+ if (header_ok)
+ quote = '>';
+ break;
+ case '>':
+ if (c == quote)
+ quote = 0;
+ break;
+
+ case '"':
+ case '\'':
+ if (c == quote)
+ quote = 0;
+ else if (!quote)
+ quote = c;
+ break;
+
+ case '\\':
+ if (is_vspace (*cur))
+ {
+ out--;
+ cur = skip_escaped_newlines (pfile, cur - 1);
+ continue;
+ }
+ else
+ {
+ /* Skip escaped quotes here, it's easier than above, but
+ take care to first skip escaped newlines. */
+ cur = skip_escaped_newlines (pfile, cur);
+ if (*cur == '\\' || *cur == '"' || *cur == '\'')
+ *out++ = *cur++;
+ }
+ break;
+
+ case '/':
+ /* Traditional CPP does not recognize comments within
+ literals. */
+ if (!quote)
+ {
+ cur = skip_escaped_newlines (pfile, cur);
+ if (*cur == '*')
+ {
+ pfile->out.cur = out;
+ cur = copy_comment (pfile, cur, macro != 0);
+ out = pfile->out.cur;
+ continue;
+ }
+ }
+ break;
+
+ case '_':
+ case 'a': case 'b': case 'c': case 'd': case 'e': 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 's': case 't': case 'u': case 'v': case 'w': case 'x':
+ case 'y': case 'z':
+ case 'A': case 'B': case 'C': case 'D': case 'E': 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 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+ case 'Y': case 'Z':
+ if (!pfile->state.skipping && (quote == 0 || macro))
+ {
+ cpp_hashnode *node;
+ uchar *out_start = out - 1;
+
+ pfile->out.cur = out_start;
+ node = lex_identifier (pfile, cur - 1);
+ out = pfile->out.cur;
+ cur = CUR (context);
+
+ if (node->type == NT_MACRO
+ /* Should we expand for ls_answer? */
+ && (lex_state == ls_none || lex_state == ls_fun_open)
+ && !pfile->state.prevent_expansion)
+ {
+ /* Macros invalidate MI optimization. */
+ pfile->mi_valid = false;
+ if (! (node->flags & NODE_BUILTIN)
+ && node->value.macro->fun_like)
+ {
+ maybe_start_funlike (pfile, node, out_start, &fmacro);
+ lex_state = ls_fun_open;
+ fmacro.line = pfile->line;
+ continue;
+ }
+ else if (!recursive_macro (pfile, node))
+ {
+ /* Remove the object-like macro's name from the
+ output, and push its replacement text. */
+ pfile->out.cur = out_start;
+ push_replacement_text (pfile, node);
+ lex_state = ls_none;
+ goto new_context;
+ }
+ }
+ else if (macro && node->arg_index)
+ {
+ /* Found a parameter in the replacement text of a
+ #define. Remove its name from the output. */
+ pfile->out.cur = out_start;
+ save_replacement_text (pfile, macro, node->arg_index);
+ out = pfile->out.base;
+ }
+ else if (lex_state == ls_hash)
+ {
+ lex_state = ls_predicate;
+ continue;
+ }
+ else if (pfile->state.in_expression
+ && node == pfile->spec_nodes.n_defined)
+ {
+ lex_state = ls_defined;
+ continue;
+ }
+ }
+ break;
+
+ case '(':
+ if (quote == 0)
+ {
+ paren_depth++;
+ if (lex_state == ls_fun_open)
+ {
+ if (recursive_macro (pfile, fmacro.node))
+ lex_state = ls_none;
+ else
+ {
+ lex_state = ls_fun_close;
+ paren_depth = 1;
+ out = pfile->out.base + fmacro.offset;
+ fmacro.args[0] = fmacro.offset;
+ }
+ }
+ else if (lex_state == ls_predicate)
+ lex_state = ls_answer;
+ else if (lex_state == ls_defined)
+ lex_state = ls_defined_close;
+ }
+ break;
+
+ case ',':
+ if (quote == 0 && lex_state == ls_fun_close && paren_depth == 1)
+ save_argument (&fmacro, out - pfile->out.base);
+ break;
+
+ case ')':
+ if (quote == 0)
+ {
+ paren_depth--;
+ if (lex_state == ls_fun_close && paren_depth == 0)
+ {
+ cpp_macro *m = fmacro.node->value.macro;
+
+ m->used = 1;
+ lex_state = ls_none;
+ save_argument (&fmacro, out - pfile->out.base);
+
+ /* A single zero-length argument is no argument. */
+ if (fmacro.argc == 1
+ && m->paramc == 0
+ && out == pfile->out.base + fmacro.offset + 1)
+ fmacro.argc = 0;
+
+ if (_cpp_arguments_ok (pfile, m, fmacro.node, fmacro.argc))
+ {
+ /* Remove the macro's invocation from the
+ output, and push its replacement text. */
+ pfile->out.cur = (pfile->out.base
+ + fmacro.offset);
+ CUR (context) = cur;
+ replace_args_and_push (pfile, &fmacro);
+ goto new_context;
+ }
+ }
+ else if (lex_state == ls_answer || lex_state == ls_defined_close)
+ lex_state = ls_none;
+ }
+ break;
+
+ case '#':
+ if (out - 1 == pfile->out.base
+ /* A '#' from a macro doesn't start a directive. */
+ && !pfile->context->prev
+ && !pfile->state.in_directive)
+ {
+ /* A directive. With the way _cpp_handle_directive
+ currently works, we only want to call it if either we
+ know the directive is OK, or we want it to fail and
+ be removed from the output. If we want it to be
+ passed through (the assembler case) then we must not
+ call _cpp_handle_directive. */
+ pfile->out.cur = out;
+ cur = skip_whitespace (pfile, cur, true /* skip_comments */);
+ out = pfile->out.cur;
+
+ if (is_vspace (*cur))
+ {
+ /* Null directive. Ignore it and don't invalidate
+ the MI optimization. */
+ out = pfile->out.base;
+ continue;
+ }
+ else
+ {
+ bool do_it = false;
+
+ if (is_numstart (*cur)
+ && CPP_OPTION (pfile, lang) != CLK_ASM)
+ do_it = true;
+ else if (is_idstart (*cur))
+ /* Check whether we know this directive, but don't
+ advance. */
+ do_it = lex_identifier (pfile, cur)->directive_index != 0;
+
+ if (do_it || CPP_OPTION (pfile, lang) != CLK_ASM)
+ {
+ /* This is a kludge. We want to have the ISO
+ preprocessor lex the next token. */
+ pfile->buffer->cur = cur;
+ _cpp_handle_directive (pfile, false /* indented */);
+ /* #include changes pfile->buffer so we need to
+ update the limits of the current context. */
+ goto start_logical_line;
+ }
+ }
+ }
+
+ if (pfile->state.in_expression)
+ {
+ lex_state = ls_hash;
+ continue;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Non-whitespace disables MI optimization and stops treating
+ '<' as a quote in #include. */
+ header_ok = false;
+ if (!pfile->state.in_directive)
+ pfile->mi_valid = false;
+
+ if (lex_state == ls_none)
+ continue;
+
+ /* Some of these transitions of state are syntax errors. The
+ ISO preprocessor will issue errors later. */
+ if (lex_state == ls_fun_open)
+ /* Missing '('. */
+ lex_state = ls_none;
+ else if (lex_state == ls_hash
+ || lex_state == ls_predicate
+ || lex_state == ls_defined)
+ lex_state = ls_none;
+
+ /* ls_answer and ls_defined_close keep going until ')'. */
+ }
+
+ done:
+ out[-1] = '\0';
+ pfile->buffer->cur = cur;
+ pfile->out.cur = out - 1;
+ if (fmacro.buff)
+ _cpp_release_buff (pfile, fmacro.buff);
+
+ if (lex_state == ls_fun_close)
+ cpp_error_with_line (pfile, DL_ERROR, fmacro.line, 0,
+ "unterminated argument list invoking macro \"%s\"",
+ NODE_NAME (fmacro.node));
+}
+
+/* Push a context holding the replacement text of the macro NODE on
+ the context stack. NODE is either object-like, or a function-like
+ macro with no arguments. */
+static void
+push_replacement_text (pfile, node)
+ cpp_reader *pfile;
+ cpp_hashnode *node;
+{
+ size_t len;
+ const uchar *text;
+
+ if (node->flags & NODE_BUILTIN)
+ {
+ text = _cpp_builtin_macro_text (pfile, node);
+ len = ustrlen (text);
+ }
+ else
+ {
+ cpp_macro *macro = node->value.macro;
+ macro->used = 1;
+ text = macro->exp.text;
+ len = macro->count;
+ }
+
+ _cpp_push_text_context (pfile, node, text, len);
+}
+
+/* Returns TRUE if traditional macro recursion is detected. */
+static bool
+recursive_macro (pfile, node)
+ cpp_reader *pfile;
+ cpp_hashnode *node;
+{
+ bool recursing = !!(node->flags & NODE_DISABLED);
+
+ /* Object-like macros that are already expanding are necessarily
+ recursive.
+
+ However, it is possible to have traditional function-like macros
+ that are not infinitely recursive but recurse to any given depth.
+ Further, it is easy to construct examples that get ever longer
+ until the point they stop recursing. So there is no easy way to
+ detect true recursion; instead we assume any expansion more than
+ 20 deep since the first invocation of this macro must be
+ recursing. */
+ if (recursing && node->value.macro->fun_like)
+ {
+ size_t depth = 0;
+ cpp_context *context = pfile->context;
+
+ do
+ {
+ depth++;
+ if (context->macro == node && depth > 20)
+ break;
+ context = context->prev;
+ }
+ while (context);
+ recursing = context != NULL;
+ }
+
+ if (recursing)
+ cpp_error (pfile, DL_ERROR,
+ "detected recursion whilst expanding macro \"%s\"",
+ NODE_NAME (node));
+
+ return recursing;
+}
+
+/* Return the length of the replacement text of a function-like or
+ object-like non-builtin macro. */
+size_t
+_cpp_replacement_text_len (macro)
+ const cpp_macro *macro;
+{
+ size_t len;
+
+ if (macro->fun_like && (macro->paramc != 0))
+ {
+ const uchar *exp;
+
+ len = 0;
+ for (exp = macro->exp.text;;)
+ {
+ struct block *b = (struct block *) exp;
+
+ len += b->text_len;
+ if (b->arg_index == 0)
+ break;
+ len += NODE_LEN (macro->params[b->arg_index - 1]);
+ exp += BLOCK_LEN (b->text_len);
+ }
+ }
+ else
+ len = macro->count;
+
+ return len;
+}
+
+/* Copy the replacement text of MACRO to DEST, which must be of
+ sufficient size. It is not NUL-terminated. The next character is
+ returned. */
+uchar *
+_cpp_copy_replacement_text (macro, dest)
+ const cpp_macro *macro;
+ uchar *dest;
+{
+ if (macro->fun_like && (macro->paramc != 0))
+ {
+ const uchar *exp;
+
+ for (exp = macro->exp.text;;)
+ {
+ struct block *b = (struct block *) exp;
+ cpp_hashnode *param;
+
+ memcpy (dest, b->text, b->text_len);
+ dest += b->text_len;
+ if (b->arg_index == 0)
+ break;
+ param = macro->params[b->arg_index - 1];
+ memcpy (dest, NODE_NAME (param), NODE_LEN (param));
+ dest += NODE_LEN (param);
+ exp += BLOCK_LEN (b->text_len);
+ }
+ }
+ else
+ {
+ memcpy (dest, macro->exp.text, macro->count);
+ dest += macro->count;
+ }
+
+ return dest;
+}
+
+/* Push a context holding the replacement text of the macro NODE on
+ the context stack. NODE is either object-like, or a function-like
+ macro with no arguments. */
+static void
+replace_args_and_push (pfile, fmacro)
+ cpp_reader *pfile;
+ struct fun_macro *fmacro;
+{
+ cpp_macro *macro = fmacro->node->value.macro;
+
+ if (macro->paramc == 0)
+ push_replacement_text (pfile, fmacro->node);
+ else
+ {
+ const uchar *exp;
+ uchar *p;
+ _cpp_buff *buff;
+ size_t len = 0;
+
+ /* Calculate the length of the argument-replaced text. */
+ for (exp = macro->exp.text;;)
+ {
+ struct block *b = (struct block *) exp;
+
+ len += b->text_len;
+ if (b->arg_index == 0)
+ break;
+ len += (fmacro->args[b->arg_index]
+ - fmacro->args[b->arg_index - 1] - 1);
+ exp += BLOCK_LEN (b->text_len);
+ }
+
+ /* Allocate room for the expansion plus NUL. */
+ buff = _cpp_get_buff (pfile, len + 1);
+
+ /* Copy the expansion and replace arguments. */
+ p = BUFF_FRONT (buff);
+ for (exp = macro->exp.text;;)
+ {
+ struct block *b = (struct block *) exp;
+ size_t arglen;
+
+ memcpy (p, b->text, b->text_len);
+ p += b->text_len;
+ if (b->arg_index == 0)
+ break;
+ arglen = (fmacro->args[b->arg_index]
+ - fmacro->args[b->arg_index - 1] - 1);
+ memcpy (p, pfile->out.base + fmacro->args[b->arg_index - 1],
+ arglen);
+ p += arglen;
+ exp += BLOCK_LEN (b->text_len);
+ }
+
+ /* NUL-terminate. */
+ *p = '\0';
+ _cpp_push_text_context (pfile, fmacro->node, BUFF_FRONT (buff), len);
+
+ /* So we free buffer allocation when macro is left. */
+ pfile->context->buff = buff;
+ }
+}
+
+/* Read and record the parameters, if any, of a function-like macro
+ definition. Destroys pfile->out.cur.
+
+ Returns true on success, false on failure (syntax error or a
+ duplicate parameter). On success, CUR (pfile->context) is just
+ past the closing parenthesis. */
+static bool
+scan_parameters (pfile, macro)
+ cpp_reader *pfile;
+ cpp_macro *macro;
+{
+ const uchar *cur = CUR (pfile->context) + 1;
+ bool ok;
+
+ for (;;)
+ {
+ cur = skip_whitespace (pfile, cur, true /* skip_comments */);
+
+ if (is_idstart (*cur))
+ {
+ ok = false;
+ if (_cpp_save_parameter (pfile, macro, lex_identifier (pfile, cur)))
+ break;
+ cur = skip_whitespace (pfile, CUR (pfile->context),
+ true /* skip_comments */);
+ if (*cur == ',')
+ {
+ cur++;
+ continue;
+ }
+ ok = (*cur == ')');
+ break;
+ }
+
+ ok = (*cur == ')' && macro->paramc == 0);
+ break;
+ }
+
+ CUR (pfile->context) = cur + (*cur == ')');
+
+ return ok;
+}
+
+/* Save the text from pfile->out.base to pfile->out.cur as
+ the replacement text for the current macro, followed by argument
+ ARG_INDEX, with zero indicating the end of the replacement
+ text. */
+static void
+save_replacement_text (pfile, macro, arg_index)
+ cpp_reader *pfile;
+ cpp_macro *macro;
+ unsigned int arg_index;
+{
+ size_t len = pfile->out.cur - pfile->out.base;
+ uchar *exp;
+
+ if (macro->paramc == 0)
+ {
+ /* Object-like and function-like macros without parameters
+ simply store their NUL-terminated replacement text. */
+ exp = _cpp_unaligned_alloc (pfile, len + 1);
+ memcpy (exp, pfile->out.base, len);
+ exp[len] = '\0';
+ macro->exp.text = exp;
+ macro->count = len;
+ }
+ else
+ {
+ /* Store the text's length (unsigned int), the argument index
+ (unsigned short, base 1) and then the text. */
+ size_t blen = BLOCK_LEN (len);
+ struct block *block;
+
+ if (macro->count + blen > BUFF_ROOM (pfile->a_buff))
+ _cpp_extend_buff (pfile, &pfile->a_buff, macro->count + blen);
+
+ exp = BUFF_FRONT (pfile->a_buff);
+ block = (struct block *) (exp + macro->count);
+ macro->exp.text = exp;
+
+ /* Write out the block information. */
+ block->text_len = len;
+ block->arg_index = arg_index;
+ memcpy (block->text, pfile->out.base, len);
+
+ /* Lex the rest into the start of the output buffer. */
+ pfile->out.cur = pfile->out.base;
+
+ macro->count += blen;
+
+ /* If we've finished, commit the memory. */
+ if (arg_index == 0)
+ BUFF_FRONT (pfile->a_buff) += macro->count;
+ }
+}
+
+/* Analyze and save the replacement text of a macro. Returns true on
+ success. */
+bool
+_cpp_create_trad_definition (pfile, macro)
+ cpp_reader *pfile;
+ cpp_macro *macro;
+{
+ const uchar *cur;
+ uchar *limit;
+ cpp_context *context = pfile->context;
+
+ /* The context has not been set up for command line defines, and CUR
+ has not been updated for the macro name for in-file defines. */
+ pfile->out.cur = pfile->out.base;
+ CUR (context) = pfile->buffer->cur;
+ RLIMIT (context) = pfile->buffer->rlimit;
+ check_output_buffer (pfile, RLIMIT (context) - CUR (context));
+
+ /* Is this a function-like macro? */
+ if (* CUR (context) == '(')
+ {
+ /* Setting macro to NULL indicates an error occurred, and
+ prevents unnecessary work in scan_out_logical_line. */
+ if (!scan_parameters (pfile, macro))
+ macro = NULL;
+ else
+ {
+ /* Success. Commit the parameter array. */
+ macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
+ BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc];
+ macro->fun_like = 1;
+ }
+ }
+
+ /* Skip leading whitespace in the replacement text. */
+ pfile->buffer->cur
+ = skip_whitespace (pfile, CUR (context),
+ CPP_OPTION (pfile, discard_comments_in_macro_exp));
+
+ pfile->state.prevent_expansion++;
+ scan_out_logical_line (pfile, macro);
+ pfile->state.prevent_expansion--;
+
+ if (!macro)
+ return false;
+
+ /* Skip trailing white space. */
+ cur = pfile->out.base;
+ limit = pfile->out.cur;
+ while (limit > cur && is_space (limit[-1]))
+ limit--;
+ pfile->out.cur = limit;
+ save_replacement_text (pfile, macro, 0);
+
+ return true;
+}
+
+/* Copy SRC of length LEN to DEST, but convert all contiguous
+ whitespace to a single space, provided it is not in quotes. The
+ quote currently in effect is pointed to by PQUOTE, and is updated
+ by the function. Returns the number of bytes copied. */
+static size_t
+canonicalize_text (dest, src, len, pquote)
+ uchar *dest;
+ const uchar *src;
+ size_t len;
+ uchar *pquote;
+{
+ uchar *orig_dest = dest;
+ uchar quote = *pquote;
+
+ while (len)
+ {
+ if (is_space (*src) && !quote)
+ {
+ do
+ src++, len--;
+ while (len && is_space (*src));
+ *dest++ = ' ';
+ }
+ else
+ {
+ if (*src == '\'' || *src == '"')
+ {
+ if (!quote)
+ quote = *src;
+ else if (quote == *src)
+ quote = 0;
+ }
+ *dest++ = *src++, len--;
+ }
+ }
+
+ *pquote = quote;
+ return dest - orig_dest;
+}
+
+/* Returns true if MACRO1 and MACRO2 have expansions different other
+ than in the form of their whitespace. */
+bool
+_cpp_expansions_different_trad (macro1, macro2)
+ const cpp_macro *macro1, *macro2;
+{
+ uchar *p1 = xmalloc (macro1->count + macro2->count);
+ uchar *p2 = p1 + macro1->count;
+ uchar quote1 = 0, quote2 = 0;
+ bool mismatch;
+ size_t len1, len2;
+
+ if (macro1->paramc > 0)
+ {
+ const uchar *exp1 = macro1->exp.text, *exp2 = macro2->exp.text;
+
+ mismatch = true;
+ for (;;)
+ {
+ struct block *b1 = (struct block *) exp1;
+ struct block *b2 = (struct block *) exp2;
+
+ if (b1->arg_index != b2->arg_index)
+ break;
+
+ len1 = canonicalize_text (p1, b1->text, b1->text_len, &quote1);
+ len2 = canonicalize_text (p2, b2->text, b2->text_len, &quote2);
+ if (len1 != len2 || memcmp (p1, p2, len1))
+ break;
+ if (b1->arg_index == 0)
+ {
+ mismatch = false;
+ break;
+ }
+ exp1 += BLOCK_LEN (b1->text_len);
+ exp2 += BLOCK_LEN (b2->text_len);
+ }
+ }
+ else
+ {
+ len1 = canonicalize_text (p1, macro1->exp.text, macro1->count, &quote1);
+ len2 = canonicalize_text (p2, macro2->exp.text, macro2->count, &quote2);
+ mismatch = (len1 != len2 || memcmp (p1, p2, len1));
+ }
+
+ free (p1);
+ return mismatch;
+}
diff --git a/contrib/gcc/crtstuff.c b/contrib/gcc/crtstuff.c
index d3484e3..cdc447d 100644
--- a/contrib/gcc/crtstuff.c
+++ b/contrib/gcc/crtstuff.c
@@ -90,6 +90,11 @@ call_ ## FUNC (void) \
#if defined(EH_FRAME_SECTION_NAME) && !defined(USE_PT_GNU_EH_FRAME)
# define USE_EH_FRAME_REGISTRY
#endif
+#if defined(EH_FRAME_SECTION_NAME) && defined(HAVE_LD_RO_RW_SECTION_MIXING)
+# define EH_FRAME_SECTION_CONST const
+#else
+# define EH_FRAME_SECTION_CONST
+#endif
/* We do not want to add the weak attribute to the declarations of these
routines in unwind-dw2-fde.h because that will cause the definition of
@@ -126,8 +131,6 @@ extern void *__deregister_frame_info_bases (void *)
/* Likewise for _Jv_RegisterClasses. */
extern void _Jv_RegisterClasses (void *) TARGET_ATTRIBUTE_WEAK;
-#ifndef OBJECT_FORMAT_MACHO
-
#ifdef OBJECT_FORMAT_ELF
/* Declare a pointer to void function type. */
@@ -187,13 +190,13 @@ STATIC func_ptr __DTOR_LIST__[1]
= { (func_ptr) (-1) };
#endif /* __DTOR_LIST__ alternatives */
-#ifdef EH_FRAME_SECTION_NAME
+#ifdef USE_EH_FRAME_REGISTRY
/* Stick a label at the beginning of the frame unwind info so we can register
and deregister it with the exception handling library code. */
-STATIC char __EH_FRAME_BEGIN__[]
+STATIC EH_FRAME_SECTION_CONST char __EH_FRAME_BEGIN__[]
__attribute__((section(EH_FRAME_SECTION_NAME), aligned(4)))
= { };
-#endif /* EH_FRAME_SECTION_NAME */
+#endif /* USE_EH_FRAME_REGISTRY */
#ifdef JCR_SECTION_NAME
/* Stick a label at the beginning of the java class registration info
@@ -213,13 +216,9 @@ STATIC void *__JCR_LIST__[]
in one DSO or the main program is not used in another object. The
dynamic linker takes care of this. */
-/* XXX Ideally the following should be implemented using
- __attribute__ ((__visibility__ ("hidden")))
- but the __attribute__ support is not yet there. */
#ifdef HAVE_GAS_HIDDEN
-asm (".hidden\t__dso_handle");
+extern void *__dso_handle __attribute__ ((__visibility__ ("hidden")));
#endif
-
#ifdef CRTSTUFFS_O
void *__dso_handle = &__dso_handle;
#else
@@ -459,7 +458,7 @@ STATIC func_ptr __DTOR_END__[1]
#ifdef EH_FRAME_SECTION_NAME
/* Terminate the frame unwind info section with a 4byte 0 as a sentinel;
this would be the 'length' field in a real FDE. */
-STATIC int __FRAME_END__[]
+STATIC EH_FRAME_SECTION_CONST int __FRAME_END__[]
__attribute__ ((unused, mode(SI), section(EH_FRAME_SECTION_NAME),
aligned(4)))
= { 0 };
@@ -546,67 +545,3 @@ __do_global_ctors (void)
#else /* ! CRT_BEGIN && ! CRT_END */
#error "One of CRT_BEGIN or CRT_END must be defined."
#endif
-
-#else /* OBJECT_FORMAT_MACHO */
-
-/* For Mach-O format executables, we assume that the system's runtime is
- smart enough to handle constructors and destructors, but doesn't have
- an init section (if it can't even handle constructors/destructors
- you should be using INVOKE__main, not crtstuff). All we need to do
- is install/deinstall the frame information for exceptions. We do this
- by putting a constructor in crtbegin.o and a destructor in crtend.o.
-
- crtend.o also puts in the terminating zero in the frame information
- segment. */
-
-/* The crtstuff for other object formats use the symbol __EH_FRAME_BEGIN__
- to figure out the start of the exception frame, but here we use
- getsectbynamefromheader to find this value. Either method would work,
- but this method avoids creating any global symbols, which seems
- cleaner. */
-
-#include <mach-o/ldsyms.h>
-extern const struct section *
- getsectbynamefromheader (const struct mach_header *,
- const char *, const char *);
-
-#ifdef CRT_BEGIN
-
-static void __reg_frame_ctor (void) __attribute__ ((constructor));
-
-static void
-__reg_frame_ctor (void)
-{
- static struct object object;
- const struct section *eh_frame;
-
- eh_frame = getsectbynamefromheader (&_mh_execute_header,
- "__TEXT", "__eh_frame");
- __register_frame_info ((void *) eh_frame->addr, &object);
-}
-
-#elif defined(CRT_END)
-
-static void __dereg_frame_dtor (void) __attribute__ ((destructor));
-
-static void
-__dereg_frame_dtor (void)
-{
- const struct section *eh_frame;
-
- eh_frame = getsectbynamefromheader (&_mh_execute_header,
- "__TEXT", "__eh_frame");
- __deregister_frame_info ((void *) eh_frame->addr);
-}
-
-/* Terminate the frame section with a final zero. */
-STATIC int __FRAME_END__[]
- __attribute__ ((unused, mode(SI), section(EH_FRAME_SECTION_NAME),
- aligned(4)))
- = { 0 };
-
-#else /* ! CRT_BEGIN && ! CRT_END */
-#error "One of CRT_BEGIN or CRT_END must be defined."
-#endif
-
-#endif /* OBJECT_FORMAT_MACHO */
diff --git a/contrib/gcc/cse.c b/contrib/gcc/cse.c
index 65f4542f..1ace412 100644
--- a/contrib/gcc/cse.c
+++ b/contrib/gcc/cse.c
@@ -37,6 +37,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "toplev.h"
#include "output.h"
#include "ggc.h"
+#include "timevar.h"
/* The basic idea of common subexpression elimination is to go
through the code, keeping a record of expressions that would
@@ -315,6 +316,10 @@ struct cse_reg_info
reg_tick value, such expressions existing in the hash table are
invalid. */
int reg_in_table;
+
+ /* The SUBREG that was set when REG_TICK was last incremented. Set
+ to -1 if the last store was to the whole register, not a subreg. */
+ unsigned int subreg_ticked;
};
/* A free list of cse_reg_info entries. */
@@ -513,6 +518,11 @@ struct table_elt
#define REG_IN_TABLE(N) ((GET_CSE_REG_INFO (N))->reg_in_table)
+/* Get the SUBREG set at the last increment to REG_TICK (-1 if not a
+ SUBREG). */
+
+#define SUBREG_TICKED(N) ((GET_CSE_REG_INFO (N))->subreg_ticked)
+
/* Get the quantity number for REG. */
#define REG_QTY(N) ((GET_CSE_REG_INFO (N))->reg_qty)
@@ -690,7 +700,7 @@ static int check_dependence PARAMS ((rtx *, void *));
static void flush_hash_table PARAMS ((void));
static bool insn_live_p PARAMS ((rtx, int *));
static bool set_live_p PARAMS ((rtx, rtx, int *));
-static bool dead_libcall_p PARAMS ((rtx));
+static bool dead_libcall_p PARAMS ((rtx, int *));
/* Dump the expressions in the equivalence class indicated by CLASSP.
This function is used only for debugging. */
@@ -719,10 +729,25 @@ approx_reg_cost_1 (xp, data)
void *data;
{
rtx x = *xp;
- regset set = (regset) data;
+ int *cost_p = data;
if (x && GET_CODE (x) == REG)
- SET_REGNO_REG_SET (set, REGNO (x));
+ {
+ unsigned int regno = REGNO (x);
+
+ if (! CHEAP_REGNO (regno))
+ {
+ if (regno < FIRST_PSEUDO_REGISTER)
+ {
+ if (SMALL_REGISTER_CLASSES)
+ return 1;
+ *cost_p += 2;
+ }
+ else
+ *cost_p += 1;
+ }
+ }
+
return 0;
}
@@ -735,28 +760,12 @@ static int
approx_reg_cost (x)
rtx x;
{
- regset_head set;
- int i;
int cost = 0;
- int hardregs = 0;
-
- INIT_REG_SET (&set);
- for_each_rtx (&x, approx_reg_cost_1, (void *)&set);
- EXECUTE_IF_SET_IN_REG_SET
- (&set, 0, i,
- {
- if (! CHEAP_REGNO (i))
- {
- if (i < FIRST_PSEUDO_REGISTER)
- hardregs++;
+ if (for_each_rtx (&x, approx_reg_cost_1, (void *) &cost))
+ return MAX_COST;
- cost += i < FIRST_PSEUDO_REGISTER ? 2 : 1;
- }
- });
-
- CLEAR_REG_SET (&set);
- return hardregs && SMALL_REGISTER_CLASSES ? MAX_COST : cost;
+ return cost;
}
/* Return a negative value if an rtx A, whose costs are given by COST_A
@@ -767,7 +776,7 @@ static int
preferrable (cost_a, regcost_a, cost_b, regcost_b)
int cost_a, regcost_a, cost_b, regcost_b;
{
- /* First, get rid of a cases involving expressions that are entirely
+ /* First, get rid of cases involving expressions that are entirely
unwanted. */
if (cost_a != cost_b)
{
@@ -841,13 +850,7 @@ rtx_cost (x, outer_code)
switch (code)
{
case MULT:
- /* Count multiplication by 2**n as a shift,
- because if we are considering it, we would output it as a shift. */
- if (GET_CODE (XEXP (x, 1)) == CONST_INT
- && exact_log2 (INTVAL (XEXP (x, 1))) >= 0)
- total = 2;
- else
- total = COSTS_N_INSNS (5);
+ total = COSTS_N_INSNS (5);
break;
case DIV:
case UDIV:
@@ -963,6 +966,7 @@ get_cse_reg_info (regno)
/* Initialize it. */
p->reg_tick = 1;
p->reg_in_table = -1;
+ p->subreg_ticked = -1;
p->reg_qty = regno;
p->regno = regno;
p->next = cse_reg_info_used_list;
@@ -1197,6 +1201,7 @@ mention_regs (x)
remove_invalid_refs (i);
REG_IN_TABLE (i) = REG_TICK (i);
+ SUBREG_TICKED (i) = -1;
}
return 0;
@@ -1212,17 +1217,20 @@ mention_regs (x)
if (REG_IN_TABLE (i) >= 0 && REG_IN_TABLE (i) != REG_TICK (i))
{
- /* If reg_tick has been incremented more than once since
- reg_in_table was last set, that means that the entire
- register has been set before, so discard anything memorized
- for the entire register, including all SUBREG expressions. */
- if (REG_IN_TABLE (i) != REG_TICK (i) - 1)
+ /* If REG_IN_TABLE (i) differs from REG_TICK (i) by one, and
+ the last store to this register really stored into this
+ subreg, then remove the memory of this subreg.
+ Otherwise, remove any memory of the entire register and
+ all its subregs from the table. */
+ if (REG_TICK (i) - REG_IN_TABLE (i) > 1
+ || SUBREG_TICKED (i) != REGNO (SUBREG_REG (x)))
remove_invalid_refs (i);
else
remove_invalid_subreg_refs (i, SUBREG_BYTE (x), GET_MODE (x));
}
REG_IN_TABLE (i) = REG_TICK (i);
+ SUBREG_TICKED (i) = REGNO (SUBREG_REG (x));
return 0;
}
@@ -1600,8 +1608,8 @@ insert (x, classp, hash, mode)
elt->is_const = (CONSTANT_P (x)
/* GNU C++ takes advantage of this for `this'
(and other const values). */
- || (RTX_UNCHANGING_P (x)
- && GET_CODE (x) == REG
+ || (GET_CODE (x) == REG
+ && RTX_UNCHANGING_P (x)
&& REGNO (x) >= FIRST_PSEUDO_REGISTER)
|| FIXED_BASE_PLUS_P (x));
@@ -1867,6 +1875,7 @@ invalidate (x, full_mode)
delete_reg_equiv (regno);
REG_TICK (regno)++;
+ SUBREG_TICKED (regno) = -1;
if (regno >= FIRST_PSEUDO_REGISTER)
{
@@ -1894,6 +1903,7 @@ invalidate (x, full_mode)
CLEAR_HARD_REG_BIT (hard_regs_in_table, rn);
delete_reg_equiv (rn);
REG_TICK (rn)++;
+ SUBREG_TICKED (rn) = -1;
}
if (in_table)
@@ -1989,7 +1999,7 @@ remove_invalid_refs (regno)
{
next = p->next_same_hash;
if (GET_CODE (p->exp) != REG
- && refers_to_regno_p (regno, regno + 1, p->exp, (rtx*) 0))
+ && refers_to_regno_p (regno, regno + 1, p->exp, (rtx *) 0))
remove_from_table (p, i);
}
}
@@ -2019,7 +2029,7 @@ remove_invalid_subreg_refs (regno, offset, mode)
|| (((SUBREG_BYTE (exp)
+ (GET_MODE_SIZE (GET_MODE (exp)) - 1)) >= offset)
&& SUBREG_BYTE (exp) <= end))
- && refers_to_regno_p (regno, regno + 1, p->exp, (rtx*) 0))
+ && refers_to_regno_p (regno, regno + 1, p->exp, (rtx *) 0))
remove_from_table (p, i);
}
}
@@ -2099,7 +2109,10 @@ invalidate_for_call ()
{
delete_reg_equiv (regno);
if (REG_TICK (regno) >= 0)
- REG_TICK (regno)++;
+ {
+ REG_TICK (regno)++;
+ SUBREG_TICKED (regno) = -1;
+ }
in_table |= (TEST_HARD_REG_BIT (hard_regs_in_table, regno) != 0);
}
@@ -2211,8 +2224,8 @@ canon_hash_string (ps)
const char *ps;
{
unsigned hash = 0;
- const unsigned char *p = (const unsigned char *)ps;
-
+ const unsigned char *p = (const unsigned char *) ps;
+
if (p)
while (*p)
hash += *p++;
@@ -2264,7 +2277,7 @@ canon_hash (x, mode)
failure to do so leads to failure to simplify 0<100 type of
conditionals.
- On all machines, we can't record any global registers.
+ On all machines, we can't record any global registers.
Nor should we record any register that is in a small
class, as defined by CLASS_LIKELY_SPILLED_P. */
@@ -2326,11 +2339,7 @@ canon_hash (x, mode)
the integers representing the constant. */
hash += (unsigned) code + (unsigned) GET_MODE (x);
if (GET_MODE (x) != VOIDmode)
- for (i = 2; i < GET_RTX_LENGTH (CONST_DOUBLE); i++)
- {
- unsigned HOST_WIDE_INT tem = XWINT (x, i);
- hash += tem;
- }
+ hash += real_hash (CONST_DOUBLE_REAL_VALUE (x));
else
hash += ((unsigned) CONST_DOUBLE_LOW (x)
+ (unsigned) CONST_DOUBLE_HIGH (x));
@@ -2387,7 +2396,7 @@ canon_hash (x, mode)
if (GET_CODE (XEXP (x, 0)) == MEM
&& ! MEM_VOLATILE_P (XEXP (x, 0)))
{
- hash += (unsigned)USE;
+ hash += (unsigned) USE;
x = XEXP (x, 0);
if (! RTX_UNCHANGING_P (x) || FIXED_BASE_PLUS_P (XEXP (x, 0)))
@@ -2778,9 +2787,9 @@ cse_rtx_varies_p (x, from_alias)
replace each register reference inside it
with the "oldest" equivalent register.
- If INSN is non-zero and we are replacing a pseudo with a hard register
+ If INSN is nonzero and we are replacing a pseudo with a hard register
or vice versa, validate_change is used to ensure that INSN remains valid
- after we make our substitution. The calls are made with IN_GROUP non-zero
+ after we make our substitution. The calls are made with IN_GROUP nonzero
so apply_change_group must be called upon the outermost return from this
function (unless INSN is zero). The result of apply_change_group can
generally be discarded since the changes we are making are optional. */
@@ -3135,7 +3144,7 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
while (arg2 == CONST0_RTX (GET_MODE (arg1)))
{
- /* Set non-zero when we find something of interest. */
+ /* Set nonzero when we find something of interest. */
rtx x = 0;
int reverse_code = 0;
struct table_elt *p = 0;
@@ -3153,13 +3162,17 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
else if (GET_RTX_CLASS (GET_CODE (arg1)) == '<')
{
+#ifdef FLOAT_STORE_FLAG_VALUE
+ REAL_VALUE_TYPE fsfv;
+#endif
+
if (code == NE
|| (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_INT
&& code == LT && STORE_FLAG_VALUE == -1)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_FLOAT
- && (REAL_VALUE_NEGATIVE
- (FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
+ && (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
+ REAL_VALUE_NEGATIVE (fsfv)))
#endif
)
x = arg1;
@@ -3168,8 +3181,8 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
&& code == GE && STORE_FLAG_VALUE == -1)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_FLOAT
- && (REAL_VALUE_NEGATIVE
- (FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
+ && (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
+ REAL_VALUE_NEGATIVE (fsfv)))
#endif
)
x = arg1, reverse_code = 1;
@@ -3205,6 +3218,9 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
for (; p; p = p->next_same_value)
{
enum machine_mode inner_mode = GET_MODE (p->exp);
+#ifdef FLOAT_STORE_FLAG_VALUE
+ REAL_VALUE_TYPE fsfv;
+#endif
/* If the entry isn't valid, skip it. */
if (! exp_equiv_p (p->exp, p->exp, 1, 0))
@@ -3229,8 +3245,8 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (code == LT
&& GET_MODE_CLASS (inner_mode) == MODE_FLOAT
- && (REAL_VALUE_NEGATIVE
- (FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
+ && (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
+ REAL_VALUE_NEGATIVE (fsfv)))
#endif
)
&& GET_RTX_CLASS (GET_CODE (p->exp)) == '<'))
@@ -3249,8 +3265,8 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (code == GE
&& GET_MODE_CLASS (inner_mode) == MODE_FLOAT
- && (REAL_VALUE_NEGATIVE
- (FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
+ && (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
+ REAL_VALUE_NEGATIVE (fsfv)))
#endif
)
&& GET_RTX_CLASS (GET_CODE (p->exp)) == '<')
@@ -3282,7 +3298,8 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
enum rtx_code reversed = reversed_comparison_code (x, NULL_RTX);
if (reversed == UNKNOWN)
break;
- else code = reversed;
+ else
+ code = reversed;
}
else if (GET_RTX_CLASS (GET_CODE (x)) == '<')
code = GET_CODE (x);
@@ -3734,6 +3751,7 @@ fold_rtx (x, insn)
rtx cheap_arg, expensive_arg;
rtx replacements[2];
int j;
+ int old_cost = COST_IN (XEXP (x, i), code);
/* Most arguments are cheap, so handle them specially. */
switch (GET_CODE (arg))
@@ -3822,9 +3840,8 @@ fold_rtx (x, insn)
replacements[0] = cheap_arg;
replacements[1] = expensive_arg;
- for (j = 0; j < 2 && replacements[j]; j++)
+ for (j = 0; j < 2 && replacements[j]; j++)
{
- int old_cost = COST_IN (XEXP (x, i), code);
int new_cost = COST_IN (replacements[j], code);
/* Stop if what existed before was cheaper. Prefer constants
@@ -3940,7 +3957,7 @@ fold_rtx (x, insn)
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
{
true_rtx = (CONST_DOUBLE_FROM_REAL_VALUE
- (FLOAT_STORE_FLAG_VALUE (mode), mode));
+ (FLOAT_STORE_FLAG_VALUE (mode), mode));
false_rtx = CONST0_RTX (mode);
}
#endif
@@ -3995,19 +4012,18 @@ fold_rtx (x, insn)
& HASH_MASK), mode_arg0))
&& p0->first_same_value == p1->first_same_value))
{
- /* Sadly two equal NaNs are not equivalent. */
- if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || ! FLOAT_MODE_P (mode_arg0)
- || flag_unsafe_math_optimizations)
- return ((code == EQ || code == LE || code == GE
- || code == LEU || code == GEU || code == UNEQ
- || code == UNLE || code == UNGE || code == ORDERED)
- ? true_rtx : false_rtx);
- /* Take care for the FP compares we can resolve. */
- if (code == UNEQ || code == UNLE || code == UNGE)
- return true_rtx;
- if (code == LTGT || code == LT || code == GT)
- return false_rtx;
+ /* Sadly two equal NaNs are not equivalent. */
+ if (!HONOR_NANS (mode_arg0))
+ return ((code == EQ || code == LE || code == GE
+ || code == LEU || code == GEU || code == UNEQ
+ || code == UNLE || code == UNGE
+ || code == ORDERED)
+ ? true_rtx : false_rtx);
+ /* Take care for the FP compares we can resolve. */
+ if (code == UNEQ || code == UNLE || code == UNGE)
+ return true_rtx;
+ if (code == LTGT || code == LT || code == GT)
+ return false_rtx;
}
/* If FOLDED_ARG0 is a register, see if the comparison we are
@@ -4215,7 +4231,7 @@ fold_rtx (x, insn)
from_plus:
case SMIN: case SMAX: case UMIN: case UMAX:
case IOR: case AND: case XOR:
- case MULT: case DIV: case UDIV:
+ case MULT:
case ASHIFT: case LSHIFTRT: case ASHIFTRT:
/* If we have (<op> <reg> <const_int>) for an associative OP and REG
is known to be of similar form, we may be able to replace the
@@ -4263,11 +4279,9 @@ fold_rtx (x, insn)
break;
/* Compute the code used to compose the constants. For example,
- A/C1/C2 is A/(C1 * C2), so if CODE == DIV, we want MULT. */
+ A-C1-C2 is A-(C1 + C2), so if CODE == MINUS, we want PLUS. */
- associate_code
- = (code == MULT || code == DIV || code == UDIV ? MULT
- : is_shift || code == PLUS || code == MINUS ? PLUS : code);
+ associate_code = (is_shift || code == MINUS ? PLUS : code);
new_const = simplify_binary_operation (associate_code, mode,
const_arg1, inner_const);
@@ -4305,6 +4319,14 @@ fold_rtx (x, insn)
}
break;
+ case DIV: case UDIV:
+ /* ??? The associative optimization performed immediately above is
+ also possible for DIV and UDIV using associate_code of MULT.
+ However, we would need extra code to verify that the
+ multiplication does not overflow, that is, there is no overflow
+ in the calculation of new_const. */
+ break;
+
default:
break;
}
@@ -5007,7 +5029,7 @@ cse_insn (insn, libcall_insn)
int src_folded_regcost = MAX_COST;
int src_related_regcost = MAX_COST;
int src_elt_regcost = MAX_COST;
- /* Set non-zero if we need to call force_const_mem on with the
+ /* Set nonzero if we need to call force_const_mem on with the
contents of src_folded before using it. */
int src_folded_force_flag = 0;
@@ -5347,9 +5369,9 @@ cse_insn (insn, libcall_insn)
if (src == src_folded)
src_folded = 0;
- /* At this point, ELT, if non-zero, points to a class of expressions
+ /* At this point, ELT, if nonzero, points to a class of expressions
equivalent to the source of this SET and SRC, SRC_EQV, SRC_FOLDED,
- and SRC_RELATED, if non-zero, each contain additional equivalent
+ and SRC_RELATED, if nonzero, each contain additional equivalent
expressions. Prune these latter expressions by deleting expressions
already in the equivalence class.
@@ -5486,13 +5508,13 @@ cse_insn (insn, libcall_insn)
continue;
}
- if (elt)
+ if (elt)
{
src_elt_cost = elt->cost;
src_elt_regcost = elt->regcost;
}
- /* Find cheapest and skip it for the next time. For items
+ /* Find cheapest and skip it for the next time. For items
of equal cost, use this order:
src_folded, src, src_eqv, src_related and hash table entry. */
if (src_folded
@@ -5526,7 +5548,7 @@ cse_insn (insn, libcall_insn)
else if (src_related
&& preferrable (src_related_cost, src_related_regcost,
src_elt_cost, src_elt_regcost) <= 0)
- trial = copy_rtx (src_related), src_related_cost = MAX_COST;
+ trial = copy_rtx (src_related), src_related_cost = MAX_COST;
else
{
trial = copy_rtx (elt->exp);
@@ -5691,7 +5713,7 @@ cse_insn (insn, libcall_insn)
a new one if one does not already exist. */
set_unique_reg_note (insn, REG_EQUAL, src_const);
- /* If storing a constant value in a register that
+ /* If storing a constant value in a register that
previously held the constant value 0,
record this fact with a REG_WAS_0 note on this insn.
@@ -5817,10 +5839,11 @@ cse_insn (insn, libcall_insn)
and hope for the best. */
if (n_sets == 1)
{
- rtx new = emit_jump_insn_before (gen_jump (XEXP (src, 0)), insn);
+ rtx new = emit_jump_insn_after (gen_jump (XEXP (src, 0)), insn);
JUMP_LABEL (new) = XEXP (src, 0);
LABEL_NUSES (XEXP (src, 0))++;
+ delete_insn (insn);
insn = new;
/* Now emit a BARRIER after the unconditional jump. */
@@ -6201,15 +6224,38 @@ cse_insn (insn, libcall_insn)
rtx new_src = 0;
unsigned src_hash;
struct table_elt *src_elt;
+ int byte = 0;
/* Ignore invalid entries. */
if (GET_CODE (elt->exp) != REG
&& ! exp_equiv_p (elt->exp, elt->exp, 1, 0))
continue;
- new_src = gen_lowpart_if_possible (new_mode, elt->exp);
- if (new_src == 0)
- new_src = gen_rtx_SUBREG (new_mode, elt->exp, 0);
+ /* We may have already been playing subreg games. If the
+ mode is already correct for the destination, use it. */
+ if (GET_MODE (elt->exp) == new_mode)
+ new_src = elt->exp;
+ else
+ {
+ /* Calculate big endian correction for the SUBREG_BYTE.
+ We have already checked that M1 (GET_MODE (dest))
+ is not narrower than M2 (new_mode). */
+ if (BYTES_BIG_ENDIAN)
+ byte = (GET_MODE_SIZE (GET_MODE (dest))
+ - GET_MODE_SIZE (new_mode));
+
+ new_src = simplify_gen_subreg (new_mode, elt->exp,
+ GET_MODE (dest), byte);
+ }
+
+ /* The call to simplify_gen_subreg fails if the value
+ is VOIDmode, yet we can't do any simplification, e.g.
+ for EXPR_LISTs denoting function call results.
+ It is invalid to construct a SUBREG with a VOIDmode
+ SUBREG_REG, hence a zero new_src means we can't do
+ this substitution. */
+ if (! new_src)
+ continue;
src_hash = HASH (new_src, new_mode);
src_elt = lookup (new_src, src_hash, new_mode);
@@ -6270,8 +6316,16 @@ cse_insn (insn, libcall_insn)
if ((src_ent->first_reg == REGNO (SET_DEST (sets[0].rtl)))
&& ! find_reg_note (insn, REG_RETVAL, NULL_RTX))
{
- rtx prev = prev_nonnote_insn (insn);
-
+ rtx prev = insn;
+ /* Scan for the previous nonnote insn, but stop at a basic
+ block boundary. */
+ do
+ {
+ prev = PREV_INSN (prev);
+ }
+ while (prev && GET_CODE (prev) == NOTE
+ && NOTE_LINE_NUMBER (prev) != NOTE_INSN_BASIC_BLOCK);
+
/* Do not swap the registers around if the previous instruction
attaches a REG_EQUIV note to REG1.
@@ -6282,7 +6336,7 @@ cse_insn (insn, libcall_insn)
This section previously turned the REG_EQUIV into a REG_EQUAL
note. We cannot do that because REG_EQUIV may provide an
- uninitialised stack slot when REG_PARM_STACK_SPACE is used. */
+ uninitialized stack slot when REG_PARM_STACK_SPACE is used. */
if (prev != 0 && GET_CODE (prev) == INSN
&& GET_CODE (PATTERN (prev)) == SET
@@ -6380,7 +6434,11 @@ addr_affects_sp_p (addr)
&& REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
{
if (REG_TICK (STACK_POINTER_REGNUM) >= 0)
- REG_TICK (STACK_POINTER_REGNUM)++;
+ {
+ REG_TICK (STACK_POINTER_REGNUM)++;
+ /* Is it possible to use a subreg of SP? */
+ SUBREG_TICKED (STACK_POINTER_REGNUM) = -1;
+ }
/* This should be *very* rare. */
if (TEST_HARD_REG_BIT (hard_regs_in_table, STACK_POINTER_REGNUM))
@@ -6810,10 +6868,10 @@ cse_set_around_loop (x, insn, loop_start)
the total number of SETs in all the insns of the block, the last insn of the
block, and the branch path.
- The branch path indicates which branches should be followed. If a non-zero
+ The branch path indicates which branches should be followed. If a nonzero
path size is specified, the block should be rescanned and a different set
of branches will be taken. The branch path is only used if
- FLAG_CSE_FOLLOW_JUMPS or FLAG_CSE_SKIP_BLOCKS is non-zero.
+ FLAG_CSE_FOLLOW_JUMPS or FLAG_CSE_SKIP_BLOCKS is nonzero.
DATA is a pointer to a struct cse_basic_block_data, defined below, that is
used to describe the block. It is filled in with the information about
@@ -6839,7 +6897,7 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop, skip_blocks)
/* Update the previous branch path, if any. If the last branch was
previously TAKEN, mark it NOT_TAKEN. If it was previously NOT_TAKEN,
shorten the path by one and look at the previous branch. We know that
- at least one branch must have been taken if PATH_SIZE is non-zero. */
+ at least one branch must have been taken if PATH_SIZE is nonzero. */
while (path_size > 0)
{
if (data->path[path_size - 1].status != NOT_TAKEN)
@@ -7184,7 +7242,7 @@ cse_main (f, nregs, after_loop, file)
block. NEXT_BRANCH points to the branch path when following jumps or
a null path when not following jumps.
- AROUND_LOOP is non-zero if we are to try to cse around to the start of a
+ AROUND_LOOP is nonzero if we are to try to cse around to the start of a
loop. This is true when we are being called for the last time on a
block and this CSE pass is before loop.c. */
@@ -7383,7 +7441,7 @@ cse_basic_block (from, to, next_branch, around_loop)
we can cse into the loop. Don't do this if we changed the jump
structure of a loop unless we aren't going to be following jumps. */
- insn = prev_nonnote_insn(to);
+ insn = prev_nonnote_insn (to);
if ((cse_jumps_altered == 0
|| (flag_cse_follow_jumps == 0 && flag_cse_skip_blocks == 0))
&& around_loop && to != 0
@@ -7435,6 +7493,7 @@ count_reg_usage (x, counts, dest, incr)
int incr;
{
enum rtx_code code;
+ rtx note;
const char *fmt;
int i, j;
@@ -7492,16 +7551,13 @@ count_reg_usage (x, counts, dest, incr)
/* Things used in a REG_EQUAL note aren't dead since loop may try to
use them. */
- count_reg_usage (REG_NOTES (x), counts, NULL_RTX, incr);
+ note = find_reg_equal_equiv_note (x);
+ if (note)
+ count_reg_usage (XEXP (note, 0), counts, NULL_RTX, incr);
return;
- case EXPR_LIST:
case INSN_LIST:
- if (REG_NOTE_KIND (x) == REG_EQUAL
- || (REG_NOTE_KIND (x) != REG_NONNEG && GET_CODE (XEXP (x,0)) == USE))
- count_reg_usage (XEXP (x, 0), counts, NULL_RTX, incr);
- count_reg_usage (XEXP (x, 1), counts, NULL_RTX, incr);
- return;
+ abort ();
default:
break;
@@ -7561,7 +7617,9 @@ insn_live_p (insn, counts)
int *counts;
{
int i;
- if (GET_CODE (PATTERN (insn)) == SET)
+ if (flag_non_call_exceptions && may_trap_p (PATTERN (insn)))
+ return true;
+ else if (GET_CODE (PATTERN (insn)) == SET)
return set_live_p (PATTERN (insn), insn, counts);
else if (GET_CODE (PATTERN (insn)) == PARALLEL)
{
@@ -7586,8 +7644,9 @@ insn_live_p (insn, counts)
/* Return true if libcall is dead as a whole. */
static bool
-dead_libcall_p (insn)
+dead_libcall_p (insn, counts)
rtx insn;
+ int *counts;
{
rtx note;
/* See if there's a REG_EQUAL note on this insn and try to
@@ -7604,11 +7663,17 @@ dead_libcall_p (insn)
if (!new)
new = XEXP (note, 0);
+ /* While changing insn, we must update the counts accordingly. */
+ count_reg_usage (insn, counts, NULL_RTX, -1);
+
if (set && validate_change (insn, &SET_SRC (set), new, 0))
{
+ count_reg_usage (insn, counts, NULL_RTX, 1);
remove_note (insn, find_reg_note (insn, REG_RETVAL, NULL_RTX));
+ remove_note (insn, note);
return true;
}
+ count_reg_usage (insn, counts, NULL_RTX, 1);
}
return false;
}
@@ -7621,81 +7686,42 @@ dead_libcall_p (insn)
move dead invariants out of loops or make givs for dead quantities. The
remaining passes of the compilation are also sped up. */
-void
-delete_trivially_dead_insns (insns, nreg, preserve_basic_blocks)
+int
+delete_trivially_dead_insns (insns, nreg)
rtx insns;
int nreg;
- int preserve_basic_blocks;
{
int *counts;
rtx insn, prev;
- int i;
int in_libcall = 0, dead_libcall = 0;
- basic_block bb;
+ int ndead = 0, nlastdead, niterations = 0;
+ timevar_push (TV_DELETE_TRIVIALLY_DEAD);
/* First count the number of times each register is used. */
counts = (int *) xcalloc (nreg, sizeof (int));
for (insn = next_real_insn (insns); insn; insn = next_real_insn (insn))
count_reg_usage (insn, counts, NULL_RTX, 1);
- /* Go from the last insn to the first and delete insns that only set unused
- registers or copy a register to itself. As we delete an insn, remove
- usage counts for registers it uses.
-
- The first jump optimization pass may leave a real insn as the last
- insn in the function. We must not skip that insn or we may end
- up deleting code that is not really dead. */
- insn = get_last_insn ();
- if (! INSN_P (insn))
- insn = prev_real_insn (insn);
-
- if (!preserve_basic_blocks)
- for (; insn; insn = prev)
- {
- int live_insn = 0;
-
- prev = prev_real_insn (insn);
-
- /* Don't delete any insns that are part of a libcall block unless
- we can delete the whole libcall block.
-
- Flow or loop might get confused if we did that. Remember
- that we are scanning backwards. */
- if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
- {
- in_libcall = 1;
- live_insn = 1;
- dead_libcall = dead_libcall_p (insn);
- }
- else if (in_libcall)
- live_insn = ! dead_libcall;
- else
- live_insn = insn_live_p (insn, counts);
-
- /* If this is a dead insn, delete it and show registers in it aren't
- being used. */
-
- if (! live_insn)
- {
- count_reg_usage (insn, counts, NULL_RTX, -1);
- delete_related_insns (insn);
- }
+ do
+ {
+ nlastdead = ndead;
+ niterations++;
+ /* Go from the last insn to the first and delete insns that only set unused
+ registers or copy a register to itself. As we delete an insn, remove
+ usage counts for registers it uses.
+
+ The first jump optimization pass may leave a real insn as the last
+ insn in the function. We must not skip that insn or we may end
+ up deleting code that is not really dead. */
+ insn = get_last_insn ();
+ if (! INSN_P (insn))
+ insn = prev_real_insn (insn);
- if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
- {
- in_libcall = 0;
- dead_libcall = 0;
- }
- }
- else
- for (i = 0; i < n_basic_blocks; i++)
- for (bb = BASIC_BLOCK (i), insn = bb->end; insn != bb->head; insn = prev)
+ for (; insn; insn = prev)
{
int live_insn = 0;
- prev = PREV_INSN (insn);
- if (!INSN_P (insn))
- continue;
+ prev = prev_real_insn (insn);
/* Don't delete any insns that are part of a libcall block unless
we can delete the whole libcall block.
@@ -7706,7 +7732,7 @@ delete_trivially_dead_insns (insns, nreg, preserve_basic_blocks)
{
in_libcall = 1;
live_insn = 1;
- dead_libcall = dead_libcall_p (insn);
+ dead_libcall = dead_libcall_p (insn, counts);
}
else if (in_libcall)
live_insn = ! dead_libcall;
@@ -7719,7 +7745,8 @@ delete_trivially_dead_insns (insns, nreg, preserve_basic_blocks)
if (! live_insn)
{
count_reg_usage (insn, counts, NULL_RTX, -1);
- delete_insn (insn);
+ delete_insn_and_edges (insn);
+ ndead++;
}
if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
@@ -7728,7 +7755,14 @@ delete_trivially_dead_insns (insns, nreg, preserve_basic_blocks)
dead_libcall = 0;
}
}
+ }
+ while (ndead != nlastdead);
+ if (rtl_dump_file && ndead)
+ fprintf (rtl_dump_file, "Deleted %i trivially dead insns; %i iterations\n",
+ ndead, niterations);
/* Clean up. */
free (counts);
+ timevar_pop (TV_DELETE_TRIVIALLY_DEAD);
+ return ndead;
}
diff --git a/contrib/gcc/cselib.c b/contrib/gcc/cselib.c
index b0348fb..e3b228c 100644
--- a/contrib/gcc/cselib.c
+++ b/contrib/gcc/cselib.c
@@ -35,12 +35,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "toplev.h"
#include "output.h"
#include "ggc.h"
-#include "obstack.h"
#include "hashtab.h"
#include "cselib.h"
static int entry_and_rtx_equal_p PARAMS ((const void *, const void *));
-static unsigned int get_value_hash PARAMS ((const void *));
+static hashval_t get_value_hash PARAMS ((const void *));
static struct elt_list *new_elt_list PARAMS ((struct elt_list *,
cselib_val *));
static struct elt_loc_list *new_elt_loc_list PARAMS ((struct elt_loc_list *,
@@ -79,11 +78,12 @@ static void cselib_record_sets PARAMS ((rtx));
the locations of the entries with the rtx we are looking up. */
/* A table that enables us to look up elts by their value. */
-static htab_t hash_table;
+static GTY((param_is (cselib_val))) htab_t hash_table;
/* This is a global so we don't have to pass this through every function.
It is used in new_elt_loc_list to set SETTING_INSN. */
static rtx cselib_current_insn;
+static bool cselib_current_insn_in_libcall;
/* Every new unknown value gets a unique number. */
static unsigned int next_unknown_value;
@@ -101,31 +101,27 @@ static int n_useless_values;
/* This table maps from register number to values. It does not contain
pointers to cselib_val structures, but rather elt_lists. The purpose is
to be able to refer to the same register in different modes. */
-static varray_type reg_values;
+static GTY(()) varray_type reg_values;
+static GTY((deletable (""))) varray_type reg_values_old;
#define REG_VALUES(I) VARRAY_ELT_LIST (reg_values, (I))
/* The largest number of hard regs used by any entry added to the
- REG_VALUES table. Cleared on each clear_table() invocation. */
+ REG_VALUES table. Cleared on each clear_table() invocation. */
static unsigned int max_value_regs;
/* Here the set of indices I with REG_VALUES(I) != 0 is saved. This is used
in clear_table() for fast emptying. */
-static varray_type used_regs;
+static GTY(()) varray_type used_regs;
+static GTY((deletable (""))) varray_type used_regs_old;
/* We pass this to cselib_invalidate_mem to invalidate all of
memory for a non-const call instruction. */
-static rtx callmem;
-
-/* Memory for our structures is allocated from this obstack. */
-static struct obstack cselib_obstack;
-
-/* Used to quickly free all memory. */
-static char *cselib_startobj;
+static GTY(()) rtx callmem;
/* Caches for unused structures. */
-static cselib_val *empty_vals;
-static struct elt_list *empty_elt_lists;
-static struct elt_loc_list *empty_elt_loc_lists;
+static GTY((deletable (""))) cselib_val *empty_vals;
+static GTY((deletable (""))) struct elt_list *empty_elt_lists;
+static GTY((deletable (""))) struct elt_loc_list *empty_elt_loc_lists;
/* Set by discard_useless_locs if it deleted the last location of any
value. */
@@ -145,8 +141,7 @@ new_elt_list (next, elt)
if (el)
empty_elt_lists = el->next;
else
- el = (struct elt_list *) obstack_alloc (&cselib_obstack,
- sizeof (struct elt_list));
+ el = (struct elt_list *) ggc_alloc (sizeof (struct elt_list));
el->next = next;
el->elt = elt;
return el;
@@ -165,11 +160,11 @@ new_elt_loc_list (next, loc)
if (el)
empty_elt_loc_lists = el->next;
else
- el = (struct elt_loc_list *) obstack_alloc (&cselib_obstack,
- sizeof (struct elt_loc_list));
+ el = (struct elt_loc_list *) ggc_alloc (sizeof (struct elt_loc_list));
el->next = next;
el->loc = loc;
el->setting_insn = cselib_current_insn;
+ el->in_libcall = cselib_current_insn_in_libcall;
return el;
}
@@ -236,11 +231,7 @@ clear_table (clear_all)
VARRAY_POP_ALL (used_regs);
htab_empty (hash_table);
- obstack_free (&cselib_obstack, cselib_startobj);
- empty_vals = 0;
- empty_elt_lists = 0;
- empty_elt_loc_lists = 0;
n_useless_values = 0;
next_unknown_value = 0;
@@ -285,7 +276,7 @@ entry_and_rtx_equal_p (entry, x_arg)
hash_rtx when adding an element; this function just extracts the hash
value from a cselib_val structure. */
-static unsigned int
+static hashval_t
get_value_hash (entry)
const void *entry;
{
@@ -592,8 +583,7 @@ hash_rtx (x, mode, create)
the integers representing the constant. */
hash += (unsigned) code + (unsigned) GET_MODE (x);
if (GET_MODE (x) != VOIDmode)
- for (i = 2; i < GET_RTX_LENGTH (CONST_DOUBLE); i++)
- hash += XWINT (x, i);
+ hash += real_hash (CONST_DOUBLE_REAL_VALUE (x));
else
hash += ((unsigned) CONST_DOUBLE_LOW (x)
+ (unsigned) CONST_DOUBLE_HIGH (x));
@@ -704,7 +694,7 @@ new_cselib_val (value, mode)
if (e)
empty_vals = e->u.next_free;
else
- e = (cselib_val *) obstack_alloc (&cselib_obstack, sizeof (cselib_val));
+ e = (cselib_val *) ggc_alloc (sizeof (cselib_val));
if (value == 0)
abort ();
@@ -971,8 +961,11 @@ cselib_invalidate_regno (regno, mode)
pseudos, only REGNO is affected. For hard regs, we must take MODE
into account, and we must also invalidate lower register numbers
if they contain values that overlap REGNO. */
- if (regno < FIRST_PSEUDO_REGISTER && mode != VOIDmode)
+ if (regno < FIRST_PSEUDO_REGISTER)
{
+ if (mode == VOIDmode)
+ abort ();
+
if (regno < max_value_regs)
i = 0;
else
@@ -1320,6 +1313,10 @@ cselib_process_insn (insn)
int i;
rtx x;
+ if (find_reg_note (insn, REG_LIBCALL, NULL))
+ cselib_current_insn_in_libcall = true;
+ if (find_reg_note (insn, REG_RETVAL, NULL))
+ cselib_current_insn_in_libcall = false;
cselib_current_insn = insn;
/* Forget everything at a CODE_LABEL, a volatile asm, or a setjmp. */
@@ -1347,7 +1344,7 @@ cselib_process_insn (insn)
{
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (call_used_regs[i])
- cselib_invalidate_regno (i, VOIDmode);
+ cselib_invalidate_regno (i, reg_raw_mode[i]);
if (! CONST_OR_PURE_CALL_P (insn))
cselib_invalidate_mem (callmem);
@@ -1399,21 +1396,27 @@ cselib_update_varray_sizes ()
void
cselib_init ()
{
- /* These are only created once. */
+ /* This is only created once. */
if (! callmem)
- {
- gcc_obstack_init (&cselib_obstack);
- cselib_startobj = obstack_alloc (&cselib_obstack, 0);
-
- callmem = gen_rtx_MEM (BLKmode, const0_rtx);
- ggc_add_rtx_root (&callmem, 1);
- }
+ callmem = gen_rtx_MEM (BLKmode, const0_rtx);
cselib_nregs = max_reg_num ();
- VARRAY_ELT_LIST_INIT (reg_values, cselib_nregs, "reg_values");
- VARRAY_UINT_INIT (used_regs, cselib_nregs, "used_regs");
- hash_table = htab_create (31, get_value_hash, entry_and_rtx_equal_p, NULL);
+ if (reg_values_old != NULL && VARRAY_SIZE (reg_values_old) >= cselib_nregs)
+ {
+ reg_values = reg_values_old;
+ used_regs = used_regs_old;
+ VARRAY_CLEAR (reg_values);
+ VARRAY_CLEAR (used_regs);
+ }
+ else
+ {
+ VARRAY_ELT_LIST_INIT (reg_values, cselib_nregs, "reg_values");
+ VARRAY_UINT_INIT (used_regs, cselib_nregs, "used_regs");
+ }
+ hash_table = htab_create_ggc (31, get_value_hash, entry_and_rtx_equal_p,
+ NULL);
clear_table (1);
+ cselib_current_insn_in_libcall = false;
}
/* Called when the current user is done with cselib. */
@@ -1421,8 +1424,13 @@ cselib_init ()
void
cselib_finish ()
{
- clear_table (0);
- VARRAY_FREE (reg_values);
- VARRAY_FREE (used_regs);
- htab_delete (hash_table);
+ reg_values_old = reg_values;
+ reg_values = 0;
+ used_regs_old = used_regs;
+ used_regs = 0;
+ hash_table = 0;
+ n_useless_values = 0;
+ next_unknown_value = 0;
}
+
+#include "gt-cselib.h"
diff --git a/contrib/gcc/cselib.h b/contrib/gcc/cselib.h
index 7288598..f29ee8d 100644
--- a/contrib/gcc/cselib.h
+++ b/contrib/gcc/cselib.h
@@ -20,17 +20,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
/* Describe a value. */
-typedef struct cselib_val_struct
+typedef struct cselib_val_struct GTY(())
{
/* The hash value. */
unsigned int value;
- union
+ union cselib_val_u
{
/* A VALUE rtx that points back to this structure. */
- rtx val_rtx;
+ rtx GTY ((tag ("1"))) val_rtx;
/* Used to keep a list of free cselib_val structures. */
- struct cselib_val_struct *next_free;
- } u;
+ struct cselib_val_struct * GTY ((skip (""))) next_free;
+ } GTY ((desc ("1"))) u;
/* All rtl expressions that hold this value at the current time during a
scan. */
@@ -41,7 +41,7 @@ typedef struct cselib_val_struct
} cselib_val;
/* A list of rtl expressions that hold the same value. */
-struct elt_loc_list
+struct elt_loc_list GTY(())
{
/* Next element in the list. */
struct elt_loc_list *next;
@@ -49,10 +49,12 @@ struct elt_loc_list
rtx loc;
/* The insn that made the equivalence. */
rtx setting_insn;
+ /* True when setting insn is inside libcall. */
+ bool in_libcall;
};
/* A list of cselib_val structures. */
-struct elt_list
+struct elt_list GTY(())
{
struct elt_list *next;
cselib_val *elt;
diff --git a/contrib/gcc/dbxout.c b/contrib/gcc/dbxout.c
index bd7f9a7..60ca664 100644
--- a/contrib/gcc/dbxout.c
+++ b/contrib/gcc/dbxout.c
@@ -1,6 +1,6 @@
/* Output dbx-format symbol table information from GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -155,7 +155,7 @@ static int source_label_number = 1;
#endif
#ifdef DEBUG_SYMS_TEXT
-#define FORCE_TEXT text_section ();
+#define FORCE_TEXT function_section (current_function_decl);
#else
#define FORCE_TEXT
#endif
@@ -309,6 +309,7 @@ static void print_int_cst_octal PARAMS ((tree));
static void print_octal PARAMS ((unsigned HOST_WIDE_INT, int));
static void print_wide_int PARAMS ((HOST_WIDE_INT));
static void dbxout_type_name PARAMS ((tree));
+static void dbxout_class_name_qualifiers PARAMS ((tree));
static int dbxout_symbol_location PARAMS ((tree, tree, const char *, rtx));
static void dbxout_symbol_name PARAMS ((tree, const char *, int));
static void dbxout_prepare_symbol PARAMS ((tree));
@@ -327,7 +328,7 @@ static void dbxout_begin_block PARAMS ((unsigned, unsigned));
static void dbxout_end_block PARAMS ((unsigned, unsigned));
static void dbxout_function_decl PARAMS ((tree));
-struct gcc_debug_hooks dbx_debug_hooks =
+const struct gcc_debug_hooks dbx_debug_hooks =
{
dbxout_init,
dbxout_finish,
@@ -340,8 +341,8 @@ struct gcc_debug_hooks dbx_debug_hooks =
debug_true_tree, /* ignore_block */
dbxout_source_line, /* source_line */
dbxout_source_line, /* begin_prologue: just output line info */
- debug_nothing_int, /* end_prologue */
- debug_nothing_void, /* end_epilogue */
+ debug_nothing_int_charstar, /* end_prologue */
+ debug_nothing_int_charstar, /* end_epilogue */
#ifdef DBX_FUNCTION_FIRST
dbxout_begin_function,
#else
@@ -357,7 +358,7 @@ struct gcc_debug_hooks dbx_debug_hooks =
#endif /* DBX_DEBUGGING_INFO */
#if defined (XCOFF_DEBUGGING_INFO)
-struct gcc_debug_hooks xcoff_debug_hooks =
+const struct gcc_debug_hooks xcoff_debug_hooks =
{
dbxout_init,
dbxout_finish,
@@ -370,7 +371,7 @@ struct gcc_debug_hooks xcoff_debug_hooks =
debug_true_tree, /* ignore_block */
xcoffout_source_line,
xcoffout_begin_prologue, /* begin_prologue */
- debug_nothing_int, /* end_prologue */
+ debug_nothing_int_charstar, /* end_prologue */
xcoffout_end_epilogue,
debug_nothing_tree, /* begin_function */
xcoffout_end_function,
@@ -417,7 +418,7 @@ dbxout_init (input_file_name)
const char *input_file_name;
{
char ltext_label_name[100];
- tree syms = getdecls ();
+ tree syms = (*lang_hooks.decls.getdecls) ();
asmfile = asm_out_file;
@@ -674,7 +675,7 @@ dbxout_global_decl (decl)
&& ! DECL_EXTERNAL (decl)
&& DECL_RTL_SET_P (decl)) /* Not necessary? */
dbxout_symbol (decl, 0);
-}
+}
/* At the end of compilation, finish writing the symbol table.
Unless you define DBX_OUTPUT_MAIN_SOURCE_FILE_END, the default is
@@ -1019,7 +1020,7 @@ dbxout_type_methods (type)
}
if (!need_prefix)
{
- putc (';', asmfile);
+ putc (';', asmfile);
CHARS (1);
}
}
@@ -1107,7 +1108,9 @@ dbxout_type (type, full)
static int anonymous_type_number = 0;
if (TREE_CODE (type) == VECTOR_TYPE)
- type = TYPE_DEBUG_REPRESENTATION_TYPE (type);
+ /* The frontend feeds us a representation for the vector as a struct
+ containing an array. Pull out the array type. */
+ type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type)));
/* If there was an input error and we don't really have a type,
avoid crashing and write something that is at least valid
@@ -1279,7 +1282,7 @@ dbxout_type (type, full)
write it as a subtype. */
else if (TREE_TYPE (type) != 0
&& TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
- {
+ {
/* If the size is non-standard, say what it is if we can use
GDB extensions. */
@@ -1292,10 +1295,10 @@ dbxout_type (type, full)
}
dbxout_range_type (type);
- }
+ }
else
- {
+ {
/* If the size is non-standard, say what it is if we can use
GDB extensions. */
@@ -1319,7 +1322,7 @@ dbxout_type (type, full)
larger. This is because we print the bounds as signed decimal,
and hence they can't span same size unsigned types. */
- if (use_gnu_debug_info_extensions
+ if (use_gnu_debug_info_extensions
&& TYPE_MIN_VALUE (type) != 0
&& TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
&& TYPE_MAX_VALUE (type) != 0
@@ -1348,7 +1351,7 @@ dbxout_type (type, full)
else
/* Output other integer types as subranges of `int'. */
dbxout_range_type (type);
- }
+ }
break;
@@ -1861,7 +1864,7 @@ print_wide_int (c)
CHARS (digs);
}
-
+
/* Output the name of type TYPE, with no punctuation.
Such names can be set up either by typedef declarations
or by struct, enum and union tags. */
@@ -1887,6 +1890,33 @@ dbxout_type_name (type)
fprintf (asmfile, "%s", IDENTIFIER_POINTER (t));
CHARS (IDENTIFIER_LENGTH (t));
}
+
+/* Output leading leading struct or class names needed for qualifying
+ type whose scope is limited to a struct or class. */
+
+static void
+dbxout_class_name_qualifiers (decl)
+ tree decl;
+{
+ tree context = decl_type_context (decl);
+
+ if (context != NULL_TREE
+ && TREE_CODE(context) == RECORD_TYPE
+ && TYPE_NAME (context) != 0
+ && (TREE_CODE (TYPE_NAME (context)) == IDENTIFIER_NODE
+ || (DECL_NAME (TYPE_NAME (context)) != 0)))
+ {
+ tree name = TYPE_NAME (context);
+
+ if (TREE_CODE (name) == TYPE_DECL)
+ {
+ dbxout_class_name_qualifiers (name);
+ name = DECL_NAME (name);
+ }
+ fprintf (asmfile, "%s::", IDENTIFIER_POINTER (name));
+ CHARS (IDENTIFIER_LENGTH (name) + 2);
+ }
+}
/* Output a .stabs for the symbol defined by DECL,
which must be a ..._DECL node in the normal namespace.
@@ -2007,7 +2037,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. */
- && DECL_ARTIFICIAL (decl)
+ && DECL_ARTIFICIAL (decl)
/* Do not generate a tag for records of variable size,
since this type can not be properly described in the
DBX format, and it confuses some tools such as objdump. */
@@ -2028,9 +2058,17 @@ dbxout_symbol (decl, local)
dbxout_finish_symbol (NULL_TREE);
}
+ /* Output .stabs (or whatever) and leading double quote. */
+ fprintf (asmfile, "%s\"", ASM_STABS_OP);
+
+ if (use_gnu_debug_info_extensions)
+ {
+ /* Output leading class/struct qualifiers. */
+ dbxout_class_name_qualifiers (decl);
+ }
+
/* Output typedef name. */
- fprintf (asmfile, "%s\"%s:", ASM_STABS_OP,
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (decl)));
/* Short cut way to output a tag also. */
if ((TREE_CODE (type) == RECORD_TYPE
@@ -2039,7 +2077,7 @@ dbxout_symbol (decl, local)
&& TYPE_NAME (type) == decl
/* Distinguish the implicit typedefs of C++
from explicit ones that might be found in C. */
- && DECL_ARTIFICIAL (decl))
+ && DECL_ARTIFICIAL (decl))
{
if (use_gnu_debug_info_extensions && have_used_extensions)
{
@@ -2172,7 +2210,7 @@ dbxout_symbol (decl, local)
result = dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
break;
-
+
default:
break;
}
@@ -2196,7 +2234,7 @@ dbxout_symbol_location (decl, type, suffix, home)
/* Don't mention a variable at all
if it was completely optimized into nothingness.
-
+
If the decl was from an inline function, then its rtl
is not identically the rtl that was used in this
particular compilation. */
@@ -2275,7 +2313,7 @@ dbxout_symbol_location (decl, type, suffix, home)
|| GET_CODE (tmp) == LABEL_REF)
current_sym_addr = tmp;
}
-
+
/* Ultrix `as' seems to need this. */
#ifdef DBX_STATIC_STAB_DATA_SECTION
data_section ();
@@ -2480,7 +2518,7 @@ dbxout_finish_symbol (sym)
#endif
}
-/* Output definitions of all the decls in a chain. Return non-zero if
+/* Output definitions of all the decls in a chain. Return nonzero if
anything was output */
int
@@ -2564,7 +2602,7 @@ dbxout_parms (parms)
}
/* It is quite tempting to use:
-
+
dbxout_type (TREE_TYPE (parms), 0);
as the next statement, rather than using DECL_ARG_TYPE(), so
@@ -2577,7 +2615,7 @@ dbxout_parms (parms)
double on the stack, but if we emit a stab saying the type is a
float, then gdb will only read in a single value, and this will
produce an erroneous value. */
- dbxout_type (DECL_ARG_TYPE (parms), 0);
+ dbxout_type (DECL_ARG_TYPE (parms), 0);
current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr);
dbxout_finish_symbol (parms);
}
@@ -2695,13 +2733,14 @@ dbxout_parms (parms)
const char *const decl_name = (DECL_NAME (parms)
? IDENTIFIER_POINTER (DECL_NAME (parms))
: "(anon)");
- if (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 0)) == REG)
- current_sym_value = 0;
+ if (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 0)) == REG)
+ current_sym_value = 0;
else
current_sym_value
= INTVAL (XEXP (XEXP (XEXP (DECL_RTL (parms), 0), 0), 1));
current_sym_addr = 0;
-
+ current_sym_code = N_PSYM;
+
FORCE_TEXT;
fprintf (asmfile, "%s\"%s:v", ASM_STABS_OP, decl_name);
@@ -2739,7 +2778,7 @@ dbxout_parms (parms)
&& TYPE_MODE (TREE_TYPE (parms)) != GET_MODE (DECL_RTL (parms))
&& GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))) < UNITS_PER_WORD)
{
- current_sym_value +=
+ current_sym_value +=
GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))
- GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms)));
}
@@ -2849,7 +2888,7 @@ dbxout_block (block, depth, args)
int blocknum = -1;
#if DBX_BLOCKS_FUNCTION_RELATIVE
- const char *begin_label;
+ const char *begin_label;
if (current_function_func_begin_label != NULL_TREE)
begin_label = IDENTIFIER_POINTER (current_function_func_begin_label);
else
diff --git a/contrib/gcc/debug.c b/contrib/gcc/debug.c
index 75d13ba..682f6ed 100644
--- a/contrib/gcc/debug.c
+++ b/contrib/gcc/debug.c
@@ -20,7 +20,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "debug.h"
/* The do-nothing debug hooks. */
-struct gcc_debug_hooks do_nothing_debug_hooks =
+const struct gcc_debug_hooks do_nothing_debug_hooks =
{
debug_nothing_charstar,
debug_nothing_charstar,
@@ -33,8 +33,8 @@ struct gcc_debug_hooks do_nothing_debug_hooks =
debug_true_tree, /* ignore_block */
debug_nothing_int_charstar, /* source_line */
debug_nothing_int_charstar, /* begin_prologue */
- debug_nothing_int, /* end_prologue */
- debug_nothing_void, /* end_epilogue */
+ debug_nothing_int_charstar, /* end_prologue */
+ debug_nothing_int_charstar, /* end_epilogue */
debug_nothing_tree, /* begin_function */
debug_nothing_int, /* end_function */
debug_nothing_tree, /* function_decl */
diff --git a/contrib/gcc/debug.h b/contrib/gcc/debug.h
index 1f4349d..11c996f 100644
--- a/contrib/gcc/debug.h
+++ b/contrib/gcc/debug.h
@@ -23,7 +23,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
toplev.c according to command line options. */
struct gcc_debug_hooks
{
- /* Initialise debug output. MAIN_FILENAME is the name of the main
+ /* Initialize debug output. MAIN_FILENAME is the name of the main
input file. */
void (* init) PARAMS ((const char *main_filename));
@@ -68,10 +68,10 @@ struct gcc_debug_hooks
/* Called at end of prologue code. LINE is the first line in the
function. */
- void (* end_prologue) PARAMS ((unsigned int line));
+ void (* end_prologue) PARAMS ((unsigned int line, const char *file));
/* Record end of epilogue code. */
- void (* end_epilogue) PARAMS ((void));
+ void (* end_epilogue) PARAMS ((unsigned int line, const char *file));
/* Called at start of function DECL, before it is declared. */
void (* begin_function) PARAMS ((tree decl));
@@ -103,7 +103,7 @@ struct gcc_debug_hooks
void (* label) PARAMS ((rtx));
};
-extern struct gcc_debug_hooks *debug_hooks;
+extern const struct gcc_debug_hooks *debug_hooks;
/* The do-nothing hooks. */
extern void debug_nothing_void
@@ -124,28 +124,22 @@ extern void debug_nothing_rtx
PARAMS ((rtx));
/* Hooks for various debug formats. */
-extern struct gcc_debug_hooks do_nothing_debug_hooks;
-extern struct gcc_debug_hooks dbx_debug_hooks;
-extern struct gcc_debug_hooks sdb_debug_hooks;
-extern struct gcc_debug_hooks xcoff_debug_hooks;
-extern struct gcc_debug_hooks dwarf_debug_hooks;
-extern struct gcc_debug_hooks dwarf2_debug_hooks;
-extern struct gcc_debug_hooks vmsdbg_debug_hooks;
+extern const struct gcc_debug_hooks do_nothing_debug_hooks;
+extern const struct gcc_debug_hooks dbx_debug_hooks;
+extern const struct gcc_debug_hooks sdb_debug_hooks;
+extern const struct gcc_debug_hooks xcoff_debug_hooks;
+extern const struct gcc_debug_hooks dwarf_debug_hooks;
+extern const struct gcc_debug_hooks dwarf2_debug_hooks;
+extern const struct gcc_debug_hooks vmsdbg_debug_hooks;
/* Dwarf2 frame information. */
extern void dwarf2out_begin_prologue PARAMS ((unsigned int, const char *));
-extern void dwarf2out_end_epilogue PARAMS ((void));
+extern void dwarf2out_end_epilogue PARAMS ((unsigned int, const char *));
extern void dwarf2out_frame_init PARAMS ((void));
extern void dwarf2out_frame_finish PARAMS ((void));
/* Decide whether we want to emit frame unwind information for the current
translation unit. */
extern int dwarf2out_do_frame PARAMS ((void));
-/* When writing VMS debug info, output label after the prologue of the
- function. */
-extern void vmsdbgout_after_prologue PARAMS ((void));
-
-
-
#endif /* !GCC_DEBUG_H */
diff --git a/contrib/gcc/defaults.h b/contrib/gcc/defaults.h
index c6f8a43..0c71996 100644
--- a/contrib/gcc/defaults.h
+++ b/contrib/gcc/defaults.h
@@ -23,6 +23,13 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#ifndef GCC_DEFAULTS_H
#define GCC_DEFAULTS_H
+#ifndef GET_ENVIRONMENT
+#define GET_ENVIRONMENT(VALUE, NAME) do { (VALUE) = getenv (NAME); } while (0)
+#endif
+
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+
/* Define default standard character escape sequences. */
#ifndef TARGET_BELL
# define TARGET_BELL 007
@@ -35,6 +42,18 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
# define TARGET_ESC 033
#endif
+/* When removal of CPP_PREDEFINES is complete, TARGET_CPU_CPP_BULITINS
+ can also be removed from here. */
+#ifndef TARGET_OS_CPP_BUILTINS
+# define TARGET_OS_CPP_BUILTINS()
+#endif
+#ifndef TARGET_CPU_CPP_BUILTINS
+# define TARGET_CPU_CPP_BUILTINS()
+#endif
+#ifndef CPP_PREDEFINES
+# define CPP_PREDEFINES ""
+#endif
+
/* Store in OUTPUT a string (made with alloca) containing
an assembler-name for a local static variable or function named NAME.
LABELNO is an integer which is different for each call. */
@@ -68,12 +87,6 @@ do { fputs (integer_asm_op (POINTER_SIZE / UNITS_PER_WORD, TRUE), FILE); \
} while (0)
#endif
-/* Provide default for ASM_OUTPUT_ALTERNATE_LABEL_NAME. */
-#ifndef ASM_OUTPUT_ALTERNATE_LABEL_NAME
-#define ASM_OUTPUT_ALTERNATE_LABEL_NAME(FILE,INSN) \
-do { ASM_OUTPUT_LABEL(FILE,LABEL_ALTERNATE_NAME (INSN)); } while (0)
-#endif
-
/* choose a reasonable default for ASM_OUTPUT_ASCII. */
#ifndef ASM_OUTPUT_ASCII
@@ -127,6 +140,14 @@ do { ASM_OUTPUT_LABEL(FILE,LABEL_ALTERNATE_NAME (INSN)); } while (0)
#endif
#endif
+/* 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. */
+
+#ifndef ASM_OUTPUT_LABEL
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { assemble_name ((FILE), (NAME)); fputs (":\n", (FILE)); } while (0)
+#endif
+
/* This is how to output a reference to a user-level label named NAME. */
#ifndef ASM_OUTPUT_LABELREF
@@ -156,6 +177,51 @@ do { ASM_OUTPUT_LABEL(FILE,LABEL_ALTERNATE_NAME (INSN)); } while (0)
#endif
#endif
+/* How to emit a .type directive. */
+#ifndef ASM_OUTPUT_TYPE_DIRECTIVE
+#if defined TYPE_ASM_OP && defined TYPE_OPERAND_FMT
+#define ASM_OUTPUT_TYPE_DIRECTIVE(STREAM, NAME, TYPE) \
+ do \
+ { \
+ fputs (TYPE_ASM_OP, STREAM); \
+ assemble_name (STREAM, NAME); \
+ fputs (", ", STREAM); \
+ fprintf (STREAM, TYPE_OPERAND_FMT, TYPE); \
+ putc ('\n', STREAM); \
+ } \
+ while (0)
+#endif
+#endif
+
+/* How to emit a .size directive. */
+#ifndef ASM_OUTPUT_SIZE_DIRECTIVE
+#ifdef SIZE_ASM_OP
+#define ASM_OUTPUT_SIZE_DIRECTIVE(STREAM, NAME, SIZE) \
+ do \
+ { \
+ HOST_WIDE_INT size_ = (SIZE); \
+ fputs (SIZE_ASM_OP, STREAM); \
+ assemble_name (STREAM, NAME); \
+ fputs (", ", STREAM); \
+ fprintf (STREAM, HOST_WIDE_INT_PRINT_DEC, size_); \
+ putc ('\n', STREAM); \
+ } \
+ while (0)
+
+#define ASM_OUTPUT_MEASURED_SIZE(STREAM, NAME) \
+ do \
+ { \
+ fputs (SIZE_ASM_OP, STREAM); \
+ assemble_name (STREAM, NAME); \
+ fputs (", .-", STREAM); \
+ assemble_name (STREAM, NAME); \
+ putc ('\n', STREAM); \
+ } \
+ while (0)
+
+#endif
+#endif
+
/* This determines whether or not we support weak symbols. */
#ifndef SUPPORTS_WEAK
#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
@@ -174,6 +240,11 @@ do { ASM_OUTPUT_LABEL(FILE,LABEL_ALTERNATE_NAME (INSN)); } while (0)
#endif
#endif
+/* By default, there is no prefix on user-defined symbols. */
+#ifndef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+#endif
+
/* If the target supports weak symbols, define TARGET_ATTRIBUTE_WEAK to
provide a weak attribute. Else define it to nothing.
@@ -211,7 +282,8 @@ do { ASM_OUTPUT_LABEL(FILE,LABEL_ALTERNATE_NAME (INSN)); } while (0)
/* If we have named sections, and we're using crtstuff to run ctors,
use them for registering eh frame information. */
-#if defined (TARGET_ASM_NAMED_SECTION) && !defined(EH_FRAME_IN_DATA_SECTION)
+#if defined (TARGET_ASM_NAMED_SECTION) && DWARF2_UNWIND_INFO \
+ && !defined(EH_FRAME_IN_DATA_SECTION)
#ifndef EH_FRAME_SECTION_NAME
#define EH_FRAME_SECTION_NAME ".eh_frame"
#endif
@@ -226,28 +298,6 @@ do { ASM_OUTPUT_LABEL(FILE,LABEL_ALTERNATE_NAME (INSN)); } while (0)
#endif
#endif
-/* If we have no definition for UNIQUE_SECTION, but do have the
- ability to generate arbitrary sections, construct something
- reasonable. */
-#ifndef UNIQUE_SECTION
-#define UNIQUE_SECTION(DECL,RELOC) \
-do { \
- int len; \
- const char *name; \
- char *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
-
/* By default, we generate a label at the beginning and end of the
text section, and compute the size of the text section by
subtracting the two. However, on some platforms that doesn't
@@ -281,6 +331,14 @@ do { \
your target, you should override these values by defining the
appropriate symbols in your tm.h file. */
+#ifndef BITS_PER_UNIT
+#define BITS_PER_UNIT 8
+#endif
+
+#ifndef BITS_PER_WORD
+#define BITS_PER_WORD (BITS_PER_UNIT * UNITS_PER_WORD)
+#endif
+
#ifndef CHAR_TYPE_SIZE
#define CHAR_TYPE_SIZE BITS_PER_UNIT
#endif
@@ -310,10 +368,6 @@ do { \
#define WCHAR_TYPE_SIZE INT_TYPE_SIZE
#endif
-#ifndef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
-#endif
-
#ifndef FLOAT_TYPE_SIZE
#define FLOAT_TYPE_SIZE BITS_PER_WORD
#endif
@@ -326,6 +380,11 @@ do { \
#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
#endif
+/* Width in bits of a pointer. Mind the value of the macro `Pmode'. */
+#ifndef POINTER_SIZE
+#define POINTER_SIZE BITS_PER_WORD
+#endif
+
#ifndef BUILD_VA_LIST_TYPE
#define BUILD_VA_LIST_TYPE(X) ((X) = ptr_type_node)
#endif
@@ -371,7 +430,7 @@ do { \
#endif
/* By default, the C++ compiler will use function addresses in the
- vtable entries. Setting this non-zero tells the compiler to use
+ vtable entries. Setting this nonzero tells the compiler to use
function descriptors instead. The value of this macro says how
many words wide the descriptor is (normally 2). It is assumed
that the address of a function descriptor may be treated as a
@@ -380,6 +439,22 @@ do { \
#define TARGET_VTABLE_USES_DESCRIPTORS 0
#endif
+/* By default, the vtable entries are void pointers, the so the alignment
+ is the same as pointer alignment. The value of this macro specifies
+ the alignment of the vtable entry in bits. It should be defined only
+ when special alignment is necessary. */
+#ifndef TARGET_VTABLE_ENTRY_ALIGN
+#define TARGET_VTABLE_ENTRY_ALIGN POINTER_SIZE
+#endif
+
+/* There are a few non-descriptor entries in the vtable at offsets below
+ zero. If these entries must be padded (say, to preserve the alignment
+ specified by TARGET_VTABLE_ENTRY_ALIGN), set this to the number of
+ words in each data entry. */
+#ifndef TARGET_VTABLE_DATA_ENTRY_DISTANCE
+#define TARGET_VTABLE_DATA_ENTRY_DISTANCE 1
+#endif
+
/* Select a format to encode pointers in exception handling data. We
prefer those that result in fewer dynamic relocations. Assume no
special support here and encode direct references. */
@@ -398,13 +473,6 @@ do { \
? ptrmemfunc_vbit_in_pfn : ptrmemfunc_vbit_in_delta)
#endif
-/* True if it is possible to profile code that does not have a frame
- pointer. */
-
-#ifndef TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
-#define TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER true
-#endif
-
#ifndef DEFAULT_GDB_EXTENSIONS
#define DEFAULT_GDB_EXTENSIONS 1
#endif
@@ -445,14 +513,16 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
#define PREFERRED_DEBUGGING_TYPE NO_DEBUG
#endif
-/* This is set to 1 if BYTES_BIG_ENDIAN is defined but the target uses a
- little-endian method of passing and returning structures in registers.
- On the HP-UX IA64 and PA64 platforms structures are aligned differently
- then integral values and setting this value to 1 will allow for the
- special handling of structure arguments and return values in regs. */
+/* Define codes for all the float formats that we know of. */
+#define UNKNOWN_FLOAT_FORMAT 0
+#define IEEE_FLOAT_FORMAT 1
+#define VAX_FLOAT_FORMAT 2
+#define IBM_FLOAT_FORMAT 3
+#define C4X_FLOAT_FORMAT 4
-#ifndef FUNCTION_ARG_REG_LITTLE_ENDIAN
-#define FUNCTION_ARG_REG_LITTLE_ENDIAN 0
+/* Default to IEEE float if not specified. Nearly all machines use it. */
+#ifndef TARGET_FLOAT_FORMAT
+#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
#endif
/* Determine the register class for registers suitable to be the base
@@ -462,10 +532,79 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
#define MODE_BASE_REG_CLASS(MODE) BASE_REG_CLASS
#endif
+#ifndef LARGEST_EXPONENT_IS_NORMAL
+#define LARGEST_EXPONENT_IS_NORMAL(SIZE) 0
+#endif
+
+#ifndef ROUND_TOWARDS_ZERO
+#define ROUND_TOWARDS_ZERO 0
+#endif
+
+#ifndef MODE_HAS_NANS
+#define MODE_HAS_NANS(MODE) \
+ (FLOAT_MODE_P (MODE) \
+ && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT \
+ && !LARGEST_EXPONENT_IS_NORMAL (GET_MODE_BITSIZE (MODE)))
+#endif
+
+#ifndef MODE_HAS_INFINITIES
+#define MODE_HAS_INFINITIES(MODE) \
+ (FLOAT_MODE_P (MODE) \
+ && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT \
+ && !LARGEST_EXPONENT_IS_NORMAL (GET_MODE_BITSIZE (MODE)))
+#endif
+
+#ifndef MODE_HAS_SIGNED_ZEROS
+#define MODE_HAS_SIGNED_ZEROS(MODE) \
+ (FLOAT_MODE_P (MODE) && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+#endif
+
+#ifndef MODE_HAS_SIGN_DEPENDENT_ROUNDING
+#define MODE_HAS_SIGN_DEPENDENT_ROUNDING(MODE) \
+ (FLOAT_MODE_P (MODE) \
+ && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT \
+ && !ROUND_TOWARDS_ZERO)
+#endif
+
+/* If FLOAT_WORDS_BIG_ENDIAN and HOST_FLOAT_WORDS_BIG_ENDIAN are not defined
+ in the header files, then this implies the word-endianness is the same as
+ for integers. */
+#ifndef FLOAT_WORDS_BIG_ENDIAN
+#define FLOAT_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
+#endif
+
+#ifndef TARGET_FLT_EVAL_METHOD
+#define TARGET_FLT_EVAL_METHOD 0
+#endif
+
+#ifndef HOT_TEXT_SECTION_NAME
+#define HOT_TEXT_SECTION_NAME "text.hot"
+#endif
+
+#ifndef UNLIKELY_EXECUTED_TEXT_SECTION_NAME
+#define UNLIKELY_EXECUTED_TEXT_SECTION_NAME "text.unlikely"
+#endif
+
+#ifndef VECTOR_MODE_SUPPORTED_P
+#define VECTOR_MODE_SUPPORTED_P(MODE) 0
+#endif
+
/* Determine whether __cxa_atexit, rather than atexit, is used to
- register C++ destructors for local statics and global objects. */
+ register C++ destructors for local statics and global objects. */
#ifndef DEFAULT_USE_CXA_ATEXIT
#define DEFAULT_USE_CXA_ATEXIT 0
#endif
+/* Determine whether extra constraint letter should be handled
+ via address reload (like 'o'). */
+#ifndef EXTRA_MEMORY_CONSTRAINT
+#define EXTRA_MEMORY_CONSTRAINT(C) 0
+#endif
+
+/* Determine whether extra constraint letter should be handled
+ as an address (like 'p'). */
+#ifndef EXTRA_ADDRESS_CONSTRAINT
+#define EXTRA_ADDRESS_CONSTRAINT(C) 0
+#endif
+
#endif /* ! GCC_DEFAULTS_H */
diff --git a/contrib/gcc/demangle.h b/contrib/gcc/demangle.h
index ad0569a..bff2669 100644
--- a/contrib/gcc/demangle.h
+++ b/contrib/gcc/demangle.h
@@ -1,5 +1,5 @@
/* Defs for interface to demanglers.
- Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001
+ Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -21,7 +21,11 @@
#if !defined (DEMANGLE_H)
#define DEMANGLE_H
-#include <ansidecl.h>
+#include "ansidecl.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
/* Options passed to cplus_demangle (in 2nd parameter). */
@@ -160,4 +164,8 @@ enum gnu_v3_dtor_kinds {
extern enum gnu_v3_dtor_kinds
is_gnu_v3_mangled_dtor PARAMS ((const char *name));
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
#endif /* DEMANGLE_H */
diff --git a/contrib/gcc/df.c b/contrib/gcc/df.c
index ed0fd77..fb434ff 100644
--- a/contrib/gcc/df.c
+++ b/contrib/gcc/df.c
@@ -153,8 +153,6 @@ when optimising a loop, only certain registers are of interest.
Perhaps there should be a bitmap argument to df_analyse to specify
which registers should be analysed? */
-#define HANDLE_SUBREG
-
#include "config.h"
#include "system.h"
#include "rtl.h"
@@ -171,32 +169,14 @@ Perhaps there should be a bitmap argument to df_analyse to specify
#include "df.h"
#include "fibheap.h"
-#define FOR_ALL_BBS(BB, CODE) \
-do { \
- int node_; \
- for (node_ = 0; node_ < n_basic_blocks; node_++) \
- {(BB) = BASIC_BLOCK (node_); CODE;};} while (0)
-
-#define FOR_EACH_BB_IN_BITMAP(BITMAP, MIN, BB, CODE) \
-do { \
- unsigned int node_; \
- EXECUTE_IF_SET_IN_BITMAP (BITMAP, MIN, node_, \
- {(BB) = BASIC_BLOCK (node_); CODE;});} while (0)
-
-#define FOR_EACH_BB_IN_BITMAP_REV(BITMAP, MIN, BB, CODE) \
-do { \
- unsigned int node_; \
- EXECUTE_IF_SET_IN_BITMAP_REV (BITMAP, node_, \
- {(BB) = BASIC_BLOCK (node_); CODE;});} while (0)
-
-#define FOR_EACH_BB_IN_SBITMAP(BITMAP, MIN, BB, CODE) \
-do { \
- unsigned int node_; \
- EXECUTE_IF_SET_IN_SBITMAP (BITMAP, MIN, node_, \
- {(BB) = BASIC_BLOCK (node_); CODE;});} while (0)
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
+#define FOR_EACH_BB_IN_BITMAP(BITMAP, MIN, BB, CODE) \
+ do \
+ { \
+ unsigned int node_; \
+ EXECUTE_IF_SET_IN_BITMAP (BITMAP, MIN, node_, \
+ {(BB) = BASIC_BLOCK (node_); CODE;}); \
+ } \
+ while (0)
static struct obstack df_ref_obstack;
static struct df *ddf;
@@ -205,7 +185,7 @@ static void df_reg_table_realloc PARAMS((struct df *, int));
#if 0
static void df_def_table_realloc PARAMS((struct df *, int));
#endif
-static void df_insn_table_realloc PARAMS((struct df *, int));
+static void df_insn_table_realloc PARAMS((struct df *, unsigned int));
static void df_bitmaps_alloc PARAMS((struct df *, int));
static void df_bitmaps_free PARAMS((struct df *, int));
static void df_free PARAMS((struct df *));
@@ -295,16 +275,16 @@ static void df_chain_dump PARAMS((struct df_link *, FILE *file));
static void df_chain_dump_regno PARAMS((struct df_link *, FILE *file));
static void df_regno_debug PARAMS ((struct df *, unsigned int, FILE *));
static void df_ref_debug PARAMS ((struct df *, struct ref *, FILE *));
-static void df_rd_transfer_function PARAMS ((int, int *, bitmap, bitmap,
+static void df_rd_transfer_function PARAMS ((int, int *, bitmap, bitmap,
bitmap, bitmap, void *));
-static void df_ru_transfer_function PARAMS ((int, int *, bitmap, bitmap,
+static void df_ru_transfer_function PARAMS ((int, int *, bitmap, bitmap,
bitmap, bitmap, void *));
-static void df_lr_transfer_function PARAMS ((int, int *, bitmap, bitmap,
+static void df_lr_transfer_function PARAMS ((int, int *, bitmap, bitmap,
bitmap, bitmap, void *));
-static void hybrid_search_bitmap PARAMS ((basic_block, bitmap *, bitmap *,
- bitmap *, bitmap *, enum df_flow_dir,
- enum df_confluence_op,
- transfer_function_bitmap,
+static void hybrid_search_bitmap PARAMS ((basic_block, bitmap *, bitmap *,
+ bitmap *, bitmap *, enum df_flow_dir,
+ enum df_confluence_op,
+ transfer_function_bitmap,
sbitmap, sbitmap, void *));
static void hybrid_search_sbitmap PARAMS ((basic_block, sbitmap *, sbitmap *,
sbitmap *, sbitmap *, enum df_flow_dir,
@@ -317,17 +297,20 @@ static inline bool read_modify_subreg_p PARAMS ((rtx));
/* Local memory allocation/deallocation routines. */
-/* Increase the insn info table by SIZE more elements. */
+/* Increase the insn info table to have space for at least SIZE + 1
+ elements. */
static void
df_insn_table_realloc (df, size)
struct df *df;
- int size;
+ unsigned int size;
{
- /* Make table 25 percent larger by default. */
- if (! size)
- size = df->insn_size / 4;
+ size++;
+ if (size <= df->insn_size)
+ return;
- size += df->insn_size;
+ /* Make the table a little larger than requested, so we don't need
+ to enlarge it so often. */
+ size += df->insn_size / 4;
df->insns = (struct insn_info *)
xrealloc (df->insns, size * sizeof (struct insn_info));
@@ -356,6 +339,8 @@ df_reg_table_realloc (df, size)
size = df->reg_size / 4;
size += df->reg_size;
+ if (size < max_reg_num ())
+ size = max_reg_num ();
df->regs = (struct reg_info *)
xrealloc (df->regs, size * sizeof (struct reg_info));
@@ -393,7 +378,7 @@ df_def_table_realloc (df, size)
/* Link all the new refs together, overloading the chain field. */
for (i = 0; i < size - 1; i++)
- refs[i].chain = (struct df_link *)(refs + i + 1);
+ refs[i].chain = (struct df_link *) (refs + i + 1);
refs[size - 1].chain = 0;
}
#endif
@@ -406,11 +391,11 @@ df_bitmaps_alloc (df, flags)
struct df *df;
int flags;
{
- unsigned int i;
int dflags = 0;
+ basic_block bb;
/* Free the bitmaps if they need resizing. */
- if ((flags & DF_LR) && df->n_regs < (unsigned int)max_reg_num ())
+ if ((flags & DF_LR) && df->n_regs < (unsigned int) max_reg_num ())
dflags |= DF_LR | DF_RU;
if ((flags & DF_RU) && df->n_uses < df->use_id)
dflags |= DF_RU;
@@ -423,9 +408,8 @@ df_bitmaps_alloc (df, flags)
df->n_defs = df->def_id;
df->n_uses = df->use_id;
- for (i = 0; i < df->n_bbs; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
struct bb_info *bb_info = DF_BB_INFO (df, bb);
if (flags & DF_RD && ! bb_info->rd_in)
@@ -474,11 +458,10 @@ df_bitmaps_free (df, flags)
struct df *df ATTRIBUTE_UNUSED;
int flags;
{
- unsigned int i;
+ basic_block bb;
- for (i = 0; i < df->n_bbs; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
struct bb_info *bb_info = DF_BB_INFO (df, bb);
if (!bb_info)
@@ -527,14 +510,14 @@ df_bitmaps_free (df, flags)
}
-/* Allocate and initialise dataflow memory. */
+/* Allocate and initialize dataflow memory. */
static void
df_alloc (df, n_regs)
struct df *df;
int n_regs;
{
int n_insns;
- int i;
+ basic_block bb;
gcc_obstack_init (&df_ref_obstack);
@@ -555,7 +538,7 @@ df_alloc (df, n_regs)
df->uses = xmalloc (df->use_size * sizeof (*df->uses));
df->n_regs = n_regs;
- df->n_bbs = n_basic_blocks;
+ df->n_bbs = last_basic_block;
/* Allocate temporary working array used during local dataflow analysis. */
df->reg_def_last = xmalloc (df->n_regs * sizeof (struct ref *));
@@ -569,11 +552,11 @@ df_alloc (df, n_regs)
df->flags = 0;
- df->bbs = xcalloc (df->n_bbs, sizeof (struct bb_info));
+ df->bbs = xcalloc (last_basic_block, sizeof (struct bb_info));
df->all_blocks = BITMAP_XMALLOC ();
- for (i = 0; i < n_basic_blocks; i++)
- bitmap_set_bit (df->all_blocks, i);
+ FOR_EACH_BB (bb)
+ bitmap_set_bit (df->all_blocks, bb->index);
}
@@ -633,8 +616,7 @@ static rtx df_reg_use_gen (regno)
rtx reg;
rtx use;
- reg = regno >= FIRST_PSEUDO_REGISTER
- ? regno_reg_rtx[regno] : gen_rtx_REG (reg_raw_mode[regno], regno);
+ reg = regno_reg_rtx[regno];
use = gen_rtx_USE (GET_MODE (reg), reg);
return use;
@@ -648,8 +630,7 @@ static rtx df_reg_clobber_gen (regno)
rtx reg;
rtx use;
- reg = regno >= FIRST_PSEUDO_REGISTER
- ? regno_reg_rtx[regno] : gen_rtx_REG (reg_raw_mode[regno], regno);
+ reg = regno_reg_rtx[regno];
use = gen_rtx_CLOBBER (GET_MODE (reg), reg);
return use;
@@ -881,7 +862,7 @@ df_ref_record (df, reg, loc, insn, ref_type, ref_flags)
XXX Is that true? We could also use the global word_mode variable. */
if (GET_CODE (reg) == SUBREG
&& (GET_MODE_SIZE (GET_MODE (reg)) < GET_MODE_SIZE (word_mode)
- || GET_MODE_SIZE (GET_MODE (reg))
+ || GET_MODE_SIZE (GET_MODE (reg))
>= GET_MODE_SIZE (GET_MODE (SUBREG_REG (reg)))))
{
loc = &SUBREG_REG (reg);
@@ -902,10 +883,14 @@ df_ref_record (df, reg, loc, insn, ref_type, ref_flags)
are really referenced. E.g. a (subreg:SI (reg:DI 0) 0) does _not_
reference the whole reg 0 in DI mode (which would also include
reg 1, at least, if 0 and 1 are SImode registers). */
- endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ endregno = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ if (GET_CODE (reg) == SUBREG)
+ regno += subreg_regno_offset (regno, GET_MODE (SUBREG_REG (reg)),
+ SUBREG_BYTE (reg), GET_MODE (reg));
+ endregno += regno;
for (i = regno; i < endregno; i++)
- df_ref_record_1 (df, gen_rtx_REG (reg_raw_mode[i], i),
+ df_ref_record_1 (df, regno_reg_rtx[i],
loc, insn, ref_type, ref_flags);
}
else
@@ -914,18 +899,23 @@ df_ref_record (df, reg, loc, insn, ref_type, ref_flags)
}
}
-/* Writes to SUBREG of inndermode wider than word and outermode shorter than
- word are read-modify-write. */
+/* Writes to paradoxical subregs, or subregs which are too narrow
+ are read-modify-write. */
static inline bool
read_modify_subreg_p (x)
rtx x;
{
+ unsigned int isize, osize;
if (GET_CODE (x) != SUBREG)
return false;
- if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) <= UNITS_PER_WORD)
+ isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
+ osize = GET_MODE_SIZE (GET_MODE (x));
+ if (isize <= osize)
+ return true;
+ if (isize <= UNITS_PER_WORD)
return false;
- if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
+ if (osize >= UNITS_PER_WORD)
return false;
return true;
}
@@ -949,14 +939,21 @@ df_def_record_1 (df, x, bb, insn)
int i;
for (i = XVECLEN (dst, 0) - 1; i >= 0; i--)
- df_def_record_1 (df, XVECEXP (dst, 0, i), bb, insn);
+ df_def_record_1 (df, XVECEXP (dst, 0, i), bb, insn);
return;
}
+#ifdef CLASS_CANNOT_CHANGE_MODE
+ if (GET_CODE (dst) == SUBREG
+ && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (dst)),
+ GET_MODE (dst)))
+ flags |= DF_REF_MODE_CHANGE;
+#endif
+
/* May be, we should flag the use of strict_low_part somehow. Might be
handy for the reg allocator. */
while (GET_CODE (dst) == STRICT_LOW_PART
- || GET_CODE (dst) == ZERO_EXTRACT
+ || GET_CODE (dst) == ZERO_EXTRACT
|| GET_CODE (dst) == SIGN_EXTRACT
|| read_modify_subreg_p (dst))
{
@@ -967,14 +964,20 @@ df_def_record_1 (df, x, bb, insn)
loc = &XEXP (dst, 0);
dst = *loc;
}
+#ifdef CLASS_CANNOT_CHANGE_MODE
+ if (GET_CODE (dst) == SUBREG
+ && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (dst)),
+ GET_MODE (dst)))
+ flags |= DF_REF_MODE_CHANGE;
+#endif
loc = &XEXP (dst, 0);
dst = *loc;
flags |= DF_REF_READ_WRITE;
}
-
- if (GET_CODE (dst) == REG
- || (GET_CODE (dst) == SUBREG && GET_CODE (SUBREG_REG (dst)) == REG))
- df_ref_record (df, dst, loc, insn, DF_REF_REG_DEF, flags);
+
+ if (GET_CODE (dst) == REG
+ || (GET_CODE (dst) == SUBREG && GET_CODE (SUBREG_REG (dst)) == REG))
+ df_ref_record (df, dst, loc, insn, DF_REF_REG_DEF, flags);
}
@@ -1034,6 +1037,7 @@ df_uses_record (df, loc, ref_type, bb, insn, flags)
case CONST_DOUBLE:
case CONST_VECTOR:
case PC:
+ case CC0:
case ADDR_VEC:
case ADDR_DIFF_VEC:
return;
@@ -1062,6 +1066,11 @@ df_uses_record (df, loc, ref_type, bb, insn, flags)
df_uses_record (df, loc, ref_type, bb, insn, flags);
return;
}
+#ifdef CLASS_CANNOT_CHANGE_MODE
+ if (CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (x),
+ GET_MODE (SUBREG_REG (x))))
+ flags |= DF_REF_MODE_CHANGE;
+#endif
/* ... Fall through ... */
@@ -1078,19 +1087,28 @@ df_uses_record (df, loc, ref_type, bb, insn, flags)
switch (GET_CODE (dst))
{
+ enum df_ref_flags use_flags;
case SUBREG:
if (read_modify_subreg_p (dst))
{
+ use_flags = DF_REF_READ_WRITE;
+#ifdef CLASS_CANNOT_CHANGE_MODE
+ if (CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (dst),
+ GET_MODE (SUBREG_REG (dst))))
+ use_flags |= DF_REF_MODE_CHANGE;
+#endif
df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb,
- insn, DF_REF_READ_WRITE);
+ insn, use_flags);
break;
}
/* ... FALLTHRU ... */
case REG:
+ case PARALLEL:
case PC:
- break;
+ case CC0:
+ break;
case MEM:
- df_uses_record (df, &XEXP (dst, 0),
+ df_uses_record (df, &XEXP (dst, 0),
DF_REF_REG_MEM_STORE,
bb, insn, 0);
break;
@@ -1099,8 +1117,14 @@ df_uses_record (df, loc, ref_type, bb, insn, flags)
dst = XEXP (dst, 0);
if (GET_CODE (dst) != SUBREG)
abort ();
+ use_flags = DF_REF_READ_WRITE;
+#ifdef CLASS_CANNOT_CHANGE_MODE
+ if (CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (dst),
+ GET_MODE (SUBREG_REG (dst))))
+ use_flags |= DF_REF_MODE_CHANGE;
+#endif
df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb,
- insn, DF_REF_READ_WRITE);
+ insn, use_flags);
break;
case ZERO_EXTRACT:
case SIGN_EXTRACT:
@@ -1135,7 +1159,7 @@ df_uses_record (df, loc, ref_type, bb, insn, flags)
For now, just mark any regs we can find in ASM_OPERANDS as
used. */
- /* For all ASM_OPERANDS, we must traverse the vector of input operands.
+ /* For all ASM_OPERANDS, we must traverse the vector of input operands.
We can not just fall through here since then we would be confused
by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
traditional asms unlike their normal usage. */
@@ -1217,12 +1241,12 @@ df_insn_refs_record (df, bb, insn)
{
switch (REG_NOTE_KIND (note))
{
- case REG_EQUIV:
- case REG_EQUAL:
- df_uses_record (df, &XEXP (note, 0), DF_REF_REG_USE,
- bb, insn, 0);
- default:
- break;
+ case REG_EQUIV:
+ case REG_EQUAL:
+ df_uses_record (df, &XEXP (note, 0), DF_REF_REG_USE,
+ bb, insn, 0);
+ default:
+ break;
}
}
@@ -1253,7 +1277,7 @@ df_insn_refs_record (df, bb, insn)
{
x = df_reg_use_gen (i);
df_uses_record (df, &SET_DEST (x),
- DF_REF_REG_USE, bb, insn, 0);
+ DF_REF_REG_USE, bb, insn, 0);
}
}
}
@@ -1355,6 +1379,11 @@ df_bb_reg_def_chain_create (df, bb)
{
struct ref *def = link->ref;
unsigned int dregno = DF_REF_REGNO (def);
+ /* Don't add ref's to the chain two times. I.e. only add
+ new refs. XXX the same could be done by testing if the current
+ insn is a modified (or a new) one. This would be faster. */
+ if (DF_REF_ID (def) < df->def_id_save)
+ continue;
df->regs[dregno].defs
= df_link_create (def, df->regs[dregno].defs);
@@ -1404,6 +1433,11 @@ df_bb_reg_use_chain_create (df, bb)
{
struct ref *use = link->ref;
unsigned int uregno = DF_REF_REGNO (use);
+ /* Don't add ref's to the chain two times. I.e. only add
+ new refs. XXX the same could be done by testing if the current
+ insn is a modified (or a new) one. This would be faster. */
+ if (DF_REF_ID (use) < df->use_id_save)
+ continue;
df->regs[uregno].uses
= df_link_create (use, df->regs[uregno].uses);
@@ -1673,7 +1707,7 @@ df_bb_rd_local_compute (df, bb)
bitmap_set_bit (bb_info->rd_gen, DF_REF_ID (def));
}
}
-
+
bb_info->rd_valid = 1;
}
@@ -1703,7 +1737,7 @@ df_bb_ru_local_compute (df, bb)
/* This is much more tricky than computing reaching defs. With
reaching defs, defs get killed by other defs. With upwards
exposed uses, these get killed by defs with the same regno. */
-
+
struct bb_info *bb_info = DF_BB_INFO (df, bb);
rtx insn;
@@ -1946,6 +1980,8 @@ df_analyse_1 (df, blocks, flags, update)
int aflags;
int dflags;
int i;
+ basic_block bb;
+
dflags = 0;
aflags = flags;
if (flags & DF_UD_CHAIN)
@@ -1961,7 +1997,7 @@ df_analyse_1 (df, blocks, flags, update)
aflags |= DF_LR;
if (! blocks)
- blocks = df->all_blocks;
+ blocks = df->all_blocks;
df->flags = flags;
if (update)
@@ -2009,39 +2045,38 @@ df_analyse_1 (df, blocks, flags, update)
df_reg_use_chain_create (df, blocks);
}
- df->dfs_order = xmalloc (sizeof(int) * n_basic_blocks);
- df->rc_order = xmalloc (sizeof(int) * n_basic_blocks);
- df->rts_order = xmalloc (sizeof(int) * n_basic_blocks);
- df->inverse_dfs_map = xmalloc (sizeof(int) * n_basic_blocks);
- df->inverse_rc_map = xmalloc (sizeof(int) * n_basic_blocks);
- df->inverse_rts_map = xmalloc (sizeof(int) * n_basic_blocks);
-
+ df->dfs_order = xmalloc (sizeof (int) * n_basic_blocks);
+ df->rc_order = xmalloc (sizeof (int) * n_basic_blocks);
+ df->rts_order = xmalloc (sizeof (int) * n_basic_blocks);
+ df->inverse_dfs_map = xmalloc (sizeof (int) * last_basic_block);
+ df->inverse_rc_map = xmalloc (sizeof (int) * last_basic_block);
+ df->inverse_rts_map = xmalloc (sizeof (int) * last_basic_block);
+
flow_depth_first_order_compute (df->dfs_order, df->rc_order);
flow_reverse_top_sort_order_compute (df->rts_order);
- for (i = 0; i < n_basic_blocks; i ++)
- {
- df->inverse_dfs_map[df->dfs_order[i]] = i;
- df->inverse_rc_map[df->rc_order[i]] = i;
- df->inverse_rts_map[df->rts_order[i]] = i;
- }
+ for (i = 0; i < n_basic_blocks; i++)
+ {
+ df->inverse_dfs_map[df->dfs_order[i]] = i;
+ df->inverse_rc_map[df->rc_order[i]] = i;
+ df->inverse_rts_map[df->rts_order[i]] = i;
+ }
if (aflags & DF_RD)
{
/* Compute the sets of gens and kills for the defs of each bb. */
df_rd_local_compute (df, df->flags & DF_RD ? blocks : df->all_blocks);
{
- int i;
- bitmap *in = xmalloc (sizeof (bitmap) * n_basic_blocks);
- bitmap *out = xmalloc (sizeof (bitmap) * n_basic_blocks);
- bitmap *gen = xmalloc (sizeof (bitmap) * n_basic_blocks);
- bitmap *kill = xmalloc (sizeof (bitmap) * n_basic_blocks);
- for (i = 0; i < n_basic_blocks; i ++)
+ bitmap *in = xmalloc (sizeof (bitmap) * last_basic_block);
+ bitmap *out = xmalloc (sizeof (bitmap) * last_basic_block);
+ bitmap *gen = xmalloc (sizeof (bitmap) * last_basic_block);
+ bitmap *kill = xmalloc (sizeof (bitmap) * last_basic_block);
+ FOR_EACH_BB (bb)
{
- in[i] = DF_BB_INFO (df, BASIC_BLOCK (i))->rd_in;
- out[i] = DF_BB_INFO (df, BASIC_BLOCK (i))->rd_out;
- gen[i] = DF_BB_INFO (df, BASIC_BLOCK (i))->rd_gen;
- kill[i] = DF_BB_INFO (df, BASIC_BLOCK (i))->rd_kill;
+ in[bb->index] = DF_BB_INFO (df, bb)->rd_in;
+ out[bb->index] = DF_BB_INFO (df, bb)->rd_out;
+ gen[bb->index] = DF_BB_INFO (df, bb)->rd_gen;
+ kill[bb->index] = DF_BB_INFO (df, bb)->rd_kill;
}
- iterative_dataflow_bitmap (in, out, gen, kill, df->all_blocks,
+ iterative_dataflow_bitmap (in, out, gen, kill, df->all_blocks,
FORWARD, UNION, df_rd_transfer_function,
df->inverse_rc_map, NULL);
free (in);
@@ -2066,19 +2101,18 @@ df_analyse_1 (df, blocks, flags, update)
uses in each bb. */
df_ru_local_compute (df, df->flags & DF_RU ? blocks : df->all_blocks);
{
- int i;
- bitmap *in = xmalloc (sizeof (bitmap) * n_basic_blocks);
- bitmap *out = xmalloc (sizeof (bitmap) * n_basic_blocks);
- bitmap *gen = xmalloc (sizeof (bitmap) * n_basic_blocks);
- bitmap *kill = xmalloc (sizeof (bitmap) * n_basic_blocks);
- for (i = 0; i < n_basic_blocks; i ++)
+ bitmap *in = xmalloc (sizeof (bitmap) * last_basic_block);
+ bitmap *out = xmalloc (sizeof (bitmap) * last_basic_block);
+ bitmap *gen = xmalloc (sizeof (bitmap) * last_basic_block);
+ bitmap *kill = xmalloc (sizeof (bitmap) * last_basic_block);
+ FOR_EACH_BB (bb)
{
- in[i] = DF_BB_INFO (df, BASIC_BLOCK (i))->ru_in;
- out[i] = DF_BB_INFO (df, BASIC_BLOCK (i))->ru_out;
- gen[i] = DF_BB_INFO (df, BASIC_BLOCK (i))->ru_gen;
- kill[i] = DF_BB_INFO (df, BASIC_BLOCK (i))->ru_kill;
+ in[bb->index] = DF_BB_INFO (df, bb)->ru_in;
+ out[bb->index] = DF_BB_INFO (df, bb)->ru_out;
+ gen[bb->index] = DF_BB_INFO (df, bb)->ru_gen;
+ kill[bb->index] = DF_BB_INFO (df, bb)->ru_kill;
}
- iterative_dataflow_bitmap (in, out, gen, kill, df->all_blocks,
+ iterative_dataflow_bitmap (in, out, gen, kill, df->all_blocks,
BACKWARD, UNION, df_ru_transfer_function,
df->inverse_rts_map, NULL);
free (in);
@@ -2099,26 +2133,25 @@ df_analyse_1 (df, blocks, flags, update)
/* Free up bitmaps that are no longer required. */
if (dflags)
- df_bitmaps_free (df, dflags);
+ df_bitmaps_free (df, dflags);
if (aflags & DF_LR)
{
/* Compute the sets of defs and uses of live variables. */
- df_lr_local_compute (df, df->flags & DF_LR ? blocks : df->all_blocks);
+ df_lr_local_compute (df, df->flags & DF_LR ? blocks : df->all_blocks);
{
- int i;
- bitmap *in = xmalloc (sizeof (bitmap) * n_basic_blocks);
- bitmap *out = xmalloc (sizeof (bitmap) * n_basic_blocks);
- bitmap *use = xmalloc (sizeof (bitmap) * n_basic_blocks);
- bitmap *def = xmalloc (sizeof (bitmap) * n_basic_blocks);
- for (i = 0; i < n_basic_blocks; i ++)
+ bitmap *in = xmalloc (sizeof (bitmap) * last_basic_block);
+ bitmap *out = xmalloc (sizeof (bitmap) * last_basic_block);
+ bitmap *use = xmalloc (sizeof (bitmap) * last_basic_block);
+ bitmap *def = xmalloc (sizeof (bitmap) * last_basic_block);
+ FOR_EACH_BB (bb)
{
- in[i] = DF_BB_INFO (df, BASIC_BLOCK (i))->lr_in;
- out[i] = DF_BB_INFO (df, BASIC_BLOCK (i))->lr_out;
- use[i] = DF_BB_INFO (df, BASIC_BLOCK (i))->lr_use;
- def[i] = DF_BB_INFO (df, BASIC_BLOCK (i))->lr_def;
+ in[bb->index] = DF_BB_INFO (df, bb)->lr_in;
+ out[bb->index] = DF_BB_INFO (df, bb)->lr_out;
+ use[bb->index] = DF_BB_INFO (df, bb)->lr_use;
+ def[bb->index] = DF_BB_INFO (df, bb)->lr_def;
}
- iterative_dataflow_bitmap (in, out, use, def, df->all_blocks,
+ iterative_dataflow_bitmap (in, out, use, def, df->all_blocks,
BACKWARD, UNION, df_lr_transfer_function,
df->inverse_rts_map, NULL);
free (in);
@@ -2141,7 +2174,7 @@ df_analyse_1 (df, blocks, flags, update)
}
-/* Initialise dataflow analysis. */
+/* Initialize dataflow analysis. */
struct df *
df_init ()
{
@@ -2229,8 +2262,6 @@ df_bb_refs_update (df, bb)
/* Scan the insn for refs. */
df_insn_refs_record (df, bb, insn);
-
- bitmap_clear_bit (df->insns_modified, uid);
count++;
}
if (insn == bb->end)
@@ -2248,7 +2279,7 @@ df_refs_update (df)
basic_block bb;
int count = 0;
- if ((unsigned int)max_reg_num () >= df->reg_size)
+ if ((unsigned int) max_reg_num () >= df->reg_size)
df_reg_table_realloc (df, 0);
df_refs_queue (df);
@@ -2263,19 +2294,22 @@ df_refs_update (df)
}
-/* Return non-zero if any of the requested blocks in the bitmap
+/* Return nonzero if any of the requested blocks in the bitmap
BLOCKS have been modified. */
static int
df_modified_p (df, blocks)
struct df *df;
bitmap blocks;
{
- unsigned int j;
int update = 0;
+ basic_block bb;
+
+ if (!df->n_bbs)
+ return 0;
- for (j = 0; j < df->n_bbs; j++)
- if (bitmap_bit_p (df->bbs_modified, j)
- && (! blocks || (blocks == (bitmap) -1) || bitmap_bit_p (blocks, j)))
+ FOR_EACH_BB (bb)
+ if (bitmap_bit_p (df->bbs_modified, bb->index)
+ && (! blocks || (blocks == (bitmap) -1) || bitmap_bit_p (blocks, bb->index)))
{
update = 1;
break;
@@ -2298,7 +2332,7 @@ df_analyse (df, blocks, flags)
/* We could deal with additional basic blocks being created by
rescanning everything again. */
- if (df->n_bbs && df->n_bbs != (unsigned int)n_basic_blocks)
+ if (df->n_bbs && df->n_bbs != (unsigned int) last_basic_block)
abort ();
update = df_modified_p (df, blocks);
@@ -2311,7 +2345,7 @@ df_analyse (df, blocks, flags)
/* Recompute everything from scratch. */
df_free (df);
}
- /* Allocate and initialise data structures. */
+ /* Allocate and initialize data structures. */
df_alloc (df, max_reg_num ());
df_analyse_1 (df, 0, flags, 0);
update = 1;
@@ -2326,6 +2360,7 @@ df_analyse (df, blocks, flags)
df_analyse_1 (df, blocks, flags, 1);
bitmap_zero (df->bbs_modified);
+ bitmap_zero (df->insns_modified);
}
}
return update;
@@ -2408,10 +2443,8 @@ df_refs_unlink (df, blocks)
}
else
{
- FOR_ALL_BBS (bb,
- {
+ FOR_EACH_BB (bb)
df_bb_refs_unlink (df, bb);
- });
}
}
#endif
@@ -2455,9 +2488,8 @@ df_insn_modify (df, bb, insn)
unsigned int uid;
uid = INSN_UID (insn);
-
if (uid >= df->insn_size)
- df_insn_table_realloc (df, 0);
+ df_insn_table_realloc (df, uid);
bitmap_set_bit (df->bbs_modified, bb->index);
bitmap_set_bit (df->insns_modified, uid);
@@ -2470,8 +2502,7 @@ df_insn_modify (df, bb, insn)
}
-typedef struct replace_args
-{
+typedef struct replace_args {
rtx match;
rtx replacement;
rtx insn;
@@ -2744,7 +2775,7 @@ df_insns_modify (df, bb, first_insn, last_insn)
uid = INSN_UID (insn);
if (uid >= df->insn_size)
- df_insn_table_realloc (df, 0);
+ df_insn_table_realloc (df, uid);
df_insn_modify (df, bb, insn);
@@ -2924,7 +2955,7 @@ df_insn_dominates_all_uses_p (df, bb, insn)
}
-/* Return non-zero if all DF dominates all the uses within the bitmap
+/* Return nonzero if all DF dominates all the uses within the bitmap
BLOCKS. */
static int
df_def_dominates_uses_p (df, def, blocks)
@@ -2955,7 +2986,7 @@ df_def_dominates_uses_p (df, def, blocks)
}
-/* Return non-zero if all the defs of INSN within BB dominates
+/* Return nonzero if all the defs of INSN within BB dominates
all the corresponding uses. */
int
df_insn_dominates_uses_p (df, bb, insn, blocks)
@@ -3002,7 +3033,7 @@ df_regno_bb (df, regno)
}
-/* Return non-zero if REG used in multiple basic blocks. */
+/* Return nonzero if REG used in multiple basic blocks. */
int
df_reg_global_p (df, reg)
struct df *df;
@@ -3022,7 +3053,7 @@ df_reg_lifetime (df, reg)
}
-/* Return non-zero if REG live at start of BB. */
+/* Return nonzero if REG live at start of BB. */
int
df_bb_reg_live_start_p (df, bb, reg)
struct df *df ATTRIBUTE_UNUSED;
@@ -3040,7 +3071,7 @@ df_bb_reg_live_start_p (df, bb, reg)
}
-/* Return non-zero if REG live at end of BB. */
+/* Return nonzero if REG live at end of BB. */
int
df_bb_reg_live_end_p (df, bb, reg)
struct df *df ATTRIBUTE_UNUSED;
@@ -3260,9 +3291,9 @@ df_chain_dump_regno (link, file)
for (; link; link = link->next)
{
fprintf (file, "%c%d(%d) ",
- DF_REF_REG_DEF_P (link->ref) ? 'd' : 'u',
- DF_REF_ID (link->ref),
- DF_REF_REGNO (link->ref));
+ DF_REF_REG_DEF_P (link->ref) ? 'd' : 'u',
+ DF_REF_ID (link->ref),
+ DF_REF_REGNO (link->ref));
}
fprintf (file, "}");
}
@@ -3274,8 +3305,8 @@ df_dump (df, flags, file)
int flags;
FILE *file;
{
- unsigned int i;
unsigned int j;
+ basic_block bb;
if (! df || ! file)
return;
@@ -3286,22 +3317,23 @@ df_dump (df, flags, file)
if (flags & DF_RD)
{
+ basic_block bb;
+
fprintf (file, "Reaching defs:\n");
- for (i = 0; i < df->n_bbs; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
struct bb_info *bb_info = DF_BB_INFO (df, bb);
if (! bb_info->rd_in)
continue;
- fprintf (file, "bb %d in \t", i);
+ fprintf (file, "bb %d in \t", bb->index);
dump_bitmap (file, bb_info->rd_in);
- fprintf (file, "bb %d gen \t", i);
+ fprintf (file, "bb %d gen \t", bb->index);
dump_bitmap (file, bb_info->rd_gen);
- fprintf (file, "bb %d kill\t", i);
+ fprintf (file, "bb %d kill\t", bb->index);
dump_bitmap (file, bb_info->rd_kill);
- fprintf (file, "bb %d out \t", i);
+ fprintf (file, "bb %d out \t", bb->index);
dump_bitmap (file, bb_info->rd_out);
}
}
@@ -3329,21 +3361,20 @@ df_dump (df, flags, file)
if (flags & DF_RU)
{
fprintf (file, "Reaching uses:\n");
- for (i = 0; i < df->n_bbs; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
struct bb_info *bb_info = DF_BB_INFO (df, bb);
if (! bb_info->ru_in)
continue;
- fprintf (file, "bb %d in \t", i);
+ fprintf (file, "bb %d in \t", bb->index);
dump_bitmap (file, bb_info->ru_in);
- fprintf (file, "bb %d gen \t", i);
+ fprintf (file, "bb %d gen \t", bb->index);
dump_bitmap (file, bb_info->ru_gen);
- fprintf (file, "bb %d kill\t", i);
+ fprintf (file, "bb %d kill\t", bb->index);
dump_bitmap (file, bb_info->ru_kill);
- fprintf (file, "bb %d out \t", i);
+ fprintf (file, "bb %d out \t", bb->index);
dump_bitmap (file, bb_info->ru_out);
}
}
@@ -3371,21 +3402,20 @@ df_dump (df, flags, file)
if (flags & DF_LR)
{
fprintf (file, "Live regs:\n");
- for (i = 0; i < df->n_bbs; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
struct bb_info *bb_info = DF_BB_INFO (df, bb);
if (! bb_info->lr_in)
continue;
- fprintf (file, "bb %d in \t", i);
+ fprintf (file, "bb %d in \t", bb->index);
dump_bitmap (file, bb_info->lr_in);
- fprintf (file, "bb %d use \t", i);
+ fprintf (file, "bb %d use \t", bb->index);
dump_bitmap (file, bb_info->lr_use);
- fprintf (file, "bb %d def \t", i);
+ fprintf (file, "bb %d def \t", bb->index);
dump_bitmap (file, bb_info->lr_def);
- fprintf (file, "bb %d out \t", i);
+ fprintf (file, "bb %d out \t", bb->index);
dump_bitmap (file, bb_info->lr_out);
}
}
@@ -3401,42 +3431,42 @@ df_dump (df, flags, file)
&& (reg_info[j].n_uses || reg_info[j].n_defs))
|| ((flags & DF_RD_CHAIN) && reg_info[j].defs)
|| ((flags & DF_RU_CHAIN) && reg_info[j].uses))
- {
- fprintf (file, "reg %d", j);
- if ((flags & DF_RD_CHAIN) && (flags & DF_RU_CHAIN))
- {
- basic_block bb = df_regno_bb (df, j);
+ {
+ fprintf (file, "reg %d", j);
+ if ((flags & DF_RD_CHAIN) && (flags & DF_RU_CHAIN))
+ {
+ basic_block bb = df_regno_bb (df, j);
- if (bb)
- fprintf (file, " bb %d", bb->index);
- else
- fprintf (file, " bb ?");
- }
- if (flags & DF_REG_INFO)
- {
- fprintf (file, " life %d", reg_info[j].lifetime);
- }
+ if (bb)
+ fprintf (file, " bb %d", bb->index);
+ else
+ fprintf (file, " bb ?");
+ }
+ if (flags & DF_REG_INFO)
+ {
+ fprintf (file, " life %d", reg_info[j].lifetime);
+ }
- if ((flags & DF_REG_INFO) || (flags & DF_RD_CHAIN))
- {
- fprintf (file, " defs ");
- if (flags & DF_REG_INFO)
- fprintf (file, "%d ", reg_info[j].n_defs);
- if (flags & DF_RD_CHAIN)
- df_chain_dump (reg_info[j].defs, file);
- }
+ if ((flags & DF_REG_INFO) || (flags & DF_RD_CHAIN))
+ {
+ fprintf (file, " defs ");
+ if (flags & DF_REG_INFO)
+ fprintf (file, "%d ", reg_info[j].n_defs);
+ if (flags & DF_RD_CHAIN)
+ df_chain_dump (reg_info[j].defs, file);
+ }
- if ((flags & DF_REG_INFO) || (flags & DF_RU_CHAIN))
- {
- fprintf (file, " uses ");
- if (flags & DF_REG_INFO)
- fprintf (file, "%d ", reg_info[j].n_uses);
- if (flags & DF_RU_CHAIN)
- df_chain_dump (reg_info[j].uses, file);
- }
+ if ((flags & DF_REG_INFO) || (flags & DF_RU_CHAIN))
+ {
+ fprintf (file, " uses ");
+ if (flags & DF_REG_INFO)
+ fprintf (file, "%d ", reg_info[j].n_uses);
+ if (flags & DF_RU_CHAIN)
+ df_chain_dump (reg_info[j].uses, file);
+ }
- fprintf (file, "\n");
- }
+ fprintf (file, "\n");
+ }
}
}
fprintf (file, "\n");
@@ -3458,7 +3488,7 @@ df_insn_debug (df, insn, file)
if (df->insns[uid].defs)
bbi = DF_REF_BBNO (df->insns[uid].defs->ref);
- else if (df->insns[uid].uses)
+ else if (df->insns[uid].uses)
bbi = DF_REF_BBNO (df->insns[uid].uses->ref);
else
bbi = -1;
@@ -3486,13 +3516,13 @@ df_insn_debug_regno (df, insn, file)
if (df->insns[uid].defs)
bbi = DF_REF_BBNO (df->insns[uid].defs->ref);
- else if (df->insns[uid].uses)
+ else if (df->insns[uid].uses)
bbi = DF_REF_BBNO (df->insns[uid].uses->ref);
else
bbi = -1;
fprintf (file, "insn %d bb %d luid %d defs ",
- uid, bbi, DF_INSN_LUID (df, insn));
+ uid, bbi, DF_INSN_LUID (df, insn));
df_chain_dump_regno (df->insns[uid].defs, file);
fprintf (file, " uses ");
df_chain_dump_regno (df->insns[uid].uses, file);
@@ -3595,9 +3625,9 @@ debug_df_chain (link)
/* Hybrid search algorithm from "Implementation Techniques for
Efficient Data-Flow Analysis of Large Programs". */
-static void
-hybrid_search_bitmap (block, in, out, gen, kill, dir,
- conf_op, transfun, visited, pending,
+static void
+hybrid_search_bitmap (block, in, out, gen, kill, dir,
+ conf_op, transfun, visited, pending,
data)
basic_block block;
bitmap *in, *out, *gen, *kill;
@@ -3611,7 +3641,7 @@ hybrid_search_bitmap (block, in, out, gen, kill, dir,
int changed;
int i = block->index;
edge e;
- basic_block bb= block;
+ basic_block bb = block;
SET_BIT (visited, block->index);
if (TEST_BIT (pending, block->index))
{
@@ -3634,16 +3664,16 @@ hybrid_search_bitmap (block, in, out, gen, kill, dir,
}
}
}
- else
+ else
{
/* Calculate <conf_op> of successor ins */
- bitmap_zero(out[i]);
+ bitmap_zero (out[i]);
for (e = bb->succ; e != 0; e = e->succ_next)
{
if (e->dest == EXIT_BLOCK_PTR)
continue;
switch (conf_op)
- {
+ {
case UNION:
bitmap_a_or_b (out[i], out[i], in[e->dest->index]);
break;
@@ -3652,7 +3682,7 @@ hybrid_search_bitmap (block, in, out, gen, kill, dir,
break;
}
}
- }
+ }
/* Common part */
(*transfun)(i, &changed, in[i], out[i], gen[i], kill[i], data);
RESET_BIT (pending, i);
@@ -3685,8 +3715,8 @@ hybrid_search_bitmap (block, in, out, gen, kill, dir,
if (e->dest == EXIT_BLOCK_PTR || e->dest->index == i)
continue;
if (!TEST_BIT (visited, e->dest->index))
- hybrid_search_bitmap (e->dest, in, out, gen, kill, dir,
- conf_op, transfun, visited, pending,
+ hybrid_search_bitmap (e->dest, in, out, gen, kill, dir,
+ conf_op, transfun, visited, pending,
data);
}
}
@@ -3697,8 +3727,8 @@ hybrid_search_bitmap (block, in, out, gen, kill, dir,
if (e->src == ENTRY_BLOCK_PTR || e->src->index == i)
continue;
if (!TEST_BIT (visited, e->src->index))
- hybrid_search_bitmap (e->src, in, out, gen, kill, dir,
- conf_op, transfun, visited, pending,
+ hybrid_search_bitmap (e->src, in, out, gen, kill, dir,
+ conf_op, transfun, visited, pending,
data);
}
}
@@ -3706,8 +3736,8 @@ hybrid_search_bitmap (block, in, out, gen, kill, dir,
/* Hybrid search for sbitmaps, rather than bitmaps. */
-static void
-hybrid_search_sbitmap (block, in, out, gen, kill, dir,
+static void
+hybrid_search_sbitmap (block, in, out, gen, kill, dir,
conf_op, transfun, visited, pending,
data)
basic_block block;
@@ -3722,7 +3752,7 @@ hybrid_search_sbitmap (block, in, out, gen, kill, dir,
int changed;
int i = block->index;
edge e;
- basic_block bb= block;
+ basic_block bb = block;
SET_BIT (visited, block->index);
if (TEST_BIT (pending, block->index))
{
@@ -3745,16 +3775,16 @@ hybrid_search_sbitmap (block, in, out, gen, kill, dir,
}
}
}
- else
+ else
{
/* Calculate <conf_op> of successor ins */
- sbitmap_zero(out[i]);
+ sbitmap_zero (out[i]);
for (e = bb->succ; e != 0; e = e->succ_next)
{
if (e->dest == EXIT_BLOCK_PTR)
continue;
switch (conf_op)
- {
+ {
case UNION:
sbitmap_a_or_b (out[i], out[i], in[e->dest->index]);
break;
@@ -3763,7 +3793,7 @@ hybrid_search_sbitmap (block, in, out, gen, kill, dir,
break;
}
}
- }
+ }
/* Common part */
(*transfun)(i, &changed, in[i], out[i], gen[i], kill[i], data);
RESET_BIT (pending, i);
@@ -3796,8 +3826,8 @@ hybrid_search_sbitmap (block, in, out, gen, kill, dir,
if (e->dest == EXIT_BLOCK_PTR || e->dest->index == i)
continue;
if (!TEST_BIT (visited, e->dest->index))
- hybrid_search_sbitmap (e->dest, in, out, gen, kill, dir,
- conf_op, transfun, visited, pending,
+ hybrid_search_sbitmap (e->dest, in, out, gen, kill, dir,
+ conf_op, transfun, visited, pending,
data);
}
}
@@ -3808,8 +3838,8 @@ hybrid_search_sbitmap (block, in, out, gen, kill, dir,
if (e->src == ENTRY_BLOCK_PTR || e->src->index == i)
continue;
if (!TEST_BIT (visited, e->src->index))
- hybrid_search_sbitmap (e->src, in, out, gen, kill, dir,
- conf_op, transfun, visited, pending,
+ hybrid_search_sbitmap (e->src, in, out, gen, kill, dir,
+ conf_op, transfun, visited, pending,
data);
}
}
@@ -3827,20 +3857,20 @@ hybrid_search_sbitmap (block, in, out, gen, kill, dir,
transfun = Transfer function.
order = Order to iterate in. (Should map block numbers -> order)
data = Whatever you want. It's passed to the transfer function.
-
+
This function will perform iterative bitvector dataflow, producing
the in and out sets. Even if you only want to perform it for a
small number of blocks, the vectors for in and out must be large
enough for *all* blocks, because changing one block might affect
others. However, it'll only put what you say to analyze on the
initial worklist.
-
+
For forward problems, you probably want to pass in a mapping of
block number to rc_order (like df->inverse_rc_map).
*/
void
-iterative_dataflow_sbitmap (in, out, gen, kill, blocks,
- dir, conf_op, transfun, order, data)
+iterative_dataflow_sbitmap (in, out, gen, kill, blocks,
+ dir, conf_op, transfun, order, data)
sbitmap *in, *out, *gen, *kill;
bitmap blocks;
enum df_flow_dir dir;
@@ -3853,14 +3883,14 @@ iterative_dataflow_sbitmap (in, out, gen, kill, blocks,
fibheap_t worklist;
basic_block bb;
sbitmap visited, pending;
- pending = sbitmap_alloc (n_basic_blocks);
- visited = sbitmap_alloc (n_basic_blocks);
+ pending = sbitmap_alloc (last_basic_block);
+ visited = sbitmap_alloc (last_basic_block);
sbitmap_zero (pending);
sbitmap_zero (visited);
worklist = fibheap_new ();
EXECUTE_IF_SET_IN_BITMAP (blocks, 0, i,
{
- fibheap_insert (worklist, order[i], (void *) (size_t) i);
+ fibheap_insert (worklist, order[i], (void *) (size_t) i);
SET_BIT (pending, i);
if (dir == FORWARD)
sbitmap_copy (out[i], gen[i]);
@@ -3874,7 +3904,7 @@ iterative_dataflow_sbitmap (in, out, gen, kill, blocks,
i = (size_t) fibheap_extract_min (worklist);
bb = BASIC_BLOCK (i);
if (!TEST_BIT (visited, bb->index))
- hybrid_search_sbitmap (bb, in, out, gen, kill, dir,
+ hybrid_search_sbitmap (bb, in, out, gen, kill, dir,
conf_op, transfun, visited, pending, data);
}
if (sbitmap_first_set_bit (pending) != -1)
@@ -3888,7 +3918,7 @@ iterative_dataflow_sbitmap (in, out, gen, kill, blocks,
else
{
break;
- }
+ }
}
sbitmap_free (pending);
sbitmap_free (visited);
@@ -3898,8 +3928,8 @@ iterative_dataflow_sbitmap (in, out, gen, kill, blocks,
/* Exactly the same as iterative_dataflow_sbitmap, except it works on
bitmaps instead */
void
-iterative_dataflow_bitmap (in, out, gen, kill, blocks,
- dir, conf_op, transfun, order, data)
+iterative_dataflow_bitmap (in, out, gen, kill, blocks,
+ dir, conf_op, transfun, order, data)
bitmap *in, *out, *gen, *kill;
bitmap blocks;
enum df_flow_dir dir;
@@ -3912,8 +3942,8 @@ iterative_dataflow_bitmap (in, out, gen, kill, blocks,
fibheap_t worklist;
basic_block bb;
sbitmap visited, pending;
- pending = sbitmap_alloc (n_basic_blocks);
- visited = sbitmap_alloc (n_basic_blocks);
+ pending = sbitmap_alloc (last_basic_block);
+ visited = sbitmap_alloc (last_basic_block);
sbitmap_zero (pending);
sbitmap_zero (visited);
worklist = fibheap_new ();
@@ -3933,7 +3963,7 @@ iterative_dataflow_bitmap (in, out, gen, kill, blocks,
i = (size_t) fibheap_extract_min (worklist);
bb = BASIC_BLOCK (i);
if (!TEST_BIT (visited, bb->index))
- hybrid_search_bitmap (bb, in, out, gen, kill, dir,
+ hybrid_search_bitmap (bb, in, out, gen, kill, dir,
conf_op, transfun, visited, pending, data);
}
if (sbitmap_first_set_bit (pending) != -1)
@@ -3947,9 +3977,9 @@ iterative_dataflow_bitmap (in, out, gen, kill, blocks,
else
{
break;
- }
+ }
}
sbitmap_free (pending);
sbitmap_free (visited);
- fibheap_delete (worklist);
+ fibheap_delete (worklist);
}
diff --git a/contrib/gcc/df.h b/contrib/gcc/df.h
index 7f4e4be..59f3143 100644
--- a/contrib/gcc/df.h
+++ b/contrib/gcc/df.h
@@ -50,7 +50,16 @@ struct df_link
enum df_ref_flags
{
- DF_REF_READ_WRITE = 1
+ DF_REF_READ_WRITE = 1,
+
+ /* This flag is set on register references itself representing a or
+ being inside a subreg on machines which have CLASS_CANNOT_CHANGE_MODE
+ and where the mode change of that subreg expression is invalid for
+ this class. Note, that this flag can also be set on df_refs
+ representing the REG itself (i.e. one might not see the subreg
+ anyore). Also note, that this flag is set also for hardreg refs.
+ I.e. you must check yourself if it's a pseudo. */
+ DF_REF_MODE_CHANGE = 2
};
/* Define a register reference structure. */
@@ -61,7 +70,7 @@ struct ref
rtx *loc; /* Loc is the location of the reg. */
struct df_link *chain; /* Head of def-use or use-def chain. */
enum df_ref_type type; /* Type of ref. */
- int id; /* Ref index. */
+ unsigned int id; /* Ref index. */
enum df_ref_flags flags; /* Various flags. */
};
diff --git a/contrib/gcc/diagnostic.c b/contrib/gcc/diagnostic.c
index 4ff157d..a7f2d2c 100644
--- a/contrib/gcc/diagnostic.c
+++ b/contrib/gcc/diagnostic.c
@@ -1,4 +1,4 @@
-/* Language-independent diagnostic subroutines for the GNU C compiler
+/* Language-independent diagnostic subroutines for the GNU Compiler Collection
Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
@@ -34,65 +34,52 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "toplev.h"
#include "intl.h"
#include "diagnostic.h"
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-#define output_formatted_integer(BUFFER, FORMAT, INTEGER) \
- do { \
- sprintf ((BUFFER)->digit_buffer, FORMAT, INTEGER); \
- output_add_string (BUFFER, (BUFFER)->digit_buffer); \
- } while (0)
+#include "langhooks.h"
+#include "langhooks-def.h"
#define output_text_length(BUFFER) (BUFFER)->line_length
#define is_starting_newline(BUFFER) (output_text_length (BUFFER) == 0)
-#define output_prefix(BUFFER) (BUFFER)->state.prefix
#define line_wrap_cutoff(BUFFER) (BUFFER)->state.maximum_length
#define prefix_was_emitted_for(BUFFER) (BUFFER)->state.emitted_prefix_p
-#define output_buffer_ptr_to_format_args(BUFFER) (BUFFER)->state.format_args
-
-#define diagnostic_args output_buffer_ptr_to_format_args (diagnostic_buffer)
-#define diagnostic_msg output_buffer_text_cursor (diagnostic_buffer)
/* Prototypes. */
-static void diagnostic_finish PARAMS ((output_buffer *));
-static void output_do_verbatim PARAMS ((output_buffer *,
- const char *, va_list *));
+static void output_flush PARAMS ((output_buffer *));
+static void output_do_verbatim PARAMS ((output_buffer *, text_info *));
static void output_buffer_to_stream PARAMS ((output_buffer *));
-static void output_format PARAMS ((output_buffer *));
+static void output_format PARAMS ((output_buffer *, text_info *));
static void output_indent PARAMS ((output_buffer *));
static char *vbuild_message_string PARAMS ((const char *, va_list))
ATTRIBUTE_PRINTF (1, 0);
static char *build_message_string PARAMS ((const char *, ...))
ATTRIBUTE_PRINTF_1;
-static void output_do_printf PARAMS ((output_buffer *, const char *))
- ATTRIBUTE_PRINTF (2, 0);
-static void format_with_decl PARAMS ((output_buffer *, tree));
-static void diagnostic_for_decl PARAMS ((tree, const char *, va_list *, int));
+static void format_with_decl PARAMS ((output_buffer *, text_info *, tree));
+static void diagnostic_for_decl PARAMS ((diagnostic_info *, tree));
static void set_real_maximum_length PARAMS ((output_buffer *));
static void output_unsigned_decimal PARAMS ((output_buffer *, unsigned int));
static void output_long_decimal PARAMS ((output_buffer *, long int));
static void output_long_unsigned_decimal PARAMS ((output_buffer *,
- long unsigned int));
+ long unsigned int));
static void output_octal PARAMS ((output_buffer *, unsigned int));
static void output_long_octal PARAMS ((output_buffer *, unsigned long int));
static void output_hexadecimal PARAMS ((output_buffer *, unsigned int));
static void output_long_hexadecimal PARAMS ((output_buffer *,
- unsigned long int));
+ unsigned long int));
+static void output_pointer PARAMS ((output_buffer *, void *));
static void output_append_r PARAMS ((output_buffer *, const char *, int));
static void wrap_text PARAMS ((output_buffer *, const char *, const char *));
static void maybe_wrap_text PARAMS ((output_buffer *, const char *,
- const char *));
-static void clear_diagnostic_info PARAMS ((output_buffer *));
+ const char *));
+static void output_clear_data PARAMS ((output_buffer *));
-static void default_diagnostic_starter PARAMS ((output_buffer *,
- diagnostic_context *));
-static void default_diagnostic_finalizer PARAMS ((output_buffer *,
- diagnostic_context *));
+static void default_diagnostic_starter PARAMS ((diagnostic_context *,
+ diagnostic_info *));
+static void default_diagnostic_finalizer PARAMS ((diagnostic_context *,
+ diagnostic_info *));
-static void error_recursion PARAMS ((void)) ATTRIBUTE_NORETURN;
+static void error_recursion PARAMS ((diagnostic_context *)) ATTRIBUTE_NORETURN;
+static bool text_specifies_location PARAMS ((text_info *, location_t *));
extern int rtl_dump_and_exit;
extern int warnings_are_errors;
@@ -101,101 +88,9 @@ extern int warnings_are_errors;
static diagnostic_context global_diagnostic_context;
diagnostic_context *global_dc = &global_diagnostic_context;
-/* This will be removed shortly. */
-output_buffer *diagnostic_buffer = &global_diagnostic_context.buffer;
-
-/* Function of last error message;
- more generally, function such that if next error message is in it
- then we don't have to mention the function name. */
-static tree last_error_function = NULL;
-
-/* Used to detect when input_file_stack has changed since last described. */
-static int last_error_tick;
-
-/* Called by report_error_function to print out function name.
- Default may be overridden by language front-ends. */
-
-void (*print_error_function) PARAMS ((diagnostic_context *, const char *))
- = default_print_error_function;
-
-/* Prevent recursion into the error handler. */
-static int diagnostic_lock;
-
-/* Return truthvalue if current input file is different from the most recent
- file involved in a diagnostic message. */
-
-int
-error_module_changed ()
-{
- return last_error_tick != input_file_stack_tick;
-}
-
-/* Remember current file as being the most recent file involved in a
- diagnostic message. */
-
-void
-record_last_error_module ()
-{
- last_error_tick = input_file_stack_tick;
-}
-
-/* Same as error_module_changed, but for function. */
-
-int
-error_function_changed ()
-{
- return last_error_function != current_function_decl;
-}
-
-/* Same as record_last_error_module, but for function. */
-
-void
-record_last_error_function ()
-{
- last_error_function = current_function_decl;
-}
-
-/* Initialize the diagnostic message outputting machinery. */
-
-void
-diagnostic_initialize (context)
- diagnostic_context *context;
-{
- memset (context, 0, sizeof *context);
- obstack_init (&context->buffer.obstack);
-
- /* By default, diagnostics are sent to stderr. */
- output_buffer_attached_stream (&context->buffer) = stderr;
-
- /* By default, we emit prefixes once per message. */
- diagnostic_prefixing_rule (context) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
-
- diagnostic_starter (context) = default_diagnostic_starter;
- diagnostic_finalizer (context) = default_diagnostic_finalizer;
-}
-
-/* Returns true if BUFFER is in line-wrapping mode. */
-
-int
-output_is_line_wrapping (buffer)
- output_buffer *buffer;
-{
- return diagnostic_line_cutoff (buffer) > 0;
-}
-
-/* Return BUFFER's prefix. */
-
-const char *
-output_get_prefix (buffer)
- const output_buffer *buffer;
-{
- return output_prefix (buffer);
-}
-
/* Subroutine of output_set_maximum_length. Set up BUFFER's
internal maximum characters per line. */
-
static void
set_real_maximum_length (buffer)
output_buffer *buffer;
@@ -203,45 +98,43 @@ set_real_maximum_length (buffer)
/* If we're told not to wrap lines then do the obvious thing. In case
we'll emit prefix only once per diagnostic message, it is appropriate
not to increase unnecessarily the line-length cut-off. */
- if (! output_is_line_wrapping (buffer)
- || diagnostic_prefixing_rule (buffer) == DIAGNOSTICS_SHOW_PREFIX_ONCE
- || diagnostic_prefixing_rule (buffer) == DIAGNOSTICS_SHOW_PREFIX_NEVER)
- line_wrap_cutoff (buffer) = diagnostic_line_cutoff (buffer);
+ if (!output_is_line_wrapping (buffer)
+ || output_prefixing_rule (buffer) == DIAGNOSTICS_SHOW_PREFIX_ONCE
+ || output_prefixing_rule (buffer) == DIAGNOSTICS_SHOW_PREFIX_NEVER)
+ line_wrap_cutoff (buffer) = output_line_cutoff (buffer);
else
{
- int prefix_length =
- output_prefix (buffer) ? strlen (output_prefix (buffer)) : 0;
+ int prefix_length = buffer->state.prefix ?
+ strlen (buffer->state.prefix) : 0;
/* If the prefix is ridiculously too long, output at least
32 characters. */
- if (diagnostic_line_cutoff (buffer) - prefix_length < 32)
- line_wrap_cutoff (buffer) = diagnostic_line_cutoff (buffer) + 32;
+ if (output_line_cutoff (buffer) - prefix_length < 32)
+ line_wrap_cutoff (buffer) = output_line_cutoff (buffer) + 32;
else
- line_wrap_cutoff (buffer) = diagnostic_line_cutoff (buffer);
+ line_wrap_cutoff (buffer) = output_line_cutoff (buffer);
}
}
/* Sets the number of maximum characters per line BUFFER can output
in line-wrapping mode. A LENGTH value 0 suppresses line-wrapping. */
-
void
output_set_maximum_length (buffer, length)
output_buffer *buffer;
int length;
{
- diagnostic_line_cutoff (buffer) = length;
+ output_line_cutoff (buffer) = length;
set_real_maximum_length (buffer);
}
/* Sets BUFFER's PREFIX. */
-
void
output_set_prefix (buffer, prefix)
output_buffer *buffer;
const char *prefix;
{
- output_prefix (buffer) = prefix;
+ buffer->state.prefix = prefix;
set_real_maximum_length (buffer);
- prefix_was_emitted_for (buffer) = 0;
+ prefix_was_emitted_for (buffer) = false;
output_indentation (buffer) = 0;
}
@@ -252,27 +145,25 @@ output_last_position (buffer)
const output_buffer *buffer;
{
const char *p = NULL;
-
+
if (obstack_base (&buffer->obstack) != obstack_next_free (&buffer->obstack))
p = ((const char *) obstack_next_free (&buffer->obstack)) - 1;
return p;
}
/* Free BUFFER's prefix, a previously malloc'd string. */
-
void
output_destroy_prefix (buffer)
output_buffer *buffer;
{
- if (output_prefix (buffer) != NULL)
+ if (buffer->state.prefix != NULL)
{
- free ((char *) output_prefix (buffer));
- output_prefix (buffer) = NULL;
+ free ((char *) buffer->state.prefix);
+ buffer->state.prefix = NULL;
}
}
/* Zero out any text output so far in BUFFER. */
-
void
output_clear_message_text (buffer)
output_buffer *buffer;
@@ -281,21 +172,17 @@ output_clear_message_text (buffer)
output_text_length (buffer) = 0;
}
-/* Zero out any diagnostic data used so far by BUFFER. */
-
+/* Zero out any formatting data used so far by BUFFER. */
static void
-clear_diagnostic_info (buffer)
+output_clear_data (buffer)
output_buffer *buffer;
{
- output_buffer_text_cursor (buffer) = NULL;
- output_buffer_ptr_to_format_args (buffer) = NULL;
- prefix_was_emitted_for (buffer) = 0;
+ prefix_was_emitted_for (buffer) = false;
output_indentation (buffer) = 0;
}
/* Construct an output BUFFER with PREFIX and of MAXIMUM_LENGTH
characters per line. */
-
void
init_output_buffer (buffer, prefix, maximum_length)
output_buffer *buffer;
@@ -305,26 +192,24 @@ init_output_buffer (buffer, prefix, maximum_length)
memset (buffer, 0, sizeof (output_buffer));
obstack_init (&buffer->obstack);
output_buffer_attached_stream (buffer) = stderr;
- diagnostic_line_cutoff (buffer) = maximum_length;
- diagnostic_prefixing_rule (buffer) = diagnostic_prefixing_rule (global_dc);
+ output_line_cutoff (buffer) = maximum_length;
+ output_prefixing_rule (buffer) = diagnostic_prefixing_rule (global_dc);
output_set_prefix (buffer, prefix);
output_text_length (buffer) = 0;
- clear_diagnostic_info (buffer);
+ output_clear_data (buffer);
}
/* Reinitialize BUFFER. */
-
void
output_clear (buffer)
output_buffer *buffer;
{
output_clear_message_text (buffer);
- clear_diagnostic_info (buffer);
+ output_clear_data (buffer);
}
/* Finishes constructing a NULL-terminated character string representing
the BUFFERed message. */
-
const char *
output_finalize_message (buffer)
output_buffer *buffer;
@@ -333,16 +218,8 @@ output_finalize_message (buffer)
return output_message_text (buffer);
}
-void
-flush_diagnostic_buffer ()
-{
- output_buffer_to_stream (diagnostic_buffer);
- fflush (output_buffer_attached_stream (diagnostic_buffer));
-}
-
/* Return the amount of characters BUFFER can accept to
make a full line. */
-
int
output_space_left (buffer)
const output_buffer *buffer;
@@ -351,41 +228,39 @@ output_space_left (buffer)
}
/* Write out BUFFER's prefix. */
-
void
output_emit_prefix (buffer)
output_buffer *buffer;
{
- if (output_prefix (buffer) != NULL)
+ if (buffer->state.prefix != NULL)
{
- switch (diagnostic_prefixing_rule (buffer))
- {
- default:
- case DIAGNOSTICS_SHOW_PREFIX_NEVER:
- break;
-
- case DIAGNOSTICS_SHOW_PREFIX_ONCE:
- if (prefix_was_emitted_for (buffer))
- {
- output_indent (buffer);
- break;
- }
- output_indentation (buffer) += 3;
- /* Fall through. */
-
- case DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE:
- {
- int prefix_length = strlen (output_prefix (buffer));
- output_append_r (buffer, output_prefix (buffer), prefix_length);
- prefix_was_emitted_for (buffer) = 1;
- }
- break;
- }
+ switch (output_prefixing_rule (buffer))
+ {
+ default:
+ case DIAGNOSTICS_SHOW_PREFIX_NEVER:
+ break;
+
+ case DIAGNOSTICS_SHOW_PREFIX_ONCE:
+ if (prefix_was_emitted_for (buffer))
+ {
+ output_indent (buffer);
+ break;
+ }
+ output_indentation (buffer) += 3;
+ /* Fall through. */
+
+ case DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE:
+ {
+ int prefix_length = strlen (buffer->state.prefix);
+ output_append_r (buffer, buffer->state.prefix, prefix_length);
+ prefix_was_emitted_for (buffer) = true;
+ }
+ break;
+ }
}
}
/* Have BUFFER start a new line. */
-
void
output_add_newline (buffer)
output_buffer *buffer;
@@ -395,7 +270,6 @@ output_add_newline (buffer)
}
/* Appends a character to BUFFER. */
-
void
output_add_character (buffer, c)
output_buffer *buffer;
@@ -408,7 +282,6 @@ output_add_character (buffer, c)
}
/* Adds a space to BUFFER. */
-
void
output_add_space (buffer)
output_buffer *buffer;
@@ -424,13 +297,12 @@ output_add_space (buffer)
/* These functions format an INTEGER into BUFFER as suggested by their
names. */
-
void
output_decimal (buffer, i)
output_buffer *buffer;
int i;
{
- output_formatted_integer (buffer, "%d", i);
+ output_formatted_scalar (buffer, "%d", i);
}
static void
@@ -438,7 +310,7 @@ output_long_decimal (buffer, i)
output_buffer *buffer;
long int i;
{
- output_formatted_integer (buffer, "%ld", i);
+ output_formatted_scalar (buffer, "%ld", i);
}
static void
@@ -446,7 +318,7 @@ output_unsigned_decimal (buffer, i)
output_buffer *buffer;
unsigned int i;
{
- output_formatted_integer (buffer, "%u", i);
+ output_formatted_scalar (buffer, "%u", i);
}
static void
@@ -454,7 +326,7 @@ output_long_unsigned_decimal (buffer, i)
output_buffer *buffer;
long unsigned int i;
{
- output_formatted_integer (buffer, "%lu", i);
+ output_formatted_scalar (buffer, "%lu", i);
}
static void
@@ -462,7 +334,7 @@ output_octal (buffer, i)
output_buffer *buffer;
unsigned int i;
{
- output_formatted_integer (buffer, "%o", i);
+ output_formatted_scalar (buffer, "%o", i);
}
static void
@@ -470,7 +342,7 @@ output_long_octal (buffer, i)
output_buffer *buffer;
unsigned long int i;
{
- output_formatted_integer (buffer, "%lo", i);
+ output_formatted_scalar (buffer, "%lo", i);
}
static void
@@ -478,7 +350,7 @@ output_hexadecimal (buffer, i)
output_buffer *buffer;
unsigned int i;
{
- output_formatted_integer (buffer, "%x", i);
+ output_formatted_scalar (buffer, "%x", i);
}
static void
@@ -486,12 +358,19 @@ output_long_hexadecimal (buffer, i)
output_buffer *buffer;
unsigned long int i;
{
- output_formatted_integer (buffer, "%lx", i);
+ output_formatted_scalar (buffer, "%lx", i);
+}
+
+static void
+output_pointer (buffer, p)
+ output_buffer *buffer;
+ void *p;
+{
+ output_formatted_scalar (buffer, HOST_PTR_PRINTF, p);
}
/* Append to BUFFER a string specified by its STARTING character
and LENGTH. */
-
static void
output_append_r (buffer, start, length)
output_buffer *buffer;
@@ -503,10 +382,9 @@ output_append_r (buffer, start, length)
}
/* Append a string deliminated by START and END to BUFFER. No wrapping is
- done. However, if beginning a new line then emit output_prefix (BUFFER)
+ done. However, if beginning a new line then emit BUFFER->state.prefix
and skip any leading whitespace if appropriate. The caller must ensure
that it is safe to do so. */
-
void
output_append (buffer, start, end)
output_buffer *buffer;
@@ -518,8 +396,8 @@ output_append (buffer, start, end)
{
output_emit_prefix (buffer);
if (output_is_line_wrapping (buffer))
- while (start != end && *start == ' ')
- ++start;
+ while (start != end && *start == ' ')
+ ++start;
}
output_append_r (buffer, start, end - start);
}
@@ -536,43 +414,41 @@ output_indent (buffer)
}
/* Wrap a text delimited by START and END into BUFFER. */
-
static void
wrap_text (buffer, start, end)
output_buffer *buffer;
const char *start;
const char *end;
{
- int is_wrapping = output_is_line_wrapping (buffer);
-
+ bool is_wrapping = output_is_line_wrapping (buffer);
+
while (start != end)
{
- /* Dump anything bordered by whitespaces. */
+ /* Dump anything bordered by whitespaces. */
{
- const char *p = start;
- while (p != end && *p != ' ' && *p != '\n')
- ++p;
- if (is_wrapping && p - start >= output_space_left (buffer))
- output_add_newline (buffer);
- output_append (buffer, start, p);
- start = p;
+ const char *p = start;
+ while (p != end && *p != ' ' && *p != '\n')
+ ++p;
+ if (is_wrapping && p - start >= output_space_left (buffer))
+ output_add_newline (buffer);
+ output_append (buffer, start, p);
+ start = p;
}
if (start != end && *start == ' ')
- {
- output_add_space (buffer);
- ++start;
- }
+ {
+ output_add_space (buffer);
+ ++start;
+ }
if (start != end && *start == '\n')
- {
- output_add_newline (buffer);
- ++start;
- }
+ {
+ output_add_newline (buffer);
+ ++start;
+ }
}
}
/* Same as wrap_text but wrap text only when in line-wrapping mode. */
-
static void
maybe_wrap_text (buffer, start, end)
output_buffer *buffer;
@@ -588,7 +464,6 @@ maybe_wrap_text (buffer, start, end)
/* Append a STRING to BUFFER; the STRING might be line-wrapped if in
appropriate mode. */
-
void
output_add_string (buffer, str)
output_buffer *buffer;
@@ -597,6 +472,16 @@ output_add_string (buffer, str)
maybe_wrap_text (buffer, str, str + (str ? strlen (str) : 0));
}
+/* Append an identifier ID to BUFFER. */
+void
+output_add_identifier (buffer, id)
+ output_buffer *buffer;
+ tree id;
+{
+ output_append (buffer, IDENTIFIER_POINTER (id),
+ IDENTIFIER_POINTER (id) + IDENTIFIER_LENGTH (id));
+}
+
/* Flush the content of BUFFER onto the attached stream,
and reinitialize. */
@@ -609,9 +494,8 @@ output_buffer_to_stream (buffer)
output_clear_message_text (buffer);
}
-/* Format a message pointed to by output_buffer_text_cursor (BUFFER) using
- output_buffer_format_args (BUFFER) as appropriate. The following format
- specifiers are recognized as being language independent:
+/* Format a message pointed to by TEXT. The following format specifiers are
+ recognized as being language independent:
%d, %i: (signed) integer in base ten.
%u: unsigned integer in base ten.
%o: unsigned integer in base eight.
@@ -619,124 +503,128 @@ output_buffer_to_stream (buffer)
%ld, %li, %lo, %lu, %lx: long versions of the above.
%c: character.
%s: string.
+ %p: pointer.
%%: `%'.
- %*.s: a substring the length of which is specified by an integer. */
-
+ %*.s: a substring the length of which is specified by an integer.
+ %H: location_t. */
static void
-output_format (buffer)
+output_format (buffer, text)
output_buffer *buffer;
+ text_info *text;
{
- for (; *output_buffer_text_cursor (buffer);
- ++output_buffer_text_cursor (buffer))
+ for (; *text->format_spec; ++text->format_spec)
{
- int long_integer = 0;
+ bool long_integer = 0;
/* Ignore text. */
{
- const char *p = output_buffer_text_cursor (buffer);
- while (*p && *p != '%')
- ++p;
- wrap_text (buffer, output_buffer_text_cursor (buffer), p);
- output_buffer_text_cursor (buffer) = p;
+ const char *p = text->format_spec;
+ while (*p && *p != '%')
+ ++p;
+ wrap_text (buffer, text->format_spec, p);
+ text->format_spec = p;
}
- if (!*output_buffer_text_cursor (buffer))
- break;
+ if (*text->format_spec == '\0')
+ break;
/* We got a '%'. Let's see what happens. Record whether we're
parsing a long integer format specifier. */
- if (*++output_buffer_text_cursor (buffer) == 'l')
- {
- long_integer = 1;
- ++output_buffer_text_cursor (buffer);
- }
+ if (*++text->format_spec == 'l')
+ {
+ long_integer = true;
+ ++text->format_spec;
+ }
/* Handle %c, %d, %i, %ld, %li, %lo, %lu, %lx, %o, %s, %u,
%x, %.*s; %%. And nothing else. Front-ends should install
printers to grok language specific format specifiers. */
- switch (*output_buffer_text_cursor (buffer))
- {
- case 'c':
- output_add_character
- (buffer, va_arg (output_buffer_format_args (buffer), int));
- break;
-
- case 'd':
- case 'i':
- if (long_integer)
- output_long_decimal
- (buffer, va_arg (output_buffer_format_args (buffer), long int));
- else
- output_decimal
- (buffer, va_arg (output_buffer_format_args (buffer), int));
- break;
+ switch (*text->format_spec)
+ {
+ case 'c':
+ output_add_character (buffer, va_arg (*text->args_ptr, int));
+ break;
+
+ case 'd':
+ case 'i':
+ if (long_integer)
+ output_long_decimal (buffer, va_arg (*text->args_ptr, long int));
+ else
+ output_decimal (buffer, va_arg (*text->args_ptr, int));
+ break;
- case 'o':
- if (long_integer)
- output_long_octal (buffer,
- va_arg (output_buffer_format_args (buffer),
- unsigned long int));
- else
- output_octal (buffer,
- va_arg (output_buffer_format_args (buffer),
- unsigned int));
- break;
+ case 'o':
+ if (long_integer)
+ output_long_octal (buffer,
+ va_arg (*text->args_ptr, unsigned long int));
+ else
+ output_octal (buffer, va_arg (*text->args_ptr, unsigned int));
+ break;
- case 's':
- output_add_string (buffer,
- va_arg (output_buffer_format_args (buffer),
- const char *));
- break;
+ case 's':
+ output_add_string (buffer, va_arg (*text->args_ptr, const char *));
+ break;
- case 'u':
- if (long_integer)
- output_long_unsigned_decimal
- (buffer, va_arg (output_buffer_format_args (buffer),
- long unsigned int));
- else
- output_unsigned_decimal
- (buffer, va_arg (output_buffer_format_args (buffer),
- unsigned int));
- break;
-
- case 'x':
- if (long_integer)
- output_long_hexadecimal
- (buffer, va_arg (output_buffer_format_args (buffer),
- unsigned long int));
- else
- output_hexadecimal
- (buffer, va_arg (output_buffer_format_args (buffer),
- unsigned int));
+ case 'p':
+ output_pointer (buffer, va_arg (*text->args_ptr, void *));
break;
- case '%':
- output_add_character (buffer, '%');
- break;
+ case 'u':
+ if (long_integer)
+ output_long_unsigned_decimal
+ (buffer, va_arg (*text->args_ptr, long unsigned int));
+ else
+ output_unsigned_decimal
+ (buffer, va_arg (*text->args_ptr, unsigned int));
+ break;
+
+ case 'x':
+ if (long_integer)
+ output_long_hexadecimal
+ (buffer, va_arg (*text->args_ptr, unsigned long int));
+ else
+ output_hexadecimal
+ (buffer, va_arg (*text->args_ptr, unsigned int));
+ break;
+
+ case '%':
+ output_add_character (buffer, '%');
+ break;
- case '.':
+ case 'H':
{
- int n;
- const char *s;
- /* We handle no precision specifier but `%.*s'. */
- if (*++output_buffer_text_cursor (buffer) != '*')
- abort ();
- else if (*++output_buffer_text_cursor (buffer) != 's')
- abort ();
- n = va_arg (output_buffer_format_args (buffer), int);
- s = va_arg (output_buffer_format_args (buffer), const char *);
- output_append (buffer, s, s + n);
+ const location_t *locus = va_arg (*text->args_ptr, location_t *);
+ output_add_string (buffer, "file '");
+ output_add_string (buffer, locus->file);
+ output_add_string (buffer, "', line ");
+ output_decimal (buffer, locus->line);
}
break;
- default:
- if (!buffer->format_decoder || !(*buffer->format_decoder) (buffer))
- {
- /* Hmmm. The front-end failed to install a format translator
+ case '.':
+ {
+ int n;
+ const char *s;
+ /* We handle no precision specifier but `%.*s'. */
+ if (*++text->format_spec != '*')
+ abort ();
+ else if (*++text->format_spec != 's')
+ abort ();
+ n = va_arg (*text->args_ptr, int);
+ s = va_arg (*text->args_ptr, const char *);
+ output_append (buffer, s, s + n);
+ }
+ break;
+
+ default:
+ if (!buffer->format_decoder
+ || !(*buffer->format_decoder) (buffer, text))
+ {
+ /* Hmmm. The front-end failed to install a format translator
but called us with an unrecognized format. Sorry. */
- abort ();
- }
- }
+ abort ();
+ }
+ }
}
}
@@ -753,7 +641,6 @@ vbuild_message_string (msg, ap)
/* Return a malloc'd string containing MSG formatted a la
printf. The caller is responsible for freeing the memory. */
-
static char *
build_message_string VPARAMS ((const char *msg, ...))
{
@@ -769,33 +656,7 @@ build_message_string VPARAMS ((const char *msg, ...))
return str;
}
-/* Return a malloc'd string describing a location. The caller is
- responsible for freeing the memory. */
-
-char *
-context_as_prefix (file, line, warn)
- const char *file;
- int line;
- int warn;
-{
- if (file)
- {
- if (warn)
- return build_message_string (_("%s:%d: warning: "), file, line);
- else
- return build_message_string ("%s:%d: ", file, line);
- }
- else
- {
- if (warn)
- return build_message_string (_("%s: warning: "), progname);
- else
- return build_message_string ("%s: ", progname);
- }
-}
-
-/* Same as context_as_prefix, but only the source FILE is given. */
-
+/* Same as diagnsotic_build_prefix, but only the source FILE is given. */
char *
file_name_as_prefix (f)
const char *f;
@@ -803,52 +664,34 @@ file_name_as_prefix (f)
return build_message_string ("%s: ", f);
}
-/* Format a MESSAGE into BUFFER. Automatically wrap lines. */
-
-static void
-output_do_printf (buffer, msg)
- output_buffer *buffer;
- const char *msg;
-{
- char *message = vbuild_message_string (msg,
- output_buffer_format_args (buffer));
-
- wrap_text (buffer, message, message + strlen (message));
- free (message);
-}
-
-
/* Format a message into BUFFER a la printf. */
-
void
output_printf VPARAMS ((struct output_buffer *buffer, const char *msgid, ...))
{
- va_list *old_args;
-
+ text_info text;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, output_buffer *, buffer);
VA_FIXEDARG (ap, const char *, msgid);
- old_args = output_buffer_ptr_to_format_args (buffer);
- output_buffer_ptr_to_format_args (buffer) = &ap;
- output_do_printf (buffer, _(msgid));
- output_buffer_ptr_to_format_args (buffer) = old_args;
+ text.args_ptr = &ap;
+ text.format_spec = _(msgid);
+ output_format (buffer, &text);
VA_CLOSE (ap);
}
/* Print a message relevant to the given DECL. */
-
static void
-format_with_decl (buffer, decl)
+format_with_decl (buffer, text, decl)
output_buffer *buffer;
+ text_info *text;
tree decl;
{
const char *p;
-
+
/* Do magic to get around lack of varargs support for insertion
of arguments into existing list. We know that the decl is first;
we ass_u_me that it will be printed with "%s". */
- for (p = output_buffer_text_cursor (buffer); *p; ++p)
+ for (p = text->format_spec; *p; ++p)
{
if (*p == '%')
{
@@ -862,12 +705,12 @@ format_with_decl (buffer, decl)
}
/* Print the left-hand substring. */
- maybe_wrap_text (buffer, output_buffer_text_cursor (buffer), p);
-
+ maybe_wrap_text (buffer, text->format_spec, p);
+
if (*p == '%') /* Print the name. */
{
const char *const n = (DECL_NAME (decl)
- ? (*decl_printable_name) (decl, 2)
+ ? (*lang_hooks.decl_printable_name) (decl, 2)
: _("((anonymous))"));
output_add_string (buffer, n);
while (*p)
@@ -880,76 +723,220 @@ format_with_decl (buffer, decl)
if (*p) /* Print the rest of the message. */
{
- output_buffer_text_cursor (buffer) = p;
- output_format (buffer);
+ text->format_spec = p;
+ output_format (buffer, text);
}
}
+/* Flush the content of BUFFER onto the attached stream. */
+static void
+output_flush (buffer)
+ output_buffer *buffer;
+{
+ output_buffer_to_stream (buffer);
+ output_clear_data (buffer);
+ fputc ('\n', output_buffer_attached_stream (buffer));
+ fflush (output_buffer_attached_stream (buffer));
+}
+
+/* Helper subroutine of output_verbatim and verbatim. Do the appropriate
+ settings needed by BUFFER for a verbatim formatting. */
+static void
+output_do_verbatim (buffer, text)
+ output_buffer *buffer;
+ text_info *text;
+{
+ diagnostic_prefixing_rule_t rule = output_prefixing_rule (buffer);
+ int line_cutoff = output_line_cutoff (buffer);
+
+ /* Set verbatim mode. */
+ output_prefixing_rule (buffer) = DIAGNOSTICS_SHOW_PREFIX_NEVER;
+ output_line_cutoff (buffer) = 0;
+ /* Do the actual formatting. */
+ output_format (buffer, text);
+ /* Restore previous settings. */
+ output_prefixing_rule (buffer) = rule;
+ output_line_cutoff (buffer) = line_cutoff;
+}
+
+/* Output MESSAGE verbatim into BUFFER. */
+void
+output_verbatim VPARAMS ((output_buffer *buffer, const char *msgid, ...))
+{
+ text_info text;
+ VA_OPEN (ap, msgid);
+ VA_FIXEDARG (ap, output_buffer *, buffer);
+ VA_FIXEDARG (ap, const char *, msgid);
+
+ text.format_spec = msgid;
+ text.args_ptr = &ap;
+ output_do_verbatim (buffer, &text);
+ VA_CLOSE (ap);
+}
+
+
+/* Initialize the diagnostic message outputting machinery. */
+void
+diagnostic_initialize (context)
+ diagnostic_context *context;
+{
+ memset (context, 0, sizeof *context);
+ obstack_init (&context->buffer.obstack);
+
+ /* By default, diagnostics are sent to stderr. */
+ output_buffer_attached_stream (&context->buffer) = stderr;
+
+ /* By default, we emit prefixes once per message. */
+ diagnostic_prefixing_rule (context) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
+
+ diagnostic_starter (context) = default_diagnostic_starter;
+ diagnostic_finalizer (context) = default_diagnostic_finalizer;
+ context->warnings_are_errors_message = warnings_are_errors;
+}
+
+/* Returns true if the next format specifier in TEXT is a format specifier
+ for a location_t. If so, update the object pointed by LOCUS to reflect
+ the specified location in *TEXT->args_ptr. */
+static bool
+text_specifies_location (text, locus)
+ text_info *text;
+ location_t *locus;
+{
+ const char *p;
+ /* Skip any leading text. */
+ for (p = text->format_spec; *p && *p != '%'; ++p)
+ ;
+
+ /* Extract the location information if any. */
+ if (*p == '%' && *++p == 'H')
+ {
+ *locus = *va_arg (*text->args_ptr, location_t *);
+ text->format_spec = p + 1;
+ return true;
+ }
+
+ return false;
+}
+
+void
+diagnostic_set_info (diagnostic, msgid, args, file, line, kind)
+ diagnostic_info *diagnostic;
+ const char *msgid;
+ va_list *args;
+ const char *file;
+ int line;
+ diagnostic_t kind;
+{
+ diagnostic->message.format_spec = msgid;
+ diagnostic->message.args_ptr = args;
+ /* If the diagnostic message doesn't specify a loccation,
+ use FILE and LINE. */
+ if (!text_specifies_location (&diagnostic->message, &diagnostic->location))
+ {
+ diagnostic->location.file = file;
+ diagnostic->location.line = line;
+ }
+ diagnostic->kind = kind;
+}
+
+/* Return a malloc'd string describing a location. The caller is
+ responsible for freeing the memory. */
+char *
+diagnostic_build_prefix (diagnostic)
+ diagnostic_info *diagnostic;
+{
+ static const char *const diagnostic_kind_text[] = {
+#define DEFINE_DIAGNOSTIC_KIND(K, T) (T),
+#include "diagnostic.def"
+#undef DEFINE_DIAGNOSTIC_KIND
+ "must-not-happen"
+ };
+ if (diagnostic->kind >= DK_LAST_DIAGNOSTIC_KIND)
+ abort();
+
+ return diagnostic->location.file
+ ? build_message_string ("%s:%d: %s",
+ diagnostic->location.file,
+ diagnostic->location.line,
+ _(diagnostic_kind_text[diagnostic->kind]))
+ : build_message_string ("%s: %s", progname,
+ _(diagnostic_kind_text[diagnostic->kind]));
+}
/* Report a diagnostic MESSAGE at the declaration DECL.
MSG is a format string which uses %s to substitute the declaration
name; subsequent substitutions are a la output_format. */
-
static void
-diagnostic_for_decl (decl, msgid, args_ptr, warn)
+diagnostic_for_decl (diagnostic, decl)
+ diagnostic_info *diagnostic;
tree decl;
- const char *msgid;
- va_list *args_ptr;
- int warn;
{
- output_state os;
+ if (global_dc->lock++)
+ error_recursion (global_dc);
- if (diagnostic_lock++)
- error_recursion ();
-
- if (count_error (warn))
+ if (diagnostic_count_diagnostic (global_dc, diagnostic->kind))
{
- os = output_buffer_state (diagnostic_buffer);
- report_error_function (DECL_SOURCE_FILE (decl));
+ diagnostic_report_current_function (global_dc);
output_set_prefix
- (diagnostic_buffer, context_as_prefix
- (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl), warn));
- output_buffer_ptr_to_format_args (diagnostic_buffer) = args_ptr;
- output_buffer_text_cursor (diagnostic_buffer) = _(msgid);
- format_with_decl (diagnostic_buffer, decl);
- diagnostic_finish ((output_buffer *) global_dc);
- output_destroy_prefix (diagnostic_buffer);
-
- output_buffer_state (diagnostic_buffer) = os;
+ (&global_dc->buffer, diagnostic_build_prefix (diagnostic));
+ format_with_decl (&global_dc->buffer, &diagnostic->message, decl);
+ output_flush (&global_dc->buffer);
+ output_destroy_prefix (&global_dc->buffer);
}
- diagnostic_lock--;
+ global_dc->lock--;
}
-
-/* Count an error or warning. Return 1 if the message should be printed. */
-
-int
-count_error (warningp)
- int warningp;
+void
+diagnostic_flush_buffer (context)
+ diagnostic_context *context;
{
- if (warningp && !diagnostic_report_warnings_p ())
- return 0;
+ output_buffer_to_stream (&context->buffer);
+ fflush (output_buffer_attached_stream (&context->buffer));
+}
- if (warningp && !warnings_are_errors)
- warningcount++;
- else
+/* Count a diagnostic. Return true if the message should be printed. */
+bool
+diagnostic_count_diagnostic (context, kind)
+ diagnostic_context *context;
+ diagnostic_t kind;
+{
+ switch (kind)
{
- static int warning_message = 0;
+ default:
+ abort();
+ break;
+
+ case DK_FATAL: case DK_ICE: case DK_SORRY:
+ case DK_ANACHRONISM: case DK_NOTE:
+ ++diagnostic_kind_count (context, kind);
+ break;
+
+ case DK_WARNING:
+ if (!diagnostic_report_warnings_p ())
+ return false;
+ else if (!warnings_are_errors)
+ {
+ ++diagnostic_kind_count (context, DK_WARNING);
+ break;
+ }
+ /* else fall through. */
- if (warningp && !warning_message)
- {
- verbatim ("%s: warnings being treated as errors\n", progname);
- warning_message = 1;
- }
- errorcount++;
+ case DK_ERROR:
+ if (kind == DK_WARNING && context->warnings_are_errors_message)
+ {
+ output_verbatim (&context->buffer,
+ "%s: warnings being treated as errors\n", progname);
+ context->warnings_are_errors_message = false;
+ }
+ ++diagnostic_kind_count (context, DK_ERROR);
+ break;
}
- return 1;
+ return true;
}
/* Print a diagnostic MSGID on FILE. This is just fprintf, except it
runs its second argument through gettext. */
-
void
fnotice VPARAMS ((FILE *file, const char *msgid, ...))
{
@@ -964,52 +951,49 @@ fnotice VPARAMS ((FILE *file, const char *msgid, ...))
/* Print a fatal I/O error message. Argument are like printf.
Also include a system error message based on `errno'. */
-
void
fatal_io_error VPARAMS ((const char *msgid, ...))
{
- output_state os;
-
+ text_info text;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
- os = output_buffer_state (diagnostic_buffer);
-
- output_printf (diagnostic_buffer, "%s: %s: ", progname, xstrerror (errno));
- output_buffer_ptr_to_format_args (diagnostic_buffer) = &ap;
- output_buffer_text_cursor (diagnostic_buffer) = _(msgid);
- output_format (diagnostic_buffer);
- diagnostic_finish ((output_buffer *) global_dc);
- output_buffer_state (diagnostic_buffer) = os;
+ text.format_spec = _(msgid);
+ text.args_ptr = &ap;
+ output_printf (&global_dc->buffer, "%s: %s: ", progname, xstrerror (errno));
+ output_format (&global_dc->buffer, &text);
+ output_flush (&global_dc->buffer);
VA_CLOSE (ap);
exit (FATAL_EXIT_CODE);
}
/* Issue a pedantic warning MSGID. */
-
void
pedwarn VPARAMS ((const char *msgid, ...))
{
- diagnostic_context dc;
-
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
- set_diagnostic_context
- (&dc, msgid, &ap, input_filename, lineno, !flag_pedantic_errors);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, _(msgid), &ap, input_filename, lineno,
+ pedantic_error_kind ());
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
}
-/* Issue a pedantic waring about DECL. */
-
+/* Issue a pedantic warning about DECL. */
void
pedwarn_with_decl VPARAMS ((tree decl, const char *msgid, ...))
{
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, tree, decl);
VA_FIXEDARG (ap, const char *, msgid);
+ diagnostic_set_info (&diagnostic, _(msgid), &ap,
+ DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl),
+ pedantic_error_kind ());
+
/* We don't want -pedantic-errors to cause the compilation to fail from
"errors" in system header files. Sometimes fixincludes can't fix what's
broken (eg: unsigned char bitfields - fixing it may change the alignment
@@ -1017,106 +1001,98 @@ pedwarn_with_decl VPARAMS ((tree decl, const char *msgid, ...))
or kernel uses the original layout). There's no point in issuing a
warning either, it's just unnecessary noise. */
if (!DECL_IN_SYSTEM_HEADER (decl))
- diagnostic_for_decl (decl, msgid, &ap, !flag_pedantic_errors);
+ diagnostic_for_decl (&diagnostic, decl);
VA_CLOSE (ap);
}
/* Same as above but within the context FILE and LINE. */
-
void
pedwarn_with_file_and_line VPARAMS ((const char *file, int line,
const char *msgid, ...))
{
- diagnostic_context dc;
-
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, file);
VA_FIXEDARG (ap, int, line);
VA_FIXEDARG (ap, const char *, msgid);
- set_diagnostic_context (&dc, msgid, &ap, file, line, !flag_pedantic_errors);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, _(msgid), &ap, file, line,
+ pedantic_error_kind ());
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
}
/* Just apologize with MSGID. */
-
void
sorry VPARAMS ((const char *msgid, ...))
{
- output_state os;
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
++sorrycount;
- os = output_buffer_state (diagnostic_buffer);
+ diagnostic_set_info (&diagnostic, _(msgid), &ap,
+ input_filename, lineno, DK_SORRY);
output_set_prefix
- (diagnostic_buffer, context_as_prefix (input_filename, lineno, 0));
- output_printf (diagnostic_buffer, "sorry, not implemented: ");
- output_buffer_ptr_to_format_args (diagnostic_buffer) = &ap;
- output_buffer_text_cursor (diagnostic_buffer) = _(msgid);
- output_format (diagnostic_buffer);
- diagnostic_finish ((output_buffer *) global_dc);
- output_buffer_state (diagnostic_buffer) = os;
+ (&global_dc->buffer, diagnostic_build_prefix (&diagnostic));
+ output_format (&global_dc->buffer, &diagnostic.message);
+ output_flush (&global_dc->buffer);
VA_CLOSE (ap);
}
/* Called when the start of a function definition is parsed,
this function prints on stderr the name of the function. */
-
void
announce_function (decl)
tree decl;
{
- if (! quiet_flag)
+ if (!quiet_flag)
{
if (rtl_dump_and_exit)
verbatim ("%s ", IDENTIFIER_POINTER (DECL_NAME (decl)));
else
- verbatim (" %s", (*decl_printable_name) (decl, 2));
+ verbatim (" %s", (*lang_hooks.decl_printable_name) (decl, 2));
fflush (stderr);
- output_needs_newline (diagnostic_buffer) = 1;
- record_last_error_function ();
+ output_needs_newline (&global_dc->buffer) = true;
+ diagnostic_set_last_function (global_dc);
}
}
/* The default function to print out name of current function that caused
an error. */
-
void
-default_print_error_function (context, file)
+lhd_print_error_function (context, file)
diagnostic_context *context;
const char *file;
{
- if (error_function_changed ())
+ if (diagnostic_last_function_changed (context))
{
- char *prefix = file ? build_message_string ("%s: ", file) : NULL;
- output_state os;
+ const char *old_prefix = output_prefix (&context->buffer);
+ char *new_prefix = file ? build_message_string ("%s: ", file) : NULL;
+
+ output_set_prefix (&context->buffer, new_prefix);
- os = output_buffer_state (context);
- output_set_prefix ((output_buffer *) context, prefix);
-
if (current_function_decl == NULL)
- output_add_string ((output_buffer *) context, _("At top level:"));
+ output_add_string (&context->buffer, _("At top level:"));
else
{
if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE)
- output_printf
- ((output_buffer *) context, "In member function `%s':",
- (*decl_printable_name) (current_function_decl, 2));
+ output_printf
+ (&context->buffer, "In member function `%s':",
+ (*lang_hooks.decl_printable_name) (current_function_decl, 2));
else
- output_printf
- ((output_buffer *) context, "In function `%s':",
- (*decl_printable_name) (current_function_decl, 2));
+ output_printf
+ (&context->buffer, "In function `%s':",
+ (*lang_hooks.decl_printable_name) (current_function_decl, 2));
}
- output_add_newline ((output_buffer *) context);
+ output_add_newline (&context->buffer);
- record_last_error_function ();
- output_buffer_to_stream ((output_buffer *) context);
- output_buffer_state (context) = os;
- free ((char*) prefix);
+ diagnostic_set_last_function (context);
+ output_buffer_to_stream (&context->buffer);
+ context->buffer.state.prefix = old_prefix;
+ free ((char*) new_prefix);
}
}
@@ -1125,37 +1101,41 @@ default_print_error_function (context, file)
We ignore the FILE parameter, as it cannot be relied upon. */
void
-report_error_function (file)
- const char *file ATTRIBUTE_UNUSED;
+diagnostic_report_current_function (context)
+ diagnostic_context *context;
{
- report_problematic_module ((output_buffer *) global_dc);
- (*print_error_function) (global_dc, input_filename);
+ diagnostic_report_current_module (context);
+ (*lang_hooks.print_error_function) (context, input_filename);
}
void
error_with_file_and_line VPARAMS ((const char *file, int line,
const char *msgid, ...))
{
- diagnostic_context dc;
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, file);
VA_FIXEDARG (ap, int, line);
VA_FIXEDARG (ap, const char *, msgid);
- set_diagnostic_context (&dc, msgid, &ap, file, line, /* warn = */ 0);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, msgid, &ap, file, line, DK_ERROR);
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
}
void
error_with_decl VPARAMS ((tree decl, const char *msgid, ...))
{
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, tree, decl);
VA_FIXEDARG (ap, const char *, msgid);
- diagnostic_for_decl (decl, msgid, &ap, /* warn = */ 0);
+ diagnostic_set_info (&diagnostic, msgid, &ap,
+ DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl),
+ DK_ERROR);
+ diagnostic_for_decl (&diagnostic, decl);
VA_CLOSE (ap);
}
@@ -1165,14 +1145,14 @@ error_with_decl VPARAMS ((tree decl, const char *msgid, ...))
void
error VPARAMS ((const char *msgid, ...))
{
- diagnostic_context dc;
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
- set_diagnostic_context
- (&dc, msgid, &ap, input_filename, lineno, /* warn = */ 0);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, msgid, &ap, input_filename, lineno,
+ DK_ERROR);
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
}
@@ -1182,44 +1162,30 @@ error VPARAMS ((const char *msgid, ...))
void
fatal_error VPARAMS ((const char *msgid, ...))
{
- diagnostic_context dc;
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
- set_diagnostic_context
- (&dc, msgid, &ap, input_filename, lineno, /* warn = */ 0);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, msgid, &ap, input_filename, lineno,
+ DK_FATAL);
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
fnotice (stderr, "compilation terminated.\n");
exit (FATAL_EXIT_CODE);
}
-/* Report a compiler error at the current line number. Allow a front end to
- intercept the message. */
-
-static void (*internal_error_function) PARAMS ((const char *, va_list *));
-
-/* Set the function to call when a compiler error occurs. */
-
-void
-set_internal_error_function (f)
- void (*f) PARAMS ((const char *, va_list *));
-{
- internal_error_function = f;
-}
-
void
internal_error VPARAMS ((const char *msgid, ...))
{
- diagnostic_context dc;
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
- if (diagnostic_lock)
- error_recursion ();
+ if (global_dc->lock)
+ error_recursion (global_dc);
#ifndef ENABLE_CHECKING
if (errorcount > 0 || sorrycount > 0)
@@ -1230,18 +1196,18 @@ internal_error VPARAMS ((const char *msgid, ...))
}
#endif
- if (internal_error_function != 0)
- (*internal_error_function) (_(msgid), &ap);
-
- set_diagnostic_context
- (&dc, msgid, &ap, input_filename, lineno, /* warn = */0);
- report_diagnostic (&dc);
+ if (global_dc->internal_error != 0)
+ (*global_dc->internal_error) (_(msgid), &ap);
+
+ diagnostic_set_info (&diagnostic, msgid, &ap, input_filename, lineno,
+ DK_ICE);
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
fnotice (stderr,
"Please submit a full bug report,\n\
with preprocessed source if appropriate.\n\
-See %s for instructions.\n", GCCBUGURL);
+See %s for instructions.\n", bug_report_url);
exit (FATAL_EXIT_CODE);
}
@@ -1249,99 +1215,61 @@ void
warning_with_file_and_line VPARAMS ((const char *file, int line,
const char *msgid, ...))
{
- diagnostic_context dc;
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, file);
VA_FIXEDARG (ap, int, line);
VA_FIXEDARG (ap, const char *, msgid);
- set_diagnostic_context (&dc, msgid, &ap, file, line, /* warn = */ 1);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, msgid, &ap, file, line, DK_WARNING);
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
}
void
warning_with_decl VPARAMS ((tree decl, const char *msgid, ...))
{
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, tree, decl);
VA_FIXEDARG (ap, const char *, msgid);
- diagnostic_for_decl (decl, msgid, &ap, /* warn = */ 1);
+ diagnostic_set_info (&diagnostic, msgid, &ap,
+ DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl),
+ DK_WARNING);
+ diagnostic_for_decl (&diagnostic, decl);
VA_CLOSE (ap);
}
void
warning VPARAMS ((const char *msgid, ...))
{
- diagnostic_context dc;
+ diagnostic_info diagnostic;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
- set_diagnostic_context
- (&dc, msgid, &ap, input_filename, lineno, /* warn = */ 1);
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, msgid, &ap, input_filename, lineno,
+ DK_WARNING);
+ report_diagnostic (&diagnostic);
VA_CLOSE (ap);
}
-/* Flush diagnostic_buffer content on stderr. */
-
-static void
-diagnostic_finish (buffer)
- output_buffer *buffer;
-{
- output_buffer_to_stream (buffer);
- clear_diagnostic_info (buffer);
- fputc ('\n', output_buffer_attached_stream (buffer));
- fflush (output_buffer_attached_stream (buffer));
-}
-
-/* Helper subroutine of output_verbatim and verbatim. Do the appropriate
- settings needed by BUFFER for a verbatim formatting. */
-
-static void
-output_do_verbatim (buffer, msgid, args_ptr)
- output_buffer *buffer;
- const char *msgid;
- va_list *args_ptr;
-{
- output_state os;
-
- os = output_buffer_state (buffer);
- output_prefix (buffer) = NULL;
- diagnostic_prefixing_rule (buffer) = DIAGNOSTICS_SHOW_PREFIX_NEVER;
- output_buffer_text_cursor (buffer) = _(msgid);
- output_buffer_ptr_to_format_args (buffer) = args_ptr;
- output_set_maximum_length (buffer, 0);
- output_format (buffer);
- output_buffer_state (buffer) = os;
-}
-
-/* Output MESSAGE verbatim into BUFFER. */
-
-void
-output_verbatim VPARAMS ((output_buffer *buffer, const char *msgid, ...))
-{
- VA_OPEN (ap, msgid);
- VA_FIXEDARG (ap, output_buffer *, buffer);
- VA_FIXEDARG (ap, const char *, msgid);
-
- output_do_verbatim (buffer, msgid, &ap);
- VA_CLOSE (ap);
-}
/* Same as above but use diagnostic_buffer. */
void
verbatim VPARAMS ((const char *msgid, ...))
{
+ text_info text;
VA_OPEN (ap, msgid);
VA_FIXEDARG (ap, const char *, msgid);
- output_do_verbatim (diagnostic_buffer, msgid, &ap);
- output_buffer_to_stream (diagnostic_buffer);
+ text.format_spec = _(msgid);
+ text.args_ptr = &ap;
+ output_do_verbatim (&global_dc->buffer, &text);
+ output_buffer_to_stream (&global_dc->buffer);
VA_CLOSE (ap);
}
@@ -1352,27 +1280,22 @@ verbatim VPARAMS ((const char *msgid, ...))
in the documentation of output_format. */
void
-report_diagnostic (dc)
- diagnostic_context *dc;
+diagnostic_report_diagnostic (context, diagnostic)
+ diagnostic_context *context;
+ diagnostic_info *diagnostic;
{
- output_state os;
-
- if (diagnostic_lock++)
- error_recursion ();
+ if (context->lock++)
+ error_recursion (context);
- if (count_error (diagnostic_is_warning (dc)))
+ if (diagnostic_count_diagnostic (context, diagnostic->kind))
{
- os = output_buffer_state (diagnostic_buffer);
- diagnostic_msg = diagnostic_message (dc);
- diagnostic_args = diagnostic_argument_list (dc);
- (*diagnostic_starter (dc)) (diagnostic_buffer, dc);
- output_format (diagnostic_buffer);
- (*diagnostic_finalizer (dc)) (diagnostic_buffer, dc);
- diagnostic_finish ((output_buffer *) global_dc);
- output_buffer_state (diagnostic_buffer) = os;
+ (*diagnostic_starter (context)) (context, diagnostic);
+ output_format (&context->buffer, &diagnostic->message);
+ (*diagnostic_finalizer (context)) (context, diagnostic);
+ output_flush (&context->buffer);
}
- diagnostic_lock--;
+ --context->lock;
}
/* Inform the user that an error occurred while trying to report some
@@ -1381,17 +1304,18 @@ report_diagnostic (dc)
This mustn't use internal_error, that will cause infinite recursion. */
static void
-error_recursion ()
+error_recursion (context)
+ diagnostic_context *context;
{
- if (diagnostic_lock < 3)
- diagnostic_finish ((output_buffer *) global_dc);
+ if (context->lock < 3)
+ output_flush (&context->buffer);
fnotice (stderr,
"Internal compiler error: Error reporting routines re-entered.\n");
fnotice (stderr,
"Please submit a full bug report,\n\
with preprocessed source if appropriate.\n\
-See %s for instructions.\n", GCCBUGURL);
+See %s for instructions.\n", bug_report_url);
exit (FATAL_EXIT_CODE);
}
@@ -1449,81 +1373,68 @@ fancy_abort (file, line, function)
int line;
const char *function;
{
- internal_error ("Internal compiler error in %s, at %s:%d",
- function, trim_filename (file), line);
+ internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
}
-/* Setup DC for reporting a diagnostic MESSAGE (an error or a WARNING),
- using arguments pointed to by ARGS_PTR, issued at a location specified
- by FILE and LINE. */
-
void
-set_diagnostic_context (dc, msgid, args_ptr, file, line, warn)
- diagnostic_context *dc;
- const char *msgid;
- va_list *args_ptr;
- const char *file;
- int line;
- int warn;
-{
- memset (dc, 0, sizeof (diagnostic_context));
- diagnostic_message (dc) = _(msgid);
- diagnostic_argument_list (dc) = args_ptr;
- diagnostic_file_location (dc) = file;
- diagnostic_line_location (dc) = line;
- diagnostic_is_warning (dc) = warn;
- diagnostic_starter (dc) = diagnostic_starter (global_dc);
- diagnostic_finalizer (dc) = diagnostic_finalizer (global_dc);
-}
-
-void
-report_problematic_module (buffer)
- output_buffer *buffer;
+diagnostic_report_current_module (context)
+ diagnostic_context *context;
{
struct file_stack *p;
- if (output_needs_newline (buffer))
+ if (output_needs_newline (&context->buffer))
{
- output_add_newline (buffer);
- output_needs_newline (buffer) = 0;
+ output_add_newline (&context->buffer);
+ output_needs_newline (&context->buffer) = false;
}
if (input_file_stack && input_file_stack->next != 0
- && error_module_changed ())
+ && diagnostic_last_module_changed (context))
{
for (p = input_file_stack->next; p; p = p->next)
if (p == input_file_stack->next)
- output_verbatim
- (buffer, "In file included from %s:%d", p->name, p->line);
+ output_verbatim (&context->buffer,
+ "In file included from %s:%d", p->name, p->line);
else
- output_verbatim
- (buffer, ",\n from %s:%d", p->name, p->line);
- output_verbatim (buffer, ":\n");
- record_last_error_module ();
+ output_verbatim (&context->buffer,
+ ",\n from %s:%d", p->name, p->line);
+ output_verbatim (&context->buffer, ":\n");
+ diagnostic_set_last_module (context);
}
}
static void
-default_diagnostic_starter (buffer, dc)
- output_buffer *buffer;
- diagnostic_context *dc;
+default_diagnostic_starter (context, diagnostic)
+ diagnostic_context *context;
+ diagnostic_info *diagnostic;
{
- report_error_function (diagnostic_file_location (dc));
- output_set_prefix (buffer,
- context_as_prefix (diagnostic_file_location (dc),
- diagnostic_line_location (dc),
- diagnostic_is_warning (dc)));
+ diagnostic_report_current_function (context);
+ output_set_prefix (&context->buffer, diagnostic_build_prefix (diagnostic));
}
static void
-default_diagnostic_finalizer (buffer, dc)
- output_buffer *buffer;
- diagnostic_context *dc __attribute__((__unused__));
+default_diagnostic_finalizer (context, diagnostic)
+ diagnostic_context *context;
+ diagnostic_info *diagnostic __attribute__((unused));
+{
+ output_destroy_prefix (&context->buffer);
+}
+
+void
+inform VPARAMS ((const char *msgid, ...))
{
- output_destroy_prefix (buffer);
+ diagnostic_info diagnostic;
+
+ VA_OPEN (ap, msgid);
+ VA_FIXEDARG (ap, const char *, msgid);
+
+ diagnostic_set_info (&diagnostic, msgid, &ap, input_filename, lineno,
+ DK_NOTE);
+ report_diagnostic (&diagnostic);
+ VA_CLOSE (ap);
}
-void
+void
warn_deprecated_use (node)
tree node;
{
@@ -1544,7 +1455,7 @@ warn_deprecated_use (node)
else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
&& DECL_NAME (TYPE_NAME (node)))
what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node)));
-
+
if (what)
{
if (decl)
diff --git a/contrib/gcc/diagnostic.def b/contrib/gcc/diagnostic.def
index 07aa495..83e5d9c 100644
--- a/contrib/gcc/diagnostic.def
+++ b/contrib/gcc/diagnostic.def
@@ -1,7 +1,9 @@
-DEFINE_DIAGNOSTIC_KIND (DK_FATAL, "Fatal error: ")
-DEFINE_DIAGNOSTIC_KIND (DK_ICE, "Internal compiler error: ")
-DEFINE_DIAGNOSTIC_KIND (DK_SORRY, "Sorry, unimplemented: ")
-DEFINE_DIAGNOSTIC_KIND (DK_ERROR, "Error: ")
-DEFINE_DIAGNOSTIC_KIND (DK_WARNING, "Warning: ")
-DEFINE_DIAGNOSTIC_KIND (DK_ANACHRONISM, "Anachronism: ")
-DEFINE_DIAGNOSTIC_KIND (DK_NOTE, "Note: ")
+DEFINE_DIAGNOSTIC_KIND (DK_FATAL, "fatal error: ")
+DEFINE_DIAGNOSTIC_KIND (DK_ICE, "internal compiler error: ")
+DEFINE_DIAGNOSTIC_KIND (DK_SORRY, "sorry, unimplemented: ")
+DEFINE_DIAGNOSTIC_KIND (DK_ERROR, "error: ")
+DEFINE_DIAGNOSTIC_KIND (DK_WARNING, "warning: ")
+DEFINE_DIAGNOSTIC_KIND (DK_ANACHRONISM, "anachronism: ")
+DEFINE_DIAGNOSTIC_KIND (DK_NOTE, "note: ")
+DEFINE_DIAGNOSTIC_KIND (DK_DEBUG, "debug: ")
+
diff --git a/contrib/gcc/diagnostic.h b/contrib/gcc/diagnostic.h
index c864405..e088891 100644
--- a/contrib/gcc/diagnostic.h
+++ b/contrib/gcc/diagnostic.h
@@ -23,14 +23,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define GCC_DIAGNOSTIC_H
#include "obstack.h"
+#include "location.h"
-/* Forward declarations. */
-typedef struct output_buffer output_buffer;
-typedef struct diagnostic_context diagnostic_context;
-typedef void (*diagnostic_starter_fn) PARAMS ((output_buffer *,
- diagnostic_context *));
-typedef diagnostic_starter_fn diagnostic_finalizer_fn;
+/* The type of a text to be formatted according a format specification
+ along with a list of things. */
+typedef struct
+{
+ const char *format_spec;
+ va_list *args_ptr;
+} text_info;
+/* Contants used to discreminate diagnostics. */
typedef enum
{
#define DEFINE_DIAGNOSTIC_KIND(K, M) K,
@@ -39,6 +42,17 @@ typedef enum
DK_LAST_DIAGNOSTIC_KIND
} diagnostic_t;
+/* A diagnostic is described by the MESSAGE to send, the FILE and LINE of
+ its context and its KIND (ice, error, warning, note, ...) See complete
+ list in diagnostic.def. */
+typedef struct
+{
+ text_info message;
+ location_t location;
+ /* The kind of diagnostic it is about. */
+ diagnostic_t kind;
+} diagnostic_info;
+
#define pedantic_error_kind() (flag_pedantic_errors ? DK_ERROR : DK_WARNING)
/* How often diagnostics are prefixed by their locations:
@@ -53,11 +67,6 @@ typedef enum
DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE = 0x2
} diagnostic_prefixing_rule_t;
-/* The type of front-end specific hook that formats trees into an
- output_buffer. A language specific printer returns a truth value if
- everything goes well. */
-typedef int (*printer_fn) PARAMS ((output_buffer *));
-
/* This data structure encapsulates an output_buffer's state. */
typedef struct
{
@@ -83,24 +92,18 @@ typedef struct
/* Current prefixing rule. */
diagnostic_prefixing_rule_t prefixing_rule;
-
- /* The current char to output. Updated by front-end (*format_map) when
- it is called to report front-end printer for a specified format. */
- const char *cursor;
-
- /* A pointer to the variable argument-list for formatting. */
- va_list *format_args;
-
- /* The number of times we have issued diagnostics. */
- int diagnostic_count[DK_LAST_DIAGNOSTIC_KIND];
} output_state;
-/* The output buffer datatype. This is best seen as an abstract datatype. */
+/* The type of a hook that formats client-specific data (trees mostly) into
+ an output_buffer. A client-supplied formatter returns true if everything
+ goes well. */
+typedef struct output_buffer output_buffer;
+typedef bool (*printer_fn) PARAMS ((output_buffer *, text_info *));
+
+/* The output buffer datatype. This is best seen as an abstract datatype
+ whose fields should not be accessed directly by clients. */
struct output_buffer
{
- /* Internal data. These fields should not be accessed directly by
- front-ends. */
-
/* The current state of the buffer. */
output_state state;
@@ -117,46 +120,60 @@ struct output_buffer
floating-point value. */
char digit_buffer[128];
-/* If non-NULL, this function formats data in the BUFFER. When called,
- output_buffer_text_cursor (BUFFER) points to a format code.
- FORMAT_DECODER should call output_add_string (and related functions)
- to add data to the BUFFER. FORMAT_DECODER can read arguments from
- output_buffer_format_args (BUFFER) using VA_ARG. If the BUFFER needs
- additional characters from the format string, it should advance
- the output_buffer_text_cursor (BUFFER) as it goes. When FORMAT_DECODER
- returns, output_buffer_text_cursor (BUFFER) should point to the last
- character processed. */
-
+ /* If non-NULL, this function formats a TEXT into the BUFFER. When called,
+ TEXT->format_spec points to a format code. FORMAT_DECODER should call
+ output_add_string (and related functions) to add data to the BUFFER.
+ FORMAT_DECODER can read arguments from *TEXT->args_pts using VA_ARG.
+ If the BUFFER needs additional characters from the format string, it
+ should advance the TEXT->format_spec as it goes. When FORMAT_DECODER
+ returns, TEXT->format_spec should point to the last character processed.
+ */
printer_fn format_decoder;
-};
+} ;
-/* Current state of the diagnostic_context' output_buffer. This macro
- accepts both `diagnostic_context *' and `output_buffer *'. */
-#define output_buffer_state(BUFFER) ((output_buffer *)(BUFFER))->state
+#define output_prefix(BUFFER) (BUFFER)->state.prefix
/* The stream attached to the output_buffer, where the formatted
diagnostics will ultimately go. Works only on `output_buffer *'. */
#define output_buffer_attached_stream(BUFFER) (BUFFER)->stream
-/* This points to the beginning of the rest of the diagnostic message
- to be formatted. Accepts only `output_buffer *'s. */
-#define output_buffer_text_cursor(BUFFER) (BUFFER)->state.cursor
-
-/* The rest of the `variable argument list' not yet processed.
- This macro works on both `output_state *' and `output_buffer *'. */
-#define output_buffer_format_args(BUFFER) \
- *(((output_state *)(BUFFER))->format_args)
-
/* In line-wrapping mode, whether we should start a new line. */
#define output_needs_newline(BUFFER) (BUFFER)->state.need_newline_p
/* The amount of whitespace to be emitted when starting a new line. */
#define output_indentation(BUFFER) (BUFFER)->state.indent_skip
-/* A pointer to the formatted diagonstic message. */
+/* A pointer to the formatted diagnostic message. */
#define output_message_text(BUFFER) \
((const char *) obstack_base (&(BUFFER)->obstack))
+/* Client supplied function used to decode formats. */
+#define output_format_decoder(BUFFER) (BUFFER)->format_decoder
+
+/* Prefixing rule used in formatting a diagnostic message. */
+#define output_prefixing_rule(BUFFER) (BUFFER)->state.prefixing_rule
+
+/* Maximum characters per line in automatic line wrapping mode.
+ Zero means don't wrap lines. */
+#define output_line_cutoff(BUFFER) (BUFFER)->state.ideal_maximum_length
+
+/* True if BUFFER is in line-wrapping mode. */
+#define output_is_line_wrapping(BUFFER) (output_line_cutoff (BUFFER) > 0)
+
+#define output_formatted_scalar(BUFFER, FORMAT, INTEGER) \
+ do \
+ { \
+ sprintf ((BUFFER)->digit_buffer, FORMAT, INTEGER); \
+ output_add_string (BUFFER, (BUFFER)->digit_buffer); \
+ } \
+ while (0)
+
+/* Forward declarations. */
+typedef struct diagnostic_context diagnostic_context;
+typedef void (*diagnostic_starter_fn) PARAMS ((diagnostic_context *,
+ diagnostic_info *));
+typedef diagnostic_starter_fn diagnostic_finalizer_fn;
+
/* This data structure bundles altogether any information relevant to
the context of a diagnostic message. */
struct diagnostic_context
@@ -166,21 +183,12 @@ struct diagnostic_context
output_buffer. */
output_buffer buffer;
- /* The diagnostic message to output. */
- const char *message;
-
- /* A pointer to a variable list of the arguments necessary for the
- purpose of message formatting. */
- va_list *args_ptr;
-
- /* The name of the source file involved in the diiagnostic. */
- const char *file;
-
- /* The line-location in the source file. */
- int line;
+ /* The number of times we have issued diagnostics. */
+ int diagnostic_count[DK_LAST_DIAGNOSTIC_KIND];
- /* Is this message a warning? */
- int warn;
+ /* True if we should display the "warnings are being tread as error"
+ message, usually displayed once per compiler run. */
+ bool warnings_are_errors_message;
/* This function is called before any message is printed out. It is
responsible for preparing message prefix and such. For example, it
@@ -189,30 +197,27 @@ struct diagnostic_context
from "/home/gdr/src/nifty_printer.h:56:
...
*/
- void (*begin_diagnostic) PARAMS ((output_buffer *, diagnostic_context *));
+ diagnostic_starter_fn begin_diagnostic;
/* This function is called after the diagnostic message is printed. */
- void (*end_diagnostic) PARAMS ((output_buffer *, diagnostic_context *));
+ diagnostic_finalizer_fn end_diagnostic;
- /* Hook for front-end extensions. */
- void *x_data;
-};
-
-/* The diagnostic message being formatted. */
-#define diagnostic_message(DC) (DC)->message
-
-/* A pointer to the variable argument list used in a call
- to a diagonstic routine. */
-#define diagnostic_argument_list(DC) (DC)->args_ptr
+ /* Client hook to report an internal error. */
+ void (*internal_error) PARAMS ((const char *, va_list *));
-/* The program file to which the diagnostic is referring to. */
-#define diagnostic_file_location(DC) (DC)->file
+ /* Function of last diagnostic message; more generally, function such that
+ if next diagnostic message is in it then we don't have to mention the
+ function name. */
+ tree last_function;
-/* The program source line referred to in the diagnostic message. */
-#define diagnostic_line_location(DC) (DC)->line
+ /* Used to detect when input_file_stack has changed since last described. */
+ int last_module;
-/* Tell whether the diagnostic message is to be treated as a warning. */
-#define diagnostic_is_warning(DC) (DC)->warn
+ int lock;
+
+ /* Hook for front-end extensions. */
+ void *x_data;
+};
/* Client supplied function to announce a diagnostic. */
#define diagnostic_starter(DC) (DC)->begin_diagnostic
@@ -224,60 +229,78 @@ struct diagnostic_context
/* Extension hook for client. */
#define diagnostic_auxiliary_data(DC) (DC)->x_data
-/* Client supplied function used to decode formats. Can operate on both
- `output_buffer *' and `diagnostic_context *'. */
-#define diagnostic_format_decoder(DC) ((output_buffer *)(DC))->format_decoder
+/* Same as output_format_decoder. Works on 'diagnostic_context *'. */
+#define diagnostic_format_decoder(DC) output_format_decoder (&(DC)->buffer)
-/* Prefixing rule used in formatting a diagnostic message. Accepts both
- `output_buffer *' and `diagnostic_context *'. */
-#define diagnostic_prefixing_rule(DC) \
- ((output_buffer *)(DC))->state.prefixing_rule
+/* Same as output_prefixing_rule. Works on 'diagnostic_context *'. */
+#define diagnostic_prefixing_rule(DC) output_prefixing_rule (&(DC)->buffer)
/* Maximum characters per line in automatic line wrapping mode.
Zero means don't wrap lines. */
-#define diagnostic_line_cutoff(DC) \
- ((output_buffer *)(DC))->state.ideal_maximum_length
+#define diagnostic_line_cutoff(DC) output_line_cutoff (&(DC)->buffer)
-/* This diagnostic context is used by front-ends that directly output
+/* True if the last function in which a diagnostic was reported is
+ different from the current one. */
+#define diagnostic_last_function_changed(DC) \
+ ((DC)->last_function != current_function_decl)
+
+/* Remember the current function as being the last one in which we report
+ a diagnostic. */
+#define diagnostic_set_last_function(DC) \
+ (DC)->last_function = current_function_decl
+
+/* True if the last module or file in which a diagnostic was reported is
+ different from the current one. */
+#define diagnostic_last_module_changed(DC) \
+ ((DC)->last_module != input_file_stack_tick)
+
+/* Remember the current module or file as being the last one in which we
+ report a diagnostic. */
+#define diagnostic_set_last_module(DC) \
+ (DC)->last_module = input_file_stack_tick
+
+/* This diagnostic_context is used by front-ends that directly output
diagnostic messages without going through `error', `warning',
and similar functions. */
extern diagnostic_context *global_dc;
-/* This will be removed shortly. */
-extern output_buffer *diagnostic_buffer;
-
/* The total count of a KIND of diagnostics meitted so far. */
-#define diagnostic_kind_count(DC, DK) \
- ((output_buffer *)(DC))->state.diagnostic_count[(int) (DK)]
+#define diagnostic_kind_count(DC, DK) (DC)->diagnostic_count[(int) (DK)]
/* The number of errors that have been issued so far. Ideally, these
- would take an output_buffer as an argument. */
+ would take a diagnostic_context as an argument. */
#define errorcount diagnostic_kind_count (global_dc, DK_ERROR)
/* Similarly, but for warnings. */
#define warningcount diagnostic_kind_count (global_dc, DK_WARNING)
/* Similarly, but for sorrys. */
#define sorrycount diagnostic_kind_count (global_dc, DK_SORRY)
-/* Returns non-zero if warnings should be emitted. */
+/* Returns nonzero if warnings should be emitted. */
#define diagnostic_report_warnings_p() \
(!inhibit_warnings \
&& !(in_system_header && !warn_system_headers))
+#define report_diagnostic(D) diagnostic_report_diagnostic (global_dc, D)
-/* Prototypes */
-extern void set_diagnostic_context PARAMS ((diagnostic_context *,
- const char *, va_list *,
- const char *, int, int));
-extern void set_internal_error_function PARAMS ((void (*)
- PARAMS ((const char *,
- va_list *))));
-extern void report_diagnostic PARAMS ((diagnostic_context *));
+/* Dignostic related functions. */
extern void diagnostic_initialize PARAMS ((diagnostic_context *));
+extern void diagnostic_report_current_module PARAMS ((diagnostic_context *));
+extern void diagnostic_report_current_function PARAMS ((diagnostic_context *));
+extern void diagnostic_flush_buffer PARAMS ((diagnostic_context *));
+extern bool diagnostic_count_diagnostic PARAMS ((diagnostic_context *,
+ diagnostic_t));
+extern void diagnostic_report_diagnostic PARAMS ((diagnostic_context *,
+ diagnostic_info *));
+extern void diagnostic_set_info PARAMS ((diagnostic_info *,
+ const char *, va_list *,
+ const char *, int,
+ diagnostic_t));
+extern char *diagnostic_build_prefix PARAMS ((diagnostic_info *));
+
+/* Pure text formatting support functions. */
extern void init_output_buffer PARAMS ((output_buffer *,
const char *, int));
-extern void flush_diagnostic_buffer PARAMS ((void));
extern void output_clear PARAMS ((output_buffer *));
-extern const char *output_get_prefix PARAMS ((const output_buffer *));
extern const char *output_last_position PARAMS ((const output_buffer *));
extern void output_set_prefix PARAMS ((output_buffer *,
const char *));
@@ -293,29 +316,15 @@ extern void output_add_character PARAMS ((output_buffer *, int));
extern void output_decimal PARAMS ((output_buffer *, int));
extern void output_add_string PARAMS ((output_buffer *,
const char *));
+extern void output_add_identifier PARAMS ((output_buffer *, tree));
extern const char *output_finalize_message PARAMS ((output_buffer *));
extern void output_clear_message_text PARAMS ((output_buffer *));
extern void output_printf PARAMS ((output_buffer *, const char *,
...)) ATTRIBUTE_PRINTF_2;
-extern int output_is_line_wrapping PARAMS ((output_buffer *));
extern void output_verbatim PARAMS ((output_buffer *, const char *,
- ...)) ATTRIBUTE_PRINTF_2;
-extern void verbatim PARAMS ((const char *, ...))
- ATTRIBUTE_PRINTF_1;
-extern char *context_as_prefix PARAMS ((const char *, int, int));
+ ...));
+extern void verbatim PARAMS ((const char *, ...));
extern char *file_name_as_prefix PARAMS ((const char *));
-extern int error_module_changed PARAMS ((void));
-extern void record_last_error_module PARAMS ((void));
-extern int error_function_changed PARAMS ((void));
-extern void record_last_error_function PARAMS ((void));
-extern void report_problematic_module PARAMS ((output_buffer *));
-
-/* Called by report_error_function to print out function name.
- * Default may be overridden by language front-ends. */
-extern void (*print_error_function) PARAMS ((diagnostic_context *,
- const char *));
-
-extern void default_print_error_function PARAMS ((diagnostic_context *,
- const char *));
+extern void inform PARAMS ((const char *, ...));
#endif /* ! GCC_DIAGNOSTIC_H */
diff --git a/contrib/gcc/doc/bugreport.texi b/contrib/gcc/doc/bugreport.texi
index 1ac26c5..d9613ef 100644
--- a/contrib/gcc/doc/bugreport.texi
+++ b/contrib/gcc/doc/bugreport.texi
@@ -1,5 +1,5 @@
@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-@c 1999, 2000, 2001 Free Software Foundation, Inc.
+@c 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -14,29 +14,14 @@ When you encounter a problem, the first thing to do is to see if it is
already known. @xref{Trouble}. If it isn't known, then you should
report the problem.
-Reporting a bug may help you by bringing a solution to your problem, or
-it may not. (If it does not, look in the service directory; see
-@ref{Service}.) In any case, the principal function of a bug report is
-to help the entire community by making the next version of GCC work
-better. Bug reports are your contribution to the maintenance of GCC@.
-
-Since the maintainers are very overloaded, we cannot respond to every
-bug report. However, if the bug has not been fixed, we are likely to
-send you a patch and ask you to tell us whether it works.
-
-In order for a bug report to serve its purpose, you must include the
-information that makes for fixing the bug.
-
@menu
* Criteria: Bug Criteria. Have you really found a bug?
-* Where: Bug Lists. Where to send your bug report.
* Reporting: Bug Reporting. How to report a bug effectively.
-* GNATS: gccbug. You can use a bug reporting tool.
* Known: Trouble. Known problems.
* Help: Service. Where to ask for help.
@end menu
-@node Bug Criteria,Bug Lists,,Bugs
+@node Bug Criteria,Bug Reporting,,Bugs
@section Have You Found a Bug?
@cindex bug criteria
@@ -64,13 +49,9 @@ prevent the assembler from being run.
If the compiler produces valid assembly code that does not correctly
execute the input source code, that is a compiler bug.
-However, you must double-check to make sure, because you may have run
-into an incompatibility between GNU C and traditional C
-(@pxref{Incompatibilities}). These incompatibilities might be considered
-bugs, but they are inescapable consequences of valuable features.
-
-Or you may have a program whose behavior is undefined, which happened
-by chance to give the desired results with another C or C++ compiler.
+However, you must double-check to make sure, because you may have a
+program whose behavior is undefined, which happened by chance to give
+the desired results with another C or C++ compiler.
For example, in many nonoptimizing compilers, you can write @samp{x;}
at the end of a function instead of @samp{return x;}, with the same
@@ -103,292 +84,11 @@ If you are an experienced user of one of the languages GCC supports, your
suggestions for improvement of GCC are welcome in any case.
@end itemize
-@node Bug Lists,Bug Reporting,Bug Criteria,Bugs
-@section Where to Report Bugs
-@cindex bug report mailing lists
-@kindex gcc-bugs@@gcc.gnu.org or bug-gcc@@gnu.org
-Send bug reports for the GNU Compiler Collection to
-@email{gcc-bugs@@gcc.gnu.org}. In accordance with the GNU-wide
-convention, in which bug reports for tool ``foo'' are sent
-to @samp{bug-foo@@gnu.org}, the address @email{bug-gcc@@gnu.org}
-may also be used; it will forward to the address given above.
-
-Please read @uref{http://gcc.gnu.org/bugs.html} for additional and/or
-more up-to-date bug reporting instructions before you post a bug report.
-
-@node Bug Reporting,gccbug,Bug Lists,Bugs
-@section How to Report Bugs
+@node Bug Reporting,,Bug Criteria,Bugs
+@section How and where to Report Bugs
@cindex compiler bugs, reporting
-The fundamental principle of reporting bugs usefully is this:
-@strong{report all the facts}. If you are not sure whether to state a
-fact or leave it out, state it!
-
-Often people omit facts because they think they know what causes the
-problem and they conclude that some details don't matter. Thus, you might
-assume that the name of the variable you use in an example does not matter.
-Well, probably it doesn't, but one cannot be sure. Perhaps the bug is a
-stray memory reference which happens to fetch from the location where that
-name is stored in memory; perhaps, if the name were different, the contents
-of that location would fool the compiler into doing the right thing despite
-the bug. Play it safe and give a specific, complete example. That is the
-easiest thing for you to do, and the most helpful.
-
-Keep in mind that the purpose of a bug report is to enable someone to
-fix the bug if it is not known. It isn't very important what happens if
-the bug is already known. Therefore, always write your bug reports on
-the assumption that the bug is not known.
-
-Sometimes people give a few sketchy facts and ask, ``Does this ring a
-bell?'' This cannot help us fix a bug, so it is basically useless. We
-respond by asking for enough details to enable us to investigate.
-You might as well expedite matters by sending them to begin with.
-
-Try to make your bug report self-contained. If we have to ask you for
-more information, it is best if you include all the previous information
-in your response, as well as the information that was missing.
-
-Please report each bug in a separate message. This makes it easier for
-us to track which bugs have been fixed and to forward your bugs reports
-to the appropriate maintainer.
-
-To enable someone to investigate the bug, you should include all these
-things:
-
-@itemize @bullet
-@item
-The version of GCC@. You can get this by running it with the
-@option{-v} option.
-
-Without this, we won't know whether there is any point in looking for
-the bug in the current version of GCC@.
-
-@item
-A complete input file that will reproduce the bug. If the bug is in the
-C preprocessor, send a source file and any header files that it
-requires. If the bug is in the compiler proper (@file{cc1}), send the
-preprocessor output generated by adding @option{-save-temps} to the
-compilation command (@pxref{Debugging Options}). When you do this, use
-the same @option{-I}, @option{-D} or @option{-U} options that you used in
-actual compilation. Then send the @var{input}.i or @var{input}.ii files
-generated.
-
-A single statement is not enough of an example. In order to compile it,
-it must be embedded in a complete file of compiler input; and the bug
-might depend on the details of how this is done.
-
-Without a real example one can compile, all anyone can do about your bug
-report is wish you luck. It would be futile to try to guess how to
-provoke the bug. For example, bugs in register allocation and reloading
-frequently depend on every little detail of the function they happen in.
-
-Even if the input file that fails comes from a GNU program, you should
-still send the complete test case. Don't ask the GCC maintainers to
-do the extra work of obtaining the program in question---they are all
-overworked as it is. Also, the problem may depend on what is in the
-header files on your system; it is unreliable for the GCC maintainers
-to try the problem with the header files available to them. By sending
-CPP output, you can eliminate this source of uncertainty and save us
-a certain percentage of wild goose chases.
-
-@item
-The command arguments you gave GCC to compile that example
-and observe the bug. For example, did you use @option{-O}? To guarantee
-you won't omit something important, list all the options.
-
-If we were to try to guess the arguments, we would probably guess wrong
-and then we would not encounter the bug.
-
-@item
-The type of machine you are using, and the operating system name and
-version number.
-
-@item
-The operands you gave to the @code{configure} command when you installed
-the compiler.
-
-@item
-A complete list of any modifications you have made to the compiler
-source. (We don't promise to investigate the bug unless it happens in
-an unmodified compiler. But if you've made modifications and don't tell
-us, then you are sending us on a wild goose chase.)
-
-Be precise about these changes. A description in English is not
-enough---send a context diff for them.
-
-Adding files of your own (such as a machine description for a machine we
-don't support) is a modification of the compiler source.
-
-@item
-Details of any other deviations from the standard procedure for installing
-GCC@.
-
-@item
-A description of what behavior you observe that you believe is
-incorrect. For example, ``The compiler gets a fatal signal,'' or,
-``The assembler instruction at line 208 in the output is incorrect.''
-
-Of course, if the bug is that the compiler gets a fatal signal, then one
-can't miss it. But if the bug is incorrect output, the maintainer might
-not notice unless it is glaringly wrong. None of us has time to study
-all the assembler code from a 50-line C program just on the chance that
-one instruction might be wrong. We need @emph{you} to do this part!
-
-Even if the problem you experience is a fatal signal, you should still
-say so explicitly. Suppose something strange is going on, such as, your
-copy of the compiler is out of synch, or you have encountered a bug in
-the C library on your system. (This has happened!) Your copy might
-crash and the copy here would not. If you @i{said} to expect a crash,
-then when the compiler here fails to crash, we would know that the bug
-was not happening. If you don't say to expect a crash, then we would
-not know whether the bug was happening. We would not be able to draw
-any conclusion from our observations.
-
-If the problem is a diagnostic when compiling GCC with some other
-compiler, say whether it is a warning or an error.
-
-Often the observed symptom is incorrect output when your program is run.
-Sad to say, this is not enough information unless the program is short
-and simple. None of us has time to study a large program to figure out
-how it would work if compiled correctly, much less which line of it was
-compiled wrong. So you will have to do that. Tell us which source line
-it is, and what incorrect result happens when that line is executed. A
-person who understands the program can find this as easily as finding a
-bug in the program itself.
-
-@item
-If you send examples of assembler code output from GCC,
-please use @option{-g} when you make them. The debugging information
-includes source line numbers which are essential for correlating the
-output with the input.
-
-@item
-If you wish to mention something in the GCC source, refer to it by
-context, not by line number.
-
-The line numbers in the development sources don't match those in your
-sources. Your line numbers would convey no useful information to the
-maintainers.
-
-@item
-Additional information from a debugger might enable someone to find a
-problem on a machine which he does not have available. However, you
-need to think when you collect this information if you want it to have
-any chance of being useful.
-
-@cindex backtrace for bug reports
-For example, many people send just a backtrace, but that is never
-useful by itself. A simple backtrace with arguments conveys little
-about GCC because the compiler is largely data-driven; the same
-functions are called over and over for different RTL insns, doing
-different things depending on the details of the insn.
-
-Most of the arguments listed in the backtrace are useless because they
-are pointers to RTL list structure. The numeric values of the
-pointers, which the debugger prints in the backtrace, have no
-significance whatever; all that matters is the contents of the objects
-they point to (and most of the contents are other such pointers).
-
-In addition, most compiler passes consist of one or more loops that
-scan the RTL insn sequence. The most vital piece of information about
-such a loop---which insn it has reached---is usually in a local variable,
-not in an argument.
-
-@findex debug_rtx
-What you need to provide in addition to a backtrace are the values of
-the local variables for several stack frames up. When a local
-variable or an argument is an RTX, first print its value and then use
-the GDB command @code{pr} to print the RTL expression that it points
-to. (If GDB doesn't run on your machine, use your debugger to call
-the function @code{debug_rtx} with the RTX as an argument.) In
-general, whenever a variable is a pointer, its value is no use
-without the data it points to.
-@end itemize
-
-Here are some things that are not necessary:
-
-@itemize @bullet
-@item
-A description of the envelope of the bug.
-
-Often people who encounter a bug spend a lot of time investigating
-which changes to the input file will make the bug go away and which
-changes will not affect it.
-
-This is often time consuming and not very useful, because the way we
-will find the bug is by running a single example under the debugger with
-breakpoints, not by pure deduction from a series of examples. You might
-as well save your time for something else.
-
-Of course, if you can find a simpler example to report @emph{instead} of
-the original one, that is a convenience. Errors in the output will be
-easier to spot, running under the debugger will take less time, etc.
-Most GCC bugs involve just one function, so the most straightforward
-way to simplify an example is to delete all the function definitions
-except the one where the bug occurs. Those earlier in the file may be
-replaced by external declarations if the crucial function depends on
-them. (Exception: inline functions may affect compilation of functions
-defined later in the file.)
-
-However, simplification is not vital; if you don't want to do this,
-report the bug anyway and send the entire test case you used.
-
-@item
-In particular, some people insert conditionals @samp{#ifdef BUG} around
-a statement which, if removed, makes the bug not happen. These are just
-clutter; we won't pay any attention to them anyway. Besides, you should
-send us cpp output, and that can't have conditionals.
-
-@item
-A patch for the bug.
-
-A patch for the bug is useful if it is a good one. But don't omit the
-necessary information, such as the test case, on the assumption that a
-patch is all we need. We might see problems with your patch and decide
-to fix the problem another way, or we might not understand it at all.
-
-Sometimes with a program as complicated as GCC it is very hard to
-construct an example that will make the program follow a certain path
-through the code. If you don't send the example, we won't be able to
-construct one, so we won't be able to verify that the bug is fixed.
-
-And if we can't understand what bug you are trying to fix, or why your
-patch should be an improvement, we won't install it. A test case will
-help us to understand.
-
-See @uref{http://gcc.gnu.org/contribute.html}
-for guidelines on how to make it easy for us to
-understand and install your patches.
-
-@item
-A guess about what the bug is or what it depends on.
-
-Such guesses are usually wrong. Even I can't guess right about such
-things without first using the debugger to find the facts.
-
-@item
-A core dump file.
-
-We have no way of examining a core dump for your type of machine
-unless we have an identical system---and if we do have one,
-we should be able to reproduce the crash ourselves.
-@end itemize
-
-@node gccbug,, Bug Reporting, Bugs
-@section The gccbug script
-@cindex gccbug script
-
-To simplify creation of bug reports, and to allow better tracking of
-reports, we use the GNATS bug tracking system. Part of that system is
-the @code{gccbug} script. This is a Unix shell script, so you need a
-shell to run it. It is normally installed in the same directory where
-@code{gcc} is installed.
-
-The gccbug script is derived from send-pr, @pxref{using
-send-pr,,Creating new Problem Reports,send-pr,Reporting Problems}. When
-invoked, it starts a text editor so you can fill out the various fields
-of the report. When the you quit the editor, the report is automatically
-send to the bug reporting address.
-
-A number of fields in this bug report form are specific to GCC, and are
-explained at @uref{http://gcc.gnu.org/gnats.html}.
+Bugs should be reported to our bug database. Please refer to
+@uref{http://gcc.gnu.org/bugs.html} for up-to-date instructions how to
+submit bug reports. Copies of this file in HTML (@file{bugs.html}) and
+plain text (@file{BUGS}) are also part of GCC releases.
diff --git a/contrib/gcc/doc/c-tree.texi b/contrib/gcc/doc/c-tree.texi
index 35da90a..8f5a5bb 100644
--- a/contrib/gcc/doc/c-tree.texi
+++ b/contrib/gcc/doc/c-tree.texi
@@ -84,8 +84,8 @@ we will refer to trees in ordinary type, rather than in @code{this
font}, except when talking about the actual C type @code{tree}.
You can tell what kind of node a particular tree is by using the
-@code{TREE_CODE} macro. Many, many macros take a trees as input and
-return trees as output. However, most macros require a certain kinds of
+@code{TREE_CODE} macro. Many, many macros take trees as input and
+return trees as output. However, most macros require a certain kind of
tree node as input. In other words, there is a type-system for trees,
but it is not reflected in the C type-system.
@@ -1771,6 +1771,7 @@ This macro returns the attributes on the type @var{type}.
@tindex CLEANUP_POINT_EXPR
@tindex ARRAY_REF
@tindex VTABLE_REF
+@tindex VA_ARG_EXPR
The internal representation for expressions is for the most part quite
straightforward. However, there are a few facts that one must bear in
@@ -2062,7 +2063,7 @@ integral type.
The result of a @code{TRUNC_DIV_EXPR} is always rounded towards zero.
The @code{TRUNC_MOD_EXPR} of two operands @code{a} and @code{b} is
-always @code{a - a/b} where the division is as if computed by a
+always @code{a - (a/b)*b} where the division is as if computed by a
@code{TRUNC_DIV_EXPR}.
@item ARRAY_REF
@@ -2126,25 +2127,21 @@ These nodes represent @code{?:} expressions. The first operand
is of boolean or integral type. If it evaluates to a nonzero value,
the second operand should be evaluated, and returned as the value of the
expression. Otherwise, the third operand is evaluated, and returned as
-the value of the expression. As a GNU extension, the middle operand of
-the @code{?:} operator may be omitted in the source, like this:
-
-@example
-x ? : 3
-@end example
-@noindent
-which is equivalent to
-
-@example
-x ? x : 3
-@end example
-
-@noindent
-assuming that @code{x} is an expression without side-effects. However,
-in the case that the first operation causes side effects, the
-side-effects occur only once. Consumers of the internal representation
-do not need to worry about this oddity; the second operand will be
-always be present in the internal representation.
+the value of the expression.
+
+The second operand must have the same type as the entire expression,
+unless it unconditionally throws an exception or calls a noreturn
+function, in which case it should have void type. The same constraints
+apply to the third operand. This allows array bounds checks to be
+represented conveniently as @code{(i >= 0 && i < 10) ? i : abort()}.
+
+As a GNU extension, the C language front-ends allow the second
+operand of the @code{?:} operator may be omitted in the source.
+For example, @code{x ? : 3} is equivalent to @code{x ? x : 3},
+assuming that @code{x} is an expression without side-effects.
+In the tree representation, however, the second operand is always
+present, possibly protected by @code{SAVE_EXPR} if the first
+argument does cause side-effects.
@item CALL_EXPR
These nodes are used to represent calls to functions, including
@@ -2312,4 +2309,10 @@ The first operand is the expression that computes the vtable reference.
The second operand is the @code{VAR_DECL} of the vtable. The third
operand is an @code{INTEGER_CST} of the byte offset into the vtable.
+@item VA_ARG_EXPR
+This node is used to implement support for the C/C++ variable argument-list
+mechanism. It represents expressions like @code{va_arg (ap, type)}.
+Its @code{TREE_TYPE} yields the tree representation for @code{type} and
+its sole argument yields the representation for @code{ap}.
+
@end table
diff --git a/contrib/gcc/doc/collect2.texi b/contrib/gcc/doc/collect2.texi
index 2cd1d3c..a3d43b2 100644
--- a/contrib/gcc/doc/collect2.texi
+++ b/contrib/gcc/doc/collect2.texi
@@ -52,7 +52,7 @@ if specified.
@end itemize
``The compiler's search directories'' means all the directories where
-@code{gcc} searches for passes of the compiler. This includes
+@command{gcc} searches for passes of the compiler. This includes
directories that you specify with @option{-B}.
Cross-compilers search a little differently:
diff --git a/contrib/gcc/doc/compat.texi b/contrib/gcc/doc/compat.texi
index 3c2931b..274368a 100644
--- a/contrib/gcc/doc/compat.texi
+++ b/contrib/gcc/doc/compat.texi
@@ -130,11 +130,11 @@ C++ library. This requires specifying the location of the C++ library
header files when invoking the compiler whose usual library is not being
used. The location of GCC's C++ header files depends on how the GCC
build was configured, but can be seen by using the G++ @option{-v} option.
-With default configuration options for G++ 3.2 the compile line for a
+With default configuration options for G++ 3.3 the compile line for a
different C++ compiler needs to include
@example
- -I@var{gcc_install_directory}/include/c++/3.2
+ -I@var{gcc_install_directory}/include/c++/3.3
@end example
Similarly, compiling code with G++ that must use a C++ library other
diff --git a/contrib/gcc/doc/contrib.texi b/contrib/gcc/doc/contrib.texi
index 8cafaeb..1c3aa25 100644
--- a/contrib/gcc/doc/contrib.texi
+++ b/contrib/gcc/doc/contrib.texi
@@ -1,5 +1,5 @@
-@c Copyright (C) 1988,1989,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002
-@c Free Software Foundation, Inc.
+@c Copyright (C) 1988,1989,1992,1993,1994,1995,1996,1997,1998,1999,2000,
+@c 2001,2002,2003 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -10,8 +10,8 @@
The GCC project would like to thank its many contributors. Without them the
project would not have been nearly as successful as it has been. Any omissions
in this list are accidental. Feel free to contact
-@email{law@@redhat.com} if you have been left out
-or some of your contributions are not listed. Please keep this list in
+@email{law@@redhat.com} or @email{gerald@@pfeifer.com} if you have been left
+out or some of your contributions are not listed. Please keep this list in
alphabetical order.
@itemize @bullet
@@ -29,7 +29,7 @@ James van Artsdalen wrote the code that makes efficient use of
the Intel 80387 register stack.
@item
-Alasdair Baird for various bugfixes.
+Alasdair Baird for various bug fixes.
@item
Gerald Baumgartner added the signature extension to the C++ front end.
@@ -41,7 +41,14 @@ Godmar Back for his Java improvements and encouragement.
Scott Bambrough for help porting the Java compiler.
@item
-Jon Beniston for his Win32 port of Java.
+Wolfgang Bangerth for processing tons of bug reports.
+
+@item
+Jon Beniston for his Windows port of Java.
+
+@item
+Daniel Berlin for better DWARF2 support, faster/better optimizations,
+improved alias analysis, plus migrating us to Bugzilla.
@item
Geoff Berry for his Java object serialization work and various patches.
@@ -51,6 +58,9 @@ Eric Blake for helping to make GCJ and libgcj conform to the
specifications.
@item
+Segher Boessenkool for various fixes.
+
+@item
Hans-J. Boehm for his @uref{http://www.hpl.hp.com/personal/Hans_Boehm/gc/,,
garbage collector}, IA-64 libffi port, and other Java work.
@@ -59,6 +69,9 @@ Neil Booth for work on cpplib, lang hooks, debug hooks and other
miscellaneous clean-ups.
@item
+Eric Botcazou for fixing middle- and backend bugs left and right.
+
+@item
Per Bothner for his direction via the steering committee and various
improvements to our infrastructure for supporting new languages. Chill
front end implementation. Initial implementations of
@@ -105,7 +118,10 @@ John Carr for his alias work, SPARC hacking, infrastructure improvements,
previous contributions to the steering committee, loop optimizations, etc.
@item
-Steve Chamberlain for support for the Hitachi SH and H8 processors
+Stephane Carrez for 68HC11 and 68HC12 ports.
+
+@item
+Steve Chamberlain for support for the Renesas SH and H8 processors
and the PicoJava processor, and for GCJ config fixes.
@item
@@ -158,6 +174,10 @@ Russell Davidson for fstream and stringstream fixes in libstdc++.
Mo DeJong for GCJ and libgcj bug fixes.
@item
+DJ Delorie for the DJGPP port, build and libiberty maintenance, and
+various bug fixes.
+
+@item
Gabriel Dos Reis for contributions to g++, contributions and
maintenance of GCC diagnostics infrastructure, libstdc++-v3,
including valarray<>, complex<>, maintaining the numerics library
@@ -172,12 +192,16 @@ maintaining complex<>, sanity checking and disbursement, configuration
architecture, libio maintenance, and early math work.
@item
+Zdenek Dvorak for a new loop unroller and various fixes.
+
+@item
Richard Earnshaw for his ongoing work with the ARM@.
@item
David Edelsohn for his direction via the steering committee, ongoing work
-with the RS6000/PowerPC port, help cleaning up Haifa loop changes, and
-for doing the entire AIX port of libstdc++ with his bare hands.
+with the RS6000/PowerPC port, help cleaning up Haifa loop changes,
+doing the entire AIX port of libstdc++ with his bare hands, and for
+ensuring GCC properly keeps working on AIX.
@item
Kevin Ediger for the floating point formatting of num_put::do_put in
@@ -186,7 +210,7 @@ libstdc++.
@item
Phil Edwards for libstdc++ work including configuration hackery,
documentation maintainer, chief breaker of the web pages, the occasional
-iostream bugfix, and work on shared library symbol versioning.
+iostream bug fix, and work on shared library symbol versioning.
@item
Paul Eggert for random hacking all over GCC@.
@@ -199,6 +223,9 @@ configuration support for locales and fstream-related fixes.
Vadim Egorov for libstdc++ fixes in strings, streambufs, and iostreams.
@item
+Christian Ehrhardt for dealing with bug reports.
+
+@item
Ben Elliston for his work to move the Objective-C runtime into its
own subdirectory and for his work on autoconf.
@@ -210,17 +237,22 @@ Doug Evans for much of the global optimization framework, arc, m32r,
and SPARC work.
@item
+Christopher Faylor for his work on the Cygwin port and for caring and
+feeding the gcc.gnu.org box and saving its users tons of spam.
+
+@item
Fred Fish for BeOS support and Ada fixes.
@item
Ivan Fontes Garcia for the Portugese translation of the GCJ FAQ.
@item
-Peter Gerwinski for various bugfixes and the Pascal front end.
+Peter Gerwinski for various bug fixes and the Pascal front end.
@item
-Kaveh Ghazi for his direction via the steering committee and
-amazing work to make @samp{-W -Wall} useful.
+Kaveh Ghazi for his direction via the steering committee,
+amazing work to make @samp{-W -Wall} useful, and continuously testing
+GCC on a plethora of platforms.
@item
John Gilmore for a donation to the FSF earmarked improving GNU Java.
@@ -251,7 +283,7 @@ Intel 386 and 860 support.
@item
Bruno Haible for improvements in the runtime overhead for EH, new
-warnings and assorted bugfixes.
+warnings and assorted bug fixes.
@item
Andrew Haley for his amazing Java compiler and library efforts.
@@ -268,18 +300,25 @@ fixes.
Kate Hedstrom for staking the g77 folks with an initial testsuite.
@item
-Richard Henderson for his ongoing SPARC, alpha, and ia32 work, loop
+Richard Henderson for his ongoing SPARC, alpha, ia32, and ia64 work, loop
opts, and generally fixing lots of old problems we've ignored for
years, flow rewrite and lots of further stuff, including reviewing
tons of patches.
@item
+Aldy Hernandez for working on the PowerPC port, SIMD support, and
+various fixes.
+
+@item
Nobuyuki Hikichi of Software Research Associates, Tokyo, contributed
the support for the Sony NEWS machine.
@item
+Kazu Hirata for caring and feeding the Renesas H8/300 port and various fixes.
+
+@item
Manfred Hollstein for his ongoing work to keep the m88k alive, lots
-of testing an bugfixing, particularly of our configury code.
+of testing and bug fixing, particularly of our configury code.
@item
Steve Holmgren for MachTen patches.
@@ -288,7 +327,7 @@ Steve Holmgren for MachTen patches.
Jan Hubicka for his x86 port improvements.
@item
-Christian Iseli for various bugfixes.
+Christian Iseli for various bug fixes.
@item
Kamil Iskra for general m68k hacking.
@@ -297,7 +336,7 @@ Kamil Iskra for general m68k hacking.
Lee Iverson for random fixes and MIPS testing.
@item
-Andreas Jaeger for various fixes to the MIPS port
+Andreas Jaeger for testing and benchmarking of GCC and various bug fixes.
@item
Jakub Jelinek for his SPARC work and sibling call optimizations as well
@@ -305,11 +344,11 @@ as lots of bug fixes and test cases, and for improving the Java build
system.
@item
-Janis Johnson for ia64 testing and fixes and for her quality improvement
-sidetracks.
+Janis Johnson for ia64 testing and fixes, her quality improvement
+sidetracks, and web page maintenance.
@item
-J. Kean Johnston for OpenServer support.
+Kean Johnston for SCO OpenServer support and various fixes.
@item
Tim Josling for the sample language treelang based originally on Richard
@@ -325,7 +364,7 @@ Klaus Kaempf for his ongoing work to make alpha-vms a viable target.
David Kashtan of SRI adapted GCC to VMS@.
@item
-Ryszard Kabatek for many, many libstdc++ bugfixes and optimizations of
+Ryszard Kabatek for many, many libstdc++ bug fixes and optimizations of
strings, especially member functions, and for auto_ptr fixes.
@item
@@ -363,7 +402,7 @@ Robin Kirkham for cpu32 support.
Mark Klein for PA improvements.
@item
-Thomas Koenig for various bugfixes.
+Thomas Koenig for various bug fixes.
@item
Bruce Korb for the new and improved fixincludes code.
@@ -389,7 +428,8 @@ with analysis and improvements of x86 performance.
Ted Lemon wrote parts of the RTL reader and printer.
@item
-Kriang Lerdsuwanakij for improvements to demangler and various c++ fixes.
+Kriang Lerdsuwanakij for C++ improvements including template as template
+parameter support, and many C++ fixes.
@item
Warren Levy for tremendous work on libgcj (Java Runtime Library) and
@@ -406,7 +446,7 @@ patches.
Robert Lipe for OpenServer support, new testsuites, testing, etc.
@item
-Weiwen Liu for testing and various bugfixes.
+Weiwen Liu for testing and various bug fixes.
@item
Dave Love for his ongoing work with the Fortran front end and
@@ -450,7 +490,7 @@ for Java test code.
Bryce McKinlay for numerous GCJ and libgcj fixes and improvements.
@item
-Adam Megacz for his work on the Win32 port of GCJ.
+Adam Megacz for his work on the Windows port of GCJ.
@item
Michael Meissner for LRS framework, ia32, m32r, v850, m88k, MIPS,
@@ -469,7 +509,7 @@ developers.
Gary Miller ported GCC to Charles River Data Systems machines.
@item
-Alfred Minarik for libstdc++ string and ios bugfixes, and turning the
+Alfred Minarik for libstdc++ string and ios bug fixes, and turning the
entire libstdc++ testsuite namespace-compatible.
@item
@@ -527,6 +567,9 @@ MT-safe string and shadow headers.
Felix Natter for documentation on porting libstdc++.
@item
+Nathanael Nerode for cleaning up the configuration/build process.
+
+@item
NeXT, Inc.@: donated the front end that supports the Objective-C
language.
@@ -538,6 +581,10 @@ engine setup, various documentation fixes and other small fixes.
Geoff Noer for this work on getting cygwin native builds working.
@item
+Diego Novillo for his SPEC performance tracking web pages and assorted
+fixes in the middle end and various back ends.
+
+@item
David O'Brien for the FreeBSD/alpha, FreeBSD/AMD x86-64, FreeBSD/ARM,
FreeBSD/PowerPC, and FreeBSD/SPARC64 ports and related infrastructure
improvements.
@@ -555,6 +602,9 @@ ABI support, improvements to dejagnu's MIPS support, Java configuration
clean-ups and porting work, etc.
@item
+Hartmut Penner for work on the s390 port.
+
+@item
Paul Petersen wrote the machine description for the Alliant FX/8.
@item
@@ -585,13 +635,17 @@ David Reese of Sun Microsystems contributed to the Solaris on PowerPC
port.
@item
+Volker Reichelt for keeping up with the problem reports.
+
+@item
Joern Rennecke for maintaining the sh port, loop, regmove & reload
hacking.
@item
Loren J. Rittle for improvements to libstdc++-v3 including the FreeBSD
port, threading fixes, thread-related configury changes, critical
-threading documentation, and solutions to really tricky I/O problems.
+threading documentation, and solutions to really tricky I/O problems,
+as well as keeping GCC properly working on FreeBSD and continuous testing.
@item
Craig Rodrigues for processing tons of bug reports.
@@ -616,6 +670,10 @@ Juha Sarlin for improvements to the H8 code generator.
Greg Satz assisted in making GCC work on HP-UX for the 9000 series 300.
@item
+Roger Sayle for improvements to constant folding and GCC's RTL optimizers
+as well as for fixing numerous bugs.
+
+@item
Bradley Schatz for his work on the GCJ FAQ.
@item
@@ -667,6 +725,9 @@ Andrey Slepuhin for assorted AIX hacking.
Christopher Smith did the port for Convex machines.
@item
+Danny Smith for his major efforts on the Mingw (and Cygwin) ports.
+
+@item
Randy Smith finished the Sun FPA support.
@item
@@ -716,7 +777,7 @@ Holger Teutsch provided the support for the Clipper CPU.
Gary Thomas for his ongoing work to make the PPC work for GNU/Linux.
@item
-Philipp Thomas for random bugfixes throughout the compiler
+Philipp Thomas for random bug fixes throughout the compiler
@item
Jason Thorpe for thread support in libstdc++ on NetBSD.
@@ -726,7 +787,7 @@ Kresten Krab Thorup wrote the run time support for the Objective-C
language and the fantastic Java bytecode interpreter.
@item
-Michael Tiemann for random bugfixes, the first instruction scheduler,
+Michael Tiemann for random bug fixes, the first instruction scheduler,
initial C++ support, function integration, NS32k, SPARC and M88k
machine description work, delay slot scheduling.
@@ -767,7 +828,7 @@ Dean Wakerley for converting the install documentation from HTML to texinfo
in time for GCC 3.0.
@item
-Krister Walfridsson for random bugfixes.
+Krister Walfridsson for random bug fixes.
@item
Stephen M. Webb for time and effort on making libstdc++ shadow files
@@ -780,7 +841,10 @@ related infrastructure improvements to help x86 code generation,
value range propagation and other work, WE32k port.
@item
-Zack Weinberg for major work on cpplib and various other bugfixes.
+Ulrich Weigand for work on the s390 port.
+
+@item
+Zack Weinberg for major work on cpplib and various other bug fixes.
@item
Matt Welsh for help with Linux Threads support in GCJ.
@@ -821,9 +885,9 @@ Gilles Zunino for help porting Java to Irix.
@end itemize
-
-We'd also like to thank the folks who have contributed time and energy in
-testing GCC:
+In addition to the above, all of which also contributed time and energy in
+testing GCC, we would like to thank the following for their contributions
+to testing:
@itemize @bullet
@item
@@ -860,12 +924,6 @@ Frank Braun
Rodney Brown
@item
-Joe Buck
-
-@item
-Craig Burley
-
-@item
Sidney Cadot
@item
@@ -875,12 +933,6 @@ Bradford Castalia
Ralph Doncaster
@item
-Ulrich Drepper
-
-@item
-David Edelsohn
-
-@item
Richard Emberson
@item
@@ -905,9 +957,6 @@ Charles-Antoine Gauthier
Yung Shing Gene
@item
-Kaveh Ghazi
-
-@item
David Gilbert
@item
@@ -932,21 +981,9 @@ Amancio Hasty
Bryan W. Headley
@item
-Kate Hedstrom
-
-@item
-Richard Henderson
-
-@item
Kevin B. Hendricks
@item
-Manfred Hollstein
-
-@item
-Kamil Iskra
-
-@item
Joep Jansen
@item
@@ -962,30 +999,15 @@ Tobias Kuipers
Anand Krishnaswamy
@item
-Jeff Law
-
-@item
-Robert Lipe
-
-@item
llewelly
@item
Damon Love
@item
-Dave Love
-
-@item
-H.J. Lu
-
-@item
Brad Lucier
@item
-Mumit Khan
-
-@item
Matthias Klose
@item
@@ -995,12 +1017,6 @@ Martin Knoblauch
Jesse Macnish
@item
-David Miller
-
-@item
-Toon Moene
-
-@item
Stefan Morrell
@item
@@ -1013,9 +1029,6 @@ Matthias Mueller
Pekka Nikander
@item
-Alexandre Oliva
-
-@item
Jon Olson
@item
@@ -1037,9 +1050,6 @@ Paul Reilly
Tom Reilly
@item
-Loren J. Rittle
-
-@item
Torsten Rueger
@item
@@ -1049,24 +1059,15 @@ Danny Sadinoff
Marc Schifer
@item
-Peter Schmid
-
-@item
David Schuler
@item
Vin Shelton
@item
-Franz Sirl
-
-@item
Tim Souder
@item
-Mike Stump
-
-@item
Adam Sulmicki
@item
@@ -1076,9 +1077,6 @@ George Talbot
Gregory Warnes
@item
-Carlo Wood
-
-@item
David E. Young
@item
diff --git a/contrib/gcc/doc/cpp.texi b/contrib/gcc/doc/cpp.texi
index 39e6a28..a6d6fb0 100644
--- a/contrib/gcc/doc/cpp.texi
+++ b/contrib/gcc/doc/cpp.texi
@@ -6,10 +6,10 @@
@c @cropmarks
@c @finalout
-@macro copyrightnotice
+@copying
@c man begin COPYRIGHT
Copyright @copyright{} 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996,
-1997, 1998, 1999, 2000, 2001
+1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
@@ -23,9 +23,7 @@ section entitled ``GNU Free Documentation License''.
man page gfdl(7).
@c man end
@end ignore
-@end macro
-@macro covertexts
@c man begin COPYRIGHT
This manual contains no Invariant Sections. The Front-Cover Texts are
(a) (see below), and the Back-Cover Texts are (b) (see below).
@@ -40,7 +38,7 @@ This manual contains no Invariant Sections. The Front-Cover Texts are
software. Copies published by the Free Software Foundation raise
funds for GNU development.
@c man end
-@end macro
+@end copying
@macro gcctabopt{body}
@code{\body\}
@@ -48,6 +46,7 @@ This manual contains no Invariant Sections. The Front-Cover Texts are
@c Create a separate index for command line options.
@defcodeindex op
+@syncodeindex vr op
@c Used in cppopts.texi and cppenv.texi.
@set cppmanual
@@ -69,12 +68,12 @@ This manual contains no Invariant Sections. The Front-Cover Texts are
@c There is a fill at the bottom of the page, so we need a filll to
@c override it.
@vskip 0pt plus 1filll
-@copyrightnotice{}
-@covertexts{}
+@insertcopying
@end titlepage
@contents
@page
+@ifnottex
@node Top
@top
The C preprocessor implements the macro language used to transform C,
@@ -96,8 +95,8 @@ useful on its own.
* Invocation::
* Environment Variables::
* GNU Free Documentation License::
-* Option Index::
* Index of Directives::
+* Option Index::
* Concept Index::
@detailmenu
@@ -129,6 +128,7 @@ Macros
* Variadic Macros::
* Predefined Macros::
* Undefining and Redefining Macros::
+* Directives Within Macro Arguments::
* Macro Pitfalls::
Predefined Macros
@@ -173,14 +173,11 @@ Obsolete Features
* Assertions::
* Obsolete once-only headers::
-* Miscellaneous obsolete features::
@end detailmenu
@end menu
-@ifnottex
-@copyrightnotice{}
-@covertexts{}
+@insertcopying
@end ifnottex
@node Overview
@@ -203,7 +200,7 @@ will be removed, and the Makefile will not work.
Having said that, you can often get away with using cpp on things which
are not C@. Other Algol-ish programming languages are often safe
-(Pascal, Ada, etc.) So is assembly, with caution. @option{-traditional}
+(Pascal, Ada, etc.) So is assembly, with caution. @option{-traditional-cpp}
mode preserves more white space, and is otherwise more permissive. Many
of the problems can be avoided by writing C or C++ style comments
instead of native language comments, and keeping macros simple.
@@ -223,6 +220,16 @@ of a program which does not expect them. To get strict ISO Standard C,
you should use the @option{-std=c89} or @option{-std=c99} options, depending
on which version of the standard you want. To get all the mandatory
diagnostics, you must also use @option{-pedantic}. @xref{Invocation}.
+
+This manual describes the behavior of the ISO preprocessor. To
+minimize gratuitous differences, where the ISO preprocessor's
+behavior does not conflict with traditional semantics, the
+traditional preprocessor should behave the same way. The various
+differences that do exist are detailed in the section @ref{Traditional
+Mode}.
+
+For clarity, unless noted otherwise, references to @samp{CPP} in this
+manual refer to GNU CPP.
@c man end
@menu
@@ -237,7 +244,7 @@ diagnostics, you must also use @option{-pedantic}. @xref{Invocation}.
The preprocessor performs a series of textual transformations on its
input. These happen before all other processing. Conceptually, they
happen in a rigid order, and the entire file is run through each
-transformation before the next one begins. GNU CPP actually does them
+transformation before the next one begins. CPP actually does them
all at once, for performance reasons. These transformations correspond
roughly to the first three ``phases of translation'' described in the C
standard.
@@ -248,7 +255,7 @@ standard.
@cindex line endings
The input file is read into memory and broken into lines.
-GNU CPP expects its input to be a text file, that is, an unstructured
+CPP expects its input to be a text file, that is, an unstructured
stream of ASCII characters, with some characters indicating the end of a
line of text. Extended ASCII character sets, such as ISO Latin-1 or
Unicode encoded in UTF-8, are also acceptable. Character sets that are
@@ -274,16 +281,17 @@ warning message.
@item
@cindex trigraphs
-If trigraphs are enabled, they are replaced by their corresponding
-single characters.
+@anchor{trigraphs}If trigraphs are enabled, they are replaced by their
+corresponding single characters. By default GCC ignores trigraphs,
+but if you request a strictly conforming mode with the @option{-std}
+option, or you specify the @option{-trigraphs} option, then it
+converts them.
These are nine three-character sequences, all starting with @samp{??},
that are defined by ISO C to stand for single characters. They permit
obsolete systems that lack some of C's punctuation to use C@. For
example, @samp{??/} stands for @samp{\}, so @t{'??/n'} is a character
-constant for a newline. By default, GCC ignores trigraphs, but if you
-request a strictly conforming mode with the @option{-std} option, then
-it converts them.
+constant for a newline.
Trigraphs are not popular and many compilers implement them incorrectly.
Portable code should not rely on trigraphs being either converted or
@@ -401,26 +409,8 @@ extremely confusing and should not be used in code intended to be
readable.
There is no way to prevent a backslash at the end of a line from being
-interpreted as a backslash-newline.
-
-@example
-"foo\\
-bar"
-@end example
-
-@noindent
-is equivalent to @code{"foo\bar"}, not to @code{"foo\\bar"}. To avoid
-having to worry about this, do not use the deprecated GNU extension
-which permits multi-line strings. Instead, use string literal
-concatenation:
-
-@example
- "foo\\"
- "bar"
-@end example
-
-@noindent
-Your program will be more portable this way, too.
+interpreted as a backslash-newline. This cannot affect any correct
+program, however.
@node Tokenization
@section Tokenization
@@ -535,11 +525,10 @@ closing quote or angle bracket. The preprocessor looks for the header
file in different places depending on which form you use. @xref{Include
Operation}.
-In standard C, no string literal may extend past the end of a line. GNU
-CPP accepts multi-line string constants, but not multi-line character
-constants or header file names. This extension is deprecated and will
-be removed in GCC 3.1. You may use continued lines instead, or string
-constant concatenation. @xref{Differences from previous versions}.
+No string literal may extend past the end of a line. Older versions
+of GCC accepted multi-line string constants. You may use continued
+lines instead, or string constant concatenation. @xref{Differences
+from previous versions}.
@cindex punctuators
@cindex digraphs
@@ -795,10 +784,10 @@ those are merely the typical uses. Any fragment of a C program can be
included from another file. The include file could even contain the
beginning of a statement that is concluded in the containing file, or
the end of a statement that was started in the including file. However,
-a comment or a string or character constant may not start in the
-included file and finish in the including file. An unterminated
-comment, string constant or character constant in an included file is
-considered to end (with an error message) at the end of the file.
+an included file must consist of complete tokens. Comments and string
+literals which have not been closed by the end of an included file are
+invalid. For error recovery, they are considered to end at the end of
+the file.
To avoid confusion, it is best if header files contain only complete
syntactic units---function declarations or definitions, type
@@ -909,7 +898,7 @@ because @code{FILE_FOO_SEEN} is defined. The preprocessor will skip
over the entire contents of the file, and the compiler will not see it
twice.
-GNU CPP optimizes even further. It remembers when a header file has a
+CPP optimizes even further. It remembers when a header file has a
wrapper @samp{#ifndef}. If a subsequent @samp{#include} specifies that
header, and the macro in the @samp{#ifndef} is still defined, it does
not bother to rescan the file at all.
@@ -1128,6 +1117,7 @@ macros when you are compiling C++.
* Variadic Macros::
* Predefined Macros::
* Undefining and Redefining Macros::
+* Directives Within Macro Arguments::
* Macro Pitfalls::
@end menu
@@ -1621,7 +1611,7 @@ or to paste its leading or trailing token with another token. (But see
below for an important special case for @samp{##}.)
If your macro is complicated, you may want a more descriptive name for
-the variable argument than @code{@w{__VA_ARGS__}}. GNU CPP permits
+the variable argument than @code{@w{__VA_ARGS__}}. CPP permits
this, as an extension. You may write an argument name immediately
before the @samp{@dots{}}; that name is used for the variable argument.
The @code{eprintf} macro above could be written
@@ -1631,7 +1621,7 @@ The @code{eprintf} macro above could be written
@end example
@noindent
-using this extension. You cannot use @code{__VA_ARGS__} and this
+using this extension. You cannot use @code{@w{__VA_ARGS__}} and this
extension in the same macro.
You can have named arguments as well as variable arguments in a variadic
@@ -1705,7 +1695,7 @@ only named variable arguments. On the other hand, if you are concerned
with portability to other conforming implementations of C99, you should
use only @code{@w{__VA_ARGS__}}.
-Previous versions of GNU CPP implemented the comma-deletion extension
+Previous versions of CPP implemented the comma-deletion extension
much more generally. We have restricted it in this release to minimize
the differences from C99. To get the same effect with both this and
previous versions of GCC, the token preceding the special @samp{##} must
@@ -1800,23 +1790,31 @@ the preprocessor is being run. The string constant contains eleven
characters and looks like @code{@w{"Feb 12 1996"}}. If the day of the
month is less than 10, it is padded with a space on the left.
+If GCC cannot determine the current date, it will emit a warning message
+(once per compilation) and @code{__DATE__} will expand to
+@code{@w{"??? ?? ????"}}.
+
@item __TIME__
This macro expands to a string constant that describes the time at
which the preprocessor is being run. The string constant contains
eight characters and looks like @code{"23:59:01"}.
+If GCC cannot determine the current time, it will emit a warning message
+(once per compilation) and @code{__TIME__} will expand to
+@code{"??:??:??"}.
+
@item __STDC__
In normal operation, this macro expands to the constant 1, to signify
that this compiler conforms to ISO Standard C@. If GNU CPP is used with
a compiler other than GCC, this is not necessarily true; however, the
-preprocessor always conforms to the standard, unless the
-@option{-traditional} option is used.
+preprocessor always conforms to the standard unless the
+@option{-traditional-cpp} option is used.
-This macro is not defined if the @option{-traditional} option is used.
+This macro is not defined if the @option{-traditional-cpp} option is used.
On some hosts, the system compiler uses a different convention, where
@code{__STDC__} is normally 0, but is 1 if the user specifies strict
-conformance to the C Standard. GNU CPP follows the host convention when
+conformance to the C Standard. CPP follows the host convention when
processing system header files, but when processing user files
@code{__STDC__} is always 1. This has been reported to cause problems;
for instance, some versions of Solaris provide X Windows headers that
@@ -1835,8 +1833,8 @@ The value @code{199409L} signifies the 1989 C standard as amended in
the 1999 revision of the C standard. Support for the 1999 revision is
not yet complete.
-This macro is not defined if the @option{-traditional} option is used, nor
-when compiling C++ or Objective-C@.
+This macro is not defined if the @option{-traditional-cpp} option is
+used, nor when compiling C++ or Objective-C@.
@item __STDC_HOSTED__
This macro is defined, with value 1, if the compiler's target is a
@@ -1970,6 +1968,10 @@ unsigned on the target machine. It exists to cause the standard header
file @file{limits.h} to work correctly. You should not use this macro
yourself; instead, refer to the standard macros defined in @file{limits.h}.
+@item __WCHAR_UNSIGNED__
+Like @code{__CHAR_UNSIGNED__}, this macro is defined if and only if the
+data type @code{wchar_t} is unsigned and the front-end is in C++ mode.
+
@item __REGISTER_PREFIX__
This macro expands to a single token (not a string constant) which is
the prefix applied to CPU register names in assembly language for this
@@ -2000,10 +2002,35 @@ typedefs, respectively. They exist to make the standard header files
these macros directly; instead, include the appropriate headers and use
the typedefs.
+@item __CHAR_BIT__
+Defined to the number of bits used in the representation of the
+@code{char} data type. It exists to make the standard header given
+numerical limits work correctly. You should not use
+this macro directly; instead, include the appropriate headers.
+
+@item __SCHAR_MAX__
+@itemx __WCHAR_MAX__
+@itemx __SHRT_MAX__
+@itemx __INT_MAX__
+@itemx __LONG_MAX__
+@itemx __LONG_LONG_MAX__
+Defined to the maximum value of the @code{signed char}, @code{wchar_t},
+@code{signed short},
+@code{signed int}, @code{signed long}, and @code{signed long long} types
+respectively. They exist to make the standard header given numerical limits
+work correctly. You should not use these macros directly; instead, include
+the appropriate headers.
+
@item __USING_SJLJ_EXCEPTIONS__
This macro is defined, with value 1, if the compiler uses the old
mechanism based on @code{setjmp} and @code{longjmp} for exception
handling.
+
+@item __NEXT_RUNTIME__
+This macro is defined, with value 1, if (and only if) the NeXT runtime
+(as in @option{-fnext-runtime}) is in use for Objective-C. If the GNU
+runtime is used, this macro is not defined, so that you can use this
+macro to determine which runtime (NeXT or GNU) is being used.
@end table
@node System-specific Predefined Macros
@@ -2136,6 +2163,50 @@ the same, the redefinition is silently ignored. This allows, for
instance, two different headers to define a common macro. The
preprocessor will only complain if the definitions do not match.
+@node Directives Within Macro Arguments
+@section Directives Within Macro Arguments
+@cindex macro arguments and directives
+
+Occasionally it is convenient to use preprocessor directives within
+the arguments of a macro. The C and C++ standards declare that
+behavior in these cases is undefined.
+
+Versions of CPP prior to 3.2 would reject such constructs with an
+error message. This was the only syntactic difference between normal
+functions and function-like macros, so it seemed attractive to remove
+this limitation, and people would often be surprised that they could
+not use macros in this way. Moreover, sometimes people would use
+conditional compilation in the argument list to a normal library
+function like @samp{printf}, only to find that after a library upgrade
+@samp{printf} had changed to be a function-like macro, and their code
+would no longer compile. So from version 3.2 we changed CPP to
+successfully process arbitrary directives within macro arguments in
+exactly the same way as it would have processed the directive were the
+function-like macro invocation not present.
+
+If, within a macro invocation, that macro is redefined, then the new
+definition takes effect in time for argument pre-expansion, but the
+original definition is still used for argument replacement. Here is a
+pathological example:
+
+@smallexample
+#define f(x) x x
+f (1
+#undef f
+#define f 2
+f)
+@end smallexample
+
+@noindent
+which expands to
+
+@smallexample
+1 2 1 2
+@end smallexample
+
+@noindent
+with the semantics described above.
+
@node Macro Pitfalls
@section Macro Pitfalls
@cindex problems with macros
@@ -2723,7 +2794,7 @@ good practice if there is a lot of @var{controlled text}, because it
helps people match the @samp{#endif} to the corresponding @samp{#ifdef}.
Older programs sometimes put @var{MACRO} directly after the
@samp{#endif} without enclosing it in a comment. This is invalid code
-according to the C standard. GNU CPP accepts it with a warning. It
+according to the C standard. CPP accepts it with a warning. It
never affects which @samp{#ifndef} the @samp{#endif} matches.
@findex #ifndef
@@ -3059,7 +3130,7 @@ file it specifies, until something else happens to change that.
constant: backslash escapes are interpreted. This is different from
@samp{#include}.
-Previous versions of GNU CPP did not interpret escapes in @samp{#line};
+Previous versions of CPP did not interpret escapes in @samp{#line};
we have changed it because the standard requires they be interpreted,
and most other compilers do.
@@ -3226,8 +3297,8 @@ This directive is not part of the C standard, but it is not an official
GNU extension either. We believe it came from System V@.
@findex #sccs
-The @samp{#sccs} directive is recognized on some systems, because it
-appears in their header files. It is a very old, obscure, extension
+The @samp{#sccs} directive is recognized, because it appears in the
+header files of some systems. It is a very old, obscure, extension
which we did not invent, and we have been unable to find any
documentation of what it should do, so GCC simply ignores it.
@@ -3321,91 +3392,230 @@ the directive name.
Traditional (pre-standard) C preprocessing is rather different from
the preprocessing specified by the standard. When GCC is given the
-@option{-traditional} option, it attempts to emulate a traditional
-preprocessor. We do not guarantee that GCC's behavior under
-@option{-traditional} matches any pre-standard preprocessor exactly.
+@option{-traditional-cpp} option, it attempts to emulate a traditional
+preprocessor.
-Traditional mode exists only for backward compatibility. We have no
-plans to augment it in any way nor will we change it except to fix
-catastrophic bugs. You should be aware that modern C libraries often
-have header files which are incompatible with traditional mode.
+GCC versions 3.2 and later only support traditional mode semantics in
+the preprocessor, and not in the compiler front ends. This chapter
+outlines the traditional preprocessor semantics we implemented.
-This is a list of the differences. It may not be complete, and may not
-correspond exactly to the behavior of either GCC or a true traditional
-preprocessor.
+The implementation does not correspond precisely to the behavior of
+earlier versions of GCC, nor to any true traditional preprocessor.
+After all, inconsistencies among traditional implementations were a
+major motivation for C standardization. However, we intend that it
+should be compatible with true traditional preprocessors in all ways
+that actually matter.
-@itemize @bullet
-@item
-Traditional macro expansion pays no attention to single-quote or
-double-quote characters; macro argument symbols are replaced by the
-argument values even when they appear within apparent string or
-character constants.
+@menu
+* Traditional lexical analysis::
+* Traditional macros::
+* Traditional miscellany::
+* Traditional warnings::
+@end menu
-@item
-Traditionally, it is permissible for a macro expansion to end in the
-middle of a string or character constant. The constant continues into
-the text surrounding the macro call.
+@node Traditional lexical analysis
+@section Traditional lexical analysis
-@item
-However, the end of the line terminates a string or character constant,
-with no error. (This is a kluge. Traditional mode is commonly used to
-preprocess things which are not C, and have a different comment syntax.
-Single apostrophes often appear in comments. This kluge prevents the
-traditional preprocessor from issuing errors on such comments.)
+The traditional preprocessor does not decompose its input into tokens
+the same way a standards-conforming preprocessor does. The input is
+simply treated as a stream of text with minimal internal form.
-@item
-Preprocessing directives are recognized in traditional C only when their
-leading @samp{#} appears in the first column. There can be no
-whitespace between the beginning of the line and the @samp{#}.
+This implementation does not treat trigraphs (@pxref{trigraphs})
+specially since they were an invention of the standards committee. It
+handles arbitrarily-positioned escaped newlines properly and splices
+the lines as you would expect; many traditional preprocessors did not
+do this.
-@item
-In traditional C, a comment is equivalent to no text at all. (In ISO
-C, a comment counts as whitespace.) It can be used sort of the same way
-that @samp{##} is used in ISO C, to paste macro arguments together.
+The form of horizontal whitespace in the input file is preserved in
+the output. In particular, hard tabs remain hard tabs. This can be
+useful if, for example, you are preprocessing a Makefile.
-@item
-Traditional C does not have the concept of a preprocessing number.
+Traditional CPP only recognizes C-style block comments, and treats the
+@samp{/*} sequence as introducing a comment only if it lies outside
+quoted text. Quoted text is introduced by the usual single and double
+quotes, and also by an initial @samp{<} in a @code{#include}
+directive.
-@item
-A macro is not suppressed within its own definition, in traditional C@.
-Thus, any macro that is used recursively inevitably causes an error.
+Traditionally, comments are completely removed and are not replaced
+with a space. Since a traditional compiler does its own tokenization
+of the output of the preprocessor, this means that comments can
+effectively be used as token paste operators. However, comments
+behave like separators for text handled by the preprocessor itself,
+since it doesn't re-lex its input. For example, in
-@item
-The @samp{#} and @samp{##} operators are not available in traditional
-C@.
+@smallexample
+#if foo/**/bar
+@end smallexample
+
+@noindent
+@samp{foo} and @samp{bar} are distinct identifiers and expanded
+separately if they happen to be macros. In other words, this
+directive is equivalent to
+
+@smallexample
+#if foo bar
+@end smallexample
+
+@noindent
+rather than
+
+@smallexample
+#if foobar
+@end smallexample
+
+Generally speaking, in traditional mode an opening quote need not have
+a matching closing quote. In particular, a macro may be defined with
+replacement text that contains an unmatched quote. Of course, if you
+attempt to compile preprocessed output containing an unmatched quote
+you will get a syntax error.
+However, all preprocessing directives other than @code{#define}
+require matching quotes. For example:
+
+@smallexample
+#define m This macro's fine and has an unmatched quote
+"/* This is not a comment. */
+/* This is a comment. The following #include directive
+ is ill-formed. */
+#include <stdio.h
+@end smallexample
+
+Just as for the ISO preprocessor, what would be a closing quote can be
+escaped with a backslash to prevent the quoted text from closing.
+
+@node Traditional macros
+@section Traditional macros
+
+The major difference between traditional and ISO macros is that the
+former expand to text rather than to a token sequence. CPP removes
+all leading and trailing horizontal whitespace from a macro's
+replacement text before storing it, but preserves the form of internal
+whitespace.
+
+One consequence is that it is legitimate for the replacement text to
+contain an unmatched quote (@pxref{Traditional lexical analysis}). An
+unclosed string or character constant continues into the text
+following the macro call. Similarly, the text at the end of a macro's
+expansion can run together with the text after the macro invocation to
+produce a single token.
+
+Normally comments are removed from the replacement text after the
+macro is expanded, but if the @option{-CC} option is passed on the
+command line comments are preserved. (In fact, the current
+implementation removes comments even before saving the macro
+replacement text, but it careful to do it in such a way that the
+observed effect is identical even in the function-like macro case.)
+
+The ISO stringification operator @samp{#} and token paste operator
+@samp{##} have no special meaning. As explained later, an effect
+similar to these operators can be obtained in a different way. Macro
+names that are embedded in quotes, either from the main file or after
+macro replacement, do not expand.
+
+CPP replaces an unquoted object-like macro name with its replacement
+text, and then rescans it for further macros to replace. Unlike
+standard macro expansion, traditional macro expansion has no provision
+to prevent recursion. If an object-like macro appears unquoted in its
+replacement text, it will be replaced again during the rescan pass,
+and so on @emph{ad infinitum}. GCC detects when it is expanding
+recursive macros, emits an error message, and continues after the
+offending macro invocation.
+
+@smallexample
+#define PLUS +
+#define INC(x) PLUS+x
+INC(foo);
+ @expansion{} ++foo;
+@end smallexample
+
+Function-like macros are similar in form but quite different in
+behavior to their ISO counterparts. Their arguments are contained
+within parentheses, are comma-separated, and can cross physical lines.
+Commas within nested parentheses are not treated as argument
+separators. Similarly, a quote in an argument cannot be left
+unclosed; a following comma or parenthesis that comes before the
+closing quote is treated like any other character. There is no
+facility for handling variadic macros.
+
+This implementation removes all comments from macro arguments, unless
+the @option{-C} option is given. The form of all other horizontal
+whitespace in arguments is preserved, including leading and trailing
+whitespace. In particular
+
+@smallexample
+f( )
+@end smallexample
+
+@noindent
+is treated as an invocation of the macro @samp{f} with a single
+argument consisting of a single space. If you want to invoke a
+function-like macro that takes no arguments, you must not leave any
+whitespace between the parentheses.
+
+If a macro argument crosses a new line, the new line is replaced with
+a space when forming the argument. If the previous line contained an
+unterminated quote, the following line inherits the quoted state.
+
+Traditional preprocessors replace parameters in the replacement text
+with their arguments regardless of whether the parameters are within
+quotes or not. This provides a way to stringize arguments. For
+example
+
+@smallexample
+#define str(x) "x"
+str(/* A comment */some text )
+ @expansion{} "some text "
+@end smallexample
+
+@noindent
+Note that the comment is removed, but that the trailing space is
+preserved. Here is an example of using a comment to effect token
+pasting.
+
+@smallexample
+#define suffix(x) foo_/**/x
+suffix(bar)
+ @expansion{} foo_bar
+@end smallexample
+
+@node Traditional miscellany
+@section Traditional miscellany
+
+Here are some things to be aware of when using the traditional
+preprocessor.
+
+@itemize @bullet
@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 ISO C@.
+Preprocessing directives are recognized only when their leading
+@samp{#} appears in the first column. There can be no whitespace
+between the beginning of the line and the @samp{#}, but whitespace can
+follow the @samp{#}.
@item
-None of the GNU extensions to the preprocessor are available in
-traditional mode, with the exception of a partial implementation of
-assertions, and those may be removed in the future.
+A true traditional C preprocessor does not recognize @samp{#error} or
+@samp{#pragma}, and may not recognize @samp{#elif}. CPP supports all
+the directives in traditional mode that it supports in ISO mode,
+including extensions, with the exception that the effects of
+@samp{#pragma GCC poison} are undefined.
@item
-A true traditional C preprocessor does not recognize @samp{#elif},
-@samp{#error}, or @samp{#pragma}. GCC supports @samp{#elif} and
-@samp{#error} even in traditional mode, but not @samp{#pragma}.
+__STDC__ is not defined.
@item
-Traditional mode is text-based, not token-based, and comments are
-stripped after macro expansion. Therefore, @samp{/**/} can be used to
-paste tokens together provided that there is no whitespace between it
-and the tokens to be pasted.
+If you use digraphs the behavior is undefined.
@item
-Traditional mode preserves the amount and form of whitespace provided by
-the user. Hard tabs remain hard tabs. This can be useful, e.g.@: if you
-are preprocessing a Makefile (which we do not encourage).
+If a line that looks like a directive appears within macro arguments,
+the behavior is undefined.
+
@end itemize
+@node Traditional warnings
+@section Traditional warnings
You can request warnings about features that did not exist, or worked
differently, in traditional C with the @option{-Wtraditional} option.
-This works only if you do @emph{not} specify @option{-traditional}. GCC
-does not warn about features of ISO C which you must use when you are
-using a conforming compiler, such as the @samp{#} and @samp{##}
+GCC does not warn about features of ISO C which you must use when you
+are using a conforming compiler, such as the @samp{#} and @samp{##}
operators.
Presently @option{-Wtraditional} warns about:
@@ -3428,9 +3638,9 @@ traditional implementations would not recognize @samp{#elif}, so it
suggests avoiding it altogether.
@item
-A function-like macro that appears without an argument list. In
-traditional C this was an error. In ISO C it merely means that the
-macro is not expanded.
+A function-like macro that appears without an argument list. In some
+traditional preprocessors this was an error. In ISO C it merely means
+that the macro is not expanded.
@item
The unary plus operator. This did not exist in traditional C@.
@@ -3458,7 +3668,7 @@ reliance on behavior described here, as it is possible that it will
change subtly in future implementations.
Also documented here are obsolete features and changes from previous
-versions of GNU CPP@.
+versions of CPP@.
@menu
* Implementation-defined behavior::
@@ -3471,7 +3681,7 @@ versions of GNU CPP@.
@section Implementation-defined behavior
@cindex implementation-defined behavior
-This is how GNU CPP behaves in all the cases which the C standard
+This is how CPP behaves in all the cases which the C standard
describes as @dfn{implementation-defined}. This term means that the
implementation is free to do what it likes, but must document its choice
and stick to it.
@@ -3494,17 +3704,25 @@ same column as it did in the original source file.
@item The numeric value of character constants in preprocessor expressions.
-The preprocessor and compiler interpret character constants in the same
-way; escape sequences such as @samp{\a} are given the values they would
-have on the target machine.
-
-Multi-character character constants are interpreted a character at a
-time, shifting the previous result left by the number of bits per
-character on the host, and adding the new character. For example, 'ab'
-on an 8-bit host would be interpreted as @w{'a' * 256 + 'b'}. If there
-are more characters in the constant than can fit in the widest native
-integer type on the host, usually a @code{long}, the excess characters
-are ignored and a diagnostic is given.
+The preprocessor and compiler interpret character constants in the
+same way; i.e.@: escape sequences such as @samp{\a} are given the
+values they would have on the target machine.
+
+The compiler values a multi-character character constant a character
+at a time, shifting the previous value left by the number of bits per
+target character, and then or-ing in the bit-pattern of the new
+character truncated to the width of a target character. The final
+bit-pattern is given type @code{int}, and is therefore signed,
+regardless of whether single characters are signed or not (a slight
+change from versions 3.1 and earlier of GCC). If there are more
+characters in the constant than would fit in the target @code{int} the
+compiler issues a warning, and the excess leading characters are
+ignored.
+
+For example, 'ab' for a target with an 8-bit @code{char} would be
+interpreted as @w{(int) ((unsigned char) 'a' * 256 + (unsigned char)
+'b')}, and '\234a' as @w{(int) ((unsigned char) '\234' * 256 + (unsigned
+char) 'a')}.
@item Source file inclusion.
@@ -3531,7 +3749,7 @@ pragmas.
@section Implementation limits
@cindex implementation limits
-GNU CPP has a small number of internal limits. This section lists the
+CPP has a small number of internal limits. This section lists the
limits which the C standard requires to be no lower than some minimum,
and all the others we are aware of. We intend there to be as few limits
as possible. If you encounter an undocumented or inconvenient limit,
@@ -3554,10 +3772,10 @@ The standard requires at least 15 levels.
@item Nesting levels of conditional inclusion.
-The C standard mandates this be at least 63. GNU CPP is limited only by
+The C standard mandates this be at least 63. CPP is limited only by
available memory.
-@item Levels of parenthesised expressions within a full expression.
+@item Levels of parenthesized expressions within a full expression.
The C standard requires this to be at least 63. In preprocessor
conditional expressions, it is limited only by available memory.
@@ -3569,7 +3787,7 @@ requires only that the first 63 be significant.
@item Number of macros simultaneously defined in a single translation unit.
-The standard requires at least 4095 be possible. GNU CPP is limited only
+The standard requires at least 4095 be possible. CPP is limited only
by available memory.
@item Number of parameters in a macro definition and arguments in a macro call.
@@ -3579,7 +3797,7 @@ required by the standard is 127.
@item Number of characters on a logical source line.
-The C standard requires a minimum of 4096 be permitted. GNU CPP places
+The C standard requires a minimum of 4096 be permitted. CPP places
no limits on this, but you may get incorrect column numbers reported in
diagnostics for lines longer than 65,535 characters.
@@ -3596,14 +3814,13 @@ may not be a limitation.
@node Obsolete Features
@section Obsolete Features
-GNU CPP has a number of features which are present mainly for
+CPP has a number of features which are present mainly for
compatibility with older programs. We discourage their use in new code.
In some cases, we plan to remove the feature in a future version of GCC@.
@menu
* Assertions::
* Obsolete once-only headers::
-* Miscellaneous obsolete features::
@end menu
@node Assertions
@@ -3671,9 +3888,9 @@ answers. Subsequent assertions do not override previous ones for the
same predicate. All the answers for any given predicate are
simultaneously true.
-@cindex assertions, cancelling
+@cindex assertions, canceling
@findex #unassert
-Assertions can be cancelled with the @samp{#unassert} directive. It
+Assertions can be canceled with the @samp{#unassert} directive. It
has the same syntax as @samp{#assert}. In that form it cancels only the
answer which was specified on the @samp{#unassert} line; other answers
for that predicate remain true. You can cancel an entire predicate by
@@ -3693,7 +3910,7 @@ You can also make or cancel assertions using command line options.
@node Obsolete once-only headers
@subsection Obsolete once-only headers
-GNU CPP supports two more ways of indicating that a header file should be
+CPP supports two more ways of indicating that a header file should be
read only once. Neither one is as portable as a wrapper @samp{#ifndef},
and we recommend you do not use them in new programs.
@@ -3726,49 +3943,12 @@ matter what.
but it is not recognized by all preprocessors, so you cannot rely on it
in a portable program.
-@node Miscellaneous obsolete features
-@subsection Miscellaneous obsolete features
-
-Here are a few more obsolete features.
-
-@itemize @bullet
-@cindex invalid token paste
-@item Attempting to paste two tokens which together do not form a valid
-preprocessing token.
-
-The preprocessor currently warns about this, and the resulting
-preprocessed output is undefined. The tokens remain distinct if the
-preprocessor is being used directly by the compiler front end.
-
-Most of the time, when you get this warning, you will find that @samp{##}
-is being used superstitiously, to guard against whitespace appearing
-between two tokens. It is almost always safe to delete the @samp{##}.
-
-@cindex pragma poison
-@item @code{#pragma poison}
-
-This is the same as @code{#pragma GCC poison}. The version without the
-@code{GCC} prefix is deprecated. @xref{Pragmas}.
-
-@cindex multi-line string constants
-@item Multi-line string constants
-
-GCC currently allows a string constant to extend across multiple logical
-lines of the source file. This extension is deprecated and will be
-removed in a future version of GCC@. Such string constants are already
-rejected in all directives apart from @samp{#define}.
-
-Instead, make use of ISO C concatenation of adjacent string literals, or
-use @samp{\n} followed by a backslash-newline.
-
-@end itemize
-
@node Differences from previous versions
@section Differences from previous versions
@cindex differences from previous versions
This section details behavior which has changed from previous versions
-of GNU CPP@. We do not plan to change it again in the near future, but
+of CPP@. We do not plan to change it again in the near future, but
we do not promise not to, either.
The ``previous versions'' discussed here are 2.95 and before. The
@@ -3794,7 +3974,7 @@ GCC 3.0 evaluates @samp{#} and @samp{##} at the same time and strictly
left to right. Older versions evaluated all @samp{#} operators first,
then all @samp{##} operators, in an unreliable order.
-@item The form of whitespace betwen tokens in preprocessor output
+@item The form of whitespace between tokens in preprocessor output
@xref{Preprocessor Output}, for the current textual format. This is
also the format used by stringification. Normally, the preprocessor
@@ -3817,7 +3997,7 @@ versions accepted it silently.
Formerly, in a macro expansion, if @samp{##} appeared before a variable
arguments parameter, and the set of tokens specified for that argument
-in the macro invocation was empty, previous versions of GNU CPP would
+in the macro invocation was empty, previous versions of CPP would
back up and remove the preceding sequence of non-whitespace characters
(@strong{not} the preceding token). This extension is in direct
conflict with the 1999 C standard and has been drastically pared back.
@@ -3828,15 +4008,6 @@ omitted entirely, the comma will be removed from the expansion. If the
variable argument is empty, or the token before @samp{##} is not a
comma, then @samp{##} behaves as a normal token paste.
-@item Traditional mode and GNU extensions
-
-Traditional mode used to be implemented in the same program as normal
-preprocessing. Therefore, all the GNU extensions to the preprocessor
-were still available in traditional mode. It is now a separate program
-and does not implement any of the GNU extensions, except for a partial
-implementation of assertions. Even those may be removed in a future
-release.
-
@item @samp{#line} and @samp{#include}
The @samp{#line} directive used to change GCC's notion of the
@@ -3934,25 +4105,26 @@ Note that you can also specify places to search using options such as
@option{-M} (@pxref{Invocation}). These take precedence over
environment variables, which in turn take precedence over the
configuration of GCC@.
-
+
@include cppenv.texi
@c man end
+@page
@include fdl.texi
@page
-@node Option Index
-@unnumbered Option Index
-
-CPP's command line options are indexed here without any initial
-@samp{-} or @samp{--}.
-
-@printindex op
-
@node Index of Directives
@unnumbered Index of Directives
@printindex fn
+@node Option Index
+@unnumbered Option Index
+@noindent
+CPP's command line options and environment variables are indexed here
+without any initial @samp{-} or @samp{--}.
+@printindex op
+
+@page
@node Concept Index
@unnumbered Concept Index
@printindex cp
diff --git a/contrib/gcc/doc/cppenv.texi b/contrib/gcc/doc/cppenv.texi
index d60f7ee..7a913f1 100644
--- a/contrib/gcc/doc/cppenv.texi
+++ b/contrib/gcc/doc/cppenv.texi
@@ -10,7 +10,7 @@
@c If this file is included with the flag ``cppmanual'' set, it is
@c formatted for inclusion in the CPP manual; otherwise the main GCC manual.
-@ftable @env
+@vtable @env
@item CPATH
@itemx C_INCLUDE_PATH
@itemx CPLUS_INCLUDE_PATH
@@ -25,7 +25,7 @@ semicolon, and for almost all other targets it is a colon.
@env{CPATH} specifies a list of directories to be searched as if
specified with @option{-I}, but after any paths given with @option{-I}
-options on the command line. The environment variable is used
+options on the command line. This environment variable is used
regardless of which language is being preprocessed.
The remaining environment variables apply only when preprocessing the
@@ -33,12 +33,19 @@ particular language indicated. Each specifies a list of directories
to be searched as if specified with @option{-isystem}, but after any
paths given with @option{-isystem} options on the command line.
+In all these variables, an empty element instructs the compiler to
+search its current working directory. Empty elements can appear at the
+beginning or end of a path. For instance, if the value of
+@env{CPATH} is @code{:/special/include}, that has the same
+effect as @samp{@w{-I. -I/special/include}}.
+
+@c man end
@ifset cppmanual
See also @ref{Search Path}.
@end ifset
+@c man begin ENVIRONMENT
@item DEPENDENCIES_OUTPUT
-@anchor{DEPENDENCIES_OUTPUT}
@cindex dependencies for make as output
If this variable is set, its value specifies how to output
dependencies for Make based on the non-system header files processed
@@ -63,15 +70,14 @@ with an optional @option{-MT} switch too.
@item SUNPRO_DEPENDENCIES
@cindex dependencies for make as output
-This variable is the same as the environment variable
-@env{DEPENDENCIES_OUTPUT} (@pxref{DEPENDENCIES_OUTPUT}), except that
-system header files are not ignored, so it implies @option{-M} rather
-than @option{-MM}. However, the dependence on the main input file is
-omitted.
+This variable is the same as @env{DEPENDENCIES_OUTPUT} (see above),
+except that system header files are not ignored, so it implies
+@option{-M} rather than @option{-MM}. However, the dependence on the
+main input file is omitted.
@ifset cppmanual
@xref{Invocation}.
@end ifset
@ifclear cppmanual
@xref{Preprocessor Options}.
@end ifclear
-@end ftable
+@end vtable
diff --git a/contrib/gcc/doc/cppopts.texi b/contrib/gcc/doc/cppopts.texi
index 308e989..7abb803 100644
--- a/contrib/gcc/doc/cppopts.texi
+++ b/contrib/gcc/doc/cppopts.texi
@@ -51,16 +51,14 @@ for header files.
@xref{Search Path}.
@end ifset
Directories named by @option{-I} are searched before the standard
-system include directories.
-
-It is dangerous to specify a standard system include directory in an
-@option{-I} option. This defeats the special treatment of system
-headers
+system include directories. If the directory @var{dir} is a standard
+system include directory, the option is ignored to ensure that the
+default search order for system directories and the special treatment
+of system headers are not defeated
@ifset cppmanual
(@pxref{System Headers})
@end ifset
-. It can also defeat the repairs to buggy system headers which GCC
-makes when it is installed.
+.
@item -o @var{file}
@opindex o
@@ -110,6 +108,44 @@ Warn whenever an identifier which is not a macro is encountered in an
@samp{#if} directive, outside of @samp{defined}. Such identifiers are
replaced with zero.
+@item -Wunused-macros
+@opindex Wunused-macros
+Warn about macros defined in the main file that are unused. A macro
+is @dfn{used} if it is expanded or tested for existence at least once.
+The preprocessor will also warn if the macro has not been used at the
+time it is redefined or undefined.
+
+Built-in macros, macros defined on the command line, and macros
+defined in include files are not warned about.
+
+@strong{Note:} If a macro is actually used, but only used in skipped
+conditional blocks, then CPP will report it as unused. To avoid the
+warning in such a case, you might improve the scope of the macro's
+definition by, for example, moving it into the first skipped block.
+Alternatively, you could provide a dummy use with something like:
+
+@smallexample
+#if defined the_macro_causing_the_warning
+#endif
+@end smallexample
+
+@item -Wendif-labels
+@opindex Wendif-labels
+Warn whenever an @samp{#else} or an @samp{#endif} are followed by text.
+This usually happens in code of the form
+
+@smallexample
+#if FOO
+@dots{}
+#else FOO
+@dots{}
+#endif FOO
+@end smallexample
+
+@noindent
+The second and third @code{FOO} should be in comments, but often are not
+in older programs. This warning is on by default.
+
@item -Werror
@opindex Werror
Make all warnings into hard errors. Source code which triggers warnings
@@ -158,10 +194,11 @@ This option does not suppress the preprocessor's debug output, such as
@option{-dM}. To avoid mixing such debug output with the dependency
rules you should explicitly specify the dependency output file with
@option{-MF}, or use an environment variable like
-@env{DEPENDENCIES_OUTPUT} (@pxref{DEPENDENCIES_OUTPUT}). Debug output
+@env{DEPENDENCIES_OUTPUT} (@pxref{Environment Variables}). Debug output
will still be sent to the regular output stream as normal.
-Passing @option{-M} to the driver implies @option{-E}.
+Passing @option{-M} to the driver implies @option{-E}, and suppresses
+warnings with an implicit @option{-w}.
@item -MM
@opindex MM
@@ -187,10 +224,13 @@ When used with the driver options @option{-MD} or @option{-MMD},
@item -MG
@opindex MG
-When used with @option{-M} or @option{-MM}, @option{-MG} says to treat missing
-header files as generated files and assume they live in the same
-directory as the source file. It suppresses preprocessed output, as a
-missing header file is ordinarily an error.
+In conjunction with an option such as @option{-M} requesting
+dependency generation, @option{-MG} assumes missing header files are
+generated files and adds them to the dependency list without raising
+an error. The dependency filename is taken directly from the
+@code{#include} directive without prepending any path. @option{-MG}
+also suppresses preprocessed output, as a missing header file renders
+this useless.
This feature is used in automatic updating of makefiles.
@@ -284,9 +324,8 @@ option.
@itemx -ansi
@opindex ansi
@opindex std=
-Specify the standard to which the code should conform. Currently cpp
-only knows about the standards for C; other language standards will be
-added in the future.
+Specify the standard to which the code should conform. Currently CPP
+knows about C and C++ standards; others may be added in the future.
@var{standard}
may be one of:
@@ -314,6 +353,13 @@ The 1990 C standard plus GNU extensions. This is the default.
@item gnu99
@itemx gnu9x
The 1999 C standard plus GNU extensions.
+
+@item c++98
+The 1998 ISO C++ standard plus amendments.
+
+@item gnu++98
+The same as @option{-std=c++98} plus GNU extensions. This is the
+default for C++ code.
@end table
@item -I-
@@ -441,13 +487,6 @@ it does not use shell special characters.
Cancel an assertion with the predicate @var{predicate} and answer
@var{answer}.
-@item -A-
-@opindex A-
-Cancel all predefined assertions and all assertions preceding it on
-the command line. Also, undefine all predefined macros and all
-macros preceding it on the command line. (This is a historical wart and
-may change in the future.)
-
@item -dCHARS
@var{CHARS} is a sequence of one or more of the following characters,
and must not be preceded by a space. Other characters are interpreted
@@ -510,6 +549,19 @@ For example, comments appearing at the start of what would be a
directive line have the effect of turning that line into an ordinary
source line, since the first token on the line is no longer a @samp{#}.
+@item -CC
+Do not discard comments, including during macro expansion. This is
+like @option{-C}, except that comments contained within macros are
+also passed through to the output file where the macro is expanded.
+
+In addition to the side-effects of the @option{-C} option, the
+@option{-CC} option causes all C++-style comments inside a macro
+to be converted to C-style comments. This is to prevent later use
+of that macro from inadvertently commenting out the remainder of
+the source line.
+
+The @option{-CC} option is generally used to support lint comments.
+
@item -gcc
@opindex gcc
Define the macros @sc{__gnuc__}, @sc{__gnuc_minor__} and
@@ -517,10 +569,10 @@ Define the macros @sc{__gnuc__}, @sc{__gnuc_minor__} and
@command{gcc -E}; you can turn them off in that case with
@option{-no-gcc}.
-@item -traditional
-@opindex traditional
-Try to imitate the behavior of old-fashioned C, as opposed to ISO
-C@.
+@item -traditional-cpp
+@opindex traditional-cpp
+Try to imitate the behavior of old-fashioned C preprocessors, as
+opposed to ISO C preprocessors.
@ifset cppmanual
@xref{Traditional Mode}.
@end ifset
@@ -552,16 +604,8 @@ Replacement: [ ] @{ @} # \ ^ | ~
Enable special code to work around file systems which only permit very
short file names, such as MS-DOS@.
-@item -$
-@opindex $
-Forbid the use of @samp{$} in identifiers. The C standard allows
-implementations to define extra characters that can appear in
-identifiers. By default GNU CPP permits @samp{$}, a common extension.
-
-@item -h
@itemx --help
@itemx --target-help
-@opindex h
@opindex help
@opindex target-help
Print text describing all the command line options instead of
diff --git a/contrib/gcc/doc/extend.texi b/contrib/gcc/doc/extend.texi
index 281e4ac..484a646 100644
--- a/contrib/gcc/doc/extend.texi
+++ b/contrib/gcc/doc/extend.texi
@@ -1,4 +1,5 @@
-@c Copyright (C) 1988,1989,1992,1993,1994,1996,1998,1999,2000,2001,2002 Free Software Foundation, Inc.
+@c Copyright (C) 1988,1989,1992,1993,1994,1996,1998,1999,2000,2001,2002,
+@c 2003 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -35,6 +36,8 @@ along with the section number from the ISO/IEC 9899:1999 standard.
@item
@cite{How a diagnostic is identified (3.10, 5.1.1.3).}
+Diagnostics consist of all the output sent to stderr by GCC.
+
@item
@cite{Whether each nonempty sequence of white-space characters other than
new-line is retained or replaced by one space character in translation
@@ -58,6 +61,11 @@ and their correspondence to universal character names (6.4.2).}
@item
@cite{The number of significant initial characters in an identifier
(5.2.4.1, 6.4.2).}
+
+For internal names, all characters are significant. For external names,
+the number of significant characters are defined by the linker; for
+almost all targets, all characters are significant.
+
@end itemize
@node Characters implementation
@@ -123,6 +131,9 @@ sequence not represented in the execution character set (6.4.5).}
two's complement, or one's complement, and whether the extraordinary value
is a trap representation or an ordinary value (6.2.6.2).}
+GCC supports only two's complement integer types, and all bit patterns
+are ordinary values.
+
@item
@cite{The rank of any extended integer type relative to another extended
integer type with the same precision (6.3.1.1).}
@@ -238,10 +249,36 @@ of the same array (6.5.6).}
@cite{The extent to which suggestions made by using the @code{register}
storage-class specifier are effective (6.7.1).}
+The @code{register} specifier affects code generation only in these ways:
+
+@itemize @bullet
+@item
+When used as part of the register variable extension, see
+@ref{Explicit Reg Vars}.
+
+@item
+When @option{-O0} is in use, the compiler allocates distinct stack
+memory for all variables that do not have the @code{register}
+storage-class specifier; if @code{register} is specified, the variable
+may have a shorter lifespan than the code would indicate and may never
+be placed in memory.
+
+@item
+On some rare x86 targets, @code{setjmp} doesn't save the registers in
+all circumstances. In those cases, GCC doesn't allocate any variables
+in registers unless they are marked @code{register}.
+
+@end itemize
+
@item
@cite{The extent to which suggestions made by using the inline function
specifier are effective (6.7.4).}
+GCC will not inline any functions if the @option{-fno-inline} option is
+used or if @option{-O0} is used. Otherwise, GCC may still be unable to
+inline a function for many reasons; the @option{-Winline} option may be
+used to determine if a function has not been inlined and why not.
+
@end itemize
@node Structures unions enumerations and bit-fields implementation
@@ -315,6 +352,8 @@ name (6.10.2).}
@item
@cite{The nesting limit for @code{#include} processing (6.10.2).}
+GCC imposes a limit of 200 nested @code{#include}s.
+
@item
@cite{Whether the @samp{#} operator inserts a @samp{\} character before
the @samp{\} character that begins a universal character name in a
@@ -328,6 +367,10 @@ directive (6.10.6).}
@cite{The definitions for @code{__DATE__} and @code{__TIME__} when
respectively, the date and time of translation are not available (6.10.8).}
+If the date and time are not available, @code{__DATE__} expands to
+@code{@w{"??? ?? ????"}} and @code{__TIME__} expands to
+@code{"??:??:??"}.
+
@end itemize
@node Library functions implementation
@@ -393,9 +436,9 @@ extensions, accepted by GCC in C89 mode and in C++.
* Hex Floats:: Hexadecimal floating-point constants.
* Zero Length:: Zero-length arrays.
* Variable Length:: Arrays whose length is computed at run time.
+* Empty Structures:: Structures with no members.
* Variadic Macros:: Macros with a variable number of arguments.
* Escaped Newlines:: Slightly looser rules for escaped newlines.
-* Multi-line Strings:: String literals with embedded newlines.
* Subscripting:: Any array can be subscripted, even if not an lvalue.
* Pointer Arith:: Arithmetic on @code{void}-pointers and function pointers.
* Initializers:: Non-constant initializers.
@@ -431,6 +474,7 @@ extensions, accepted by GCC in C89 mode and in C++.
* Target Builtins:: Built-in functions specific to particular targets.
* Pragmas:: Pragmas accepted by GCC.
* Unnamed Fields:: Unnamed struct/union fields within structs/unions.
+* Thread-Local:: Per-thread variables.
@end menu
@node Statement Exprs
@@ -442,7 +486,6 @@ extensions, accepted by GCC in C89 mode and in C++.
@c the above section title wrapped and causes an underfull hbox.. i
@c changed it from "within" to "in". --mew 4feb93
-
A compound statement enclosed in parentheses may appear as an expression
in GNU C@. This allows you to use loops, switches, and local variables
within an expression.
@@ -549,7 +592,7 @@ __label__ @var{label};
or
@example
-__label__ @var{label1}, @var{label2}, @dots{};
+__label__ @var{label1}, @var{label2}, /* @r{@dots{}} */;
@end example
Local label declarations must come at the beginning of the statement
@@ -600,7 +643,7 @@ wherever a constant of that type is valid. For example:
@example
void *ptr;
-@dots{}
+/* @r{@dots{}} */
ptr = &&foo;
@end example
@@ -695,9 +738,9 @@ bar (int *array, int offset, int size)
int access (int *array, int index)
@{ return array[index + offset]; @}
int i;
- @dots{}
+ /* @r{@dots{}} */
for (i = 0; i < size; i++)
- @dots{} access (array, i) @dots{}
+ /* @r{@dots{}} */ access (array, i) /* @r{@dots{}} */
@}
@end group
@end example
@@ -757,10 +800,10 @@ bar (int *array, int offset, int size)
return array[index + offset];
@}
int i;
- @dots{}
+ /* @r{@dots{}} */
for (i = 0; i < size; i++)
- @dots{} access (array, i) @dots{}
- @dots{}
+ /* @r{@dots{}} */ access (array, i) /* @r{@dots{}} */
+ /* @r{@dots{}} */
return 0;
/* @r{Control comes here from @code{access}
@@ -781,14 +824,14 @@ bar (int *array, int offset, int size)
@{
__label__ failure;
auto int access (int *, int);
- @dots{}
+ /* @r{@dots{}} */
int access (int *array, int index)
@{
if (index > size)
goto failure;
return array[index + offset];
@}
- @dots{}
+ /* @r{@dots{}} */
@}
@end example
@@ -843,19 +886,6 @@ the containing function. You should specify, for @var{result}, a value
returned by @code{__builtin_apply}.
@end deftypefn
-@cindex underscores in variables in macros
-@cindex @samp{_} in variables in macros
-@cindex local variables in macros
-@cindex variables, local, in macros
-@cindex macros, local variables in
-
-The reason for using names that start with underscores for the local
-variables is to avoid conflicts with variable names that occur within the
-expressions that are substituted for @code{a} and @code{b}. Eventually we
-hope to design a new form of declaration syntax that allows you to declare
-variables whose scopes start only after their initializers; this will be a
-more reliable way to prevent such conflicts.
-
@node Typeof
@section Referring to a Type with @code{typeof}
@findex typeof
@@ -906,6 +936,19 @@ arithmetic type and evaluates each of its arguments exactly once:
_a > _b ? _a : _b; @})
@end example
+@cindex underscores in variables in macros
+@cindex @samp{_} in variables in macros
+@cindex local variables in macros
+@cindex variables, local, in macros
+@cindex macros, local variables in
+
+The reason for using names that start with underscores for the local
+variables is to avoid conflicts with variable names that occur within the
+expressions that are substituted for @code{a} and @code{b}. Eventually we
+hope to design a new form of declaration syntax that allows you to declare
+variables whose scopes start only after their initializers; this will be a
+more reliable way to prevent such conflicts.
+
@noindent
Some more examples of the use of @code{typeof}:
@@ -989,6 +1032,7 @@ This will work with all versions of GCC@.
@cindex lvalues, generalized
@cindex extensions, @code{?:}
@cindex @code{?:} extensions
+
Compound expressions, conditional expressions and casts are allowed as
lvalues provided their operands are lvalues. This means that you can take
their addresses or store values into them.
@@ -1181,17 +1225,14 @@ provided as built-in functions by GCC@.
GCC can allocate complex automatic variables in a noncontiguous
fashion; it's even possible for the real part to be in a register while
-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 GCC describes a noncontiguous complex
-variable as if it were two separate variables of noncomplex type.
+the imaginary part is on the stack (or vice-versa). Only the DWARF2
+debug info format can represent this, so use of DWARF2 is recommended.
+If you are using the stabs debug info format, GCC 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
variables are named @code{foo$real} and @code{foo$imag}. You can
examine and set these two fictitious variables with your debugger.
-A future version of GDB will know how to recognize such pairs and treat
-them as a single variable with a complex type.
-
@node Hex Floats
@section Hex Floats
@cindex hex floats
@@ -1241,7 +1282,7 @@ struct line *thisline = (struct line *)
thisline->length = this_length;
@end example
-In ISO C89, you would have to give @code{contents} a length of 1, which
+In ISO C90, you would have to give @code{contents} a length of 1, which
means either you waste space or complicate the argument to @code{malloc}.
In ISO C99, you would use a @dfn{flexible array member}, which is
@@ -1260,6 +1301,12 @@ of zero-length arrays, @code{sizeof} evaluates to zero.
@item
Flexible array members may only appear as the last member of a
@code{struct} that is otherwise non-empty.
+
+@item
+A structure containing a flexible array member, or a union containing
+such a structure (possibly recursively), may not be a member of a
+structure or an element of an array. (However, these uses are
+permitted by GCC as extensions.)
@end itemize
GCC versions before 3.0 allowed zero-length arrays to be statically
@@ -1311,6 +1358,21 @@ struct bar c = @{ @{ 1, @{ @} @} @}; // @r{Valid.}
struct foo d[1] = @{ @{ 1 @{ 2, 3, 4 @} @} @}; // @r{Invalid.}
@end example
+@node Empty Structures
+@section Structures With No Members
+@cindex empty structures
+@cindex zero-size structures
+
+GCC permits a C structure to have no members:
+
+@example
+struct empty @{
+@};
+@end example
+
+The structure will have size zero. In C++, empty structures are part
+of the language, and the language standard says they have size 1.
+
@node Variable Length
@section Arrays of Variable Length
@cindex variable-length arrays
@@ -1363,7 +1425,7 @@ You can also use variable-length arrays as arguments to functions:
struct entry
tester (int len, char data[len][len])
@{
- @dots{}
+ /* @r{@dots{}} */
@}
@end example
@@ -1378,7 +1440,7 @@ use a forward declaration in the parameter list---another GNU extension.
struct entry
tester (int len; char data[len][len], int len)
@{
- @dots{}
+ /* @r{@dots{}} */
@}
@end example
@@ -1463,29 +1525,16 @@ argument, these arguments are not macro expanded.
@cindex escaped newlines
@cindex newlines (escaped)
-Recently, the non-traditional preprocessor has relaxed its treatment of
-escaped newlines. Previously, the newline had to immediately follow a
+Recently, the preprocessor has relaxed its treatment of escaped
+newlines. Previously, the newline had to immediately follow a
backslash. The current implementation allows whitespace in the form of
spaces, horizontal and vertical tabs, and form feeds between the
backslash and the subsequent newline. The preprocessor issues a
warning, but treats it as a valid escaped newline and combines the two
lines to form a single logical line. This works within comments and
-tokens, including multi-line strings, as well as between tokens.
-Comments are @emph{not} treated as whitespace for the purposes of this
-relaxation, since they have not yet been replaced with spaces.
-
-@node Multi-line Strings
-@section String Literals with Embedded Newlines
-@cindex multi-line string literals
-
-As an extension, GNU CPP permits string literals to cross multiple lines
-without escaping the embedded newlines. Each embedded newline is
-replaced with a single @samp{\n} character in the resulting string
-literal, regardless of what form the newline took originally.
-
-CPP currently allows such strings in directives as well (other than the
-@samp{#include} family). This is deprecated and will eventually be
-removed.
+tokens, as well as between tokens. Comments are @emph{not} treated as
+whitespace for the purposes of this relaxation, since they have not
+yet been replaced with spaces.
@node Subscripting
@section Non-Lvalue Arrays May Have Subscripts
@@ -1545,7 +1594,7 @@ Here is an example of an initializer with run-time varying elements:
foo (float f, float g)
@{
float beat_freqs[2] = @{ f-g, f+g @};
- @dots{}
+ /* @r{@dots{}} */
@}
@end example
@@ -1834,7 +1883,7 @@ union type is equivalent to storing in a member of the union:
@example
union foo u;
-@dots{}
+/* @r{@dots{}} */
u = (union foo) x @equiv{} u.i = x
u = (union foo) y @equiv{} u.d = y
@end example
@@ -1843,7 +1892,7 @@ You can also use the union cast as a function argument:
@example
void hack (union foo);
-@dots{}
+/* @r{@dots{}} */
hack ((union foo) x);
@end example
@@ -1859,7 +1908,7 @@ C89 mode. For example, you could do:
@example
int i;
-@dots{}
+/* @r{@dots{}} */
i++;
int j = i + 2;
@end example
@@ -1878,6 +1927,7 @@ the enclosing block.
@cindex @code{volatile} applied to function
@cindex @code{const} applied to function
@cindex functions with @code{printf}, @code{scanf}, @code{strftime} or @code{strfmon} style arguments
+@cindex functions with non-null pointer arguments
@cindex functions that are passed arguments in registers on the 386
@cindex functions that pop the argument stack on the 386
@cindex functions that do not pop the argument stack on the 386
@@ -1891,14 +1941,14 @@ attributes when making a declaration. This keyword is followed by an
attribute specification inside double parentheses. The following
attributes are currently defined for functions on all targets:
@code{noreturn}, @code{noinline}, @code{always_inline},
-@code{pure}, @code{const},
+@code{pure}, @code{const}, @code{nothrow},
@code{format}, @code{format_arg}, @code{no_instrument_function},
@code{section}, @code{constructor}, @code{destructor}, @code{used},
-@code{unused}, @code{deprecated}, @code{weak}, @code{malloc}, and
-@code{alias}. Several other attributes are defined for functions on
-particular target systems. Other attributes, including @code{section}
-are supported for variables declarations (@pxref{Variable Attributes})
-and for types (@pxref{Type Attributes}).
+@code{unused}, @code{deprecated}, @code{weak}, @code{malloc},
+@code{alias}, and @code{nonnull}. Several other attributes are defined
+for functions on particular target systems. Other attributes, including
+@code{section} are supported for variables declarations
+(@pxref{Variable Attributes}) and for types (@pxref{Type Attributes}).
You may also specify attributes with @samp{__} preceding and following
each keyword. This allows you to use them in header files without
@@ -1921,9 +1971,9 @@ their own functions that never return. You can declare them
void fatal () __attribute__ ((noreturn));
void
-fatal (@dots{})
+fatal (/* @r{@dots{}} */)
@{
- @dots{} /* @r{Print error message.} */ @dots{}
+ /* @r{@dots{}} */ /* @r{Print error message.} */ /* @r{@dots{}} */
exit (1);
@}
@end group
@@ -2015,6 +2065,14 @@ extern const intfn square;
This approach does not work in GNU C++ from 2.6.0 on, since the language
specifies that the @samp{const} must be attached to the return value.
+@cindex @code{nothrow} function attribute
+@item nothrow
+The @code{nothrow} attribute is used to inform the compiler that a
+function cannot throw an exception. For example, most functions in
+the standard C library can be guaranteed not to throw an exception
+with the notable exceptions of @code{qsort} and @code{bsearch} that
+take function pointer arguments. The @code{nothrow} attribute is not
+implemented in GCC versions earlier than 3.2.
@item format (@var{archetype}, @var{string-index}, @var{first-to-check})
@cindex @code{format} function attribute
@@ -2110,6 +2168,35 @@ requested by @option{-ansi} or an appropriate @option{-std} option, or
@option{-ffreestanding} is used. @xref{C Dialect Options,,Options
Controlling C Dialect}.
+@item nonnull (@var{arg-index}, @dots{})
+@cindex @code{nonnull} function attribute
+The @code{nonnull} attribute specifies that some function parameters should
+be non-null pointers. For instance, the declaration:
+
+@smallexample
+extern void *
+my_memcpy (void *dest, const void *src, size_t len)
+ __attribute__((nonnull (1, 2)));
+@end smallexample
+
+@noindent
+causes the compiler to check that, in calls to @code{my_memcpy},
+arguments @var{dest} and @var{src} are non-null. If the compiler
+determines that a null pointer is passed in an argument slot marked
+as non-null, and the @option{-Wnonnull} option is enabled, a warning
+is issued. The compiler may also choose to make optimizations based
+on the knowledge that certain function arguments will not be null.
+
+If no argument index list is given to the @code{nonnull} attribute,
+all pointer arguments are marked as non-null. To illustrate, the
+following declaration is equivalent to the previous example:
+
+@smallexample
+extern void *
+my_memcpy (void *dest, const void *src, size_t len)
+ __attribute__((nonnull));
+@end smallexample
+
@item no_instrument_function
@cindex @code{no_instrument_function} function attribute
@opindex finstrument-functions
@@ -2208,7 +2295,7 @@ The @code{alias} attribute causes the declaration to be emitted as an
alias for another symbol, which must be specified. For instance,
@smallexample
-void __f () @{ /* do something */; @}
+void __f () @{ /* @r{Do something.} */; @}
void f () __attribute__ ((weak, alias ("__f")));
@end smallexample
@@ -2217,7 +2304,60 @@ mangled name for the target must be used.
Not all target machines support this attribute.
+@item visibility ("@var{visibility_type}")
+@cindex @code{visibility} attribute
+The @code{visibility} attribute on ELF targets causes the declaration
+to be emitted with default, hidden, protected or internal visibility.
+
+@smallexample
+void __attribute__ ((visibility ("protected")))
+f () @{ /* @r{Do something.} */; @}
+int i __attribute__ ((visibility ("hidden")));
+@end smallexample
+
+See the ELF gABI for complete details, but the short story is:
+
+@table @dfn
+@item default
+Default visibility is the normal case for ELF. This value is
+available for the visibility attribute to override other options
+that may change the assumed visibility of symbols.
+
+@item hidden
+Hidden visibility indicates that the symbol will not be placed into
+the dynamic symbol table, so no other @dfn{module} (executable or
+shared library) can reference it directly.
+
+@item protected
+Protected visibility indicates that the symbol will be placed in the
+dynamic symbol table, but that references within the defining module
+will bind to the local symbol. That is, the symbol cannot be overridden
+by another module.
+
+@item internal
+Internal visibility is like hidden visibility, but with additional
+processor specific semantics. Unless otherwise specified by the psABI,
+gcc defines internal visibility to mean that the function is @emph{never}
+called from another module. Note that hidden symbols, while then cannot
+be referenced directly by other modules, can be referenced indirectly via
+function pointers. By indicating that a symbol cannot be called from
+outside the module, gcc may for instance omit the load of a PIC register
+since it is known that the calling function loaded the correct value.
+@end table
+
+Not all ELF targets support this attribute.
+
+@item tls_model ("@var{tls_model}")
+@cindex @code{tls_model} attribute
+The @code{tls_model} attribute sets thread-local storage model
+(@pxref{Thread-Local}) of a particular @code{__thread} variable,
+overriding @code{-ftls-model=} command line switch on a per-variable
+basis.
+The @var{tls_model} argument should be one of @code{global-dynamic},
+@code{local-dynamic}, @code{initial-exec} or @code{local-exec}.
+
@item regparm (@var{number})
+@cindex @code{regparm} attribute
@cindex functions that are passed arguments in registers on the 386
On the Intel 386, the @code{regparm} attribute causes the compiler to
pass up to @var{number} integer arguments in registers EAX,
@@ -2225,6 +2365,16 @@ EDX, and ECX instead of on the stack. Functions that take a
variable number of arguments will continue to be passed all of their
arguments on the stack.
+Beware that on some ELF systems this attribute is unsuitable for
+global functions in shared libraries with lazy binding (which is the
+default). Lazy binding will send the first call via resolving code in
+the loader, which might assume EAX, EDX and ECX can be clobbered, as
+per the standard calling conventions. Solaris 8 is affected by this.
+GNU systems with GLIBC 2.1 or higher, and FreeBSD, are believed to be
+safe since the loaders there save all registers. (Lazy binding can be
+disabled with the linker or the loader if desired, to avoid the
+problem.)
+
@item stdcall
@cindex functions that pop the argument stack on the 386
On the Intel 386, the @code{stdcall} attribute causes the compiler to
@@ -2245,12 +2395,17 @@ useful to override the effects of the @option{-mrtd} switch.
The PowerPC compiler for Windows NT currently ignores the @code{cdecl}
attribute.
-@item longcall
+@item longcall/shortcall
@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.
+compiler to always call this function via a pointer, just as it would if
+the @option{-mlongcall} option had been specified. The @code{shortcall}
+attribute causes the compiler not to do this. These attributes override
+both the @option{-mlongcall} switch and the @code{#pragma longcall}
+setting.
+
+@xref{RS/6000 and PowerPC Options}, for more information on when long
+calls are and are not necessary.
@item long_call/short_call
@cindex indirect calls on ARM
@@ -2372,9 +2527,9 @@ attribute is present. Interrupts will be disabled inside function.
@item naked
@cindex function without a prologue/epilogue code
-Use this attribute on the ARM or AVR ports to indicate that the specified
-function do not need prologue/epilogue sequences generated by the
-compiler. It is up to the programmer to provide these sequences.
+Use this attribute on the ARM, AVR and IP2K ports to indicate that the
+specified function do not need prologue/epilogue sequences generated by
+the compiler. It is up to the programmer to provide these sequences.
@item model (@var{model-name})
@cindex function addressability on the M32R/D
@@ -2396,6 +2551,30 @@ 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).
+@item far
+@cindex functions which handle memory bank switching
+On 68HC11 and 68HC12 the @code{far} attribute causes the compiler to
+use a calling convention that takes care of switching memory banks when
+entering and leaving a function. This calling convention is also the
+default when using the @option{-mlong-calls} option.
+
+On 68HC12 the compiler will use the @code{call} and @code{rtc} instructions
+to call and return from a function.
+
+On 68HC11 the compiler will generate a sequence of instructions
+to invoke a board-specific routine to switch the memory bank and call the
+real function. The board-specific routine simulates a @code{call}.
+At the end of a function, it will jump to a board-specific routine
+instead of using @code{rts}. The board-specific return routine simulates
+the @code{rtc}.
+
+@item near
+@cindex functions which do not handle memory bank switching on 68HC11/68HC12
+On 68HC11 and 68HC12 the @code{near} attribute causes the compiler to
+use the normal calling convention based on @code{jsr} and @code{rts}.
+This attribute can be used to cancel the effect of the @option{-mlong-calls}
+option.
+
@end table
You can specify multiple attributes in a declaration by separating them
@@ -2729,11 +2908,10 @@ extension is irrelevant.
In GNU C, you may use C++ style comments, which start with @samp{//} and
continue until the end of the line. Many other C implementations allow
-such comments, and they are likely to be in a future C standard.
-However, C++ style comments are not recognized if you specify
-@w{@option{-ansi}}, a @option{-std} option specifying a version of ISO C
-before C99, or @w{@option{-traditional}}, since they are incompatible
-with traditional constructs like @code{dividend//*comment*/divisor}.
+such comments, and they are included in the 1999 C standard. However,
+C++ style comments are not recognized if you specify an @option{-std}
+option specifying a version of ISO C before C99, or @option{-ansi}
+(equivalent to @option{-std=c89}).
@node Dollar Signs
@section Dollar Signs in Identifier Names
@@ -2870,6 +3048,22 @@ up to a maximum of 8 byte alignment, then specifying @code{aligned(16)}
in an @code{__attribute__} will still only provide you with 8 byte
alignment. See your linker documentation for further information.
+@item cleanup (@var{cleanup_function})
+@cindex @code{cleanup} attribute
+The @code{cleanup} attribute runs a function when the variable goes
+out of scope. This attribute can only be applied to auto function
+scope variables; it may not be applied to parameters or variables
+with static storage duration. The function must take one parameter,
+a pointer to a type compatible with the variable. The return value
+of the function (if any) is ignored.
+
+If @option{-fexceptions} is enabled, then @var{cleanup_function}
+will be run during the stack unwinding that happens during the
+processing of the exception. Note that the @code{cleanup} attribute
+does not allow the exception to be caught, only to perform an action.
+It is undefined what happens if @var{cleanup_function} does not
+return normally.
+
@item mode (@var{mode})
@cindex @code{mode} attribute
This attribute specifies the data type for the declaration---whichever
@@ -3078,10 +3272,11 @@ packed))}.
The keyword @code{__attribute__} allows you to specify special
attributes of @code{struct} and @code{union} types when you define such
types. This keyword is followed by an attribute specification inside
-double parentheses. Five attributes are currently defined for types:
+double parentheses. Six attributes are currently defined for types:
@code{aligned}, @code{packed}, @code{transparent_union}, @code{unused},
-and @code{deprecated}. Other attributes are defined for functions
-(@pxref{Function Attributes}) and for variables (@pxref{Variable Attributes}).
+@code{deprecated} and @code{may_alias}. Other attributes are defined for
+functions (@pxref{Function Attributes}) and for variables
+(@pxref{Variable Attributes}).
You may also specify any one of these attributes with @samp{__}
preceding and following its keyword. This allows you to use these
@@ -3115,7 +3310,7 @@ typedef int more_aligned_int __attribute__ ((aligned (8)));
@noindent
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
+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
the compiler to use the @code{ldd} and @code{std} (doubleword load and
store) instructions when copying one variable of type @code{struct S} to
@@ -3292,6 +3487,36 @@ deprecated. Similarly for line 6.
The @code{deprecated} attribute can also be used for functions and
variables (@pxref{Function Attributes}, @pxref{Variable Attributes}.)
+@item may_alias
+Accesses to objects with types with this attribute are not subjected to
+type-based alias analysis, but are instead assumed to be able to alias
+any other type of objects, just like the @code{char} type. See
+@option{-fstrict-aliasing} for more information on aliasing issues.
+
+Example of use:
+
+@smallexample
+typedef short __attribute__((__may_alias__)) short_a;
+
+int
+main (void)
+@{
+ int a = 0x12345678;
+ short_a *b = (short_a *) &a;
+
+ b[1] = 0;
+
+ if (a == 0x12345678)
+ abort();
+
+ exit(0);
+@}
+@end smallexample
+
+If you replaced @code{short_a} with @code{short} in the variable
+declaration, the above program would abort when compiled with
+@option{-fstrict-aliasing}, which is on by default at @option{-O2} or
+above in recent GCC versions.
@end table
To specify multiple attributes, separate them by commas within the
@@ -3550,7 +3775,10 @@ asm volatile ("movc3 %0,%1,%2"
You may not write a clobber description in a way that overlaps with an
input or output operand. For example, you may not have an operand
describing a register class with one member if you mention that register
-in the clobber list. There is no way for you to specify that an input
+in the clobber list. Variables declared to live in specific registers
+(@pxref{Explicit Reg Vars}), and used as asm input or output operands must
+have no part mentioned in the clobber description.
+There is no way for you to specify that an input
operand is modified without also specifying it as an output
operand. Note that if all the output operands you specify are for this
purpose (and hence unused), you will then also need to specify
@@ -3854,7 +4082,7 @@ extern func () asm ("FUNC");
func (x, y)
int x, y;
-@dots{}
+/* @r{@dots{}} */
@end example
It is up to you to make sure that the assembler names you choose do not
@@ -3990,7 +4218,7 @@ being used for other purposes in the preceding functions.
Global register variables may not have initial values, because an
executable file has no means to supply initial contents for a register.
-On the Sparc, there are reports that g3 @dots{} g7 are suitable
+On the SPARC, there are reports that g3 @dots{} g7 are suitable
registers, but certain library functions, such as @code{getwd}, as well
as the subroutines for division and remainder, modify g3 and g4. g1 and
g2 are local temporaries.
@@ -4047,25 +4275,20 @@ be deleted or moved or simplified.
@cindex alternate keywords
@cindex keywords, alternate
-The option @option{-traditional} disables certain keywords;
@option{-ansi} and the various @option{-std} options disable certain
-others. This causes trouble when you want to use GNU C extensions, or
-ISO C features, in a general-purpose header file that should be usable
-by all programs, including ISO C programs and traditional ones. The
-keywords @code{asm}, @code{typeof} and @code{inline} cannot be used
-since they won't work in a program compiled with @option{-ansi}
-(although @code{inline} can be used in a program compiled with
-@option{-std=c99}), while the keywords @code{const}, @code{volatile},
-@code{signed}, @code{typeof} and @code{inline} won't work in a program
-compiled with @option{-traditional}. The ISO C99 keyword
+keywords. This causes trouble when you want to use GNU C extensions, or
+a general-purpose header file that should be usable by all programs,
+including ISO C programs. The keywords @code{asm}, @code{typeof} and
+@code{inline} are not available in programs compiled with
+@option{-ansi} or @option{-std} (although @code{inline} can be used in a
+program compiled with @option{-std=c99}). The ISO C99 keyword
@code{restrict} is only available when @option{-std=gnu99} (which will
eventually be the default) or @option{-std=c99} (or the equivalent
@option{-std=iso9899:1999}) is used.
The way to solve these problems is to put @samp{__} at the beginning and
end of each problematical keyword. For example, use @code{__asm__}
-instead of @code{asm}, @code{__const__} instead of @code{const}, and
-@code{__inline__} instead of @code{inline}.
+instead of @code{asm}, and @code{__inline__} instead of @code{inline}.
Other C compilers won't accept these alternative keywords; if you want to
compile with another compiler, you can define the alternate keywords as
@@ -4197,7 +4420,10 @@ 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.
+of the caller of the current function, and so forth. When inlining
+the expected behavior is that the function will return the address of
+the function that will be returned to. To work around this behavior use
+the @code{noinline} function attribute.
The @var{level} argument must be a constant integer.
@@ -4273,28 +4499,49 @@ A floating point value, as wide as a SI mode integer, usually 32 bits.
A floating point value, as wide as a DI mode integer, usually 64 bits.
@end table
-Not all base types or combinations are always valid; which modes can be used
-is determined by the target machine. For example, if targetting the i386 MMX
-extensions, only @code{V8QI}, @code{V4HI} and @code{V2SI} are allowed modes.
+Specifying a combination that is not valid for the current architecture
+will cause gcc to synthesize the instructions using a narrower mode.
+For example, if you specify a variable of type @code{V4SI} and your
+architecture does not allow for this specific SIMD type, gcc will
+produce code that uses 4 @code{SIs}.
+
+The types defined in this manner can be used with a subset of normal C
+operations. Currently, gcc will allow using the following operators on
+these types: @code{+, -, *, /, unary minus}@.
+
+The operations behave like C++ @code{valarrays}. Addition is defined as
+the addition of the corresponding elements of the operands. For
+example, in the code below, each of the 4 elements in @var{a} will be
+added to the corresponding 4 elements in @var{b} and the resulting
+vector will be stored in @var{c}.
+
+@example
+typedef int v4si __attribute__ ((mode(V4SI)));
+
+v4si a, b, c;
+
+c = a + b;
+@end example
-There are no @code{V1xx} vector modes - they would be identical to the
-corresponding base mode.
+Subtraction, multiplication, and division operate in a similar manner.
+Likewise, the result of using the unary minus operator on a vector type
+is a vector whose elements are the negative value of the corresponding
+elements in the operand.
-There is no distinction between signed and unsigned vector modes. This
-distinction is made by the operations that perform on the vectors, not
-by the data type.
+You can declare variables and use them in function calls and returns, as
+well as in assignments and some casts. You can specify a vector type as
+a return type for a function. Vector types can also be used as function
+arguments. It is possible to cast from one vector type to another,
+provided they are of the same size (in fact, you can also cast vectors
+to and from other datatypes of the same size).
-The types defined in this manner are somewhat special, they cannot be
-used with most normal C operations (i.e., a vector addition can @emph{not}
-be represented by a normal addition of two vector type variables). You
-can declare only variables and use them in function calls and returns, as
-well as in assignments and some casts. It is possible to cast from one
-vector type to another, provided they are of the same size (in fact, you
-can also cast vectors to and from other datatypes of the same size).
+You cannot operate between vectors of different lengths or different
+signedness without a cast.
-A port that supports vector operations provides a set of built-in functions
-that can be used to operate on vectors. For example, a function to add two
-vectors and multiply the result by a third could look like this:
+A port that supports hardware vector operations, usually provides a set
+of built-in functions that can be used to operate on vectors. For
+example, a function to add two vectors and multiply the result by a
+third could look like this:
@example
v4si f (v4si a, v4si b, v4si c)
@@ -4334,6 +4581,9 @@ v4si f (v4si a, v4si b, v4si c)
@findex exit
@findex _exit
@findex _Exit
+@findex exp
+@findex expf
+@findex expl
@findex fabs
@findex fabsf
@findex fabsl
@@ -4346,18 +4596,27 @@ v4si f (v4si a, v4si b, v4si c)
@findex index
@findex labs
@findex llabs
+@findex log
+@findex logf
+@findex logl
@findex memcmp
@findex memcpy
@findex memset
@findex printf
@findex printf_unlocked
+@findex putchar
+@findex puts
@findex rindex
+@findex scanf
@findex sin
@findex sinf
@findex sinl
+@findex snprintf
+@findex sprintf
@findex sqrt
@findex sqrtf
@findex sqrtl
+@findex sscanf
@findex strcat
@findex strchr
@findex strcmp
@@ -4371,6 +4630,11 @@ v4si f (v4si a, v4si b, v4si c)
@findex strrchr
@findex strspn
@findex strstr
+@findex vprintf
+@findex vscanf
+@findex vsnprintf
+@findex vsprintf
+@findex vsscanf
GCC provides a large number of built-in functions other than the ones
mentioned above. Some of these are for internal use in the processing
@@ -4395,7 +4659,9 @@ The functions @code{abort}, @code{exit}, @code{_Exit} and @code{_exit}
are recognized and presumed not to return, but otherwise are not built
in. @code{_exit} is not recognized in strict ISO C mode (@option{-ansi},
@option{-std=c89} or @option{-std=c99}). @code{_Exit} is not recognized in
-strict C89 mode (@option{-ansi} or @option{-std=c89}).
+strict C89 mode (@option{-ansi} or @option{-std=c89}). All these functions
+have corresponding versions prefixed with @code{__builtin_}, which may be
+used even in strict C89 mode.
Outside strict ISO C mode, the functions @code{alloca}, @code{bcmp},
@code{bzero}, @code{index}, @code{rindex}, @code{ffs}, @code{fputs_unlocked},
@@ -4406,20 +4672,26 @@ mode.
The ISO C99 functions @code{conj}, @code{conjf}, @code{conjl},
@code{creal}, @code{crealf}, @code{creall}, @code{cimag}, @code{cimagf},
-@code{cimagl}, @code{llabs} and @code{imaxabs} are handled as built-in
-functions except in strict ISO C89 mode. There are also built-in
+@code{cimagl}, @code{imaxabs}, @code{llabs}, @code{snprintf},
+@code{vscanf}, @code{vsnprintf} and @code{vsscanf} are handled as built-in
+functions except in strict ISO C90 mode. There are also built-in
versions of the ISO C99 functions @code{cosf}, @code{cosl},
-@code{fabsf}, @code{fabsl}, @code{sinf}, @code{sinl}, @code{sqrtf}, and
-@code{sqrtl}, that are recognized in any mode since ISO C89 reserves
+@code{expf}, @code{expl}, @code{fabsf}, @code{fabsl},
+@code{logf}, @code{logl}, @code{sinf}, @code{sinl}, @code{sqrtf}, and
+@code{sqrtl}, that are recognized in any mode since ISO C90 reserves
these names for the purpose to which ISO C99 puts them. All these
functions have corresponding versions prefixed with @code{__builtin_}.
-The ISO C89 functions @code{abs}, @code{cos}, @code{fabs},
-@code{fprintf}, @code{fputs}, @code{labs}, @code{memcmp}, @code{memcpy},
-@code{memset}, @code{printf}, @code{sin}, @code{sqrt}, @code{strcat},
+The ISO C90 functions @code{abs}, @code{cos}, @code{exp}, @code{fabs},
+@code{fprintf}, @code{fputs}, @code{labs}, @code{log},
+@code{memcmp}, @code{memcpy},
+@code{memset}, @code{printf}, @code{putchar}, @code{puts}, @code{scanf},
+@code{sin}, @code{snprintf}, @code{sprintf}, @code{sqrt}, @code{sscanf},
+@code{strcat},
@code{strchr}, @code{strcmp}, @code{strcpy}, @code{strcspn},
@code{strlen}, @code{strncat}, @code{strncmp}, @code{strncpy},
-@code{strpbrk}, @code{strrchr}, @code{strspn}, and @code{strstr} are all
+@code{strpbrk}, @code{strrchr}, @code{strspn}, @code{strstr},
+@code{vprintf} and @code{vsprintf} are all
recognized as built-in functions unless @option{-fno-builtin} is
specified (or @option{-fno-builtin-@var{function}} is specified for an
individual function). All of these functions have corresponding
@@ -4506,13 +4778,15 @@ as @var{exp2}.
Example:
@smallexample
-#define foo(x) \
- __builtin_choose_expr (__builtin_types_compatible_p (typeof (x), double), \
- foo_double (x), \
- __builtin_choose_expr (__builtin_types_compatible_p (typeof (x), float), \
- foo_float (x), \
- /* @r{The void expression results in a compile-time error} \
- @r{when assigning the result to something.} */ \
+#define foo(x) \
+ __builtin_choose_expr ( \
+ __builtin_types_compatible_p (typeof (x), double), \
+ foo_double (x), \
+ __builtin_choose_expr ( \
+ __builtin_types_compatible_p (typeof (x), float), \
+ foo_float (x), \
+ /* @r{The void expression results in a compile-time error} \
+ @r{when assigning the result to something.} */ \
(void)0))
@end smallexample
@@ -4559,7 +4833,7 @@ data. For instance, you can write
@smallexample
static const int table[] = @{
__builtin_constant_p (EXPRESSION) ? (EXPRESSION) : -1,
- /* ... */
+ /* @r{@dots{}} */
@};
@end smallexample
@@ -4635,7 +4909,7 @@ for (i = 0; i < n; i++)
a[i] = a[i] + b[i];
__builtin_prefetch (&a[i+j], 1, 1);
__builtin_prefetch (&b[i+j], 0, 1);
- /* ... */
+ /* @r{@dots{}} */
@}
@end smallexample
@@ -4649,6 +4923,74 @@ is evaluated if it includes side effects but no other code is generated
and GCC does not issue a warning.
@end deftypefn
+@deftypefn {Built-in Function} double __builtin_huge_val (void)
+Returns a positive infinity, if supported by the floating-point format,
+else @code{DBL_MAX}. This function is suitable for implementing the
+ISO C macro @code{HUGE_VAL}.
+@end deftypefn
+
+@deftypefn {Built-in Function} float __builtin_huge_valf (void)
+Similar to @code{__builtin_huge_val}, except the return type is @code{float}.
+@end deftypefn
+
+@deftypefn {Built-in Function} {long double} __builtin_huge_vall (void)
+Similar to @code{__builtin_huge_val}, except the return
+type is @code{long double}.
+@end deftypefn
+
+@deftypefn {Built-in Function} double __builtin_inf (void)
+Similar to @code{__builtin_huge_val}, except a warning is generated
+if the target floating-point format does not support infinities.
+This function is suitable for implementing the ISO C99 macro @code{INFINITY}.
+@end deftypefn
+
+@deftypefn {Built-in Function} float __builtin_inff (void)
+Similar to @code{__builtin_inf}, except the return type is @code{float}.
+@end deftypefn
+
+@deftypefn {Built-in Function} {long double} __builtin_infl (void)
+Similar to @code{__builtin_inf}, except the return
+type is @code{long double}.
+@end deftypefn
+
+@deftypefn {Built-in Function} double __builtin_nan (const char *str)
+This is an implementation of the ISO C99 function @code{nan}.
+
+Since ISO C99 defines this function in terms of @code{strtod}, which we
+do not implement, a description of the parsing is in order. The string
+is parsed as by @code{strtol}; that is, the base is recognized by
+leading @samp{0} or @samp{0x} prefixes. The number parsed is placed
+in the significand such that the least significant bit of the number
+is at the least significant bit of the significand. The number is
+truncated to fit the significand field provided. The significand is
+forced to be a quiet NaN.
+
+This function, if given a string literal, is evaluated early enough
+that it is considered a compile-time constant.
+@end deftypefn
+
+@deftypefn {Built-in Function} float __builtin_nanf (const char *str)
+Similar to @code{__builtin_nan}, except the return type is @code{float}.
+@end deftypefn
+
+@deftypefn {Built-in Function} {long double} __builtin_nanl (const char *str)
+Similar to @code{__builtin_nan}, except the return type is @code{long double}.
+@end deftypefn
+
+@deftypefn {Built-in Function} double __builtin_nans (const char *str)
+Similar to @code{__builtin_nan}, except the significand is forced
+to be a signaling NaN. The @code{nans} function is proposed by
+@uref{http://std.dkuug.dk/JTC1/SC22/WG14/www/docs/n965.htm,,WG14 N965}.
+@end deftypefn
+
+@deftypefn {Built-in Function} float __builtin_nansf (const char *str)
+Similar to @code{__builtin_nans}, except the return type is @code{float}.
+@end deftypefn
+
+@deftypefn {Built-in Function} {long double} __builtin_nansl (const char *str)
+Similar to @code{__builtin_nans}, except the return type is @code{long double}.
+@end deftypefn
+
@node Target Builtins
@section Built-in Functions Specific to Particular Target Machines
@@ -4657,10 +4999,93 @@ to those machines. Generally these generate calls to specific machine
instructions, but allow the compiler to schedule those calls.
@menu
+* Alpha Built-in Functions::
* X86 Built-in Functions::
* PowerPC AltiVec Built-in Functions::
@end menu
+@node Alpha Built-in Functions
+@subsection Alpha Built-in Functions
+
+These built-in functions are available for the Alpha family of
+processors, depending on the command-line switches used.
+
+The following built-in functions are always available. They
+all generate the machine instruction that is part of the name.
+
+@example
+long __builtin_alpha_implver (void)
+long __builtin_alpha_rpcc (void)
+long __builtin_alpha_amask (long)
+long __builtin_alpha_cmpbge (long, long)
+long __builtin_alpha_extbl (long, long)
+long __builtin_alpha_extwl (long, long)
+long __builtin_alpha_extll (long, long)
+long __builtin_alpha_extql (long, long)
+long __builtin_alpha_extwh (long, long)
+long __builtin_alpha_extlh (long, long)
+long __builtin_alpha_extqh (long, long)
+long __builtin_alpha_insbl (long, long)
+long __builtin_alpha_inswl (long, long)
+long __builtin_alpha_insll (long, long)
+long __builtin_alpha_insql (long, long)
+long __builtin_alpha_inswh (long, long)
+long __builtin_alpha_inslh (long, long)
+long __builtin_alpha_insqh (long, long)
+long __builtin_alpha_mskbl (long, long)
+long __builtin_alpha_mskwl (long, long)
+long __builtin_alpha_mskll (long, long)
+long __builtin_alpha_mskql (long, long)
+long __builtin_alpha_mskwh (long, long)
+long __builtin_alpha_msklh (long, long)
+long __builtin_alpha_mskqh (long, long)
+long __builtin_alpha_umulh (long, long)
+long __builtin_alpha_zap (long, long)
+long __builtin_alpha_zapnot (long, long)
+@end example
+
+The following built-in functions are always with @option{-mmax}
+or @option{-mcpu=@var{cpu}} where @var{cpu} is @code{pca56} or
+later. They all generate the machine instruction that is part
+of the name.
+
+@example
+long __builtin_alpha_pklb (long)
+long __builtin_alpha_pkwb (long)
+long __builtin_alpha_unpkbl (long)
+long __builtin_alpha_unpkbw (long)
+long __builtin_alpha_minub8 (long, long)
+long __builtin_alpha_minsb8 (long, long)
+long __builtin_alpha_minuw4 (long, long)
+long __builtin_alpha_minsw4 (long, long)
+long __builtin_alpha_maxub8 (long, long)
+long __builtin_alpha_maxsb8 (long, long)
+long __builtin_alpha_maxuw4 (long, long)
+long __builtin_alpha_maxsw4 (long, long)
+long __builtin_alpha_perr (long, long)
+@end example
+
+The following built-in functions are always with @option{-mcix}
+or @option{-mcpu=@var{cpu}} where @var{cpu} is @code{ev67} or
+later. They all generate the machine instruction that is part
+of the name.
+
+@example
+long __builtin_alpha_cttz (long)
+long __builtin_alpha_ctlz (long)
+long __builtin_alpha_ctpop (long)
+@end example
+
+The following builtins are available on systems that use the OSF/1
+PALcode. Normally they invoke the @code{rduniq} and @code{wruniq}
+PAL calls, but when invoked with @option{-mtls-kernel}, they invoke
+@code{rdval} and @code{wrval}.
+
+@example
+void *__builtin_thread_pointer (void)
+void __builtin_set_thread_pointer (void *)
+@end example
+
@node X86 Built-in Functions
@subsection X86 Built-in Functions
@@ -4784,14 +5209,10 @@ v4si __builtin_ia32_cmpordps (v4sf, v4sf)
v4si __builtin_ia32_cmpeqss (v4sf, v4sf)
v4si __builtin_ia32_cmpltss (v4sf, v4sf)
v4si __builtin_ia32_cmpless (v4sf, v4sf)
-v4si __builtin_ia32_cmpgtss (v4sf, v4sf)
-v4si __builtin_ia32_cmpgess (v4sf, v4sf)
v4si __builtin_ia32_cmpunordss (v4sf, v4sf)
v4si __builtin_ia32_cmpneqss (v4sf, v4sf)
v4si __builtin_ia32_cmpnlts (v4sf, v4sf)
v4si __builtin_ia32_cmpnless (v4sf, v4sf)
-v4si __builtin_ia32_cmpngtss (v4sf, v4sf)
-v4si __builtin_ia32_cmpngess (v4sf, v4sf)
v4si __builtin_ia32_cmpordss (v4sf, v4sf)
v4sf __builtin_ia32_maxps (v4sf, v4sf)
v4sf __builtin_ia32_maxss (v4sf, v4sf)
@@ -4904,6 +5325,25 @@ The following functions are made available by including
@option{-mabi=altivec}. The functions implement the functionality
described in Motorola's AltiVec Programming Interface Manual.
+There are a few differences from Motorola's documentation and GCC's
+implementation. Vector constants are done with curly braces (not
+parentheses). Vector initializers require no casts if the vector
+constant is of the same type as the variable it is initializing. The
+@code{vector bool} type is deprecated and will be discontinued in
+further revisions. Use @code{vector signed} instead. If @code{signed}
+or @code{unsigned} is omitted, the vector type will default to
+@code{signed}. Lastly, all overloaded functions are implemented with macros
+for the C implementation. So code the following example will not work:
+
+@smallexample
+ vec_add ((vector signed int)@{1, 2, 3, 4@}, foo);
+@end smallexample
+
+Since vec_add is a macro, the vector constant in the above example will
+be treated as four different arguments. Wrap the entire argument in
+parentheses for this to work. The C++ implementation does not use
+macros.
+
@emph{Note:} Only the @code{<altivec.h>} interface is supported.
Internally, GCC uses built-in functions to achieve the functionality in
the aforementioned header file, but they are not supported and are
@@ -5249,7 +5689,9 @@ vector unsigned int vec_mulo (vector unsigned short,
vector signed int vec_mulo (vector signed short, vector signed short);
vector float vec_nmsub (vector float, vector float, vector float);
+@end smallexample
+@smallexample
vector float vec_nor (vector float, vector float);
vector signed int vec_nor (vector signed int, vector signed int);
vector unsigned int vec_nor (vector unsigned int, vector unsigned int);
@@ -5815,7 +6257,9 @@ vector signed int vec_any_eq (vector signed char, vector unsigned char);
vector signed int vec_any_eq (vector signed char, vector signed char);
vector signed int vec_any_eq (vector unsigned char, vector signed char);
+@end smallexample
+@smallexample
vector signed int vec_any_eq (vector unsigned char,
vector unsigned char);
vector signed int vec_any_eq (vector signed short,
@@ -5970,6 +6414,7 @@ for further explanation.
@menu
* ARM Pragmas::
+* RS/6000 and PowerPC Pragmas::
* Darwin Pragmas::
* Solaris Pragmas::
* Tru64 Pragmas::
@@ -5998,6 +6443,27 @@ Do not affect the @code{long_call} or @code{short_call} attributes of
subsequent functions.
@end table
+@node RS/6000 and PowerPC Pragmas
+@subsection RS/6000 and PowerPC Pragmas
+
+The RS/6000 and PowerPC targets define one pragma for controlling
+whether or not the @code{longcall} attribute is added to function
+declarations by default. This pragma overrides the @option{-mlongcall}
+option, but not the @code{longcall} and @code{shortcall} attributes.
+@xref{RS/6000 and PowerPC Options}, for more information about when long
+calls are and are not necessary.
+
+@table @code
+@item longcall (1)
+@cindex pragma, longcall
+Apply the @code{longcall} attribute to all subsequent function
+declarations.
+
+@item longcall (0)
+Do not apply the @code{longcall} attribute to subsequent function
+declarations.
+@end table
+
@c Describe c4x pragmas here.
@c Describe h8300 pragmas here.
@c Describe i370 pragmas here.
@@ -6010,7 +6476,7 @@ subsequent functions.
The following pragmas are available for all architectures running the
Darwin operating system. These are useful for compatibility with other
-MacOS compilers.
+Mac OS compilers.
@table @code
@item mark @var{tokens}@dots{}
@@ -6066,13 +6532,14 @@ is supported.
This pragma renames all subsequent function and variable declarations
such that @var{string} is prepended to the name. This effect may be
-terminated by using another @code{extern_prefix} pragma with the
+terminated by using another @code{extern_prefix} pragma with the
empty string.
This pragma is similar in intent to to the asm labels extension
(@pxref{Asm Labels}) in that the system programmer wants to change
the assembly-level ABI without changing the source-level API. The
-preprocessor defines @code{__EXTERN_PREFIX} if the pragma is available.
+preprocessor defines @code{__PRAGMA_EXTERN_PREFIX} if the pragma is
+available.
@end table
@node Unnamed Fields
@@ -6116,6 +6583,265 @@ It is ambiguous which @code{a} is being referred to with @samp{foo.a}.
Such constructs are not supported and must be avoided. In the future,
such constructs may be detected and treated as compilation errors.
+@node Thread-Local
+@section Thread-Local Storage
+@cindex Thread-Local Storage
+@cindex @acronym{TLS}
+@cindex __thread
+
+Thread-local storage (@acronym{TLS}) is a mechanism by which variables
+are allocated such that there is one instance of the variable per extant
+thread. The run-time model GCC uses to implement this originates
+in the IA-64 processor-specific ABI, but has since been migrated
+to other processors as well. It requires significant support from
+the linker (@command{ld}), dynamic linker (@command{ld.so}), and
+system libraries (@file{libc.so} and @file{libpthread.so}), so it
+is not available everywhere.
+
+At the user level, the extension is visible with a new storage
+class keyword: @code{__thread}. For example:
+
+@example
+__thread int i;
+extern __thread struct state s;
+static __thread char *p;
+@end example
+
+The @code{__thread} specifier may be used alone, with the @code{extern}
+or @code{static} specifiers, but with no other storage class specifier.
+When used with @code{extern} or @code{static}, @code{__thread} must appear
+immediately after the other storage class specifier.
+
+The @code{__thread} specifier may be applied to any global, file-scoped
+static, function-scoped static, or static data member of a class. It may
+not be applied to block-scoped automatic or non-static data member.
+
+When the address-of operator is applied to a thread-local variable, it is
+evaluated at run-time and returns the address of the current thread's
+instance of that variable. An address so obtained may be used by any
+thread. When a thread terminates, any pointers to thread-local variables
+in that thread become invalid.
+
+No static initialization may refer to the address of a thread-local variable.
+
+In C++, if an initializer is present for a thread-local variable, it must
+be a @var{constant-expression}, as defined in 5.19.2 of the ANSI/ISO C++
+standard.
+
+See @uref{http://people.redhat.com/drepper/tls.pdf,
+ELF Handling For Thread-Local Storage} for a detailed explanation of
+the four thread-local storage addressing models, and how the run-time
+is expected to function.
+
+@menu
+* C99 Thread-Local Edits::
+* C++98 Thread-Local Edits::
+@end menu
+
+@node C99 Thread-Local Edits
+@subsection ISO/IEC 9899:1999 Edits for Thread-Local Storage
+
+The following are a set of changes to ISO/IEC 9899:1999 (aka C99)
+that document the exact semantics of the language extension.
+
+@itemize @bullet
+@item
+@cite{5.1.2 Execution environments}
+
+Add new text after paragraph 1
+
+@quotation
+Within either execution environment, a @dfn{thread} is a flow of
+control within a program. It is implementation defined whether
+or not there may be more than one thread associated with a program.
+It is implementation defined how threads beyond the first are
+created, the name and type of the function called at thread
+startup, and how threads may be terminated. However, objects
+with thread storage duration shall be initialized before thread
+startup.
+@end quotation
+
+@item
+@cite{6.2.4 Storage durations of objects}
+
+Add new text before paragraph 3
+
+@quotation
+An object whose identifier is declared with the storage-class
+specifier @w{@code{__thread}} has @dfn{thread storage duration}.
+Its lifetime is the entire execution of the thread, and its
+stored value is initialized only once, prior to thread startup.
+@end quotation
+
+@item
+@cite{6.4.1 Keywords}
+
+Add @code{__thread}.
+
+@item
+@cite{6.7.1 Storage-class specifiers}
+
+Add @code{__thread} to the list of storage class specifiers in
+paragraph 1.
+
+Change paragraph 2 to
+
+@quotation
+With the exception of @code{__thread}, at most one storage-class
+specifier may be given [@dots{}]. The @code{__thread} specifier may
+be used alone, or immediately following @code{extern} or
+@code{static}.
+@end quotation
+
+Add new text after paragraph 6
+
+@quotation
+The declaration of an identifier for a variable that has
+block scope that specifies @code{__thread} shall also
+specify either @code{extern} or @code{static}.
+
+The @code{__thread} specifier shall be used only with
+variables.
+@end quotation
+@end itemize
+
+@node C++98 Thread-Local Edits
+@subsection ISO/IEC 14882:1998 Edits for Thread-Local Storage
+
+The following are a set of changes to ISO/IEC 14882:1998 (aka C++98)
+that document the exact semantics of the language extension.
+
+@itemize @bullet
+@b{[intro.execution]}
+
+New text after paragraph 4
+
+@quotation
+A @dfn{thread} is a flow of control within the abstract machine.
+It is implementation defined whether or not there may be more than
+one thread.
+@end quotation
+
+New text after paragraph 7
+
+@quotation
+It is unspecified whether additional action must be taken to
+ensure when and whether side effects are visible to other threads.
+@end quotation
+
+@item
+@b{[lex.key]}
+
+Add @code{__thread}.
+
+@item
+@b{[basic.start.main]}
+
+Add after paragraph 5
+
+@quotation
+The thread that begins execution at the @code{main} function is called
+the @dfn{main thread}. It is implementation defined how functions
+beginning threads other than the main thread are designated or typed.
+A function so designated, as well as the @code{main} function, is called
+a @dfn{thread startup function}. It is implementation defined what
+happens if a thread startup function returns. It is implementation
+defined what happens to other threads when any thread calls @code{exit}.
+@end quotation
+
+@item
+@b{[basic.start.init]}
+
+Add after paragraph 4
+
+@quotation
+The storage for an object of thread storage duration shall be
+statically initialized before the first statement of the thread startup
+function. An object of thread storage duration shall not require
+dynamic initialization.
+@end quotation
+
+@item
+@b{[basic.start.term]}
+
+Add after paragraph 3
+
+@quotation
+The type of an object with thread storage duration shall not have a
+non-trivial destructor, nor shall it be an array type whose elements
+(directly or indirectly) have non-trivial destructors.
+@end quotation
+
+@item
+@b{[basic.stc]}
+
+Add ``thread storage duration'' to the list in paragraph 1.
+
+Change paragraph 2
+
+@quotation
+Thread, static, and automatic storage durations are associated with
+objects introduced by declarations [@dots{}].
+@end quotation
+
+Add @code{__thread} to the list of specifiers in paragraph 3.
+
+@item
+@b{[basic.stc.thread]}
+
+New section before @b{[basic.stc.static]}
+
+@quotation
+The keyword @code{__thread} applied to a non-local object gives the
+object thread storage duration.
+
+A local variable or class data member declared both @code{static}
+and @code{__thread} gives the variable or member thread storage
+duration.
+@end quotation
+
+@item
+@b{[basic.stc.static]}
+
+Change paragraph 1
+
+@quotation
+All objects which have neither thread storage duration, dynamic
+storage duration nor are local [@dots{}].
+@end quotation
+
+@item
+@b{[dcl.stc]}
+
+Add @code{__thread} to the list in paragraph 1.
+
+Change paragraph 1
+
+@quotation
+With the exception of @code{__thread}, at most one
+@var{storage-class-specifier} shall appear in a given
+@var{decl-specifier-seq}. The @code{__thread} specifier may
+be used alone, or immediately following the @code{extern} or
+@code{static} specifiers. [@dots{}]
+@end quotation
+
+Add after paragraph 5
+
+@quotation
+The @code{__thread} specifier can be applied only to the names of objects
+and to anonymous unions.
+@end quotation
+
+@item
+@b{[class.mem]}
+
+Add after paragraph 6
+
+@quotation
+Non-@code{static} members shall not be @code{__thread}.
+@end quotation
+@end itemize
+
@node C++ Extensions
@chapter Extensions to the C++ Language
@cindex extensions, C++ language
@@ -6290,7 +7016,7 @@ context.
@example
void fn (int *__restrict__ rptr, int &__restrict__ rref)
@{
- @dots{}
+ /* @r{@dots{}} */
@}
@end example
@@ -6304,7 +7030,7 @@ unaliased by using @code{__restrict__} as a member function qualifier.
@example
void T::fn () __restrict__
@{
- @dots{}
+ /* @r{@dots{}} */
@}
@end example
@@ -6515,7 +7241,6 @@ If any calls were not inlined, you will get linker errors.
@node Template Instantiation
@section Where's the Template?
-
@cindex template instantiation
C++ templates are the first language feature to require more
@@ -6634,8 +7359,8 @@ compile it without @option{-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
+g++ has extended the template instantiation syntax given in the ISO
+standard to allow forward declaration of explicit instantiations
(with @code{extern}), instantiation of the compiler support data for a
template class (i.e.@: the vtable) without instantiating any of its
members (with @code{inline}), and instantiation of only the static data
@@ -6655,48 +7380,12 @@ each translation unit will contain instances of each of the templates it
uses. In a large program, this can lead to an unacceptable amount of code
duplication.
-@item
-@opindex fexternal-templates
-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
-@option{-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>;
-template ostream& operator << (ostream&, const A<int>&);
-@end example
-
-This strategy will work with code written for either model. If you are
-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.
-
-@item
-@opindex falt-external-templates
-A slight variation on this approach is to use the flag
-@option{-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.
-
@xref{C++ Interface,,Declarations and Definitions in One Header}, for
more discussion of these pragmas.
@end enumerate
@node Bound member functions
@section Extracting the function pointer from a bound pointer to member function
-
@cindex pmf
@cindex pointer to member function
@cindex bound pointer to member function
@@ -6853,7 +7542,7 @@ Floating and complex non-type template parameters have been deprecated,
and are now removed from g++.
The implicit typename extension has been deprecated and will be removed
-from g++ at some point. In some cases g++ determines that a dependant
+from g++ at some point. In some cases g++ determines that a dependent
type such as @code{TPL<T>::X} is a type without needing a
@code{typename} keyword, contrary to the standard.
diff --git a/contrib/gcc/doc/frontends.texi b/contrib/gcc/doc/frontends.texi
index a5efb63..1ee5685 100644
--- a/contrib/gcc/doc/frontends.texi
+++ b/contrib/gcc/doc/frontends.texi
@@ -4,16 +4,17 @@
@c For copying conditions, see the file gcc.texi.
@node G++ and GCC
-@chapter Compile C, C++, Objective-C, Ada, Fortran, or Java
+@chapter Compile C, C++, Objective-C, Ada, Fortran, Java, or treelang
@cindex Objective-C
@cindex Fortran
@cindex Java
@cindex Ada
+@cindex treelang
Several versions of the compiler (C, C++, Objective-C, Ada,
-Fortran, and Java) are integrated; this is why we use the name
+Fortran, Java and treelang) are integrated; this is why we use the name
``GNU Compiler Collection''. GCC can compile programs written in any of these
-languages. The Ada, Fortran, and Java compilers are described in
+languages. The Ada, Fortran, Java and treelang compilers are described in
separate manuals.
@cindex GCC
diff --git a/contrib/gcc/doc/gcc.texi b/contrib/gcc/doc/gcc.texi
index 631d56c..721150a 100644
--- a/contrib/gcc/doc/gcc.texi
+++ b/contrib/gcc/doc/gcc.texi
@@ -60,25 +60,12 @@
\global\setfont\defbf\ttbshape{10}{\magstep1}
@end tex
-@macro copyrightnotice
+@copying
Copyright @copyright{} 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
-@end macro
-@ifnottex
-@dircategory Programming
-@direntry
-* gcc: (gcc). The GNU Compiler Collection.
-@end direntry
-This file documents the use of the GNU compilers.
-@sp 1
-Published by the Free Software Foundation@*
-59 Temple Place - Suite 330@*
-Boston, MA 02111-1307 USA
-@sp 1
-@copyrightnotice{}
-@sp 1
+1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.1 or
+under the terms of the GNU Free Documentation License, Version 1.2 or
any later version published by the Free Software Foundation; with the
Invariant Sections being ``GNU General Public License'' and ``Funding
Free Software'', the Front-Cover texts being (a) (see below), and with
@@ -94,6 +81,20 @@ included in the section entitled ``GNU Free Documentation License''.
You have freedom to copy and modify this GNU Manual, like GNU
software. Copies published by the Free Software Foundation raise
funds for GNU development.
+@end copying
+@ifnottex
+@dircategory Programming
+@direntry
+* gcc: (gcc). The GNU Compiler Collection.
+@end direntry
+This file documents the use of the GNU compilers.
+@sp 1
+Published by the Free Software Foundation@*
+59 Temple Place - Suite 330@*
+Boston, MA 02111-1307 USA
+@sp 1
+@insertcopying
+@sp 1
@end ifnottex
@setchapternewpage odd
@@ -102,14 +103,12 @@ included in the section entitled ``GNU Free Documentation License''.
@sp 2
@center Richard M. Stallman
@sp 3
-@center Last updated 20 April 2002
+@center Last updated 30 December 2002
@sp 1
@center for GCC @value{version-GCC}
@page
@vskip 0pt plus 1filll
-@copyrightnotice{}
-@sp 2
For GCC Version @value{version-GCC}@*
@sp 1
Published by the Free Software Foundation @*
@@ -122,23 +121,7 @@ Printed copies are available for $50 each.@*
ISBN 1-882114-37-X
@end ifset
@sp 1
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.1 or
-any later version published by the Free Software Foundation; with the
-Invariant Sections being ``GNU General Public License'', the Front-Cover
-texts being (a) (see below), and with the Back-Cover Texts being (b)
-(see below). A copy of the license is included in the section entitled
-``GNU Free Documentation License''.
-
-(a) The FSF's Front-Cover Text is:
-
- A GNU Manual
-
-(b) The FSF's Back-Cover Text is:
-
- You have freedom to copy and modify this GNU Manual, like GNU
- software. Copies published by the Free Software Foundation raise
- funds for GNU development.
+@insertcopying
@end titlepage
@summarycontents
@contents
@@ -170,7 +153,6 @@ Introduction, gccint, GNU Compiler Collection (GCC) Internals}.
* Bugs:: How, why and where to report bugs.
* Service:: How to find suppliers of support for GCC.
* Contributing:: How to contribute to testing and developing GCC.
-* VMS:: Using GCC on VMS.
* Funding:: How to help assure funding for free software.
* GNU Project:: The GNU Project and GNU/Linux.
@@ -181,7 +163,7 @@ Introduction, gccint, GNU Compiler Collection (GCC) Internals}.
* Contributors:: People who have contributed to GCC.
* Option Index:: Index to command line options.
-* Index:: Index of concepts and symbol names.
+* Keyword Index:: Index of concepts and symbol names.
@end menu
@include frontends.texi
@@ -195,7 +177,6 @@ Introduction, gccint, GNU Compiler Collection (GCC) Internals}.
@include bugreport.texi
@include service.texi
@include contribute.texi
-@include vms.texi
@include funding.texi
@include gnu.texi
@@ -224,8 +205,8 @@ form; it may sometimes be useful to look up both forms.
@printindex op
-@node Index
-@unnumbered Index
+@node Keyword Index
+@unnumbered Keyword Index
@printindex cp
diff --git a/contrib/gcc/doc/gccint.texi b/contrib/gcc/doc/gccint.texi
index 82a7d31..b6bec09 100644
--- a/contrib/gcc/doc/gccint.texi
+++ b/contrib/gcc/doc/gccint.texi
@@ -46,25 +46,12 @@
\global\setfont\defbf\ttbshape{10}{\magstep1}
@end tex
-@macro copyrightnotice
+@copying
Copyright @copyright{} 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
-@end macro
-@ifnottex
-@dircategory Programming
-@direntry
-* gccint: (gccint). Internals of the GNU Compiler Collection.
-@end direntry
-This file documents the internals of the GNU compilers.
-@sp 1
-Published by the Free Software Foundation@*
-59 Temple Place - Suite 330@*
-Boston, MA 02111-1307 USA
-@sp 1
-@copyrightnotice{}
-@sp 1
+1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.1 or
+under the terms of the GNU Free Documentation License, Version 1.2 or
any later version published by the Free Software Foundation; with the
Invariant Sections being ``GNU General Public License'' and ``Funding
Free Software'', the Front-Cover texts being (a) (see below), and with
@@ -80,6 +67,19 @@ included in the section entitled ``GNU Free Documentation License''.
You have freedom to copy and modify this GNU Manual, like GNU
software. Copies published by the Free Software Foundation raise
funds for GNU development.
+@end copying
+@ifnottex
+@dircategory Programming
+@direntry
+* gccint: (gccint). Internals of the GNU Compiler Collection.
+@end direntry
+This file documents the internals of the GNU compilers.
+@sp 1
+Published by the Free Software Foundation@*
+59 Temple Place - Suite 330@*
+Boston, MA 02111-1307 USA
+@sp 1
+@insertcopying
@end ifnottex
@setchapternewpage odd
@@ -88,14 +88,12 @@ included in the section entitled ``GNU Free Documentation License''.
@sp 2
@center Richard M. Stallman
@sp 3
-@center Last updated 10 January 2002
+@center Last updated 28 December 2002
@sp 1
@center for GCC @value{version-GCC}
@page
@vskip 0pt plus 1filll
-@copyrightnotice{}
-@sp 2
For GCC Version @value{version-GCC}@*
@sp 1
Published by the Free Software Foundation @*
@@ -108,23 +106,7 @@ Printed copies are available for $50 each.@*
ISBN 1-882114-37-X
@end ifset
@sp 1
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.1 or
-any later version published by the Free Software Foundation; with the
-Invariant Sections being ``GNU General Public License'', the Front-Cover
-texts being (a) (see below), and with the Back-Cover Texts being (b)
-(see below). A copy of the license is included in the section entitled
-``GNU Free Documentation License''.
-
-(a) The FSF's Front-Cover Text is:
-
- A GNU Manual
-
-(b) The FSF's Back-Cover Text is:
-
- You have freedom to copy and modify this GNU Manual, like GNU
- software. Copies published by the Free Software Foundation raise
- funds for GNU development.
+@insertcopying
@end titlepage
@summarycontents
@contents
@@ -169,6 +151,7 @@ Additional tutorial information is linked to from
* Fragments:: Writing the @file{t-@var{target}} and @file{x-@var{host}} files.
* Collect2:: How @code{collect2} works; how it finds @code{ld}.
* Header Dirs:: Understanding the standard header file directories.
+* Type Information:: GCC's memory management; generating type information.
* Funding:: How to help assure funding for free software.
* GNU Project:: The GNU Project and GNU/Linux.
@@ -196,6 +179,7 @@ Additional tutorial information is linked to from
@include fragments.texi
@include collect2.texi
@include headerdirs.texi
+@include gty.texi
@include funding.texi
@include gnu.texi
diff --git a/contrib/gcc/doc/gcov.texi b/contrib/gcc/doc/gcov.texi
index 78e6667..85d5289 100644
--- a/contrib/gcc/doc/gcov.texi
+++ b/contrib/gcc/doc/gcov.texi
@@ -1,13 +1,15 @@
-@c Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
+@c Copyright (C) 1996, 1997, 1999, 2000, 2001,
+@c 2002, 2003 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@ignore
@c man begin COPYRIGHT
-Copyright @copyright{} 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
+Copyright @copyright{} 1996, 1997, 1999, 2000, 2001, 2002, 2003
+Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.1 or
+under the terms of the GNU Free Documentation License, Version 1.2 or
any later version published by the Free Software Foundation; with the
Invariant Sections being ``GNU General Public License'' and ``Funding
Free Software'', the Front-Cover texts being (a) (see below), and with
@@ -47,12 +49,13 @@ test code coverage in your programs.
@c man begin DESCRIPTION
@command{gcov} is a test coverage program. Use it in concert with GCC
-to analyze your programs to help create more efficient, faster
-running code. You can use @command{gcov} as a profiling tool to help
-discover where your optimization efforts will best affect your code. You
-can also use @command{gcov} along with the other profiling tool,
-@command{gprof}, to assess which parts of your code use the greatest amount
-of computing time.
+to analyze your programs to help create more efficient, faster running
+code and to discover untested parts of your program. You can use
+@command{gcov} as a profiling tool to help discover where your
+optimization efforts will best affect your code. You can also use
+@command{gcov} along with the other profiling tool, @command{gprof}, to
+assess which parts of your code use the greatest amount of computing
+time.
Profiling tools help you analyze your code's performance. Using a
profiler such as @command{gcov} or @command{gprof}, you can find out some
@@ -117,10 +120,13 @@ gcov @r{[}@var{options}@r{]} @var{sourcefile}
@ignore
@c man begin SYNOPSIS
gcov [@option{-v}|@option{--version}] [@option{-h}|@option{--help}]
- [@option{-b}|@option{--branch-probabilities}] [@option{-c}|@option{--branch-counts}]
- [@option{-n}|@option{--no-output}] [@option{-l}|@option{--long-file-names}]
+ [@option{-b}|@option{--branch-probabilities}]
+ [@option{-c}|@option{--branch-counts}]
+ [@option{-n}|@option{--no-output}]
+ [@option{-l}|@option{--long-file-names}]
+ [@option{-p}|@option{--preserve-paths}]
[@option{-f}|@option{--function-summaries}]
- [@option{-o}|@option{--object-directory} @var{directory}] @var{sourcefile}
+ [@option{-o}|@option{--object-directory} @var{directory|file}] @var{sourcefile}
@c man end
@c man begin SEEALSO
gpl(7), gfdl(7), fsf-funding(7), gcc(1) and the Info entry for @file{gcc}.
@@ -159,31 +165,71 @@ Do not create the @command{gcov} output file.
Create long file names for included source files. For example, if the
header file @file{x.h} contains code, and was included in the file
@file{a.c}, then running @command{gcov} on the file @file{a.c} will produce
-an output file called @file{a.c.x.h.gcov} instead of @file{x.h.gcov}.
+an output file called @file{a.c##x.h.gcov} instead of @file{x.h.gcov}.
This can be useful if @file{x.h} is included in multiple source files.
+@item -p
+@itemx --preserve-paths
+Preserve complete path information in the names of generated
+@file{.gcov} files. Without this option, just the filename component is
+used. With this option, all directories are used, with '/' characters
+translated to '#' characters, '.' directory components removed and '..'
+components renamed to '^'. This is useful if sourcefiles are in several
+different directories. It also affects the @samp{-l} option.
+
@item -f
@itemx --function-summaries
Output summaries for each function in addition to the file level summary.
-@item -o @var{directory}
+@item -o @var{directory|file}
@itemx --object-directory @var{directory}
-The directory where the object files live. Gcov will search for @file{.bb},
-@file{.bbg}, and @file{.da} files in this directory.
+@itemx --object-file @var{file}
+Specify either the directory containing the gcov data files, or the
+object path name. The @file{.bb}, @file{.bbg}, and
+@file{.da} data files are searched for using this option. If a directory
+is specified, the data files are in that directory and named after the
+source file name, without its extension. If a file is specified here,
+the data files are named after that file, without its extension. If this
+option is not supplied, it defaults to the current directory.
+
@end table
-@need 3000
+@command{gcov} should be run with the current directory the same as that
+when you invoked the compiler. Otherwise it will not be able to locate
+the source files. @command{gcov} produces files called
+@file{@var{mangledname}.gcov} in the current directory. These contain
+the coverage information of the source file they correspond to.
+One @file{.gcov} file is produced for each source file containing code,
+which was compiled to produce the data files. The @file{.gcov} files
+contain the ':' separated fields along with program source code. The
+format is
+
+@smallexample
+@var{execution_count}:@var{line_number}:@var{source line text}
+@end smallexample
+
+Additional block information may succeed each line, when requested by
+command line option. The @var{execution_count} is @samp{-} for lines
+containing no code and @samp{#####} for lines which were never
+executed. Some lines of information at the start have @var{line_number}
+of zero.
+
+When printing percentages, 0% and 100% are only printed when the values
+are @emph{exactly} 0% and 100% respectively. Other values which would
+conventionally be rounded to 0% or 100% are instead printed as the
+nearest non-boundary value.
+
When using @command{gcov}, you must first compile your program with two
special GCC options: @samp{-fprofile-arcs -ftest-coverage}.
This tells the compiler to generate additional information needed by
gcov (basically a flow graph of the program) and also includes
additional code in the object files for generating the extra profiling
information needed by gcov. These additional files are placed in the
-directory where the source code is located.
+directory where the object file is located.
Running the program will cause profile output to be generated. For each
source file compiled with @option{-fprofile-arcs}, an accompanying @file{.da}
-file will be placed in the source directory.
+file will be placed in the object file directory.
Running @command{gcov} with your program's source file names as arguments
will now produce a listing of the code along with frequency of execution
@@ -194,7 +240,7 @@ is what you see when you use the basic @command{gcov} facility:
$ gcc -fprofile-arcs -ftest-coverage tmp.c
$ a.out
$ gcov tmp.c
- 87.50% of 8 source lines executed in file tmp.c
+90.00% of 10 source lines executed in file tmp.c
Creating tmp.c.gcov.
@end smallexample
@@ -202,20 +248,25 @@ The file @file{tmp.c.gcov} contains output from @command{gcov}.
Here is a sample:
@smallexample
- main()
- @{
- 1 int i, total;
-
- 1 total = 0;
-
- 11 for (i = 0; i < 10; i++)
- 10 total += i;
-
- 1 if (total != 45)
- ###### printf ("Failure\n");
- else
- 1 printf ("Success\n");
- 1 @}
+ -: 0:Source:tmp.c
+ -: 0:Object:tmp.bb
+ -: 1:#include <stdio.h>
+ -: 2:
+ -: 3:int main (void)
+ 1: 4:@{
+ 1: 5: int i, total;
+ -: 6:
+ 1: 7: total = 0;
+ -: 8:
+ 11: 9: for (i = 0; i < 10; i++)
+ 10: 10: total += i;
+ -: 11:
+ 1: 12: if (total != 45)
+ #####: 13: printf ("Failure\n");
+ -: 14: else
+ 1: 15: printf ("Success\n");
+ 1: 16: return 0;
+ 1: 17:@}
@end smallexample
@need 450
@@ -223,37 +274,42 @@ When you use the @option{-b} option, your output looks like this:
@smallexample
$ gcov -b tmp.c
- 87.50% of 8 source lines executed in file tmp.c
- 80.00% of 5 branches executed in file tmp.c
- 80.00% of 5 branches taken at least once in file tmp.c
- 50.00% of 2 calls executed in file tmp.c
+90.00% of 10 source lines executed in file tmp.c
+80.00% of 5 branches executed in file tmp.c
+80.00% of 5 branches taken at least once in file tmp.c
+50.00% of 2 calls executed in file tmp.c
Creating tmp.c.gcov.
@end smallexample
Here is a sample of a resulting @file{tmp.c.gcov} file:
@smallexample
- main()
- @{
- 1 int i, total;
-
- 1 total = 0;
-
- 11 for (i = 0; i < 10; i++)
-branch 0 taken = 91%
-branch 1 taken = 100%
-branch 2 taken = 100%
- 10 total += i;
-
- 1 if (total != 45)
-branch 0 taken = 100%
- ###### printf ("Failure\n");
-call 0 never executed
-branch 1 never executed
- else
- 1 printf ("Success\n");
-call 0 returns = 100%
- 1 @}
+ -: 0:Source:tmp.c
+ -: 0:Object:tmp.bb
+ -: 1:#include <stdio.h>
+ -: 2:
+ -: 3:int main (void)
+ 1: 4:@{
+ 1: 5: int i, total;
+ -: 6:
+ 1: 7: total = 0;
+ -: 8:
+ 11: 9: for (i = 0; i < 10; i++)
+branch 0: taken 90%
+branch 1: taken 100%
+branch 2: taken 100%
+ 10: 10: total += i;
+ -: 11:
+ 1: 12: if (total != 45)
+branch 0: taken 100%
+ #####: 13: printf ("Failure\n");
+call 0: never executed
+branch 1: never executed
+ -: 14: else
+ 1: 15: printf ("Success\n");
+call 0: returns 100%
+ 1: 16: return 0;
+ 1: 17:@}
@end smallexample
For each basic block, a line is printed after the last line of the basic
@@ -286,11 +342,11 @@ provide more accurate long-term information over a large number of
program runs.
The data in the @file{.da} files is saved immediately before the program
-exits. For each source file compiled with @option{-fprofile-arcs}, the profiling
-code first attempts to read in an existing @file{.da} file; if the file
-doesn't match the executable (differing number of basic block counts) it
-will ignore the contents of the file. It then adds in the new execution
-counts and finally writes the data to the file.
+exits. For each source file compiled with @option{-fprofile-arcs}, the
+profiling code first attempts to read in an existing @file{.da} file; if
+the file doesn't match the executable (differing number of basic block
+counts) it will ignore the contents of the file. It then adds in the
+new execution counts and finally writes the data to the file.
@node Gcov and Optimization
@section Using @command{gcov} with GCC Optimization
@@ -319,10 +375,10 @@ the @command{gcov} output looks like this if you compiled the program with
optimization:
@smallexample
- 100 if (a != b)
- 100 c = 1;
- 100 else
- 100 c = 0;
+ 100: 12:if (a != b)
+ 100: 13: c = 1;
+ 100: 14:else
+ 100: 15: c = 0;
@end smallexample
The output shows that this block of code, combined by optimization,
@@ -348,12 +404,13 @@ functions within those files, and line numbers corresponding to each
basic block in the source file.
The @file{.bb} file format consists of several lists of 4-byte integers
-which correspond to the line numbers of each basic block in the
-file. Each list is terminated by a line number of 0. A line number of @minus{}1
-is used to designate that the source file name (padded to a 4-byte
-boundary and followed by another @minus{}1) follows. In addition, a line number
-of @minus{}2 is used to designate that the name of a function (also padded to a
-4-byte boundary and followed by a @minus{}2) follows.
+which correspond to the line numbers of each basic block in the file.
+Each list is terminated by a line number of 0. A line number of
+@minus{}1 is used to designate that the source file name (padded to a
+4-byte boundary and followed by another @minus{}1) follows. In
+addition, a line number of @minus{}2 is used to designate that the name
+of a function (also padded to a 4-byte boundary and followed by a
+@minus{}2) follows.
The @file{.bbg} file is used to reconstruct the program flow graph for
the source file. It contains a list of the program flow arcs (possible
@@ -363,6 +420,8 @@ program flow.
In the @file{.bbg} file, the format is:
@smallexample
+ name of function #0
+ checksum of function #0
number of basic blocks for function #0 (4-byte number)
total number of arcs for function #0 (4-byte number)
count of arcs in basic block #0 (4-byte number)
@@ -383,22 +442,61 @@ A @minus{}1 (stored as a 4-byte number) is used to separate each function's
list of basic blocks, and to verify that the file has been read
correctly.
+The function name is stored as a @minus{}1 (4 bytes), the length (4 bytes),
+the name itself (padded to 4-byte boundary) followed by a @minus{}1 (4 bytes).
+
+The flags are defined as follows:
+@itemize
+@item bit0
+On function spanning tree
+
+@item bit1
+Is a fake edge
+
+@item bit2
+Is the fall through edge from one block to its immediate successor.
+
+@item bit3-bit31
+For future expansion
+
+@end itemize
+
The @file{.da} file is generated when a program containing object files
built with the GCC @option{-fprofile-arcs} option is executed. A
separate @file{.da} file is created for each source file compiled with
this option, and the name of the @file{.da} file is stored as an
absolute pathname in the resulting object file. This path name is
-derived from the source file name by substituting a @file{.da} suffix.
-
-The format of the @file{.da} file is fairly simple. The first 8-byte
-number is the number of counts in the file, followed by the counts
-(stored as 8-byte numbers). Each count corresponds to the number of
-times each arc in the program is executed. The counts are cumulative;
-each time the program is executed, it attempts to combine the existing
-@file{.da} files with the new counts for this invocation of the
-program. It ignores the contents of any @file{.da} files whose number of
-arcs doesn't correspond to the current program, and merely overwrites
-them instead.
+derived from the object file name by substituting a @file{.da} suffix.
+
+The @file{.da} consists of one or more blocks with the following
+structure:
+@smallexample
+ "magic" number @minus{}123 (4-byte number)
+ number of functions (4-byte number)
+ length of the "extension block" in bytes
+ extension block (variable length)
+ name of function #0 (the same format as in .bbg file)
+ checksum of function #0
+ number of instrumented arcs (4-byte number)
+ count of arc #0 (8-byte number)
+ count of arc #1 (8-byte number)
+ @dots{}
+ count of arc #M_0 (8-byte number)
+ name of function #1 (the same format as in .bbg file)
+ checksum of function #1
+ @dots{}
+@end smallexample
+Multiple program runs might merge data into a single block, or might
+append a new block. The current structure of the extension block is as
+follows:
+@smallexample
+ number of instrumented arcs in whole program (4-byte number)
+ sum all of instrumented arcs in whole program (8-byte number)
+ maximal value of counter in whole program (8-byte number)
+ number of instrumented arcs in the object file (4-byte number)
+ sum all of instrumented arcs in the object file (8-byte number)
+ maximal value of counter in the object file (8-byte number)
+@end smallexample
All three of these files use the functions in @file{gcov-io.h} to store
integers; the functions in this header provide a machine-independent
diff --git a/contrib/gcc/doc/gty.texi b/contrib/gcc/doc/gty.texi
new file mode 100644
index 0000000..31d5252
--- /dev/null
+++ b/contrib/gcc/doc/gty.texi
@@ -0,0 +1,328 @@
+@c Copyright (C) 2002, 2003
+@c Free Software Foundation, Inc.
+@c This is part of the GCC manual.
+@c For copying conditions, see the file gcc.texi.
+
+@node Type Information
+@chapter Memory Management and Type Information
+@cindex GGC
+@findex GTY
+
+GCC uses some fairly sophisticated memory management techniques, which
+involve determining information about GCC's data structures from GCC's
+source code and using this information to perform garbage collection.
+
+A full C parser would be too overcomplicated for this task, so a limited
+subset of C is interpreted and special markers are used to determine
+what parts of the source to look at. The parser can also detect
+simple typedefs of the form @code{typedef struct ID1 *ID2;} and
+@code{typedef int ID3;}, and these don't need to be specially marked.
+
+The two forms that do need to be marked are:
+@verbatim
+struct ID1 GTY(([options]))
+{
+ [fields]
+};
+
+typedef struct ID2 GTY(([options]))
+{
+ [fields]
+} ID3;
+@end verbatim
+
+@menu
+* GTY Options:: What goes inside a @code{GTY(())}.
+* GGC Roots:: Making global variables GGC roots.
+* Files:: How the generated files work.
+@end menu
+
+@node GTY Options
+@section The Inside of a @code{GTY(())}
+
+Sometimes the C code is not enough to fully describe the type structure.
+Extra information can be provided by using more @code{GTY} markers.
+These markers can be placed:
+@itemize @bullet
+@item
+In a structure definition, before the open brace;
+@item
+In a global variable declaration, after the keyword @code{static} or
+@code{extern}; and
+@item
+In a structure field definition, before the name of the field.
+@end itemize
+
+The format of a marker is
+@verbatim
+GTY (([name] ([param]), [name] ([param]) ...))
+@end verbatim
+The parameter is either a string or a type name.
+
+When the parameter is a string, often it is a fragment of C code. Three
+special escapes may be available:
+
+@cindex % in GTY option
+@table @code
+@item %h
+This expands to an expression that evaluates to the current structure.
+@item %1
+This expands to an expression that evaluates to the structure that
+immediately contains the current structure.
+@item %0
+This expands to an expression that evaluates to the outermost structure
+that contains the current structure.
+@item %a
+This expands to the string of the form @code{[i1][i2]...} that indexes
+the array item currently being marked. For instance, if the field
+being marked is @code{foo}, then @code{%1.foo%a} is the same as @code{%h}.
+@end table
+
+The available options are:
+
+@table @code
+@findex length
+@item length
+
+There are two places the type machinery will need to be explicitly told
+the length of an array. The first case is when a structure ends in a
+variable-length array, like this:
+@verbatim
+struct rtvec_def GTY(()) {
+ int num_elem; /* number of elements */
+ rtx GTY ((length ("%h.num_elem"))) elem[1];
+};
+@end verbatim
+In this case, the @code{length} option is used to override the specified
+array length (which should usually be @code{1}). The parameter of the
+option is a fragment of C code that calculates the length.
+
+The second case is when a structure or a global variable contains a
+pointer to an array, like this:
+@smallexample
+tree *
+ GTY ((length ("%h.regno_pointer_align_length"))) regno_decl;
+@end smallexample
+In this case, @code{regno_decl} has been allocated by writing something like
+@smallexample
+ x->regno_decl =
+ ggc_alloc (x->regno_pointer_align_length * sizeof (tree));
+@end smallexample
+and the @code{length} provides the length of the field.
+
+This second use of @code{length} also works on global variables, like:
+@verbatim
+ static GTY((length ("reg_base_value_size")))
+ rtx *reg_base_value;
+@end verbatim
+
+@findex skip
+@item skip
+
+If @code{skip} is applied to a field, the type machinery will ignore it.
+This is somewhat dangerous; the only safe use is in a union when one
+field really isn't ever used.
+
+@findex desc
+@findex tag
+@findex default
+@item desc
+@itemx tag
+@itemx default
+
+The type machinery needs to be told which field of a @code{union} is
+currently active. This is done by giving each field a constant @code{tag}
+value, and then specifying a discriminator using @code{desc}. For example,
+@smallexample
+struct tree_binding GTY(())
+@{
+ struct tree_common common;
+ union tree_binding_u @{
+ tree GTY ((tag ("0"))) scope;
+ struct cp_binding_level * GTY ((tag ("1"))) level;
+ @} GTY ((desc ("BINDING_HAS_LEVEL_P ((tree)&%0)"))) scope;
+ tree value;
+@};
+@end smallexample
+
+In the @code{desc} option, the ``current structure'' is the union that
+it discriminates. Use @code{%1} to mean the structure containing it.
+(There are no escapes available to the @code{tag} option, since it's
+supposed to be a constant.)
+
+Each @code{tag} should be different. If no @code{tag} is matched,
+the field marked with @code{default} is used if there is one, otherwise
+no field in the union will be marked.
+
+@findex param_is
+@findex use_param
+@item param_is
+@itemx use_param
+
+Sometimes it's convenient to define some data structure to work on
+generic pointers (that is, @code{PTR}) and then use it with a specific
+type. @code{param_is} specifies the real type pointed to, and
+@code{use_param} says where in the generic data structure that type
+should be put.
+
+For instance, to have a @code{htab_t} that points to trees, one should write
+@verbatim
+ htab_t GTY ((param_is (union tree_node))) ict;
+@end verbatim
+
+@findex param@var{n}_is
+@findex use_param@var{n}
+@item param@var{n}_is
+@itemx use_param@var{n}
+
+In more complicated cases, the data structure might need to work on
+several different types, which might not necessarily all be pointers.
+For this, @code{param1_is} through @code{param9_is} may be used to
+specify the real type of a field identified by @code{use_param1} through
+@code{use_param9}.
+
+@findex use_params
+@item use_params
+
+When a structure contains another structure that is parameterized,
+there's no need to do anything special, the inner structure inherits the
+parameters of the outer one. When a structure contains a pointer to a
+parameterized structure, the type machinery won't automatically detect
+this (it could, it just doesn't yet), so it's necessary to tell it that
+the pointed-to structure should use the same parameters as the outer
+structure. This is done by marking the pointer with the
+@code{use_params} option.
+
+@findex deletable
+@item deletable
+
+@code{deletable}, when applied to a global variable, indicates that when
+garbage collection runs, there's no need to mark anything pointed to
+by this variable, it can just be set to @code{NULL} instead. This is used
+to keep a list of free structures around for re-use.
+
+@findex if_marked
+@item if_marked
+
+Suppose you want some kinds of object to be unique, and so you put them
+in a hash table. If garbage collection marks the hash table, these
+objects will never be freed, even if the last other reference to them
+goes away. GGC has special handling to deal with this: if you use the
+@code{if_marked} option on a global hash table, GGC will call the
+routine whose name is the parameter to the option on each hash table
+entry. If the routine returns nonzero, the hash table entry will
+be marked as usual. If the routine returns zero, the hash table entry
+will be deleted.
+
+The routine @code{ggc_marked_p} can be used to determine if an element
+has been marked already; in fact, the usual case is to use
+@code{if_marked ("ggc_marked_p")}.
+
+@findex maybe_undef
+@item maybe_undef
+
+When applied to a field, @code{maybe_undef} indicates that it's OK if
+the structure that this fields points to is never defined, so long as
+this field is always @code{NULL}. This is used to avoid requiring
+backends to define certain optional structures. It doesn't work with
+language frontends.
+
+@findex special
+@item special
+
+The @code{special} option is used for those bizarre cases that are just
+too hard to deal with otherwise. Don't use it for new code.
+
+@end table
+
+@node GGC Roots
+@section Marking Roots for the Garbage Collector
+@cindex roots, marking
+@cindex marking roots
+
+In addition to keeping track of types, the type machinery also locates
+the global variables that the garbage collector starts at. There are
+two syntaxes it accepts to indicate a root:
+
+@enumerate
+@item
+@verb{|extern GTY (([options])) [type] ID;|}
+@item
+@verb{|static GTY (([options])) [type] ID;|}
+@end enumerate
+
+These are the only syntaxes that are accepted. In particular, if you
+want to mark a variable that is only declared as
+@verbatim
+int ID;
+@end verbatim
+or similar, you should either make it @code{static} or you should create
+a @code{extern} declaration in a header file somewhere.
+
+@node Files
+@section Source Files Containing Type Information
+@cindex generated files
+@cindex files, generated
+
+Whenever you add @code{GTY} markers to a new source file, there are three
+things you need to do:
+
+@enumerate
+@item
+You need to add the file to the list of source files the type
+machinery scans. There are three cases:
+
+@enumerate a
+@item
+For a back-end file, this is usually done
+automatically; if not, you should add it to @code{target_gtfiles} in
+the appropriate port's entries in @file{config.gcc}.
+
+@item
+For files shared by all front ends, this is done by adding the
+filename to the @code{GTFILES} variable in @file{Makefile.in}.
+
+@item
+For any other file used by a front end, this is done by adding the
+filename to the @code{gtfiles} variable defined in
+@file{config-lang.in}. For C, the file is @file{c-config-lang.in}.
+This list should include all files that have GTY macros in them that
+are used in that front end, other than those defined in the previous
+list items. For example, it is common for front end writers to use
+@file{c-common.c} and other files from the C front end, and these
+should be included in the @file{gtfiles} variable for such front ends.
+
+@end enumerate
+
+@item
+If the file was a header file, you'll need to check that it's included
+in the right place to be visible to the generated files. For a back-end
+header file, this should be done automatically. For a front-end header
+file, it needs to be included by the same file that includes
+@file{gtype-@var{lang}.h}. For other header files, it needs to be
+included in @file{gtype-desc.c}, which is a generated file, so add it to
+@code{ifiles} in @code{open_base_file} in @file{gengtype.c}.
+
+For source files that aren't header files, the machinery will generate a
+header file that should be included in the source file you just changed.
+The file will be called @file{gt-@var{path}.h} where @var{path} is the
+pathname relative to the @file{gcc} directory with slashes replaced by
+@verb{|-|}, so for example the header file to be included in
+@file{objc/objc-parse.c} is called @file{gt-objc-objc-parse.c}. The
+generated header file should be included after everything else in the
+source file. Don't forget to mention this file as a dependency in the
+@file{Makefile}!
+
+@item
+If a new @file{gt-@var{path}.h} file is needed, you need to arrange to
+add a @file{Makefile} rule that will ensure this file can be built.
+This is done by making it a dependency of @code{s-gtype}, like this:
+@verbatim
+gt-path.h : s-gtype ; @true
+@end verbatim
+@end enumerate
+
+For language frontends, there is another file that needs to be included
+somewhere. It will be called @file{gtype-@var{lang}.h}, where
+@var{lang} is the name of the subdirectory the language is contained in.
+It will need @file{Makefile} rules just like the other generated files.
diff --git a/contrib/gcc/doc/headerdirs.texi b/contrib/gcc/doc/headerdirs.texi
index 17db57f..beac0dd 100644
--- a/contrib/gcc/doc/headerdirs.texi
+++ b/contrib/gcc/doc/headerdirs.texi
@@ -15,7 +15,7 @@ are already suitable for ISO C and GNU CC, nothing special need be
done).
@code{GPLUSPLUS_INCLUDE_DIR} means the same thing for native and cross. It
-is where @code{g++} looks first for header files. The C++ library
+is where @command{g++} looks first for header files. The C++ library
installs only target independent header files in that directory.
@code{LOCAL_INCLUDE_DIR} is used only by native compilers. GNU CC
diff --git a/contrib/gcc/doc/include/fdl.texi b/contrib/gcc/doc/include/fdl.texi
index 1f3d8b652..2a4da78 100644
--- a/contrib/gcc/doc/include/fdl.texi
+++ b/contrib/gcc/doc/include/fdl.texi
@@ -33,10 +33,10 @@ of this license document, but changing it is not allowed.
@end ifclear
@cindex FDL, GNU Free Documentation License
-@center Version 1.1, March 2000
+@center Version 1.2, November 2002
@display
-Copyright @copyright{} 2000 Free Software Foundation, Inc.
+Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
@@ -48,12 +48,12 @@ of this license document, but changing it is not allowed.
PREAMBLE
The purpose of this License is to make a manual, textbook, or other
-written document @dfn{free} in the sense of freedom: to assure everyone
-the effective freedom to copy and redistribute it, with or without
-modifying it, either commercially or noncommercially. Secondarily,
-this License preserves for the author and publisher a way to get
-credit for their work, while not being considered responsible for
-modifications made by others.
+functional and useful document @dfn{free} in the sense of freedom: to
+assure everyone the effective freedom to copy and redistribute it,
+with or without modifying it, either commercially or noncommercially.
+Secondarily, this License preserves for the author and publisher a way
+to get credit for their work, while not being considered responsible
+for modifications made by others.
This License is a kind of ``copyleft'', which means that derivative
works of the document must themselves be free in the same sense. It
@@ -71,57 +71,69 @@ principally for works whose purpose is instruction or reference.
@item
APPLICABILITY AND DEFINITIONS
-This License applies to any manual or other work that contains a
-notice placed by the copyright holder saying it can be distributed
-under the terms of this License. The ``Document'', below, refers to any
-such manual or work. Any member of the public is a licensee, and is
-addressed as ``you''.
+This License applies to any manual or other work, in any medium, that
+contains a notice placed by the copyright holder saying it can be
+distributed under the terms of this License. Such a notice grants a
+world-wide, royalty-free license, unlimited in duration, to use that
+work under the conditions stated herein. The ``Document'', below,
+refers to any such manual or work. Any member of the public is a
+licensee, and is addressed as ``you''. You accept the license if you
+copy, modify or distribute the work in a way requiring permission
+under copyright law.
A ``Modified Version'' of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.
-A ``Secondary Section'' is a named appendix or a front-matter section of
-the Document that deals exclusively with the relationship of the
-publishers or authors of the Document to the Document's overall subject
-(or to related matters) and contains nothing that could fall directly
-within that overall subject. (For example, if the Document is in part a
-textbook of mathematics, a Secondary Section may not explain any
-mathematics.) The relationship could be a matter of historical
+A ``Secondary Section'' is a named appendix or a front-matter section
+of the Document that deals exclusively with the relationship of the
+publishers or authors of the Document to the Document's overall
+subject (or to related matters) and contains nothing that could fall
+directly within that overall subject. (Thus, if the Document is in
+part a textbook of mathematics, a Secondary Section may not explain
+any mathematics.) The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding
them.
The ``Invariant Sections'' are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
-that says that the Document is released under this License.
+that says that the Document is released under this License. If a
+section does not fit the above definition of Secondary then it is not
+allowed to be designated as Invariant. The Document may contain zero
+Invariant Sections. If the Document does not identify any Invariant
+Sections then there are none.
The ``Cover Texts'' are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
-the Document is released under this License.
+the Document is released under this License. A Front-Cover Text may
+be at most 5 words, and a Back-Cover Text may be at most 25 words.
A ``Transparent'' copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
-general public, whose contents can be viewed and edited directly and
+general public, that is suitable for revising the document
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or
for automatic translation to a variety of formats suitable for input
to text formatters. A copy made in an otherwise Transparent file
-format whose markup has been designed to thwart or discourage
-subsequent modification by readers is not Transparent. A copy that is
-not ``Transparent'' is called ``Opaque''.
+format whose markup, or absence of markup, has been arranged to thwart
+or discourage subsequent modification by readers is not Transparent.
+An image format is not Transparent if used for any substantial amount
+of text. A copy that is not ``Transparent'' is called ``Opaque''.
Examples of suitable formats for Transparent copies include plain
-@sc{ascii} without markup, Texinfo input format, La@TeX{} input format,
-@acronym{SGML} or @acronym{XML} using a publicly available
-@acronym{DTD}, and standard-conforming simple @acronym{HTML} designed
-for human modification. Opaque formats include PostScript,
-@acronym{PDF}, proprietary formats that can be read and edited only by
-proprietary word processors, @acronym{SGML} or @acronym{XML} for which
-the @acronym{DTD} and/or processing tools are not generally available,
-and the machine-generated @acronym{HTML} produced by some word
-processors for output purposes only.
+@sc{ascii} without markup, Texinfo input format, La@TeX{} input
+format, @acronym{SGML} or @acronym{XML} using a publicly available
+@acronym{DTD}, and standard-conforming simple @acronym{HTML},
+PostScript or @acronym{PDF} designed for human modification. Examples
+of transparent image formats include @acronym{PNG}, @acronym{XCF} and
+@acronym{JPG}. Opaque formats include proprietary formats that can be
+read and edited only by proprietary word processors, @acronym{SGML} or
+@acronym{XML} for which the @acronym{DTD} and/or processing tools are
+not generally available, and the machine-generated @acronym{HTML},
+PostScript or @acronym{PDF} produced by some word processors for
+output purposes only.
The ``Title Page'' means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
@@ -130,6 +142,21 @@ formats which do not have any title page as such, ``Title Page'' means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.
+A section ``Entitled XYZ'' means a named subunit of the Document whose
+title either is precisely XYZ or contains XYZ in parentheses following
+text that translates XYZ in another language. (Here XYZ stands for a
+specific section name mentioned below, such as ``Acknowledgements'',
+``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title''
+of such a section when you modify the Document means that it remains a
+section ``Entitled XYZ'' according to this definition.
+
+The Document may include Warranty Disclaimers next to the notice which
+states that this License applies to the Document. These Warranty
+Disclaimers are considered to be included by reference in this
+License, but only as regards disclaiming warranties: any other
+implication that these Warranty Disclaimers may have is void and has
+no effect on the meaning of this License.
+
@item
VERBATIM COPYING
@@ -149,9 +176,10 @@ you may publicly display copies.
@item
COPYING IN QUANTITY
-If you publish printed copies of the Document numbering more than 100,
-and the Document's license notice requires Cover Texts, you must enclose
-the copies in covers that carry, clearly and legibly, all these Cover
+If you publish printed copies (or copies in media that commonly have
+printed covers) of the Document, numbering more than 100, and the
+Document's license notice requires Cover Texts, you must enclose the
+copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover. Both covers must also clearly and legibly identify
you as the publisher of these copies. The front cover must present
@@ -169,16 +197,15 @@ pages.
If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy
-a publicly-accessible computer-network location containing a complete
-Transparent copy of the Document, free of added material, which the
-general network-using public has access to download anonymously at no
-charge using public-standard network protocols. If you use the latter
-option, you must take reasonably prudent steps, when you begin
-distribution of Opaque copies in quantity, to ensure that this
-Transparent copy will remain thus accessible at the stated location
-until at least one year after the last time you distribute an Opaque
-copy (directly or through your agents or retailers) of that edition to
-the public.
+a computer-network location from which the general network-using
+public has access to download using public-standard network protocols
+a complete Transparent copy of the Document, free of added material.
+If you use the latter option, you must take reasonably prudent steps,
+when you begin distribution of Opaque copies in quantity, to ensure
+that this Transparent copy will remain thus accessible at the stated
+location until at least one year after the last time you distribute an
+Opaque copy (directly or through your agents or retailers) of that
+edition to the public.
It is requested, but not required, that you contact the authors of the
Document well before redistributing any large number of copies, to give
@@ -206,7 +233,8 @@ if the original publisher of that version gives permission.
List on the Title Page, as authors, one or more persons or entities
responsible for authorship of the modifications in the Modified
Version, together with at least five of the principal authors of the
-Document (all of its principal authors, if it has less than five).
+Document (all of its principal authors, if it has fewer than five),
+unless they release you from this requirement.
@item
State on the Title page the name of the publisher of the
@@ -232,10 +260,10 @@ and required Cover Texts given in the Document's license notice.
Include an unaltered copy of this License.
@item
-Preserve the section entitled ``History'', and its title, and add to
-it an item stating at least the title, year, new authors, and
+Preserve the section Entitled ``History'', Preserve its Title, and add
+to it an item stating at least the title, year, new authors, and
publisher of the Modified Version as given on the Title Page. If
-there is no section entitled ``History'' in the Document, create one
+there is no section Entitled ``History'' in the Document, create one
stating the title, year, authors, and publisher of the Document as
given on its Title Page, then add an item describing the Modified
Version as stated in the previous sentence.
@@ -250,10 +278,10 @@ least four years before the Document itself, or if the original
publisher of the version it refers to gives permission.
@item
-In any section entitled ``Acknowledgments'' or ``Dedications'',
-preserve the section's title, and preserve in the section all the
-substance and tone of each of the contributor acknowledgments
-and/or dedications given therein.
+For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
+the Title of the section, and preserve in the section all the
+substance and tone of each of the contributor acknowledgements and/or
+dedications given therein.
@item
Preserve all the Invariant Sections of the Document,
@@ -261,12 +289,15 @@ unaltered in their text and in their titles. Section numbers
or the equivalent are not considered part of the section titles.
@item
-Delete any section entitled ``Endorsements''. Such a section
+Delete any section Entitled ``Endorsements''. Such a section
may not be included in the Modified Version.
@item
-Do not retitle any existing section as ``Endorsements''
-or to conflict in title with any Invariant Section.
+Do not retitle any existing section to be Entitled ``Endorsements'' or
+to conflict in title with any Invariant Section.
+
+@item
+Preserve any Warranty Disclaimers.
@end enumerate
If the Modified Version includes new front-matter sections or
@@ -276,7 +307,7 @@ of these sections as invariant. To do this, add their titles to the
list of Invariant Sections in the Modified Version's license notice.
These titles must be distinct from any other section titles.
-You may add a section entitled ``Endorsements'', provided it contains
+You may add a section Entitled ``Endorsements'', provided it contains
nothing but endorsements of your Modified Version by various
parties---for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a
@@ -304,7 +335,7 @@ License, under the terms defined in section 4 above for modified
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and
list them all as Invariant Sections of your combined work in its
-license notice.
+license notice, and that you preserve all their Warranty Disclaimers.
The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
@@ -315,11 +346,11 @@ author or publisher of that section if known, or else a unique number.
Make the same adjustment to the section titles in the list of
Invariant Sections in the license notice of the combined work.
-In the combination, you must combine any sections entitled ``History''
-in the various original documents, forming one section entitled
-``History''; likewise combine any sections entitled ``Acknowledgments'',
-and any sections entitled ``Dedications''. You must delete all sections
-entitled ``Endorsements.''
+In the combination, you must combine any sections Entitled ``History''
+in the various original documents, forming one section Entitled
+``History''; likewise combine any sections Entitled ``Acknowledgements'',
+and any sections Entitled ``Dedications''. You must delete all
+sections Entitled ``Endorsements.''
@item
COLLECTIONS OF DOCUMENTS
@@ -340,18 +371,20 @@ AGGREGATION WITH INDEPENDENT WORKS
A compilation of the Document or its derivatives with other separate
and independent documents or works, in or on a volume of a storage or
-distribution medium, does not as a whole count as a Modified Version
-of the Document, provided no compilation copyright is claimed for the
-compilation. Such a compilation is called an ``aggregate'', and this
-License does not apply to the other self-contained works thus compiled
-with the Document, on account of their being thus compiled, if they
-are not themselves derivative works of the Document.
+distribution medium, is called an ``aggregate'' if the copyright
+resulting from the compilation is not used to limit the legal rights
+of the compilation's users beyond what the individual works permit.
+When the Document is included an aggregate, this License does not
+apply to the other works in the aggregate which are not themselves
+derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these
-copies of the Document, then if the Document is less than one quarter
-of the entire aggregate, the Document's Cover Texts may be placed on
-covers that surround only the Document within the aggregate.
-Otherwise they must appear on covers around the whole aggregate.
+copies of the Document, then if the Document is less than one half of
+the entire aggregate, the Document's Cover Texts may be placed on
+covers that bracket the Document within the aggregate, or the
+electronic equivalent of covers if the Document is in electronic form.
+Otherwise they must appear on printed covers that bracket the whole
+aggregate.
@item
TRANSLATION
@@ -362,10 +395,17 @@ Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections. You may include a
-translation of this License provided that you also include the
-original English version of this License. In case of a disagreement
-between the translation and the original English version of this
-License, the original English version will prevail.
+translation of this License, and all the license notices in the
+Document, and any Warrany Disclaimers, provided that you also include
+the original English version of this License and the original versions
+of those notices and disclaimers. In case of a disagreement between
+the translation and the original version of this License or a notice
+or disclaimer, the original version will prevail.
+
+If a section in the Document is Entitled ``Acknowledgements'',
+``Dedications'', or ``History'', the requirement (section 4) to Preserve
+its Title (section 1) will typically require changing the actual
+title.
@item
TERMINATION
@@ -408,19 +448,28 @@ license notices just after the title page:
@group
Copyright (C) @var{year} @var{your name}.
Permission is granted to copy, distribute and/or modify this document
- under the terms of the GNU Free Documentation License, Version 1.1
+ under the terms of the GNU Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
- with the Invariant Sections being @var{list their titles}, with the
- Front-Cover Texts being @var{list}, and with the Back-Cover Texts being @var{list}.
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled ``GNU
Free Documentation License''.
@end group
@end smallexample
-If you have no Invariant Sections, write ``with no Invariant Sections''
-instead of saying which ones are invariant. If you have no
-Front-Cover Texts, write ``no Front-Cover Texts'' instead of
-``Front-Cover Texts being @var{list}''; likewise for Back-Cover Texts.
+If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
+replace the ``with...Texts.'' line with this:
+
+@smallexample
+@group
+ with the Invariant Sections being @var{list their titles}, with
+ the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
+ being @var{list}.
+@end group
+@end smallexample
+
+If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of
diff --git a/contrib/gcc/doc/include/gcc-common.texi b/contrib/gcc/doc/include/gcc-common.texi
index f489693..0a51d93 100644
--- a/contrib/gcc/doc/include/gcc-common.texi
+++ b/contrib/gcc/doc/include/gcc-common.texi
@@ -4,7 +4,12 @@
@c Common values used in the GCC manuals:
-@set version-GCC 3.2.2
+@set version-GCC 3.3.1
+
+@c DEVELOPMENT is set to indicate an in-development version,
+@c as compared to a release version. When making a release
+@c branch, clear this.
+@clear DEVELOPMENT
@c Common macros to support generating man pages:
diff --git a/contrib/gcc/doc/include/gpl.texi b/contrib/gcc/doc/include/gpl.texi
index 4304b72..eaff30c 100644
--- a/contrib/gcc/doc/include/gpl.texi
+++ b/contrib/gcc/doc/include/gpl.texi
@@ -7,7 +7,7 @@ gfdl(7), fsf-funding(7).
@c man end
@c man begin COPYRIGHT
Copyright @copyright{} 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.
@@ -20,7 +20,7 @@ of this license document, but changing it is not allowed.
@display
Copyright @copyright{} 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.
@@ -365,9 +365,8 @@ 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.
+along with this program; if not, write to the Free Software Foundation,
+Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
@end smallexample
Also add information on how to contact you by electronic and paper mail.
diff --git a/contrib/gcc/doc/include/texinfo.tex b/contrib/gcc/doc/include/texinfo.tex
index 99113dd..a8541dc 100644
--- a/contrib/gcc/doc/include/texinfo.tex
+++ b/contrib/gcc/doc/include/texinfo.tex
@@ -3,10 +3,10 @@
% Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
%
-\def\texinfoversion{2002-03-01.06}
+\def\texinfoversion{2002-12-26.16}
%
-% Copyright (C) 1985, 86, 88, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
-% 2000, 01, 02 Free Software Foundation, Inc.
+% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
+% 1996, 1997, 1998, 1999, 2000, 2001, 2002 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
@@ -29,19 +29,17 @@
%
% Please try the latest version of texinfo.tex before submitting bug
% reports; you can get the latest version from:
-% ftp://ftp.gnu.org/gnu/texinfo.tex
+% ftp://ftp.gnu.org/gnu/texinfo/texinfo.tex
% (and all GNU mirrors, see http://www.gnu.org/order/ftp.html)
-% ftp://texinfo.org/texinfo/texinfo.tex
% ftp://tug.org/tex/texinfo.tex
% (and all CTAN mirrors, see http://www.ctan.org),
% and /home/gd/gnu/doc/texinfo.tex on the GNU machines.
%
+% The GNU Texinfo home page is http://www.gnu.org/software/texinfo.
+%
% The texinfo.tex in any given Texinfo distribution could well be out
% of date, so if that's what you're using, please check.
%
-% Texinfo has a small home page at http://texinfo.org/ and also
-% http://www.gnu.org/software/texinfo.
-%
% Send bug reports to bug-texinfo@gnu.org. Please include including a
% complete document in each bug report with which we can reproduce the
% problem. Patches are, of course, greatly appreciated.
@@ -53,7 +51,7 @@
% texindex foo.??
% tex foo.texi
% tex foo.texi
-% dvips foo.dvi -o # or whatever, to process the dvi file; this makes foo.ps.
+% dvips foo.dvi -o # or whatever; this makes foo.ps.
% The extra TeX runs get the cross-reference information correct.
% Sometimes one run after texindex suffices, and sometimes you need more
% than two; texi2dvi does it as many times as necessary.
@@ -69,6 +67,13 @@
\everyjob{\message{[Texinfo version \texinfoversion]}%
\catcode`+=\active \catcode`\_=\active}
+\message{Basics,}
+\chardef\other=12
+
+% We never want plain's outer \+ definition in Texinfo.
+% For @tex, we can use \tabalign.
+\let\+ = \relax
+
% Save some parts of plain tex whose names we will redefine.
\let\ptexb=\b
\let\ptexbullet=\bullet
@@ -79,19 +84,16 @@
\let\ptexend=\end
\let\ptexequiv=\equiv
\let\ptexexclam=\!
+\let\ptexgtr=>
+\let\ptexhat=^
\let\ptexi=\i
\let\ptexlbrace=\{
+\let\ptexless=<
+\let\ptexplus=+
\let\ptexrbrace=\}
\let\ptexstar=\*
\let\ptext=\t
-% We never want plain's outer \+ definition in Texinfo.
-% For @tex, we can use \tabalign.
-\let\+ = \relax
-
-\message{Basics,}
-\chardef\other=12
-
% If this character appears in an error message or help string, it
% starts a new line in the output.
\newlinechar = `^^J
@@ -142,36 +144,48 @@
%
\def\gobble#1{}
+% True if #1 is the empty string, i.e., called like `\ifempty{}'.
+%
+\def\ifempty#1{\ifemptyx #1\emptymarkA\emptymarkB}%
+\def\ifemptyx#1#2\emptymarkB{\ifx #1\emptymarkA}%
+
+% Hyphenation fixes.
\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
-\newdimen \normaloffset
+\newdimen\bindingoffset
+\newdimen\normaloffset
\newdimen\pagewidth \newdimen\pageheight
% Sometimes it is convenient to have everything in the transcript file
% and nothing on the terminal. We don't just call \tracingall here,
-% since that produces some useless output on the terminal.
+% since that produces some useless output on the terminal. We also make
+% some effort to order the tracing commands to reduce output in the log
+% file; cf. trace.sty in LaTeX.
%
\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
-\ifx\eTeXversion\undefined
-\def\loggingall{\tracingcommands2 \tracingstats2
- \tracingpages1 \tracingoutput1 \tracinglostchars1
- \tracingmacros2 \tracingparagraphs1 \tracingrestores1
- \showboxbreadth\maxdimen\showboxdepth\maxdimen
-}%
-\else
-\def\loggingall{\tracingcommands3 \tracingstats2
- \tracingpages1 \tracingoutput1 \tracinglostchars1
- \tracingmacros2 \tracingparagraphs1 \tracingrestores1
- \tracingscantokens1 \tracingassigns1 \tracingifs1
- \tracinggroups1 \tracingnesting2
- \showboxbreadth\maxdimen\showboxdepth\maxdimen
+\def\loggingall{%
+ \tracingstats2
+ \tracingpages1
+ \tracinglostchars2 % 2 gives us more in etex
+ \tracingparagraphs1
+ \tracingoutput1
+ \tracingmacros2
+ \tracingrestores1
+ \showboxbreadth\maxdimen \showboxdepth\maxdimen
+ \ifx\eTeXversion\undefined\else % etex gives us more logging
+ \tracingscantokens1
+ \tracingifs1
+ \tracinggroups1
+ \tracingnesting2
+ \tracingassigns1
+ \fi
+ \tracingcommands3 % 3 gives us more in etex
+ \errorcontextlines\maxdimen
}%
-\fi
% add check for \lastpenalty to plain's definitions. If the last thing
% we did was a \nobreak, we don't want to insert more space.
@@ -436,17 +450,6 @@
}
-% Single-spacing is done by various environments (specifically, in
-% \nonfillstart and \quotations).
-\newskip\singlespaceskip \singlespaceskip = 12.5pt
-\def\singlespace{%
- % Why was this kern here? It messes up equalizing space above and below
- % environments. --karl, 6may93
- %{\advance \baselineskip by -\singlespaceskip
- %\kern \baselineskip}%
- \setleading\singlespaceskip
-}
-
%% Simple single-character @ commands
% @@ prints an @
@@ -841,12 +844,6 @@ where each line of input produces a line of output.}
% to set catcodes according to plain TeX first, to allow for subscripts,
% superscripts, special math chars, etc.
%
-% @math does not do math typesetting in section titles, index
-% entries, and other such contexts where the catcodes are set before
-% @math gets a chance to work. This could perhaps be fixed, but for now
-% at least we can have real math in the main text, where it's needed most.
-%
-%
\let\implicitmath = $%$ font-lock fix
%
% One complication: _ usually means subscripts, but it could also mean
@@ -857,12 +854,42 @@ where each line of input produces a line of output.}
{\catcode95 = \active % 95 = _
\gdef\mathunderscore{%
\catcode95=\active
- \def_{\ifnum\fam=\slfam\_\else\sb\fi}%
+ \def_{\ifnum\fam=\slfam \_\else\sb\fi}%
}}
%
-\def\math{\tex\mathcode`\_="8000\mathunderscore \implicitmath\finishmath}
+% Another complication: we want \\ (and @\) to output a \ character.
+% FYI, plain.tex uses \\ as a temporary control sequence (why?), but
+% this is not advertised and we don't care. Texinfo does not
+% otherwise define @\.
+%
+% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\.
+\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi}
+%
+\def\math{%
+ \tex
+ \mathcode`\_="8000 \mathunderscore
+ \let\\ = \mathbackslash
+ \mathactive
+ \implicitmath\finishmath}
\def\finishmath#1{#1\implicitmath\Etex}
+% Some active characters (such as <) are spaced differently in math.
+% We have to reset their definitions in case the @math was an
+% argument to a command which set the catcodes (such as @item or @section).
+%
+{
+ \catcode`^ = \active
+ \catcode`< = \active
+ \catcode`> = \active
+ \catcode`+ = \active
+ \gdef\mathactive{%
+ \let^ = \ptexhat
+ \let< = \ptexless
+ \let> = \ptexgtr
+ \let+ = \ptexplus
+ }
+}
+
% @bullet and @minus need the same treatment as @math, just above.
\def\bullet{\implicitmath\ptexbullet\implicitmath}
\def\minus{\implicitmath-\implicitmath}
@@ -954,7 +981,7 @@ where each line of input produces a line of output.}
\ifx\empty\imagewidth\else width \imagewidth \fi
\ifx\empty\imageheight\else height \imageheight \fi
\ifnum\pdftexversion<13
- #1.pdf%
+ #1.pdf%
\else
{#1.pdf}%
\fi
@@ -976,40 +1003,39 @@ where each line of input produces a line of output.}
\openin 1 \jobname.toc
\ifeof 1\else\begingroup
\closein 1
- \indexnofonts
- \def\tt{}
- \let\_ = \normalunderscore
% Thanh's hack / proper braces in bookmarks
\edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace
\edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace
%
\def\chapentry ##1##2##3{}
- \let\appendixentry = \chapentry
- \def\unnumbchapentry ##1##2{}
\def\secentry ##1##2##3##4{\advancenumber{chap##2}}
- \def\unnumbsecentry ##1##2{}
\def\subsecentry ##1##2##3##4##5{\advancenumber{sec##2.##3}}
- \def\unnumbsubsecentry ##1##2{}
\def\subsubsecentry ##1##2##3##4##5##6{\advancenumber{subsec##2.##3.##4}}
- \def\unnumbsubsubsecentry ##1##2{}
+ \let\appendixentry = \chapentry
+ \let\unnumbchapentry = \chapentry
+ \let\unnumbsecentry = \secentry
+ \let\unnumbsubsecentry = \subsecentry
+ \let\unnumbsubsubsecentry = \subsubsecentry
\input \jobname.toc
\def\chapentry ##1##2##3{%
\pdfoutline goto name{\pdfmkpgn{##3}}count-\expnumber{chap##2}{##1}}
- \let\appendixentry = \chapentry
- \def\unnumbchapentry ##1##2{%
- \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
\def\secentry ##1##2##3##4{%
\pdfoutline goto name{\pdfmkpgn{##4}}count-\expnumber{sec##2.##3}{##1}}
- \def\unnumbsecentry ##1##2{%
- \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
\def\subsecentry ##1##2##3##4##5{%
\pdfoutline goto name{\pdfmkpgn{##5}}count-\expnumber{subsec##2.##3.##4}{##1}}
- \def\unnumbsubsecentry ##1##2{%
- \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
\def\subsubsecentry ##1##2##3##4##5##6{%
\pdfoutline goto name{\pdfmkpgn{##6}}{##1}}
- \def\unnumbsubsubsecentry ##1##2{%
- \pdfoutline goto name{\pdfmkpgn{##2}}{##1}}
+ \let\appendixentry = \chapentry
+ \let\unnumbchapentry = \chapentry
+ \let\unnumbsecentry = \secentry
+ \let\unnumbsubsecentry = \subsecentry
+ \let\unnumbsubsubsecentry = \subsubsecentry
+ %
+ % Make special characters normal for writing to the pdf file.
+ %
+ \indexnofonts
+ \let\tt=\relax
+ \turnoffactive
\input \jobname.toc
\endgroup\fi
}}
@@ -1159,7 +1185,7 @@ where each line of input produces a line of output.}
\newcount\mainmagstep
\ifx\bigger\relax
% not really supported.
- \let\mainmagstep=\magstep1
+ \mainmagstep=\magstep1
\setfont\textrm\rmshape{12}{1000}
\setfont\texttt\ttshape{12}{1000}
\else
@@ -1220,6 +1246,7 @@ where each line of input produces a line of output.}
\font\titlei=cmmi12 scaled \magstep3
\font\titlesy=cmsy10 scaled \magstep4
\def\authorrm{\secrm}
+\def\authortt{\sectt}
% Chapter (and unnumbered) fonts (17.28pt).
\setfont\chaprm\rmbshape{12}{\magstep2}
@@ -1334,6 +1361,7 @@ where each line of input produces a line of output.}
\setfont\shortcontrm\rmshape{12}{1000}
\setfont\shortcontbf\bxshape{12}{1000}
\setfont\shortcontsl\slshape{12}{1000}
+\setfont\shortconttt\ttshape{12}{1000}
%% Add scribe-like font environments, plus @l for inline lisp (usually sans
%% serif) and @ii for TeX italic
@@ -1341,8 +1369,8 @@ where each line of input produces a line of output.}
% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
% unless the following character is such as not to need one.
\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else\/\fi\fi\fi}
-\def\smartslanted#1{{\sl #1}\futurelet\next\smartitalicx}
-\def\smartitalic#1{{\it #1}\futurelet\next\smartitalicx}
+\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx}
+\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx}
\let\i=\smartitalic
\let\var=\smartslanted
@@ -1431,11 +1459,19 @@ where each line of input produces a line of output.}
\def\realdash{-}
\def\codedash{-\discretionary{}{}{}}
-\def\codeunder{\ifusingtt{\normalunderscore\discretionary{}{}{}}{\_}}
+\def\codeunder{%
+ % this is all so @math{@code{var_name}+1} can work. In math mode, _
+ % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.)
+ % will therefore expand the active definition of _, which is us
+ % (inside @code that is), therefore an endless loop.
+ \ifusingtt{\ifmmode
+ \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_.
+ \else\normalunderscore \fi
+ \discretionary{}{}{}}%
+ {\_}%
+}
\def\codex #1{\tclose{#1}\endgroup}
-%\let\exp=\tclose %Was temporary
-
% @kbd is like @code, except that if the argument is just one @key command,
% then @kbd has no effect.
@@ -1573,7 +1609,8 @@ where each line of input produces a line of output.}
\let\subtitlerm=\tenrm
\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
%
- \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines}%
+ \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines
+ \let\tt=\authortt}%
%
% Leave some space at the very top of the page.
\vglue\titlepagetopglue
@@ -1637,8 +1674,6 @@ where each line of input produces a line of output.}
\global\let\contents = \relax
\global\let\shortcontents = \relax
\fi
- %
- \ifpdf \pdfmakepagedesttrue \fi
}
\def\finishtitlepage{%
@@ -1856,10 +1891,18 @@ where each line of input produces a line of output.}
% \parskip glue -- logically it's part of the @item we just started.
\nobreak \vskip-\parskip
%
- % Stop a page break at the \parskip glue coming up. Unfortunately
+ % Stop a page break at the \parskip glue coming up. (Unfortunately
% we can't prevent a possible page break at the following
- % \baselineskip glue.
- \nobreak
+ % \baselineskip glue.) However, if what follows is an environment
+ % such as @example, there will be no \parskip glue; then
+ % the negative vskip we just would cause the example and the item to
+ % crash together. So we use this bizarre value of 10001 as a signal
+ % to \aboveenvbreak to insert \parskip glue after all.
+ % (Possibly there are other commands that could be followed by
+ % @example which need the same treatment, but not section titles; or
+ % maybe section titles are the only special case and they should be
+ % penalty 10001...)
+ \penalty 10001
\endgroup
\itemxneedsnegativevskipfalse
\else
@@ -2396,20 +2439,20 @@ width0pt\relax} \fi
\let\item = \relax
}
-% Ignore @ignore ... @end ignore.
-%
-\def\ignore{\doignore{ignore}}
-
-% Also ignore @ifinfo, @ifhtml, @ifnottex, @html, @menu,
-% @documentdescription, and @direntry text.
+% Ignore @ignore, @ifhtml, @ifinfo, and the like.
%
-\def\ifinfo{\doignore{ifinfo}}
+\def\direntry{\doignore{direntry}}
+\def\documentdescriptionword{documentdescription}
+\def\documentdescription{\doignore{documentdescription}}
+\def\html{\doignore{html}}
\def\ifhtml{\doignore{ifhtml}}
+\def\ifinfo{\doignore{ifinfo}}
\def\ifnottex{\doignore{ifnottex}}
-\def\html{\doignore{html}}
+\def\ifplaintext{\doignore{ifplaintext}}
+\def\ifxml{\doignore{ifxml}}
+\def\ignore{\doignore{ignore}}
\def\menu{\doignore{menu}}
-\def\documentdescription{\doignore{documentdescription}}
-\def\direntry{\doignore{direntry}}
+\def\xml{\doignore{xml}}
% @dircategory CATEGORY -- specify a category of the dir file
% which this file should belong to. Ignore this in TeX.
@@ -2436,14 +2479,21 @@ width0pt\relax} \fi
% We must not have @c interpreted as a control sequence.
\catcode`\@ = 12
%
- % Make the letter c a comment character so that the rest of the line
- % will be ignored. This way, the document can have (for example)
- % @c @end ifinfo
- % and the @end ifinfo will be properly ignored.
- % (We've just changed @ to catcode 12.)
- \catcode`\c = 14
+ \def\ignoreword{#1}%
+ \ifx\ignoreword\documentdescriptionword
+ % The c kludge breaks documentdescription, since
+ % `documentdescription' contains a `c'. Means not everything will
+ % be ignored inside @documentdescription, but oh well...
+ \else
+ % Make the letter c a comment character so that the rest of the line
+ % will be ignored. This way, the document can have (for example)
+ % @c @end ifinfo
+ % and the @end ifinfo will be properly ignored.
+ % (We've just changed @ to catcode 12.)
+ \catcode`\c = 14
+ \fi
%
- % And now expand that command.
+ % And now expand the command defined above.
\doignoretext
}
@@ -2462,7 +2512,7 @@ width0pt\relax} \fi
\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.org/pub/gnu/TeX.README.)}
+ \immediate\write16{ (See ftp://ftp.gnu.org/non-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.}
@@ -2484,7 +2534,7 @@ width0pt\relax} \fi
% We must actually expand the ignored text to look for the @end
% command, so that nested ignore constructs work. Thus, we put the
% text into a \vbox and then do nothing with the result. To minimize
- % the change of memory overflow, we follow the approach outlined on
+ % the chance of memory overflow, we follow the approach outlined on
% page 401 of the TeXbook: make the current font be a dummy font.
%
\setbox0 = \vbox\bgroup
@@ -2536,7 +2586,7 @@ width0pt\relax} \fi
% Do minimal line-breaking.
\pretolerance = 10000
%
- % Do not execute instructions in @tex
+ % Do not execute instructions in @tex.
\def\tex{\doignore{tex}}%
% Do not execute macro definitions.
% `c' is a comment character, so the word `macro' will get cut off.
@@ -2634,19 +2684,21 @@ width0pt\relax} \fi
\def\ifclearfail{\nestedignore{ifclear}}
\defineunmatchedend{ifclear}
-% @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.
+% @iftex, @ifnothtml, @ifnotinfo, @ifnotplaintext 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}}
+\def\ifnotplaintext{\conditionalsucceed{ifnotplaintext}}
\defineunmatchedend{iftex}
\defineunmatchedend{ifnothtml}
\defineunmatchedend{ifnotinfo}
+\defineunmatchedend{ifnotplaintext}
-% 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
+% We can't just want to start a group at @iftex (etc.) and end it at
+% @end iftex, since then @set commands inside the conditional have no
% effect (they'd get reverted at the end of the group). So we must
% define \Eiftex to redefine itself to be its previous value. (We can't
% just define it to fail again with an ``unmatched end'' error, since
@@ -2861,7 +2913,7 @@ width0pt\relax} \fi
% If an index command is used in an @example environment, any spaces
% therein should become regular spaces in the raw index file, not the
-% expansion of \tie (\\leavevmode \penalty \@M \ ).
+% expansion of \tie (\leavevmode \penalty \@M \ ).
{\obeyspaces
\gdef\unsepspaces{\obeyspaces\let =\space}}
@@ -3524,13 +3576,18 @@ width0pt\relax} \fi
\global\let\subsubsection = \numberedsubsubsec
}
+% we use \chapno to avoid indenting back
+\def\appendixbox#1{%
+ \setbox0 = \hbox{\putwordAppendix{} \the\chapno}%
+ \hbox to \wd0{#1\hss}}
+
\outer\def\appendix{\parsearg\appendixyyy}
\def\appendixyyy #1{\apphead0{#1}} % normally apphead0 calls appendixzzz
\def\appendixzzz #1{%
\secno=0 \subsecno=0 \subsubsecno=0
\global\advance \appendixno by 1
\message{\putwordAppendix\space \appendixletter}%
-\chapmacro {#1}{\putwordAppendix{} \appendixletter}%
+\chapmacro {#1}{\appendixbox{\putwordAppendix{} \appendixletter}}%
\gdef\thissection{#1}%
\gdef\thischaptername{#1}%
\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}%
@@ -3572,7 +3629,7 @@ width0pt\relax} \fi
\unnumbchapmacro {#1}%
\gdef\thischapter{#1}\gdef\thissection{#1}%
\toks0 = {#1}%
-\edef\temp{\noexpand\writetocentry{\realbackslash unnumbchapentry{\the\toks0}}}%
+\edef\temp{\noexpand\writetocentry{\realbackslash unnumbchapentry{\the\toks0}{\the\chapno}}}%
\temp
\unnumbnoderef
\global\let\section = \unnumberedsec
@@ -3613,7 +3670,8 @@ width0pt\relax} \fi
\def\unnumberedseczzz #1{%
\plainsecheading {#1}\gdef\thissection{#1}%
\toks0 = {#1}%
-\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsecentry{\the\toks0}}}%
+\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsecentry%
+ {\the\toks0}{\the\chapno}{\the\secno}}}%
\temp
\unnumbnoderef
\nobreak
@@ -3652,7 +3710,7 @@ width0pt\relax} \fi
\plainsubsecheading {#1}\gdef\thissection{#1}%
\toks0 = {#1}%
\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsecentry%
- {\the\toks0}}}%
+ {\the\toks0}{\the\chapno}{\the\secno}{\the\subsecno}}}%
\temp
\unnumbnoderef
\nobreak
@@ -3693,7 +3751,7 @@ width0pt\relax} \fi
\plainsubsubsecheading {#1}\gdef\thissection{#1}%
\toks0 = {#1}%
\edef\temp{\noexpand\writetocentry{\realbackslash unnumbsubsubsecentry%
- {\the\toks0}}}%
+ {\the\toks0}{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}}}%
\temp
\unnumbnoderef
\nobreak
@@ -3892,7 +3950,16 @@ width0pt\relax} \fi
\hangindent = \wd0 % zero if no section number
\unhbox0 #3}%
}%
- \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak
+ % Add extra space after the heading -- either a line space or a
+ % paragraph space, whichever is more. (Some people like to set
+ % \parskip to large values for some reason.)
+ \nobreak
+ \ifdim\parskip>\normalbaselineskip
+ \kern\parskip
+ \else
+ \kern\normalbaselineskip
+ \fi
+ \nobreak
}
@@ -3905,7 +3972,7 @@ width0pt\relax} \fi
% argument, which will end up as the last argument to the \...entry macro.
%
% We open the .toc file here instead of at @setfilename or any other
-% given time so that @contents can be put in the document anywhere.
+% fixed time so that @contents can be put in the document anywhere.
%
\newif\iftocfileopened
\def\writetocentry#1{%
@@ -3914,6 +3981,14 @@ width0pt\relax} \fi
\global\tocfileopenedtrue
\fi
\iflinks \write\tocfile{#1{\folio}}\fi
+ %
+ % Tell \shipout to create a page destination if we're doing pdf, which
+ % will be the target of the links in the table of contents. We can't
+ % just do it on every page because the title pages are numbered 1 and
+ % 2 (the page numbers aren't printed), and so are the first two pages
+ % of the document. Thus, we'd have two destinations named `1', and
+ % two named `2'.
+ \ifpdf \pdfmakepagedesttrue \fi
}
\newskip\contentsrightmargin \contentsrightmargin=1in
@@ -3973,16 +4048,17 @@ width0pt\relax} \fi
\let\unnumbchapentry = \shortunnumberedentry
% We want a true roman here for the page numbers.
\secfonts
- \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
+ \let\rm=\shortcontrm \let\bf=\shortcontbf
+ \let\sl=\shortcontsl \let\tt=\shortconttt
\rm
\hyphenpenalty = 10000
\advance\baselineskip by 1pt % Open it up a little.
\def\secentry ##1##2##3##4{}
- \def\unnumbsecentry ##1##2{}
\def\subsecentry ##1##2##3##4##5{}
- \def\unnumbsubsecentry ##1##2{}
\def\subsubsecentry ##1##2##3##4##5##6{}
- \def\unnumbsubsubsecentry ##1##2{}
+ \let\unnumbsecentry = \secentry
+ \let\unnumbsubsecentry = \subsecentry
+ \let\unnumbsubsubsecentry = \subsubsecentry
\openin 1 \jobname.toc
\ifeof 1 \else
\closein 1
@@ -4015,7 +4091,8 @@ width0pt\relax} \fi
}
% Appendices, in the main contents.
-\def\appendixentry#1#2#3{\dochapentry{\putwordAppendix{} #2\labelspace#1}{#3}}
+\def\appendixentry#1#2#3{%
+ \dochapentry{\appendixbox{\putwordAppendix{} #2}\labelspace#1}{#3}}
%
% Appendices, in the short toc.
\let\shortappendixentry = \shortchapentry
@@ -4039,21 +4116,21 @@ width0pt\relax} \fi
}
% Unnumbered chapters.
-\def\unnumbchapentry#1#2{\dochapentry{#1}{#2}}
-\def\shortunnumberedentry#1#2{\tocentry{#1}{\doshortpageno\bgroup#2\egroup}}
+\def\unnumbchapentry#1#2#3{\dochapentry{#1}{#3}}
+\def\shortunnumberedentry#1#2#3{\tocentry{#1}{\doshortpageno\bgroup#3\egroup}}
% Sections.
\def\secentry#1#2#3#4{\dosecentry{#2.#3\labelspace#1}{#4}}
-\def\unnumbsecentry#1#2{\dosecentry{#1}{#2}}
+\def\unnumbsecentry#1#2#3#4{\dosecentry{#1}{#4}}
% Subsections.
\def\subsecentry#1#2#3#4#5{\dosubsecentry{#2.#3.#4\labelspace#1}{#5}}
-\def\unnumbsubsecentry#1#2{\dosubsecentry{#1}{#2}}
+\def\unnumbsubsecentry#1#2#3#4#5{\dosubsecentry{#1}{#5}}
% And subsubsections.
\def\subsubsecentry#1#2#3#4#5#6{%
\dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
-\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
+\def\unnumbsubsubsecentry#1#2#3#4#5#6{\dosubsubsecentry{#1}{#6}}
% This parameter controls the indentation of the various levels.
\newdimen\tocindent \tocindent = 3pc
@@ -4114,36 +4191,27 @@ width0pt\relax} \fi
\message{environments,}
% @foo ... @end foo.
+% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
+%
% Since these characters are used in examples, it should be an even number of
% \tt widths. Each \tt character is 1en, so two makes it 1em.
-% Furthermore, these definitions must come after we define our fonts.
-\newbox\dblarrowbox \newbox\longdblarrowbox
-\newbox\pushcharbox \newbox\bullbox
-\newbox\equivbox \newbox\errorbox
-
-%{\tentt
-%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
-%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
-%\global\setbox\pushcharbox = \hbox to 1em{\hfil$\dashv$\hfil}
-%\global\setbox\equivbox = \hbox to 1em{\hfil$\ptexequiv$\hfil}
-% Adapted from the manmac format (p.420 of TeXbook)
-%\global\setbox\bullbox = \hbox to 1em{\kern.15em\vrule height .75ex width .85ex
-% 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}}
+% The @error{} command.
% Adapted from the TeXbook's \boxit.
+%
+\newbox\errorbox
+%
{\tentt \global\dimen0 = 3em}% Width of the box.
\dimen2 = .55pt % Thickness of rules
% The text. (`r' is open on the right, `e' somewhat less so on the left.)
\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
-
+%
\global\setbox\errorbox=\hbox to \dimen0{\hfil
\hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
\advance\hsize by -2\dimen2 % Rules.
@@ -4154,8 +4222,7 @@ width0pt\relax} \fi
\kern3pt\vrule width\dimen2}% Space to right.
\hrule height\dimen2}
\hfil}
-
-% The @error{} command.
+%
\def\error{\leavevmode\lower.7ex\copy\errorbox}
% @tex ... @end tex escapes into raw Tex temporarily.
@@ -4195,9 +4262,9 @@ width0pt\relax} \fi
\def\@{@}%
\let\Etex=\endgroup}
-% Define @lisp ... @endlisp.
+% Define @lisp ... @end lisp.
% @lisp does a \begingroup so it can rebind things,
-% including the definition of @endlisp (which normally is erroneous).
+% including the definition of @end lisp (which normally is erroneous).
% Amount to narrow the margins by for @lisp.
\newskip\lispnarrowing \lispnarrowing=0.4in
@@ -4226,15 +4293,18 @@ width0pt\relax} \fi
% Make spacing and below environment symmetrical. We use \parskip here
% to help in doing that, since in @example-like environments \parskip
% is reset to zero; thus the \afterenvbreak inserts no space -- but the
-% start of the next paragraph will insert \parskip
+% start of the next paragraph will insert \parskip.
%
\def\aboveenvbreak{{%
- \ifnum\lastpenalty < 10000
+ % =10000 instead of <10000 because of a special case in \itemzzz, q.v.
+ \ifnum \lastpenalty=10000 \else
\advance\envskipamount by \parskip
\endgraf
\ifdim\lastskip<\envskipamount
\removelastskip
- \penalty-50
+ % it's not a good place to break if the last penalty was \nobreak
+ % or better ...
+ \ifnum\lastpenalty>10000 \else \penalty-50 \fi
\vskip\envskipamount
\fi
\fi
@@ -4313,7 +4383,6 @@ width0pt\relax} \fi
\inENV % This group ends at the end of the body
\hfuzz = 12pt % Don't be fussy
\sepspaces % Make spaces be word-separators rather than space tokens.
- \singlespace
\let\par = \lisppar % don't ignore blank lines
\obeylines % each line of input is a line of output
\parskip = 0pt
@@ -4428,7 +4497,6 @@ width0pt\relax} \fi
\def\quotation{%
\begingroup\inENV %This group ends at the end of the @quotation body
{\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
- \singlespace
\parindent=0pt
% We have retained a nonzero parskip for the environment, since we're
% doing normal filling. So to avoid extra space below the environment...
@@ -4451,10 +4519,14 @@ width0pt\relax} \fi
%
% [Knuth]: Donald Ervin Knuth, 1996. The TeXbook.
%
-% [Knuth] p. 344; only we need to do '@' too
+% [Knuth] p.344; only we need to do the other characters Texinfo sets
+% active too. Otherwise, they get lost as the first character on a
+% verbatim line.
\def\dospecials{%
- \do\ \do\\\do\@\do\{\do\}\do\$\do\&%
- \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~}
+ \do\ \do\\\do\{\do\}\do\$\do\&%
+ \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~%
+ \do\<\do\>\do\|\do\@\do+\do\"%
+}
%
% [Knuth] p. 380
\def\uncatcodespecials{%
@@ -4541,7 +4613,7 @@ width0pt\relax} \fi
%
% For Texinfo it's a lot easier than for LaTeX,
% because texinfo's \verbatim doesn't stop at '\end{verbatim}':
-% we need not redefine '\', '{' and '}'
+% we need not redefine '\', '{' and '}'.
%
% Inspired by LaTeX's verbatim command set [latex.ltx]
%% Include LaTeX hack for completeness -- never know
@@ -4551,9 +4623,14 @@ width0pt\relax} \fi
%% \catcode`\\=12|gdef|doverbatim#1@end verbatim[
%% #1|endgroup|def|Everbatim[]|end[verbatim]]
%% |endgroup
+%
\begingroup
\catcode`\ =\active
- \gdef\doverbatim#1@end verbatim{#1\end{verbatim}}
+ \obeylines %
+ % ignore everything up to the first ^^M, that's the newline at the end
+ % of the @verbatim input line itself. Otherwise we get an extra blank
+ % line in the output.
+ \gdef\doverbatim#1^^M#2@end verbatim{#2\end{verbatim}}%
\endgroup
%
\def\verbatim{%
@@ -4595,24 +4672,94 @@ width0pt\relax} \fi
\endgroup\nonfillfinish\endgroup
}
+% @copying ... @end copying.
+% Save the text away for @insertcopying later. Many commands won't be
+% allowed in this context, but that's ok.
+%
+% We save the uninterpreted tokens, rather than creating a box.
+% Saving the text in a box would be much easier, but then all the
+% typesetting commands (@smallbook, font changes, etc.) have to be done
+% beforehand -- and a) we want @copying to be done first in the source
+% file; b) letting users define the frontmatter in as flexible order as
+% possible is very desirable.
+%
+\def\copying{\begingroup
+ % Define a command to swallow text until we reach `@end copying'.
+ % \ is the escape char in this texinfo.tex file, so it is the
+ % delimiter for the command; @ will be the escape char when we read
+ % it, but that doesn't matter.
+ \long\def\docopying##1\end copying{\gdef\copyingtext{##1}\enddocopying}%
+ %
+ % We must preserve ^^M's in the input file; see \insertcopying below.
+ \catcode`\^^M = \active
+ \docopying
+}
+
+% What we do to finish off the copying text.
+%
+\def\enddocopying{\endgroup\ignorespaces}
+
+% @insertcopying. Here we must play games with ^^M's. On the one hand,
+% we need them to delimit commands such as `@end quotation', so they
+% must be active. On the other hand, we certainly don't want every
+% end-of-line to be a \par, as would happen with the normal active
+% definition of ^^M. On the third hand, two ^^M's in a row should still
+% generate a \par.
+%
+% Our approach is to make ^^M insert a space and a penalty1 normally;
+% then it can also check if \lastpenalty=1. If it does, then manually
+% do \par.
+%
+% This messes up the normal definitions of @c[omment], so we redefine
+% it. Similarly for @ignore. (These commands are used in the gcc
+% manual for man page generation.)
+%
+% Seems pretty fragile, most line-oriented commands will presumably
+% fail, but for the limited use of getting the copying text (which
+% should be quite simple) inserted, we can hope it's ok.
+%
+{\catcode`\^^M=\active %
+\gdef\insertcopying{\begingroup %
+ \parindent = 0pt % looks wrong on title page
+ \def^^M{%
+ \ifnum \lastpenalty=1 %
+ \par %
+ \else %
+ \space \penalty 1 %
+ \fi %
+ }%
+ %
+ % Fix @c[omment] for catcode 13 ^^M's.
+ \def\c##1^^M{\ignorespaces}%
+ \let\comment = \c %
+ %
+ % Don't bother jumping through all the hoops that \doignore does, it
+ % would be very hard since the catcodes are already set.
+ \long\def\ignore##1\end ignore{\ignorespaces}%
+ %
+ \copyingtext %
+\endgroup}%
+}
\message{defuns,}
% @defun etc.
% Allow user to change definition object font (\df) internally
-\def\setdeffont #1 {\csname DEF#1\endcsname}
+\def\setdeffont#1 {\csname DEF#1\endcsname}
\newskip\defbodyindent \defbodyindent=.4in
\newskip\defargsindent \defargsindent=50pt
-\newskip\deftypemargin \deftypemargin=12pt
\newskip\deflastargmargin \deflastargmargin=18pt
\newcount\parencount
-% define \functionparens, which makes ( and ) and & do special things.
-% \functionparens affects the group it is contained in.
+
+% We want ()&[] to print specially on the defun line.
+%
\def\activeparens{%
-\catcode`\(=\active \catcode`\)=\active \catcode`\&=\active
-\catcode`\[=\active \catcode`\]=\active}
+ \catcode`\(=\active \catcode`\)=\active
+ \catcode`\&=\active
+ \catcode`\[=\active \catcode`\]=\active
+}
% Make control sequences which act like normal parenthesis chars.
\let\lparen = ( \let\rparen = )
@@ -4663,84 +4810,117 @@ width0pt\relax} \fi
\global\let& = \ampnr
}
-% First, defname, which formats the header line itself.
-% #1 should be the function name.
-% #2 should be the type of definition, such as "Function".
-
-\def\defname #1#2{%
-% Get the values of \leftskip and \rightskip as they were
-% outside the @def...
-\dimen2=\leftskip
-\advance\dimen2 by -\defbodyindent
-\noindent
-\setbox0=\hbox{\hskip \deflastargmargin{\rm #2}\hskip \deftypemargin}%
-\dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
-\dimen1=\hsize \advance \dimen1 by -\defargsindent %size for continuations
-\parshape 2 0in \dimen0 \defargsindent \dimen1
-% Now output arg 2 ("Function" or some such)
-% ending at \deftypemargin from the right margin,
-% but stuck inside a box of width 0 so it does not interfere with linebreaking
-{% Adjust \hsize to exclude the ambient margins,
-% so that \rightline will obey them.
-\advance \hsize by -\dimen2
-\rlap{\rightline{{\rm #2}\hskip -1.25pc }}}%
-% Make all lines underfull and no complaints:
-\tolerance=10000 \hbadness=10000
-\advance\leftskip by -\defbodyindent
-\exdentamount=\defbodyindent
-{\df #1}\enskip % Generate function name
-}
-
-% Actually process the body of a definition
-% #1 should be the terminating control sequence, such as \Edefun.
-% #2 should be the "another name" control sequence, such as \defunx.
-% #3 should be the control sequence that actually processes the header,
-% such as \defunheader.
-
-\def\defparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
-\medbreak %
-% Define the end token that this defining construct specifies
-% so that it will exit this group.
-\def#1{\endgraf\endgroup\medbreak}%
-\def#2{\begingroup\obeylines\activeparens\spacesplit#3}%
-\parindent=0in
-\advance\leftskip by \defbodyindent
-\exdentamount=\defbodyindent
-\begingroup %
-\catcode 61=\active % 61 is `='
-\obeylines\activeparens\spacesplit#3}
+% \defname, which formats the name of the @def (not the args).
+% #1 is the function name.
+% #2 is the type of definition, such as "Function".
+%
+\def\defname#1#2{%
+ % How we'll output the type name. Putting it in brackets helps
+ % distinguish it from the body text that may end up on the next line
+ % just below it.
+ \ifempty{#2}%
+ \def\defnametype{}%
+ \else
+ \def\defnametype{[\rm #2]}%
+ \fi
+ %
+ % Get the values of \leftskip and \rightskip as they were outside the @def...
+ \dimen2=\leftskip
+ \advance\dimen2 by -\defbodyindent
+ %
+ % Figure out values for the paragraph shape.
+ \setbox0=\hbox{\hskip \deflastargmargin{\defnametype}}%
+ \dimen0=\hsize \advance \dimen0 by -\wd0 % compute size for first line
+ \dimen1=\hsize \advance \dimen1 by -\defargsindent % size for continuations
+ \parshape 2 0in \dimen0 \defargsindent \dimen1
+ %
+ % Output arg 2 ("Function" or some such) but stuck inside a box of
+ % width 0 so it does not interfere with linebreaking.
+ \noindent
+ %
+ {% Adjust \hsize to exclude the ambient margins,
+ % so that \rightline will obey them.
+ \advance \hsize by -\dimen2
+ \dimen3 = 0pt % was -1.25pc
+ \rlap{\rightline{\defnametype\kern\dimen3}}%
+ }%
+ %
+ % Allow all lines to be underfull without complaint:
+ \tolerance=10000 \hbadness=10000
+ \advance\leftskip by -\defbodyindent
+ \exdentamount=\defbodyindent
+ {\df #1}\enskip % output function name
+ % \defunargs will be called next to output the arguments, if any.
+}
+% Common pieces to start any @def...
% #1 is the \E... control sequence to end the definition (which we define).
-% #2 is the \...x control sequence for consecutive fns (which we define).
-% #3 is the control sequence to call to resume processing.
+% #2 is the \...x control sequence (which our caller defines).
+% #3 is the control sequence to process the header, such as \defunheader.
+%
+\def\parsebodycommon#1#2#3{%
+ \begingroup\inENV
+ % If there are two @def commands in a row, we'll have a \nobreak,
+ % which is there to keep the function description together with its
+ % header. But if there's nothing but headers, we want to allow a
+ % break after all.
+ \ifnum\lastpenalty=10000 \penalty0 \fi
+ \medbreak
+ %
+ % Define the \E... end token that this defining construct specifies
+ % so that it will exit this group.
+ \def#1{\endgraf\endgroup\medbreak}%
+ %
+ \parindent=0in
+ \advance\leftskip by \defbodyindent
+ \exdentamount=\defbodyindent
+}
+
+% Common part of the \...x definitions.
+%
+\def\defxbodycommon{%
+ % As with \parsebodycommon above, allow line break if we have multiple
+ % x headers in a row. It's not a great place, though.
+ \ifnum\lastpenalty=10000 \penalty1000 \fi
+ %
+ \begingroup\obeylines
+}
+
+% Process body of @defun, @deffn, @defmac, etc.
+%
+\def\defparsebody#1#2#3{%
+ \parsebodycommon{#1}{#2}{#3}%
+ \def#2{\defxbodycommon \activeparens \spacesplit#3}%
+ \catcode61=\active % 61 is `='
+ \begingroup\obeylines\activeparens
+ \spacesplit#3%
+}
+
+% #1, #2, #3 are the common arguments (see \parsebodycommon above).
% #4, delimited by the space, is the class name.
%
-\def\defmethparsebody#1#2#3#4 {\begingroup\inENV %
-\medbreak %
-% Define the end token that this defining construct specifies
-% so that it will exit this group.
-\def#1{\endgraf\endgroup\medbreak}%
-\def#2##1 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}}}%
-\parindent=0in
-\advance\leftskip by \defbodyindent
-\exdentamount=\defbodyindent
-\begingroup\obeylines\activeparens\spacesplit{#3{#4}}}
+\def\defmethparsebody#1#2#3#4 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \def#2##1 {\defxbodycommon \activeparens \spacesplit{#3{##1}}}%
+ \begingroup\obeylines\activeparens
+ % The \empty here prevents misinterpretation of a construct such as
+ % @deffn {whatever} {Enharmonic comma}
+ % See comments at \deftpparsebody, although in our case we don't have
+ % to remove the \empty afterwards, since it is empty.
+ \spacesplit{#3{#4}}\empty
+}
% Used for @deftypemethod and @deftypeivar.
-% #1 is the \E... control sequence to end the definition (which we define).
-% #2 is the \...x control sequence for consecutive fns (which we define).
-% #3 is the control sequence to call to resume processing.
+% #1, #2, #3 are the common arguments (see \defparsebody).
% #4, delimited by a space, is the class name.
% #5 is the method's return type.
%
-\def\deftypemethparsebody#1#2#3#4 #5 {\begingroup\inENV
- \medbreak
- \def#1{\endgraf\endgroup\medbreak}%
- \def#2##1 ##2 {\begingroup\obeylines\activeparens\spacesplit{#3{##1}{##2}}}%
- \parindent=0in
- \advance\leftskip by \defbodyindent
- \exdentamount=\defbodyindent
- \begingroup\obeylines\activeparens\spacesplit{#3{#4}{#5}}}
+\def\deftypemethparsebody#1#2#3#4 #5 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \def#2##1 ##2 {\defxbodycommon \activeparens \spacesplit{#3{##1}{##2}}}%
+ \begingroup\obeylines\activeparens
+ \spacesplit{#3{#4}{#5}}%
+}
% Used for @deftypeop. The change from \deftypemethparsebody is an
% extra argument at the beginning which is the `category', instead of it
@@ -4749,64 +4929,48 @@ width0pt\relax} \fi
% input at hand. Thus also need a control sequence (passed as #5) for
% the \E... definition to assign the category name to.
%
-\def\deftypeopparsebody#1#2#3#4#5 #6 {\begingroup\inENV
- \medbreak
- \def#1{\endgraf\endgroup\medbreak}%
- \def#2##1 ##2 ##3 {%
- \def#4{##1}%
- \begingroup\obeylines\activeparens\spacesplit{#3{##2}{##3}}}%
- \parindent=0in
- \advance\leftskip by \defbodyindent
- \exdentamount=\defbodyindent
- \begingroup\obeylines\activeparens\spacesplit{#3{#5}{#6}}}
-
-\def\defopparsebody #1#2#3#4#5 {\begingroup\inENV %
-\medbreak %
-% Define the end token that this defining construct specifies
-% so that it will exit this group.
-\def#1{\endgraf\endgroup\medbreak}%
-\def#2##1 ##2 {\def#4{##1}%
-\begingroup\obeylines\activeparens\spacesplit{#3{##2}}}%
-\parindent=0in
-\advance\leftskip by \defbodyindent
-\exdentamount=\defbodyindent
-\begingroup\obeylines\activeparens\spacesplit{#3{#5}}}
+\def\deftypeopparsebody#1#2#3#4#5 #6 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \def#2##1 ##2 ##3 {\def#4{##1}%
+ \defxbodycommon \activeparens \spacesplit{#3{##2}{##3}}}%
+ \begingroup\obeylines\activeparens
+ \spacesplit{#3{#5}{#6}}%
+}
+
+% For @defop.
+\def\defopparsebody #1#2#3#4#5 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \def#2##1 ##2 {\def#4{##1}%
+ \defxbodycommon \activeparens \spacesplit{#3{##2}}}%
+ \begingroup\obeylines\activeparens
+ \spacesplit{#3{#5}}%
+}
% These parsing functions are similar to the preceding ones
% except that they do not make parens into active characters.
% These are used for "variables" since they have no arguments.
-
-\def\defvarparsebody #1#2#3{\begingroup\inENV% Environment for definitionbody
-\medbreak %
-% Define the end token that this defining construct specifies
-% so that it will exit this group.
-\def#1{\endgraf\endgroup\medbreak}%
-\def#2{\begingroup\obeylines\spacesplit#3}%
-\parindent=0in
-\advance\leftskip by \defbodyindent
-\exdentamount=\defbodyindent
-\begingroup %
-\catcode 61=\active %
-\obeylines\spacesplit#3}
-
-% 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 %
- % Define the end token that this defining construct specifies
- % so that it will exit this group.
- \def#1{\endgraf\endgroup\medbreak}%
- \def#2##1 {\begingroup\obeylines\spacesplit{#3{##1}}}%
- \parindent=0in
- \advance\leftskip by \defbodyindent
- \exdentamount=\defbodyindent
+\def\defvarparsebody #1#2#3{%
+ \parsebodycommon{#1}{#2}{#3}%
+ \def#2{\defxbodycommon \spacesplit#3}%
+ \catcode61=\active %
+ \begingroup\obeylines
+ \spacesplit#3%
+}
+
+% @defopvar.
+\def\defopvarparsebody #1#2#3#4#5 {%
+ \parsebodycommon{#1}{#2}{#3}%
+ \def#2##1 ##2 {\def#4{##1}%
+ \defxbodycommon \spacesplit{#3{##2}}}%
\begingroup\obeylines
+ \spacesplit{#3{#5}}%
}
\def\defvrparsebody#1#2#3#4 {%
\parsebodycommon{#1}{#2}{#3}%
+ \def#2##1 {\defxbodycommon \spacesplit{#3{##1}}}%
+ \begingroup\obeylines
\spacesplit{#3{#4}}%
}
@@ -4821,6 +4985,8 @@ width0pt\relax} \fi
%
\def\deftpparsebody #1#2#3#4 {%
\parsebodycommon{#1}{#2}{#3}%
+ \def#2##1 {\defxbodycommon \spacesplit{#3{##1}}}%
+ \begingroup\obeylines
\spacesplit{\parsetpheaderline{#3{#4}}}\empty
}
@@ -4837,32 +5003,22 @@ width0pt\relax} \fi
#1{\removeemptybraces#2\relax}{#3}%
}%
-\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
-\medbreak %
-% Define the end token that this defining construct specifies
-% so that it will exit this group.
-\def#1{\endgraf\endgroup\medbreak}%
-\def#2##1 ##2 {\def#4{##1}%
-\begingroup\obeylines\spacesplit{#3{##2}}}%
-\parindent=0in
-\advance\leftskip by \defbodyindent
-\exdentamount=\defbodyindent
-\begingroup\obeylines\spacesplit{#3{#5}}}
-
-% Split up #2 at the first space token.
+% Split up #2 (the rest of the input line) at the first space token.
% call #1 with two arguments:
% the first is all of #2 before the space token,
% the second is all of #2 after that space token.
% If #2 contains no space token, all of it is passed as the first arg
% and the second is passed as empty.
-
-{\obeylines
-\gdef\spacesplit#1#2^^M{\endgroup\spacesplitfoo{#1}#2 \relax\spacesplitfoo}%
-\long\gdef\spacesplitfoo#1#2 #3#4\spacesplitfoo{%
-\ifx\relax #3%
-#1{#2}{}\else #1{#2}{#3#4}\fi}}
-
-% So much for the things common to all kinds of definitions.
+%
+{\obeylines %
+ \gdef\spacesplit#1#2^^M{\endgroup\spacesplitx{#1}#2 \relax\spacesplitx}%
+ \long\gdef\spacesplitx#1#2 #3#4\spacesplitx{%
+ \ifx\relax #3%
+ #1{#2}{}%
+ \else %
+ #1{#2}{#3#4}%
+ \fi}%
+}
% Define @defun.
@@ -5273,7 +5429,7 @@ width0pt\relax} \fi
\message{Warning: redefining \the\macname}%
\else
\expandafter\ifx\csname \the\macname\endcsname \relax
- \else \errmessage{The name \the\macname\space is reserved}\fi
+ \else \errmessage{Macro name \the\macname\space already defined}\fi
\global\cslet{macsave.\the\macname}{\the\macname}%
\global\expandafter\let\csname ismacro.\the\macname\endcsname=1%
% Add the macroname to \macrolist
@@ -6019,11 +6175,13 @@ should work if nowhere else does.}
}
% Parameters in order: 1) textheight; 2) textwidth; 3) voffset;
-% 4) hoffset; 5) binding offset; 6) topskip. We also call
-% \setleading{\textleading}, so the caller should define \textleading.
-% The caller should also set \parskip.
+% 4) hoffset; 5) binding offset; 6) topskip; 7) physical page height; 8)
+% physical page width.
+%
+% We also call \setleading{\textleading}, so the caller should define
+% \textleading. The caller should also set \parskip.
%
-\def\internalpagesizes#1#2#3#4#5#6{%
+\def\internalpagesizes#1#2#3#4#5#6#7#8{%
\voffset = #3\relax
\topskip = #6\relax
\splittopskip = \topskip
@@ -6042,6 +6200,11 @@ should work if nowhere else does.}
\normaloffset = #4\relax
\bindingoffset = #5\relax
%
+ \ifpdf
+ \pdfpageheight #7\relax
+ \pdfpagewidth #8\relax
+ \fi
+ %
\setleading{\textleading}
%
\parindent = \defaultparindent
@@ -6063,7 +6226,10 @@ should work if nowhere else does.}
\textleading = 13.2pt
%
% If page is nothing but text, make it come out even.
- \internalpagesizes{46\baselineskip}{6in}{\voffset}{.25in}{\bindingoffset}{36pt}%
+ \internalpagesizes{46\baselineskip}{6in}%
+ {\voffset}{.25in}%
+ {\bindingoffset}{36pt}%
+ {11in}{8.5in}%
}}
% Use @smallbook to reset parameters for 7x9.5 (or so) format.
@@ -6071,13 +6237,15 @@ should work if nowhere else does.}
\parskip = 2pt plus 1pt
\textleading = 12pt
%
- \internalpagesizes{7.5in}{5.in}{\voffset}{.25in}{\bindingoffset}{16pt}%
+ \internalpagesizes{7.5in}{5in}%
+ {\voffset}{.25in}%
+ {\bindingoffset}{16pt}%
+ {9.25in}{7in}%
%
\lispnarrowing = 0.3in
\tolerance = 700
\hfuzz = 1pt
\contentsrightmargin = 0pt
- \deftypemargin = 0pt
\defbodyindent = .5cm
\smallenvironments
}}
@@ -6085,12 +6253,27 @@ should work if nowhere else does.}
% Use @afourpaper to print on European A4 paper.
\def\afourpaper{{\globaldefs = 1
\parskip = 3pt plus 2pt minus 1pt
- \textleading = 12pt
+ \textleading = 13.2pt
%
- \internalpagesizes{53\baselineskip}{160mm}{\voffset}{4mm}{\bindingoffset}{44pt}%
+ % Double-side printing via postscript on Laserjet 4050
+ % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm.
+ % To change the settings for a different printer or situation, adjust
+ % \normaloffset until the front-side and back-side texts align. Then
+ % do the same for \bindingoffset. You can set these for testing in
+ % your texinfo source file like this:
+ % @tex
+ % \global\normaloffset = -6mm
+ % \global\bindingoffset = 10mm
+ % @end tex
+ \internalpagesizes{51\baselineskip}{160mm}
+ {\voffset}{\hoffset}%
+ {\bindingoffset}{44pt}%
+ {297mm}{210mm}%
%
\tolerance = 700
\hfuzz = 1pt
+ \contentsrightmargin = 0pt
+ \defbodyindent = 5mm
}}
% Use @afivepaper to print on European A5 paper.
@@ -6100,37 +6283,42 @@ should work if nowhere else does.}
\parskip = 2pt plus 1pt minus 0.1pt
\textleading = 12.5pt
%
- \internalpagesizes{166mm}{120mm}{\voffset}{-8mm}{\bindingoffset}{8pt}%
+ \internalpagesizes{160mm}{120mm}%
+ {\voffset}{\hoffset}%
+ {\bindingoffset}{8pt}%
+ {210mm}{148mm}%
%
\lispnarrowing = 0.2in
\tolerance = 800
\hfuzz = 1.2pt
- \contentsrightmargin = 0mm
- \deftypemargin = 0pt
+ \contentsrightmargin = 0pt
\defbodyindent = 2mm
\tableindent = 12mm
%
\smallenvironments
}}
-% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin
-% 29mm, hence bottom margin 28mm, nominal side margin 3cm.
+% A specific text layout, 24x15cm overall, intended for A4 paper.
\def\afourlatex{{\globaldefs = 1
- \textleading = 13.6pt
- %
\afourpaper
- \internalpagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm}%
+ \internalpagesizes{237mm}{150mm}%
+ {\voffset}{4.6mm}%
+ {\bindingoffset}{7mm}%
+ {297mm}{210mm}%
%
- % Must explicitly reset to 0 because we call \afourpaper, apparently,
- % although this does not entirely make sense.
+ % Must explicitly reset to 0 because we call \afourpaper.
\globaldefs = 0
}}
-% Use @afourwide to print on European A4 paper in wide format.
-\def\afourwide{%
+% Use @afourwide to print on A4 paper in landscape format.
+\def\afourwide{{\globaldefs = 1
\afourpaper
- \internalpagesizes{6.5in}{9.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}%
-}
+ \internalpagesizes{241mm}{165mm}%
+ {\voffset}{-2.95mm}%
+ {\bindingoffset}{7mm}%
+ {297mm}{210mm}%
+ \globaldefs = 0
+}}
% @pagesizes TEXTHEIGHT[,TEXTWIDTH]
% Perhaps we should allow setting the margins, \topskip, \parskip,
@@ -6145,7 +6333,16 @@ should work if nowhere else does.}
\parskip = 3pt plus 2pt minus 1pt
\setleading{\textleading}%
%
- \internalpagesizes{#1}{\hsize}{\voffset}{\normaloffset}{\bindingoffset}{44pt}%
+ \dimen0 = #1
+ \advance\dimen0 by \voffset
+ %
+ \dimen2 = \hsize
+ \advance\dimen2 by \normaloffset
+ %
+ \internalpagesizes{#1}{\hsize}%
+ {\voffset}{\normaloffset}%
+ {\bindingoffset}{44pt}%
+ {\dimen0}{\dimen2}%
}}
% Set default to letter.
@@ -6269,16 +6466,8 @@ should work if nowhere else does.}
@let+=@normalplus
@let$=@normaldollar}%$ font-lock fix
-@def@normalturnoffactive{@let"=@normaldoublequote
-@let\=@normalbackslash
-@let~=@normaltilde
-@let^=@normalcaret
-@let_=@normalunderscore
-@let|=@normalverticalbar
-@let<=@normalless
-@let>=@normalgreater
-@let+=@normalplus
-@let$=@normaldollar}%$ font-lock fix
+% Same as @turnoffactive except for \.
+@def@normalturnoffactive{@turnoffactive @let\=@normalbackslash}
% Make _ and + \other characters, temporarily.
% This is canceled by @fixbackslash.
diff --git a/contrib/gcc/doc/interface.texi b/contrib/gcc/doc/interface.texi
index 846de56..c554434 100644
--- a/contrib/gcc/doc/interface.texi
+++ b/contrib/gcc/doc/interface.texi
@@ -57,7 +57,7 @@ compiler for the system. We may implement register argument passing on
certain machines once we have a complete GNU system so that we can
compile the libraries with GCC@.
-On some machines (particularly the Sparc), certain types of arguments
+On some machines (particularly the SPARC), certain types of arguments
are passed ``by invisible reference''. This means that the value is
stored in memory, and the address of the memory location is passed to
the subroutine.
diff --git a/contrib/gcc/doc/invoke.texi b/contrib/gcc/doc/invoke.texi
index 62785ff..d69d896 100644
--- a/contrib/gcc/doc/invoke.texi
+++ b/contrib/gcc/doc/invoke.texi
@@ -9,7 +9,7 @@ Copyright @copyright{} 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.1 or
+under the terms of the GNU Free Documentation License, Version 1.2 or
any later version published by the Free Software Foundation; with the
Invariant Sections being ``GNU General Public License'' and ``Funding
Free Software'', the Front-Cover texts being (a) (see below), and with
@@ -66,7 +66,6 @@ for contributors to GCC@.
@cindex options, GCC command
@c man begin DESCRIPTION
-
When you invoke GCC, it normally does preprocessing, compilation,
assembly and linking. The ``overall options'' allow you to stop this
process at an intermediate stage. For example, the @option{-c} option
@@ -155,16 +154,14 @@ in the following sections.
@table @emph
@item Overall Options
@xref{Overall Options,,Options Controlling the Kind of Output}.
-@gccoptlist{
--c -S -E -o @var{file} -pipe -pass-exit-codes -x @var{language} @gol
--v -### --help --target-help --version}
+@gccoptlist{-c -S -E -o @var{file} -pipe -pass-exit-codes @gol
+-x @var{language} -v -### --help --target-help --version}
@item C Language Options
@xref{C Dialect Options,,Options Controlling C Dialect}.
-@gccoptlist{
--ansi -std=@var{standard} -aux-info @var{filename} @gol
--fno-asm -fno-builtin -fno-builtin-@var{function} @gol
--fhosted -ffreestanding @gol
+@gccoptlist{-ansi -std=@var{standard} -aux-info @var{filename} @gol
+-fno-asm -fno-builtin -fno-builtin-@var{function} @gol
+-fhosted -ffreestanding -fms-extensions @gol
-trigraphs -no-integrated-cpp -traditional -traditional-cpp @gol
-fallow-single-precision -fcond-mismatch @gol
-fsigned-bitfields -fsigned-char @gol
@@ -173,9 +170,8 @@ in the following sections.
@item C++ Language Options
@xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
-@gccoptlist{
--fno-access-control -fcheck-new -fconserve-space @gol
--fno-const-strings -fdollars-in-identifiers @gol
+@gccoptlist{-fabi-version=@var{n} -fno-access-control -fcheck-new @gol
+-fconserve-space -fno-const-strings -fdollars-in-identifiers @gol
-fno-elide-constructors @gol
-fno-enforce-eh-specs -fexternal-templates @gol
-falt-external-templates @gol
@@ -187,7 +183,7 @@ in the following sections.
-fno-optional-diags -fpermissive @gol
-frepo -fno-rtti -fstats -ftemplate-depth-@var{n} @gol
-fuse-cxa-atexit -fvtable-gc -fno-weak -nostdinc++ @gol
--fno-default-inline -Wabi -Wctor-dtor-privacy @gol
+-fno-default-inline -Wabi -Wctor-dtor-privacy @gol
-Wnon-virtual-dtor -Wreorder @gol
-Weffc++ -Wno-deprecated @gol
-Wno-non-template-friend -Wold-style-cast @gol
@@ -196,61 +192,58 @@ in the following sections.
@item Objective-C Language Options
@xref{Objective-C Dialect Options,,Options Controlling Objective-C Dialect}.
-@gccoptlist{
--fconstant-string-class=@var{class-name} @gol
+@gccoptlist{-fconstant-string-class=@var{class-name} @gol
-fgnu-runtime -fnext-runtime -gen-decls @gol
--Wno-protocol -Wselector}
+-Wno-protocol -Wselector -Wundeclared-selector}
@item Language Independent Options
@xref{Language Independent Options,,Options to Control Diagnostic Messages Formatting}.
-@gccoptlist{
--fmessage-length=@var{n} @gol
+@gccoptlist{-fmessage-length=@var{n} @gol
-fdiagnostics-show-location=@r{[}once@r{|}every-line@r{]}}
@item Warning Options
@xref{Warning Options,,Options to Request or Suppress Warnings}.
-@gccoptlist{
--fsyntax-only -pedantic -pedantic-errors @gol
--w -W -Wall -Waggregate-return @gol
+@gccoptlist{-fsyntax-only -pedantic -pedantic-errors @gol
+-w -W -Wall -Waggregate-return @gol
-Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment @gol
-Wconversion -Wno-deprecated-declarations @gol
--Wdisabled-optimization -Wdiv-by-zero -Werror @gol
+-Wdisabled-optimization -Wno-div-by-zero -Werror @gol
-Wfloat-equal -Wformat -Wformat=2 @gol
-Wformat-nonliteral -Wformat-security @gol
-Wimplicit -Wimplicit-int @gol
-Wimplicit-function-declaration @gol
-Werror-implicit-function-declaration @gol
--Wimport -Winline @gol
+-Wimport -Winline -Wno-endif-labels @gol
-Wlarger-than-@var{len} -Wlong-long @gol
-Wmain -Wmissing-braces @gol
-Wmissing-format-attribute -Wmissing-noreturn @gol
--Wmultichar -Wno-format-extra-args -Wno-format-y2k @gol
--Wno-import -Wpacked -Wpadded @gol
+-Wno-multichar -Wno-format-extra-args -Wno-format-y2k @gol
+-Wno-import -Wnonnull -Wpacked -Wpadded @gol
-Wparentheses -Wpointer-arith -Wredundant-decls @gol
-Wreturn-type -Wsequence-point -Wshadow @gol
--Wsign-compare -Wswitch -Wsystem-headers @gol
--Wtrigraphs -Wundef -Wuninitialized @gol
+-Wsign-compare -Wstrict-aliasing @gol
+-Wswitch -Wswitch-default -Wswitch-enum @gol
+-Wsystem-headers -Wtrigraphs -Wundef -Wuninitialized @gol
-Wunknown-pragmas -Wunreachable-code @gol
-Wunused -Wunused-function -Wunused-label -Wunused-parameter @gol
-Wunused-value -Wunused-variable -Wwrite-strings}
@item C-only Warning Options
-@gccoptlist{
--Wbad-function-cast -Wmissing-declarations @gol
+@gccoptlist{-Wbad-function-cast -Wmissing-declarations @gol
-Wmissing-prototypes -Wnested-externs @gol
-Wstrict-prototypes -Wtraditional}
@item Debugging Options
@xref{Debugging Options,,Options for Debugging Your Program or GCC}.
-@gccoptlist{
--d@var{letters} -dumpspecs -dumpmachine -dumpversion @gol
--fdump-unnumbered -fdump-translation-unit@r{[}-@var{n}@r{]} @gol
+@gccoptlist{-d@var{letters} -dumpspecs -dumpmachine -dumpversion @gol
+-fdump-unnumbered -fdump-translation-unit@r{[}-@var{n}@r{]} @gol
-fdump-class-hierarchy@r{[}-@var{n}@r{]} @gol
--fdump-tree-original@r{[}-@var{n}@r{]} -fdump-tree-optimized@r{[}-@var{n}@r{]} @gol
+-fdump-tree-original@r{[}-@var{n}@r{]} @gol
+-fdump-tree-optimized@r{[}-@var{n}@r{]} @gol
-fdump-tree-inlined@r{[}-@var{n}@r{]} @gol
--fmem-report -fpretend-float @gol
--fprofile-arcs -fsched-verbose=@var{n} @gol
--ftest-coverage -ftime-report @gol
+-feliminate-dwarf2-dups -fmem-report @gol
+-fprofile-arcs -frandom-seed=@var{n} @gol
+-fsched-verbose=@var{n} -ftest-coverage -ftime-report @gol
-g -g@var{level} -gcoff -gdwarf -gdwarf-1 -gdwarf-1+ -gdwarf-2 @gol
-ggdb -gstabs -gstabs+ -gvms -gxcoff -gxcoff+ @gol
-p -pg -print-file-name=@var{library} -print-libgcc-file-name @gol
@@ -260,40 +253,41 @@ in the following sections.
@item Optimization Options
@xref{Optimize Options,,Options that Control Optimization}.
-@gccoptlist{
--falign-functions=@var{n} -falign-jumps=@var{n} @gol
+@gccoptlist{-falign-functions=@var{n} -falign-jumps=@var{n} @gol
-falign-labels=@var{n} -falign-loops=@var{n} @gol
--fbounds-check @gol
--fbranch-probabilities -fcaller-saves -fcprop-registers @gol
+-fbranch-probabilities -fcaller-saves -fcprop-registers @gol
-fcse-follow-jumps -fcse-skip-blocks -fdata-sections @gol
-fdelayed-branch -fdelete-null-pointer-checks @gol
-fexpensive-optimizations -ffast-math -ffloat-store @gol
-fforce-addr -fforce-mem -ffunction-sections @gol
--fgcse -fgcse-lm -fgcse-sm @gol
+-fgcse -fgcse-lm -fgcse-sm -floop-optimize -fcrossjumping @gol
+-fif-conversion -fif-conversion2 @gol
-finline-functions -finline-limit=@var{n} -fkeep-inline-functions @gol
-fkeep-static-consts -fmerge-constants -fmerge-all-constants @gol
--fmove-all-movables -fno-branch-count-reg @gol
+-fmove-all-movables -fnew-ra -fno-branch-count-reg @gol
-fno-default-inline -fno-defer-pop @gol
-fno-function-cse -fno-guess-branch-probability @gol
-fno-inline -fno-math-errno -fno-peephole -fno-peephole2 @gol
--funsafe-math-optimizations -fno-trapping-math @gol
+-funsafe-math-optimizations -ffinite-math-only @gol
+-fno-trapping-math -fno-zero-initialized-in-bss @gol
-fomit-frame-pointer -foptimize-register-move @gol
-foptimize-sibling-calls -fprefetch-loop-arrays @gol
--freduce-all-givs -fregmove -frename-registers @gol
+-freduce-all-givs -fregmove -frename-registers @gol
+-freorder-blocks -freorder-functions @gol
-frerun-cse-after-loop -frerun-loop-opt @gol
-fschedule-insns -fschedule-insns2 @gol
--fno-sched-interblock -fno-sched-spec @gol
--fsched-spec-load -fsched-spec-load-dangerous @gol
--fsingle-precision-constant -fssa -fssa-ccp -fssa-dce @gol
--fstrength-reduce -fstrict-aliasing -fthread-jumps @gol
--ftrapv -funroll-all-loops -funroll-loops @gol
---param @var{name}=@var{value}
+-fno-sched-interblock -fno-sched-spec -fsched-spec-load @gol
+-fsched-spec-load-dangerous -fsignaling-nans @gol
+-fsingle-precision-constant -fssa -fssa-ccp -fssa-dce @gol
+-fstrength-reduce -fstrict-aliasing -ftracer -fthread-jumps @gol
+-funroll-all-loops -funroll-loops @gol
+--param @var{name}=@var{value} @gol
-O -O0 -O1 -O2 -O3 -Os}
@item Preprocessor Options
@xref{Preprocessor Options,,Options Controlling the Preprocessor}.
-@gccoptlist{
--$ -A@var{question}=@var{answer} -A-@var{question}@r{[}=@var{answer}@r{]} @gol
+@gccoptlist{-$ -A@var{question}=@var{answer} @gol
+-A-@var{question}@r{[}=@var{answer}@r{]} @gol
-C -dD -dI -dM -dN @gol
-D@var{macro}@r{[}=@var{defn}@r{]} -E -H @gol
-idirafter @var{dir} @gol
@@ -305,13 +299,11 @@ in the following sections.
@item Assembler Option
@xref{Assembler Options,,Passing Options to the Assembler}.
-@gccoptlist{
--Wa,@var{option}}
+@gccoptlist{-Wa,@var{option}}
@item Linker Options
@xref{Link Options,,Options for Linking}.
-@gccoptlist{
-@var{object-file-name} -l@var{library} @gol
+@gccoptlist{@var{object-file-name} -l@var{library} @gol
-nostartfiles -nodefaultlibs -nostdlib @gol
-s -static -static-libgcc -shared -shared-libgcc -symbolic @gol
-Wl,@var{option} -Xlinker @var{option} @gol
@@ -319,37 +311,32 @@ in the following sections.
@item Directory Options
@xref{Directory Options,,Options for Directory Search}.
-@gccoptlist{
--B@var{prefix} -I@var{dir} -I- -L@var{dir} -specs=@var{file}}
+@gccoptlist{-B@var{prefix} -I@var{dir} -I- -L@var{dir} -specs=@var{file}}
@item Target Options
@c I wrote this xref this way to avoid overfull hbox. -- rms
@xref{Target Options}.
-@gccoptlist{
--b @var{machine} -V @var{version}}
+@gccoptlist{-V @var{version} -b @var{machine}}
@item Machine Dependent Options
@xref{Submodel Options,,Hardware Models and Configurations}.
@emph{M680x0 Options}
-@gccoptlist{
--m68000 -m68020 -m68020-40 -m68020-60 -m68030 -m68040 @gol
+@gccoptlist{-m68000 -m68020 -m68020-40 -m68020-60 -m68030 -m68040 @gol
-m68060 -mcpu32 -m5200 -m68881 -mbitfield -mc68000 -mc68020 @gol
-mfpa -mnobitfield -mrtd -mshort -msoft-float -mpcrel @gol
-malign-int -mstrict-align}
@emph{M68hc1x Options}
-@gccoptlist{
--m6811 -m6812 -m68hc11 -m68hc12 @gol
--mauto-incdec -mshort -msoft-reg-count=@var{count}}
+@gccoptlist{-m6811 -m6812 -m68hc11 -m68hc12 -m68hcs12 @gol
+-mauto-incdec -minmax -mlong-calls -mshort @gol
+-msoft-reg-count=@var{count}}
@emph{VAX Options}
-@gccoptlist{
--mg -mgnu -munix}
+@gccoptlist{-mg -mgnu -munix}
@emph{SPARC Options}
-@gccoptlist{
--mcpu=@var{cpu-type} @gol
+@gccoptlist{-mcpu=@var{cpu-type} @gol
-mtune=@var{cpu-type} @gol
-mcmodel=@var{code-model} @gol
-m32 -m64 @gol
@@ -362,25 +349,8 @@ in the following sections.
-msoft-float -msoft-quad-float -msparclite -mstack-bias @gol
-msupersparc -munaligned-doubles -mv8}
-@emph{Convex Options}
-@gccoptlist{
--mc1 -mc2 -mc32 -mc34 -mc38 @gol
--margcount -mnoargcount @gol
--mlong32 -mlong64 @gol
--mvolatile-cache -mvolatile-nocache}
-
-@emph{AMD29K Options}
-@gccoptlist{
--m29000 -m29050 -mbw -mnbw -mdw -mndw @gol
--mlarge -mnormal -msmall @gol
--mkernel-registers -mno-reuse-arg-regs @gol
--mno-stack-check -mno-storem-bug @gol
--mreuse-arg-regs -msoft-float -mstack-check @gol
--mstorem-bug -muser-registers}
-
@emph{ARM Options}
-@gccoptlist{
--mapcs-frame -mno-apcs-frame @gol
+@gccoptlist{-mapcs-frame -mno-apcs-frame @gol
-mapcs-26 -mapcs-32 @gol
-mapcs-stack-check -mno-apcs-stack-check @gol
-mapcs-float -mno-apcs-float @gol
@@ -392,7 +362,6 @@ in the following sections.
-mthumb-interwork -mno-thumb-interwork @gol
-mcpu=@var{name} -march=@var{name} -mfpe=@var{name} @gol
-mstructure-size-boundary=@var{n} @gol
--mbsd -mxopen -mno-symrename @gol
-mabort-on-noreturn @gol
-mlong-calls -mno-long-calls @gol
-msingle-pic-base -mno-single-pic-base @gol
@@ -401,26 +370,22 @@ in the following sections.
-mpoke-function-name @gol
-mthumb -marm @gol
-mtpcs-frame -mtpcs-leaf-frame @gol
--mcaller-super-interworking -mcallee-super-interworking }
+-mcaller-super-interworking -mcallee-super-interworking}
@emph{MN10200 Options}
-@gccoptlist{
--mrelax}
+@gccoptlist{-mrelax}
@emph{MN10300 Options}
-@gccoptlist{
--mmult-bug -mno-mult-bug @gol
+@gccoptlist{-mmult-bug -mno-mult-bug @gol
-mam33 -mno-am33 @gol
-mno-crt0 -mrelax}
@emph{M32R/D Options}
-@gccoptlist{
--m32rx -m32r -mcode-model=@var{model-type} -msdata=@var{sdata-type} @gol
--G @var{num}}
+@gccoptlist{-m32rx -m32r -mcode-model=@var{model-type} @gol
+-msdata=@var{sdata-type} -G @var{num}}
@emph{M88K Options}
-@gccoptlist{
--m88000 -m88100 -m88110 -mbig-pic @gol
+@gccoptlist{-m88000 -m88100 -m88110 -mbig-pic @gol
-mcheck-zero-division -mhandle-large-shift @gol
-midentify-revision -mno-check-zero-division @gol
-mno-ocs-debug-info -mno-ocs-frame-position @gol
@@ -432,12 +397,11 @@ in the following sections.
-mversion-03.00 -mwarn-passed-structs}
@emph{RS/6000 and PowerPC Options}
-@gccoptlist{
--mcpu=@var{cpu-type} @gol
+@gccoptlist{-mcpu=@var{cpu-type} @gol
-mtune=@var{cpu-type} @gol
-mpower -mno-power -mpower2 -mno-power2 @gol
-mpowerpc -mpowerpc64 -mno-powerpc @gol
--maltivec -mno-altivec @gol
+-maltivec -mno-altivec @gol
-mpowerpc-gpopt -mno-powerpc-gpopt @gol
-mpowerpc-gfxopt -mno-powerpc-gfxopt @gol
-mnew-mnemonics -mold-mnemonics @gol
@@ -448,24 +412,46 @@ in the following sections.
-mfused-madd -mno-fused-madd -mbit-align -mno-bit-align @gol
-mstrict-align -mno-strict-align -mrelocatable @gol
-mno-relocatable -mrelocatable-lib -mno-relocatable-lib @gol
--mtoc -mno-toc -mlittle -mlittle-endian -mbig -mbig-endian @gol
--mcall-aix -mcall-sysv -mcall-netbsd @gol
--maix-struct-return -msvr4-struct-return @gol
--mabi=altivec -mabi=no-altivec @gol
+-mtoc -mno-toc -mlittle -mlittle-endian -mbig -mbig-endian @gol
+-mcall-aix -mcall-sysv -mcall-netbsd @gol
+-maix-struct-return -msvr4-struct-return @gol
+-mabi=altivec -mabi=no-altivec @gol
+-mabi=spe -mabi=no-spe @gol
+-misel=yes -misel=no @gol
-mprototype -mno-prototype @gol
--msim -mmvme -mads -myellowknife -memb -msdata @gol
--msdata=@var{opt} -mvxworks -G @var{num} -pthread}
+-msim -mmvme -mads -myellowknife -memb -msdata @gol
+-msdata=@var{opt} -mvxworks -mwindiss -G @var{num} -pthread}
-@emph{RT Options}
+@emph{Darwin Options}
@gccoptlist{
--mcall-lib-mul -mfp-arg-in-fpregs -mfp-arg-in-gregs @gol
+-all_load -allowable_client -arch -arch_errors_fatal @gol
+-arch_only -bind_at_load -bundle -bundle_loader @gol
+-client_name -compatibility_version -current_version @gol
+-dependency-file -dylib_file -dylinker_install_name @gol
+-dynamic -dynamiclib -exported_symbols_list @gol
+-filelist -flat_namespace -force_cpusubtype_ALL @gol
+-force_flat_namespace -headerpad_max_install_names @gol
+-image_base -init -install_name -keep_private_externs @gol
+-multi_module -multiply_defined -multiply_defined_unused @gol
+-noall_load -nomultidefs -noprebind -noseglinkedit @gol
+-pagezero_size -prebind -prebind_all_twolevel_modules @gol
+-private_bundle -read_only_relocs -sectalign @gol
+-sectobjectsymbols -whyload -seg1addr @gol
+-sectcreate -sectobjectsymbols -sectorder @gol
+-seg_addr_table -seg_addr_table_filename -seglinkedit @gol
+-segprot -segs_read_only_addr -segs_read_write_addr @gol
+-single_module -static -sub_library -sub_umbrella @gol
+-twolevel_namespace -umbrella -undefined @gol
+-unexported_symbols_list -weak_reference_mismatches -whatsloaded}
+
+@emph{RT Options}
+@gccoptlist{-mcall-lib-mul -mfp-arg-in-fpregs -mfp-arg-in-gregs @gol
-mfull-fp-blocks -mhc-struct-return -min-line-mul @gol
-mminimum-fp-blocks -mnohc-struct-return}
@emph{MIPS Options}
-@gccoptlist{
--mabicalls -march=@var{cpu-type} -mtune=@var{cpu=type} @gol
--mcpu=@var{cpu-type} -membedded-data -muninit-const-in-rodata @gol
+@gccoptlist{-mabicalls -march=@var{cpu-type} -mtune=@var{cpu=type} @gol
+-mcpu=@var{cpu-type} -membedded-data -muninit-const-in-rodata @gol
-membedded-pic -mfp32 -mfp64 -mfused-madd -mno-fused-madd @gol
-mgas -mgp32 -mgp64 @gol
-mgpopt -mhalf-pic -mhard-float -mint64 -mips1 @gol
@@ -478,39 +464,39 @@ in the following sections.
-m4650 -msingle-float -mmad @gol
-mstats -EL -EB -G @var{num} -nocpp @gol
-mabi=32 -mabi=n32 -mabi=64 -mabi=eabi @gol
--mfix7000 -mno-crt0 -mflush-func=@var{func} -mno-flush-func}
+-mfix7000 -mno-crt0 -mflush-func=@var{func} -mno-flush-func @gol
+-mbranch-likely -mno-branch-likely}
@emph{i386 and x86-64 Options}
-@gccoptlist{
--mcpu=@var{cpu-type} -march=@var{cpu-type} -mfpmath=@var{unit} @gol
--masm=@var{dialect} -mno-fancy-math-387 @gol
+@gccoptlist{-mcpu=@var{cpu-type} -march=@var{cpu-type} @gol
+-mfpmath=@var{unit} -masm=@var{dialect} -mno-fancy-math-387 @gol
-mno-fp-ret-in-387 -msoft-float -msvr3-shlib @gol
-mno-wide-multiply -mrtd -malign-double @gol
-mpreferred-stack-boundary=@var{num} @gol
--mmmx -msse -msse2 -m3dnow @gol
+-mmmx -msse -msse2 -m3dnow @gol
-mthreads -mno-align-stringops -minline-all-stringops @gol
-mpush-args -maccumulate-outgoing-args -m128bit-long-double @gol
-m96bit-long-double -mregparm=@var{num} -momit-leaf-frame-pointer @gol
-mno-red-zone@gol
-mcmodel=@var{code-model} @gol
--m32 -m64}
+-m32 -m64}
@emph{HPPA Options}
-@gccoptlist{
--march=@var{architecture-type} @gol
+@gccoptlist{-march=@var{architecture-type} @gol
-mbig-switch -mdisable-fpregs -mdisable-indexing @gol
--mfast-indirect-calls -mgas -mjump-in-delay @gol
+-mfast-indirect-calls -mgas -mgnu-ld -mhp-ld @gol
+-mjump-in-delay -mlinker-opt -mlong-calls @gol
-mlong-load-store -mno-big-switch -mno-disable-fpregs @gol
-mno-disable-indexing -mno-fast-indirect-calls -mno-gas @gol
-mno-jump-in-delay -mno-long-load-store @gol
-mno-portable-runtime -mno-soft-float @gol
-mno-space-regs -msoft-float -mpa-risc-1-0 @gol
-mpa-risc-1-1 -mpa-risc-2-0 -mportable-runtime @gol
--mschedule=@var{cpu-type} -mspace-regs}
+-mschedule=@var{cpu-type} -mspace-regs -msio -mwsio @gol
+-nolibdld -static -threads}
@emph{Intel 960 Options}
-@gccoptlist{
--m@var{cpu-type} -masm-compat -mclean-linkage @gol
+@gccoptlist{-m@var{cpu-type} -masm-compat -mclean-linkage @gol
-mcode-align -mcomplex-addr -mleaf-procedures @gol
-mic-compat -mic2.0-compat -mic3.0-compat @gol
-mintel-asm -mno-clean-linkage -mno-code-align @gol
@@ -520,8 +506,7 @@ in the following sections.
-mtail-call}
@emph{DEC Alpha Options}
-@gccoptlist{
--mno-fp-regs -msoft-float -malpha-as -mgas @gol
+@gccoptlist{-mno-fp-regs -msoft-float -malpha-as -mgas @gol
-mieee -mieee-with-inexact -mieee-conformant @gol
-mfp-trap-mode=@var{mode} -mfp-rounding-mode=@var{mode} @gol
-mtrap-precision=@var{mode} -mbuild-constants @gol
@@ -532,111 +517,96 @@ in the following sections.
-mmemory-latency=@var{time}}
@emph{DEC Alpha/VMS Options}
-@gccoptlist{
--mvms-return-codes}
-
-@emph{Clipper Options}
-@gccoptlist{
--mc300 -mc400}
+@gccoptlist{-mvms-return-codes}
@emph{H8/300 Options}
-@gccoptlist{
--mrelax -mh -ms -mint32 -malign-300}
+@gccoptlist{-mrelax -mh -ms -mn -mint32 -malign-300}
@emph{SH Options}
-@gccoptlist{
--m1 -m2 -m3 -m3e @gol
+@gccoptlist{-m1 -m2 -m3 -m3e @gol
-m4-nofpu -m4-single-only -m4-single -m4 @gol
--m5-64media -m5-64media-nofpu @gol
--m5-32media -m5-32media-nofpu @gol
--m5-compact -m5-compact-nofpu @gol
+-m5-64media -m5-64media-nofpu @gol
+-m5-32media -m5-32media-nofpu @gol
+-m5-compact -m5-compact-nofpu @gol
-mb -ml -mdalign -mrelax @gol
-mbigtable -mfmovd -mhitachi -mnomacsave @gol
-mieee -misize -mpadstruct -mspace @gol
-mprefergot -musermode}
@emph{System V Options}
-@gccoptlist{
--Qy -Qn -YP,@var{paths} -Ym,@var{dir}}
+@gccoptlist{-Qy -Qn -YP,@var{paths} -Ym,@var{dir}}
@emph{ARC Options}
-@gccoptlist{
--EB -EL @gol
+@gccoptlist{-EB -EL @gol
-mmangle-cpu -mcpu=@var{cpu} -mtext=@var{text-section} @gol
-mdata=@var{data-section} -mrodata=@var{readonly-data-section}}
@emph{TMS320C3x/C4x Options}
-@gccoptlist{
--mcpu=@var{cpu} -mbig -msmall -mregparm -mmemparm @gol
+@gccoptlist{-mcpu=@var{cpu} -mbig -msmall -mregparm -mmemparm @gol
-mfast-fix -mmpyi -mbk -mti -mdp-isr-reload @gol
-mrpts=@var{count} -mrptb -mdb -mloop-unsigned @gol
-mparallel-insns -mparallel-mpy -mpreserve-float}
@emph{V850 Options}
-@gccoptlist{
--mlong-calls -mno-long-calls -mep -mno-ep @gol
+@gccoptlist{-mlong-calls -mno-long-calls -mep -mno-ep @gol
-mprolog-function -mno-prolog-function -mspace @gol
-mtda=@var{n} -msda=@var{n} -mzda=@var{n} @gol
+-mapp-regs -mno-app-regs @gol
+-mdisable-callt -mno-disable-callt @gol
+-mv850e @gol
-mv850 -mbig-switch}
@emph{NS32K Options}
-@gccoptlist{
--m32032 -m32332 -m32532 -m32081 -m32381 @gol
+@gccoptlist{-m32032 -m32332 -m32532 -m32081 -m32381 @gol
-mmult-add -mnomult-add -msoft-float -mrtd -mnortd @gol
-mregparam -mnoregparam -msb -mnosb @gol
-mbitfield -mnobitfield -mhimem -mnohimem}
@emph{AVR Options}
-@gccoptlist{
--mmcu=@var{mcu} -msize -minit-stack=@var{n} -mno-interrupts @gol
+@gccoptlist{-mmcu=@var{mcu} -msize -minit-stack=@var{n} -mno-interrupts @gol
-mcall-prologues -mno-tablejump -mtiny-stack}
@emph{MCore Options}
-@gccoptlist{
--mhardlit -mno-hardlit -mdiv -mno-div -mrelax-immediates @gol
+@gccoptlist{-mhardlit -mno-hardlit -mdiv -mno-div -mrelax-immediates @gol
-mno-relax-immediates -mwide-bitfields -mno-wide-bitfields @gol
-m4byte-functions -mno-4byte-functions -mcallgraph-data @gol
-mno-callgraph-data -mslow-bytes -mno-slow-bytes -mno-lsim @gol
-mlittle-endian -mbig-endian -m210 -m340 -mstack-increment}
@emph{MMIX Options}
-@gccoptlist{
--mlibfuncs -mno-libfuncs -mepsilon -mno-epsilon -mabi=gnu @gol
--mabi=mmixware -mzero-extend -mknuthdiv -mtoplevel-symbols @gol
--melf -mbranch-predict -mno-branch-predict -mbase-addresses @gol
--mno-base-addresses}
+@gccoptlist{-mlibfuncs -mno-libfuncs -mepsilon -mno-epsilon -mabi=gnu @gol
+-mabi=mmixware -mzero-extend -mknuthdiv -mtoplevel-symbols @gol
+-melf -mbranch-predict -mno-branch-predict -mbase-addresses @gol
+-mno-base-addresses -msingle-exit -mno-single-exit}
@emph{IA-64 Options}
-@gccoptlist{
--mbig-endian -mlittle-endian -mgnu-as -mgnu-ld -mno-pic @gol
+@gccoptlist{-mbig-endian -mlittle-endian -mgnu-as -mgnu-ld -mno-pic @gol
-mvolatile-asm-stop -mb-step -mregister-names -mno-sdata @gol
--mconstant-gp -mauto-pic -minline-divide-min-latency @gol
--minline-divide-max-throughput -mno-dwarf2-asm @gol
+-mconstant-gp -mauto-pic -minline-float-divide-min-latency @gol
+-minline-float-divide-max-throughput @gol
+-minline-int-divide-min-latency @gol
+-minline-int-divide-max-throughput -mno-dwarf2-asm @gol
-mfixed-range=@var{register-range}}
@emph{D30V Options}
-@gccoptlist{
--mextmem -mextmemory -monchip -mno-asm-optimize @gol
--masm-optimize -mbranch-cost=@var{n} -mcond-exec=@var{n}}
+@gccoptlist{-mextmem -mextmemory -monchip -mno-asm-optimize @gol
+-masm-optimize -mbranch-cost=@var{n} -mcond-exec=@var{n}}
@emph{S/390 and zSeries Options}
-@gccoptlist{
--mhard-float -msoft-float -mbackchain -mno-backchain @gol
--msmall-exec -mno-small-exec -mmvcle -mno-mvcle @gol
--m64 -m31 -mdebug -mno-debug}
+@gccoptlist{-mhard-float -msoft-float -mbackchain -mno-backchain @gol
+-msmall-exec -mno-small-exec -mmvcle -mno-mvcle @gol
+-m64 -m31 -mdebug -mno-debug}
@emph{CRIS Options}
-@gccoptlist{
--mcpu=@var{cpu} -march=@var{cpu} -mtune=@var{cpu} @gol
--mmax-stack-frame=@var{n} -melinux-stacksize=@var{n} @gol
--metrax4 -metrax100 -mpdebug -mcc-init -mno-side-effects @gol
--mstack-align -mdata-align -mconst-align @gol
--m32-bit -m16-bit -m8-bit -mno-prologue-epilogue -mno-gotplt @gol
--melf -maout -melinux -mlinux -sim -sim2}
+@gccoptlist{-mcpu=@var{cpu} -march=@var{cpu} -mtune=@var{cpu} @gol
+-mmax-stack-frame=@var{n} -melinux-stacksize=@var{n} @gol
+-metrax4 -metrax100 -mpdebug -mcc-init -mno-side-effects @gol
+-mstack-align -mdata-align -mconst-align @gol
+-m32-bit -m16-bit -m8-bit -mno-prologue-epilogue -mno-gotplt @gol
+-melf -maout -melinux -mlinux -sim -sim2}
@emph{PDP-11 Options}
-@gccoptlist{
--mfpu -msoft-float -mac0 -mno-ac0 -m40 -m45 -m10 @gol
+@gccoptlist{-mfpu -msoft-float -mac0 -mno-ac0 -m40 -m45 -m10 @gol
-mbcopy -mbcopy-builtin -mint32 -mno-int16 @gol
-mint16 -mno-int32 -mfloat32 -mno-float64 @gol
-mfloat64 -mno-float32 -mabshi -mno-abshi @gol
@@ -644,44 +614,57 @@ in the following sections.
-msplit -mno-split -munix-asm -mdec-asm}
@emph{Xstormy16 Options}
-@gccoptlist{
--msim}
+@gccoptlist{-msim}
@emph{Xtensa Options}
-@gccoptlist{
--mbig-endian -mlittle-endian @gol
--mdensity -mno-density @gol
--mmac16 -mno-mac16 @gol
--mmul16 -mno-mul16 @gol
--mmul32 -mno-mul32 @gol
--mnsa -mno-nsa @gol
--mminmax -mno-minmax @gol
--msext -mno-sext @gol
--mbooleans -mno-booleans @gol
--mhard-float -msoft-float @gol
--mfused-madd -mno-fused-madd @gol
--mserialize-volatile -mno-serialize-volatile @gol
--mtext-section-literals -mno-text-section-literals @gol
--mtarget-align -mno-target-align @gol
--mlongcalls -mno-longcalls}
+@gccoptlist{-mbig-endian -mlittle-endian @gol
+-mdensity -mno-density @gol
+-mmac16 -mno-mac16 @gol
+-mmul16 -mno-mul16 @gol
+-mmul32 -mno-mul32 @gol
+-mnsa -mno-nsa @gol
+-mminmax -mno-minmax @gol
+-msext -mno-sext @gol
+-mbooleans -mno-booleans @gol
+-mhard-float -msoft-float @gol
+-mfused-madd -mno-fused-madd @gol
+-mserialize-volatile -mno-serialize-volatile @gol
+-mtext-section-literals -mno-text-section-literals @gol
+-mtarget-align -mno-target-align @gol
+-mlongcalls -mno-longcalls}
+
+@emph{FRV Options}
+@gccoptlist{-mgpr-32 -mgpr-64 -mfpr-32 -mfpr-64 @gol
+-mhard-float -msoft-float -malloc-cc -mfixed-cc @gol
+-mdword -mno-dword -mdouble -mno-double @gol
+-mmedia -mno-media -mmuladd -mno-muladd -mlibrary-pic @gol
+-macc-4 -macc-8 -mpack -mno-pack -mno-eflags @gol
+-mcond-move -mno-cond-move -mscc -mno-scc @gol
+-mcond-exec -mno-cond-exec -mvliw-branch -mno-vliw-branch @gol
+-mmulti-cond-exec -mno-multi-cond-exec -mnested-cond-exec @gol
+-mno-nested-cond-exec -mtomcat-stats @gol
+-mcpu=@var{cpu}}
+
+
@item Code Generation Options
@xref{Code Gen Options,,Options for Code Generation Conventions}.
-@gccoptlist{
--fcall-saved-@var{reg} -fcall-used-@var{reg} @gol
--ffixed-@var{reg} -fexceptions @gol
+@gccoptlist{-fcall-saved-@var{reg} -fcall-used-@var{reg} @gol
+-ffixed-@var{reg} -fexceptions @gol
-fnon-call-exceptions -funwind-tables @gol
-fasynchronous-unwind-tables @gol
-finhibit-size-directive -finstrument-functions @gol
-fno-common -fno-ident -fno-gnu-linker @gol
-fpcc-struct-return -fpic -fPIC @gol
-freg-struct-return -fshared-data -fshort-enums @gol
--fshort-double -fshort-wchar -fvolatile @gol
+-fshort-double -fshort-wchar -fvolatile @gol
-fvolatile-global -fvolatile-static @gol
-fverbose-asm -fpack-struct -fstack-check @gol
-fstack-limit-register=@var{reg} -fstack-limit-symbol=@var{sym} @gol
-fargument-alias -fargument-noalias @gol
--fargument-noalias-global -fleading-underscore}
+-fargument-noalias-global -fleading-underscore @gol
+-ftls-model=@var{model} @gol
+-ftrapv -fbounds-check}
@end table
@menu
@@ -818,6 +801,7 @@ assembler assembler-with-cpp
ada
f77 f77-cpp-input ratfor
java
+treelang
@end example
@item -x none
@@ -974,11 +958,11 @@ from C, such as C++ and Objective-C) that the compiler accepts:
@cindex ISO support
@item -ansi
@opindex ansi
-In C mode, support all ISO C89 programs. In C++ mode,
+In C mode, support all ISO C90 programs. In C++ mode,
remove GNU extensions that conflict with ISO C++.
This turns off certain features of GCC that are incompatible with ISO
-C89 (when compiling C code), or of standard C++ (when compiling C++ code),
+C90 (when compiling C code), or of standard C++ (when compiling C++ code),
such as the @code{asm} and @code{typeof} keywords, and
predefined macros such as @code{unix} and @code{vax} that identify the
type of system you are using. It also enables the undesirable and
@@ -1013,33 +997,39 @@ affected.
@item -std=
@opindex std
Determine the language standard. This option is currently only
-supported when compiling C@. A value for this option must be provided;
-possible values are
+supported when compiling C or C++. A value for this option must be
+provided; possible values are
@table @samp
@item c89
@itemx iso9899:1990
-ISO C89 (same as @option{-ansi}).
+ISO C90 (same as @option{-ansi}).
@item iso9899:199409
-ISO C89 as modified in amendment 1.
+ISO C90 as modified in amendment 1.
@item c99
@itemx c9x
@itemx iso9899:1999
@itemx iso9899:199x
ISO C99. Note that this standard is not yet fully supported; see
-@w{@uref{http://gcc.gnu.org/gcc-3.1/c99status.html}} for more information. The
+@w{@uref{http://gcc.gnu.org/gcc-3.3/c99status.html}} for more information. The
names @samp{c9x} and @samp{iso9899:199x} are deprecated.
@item gnu89
-Default, ISO C89 plus GNU extensions (including some C99 features).
+Default, ISO C90 plus GNU extensions (including some C99 features).
@item gnu99
@item gnu9x
ISO C99 plus GNU extensions. When ISO C99 is fully implemented in GCC,
this will become the default. The name @samp{gnu9x} is deprecated.
+@item c++98
+The 1998 ISO C++ standard plus amendments.
+
+@item gnu++98
+The same as @option{-std=c++98} plus GNU extensions. This is the
+default for C++ code.
@end table
Even when this option is not specified, you can still use some of the
@@ -1048,7 +1038,7 @@ previous C standards. For example, you may use @code{__restrict__} even
when @option{-std=c99} is not specified.
The @option{-std} options specifying some version of ISO C have the same
-effects as @option{-ansi}, except that features that were not in ISO C89
+effects as @option{-ansi}, except that features that were not in ISO C90
but are in the specified version (for example, @samp{//} comments and
the @code{inline} keyword in ISO C99) are not disabled.
@@ -1086,7 +1076,7 @@ switch only affects the @code{asm} and @code{typeof} keywords, since
@code{inline} is a standard keyword in ISO C99.
@item -fno-builtin
-@itemx -fno-builtin-@var{function} @r{(C and Objective-C only)}
+@itemx -fno-builtin-@var{function}
@opindex fno-builtin
@cindex built-in functions
Don't recognize built-in functions that do not begin with
@@ -1104,15 +1094,8 @@ and faster, but since the function calls no longer appear as such, you
cannot set a breakpoint on those calls, nor can you change the behavior
of the functions by linking with a different library.
-In C++, @option{-fno-builtin} is always in effect. The @option{-fbuiltin}
-option has no effect. Therefore, in C++, the only way to get the
-optimization benefits of built-in functions is to call the function
-using the @samp{__builtin_} prefix. The GNU C++ Standard Library uses
-built-in functions to implement many functions (like
-@code{std::strchr}), so that you automatically get efficient code.
-
-With the @option{-fno-builtin-@var{function}} option, not available
-when compiling C++, only the built-in function @var{function} is
+With the @option{-fno-builtin-@var{function}} option
+only the built-in function @var{function} is
disabled. @var{function} must not begin with @samp{__builtin_}. If a
function is named this is not built-in in this version of GCC, this
option is ignored. There is no corresponding
@@ -1148,6 +1131,10 @@ This is equivalent to @option{-fno-hosted}.
@xref{Standards,,Language Standards Supported by GCC}, for details of
freestanding and hosted environments.
+@item -fms-extensions
+@opindex fms-extensions
+Accept some non-standard constructs used in Microsoft header files.
+
@item -trigraphs
@opindex trigraphs
Support ISO C trigraphs. The @option{-ansi} option (and @option{-std}
@@ -1155,86 +1142,25 @@ options for strict ISO C conformance) implies @option{-trigraphs}.
@item -no-integrated-cpp
@opindex no-integrated-cpp
-Invoke the external cpp during compilation. The default is to use the
-integrated cpp (internal cpp). This option also allows a
-user-supplied cpp via the @option{-B} option. This flag is applicable
-in both C and C++ modes.
+Performs a compilation in two passes: preprocessing and compiling. This
+option allows a user supplied "cc1", "cc1plus", or "cc1obj" via the
+@option{-B} option. The user supplied compilation step can then add in
+an additional preprocessing step after normal preprocessing but before
+compiling. The default is to use the integrated cpp (internal cpp)
-We do not guarantee to retain this option in future, and we may change
-its semantics.
+The semantics of this option will change if "cc1", "cc1plus", and
+"cc1obj" are merged.
@cindex traditional C language
@cindex C language, traditional
@item -traditional
-@opindex traditional
-Attempt to support some aspects of traditional C compilers.
-Specifically:
-
-@itemize @bullet
-@item
-All @code{extern} declarations take effect globally even if they
-are written inside of a function definition. This includes implicit
-declarations of functions.
-
-@item
-The newer keywords @code{typeof}, @code{inline}, @code{signed}, @code{const}
-and @code{volatile} are not recognized. (You can still use the
-alternative keywords such as @code{__typeof__}, @code{__inline__}, and
-so on.)
-
-@item
-Comparisons between pointers and integers are always allowed.
-
-@item
-Integer types @code{unsigned short} and @code{unsigned char} promote
-to @code{unsigned int}.
-
-@item
-Out-of-range floating point literals are not an error.
-
-@item
-Certain constructs which ISO regards as a single invalid preprocessing
-number, such as @samp{0xe-0xd}, are treated as expressions instead.
-
-@item
-String ``constants'' are not necessarily constant; they are stored in
-writable space, and identical looking constants are allocated
-separately. (This is the same as the effect of
-@option{-fwritable-strings}.)
-
-@cindex @code{longjmp} and automatic variables
-@item
-All automatic variables not declared @code{register} are preserved by
-@code{longjmp}. Ordinarily, GNU C follows ISO C: automatic variables
-not declared @code{volatile} may be clobbered.
-
-@item
-@cindex @samp{\x}
-@cindex @samp{\a}
-@cindex escape sequences, traditional
-The character escape sequences @samp{\x} and @samp{\a} evaluate as the
-literal characters @samp{x} and @samp{a} respectively. Without
-@w{@option{-traditional}}, @samp{\x} is a prefix for the hexadecimal
-representation of a character, and @samp{\a} produces a bell.
-@end itemize
-
-This option is deprecated and may be removed.
-
-You may wish to use @option{-fno-builtin} as well as @option{-traditional}
-if your program uses names that are normally GNU C built-in functions for
-other purposes of its own.
-
-You cannot use @option{-traditional} if you include any header files that
-rely on ISO C features. Some vendors are starting to ship systems with
-ISO C header files and you cannot use @option{-traditional} on such
-systems to compile files that include any system headers.
-
-The @option{-traditional} option also enables @option{-traditional-cpp}.
-
-@item -traditional-cpp
+@itemx -traditional-cpp
@opindex traditional-cpp
-Attempt to support some aspects of traditional C preprocessors.
-See the GNU CPP manual for details.
+@opindex traditional
+Formerly, these options caused GCC to attempt to emulate a pre-standard
+C compiler. They are now only supported with the @option{-E} switch.
+The preprocessor continues to support a pre-standard mode. See the GNU
+CPP manual for details.
@item -fcond-mismatch
@opindex fcond-mismatch
@@ -1282,31 +1208,14 @@ declaration does not use either @code{signed} or @code{unsigned}. By
default, such a bit-field is signed, because this is consistent: the
basic integer types such as @code{int} are signed types.
-However, when @option{-traditional} is used, bit-fields are all unsigned
-no matter what.
-
@item -fwritable-strings
@opindex fwritable-strings
Store string constants in the writable data segment and don't uniquize
them. This is for compatibility with old programs which assume they can
-write into string constants. The option @option{-traditional} also has
-this effect.
+write into string constants.
Writing into string constants is a very bad idea; ``constants'' should
be constant.
-
-@item -fallow-single-precision
-@opindex fallow-single-precision
-Do not promote single precision math operations to double precision,
-even when compiling with @option{-traditional}.
-
-Traditional K&R C promotes all floating point operations to double
-precision, regardless of the sizes of the operands. On the
-architecture for which you are compiling, single precision may be faster
-than double precision. If you must use @option{-traditional}, but want
-to use single precision operations when the operands are single
-precision, use this option. This option has no effect when compiling
-with ISO or GNU C conventions (the default).
@end table
@node C++ Dialect Options
@@ -1332,6 +1241,17 @@ language supported by GCC@.
Here is a list of options that are @emph{only} for compiling C++ programs:
@table @gcctabopt
+
+@item -fabi-version=@var{n}
+@opindex fabi-version
+Use version @var{n} of the C++ ABI. Version 1 is the version of the C++
+ABI that first appeared in G++ 3.2. Version 0 will always be the
+version that conforms most closely to the C++ ABI specification.
+Therefore, the ABI obtained using version 0 will change as ABI bugs are
+fixed.
+
+The default is version 1.
+
@item -fno-access-control
@opindex fno-access-control
Turn off all access checking. This switch is mainly useful for working
@@ -1340,14 +1260,14 @@ around bugs in the access control code.
@item -fcheck-new
@opindex fcheck-new
Check that the pointer returned by @code{operator new} is non-null
-before attempting to modify the storage allocated. The current Working
-Paper requires that @code{operator new} never return a null pointer, so
-this check is normally unnecessary.
-
-An alternative to using this option is to specify that your
-@code{operator new} does not throw any exceptions; if you declare it
-@samp{throw()}, G++ will check the return value. See also @samp{new
-(nothrow)}.
+before attempting to modify the storage allocated. This check is
+normally unnecessary because the C++ standard specifies that
+@code{operator new} will only return @code{0} if it is declared
+@samp{throw()}, in which case the compiler will always check the
+return value even without this option. In all other cases, when
+@code{operator new} has a non-empty exception specification, memory
+exhaustion is signalled by throwing @code{std::bad_alloc}. See also
+@samp{new (nothrow)}.
@item -fconserve-space
@opindex fconserve-space
@@ -1478,10 +1398,9 @@ a name having multiple meanings within a class.
@item -fpermissive
@opindex fpermissive
-Downgrade messages about nonconformant code from errors to warnings. By
-default, G++ effectively sets @option{-pedantic-errors} without
-@option{-pedantic}; this option reverses that. This behavior and this
-option are superseded by @option{-pedantic}, which works as it does for GNU C@.
+Downgrade some diagnostics about nonconformant code from errors to
+warnings. Thus, using @option{-fpermissive} will allow some
+nonconforming code to compile.
@item -frepo
@opindex frepo
@@ -1568,7 +1487,7 @@ You should rewrite your code to avoid these warnings if you are
concerned about the fact that code generated by G++ may not be binary
compatible with code generated by other compilers.
-The known incompatibilites at this point include:
+The known incompatibilities at this point include:
@itemize @bullet
@@ -1605,18 +1524,66 @@ explicitly padding @code{A} so that its size is a multiple of its
alignment (ignoring virtual base classes); that will cause G++ and other
compilers to layout @code{C} identically.
+@item
+Incorrect handling of bit-fields with declared widths greater than that
+of their underlying types, when the bit-fields appear in a union. For
+example:
+
+@smallexample
+union U @{ int i : 4096; @};
+@end smallexample
+
+@noindent
+Assuming that an @code{int} does not have 4096 bits, G++ will make the
+union too small by the number of bits in an @code{int}.
+
+@item
+Empty classes can be placed at incorrect offsets. For example:
+
+@smallexample
+struct A @{@};
+
+struct B @{
+ A a;
+ virtual void f ();
+@};
+
+struct C : public B, public A @{@};
+@end smallexample
+
+@noindent
+G++ will place the @code{A} base class of @code{C} at a nonzero offset;
+it should be placed at offset zero. G++ mistakenly believes that the
+@code{A} data member of @code{B} is already at offset zero.
+
+@item
+Names of template functions whose types involve @code{typename} or
+template template parameters can be mangled incorrectly.
+
+@smallexample
+template <typename Q>
+void f(typename Q::X) @{@}
+
+template <template <typename> class Q>
+void f(typename Q<int>::X) @{@}
+@end smallexample
+
+@noindent
+Instantiations of these templates may be mangled incorrectly.
+
@end itemize
@item -Wctor-dtor-privacy @r{(C++ only)}
@opindex Wctor-dtor-privacy
Warn when a class seems unusable, because all the constructors or
destructors in a class are private and the class has no friends or
-public static member functions.
+public static member functions. This warning is enabled by default.
@item -Wnon-virtual-dtor @r{(C++ only)}
@opindex Wnon-virtual-dtor
Warn when a class declares a non-virtual destructor that should probably
be virtual, because it looks like the class will be used polymorphically.
+This warning is enabled by @option{-Wall}.
@item -Wreorder @r{(C++ only)}
@opindex Wreorder
@@ -1635,7 +1602,7 @@ struct A @{
Here the compiler will warn that the member initializers for @samp{i}
and @samp{j} will be rearranged to match the declaration order of the
-members.
+members. This warning is enabled by @option{-Wall}.
@end table
The following @option{-W@dots{}} options are not affected by @option{-Wall}.
@@ -1810,7 +1777,9 @@ runtime. This is the default for most types of systems.
@item -fnext-runtime
@opindex fnext-runtime
Generate output compatible with the NeXT runtime. This is the default
-for NeXT-based systems, including Darwin and Mac OS X@.
+for NeXT-based systems, including Darwin and Mac OS X@. The macro
+@code{__NEXT_RUNTIME__} is predefined if (and only if) this option is
+used.
@item -gen-decls
@opindex gen-decls
@@ -1819,12 +1788,39 @@ file named @file{@var{sourcename}.decl}.
@item -Wno-protocol
@opindex Wno-protocol
-Do not warn if methods required by a protocol are not implemented
-in the class adopting it.
+If a class is declared to implement a protocol, a warning is issued for
+every method in the protocol that is not implemented by the class. The
+default behavior is to issue a warning for every method not explicitly
+implemented in the class, even if a method implementation is inherited
+from the superclass. If you use the @code{-Wno-protocol} option, then
+methods inherited from the superclass are considered to be implemented,
+and no warning is issued for them.
@item -Wselector
@opindex Wselector
-Warn if a selector has multiple methods of different types defined.
+Warn if multiple methods of different types for the same selector are
+found during compilation. The check is performed on the list of methods
+in the final stage of compilation. Additionally, a check is performed
+that for each selector appearing in a @code{@@selector(@dots{})}
+expression, a corresponding method with that selector has been found
+during compilation. Because these checks scan the method table only at
+the end of compilation, these warnings are not produced if the final
+stage of compilation is not reached, for example because an error is
+found during compilation, or because the @code{-fsyntax-only} option is
+being used.
+
+@item -Wundeclared-selector
+@opindex Wundeclared-selector
+Warn if a @code{@@selector(@dots{})} expression referring to an
+undeclared selector is found. A selector is considered undeclared if no
+method with that name has been declared (explicitly, in an
+@code{@@interface} or @code{@@protocol} declaration, or implicitly, in
+an @code{@@implementation} section) before the
+@code{@@selector(@dots{})} expression. This option always performs its
+checks as soon as a @code{@@selector(@dots{})} expression is found
+(while @code{-Wselector} only performs its checks in the final stage of
+compilation), and so additionally enforces the coding style convention
+that methods and selectors must be declared before being used.
@c not documented because only avail via -Wp
@c @item -print-objc-runtime-info
@@ -1975,7 +1971,7 @@ attributes (@pxref{Function Attributes}), in the @code{printf},
not in the C standard) families.
The formats are checked against the format features supported by GNU
-libc version 2.2. These include all ISO C89 and C99 features, as well
+libc version 2.2. These include all ISO C90 and C99 features, as well
as features from the Single Unix Specification and some BSD and GNU
extensions. Other library implementations may not support all these
features; GCC does not support warning about features that go beyond a
@@ -1985,11 +1981,14 @@ in the selected standard version (but not for @code{strfmon} formats,
since those are not in any version of the C standard). @xref{C Dialect
Options,,Options Controlling C Dialect}.
+Since @option{-Wformat} also checks for null format arguments for
+several functions, @option{-Wformat} also implies @option{-Wnonnull}.
+
@option{-Wformat} is included in @option{-Wall}. For more control over some
aspects of format checking, the options @option{-Wno-format-y2k},
-@option{-Wno-format-extra-args}, @option{-Wformat-nonliteral},
-@option{-Wformat-security} and @option{-Wformat=2} are available, but are
-not included in @option{-Wall}.
+@option{-Wno-format-extra-args}, @option{-Wno-format-zero-length},
+@option{-Wformat-nonliteral}, @option{-Wformat-security}, and
+@option{-Wformat=2} are available, but are not included in @option{-Wall}.
@item -Wno-format-y2k
@opindex Wno-format-y2k
@@ -2010,6 +2009,11 @@ in the case of @code{scanf} formats, this option will suppress the
warning if the unused arguments are all pointers, since the Single
Unix Specification says that such unused arguments are allowed.
+@item -Wno-format-zero-length
+@opindex Wno-format-zero-length
+If @option{-Wformat} is specified, do not warn about zero-length formats.
+The C standard specifies that zero-length formats are allowed.
+
@item -Wformat-nonliteral
@opindex Wformat-nonliteral
If @option{-Wformat} is specified, also warn if the format string is not a
@@ -2034,6 +2038,14 @@ Enable @option{-Wformat} plus format checks not included in
@option{-Wformat}. Currently equivalent to @samp{-Wformat
-Wformat-nonliteral -Wformat-security}.
+@item -Wnonnull
+@opindex Wnonnull
+Enable warning about passing a null pointer for arguments marked as
+requiring a non-null value by the @code{nonnull} function attribute.
+
+@option{-Wnonnull} is included in @option{-Wall} and @option{-Wformat}. It
+can be disabled with the @option{-Wno-nonnull} option.
+
@item -Wimplicit-int
@opindex Wimplicit-int
Warn when a declaration does not specify a type.
@@ -2176,6 +2188,18 @@ enumeration. (The presence of a @code{default} label prevents this
warning.) @code{case} labels outside the enumeration range also
provoke warnings when this option is used.
+@item -Wswitch-default
+@opindex Wswitch-switch
+Warn whenever a @code{switch} statement does not have a @code{default}
+case.
+
+@item -Wswitch-enum
+@opindex Wswitch-enum
+Warn whenever a @code{switch} statement has an index of enumeral type
+and lacks a @code{case} for one or more of the named codes of that
+enumeration. @code{case} labels outside the enumeration range also
+provoke warnings when this option is used.
+
@item -Wtrigraphs
@opindex Wtrigraphs
Warn if any trigraphs are encountered that might change the meaning of
@@ -2216,7 +2240,7 @@ To suppress this warning cast the expression to @samp{void}.
@item -Wunused
@opindex Wunused
-All all the above @option{-Wunused} options combined.
+All the above @option{-Wunused} options combined.
In order to get a warning about an unused function parameter, you must
either specify @samp{-W -Wunused} or separately specify
@@ -2297,13 +2321,6 @@ Some spurious warnings can be avoided if you declare all the functions
you use that never return as @code{noreturn}. @xref{Function
Attributes}.
-@item -Wreorder @r{(C++ only)}
-@opindex Wreorder
-@cindex reordering, warning
-@cindex warning for reordering of member initializers
-Warn when the order of member initializers given in the code does not
-match the order in which they must be executed. For instance:
-
@item -Wunknown-pragmas
@opindex Wunknown-pragmas
@cindex warning for unknown pragmas
@@ -2314,41 +2331,22 @@ GCC@. If this command line option is used, warnings will even be issued
for unknown pragmas in system header files. This is not the case if
the warnings were only enabled by the @option{-Wall} command line option.
+@item -Wstrict-aliasing
+@opindex Wstrict-aliasing
+This option is only active when @option{-fstrict-aliasing} is active.
+It warns about code which might break the strict aliasing rules that the
+compiler is using for optimization. The warning does not catch all
+cases, but does attempt to catch the more common pitfalls. It is
+included in @option{-Wall}.
+
@item -Wall
@opindex Wall
All of the above @samp{-W} options combined. This enables all the
warnings about constructions that some users consider questionable, and
that are easy to avoid (or modify to prevent the warning), even in
-conjunction with macros.
-
-@item -Wdiv-by-zero
-@opindex Wno-div-by-zero
-@opindex Wdiv-by-zero
-Warn about compile-time integer division by zero. This is default. To
-inhibit the warning messages, use @option{-Wno-div-by-zero}. Floating
-point division by zero is not warned about, as it can be a legitimate
-way of obtaining infinities and NaNs.
-
-@item -Wmultichar
-@opindex Wno-multichar
-@opindex Wmultichar
-Warn if a multicharacter constant (@samp{'FOOF'}) is used. This is
-default. To inhibit the warning messages, use @option{-Wno-multichar}.
-Usually they indicate a typo in the user's code, as they have
-implementation-defined values, and should not be used in portable code.
-
-@item -Wsystem-headers
-@opindex Wsystem-headers
-@cindex warnings from system headers
-@cindex system headers, warnings from
-Print warning messages for constructs found in system header files.
-Warnings from system headers are normally suppressed, on the assumption
-that they usually do not indicate real problems and would only make the
-compiler output harder to read. Using this command line option tells
-GCC to emit warnings from system headers as if they occurred in user
-code. However, note that using @option{-Wall} in conjunction with this
-option will @emph{not} warn about unknown pragmas in system
-headers---for that, @option{-Wunknown-pragmas} must also be used.
+conjunction with macros. This also enables some language-specific
+warnings described in @ref{C++ Dialect Options} and
+@ref{Objective-C Dialect Options}.
@end table
The following @option{-W@dots{}} options are not implied by @option{-Wall}.
@@ -2437,6 +2435,26 @@ struct s x = @{ 3, 4 @};
@end smallexample
@end itemize
+@item -Wno-div-by-zero
+@opindex Wno-div-by-zero
+@opindex Wdiv-by-zero
+Do not warn about compile-time integer division by zero. Floating point
+division by zero is not warned about, as it can be a legitimate way of
+obtaining infinities and NaNs.
+
+@item -Wsystem-headers
+@opindex Wsystem-headers
+@cindex warnings from system headers
+@cindex system headers, warnings from
+Print warning messages for constructs found in system header files.
+Warnings from system headers are normally suppressed, on the assumption
+that they usually do not indicate real problems and would only make the
+compiler output harder to read. Using this command line option tells
+GCC to emit warnings from system headers as if they occurred in user
+code. However, note that using @option{-Wall} in conjunction with this
+option will @emph{not} warn about unknown pragmas in system
+headers---for that, @option{-Wunknown-pragmas} must also be used.
+
@item -Wfloat-equal
@opindex Wfloat-equal
Warn if floating point values are used in equality comparisons.
@@ -2444,7 +2462,7 @@ Warn if floating point values are used in equality comparisons.
The idea behind this is that sometimes it is convenient (for the
programmer) to consider floating-point values as approximations to
infinitely precise real numbers. If you are doing this, then you need
-to compute (by analysing the code, or in some other way) the maximum or
+to compute (by analyzing the code, or in some other way) the maximum or
likely maximum error that the computation introduces, and allow for it
when performing comparisons (and when producing output, but that's a
different problem). In particular, instead of testing for equality, you
@@ -2529,12 +2547,25 @@ Conversions by prototypes between fixed/floating point values and vice
versa. The absence of these prototypes when compiling with traditional
C would cause serious problems. This is a subset of the possible
conversion warnings, for the full set use @option{-Wconversion}.
+
+@item
+Use of ISO C style function definitions. This warning intentionally is
+@emph{not} issued for prototype declarations or variadic functions
+because these ISO C features will appear in your code when using
+libiberty's traditional C compatibility macros, @code{PARAMS} and
+@code{VPARAMS}. This warning is also bypassed for nested functions
+because that feature is already a gcc extension and thus not relevant to
+traditional C compatibility.
@end itemize
@item -Wundef
@opindex Wundef
Warn if an undefined identifier is evaluated in an @samp{#if} directive.
+@item -Wendif-labels
+@opindex Wendif-labels
+Warn whenever an @samp{#else} or an @samp{#endif} are followed by text.
+
@item -Wshadow
@opindex Wshadow
Warn whenever a local variable shadows another local variable, parameter or
@@ -2602,8 +2633,8 @@ casts like @code{(unsigned) -1}.
@cindex signed and unsigned values, comparison warning
Warn when a comparison between signed and unsigned values could produce
an incorrect result when the signed value is converted to unsigned.
-This warning is also enabled by @option{-W}; to get the other warnings
-of @option{-W} without this warning, use @samp{-W -Wno-sign-compare}.
+This warning is enabled by @option{-W}, and by @option{-Wall}
+in C++ only.
@item -Waggregate-return
@opindex Waggregate-return
@@ -2625,7 +2656,7 @@ declaration. This warning is issued even if the definition itself
provides a prototype. The aim is to detect global functions that fail
to be declared in header files.
-@item -Wmissing-declarations
+@item -Wmissing-declarations @r{(C only)}
@opindex Wmissing-declarations
Warn if a global function is defined without a previous declaration.
Do so even if the definition itself provides a prototype.
@@ -2653,6 +2684,13 @@ case, and some functions for which @code{format} attributes are
appropriate may not be detected. This option has no effect unless
@option{-Wformat} is enabled (possibly by @option{-Wall}).
+@item -Wno-multichar
+@opindex Wno-multichar
+@opindex Wmultichar
+Do not warn if a multicharacter constant (@samp{'FOOF'}) is used.
+Usually they indicate a typo in the user's code, as they have
+implementation-defined values, and should not be used in portable code.
+
@item -Wno-deprecated-declarations
@opindex Wno-deprecated-declarations
Do not warn about uses of functions, variables, and types marked as
@@ -2723,6 +2761,15 @@ code is to provide behavior which is selectable at compile-time.
@item -Winline
@opindex Winline
Warn if a function can not be inlined and it was declared as inline.
+Even with this option, the compiler will not warn about failures to
+inline functions declared in system headers.
+
+The compiler uses a variety of heuristics to determine whether or not
+to inline a function. For example, the compiler takes into account
+the size of the function being inlined and the the amount of inlining
+that has already been done in the current function. Therefore,
+seemingly insignificant changes in the source program can cause the
+warnings produced by @option{-Winline} to appear or disappear.
@item -Wlong-long
@opindex Wlong-long
@@ -2831,6 +2878,8 @@ Produce debugging information in DWARF version 1 format (if that is
supported). This is the format used by SDB on most System V Release 4
systems.
+This option is deprecated.
+
@item -gdwarf+
@opindex gdwarf+
Produce debugging information in DWARF version 1 format (if that is
@@ -2838,6 +2887,8 @@ supported), using GNU extensions understood only by the GNU debugger
(GDB)@. The use of these extensions is likely to make other debuggers
crash or refuse to read the program.
+This option is deprecated.
+
@item -gdwarf-2
@opindex gdwarf-2
Produce debugging information in DWARF version 2 format (if that is
@@ -2871,19 +2922,25 @@ and DWARF2, neither @option{-gdwarf} nor @option{-gdwarf-2} accept
a concatenated debug level. Instead use an additional @option{-g@var{level}}
option to change the debug level for DWARF1 or DWARF2.
-@cindex @code{prof}
+@item -feliminate-dwarf2-dups
+@opindex feliminate-dwarf2-dups
+Compress DWARF2 debugging information by eliminating duplicated
+information about each symbol. This option only makes sense when
+generating DWARF2 debugging information with @option{-gdwarf-2}.
+
+@cindex @command{prof}
@item -p
@opindex p
Generate extra code to write profile information suitable for the
-analysis program @code{prof}. You must use this option when compiling
+analysis program @command{prof}. You must use this option when compiling
the source files you want data about, and you must also use it when
linking.
-@cindex @code{gprof}
+@cindex @command{gprof}
@item -pg
@opindex pg
Generate extra code to write profile information suitable for the
-analysis program @code{gprof}. You must use this option when compiling
+analysis program @command{gprof}. You must use this option when compiling
the source files you want data about, and you must also use it when
linking.
@@ -2904,11 +2961,16 @@ allocation when it finishes.
@item -fprofile-arcs
@opindex fprofile-arcs
-Instrument @dfn{arcs} during compilation to generate coverage data
-or for profile-directed block ordering. During execution the program
+Instrument @dfn{arcs} during compilation to generate coverage data or
+for profile-directed block ordering. During execution the program
records how many times each branch is executed and how many times it is
taken. When the compiled program exits it saves this data to a file
-called @file{@var{sourcename}.da} for each source file.
+called @file{@var{auxname}.da} for each source file. @var{auxname} is
+generated from the name of the output file, if explicitly specified and
+it is not the final executable, otherwise it is the basename of the
+source file. In both cases any suffix is removed (e.g. @file{foo.da}
+for input file @file{dir/foo.c}, or @file{dir/foo.da} for output file
+specified as @option{-o dir/foo.o}).
For profile-directed block ordering, compile the program with
@option{-fprofile-arcs} plus optimization and code generation options,
@@ -2918,7 +2980,7 @@ optimization and code generation options plus
@option{-fbranch-probabilities} (@pxref{Optimize Options,,Options that
Control Optimization}).
-The other use of @option{-fprofile-arcs} is for use with @code{gcov},
+The other use of @option{-fprofile-arcs} is for use with @command{gcov},
when it is used with the @option{-ftest-coverage} option.
With @option{-fprofile-arcs}, for each function of your program GCC
@@ -2933,19 +2995,19 @@ block must be created to hold the instrumentation code.
@item -ftest-coverage
@opindex ftest-coverage
Create data files for the @command{gcov} code-coverage utility
-(@pxref{Gcov,, @command{gcov}---a Test Coverage Program}).
-The data file names begin with the name of your source file:
+(@pxref{Gcov,, @command{gcov}---a Test Coverage Program}). See
+@option{-fprofile-arcs} option above for a description of @var{auxname}.
@table @gcctabopt
-@item @var{sourcename}.bb
-A mapping from basic blocks to line numbers, which @code{gcov} uses to
+@item @var{auxname}.bb
+A mapping from basic blocks to line numbers, which @command{gcov} uses to
associate basic block execution counts with line numbers.
-@item @var{sourcename}.bbg
-A list of all arcs in the program flow graph. This allows @code{gcov}
+@item @var{auxname}.bbg
+A list of all arcs in the program flow graph. This allows @command{gcov}
to reconstruct the program flow graph, so that it can compute all basic
block and arc execution counts from the information in the
-@code{@var{sourcename}.da} file.
+@file{@var{auxname}.da} file.
@end table
Use @option{-ftest-coverage} with @option{-fprofile-arcs}; the latter
@@ -2953,9 +3015,9 @@ option adds instrumentation to the program, which then writes
execution counts to another data file:
@table @gcctabopt
-@item @var{sourcename}.da
+@item @var{auxname}.da
Runtime arc execution counts, used in conjunction with the arc
-information in the file @code{@var{sourcename}.bbg}.
+information in the file @file{@var{auxname}.bbg}.
@end table
Coverage data will map better to the source files if
@@ -2966,8 +3028,12 @@ Coverage data will map better to the source files if
Says to make debugging dumps during compilation at times specified by
@var{letters}. This is used for debugging the compiler. The file names
for most of the dumps are made by appending a pass number and a word to
-the source file name (e.g. @file{foo.c.00.rtl} or @file{foo.c.01.sibling}).
-Here are the possible letters for use in @var{letters}, and their meanings:
+the @var{dumpname}. @var{dumpname} is generated from the name of the
+output file, if explicitly specified and it is not an executable,
+otherwise it is the basename of the source file. In both cases any
+suffix is removed (e.g. @file{foo.00.rtl} or @file{foo.01.sibling}).
+Here are the possible letters for use in @var{letters}, and their
+meanings:
@table @samp
@item A
@@ -2978,16 +3044,16 @@ Annotate the assembler output with miscellaneous debugging information.
Dump after computing branch probabilities, to @file{@var{file}.14.bp}.
@item B
@opindex dB
-Dump after block reordering, to @file{@var{file}.29.bbro}.
+Dump after block reordering, to @file{@var{file}.32.bbro}.
@item c
@opindex dc
-Dump after instruction combination, to the file @file{@var{file}.16.combine}.
+Dump after instruction combination, to the file @file{@var{file}.19.combine}.
@item C
@opindex dC
-Dump after the first if conversion, to the file @file{@var{file}.17.ce}.
+Dump after the first if conversion, to the file @file{@var{file}.15.ce1}.
@item d
@opindex dd
-Dump after delayed branch scheduling, to @file{@var{file}.31.dbr}.
+Dump after delayed branch scheduling, to @file{@var{file}.34.dbr}.
@item D
@opindex dD
Dump all macro definitions, at the end of preprocessing, in addition to
@@ -2998,28 +3064,23 @@ Dump after SSA optimizations, to @file{@var{file}.04.ssa} and
@file{@var{file}.07.ussa}.
@item E
@opindex dE
-Dump after the second if conversion, to @file{@var{file}.26.ce2}.
+Dump after the second if conversion, to @file{@var{file}.29.ce3}.
@item f
@opindex df
-Dump after life analysis, to @file{@var{file}.15.life}.
+Dump after control and data flow analysis, to @file{@var{file}.14.cfg}.
+Also dump after life analysis, to @file{@var{file}.18.life}.
@item F
@opindex dF
-Dump after purging @code{ADDRESSOF} codes, to @file{@var{file}.09.addressof}.
+Dump after purging @code{ADDRESSOF} codes, to @file{@var{file}.10.addressof}.
@item g
@opindex dg
-Dump after global register allocation, to @file{@var{file}.21.greg}.
+Dump after global register allocation, to @file{@var{file}.24.greg}.
+@item G
+@opindex dG
+Dump after GCSE, to @file{@var{file}.11.gcse}.
@item h
@opindex dh
Dump after finalization of EH handling code, to @file{@var{file}.02.eh}.
-@item k
-@opindex dk
-Dump after reg-to-stack conversion, to @file{@var{file}.28.stack}.
-@item o
-@opindex do
-Dump after post-reload optimizations, to @file{@var{file}.22.postreload}.
-@item G
-@opindex dG
-Dump after GCSE, to @file{@var{file}.10.gcse}.
@item i
@opindex di
Dump after sibling call optimizations, to @file{@var{file}.01.sibling}.
@@ -3028,49 +3089,62 @@ Dump after sibling call optimizations, to @file{@var{file}.01.sibling}.
Dump after the first jump optimization, to @file{@var{file}.03.jump}.
@item k
@opindex dk
-Dump after conversion from registers to stack, to @file{@var{file}.32.stack}.
+Dump after conversion from registers to stack, to @file{@var{file}.31.stack}.
@item l
@opindex dl
-Dump after local register allocation, to @file{@var{file}.20.lreg}.
+Dump after local register allocation, to @file{@var{file}.23.lreg}.
@item L
@opindex dL
-Dump after loop optimization, to @file{@var{file}.11.loop}.
+Dump after loop optimization, to @file{@var{file}.12.loop}.
@item M
@opindex dM
-Dump after performing the machine dependent reorganisation pass, to
-@file{@var{file}.30.mach}.
+Dump after performing the machine dependent reorganization pass, to
+@file{@var{file}.33.mach}.
@item n
@opindex dn
-Dump after register renumbering, to @file{@var{file}.25.rnreg}.
+Dump after register renumbering, to @file{@var{file}.28.rnreg}.
@item N
@opindex dN
-Dump after the register move pass, to @file{@var{file}.18.regmove}.
+Dump after the register move pass, to @file{@var{file}.21.regmove}.
+@item o
+@opindex do
+Dump after post-reload optimizations, to @file{@var{file}.25.postreload}.
@item r
@opindex dr
Dump after RTL generation, to @file{@var{file}.00.rtl}.
@item R
@opindex dR
-Dump after the second scheduling pass, to @file{@var{file}.27.sched2}.
+Dump after the second scheduling pass, to @file{@var{file}.30.sched2}.
@item s
@opindex ds
Dump after CSE (including the jump optimization that sometimes follows
-CSE), to @file{@var{file}.08.cse}.
+CSE), to @file{@var{file}.09.cse}.
@item S
@opindex dS
-Dump after the first scheduling pass, to @file{@var{file}.19.sched}.
+Dump after the first scheduling pass, to @file{@var{file}.22.sched}.
@item t
@opindex dt
Dump after the second CSE pass (including the jump optimization that
-sometimes follows CSE), to @file{@var{file}.12.cse2}.
+sometimes follows CSE), to @file{@var{file}.17.cse2}.
+@item T
+@opindex dT
+Dump after running tracer, to @file{@var{file}.16.tracer}.
+@item u
+@opindex du
+Dump after null pointer elimination pass to @file{@var{file}.08.null}.
@item w
@opindex dw
-Dump after the second flow pass, to @file{@var{file}.23.flow2}.
+Dump after the second flow pass, to @file{@var{file}.26.flow2}.
+@item W
+@opindex dW
+Dump after SSA conditional constant propagation, to
+@file{@var{file}.05.ssaccp}.
@item X
@opindex dX
Dump after SSA dead code elimination, to @file{@var{file}.06.ssadce}.
@item z
@opindex dz
-Dump after the peephole pass, to @file{@var{file}.24.peephole2}.
+Dump after the peephole pass, to @file{@var{file}.27.peephole2}.
@item a
@opindex da
Produce all the dumps listed above.
@@ -3160,6 +3234,14 @@ Dump after all tree based optimization, to @file{@var{file}.optimized}.
Dump after function inlining, to @file{@var{file}.inlined}.
@end table
+@item -frandom-seed=@var{string}
+@opindex frandom-string
+This option provides a seed that GCC uses when it would otherwise use
+random numbers. At present, this is used to generate certain symbol names
+that have to be different in every compiled file.
+
+The @var{string} should be different for every file you compile.
+
@item -fsched-verbose=@var{n}
@opindex fsched-verbose
On targets that use instruction scheduling, this option controls the
@@ -3177,14 +3259,6 @@ and unit/insn info. For @var{n} greater than two, it includes RTL
at abort point, control-flow and regions info. And for @var{n} over
four, @option{-fsched-verbose} also includes dependence info.
-@item -fpretend-float
-@opindex fpretend-float
-When running a cross-compiler, pretend that the target machine uses the
-same floating point format as the host machine. This causes incorrect
-output of the actual floating constants, but the actual instruction
-sequence will probably be the same as GCC would make when running on
-the target machine.
-
@item -save-temps
@opindex save-temps
Store the usual ``temporary'' intermediate files permanently; place them
@@ -3280,7 +3354,22 @@ is used when GCC itself is being built.) @xref{Spec Files}.
@cindex optimize options
@cindex options, optimization
-These options control various sorts of optimizations:
+These options control various sorts of optimizations.
+
+Without any optimization option, the compiler's goal is to reduce the
+cost of compilation and to make debugging produce the expected
+results. Statements are independent: if you stop the program with a
+breakpoint between statements, you can then assign a new value to any
+variable or change the program counter to any other statement in the
+function and get exactly the results you would expect from the source
+code.
+
+Turning on optimization flags makes the compiler attempt to improve
+the performance and/or code size at the expense of compilation time
+and possibly the ability to debug the program.
+
+Not all optimizations are controlled directly by a flag. Only
+optimizations that have a flag are listed.
@table @gcctabopt
@item -O
@@ -3290,17 +3379,25 @@ These options control various sorts of optimizations:
Optimize. Optimizing compilation takes somewhat more time, and a lot
more memory for a large function.
-Without @option{-O}, the compiler's goal is to reduce the cost of
-compilation and to make debugging produce the expected results.
-Statements are independent: if you stop the program with a breakpoint
-between statements, you can then assign a new value to any variable or
-change the program counter to any other statement in the function and
-get exactly the results you would expect from the source code.
-
With @option{-O}, the compiler tries to reduce code size and execution
time, without performing any optimizations that take a great deal of
compilation time.
+@option{-O} turns on the following optimization flags:
+@gccoptlist{-fdefer-pop @gol
+-fmerge-constants @gol
+-fthread-jumps @gol
+-floop-optimize @gol
+-fcrossjumping @gol
+-fif-conversion @gol
+-fif-conversion2 @gol
+-fdelayed-branch @gol
+-fguess-branch-probability @gol
+-fcprop-registers}
+
+@option{-O} also turns on @option{-fomit-frame-pointer} on machines
+where doing so does not interfere with debugging.
+
@item -O2
@opindex O2
Optimize even more. GCC performs nearly all supported optimizations
@@ -3309,10 +3406,25 @@ perform loop unrolling or function inlining when you specify @option{-O2}.
As compared to @option{-O}, this option increases both compilation time
and the performance of the generated code.
-@option{-O2} turns on all optional optimizations except for loop unrolling,
-function inlining, and register renaming. It also turns on the
-@option{-fforce-mem} option on all machines and frame pointer elimination
-on machines where doing so does not interfere with debugging.
+@option{-O2} turns on all optimization flags specified by @option{-O}. It
+also turns on the following optimization flags:
+@gccoptlist{-fforce-mem @gol
+-foptimize-sibling-calls @gol
+-fstrength-reduce @gol
+-fcse-follow-jumps -fcse-skip-blocks @gol
+-frerun-cse-after-loop -frerun-loop-opt @gol
+-fgcse -fgcse-lm -fgcse-sm @gol
+-fdelete-null-pointer-checks @gol
+-fexpensive-optimizations @gol
+-fregmove @gol
+-fschedule-insns -fschedule-insns2 @gol
+-fsched-interblock -fsched-spec @gol
+-fcaller-saves @gol
+-fpeephole2 @gol
+-freorder-blocks -freorder-functions @gol
+-fstrict-aliasing @gol
+-falign-functions -falign-jumps @gol
+-falign-loops -falign-labels}
Please note the warning under @option{-fgcse} about
invoking @option{-O2} on programs that use computed gotos.
@@ -3325,7 +3437,7 @@ Optimize yet more. @option{-O3} turns on all optimizations specified by
@item -O0
@opindex O0
-Do not optimize.
+Do not optimize. This is the default.
@item -Os
@opindex Os
@@ -3333,33 +3445,27 @@ Optimize for size. @option{-Os} enables all @option{-O2} optimizations that
do not typically increase code size. It also performs further
optimizations designed to reduce code size.
+@option{-Os} disables the following optimization flags:
+@gccoptlist{-falign-functions -falign-jumps -falign-loops @gol
+-falign-labels -freorder-blocks -fprefetch-loop-arrays}
+
If you use multiple @option{-O} options, with or without level numbers,
the last such option is the one that is effective.
@end table
Options of the form @option{-f@var{flag}} specify machine-independent
flags. Most flags have both positive and negative forms; the negative
-form of @option{-ffoo} would be @option{-fno-foo}. In the table below,
-only one of the forms is listed---the one which is not the default.
-You can figure out the other form by either removing @samp{no-} or
-adding it.
-
-@table @gcctabopt
-@item -ffloat-store
-@opindex ffloat-store
-Do not store floating point variables in registers, and inhibit other
-options that might change whether a floating point value is taken from a
-register or memory.
+form of @option{-ffoo} would be @option{-fno-foo}. In the table
+below, only one of the forms is listed---the one you typically will
+use. You can figure out the other form by either removing @samp{no-}
+or adding it.
-@cindex floating point precision
-This option prevents undesirable excess precision on machines such as
-the 68000 where the floating registers (of the 68881) keep more
-precision than a @code{double} is supposed to have. Similarly for the
-x86 architecture. For most programs, the excess precision does only
-good, but a few programs rely on the precise definition of IEEE floating
-point. Use @option{-ffloat-store} for such programs, after modifying
-them to store all pertinent intermediate computations into variables.
+The following options control specific optimizations. They are either
+activated by @option{-O} options or are related to ones that are. You
+can use the following flags in the rare cases when ``fine-tuning'' of
+optimizations to be performed is desired.
+@table @gcctabopt
@item -fno-default-inline
@opindex fno-default-inline
Do not make member functions inline by default merely because they are
@@ -3375,13 +3481,17 @@ returns. For machines which must pop arguments after a function call,
the compiler normally lets arguments accumulate on the stack for several
function calls and pops them all at once.
+Disabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -fforce-mem
@opindex fforce-mem
Force memory operands to be copied into registers before doing
arithmetic on them. This produces better code by making all memory
references potential common subexpressions. When they are not common
subexpressions, instruction combination should eliminate the separate
-register-load. The @option{-O2} option turns on this option.
+register-load.
+
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
@item -fforce-addr
@opindex fforce-addr
@@ -3404,14 +3514,13 @@ machine-description macro @code{FRAME_POINTER_REQUIRED} controls
whether a target machine supports this flag. @xref{Registers,,Register
Usage, gccint, GNU Compiler Collection (GCC) Internals}.
+Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -foptimize-sibling-calls
@opindex foptimize-sibling-calls
Optimize sibling and tail recursive calls.
-@item -ftrapv
-@opindex ftrapv
-This option generates traps for signed overflow on addition, subtraction,
-multiplication operations.
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
@item -fno-inline
@opindex fno-inline
@@ -3429,11 +3538,13 @@ If all calls to a given function are integrated, and the function is
declared @code{static}, then the function is normally not output as
assembler code in its own right.
+Enabled at level @option{-O3}.
+
@item -finline-limit=@var{n}
@opindex finline-limit
By default, gcc limits the size of functions that can be inlined. This flag
allows the control of this limit for functions that are explicitly marked as
-inline (ie marked with the inline keyword or defined within the class
+inline (i.e., marked with the inline keyword or defined within the class
definition in c++). @var{n} is the size of functions that can be inlined in
number of pseudo instructions (not counting parameter handling). The default
value of @var{n} is 600.
@@ -3443,6 +3554,28 @@ the compilation faster and less code will be inlined (which presumably
means slower programs). This option is particularly useful for programs that
use inlining heavily such as those based on recursive templates with C++.
+Inlining is actually controlled by a number of parameters, which may be
+specified individually by using @option{--param @var{name}=@var{value}}.
+The @option{-finline-limit=@var{n}} option sets some of these parameters
+as follows:
+
+ @table @gcctabopt
+ @item max-inline-insns
+ is set to @var{n}.
+ @item max-inline-insns-single
+ is set to @var{n}/2.
+ @item max-inline-insns-auto
+ is set to @var{n}/2.
+ @item min-inline-insns
+ is set to 130 or @var{n}/4, whichever is smaller.
+ @item max-inline-insns-rtl
+ is set to @var{n}.
+ @end table
+
+Using @option{-finline-limit=600} thus results in the default settings
+for these parameters. See below for a documentation of the individual
+parameters controlling inlining.
+
@emph{Note:} pseudo instruction represents, in this particular context, an
abstract measurement of function's size. In no way, it represents a count
of assembly instructions and as such its exact meaning might change from one
@@ -3466,10 +3599,13 @@ optimization is turned on, use the @option{-fno-keep-static-consts} option.
@item -fmerge-constants
Attempt to merge identical constants (string constants and floating point
-constants) accross compilation units.
+constants) across compilation units.
-This option is default for optimized compilation if assembler and linker
-support it. Use @option{-fno-merge-constants} to inhibit this behavior.
+This option is the default for optimized compilation if the assembler and
+linker support it. Use @option{-fno-merge-constants} to inhibit this
+behavior.
+
+Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}.
@item -fmerge-all-constants
Attempt to merge identical constants and identical variables.
@@ -3489,6 +3625,9 @@ register, compare it against zero, then branch based upon the result.
This option is only meaningful on architectures that support such
instructions, which include x86, PowerPC, IA-64 and S/390.
+The default is @option{-fbranch-count-reg}, enabled when
+@option{-fstrength-reduce} is enabled.
+
@item -fno-function-cse
@opindex fno-function-cse
Do not put function addresses in registers; make each instruction that
@@ -3498,87 +3637,28 @@ This option results in less efficient code, but some strange hacks
that alter the assembler output may be confused by the optimizations
performed when this option is not used.
-@item -ffast-math
-@opindex ffast-math
-Sets @option{-fno-math-errno}, @option{-funsafe-math-optimizations}, and @*
-@option{-fno-trapping-math}.
-
-This option causes the preprocessor macro @code{__FAST_MATH__} to be defined.
-
-This option should never be turned on by any @option{-O} option since
-it can result in incorrect output for programs which depend on
-an exact implementation of IEEE or ISO rules/specifications for
-math functions.
-
-@item -fno-math-errno
-@opindex fno-math-errno
-Do not set ERRNO after calling math functions that are executed
-with a single instruction, e.g., sqrt. A program that relies on
-IEEE exceptions for math error handling may want to use this flag
-for speed while maintaining IEEE arithmetic compatibility.
-
-This option should never be turned on by any @option{-O} option since
-it can result in incorrect output for programs which depend on
-an exact implementation of IEEE or ISO rules/specifications for
-math functions.
-
-The default is @option{-fmath-errno}.
-
-@item -funsafe-math-optimizations
-@opindex funsafe-math-optimizations
-Allow optimizations for floating-point arithmetic that (a) assume
-that arguments and results are valid and (b) may violate IEEE or
-ANSI standards. When used at link-time, it may include libraries
-or startup files that change the default FPU control word or other
-similar optimizations.
+The default is @option{-ffunction-cse}
-This option should never be turned on by any @option{-O} option since
-it can result in incorrect output for programs which depend on
-an exact implementation of IEEE or ISO rules/specifications for
-math functions.
+@item -fno-zero-initialized-in-bss
+@opindex fno-zero-initialized-in-bss
+If the target supports a BSS section, GCC by default puts variables that
+are initialized to zero into BSS@. This can save space in the resulting
+code.
-The default is @option{-fno-unsafe-math-optimizations}.
+This option turns off this behavior because some programs explicitly
+rely on variables going to the data section. E.g., so that the
+resulting executable can find the beginning of that section and/or make
+assumptions based on that.
-@item -fno-trapping-math
-@opindex fno-trapping-math
-Compile code assuming that floating-point operations cannot generate
-user-visible traps. Setting this option may allow faster code
-if one relies on ``non-stop'' IEEE arithmetic, for example.
+The default is @option{-fzero-initialized-in-bss}.
-This option should never be turned on by any @option{-O} option since
-it can result in incorrect output for programs which depend on
-an exact implementation of IEEE or ISO rules/specifications for
-math functions.
-
-The default is @option{-ftrapping-math}.
-
-@item -fbounds-check
-@opindex fbounds-check
-For front-ends that support it, generate additional code to check that
-indices used to access arrays are within the declared range. This is
-currenly only supported by the Java and Fortran 77 front-ends, where
-this option defaults to true and false respectively.
-
-@end table
-
-The following options control specific optimizations. The @option{-O2}
-option turns on all of these optimizations except @option{-funroll-loops}
-and @option{-funroll-all-loops}. On most machines, the @option{-O} option
-turns on the @option{-fthread-jumps} and @option{-fdelayed-branch} options,
-but specific machines may handle it differently.
-
-You can use the following flags in the rare cases when ``fine-tuning''
-of optimizations to be performed is desired.
-
-Not all of the optimizations performed by GCC have @option{-f} options
-to control them.
-
-@table @gcctabopt
@item -fstrength-reduce
@opindex fstrength-reduce
Perform the optimizations of loop strength reduction and
elimination of iteration variables.
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -fthread-jumps
@opindex fthread-jumps
Perform optimizations where we check to see if a jump branches to a
@@ -3587,6 +3667,8 @@ so, the first branch is redirected to either the destination of the
second branch or a point immediately following it, depending on whether
the condition is known to be true or false.
+Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -fcse-follow-jumps
@opindex fcse-follow-jumps
In common subexpression elimination, scan through jump instructions
@@ -3595,6 +3677,8 @@ example, when CSE encounters an @code{if} statement with an
@code{else} clause, CSE will follow the jump when the condition
tested is false.
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -fcse-skip-blocks
@opindex fcse-skip-blocks
This is similar to @option{-fcse-follow-jumps}, but causes CSE to
@@ -3603,15 +3687,21 @@ encounters a simple @code{if} statement with no else clause,
@option{-fcse-skip-blocks} causes CSE to follow the jump around the
body of the @code{if}.
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -frerun-cse-after-loop
@opindex frerun-cse-after-loop
Re-run common subexpression elimination after loop optimizations has been
performed.
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -frerun-loop-opt
@opindex frerun-loop-opt
Run the loop optimizer twice.
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -fgcse
@opindex fgcse
Perform a global common subexpression elimination pass.
@@ -3619,9 +3709,11 @@ This pass also performs global constant and copy propagation.
@emph{Note:} When compiling a program using computed gotos, a GCC
extension, you may get better runtime performance if you disable
-the global common subexpression elmination pass by adding
+the global common subexpression elimination pass by adding
@option{-fno-gcse} to the command line.
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -fgcse-lm
@opindex fgcse-lm
When @option{-fgcse-lm} is enabled, global common subexpression elimination will
@@ -3629,6 +3721,8 @@ attempt to move loads which are only killed by stores into themselves. This
allows a loop containing a load/store sequence to be changed to a load outside
the loop, and a copy/store within the loop.
+Enabled by default when gcse is enabled.
+
@item -fgcse-sm
@opindex fgcse-sm
When @option{-fgcse-sm} is enabled, A store motion pass is run after global common
@@ -3636,6 +3730,39 @@ subexpression elimination. This pass will attempt to move stores out of loops.
When used in conjunction with @option{-fgcse-lm}, loops containing a load/store sequence
can be changed to a load before the loop and a store after the loop.
+Enabled by default when gcse is enabled.
+
+@item -floop-optimize
+@opindex floop-optimize
+Perform loop optimizations: move constant expressions out of loops, simplify
+exit test conditions and optionally do strength-reduction and loop unrolling as
+well.
+
+Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}.
+
+@item -fcrossjumping
+@opindex crossjumping
+Perform cross-jumping transformation. This transformation unifies equivalent code and save code size. The
+resulting code may or may not perform better than without cross-jumping.
+
+Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}.
+
+@item -fif-conversion
+@opindex if-conversion
+Attempt to transform conditional jumps into branch-less equivalents. This
+include use of conditional moves, min, max, set flags and abs instructions, and
+some tricks doable by standard arithmetics. The use of conditional execution
+on chips where it is available is controlled by @code{if-conversion2}.
+
+Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}.
+
+@item -fif-conversion2
+@opindex if-conversion2
+Use conditional execution (where available) to transform conditional jumps into
+branch-less equivalents.
+
+Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -fdelete-null-pointer-checks
@opindex fdelete-null-pointer-checks
Use global dataflow analysis to identify and eliminate useless checks
@@ -3648,10 +3775,14 @@ safely dereference null pointers. Use
@option{-fno-delete-null-pointer-checks} to disable this optimization
for programs which depend on that behavior.
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -fexpensive-optimizations
@opindex fexpensive-optimizations
Perform a number of minor optimizations that are relatively expensive.
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -foptimize-register-move
@itemx -fregmove
@opindex foptimize-register-move
@@ -3659,18 +3790,21 @@ Perform a number of minor optimizations that are relatively expensive.
Attempt to reassign register numbers in move instructions and as
operands of other simple instructions in order to maximize the amount of
register tying. This is especially helpful on machines with two-operand
-instructions. GCC enables this optimization by default with @option{-O2}
-or higher.
+instructions.
Note @option{-fregmove} and @option{-foptimize-register-move} are the same
optimization.
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -fdelayed-branch
@opindex fdelayed-branch
If supported for the target machine, attempt to reorder instructions
to exploit instruction slots available after delayed branch
instructions.
+Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -fschedule-insns
@opindex fschedule-insns
If supported for the target machine, attempt to reorder instructions to
@@ -3679,6 +3813,8 @@ helps machines that have slow floating point or memory load instructions
by allowing other instructions to be issued until the result of the load
or floating point instruction is required.
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -fschedule-insns2
@opindex fschedule-insns2
Similar to @option{-fschedule-insns}, but requests an additional pass of
@@ -3686,6 +3822,8 @@ instruction scheduling after register allocation has been done. This is
especially useful on machines with a relatively small number of
registers and where memory load instructions take more than one cycle.
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -fno-sched-interblock
@opindex fno-sched-interblock
Don't schedule instructions across basic blocks. This is normally
@@ -3710,28 +3848,6 @@ Allow speculative motion of more load instructions. This only makes
sense when scheduling before register allocation, i.e.@: with
@option{-fschedule-insns} or at @option{-O2} or higher.
-@item -ffunction-sections
-@itemx -fdata-sections
-@opindex ffunction-sections
-@opindex fdata-sections
-Place each function or data item into its own section in the output
-file if the target supports arbitrary sections. The name of the
-function or the name of the data item determines the section's name
-in the output file.
-
-Use these options on systems where the linker can perform optimizations
-to improve locality of reference in the instruction space. HPPA
-processors running HP-UX and Sparc processors running Solaris 2 have
-linkers with such optimizations. Other systems using the ELF object format
-as well as AIX may have these optimizations in the future.
-
-Only use these options when there are significant benefits from doing
-so. When you specify these options, the assembler and linker will
-create larger object and executable files and will also be slower.
-You will not be able to use @code{gprof} on all systems if you
-specify this option and you may have problems with debugging if
-you specify both this option and @option{-g}.
-
@item -fcaller-saves
@opindex fcaller-saves
Enable values to be allocated in registers that will be clobbered by
@@ -3742,27 +3858,7 @@ seems to result in better code than would otherwise be produced.
This option is always enabled by default on certain machines, usually
those which have no call-preserved registers to use instead.
-For all machines, optimization level 2 and higher enables this flag by
-default.
-
-@item -funroll-loops
-@opindex funroll-loops
-Unroll loops whose number of iterations can be determined at compile
-time or upon entry to the loop. @option{-funroll-loops} implies both
-@option{-fstrength-reduce} and @option{-frerun-cse-after-loop}. This
-option makes code larger, and may or may not make it run faster.
-
-@item -funroll-all-loops
-@opindex funroll-all-loops
-Unroll all loops, even if their number of iterations is uncertain when
-the loop is entered. This usually makes programs run more slowly.
-@option{-funroll-all-loops} implies the same options as
-@option{-funroll-loops},
-
-@item -fprefetch-loop-arrays
-@opindex fprefetch-loop-arrays
-If supported by the target machine, generate instructions to prefetch
-memory to improve the performance of loops that access large arrays.
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
@item -fmove-all-movables
@opindex fmove-all-movables
@@ -3800,27 +3896,10 @@ between @option{-fno-peephole} and @option{-fno-peephole2} is in how they
are implemented in the compiler; some targets use one, some use the
other, a few use both.
-@item -fbranch-probabilities
-@opindex fbranch-probabilities
-After running a program compiled with @option{-fprofile-arcs}
-(@pxref{Debugging Options,, Options for Debugging Your Program or
-@command{gcc}}), you can compile it a second time using
-@option{-fbranch-probabilities}, to improve optimizations based on
-the number of times each branch was taken. When the program
-compiled with @option{-fprofile-arcs} exits it saves arc execution
-counts to a file called @file{@var{sourcename}.da} for each source
-file The information in this data file is very dependent on the
-structure of the generated code, so you must use the same source code
-and the same optimization options for both compilations.
-
-With @option{-fbranch-probabilities}, GCC puts a @samp{REG_EXEC_COUNT}
-note on the first instruction of each basic block, and a
-@samp{REG_BR_PROB} note on each @samp{JUMP_INSN} and @samp{CALL_INSN}.
-These can be used to improve optimization. Currently, they are only
-used in one place: in @file{reorg.c}, instead of guessing which path a
-branch is mostly to take, the @samp{REG_BR_PROB} values are used to
-exactly determine which path is taken more often.
+@option{-fpeephole} is enabled by default.
+@option{-fpeephole2} enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+@item -fbranch-probabilities
@item -fno-guess-branch-probability
@opindex fno-guess-branch-probability
Do not guess branch probabilities using a randomized model.
@@ -3837,6 +3916,30 @@ non-determinism is of paramount import. This switch allows users to
reduce non-determinism, possibly at the expense of inferior
optimization.
+The default is @option{-fguess-branch-probability} at levels
+@option{-O}, @option{-O2}, @option{-O3}, @option{-Os}.
+
+@item -freorder-blocks
+@opindex freorder-blocks
+Reorder basic blocks in the compiled function in order to reduce number of
+taken branches and improve code locality.
+
+Enabled at levels @option{-O2}, @option{-O3}.
+
+@item -freorder-functions
+@opindex freorder-functions
+Reorder basic blocks in the compiled function in order to reduce number of
+taken branches and improve code locality. This is implemented by using special
+subsections @code{text.hot} for most frequently executed functions and
+@code{text.unlikely} for unlikely executed functions. Reordering is done by
+the linker so object file format must support named sections and linker must
+place them in a reasonable way.
+
+Also profile feedback must be available in to make this option effective. See
+@option{-fprofile-arcs} for details.
+
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -fstrict-aliasing
@opindex fstrict-aliasing
Allows the compiler to assume the strictest aliasing rules applicable to
@@ -3882,6 +3985,8 @@ node, an alias set for the node. Nodes in different alias sets are not
allowed to alias. For an example, see the C front-end function
@code{c_get_alias_set}.
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
@item -falign-functions
@itemx -falign-functions=@var{n}
@opindex falign-functions
@@ -3897,7 +4002,9 @@ equivalent and mean that functions will not be aligned.
Some assemblers only support this flag when @var{n} is a power of two;
in that case, it is rounded up.
-If @var{n} is not specified, use a machine-dependent default.
+If @var{n} is not specified or is zero, use a machine-dependent default.
+
+Enabled at levels @option{-O2}, @option{-O3}.
@item -falign-labels
@itemx -falign-labels=@var{n}
@@ -3907,11 +4014,16 @@ Align all branch targets to a power-of-two boundary, skipping up to
make code slower, because it must insert dummy operations for when the
branch target is reached in the usual flow of the code.
+@option{-fno-align-labels} and @option{-falign-labels=1} are
+equivalent and mean that labels will not be aligned.
+
If @option{-falign-loops} or @option{-falign-jumps} are applicable and
are greater than this value, then their values are used instead.
-If @var{n} is not specified, use a machine-dependent default which is
-very likely to be @samp{1}, meaning no alignment.
+If @var{n} is not specified or is zero, use a machine-dependent default
+which is very likely to be @samp{1}, meaning no alignment.
+
+Enabled at levels @option{-O2}, @option{-O3}.
@item -falign-loops
@itemx -falign-loops=@var{n}
@@ -3921,7 +4033,12 @@ like @option{-falign-functions}. The hope is that the loop will be
executed many times, which will make up for any execution of the dummy
operations.
-If @var{n} is not specified, use a machine-dependent default.
+@option{-fno-align-loops} and @option{-falign-loops=1} are
+equivalent and mean that loops will not be aligned.
+
+If @var{n} is not specified or is zero, use a machine-dependent default.
+
+Enabled at levels @option{-O2}, @option{-O3}.
@item -falign-jumps
@itemx -falign-jumps=@var{n}
@@ -3931,7 +4048,224 @@ where the targets can only be reached by jumping, skipping up to @var{n}
bytes like @option{-falign-functions}. In this case, no dummy operations
need be executed.
-If @var{n} is not specified, use a machine-dependent default.
+@option{-fno-align-jumps} and @option{-falign-jumps=1} are
+equivalent and mean that loops will not be aligned.
+
+If @var{n} is not specified or is zero, use a machine-dependent default.
+
+Enabled at levels @option{-O2}, @option{-O3}.
+
+@item -frename-registers
+@opindex frename-registers
+Attempt to avoid false dependencies in scheduled code by making use
+of registers left over after register allocation. This optimization
+will most benefit processors with lots of registers. It can, however,
+make debugging impossible, since variables will no longer stay in
+a ``home register''.
+
+Enabled at levels @option{-O3}.
+
+@item -fno-cprop-registers
+@opindex fno-cprop-registers
+After register allocation and post-register allocation instruction splitting,
+we perform a copy-propagation pass to try to reduce scheduling dependencies
+and occasionally eliminate the copy.
+
+Disabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}.
+
+@end table
+
+The following options control compiler behavior regarding floating
+point arithmetic. These options trade off between speed and
+correctness. All must be specifically enabled.
+
+@table @gcctabopt
+@item -ffloat-store
+@opindex ffloat-store
+Do not store floating point variables in registers, and inhibit other
+options that might change whether a floating point value is taken from a
+register or memory.
+
+@cindex floating point precision
+This option prevents undesirable excess precision on machines such as
+the 68000 where the floating registers (of the 68881) keep more
+precision than a @code{double} is supposed to have. Similarly for the
+x86 architecture. For most programs, the excess precision does only
+good, but a few programs rely on the precise definition of IEEE floating
+point. Use @option{-ffloat-store} for such programs, after modifying
+them to store all pertinent intermediate computations into variables.
+
+@item -ffast-math
+@opindex ffast-math
+Sets @option{-fno-math-errno}, @option{-funsafe-math-optimizations}, @*
+@option{-fno-trapping-math}, @option{-ffinite-math-only} and @*
+@option{-fno-signaling-nans}.
+
+This option causes the preprocessor macro @code{__FAST_MATH__} to be defined.
+
+This option should never be turned on by any @option{-O} option since
+it can result in incorrect output for programs which depend on
+an exact implementation of IEEE or ISO rules/specifications for
+math functions.
+
+@item -fno-math-errno
+@opindex fno-math-errno
+Do not set ERRNO after calling math functions that are executed
+with a single instruction, e.g., sqrt. A program that relies on
+IEEE exceptions for math error handling may want to use this flag
+for speed while maintaining IEEE arithmetic compatibility.
+
+This option should never be turned on by any @option{-O} option since
+it can result in incorrect output for programs which depend on
+an exact implementation of IEEE or ISO rules/specifications for
+math functions.
+
+The default is @option{-fmath-errno}.
+
+@item -funsafe-math-optimizations
+@opindex funsafe-math-optimizations
+Allow optimizations for floating-point arithmetic that (a) assume
+that arguments and results are valid and (b) may violate IEEE or
+ANSI standards. When used at link-time, it may include libraries
+or startup files that change the default FPU control word or other
+similar optimizations.
+
+This option should never be turned on by any @option{-O} option since
+it can result in incorrect output for programs which depend on
+an exact implementation of IEEE or ISO rules/specifications for
+math functions.
+
+The default is @option{-fno-unsafe-math-optimizations}.
+
+@item -ffinite-math-only
+@opindex ffinite-math-only
+Allow optimizations for floating-point arithmetic that assume
+that arguments and results are not NaNs or +-Infs.
+
+This option should never be turned on by any @option{-O} option since
+it can result in incorrect output for programs which depend on
+an exact implementation of IEEE or ISO rules/specifications.
+
+The default is @option{-fno-finite-math-only}.
+
+@item -fno-trapping-math
+@opindex fno-trapping-math
+Compile code assuming that floating-point operations cannot generate
+user-visible traps. These traps include division by zero, overflow,
+underflow, inexact result and invalid operation. This option implies
+@option{-fno-signaling-nans}. Setting this option may allow faster
+code if one relies on ``non-stop'' IEEE arithmetic, for example.
+
+This option should never be turned on by any @option{-O} option since
+it can result in incorrect output for programs which depend on
+an exact implementation of IEEE or ISO rules/specifications for
+math functions.
+
+The default is @option{-ftrapping-math}.
+
+@item -fsignaling-nans
+@opindex fsignaling-nans
+Compile code assuming that IEEE signaling NaNs may generate user-visible
+traps during floating-point operations. Setting this option disables
+optimizations that may change the number of exceptions visible with
+signaling NaNs. This option implies @option{-ftrapping-math}.
+
+This option causes the preprocessor macro @code{__SUPPORT_SNAN__} to
+be defined.
+
+The default is @option{-fno-signaling-nans}.
+
+This option is experimental and does not currently guarantee to
+disable all GCC optimizations that affect signaling NaN behavior.
+
+@item -fsingle-precision-constant
+@opindex fsingle-precision-constant
+Treat floating point constant as single precision constant instead of
+implicitly converting it to double precision constant.
+
+
+@end table
+
+The following options control optimizations that may improve
+performance, but are not enabled by any @option{-O} options. This
+section includes experimental options that may produce broken code.
+
+@table @gcctabopt
+@item -fbranch-probabilities
+@opindex fbranch-probabilities
+After running a program compiled with @option{-fprofile-arcs}
+(@pxref{Debugging Options,, Options for Debugging Your Program or
+@command{gcc}}), you can compile it a second time using
+@option{-fbranch-probabilities}, to improve optimizations based on
+the number of times each branch was taken. When the program
+compiled with @option{-fprofile-arcs} exits it saves arc execution
+counts to a file called @file{@var{sourcename}.da} for each source
+file The information in this data file is very dependent on the
+structure of the generated code, so you must use the same source code
+and the same optimization options for both compilations.
+
+With @option{-fbranch-probabilities}, GCC puts a
+@samp{REG_BR_PROB} note on each @samp{JUMP_INSN} and @samp{CALL_INSN}.
+These can be used to improve optimization. Currently, they are only
+used in one place: in @file{reorg.c}, instead of guessing which path a
+branch is mostly to take, the @samp{REG_BR_PROB} values are used to
+exactly determine which path is taken more often.
+
+@item -fnew-ra
+@opindex fnew-ra
+Use a graph coloring register allocator. Currently this option is meant
+for testing, so we are interested to hear about miscompilations with
+@option{-fnew-ra}.
+
+@item -ftracer
+@opindex ftracer
+Perform tail duplication to enlarge superblock size. This transformation
+simplifies the control flow of the function allowing other optimizations to do
+better job.
+
+@item -funroll-loops
+@opindex funroll-loops
+Unroll loops whose number of iterations can be determined at compile
+time or upon entry to the loop. @option{-funroll-loops} implies both
+@option{-fstrength-reduce} and @option{-frerun-cse-after-loop}. This
+option makes code larger, and may or may not make it run faster.
+
+@item -funroll-all-loops
+@opindex funroll-all-loops
+Unroll all loops, even if their number of iterations is uncertain when
+the loop is entered. This usually makes programs run more slowly.
+@option{-funroll-all-loops} implies the same options as
+@option{-funroll-loops},
+
+@item -fprefetch-loop-arrays
+@opindex fprefetch-loop-arrays
+If supported by the target machine, generate instructions to prefetch
+memory to improve the performance of loops that access large arrays.
+
+Disabled at level @option{-Os}.
+
+@item -ffunction-sections
+@itemx -fdata-sections
+@opindex ffunction-sections
+@opindex fdata-sections
+Place each function or data item into its own section in the output
+file if the target supports arbitrary sections. The name of the
+function or the name of the data item determines the section's name
+in the output file.
+
+Use these options on systems where the linker can perform optimizations
+to improve locality of reference in the instruction space. Most systems
+using the ELF object format and SPARC processors running Solaris 2 have
+linkers with such optimizations. AIX may have these optimizations in
+the future.
+
+
+Only use these options when there are significant benefits from doing
+so. When you specify these options, the assembler and linker will
+create larger object and executable files and will also be slower.
+You will not be able to use @code{gprof} on all systems if you
+specify this option and you may have problems with debugging if
+you specify both this option and @option{-g}.
@item -fssa
@opindex fssa
@@ -3950,24 +4284,6 @@ Perform Sparse Conditional Constant Propagation in SSA form. Requires
Perform aggressive dead-code elimination in SSA form. Requires @option{-fssa}.
Like @option{-fssa}, this is an experimental feature.
-@item -fsingle-precision-constant
-@opindex fsingle-precision-constant
-Treat floating point constant as single precision constant instead of
-implicitly converting it to double precision constant.
-
-@item -frename-registers
-@opindex frename-registers
-Attempt to avoid false dependencies in scheduled code by making use
-of registers left over after register allocation. This optimization
-will most benefit processors with lots of registers. It can, however,
-make debugging impossible, since variables will no longer stay in
-a ``home register''.
-
-@item -fno-cprop-registers
-@opindex fno-cprop-registers
-After register allocation and post-register allocation instruction splitting,
-we perform a copy-propagation pass to try to reduce scheduling dependencies
-and occasionally eliminate the copy.
@item --param @var{name}=@var{value}
@opindex param
@@ -3981,6 +4297,13 @@ In each case, the @var{value} is an integer. The allowable choices for
@var{name} are given in the following table:
@table @gcctabopt
+@item max-crossjump-edges
+The maximum number of incoming edges to consider for crossjumping.
+The algorithm used by @option{-fcrossjumping} is @math{O(N^2)} in
+the number of edges incoming to each block. Increasing values mean
+more aggressive optimization, making the compile time increase with
+probably small improvement in executable size.
+
@item max-delay-slot-insn-search
The maximum number of instructions to consider when looking for an
instruction to fill a delay slot. If more than this arbitrary number of
@@ -4012,10 +4335,133 @@ before flushing the current state and starting over. Large functions
with few branches or calls can create excessively large lists which
needlessly consume memory and resources.
+@item max-inline-insns-single
+Several parameters control the tree inliner used in gcc.
+This number sets the maximum number of instructions (counted in gcc's
+internal representation) in a single function that the tree inliner
+will consider for inlining. This only affects functions declared
+inline and methods implemented in a class declaration (C++).
+The default value is 300.
+
+@item max-inline-insns-auto
+When you use @option{-finline-functions} (included in @option{-O3}),
+a lot of functions that would otherwise not be considered for inlining
+by the compiler will be investigated. To those functions, a different
+(more restrictive) limit compared to functions declared inline can
+be applied.
+The default value is 300.
+
@item max-inline-insns
-If an function contains more than this many instructions, it
-will not be inlined. This option is precisely equivalent to
-@option{-finline-limit}.
+The tree inliner does decrease the allowable size for single functions
+to be inlined after we already inlined the number of instructions
+given here by repeated inlining. This number should be a factor of
+two or more larger than the single function limit.
+Higher numbers result in better runtime performance, but incur higher
+compile-time resource (CPU time, memory) requirements and result in
+larger binaries. Very high values are not advisable, as too large
+binaries may adversely affect runtime performance.
+The default value is 600.
+
+@item max-inline-slope
+After exceeding the maximum number of inlined instructions by repeated
+inlining, a linear function is used to decrease the allowable size
+for single functions. The slope of that function is the negative
+reciprocal of the number specified here.
+The default value is 32.
+
+@item min-inline-insns
+The repeated inlining is throttled more and more by the linear function
+after exceeding the limit. To avoid too much throttling, a minimum for
+this function is specified here to allow repeated inlining for very small
+functions even when a lot of repeated inlining already has been done.
+The default value is 130.
+
+@item max-inline-insns-rtl
+For languages that use the RTL inliner (this happens at a later stage
+than tree inlining), you can set the maximum allowable size (counted
+in RTL instructions) for the RTL inliner with this parameter.
+The default value is 600.
+
+
+@item max-unrolled-insns
+The maximum number of instructions that a loop should have if that loop
+is unrolled, and if the loop is unrolled, it determines how many times
+the loop code is unrolled.
+
+@item hot-bb-count-fraction
+Select fraction of the maximal count of repetitions of basic block in program
+given basic block needs to have to be considered hot.
+
+@item hot-bb-frequency-fraction
+Select fraction of the maximal frequency of executions of basic block in
+function given basic block needs to have to be considered hot
+
+@item tracer-dynamic-coverage
+@itemx tracer-dynamic-coverage-feedback
+
+This value is used to limit superblock formation once the given percentage of
+executed instructions is covered. This limits unnecessary code size
+expansion.
+
+The @option{tracer-dynamic-coverage-feedback} is used only when profile
+feedback is available. The real profiles (as opposed to statically estimated
+ones) are much less balanced allowing the threshold to be larger value.
+
+@item tracer-max-code-growth
+Stop tail duplication once code growth has reached given percentage. This is
+rather hokey argument, as most of the duplicates will be eliminated later in
+cross jumping, so it may be set to much higher values than is the desired code
+growth.
+
+@item tracer-min-branch-ratio
+
+Stop reverse growth when the reverse probability of best edge is less than this
+threshold (in percent).
+
+@item tracer-min-branch-ratio
+@itemx tracer-min-branch-ratio-feedback
+
+Stop forward growth if the best edge do have probability lower than this
+threshold.
+
+Similarly to @option{tracer-dynamic-coverage} two values are present, one for
+compilation for profile feedback and one for compilation without. The value
+for compilation with profile feedback needs to be more conservative (higher) in
+order to make tracer effective.
+
+@item ggc-min-expand
+
+GCC uses a garbage collector to manage its own memory allocation. This
+parameter specifies the minimum percentage by which the garbage
+collector's heap should be allowed to expand between collections.
+Tuning this may improve compilation speed; it has no effect on code
+generation.
+
+The default is 30% + 70% * (RAM/1GB) with an upper bound of 100% when
+RAM >= 1GB. If @code{getrlimit} is available, the notion of "RAM" is
+the smallest of actual RAM, RLIMIT_RSS, RLIMIT_DATA and RLIMIT_AS. If
+GCC is not able to calculate RAM on a particular platform, the lower
+bound of 30% is used. Setting this parameter and
+@option{ggc-min-heapsize} to zero causes a full collection to occur at
+every opportunity. This is extremely slow, but can be useful for
+debugging.
+
+@item ggc-min-heapsize
+
+Minimum size of the garbage collector's heap before it begins bothering
+to collect garbage. The first collection occurs after the heap expands
+by @option{ggc-min-expand}% beyond @option{ggc-min-heapsize}. Again,
+tuning this may improve compilation speed, and has no effect on code
+generation.
+
+The default is RAM/8, with a lower bound of 4096 (four megabytes) and an
+upper bound of 131072 (128 megabytes). If @code{getrlimit} is
+available, the notion of "RAM" is the smallest of actual RAM,
+RLIMIT_RSS, RLIMIT_DATA and RLIMIT_AS. If GCC is not able to calculate
+RAM on a particular platform, the lower bound is used. Setting this
+parameter very large effectively disables garbage collection. Setting
+this parameter and @option{ggc-min-expand} to zero causes a full
+collection to occur at every opportunity.
@end table
@end table
@@ -4287,7 +4733,7 @@ If a standard system include directory, or a directory specified with
option will be ignored. The directory will still be searched but as a
system directory at its normal position in the system include chain.
This is to ensure that GCC's procedure to fix buggy system headers and
-the ordering for the include_next directive are not inadvertantly changed.
+the ordering for the include_next directive are not inadvertently changed.
If you really need to change the search order for system directories,
use the @option{-nostdinc} and/or @option{-isystem} options.
@@ -4377,6 +4823,7 @@ are processed in order, from left to right.
@node Spec Files
@section Specifying subprocesses and the switches to pass to them
@cindex Spec Files
+
@command{gcc} is a driver program. It performs its job by invoking a
sequence of other programs to do the work of compiling, assembling and
linking. GCC interprets its command-line parameters and uses these to
@@ -4725,6 +5172,41 @@ Substitute the variable part of a matched option. See below.
Note that each comma in the substituted string is replaced by
a single space.
+@item %:@var{function}(@var{args})
+Call the named function @var{function}, passing it @var{args}.
+@var{args} is first processed as a nested spec string, then split
+into an argument vector in the usual fashion. The function returns
+a string which is processed as if it had appeared literally as part
+of the current spec.
+
+The following built-in spec functions are provided:
+
+@table @code
+@item @code{if-exists}
+The @code{if-exists} spec function takes one argument, an absolute
+pathname to a file. If the file exists, @code{if-exists} returns the
+pathname. Here is a small example of its usage:
+
+@smallexample
+*startfile:
+crt0%O%s %:if-exists(crti%O%s) crtbegin%O%s
+@end smallexample
+
+@item @code{if-exists-else}
+The @code{if-exists-else} spec function is similar to the @code{if-exists}
+spec function, except that it takes two arguments. The first argument is
+an absolute pathname to a file. If the file exists, @code{if-exists-else}
+returns the pathname. If it does not exist, it returns the second argument.
+This way, @code{if-exists-else} can be used to select one file or another,
+based on the existence of the first. Here is a small example of its usage:
+
+@smallexample
+*startfile:
+crt0%O%s %:if-exists(crti%O%s) \
+%:if-exists-else(crtbeginT%O%s crtbegin%O%s)
+@end smallexample
+@end table
+
@item %@{@code{S}@}
Substitutes the @code{-S} switch, if that switch was given to GCC@.
If that switch was not specified, this substitutes nothing. Note that
@@ -4846,22 +5328,16 @@ proper position among the other output files.
@cindex compiler version, specifying
@cindex target machine, specifying
-By default, GCC compiles code for the same type of machine that you
-are using. However, it can also be installed as a cross-compiler, to
-compile for some other type of machine. In fact, several different
-configurations of GCC, for different target machines, can be
-installed side by side. Then you specify which one to use with the
-@option{-b} option.
-
-In addition, older and newer versions of GCC can be installed side
-by side. One of them (probably the newest) will be the default, but
-you may sometimes wish to use another.
+The usual way to run GCC is to run the executable called @file{gcc}, or
+@file{<machine>-gcc} when cross-compiling, or
+@file{<machine>-gcc-<version>} to run a version other than the one that
+was installed last. Sometimes this is inconvenient, so GCC provides
+options that will switch to another cross-compiler or version.
@table @gcctabopt
@item -b @var{machine}
@opindex b
The argument @var{machine} specifies the target machine for compilation.
-This is useful when you have installed GCC as a cross-compiler.
The value to use for @var{machine} is the same as was specified as the
machine type when configuring GCC as a cross-compiler. For
@@ -4869,61 +5345,16 @@ example, if a cross-compiler was configured with @samp{configure
i386v}, meaning to compile for an 80386 running System V, then you
would specify @option{-b i386v} to run that cross compiler.
-When you do not specify @option{-b}, it normally means to compile for
-the same type of machine that you are using.
-
@item -V @var{version}
@opindex V
The argument @var{version} specifies which version of GCC to run.
This is useful when multiple versions are installed. For example,
@var{version} might be @samp{2.0}, meaning to run GCC version 2.0.
-
-The default version, when you do not specify @option{-V}, is the last
-version of GCC that you installed.
@end table
-The @option{-b} and @option{-V} options actually work by controlling part of
-the file name used for the executable files and libraries used for
-compilation. A given version of GCC, for a given target machine, is
-normally kept in the directory @file{/usr/local/lib/gcc-lib/@var{machine}/@var{version}}.
-
-Thus, sites can customize the effect of @option{-b} or @option{-V} either by
-changing the names of these directories or adding alternate names (or
-symbolic links). If in directory @file{/usr/local/lib/gcc-lib/} the
-file @file{80386} is a link to the file @file{i386v}, then @option{-b
-80386} becomes an alias for @option{-b i386v}.
-
-In one respect, the @option{-b} or @option{-V} do not completely change
-to a different compiler: the top-level driver program @command{gcc}
-that you originally invoked continues to run and invoke the other
-executables (preprocessor, compiler per se, assembler and linker)
-that do the real work. However, since no real work is done in the
-driver program, it usually does not matter that the driver program
-in use is not the one for the specified target. It is common for the
-interface to the other executables to change incompatibly between
-compiler versions, so unless the version specified is very close to that
-of the driver (for example, @option{-V 3.0} with a driver program from GCC
-version 3.0.1), use of @option{-V} may not work; for example, using
-@option{-V 2.95.2} will not work with a driver program from GCC 3.0.
-
-The only way that the driver program depends on the target machine is
-in the parsing and handling of special machine-specific options.
-However, this is controlled by a file which is found, along with the
-other executables, in the directory for the specified version and
-target machine. As a result, a single installed driver program adapts
-to any specified target machine, and sufficiently similar compiler
-versions.
-
-The driver program executable does control one significant thing,
-however: the default version and target machine. Therefore, you can
-install different instances of the driver program, compiled for
-different targets or versions, under different names.
-
-For example, if the driver for version 2.0 is installed as @command{ogcc}
-and that for version 2.1 is installed as @command{gcc}, then the command
-@command{gcc} will use version 2.1 by default, while @command{ogcc} will use
-2.0 by default. However, you can choose either version with either
-command with the @option{-V} option.
+The @option{-V} and @option{-b} options work by running the
+@file{<machine>-gcc-<version>} executable, so there's no real reason to
+use them if you can just run that directly.
@node Submodel Options
@section Hardware Models and Configurations
@@ -4956,14 +5387,13 @@ that macro, which enables you to change the defaults.
* M68hc1x Options::
* VAX Options::
* SPARC Options::
-* Convex Options::
-* AMD29K Options::
* ARM Options::
* MN10200 Options::
* MN10300 Options::
* M32R/D Options::
* M88K Options::
* RS/6000 and PowerPC Options::
+* Darwin Options::
* RT Options::
* MIPS Options::
* i386 and x86-64 Options::
@@ -4971,7 +5401,6 @@ that macro, which enables you to change the defaults.
* Intel 960 Options::
* DEC Alpha Options::
* DEC Alpha/VMS Options::
-* Clipper Options::
* H8/300 Options::
* SH Options::
* System V Options::
@@ -4989,6 +5418,7 @@ that macro, which enables you to change the defaults.
* PDP-11 Options::
* Xstormy16 Options::
* Xtensa Options::
+* FRV Options::
@end menu
@node M680x0 Options
@@ -5187,11 +5617,31 @@ when the compiler is configured for 68HC11-based systems.
Generate output for a 68HC12. This is the default
when the compiler is configured for 68HC12-based systems.
+@item -m68S12
+@itemx -m68hcs12
+@opindex m68S12
+@opindex m68hcs12
+Generate output for a 68HCS12.
+
@item -mauto-incdec
@opindex mauto-incdec
Enable the use of 68HC12 pre and post auto-increment and auto-decrement
addressing modes.
+@item -minmax
+@itemx -nominmax
+@opindex minmax
+@opindex mnominmax
+Enable the use of 68HC12 min and max instructions.
+
+@item -mlong-calls
+@itemx -mno-long-calls
+@opindex mlong-calls
+@opindex mno-long-calls
+Treat all calls as being far away (near). If calls are assumed to be
+far away, the compiler will use the @code{call} instruction to
+call a function and the @code{rtc} instruction for returning.
+
@item -mshort
@opindex mshort
Consider type @code{int} to be 16 bits wide, like @code{short int}.
@@ -5325,7 +5775,7 @@ With @option{-mfaster-structs}, the compiler assumes that structures
should have 8 byte alignment. This enables the use of pairs of
@code{ldd} and @code{std} instructions for copies in structure
assignment, in place of twice as many @code{ld} and @code{st} pairs.
-However, the use of this changed alignment directly violates the Sparc
+However, the use of this changed alignment directly violates the SPARC
ABI@. Thus, it's intended only for use on targets where the developer
acknowledges that their resulting code will not be directly in line with
the rules of the ABI@.
@@ -5357,11 +5807,11 @@ They have been replaced with @option{-mcpu=xxx}.
These two options select the processor for which the code is optimized.
With @option{-mcypress} (the default), the compiler optimizes code for the
-Cypress CY7C602 chip, as used in the SparcStation/SparcServer 3xx series.
-This is also appropriate for the older SparcStation 1, 2, IPX etc.
+Cypress CY7C602 chip, as used in the SPARCStation/SPARCServer 3xx series.
+This is also appropriate for the older SPARCStation 1, 2, IPX etc.
-With @option{-msupersparc} the compiler optimizes code for the SuperSparc cpu, as
-used in the SparcStation 10, 1000 and 2000 series. This flag also enables use
+With @option{-msupersparc} the compiler optimizes code for the SuperSPARC cpu, as
+used in the SPARCStation 10, 1000 and 2000 series. This flag also enables use
of the full SPARC v8 instruction set.
These options are deprecated and will be deleted in a future GCC release.
@@ -5373,7 +5823,8 @@ Set the instruction set, register set, and instruction scheduling parameters
for machine type @var{cpu_type}. Supported values for @var{cpu_type} are
@samp{v7}, @samp{cypress}, @samp{v8}, @samp{supersparc}, @samp{sparclite},
@samp{hypersparc}, @samp{sparclite86x}, @samp{f930}, @samp{f934},
-@samp{sparclet}, @samp{tsc701}, @samp{v9}, and @samp{ultrasparc}.
+@samp{sparclet}, @samp{tsc701}, @samp{v9}, @samp{ultrasparc}, and
+@samp{ultrasparc3}.
Default instruction scheduling parameters are used for values that select
an architecture and not an implementation. These are @samp{v7}, @samp{v8},
@@ -5387,7 +5838,7 @@ implementations.
v8: supersparc, hypersparc
sparclite: f930, f934, sparclite86x
sparclet: tsc701
- v9: ultrasparc
+ v9: ultrasparc, ultrasparc3
@end smallexample
@item -mtune=@var{cpu_type}
@@ -5400,7 +5851,8 @@ The same values for @option{-mcpu=@var{cpu_type}} can be used for
@option{-mtune=@var{cpu_type}}, but the only useful values are those
that select a particular cpu implementation. Those are @samp{cypress},
@samp{supersparc}, @samp{hypersparc}, @samp{f930}, @samp{f934},
-@samp{sparclite86x}, @samp{tsc701}, and @samp{ultrasparc}.
+@samp{sparclite86x}, @samp{tsc701}, @samp{ultrasparc}, and
+@samp{ultrasparc3}.
@end table
@@ -5485,195 +5937,6 @@ when making stack frame references.
Otherwise, assume no such offset is present.
@end table
-@node Convex Options
-@subsection Convex Options
-@cindex Convex options
-
-These @samp{-m} options are defined for Convex:
-
-@table @gcctabopt
-@item -mc1
-@opindex mc1
-Generate output for C1. The code will run on any Convex machine.
-The preprocessor symbol @code{__convex__c1__} is defined.
-
-@item -mc2
-@opindex mc2
-Generate output for C2. Uses instructions not available on C1.
-Scheduling and other optimizations are chosen for max performance on C2.
-The preprocessor symbol @code{__convex_c2__} is defined.
-
-@item -mc32
-@opindex mc32
-Generate output for C32xx. Uses instructions not available on C1.
-Scheduling and other optimizations are chosen for max performance on C32.
-The preprocessor symbol @code{__convex_c32__} is defined.
-
-@item -mc34
-@opindex mc34
-Generate output for C34xx. Uses instructions not available on C1.
-Scheduling and other optimizations are chosen for max performance on C34.
-The preprocessor symbol @code{__convex_c34__} is defined.
-
-@item -mc38
-@opindex mc38
-Generate output for C38xx. Uses instructions not available on C1.
-Scheduling and other optimizations are chosen for max performance on C38.
-The preprocessor symbol @code{__convex_c38__} is defined.
-
-@item -margcount
-@opindex margcount
-Generate code which puts an argument count in the word preceding each
-argument list. This is compatible with regular CC, and a few programs
-may need the argument count word. GDB and other source-level debuggers
-do not need it; this info is in the symbol table.
-
-@item -mnoargcount
-@opindex mnoargcount
-Omit the argument count word. This is the default.
-
-@item -mvolatile-cache
-@opindex mvolatile-cache
-Allow volatile references to be cached. This is the default.
-
-@item -mvolatile-nocache
-@opindex mvolatile-nocache
-Volatile references bypass the data cache, going all the way to memory.
-This is only needed for multi-processor code that does not use standard
-synchronization instructions. Making non-volatile references to volatile
-locations will not necessarily work.
-
-@item -mlong32
-@opindex mlong32
-Type long is 32 bits, the same as type int. This is the default.
-
-@item -mlong64
-@opindex mlong64
-Type long is 64 bits, the same as type long long. This option is useless,
-because no library support exists for it.
-@end table
-
-@node AMD29K Options
-@subsection AMD29K Options
-@cindex AMD29K options
-
-These @samp{-m} options are defined for the AMD Am29000:
-
-@table @gcctabopt
-@item -mdw
-@opindex mdw
-@cindex DW bit (29k)
-Generate code that assumes the @code{DW} bit is set, i.e., that byte and
-halfword operations are directly supported by the hardware. This is the
-default.
-
-@item -mndw
-@opindex mndw
-Generate code that assumes the @code{DW} bit is not set.
-
-@item -mbw
-@opindex mbw
-@cindex byte writes (29k)
-Generate code that assumes the system supports byte and halfword write
-operations. This is the default.
-
-@item -mnbw
-@opindex mnbw
-Generate code that assumes the systems does not support byte and
-halfword write operations. @option{-mnbw} implies @option{-mndw}.
-
-@item -msmall
-@opindex msmall
-@cindex memory model (29k)
-Use a small memory model that assumes that all function addresses are
-either within a single 256 KB segment or at an absolute address of less
-than 256k. This allows the @code{call} instruction to be used instead
-of a @code{const}, @code{consth}, @code{calli} sequence.
-
-@item -mnormal
-@opindex mnormal
-Use the normal memory model: Generate @code{call} instructions only when
-calling functions in the same file and @code{calli} instructions
-otherwise. This works if each file occupies less than 256 KB but allows
-the entire executable to be larger than 256 KB@. This is the default.
-
-@item -mlarge
-@opindex mlarge
-Always use @code{calli} instructions. Specify this option if you expect
-a single file to compile into more than 256 KB of code.
-
-@item -m29050
-@opindex m29050
-@cindex processor selection (29k)
-Generate code for the Am29050.
-
-@item -m29000
-@opindex m29000
-Generate code for the Am29000. This is the default.
-
-@item -mkernel-registers
-@opindex mkernel-registers
-@cindex kernel and user registers (29k)
-Generate references to registers @code{gr64-gr95} instead of to
-registers @code{gr96-gr127}. This option can be used when compiling
-kernel code that wants a set of global registers disjoint from that used
-by user-mode code.
-
-Note that when this option is used, register names in @samp{-f} flags
-must use the normal, user-mode, names.
-
-@item -muser-registers
-@opindex muser-registers
-Use the normal set of global registers, @code{gr96-gr127}. This is the
-default.
-
-@item -mstack-check
-@itemx -mno-stack-check
-@opindex mstack-check
-@opindex mno-stack-check
-@cindex stack checks (29k)
-Insert (or do not insert) a call to @code{__msp_check} after each stack
-adjustment. This is often used for kernel code.
-
-@item -mstorem-bug
-@itemx -mno-storem-bug
-@opindex mstorem-bug
-@opindex mno-storem-bug
-@cindex storem bug (29k)
-@option{-mstorem-bug} handles 29k processors which cannot handle the
-separation of a mtsrim insn and a storem instruction (most 29000 chips
-to date, but not the 29050).
-
-@item -mno-reuse-arg-regs
-@itemx -mreuse-arg-regs
-@opindex mno-reuse-arg-regs
-@opindex mreuse-arg-regs
-@option{-mno-reuse-arg-regs} tells the compiler to only use incoming argument
-registers for copying out arguments. This helps detect calling a function
-with fewer arguments than it was declared with.
-
-@item -mno-impure-text
-@itemx -mimpure-text
-@opindex mno-impure-text
-@opindex mimpure-text
-@option{-mimpure-text}, used in addition to @option{-shared}, tells the compiler to
-not pass @option{-assert pure-text} to the linker when linking a shared object.
-
-@item -msoft-float
-@opindex msoft-float
-Generate output containing library calls for floating point.
-@strong{Warning:} the requisite libraries are not part of GCC@.
-Normally the facilities of the machine's usual C compiler are used, but
-this can't be done directly in cross-compilation. You must make your
-own arrangements to provide suitable library functions for
-cross-compilation.
-
-@item -mno-multm
-@opindex mno-multm
-Do not generate multm or multmu instructions. This is useful for some embedded
-systems which do not have trap handlers for these instructions.
-@end table
-
@node ARM Options
@subsection ARM Options
@cindex ARM options
@@ -5803,7 +6066,7 @@ memory a feature of the ARM architecture allows a word load to be used,
even if the address is unaligned, and the processor core will rotate the
data as it is being loaded. This option tells the compiler that such
misaligned accesses will cause a MMU trap and that it should instead
-synthesise the access as a series of byte accesses. The compiler can
+synthesize the access as a series of byte accesses. The compiler can
still use word accesses to load half-word data if it knows that the
address is aligned to a word boundary.
@@ -5838,25 +6101,6 @@ These are deprecated aliases for @option{-malignment-traps}.
@opindex mshort-load-words
This are deprecated aliases for @option{-mno-alignment-traps}.
-@item -mbsd
-@opindex mbsd
-This option only applies to RISC iX@. Emulate the native BSD-mode
-compiler. This is the default if @option{-ansi} is not specified.
-
-@item -mxopen
-@opindex mxopen
-This option only applies to RISC iX@. Emulate the native X/Open-mode
-compiler.
-
-@item -mno-symrename
-@opindex mno-symrename
-This option only applies to RISC iX@. Do not run the assembler
-post-processor, @samp{symrename}, after code has been assembled.
-Normally it is necessary to modify some of the standard symbols in
-preparation for linking with the RISC iX C library; this option
-suppresses this pass. The post-processor is never run when the
-compiler is built for cross-compilation.
-
@item -mcpu=@var{name}
@opindex mcpu
This specifies the name of the target ARM processor. GCC uses this name
@@ -6021,6 +6265,7 @@ of executing a function pointer if this option is enabled.
@node MN10200 Options
@subsection MN10200 Options
@cindex MN10200 options
+
These @option{-m} options are defined for Matsushita MN10200 architectures:
@table @gcctabopt
@@ -6036,6 +6281,7 @@ This option makes symbolic debugging impossible.
@node MN10300 Options
@subsection MN10300 Options
@cindex MN10300 options
+
These @option{-m} options are defined for Matsushita MN10300 architectures:
@table @gcctabopt
@@ -6198,9 +6444,9 @@ underscore as prefix on each name.
Include (or omit) additional debugging information (about registers used
in each stack frame) as specified in the 88open Object Compatibility
Standard, ``OCS''@. This extra information allows debugging of code that
-has had the frame pointer eliminated. The default for DG/UX, SVr4, and
-Delta 88 SVr3.2 is to include this information; other 88k configurations
-omit this information by default.
+has had the frame pointer eliminated. The default for SVr4 and Delta 88
+SVr3.2 is to include this information; other 88k configurations omit this
+information by default.
@item -mocs-frame-position
@opindex mocs-frame-position
@@ -6208,7 +6454,7 @@ omit this information by default.
When emitting COFF debugging information for automatic variables and
parameters stored on the stack, use the offset from the canonical frame
address, which is the stack pointer (register 31) on entry to the
-function. The DG/UX, SVr4, Delta88 SVr3.2, and BCS configurations use
+function. The SVr4 and Delta88 SVr3.2, and BCS configurations use
@option{-mocs-frame-position}; other 88k configurations have the default
@option{-mno-ocs-frame-position}.
@@ -6295,9 +6541,8 @@ that is used on System V release 4.
SVr4.
@end enumerate
-@option{-msvr4} is the default for the m88k-motorola-sysv4 and
-m88k-dg-dgux m88k configurations. @option{-msvr3} is the default for all
-other m88k configurations.
+@option{-msvr4} is the default for the m88k-motorola-sysv4 configuration.
+@option{-msvr3} is the default for all other m88k configurations.
@item -mversion-03.00
@opindex mversion-03.00
@@ -6503,7 +6748,7 @@ The @option{-mcpu} options automatically enable or disable other
@table @samp
@item common
-@option{-mno-power}, @option{-mno-powerc}
+@option{-mno-power}, @option{-mno-powerpc}
@item power
@itemx power2
@@ -6555,6 +6800,21 @@ allow access to the AltiVec instruction set. You may also need to set
@option{-mabi=altivec} to adjust the current ABI with AltiVec ABI
enhancements.
+@item -mabi=spe
+@opindex mabi=spe
+Extend the current ABI with SPE ABI extensions. This does not change
+the default ABI, instead it adds the SPE ABI extensions to the current
+ABI@.
+
+@item -mabi=no-spe
+@opindex mabi=no-spe
+Disable Booke SPE ABI extensions for the current ABI.
+
+@item -misel=@var{yes/no}
+@itemx -misel
+@opindex misel
+This switch enables or disables the generation of ISEL instructions.
+
@item -mfull-toc
@itemx -mno-fp-in-toc
@itemx -mno-sum-in-toc
@@ -6844,6 +7104,10 @@ On embedded PowerPC systems, assume that the startup module is called
On System V.4 and embedded PowerPC systems, specify that you are
compiling for a VxWorks system.
+@item -mwindiss
+@opindex mwindiss
+Specify that you are compiling for the WindISS simulation environment.
+
@item -memb
@opindex memb
On embedded PowerPC systems, set the @var{PPC_EMB} bit in the ELF flags
@@ -6928,6 +7192,24 @@ All modules should be compiled with the same @option{-G @var{num}} value.
On System V.4 and embedded PowerPC systems do (do not) emit register
names in the assembly language output using symbolic forms.
+@item -mlongcall
+@itemx -mno-longcall
+@opindex mlongcall
+@opindex mno-longcall
+Default to making all function calls via pointers, so that functions
+which reside further than 64 megabytes (67,108,864 bytes) from the
+current location can be called. This setting can be overridden by the
+@code{shortcall} function attribute, or by @code{#pragma longcall(0)}.
+
+Some linkers are capable of detecting out-of-range calls and generating
+glue code on the fly. On these systems, long calls are unnecessary and
+generate slower code. As of this writing, the AIX linker can do this,
+as can the GNU linker for PowerPC/64. It is planned to add this feature
+to the GNU linker for 32-bit PowerPC systems as well.
+
+In the future, we may cause GCC to ignore all longcall specifications
+when the linker is known to generate glue.
+
@item -pthread
@opindex pthread
Adds support for multithreading with the @dfn{pthreads} library.
@@ -6935,6 +7217,157 @@ This option sets flags for both the preprocessor and linker.
@end table
+@node Darwin Options
+@subsection Darwin Options
+@cindex Darwin options
+
+These options are defined for all architectures running the Darwin operating
+system. These are useful for compatibility with other Mac OS compilers.
+
+@table @gcctabopt
+@item -all_load
+@opindex all_load
+Loads all members of static archive libraries.
+See man ld(1) for more information.
+
+@item -arch_errors_fatal
+@opindex arch_errors_fatal
+Cause the errors having to do with files that have the wrong architecture
+to be fatal.
+
+@item -bind_at_load
+@opindex bind_at_load
+Causes the output file to be marked such that the dynamic linker will
+bind all undefined references when the file is loaded or launched.
+
+@item -bundle
+@opindex bundle
+Produce a Mach-o bundle format file.
+See man ld(1) for more information.
+
+@item -bundle_loader @var{executable}
+@opindex bundle_loader
+This specifies the @var{executable} that will be loading the build
+output file being linked. See man ld(1) for more information.
+
+@item -allowable_client @var{client_name}
+@item -arch_only
+
+@item -client_name
+@item -compatibility_version
+@item -current_version
+@item -dependency-file
+@item -dylib_file
+@item -dylinker_install_name
+@item -dynamic
+@item -dynamiclib
+@item -exported_symbols_list
+@item -filelist
+@item -flat_namespace
+@item -force_cpusubtype_ALL
+@item -force_flat_namespace
+@item -headerpad_max_install_names
+@item -image_base
+@item -init
+@item -install_name
+@item -keep_private_externs
+@item -multi_module
+@item -multiply_defined
+@item -multiply_defined_unused
+@item -noall_load
+@item -nomultidefs
+@item -noprebind
+@item -noseglinkedit
+@item -pagezero_size
+@item -prebind
+@item -prebind_all_twolevel_modules
+@item -private_bundle
+@item -read_only_relocs
+@item -sectalign
+@item -sectobjectsymbols
+@item -whyload
+@item -seg1addr
+@item -sectcreate
+@item -sectobjectsymbols
+@item -sectorder
+@item -seg_addr_table
+@item -seg_addr_table_filename
+@item -seglinkedit
+@item -segprot
+@item -segs_read_only_addr
+@item -segs_read_write_addr
+@item -single_module
+@item -static
+@item -sub_library
+@item -sub_umbrella
+@item -twolevel_namespace
+@item -umbrella
+@item -undefined
+@item -unexported_symbols_list
+@item -weak_reference_mismatches
+@item -whatsloaded
+
+@opindex allowable_client
+@opindex arch_only
+@opindex client_name
+@opindex compatibility_version
+@opindex current_version
+@opindex dependency-file
+@opindex dylib_file
+@opindex dylinker_install_name
+@opindex dynamic
+@opindex dynamiclib
+@opindex exported_symbols_list
+@opindex filelist
+@opindex flat_namespace
+@opindex force_cpusubtype_ALL
+@opindex force_flat_namespace
+@opindex headerpad_max_install_names
+@opindex image_base
+@opindex init
+@opindex install_name
+@opindex keep_private_externs
+@opindex multi_module
+@opindex multiply_defined
+@opindex multiply_defined_unused
+@opindex noall_load
+@opindex nomultidefs
+@opindex noprebind
+@opindex noseglinkedit
+@opindex pagezero_size
+@opindex prebind
+@opindex prebind_all_twolevel_modules
+@opindex private_bundle
+@opindex read_only_relocs
+@opindex sectalign
+@opindex sectobjectsymbols
+@opindex whyload
+@opindex seg1addr
+@opindex sectcreate
+@opindex sectobjectsymbols
+@opindex sectorder
+@opindex seg_addr_table
+@opindex seg_addr_table_filename
+@opindex seglinkedit
+@opindex segprot
+@opindex segs_read_only_addr
+@opindex segs_read_write_addr
+@opindex single_module
+@opindex static
+@opindex sub_library
+@opindex sub_umbrella
+@opindex twolevel_namespace
+@opindex umbrella
+@opindex undefined
+@opindex unexported_symbols_list
+@opindex weak_reference_mismatches
+@opindex whatsloaded
+
+This options are available for Darwin linker. Darwin linker man page
+describes them in detail.
+@end table
+
+
@node RT Options
@subsection IBM RT Options
@cindex RT options
@@ -6963,14 +7396,13 @@ Do not include extra scratch space in floating point data blocks. This
results in smaller code, but slower execution, since scratch space must
be allocated dynamically.
-@cindex @file{varargs.h} and RT PC
@cindex @file{stdarg.h} and RT PC
@item -mfp-arg-in-fpregs
@opindex mfp-arg-in-fpregs
Use a calling sequence incompatible with the IBM calling convention in
which floating point arguments are passed in floating point registers.
-Note that @code{varargs.h} and @code{stdarg.h} will not work with
-floating point operands if this option is specified.
+Note that @code{stdarg.h} will not work with floating point operands
+if this option is specified.
@item -mfp-arg-in-gregs
@opindex mfp-arg-in-gregs
@@ -7000,65 +7432,77 @@ These @samp{-m} options are defined for the MIPS family of computers:
@table @gcctabopt
-@item -march=@var{cpu-type}
+@item -march=@var{arch}
@opindex march
-Assume the defaults for the machine type @var{cpu-type} when generating
-instructions. The choices for @var{cpu-type} are @samp{r2000}, @samp{r3000},
-@samp{r3900}, @samp{r4000}, @samp{r4100}, @samp{r4300}, @samp{r4400},
-@samp{r4600}, @samp{r4650}, @samp{r5000}, @samp{r6000}, @samp{r8000},
-and @samp{orion}. Additionally, the @samp{r2000}, @samp{r3000},
-@samp{r4000}, @samp{r5000}, and @samp{r6000} can be abbreviated as
-@samp{r2k} (or @samp{r2K}), @samp{r3k}, etc.
-
-@item -mtune=@var{cpu-type}
+Generate code that will run on @var{arch}, which can be the name of a
+generic MIPS ISA, or the name of a particular processor. The ISA names
+are: @samp{mips1}, @samp{mips2}, @samp{mips3}, @samp{mips4}, @samp{mips32}
+and @samp{mips64}. The processor names are: @samp{r2000},
+@samp{r3000}, @samp{r3900}, @samp{r4000}, @samp{vr4100}, @samp{vr4300},
+@samp{r4400}, @samp{r4600}, @samp{r4650}, @samp{vr5000}, @samp{r6000},
+@samp{r8000}, @samp{4kc}, @samp{4kp}, @samp{5kc}, @samp{20kc},
+@samp{orion}, and @samp{sb1}. The special value @samp{from-abi} selects the
+most compatible architecture for the selected ABI (that is,
+@samp{mips1} for 32-bit ABIs and @samp{mips3} for 64-bit ABIs)@.
+
+In processor names, a final @samp{000} can be abbreviated as @samp{k}
+(for example, @samp{-march=r2k}). Prefixes are optional, and
+@samp{vr} may be written @samp{r}.
+
+GCC defines two macros based on the value of this option. The first
+is @samp{_MIPS_ARCH}, which gives the name of target architecture, as
+a string. The second has the form @samp{_MIPS_ARCH_@var{foo}},
+where @var{foo} is the capitalized value of @samp{_MIPS_ARCH}@.
+For example, @samp{-march=r2000} will set @samp{_MIPS_ARCH}
+to @samp{"r2000"} and define the macro @samp{_MIPS_ARCH_R2000}.
+
+Note that the @samp{_MIPS_ARCH} macro uses the processor names given
+above. In other words, it will have the full prefix and will not
+abbreviate @samp{000} as @samp{k}. In the case of @samp{from-abi},
+the macro names the resolved architecture (either @samp{"mips1"} or
+@samp{"mips3"}). It names the default architecture when no
+@option{-march} option is given.
+
+@item -mtune=@var{arch}
@opindex mtune
-Assume the defaults for the machine type @var{cpu-type} when scheduling
-instructions. The choices for @var{cpu-type} are @samp{r2000}, @samp{r3000},
-@samp{r3900}, @samp{r4000}, @samp{r4100}, @samp{r4300}, @samp{r4400},
-@samp{r4600}, @samp{r4650}, @samp{r5000}, @samp{r6000}, @samp{r8000},
-and @samp{orion}. Additionally, the @samp{r2000}, @samp{r3000},
-@samp{r4000}, @samp{r5000}, and @samp{r6000} can be abbreviated as
-@samp{r2k} (or @samp{r2K}), @samp{r3k}, etc. While picking a specific
-@var{cpu-type} will schedule things appropriately for that particular
-chip, the compiler will not generate any code that does not meet level 1
-of the MIPS ISA (instruction set architecture) without a @option{-mipsX}
-or @option{-mabi} switch being used.
+Optimize for @var{arch}. Among other things, this option controls
+the way instructions are scheduled, and the perceived cost of arithmetic
+operations. The list of @var{arch} values is the same as for
+@option{-march}.
-@item -mcpu=@var{cpu-type}
-@opindex mcpu
-This is identical to specifying both @option{-march} and @option{-mtune}.
+When this option is not used, GCC will optimize for the processor
+specified by @option{-march}. By using @option{-march} and
+@option{-mtune} together, it is possible to generate code that will
+run on a family of processors, but optimize the code for one
+particular member of that family.
+
+@samp{-mtune} defines the macros @samp{_MIPS_TUNE} and
+@samp{_MIPS_TUNE_@var{foo}}, which work in the same way as the
+@samp{-march} ones described above.
@item -mips1
@opindex mips1
-Issue instructions from level 1 of the MIPS ISA@. This is the default.
-@samp{r3000} is the default @var{cpu-type} at this ISA level.
+Equivalent to @samp{-march=mips1}.
@item -mips2
@opindex mips2
-Issue instructions from level 2 of the MIPS ISA (branch likely, square
-root instructions). @samp{r6000} is the default @var{cpu-type} at this
-ISA level.
+Equivalent to @samp{-march=mips2}.
@item -mips3
@opindex mips3
-Issue instructions from level 3 of the MIPS ISA (64-bit instructions).
-@samp{r4000} is the default @var{cpu-type} at this ISA level.
+Equivalent to @samp{-march=mips3}.
@item -mips4
@opindex mips4
-Issue instructions from level 4 of the MIPS ISA (conditional move,
-prefetch, enhanced FPU instructions). @samp{r8000} is the default
-@var{cpu-type} at this ISA level.
+Equivalent to @samp{-march=mips4}.
-@item -mfp32
-@opindex mfp32
-Assume that 32 32-bit floating point registers are available. This is
-the default.
+@item -mips32
+@opindex mips32
+Equivalent to @samp{-march=mips32}.
-@item -mfp64
-@opindex mfp64
-Assume that 32 64-bit floating point registers are available. This is
-the default when the @option{-mips3} option is used.
+@item -mips64
+@opindex mips64
+Equivalent to @samp{-march=mips64}.
@item -mfused-madd
@itemx -mno-fused-madd
@@ -7072,15 +7516,21 @@ in the mode where denormals are rounded to zero where denormals
generated by multiply and accumulate instructions cause exceptions
anyway.
+@item -mfp32
+@opindex mfp32
+Assume that floating point registers are 32 bits wide.
+
+@item -mfp64
+@opindex mfp64
+Assume that floating point registers are 64 bits wide.
+
@item -mgp32
@opindex mgp32
-Assume that 32 32-bit general purpose registers are available. This is
-the default.
+Assume that general purpose registers are 32 bits wide.
@item -mgp64
@opindex mgp64
-Assume that 32 64-bit general purpose registers are available. This is
-the default when the @option{-mips3} option is used.
+Assume that general purpose registers are 64 bits wide.
@item -mint64
@opindex mint64
@@ -7096,31 +7546,32 @@ explanation of the default, and the width of pointers.
@opindex mlong32
Force long, int, and pointer types to be 32 bits wide.
-If none of @option{-mlong32}, @option{-mlong64}, or @option{-mint64} are set,
-the size of ints, longs, and pointers depends on the ABI and ISA chosen.
-For @option{-mabi=32}, and @option{-mabi=n32}, ints and longs are 32 bits
-wide. For @option{-mabi=64}, ints are 32 bits, and longs are 64 bits wide.
-For @option{-mabi=eabi} and either @option{-mips1} or @option{-mips2}, ints
-and longs are 32 bits wide. For @option{-mabi=eabi} and higher ISAs, ints
-are 32 bits, and longs are 64 bits wide. The width of pointer types is
-the smaller of the width of longs or the width of general purpose
-registers (which in turn depends on the ISA)@.
+The default size of ints, longs and pointers depends on the ABI@. All
+the supported ABIs use 32-bit ints. The n64 ABI uses 64-bit longs, as
+does the 64-bit Cygnus EABI; the others use 32-bit longs. Pointers
+are the same size as longs, or the same size as integer registers,
+whichever is smaller.
@item -mabi=32
@itemx -mabi=o64
@itemx -mabi=n32
@itemx -mabi=64
@itemx -mabi=eabi
+@itemx -mabi=meabi
@opindex mabi=32
@opindex mabi=o64
@opindex mabi=n32
@opindex mabi=64
@opindex mabi=eabi
-Generate code for the indicated ABI@. The default instruction level is
-@option{-mips1} for @samp{32}, @option{-mips3} for @samp{n32}, and
-@option{-mips4} otherwise. Conversely, with @option{-mips1} or
-@option{-mips2}, the default ABI is @samp{32}; otherwise, the default ABI
-is @samp{64}.
+@opindex mabi=meabi
+Generate code for the given ABI@.
+
+Note that there are two embedded ABIs: @option{-mabi=eabi}
+selects the one defined by Cygnus while @option{-meabi=meabi}
+selects the one defined by MIPS@. Both these ABIs have
+32-bit and 64-bit variants. Normally, GCC will generate
+64-bit code when you select a 64-bit architecture, but you
+can use @option{-mgp32} to get 32-bit code instead.
@item -mmips-as
@opindex mmips-as
@@ -7343,12 +7794,19 @@ memory range for which the cache is being flushed, the size of the
memory range, and the number 3 (to flush both caches). The default
depends on the target gcc was configured for, but commonly is either
@samp{_flush_func} or @samp{__cpu_flush}.
-@end table
-These options are defined by the macro
-@code{TARGET_SWITCHES} in the machine description. The default for the
-options is also defined by that macro, which enables you to change the
-defaults.
+@item -mbranch-likely
+@itemx -mno-branch-likely
+@opindex mbranch-likely
+@opindex mno-branch-likely
+Enable or disable use of Branch Likely instructions, regardless of the
+default for the selected architecture. By default, Branch Likely
+instructions may be generated if they are supported by the selected
+architecture. An exception is for the MIPS32 and MIPS64 architectures
+and processors which implement those architectures; for those, Branch
+Likely instructions will not be generated by default because the MIPS32
+and MIPS64 architectures specifically deprecate their use.
+@end table
@node i386 and x86-64 Options
@subsection Intel 386 and AMD x86-64 Options
@@ -7368,8 +7826,8 @@ for the ABI and the set of available instructions. The choices for
@var{cpu-type} are @samp{i386}, @samp{i486}, @samp{i586}, @samp{i686},
@samp{pentium}, @samp{pentium-mmx}, @samp{pentiumpro}, @samp{pentium2},
@samp{pentium3}, @samp{pentium4}, @samp{k6}, @samp{k6-2}, @samp{k6-3},
-@samp{athlon}, @samp{athlon-tbird}, @samp{athlon-4}, @samp{athlon-xp}
-and @samp{athlon-mp}.
+@samp{athlon}, @samp{athlon-tbird}, @samp{athlon-4}, @samp{athlon-xp},
+@samp{athlon-mp}, @samp{winchip-c6}, @samp{winchip2} and @samp{c3}.
While picking a specific @var{cpu-type} will schedule things appropriately
for that particular chip, the compiler will not generate any code that
@@ -7405,7 +7863,7 @@ for @var{unit} are:
@item 387
Use the standard 387 floating point coprocessor present majority of chips and
emulated otherwise. Code compiled with this option will run almost everywhere.
-The temporary results are computed in 80bit precesion instead of precision
+The temporary results are computed in 80bit precision instead of precision
specified by the type resulting in slightly different results compared to most
of other chips. See @option{-ffloat-store} for more detailed description.
@@ -7431,7 +7889,7 @@ code that expects temporaries to be 80bit.
This is the default choice for x86-64 compiler.
@item sse,387
-Attempt to utilize both instruction sets at once. This effectivly double the
+Attempt to utilize both instruction sets at once. This effectively double the
amount of available registers and on chips with separate execution units for
387 and SSE the execution resources too. Use this option with care, as it is
still experimental, because gcc register allocator does not model separate
@@ -7614,8 +8072,8 @@ direct access to the MMX, SSE and 3Dnow extensions of the instruction set.
@xref{X86 Built-in Functions}, for details of the functions enabled
and disabled by these switches.
-To have SSE/SSE2 instructions generated automatically from floating-point code,
-see @option{-mfpmath=sse}.
+To have SSE/SSE2 instructions generated automatically from floating-point
+code, see @option{-mfpmath=sse}.
@item -mpush-args
@itemx -mno-push-args
@@ -7799,15 +8257,16 @@ Enable the use of assembler directives only GAS understands.
@opindex mschedule
Schedule code according to the constraints for the machine type
@var{cpu-type}. The choices for @var{cpu-type} are @samp{700}
-@samp{7100}, @samp{7100LC}, @samp{7200}, and @samp{8000}. Refer to
-@file{/usr/lib/sched.models} on an HP-UX system to determine the
-proper scheduling option for your machine.
+@samp{7100}, @samp{7100LC}, @samp{7200}, @samp{7300} and @samp{8000}. Refer
+to @file{/usr/lib/sched.models} on an HP-UX system to determine the
+proper scheduling option for your machine. The default scheduling is
+@samp{8000}.
@item -mlinker-opt
@opindex mlinker-opt
-Enable the optimization pass in the HPUX linker. Note this makes symbolic
-debugging impossible. It also triggers a bug in the HPUX 8 and HPUX 9 linkers
-in which they give bogus error messages when linking some programs.
+Enable the optimization pass in the HP-UX linker. Note this makes symbolic
+debugging impossible. It also triggers a bug in the HP-UX 8 and HP-UX 9
+linkers in which they give bogus error messages when linking some programs.
@item -msoft-float
@opindex msoft-float
@@ -7824,6 +8283,88 @@ therefore, it is only useful if you compile @emph{all} of a program with
this option. In particular, you need to compile @file{libgcc.a}, the
library that comes with GCC, with @option{-msoft-float} in order for
this to work.
+
+@item -msio
+@opindex msio
+Generate the predefine, @code{_SIO}, for server IO. The default is
+@option{-mwsio}. This generates the predefines, @code{__hp9000s700},
+@code{__hp9000s700__} and @code{_WSIO}, for workstation IO. These
+options are available under HP-UX and HI-UX.
+
+@item -mgnu-ld
+@opindex gnu-ld
+Use GNU ld specific options. This passes @option{-shared} to ld when
+building a shared library. It is the default when GCC is configured,
+explicitly or implicitly, with the GNU linker. This option does not
+have any affect on which ld is called, it only changes what parameters
+are passed to that ld. The ld that is called is determined by the
+@option{--with-ld} configure option, gcc's program search path, and
+finally by the user's @env{PATH}. The linker used by GCC can be printed
+using @samp{which `gcc -print-prog-name=ld`}.
+
+@item -mhp-ld
+@opindex hp-ld
+Use HP ld specific options. This passes @option{-b} to ld when building
+a shared library and passes @option{+Accept TypeMismatch} to ld on all
+links. It is the default when GCC is configured, explicitly or
+implicitly, with the HP linker. This option does not have any affect on
+which ld is called, it only changes what parameters are passed to that
+ld. The ld that is called is determined by the @option{--with-ld}
+configure option, gcc's program search path, and finally by the user's
+@env{PATH}. The linker used by GCC can be printed using @samp{which
+`gcc -print-prog-name=ld`}.
+
+@item -mlong-calls
+@opindex mno-long-calls
+Generate code that uses long call sequences. This ensures that a call
+is always able to reach linker generated stubs. The default is to generate
+long calls only when the distance from the call site to the beginning
+of the function or translation unit, as the case may be, exceeds a
+predefined limit set by the branch type being used. The limits for
+normal calls are 7,600,000 and 240,000 bytes, respectively for the
+PA 2.0 and PA 1.X architectures. Sibcalls are always limited at
+240,000 bytes.
+
+Distances are measured from the beginning of functions when using the
+@option{-ffunction-sections} option, or when using the @option{-mgas}
+and @option{-mno-portable-runtime} options together under HP-UX with
+the SOM linker.
+
+It is normally not desirable to use this option as it will degrade
+performance. However, it may be useful in large applications,
+particularly when partial linking is used to build the application.
+
+The types of long calls used depends on the capabilities of the
+assembler and linker, and the type of code being generated. The
+impact on systems that support long absolute calls, and long pic
+symbol-difference or pc-relative calls should be relatively small.
+However, an indirect call is used on 32-bit ELF systems in pic code
+and it is quite long.
+
+@item -nolibdld
+@opindex nolibdld
+Suppress the generation of link options to search libdld.sl when the
+@option{-static} option is specified on HP-UX 10 and later.
+
+@item -static
+@opindex static
+The HP-UX implementation of setlocale in libc has a dependency on
+libdld.sl. There isn't an archive version of libdld.sl. Thus,
+when the @option{-static} option is specified, special link options
+are needed to resolve this dependency.
+
+On HP-UX 10 and later, the GCC driver adds the necessary options to
+link with libdld.sl when the @option{-static} option is specified.
+This causes the resulting binary to be dynamic. On the 64-bit port,
+the linkers generate dynamic binaries by default in any case. The
+@option{-nolibdld} option can be used to prevent the GCC driver from
+adding these link options.
+
+@item -threads
+@opindex threads
+Add support for multithreading with the @dfn{dce thread} library
+under HP-UX. This option sets flags for both the preprocessor and
+linker.
@end table
@node Intel 960 Options
@@ -8143,7 +8684,7 @@ arithmetic instead of IEEE single and double precision.
@opindex mno-explicit-relocs
Older Alpha assemblers provided no way to generate symbol relocations
except via assembler macros. Use of these macros does not allow
-optimial instruction scheduling. GNU binutils as of version 2.12
+optimal instruction scheduling. GNU binutils as of version 2.12
supports a new syntax that allows the compiler to explicitly mark
which relocations should apply to which instructions. This option
is mostly useful for debugging, as GCC detects the capabilities of
@@ -8251,22 +8792,6 @@ Return VMS condition codes from main. The default is to return POSIX
style condition (e.g.@ error) codes.
@end table
-@node Clipper Options
-@subsection Clipper Options
-
-These @samp{-m} options are defined for the Clipper implementations:
-
-@table @gcctabopt
-@item -mc300
-@opindex mc300
-Produce code for a C300 Clipper processor. This is the default.
-
-@item -mc400
-@opindex mc400
-Produce code for a C400 Clipper processor, i.e.@: use floating point
-registers f8--f15.
-@end table
-
@node H8/300 Options
@subsection H8/300 Options
@@ -8285,11 +8810,16 @@ Generate code for the H8/300H@.
@item -ms
@opindex ms
-Generate code for the H8/S@.
+Generate code for the H8S@.
+
+@item -mn
+@opindex mn
+Generate code for the H8S and H8/300H in the normal mode. This switch
+must be used either with -mh or -ms.
@item -ms2600
@opindex ms2600
-Generate code for the H8/S2600. This switch must be used with @option{-ms}.
+Generate code for the H8S/2600. This switch must be used with @option{-ms}.
@item -mint32
@opindex mint32
@@ -8297,8 +8827,8 @@ Make @code{int} data 32 bits by default.
@item -malign-300
@opindex malign-300
-On the H8/300H and H8/S, use the same alignment rules as for the H8/300.
-The default for the H8/300H and H8/S is to align longs and floats on 4
+On the H8/300H and H8S, use the same alignment rules as for the H8/300.
+The default for the H8/300H and H8S is to align longs and floats on 4
byte boundaries.
@option{-malign-300} causes them to be aligned on 2 byte boundaries.
This option has no effect on the H8/300.
@@ -8374,7 +8904,7 @@ Enable the use of the instruction @code{fmovd}.
@item -mhitachi
@opindex mhitachi
-Comply with the calling conventions defined by Hitachi.
+Comply with the calling conventions defined by Renesas.
@item -mnomacsave
@opindex mnomacsave
@@ -8493,10 +9023,10 @@ DBcond(D), instructions. This is enabled by default for the C4x. To be
on the safe side, this is disabled for the C3x, since the maximum
iteration count on the C3x is @math{2^{23} + 1} (but who iterates loops more than
@math{2^{23}} times on the C3x?). Note that GCC will try to reverse a loop so
-that it can utilise the decrement and branch instruction, but will give
+that it can utilize the decrement and branch instruction, but will give
up if there is more than one memory reference in the loop. Thus a loop
where the loop counter is decremented can generate slightly more
-efficient code, in cases where the RPTB instruction cannot be utilised.
+efficient code, in cases where the RPTB instruction cannot be utilized.
@item -mdp-isr-reload
@itemx -mparanoid
@@ -8663,6 +9193,34 @@ Specify that the target processor is the V850.
Generate code suitable for big switch tables. Use this option only if
the assembler/linker complain about out of range branches within a switch
table.
+
+@item -mapp-regs
+@opindex mapp-regs
+This option will cause r2 and r5 to be used in the code generated by
+the compiler. This setting is the default.
+
+@item -mno-app-regs
+@opindex mno-app-regs
+This option will cause r2 and r5 to be treated as fixed registers.
+
+@item -mv850e
+@opindex mv850e
+Specify that the target processor is the V850E. The preprocessor
+constant @samp{__v850e__} will be defined if this option is used.
+
+If neither @option{-mv850} nor @option{-mv850e} are defined
+then a default target processor will be chosen and the relevant
+@samp{__v850*__} preprocessor constant will be defined.
+
+The preprocessor constants @samp{__v850} and @samp{__v851__} are always
+defined, regardless of which processor variant is the target.
+
+@item -mdisable-callt
+@opindex mdisable-callt
+This option will suppress generation of the CALLT instruction for the
+v850e flavors of the v850 architecture. The default is
+@option{-mno-disable-callt} which allows the CALLT instruction to be used.
+
@end table
@node ARC Options
@@ -8769,6 +9327,15 @@ Do not try and generate multiply-add floating point instructions
Generate output containing library calls for floating point.
@strong{Warning:} the requisite libraries may not be available.
+@item -mieee-compare
+@itemx -mno-ieee-compare
+@opindex mieee-compare
+@opindex mno-ieee-compare
+Control whether or not the compiler uses IEEE floating point
+comparisons. These handle correctly the case where the result of a
+comparison is unordered.
+@strong{Warning:} the requisite kernel support may not be available.
+
@item -mnobitfield
@opindex mnobitfield
Do not use the bit-field instructions. On some machines it is faster to
@@ -8910,75 +9477,57 @@ processors.
@table @gcctabopt
@item -mhardlit
-@itemx -mhardlit
@itemx -mno-hardlit
@opindex mhardlit
-@opindex mhardlit
@opindex mno-hardlit
Inline constants into the code stream if it can be done in two
instructions or less.
@item -mdiv
-@itemx -mdiv
@itemx -mno-div
@opindex mdiv
-@opindex mdiv
@opindex mno-div
Use the divide instruction. (Enabled by default).
@item -mrelax-immediate
-@itemx -mrelax-immediate
@itemx -mno-relax-immediate
@opindex mrelax-immediate
-@opindex mrelax-immediate
@opindex mno-relax-immediate
Allow arbitrary sized immediates in bit operations.
@item -mwide-bitfields
-@itemx -mwide-bitfields
@itemx -mno-wide-bitfields
@opindex mwide-bitfields
-@opindex mwide-bitfields
@opindex mno-wide-bitfields
Always treat bit-fields as int-sized.
@item -m4byte-functions
-@itemx -m4byte-functions
@itemx -mno-4byte-functions
@opindex m4byte-functions
-@opindex m4byte-functions
@opindex mno-4byte-functions
Force all functions to be aligned to a four byte boundary.
@item -mcallgraph-data
-@itemx -mcallgraph-data
@itemx -mno-callgraph-data
@opindex mcallgraph-data
-@opindex mcallgraph-data
@opindex mno-callgraph-data
Emit callgraph information.
@item -mslow-bytes
-@itemx -mslow-bytes
@itemx -mno-slow-bytes
@opindex mslow-bytes
-@opindex mslow-bytes
@opindex mno-slow-bytes
Prefer word access when reading byte quantities.
@item -mlittle-endian
-@itemx -mlittle-endian
@itemx -mbig-endian
@opindex mlittle-endian
-@opindex mlittle-endian
@opindex mbig-endian
Generate code for a little endian target.
@item -m210
-@itemx -m210
@itemx -m340
@opindex m210
-@opindex m210
@opindex m340
Generate code for the 210 processor.
@end table
@@ -8992,7 +9541,7 @@ These are the @samp{-m} options defined for the Intel IA-64 architecture.
@table @gcctabopt
@item -mbig-endian
@opindex mbig-endian
-Generate code for a big endian target. This is the default for HPUX@.
+Generate code for a big endian target. This is the default for HP-UX@.
@item -mlittle-endian
@opindex mlittle-endian
@@ -9055,13 +9604,25 @@ useful when compiling kernel code.
Generate code that is self-relocatable. This implies @option{-mconstant-gp}.
This is useful when compiling firmware code.
-@item -minline-divide-min-latency
-@opindex minline-divide-min-latency
-Generate code for inline divides using the minimum latency algorithm.
+@item -minline-float-divide-min-latency
+@opindex minline-float-divide-min-latency
+Generate code for inline divides of floating point values
+using the minimum latency algorithm.
+
+@item -minline-float-divide-max-throughput
+@opindex minline-float-divide-max-throughput
+Generate code for inline divides of floating point values
+using the maximum throughput algorithm.
-@item -minline-divide-max-throughput
-@opindex minline-divide-max-throughput
-Generate code for inline divides using the maximum throughput algorithm.
+@item -minline-int-divide-min-latency
+@opindex minline-int-divide-min-latency
+Generate code for inline divides of integer values
+using the minimum latency algorithm.
+
+@item -minline-int-divide-max-throughput
+@opindex minline-int-divide-max-throughput
+Generate code for inline divides of integer values
+using the maximum throughput algorithm.
@item -mno-dwarf2-asm
@itemx -mdwarf2-asm
@@ -9175,7 +9736,7 @@ targets default to @option{-m64}.
@opindex mmvcle
@opindex mno-mvcle
Generate (or do not generate) code using the @code{mvcle} instruction
-to perform block moves. When @option{-mno-mvcle} is specifed,
+to perform block moves. When @option{-mno-mvcle} is specified,
use a @code{mvc} loop instead. This is the default.
@item -mdebug
@@ -9401,6 +9962,13 @@ to 255 from the value held in the register. The generally leads to short
and fast code, but the number of different data items that can be
addressed is limited. This means that a program that uses lots of static
data may require @option{-mno-base-addresses}.
+
+@item -msingle-exit
+@itemx -mno-single-exit
+@opindex msingle-exit
+@opindex mno-single-exit
+Force (do not force) generated code to have a single exit point in each
+function.
@end table
@node PDP-11 Options
@@ -9520,6 +10088,233 @@ These options are defined for Xstormy16:
Choose startup files and linker script suitable for the simulator.
@end table
+@node FRV Options
+@subsection FRV Options
+@cindex FRV Options
+
+@table @gcctabopt
+@item -mgpr-32
+@opindex mgpr-32
+
+Only use the first 32 general purpose registers.
+
+@item -mgpr-64
+@opindex mgpr-64
+
+Use all 64 general purpose registers.
+
+@item -mfpr-32
+@opindex mfpr-32
+
+Use only the first 32 floating point registers.
+
+@item -mfpr-64
+@opindex mfpr-64
+
+Use all 64 floating point registers
+
+@item -mhard-float
+@opindex mhard-float
+
+Use hardware instructions for floating point operations.
+
+@item -msoft-float
+@opindex msoft-float
+
+Use library routines for floating point operations.
+
+@item -malloc-cc
+@opindex malloc-cc
+
+Dynamically allocate condition code registers.
+
+@item -mfixed-cc
+@opindex mfixed-cc
+
+Do not try to dynamically allocate condition code registers, only
+use @code{icc0} and @code{fcc0}.
+
+@item -mdword
+@opindex mdword
+
+Change ABI to use double word insns.
+
+@item -mno-dword
+@opindex mno-dword
+
+Do not use double word instructions.
+
+@item -mdouble
+@opindex mdouble
+
+Use floating point double instructions.
+
+@item -mno-double
+@opindex mno-double
+
+Do not use floating point double instructions.
+
+@item -mmedia
+@opindex mmedia
+
+Use media instructions.
+
+@item -mno-media
+@opindex mno-media
+
+Do not use media instructions.
+
+@item -mmuladd
+@opindex mmuladd
+
+Use multiply and add/subtract instructions.
+
+@item -mno-muladd
+@opindex mno-muladd
+
+Do not use multiply and add/subtract instructions.
+
+@item -mlibrary-pic
+@opindex mlibrary-pic
+
+Enable PIC support for building libraries
+
+@item -macc-4
+@opindex macc-4
+
+Use only the first four media accumulator registers.
+
+@item -macc-8
+@opindex macc-8
+
+Use all eight media accumulator registers.
+
+@item -mpack
+@opindex mpack
+
+Pack VLIW instructions.
+
+@item -mno-pack
+@opindex mno-pack
+
+Do not pack VLIW instructions.
+
+@item -mno-eflags
+@opindex mno-eflags
+
+Do not mark ABI switches in e_flags.
+
+@item -mcond-move
+@opindex mcond-move
+
+Enable the use of conditional-move instructions (default).
+
+This switch is mainly for debugging the compiler and will likely be removed
+in a future version.
+
+@item -mno-cond-move
+@opindex mno-cond-move
+
+Disable the use of conditional-move instructions.
+
+This switch is mainly for debugging the compiler and will likely be removed
+in a future version.
+
+@item -mscc
+@opindex mscc
+
+Enable the use of conditional set instructions (default).
+
+This switch is mainly for debugging the compiler and will likely be removed
+in a future version.
+
+@item -mno-scc
+@opindex mno-scc
+
+Disable the use of conditional set instructions.
+
+This switch is mainly for debugging the compiler and will likely be removed
+in a future version.
+
+@item -mcond-exec
+@opindex mcond-exec
+
+Enable the use of conditional execution (default).
+
+This switch is mainly for debugging the compiler and will likely be removed
+in a future version.
+
+@item -mno-cond-exec
+@opindex mno-cond-exec
+
+Disable the use of conditional execution.
+
+This switch is mainly for debugging the compiler and will likely be removed
+in a future version.
+
+@item -mvliw-branch
+@opindex mvliw-branch
+
+Run a pass to pack branches into VLIW instructions (default).
+
+This switch is mainly for debugging the compiler and will likely be removed
+in a future version.
+
+@item -mno-vliw-branch
+@opindex mno-vliw-branch
+
+Do not run a pass to pack branches into VLIW instructions.
+
+This switch is mainly for debugging the compiler and will likely be removed
+in a future version.
+
+@item -mmulti-cond-exec
+@opindex mmulti-cond-exec
+
+Enable optimization of @code{&&} and @code{||} in conditional execution
+(default).
+
+This switch is mainly for debugging the compiler and will likely be removed
+in a future version.
+
+@item -mno-multi-cond-exec
+@opindex mno-multi-cond-exec
+
+Disable optimization of @code{&&} and @code{||} in conditional execution.
+
+This switch is mainly for debugging the compiler and will likely be removed
+in a future version.
+
+@item -mnested-cond-exec
+@opindex mnested-cond-exec
+
+Enable nested conditional execution optimizations (default).
+
+This switch is mainly for debugging the compiler and will likely be removed
+in a future version.
+
+@item -mno-nested-cond-exec
+@opindex mno-nested-cond-exec
+
+Disable nested conditional execution optimizations.
+
+This switch is mainly for debugging the compiler and will likely be removed
+in a future version.
+
+@item -mtomcat-stats
+@opindex mtomcat-stats
+
+Cause gas to print out tomcat statistics.
+
+@item -mcpu=@var{cpu}
+@opindex mcpu
+
+Select the processor type for which to generate code. Possible values are
+@samp{simple}, @samp{tomcat}, @samp{fr500}, @samp{fr400}, @samp{fr300},
+@samp{frv}.
+
+@end table
+
@node Xtensa Options
@subsection Xtensa Options
@cindex Xtensa Options
@@ -9709,6 +10504,18 @@ can figure out the other form by either removing @samp{no-} or adding
it.
@table @gcctabopt
+@item -fbounds-check
+@opindex fbounds-check
+For front-ends that support it, generate additional code to check that
+indices used to access arrays are within the declared range. This is
+currently only supported by the Java and Fortran 77 front-ends, where
+this option defaults to true and false respectively.
+
+@item -ftrapv
+@opindex ftrapv
+This option generates traps for signed overflow on addition, subtraction,
+multiplication operations.
+
@item -fexceptions
@opindex fexceptions
Enable exception handling. Generates extra code needed to propagate
@@ -9887,7 +10694,7 @@ loader is not part of GCC; it is part of the operating system). If
the GOT size for the linked executable exceeds a machine-specific
maximum size, you get an error message from the linker indicating that
@option{-fpic} does not work; in that case, recompile with @option{-fPIC}
-instead. (These maximums are 16k on the m88k, 8k on the Sparc, and 32k
+instead. (These maximums are 16k on the m88k, 8k on the SPARC, and 32k
on the m68k and RS/6000. The 386 has no such limit.)
Position-independent code requires special support, and therefore works
@@ -9900,7 +10707,7 @@ position-independent.
If supported for the target machine, emit position-independent code,
suitable for dynamic linking and avoiding any limit on the size of the
global offset table. This option makes a difference on the m68k, m88k,
-and the Sparc.
+and the SPARC.
Position-independent code requires special support, and therefore works
only on certain machines.
@@ -9955,7 +10762,7 @@ Pack all structure members together without holes.
@strong{Warning:} the @option{-fpack-struct} switch causes GCC to generate
code that is not binary compatible with code generated without that switch.
-Additionally, it makes the code suboptimial.
+Additionally, it makes the code suboptimal.
Use it to conform to a non-default application binary interface.
@item -finstrument-functions
@@ -10057,6 +10864,14 @@ is to help link with legacy assembly code.
generate code that is not binary compatible with code generated without that
switch. Use it to conform to a non-default application binary interface.
Not all targets provide complete support for this switch.
+
+@item -ftls-model=@var{model}
+Alter the thread-local storage model to be used (@pxref{Thread-Local}).
+The @var{model} argument should be one of @code{global-dynamic},
+@code{local-dynamic}, @code{initial-exec} or @code{local-exec}.
+
+The default without @option{-fpic} is @code{initial-exec}; with
+@option{-fpic} the default is @code{global-dynamic}.
@end table
@c man end
@@ -10066,7 +10881,6 @@ Not all targets provide complete support for this switch.
@cindex environment variables
@c man begin ENVIRONMENT
-
This section describes several environment variables that affect how GCC
operates. Some of them work by specifying directories or prefixes to use
when searching for various kinds of files. Some are used to specify other
@@ -10275,16 +11089,16 @@ prototype information about standard system functions. This option
applies only to @code{protoize}.
@item -c @var{compilation-options}
-Use @var{compilation-options} as the options when running @code{gcc} to
+Use @var{compilation-options} as the options when running @command{gcc} to
produce the @samp{.X} files. The special option @option{-aux-info} is
-always passed in addition, to tell @code{gcc} to write a @samp{.X} file.
+always passed in addition, to tell @command{gcc} to write a @samp{.X} file.
Note that the compilation options must be given as a single argument to
@code{protoize} or @code{unprotoize}. If you want to specify several
-@code{gcc} options, you must quote the entire set of compilation options
+@command{gcc} options, you must quote the entire set of compilation options
to make them a single word in the shell.
-There are certain @code{gcc} arguments that you cannot use, because they
+There are certain @command{gcc} arguments that you cannot use, because they
would produce the wrong kind of output. These include @option{-g},
@option{-O}, @option{-c}, @option{-S}, and @option{-o} If you include these in
the @var{compilation-options}, they are ignored.
@@ -10337,12 +11151,12 @@ Use the program @var{program} as the compiler. Normally, the name
Work quietly. Most warnings are suppressed.
@item -v
-Print the version number, just like @option{-v} for @code{gcc}.
+Print the version number, just like @option{-v} for @command{gcc}.
@end table
If you need special compiler options to compile one of your program's
source files, then you should generate that file's @samp{.X} file
-specially, by running @code{gcc} on that source file with the
+specially, by running @command{gcc} on that source file with the
appropriate options and the option @option{-aux-info}. Then run
@code{protoize} on the entire set of files. @code{protoize} will use
the existing @samp{.X} file because it is newer than the source file.
diff --git a/contrib/gcc/doc/makefile.texi b/contrib/gcc/doc/makefile.texi
index 6d6b025..1e64c5e 100644
--- a/contrib/gcc/doc/makefile.texi
+++ b/contrib/gcc/doc/makefile.texi
@@ -13,18 +13,18 @@ This is the default target. Depending on what your build/host/target
configuration is, it coordinates all the things that need to be built.
@item doc
-Produce info-formatted documentation. Also, @code{make dvi} is
-available for DVI-formatted documentation, and @code{make
+Produce info-formatted documentation. Also, @samp{make dvi} is
+available for DVI-formatted documentation, and @samp{make
generated-manpages} to generate man pages.
@item mostlyclean
Delete the files made while building the compiler.
@item clean
-That, and all the other files built by @code{make all}.
+That, and all the other files built by @samp{make all}.
@item distclean
-That, and all the files created by @code{configure}.
+That, and all the files created by @command{configure}.
@item extraclean
That, and any temporary or intermediate files, like emacs backup files.
@@ -43,7 +43,7 @@ Deletes installed files.
@item check
Run the testsuite. This creates a @file{testsuite} subdirectory that
has various @file{.sum} and @file{.log} files containing the results of
-the testing. You can run subsets with, for example, @code{make check-gcc}.
+the testing. You can run subsets with, for example, @samp{make check-gcc}.
You can specify specific tests by setting RUNTESTFLAGS to be the name
of the @file{.exp} file, optionally followed by (for some tests) an equals
and a file wildcard, like:
@@ -59,7 +59,7 @@ installed, such as TCL or dejagnu.
Builds gcc three times---once with the native compiler, once with the
native-built compiler it just built, and once with the compiler it built
the second time. In theory, the last two should produce the same
-results, which @code{make compare} can check. Each step of this process
+results, which @samp{make compare} can check. Each step of this process
is called a ``stage'', and the results of each stage @var{N}
(@var{N} = 1@dots{}3) are copied to a subdirectory @file{stage@var{N}/}.
@@ -81,7 +81,7 @@ special invocation, using this target means you don't have to keep track
of which stage you're on or what invocation that stage needs.
@item cleanstrap
-Removed everything (@code{make clean}) and rebuilds (@code{make bootstrap}).
+Removed everything (@samp{make clean}) and rebuilds (@samp{make bootstrap}).
@item stage@var{N} (@var{N} = 1@dots{}4)
For each stage, moves the appropriate files to the @file{stage@var{N}}
diff --git a/contrib/gcc/doc/md.texi b/contrib/gcc/doc/md.texi
index b38ef5e..6184fc3 100644
--- a/contrib/gcc/doc/md.texi
+++ b/contrib/gcc/doc/md.texi
@@ -845,8 +845,8 @@ that of the host machine (on which the compiler is running).
@cindex @samp{F} in constraint
@item @samp{F}
-An immediate floating operand (expression code @code{const_double}) is
-allowed.
+An immediate floating operand (expression code @code{const_double} or
+@code{const_vector}) is allowed.
@cindex @samp{G} in constraint
@cindex @samp{H} in constraint
@@ -898,7 +898,7 @@ digit is used together with letters within the same alternative, the
digit should come last.
This number is allowed to be more than a single digit. If multiple
-digits are encountered consecutavely, they are interpreted as a single
+digits are encountered consecutively, they are interpreted as a single
decimal integer. There is scant chance for ambiguity, since to-date
it has never been desirable that @samp{10} be interpreted as matching
either operand 1 @emph{or} operand 0. Should this be desired, one
@@ -965,7 +965,7 @@ The machine description macro @code{REG_CLASS_FROM_LETTER} has first
cut at the otherwise unused letters. If it evaluates to @code{NO_REGS},
then @code{EXTRA_CONSTRAINT} is evaluated.
-A typical use for @code{EXTRA_CONSTRANT} would be to distinguish certain
+A typical use for @code{EXTRA_CONSTRAINT} would be to distinguish certain
types of memory references that affect other insn operands.
@end ifset
@end table
@@ -1256,6 +1256,8 @@ instruction is defined:
@dots{})
@end smallexample
@end ifset
+GCC can only handle one commutative pair in an asm; if you use more,
+the compiler may fail.
@cindex @samp{#} in constraint
@item #
@@ -1374,60 +1376,6 @@ An item in the constant pool
A symbol in the text segment of the current file
@end table
-@item AMD 29000 family---@file{a29k.h}
-@table @code
-@item l
-Local register 0
-
-@item b
-Byte Pointer (@samp{BP}) register
-
-@item q
-@samp{Q} register
-
-@item h
-Special purpose register
-
-@item A
-First accumulator register
-
-@item a
-Other accumulator register
-
-@item f
-Floating point register
-
-@item I
-Constant greater than 0, less than 0x100
-
-@item J
-Constant greater than 0, less than 0x10000
-
-@item K
-Constant whose high 24 bits are on (1)
-
-@item L
-16-bit constant whose high 8 bits are on (1)
-
-@item M
-32-bit constant whose high 16 bits are on (1)
-
-@item N
-32-bit negative constant that fits in 8 bits
-
-@item O
-The constant 0x80000000 or, on the 29050, any 32-bit constant
-whose low 16 bits are 0.
-
-@item P
-16-bit negative constant that fits in 8 bits
-
-@item G
-@itemx H
-A floating point constant (in @code{asm} statements, use the machine
-independent @samp{E} or @samp{F} instead)
-@end table
-
@item AVR family---@file{avr.h}
@table @code
@item l
@@ -1606,6 +1554,10 @@ Second floating point register
@item c
@samp{c} register
+@item C
+Specifies constant that can be easily constructed in SSE register without
+loading it from memory.
+
@item d
@samp{d} register
@@ -1681,6 +1633,232 @@ Floating point 0
Floating point 1
@end table
+@item Intel IA-64---@file{ia64.h}
+@table @code
+@item a
+General register @code{r0} to @code{r3} for @code{addl} instruction
+
+@item b
+Branch register
+
+@item c
+Predicate register (@samp{c} as in ``conditional'')
+
+@item d
+Application register residing in M-unit
+
+@item e
+Application register residing in I-unit
+
+@item f
+Floating-point register
+
+@item m
+Memory operand.
+Remember that @samp{m} allows postincrement and postdecrement which
+require printing with @samp{%Pn} on IA-64.
+Use @samp{S} to disallow postincrement and postdecrement.
+
+@item G
+Floating-point constant 0.0 or 1.0
+
+@item I
+14-bit signed integer constant
+
+@item J
+22-bit signed integer constant
+
+@item K
+8-bit signed integer constant for logical instructions
+
+@item L
+8-bit adjusted signed integer constant for compare pseudo-ops
+
+@item M
+6-bit unsigned integer constant for shift counts
+
+@item N
+9-bit signed integer constant for load and store postincrements
+
+@item O
+The constant zero
+
+@item P
+0 or -1 for @code{dep} instruction
+
+@item Q
+Non-volatile memory for floating-point loads and stores
+
+@item R
+Integer constant in the range 1 to 4 for @code{shladd} instruction
+
+@item S
+Memory operand except postincrement and postdecrement
+@end table
+
+@item FRV---@file{frv.h}
+@table @code
+@item a
+Register in the class @code{ACC_REGS} (@code{acc0} to @code{acc7}).
+
+@item b
+Register in the class @code{EVEN_ACC_REGS} (@code{acc0} to @code{acc7}).
+
+@item c
+Register in the class @code{CC_REGS} (@code{fcc0} to @code{fcc3} and
+@code{icc0} to @code{icc3}).
+
+@item d
+Register in the class @code{GPR_REGS} (@code{gr0} to @code{gr63}).
+
+@item e
+Register in the class @code{EVEN_REGS} (@code{gr0} to @code{gr63}).
+Odd registers are excluded not in the class but through the use of a machine
+mode larger than 4 bytes.
+
+@item f
+Register in the class @code{FPR_REGS} (@code{fr0} to @code{fr63}).
+
+@item h
+Register in the class @code{FEVEN_REGS} (@code{fr0} to @code{fr63}).
+Odd registers are excluded not in the class but through the use of a machine
+mode larger than 4 bytes.
+
+@item l
+Register in the class @code{LR_REG} (the @code{lr} register).
+
+@item q
+Register in the class @code{QUAD_REGS} (@code{gr2} to @code{gr63}).
+Register numbers not divisible by 4 are excluded not in the class but through
+the use of a machine mode larger than 8 bytes.
+
+@item t
+Register in the class @code{ICC_REGS} (@code{icc0} to @code{icc3}).
+
+@item u
+Register in the class @code{FCC_REGS} (@code{fcc0} to @code{fcc3}).
+
+@item v
+Register in the class @code{ICR_REGS} (@code{cc4} to @code{cc7}).
+
+@item w
+Register in the class @code{FCR_REGS} (@code{cc0} to @code{cc3}).
+
+@item x
+Register in the class @code{QUAD_FPR_REGS} (@code{fr0} to @code{fr63}).
+Register numbers not divisible by 4 are excluded not in the class but through
+the use of a machine mode larger than 8 bytes.
+
+@item z
+Register in the class @code{SPR_REGS} (@code{lcr} and @code{lr}).
+
+@item A
+Register in the class @code{QUAD_ACC_REGS} (@code{acc0} to @code{acc7}).
+
+@item B
+Register in the class @code{ACCG_REGS} (@code{accg0} to @code{accg7}).
+
+@item C
+Register in the class @code{CR_REGS} (@code{cc0} to @code{cc7}).
+
+@item G
+Floating point constant zero
+
+@item I
+6-bit signed integer constant
+
+@item J
+10-bit signed integer constant
+
+@item L
+16-bit signed integer constant
+
+@item M
+16-bit unsigned integer constant
+
+@item N
+12-bit signed integer constant that is negative---i.e.@: in the
+range of @minus{}2048 to @minus{}1
+
+@item O
+Constant zero
+
+@item P
+12-bit signed integer constant that is greater than zero---i.e.@: in the
+range of 1 to 2047.
+
+@end table
+
+@item IP2K---@file{ip2k.h}
+@table @code
+@item a
+@samp{DP} or @samp{IP} registers (general address)
+
+@item f
+@samp{IP} register
+
+@item j
+@samp{IPL} register
+
+@item k
+@samp{IPH} register
+
+@item b
+@samp{DP} register
+
+@item y
+@samp{DPH} register
+
+@item z
+@samp{DPL} register
+
+@item q
+@samp{SP} register
+
+@item c
+@samp{DP} or @samp{SP} registers (offsettable address)
+
+@item d
+Non-pointer registers (not @samp{SP}, @samp{DP}, @samp{IP})
+
+@item u
+Non-SP registers (everything except @samp{SP})
+
+@item R
+Indirect thru @samp{IP} - Avoid this except for @code{QImode}, since we
+can't access extra bytes
+
+@item S
+Indirect thru @samp{SP} or @samp{DP} with short displacement (0..127)
+
+@item T
+Data-section immediate value
+
+@item I
+Integers from @minus{}255 to @minus{}1
+
+@item J
+Integers from 0 to 7---valid bit number in a register
+
+@item K
+Integers from 0 to 127---valid displacement for addressing mode
+
+@item L
+Integers from 1 to 127
+
+@item M
+Integer @minus{}1
+
+@item N
+Integer 1
+
+@item O
+Zero
+
+@item P
+Integers from 0 to 255
+@end table
+
@item MIPS---@file{mips.h}
@table @code
@item d
@@ -1846,10 +2024,27 @@ Constants in the range @minus{}8 to 2
@item SPARC---@file{sparc.h}
@table @code
@item f
-Floating-point register that can hold 32- or 64-bit values.
+Floating-point register on the SPARC-V8 architecture and
+lower floating-point register on the SPARC-V9 architecture.
@item e
-Floating-point register that can hold 64- or 128-bit values.
+Floating-point register. It is equivalent to @samp{f} on the
+SPARC-V8 architecture and contains both lower and upper
+floating-point registers on the SPARC-V9 architecture.
+
+@item c
+Floating-point condition code register.
+
+@item d
+Lower floating-point register. It is only valid on the SPARC-V9
+architecture when the Visual Instruction Set is available.
+
+@item b
+Floating-point register. It is only valid on the SPARC-V9 architecture
+when the Visual Instruction Set is available.
+
+@item h
+64-bit global or out register for the SPARC-V8+ architecture.
@item I
Signed 13-bit constant
@@ -1872,6 +2067,9 @@ Same as @samp{K}, except that it verifies that bits that are not in the
lower 32-bit range are all zero. Must be used instead of @samp{K} for
modes wider than @code{SImode}
+@item O
+The constant 4096
+
@item G
Floating-point zero
@@ -2074,7 +2272,7 @@ A memory reference that is a stack push.
A memory reference that is a stack pop.
@item S
-A memory reference that refers to an constant address of known value.
+A memory reference that refers to a constant address of known value.
@item T
The register indicated by Rx (not implemented yet).
@@ -2262,8 +2460,7 @@ Write the generated insn as a @code{parallel} with elements being a
@code{set} of one register from the appropriate memory location (you may
also need @code{use} or @code{clobber} elements). Use a
@code{match_parallel} (@pxref{RTL Template}) to recognize the insn. See
-@file{a29k.md} and @file{rs6000.md} for examples of the use of this insn
-pattern.
+@file{rs6000.md} for examples of the use of this insn pattern.
@cindex @samp{store_multiple} instruction pattern
@item @samp{store_multiple}
@@ -2274,7 +2471,7 @@ operand 2 is a constant: the number of consecutive registers.
@cindex @code{push@var{m}} instruction pattern
@item @samp{push@var{m}}
-Output an push instruction. Operand 0 is value to push. Used only when
+Output a push instruction. Operand 0 is value to push. Used only when
@code{PUSH_ROUNDING} is defined. For historical reason, this pattern may be
missing and in such case an @code{mov} expander is used instead, with a
@code{MEM} expression forming the push operation. The @code{mov} expander
@@ -2390,7 +2587,45 @@ Store the absolute value of operand 1 into operand 0.
Store the square root of operand 1 into operand 0.
The @code{sqrt} built-in function of C always uses the mode which
-corresponds to the C data type @code{double}.
+corresponds to the C data type @code{double} and the @code{sqrtf}
+built-in function uses the mode which corresponds to the C data
+type @code{float}.
+
+@cindex @code{cos@var{m}2} instruction pattern
+@item @samp{cos@var{m}2}
+Store the cosine of operand 1 into operand 0.
+
+The @code{cos} built-in function of C always uses the mode which
+corresponds to the C data type @code{double} and the @code{cosf}
+built-in function uses the mode which corresponds to the C data
+type @code{float}.
+
+@cindex @code{sin@var{m}2} instruction pattern
+@item @samp{sin@var{m}2}
+Store the sine of operand 1 into operand 0.
+
+The @code{sin} built-in function of C always uses the mode which
+corresponds to the C data type @code{double} and the @code{sinf}
+built-in function uses the mode which corresponds to the C data
+type @code{float}.
+
+@cindex @code{exp@var{m}2} instruction pattern
+@item @samp{exp@var{m}2}
+Store the exponential of operand 1 into operand 0.
+
+The @code{exp} built-in function of C always uses the mode which
+corresponds to the C data type @code{double} and the @code{expf}
+built-in function uses the mode which corresponds to the C data
+type @code{float}.
+
+@cindex @code{log@var{m}2} instruction pattern
+@item @samp{log@var{m}2}
+Store the natural logarithm of operand 1 into operand 0.
+
+The @code{log} built-in function of C always uses the mode which
+corresponds to the C data type @code{double} and the @code{logf}
+built-in function uses the mode which corresponds to the C data
+type @code{float}.
@cindex @code{ffs@var{m}2} instruction pattern
@item @samp{ffs@var{m}2}
@@ -3139,14 +3374,6 @@ respectively, a low or moderate degree of temporal locality.
Targets that do not support write prefetches or locality hints can ignore
the values of operands 1 and 2.
-@cindex @code{cycle_display} instruction pattern
-@item @samp{cycle_display}
-
-This pattern, if present, will be emitted by the instruction scheduler at
-the beginning of each new clock cycle. This can be used for annotating the
-assembler output with cycle counts. Operand 0 is a @code{const_int} that
-holds the clock cycle.
-
@end table
@node Pattern Ordering
@@ -3317,7 +3544,7 @@ multiple condition registers, use a pseudo register.
@findex next_cc0_user
On some machines, the type of branch instruction generated may depend on
the way the condition code was produced; for example, on the 68k and
-Sparc, setting the condition code directly from an add or subtract
+SPARC, setting the condition code directly from an add or subtract
instruction does not clear the overflow bit the way that a test
instruction does, so a different branch instruction must be used for
some conditional branches. For machines that use @code{(cc0)}, the set
@@ -3336,7 +3563,7 @@ different formats of the condition code register.
Registers used to store the condition code value should have a mode that
is in class @code{MODE_CC}. Normally, it will be @code{CCmode}. If
additional modes are required (as for the add example mentioned above in
-the Sparc), define the macro @code{EXTRA_CC_MODES} to list the
+the SPARC), define the macro @code{EXTRA_CC_MODES} to list the
additional modes required (@pxref{Condition Code}). Also define
@code{SELECT_CC_MODE} to choose a mode given an operand of a compare.
@@ -3348,7 +3575,7 @@ be specified at that time.
If the cases that require different modes would be made by instruction
combination, the macro @code{SELECT_CC_MODE} determines which machine
mode should be used for the comparison result. The patterns should be
-written using that mode. To support the case of the add on the Sparc
+written using that mode. To support the case of the add on the SPARC
discussed above, we have the pattern
@smallexample
@@ -3362,7 +3589,7 @@ discussed above, we have the pattern
"@dots{}")
@end smallexample
-The @code{SELECT_CC_MODE} macro on the Sparc returns @code{CC_NOOVmode}
+The @code{SELECT_CC_MODE} macro on the SPARC returns @code{CC_NOOVmode}
for comparisons whose argument is a @code{plus}.
@node Looping Patterns
@@ -3370,7 +3597,7 @@ for comparisons whose argument is a @code{plus}.
@cindex looping instruction patterns
@cindex defining looping instruction patterns
-Some machines have special jump instructions that can be utilised to
+Some machines have special jump instructions that can be utilized to
make loops more efficient. A common example is the 68000 @samp{dbra}
instruction which performs a decrement of a register and a branch if the
result was greater than zero. Other machines, in particular digital
@@ -3501,6 +3728,14 @@ For these operators, if only one operand is a @code{neg}, @code{not},
@code{mult}, @code{plus}, or @code{minus} expression, it will be the
first operand.
+@item
+In combinations of @code{neg}, @code{mult}, @code{plus}, and
+@code{minus}, the @code{neg} operations (if any) will be moved inside
+the operations as far as possible. For instance,
+@code{(neg (mult A B))} is canonicalized as @code{(mult (neg A) B)}, but
+@code{(plus (mult (neg A) B) C)} is canonicalized as
+@code{(minus A (mult B C))}.
+
@cindex @code{compare}, canonicalization of
@item
For the @code{compare} operator, a constant is always the second operand
@@ -3810,13 +4045,14 @@ in the compiler.
@cindex instruction splitting
@cindex splitting instructions
-There are two cases where you should specify how to split a pattern into
-multiple insns. On machines that have instructions requiring delay
-slots (@pxref{Delay Slots}) or that have instructions whose output is
-not available for multiple cycles (@pxref{Function Units}), the compiler
-phases that optimize these cases need to be able to move insns into
-one-instruction delay slots. However, some insns may generate more than one
-machine instruction. These insns cannot be placed into a delay slot.
+There are two cases where you should specify how to split a pattern
+into multiple insns. On machines that have instructions requiring
+delay slots (@pxref{Delay Slots}) or that have instructions whose
+output is not available for multiple cycles (@pxref{Processor pipeline
+description}), the compiler phases that optimize these cases need to
+be able to move insns into one-instruction delay slots. However, some
+insns may generate more than one machine instruction. These insns
+cannot be placed into a delay slot.
Often you can rewrite the single insn as a list of individual insns,
each corresponding to one machine instruction. The disadvantage of
@@ -3978,7 +4214,7 @@ instruction is always valid, as compiler expect identical behavior of new
jump. When new sequence contains multiple jump instructions or new labels,
more assistance is needed. Splitter is required to create only unconditional
jumps, or simple conditional jump instructions. Additionally it must attach a
-@code{REG_BR_PROB} note to each conditional jump. An global variable
+@code{REG_BR_PROB} note to each conditional jump. A global variable
@code{split_branch_probability} hold the probability of original branch in case
it was an simple conditional jump, @minus{}1 otherwise. To simplify
recomputing of edge frequencies, new sequence is required to have only
@@ -4061,7 +4297,7 @@ For example:
@end smallexample
-Where @var{pathname} is a string that specifies the the location of the file,
+Where @var{pathname} is a string that specifies the location of the file,
specifies the include file to be in @file{gcc/config/target/filestuff}. The
directory @file{gcc/config/target} is regarded as the default directory.
@@ -4436,7 +4672,7 @@ to track the condition codes.
* Insn Lengths:: Computing the length of insns.
* Constant Attributes:: Defining attributes that are constant.
* Delay Slots:: Defining delay slots required for a machine.
-* Function Units:: Specifying information for insn scheduling.
+* Processor pipeline description:: Specifying information for insn scheduling.
@end menu
@node Defining Attributes
@@ -5066,14 +5302,101 @@ branch is true, we might represent this as follows:
@end smallexample
@c the above is *still* too long. --mew 4feb93
-@node Function Units
-@subsection Specifying Function Units
+@node Processor pipeline description
+@subsection Specifying processor pipeline description
+@cindex processor pipeline description
+@cindex processor functional units
+@cindex instruction latency time
+@cindex interlock delays
+@cindex data dependence delays
+@cindex reservation delays
+@cindex pipeline hazard recognizer
+@cindex automaton based pipeline description
+@cindex regular expressions
+@cindex deterministic finite state automaton
+@cindex automaton based scheduler
+@cindex RISC
+@cindex VLIW
+
+To achieve better performance, most modern processors
+(super-pipelined, superscalar @acronym{RISC}, and @acronym{VLIW}
+processors) have many @dfn{functional units} on which several
+instructions can be executed simultaneously. An instruction starts
+execution if its issue conditions are satisfied. If not, the
+instruction is stalled until its conditions are satisfied. Such
+@dfn{interlock (pipeline) delay} causes interruption of the fetching
+of successor instructions (or demands nop instructions, e.g. for some
+MIPS processors).
+
+There are two major kinds of interlock delays in modern processors.
+The first one is a data dependence delay determining @dfn{instruction
+latency time}. The instruction execution is not started until all
+source data have been evaluated by prior instructions (there are more
+complex cases when the instruction execution starts even when the data
+are not available but will be ready in given time after the
+instruction execution start). Taking the data dependence delays into
+account is simple. The data dependence (true, output, and
+anti-dependence) delay between two instructions is given by a
+constant. In most cases this approach is adequate. The second kind
+of interlock delays is a reservation delay. The reservation delay
+means that two instructions under execution will be in need of shared
+processors resources, i.e. buses, internal registers, and/or
+functional units, which are reserved for some time. Taking this kind
+of delay into account is complex especially for modern @acronym{RISC}
+processors.
+
+The task of exploiting more processor parallelism is solved by an
+instruction scheduler. For a better solution to this problem, the
+instruction scheduler has to have an adequate description of the
+processor parallelism (or @dfn{pipeline description}). Currently GCC
+provides two alternative ways to describe processor parallelism,
+both described below. The first method is outlined in the next section;
+it was once the only method provided by GCC, and thus is used in a number
+of exiting ports. The second, and preferred method, specifies functional
+unit reservations for groups of instructions with the aid of @dfn{regular
+expressions}. This is called the @dfn{automaton based description}.
+
+The GCC instruction scheduler uses a @dfn{pipeline hazard recognizer} to
+figure out the possibility of the instruction issue by the processor
+on a given simulated processor cycle. The pipeline hazard recognizer is
+automatically generated from the processor pipeline description. The
+pipeline hazard recognizer generated from the automaton based
+description is more sophisticated and based on a deterministic finite
+state automaton (@acronym{DFA}) and therefore faster than one
+generated from the old description. Furthermore, its speed is not dependent
+on processor complexity. The instruction issue is possible if there is
+a transition from one automaton state to another one.
+
+You can use any model to describe processor pipeline characteristics
+or even a mix of them. You could use the old description for some
+processor submodels and the @acronym{DFA}-based one for the rest
+processor submodels.
+
+In general, the usage of the automaton based description is more
+preferable. Its model is more rich. It permits to describe more
+accurately pipeline characteristics of processors which results in
+improving code quality (although sometimes only on several percent
+fractions). It will be also used as an infrastructure to implement
+sophisticated and practical insn scheduling which will try many
+instruction sequences to choose the best one.
+
+
+@menu
+* Old pipeline description:: Specifying information for insn scheduling.
+* Automaton pipeline description:: Describing insn pipeline characteristics.
+* Comparison of the two descriptions:: Drawbacks of the old pipeline description
+@end menu
+
+@node Old pipeline description
+@subsubsection Specifying Function Units
+@cindex old pipeline description
@cindex function units, for scheduling
-On most RISC machines, there are instructions whose results are not
-available for a specific number of cycles. Common cases are instructions
-that load data from memory. On many machines, a pipeline stall will result
-if the data is referenced too soon after the load instruction.
+On most @acronym{RISC} machines, there are instructions whose results
+are not available for a specific number of cycles. Common cases are
+instructions that load data from memory. On many machines, a pipeline
+stall will result if the data is referenced too soon after the load
+instruction.
In addition, many newer microprocessors have multiple function units, usually
one for integer and one for floating point, and often will incur pipeline
@@ -5087,13 +5410,14 @@ due to function unit conflicts.
For the purposes of the specifications in this section, a machine is
divided into @dfn{function units}, each of which execute a specific
-class of instructions in first-in-first-out order. Function units that
-accept one instruction each cycle and allow a result to be used in the
-succeeding instruction (usually via forwarding) need not be specified.
-Classic RISC microprocessors will normally have a single function unit,
-which we can call @samp{memory}. The newer ``superscalar'' processors
-will often have function units for floating point operations, usually at
-least a floating point adder and multiplier.
+class of instructions in first-in-first-out order. Function units
+that accept one instruction each cycle and allow a result to be used
+in the succeeding instruction (usually via forwarding) need not be
+specified. Classic @acronym{RISC} microprocessors will normally have
+a single function unit, which we can call @samp{memory}. The newer
+``superscalar'' processors will often have function units for floating
+point operations, usually at least a floating point adder and
+multiplier.
@findex define_function_unit
Each usage of a function units by a class of insns is specified with a
@@ -5156,10 +5480,10 @@ Typical uses of this vector are where a floating point function unit can
pipeline either single- or double-precision operations, but not both, or
where a memory unit can pipeline loads, but not stores, etc.
-As an example, consider a classic RISC machine where the result of a
-load instruction is not available for two cycles (a single ``delay''
-instruction is required) and where only one load instruction can be executed
-simultaneously. This would be specified as:
+As an example, consider a classic @acronym{RISC} machine where the
+result of a load instruction is not available for two cycles (a single
+``delay'' instruction is required) and where only one load instruction
+can be executed simultaneously. This would be specified as:
@smallexample
(define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0)
@@ -5185,6 +5509,405 @@ used during their execution and there is no way of representing that
conflict. We welcome any examples of how function unit conflicts work
in such processors and suggestions for their representation.
+@node Automaton pipeline description
+@subsubsection Describing instruction pipeline characteristics
+@cindex automaton based pipeline description
+
+This section describes constructions of the automaton based processor
+pipeline description. The order of all mentioned below constructions
+in the machine description file is not important.
+
+@findex define_automaton
+@cindex pipeline hazard recognizer
+The following optional construction describes names of automata
+generated and used for the pipeline hazards recognition. Sometimes
+the generated finite state automaton used by the pipeline hazard
+recognizer is large. If we use more than one automaton and bind functional
+units to the automata, the summary size of the automata usually is
+less than the size of the single automaton. If there is no one such
+construction, only one finite state automaton is generated.
+
+@smallexample
+(define_automaton @var{automata-names})
+@end smallexample
+
+@var{automata-names} is a string giving names of the automata. The
+names are separated by commas. All the automata should have unique names.
+The automaton name is used in construction @code{define_cpu_unit} and
+@code{define_query_cpu_unit}.
+
+@findex define_cpu_unit
+@cindex processor functional units
+Each processor functional unit used in description of instruction
+reservations should be described by the following construction.
+
+@smallexample
+(define_cpu_unit @var{unit-names} [@var{automaton-name}])
+@end smallexample
+
+@var{unit-names} is a string giving the names of the functional units
+separated by commas. Don't use name @samp{nothing}, it is reserved
+for other goals.
+
+@var{automaton-name} is a string giving the name of the automaton with
+which the unit is bound. The automaton should be described in
+construction @code{define_automaton}. You should give
+@dfn{automaton-name}, if there is a defined automaton.
+
+@findex define_query_cpu_unit
+@cindex querying function unit reservations
+The following construction describes CPU functional units analogously
+to @code{define_cpu_unit}. If we use automata without their
+minimization, the reservation of such units can be queried for an
+automaton state. The instruction scheduler never queries reservation
+of functional units for given automaton state. So as a rule, you
+don't need this construction. This construction could be used for
+future code generation goals (e.g. to generate @acronym{VLIW} insn
+templates).
+
+@smallexample
+(define_query_cpu_unit @var{unit-names} [@var{automaton-name}])
+@end smallexample
+
+@var{unit-names} is a string giving names of the functional units
+separated by commas.
+
+@var{automaton-name} is a string giving the name of the automaton with
+which the unit is bound.
+
+@findex define_insn_reservation
+@cindex instruction latency time
+@cindex regular expressions
+@cindex data bypass
+The following construction is the major one to describe pipeline
+characteristics of an instruction.
+
+@smallexample
+(define_insn_reservation @var{insn-name} @var{default_latency}
+ @var{condition} @var{regexp})
+@end smallexample
+
+@var{default_latency} is a number giving latency time of the
+instruction. There is an important difference between the old
+description and the automaton based pipeline description. The latency
+time is used for all dependencies when we use the old description. In
+the automaton based pipeline description, the given latency time is only
+used for true dependencies. The cost of anti-dependencies is always
+zero and the cost of output dependencies is the difference between
+latency times of the producing and consuming insns (if the difference
+is negative, the cost is considered to be zero). You can always
+change the default costs for any description by using the target hook
+@code{TARGET_SCHED_ADJUST_COST} (@pxref{Scheduling}).
+
+@var{insn-names} is a string giving the internal name of the insn. The
+internal names are used in constructions @code{define_bypass} and in
+the automaton description file generated for debugging. The internal
+name has nothing in common with the names in @code{define_insn}. It is a
+good practice to use insn classes described in the processor manual.
+
+@var{condition} defines what RTL insns are described by this
+construction. You should remember that you will be in trouble if
+@var{condition} for two or more different
+@code{define_insn_reservation} constructions is TRUE for an insn. In
+this case what reservation will be used for the insn is not defined.
+Such cases are not checked during generation of the pipeline hazards
+recognizer because in general recognizing that two conditions may have
+the same value is quite difficult (especially if the conditions
+contain @code{symbol_ref}). It is also not checked during the
+pipeline hazard recognizer work because it would slow down the
+recognizer considerably.
+
+@var{regexp} is a string describing the reservation of the cpu's functional
+units by the instruction. The reservations are described by a regular
+expression according to the following syntax:
+
+@smallexample
+ regexp = regexp "," oneof
+ | oneof
+
+ oneof = oneof "|" allof
+ | allof
+
+ allof = allof "+" repeat
+ | repeat
+
+ repeat = element "*" number
+ | element
+
+ element = cpu_function_unit_name
+ | reservation_name
+ | result_name
+ | "nothing"
+ | "(" regexp ")"
+@end smallexample
+
+@itemize @bullet
+@item
+@samp{,} is used for describing the start of the next cycle in
+the reservation.
+
+@item
+@samp{|} is used for describing a reservation described by the first
+regular expression @strong{or} a reservation described by the second
+regular expression @strong{or} etc.
+
+@item
+@samp{+} is used for describing a reservation described by the first
+regular expression @strong{and} a reservation described by the
+second regular expression @strong{and} etc.
+
+@item
+@samp{*} is used for convenience and simply means a sequence in which
+the regular expression are repeated @var{number} times with cycle
+advancing (see @samp{,}).
+
+@item
+@samp{cpu_function_unit_name} denotes reservation of the named
+functional unit.
+
+@item
+@samp{reservation_name} --- see description of construction
+@samp{define_reservation}.
+
+@item
+@samp{nothing} denotes no unit reservations.
+@end itemize
+
+@findex define_reservation
+Sometimes unit reservations for different insns contain common parts.
+In such case, you can simplify the pipeline description by describing
+the common part by the following construction
+
+@smallexample
+(define_reservation @var{reservation-name} @var{regexp})
+@end smallexample
+
+@var{reservation-name} is a string giving name of @var{regexp}.
+Functional unit names and reservation names are in the same name
+space. So the reservation names should be different from the
+functional unit names and can not be reserved name @samp{nothing}.
+
+@findex define_bypass
+@cindex instruction latency time
+@cindex data bypass
+The following construction is used to describe exceptions in the
+latency time for given instruction pair. This is so called bypasses.
+
+@smallexample
+(define_bypass @var{number} @var{out_insn_names} @var{in_insn_names}
+ [@var{guard}])
+@end smallexample
+
+@var{number} defines when the result generated by the instructions
+given in string @var{out_insn_names} will be ready for the
+instructions given in string @var{in_insn_names}. The instructions in
+the string are separated by commas.
+
+@var{guard} is an optional string giving the name of a C function which
+defines an additional guard for the bypass. The function will get the
+two insns as parameters. If the function returns zero the bypass will
+be ignored for this case. The additional guard is necessary to
+recognize complicated bypasses, e.g. when the consumer is only an address
+of insn @samp{store} (not a stored value).
+
+@findex exclusion_set
+@findex presence_set
+@findex absence_set
+@cindex VLIW
+@cindex RISC
+Usually the following three constructions are used to describe
+@acronym{VLIW} processors (more correctly to describe a placement of
+small insns into @acronym{VLIW} insn slots). Although they can be
+used for @acronym{RISC} processors too.
+
+@smallexample
+(exclusion_set @var{unit-names} @var{unit-names})
+(presence_set @var{unit-names} @var{unit-names})
+(absence_set @var{unit-names} @var{unit-names})
+@end smallexample
+
+@var{unit-names} is a string giving names of functional units
+separated by commas.
+
+The first construction (@samp{exclusion_set}) means that each
+functional unit in the first string can not be reserved simultaneously
+with a unit whose name is in the second string and vice versa. For
+example, the construction is useful for describing processors
+(e.g. some SPARC processors) with a fully pipelined floating point
+functional unit which can execute simultaneously only single floating
+point insns or only double floating point insns.
+
+The second construction (@samp{presence_set}) means that each
+functional unit in the first string can not be reserved unless at
+least one of units whose names are in the second string is reserved.
+This is an asymmetric relation. For example, it is useful for
+description that @acronym{VLIW} @samp{slot1} is reserved after
+@samp{slot0} reservation.
+
+The third construction (@samp{absence_set}) means that each functional
+unit in the first string can be reserved only if each unit whose name
+is in the second string is not reserved. This is an asymmetric
+relation (actually @samp{exclusion_set} is analogous to this one but
+it is symmetric). For example, it is useful for description that
+@acronym{VLIW} @samp{slot0} can not be reserved after @samp{slot1} or
+@samp{slot2} reservation.
+
+All functional units mentioned in a set should belong to the same
+automaton.
+
+@findex automata_option
+@cindex deterministic finite state automaton
+@cindex nondeterministic finite state automaton
+@cindex finite state automaton minimization
+You can control the generator of the pipeline hazard recognizer with
+the following construction.
+
+@smallexample
+(automata_option @var{options})
+@end smallexample
+
+@var{options} is a string giving options which affect the generated
+code. Currently there are the following options:
+
+@itemize @bullet
+@item
+@dfn{no-minimization} makes no minimization of the automaton. This is
+only worth to do when we are going to query CPU functional unit
+reservations in an automaton state.
+
+@item
+@dfn{time} means printing additional time statistics about
+generation of automata.
+
+@item
+@dfn{v} means a generation of the file describing the result automata.
+The file has suffix @samp{.dfa} and can be used for the description
+verification and debugging.
+
+@item
+@dfn{w} means a generation of warning instead of error for
+non-critical errors.
+
+@item
+@dfn{ndfa} makes nondeterministic finite state automata. This affects
+the treatment of operator @samp{|} in the regular expressions. The
+usual treatment of the operator is to try the first alternative and,
+if the reservation is not possible, the second alternative. The
+nondeterministic treatment means trying all alternatives, some of them
+may be rejected by reservations in the subsequent insns. You can not
+query functional unit reservations in nondeterministic automaton
+states.
+@end itemize
+
+As an example, consider a superscalar @acronym{RISC} machine which can
+issue three insns (two integer insns and one floating point insn) on
+the cycle but can finish only two insns. To describe this, we define
+the following functional units.
+
+@smallexample
+(define_cpu_unit "i0_pipeline, i1_pipeline, f_pipeline")
+(define_cpu_unit "port0, port1")
+@end smallexample
+
+All simple integer insns can be executed in any integer pipeline and
+their result is ready in two cycles. The simple integer insns are
+issued into the first pipeline unless it is reserved, otherwise they
+are issued into the second pipeline. Integer division and
+multiplication insns can be executed only in the second integer
+pipeline and their results are ready correspondingly in 8 and 4
+cycles. The integer division is not pipelined, i.e. the subsequent
+integer division insn can not be issued until the current division
+insn finished. Floating point insns are fully pipelined and their
+results are ready in 3 cycles. Where the result of a floating point
+insn is used by an integer insn, an additional delay of one cycle is
+incurred. To describe all of this we could specify
+
+@smallexample
+(define_cpu_unit "div")
+
+(define_insn_reservation "simple" 2 (eq_attr "type" "int")
+ "(i0_pipeline | i1_pipeline), (port0 | port1)")
+
+(define_insn_reservation "mult" 4 (eq_attr "type" "mult")
+ "i1_pipeline, nothing*2, (port0 | port1)")
+
+(define_insn_reservation "div" 8 (eq_attr "type" "div")
+ "i1_pipeline, div*7, div + (port0 | port1)")
+
+(define_insn_reservation "float" 3 (eq_attr "type" "float")
+ "f_pipeline, nothing, (port0 | port1))
+
+(define_bypass 4 "float" "simple,mult,div")
+@end smallexample
+
+To simplify the description we could describe the following reservation
+
+@smallexample
+(define_reservation "finish" "port0|port1")
+@end smallexample
+
+and use it in all @code{define_insn_reservation} as in the following
+construction
+
+@smallexample
+(define_insn_reservation "simple" 2 (eq_attr "type" "int")
+ "(i0_pipeline | i1_pipeline), finish")
+@end smallexample
+
+
+@node Comparison of the two descriptions
+@subsubsection Drawbacks of the old pipeline description
+@cindex old pipeline description
+@cindex automaton based pipeline description
+@cindex processor functional units
+@cindex interlock delays
+@cindex instruction latency time
+@cindex pipeline hazard recognizer
+@cindex data bypass
+
+The old instruction level parallelism description and the pipeline
+hazards recognizer based on it have the following drawbacks in
+comparison with the @acronym{DFA}-based ones:
+
+@itemize @bullet
+@item
+Each functional unit is believed to be reserved at the instruction
+execution start. This is a very inaccurate model for modern
+processors.
+
+@item
+An inadequate description of instruction latency times. The latency
+time is bound with a functional unit reserved by an instruction not
+with the instruction itself. In other words, the description is
+oriented to describe at most one unit reservation by each instruction.
+It also does not permit to describe special bypasses between
+instruction pairs.
+
+@item
+The implementation of the pipeline hazard recognizer interface has
+constraints on number of functional units. This is a number of bits
+in integer on the host machine.
+
+@item
+The interface to the pipeline hazard recognizer is more complex than
+one to the automaton based pipeline recognizer.
+
+@item
+An unnatural description when you write a unit and a condition which
+selects instructions using the unit. Writing all unit reservations
+for an instruction (an instruction class) is more natural.
+
+@item
+The recognition of the interlock delays has a slow implementation. The GCC
+scheduler supports structures which describe the unit reservations.
+The more functional units a processor has, the slower its pipeline hazard
+recognizer will be. Such an implementation would become even slower when we
+allowed to
+reserve functional units not only at the instruction execution start.
+In an automaton based pipeline hazard recognizer, speed is not dependent
+on processor complexity.
+@end itemize
+
@node Conditional Execution
@section Conditional Execution
@cindex conditional execution
diff --git a/contrib/gcc/doc/objc.texi b/contrib/gcc/doc/objc.texi
index d3fd775..a0c40f7 100644
--- a/contrib/gcc/doc/objc.texi
+++ b/contrib/gcc/doc/objc.texi
@@ -25,7 +25,6 @@ comments about this document to Ovidiu Predescu
@node Executing code before main, Type encoding, Objective-C, Objective-C
@section @code{+load}: Executing code before main
-
The GNU Objective-C runtime provides a way that allows you to execute
code before the execution of the program enters the @code{main}
function. The code is executed on a per-class and a per-category basis,
@@ -396,7 +395,7 @@ prefixing a C constant string with the character @samp{@@}:
id myString = @@"this is a constant string object";
@end example
-The constant string objects are usually instances of the
+The constant string objects are by default instances of the
@code{NXConstantString} class which is provided by the GNU Objective-C
runtime. To get the definition of this class you must include the
@file{objc/NXConstStr.h} header file.
@@ -409,8 +408,9 @@ as @code{NXConstantString}'s structure:
@example
-@@interface NXConstantString : Object
+@@interface MyConstantStringClass
@{
+ Class isa;
char *c_string;
unsigned int len;
@}
@@ -418,15 +418,31 @@ as @code{NXConstantString}'s structure:
@end example
-User class libraries may choose to inherit the customized constant
-string class from a different class than @code{Object}. There is no
-requirement in the methods the constant string class has to implement.
-
-When a file is compiled with the @option{-fconstant-string-class} option,
-all the constant string objects will be instances of the class specified
-as argument to this option. It is possible to have multiple compilation
-units referring to different constant string classes, neither the
-compiler nor the linker impose any restrictions in doing this.
+@code{NXConstantString} inherits from @code{Object}; user class
+libraries may choose to inherit the customized constant string class
+from a different class than @code{Object}. There is no requirement in
+the methods the constant string class has to implement, but the final
+ivar layout of the class must be the compatible with the given
+structure.
+
+When the compiler creates the statically allocated constant string
+object, the @code{c_string} field will be filled by the compiler with
+the string; the @code{length} field will be filled by the compiler with
+the string length; the @code{isa} pointer will be filled with
+@code{NULL} by the compiler, and it will later be fixed up automatically
+at runtime by the GNU Objective-C runtime library to point to the class
+which was set by the @option{-fconstant-string-class} option when the
+object file is loaded (if you wonder how it works behind the scenes, the
+name of the class to use, and the list of static objects to fixup, are
+stored by the compiler in the object file in a place where the GNU
+runtime library will find them at runtime).
+
+As a result, when a file is compiled with the
+@option{-fconstant-string-class} option, all the constant string objects
+will be instances of the class specified as argument to this option. It
+is possible to have multiple compilation units referring to different
+constant string classes, neither the compiler nor the linker impose any
+restrictions in doing this.
@c =========================================================================
@node compatibility_alias
diff --git a/contrib/gcc/doc/passes.texi b/contrib/gcc/doc/passes.texi
index 1a5f8b0..9a1941b 100644
--- a/contrib/gcc/doc/passes.texi
+++ b/contrib/gcc/doc/passes.texi
@@ -109,6 +109,7 @@ The files
@file{c-common.c},
@file{c-common.def},
@file{c-format.c},
+@file{c-opts.c},
@file{c-pragma.c},
@file{c-semantics.c},
and
@@ -116,7 +117,6 @@ and
along with header files
@file{c-common.h},
@file{c-dump.h},
-@file{c-lex.h},
and
@file{c-pragma.h},
are also used for all of the above languages.
@@ -206,7 +206,7 @@ the input file name.
@cindex sibling call optimization
@item
-Sibiling call optimization. This pass performs tail recursion
+Sibling call optimization. This pass performs tail recursion
elimination, and tail and sibling call optimizations. The purpose of
these optimizations is to reduce the overhead of function calls,
whenever possible.
@@ -458,13 +458,20 @@ The option @option{-dS} causes a debugging dump of the RTL code after this
pass is run for the first time. The dump file's name is made by
appending @samp{.sched} to the input file name.
+@cindex register allocation
+@item
+Register allocation. These passes make sure that all occurrences of pseudo
+registers are eliminated, either by allocating them to a hard register,
+replacing them by an equivalent expression (e.g.@: a constant) or by placing
+them on the stack. This is done in several subpasses:
+
+@itemize @bullet
@cindex register class preference pass
@item
Register class preferencing. The RTL code is scanned to find out
which register class is best for each pseudo register. The source
file is @file{regclass.c}.
-@cindex register allocation
@cindex local register allocation
@item
Local register allocation (@file{local-alloc.c}). This pass allocates
@@ -483,6 +490,17 @@ Global register allocation (@file{global.c}). This pass
allocates hard registers for the remaining pseudo registers (those
whose life spans are not contained in one basic block).
+@cindex graph coloring register allocation
+@opindex fnew-ra
+@opindex dl
+@item
+Graph coloring register allocator. The files @file{ra.c}, @file{ra-build.c},
+@file{ra-colorize.c}, @file{ra-debug.c}, @file{ra-rewrite.c} together with
+the header @file{ra.h} contain another register allocator, which is used
+when the option @option{-fnew-ra} is given. In that case it is run instead
+of the above mentioned local and global register allocation passes, and the
+option @option{-dl} causes a debugging dump of its work.
+
@cindex reloading
@item
Reloading. This pass renumbers pseudo registers with the hardware
@@ -504,6 +522,7 @@ Source files are @file{reload.c} and @file{reload1.c}, plus the header
The option @option{-dg} causes a debugging dump of the RTL code after
this pass. This dump file's name is made by appending @samp{.greg} to
the input file name.
+@end itemize
@cindex instruction scheduling
@cindex scheduling, instruction
@@ -531,17 +550,6 @@ The option @option{-dB} causes a debugging dump of the RTL code after
this pass. This dump file's name is made by appending @samp{.bbro} to
the input file name.
-@cindex cross-jumping
-@cindex no-op move instructions
-@item
-Jump optimization is repeated, this time including cross-jumping
-and deletion of no-op move instructions.
-
-@opindex dJ
-The option @option{-dJ} causes a debugging dump of the RTL code after
-this pass. This dump file's name is made by appending @samp{.jump2}
-to the input file name.
-
@cindex delayed branch scheduling
@cindex scheduling, delayed branch
@item
@@ -653,6 +661,8 @@ Several passes use instruction attributes. A definition of the
attributes defined for a particular machine is in file
@file{insn-attr.h}, which is generated from the machine description by
the program @file{genattr}. The file @file{insn-attrtab.c} contains
-subroutines to obtain the attribute values for insns. It is generated
-from the machine description by the program @file{genattrtab}.
+subroutines to obtain the attribute values for insns and information
+about processor pipeline characteristics for the instruction
+scheduler. It is generated from the machine description by the
+program @file{genattrtab}.
@end itemize
diff --git a/contrib/gcc/doc/rtl.texi b/contrib/gcc/doc/rtl.texi
index 56a02d3..302957c 100644
--- a/contrib/gcc/doc/rtl.texi
+++ b/contrib/gcc/doc/rtl.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1988, 1989, 1992, 1994, 1997, 1998, 1999, 2000, 2001, 2002
+@c Copyright (C) 1988, 1989, 1992, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003
@c Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -243,6 +243,9 @@ core, @samp{V} is equivalent to @samp{E}, but when the object is read
from an @samp{md} file, the vector value of this operand may be omitted.
An omitted vector is effectively the same as a vector of no elements.
+@item B
+@samp{B} indicates a pointer to basic block structure.
+
@item 0
@samp{0} means a slot whose contents do not fit any normal category.
@samp{0} slots are not printed at all in dumps, and are often used in
@@ -371,7 +374,7 @@ to access them.
RTL expressions contain several flags (one-bit bit-fields)
that are used in certain types of expression. Most often they
-are accessed with the following macros, which expand into lvalues:
+are accessed with the following macros, which expand into lvalues.
@table @code
@findex CONSTANT_POOL_ADDRESS_P
@@ -395,13 +398,15 @@ indicates that the insn represents a call to a const or pure function.
Stored in the @code{unchanging} field and printed as @samp{/u}.
@findex INSN_ANNULLED_BRANCH_P
+@cindex @code{jump_insn} and @samp{/u}
+@cindex @code{call_insn} and @samp{/u}
@cindex @code{insn} and @samp{/u}
-@cindex @code{unchanging}, in @code{insn}
+@cindex @code{unchanging}, in @code{jump_insn}, @code{call_insn} and @code{insn}
@item INSN_ANNULLED_BRANCH_P (@var{x})
-In an @code{insn} in the delay slot of a branch insn, indicates that an
-annulling branch should be used. See the discussion under
-@code{sequence} below. Stored in the @code{unchanging} field and printed
-as @samp{/u}.
+In a @code{jump_insn}, @code{call_insn}, or @code{insn} indicates
+that the branch is an annulling one. See the discussion under
+@code{sequence} below. Stored in the @code{unchanging} field and
+printed as @samp{/u}.
@findex INSN_DEAD_CODE_P
@cindex @code{insn} and @samp{/s}
@@ -413,16 +418,26 @@ Stored in the @code{in_struct} field and printed as @samp{/s}.
@findex INSN_DELETED_P
@cindex @code{insn} and @samp{/v}
-@cindex @code{volatil}, in @code{insn}
+@cindex @code{call_insn} and @samp{/v}
+@cindex @code{jump_insn} and @samp{/v}
+@cindex @code{code_label} and @samp{/v}
+@cindex @code{barrier} and @samp{/v}
+@cindex @code{note} and @samp{/v}
+@cindex @code{volatil}, in @code{insn}, @code{call_insn}, @code{jump_insn}, @code{code_label}, @code{barrier}, and @code{note}
@item INSN_DELETED_P (@var{x})
-In an @code{insn}, nonzero if the insn has been deleted. Stored in the
+In an @code{insn}, @code{call_insn}, @code{jump_insn}, @code{code_label},
+@code{barrier}, or @code{note},
+nonzero if the insn has been deleted. Stored in the
@code{volatil} field and printed as @samp{/v}.
@findex INSN_FROM_TARGET_P
@cindex @code{insn} and @samp{/s}
-@cindex @code{in_struct}, in @code{insn}
+@cindex @code{jump_insn} and @samp{/s}
+@cindex @code{call_insn} and @samp{/s}
+@cindex @code{in_struct}, in @code{insn} and @code{jump_insn} and @code{call_insn}
@item INSN_FROM_TARGET_P (@var{x})
-In an @code{insn} in a delay slot of a branch, indicates that the insn
+In an @code{insn} or @code{jump_insn} or @code{call_insn} in a delay
+slot of a branch, indicates that the insn
is from the target of the branch. If the branch insn has
@code{INSN_ANNULLED_BRANCH_P} set, this insn will only be executed if
the branch is taken. For annulled branches with
@@ -441,39 +456,23 @@ label. Stored in the @code{in_struct} field and printed as @samp{/s}.
@findex LABEL_PRESERVE_P
@cindex @code{code_label} and @samp{/i}
-@cindex @code{in_struct}, in @code{code_label}
+@cindex @code{note} and @samp{/i}
+@cindex @code{in_struct}, in @code{code_label} and @code{note}
@item LABEL_PRESERVE_P (@var{x})
-In a @code{code_label}, indicates that the label is referenced by
+In a @code{code_label} or @code{note}, indicates that the label is referenced by
code or data not visible to the RTL of a given function.
Labels referenced by a non-local goto will have this bit set. Stored
in the @code{in_struct} field and printed as @samp{/s}.
@findex LABEL_REF_NONLOCAL_P
@cindex @code{label_ref} and @samp{/v}
-@cindex @code{volatil}, in @code{label_ref}
+@cindex @code{reg_label} and @samp{/v}
+@cindex @code{volatil}, in @code{label_ref} and @code{reg_label}
@item LABEL_REF_NONLOCAL_P (@var{x})
In @code{label_ref} and @code{reg_label} expressions, nonzero if this is
a reference to a non-local label.
Stored in the @code{volatil} field and printed as @samp{/v}.
-@findex LINK_COST_FREE
-@cindex @code{insn_list} and @samp{/c}
-@cindex @code{call}, in @code{insn_list}
-@item LINK_COST_FREE (@var{x})
-In the @code{LOG_LINKS} @code{insn_list} during scheduling, nonzero when
-the cost of executing an instruction through the link is zero, i.e., the
-link makes the cost free. Stored in the @code{call} field and printed
-as @samp{/c}.
-
-@findex LINK_COST_ZERO
-@cindex @code{insn_list} and @samp{/j}
-@cindex @code{jump}, in @code{insn_list}
-@item LINK_COST_ZERO (@var{x})
-In the @code{LOG_LINKS} @code{insn_list} during scheduling, nonzero when
-the cost of executing an instruction through the link varies and is
-unchanged, i.e., the link has zero additional cost.
-Stored in the @code{jump} field and printed as @samp{/j}.
-
@findex MEM_IN_STRUCT_P
@cindex @code{mem} and @samp{/s}
@cindex @code{in_struct}, in @code{mem}
@@ -508,10 +507,12 @@ Stored in the @code{frame_related} field and printed as @samp{/f}.
@findex MEM_VOLATILE_P
@cindex @code{mem} and @samp{/v}
-@cindex @code{volatil}, in @code{mem}
+@cindex @code{asm_input} and @samp{/v}
+@cindex @code{asm_operands} and @samp{/v}
+@cindex @code{volatil}, in @code{mem}, @code{asm_operands}, and @code{asm_input}
@item MEM_VOLATILE_P (@var{x})
-In @code{mem} and @code{asm_operands} expressions, nonzero for volatile
-memory references.
+In @code{mem}, @code{asm_operands}, and @code{asm_input} expressions,
+nonzero for volatile memory references.
Stored in the @code{volatil} field and printed as @samp{/v}.
@findex REG_FUNCTION_VALUE_P
@@ -553,9 +554,14 @@ in this kind of use.
@findex RTX_FRAME_RELATED_P
@cindex @code{insn} and @samp{/f}
-@cindex @code{frame_related}, in @code{insn}
+@cindex @code{call_insn} and @samp{/f}
+@cindex @code{jump_insn} and @samp{/f}
+@cindex @code{barrier} and @samp{/f}
+@cindex @code{set} and @samp{/f}
+@cindex @code{frame_related}, in @code{insn}, @code{call_insn}, @code{jump_insn}, @code{barrier}, and @code{set}
@item RTX_FRAME_RELATED_P (@var{x})
-Nonzero in an @code{insn} or @code{set} which is part of a function prologue
+Nonzero in an @code{insn}, @code{call_insn}, @code{jump_insn},
+@code{barrier}, or @code{set} which is part of a function prologue
and sets the stack pointer, sets the frame pointer, or saves a register.
This flag should also be set on an instruction that sets up a temporary
register to use in place of the frame pointer.
@@ -582,26 +588,39 @@ prologues.
@findex RTX_INTEGRATED_P
@cindex @code{insn} and @samp{/i}
-@cindex @code{integrated}, in @code{insn}
+@cindex @code{call_insn} and @samp{/i}
+@cindex @code{jump_insn} and @samp{/i}
+@cindex @code{barrier} and @samp{/i}
+@cindex @code{code_label} and @samp{/i}
+@cindex @code{insn_list} and @samp{/i}
+@cindex @code{const} and @samp{/i}
+@cindex @code{note} and @samp{/i}
+@cindex @code{integrated}, in @code{insn}, @code{call_insn}, @code{jump_insn}, @code{barrier}, @code{code_label}, @code{insn_list}, @code{const}, and @code{note}
@item RTX_INTEGRATED_P (@var{x})
-Nonzero in an @code{insn}, @code{insn_list}, or @code{const} if it
+Nonzero in an @code{insn}, @code{call_insn}, @code{jump_insn}, @code{barrier},
+@code{code_label}, @code{insn_list}, @code{const}, or @code{note} if it
resulted from an in-line function call.
Stored in the @code{integrated} field and printed as @samp{/i}.
@findex RTX_UNCHANGING_P
@cindex @code{reg} and @samp{/u}
@cindex @code{mem} and @samp{/u}
+@cindex @code{concat} and @samp{/u}
@cindex @code{unchanging}, in @code{reg} and @code{mem}
@item RTX_UNCHANGING_P (@var{x})
-Nonzero in a @code{reg} or @code{mem} if the memory is set at most once,
+Nonzero in a @code{reg}, @code{mem}, or @code{concat} if the memory
+is set at most once,
anywhere. This does not mean that it is function invariant.
Stored in the @code{unchanging} field and printed as @samp{/u}.
@findex SCHED_GROUP_P
-@cindex @code{insn} and @samp{/i}
-@cindex @code{in_struct}, in @code{insn}
+@cindex @code{insn} and @samp{/s}
+@cindex @code{call_insn} and @samp{/s}
+@cindex @code{jump_insn} and @samp{/s}
+@cindex @code{in_struct}, in @code{insn}, @code{jump_insn} and @code{call_insn}
@item SCHED_GROUP_P (@var{x})
-During instruction scheduling, in an @code{insn}, indicates that the
+During instruction scheduling, in an @code{insn}, @code{call_insn} or
+@code{jump_insn}, indicates that the
previous insn must be scheduled together with this insn. This is used to
ensure that certain groups of instructions will not be split up by the
instruction scheduling pass, for example, @code{use} insns before
@@ -631,13 +650,29 @@ string constant pool.
Stored in the @code{frame_related} field and printed as @samp{/f}.
@findex SUBREG_PROMOTED_UNSIGNED_P
-@cindex @code{subreg} and @samp{/u}
+@cindex @code{subreg} and @samp{/u} and @samp{/v}
@cindex @code{unchanging}, in @code{subreg}
+@cindex @code{volatil}, in @code{subreg}
@item SUBREG_PROMOTED_UNSIGNED_P (@var{x})
-Nonzero in a @code{subreg} that has @code{SUBREG_PROMOTED_VAR_P} nonzero
-if the object being referenced is kept zero-extended and zero if it
-is kept sign-extended. Stored in the @code{unchanging} field and
-printed as @samp{/u}.
+Returns a value greater then zero for a @code{subreg} that has
+@code{SUBREG_PROMOTED_VAR_P} nonzero if the object being referenced is kept
+zero-extended, zero if it is kept sign-extended, and less then zero if it is
+extended some other way via the @code{ptr_extend} instruction.
+Stored in the @code{unchanging}
+field and @code{volatil} field, printed as @samp{/u} and @samp{/v}.
+This macro may only be used to get the value it may not be used to change
+the value. Use @code{SUBREG_PROMOTED_UNSIGNED_SET} to change the value.
+
+@findex SUBREG_PROMOTED_UNSIGNED_SET
+@cindex @code{subreg} and @samp{/u}
+@cindex @code{unchanging}, in @code{subreg}
+@cindex @code{volatil}, in @code{subreg}
+@item SUBREG_PROMOTED_UNSIGNED_SET (@var{x})
+Set the @code{unchanging} and @code{volatil} fields in a @code{subreg}
+to reflect zero, sign, or other extension. If @code{volatil} is
+zero, then @code{unchanging} as nonzero means zero extension and as
+zero means sign extension. If @code{volatil} is nonzero then some
+other type of extension was done via the @code{ptr_extend} instruction.
@findex SUBREG_PROMOTED_VAR_P
@cindex @code{subreg} and @samp{/s}
@@ -680,8 +715,7 @@ These are the fields to which the above macros refer:
@findex call
@cindex @samp{/c} in RTL dump
@item call
-In the @code{LOG_LINKS} of an @code{insn_list} during scheduling, 1 means that
-the cost of executing an instruction through the link is zero.
+This flag is currently unused.
In an RTL dump, this flag is represented as @samp{/c}.
@@ -729,7 +763,8 @@ label that would have been deleted is replaced with a @code{note} of type
In an @code{insn} during dead-code elimination, 1 means that the insn is
dead code.
-In an @code{insn} during reorg for an insn in the delay slot of a branch,
+In an @code{insn} or @code{jump_insn} during reorg for an insn in the
+delay slot of a branch,
1 means that this insn is from the target of the branch.
In an @code{insn} during instruction scheduling, 1 means that this insn
@@ -763,9 +798,6 @@ In a @code{set}, 1 means it is for a return.
In a @code{call_insn}, 1 means it is a sibling call.
-In the @code{LOG_LINKS} of an @code{insn_list} during scheduling, 1 means the
-cost of executing an instruction through the link varies and is unchanging.
-
In an RTL dump, this flag is represented as @samp{/j}.
@findex unchanging
@@ -777,7 +809,8 @@ that the value of the expression never changes.
In @code{subreg} expressions, it is 1 if the @code{subreg} references an
unsigned object whose mode has been promoted to a wider mode.
-In an @code{insn}, 1 means that this is an annulling branch.
+In an @code{insn} or @code{jump_insn} in the delay slot of a branch
+instruction, 1 means an annulling branch should be used.
In a @code{symbol_ref} expression, 1 means that this symbol addresses
something in the per-function constant pool.
@@ -805,7 +838,8 @@ the symbol has already been written.
@cindex @samp{/v} in RTL dump
@item volatil
@cindex volatile memory references
-In a @code{mem} or @code{asm_operands} expression, it is 1 if the memory
+In a @code{mem}, @code{asm_operands}, or @code{asm_input}
+expression, it is 1 if the memory
reference is volatile. Volatile memory references may not be deleted,
reordered or combined.
@@ -1188,7 +1222,7 @@ If @var{m} is @code{VOIDmode}, the bits of the value are stored in
If the constant is floating point (regardless of its precision), then
the number of integers used to store the value depends on the size of
-@code{REAL_VALUE_TYPE} (@pxref{Cross-compilation}). The integers
+@code{REAL_VALUE_TYPE} (@pxref{Floating Point}). The integers
represent a floating point number, but not precisely in the target
machine's or host machine's floating point format. To convert them to
the precise bit pattern used by the target machine, use the macro
@@ -1511,7 +1545,7 @@ preferable approach if only a small subset of instructions modify the
condition code. Other machines store condition codes in general
registers; in such cases a pseudo register should be used.
-Some machines, such as the Sparc and RS/6000, have two sets of
+Some machines, such as the SPARC and RS/6000, have two sets of
arithmetic instructions, one that sets and one that does not set the
condition code. This is best handled by normally generating the
instruction that does not set the condition code, and making a pattern
@@ -1542,6 +1576,10 @@ a unit of memory is accessed. @var{alias} specifies an alias set for the
reference. In general two items are in different alias sets if they cannot
reference the same memory address.
+The construct @code{(mem:BLK (scratch))} is considered to alias all
+other memories. Thus it may be used as a memory barrier in epilogue
+stack deallocation patterns.
+
@findex addressof
@item (addressof:@var{m} @var{reg})
This RTX represents a request for the address of register @var{reg}. Its mode
@@ -1816,14 +1854,14 @@ valid.
Comparison operators test a relation on two operands and are considered
to represent a machine-dependent nonzero value described by, but not
necessarily equal to, @code{STORE_FLAG_VALUE} (@pxref{Misc})
-if the relation holds, or zero if it does not. The mode of the
-comparison operation is independent of the mode of the data being
-compared. If the comparison operation is being tested (e.g., the first
-operand of an @code{if_then_else}), the mode must be @code{VOIDmode}.
-If the comparison operation is producing data to be stored in some
-variable, the mode must be in class @code{MODE_INT}. All comparison
-operations producing data must use the same mode, which is
-machine-specific.
+if the relation holds, or zero if it does not, for comparison operators
+whose results have a `MODE_INT' mode, and
+@code{FLOAT_STORE_FLAG_VALUE} (@pxref{Misc}) if the relation holds, or
+zero if it does not, for comparison operators that return floating-point
+values. The mode of the comparison operation is independent of the mode
+of the data being compared. If the comparison operation is being tested
+(e.g., the first operand of an @code{if_then_else}), the mode must be
+@code{VOIDmode}.
@cindex condition codes
There are two ways that comparison operations may be used. The
@@ -2256,7 +2294,8 @@ trouble to describe the values that are stored, but it is essential to
inform the compiler that the registers will be altered, lest it
attempt to keep data in them across the string instruction.
-If @var{x} is @code{(mem:BLK (const_int 0))}, it means that all memory
+If @var{x} is @code{(mem:BLK (const_int 0))} or
+@code{(mem:BLK (scratch))}, it means that all memory
locations must be presumed clobbered. If @var{x} is a @code{parallel},
it has the same meaning as a @code{parallel} in a @code{set} expression.
@@ -2538,9 +2577,6 @@ Represents the side effect of setting @var{x} to @var{y} and
represents @var{x} before @var{x} is modified. @var{x} must be a
@code{reg} or @code{mem}, but most machines allow only a @code{reg}.
@var{m} must be the machine mode for pointers on the machine in use.
-The amount @var{x} is decremented by is the length in bytes of the
-machine mode of the containing memory reference of which this expression
-serves as the address. Note that this is not currently implemented.
The expression @var{y} must be one of three forms:
@table @code
@@ -2560,7 +2596,7 @@ Here is an example of its use:
This says to modify pseudo register 42 by adding the contents of pseudo
register 48 to it, after the use of what ever 42 points to.
-@findex post_modify
+@findex pre_modify
@item (pre_modify:@var{m} @var{x} @var{expr})
Similar except side effects happen before the use.
@end table
@@ -2792,13 +2828,32 @@ Besides as a @code{code_label}, a label can also be represented as a
@findex LABEL_NUSES
The field @code{LABEL_NUSES} is only defined once the jump optimization
-phase is completed and contains the number of times this label is
+phase is completed. It contains the number of times this label is
referenced in the current function.
-@findex LABEL_ALTERNATE_NAME
-The field @code{LABEL_ALTERNATE_NAME} is used to associate a name with
-a @code{code_label}. If this field is defined, the alternate name will
-be emitted instead of an internally generated label name.
+@findex LABEL_KIND
+@findex SET_LABEL_KIND
+@findex LABEL_ALT_ENTRY_P
+@cindex alternate entry points
+The field @code{LABEL_KIND} differentiates four different types of
+labels: @code{LABEL_NORMAL}, @code{LABEL_STATIC_ENTRY},
+@code{LABEL_GLOBAL_ENTRY}, and @code{LABEL_WEAK_ENTRY}. The only labels
+that do not have type @code{LABEL_NORMAL} are @dfn{alternate entry
+points} to the current function. These may be static (visible only in
+the containing translation unit), global (exposed to all translation
+units), or weak (global, but can be overridden by another symbol with the
+same name).
+
+Much of the compiler treats all four kinds of label identically. Some
+of it needs to know whether or not a label is an alternate entry point;
+for this purpose, the macro @code{LABEL_ALT_ENTRY_P} is provided. It is
+equivalent to testing whether @samp{LABEL_KIND (label) == LABEL_NORMAL}.
+The only place that cares about the distinction between static, global,
+and weak alternate entry points, besides the front-end code that creates
+them, is the function @code{output_alternate_entry_point}, in
+@file{final.c}.
+
+To set the kind of a label, use the @code{SET_LABEL_KIND} macro.
@findex barrier
@item barrier
@@ -3199,12 +3254,6 @@ 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
diff --git a/contrib/gcc/doc/service.texi b/contrib/gcc/doc/service.texi
index 8637744..4cc2b70 100644
--- a/contrib/gcc/doc/service.texi
+++ b/contrib/gcc/doc/service.texi
@@ -1,5 +1,5 @@
@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-@c 1999, 2000, 2001 Free Software Foundation, Inc.
+@c 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -24,7 +24,5 @@ The service directory is found at
@uref{http://www.gnu.org/prep/service.html}.
@end itemize
-@c For further information, see
-@c @uref{http://gcc.gnu.org/cgi-bin/fom.cgi?file=12}.
-@c FIXME: this URL may be too volatile, this FAQ entry needs to move to
-@c the regular web pages before we can uncomment the reference.
+For further information, see
+@uref{http://gcc.gnu.org/faq.html#support}.
diff --git a/contrib/gcc/doc/sourcebuild.texi b/contrib/gcc/doc/sourcebuild.texi
index 8977869..c60dcfa 100644
--- a/contrib/gcc/doc/sourcebuild.texi
+++ b/contrib/gcc/doc/sourcebuild.texi
@@ -124,7 +124,7 @@ the files in these directories.
@item config
Configuration files for supported architectures and operating
systems. @xref{Back End, , Anatomy of a Target Back End}, for
-details of the files in thie directory.
+details of the files in this directory.
@item doc
Texinfo documentation for GCC, together with automatically generated
@@ -155,7 +155,7 @@ various languages, @file{@var{language}.po}. This directory also
contains @file{gcc.pot}, the template for these message catalogues,
@file{exgettext}, a wrapper around @command{gettext} to extract the
messages from the GCC sources and create @file{gcc.pot}, which is run
-by @command{make gcc.pot}, and @file{EXCLUDES}, a list of files from
+by @samp{make gcc.pot}, and @file{EXCLUDES}, a list of files from
which messages should not be extracted.
@item testsuite
@@ -246,8 +246,8 @@ libraries are also installed by GCC; these are not documented here.
Several of the headers GCC installs are in the @file{ginclude}
directory. These headers, @file{iso646.h},
-@file{stdarg.h}, @file{stdbool.h}, @file{stddef.h} and
-@file{varargs.h}, are installed in @file{@var{libsubdir}/include},
+@file{stdarg.h}, @file{stdbool.h}, and @file{stddef.h},
+are installed in @file{@var{libsubdir}/include},
unless the target Makefile fragment (@pxref{Target Fragment})
overrides this by setting @code{USER_H}.
@@ -255,12 +255,13 @@ In addition to these headers and those generated by fixing system
headers to work with GCC, some other headers may also be installed in
@file{@var{libsubdir}/include}. @file{config.gcc} may set
@code{extra_headers}; this specifies additional headers under
-@file{config} to be installed on some systems. GCC normally installs
-a @code{<float.h>} file; these are kept as
-@file{config/float-@var{format}.h}, where @var{format} is specified by
-a @code{float_format} setting in @file{config.gcc}, and a setting
-@samp{float_format=none} disables installation of this header. GCC
-also installs its own version of @code{<limits.h>}; this is generated
+@file{config} to be installed on some systems.
+
+GCC installs its own version of @code{<float.h>}, from @file{ginclude/float.h}.
+This is done to cope with command-line options that change the
+representation of floating point numbers.
+
+GCC also installs its own version of @code{<limits.h>}; this is generated
from @file{glimits.h}, together with @file{limitx.h} and
@file{limity.h} if the system also has its own version of
@code{<limits.h>}. (GCC provides its own header because it is
@@ -277,7 +278,7 @@ needs fixing, @file{syslimits.h} is the fixed copy.
The main GCC documentation is in the form of manuals in Texinfo
format. These are installed in Info format, and DVI versions may be
-generated by @command{make dvi}. In addition, some man pages are
+generated by @samp{make dvi}. In addition, some man pages are
generated from the Texinfo manuals, there are some other text files
with miscellaneous documentation, and runtime libraries have their own
documentation outside the @file{gcc} directory. FIXME: document the
@@ -311,9 +312,9 @@ The GNU General Public License.
A copy of @file{texinfo.tex} known to work with the GCC manuals.
@end table
-DVI formatted manuals are generated by @command{make dvi}, which uses
+DVI formatted manuals are generated by @samp{make dvi}, which uses
@command{texi2dvi} (via the Makefile macro @code{$(TEXI2DVI)}). Info
-manuals are generated by @command{make info} (which is run as part of
+manuals are generated by @samp{make info} (which is run as part of
a bootstrap); this generates the manuals in the source directory,
using @command{makeinfo} via the Makefile macro @code{$(MAKEINFO)},
and they are included in release distributions.
@@ -329,7 +330,7 @@ not themselves the root files of manuals, may have names that appear
more than once in the source tree.) The manual file
@file{@var{name}.texi} should only include other files in its own
directory or in @file{doc/include}. HTML manuals will be generated by
-@command{makeinfo --html} and PostScript manuals by @command{texi2dvi}
+@samp{makeinfo --html} and PostScript manuals by @command{texi2dvi}
and @command{dvips}. All Texinfo files that are parts of manuals must
be checked into CVS, even if they are generated files, for the
generation of online manuals to work.
@@ -492,6 +493,9 @@ inclusion in GCC, should be made available on the GCC FTP site
@item
The release and snapshot script @file{maintainer-scripts/gcc_release}
should be updated to generate appropriate tarballs for this front end.
+The associated @file{maintainer-scripts/snapshot-README} and
+@file{maintainer-scripts/snapshot-index.html} files should be updated
+to list the tarballs and diffs for this front end.
@item
If this front end includes its own version files that include the
current date, @file{maintainer-scripts/update_version} should be
@@ -537,7 +541,7 @@ deprecated).
FIXME: exactly what goes in each of these targets?
@item info
Build info documentation for the front end, in the source directory.
-This target is only called by @command{make bootstrap} if a suitable
+This target is only called by @samp{make bootstrap} if a suitable
version of @command{makeinfo} is available, so does not need to check
for this, and should fail if an error occurs.
@item dvi
@@ -607,9 +611,10 @@ codes.
@node Front End Config
@subsubsection The Front End @file{config-lang.in} File
-Each language subdirectory contains a @file{config-lang.in} file.
-This file is a shell script that may define some variables describing
-the language:
+Each language subdirectory contains a @file{config-lang.in} file. In
+addition the main directory contains @file{c-config-lang.in}, which
+contains limited information for the C language. This file is a shell
+script that may define some variables describing the language:
@table @code
@item language
@@ -652,6 +657,12 @@ by @file{configure} substituting values in them. This mechanism can
be used to create a file @file{@var{language}/Makefile} from
@file{@var{language}/Makefile.in}, but this is deprecated, building
everything from the single @file{gcc/Makefile} is preferred.
+@item gtfiles
+If defined, a space-separated list of files that should be scanned by
+gengtype.c to generate the garbage collection tables and routines for
+this language. This excludes the files that are common to all front
+ends. @xref{Type Information}.
+
@end table
@node Back End
@@ -671,6 +682,10 @@ possibly a target Makefile fragment @file{t-@var{machine}}
some other files. The names of these files may be changed from the
defaults given by explicit specifications in @file{config.gcc}.
@item
+If necessary, a file @file{@var{machine}-modes.def} in the
+@file{@var{machine}} directory, containing additional machine modes to
+represent condition codes. @xref{Condition Code}, for further details.
+@item
Entries in @file{config.gcc} (@pxref{System Config, , The
@file{config.gcc} File}) for the systems with this target
architecture.
@@ -736,9 +751,12 @@ suites. Currently only the C language test suites are documented
here; FIXME: document the others.
@menu
-* Test Idioms:: Idioms used in test suite code.
-* C Tests:: The C language test suites.
-* libgcj Tests:: The Java library test suites.
+* Test Idioms:: Idioms used in test suite code.
+* C Tests:: The C language test suites.
+* libgcj Tests:: The Java library test suites.
+* gcov Testing:: Support for testing gcov.
+* profopt Testing:: Support for testing profile-directed optimizations.
+* compat Testing:: Support for testing binary compatibility.
@end menu
@node Test Idioms
@@ -810,6 +828,10 @@ the function should remain, that function may be defined as
@code{static} to call @code{abort ()} (although redeclaring a function
as static may not work on all targets).
+All testcases must be portable. Target-specific testcases must have
+appropriate code to avoid causing failures on unsupported systems;
+unfortunately, the mechanisms for this differ by directory.
+
FIXME: discuss non-C test suites here.
@node C Tests
@@ -819,6 +841,42 @@ GCC contains the following C language test suites, in the
@file{gcc/testsuite} directory:
@table @file
+@item gcc.dg
+This contains tests of particular features of the C compiler, using the
+more modern @samp{dg} harness. Correctness tests for various compiler
+features should go here if possible.
+
+Magic comments determine whether the file
+is preprocessed, compiled, linked or run. In these tests, error and warning
+message texts are compared against expected texts or regular expressions
+given in comments. These tests are run with the options @samp{-ansi -pedantic}
+unless other options are given in the test. Except as noted below they
+are not run with multiple optimization options.
+@item gcc.dg/cpp
+This subdirectory contains tests of the preprocessor.
+@item gcc.dg/debug
+This subdirectory contains tests for debug formats. Tests in this
+subdirectory are run for each debug format that the compiler supports.
+@item gcc.dg/format
+This subdirectory contains tests of the @option{-Wformat} format
+checking. Tests in this directory are run with and without
+@option{-DWIDE}.
+@item gcc.dg/noncompile
+This subdirectory contains tests of code that should not compile and
+does not need any special compilation options. They are run with
+multiple optimization options, since sometimes invalid code crashes
+the compiler with optimization.
+@item gcc.dg/special
+FIXME: describe this.
+
+@item gcc.c-torture
+This contains particular code fragments which have historically broken easily.
+These tests are run with multiple optimization options, so tests for features
+which only break at some optimization levels belong here. This also contains
+tests to check that certain optimizations occur. It might be worthwhile to
+separate the correctness tests cleanly from the code quality tests, but
+it hasn't been done yet.
+
@item gcc.c-torture/compat
FIXME: describe this.
@@ -836,37 +894,35 @@ such as @code{NO_LABEL_VALUES} and @code{STACK_SIZE} are used.
@item gcc.c-torture/execute
This test suite contains test cases that should compile, link and run;
otherwise the same comments as for @file{gcc.c-torture/compile} apply.
+@item gcc.c-torture/execute/ieee
+This contains tests which are specific to IEEE floating point.
@item gcc.c-torture/unsorted
FIXME: describe this.
This directory should probably not be used for new tests.
-@item gcc.dg
-This test suite contains tests using the more modern @samp{dg} harness.
-Magic comments determine whether the file is preprocessed, compiled,
-linked or run. In these tests, error and warning message texts are
-compared against expected texts or regular expressions given in
-comments. These tests are run with the options @samp{-ansi -pedantic}
-unless other options are given in the test. Except as noted below they
-are not run with multiple optimization options.
-@item gcc.dg/cpp
-This subdirectory contains tests of the preprocessor.
-@item gcc.dg/debug
-This subdirectory contains tests for debug formats. Tests in this
-subdirectory are run for each debug format that the compiler supports.
-@item gcc.dg/format
-This subdirectory contains tests of the @option{-Wformat} format
-checking. Tests in this directory are run with and without
-@option{-DWIDE}.
-@item gcc.dg/noncompile
-This subdirectory contains tests of code that should not compile and
-does not need any special compilation options. They are run with
-multiple optimization options, since sometimes invalid code crashes
-the compiler with optimization.
-@item gcc.dg/special
-FIXME: describe this.
@item gcc.c-torture/misc-tests
-FIXME: describe this, when it should be used for new tests and when it
-shouldn't.
+This directory contains C tests that require special handling. Some
+of these tests have individual expect files, and others share
+special-purpose expect files:
+
+@table @file
+@item @code{bprob*.c}
+Test @option{-fbranch-probabilities} using @file{bprob.exp}, which
+in turn uses the generic, language-independent framework
+(@pxref{profopt Testing, , Support for testing profile-directed
+optimizations}).
+
+@item @code{dg-*.c}
+Test the testsuite itself using @file{dg-test.exp}.
+
+@item @code{gcov*.c}
+Test @command{gcov} output using @file{gcov.exp}, which in turn uses the
+language-independent support (@pxref{gcov Testing, , Support for testing gcov}).
+
+@item @code{i386-pf-*.c}
+Test i386-specific support for data prefetch using @file{i386-prefetch.exp}.
+@end table
+
@end table
FIXME: merge in @file{testsuite/README.gcc} and discuss the format of
@@ -882,12 +938,208 @@ tests can be checked into this testsuite.
Regression testing of the core packages in libgcj is also covered by the
Mauve test suite. The @uref{http://sources.redhat.com/mauve/,,Mauve Project}
develops tests for the Java Class Libraries. These tests are run as part
-of libgcj testing by specifying the location of the Mauve tree when invoking
-@samp{make}, as in @samp{make MAUVEDIR=~/mauve check}.
+of libgcj testing by placing the Mauve tree within the libjava testsuite
+sources at @file{libjava/testsuite/libjava.mauve/mauve}, or by specifying
+the location of that tree when invoking @samp{make}, as in
+@samp{make MAUVEDIR=~/mauve check}.
+
+To detect regressions, a mechanism in @file{mauve.exp} compares the
+failures for a test run against the list of expected failures in
+@file{libjava/testsuite/libjava.mauve/xfails} from the source hierarchy.
+Update this file when adding new failing tests to Mauve, or when fixing
+bugs in libgcj that had caused Mauve test failures.
The @uref{http://oss.software.ibm.com/developerworks/opensource/jacks/,,
Jacks} project provides a test suite for Java compilers that can be used
-to test changes that affect the GCJ front end. There is no automated
-mechanism to run the Jacks suite as part of GCJ testing.
+to test changes that affect the GCJ front end. This test suite is run as
+part of Java testing by placing the Jacks tree within the the libjava
+testsuite sources at @file{libjava/testsuite/libjava.jacks/jacks}.
We encourage developers to contribute test cases to Mauve and Jacks.
+
+@node gcov Testing
+@subsection Support for testing @command{gcov}
+
+Language-independent support for testing @command{gcov}, and for checking
+that branch profiling produces expected values, is provided by the
+expect file @file{gcov.exp}. @command{gcov} tests also rely on procedures
+in @file{gcc.dg.exp} to compile and run the test program. A typical
+@command{gcov} test contains the following DejaGNU commands within comments:
+
+@smallexample
+@{ dg-options "-fprofile-arcs -ftest-coverage" @}
+@{ dg-do run @{ target native @} @}
+@{ dg-final @{ run-gcov sourcefile @} @}
+@end smallexample
+
+Checks of @command{gcov} output can include line counts, branch percentages,
+and call return percentages. All of these checks are requested via
+commands that appear in comments in the test's source file.
+Commands to check line counts are processed by default.
+Commands to check branch percentages and call return percentages are
+processed if there is a file with the same basename as the source
+file and a suffix @file{.x} that contains a line
+@code{set gcov_verify_branches 1} or @code{set gcov_verify_calls 1},
+respectively.
+
+A line count command appears within a comment on the source line
+that is expected to get the specified count and has the form
+@code{count(@var{cnt})}. A test should only check line counts for
+lines that will get the same count for any architecture.
+
+Commands to check branch percentages (@code{branch}) and call
+return percentages (@code{returns}) are very similar to each other.
+A beginning command appears on or before the first of a range of
+lines that will report the percentage, and the ending command
+follows that range of lines. The beginning command can include a
+list of percentages, all of which are expected to be found within
+the range. A range is terminated by the next command of the same
+kind. A command @code{branch(end)} or @code{returns(end)} marks
+the end of a range without starting a new one. For example:
+
+@smallexample
+if (i > 10 && j > i && j < 20) /* branch(27 50 75) */
+ /* branch(end) */
+ foo (i, j);
+@end smallexample
+
+For a call return percentage, the value specified is the
+percentage of calls reported to return. For a branch percentage,
+the value is either the expected percentage or 100 minus that
+value, since the direction of a branch can differ depending on the
+target or the optimization level.
+
+Not all branches and calls need to be checked. A test should not
+check for branches that might be optimized away or replaced with
+predicated instructions. Don't check for calls inserted by the
+compiler or ones that might be inlined or optimized away.
+
+A single test can check for combinations of line counts, branch
+percentages, and call return percentages. The command to check a
+line count must appear on the line that will report that count, but
+commands to check branch percentages and call return percentages can
+bracket the lines that report them.
+
+@node profopt Testing
+@subsection Support for testing profile-directed optimizations
+
+The file @file{profopt.exp} provides language-independent support for
+checking correct execution of a test built with profile-directed
+optimization. This testing requires that a test program be built and
+executed twice. The first time it is compiled to generate profile
+data, and the second time it is compiled to use the data that was
+generated during the first execution. The second execution is to
+verify that the test produces the expected results.
+
+To check that the optimization actually generated better code, a
+test can be built and run a third time with normal optimizations to
+verify that the performance is better with the profile-directed
+optimizations. @file{profopt.exp} has the beginnings of this kind
+of support.
+
+@file{profopt.exp} provides generic support for profile-directed
+optimizations. Each set of tests that uses it provides information
+about a specific optimization:
+
+@table @code
+@item tool
+tool being tested, e.g., gcc
+
+@item profile_option
+options used to generate profile data
+
+@item feedback_option
+options used to optimize using that profile data
+
+@item prof_ext
+suffix of profile data files
+
+@item PROFOPT_OPTIONS
+list of options with which to run each test, similar to the lists for
+torture tests
+@end table
+
+@node compat Testing
+@subsection Support for testing binary compatibility
+
+The file @file{compat.exp} provides language-independent support for
+binary compatibility testing. It supports testing interoperability
+of two compilers that follow the same ABI, or of multiple sets of
+compiler options that should not affect binary compatibility.
+It is intended to be used for test suites that complement ABI test
+suites.
+
+A test supported by this framework has three parts, each in a
+separate source file: a main program and two pieces that interact
+with each other to split up the functionality being tested.
+
+@table @file
+@item @var{testname}_main.@var{suffix}
+Contains the main program, which calls a function in file
+@file{@var{testname}_x.@var{suffix}}.
+
+@item @var{testname}_x.@var{suffix}
+Contains at least one call to a function in
+@file{@var{testname}_y.@var{suffix}}.
+
+@item @var{testname}_y.@var{suffix}
+Shares data with, or gets arguments from,
+@file{@var{testname}_x.@var{suffix}}.
+@end table
+
+Within each test, the main program and one functional piece are
+compiled by the GCC under test. The other piece can be compiled by
+an alternate compiler. If no alternate compiler is specified,
+then all three source files are all compiled by the GCC under test.
+It's also possible to specify a pair of lists of compiler options,
+one list for each compiler, so that each test will be compiled with
+each pair of options.
+
+@file{compat.exp} defines default pairs of compiler options.
+These can be overridden by defining the environment variable
+@env{COMPAT_OPTIONS} as:
+
+@smallexample
+COMPAT_OPTIONS="[list [list @{@var{tst1}@} @{@var{alt1}@}]
+ ...[list @{@var{tstn}@} @{@var{altn}@}]]"
+@end smallexample
+
+where @var{tsti} and @var{alti} are lists of options, with @var{tsti}
+used by the compiler under test and @var{alti} used by the alternate
+compiler. For example, with
+@code{[list [list @{-g -O0@} @{-O3@}] [list @{-fpic@} @{-fPIC -O2@}]]},
+the test is first built with @code{-g -O0} by the compiler under
+test and with @code{-O3} by the alternate compiler. The test is
+built a second time using @code{-fpic} by the compiler under test
+and @code{-fPIC -O2} by the alternate compiler.
+
+An alternate compiler is specified by defining an environment
+variable; for C++ define @env{ALT_CXX_UNDER_TEST} to be the full
+pathname of an installed compiler. That will be written to the
+@file{site.exp} file used by DejaGNU. The default is to build each
+test with the compiler under test using the first of each pair of
+compiler options from @env{COMPAT_OPTIONS}. When
+@env{ALT_CXX_UNDER_TEST} is @code{same}, each test is built using
+the compiler under test but with combinations of the options from
+@env{COMPAT_OPTIONS}.
+
+To run only the C++ compatibility suite using the compiler under test
+and another version of GCC using specific compiler options, do the
+following from @file{@var{objdir}/gcc}:
+
+@smallexample
+rm site.exp
+make -k \
+ ALT_CXX_UNDER_TEST=$@{alt_prefix@}/bin/g++ \
+ COMPAT_OPTIONS="lists as shown above" \
+ check-c++ \
+ RUNTESTFLAGS="compat.exp"
+@end smallexample
+
+A test that fails when the source files are compiled with different
+compilers, but passes when the files are compiled with the same
+compiler, demonstrates incompatibility of the generated code or
+runtime support. A test that fails for the alternate compiler but
+passes for the compiler under test probably tests for a bug that was
+fixed in the compiler under test but is present in the alternate
+compiler.
diff --git a/contrib/gcc/doc/standards.texi b/contrib/gcc/doc/standards.texi
index b3e8b18..c939498 100644
--- a/contrib/gcc/doc/standards.texi
+++ b/contrib/gcc/doc/standards.texi
@@ -14,7 +14,6 @@
@cindex X3.159-1989
@cindex ISO C standard
@cindex ISO C
-@cindex ISO C89
@cindex ISO C90
@cindex ISO/IEC 9899
@cindex ISO 9899
@@ -80,7 +79,7 @@ as @dfn{AMD1}; the amended standard is sometimes known as @dfn{C94} or
A new edition of the ISO C standard was published in 1999 as ISO/IEC
9899:1999, and is commonly known as @dfn{C99}. GCC has incomplete
support for this standard version; see
-@uref{http://gcc.gnu.org/gcc-3.1/c99status.html} for details. To select this
+@uref{http://gcc.gnu.org/gcc-3.3/c99status.html} for details. To select this
standard, use @option{-std=c99} or @option{-std=iso9899:1999}. (While in
development, drafts of this standard version were referred to as
@dfn{C9X}.)
@@ -89,13 +88,6 @@ Errors in the 1999 ISO C standard were corrected in a Technical
Corrigendum published in 2001. GCC does not support the uncorrected
version.
-@opindex traditional
-GCC also has some limited support for traditional (pre-ISO) C with the
-@option{-traditional} option. This support may be of use for compiling
-some very old programs that have not been updated to ISO C, but should
-not be used for new programs. It will not work with some modern C
-libraries such as the GNU C library.
-
By default, GCC provides some extensions to the C language that on
rare occasions conflict with the C standard. @xref{C
Extensions,,Extensions to the C Language Family}. Use of the
@@ -182,6 +174,13 @@ is an older example
has additional useful information
@end itemize
+@cindex treelang
+There is no standard for treelang, which is a sample language front end
+for GCC. Its only purpose is as a sample for people wishing to write a
+new language for GCC. The language is documented in
+@file{gcc/treelang/treelang.texi} which can be turned into info or
+HTML format.
+
@xref{Top, GNAT Reference Manual, About This Guide, gnat_rm,
GNAT Reference Manual}, for information on standard
conformance and compatibility of the Ada compiler.
@@ -190,4 +189,4 @@ conformance and compatibility of the Ada compiler.
Fortran}, for details of the Fortran language supported by GCC@.
@xref{Compatibility,,Compatibility with the Java Platform, gcj, GNU gcj},
-for details of compatibility between @code{gcj} and the Java Platform.
+for details of compatibility between @command{gcj} and the Java Platform.
diff --git a/contrib/gcc/doc/tm.texi b/contrib/gcc/doc/tm.texi
index 4b29d52..21c7c2a 100644
--- a/contrib/gcc/doc/tm.texi
+++ b/contrib/gcc/doc/tm.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1988,1989,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002
+@c Copyright (C) 1988,1989,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003
@c Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -46,9 +46,10 @@ through the macros defined in the @file{.h} file.
* PIC:: Macros for position independent code.
* Assembler Format:: Defining how to write insns and pseudo-ops to output.
* Debugging Info:: Defining the format of debugging output.
-* Cross-compilation:: Handling floating point for cross-compilers.
+* Floating Point:: Handling floating point for cross-compilers.
* Mode Switching:: Insertion of mode-switching instructions.
* Target Attributes:: Defining target-specific uses of @code{__attribute__}.
+* MIPS Coprocessors:: MIPS coprocessor support and how to customize it.
* Misc:: Everything else.
@end menu
@@ -162,6 +163,23 @@ multilibs. Example nonsensical definition, where @code{-malt-abi},
@{ "-compat", "-EB -malign=4 -mspoo" @}
@end smallexample
+@findex DRIVER_SELF_SPECS
+@item DRIVER_SELF_SPECS
+A list of specs for the driver itself. It should be a suitable
+initializer for an array of strings, with no surrounding braces.
+
+The driver applies these specs to its own command line before choosing
+the multilib directory or running any subcommands. It applies them in
+the order given, so each spec can depend on the options added by
+earlier ones. It is also possible to remove options using
+@samp{%<@var{option}} in the usual way.
+
+This macro can be useful when a port has several interdependent target
+options. It provides a way of standardizing the command line so
+that the other specs are easier to write.
+
+Do not define this macro if it does not need to do anything.
+
@findex CPP_SPEC
@item CPP_SPEC
A C string constant that tells the GCC driver program options to
@@ -176,46 +194,6 @@ This macro is just like @code{CPP_SPEC}, but is used for C++, rather
than C@. If you do not define this macro, then the value of
@code{CPP_SPEC} (if any) will be used instead.
-@findex NO_BUILTIN_SIZE_TYPE
-@item NO_BUILTIN_SIZE_TYPE
-If this macro is defined, the preprocessor will not define the built-in macro
-@code{__SIZE_TYPE__}. The macro @code{__SIZE_TYPE__} must then be defined
-by @code{CPP_SPEC} instead.
-
-This should be defined if @code{SIZE_TYPE} depends on target dependent flags
-which are not accessible to the preprocessor. Otherwise, it should not
-be defined.
-
-@findex NO_BUILTIN_PTRDIFF_TYPE
-@item NO_BUILTIN_PTRDIFF_TYPE
-If this macro is defined, the preprocessor will not define the built-in macro
-@code{__PTRDIFF_TYPE__}. The macro @code{__PTRDIFF_TYPE__} must then be
-defined by @code{CPP_SPEC} instead.
-
-This should be defined if @code{PTRDIFF_TYPE} depends on target dependent flags
-which are not accessible to the preprocessor. Otherwise, it should not
-be defined.
-
-@findex NO_BUILTIN_WCHAR_TYPE
-@item NO_BUILTIN_WCHAR_TYPE
-If this macro is defined, the preprocessor will not define the built-in macro
-@code{__WCHAR_TYPE__}. The macro @code{__WCHAR_TYPE__} must then be
-defined by @code{CPP_SPEC} instead.
-
-This should be defined if @code{WCHAR_TYPE} depends on target dependent flags
-which are not accessible to the preprocessor. Otherwise, it should not
-be defined.
-
-@findex NO_BUILTIN_WINT_TYPE
-@item NO_BUILTIN_WINT_TYPE
-If this macro is defined, the preprocessor will not define the built-in macro
-@code{__WINT_TYPE__}. The macro @code{__WINT_TYPE__} must then be
-defined by @code{CPP_SPEC} instead.
-
-This should be defined if @code{WINT_TYPE} depends on target dependent flags
-which are not accessible to the preprocessor. Otherwise, it should not
-be defined.
-
@findex CC1_SPEC
@item CC1_SPEC
A C string constant that tells the GCC driver program options to
@@ -412,7 +390,7 @@ the target makefile fragment or if none of the options listed in
@findex RELATIVE_PREFIX_NOT_LINKDIR
@item RELATIVE_PREFIX_NOT_LINKDIR
-Define this macro to tell @code{gcc} that it should only translate
+Define this macro to tell @command{gcc} that it should only translate
a @option{-B} prefix into a @option{-L} linker option if the prefix
indicates an absolute file name.
@@ -622,6 +600,53 @@ The macro @code{STANDARD_STARTFILE_PREFIX}.
Here are run-time target specifications.
@table @code
+@findex TARGET_CPU_CPP_BUILTINS
+@item TARGET_CPU_CPP_BUILTINS()
+This function-like macro expands to a block of code that defines
+built-in preprocessor macros and assertions for the target cpu, using
+the functions @code{builtin_define}, @code{builtin_define_std} and
+@code{builtin_assert} defined in @file{c-common.c}. When the front end
+calls this macro it provides a trailing semicolon, and since it has
+finished command line option processing your code can use those
+results freely.
+
+@code{builtin_assert} takes a string in the form you pass to the
+command-line option @option{-A}, such as @code{cpu=mips}, and creates
+the assertion. @code{builtin_define} takes a string in the form
+accepted by option @option{-D} and unconditionally defines the macro.
+
+@code{builtin_define_std} takes a string representing the name of an
+object-like macro. If it doesn't lie in the user's namespace,
+@code{builtin_define_std} defines it unconditionally. Otherwise, it
+defines a version with two leading underscores, and another version
+with two leading and trailing underscores, and defines the original
+only if an ISO standard was not requested on the command line. For
+example, passing @code{unix} defines @code{__unix}, @code{__unix__}
+and possibly @code{unix}; passing @code{_mips} defines @code{__mips},
+@code{__mips__} and possibly @code{_mips}, and passing @code{_ABI64}
+defines only @code{_ABI64}.
+
+You can also test for the C dialect being compiled. The variable
+@code{c_language} is set to one of @code{clk_c}, @code{clk_cplusplus}
+or @code{clk_objective_c}. Note that if we are preprocessing
+assembler, this variable will be @code{clk_c} but the function-like
+macro @code{preprocessing_asm_p()} will return true, so you might want
+to check for that first. If you need to check for strict ANSI, the
+variable @code{flag_iso} can be used. The function-like macro
+@code{preprocessing_trad_p()} can be used to check for traditional
+preprocessing.
+
+With @code{TARGET_OS_CPP_BUILTINS} this macro obsoletes the
+@code{CPP_PREDEFINES} target macro.
+
+@findex TARGET_OS_CPP_BUILTINS
+@item TARGET_OS_CPP_BUILTINS()
+Similarly to @code{TARGET_CPU_CPP_BUILTINS} but this macro is optional
+and is used for the target operating system instead.
+
+With @code{TARGET_CPU_CPP_BUILTINS} this macro obsoletes the
+@code{CPP_PREDEFINES} target macro.
+
@findex CPP_PREDEFINES
@item CPP_PREDEFINES
Define this to be a string constant containing @option{-D} options to
@@ -819,11 +844,9 @@ structure contains a field called @code{machine} whose type is
to their own specific data.
If a target needs per-function specific data it should define the type
-@code{struct machine_function} and also the macro
-@code{INIT_EXPANDERS}. This macro should be used to initialize some or
-all of the function pointers @code{init_machine_status},
-@code{free_machine_status} and @code{mark_machine_status}. These
-pointers are explained below.
+@code{struct machine_function} and also the macro @code{INIT_EXPANDERS}.
+This macro should be used to initialize the function pointer
+@code{init_machine_status}. This pointer is explained below.
One typical use of per-function, target specific data is to create an
RTX to hold the register containing the function's return address. This
@@ -859,19 +882,9 @@ specific initialization of the @code{struct function} structure. It is
intended that this would be used to initialize the @code{machine} of
that structure.
-@findex free_machine_status
-@item free_machine_status
-This is a @code{void (*)(struct function *)} function pointer. If this
-pointer is non-@code{NULL} it will be called once per function, after the
-function has been compiled, in order to allow any memory allocated
-during the @code{init_machine_status} function call to be freed.
-
-@findex mark_machine_status
-@item mark_machine_status
-This is a @code{void (*)(struct function *)} function pointer. If this
-pointer is non-@code{NULL} it will be called once per function in order to mark
-any data items in the @code{struct machine_function} structure which
-need garbage collection.
+@code{struct machine_function} structures are expected to be freed by GC.
+Generally, any memory that they reference must be allocated by using
+@code{ggc_alloc}, including the structure itself.
@end table
@@ -930,11 +943,12 @@ multi-word integers.
@findex BITS_PER_UNIT
@item BITS_PER_UNIT
Define this macro to be the number of bits in an addressable storage
-unit (byte); normally 8.
+unit (byte). If you do not define this macro the default is 8.
@findex BITS_PER_WORD
@item BITS_PER_WORD
-Number of bits in a word; normally 32.
+Number of bits in a word. If you do not define this macro, the default
+is @code{BITS_PER_UNIT * UNITS_PER_WORD}.
@findex MAX_BITS_PER_WORD
@item MAX_BITS_PER_WORD
@@ -956,7 +970,8 @@ smallest value that @code{UNITS_PER_WORD} can have at run-time.
@item POINTER_SIZE
Width of a pointer, in bits. You must specify a value no wider than the
width of @code{Pmode}. If it is not equal to the width of @code{Pmode},
-you must define @code{POINTERS_EXTEND_UNSIGNED}.
+you must define @code{POINTERS_EXTEND_UNSIGNED}. If you do not specify
+a value the default is @code{BITS_PER_WORD}.
@findex POINTERS_EXTEND_UNSIGNED
@item POINTERS_EXTEND_UNSIGNED
@@ -1219,10 +1234,15 @@ Like @code{PCC_BITFIELD_TYPE_MATTERS} except that its effect is limited
to aligning a bit-field within the structure.
@findex MEMBER_TYPE_FORCES_BLK
-@item MEMBER_TYPE_FORCES_BLK (@var{field})
+@item MEMBER_TYPE_FORCES_BLK (@var{field}, @var{mode})
Return 1 if a structure or array containing @var{field} should be accessed using
@code{BLKMODE}.
+If @var{field} is the only field in the structure, @var{mode} is its
+mode, otherwise @var{mode} is VOIDmode. @var{mode} is provided in the
+case where structures of one field would require the structure's mode to
+retain the field's mode.
+
Normally, this is not needed. See the file @file{c4x.h} for an example
of how to use this macro to prevent a structure having a floating point
field from being accessed in an integer mode.
@@ -1290,22 +1310,6 @@ You need not define this macro if it always returns @code{word_mode}.
You would most commonly define this macro if the @code{allocate_stack}
pattern needs to support both a 32- and a 64-bit mode.
-@findex CHECK_FLOAT_VALUE
-@item CHECK_FLOAT_VALUE (@var{mode}, @var{value}, @var{overflow})
-A C statement to validate the value @var{value} (of type
-@code{double}) for mode @var{mode}. This means that you check whether
-@var{value} fits within the possible range of values for mode
-@var{mode} on this target machine. The mode @var{mode} is always
-a mode of class @code{MODE_FLOAT}. @var{overflow} is nonzero if
-the value is already known to be out of range.
-
-If @var{value} is not valid or if @var{overflow} is nonzero, you should
-set @var{overflow} to 1 and then assign some valid value to @var{value}.
-Allowing an invalid value to go through the compiler can produce
-incorrect assembler code which may even cause Unix assemblers to crash.
-
-This macro need not be defined if there is no work for it to do.
-
@findex TARGET_FLOAT_FORMAT
@item TARGET_FLOAT_FORMAT
A code distinguishing the floating point format of the target machine.
@@ -1319,7 +1323,8 @@ need to define this macro when the format is IEEE@.
@findex VAX_FLOAT_FORMAT
@item VAX_FLOAT_FORMAT
-This code indicates the ``D float'' format used on the VAX@.
+This code indicates the ``F float'' (for @code{float}) and ``D float''
+or ``G float'' formats (for @code{double}) used on the VAX and PDP-11@.
@findex IBM_FLOAT_FORMAT
@item IBM_FLOAT_FORMAT
@@ -1334,15 +1339,101 @@ This code indicates the format used on the TMS320C3x/C4x.
This code indicates any other format.
@end table
-The value of this macro is compared with @code{HOST_FLOAT_FORMAT}, which
-is defined by the @command{configure} script, to determine whether the
-target machine has the same format as the host machine. If any other
+If any other
formats are actually in use on 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}.
+@findex MODE_HAS_NANS
+@item MODE_HAS_NANS (@var{mode})
+When defined, this macro should be true if @var{mode} has a NaN
+representation. The compiler assumes that NaNs are not equal to
+anything (including themselves) and that addition, subtraction,
+multiplication and division all return NaNs when one operand is
+NaN@.
+
+By default, this macro is true if @var{mode} is a floating-point
+mode and the target floating-point format is IEEE@.
+
+@findex MODE_HAS_INFINITIES
+@item MODE_HAS_INFINITIES (@var{mode})
+This macro should be true if @var{mode} can represent infinity. At
+present, the compiler uses this macro to decide whether @samp{x - x}
+is always defined. By default, the macro is true when @var{mode}
+is a floating-point mode and the target format is IEEE@.
+
+@findex MODE_HAS_SIGNED_ZEROS
+@item MODE_HAS_SIGNED_ZEROS (@var{mode})
+True if @var{mode} distinguishes between positive and negative zero.
+The rules are expected to follow the IEEE standard:
+
+@itemize @bullet
+@item
+@samp{x + x} has the same sign as @samp{x}.
+
+@item
+If the sum of two values with opposite sign is zero, the result is
+positive for all rounding modes expect towards @minus{}infinity, for
+which it is negative.
+
+@item
+The sign of a product or quotient is negative when exactly one
+of the operands is negative.
+@end itemize
+
+The default definition is true if @var{mode} is a floating-point
+mode and the target format is IEEE@.
+
+@findex MODE_HAS_SIGN_DEPENDENT_ROUNDING
+@item MODE_HAS_SIGN_DEPENDENT_ROUNDING (@var{mode})
+If defined, this macro should be true for @var{mode} if it has at
+least one rounding mode in which @samp{x} and @samp{-x} can be
+rounded to numbers of different magnitude. Two such modes are
+towards @minus{}infinity and towards +infinity.
+
+The default definition of this macro is true if @var{mode} is
+a floating-point mode and the target format is IEEE@.
+
+@findex ROUND_TOWARDS_ZERO
+@item ROUND_TOWARDS_ZERO
+If defined, this macro should be true if the prevailing rounding
+mode is towards zero. A true value has the following effects:
+
+@itemize @bullet
+@item
+@code{MODE_HAS_SIGN_DEPENDENT_ROUNDING} will be false for all modes.
+
+@item
+@file{libgcc.a}'s floating-point emulator will round towards zero
+rather than towards nearest.
+
+@item
+The compiler's floating-point emulator will round towards zero after
+doing arithmetic, and when converting from the internal float format to
+the target format.
+@end itemize
+
+The macro does not affect the parsing of string literals. When the
+primary rounding mode is towards zero, library functions like
+@code{strtod} might still round towards nearest, and the compiler's
+parser should behave like the target's @code{strtod} where possible.
+
+Not defining this macro is equivalent to returning zero.
+
+@findex LARGEST_EXPONENT_IS_NORMAL
+@item LARGEST_EXPONENT_IS_NORMAL (@var{size})
+This macro should return true if floats with @var{size}
+bits do not have a NaN or infinity representation, but use the largest
+exponent for normal numbers instead.
+
+Defining this macro to true for @var{size} causes @code{MODE_HAS_NANS}
+and @code{MODE_HAS_INFINITIES} to be false for @var{size}-bit modes.
+It also affects the way @file{libgcc.a} and @file{real.c} emulate
+floating-point arithmetic.
+
+The default definition of this macro returns false for all sizes.
@end table
@deftypefn {Target Hook} bool TARGET_MS_BITFIELD_LAYOUT_P (tree @var{record_type})
@@ -1355,8 +1446,22 @@ alignment of the underlying types of itself and of the previous
bit-field; (ii) a zero-sized bit-field will affect the alignment of
the whole enclosing structure, even if it is unnamed; except that
(iii) a zero-sized bit-field will be disregarded unless it follows
-another bit-field of non-zero size. If this hook returns @code{true},
+another bit-field of nonzero size. If this hook returns @code{true},
other macros that control bit-field layout are ignored.
+
+When a bit-field is inserted into a packed record, the whole size
+of the underlying type is used by one or more same-size adjacent
+bit-fields (that is, if its long:3, 32 bits is used in the record,
+and any additional adjacent long bit-fields are packed into the same
+chunk of 32 bits. However, if the size changes, a new field of that
+size is allocated). In an unpacked record, this is the same as using
+alignment, but not equivalent when packing.
+
+If both MS bit-fields and @samp{__attribute__((packed))} are used,
+the latter will take precedence. If @samp{__attribute__((packed))} is
+used on a single field when MS bit-fields are in use, it will take
+precedence for that field, but the alignment of the rest of the structure
+may affect its placement.
@end deftypefn
@node Type Layout
@@ -1414,14 +1519,6 @@ A C expression for the size in bits of the type @code{char} on the
target machine. If you don't define this, the default is
@code{BITS_PER_UNIT}.
-@findex MAX_CHAR_TYPE_SIZE
-@item MAX_CHAR_TYPE_SIZE
-Maximum number for the size in bits of the type @code{char} on the
-target machine. If this is undefined, the default is
-@code{CHAR_TYPE_SIZE}. Otherwise, it is the constant value that is the
-largest value that @code{CHAR_TYPE_SIZE} can have at run-time. This is
-used in @code{cpp}.
-
@findex BOOL_TYPE_SIZE
@item BOOL_TYPE_SIZE
A C expression for the size in bits of the C++ type @code{bool} and
@@ -1452,9 +1549,12 @@ target machine. If this is undefined, the default is
the largest value that @code{LONG_DOUBLE_TYPE_SIZE} can have at run-time.
This is used in @code{cpp}.
-@findex INTEL_EXTENDED_IEEE_FORMAT
-Define this macro to be 1 if the target machine uses 80-bit floating-point
-values with 128-bit size and alignment. This is used in @file{real.c}.
+@findex TARGET_FLT_EVAL_METHOD
+@item TARGET_FLT_EVAL_METHOD
+A C expression for the value for @code{FLT_EVAL_METHOD} in @file{float.h},
+assuming, if applicable, that the floating-point control word is in its
+default state. If you do not define this macro the value of
+@code{FLT_EVAL_METHOD} will be zero.
@findex WIDEST_HARDWARE_FP_SIZE
@item WIDEST_HARDWARE_FP_SIZE
@@ -1620,6 +1720,20 @@ pointer to which the function's data is relative.
If vtables are used, the value of this macro should be the number
of words that the function descriptor occupies.
+
+@findex TARGET_VTABLE_ENTRY_ALIGN
+@item TARGET_VTABLE_ENTRY_ALIGN
+By default, the vtable entries are void pointers, the so the alignment
+is the same as pointer alignment. The value of this macro specifies
+the alignment of the vtable entry in bits. It should be defined only
+when special alignment is necessary. */
+
+@findex TARGET_VTABLE_DATA_ENTRY_DISTANCE
+@item TARGET_VTABLE_DATA_ENTRY_DISTANCE
+There are a few non-descriptor entries in the vtable at offsets below
+zero. If these entries must be padded (say, to preserve the alignment
+specified by @code{TARGET_VTABLE_ENTRY_ALIGN}), set this to the number
+of words in each data entry.
@end table
@node Escape Sequences
@@ -2190,7 +2304,7 @@ which is the register value plus a displacement.
@findex MODE_BASE_REG_CLASS
@item MODE_BASE_REG_CLASS (@var{mode})
This is a variation of the @code{BASE_REG_CLASS} macro which allows
-the selection of a base register in a mode depenedent manner. If
+the selection of a base register in a mode dependent manner. If
@var{mode} is VOIDmode then it should return the same value as
@code{BASE_REG_CLASS}.
@@ -2299,7 +2413,7 @@ from memory or even from other types of registers. An example is the
from general registers, but not memory. Some machines allow copying all
registers to and from memory, but require a scratch register for stores
to some memory locations (e.g., those with symbolic address on the RT,
-and those with certain symbolic address on the Sparc when compiling
+and those with certain symbolic address on the SPARC when compiling
PIC)@. In some cases, both an intermediate and a scratch register are
required.
@@ -2447,25 +2561,22 @@ should be the maximum value of @code{HARD_REGNO_NREGS (@var{regno},
This macro helps control the handling of multiple-word values
in the reload pass.
-@item CLASS_CANNOT_CHANGE_MODE
-If defined, a C expression for a class that contains registers for
-which the compiler may not change modes arbitrarily.
-
-@item CLASS_CANNOT_CHANGE_MODE_P(@var{from}, @var{to})
-A C expression that is true if, for a register in
-@code{CLASS_CANNOT_CHANGE_MODE}, the requested mode punning is invalid.
+@item CANNOT_CHANGE_MODE_CLASS(@var{from}, @var{to}, @var{class})
+If defined, a C expression that returns nonzero for a @var{class} for which
+a change from mode @var{from} to mode @var{to} is invalid.
For the example, loading 32-bit integer or floating-point objects into
floating-point registers on the Alpha extends them to 64 bits.
Therefore loading a 64-bit object and then storing it as a 32-bit object
does not store the low-order 32 bits, as would be the case for a normal
-register. Therefore, @file{alpha.h} defines @code{CLASS_CANNOT_CHANGE_MODE}
-as @code{FLOAT_REGS} and @code{CLASS_CANNOT_CHANGE_MODE_P} restricts
-mode changes to same-size modes.
+register. Therefore, @file{alpha.h} defines @code{CANNOT_CHANGE_MODE_CLASS}
+as below:
-Compare this to IA-64, which extends floating-point values to 82 bits,
-and stores 64-bit integers in a different format than 64-bit doubles.
-Therefore @code{CLASS_CANNOT_CHANGE_MODE_P} is always true.
+@example
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? reg_classes_intersect_p (FLOAT_REGS, (CLASS)) : 0)
+@end example
@end table
Three other special macros describe which operands fit which constraint
@@ -2518,6 +2629,44 @@ letter @samp{Q} is defined as representing a memory address that does
a @samp{Q} constraint on the input and @samp{r} on the output. The next
alternative specifies @samp{m} on the input and a register class that
does not include r0 on the output.
+
+@findex EXTRA_MEMORY_CONSTRAINT
+@item EXTRA_MEMORY_CONSTRAINT (@var{c})
+A C expression that defines the optional machine-dependent constraint
+letters, amongst those accepted by @code{EXTRA_CONSTRAINT}, that should
+be treated like memory constraints by the reload pass.
+
+It should return 1 if the operand type represented by the constraint
+letter @var{c} comprises a subset of all memory references including
+all those whose address is simply a base register. This allows the reload
+pass to reload an operand, if it does not directly correspond to the operand
+type of @var{c}, by copying its address into a base register.
+
+For example, on the S/390, some instructions do not accept arbitrary
+memory references, but only those that do not make use of an index
+register. The constraint letter @samp{Q} is defined via
+@code{EXTRA_CONSTRAINT} as representing a memory address of this type.
+If the letter @samp{Q} is marked as @code{EXTRA_MEMORY_CONSTRAINT},
+a @samp{Q} constraint can handle any memory operand, because the
+reload pass knows it can be reloaded by copying the memory address
+into a base register if required. This is analogous to the way
+a @samp{o} constraint can handle any memory operand.
+
+@findex EXTRA_ADDRESS_CONSTRAINT
+@item EXTRA_ADDRESS_CONSTRAINT (@var{c})
+A C expression that defines the optional machine-dependent constraint
+letters, amongst those accepted by @code{EXTRA_CONSTRAINT}, that should
+be treated like address constraints by the reload pass.
+
+It should return 1 if the operand type represented by the constraint
+letter @var{c} comprises a subset of all memory addresses including
+all those that consist of just a base register. This allows the reload
+pass to reload an operand, if it does not directly correspond to the operand
+type of @var{c}, by copying it into a base register.
+
+Any constraint marked as @code{EXTRA_ADDRESS_CONSTRAINT} can only
+be used with the @code{address_operand} predicate. It is treated
+analogously to the @samp{p} constraint.
@end table
@node Stack and Calling
@@ -2566,7 +2715,7 @@ definition used does not matter.
This macro defines the operation used when something is pushed
on the stack. In RTL, a push operation will be
-@code{(set (mem (STACK_PUSH_CODE (reg sp))) ...)}
+@code{(set (mem (STACK_PUSH_CODE (reg sp))) @dots{})}
The choices are @code{PRE_DEC}, @code{POST_DEC}, @code{PRE_INC},
and @code{POST_INC}. Which of these is correct depends on
@@ -2641,7 +2790,7 @@ address of the stack word that points to the previous frame.
@item SETUP_FRAME_ADDRESSES
If defined, a C expression that produces the machine-specific code to
setup the stack so that arbitrary frames can be accessed. For example,
-on the Sparc, we must flush all of the register windows to the stack
+on the SPARC, we must flush all of the register windows to the stack
before we can access arbitrary stack frames. You will seldom need to
define this macro.
@@ -2750,8 +2899,12 @@ It will be assigned zero on code paths that return normally.
Typically this is a call-clobbered hard register that is otherwise
untouched by the epilogue, but could also be a stack slot.
-You must define this macro if you want to support call frame exception
-handling like that provided by DWARF 2.
+Do not define this macro if the stack pointer is saved and restored
+by the regular prolog and epilog code in the call frame itself; in
+this case, the exception handling library routines will update the
+stack location to be restored in place. Otherwise, you must define
+this macro if you want to support call frame exception handling like
+that provided by DWARF 2.
@findex EH_RETURN_HANDLER_RTX
@item EH_RETURN_HANDLER_RTX
@@ -2763,8 +2916,9 @@ Typically this is the location in the call frame at which the normal
return address is stored. For targets that return by popping an
address off the stack, this might be a memory address just below
the @emph{target} call frame rather than inside the current call
-frame. @code{EH_RETURN_STACKADJ_RTX} will have already been assigned,
-so it may be used to calculate the location of the target call frame.
+frame. If defined, @code{EH_RETURN_STACKADJ_RTX} will have already
+been assigned, so it may be used to calculate the location of the
+target call frame.
Some targets have more complex requirements than storing to an
address calculable during initial code generation. In that case
@@ -3434,14 +3588,6 @@ nonzero, the caller does not make a copy. Instead, it passes a pointer to the
determined that the value won't be modified, it need not make a copy;
otherwise a copy must be made.
-@findex FUNCTION_ARG_REG_LITTLE_ENDIAN
-@item FUNCTION_ARG_REG_LITTLE_ENDIAN
-If defined TRUE on a big-endian system then structure arguments passed
-(and returned) in registers are passed in a little-endian manner instead of
-the big-endian manner. On the HP-UX IA64 and PA64 platforms structures are
-aligned differently then integral values and setting this value to true will
-allow for the special handling of structure arguments and return values.
-
@findex CUMULATIVE_ARGS
@item CUMULATIVE_ARGS
A C type for declaring a variable that is used as the first argument of
@@ -3567,11 +3713,6 @@ This section discusses the macros that control returning scalars as
values---values that can fit in registers.
@table @code
-@findex TRADITIONAL_RETURN_FLOAT
-@item TRADITIONAL_RETURN_FLOAT
-Define this macro if @option{-traditional} should not cause functions
-declared to return @code{float} to convert the value to @code{double}.
-
@findex FUNCTION_VALUE
@item FUNCTION_VALUE (@var{valtype}, @var{func})
A C expression to create an RTX representing the place where a
@@ -3916,7 +4057,7 @@ arguments. But usually, on such machines, nothing else has been pushed
yet, because the function prologue itself does all the pushing.) This
region is used on machines where an argument may be passed partly in
registers and partly in memory, and, in some cases to support the
-features in @code{<varargs.h>} and @code{<stdarg.h>}.
+features in @code{<stdarg.h>}.
@item
An area of memory used to save certain registers used by the function.
@@ -4003,9 +4144,11 @@ outputting the insns in this list, usually by calling
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
+@end table
+
+@findex TARGET_ASM_OUTPUT_MI_THUNK
+@deftypefn {Target Hook} void TARGET_ASM_OUTPUT_MI_THUNK (FILE *@var{file}, tree @var{thunk_fndecl}, HOST_WIDE_INT @var{delta}, tree @var{function})
+A function 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
@@ -4036,7 +4179,24 @@ If you do not define this macro, the target-independent code in the C++
front end 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
+@end deftypefn
+
+@findex TARGET_ASM_OUTPUT_MI_VCALL_THUNK
+@deftypefn {Target Hook} void TARGET_ASM_OUTPUT_MI_VCALL_THUNK (FILE *@var{file}, tree @var{thunk_fndecl}, HOST_WIDE_INT @var{delta}, int @var{vcall_offset}, tree @var{function})
+A function like @code{TARGET_ASM_OUTPUT_MI_THUNK}, except that if
+@var{vcall_offset} is nonzero, an additional adjustment should be made
+after adding @code{delta}. In particular, if @var{p} is the
+adjusted pointer, the following adjustment should be made:
+
+@example
+p += (*((ptrdiff_t **)p))[vcall_offset/sizeof(ptrdiff_t)]
+@end example
+
+@noindent
+If this function is defined, it will always be used in place of
+@code{TARGET_ASM_OUTPUT_MI_THUNK}.
+
+@end deftypefn
@node Profiling
@subsection Generating Code for Profiling
@@ -4078,22 +4238,6 @@ must not use the @var{labelno} argument to @code{FUNCTION_PROFILER}.
@item PROFILE_BEFORE_PROLOGUE
Define this macro if the code for function profiling should come before
the function prologue. Normally, the profiling code comes after.
-
-
-@findex TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
-@item TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
-On some targets, it is impossible to use profiling when the frame
-pointer has been omitted. For example, on x86 GNU/Linux systems,
-the @code{mcount} routine provided by the GNU C Library finds the
-address of the routine that called the routine that called @code{mcount}
-by looking in the immediate caller's stack frame. If the immediate
-caller has no frame pointer, this lookup will fail.
-
-By default, GCC assumes that the target does allow profiling when the
-frame pointer is omitted. This macro should be defined to a C
-expression that evaluates to @code{false} if the target does not allow
-profiling when the frame pointer is omitted.
-
@end table
@node Tail Calls
@@ -4524,6 +4668,13 @@ remainder in division of one unsigned full-word by another. If you do
not define this macro, the default name is used, which is
@code{__umoddi3}, a function defined in @file{libgcc.a}.
+@findex DECLARE_LIBRARY_RENAMES
+@item DECLARE_LIBRARY_RENAMES
+This macro, if defined, should expand to a piece of C code that will get
+expanded when compiling functions for libgcc.a. It can be used to
+provide alternate names for gcc's internal library functions if there
+are ABI-mandated names that the compiler should provide.
+
@findex INIT_TARGET_OPTABS
@item INIT_TARGET_OPTABS
Define this macro as a C statement that declares additional library
@@ -4692,11 +4843,11 @@ sums that are not marked with @code{const}. It assumes that a naked
naked constant sums as illegitimate addresses, so that none of them will
be given to @code{PRINT_OPERAND_ADDRESS}.
-@cindex @code{ENCODE_SECTION_INFO} and address validation
+@cindex @code{TARGET_ENCODE_SECTION_INFO} and address validation
On some machines, whether a symbolic address is legitimate depends on
the section that the address refers to. On these machines, define the
-macro @code{ENCODE_SECTION_INFO} to store the information into the
-@code{symbol_ref}, and then check for it here. When you see a
+target hook @code{TARGET_ENCODE_SECTION_INFO} to store the information
+into the @code{symbol_ref}, and then check for it here. When you see a
@code{const}, you will have to look inside it to find the
@code{symbol_ref} in order to determine the section. @xref{Assembler
Format}.
@@ -4706,8 +4857,8 @@ The best way to modify the name string is by adding text to the
beginning, with suitable punctuation to prevent any ambiguity. Allocate
the new name in @code{saveable_obstack}. You will have to modify
@code{ASM_OUTPUT_LABELREF} to remove and decode the added text and
-output the name accordingly, and define @code{STRIP_NAME_ENCODING} to
-access the original name string.
+output the name accordingly, and define @code{TARGET_STRIP_NAME_ENCODING}
+to access the original name string.
You can check the information stored here into the @code{symbol_ref} in
the definitions of the macros @code{GO_IF_LEGITIMATE_ADDRESS} and
@@ -4931,29 +5082,34 @@ two places, the @file{md} file and in @code{NOTICE_UPDATE_CC}.
@findex EXTRA_CC_MODES
@item EXTRA_CC_MODES
-A list of additional modes for condition code values in registers
-(@pxref{Jump Patterns}). This macro should expand to a sequence of
-calls of the macro @code{CC} separated by white space. @code{CC} takes
-two arguments. The first is the enumeration name of the mode, which
-should begin with @samp{CC} and end with @samp{mode}. The second is a C
-string giving the printable name of the mode; it should be the same as
-the first argument, but with the trailing @samp{mode} removed.
+Condition codes are represented in registers by machine modes of class
+@code{MODE_CC}. By default, there is just one mode, @code{CCmode}, with
+this class. If you need more such modes, create a file named
+@file{@var{machine}-modes.def} in your @file{config/@var{machine}}
+directory (@pxref{Back End, , Anatomy of a Target Back End}), containing
+a list of these modes. Each entry in the list should be a call to the
+macro @code{CC}. This macro takes one argument, which is the name of
+the mode: it should begin with @samp{CC}. Do not put quotation marks
+around the name, or include the trailing @samp{mode}; these are
+automatically added. There should not be anything else in the file
+except comments.
+
+A sample @file{@var{machine}-modes.def} file might look like this:
-You should only define this macro if additional modes are required.
-
-A sample definition of @code{EXTRA_CC_MODES} is:
@smallexample
-#define EXTRA_CC_MODES \
- CC(CC_NOOVmode, "CC_NOOV") \
- CC(CCFPmode, "CCFP") \
- CC(CCFPEmode, "CCFPE")
+CC (CC_NOOV) /* @r{Comparison only valid if there was no overflow.} */
+CC (CCFP) /* @r{Floating point comparison that cannot trap.} */
+CC (CCFPE) /* @r{Floating point comparison that may trap.} */
@end smallexample
+When you create this file, the macro @code{EXTRA_CC_MODES} is
+automatically defined by @command{configure}, with value @samp{1}.
+
@findex SELECT_CC_MODE
@item SELECT_CC_MODE (@var{op}, @var{x}, @var{y})
Returns a mode from class @code{MODE_CC} to be used when comparison
operation code @var{op} is applied to rtx @var{x} and @var{y}. For
-example, on the Sparc, @code{SELECT_CC_MODE} is defined as (see
+example, on the SPARC, @code{SELECT_CC_MODE} is defined as (see
@pxref{Jump Patterns} for a description of the reason for this
definition)
@@ -4997,7 +5153,7 @@ then @code{REVERSIBLE_CC_MODE (@var{mode})} must be zero.
You need not define this macro if it would always returns zero or if the
floating-point format is anything other than @code{IEEE_FLOAT_FORMAT}.
-For example, here is the definition used on the Sparc, where floating-point
+For example, here is the definition used on the SPARC, where floating-point
inequality comparisons are always given @code{CCFPEmode}:
@smallexample
@@ -5246,6 +5402,22 @@ than @code{MOVE_RATIO}.
A C expression used by @code{move_by_pieces} to determine the largest unit
a load or store used to copy memory is. Defaults to @code{MOVE_MAX}.
+@findex CLEAR_RATIO
+@item CLEAR_RATIO
+The threshold of number of scalar move insns, @emph{below} which a sequence
+of insns should be generated to clear memory instead of a string clear insn
+or a library call. Increasing the value will always make code faster, but
+eventually incurs high cost in increased code size.
+
+If you don't define this, a reasonable default is used.
+
+@findex CLEAR_BY_PIECES_P
+@item CLEAR_BY_PIECES_P (@var{size}, @var{alignment})
+A C expression used to determine whether @code{clear_by_pieces} will be used
+to clear a chunk of memory, or whether some other block clear mechanism
+will be used. Defaults to 1 if @code{move_by_pieces_ninsns} returns less
+than @code{CLEAR_RATIO}.
+
@findex USE_LOAD_POST_INCREMENT
@item USE_LOAD_POST_INCREMENT (@var{mode})
A C expression used to determine whether a load postincrement is a good
@@ -5315,11 +5487,18 @@ hooks for this purpose. It is usually enough to define just a few of
them: try the first ones in this list first.
@deftypefn {Target Hook} int TARGET_SCHED_ISSUE_RATE (void)
-This hook returns the maximum number of instructions that can ever issue
-at the same time on the target machine. The default is one. This value
-must be constant over the entire compilation. If you need it to vary
-depending on what the instructions are, you must use
+This hook returns the maximum number of instructions that can ever
+issue at the same time on the target machine. The default is one.
+Although the insn scheduler can define itself the possibility of issue
+an insn on the same cycle, the value can serve as an additional
+constraint to issue insns on the same simulated processor cycle (see
+hooks @samp{TARGET_SCHED_REORDER} and @samp{TARGET_SCHED_REORDER2}).
+This value must be constant over the entire compilation. If you need
+it to vary depending on what the instructions are, you must use
@samp{TARGET_SCHED_VARIABLE_ISSUE}.
+
+For the automaton based pipeline interface, you could define this hook
+to return the value of the macro @code{MAX_DFA_ISSUE_RATE}.
@end deftypefn
@deftypefn {Target Hook} int TARGET_SCHED_VARIABLE_ISSUE (FILE *@var{file}, int @var{verbose}, rtx @var{insn}, int @var{more})
@@ -5335,12 +5514,18 @@ instruction that was scheduled.
@end deftypefn
@deftypefn {Target Hook} int TARGET_SCHED_ADJUST_COST (rtx @var{insn}, rtx @var{link}, rtx @var{dep_insn}, int @var{cost})
-This function corrects the value of @var{cost} based on the relationship
-between @var{insn} and @var{dep_insn} through the dependence @var{link}.
-It should return the new value. The default is to make no adjustment to
-@var{cost}. This can be used for example to specify to the scheduler
+This function corrects the value of @var{cost} based on the
+relationship between @var{insn} and @var{dep_insn} through the
+dependence @var{link}. It should return the new value. The default
+is to make no adjustment to @var{cost}. This can be used for example
+to specify to the scheduler using the traditional pipeline description
that an output- or anti-dependence does not incur the same cost as a
-data-dependence.
+data-dependence. If the scheduler using the automaton based pipeline
+description, the cost of anti-dependence is zero and the cost of
+output-dependence is maximum of one and the difference of latency
+times of the first and the second insns. If these values are not
+acceptable, you could use the hook to modify them too. See also
+@pxref{Automaton pipeline description}.
@end deftypefn
@deftypefn {Target Hook} int TARGET_SCHED_ADJUST_PRIORITY (rtx @var{insn}, int @var{priority})
@@ -5398,14 +5583,140 @@ to. @var{verbose} is the verbose level provided by
@option{-fsched-verbose-@var{n}}.
@end deftypefn
-@deftypefn {Target Hook} rtx TARGET_SCHED_CYCLE_DISPLAY (int @var{clock}, rtx @var{last})
-This hook is called in verbose mode only, at the beginning of each pass
-over a basic block. It should insert an insn into the chain after
-@var{last}, which has no effect, but records the value @var{clock} in
-RTL dumps and assembly output. Define this hook only if you need this
-level of detail about what the scheduler is doing.
+@deftypefn {Target Hook} int TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE (void)
+This hook is called many times during insn scheduling. If the hook
+returns nonzero, the automaton based pipeline description is used for
+insn scheduling. Otherwise the traditional pipeline description is
+used. The default is usage of the traditional pipeline description.
+
+You should also remember that to simplify the insn scheduler sources
+an empty traditional pipeline description interface is generated even
+if there is no a traditional pipeline description in the @file{.md}
+file. The same is true for the automaton based pipeline description.
+That means that you should be accurate in defining the hook.
+@end deftypefn
+
+@deftypefn {Target Hook} int TARGET_SCHED_DFA_PRE_CYCLE_INSN (void)
+The hook returns an RTL insn. The automaton state used in the
+pipeline hazard recognizer is changed as if the insn were scheduled
+when the new simulated processor cycle starts. Usage of the hook may
+simplify the automaton pipeline description for some @acronym{VLIW}
+processors. If the hook is defined, it is used only for the automaton
+based pipeline description. The default is not to change the state
+when the new simulated processor cycle starts.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN (void)
+The hook can be used to initialize data used by the previous hook.
+@end deftypefn
+
+@deftypefn {Target Hook} int TARGET_SCHED_DFA_POST_CYCLE_INSN (void)
+The hook is analogous to @samp{TARGET_SCHED_DFA_PRE_CYCLE_INSN} but used
+to changed the state as if the insn were scheduled when the new
+simulated processor cycle finishes.
@end deftypefn
+@deftypefn {Target Hook} void TARGET_SCHED_INIT_DFA_POST_CYCLE_INSN (void)
+The hook is analogous to @samp{TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN} but
+used to initialize data used by the previous hook.
+@end deftypefn
+
+@deftypefn {Target Hook} int TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD (void)
+This hook controls better choosing an insn from the ready insn queue
+for the @acronym{DFA}-based insn scheduler. Usually the scheduler
+chooses the first insn from the queue. If the hook returns a positive
+value, an additional scheduler code tries all permutations of
+@samp{TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD ()}
+subsequent ready insns to choose an insn whose issue will result in
+maximal number of issued insns on the same cycle. For the
+@acronym{VLIW} processor, the code could actually solve the problem of
+packing simple insns into the @acronym{VLIW} insn. Of course, if the
+rules of @acronym{VLIW} packing are described in the automaton.
+
+This code also could be used for superscalar @acronym{RISC}
+processors. Let us consider a superscalar @acronym{RISC} processor
+with 3 pipelines. Some insns can be executed in pipelines @var{A} or
+@var{B}, some insns can be executed only in pipelines @var{B} or
+@var{C}, and one insn can be executed in pipeline @var{B}. The
+processor may issue the 1st insn into @var{A} and the 2nd one into
+@var{B}. In this case, the 3rd insn will wait for freeing @var{B}
+until the next cycle. If the scheduler issues the 3rd insn the first,
+the processor could issue all 3 insns per cycle.
+
+Actually this code demonstrates advantages of the automaton based
+pipeline hazard recognizer. We try quickly and easy many insn
+schedules to choose the best one.
+
+The default is no multipass scheduling.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_SCHED_INIT_DFA_BUBBLES (void)
+The @acronym{DFA}-based scheduler could take the insertion of nop
+operations for better insn scheduling into account. It can be done
+only if the multi-pass insn scheduling works (see hook
+@samp{TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD}).
+
+Let us consider a @acronym{VLIW} processor insn with 3 slots. Each
+insn can be placed only in one of the three slots. We have 3 ready
+insns @var{A}, @var{B}, and @var{C}. @var{A} and @var{C} can be
+placed only in the 1st slot, @var{B} can be placed only in the 3rd
+slot. We described the automaton which does not permit empty slot
+gaps between insns (usually such description is simpler). Without
+this code the scheduler would place each insn in 3 separate
+@acronym{VLIW} insns. If the scheduler places a nop insn into the 2nd
+slot, it could place the 3 insns into 2 @acronym{VLIW} insns. What is
+the nop insn is returned by hook @samp{TARGET_SCHED_DFA_BUBBLE}. Hook
+@samp{TARGET_SCHED_INIT_DFA_BUBBLES} can be used to initialize or
+create the nop insns.
+
+You should remember that the scheduler does not insert the nop insns.
+It is not wise because of the following optimizations. The scheduler
+only considers such possibility to improve the result schedule. The
+nop insns should be inserted lately, e.g. on the final phase.
+@end deftypefn
+
+@deftypefn {Target Hook} rtx TARGET_SCHED_DFA_BUBBLE (int @var{index})
+This hook @samp{FIRST_CYCLE_MULTIPASS_SCHEDULING} is used to insert
+nop operations for better insn scheduling when @acronym{DFA}-based
+scheduler makes multipass insn scheduling (see also description of
+hook @samp{TARGET_SCHED_INIT_DFA_BUBBLES}). This hook
+returns a nop insn with given @var{index}. The indexes start with
+zero. The hook should return @code{NULL} if there are no more nop
+insns with indexes greater than given index.
+@end deftypefn
+
+Macros in the following table are generated by the program
+@file{genattr} and can be useful for writing the hooks.
+
+@table @code
+@findex TRADITIONAL_PIPELINE_INTERFACE
+@item TRADITIONAL_PIPELINE_INTERFACE
+The macro definition is generated if there is a traditional pipeline
+description in @file{.md} file. You should also remember that to
+simplify the insn scheduler sources an empty traditional pipeline
+description interface is generated even if there is no a traditional
+pipeline description in the @file{.md} file. The macro can be used to
+distinguish the two types of the traditional interface.
+
+@findex DFA_PIPELINE_INTERFACE
+@item DFA_PIPELINE_INTERFACE
+The macro definition is generated if there is an automaton pipeline
+description in @file{.md} file. You should also remember that to
+simplify the insn scheduler sources an empty automaton pipeline
+description interface is generated even if there is no an automaton
+pipeline description in the @file{.md} file. The macro can be used to
+distinguish the two types of the automaton interface.
+
+@findex MAX_DFA_ISSUE_RATE
+@item MAX_DFA_ISSUE_RATE
+The macro definition is generated in the automaton based pipeline
+description interface. Its value is calculated from the automaton
+based pipeline description and is equal to maximal number of all insns
+described in constructions @samp{define_insn_reservation} which can be
+issued on the same processor cycle.
+
+@end table
+
@node Sections
@section Dividing the Output into Sections (Texts, Data, @dots{})
@c the above section title is WAY too long. maybe cut the part between
@@ -5436,12 +5747,39 @@ Normally this is not needed, as simply defining @code{TEXT_SECTION_ASM_OP}
is enough. The MIPS port uses this to sort all functions after all data
declarations.
+@findex HOT_TEXT_SECTION_NAME
+@item HOT_TEXT_SECTION_NAME
+If defined, a C string constant for the name of the section containing most
+frequently executed functions of the program. If not defined, GCC will provide
+a default definition if the target supports named sections.
+
+@findex UNLIKELY_EXECUTED_TEXT_SECTION_NAME
+@item UNLIKELY_EXECUTED_TEXT_SECTION_NAME
+If defined, a C string constant for the name of the section containing unlikely
+executed functions in the program.
+
@findex DATA_SECTION_ASM_OP
@item DATA_SECTION_ASM_OP
A C expression whose value is a string, including spacing, containing the
assembler operation to identify the following data as writable initialized
data. Normally @code{"\t.data"} is right.
+@findex READONLY_DATA_SECTION_ASM_OP
+@item READONLY_DATA_SECTION_ASM_OP
+A C expression whose value is a string, including spacing, containing the
+assembler operation to identify the following data as read-only initialized
+data.
+
+@findex READONLY_DATA_SECTION
+@item READONLY_DATA_SECTION
+A macro naming a function to call to switch to the proper section for
+read-only data. The default is to use @code{READONLY_DATA_SECTION_ASM_OP}
+if defined, else fall back to @code{text_section}.
+
+The most common definition will be @code{data_section}, if the target
+does not have a special read-only data section, and does not put data
+in the text section.
+
@findex SHARED_SECTION_ASM_OP
@item SHARED_SECTION_ASM_OP
If defined, a C expression whose value is a string, including spacing,
@@ -5515,44 +5853,6 @@ functions should do jobs analogous to those of @code{text_section} and
@code{data_section}, for your additional sections. Do not define this
macro if you do not define @code{EXTRA_SECTIONS}.
-@findex READONLY_DATA_SECTION
-@item READONLY_DATA_SECTION
-On most machines, read-only variables, constants, and jump tables are
-placed in the text section. If this is not the case on your machine,
-this macro should be defined to be the name of a function (either
-@code{data_section} or a function defined in @code{EXTRA_SECTIONS}) that
-switches to the section to be used for read-only items.
-
-If these items should be placed in the text section, this macro should
-not be defined.
-
-@findex SELECT_SECTION
-@item SELECT_SECTION (@var{exp}, @var{reloc}, @var{align})
-A C statement or statements to switch to the appropriate section for
-output of @var{exp}. You can assume that @var{exp} is either a
-@code{VAR_DECL} node or a constant of some sort. @var{reloc}
-indicates whether the initial value of @var{exp} requires link-time
-relocations. Bit 1 is set when variable contains local relocations
-only, while bit 2 is set for global relocations.
-Select the section by calling @code{text_section} or one
-of the alternatives for other sections. @var{align} is the constant
-alignment in bits.
-
-Do not define this macro if you put all read-only variables and
-constants in the read-only data section (usually the text section).
-
-@findex SELECT_RTX_SECTION
-@item SELECT_RTX_SECTION (@var{mode}, @var{rtx}, @var{align})
-A C statement or statements to switch to the appropriate section for
-output of @var{rtx} in mode @var{mode}. You can assume that @var{rtx}
-is some kind of constant in RTL@. The argument @var{mode} is redundant
-except in the case of a @code{const_int} rtx. Select the section by
-calling @code{text_section} or one of the alternatives for other
-sections. @var{align} is the constant alignment in bits.
-
-Do not define this macro if you put all constants in the read-only
-data section.
-
@findex JUMP_TABLES_IN_TEXT_SECTION
@item JUMP_TABLES_IN_TEXT_SECTION
Define this macro to be an expression with a nonzero value if jump
@@ -5561,44 +5861,104 @@ section, along with the assembler instructions. Otherwise, the
readonly data section is used.
This macro is irrelevant if there is no separate readonly data section.
+@end table
+
+@deftypefn {Target Hook} void TARGET_ASM_SELECT_SECTION (tree @var{exp}, int @var{reloc}, unsigned HOST_WIDE_INT @var{align})
+Switches to the appropriate section for output of @var{exp}. You can
+assume that @var{exp} is either a @code{VAR_DECL} node or a constant of
+some sort. @var{reloc} indicates whether the initial value of @var{exp}
+requires link-time relocations. Bit 0 is set when variable contains
+local relocations only, while bit 1 is set for global relocations.
+Select the section by calling @code{data_section} or one of the
+alternatives for other sections. @var{align} is the constant alignment
+in bits.
+
+The default version of this function takes care of putting read-only
+variables in @code{readonly_data_section}.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_ASM_UNIQUE_SECTION (tree @var{decl}, int @var{reloc})
+Build up a unique section name, expressed as a @code{STRING_CST} node,
+and assign it to @samp{DECL_SECTION_NAME (@var{decl})}.
+As with @code{TARGET_ASM_SELECT_SECTION}, @var{reloc} indicates whether
+the initial value of @var{exp} requires link-time relocations.
+
+The default version of this function appends the symbol name to the
+ELF section name that would normally be used for the symbol. For
+example, the function @code{foo} would be placed in @code{.text.foo}.
+Whatever the actual target object format, this is often good enough.
+@end deftypefn
-@findex ENCODE_SECTION_INFO
-@item ENCODE_SECTION_INFO (@var{decl})
-Define this macro if references to a symbol or a constant must be
+@deftypefn {Target Hook} void TARGET_ASM_SELECT_RTX_SECTION (enum machine_mode @var{mode}, rtx @var{x}, unsigned HOST_WIDE_INT @var{align})
+Switches to the appropriate section for output of constant pool entry
+@var{x} in @var{mode}. You can assume that @var{x} is some kind of
+constant in RTL@. The argument @var{mode} is redundant except in the
+case of a @code{const_int} rtx. Select the section by calling
+@code{readonly_data_section} or one of the alternatives for other
+sections. @var{align} is the constant alignment in bits.
+
+The default version of this function takes care of putting symbolic
+constants in @code{flag_pic} mode in @code{data_section} and everything
+else in @code{readonly_data_section}.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_ENCODE_SECTION_INFO (tree @var{decl}, int @var{new_decl_p})
+Define this hook if references to a symbol or a constant must be
treated differently depending on something about the variable or
function named by the symbol (such as what section it is in).
-The macro definition, if any, is executed under two circumstances. One
-is immediately after the rtl for @var{decl} that represents a variable
-or a function has been created and stored in @code{DECL_RTL
-(@var{decl})}. The value of the rtl will be a @code{mem} whose address
-is a @code{symbol_ref}. The other is immediately after the rtl for
-@var{decl} that represents a constant has been created and stored in
-@code{TREE_CST_RTL (@var{decl})}. The macro is called once for each
-distinct constant in a source file.
-
-@cindex @code{SYMBOL_REF_FLAG}, in @code{ENCODE_SECTION_INFO}
-The usual thing for this macro to do is to record a flag in the
+The hook is executed under two circumstances. One is immediately after
+the rtl for @var{decl} that represents a variable or a function has been
+created and stored in @code{DECL_RTL(@var{decl})}. The value of the rtl
+will be a @code{mem} whose address is a @code{symbol_ref}. The other is
+immediately after the rtl for @var{decl} that represents a constant has
+been created and stored in @code{TREE_CST_RTL (@var{decl})}. The macro
+is called once for each distinct constant in a source file.
+
+The @var{new_decl_p} argument will be true if this is the first time
+that @code{ENCODE_SECTION_INFO} has been invoked on this decl. It will
+be false for subsequent invocations, which will happen for duplicate
+declarations. Whether or not anything must be done for the duplicate
+declaration depends on whether the hook examines @code{DECL_ATTRIBUTES}.
+
+@cindex @code{SYMBOL_REF_FLAG}, in @code{TARGET_ENCODE_SECTION_INFO}
+The usual thing for this hook to do is to record a flag in the
@code{symbol_ref} (such as @code{SYMBOL_REF_FLAG}) or to store a
-modified name string in the @code{symbol_ref} (if one bit is not enough
-information).
-
-@findex STRIP_NAME_ENCODING
-@item STRIP_NAME_ENCODING (@var{var}, @var{sym_name})
-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
-@item UNIQUE_SECTION (@var{decl}, @var{reloc})
-A C statement to build up a unique section name, expressed as a
-@code{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, GCC will use
-the symbol name prefixed by @samp{.} as the section name. Note - this
-macro can now be called for uninitialized data items as well as
-initialized data and functions.
-@end table
+modified name string in the @code{symbol_ref} (if one bit is not
+enough information).
+@end deftypefn
+
+@deftypefn {Target Hook} const char *TARGET_STRIP_NAME_ENCODING (const char *name)
+Decode @var{name} and return the real name part, sans
+the characters that @code{TARGET_ENCODE_SECTION_INFO}
+may have added.
+@end deftypefn
+
+@deftypefn {Target Hook} bool TARGET_IN_SMALL_DATA_P (tree @var{exp})
+Returns true if @var{exp} should be placed into a ``small data'' section.
+The default version of this hook always returns false.
+@end deftypefn
+
+@deftypevar {Target Hook} bool TARGET_HAVE_SRODATA_SECTION
+Contains the value true if the target places read-only
+``small data'' into a separate section. The default value is false.
+@end deftypevar
+
+@deftypefn {Target Hook} bool TARGET_BINDS_LOCAL_P (tree @var{exp})
+Returns true if @var{exp} names an object for which name resolution
+rules must resolve to the current ``module'' (dynamic shared library
+or executable image).
+
+The default version of this hook implements the name resolution rules
+for ELF, which has a looser model of global name binding than other
+currently supported object file formats.
+@end deftypefn
+
+@deftypevar {Target Hook} bool TARGET_HAVE_TLS
+Contains the value true if the target supports thread-local storage.
+The default value is false.
+@end deftypevar
+
@node PIC
@section Position Independent Code
@@ -5966,26 +6326,18 @@ of @code{ASM_OUTPUT_DOUBLE} and the like:
@findex REAL_VALUE_TO_TARGET_DOUBLE
@findex REAL_VALUE_TO_TARGET_LONG_DOUBLE
These translate @var{x}, of type @code{REAL_VALUE_TYPE}, to the target's
-floating point representation, and store its bit pattern in the array of
-@code{long int} whose address is @var{l}. The number of elements in the
-output array is determined by the size of the desired target floating
-point data type: 32 bits of it go in each @code{long int} array
-element. Each array element holds 32 bits of the result, even if
-@code{long int} is wider than 32 bits on the host machine.
+floating point representation, and store its bit pattern in the variable
+@var{l}. For @code{REAL_VALUE_TO_TARGET_SINGLE}, this variable should
+be a simple @code{long int}. For the others, it should be an array of
+@code{long int}. The number of elements in this array is determined by
+the size of the desired target floating point data type: 32 bits of it
+go in each @code{long int} array element. Each array element holds 32
+bits of the result, even if @code{long int} is wider than 32 bits on the
+host machine.
The array element values are designed so that you can print them out
using @code{fprintf} in the order they should appear in the target
machine's memory.
-
-@item REAL_VALUE_TO_DECIMAL (@var{x}, @var{format}, @var{string})
-@findex REAL_VALUE_TO_DECIMAL
-This macro converts @var{x}, of type @code{REAL_VALUE_TYPE}, to a
-decimal number and stores it as a string into @var{string}.
-You must pass, as @var{string}, the address of a long enough block
-of space to hold the result.
-
-The argument @var{format} is a @code{printf}-specification that serves
-as a suggestion for how to format the output string.
@end table
@node Uninitialized Data
@@ -6122,7 +6474,78 @@ A C statement (sans semicolon) to output to the stdio stream
@var{stream} the assembler definition of a label named @var{name}.
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.
+assembler syntax for defining the name, and a newline. A default
+definition of this macro is provided which is correct for most systems.
+
+@findex SIZE_ASM_OP
+@item SIZE_ASM_OP
+A C string containing the appropriate assembler directive to specify the
+size of a symbol, without any arguments. On systems that use ELF, the
+default (in @file{config/elfos.h}) is @samp{"\t.size\t"}; on other
+systems, the default is not to define this macro.
+
+Define this macro only if it is correct to use the default definitions
+of @code{ASM_OUTPUT_SIZE_DIRECTIVE} and @code{ASM_OUTPUT_MEASURED_SIZE}
+for your system. If you need your own custom definitions of those
+macros, or if you do not need explicit symbol sizes at all, do not
+define this macro.
+
+@findex ASM_OUTPUT_SIZE_DIRECTIVE
+@item ASM_OUTPUT_SIZE_DIRECTIVE (@var{stream}, @var{name}, @var{size})
+A C statement (sans semicolon) to output to the stdio stream
+@var{stream} a directive telling the assembler that the size of the
+symbol @var{name} is @var{size}. @var{size} is a @code{HOST_WIDE_INT}.
+If you define @code{SIZE_ASM_OP}, a default definition of this macro is
+provided.
+
+@findex ASM_OUTPUT_MEASURED_SIZE
+@item ASM_OUTPUT_MEASURED_SIZE (@var{stream}, @var{name})
+A C statement (sans semicolon) to output to the stdio stream
+@var{stream} a directive telling the assembler to calculate the size of
+the symbol @var{name} by subtracting its address from the current
+address.
+
+If you define @code{SIZE_ASM_OP}, a default definition of this macro is
+provided. The default assumes that the assembler recognizes a special
+@samp{.} symbol as referring to the current address, and can calculate
+the difference between this and another symbol. If your assembler does
+not recognize @samp{.} or cannot do calculations with it, you will need
+to redefine @code{ASM_OUTPUT_MEASURED_SIZE} to use some other technique.
+
+@findex TYPE_ASM_OP
+@item TYPE_ASM_OP
+A C string containing the appropriate assembler directive to specify the
+type of a symbol, without any arguments. On systems that use ELF, the
+default (in @file{config/elfos.h}) is @samp{"\t.type\t"}; on other
+systems, the default is not to define this macro.
+
+Define this macro only if it is correct to use the default definition of
+@code{ASM_OUTPUT_TYPE_DIRECTIVE} for your system. If you need your own
+custom definition of this macro, or if you do not need explicit symbol
+types at all, do not define this macro.
+
+@findex TYPE_OPERAND_FMT
+@item TYPE_OPERAND_FMT
+A C string which specifies (using @code{printf} syntax) the format of
+the second operand to @code{TYPE_ASM_OP}. On systems that use ELF, the
+default (in @file{config/elfos.h}) is @samp{"@@%s"}; on other systems,
+the default is not to define this macro.
+
+Define this macro only if it is correct to use the default definition of
+@code{ASM_OUTPUT_TYPE_DIRECTIVE} for your system. If you need your own
+custom definition of this macro, or if you do not need explicit symbol
+types at all, do not define this macro.
+
+@findex ASM_OUTPUT_TYPE_DIRECTIVE
+@item ASM_OUTPUT_TYPE_DIRECTIVE (@var{stream}, @var{type})
+A C statement (sans semicolon) to output to the stdio stream
+@var{stream} a directive telling the assembler that the type of the
+symbol @var{name} is @var{type}. @var{type} is a C string; currently,
+that string is always either @samp{"function"} or @samp{"object"}, but
+you should not count on this.
+
+If you define @code{TYPE_ASM_OP} and @code{TYPE_OPERAND_FMT}, a default
+definition of this macro is provided.
@findex ASM_DECLARE_FUNCTION_NAME
@item ASM_DECLARE_FUNCTION_NAME (@var{stream}, @var{name}, @var{decl})
@@ -6136,6 +6559,9 @@ outputting the label definition (perhaps using
If this macro is not defined, then the function name is defined in the
usual manner as a label (by means of @code{ASM_OUTPUT_LABEL}).
+You may wish to use @code{ASM_OUTPUT_TYPE_DIRECTIVE} in the definition
+of this macro.
+
@findex ASM_DECLARE_FUNCTION_SIZE
@item ASM_DECLARE_FUNCTION_SIZE (@var{stream}, @var{name}, @var{decl})
A C statement (sans semicolon) to output to the stdio stream
@@ -6146,6 +6572,9 @@ representing the function.
If this macro is not defined, then the function size is not defined.
+You may wish to use @code{ASM_OUTPUT_MEASURED_SIZE} in the definition
+of this macro.
+
@findex ASM_DECLARE_OBJECT_NAME
@item ASM_DECLARE_OBJECT_NAME (@var{stream}, @var{name}, @var{decl})
A C statement (sans semicolon) to output to the stdio stream
@@ -6157,6 +6586,9 @@ label definition (perhaps using @code{ASM_OUTPUT_LABEL}). The argument
If this macro is not defined, then the variable name is defined in the
usual manner as a label (by means of @code{ASM_OUTPUT_LABEL}).
+You may wish to use @code{ASM_OUTPUT_TYPE_DIRECTIVE} and/or
+@code{ASM_OUTPUT_SIZE_DIRECTIVE} in the definition of this macro.
+
@findex ASM_DECLARE_REGISTER_GLOBAL
@item ASM_DECLARE_REGISTER_GLOBAL (@var{stream}, @var{decl}, @var{regno}, @var{name})
A C statement (sans semicolon) to output to the stdio stream
@@ -6177,15 +6609,20 @@ something about the size of the object.
If you don't define this macro, that is equivalent to defining it to do
nothing.
-@findex ASM_GLOBALIZE_LABEL
-@item ASM_GLOBALIZE_LABEL (@var{stream}, @var{name})
-A C statement (sans semicolon) to output to the stdio stream
+You may wish to use @code{ASM_OUTPUT_SIZE_DIRECTIVE} and/or
+@code{ASM_OUTPUT_MEASURED_SIZE} in the definition of this macro.
+@end table
+
+@deftypefn {Target Hook} void TARGET_ASM_GLOBALIZE_LABEL (FILE *@var{stream}, const char *@var{name})
+This target hook is a function to output to the stdio stream
@var{stream} some commands that will make the label @var{name} global;
-that is, available for reference from other files. 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 making that name global, and a newline.
+that is, available for reference from other files.
+
+The default implementation relies on a proper definition of
+@code{GLOBAL_ASM_OP}.
+@end deftypefn
+@table @code
@findex ASM_WEAKEN_LABEL
@item ASM_WEAKEN_LABEL (@var{stream}, @var{name})
A C statement (sans semicolon) to output to the stdio stream
@@ -6241,6 +6678,12 @@ 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.
+@deftypefn {Target Hook} void TARGET_ASM_ASSEMBLE_VISIBILITY (tree @var{decl}, const char *@var{visibility})
+This target hook is a function to output to @var{asm_out_file} some
+commands that will make the symbol(s) associated with @var{decl} have
+hidden, protected or internal visibility as specified by @var{visibility}.
+@end deftypefn
+
@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
@@ -6276,17 +6719,17 @@ A C statement (sans semicolon) to output a reference to
@code{SYMBOL_REF} @var{sym}. If not defined, @code{assemble_name}
will be used to output the name of the symbol. This macro may be used
to modify the way a symbol is referenced depending on information
-encoded by @code{ENCODE_SECTION_INFO}.
+encoded by @code{TARGET_ENCODE_SECTION_INFO}.
@findex ASM_OUTPUT_LABEL_REF
@item ASM_OUTPUT_LABEL_REF (@var{stream}, @var{buf})
A C statement (sans semicolon) to output a reference to @var{buf}, the
-result of ASM_GENERATE_INTERNAL_LABEL. If not defined,
+result of @code{ASM_GENERATE_INTERNAL_LABEL}. If not defined,
@code{assemble_name} will be used to output the name of the symbol.
This macro is not used by @code{output_asm_label}, or the @code{%l}
specifier that calls it; the intention is that this macro should be set
-when it is necessary to output a label differently when its address
-is being taken.
+when it is necessary to output a label differently when its address is
+being taken.
@findex ASM_OUTPUT_INTERNAL_LABEL
@item ASM_OUTPUT_INTERNAL_LABEL (@var{stream}, @var{prefix}, @var{num})
@@ -6322,17 +6765,6 @@ bundles.
If this macro is not defined, then @code{ASM_OUTPUT_INTERNAL_LABEL} will be
used.
-@findex ASM_OUTPUT_ALTERNATE_LABEL_NAME
-@item ASM_OUTPUT_ALTERNATE_LABEL_NAME (@var{stream}, @var{string})
-A C statement to output to the stdio stream @var{stream} the string
-@var{string}.
-
-The default definition of this macro is as follows:
-
-@example
-fprintf (@var{stream}, "%s:\n", LABEL_ALTERNATE_NAME (INSN))
-@end example
-
@findex ASM_GENERATE_INTERNAL_LABEL
@item ASM_GENERATE_INTERNAL_LABEL (@var{string}, @var{prefix}, @var{num})
A C statement to store into the string @var{string} a label whose name
@@ -6386,15 +6818,6 @@ to have the value of the tree node @var{decl_of_value}. This macro will
be used in preference to @samp{ASM_OUTPUT_DEF} if it is defined and if
the tree nodes are available.
-@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}. GCC guarantees that the symbols @var{high}
-and @var{low} are already known by the assembler so that the difference
-resolves into a constant.
-
@findex SET_ASM_OP
If @code{SET_ASM_OP} is defined, a default definition is provided which is
correct for most systems.
@@ -6513,7 +6936,7 @@ When arbitrary sections are available, there are two variants, depending
upon how the code in @file{crtstuff.c} is called. On systems that
support a @dfn{.init} section which is executed at program startup,
parts of @file{crtstuff.c} are compiled into that section. The
-program is linked by the @code{gcc} driver like this:
+program is linked by the @command{gcc} driver like this:
@example
ld -o @var{output_file} crti.o crtbegin.o @dots{} -lgcc crtend.o crtn.o
@@ -6832,10 +7255,10 @@ A C compound statement to output to stdio stream @var{stream} the
assembler syntax for an instruction operand that is a memory reference
whose address is @var{x}. @var{x} is an RTL expression.
-@cindex @code{ENCODE_SECTION_INFO} usage
+@cindex @code{TARGET_ENCODE_SECTION_INFO} usage
On some machines, the syntax for a symbolic address depends on the
-section that the address refers to. On these machines, define the macro
-@code{ENCODE_SECTION_INFO} to store the information into the
+section that the address refers to. On these machines, define the hook
+@code{TARGET_ENCODE_SECTION_INFO} to store the information into the
@code{symbol_ref}, and then check for it here. @xref{Assembler Format}.
@findex DBR_OUTPUT_SEQEND
@@ -7082,6 +7505,13 @@ is a function that outputs a standard GAS section directive, if
directive followed by a synthetic label.
@end deftypefn
+@deftypevar {Target Hook} bool TARGET_TERMINATE_DW2_EH_FRAME_INFO
+Contains the value true if the target should add a zero word onto the
+end of a Dwarf-2 frame info section when used for exception handling.
+Default value is false if @code{EH_FRAME_SECTION_NAME} is defined, and
+true otherwise.
+@end deftypevar
+
@node Alignment Output
@subsection Assembler Commands for Alignment
@@ -7174,6 +7604,11 @@ A C statement to output to the stdio stream @var{stream} an assembler
command to advance the location counter to a multiple of 2 to the
@var{power} bytes. @var{power} will be a C expression of type @code{int}.
+@findex ASM_OUTPUT_ALIGN_WITH_NOP
+@item ASM_OUTPUT_ALIGN_WITH_NOP (@var{stream}, @var{power})
+Like @code{ASM_OUTPUT_ALIGN}, except that the ``nop'' instruction is used
+for padding, if necessary.
+
@findex ASM_OUTPUT_MAX_SKIP_ALIGN
@item ASM_OUTPUT_MAX_SKIP_ALIGN (@var{stream}, @var{power}, @var{max_skip})
A C statement to output to the stdio stream @var{stream} an assembler
@@ -7620,6 +8055,22 @@ Define this macro to be a nonzero value if the assembler can generate Dwarf 2
line debug info sections. This will result in much more compact line number
tables, and hence is desirable if it works.
+@findex ASM_OUTPUT_DWARF_DELTA
+@item ASM_OUTPUT_DWARF_DELTA (@var{stream}, @var{size}, @var{label1}, @var{label2})
+A C statement to issue assembly directives that create a difference
+between the two given labels, using an integer of the given size.
+
+@findex ASM_OUTPUT_DWARF_OFFSET
+@item ASM_OUTPUT_DWARF_OFFSET (@var{stream}, @var{size}, @var{label})
+A C statement to issue assembly directives that create a
+section-relative reference to the given label, using an integer of the
+given size.
+
+@findex ASM_OUTPUT_DWARF_PCREL
+@item ASM_OUTPUT_DWARF_PCREL (@var{stream}, @var{size}, @var{label})
+A C statement to issue assembly directives that create a self-relative
+reference to the given label, using an integer of the given size.
+
@findex PUT_SDB_@dots{}
@item PUT_SDB_@dots{}
Define these macros to override the assembler syntax for the special
@@ -7673,180 +8124,118 @@ behavior is controlled by @code{OPTIMIZATION_OPTIONS} and
@code{OVERRIDE_OPTIONS}.
@end table
-@node Cross-compilation
+@node Floating Point
@section 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,
+While all modern machines use twos-complement representation for integers,
there are a variety of representations for floating point numbers. This
means that in a cross-compiler the representation of floating point numbers
in the compiled program may be different from that used in the machine
doing the compilation.
-@findex atof
Because different representation systems may offer different amounts of
-range and precision, the cross compiler cannot safely use the host
-machine's floating point arithmetic. Therefore, floating point constants
-must be represented in the target machine's format. This means that the
-cross compiler cannot use @code{atof} to parse a floating point constant;
-it must have its own special routine to use instead. Also, constant
-folding must emulate the target machine's arithmetic (or must not be done
-at all).
+range and precision, all floating point constants must be represented in
+the target machine's format. Therefore, the cross compiler cannot
+safely use the host machine's floating point arithmetic; it must emulate
+the target's arithmetic. To ensure consistency, GCC always uses
+emulation to work with floating point values, even when the host and
+target floating point formats are identical.
+
+The following macros are provided by @file{real.h} for the compiler to
+use. All parts of the compiler which generate or optimize
+floating-point calculations must use these macros. They may evaluate
+their operands more than once, so operands must not have side effects.
+
+@defmac REAL_VALUE_TYPE
+The C data type to be used to hold a floating point value in the target
+machine's format. Typically this is a @code{struct} containing an
+array of @code{HOST_WIDE_INT}, but all code should treat it as an opaque
+quantity.
+@end defmac
+
+@deftypefn Macro int REAL_VALUES_EQUAL (REAL_VALUE_TYPE @var{x}, REAL_VALUE_TYPE @var{y})
+Compares for equality the two values, @var{x} and @var{y}. If the target
+floating point format supports negative zeroes and/or NaNs,
+@samp{REAL_VALUES_EQUAL (-0.0, 0.0)} is true, and
+@samp{REAL_VALUES_EQUAL (NaN, NaN)} is false.
+@end deftypefn
-The macros in the following table should be defined only if you are cross
-compiling between different floating point formats.
+@deftypefn Macro int REAL_VALUES_LESS (REAL_VALUE_TYPE @var{x}, REAL_VALUE_TYPE @var{y})
+Tests whether @var{x} is less than @var{y}.
+@end deftypefn
-Otherwise, don't define them. Then default definitions will be set up which
-use @code{double} as the data type, @code{==} to test for equality, etc.
+@deftypefn Macro HOST_WIDE_INT REAL_VALUE_FIX (REAL_VALUE_TYPE @var{x})
+Truncates @var{x} to a signed integer, rounding toward zero.
+@end deftypefn
-You don't need to worry about how many times you use an operand of any
-of these macros. The compiler never uses operands which have side effects.
+@deftypefn Macro {unsigned HOST_WIDE_INT} REAL_VALUE_UNSIGNED_FIX (REAL_VALUE_TYPE @var{x})
+Truncates @var{x} to an unsigned integer, rounding toward zero. If
+@var{x} is negative, returns zero.
+@end deftypefn
-@table @code
-@findex REAL_VALUE_TYPE
-@item REAL_VALUE_TYPE
-A macro for the C data type to be used to hold a floating point value
-in the target machine's format. Typically this would be a
-@code{struct} containing an array of @code{int}.
-
-@findex REAL_VALUES_EQUAL
-@item REAL_VALUES_EQUAL (@var{x}, @var{y})
-A macro for a C expression which compares for equality the two values,
-@var{x} and @var{y}, both of type @code{REAL_VALUE_TYPE}.
-
-@findex REAL_VALUES_LESS
-@item REAL_VALUES_LESS (@var{x}, @var{y})
-A macro for a C expression which tests whether @var{x} is less than
-@var{y}, both values being of type @code{REAL_VALUE_TYPE} and
-interpreted as floating point numbers in the target machine's
-representation.
-
-@findex REAL_VALUE_LDEXP
-@findex ldexp
-@item REAL_VALUE_LDEXP (@var{x}, @var{scale})
-A macro for a C expression which performs the standard library
-function @code{ldexp}, but using the target machine's floating point
-representation. Both @var{x} and the value of the expression have
-type @code{REAL_VALUE_TYPE}. The second argument, @var{scale}, is an
-integer.
-
-@findex REAL_VALUE_FIX
-@item REAL_VALUE_FIX (@var{x})
-A macro whose definition is a C expression to convert the target-machine
-floating point value @var{x} to a signed integer. @var{x} has type
-@code{REAL_VALUE_TYPE}.
-
-@findex REAL_VALUE_UNSIGNED_FIX
-@item REAL_VALUE_UNSIGNED_FIX (@var{x})
-A macro whose definition is a C expression to convert the target-machine
-floating point value @var{x} to an unsigned integer. @var{x} has type
-@code{REAL_VALUE_TYPE}.
-
-@findex REAL_VALUE_RNDZINT
-@item REAL_VALUE_RNDZINT (@var{x})
-A macro whose definition is a C expression to round the target-machine
-floating point value @var{x} towards zero to an integer value (but still
-as a floating point number). @var{x} has type @code{REAL_VALUE_TYPE},
-and so does the value.
-
-@findex REAL_VALUE_UNSIGNED_RNDZINT
-@item REAL_VALUE_UNSIGNED_RNDZINT (@var{x})
-A macro whose definition is a C expression to round the target-machine
-floating point value @var{x} towards zero to an unsigned integer value
-(but still represented as a floating point number). @var{x} has type
-@code{REAL_VALUE_TYPE}, and so does the value.
-
-@findex REAL_VALUE_ATOF
-@item REAL_VALUE_ATOF (@var{string}, @var{mode})
-A macro for a C expression which converts @var{string}, an expression of
-type @code{char *}, into a floating point number in the target machine's
-representation for mode @var{mode}. The value has type
-@code{REAL_VALUE_TYPE}.
-
-@findex REAL_INFINITY
-@item REAL_INFINITY
-Define this macro if infinity is a possible floating point value, and
-therefore division by 0 is legitimate.
-
-@findex REAL_VALUE_ISINF
-@findex isinf
-@item REAL_VALUE_ISINF (@var{x})
-A macro for a C expression which determines whether @var{x}, a floating
-point value, is infinity. The value has type @code{int}.
-By default, this is defined to call @code{isinf}.
-
-@findex REAL_VALUE_ISNAN
-@findex isnan
-@item REAL_VALUE_ISNAN (@var{x})
-A macro for a C expression which determines whether @var{x}, a floating
-point value, is a ``nan'' (not-a-number). The value has type
-@code{int}. By default, this is defined to call @code{isnan}.
-@end table
+@deftypefn Macro REAL_VALUE_TYPE REAL_VALUE_ATOF (const char *@var{string}, enum machine_mode @var{mode})
+Converts @var{string} into a floating point number in the target machine's
+representation for mode @var{mode}. This routine can handle both
+decimal and hexadecimal floating point constants, using the syntax
+defined by the C language for both.
+@end deftypefn
-@cindex constant folding and floating point
-Define the following additional macros if you want to make floating
-point constant folding work while cross compiling. If you don't
-define them, cross compilation is still possible, but constant folding
-will not happen for floating point values.
+@deftypefn Macro int REAL_VALUE_NEGATIVE (REAL_VALUE_TYPE @var{x})
+Returns 1 if @var{x} is negative (including negative zero), 0 otherwise.
+@end deftypefn
-@table @code
-@findex REAL_ARITHMETIC
-@item REAL_ARITHMETIC (@var{output}, @var{code}, @var{x}, @var{y})
-A macro for a C statement which calculates an arithmetic operation of
-the two floating point values @var{x} and @var{y}, both of type
-@code{REAL_VALUE_TYPE} in the target machine's representation, to
-produce a result of the same type and representation which is stored
-in @var{output} (which will be a variable).
-
-The operation to be performed is specified by @var{code}, a tree code
-which will always be one of the following: @code{PLUS_EXPR},
-@code{MINUS_EXPR}, @code{MULT_EXPR}, @code{RDIV_EXPR},
-@code{MAX_EXPR}, @code{MIN_EXPR}.
-
-@cindex overflow while constant folding
-The expansion of this macro is responsible for checking for overflow.
-If overflow happens, the macro expansion should execute the statement
-@code{return 0;}, which indicates the inability to perform the
-arithmetic operation requested.
-
-@findex REAL_VALUE_NEGATE
-@item REAL_VALUE_NEGATE (@var{x})
-A macro for a C expression which returns the negative of the floating
-point value @var{x}. Both @var{x} and the value of the expression
-have type @code{REAL_VALUE_TYPE} and are in the target machine's
-floating point representation.
-
-There is no way for this macro to report overflow, since overflow
-can't happen in the negation operation.
-
-@findex REAL_VALUE_TRUNCATE
-@item REAL_VALUE_TRUNCATE (@var{mode}, @var{x})
-A macro for a C expression which converts the floating point value
-@var{x} to mode @var{mode}.
-
-Both @var{x} and the value of the expression are in the target machine's
-floating point representation and have type @code{REAL_VALUE_TYPE}.
-However, the value should have an appropriate bit pattern to be output
-properly as a floating constant whose precision accords with mode
-@var{mode}.
+@deftypefn Macro int REAL_VALUE_ISINF (REAL_VALUE_TYPE @var{x})
+Determines whether @var{x} represents infinity (positive or negative).
+@end deftypefn
+
+@deftypefn Macro int REAL_VALUE_ISNAN (REAL_VALUE_TYPE @var{x})
+Determines whether @var{x} represents a ``NaN'' (not-a-number).
+@end deftypefn
+
+@deftypefn Macro void REAL_ARITHMETIC (REAL_VALUE_TYPE @var{output}, enum tree_code @var{code}, REAL_VALUE_TYPE @var{x}, REAL_VALUE_TYPE @var{y})
+Calculates an arithmetic operation on the two floating point values
+@var{x} and @var{y}, storing the result in @var{output} (which must be a
+variable).
+
+The operation to be performed is specified by @var{code}. Only the
+following codes are supported: @code{PLUS_EXPR}, @code{MINUS_EXPR},
+@code{MULT_EXPR}, @code{RDIV_EXPR}, @code{MAX_EXPR}, @code{MIN_EXPR}.
+
+If @code{REAL_ARITHMETIC} is asked to evaluate division by zero and the
+target's floating point format cannot represent infinity, it will call
+@code{abort}. Callers should check for this situation first, using
+@code{MODE_HAS_INFINITIES}. @xref{Storage Layout}.
+@end deftypefn
+
+@deftypefn Macro REAL_VALUE_TYPE REAL_VALUE_NEGATE (REAL_VALUE_TYPE @var{x})
+Returns the negative of the floating point value @var{x}.
+@end deftypefn
-There is no way for this macro to report overflow.
+@deftypefn Macro REAL_VALUE_TYPE REAL_VALUE_ABS (REAL_VALUE_TYPE @var{x})
+Returns the absolute value of @var{x}.
+@end deftypefn
-@findex REAL_VALUE_TO_INT
-@item REAL_VALUE_TO_INT (@var{low}, @var{high}, @var{x})
-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}.
+@deftypefn Macro REAL_VALUE_TYPE REAL_VALUE_TRUNCATE (REAL_VALUE_TYPE @var{mode}, enum machine_mode @var{x})
+Truncates the floating point value @var{x} to fit in @var{mode}. The
+return value is still a full-size @code{REAL_VALUE_TYPE}, but it has an
+appropriate bit pattern to be output asa floating constant whose
+precision accords with mode @var{mode}.
+@end deftypefn
+
+@deftypefn Macro void REAL_VALUE_TO_INT (HOST_WIDE_INT @var{low}, HOST_WIDE_INT @var{high}, REAL_VALUE_TYPE @var{x})
+Converts a floating point value @var{x} into a double-precision integer
+which is then stored into @var{low} and @var{high}. If the value is not
+integral, it is truncated.
+@end deftypefn
-@item REAL_VALUE_FROM_INT (@var{x}, @var{low}, @var{high}, @var{mode})
+@deftypefn Macro void REAL_VALUE_FROM_INT (REAL_VALUE_TYPE @var{x}, HOST_WIDE_INT @var{low}, HOST_WIDE_INT @var{high}, enum machine_mode @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
+Converts a double-precision integer found in @var{low} and @var{high},
+into a floating point value which is then stored into @var{x}. The
+value is truncated to fit in mode @var{mode}.
+@end deftypefn
@node Mode Switching
@section Mode Switching Instructions
@@ -7997,6 +8386,50 @@ attributes, @code{false} otherwise. By default, if a function has a
target specific attribute attached to it, it will not be inlined.
@end deftypefn
+@node MIPS Coprocessors
+@section Defining coprocessor specifics for MIPS targets.
+@cindex MIPS coprocessor-definition macros
+
+The MIPS specification allows MIPS implementations to have as many as 4
+coprocessors, each with as many as 32 private registers. gcc supports
+accessing these registers and transferring values between the registers
+and memory using asm-ized variables. For example:
+
+@smallexample
+ register unsigned int cp0count asm ("c0r1");
+ unsigned int d;
+
+ d = cp0count + 3;
+@end smallexample
+
+(``c0r1'' is the default name of register 1 in coprocessor 0; alternate
+names may be added as described below, or the default names may be
+overridden entirely in @code{SUBTARGET_CONDITIONAL_REGISTER_USAGE}.)
+
+Coprocessor registers are assumed to be epilogue-used; sets to them will
+be preserved even if it does not appear that the register is used again
+later in the function.
+
+Another note: according to the MIPS spec, coprocessor 1 (if present) is
+the FPU. One accesses COP1 registers through standard mips
+floating-point support; they are not included in this mechanism.
+
+There is one macro used in defining the MIPS coprocessor interface which
+you may want to override in subtargets; it is described below.
+
+@table @code
+
+@item ALL_COP_ADDITIONAL_REGISTER_NAMES
+@findex ALL_COP_ADDITIONAL_REGISTER_NAMES
+A comma-separated list (with leading comma) of pairs describing the
+alternate names of coprocessor registers. The format of each entry should be
+@smallexample
+@{ @var{alternatename}, @var{register_number}@}
+@end smallexample
+Default: empty.
+
+@end table
+
@node Misc
@section Miscellaneous Parameters
@cindex parameters, miscellaneous
@@ -8059,7 +8492,7 @@ elements of a jump-table should have.
Optional: return the preferred mode for an @code{addr_diff_vec}
when the minimum and maximum offset are known. If you define this,
it enables extra code in branch shortening to deal with @code{addr_diff_vec}.
-To make this work, you also have to define INSN_ALIGN and
+To make this work, you also have to define @code{INSN_ALIGN} and
make the alignment for @code{addr_diff_vec} explicit.
The @var{body} argument is provided so that the offset_unsigned and scale
flags can be updated.
@@ -8316,11 +8749,6 @@ Defining @code{STDC_0_IN_SYSTEM_HEADERS} makes GNU CPP follows the host
convention when processing system header files, but when processing user
files @code{__STDC__} will always expand to 1.
-@findex SCCS_DIRECTIVE
-@item SCCS_DIRECTIVE
-Define this if the preprocessor should ignore @code{#sccs} directives
-and print no error message.
-
@findex NO_IMPLICIT_EXTERN_C
@item NO_IMPLICIT_EXTERN_C
Define this macro if the system header files support C++ as well as C@.
@@ -8401,6 +8829,21 @@ within a structure, in much the same way as the @samp{__aligned__} and
@samp{__packed__} @code{__attribute__}s do. A pack value of zero resets
the behavior to the default.
+A subtlety for Microsoft Visual C/C++ style bit-field packing
+(e.g. -mms-bitfields) for targets that support it:
+When a bit-field is inserted into a packed record, the whole size
+of the underlying type is used by one or more same-size adjacent
+bit-fields (that is, if its long:3, 32 bits is used in the record,
+and any additional adjacent long bit-fields are packed into the same
+chunk of 32 bits. However, if the size changes, a new field of that
+size is allocated).
+
+If both MS bit-fields and @samp{__attribute__((packed))} are used,
+the latter will take precedence. If @samp{__attribute__((packed))} is
+used on a single field when MS bit-fields are in use, it will take
+precedence for that field, but the alignment of the rest of the structure
+may affect its placement.
+
The weak pragma only works if @code{SUPPORTS_WEAK} and
@code{ASM_WEAKEN_LABEL} are defined. If enabled it allows the creation
of specifically named weak labels, optionally with a value.
@@ -8561,29 +9004,54 @@ conditional execution instructions instead of a branch. A value of
1 if it does use cc0.
@findex IFCVT_MODIFY_TESTS
-@item IFCVT_MODIFY_TESTS
-A C expression to modify the tests in @code{TRUE_EXPR}, and
-@code{FALSE_EXPR} for use in converting insns in @code{TEST_BB},
-@code{THEN_BB}, @code{ELSE_BB}, and @code{JOIN_BB} basic blocks to
-conditional execution. Set either @code{TRUE_EXPR} or @code{FALSE_EXPR}
-to a null pointer if the tests cannot be converted.
+@item IFCVT_MODIFY_TESTS(@var{ce_info}, @var{true_expr}, @var{false_expr})
+Used if the target needs to perform machine-dependent modifications on the
+conditionals used for turning basic blocks into conditionally executed code.
+@var{ce_info} points to a data structure, @code{struct ce_if_block}, which
+contains information about the currently processed blocks. @var{true_expr}
+and @var{false_expr} are the tests that are used for converting the
+then-block and the else-block, respectively. Set either @var{true_expr} or
+@var{false_expr} to a null pointer if the tests cannot be converted.
+
+@findex IFCVT_MODIFY_MULTIPLE_TESTS
+@item IFCVT_MODIFY_MULTIPLE_TESTS(@var{ce_info}, @var{bb}, @var{true_expr}, @var{false_expr})
+Like @code{IFCVT_MODIFY_TESTS}, but used when converting more complicated
+if-statements into conditions combined by @code{and} and @code{or} operations.
+@var{bb} contains the basic block that contains the test that is currently
+being processed and about to be turned into a condition.
@findex IFCVT_MODIFY_INSN
-@item IFCVT_MODIFY_INSN
-A C expression to modify the @code{PATTERN} of an @code{INSN} that is to
-be converted to conditional execution format.
+@item IFCVT_MODIFY_INSN(@var{ce_info}, @var{pattern}, @var{insn})
+A C expression to modify the @var{PATTERN} of an @var{INSN} that is to
+be converted to conditional execution format. @var{ce_info} points to
+a data structure, @code{struct ce_if_block}, which contains information
+about the currently processed blocks.
@findex IFCVT_MODIFY_FINAL
-@item IFCVT_MODIFY_FINAL
+@item IFCVT_MODIFY_FINAL(@var{ce_info})
A C expression to perform any final machine dependent modifications in
-converting code to conditional execution in the basic blocks
-@code{TEST_BB}, @code{THEN_BB}, @code{ELSE_BB}, and @code{JOIN_BB}.
+converting code to conditional execution. The involved basic blocks
+can be found in the @code{struct ce_if_block} structure that is pointed
+to by @var{ce_info}.
@findex IFCVT_MODIFY_CANCEL
-@item IFCVT_MODIFY_CANCEL
+@item IFCVT_MODIFY_CANCEL(@var{ce_info})
A C expression to cancel any machine dependent modifications in
-converting code to conditional execution in the basic blocks
-@code{TEST_BB}, @code{THEN_BB}, @code{ELSE_BB}, and @code{JOIN_BB}.
+converting code to conditional execution. The involved basic blocks
+can be found in the @code{struct ce_if_block} structure that is pointed
+to by @var{ce_info}.
+
+@findex IFCVT_INIT_EXTRA_FIELDS
+@item IFCVT_INIT_EXTRA_FIELDS(@var{ce_info})
+A C expression to initialize any extra fields in a @code{struct ce_if_block}
+structure, which are defined by the @code{IFCVT_EXTRA_FIELDS} macro.
+
+@findex IFCVT_EXTRA_FIELDS
+@item IFCVT_EXTRA_FIELDS
+If defined, it should expand to a set of field declarations that will be
+added to the @code{struct ce_if_block} structure. These should be initialized
+by the @code{IFCVT_INIT_EXTRA_FIELDS} macro.
+
@end table
@deftypefn {Target Hook} void TARGET_INIT_BUILTINS ()
@@ -8668,6 +9136,22 @@ Define this macro for systems like AIX, where the linker discards
object files that are not referenced from @code{main} and uses export
lists.
+@findex MODIFY_JNI_METHOD_CALL
+@item MODIFY_JNI_METHOD_CALL (@var{mdecl})
+Define this macro to a C expression representing a variant of the
+method call @var{mdecl}, if Java Native Interface (JNI) methods
+must be invoked differently from other methods on your target.
+For example, on 32-bit Windows, JNI methods must be invoked using
+the @code{stdcall} calling convention and this macro is then
+defined as this expression:
+
+@smallexample
+build_type_attribute_variant (@var{mdecl},
+ build_tree_list
+ (get_identifier ("stdcall"),
+ NULL))
+@end smallexample
+
@end table
@deftypefn {Target Hook} bool TARGET_CANNOT_MODIFY_JUMPS_P (void)
diff --git a/contrib/gcc/doc/trouble.texi b/contrib/gcc/doc/trouble.texi
index 4cfef9f..4a8f0c3 100644
--- a/contrib/gcc/doc/trouble.texi
+++ b/contrib/gcc/doc/trouble.texi
@@ -163,7 +163,7 @@ Naturally, this does not happen when you use GCC@.
You must specify all three options explicitly.
@item
-On a Sparc, GCC aligns all values of type @code{double} on an 8-byte
+On a SPARC, GCC aligns all values of type @code{double} on an 8-byte
boundary, and it expects every @code{double} to be so aligned. The Sun
compiler usually gives @code{double} values 8-byte alignment, with one
exception: function arguments of type @code{double} may not be aligned.
@@ -202,7 +202,7 @@ Storing into the pointer can be done likewise with the same union.
@item
On Solaris, the @code{malloc} function in the @file{libmalloc.a} library
may allocate memory that is only 4 byte aligned. Since GCC on the
-Sparc assumes that doubles are 8 byte aligned, this may result in a
+SPARC assumes that doubles are 8 byte aligned, this may result in a
fatal signal if doubles are stored in memory allocated by the
@file{libmalloc.a} library.
@@ -219,7 +219,7 @@ when linking, compile and link against the file
@file{mit/util/misc/dlsym.c} from the MIT version of X windows.
@item
-The 128-bit long double format that the Sparc port supports currently
+The 128-bit long double format that the SPARC port supports currently
works by using the architecturally defined quad-word floating point
instructions. Since there is no hardware that supports these
instructions they must be emulated by the operating system. Long
@@ -338,47 +338,6 @@ you cannot successfully use @samp{$} in identifiers on the RS/6000 due
to a restriction in the IBM assembler. GAS supports these
identifiers.
-@item
-@opindex mno-serialize-volatile
-There is an assembler bug in versions of DG/UX prior to 5.4.2.01 that
-occurs when the @samp{fldcr} instruction is used. GCC uses
-@samp{fldcr} on the 88100 to serialize volatile memory references. Use
-the option @option{-mno-serialize-volatile} if your version of the
-assembler has this bug.
-
-@item
-On VMS, GAS versions 1.38.1 and earlier may cause spurious warning
-messages from the linker. These warning messages complain of mismatched
-psect attributes. You can ignore them.
-
-@item
-On NewsOS version 3, if you include both of the files @file{stddef.h}
-and @file{sys/types.h}, you get an error because there are two typedefs
-of @code{size_t}. You should change @file{sys/types.h} by adding these
-lines around the definition of @code{size_t}:
-
-@smallexample
-#ifndef _SIZE_T
-#define _SIZE_T
-@var{actual-typedef-here}
-#endif
-@end smallexample
-
-@cindex Alliant
-@item
-On the Alliant, the system's own convention for returning structures
-and unions is unusual, and is not compatible with GCC no matter
-what options are used.
-
-@cindex RT PC
-@cindex IBM RT PC
-@item
-@opindex mhc-struct-return
-On the IBM RT PC, the MetaWare HighC compiler (hc) uses a different
-convention for structure and union returning. Use the option
-@option{-mhc-struct-return} to tell GCC to use a convention compatible
-with it.
-
@cindex VAX calling convention
@cindex Ultrix calling convention
@item
@@ -395,42 +354,10 @@ these options to produce code compatible with the Fortran compiler:
@end smallexample
@item
-On the WE32k, you may find that programs compiled with GCC do not
-work with the standard shared C library. You may need to link with
-the ordinary C compiler. If you do so, you must specify the following
-options:
-
-@smallexample
--L/usr/local/lib/gcc-lib/we32k-att-sysv/2.8.1 -lgcc -lc_s
-@end smallexample
-
-The first specifies where to find the library @file{libgcc.a}
-specified with the @option{-lgcc} option.
-
-GCC does linking by invoking @command{ld}, just as @command{cc} does, and
-there is no reason why it @emph{should} matter which compilation program
-you use to invoke @command{ld}. If someone tracks this problem down,
-it can probably be fixed easily.
-
-@item
On the Alpha, you may get assembler errors about invalid syntax as a
result of floating point constants. This is due to a bug in the C
library functions @code{ecvt}, @code{fcvt} and @code{gcvt}. Given valid
floating point numbers, they sometimes print @samp{NaN}.
-
-@item
-On Irix 4.0.5F (and perhaps in some other versions), an assembler bug
-sometimes reorders instructions incorrectly when optimization is turned
-on. If you think this may be happening to you, try using the GNU
-assembler; GAS version 2.1 supports ECOFF on Irix.
-
-@opindex noasmopt
-Or use the @option{-noasmopt} option when you compile GCC with itself,
-and then again when you compile your program. (This is a temporary
-kludge to turn off assembler optimization on Irix.) If this proves to
-be what you need, edit the assembler spec in the file @file{specs} so
-that it unconditionally passes @option{-O0} to the assembler, and never
-passes @option{-O2} or @option{-O3}.
@end itemize
@node External Bugs
@@ -445,8 +372,7 @@ Parse errors may occur compiling X11 on a Decstation running Ultrix 4.2
because of problems in DEC's versions of the X11 header files
@file{X11/Xlib.h} and @file{X11/Xutil.h}. People recommend adding
@option{-I/usr/include/mit} to use the MIT versions of the header files,
-using the @option{-traditional} switch to turn off ISO C, or fixing the
-header files by adding this:
+or fixing the header files by adding this:
@example
#ifdef __STDC__
@@ -486,9 +412,7 @@ MALLOC=gmalloc.o
@opindex traditional
There are several noteworthy incompatibilities between GNU C and K&R
-(non-ISO) versions of C@. The @option{-traditional} option
-eliminates many of these incompatibilities, @emph{but not all}, by
-telling GCC to behave like a K&R C compiler.
+(non-ISO) versions of C@.
@itemize @bullet
@cindex string constants
@@ -518,7 +442,6 @@ The best solution to these problems is to change the program to use
purposes instead of string constants. But if this is not possible,
you can use the @option{-fwritable-strings} flag, which directs GCC
to handle string constants the same way most C compilers do.
-@option{-traditional} also has this effect, among others.
@item
@code{-2147483648} is positive.
@@ -538,9 +461,6 @@ string constants. For example, the following macro in GCC
@noindent
will produce output @code{"a"} regardless of what the argument @var{a} is.
-The @option{-traditional} option directs GCC to handle such cases
-(among others) in the old-fashioned (non-ISO) fashion.
-
@cindex @code{setjmp} incompatibilities
@cindex @code{longjmp} incompatibilities
@item
@@ -575,11 +495,6 @@ in it.
If you use the @option{-W} option with the @option{-O} option, you will
get a warning when GCC thinks such a problem might be possible.
-The @option{-traditional} option directs GCC to put variables in
-the stack by default, rather than in registers, in functions that
-call @code{setjmp}. This results in the behavior found in
-traditional C compilers.
-
@item
Programs that use preprocessing directives in the middle of macro
arguments do not work with GCC@. For example, a program like this
@@ -593,9 +508,7 @@ foobar (
@end group
@end example
-ISO C does not permit such a construct. It would make sense to support
-it when @option{-traditional} is used, but it is too much work to
-implement.
+ISO C does not permit such a construct.
@item
K&R compilers allow comments to cross over an inclusion boundary
@@ -613,9 +526,6 @@ have the same scope as any other declaration in the same place.
In some other C compilers, a @code{extern} declaration affects all the
rest of the file even if it happens within a block.
-The @option{-traditional} option directs GCC to treat all @code{extern}
-declarations as global, like traditional compilers.
-
@item
In traditional C, you can combine @code{long}, etc., with a typedef name,
as shown here:
@@ -626,18 +536,15 @@ typedef long foo bar;
@end example
In ISO C, this is not allowed: @code{long} and other type modifiers
-require an explicit @code{int}. Because this criterion is expressed
-by Bison grammar rules rather than C code, the @option{-traditional}
-flag cannot alter it.
+require an explicit @code{int}.
@cindex typedef names as function parameters
@item
-PCC allows typedef names to be used as function parameters. The
-difficulty described immediately above applies here too.
+PCC allows typedef names to be used as function parameters.
@item
-When in @option{-traditional} mode, GCC allows the following erroneous
-pair of declarations to appear together in a given scope:
+Traditional C allows the following erroneous pair of declarations to
+appear together in a given scope:
@example
typedef int foo;
@@ -645,19 +552,18 @@ typedef foo foo;
@end example
@item
-GCC treats all characters of identifiers as significant, even when in
-@option{-traditional} mode. According to K&R-1 (2.2), ``No more than the
-first eight characters are significant, although more may be used.''.
-Also according to K&R-1 (2.2), ``An identifier is a sequence of letters
-and digits; the first character must be a letter. The underscore _
-counts as a letter.'', but GCC also allows dollar signs in identifiers.
+GCC treats all characters of identifiers as significant. According to
+K&R-1 (2.2), ``No more than the first eight characters are significant,
+although more may be used.''. Also according to K&R-1 (2.2), ``An
+identifier is a sequence of letters and digits; the first character must
+be a letter. The underscore _ counts as a letter.'', but GCC also
+allows dollar signs in identifiers.
@cindex whitespace
@item
PCC allows whitespace in the middle of compound assignment operators
such as @samp{+=}. GCC, following the ISO standard, does not
-allow this. The difficulty described immediately above applies here
-too.
+allow this.
@cindex apostrophes
@cindex '
@@ -675,8 +581,7 @@ You can't expect this to work.
@end example
The best solution to such a problem is to put the text into an actual
-C comment delimited by @samp{/*@dots{}*/}. However,
-@option{-traditional} suppresses these error messages.
+C comment delimited by @samp{/*@dots{}*/}.
@item
Many user programs contain the declaration @samp{long time ();}. In the
@@ -916,27 +821,20 @@ You can partially avoid this problem by using the @option{-ffloat-store}
option (@pxref{Optimize Options}).
@item
-On the MIPS, variable argument functions using @file{varargs.h}
-cannot have a floating point value for the first argument. The
-reason for this is that in the absence of a prototype in scope,
-if the first argument is a floating point, it is passed in a
-floating point register, rather than an integer register.
-
-If the code is rewritten to use the ISO standard @file{stdarg.h}
-method of variable arguments, and the prototype is in scope at
-the time of the call, everything will work fine.
-
-@item
-On the H8/300 and H8/300H, variable argument functions must be
-implemented using the ISO standard @file{stdarg.h} method of
-variable arguments. Furthermore, calls to functions using @file{stdarg.h}
-variable arguments must have a prototype for the called function
-in scope at the time of the call.
-
-@item
On AIX and other platforms without weak symbol support, templates
need to be instantiated explicitly and symbols for static members
of templates will not be generated.
+
+@item
+On AIX, GCC scans object files and library archives for static
+constructors and destructors when linking an application before the
+linker prunes unreferenced symbols. This is necessary to prevent the
+AIX linker from mistakenly assuming that static constructor or
+destructor are unused and removing them before the scanning can occur.
+All static constructors and destructors found will be referenced even
+though the modules in which they occur may not be used by the program.
+This may lead to both increased executable size and unexpected symbol
+references.
@end itemize
@node C++ Misunderstandings
@@ -988,9 +886,9 @@ int Foo::bar = 0;
@end example
Other C++ compilers may not correctly implement the standard behavior.
-As a result, when you switch to @code{g++} from one of these compilers,
+As a result, when you switch to @command{g++} from one of these compilers,
you may discover that a program that appeared to work correctly in fact
-does not conform to the standard: @code{g++} reports as undefined
+does not conform to the standard: @command{g++} reports as undefined
symbols any static data members that lack definitions.
@node Temporaries
@@ -1298,12 +1196,11 @@ they write programs which have the same meaning in both C dialects.)
@item
@opindex ansi
-@opindex traditional
@opindex std
Undefining @code{__STDC__} when @option{-ansi} is not used.
-Currently, GCC defines @code{__STDC__} as long as you don't use
-@option{-traditional}. This provides good results in practice.
+Currently, GCC defines @code{__STDC__} unconditionally. This provides
+good results in practice.
Programmers normally use conditionals on @code{__STDC__} to ask whether
it is safe to use certain features of ISO C, such as function
diff --git a/contrib/gcc/doloop.c b/contrib/gcc/doloop.c
index 25deb503..67b742c 100644
--- a/contrib/gcc/doloop.c
+++ b/contrib/gcc/doloop.c
@@ -140,7 +140,7 @@ doloop_condition_get (pattern)
/* Return an estimate of the maximum number of loop iterations for the
loop specified by LOOP or zero if the loop is not normal.
- MODE is the mode of the iteration count and NONNEG is non-zero if
+ MODE is the mode of the iteration count and NONNEG is nonzero if
the iteration count has been proved to be non-negative. */
static unsigned HOST_WIDE_INT
doloop_iterations_max (loop_info, mode, nonneg)
@@ -249,7 +249,7 @@ doloop_iterations_max (loop_info, mode, nonneg)
}
-/* Return non-zero if the loop specified by LOOP is suitable for
+/* Return nonzero if the loop specified by LOOP is suitable for
the use of special low-overhead looping instructions. */
static int
doloop_valid_p (loop, jump_insn)
@@ -263,7 +263,7 @@ doloop_valid_p (loop, jump_insn)
|| ! onlyjump_p (jump_insn))
{
if (loop_dump_stream)
- fprintf (loop_dump_stream,
+ fprintf (loop_dump_stream,
"Doloop: Invalid jump at loop end.\n");
return 0;
}
@@ -339,6 +339,7 @@ doloop_valid_p (loop, jump_insn)
condition at run-time and have an additional jump around the loop
to ensure an infinite loop. */
if (loop_info->comparison_code == NE
+ && !loop_info->preconditioned
&& INTVAL (loop_info->increment) != -1
&& INTVAL (loop_info->increment) != 1)
{
@@ -361,13 +362,13 @@ doloop_valid_p (loop, jump_insn)
{
/* If the comparison is LEU and the comparison value is UINT_MAX
then the loop will not terminate. Similarly, if the
- comparison code is GEU and the initial value is 0, the loop
- will not terminate.
+ comparison code is GEU and the comparison value is 0, the
+ loop will not terminate.
If the absolute increment is not 1, the loop can be infinite
even with LTU/GTU, e.g. for (i = 3; i > 0; i -= 2)
- Note that with LE and GE, the loop behaviour is undefined
+ Note that with LE and GE, the loop behavior is undefined
(C++ standard section 5 clause 5) if an overflow occurs, say
between INT_MAX and INT_MAX + 1. We thus don't have to worry
about these two cases.
@@ -375,7 +376,7 @@ doloop_valid_p (loop, jump_insn)
??? We could compute these conditions at run-time and have a
additional jump around the loop to ensure an infinite loop.
However, it is very unlikely that this is the intended
- behaviour of the loop and checking for these rare boundary
+ behavior of the loop and checking for these rare boundary
conditions would pessimize all other code.
If the loop is executed only a few times an extra check to
@@ -399,7 +400,7 @@ doloop_valid_p (loop, jump_insn)
number of loop iterations, ITERATIONS_MAX is a CONST_INT specifying
the maximum number of loop iterations, and DOLOOP_INSN is the
low-overhead looping insn to emit at the end of the loop. This
- returns non-zero if it was successful. */
+ returns nonzero if it was successful. */
static int
doloop_modify (loop, iterations, iterations_max,
doloop_seq, start_label, condition)
@@ -490,7 +491,7 @@ doloop_modify (loop, iterations, iterations_max,
/* Insert initialization of the count register into the loop header. */
convert_move (counter_reg, count, 1);
- sequence = gen_sequence ();
+ sequence = get_insns ();
end_sequence ();
emit_insn_before (sequence, loop->start);
@@ -508,7 +509,7 @@ doloop_modify (loop, iterations, iterations_max,
{
start_sequence ();
emit_insn (init);
- sequence = gen_sequence ();
+ sequence = get_insns ();
end_sequence ();
emit_insn_after (sequence, loop->start);
}
@@ -539,7 +540,7 @@ doloop_modify (loop, iterations, iterations_max,
not present, we emit one. The loop to modify is described by LOOP.
ITERATIONS_MAX is a CONST_INT specifying the estimated maximum
number of loop iterations. DOLOOP_INSN is the low-overhead looping
- insn to insert. Returns non-zero if loop successfully modified. */
+ insn to insert. Returns nonzero if loop successfully modified. */
static int
doloop_modify_runtime (loop, iterations_max,
doloop_seq, start_label, mode, condition)
@@ -600,18 +601,17 @@ doloop_modify_runtime (loop, iterations_max,
t1 = abs_inc * unroll_number; increment per loop
n = (abs (final - initial) + abs_inc - 1) / t1; full loops
- n += ((abs (final - initial) + abs_inc - 1) % t1) >= abs_inc;
+ n += (abs (final - initial) + abs_inc - 1) % t1) >= abs_inc;
partial loop
which works out to be equivalent to
n = (abs (final - initial) + t1 - 1) / t1;
- However, in certain cases the unrolled loop will be preconditioned
- by emitting copies of the loop body with conditional branches,
- so that the unrolled loop is always a full loop and thus needs
- no exit tests. In this case we don't want to add the partial
- loop count. As above, when t1 is a power of two we don't need to
- worry about overflow.
+ In the case where the loop was preconditioned, a few iterations
+ may have been executed earlier; but 'initial' was adjusted as they
+ were executed, so we don't need anything special for that case here.
+ As above, when t1 is a power of two we don't need to worry about
+ overflow.
The division and modulo operations can be avoided by requiring
that the increment is a power of 2 (precondition_loop_p enforces
@@ -686,15 +686,13 @@ doloop_modify_runtime (loop, iterations_max,
if (shift_count < 0)
abort ();
- if (loop_info->preconditioned)
- diff = expand_simple_binop (GET_MODE (diff), PLUS,
- diff, GEN_INT (abs_inc - 1),
- diff, 1, OPTAB_LIB_WIDEN);
- else
- diff = expand_simple_binop (GET_MODE (diff), PLUS,
- diff, GEN_INT (abs_loop_inc - 1),
- diff, 1, OPTAB_LIB_WIDEN);
+ /* (abs (final - initial) + abs_inc * unroll_number - 1) */
+ diff = expand_simple_binop (GET_MODE (diff), PLUS,
+ diff, GEN_INT (abs_loop_inc - 1),
+ diff, 1, OPTAB_LIB_WIDEN);
+ /* (abs (final - initial) + abs_inc * unroll_number - 1)
+ / (abs_inc * unroll_number) */
diff = expand_simple_binop (GET_MODE (diff), LSHIFTRT,
diff, GEN_INT (shift_count),
diff, 1, OPTAB_LIB_WIDEN);
@@ -740,7 +738,7 @@ doloop_modify_runtime (loop, iterations_max,
}
}
- sequence = gen_sequence ();
+ sequence = get_insns ();
end_sequence ();
emit_insn_before (sequence, loop->start);
@@ -755,7 +753,7 @@ doloop_modify_runtime (loop, iterations_max,
suitable. We distinguish between loops with compile-time bounds
and those with run-time bounds. Information from LOOP is used to
compute the number of iterations and to determine whether the loop
- is a candidate for this optimization. Returns non-zero if loop
+ is a candidate for this optimization. Returns nonzero if loop
successfully modified. */
int
doloop_optimize (loop)
@@ -794,7 +792,7 @@ doloop_optimize (loop)
&increment, &mode))
{
if (loop_dump_stream)
- fprintf (loop_dump_stream,
+ fprintf (loop_dump_stream,
"Doloop: Cannot precondition loop.\n");
return 0;
}
@@ -864,18 +862,19 @@ doloop_optimize (loop)
return 0;
}
- /* A raw define_insn may yield a plain pattern. If a sequence
- was involved, the last must be the jump instruction. */
- if (GET_CODE (doloop_seq) == SEQUENCE)
+ /* If multiple instructions were created, the last must be the
+ jump instruction. Also, a raw define_insn may yield a plain
+ pattern. */
+ doloop_pat = doloop_seq;
+ if (INSN_P (doloop_pat))
{
- doloop_pat = XVECEXP (doloop_seq, 0, XVECLEN (doloop_seq, 0) - 1);
+ while (NEXT_INSN (doloop_pat) != NULL_RTX)
+ doloop_pat = NEXT_INSN (doloop_pat);
if (GET_CODE (doloop_pat) == JUMP_INSN)
doloop_pat = PATTERN (doloop_pat);
else
doloop_pat = NULL_RTX;
}
- else
- doloop_pat = doloop_seq;
if (! doloop_pat
|| ! (condition = doloop_condition_get (doloop_pat)))
diff --git a/contrib/gcc/dominance.c b/contrib/gcc/dominance.c
index 8bfd09d..1bba31f 100644
--- a/contrib/gcc/dominance.c
+++ b/contrib/gcc/dominance.c
@@ -1,9 +1,9 @@
/* Calculate (post)dominators in slightly super-linear time.
Copyright (C) 2000 Free Software Foundation, Inc.
Contributed by Michael Matz (matz@ifh.de).
-
+
This file is part of GCC.
-
+
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
@@ -38,14 +38,26 @@
#include "rtl.h"
#include "hard-reg-set.h"
#include "basic-block.h"
+#include "errors.h"
+#include "et-forest.h"
+struct dominance_info
+{
+ et_forest_t forest;
+ varray_type varray;
+};
+
+#define BB_NODE(info, bb) \
+ ((et_forest_node_t)VARRAY_GENERIC_PTR ((info)->varray, (bb)->index + 2))
+#define SET_BB_NODE(info, bb, node) \
+ (VARRAY_GENERIC_PTR ((info)->varray, (bb)->index + 2) = (node))
/* We name our nodes with integers, beginning with 1. Zero is reserved for
'undefined' or 'end of list'. The name of each node is given by the dfs
number of the corresponding basic block. Please note, that we include the
artificial ENTRY_BLOCK (or EXIT_BLOCK in the post-dom case) in our lists to
support multiple entry points. As it has no real basic block index we use
- 'n_basic_blocks' for that. Its dfs number is of course 1. */
+ 'last_basic_block' for that. Its dfs number is of course 1. */
/* Type of Basic Block aka. TBB */
typedef unsigned int TBB;
@@ -89,7 +101,7 @@ struct dom_info
number of that node in DFS order counted from 1. This is an index
into most of the other arrays in this structure. */
TBB *dfs_order;
- /* If x is the DFS-index of a node which corresponds with an basic block,
+ /* If x is the DFS-index of a node which corresponds with a basic block,
dfs_to_bb[x] is that basic block. Note, that in our structure there are
more nodes that basic blocks, so only dfs_to_bb[dfs_order[bb->index]]==bb
is true for every basic block bb, but not the opposite. */
@@ -113,26 +125,27 @@ static TBB eval PARAMS ((struct dom_info *, TBB));
static void link_roots PARAMS ((struct dom_info *, TBB, TBB));
static void calc_idoms PARAMS ((struct dom_info *,
enum cdi_direction));
-static void idoms_to_doms PARAMS ((struct dom_info *,
- sbitmap *));
+void debug_dominance_info PARAMS ((dominance_info));
/* Helper macro for allocating and initializing an array,
for aesthetic reasons. */
#define init_ar(var, type, num, content) \
- do { \
- unsigned int i = 1; /* Catch content == i. */ \
- if (! (content)) \
- (var) = (type *) xcalloc ((num), sizeof (type)); \
- else \
- { \
- (var) = (type *) xmalloc ((num) * sizeof (type)); \
- for (i = 0; i < num; i++) \
- (var)[i] = (content); \
- } \
- } while (0)
+ do \
+ { \
+ unsigned int i = 1; /* Catch content == i. */ \
+ if (! (content)) \
+ (var) = (type *) xcalloc ((num), sizeof (type)); \
+ else \
+ { \
+ (var) = (type *) xmalloc ((num) * sizeof (type)); \
+ for (i = 0; i < num; i++) \
+ (var)[i] = (content); \
+ } \
+ } \
+ while (0)
/* Allocate all needed memory in a pessimistic fashion (so we round up).
- This initialises the contents of DI, which already must be allocated. */
+ This initializes the contents of DI, which already must be allocated. */
static void
init_dom_info (di)
@@ -153,7 +166,7 @@ init_dom_info (di)
init_ar (di->set_size, unsigned int, num, 1);
init_ar (di->set_child, TBB, num, 0);
- init_ar (di->dfs_order, TBB, (unsigned int) n_basic_blocks + 1, 0);
+ init_ar (di->dfs_order, TBB, (unsigned int) last_basic_block + 1, 0);
init_ar (di->dfs_to_bb, basic_block, num, 0);
di->dfsnum = 1;
@@ -269,7 +282,7 @@ calc_dfs_tree_nonrec (di, bb, reverse)
if (bb != en_block)
my_i = di->dfs_order[bb->index];
else
- my_i = di->dfs_order[n_basic_blocks];
+ my_i = di->dfs_order[last_basic_block];
child_i = di->dfs_order[bn->index] = di->dfsnum++;
di->dfs_to_bb[child_i] = bn;
di->dfs_parent[child_i] = my_i;
@@ -312,7 +325,7 @@ calc_dfs_tree (di, reverse)
{
/* The first block is the ENTRY_BLOCK (or EXIT_BLOCK if REVERSE). */
basic_block begin = reverse ? EXIT_BLOCK_PTR : ENTRY_BLOCK_PTR;
- di->dfs_order[n_basic_blocks] = di->dfsnum;
+ di->dfs_order[last_basic_block] = di->dfsnum;
di->dfs_to_bb[di->dfsnum] = begin;
di->dfsnum++;
@@ -324,10 +337,9 @@ calc_dfs_tree (di, reverse)
They are reverse-unreachable. In the dom-case we disallow such
nodes, but in post-dom we have to deal with them, so we simply
include them in the DFS tree which actually becomes a forest. */
- int i;
- for (i = n_basic_blocks - 1; i >= 0; i--)
+ basic_block b;
+ FOR_EACH_BB_REVERSE (b)
{
- basic_block b = BASIC_BLOCK (i);
if (di->dfs_order[b->index])
continue;
di->dfs_order[b->index] = di->dfsnum;
@@ -492,7 +504,7 @@ calc_idoms (di, reverse)
e_next = e->pred_next;
}
if (b == en_block)
- k1 = di->dfs_order[n_basic_blocks];
+ k1 = di->dfs_order[last_basic_block];
else
k1 = di->dfs_order[b->index];
@@ -530,53 +542,9 @@ calc_idoms (di, reverse)
di->dom[v] = di->dom[di->dom[v]];
}
-/* Convert the information about immediate dominators (in DI) to sets of all
- dominators (in DOMINATORS). */
-
-static void
-idoms_to_doms (di, dominators)
- struct dom_info *di;
- sbitmap *dominators;
-{
- TBB i, e_index;
- int bb, bb_idom;
- sbitmap_vector_zero (dominators, n_basic_blocks);
- /* We have to be careful, to not include the ENTRY_BLOCK or EXIT_BLOCK
- in the list of (post)-doms, so remember that in e_index. */
- e_index = di->dfs_order[n_basic_blocks];
-
- for (i = 1; i <= di->nodes; i++)
- {
- if (i == e_index)
- continue;
- bb = di->dfs_to_bb[i]->index;
-
- if (di->dom[i] && (di->dom[i] != e_index))
- {
- bb_idom = di->dfs_to_bb[di->dom[i]]->index;
- sbitmap_copy (dominators[bb], dominators[bb_idom]);
- }
- else
- {
- /* It has no immediate dom or only ENTRY_BLOCK or EXIT_BLOCK.
- If it is a child of ENTRY_BLOCK that's OK, and it's only
- dominated by itself; if it's _not_ a child of ENTRY_BLOCK, it
- means, it is unreachable. That case has been disallowed in the
- building of the DFS tree, so we are save here. For the reverse
- flow graph it means, it has no children, so, to be compatible
- with the old code, we set the post_dominators to all one. */
- if (!di->dom[i])
- {
- sbitmap_ones (dominators[bb]);
- }
- }
- SET_BIT (dominators[bb], bb);
- }
-}
-
/* The main entry point into this module. IDOM is an integer array with room
- for n_basic_blocks integers, DOMS is a preallocated sbitmap array having
- room for n_basic_blocks^2 bits, and POST is true if the caller wants to
+ for last_basic_block integers, DOMS is a preallocated sbitmap array having
+ room for last_basic_block^2 bits, and POST is true if the caller wants to
know post-dominators.
On return IDOM[i] will be the BB->index of the immediate (post) dominator
@@ -586,37 +554,259 @@ idoms_to_doms (di, dominators)
Either IDOM or DOMS may be NULL (meaning the caller is not interested in
immediate resp. all dominators). */
-void
-calculate_dominance_info (idom, doms, reverse)
- int *idom;
- sbitmap *doms;
+dominance_info
+calculate_dominance_info (reverse)
enum cdi_direction reverse;
{
struct dom_info di;
+ dominance_info info;
+ basic_block b;
+
+ /* allocate structure for dominance information. */
+ info = xmalloc (sizeof (struct dominance_info));
+ info->forest = et_forest_create ();
+ VARRAY_GENERIC_PTR_INIT (info->varray, last_basic_block + 3, "dominance info");
+
+ /* Add the two well-known basic blocks. */
+ SET_BB_NODE (info, ENTRY_BLOCK_PTR, et_forest_add_node (info->forest,
+ ENTRY_BLOCK_PTR));
+ SET_BB_NODE (info, EXIT_BLOCK_PTR, et_forest_add_node (info->forest,
+ EXIT_BLOCK_PTR));
+ FOR_EACH_BB (b)
+ SET_BB_NODE (info, b, et_forest_add_node (info->forest, b));
- if (!doms && !idom)
- return;
init_dom_info (&di);
calc_dfs_tree (&di, reverse);
calc_idoms (&di, reverse);
- if (idom)
+
+ FOR_EACH_BB (b)
+ {
+ TBB d = di.dom[di.dfs_order[b->index]];
+
+ if (di.dfs_to_bb[d])
+ et_forest_add_edge (info->forest, BB_NODE (info, di.dfs_to_bb[d]), BB_NODE (info, b));
+ }
+
+ free_dom_info (&di);
+ return info;
+}
+
+/* Free dominance information. */
+void
+free_dominance_info (info)
+ dominance_info info;
+{
+ basic_block bb;
+
+ /* Allow users to create new basic block without setting up the dominance
+ information for them. */
+ FOR_EACH_BB (bb)
+ if (bb->index < (int)(info->varray->num_elements - 2)
+ && BB_NODE (info, bb))
+ delete_from_dominance_info (info, bb);
+ delete_from_dominance_info (info, ENTRY_BLOCK_PTR);
+ delete_from_dominance_info (info, EXIT_BLOCK_PTR);
+ et_forest_delete (info->forest);
+ VARRAY_GROW (info->varray, 0);
+ free (info);
+}
+
+/* Return the immediate dominator of basic block BB. */
+basic_block
+get_immediate_dominator (dom, bb)
+ dominance_info dom;
+ basic_block bb;
+{
+ return et_forest_node_value (dom->forest,
+ et_forest_parent (dom->forest,
+ BB_NODE (dom, bb)));
+}
+
+/* Set the immediate dominator of the block possibly removing
+ existing edge. NULL can be used to remove any edge. */
+inline void
+set_immediate_dominator (dom, bb, dominated_by)
+ dominance_info dom;
+ basic_block bb, dominated_by;
+{
+ void *aux_bb_node;
+ et_forest_node_t bb_node = BB_NODE (dom, bb);
+
+ aux_bb_node = et_forest_parent (dom->forest, bb_node);
+ if (aux_bb_node)
+ et_forest_remove_edge (dom->forest, aux_bb_node, bb_node);
+ if (dominated_by != NULL)
+ {
+ if (bb == dominated_by)
+ abort ();
+ if (!et_forest_add_edge (dom->forest, BB_NODE (dom, dominated_by), bb_node))
+ abort ();
+ }
+}
+
+/* Store all basic blocks dominated by BB into BBS and return their number. */
+int
+get_dominated_by (dom, bb, bbs)
+ dominance_info dom;
+ basic_block bb;
+ basic_block **bbs;
+{
+ int n, i;
+
+ *bbs = xmalloc (n_basic_blocks * sizeof (basic_block));
+ n = et_forest_enumerate_sons (dom->forest, BB_NODE (dom, bb), (et_forest_node_t *)*bbs);
+ for (i = 0; i < n; i++)
+ (*bbs)[i] = et_forest_node_value (dom->forest, (et_forest_node_t)(*bbs)[i]);
+ return n;
+}
+
+/* Redirect all edges pointing to BB to TO. */
+void
+redirect_immediate_dominators (dom, bb, to)
+ dominance_info dom;
+ basic_block bb;
+ basic_block to;
+{
+ et_forest_node_t *bbs = xmalloc (n_basic_blocks * sizeof (basic_block));
+ et_forest_node_t node = BB_NODE (dom, bb);
+ et_forest_node_t node2 = BB_NODE (dom, to);
+ int n = et_forest_enumerate_sons (dom->forest, node, bbs);
+ int i;
+
+ for (i = 0; i < n; i++)
{
- int i;
- for (i = 0; i < n_basic_blocks; i++)
+ et_forest_remove_edge (dom->forest, node, bbs[i]);
+ et_forest_add_edge (dom->forest, node2, bbs[i]);
+ }
+ free (bbs);
+}
+
+/* Find first basic block in the tree dominating both BB1 and BB2. */
+basic_block
+nearest_common_dominator (dom, bb1, bb2)
+ dominance_info dom;
+ basic_block bb1;
+ basic_block bb2;
+{
+ if (!bb1)
+ return bb2;
+ if (!bb2)
+ return bb1;
+ return et_forest_node_value (dom->forest,
+ et_forest_common_ancestor (dom->forest,
+ BB_NODE (dom, bb1),
+ BB_NODE (dom,
+ bb2)));
+}
+
+/* Return TRUE in case BB1 is dominated by BB2. */
+bool
+dominated_by_p (dom, bb1, bb2)
+ dominance_info dom;
+ basic_block bb1;
+ basic_block bb2;
+{
+ return nearest_common_dominator (dom, bb1, bb2) == bb2;
+}
+
+/* Verify invariants of dominator structure. */
+void
+verify_dominators (dom)
+ dominance_info dom;
+{
+ int err = 0;
+ basic_block bb;
+
+ FOR_EACH_BB (bb)
+ {
+ basic_block dom_bb;
+
+ dom_bb = recount_dominator (dom, bb);
+ if (dom_bb != get_immediate_dominator (dom, bb))
{
- basic_block b = BASIC_BLOCK (i);
- TBB d = di.dom[di.dfs_order[b->index]];
-
- /* The old code didn't modify array elements of nodes having only
- itself as dominator (d==0) or only ENTRY_BLOCK (resp. EXIT_BLOCK)
- (d==1). */
- if (d > 1)
- idom[i] = di.dfs_to_bb[d]->index;
+ error ("dominator of %d should be %d, not %d",
+ bb->index, dom_bb->index, get_immediate_dominator(dom, bb)->index);
+ err = 1;
}
}
- if (doms)
- idoms_to_doms (&di, doms);
+ if (err)
+ abort ();
+}
- free_dom_info (&di);
+/* Recount dominator of BB. */
+basic_block
+recount_dominator (dom, bb)
+ dominance_info dom;
+ basic_block bb;
+{
+ basic_block dom_bb = NULL;
+ edge e;
+
+ for (e = bb->pred; e; e = e->pred_next)
+ {
+ if (!dominated_by_p (dom, e->src, bb))
+ dom_bb = nearest_common_dominator (dom, dom_bb, e->src);
+ }
+
+ return dom_bb;
+}
+
+/* Iteratively recount dominators of BBS. The change is supposed to be local
+ and not to grow further. */
+void
+iterate_fix_dominators (dom, bbs, n)
+ dominance_info dom;
+ basic_block *bbs;
+ int n;
+{
+ int i, changed = 1;
+ basic_block old_dom, new_dom;
+
+ while (changed)
+ {
+ changed = 0;
+ for (i = 0; i < n; i++)
+ {
+ old_dom = get_immediate_dominator (dom, bbs[i]);
+ new_dom = recount_dominator (dom, bbs[i]);
+ if (old_dom != new_dom)
+ {
+ changed = 1;
+ set_immediate_dominator (dom, bbs[i], new_dom);
+ }
+ }
+ }
+}
+
+void
+add_to_dominance_info (dom, bb)
+ dominance_info dom;
+ basic_block bb;
+{
+ VARRAY_GROW (dom->varray, last_basic_block + 3);
+#ifdef ENABLE_CHECKING
+ if (BB_NODE (dom, bb))
+ abort ();
+#endif
+ SET_BB_NODE (dom, bb, et_forest_add_node (dom->forest, bb));
+}
+
+void
+delete_from_dominance_info (dom, bb)
+ dominance_info dom;
+ basic_block bb;
+{
+ et_forest_remove_node (dom->forest, BB_NODE (dom, bb));
+ SET_BB_NODE (dom, bb, NULL);
+}
+
+void
+debug_dominance_info (dom)
+ dominance_info dom;
+{
+ basic_block bb, bb2;
+ FOR_EACH_BB (bb)
+ if ((bb2 = get_immediate_dominator (dom, bb)))
+ fprintf (stderr, "%i %i\n", bb->index, bb2->index);
}
diff --git a/contrib/gcc/doschk.c b/contrib/gcc/doschk.c
index ad553df..d024efc 100644
--- a/contrib/gcc/doschk.c
+++ b/contrib/gcc/doschk.c
@@ -71,13 +71,13 @@ char *path;
char *last_slash = strrchr (path, '/');
char *cp, *dp;
int dots_seen, chars_seen;
-
+
if (last_slash+1 == null)
{
* --null = '\0';
last_slash = strrchr (path, '/');
}
-
+
if (!last_slash)
{
last_slash = first-1;
@@ -239,7 +239,7 @@ display_problems ()
{
ENT **elist, *ent;
int ecount, i, first, first_err;
-
+
for (ecount=0, ent=eroot; ent; ent=ent->next, ecount++);
elist = (ENT **)malloc (sizeof (ENT *) * ecount);
for (ecount=0, ent=eroot; ent; ent=ent->next, ecount++)
diff --git a/contrib/gcc/dummy-conditions.c b/contrib/gcc/dummy-conditions.c
new file mode 100644
index 0000000..157f86b
--- /dev/null
+++ b/contrib/gcc/dummy-conditions.c
@@ -0,0 +1,34 @@
+/* Support for calculating constant conditions.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "hconfig.h"
+#include "system.h"
+#include "gensupport.h"
+
+/* MD generators that are run before insn-conditions.c exists should
+ link against this file instead. Currently that is genconditions
+ and genconstants. */
+
+/* Empty conditions table to prevent link errors. */
+const struct c_test insn_conditions[1] = { { 0, 0 } };
+const size_t n_insn_conditions = 0;
+
+/* Disable insn elision, since it is currently impossible. */
+const int insn_elision_unavailable = 1;
diff --git a/contrib/gcc/dwarf2.h b/contrib/gcc/dwarf2.h
index a84eb2c..a7f5f0f 100644
--- a/contrib/gcc/dwarf2.h
+++ b/contrib/gcc/dwarf2.h
@@ -399,10 +399,12 @@ enum dwarf_location_atom
DW_OP_push_object_address = 0x97,
DW_OP_call2 = 0x98,
DW_OP_call4 = 0x99,
- DW_OP_calli = 0x9a
+ DW_OP_call_ref = 0x9a,
+ /* GNU extensions. */
+ DW_OP_GNU_push_tls_address = 0xe0
};
-#define DW_OP_lo_user 0x80 /* Implementation-defined range start. */
+#define DW_OP_lo_user 0xe0 /* Implementation-defined range start. */
#define DW_OP_hi_user 0xff /* Implementation-defined range end. */
/* Type encodings. */
diff --git a/contrib/gcc/dwarf2asm.c b/contrib/gcc/dwarf2asm.c
index 2222ecd..b5a87de 100644
--- a/contrib/gcc/dwarf2asm.c
+++ b/contrib/gcc/dwarf2asm.c
@@ -60,7 +60,7 @@ dw2_assemble_integer (size, x)
else
assemble_integer (x, size, BITS_PER_UNIT, 1);
}
-
+
/* Output an immediate constant in a given size. */
@@ -104,11 +104,14 @@ dw2_asm_output_delta VPARAMS ((int size, const char *lab1, const char *lab2,
VA_FIXEDARG (ap, const char *, lab2);
VA_FIXEDARG (ap, const char *, comment);
+#ifdef ASM_OUTPUT_DWARF_DELTA
+ ASM_OUTPUT_DWARF_DELTA (asm_out_file, size, lab1, lab2);
+#else
dw2_assemble_integer (size,
gen_rtx_MINUS (Pmode,
gen_rtx_SYMBOL_REF (Pmode, lab1),
gen_rtx_SYMBOL_REF (Pmode, lab2)));
-
+#endif
if (flag_debug_asm && comment)
{
fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
@@ -316,7 +319,7 @@ size_of_sleb128 (value)
}
/* Given an encoding, return the number of bytes the format occupies.
- This is only defined for fixed-size encodings, and so does not
+ This is only defined for fixed-size encodings, and so does not
include leb128. */
int
@@ -561,7 +564,7 @@ dw2_asm_output_data_uleb128 VPARAMS ((unsigned HOST_WIDE_INT value,
VA_CLOSE (ap);
}
-/* Output an signed LEB128 quantity. */
+/* Output a signed LEB128 quantity. */
void
dw2_asm_output_data_sleb128 VPARAMS ((HOST_WIDE_INT value,
@@ -704,7 +707,7 @@ mark_indirect_pool_entry (node, data)
splay_tree_node node;
void* data ATTRIBUTE_UNUSED;
{
- ggc_mark_nonnull_tree ((tree) node->value);
+ ggc_mark_tree ((tree) node->value);
return 0;
}
@@ -739,7 +742,7 @@ dw2_force_const_mem (x)
if (GET_CODE (x) != SYMBOL_REF)
abort ();
- STRIP_NAME_ENCODING (str, XSTR (x, 0));
+ str = (* targetm.strip_name_encoding) (XSTR (x, 0));
node = splay_tree_lookup (indirect_pool, (splay_tree_key) str);
if (node)
decl = (tree) node->value;
@@ -845,7 +848,7 @@ dw2_asm_output_encoded_addr_rtx VPARAMS ((int encoding,
{
restart:
/* Allow the target first crack at emitting this. Some of the
- special relocations require special directives instead of
+ special relocations require special directives instead of
just ".4byte" or whatever. */
#ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
@@ -883,7 +886,7 @@ dw2_asm_output_encoded_addr_rtx VPARAMS ((int encoding,
break;
default:
- /* Other encodings should have been handled by
+ /* Other encodings should have been handled by
ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
abort ();
}
diff --git a/contrib/gcc/dwarf2asm.h b/contrib/gcc/dwarf2asm.h
index 859883d..8d6fd18 100644
--- a/contrib/gcc/dwarf2asm.h
+++ b/contrib/gcc/dwarf2asm.h
@@ -19,60 +19,56 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
-/* ??? Format checking yields "null format string" warnings, which is
- the way these routines are signaled that there is no associated
- debug information. So the attributes are commented out. */
-
extern void dw2_assemble_integer PARAMS ((int, rtx));
extern void dw2_asm_output_data PARAMS ((int, unsigned HOST_WIDE_INT,
const char *, ...))
- /* ATTRIBUTE_PRINTF_3 */;
+ ATTRIBUTE_NULL_PRINTF_3;
extern void dw2_asm_output_delta PARAMS ((int, const char *,
const char *,
const char *, ...))
- /* ATTRIBUTE_PRINTF_4 */;
+ ATTRIBUTE_NULL_PRINTF_4;
extern void dw2_asm_output_offset PARAMS ((int, const char *,
const char *, ...))
- /* ATTRIBUTE_PRINTF_3 */;
+ ATTRIBUTE_NULL_PRINTF_3;
extern void dw2_asm_output_pcrel PARAMS ((int, const char *,
const char *, ...))
- /* ATTRIBUTE_PRINTF_3 */;
+ ATTRIBUTE_NULL_PRINTF_3;
extern void dw2_asm_output_addr PARAMS ((int, const char *,
const char *, ...))
- /* ATTRIBUTE_PRINTF_3 */;
+ ATTRIBUTE_NULL_PRINTF_3;
extern void dw2_asm_output_addr_rtx PARAMS ((int, rtx,
const char *, ...))
- /* ATTRIBUTE_PRINTF_3 */;
+ ATTRIBUTE_NULL_PRINTF_3;
extern void dw2_asm_output_encoded_addr_rtx PARAMS ((int, rtx,
const char *, ...))
- /* ATTRIBUTE_PRINTF_3 */;
+ ATTRIBUTE_NULL_PRINTF_3;
extern void dw2_asm_output_nstring PARAMS ((const char *, size_t,
const char *, ...))
- /* ATTRIBUTE_PRINTF_3 */;
+ ATTRIBUTE_NULL_PRINTF_3;
extern void dw2_asm_output_data_uleb128 PARAMS ((unsigned HOST_WIDE_INT,
const char *, ...))
- /* ATTRIBUTE_PRINTF_2 */;
+ ATTRIBUTE_NULL_PRINTF_2;
extern void dw2_asm_output_data_sleb128 PARAMS ((HOST_WIDE_INT,
const char *, ...))
- /* ATTRIBUTE_PRINTF_2 */;
+ ATTRIBUTE_NULL_PRINTF_2;
extern void dw2_asm_output_delta_uleb128 PARAMS ((const char *, const char *,
const char *, ...))
- /* ATTRIBUTE_PRINTF_3 */;
+ ATTRIBUTE_NULL_PRINTF_3;
extern void dw2_asm_output_delta_sleb128 PARAMS ((const char *, const char *,
const char *, ...))
- /* ATTRIBUTE_PRINTF_3 */;
+ ATTRIBUTE_NULL_PRINTF_3;
extern int size_of_uleb128 PARAMS ((unsigned HOST_WIDE_INT));
extern int size_of_sleb128 PARAMS ((HOST_WIDE_INT));
diff --git a/contrib/gcc/dwarf2out.c b/contrib/gcc/dwarf2out.c
index c691dd0..e624bc9 100644
--- a/contrib/gcc/dwarf2out.c
+++ b/contrib/gcc/dwarf2out.c
@@ -38,6 +38,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "system.h"
#include "tree.h"
#include "flags.h"
+#include "real.h"
#include "rtl.h"
#include "hard-reg-set.h"
#include "regs.h"
@@ -61,6 +62,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "target.h"
#include "langhooks.h"
#include "hashtable.h"
+#include "hashtab.h"
#ifdef DWARF2_DEBUGGING_INFO
static void dwarf2out_source_line PARAMS ((unsigned int, const char *));
@@ -102,13 +104,6 @@ dwarf2out_do_frame ()
);
}
-/* The number of the current function definition for which debugging
- information is being generated. These numbers range from 1 up to the
- maximum number of function definitions contained within the current
- compilation unit. These numbers are used to create unique label id's
- unique to each function definition. */
-unsigned current_funcdef_number = 0;
-
/* The size of the target's pointer type. */
#ifndef PTR_SIZE
#define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
@@ -122,17 +117,50 @@ void
default_eh_frame_section ()
{
#ifdef EH_FRAME_SECTION_NAME
+#ifdef HAVE_LD_RO_RW_SECTION_MIXING
+ int fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0);
+ int per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
+ int lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
+ int flags;
+
+ flags = (! flag_pic
+ || ((fde_encoding & 0x70) != DW_EH_PE_absptr
+ && (fde_encoding & 0x70) != DW_EH_PE_aligned
+ && (per_encoding & 0x70) != DW_EH_PE_absptr
+ && (per_encoding & 0x70) != DW_EH_PE_aligned
+ && (lsda_encoding & 0x70) != DW_EH_PE_absptr
+ && (lsda_encoding & 0x70) != DW_EH_PE_aligned))
+ ? 0 : SECTION_WRITE;
+ named_section_flags (EH_FRAME_SECTION_NAME, flags);
+#else
named_section_flags (EH_FRAME_SECTION_NAME, SECTION_WRITE);
+#endif
#else
tree label = get_file_function_name ('F');
data_section ();
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
- ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
+ (*targetm.asm_out.globalize_label) (asm_out_file, IDENTIFIER_POINTER (label));
ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
#endif
}
+/* Array of RTXes referenced by the debugging information, which therefore
+ must be kept around forever. */
+static GTY(()) varray_type used_rtx_varray;
+
+/* A pointer to the base of a list of incomplete types which might be
+ completed at some later time. incomplete_types_list needs to be a VARRAY
+ because we want to tell the garbage collector about it. */
+static GTY(()) varray_type incomplete_types;
+
+/* A pointer to the base of a table of references to declaration
+ scopes. This table is a display which tracks the nesting
+ of declaration scopes at the current scope and containing
+ scopes. This table is used to find the proper place to
+ define type declaration DIE's. */
+static GTY(()) varray_type decl_scope_table;
+
#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
/* How to start an assembler comment. */
@@ -193,6 +221,7 @@ typedef struct dw_fde_struct
const char *dw_fde_end;
dw_cfi_ref dw_fde_cfi;
unsigned funcdef_number;
+ unsigned all_throwers_are_sibcalls : 1;
unsigned nothrow : 1;
unsigned uses_eh_lsda : 1;
}
@@ -307,11 +336,6 @@ static void def_cfa_1 PARAMS ((const char *,
#define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4)
#define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4)
-/* Pseudo-op for defining a new section. */
-#ifndef SECTION_ASM_OP
-#define SECTION_ASM_OP "\t.section\t"
-#endif
-
#ifndef DEBUG_FRAME_SECTION
#define DEBUG_FRAME_SECTION ".debug_frame"
#endif
@@ -327,35 +351,15 @@ static void def_cfa_1 PARAMS ((const char *,
#define FRAME_BEGIN_LABEL "Lframe"
#define CIE_AFTER_SIZE_LABEL "LSCIE"
#define CIE_END_LABEL "LECIE"
-#define CIE_LENGTH_LABEL "LLCIE"
#define FDE_LABEL "LSFDE"
#define FDE_AFTER_SIZE_LABEL "LASFDE"
#define FDE_END_LABEL "LEFDE"
-#define FDE_LENGTH_LABEL "LLFDE"
#define LINE_NUMBER_BEGIN_LABEL "LSLT"
#define LINE_NUMBER_END_LABEL "LELT"
#define LN_PROLOG_AS_LABEL "LASLTP"
#define LN_PROLOG_END_LABEL "LELTP"
#define DIE_LABEL_PREFIX "DW"
-/* Definitions of defaults for various types of primitive assembly language
- output operations. These may be overridden from within the tm.h file,
- but typically, that is unnecessary. */
-
-#ifdef SET_ASM_OP
-#ifndef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
-#define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO) \
- do { \
- fprintf (FILE, "%s", SET_ASM_OP); \
- assemble_name (FILE, SY); \
- fputc (',', FILE); \
- assemble_name (FILE, HI); \
- fputc ('-', FILE); \
- assemble_name (FILE, LO); \
- } while (0)
-#endif
-#endif
-
/* The DWARF 2 CFA column which tracks the return address. Normally this
is the column for PC, or the first column after all of the hard
registers. */
@@ -382,9 +386,9 @@ static void def_cfa_1 PARAMS ((const char *,
/* Hook used by __throw. */
rtx
-expand_builtin_dwarf_fp_regnum ()
+expand_builtin_dwarf_sp_column ()
{
- return GEN_INT (DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM));
+ return GEN_INT (DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM));
}
/* Return a pointer to a copy of the section string name S with all
@@ -951,6 +955,8 @@ stack_adjust_offset (pattern)
return 0;
offset = INTVAL (XEXP (src, 1));
+ if (code == PLUS)
+ offset = -offset;
}
else if (GET_CODE (dest) == MEM)
{
@@ -958,30 +964,47 @@ stack_adjust_offset (pattern)
src = XEXP (dest, 0);
code = GET_CODE (src);
- if ((code != PRE_DEC && code != PRE_INC && code != PRE_MODIFY)
- || XEXP (src, 0) != stack_pointer_rtx)
- return 0;
-
- if (code == PRE_MODIFY)
+ switch (code)
{
- rtx val = XEXP (XEXP (src, 1), 1);
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ if (XEXP (src, 0) == stack_pointer_rtx)
+ {
+ rtx val = XEXP (XEXP (src, 1), 1);
+ /* We handle only adjustments by constant amount. */
+ if (GET_CODE (XEXP (src, 1)) != PLUS ||
+ GET_CODE (val) != CONST_INT)
+ abort ();
+ offset = -INTVAL (val);
+ break;
+ }
+ return 0;
- /* We handle only adjustments by constant amount. */
- if (GET_CODE (XEXP (src, 1)) != PLUS ||
- GET_CODE (val) != CONST_INT)
- abort ();
+ case PRE_DEC:
+ case POST_DEC:
+ if (XEXP (src, 0) == stack_pointer_rtx)
+ {
+ offset = GET_MODE_SIZE (GET_MODE (dest));
+ break;
+ }
+ return 0;
- offset = -INTVAL (val);
+ case PRE_INC:
+ case POST_INC:
+ if (XEXP (src, 0) == stack_pointer_rtx)
+ {
+ offset = -GET_MODE_SIZE (GET_MODE (dest));
+ break;
+ }
+ return 0;
+
+ default:
+ return 0;
}
- else
- offset = GET_MODE_SIZE (GET_MODE (dest));
}
else
return 0;
- if (code == PLUS || code == PRE_INC)
- offset = -offset;
-
return offset;
}
@@ -1096,7 +1119,7 @@ flush_queued_reg_saves ()
{
struct queued_reg_save *q, *next;
- for (q = queued_reg_saves; q ; q = next)
+ for (q = queued_reg_saves; q; q = next)
{
dwarf2out_reg_save (last_reg_save_label, REGNO (q->reg), q->cfa_offset);
next = q->next;
@@ -1113,13 +1136,13 @@ clobbers_queued_reg_save (insn)
{
struct queued_reg_save *q;
- for (q = queued_reg_saves; q ; q = q->next)
+ for (q = queued_reg_saves; q; q = q->next)
if (modified_in_p (q->reg, insn))
return true;
return false;
}
-
+
/* A temporary register holding an integral value used in adjusting SP
or setting up the store_reg. The "offset" field holds the integer
@@ -1155,7 +1178,7 @@ static dw_cfa_location cfa_temp;
had better be the one we think we're using for this purpose.
Except: If the register being saved is the CFA register, and the
- offset is non-zero, we are saving the CFA, so we assume we have to
+ offset is nonzero, we are saving the CFA, so we assume we have to
use DW_CFA_def_cfa_expression. If the offset is 0, we assume that
the intent is to save the value of SP from the previous frame.
@@ -1170,7 +1193,7 @@ static dw_cfa_location cfa_temp;
stores the value, which will be used to adjust the
stack pointer. cfa_temp is also used like cfa_store,
to track stores to the stack via fp or a temp reg.
-
+
Rules 1- 4: Setting a register's value to cfa.reg or an expression
with cfa.reg as the first operand changes the cfa.reg and its
cfa.offset. Rule 1 and 4 also set cfa_temp.reg and
@@ -1638,7 +1661,7 @@ dwarf2out_frame_debug (insn)
if (! RTX_FRAME_RELATED_P (insn))
{
if (!ACCUMULATE_OUTGOING_ARGS)
- dwarf2out_stack_adjust (insn);
+ dwarf2out_stack_adjust (insn);
return;
}
@@ -1789,24 +1812,30 @@ output_call_frame_info (for_eh)
dw_fde_ref fde;
dw_cfi_ref cfi;
char l1[20], l2[20], section_start_label[20];
- int any_lsda_needed = 0;
+ bool any_lsda_needed = false;
char augmentation[6];
int augmentation_size;
int fde_encoding = DW_EH_PE_absptr;
int per_encoding = DW_EH_PE_absptr;
int lsda_encoding = DW_EH_PE_absptr;
- /* If we don't have any functions we'll want to unwind out of, don't emit any
- EH unwind information. */
+ /* Don't emit a CIE if there won't be any FDEs. */
+ if (fde_table_in_use == 0)
+ return;
+
+ /* If we don't have any functions we'll want to unwind out of, don't
+ emit any EH unwind information. Note that if exceptions aren't
+ enabled, we won't have collected nothrow information, and if we
+ asked for asynchronous tables, we always want this info. */
if (for_eh)
{
- int any_eh_needed = flag_asynchronous_unwind_tables;
+ bool any_eh_needed = !flag_exceptions || flag_asynchronous_unwind_tables;
for (i = 0; i < fde_table_in_use; i++)
if (fde_table[i].uses_eh_lsda)
- any_eh_needed = any_lsda_needed = 1;
+ any_eh_needed = any_lsda_needed = true;
else if (! fde_table[i].nothrow)
- any_eh_needed = 1;
+ any_eh_needed = true;
if (! any_eh_needed)
return;
@@ -1878,7 +1907,7 @@ output_call_frame_info (for_eh)
if (p > augmentation + 1)
{
augmentation[0] = 'z';
- *p = '\0';
+ *p = '\0';
}
/* Ug. Some platforms can't do unaligned dynamic relocations at all. */
@@ -1934,7 +1963,7 @@ output_call_frame_info (for_eh)
output_cfi (cfi, NULL, for_eh);
/* Pad the CIE out to an address sized boundary. */
- ASM_OUTPUT_ALIGN (asm_out_file,
+ ASM_OUTPUT_ALIGN (asm_out_file,
floor_log2 (for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE));
ASM_OUTPUT_LABEL (asm_out_file, l2);
@@ -1944,8 +1973,9 @@ output_call_frame_info (for_eh)
fde = &fde_table[i];
/* Don't emit EH unwind info for leaf functions that don't need it. */
- if (!flag_asynchronous_unwind_tables && for_eh && fde->nothrow
- && ! fde->uses_eh_lsda)
+ if (for_eh && !flag_asynchronous_unwind_tables && flag_exceptions
+ && (fde->nothrow || fde->all_throwers_are_sibcalls)
+ && !fde->uses_eh_lsda)
continue;
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, FDE_LABEL, for_eh + i * 2);
@@ -1967,15 +1997,15 @@ output_call_frame_info (for_eh)
gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin),
"FDE initial location");
dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
- fde->dw_fde_end, fde->dw_fde_begin,
+ fde->dw_fde_end, fde->dw_fde_begin,
"FDE address range");
}
else
{
dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin,
"FDE initial location");
- dw2_asm_output_delta (DWARF2_ADDR_SIZE,
- fde->dw_fde_end, fde->dw_fde_begin,
+ dw2_asm_output_delta (DWARF2_ADDR_SIZE,
+ fde->dw_fde_end, fde->dw_fde_begin,
"FDE address range");
}
@@ -2028,15 +2058,13 @@ output_call_frame_info (for_eh)
output_cfi (cfi, fde, for_eh);
/* Pad the FDE out to an address sized boundary. */
- ASM_OUTPUT_ALIGN (asm_out_file,
+ ASM_OUTPUT_ALIGN (asm_out_file,
floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE)));
ASM_OUTPUT_LABEL (asm_out_file, l2);
}
-#ifndef EH_FRAME_SECTION_NAME
- if (for_eh)
+ if (for_eh && targetm.terminate_dw2_eh_frame_info)
dw2_asm_output_data (4, 0, "End of Table");
-#endif
#ifdef MIPS_DEBUGGING_INFO
/* Work around Irix 6 assembler bug whereby labels at the end of a section
get a value of 0. Putting .align 0 after the label fixes it. */
@@ -2073,12 +2101,11 @@ dwarf2out_begin_prologue (line, file)
return;
#endif
- current_funcdef_number++;
function_section (current_function_decl);
ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
- current_funcdef_number);
+ current_function_funcdef_no);
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, FUNC_BEGIN_LABEL,
- current_funcdef_number);
+ current_function_funcdef_no);
current_function_func_begin_label = get_identifier (label);
#ifdef IA64_UNWIND_INFO
@@ -2105,9 +2132,10 @@ dwarf2out_begin_prologue (line, file)
fde->dw_fde_current_label = NULL;
fde->dw_fde_end = NULL;
fde->dw_fde_cfi = NULL;
- fde->funcdef_number = current_funcdef_number;
+ fde->funcdef_number = current_function_funcdef_no;
fde->nothrow = current_function_nothrow;
fde->uses_eh_lsda = cfun->uses_eh_lsda;
+ fde->all_throwers_are_sibcalls = cfun->all_throwers_are_sibcalls;
args_size = old_args_size = 0;
@@ -2124,14 +2152,17 @@ dwarf2out_begin_prologue (line, file)
been generated. */
void
-dwarf2out_end_epilogue ()
+dwarf2out_end_epilogue (line, file)
+ unsigned int line ATTRIBUTE_UNUSED;
+ const char *file ATTRIBUTE_UNUSED;
{
dw_fde_ref fde;
char label[MAX_ARTIFICIAL_LABEL_BYTES];
/* Output a label to mark the endpoint of the code generated for this
function. */
- ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, current_funcdef_number);
+ ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
+ current_function_funcdef_no);
ASM_OUTPUT_LABEL (asm_out_file, label);
fde = &fde_table[fde_table_in_use - 1];
fde->dw_fde_end = xstrdup (label);
@@ -2169,6 +2200,11 @@ dwarf2out_frame_finish ()
/* And now, the subset of the debugging information support code necessary
for emitting location expressions. */
+/* We need some way to distinguish DW_OP_addr with a direct symbol
+ relocation from DW_OP_addr with a dtp-relative symbol relocation. */
+#define INTERNAL_DW_OP_tls_addr (0x100 + DW_OP_addr)
+
+
typedef struct dw_val_struct *dw_val_ref;
typedef struct die_struct *dw_die_ref;
typedef struct dw_loc_descr_struct *dw_loc_descr_ref;
@@ -2294,6 +2330,7 @@ dwarf_stack_op_name (op)
switch (op)
{
case DW_OP_addr:
+ case INTERNAL_DW_OP_tls_addr:
return "DW_OP_addr";
case DW_OP_deref:
return "DW_OP_deref";
@@ -2583,6 +2620,16 @@ dwarf_stack_op_name (op)
return "DW_OP_xderef_size";
case DW_OP_nop:
return "DW_OP_nop";
+ case DW_OP_push_object_address:
+ return "DW_OP_push_object_address";
+ case DW_OP_call2:
+ return "DW_OP_call2";
+ case DW_OP_call4:
+ return "DW_OP_call4";
+ case DW_OP_call_ref:
+ return "DW_OP_call_ref";
+ case DW_OP_GNU_push_tls_address:
+ return "DW_OP_GNU_push_tls_address";
default:
return "OP_<unknown>";
}
@@ -2640,6 +2687,7 @@ size_of_loc_descr (loc)
switch (loc->dw_loc_opc)
{
case DW_OP_addr:
+ case INTERNAL_DW_OP_tls_addr:
size += DWARF2_ADDR_SIZE;
break;
case DW_OP_const1u:
@@ -2725,6 +2773,15 @@ size_of_loc_descr (loc)
case DW_OP_xderef_size:
size += 1;
break;
+ case DW_OP_call2:
+ size += 2;
+ break;
+ case DW_OP_call4:
+ size += 4;
+ break;
+ case DW_OP_call_ref:
+ size += DWARF2_ADDR_SIZE;
+ break;
default:
break;
}
@@ -2874,6 +2931,17 @@ output_loc_operands (loc)
case DW_OP_xderef_size:
dw2_asm_output_data (1, val1->v.val_int, NULL);
break;
+
+ case INTERNAL_DW_OP_tls_addr:
+#ifdef ASM_OUTPUT_DWARF_DTPREL
+ ASM_OUTPUT_DWARF_DTPREL (asm_out_file, DWARF2_ADDR_SIZE,
+ val1->v.val_addr);
+ fputc ('\n', asm_out_file);
+#else
+ abort ();
+#endif
+ break;
+
default:
/* Other codes have no operands. */
break;
@@ -3085,7 +3153,7 @@ static void dwarf2out_abstract_function PARAMS ((tree));
/* The debug hooks structure. */
-struct gcc_debug_hooks dwarf2_debug_hooks =
+const struct gcc_debug_hooks dwarf2_debug_hooks =
{
dwarf2out_init,
dwarf2out_finish,
@@ -3098,7 +3166,7 @@ struct gcc_debug_hooks dwarf2_debug_hooks =
dwarf2out_ignore_block,
dwarf2out_source_line,
dwarf2out_begin_prologue,
- debug_nothing_int, /* end_prologue */
+ debug_nothing_int_charstar, /* end_prologue */
dwarf2out_end_epilogue,
debug_nothing_tree, /* begin_function */
debug_nothing_int, /* end_function */
@@ -3212,7 +3280,7 @@ limbo_die_node;
#define ASM_COMMENT_START ";#"
#endif
-/* Define a macro which returns non-zero for a TYPE_DECL which was
+/* Define a macro which returns nonzero for a TYPE_DECL which was
implicitly generated for a tagged type.
Note that unlike the gcc front end (which generates a NULL named
@@ -3236,14 +3304,9 @@ limbo_die_node;
/* Information concerning the compilation unit's programming
language, and compiler version. */
-extern int flag_traditional;
-
/* Fixed size portion of the DWARF compilation unit header. */
#define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3)
-/* Fixed size portion of debugging line information prolog. */
-#define DWARF_LINE_PROLOG_HEADER_SIZE 5
-
/* Fixed size portion of public names info. */
#define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2)
@@ -3290,6 +3353,10 @@ static unsigned long next_die_offset;
/* Record the root of the DIE's built for the current compilation unit. */
static dw_die_ref comp_unit_die;
+/* We need special handling in dwarf2out_start_source_file if it is
+ first one. */
+static int is_main_source;
+
/* A list of DIEs with a NULL parent waiting to be relocated. */
static limbo_die_node *limbo_die_list = 0;
@@ -3328,13 +3395,6 @@ static unsigned decl_die_table_in_use;
decl_die_table. */
#define DECL_DIE_TABLE_INCREMENT 256
-/* A pointer to the base of a table of references to declaration
- scopes. This table is a display which tracks the nesting
- of declaration scopes at the current scope and containing
- scopes. This table is used to find the proper place to
- define type declaration DIE's. */
-varray_type decl_scope_table;
-
/* A pointer to the base of a list of references to DIE's that
are uniquely identified by their tag, presence/absence of
children DIE's, and list of attribute/value pairs. */
@@ -3417,21 +3477,12 @@ static unsigned ranges_table_in_use;
/* Whether we have location lists that need outputting */
static unsigned have_location_lists;
-/* A pointer to the base of a list of incomplete types which might be
- completed at some later time. incomplete_types_list needs to be a VARRAY
- because we want to tell the garbage collector about it. */
-varray_type incomplete_types;
-
/* Record whether the function being analyzed contains inlined functions. */
static int current_function_has_inlines;
#if 0 && defined (MIPS_DEBUGGING_INFO)
static int comp_unit_has_inlines;
#endif
-/* Array of RTXes referenced by the debugging information, which therefore
- must be kept around forever. This is a GC root. */
-static varray_type used_rtx_varray;
-
/* Forward declarations for functions defined in this file. */
static int is_pseudo_reg PARAMS ((rtx));
@@ -3542,15 +3593,29 @@ static dw_die_ref pop_compile_unit PARAMS ((dw_die_ref));
static void loc_checksum PARAMS ((dw_loc_descr_ref,
struct md5_ctx *));
static void attr_checksum PARAMS ((dw_attr_ref,
- struct md5_ctx *));
+ struct md5_ctx *,
+ int *));
static void die_checksum PARAMS ((dw_die_ref,
- struct md5_ctx *));
+ struct md5_ctx *,
+ int *));
+static int same_loc_p PARAMS ((dw_loc_descr_ref,
+ dw_loc_descr_ref, int *));
+static int same_dw_val_p PARAMS ((dw_val_node *, dw_val_node *,
+ int *));
+static int same_attr_p PARAMS ((dw_attr_ref, dw_attr_ref, int *));
+static int same_die_p PARAMS ((dw_die_ref, dw_die_ref, int *));
+static int same_die_p_wrap PARAMS ((dw_die_ref, dw_die_ref));
static void compute_section_prefix PARAMS ((dw_die_ref));
static int is_type_die PARAMS ((dw_die_ref));
static int is_comdat_die PARAMS ((dw_die_ref));
static int is_symbol_die PARAMS ((dw_die_ref));
static void assign_symbol_names PARAMS ((dw_die_ref));
static void break_out_includes PARAMS ((dw_die_ref));
+static hashval_t htab_cu_hash PARAMS ((const void *));
+static int htab_cu_eq PARAMS ((const void *, const void *));
+static void htab_cu_del PARAMS ((void *));
+static int check_duplicate_cu PARAMS ((dw_die_ref, htab_t, unsigned *));
+static void record_comdat_symbol_number PARAMS ((dw_die_ref, htab_t, unsigned));
static void add_sibling_attributes PARAMS ((dw_die_ref));
static void build_abbrev_table PARAMS ((dw_die_ref));
static void output_location_lists PARAMS ((dw_die_ref));
@@ -3559,6 +3624,7 @@ static unsigned long size_of_die PARAMS ((dw_die_ref));
static void calc_die_sizes PARAMS ((dw_die_ref));
static void mark_dies PARAMS ((dw_die_ref));
static void unmark_dies PARAMS ((dw_die_ref));
+static void unmark_all_dies PARAMS ((dw_die_ref));
static unsigned long size_of_pubnames PARAMS ((void));
static unsigned long size_of_aranges PARAMS ((void));
static enum dwarf_form value_format PARAMS ((dw_attr_ref));
@@ -3567,7 +3633,7 @@ static void output_abbrev_section PARAMS ((void));
static void output_die_symbol PARAMS ((dw_die_ref));
static void output_die PARAMS ((dw_die_ref));
static void output_compilation_unit_header PARAMS ((void));
-static void output_comp_unit PARAMS ((dw_die_ref));
+static void output_comp_unit PARAMS ((dw_die_ref, int));
static const char *dwarf2_name PARAMS ((tree, int));
static void add_pubname PARAMS ((tree, dw_die_ref));
static void output_pubnames PARAMS ((void));
@@ -3594,11 +3660,12 @@ static dw_loc_descr_ref loc_descriptor_from_tree PARAMS ((tree, int));
static HOST_WIDE_INT ceiling PARAMS ((HOST_WIDE_INT, unsigned int));
static tree field_type PARAMS ((tree));
static unsigned int simple_type_align_in_bits PARAMS ((tree));
-static unsigned int simple_field_decl_align_in_bits PARAMS ((tree));
+static unsigned int simple_decl_align_in_bits PARAMS ((tree));
static unsigned HOST_WIDE_INT simple_type_size_in_bits PARAMS ((tree));
static HOST_WIDE_INT field_byte_offset PARAMS ((tree));
static void add_AT_location_description PARAMS ((dw_die_ref,
- enum dwarf_attribute, rtx));
+ enum dwarf_attribute,
+ dw_loc_descr_ref));
static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree));
static void add_const_value_attribute PARAMS ((dw_die_ref, rtx));
static rtx rtl_for_decl_location PARAMS ((tree));
@@ -3666,7 +3733,7 @@ static void retry_incomplete_types PARAMS ((void));
static void gen_type_die_for_member PARAMS ((tree, tree, dw_die_ref));
static void splice_child_die PARAMS ((dw_die_ref, dw_die_ref));
static int file_info_cmp PARAMS ((const void *, const void *));
-static dw_loc_list_ref new_loc_list PARAMS ((dw_loc_descr_ref,
+static dw_loc_list_ref new_loc_list PARAMS ((dw_loc_descr_ref,
const char *, const char *,
const char *, unsigned));
static void add_loc_descr_to_loc_list PARAMS ((dw_loc_list_ref *,
@@ -3761,24 +3828,12 @@ static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
#ifndef TEXT_END_LABEL
#define TEXT_END_LABEL "Letext"
#endif
-#ifndef DATA_END_LABEL
-#define DATA_END_LABEL "Ledata"
-#endif
-#ifndef BSS_END_LABEL
-#define BSS_END_LABEL "Lebss"
-#endif
#ifndef BLOCK_BEGIN_LABEL
#define BLOCK_BEGIN_LABEL "LBB"
#endif
#ifndef BLOCK_END_LABEL
#define BLOCK_END_LABEL "LBE"
#endif
-#ifndef BODY_BEGIN_LABEL
-#define BODY_BEGIN_LABEL "Lbb"
-#endif
-#ifndef BODY_END_LABEL
-#define BODY_END_LABEL "Lbe"
-#endif
#ifndef LINE_CODE_LABEL
#define LINE_CODE_LABEL "LM"
#endif
@@ -3830,7 +3885,7 @@ type_main_variant (type)
return type;
}
-/* Return non-zero if the given type node represents a tagged type. */
+/* Return nonzero if the given type node represents a tagged type. */
static inline int
is_tagged_type (type)
@@ -4489,7 +4544,7 @@ add_AT_string (die, attr_kind, str)
{
dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
struct indirect_string_node *node;
-
+
if (! debug_str_hash)
{
debug_str_hash = ht_create (10);
@@ -4900,7 +4955,7 @@ is_cxx ()
{
return (get_AT_unsigned (comp_unit_die, DW_AT_language)
== DW_LANG_C_plus_plus);
-}
+}
static inline int
is_fortran ()
@@ -5099,7 +5154,7 @@ static inline dw_die_ref
lookup_type_die (type)
tree type;
{
- return (dw_die_ref) TYPE_SYMTAB_POINTER (type);
+ return TYPE_SYMTAB_DIE (type);
}
/* Equate a DIE to a given type specifier. */
@@ -5109,7 +5164,7 @@ equate_type_number_to_die (type, type_die)
tree type;
dw_die_ref type_die;
{
- TYPE_SYMTAB_POINTER (type) = (char *) type_die;
+ TYPE_SYMTAB_DIE (type) = type_die;
}
/* Return the DIE associated with a given declaration. */
@@ -5404,9 +5459,10 @@ loc_checksum (loc, ctx)
/* Calculate the checksum of an attribute. */
static void
-attr_checksum (at, ctx)
+attr_checksum (at, ctx, mark)
dw_attr_ref at;
struct md5_ctx *ctx;
+ int *mark;
{
dw_loc_descr_ref loc;
rtx r;
@@ -5464,9 +5520,8 @@ attr_checksum (at, ctx)
break;
case dw_val_class_die_ref:
- if (AT_ref (at)->die_offset)
- CHECKSUM (AT_ref (at)->die_offset);
- /* FIXME else use target die name or something. */
+ die_checksum (AT_ref (at), ctx, mark);
+ break;
case dw_val_class_fde_ref:
case dw_val_class_lbl_id:
@@ -5481,25 +5536,195 @@ attr_checksum (at, ctx)
/* Calculate the checksum of a DIE. */
static void
-die_checksum (die, ctx)
+die_checksum (die, ctx, mark)
dw_die_ref die;
struct md5_ctx *ctx;
+ int *mark;
{
dw_die_ref c;
dw_attr_ref a;
+ /* To avoid infinite recursion. */
+ if (die->die_mark)
+ {
+ CHECKSUM (die->die_mark);
+ return;
+ }
+ die->die_mark = ++(*mark);
+
CHECKSUM (die->die_tag);
for (a = die->die_attr; a; a = a->dw_attr_next)
- attr_checksum (a, ctx);
+ attr_checksum (a, ctx, mark);
for (c = die->die_child; c; c = c->die_sib)
- die_checksum (c, ctx);
+ die_checksum (c, ctx, mark);
}
#undef CHECKSUM
#undef CHECKSUM_STRING
+/* Do the location expressions look same? */
+static inline int
+same_loc_p (loc1, loc2, mark)
+ dw_loc_descr_ref loc1;
+ dw_loc_descr_ref loc2;
+ int *mark;
+{
+ return loc1->dw_loc_opc == loc2->dw_loc_opc
+ && same_dw_val_p (&loc1->dw_loc_oprnd1, &loc2->dw_loc_oprnd1, mark)
+ && same_dw_val_p (&loc1->dw_loc_oprnd2, &loc2->dw_loc_oprnd2, mark);
+}
+
+/* Do the values look the same? */
+static int
+same_dw_val_p (v1, v2, mark)
+ dw_val_node *v1;
+ dw_val_node *v2;
+ int *mark;
+{
+ dw_loc_descr_ref loc1, loc2;
+ rtx r1, r2;
+ unsigned i;
+
+ if (v1->val_class != v2->val_class)
+ return 0;
+
+ switch (v1->val_class)
+ {
+ case dw_val_class_const:
+ return v1->v.val_int == v2->v.val_int;
+ case dw_val_class_unsigned_const:
+ return v1->v.val_unsigned == v2->v.val_unsigned;
+ case dw_val_class_long_long:
+ return v1->v.val_long_long.hi == v2->v.val_long_long.hi
+ && v1->v.val_long_long.low == v2->v.val_long_long.low;
+ case dw_val_class_float:
+ if (v1->v.val_float.length != v2->v.val_float.length)
+ return 0;
+ for (i = 0; i < v1->v.val_float.length; i++)
+ if (v1->v.val_float.array[i] != v2->v.val_float.array[i])
+ return 0;
+ return 1;
+ case dw_val_class_flag:
+ return v1->v.val_flag == v2->v.val_flag;
+ case dw_val_class_str:
+ return !strcmp((const char *) HT_STR (&v1->v.val_str->id),
+ (const char *) HT_STR (&v2->v.val_str->id));
+
+ case dw_val_class_addr:
+ r1 = v1->v.val_addr;
+ r2 = v2->v.val_addr;
+ if (GET_CODE (r1) != GET_CODE (r2))
+ return 0;
+ switch (GET_CODE (r1))
+ {
+ case SYMBOL_REF:
+ return !strcmp (XSTR (r1, 0), XSTR (r2, 0));
+
+ default:
+ abort ();
+ }
+
+ case dw_val_class_offset:
+ return v1->v.val_offset == v2->v.val_offset;
+
+ case dw_val_class_loc:
+ for (loc1 = v1->v.val_loc, loc2 = v2->v.val_loc;
+ loc1 && loc2;
+ loc1 = loc1->dw_loc_next, loc2 = loc2->dw_loc_next)
+ if (!same_loc_p (loc1, loc2, mark))
+ return 0;
+ return !loc1 && !loc2;
+
+ case dw_val_class_die_ref:
+ return same_die_p (v1->v.val_die_ref.die, v2->v.val_die_ref.die, mark);
+
+ case dw_val_class_fde_ref:
+ case dw_val_class_lbl_id:
+ case dw_val_class_lbl_offset:
+ return 1;
+
+ default:
+ return 1;
+ }
+}
+
+/* Do the attributes look the same? */
+
+static int
+same_attr_p (at1, at2, mark)
+ dw_attr_ref at1;
+ dw_attr_ref at2;
+ int *mark;
+{
+ if (at1->dw_attr != at2->dw_attr)
+ return 0;
+
+ /* We don't care about differences in file numbering. */
+ if (at1->dw_attr == DW_AT_decl_file
+ /* Or that this was compiled with a different compiler snapshot; if
+ the output is the same, that's what matters. */
+ || at1->dw_attr == DW_AT_producer)
+ return 1;
+
+ return same_dw_val_p (&at1->dw_attr_val, &at2->dw_attr_val, mark);
+}
+
+/* Do the dies look the same? */
+
+static int
+same_die_p (die1, die2, mark)
+ dw_die_ref die1;
+ dw_die_ref die2;
+ int *mark;
+{
+ dw_die_ref c1, c2;
+ dw_attr_ref a1, a2;
+
+ /* To avoid infinite recursion. */
+ if (die1->die_mark)
+ return die1->die_mark == die2->die_mark;
+ die1->die_mark = die2->die_mark = ++(*mark);
+
+ if (die1->die_tag != die2->die_tag)
+ return 0;
+
+ for (a1 = die1->die_attr, a2 = die2->die_attr;
+ a1 && a2;
+ a1 = a1->dw_attr_next, a2 = a2->dw_attr_next)
+ if (!same_attr_p (a1, a2, mark))
+ return 0;
+ if (a1 || a2)
+ return 0;
+
+ for (c1 = die1->die_child, c2 = die2->die_child;
+ c1 && c2;
+ c1 = c1->die_sib, c2 = c2->die_sib)
+ if (!same_die_p (c1, c2, mark))
+ return 0;
+ if (c1 || c2)
+ return 0;
+
+ return 1;
+}
+
+/* Do the dies look the same? Wrapper around same_die_p. */
+
+static int
+same_die_p_wrap (die1, die2)
+ dw_die_ref die1;
+ dw_die_ref die2;
+{
+ int mark = 0;
+ int ret = same_die_p (die1, die2, &mark);
+
+ unmark_all_dies (die1);
+ unmark_all_dies (die2);
+
+ return ret;
+}
+
/* The prefix to attach to symbols on DIEs in the current comdat debug
info section. */
static char *comdat_symbol_id;
@@ -5514,10 +5739,11 @@ static void
compute_section_prefix (unit_die)
dw_die_ref unit_die;
{
- const char *base = lbasename (get_AT_string (unit_die, DW_AT_name));
+ const char *die_name = get_AT_string (unit_die, DW_AT_name);
+ const char *base = die_name ? lbasename (die_name) : "anonymous";
char *name = (char *) alloca (strlen (base) + 64);
char *p;
- int i;
+ int i, mark;
unsigned char checksum[16];
struct md5_ctx ctx;
@@ -5525,7 +5751,9 @@ compute_section_prefix (unit_die)
the name filename of the unit. */
md5_init_ctx (&ctx);
- die_checksum (unit_die, &ctx);
+ mark = 0;
+ die_checksum (unit_die, &ctx, &mark);
+ unmark_all_dies (unit_die);
md5_finish_ctx (&ctx, checksum);
sprintf (name, "%s.", base);
@@ -5567,6 +5795,7 @@ is_type_die (die)
case DW_TAG_file_type:
case DW_TAG_packed_type:
case DW_TAG_volatile_type:
+ case DW_TAG_typedef:
return 1;
default:
return 0;
@@ -5611,7 +5840,7 @@ is_symbol_die (c)
dw_die_ref c;
{
return (is_type_die (c)
- || (get_AT (c, DW_AT_declaration)
+ || (get_AT (c, DW_AT_declaration)
&& !get_AT (c, DW_AT_specification)));
}
@@ -5652,6 +5881,104 @@ assign_symbol_names (die)
assign_symbol_names (c);
}
+struct cu_hash_table_entry
+{
+ dw_die_ref cu;
+ unsigned min_comdat_num, max_comdat_num;
+ struct cu_hash_table_entry *next;
+};
+
+/* Routines to manipulate hash table of CUs. */
+static hashval_t
+htab_cu_hash (of)
+ const void *of;
+{
+ const struct cu_hash_table_entry *entry = of;
+
+ return htab_hash_string (entry->cu->die_symbol);
+}
+
+static int
+htab_cu_eq (of1, of2)
+ const void *of1;
+ const void *of2;
+{
+ const struct cu_hash_table_entry *entry1 = of1;
+ const struct die_struct *entry2 = of2;
+
+ return !strcmp (entry1->cu->die_symbol, entry2->die_symbol);
+}
+
+static void
+htab_cu_del (what)
+ void *what;
+{
+ struct cu_hash_table_entry *next, *entry = what;
+
+ while (entry)
+ {
+ next = entry->next;
+ free (entry);
+ entry = next;
+ }
+}
+
+/* Check whether we have already seen this CU and set up SYM_NUM
+ accordingly. */
+static int
+check_duplicate_cu (cu, htable, sym_num)
+ dw_die_ref cu;
+ htab_t htable;
+ unsigned *sym_num;
+{
+ struct cu_hash_table_entry dummy;
+ struct cu_hash_table_entry **slot, *entry, *last = &dummy;
+
+ dummy.max_comdat_num = 0;
+
+ slot = (struct cu_hash_table_entry **)
+ htab_find_slot_with_hash (htable, cu, htab_hash_string (cu->die_symbol),
+ INSERT);
+ entry = *slot;
+
+ for (; entry; last = entry, entry = entry->next)
+ {
+ if (same_die_p_wrap (cu, entry->cu))
+ break;
+ }
+
+ if (entry)
+ {
+ *sym_num = entry->min_comdat_num;
+ return 1;
+ }
+
+ entry = xcalloc (1, sizeof (struct cu_hash_table_entry));
+ entry->cu = cu;
+ entry->min_comdat_num = *sym_num = last->max_comdat_num;
+ entry->next = *slot;
+ *slot = entry;
+
+ return 0;
+}
+
+/* Record SYM_NUM to record of CU in HTABLE. */
+static void
+record_comdat_symbol_number (cu, htable, sym_num)
+ dw_die_ref cu;
+ htab_t htable;
+ unsigned sym_num;
+{
+ struct cu_hash_table_entry **slot, *entry;
+
+ slot = (struct cu_hash_table_entry **)
+ htab_find_slot_with_hash (htable, cu, htab_hash_string (cu->die_symbol),
+ NO_INSERT);
+ entry = *slot;
+
+ entry->max_comdat_num = sym_num;
+}
+
/* Traverse the DIE (which is always comp_unit_die), and set up
additional compilation units for each of the include files we see
bracketed by BINCL/EINCL. */
@@ -5662,9 +5989,10 @@ break_out_includes (die)
{
dw_die_ref *ptr;
dw_die_ref unit = NULL;
- limbo_die_node *node;
+ limbo_die_node *node, **pnode;
+ htab_t cu_hash_table;
- for (ptr = &(die->die_child); *ptr; )
+ for (ptr = &(die->die_child); *ptr;)
{
dw_die_ref c = *ptr;
@@ -5703,11 +6031,27 @@ break_out_includes (die)
#endif
assign_symbol_names (die);
- for (node = limbo_die_list; node; node = node->next)
+ cu_hash_table = htab_create (10, htab_cu_hash, htab_cu_eq, htab_cu_del);
+ for (node = limbo_die_list, pnode = &limbo_die_list;
+ node;
+ node = node->next)
{
+ int is_dupl;
+
compute_section_prefix (node->die);
+ is_dupl = check_duplicate_cu (node->die, cu_hash_table,
+ &comdat_symbol_number);
assign_symbol_names (node->die);
+ if (is_dupl)
+ *pnode = node->next;
+ else
+ {
+ pnode = &node->next;
+ record_comdat_symbol_number (node->die, cu_hash_table,
+ comdat_symbol_number);
+ }
}
+ htab_delete (cu_hash_table);
}
/* Traverse the DIE and add a sibling attribute if it may have the
@@ -5746,6 +6090,7 @@ output_location_lists (die)
output_location_lists (c);
}
+
/* The format of each DIE (and its attribute value pairs) is encoded in an
abbreviation table. This routine builds the abbreviation table and assigns
a unique abbreviation id for each abbreviation entry. The children of each
@@ -5951,6 +6296,9 @@ mark_dies (die)
{
dw_die_ref c;
+ if (die->die_mark)
+ abort ();
+
die->die_mark = 1;
for (c = die->die_child; c; c = c->die_sib)
mark_dies (c);
@@ -5964,11 +6312,35 @@ unmark_dies (die)
{
dw_die_ref c;
+ if (!die->die_mark)
+ abort ();
+
die->die_mark = 0;
for (c = die->die_child; c; c = c->die_sib)
unmark_dies (c);
}
+/* Clear the marks for a die, its children and referred dies. */
+
+static void
+unmark_all_dies (die)
+ dw_die_ref die;
+{
+ dw_die_ref c;
+ dw_attr_ref a;
+
+ if (!die->die_mark)
+ return;
+ die->die_mark = 0;
+
+ for (c = die->die_child; c; c = c->die_sib)
+ unmark_all_dies (c);
+
+ for (a = die->die_attr; a; a = a->dw_attr_next)
+ if (AT_class (a) == dw_val_class_die_ref)
+ unmark_all_dies (AT_ref (a));
+}
+
/* Return the size of the .debug_pubnames table generated for the
compilation unit. */
@@ -6144,7 +6516,7 @@ output_die_symbol (die)
/* We make these global, not weak; if the target doesn't support
.linkonce, it doesn't support combining the sections, so debugging
will break. */
- ASM_GLOBALIZE_LABEL (asm_out_file, sym);
+ (*targetm.asm_out.globalize_label) (asm_out_file, sym);
ASM_OUTPUT_LABEL (asm_out_file, sym);
}
@@ -6168,7 +6540,7 @@ new_loc_list (expr, begin, end, section, gensym)
retlist->end = end;
retlist->expr = expr;
retlist->section = section;
- if (gensym)
+ if (gensym)
retlist->ll_symbol = gen_internal_sym ("LLST");
return retlist;
@@ -6185,7 +6557,7 @@ add_loc_descr_to_loc_list (list_head, descr, begin, end, section)
const char *section;
{
dw_loc_list_ref *d;
-
+
/* Find the end of the chain. */
for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
;
@@ -6216,7 +6588,7 @@ output_loc_list (list_head)
"Location list base address specifier base");
}
- for (curr = list_head; curr != NULL; curr=curr->dw_loc_next)
+ for (curr = list_head; curr != NULL; curr = curr->dw_loc_next)
{
unsigned long size;
@@ -6227,7 +6599,7 @@ output_loc_list (list_head)
"Location list end address (%s)",
list_head->ll_symbol);
size = size_of_locs (curr->expr);
-
+
/* Output the block length for this list of location operations. */
if (size > 0xffff)
abort ();
@@ -6316,7 +6688,7 @@ output_die (die)
dw2_asm_output_data (1,
2 * HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR,
- "%s", name);
+ "%s", name);
if (WORDS_BIG_ENDIAN)
{
@@ -6341,7 +6713,7 @@ output_die (die)
unsigned int i;
dw2_asm_output_data (1, a->dw_attr_val.v.val_float.length * 4,
- "%s", name);
+ "%s", name);
for (i = 0; i < a->dw_attr_val.v.val_float.length; i++)
dw2_asm_output_data (4, a->dw_attr_val.v.val_float.array[i],
@@ -6353,7 +6725,7 @@ output_die (die)
dw2_asm_output_data (1, AT_flag (a), "%s", name);
break;
- case dw_val_class_loc_list:
+ case dw_val_class_loc_list:
{
char *sym = AT_loc_list (a)->ll_symbol;
@@ -6438,10 +6810,16 @@ output_compilation_unit_header ()
/* Output the compilation unit DIE and its children. */
static void
-output_comp_unit (die)
+output_comp_unit (die, output_if_empty)
dw_die_ref die;
+ int output_if_empty;
{
const char *secname;
+ char *oldsym, *tmp;
+
+ /* Unless we are outputting main CU, we may throw away empty ones. */
+ if (!output_if_empty && die->die_child == NULL)
+ return;
/* Even if there are no children of this DIE, we must output the information
about the compilation unit. Otherwise, on an empty translation unit, we
@@ -6456,11 +6834,12 @@ output_comp_unit (die)
next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
calc_die_sizes (die);
- if (die->die_symbol)
+ oldsym = die->die_symbol;
+ if (oldsym)
{
- char *tmp = (char *) alloca (strlen (die->die_symbol) + 24);
+ tmp = (char *) alloca (strlen (oldsym) + 24);
- sprintf (tmp, ".gnu.linkonce.wi.%s", die->die_symbol);
+ sprintf (tmp, ".gnu.linkonce.wi.%s", oldsym);
secname = tmp;
die->die_symbol = NULL;
}
@@ -6474,20 +6853,23 @@ output_comp_unit (die)
/* Leave the marks on the main CU, so we can check them in
output_pubnames. */
- if (die->die_symbol)
- unmark_dies (die);
+ if (oldsym)
+ {
+ unmark_dies (die);
+ die->die_symbol = oldsym;
+ }
}
-/* The DWARF2 pubname for a nested thingy looks like "A::f". The output
- of decl_printable_name for C++ looks like "A::f(int)". Let's drop the
- argument list, and maybe the scope. */
+/* The DWARF2 pubname for a nested thingy looks like "A::f". The
+ output of lang_hooks.decl_printable_name for C++ looks like
+ "A::f(int)". Let's drop the argument list, and maybe the scope. */
static const char *
dwarf2_name (decl, scope)
tree decl;
int scope;
{
- return (*decl_printable_name) (decl, scope ? 1 : 0);
+ return (*lang_hooks.decl_printable_name) (decl, scope ? 1 : 0);
}
/* Add a new entry to .debug_pubnames if appropriate. */
@@ -6923,7 +7305,7 @@ output_file_names ()
if (total > dirs[i].length + 1)
{
/* It's worthwhile adding. */
- for (j = i; j < ndirs; j++)
+ for (j = i; j < ndirs; j++)
if (savehere[j] > 0)
{
/* Remember how much we saved for this directory so far. */
@@ -7422,7 +7804,7 @@ root_type (type)
}
}
-/* Given a pointer to an arbitrary ..._TYPE tree node, return non-zero if the
+/* Given a pointer to an arbitrary ..._TYPE tree node, return nonzero if the
given input type is a Dwarf "fundamental" type. Otherwise return null. */
static inline int
@@ -7484,10 +7866,10 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
/* See if we already have the appropriately qualified variant of
this type. */
- qualified_type
+ qualified_type
= get_qualified_type (type,
((is_const_type ? TYPE_QUAL_CONST : 0)
- | (is_volatile_type
+ | (is_volatile_type
? TYPE_QUAL_VOLATILE : 0)));
/* If we do, then we can just use its DIE, if it exists. */
@@ -7499,7 +7881,7 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
}
/* Handle C typedef types. */
- if (qualified_type && TYPE_NAME (qualified_type)
+ if (qualified_type && TYPE_NAME (qualified_type)
&& TREE_CODE (TYPE_NAME (qualified_type)) == TYPE_DECL
&& DECL_ORIGINAL_TYPE (TYPE_NAME (qualified_type)))
{
@@ -7567,7 +7949,12 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
copy was created to help us keep track of typedef names) and
that copy might have a different TYPE_UID from the original
..._TYPE node. */
- mod_type_die = lookup_type_die (type_main_variant (type));
+ if (TREE_CODE (type) != VECTOR_TYPE)
+ mod_type_die = lookup_type_die (type_main_variant (type));
+ else
+ /* Vectors have the debugging information in the type,
+ not the main variant. */
+ mod_type_die = lookup_type_die (type);
if (mod_type_die == NULL)
abort ();
}
@@ -7792,6 +8179,11 @@ mem_loc_descriptor (rtl, mode)
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
break;
+ case LO_SUM:
+ rtl = XEXP (rtl, 1);
+
+ /* ... fall through ... */
+
case LABEL_REF:
/* Some ports can transform a symbol ref into a label ref, because
the symbol ref is too far away and has to be dumped into a constant
@@ -8029,6 +8421,42 @@ loc_descriptor_from_tree (loc, addressp)
: 0);
case VAR_DECL:
+ if (DECL_THREAD_LOCAL (loc))
+ {
+ rtx rtl;
+
+#ifndef ASM_OUTPUT_DWARF_DTPREL
+ /* If this is not defined, we have no way to emit the data. */
+ return 0;
+#endif
+
+ /* The way DW_OP_GNU_push_tls_address is specified, we can only
+ look up addresses of objects in the current module. */
+ if (DECL_EXTERNAL (loc))
+ return 0;
+
+ rtl = rtl_for_decl_location (loc);
+ if (rtl == NULL_RTX)
+ return 0;
+
+ if (GET_CODE (rtl) != MEM)
+ return 0;
+ rtl = XEXP (rtl, 0);
+ if (! CONSTANT_P (rtl))
+ return 0;
+
+ ret = new_loc_descr (INTERNAL_DW_OP_tls_addr, 0, 0);
+ ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
+ ret->dw_loc_oprnd1.v.val_addr = rtl;
+
+ ret1 = new_loc_descr (DW_OP_GNU_push_tls_address, 0, 0);
+ add_loc_descr (&ret, ret1);
+
+ indirect_p = 1;
+ break;
+ }
+ /* FALLTHRU */
+
case PARM_DECL:
{
rtx rtl = rtl_for_decl_location (loc);
@@ -8121,7 +8549,7 @@ loc_descriptor_from_tree (loc, addressp)
return 0;
break;
- case TRUTH_AND_EXPR:
+ case TRUTH_AND_EXPR:
case TRUTH_ANDIF_EXPR:
case BIT_AND_EXPR:
op = DW_OP_and;
@@ -8357,28 +8785,10 @@ simple_type_align_in_bits (type)
}
static inline unsigned
-simple_field_decl_align_in_bits (field)
- tree field;
+simple_decl_align_in_bits (decl)
+ tree decl;
{
- unsigned align;
-
- if (TREE_CODE (field) == ERROR_MARK)
- return BITS_PER_WORD;
-
- align = DECL_ALIGN (field);
-
-#ifdef BIGGEST_FIELD_ALIGNMENT
- /* Some targets (i.e. i386) limit union field alignment
- to a lower boundary than alignment of variables unless
- it was overridden by attribute aligned. */
- if (! DECL_USER_ALIGN (field))
- align = MIN (align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
-#endif
-
-#ifdef ADJUST_FIELD_ALIGN
- align = ADJUST_FIELD_ALIGN (field, align);
-#endif
- return align;
+ return (TREE_CODE (decl) != ERROR_MARK) ? DECL_ALIGN (decl) : BITS_PER_WORD;
}
/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE
@@ -8452,7 +8862,7 @@ field_byte_offset (decl)
type_size_in_bits = simple_type_size_in_bits (type);
type_align_in_bits = simple_type_align_in_bits (type);
- decl_align_in_bits = simple_field_decl_align_in_bits (decl);
+ decl_align_in_bits = simple_decl_align_in_bits (decl);
/* The GCC front-end doesn't make any attempt to keep track of the starting
bit offset (relative to the start of the containing structure type) of the
@@ -8529,14 +8939,12 @@ field_byte_offset (decl)
whole parameters. Note that the location attributes for struct fields are
generated by the routine `data_member_location_attribute' below. */
-static void
-add_AT_location_description (die, attr_kind, rtl)
+static inline void
+add_AT_location_description (die, attr_kind, descr)
dw_die_ref die;
enum dwarf_attribute attr_kind;
- rtx rtl;
+ dw_loc_descr_ref descr;
{
- dw_loc_descr_ref descr = loc_descriptor (rtl);
-
if (descr != 0)
add_AT_loc (die, attr_kind, descr);
}
@@ -8660,7 +9068,7 @@ add_const_value_attribute (die, rtl)
out, and the CONST_INT rtx is assigned VOIDmode. */
{
HOST_WIDE_INT val = INTVAL (rtl);
-
+
/* ??? We really should be using HOST_WIDE_INT throughout. */
if (val < 0 && (long) val == val)
add_AT_int (die, DW_AT_const_value, (long) val);
@@ -8689,7 +9097,7 @@ add_const_value_attribute (die, rtl)
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
{
unsigned length = GET_MODE_SIZE (mode) / 4;
- long *array = (long *) xmalloc (sizeof (long) * length);
+ long *array = (long *) xmalloc (sizeof (long) * length);
REAL_VALUE_TYPE rv;
REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
@@ -8841,13 +9249,17 @@ rtl_for_decl_location (decl)
rtl = DECL_RTL_IF_SET (decl);
/* When generating abstract instances, ignore everything except
- constants and symbols living in memory. */
+ constants, symbols living in memory, and symbols living in
+ fixed registers. */
if (! reload_completed)
{
if (rtl
&& (CONSTANT_P (rtl)
|| (GET_CODE (rtl) == MEM
- && CONSTANT_P (XEXP (rtl, 0)))))
+ && CONSTANT_P (XEXP (rtl, 0)))
+ || (GET_CODE (rtl) == REG
+ && TREE_CODE (decl) == VAR_DECL
+ && TREE_STATIC (decl))))
{
#ifdef ASM_SIMPLIFY_DWARF_ADDR
rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl);
@@ -8961,6 +9373,13 @@ rtl_for_decl_location (decl)
if (rtl)
rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl);
#endif
+
+ /* If we don't look past the constant pool, we risk emitting a
+ reference to a constant pool entry that isn't referenced from
+ code, and thus is not emitted. */
+ if (rtl)
+ rtl = avoid_constant_pool_reference (rtl);
+
return rtl;
}
@@ -8981,6 +9400,7 @@ add_location_or_const_value_attribute (die, decl)
tree decl;
{
rtx rtl;
+ dw_loc_descr_ref descr;
if (TREE_CODE (decl) == ERROR_MARK)
return;
@@ -8991,16 +9411,11 @@ add_location_or_const_value_attribute (die, decl)
if (rtl == NULL_RTX)
return;
- /* If we don't look past the constant pool, we risk emitting a
- reference to a constant pool entry that isn't referenced from
- code, and thus is not emitted. */
- rtl = avoid_constant_pool_reference (rtl);
-
switch (GET_CODE (rtl))
{
case ADDRESSOF:
- /* The address of a variable that was optimized away; don't emit
- anything. */
+ /* The address of a variable that was optimized away;
+ don't emit anything. */
break;
case CONST_INT:
@@ -9015,12 +9430,24 @@ add_location_or_const_value_attribute (die, decl)
break;
case MEM:
- case REG:
- case SUBREG:
- case CONCAT:
- add_AT_location_description (die, DW_AT_location, rtl);
+ if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
+ {
+ /* Need loc_descriptor_from_tree since that's where we know
+ how to handle TLS variables. Want the object's address
+ since the top-level DW_AT_location assumes such. See
+ the confusion in loc_descriptor for reference. */
+ descr = loc_descriptor_from_tree (decl, 1);
+ }
+ else
+ {
+ case REG:
+ case SUBREG:
+ case CONCAT:
+ descr = loc_descriptor (rtl);
+ }
+ add_AT_location_description (die, DW_AT_location, descr);
break;
-
+
default:
abort ();
}
@@ -9152,7 +9579,8 @@ add_bound_info (subrange_die, bound_attr, bound)
add_AT_flag (decl_die, DW_AT_artificial, 1);
add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
- add_AT_location_description (decl_die, DW_AT_location, loc);
+ add_AT_location_description (decl_die, DW_AT_location,
+ loc_descriptor (loc));
add_AT_die_ref (subrange_die, bound_attr, decl_die);
}
@@ -10060,7 +10488,7 @@ gen_formal_types_die (function_or_method_type, context_die)
}
else
arg = NULL_TREE;
-
+
first_parm_type = TYPE_ARG_TYPES (function_or_method_type);
/* Make our first pass over the list of formal parameter types and output a
@@ -10144,7 +10572,7 @@ dwarf2out_abstract_function (decl)
/* Make sure we have the actual abstract inline, not a clone. */
decl = DECL_ORIGIN (decl);
- old_die = lookup_decl_die (decl);
+ old_die = lookup_decl_die (decl);
if (old_die && get_AT_unsigned (old_die, DW_AT_inline))
/* We've already generated the abstract instance. */
return;
@@ -10158,7 +10586,7 @@ dwarf2out_abstract_function (decl)
gen_type_die_for_member
(context, decl, decl_function_context (decl) ? NULL : comp_unit_die);
}
-
+
/* Pretend we've just finished compiling this function. */
save_fn = current_function_decl;
current_function_decl = decl;
@@ -10331,10 +10759,10 @@ gen_subprogram_die (decl, context_die)
equate_decl_number_to_die (decl, subr_die);
ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL,
- current_funcdef_number);
+ current_function_funcdef_no);
add_AT_lbl_id (subr_die, DW_AT_low_pc, label_id);
ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
- current_funcdef_number);
+ current_function_funcdef_no);
add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id);
add_pubname (decl, subr_die);
@@ -10357,7 +10785,7 @@ gen_subprogram_die (decl, context_die)
is not part of the state saved/restored for inline functions. */
if (current_function_needs_context)
add_AT_location_description (subr_die, DW_AT_static_link,
- lookup_static_chain (decl));
+ loc_descriptor (lookup_static_chain (decl)));
#endif
}
@@ -10477,7 +10905,7 @@ gen_variable_die (decl, context_die)
??? Duplicated blocks have been rewritten to use .debug_ranges. */
else if (old_die && TREE_STATIC (decl)
- && get_AT_flag (old_die, DW_AT_declaration) == 1)
+ && get_AT_flag (old_die, DW_AT_declaration) == 1)
{
/* This is a definition of a C++ class level static. */
add_AT_die_ref (var_die, DW_AT_specification, old_die);
@@ -10665,8 +11093,12 @@ gen_field_die (decl, context_die)
tree decl;
dw_die_ref context_die;
{
- dw_die_ref decl_die = new_die (DW_TAG_member, context_die, decl);
+ dw_die_ref decl_die;
+ if (TREE_TYPE (decl) == error_mark_node)
+ return;
+
+ decl_die = new_die (DW_TAG_member, context_die, decl);
add_name_and_src_coords_attributes (decl_die, decl);
add_type_attribute (decl_die, member_declared_type (decl),
TREE_READONLY (decl), TREE_THIS_VOLATILE (decl),
@@ -10789,8 +11221,6 @@ gen_compile_unit_die (filename)
language = DW_LANG_Pascal83;
else if (strcmp (language_string, "GNU Java") == 0)
language = DW_LANG_Java;
- else if (flag_traditional)
- language = DW_LANG_C;
else
language = DW_LANG_C89;
@@ -11058,22 +11488,32 @@ gen_type_die (type, context_die)
if (type == NULL_TREE || type == error_mark_node)
return;
- /* We are going to output a DIE to represent the unqualified version of
- this type (i.e. without any const or volatile qualifiers) so get the
- main variant (i.e. the unqualified version) of this type now. */
- type = type_main_variant (type);
-
- if (TREE_ASM_WRITTEN (type))
- return;
-
if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
{
+ if (TREE_ASM_WRITTEN (type))
+ return;
+
+ /* Prevent broken recursion; we can't hand off to the same type. */
+ if (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) == type)
+ abort ();
+
TREE_ASM_WRITTEN (type) = 1;
gen_decl_die (TYPE_NAME (type), context_die);
return;
}
+ /* We are going to output a DIE to represent the unqualified version
+ of this type (i.e. without any const or volatile qualifiers) so
+ get the main variant (i.e. the unqualified version) of this type
+ now. (Vectors are special because the debugging info is in the
+ cloned type itself). */
+ if (TREE_CODE (type) != VECTOR_TYPE)
+ type = type_main_variant (type);
+
+ if (TREE_ASM_WRITTEN (type))
+ return;
+
switch (TREE_CODE (type))
{
case ERROR_MARK:
@@ -11377,6 +11817,10 @@ decls_for_scope (stmt, context_die, depth)
gen_decl_die (decl, context_die);
}
+ /* If we're at -g1, we're not interested in subblocks. */
+ if (debug_info_level <= DINFO_LEVEL_TERSE)
+ return;
+
/* Output the DIEs to represent all sub-blocks (and the items declared
therein) of this block. */
for (subblocks = BLOCK_SUBBLOCKS (stmt);
@@ -11558,7 +12002,7 @@ mark_limbo_die_list (ptr)
void *ptr ATTRIBUTE_UNUSED;
{
limbo_die_node *node;
- for (node = limbo_die_list; node ; node = node->next)
+ for (node = limbo_die_list; node; node = node->next)
ggc_mark_tree (node->created_for);
}
@@ -11654,7 +12098,9 @@ dwarf2out_decl (decl)
/* If we're a nested function, initially use a parent of NULL; if we're
a plain function, this will be fixed up in decls_for_scope. If
we're a method, it will be ignored, since we already have a DIE. */
- if (decl_function_context (decl))
+ if (decl_function_context (decl)
+ /* But if we're in terse mode, we don't care about scope. */
+ && debug_info_level > DINFO_LEVEL_TERSE)
context_die = NULL;
break;
@@ -11811,7 +12257,11 @@ lookup_filename (file_name)
file_table.last_lookup_index = i;
if (DWARF2_ASM_LINE_DEBUG_INFO)
- fprintf (asm_out_file, "\t.file %u \"%s\"\n", i, file_name);
+ {
+ fprintf (asm_out_file, "\t.file %u ", i);
+ output_quoted_string (asm_out_file, file_name);
+ fputc ('\n', asm_out_file);
+ }
return i;
}
@@ -11883,7 +12333,7 @@ dwarf2out_source_line (line, filename)
= &separate_line_info_table[separate_line_info_table_in_use++];
line_info->dw_file_num = lookup_filename (filename);
line_info->dw_line_num = line;
- line_info->function = current_funcdef_number;
+ line_info->function = current_function_funcdef_no;
}
else
{
@@ -11918,13 +12368,17 @@ dwarf2out_start_source_file (lineno, filename)
unsigned int lineno;
const char *filename;
{
- if (flag_eliminate_dwarf2_dups)
+ if (flag_eliminate_dwarf2_dups && !is_main_source)
{
/* Record the beginning of the file for break_out_includes. */
- dw_die_ref bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL);
+ dw_die_ref bincl_die;
+
+ bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL);
add_AT_string (bincl_die, DW_AT_name, filename);
}
+ is_main_source = 0;
+
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
{
named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
@@ -12013,7 +12467,6 @@ dwarf2out_init (main_input_filename)
/* Allocate the initial hunk of the decl_scope_table. */
VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table");
- ggc_add_tree_varray_root (&decl_scope_table, 1);
/* Allocate the initial hunk of the abbrev_die_table. */
abbrev_die_table
@@ -12038,12 +12491,11 @@ dwarf2out_init (main_input_filename)
taken as being relative to the directory from which the compiler was
invoked when the given (base) source file was compiled. */
comp_unit_die = gen_compile_unit_die (main_input_filename);
+ is_main_source = 1;
VARRAY_TREE_INIT (incomplete_types, 64, "incomplete_types");
- ggc_add_tree_varray_root (&incomplete_types, 1);
VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray");
- ggc_add_rtx_varray_root (&used_rtx_varray, 1);
ggc_add_root (&limbo_die_list, 1, 1, mark_limbo_die_list);
@@ -12164,7 +12616,7 @@ dwarf2out_finish (input_filename)
add_child_die (comp_unit_die, die);
else if (node->created_for
&& ((DECL_P (node->created_for)
- && (context = DECL_CONTEXT (node->created_for)))
+ && (context = DECL_CONTEXT (node->created_for)))
|| (TYPE_P (node->created_for)
&& (context = TYPE_CONTEXT (node->created_for))))
&& TREE_CODE (context) == FUNCTION_DECL)
@@ -12257,9 +12709,9 @@ dwarf2out_finish (input_filename)
/* Output all of the compilation units. We put the main one last so that
the offsets are available to output_pubnames. */
for (node = limbo_die_list; node; node = node->next)
- output_comp_unit (node->die);
+ output_comp_unit (node->die, 0);
- output_comp_unit (comp_unit_die);
+ output_comp_unit (comp_unit_die, 0);
/* Output the abbreviation table. */
named_section_flags (DEBUG_ABBREV_SECTION, SECTION_DEBUG);
@@ -12290,9 +12742,10 @@ dwarf2out_finish (input_filename)
/* Have to end the primary source file. */
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
- {
+ {
named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
dw2_asm_output_data (1, DW_MACINFO_end_file, "End file");
+ dw2_asm_output_data (1, 0, "End compilation unit");
}
/* If we emitted any DW_FORM_strp form attribute, output the string
@@ -12300,4 +12753,11 @@ dwarf2out_finish (input_filename)
if (debug_str_hash)
ht_forall (debug_str_hash, output_indirect_string, NULL);
}
-#endif /* DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO */
+#else
+
+/* This should never be used, but its address is needed for comparisons. */
+const struct gcc_debug_hooks dwarf2_debug_hooks;
+
+#endif /* DWARF2_DEBUGGING_INFO */
+
+#include "gt-dwarf2out.h"
diff --git a/contrib/gcc/dwarf2out.h b/contrib/gcc/dwarf2out.h
index 5c6200c..63cedea 100644
--- a/contrib/gcc/dwarf2out.h
+++ b/contrib/gcc/dwarf2out.h
@@ -26,5 +26,3 @@ struct die_struct;
extern void debug_dwarf_die PARAMS ((struct die_struct *));
extern void dwarf2out_set_demangle_name_func PARAMS ((const char *(*) (const char *)));
extern void dwarf2out_add_library_unit_info PARAMS ((const char *, const char *));
-
-extern unsigned current_funcdef_number;
diff --git a/contrib/gcc/dwarfout.c b/contrib/gcc/dwarfout.c
index 481d0c0..bbbfcfc 100644
--- a/contrib/gcc/dwarfout.c
+++ b/contrib/gcc/dwarfout.c
@@ -1,6 +1,6 @@
/* Output Dwarf format symbol table information from the GNU C compiler.
- Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 2002,
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@monkeys.com) of Network Computing Devices.
This file is part of GCC.
@@ -43,7 +43,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
The generation of DWARF debugging information by the GNU version 2.x C
compiler has now been tested rather extensively for m88k, i386, i860, and
- Sparc targets. The DWARF output of the GNU C compiler appears to inter-
+ SPARC targets. The DWARF output of the GNU C compiler appears to inter-
operate well with the standard SVR4 SDB debugger on these kinds of target
systems (but of course, there are no guarantees).
@@ -162,7 +162,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
is required by the current DWARF draft specification.
Specifically, the current DWARF draft specification seems to require that
- the type of an non-unsigned integral bit-field member of a struct or union
+ the type of a non-unsigned integral bit-field member of a struct or union
type be represented as either a "signed" type or as a "plain" type,
depending upon the exact set of keywords that were used in the
type specification for the given bit-field member. It was felt (by the
@@ -523,7 +523,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
are still being discussed. Also, we in the PLSIG are still discussing
whether or not we need to do anything special for C++ templates. (At this
time it is not yet clear whether we even need to do anything special for
- these.)
+ these.)
With regard to FORTRAN, the UI/PLSIG has defined what is believed to be a
complete and sufficient set of codes and rules for adequately representing
@@ -560,7 +560,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
Other possible `compacting' transformations designed to save disk
space and to reduce linker & debugger I/O activity.
-*/
+*/
#include "config.h"
@@ -569,6 +569,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "dwarf.h"
#include "tree.h"
#include "flags.h"
+#include "function.h"
#include "rtl.h"
#include "hard-reg-set.h"
#include "insn-config.h"
@@ -599,7 +600,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
fprintf ((FILE), "%s", reg_names[REGNO (RTX)])
#endif
-/* Define a macro which returns non-zero for any tagged type which is
+/* Define a macro which returns nonzero for any tagged type which is
used (directly or indirectly) in the specification of either some
function's return type or some formal parameter of some function.
We use this macro when we are operating in "terse" mode to help us
@@ -611,12 +612,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
for these nodes. For now, we have to just fake it. It it safe for
us to simply return zero for all complete tagged types (which will
get forced out anyway if they were used in the specification of some
- formal or return type) and non-zero for all incomplete tagged types.
+ formal or return type) and nonzero for all incomplete tagged types.
*/
#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
+/* Define a macro which returns nonzero for a TYPE_DECL which was
implicitly generated for a tagged type.
Note that unlike the gcc front end (which generates a NULL named
@@ -631,8 +632,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
&& is_tagged_type (TREE_TYPE (decl)) \
&& decl == TYPE_STUB_DECL (TREE_TYPE (decl))))
-extern int flag_traditional;
-
/* Maximum size (in bytes) of an artificially generated label. */
#define MAX_ARTIFICIAL_LABEL_BYTES 30
@@ -708,7 +707,7 @@ static unsigned pending_siblings_allocated;
#define PENDING_SIBLINGS_INCREMENT 64
-/* Non-zero if we are performing our file-scope finalization pass and if
+/* Nonzero if we are performing our file-scope finalization pass and if
we should force out Dwarf descriptions of any and all file-scope
tagged types which are still incomplete types. */
@@ -758,14 +757,6 @@ static unsigned incomplete_types;
static tree fake_containing_scope;
-/* The number of the current function definition that we are generating
- debugging information for. These numbers range from 1 up to the maximum
- number of function definitions contained within the current compilation
- unit. These numbers are used to create unique labels for various things
- contained within various function definitions. */
-
-static unsigned current_funcdef_number = 1;
-
/* A pointer to the ..._DECL node which we have most recently been working
on. We keep this around just in case something about it looks screwy
and we want to tell the user what the source coordinates for the actual
@@ -791,9 +782,9 @@ static void dwarfout_end_source_file PARAMS ((unsigned));
static void dwarfout_end_source_file_check PARAMS ((unsigned));
static void dwarfout_begin_block PARAMS ((unsigned, unsigned));
static void dwarfout_end_block PARAMS ((unsigned, unsigned));
-static void dwarfout_end_epilogue PARAMS ((void));
+static void dwarfout_end_epilogue PARAMS ((unsigned int, const char *));
static void dwarfout_source_line PARAMS ((unsigned int, const char *));
-static void dwarfout_end_prologue PARAMS ((unsigned int));
+static void dwarfout_end_prologue PARAMS ((unsigned int, const char *));
static void dwarfout_end_function PARAMS ((unsigned int));
static void dwarfout_function_decl PARAMS ((tree));
static void dwarfout_global_decl PARAMS ((tree));
@@ -944,9 +935,6 @@ static void retry_incomplete_types PARAMS ((void));
#ifndef FILE_ASM_OP
#define FILE_ASM_OP "\t.file\t"
#endif
-#ifndef VERSION_ASM_OP
-#define VERSION_ASM_OP "\t.version\t"
-#endif
#ifndef SET_ASM_OP
#define SET_ASM_OP "\t.set\t"
#endif
@@ -1150,18 +1138,6 @@ static void retry_incomplete_types PARAMS ((void));
#ifndef BOUND_END_LABEL_FMT
#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"
-#endif
-#ifndef DERIV_END_LABEL_FMT
-#define DERIV_END_LABEL_FMT "*.L_d%u_e"
-#endif
-#ifndef SL_BEGIN_LABEL_FMT
-#define SL_BEGIN_LABEL_FMT "*.L_sl%u"
-#endif
-#ifndef SL_END_LABEL_FMT
-#define SL_END_LABEL_FMT "*.L_sl%u_e"
-#endif
#ifndef BODY_BEGIN_LABEL_FMT
#define BODY_BEGIN_LABEL_FMT "*.L_b%u"
#endif
@@ -1289,12 +1265,12 @@ static void retry_incomplete_types PARAMS ((void));
ASM_OUTPUT_ASCII ((FILE), P, strlen (P)+1)
#else
#define ASM_OUTPUT_DWARF_STRING_NEWLINE(FILE,P) \
- ASM_OUTPUT_DWARF_STRING (FILE,P), ASM_OUTPUT_DWARF_STRING (FILE,"\n")
+ ASM_OUTPUT_DWARF_STRING (FILE,P), ASM_OUTPUT_DWARF_STRING (FILE,"\n")
#endif
/* The debug hooks structure. */
-struct gcc_debug_hooks dwarf_debug_hooks =
+const struct gcc_debug_hooks dwarf_debug_hooks =
{
dwarfout_init,
dwarfout_finish,
@@ -1325,7 +1301,7 @@ is_pseudo_reg (rtl)
rtx rtl;
{
return (((GET_CODE (rtl) == REG) && (REGNO (rtl) >= FIRST_PSEUDO_REGISTER))
- || ((GET_CODE (rtl) == SUBREG)
+ || ((GET_CODE (rtl) == SUBREG)
&& (REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER)));
}
@@ -1343,13 +1319,13 @@ type_main_variant (type)
if (TREE_CODE (type) == ARRAY_TYPE)
{
while (type != TYPE_MAIN_VARIANT (type))
- type = TYPE_MAIN_VARIANT (type);
+ type = TYPE_MAIN_VARIANT (type);
}
return type;
}
-/* Return non-zero if the given type node represents a tagged type. */
+/* Return nonzero if the given type node represents a tagged type. */
static inline int
is_tagged_type (type)
@@ -1609,7 +1585,7 @@ static tree
decl_ultimate_origin (decl)
tree decl;
{
-#ifdef ENABLE_CHECKING
+#ifdef ENABLE_CHECKING
if (DECL_FROM_INLINE (DECL_ORIGIN (decl)))
/* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the
most distant ancestor, this should never happen. */
@@ -1707,7 +1683,7 @@ output_signed_leb128 (value)
if (negative)
value |= 0xfe000000; /* manually sign extend */
if (((value == 0) && ((byte & 0x40) == 0))
- || ((value == -1) && ((byte & 0x40) == 1)))
+ || ((value == -1) && ((byte & 0x40) == 1)))
more = 0;
else
{
@@ -1974,7 +1950,7 @@ write_modifier_bytes (type, decl_const, 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 a pointer to an arbitrary ..._TYPE tree node, return nonzero if the
given input type is a Dwarf "fundamental" type. Otherwise return zero. */
static inline int
@@ -2843,8 +2819,8 @@ location_or_const_value_attribute (decl)
if (rtl == NULL_RTX || is_pseudo_reg (rtl))
{
/* This decl represents a formal parameter which was optimized out. */
- tree declared_type = type_main_variant (TREE_TYPE (decl));
- tree passed_type = type_main_variant (DECL_ARG_TYPE (decl));
+ tree declared_type = type_main_variant (TREE_TYPE (decl));
+ tree passed_type = type_main_variant (DECL_ARG_TYPE (decl));
/* Note that DECL_INCOMING_RTL may be NULL in here, but we handle
*all* cases where (rtl == NULL_RTX) just below. */
@@ -3330,6 +3306,13 @@ member_attribute (context)
}
#if 0
+#ifndef SL_BEGIN_LABEL_FMT
+#define SL_BEGIN_LABEL_FMT "*.L_sl%u"
+#endif
+#ifndef SL_END_LABEL_FMT
+#define SL_END_LABEL_FMT "*.L_sl%u_e"
+#endif
+
static inline void
string_length_attribute (upper_bound)
tree upper_bound;
@@ -3468,10 +3451,10 @@ pure_or_virtual_attribute (func_decl)
{
#if 0 /* DECL_ABSTRACT_VIRTUAL_P is C++-specific. */
if (DECL_ABSTRACT_VIRTUAL_P (func_decl))
- ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_pure_virtual);
+ ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_pure_virtual);
else
#endif
- ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
+ ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
}
@@ -3510,7 +3493,7 @@ name_and_src_coords_attributes (decl)
file_index = lookup_filename (DECL_SOURCE_FILE (decl));
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_SECTION);
- src_coords_attribute (file_index, DECL_SOURCE_LINE (decl));
+ src_coords_attribute (file_index, DECL_SOURCE_LINE (decl));
}
#endif /* defined(DWARF_DECL_COORDINATES) */
}
@@ -3591,7 +3574,7 @@ type_tag (type)
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
t = TYPE_NAME (type);
- /* The g++ front end makes the TYPE_NAME of *each* tagged type point to
+ /* 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
@@ -3898,13 +3881,14 @@ output_global_subroutine_die (arg)
char label[MAX_ARTIFICIAL_LABEL_BYTES];
low_pc_attribute (function_start_label (decl));
- sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
+ sprintf (label, FUNC_END_LABEL_FMT, current_function_funcdef_no);
high_pc_attribute (label);
if (use_gnu_debug_info_extensions)
{
- sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
+ sprintf (label, BODY_BEGIN_LABEL_FMT,
+ current_function_funcdef_no);
body_begin_attribute (label);
- sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
+ sprintf (label, BODY_END_LABEL_FMT, current_function_funcdef_no);
body_end_attribute (label);
}
}
@@ -4154,8 +4138,6 @@ output_compile_unit_die (arg)
language_attribute (LANG_PASCAL83);
else if (strcmp (language_string, "GNU Java") == 0)
language_attribute (LANG_JAVA);
- else if (flag_traditional)
- language_attribute (LANG_C);
else
language_attribute (LANG_C89);
low_pc_attribute (TEXT_BEGIN_LABEL);
@@ -4174,7 +4156,7 @@ output_compile_unit_die (arg)
sf_names_attribute (SFNAMES_BEGIN_LABEL);
src_info_attribute (SRCINFO_BEGIN_LABEL);
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
- mac_info_attribute (MACINFO_BEGIN_LABEL);
+ mac_info_attribute (MACINFO_BEGIN_LABEL);
}
}
@@ -4217,7 +4199,7 @@ output_inheritance_die (arg)
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_protected);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
-}
+}
static void
output_structure_type_die (arg)
@@ -4281,13 +4263,14 @@ output_local_subroutine_die (arg)
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
low_pc_attribute (function_start_label (decl));
- sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
+ sprintf (label, FUNC_END_LABEL_FMT, current_function_funcdef_no);
high_pc_attribute (label);
if (use_gnu_debug_info_extensions)
{
- sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
+ sprintf (label, BODY_BEGIN_LABEL_FMT,
+ current_function_funcdef_no);
body_begin_attribute (label);
- sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
+ sprintf (label, BODY_END_LABEL_FMT, current_function_funcdef_no);
body_end_attribute (label);
}
}
@@ -4550,7 +4533,7 @@ pend_type (type)
TREE_ASM_WRITTEN (type) = 1;
}
-/* Return non-zero if it is legitimate to output DIEs to represent a
+/* Return nonzero if it is legitimate to output DIEs to represent a
given type while we are generating the list of child DIEs for some
DIE (e.g. a function or lexical block DIE) associated with a given scope.
@@ -4801,7 +4784,7 @@ output_type (type, containing_scope)
end_sibling_chain ();
break;
- case ARRAY_TYPE:
+ case ARRAY_TYPE:
if (TYPE_STRING_FLAG (type) && TREE_CODE(TREE_TYPE(type)) == CHAR_TYPE)
{
output_type (TREE_TYPE (type), containing_scope);
@@ -5156,8 +5139,8 @@ output_decls_for_scope (stmt, depth)
tree subblocks;
for (subblocks = BLOCK_SUBBLOCKS (stmt);
- subblocks;
- subblocks = BLOCK_CHAIN (subblocks))
+ subblocks;
+ subblocks = BLOCK_CHAIN (subblocks))
output_block (subblocks, depth + 1);
}
}
@@ -5203,10 +5186,10 @@ output_decl (decl, containing_scope)
if ((TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE)
&& ((DECL_NAME (decl) == 0 && TYPE_NAME (TREE_TYPE (decl)) == 0)
- || (TYPE_FIELDS (TREE_TYPE (decl))
+ || (TYPE_FIELDS (TREE_TYPE (decl))
&& (TREE_CODE (TYPE_FIELDS (TREE_TYPE (decl))) == ERROR_MARK))))
return;
-
+
/* If this ..._DECL node is marked to be ignored, then ignore it. */
if (DECL_IGNORED_P (decl))
@@ -5331,7 +5314,7 @@ output_decl (decl, containing_scope)
for (parm = arg_decls; parm; parm = TREE_CHAIN (parm))
if (TREE_CODE (parm) == PARM_DECL)
- {
+ {
if (DECL_NAME(parm) &&
!strcmp(IDENTIFIER_POINTER(DECL_NAME(parm)),
"__builtin_va_alist") )
@@ -5368,13 +5351,13 @@ output_decl (decl, containing_scope)
/* 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);
- }
- else
- {
- /* this is unprototyped, check for undefined (just declaration) */
- if (!DECL_INITIAL (decl))
- output_die (output_unspecified_parameters_die, decl);
- }
+ }
+ else
+ {
+ /* this is unprototyped, check for undefined (just declaration) */
+ if (!DECL_INITIAL (decl))
+ output_die (output_unspecified_parameters_die, decl);
+ }
}
/* Output Dwarf info for all of the stuff within the body of the
@@ -5433,7 +5416,7 @@ output_decl (decl, containing_scope)
if (debug_info_level <= DINFO_LEVEL_TERSE)
if (! TYPE_DECL_IS_STUB (decl)
|| (! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)) && ! in_class))
- return;
+ return;
/* In the special case of a TYPE_DECL node representing
the declaration of some type tag, if the given TYPE_DECL is
@@ -5474,7 +5457,7 @@ output_decl (decl, containing_scope)
any variable declarations or definitions. */
if (debug_info_level <= DINFO_LEVEL_TERSE)
- break;
+ break;
/* Output any DIEs that are needed to specify the type of this data
object. */
@@ -5508,7 +5491,7 @@ output_decl (decl, containing_scope)
function. */
{
- void (*func) PARAMS ((void *));
+ void (*func) PARAMS ((void *));
register tree origin = decl_ultimate_origin (decl);
if (origin != NULL && TREE_CODE (origin) == PARM_DECL)
@@ -5529,7 +5512,7 @@ output_decl (decl, containing_scope)
if (DECL_NAME (decl) != 0)
{
output_type (member_declared_type (decl), containing_scope);
- output_die (output_member_die, decl);
+ output_die (output_member_die, decl);
}
break;
@@ -5629,7 +5612,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
these same functions should NOT be ignored however. */
if (DECL_EXTERNAL (decl) && DECL_FUNCTION_CODE (decl))
- return;
+ return;
/* What we would really like to do here is to filter out all mere
file-scope declarations of file-scope functions which are never
@@ -5729,7 +5712,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_ARANGES_SECTION);
ASM_OUTPUT_DWARF_ADDR (asm_out_file,
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
(unsigned) int_size_in_bytes (TREE_TYPE (decl)));
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
@@ -5739,7 +5722,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
any variable declarations or definitions. */
if (debug_info_level <= DINFO_LEVEL_TERSE)
- return;
+ return;
break;
@@ -5777,7 +5760,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
if (debug_info_level <= DINFO_LEVEL_TERSE)
if (! TYPE_DECL_IS_STUB (decl)
|| ! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)))
- return;
+ return;
break;
@@ -5807,7 +5790,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
if this is not a nested function or class. If this is a nested type,
then the remaining pending_types will be emitted when the containing type
is handled. */
-
+
if (! DECL_CONTEXT (decl))
{
if (pending_types != 0)
@@ -5815,9 +5798,6 @@ dwarfout_file_scope_decl (decl, set_finalizing)
}
ASM_OUTPUT_POP_SECTION (asm_out_file);
-
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) != NULL)
- current_funcdef_number++;
}
/* Output a marker (i.e. a label) for the beginning of the generated code
@@ -5855,8 +5835,9 @@ dwarfout_end_block (line, blocknum)
to their home locations). */
static void
-dwarfout_end_prologue (line)
+dwarfout_end_prologue (line, file)
unsigned int line ATTRIBUTE_UNUSED;
+ const char *file ATTRIBUTE_UNUSED;
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -5864,7 +5845,7 @@ dwarfout_end_prologue (line)
return;
function_section (current_function_decl);
- sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
+ sprintf (label, BODY_BEGIN_LABEL_FMT, current_function_funcdef_no);
ASM_OUTPUT_LABEL (asm_out_file, label);
}
@@ -5880,7 +5861,7 @@ dwarfout_end_function (line)
if (! use_gnu_debug_info_extensions)
return;
function_section (current_function_decl);
- sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
+ sprintf (label, BODY_END_LABEL_FMT, current_function_funcdef_no);
ASM_OUTPUT_LABEL (asm_out_file, label);
}
@@ -5889,14 +5870,16 @@ dwarfout_end_function (line)
has been generated. */
static void
-dwarfout_end_epilogue ()
+dwarfout_end_epilogue (line, file)
+ unsigned int line ATTRIBUTE_UNUSED;
+ const char *file ATTRIBUTE_UNUSED;
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
/* Output a label to mark the endpoint of the code generated for this
function. */
- sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
+ sprintf (label, FUNC_END_LABEL_FMT, current_function_funcdef_no);
ASM_OUTPUT_LABEL (asm_out_file, label);
}
@@ -5936,9 +5919,9 @@ generate_new_sfname_entry ()
sprintf (label, SFNAMES_ENTRY_LABEL_FMT, filename_table[0].number);
ASM_OUTPUT_LABEL (asm_out_file, label);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file,
- filename_table[0].name
- ? filename_table[0].name
- : "");
+ filename_table[0].name
+ ? filename_table[0].name
+ : "");
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
@@ -5990,7 +5973,7 @@ lookup_filename (file_name)
same filename will find it as quickly as possible. */
shuffle_filename_entry (search_p);
- return filename_table[0].number;
+ return filename_table[0].number;
}
/* We come here whenever we have a new filename which is not registered
@@ -6068,18 +6051,18 @@ dwarfout_source_line (line, filename)
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];
+ {
+ char line_entry_label[MAX_ARTIFICIAL_LABEL_BYTES];
- sprintf (line_entry_label, LINE_ENTRY_LABEL_FMT, last_line_entry_num);
- ASM_OUTPUT_LABEL (asm_out_file, line_entry_label);
- }
+ sprintf (line_entry_label, LINE_ENTRY_LABEL_FMT, last_line_entry_num);
+ ASM_OUTPUT_LABEL (asm_out_file, line_entry_label);
+ }
{
- const char *tail = strrchr (filename, '/');
+ const char *tail = strrchr (filename, '/');
- if (tail != NULL)
- filename = tail;
+ if (tail != NULL)
+ filename = tail;
}
dw2_asm_output_data (4, line, "%s:%u", filename, line);
@@ -6088,7 +6071,7 @@ dwarfout_source_line (line, filename)
ASM_OUTPUT_POP_SECTION (asm_out_file);
if (this_file_entry_num != prev_file_entry_num)
- generate_srcinfo_entry (last_line_entry_num, this_file_entry_num);
+ generate_srcinfo_entry (last_line_entry_num, this_file_entry_num);
prev_file_entry_num = this_file_entry_num;
}
}
@@ -6195,6 +6178,8 @@ static void
dwarfout_init (main_input_filename)
const char *main_input_filename;
{
+ warning ("support for the DWARF1 debugging format is deprecated");
+
/* Remember the name of the primary input file. */
primary_filename = main_input_filename;
@@ -6281,7 +6266,7 @@ dwarfout_init (main_input_filename)
/* 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, DEBUG_SFNAMES_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, SFNAMES_BEGIN_LABEL);
@@ -6298,29 +6283,29 @@ dwarfout_init (main_input_filename)
}
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
-
+
if (debug_info_level >= DINFO_LEVEL_VERBOSE
&& use_gnu_debug_info_extensions)
{
- /* Output a starting label for the .debug_macinfo section. This
+ /* Output a starting label for the .debug_macinfo section. This
label will be referenced by the AT_mac_info attribute in the
TAG_compile_unit DIE. */
-
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
- ASM_OUTPUT_LABEL (asm_out_file, MACINFO_BEGIN_LABEL);
- ASM_OUTPUT_POP_SECTION (asm_out_file);
+
+ fputc ('\n', asm_out_file);
+ ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
+ ASM_OUTPUT_LABEL (asm_out_file, MACINFO_BEGIN_LABEL);
+ ASM_OUTPUT_POP_SECTION (asm_out_file);
}
/* Generate the initial entry for the .line section. */
-
+
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, LINE_BEGIN_LABEL);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, LINE_END_LABEL, LINE_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
-
+
if (use_gnu_debug_info_extensions)
{
/* Generate the initial entry for the .debug_srcinfo section. */
@@ -6339,16 +6324,16 @@ dwarfout_init (main_input_filename)
#endif
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
-
+
/* Generate the initial entry for the .debug_pubnames section. */
-
+
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_PUBNAMES_SECTION);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, DEBUG_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
-
+
/* Generate the initial entry for the .debug_aranges section. */
-
+
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_ARANGES_SECTION);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
@@ -6474,7 +6459,7 @@ dwarfout_finish (main_input_filename)
if (debug_info_level >= DINFO_LEVEL_NORMAL)
{
/* Output a terminating entry for the .line section. */
-
+
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, LINE_LAST_ENTRY_LABEL);
@@ -6483,7 +6468,7 @@ dwarfout_finish (main_input_filename)
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, TEXT_END_LABEL, TEXT_BEGIN_LABEL);
ASM_OUTPUT_LABEL (asm_out_file, LINE_END_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
-
+
if (use_gnu_debug_info_extensions)
{
/* Output a terminating entry for the .debug_srcinfo section. */
@@ -6499,7 +6484,7 @@ dwarfout_finish (main_input_filename)
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
{
/* Output terminating entries for the .debug_macinfo section. */
-
+
dwarfout_end_source_file (0);
fputc ('\n', asm_out_file);
@@ -6508,15 +6493,15 @@ dwarfout_finish (main_input_filename)
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
-
+
/* Generate the terminating entry for the .debug_pubnames section. */
-
+
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_PUBNAMES_SECTION);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
ASM_OUTPUT_POP_SECTION (asm_out_file);
-
+
/* Generate the terminating entries for the .debug_aranges section.
Note that we want to do this only *after* we have output the end
@@ -6530,7 +6515,7 @@ dwarfout_finish (main_input_filename)
entries at this late point in the assembly output, we skirt the
issue simply by avoiding forward-references.
*/
-
+
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_ARANGES_SECTION);
diff --git a/contrib/gcc/emit-rtl.c b/contrib/gcc/emit-rtl.c
index e2bbd85..172a82d 100644
--- a/contrib/gcc/emit-rtl.c
+++ b/contrib/gcc/emit-rtl.c
@@ -50,7 +50,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "insn-config.h"
#include "recog.h"
#include "real.h"
-#include "obstack.h"
#include "bitmap.h"
#include "basic-block.h"
#include "ggc.h"
@@ -87,11 +86,17 @@ static int no_line_numbers;
/* Commonly used rtx's, so that we only need space for one copy.
These are initialized once for the entire compilation.
- All of these except perhaps the floating-point CONST_DOUBLEs
- are unique; no other rtx-object will be equal to any of these. */
+ All of these are unique; no other rtx-object will be equal to any
+ of these. */
rtx global_rtl[GR_MAX];
+/* Commonly used RTL for hard registers. These objects are not necessarily
+ unique, so we allocate them separately from global_rtl. They are
+ initialized once per compilation unit, then copied into regno_reg_rtx
+ at the beginning of each function. */
+static GTY(()) rtx static_regno_reg_rtx[FIRST_PSEUDO_REGISTER];
+
/* We record floating-point CONST_DOUBLEs in each floating-point mode for
the values of 0, 1, and 2. For the integer entries and VOIDmode, we
record a copy of const[012]_rtx. */
@@ -143,30 +148,16 @@ rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
/* A hash table storing CONST_INTs whose absolute value is greater
than MAX_SAVED_CONST_INT. */
-static htab_t const_int_htab;
+static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
+ htab_t const_int_htab;
/* A hash table storing memory attribute structures. */
-static htab_t mem_attrs_htab;
-
-/* start_sequence and gen_sequence can make a lot of rtx expressions which are
- shortly thrown away. We use two mechanisms to prevent this waste:
-
- For sizes up to 5 elements, we keep a SEQUENCE and its associated
- rtvec for use by gen_sequence. One entry for each size is
- sufficient because most cases are calls to gen_sequence followed by
- immediately emitting the SEQUENCE. Reuse is safe since emitting a
- sequence is destructive on the insn in it anyway and hence can't be
- redone.
-
- We do not bother to save this cached data over nested function calls.
- Instead, we just reinitialize them. */
-
-#define SEQUENCE_RESULT_SIZE 5
-
-static rtx sequence_result[SEQUENCE_RESULT_SIZE];
+static GTY ((if_marked ("ggc_marked_p"), param_is (struct mem_attrs)))
+ htab_t mem_attrs_htab;
-/* During RTL generation, we also keep a list of free INSN rtl codes. */
-static rtx free_insn;
+/* A hash table storing all CONST_DOUBLEs. */
+static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
+ htab_t const_double_htab;
#define first_insn (cfun->emit->x_first_insn)
#define last_insn (cfun->emit->x_last_insn)
@@ -178,7 +169,6 @@ static rtx free_insn;
static rtx make_jump_insn_raw PARAMS ((rtx));
static rtx make_call_insn_raw PARAMS ((rtx));
static rtx find_line_note PARAMS ((rtx));
-static void mark_sequence_stack PARAMS ((struct sequence_stack *));
static rtx change_address_1 PARAMS ((rtx, enum machine_mode, rtx,
int));
static void unshare_all_rtl_1 PARAMS ((rtx));
@@ -188,10 +178,13 @@ static void mark_label_nuses PARAMS ((rtx));
static hashval_t const_int_htab_hash PARAMS ((const void *));
static int const_int_htab_eq PARAMS ((const void *,
const void *));
+static hashval_t const_double_htab_hash PARAMS ((const void *));
+static int const_double_htab_eq PARAMS ((const void *,
+ const void *));
+static rtx lookup_const_double PARAMS ((rtx));
static hashval_t mem_attrs_htab_hash PARAMS ((const void *));
static int mem_attrs_htab_eq PARAMS ((const void *,
const void *));
-static void mem_attrs_mark PARAMS ((const void *));
static mem_attrs *get_mem_attrs PARAMS ((HOST_WIDE_INT, tree, rtx,
rtx, unsigned int,
enum machine_mode));
@@ -208,10 +201,10 @@ static hashval_t
const_int_htab_hash (x)
const void *x;
{
- return (hashval_t) INTVAL ((const struct rtx_def *) x);
+ return (hashval_t) INTVAL ((struct rtx_def *) x);
}
-/* Returns non-zero if the value represented by X (which is really a
+/* Returns nonzero if the value represented by X (which is really a
CONST_INT) is the same as that given by Y (which is really a
HOST_WIDE_INT *). */
@@ -220,7 +213,41 @@ const_int_htab_eq (x, y)
const void *x;
const void *y;
{
- return (INTVAL ((const struct rtx_def *) x) == *((const HOST_WIDE_INT *) y));
+ return (INTVAL ((rtx) x) == *((const HOST_WIDE_INT *) y));
+}
+
+/* Returns a hash code for X (which is really a CONST_DOUBLE). */
+static hashval_t
+const_double_htab_hash (x)
+ const void *x;
+{
+ rtx value = (rtx) x;
+ hashval_t h;
+
+ if (GET_MODE (value) == VOIDmode)
+ h = CONST_DOUBLE_LOW (value) ^ CONST_DOUBLE_HIGH (value);
+ else
+ h = real_hash (CONST_DOUBLE_REAL_VALUE (value));
+ return h;
+}
+
+/* Returns nonzero if the value represented by X (really a ...)
+ is the same as that represented by Y (really a ...) */
+static int
+const_double_htab_eq (x, y)
+ const void *x;
+ const void *y;
+{
+ rtx a = (rtx)x, b = (rtx)y;
+
+ if (GET_MODE (a) != GET_MODE (b))
+ return 0;
+ if (GET_MODE (a) == VOIDmode)
+ return (CONST_DOUBLE_LOW (a) == CONST_DOUBLE_LOW (b)
+ && CONST_DOUBLE_HIGH (a) == CONST_DOUBLE_HIGH (b));
+ else
+ return real_identical (CONST_DOUBLE_REAL_VALUE (a),
+ CONST_DOUBLE_REAL_VALUE (b));
}
/* Returns a hash code for X (which is a really a mem_attrs *). */
@@ -237,7 +264,7 @@ mem_attrs_htab_hash (x)
^ (size_t) p->expr);
}
-/* Returns non-zero if the value represented by X (which is really a
+/* Returns nonzero if the value represented by X (which is really a
mem_attrs *) is the same as that given by Y (which is also really a
mem_attrs *). */
@@ -253,25 +280,6 @@ mem_attrs_htab_eq (x, y)
&& p->size == q->size && p->align == q->align);
}
-/* This routine is called when we determine that we need a mem_attrs entry.
- It marks the associated decl and RTL as being used, if present. */
-
-static void
-mem_attrs_mark (x)
- const void *x;
-{
- mem_attrs *p = (mem_attrs *) x;
-
- if (p->expr)
- ggc_mark_tree (p->expr);
-
- if (p->offset)
- ggc_mark_rtx (p->offset);
-
- if (p->size)
- ggc_mark_rtx (p->size);
-}
-
/* Allocate a new mem_attrs structure and insert it into the hash table if
one identical to it is not already in the table. We are doing this for
MEM of mode MODE. */
@@ -363,32 +371,133 @@ gen_int_mode (c, mode)
return GEN_INT (trunc_int_for_mode (c, mode));
}
-/* CONST_DOUBLEs needs special handling because their length is known
- only at run-time. */
+/* CONST_DOUBLEs might be created from pairs of integers, or from
+ REAL_VALUE_TYPEs. Also, their length is known only at run time,
+ so we cannot use gen_rtx_raw_CONST_DOUBLE. */
+
+/* Determine whether REAL, a CONST_DOUBLE, already exists in the
+ hash table. If so, return its counterpart; otherwise add it
+ to the hash table and return it. */
+static rtx
+lookup_const_double (real)
+ rtx real;
+{
+ void **slot = htab_find_slot (const_double_htab, real, INSERT);
+ if (*slot == 0)
+ *slot = real;
+
+ return (rtx) *slot;
+}
+/* Return a CONST_DOUBLE rtx for a floating-point value specified by
+ VALUE in mode MODE. */
rtx
-gen_rtx_CONST_DOUBLE (mode, arg0, arg1)
+const_double_from_real_value (value, mode)
+ REAL_VALUE_TYPE value;
enum machine_mode mode;
- HOST_WIDE_INT arg0, arg1;
{
- rtx r = rtx_alloc (CONST_DOUBLE);
- int i;
+ rtx real = rtx_alloc (CONST_DOUBLE);
+ PUT_MODE (real, mode);
- PUT_MODE (r, mode);
- X0EXP (r, 0) = NULL_RTX;
- XWINT (r, 1) = arg0;
- XWINT (r, 2) = arg1;
+ memcpy (&CONST_DOUBLE_LOW (real), &value, sizeof (REAL_VALUE_TYPE));
- for (i = GET_RTX_LENGTH (CONST_DOUBLE) - 1; i > 2; --i)
- XWINT (r, i) = 0;
+ return lookup_const_double (real);
+}
+
+/* Return a CONST_DOUBLE or CONST_INT for a value specified as a pair
+ of ints: I0 is the low-order word and I1 is the high-order word.
+ Do not use this routine for non-integer modes; convert to
+ REAL_VALUE_TYPE and use CONST_DOUBLE_FROM_REAL_VALUE. */
+
+rtx
+immed_double_const (i0, i1, mode)
+ HOST_WIDE_INT i0, i1;
+ enum machine_mode mode;
+{
+ rtx value;
+ unsigned int i;
+
+ if (mode != VOIDmode)
+ {
+ int width;
+ if (GET_MODE_CLASS (mode) != MODE_INT
+ && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT
+ /* We can get a 0 for an error mark. */
+ && GET_MODE_CLASS (mode) != MODE_VECTOR_INT
+ && GET_MODE_CLASS (mode) != MODE_VECTOR_FLOAT)
+ abort ();
+
+ /* We clear out all bits that don't belong in MODE, unless they and
+ our sign bit are all one. So we get either a reasonable negative
+ value or a reasonable unsigned value for this mode. */
+ width = GET_MODE_BITSIZE (mode);
+ if (width < HOST_BITS_PER_WIDE_INT
+ && ((i0 & ((HOST_WIDE_INT) (-1) << (width - 1)))
+ != ((HOST_WIDE_INT) (-1) << (width - 1))))
+ i0 &= ((HOST_WIDE_INT) 1 << width) - 1, i1 = 0;
+ else if (width == HOST_BITS_PER_WIDE_INT
+ && ! (i1 == ~0 && i0 < 0))
+ i1 = 0;
+ else if (width > 2 * HOST_BITS_PER_WIDE_INT)
+ /* We cannot represent this value as a constant. */
+ abort ();
+
+ /* If this would be an entire word for the target, but is not for
+ the host, then sign-extend on the host so that the number will
+ look the same way on the host that it would on the target.
+
+ For example, when building a 64 bit alpha hosted 32 bit sparc
+ targeted compiler, then we want the 32 bit unsigned value -1 to be
+ represented as a 64 bit value -1, and not as 0x00000000ffffffff.
+ The latter confuses the sparc backend. */
+
+ if (width < HOST_BITS_PER_WIDE_INT
+ && (i0 & ((HOST_WIDE_INT) 1 << (width - 1))))
+ i0 |= ((HOST_WIDE_INT) (-1) << width);
+
+ /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a
+ CONST_INT.
+
+ ??? Strictly speaking, this is wrong if we create a CONST_INT for
+ a large unsigned constant with the size of MODE being
+ HOST_BITS_PER_WIDE_INT and later try to interpret that constant
+ in a wider mode. In that case we will mis-interpret it as a
+ negative number.
+
+ Unfortunately, the only alternative is to make a CONST_DOUBLE for
+ any constant in any mode if it is an unsigned constant larger
+ than the maximum signed integer in an int on the host. However,
+ doing this will break everyone that always expects to see a
+ CONST_INT for SImode and smaller.
+
+ We have always been making CONST_INTs in this case, so nothing
+ new is being broken. */
+
+ if (width <= HOST_BITS_PER_WIDE_INT)
+ i1 = (i0 < 0) ? ~(HOST_WIDE_INT) 0 : 0;
+ }
- return r;
+ /* If this integer fits in one word, return a CONST_INT. */
+ if ((i1 == 0 && i0 >= 0) || (i1 == ~0 && i0 < 0))
+ return GEN_INT (i0);
+
+ /* We use VOIDmode for integers. */
+ value = rtx_alloc (CONST_DOUBLE);
+ PUT_MODE (value, VOIDmode);
+
+ CONST_DOUBLE_LOW (value) = i0;
+ CONST_DOUBLE_HIGH (value) = i1;
+
+ for (i = 2; i < (sizeof CONST_DOUBLE_FORMAT - 1); i++)
+ XWINT (value, i) = 0;
+
+ return lookup_const_double (value);
}
rtx
gen_rtx_REG (mode, regno)
enum machine_mode mode;
- int regno;
+ unsigned int regno;
{
/* In case the MD file explicitly references the frame pointer, have
all such references point to the same frame pointer. This is
@@ -406,10 +515,12 @@ gen_rtx_REG (mode, regno)
if (mode == Pmode && !reload_in_progress)
{
- if (regno == FRAME_POINTER_REGNUM)
+ if (regno == FRAME_POINTER_REGNUM
+ && (!reload_completed || frame_pointer_needed))
return frame_pointer_rtx;
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- if (regno == HARD_FRAME_POINTER_REGNUM)
+ if (regno == HARD_FRAME_POINTER_REGNUM
+ && (!reload_completed || frame_pointer_needed))
return hard_frame_pointer_rtx;
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM && HARD_FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
@@ -422,11 +533,31 @@ gen_rtx_REG (mode, regno)
#endif
if (regno == PIC_OFFSET_TABLE_REGNUM
&& fixed_regs[PIC_OFFSET_TABLE_REGNUM])
- return pic_offset_table_rtx;
+ return pic_offset_table_rtx;
if (regno == STACK_POINTER_REGNUM)
return stack_pointer_rtx;
}
+#if 0
+ /* If the per-function register table has been set up, try to re-use
+ an existing entry in that table to avoid useless generation of RTL.
+
+ This code is disabled for now until we can fix the various backends
+ which depend on having non-shared hard registers in some cases. Long
+ term we want to re-enable this code as it can significantly cut down
+ on the amount of useless RTL that gets generated.
+
+ We'll also need to fix some code that runs after reload that wants to
+ set ORIGINAL_REGNO. */
+
+ if (cfun
+ && cfun->emit
+ && regno_reg_rtx
+ && regno < FIRST_PSEUDO_REGISTER
+ && reg_raw_mode[regno] == mode)
+ return regno_reg_rtx[regno];
+#endif
+
return gen_raw_REG (mode, regno);
}
@@ -463,7 +594,7 @@ gen_rtx_SUBREG (mode, reg, offset)
if (offset >= GET_MODE_SIZE (GET_MODE (reg)))
abort ();
#endif
- return gen_rtx_fmt_ei (SUBREG, mode, reg, offset);
+ return gen_rtx_raw_SUBREG (mode, reg, offset);
}
/* Generate a SUBREG representing the least-significant part of REG if MODE
@@ -532,7 +663,7 @@ gen_rtx VPARAMS ((enum rtx_code code, enum machine_mode mode, ...))
HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT);
HOST_WIDE_INT arg1 = va_arg (p, HOST_WIDE_INT);
- rt_val = gen_rtx_CONST_DOUBLE (mode, arg0, arg1);
+ rt_val = immed_double_const (arg0, arg1, mode);
}
break;
@@ -671,12 +802,7 @@ gen_reg_rtx (mode)
which makes much better code. Besides, allocating DCmode
pseudos overstrains reload on some machines like the 386. */
rtx realpart, imagpart;
- int size = GET_MODE_UNIT_SIZE (mode);
- enum machine_mode partmode
- = mode_for_size (size * BITS_PER_UNIT,
- (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
- ? MODE_FLOAT : MODE_INT),
- 0);
+ enum machine_mode partmode = GET_MODE_INNER (mode);
realpart = gen_reg_rtx (partmode);
imagpart = gen_reg_rtx (partmode);
@@ -693,17 +819,17 @@ gen_reg_rtx (mode)
rtx *new1;
tree *new2;
- new = xrealloc (f->emit->regno_pointer_align, old_size * 2);
+ new = ggc_realloc (f->emit->regno_pointer_align, old_size * 2);
memset (new + old_size, 0, old_size);
f->emit->regno_pointer_align = (unsigned char *) new;
- new1 = (rtx *) xrealloc (f->emit->x_regno_reg_rtx,
- old_size * 2 * sizeof (rtx));
+ new1 = (rtx *) ggc_realloc (f->emit->x_regno_reg_rtx,
+ old_size * 2 * sizeof (rtx));
memset (new1 + old_size, 0, old_size * sizeof (rtx));
regno_reg_rtx = new1;
- new2 = (tree *) xrealloc (f->emit->regno_decl,
- old_size * 2 * sizeof (tree));
+ new2 = (tree *) ggc_realloc (f->emit->regno_decl,
+ old_size * 2 * sizeof (tree));
memset (new2 + old_size, 0, old_size * sizeof (tree));
f->emit->regno_decl = new2;
@@ -799,7 +925,11 @@ subreg_hard_regno (x, check_mode)
abort ();
if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
abort ();
-
+#ifdef ENABLE_CHECKING
+ if (!subreg_offset_representable_p (REGNO (reg), GET_MODE (reg),
+ SUBREG_BYTE (x), mode))
+ abort ();
+#endif
/* Catch non-congruent offsets too. */
byte_offset = SUBREG_BYTE (x);
if ((byte_offset % GET_MODE_SIZE (mode)) != 0)
@@ -866,8 +996,12 @@ gen_lowpart_common (mode, x)
return gen_rtx_fmt_e (GET_CODE (x), mode, XEXP (x, 0));
}
else if (GET_CODE (x) == SUBREG || GET_CODE (x) == REG
- || GET_CODE (x) == CONCAT)
+ || GET_CODE (x) == CONCAT || GET_CODE (x) == CONST_VECTOR)
return simplify_gen_subreg (mode, x, GET_MODE (x), offset);
+ else if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+ && GET_MODE (x) == VOIDmode)
+ return simplify_gen_subreg (mode, x, int_mode_for_mode (mode), offset);
/* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits
from the low-order part of the constant. */
else if ((GET_MODE_CLASS (mode) == MODE_INT
@@ -900,94 +1034,7 @@ gen_lowpart_common (mode, x)
}
}
-#ifndef REAL_ARITHMETIC
- /* If X is an integral constant but we want it in floating-point, it
- must be the case that we have a union of an integer and a floating-point
- value. If the machine-parameters allow it, simulate that union here
- and return the result. The two-word and single-word cases are
- different. */
-
- else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
- && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
- || flag_pretend_float)
- && GET_MODE_CLASS (mode) == MODE_FLOAT
- && GET_MODE_SIZE (mode) == UNITS_PER_WORD
- && GET_CODE (x) == CONST_INT
- && sizeof (float) * HOST_BITS_PER_CHAR == HOST_BITS_PER_WIDE_INT)
- {
- union {HOST_WIDE_INT i; float d; } u;
-
- u.i = INTVAL (x);
- return CONST_DOUBLE_FROM_REAL_VALUE (u.d, mode);
- }
- else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
- && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
- || flag_pretend_float)
- && GET_MODE_CLASS (mode) == MODE_FLOAT
- && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
- && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
- && GET_MODE (x) == VOIDmode
- && (sizeof (double) * HOST_BITS_PER_CHAR
- == 2 * HOST_BITS_PER_WIDE_INT))
- {
- union {HOST_WIDE_INT i[2]; double d; } u;
- HOST_WIDE_INT low, high;
-
- if (GET_CODE (x) == CONST_INT)
- low = INTVAL (x), high = low >> (HOST_BITS_PER_WIDE_INT -1);
- else
- low = CONST_DOUBLE_LOW (x), high = CONST_DOUBLE_HIGH (x);
-#ifdef HOST_WORDS_BIG_ENDIAN
- u.i[0] = high, u.i[1] = low;
-#else
- u.i[0] = low, u.i[1] = high;
-#endif
- return CONST_DOUBLE_FROM_REAL_VALUE (u.d, mode);
- }
-
- /* 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. */
-
- else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
- && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
- || flag_pretend_float)
- && (GET_MODE_CLASS (mode) == MODE_INT
- || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
- && GET_CODE (x) == CONST_DOUBLE
- && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
- && GET_MODE_BITSIZE (mode) == BITS_PER_WORD)
- return constant_subword (x, (offset / UNITS_PER_WORD), 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
- integer. Only do this is the host and target parameters are
- compatible. */
-
- else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
- && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
- || flag_pretend_float)
- && (GET_MODE_CLASS (mode) == MODE_INT
- || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
- && GET_CODE (x) == CONST_DOUBLE
- && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
- && GET_MODE_BITSIZE (mode) == 2 * BITS_PER_WORD)
- {
- rtx lowpart, highpart;
-
- lowpart = constant_subword (x,
- (offset / UNITS_PER_WORD) + WORDS_BIG_ENDIAN,
- GET_MODE (x));
- highpart = constant_subword (x,
- (offset / UNITS_PER_WORD) + (! WORDS_BIG_ENDIAN),
- GET_MODE (x));
- if (lowpart && GET_CODE (lowpart) == CONST_INT
- && highpart && GET_CODE (highpart) == CONST_INT)
- return immed_double_const (INTVAL (lowpart), INTVAL (highpart), mode);
- }
-#else /* ifndef REAL_ARITHMETIC */
-
- /* When we have a FP emulator, we can handle all conversions between
+ /* The floating-point emulator can handle all conversions between
FP and integer operands. This simplifies reload because it
doesn't have to deal with constructs like (subreg:DI
(const_double:SF ...)) or (subreg:DF (const_int ...)). */
@@ -997,22 +1044,21 @@ gen_lowpart_common (mode, x)
else if (GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_MODE_BITSIZE (mode) == 32
&& GET_CODE (x) == CONST_INT)
- {
+ {
REAL_VALUE_TYPE r;
- HOST_WIDE_INT i;
+ long i = INTVAL (x);
- i = INTVAL (x);
- r = REAL_VALUE_FROM_TARGET_SINGLE (i);
+ real_from_target (&r, &i, mode);
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
- }
+ }
else if (GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_MODE_BITSIZE (mode) == 64
&& (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
&& GET_MODE (x) == VOIDmode)
{
REAL_VALUE_TYPE r;
- HOST_WIDE_INT i[2];
HOST_WIDE_INT low, high;
+ long i[2];
if (GET_CODE (x) == CONST_INT)
{
@@ -1025,18 +1071,17 @@ gen_lowpart_common (mode, x)
high = CONST_DOUBLE_HIGH (x);
}
-#if HOST_BITS_PER_WIDE_INT == 32
+ if (HOST_BITS_PER_WIDE_INT > 32)
+ high = low >> 31 >> 1;
+
/* REAL_VALUE_TARGET_DOUBLE takes the addressing order of the
target machine. */
if (WORDS_BIG_ENDIAN)
i[0] = high, i[1] = low;
else
i[0] = low, i[1] = high;
-#else
- i[0] = low;
-#endif
- r = REAL_VALUE_FROM_TARGET_DOUBLE (i);
+ real_from_target (&r, i, mode);
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
}
else if ((GET_MODE_CLASS (mode) == MODE_INT
@@ -1054,16 +1099,16 @@ gen_lowpart_common (mode, x)
switch (GET_MODE_BITSIZE (GET_MODE (x)))
{
case 32:
- REAL_VALUE_TO_TARGET_SINGLE (r, i[3 * endian]);
+ REAL_VALUE_TO_TARGET_SINGLE (r, i[3 * endian]);
i[1] = 0;
i[2] = 0;
- i[3 - 3 * endian] = 0;
- break;
+ i[3 - 3 * endian] = 0;
+ break;
case 64:
- REAL_VALUE_TO_TARGET_DOUBLE (r, i + 2 * endian);
+ REAL_VALUE_TO_TARGET_DOUBLE (r, i + 2 * endian);
i[2 - 2 * endian] = 0;
i[3 - 2 * endian] = 0;
- break;
+ break;
case 96:
REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, i + endian);
i[3 - 3 * endian] = 0;
@@ -1089,7 +1134,6 @@ gen_lowpart_common (mode, x)
mode);
#endif
}
-#endif /* ifndef REAL_ARITHMETIC */
/* Otherwise, we can't do this. */
return 0;
@@ -1232,8 +1276,8 @@ gen_highpart (mode, x)
be VOIDmode constant. */
rtx
gen_highpart_mode (outermode, innermode, exp)
- enum machine_mode outermode, innermode;
- rtx exp;
+ enum machine_mode outermode, innermode;
+ rtx exp;
{
if (GET_MODE (exp) != VOIDmode)
{
@@ -1244,6 +1288,7 @@ gen_highpart_mode (outermode, innermode, exp)
return simplify_gen_subreg (outermode, exp, innermode,
subreg_highpart_offset (outermode, innermode));
}
+
/* Return offset in bytes to get OUTERMODE low part
of the value in mode INNERMODE stored in memory in target format. */
@@ -1275,7 +1320,7 @@ subreg_highpart_offset (outermode, innermode)
int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode));
if (GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode))
- abort ();
+ abort ();
if (difference > 0)
{
@@ -1323,7 +1368,6 @@ constant_subword (op, offset, mode)
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD)
return op;
-#ifdef REAL_ARITHMETIC
/* The output is some bits, the width of the target machine's word.
A wider-word host can surely hold them in a CONST_INT. A narrower-word
host can't. */
@@ -1402,32 +1446,10 @@ constant_subword (op, offset, mode)
else
abort ();
}
-#else /* no REAL_ARITHMETIC */
- if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
- && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
- || flag_pretend_float)
- && GET_MODE_CLASS (mode) == MODE_FLOAT
- && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
- && GET_CODE (op) == CONST_DOUBLE)
- {
- /* The constant is stored in the host's word-ordering,
- but we want to access it in the target's word-ordering. Some
- compilers don't like a conditional inside macro args, so we have two
- copies of the return. */
-#ifdef HOST_WORDS_BIG_ENDIAN
- return GEN_INT (offset == WORDS_BIG_ENDIAN
- ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
-#else
- return GEN_INT (offset != WORDS_BIG_ENDIAN
- ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
-#endif
- }
-#endif /* no REAL_ARITHMETIC */
/* Single word float is a little harder, since single- and double-word
values often do not have the same high-order bits. We have already
verified that we want the only defined word of the single-word value. */
-#ifdef REAL_ARITHMETIC
if (GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_MODE_BITSIZE (mode) == 32
&& GET_CODE (op) == CONST_DOUBLE)
@@ -1451,40 +1473,6 @@ constant_subword (op, offset, mode)
return GEN_INT (val);
}
-#else
- 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)
- {
- double d;
- union {float f; HOST_WIDE_INT i; } u;
-
- REAL_VALUE_FROM_CONST_DOUBLE (d, op);
-
- 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.
Convert to proper endianness now since these cases need it.
@@ -1680,10 +1668,10 @@ component_ref_for_mem_expr (ref)
|| TREE_CODE (inner) == VIEW_CONVERT_EXPR
|| TREE_CODE (inner) == SAVE_EXPR
|| TREE_CODE (inner) == PLACEHOLDER_EXPR)
- if (TREE_CODE (inner) == PLACEHOLDER_EXPR)
- inner = find_placeholder (inner, &placeholder_ptr);
- else
- inner = TREE_OPERAND (inner, 0);
+ if (TREE_CODE (inner) == PLACEHOLDER_EXPR)
+ inner = find_placeholder (inner, &placeholder_ptr);
+ else
+ inner = TREE_OPERAND (inner, 0);
if (! DECL_P (inner))
inner = NULL_TREE;
@@ -1786,7 +1774,7 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos)
size = (DECL_SIZE_UNIT (t)
&& host_integerp (DECL_SIZE_UNIT (t), 1)
? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0);
- align = DECL_ALIGN (t);
+ align = DECL_ALIGN (t);
}
/* If this is a constant, we know the alignment. */
@@ -1816,11 +1804,14 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos)
else if (TREE_CODE (t) == ARRAY_REF)
{
tree off_tree = size_zero_node;
+ /* We can't modify t, because we use it at the end of the
+ function. */
+ tree t2 = t;
do
{
- tree index = TREE_OPERAND (t, 1);
- tree array = TREE_OPERAND (t, 0);
+ tree index = TREE_OPERAND (t2, 1);
+ tree array = TREE_OPERAND (t2, 0);
tree domain = TYPE_DOMAIN (TREE_TYPE (array));
tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0);
tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array)));
@@ -1838,7 +1829,7 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos)
component to one. */
if (! TREE_CONSTANT (index)
&& contains_placeholder_p (index))
- index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, t);
+ index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, t2);
if (! TREE_CONSTANT (unit_size)
&& contains_placeholder_p (unit_size))
unit_size = build (WITH_RECORD_EXPR, sizetype,
@@ -1850,28 +1841,28 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos)
index,
unit_size)),
off_tree));
- t = TREE_OPERAND (t, 0);
+ t2 = TREE_OPERAND (t2, 0);
}
- while (TREE_CODE (t) == ARRAY_REF);
+ while (TREE_CODE (t2) == ARRAY_REF);
- if (DECL_P (t))
+ if (DECL_P (t2))
{
- expr = t;
+ expr = t2;
offset = NULL;
if (host_integerp (off_tree, 1))
{
HOST_WIDE_INT ioff = tree_low_cst (off_tree, 1);
HOST_WIDE_INT aoff = (ioff & -ioff) * BITS_PER_UNIT;
- align = DECL_ALIGN (t);
+ align = DECL_ALIGN (t2);
if (aoff && aoff < align)
align = aoff;
offset = GEN_INT (ioff);
apply_bitpos = bitpos;
}
}
- else if (TREE_CODE (t) == COMPONENT_REF)
+ else if (TREE_CODE (t2) == COMPONENT_REF)
{
- expr = component_ref_for_mem_expr (t);
+ expr = component_ref_for_mem_expr (t2);
if (host_integerp (off_tree, 1))
{
offset = GEN_INT (tree_low_cst (off_tree, 1));
@@ -1881,10 +1872,10 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos)
the size we got from the type? */
}
else if (flag_argument_noalias > 1
- && TREE_CODE (t) == INDIRECT_REF
- && TREE_CODE (TREE_OPERAND (t, 0)) == PARM_DECL)
+ && TREE_CODE (t2) == INDIRECT_REF
+ && TREE_CODE (TREE_OPERAND (t2, 0)) == PARM_DECL)
{
- expr = t;
+ expr = t2;
offset = NULL;
}
}
@@ -1942,7 +1933,7 @@ set_mem_alias_set (mem, set)
rtx mem;
HOST_WIDE_INT set;
{
-#ifdef ENABLE_CHECKING
+#ifdef ENABLE_CHECKING
/* If the new and old alias sets don't conflict, something is wrong. */
if (!alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)))
abort ();
@@ -2082,7 +2073,7 @@ adjust_address_1 (memref, mode, offset, validate, adjust)
unsigned int memalign = MEM_ALIGN (memref);
/* ??? Prefer to create garbage instead of creating shared rtl.
- This may happen even if offset is non-zero -- consider
+ This may happen even if offset is nonzero -- consider
(plus (plus reg reg) const_int) -- so do this always. */
addr = copy_rtx (addr);
@@ -2160,7 +2151,7 @@ offset_address (memref, offset, pow2)
new = simplify_gen_binary (PLUS, Pmode, addr, offset);
- /* At this point we don't know _why_ the address is invalid. It
+ /* At this point we don't know _why_ the address is invalid. It
could have secondary memory refereces, multiplies or anything.
However, if we did go and rearrange things, we can wind up not
@@ -2187,7 +2178,7 @@ offset_address (memref, offset, pow2)
GET_MODE (new));
return new;
}
-
+
/* Return a memory reference like MEMREF, but with its address changed to
ADDR. The caller is asserting that the actual piece of memory pointed
to is the same, just the form of the address is being changed, such as
@@ -2299,14 +2290,8 @@ widen_memory_access (memref, mode, offset)
rtx
gen_label_rtx ()
{
- rtx label;
-
- label = gen_rtx_CODE_LABEL (VOIDmode, 0, NULL_RTX,
- NULL_RTX, label_num++, NULL, NULL);
-
- LABEL_NUSES (label) = 0;
- LABEL_ALTERNATE_NAME (label) = NULL;
- return label;
+ return gen_rtx_CODE_LABEL (VOIDmode, 0, NULL_RTX, NULL_RTX,
+ NULL, label_num++, NULL);
}
/* For procedure integration. */
@@ -2362,22 +2347,6 @@ restore_emit_status (p)
struct function *p ATTRIBUTE_UNUSED;
{
last_label_num = 0;
- clear_emit_caches ();
-}
-
-/* Clear out all parts of the state in F that can safely be discarded
- after the function has been compiled, to let garbage collection
- reclaim the memory. */
-
-void
-free_emit_status (f)
- struct function *f;
-{
- free (f->emit->x_regno_reg_rtx);
- free (f->emit->regno_pointer_align);
- free (f->emit->regno_decl);
- free (f->emit);
- f->emit = NULL;
}
/* Go through all the RTL insn bodies and copy any invalid shared
@@ -2532,11 +2501,11 @@ copy_most_rtx (orig, may_share)
copy = rtx_alloc (code);
PUT_MODE (copy, GET_MODE (orig));
- copy->in_struct = orig->in_struct;
- copy->volatil = orig->volatil;
- copy->unchanging = orig->unchanging;
- copy->integrated = orig->integrated;
- copy->frame_related = orig->frame_related;
+ RTX_FLAG (copy, in_struct) = RTX_FLAG (orig, in_struct);
+ RTX_FLAG (copy, volatil) = RTX_FLAG (orig, volatil);
+ RTX_FLAG (copy, unchanging) = RTX_FLAG (orig, unchanging);
+ RTX_FLAG (copy, integrated) = RTX_FLAG (orig, integrated);
+ RTX_FLAG (copy, frame_related) = RTX_FLAG (orig, frame_related);
format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
@@ -2669,7 +2638,7 @@ copy_rtx_if_shared (orig)
/* This rtx may not be shared. If it has already been seen,
replace it with a copy of itself. */
- if (x->used)
+ if (RTX_FLAG (x, used))
{
rtx copy;
@@ -2680,7 +2649,7 @@ copy_rtx_if_shared (orig)
x = copy;
copied = 1;
}
- x->used = 1;
+ RTX_FLAG (x, used) = 1;
/* Now scan the subexpressions recursively.
We can store any replaced subexpressions directly into X
@@ -2759,7 +2728,7 @@ reset_used_flags (x)
break;
}
- x->used = 0;
+ RTX_FLAG (x, used) = 0;
format_ptr = GET_RTX_FORMAT (code);
for (i = 0; i < GET_RTX_LENGTH (code); i++)
@@ -2826,6 +2795,17 @@ get_insns ()
return first_insn;
}
+/* Specify a new insn as the first in the chain. */
+
+void
+set_first_insn (insn)
+ rtx insn;
+{
+ if (PREV_INSN (insn) != 0)
+ abort ();
+ first_insn = insn;
+}
+
/* Return the last insn emitted in current sequence or current function. */
rtx
@@ -2859,6 +2839,42 @@ get_last_insn_anywhere ()
return 0;
}
+/* Return the first nonnote insn emitted in current sequence or current
+ function. This routine looks inside SEQUENCEs. */
+
+rtx
+get_first_nonnote_insn ()
+{
+ rtx insn = first_insn;
+
+ while (insn)
+ {
+ insn = next_insn (insn);
+ if (insn == 0 || GET_CODE (insn) != NOTE)
+ break;
+ }
+
+ return insn;
+}
+
+/* Return the last nonnote insn emitted in current sequence or current
+ function. This routine looks inside SEQUENCEs. */
+
+rtx
+get_last_nonnote_insn ()
+{
+ rtx insn = last_insn;
+
+ while (insn)
+ {
+ insn = previous_insn (insn);
+ if (insn == 0 || GET_CODE (insn) != NOTE)
+ break;
+ }
+
+ return insn;
+}
+
/* Return a number larger than any instruction's uid in this function. */
int
@@ -3151,8 +3167,8 @@ prev_cc0_setter (insn)
/* Increment the label uses for all labels present in rtx. */
static void
-mark_label_nuses(x)
- rtx x;
+mark_label_nuses (x)
+ rtx x;
{
enum rtx_code code;
int i, j;
@@ -3166,9 +3182,9 @@ mark_label_nuses(x)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- mark_label_nuses (XEXP (x, i));
+ mark_label_nuses (XEXP (x, i));
else if (fmt[i] == 'E')
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
mark_label_nuses (XVECEXP (x, i, j));
}
}
@@ -3177,7 +3193,7 @@ mark_label_nuses(x)
/* Try splitting insns that can be split for better scheduling.
PAT is the pattern which might split.
TRIAL is the insn providing PAT.
- LAST is non-zero if we should return the last insn of the sequence produced.
+ LAST is nonzero if we should return the last insn of the sequence produced.
If this routine succeeds in splitting, it returns the first or last
replacement insn depending on the value of LAST. Otherwise, it
@@ -3194,6 +3210,8 @@ try_split (pat, trial, last)
rtx tem;
rtx note, seq;
int probability;
+ rtx insn_last, insn;
+ int njumps = 0;
if (any_condjump_p (trial)
&& (note = find_reg_note (trial, REG_BR_PROB, 0)))
@@ -3212,145 +3230,147 @@ try_split (pat, trial, last)
after = NEXT_INSN (after);
}
- if (seq)
+ if (!seq)
+ return trial;
+
+ /* Avoid infinite loop if any insn of the result matches
+ the original pattern. */
+ insn_last = seq;
+ while (1)
+ {
+ if (INSN_P (insn_last)
+ && rtx_equal_p (PATTERN (insn_last), pat))
+ return trial;
+ if (!NEXT_INSN (insn_last))
+ break;
+ insn_last = NEXT_INSN (insn_last);
+ }
+
+ /* Mark labels. */
+ for (insn = insn_last; insn ; insn = PREV_INSN (insn))
{
- /* SEQ can either be a SEQUENCE or the pattern of a single insn.
- The latter case will normally arise only when being done so that
- it, in turn, will be split (SFmode on the 29k is an example). */
- if (GET_CODE (seq) == SEQUENCE)
+ if (GET_CODE (insn) == JUMP_INSN)
{
- int i, njumps = 0;
-
- /* Avoid infinite loop if any insn of the result matches
- the original pattern. */
- for (i = 0; i < XVECLEN (seq, 0); i++)
- if (GET_CODE (XVECEXP (seq, 0, i)) == INSN
- && rtx_equal_p (PATTERN (XVECEXP (seq, 0, i)), pat))
- return trial;
-
- /* Mark labels. */
- for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (seq, 0, i)) == JUMP_INSN)
- {
- rtx insn = XVECEXP (seq, 0, i);
- mark_jump_label (PATTERN (insn),
- XVECEXP (seq, 0, i), 0);
- njumps++;
- if (probability != -1
- && any_condjump_p (insn)
- && !find_reg_note (insn, REG_BR_PROB, 0))
- {
- /* We can preserve the REG_BR_PROB notes only if exactly
- one jump is created, otherwise the machine description
- is responsible for this step using
- split_branch_probability variable. */
- if (njumps != 1)
- abort ();
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_BR_PROB,
- GEN_INT (probability),
- REG_NOTES (insn));
- }
- }
-
- /* If we are splitting a CALL_INSN, look for the CALL_INSN
- in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it. */
- if (GET_CODE (trial) == CALL_INSN)
- for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (seq, 0, i)) == CALL_INSN)
- CALL_INSN_FUNCTION_USAGE (XVECEXP (seq, 0, i))
- = CALL_INSN_FUNCTION_USAGE (trial);
-
- /* Copy notes, particularly those related to the CFG. */
- for (note = REG_NOTES (trial); note ; note = XEXP (note, 1))
+ mark_jump_label (PATTERN (insn), insn, 0);
+ njumps++;
+ if (probability != -1
+ && any_condjump_p (insn)
+ && !find_reg_note (insn, REG_BR_PROB, 0))
{
- switch (REG_NOTE_KIND (note))
- {
- case REG_EH_REGION:
- for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
- {
- rtx insn = XVECEXP (seq, 0, i);
- if (GET_CODE (insn) == CALL_INSN
- || (flag_non_call_exceptions
- && may_trap_p (PATTERN (insn))))
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_EH_REGION,
- XEXP (note, 0),
- REG_NOTES (insn));
- }
- break;
+ /* We can preserve the REG_BR_PROB notes only if exactly
+ one jump is created, otherwise the machine description
+ is responsible for this step using
+ split_branch_probability variable. */
+ if (njumps != 1)
+ abort ();
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_BR_PROB,
+ GEN_INT (probability),
+ REG_NOTES (insn));
+ }
+ }
+ }
- case REG_NORETURN:
- case REG_SETJMP:
- case REG_ALWAYS_RETURN:
- for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
- {
- rtx insn = XVECEXP (seq, 0, i);
- if (GET_CODE (insn) == CALL_INSN)
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
- XEXP (note, 0),
- REG_NOTES (insn));
- }
- break;
+ /* If we are splitting a CALL_INSN, look for the CALL_INSN
+ in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it. */
+ if (GET_CODE (trial) == CALL_INSN)
+ {
+ for (insn = insn_last; insn ; insn = PREV_INSN (insn))
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ CALL_INSN_FUNCTION_USAGE (insn)
+ = CALL_INSN_FUNCTION_USAGE (trial);
+ SIBLING_CALL_P (insn) = SIBLING_CALL_P (trial);
+ }
+ }
- case REG_NON_LOCAL_GOTO:
- for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
- {
- rtx insn = XVECEXP (seq, 0, i);
- if (GET_CODE (insn) == JUMP_INSN)
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
- XEXP (note, 0),
- REG_NOTES (insn));
- }
- break;
+ /* Copy notes, particularly those related to the CFG. */
+ for (note = REG_NOTES (trial); note; note = XEXP (note, 1))
+ {
+ switch (REG_NOTE_KIND (note))
+ {
+ case REG_EH_REGION:
+ insn = insn_last;
+ while (insn != NULL_RTX)
+ {
+ if (GET_CODE (insn) == CALL_INSN
+ || (flag_non_call_exceptions
+ && may_trap_p (PATTERN (insn))))
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_EH_REGION,
+ XEXP (note, 0),
+ REG_NOTES (insn));
+ insn = PREV_INSN (insn);
+ }
+ break;
- default:
- break;
- }
+ case REG_NORETURN:
+ case REG_SETJMP:
+ case REG_ALWAYS_RETURN:
+ insn = insn_last;
+ while (insn != NULL_RTX)
+ {
+ if (GET_CODE (insn) == CALL_INSN)
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
+ XEXP (note, 0),
+ REG_NOTES (insn));
+ insn = PREV_INSN (insn);
+ }
+ break;
+
+ case REG_NON_LOCAL_GOTO:
+ insn = insn_last;
+ while (insn != NULL_RTX)
+ {
+ if (GET_CODE (insn) == JUMP_INSN)
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
+ XEXP (note, 0),
+ REG_NOTES (insn));
+ insn = PREV_INSN (insn);
}
+ break;
- /* If there are LABELS inside the split insns increment the
- usage count so we don't delete the label. */
- if (GET_CODE (trial) == INSN)
- for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (seq, 0, i)) == INSN)
- mark_label_nuses (PATTERN (XVECEXP (seq, 0, i)));
-
- tem = emit_insn_after (seq, trial);
-
- delete_related_insns (trial);
- if (has_barrier)
- emit_barrier_after (tem);
-
- /* Recursively call try_split for each new insn created; by the
- time control returns here that insn will be fully split, so
- set LAST and continue from the insn after the one returned.
- We can't use next_active_insn here since AFTER may be a note.
- Ignore deleted insns, which can be occur if not optimizing. */
- for (tem = NEXT_INSN (before); tem != after; tem = NEXT_INSN (tem))
- if (! INSN_DELETED_P (tem) && INSN_P (tem))
- tem = try_split (PATTERN (tem), tem, 1);
+ default:
+ break;
}
- /* Avoid infinite loop if the result matches the original pattern. */
- else if (rtx_equal_p (seq, pat))
- return trial;
- else
+ }
+
+ /* If there are LABELS inside the split insns increment the
+ usage count so we don't delete the label. */
+ if (GET_CODE (trial) == INSN)
+ {
+ insn = insn_last;
+ while (insn != NULL_RTX)
{
- PATTERN (trial) = seq;
- INSN_CODE (trial) = -1;
- try_split (seq, trial, last);
- }
+ if (GET_CODE (insn) == INSN)
+ mark_label_nuses (PATTERN (insn));
- /* Return either the first or the last insn, depending on which was
- requested. */
- return last
- ? (after ? PREV_INSN (after) : last_insn)
- : NEXT_INSN (before);
+ insn = PREV_INSN (insn);
+ }
}
- return trial;
+ tem = emit_insn_after_scope (seq, trial, INSN_SCOPE (trial));
+
+ delete_insn (trial);
+ if (has_barrier)
+ emit_barrier_after (tem);
+
+ /* Recursively call try_split for each new insn created; by the
+ time control returns here that insn will be fully split, so
+ set LAST and continue from the insn after the one returned.
+ We can't use next_active_insn here since AFTER may be a note.
+ Ignore deleted insns, which can be occur if not optimizing. */
+ for (tem = NEXT_INSN (before); tem != after; tem = NEXT_INSN (tem))
+ if (! INSN_DELETED_P (tem) && INSN_P (tem))
+ tem = try_split (PATTERN (tem), tem, 1);
+
+ /* Return either the first or the last insn, depending on which was
+ requested. */
+ return last
+ ? (after ? PREV_INSN (after) : last_insn)
+ : NEXT_INSN (before);
}
/* Make and return an INSN rtx, initializing all its slots.
@@ -3369,6 +3389,8 @@ make_insn_raw (pattern)
INSN_CODE (insn) = -1;
LOG_LINKS (insn) = NULL;
REG_NOTES (insn) = NULL;
+ INSN_SCOPE (insn) = NULL;
+ BLOCK_FOR_INSN (insn) = NULL;
#ifdef ENABLE_RTL_CHECKING
if (insn
@@ -3385,7 +3407,7 @@ make_insn_raw (pattern)
return insn;
}
-/* Like `make_insn' but make a JUMP_INSN instead of an insn. */
+/* Like `make_insn_raw' but make a JUMP_INSN instead of an insn. */
static rtx
make_jump_insn_raw (pattern)
@@ -3401,11 +3423,13 @@ make_jump_insn_raw (pattern)
LOG_LINKS (insn) = NULL;
REG_NOTES (insn) = NULL;
JUMP_LABEL (insn) = NULL;
+ INSN_SCOPE (insn) = NULL;
+ BLOCK_FOR_INSN (insn) = NULL;
return insn;
}
-/* Like `make_insn' but make a CALL_INSN instead of an insn. */
+/* Like `make_insn_raw' but make a CALL_INSN instead of an insn. */
static rtx
make_call_insn_raw (pattern)
@@ -3421,6 +3445,8 @@ make_call_insn_raw (pattern)
LOG_LINKS (insn) = NULL;
REG_NOTES (insn) = NULL;
CALL_INSN_FUNCTION_USAGE (insn) = NULL;
+ INSN_SCOPE (insn) = NULL;
+ BLOCK_FOR_INSN (insn) = NULL;
return insn;
}
@@ -3485,11 +3511,13 @@ add_insn_after (insn, after)
abort ();
}
- if (basic_block_for_insn
- && (unsigned int) INSN_UID (after) < basic_block_for_insn->num_elements
+ if (GET_CODE (after) != BARRIER
+ && GET_CODE (insn) != BARRIER
&& (bb = BLOCK_FOR_INSN (after)))
{
set_block_for_insn (insn, bb);
+ if (INSN_P (insn))
+ bb->flags |= BB_DIRTY;
/* Should not happen as first in the BB is always
either NOTE or LABEL. */
if (bb->end == after
@@ -3552,11 +3580,13 @@ add_insn_before (insn, before)
abort ();
}
- if (basic_block_for_insn
- && (unsigned int) INSN_UID (before) < basic_block_for_insn->num_elements
+ if (GET_CODE (before) != BARRIER
+ && GET_CODE (insn) != BARRIER
&& (bb = BLOCK_FOR_INSN (before)))
{
set_block_for_insn (insn, bb);
+ if (INSN_P (insn))
+ bb->flags |= BB_DIRTY;
/* Should not happen as first in the BB is always
either NOTE or LABEl. */
if (bb->head == insn
@@ -3630,10 +3660,11 @@ remove_insn (insn)
if (stack == 0)
abort ();
}
- if (basic_block_for_insn
- && (unsigned int) INSN_UID (insn) < basic_block_for_insn->num_elements
+ if (GET_CODE (insn) != BARRIER
&& (bb = BLOCK_FOR_INSN (insn)))
{
+ if (INSN_P (insn))
+ bb->flags |= BB_DIRTY;
if (bb->head == insn)
{
/* Never ever delete the basic block note without deleting whole
@@ -3706,19 +3737,18 @@ reorder_insns (from, to, after)
reorder_insns_nobb (from, to, after);
- if (basic_block_for_insn
- && (unsigned int) INSN_UID (after) < basic_block_for_insn->num_elements
+ if (GET_CODE (after) != BARRIER
&& (bb = BLOCK_FOR_INSN (after)))
{
rtx x;
-
- if (basic_block_for_insn
- && ((unsigned int) INSN_UID (from)
- < basic_block_for_insn->num_elements)
+ bb->flags |= BB_DIRTY;
+
+ if (GET_CODE (from) != BARRIER
&& (bb2 = BLOCK_FOR_INSN (from)))
{
if (bb2->end == to)
bb2->end = prev;
+ bb2->flags |= BB_DIRTY;
}
if (bb->end == after)
@@ -3740,7 +3770,7 @@ find_line_note (insn)
for (; insn; insn = PREV_INSN (insn))
if (GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) >= 0)
+ && NOTE_LINE_NUMBER (insn) >= 0)
break;
return insn;
@@ -3841,7 +3871,7 @@ remove_unnecessary_notes ()
then there is no PC range in the generated code that will
actually be in this block, so there's no point in
remembering the existence of the block. */
- for (tmp = PREV_INSN (insn); tmp ; tmp = PREV_INSN (tmp))
+ for (tmp = PREV_INSN (insn); tmp; tmp = PREV_INSN (tmp))
{
/* This block contains a real instruction. Note that we
don't include labels; if the only thing in the block
@@ -3885,76 +3915,173 @@ remove_unnecessary_notes ()
}
-/* Emit an insn of given code and pattern
- at a specified place within the doubly-linked list. */
+/* Emit insn(s) of given code and pattern
+ at a specified place within the doubly-linked list.
-/* Make an instruction with body PATTERN
- and output it before the instruction BEFORE. */
+ All of the emit_foo global entry points accept an object
+ X which is either an insn list or a PATTERN of a single
+ instruction.
+
+ There are thus a few canonical ways to generate code and
+ emit it at a specific place in the instruction stream. For
+ example, consider the instruction named SPOT and the fact that
+ we would like to emit some instructions before SPOT. We might
+ do it like this:
+
+ start_sequence ();
+ ... emit the new instructions ...
+ insns_head = get_insns ();
+ end_sequence ();
+
+ emit_insn_before (insns_head, SPOT);
+
+ It used to be common to generate SEQUENCE rtl instead, but that
+ is a relic of the past which no longer occurs. The reason is that
+ SEQUENCE rtl results in much fragmented RTL memory since the SEQUENCE
+ generated would almost certainly die right after it was created. */
+
+/* Make X be output before the instruction BEFORE. */
rtx
-emit_insn_before (pattern, before)
- rtx pattern, before;
+emit_insn_before (x, before)
+ rtx x, before;
{
- rtx insn = before;
+ rtx last = before;
+ rtx insn;
- if (GET_CODE (pattern) == SEQUENCE)
- {
- int i;
+#ifdef ENABLE_RTL_CHECKING
+ if (before == NULL_RTX)
+ abort ();
+#endif
+
+ if (x == NULL_RTX)
+ return last;
- for (i = 0; i < XVECLEN (pattern, 0); i++)
+ switch (GET_CODE (x))
+ {
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ insn = x;
+ while (insn)
{
- insn = XVECEXP (pattern, 0, i);
+ rtx next = NEXT_INSN (insn);
add_insn_before (insn, before);
+ last = insn;
+ insn = next;
}
- }
- else
- {
- insn = make_insn_raw (pattern);
- add_insn_before (insn, before);
+ break;
+
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ last = make_insn_raw (x);
+ add_insn_before (last, before);
+ break;
}
- return insn;
+ return last;
}
-/* Make an instruction with body PATTERN and code JUMP_INSN
+/* Make an instruction with body X and code JUMP_INSN
and output it before the instruction BEFORE. */
rtx
-emit_jump_insn_before (pattern, before)
- rtx pattern, before;
+emit_jump_insn_before (x, before)
+ rtx x, before;
{
- rtx insn;
+ rtx insn, last = NULL_RTX;
- if (GET_CODE (pattern) == SEQUENCE)
- insn = emit_insn_before (pattern, before);
- else
+#ifdef ENABLE_RTL_CHECKING
+ if (before == NULL_RTX)
+ abort ();
+#endif
+
+ switch (GET_CODE (x))
{
- insn = make_jump_insn_raw (pattern);
- add_insn_before (insn, before);
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ insn = x;
+ while (insn)
+ {
+ rtx next = NEXT_INSN (insn);
+ add_insn_before (insn, before);
+ last = insn;
+ insn = next;
+ }
+ break;
+
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ last = make_jump_insn_raw (x);
+ add_insn_before (last, before);
+ break;
}
- return insn;
+ return last;
}
-/* Make an instruction with body PATTERN and code CALL_INSN
+/* Make an instruction with body X and code CALL_INSN
and output it before the instruction BEFORE. */
rtx
-emit_call_insn_before (pattern, before)
- rtx pattern, before;
+emit_call_insn_before (x, before)
+ rtx x, before;
{
- rtx insn;
+ rtx last = NULL_RTX, insn;
- if (GET_CODE (pattern) == SEQUENCE)
- insn = emit_insn_before (pattern, before);
- else
+#ifdef ENABLE_RTL_CHECKING
+ if (before == NULL_RTX)
+ abort ();
+#endif
+
+ switch (GET_CODE (x))
{
- insn = make_call_insn_raw (pattern);
- add_insn_before (insn, before);
- PUT_CODE (insn, CALL_INSN);
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ insn = x;
+ while (insn)
+ {
+ rtx next = NEXT_INSN (insn);
+ add_insn_before (insn, before);
+ last = insn;
+ insn = next;
+ }
+ break;
+
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ last = make_call_insn_raw (x);
+ add_insn_before (last, before);
+ break;
}
- return insn;
+ return last;
}
/* Make an insn of code BARRIER
@@ -4000,50 +4127,106 @@ emit_note_before (subtype, before)
INSN_UID (note) = cur_insn_uid++;
NOTE_SOURCE_FILE (note) = 0;
NOTE_LINE_NUMBER (note) = subtype;
+ BLOCK_FOR_INSN (note) = NULL;
add_insn_before (note, before);
return note;
}
-/* Make an insn of code INSN with body PATTERN
- and output it after the insn AFTER. */
+/* Helper for emit_insn_after, handles lists of instructions
+ efficiently. */
-rtx
-emit_insn_after (pattern, after)
- rtx pattern, after;
+static rtx emit_insn_after_1 PARAMS ((rtx, rtx));
+
+static rtx
+emit_insn_after_1 (first, after)
+ rtx first, after;
{
- rtx insn = after;
+ rtx last;
+ rtx after_after;
+ basic_block bb;
- if (GET_CODE (pattern) == SEQUENCE)
+ if (GET_CODE (after) != BARRIER
+ && (bb = BLOCK_FOR_INSN (after)))
{
- int i;
-
- for (i = 0; i < XVECLEN (pattern, 0); i++)
- {
- insn = XVECEXP (pattern, 0, i);
- add_insn_after (insn, after);
- after = insn;
- }
+ bb->flags |= BB_DIRTY;
+ for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
+ if (GET_CODE (last) != BARRIER)
+ set_block_for_insn (last, bb);
+ if (GET_CODE (last) != BARRIER)
+ set_block_for_insn (last, bb);
+ if (bb->end == after)
+ bb->end = last;
}
else
+ for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
+ continue;
+
+ after_after = NEXT_INSN (after);
+
+ NEXT_INSN (after) = first;
+ PREV_INSN (first) = after;
+ NEXT_INSN (last) = after_after;
+ if (after_after)
+ PREV_INSN (after_after) = last;
+
+ if (after == last_insn)
+ last_insn = last;
+ return last;
+}
+
+/* Make X be output after the insn AFTER. */
+
+rtx
+emit_insn_after (x, after)
+ rtx x, after;
+{
+ rtx last = after;
+
+#ifdef ENABLE_RTL_CHECKING
+ if (after == NULL_RTX)
+ abort ();
+#endif
+
+ if (x == NULL_RTX)
+ return last;
+
+ switch (GET_CODE (x))
{
- insn = make_insn_raw (pattern);
- add_insn_after (insn, after);
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ last = emit_insn_after_1 (x, after);
+ break;
+
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ last = make_insn_raw (x);
+ add_insn_after (last, after);
+ break;
}
- return insn;
+ return last;
}
/* Similar to emit_insn_after, except that line notes are to be inserted so
as to act as if this insn were at FROM. */
void
-emit_insn_after_with_line_notes (pattern, after, from)
- rtx pattern, after, from;
+emit_insn_after_with_line_notes (x, after, from)
+ rtx x, after, from;
{
rtx from_line = find_line_note (from);
rtx after_line = find_line_note (after);
- rtx insn = emit_insn_after (pattern, after);
+ rtx insn = emit_insn_after (x, after);
if (from_line)
emit_line_note_after (NOTE_SOURCE_FILE (from_line),
@@ -4056,24 +4239,84 @@ emit_insn_after_with_line_notes (pattern, after, from)
insn);
}
-/* Make an insn of code JUMP_INSN with body PATTERN
+/* Make an insn of code JUMP_INSN with body X
and output it after the insn AFTER. */
rtx
-emit_jump_insn_after (pattern, after)
- rtx pattern, after;
+emit_jump_insn_after (x, after)
+ rtx x, after;
{
- rtx insn;
+ rtx last;
- if (GET_CODE (pattern) == SEQUENCE)
- insn = emit_insn_after (pattern, after);
- else
+#ifdef ENABLE_RTL_CHECKING
+ if (after == NULL_RTX)
+ abort ();
+#endif
+
+ switch (GET_CODE (x))
{
- insn = make_jump_insn_raw (pattern);
- add_insn_after (insn, after);
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ last = emit_insn_after_1 (x, after);
+ break;
+
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ last = make_jump_insn_raw (x);
+ add_insn_after (last, after);
+ break;
}
- return insn;
+ return last;
+}
+
+/* Make an instruction with body X and code CALL_INSN
+ and output it after the instruction AFTER. */
+
+rtx
+emit_call_insn_after (x, after)
+ rtx x, after;
+{
+ rtx last;
+
+#ifdef ENABLE_RTL_CHECKING
+ if (after == NULL_RTX)
+ abort ();
+#endif
+
+ switch (GET_CODE (x))
+ {
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ last = emit_insn_after_1 (x, after);
+ break;
+
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ last = make_call_insn_raw (x);
+ add_insn_after (last, after);
+ break;
+ }
+
+ return last;
}
/* Make an insn of code BARRIER
@@ -4120,6 +4363,7 @@ emit_note_after (subtype, after)
INSN_UID (note) = cur_insn_uid++;
NOTE_SOURCE_FILE (note) = 0;
NOTE_LINE_NUMBER (note) = subtype;
+ BLOCK_FOR_INSN (note) = NULL;
add_insn_after (note, after);
return note;
}
@@ -4140,165 +4384,219 @@ emit_line_note_after (file, line, after)
return 0;
}
- note = rtx_alloc (NOTE);
+ note = rtx_alloc (NOTE);
INSN_UID (note) = cur_insn_uid++;
NOTE_SOURCE_FILE (note) = file;
NOTE_LINE_NUMBER (note) = line;
+ BLOCK_FOR_INSN (note) = NULL;
add_insn_after (note, after);
return note;
}
-/* Make an insn of code INSN with pattern PATTERN
- and add it to the end of the doubly-linked list.
- If PATTERN is a SEQUENCE, take the elements of it
- and emit an insn for each element.
-
- Returns the last insn emitted. */
-
+/* Like emit_insn_after, but set INSN_SCOPE according to SCOPE. */
rtx
-emit_insn (pattern)
- rtx pattern;
+emit_insn_after_scope (pattern, after, scope)
+ rtx pattern, after;
+ tree scope;
{
- rtx insn = last_insn;
+ rtx last = emit_insn_after (pattern, after);
- if (GET_CODE (pattern) == SEQUENCE)
+ after = NEXT_INSN (after);
+ while (1)
{
- int i;
-
- for (i = 0; i < XVECLEN (pattern, 0); i++)
- {
- insn = XVECEXP (pattern, 0, i);
- add_insn (insn);
- }
+ if (active_insn_p (after))
+ INSN_SCOPE (after) = scope;
+ if (after == last)
+ break;
+ after = NEXT_INSN (after);
}
- else
+ return last;
+}
+
+/* Like emit_jump_insn_after, but set INSN_SCOPE according to SCOPE. */
+rtx
+emit_jump_insn_after_scope (pattern, after, scope)
+ rtx pattern, after;
+ tree scope;
+{
+ rtx last = emit_jump_insn_after (pattern, after);
+
+ after = NEXT_INSN (after);
+ while (1)
{
- insn = make_insn_raw (pattern);
- add_insn (insn);
+ if (active_insn_p (after))
+ INSN_SCOPE (after) = scope;
+ if (after == last)
+ break;
+ after = NEXT_INSN (after);
}
-
- return insn;
+ return last;
}
-/* Emit the insns in a chain starting with INSN.
- Return the last insn emitted. */
-
+/* Like emit_call_insn_after, but set INSN_SCOPE according to SCOPE. */
rtx
-emit_insns (insn)
- rtx insn;
+emit_call_insn_after_scope (pattern, after, scope)
+ rtx pattern, after;
+ tree scope;
{
- rtx last = 0;
+ rtx last = emit_call_insn_after (pattern, after);
- while (insn)
+ after = NEXT_INSN (after);
+ while (1)
{
- rtx next = NEXT_INSN (insn);
- add_insn (insn);
- last = insn;
- insn = next;
+ if (active_insn_p (after))
+ INSN_SCOPE (after) = scope;
+ if (after == last)
+ break;
+ after = NEXT_INSN (after);
}
-
return last;
}
-/* Emit the insns in a chain starting with INSN and place them in front of
- the insn BEFORE. Return the last insn emitted. */
-
+/* Like emit_insn_before, but set INSN_SCOPE according to SCOPE. */
rtx
-emit_insns_before (insn, before)
- rtx insn;
- rtx before;
+emit_insn_before_scope (pattern, before, scope)
+ rtx pattern, before;
+ tree scope;
{
- rtx last = 0;
+ rtx first = PREV_INSN (before);
+ rtx last = emit_insn_before (pattern, before);
- while (insn)
+ first = NEXT_INSN (first);
+ while (1)
{
- rtx next = NEXT_INSN (insn);
- add_insn_before (insn, before);
- last = insn;
- insn = next;
+ if (active_insn_p (first))
+ INSN_SCOPE (first) = scope;
+ if (first == last)
+ break;
+ first = NEXT_INSN (first);
}
-
return last;
}
+
+/* Take X and emit it at the end of the doubly-linked
+ INSN list.
-/* Emit the insns in a chain starting with FIRST and place them in back of
- the insn AFTER. Return the last insn emitted. */
+ Returns the last insn emitted. */
rtx
-emit_insns_after (first, after)
- rtx first;
- rtx after;
+emit_insn (x)
+ rtx x;
{
- rtx last;
- rtx after_after;
- basic_block bb;
-
- if (!after)
- abort ();
+ rtx last = last_insn;
+ rtx insn;
- if (!first)
- return after;
+ if (x == NULL_RTX)
+ return last;
- if (basic_block_for_insn
- && (unsigned int) INSN_UID (after) < basic_block_for_insn->num_elements
- && (bb = BLOCK_FOR_INSN (after)))
+ switch (GET_CODE (x))
{
- for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
- set_block_for_insn (last, bb);
- set_block_for_insn (last, bb);
- if (bb->end == after)
- bb->end = last;
- }
- else
- for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
- continue;
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ insn = x;
+ while (insn)
+ {
+ rtx next = NEXT_INSN (insn);
+ add_insn (insn);
+ last = insn;
+ insn = next;
+ }
+ break;
- after_after = NEXT_INSN (after);
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
- NEXT_INSN (after) = first;
- PREV_INSN (first) = after;
- NEXT_INSN (last) = after_after;
- if (after_after)
- PREV_INSN (after_after) = last;
+ default:
+ last = make_insn_raw (x);
+ add_insn (last);
+ break;
+ }
- if (after == last_insn)
- last_insn = last;
return last;
}
-/* Make an insn of code JUMP_INSN with pattern PATTERN
+/* Make an insn of code JUMP_INSN with pattern X
and add it to the end of the doubly-linked list. */
rtx
-emit_jump_insn (pattern)
- rtx pattern;
+emit_jump_insn (x)
+ rtx x;
{
- if (GET_CODE (pattern) == SEQUENCE)
- return emit_insn (pattern);
- else
+ rtx last = NULL_RTX, insn;
+
+ switch (GET_CODE (x))
{
- rtx insn = make_jump_insn_raw (pattern);
- add_insn (insn);
- return insn;
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ insn = x;
+ while (insn)
+ {
+ rtx next = NEXT_INSN (insn);
+ add_insn (insn);
+ last = insn;
+ insn = next;
+ }
+ break;
+
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ last = make_jump_insn_raw (x);
+ add_insn (last);
+ break;
}
+
+ return last;
}
-/* Make an insn of code CALL_INSN with pattern PATTERN
+/* Make an insn of code CALL_INSN with pattern X
and add it to the end of the doubly-linked list. */
rtx
-emit_call_insn (pattern)
- rtx pattern;
+emit_call_insn (x)
+ rtx x;
{
- if (GET_CODE (pattern) == SEQUENCE)
- return emit_insn (pattern);
- else
+ rtx insn;
+
+ switch (GET_CODE (x))
{
- rtx insn = make_call_insn_raw (pattern);
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ insn = emit_insn (x);
+ break;
+
+#ifdef ENABLE_RTL_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ insn = make_call_insn_raw (x);
add_insn (insn);
- PUT_CODE (insn, CALL_INSN);
- return insn;
+ break;
}
+
+ return insn;
}
/* Add the label LABEL to the end of the doubly-linked list. */
@@ -4381,6 +4679,7 @@ emit_note (file, line)
INSN_UID (note) = cur_insn_uid++;
NOTE_SOURCE_FILE (note) = file;
NOTE_LINE_NUMBER (note) = line;
+ BLOCK_FOR_INSN (note) = NULL;
add_insn (note);
return note;
}
@@ -4515,6 +4814,9 @@ emit (x)
abort ();
}
+/* Space for free sequence stack entries. */
+static GTY ((deletable (""))) struct sequence_stack *free_sequence_stack;
+
/* Begin emitting insns to a sequence which can be packaged in an
RTL_EXPR. If this sequence will contain something that might cause
the compiler to pop arguments to function calls (because those
@@ -4528,7 +4830,13 @@ start_sequence ()
{
struct sequence_stack *tem;
- tem = (struct sequence_stack *) xmalloc (sizeof (struct sequence_stack));
+ if (free_sequence_stack != NULL)
+ {
+ tem = free_sequence_stack;
+ free_sequence_stack = tem->next;
+ }
+ else
+ tem = (struct sequence_stack *) ggc_alloc (sizeof (struct sequence_stack));
tem->next = seq_stack;
tem->first = first_insn;
@@ -4625,12 +4933,12 @@ pop_topmost_sequence ()
/* After emitting to a sequence, restore previous saved state.
To get the contents of the sequence just made, you must call
- `gen_sequence' *before* calling here.
+ `get_insns' *before* calling here.
If the compiler might have deferred popping arguments while
generating this sequence, and this sequence will not be immediately
inserted into the instruction stream, use do_pending_stack_adjust
- before calling gen_sequence. That will ensure that the deferred
+ before calling get_insns. That will ensure that the deferred
pops are inserted into this sequence, and not into some random
location in the instruction stream. See INHIBIT_DEFER_POP for more
information about deferred popping of arguments. */
@@ -4645,7 +4953,9 @@ end_sequence ()
seq_rtl_expr = tem->sequence_rtl_expr;
seq_stack = tem->next;
- free (tem);
+ memset (tem, 0, sizeof (*tem));
+ tem->next = free_sequence_stack;
+ free_sequence_stack = tem;
}
/* This works like end_sequence, but records the old sequence in FIRST
@@ -4657,7 +4967,7 @@ end_full_sequence (first, last)
{
*first = first_insn;
*last = last_insn;
- end_sequence();
+ end_sequence ();
}
/* Return 1 if currently emitting into a sequence. */
@@ -4667,45 +4977,6 @@ in_sequence_p ()
{
return seq_stack != 0;
}
-
-/* Generate a SEQUENCE rtx containing the insns already emitted
- to the current sequence.
-
- This is how the gen_... function from a DEFINE_EXPAND
- constructs the SEQUENCE that it returns. */
-
-rtx
-gen_sequence ()
-{
- rtx result;
- rtx tem;
- int i;
- int len;
-
- /* Count the insns in the chain. */
- len = 0;
- for (tem = first_insn; tem; tem = NEXT_INSN (tem))
- len++;
-
- /* If only one insn, return it rather than a SEQUENCE.
- (Now that we cache SEQUENCE expressions, it isn't worth special-casing
- the case of an empty list.)
- We only return the pattern of an insn if its code is INSN and it
- has no notes. This ensures that no information gets lost. */
- if (len == 1
- && ! RTX_FRAME_RELATED_P (first_insn)
- && GET_CODE (first_insn) == INSN
- /* Don't throw away any reg notes. */
- && REG_NOTES (first_insn) == 0)
- return PATTERN (first_insn);
-
- result = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (len));
-
- for (i = 0, tem = first_insn; tem; tem = NEXT_INSN (tem), i++)
- XVECEXP (result, 0, i) = tem;
-
- return result;
-}
/* Put the various virtual registers into REGNO_REG_RTX. */
@@ -4721,16 +4992,6 @@ init_virtual_regs (es)
ptr[VIRTUAL_CFA_REGNUM] = virtual_cfa_rtx;
}
-void
-clear_emit_caches ()
-{
- int i;
-
- /* Clear the start_sequence/gen_sequence cache. */
- for (i = 0; i < SEQUENCE_RESULT_SIZE; i++)
- sequence_result[i] = 0;
- free_insn = 0;
-}
/* Used by copy_insn_1 to avoid copying SCRATCHes more than once. */
static rtx copy_insn_scratch_in[MAX_RECOG_OPERANDS];
@@ -4818,14 +5079,14 @@ copy_insn_1 (orig)
/* We do not copy the USED flag, which is used as a mark bit during
walks over the RTL. */
- copy->used = 0;
+ RTX_FLAG (copy, used) = 0;
/* We do not copy JUMP, CALL, or FRAME_RELATED for INSNs. */
if (GET_RTX_CLASS (code) == 'i')
{
- copy->jump = 0;
- copy->call = 0;
- copy->frame_related = 0;
+ RTX_FLAG (copy, jump) = 0;
+ RTX_FLAG (copy, call) = 0;
+ RTX_FLAG (copy, frame_related) = 0;
}
format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
@@ -4913,7 +5174,7 @@ init_emit ()
{
struct function *f = cfun;
- f->emit = (struct emit_status *) xmalloc (sizeof (struct emit_status));
+ f->emit = (struct emit_status *) ggc_alloc (sizeof (struct emit_status));
first_insn = NULL;
last_insn = NULL;
seq_rtl_expr = NULL;
@@ -4925,21 +5186,26 @@ init_emit ()
last_label_num = 0;
seq_stack = NULL;
- clear_emit_caches ();
-
/* Init the tables that describe all the pseudo regs. */
f->emit->regno_pointer_align_length = LAST_VIRTUAL_REGISTER + 101;
f->emit->regno_pointer_align
- = (unsigned char *) xcalloc (f->emit->regno_pointer_align_length,
- sizeof (unsigned char));
+ = (unsigned char *) ggc_alloc_cleared (f->emit->regno_pointer_align_length
+ * sizeof (unsigned char));
regno_reg_rtx
- = (rtx *) xcalloc (f->emit->regno_pointer_align_length, sizeof (rtx));
+ = (rtx *) ggc_alloc_cleared (f->emit->regno_pointer_align_length
+ * sizeof (rtx));
f->emit->regno_decl
- = (tree *) xcalloc (f->emit->regno_pointer_align_length, sizeof (tree));
+ = (tree *) ggc_alloc_cleared (f->emit->regno_pointer_align_length
+ * sizeof (tree));
+
+ /* Put copies of all the hard registers into regno_reg_rtx. */
+ memcpy (regno_reg_rtx,
+ static_regno_reg_rtx,
+ FIRST_PSEUDO_REGISTER * sizeof (rtx));
/* Put copies of all the virtual register rtx into regno_reg_rtx. */
init_virtual_regs (f->emit);
@@ -4975,46 +5241,6 @@ init_emit ()
#endif
}
-/* Mark SS for GC. */
-
-static void
-mark_sequence_stack (ss)
- struct sequence_stack *ss;
-{
- while (ss)
- {
- ggc_mark_rtx (ss->first);
- ggc_mark_tree (ss->sequence_rtl_expr);
- ss = ss->next;
- }
-}
-
-/* Mark ES for GC. */
-
-void
-mark_emit_status (es)
- struct emit_status *es;
-{
- rtx *r;
- tree *t;
- int i;
-
- if (es == 0)
- return;
-
- for (i = es->regno_pointer_align_length, r = es->x_regno_reg_rtx,
- t = es->regno_decl;
- i > 0; --i, ++r, ++t)
- {
- ggc_mark_rtx (*r);
- ggc_mark_tree (*t);
- }
-
- mark_sequence_stack (es->sequence_stack);
- ggc_mark_tree (es->sequence_rtl_expr);
- ggc_mark_rtx (es->x_first_insn);
-}
-
/* Generate the constant 0. */
static rtx
@@ -5038,10 +5264,26 @@ gen_const_vector_0 (mode)
for (i = 0; i < units; ++i)
RTVEC_ELT (v, i) = CONST0_RTX (inner);
- tem = gen_rtx_CONST_VECTOR (mode, v);
+ tem = gen_rtx_raw_CONST_VECTOR (mode, v);
return tem;
}
+/* Generate a vector like gen_rtx_raw_CONST_VEC, but use the zero vector when
+ all elements are zero. */
+rtx
+gen_rtx_CONST_VECTOR (mode, v)
+ enum machine_mode mode;
+ rtvec v;
+{
+ rtx inner_zero = CONST0_RTX (GET_MODE_INNER (mode));
+ int i;
+
+ for (i = GET_MODE_NUNITS (mode) - 1; i >= 0; i--)
+ if (RTVEC_ELT (v, i) != inner_zero)
+ return gen_rtx_raw_CONST_VECTOR (mode, v);
+ return CONST0_RTX (mode);
+}
+
/* Create some permanent unique rtl objects shared between all functions.
LINE_NUMBERS is nonzero if line numbers are to be generated. */
@@ -5053,14 +5295,16 @@ init_emit_once (line_numbers)
enum machine_mode mode;
enum machine_mode double_mode;
- /* Initialize the CONST_INT and memory attribute hash tables. */
+ /* Initialize the CONST_INT, CONST_DOUBLE, and memory attribute hash
+ tables. */
const_int_htab = htab_create (37, const_int_htab_hash,
const_int_htab_eq, NULL);
- ggc_add_deletable_htab (const_int_htab, 0, 0);
+
+ const_double_htab = htab_create (37, const_double_htab_hash,
+ const_double_htab_eq, NULL);
mem_attrs_htab = htab_create (37, mem_attrs_htab_hash,
mem_attrs_htab_eq, NULL);
- ggc_add_deletable_htab (mem_attrs_htab, 0, mem_attrs_mark);
no_line_numbers = ! line_numbers;
@@ -5115,8 +5359,10 @@ init_emit_once (line_numbers)
gen_raw_REG (Pmode, VIRTUAL_OUTGOING_ARGS_REGNUM);
virtual_cfa_rtx = gen_raw_REG (Pmode, VIRTUAL_CFA_REGNUM);
- /* These rtx must be roots if GC is enabled. */
- ggc_add_rtx_root (global_rtl, GR_MAX);
+ /* Initialize RTL for commonly used hard registers. These are
+ copied into regno_reg_rtx as we begin to compile each function. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ static_regno_reg_rtx[i] = gen_raw_REG (reg_raw_mode[i], i);
#ifdef INIT_EXPANDERS
/* This is to initialize {init|mark|free}_machine_status before the first
@@ -5133,7 +5379,6 @@ init_emit_once (line_numbers)
for (i = - MAX_SAVED_CONST_INT; i <= MAX_SAVED_CONST_INT; i++)
const_int_rtx[i + MAX_SAVED_CONST_INT] =
gen_rtx_raw_CONST_INT (VOIDmode, (HOST_WIDE_INT) i);
- ggc_add_rtx_root (const_int_rtx, 2 * MAX_SAVED_CONST_INT + 1);
if (STORE_FLAG_VALUE >= - MAX_SAVED_CONST_INT
&& STORE_FLAG_VALUE <= MAX_SAVED_CONST_INT)
@@ -5141,35 +5386,20 @@ init_emit_once (line_numbers)
else
const_true_rtx = gen_rtx_CONST_INT (VOIDmode, STORE_FLAG_VALUE);
- dconst0 = REAL_VALUE_ATOF ("0", double_mode);
- dconst1 = REAL_VALUE_ATOF ("1", double_mode);
- dconst2 = REAL_VALUE_ATOF ("2", double_mode);
- dconstm1 = REAL_VALUE_ATOF ("-1", double_mode);
+ REAL_VALUE_FROM_INT (dconst0, 0, 0, double_mode);
+ REAL_VALUE_FROM_INT (dconst1, 1, 0, double_mode);
+ REAL_VALUE_FROM_INT (dconst2, 2, 0, double_mode);
+ REAL_VALUE_FROM_INT (dconstm1, -1, -1, double_mode);
for (i = 0; i <= 2; i++)
{
+ REAL_VALUE_TYPE *r =
+ (i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2);
+
for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
- {
- rtx tem = rtx_alloc (CONST_DOUBLE);
- union real_extract u;
-
- /* Zero any holes in a structure. */
- memset ((char *) &u, 0, sizeof u);
- u.d = i == 0 ? dconst0 : i == 1 ? dconst1 : dconst2;
-
- /* Avoid trailing garbage in the rtx. */
- if (sizeof (u) < sizeof (HOST_WIDE_INT))
- CONST_DOUBLE_LOW (tem) = 0;
- if (sizeof (u) < 2 * sizeof (HOST_WIDE_INT))
- CONST_DOUBLE_HIGH (tem) = 0;
-
- memcpy (&CONST_DOUBLE_LOW (tem), &u, sizeof u);
- CONST_DOUBLE_CHAIN (tem) = NULL_RTX;
- PUT_MODE (tem, mode);
-
- const_tiny_rtx[i][(int) mode] = tem;
- }
+ const_tiny_rtx[i][(int) mode] =
+ CONST_DOUBLE_FROM_REAL_VALUE (*r, mode);
const_tiny_rtx[i][(int) VOIDmode] = GEN_INT (i);
@@ -5201,12 +5431,6 @@ init_emit_once (line_numbers)
if (STORE_FLAG_VALUE == 1)
const_tiny_rtx[1][(int) BImode] = const1_rtx;
- /* For bounded pointers, `&const_tiny_rtx[0][0]' is not the same as
- `(rtx *) const_tiny_rtx'. The former has bounds that only cover
- `const_tiny_rtx[0]', whereas the latter has bounds that cover all. */
- ggc_add_rtx_root ((rtx *) const_tiny_rtx, sizeof const_tiny_rtx / sizeof (rtx));
- ggc_add_rtx_root (&const_true_rtx, 1);
-
#ifdef RETURN_ADDRESS_POINTER_REGNUM
return_address_pointer_rtx
= gen_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM);
@@ -5253,13 +5477,6 @@ init_emit_once (line_numbers)
if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
-
- ggc_add_rtx_root (&pic_offset_table_rtx, 1);
- ggc_add_rtx_root (&struct_value_rtx, 1);
- ggc_add_rtx_root (&struct_value_incoming_rtx, 1);
- ggc_add_rtx_root (&static_chain_rtx, 1);
- ggc_add_rtx_root (&static_chain_incoming_rtx, 1);
- ggc_add_rtx_root (&return_address_pointer_rtx, 1);
}
/* Query and clear/ restore no_line_numbers. This is used by the
@@ -5283,3 +5500,72 @@ restore_line_number_status (old_value)
{
no_line_numbers = old_value;
}
+
+/* Produce exact duplicate of insn INSN after AFTER.
+ Care updating of libcall regions if present. */
+
+rtx
+emit_copy_of_insn_after (insn, after)
+ rtx insn, after;
+{
+ rtx new;
+ rtx note1, note2, link;
+
+ switch (GET_CODE (insn))
+ {
+ case INSN:
+ new = emit_insn_after (copy_insn (PATTERN (insn)), after);
+ break;
+
+ case JUMP_INSN:
+ new = emit_jump_insn_after (copy_insn (PATTERN (insn)), after);
+ break;
+
+ case CALL_INSN:
+ new = emit_call_insn_after (copy_insn (PATTERN (insn)), after);
+ if (CALL_INSN_FUNCTION_USAGE (insn))
+ CALL_INSN_FUNCTION_USAGE (new)
+ = copy_insn (CALL_INSN_FUNCTION_USAGE (insn));
+ SIBLING_CALL_P (new) = SIBLING_CALL_P (insn);
+ CONST_OR_PURE_CALL_P (new) = CONST_OR_PURE_CALL_P (insn);
+ break;
+
+ default:
+ abort ();
+ }
+
+ /* Update LABEL_NUSES. */
+ mark_jump_label (PATTERN (new), new, 0);
+
+ INSN_SCOPE (new) = INSN_SCOPE (insn);
+
+ /* Copy all REG_NOTES except REG_LABEL since mark_jump_label will
+ make them. */
+ for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+ if (REG_NOTE_KIND (link) != REG_LABEL)
+ {
+ if (GET_CODE (link) == EXPR_LIST)
+ REG_NOTES (new)
+ = copy_insn_1 (gen_rtx_EXPR_LIST (REG_NOTE_KIND (link),
+ XEXP (link, 0),
+ REG_NOTES (new)));
+ else
+ REG_NOTES (new)
+ = copy_insn_1 (gen_rtx_INSN_LIST (REG_NOTE_KIND (link),
+ XEXP (link, 0),
+ REG_NOTES (new)));
+ }
+
+ /* Fix the libcall sequences. */
+ if ((note1 = find_reg_note (new, REG_RETVAL, NULL_RTX)) != NULL)
+ {
+ rtx p = new;
+ while ((note2 = find_reg_note (p, REG_LIBCALL, NULL_RTX)) == NULL)
+ p = PREV_INSN (p);
+ XEXP (note1, 0) = p;
+ XEXP (note2, 0) = new;
+ }
+ return new;
+}
+
+#include "gt-emit-rtl.h"
diff --git a/contrib/gcc/errors.h b/contrib/gcc/errors.h
index 5306c2e..b48f855 100644
--- a/contrib/gcc/errors.h
+++ b/contrib/gcc/errors.h
@@ -39,5 +39,5 @@ extern void fancy_abort PARAMS ((const char *, int, const char *))
extern int have_error;
extern const char *progname;
-
+
#endif /* ! GCC_ERRORS_H */
diff --git a/contrib/gcc/et-forest.c b/contrib/gcc/et-forest.c
new file mode 100644
index 0000000..84594d4
--- /dev/null
+++ b/contrib/gcc/et-forest.c
@@ -0,0 +1,680 @@
+/* ET-trees datastructure implementation.
+ Contributed by Pavel Nejedly
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+ The ET-forest structure is described in:
+ D. D. Sleator and R. E. Tarjan. A data structure for dynamic trees.
+ J. G'omput. System Sci., 26(3):362 381, 1983.
+*/
+
+#include "config.h"
+#include "system.h"
+#include "et-forest.h"
+
+struct et_forest_occurrence;
+typedef struct et_forest_occurrence* et_forest_occurrence_t;
+
+/* The ET-forest type. */
+struct et_forest
+{
+ /* Linked list of nodes is used to destroy the structure. */
+ int nnodes;
+};
+
+/* Single occurrence of node in ET-forest.
+ A single node may have multiple occurrences.
+ */
+struct et_forest_occurrence
+{
+ /* Parent in the splay-tree. */
+ et_forest_occurrence_t parent;
+
+ /* Children in the splay-tree. */
+ et_forest_occurrence_t left, right;
+
+ /* Counts of vertices in the two splay-subtrees. */
+ int count_left, count_right;
+
+ /* Next occurrence of this node in the sequence. */
+ et_forest_occurrence_t next;
+
+ /* The node, which this occurrence is of. */
+ et_forest_node_t node;
+};
+
+
+/* ET-forest node. */
+struct et_forest_node
+{
+ et_forest_t forest;
+ void *value;
+
+ /* First and last occurrence of this node in the sequence. */
+ et_forest_occurrence_t first, last;
+};
+
+
+static et_forest_occurrence_t splay PARAMS ((et_forest_occurrence_t));
+static void remove_all_occurrences PARAMS ((et_forest_node_t));
+static inline et_forest_occurrence_t find_leftmost_node
+ PARAMS ((et_forest_occurrence_t));
+static inline et_forest_occurrence_t find_rightmost_node
+ PARAMS ((et_forest_occurrence_t));
+static int calculate_value PARAMS ((et_forest_occurrence_t));
+
+/* Return leftmost node present in the tree roted by OCC. */
+static inline et_forest_occurrence_t
+find_leftmost_node (occ)
+ et_forest_occurrence_t occ;
+{
+ while (occ->left)
+ occ = occ->left;
+
+ return occ;
+}
+
+/* Return rightmost node present in the tree roted by OCC. */
+static inline et_forest_occurrence_t
+find_rightmost_node (occ)
+ et_forest_occurrence_t occ;
+{
+ while (occ->right)
+ occ = occ->right;
+ return occ;
+}
+
+
+/* Operation splay for splay tree structure representing ocuurences. */
+static et_forest_occurrence_t
+splay (node)
+ et_forest_occurrence_t node;
+{
+ et_forest_occurrence_t parent;
+ et_forest_occurrence_t grandparent;
+
+ while (1)
+ {
+ parent = node->parent;
+
+ if (! parent)
+ return node; /* node == root. */
+
+ grandparent = parent->parent;
+
+ if (! grandparent)
+ break;
+
+ /* Now there are four possible combinations: */
+
+ if (node == parent->left)
+ {
+ if (parent == grandparent->left)
+ {
+ et_forest_occurrence_t node1, node2;
+ int count1, count2;
+
+ node1 = node->right;
+ count1 = node->count_right;
+ node2 = parent->right;
+ count2 = parent->count_right;
+
+ grandparent->left = node2;
+ grandparent->count_left = count2;
+ if (node2)
+ node2->parent = grandparent;
+ parent->left = node1;
+ parent->count_left = count1;
+ if (node1)
+ node1->parent = parent;
+ parent->right = grandparent;
+ parent->count_right = count2 + grandparent->count_right + 1;
+ node->right = parent;
+ node->count_right = count1 + parent->count_right + 1;
+
+ node->parent = grandparent->parent;
+ parent->parent = node;
+ grandparent->parent = parent;
+
+ if (node->parent)
+ {
+ if (node->parent->left == grandparent)
+ node->parent->left = node;
+ else
+ node->parent->right = node;
+ }
+ }
+ else
+ {
+ /* parent == grandparent->right && node == parent->left*/
+ et_forest_occurrence_t node1, node2;
+ int count1, count2;
+
+ node1 = node->left;
+ count1 = node->count_left;
+ node2 = node->right;
+ count2 = node->count_right;
+
+ grandparent->right = node1;
+ grandparent->count_right = count1;
+ if (node1)
+ node1->parent = grandparent;
+ parent->left = node2;
+ parent->count_left = count2;
+ if (node2)
+ node2->parent = parent;
+ node->left = grandparent;
+ node->count_left = grandparent->count_left + count1 + 1;
+ node->right = parent;
+ node->count_right = parent->count_right + count2 + 1;
+
+ node->parent = grandparent->parent;
+ parent->parent = node;
+ grandparent->parent = node;
+
+ if (node->parent)
+ {
+ if (node->parent->left == grandparent)
+ node->parent->left = node;
+ else
+ node->parent->right = node;
+ }
+ }
+ }
+ else
+ {
+ /* node == parent->right. */
+ if (parent == grandparent->left)
+ {
+ et_forest_occurrence_t node1, node2;
+ int count1, count2;
+
+ node1 = node->left;
+ count1 = node->count_left;
+ node2 = node->right;
+ count2 = node->count_right;
+
+ parent->right = node1;
+ parent->count_right = count1;
+ if (node1)
+ node1->parent = parent;
+ grandparent->left = node2;
+ grandparent->count_left = count2;
+ if (node2)
+ node2->parent = grandparent;
+ node->left = parent;
+ node->count_left = parent->count_left + count1 + 1;
+ node->right = grandparent;
+ node->count_right = grandparent->count_right + count2 + 1;
+
+ node->parent = grandparent->parent;
+ parent->parent = node;
+ grandparent->parent = node;
+
+ if (node->parent)
+ {
+ if (node->parent->left == grandparent)
+ node->parent->left = node;
+ else
+ node->parent->right = node;
+ }
+ }
+ else
+ {
+ /* parent == grandparent->right && node == parent->right*/
+ et_forest_occurrence_t node1, node2;
+ int count1, count2;
+
+ node1 = node->left;
+ count1 = node->count_left;
+ node2 = parent->left;
+ count2 = parent->count_left;
+
+ grandparent->right = node2;
+ grandparent->count_right = count2;
+ if (node2)
+ node2->parent = grandparent;
+ parent->right = node1;
+ parent->count_right = count1;
+ if (node1)
+ node1->parent = parent;
+ parent->left = grandparent;
+ parent->count_left = count2 + grandparent->count_left + 1;
+ node->left = parent;
+ node->count_left = count1 + parent->count_left + 1;
+
+ node->parent = grandparent->parent;
+ parent->parent = node;
+ grandparent->parent = parent;
+
+ if (node->parent)
+ {
+ if (node->parent->left == grandparent)
+ node->parent->left = node;
+ else
+ node->parent->right = node;
+ }
+ }
+ }
+
+ }
+
+ /* parent == root. */
+ /* There are two possible combinations: */
+
+ if (node == parent->left)
+ {
+ et_forest_occurrence_t node1;
+ int count1;
+
+ node1 = node->right;
+ count1 = node->count_right;
+
+ parent->left = node1;
+ parent->count_left = count1;
+ if (node1)
+ node1->parent = parent;
+ node->right = parent;
+ node->count_right = parent->count_right + 1 + count1;
+ node->parent = parent->parent; /* the same as = 0; */
+ parent->parent = node;
+
+ if (node->parent)
+ {
+ if (node->parent->left == parent)
+ node->parent->left = node;
+ else
+ node->parent->right = node;
+ }
+ }
+ else
+ {
+ /* node == parent->right. */
+ et_forest_occurrence_t node1;
+ int count1;
+
+ node1 = node->left;
+ count1 = node->count_left;
+
+ parent->right = node1;
+ parent->count_right = count1;
+ if (node1)
+ node1->parent = parent;
+ node->left = parent;
+ node->count_left = parent->count_left + 1 + count1;
+ node->parent = parent->parent; /* the same as = 0; */
+ parent->parent = node;
+
+ if (node->parent)
+ {
+ if (node->parent->left == parent)
+ node->parent->left = node;
+ else
+ node->parent->right = node;
+ }
+ }
+
+ return node;
+}
+
+/* Remove all occurences of the given node before destroying the node. */
+static void
+remove_all_occurrences (forest_node)
+ et_forest_node_t forest_node;
+{
+ et_forest_occurrence_t first = forest_node->first;
+ et_forest_occurrence_t last = forest_node->last;
+ et_forest_occurrence_t node;
+
+ splay (first);
+
+ if (first->left)
+ first->left->parent = 0;
+ if (first->right)
+ first->right->parent = 0;
+
+ if (last != first)
+ {
+ splay (last);
+
+ if (last->left)
+ last->left->parent = 0;
+ if (last->right)
+ last->right->parent = 0;
+ }
+
+ if (last->right && first->left) /* actually, first->left would suffice. */
+ {
+ /* Need to join them. */
+ et_forest_occurrence_t prev_node, next_node;
+
+ prev_node = splay (find_rightmost_node (first->left));
+ next_node = splay (find_leftmost_node (last->right));
+ /* prev_node and next_node are consecutive occurencies
+ of the same node. */
+ if (prev_node->next != next_node)
+ abort ();
+
+ prev_node->right = next_node->right;
+ prev_node->count_right = next_node->count_right;
+ prev_node->next = next_node->next;
+ if (prev_node->right)
+ prev_node->right->parent = prev_node;
+
+ if (prev_node->node->last == next_node)
+ prev_node->node->last = prev_node;
+
+ free (next_node);
+ }
+
+ if (first != last)
+ {
+ node = first->next;
+
+ while (node != last)
+ {
+ et_forest_occurrence_t next_node;
+
+ splay (node);
+
+ if (node->left)
+ node->left->parent = 0;
+ if (node->right)
+ node->right->parent = 0;
+
+ next_node = node->next;
+ free (node);
+ node = next_node;
+ }
+ }
+
+ free (first);
+ if (first != last)
+ free (last);
+}
+
+/* Calculate ET value of the given node. */
+static inline int
+calculate_value (node)
+ et_forest_occurrence_t node;
+{
+ int value = node->count_left;
+
+ while (node->parent)
+ {
+ if (node == node->parent->right)
+ value += node->parent->count_left + 1;
+
+ node = node->parent;
+ }
+
+ return value;
+}
+
+
+
+
+/* Create ET-forest structure. */
+et_forest_t
+et_forest_create ()
+{
+
+ et_forest_t forest = xmalloc (sizeof (struct et_forest));
+
+ forest->nnodes = 0;
+ return forest;
+}
+
+
+
+/* Deallocate the structure. */
+void
+et_forest_delete (forest)
+ et_forest_t forest;
+{
+ if (forest->nnodes)
+ abort ();
+
+ free (forest);
+}
+
+/* Create new node with VALUE and return the edge.
+ Return NULL when memory allocation failed. */
+et_forest_node_t
+et_forest_add_node (forest, value)
+ et_forest_t forest;
+ void *value;
+{
+ /* Create node with one occurrence. */
+ et_forest_node_t node;
+ et_forest_occurrence_t occ;
+
+ node = xmalloc (sizeof (struct et_forest_node));
+ occ = xmalloc (sizeof (struct et_forest_occurrence));
+
+ node->first = node->last = occ;
+ node->value = value;
+ forest->nnodes++;
+
+ occ->node = node;
+ occ->left = occ->right = occ->parent = 0;
+ occ->next = 0;
+ occ->count_left = occ->count_right = 0;
+ return node;
+}
+
+/* Add new edge to the tree, return 1 if succesfull.
+ 0 indicates that creation of the edge will close the cycle in graph. */
+int
+et_forest_add_edge (forest, parent_node, child_node)
+ et_forest_t forest ATTRIBUTE_UNUSED;
+ et_forest_node_t parent_node;
+ et_forest_node_t child_node;
+{
+ et_forest_occurrence_t new_occ, parent_occ, child_occ;
+
+ if (! parent_node || ! child_node)
+ abort ();
+
+ parent_occ = parent_node->first;
+ child_occ = child_node->first;
+
+ splay (parent_occ);
+ splay (child_occ);
+
+ if (parent_occ->parent)
+ return 0; /* Both child and parent are in the same tree. */
+
+ if (child_occ->left)
+ abort (); /* child must be root of its containing tree. */
+
+ new_occ = xmalloc (sizeof (struct et_forest_occurrence));
+
+ new_occ->node = parent_node;
+ new_occ->left = child_occ;
+ new_occ->count_left = child_occ->count_right + 1; /* count_left is 0. */
+ new_occ->right = parent_occ->right;
+ new_occ->count_right = parent_occ->count_right;
+ new_occ->parent = parent_occ;
+ new_occ->next = parent_occ->next;
+ child_occ->parent = new_occ;
+ parent_occ->right = new_occ;
+ parent_occ->count_right = new_occ->count_left + new_occ->count_right + 1;
+ parent_occ->next = new_occ;
+ if (new_occ->right)
+ new_occ->right->parent = new_occ;
+
+ if (parent_node->last == parent_occ)
+ parent_node->last = new_occ;
+ return 1;
+}
+
+/* Remove NODE from the tree and all connected edges. */
+void
+et_forest_remove_node (forest, node)
+ et_forest_t forest;
+ et_forest_node_t node;
+{
+ remove_all_occurrences (node);
+ forest->nnodes--;
+
+ free (node);
+}
+
+/* Remove edge from the tree, return 1 if sucesfull,
+ 0 indicates nonexisting edge. */
+int
+et_forest_remove_edge (forest, parent_node, child_node)
+ et_forest_t forest ATTRIBUTE_UNUSED;
+ et_forest_node_t parent_node;
+ et_forest_node_t child_node;
+{
+ et_forest_occurrence_t parent_pre_occ, parent_post_occ;
+
+ splay (child_node->first);
+
+ if (! child_node->first->left)
+ return 0;
+
+ parent_pre_occ = find_rightmost_node (child_node->first->left);
+ if (parent_pre_occ->node != parent_node)
+ abort ();
+
+ splay (parent_pre_occ);
+ parent_pre_occ->right->parent = 0;
+
+ parent_post_occ = parent_pre_occ->next;
+ splay (parent_post_occ);
+
+ parent_post_occ->left->parent = 0;
+
+ parent_pre_occ->right = parent_post_occ->right;
+ parent_pre_occ->count_right = parent_post_occ->count_right;
+ if (parent_post_occ->right)
+ parent_post_occ->right->parent = parent_pre_occ;
+
+ parent_pre_occ->next = parent_post_occ->next;
+
+ if (parent_post_occ == parent_node->last)
+ parent_node->last = parent_pre_occ;
+
+ free (parent_post_occ);
+ return 1;
+}
+
+/* Return the parent of the NODE if any, NULL otherwise. */
+et_forest_node_t
+et_forest_parent (forest, node)
+ et_forest_t forest ATTRIBUTE_UNUSED;
+ et_forest_node_t node;
+{
+ splay (node->first);
+
+ if (node->first->left)
+ return find_rightmost_node (node->first->left)->node;
+ else
+ return 0;
+}
+
+
+/* Return nearest common ancestor of NODE1 and NODE2.
+ Return NULL of they are in different trees. */
+et_forest_node_t
+et_forest_common_ancestor (forest, node1, node2)
+ et_forest_t forest ATTRIBUTE_UNUSED;
+ et_forest_node_t node1;
+ et_forest_node_t node2;
+{
+ int value1, value2, max_value;
+ et_forest_node_t ancestor;
+
+ if (node1 == node2)
+ return node1;
+
+ if (! node1 || ! node2)
+ abort ();
+
+ splay (node1->first);
+ splay (node2->first);
+
+ if (! node1->first->parent) /* The two vertices are in different trees. */
+ return 0;
+
+ value2 = calculate_value (node2->first);
+ value1 = calculate_value (node1->first);
+
+ if (value1 < value2)
+ {
+ ancestor = node1;
+ max_value = value2;
+ }
+ else
+ {
+ ancestor = node2;
+ max_value = value1;
+ }
+
+ while (calculate_value (ancestor->last) < max_value)
+ {
+ /* Find parent node. */
+ splay (ancestor->first);
+ ancestor = find_rightmost_node (ancestor->first->left) ->node;
+ }
+
+ return ancestor;
+}
+
+/* Return the value pointer of node set during it's creation. */
+void *
+et_forest_node_value (forest, node)
+ et_forest_t forest ATTRIBUTE_UNUSED;
+ et_forest_node_t node;
+{
+ /* Alloc threading NULL as a special node of the forest. */
+ if (!node)
+ return NULL;
+ return node->value;
+}
+
+/* Find all sons of NODE and store them into ARRAY allocated by the caller.
+ Return number of nodes found. */
+int
+et_forest_enumerate_sons (forest, node, array)
+ et_forest_t forest ATTRIBUTE_UNUSED;
+ et_forest_node_t node;
+ et_forest_node_t *array;
+{
+ int n = 0;
+ et_forest_occurrence_t occ = node->first, stop = node->last, occ1;
+
+ /* Parent is the rightmost node of the left successor.
+ Look for all occurences having no right succesor
+ and lookup the sons. */
+ while (occ != stop)
+ {
+ splay (occ);
+ if (occ->right)
+ {
+ occ1 = find_leftmost_node (occ->right);
+ if (occ1->node->first == occ1)
+ array[n++] = occ1->node;
+ }
+ occ = occ->next;
+ }
+ return n;
+}
diff --git a/contrib/gcc/et-forest.h b/contrib/gcc/et-forest.h
new file mode 100644
index 0000000..8f4290c
--- /dev/null
+++ b/contrib/gcc/et-forest.h
@@ -0,0 +1,83 @@
+/* Et-forest data structure implementation.
+ Copyright (C) 2002 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 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This package implements ET forest data structure. Each tree in
+ the structure maintains a tree structure and offers logarithmic time
+ for tree operations (insertion and removal of nodes and edges) and
+ poly-logarithmic time for nearest common ancesto.
+
+ ET tree strores its structue as a sequence of symbols obtained
+ by dfs(root)
+
+ dfs (node)
+ {
+ s = node;
+ for each child c of node do
+ s = concat (s, c, node);
+ return s;
+ }
+
+ For example for tree
+
+ 1
+ / | \
+ 2 3 4
+ / |
+ 4 5
+
+ the sequence is 1 2 4 2 5 3 1 3 1 4 1.
+
+ The sequence is stored in a sligtly modified splay tree.
+ In order to support various types of node values, a hashtable
+ is used to convert node values to the internal representation. */
+
+#ifndef _ET_TREE_H
+#define _ET_TREE_H
+
+#include <ansidecl.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct et_forest *et_forest_t;
+typedef struct et_forest_node *et_forest_node_t;
+
+extern et_forest_t et_forest_create PARAMS ((void));
+
+extern void et_forest_delete PARAMS ((et_forest_t));
+
+extern et_forest_node_t et_forest_add_node PARAMS ((et_forest_t, void *));
+extern int et_forest_add_edge PARAMS ((et_forest_t, et_forest_node_t,
+ et_forest_node_t));
+extern void et_forest_remove_node PARAMS ((et_forest_t, et_forest_node_t));
+extern int et_forest_remove_edge PARAMS ((et_forest_t, et_forest_node_t,
+ et_forest_node_t));
+extern et_forest_node_t et_forest_parent PARAMS ((et_forest_t, et_forest_node_t));
+extern et_forest_node_t et_forest_common_ancestor PARAMS ((et_forest_t,
+ et_forest_node_t,
+ et_forest_node_t));
+extern void * et_forest_node_value PARAMS ((et_forest_t, et_forest_node_t));
+extern int et_forest_enumerate_sons PARAMS ((et_forest_t, et_forest_node_t,
+ et_forest_node_t *));
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _ET_TREE_H */
diff --git a/contrib/gcc/except.c b/contrib/gcc/except.c
index a258731..b6f851b 100644
--- a/contrib/gcc/except.c
+++ b/contrib/gcc/except.c
@@ -70,15 +70,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ggc.h"
#include "tm_p.h"
#include "target.h"
+#include "langhooks.h"
/* Provide defaults for stuff that may not be defined when using
sjlj exceptions. */
-#ifndef EH_RETURN_STACKADJ_RTX
-#define EH_RETURN_STACKADJ_RTX 0
-#endif
-#ifndef EH_RETURN_HANDLER_RTX
-#define EH_RETURN_HANDLER_RTX 0
-#endif
#ifndef EH_RETURN_DATA_REGNO
#define EH_RETURN_DATA_REGNO(N) INVALID_REGNUM
#endif
@@ -99,20 +94,18 @@ tree (*lang_eh_runtime_type) PARAMS ((tree));
/* A hash table of label to region number. */
-struct ehl_map_entry
+struct ehl_map_entry GTY(())
{
rtx label;
struct eh_region *region;
};
-static htab_t exception_handler_label_map;
-
static int call_site_base;
-static unsigned int sjlj_funcdef_number;
-static htab_t type_to_runtime_map;
+static GTY ((param_is (union tree_node)))
+ htab_t type_to_runtime_map;
/* Describe the SjLj_Function_Context structure. */
-static tree sjlj_fc_type_node;
+static GTY(()) tree sjlj_fc_type_node;
static int sjlj_fc_call_site_ofs;
static int sjlj_fc_data_ofs;
static int sjlj_fc_personality_ofs;
@@ -120,7 +113,7 @@ static int sjlj_fc_lsda_ofs;
static int sjlj_fc_jbuf_ofs;
/* Describes one exception region. */
-struct eh_region
+struct eh_region GTY(())
{
/* The immediately surrounding region. */
struct eh_region *outer;
@@ -150,50 +143,51 @@ struct eh_region
} type;
/* Holds the action to perform based on the preceding type. */
- union {
+ union eh_region_u {
/* A list of catch blocks, a surrounding try block,
and the label for continuing after a catch. */
- struct {
+ struct eh_region_u_try {
struct eh_region *catch;
struct eh_region *last_catch;
struct eh_region *prev_try;
rtx continue_label;
- } try;
+ } GTY ((tag ("ERT_TRY"))) try;
/* The list through the catch handlers, the list of type objects
matched, and the list of associated filters. */
- struct {
+ struct eh_region_u_catch {
struct eh_region *next_catch;
struct eh_region *prev_catch;
tree type_list;
tree filter_list;
- } catch;
+ } GTY ((tag ("ERT_CATCH"))) catch;
/* A tree_list of allowed types. */
- struct {
+ struct eh_region_u_allowed {
tree type_list;
int filter;
- } allowed;
+ } GTY ((tag ("ERT_ALLOWED_EXCEPTIONS"))) allowed;
/* The type given by a call to "throw foo();", or discovered
for a throw. */
- struct {
+ struct eh_region_u_throw {
tree type;
- } throw;
+ } GTY ((tag ("ERT_THROW"))) throw;
/* Retain the cleanup expression even after expansion so that
we can match up fixup regions. */
- struct {
+ struct eh_region_u_cleanup {
tree exp;
- } cleanup;
+ struct eh_region *prev_try;
+ } GTY ((tag ("ERT_CLEANUP"))) cleanup;
/* The real region (by expression and by pointer) that fixup code
should live in. */
- struct {
+ struct eh_region_u_fixup {
tree cleanup_exp;
struct eh_region *real_region;
- } fixup;
- } u;
+ } GTY ((tag ("ERT_FIXUP"))) fixup;
+ } GTY ((desc ("%0.type"))) u;
/* Entry point for this region's handler before landing pads are built. */
rtx label;
@@ -207,16 +201,25 @@ struct eh_region
/* The RESX insn for handing off control to the next outermost handler,
if appropriate. */
rtx resume;
+
+ /* True if something in this region may throw. */
+ unsigned may_contain_throw : 1;
+};
+
+struct call_site_record GTY(())
+{
+ rtx landing_pad;
+ int action;
};
/* Used to save exception status for each function. */
-struct eh_status
+struct eh_status GTY(())
{
/* The tree of all regions for this function. */
struct eh_region *region_tree;
/* The same information as an indexable array. */
- struct eh_region **region_array;
+ struct eh_region ** GTY ((length ("%h.last_region_number"))) region_array;
/* The most recently open region. */
struct eh_region *cur_region;
@@ -224,12 +227,6 @@ struct eh_status
/* This is the region for which we are processing catch blocks. */
struct eh_region *try_region;
- /* A stack (TREE_LIST) of lists of handlers. The TREE_VALUE of each
- node is itself a TREE_CHAINed list of handlers for regions that
- are not yet closed. The TREE_VALUE of each entry contains the
- handler for the corresponding entry on the ehstack. */
- tree protect_list;
-
rtx filter;
rtx exc_ptr;
@@ -240,11 +237,10 @@ struct eh_status
varray_type ehspec_data;
varray_type action_record_data;
- struct call_site_record
- {
- rtx landing_pad;
- int action;
- } *call_site_data;
+ htab_t GTY ((param_is (struct ehl_map_entry))) exception_handler_label_map;
+
+ struct call_site_record * GTY ((length ("%h.call_site_data_used")))
+ call_site_data;
int call_site_data_used;
int call_site_data_size;
@@ -257,17 +253,9 @@ struct eh_status
};
-static void mark_eh_region PARAMS ((struct eh_region *));
-static int mark_ehl_map_entry PARAMS ((PTR *, PTR));
-static void mark_ehl_map PARAMS ((void *));
-
-static void free_region PARAMS ((struct eh_region *));
-
static int t2r_eq PARAMS ((const PTR,
const PTR));
static hashval_t t2r_hash PARAMS ((const PTR));
-static int t2r_mark_1 PARAMS ((PTR *, PTR));
-static void t2r_mark PARAMS ((PTR));
static void add_type_for_runtime PARAMS ((tree));
static tree lookup_type_for_runtime PARAMS ((tree));
@@ -315,7 +303,6 @@ static void sjlj_build_landing_pads PARAMS ((void));
static hashval_t ehl_hash PARAMS ((const PTR));
static int ehl_eq PARAMS ((const PTR,
const PTR));
-static void ehl_free PARAMS ((PTR));
static void add_ehl_entry PARAMS ((rtx,
struct eh_region *));
static void remove_exception_handler_label PARAMS ((rtx));
@@ -364,7 +351,7 @@ static void sjlj_output_call_site_table PARAMS ((void));
/* Routine to see if exception handling is turned on.
- DO_WARN is non-zero if we want to inform the user that exception
+ DO_WARN is nonzero if we want to inform the user that exception
handling is turned off.
This is used to ensure that -fexceptions has been specified if the
@@ -391,13 +378,10 @@ doing_eh (do_warn)
void
init_eh ()
{
- ggc_add_root (&exception_handler_label_map, 1, 1, mark_ehl_map);
-
if (! flag_exceptions)
return;
- type_to_runtime_map = htab_create (31, t2r_hash, t2r_eq, NULL);
- ggc_add_root (&type_to_runtime_map, 1, sizeof (htab_t), t2r_mark);
+ type_to_runtime_map = htab_create_ggc (31, t2r_hash, t2r_eq, NULL);
/* Create the SjLj_Function_Context structure. This should match
the definition in unwind-sjlj.c. */
@@ -405,8 +389,7 @@ init_eh ()
{
tree f_jbuf, f_per, f_lsda, f_prev, f_cs, f_data, tmp;
- sjlj_fc_type_node = make_lang_type (RECORD_TYPE);
- ggc_add_tree_root (&sjlj_fc_type_node, 1);
+ sjlj_fc_type_node = (*lang_hooks.types.make_type) (RECORD_TYPE);
f_prev = build_decl (FIELD_DECL, get_identifier ("__prev"),
build_pointer_type (sjlj_fc_type_node));
@@ -417,7 +400,8 @@ init_eh ()
DECL_FIELD_CONTEXT (f_cs) = sjlj_fc_type_node;
tmp = build_index_type (build_int_2 (4 - 1, 0));
- tmp = build_array_type (type_for_mode (word_mode, 1), tmp);
+ tmp = build_array_type ((*lang_hooks.types.type_for_mode) (word_mode, 1),
+ tmp);
f_data = build_decl (FIELD_DECL, get_identifier ("__data"), tmp);
DECL_FIELD_CONTEXT (f_data) = sjlj_fc_type_node;
@@ -488,210 +472,9 @@ init_eh ()
void
init_eh_for_function ()
{
- cfun->eh = (struct eh_status *) xcalloc (1, sizeof (struct eh_status));
+ cfun->eh = (struct eh_status *)
+ ggc_alloc_cleared (sizeof (struct eh_status));
}
-
-/* Mark EH for GC. */
-
-static void
-mark_eh_region (region)
- struct eh_region *region;
-{
- if (! region)
- return;
-
- switch (region->type)
- {
- case ERT_UNKNOWN:
- /* This can happen if a nested function is inside the body of a region
- and we do a GC as part of processing it. */
- break;
- case ERT_CLEANUP:
- ggc_mark_tree (region->u.cleanup.exp);
- break;
- case ERT_TRY:
- ggc_mark_rtx (region->u.try.continue_label);
- break;
- case ERT_CATCH:
- ggc_mark_tree (region->u.catch.type_list);
- ggc_mark_tree (region->u.catch.filter_list);
- break;
- case ERT_ALLOWED_EXCEPTIONS:
- ggc_mark_tree (region->u.allowed.type_list);
- break;
- case ERT_MUST_NOT_THROW:
- break;
- case ERT_THROW:
- ggc_mark_tree (region->u.throw.type);
- break;
- case ERT_FIXUP:
- ggc_mark_tree (region->u.fixup.cleanup_exp);
- break;
- default:
- abort ();
- }
-
- ggc_mark_rtx (region->label);
- ggc_mark_rtx (region->resume);
- ggc_mark_rtx (region->landing_pad);
- ggc_mark_rtx (region->post_landing_pad);
-}
-
-static int
-mark_ehl_map_entry (pentry, data)
- PTR *pentry;
- PTR data ATTRIBUTE_UNUSED;
-{
- struct ehl_map_entry *entry = *(struct ehl_map_entry **) pentry;
- ggc_mark_rtx (entry->label);
- return 1;
-}
-
-static void
-mark_ehl_map (pp)
- void *pp;
-{
- htab_t map = *(htab_t *) pp;
- if (map)
- htab_traverse (map, mark_ehl_map_entry, NULL);
-}
-
-void
-mark_eh_status (eh)
- struct eh_status *eh;
-{
- int i;
-
- if (eh == 0)
- return;
-
- /* If we've called collect_eh_region_array, use it. Otherwise walk
- the tree non-recursively. */
- if (eh->region_array)
- {
- for (i = eh->last_region_number; i > 0; --i)
- {
- struct eh_region *r = eh->region_array[i];
- if (r && r->region_number == i)
- mark_eh_region (r);
- }
- }
- else if (eh->region_tree)
- {
- struct eh_region *r = eh->region_tree;
- while (1)
- {
- mark_eh_region (r);
- if (r->inner)
- r = r->inner;
- else if (r->next_peer)
- r = r->next_peer;
- else
- {
- do {
- r = r->outer;
- if (r == NULL)
- goto tree_done;
- } while (r->next_peer == NULL);
- r = r->next_peer;
- }
- }
- tree_done:;
- }
-
- ggc_mark_tree (eh->protect_list);
- ggc_mark_rtx (eh->filter);
- ggc_mark_rtx (eh->exc_ptr);
- ggc_mark_tree_varray (eh->ttype_data);
-
- if (eh->call_site_data)
- {
- for (i = eh->call_site_data_used - 1; i >= 0; --i)
- ggc_mark_rtx (eh->call_site_data[i].landing_pad);
- }
-
- ggc_mark_rtx (eh->ehr_stackadj);
- ggc_mark_rtx (eh->ehr_handler);
- ggc_mark_rtx (eh->ehr_label);
-
- ggc_mark_rtx (eh->sjlj_fc);
- ggc_mark_rtx (eh->sjlj_exit_after);
-}
-
-static inline void
-free_region (r)
- struct eh_region *r;
-{
- /* Note that the aka bitmap is freed by regset_release_memory. But if
- we ever replace with a non-obstack implementation, this would be
- the place to do it. */
- free (r);
-}
-
-void
-free_eh_status (f)
- struct function *f;
-{
- struct eh_status *eh = f->eh;
-
- if (eh->region_array)
- {
- int i;
- for (i = eh->last_region_number; i > 0; --i)
- {
- struct eh_region *r = eh->region_array[i];
- /* Mind we don't free a region struct more than once. */
- if (r && r->region_number == i)
- free_region (r);
- }
- free (eh->region_array);
- }
- else if (eh->region_tree)
- {
- struct eh_region *next, *r = eh->region_tree;
- while (1)
- {
- if (r->inner)
- r = r->inner;
- else if (r->next_peer)
- {
- next = r->next_peer;
- free_region (r);
- r = next;
- }
- else
- {
- do {
- next = r->outer;
- free_region (r);
- r = next;
- if (r == NULL)
- goto tree_done;
- } while (r->next_peer == NULL);
- next = r->next_peer;
- free_region (r);
- r = next;
- }
- }
- tree_done:;
- }
-
- VARRAY_FREE (eh->ttype_data);
- VARRAY_FREE (eh->ehspec_data);
- VARRAY_FREE (eh->action_record_data);
- if (eh->call_site_data)
- free (eh->call_site_data);
-
- free (eh);
- f->eh = NULL;
-
- if (exception_handler_label_map)
- {
- htab_delete (exception_handler_label_map);
- exception_handler_label_map = NULL;
- }
-}
-
/* Start an exception handling region. All instructions emitted
after this point are considered to be part of the region until
@@ -708,7 +491,7 @@ expand_eh_region_start ()
return;
/* Insert a new blank region as a leaf in the tree. */
- new_region = (struct eh_region *) xcalloc (1, sizeof (*new_region));
+ new_region = (struct eh_region *) ggc_alloc_cleared (sizeof (*new_region));
cur_region = cfun->eh->cur_region;
new_region->outer = cur_region;
if (cur_region)
@@ -766,39 +549,43 @@ expand_eh_region_end_cleanup (handler)
region->type = ERT_CLEANUP;
region->label = gen_label_rtx ();
region->u.cleanup.exp = handler;
+ region->u.cleanup.prev_try = cfun->eh->try_region;
around_label = gen_label_rtx ();
emit_jump (around_label);
emit_label (region->label);
- /* Give the language a chance to specify an action to be taken if an
- exception is thrown that would propagate out of the HANDLER. */
- protect_cleanup_actions
- = (lang_protect_cleanup_actions
- ? (*lang_protect_cleanup_actions) ()
- : NULL_TREE);
+ if (flag_non_call_exceptions || region->may_contain_throw)
+ {
+ /* Give the language a chance to specify an action to be taken if an
+ exception is thrown that would propagate out of the HANDLER. */
+ protect_cleanup_actions
+ = (lang_protect_cleanup_actions
+ ? (*lang_protect_cleanup_actions) ()
+ : NULL_TREE);
- if (protect_cleanup_actions)
- expand_eh_region_start ();
+ if (protect_cleanup_actions)
+ expand_eh_region_start ();
- /* In case this cleanup involves an inline destructor with a try block in
- it, we need to save the EH return data registers around it. */
- data_save[0] = gen_reg_rtx (Pmode);
- emit_move_insn (data_save[0], get_exception_pointer (cfun));
- data_save[1] = gen_reg_rtx (word_mode);
- emit_move_insn (data_save[1], get_exception_filter (cfun));
+ /* In case this cleanup involves an inline destructor with a try block in
+ it, we need to save the EH return data registers around it. */
+ data_save[0] = gen_reg_rtx (ptr_mode);
+ emit_move_insn (data_save[0], get_exception_pointer (cfun));
+ data_save[1] = gen_reg_rtx (word_mode);
+ emit_move_insn (data_save[1], get_exception_filter (cfun));
- expand_expr (handler, const0_rtx, VOIDmode, 0);
+ expand_expr (handler, const0_rtx, VOIDmode, 0);
- emit_move_insn (cfun->eh->exc_ptr, data_save[0]);
- emit_move_insn (cfun->eh->filter, data_save[1]);
+ emit_move_insn (cfun->eh->exc_ptr, data_save[0]);
+ emit_move_insn (cfun->eh->filter, data_save[1]);
- if (protect_cleanup_actions)
- expand_eh_region_end_must_not_throw (protect_cleanup_actions);
+ if (protect_cleanup_actions)
+ expand_eh_region_end_must_not_throw (protect_cleanup_actions);
- /* We need any stack adjustment complete before the around_label. */
- do_pending_stack_adjust ();
+ /* We need any stack adjustment complete before the around_label. */
+ do_pending_stack_adjust ();
+ }
/* We delay the generation of the _Unwind_Resume until we generate
landing pads. We emit a marker here so as to get good control
@@ -856,11 +643,11 @@ expand_start_catch (type_or_list)
tree type_node;
if (TREE_CODE (type_or_list) != TREE_LIST)
- type_list = tree_cons (NULL_TREE, type_or_list, NULL_TREE);
+ type_list = tree_cons (NULL_TREE, type_or_list, NULL_TREE);
type_node = type_list;
for (; type_node; type_node = TREE_CHAIN (type_node))
- add_type_for_runtime (TREE_VALUE (type_node));
+ add_type_for_runtime (TREE_VALUE (type_node));
}
expand_eh_region_start ();
@@ -1034,6 +821,22 @@ expand_eh_region_end_fixup (handler)
fixup->u.fixup.cleanup_exp = handler;
}
+/* Note that the current EH region (if any) may contain a throw, or a
+ call to a function which itself may contain a throw. */
+
+void
+note_eh_region_may_contain_throw ()
+{
+ struct eh_region *region;
+
+ region = cfun->eh->cur_region;
+ while (region && !region->may_contain_throw)
+ {
+ region->may_contain_throw = 1;
+ region = region->outer;
+ }
+}
+
/* Return an rtl expression for a pointer to the exception object
within a handler. */
@@ -1044,7 +847,7 @@ get_exception_pointer (fun)
rtx exc_ptr = fun->eh->exc_ptr;
if (fun == cfun && ! exc_ptr)
{
- exc_ptr = gen_reg_rtx (Pmode);
+ exc_ptr = gen_reg_rtx (ptr_mode);
fun->eh->exc_ptr = exc_ptr;
}
return exc_ptr;
@@ -1066,55 +869,6 @@ get_exception_filter (fun)
return filter;
}
-/* Begin a region that will contain entries created with
- add_partial_entry. */
-
-void
-begin_protect_partials ()
-{
- /* Push room for a new list. */
- cfun->eh->protect_list
- = tree_cons (NULL_TREE, NULL_TREE, cfun->eh->protect_list);
-}
-
-/* Start a new exception region for a region of code that has a
- cleanup action and push the HANDLER for the region onto
- protect_list. All of the regions created with add_partial_entry
- will be ended when end_protect_partials is invoked.
-
- ??? The only difference between this purpose and that of
- expand_decl_cleanup is that in this case, we only want the cleanup to
- run if an exception is thrown. This should also be handled using
- binding levels. */
-
-void
-add_partial_entry (handler)
- tree handler;
-{
- expand_eh_region_start ();
-
- /* Add this entry to the front of the list. */
- TREE_VALUE (cfun->eh->protect_list)
- = tree_cons (NULL_TREE, handler, TREE_VALUE (cfun->eh->protect_list));
-}
-
-/* End all the pending exception regions on protect_list. */
-
-void
-end_protect_partials ()
-{
- tree t;
-
- /* Pop the topmost entry. */
- t = TREE_VALUE (cfun->eh->protect_list);
- cfun->eh->protect_list = TREE_CHAIN (cfun->eh->protect_list);
-
- /* End all the exception regions. */
- for (; t; t = TREE_CHAIN (t))
- expand_eh_region_end_cleanup (TREE_VALUE (t));
-}
-
-
/* This section is for the exception handling specific optimization pass. */
/* Random access the exception region tree. It's just as simple to
@@ -1130,7 +884,8 @@ collect_eh_region_array ()
if (! i)
return;
- array = xcalloc (cfun->eh->last_region_number + 1, sizeof (*array));
+ array = ggc_alloc_cleared ((cfun->eh->last_region_number + 1)
+ * sizeof (*array));
cfun->eh->region_array = array;
while (1)
@@ -1219,7 +974,7 @@ remove_fixup_regions ()
/* Allow GC to maybe free some memory. */
if (fixup->type == ERT_CLEANUP)
- fixup->u.cleanup.exp = NULL_TREE;
+ fixup->u.cleanup.exp = NULL_TREE;
if (fixup->type != ERT_FIXUP)
continue;
@@ -1275,23 +1030,23 @@ remove_unreachable_regions (insns)
continue;
if (r->resume)
- {
+ {
if (uid_region_num[INSN_UID (r->resume)])
abort ();
uid_region_num[INSN_UID (r->resume)] = i;
- }
+ }
if (r->label)
- {
+ {
if (uid_region_num[INSN_UID (r->label)])
abort ();
uid_region_num[INSN_UID (r->label)] = i;
- }
+ }
if (r->type == ERT_TRY && r->u.try.continue_label)
- {
+ {
if (uid_region_num[INSN_UID (r->u.try.continue_label)])
abort ();
uid_region_num[INSN_UID (r->u.try.continue_label)] = i;
- }
+ }
}
for (insn = insns; insn; insn = NEXT_INSN (insn))
@@ -1431,12 +1186,12 @@ add_ehl_entry (label, region)
LABEL_PRESERVE_P (label) = 1;
- entry = (struct ehl_map_entry *) xmalloc (sizeof (*entry));
+ entry = (struct ehl_map_entry *) ggc_alloc (sizeof (*entry));
entry->label = label;
entry->region = region;
slot = (struct ehl_map_entry **)
- htab_find_slot (exception_handler_label_map, entry, INSERT);
+ htab_find_slot (cfun->eh->exception_handler_label_map, entry, INSERT);
/* Before landing pad creation, each exception handler has its own
label. After landing pad creation, the exception handlers may
@@ -1448,29 +1203,20 @@ add_ehl_entry (label, region)
*slot = entry;
}
-static void
-ehl_free (pentry)
- PTR pentry;
-{
- struct ehl_map_entry *entry = (struct ehl_map_entry *)pentry;
- LABEL_PRESERVE_P (entry->label) = 0;
- free (entry);
-}
-
void
find_exception_handler_labels ()
{
int i;
- if (exception_handler_label_map)
- htab_empty (exception_handler_label_map);
+ if (cfun->eh->exception_handler_label_map)
+ htab_empty (cfun->eh->exception_handler_label_map);
else
{
/* ??? The expansion factor here (3/2) must be greater than the htab
occupancy factor (4/3) to avoid unnecessary resizing. */
- exception_handler_label_map
- = htab_create (cfun->eh->last_region_number * 3 / 2,
- ehl_hash, ehl_eq, ehl_free);
+ cfun->eh->exception_handler_label_map
+ = htab_create_ggc (cfun->eh->last_region_number * 3 / 2,
+ ehl_hash, ehl_eq, NULL);
}
if (cfun->eh->region_tree == NULL)
@@ -1522,7 +1268,7 @@ duplicate_eh_region_1 (o, map)
struct inline_remap *map;
{
struct eh_region *n
- = (struct eh_region *) xcalloc (1, sizeof (struct eh_region));
+ = (struct eh_region *) ggc_alloc_cleared (sizeof (struct eh_region));
n->region_number = o->region_number + cfun->eh->last_region_number;
n->type = o->type;
@@ -1583,9 +1329,9 @@ duplicate_eh_region_2 (o, n_array)
case ERT_CATCH:
if (o->u.catch.next_catch)
- n->u.catch.next_catch = n_array[o->u.catch.next_catch->region_number];
+ n->u.catch.next_catch = n_array[o->u.catch.next_catch->region_number];
if (o->u.catch.prev_catch)
- n->u.catch.prev_catch = n_array[o->u.catch.prev_catch->region_number];
+ n->u.catch.prev_catch = n_array[o->u.catch.prev_catch->region_number];
break;
default:
@@ -1687,23 +1433,6 @@ t2r_hash (pentry)
return TYPE_HASH (TREE_PURPOSE (entry));
}
-static int
-t2r_mark_1 (slot, data)
- PTR *slot;
- PTR data ATTRIBUTE_UNUSED;
-{
- tree contents = (tree) *slot;
- ggc_mark_tree (contents);
- return 1;
-}
-
-static void
-t2r_mark (addr)
- PTR addr;
-{
- htab_traverse (*(htab_t *)addr, t2r_mark_1, NULL);
-}
-
static void
add_type_for_runtime (type)
tree type;
@@ -1735,7 +1464,7 @@ lookup_type_for_runtime (type)
/* Represent an entry in @TTypes for either catch actions
or exception filter actions. */
-struct ttypes_filter
+struct ttypes_filter GTY(())
{
tree t;
int filter;
@@ -1968,7 +1697,6 @@ build_post_landing_pads ()
struct eh_region *c;
for (c = region->u.try.catch; c ; c = c->u.catch.next_catch)
{
- /* ??? _Unwind_ForcedUnwind wants no match here. */
if (c->u.catch.type_list == NULL)
emit_jump (c->label);
else
@@ -2003,7 +1731,7 @@ build_post_landing_pads ()
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, region->u.try.catch->label);
+ emit_insn_before (seq, region->u.try.catch->label);
break;
case ERT_ALLOWED_EXCEPTIONS:
@@ -2027,7 +1755,7 @@ build_post_landing_pads ()
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, region->label);
+ emit_insn_before (seq, region->label);
break;
case ERT_CLEANUP:
@@ -2080,11 +1808,11 @@ connect_post_landing_pads ()
emit_jump (outer->post_landing_pad);
else
emit_library_call (unwind_resume_libfunc, LCT_THROW,
- VOIDmode, 1, cfun->eh->exc_ptr, Pmode);
+ VOIDmode, 1, cfun->eh->exc_ptr, ptr_mode);
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, region->resume);
+ emit_insn_before (seq, region->resume);
delete_insn (region->resume);
}
}
@@ -2153,14 +1881,14 @@ dw2_build_landing_pads ()
}
emit_move_insn (cfun->eh->exc_ptr,
- gen_rtx_REG (Pmode, EH_RETURN_DATA_REGNO (0)));
+ gen_rtx_REG (ptr_mode, EH_RETURN_DATA_REGNO (0)));
emit_move_insn (cfun->eh->filter,
gen_rtx_REG (word_mode, EH_RETURN_DATA_REGNO (1)));
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, region->post_landing_pad);
+ emit_insn_before (seq, region->post_landing_pad);
}
}
@@ -2335,7 +2063,7 @@ sjlj_mark_call_sites (lp_info)
/* Don't separate a call from it's argument loads. */
before = insn;
if (GET_CODE (insn) == CALL_INSN)
- before = find_first_parameter_load (insn, NULL_RTX);
+ before = find_first_parameter_load (insn, NULL_RTX);
start_sequence ();
mem = adjust_address (cfun->eh->sjlj_fc, TYPE_MODE (integer_type_node),
@@ -2344,7 +2072,7 @@ sjlj_mark_call_sites (lp_info)
p = get_insns ();
end_sequence ();
- emit_insns_before (p, before);
+ emit_insn_before (p, before);
last_call_site = this_call_site;
}
}
@@ -2372,7 +2100,7 @@ sjlj_emit_function_enter (dispatch_label)
if (cfun->uses_eh_lsda)
{
char buf[20];
- ASM_GENERATE_INTERNAL_LABEL (buf, "LLSDA", sjlj_funcdef_number);
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LLSDA", current_function_funcdef_no);
emit_move_insn (mem, gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)));
}
else
@@ -2411,7 +2139,7 @@ sjlj_emit_function_enter (dispatch_label)
if (GET_CODE (fn_begin) == NOTE
&& NOTE_LINE_NUMBER (fn_begin) == NOTE_INSN_FUNCTION_BEG)
break;
- emit_insns_after (seq, fn_begin);
+ emit_insn_after (seq, fn_begin);
}
/* Call back from expand_function_end to know where we should put
@@ -2441,7 +2169,7 @@ sjlj_emit_function_exit ()
post-dominates all can_throw_internal instructions. This is
the last possible moment. */
- emit_insns_after (seq, cfun->eh->sjlj_exit_after);
+ emit_insn_after (seq, cfun->eh->sjlj_exit_after);
}
static void
@@ -2505,8 +2233,8 @@ sjlj_emit_dispatch_table (dispatch_label, lp_info)
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, (cfun->eh->region_array[first_reachable]
- ->post_landing_pad));
+ emit_insn_before (seq, (cfun->eh->region_array[first_reachable]
+ ->post_landing_pad));
}
static void
@@ -2553,9 +2281,7 @@ finish_eh_generation ()
connect many of the handlers, and then type information will not
be effective. Still, this is a win over previous implementations. */
- rebuild_jump_labels (get_insns ());
- find_basic_blocks (get_insns (), max_reg_num (), 0);
- cleanup_cfg (CLEANUP_PRE_LOOP);
+ cleanup_cfg (CLEANUP_PRE_LOOP | CLEANUP_NO_INSN_DEL);
/* These registers are used by the landing pads. Make sure they
have been generated. */
@@ -2578,7 +2304,7 @@ finish_eh_generation ()
find_exception_handler_labels ();
rebuild_jump_labels (get_insns ());
find_basic_blocks (get_insns (), max_reg_num (), 0);
- cleanup_cfg (CLEANUP_PRE_LOOP);
+ cleanup_cfg (CLEANUP_PRE_LOOP | CLEANUP_NO_INSN_DEL);
}
static hashval_t
@@ -2615,16 +2341,16 @@ remove_exception_handler_label (label)
/* If exception_handler_label_map was not built yet,
there is nothing to do. */
- if (exception_handler_label_map == NULL)
+ if (cfun->eh->exception_handler_label_map == NULL)
return;
tmp.label = label;
slot = (struct ehl_map_entry **)
- htab_find_slot (exception_handler_label_map, &tmp, NO_INSERT);
+ htab_find_slot (cfun->eh->exception_handler_label_map, &tmp, NO_INSERT);
if (! slot)
abort ();
- htab_clear_slot (exception_handler_label_map, (void **) slot);
+ htab_clear_slot (cfun->eh->exception_handler_label_map, (void **) slot);
}
/* Splice REGION from the region tree etc. */
@@ -2654,7 +2380,7 @@ remove_eh_handler (region)
if (outer)
{
if (!outer->aka)
- outer->aka = BITMAP_XMALLOC ();
+ outer->aka = BITMAP_GGC_ALLOC ();
if (region->aka)
bitmap_a_or_b (outer->aka, outer->aka, region->aka);
bitmap_set_bit (outer->aka, region->region_number);
@@ -2713,8 +2439,6 @@ remove_eh_handler (region)
remove_eh_handler (try);
}
}
-
- free_region (region);
}
/* LABEL heads a basic block that is about to be deleted. If this
@@ -2737,7 +2461,7 @@ maybe_remove_eh_handler (label)
tmp.label = label;
slot = (struct ehl_map_entry **)
- htab_find_slot (exception_handler_label_map, &tmp, NO_INSERT);
+ htab_find_slot (cfun->eh->exception_handler_label_map, &tmp, NO_INSERT);
if (! slot)
return;
region = (*slot)->region;
@@ -2750,7 +2474,7 @@ maybe_remove_eh_handler (label)
are no more contained calls, which we don't see here. */
if (region->type == ERT_MUST_NOT_THROW)
{
- htab_clear_slot (exception_handler_label_map, (void **) slot);
+ htab_clear_slot (cfun->eh->exception_handler_label_map, (void **) slot);
region->label = NULL_RTX;
}
else
@@ -2764,7 +2488,7 @@ void
for_each_eh_label (callback)
void (*callback) PARAMS ((rtx));
{
- htab_traverse (exception_handler_label_map, for_each_eh_label_1,
+ htab_traverse (cfun->eh->exception_handler_label_map, for_each_eh_label_1,
(void *)callback);
}
@@ -2783,7 +2507,7 @@ for_each_eh_label_1 (pentry, data)
/* This section describes CFG exception edges for flow. */
/* For communicating between calls to reachable_next_level. */
-struct reachable_info
+struct reachable_info GTY(())
{
tree types_caught;
tree types_allowed;
@@ -2870,8 +2594,6 @@ reachable_next_level (region, type_thrown, info)
for (c = region->u.try.catch; c ; c = c->u.catch.next_catch)
{
/* A catch-all handler ends the search. */
- /* ??? _Unwind_ForcedUnwind will want outer cleanups
- to be run as well. */
if (c->u.catch.type_list == NULL)
{
add_reachable_handler (info, region, c);
@@ -2995,7 +2717,7 @@ reachable_next_level (region, type_thrown, info)
if (info && info->handlers)
{
add_reachable_handler (info, region, region);
- return RNL_CAUGHT;
+ return RNL_CAUGHT;
}
else
return RNL_BLOCKED;
@@ -3053,10 +2775,20 @@ reachable_handlers (insn)
region = region->outer;
}
- for (; region; region = region->outer)
- if (reachable_next_level (region, type_thrown, &info) >= RNL_CAUGHT)
- break;
-
+ while (region)
+ {
+ if (reachable_next_level (region, type_thrown, &info) >= RNL_CAUGHT)
+ break;
+ /* If we have processed one cleanup, there is no point in
+ processing any more of them. Each cleanup will have an edge
+ to the next outer cleanup region, so the flow graph will be
+ accurate. */
+ if (region->type == ERT_CLEANUP)
+ region = region->u.cleanup.prev_try;
+ else
+ region = region->outer;
+ }
+
return info.handlers;
}
@@ -3115,7 +2847,7 @@ can_throw_internal (insn)
if (how == RNL_BLOCKED)
return false;
if (how != RNL_NOT_CAUGHT)
- return true;
+ return true;
}
return false;
@@ -3186,25 +2918,50 @@ can_throw_external (insn)
return true;
}
-/* True if nothing in this function can throw outside this function. */
+/* Set current_function_nothrow and cfun->all_throwers_are_sibcalls. */
-bool
-nothrow_function_p ()
+void
+set_nothrow_function_flags ()
{
rtx insn;
+
+ current_function_nothrow = 1;
- if (! flag_exceptions)
- return true;
+ /* Assume cfun->all_throwers_are_sibcalls until we encounter
+ something that can throw an exception. We specifically exempt
+ CALL_INSNs that are SIBLING_CALL_P, as these are really jumps,
+ and can't throw. Most CALL_INSNs are not SIBLING_CALL_P, so this
+ is optimistic. */
+ cfun->all_throwers_are_sibcalls = 1;
+
+ if (! flag_exceptions)
+ return;
+
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (can_throw_external (insn))
- return false;
+ {
+ current_function_nothrow = 0;
+
+ if (GET_CODE (insn) != CALL_INSN || !SIBLING_CALL_P (insn))
+ {
+ cfun->all_throwers_are_sibcalls = 0;
+ return;
+ }
+ }
+
for (insn = current_function_epilogue_delay_list; insn;
insn = XEXP (insn, 1))
if (can_throw_external (insn))
- return false;
+ {
+ current_function_nothrow = 0;
- return true;
+ if (GET_CODE (insn) != CALL_INSN || !SIBLING_CALL_P (insn))
+ {
+ cfun->all_throwers_are_sibcalls = 0;
+ return;
+ }
+ }
}
@@ -3261,6 +3018,16 @@ expand_builtin_extract_return_addr (addr_tree)
{
rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, 0);
+ if (GET_MODE (addr) != Pmode
+ && GET_MODE (addr) != VOIDmode)
+ {
+#ifdef POINTERS_EXTEND_UNSIGNED
+ addr = convert_memory_address (Pmode, addr);
+#else
+ addr = convert_to_mode (Pmode, addr, 0);
+#endif
+ }
+
/* First mask out any unwanted bits. */
#ifdef MASK_RETURN_ADDR
expand_and (Pmode, addr, MASK_RETURN_ADDR, addr);
@@ -3302,77 +3069,73 @@ expand_builtin_frob_return_addr (addr_tree)
void
expand_builtin_eh_return (stackadj_tree, handler_tree)
- tree stackadj_tree, handler_tree;
+ tree stackadj_tree ATTRIBUTE_UNUSED;
+ tree handler_tree;
{
- rtx stackadj, handler;
-
- stackadj = expand_expr (stackadj_tree, cfun->eh->ehr_stackadj, VOIDmode, 0);
- handler = expand_expr (handler_tree, cfun->eh->ehr_handler, VOIDmode, 0);
+ rtx tmp;
+#ifdef EH_RETURN_STACKADJ_RTX
+ tmp = expand_expr (stackadj_tree, cfun->eh->ehr_stackadj, VOIDmode, 0);
#ifdef POINTERS_EXTEND_UNSIGNED
- if (GET_MODE (stackadj) != Pmode)
- stackadj = convert_memory_address (Pmode, stackadj);
-
- if (GET_MODE (handler) != Pmode)
- handler = convert_memory_address (Pmode, handler);
+ if (GET_MODE (tmp) != Pmode)
+ tmp = convert_memory_address (Pmode, tmp);
+#endif
+ if (!cfun->eh->ehr_stackadj)
+ cfun->eh->ehr_stackadj = copy_to_reg (tmp);
+ else if (tmp != cfun->eh->ehr_stackadj)
+ emit_move_insn (cfun->eh->ehr_stackadj, tmp);
#endif
- if (! cfun->eh->ehr_label)
- {
- cfun->eh->ehr_stackadj = copy_to_reg (stackadj);
- cfun->eh->ehr_handler = copy_to_reg (handler);
- cfun->eh->ehr_label = gen_label_rtx ();
- }
- else
- {
- if (stackadj != cfun->eh->ehr_stackadj)
- emit_move_insn (cfun->eh->ehr_stackadj, stackadj);
- if (handler != cfun->eh->ehr_handler)
- emit_move_insn (cfun->eh->ehr_handler, handler);
- }
+ tmp = expand_expr (handler_tree, cfun->eh->ehr_handler, VOIDmode, 0);
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE (tmp) != Pmode)
+ tmp = convert_memory_address (Pmode, tmp);
+#endif
+ if (!cfun->eh->ehr_handler)
+ cfun->eh->ehr_handler = copy_to_reg (tmp);
+ else if (tmp != cfun->eh->ehr_handler)
+ emit_move_insn (cfun->eh->ehr_handler, tmp);
+ if (!cfun->eh->ehr_label)
+ cfun->eh->ehr_label = gen_label_rtx ();
emit_jump (cfun->eh->ehr_label);
}
void
expand_eh_return ()
{
- rtx sa, ra, around_label;
+ rtx around_label;
if (! cfun->eh->ehr_label)
return;
- sa = EH_RETURN_STACKADJ_RTX;
- if (! sa)
- {
- error ("__builtin_eh_return not supported on this target");
- return;
- }
-
current_function_calls_eh_return = 1;
+#ifdef EH_RETURN_STACKADJ_RTX
+ emit_move_insn (EH_RETURN_STACKADJ_RTX, const0_rtx);
+#endif
+
around_label = gen_label_rtx ();
- emit_move_insn (sa, const0_rtx);
emit_jump (around_label);
emit_label (cfun->eh->ehr_label);
clobber_return_register ();
+#ifdef EH_RETURN_STACKADJ_RTX
+ emit_move_insn (EH_RETURN_STACKADJ_RTX, cfun->eh->ehr_stackadj);
+#endif
+
#ifdef HAVE_eh_return
if (HAVE_eh_return)
- emit_insn (gen_eh_return (cfun->eh->ehr_stackadj, cfun->eh->ehr_handler));
+ emit_insn (gen_eh_return (cfun->eh->ehr_handler));
else
#endif
{
- ra = EH_RETURN_HANDLER_RTX;
- if (! ra)
- {
- error ("__builtin_eh_return not supported on this target");
- ra = gen_reg_rtx (Pmode);
- }
-
- emit_move_insn (sa, cfun->eh->ehr_stackadj);
- emit_move_insn (ra, cfun->eh->ehr_handler);
+#ifdef EH_RETURN_HANDLER_RTX
+ emit_move_insn (EH_RETURN_HANDLER_RTX, cfun->eh->ehr_handler);
+#else
+ error ("__builtin_eh_return not supported on this target");
+#endif
}
emit_label (around_label);
@@ -3563,7 +3326,7 @@ add_call_site (landing_pad, action)
{
size = (size ? size * 2 : 64);
data = (struct call_site_record *)
- xrealloc (data, sizeof (*data) * size);
+ ggc_realloc (data, sizeof (*data) * size);
cfun->eh->call_site_data = data;
cfun->eh->call_site_data_size = size;
}
@@ -3847,6 +3610,33 @@ sjlj_output_call_site_table ()
call_site_base += n;
}
+/* Tell assembler to switch to the section for the exception handling
+ table. */
+
+void
+default_exception_section ()
+{
+ if (targetm.have_named_sections)
+ {
+ int flags;
+#ifdef HAVE_LD_RO_RW_SECTION_MIXING
+ int tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
+
+ flags = (! flag_pic
+ || ((tt_format & 0x70) != DW_EH_PE_absptr
+ && (tt_format & 0x70) != DW_EH_PE_aligned))
+ ? 0 : SECTION_WRITE;
+#else
+ flags = SECTION_WRITE;
+#endif
+ named_section_flags (".gcc_except_table", flags);
+ }
+ else if (flag_pic)
+ data_section ();
+ else
+ readonly_data_section ();
+}
+
void
output_function_exception_table ()
{
@@ -3859,17 +3649,12 @@ output_function_exception_table ()
int call_site_len;
#endif
int have_tt_data;
- int funcdef_number;
int tt_format_size = 0;
/* Not all functions need anything. */
if (! cfun->uses_eh_lsda)
return;
- funcdef_number = (USING_SJLJ_EXCEPTIONS
- ? sjlj_funcdef_number
- : current_funcdef_number);
-
#ifdef IA64_UNWIND_INFO
fputs ("\t.personality\t", asm_out_file);
output_addr_const (asm_out_file, eh_personality_libfunc);
@@ -3890,14 +3675,16 @@ output_function_exception_table ()
{
tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
#ifdef HAVE_AS_LEB128
- ASM_GENERATE_INTERNAL_LABEL (ttype_label, "LLSDATT", funcdef_number);
+ ASM_GENERATE_INTERNAL_LABEL (ttype_label, "LLSDATT",
+ current_function_funcdef_no);
#endif
tt_format_size = size_of_encoded_value (tt_format);
assemble_align (tt_format_size * BITS_PER_UNIT);
}
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LLSDA", funcdef_number);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LLSDA",
+ current_function_funcdef_no);
/* The LSDA header. */
@@ -3929,7 +3716,7 @@ output_function_exception_table ()
#ifdef HAVE_AS_LEB128
char ttype_after_disp_label[32];
ASM_GENERATE_INTERNAL_LABEL (ttype_after_disp_label, "LLSDATTD",
- funcdef_number);
+ current_function_funcdef_no);
dw2_asm_output_delta_uleb128 (ttype_label, ttype_after_disp_label,
"@TType base offset");
ASM_OUTPUT_LABEL (asm_out_file, ttype_after_disp_label);
@@ -3975,9 +3762,9 @@ output_function_exception_table ()
#ifdef HAVE_AS_LEB128
ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label, "LLSDACSB",
- funcdef_number);
+ current_function_funcdef_no);
ASM_GENERATE_INTERNAL_LABEL (cs_end_label, "LLSDACSE",
- funcdef_number);
+ current_function_funcdef_no);
dw2_asm_output_delta_uleb128 (cs_end_label, cs_after_size_label,
"Call-site table length");
ASM_OUTPUT_LABEL (asm_out_file, cs_after_size_label);
@@ -4019,7 +3806,7 @@ output_function_exception_table ()
assemble_integer (value, tt_format_size,
tt_format_size * BITS_PER_UNIT, 1);
else
- dw2_asm_output_encoded_addr_rtx (tt_format, value, NULL);
+ dw2_asm_output_encoded_addr_rtx (tt_format, value, NULL);
}
#ifdef HAVE_AS_LEB128
@@ -4034,7 +3821,6 @@ output_function_exception_table ()
(i ? NULL : "Exception specification table"));
function_section (current_function_decl);
-
- if (USING_SJLJ_EXCEPTIONS)
- sjlj_funcdef_number += 1;
}
+
+#include "gt-except.h"
diff --git a/contrib/gcc/except.h b/contrib/gcc/except.h
index 883a2b1..320552c 100644
--- a/contrib/gcc/except.h
+++ b/contrib/gcc/except.h
@@ -83,18 +83,9 @@ extern void expand_eh_region_end_throw PARAMS ((tree));
destroying an object twice. */
extern void expand_eh_region_end_fixup PARAMS ((tree));
-/* Begin a region that will contain entries created with
- add_partial_entry. */
-extern void begin_protect_partials PARAMS ((void));
-
-/* Create a new exception region and add the handler for the region
- onto a list. These regions will be ended (and their handlers emitted)
- when end_protect_partials is invoked. */
-extern void add_partial_entry PARAMS ((tree));
-
-/* End all of the pending exception regions that have handlers added with
- add_partial_entry. */
-extern void end_protect_partials PARAMS ((void));
+/* Note that the current EH region (if any) may contain a throw, or a
+ call to a function which itself may contain a throw. */
+extern void note_eh_region_may_contain_throw PARAMS ((void));
/* Invokes CALLBACK for every exception handler label. Only used by old
loop hackery; should not be used by new code. */
@@ -104,8 +95,8 @@ extern void for_each_eh_label PARAMS ((void (*) (rtx)));
extern bool can_throw_internal PARAMS ((rtx));
extern bool can_throw_external PARAMS ((rtx));
-/* Return nonzero if nothing in this function can throw. */
-extern bool nothrow_function_p PARAMS ((void));
+/* Set current_function_nothrow and cfun->all_throwers_are_sibcalls. */
+extern void set_nothrow_function_flags PARAMS ((void));
/* After initial rtl generation, call back to finish generating
exception support code. */
@@ -128,7 +119,7 @@ extern rtx expand_builtin_eh_return_data_regno PARAMS ((tree));
extern rtx expand_builtin_extract_return_addr PARAMS ((tree));
extern void expand_builtin_init_dwarf_reg_sizes PARAMS ((tree));
extern rtx expand_builtin_frob_return_addr PARAMS ((tree));
-extern rtx expand_builtin_dwarf_fp_regnum PARAMS ((void));
+extern rtx expand_builtin_dwarf_sp_column PARAMS ((void));
extern void expand_builtin_eh_return PARAMS ((tree, tree));
extern void expand_eh_return PARAMS ((void));
extern rtx get_exception_pointer PARAMS ((struct function *));
@@ -164,7 +155,6 @@ extern tree (*lang_eh_runtime_type) PARAMS ((tree));
#if ! (defined (EH_RETURN_DATA_REGNO) \
&& (defined (IA64_UNWIND_INFO) \
|| (DWARF2_UNWIND_INFO \
- && defined (EH_RETURN_STACKADJ_RTX) \
&& (defined (EH_RETURN_HANDLER_RTX) \
|| defined (HAVE_eh_return)))))
#define MUST_USE_SJLJ_EXCEPTIONS 1
@@ -181,9 +171,6 @@ extern tree (*lang_eh_runtime_type) PARAMS ((tree));
# ifndef EH_RETURN_DATA_REGNO
#error "EH_RETURN_DATA_REGNO required"
# endif
-# ifndef EH_RETURN_STACKADJ_RTX
- #error "EH_RETURN_STACKADJ_RTX required"
-# endif
# if !defined(EH_RETURN_HANDLER_RTX) && !defined(HAVE_eh_return)
#error "EH_RETURN_HANDLER_RTX or eh_return required"
# endif
diff --git a/contrib/gcc/explow.c b/contrib/gcc/explow.c
index 97435a7..0d9139a 100644
--- a/contrib/gcc/explow.c
+++ b/contrib/gcc/explow.c
@@ -49,6 +49,10 @@ trunc_int_for_mode (c, mode)
{
int width = GET_MODE_BITSIZE (mode);
+ /* You want to truncate to a _what_? */
+ if (! SCALAR_INT_MODE_P (mode))
+ abort ();
+
/* Canonicalize BImode to 0 and STORE_FLAG_VALUE. */
if (mode == BImode)
return c & 1 ? STORE_FLAG_VALUE : 0;
@@ -367,6 +371,7 @@ convert_memory_address (to_mode, x)
{
enum machine_mode from_mode = to_mode == ptr_mode ? Pmode : ptr_mode;
rtx temp;
+ enum rtx_code code;
/* Here we handle some special cases. If none of them apply, fall through
to the default case. */
@@ -374,55 +379,55 @@ convert_memory_address (to_mode, x)
{
case CONST_INT:
case CONST_DOUBLE:
- return x;
+ if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode))
+ code = TRUNCATE;
+ else if (POINTERS_EXTEND_UNSIGNED < 0)
+ break;
+ else if (POINTERS_EXTEND_UNSIGNED > 0)
+ code = ZERO_EXTEND;
+ else
+ code = SIGN_EXTEND;
+ temp = simplify_unary_operation (code, to_mode, x, from_mode);
+ if (temp)
+ return temp;
+ break;
case SUBREG:
- if (POINTERS_EXTEND_UNSIGNED >= 0
- && (SUBREG_PROMOTED_VAR_P (x) || REG_POINTER (SUBREG_REG (x)))
+ if ((SUBREG_PROMOTED_VAR_P (x) || REG_POINTER (SUBREG_REG (x)))
&& GET_MODE (SUBREG_REG (x)) == to_mode)
return SUBREG_REG (x);
break;
case LABEL_REF:
- if (POINTERS_EXTEND_UNSIGNED >= 0)
- {
- temp = gen_rtx_LABEL_REF (to_mode, XEXP (x, 0));
- LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x);
- return temp;
- }
+ temp = gen_rtx_LABEL_REF (to_mode, XEXP (x, 0));
+ LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x);
+ return temp;
break;
case SYMBOL_REF:
- if (POINTERS_EXTEND_UNSIGNED >= 0)
- {
- 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);
- STRING_POOL_ADDRESS_P (temp) = STRING_POOL_ADDRESS_P (x);
- return temp;
- }
+ temp = shallow_copy_rtx (x);
+ PUT_MODE (temp, to_mode);
+ return temp;
break;
case CONST:
- if (POINTERS_EXTEND_UNSIGNED >= 0)
- return gen_rtx_CONST (to_mode,
- convert_memory_address (to_mode, XEXP (x, 0)));
+ return gen_rtx_CONST (to_mode,
+ convert_memory_address (to_mode, XEXP (x, 0)));
break;
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 (POINTERS_EXTEND_UNSIGNED >= 0
- && (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))))))
+ /* For addition we can safely permute the conversion and addition
+ operation if one operand is a constant and converting the constant
+ does not change it. We can always safely permute them if we are
+ making the address narrower. */
+ if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
+ || (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && XEXP (x, 1) == convert_memory_address (to_mode, XEXP (x, 1))))
return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
convert_memory_address (to_mode, XEXP (x, 0)),
- convert_memory_address (to_mode, XEXP (x, 1)));
+ XEXP (x, 1));
break;
default:
@@ -650,8 +655,18 @@ maybe_set_unchanging (ref, t)
/* We can set RTX_UNCHANGING_P from TREE_READONLY for decls whose
initialization is only executed once, or whose initializer always
has the same value. Currently we simplify this to PARM_DECLs in the
- first case, and decls with TREE_CONSTANT initializers in the second. */
+ first case, and decls with TREE_CONSTANT initializers in the second.
+
+ We cannot do this for non-static aggregates, because of the double
+ writes that can be generated by store_constructor, depending on the
+ contents of the initializer. Yes, this does eliminate a good fraction
+ of the number of uses of RTX_UNCHANGING_P for a language like Ada.
+ It also eliminates a good quantity of bugs. Let this be incentive to
+ eliminate RTX_UNCHANGING_P entirely in favour of a more reliable
+ solution, perhaps based on alias sets. */
+
if ((TREE_READONLY (t) && DECL_P (t)
+ && (TREE_STATIC (t) || ! AGGREGATE_TYPE_P (TREE_TYPE (t)))
&& (TREE_CODE (t) == PARM_DECL
|| DECL_INITIAL (t) == NULL_TREE
|| TREE_CONSTANT (DECL_INITIAL (t))))
@@ -816,7 +831,7 @@ copy_to_suggested_reg (x, target, mode)
PUNSIGNEDP points to the signedness of the type and may be adjusted
to show what signedness to use on extension operations.
- FOR_CALL is non-zero if this call is promoting args for a call. */
+ FOR_CALL is nonzero if this call is promoting args for a call. */
enum machine_mode
promote_mode (type, mode, punsignedp, for_call)
@@ -1023,7 +1038,7 @@ emit_stack_save (save_level, psave, after)
if (sa != 0)
sa = validize_mem (sa);
emit_insn (fcn (sa, stack_pointer_rtx));
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
emit_insn_after (seq, after);
}
@@ -1076,7 +1091,17 @@ emit_stack_restore (save_level, sa, after)
}
if (sa != 0)
- sa = validize_mem (sa);
+ {
+ sa = validize_mem (sa);
+ /* These clobbers prevent the scheduler from moving
+ references to variable arrays below the code
+ that deletes (pops) the arrays. */
+ emit_insn (gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_MEM (BLKmode,
+ gen_rtx_SCRATCH (VOIDmode))));
+ emit_insn (gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_MEM (BLKmode, stack_pointer_rtx)));
+ }
if (after)
{
@@ -1084,7 +1109,7 @@ emit_stack_restore (save_level, sa, after)
start_sequence ();
emit_insn (fcn (stack_pointer_rtx, sa));
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
emit_insn_after (seq, after);
}
@@ -1216,7 +1241,7 @@ allocate_dynamic_stack_space (size, target, known_align)
always know its final value at this point in the compilation (it
might depend on the size of the outgoing parameter lists, for
example), so we must align the value to be returned in that case.
- (Note that STACK_DYNAMIC_OFFSET will have a default non-zero value if
+ (Note that STACK_DYNAMIC_OFFSET will have a default nonzero value if
STACK_POINTER_OFFSET or ACCUMULATE_OUTGOING_ARGS are defined).
We must also do an alignment operation on the returned value if
the stack pointer alignment is less strict that BIGGEST_ALIGNMENT.
@@ -1389,7 +1414,7 @@ allocate_dynamic_stack_space (size, target, known_align)
#ifdef SETJMP_VIA_SAVE_AREA
if (setjmpless_size != NULL_RTX)
{
- rtx note_target = get_last_insn ();
+ rtx note_target = get_last_insn ();
REG_NOTES (note_target)
= gen_rtx_EXPR_LIST (REG_SAVE_AREA, setjmpless_size,
@@ -1436,14 +1461,13 @@ allocate_dynamic_stack_space (size, target, known_align)
run-time routine to call to check the stack, so provide a mechanism for
calling that routine. */
-static rtx stack_check_libfunc;
+static GTY(()) rtx stack_check_libfunc;
void
set_stack_check_libfunc (libfunc)
rtx libfunc;
{
stack_check_libfunc = libfunc;
- ggc_add_rtx_root (&stack_check_libfunc, 1);
}
/* Emit one stack probe at ADDRESS, an address within the stack. */
@@ -1488,9 +1512,9 @@ probe_stack_range (first, size)
if (stack_check_libfunc != 0)
{
rtx addr = memory_address (QImode,
- gen_rtx (STACK_GROW_OP, Pmode,
- stack_pointer_rtx,
- plus_constant (size, first)));
+ gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
+ stack_pointer_rtx,
+ plus_constant (size, first)));
#ifdef POINTERS_EXTEND_UNSIGNED
if (GET_MODE (addr) != ptr_mode)
@@ -1507,9 +1531,9 @@ probe_stack_range (first, size)
{
insn_operand_predicate_fn pred;
rtx last_addr
- = force_operand (gen_rtx_STACK_GROW_OP (Pmode,
- stack_pointer_rtx,
- plus_constant (size, first)),
+ = force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
+ stack_pointer_rtx,
+ plus_constant (size, first)),
NULL_RTX);
pred = insn_data[(int) CODE_FOR_check_stack].operand[0].predicate;
@@ -1634,17 +1658,17 @@ hard_function_value (valtype, func, outgoing)
will match and we will abort later in this function. */
for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
- tmpmode != VOIDmode;
- tmpmode = GET_MODE_WIDER_MODE (tmpmode))
- {
- /* Have we found a large enough mode? */
- if (GET_MODE_SIZE (tmpmode) >= bytes)
- break;
- }
+ tmpmode != VOIDmode;
+ tmpmode = GET_MODE_WIDER_MODE (tmpmode))
+ {
+ /* Have we found a large enough mode? */
+ if (GET_MODE_SIZE (tmpmode) >= bytes)
+ break;
+ }
/* No suitable mode found. */
if (tmpmode == VOIDmode)
- abort ();
+ abort ();
PUT_MODE (val, tmpmode);
}
@@ -1698,3 +1722,5 @@ rtx_to_tree_code (code)
}
return ((int) tcode);
}
+
+#include "gt-explow.h"
diff --git a/contrib/gcc/expmed.c b/contrib/gcc/expmed.c
index ce89335..2274bda 100644
--- a/contrib/gcc/expmed.c
+++ b/contrib/gcc/expmed.c
@@ -33,6 +33,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "optabs.h"
#include "real.h"
#include "recog.h"
+#include "langhooks.h"
static void store_fixed_bit_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
@@ -53,7 +54,7 @@ static rtx extract_split_bit_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
static void do_cmp_and_jump PARAMS ((rtx, rtx, enum rtx_code,
enum machine_mode, rtx));
-/* Non-zero means divides or modulus operations are relatively cheap for
+/* Nonzero means divides or modulus operations are relatively cheap for
powers of two, so don't use branches; emit the operation instead.
Usually, this will mean that the MD file will emit non-branch
sequences. */
@@ -103,16 +104,15 @@ static int mul_highpart_cost[NUM_MACHINE_MODES];
void
init_expmed ()
{
- /* This is "some random pseudo register" for purposes of calling recog
- to see what insns exist. */
- rtx reg = gen_rtx_REG (word_mode, 10000);
- rtx shift_insn, shiftadd_insn, shiftsub_insn;
+ rtx reg, shift_insn, shiftadd_insn, shiftsub_insn;
int dummy;
int m;
enum machine_mode mode, wider_mode;
start_sequence ();
+ /* This is "some random pseudo register" for purposes of calling recog
+ to see what insns exist. */
reg = gen_rtx_REG (word_mode, 10000);
zero_cost = rtx_cost (const0_rtx, 0);
@@ -143,19 +143,18 @@ init_expmed ()
for (m = 1; m < MAX_BITS_PER_WORD; m++)
{
+ rtx c_int = GEN_INT ((HOST_WIDE_INT) 1 << m);
shift_cost[m] = shiftadd_cost[m] = shiftsub_cost[m] = 32000;
XEXP (SET_SRC (PATTERN (shift_insn)), 1) = GEN_INT (m);
if (recog (PATTERN (shift_insn), shift_insn, &dummy) >= 0)
shift_cost[m] = rtx_cost (SET_SRC (PATTERN (shift_insn)), SET);
- XEXP (XEXP (SET_SRC (PATTERN (shiftadd_insn)), 0), 1)
- = GEN_INT ((HOST_WIDE_INT) 1 << m);
+ XEXP (XEXP (SET_SRC (PATTERN (shiftadd_insn)), 0), 1) = c_int;
if (recog (PATTERN (shiftadd_insn), shiftadd_insn, &dummy) >= 0)
shiftadd_cost[m] = rtx_cost (SET_SRC (PATTERN (shiftadd_insn)), SET);
- XEXP (XEXP (SET_SRC (PATTERN (shiftsub_insn)), 0), 1)
- = GEN_INT ((HOST_WIDE_INT) 1 << m);
+ XEXP (XEXP (SET_SRC (PATTERN (shiftsub_insn)), 0), 1) = c_int;
if (recog (PATTERN (shiftsub_insn), shiftsub_insn, &dummy) >= 0)
shiftsub_cost[m] = rtx_cost (SET_SRC (PATTERN (shiftsub_insn)), SET);
}
@@ -347,7 +346,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, total_size)
&& (GET_CODE (op0) != MEM
? ((GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD
|| GET_MODE_SIZE (GET_MODE (op0)) == GET_MODE_SIZE (fieldmode))
- && byte_offset % GET_MODE_SIZE (fieldmode) == 0)
+ && byte_offset % GET_MODE_SIZE (fieldmode) == 0)
: (! SLOW_UNALIGNED_ACCESS (fieldmode, MEM_ALIGN (op0))
|| (offset * BITS_PER_UNIT % bitsize == 0
&& MEM_ALIGN (op0) % GET_MODE_BITSIZE (fieldmode) == 0))))
@@ -535,7 +534,9 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, total_size)
structure fields. */
if (GET_MODE_CLASS (GET_MODE (value)) != MODE_INT
&& GET_MODE_CLASS (GET_MODE (value)) != MODE_PARTIAL_INT)
- value = gen_lowpart (word_mode, value);
+ value = gen_lowpart ((GET_MODE (value) == VOIDmode
+ ? word_mode : int_mode_for_mode (GET_MODE (value))),
+ value);
/* Now OFFSET is nonzero only if OP0 is memory
and is therefore always measured in bytes. */
@@ -656,7 +657,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, total_size)
value1 = gen_lowpart (maxmode, value1);
}
else if (GET_CODE (value) == CONST_INT)
- value1 = GEN_INT (trunc_int_for_mode (INTVAL (value), maxmode));
+ value1 = gen_int_mode (INTVAL (value), maxmode);
else if (!CONSTANT_P (value))
/* Parse phase is supposed to make VALUE's data type
match that of the component reference, which is a type
@@ -675,7 +676,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, total_size)
if (pat)
emit_insn (pat);
else
- {
+ {
delete_insns_since (last);
store_fixed_bit_field (op0, offset, bitsize, bitpos, value);
}
@@ -737,8 +738,8 @@ store_fixed_bit_field (op0, offset, bitsize, bitpos, value)
mode = GET_MODE (op0);
if (GET_MODE_BITSIZE (mode) == 0
- || GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (word_mode))
- mode = word_mode;
+ || GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (word_mode))
+ mode = word_mode;
mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0));
@@ -1032,25 +1033,15 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
if (tmode == VOIDmode)
tmode = mode;
+
while (GET_CODE (op0) == SUBREG)
{
- int outer_size = GET_MODE_BITSIZE (GET_MODE (op0));
- int inner_size = GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)));
-
- offset += SUBREG_BYTE (op0) / UNITS_PER_WORD;
-
- inner_size = MIN (inner_size, BITS_PER_WORD);
-
- if (BYTES_BIG_ENDIAN && (outer_size < inner_size))
+ bitpos += SUBREG_BYTE (op0) * BITS_PER_UNIT;
+ if (bitpos > unit)
{
- bitpos += inner_size - outer_size;
- if (bitpos > unit)
- {
- offset += (bitpos / unit);
- bitpos %= unit;
- }
+ offset += (bitpos / unit);
+ bitpos %= unit;
}
-
op0 = SUBREG_REG (op0);
}
@@ -1087,9 +1078,13 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
set_mem_expr (op0, 0);
}
- /* ??? We currently assume TARGET is at least as big as BITSIZE.
- If that's wrong, the solution is to test for it and set TARGET to 0
- if needed. */
+ /* Extraction of a full-word or multi-word value from a structure
+ in a register or aligned memory can be done with just a SUBREG.
+ A subword value in the least significant part of a register
+ can also be extracted with a SUBREG. For this, we need the
+ byte offset of the value in op0. */
+
+ byte_offset = bitpos / BITS_PER_UNIT + offset * UNITS_PER_WORD;
/* If OP0 is a register, BITPOS must count within a word.
But as we have it, it counts within whatever size OP0 now has.
@@ -1099,18 +1094,13 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
&& unit > GET_MODE_BITSIZE (GET_MODE (op0)))
bitpos += unit - GET_MODE_BITSIZE (GET_MODE (op0));
- /* Extracting a full-word or multi-word value
- from a structure in a register or aligned memory.
- This can be done with just SUBREG.
- So too extracting a subword value in
- the least significant part of the register. */
-
- byte_offset = (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
- + (offset * UNITS_PER_WORD);
+ /* ??? We currently assume TARGET is at least as big as BITSIZE.
+ If that's wrong, the solution is to test for it and set TARGET to 0
+ if needed. */
mode1 = (VECTOR_MODE_P (tmode)
- ? mode
- : mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0));
+ ? mode
+ : mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0));
if (((GET_CODE (op0) != MEM
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
@@ -1928,12 +1918,12 @@ expand_shift (code, mode, shifted, amount, target, unsignedp)
if (SHIFT_COUNT_TRUNCATED)
{
if (GET_CODE (op1) == CONST_INT
- && ((unsigned HOST_WIDE_INT) INTVAL (op1) >=
+ && ((unsigned HOST_WIDE_INT) INTVAL (op1) >=
(unsigned HOST_WIDE_INT) GET_MODE_BITSIZE (mode)))
- op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
+ op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
% GET_MODE_BITSIZE (mode));
else if (GET_CODE (op1) == SUBREG
- && SUBREG_BYTE (op1) == 0)
+ && subreg_lowpart_p (op1))
op1 = SUBREG_REG (op1);
}
#endif
@@ -2566,8 +2556,8 @@ expand_mult (mode, op0, op1, target, unsignedp)
there is no difference between signed and unsigned. */
op0 = expand_binop (mode,
! unsignedp
- && flag_trapv && (GET_MODE_CLASS(mode) == MODE_INT)
- ? smulv_optab : smul_optab,
+ && flag_trapv && (GET_MODE_CLASS(mode) == MODE_INT)
+ ? smulv_optab : smul_optab,
op0, op1, target, unsignedp, OPTAB_LIB_WIDEN);
if (op0 == 0)
abort ();
@@ -2790,7 +2780,7 @@ expand_mult_highpart (mode, op0, cnst1, target, unsignedp, max_cost)
if (size > HOST_BITS_PER_WIDE_INT)
abort ();
- op1 = GEN_INT (trunc_int_for_mode (cnst1, mode));
+ op1 = gen_int_mode (cnst1, mode);
wide_op1
= immed_double_const (cnst1,
@@ -2932,7 +2922,7 @@ expand_mult_highpart (mode, op0, cnst1, target, unsignedp, max_cost)
the result is exact for inputs up to 0x1fffffff.
The input range can be reduced by using cross-sum rules.
For odd divisors >= 3, the following table gives right shift counts
- so that if an number is shifted by an integer multiple of the given
+ so that if a number is shifted by an integer multiple of the given
amount, the remainder stays the same:
2, 4, 3, 6, 10, 12, 4, 8, 18, 6, 11, 20, 18, 0, 5, 10, 12, 0, 12, 20,
14, 12, 23, 21, 8, 0, 20, 18, 0, 0, 6, 12, 0, 22, 0, 18, 20, 30, 0, 0,
@@ -3012,9 +3002,9 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
if (! unsignedp && op1 == constm1_rtx)
{
if (rem_flag)
- return const0_rtx;
+ return const0_rtx;
return expand_unop (mode, flag_trapv && GET_MODE_CLASS(mode) == MODE_INT
- ? negv_optab : neg_optab, op0, target, 0);
+ ? negv_optab : neg_optab, op0, target, 0);
}
if (target
@@ -3277,7 +3267,7 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
if (rem_flag && d < 0)
{
d = abs_d;
- op1 = GEN_INT (trunc_int_for_mode (abs_d, compute_mode));
+ op1 = gen_int_mode (abs_d, compute_mode);
}
if (d == 1)
@@ -3316,8 +3306,8 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
t1 = copy_to_mode_reg (compute_mode, op0);
do_cmp_and_jump (t1, const0_rtx, GE,
compute_mode, label);
- expand_inc (t1, GEN_INT (trunc_int_for_mode
- (abs_d - 1, compute_mode)));
+ expand_inc (t1, gen_int_mode (abs_d - 1,
+ compute_mode));
emit_label (label);
quotient = expand_shift (RSHIFT_EXPR, compute_mode, t1,
build_int_2 (lgup, 0),
@@ -3857,8 +3847,7 @@ expand_divmod (rem_flag, code, mode, op0, op1, target, unsignedp)
t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
build_int_2 (pre_shift, 0), NULL_RTX, unsignedp);
quotient = expand_mult (compute_mode, t1,
- GEN_INT (trunc_int_for_mode
- (ml, compute_mode)),
+ gen_int_mode (ml, compute_mode),
NULL_RTX, 0);
insn = get_last_insn ();
@@ -4112,21 +4101,22 @@ make_tree (type, x)
make_tree (type, XEXP (x, 1))));
case LSHIFTRT:
+ t = (*lang_hooks.types.unsigned_type) (type);
return fold (convert (type,
- build (RSHIFT_EXPR, unsigned_type (type),
- make_tree (unsigned_type (type),
- XEXP (x, 0)),
+ build (RSHIFT_EXPR, t,
+ make_tree (t, XEXP (x, 0)),
make_tree (type, XEXP (x, 1)))));
case ASHIFTRT:
+ t = (*lang_hooks.types.signed_type) (type);
return fold (convert (type,
- build (RSHIFT_EXPR, signed_type (type),
- make_tree (signed_type (type), XEXP (x, 0)),
+ build (RSHIFT_EXPR, t,
+ make_tree (t, XEXP (x, 0)),
make_tree (type, XEXP (x, 1)))));
case DIV:
if (TREE_CODE (type) != REAL_TYPE)
- t = signed_type (type);
+ t = (*lang_hooks.types.signed_type) (type);
else
t = type;
@@ -4135,7 +4125,7 @@ make_tree (type, x)
make_tree (t, XEXP (x, 0)),
make_tree (t, XEXP (x, 1)))));
case UDIV:
- t = unsigned_type (type);
+ t = (*lang_hooks.types.unsigned_type) (type);
return fold (convert (type,
build (TRUNC_DIV_EXPR, t,
make_tree (t, XEXP (x, 0)),
@@ -4143,7 +4133,8 @@ make_tree (type, x)
case SIGN_EXTEND:
case ZERO_EXTEND:
- t = type_for_mode (GET_MODE (XEXP (x, 0)), GET_CODE (x) == ZERO_EXTEND);
+ t = (*lang_hooks.types.type_for_mode) (GET_MODE (XEXP (x, 0)),
+ GET_CODE (x) == ZERO_EXTEND);
return fold (convert (type, make_tree (t, XEXP (x, 0))));
default:
@@ -4165,12 +4156,50 @@ make_tree (type, x)
}
}
+/* Check whether the multiplication X * MULT + ADD overflows.
+ X, MULT and ADD must be CONST_*.
+ MODE is the machine mode for the computation.
+ X and MULT must have mode MODE. ADD may have a different mode.
+ So can X (defaults to same as MODE).
+ UNSIGNEDP is nonzero to do unsigned multiplication. */
+
+bool
+const_mult_add_overflow_p (x, mult, add, mode, unsignedp)
+ rtx x, mult, add;
+ enum machine_mode mode;
+ int unsignedp;
+{
+ tree type, mult_type, add_type, result;
+
+ type = (*lang_hooks.types.type_for_mode) (mode, unsignedp);
+
+ /* In order to get a proper overflow indication from an unsigned
+ type, we have to pretend that it's a sizetype. */
+ mult_type = type;
+ if (unsignedp)
+ {
+ mult_type = copy_node (type);
+ TYPE_IS_SIZETYPE (mult_type) = 1;
+ }
+
+ add_type = (GET_MODE (add) == VOIDmode ? mult_type
+ : (*lang_hooks.types.type_for_mode) (GET_MODE (add), unsignedp));
+
+ result = fold (build (PLUS_EXPR, mult_type,
+ fold (build (MULT_EXPR, mult_type,
+ make_tree (mult_type, x),
+ make_tree (mult_type, mult))),
+ make_tree (add_type, add)));
+
+ return TREE_CONSTANT_OVERFLOW (result);
+}
+
/* Return an rtx representing the value of X * MULT + ADD.
TARGET is a suggestion for where to store the result (an rtx).
MODE is the machine mode for the computation.
X and MULT must have mode MODE. ADD may have a different mode.
So can X (defaults to same as MODE).
- UNSIGNEDP is non-zero to do unsigned multiplication.
+ UNSIGNEDP is nonzero to do unsigned multiplication.
This may emit insns. */
rtx
@@ -4179,9 +4208,10 @@ expand_mult_add (x, target, mult, add, mode, unsignedp)
enum machine_mode mode;
int unsignedp;
{
- tree type = type_for_mode (mode, unsignedp);
+ tree type = (*lang_hooks.types.type_for_mode) (mode, unsignedp);
tree add_type = (GET_MODE (add) == VOIDmode
- ? type : type_for_mode (GET_MODE (add), unsignedp));
+ ? type: (*lang_hooks.types.type_for_mode) (GET_MODE (add),
+ unsignedp));
tree result = fold (build (PLUS_EXPR, type,
fold (build (MULT_EXPR, type,
make_tree (type, x),
@@ -4311,19 +4341,27 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
{
if (code == EQ || code == NE)
{
+ rtx op00, op01, op0both;
+
/* Do a logical OR of the two words and compare the result. */
- rtx op0h = gen_highpart (word_mode, op0);
- rtx op0l = gen_lowpart (word_mode, op0);
- rtx op0both = expand_binop (word_mode, ior_optab, op0h, op0l,
- NULL_RTX, unsignedp, OPTAB_DIRECT);
+ op00 = simplify_gen_subreg (word_mode, op0, mode, 0);
+ op01 = simplify_gen_subreg (word_mode, op0, mode, UNITS_PER_WORD);
+ op0both = expand_binop (word_mode, ior_optab, op00, op01,
+ NULL_RTX, unsignedp, OPTAB_DIRECT);
if (op0both != 0)
return emit_store_flag (target, code, op0both, op1, word_mode,
unsignedp, normalizep);
}
else if (code == LT || code == GE)
- /* If testing the sign bit, can just test on high word. */
- return emit_store_flag (target, code, gen_highpart (word_mode, op0),
- op1, word_mode, unsignedp, normalizep);
+ {
+ rtx op0h;
+
+ /* If testing the sign bit, can just test on high word. */
+ op0h = simplify_gen_subreg (word_mode, op0, mode,
+ subreg_highpart_offset (word_mode, mode));
+ return emit_store_flag (target, code, op0h, op1, word_mode,
+ unsignedp, normalizep);
+ }
}
/* From now on, we won't change CODE, so set ICODE now. */
@@ -4583,7 +4621,7 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep)
if (code == EQ || code == NE)
{
/* For EQ or NE, one way to do the comparison is to apply an operation
- that converts the operand into a positive number if it is non-zero
+ that converts the operand into a positive number if it is nonzero
or zero if it was originally zero. Then, for EQ, we subtract 1 and
for NE we negate. This puts the result in the sign bit. Then we
normalize with a shift, if needed.
diff --git a/contrib/gcc/expr.c b/contrib/gcc/expr.c
index 2a13cd4..de68218 100644
--- a/contrib/gcc/expr.c
+++ b/contrib/gcc/expr.c
@@ -22,9 +22,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
#include "machmode.h"
+#include "real.h"
#include "rtl.h"
#include "tree.h"
-#include "obstack.h"
#include "flags.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -75,6 +75,15 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define CASE_VECTOR_PC_RELATIVE 0
#endif
+/* Convert defined/undefined to boolean. */
+#ifdef TARGET_MEM_FUNCTIONS
+#undef TARGET_MEM_FUNCTIONS
+#define TARGET_MEM_FUNCTIONS 1
+#else
+#define TARGET_MEM_FUNCTIONS 0
+#endif
+
+
/* If this is nonzero, we do not bother generating VOLATILE
around volatile memory references, and we are willing to
output indirect addresses. If cse is to follow, we reject
@@ -119,14 +128,17 @@ struct store_by_pieces
int reverse;
};
-extern struct obstack permanent_obstack;
-
static rtx enqueue_insn PARAMS ((rtx, rtx));
static unsigned HOST_WIDE_INT move_by_pieces_ninsns
PARAMS ((unsigned HOST_WIDE_INT,
unsigned int));
static void move_by_pieces_1 PARAMS ((rtx (*) (rtx, ...), enum machine_mode,
struct move_by_pieces *));
+static bool block_move_libcall_safe_for_call_parm PARAMS ((void));
+static bool emit_block_move_via_movstr PARAMS ((rtx, rtx, rtx, unsigned));
+static rtx emit_block_move_via_libcall PARAMS ((rtx, rtx, rtx));
+static tree emit_block_move_libcall_fn PARAMS ((int));
+static void emit_block_move_via_loop PARAMS ((rtx, rtx, rtx, unsigned));
static rtx clear_by_pieces_1 PARAMS ((PTR, HOST_WIDE_INT,
enum machine_mode));
static void clear_by_pieces PARAMS ((rtx, unsigned HOST_WIDE_INT,
@@ -136,6 +148,10 @@ static void store_by_pieces_1 PARAMS ((struct store_by_pieces *,
static void store_by_pieces_2 PARAMS ((rtx (*) (rtx, ...),
enum machine_mode,
struct store_by_pieces *));
+static bool clear_storage_via_clrstr PARAMS ((rtx, rtx, unsigned));
+static rtx clear_storage_via_libcall PARAMS ((rtx, rtx));
+static tree clear_storage_libcall_fn PARAMS ((int));
+static rtx compress_float_constant PARAMS ((rtx, rtx));
static rtx get_subtarget PARAMS ((rtx));
static int is_zeros_p PARAMS ((tree));
static int mostly_zeros_p PARAMS ((tree));
@@ -169,6 +185,10 @@ static void do_tablejump PARAMS ((rtx, enum machine_mode, rtx, rtx, rtx));
static char direct_load[NUM_MACHINE_MODES];
static char direct_store[NUM_MACHINE_MODES];
+/* Record for each mode whether we can float-extend from memory. */
+
+static bool float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
+
/* If a memory-to-memory move would take MOVE_RATIO or more simple
move-instruction sequences, we will do a movstr or libcall instead. */
@@ -188,13 +208,32 @@ static char direct_store[NUM_MACHINE_MODES];
(move_by_pieces_ninsns (SIZE, ALIGN) < (unsigned int) MOVE_RATIO)
#endif
+/* If a clear memory operation would take CLEAR_RATIO or more simple
+ move-instruction sequences, we will do a clrstr or libcall instead. */
+
+#ifndef CLEAR_RATIO
+#if defined (HAVE_clrstrqi) || defined (HAVE_clrstrhi) || defined (HAVE_clrstrsi) || defined (HAVE_clrstrdi) || defined (HAVE_clrstrti)
+#define CLEAR_RATIO 2
+#else
+/* If we are optimizing for space, cut down the default clear ratio. */
+#define CLEAR_RATIO (optimize_size ? 3 : 15)
+#endif
+#endif
+
+/* This macro is used to determine whether clear_by_pieces should be
+ called to clear storage. */
+#ifndef CLEAR_BY_PIECES_P
+#define CLEAR_BY_PIECES_P(SIZE, ALIGN) \
+ (move_by_pieces_ninsns (SIZE, ALIGN) < (unsigned int) CLEAR_RATIO)
+#endif
+
/* This array records the insn_code of insns to perform block moves. */
enum insn_code movstr_optab[NUM_MACHINE_MODES];
/* This array records the insn_code of insns to perform block clears. */
enum insn_code clrstr_optab[NUM_MACHINE_MODES];
-/* SLOW_UNALIGNED_ACCESS is non-zero if unaligned accesses are very slow. */
+/* SLOW_UNALIGNED_ACCESS is nonzero if unaligned accesses are very slow. */
#ifndef SLOW_UNALIGNED_ACCESS
#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
@@ -210,8 +249,7 @@ init_expr_once ()
enum machine_mode mode;
int num_clobbers;
rtx mem, mem1;
-
- start_sequence ();
+ rtx reg;
/* Try indexing by frame ptr and try by stack ptr.
It is known that on the Convex the stack ptr isn't a valid index.
@@ -219,18 +257,23 @@ init_expr_once ()
mem = gen_rtx_MEM (VOIDmode, stack_pointer_rtx);
mem1 = gen_rtx_MEM (VOIDmode, frame_pointer_rtx);
- insn = emit_insn (gen_rtx_SET (0, NULL_RTX, NULL_RTX));
- pat = PATTERN (insn);
+ /* A scratch register we can modify in-place below to avoid
+ useless RTL allocations. */
+ reg = gen_rtx_REG (VOIDmode, -1);
+
+ insn = rtx_alloc (INSN);
+ pat = gen_rtx_SET (0, NULL_RTX, NULL_RTX);
+ PATTERN (insn) = pat;
for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES;
mode = (enum machine_mode) ((int) mode + 1))
{
int regno;
- rtx reg;
direct_load[(int) mode] = direct_store[(int) mode] = 0;
PUT_MODE (mem, mode);
PUT_MODE (mem1, mode);
+ PUT_MODE (reg, mode);
/* See if there is some register that can be used in this mode and
directly loaded or stored from memory. */
@@ -243,7 +286,7 @@ init_expr_once ()
if (! HARD_REGNO_MODE_OK (regno, mode))
continue;
- reg = gen_rtx_REG (mode, regno);
+ REGNO (reg) = regno;
SET_SRC (pat) = mem;
SET_DEST (pat) = reg;
@@ -267,7 +310,27 @@ init_expr_once ()
}
}
- end_sequence ();
+ mem = gen_rtx_MEM (VOIDmode, gen_rtx_raw_REG (Pmode, 10000));
+
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ {
+ enum machine_mode srcmode;
+ for (srcmode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); srcmode != mode;
+ srcmode = GET_MODE_WIDER_MODE (srcmode))
+ {
+ enum insn_code ic;
+
+ ic = can_extend_p (mode, srcmode, 0);
+ if (ic == CODE_FOR_nothing)
+ continue;
+
+ PUT_MODE (mem, srcmode);
+
+ if ((*insn_data[ic].operand[1].predicate) (mem, srcmode))
+ float_extend_from_mem[mode][srcmode] = true;
+ }
+ }
}
/* This is run at the start of compiling a function. */
@@ -275,7 +338,7 @@ init_expr_once ()
void
init_expr ()
{
- cfun->expr = (struct expr_status *) xmalloc (sizeof (struct expr_status));
+ cfun->expr = (struct expr_status *) ggc_alloc (sizeof (struct expr_status));
pending_chain = 0;
pending_stack_adjust = 0;
@@ -286,26 +349,6 @@ init_expr ()
forced_labels = 0;
}
-void
-mark_expr_status (p)
- struct expr_status *p;
-{
- if (p == NULL)
- return;
-
- ggc_mark_rtx (p->x_saveregs_value);
- ggc_mark_rtx (p->x_apply_args_value);
- ggc_mark_rtx (p->x_forced_labels);
-}
-
-void
-free_expr_status (f)
- struct function *f;
-{
- free (f->expr);
- f->expr = NULL;
-}
-
/* Small sanity check that the queue is empty at the end of a function. */
void
@@ -466,13 +509,29 @@ emit_queue ()
{
rtx body = QUEUED_BODY (p);
- if (GET_CODE (body) == SEQUENCE)
+ switch (GET_CODE (body))
{
- QUEUED_INSN (p) = XVECEXP (QUEUED_BODY (p), 0, 0);
- emit_insn (QUEUED_BODY (p));
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case CODE_LABEL:
+ case BARRIER:
+ case NOTE:
+ QUEUED_INSN (p) = body;
+ emit_insn (body);
+ break;
+
+#ifdef ENABLE_CHECKING
+ case SEQUENCE:
+ abort ();
+ break;
+#endif
+
+ default:
+ QUEUED_INSN (p) = emit_insn (body);
+ break;
}
- else
- QUEUED_INSN (p) = emit_insn (QUEUED_BODY (p));
+
pending_chain = QUEUED_NEXT (p);
}
}
@@ -495,7 +554,8 @@ convert_move (to, from, unsignedp)
rtx libcall;
/* rtx code for making an equivalent value. */
- enum rtx_code equiv_code = (unsignedp ? ZERO_EXTEND : SIGN_EXTEND);
+ enum rtx_code equiv_code = (unsignedp < 0 ? UNKNOWN
+ : (unsignedp ? ZERO_EXTEND : SIGN_EXTEND));
to = protect_from_queue (to, 1);
from = protect_from_queue (from, 0);
@@ -1337,6 +1397,8 @@ convert_modes (mode, oldmode, x, unsignedp)
&& ((GET_CODE (x) == MEM && ! MEM_VOLATILE_P (x)
&& direct_load[(int) mode])
|| (GET_CODE (x) == REG
+ && (! HARD_REGISTER_P (x)
+ || HARD_REGNO_MODE_OK (REGNO (x), mode))
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
GET_MODE_BITSIZE (GET_MODE (x)))))))))
{
@@ -1356,7 +1418,7 @@ convert_modes (mode, oldmode, x, unsignedp)
&& (val & ((HOST_WIDE_INT) 1 << (width - 1))))
val |= (HOST_WIDE_INT) (-1) << width;
- return GEN_INT (trunc_int_for_mode (val, mode));
+ return gen_int_mode (val, mode);
}
return gen_lowpart (mode, x);
@@ -1378,6 +1440,13 @@ convert_modes (mode, oldmode, x, unsignedp)
#define MOVE_MAX_PIECES MOVE_MAX
#endif
+/* STORE_MAX_PIECES is the number of bytes at a time that we can
+ store efficiently. Due to internal GCC limitations, this is
+ MOVE_MAX_PIECES limited by the number of bytes GCC can represent
+ for an immediate constant. */
+
+#define STORE_MAX_PIECES MIN (MOVE_MAX_PIECES, 2 * sizeof (HOST_WIDE_INT))
+
/* Generate several move instructions to copy LEN bytes from block FROM to
block TO. (These are MEM rtx's with BLKmode). The caller must pass FROM
and TO through protect_from_queue before calling.
@@ -1608,33 +1677,53 @@ move_by_pieces_1 (genfun, mode, data)
}
}
-/* Emit code to move a block Y to a block X.
- This may be done with string-move instructions,
- with multiple scalar move instructions, or with a library call.
+/* Emit code to move a block Y to a block X. This may be done with
+ string-move instructions, with multiple scalar move instructions,
+ or with a library call.
- Both X and Y must be MEM rtx's (perhaps inside VOLATILE)
- with mode BLKmode.
+ Both X and Y must be MEM rtx's (perhaps inside VOLATILE) with mode BLKmode.
SIZE is an rtx that says how long they are.
ALIGN is the maximum alignment we can assume they have.
+ METHOD describes what kind of copy this is, and what mechanisms may be used.
Return the address of the new block, if memcpy is called and returns it,
0 otherwise. */
rtx
-emit_block_move (x, y, size)
- rtx x, y;
- rtx size;
+emit_block_move (x, y, size, method)
+ rtx x, y, size;
+ enum block_op_methods method;
{
+ bool may_use_call;
rtx retval = 0;
-#ifdef TARGET_MEM_FUNCTIONS
- static tree fn;
- tree call_expr, arg_list;
-#endif
- unsigned int align = MIN (MEM_ALIGN (x), MEM_ALIGN (y));
+ unsigned int align;
+
+ switch (method)
+ {
+ case BLOCK_OP_NORMAL:
+ may_use_call = true;
+ break;
+
+ case BLOCK_OP_CALL_PARM:
+ may_use_call = block_move_libcall_safe_for_call_parm ();
+
+ /* Make inhibit_defer_pop nonzero around the library call
+ to force it to pop the arguments right away. */
+ NO_DEFER_POP;
+ break;
+
+ case BLOCK_OP_NO_LIBCALL:
+ may_use_call = false;
+ break;
+
+ default:
+ abort ();
+ }
+
+ align = MIN (MEM_ALIGN (x), MEM_ALIGN (y));
if (GET_MODE (x) != BLKmode)
abort ();
-
if (GET_MODE (y) != BLKmode)
abort ();
@@ -1649,164 +1738,347 @@ emit_block_move (x, y, size)
if (size == 0)
abort ();
+ /* Set MEM_SIZE as appropriate for this block copy. The main place this
+ can be incorrect is coming from __builtin_memcpy. */
+ if (GET_CODE (size) == CONST_INT)
+ {
+ x = shallow_copy_rtx (x);
+ y = shallow_copy_rtx (y);
+ set_mem_size (x, size);
+ set_mem_size (y, size);
+ }
+
if (GET_CODE (size) == CONST_INT && MOVE_BY_PIECES_P (INTVAL (size), align))
move_by_pieces (x, y, INTVAL (size), align);
+ else if (emit_block_move_via_movstr (x, y, size, align))
+ ;
+ else if (may_use_call)
+ retval = emit_block_move_via_libcall (x, y, size);
+ else
+ emit_block_move_via_loop (x, y, size, align);
+
+ if (method == BLOCK_OP_CALL_PARM)
+ OK_DEFER_POP;
+
+ return retval;
+}
+
+/* A subroutine of emit_block_move. Returns true if calling the
+ block move libcall will not clobber any parameters which may have
+ already been placed on the stack. */
+
+static bool
+block_move_libcall_safe_for_call_parm ()
+{
+ if (PUSH_ARGS)
+ return true;
else
{
- /* Try the most limited insn first, because there's no point
- including more than one in the machine description unless
- the more limited one has some advantage. */
-
- rtx opalign = GEN_INT (align / BITS_PER_UNIT);
- enum machine_mode mode;
-
- /* Since this is a move insn, we don't care about volatility. */
- volatile_ok = 1;
-
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- {
- enum insn_code code = movstr_optab[(int) mode];
- insn_operand_predicate_fn pred;
-
- if (code != CODE_FOR_nothing
- /* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT
- here because if SIZE is less than the mode mask, as it is
- returned by the macro, it will definitely be less than the
- actual mode mask. */
- && ((GET_CODE (size) == CONST_INT
- && ((unsigned HOST_WIDE_INT) INTVAL (size)
- <= (GET_MODE_MASK (mode) >> 1)))
- || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
- && ((pred = insn_data[(int) code].operand[0].predicate) == 0
- || (*pred) (x, BLKmode))
- && ((pred = insn_data[(int) code].operand[1].predicate) == 0
- || (*pred) (y, BLKmode))
- && ((pred = insn_data[(int) code].operand[3].predicate) == 0
- || (*pred) (opalign, VOIDmode)))
- {
- rtx op2;
- rtx last = get_last_insn ();
- rtx pat;
+ /* Check to see whether memcpy takes all register arguments. */
+ static enum {
+ takes_regs_uninit, takes_regs_no, takes_regs_yes
+ } takes_regs = takes_regs_uninit;
- op2 = convert_to_mode (mode, size, 1);
- pred = insn_data[(int) code].operand[2].predicate;
- if (pred != 0 && ! (*pred) (op2, mode))
- op2 = copy_to_mode_reg (mode, op2);
+ switch (takes_regs)
+ {
+ case takes_regs_uninit:
+ {
+ CUMULATIVE_ARGS args_so_far;
+ tree fn, arg;
- pat = GEN_FCN ((int) code) (x, y, op2, opalign);
- if (pat)
- {
- emit_insn (pat);
- volatile_ok = 0;
- return 0;
- }
- else
- delete_insns_since (last);
+ fn = emit_block_move_libcall_fn (false);
+ INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (fn), NULL_RTX, 0);
+
+ arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ for ( ; arg != void_list_node ; arg = TREE_CHAIN (arg))
+ {
+ enum machine_mode mode = TYPE_MODE (TREE_VALUE (arg));
+ rtx tmp = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
+ if (!tmp || !REG_P (tmp))
+ goto fail_takes_regs;
+#ifdef FUNCTION_ARG_PARTIAL_NREGS
+ if (FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode,
+ NULL_TREE, 1))
+ goto fail_takes_regs;
+#endif
+ FUNCTION_ARG_ADVANCE (args_so_far, mode, NULL_TREE, 1);
+ }
+ }
+ takes_regs = takes_regs_yes;
+ /* FALLTHRU */
+
+ case takes_regs_yes:
+ return true;
+
+ fail_takes_regs:
+ takes_regs = takes_regs_no;
+ /* FALLTHRU */
+ case takes_regs_no:
+ return false;
+
+ default:
+ abort ();
+ }
+ }
+}
+
+/* A subroutine of emit_block_move. Expand a movstr pattern;
+ return true if successful. */
+
+static bool
+emit_block_move_via_movstr (x, y, size, align)
+ rtx x, y, size;
+ unsigned int align;
+{
+ /* Try the most limited insn first, because there's no point
+ including more than one in the machine description unless
+ the more limited one has some advantage. */
+
+ rtx opalign = GEN_INT (align / BITS_PER_UNIT);
+ enum machine_mode mode;
+
+ /* Since this is a move insn, we don't care about volatility. */
+ volatile_ok = 1;
+
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ {
+ enum insn_code code = movstr_optab[(int) mode];
+ insn_operand_predicate_fn pred;
+
+ if (code != CODE_FOR_nothing
+ /* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT
+ here because if SIZE is less than the mode mask, as it is
+ returned by the macro, it will definitely be less than the
+ actual mode mask. */
+ && ((GET_CODE (size) == CONST_INT
+ && ((unsigned HOST_WIDE_INT) INTVAL (size)
+ <= (GET_MODE_MASK (mode) >> 1)))
+ || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
+ && ((pred = insn_data[(int) code].operand[0].predicate) == 0
+ || (*pred) (x, BLKmode))
+ && ((pred = insn_data[(int) code].operand[1].predicate) == 0
+ || (*pred) (y, BLKmode))
+ && ((pred = insn_data[(int) code].operand[3].predicate) == 0
+ || (*pred) (opalign, VOIDmode)))
+ {
+ rtx op2;
+ rtx last = get_last_insn ();
+ rtx pat;
+
+ op2 = convert_to_mode (mode, size, 1);
+ pred = insn_data[(int) code].operand[2].predicate;
+ if (pred != 0 && ! (*pred) (op2, mode))
+ op2 = copy_to_mode_reg (mode, op2);
+
+ /* ??? When called via emit_block_move_for_call, it'd be
+ nice if there were some way to inform the backend, so
+ that it doesn't fail the expansion because it thinks
+ emitting the libcall would be more efficient. */
+
+ pat = GEN_FCN ((int) code) (x, y, op2, opalign);
+ if (pat)
+ {
+ emit_insn (pat);
+ volatile_ok = 0;
+ return true;
}
+ else
+ delete_insns_since (last);
}
+ }
- volatile_ok = 0;
+ volatile_ok = 0;
+ return false;
+}
- /* X, Y, or SIZE may have been passed through protect_from_queue.
+/* A subroutine of emit_block_move. Expand a call to memcpy or bcopy.
+ Return the return value from memcpy, 0 otherwise. */
- It is unsafe to save the value generated by protect_from_queue
- and reuse it later. Consider what happens if emit_queue is
- called before the return value from protect_from_queue is used.
+static rtx
+emit_block_move_via_libcall (dst, src, size)
+ rtx dst, src, size;
+{
+ tree call_expr, arg_list, fn, src_tree, dst_tree, size_tree;
+ enum machine_mode size_mode;
+ rtx retval;
- Expansion of the CALL_EXPR below will call emit_queue before
- we are finished emitting RTL for argument setup. So if we are
- not careful we could get the wrong value for an argument.
+ /* DST, SRC, or SIZE may have been passed through protect_from_queue.
- To avoid this problem we go ahead and emit code to copy X, Y &
- SIZE into new pseudos. We can then place those new pseudos
- into an RTL_EXPR and use them later, even after a call to
- emit_queue.
+ It is unsafe to save the value generated by protect_from_queue
+ and reuse it later. Consider what happens if emit_queue is
+ called before the return value from protect_from_queue is used.
- Note this is not strictly needed for library calls since they
- do not call emit_queue before loading their arguments. However,
- we may need to have library calls call emit_queue in the future
- since failing to do so could cause problems for targets which
- define SMALL_REGISTER_CLASSES and pass arguments in registers. */
- x = copy_to_mode_reg (Pmode, XEXP (x, 0));
- y = copy_to_mode_reg (Pmode, XEXP (y, 0));
+ Expansion of the CALL_EXPR below will call emit_queue before
+ we are finished emitting RTL for argument setup. So if we are
+ not careful we could get the wrong value for an argument.
-#ifdef TARGET_MEM_FUNCTIONS
- size = copy_to_mode_reg (TYPE_MODE (sizetype), size);
-#else
- size = convert_to_mode (TYPE_MODE (integer_type_node), size,
- TREE_UNSIGNED (integer_type_node));
- size = copy_to_mode_reg (TYPE_MODE (integer_type_node), size);
-#endif
+ To avoid this problem we go ahead and emit code to copy X, Y &
+ SIZE into new pseudos. We can then place those new pseudos
+ into an RTL_EXPR and use them later, even after a call to
+ emit_queue.
-#ifdef TARGET_MEM_FUNCTIONS
- /* It is incorrect to use the libcall calling conventions to call
- memcpy in this context.
+ Note this is not strictly needed for library calls since they
+ do not call emit_queue before loading their arguments. However,
+ we may need to have library calls call emit_queue in the future
+ since failing to do so could cause problems for targets which
+ define SMALL_REGISTER_CLASSES and pass arguments in registers. */
- This could be a user call to memcpy and the user may wish to
- examine the return value from memcpy.
+ dst = copy_to_mode_reg (Pmode, XEXP (dst, 0));
+ src = copy_to_mode_reg (Pmode, XEXP (src, 0));
- For targets where libcalls and normal calls have different conventions
- for returning pointers, we could end up generating incorrect code.
+ if (TARGET_MEM_FUNCTIONS)
+ size_mode = TYPE_MODE (sizetype);
+ else
+ size_mode = TYPE_MODE (unsigned_type_node);
+ size = convert_to_mode (size_mode, size, 1);
+ size = copy_to_mode_reg (size_mode, size);
+
+ /* It is incorrect to use the libcall calling conventions to call
+ memcpy in this context. This could be a user call to memcpy and
+ the user may wish to examine the return value from memcpy. For
+ targets where libcalls and normal calls have different conventions
+ for returning pointers, we could end up generating incorrect code.
+
+ For convenience, we generate the call to bcopy this way as well. */
+
+ dst_tree = make_tree (ptr_type_node, dst);
+ src_tree = make_tree (ptr_type_node, src);
+ if (TARGET_MEM_FUNCTIONS)
+ size_tree = make_tree (sizetype, size);
+ else
+ size_tree = make_tree (unsigned_type_node, size);
- So instead of using a libcall sequence we build up a suitable
- CALL_EXPR and expand the call in the normal fashion. */
- if (fn == NULL_TREE)
- {
- tree fntype;
+ fn = emit_block_move_libcall_fn (true);
+ arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE);
+ if (TARGET_MEM_FUNCTIONS)
+ {
+ arg_list = tree_cons (NULL_TREE, src_tree, arg_list);
+ arg_list = tree_cons (NULL_TREE, dst_tree, arg_list);
+ }
+ else
+ {
+ arg_list = tree_cons (NULL_TREE, dst_tree, arg_list);
+ arg_list = tree_cons (NULL_TREE, src_tree, arg_list);
+ }
+
+ /* Now we have to build up the CALL_EXPR itself. */
+ call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
+ call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+ call_expr, arg_list, NULL_TREE);
+ TREE_SIDE_EFFECTS (call_expr) = 1;
+
+ retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
+
+ /* If we are initializing a readonly value, show the above call
+ clobbered it. Otherwise, a load from it may erroneously be
+ hoisted from a loop. */
+ if (RTX_UNCHANGING_P (dst))
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, dst));
+
+ return (TARGET_MEM_FUNCTIONS ? retval : NULL_RTX);
+}
- /* This was copied from except.c, I don't know if all this is
- necessary in this context or not. */
+/* A subroutine of emit_block_move_via_libcall. Create the tree node
+ for the function we use for block copies. The first time FOR_CALL
+ is true, we call assemble_external. */
+
+static GTY(()) tree block_move_fn;
+
+static tree
+emit_block_move_libcall_fn (for_call)
+ int for_call;
+{
+ static bool emitted_extern;
+ tree fn = block_move_fn, args;
+
+ if (!fn)
+ {
+ if (TARGET_MEM_FUNCTIONS)
+ {
fn = get_identifier ("memcpy");
- fntype = build_pointer_type (void_type_node);
- fntype = build_function_type (fntype, NULL_TREE);
- fn = build_decl (FUNCTION_DECL, fn, fntype);
- ggc_add_tree_root (&fn, 1);
- DECL_EXTERNAL (fn) = 1;
- TREE_PUBLIC (fn) = 1;
- DECL_ARTIFICIAL (fn) = 1;
- TREE_NOTHROW (fn) = 1;
- make_decl_rtl (fn, NULL);
- assemble_external (fn);
- }
-
- /* We need to make an argument list for the function call.
-
- memcpy has three arguments, the first two are void * addresses and
- the last is a size_t byte count for the copy. */
- arg_list
- = build_tree_list (NULL_TREE,
- make_tree (build_pointer_type (void_type_node), x));
- TREE_CHAIN (arg_list)
- = build_tree_list (NULL_TREE,
- make_tree (build_pointer_type (void_type_node), y));
- TREE_CHAIN (TREE_CHAIN (arg_list))
- = build_tree_list (NULL_TREE, make_tree (sizetype, size));
- TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE;
-
- /* Now we have to build up the CALL_EXPR itself. */
- call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
- call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
- call_expr, arg_list, NULL_TREE);
- TREE_SIDE_EFFECTS (call_expr) = 1;
-
- retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
-#else
- emit_library_call (bcopy_libfunc, LCT_NORMAL,
- VOIDmode, 3, y, Pmode, x, Pmode,
- convert_to_mode (TYPE_MODE (integer_type_node), size,
- TREE_UNSIGNED (integer_type_node)),
- TYPE_MODE (integer_type_node));
-#endif
+ args = build_function_type_list (ptr_type_node, ptr_type_node,
+ const_ptr_type_node, sizetype,
+ NULL_TREE);
+ }
+ else
+ {
+ fn = get_identifier ("bcopy");
+ args = build_function_type_list (void_type_node, const_ptr_type_node,
+ ptr_type_node, unsigned_type_node,
+ NULL_TREE);
+ }
- /* If we are initializing a readonly value, show the above call
- clobbered it. Otherwise, a load from it may erroneously be hoisted
- from a loop. */
- if (RTX_UNCHANGING_P (x))
- emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
+ fn = build_decl (FUNCTION_DECL, fn, args);
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ TREE_NOTHROW (fn) = 1;
+
+ block_move_fn = fn;
}
- return retval;
+ if (for_call && !emitted_extern)
+ {
+ emitted_extern = true;
+ make_decl_rtl (fn, NULL);
+ assemble_external (fn);
+ }
+
+ return fn;
+}
+
+/* A subroutine of emit_block_move. Copy the data via an explicit
+ loop. This is used only when libcalls are forbidden. */
+/* ??? It'd be nice to copy in hunks larger than QImode. */
+
+static void
+emit_block_move_via_loop (x, y, size, align)
+ rtx x, y, size;
+ unsigned int align ATTRIBUTE_UNUSED;
+{
+ rtx cmp_label, top_label, iter, x_addr, y_addr, tmp;
+ enum machine_mode iter_mode;
+
+ iter_mode = GET_MODE (size);
+ if (iter_mode == VOIDmode)
+ iter_mode = word_mode;
+
+ top_label = gen_label_rtx ();
+ cmp_label = gen_label_rtx ();
+ iter = gen_reg_rtx (iter_mode);
+
+ emit_move_insn (iter, const0_rtx);
+
+ x_addr = force_operand (XEXP (x, 0), NULL_RTX);
+ y_addr = force_operand (XEXP (y, 0), NULL_RTX);
+ do_pending_stack_adjust ();
+
+ emit_note (NULL, NOTE_INSN_LOOP_BEG);
+
+ emit_jump (cmp_label);
+ emit_label (top_label);
+
+ tmp = convert_modes (Pmode, iter_mode, iter, true);
+ x_addr = gen_rtx_PLUS (Pmode, x_addr, tmp);
+ y_addr = gen_rtx_PLUS (Pmode, y_addr, tmp);
+ x = change_address (x, QImode, x_addr);
+ y = change_address (y, QImode, y_addr);
+
+ emit_move_insn (x, y);
+
+ tmp = expand_simple_binop (iter_mode, PLUS, iter, const1_rtx, iter,
+ true, OPTAB_LIB_WIDEN);
+ if (tmp != iter)
+ emit_move_insn (iter, tmp);
+
+ emit_note (NULL, NOTE_INSN_LOOP_CONT);
+ emit_label (cmp_label);
+
+ emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
+ true, top_label);
+
+ emit_note (NULL, NOTE_INSN_LOOP_END);
}
/* Copy all or part of a value X into registers starting at REGNO.
@@ -1877,8 +2149,7 @@ move_block_from_reg (regno, x, nregs, size)
/* If SIZE is that of a mode no bigger than a word, just use that
mode's store operation. */
if (size <= UNITS_PER_WORD
- && (mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0)) != BLKmode
- && !FUNCTION_ARG_REG_LITTLE_ENDIAN)
+ && (mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0)) != BLKmode)
{
emit_move_insn (adjust_address (x, mode, 0), gen_rtx_REG (mode, regno));
return;
@@ -1887,9 +2158,7 @@ move_block_from_reg (regno, x, nregs, size)
/* Blocks smaller than a word on a BYTES_BIG_ENDIAN machine must be aligned
to the left before storing to memory. Note that the previous test
doesn't handle all cases (e.g. SIZE == 3). */
- if (size < UNITS_PER_WORD
- && BYTES_BIG_ENDIAN
- && !FUNCTION_ARG_REG_LITTLE_ENDIAN)
+ if (size < UNITS_PER_WORD && BYTES_BIG_ENDIAN)
{
rtx tem = operand_subword (x, 0, 1, BLKmode);
rtx shift;
@@ -1933,6 +2202,42 @@ move_block_from_reg (regno, x, nregs, size)
}
}
+/* Generate a PARALLEL rtx for a new non-consecutive group of registers from
+ ORIG, where ORIG is a non-consecutive group of registers represented by
+ a PARALLEL. The clone is identical to the original except in that the
+ original set of registers is replaced by a new set of pseudo registers.
+ The new set has the same modes as the original set. */
+
+rtx
+gen_group_rtx (orig)
+ rtx orig;
+{
+ int i, length;
+ rtx *tmps;
+
+ if (GET_CODE (orig) != PARALLEL)
+ abort ();
+
+ length = XVECLEN (orig, 0);
+ tmps = (rtx *) alloca (sizeof (rtx) * length);
+
+ /* Skip a NULL entry in first slot. */
+ i = XEXP (XVECEXP (orig, 0, 0), 0) ? 0 : 1;
+
+ if (i)
+ tmps[0] = 0;
+
+ for (; i < length; i++)
+ {
+ enum machine_mode mode = GET_MODE (XEXP (XVECEXP (orig, 0, i), 0));
+ rtx offset = XEXP (XVECEXP (orig, 0, i), 1);
+
+ tmps[i] = gen_rtx_EXPR_LIST (VOIDmode, gen_reg_rtx (mode), offset);
+ }
+
+ return gen_rtx_PARALLEL (GET_MODE (orig), gen_rtvec_v (length, tmps));
+}
+
/* Emit code to move a block SRC to a block DST, where DST is non-consecutive
registers represented by a PARALLEL. SSIZE represents the total size of
block SRC in bytes, or -1 if not known. */
@@ -2008,21 +2313,26 @@ emit_group_load (dst, orig_src, ssize)
}
else if (GET_CODE (src) == CONCAT)
{
- if ((bytepos == 0
- && bytelen == GET_MODE_SIZE (GET_MODE (XEXP (src, 0))))
- || (bytepos == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (XEXP (src, 0)))
- && bytelen == GET_MODE_SIZE (GET_MODE (XEXP (src, 1)))))
+ unsigned int slen = GET_MODE_SIZE (GET_MODE (src));
+ unsigned int slen0 = GET_MODE_SIZE (GET_MODE (XEXP (src, 0)));
+
+ if ((bytepos == 0 && bytelen == slen0)
+ || (bytepos != 0 && bytepos + bytelen <= slen))
{
- tmps[i] = XEXP (src, bytepos != 0);
+ /* The following assumes that the concatenated objects all
+ have the same size. In this case, a simple calculation
+ can be used to determine the object and the bit field
+ to be extracted. */
+ tmps[i] = XEXP (src, bytepos / slen0);
if (! CONSTANT_P (tmps[i])
&& (GET_CODE (tmps[i]) != REG || GET_MODE (tmps[i]) != mode))
tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT,
- 0, 1, NULL_RTX, mode, mode, ssize);
+ (bytepos % slen0) * BITS_PER_UNIT,
+ 1, NULL_RTX, mode, mode, ssize);
}
else if (bytepos == 0)
{
- rtx mem = assign_stack_temp (GET_MODE (src),
- GET_MODE_SIZE (GET_MODE (src)), 0);
+ rtx mem = assign_stack_temp (GET_MODE (src), slen, 0);
emit_move_insn (mem, src);
tmps[i] = adjust_address (mem, mode, 0);
}
@@ -2049,6 +2359,26 @@ emit_group_load (dst, orig_src, ssize)
emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0), tmps[i]);
}
+/* Emit code to move a block SRC to block DST, where SRC and DST are
+ non-consecutive groups of registers, each represented by a PARALLEL. */
+
+void
+emit_group_move (dst, src)
+ rtx dst, src;
+{
+ int i;
+
+ if (GET_CODE (src) != PARALLEL
+ || GET_CODE (dst) != PARALLEL
+ || XVECLEN (src, 0) != XVECLEN (dst, 0))
+ abort ();
+
+ /* Skip first entry if NULL. */
+ for (i = XEXP (XVECEXP (src, 0, 0), 0) ? 0 : 1; i < XVECLEN (src, 0); i++)
+ emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0),
+ XEXP (XVECEXP (src, 0, i), 0));
+}
+
/* Emit code to move a block SRC to a block DST, where SRC is non-consecutive
registers represented by a PARALLEL. SSIZE represents the total size of
block DST, or -1 if not known. */
@@ -2108,7 +2438,7 @@ emit_group_store (orig_dst, src, ssize)
{
dst = gen_reg_rtx (GET_MODE (orig_dst));
/* Make life a bit easier for combine. */
- emit_move_insn (dst, const0_rtx);
+ emit_move_insn (dst, CONST0_RTX (GET_MODE (orig_dst)));
}
/* Process the pieces. */
@@ -2140,6 +2470,15 @@ emit_group_store (orig_dst, src, ssize)
bytepos -= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0)));
dest = XEXP (dst, 1);
}
+ else if (bytepos == 0 && XVECLEN (src, 0))
+ {
+ dest = assign_stack_temp (GET_MODE (dest),
+ GET_MODE_SIZE (GET_MODE (dest)), 0);
+ emit_move_insn (adjust_address (dest, GET_MODE (tmps[i]), bytepos),
+ tmps[i]);
+ dst = dest;
+ break;
+ }
else
abort ();
}
@@ -2158,7 +2497,7 @@ emit_group_store (orig_dst, src, ssize)
emit_queue ();
/* Copy from the pseudo into the (probable) hard reg. */
- if (GET_CODE (dst) == REG)
+ if (orig_dst != dst)
emit_move_insn (orig_dst, dst);
}
@@ -2192,26 +2531,17 @@ copy_blkmode_from_reg (tgtblk, srcreg, type)
}
/* This code assumes srcreg is at least a full word. If it isn't, copy it
- into a new pseudo which is a full word.
+ into a new pseudo which is a full word. */
- If FUNCTION_ARG_REG_LITTLE_ENDIAN is set and convert_to_mode does a copy,
- the wrong part of the register gets copied so we fake a type conversion
- in place. */
if (GET_MODE (srcreg) != BLKmode
&& GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
- {
- if (FUNCTION_ARG_REG_LITTLE_ENDIAN)
- srcreg = simplify_gen_subreg (word_mode, srcreg, GET_MODE (srcreg), 0);
- else
- srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type));
- }
+ srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type));
/* Structures whose size is not a multiple of a word are aligned
to the least significant byte (to the right). On a BYTES_BIG_ENDIAN
machine, this means we must skip the empty high order bytes when
calculating the bit offset. */
if (BYTES_BIG_ENDIAN
- && !FUNCTION_ARG_REG_LITTLE_ENDIAN
&& bytes % UNITS_PER_WORD)
big_endian_correction
= (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
@@ -2282,7 +2612,7 @@ use_regs (call_fusage, regno, nregs)
abort ();
for (i = 0; i < nregs; i++)
- use_reg (call_fusage, gen_rtx_REG (reg_raw_mode[regno + i], regno + i));
+ use_reg (call_fusage, regno_reg_rtx[regno + i]);
}
/* Add USE expressions to *CALL_FUSAGE for each REG contained in the
@@ -2309,6 +2639,12 @@ use_group_regs (call_fusage, regs)
}
+/* Determine whether the LEN bytes generated by CONSTFUN can be
+ stored to memory using several move instructions. CONSTFUNDATA is
+ a pointer which will be passed as argument in every CONSTFUN call.
+ ALIGN is maximum alignment we can assume. Return nonzero if a
+ call to store_by_pieces should succeed. */
+
int
can_store_by_pieces (len, constfun, constfundata, align)
unsigned HOST_WIDE_INT len;
@@ -2339,7 +2675,7 @@ can_store_by_pieces (len, constfun, constfundata, align)
{
l = len;
mode = VOIDmode;
- max_size = MOVE_MAX_PIECES + 1;
+ max_size = STORE_MAX_PIECES + 1;
while (max_size > 1)
{
for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
@@ -2450,7 +2786,7 @@ store_by_pieces_1 (data, align)
unsigned int align;
{
rtx to_addr = XEXP (data->to, 0);
- unsigned HOST_WIDE_INT max_size = MOVE_MAX_PIECES + 1;
+ unsigned HOST_WIDE_INT max_size = STORE_MAX_PIECES + 1;
enum machine_mode mode = VOIDmode, tmode;
enum insn_code icode;
@@ -2575,10 +2911,6 @@ clear_storage (object, size)
rtx object;
rtx size;
{
-#ifdef TARGET_MEM_FUNCTIONS
- static tree fn;
- tree call_expr, arg_list;
-#endif
rtx retval = 0;
unsigned int align = (GET_CODE (object) == MEM ? MEM_ALIGN (object)
: GET_MODE_ALIGNMENT (GET_MODE (object)));
@@ -2587,7 +2919,7 @@ clear_storage (object, size)
just move a zero. Otherwise, do this a piece at a time. */
if (GET_MODE (object) != BLKmode
&& GET_CODE (size) == CONST_INT
- && GET_MODE_SIZE (GET_MODE (object)) == (unsigned int) INTVAL (size))
+ && INTVAL (size) == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (object)))
emit_move_insn (object, CONST0_RTX (GET_MODE (object)));
else
{
@@ -2595,160 +2927,201 @@ clear_storage (object, size)
size = protect_from_queue (size, 0);
if (GET_CODE (size) == CONST_INT
- && MOVE_BY_PIECES_P (INTVAL (size), align))
+ && CLEAR_BY_PIECES_P (INTVAL (size), align))
clear_by_pieces (object, INTVAL (size), align);
+ else if (clear_storage_via_clrstr (object, size, align))
+ ;
else
- {
- /* Try the most limited insn first, because there's no point
- including more than one in the machine description unless
- the more limited one has some advantage. */
+ retval = clear_storage_via_libcall (object, size);
+ }
- rtx opalign = GEN_INT (align / BITS_PER_UNIT);
- enum machine_mode mode;
+ return retval;
+}
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- {
- enum insn_code code = clrstr_optab[(int) mode];
- insn_operand_predicate_fn pred;
-
- if (code != CODE_FOR_nothing
- /* We don't need MODE to be narrower than
- BITS_PER_HOST_WIDE_INT here because if SIZE is less than
- the mode mask, as it is returned by the macro, it will
- definitely be less than the actual mode mask. */
- && ((GET_CODE (size) == CONST_INT
- && ((unsigned HOST_WIDE_INT) INTVAL (size)
- <= (GET_MODE_MASK (mode) >> 1)))
- || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
- && ((pred = insn_data[(int) code].operand[0].predicate) == 0
- || (*pred) (object, BLKmode))
- && ((pred = insn_data[(int) code].operand[2].predicate) == 0
- || (*pred) (opalign, VOIDmode)))
- {
- rtx op1;
- rtx last = get_last_insn ();
- rtx pat;
+/* A subroutine of clear_storage. Expand a clrstr pattern;
+ return true if successful. */
- op1 = convert_to_mode (mode, size, 1);
- pred = insn_data[(int) code].operand[1].predicate;
- if (pred != 0 && ! (*pred) (op1, mode))
- op1 = copy_to_mode_reg (mode, op1);
+static bool
+clear_storage_via_clrstr (object, size, align)
+ rtx object, size;
+ unsigned int align;
+{
+ /* Try the most limited insn first, because there's no point
+ including more than one in the machine description unless
+ the more limited one has some advantage. */
- pat = GEN_FCN ((int) code) (object, op1, opalign);
- if (pat)
- {
- emit_insn (pat);
- return 0;
- }
- else
- delete_insns_since (last);
- }
+ rtx opalign = GEN_INT (align / BITS_PER_UNIT);
+ enum machine_mode mode;
+
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ {
+ enum insn_code code = clrstr_optab[(int) mode];
+ insn_operand_predicate_fn pred;
+
+ if (code != CODE_FOR_nothing
+ /* We don't need MODE to be narrower than
+ BITS_PER_HOST_WIDE_INT here because if SIZE is less than
+ the mode mask, as it is returned by the macro, it will
+ definitely be less than the actual mode mask. */
+ && ((GET_CODE (size) == CONST_INT
+ && ((unsigned HOST_WIDE_INT) INTVAL (size)
+ <= (GET_MODE_MASK (mode) >> 1)))
+ || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
+ && ((pred = insn_data[(int) code].operand[0].predicate) == 0
+ || (*pred) (object, BLKmode))
+ && ((pred = insn_data[(int) code].operand[2].predicate) == 0
+ || (*pred) (opalign, VOIDmode)))
+ {
+ rtx op1;
+ rtx last = get_last_insn ();
+ rtx pat;
+
+ op1 = convert_to_mode (mode, size, 1);
+ pred = insn_data[(int) code].operand[1].predicate;
+ if (pred != 0 && ! (*pred) (op1, mode))
+ op1 = copy_to_mode_reg (mode, op1);
+
+ pat = GEN_FCN ((int) code) (object, op1, opalign);
+ if (pat)
+ {
+ emit_insn (pat);
+ return true;
}
+ else
+ delete_insns_since (last);
+ }
+ }
- /* OBJECT or SIZE may have been passed through protect_from_queue.
+ return false;
+}
- It is unsafe to save the value generated by protect_from_queue
- and reuse it later. Consider what happens if emit_queue is
- called before the return value from protect_from_queue is used.
+/* A subroutine of clear_storage. Expand a call to memset or bzero.
+ Return the return value of memset, 0 otherwise. */
- Expansion of the CALL_EXPR below will call emit_queue before
- we are finished emitting RTL for argument setup. So if we are
- not careful we could get the wrong value for an argument.
+static rtx
+clear_storage_via_libcall (object, size)
+ rtx object, size;
+{
+ tree call_expr, arg_list, fn, object_tree, size_tree;
+ enum machine_mode size_mode;
+ rtx retval;
- To avoid this problem we go ahead and emit code to copy OBJECT
- and SIZE into new pseudos. We can then place those new pseudos
- into an RTL_EXPR and use them later, even after a call to
- emit_queue.
+ /* OBJECT or SIZE may have been passed through protect_from_queue.
- Note this is not strictly needed for library calls since they
- do not call emit_queue before loading their arguments. However,
- we may need to have library calls call emit_queue in the future
- since failing to do so could cause problems for targets which
- define SMALL_REGISTER_CLASSES and pass arguments in registers. */
- object = copy_to_mode_reg (Pmode, XEXP (object, 0));
+ It is unsafe to save the value generated by protect_from_queue
+ and reuse it later. Consider what happens if emit_queue is
+ called before the return value from protect_from_queue is used.
-#ifdef TARGET_MEM_FUNCTIONS
- size = copy_to_mode_reg (TYPE_MODE (sizetype), size);
-#else
- size = convert_to_mode (TYPE_MODE (integer_type_node), size,
- TREE_UNSIGNED (integer_type_node));
- size = copy_to_mode_reg (TYPE_MODE (integer_type_node), size);
-#endif
+ Expansion of the CALL_EXPR below will call emit_queue before
+ we are finished emitting RTL for argument setup. So if we are
+ not careful we could get the wrong value for an argument.
-#ifdef TARGET_MEM_FUNCTIONS
- /* It is incorrect to use the libcall calling conventions to call
- memset in this context.
+ To avoid this problem we go ahead and emit code to copy OBJECT
+ and SIZE into new pseudos. We can then place those new pseudos
+ into an RTL_EXPR and use them later, even after a call to
+ emit_queue.
- This could be a user call to memset and the user may wish to
- examine the return value from memset.
+ Note this is not strictly needed for library calls since they
+ do not call emit_queue before loading their arguments. However,
+ we may need to have library calls call emit_queue in the future
+ since failing to do so could cause problems for targets which
+ define SMALL_REGISTER_CLASSES and pass arguments in registers. */
- For targets where libcalls and normal calls have different
- conventions for returning pointers, we could end up generating
- incorrect code.
+ object = copy_to_mode_reg (Pmode, XEXP (object, 0));
- So instead of using a libcall sequence we build up a suitable
- CALL_EXPR and expand the call in the normal fashion. */
- if (fn == NULL_TREE)
- {
- tree fntype;
-
- /* This was copied from except.c, I don't know if all this is
- necessary in this context or not. */
- fn = get_identifier ("memset");
- fntype = build_pointer_type (void_type_node);
- fntype = build_function_type (fntype, NULL_TREE);
- fn = build_decl (FUNCTION_DECL, fn, fntype);
- ggc_add_tree_root (&fn, 1);
- DECL_EXTERNAL (fn) = 1;
- TREE_PUBLIC (fn) = 1;
- DECL_ARTIFICIAL (fn) = 1;
- TREE_NOTHROW (fn) = 1;
- make_decl_rtl (fn, NULL);
- assemble_external (fn);
- }
+ if (TARGET_MEM_FUNCTIONS)
+ size_mode = TYPE_MODE (sizetype);
+ else
+ size_mode = TYPE_MODE (unsigned_type_node);
+ size = convert_to_mode (size_mode, size, 1);
+ size = copy_to_mode_reg (size_mode, size);
- /* We need to make an argument list for the function call.
-
- memset has three arguments, the first is a void * addresses, the
- second an integer with the initialization value, the last is a
- size_t byte count for the copy. */
- arg_list
- = build_tree_list (NULL_TREE,
- make_tree (build_pointer_type (void_type_node),
- object));
- TREE_CHAIN (arg_list)
- = build_tree_list (NULL_TREE,
- make_tree (integer_type_node, const0_rtx));
- TREE_CHAIN (TREE_CHAIN (arg_list))
- = build_tree_list (NULL_TREE, make_tree (sizetype, size));
- TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE;
-
- /* Now we have to build up the CALL_EXPR itself. */
- call_expr = build1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (fn)), fn);
- call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
- call_expr, arg_list, NULL_TREE);
- TREE_SIDE_EFFECTS (call_expr) = 1;
-
- retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
-#else
- emit_library_call (bzero_libfunc, LCT_NORMAL,
- VOIDmode, 2, object, Pmode, size,
- TYPE_MODE (integer_type_node));
-#endif
+ /* It is incorrect to use the libcall calling conventions to call
+ memset in this context. This could be a user call to memset and
+ the user may wish to examine the return value from memset. For
+ targets where libcalls and normal calls have different conventions
+ for returning pointers, we could end up generating incorrect code.
+
+ For convenience, we generate the call to bzero this way as well. */
+
+ object_tree = make_tree (ptr_type_node, object);
+ if (TARGET_MEM_FUNCTIONS)
+ size_tree = make_tree (sizetype, size);
+ else
+ size_tree = make_tree (unsigned_type_node, size);
+
+ fn = clear_storage_libcall_fn (true);
+ arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE);
+ if (TARGET_MEM_FUNCTIONS)
+ arg_list = tree_cons (NULL_TREE, integer_zero_node, arg_list);
+ arg_list = tree_cons (NULL_TREE, object_tree, arg_list);
+
+ /* Now we have to build up the CALL_EXPR itself. */
+ call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
+ call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+ call_expr, arg_list, NULL_TREE);
+ TREE_SIDE_EFFECTS (call_expr) = 1;
+
+ retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
+
+ /* If we are initializing a readonly value, show the above call
+ clobbered it. Otherwise, a load from it may erroneously be
+ hoisted from a loop. */
+ if (RTX_UNCHANGING_P (object))
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, object));
+
+ return (TARGET_MEM_FUNCTIONS ? retval : NULL_RTX);
+}
+
+/* A subroutine of clear_storage_via_libcall. Create the tree node
+ for the function we use for block clears. The first time FOR_CALL
+ is true, we call assemble_external. */
+
+static GTY(()) tree block_clear_fn;
- /* If we are initializing a readonly value, show the above call
- clobbered it. Otherwise, a load from it may erroneously be
- hoisted from a loop. */
- if (RTX_UNCHANGING_P (object))
- emit_insn (gen_rtx_CLOBBER (VOIDmode, object));
+static tree
+clear_storage_libcall_fn (for_call)
+ int for_call;
+{
+ static bool emitted_extern;
+ tree fn = block_clear_fn, args;
+
+ if (!fn)
+ {
+ if (TARGET_MEM_FUNCTIONS)
+ {
+ fn = get_identifier ("memset");
+ args = build_function_type_list (ptr_type_node, ptr_type_node,
+ integer_type_node, sizetype,
+ NULL_TREE);
+ }
+ else
+ {
+ fn = get_identifier ("bzero");
+ args = build_function_type_list (void_type_node, ptr_type_node,
+ unsigned_type_node, NULL_TREE);
}
+
+ fn = build_decl (FUNCTION_DECL, fn, args);
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ TREE_NOTHROW (fn) = 1;
+
+ block_clear_fn = fn;
}
- return retval;
-}
+ if (for_call && !emitted_extern)
+ {
+ emitted_extern = true;
+ make_decl_rtl (fn, NULL);
+ assemble_external (fn);
+ }
+ return fn;
+}
+
/* Generate code to copy Y into X.
Both Y and X must have the same mode, except that
Y can be a constant with VOIDmode.
@@ -2773,10 +3146,24 @@ emit_move_insn (x, y)
/* Never force constant_p_rtx to memory. */
if (GET_CODE (y) == CONSTANT_P_RTX)
;
- else if (CONSTANT_P (y) && ! LEGITIMATE_CONSTANT_P (y))
+ else if (CONSTANT_P (y))
{
- y_cst = y;
- y = force_const_mem (mode, y);
+ if (optimize
+ && SCALAR_FLOAT_MODE_P (GET_MODE (x))
+ && (last_insn = compress_float_constant (x, y)))
+ return last_insn;
+
+ if (!LEGITIMATE_CONSTANT_P (y))
+ {
+ y_cst = y;
+ y = force_const_mem (mode, y);
+
+ /* If the target's cannot_force_const_mem prevented the spill,
+ assume that the target's move expanders will also take care
+ of the non-legitimate constant. */
+ if (!y)
+ y = y_cst;
+ }
}
/* If X or Y are memory references, verify that their addresses are valid
@@ -2826,11 +3213,7 @@ emit_move_insn_1 (x, y)
/* Expand complex moves by moving real part and imag part, if possible. */
else if ((class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
- && BLKmode != (submode = mode_for_size ((GET_MODE_UNIT_SIZE (mode)
- * BITS_PER_UNIT),
- (class == MODE_COMPLEX_INT
- ? MODE_INT : MODE_FLOAT),
- 0))
+ && BLKmode != (submode = GET_MODE_INNER (mode))
&& (mov_optab->handlers[(int) submode].insn_code
!= CODE_FOR_nothing))
{
@@ -2992,10 +3375,10 @@ emit_move_insn_1 (x, y)
return get_last_insn ();
}
- /* This will handle any multi-word mode that lacks a move_insn pattern.
- However, you will get better code if you define such patterns,
+ /* This will handle any multi-word or full-word mode that lacks a move_insn
+ pattern. However, you will get better code if you define such patterns,
even if they must turn into multiple assembler instructions. */
- else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+ else if (GET_MODE_SIZE (mode) >= UNITS_PER_WORD)
{
rtx last_insn = 0;
rtx seq, inner;
@@ -3010,7 +3393,7 @@ emit_move_insn_1 (x, y)
{
rtx temp;
enum rtx_code code;
-
+
/* Do not use anti_adjust_stack, since we don't want to update
stack_pointer_delta. */
temp = expand_binop (Pmode,
@@ -3025,18 +3408,18 @@ emit_move_insn_1 (x, y)
(GET_MODE_SIZE (GET_MODE (x)))),
stack_pointer_rtx, 0, OPTAB_LIB_WIDEN);
- if (temp != stack_pointer_rtx)
- emit_move_insn (stack_pointer_rtx, temp);
+ if (temp != stack_pointer_rtx)
+ emit_move_insn (stack_pointer_rtx, temp);
code = GET_CODE (XEXP (x, 0));
/* Just hope that small offsets off SP are OK. */
if (code == POST_INC)
- temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
GEN_INT (-((HOST_WIDE_INT)
GET_MODE_SIZE (GET_MODE (x)))));
else if (code == POST_DEC)
- temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
GEN_INT (GET_MODE_SIZE (GET_MODE (x))));
else
temp = stack_pointer_rtx;
@@ -3083,7 +3466,7 @@ emit_move_insn_1 (x, y)
last_insn = emit_move_insn (xpart, ypart);
}
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
/* Show the output dies here. This is necessary for SUBREGs
@@ -3102,6 +3485,64 @@ emit_move_insn_1 (x, y)
else
abort ();
}
+
+/* If Y is representable exactly in a narrower mode, and the target can
+ perform the extension directly from constant or memory, then emit the
+ move as an extension. */
+
+static rtx
+compress_float_constant (x, y)
+ rtx x, y;
+{
+ enum machine_mode dstmode = GET_MODE (x);
+ enum machine_mode orig_srcmode = GET_MODE (y);
+ enum machine_mode srcmode;
+ REAL_VALUE_TYPE r;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, y);
+
+ for (srcmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_srcmode));
+ srcmode != orig_srcmode;
+ srcmode = GET_MODE_WIDER_MODE (srcmode))
+ {
+ enum insn_code ic;
+ rtx trunc_y, last_insn;
+
+ /* Skip if the target can't extend this way. */
+ ic = can_extend_p (dstmode, srcmode, 0);
+ if (ic == CODE_FOR_nothing)
+ continue;
+
+ /* Skip if the narrowed value isn't exact. */
+ if (! exact_real_truncate (srcmode, &r))
+ continue;
+
+ trunc_y = CONST_DOUBLE_FROM_REAL_VALUE (r, srcmode);
+
+ if (LEGITIMATE_CONSTANT_P (trunc_y))
+ {
+ /* Skip if the target needs extra instructions to perform
+ the extension. */
+ if (! (*insn_data[ic].operand[1].predicate) (trunc_y, srcmode))
+ continue;
+ }
+ else if (float_extend_from_mem[dstmode][srcmode])
+ trunc_y = validize_mem (force_const_mem (srcmode, trunc_y));
+ else
+ continue;
+
+ emit_unop_insn (ic, x, trunc_y, UNKNOWN);
+ last_insn = get_last_insn ();
+
+ if (GET_CODE (x) == REG)
+ REG_NOTES (last_insn)
+ = gen_rtx_EXPR_LIST (REG_EQUAL, y, REG_NOTES (last_insn));
+
+ return last_insn;
+ }
+
+ return NULL_RTX;
+}
/* Pushing data onto the stack. */
@@ -3255,7 +3696,7 @@ emit_single_push_insn (mode, x, type)
void
emit_push_insn (x, mode, type, size, align, partial, reg, extra,
args_addr, args_so_far, reg_parm_stack_space,
- alignment_pad)
+ alignment_pad)
rtx x;
enum machine_mode mode;
tree type;
@@ -3282,7 +3723,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
Default is below for small data on big-endian machines; else above. */
enum direction where_pad = FUNCTION_ARG_PADDING (mode, type);
- /* Invert direction if stack is post-decrement.
+ /* Invert direction if stack is post-decrement.
FIXME: why? */
if (STACK_PUSH_CODE == POST_DEC)
if (where_pad != none)
@@ -3380,6 +3821,18 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
args_addr,
args_so_far),
skip));
+
+ if (!ACCUMULATE_OUTGOING_ARGS)
+ {
+ /* If the source is referenced relative to the stack pointer,
+ copy it to another register to stabilize it. We do not need
+ to do this if we know that we won't be changing sp. */
+
+ if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp)
+ || reg_mentioned_p (virtual_outgoing_args_rtx, temp))
+ temp = copy_to_reg (temp);
+ }
+
target = gen_rtx_MEM (BLKmode, temp);
if (type != 0)
@@ -3391,90 +3844,12 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
of sibling calls. */
set_mem_alias_set (target, 0);
}
- else
- set_mem_align (target, align);
-
- /* TEMP is the address of the block. Copy the data there. */
- if (GET_CODE (size) == CONST_INT
- && MOVE_BY_PIECES_P ((unsigned) INTVAL (size), align))
- {
- move_by_pieces (target, xinner, INTVAL (size), align);
- goto ret;
- }
- else
- {
- rtx opalign = GEN_INT (align / BITS_PER_UNIT);
- enum machine_mode mode;
-
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- {
- enum insn_code code = movstr_optab[(int) mode];
- insn_operand_predicate_fn pred;
-
- if (code != CODE_FOR_nothing
- && ((GET_CODE (size) == CONST_INT
- && ((unsigned HOST_WIDE_INT) INTVAL (size)
- <= (GET_MODE_MASK (mode) >> 1)))
- || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
- && (!(pred = insn_data[(int) code].operand[0].predicate)
- || ((*pred) (target, BLKmode)))
- && (!(pred = insn_data[(int) code].operand[1].predicate)
- || ((*pred) (xinner, BLKmode)))
- && (!(pred = insn_data[(int) code].operand[3].predicate)
- || ((*pred) (opalign, VOIDmode))))
- {
- rtx op2 = convert_to_mode (mode, size, 1);
- rtx last = get_last_insn ();
- rtx pat;
-
- pred = insn_data[(int) code].operand[2].predicate;
- if (pred != 0 && ! (*pred) (op2, mode))
- op2 = copy_to_mode_reg (mode, op2);
-
- pat = GEN_FCN ((int) code) (target, xinner,
- op2, opalign);
- if (pat)
- {
- emit_insn (pat);
- goto ret;
- }
- else
- delete_insns_since (last);
- }
- }
- }
-
- if (!ACCUMULATE_OUTGOING_ARGS)
- {
- /* If the source is referenced relative to the stack pointer,
- copy it to another register to stabilize it. We do not need
- to do this if we know that we won't be changing sp. */
- if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp)
- || reg_mentioned_p (virtual_outgoing_args_rtx, temp))
- temp = copy_to_reg (temp);
- }
+ /* ALIGN may well be better aligned than TYPE, e.g. due to
+ PARM_BOUNDARY. Assume the caller isn't lying. */
+ set_mem_align (target, align);
- /* Make inhibit_defer_pop nonzero around the library call
- to force it to pop the bcopy-arguments right away. */
- NO_DEFER_POP;
-#ifdef TARGET_MEM_FUNCTIONS
- emit_library_call (memcpy_libfunc, LCT_NORMAL,
- VOIDmode, 3, temp, Pmode, XEXP (xinner, 0), Pmode,
- convert_to_mode (TYPE_MODE (sizetype),
- size, TREE_UNSIGNED (sizetype)),
- TYPE_MODE (sizetype));
-#else
- emit_library_call (bcopy_libfunc, LCT_NORMAL,
- VOIDmode, 3, XEXP (xinner, 0), Pmode, temp, Pmode,
- convert_to_mode (TYPE_MODE (integer_type_node),
- size,
- TREE_UNSIGNED (integer_type_node)),
- TYPE_MODE (integer_type_node));
-#endif
- OK_DEFER_POP;
+ emit_block_move (target, xinner, size, BLOCK_OP_CALL_PARM);
}
}
else if (partial > 0)
@@ -3579,10 +3954,8 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
emit_move_insn (dest, x);
}
-
}
- ret:
/* If part should go in registers, copy that part
into the appropriate registers. Do this now, at the end,
since mem-to-mem copies above may do function calls. */
@@ -3658,7 +4031,8 @@ expand_assignment (to, from, want_value, suggest_reg)
problem. */
if (TREE_CODE (to) == COMPONENT_REF || TREE_CODE (to) == BIT_FIELD_REF
- || TREE_CODE (to) == ARRAY_REF || TREE_CODE (to) == ARRAY_RANGE_REF)
+ || TREE_CODE (to) == ARRAY_REF || TREE_CODE (to) == ARRAY_RANGE_REF
+ || TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE)
{
enum machine_mode mode1;
HOST_WIDE_INT bitsize, bitpos;
@@ -3689,7 +4063,7 @@ expand_assignment (to, from, want_value, suggest_reg)
#ifdef POINTERS_EXTEND_UNSIGNED
if (GET_MODE (offset_rtx) != Pmode)
- offset_rtx = convert_memory_address (Pmode, offset_rtx);
+ offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
#else
if (GET_MODE (offset_rtx) != ptr_mode)
offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
@@ -3716,8 +4090,6 @@ expand_assignment (to, from, want_value, suggest_reg)
if (GET_CODE (to_rtx) == MEM)
{
- tree old_expr = MEM_EXPR (to_rtx);
-
/* If the field is at offset zero, we could have been given the
DECL_RTX of the parent struct. Don't munge it. */
to_rtx = shallow_copy_rtx (to_rtx);
@@ -3797,7 +4169,7 @@ expand_assignment (to, from, want_value, suggest_reg)
if (GET_CODE (to_rtx) == PARALLEL)
emit_group_load (to_rtx, value, int_size_in_bytes (TREE_TYPE (from)));
else if (GET_MODE (to_rtx) == BLKmode)
- emit_block_move (to_rtx, value, expr_size (from));
+ emit_block_move (to_rtx, value, expr_size (from), BLOCK_OP_NORMAL);
else
{
#ifdef POINTERS_EXTEND_UNSIGNED
@@ -3852,21 +4224,21 @@ expand_assignment (to, from, want_value, suggest_reg)
size = expr_size (from);
from_rtx = expand_expr (from, NULL_RTX, VOIDmode, 0);
-#ifdef TARGET_MEM_FUNCTIONS
- emit_library_call (memmove_libfunc, LCT_NORMAL,
- VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
- XEXP (from_rtx, 0), Pmode,
- convert_to_mode (TYPE_MODE (sizetype),
- size, TREE_UNSIGNED (sizetype)),
- TYPE_MODE (sizetype));
-#else
- emit_library_call (bcopy_libfunc, LCT_NORMAL,
- VOIDmode, 3, XEXP (from_rtx, 0), Pmode,
- XEXP (to_rtx, 0), Pmode,
- convert_to_mode (TYPE_MODE (integer_type_node),
- size, TREE_UNSIGNED (integer_type_node)),
- TYPE_MODE (integer_type_node));
-#endif
+ if (TARGET_MEM_FUNCTIONS)
+ emit_library_call (memmove_libfunc, LCT_NORMAL,
+ VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
+ XEXP (from_rtx, 0), Pmode,
+ convert_to_mode (TYPE_MODE (sizetype),
+ size, TREE_UNSIGNED (sizetype)),
+ TYPE_MODE (sizetype));
+ else
+ emit_library_call (bcopy_libfunc, LCT_NORMAL,
+ VOIDmode, 3, XEXP (from_rtx, 0), Pmode,
+ XEXP (to_rtx, 0), Pmode,
+ convert_to_mode (TYPE_MODE (integer_type_node),
+ size,
+ TREE_UNSIGNED (integer_type_node)),
+ TYPE_MODE (integer_type_node));
preserve_temp_slots (to_rtx);
free_temp_slots ();
@@ -3888,7 +4260,7 @@ expand_assignment (to, from, want_value, suggest_reg)
and storing the value into TARGET.
TARGET may contain a QUEUED rtx.
- If WANT_VALUE is nonzero, return a copy of the value
+ If WANT_VALUE & 1 is nonzero, return a copy of the value
not in TARGET, so that we can be sure to use the proper
value in a containing expression even if TARGET has something
else stored in it. If possible, we copy the value through a pseudo
@@ -3903,9 +4275,12 @@ expand_assignment (to, from, want_value, suggest_reg)
with no sequence point. Will other languages need this to
be more thorough?
- If WANT_VALUE is 0, we return NULL, to make sure
+ If WANT_VALUE & 1 is 0, we return NULL, to make sure
to catch quickly any cases where the caller uses the value
- and fails to set WANT_VALUE. */
+ and fails to set WANT_VALUE.
+
+ If WANT_VALUE & 2 is set, this is a store into a call param on the
+ stack, and block moves may need to be treated specially. */
rtx
store_expr (exp, target, want_value)
@@ -3917,11 +4292,22 @@ store_expr (exp, target, want_value)
int dont_return_target = 0;
int dont_store_target = 0;
+ if (VOID_TYPE_P (TREE_TYPE (exp)))
+ {
+ /* C++ can generate ?: expressions with a throw expression in one
+ branch and an rvalue in the other. Here, we resolve attempts to
+ store the throw expression's nonexistant result. */
+ if (want_value)
+ abort ();
+ expand_expr (exp, const0_rtx, VOIDmode, 0);
+ return NULL_RTX;
+ }
if (TREE_CODE (exp) == COMPOUND_EXPR)
{
/* Perform first part of compound expression, then assign from second
part. */
- expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
+ expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
+ want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
emit_queue ();
return store_expr (TREE_OPERAND (exp, 1), target, want_value);
}
@@ -3941,20 +4327,20 @@ store_expr (exp, target, want_value)
NO_DEFER_POP;
jumpifnot (TREE_OPERAND (exp, 0), lab1);
start_cleanup_deferral ();
- store_expr (TREE_OPERAND (exp, 1), target, 0);
+ store_expr (TREE_OPERAND (exp, 1), target, want_value & 2);
end_cleanup_deferral ();
emit_queue ();
emit_jump_insn (gen_jump (lab2));
emit_barrier ();
emit_label (lab1);
start_cleanup_deferral ();
- store_expr (TREE_OPERAND (exp, 2), target, 0);
+ store_expr (TREE_OPERAND (exp, 2), target, want_value & 2);
end_cleanup_deferral ();
emit_queue ();
emit_label (lab2);
OK_DEFER_POP;
- return want_value ? target : NULL_RTX;
+ return want_value & 1 ? target : NULL_RTX;
}
else if (queued_subexp_p (target))
/* If target contains a postincrement, let's not risk
@@ -3964,18 +4350,24 @@ store_expr (exp, target, want_value)
{
/* Expand EXP into a new pseudo. */
temp = gen_reg_rtx (GET_MODE (target));
- temp = expand_expr (exp, temp, GET_MODE (target), 0);
+ temp = expand_expr (exp, temp, GET_MODE (target),
+ (want_value & 2
+ ? EXPAND_STACK_PARM : EXPAND_NORMAL));
}
else
- temp = expand_expr (exp, NULL_RTX, GET_MODE (target), 0);
+ temp = expand_expr (exp, NULL_RTX, GET_MODE (target),
+ (want_value & 2
+ ? EXPAND_STACK_PARM : EXPAND_NORMAL));
/* If target is volatile, ANSI requires accessing the value
*from* the target, if it is accessed. So make that happen.
In no case return the target itself. */
- if (! MEM_VOLATILE_P (target) && want_value)
+ if (! MEM_VOLATILE_P (target) && (want_value & 1) != 0)
dont_return_target = 1;
}
- else if (want_value && GET_CODE (target) == MEM && ! MEM_VOLATILE_P (target)
+ else if ((want_value & 1) != 0
+ && GET_CODE (target) == MEM
+ && ! MEM_VOLATILE_P (target)
&& GET_MODE (target) != BLKmode)
/* If target is in memory and caller wants value in a register instead,
arrange that. Pass TARGET as target for expand_expr so that,
@@ -3984,7 +4376,8 @@ store_expr (exp, target, want_value)
Don't do this if TARGET is volatile because we are supposed
to write it and then read it. */
{
- temp = expand_expr (exp, target, GET_MODE (target), 0);
+ temp = expand_expr (exp, target, GET_MODE (target),
+ want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode)
{
/* If TEMP is already in the desired TARGET, only copy it from
@@ -3998,7 +4391,7 @@ store_expr (exp, target, want_value)
dont_return_target = 1;
}
else if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
- /* If this is an scalar in a register that is stored in a wider mode
+ /* If this is a scalar in a register that is stored in a wider mode
than the declared mode, compute the result into its declared mode
and then convert to the wider mode. Our value is the computed
expression. */
@@ -4011,30 +4404,31 @@ store_expr (exp, target, want_value)
the extend. But don't do this if the type of EXP is a subtype
of something else since then the conversion might involve
more than just converting modes. */
- if (! want_value && INTEGRAL_TYPE_P (TREE_TYPE (exp))
+ if ((want_value & 1) == 0
+ && INTEGRAL_TYPE_P (TREE_TYPE (exp))
&& TREE_TYPE (TREE_TYPE (exp)) == 0)
{
if (TREE_UNSIGNED (TREE_TYPE (exp))
!= SUBREG_PROMOTED_UNSIGNED_P (target))
- exp
- = convert
- (signed_or_unsigned_type (SUBREG_PROMOTED_UNSIGNED_P (target),
- TREE_TYPE (exp)),
- exp);
-
- exp = convert (type_for_mode (GET_MODE (SUBREG_REG (target)),
- SUBREG_PROMOTED_UNSIGNED_P (target)),
+ exp = convert
+ ((*lang_hooks.types.signed_or_unsigned_type)
+ (SUBREG_PROMOTED_UNSIGNED_P (target), TREE_TYPE (exp)), exp);
+
+ exp = convert ((*lang_hooks.types.type_for_mode)
+ (GET_MODE (SUBREG_REG (target)),
+ SUBREG_PROMOTED_UNSIGNED_P (target)),
exp);
inner_target = SUBREG_REG (target);
}
- temp = expand_expr (exp, inner_target, VOIDmode, 0);
+ temp = expand_expr (exp, inner_target, VOIDmode,
+ want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
/* If TEMP is a volatile MEM and we want a result value, make
the access now so it gets done only once. Likewise if
it contains TARGET. */
- if (GET_CODE (temp) == MEM && want_value
+ if (GET_CODE (temp) == MEM && (want_value & 1) != 0
&& (MEM_VOLATILE_P (temp)
|| reg_mentioned_p (SUBREG_REG (target), XEXP (temp, 0))))
temp = copy_to_reg (temp);
@@ -4057,14 +4451,14 @@ store_expr (exp, target, want_value)
target. Otherwise, the caller might get confused by a result whose
mode is larger than expected. */
- if (want_value && GET_MODE (temp) != GET_MODE (target))
+ if ((want_value & 1) != 0 && GET_MODE (temp) != GET_MODE (target))
{
if (GET_MODE (temp) != VOIDmode)
{
temp = gen_lowpart_SUBREG (GET_MODE (target), temp);
SUBREG_PROMOTED_VAR_P (temp) = 1;
- SUBREG_PROMOTED_UNSIGNED_P (temp)
- = SUBREG_PROMOTED_UNSIGNED_P (target);
+ SUBREG_PROMOTED_UNSIGNED_SET (temp,
+ SUBREG_PROMOTED_UNSIGNED_P (target));
}
else
temp = convert_modes (GET_MODE (target),
@@ -4072,11 +4466,12 @@ store_expr (exp, target, want_value)
temp, SUBREG_PROMOTED_UNSIGNED_P (target));
}
- return want_value ? temp : NULL_RTX;
+ return want_value & 1 ? temp : NULL_RTX;
}
else
{
- temp = expand_expr (exp, target, GET_MODE (target), 0);
+ temp = expand_expr (exp, target, GET_MODE (target),
+ want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
/* Return TARGET if it's a specified hardware register.
If TARGET is a volatile mem ref, either return TARGET
or return a reg copied *from* TARGET; ANSI requires this.
@@ -4088,7 +4483,7 @@ store_expr (exp, target, want_value)
&& REGNO (target) < FIRST_PSEUDO_REGISTER)
&& !(GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
&& ! rtx_equal_p (temp, target)
- && (CONSTANT_P (temp) || want_value))
+ && (CONSTANT_P (temp) || (want_value & 1) != 0))
dont_return_target = 1;
}
@@ -4125,7 +4520,12 @@ store_expr (exp, target, want_value)
but TARGET is not valid memory reference, TEMP will differ
from TARGET although it is really the same location. */
&& (TREE_CODE_CLASS (TREE_CODE (exp)) != 'd'
- || target != DECL_RTL_IF_SET (exp)))
+ || target != DECL_RTL_IF_SET (exp))
+ /* If there's nothing to copy, don't bother. Don't call expr_size
+ unless necessary, because some front-ends (C++) expr_size-hook
+ aborts on objects that are not supposed to be bit-copied or
+ bit-initialized. */
+ && expr_size (exp) != const0_rtx)
{
target = protect_from_queue (target, 1);
if (GET_MODE (temp) != GET_MODE (target)
@@ -4154,7 +4554,9 @@ store_expr (exp, target, want_value)
if (GET_CODE (size) == CONST_INT
&& INTVAL (size) < TREE_STRING_LENGTH (exp))
- emit_block_move (target, temp, size);
+ emit_block_move (target, temp, size,
+ (want_value & 2
+ ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
else
{
/* Compute the size of the data to copy from the string. */
@@ -4162,13 +4564,18 @@ store_expr (exp, target, want_value)
= size_binop (MIN_EXPR,
make_tree (sizetype, size),
size_int (TREE_STRING_LENGTH (exp)));
- rtx copy_size_rtx = expand_expr (copy_size, NULL_RTX,
- VOIDmode, 0);
+ rtx copy_size_rtx
+ = expand_expr (copy_size, NULL_RTX, VOIDmode,
+ (want_value & 2
+ ? EXPAND_STACK_PARM : EXPAND_NORMAL));
rtx label = 0;
/* Copy that much. */
- copy_size_rtx = convert_to_mode (ptr_mode, copy_size_rtx, 0);
- emit_block_move (target, temp, copy_size_rtx);
+ copy_size_rtx = convert_to_mode (ptr_mode, copy_size_rtx,
+ TREE_UNSIGNED (sizetype));
+ emit_block_move (target, temp, copy_size_rtx,
+ (want_value & 2
+ ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
/* Figure out how much is left in TARGET that we have to clear.
Do all calculations in ptr_mode. */
@@ -4186,8 +4593,8 @@ store_expr (exp, target, want_value)
#ifdef POINTERS_EXTEND_UNSIGNED
if (GET_MODE (copy_size_rtx) != Pmode)
- copy_size_rtx = convert_memory_address (Pmode,
- copy_size_rtx);
+ copy_size_rtx = convert_to_mode (Pmode, copy_size_rtx,
+ TREE_UNSIGNED (sizetype));
#endif
target = offset_address (target, copy_size_rtx,
@@ -4209,13 +4616,15 @@ store_expr (exp, target, want_value)
else if (GET_CODE (target) == PARALLEL)
emit_group_load (target, temp, int_size_in_bytes (TREE_TYPE (exp)));
else if (GET_MODE (temp) == BLKmode)
- emit_block_move (target, temp, expr_size (exp));
+ emit_block_move (target, temp, expr_size (exp),
+ (want_value & 2
+ ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
else
emit_move_insn (target, temp);
}
/* If we don't want a value, return NULL_RTX. */
- if (! want_value)
+ if ((want_value & 1) == 0)
return NULL_RTX;
/* If we are supposed to return TEMP, do so as long as it isn't a MEM.
@@ -4224,7 +4633,8 @@ store_expr (exp, target, want_value)
return temp;
/* Return TARGET itself if it is a hard register. */
- else if (want_value && GET_MODE (target) != BLKmode
+ else if ((want_value & 1) != 0
+ && GET_MODE (target) != BLKmode
&& ! (GET_CODE (target) == REG
&& REGNO (target) < FIRST_PSEUDO_REGISTER))
return copy_to_reg (target);
@@ -4338,7 +4748,7 @@ store_constructor_field (target, bitsize, bitpos, mode, exp, type, cleared,
{
if (TREE_CODE (exp) == CONSTRUCTOR
&& bitpos % BITS_PER_UNIT == 0
- /* If we have a non-zero bitpos for a register target, then we just
+ /* If we have a nonzero bitpos for a register target, then we just
let store_field do the bitfield handling. This is unlikely to
generate unnecessary clear instructions anyways. */
&& (bitpos == 0 || GET_CODE (target) == MEM))
@@ -4491,7 +4901,7 @@ store_constructor (exp, target, cleared, size)
#ifdef POINTERS_EXTEND_UNSIGNED
if (GET_MODE (offset_rtx) != Pmode)
- offset_rtx = convert_memory_address (Pmode, offset_rtx);
+ offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
#else
if (GET_MODE (offset_rtx) != ptr_mode)
offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
@@ -4526,7 +4936,8 @@ store_constructor (exp, target, cleared, size)
if (TYPE_PRECISION (type) < BITS_PER_WORD)
{
- type = type_for_size (BITS_PER_WORD, TREE_UNSIGNED (type));
+ type = (*lang_hooks.types.type_for_size)
+ (BITS_PER_WORD, TREE_UNSIGNED (type));
value = convert (type, value);
}
@@ -4924,9 +5335,7 @@ store_constructor (exp, target, cleared, size)
tree startbit = TREE_PURPOSE (elt);
/* End of range of element, or element value. */
tree endbit = TREE_VALUE (elt);
-#ifdef TARGET_MEM_FUNCTIONS
HOST_WIDE_INT startb, endb;
-#endif
rtx bitlength_rtx, startbit_rtx, endbit_rtx, targetx;
bitlength_rtx = expand_expr (bitlength,
@@ -4955,7 +5364,8 @@ store_constructor (exp, target, cleared, size)
{
targetx
= assign_temp
- ((build_qualified_type (type_for_mode (GET_MODE (target), 0),
+ ((build_qualified_type ((*lang_hooks.types.type_for_mode)
+ (GET_MODE (target), 0),
TYPE_QUAL_CONST)),
0, 1, 1);
emit_move_insn (targetx, target);
@@ -4966,11 +5376,10 @@ store_constructor (exp, target, cleared, size)
else
abort ();
-#ifdef TARGET_MEM_FUNCTIONS
- /* Optimization: If startbit and endbit are
- constants divisible by BITS_PER_UNIT,
- call memset instead. */
- if (TREE_CODE (startbit) == INTEGER_CST
+ /* Optimization: If startbit and endbit are constants divisible
+ by BITS_PER_UNIT, call memset instead. */
+ if (TARGET_MEM_FUNCTIONS
+ && TREE_CODE (startbit) == INTEGER_CST
&& TREE_CODE (endbit) == INTEGER_CST
&& (startb = TREE_INT_CST_LOW (startbit)) % BITS_PER_UNIT == 0
&& (endb = TREE_INT_CST_LOW (endbit) + 1) % BITS_PER_UNIT == 0)
@@ -4985,7 +5394,6 @@ store_constructor (exp, target, cleared, size)
TYPE_MODE (sizetype));
}
else
-#endif
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__setbits"),
LCT_NORMAL, VOIDmode, 4, XEXP (targetx, 0),
Pmode, bitlength_rtx, TYPE_MODE (sizetype),
@@ -5139,7 +5547,8 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type,
target = adjust_address (target, VOIDmode, bitpos / BITS_PER_UNIT);
emit_block_move (target, temp,
GEN_INT ((bitsize + BITS_PER_UNIT - 1)
- / BITS_PER_UNIT));
+ / BITS_PER_UNIT),
+ BLOCK_OP_NORMAL);
return value_mode == VOIDmode ? const0_rtx : target;
}
@@ -5164,8 +5573,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type,
if (unsignedp)
return expand_and (tmode, temp,
- GEN_INT (trunc_int_for_mode (width_mask,
- tmode)),
+ gen_int_mode (width_mask, tmode),
NULL_RTX);
count = build_int_2 (GET_MODE_BITSIZE (tmode) - bitsize, 0);
@@ -5630,22 +6038,31 @@ safe_from_p (x, exp, top_p)
case 'x':
if (TREE_CODE (exp) == TREE_LIST)
- return ((TREE_VALUE (exp) == 0
- || safe_from_p (x, TREE_VALUE (exp), 0))
- && (TREE_CHAIN (exp) == 0
- || safe_from_p (x, TREE_CHAIN (exp), 0)));
+ {
+ while (1)
+ {
+ if (TREE_VALUE (exp) && !safe_from_p (x, TREE_VALUE (exp), 0))
+ return 0;
+ exp = TREE_CHAIN (exp);
+ if (!exp)
+ return 1;
+ if (TREE_CODE (exp) != TREE_LIST)
+ return safe_from_p (x, exp, 0);
+ }
+ }
else if (TREE_CODE (exp) == ERROR_MARK)
return 1; /* An already-visited SAVE_EXPR? */
else
return 0;
- case '1':
- return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
-
case '2':
case '<':
- return (safe_from_p (x, TREE_OPERAND (exp, 0), 0)
- && safe_from_p (x, TREE_OPERAND (exp, 1), 0));
+ if (!safe_from_p (x, TREE_OPERAND (exp, 1), 0))
+ return 0;
+ /* FALLTHRU */
+
+ case '1':
+ return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
case 'e':
case 'r':
@@ -6043,7 +6460,14 @@ find_placeholder (exp, plist)
EXPAND_CONST_ADDRESS says that it is okay to return a MEM
with a constant address even if that address is not normally legitimate.
- EXPAND_INITIALIZER and EXPAND_SUM also have this effect. */
+ EXPAND_INITIALIZER and EXPAND_SUM also have this effect.
+
+ EXPAND_STACK_PARM is used when expanding to a TARGET on the stack for
+ a call parameter. Such targets require special care as we haven't yet
+ marked TARGET so that it's safe from being trashed by libcalls. We
+ don't want to use TARGET for anything but the final result;
+ Intermediate values must go elsewhere. Additionally, calls to
+ emit_block_move will be flagged with BLOCK_OP_CALL_PARM. */
rtx
expand_expr (exp, target, tmode, modifier)
@@ -6186,7 +6610,7 @@ expand_expr (exp, target, tmode, modifier)
if (! cse_not_expected && mode != BLKmode && target
&& (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER)
&& ! (code == CONSTRUCTOR && GET_MODE_SIZE (mode) > UNITS_PER_WORD))
- target = subtarget;
+ target = 0;
switch (code)
{
@@ -6219,7 +6643,7 @@ expand_expr (exp, target, tmode, modifier)
}
case PARM_DECL:
- if (! DECL_RTL_SET_P (exp))
+ if (!DECL_RTL_SET_P (exp))
{
error_with_decl (exp, "prior parameter's size depends on `%s'");
return CONST0_RTX (mode);
@@ -6230,23 +6654,10 @@ expand_expr (exp, target, tmode, modifier)
case VAR_DECL:
/* If a static var's type was incomplete when the decl was written,
but the type is complete now, lay out the decl now. */
- if (DECL_SIZE (exp) == 0 && COMPLETE_TYPE_P (TREE_TYPE (exp))
+ if (DECL_SIZE (exp) == 0
+ && COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (TREE_TYPE (exp))
&& (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
- {
- rtx value = DECL_RTL_IF_SET (exp);
-
- layout_decl (exp, 0);
-
- /* If the RTL was already set, update its mode and memory
- attributes. */
- if (value != 0)
- {
- PUT_MODE (value, DECL_MODE (exp));
- SET_DECL_RTL (exp, 0);
- set_mem_attributes (value, exp, 1);
- SET_DECL_RTL (exp, value);
- }
- }
+ layout_decl (exp, 0);
/* ... fall through ... */
@@ -6287,7 +6698,7 @@ expand_expr (exp, target, tmode, modifier)
DECL_NONLOCAL (exp) = 1;
if (DECL_NO_STATIC_CHAIN (current_function_decl))
abort ();
- mark_addressable (exp);
+ (*lang_hooks.mark_addressable) (exp);
if (GET_CODE (DECL_RTL (exp)) != MEM)
abort ();
addr = XEXP (DECL_RTL (exp), 0);
@@ -6344,13 +6755,13 @@ expand_expr (exp, target, tmode, modifier)
/* Get the signedness used for this variable. Ensure we get the
same mode we got when the variable was declared. */
if (GET_MODE (DECL_RTL (exp))
- != promote_mode (type, DECL_MODE (exp), &unsignedp,
+ != promote_mode (type, DECL_MODE (exp), &unsignedp,
(TREE_CODE (exp) == RESULT_DECL ? 1 : 0)))
abort ();
temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp));
SUBREG_PROMOTED_VAR_P (temp) = 1;
- SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
+ SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
return temp;
}
@@ -6372,7 +6783,7 @@ expand_expr (exp, target, tmode, modifier)
return temp;
case CONST_DECL:
- return expand_expr (DECL_INITIAL (exp), target, VOIDmode, 0);
+ return expand_expr (DECL_INITIAL (exp), target, VOIDmode, modifier);
case REAL_CST:
/* If optimized, generate immediate CONST_DOUBLE
@@ -6385,7 +6796,8 @@ expand_expr (exp, target, tmode, modifier)
many insns, so we'd end up copying it to a register in any case.
Now, we do the copying in expand_binop, if appropriate. */
- return immed_real_const (exp);
+ return CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (exp),
+ TYPE_MODE (TREE_TYPE (exp)));
case COMPLEX_CST:
case STRING_CST:
@@ -6447,7 +6859,7 @@ expand_expr (exp, target, tmode, modifier)
temp = SAVE_EXPR_RTL (exp);
if (temp && GET_CODE (temp) == REG)
{
- put_var_into_stack (exp);
+ put_var_into_stack (exp, /*rescan=*/true);
temp = SAVE_EXPR_RTL (exp);
}
if (temp == 0 || GET_CODE (temp) != MEM)
@@ -6474,20 +6886,21 @@ expand_expr (exp, target, tmode, modifier)
/* If the mode of TEMP does not match that of the expression, it
must be a promoted value. We pass store_expr a SUBREG of the
wanted mode but mark it so that we know that it was already
- extended. Note that `unsignedp' was modified above in
- this case. */
+ extended. */
if (GET_CODE (temp) == REG && GET_MODE (temp) != mode)
{
temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
+ promote_mode (type, mode, &unsignedp, 0);
SUBREG_PROMOTED_VAR_P (temp) = 1;
- SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
+ SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
}
if (temp == const0_rtx)
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
else
- store_expr (TREE_OPERAND (exp, 0), temp, 0);
+ store_expr (TREE_OPERAND (exp, 0), temp,
+ modifier == EXPAND_STACK_PARM ? 2 : 0);
TREE_USED (exp) = 1;
}
@@ -6503,7 +6916,7 @@ expand_expr (exp, target, tmode, modifier)
promote_mode (type, mode, &unsignedp, 0);
temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
SUBREG_PROMOTED_VAR_P (temp) = 1;
- SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
+ SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
return temp;
}
@@ -6513,7 +6926,8 @@ expand_expr (exp, target, tmode, modifier)
{
rtx temp;
temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
- TREE_OPERAND (exp, 0) = unsave_expr_now (TREE_OPERAND (exp, 0));
+ TREE_OPERAND (exp, 0)
+ = (*lang_hooks.unsave_expr_now) (TREE_OPERAND (exp, 0));
return temp;
}
@@ -6532,9 +6946,6 @@ expand_expr (exp, target, tmode, modifier)
return temp;
}
- /* We can't find the object or there was a missing WITH_RECORD_EXPR. */
- abort ();
-
case WITH_RECORD_EXPR:
/* Put the object on the placeholder list, expand our first operand,
and pop the list. */
@@ -6592,7 +7003,7 @@ expand_expr (exp, target, tmode, modifier)
/* Mark the corresponding BLOCK for output in its proper place. */
if (TREE_OPERAND (exp, 2) != 0
&& ! TREE_USED (TREE_OPERAND (exp, 2)))
- insert_block (TREE_OPERAND (exp, 2));
+ (*lang_hooks.decls.insert_block) (TREE_OPERAND (exp, 2));
/* If VARS have not yet been expanded, expand them now. */
while (vars)
@@ -6618,7 +7029,7 @@ expand_expr (exp, target, tmode, modifier)
{
if (RTL_EXPR_SEQUENCE (exp) == const0_rtx)
abort ();
- emit_insns (RTL_EXPR_SEQUENCE (exp));
+ emit_insn (RTL_EXPR_SEQUENCE (exp));
RTL_EXPR_SEQUENCE (exp) = const0_rtx;
}
preserve_rtl_expr_result (RTL_EXPR_RTL (exp));
@@ -6644,7 +7055,13 @@ expand_expr (exp, target, tmode, modifier)
fold. Likewise, if we have a target we can use, it is best to
store directly into the target unless the type is large enough
that memcpy will be used. If we are making an initializer and
- all operands are constant, put it in memory as well. */
+ all operands are constant, put it in memory as well.
+
+ FIXME: Avoid trying to fill vector constructors piece-meal.
+ Output them with output_constant_def below unless we're sure
+ they're zeros. This should go away when vector initializers
+ are treated like VECTOR_CST instead of arrays.
+ */
else if ((TREE_STATIC (exp)
&& ((mode == BLKmode
&& ! (target != 0 && safe_from_p (target, exp, 1)))
@@ -6653,7 +7070,9 @@ expand_expr (exp, target, tmode, modifier)
&& (! MOVE_BY_PIECES_P
(tree_low_cst (TYPE_SIZE_UNIT (type), 1),
TYPE_ALIGN (type)))
- && ! mostly_zeros_p (exp))))
+ && ((TREE_CODE (type) == VECTOR_TYPE
+ && !is_zeros_p (exp))
+ || ! mostly_zeros_p (exp)))))
|| (modifier == EXPAND_INITIALIZER && TREE_CONSTANT (exp)))
{
rtx constructor = output_constant_def (exp, 1);
@@ -6670,7 +7089,8 @@ expand_expr (exp, target, tmode, modifier)
/* Handle calls that pass values in multiple non-contiguous
locations. The Irix 6 ABI has examples of this. */
if (target == 0 || ! safe_from_p (target, exp, 1)
- || GET_CODE (target) == PARALLEL)
+ || GET_CODE (target) == PARALLEL
+ || modifier == EXPAND_STACK_PARM)
target
= assign_temp (build_qualified_type (type,
(TYPE_QUALS (type)
@@ -6689,16 +7109,15 @@ expand_expr (exp, target, tmode, modifier)
tree string = string_constant (exp1, &index);
/* Try to optimize reads from const strings. */
- if (string
- && TREE_CODE (string) == STRING_CST
- && TREE_CODE (index) == INTEGER_CST
+ if (string
+ && TREE_CODE (string) == STRING_CST
+ && TREE_CODE (index) == INTEGER_CST
&& compare_tree_int (index, TREE_STRING_LENGTH (string)) < 0
- && GET_MODE_CLASS (mode) == MODE_INT
- && GET_MODE_SIZE (mode) == 1
+ && GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_SIZE (mode) == 1
&& modifier != EXPAND_WRITE)
- return
- GEN_INT (trunc_int_for_mode (TREE_STRING_POINTER (string)
- [TREE_INT_CST_LOW (index)], mode));
+ return gen_int_mode (TREE_STRING_POINTER (string)
+ [TREE_INT_CST_LOW (index)], mode);
op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
op0 = memory_address (mode, op0);
@@ -6741,23 +7160,27 @@ expand_expr (exp, target, tmode, modifier)
Don't fold if this is for wide characters since it's too
difficult to do correctly and this is a very rare case. */
- if (modifier != EXPAND_CONST_ADDRESS && modifier != EXPAND_INITIALIZER
+ if (modifier != EXPAND_CONST_ADDRESS
+ && modifier != EXPAND_INITIALIZER
+ && modifier != EXPAND_MEMORY
&& TREE_CODE (array) == STRING_CST
&& TREE_CODE (index) == INTEGER_CST
&& compare_tree_int (index, TREE_STRING_LENGTH (array)) < 0
&& GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == 1)
- return
- GEN_INT (trunc_int_for_mode (TREE_STRING_POINTER (array)
- [TREE_INT_CST_LOW (index)], mode));
+ return gen_int_mode (TREE_STRING_POINTER (array)
+ [TREE_INT_CST_LOW (index)], mode);
/* If this is a constant index into a constant array,
just get the value from the array. Handle both the cases when
we have an explicit constructor and when our operand is a variable
that was declared const. */
- if (modifier != EXPAND_CONST_ADDRESS && modifier != EXPAND_INITIALIZER
- && TREE_CODE (array) == CONSTRUCTOR && ! TREE_SIDE_EFFECTS (array)
+ if (modifier != EXPAND_CONST_ADDRESS
+ && modifier != EXPAND_INITIALIZER
+ && modifier != EXPAND_MEMORY
+ && TREE_CODE (array) == CONSTRUCTOR
+ && ! TREE_SIDE_EFFECTS (array)
&& TREE_CODE (index) == INTEGER_CST
&& 0 > compare_tree_int (index,
list_length (CONSTRUCTOR_ELTS
@@ -6778,6 +7201,7 @@ expand_expr (exp, target, tmode, modifier)
else if (optimize >= 1
&& modifier != EXPAND_CONST_ADDRESS
&& modifier != EXPAND_INITIALIZER
+ && modifier != EXPAND_MEMORY
&& TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
&& TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
&& TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK)
@@ -6809,9 +7233,8 @@ expand_expr (exp, target, tmode, modifier)
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == 1)
- return GEN_INT (trunc_int_for_mode
- (TREE_STRING_POINTER (init)
- [TREE_INT_CST_LOW (index)], mode));
+ return gen_int_mode (TREE_STRING_POINTER (init)
+ [TREE_INT_CST_LOW (index)], mode);
}
}
}
@@ -6847,6 +7270,9 @@ expand_expr (exp, target, tmode, modifier)
&& (GET_MODE_BITSIZE (DECL_MODE (TREE_PURPOSE (elt)))
<= HOST_BITS_PER_WIDE_INT))))
{
+ if (DECL_BIT_FIELD (TREE_PURPOSE (elt))
+ && modifier == EXPAND_STACK_PARM)
+ target = 0;
op0 = expand_expr (TREE_VALUE (elt), target, tmode, modifier);
if (DECL_BIT_FIELD (TREE_PURPOSE (elt)))
{
@@ -6901,10 +7327,12 @@ expand_expr (exp, target, tmode, modifier)
(TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
&& (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
!= INTEGER_CST)
+ && modifier != EXPAND_STACK_PARM
? target : NULL_RTX),
VOIDmode,
(modifier == EXPAND_INITIALIZER
- || modifier == EXPAND_CONST_ADDRESS)
+ || modifier == EXPAND_CONST_ADDRESS
+ || modifier == EXPAND_STACK_PARM)
? modifier : EXPAND_NORMAL);
/* If this is a constant, put it into a register if it is a
@@ -6921,7 +7349,8 @@ expand_expr (exp, target, tmode, modifier)
if (offset != 0)
{
- rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
+ rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode,
+ EXPAND_SUM);
/* If this object is in a register, put it into memory.
This case can't occur in C, but can in Ada if we have
@@ -6934,7 +7363,8 @@ expand_expr (exp, target, tmode, modifier)
forcing the SAVE_EXPR into memory. */
if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR)
{
- put_var_into_stack (TREE_OPERAND (exp, 0));
+ put_var_into_stack (TREE_OPERAND (exp, 0),
+ /*rescan=*/true);
op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0));
}
else
@@ -6955,7 +7385,7 @@ expand_expr (exp, target, tmode, modifier)
#ifdef POINTERS_EXTEND_UNSIGNED
if (GET_MODE (offset_rtx) != Pmode)
- offset_rtx = convert_memory_address (Pmode, offset_rtx);
+ offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
#else
if (GET_MODE (offset_rtx) != ptr_mode)
offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
@@ -7056,7 +7486,9 @@ expand_expr (exp, target, tmode, modifier)
emit_block_move (target, op0,
GEN_INT ((bitsize + BITS_PER_UNIT - 1)
- / BITS_PER_UNIT));
+ / BITS_PER_UNIT),
+ (modifier == EXPAND_STACK_PARM
+ ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
return target;
}
@@ -7066,8 +7498,10 @@ expand_expr (exp, target, tmode, modifier)
if (GET_CODE (op0) == MEM && GET_CODE (XEXP (op0, 0)) == REG)
mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
- op0 = extract_bit_field (op0, bitsize, bitpos,
- unsignedp, target, ext_mode, ext_mode,
+ op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
+ (modifier == EXPAND_STACK_PARM
+ ? NULL_RTX : target),
+ ext_mode, ext_mode,
int_size_in_bytes (TREE_TYPE (tem)));
/* If the result is a record type and BITSIZE is narrower than
@@ -7084,7 +7518,8 @@ expand_expr (exp, target, tmode, modifier)
if (mode == BLKmode)
{
rtx new = assign_temp (build_qualified_type
- (type_for_mode (ext_mode, 0),
+ ((*lang_hooks.types.type_for_mode)
+ (ext_mode, 0),
TYPE_QUAL_CONST), 0, 1, 1);
emit_move_insn (new, op0);
@@ -7276,7 +7711,8 @@ expand_expr (exp, target, tmode, modifier)
{
WITH_CLEANUP_EXPR_RTL (exp)
= expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
- expand_decl_cleanup (NULL_TREE, TREE_OPERAND (exp, 1));
+ expand_decl_cleanup_eh (NULL_TREE, TREE_OPERAND (exp, 1),
+ CLEANUP_EH_ONLY (exp));
/* That's it for this cleanup. */
TREE_OPERAND (exp, 1) = 0;
@@ -7306,10 +7742,11 @@ expand_expr (exp, target, tmode, modifier)
&& (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
== FUNCTION_DECL)
&& DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
- {
+ {
if (DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
== BUILT_IN_FRONTEND)
- return (*lang_expand_expr) (exp, original_target, tmode, modifier);
+ return (*lang_hooks.expand_expr) (exp, original_target,
+ tmode, modifier);
else
return expand_builtin (exp, target, subtarget, tmode, ignore);
}
@@ -7345,7 +7782,8 @@ expand_expr (exp, target, tmode, modifier)
if (GET_CODE (target) == MEM)
/* Store data into beginning of memory target. */
store_expr (TREE_OPERAND (exp, 0),
- adjust_address (target, TYPE_MODE (valtype), 0), 0);
+ adjust_address (target, TYPE_MODE (valtype), 0),
+ modifier == EXPAND_STACK_PARM ? 2 : 0);
else if (GET_CODE (target) == REG)
/* Store this field into a union of the proper type. */
@@ -7388,7 +7826,7 @@ expand_expr (exp, target, tmode, modifier)
tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
enum machine_mode inner_mode = TYPE_MODE (inner_type);
- if (modifier == EXPAND_INITIALIZER)
+ if (modifier == EXPAND_INITIALIZER)
return simplify_gen_subreg (mode, op0, inner_mode,
subreg_lowpart_offset (mode,
inner_mode));
@@ -7469,22 +7907,21 @@ expand_expr (exp, target, tmode, modifier)
if (GET_MODE (op0) == BLKmode)
emit_block_move (new_with_op0_mode, op0,
- GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))));
+ GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))),
+ (modifier == EXPAND_STACK_PARM
+ ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
else
emit_move_insn (new_with_op0_mode, op0);
op0 = new;
}
-
+
op0 = adjust_address (op0, TYPE_MODE (type), 0);
}
return op0;
case PLUS_EXPR:
- /* We come here from MINUS_EXPR when the second operand is a
- constant. */
- plus_expr:
this_optab = ! unsignedp && flag_trapv
&& (GET_MODE_CLASS (mode) == MODE_INT)
? addv_optab : add_optab;
@@ -7522,8 +7959,10 @@ expand_expr (exp, target, tmode, modifier)
If this is an EXPAND_SUM call, always return the sum. */
if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER
- || (mode == ptr_mode && (unsignedp || ! flag_trapv)))
+ || (mode == ptr_mode && (unsignedp || ! flag_trapv)))
{
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& TREE_CONSTANT (TREE_OPERAND (exp, 1)))
@@ -7602,6 +8041,8 @@ expand_expr (exp, target, tmode, modifier)
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier);
op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier);
+ /* We come here from MINUS_EXPR when the second operand is a
+ constant. */
both_summands:
/* Make sure any term that's a sum with a constant comes last. */
if (GET_CODE (op0) == PLUS
@@ -7671,27 +8112,33 @@ expand_expr (exp, target, tmode, modifier)
else
return gen_rtx_MINUS (mode, op0, op1);
}
- /* Convert A - const to A + (-const). */
- if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
- {
- tree negated = fold (build1 (NEGATE_EXPR, type,
- TREE_OPERAND (exp, 1)));
- if (TREE_UNSIGNED (type) || TREE_OVERFLOW (negated))
- /* If we can't negate the constant in TYPE, leave it alone and
- expand_binop will negate it for us. We used to try to do it
- here in the signed version of TYPE, but that doesn't work
- on POINTER_TYPEs. */;
- else
- {
- exp = build (PLUS_EXPR, type, TREE_OPERAND (exp, 0), negated);
- goto plus_expr;
- }
- }
this_optab = ! unsignedp && flag_trapv
&& (GET_MODE_CLASS(mode) == MODE_INT)
? subv_optab : sub_optab;
- goto binop;
+
+ /* No sense saving up arithmetic to be done
+ if it's all in the wrong mode to form part of an address.
+ And force_operand won't know whether to sign-extend or
+ zero-extend. */
+ if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
+ || mode != ptr_mode)
+ goto binop;
+
+ if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
+ subtarget = 0;
+
+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier);
+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier);
+
+ /* Convert A - const to A + (-const). */
+ if (GET_CODE (op1) == CONST_INT)
+ {
+ op1 = negate_rtx (mode, op1);
+ goto both_summands;
+ }
+
+ goto binop2;
case MULT_EXPR:
/* If first operand is constant, swap them.
@@ -7710,6 +8157,8 @@ expand_expr (exp, target, tmode, modifier)
if (modifier == EXPAND_SUM && mode == ptr_mode
&& host_integerp (TREE_OPERAND (exp, 1), 0))
{
+ tree exp1 = TREE_OPERAND (exp, 1);
+
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
EXPAND_SUM);
@@ -7728,14 +8177,17 @@ expand_expr (exp, target, tmode, modifier)
if (GET_CODE (op0) != REG)
op0 = copy_to_mode_reg (mode, op0);
- return
- gen_rtx_MULT (mode, op0,
- GEN_INT (tree_low_cst (TREE_OPERAND (exp, 1), 0)));
+ return gen_rtx_MULT (mode, op0,
+ gen_int_mode (tree_low_cst (exp1, 0),
+ TYPE_MODE (TREE_TYPE (exp1))));
}
if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
subtarget = 0;
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
+
/* Check for multiplying things that have been extended
from a narrower type. If this machine supports multiplying
in that narrower type with a result in the desired type,
@@ -7819,6 +8271,8 @@ expand_expr (exp, target, tmode, modifier)
case EXACT_DIV_EXPR:
if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
subtarget = 0;
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
/* Possible optimization: compute the dividend with EXPAND_SUM
then if the divisor is constant can optimize the case
where some terms of the dividend have coeffs divisible by it. */
@@ -7847,6 +8301,8 @@ expand_expr (exp, target, tmode, modifier)
case ROUND_MOD_EXPR:
if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
subtarget = 0;
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
return expand_divmod (1, code, mode, op0, op1, target, unsignedp);
@@ -7858,14 +8314,14 @@ expand_expr (exp, target, tmode, modifier)
case FIX_TRUNC_EXPR:
op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
- if (target == 0)
+ if (target == 0 || modifier == EXPAND_STACK_PARM)
target = gen_reg_rtx (mode);
expand_fix (target, op0, unsignedp);
return target;
case FLOAT_EXPR:
op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
- if (target == 0)
+ if (target == 0 || modifier == EXPAND_STACK_PARM)
target = gen_reg_rtx (mode);
/* expand_float can't figure out what to do if FROM has VOIDmode.
So give it the correct mode. With -O, cse will optimize this. */
@@ -7878,16 +8334,20 @@ expand_expr (exp, target, tmode, modifier)
case NEGATE_EXPR:
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
temp = expand_unop (mode,
- ! unsignedp && flag_trapv
- && (GET_MODE_CLASS(mode) == MODE_INT)
- ? negv_optab : neg_optab, op0, target, 0);
+ ! unsignedp && flag_trapv
+ && (GET_MODE_CLASS(mode) == MODE_INT)
+ ? negv_optab : neg_optab, op0, target, 0);
if (temp == 0)
abort ();
return temp;
case ABS_EXPR:
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
/* Handle complex values specially. */
if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
@@ -7905,7 +8365,9 @@ expand_expr (exp, target, tmode, modifier)
case MAX_EXPR:
case MIN_EXPR:
target = original_target;
- if (target == 0 || ! safe_from_p (target, TREE_OPERAND (exp, 1), 1)
+ if (target == 0
+ || modifier == EXPAND_STACK_PARM
+ || ! safe_from_p (target, TREE_OPERAND (exp, 1), 1)
|| (GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
|| GET_MODE (target) != mode
|| (GET_CODE (target) == REG
@@ -7962,6 +8424,8 @@ expand_expr (exp, target, tmode, modifier)
case BIT_NOT_EXPR:
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
if (temp == 0)
abort ();
@@ -7969,6 +8433,8 @@ expand_expr (exp, target, tmode, modifier)
case FFS_EXPR:
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
temp = expand_unop (mode, ffs_optab, op0, target, 1);
if (temp == 0)
abort ();
@@ -8008,6 +8474,8 @@ expand_expr (exp, target, tmode, modifier)
case RROTATE_EXPR:
if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
subtarget = 0;
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target,
unsignedp);
@@ -8027,7 +8495,9 @@ expand_expr (exp, target, tmode, modifier)
case UNGT_EXPR:
case UNGE_EXPR:
case UNEQ_EXPR:
- temp = do_store_flag (exp, target, tmode != VOIDmode ? tmode : mode, 0);
+ temp = do_store_flag (exp,
+ modifier != EXPAND_STACK_PARM ? target : NULL_RTX,
+ tmode != VOIDmode ? tmode : mode, 0);
if (temp != 0)
return temp;
@@ -8057,7 +8527,7 @@ expand_expr (exp, target, tmode, modifier)
enum machine_mode mode1 = GET_MODE (temp);
if (mode1 == VOIDmode)
mode1 = tmode != VOIDmode ? tmode : mode;
-
+
temp = copy_to_mode_reg (mode1, temp);
}
@@ -8076,7 +8546,9 @@ expand_expr (exp, target, tmode, modifier)
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
if (! ignore
- && (target == 0 || ! safe_from_p (target, exp, 1)
+ && (target == 0
+ || modifier == EXPAND_STACK_PARM
+ || ! safe_from_p (target, exp, 1)
/* Make sure we don't have a hard reg (such as function's return
value) live across basic blocks, if not optimizing. */
|| (!optimize && GET_CODE (target) == REG
@@ -8096,6 +8568,8 @@ expand_expr (exp, target, tmode, modifier)
return ignore ? const0_rtx : target;
case TRUTH_NOT_EXPR:
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
/* The parser is careful to generate TRUTH_NOT_EXPR
only with operands that are always zero or one. */
@@ -8110,7 +8584,7 @@ expand_expr (exp, target, tmode, modifier)
emit_queue ();
return expand_expr (TREE_OPERAND (exp, 1),
(ignore ? const0_rtx : target),
- VOIDmode, 0);
+ VOIDmode, modifier);
case COND_EXPR:
/* If we would have a "singleton" (see below) were it not for a
@@ -8163,6 +8637,8 @@ expand_expr (exp, target, tmode, modifier)
return const0_rtx;
}
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, modifier);
if (GET_MODE (op0) == mode)
return op0;
@@ -8203,6 +8679,8 @@ expand_expr (exp, target, tmode, modifier)
if (ignore)
temp = 0;
+ else if (modifier == EXPAND_STACK_PARM)
+ temp = assign_temp (type, 0, 0, 1);
else if (original_target
&& (safe_from_p (original_target, TREE_OPERAND (exp, 0), 1)
|| (singleton && GET_CODE (original_target) == REG
@@ -8236,29 +8714,24 @@ expand_expr (exp, target, tmode, modifier)
&& TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
{
rtx result;
+ tree cond;
optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR
- ? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
- ? addv_optab : add_optab)
- : TREE_CODE (binary_op) == MINUS_EXPR
- ? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
- ? subv_optab : sub_optab)
- : TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab
- : xor_optab);
-
- /* If we had X ? A : A + 1, do this as A + (X == 0).
-
- We have to invert the truth value here and then put it
- back later if do_store_flag fails. We cannot simply copy
- TREE_OPERAND (exp, 0) to another variable and modify that
- because invert_truthvalue can modify the tree pointed to
- by its argument. */
+ ? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
+ ? addv_optab : add_optab)
+ : TREE_CODE (binary_op) == MINUS_EXPR
+ ? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
+ ? subv_optab : sub_optab)
+ : TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab
+ : xor_optab);
+
+ /* If we had X ? A : A + 1, do this as A + (X == 0). */
if (singleton == TREE_OPERAND (exp, 1))
- TREE_OPERAND (exp, 0)
- = invert_truthvalue (TREE_OPERAND (exp, 0));
+ cond = invert_truthvalue (TREE_OPERAND (exp, 0));
+ else
+ cond = TREE_OPERAND (exp, 0);
- result = do_store_flag (TREE_OPERAND (exp, 0),
- (safe_from_p (temp, singleton, 1)
- ? temp : NULL_RTX),
+ result = do_store_flag (cond, (safe_from_p (temp, singleton, 1)
+ ? temp : NULL_RTX),
mode, BRANCH_COST <= 1);
if (result != 0 && ! integer_onep (TREE_OPERAND (binary_op, 1)))
@@ -8276,9 +8749,6 @@ expand_expr (exp, target, tmode, modifier)
return expand_binop (mode, boptab, op1, result, temp,
unsignedp, OPTAB_LIB_WIDEN);
}
- else if (singleton == TREE_OPERAND (exp, 1))
- TREE_OPERAND (exp, 0)
- = invert_truthvalue (TREE_OPERAND (exp, 0));
}
do_pending_stack_adjust ();
@@ -8298,7 +8768,8 @@ expand_expr (exp, target, tmode, modifier)
|| (GET_CODE (temp) == REG
&& REGNO (temp) < FIRST_PSEUDO_REGISTER))
temp = gen_reg_rtx (mode);
- store_expr (singleton, temp, 0);
+ store_expr (singleton, temp,
+ modifier == EXPAND_STACK_PARM ? 2 : 0);
}
else
expand_expr (singleton,
@@ -8317,11 +8788,11 @@ expand_expr (exp, target, tmode, modifier)
store_expr (build (TREE_CODE (binary_op), type,
make_tree (type, temp),
TREE_OPERAND (binary_op, 1)),
- temp, 0);
+ temp, modifier == EXPAND_STACK_PARM ? 2 : 0);
else
store_expr (build1 (TREE_CODE (unary_op), type,
make_tree (type, temp)),
- temp, 0);
+ temp, modifier == EXPAND_STACK_PARM ? 2 : 0);
op1 = op0;
}
/* Check for A op 0 ? A : FOO and A op 0 ? FOO : A where OP is any
@@ -8340,11 +8811,13 @@ expand_expr (exp, target, tmode, modifier)
if (GET_CODE (temp) == REG
&& REGNO (temp) < FIRST_PSEUDO_REGISTER)
temp = gen_reg_rtx (mode);
- store_expr (TREE_OPERAND (exp, 1), temp, 0);
+ store_expr (TREE_OPERAND (exp, 1), temp,
+ modifier == EXPAND_STACK_PARM ? 2 : 0);
jumpif (TREE_OPERAND (exp, 0), op0);
start_cleanup_deferral ();
- store_expr (TREE_OPERAND (exp, 2), temp, 0);
+ store_expr (TREE_OPERAND (exp, 2), temp,
+ modifier == EXPAND_STACK_PARM ? 2 : 0);
op1 = op0;
}
else if (temp
@@ -8359,11 +8832,13 @@ expand_expr (exp, target, tmode, modifier)
if (GET_CODE (temp) == REG
&& REGNO (temp) < FIRST_PSEUDO_REGISTER)
temp = gen_reg_rtx (mode);
- store_expr (TREE_OPERAND (exp, 2), temp, 0);
+ store_expr (TREE_OPERAND (exp, 2), temp,
+ modifier == EXPAND_STACK_PARM ? 2 : 0);
jumpifnot (TREE_OPERAND (exp, 0), op0);
start_cleanup_deferral ();
- store_expr (TREE_OPERAND (exp, 1), temp, 0);
+ store_expr (TREE_OPERAND (exp, 1), temp,
+ modifier == EXPAND_STACK_PARM ? 2 : 0);
op1 = op0;
}
else
@@ -8377,7 +8852,8 @@ expand_expr (exp, target, tmode, modifier)
example A ? throw : E */
if (temp != 0
&& TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node)
- store_expr (TREE_OPERAND (exp, 1), temp, 0);
+ store_expr (TREE_OPERAND (exp, 1), temp,
+ modifier == EXPAND_STACK_PARM ? 2 : 0);
else
expand_expr (TREE_OPERAND (exp, 1),
ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
@@ -8389,7 +8865,8 @@ expand_expr (exp, target, tmode, modifier)
start_cleanup_deferral ();
if (temp != 0
&& TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node)
- store_expr (TREE_OPERAND (exp, 2), temp, 0);
+ store_expr (TREE_OPERAND (exp, 2), temp,
+ modifier == EXPAND_STACK_PARM ? 2 : 0);
else
expand_expr (TREE_OPERAND (exp, 2),
ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
@@ -8447,7 +8924,7 @@ expand_expr (exp, target, tmode, modifier)
preserve_temp_slots (target);
SET_DECL_RTL (slot, target);
if (TREE_ADDRESSABLE (slot))
- put_var_into_stack (slot);
+ put_var_into_stack (slot, /*rescan=*/false);
/* Since SLOT is not known to the called function
to belong to its stack frame, we must build an explicit
@@ -8457,7 +8934,8 @@ expand_expr (exp, target, tmode, modifier)
built here. */
if (TREE_OPERAND (exp, 2) == 0)
- TREE_OPERAND (exp, 2) = maybe_build_cleanup (slot);
+ TREE_OPERAND (exp, 2)
+ = (*lang_hooks.maybe_build_cleanup) (slot);
cleanups = TREE_OPERAND (exp, 2);
}
}
@@ -8485,7 +8963,7 @@ expand_expr (exp, target, tmode, modifier)
/* If we must have an addressable slot, then make sure that
the RTL that we just stored in slot is OK. */
if (TREE_ADDRESSABLE (slot))
- put_var_into_stack (slot);
+ put_var_into_stack (slot, /*rescan=*/true);
}
}
@@ -8493,9 +8971,9 @@ expand_expr (exp, target, tmode, modifier)
/* Mark it as expanded. */
TREE_OPERAND (exp, 1) = NULL_TREE;
- store_expr (exp1, target, 0);
+ store_expr (exp1, target, modifier == EXPAND_STACK_PARM ? 2 : 0);
- expand_decl_cleanup (NULL_TREE, cleanups);
+ expand_decl_cleanup_eh (NULL_TREE, cleanups, CLEANUP_EH_ONLY (exp));
return target;
}
@@ -8557,7 +9035,7 @@ expand_expr (exp, target, tmode, modifier)
}
temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
-
+
return temp;
}
@@ -8578,6 +9056,8 @@ expand_expr (exp, target, tmode, modifier)
return expand_increment (exp, ! ignore, ignore);
case ADDR_EXPR:
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
/* Are we taking the address of a nested function? */
if (TREE_CODE (TREE_OPERAND (exp, 0)) == FUNCTION_DECL
&& decl_function_context (TREE_OPERAND (exp, 0)) != 0
@@ -8633,7 +9113,8 @@ expand_expr (exp, target, tmode, modifier)
forcing the SAVE_EXPR into memory. */
if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR)
{
- put_var_into_stack (TREE_OPERAND (exp, 0));
+ put_var_into_stack (TREE_OPERAND (exp, 0),
+ /*rescan=*/true);
op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0));
}
else
@@ -8646,11 +9127,11 @@ expand_expr (exp, target, tmode, modifier)
/* Handle calls that pass values in multiple
non-contiguous locations. The Irix 6 ABI has examples
of this. */
- emit_group_store (memloc, op0,
+ emit_group_store (memloc, op0,
int_size_in_bytes (inner_type));
else
emit_move_insn (memloc, op0);
-
+
op0 = memloc;
}
}
@@ -8686,19 +9167,30 @@ expand_expr (exp, target, tmode, modifier)
&& MEM_ALIGN (op0) < BIGGEST_ALIGNMENT)
{
tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
- rtx new
- = assign_stack_temp_for_type
- (TYPE_MODE (inner_type),
- MEM_SIZE (op0) ? INTVAL (MEM_SIZE (op0))
- : int_size_in_bytes (inner_type),
- 1, build_qualified_type (inner_type,
- (TYPE_QUALS (inner_type)
- | TYPE_QUAL_CONST)));
+ rtx new;
if (TYPE_ALIGN_OK (inner_type))
abort ();
- emit_block_move (new, op0, expr_size (TREE_OPERAND (exp, 0)));
+ if (TREE_ADDRESSABLE (inner_type))
+ {
+ /* We can't make a bitwise copy of this object, so fail. */
+ error ("cannot take the address of an unaligned member");
+ return const0_rtx;
+ }
+
+ new = assign_stack_temp_for_type
+ (TYPE_MODE (inner_type),
+ MEM_SIZE (op0) ? INTVAL (MEM_SIZE (op0))
+ : int_size_in_bytes (inner_type),
+ 1, build_qualified_type (inner_type,
+ (TYPE_QUALS (inner_type)
+ | TYPE_QUAL_CONST)));
+
+ emit_block_move (new, op0, expr_size (TREE_OPERAND (exp, 0)),
+ (modifier == EXPAND_STACK_PARM
+ ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
+
op0 = new;
}
@@ -8756,7 +9248,7 @@ expand_expr (exp, target, tmode, modifier)
if (GET_CODE (target) != CONCAT)
emit_no_conflict_block (insns, target, op0, op1, NULL_RTX);
else
- emit_insns (insns);
+ emit_insn (insns);
return target;
}
@@ -8788,9 +9280,9 @@ expand_expr (exp, target, tmode, modifier)
imag_t = gen_imagpart (partmode, target);
temp = expand_unop (partmode,
- ! unsignedp && flag_trapv
- && (GET_MODE_CLASS(partmode) == MODE_INT)
- ? negv_optab : neg_optab,
+ ! unsignedp && flag_trapv
+ && (GET_MODE_CLASS(partmode) == MODE_INT)
+ ? negv_optab : neg_optab,
gen_imagpart (partmode, op0), imag_t, 0);
if (temp != imag_t)
emit_move_insn (imag_t, temp);
@@ -8805,7 +9297,7 @@ expand_expr (exp, target, tmode, modifier)
if (GET_CODE (target) != CONCAT)
emit_no_conflict_block (insns, target, op0, NULL_RTX, NULL_RTX);
else
- emit_insns (insns);
+ emit_insn (insns);
return target;
}
@@ -8827,29 +9319,55 @@ expand_expr (exp, target, tmode, modifier)
{
tree try_block = TREE_OPERAND (exp, 0);
tree finally_block = TREE_OPERAND (exp, 1);
- rtx finally_label = gen_label_rtx ();
- rtx done_label = gen_label_rtx ();
- rtx return_link = gen_reg_rtx (Pmode);
- tree cleanup = build (GOTO_SUBROUTINE_EXPR, void_type_node,
- (tree) finally_label, (tree) return_link);
- TREE_SIDE_EFFECTS (cleanup) = 1;
- /* Start a new binding layer that will keep track of all cleanup
- actions to be performed. */
- expand_start_bindings (2);
+ if (!optimize || unsafe_for_reeval (finally_block) > 1)
+ {
+ /* In this case, wrapping FINALLY_BLOCK in an UNSAVE_EXPR
+ is not sufficient, so we cannot expand the block twice.
+ So we play games with GOTO_SUBROUTINE_EXPR to let us
+ expand the thing only once. */
+ /* When not optimizing, we go ahead with this form since
+ (1) user breakpoints operate more predictably without
+ code duplication, and
+ (2) we're not running any of the global optimizers
+ that would explode in time/space with the highly
+ connected CFG created by the indirect branching. */
+
+ rtx finally_label = gen_label_rtx ();
+ rtx done_label = gen_label_rtx ();
+ rtx return_link = gen_reg_rtx (Pmode);
+ tree cleanup = build (GOTO_SUBROUTINE_EXPR, void_type_node,
+ (tree) finally_label, (tree) return_link);
+ TREE_SIDE_EFFECTS (cleanup) = 1;
+
+ /* Start a new binding layer that will keep track of all cleanup
+ actions to be performed. */
+ expand_start_bindings (2);
+ target_temp_slot_level = temp_slot_level;
+
+ expand_decl_cleanup (NULL_TREE, cleanup);
+ op0 = expand_expr (try_block, target, tmode, modifier);
+
+ preserve_temp_slots (op0);
+ expand_end_bindings (NULL_TREE, 0, 0);
+ emit_jump (done_label);
+ emit_label (finally_label);
+ expand_expr (finally_block, const0_rtx, VOIDmode, 0);
+ emit_indirect_jump (return_link);
+ emit_label (done_label);
+ }
+ else
+ {
+ expand_start_bindings (2);
+ target_temp_slot_level = temp_slot_level;
- target_temp_slot_level = temp_slot_level;
+ expand_decl_cleanup (NULL_TREE, finally_block);
+ op0 = expand_expr (try_block, target, tmode, modifier);
- expand_decl_cleanup (NULL_TREE, cleanup);
- op0 = expand_expr (try_block, target, tmode, modifier);
+ preserve_temp_slots (op0);
+ expand_end_bindings (NULL_TREE, 0, 0);
+ }
- preserve_temp_slots (op0);
- expand_end_bindings (NULL_TREE, 0, 0);
- emit_jump (done_label);
- emit_label (finally_label);
- expand_expr (finally_block, const0_rtx, VOIDmode, 0);
- emit_indirect_jump (return_link);
- emit_label (done_label);
return op0;
}
@@ -8877,7 +9395,7 @@ expand_expr (exp, target, tmode, modifier)
abort ();
default:
- return (*lang_expand_expr) (exp, original_target, tmode, modifier);
+ return (*lang_hooks.expand_expr) (exp, original_target, tmode, modifier);
}
/* Here to do an ordinary binary operator, generating an instruction
@@ -8888,6 +9406,8 @@ expand_expr (exp, target, tmode, modifier)
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
binop2:
+ if (modifier == EXPAND_STACK_PARM)
+ target = 0;
temp = expand_binop (mode, this_optab, op0, op1, target,
unsignedp, OPTAB_LIB_WIDEN);
if (temp == 0)
@@ -8945,8 +9465,8 @@ is_aligning_offset (offset, exp)
== TREE_TYPE (exp)))));
}
-/* Return the tree node if a ARG corresponds to a string constant or zero
- if it doesn't. If we return non-zero, set *PTR_OFFSET to the offset
+/* Return the tree node if an ARG corresponds to a string constant or zero
+ if it doesn't. If we return nonzero, set *PTR_OFFSET to the offset
in bytes within the string that ARG is accessing. The type of the
offset will be `sizetype'. */
@@ -9314,6 +9834,12 @@ do_jump (exp, if_false_label, if_true_label)
break;
#endif
+ case UNSAVE_EXPR:
+ do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
+ TREE_OPERAND (exp, 0)
+ = (*lang_hooks.unsave_expr_now) (TREE_OPERAND (exp, 0));
+ break;
+
case NOP_EXPR:
if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF
|| TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF
@@ -9332,7 +9858,7 @@ do_jump (exp, if_false_label, if_true_label)
case NEGATE_EXPR:
case LROTATE_EXPR:
case RROTATE_EXPR:
- /* These cannot change zero->non-zero or vice versa. */
+ /* These cannot change zero->nonzero or vice versa. */
do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
break;
@@ -9358,7 +9884,7 @@ do_jump (exp, if_false_label, if_true_label)
#endif
case MINUS_EXPR:
- /* Non-zero iff operands of minus differ. */
+ /* Nonzero iff operands of minus differ. */
do_compare_and_jump (build (NE_EXPR, TREE_TYPE (exp),
TREE_OPERAND (exp, 0),
TREE_OPERAND (exp, 1)),
@@ -9378,7 +9904,7 @@ do_jump (exp, if_false_label, if_true_label)
&& TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
&& (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0
&& (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
- && (type = type_for_mode (mode, 1)) != 0
+ && (type = (*lang_hooks.types.type_for_mode) (mode, 1)) != 0
&& TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
&& (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
!= CODE_FOR_nothing))
@@ -9438,7 +9964,7 @@ do_jump (exp, if_false_label, if_true_label)
get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
&unsignedp, &volatilep);
- type = type_for_size (bitsize, unsignedp);
+ type = (*lang_hooks.types.type_for_size) (bitsize, unsignedp);
if (! SLOW_BYTE_ACCESS
&& type != 0 && bitsize >= 0
&& TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
@@ -9621,7 +10147,7 @@ do_jump (exp, if_false_label, if_true_label)
|| rcmp == UNORDERED))
do_rev = 1;
- if (! do_rev)
+ if (! do_rev)
do_compare_and_jump (exp, cmp, cmp, if_false_label, if_true_label);
else
do_compare_and_jump (exp, rcmp, rcmp, if_true_label, if_false_label);
@@ -9654,7 +10180,7 @@ do_jump (exp, if_false_label, if_true_label)
goto unordered_bcc;
unordered_bcc:
- mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+ mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
if (can_compare_p (rcode1, mode, ccp_jump))
do_compare_and_jump (exp, rcode1, rcode1, if_false_label,
if_true_label);
@@ -9723,7 +10249,7 @@ do_jump (exp, if_false_label, if_true_label)
/* Do any postincrements in the expression that was tested. */
emit_queue ();
- if (GET_CODE (temp) == CONST_INT
+ if (GET_CODE (temp) == CONST_INT
|| (GET_CODE (temp) == CONST_DOUBLE && GET_MODE (temp) == VOIDmode)
|| GET_CODE (temp) == LABEL_REF)
{
@@ -9926,6 +10452,7 @@ compare_from_rtx (op0, op1, code, unsignedp, mode, size)
enum machine_mode mode;
rtx size;
{
+ enum rtx_code ucode;
rtx tem;
/* If one operand is constant, make it the second one. Only do this
@@ -9947,8 +10474,8 @@ compare_from_rtx (op0, op1, code, unsignedp, mode, size)
do_pending_stack_adjust ();
- if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT
- && (tem = simplify_relational_operation (code, mode, op0, op1)) != 0)
+ ucode = unsignedp ? unsigned_condition (code) : code;
+ if ((tem = simplify_relational_operation (ucode, mode, op0, op1)) != 0)
return tem;
#if 0
@@ -9975,7 +10502,11 @@ compare_from_rtx (op0, op1, code, unsignedp, mode, size)
emit_cmp_insn (op0, op1, code, size, mode, unsignedp);
+#if HAVE_cc0
return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
+#else
+ return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
+#endif
}
/* Like do_compare_and_jump but expects the values to compare as two rtx's.
@@ -9994,6 +10525,7 @@ do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, size,
rtx size;
rtx if_false_label, if_true_label;
{
+ enum rtx_code ucode;
rtx tem;
int dummy_true_label = 0;
@@ -10025,8 +10557,8 @@ do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, size,
do_pending_stack_adjust ();
- if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT
- && (tem = simplify_relational_operation (code, mode, op0, op1)) != 0)
+ ucode = unsignedp ? unsigned_condition (code) : code;
+ if ((tem = simplify_relational_operation (ucode, mode, op0, op1)) != 0)
{
if (tem == const_true_rtx)
{
@@ -10167,7 +10699,7 @@ do_compare_and_jump (exp, signed_code, unsigned_code, if_false_label,
If TARGET is nonzero, store the result there if convenient.
- If ONLY_CHEAP is non-zero, only do this if it is likely to be very
+ If ONLY_CHEAP is nonzero, only do this if it is likely to be very
cheap.
Return zero if there is no suitable set-flag instruction
@@ -10519,8 +11051,8 @@ try_casesi (index_type, index_expr, minval, range,
{
if (TYPE_MODE (index_type) != index_mode)
{
- index_expr = convert (type_for_size (index_bits, 0),
- index_expr);
+ index_expr = convert ((*lang_hooks.types.type_for_size)
+ (index_bits, 0), index_expr);
index_type = TREE_TYPE (index_expr);
}
@@ -10582,6 +11114,9 @@ do_tablejump (index, mode, range, table_label, default_label)
{
rtx temp, vector;
+ if (INTVAL (range) > cfun->max_jumptable_ents)
+ cfun->max_jumptable_ents = INTVAL (range);
+
/* Do an unsigned comparison (in the proper mode) between the index
expression and the value which represents the length of the range.
Since we just finished subtracting the lower bound of the range
@@ -10627,6 +11162,7 @@ do_tablejump (index, mode, range, table_label, default_label)
temp = gen_reg_rtx (CASE_VECTOR_MODE);
vector = gen_rtx_MEM (CASE_VECTOR_MODE, index);
RTX_UNCHANGING_P (vector) = 1;
+ MEM_NOTRAP_P (vector) = 1;
convert_move (temp, vector, 0);
emit_jump_insn (gen_tablejump (temp, table_label));
@@ -10665,3 +11201,35 @@ try_tablejump (index_type, index_expr, minval, range,
table_label, default_label);
return 1;
}
+
+/* Nonzero if the mode is a valid vector mode for this architecture.
+ This returns nonzero even if there is no hardware support for the
+ vector mode, but we can emulate with narrower modes. */
+
+int
+vector_mode_valid_p (mode)
+ enum machine_mode mode;
+{
+ enum mode_class class = GET_MODE_CLASS (mode);
+ enum machine_mode innermode;
+
+ /* Doh! What's going on? */
+ if (class != MODE_VECTOR_INT
+ && class != MODE_VECTOR_FLOAT)
+ return 0;
+
+ /* Hardware support. Woo hoo! */
+ if (VECTOR_MODE_SUPPORTED_P (mode))
+ return 1;
+
+ innermode = GET_MODE_INNER (mode);
+
+ /* We should probably return 1 if requesting V4DI and we have no DI,
+ but we have V2DI, but this is probably very unlikely. */
+
+ /* If we have support for the inner mode, we can safely emulate it.
+ We may not have V2DI, but me can emulate with a pair of DIs. */
+ return mov_optab->handlers[innermode].insn_code != CODE_FOR_nothing;
+}
+
+#include "gt-expr.h"
diff --git a/contrib/gcc/expr.h b/contrib/gcc/expr.h
index fb7c61d..c38cd99 100644
--- a/contrib/gcc/expr.h
+++ b/contrib/gcc/expr.h
@@ -1,6 +1,6 @@
/* Definitions for code generation pass of GNU compiler.
Copyright (C) 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -44,13 +44,19 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define QUEUED_NEXT(P) XEXP (P, 4)
/* This is the 4th arg to `expand_expr'.
+ EXPAND_STACK_PARM means we are possibly expanding a call param onto
+ the stack. Choosing a value of 2 isn't special; It just allows
+ some code optimization in store_expr.
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.
- EXPAND_WRITE means we are only going to write to the resulting rtx. */
-enum expand_modifier {EXPAND_NORMAL, EXPAND_SUM, EXPAND_CONST_ADDRESS,
- EXPAND_INITIALIZER, EXPAND_WRITE};
+ EXPAND_WRITE means we are only going to write to the resulting rtx.
+ EXPAND_MEMORY means we are interested in a memory result, even if
+ the memory is constant and we could have propagated a constant value. */
+enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM = 2, EXPAND_SUM,
+ EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE,
+ EXPAND_MEMORY};
/* Prevent the compiler from deferring stack pops. See
inhibit_defer_pop for more information. */
@@ -132,7 +138,7 @@ enum direction {none, upward, downward}; /* Value has this type. */
/* Supply a default definition for FUNCTION_ARG_BOUNDARY. Normally, we let
FUNCTION_ARG_PADDING, which also pads the length, handle any needed
alignment. */
-
+
#ifndef FUNCTION_ARG_BOUNDARY
#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) PARM_BOUNDARY
#endif
@@ -289,7 +295,7 @@ extern rtx gen_move_insn PARAMS ((rtx, rtx));
extern int have_add2_insn PARAMS ((rtx, rtx));
extern int have_sub2_insn PARAMS ((rtx, rtx));
-/* Emit a pair of rtl insns to compare two rtx's and to jump
+/* Emit a pair of rtl insns to compare two rtx's and to jump
to a label if the comparison is true. */
extern void emit_cmp_and_jump_insns PARAMS ((rtx, rtx, enum rtx_code, rtx,
enum machine_mode, int, rtx));
@@ -303,7 +309,7 @@ rtx emit_conditional_move PARAMS ((rtx, enum rtx_code, rtx, rtx,
enum machine_mode, rtx, rtx,
enum machine_mode, int));
-/* Return non-zero if the conditional move is supported. */
+/* Return nonzero if the conditional move is supported. */
int can_conditionally_move_p PARAMS ((enum machine_mode mode));
#endif
@@ -341,7 +347,7 @@ extern rtx gen_cond_trap PARAMS ((enum rtx_code, rtx, rtx, rtx));
/* Functions from builtins.c: */
extern rtx expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
-extern void std_expand_builtin_va_start PARAMS ((int, tree, rtx));
+extern void std_expand_builtin_va_start PARAMS ((tree, rtx));
extern rtx std_expand_builtin_va_arg PARAMS ((tree, tree));
extern rtx expand_builtin_va_arg PARAMS ((tree, tree));
extern void default_init_builtins PARAMS ((void));
@@ -369,10 +375,6 @@ extern void init_expr_once PARAMS ((void));
/* This is run at the start of compiling a function. */
extern void init_expr PARAMS ((void));
-/* This function is run once to initialize stor-layout.c. */
-
-extern void init_stor_layout_once PARAMS ((void));
-
/* This is run at the end of compiling a function. */
extern void finish_expr_for_function PARAMS ((void));
@@ -398,7 +400,15 @@ extern rtx convert_modes PARAMS ((enum machine_mode, enum machine_mode,
rtx, int));
/* Emit code to move a block Y to a block X. */
-extern rtx emit_block_move PARAMS ((rtx, rtx, rtx));
+
+enum block_op_methods
+{
+ BLOCK_OP_NORMAL,
+ BLOCK_OP_NO_LIBCALL,
+ BLOCK_OP_CALL_PARM
+};
+
+extern rtx emit_block_move PARAMS ((rtx, rtx, rtx, enum block_op_methods));
/* Copy all or part of a value X into registers starting at REGNO.
The number of registers to be filled is NREGS. */
@@ -408,10 +418,17 @@ extern void move_block_to_reg PARAMS ((int, rtx, int, enum machine_mode));
The number of registers to be filled is NREGS. */
extern void move_block_from_reg PARAMS ((int, rtx, int, int));
+/* Generate a non-consecutive group of registers represented by a PARALLEL. */
+extern rtx gen_group_rtx PARAMS ((rtx));
+
/* Load a BLKmode value into non-consecutive registers represented by a
PARALLEL. */
extern void emit_group_load PARAMS ((rtx, rtx, int));
+/* Move a non-consecutive group of registers represented by a PARALLEL into
+ a non-consecutive group of registers represented by a PARALLEL. */
+extern void emit_group_move PARAMS ((rtx, rtx));
+
/* Store a BLKmode value from non-consecutive registers represented by a
PARALLEL. */
extern void emit_group_store PARAMS ((rtx, rtx, int));
@@ -435,7 +452,7 @@ extern void use_group_regs PARAMS ((rtx *, rtx));
If OBJECT has BLKmode, SIZE is its length in bytes. */
extern rtx clear_storage PARAMS ((rtx, rtx));
-/* Return non-zero if it is desirable to store LEN bytes generated by
+/* Return nonzero if it is desirable to store LEN bytes generated by
CONSTFUN with several move instructions by store_by_pieces
function. CONSTFUNDATA is a pointer which will be passed as argument
in every CONSTFUN call.
@@ -740,7 +757,7 @@ extern void emit_stack_restore PARAMS ((enum save_level, rtx, rtx));
says how many bytes. */
extern rtx allocate_dynamic_stack_space PARAMS ((rtx, rtx, int));
-/* Probe a range of stack addresses from FIRST to FIRST+SIZE, inclusive.
+/* 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
@@ -771,6 +788,7 @@ extern rtx extract_bit_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
enum machine_mode, enum machine_mode,
HOST_WIDE_INT));
extern rtx expand_mult PARAMS ((enum machine_mode, rtx, rtx, rtx, int));
+extern bool const_mult_add_overflow_p PARAMS ((rtx, rtx, rtx, enum machine_mode, int));
extern rtx expand_mult_add PARAMS ((rtx, rtx, rtx, rtx,enum machine_mode, int));
extern rtx expand_mult_highpart_adjust PARAMS ((enum machine_mode, rtx, rtx, rtx, rtx, int));
@@ -802,3 +820,5 @@ extern void do_jump_by_parts_greater_rtx PARAMS ((enum machine_mode,
extern void mark_seen_cases PARAMS ((tree, unsigned char *,
HOST_WIDE_INT, int));
#endif
+
+extern int vector_mode_valid_p PARAMS ((enum machine_mode));
diff --git a/contrib/gcc/f/ChangeLog b/contrib/gcc/f/ChangeLog
index 567bc7b..57838b0 100644
--- a/contrib/gcc/f/ChangeLog
+++ b/contrib/gcc/f/ChangeLog
@@ -1,48 +1,278 @@
-2003-02-05 Release Manager
+2003-07-09 Toon Moene <toon@moene.indiv.nluug.nl>
- * GCC 3.2.2 Released.
+ PR Fortran/11301
+ * com.c (ffecom_sym_transform_): finish_decl should have
+ the same last argument as start_decl.
-2003-01-28 Christian Cornelssen <ccorn@cs.tu-berlin.de>
+Tue Jul 8 15:18:14 2003 Andreas Schwab <schwab@suse.de>
+
+ * Make-lang.in (f/g77.dvi): Replace PWD with PWD_COMMAND.
+
+2003-07-05 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ PR Fortran/11301
+ * com.c (ffecom_sym_transform_): Only install
+ FFEINFO_whereGLOBAL symbols in the global binding
+ level if not -fno-globals.
+
+2003-06-13 Richard Henderson <rth@redhat.com>
+
+ PR debug/9864
+ * com.c (ffecom_sym_transform_): Install FFEINFO_whereGLOBAL
+ symbols in the global binding level.
+
+2003-05-18 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ PR fortran/10726
+ * intdoc.in: Fix documentation of IDATE.
+ * intdoc.texi: Regenerate.
+ * news.texi: Update due to the above.
+
+2003-05-16 Wolfgang Bangerth <bangerth@dealii.org>
+
+ * g77.texi: Remove most of the preface of the bugs section.
+
+2003-05-15 Wolfgang Bangerth <bangerth@dealii.org>
+
+ * g77.texi: Remove most of the bug reporting instructions and
+ merge them into bugs.html.
+
+2003-05-13 Release Manager
+
+ * GCC 3.3 Released.
+
+2003-05-13 Release Manager
+
+ * GCC 3.3 Released.
+
+2003-05-13 Release Manager
+
+ * GCC 3.3 Released.
+
+2003-04-11 Bud Davis <bdavis9659@comcast.net>
+
+ PR Fortran/9263
+ * gcc/f/data.c (ffedata_advance_): Check initial, final and
+ increment values for INTEGER typeness.
+ * gcc/f/news.texi: Document these fixes.
+
+2003-03-26 Roger Sayle <roger@eyesopen.com>
+
+ PR fortran/9793
+ * target.h (ffetarget_divide_integer1): Perform division by -1
+ using negation to prevent possible overflow trap on the host.
+
+2003-03-25 Marcelo Abreu <mmabreu@inf.ufrgs.br>
+
+ PR fortran/10204
+ * ffe.texi: Reference the GCC web site in the URL.
+
+2003-03-24 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ PR fortran/10197
+ * news.texi: Document PR fortran/10197 fixed.
+
+Sun Mar 23 23:43:45 2003 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/7086
+ * com.c (ffecom_sym_transform_): Adjust calls to
+ put_var_into_stack.
+ (ffe_mark_addressable): Likewise.
+
+2003-03-22 Bud Davis <bdavis9659@comcast.net>
+
+ * com.c (ffecom_constantunion_with_type): New function.
+ * com.h (ffecom_constantunion_with_type): Declare.
+ * stc.c (ffestc_R810): Check for kind type.
+ * ste.c (ffeste_R810): Use ffecom_constantunion_with_type
+ to discern SELECT CASE variables.
+
+2003-03-15 Andreas Jaeger <aj@suse.de>
+
+ * g77spec.c (DEFAULT_SWITCH_TAKES_ARG): Remove.
+ (DEFAULT_WORD_SWITCH_TAKES_ARG): Remove.
+
+2003-02-21 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ * news.texi: Document fixing PR fortran/9038.
+
+2003-02-04 Joseph S. Myers <jsm@polyomino.org.uk>
+
+ * g77.texi, invoke.texi: Update to GFDL 1.2.
+
+2003-01-30 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ * news.texi: Document fixing PR fortran/7681
+ and PR optimization/9258.
+
+2003-01-26 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ * lang-specs.h: Revert change to solve 9038.
+ * news.texi: Document this.
+
+2003-01-26 Christian Cornelssen <ccorn@cs.tu-berlin.de>
* Make-lang.in (f77.install-common, f77.install-info)
(f77.install-man, f77.uninstall): Prepend $(DESTDIR) to
destination paths in all (un)installation commands.
-2002-11-22 Toon Moene <toon@moene.indiv.nluug.nl>
+2003-01-05 Steven Bosscher <s.bosscher@student.tudelft.nl>
+
+ PR Fortran/9038
+ * lang-specs.h: Prevent -f<option> from being passed
+ to cc1.
+ * news.texi: Document this fix.
+
+2003-01-03 Bud Davis <bdavis11@directvinternet.com>
+
+ * stc.c (ffestc_R810): Allow any kind integer in
+ case statements.
+ * ste.c (ffeste_R810): Give error message when
+ case selector exceeds its valid values.
+
+2003-01-01 Andreas Jaeger <aj@suse.de>
+
+ * f/Make-lang.in ($(srcdir)/f/BUGS): Add include path for
+ gcc-common.texi.
+ ($(srcdir)/f/NEWS): Likewise.
+
+2002-12-28 Joseph S. Myers <jsm@polyomino.org.uk>
+
+ * g77.texi: Use @copying.
+
+2002-12-23 Joseph S. Myers <jsm@polyomino.org.uk>
+
+ * root.texi: Include gcc-common.texi.
+ * bugs.texi, news.texi: Don't include root.texi as part of full
+ manual.
+ * g77.texi: Update for use of gcc-common.texi.
+ * Make-lang.in ($(srcdir)/f/g77.info, f/g77.dvi): Depend on
+ $(srcdir)/doc/include/gcc-common.texi.
+
+2002-12-19 Kazu Hirata <kazu@cs.umass.edu>
+
+ * intdoc.in: Fix typos.
+
+2002-12-18 Kazu Hirata <kazu@cs.umass.edu>
+
+ * g77.texi: Fix typos.
+ * intdoc.texi: Likewise.
+ * news.texi: Follow spelling conventions.
+
+Mon Dec 16 13:55:24 2002 Mark Mitchell <mark@codesourcery.com>
+
+ * root.texi (DEVELOPMENT): @clear it.
+
+2002-11-20 Toon Moene <toon@moene.indiv.nluug.nl>
* invoke.texi: Explain the purpose of -fmove-all-movables,
-freduce-all-givs and -frerun-loop-opts better.
-2002-11-19 Release Manager
+2002-11-19 Toon Moene <toon@moene.indiv.nluug.nl>
- * GCC 3.2.1 Released.
+ PR fortran/8587
+ * news.texi: Show PR fortran/8587 fixed.
-2002-11-19 Release Manager
+2002-11-19 Jason Thorpe <thorpej@wasabisystems.com>
- * GCC 3.2.1 Released.
+ * g77spec.c (lang_specific_spec_functions): New.
-2002-11-18 Release Manager
+2002-11-02 Toon Moene <toon@moene.indiv.nluug.nl>
- * GCC 3.2.1 Released.
+ * g77.texi: Correct documentation on generating C++ prototypes
+ of Fortran routines with f2c.
+ * news.texi: Document fixes in GCC-3.3, 3.2 and 3.1.
-2002-10-28 Andris Pavenis <pavenis@latnet.lv>
- Toon Moene <toon@moene.indiv.nluug.nl>
+2002-10-30 Roger Sayle <roger@eyesopen.com>
- PR fortran/8308
- * lang-specs.h: Correct ratfor specs.
- * news.texi: Document this fix.
+ * com.c (ffecom_subscript_check_): Cast the failure branch
+ of the bounds check COND_EXPR to void, to indicate noreturn.
+ (ffe_truthvalue_conversion): Only apply truth value conversion
+ to the non-void branches of a COND_EXPR.
-2002-09-14 Hans-Peter Nilsson <hp@bitrange.com>
+2002-10-26 Andris Pavenis <pavenis@latnet.lv>
- * target.c (ffetarget_memcpy_): Don't test nonexistent
- HOST_BYTES_BIG_ENDIAN, HOST_BITS_BIG_ENDIAN. Check
- HOST_WORDS_BIG_ENDIAN against both WORDS_BIG_ENDIAN and
- BYTES_BIG_ENDIAN.
+ * lang-specs.h: Fix ratfor specs.
+
+2002-10-15 Richard Henderson <rth@redhat.com>
+
+ * target.h (ffetarget_print_real1, ffetarget_print_real2): Use
+ real_to_decimal directly, and with the new arguments.
+
+2002-09-23 Zack Weinberg <zack@codesourcery.com>
+
+ * Make-lang.in (g77spec.o): Don't depend on f/version.h.
+ (f/parse.o): Depend on version.h not f/version.h.
+ (g77version.o, f/version.o): Delete all references.
+
+ * com.c (ffecom_init_0): Fix transposed array indices in bsearch test.
+ * g77spec.c: Don't include f/version.h or refer to ffe_version_string.
+ * parse.c: Use version_string, not ffe_version_string.
+ * version.c, version.h: Delete files.
+
+2002-09-23 Kazu Hirata <kazu@cs.umass.edu>
+
+ * ChangeLog: Follow spelling conventions.
+ * ChangeLog.0: Likewise.
+ * com.c: Likewise.
+ * ffe.texi: Likewise.
+ * g77.texi: Likewise.
+ * intdoc.in: Likewise.
+ * invoke.texi: Likewise.
+ * news.texi: Likewise.
+ * intdoc.texi: Regenerate.
+
+2002-09-16 Geoffrey Keating <geoffk@apple.com>
+
+ * com.c (union lang_tree_node): Add chain_next option.
+
+2002-09-16 Richard Henderson <rth@redhat.com>
+
+ * target.c (ffetarget_real1): Don't pass FFETARGET_ATOF_
+ directly to ffetarget_make_real1.
+ (ffetarget_real2): Similarly.
+ * target.h (ffetarget_cvt_r1_to_rv_, ffetarget_cvt_rv_to_r2_,
+ ffetarget_cvt_r2_to_rv_): Use new real.h interface and simplify.
+
+2002-09-15 Kazu Hirata <kazu@cs.umass.edu>
+
+ * intdoc.texi: Regenerate.
+
+2002-09-15 Kazu Hirata <kazu@cs.umass.edu>
+
+ * ChangeLog: Follow spelling conventions.
+ * intdoc.in: Likewise.
+
+2002-09-09 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ Fix PR web/7596:
+ * ffe.texi (Front End): Fix broken links.
+ * bugs.texi (Known Bugs): Refer to gcc.gnu.org instead of
+ www.gnu.org for onlinedocs.
+ * news.texi (News): Ditto.
2002-09-07 Jan Hubicka <jh@suse.cz>
* com.c (ffe_type_for_mode): Handle long double.
+2002-09-04 Richard Henderson <rth@redhat.com>
+
+ * target.h (ffetarget_print_real1, ffetarget_print_real2): Update
+ call to REAL_VALUE_TO_DECIMAL.
+
+2002-08-31 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ * com.c: Don't set flag_finite_math_only by default.
+ * invoke.texi: Reverse the documentation of option
+ -ffinite-math-only to reflect the new default.
+
+2002-08-30 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * target.c (ffetarget_memcpy_): Don't test nonexistent
+ HOST_BYTES_BIG_ENDIAN, HOST_BITS_BIG_ENDIAN. Check
+ HOST_WORDS_BIG_ENDIAN against both WORDS_BIG_ENDIAN and
+ BYTES_BIG_ENDIAN.
+
2002-08-30 Alan Modra <amodra@bigpond.net.au>
* target.h (FFETARGET_32bit_longs): Don't define for powerpc64 or
@@ -53,45 +283,186 @@
* bugs.texi, news.texi: Update URLs for online news and bugs
lists.
-2002-08-14 Release Manager
+2002-08-22 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * where.h (struct _ffewhere_file_): Mark GTY.
+ (ffewhere_file_kill): Remove prototype.
+ * where.c: Include ggc.h.
+ (struct _ffewhere_ll_, struct _ffewhere_root_ll_): Mark GTY.
+ (ffewhere_root_ll_): Ditto. Change type from struct
+ _ffewhere_root_ll_ to struct _ffewhere_root_ll_*. All uses
+ changed.
+ (ffewhere_file_kill): Remove.
+ (ffewhere_file_new): Use GC to allocate ffewhereFile objects.
+ (ffewhere_file_set): Use GC to allocate ffewhereLL_ objects.
+ (ffewhere_init_1): Use GC to allocate ffewhere_root_ll_ sentinel.
+ Include gt-f-where.h.
+ * lex.c (ffelex_current_wf_, ffelex_include_wherefile_): Mark GTY.
+ Include gt-f-lex.h.
+ * std.c (ffestd_S3P4): Don't call ffewhere_file_kill.
+ * config-lang.in (gtfiles): Add f/where.h f/where.c and f/lex.c.
+ * Make-lang.in (gt-f-lex.h gt-f-where.h): Add to dependents of
+ s-gtype.
+ (f/lex.o): Depend on gt-f-lex.h.
+ (f/where.o): Depend on gt-f-where.h.
+
+Tue Aug 20 16:49:40 2002 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * where.c (ffewhere_track): Remove impossible if-then clause.
+
+Thu Aug 8 10:06:14 2002 Nathan Sidwell <nathan@codesourcery.com>
+
+ * f/Make-lang.in (f.mostlyclean): Remove coverage files.
+
+2002-08-06 Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
+
+ * g77.texi (Top): Rename Index to Keyword Index.
- * GCC 3.2 Released.
+2002-08-05 Toon Moene <toon@moene.indiv.nluug.nl>
-2002-08-04 Toon Moene <toon@moene.indiv.nluug.nl>
+ * invoke.texi: Improve description of
+ -fno-finite-math-only flag.
- * news.texi: Mention nothing changed for 3.2.
+Sun Aug 4 16:45:49 2002 Joseph S. Myers <jsm@polyomino.org.uk>
-Sun Aug 4 16:48:53 2002 Joseph S. Myers <jsm@polyomino.org.uk>
+ * root.texi (version-gcc): Increase to 3.3.
- * root.texi (version-gcc): Increase to 3.2.
+2002-07-30 Toon Moene <toon@moene.indiv.nluug.nl>
-2002-07-25 Release Manager
+ * com.c (ffe_init_options): Set
+ flag_finite_math_only.
+ * invoke.texi: Document -fno-finite-math-only.
- * GCC 3.1.1 Released.
+Mon Jul 29 22:05:35 2002 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
-2002-06-30 Toon Moene <toon@moene.indiv.nluug.nl>
+ * com.c (read_name_map): Use concat in lieu of xmalloc/strcpy.
+
+2002-07-25 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ * news.texi: Document better handling of (no-)alias
+ information of dummy arguments and induction variables
+ on loop unrolling.
+
+2002-07-01 Roger Sayle <roger@eyesopen.com>
+
+ * f/com.c (builtin_function): Accept additional parameter.
+ (ffe_com_init_0): Pass an additional NULL_TREE argument to
+ builtin_function.
+
+2002-06-28 Toon Moene <toon@moene.indiv.nluug.nl>
* news.texi: Mention 2 Gbyte limit on 32-bit targets
for arrays explicitly in news on g77-3.1.
-2002-05-14 Release Manager
+Thu Jun 20 21:56:34 2002 Neil Booth <neil@daikokuya.co.uk>
+
+ * lang-specs.h: Use cc1 for traditional preprocessing.
+
+2002-06-20 Andreas Jaeger <aj@suse.de>
+
+ * com.c (ffecom_prepare_expr_,ffecom_expr_power_integer_):
+ Remove #ifdefed HAHA sections.
+
+2002-06-20 Nathanael Nerode <neroden@twcny.rr.com>
+
+ * com.c: Remove #ifdef HOHO sections.
+
+2002-06-17 Jason Thorpe <thorpej@wasabisystems.com>
- * GCC 3.1 Released.
+ * bit.c: Don't include glimits.h.
+ * target.c: Likewise.
+ * where.h: Likewise.
-2002-05-14 Release Manager
+2002-06-12 Gabriel Dos Reis <gdr@codesourcery.com>
- * GCC 3.1 Released.
+ * bad.c (ffebad_start_): Adjust calls to diagnostic_count_error.
+
+2002-06-04 Gabriel Dos Reis <gdr@codesourcery.com>
+
+ * bad.c (ffebad_start_): Adjust call to count_error.
+ * Make-lang.in (f/bad.o): Depend on diagnostic.h
+ * bad.c: #include diagnostic.h
+
+2002-06-03 Geoffrey Keating <geoffk@redhat.com>
+
+ * Make-lang.in (f/com.o): Depend on debug.h.
+ * com.c: Include debug.h.
+ (LANG_HOOKS_MARK_TREE): Delete.
+ (struct lang_identifier): Use gengtype.
+ (union lang_tree_node): New.
+ (struct lang_decl): New dummy definition.
+ (struct lang_type): New dummy definition.
+ (ffe_mark_tree): Delete.
+
+ * com.c (struct language_function): New dummy structure.
+
+ * Make-lang.in: Add rules to generate gt-f-ste.h gtype-f.h; allow
+ for filename changes.
+ (com.o): Allow for filename changes; add gtype-f.h as dependency.
+ (ste.o): Add gt-f-ste.h as dependency.
+ * config-lang.in (gtfiles): Add com.h, ste.c.
+ * com.c: Replace uses of ggc_add_* with GTY markers. Include
+ gtype-f.h.
+ (mark_binding_level): Delete.
+ * com.h: Replace uses of ggc_add_* with GTY markers.
+ * ste.c: Replace uses of ggc_add_* with GTY markers. Include
+ gt-f-ste.h.
+
+ * Make-lang.in (f/gt-com.h): Build using gengtype.
+ (com.o): Depend on f/gt-com.h.
+ * com.c: Rename struct binding_level to f_binding_level.
+ (struct f_binding_level): Use gengtype.
+ (struct tree_ggc_tracker): Use gengtype.
+ (mark_tracker_head): Use gt_ggc_m_tree_ggc_tracker.
+ (make_binding_level): Use GGC.
+ (mark_binding_level): Use gt_ggc_m_f_binding_level.
+ (ffecom_init_decl_processing): Change free_binding_level
+ to a deletable root.
+ * config-lang.in (gtfiles): Define.
+ * where.c: Strings need no longer be allocated in GCable memory;
+ remove my change of 30 Dec 1999.
+
+2002-05-31 Matthew Woodcraft <mattheww@chiark.greenend.org.uk>
+
+ * lang-specs.h: Use cpp_debug_options.
+
+2002-05-28 Zack Weinberg <zack@codesourcery.com>
+
+ * bld.c, com.c, expr.c, target.c: Include real.h.
+ * Make-lang.in: Update dependency lists.
+
+2002-05-16 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ * Make-lang.in: Allow for PWDCMD to override hardcoded pwd.
+
+2002-05-09 Hassan Aurag <aurag@cae.com>
+
+ * expr.c (ffeexpr_reduced_ugly2log_): Allow logicals-as-integers
+ under -fugly-logint as arguments of .and., .or., .xor.
+
+2002-05-07 Jan Hubicka <jh@suse.cz>
+
+ * target.h (FFETARGET_32bit_longs): Undefine for x86-64.
2002-04-29 Joseph S. Myers <jsm28@cam.ac.uk>
* invoke.texi: Use @gol at ends of lines inside @gccoptlist.
* g77.texi: Update last update date.
+Thu Apr 25 07:44:44 2002 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * com.h (ffe_parse_file): Update.
+ * lex.c (ffe_parse_file): Update.
+
2002-04-20 Toon Moene <toon@moene.indiv.nluug.nl>
* root.texi: Remove variable version-g77.
* g77.texi: Remove the single use of that variable.
+Thu Apr 18 19:10:44 2002 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * com.c (incomplete_type_error): Remove.
+
Tue Apr 16 14:55:47 2002 Mark Mitchell <mark@codesourcery.com>
* com.c (ffecom_expr_power_integer): Add has_scope argument to
@@ -101,21 +472,63 @@ Mon Apr 15 10:59:14 2002 Mark Mitchell <mark@codesourcery.com>
* g77.texi: Remove Chill reference.
-2002-04-14 Hans-Peter Nilsson <hp@bitrange.com>
+2002-04-13 Toon Moene <toon@moene.indiv.nluug.nl>
+
+ * news.texi: Deprecate frontend version number;
+ update list of fixed bugs.
+
+2002-04-08 Hans-Peter Nilsson <hp@bitrange.com>
* Make-lang.in (f/target.o): Depend on diagnostic.h.
* target.c: Include diagnostic.h.
(ffetarget_memcpy_): Call sorry if host and target endians are
not matching.
-2002-04-13 Toon Moene <toon@moene.indiv.nluug.nl>
+Thu Apr 4 23:29:48 2002 Neil Booth <neil@daikokuya.demon.co.uk>
- * news.texi: Deprecate frontend version number;
- update list of fixed bugs.
+ * com.c (LANG_HOOKS_TRUTHVALUE_CONVERSION): Redefine.
+ (truthvalue_conversion): Rename. Update. Make static.
+ (ffecom_truth_value): Update.
-2002-04-01 Phil Edwards <pme@gcc.gnu.org>
+Mon Apr 1 21:39:36 2002 Neil Booth <neil@daikokuya.demon.co.uk>
- * version.c: Fix misplaced leading blanks on first line.
+ * com.c (LANG_HOOKS_MARK_ADDRESSABLE): Redefine.
+ (mark_addressable): Rename.
+ (ffecom_arrayref_, ffecom_1): Update.
+
+Mon Apr 1 09:59:53 2002 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * com.c (LANG_HOOKS_SIGNED_TYPE, LANG_HOOKS_UNSIGNED_TYPE,
+ LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE): New.
+ (unsigned_type, signed_type, signed_or_unsigned_type): Rename.
+
+Sun Mar 31 23:50:22 2002 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * com.c (lang_print_error_function): Rename.
+ (LANG_HOOKS_PRINT_ERROR_FUNCTION): Redefine.
+ (ffe_init): Don't set hook.
+
+Fri Mar 29 21:59:15 2002 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * com.c (LANG_HOOKS_TYPE_FOR_MODE, LANG_HOOKS_TYPE_FOR_SIZE):
+ Redefine.
+ (type_for_mode, type_for_size): Rename.
+ (signed_or_unsigned_type, signed_type, truthvalue_conversion,
+ unsigned_type): Use new hooks.
+
+Tue Mar 26 10:30:05 2002 Andrew Cagney <ac131313@redhat.com>
+
+ * invoke.texi (Warning Options): Mention -Wswitch-enum.
+ Fix PR c/5044.
+
+Tue Mar 26 07:30:51 2002 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * com.c (LANG_HOOKS_MARK_TREE): Redefine.
+ (lang_mark_tree): Rename ffe_mark_tree, make static.
+
+Mon Mar 25 19:27:11 2002 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * com.c (maybe_build_cleanup): Remove.
2002-03-23 Toon Moene <toon@moene.indiv.nluug.nl>
@@ -124,9 +537,60 @@ Mon Apr 15 10:59:14 2002 Mark Mitchell <mark@codesourcery.com>
addressing get caught.
* news.texi: Document the fixing of this problem.
-Mon Mar 18 18:43:22 CET 2002 Jan Hubicka <jh@suse.cz>
+Sat Mar 23 11:18:17 2002 Andrew Cagney <ac131313@redhat.com>
- * target.h (FFETARGET_32bit_longs): Undefine for x86-64.
+ * invoke.texi (Warning Options): Mention -Wswitch-default.
+
+Thu Mar 21 18:55:41 2002 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * cp-tree.h (pushdecl, pushlevel, poplevel, set_block,
+ insert_block, getdecls, global_bindings_p): New.
+
+Wed Mar 20 08:03:42 2002 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * com.c (lang_printable_name): Rename.
+ (LANG_HOOKS_DECL_PRINTABLE_NAME): Redefine.
+ (ffe_init): Don't use old hook.
+
+Sun Mar 17 18:50:15 2002 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * com.h (ffe_parse_file): Prototype.
+
+Sun Mar 17 20:57:30 2002 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * com.c (LANG_HOOKS_PARSE_FILE): Redefine.
+ * com.h (ffe_parse_file): New.
+ * parse.c (NAME_OF_STDIN): Remove.
+ (yyparse): Rename ffe_parse_file.
+
+Tue Mar 12 20:23:18 2002 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * com.c (tree_code_type, tree_code_length, tree_code_name):
+ Define.
+
+Sun Mar 10 12:37:42 2002 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * target.c (ffetarget_print_hex): Const-ify.
+
+2002-03-06 Phil Edwards <pme@gcc.gnu.org>
+
+ * version.c: Fix misplaced leading blanks on first line.
+
+2002-03-03 Zack Weinberg <zack@codesourcery.com>
+
+ * com.c, target.h: Remove all #ifndef REAL_ARITHMETIC
+ blocks, make all #ifdef REAL_ARITHMETIC blocks unconditional.
+ Delete some further #ifdef blocks predicated on REAL_ARITHMETIC.
+
+Thu Feb 28 07:53:46 2002 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * com.c (copy_lang_decl): Delete.
+
+2002-02-27 Zack Weinberg <zack@codesourcery.com>
+
+ * com.c, lex.c, top.c: Delete traditional-mode-related code
+ copied from the C front end but not used, or used only to
+ permit the compiler to link.
2002-02-13 Toon Moene <toon@moene.indiv.nluug.nl>
@@ -1528,7 +1992,7 @@ Fri Sep 24 10:48:10 1999 Bernd Schmidt <bernds@cygnus.co.uk>
Tue Sep 21 09:08:30 1999 Toon Moene <toon@moene.indiv.nluug.nl>
- * g77spec.c (lang_specific_driver): Initialise return value.
+ * g77spec.c (lang_specific_driver): Initialize return value.
Thu Sep 16 18:07:11 1999 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
@@ -2808,7 +3272,7 @@ Sat Jul 11 19:24:32 1998 Craig Burley <burley@gnu.org>
Sat Jul 11 18:24:37 1998 Craig Burley <burley@gnu.org>
* com.c (ffecom_expr_) [FFEBLD_opCONTER]: Die if padding
- for constant is non-zero.
+ for constant is nonzero.
* com.c (__eprintf): Delete this function, it is obsolete.
@@ -2864,7 +3328,7 @@ Wed Jul 1 11:19:13 1998 Craig Burley <burley@gnu.org>
and even more elegantly than those.
* target.c (ffetarget_align): Make sure alignments
- are non-zero, just in case.
+ are nonzero, just in case.
See ChangeLog.0 for earlier changes.
diff --git a/contrib/gcc/f/ChangeLog.0 b/contrib/gcc/f/ChangeLog.0
index b74222e..3d6675e 100644
--- a/contrib/gcc/f/ChangeLog.0
+++ b/contrib/gcc/f/ChangeLog.0
@@ -38,7 +38,7 @@ Mon Jun 29 09:47:33 1998 Craig Burley <burley@gnu.org>
of equiv area, extend lowering to maintain needed alignment.
* target.c (ffetarget_align): Handle negative offset correctly.
- * global.c (ffeglobal_pad_common): Warn about non-zero
+ * global.c (ffeglobal_pad_common): Warn about nonzero
padding only the first time its seen.
If new padding larger than old, update old.
(ffeglobal_save_common): Use correct type for size throughout.
@@ -2419,7 +2419,7 @@ Sat Nov 2 13:50:31 1996 Craig Burley <burley@gnu.ai.mit.edu>
function call to the type in the fall-through case).
* ste.c (ffeste_R909_finish): Don't special-case list-directed
- I/O, now that libf2c can return non-zero status codes.
+ I/O, now that libf2c can return nonzero status codes.
(ffeste_R910_finish): Ditto.
(ffeste_io_call_): Simplify logic.
(ffeste_io_impdo_):
diff --git a/contrib/gcc/f/Make-lang.in b/contrib/gcc/f/Make-lang.in
index 0bb5f20..1286f07 100644
--- a/contrib/gcc/f/Make-lang.in
+++ b/contrib/gcc/f/Make-lang.in
@@ -1,5 +1,5 @@
# Top level makefile fragment for GNU Fortran. -*-makefile-*-
-# Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+# Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
#This file is part of GNU Fortran.
@@ -65,21 +65,17 @@ F77 f77: f771$(exeext)
f77.extraclean f77.maintainer-clean f77.rebuilt \
f77.stage1 f77.stage2 f77.stage3 f77.stage4
-g77spec.o: $(srcdir)/f/g77spec.c $(srcdir)/f/version.h $(SYSTEM_H) $(GCC_H) \
+g77spec.o: $(srcdir)/f/g77spec.c $(SYSTEM_H) $(GCC_H) \
$(CONFIG_H)
(SHLIB_LINK='$(SHLIB_LINK)' \
SHLIB_MULTILIB='$(SHLIB_MULTILIB)'; \
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
$(INCLUDES) $(srcdir)/f/g77spec.c)
-g77version.o: $(srcdir)/f/version.c
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -o g77version.o \
- $(srcdir)/f/version.c
-
# Create the compiler driver for g77.
-g77$(exeext): gcc.o g77spec.o g77version.o version.o prefix.o intl.o \
+g77$(exeext): gcc.o g77spec.o version.o prefix.o intl.o \
$(LIBDEPS) $(EXTRA_GCC_OBJS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gcc.o g77spec.o g77version.o \
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gcc.o g77spec.o \
version.o prefix.o intl.o $(EXTRA_GCC_OBJS) $(LIBS)
# Create a version of the g77 driver which calls the cross-compiler.
@@ -93,7 +89,7 @@ F77_OBJS = f/bad.o f/bit.o f/bld.o f/com.o f/data.o f/equiv.o f/expr.o \
f/global.o f/implic.o f/info.o f/intrin.o f/lab.o f/lex.o f/malloc.o \
f/name.o f/parse.o f/src.o f/st.o f/sta.o f/stb.o f/stc.o \
f/std.o f/ste.o f/storag.o f/stp.o f/str.o f/sts.o f/stt.o f/stu.o \
- f/stv.o f/stw.o f/symbol.o f/target.o f/top.o f/type.o f/version.o f/where.o
+ f/stv.o f/stw.o f/symbol.o f/target.o f/top.o f/type.o f/where.o
# Use loose warnings for this front end.
f-warn =
@@ -137,6 +133,8 @@ f/fini.o:
$(HOST_CC) $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
-c $(srcdir)/f/fini.c $(OUTPUT_OPTION)
+gt-f-lex.h gt-f-where.h gt-f-com.h gt-f-ste.h gtype-f.h : s-gtype; @true
+
#
# Build hooks:
@@ -155,7 +153,8 @@ $(srcdir)/f/g77.info: $(srcdir)/f/g77.texi $(srcdir)/f/bugs.texi \
$(srcdir)/f/news.texi $(srcdir)/f/intdoc.texi \
$(srcdir)/f/root.texi $(srcdir)/doc/include/fdl.texi \
$(srcdir)/doc/include/gpl.texi \
- $(srcdir)/doc/include/funding.texi
+ $(srcdir)/doc/include/funding.texi \
+ $(srcdir)/doc/include/gcc-common.texi
if [ x$(BUILD_INFO) = xinfo ]; then \
rm -f $(srcdir)/f/g77.info-*; \
cd $(srcdir)/f && $(MAKEINFO) -I../doc/include -o g77.info g77.texi; \
@@ -166,8 +165,9 @@ f/g77.dvi: $(srcdir)/f/g77.texi $(srcdir)/f/bugs.texi \
$(srcdir)/f/news.texi $(srcdir)/f/intdoc.texi \
$(srcdir)/f/root.texi $(srcdir)/doc/include/fdl.texi \
$(srcdir)/doc/include/gpl.texi \
- $(srcdir)/doc/include/funding.texi
- s=`cd $(srcdir); pwd`; export s; \
+ $(srcdir)/doc/include/funding.texi \
+ $(srcdir)/doc/include/gcc-common.texi
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
cd f && $(TEXI2DVI) -I $$s/doc/include $$s/f/g77.texi
$(srcdir)/f/g77.1: $(srcdir)/f/invoke.texi
@@ -226,11 +226,11 @@ f/ansify$(build_exeext): f/ansify.c hconfig.h $(SYSTEM_H)
$(srcdir)/f/BUGS: f/bugs0.texi f/bugs.texi f/root.texi
cd $(srcdir)/f; $(MAKEINFO) -D BUGSONLY --no-header --no-split \
- --no-validate -o BUGS bugs0.texi
+ --no-validate -I../doc/include -o BUGS bugs0.texi
$(srcdir)/f/NEWS: f/news0.texi f/news.texi f/root.texi
cd $(srcdir)/f; $(MAKEINFO) -D NEWSONLY --no-header --no-split \
- --no-validate -o NEWS news0.texi
+ --no-validate -I../doc/include -o NEWS news0.texi
f77.rebuilt: f/g77.info $(srcdir)/f/BUGS \
$(srcdir)/f/NEWS
@@ -313,12 +313,13 @@ f77.uninstall: installdirs
f77.mostlyclean:
-rm -f f/*$(objext)
+ -rm -f f/*$(coverageexts)
-rm -f f/fini$(build_exeext) f/stamp-str f/str-*.h f/str-*.j
-rm -f f/intdoc$(build_exeext) f/ansify$(build_exeext) f/intdoc.h0
-rm -f g77.aux g77.cps g77.ky g77.toc g77.vr g77.fn g77.kys \
g77.pg g77.tp g77.vrs g77.cp g77.fns g77.log g77.pgs g77.tps
f77.clean:
- -rm -f g77spec.o g77version.o
+ -rm -f g77spec.o
f77.distclean:
-rm -f f/Makefile
f77.extraclean:
@@ -329,7 +330,7 @@ f77.maintainer-clean:
# The main makefile has already created stage?/f.
G77STAGESTUFF = f/*$(objext) f/fini$(build_exeext) f/stamp-str \
- f/str-*.h f/str-*.j g77spec.o g77version.o
+ f/str-*.h f/str-*.j g77spec.o
f77.stage1: stage1-start
-mv -f $(G77STAGESTUFF) stage1/f
@@ -350,21 +351,22 @@ f/bad.o: f/bad.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/bad.h f/bad.def f/where.h \
glimits.h f/top.h f/malloc.h flags.h f/com.h f/com-rt.def $(TREE_H) f/bld.h \
f/bld-op.def f/bit.h f/info.h f/info-b.def f/info-k.def f/info-w.def \
f/target.h f/lex.h f/type.h f/intrin.h f/intrin.def f/lab.h f/symbol.h \
- f/symbol.def f/equiv.h f/storag.h f/global.h f/name.h toplev.h intl.h
+ f/symbol.def f/equiv.h f/storag.h f/global.h f/name.h toplev.h intl.h \
+ diagnostic.h
f/bit.o: f/bit.c f/proj.h $(CONFIG_H) $(SYSTEM_H) glimits.h f/bit.h \
f/malloc.h
f/bld.o: f/bld.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/bld.h f/bld-op.def f/bit.h \
f/malloc.h f/com.h f/com-rt.def $(TREE_H) f/info.h f/info-b.def f/info-k.def \
f/info-w.def f/target.h f/bad.h f/bad.def f/where.h glimits.h f/top.h f/lex.h \
f/type.h f/lab.h f/storag.h f/symbol.h f/symbol.def f/equiv.h f/global.h \
- f/name.h f/intrin.h f/intrin.def
+ f/name.h f/intrin.h f/intrin.def real.h
f/com.o: f/com.c f/proj.h $(CONFIG_H) $(SYSTEM_H) flags.h $(RTL_H) $(TREE_H) \
output.h convert.h f/com.h f/com-rt.def f/bld.h f/bld-op.def f/bit.h \
f/malloc.h f/info.h f/info-b.def f/info-k.def f/info-w.def f/target.h f/bad.h \
f/bad.def f/where.h glimits.h f/top.h f/lex.h f/type.h f/intrin.h \
f/intrin.def f/lab.h f/symbol.h f/symbol.def f/equiv.h f/storag.h f/global.h \
f/name.h f/expr.h f/implic.h f/src.h f/st.h $(GGC_H) toplev.h diagnostic.h \
- langhooks.h langhooks-def.h intl.h
+ $(LANGHOOKS_DEF) langhooks.h intl.h real.h debug.h gt-f-com.h gtype-f.h
f/data.o: f/data.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/data.h f/bld.h f/bld-op.def \
f/bit.h f/malloc.h f/com.h f/com-rt.def $(TREE_H) f/info.h f/info-b.def \
f/info-k.def f/info-w.def f/target.h f/bad.h f/bad.def f/where.h glimits.h \
@@ -380,7 +382,7 @@ f/expr.o: f/expr.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/expr.h f/bld.h f/bld-op.de
f/info-k.def f/info-w.def f/target.h f/bad.h f/bad.def f/where.h glimits.h \
f/top.h f/lex.h f/type.h f/lab.h f/storag.h f/symbol.h f/symbol.def f/equiv.h \
f/global.h f/name.h f/intrin.h f/intrin.def f/implic.h f/src.h f/st.h \
- f/stamp-str
+ f/stamp-str real.h
f/fini.o: f/fini.c f/proj.h hconfig.h $(SYSTEM_H) f/malloc.h
f/global.o: f/global.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/global.h f/info.h \
f/info-b.def f/info-k.def f/info-w.def f/target.h $(TREE_H) f/bad.h f/bad.def \
@@ -410,7 +412,7 @@ f/lex.o: f/lex.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/top.h f/malloc.h f/where.h \
f/bld-op.def f/bit.h f/info.h f/info-b.def f/info-k.def f/info-w.def \
f/target.h f/lex.h f/type.h f/intrin.h f/intrin.def f/lab.h f/symbol.h \
f/symbol.def f/equiv.h f/storag.h f/global.h f/name.h f/src.h flags.h \
- debug.h input.h toplev.h output.h $(GGC_H)
+ debug.h input.h toplev.h output.h $(GGC_H) gt-f-lex.h
f/malloc.o: f/malloc.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/malloc.h
f/name.o: f/name.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/bad.h f/bad.def f/where.h \
glimits.h f/top.h f/malloc.h f/name.h f/global.h f/info.h f/info-b.def \
@@ -421,7 +423,7 @@ f/parse.o: f/parse.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/top.h f/malloc.h \
f/where.h glimits.h f/com.h f/com-rt.def $(TREE_H) f/bld.h f/bld-op.def \
f/bit.h f/info.h f/info-b.def f/info-k.def f/info-w.def f/target.h f/bad.h \
f/bad.def f/lex.h f/type.h f/intrin.h f/intrin.def f/lab.h f/symbol.h \
- f/symbol.def f/equiv.h f/storag.h f/global.h f/name.h f/version.h flags.h
+ f/symbol.def f/equiv.h f/storag.h f/global.h f/name.h version.h flags.h
f/src.o: f/src.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/src.h f/bad.h f/bad.def \
f/where.h glimits.h f/top.h f/malloc.h
f/st.o: f/st.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/st.h f/bad.h f/bad.def \
@@ -460,7 +462,8 @@ f/ste.o: f/ste.c f/proj.h $(CONFIG_H) $(SYSTEM_H) $(RTL_H) toplev.h f/ste.h \
f/info.h f/info-b.def f/info-k.def f/info-w.def f/target.h f/bad.h f/bad.def \
f/where.h glimits.h f/top.h f/lex.h f/type.h f/lab.h f/storag.h f/symbol.h \
f/symbol.def f/equiv.h f/global.h f/name.h f/intrin.h f/intrin.def f/stp.h \
- f/stt.h f/stamp-str f/sts.h f/stv.h f/stw.h f/expr.h f/sta.h $(GGC_H)
+ f/stt.h f/stamp-str f/sts.h f/stv.h f/stw.h f/expr.h f/sta.h $(GGC_H) \
+ gt-f-ste.h
f/storag.o: f/storag.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/storag.h f/bld.h \
f/bld-op.def f/bit.h f/malloc.h f/com.h f/com-rt.def $(TREE_H) \
f/info.h f/info-b.def f/info-k.def f/info-w.def f/target.h f/bad.h \
@@ -512,7 +515,7 @@ f/symbol.o: f/symbol.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/symbol.h \
f/lex.h f/type.h f/lab.h f/storag.h f/intrin.h f/intrin.def f/equiv.h \
f/global.h f/name.h f/src.h f/st.h
f/target.o: f/target.c f/proj.h $(CONFIG_H) $(SYSTEM_H) glimits.h f/target.h \
- $(TREE_H) f/bad.h f/bad.def f/where.h f/top.h f/malloc.h f/info.h \
+ $(TREE_H) f/bad.h f/bad.def f/where.h f/top.h f/malloc.h f/info.h real.h \
f/info-b.def f/info-k.def f/info-w.def f/type.h f/lex.h diagnostic.h
f/top.o: f/top.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/top.h f/malloc.h f/where.h \
glimits.h f/bad.h f/bad.def f/bit.h f/bld.h f/bld-op.def f/com.h \
@@ -522,6 +525,5 @@ f/top.o: f/top.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/top.h f/malloc.h f/where.h \
f/intrin.def f/data.h f/expr.h f/implic.h f/src.h f/st.h flags.h \
toplev.h
f/type.o: f/type.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/type.h f/malloc.h
-f/version.o: f/version.c f/version.h
f/where.o: f/where.c f/proj.h $(CONFIG_H) $(SYSTEM_H) f/where.h glimits.h f/top.h \
- f/malloc.h f/lex.h $(GGC_H)
+ f/malloc.h f/lex.h $(GGC_H) gt-f-where.h
diff --git a/contrib/gcc/f/bad.c b/contrib/gcc/f/bad.c
index 4de713c..21fa487 100644
--- a/contrib/gcc/f/bad.c
+++ b/contrib/gcc/f/bad.c
@@ -43,6 +43,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "toplev.h"
#include "where.h"
#include "intl.h"
+#include "diagnostic.h"
/* Externals defined here. */
@@ -202,7 +203,7 @@ ffebad_start_ (bool lex_override, ffebad errnum, ffebadSeverity sev,
if ((ffebad_severity_ != FFEBAD_severityPEDANTIC)
|| !flag_pedantic_errors)
{
- if (count_error (1) == 0)
+ if (!diagnostic_count_diagnostic (global_dc, DK_WARNING))
{ /* User wants no warnings. */
ffebad_is_temp_inhibited_ = TRUE;
return FALSE;
@@ -214,7 +215,7 @@ ffebad_start_ (bool lex_override, ffebad errnum, ffebadSeverity sev,
case FFEBAD_severityWEIRD:
case FFEBAD_severitySEVERE:
case FFEBAD_severityDISASTER:
- count_error (0);
+ diagnostic_count_diagnostic (global_dc, DK_ERROR);
break;
default:
@@ -420,7 +421,7 @@ ffebad_finish ()
{
if (bi != 0)
fputc ('\n', stderr);
- report_error_function (fn);
+ diagnostic_report_current_function (global_dc);
fprintf (stderr,
/* the trailing space on the <file>:<line>: line
fools emacs19 compilation mode into finding the
diff --git a/contrib/gcc/f/bit.c b/contrib/gcc/f/bit.c
index 70d7833..00f064b 100644
--- a/contrib/gcc/f/bit.c
+++ b/contrib/gcc/f/bit.c
@@ -31,7 +31,6 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* Include files. */
#include "proj.h"
-#include "glimits.h"
#include "bit.h"
#include "malloc.h"
diff --git a/contrib/gcc/f/bld.c b/contrib/gcc/f/bld.c
index 9161419..3460c24 100644
--- a/contrib/gcc/f/bld.c
+++ b/contrib/gcc/f/bld.c
@@ -43,6 +43,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "malloc.h"
#include "target.h"
#include "where.h"
+#include "real.h"
/* Externals defined here. */
diff --git a/contrib/gcc/f/bugs.texi b/contrib/gcc/f/bugs.texi
index bdd8765..176072c 100644
--- a/contrib/gcc/f/bugs.texi
+++ b/contrib/gcc/f/bugs.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+@c Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
@c This is part of the G77 manual.
@c For copying conditions, see the file g77.texi.
@@ -11,9 +11,8 @@
@set last-update-bugs 2002-02-01
-@include root.texi
-
@ifset DOC-BUGS
+@include root.texi
@c The immediately following lines apply to the BUGS file
@c which is derived from this file.
@emph{Note:} This file is automatically generated from the files
@@ -79,7 +78,7 @@ An online, ``live'' version of this document
(derived directly from the mainline, development version
of @code{g77} within @code{gcc})
is available via
-@uref{http://www.gnu.org/software/gcc/onlinedocs/g77/Trouble.html}.
+@uref{http://gcc.gnu.org/onlinedocs/g77/Trouble.html}.
Follow the ``Known Bugs'' link.
The following information was last updated on @value{last-update-bugs}:
diff --git a/contrib/gcc/f/com.c b/contrib/gcc/f/com.c
index 13de981..fca0f94 100644
--- a/contrib/gcc/f/com.c
+++ b/contrib/gcc/f/com.c
@@ -82,6 +82,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "proj.h"
#include "flags.h"
+#include "real.h"
#include "rtl.h"
#include "toplev.h"
#include "tree.h"
@@ -92,6 +93,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "intl.h"
#include "langhooks.h"
#include "langhooks-def.h"
+#include "debug.h"
/* VMS-specific definitions */
#ifdef VMS
@@ -154,7 +156,7 @@ tree string_type_node;
inventions should be renamed to be canonical. Note that only
the ones currently required to be global are so. */
-static tree ffecom_tree_fun_type_void;
+static GTY(()) tree ffecom_tree_fun_type_void;
tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
@@ -165,13 +167,14 @@ tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
just use build_function_type and build_pointer_type on the
appropriate _tree_type array element. */
-static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
-static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
-static tree ffecom_tree_subr_type;
-static tree ffecom_tree_ptr_to_subr_type;
-static tree ffecom_tree_blockdata_type;
+static GTY(()) tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
+static GTY(()) tree
+ ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
+static GTY(()) tree ffecom_tree_subr_type;
+static GTY(()) tree ffecom_tree_ptr_to_subr_type;
+static GTY(()) tree ffecom_tree_blockdata_type;
-static tree ffecom_tree_xargc_;
+static GTY(()) tree ffecom_tree_xargc_;
ffecomSymbol ffecom_symbol_null_
=
@@ -187,10 +190,10 @@ ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
tree ffecom_f2c_integer_type_node;
-tree ffecom_f2c_ptr_to_integer_type_node;
+static GTY(()) tree ffecom_f2c_ptr_to_integer_type_node;
tree ffecom_f2c_address_type_node;
tree ffecom_f2c_real_type_node;
-tree ffecom_f2c_ptr_to_real_type_node;
+static GTY(()) tree ffecom_f2c_ptr_to_real_type_node;
tree ffecom_f2c_doublereal_type_node;
tree ffecom_f2c_complex_type_node;
tree ffecom_f2c_doublecomplex_type_node;
@@ -261,6 +264,13 @@ struct _ffecom_concat_list_
/* Static functions (internal). */
+static tree ffe_type_for_mode PARAMS ((enum machine_mode, int));
+static tree ffe_type_for_size PARAMS ((unsigned int, int));
+static tree ffe_unsigned_type PARAMS ((tree));
+static tree ffe_signed_type PARAMS ((tree));
+static tree ffe_signed_or_unsigned_type PARAMS ((int, tree));
+static bool ffe_mark_addressable PARAMS ((tree));
+static tree ffe_truthvalue_conversion PARAMS ((tree));
static void ffecom_init_decl_processing PARAMS ((void));
static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
static tree ffecom_widest_expr_type_ (ffebld list);
@@ -364,9 +374,10 @@ static void delete_block (tree block);
static int duplicate_decls (tree newdecl, tree olddecl);
static void finish_decl (tree decl, tree init, bool is_top_level);
static void finish_function (int nested);
-static const char *lang_printable_name (tree decl, int v);
+static const char *ffe_printable_name (tree decl, int v);
+static void ffe_print_error_function (diagnostic_context *, const char *);
static tree lookup_name_current_level (tree name);
-static struct binding_level *make_binding_level (void);
+static struct f_binding_level *make_binding_level (void);
static void pop_f_function_context (void);
static void push_f_function_context (void);
static void push_parm_decl (tree parm);
@@ -388,15 +399,15 @@ static ffesymbol ffecom_primary_entry_ = NULL;
static ffesymbol ffecom_nested_entry_ = NULL;
static ffeinfoKind ffecom_primary_entry_kind_;
static bool ffecom_primary_entry_is_proc_;
-static tree ffecom_outer_function_decl_;
-static tree ffecom_previous_function_decl_;
-static tree ffecom_which_entrypoint_decl_;
-static tree ffecom_float_zero_ = NULL_TREE;
-static tree ffecom_float_half_ = NULL_TREE;
-static tree ffecom_double_zero_ = NULL_TREE;
-static tree ffecom_double_half_ = NULL_TREE;
-static tree ffecom_func_result_;/* For functions. */
-static tree ffecom_func_length_;/* For CHARACTER fns. */
+static GTY(()) tree ffecom_outer_function_decl_;
+static GTY(()) tree ffecom_previous_function_decl_;
+static GTY(()) tree ffecom_which_entrypoint_decl_;
+static GTY(()) tree ffecom_float_zero_;
+static GTY(()) tree ffecom_float_half_;
+static GTY(()) tree ffecom_double_zero_;
+static GTY(()) tree ffecom_double_half_;
+static GTY(()) tree ffecom_func_result_;/* For functions. */
+static GTY(()) tree ffecom_func_length_;/* For CHARACTER fns. */
static ffebld ffecom_list_blockdata_;
static ffebld ffecom_list_common_;
static ffebld ffecom_master_arglist_;
@@ -406,9 +417,9 @@ static ffetargetCharacterSize ffecom_master_size_;
static int ffecom_num_fns_ = 0;
static int ffecom_num_entrypoints_ = 0;
static bool ffecom_is_altreturning_ = FALSE;
-static tree ffecom_multi_type_node_;
-static tree ffecom_multi_retval_;
-static tree
+static GTY(()) tree ffecom_multi_type_node_;
+static GTY(()) tree ffecom_multi_retval_;
+static GTY(()) tree
ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
static bool ffecom_doing_entry_ = FALSE;
@@ -418,13 +429,7 @@ static int ffecom_typesize_integer1_;
/* Holds pointer-to-function expressions. */
-static tree ffecom_gfrt_[FFECOM_gfrt]
-=
-{
-#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NULL_TREE,
-#include "com-rt.def"
-#undef DEFGFRT
-};
+static GTY(()) tree ffecom_gfrt_[FFECOM_gfrt];
/* Holds the external names of the functions. */
@@ -521,7 +526,7 @@ static const char *const ffecom_gfrt_argstring_[FFECOM_gfrt]
/* Note that the information in the `names' component of the global contour
is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
-struct binding_level
+struct f_binding_level GTY(())
{
/* A chain of _DECL nodes for all variables, constants, functions,
and typedef types. These are in the reverse of the order supplied.
@@ -538,7 +543,7 @@ struct binding_level
tree this_block;
/* The binding level which this one is contained in (inherits from). */
- struct binding_level *level_chain;
+ struct f_binding_level *level_chain;
/* 0: no ffecom_prepare_* functions called at this level yet;
1: ffecom_prepare* functions called, except not ffecom_prepare_end;
@@ -546,36 +551,38 @@ struct binding_level
int prep_state;
};
-#define NULL_BINDING_LEVEL (struct binding_level *) NULL
+#define NULL_BINDING_LEVEL (struct f_binding_level *) NULL
/* The binding level currently in effect. */
-static struct binding_level *current_binding_level;
+static GTY(()) struct f_binding_level *current_binding_level;
/* A chain of binding_level structures awaiting reuse. */
-static struct binding_level *free_binding_level;
+static GTY((deletable (""))) struct f_binding_level *free_binding_level;
/* The outermost binding level, for names of file scope.
This is created when the compiler is started and exists
through the entire run. */
-static struct binding_level *global_binding_level;
+static struct f_binding_level *global_binding_level;
/* Binding level structures are initialized by copying this one. */
-static const struct binding_level clear_binding_level
+static const struct f_binding_level clear_binding_level
=
{NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
/* Language-dependent contents of an identifier. */
-struct lang_identifier
- {
- struct tree_identifier ignore;
- tree global_value, local_value, label_value;
- bool invented;
- };
+struct lang_identifier GTY(())
+{
+ struct tree_identifier common;
+ tree global_value;
+ tree local_value;
+ tree label_value;
+ bool invented;
+};
/* Macros for access to language-specific slots in an identifier. */
/* Each of these slots contains a DECL node or null. */
@@ -596,6 +603,25 @@ struct lang_identifier
#define IDENTIFIER_INVENTED(NODE) \
(((struct lang_identifier *)(NODE))->invented)
+/* The resulting tree type. */
+union lang_tree_node
+ GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
+ chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
+{
+ union tree_node GTY ((tag ("0"),
+ desc ("tree_node_structure (&%h)")))
+ generic;
+ struct lang_identifier GTY ((tag ("1"))) identifier;
+};
+
+/* Fortran doesn't use either of these. */
+struct lang_decl GTY(())
+{
+};
+struct lang_type GTY(())
+{
+};
+
/* In identifiers, C uses the following fields in a special way:
TREE_PUBLIC to record that there was a previous local extern decl.
TREE_USED to record that such a decl was used.
@@ -605,11 +631,11 @@ struct lang_identifier
that have names. Here so we can clear out their names' definitions
at the end of the function. */
-static tree named_labels;
+static GTY(()) tree named_labels;
/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
-static tree shadowed_labels;
+static GTY(()) tree shadowed_labels;
/* Return the subscript expression, modified to do range-checking.
@@ -780,6 +806,7 @@ ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
args, NULL_TREE);
TREE_SIDE_EFFECTS (die) = 1;
+ die = convert (void_type_node, die);
element = ffecom_3 (COND_EXPR,
TREE_TYPE (element),
@@ -795,7 +822,7 @@ ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
`item' is NULL_TREE, or the transformed pointer to the array.
`expr' is the original opARRAYREF expression, which is transformed
if `item' is NULL_TREE.
- `want_ptr' is non-zero if a pointer to the element, instead of
+ `want_ptr' is nonzero if a pointer to the element, instead of
the element itself, is to be returned. */
static tree
@@ -854,7 +881,7 @@ ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
return item;
if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
- && ! mark_addressable (item))
+ && ! ffe_mark_addressable (item))
return error_mark_node;
}
@@ -1787,15 +1814,8 @@ ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
callee_commons,
scalar_args))
{
-#ifdef HOHO
- tempvar = ffecom_make_tempvar (ffecom_tree_type
- [FFEINFO_basictypeCOMPLEX][kt],
- FFETARGET_charactersizeNONE,
- -1);
-#else
tempvar = hook;
assert (tempvar);
-#endif
}
else
{
@@ -2143,13 +2163,8 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
if (!ffesymbol_hook (s).addr)
item = ffecom_1_fn (item);
}
-
-#ifdef HOHO
- tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
-#else
tempvar = ffebld_nonter_hook (expr);
assert (tempvar);
-#endif
tempvar = ffecom_1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (tempvar)),
tempvar);
@@ -2201,13 +2216,8 @@ ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
tree args;
tree newlen;
-#ifdef HOHO
- tempvar = ffecom_make_tempvar (char_type_node,
- ffebld_size (expr), -1);
-#else
tempvar = ffebld_nonter_hook (expr);
assert (tempvar);
-#endif
tempvar = ffecom_1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (tempvar)),
tempvar);
@@ -4021,12 +4031,8 @@ ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
case FFEINTRIN_impCHAR:
case FFEINTRIN_impACHAR:
-#ifdef HOHO
- tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
-#else
tempvar = ffebld_nonter_hook (expr);
assert (tempvar);
-#endif
{
tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
@@ -5599,7 +5605,6 @@ ffecom_expr_power_integer_ (ffebld expr)
ffecom_start_compstmt ();
-#ifndef HAHA
rtmp = ffecom_make_tempvar ("power_r", rtype,
FFETARGET_charactersizeNONE, -1);
ltmp = ffecom_make_tempvar ("power_l", ltype,
@@ -5612,25 +5617,6 @@ ffecom_expr_power_integer_ (ffebld expr)
FFETARGET_charactersizeNONE, -1);
else
divide = NULL_TREE;
-#else /* HAHA */
- {
- tree hook;
-
- hook = ffebld_nonter_hook (expr);
- assert (hook);
- assert (TREE_CODE (hook) == TREE_VEC);
- assert (TREE_VEC_LENGTH (hook) == 4);
- rtmp = TREE_VEC_ELT (hook, 0);
- ltmp = TREE_VEC_ELT (hook, 1);
- result = TREE_VEC_ELT (hook, 2);
- divide = TREE_VEC_ELT (hook, 3);
- if (TREE_CODE (ltype) == COMPLEX_TYPE
- || TREE_CODE (ltype) == RECORD_TYPE)
- assert (divide);
- else
- assert (! divide);
- }
-#endif /* HAHA */
expand_expr_stmt (ffecom_modify (void_type_node,
rtmp,
@@ -6267,27 +6253,12 @@ ffecom_gfrt_tree_ (ffecomGfrt ix)
/* A somewhat evil way to prevent the garbage collector
from collecting 'tree' structures. */
#define NUM_TRACKED_CHUNK 63
-static struct tree_ggc_tracker
+struct tree_ggc_tracker GTY(())
{
struct tree_ggc_tracker *next;
tree trees[NUM_TRACKED_CHUNK];
-} *tracker_head = NULL;
-
-static void
-mark_tracker_head (void *arg)
-{
- struct tree_ggc_tracker *head;
- int i;
-
- for (head = * (struct tree_ggc_tracker **) arg;
- head != NULL;
- head = head->next)
- {
- ggc_mark (head);
- for (i = 0; i < NUM_TRACKED_CHUNK; i++)
- ggc_mark_tree (head->trees[i]);
- }
-}
+};
+static GTY(()) struct tree_ggc_tracker *tracker_head;
void
ffecom_save_tree_forever (tree t)
@@ -6725,15 +6696,6 @@ ffecom_let_char_ (tree dest_tree, tree dest_length,
tree citem;
tree clength;
-#ifdef HOHO
- length_array
- = lengths
- = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
- FFETARGET_charactersizeNONE, count, TRUE);
- item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
- FFETARGET_charactersizeNONE,
- count, TRUE);
-#else
{
tree hook;
@@ -6744,7 +6706,6 @@ ffecom_let_char_ (tree dest_tree, tree dest_length,
length_array = lengths = TREE_VEC_ELT (hook, 0);
item_array = items = TREE_VEC_ELT (hook, 1);
}
-#endif
for (i = 0; i < count; ++i)
{
@@ -7484,7 +7445,7 @@ ffecom_sym_transform_ (ffesymbol s)
assert (et != NULL_TREE);
if (! TREE_STATIC (et))
- put_var_into_stack (et);
+ put_var_into_stack (et, /*rescan=*/true);
offset = ffestorag_modulo (est)
+ ffestorag_offset (ffesymbol_storage (s))
@@ -8130,8 +8091,8 @@ ffecom_sym_transform_ (ffesymbol s)
DECL_EXTERNAL (t) = 1;
TREE_PUBLIC (t) = 1;
- t = start_decl (t, FALSE);
- finish_decl (t, NULL_TREE, FALSE);
+ t = start_decl (t, ffe_is_globals ());
+ finish_decl (t, NULL_TREE, ffe_is_globals ());
if ((g != NULL)
&& ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
@@ -9205,15 +9166,13 @@ ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
/* Build Namelist type. */
+static GTY(()) tree ffecom_type_namelist_var;
static tree
ffecom_type_namelist_ ()
{
- static tree type = NULL_TREE;
-
- if (type == NULL_TREE)
+ if (ffecom_type_namelist_var == NULL_TREE)
{
- static tree namefield, varsfield, nvarsfield;
- tree vardesctype;
+ tree namefield, varsfield, nvarsfield, vardesctype, type;
vardesctype = ffecom_type_vardesc_ ();
@@ -9230,22 +9189,21 @@ ffecom_type_namelist_ ()
TYPE_FIELDS (type) = namefield;
layout_type (type);
- ggc_add_tree_root (&type, 1);
+ ffecom_type_namelist_var = type;
}
- return type;
+ return ffecom_type_namelist_var;
}
/* Build Vardesc type. */
+static GTY(()) tree ffecom_type_vardesc_var;
static tree
ffecom_type_vardesc_ ()
{
- static tree type = NULL_TREE;
- static tree namefield, addrfield, dimsfield, typefield;
-
- if (type == NULL_TREE)
+ if (ffecom_type_vardesc_var == NULL_TREE)
{
+ tree namefield, addrfield, dimsfield, typefield, type;
type = make_node (RECORD_TYPE);
namefield = ffecom_decl_field (type, NULL_TREE, "name",
@@ -9260,10 +9218,10 @@ ffecom_type_vardesc_ ()
TYPE_FIELDS (type) = namefield;
layout_type (type);
- ggc_add_tree_root (&type, 1);
+ ffecom_type_vardesc_var = type;
}
- return type;
+ return ffecom_type_vardesc_var;
}
static tree
@@ -9525,7 +9483,7 @@ ffecom_1 (enum tree_code code, tree type, tree node)
if (code == ADDR_EXPR)
{
- if (!mark_addressable (node))
+ if (!ffe_mark_addressable (node))
assert ("can't mark_addressable this node!" == NULL);
}
@@ -10251,18 +10209,6 @@ ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
/* ~~Kludge! */
assert (sz != FFETARGET_charactersizeNONE);
-#ifdef HOHO
- length_array
- = lengths
- = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
- FFETARGET_charactersizeNONE, count, TRUE);
- item_array
- = items
- = ffecom_push_tempvar (ffecom_f2c_address_type_node,
- FFETARGET_charactersizeNONE, count, TRUE);
- temporary = ffecom_push_tempvar (char_type_node,
- sz, -1, TRUE);
-#else
{
tree hook;
@@ -10274,7 +10220,6 @@ ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
item_array = items = TREE_VEC_ELT (hook, 1);
temporary = TREE_VEC_ELT (hook, 2);
}
-#endif
known_length = ffecom_f2c_ftnlen_zero_node;
@@ -10648,6 +10593,78 @@ ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
return item;
}
+/* Transform constant-union to tree, with the type known. */
+
+tree
+ffecom_constantunion_with_type (ffebldConstantUnion *cu,
+ tree tree_type, ffebldConst ct)
+{
+ tree item;
+
+ int val;
+
+ switch (ct)
+ {
+#if FFETARGET_okINTEGER1
+ case FFEBLD_constINTEGER1:
+ val = ffebld_cu_val_integer1 (*cu);
+ item = build_int_2 (val, (val < 0) ? -1 : 0);
+ break;
+#endif
+#if FFETARGET_okINTEGER2
+ case FFEBLD_constINTEGER2:
+ val = ffebld_cu_val_integer2 (*cu);
+ item = build_int_2 (val, (val < 0) ? -1 : 0);
+ break;
+#endif
+#if FFETARGET_okINTEGER3
+ case FFEBLD_constINTEGER3:
+ val = ffebld_cu_val_integer3 (*cu);
+ item = build_int_2 (val, (val < 0) ? -1 : 0);
+ break;
+#endif
+#if FFETARGET_okINTEGER4
+ case FFEBLD_constINTEGER4:
+ val = ffebld_cu_val_integer4 (*cu);
+ item = build_int_2 (val, (val < 0) ? -1 : 0);
+ break;
+#endif
+#if FFETARGET_okLOGICAL1
+ case FFEBLD_constLOGICAL1:
+ val = ffebld_cu_val_logical1 (*cu);
+ item = build_int_2 (val, (val < 0) ? -1 : 0);
+ break;
+#endif
+#if FFETARGET_okLOGICAL2
+ case FFEBLD_constLOGICAL2:
+ val = ffebld_cu_val_logical2 (*cu);
+ item = build_int_2 (val, (val < 0) ? -1 : 0);
+ break;
+#endif
+#if FFETARGET_okLOGICAL3
+ case FFEBLD_constLOGICAL3:
+ val = ffebld_cu_val_logical3 (*cu);
+ item = build_int_2 (val, (val < 0) ? -1 : 0);
+ break;
+#endif
+#if FFETARGET_okLOGICAL4
+ case FFEBLD_constLOGICAL4:
+ val = ffebld_cu_val_logical4 (*cu);
+ item = build_int_2 (val, (val < 0) ? -1 : 0);
+ break;
+#endif
+ default:
+ assert ("constant type not supported"==NULL);
+ return error_mark_node;
+ break;
+ }
+
+ TREE_TYPE (item) = tree_type;
+
+ TREE_CONSTANT (item) = 1;
+
+ return item;
+}
/* Transform expression into constant tree.
If the expression can be transformed into a tree that is constant,
@@ -11180,7 +11197,7 @@ ffecom_init_0 ()
name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
(int (*)(const void *, const void *)) strcmp);
- if (name != &names[0][2])
+ if (name != &names[2][0])
{
assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
== NULL);
@@ -11724,23 +11741,23 @@ ffecom_init_0 ()
= build_function_type (void_type_node, NULL_TREE);
builtin_function ("__builtin_sqrtf", float_ftype_float,
- BUILT_IN_SQRTF, BUILT_IN_NORMAL, "sqrtf");
+ BUILT_IN_SQRTF, BUILT_IN_NORMAL, "sqrtf", NULL_TREE);
builtin_function ("__builtin_sqrt", double_ftype_double,
- BUILT_IN_SQRT, BUILT_IN_NORMAL, "sqrt");
+ BUILT_IN_SQRT, BUILT_IN_NORMAL, "sqrt", NULL_TREE);
builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
- BUILT_IN_SQRTL, BUILT_IN_NORMAL, "sqrtl");
+ BUILT_IN_SQRTL, BUILT_IN_NORMAL, "sqrtl", NULL_TREE);
builtin_function ("__builtin_sinf", float_ftype_float,
- BUILT_IN_SINF, BUILT_IN_NORMAL, "sinf");
+ BUILT_IN_SINF, BUILT_IN_NORMAL, "sinf", NULL_TREE);
builtin_function ("__builtin_sin", double_ftype_double,
- BUILT_IN_SIN, BUILT_IN_NORMAL, "sin");
+ BUILT_IN_SIN, BUILT_IN_NORMAL, "sin", NULL_TREE);
builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
- BUILT_IN_SINL, BUILT_IN_NORMAL, "sinl");
+ BUILT_IN_SINL, BUILT_IN_NORMAL, "sinl", NULL_TREE);
builtin_function ("__builtin_cosf", float_ftype_float,
- BUILT_IN_COSF, BUILT_IN_NORMAL, "cosf");
+ BUILT_IN_COSF, BUILT_IN_NORMAL, "cosf", NULL_TREE);
builtin_function ("__builtin_cos", double_ftype_double,
- BUILT_IN_COS, BUILT_IN_NORMAL, "cos");
+ BUILT_IN_COS, BUILT_IN_NORMAL, "cos", NULL_TREE);
builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
- BUILT_IN_COSL, BUILT_IN_NORMAL, "cosl");
+ BUILT_IN_COSL, BUILT_IN_NORMAL, "cosl", NULL_TREE);
pedantic_lvalues = FALSE;
@@ -11804,11 +11821,7 @@ ffecom_init_0 ()
{
REAL_VALUE_TYPE point_5;
-#ifdef REAL_ARITHMETIC
REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
-#else
- point_5 = .5;
-#endif
ffecom_float_half_ = build_real (float_type_node, point_5);
ffecom_double_half_ = build_real (double_type_node, point_5);
}
@@ -12466,27 +12479,6 @@ ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
}
break;
-#ifdef HAHA
- case FFEBLD_opPOWER:
- {
- tree rtype, ltype;
- tree rtmp, ltmp, result;
-
- ltype = ffecom_type_expr (ffebld_left (expr));
- rtype = ffecom_type_expr (ffebld_right (expr));
-
- rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
- ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
- result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
-
- tempvar = make_tree_vec (3);
- TREE_VEC_ELT (tempvar, 0) = rtmp;
- TREE_VEC_ELT (tempvar, 1) = ltmp;
- TREE_VEC_ELT (tempvar, 2) = result;
- }
- break;
-#endif /* HAHA */
-
case FFEBLD_opCONCATENATE:
{
/* This gets special handling, because only one set of temps
@@ -13009,7 +13001,7 @@ ffecom_temp_label ()
tree
ffecom_truth_value (tree expr)
{
- return truthvalue_conversion (expr);
+ return ffe_truthvalue_conversion (expr);
}
/* Return the inversion of a truth value (the inversion of what
@@ -13154,12 +13146,14 @@ bison_rule_compstmt_ ()
See tree.h for its possible values.
If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
- the name to be called if we can't opencode the function. */
+ the name to be called if we can't opencode the function. If
+ ATTRS is nonzero, use that for the function's attribute list. */
tree
builtin_function (const char *name, tree type, int function_code,
enum built_in_class class,
- const char *library_name)
+ const char *library_name,
+ tree attrs ATTRIBUTE_UNUSED)
{
tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
@@ -13639,7 +13633,7 @@ finish_function (int nested)
nested function and all). */
static const char *
-lang_printable_name (tree decl, int v)
+ffe_printable_name (tree decl, int v)
{
/* Just to keep GCC quiet about the unused variable.
In theory, differing values of V should produce different
@@ -13657,8 +13651,8 @@ lang_printable_name (tree decl, int v)
an error. */
static void
-lang_print_error_function (diagnostic_context *context __attribute__((unused)),
- const char *file)
+ffe_print_error_function (diagnostic_context *context __attribute__((unused)),
+ const char *file)
{
static ffeglobal last_g = NULL;
static ffesymbol last_s = NULL;
@@ -13727,13 +13721,13 @@ lookup_name_current_level (tree name)
return t;
}
-/* Create a new `struct binding_level'. */
+/* Create a new `struct f_binding_level'. */
-static struct binding_level *
+static struct f_binding_level *
make_binding_level ()
{
/* NOSTRICT */
- return (struct binding_level *) xmalloc (sizeof (struct binding_level));
+ return ggc_alloc (sizeof (struct f_binding_level));
}
/* Save and restore the variables in this file and elsewhere
@@ -13745,7 +13739,7 @@ struct f_function
struct f_function *next;
tree named_labels;
tree shadowed_labels;
- struct binding_level *binding_level;
+ struct f_binding_level *binding_level;
};
struct f_function *f_function_chain;
@@ -13833,7 +13827,7 @@ pushdecl_top_level (x)
tree x;
{
register tree t;
- register struct binding_level *b = current_binding_level;
+ register struct f_binding_level *b = current_binding_level;
register tree f = current_function_decl;
current_binding_level = global_binding_level;
@@ -13937,7 +13931,7 @@ start_decl (tree decl, bool is_top_level)
Returns 1 on success. If the DECLARATOR is not suitable for a function
(it defines a datum instead), we return 0, which tells
- yyparse to report a parse error.
+ ffe_parse_file to report a parse error.
NESTED is nonzero for a function nested within another function. */
@@ -14054,15 +14048,6 @@ convert (type, expr)
return error_mark_node;
}
-/* integrate_decl_tree calls this function, but since we don't use the
- DECL_LANG_SPECIFIC field, this is a no-op. */
-
-void
-copy_lang_decl (node)
- tree node UNUSED;
-{
-}
-
/* Return the list of declarations of the current level.
Note that this list is in reverse order unless/until
you nreverse it; and when you do nreverse it, you must
@@ -14082,101 +14067,11 @@ global_bindings_p ()
return current_binding_level == global_binding_level;
}
-/* Print an error message for invalid use of an incomplete type.
- VALUE is the expression that was used (or 0 if that isn't known)
- and TYPE is the type that was invalid. */
-
-void
-incomplete_type_error (value, type)
- tree value UNUSED;
- tree type;
-{
- if (TREE_CODE (type) == ERROR_MARK)
- return;
-
- assert ("incomplete type?!?" == NULL);
-}
-
-/* Mark ARG for GC. */
-static void
-mark_binding_level (void *arg)
-{
- struct binding_level *level = *(struct binding_level **) arg;
-
- while (level)
- {
- ggc_mark_tree (level->names);
- ggc_mark_tree (level->blocks);
- ggc_mark_tree (level->this_block);
- level = level->level_chain;
- }
-}
-
static void
ffecom_init_decl_processing ()
{
- static tree *const tree_roots[] = {
- &current_function_decl,
- &string_type_node,
- &ffecom_tree_fun_type_void,
- &ffecom_integer_zero_node,
- &ffecom_integer_one_node,
- &ffecom_tree_subr_type,
- &ffecom_tree_ptr_to_subr_type,
- &ffecom_tree_blockdata_type,
- &ffecom_tree_xargc_,
- &ffecom_f2c_integer_type_node,
- &ffecom_f2c_ptr_to_integer_type_node,
- &ffecom_f2c_address_type_node,
- &ffecom_f2c_real_type_node,
- &ffecom_f2c_ptr_to_real_type_node,
- &ffecom_f2c_doublereal_type_node,
- &ffecom_f2c_complex_type_node,
- &ffecom_f2c_doublecomplex_type_node,
- &ffecom_f2c_longint_type_node,
- &ffecom_f2c_logical_type_node,
- &ffecom_f2c_flag_type_node,
- &ffecom_f2c_ftnlen_type_node,
- &ffecom_f2c_ftnlen_zero_node,
- &ffecom_f2c_ftnlen_one_node,
- &ffecom_f2c_ftnlen_two_node,
- &ffecom_f2c_ptr_to_ftnlen_type_node,
- &ffecom_f2c_ftnint_type_node,
- &ffecom_f2c_ptr_to_ftnint_type_node,
- &ffecom_outer_function_decl_,
- &ffecom_previous_function_decl_,
- &ffecom_which_entrypoint_decl_,
- &ffecom_float_zero_,
- &ffecom_float_half_,
- &ffecom_double_zero_,
- &ffecom_double_half_,
- &ffecom_func_result_,
- &ffecom_func_length_,
- &ffecom_multi_type_node_,
- &ffecom_multi_retval_,
- &named_labels,
- &shadowed_labels
- };
- size_t i;
-
malloc_init ();
- /* Record our roots. */
- for (i = 0; i < ARRAY_SIZE (tree_roots); i++)
- ggc_add_tree_root (tree_roots[i], 1);
- ggc_add_tree_root (&ffecom_tree_type[0][0],
- FFEINFO_basictype*FFEINFO_kindtype);
- ggc_add_tree_root (&ffecom_tree_fun_type[0][0],
- FFEINFO_basictype*FFEINFO_kindtype);
- ggc_add_tree_root (&ffecom_tree_ptr_to_fun_type[0][0],
- FFEINFO_basictype*FFEINFO_kindtype);
- ggc_add_tree_root (ffecom_gfrt_, FFECOM_gfrt);
- ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
- mark_binding_level);
- ggc_add_root (&free_binding_level, 1, sizeof current_binding_level,
- mark_binding_level);
- ggc_add_root (&tracker_head, 1, sizeof tracker_head, mark_tracker_head);
-
ffe_init_0 ();
}
@@ -14219,6 +14114,11 @@ static void ffe_finish PARAMS ((void));
static void ffe_init_options PARAMS ((void));
static void ffe_print_identifier PARAMS ((FILE *, tree, int));
+struct language_function GTY(())
+{
+ int unused;
+};
+
#undef LANG_HOOKS_NAME
#define LANG_HOOKS_NAME "GNU F77"
#undef LANG_HOOKS_INIT
@@ -14229,8 +14129,29 @@ static void ffe_print_identifier PARAMS ((FILE *, tree, int));
#define LANG_HOOKS_INIT_OPTIONS ffe_init_options
#undef LANG_HOOKS_DECODE_OPTION
#define LANG_HOOKS_DECODE_OPTION ffe_decode_option
+#undef LANG_HOOKS_PARSE_FILE
+#define LANG_HOOKS_PARSE_FILE ffe_parse_file
+#undef LANG_HOOKS_MARK_ADDRESSABLE
+#define LANG_HOOKS_MARK_ADDRESSABLE ffe_mark_addressable
#undef LANG_HOOKS_PRINT_IDENTIFIER
#define LANG_HOOKS_PRINT_IDENTIFIER ffe_print_identifier
+#undef LANG_HOOKS_DECL_PRINTABLE_NAME
+#define LANG_HOOKS_DECL_PRINTABLE_NAME ffe_printable_name
+#undef LANG_HOOKS_PRINT_ERROR_FUNCTION
+#define LANG_HOOKS_PRINT_ERROR_FUNCTION ffe_print_error_function
+#undef LANG_HOOKS_TRUTHVALUE_CONVERSION
+#define LANG_HOOKS_TRUTHVALUE_CONVERSION ffe_truthvalue_conversion
+
+#undef LANG_HOOKS_TYPE_FOR_MODE
+#define LANG_HOOKS_TYPE_FOR_MODE ffe_type_for_mode
+#undef LANG_HOOKS_TYPE_FOR_SIZE
+#define LANG_HOOKS_TYPE_FOR_SIZE ffe_type_for_size
+#undef LANG_HOOKS_SIGNED_TYPE
+#define LANG_HOOKS_SIGNED_TYPE ffe_signed_type
+#undef LANG_HOOKS_UNSIGNED_TYPE
+#define LANG_HOOKS_UNSIGNED_TYPE ffe_unsigned_type
+#undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
+#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE ffe_signed_or_unsigned_type
/* We do not wish to use alias-set based aliasing at all. Used in the
extreme (every object with its own set, with equivalences recorded) it
@@ -14242,6 +14163,37 @@ static void ffe_print_identifier PARAMS ((FILE *, tree, int));
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+/* Table indexed by tree code giving a string containing a character
+ classifying the tree code. Possibilities are
+ t, d, s, c, r, <, 1, 2 and e. See tree.def for details. */
+
+#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
+
+const char tree_code_type[] = {
+#include "tree.def"
+};
+#undef DEFTREECODE
+
+/* Table indexed by tree code giving number of expression
+ operands beyond the fixed part of the node structure.
+ Not used for types or decls. */
+
+#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
+
+const unsigned char tree_code_length[] = {
+#include "tree.def"
+};
+#undef DEFTREECODE
+
+/* Names of tree components.
+ Used for printing out the tree and error messages. */
+#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
+
+const char *const tree_code_name[] = {
+#include "tree.def"
+};
+#undef DEFTREECODE
+
static const char *
ffe_init (filename)
const char *filename;
@@ -14262,8 +14214,6 @@ ffe_init (filename)
#endif
ffecom_init_decl_processing ();
- decl_printable_name = lang_printable_name;
- print_error_function = lang_print_error_function;
/* If the file is output from cpp, it should contain a first line
`# 1 "real-filename"', and the current design of gcc (toplev.c
@@ -14304,8 +14254,8 @@ ffe_init_options ()
flag_complex_divide_method = 1;
}
-int
-mark_addressable (exp)
+static bool
+ffe_mark_addressable (exp)
tree exp;
{
register tree x = exp;
@@ -14320,7 +14270,7 @@ mark_addressable (exp)
case CONSTRUCTOR:
TREE_ADDRESSABLE (x) = 1;
- return 1;
+ return true;
case VAR_DECL:
case CONST_DECL:
@@ -14332,7 +14282,7 @@ mark_addressable (exp)
if (TREE_PUBLIC (x))
{
assert ("address of global register var requested" == NULL);
- return 0;
+ return false;
}
assert ("address of register variable requested" == NULL);
}
@@ -14341,11 +14291,11 @@ mark_addressable (exp)
if (TREE_PUBLIC (x))
{
assert ("address of global register var requested" == NULL);
- return 0;
+ return false;
}
assert ("address of register var requested" == NULL);
}
- put_var_into_stack (x);
+ put_var_into_stack (x, /*rescan=*/true);
/* drops in */
case FUNCTION_DECL:
@@ -14356,21 +14306,10 @@ mark_addressable (exp)
#endif
default:
- return 1;
+ return true;
}
}
-/* If DECL has a cleanup, build and return that cleanup here.
- This is a callback called by expand_expr. */
-
-tree
-maybe_build_cleanup (decl)
- tree decl UNUSED;
-{
- /* There are no cleanups in Fortran. */
- return NULL_TREE;
-}
-
/* 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.
@@ -14494,7 +14433,7 @@ poplevel (keep, reverse, functionbody)
/* Pop the current level, and free the structure for reuse. */
{
- register struct binding_level *level = current_binding_level;
+ register struct f_binding_level *level = current_binding_level;
current_binding_level = current_binding_level->level_chain;
level->level_chain = free_binding_level;
@@ -14549,7 +14488,7 @@ pushdecl (x)
{
register tree t;
register tree name = DECL_NAME (x);
- register struct binding_level *b = current_binding_level;
+ register struct f_binding_level *b = current_binding_level;
if ((TREE_CODE (x) == FUNCTION_DECL)
&& (DECL_INITIAL (x) == 0)
@@ -14681,7 +14620,7 @@ void
pushlevel (tag_transparent)
int tag_transparent;
{
- register struct binding_level *newlevel = NULL_BINDING_LEVEL;
+ register struct f_binding_level *newlevel = NULL_BINDING_LEVEL;
assert (! tag_transparent);
@@ -14724,8 +14663,8 @@ set_block (block)
BLOCK_SUBBLOCKS (block));
}
-tree
-signed_or_unsigned_type (unsignedp, type)
+static tree
+ffe_signed_or_unsigned_type (unsignedp, type)
int unsignedp;
tree type;
{
@@ -14745,15 +14684,15 @@ signed_or_unsigned_type (unsignedp, type)
return (unsignedp ? long_long_unsigned_type_node
: long_long_integer_type_node);
- type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
+ type2 = ffe_type_for_size (TYPE_PRECISION (type), unsignedp);
if (type2 == NULL_TREE)
return type;
return type2;
}
-tree
-signed_type (type)
+static tree
+ffe_signed_type (type)
tree type;
{
tree type1 = TYPE_MAIN_VARIANT (type);
@@ -14781,7 +14720,7 @@ signed_type (type)
return intQI_type_node;
#endif
- type2 = type_for_size (TYPE_PRECISION (type1), 0);
+ type2 = ffe_type_for_size (TYPE_PRECISION (type1), 0);
if (type2 != NULL_TREE)
return type2;
@@ -14807,8 +14746,8 @@ signed_type (type)
The resulting type should always be `integer_type_node'. */
-tree
-truthvalue_conversion (expr)
+static tree
+ffe_truthvalue_conversion (expr)
tree expr;
{
if (TREE_CODE (expr) == ERROR_MARK)
@@ -14885,31 +14824,38 @@ truthvalue_conversion (expr)
return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
integer_type_node,
- truthvalue_conversion (TREE_OPERAND (expr, 0)),
- truthvalue_conversion (TREE_OPERAND (expr, 1)));
+ ffe_truthvalue_conversion (TREE_OPERAND (expr, 0)),
+ ffe_truthvalue_conversion (TREE_OPERAND (expr, 1)));
case NEGATE_EXPR:
case ABS_EXPR:
case FLOAT_EXPR:
case FFS_EXPR:
- /* These don't change whether an object is non-zero or zero. */
- return truthvalue_conversion (TREE_OPERAND (expr, 0));
+ /* These don't change whether an object is nonzero or zero. */
+ return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
case LROTATE_EXPR:
case RROTATE_EXPR:
- /* These don't change whether an object is zero or non-zero, but
+ /* These don't change whether an object is zero or nonzero, but
we can't ignore them if their second arg has side-effects. */
if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
- truthvalue_conversion (TREE_OPERAND (expr, 0)));
+ ffe_truthvalue_conversion (TREE_OPERAND (expr, 0)));
else
- return truthvalue_conversion (TREE_OPERAND (expr, 0));
+ return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
case COND_EXPR:
- /* Distribute the conversion into the arms of a COND_EXPR. */
- return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
- truthvalue_conversion (TREE_OPERAND (expr, 1)),
- truthvalue_conversion (TREE_OPERAND (expr, 2))));
+ {
+ /* Distribute the conversion into the arms of a COND_EXPR. */
+ tree arg1 = TREE_OPERAND (expr, 1);
+ tree arg2 = TREE_OPERAND (expr, 2);
+ if (! VOID_TYPE_P (TREE_TYPE (arg1)))
+ arg1 = ffe_truthvalue_conversion (arg1);
+ if (! VOID_TYPE_P (TREE_TYPE (arg2)))
+ arg2 = ffe_truthvalue_conversion (arg2);
+ return fold (build (COND_EXPR, integer_type_node,
+ TREE_OPERAND (expr, 0), arg1, arg2));
+ }
case CONVERT_EXPR:
/* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
@@ -14922,7 +14868,7 @@ truthvalue_conversion (expr)
/* If this is widening the argument, we can ignore it. */
if (TYPE_PRECISION (TREE_TYPE (expr))
>= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
- return truthvalue_conversion (TREE_OPERAND (expr, 0));
+ return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
break;
case MINUS_EXPR:
@@ -14967,20 +14913,20 @@ truthvalue_conversion (expr)
((TREE_SIDE_EFFECTS (expr)
? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
integer_type_node,
- truthvalue_conversion (ffecom_1 (REALPART_EXPR,
- TREE_TYPE (TREE_TYPE (expr)),
- expr)),
- truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
- TREE_TYPE (TREE_TYPE (expr)),
- expr))));
+ ffe_truthvalue_conversion (ffecom_1 (REALPART_EXPR,
+ TREE_TYPE (TREE_TYPE (expr)),
+ expr)),
+ ffe_truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
+ TREE_TYPE (TREE_TYPE (expr)),
+ expr))));
return ffecom_2 (NE_EXPR, integer_type_node,
expr,
convert (TREE_TYPE (expr), integer_zero_node));
}
-tree
-type_for_mode (mode, unsignedp)
+static tree
+ffe_type_for_mode (mode, unsignedp)
enum machine_mode mode;
int unsignedp;
{
@@ -15039,8 +14985,8 @@ type_for_mode (mode, unsignedp)
return 0;
}
-tree
-type_for_size (bits, unsignedp)
+static tree
+ffe_type_for_size (bits, unsignedp)
unsigned bits;
int unsignedp;
{
@@ -15075,8 +15021,8 @@ type_for_size (bits, unsignedp)
return 0;
}
-tree
-unsigned_type (type)
+static tree
+ffe_unsigned_type (type)
tree type;
{
tree type1 = TYPE_MAIN_VARIANT (type);
@@ -15104,7 +15050,7 @@ unsigned_type (type)
return unsigned_intQI_type_node;
#endif
- type2 = type_for_size (TYPE_PRECISION (type1), 1);
+ type2 = ffe_type_for_size (TYPE_PRECISION (type1), 1);
if (type2 != NULL_TREE)
return type2;
@@ -15118,21 +15064,6 @@ unsigned_type (type)
return type;
}
-
-void
-lang_mark_tree (t)
- union tree_node *t ATTRIBUTE_UNUSED;
-{
- if (TREE_CODE (t) == IDENTIFIER_NODE)
- {
- struct lang_identifier *i = (struct lang_identifier *) t;
- ggc_mark_tree (IDENTIFIER_GLOBAL_VALUE (i));
- ggc_mark_tree (IDENTIFIER_LOCAL_VALUE (i));
- ggc_mark_tree (IDENTIFIER_LABEL_VALUE (i));
- }
- else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
- ggc_mark (TYPE_LANG_SPECIFIC (t));
-}
/* From gcc/cccp.c, the code to handle -I. */
@@ -15178,7 +15109,7 @@ struct file_name_list
char *fname;
/* Mapping of file names for this directory. */
struct file_name_map *name_map;
- /* Non-zero if name_map is valid. */
+ /* Nonzero if name_map is valid. */
int got_name_map;
};
@@ -15465,10 +15396,10 @@ read_name_map (dirname)
dirlen = strlen (dirname);
separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
- name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
- strcpy (name, dirname);
- name[dirlen] = '/';
- strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
+ if (separator_needed)
+ name = concat (dirname, "/", FILE_NAME_MAP_FILE, NULL);
+ else
+ name = concat (dirname, FILE_NAME_MAP_FILE, NULL);
f = fopen (name, "r");
free (name);
if (!f)
@@ -15498,10 +15429,10 @@ read_name_map (dirname)
ptr->map_to = to;
else
{
- ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
- strcpy (ptr->map_to, dirname);
- ptr->map_to[dirlen] = '/';
- strcpy (ptr->map_to + dirlen + separator_needed, to);
+ if (separator_needed)
+ ptr->map_to = concat (dirname, "/", to, NULL);
+ else
+ ptr->map_to = concat (dirname, to, NULL);
free (to);
}
@@ -16205,7 +16136,7 @@ typedef doublereal E_f; // real function with -R not specified //
// (No such symbols should be defined in a strict ANSI C compiler.
We can avoid trouble with f2c-translated code by using
- gcc -ansi [-traditional].) //
+ gcc -ansi.) //
@@ -16636,3 +16567,6 @@ typedef doublereal E_f; // real function with -R not specified //
-------- (end output file from f2c)
*/
+
+#include "gt-f-com.h"
+#include "gtype-f.h"
diff --git a/contrib/gcc/f/com.h b/contrib/gcc/f/com.h
index 5e20e2b..b58e5ba 100644
--- a/contrib/gcc/f/com.h
+++ b/contrib/gcc/f/com.h
@@ -157,37 +157,42 @@ struct _ffecom_symbol_
#include "storag.h"
#include "symbol.h"
-/* Structure definitions. */
-
+extern int global_bindings_p PARAMS ((void));
+extern tree getdecls PARAMS ((void));
+extern void pushlevel PARAMS ((int));
+extern tree poplevel PARAMS ((int,int, int));
+extern void insert_block PARAMS ((tree));
+extern void set_block PARAMS ((tree));
+extern tree pushdecl PARAMS ((tree));
/* Global objects accessed by users of this module. */
-extern tree string_type_node;
-extern tree ffecom_integer_type_node;
-extern tree ffecom_integer_zero_node;
-extern tree ffecom_integer_one_node;
-extern tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
+extern GTY(()) tree string_type_node;
+extern GTY(()) tree ffecom_integer_type_node;
+extern GTY(()) tree ffecom_integer_zero_node;
+extern GTY(()) tree ffecom_integer_one_node;
+extern GTY(()) tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
extern ffecomSymbol ffecom_symbol_null_;
extern ffeinfoKindtype ffecom_pointer_kind_;
extern ffeinfoKindtype ffecom_label_kind_;
extern int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
-extern tree ffecom_f2c_integer_type_node;
-extern tree ffecom_f2c_address_type_node;
-extern tree ffecom_f2c_real_type_node;
-extern tree ffecom_f2c_doublereal_type_node;
-extern tree ffecom_f2c_complex_type_node;
-extern tree ffecom_f2c_doublecomplex_type_node;
-extern tree ffecom_f2c_longint_type_node;
-extern tree ffecom_f2c_logical_type_node;
-extern tree ffecom_f2c_flag_type_node;
-extern tree ffecom_f2c_ftnlen_type_node;
-extern tree ffecom_f2c_ftnlen_zero_node;
-extern tree ffecom_f2c_ftnlen_one_node;
-extern tree ffecom_f2c_ftnlen_two_node;
-extern tree ffecom_f2c_ptr_to_ftnlen_type_node;
-extern tree ffecom_f2c_ftnint_type_node;
-extern tree ffecom_f2c_ptr_to_ftnint_type_node;
+extern GTY(()) tree ffecom_f2c_integer_type_node;
+extern GTY(()) tree ffecom_f2c_address_type_node;
+extern GTY(()) tree ffecom_f2c_real_type_node;
+extern GTY(()) tree ffecom_f2c_doublereal_type_node;
+extern GTY(()) tree ffecom_f2c_complex_type_node;
+extern GTY(()) tree ffecom_f2c_doublecomplex_type_node;
+extern GTY(()) tree ffecom_f2c_longint_type_node;
+extern GTY(()) tree ffecom_f2c_logical_type_node;
+extern GTY(()) tree ffecom_f2c_flag_type_node;
+extern GTY(()) tree ffecom_f2c_ftnlen_type_node;
+extern GTY(()) tree ffecom_f2c_ftnlen_zero_node;
+extern GTY(()) tree ffecom_f2c_ftnlen_one_node;
+extern GTY(()) tree ffecom_f2c_ftnlen_two_node;
+extern GTY(()) tree ffecom_f2c_ptr_to_ftnlen_type_node;
+extern GTY(()) tree ffecom_f2c_ftnint_type_node;
+extern GTY(()) tree ffecom_f2c_ptr_to_ftnint_type_node;
/* Declare functions with prototypes. */
@@ -205,6 +210,8 @@ tree ffecom_arg_expr (ffebld expr, tree *length);
tree ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length);
tree ffecom_arg_ptr_to_expr (ffebld expr, tree *length);
tree ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook);
+tree ffecom_constantunion_with_type (ffebldConstantUnion *cu,
+ tree tree_type,ffebldConst ct);
tree ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
ffeinfoKindtype kt, tree tree_type);
tree ffecom_const_expr (ffebld expr);
@@ -265,6 +272,7 @@ tree ffecom_truth_value (tree expr);
tree ffecom_truth_value_invert (tree expr);
tree ffecom_type_expr (ffebld expr);
tree ffecom_which_entrypoint_decl (void);
+void ffe_parse_file (int);
/* Define macros. */
diff --git a/contrib/gcc/f/config-lang.in b/contrib/gcc/f/config-lang.in
index 168daad..92ba5cc 100644
--- a/contrib/gcc/f/config-lang.in
+++ b/contrib/gcc/f/config-lang.in
@@ -1,5 +1,5 @@
# Top level configure fragment for GNU FORTRAN.
-# Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
+# Copyright (C) 1995, 1996, 1997, 2000, 2001, 2002 Free Software Foundation, Inc.
#This file is part of GNU Fortran.
@@ -32,3 +32,5 @@ compilers="f771\$(exeext)"
stagestuff="g77\$(exeext) g77-cross\$(exeext) f771\$(exeext)"
target_libs=target-libf2c
+
+gtfiles="\$(srcdir)/f/com.c \$(srcdir)/f/com.h \$(srcdir)/f/ste.c \$(srcdir)/f/where.h \$(srcdir)/f/where.c \$(srcdir)/f/lex.c"
diff --git a/contrib/gcc/f/data.c b/contrib/gcc/f/data.c
index 3e1ae62..91b835d 100644
--- a/contrib/gcc/f/data.c
+++ b/contrib/gcc/f/data.c
@@ -1,5 +1,5 @@
/* data.c -- Implementation File (module.c template V1.0)
- Copyright (C) 1995, 1996, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 2002, 2003 Free Software Foundation, Inc.
Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -591,13 +591,29 @@ tail_recurse: /* :::::::::::::::::::: */
assert (ffeinfo_kindtype (ffebld_info (itervar))
== FFEINFO_kindtypeINTEGERDEFAULT);
ffedata_stack_->itervar = ffebld_symter (itervar);
-
+ if (ffeinfo_basictype (ffebld_info (start)) != FFEINFO_basictypeINTEGER)
+ {
+ ffebad_start (FFEBAD_DATA_EVAL);
+ ffest_ffebad_here_current_stmt (0);
+ ffebad_finish ();
+ ffedata_pop_ ();
+ ffedata_reported_error_ = TRUE;
+ return FALSE;
+ }
assert (ffeinfo_basictype (ffebld_info (start))
== FFEINFO_basictypeINTEGER);
assert (ffeinfo_kindtype (ffebld_info (start))
== FFEINFO_kindtypeINTEGERDEFAULT);
ffesymbol_set_value (ffedata_stack_->itervar, ffedata_eval_integer1_ (start));
-
+ if (ffeinfo_basictype (ffebld_info (end)) != FFEINFO_basictypeINTEGER)
+ {
+ ffebad_start (FFEBAD_DATA_EVAL);
+ ffest_ffebad_here_current_stmt (0);
+ ffebad_finish ();
+ ffedata_pop_ ();
+ ffedata_reported_error_ = TRUE;
+ return FALSE;
+ }
assert (ffeinfo_basictype (ffebld_info (end))
== FFEINFO_basictypeINTEGER);
assert (ffeinfo_kindtype (ffebld_info (end))
@@ -608,6 +624,15 @@ tail_recurse: /* :::::::::::::::::::: */
ffedata_stack_->increment = 1;
else
{
+ if (ffeinfo_basictype (ffebld_info (incr)) != FFEINFO_basictypeINTEGER)
+ {
+ ffebad_start (FFEBAD_DATA_EVAL);
+ ffest_ffebad_here_current_stmt (0);
+ ffebad_finish ();
+ ffedata_pop_ ();
+ ffedata_reported_error_ = TRUE;
+ return FALSE;
+ }
assert (ffeinfo_basictype (ffebld_info (incr))
== FFEINFO_basictypeINTEGER);
assert (ffeinfo_kindtype (ffebld_info (incr))
diff --git a/contrib/gcc/f/expr.c b/contrib/gcc/f/expr.c
index 1772727..4824be7 100644
--- a/contrib/gcc/f/expr.c
+++ b/contrib/gcc/f/expr.c
@@ -48,6 +48,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "str.h"
#include "target.h"
#include "where.h"
+#include "real.h"
/* Externals defined here. */
@@ -11501,6 +11502,24 @@ ffeexpr_reduced_ugly2log_ (ffebld reduced, ffeexprExpr_ l, ffeexprExpr_ op,
/* else Leave it alone. */
}
+ if (lbt == FFEINFO_basictypeLOGICAL)
+ {
+ ffebld_set_left (reduced, ffeexpr_convert (ffebld_left (reduced),
+ l->token, op->token, FFEINFO_basictypeINTEGER,
+ FFEINFO_kindtypeINTEGERDEFAULT, 0,
+ FFETARGET_charactersizeNONE,
+ FFEEXPR_contextLET));
+ }
+
+ if (rbt == FFEINFO_basictypeLOGICAL)
+ {
+ ffebld_set_right (reduced, ffeexpr_convert (ffebld_right (reduced),
+ r->token, op->token, FFEINFO_basictypeINTEGER,
+ FFEINFO_kindtypeINTEGERDEFAULT, 0,
+ FFETARGET_charactersizeNONE,
+ FFEEXPR_contextLET));
+ }
+
return reduced;
}
diff --git a/contrib/gcc/f/ffe.texi b/contrib/gcc/f/ffe.texi
index b6fbac9..9aa6a97 100644
--- a/contrib/gcc/f/ffe.texi
+++ b/contrib/gcc/f/ffe.texi
@@ -17,7 +17,7 @@ search for the string TBD.
If you want to help by working on one or more of these items,
email @email{gcc@@gcc.gnu.org}.
If you're planning to do more than just research issues and offer comments,
-see @uref{http://www.gnu.org/software/contribute.html} for steps you might
+see @uref{http://gcc.gnu.org/contribute.html} for steps you might
need to take first.
@menu
@@ -2028,7 +2028,7 @@ Initializes, usually a module. No type.
A generic integer of type @code{int}.
@item is
-A generic integer that contains a true (non-zero) or false (zero) value.
+A generic integer that contains a true (nonzero) or false (zero) value.
@item len
A generic integer that contains the length of something.
diff --git a/contrib/gcc/f/g77.texi b/contrib/gcc/f/g77.texi
index 82c5574..a7cd96b 100644
--- a/contrib/gcc/f/g77.texi
+++ b/contrib/gcc/f/g77.texi
@@ -2,8 +2,8 @@
@c %**start of header
@setfilename g77.info
-@set last-update 2002-04-29
-@set copyrights-g77 1995,1996,1997,1998,1999,2000,2001,2002
+@set last-update 2003-05-13
+@set copyrights-g77 1995,1996,1997,1998,1999,2000,2001,2002,2003
@include root.texi
@@ -24,33 +24,6 @@
@c and make sure the following does NOT begin with '@c':
@c @clear USING
-@c 6/27/96 FSF DO wants smallbook fmt for 1st bound edition. (from gcc.texi)
-@c @smallbook
-
-@c i also commented out the finalout command, so if there *are* any
-@c overfulls, you'll (hopefully) see the rectangle in the right hand
-@c margin. -- burley 1999-03-13 (from mew's comment in gcc.texi).
-@c @finalout
-
-@macro gcctabopt{body}
-@code{\body\}
-@end macro
-@macro gccoptlist{body}
-@smallexample
-\body\
-@end smallexample
-@end macro
-@c Makeinfo handles the above macro OK, TeX needs manual line breaks;
-@c they get lost at some point in handling the macro. But if @macro is
-@c used here rather than @alias, it produces double line breaks.
-@iftex
-@alias gol = *
-@end iftex
-@ifnottex
-@macro gol
-@end macro
-@end ifnottex
-
@ifset INTERNALS
@ifset USING
@settitle Using and Porting GNU Fortran
@@ -89,6 +62,29 @@
@c \global\normaloffset =0.75in
@c @end tex
+@copying
+Copyright @copyright{} @value{copyrights-g77} Free Software Foundation, Inc.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.2 or
+any later version published by the Free Software Foundation; with the
+Invariant Sections being ``GNU General Public License'' and ``Funding
+Free Software'', the Front-Cover
+texts being (a) (see below), and with the Back-Cover Texts being (b)
+(see below). A copy of the license is included in the section entitled
+``GNU Free Documentation License''.
+
+(a) The FSF's Front-Cover Text is:
+
+ A GNU Manual
+
+(b) The FSF's Back-Cover Text is:
+
+ You have freedom to copy and modify this GNU Manual, like GNU
+ software. Copies published by the Free Software Foundation raise
+ funds for GNU development.
+@end copying
+
@ifinfo
@dircategory Programming
@direntry
@@ -114,27 +110,7 @@ Published by the Free Software Foundation
59 Temple Place - Suite 330
Boston, MA 02111-1307 USA
-Copyright (C) @value{copyrights-g77} Free Software Foundation, Inc.
-
-
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.1 or
-any later version published by the Free Software Foundation; with the
-Invariant Sections being ``GNU General Public License'' and ``Funding
-Free Software'', the Front-Cover
-texts being (a) (see below), and with the Back-Cover Texts being (b)
-(see below). A copy of the license is included in the section entitled
-``GNU Free Documentation License''.
-
-(a) The FSF's Front-Cover Text is:
-
- A GNU Manual
-
-(b) The FSF's Back-Cover Text is:
-
- You have freedom to copy and modify this GNU Manual, like GNU
- software. Copies published by the Free Software Foundation raise
- funds for GNU development.
+@insertcopying
@end ifinfo
Contributed by James Craig Burley (@email{@value{email-burley}}).
@@ -142,7 +118,6 @@ Inspired by a first pass at translating @file{g77-0.5.16/f/DOC} that
was contributed to Craig by David Ronis (@email{ronis@@onsager.chem.mcgill.ca}).
@setchapternewpage odd
-@c @finalout
@titlepage
@ifset INTERNALS
@ifset USING
@@ -164,8 +139,6 @@ was contributed to Craig by David Ronis (@email{ronis@@onsager.chem.mcgill.ca}).
@center for version @value{which-g77}
@page
@vskip 0pt plus 1filll
-Copyright @copyright{} @value{copyrights-g77} Free Software Foundation, Inc.
-@sp 2
For the @value{which-g77} Version*
@sp 1
Published by the Free Software Foundation @*
@@ -175,24 +148,7 @@ Boston, MA 02111-1307, USA@*
@c Printed copies are available for $? each.@*
@c ISBN ???
@sp 1
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.1 or
-any later version published by the Free Software Foundation; with the
-Invariant Sections being ``GNU General Public License'' and ``Funding
-Free Software'', the Front-Cover
-texts being (a) (see below), and with the Back-Cover Texts being (b)
-(see below). A copy of the license is included in the section entitled
-``GNU Free Documentation License''.
-
-(a) The FSF's Front-Cover Text is:
-
- A GNU Manual
-
-(b) The FSF's Back-Cover Text is:
-
- You have freedom to copy and modify this GNU Manual, like GNU
- software. Copies published by the Free Software Foundation raise
- funds for GNU development.
+@insertcopying
@end titlepage
@summarycontents
@contents
@@ -275,7 +231,7 @@ most consistent with the @command{g77} product in that version.
* M: Diagnostics. Diagnostics produced by @command{g77}.
-* Index:: Index of concepts and symbol names.
+* Keyword Index:: Index of concepts and symbol names.
@end menu
@c yes, the "M: " @emph{is} intentional -- bad.def references it (CMPAMBIG)!
@@ -1045,7 +1001,7 @@ As such, GNU users rarely need consider just what kind of underlying
hardware (or, in many cases, operating system) they are using at any
particular time.
They can use and write software designed for a general-purpose,
-widely portable, heterogenous environment---the GNU environment.
+widely portable, heterogeneous environment---the GNU environment.
In line with this philosophy, GNU Fortran must evolve into a product
that is widely ported and portable not only in the sense that it can
@@ -5643,9 +5599,9 @@ The important thing about linking @command{g77}-compiled
code with C++ is that the prototypes for the @command{g77}
routines must specify C linkage to avoid name mangling.
So, use an @samp{extern "C"} declaration.
-@command{f2c}'s @option{-C++} option will take care
-of this when generating skeletons or prototype files as above, and also
-avoid clashes with C++ reserved words in addition to those in C@.
+@command{f2c}'s @option{-C++} option will not take care
+of this when generating skeletons or prototype files as above, however,
+it will avoid clashes with C++ reserved words in addition to those in C@.
@node Startup Code
@subsection Startup Code
@@ -6283,7 +6239,7 @@ single-dimensional array, so at least the dimensionality of the array
is preserved.
Debuggers that understand Fortran should have no trouble with
-non-zero low bounds, but for non-Fortran debuggers, especially
+nonzero low bounds, but for non-Fortran debuggers, especially
C debuggers, the above example might have a C equivalent of
@samp{a[4305]}.
This calculation is arrived at by eliminating the subtraction
@@ -7512,7 +7468,7 @@ set up this kind of aliasing.
(The FORTRAN 77 standard's prohibition of this sort of
overlap, generally referred to therein as ``storage
-assocation'', appears in Sections 15.9.3.6.
+association'', appears in Sections 15.9.3.6.
This prohibition allows implementations, such as @command{g77},
to, for example, implement the passing of procedures and
even values in @code{COMMON} via copy operations into local,
@@ -8547,7 +8503,7 @@ If a formatted @code{WRITE} produces an endless stream of spaces, check
that your program is linked against the correct version of the C library.
The configuration process takes care to account for your
system's normal @file{libc} not being ANSI-standard, which will
-otherwise cause this behaviour.
+otherwise cause this behavior.
If your system's default library is
ANSI-standard and you subsequently link against a non-ANSI one, there
might be problems such as this one.
@@ -9460,9 +9416,9 @@ general control over whether or not floating-point exceptions are trapped or
ignored.
(Ignoring them typically results in NaN values being
propagated in systems that conform to IEEE 754.)
-The behaviour is normally inherited from the system-dependent startup
+The behavior is normally inherited from the system-dependent startup
code, though some targets, such as the Alpha, have code generation
-options which change the behaviour.
+options which change the behavior.
Most systems provide some C-callable mechanism to change this; this can
be invoked at startup using @command{gcc}'s @code{constructor} attribute.
@@ -10464,30 +10420,11 @@ enable/disable/delete/hide intrinsics from the command line?
Your bug reports play an essential role in making GNU Fortran reliable.
When you encounter a problem, the first thing to do is to see if it is
-already known.
-@xref{Trouble}.
-If it isn't known, then you should report the problem.
-
-Reporting a bug might help you by bringing a solution to your problem, or
-it might not.
-(If it does not, look in the service directory; see
-@ref{Service}.)
-In any case, the principal function of a bug report is
-to help the entire community by making the next version of GNU Fortran work
-better.
-Bug reports are your contribution to the maintenance of GNU Fortran.
-
-Since the maintainers are very overloaded, we cannot respond to every
-bug report.
-However, if the bug has not been fixed, we are likely to
-send you a patch and ask you to tell us whether it works.
-
-In order for a bug report to serve its purpose, you must include the
-information that makes for fixing the bug.
+already known. @xref{Trouble}. If it isn't known, then you should
+report the problem.
@menu
* Criteria: Bug Criteria. Have you really found a bug?
-* Where: Bug Lists. Where to send your bug report.
* Reporting: Bug Reporting. How to report a bug effectively.
@end menu
@@ -10678,348 +10615,15 @@ It might mean the bug is in your code, and that @command{g77} simply
exposes it more readily than other compilers.
@end itemize
-@node Bug Lists
-@section Where to Report Bugs
-@cindex bug report mailing lists
-@kindex @value{email-bugs}
-Send bug reports for GNU Fortran to @email{@value{email-bugs}}.
-
-Often people think of posting bug reports to a newsgroup instead of
-mailing them.
-This sometimes appears to work, but it has one problem which can be
-crucial: a newsgroup posting does not contain a mail path back to the
-sender.
-Thus, if maintainers need more information, they might be unable
-to reach you. For this reason, you should always send bug reports by
-mail to the proper mailing list.
-
-As a last resort, send bug reports on paper to:
-
-@example
-GNU Compiler Bugs
-Free Software Foundation
-59 Temple Place - Suite 330
-Boston, MA 02111-1307, USA
-@end example
-
@node Bug Reporting
@section How to Report Bugs
@cindex compiler bugs, reporting
-The fundamental principle of reporting bugs usefully is this:
-@strong{report all the facts}.
-If you are not sure whether to state a
-fact or leave it out, state it!
-
-Often people omit facts because they think they know what causes the
-problem and they conclude that some details don't matter.
-Thus, you might
-assume that the name of the variable you use in an example does not matter.
-Well, probably it doesn't, but one cannot be sure.
-Perhaps the bug is a
-stray memory reference which happens to fetch from the location where that
-name is stored in memory; perhaps, if the name were different, the contents
-of that location would fool the compiler into doing the right thing despite
-the bug.
-Play it safe and give a specific, complete example.
-That is the
-easiest thing for you to do, and the most helpful.
-
-Keep in mind that the purpose of a bug report is to enable someone to
-fix the bug if it is not known.
-It isn't very important what happens if
-the bug is already known.
-Therefore, always write your bug reports on
-the assumption that the bug is not known.
-
-Sometimes people give a few sketchy facts and ask, ``Does this ring a
-bell?''
-This cannot help us fix a bug, so it is rarely helpful.
-We respond by asking for enough details to enable us to investigate.
-You might as well expedite matters by sending them to begin with.
-(Besides, there are enough bells ringing around here as it is.)
-
-Try to make your bug report self-contained.
-If we have to ask you for
-more information, it is best if you include all the previous information
-in your response, as well as the information that was missing.
-
-Please report each bug in a separate message.
-This makes it easier for
-us to track which bugs have been fixed and to forward your bugs reports
-to the appropriate maintainer.
-
-Do not compress and encode any part of your bug report using programs
-such as @file{uuencode}.
-If you do so it will slow down the processing
-of your bug.
-If you must submit multiple large files, use @file{shar},
-which allows us to read your message without having to run any
-decompression programs.
-
-(As a special exception for GNU Fortran bug-reporting, at least
-for now, if you are sending more than a few lines of code, if
-your program's source file format contains ``interesting'' things
-like trailing spaces or strange characters, or if you need to
-include binary data files, it is acceptable to put all the
-files together in a @command{tar} archive, and, whether you need to
-do that, it is acceptable to then compress the single file (@command{tar}
-archive or source file)
-using @command{gzip} and encode it via @command{uuencode}.
-Do not use any MIME stuff---the current maintainer can't decode this.
-Using @command{compress} instead of @command{gzip} is acceptable, assuming
-you have licensed the use of the patented algorithm in
-@command{compress} from Unisys.)
-
-To enable someone to investigate the bug, you should include all these
-things:
-
-@itemize @bullet
-@item
-The version of GNU Fortran.
-You can get this by running @command{g77} with the @option{-v} option.
-(Ignore any error messages that might be displayed
-when the linker is run.)
-
-Without this, we won't know whether there is any point in looking for
-the bug in the current version of GNU Fortran.
-
-@item
-@cindex preprocessor
-@cindex cpp program
-@cindex programs, cpp
-@pindex cpp
-A complete input file that will reproduce the bug.
-
-If your source file(s) require preprocessing
-(for example, their names have suffixes like
-@samp{.F}, @samp{.fpp}, @samp{.FPP}, and @samp{.r}),
-and the bug is in the compiler proper (@file{f771})
-or in a subsequent phase of processing,
-run your source file through the C preprocessor
-by doing @samp{g77 -E @var{sourcefile} > @var{newfile}}.
-Then, include the contents of @var{newfile} in the bug report.
-(When you do this, use the same preprocessor options---such as
-@option{-I}, @option{-D}, and @option{-U}---that you used in actual
-compilation.)
-
-A single statement is not enough of an example.
-In order to compile it,
-it must be embedded in a complete file of compiler input.
-The bug might depend on the details of how this is done.
-
-Without a real example one can compile,
-all anyone can do about your bug report is wish you luck.
-It would be futile to try to guess how to provoke the bug.
-For example, bugs in register allocation and reloading
-can depend on every little detail of the source and include files
-that trigger them.
-
-@item
-@cindex included files
-@cindex INCLUDE directive
-@cindex directive, INCLUDE
-@cindex #include directive
-@cindex directive, #include
-Note that you should include with your bug report any files
-included by the source file
-(via the @code{#include} or @code{INCLUDE} directive)
-that you send, and any files they include, and so on.
-
-It is not necessary to replace
-the @code{#include} and @code{INCLUDE} directives
-with the actual files in the version of the source file that
-you send, but it might make submitting the bug report easier
-in the end.
-However, be sure to @emph{reproduce} the bug using the @emph{exact}
-version of the source material you submit, to avoid wild-goose
-chases.
-
-@item
-The command arguments you gave GNU Fortran to compile that example
-and observe the bug. For example, did you use @option{-O}? To guarantee
-you won't omit something important, list all the options.
-
-If we were to try to guess the arguments, we would probably guess wrong
-and then we would not encounter the bug.
+Bugs should be reported to our bug database. Please refer to
+@uref{http://gcc.gnu.org/bugs.html} for up-to-date instructions how to
+submit bug reports. Copies of this file in HTML (@file{bugs.html}) and
+plain text (@file{BUGS}) are also part of GCC releases.
-@item
-The type of machine you are using, and the operating system name and
-version number.
-(Much of this information is printed by @samp{g77 -v}---if you
-include that, send along any additional info you have that you
-don't see clearly represented in that output.)
-
-@item
-The operands you gave to the @command{configure} command when you installed
-the compiler.
-
-@item
-A complete list of any modifications you have made to the compiler
-source. (We don't promise to investigate the bug unless it happens in
-an unmodified compiler. But if you've made modifications and don't tell
-us, then you are sending us on a wild-goose chase.)
-
-Be precise about these changes. A description in English is not
-enough---send a context diff for them.
-
-Adding files of your own (such as a machine description for a machine we
-don't support) is a modification of the compiler source.
-
-@item
-Details of any other deviations from the standard procedure for installing
-GNU Fortran.
-
-@item
-A description of what behavior you observe that you believe is
-incorrect. For example, ``The compiler gets a fatal signal,'' or,
-``The assembler instruction at line 208 in the output is incorrect.''
-
-Of course, if the bug is that the compiler gets a fatal signal, then one
-can't miss it. But if the bug is incorrect output, the maintainer might
-not notice unless it is glaringly wrong. None of us has time to study
-all the assembler code from a 50-line Fortran program just on the chance that
-one instruction might be wrong. We need @emph{you} to do this part!
-
-Even if the problem you experience is a fatal signal, you should still
-say so explicitly. Suppose something strange is going on, such as, your
-copy of the compiler is out of synch, or you have encountered a bug in
-the C library on your system. (This has happened!) Your copy might
-crash and the copy here would not. If you @i{said} to expect a crash,
-then when the compiler here fails to crash, we would know that the bug
-was not happening. If you don't say to expect a crash, then we would
-not know whether the bug was happening. We would not be able to draw
-any conclusion from our observations.
-
-If the problem is a diagnostic when building GNU Fortran with some other
-compiler, say whether it is a warning or an error.
-
-Often the observed symptom is incorrect output when your program is run.
-Sad to say, this is not enough information unless the program is short
-and simple. None of us has time to study a large program to figure out
-how it would work if compiled correctly, much less which line of it was
-compiled wrong. So you will have to do that. Tell us which source line
-it is, and what incorrect result happens when that line is executed. A
-person who understands the program can find this as easily as finding a
-bug in the program itself.
-
-@item
-If you send examples of assembler code output from GNU Fortran,
-please use @option{-g} when you make them. The debugging information
-includes source line numbers which are essential for correlating the
-output with the input.
-
-@item
-If you wish to mention something in the GNU Fortran source, refer to it by
-context, not by line number.
-
-The line numbers in the development sources don't match those in your
-sources. Your line numbers would convey no convenient information to the
-maintainers.
-
-@item
-Additional information from a debugger might enable someone to find a
-problem on a machine which he does not have available. However, you
-need to think when you collect this information if you want it to have
-any chance of being useful.
-
-@cindex backtrace for bug reports
-For example, many people send just a backtrace, but that is never
-useful by itself. A simple backtrace with arguments conveys little
-about GNU Fortran because the compiler is largely data-driven; the same
-functions are called over and over for different RTL insns, doing
-different things depending on the details of the insn.
-
-Most of the arguments listed in the backtrace are useless because they
-are pointers to RTL list structure. The numeric values of the
-pointers, which the debugger prints in the backtrace, have no
-significance whatever; all that matters is the contents of the objects
-they point to (and most of the contents are other such pointers).
-
-In addition, most compiler passes consist of one or more loops that
-scan the RTL insn sequence. The most vital piece of information about
-such a loop---which insn it has reached---is usually in a local variable,
-not in an argument.
-
-@findex debug_rtx
-What you need to provide in addition to a backtrace are the values of
-the local variables for several stack frames up. When a local
-variable or an argument is an RTX, first print its value and then use
-the GDB command @command{pr} to print the RTL expression that it points
-to. (If GDB doesn't run on your machine, use your debugger to call
-the function @code{debug_rtx} with the RTX as an argument.) In
-general, whenever a variable is a pointer, its value is no use
-without the data it points to.
-@end itemize
-
-Here are some things that are not necessary:
-
-@itemize @bullet
-@item
-A description of the envelope of the bug.
-
-Often people who encounter a bug spend a lot of time investigating
-which changes to the input file will make the bug go away and which
-changes will not affect it.
-
-This is often time consuming and not very useful, because the way we
-will find the bug is by running a single example under the debugger with
-breakpoints, not by pure deduction from a series of examples. You might
-as well save your time for something else.
-
-Of course, if you can find a simpler example to report @emph{instead} of
-the original one, that is a convenience. Errors in the output will be
-easier to spot, running under the debugger will take less time, etc.
-Most GNU Fortran bugs involve just one function, so the most straightforward
-way to simplify an example is to delete all the function definitions
-except the one where the bug occurs. Those earlier in the file may be
-replaced by external declarations if the crucial function depends on
-them. (Exception: inline functions might affect compilation of functions
-defined later in the file.)
-
-However, simplification is not vital; if you don't want to do this,
-report the bug anyway and send the entire test case you used.
-
-@item
-In particular, some people insert conditionals @samp{#ifdef BUG} around
-a statement which, if removed, makes the bug not happen. These are just
-clutter; we won't pay any attention to them anyway. Besides, you should
-send us preprocessor output, and that can't have conditionals.
-
-@item
-A patch for the bug.
-
-A patch for the bug is useful if it is a good one. But don't omit the
-necessary information, such as the test case, on the assumption that a
-patch is all we need. We might see problems with your patch and decide
-to fix the problem another way, or we might not understand it at all.
-
-Sometimes with a program as complicated as GNU Fortran it is very hard to
-construct an example that will make the program follow a certain path
-through the code. If you don't send the example, we won't be able to
-construct one, so we won't be able to verify that the bug is fixed.
-
-And if we can't understand what bug you are trying to fix, or why your
-patch should be an improvement, we won't install it. A test case will
-help us to understand.
-
-See @uref{http://gcc.gnu.org/contribute.html}
-for guidelines on how to make it easy for us to
-understand and install your patches.
-
-@item
-A guess about what the bug is or what it depends on.
-
-Such guesses are usually wrong. Even the maintainer can't guess right
-about such things without first using the debugger to find the facts.
-
-@item
-A core dump file.
-
-We have no way of examining a core dump for your type of machine
-unless we have an identical system---and if we do have one,
-we should be able to reproduce the crash ourselves.
-@end itemize
@node Service
@chapter How To Get Help with GNU Fortran
@@ -12262,8 +11866,8 @@ that is not Year-2000 (Y2K) compliant.
@end ifset
-@node Index
-@unnumbered Index
+@node Keyword Index
+@unnumbered Keyword Index
@printindex cp
@bye
diff --git a/contrib/gcc/f/g77spec.c b/contrib/gcc/f/g77spec.c
index 2e094d9..9206ef7 100644
--- a/contrib/gcc/f/g77spec.c
+++ b/contrib/gcc/f/g77spec.c
@@ -1,5 +1,6 @@
/* Specific flags and argument handling of the Fortran front-end.
- Copyright (C) 1997, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003
+ Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -47,7 +48,6 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "gcc.h"
-#include <f/version.h>
#ifndef MATH_LIBRARY
#define MATH_LIBRARY "-lm"
@@ -99,36 +99,14 @@ static void append_arg PARAMS ((const char *));
static int g77_newargc;
static const char **g77_newargv;
-/* --- This comes from gcc.c (2.8.1) verbatim: */
-
-/* This defines which switch letters take arguments. */
-
-#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
- ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
- || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
- || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
- || (CHAR) == 'L' || (CHAR) == 'A')
-
#ifndef SWITCH_TAKES_ARG
#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
#endif
-/* This defines which multi-letter switches take arguments. */
-
-#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR) \
- (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \
- || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \
- || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
- || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
- || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
- || !strcmp (STR, "isystem") || !strcmp (STR, "specs"))
-
#ifndef WORD_SWITCH_TAKES_ARG
#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
#endif
-/* --- End of verbatim. */
-
/* Assumes text[0] == '-'. Returns number of argv items that belong to
(and follow) this one, an option id for options important to the
caller, and a pointer to the first char of the arg, if embedded (else
@@ -374,7 +352,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
case OPTION_version:
printf ("\
-GNU Fortran (GCC %s) %s\n\
+GNU Fortran (GCC) %s\n\
Copyright (C) 2002 Free Software Foundation, Inc.\n\
\n\
GNU Fortran comes with NO WARRANTY, to the extent permitted by law.\n\
@@ -382,7 +360,7 @@ You may redistribute copies of GNU Fortran\n\
under the terms of the GNU General Public License.\n\
For more information about these matters, see the file named COPYING\n\
or type the command `info -f g77 Copying'.\n\
-", version_string, ffe_version_string);
+", version_string);
exit (0);
break;
@@ -563,3 +541,9 @@ int lang_specific_pre_link () /* Not used for F77. */
/* Number of extra output files that lang_specific_pre_link may generate. */
int lang_specific_extra_outfiles = 0; /* Not used for F77. */
+
+/* Table of language-specific spec functions. */
+const struct spec_function lang_specific_spec_functions[] =
+{
+ { 0, 0 }
+};
diff --git a/contrib/gcc/f/intdoc.in b/contrib/gcc/f/intdoc.in
index f702fa1..55d426a 100644
--- a/contrib/gcc/f/intdoc.in
+++ b/contrib/gcc/f/intdoc.in
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1999, 2003 Free Software Foundation, Inc.
* This is part of the G77 manual.
* For copying conditions, see the file g77.texi. */
@@ -646,7 +646,7 @@ magnitude truncated and its sign preserved, converted
to type @code{INTEGER(KIND=6)}.
If @var{@1@} is type @code{COMPLEX}, its real part
-is truncated and converted, and its imaginary part is disgregarded.
+is truncated and converted, and its imaginary part is disregarded.
@xref{Int Intrinsic}.
@@ -661,7 +661,7 @@ magnitude truncated and its sign preserved, converted
to type @code{INTEGER(KIND=6)}.
If @var{@1@} is type @code{COMPLEX}, its real part
-is truncated and converted, and its imaginary part is disgregarded.
+is truncated and converted, and its imaginary part is disregarded.
@xref{Int Intrinsic}.
@@ -676,7 +676,7 @@ magnitude truncated and its sign preserved, converted
to type @code{INTEGER(KIND=2)}.
If @var{@1@} is type @code{COMPLEX}, its real part
-is truncated and converted, and its imaginary part is disgregarded.
+is truncated and converted, and its imaginary part is disregarded.
@xref{Int Intrinsic}.
@@ -1288,9 +1288,9 @@ zero if not, and negative if the information isn't available.
")
DEFDOC (IDATE_unix, "Get local time info.", "\
-Fills @var{@1@} with the numerical values at the current local time
-of day, month (in the range 1--12), and year in elements 1, 2, and 3,
-respectively.
+Fills @var{@1@} with the numerical values at the current local time.
+The day (in the range 1--31), month (in the range 1--12),
+and year appear in elements 1, 2, and 3 of @var{@1@}, respectively.
The year has four significant digits.
@cindex Y10K compliance
@@ -1308,19 +1308,20 @@ as of the Year 10000.
DEFDOC (IDATE_vxt, "Get local time info (VAX/VMS).", "\
Returns the numerical values of the current local time.
The month (in the range 1--12) is returned in @var{@1@},
-the day (in the range 1--7) in @var{@2@},
+the day (in the range 1--31) in @var{@2@},
and the year in @var{@3@} (in the range 0--99).
@cindex Y2K compliance
@cindex Year 2000 compliance
@cindex wraparound, Y2K
@cindex limits, Y2K
-This intrinsic is not recommended, due to the year 2000 approaching.
-Therefore, programs making use of this intrinsic
-might not be Year 2000 (Y2K) compliant.
+This intrinsic is not recommended, due to the fact that
+its return value for year wraps around century boundaries
+(change from a larger value to a smaller one).
+Therefore, programs making use of this intrinsic, for
+instance, might not be Year 2000 (Y2K) compliant.
For example, the date might appear,
to such programs, to wrap around
-(change from a larger value to a smaller one)
as of the Year 2000.
@xref{IDate Intrinsic (UNIX)}, for information on obtaining more digits
@@ -1584,7 +1585,7 @@ almost certainly want to use something better.
")
DEFDOC (SRAND, "Random seed.", "\
-Reinitialises the generator with the seed in @var{@1@}.
+Reinitializes the generator with the seed in @var{@1@}.
@xref{IRand Intrinsic}.
@xref{Rand Intrinsic}.
")
@@ -1617,7 +1618,7 @@ Existence
DEFDOC (CHDIR_subr, "Change directory.", "\
Sets the current working directory to be @var{@1@}.
If the @var{@2@} argument is supplied, it contains 0
-on success or a non-zero error code otherwise upon return.
+on success or a nonzero error code otherwise upon return.
See @code{chdir(3)}.
@emph{Caution:} Using this routine during I/O to a unit connected with a
@@ -1631,7 +1632,7 @@ only a function, not as a subroutine, or do not support the
DEFDOC (CHDIR_func, "Change directory.", "\
Sets the current working directory to be @var{@1@}.
-Returns 0 on success or a non-zero error code.
+Returns 0 on success or a nonzero error code.
See @code{chdir(3)}.
@emph{Caution:} Using this routine during I/O to a unit connected with a
@@ -1652,7 +1653,7 @@ trailing blanks in @var{@1@} are ignored.
Currently, @var{@1@} must not contain the single quote
character.
-Returns 0 on success or a non-zero error code otherwise.
+Returns 0 on success or a nonzero error code otherwise.
Note that this currently works
by actually invoking @code{/bin/chmod} (or the @code{chmod} found when
@@ -1674,7 +1675,7 @@ Currently, @var{@1@} must not contain the single quote
character.
If the @var{@3@} argument is supplied, it contains
-0 on success or a non-zero error code upon return.
+0 on success or a nonzero error code upon return.
Note that this currently works
by actually invoking @code{/bin/chmod} (or the @code{chmod} found when
@@ -1689,7 +1690,7 @@ only a function, not as a subroutine, or do not support the
DEFDOC (GETCWD_func, "Get current working directory.", "\
Places the current working directory in @var{@1@}.
Returns 0 on
-success, otherwise a non-zero error code
+success, otherwise a nonzero error code
(@code{ENOSYS} if the system does not provide @code{getcwd(3)}
or @code{getwd(3)}).
")
@@ -1697,7 +1698,7 @@ or @code{getwd(3)}).
DEFDOC (GETCWD_subr, "Get current working directory.", "\
Places the current working directory in @var{@1@}.
If the @var{@2@} argument is supplied, it contains 0
-success or a non-zero error code upon return
+success or a nonzero error code upon return
(@code{ENOSYS} if the system does not provide @code{getcwd(3)}
or @code{getwd(3)}).
@@ -1758,7 +1759,7 @@ Number of blocks allocated (-1 if not available)
Not all these elements are relevant on all systems.
If an element is not relevant, it is returned as 0.
-Returns 0 on success or a non-zero error code.
+Returns 0 on success or a nonzero error code.
")
DEFDOC (FSTAT_subr, "Get file information.", "\
@@ -1814,7 +1815,7 @@ Not all these elements are relevant on all systems.
If an element is not relevant, it is returned as 0.
If the @var{@3@} argument is supplied, it contains
-0 on success or a non-zero error code upon return.
+0 on success or a nonzero error code upon return.
Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine, or do not support the
@@ -1878,7 +1879,7 @@ Number of blocks allocated (-1 if not available)
Not all these elements are relevant on all systems.
If an element is not relevant, it is returned as 0.
-Returns 0 on success or a non-zero error code
+Returns 0 on success or a nonzero error code
(@code{ENOSYS} if the system does not provide @code{lstat(2)}).
")
@@ -1940,7 +1941,7 @@ Not all these elements are relevant on all systems.
If an element is not relevant, it is returned as 0.
If the @var{@3@} argument is supplied, it contains
-0 on success or a non-zero error code upon return
+0 on success or a nonzero error code upon return
(@code{ENOSYS} if the system does not provide @code{lstat(2)}).
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -2002,7 +2003,7 @@ Number of blocks allocated (-1 if not available)
Not all these elements are relevant on all systems.
If an element is not relevant, it is returned as 0.
-Returns 0 on success or a non-zero error code.
+Returns 0 on success or a nonzero error code.
")
DEFDOC (STAT_subr, "Get file information.", "\
@@ -2060,7 +2061,7 @@ Not all these elements are relevant on all systems.
If an element is not relevant, it is returned as 0.
If the @var{@3@} argument is supplied, it contains
-0 on success or a non-zero error code upon return.
+0 on success or a nonzero error code upon return.
Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine, or do not support the
@@ -2073,7 +2074,7 @@ A null character (@samp{CHAR(0)}) marks the end of
the names in @var{@1@} and @var{@2@}---otherwise,
trailing blanks in @var{@1@} and @var{@2@} are ignored.
If the @var{@3@} argument is supplied, it contains
-0 on success or a non-zero error code upon return.
+0 on success or a nonzero error code upon return.
See @code{link(2)}.
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -2086,7 +2087,7 @@ Makes a (hard) link from file @var{@1@} to @var{@2@}.
A null character (@samp{CHAR(0)}) marks the end of
the names in @var{@1@} and @var{@2@}---otherwise,
trailing blanks in @var{@1@} and @var{@2@} are ignored.
-Returns 0 on success or a non-zero error code.
+Returns 0 on success or a nonzero error code.
See @code{link(2)}.
Due to the side effects performed by this intrinsic, the function
@@ -2099,7 +2100,7 @@ A null character (@samp{CHAR(0)}) marks the end of
the names in @var{@1@} and @var{@2@}---otherwise,
trailing blanks in @var{@1@} and @var{@2@} are ignored.
If the @var{@3@} argument is supplied, it contains
-0 on success or a non-zero error code upon return
+0 on success or a nonzero error code upon return
(@code{ENOSYS} if the system does not provide @code{symlink(2)}).
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -2112,7 +2113,7 @@ Makes a symbolic link from file @var{@1@} to @var{@2@}.
A null character (@samp{CHAR(0)}) marks the end of
the names in @var{@1@} and @var{@2@}---otherwise,
trailing blanks in @var{@1@} and @var{@2@} are ignored.
-Returns 0 on success or a non-zero error code
+Returns 0 on success or a nonzero error code
(@code{ENOSYS} if the system does not provide @code{symlink(2)}).
Due to the side effects performed by this intrinsic, the function
@@ -2126,7 +2127,7 @@ the names in @var{@1@} and @var{@2@}---otherwise,
trailing blanks in @var{@1@} and @var{@2@} are ignored.
See @code{rename(2)}.
If the @var{@3@} argument is supplied, it contains
-0 on success or a non-zero error code upon return.
+0 on success or a nonzero error code upon return.
Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine, or do not support the
@@ -2139,7 +2140,7 @@ A null character (@samp{CHAR(0)}) marks the end of
the names in @var{@1@} and @var{@2@}---otherwise,
trailing blanks in @var{@1@} and @var{@2@} are ignored.
See @code{rename(2)}.
-Returns 0 on success or a non-zero error code.
+Returns 0 on success or a nonzero error code.
Due to the side effects performed by this intrinsic, the function
form is not recommended.
@@ -2168,7 +2169,7 @@ A null character (@samp{CHAR(0)}) marks the end of
the name in @var{@1@}---otherwise,
trailing blanks in @var{@1@} are ignored.
If the @var{@2@} argument is supplied, it contains
-0 on success or a non-zero error code upon return.
+0 on success or a nonzero error code upon return.
See @code{unlink(2)}.
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -2181,7 +2182,7 @@ Unlink the file @var{@1@}.
A null character (@samp{CHAR(0)}) marks the end of
the name in @var{@1@}---otherwise,
trailing blanks in @var{@1@} are ignored.
-Returns 0 on success or a non-zero error code.
+Returns 0 on success or a nonzero error code.
See @code{unlink(2)}.
Due to the side effects performed by this intrinsic, the function
@@ -2238,7 +2239,7 @@ in @var{@1@}.
DEFDOC (HOSTNM_func, "Get host name.", "\
Fills @var{@1@} with the system's host name returned by
-@code{gethostname(2)}, returning 0 on success or a non-zero error code
+@code{gethostname(2)}, returning 0 on success or a nonzero error code
(@code{ENOSYS} if the system does not provide @code{gethostname(2)}).
On some systems (specifically SCO) it might be necessary to link the
@@ -2251,7 +2252,7 @@ DEFDOC (HOSTNM_subr, "Get host name.", "\
Fills @var{@1@} with the system's host name returned by
@code{gethostname(2)}.
If the @var{@2@} argument is supplied, it contains
-0 on success or a non-zero error code upon return
+0 on success or a nonzero error code upon return
(@code{ENOSYS} if the system does not provide @code{gethostname(2)}).
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -2513,7 +2514,7 @@ allowing you to take appropriate action.
DEFDOC (KILL_func, "Signal a process.", "\
Sends the signal specified by @var{@2@} to the process @var{@1@}.
-Returns 0 on success or a non-zero error code.
+Returns 0 on success or a nonzero error code.
See @code{kill(2)}.
Due to the side effects performed by this intrinsic, the function
@@ -2523,7 +2524,7 @@ form is not recommended.
DEFDOC (KILL_subr, "Signal a process.", "\
Sends the signal specified by @var{@2@} to the process @var{@1@}.
If the @var{@3@} argument is supplied, it contains
-0 on success or a non-zero error code upon return.
+0 on success or a nonzero error code upon return.
See @code{kill(2)}.
Some non-GNU implementations of Fortran provide this intrinsic as
diff --git a/contrib/gcc/f/intdoc.texi b/contrib/gcc/f/intdoc.texi
index e829b35..7de4257 100644
--- a/contrib/gcc/f/intdoc.texi
+++ b/contrib/gcc/f/intdoc.texi
@@ -2226,7 +2226,7 @@ Description:
Sets the current working directory to be @var{Dir}.
If the @var{Status} argument is supplied, it contains 0
-on success or a non-zero error code otherwise upon return.
+on success or a nonzero error code otherwise upon return.
See @code{chdir(3)}.
@emph{Caution:} Using this routine during I/O to a unit connected with a
@@ -2265,7 +2265,7 @@ Intrinsic groups: @code{badu77}.
Description:
Sets the current working directory to be @var{Dir}.
-Returns 0 on success or a non-zero error code.
+Returns 0 on success or a nonzero error code.
See @code{chdir(3)}.
@emph{Caution:} Using this routine during I/O to a unit connected with a
@@ -2315,7 +2315,7 @@ Currently, @var{Name} must not contain the single quote
character.
If the @var{Status} argument is supplied, it contains
-0 on success or a non-zero error code upon return.
+0 on success or a nonzero error code upon return.
Note that this currently works
by actually invoking @code{/bin/chmod} (or the @code{chmod} found when
@@ -2365,7 +2365,7 @@ trailing blanks in @var{Name} are ignored.
Currently, @var{Name} must not contain the single quote
character.
-Returns 0 on success or a non-zero error code otherwise.
+Returns 0 on success or a nonzero error code otherwise.
Note that this currently works
by actually invoking @code{/bin/chmod} (or the @code{chmod} found when
@@ -5067,7 +5067,7 @@ Not all these elements are relevant on all systems.
If an element is not relevant, it is returned as 0.
If the @var{Status} argument is supplied, it contains
-0 on success or a non-zero error code upon return.
+0 on success or a nonzero error code upon return.
Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine, or do not support the
@@ -5152,7 +5152,7 @@ Number of blocks allocated (-1 if not available)
Not all these elements are relevant on all systems.
If an element is not relevant, it is returned as 0.
-Returns 0 on success or a non-zero error code.
+Returns 0 on success or a nonzero error code.
For information on other intrinsics with the same name:
@xref{FStat Intrinsic (subroutine)}.
@@ -5292,7 +5292,7 @@ Description:
Places the current working directory in @var{Name}.
If the @var{Status} argument is supplied, it contains 0
-success or a non-zero error code upon return
+success or a nonzero error code upon return
(@code{ENOSYS} if the system does not provide @code{getcwd(3)}
or @code{getwd(3)}).
@@ -5327,7 +5327,7 @@ Description:
Places the current working directory in @var{Name}.
Returns 0 on
-success, otherwise a non-zero error code
+success, otherwise a nonzero error code
(@code{ENOSYS} if the system does not provide @code{getcwd(3)}
or @code{getwd(3)}).
@@ -5537,7 +5537,7 @@ Description:
Fills @var{Name} with the system's host name returned by
@code{gethostname(2)}.
If the @var{Status} argument is supplied, it contains
-0 on success or a non-zero error code upon return
+0 on success or a nonzero error code upon return
(@code{ENOSYS} if the system does not provide @code{gethostname(2)}).
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -5575,7 +5575,7 @@ Intrinsic groups: @code{unix}.
Description:
Fills @var{Name} with the system's host name returned by
-@code{gethostname(2)}, returning 0 on success or a non-zero error code
+@code{gethostname(2)}, returning 0 on success or a nonzero error code
(@code{ENOSYS} if the system does not provide @code{gethostname(2)}).
On some systems (specifically SCO) it might be necessary to link the
@@ -5893,9 +5893,9 @@ Intrinsic groups: @code{unix}.
@noindent
Description:
-Fills @var{TArray} with the numerical values at the current local time
-of day, month (in the range 1--12), and year in elements 1, 2, and 3,
-respectively.
+Fills @var{TArray} with the numerical values at the current local time.
+The day (in the range 1--31), month (in the range 1--12),
+and year appear in elements 1, 2, and 3 of @var{TArray}, respectively.
The year has four significant digits.
@cindex Y10K compliance
@@ -5941,19 +5941,20 @@ Description:
Returns the numerical values of the current local time.
The month (in the range 1--12) is returned in @var{M},
-the day (in the range 1--7) in @var{D},
+the day (in the range 1--31) in @var{D},
and the year in @var{Y} (in the range 0--99).
@cindex Y2K compliance
@cindex Year 2000 compliance
@cindex wraparound, Y2K
@cindex limits, Y2K
-This intrinsic is not recommended, due to the year 2000 approaching.
-Therefore, programs making use of this intrinsic
-might not be Year 2000 (Y2K) compliant.
+This intrinsic is not recommended, due to the fact that
+its return value for year wraps around century boundaries
+(change from a larger value to a smaller one).
+Therefore, programs making use of this intrinsic, for
+instance, might not be Year 2000 (Y2K) compliant.
For example, the date might appear,
to such programs, to wrap around
-(change from a larger value to a smaller one)
as of the Year 2000.
@xref{IDate Intrinsic (UNIX)}, for information on obtaining more digits
@@ -6543,7 +6544,7 @@ magnitude truncated and its sign preserved, converted
to type @code{INTEGER(KIND=6)}.
If @var{A} is type @code{COMPLEX}, its real part
-is truncated and converted, and its imaginary part is disgregarded.
+is truncated and converted, and its imaginary part is disregarded.
@xref{Int Intrinsic}.
@@ -6578,7 +6579,7 @@ magnitude truncated and its sign preserved, converted
to type @code{INTEGER(KIND=2)}.
If @var{A} is type @code{COMPLEX}, its real part
-is truncated and converted, and its imaginary part is disgregarded.
+is truncated and converted, and its imaginary part is disregarded.
@xref{Int Intrinsic}.
@@ -7107,7 +7108,7 @@ Description:
Sends the signal specified by @var{Signal} to the process @var{Pid}.
If the @var{Status} argument is supplied, it contains
-0 on success or a non-zero error code upon return.
+0 on success or a nonzero error code upon return.
See @code{kill(2)}.
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -7145,7 +7146,7 @@ Intrinsic groups: @code{badu77}.
Description:
Sends the signal specified by @var{Signal} to the process @var{Pid}.
-Returns 0 on success or a non-zero error code.
+Returns 0 on success or a nonzero error code.
See @code{kill(2)}.
Due to the side effects performed by this intrinsic, the function
@@ -7377,7 +7378,7 @@ A null character (@samp{CHAR(0)}) marks the end of
the names in @var{Path1} and @var{Path2}---otherwise,
trailing blanks in @var{Path1} and @var{Path2} are ignored.
If the @var{Status} argument is supplied, it contains
-0 on success or a non-zero error code upon return.
+0 on success or a nonzero error code upon return.
See @code{link(2)}.
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -7418,7 +7419,7 @@ Makes a (hard) link from file @var{Path1} to @var{Path2}.
A null character (@samp{CHAR(0)}) marks the end of
the names in @var{Path1} and @var{Path2}---otherwise,
trailing blanks in @var{Path1} and @var{Path2} are ignored.
-Returns 0 on success or a non-zero error code.
+Returns 0 on success or a nonzero error code.
See @code{link(2)}.
Due to the side effects performed by this intrinsic, the function
@@ -7802,7 +7803,7 @@ Not all these elements are relevant on all systems.
If an element is not relevant, it is returned as 0.
If the @var{Status} argument is supplied, it contains
-0 on success or a non-zero error code upon return
+0 on success or a nonzero error code upon return
(@code{ENOSYS} if the system does not provide @code{lstat(2)}).
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -7893,7 +7894,7 @@ Number of blocks allocated (-1 if not available)
Not all these elements are relevant on all systems.
If an element is not relevant, it is returned as 0.
-Returns 0 on success or a non-zero error code
+Returns 0 on success or a nonzero error code
(@code{ENOSYS} if the system does not provide @code{lstat(2)}).
For information on other intrinsics with the same name:
@@ -9085,7 +9086,7 @@ the names in @var{Path1} and @var{Path2}---otherwise,
trailing blanks in @var{Path1} and @var{Path2} are ignored.
See @code{rename(2)}.
If the @var{Status} argument is supplied, it contains
-0 on success or a non-zero error code upon return.
+0 on success or a nonzero error code upon return.
Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine, or do not support the
@@ -9126,7 +9127,7 @@ A null character (@samp{CHAR(0)}) marks the end of
the names in @var{Path1} and @var{Path2}---otherwise,
trailing blanks in @var{Path1} and @var{Path2} are ignored.
See @code{rename(2)}.
-Returns 0 on success or a non-zero error code.
+Returns 0 on success or a nonzero error code.
Due to the side effects performed by this intrinsic, the function
form is not recommended.
@@ -9418,7 +9419,7 @@ magnitude truncated and its sign preserved, converted
to type @code{INTEGER(KIND=6)}.
If @var{A} is type @code{COMPLEX}, its real part
-is truncated and converted, and its imaginary part is disgregarded.
+is truncated and converted, and its imaginary part is disregarded.
@xref{Int Intrinsic}.
@@ -9848,7 +9849,7 @@ Intrinsic groups: @code{unix}.
@noindent
Description:
-Reinitialises the generator with the seed in @var{Seed}.
+Reinitializes the generator with the seed in @var{Seed}.
@xref{IRand Intrinsic}.
@xref{Rand Intrinsic}.
@@ -9931,7 +9932,7 @@ Not all these elements are relevant on all systems.
If an element is not relevant, it is returned as 0.
If the @var{Status} argument is supplied, it contains
-0 on success or a non-zero error code upon return.
+0 on success or a nonzero error code upon return.
Some non-GNU implementations of Fortran provide this intrinsic as
only a function, not as a subroutine, or do not support the
@@ -10018,7 +10019,7 @@ Number of blocks allocated (-1 if not available)
Not all these elements are relevant on all systems.
If an element is not relevant, it is returned as 0.
-Returns 0 on success or a non-zero error code.
+Returns 0 on success or a nonzero error code.
For information on other intrinsics with the same name:
@xref{Stat Intrinsic (subroutine)}.
@@ -10067,7 +10068,7 @@ A null character (@samp{CHAR(0)}) marks the end of
the names in @var{Path1} and @var{Path2}---otherwise,
trailing blanks in @var{Path1} and @var{Path2} are ignored.
If the @var{Status} argument is supplied, it contains
-0 on success or a non-zero error code upon return
+0 on success or a nonzero error code upon return
(@code{ENOSYS} if the system does not provide @code{symlink(2)}).
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -10108,7 +10109,7 @@ Makes a symbolic link from file @var{Path1} to @var{Path2}.
A null character (@samp{CHAR(0)}) marks the end of
the names in @var{Path1} and @var{Path2}---otherwise,
trailing blanks in @var{Path1} and @var{Path2} are ignored.
-Returns 0 on success or a non-zero error code
+Returns 0 on success or a nonzero error code
(@code{ENOSYS} if the system does not provide @code{symlink(2)}).
Due to the side effects performed by this intrinsic, the function
@@ -10657,7 +10658,7 @@ A null character (@samp{CHAR(0)}) marks the end of
the name in @var{File}---otherwise,
trailing blanks in @var{File} are ignored.
If the @var{Status} argument is supplied, it contains
-0 on success or a non-zero error code upon return.
+0 on success or a nonzero error code upon return.
See @code{unlink(2)}.
Some non-GNU implementations of Fortran provide this intrinsic as
@@ -10695,7 +10696,7 @@ Unlink the file @var{File}.
A null character (@samp{CHAR(0)}) marks the end of
the name in @var{File}---otherwise,
trailing blanks in @var{File} are ignored.
-Returns 0 on success or a non-zero error code.
+Returns 0 on success or a nonzero error code.
See @code{unlink(2)}.
Due to the side effects performed by this intrinsic, the function
diff --git a/contrib/gcc/f/invoke.texi b/contrib/gcc/f/invoke.texi
index 5474eec..50c7ca4 100644
--- a/contrib/gcc/f/invoke.texi
+++ b/contrib/gcc/f/invoke.texi
@@ -9,7 +9,7 @@ Copyright @copyright{} 1996, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.1 or
+under the terms of the GNU Free Documentation License, Version 1.2 or
any later version published by the Free Software Foundation; with the
Invariant Sections being ``GNU General Public License'' and ``Funding
Free Software'', the Front-Cover texts being (a) (see below), and with
@@ -182,7 +182,7 @@ by type. Explanations are in the following sections.
-malign-double @gol
-ffloat-store -fforce-mem -fforce-addr -fno-inline @gol
-ffast-math -fstrength-reduce -frerun-cse-after-loop @gol
--funsafe-math-optimizations -fno-trapping-math @gol
+-funsafe-math-optimizations -ffinite-math-only -fno-trapping-math @gol
-fexpensive-optimizations -fdelayed-branch @gol
-fschedule-insns -fschedule-insn2 -fcaller-saves @gol
-funroll-loops -funroll-all-loops @gol
@@ -389,7 +389,7 @@ This option is supplied automatically when @option{-v} or @option{--verbose}
is specified as a command-line option for @command{g77} or @command{gcc}
and when the resulting commands compile Fortran source files.
-In GCC 3.1, this is changed back to the behaviour @command{gcc} displays
+In GCC 3.1, this is changed back to the behavior @command{gcc} displays
for @samp{.c} files.
@cindex -fset-g77-defaults option
@@ -1356,6 +1356,12 @@ Some of these have no effect when compiling programs written in Fortran:
@cindex -Wswitch option
@cindex options, -Wswitch
@item -Wswitch
+@cindex -Wswitch-default option
+@cindex options, -Wswitch-default
+@item -Wswitch-default
+@cindex -Wswitch-enum option
+@cindex options, -Wswitch-enum
+@item -Wswitch-enum
@cindex -Wtraditional option
@cindex options, -Wtraditional
@item -Wtraditional
@@ -1536,8 +1542,8 @@ Note that if you are not optimizing, no functions can be expanded inline.
@cindex conformance, IEEE 754
Might allow some programs designed to not be too dependent
on IEEE behavior for floating-point to run faster, or die trying.
-Sets @option{-funsafe-math-optimizations}, and
-@option{-fno-trapping-math}.
+Sets @option{-funsafe-math-optimizations}, @option{-ffinite-math-only},
+and @option{-fno-trapping-math}.
@cindex -funsafe-math-optimizations option
@cindex options, -funsafe-math-optimizations
@@ -1545,6 +1551,18 @@ Sets @option{-funsafe-math-optimizations}, and
Allow optimizations that may be give incorrect results
for certain IEEE inputs.
+@cindex -ffinite-math-only option
+@cindex options, -ffinite-math-only
+@item -ffinite-math-only
+Allow optimizations for floating-point arithmetic that assume
+that arguments and results are not NaNs or +-Infs.
+
+This option should never be turned on by any @option{-O} option since
+it can result in incorrect output for programs which depend on
+an exact implementation of IEEE or ISO rules/specifications.
+
+The default is @option{-fno-finite-math-only}.
+
@cindex -fno-trapping-math option
@cindex options, -fno-trapping-math
@item -fno-trapping-math
diff --git a/contrib/gcc/f/lang-specs.h b/contrib/gcc/f/lang-specs.h
index d6018bd..62b78c6 100644
--- a/contrib/gcc/f/lang-specs.h
+++ b/contrib/gcc/f/lang-specs.h
@@ -1,5 +1,5 @@
/* lang-specs.h file for Fortran
- Copyright (C) 1995, 1996, 1997, 1999, 2000, 2002
+ Copyright (C) 1995, 1996, 1997, 1999, 2000, 2002, 2003
Free Software Foundation, Inc.
Contributed by James Craig Burley.
@@ -29,12 +29,15 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
{".fpp", "@f77-cpp-input", 0},
{".FPP", "@f77-cpp-input", 0},
{"@f77-cpp-input",
- "tradcpp0 -lang-fortran %(cpp_options) %{!M:%{!MM:%{!E:%{!pipe:%g.f} |\n\
+ "cc1 -E -traditional-cpp -D_LANGUAGE_FORTRAN %(cpp_options) \
+ %{E|M|MM:%(cpp_debug_options)}\
+ %{!M:%{!MM:%{!E:%{!pipe:%g.f} |\n\
f771 %{!pipe:%g.f} %(cc1_options) %{I*} %{!fsyntax-only:%(invoke_as)}}}}", 0},
{".r", "@ratfor", 0},
{"@ratfor",
"%{C:%{!E:%eGNU C does not support -C without using -E}}\
- ratfor %{C} %{v} %{E:%W{o*}} %{!E: %{!pipe:-o %g.f} %i |\n\
+ %{CC:%{!E:%eGNU C does not support -CC without using -E}}\
+ ratfor %{C} %{CC} %{v} %{E:%W{o*}} %{!E: %{!pipe:-o %g.f} %i |\n\
f771 %{!pipe:%g.f} %(cc1_options) %{I*} %{!fsyntax-only:%(invoke_as)}}", 0},
{".f", "@f77", 0},
{".for", "@f77", 0},
diff --git a/contrib/gcc/f/lex.c b/contrib/gcc/f/lex.c
index d9f3bad..6d065dd 100644
--- a/contrib/gcc/f/lex.c
+++ b/contrib/gcc/f/lex.c
@@ -93,7 +93,7 @@ static ffelexType ffelex_first_char_[256];
/* The wf argument of the most recent active ffelex_file_(fixed,free)
function. */
-static ffewhereFile ffelex_current_wf_;
+static GTY (()) ffewhereFile ffelex_current_wf_;
/* TRUE if an INCLUDE statement can be processed (ffelex_set_include
can be called). */
@@ -106,7 +106,7 @@ static bool ffelex_set_include_;
/* Information on the pending INCLUDE file. */
static FILE *ffelex_include_file_;
static bool ffelex_include_free_form_;
-static ffewhereFile ffelex_include_wherefile_;
+static GTY(()) ffewhereFile ffelex_include_wherefile_;
/* Current master line count. */
static ffewhereLineNumber ffelex_linecount_current_;
@@ -246,8 +246,6 @@ ffelex_backslash_ (int c, ffewhereColumnNumber col)
hollerith constants. */
#define wide_flag 0
-#define warn_traditional 0
-#define flag_traditional 0
switch (state)
{
@@ -268,18 +266,6 @@ ffelex_backslash_ (int c, ffewhereColumnNumber col)
switch (c)
{
case 'x':
- if (warn_traditional)
- {
- /* xgettext:no-c-format */
- ffebad_start_msg_lex ("The meaning of `\\x' (at %0) varies with -traditional",
- FFEBAD_severityWARNING);
- ffelex_bad_here_ (0, line, column);
- ffebad_finish ();
- }
-
- if (flag_traditional)
- return c;
-
code = 0;
count = 0;
nonnull = 0;
@@ -319,24 +305,9 @@ ffelex_backslash_ (int c, ffewhereColumnNumber col)
return TARGET_BS;
case 'a':
- if (warn_traditional)
- {
- /* xgettext:no-c-format */
- ffebad_start_msg_lex ("The meaning of `\\a' (at %0) varies with -traditional",
- FFEBAD_severityWARNING);
- ffelex_bad_here_ (0, line, column);
- ffebad_finish ();
- }
-
- if (flag_traditional)
- return c;
return TARGET_BELL;
case 'v':
-#if 0 /* Vertical tab is present in common usage compilers. */
- if (flag_traditional)
- return c;
-#endif
return TARGET_VT;
case 'e':
@@ -589,12 +560,6 @@ ffelex_cfebackslash_ (int *use_d, int *d, FILE *finput)
switch (c)
{
case 'x':
- if (warn_traditional)
- warning ("the meaning of `\\x' varies with -traditional");
-
- if (flag_traditional)
- return c;
-
code = 0;
count = 0;
nonnull = 0;
@@ -672,18 +637,9 @@ ffelex_cfebackslash_ (int *use_d, int *d, FILE *finput)
return TARGET_BS;
case 'a':
- if (warn_traditional)
- warning ("the meaning of `\\a' varies with -traditional");
-
- if (flag_traditional)
- return c;
return TARGET_BELL;
case 'v':
-#if 0 /* Vertical tab is present in common usage compilers. */
- if (flag_traditional)
- return c;
-#endif
return TARGET_VT;
case 'e':
@@ -4678,3 +4634,5 @@ ffelex_token_use (ffelexToken t)
t->uses++;
return t;
}
+
+#include "gt-f-lex.h"
diff --git a/contrib/gcc/f/news.texi b/contrib/gcc/f/news.texi
index 37b08d9..fe6fa80 100644
--- a/contrib/gcc/f/news.texi
+++ b/contrib/gcc/f/news.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+@c Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
@c Free Software Foundation, Inc.
@c This is part of the G77 manual.
@c For copying conditions, see the file g77.texi.
@@ -8,13 +8,12 @@
@c Keep this the same as the dates above, since it's used
@c in the standalone derivations of this file (e.g. NEWS).
-@set copyrights-news 1995,1996,1997,1998,1999,2000,2001,2002
+@set copyrights-news 1995,1996,1997,1998,1999,2000,2001,2002,2003
-@set last-update-news 2002-10-28
-
-@include root.texi
+@set last-update-news 2003-05-18
@ifset DOC-NEWS
+@include root.texi
@c The immediately following lines apply to the NEWS file
@c which is derived from this file.
@emph{Note:} This file is automatically generated from the files
@@ -148,18 +147,69 @@ An online, ``live'' version of this document
(derived directly from the mainline, development version
of @command{g77} within @command{gcc})
is available at
-@uref{http://www.gnu.org/software/gcc/onlinedocs/g77/News.html}.
+@uref{http://gcc.gnu.org/onlinedocs/g77/News.html}.
@end ifclear
The following information was last updated on @value{last-update-news}:
+@heading In @code{GCC} 3.3 versus @code{GCC} 3.2:
+@itemize @bullet
+@item
+Problem Reports fixed (in chronological order of submission):
+@table @code
+@item 1832
+-list directed i/o overflow hangs, -fbounds-check doesn't detect
+@item 3924
+g77 generates code which is rejected by GAS if COFF debugging info is
+requested
+@item 6286
+Broken links on web pages
+@item 6367
+(libf2c) multiple repeat counts confuse namelist read into array
+@item 6491
+Logical operations error on logicals when using -fugly-logint
+@item 6742
+Generation of C++ Prototype for FORTRAN and extern "C"
+@item 7113
+Failure of g77.f-torture/execute/f90-intrinsic-bit.f -Os on irix6.5
+@item 7236
+(libf2c) OPEN(...,RECL=nnn,...) without ACCESS='DIRECT' should assume a direct
+access file
+@item 7278
+g77 "bug"; the executable misbehave (use of options -O2 -fno-automatic
+gave wrong results)
+@item 7384
+(libf2c) DATE_AND_TIME milliseconds field inactive on Windows
+@item 7388
+Incorrect output with 0-based array of characters
+@item 8587
+Double complex zero ** double precision number -> NaN instead of zero
+@item 9038
+-ffixed-line-length-none -x f77-cpp-input gives: Warning: unknown register name line-length-none
+@item 9263
+ICE caused by invalid PARAMETER in implied DO loop
+@item 10197
+Direct access files not unformatted by default
+@item 10726
+Documentation for function IDATE Intrinsic (UNIX) is wrong [fixed in 3.3.1].
+@end table
+@item
+Richard Henderson (@email{rth@@redhat.com}) analyzed and improved the handling
+of (no-)aliasing information for dummy arguments and improved the optimization
+of induction variables in unrolled loops.
+@end itemize
+
@heading In @code{GCC} 3.2 versus @code{GCC} 3.1:
@itemize @bullet
@item
Problem Reports fixed (in chronological order of submission):
@table @code
+@item 7681
+ICE in compensate_edge, at reg-stack.c:2591
@item 8308
gcc-3.x does not compile files with suffix .r (RATFOR) [Fixed in 3.2.1]
+@item 9258
+[3.2/3.3/3.4 regression] ICE in compensate_edge, at reg-stack.c:2589
@end table
@end itemize
@@ -192,6 +242,12 @@ ICE on compiling source with 540 000 000 REAL array
ICE on BESJN(integer*8,real)
@item 5837
bug in loop unrolling
+@item 6106
+sparc-sun-solaris2.7 gcc-3.1 extra g77 testsuite failures w/-m64
+@item 6138
+Incorrect acces of integer*1 variables on PA
+@item 6304
+Failure of LAPACK test dtest on irix6.5 with -mabi=64 -O2
@end table
@item
@@ -217,8 +273,8 @@ because 140 000 000 REALs is larger than the largest bit-extent that can be
expressed in 32 bits. However, bit-sizes never play a role after offsets
have been converted to byte addresses. Therefore this check has been removed,
and the limit is now 2 Gbyte of memory (around 530 000 000 REALs).
-Note: On GNU/Linux systems one has to compile programs that occupy more
-than 1 Gbyte statically, i.e.@: @code{g77 -static ...}.
+Note: On GNU/Linux systems one has to compile and link programs that occupy
+more than 1 Gbyte statically, i.e.@: @code{g77 -static ...}.
@item
Based on work done by Juergen Pfeifer (@email{juergen.pfeifer@@gmx.net})
@@ -2311,7 +2367,7 @@ fix up some of the build procedures.
@item
Change code generation for list-directed I/O so it allows
-for new versions of @code{libf2c} that might return non-zero
+for new versions of @code{libf2c} that might return nonzero
status codes for some operations previously assumed to always
return zero.
diff --git a/contrib/gcc/f/parse.c b/contrib/gcc/f/parse.c
index 29c6133..106ff3f 100644
--- a/contrib/gcc/f/parse.c
+++ b/contrib/gcc/f/parse.c
@@ -26,17 +26,16 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "version.h"
#include "flags.h"
-#define NAME_OF_STDIN "<stdin>"
-
extern FILE *finput;
-int
-yyparse ()
+void
+ffe_parse_file (set_yydebug)
+ int set_yydebug ATTRIBUTE_UNUSED;
{
ffewhereFile wf;
if (ffe_is_version ())
- fprintf (stderr, "GNU Fortran Front End version %s\n", ffe_version_string);
+ fprintf (stderr, "GNU Fortran Front End version %s\n", version_string);
if (!ffe_is_pedantic ())
ffe_set_is_pedantic (pedantic);
@@ -46,6 +45,4 @@ yyparse ()
ffe_file (wf, finput);
ffecom_finish_compile ();
-
- return 0;
}
diff --git a/contrib/gcc/f/root.texi b/contrib/gcc/f/root.texi
index 361e260..d8619cc 100644
--- a/contrib/gcc/f/root.texi
+++ b/contrib/gcc/f/root.texi
@@ -1,9 +1,4 @@
-@c DEVELOPMENT is set to indicate an in-development version,
-@c as compared to a release version. When making a release
-@c (e.g. a release branch in the CVS repository for gcc),
-@c clear this and set the version information correctly.
-@clear DEVELOPMENT
-@set version-gcc 3.2.2
+@include gcc-common.texi
@set email-general gcc@@gcc.gnu.org
@set email-help gcc-help@@gcc.gnu.org
@@ -12,7 +7,7 @@
@set path-g77 gcc/gcc/f
@set path-libf2c gcc/libf2c
-@set which-g77 GCC-@value{version-gcc}
+@set which-g77 GCC-@value{version-GCC}
@set which-gcc GCC
@set email-burley craig@@jcb-sc.com
diff --git a/contrib/gcc/f/stc.c b/contrib/gcc/f/stc.c
index 1f17766..b9602c2 100644
--- a/contrib/gcc/f/stc.c
+++ b/contrib/gcc/f/stc.c
@@ -1,5 +1,5 @@
/* stc.c -- Implementation File (module.c template V1.0)
- Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc.
Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -9195,18 +9195,19 @@ ffestc_R810 (ffesttCaseList cases, ffelexToken name)
ffebad_finish ();
continue;
}
-
if (((caseobj->expr1 != NULL)
&& ((ffeinfo_basictype (ffebld_info (caseobj->expr1))
!= s->type)
- || (ffeinfo_kindtype (ffebld_info (caseobj->expr1))
- != s->kindtype)))
+ || ((ffeinfo_kindtype (ffebld_info (caseobj->expr1))
+ != s->kindtype)
+ && (ffeinfo_kindtype (ffebld_info (caseobj->expr1)) != FFEINFO_kindtypeINTEGER1 ))
|| ((caseobj->range)
&& (caseobj->expr2 != NULL)
&& ((ffeinfo_basictype (ffebld_info (caseobj->expr2))
!= s->type)
- || (ffeinfo_kindtype (ffebld_info (caseobj->expr2))
- != s->kindtype))))
+ || ((ffeinfo_kindtype (ffebld_info (caseobj->expr2))
+ != s->kindtype)
+ && (ffeinfo_kindtype (ffebld_info (caseobj->expr2)) != FFEINFO_kindtypeINTEGER1)))))))
{
ffebad_start (FFEBAD_CASE_TYPE_DISAGREE);
ffebad_here (0, ffelex_token_where_line (caseobj->t),
@@ -9217,6 +9218,8 @@ ffestc_R810 (ffesttCaseList cases, ffelexToken name)
continue;
}
+
+
if ((s->type == FFEINFO_basictypeLOGICAL) && (caseobj->range))
{
ffebad_start (FFEBAD_CASE_LOGICAL_RANGE);
diff --git a/contrib/gcc/f/std.c b/contrib/gcc/f/std.c
index db8c723..bd2add2 100644
--- a/contrib/gcc/f/std.c
+++ b/contrib/gcc/f/std.c
@@ -1,5 +1,5 @@
/* std.c -- Implementation File (module.c template V1.0)
- Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 2000, 2002 Free Software Foundation, Inc.
Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -4774,9 +4774,7 @@ ffestd_S3P4 (ffebld filename)
fi = ffecom_open_include (ffewhere_file_name (wf),
ffelex_token_where_line (ffesta_tokens[0]),
ffelex_token_where_column (ffesta_tokens[0]));
- if (fi == NULL)
- ffewhere_file_kill (wf);
- else
+ if (fi != NULL)
ffelex_set_include (wf, (ffelex_token_type (ffesta_tokens[0])
== FFELEX_typeNAME), fi);
}
diff --git a/contrib/gcc/f/ste.c b/contrib/gcc/f/ste.c
index 2959984..2ddf181 100644
--- a/contrib/gcc/f/ste.c
+++ b/contrib/gcc/f/ste.c
@@ -1,5 +1,5 @@
/* ste.c -- Implementation File (module.c template V1.0)
- Copyright (C) 1995, 1996, 2000, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 2000, 2002, 2003 Free Software Foundation, Inc.
Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -1162,13 +1162,13 @@ ffeste_io_douio_ (ffebld expr)
declaration of variables (temporaries) to the expanding of expressions,
statements, etc. */
+static GTY(()) tree f2c_alist_struct;
static tree
ffeste_io_ialist_ (bool have_err,
ffestvUnit unit,
ffebld unit_expr,
int unit_dflt)
{
- static tree f2c_alist_struct = NULL_TREE;
tree t;
tree ttype;
tree field;
@@ -1193,8 +1193,6 @@ ffeste_io_ialist_ (bool have_err,
TYPE_FIELDS (ref) = errfield;
layout_type (ref);
- ggc_add_tree_root (&f2c_alist_struct, 1);
-
f2c_alist_struct = ref;
}
@@ -1283,6 +1281,7 @@ ffeste_io_ialist_ (bool have_err,
declaration of variables (temporaries) to the expanding of expressions,
statements, etc. */
+static GTY(()) tree f2c_cilist_struct;
static tree
ffeste_io_cilist_ (bool have_err,
ffestvUnit unit,
@@ -1294,7 +1293,6 @@ ffeste_io_cilist_ (bool have_err,
bool rec,
ffebld rec_expr)
{
- static tree f2c_cilist_struct = NULL_TREE;
tree t;
tree ttype;
tree field;
@@ -1325,8 +1323,6 @@ ffeste_io_cilist_ (bool have_err,
TYPE_FIELDS (ref) = errfield;
layout_type (ref);
- ggc_add_tree_root (&f2c_cilist_struct, 1);
-
f2c_cilist_struct = ref;
}
@@ -1508,12 +1504,12 @@ ffeste_io_cilist_ (bool have_err,
declaration of variables (temporaries) to the expanding of expressions,
statements, etc. */
+static GTY(()) tree f2c_close_struct;
static tree
ffeste_io_cllist_ (bool have_err,
ffebld unit_expr,
ffestpFile *stat_spec)
{
- static tree f2c_close_struct = NULL_TREE;
tree t;
tree ttype;
tree field;
@@ -1541,8 +1537,6 @@ ffeste_io_cllist_ (bool have_err,
TYPE_FIELDS (ref) = errfield;
layout_type (ref);
- ggc_add_tree_root (&f2c_close_struct, 1);
-
f2c_close_struct = ref;
}
@@ -1622,6 +1616,7 @@ ffeste_io_cllist_ (bool have_err,
declaration of variables (temporaries) to the expanding of expressions,
statements, etc. */
+static GTY(()) tree f2c_icilist_struct;
static tree
ffeste_io_icilist_ (bool have_err,
ffebld unit_expr,
@@ -1629,7 +1624,6 @@ ffeste_io_icilist_ (bool have_err,
ffestvFormat format,
ffestpFile *format_spec)
{
- static tree f2c_icilist_struct = NULL_TREE;
tree t;
tree ttype;
tree field;
@@ -1663,8 +1657,6 @@ ffeste_io_icilist_ (bool have_err,
TYPE_FIELDS (ref) = errfield;
layout_type (ref);
- ggc_add_tree_root (&f2c_icilist_struct, 1);
-
f2c_icilist_struct = ref;
}
@@ -1851,6 +1843,7 @@ ffeste_io_icilist_ (bool have_err,
declaration of variables (temporaries) to the expanding of expressions,
statements, etc. */
+static GTY(()) tree f2c_inquire_struct;
static tree
ffeste_io_inlist_ (bool have_err,
ffestpFile *unit_spec,
@@ -1870,7 +1863,6 @@ ffeste_io_inlist_ (bool have_err,
ffestpFile *nextrec_spec,
ffestpFile *blank_spec)
{
- static tree f2c_inquire_struct = NULL_TREE;
tree t;
tree ttype;
tree field;
@@ -1959,8 +1951,6 @@ ffeste_io_inlist_ (bool have_err,
TYPE_FIELDS (ref) = errfield;
layout_type (ref);
- ggc_add_tree_root (&f2c_inquire_struct, 1);
-
f2c_inquire_struct = ref;
}
@@ -2109,6 +2099,7 @@ ffeste_io_inlist_ (bool have_err,
declaration of variables (temporaries) to the expanding of expressions,
statements, etc. */
+static GTY(()) tree f2c_open_struct;
static tree
ffeste_io_olist_ (bool have_err,
ffebld unit_expr,
@@ -2119,7 +2110,6 @@ ffeste_io_olist_ (bool have_err,
ffestpFile *recl_spec,
ffestpFile *blank_spec)
{
- static tree f2c_open_struct = NULL_TREE;
tree t;
tree ttype;
tree field;
@@ -2163,8 +2153,6 @@ ffeste_io_olist_ (bool have_err,
TYPE_FIELDS (ref) = errfield;
layout_type (ref);
- ggc_add_tree_root (&f2c_open_struct, 1);
-
f2c_open_struct = ref;
}
@@ -2723,21 +2711,27 @@ ffeste_R810 (ffestw block, unsigned long casenum)
do
{
texprlow = (c->low == NULL) ? NULL_TREE
- : ffecom_constantunion (&ffebld_constant_union (c->low), s->type,
- s->kindtype,
- ffecom_tree_type[s->type][s->kindtype]);
+ : ffecom_constantunion_with_type (&ffebld_constant_union (c->low),
+ ffecom_tree_type[s->type][s->kindtype], c->low->consttype);
if (c->low != c->high)
{
texprhigh = (c->high == NULL) ? NULL_TREE
- : ffecom_constantunion (&ffebld_constant_union (c->high),
- s->type, s->kindtype,
- ffecom_tree_type[s->type][s->kindtype]);
+ : ffecom_constantunion_with_type (&ffebld_constant_union (c->high),
+ ffecom_tree_type[s->type][s->kindtype], c->high->consttype);
pushok = pushcase_range (texprlow, texprhigh, convert,
tlabel, &duplicate);
}
else
pushok = pushcase (texprlow, convert, tlabel, &duplicate);
- assert (pushok == 0);
+ assert((pushok !=2) || (pushok !=0));
+ if (pushok==2)
+ {
+ ffebad_start_msg ("SELECT (at %0) has duplicate cases -- check integer overflow of CASE(s)",
+ FFEBAD_severityFATAL);
+ ffebad_here (0, ffestw_line (block), ffestw_col (block));
+ ffebad_finish ();
+ ffestw_set_select_texpr (block, error_mark_node);
+ }
c = c->next_stmt;
/* Unlink prev. */
c->previous_stmt->previous_stmt->next_stmt = c;
@@ -4618,3 +4612,5 @@ ffeste_terminate_2 (void)
assert (! ffeste_top_block_);
}
#endif
+
+#include "gt-f-ste.h"
diff --git a/contrib/gcc/f/target.c b/contrib/gcc/f/target.c
index 086faed..82ae955 100644
--- a/contrib/gcc/f/target.c
+++ b/contrib/gcc/f/target.c
@@ -69,13 +69,13 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* Include files. */
#include "proj.h"
-#include "glimits.h"
#include "target.h"
#include "diagnostic.h"
#include "bad.h"
#include "info.h"
#include "lex.h"
#include "malloc.h"
+#include "real.h"
/* Externals defined here. */
@@ -2191,7 +2191,7 @@ ffetarget_print_hex (FILE *f, ffetargetTypeless value)
{
char *p;
char digits[sizeof (value) * CHAR_BIT / 4 + 1];
- static char hexdigits[16] = "0123456789ABCDEF";
+ static const char hexdigits[16] = "0123456789ABCDEF";
if (f == NULL)
f = dmpout;
@@ -2277,9 +2277,11 @@ ffetarget_real1 (ffetargetReal1 *value, ffelexToken integer,
*p = '\0';
- ffetarget_make_real1 (value,
- FFETARGET_ATOF_ (ptr,
- SFmode));
+ {
+ REAL_VALUE_TYPE rv;
+ rv = FFETARGET_ATOF_ (ptr, SFmode);
+ ffetarget_make_real1 (value, rv);
+ }
if (sz > ARRAY_SIZE (ffetarget_string_))
malloc_kill_ks (malloc_pool_image (), ptr, sz);
@@ -2363,9 +2365,11 @@ ffetarget_real2 (ffetargetReal2 *value, ffelexToken integer,
*p = '\0';
- ffetarget_make_real2 (value,
- FFETARGET_ATOF_ (ptr,
- DFmode));
+ {
+ REAL_VALUE_TYPE rv;
+ rv = FFETARGET_ATOF_ (ptr, DFmode);
+ ffetarget_make_real2 (value, rv);
+ }
if (sz > ARRAY_SIZE (ffetarget_string_))
malloc_kill_ks (malloc_pool_image (), ptr, sz);
diff --git a/contrib/gcc/f/target.h b/contrib/gcc/f/target.h
index df73dab..2125ad5 100644
--- a/contrib/gcc/f/target.h
+++ b/contrib/gcc/f/target.h
@@ -38,16 +38,6 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#endif
#endif
-/* For now, g77 requires the ability to determine the exact bit pattern
- of a float on the target machine. (Hopefully this will be changed
- soon). Make sure we can do this. */
-
-#if !defined (REAL_ARITHMETIC) \
- && ((TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT) \
- || (FLOAT_WORDS_BIG_ENDIAN != HOST_FLOAT_WORDS_BIG_ENDIAN))
-#error "g77 requires ability to access exact FP representation of target machine"
-#endif
-
/* Simple definitions and enumerations. */
#define FFETARGET_charactersizeNONE (-1)
@@ -341,117 +331,53 @@ typedef ? ffetargetLogical8;
?
#endif
#if FFETARGET_okREAL1
-#ifdef REAL_ARITHMETIC
-#ifdef FFETARGET_32bit_longs
-typedef long int ffetargetReal1;
-#define ffetargetReal1_f "l"
-#define ffetarget_cvt_r1_to_rv_ REAL_VALUE_UNTO_TARGET_SINGLE
-#define ffetarget_cvt_rv_to_r1_ REAL_VALUE_TO_TARGET_SINGLE
-#else
typedef int ffetargetReal1;
#define ffetargetReal1_f ""
-#define ffetarget_cvt_r1_to_rv_(in) \
- ({ REAL_VALUE_TYPE _rv; \
- _rv = REAL_VALUE_UNTO_TARGET_SINGLE ((long) (in)); \
+#define ffetarget_cvt_r1_to_rv_(in) \
+ ({ REAL_VALUE_TYPE _rv; \
+ long _in = (in); \
+ real_from_target (&_rv, &_in, mode_for_size (32, MODE_FLOAT, 0)); \
_rv; })
#define ffetarget_cvt_rv_to_r1_(in, out) \
({ long _tmp; \
REAL_VALUE_TO_TARGET_SINGLE ((in), _tmp); \
(out) = (ffetargetReal1) _tmp; })
#endif
-#else /* REAL_ARITHMETIC */
-typedef float ffetargetReal1;
-#define ffetargetReal1_f ""
-#endif /* REAL_ARITHMETIC */
-#endif
#if FFETARGET_okREAL2
-#ifdef REAL_ARITHMETIC
-#ifdef FFETARGET_32bit_longs
-typedef struct
- {
- long int v[2];
- }
-ffetargetReal2;
-#define ffetargetReal2_f "l"
-#define ffetarget_cvt_r2_to_rv_ REAL_VALUE_UNTO_TARGET_DOUBLE
-#define ffetarget_cvt_rv_to_r2_ REAL_VALUE_TO_TARGET_DOUBLE
-#else
-typedef struct
- {
- int v[2];
- }
-ffetargetReal2;
+typedef struct { int v[2]; } ffetargetReal2;
#define ffetargetReal2_f ""
-#define ffetarget_cvt_r2_to_rv_(in) \
- ({ REAL_VALUE_TYPE _rv; \
- long _tmp[2]; \
- _tmp[0] = (in)[0]; \
- _tmp[1] = (in)[1]; \
- _rv = REAL_VALUE_UNTO_TARGET_DOUBLE (_tmp); \
+#define ffetarget_cvt_r2_to_rv_(in) \
+ ({ REAL_VALUE_TYPE _rv; long _tmp[2]; \
+ _tmp[0] = (in)[0]; _tmp[1] = (in)[1]; \
+ real_from_target (&_rv, _tmp, mode_for_size (64, MODE_FLOAT, 0)); \
_rv; })
-#define ffetarget_cvt_rv_to_r2_(in, out) \
- ({ long _tmp[2]; \
- REAL_VALUE_TO_TARGET_DOUBLE ((in), _tmp); \
- (out)[0] = (int) (_tmp[0]); \
- (out)[1] = (int) (_tmp[1]); })
-#endif
-#else
-typedef double ffetargetReal2;
-#define ffetargetReal2_f ""
-#endif
+#define ffetarget_cvt_rv_to_r2_(in, out) \
+ ({ long _tmp[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE ((in), _tmp); \
+ (out)[0] = (int)_tmp[0]; (out)[1] = (int)_tmp[1]; })
#endif
#if FFETARGET_okREAL3
-#ifdef REAL_ARITHMETIC
typedef long ffetargetReal3[?];
-#else
-typedef ? ffetargetReal3;
-#define ffetargetReal3_f
-#endif
?
#endif
#if FFETARGET_okREAL4
-#ifdef REAL_ARITHMETIC
typedef long ffetargetReal4[?];
-#else
-typedef ? ffetargetReal4;
-#define ffetargetReal4_f
-#endif
?
#endif
#if FFETARGET_okREAL5
-#ifdef REAL_ARITHMETIC
typedef long ffetargetReal5[?];
-#else
-typedef ? ffetargetReal5;
-#define ffetargetReal5_f
-#endif
?
#endif
#if FFETARGET_okREAL6
-#ifdef REAL_ARITHMETIC
typedef long ffetargetReal6[?];
-#else
-typedef ? ffetargetReal6;
-#define ffetargetReal6_f
-#endif
?
#endif
#if FFETARGET_okREAL7
-#ifdef REAL_ARITHMETIC
typedef long ffetargetReal7[?];
-#else
-typedef ? ffetargetReal7;
-#define ffetargetReal7_f
-#endif
?
#endif
#if FFETARGET_okREAL8
-#ifdef REAL_ARITHMETIC
typedef long ffetargetReal8[?];
-#else
-typedef ? ffetargetReal8;
-#define ffetargetReal8_f
-#endif
?
#endif
#if FFETARGET_okCOMPLEX1
@@ -872,7 +798,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
REAL_VALUE_FROM_INT (resr, (long) lf, (long) ((lf < 0) ? -1 : 0), \
((kt == 1) ? SFmode : DFmode))
-#ifdef REAL_ARITHMETIC
#define ffetarget_add_complex1(res,l,r) \
({ REAL_VALUE_TYPE lr, li, rr, ri, resr, resi; \
lr = ffetarget_cvt_r1_to_rv_ ((l).real); \
@@ -895,19 +820,10 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_cvt_rv_to_r2_ (resr, &((res)->real.v[0])); \
ffetarget_cvt_rv_to_r2_ (resi, &((res)->imaginary.v[0])); \
FFEBAD; })
-#else
-#define ffetarget_add_complex1(res,l,r) \
- ((res)->real = (l).real + (r).real, \
- (res)->imaginary = (l).imaginary + (r).imaginary, FFEBAD)
-#define ffetarget_add_complex2(res,l,r) \
- ((res)->real = (l).real + (r).real, \
- (res)->imaginary = (l).imaginary + (r).imaginary, FFEBAD)
-#endif
#define ffetarget_add_integer1(res,l,r) (*(res) = (l) + (r), FFEBAD)
#define ffetarget_add_integer2(res,l,r) (*(res) = (l) + (r), FFEBAD)
#define ffetarget_add_integer3(res,l,r) (*(res) = (l) + (r), FFEBAD)
#define ffetarget_add_integer4(res,l,r) (*(res) = (l) + (r), FFEBAD)
-#ifdef REAL_ARITHMETIC
#define ffetarget_add_real1(res,l,r) \
({ REAL_VALUE_TYPE lr, rr, resr; \
lr = ffetarget_cvt_r1_to_rv_ ((l)); \
@@ -922,10 +838,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
REAL_ARITHMETIC (resr, PLUS_EXPR, lr, rr); \
ffetarget_cvt_rv_to_r2_ (resr, &((res)->v[0])); \
FFEBAD; })
-#else
-#define ffetarget_add_real1(res,l,r) (*(res) = (l) + (r), FFEBAD)
-#define ffetarget_add_real2(res,l,r) (*(res) = (l) + (r), FFEBAD)
-#endif
#define ffetarget_aggregate_ptr_memcpy(dbt,dkt,sbt,skt) \
((ffetargetCopyfunc) ffetarget_memcpy_)
#define ffetarget_and_integer1(res,l,r) (*(res) = (l) & (r), FFEBAD)
@@ -969,7 +881,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_convert_any_hollerith_ ((char *) (res), sizeof(*(res)), l)
#define ffetarget_convert_complex1_typeless(res,l) \
ffetarget_convert_any_typeless_ ((char *) (res), sizeof(*(res)), l)
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_complex1_complex2(res,l) \
({ REAL_VALUE_TYPE lr, li; \
lr = ffetarget_cvt_r2_to_rv_ (&((l).real.v[0])); \
@@ -977,11 +888,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_cvt_rv_to_r1_ (lr, (res)->real); \
ffetarget_cvt_rv_to_r1_ (li, (res)->imaginary), \
FFEBAD; })
-#else
-#define ffetarget_convert_complex1_complex2(res,l) \
- ((res)->real = (l).real, (res)->imaginary = (l).imaginary, FFEBAD)
-#endif
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_complex1_integer(res,l) \
({ REAL_VALUE_TYPE resi, resr; \
ffetargetInteger1 lf = (l); \
@@ -990,19 +896,10 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_cvt_rv_to_r1_ (resr, (res)->real); \
ffetarget_cvt_rv_to_r1_ (resi, (res)->imaginary); \
FFEBAD; })
-#else
-#define ffetarget_convert_complex1_integer(res,l) \
- ((res)->real = (l), (res)->imaginary = 0, FFEBAD)
-#endif
#define ffetarget_convert_complex1_integer1 ffetarget_convert_complex1_integer
#define ffetarget_convert_complex1_integer2 ffetarget_convert_complex1_integer
#define ffetarget_convert_complex1_integer3 ffetarget_convert_complex1_integer
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_complex1_integer4(res,l) FFEBAD_NOCANDO
-#else
-#define ffetarget_convert_complex1_integer4 ffetarget_convert_complex1_integer
-#endif
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_complex1_real1(res,l) \
((res)->real = (l), \
ffetarget_cvt_rv_to_r1_ (dconst0, (res)->imaginary), \
@@ -1013,19 +910,12 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_cvt_rv_to_r1_ (lr, (res)->real); \
ffetarget_cvt_rv_to_r1_ (dconst0, (res)->imaginary), \
FFEBAD; })
-#else
-#define ffetarget_convert_complex1_real1(res,l) \
- ((res)->real = (l), (res)->imaginary = 0, FFEBAD)
-#define ffetarget_convert_complex1_real2(res,l) \
- ((res)->real = (l), (res)->imaginary = 0, FFEBAD)
-#endif
#define ffetarget_convert_complex2_character1(res,l) \
ffetarget_convert_any_character1_ ((char *) (res), sizeof(*(res)), l)
#define ffetarget_convert_complex2_hollerith(res,l) \
ffetarget_convert_any_hollerith_ ((char *) (res), sizeof(*(res)), l)
#define ffetarget_convert_complex2_typeless(res,l) \
ffetarget_convert_any_typeless_ ((char *) (res), sizeof(*(res)), l)
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_complex2_complex1(res,l) \
({ REAL_VALUE_TYPE lr, li; \
lr = ffetarget_cvt_r1_to_rv_ ((l).real); \
@@ -1033,11 +923,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_cvt_rv_to_r2_ (lr, &((res)->real.v[0])); \
ffetarget_cvt_rv_to_r2_ (li, &((res)->imaginary.v[0])), \
FFEBAD; })
-#else
-#define ffetarget_convert_complex2_complex1(res,l) \
- ((res)->real = (l).real, (res)->imaginary = (l).imaginary, FFEBAD)
-#endif
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_complex2_integer(res,l) \
({ REAL_VALUE_TYPE resi, resr; \
ffetargetInteger1 lf = (l); \
@@ -1046,19 +931,10 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_cvt_rv_to_r2_ (resr, &((res)->real.v[0])); \
ffetarget_cvt_rv_to_r2_ (resi, &((res)->imaginary.v[0])); \
FFEBAD; })
-#else
-#define ffetarget_convert_complex2_integer(res,l) \
- ((res)->real = (l), (res)->imaginary = 0, FFEBAD)
-#endif
#define ffetarget_convert_complex2_integer1 ffetarget_convert_complex2_integer
#define ffetarget_convert_complex2_integer2 ffetarget_convert_complex2_integer
#define ffetarget_convert_complex2_integer3 ffetarget_convert_complex2_integer
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_complex2_integer4(res,l) FFEBAD_NOCANDO
-#else
-#define ffetarget_convert_complex2_integer4 ffetarget_convert_complex2_integer
-#endif
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_complex2_real1(res,l) \
({ REAL_VALUE_TYPE lr; \
lr = ffetarget_cvt_r1_to_rv_ (l); \
@@ -1069,12 +945,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
((res)->real = (l), \
ffetarget_cvt_rv_to_r2_ (dconst0, &((res)->imaginary.v[0])), \
FFEBAD)
-#else
-#define ffetarget_convert_complex2_real1(res,l) \
- ((res)->real = (l), (res)->imaginary = 0, FFEBAD)
-#define ffetarget_convert_complex2_real2(res,l) \
- ((res)->real = (l), (res)->imaginary = 0, FFEBAD)
-#endif
#define ffetarget_convert_integer2_character1(res,l) \
ffetarget_convert_integer1_character1(res,l)
#define ffetarget_convert_integer2_complex1(res,l) \
@@ -1127,15 +997,8 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_convert_integer1_typeless(res,l)
#define ffetarget_convert_integer4_character1(res,l) \
ffetarget_convert_integer1_character1(res,l)
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_integer4_complex1(res,l) FFEBAD_NOCANDO
#define ffetarget_convert_integer4_complex2(res,l) FFEBAD_NOCANDO
-#else
-#define ffetarget_convert_integer4_complex1(res,l) \
- ffetarget_convert_integer1_complex1(res,l)
-#define ffetarget_convert_integer4_complex2(res,l) \
- ffetarget_convert_integer1_complex2(res,l)
-#endif
#define ffetarget_convert_integer4_hollerith(res,l) \
ffetarget_convert_integer1_hollerith(res,l)
#define ffetarget_convert_integer4_integer1(res,l) (*(res) = (l), FFEBAD)
@@ -1149,15 +1012,8 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_convert_integer1_logical1(res,l)
#define ffetarget_convert_integer4_logical4(res,l) \
ffetarget_convert_integer1_logical1(res,l)
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_integer4_real1(res,l) FFEBAD_NOCANDO
#define ffetarget_convert_integer4_real2(res,l) FFEBAD_NOCANDO
-#else
-#define ffetarget_convert_integer4_real1(res,l) \
- ffetarget_convert_integer1_real1(res,l)
-#define ffetarget_convert_integer4_real2(res,l) \
- ffetarget_convert_integer1_real2(res,l)
-#endif
#define ffetarget_convert_integer4_typeless(res,l) \
ffetarget_convert_integer1_typeless(res,l)
#define ffetarget_convert_logical1_character1(res,l) \
@@ -1225,7 +1081,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
#define ffetarget_convert_integer1_logical2(res,l) (*(res) = (l), FFEBAD)
#define ffetarget_convert_integer1_logical3(res,l) (*(res) = (l), FFEBAD)
#define ffetarget_convert_integer1_logical4(res,l) (*(res) = (l), FFEBAD)
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_integer1_real1(res,l) \
({ REAL_VALUE_TYPE lr; \
lr = ffetarget_cvt_r1_to_rv_ (l); \
@@ -1250,12 +1105,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
REAL_VALUE_TO_INT (&ffetarget_long_val_, &ffetarget_long_junk_, lr); \
*(res) = ffetarget_long_val_; \
FFEBAD; })
-#else
-#define ffetarget_convert_integer1_real1(res,l) (*(res) = (l), FFEBAD)
-#define ffetarget_convert_integer1_real2(res,l) (*(res) = (l), FFEBAD)
-#define ffetarget_convert_integer1_complex1(res,l) (*(res) = (l).real, FFEBAD)
-#define ffetarget_convert_integer1_complex2(res,l) (*(res) = (l).real, FFEBAD)
-#endif
#define ffetarget_convert_real1_character1(res,l) \
ffetarget_convert_any_character1_ ((char *) (res), sizeof(*(res)), l)
#define ffetarget_convert_real1_hollerith(res,l) \
@@ -1264,36 +1113,23 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_convert_real1_integer1(res,l)
#define ffetarget_convert_real1_integer3(res,l) \
ffetarget_convert_real1_integer1(res,l)
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_real1_integer4(res,l) FFEBAD_NOCANDO
-#else
-#define ffetarget_convert_real1_integer4(res,l) \
- ffetarget_convert_real1_integer1(res,l)
-#endif
#define ffetarget_convert_real1_typeless(res,l) \
ffetarget_convert_any_typeless_ ((char *) (res), sizeof(*(res)), l)
#define ffetarget_convert_real1_complex1(res,l) (*(res) = (l).real, FFEBAD)
#define ffetarget_convert_real1_complex2(res,l) \
ffetarget_convert_real1_real2 ((res), (l).real)
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_real1_integer1(res,l) \
({ REAL_VALUE_TYPE resr; \
ffetargetInteger1 lf = (l); \
FFETARGET_REAL_VALUE_FROM_INT_ (resr, lf, 1); \
ffetarget_cvt_rv_to_r1_ (resr, *(res)); \
FFEBAD; })
-#else
-#define ffetarget_convert_real1_integer1(res,l) (*(res) = (l), FFEBAD)
-#endif
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_real1_real2(res,l) \
({ REAL_VALUE_TYPE lr; \
lr = ffetarget_cvt_r2_to_rv_ (&((l).v[0])); \
ffetarget_cvt_rv_to_r1_ (lr, *(res)); \
FFEBAD; })
-#else
-#define ffetarget_convert_real1_real2(res,l) (*(res) = (l), FFEBAD)
-#endif
#define ffetarget_convert_real2_character1(res,l) \
ffetarget_convert_any_character1_ ((char *) (res), sizeof(*(res)), l)
#define ffetarget_convert_real2_hollerith(res,l) \
@@ -1302,18 +1138,12 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_convert_real2_integer1(res,l)
#define ffetarget_convert_real2_integer3(res,l) \
ffetarget_convert_real2_integer1(res,l)
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_real2_integer4(res,l) FFEBAD_NOCANDO
-#else
-#define ffetarget_convert_real2_integer4(res,l) \
- ffetarget_convert_real2_integer1(res,l)
-#endif
#define ffetarget_convert_real2_typeless(res,l) \
ffetarget_convert_any_typeless_ ((char *) (res), sizeof(*(res)), l)
#define ffetarget_convert_real2_complex1(res,l) \
ffetarget_convert_real2_real1 ((res), (l).real)
#define ffetarget_convert_real2_complex2(res,l) (*(res) = (l).real, FFEBAD)
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_real2_integer(res,l) \
({ REAL_VALUE_TYPE resr; \
ffetargetInteger1 lf = (l); \
@@ -1321,28 +1151,21 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_cvt_rv_to_r2_ (resr, &((res)->v[0])); \
FFEBAD; })
#define ffetarget_convert_real2_integer1 ffetarget_convert_real2_integer
-#else
-#define ffetarget_convert_real2_integer1(res,l) (*(res) = (l), FFEBAD)
-#endif
-#ifdef REAL_ARITHMETIC
#define ffetarget_convert_real2_real1(res,l) \
({ REAL_VALUE_TYPE lr; \
lr = ffetarget_cvt_r1_to_rv_ ((l)); \
ffetarget_cvt_rv_to_r2_ (lr, &((res)->v[0])); \
FFEBAD; })
-#else
-#define ffetarget_convert_real2_real1(res,l) (*(res) = (l), FFEBAD)
-#endif
#define ffetarget_divide_integer1(res,l,r) \
(((r) == 0) ? (*(res) = 0, FFEBAD_DIV_BY_ZERO) \
- : (*(res) = (l) / (r), FFEBAD))
+ : (((r) == -1) ? (*(res) = -(l), FFEBAD) \
+ : (*(res) = (l) / (r), FFEBAD)))
#define ffetarget_divide_integer2(res,l,r) \
ffetarget_divide_integer1(res,l,r)
#define ffetarget_divide_integer3(res,l,r) \
ffetarget_divide_integer1(res,l,r)
#define ffetarget_divide_integer4(res,l,r) \
ffetarget_divide_integer1(res,l,r)
-#ifdef REAL_ARITHMETIC
#define ffetarget_divide_real1(res,l,r) \
({ REAL_VALUE_TYPE lr, rr, resr; \
lr = ffetarget_cvt_r1_to_rv_ ((l)); \
@@ -1369,15 +1192,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
FFEBAD; \
}); \
})
-#else
-#define ffetarget_divide_real1(res,l,r) \
- (((r) == 0) ? (*(res) = 0, FFEBAD_DIV_BY_ZERO) \
- : (*(res) = (l) / (r), FFEBAD))
-#define ffetarget_divide_real2(res,l,r) \
- (((r) == 0) ? (*(res) = 0, FFEBAD_DIV_BY_ZERO) \
- : (*(res) = (l) / (r), FFEBAD))
-#endif
-#ifdef REAL_ARITHMETIC
#define ffetarget_eq_complex1(res,l,r) \
({ REAL_VALUE_TYPE lr, li, rr, ri; \
lr = ffetarget_cvt_r1_to_rv_ ((l).real); \
@@ -1396,14 +1210,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
*(res) = (REAL_VALUES_EQUAL (lr, rr) && REAL_VALUES_EQUAL (li, ri)) \
? TRUE : FALSE; \
FFEBAD; })
-#else
-#define ffetarget_eq_complex1(res,l,r) \
- (*(res) = (((l).real == (r).real) && ((l).imaginary == (r).imaginary)) \
- ? TRUE : FALSE, FFEBAD)
-#define ffetarget_eq_complex2(res,l,r) \
- (*(res) = (((l).real == (r).real) && ((l).imaginary == (r).imaginary)) \
- ? TRUE : FALSE, FFEBAD)
-#endif
#define ffetarget_eq_integer1(res,l,r) \
(*(res) = ((l) == (r)) ? TRUE : FALSE, FFEBAD)
#define ffetarget_eq_integer2(res,l,r) \
@@ -1412,7 +1218,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
(*(res) = ((l) == (r)) ? TRUE : FALSE, FFEBAD)
#define ffetarget_eq_integer4(res,l,r) \
(*(res) = ((l) == (r)) ? TRUE : FALSE, FFEBAD)
-#ifdef REAL_ARITHMETIC
#define ffetarget_eq_real1(res,l,r) \
({ REAL_VALUE_TYPE lr, rr; \
lr = ffetarget_cvt_r1_to_rv_ ((l)); \
@@ -1425,12 +1230,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
rr = ffetarget_cvt_r2_to_rv_ (&((r).v[0])); \
*(res) = REAL_VALUES_EQUAL (lr, rr) ? TRUE : FALSE; \
FFEBAD; })
-#else
-#define ffetarget_eq_real1(res,l,r) \
- (*(res) = ((l) == (r)) ? TRUE : FALSE, FFEBAD)
-#define ffetarget_eq_real2(res,l,r) \
- (*(res) = ((l) == (r)) ? TRUE : FALSE, FFEBAD)
-#endif
#define ffetarget_eqv_integer1(res,l,r) (*(res) = (l) ^ ~(r), FFEBAD)
#define ffetarget_eqv_integer2(res,l,r) (*(res) = (l) ^ ~(r), FFEBAD)
#define ffetarget_eqv_integer3(res,l,r) (*(res) = (l) ^ ~(r), FFEBAD)
@@ -1447,7 +1246,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
(*(res) = ((l) >= (r)) ? TRUE : FALSE, FFEBAD)
#define ffetarget_ge_integer4(res,l,r) \
(*(res) = ((l) >= (r)) ? TRUE : FALSE, FFEBAD)
-#ifdef REAL_ARITHMETIC
#define ffetarget_ge_real1(res,l,r) \
({ REAL_VALUE_TYPE lr, rr; \
lr = ffetarget_cvt_r1_to_rv_ ((l)); \
@@ -1460,12 +1258,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
rr = ffetarget_cvt_r2_to_rv_ (&((r).v[0])); \
*(res) = REAL_VALUES_LESS (lr, rr) ? FALSE : TRUE; \
FFEBAD; })
-#else
-#define ffetarget_ge_real1(res,l,r) \
- (*(res) = ((l) >= (r)) ? TRUE : FALSE, FFEBAD)
-#define ffetarget_ge_real2(res,l,r) \
- (*(res) = ((l) >= (r)) ? TRUE : FALSE, FFEBAD)
-#endif
#define ffetarget_gt_integer1(res,l,r) \
(*(res) = ((l) > (r)) ? TRUE : FALSE, FFEBAD)
#define ffetarget_gt_integer2(res,l,r) \
@@ -1474,7 +1266,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
(*(res) = ((l) > (r)) ? TRUE : FALSE, FFEBAD)
#define ffetarget_gt_integer4(res,l,r) \
(*(res) = ((l) > (r)) ? TRUE : FALSE, FFEBAD)
-#ifdef REAL_ARITHMETIC
#define ffetarget_gt_real1(res,l,r) \
({ REAL_VALUE_TYPE lr, rr; \
lr = ffetarget_cvt_r1_to_rv_ ((l)); \
@@ -1489,12 +1280,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
*(res) = (REAL_VALUES_LESS (lr, rr) || REAL_VALUES_EQUAL (lr, rr)) \
? FALSE : TRUE; \
FFEBAD; })
-#else
-#define ffetarget_gt_real1(res,l,r) \
- (*(res) = ((l) > (r)) ? TRUE : FALSE, FFEBAD)
-#define ffetarget_gt_real2(res,l,r) \
- (*(res) = ((l) > (r)) ? TRUE : FALSE, FFEBAD)
-#endif
#define ffetarget_hexxmil(v,t) ffetarget_typeless_hex (v, t)
#define ffetarget_hexxvxt(v,t) ffetarget_typeless_hex (v, t)
#define ffetarget_hexzmil(v,t) ffetarget_typeless_hex (v, t)
@@ -1511,7 +1296,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
#define ffetarget_integerdefault_is_magical(i) \
(((unsigned int) i) == FFETARGET_integerBIG_MAGICAL)
#endif
-#ifdef REAL_ARITHMETIC
#define ffetarget_iszero_real1(l) \
({ REAL_VALUE_TYPE lr; \
lr = ffetarget_cvt_r1_to_rv_ ((l)); \
@@ -1522,10 +1306,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
lr = ffetarget_cvt_r2_to_rv_ (&((l).v[0])); \
REAL_VALUES_EQUAL (lr, dconst0); \
})
-#else
-#define ffetarget_iszero_real1(l) ((l) == 0.)
-#define ffetarget_iszero_real2(l) ((l) == 0.)
-#endif
#define ffetarget_iszero_typeless(l) ((l) == 0)
#define ffetarget_logical1(v,truth) (*(v) = truth ? 1 : 0)
#define ffetarget_le_integer1(res,l,r) \
@@ -1536,7 +1316,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
(*(res) = ((l) <= (r)) ? TRUE : FALSE, FFEBAD)
#define ffetarget_le_integer4(res,l,r) \
(*(res) = ((l) <= (r)) ? TRUE : FALSE, FFEBAD)
-#ifdef REAL_ARITHMETIC
#define ffetarget_le_real1(res,l,r) \
({ REAL_VALUE_TYPE lr, rr; \
lr = ffetarget_cvt_r1_to_rv_ ((l)); \
@@ -1551,12 +1330,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
*(res) = (REAL_VALUES_LESS (lr, rr) || REAL_VALUES_EQUAL (lr, rr)) \
? TRUE : FALSE; \
FFEBAD; })
-#else
-#define ffetarget_le_real1(res,l,r) \
- (*(res) = ((l) <= (r)) ? TRUE : FALSE, FFEBAD)
-#define ffetarget_le_real2(res,l,r) \
- (*(res) = ((l) <= (r)) ? TRUE : FALSE, FFEBAD)
-#endif
#define ffetarget_lt_integer1(res,l,r) \
(*(res) = ((l) < (r)) ? TRUE : FALSE, FFEBAD)
#define ffetarget_lt_integer2(res,l,r) \
@@ -1565,7 +1338,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
(*(res) = ((l) < (r)) ? TRUE : FALSE, FFEBAD)
#define ffetarget_lt_integer4(res,l,r) \
(*(res) = ((l) < (r)) ? TRUE : FALSE, FFEBAD)
-#ifdef REAL_ARITHMETIC
#define ffetarget_lt_real1(res,l,r) \
({ REAL_VALUE_TYPE lr, rr; \
lr = ffetarget_cvt_r1_to_rv_ ((l)); \
@@ -1578,28 +1350,16 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
rr = ffetarget_cvt_r2_to_rv_ (&((r).v[0])); \
*(res) = REAL_VALUES_LESS (lr, rr) ? TRUE : FALSE; \
FFEBAD; })
-#else
-#define ffetarget_lt_real1(res,l,r) \
- (*(res) = ((l) < (r)) ? TRUE : FALSE, FFEBAD)
-#define ffetarget_lt_real2(res,l,r) \
- (*(res) = ((l) < (r)) ? TRUE : FALSE, FFEBAD)
-#endif
#define ffetarget_length_character1(c) ((c).length)
#define ffetarget_length_characterdefault ffetarget_length_character1
-#ifdef REAL_ARITHMETIC
#define ffetarget_make_real1(res,lr) \
ffetarget_cvt_rv_to_r1_ ((lr), *(res))
#define ffetarget_make_real2(res,lr) \
ffetarget_cvt_rv_to_r2_ ((lr), &((res)->v[0]))
-#else
-#define ffetarget_make_real1(res,lr) (*(res) = (lr))
-#define ffetarget_make_real2(res,lr) (*(res) = (lr))
-#endif
#define ffetarget_multiply_integer1(res,l,r) (*(res) = (l) * (r), FFEBAD)
#define ffetarget_multiply_integer2(res,l,r) (*(res) = (l) * (r), FFEBAD)
#define ffetarget_multiply_integer3(res,l,r) (*(res) = (l) * (r), FFEBAD)
#define ffetarget_multiply_integer4(res,l,r) (*(res) = (l) * (r), FFEBAD)
-#ifdef REAL_ARITHMETIC
#define ffetarget_multiply_real1(res,l,r) \
({ REAL_VALUE_TYPE lr, rr, resr; \
lr = ffetarget_cvt_r1_to_rv_ ((l)); \
@@ -1614,11 +1374,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
REAL_ARITHMETIC (resr, MULT_EXPR, lr, rr); \
ffetarget_cvt_rv_to_r2_ (resr, &((res)->v[0])); \
FFEBAD; })
-#else
-#define ffetarget_multiply_real1(res,l,r) (*(res) = (l) * (r), FFEBAD)
-#define ffetarget_multiply_real2(res,l,r) (*(res) = (l) * (r), FFEBAD)
-#endif
-#ifdef REAL_ARITHMETIC
#define ffetarget_ne_complex1(res,l,r) \
({ REAL_VALUE_TYPE lr, li, rr, ri; \
lr = ffetarget_cvt_r1_to_rv_ ((l).real); \
@@ -1637,14 +1392,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
*(res) = (REAL_VALUES_EQUAL (lr, rr) && REAL_VALUES_EQUAL (li, ri)) \
? FALSE : TRUE; \
FFEBAD; })
-#else
-#define ffetarget_ne_complex1(res,l,r) \
- (*(res) = (((l).real != (r).real) || ((l).imaginary != (r).imaginary)) \
- ? TRUE : FALSE, FFEBAD)
-#define ffetarget_ne_complex2(res,l,r) \
- (*(res) = (((l).real != (r).real) || ((l).imaginary != (r).imaginary)) \
- ? TRUE : FALSE, FFEBAD)
-#endif
#define ffetarget_ne_integer1(res,l,r) \
(*(res) = ((l) != (r)) ? TRUE : FALSE, FFEBAD)
#define ffetarget_ne_integer2(res,l,r) \
@@ -1653,7 +1400,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
(*(res) = ((l) != (r)) ? TRUE : FALSE, FFEBAD)
#define ffetarget_ne_integer4(res,l,r) \
(*(res) = ((l) != (r)) ? TRUE : FALSE, FFEBAD)
-#ifdef REAL_ARITHMETIC
#define ffetarget_ne_real1(res,l,r) \
({ REAL_VALUE_TYPE lr, rr; \
lr = ffetarget_cvt_r1_to_rv_ ((l)); \
@@ -1666,12 +1412,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
rr = ffetarget_cvt_r2_to_rv_ (&((r).v[0])); \
*(res) = REAL_VALUES_EQUAL (lr, rr) ? FALSE : TRUE; \
FFEBAD; })
-#else
-#define ffetarget_ne_real1(res,l,r) \
- (*(res) = ((l) != (r)) ? TRUE : FALSE, FFEBAD)
-#define ffetarget_ne_real2(res,l,r) \
- (*(res) = ((l) != (r)) ? TRUE : FALSE, FFEBAD)
-#endif
#define ffetarget_neqv_integer1(res,l,r) (*(res) = (l) ^ (r), FFEBAD)
#define ffetarget_neqv_integer2(res,l,r) (*(res) = (l) ^ (r), FFEBAD)
#define ffetarget_neqv_integer3(res,l,r) (*(res) = (l) ^ (r), FFEBAD)
@@ -1727,51 +1467,30 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
fprintf ((f), "%" ffetargetLogical4_f "d", (v))
#define ffetarget_print_octalmil(f,v) ffetarget_print_octal(f,v)
#define ffetarget_print_octalvxt(f,v) ffetarget_print_octal(f,v)
-#ifdef REAL_ARITHMETIC
#define ffetarget_print_real1(f,l) \
({ REAL_VALUE_TYPE lr; \
lr = ffetarget_cvt_r1_to_rv_ ((l)); \
- REAL_VALUE_TO_DECIMAL (lr, bad_fmt_val??, ffetarget_string_); \
+ real_to_decimal (ffetarget_string_, &lr \
+ sizeof(ffetarget_string_), 0, 1); \
fputs (ffetarget_string_, (f)); \
})
#define ffetarget_print_real2(f,l) \
({ REAL_VALUE_TYPE lr; \
lr = ffetarget_cvt_r2_to_rv_ (&((l).v[0])); \
- REAL_VALUE_TO_DECIMAL (lr, bad_fmt_val??, ffetarget_string_); \
+ real_to_decimal (ffetarget_string_, &lr, \
+ sizeof(ffetarget_string_), 0, 1); \
fputs (ffetarget_string_, (f)); \
})
-#else
-#define ffetarget_print_real1(f,v) \
- fprintf ((f), "%" ffetargetReal1_f "g", (v))
-#define ffetarget_print_real2(f,v) \
- fprintf ((f), "%" ffetargetReal2_f "g", (v))
-#endif
-#ifdef REAL_ARITHMETIC
#define ffetarget_real1_one(res) ffetarget_cvt_rv_to_r1_ (dconst1, *(res))
#define ffetarget_real2_one(res) ffetarget_cvt_rv_to_r2_ (dconst1, &((res)->v[0]))
-#else
-#define ffetarget_real1_one(res) (*(res) = (float) 1.)
-#define ffetarget_real2_one(res) (*(res) = 1.)
-#endif
-#ifdef REAL_ARITHMETIC
#define ffetarget_real1_two(res) ffetarget_cvt_rv_to_r1_ (dconst2, *(res))
#define ffetarget_real2_two(res) ffetarget_cvt_rv_to_r2_ (dconst2, &((res)->v[0]))
-#else
-#define ffetarget_real1_two(res) (*(res) = (float) 2.)
-#define ffetarget_real2_two(res) (*(res) = 2.)
-#endif
-#ifdef REAL_ARITHMETIC
#define ffetarget_real1_zero(res) ffetarget_cvt_rv_to_r1_ (dconst0, *(res))
#define ffetarget_real2_zero(res) ffetarget_cvt_rv_to_r2_ (dconst0, &((res)->v[0]))
-#else
-#define ffetarget_real1_zero(res) (*(res) = (float) 0.)
-#define ffetarget_real2_zero(res) (*(res) = 0.)
-#endif
#define ffetarget_size_typeless_binary(t) ((ffetarget_num_digits_(t) + 7) / 8)
#define ffetarget_size_typeless_octal(t) \
((ffetarget_num_digits_(t) * 3 + 7) / 8)
#define ffetarget_size_typeless_hex(t) ((ffetarget_num_digits_(t) + 1) / 2)
-#ifdef REAL_ARITHMETIC
#define ffetarget_subtract_complex1(res,l,r) \
({ REAL_VALUE_TYPE lr, li, rr, ri, resr, resi; \
lr = ffetarget_cvt_r1_to_rv_ ((l).real); \
@@ -1794,19 +1513,10 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_cvt_rv_to_r2_ (resr, &((res)->real.v[0])); \
ffetarget_cvt_rv_to_r2_ (resi, &((res)->imaginary.v[0])); \
FFEBAD; })
-#else
-#define ffetarget_subtract_complex1(res,l,r) \
- ((res)->real = (l).real - (r).real, \
- (res)->imaginary = (l).imaginary - (r).imaginary, FFEBAD)
-#define ffetarget_subtract_complex2(res,l,r) \
- ((res)->real = (l).real - (r).real, \
- (res)->imaginary = (l).imaginary - (r).imaginary, FFEBAD)
-#endif
#define ffetarget_subtract_integer1(res,l,r) (*(res) = (l) - (r), FFEBAD)
#define ffetarget_subtract_integer2(res,l,r) (*(res) = (l) - (r), FFEBAD)
#define ffetarget_subtract_integer3(res,l,r) (*(res) = (l) - (r), FFEBAD)
#define ffetarget_subtract_integer4(res,l,r) (*(res) = (l) - (r), FFEBAD)
-#ifdef REAL_ARITHMETIC
#define ffetarget_subtract_real1(res,l,r) \
({ REAL_VALUE_TYPE lr, rr, resr; \
lr = ffetarget_cvt_r1_to_rv_ ((l)); \
@@ -1821,10 +1531,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
REAL_ARITHMETIC (resr, MINUS_EXPR, lr, rr); \
ffetarget_cvt_rv_to_r2_ (resr, &((res)->v[0])); \
FFEBAD; })
-#else
-#define ffetarget_subtract_real1(res,l,r) (*(res) = (l) - (r), FFEBAD)
-#define ffetarget_subtract_real2(res,l,r) (*(res) = (l) - (r), FFEBAD)
-#endif
#define ffetarget_terminate_0()
#define ffetarget_terminate_1()
#define ffetarget_terminate_2()
@@ -1832,7 +1538,6 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
#define ffetarget_terminate_4()
#define ffetarget_text_character1(c) ((c).text)
#define ffetarget_text_characterdefault ffetarget_text_character1
-#ifdef REAL_ARITHMETIC
#define ffetarget_uminus_complex1(res,l) \
({ REAL_VALUE_TYPE lr, li, resr, resi; \
lr = ffetarget_cvt_r1_to_rv_ ((l).real); \
@@ -1851,17 +1556,10 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
ffetarget_cvt_rv_to_r2_ (resr, &((res)->real.v[0])); \
ffetarget_cvt_rv_to_r2_ (resi, &((res)->imaginary.v[0])); \
FFEBAD; })
-#else
-#define ffetarget_uminus_complex1(res,l) \
- ((res)->real = -(l).real, (res)->imaginary = -(l).imaginary, FFEBAD)
-#define ffetarget_uminus_complex2(res,l) \
- ((res)->real = -(l).real, (res)->imaginary = -(l).imaginary, FFEBAD)
-#endif
#define ffetarget_uminus_integer1(res,l) (*(res) = -(l), FFEBAD)
#define ffetarget_uminus_integer2(res,l) (*(res) = -(l), FFEBAD)
#define ffetarget_uminus_integer3(res,l) (*(res) = -(l), FFEBAD)
#define ffetarget_uminus_integer4(res,l) (*(res) = -(l), FFEBAD)
-#ifdef REAL_ARITHMETIC
#define ffetarget_uminus_real1(res,l) \
({ REAL_VALUE_TYPE lr, resr; \
lr = ffetarget_cvt_r1_to_rv_ ((l)); \
@@ -1874,17 +1572,8 @@ void *ffetarget_memcpy_ (void *dst, void *src, size_t len);
resr = REAL_VALUE_NEGATE (lr); \
ffetarget_cvt_rv_to_r2_ (resr, &((res)->v[0])); \
FFEBAD; })
-#else
-#define ffetarget_uminus_real1(res,l) (*(res) = -(l), FFEBAD)
-#define ffetarget_uminus_real2(res,l) (*(res) = -(l), FFEBAD)
-#endif
-#ifdef REAL_ARITHMETIC
#define ffetarget_value_real1(lr) ffetarget_cvt_r1_to_rv_ ((lr))
#define ffetarget_value_real2(lr) ffetarget_cvt_r2_to_rv_ (&((lr).v[0]))
-#else
-#define ffetarget_value_real1
-#define ffetarget_value_real2
-#endif
#define ffetarget_xor_integer1(res,l,r) (*(res) = (l) ^ (r), FFEBAD)
#define ffetarget_xor_integer2(res,l,r) (*(res) = (l) ^ (r), FFEBAD)
#define ffetarget_xor_integer3(res,l,r) (*(res) = (l) ^ (r), FFEBAD)
diff --git a/contrib/gcc/f/top.c b/contrib/gcc/f/top.c
index 774f29f..6a789e3 100644
--- a/contrib/gcc/f/top.c
+++ b/contrib/gcc/f/top.c
@@ -58,7 +58,6 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* Externals defined here. */
-int flag_traditional; /* Shouldn't need this (C front end only)! */
bool ffe_is_do_internal_checks_ = FALSE;
bool ffe_is_90_ = FFETARGET_defaultIS_90;
bool ffe_is_automatic_ = FFETARGET_defaultIS_AUTOMATIC;
diff --git a/contrib/gcc/f/where.c b/contrib/gcc/f/where.c
index 9f85354..b16f965 100644
--- a/contrib/gcc/f/where.c
+++ b/contrib/gcc/f/where.c
@@ -1,5 +1,5 @@
/* where.c -- Implementation File (module.c template V1.0)
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 2002 Free Software Foundation, Inc.
Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -53,7 +53,7 @@ typedef struct _ffewhere_ll_ *ffewhereLL_;
/* Internal structure definitions. */
-struct _ffewhere_ll_
+struct _ffewhere_ll_ GTY (())
{
ffewhereLL_ next;
ffewhereLL_ previous;
@@ -62,7 +62,7 @@ struct _ffewhere_ll_
ffewhereLineNumber offset; /* User-desired offset (usually 1). */
};
-struct _ffewhere_root_ll_
+struct _ffewhere_root_ll_ GTY (())
{
ffewhereLL_ first;
ffewhereLL_ last;
@@ -77,7 +77,7 @@ struct _ffewhere_root_line_
/* Static objects accessed by functions in this module. */
-static struct _ffewhere_root_ll_ ffewhere_root_ll_;
+static GTY (()) struct _ffewhere_root_ll_ *ffewhere_root_ll_;
static struct _ffewhere_root_line_ ffewhere_root_line_;
/* Static functions (internal). */
@@ -95,10 +95,10 @@ ffewhere_ll_lookup_ (ffewhereLineNumber ln)
ffewhereLL_ ll;
if (ln == 0)
- return ffewhere_root_ll_.first;
+ return ffewhere_root_ll_->first;
- for (ll = ffewhere_root_ll_.last;
- ll != (ffewhereLL_) &ffewhere_root_ll_.first;
+ for (ll = ffewhere_root_ll_->last;
+ ll != (ffewhereLL_) &ffewhere_root_ll_->first;
ll = ll->previous)
{
if (ll->line_no <= ln)
@@ -109,97 +109,17 @@ ffewhere_ll_lookup_ (ffewhereLineNumber ln)
return NULL;
}
-/* A somewhat evil way to prevent the garbage collector
- from collecting 'file' structures. */
-#define NUM_FFEWHERE_HEAD_FILES 31
-static struct ffewhere_ggc_tracker
-{
- struct ffewhere_ggc_tracker *next;
- ffewhereFile files[NUM_FFEWHERE_HEAD_FILES];
-} *ffewhere_head = NULL;
-
-static void
-mark_ffewhere_head (void *arg)
-{
- struct ffewhere_ggc_tracker *head;
- int i;
-
- for (head = * (struct ffewhere_ggc_tracker **) arg;
- head != NULL;
- head = head->next)
- {
- ggc_mark (head);
- for (i = 0; i < NUM_FFEWHERE_HEAD_FILES; i++)
- ggc_mark (head->files[i]);
- }
-}
-
-
-/* Kill file object.
-
- Note that this object must not have been passed in a call
- to any other ffewhere function except ffewhere_file_name and
- ffewhere_file_namelen. */
-
-void
-ffewhere_file_kill (ffewhereFile wf)
-{
- struct ffewhere_ggc_tracker *head;
- int i;
-
- for (head = ffewhere_head; head != NULL; head = head->next)
- for (i = 0; i < NUM_FFEWHERE_HEAD_FILES; i++)
- if (head->files[i] == wf)
- {
- head->files[i] = NULL;
- return;
- }
- /* Called on a file that has already been deallocated... */
- abort();
-}
-
/* Create file object. */
ffewhereFile
ffewhere_file_new (const char *name, size_t length)
{
ffewhereFile wf;
- int filepos;
-
- wf = ggc_alloc (offsetof (struct _ffewhere_file_, text)
- + length + 1);
+ wf = ggc_alloc (offsetof (struct _ffewhere_file_, text) + length + 1);
wf->length = length;
memcpy (&wf->text[0], name, length);
wf->text[length] = '\0';
- if (ffewhere_head == NULL)
- {
- ggc_add_root (&ffewhere_head, 1, sizeof ffewhere_head,
- mark_ffewhere_head);
- filepos = NUM_FFEWHERE_HEAD_FILES;
- }
- else
- {
- for (filepos = 0; filepos < NUM_FFEWHERE_HEAD_FILES; filepos++)
- if (ffewhere_head->files[filepos] == NULL)
- {
- ffewhere_head->files[filepos] = wf;
- break;
- }
- }
- if (filepos == NUM_FFEWHERE_HEAD_FILES)
- {
- /* Need to allocate a new block. */
- struct ffewhere_ggc_tracker *old_head = ffewhere_head;
- int i;
-
- ffewhere_head = ggc_alloc (sizeof (*ffewhere_head));
- ffewhere_head->next = old_head;
- ffewhere_head->files[0] = wf;
- for (i = 1; i < NUM_FFEWHERE_HEAD_FILES; i++)
- ffewhere_head->files[i] = NULL;
- }
-
return wf;
}
@@ -211,10 +131,9 @@ void
ffewhere_file_set (ffewhereFile wf, bool have_num, ffewhereLineNumber ln)
{
ffewhereLL_ ll;
-
- ll = malloc_new_kp (ffe_pool_file (), "ffewhereLL_", sizeof (*ll));
- ll->next = (ffewhereLL_) &ffewhere_root_ll_.first;
- ll->previous = ffewhere_root_ll_.last;
+ ll = ggc_alloc (sizeof (*ll));
+ ll->next = (ffewhereLL_) &ffewhere_root_ll_->first;
+ ll->previous = ffewhere_root_ll_->last;
ll->next->previous = ll;
ll->previous->next = ll;
if (wf == NULL)
@@ -248,8 +167,12 @@ ffewhere_init_1 ()
= (ffewhereLine) &ffewhere_root_line_.first;
ffewhere_root_line_.none = 0;
- ffewhere_root_ll_.first = ffewhere_root_ll_.last
- = (ffewhereLL_) &ffewhere_root_ll_.first;
+ /* The sentinel is (must be) GGC-allocated. It is accessed as a
+ struct _ffewhere_ll_/ffewhereLL_ though its type contains just the
+ first two fields (layout-wise). */
+ ffewhere_root_ll_ = ggc_alloc_cleared (sizeof (struct _ffewhere_ll_));
+ ffewhere_root_ll_->first = ffewhere_root_ll_->last
+ = (ffewhereLL_) &ffewhere_root_ll_->first;
}
/* Return the textual content of the line. */
@@ -500,22 +423,11 @@ ffewhere_track (ffewhereLine *wl, ffewhereColumn *wc, ffewhereTrack wt,
else
{
wt[i * 2 - 2] = lo;
- if (cn > FFEWHERE_indexUNKNOWN)
- {
- wt[i * 2 - 1] = FFEWHERE_indexUNKNOWN;
- ffewhere_line_kill (*wl);
- ffewhere_column_kill (*wc);
- *wl = ffewhere_line_unknown ();
- *wc = ffewhere_column_unknown ();
- }
- else
- {
- wt[i * 2 - 1] = cn - 1;
- ffewhere_line_kill (*wl);
- ffewhere_column_kill (*wc);
- *wl = ffewhere_line_use (ffewhere_line_new (ln));
- *wc = ffewhere_column_use (ffewhere_column_new (cn));
- }
+ wt[i * 2 - 1] = cn - 1;
+ ffewhere_line_kill (*wl);
+ ffewhere_column_kill (*wc);
+ *wl = ffewhere_line_use (ffewhere_line_new (ln));
+ *wc = ffewhere_column_use (ffewhere_column_new (cn));
}
}
@@ -604,3 +516,5 @@ ffewhere_track_kill (ffewhereLine wrl, ffewhereColumn wrc UNUSED,
}
}
}
+
+#include "gt-f-where.h"
diff --git a/contrib/gcc/f/where.h b/contrib/gcc/f/where.h
index a3adb4b..cce7b2a 100644
--- a/contrib/gcc/f/where.h
+++ b/contrib/gcc/f/where.h
@@ -1,5 +1,5 @@
/* where.h -- Public #include File (module.h template V1.0)
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 2002 Free Software Foundation, Inc.
Contributed by James Craig Burley.
This file is part of GNU Fortran.
@@ -61,12 +61,11 @@ typedef unsigned int ffewhereUses_;
/* Include files needed by this one. */
-#include "glimits.h"
#include "top.h"
/* Structure definitions. */
-struct _ffewhere_file_
+struct _ffewhere_file_ GTY (())
{
size_t length;
char text[1];
@@ -88,7 +87,6 @@ extern struct _ffewhere_line_ ffewhere_unknown_line_;
/* Declare functions with prototypes. */
-void ffewhere_file_kill (ffewhereFile wf);
ffewhereFile ffewhere_file_new (const char *name, size_t length);
void ffewhere_file_set (ffewhereFile wf, bool have_num, ffewhereLineNumber ln);
void ffewhere_init_1 (void);
diff --git a/contrib/gcc/fibheap.c b/contrib/gcc/fibheap.c
index 0ba9b8d..36062d4 100644
--- a/contrib/gcc/fibheap.c
+++ b/contrib/gcc/fibheap.c
@@ -66,7 +66,7 @@ fibnode_new ()
{
fibnode_t node;
- node = xcalloc (1, sizeof *node);
+ node = (fibnode_t) xcalloc (1, sizeof *node);
node->left = node;
node->right = node;
diff --git a/contrib/gcc/fibheap.h b/contrib/gcc/fibheap.h
index d109e4a..fc37f9e 100644
--- a/contrib/gcc/fibheap.h
+++ b/contrib/gcc/fibheap.h
@@ -1,5 +1,5 @@
/* A Fibonacci heap datatype.
- Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Daniel Berlin (dan@cgsoftware.com).
This file is part of GCC.
@@ -40,7 +40,7 @@ Boston, MA 02111-1307, USA. */
#ifndef _FIBHEAP_H_
#define _FIBHEAP_H_
-#include <ansidecl.h>
+#include "ansidecl.h"
typedef long fibheapkey_t;
diff --git a/contrib/gcc/final.c b/contrib/gcc/final.c
index d86ed5e..94a0f4c 100644
--- a/contrib/gcc/final.c
+++ b/contrib/gcc/final.c
@@ -68,6 +68,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "target.h"
#include "debug.h"
#include "expr.h"
+#include "profile.h"
+#include "cfglayout.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data
@@ -98,6 +100,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define JUMP_TABLES_IN_TEXT_SECTION 0
#endif
+#if defined(READONLY_DATA_SECTION) || defined(READONLY_DATA_SECTION_ASM_OP)
+#define HAVE_READONLY_DATA_SECTION 1
+#else
+#define HAVE_READONLY_DATA_SECTION 0
+#endif
+
/* Last insn processed by final_scan_insn. */
static rtx debug_insn;
rtx current_output_insn;
@@ -114,15 +122,12 @@ static int high_function_linenum;
/* Filename of last NOTE. */
static const char *last_filename;
-/* Number of instrumented arcs when profile_arc_flag is set. */
-extern int count_instrumented_edges;
-
extern int length_unit_log; /* This is defined in insn-attrtab.c. */
/* 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. */
-static rtx this_is_asm_operands;
+rtx this_is_asm_operands;
/* Number of operands of this insn, for an `asm' with operands. */
static unsigned int insn_noperands;
@@ -198,6 +203,17 @@ static char *line_note_exists;
rtx current_insn_predicate;
#endif
+struct function_list
+{
+ struct function_list *next; /* next function */
+ const char *name; /* function name */
+ long cfg_checksum; /* function checksum */
+ long count_edges; /* number of intrumented edges in this function */
+};
+
+static struct function_list *functions_head = 0;
+static struct function_list **functions_tail = &functions_head;
+
#ifdef HAVE_ATTR_length
static int asm_insn_count PARAMS ((rtx));
#endif
@@ -206,6 +222,7 @@ static void profile_after_prologue PARAMS ((FILE *));
static void notice_source_line PARAMS ((rtx));
static rtx walk_alter_subreg PARAMS ((rtx *));
static void output_asm_name PARAMS ((void));
+static void output_alternate_entry_point PARAMS ((FILE *, rtx));
static tree get_mem_expr_from_op PARAMS ((rtx, int *));
static void output_asm_operand_names PARAMS ((rtx *, int *, int));
static void output_operand PARAMS ((rtx, int));
@@ -237,137 +254,268 @@ init_final (filename)
}
/* Called at end of source file,
- to output the block-profiling table for this entire compilation. */
+ to output the arc-profiling table for this entire compilation. */
void
end_final (filename)
const char *filename;
{
- if (profile_arc_flag)
+ if (profile_arc_flag && profile_info.count_instrumented_edges)
{
char name[20];
- int align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
- int size, rounded;
- int long_bytes = LONG_TYPE_SIZE / BITS_PER_UNIT;
- int gcov_type_bytes = GCOV_TYPE_SIZE / BITS_PER_UNIT;
- int pointer_bytes = POINTER_SIZE / BITS_PER_UNIT;
- unsigned int align2 = LONG_TYPE_SIZE;
-
- size = gcov_type_bytes * count_instrumented_edges;
- rounded = size;
-
- rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
- rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
- * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
-
- /* ??? This _really_ ought to be done with a structure layout
- and with assemble_constructor. If long_bytes != pointer_bytes
- we'll be emitting unaligned data at some point. */
- if (long_bytes != pointer_bytes)
- abort ();
+ tree string_type, string_cst;
+ tree structure_decl, structure_value, structure_pointer_type;
+ tree field_decl, decl_chain, value_chain;
+ tree sizeof_field_value, domain_type;
- data_section ();
+ /* Build types. */
+ string_type = build_pointer_type (char_type_node);
- /* 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.
- 4: always 0, for compatibility with Sun.
+ /* Libgcc2 bb structure. */
+ structure_decl = make_node (RECORD_TYPE);
+ structure_pointer_type = build_pointer_type (structure_decl);
- The following are GNU extensions:
-
- 5: address of table of start addrs of basic blocks (LPBX3).
- 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.
- 10: space reserved for basic block profiling. */
+ /* Output the main header, of 7 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.
+ 4: always 0, libgcc2 uses this as a pointer to next ``struct bb''
- ASM_OUTPUT_ALIGN (asm_out_file, align);
+ The following are GNU extensions:
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 0);
+ 5: Number of bytes in this header.
+ 6: address of table of function checksums (LPBX7). */
- /* Zero word. */
- assemble_integer (const0_rtx, long_bytes, align2, 1);
+ /* The zero word. */
+ decl_chain =
+ build_decl (FIELD_DECL, get_identifier ("zero_word"),
+ long_integer_type_node);
+ value_chain = build_tree_list (decl_chain,
+ convert (long_integer_type_node,
+ integer_zero_node));
/* Address of filename. */
- ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 1);
- assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes,
- align2, 1);
+ {
+ char *cwd, *da_filename;
+ int da_filename_len;
+
+ field_decl =
+ build_decl (FIELD_DECL, get_identifier ("filename"), string_type);
+ TREE_CHAIN (field_decl) = decl_chain;
+ decl_chain = field_decl;
+
+ cwd = getpwd ();
+ da_filename_len = strlen (filename) + strlen (cwd) + 4 + 1;
+ da_filename = (char *) alloca (da_filename_len);
+ strcpy (da_filename, cwd);
+ strcat (da_filename, "/");
+ strcat (da_filename, filename);
+ strcat (da_filename, ".da");
+ da_filename_len = strlen (da_filename);
+ string_cst = build_string (da_filename_len + 1, da_filename);
+ domain_type = build_index_type (build_int_2 (da_filename_len, 0));
+ TREE_TYPE (string_cst)
+ = build_array_type (char_type_node, domain_type);
+ value_chain = tree_cons (field_decl,
+ build1 (ADDR_EXPR, string_type, string_cst),
+ value_chain);
+ }
- /* Address of count table. */
- ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
- assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes,
- align2, 1);
+ /* Table of counts. */
+ {
+ tree gcov_type_type = make_unsigned_type (GCOV_TYPE_SIZE);
+ tree gcov_type_pointer_type = build_pointer_type (gcov_type_type);
+ tree domain_tree
+ = build_index_type (build_int_2 (profile_info.
+ count_instrumented_edges - 1, 0));
+ tree gcov_type_array_type
+ = build_array_type (gcov_type_type, domain_tree);
+ tree gcov_type_array_pointer_type
+ = build_pointer_type (gcov_type_array_type);
+ tree counts_table;
+
+ field_decl =
+ build_decl (FIELD_DECL, get_identifier ("counts"),
+ gcov_type_pointer_type);
+ TREE_CHAIN (field_decl) = decl_chain;
+ decl_chain = field_decl;
+
+ /* No values. */
+ counts_table
+ = build (VAR_DECL, gcov_type_array_type, NULL_TREE, NULL_TREE);
+ TREE_STATIC (counts_table) = 1;
+ ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
+ DECL_NAME (counts_table) = get_identifier (name);
+ assemble_variable (counts_table, 0, 0, 0);
+
+ value_chain = tree_cons (field_decl,
+ build1 (ADDR_EXPR,
+ gcov_type_array_pointer_type,
+ counts_table), value_chain);
+ }
/* Count of the # of instrumented arcs. */
- assemble_integer (GEN_INT (count_instrumented_edges),
- long_bytes, align2, 1);
+ field_decl
+ = build_decl (FIELD_DECL, get_identifier ("ncounts"),
+ long_integer_type_node);
+ TREE_CHAIN (field_decl) = decl_chain;
+ decl_chain = field_decl;
+
+ value_chain = tree_cons (field_decl,
+ convert (long_integer_type_node,
+ build_int_2 (profile_info.
+ count_instrumented_edges,
+ 0)), value_chain);
+ /* Pointer to the next bb. */
+ field_decl
+ = build_decl (FIELD_DECL, get_identifier ("next"),
+ structure_pointer_type);
+ TREE_CHAIN (field_decl) = decl_chain;
+ decl_chain = field_decl;
+
+ value_chain = tree_cons (field_decl, null_pointer_node, value_chain);
+
+ /* sizeof(struct bb). We'll set this after entire structure
+ is laid out. */
+ field_decl
+ = build_decl (FIELD_DECL, get_identifier ("sizeof_bb"),
+ long_integer_type_node);
+ TREE_CHAIN (field_decl) = decl_chain;
+ decl_chain = field_decl;
+
+ sizeof_field_value = tree_cons (field_decl, NULL, value_chain);
+ value_chain = sizeof_field_value;
+
+ /* struct bb_function []. */
+ {
+ struct function_list *item;
+ int num_nodes;
+ tree checksum_field, arc_count_field, name_field;
+ tree domain;
+ tree array_value_chain = NULL_TREE;
+ tree bb_fn_struct_type;
+ tree bb_fn_struct_array_type;
+ tree bb_fn_struct_array_pointer_type;
+ tree bb_fn_struct_pointer_type;
+ tree field_value, field_value_chain;
- /* Zero word (link field). */
- assemble_integer (const0_rtx, pointer_bytes, align2, 1);
+ bb_fn_struct_type = make_node (RECORD_TYPE);
- assemble_integer (const0_rtx, pointer_bytes, align2, 1);
+ checksum_field = build_decl (FIELD_DECL, get_identifier ("checksum"),
+ long_integer_type_node);
- /* Byte count for extended structure. */
- assemble_integer (GEN_INT (11 * UNITS_PER_WORD), long_bytes, align2, 1);
+ arc_count_field
+ = build_decl (FIELD_DECL, get_identifier ("arc_count"),
+ integer_type_node);
+ TREE_CHAIN (checksum_field) = arc_count_field;
- /* Address of function name table. */
- assemble_integer (const0_rtx, pointer_bytes, align2, 1);
+ name_field
+ = build_decl (FIELD_DECL, get_identifier ("name"), string_type);
+ TREE_CHAIN (arc_count_field) = name_field;
- /* Address of line number and filename tables if debugging. */
- assemble_integer (const0_rtx, pointer_bytes, align2, 1);
- assemble_integer (const0_rtx, pointer_bytes, align2, 1);
+ TYPE_FIELDS (bb_fn_struct_type) = checksum_field;
- /* Space for extension ptr (link field). */
- assemble_integer (const0_rtx, UNITS_PER_WORD, align2, 1);
+ num_nodes = 0;
- /* Output the file name changing the suffix to .d for
- Sun tcov compatibility. */
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 1);
- {
- char *cwd = getpwd ();
- int len = strlen (filename) + strlen (cwd) + 1;
- char *data_file = (char *) alloca (len + 4);
-
- strcpy (data_file, cwd);
- strcat (data_file, "/");
- strcat (data_file, filename);
- strip_off_ending (data_file, len);
- strcat (data_file, ".da");
- assemble_string (data_file, strlen (data_file) + 1);
+ for (item = functions_head; item != 0; item = item->next)
+ num_nodes++;
+
+ /* Note that the array contains a terminator, hence no - 1. */
+ domain = build_index_type (build_int_2 (num_nodes, 0));
+
+ bb_fn_struct_pointer_type = build_pointer_type (bb_fn_struct_type);
+ bb_fn_struct_array_type
+ = build_array_type (bb_fn_struct_type, domain);
+ bb_fn_struct_array_pointer_type
+ = build_pointer_type (bb_fn_struct_array_type);
+
+ layout_type (bb_fn_struct_type);
+ layout_type (bb_fn_struct_pointer_type);
+ layout_type (bb_fn_struct_array_type);
+ layout_type (bb_fn_struct_array_pointer_type);
+
+ for (item = functions_head; item != 0; item = item->next)
+ {
+ size_t name_len;
+
+ /* create constructor for structure. */
+ field_value_chain
+ = build_tree_list (checksum_field,
+ convert (long_integer_type_node,
+ build_int_2 (item->cfg_checksum, 0)));
+ field_value_chain
+ = tree_cons (arc_count_field,
+ convert (integer_type_node,
+ build_int_2 (item->count_edges, 0)),
+ field_value_chain);
+
+ name_len = strlen (item->name);
+ string_cst = build_string (name_len + 1, item->name);
+ domain_type = build_index_type (build_int_2 (name_len, 0));
+ TREE_TYPE (string_cst)
+ = build_array_type (char_type_node, domain_type);
+ field_value_chain = tree_cons (name_field,
+ build1 (ADDR_EXPR, string_type,
+ string_cst),
+ field_value_chain);
+
+ /* Add to chain. */
+ array_value_chain
+ = tree_cons (NULL_TREE, build (CONSTRUCTOR,
+ bb_fn_struct_type, NULL_TREE,
+ nreverse (field_value_chain)),
+ array_value_chain);
+ }
+
+ /* Add terminator. */
+ field_value = build_tree_list (arc_count_field,
+ convert (integer_type_node,
+ build_int_2 (-1, 0)));
+
+ array_value_chain = tree_cons (NULL_TREE,
+ build (CONSTRUCTOR, bb_fn_struct_type,
+ NULL_TREE, field_value),
+ array_value_chain);
+
+
+ /* Create constructor for array. */
+ field_decl
+ = build_decl (FIELD_DECL, get_identifier ("function_infos"),
+ bb_fn_struct_pointer_type);
+ value_chain = tree_cons (field_decl,
+ build1 (ADDR_EXPR,
+ bb_fn_struct_array_pointer_type,
+ build (CONSTRUCTOR,
+ bb_fn_struct_array_type,
+ NULL_TREE,
+ nreverse
+ (array_value_chain))),
+ value_chain);
+ TREE_CHAIN (field_decl) = decl_chain;
+ decl_chain = field_decl;
}
- /* Make space for the table of counts. */
- if (size == 0)
- {
- /* Realign data section. */
- ASM_OUTPUT_ALIGN (asm_out_file, align);
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 2);
- if (size != 0)
- assemble_zeros (size);
- }
- else
- {
- ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
-#ifdef ASM_OUTPUT_SHARED_LOCAL
- if (flag_shared_data)
- 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
- }
+ /* Finish structure. */
+ TYPE_FIELDS (structure_decl) = nreverse (decl_chain);
+ layout_type (structure_decl);
+
+ structure_value
+ = build (VAR_DECL, structure_decl, NULL_TREE, NULL_TREE);
+ DECL_INITIAL (structure_value)
+ = build (CONSTRUCTOR, structure_decl, NULL_TREE,
+ nreverse (value_chain));
+ TREE_STATIC (structure_value) = 1;
+ ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
+ DECL_NAME (structure_value) = get_identifier (name);
+
+ /* Size of this structure. */
+ TREE_VALUE (sizeof_field_value)
+ = convert (long_integer_type_node,
+ build_int_2 (int_size_in_bytes (structure_decl), 0));
+
+ /* Build structure. */
+ assemble_variable (structure_value, 0, 0, 0);
}
}
@@ -438,9 +586,7 @@ dbr_sequence_length ()
static int *insn_lengths;
-#ifdef HAVE_ATTR_length
varray_type insn_addresses_;
-#endif
/* Max uid for which the above arrays are valid. */
static int insn_lengths_max_uid;
@@ -527,7 +673,7 @@ get_attr_length (insn)
case JUMP_INSN:
body = PATTERN (insn);
- if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
+ if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
{
/* Alignment is machine-dependent and should be handled by
ADDR_VEC_ALIGN. */
@@ -787,8 +933,8 @@ insn_current_reference_address (branch)
void
compute_alignments ()
{
- int i;
int log, max_skip, max_log;
+ basic_block bb;
if (label_align)
{
@@ -805,9 +951,8 @@ compute_alignments ()
if (! optimize || optimize_size)
return;
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
rtx label = bb->head;
int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0;
edge e;
@@ -837,8 +982,8 @@ compute_alignments ()
if (!has_fallthru
&& (branch_frequency > BB_FREQ_MAX / 10
- || (bb->frequency > BASIC_BLOCK (i - 1)->frequency * 10
- && (BASIC_BLOCK (i - 1)->frequency
+ || (bb->frequency > bb->prev_bb->frequency * 10
+ && (bb->prev_bb->frequency
<= ENTRY_BLOCK_PTR->frequency / 2))))
{
log = JUMP_ALIGN (label);
@@ -849,10 +994,10 @@ compute_alignments ()
}
}
/* In case block is frequent and reached mostly by non-fallthru edge,
- align it. It is most likely an first block of loop. */
+ align it. It is most likely a first block of loop. */
if (has_fallthru
&& branch_frequency + fallthru_frequency > BB_FREQ_MAX / 10
- && branch_frequency > fallthru_frequency * 5)
+ && branch_frequency > fallthru_frequency * 2)
{
log = LOOP_ALIGN (label);
if (max_log < log)
@@ -974,11 +1119,7 @@ shorten_branches (first)
next = NEXT_INSN (insn);
/* ADDR_VECs only take room if read-only data goes into the text
section. */
- if (JUMP_TABLES_IN_TEXT_SECTION
-#if !defined(READONLY_DATA_SECTION)
- || 1
-#endif
- )
+ if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
if (next && GET_CODE (next) == JUMP_INSN)
{
rtx nextbody = PATTERN (next);
@@ -1128,7 +1269,7 @@ shorten_branches (first)
}
}
- INSN_ADDRESSES (uid) = insn_current_address;
+ INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid];
if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER
|| GET_CODE (insn) == CODE_LABEL)
@@ -1141,11 +1282,7 @@ shorten_branches (first)
{
/* This only takes room if read-only data goes into the text
section. */
- if (JUMP_TABLES_IN_TEXT_SECTION
-#if !defined(READONLY_DATA_SECTION)
- || 1
-#endif
- )
+ if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
insn_lengths[uid] = (XVECLEN (body,
GET_CODE (body) == ADDR_DIFF_VEC)
* GET_MODE_SIZE (GET_MODE (body)));
@@ -1346,11 +1483,7 @@ shorten_branches (first)
PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr,
max_addr - rel_addr,
body));
- if (JUMP_TABLES_IN_TEXT_SECTION
-#if !defined(READONLY_DATA_SECTION)
- || 1
-#endif
- )
+ if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
{
insn_lengths[uid]
= (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body)));
@@ -1380,7 +1513,7 @@ shorten_branches (first)
insn_current_address += insn_lengths[inner_uid];
}
- }
+ }
else
insn_current_address += insn_lengths[uid];
@@ -1537,7 +1670,7 @@ final_start_function (first, file, optimize)
if (write_symbols)
{
remove_unnecessary_notes ();
- reorder_blocks ();
+ scope_to_insns_finalize ();
number_blocks (current_function_decl);
/* We never actually put out begin/end notes for the top-level
block in the function. But, conceptually, that block is
@@ -1548,12 +1681,6 @@ final_start_function (first, file, optimize)
/* First output the function prologue: code to set up the stack frame. */
(*targetm.asm_out.function_prologue) (file, get_frame_size ());
-#ifdef VMS_DEBUGGING_INFO
- /* Output label after the prologue of the function. */
- if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
- vmsdbgout_after_prologue ();
-#endif
-
/* If the machine represents the prologue as RTL, the profiling code must
be emitted when NOTE_INSN_PROLOGUE_END is scanned. */
#ifdef HAVE_prologue
@@ -1591,7 +1718,7 @@ profile_function (file)
#ifndef NO_PROFILE_COUNTERS
data_section ();
ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
- ASM_OUTPUT_INTERNAL_LABEL (file, "LP", current_function_profile_label_no);
+ ASM_OUTPUT_INTERNAL_LABEL (file, "LP", current_function_funcdef_no);
assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
#endif
@@ -1621,7 +1748,7 @@ profile_function (file)
#endif
#endif
- FUNCTION_PROFILER (file, current_function_profile_label_no);
+ FUNCTION_PROFILER (file, current_function_funcdef_no);
#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
@@ -1664,12 +1791,12 @@ final_end_function ()
(*targetm.asm_out.function_epilogue) (asm_out_file, get_frame_size ());
/* And debug output. */
- (*debug_hooks->end_epilogue) ();
+ (*debug_hooks->end_epilogue) (last_linenum, last_filename);
#if defined (DWARF2_UNWIND_INFO)
if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG
&& dwarf2out_do_frame ())
- dwarf2out_end_epilogue ();
+ dwarf2out_end_epilogue (last_linenum, last_filename);
#endif
}
@@ -1763,16 +1890,12 @@ final (first, file, optimize, prescan)
#ifdef HAVE_ATTR_length
if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ())
{
-#ifdef STACK_REGS
- /* Irritatingly, the reg-stack pass is creating new instructions
- and because of REG_DEAD note abuse it has to run after
- shorten_branches. Fake address of -1 then. */
- insn_current_address = -1;
-#else
/* This can be triggered by bugs elsewhere in the compiler if
new insns are created after init_insn_lengths is called. */
- abort ();
-#endif
+ if (GET_CODE (insn) == NOTE)
+ insn_current_address = -1;
+ else
+ abort ();
}
else
insn_current_address = INSN_ADDRESSES (INSN_UID (insn));
@@ -1781,6 +1904,23 @@ final (first, file, optimize, prescan)
insn = final_scan_insn (insn, file, optimize, prescan, 0);
}
+ /* Store function names for edge-profiling. */
+ /* ??? Probably should re-use the existing struct function. */
+
+ if (cfun->arc_profile)
+ {
+ struct function_list *new_item = xmalloc (sizeof (struct function_list));
+
+ *functions_tail = new_item;
+ functions_tail = &new_item->next;
+
+ new_item->next = 0;
+ new_item->name = xstrdup (IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (current_function_decl)));
+ new_item->cfg_checksum = profile_info.current_function_cfg_checksum;
+ new_item->count_edges = profile_info.count_edges_instrumented_now;
+ }
+
free (line_note_exists);
line_note_exists = NULL;
}
@@ -1807,6 +1947,39 @@ get_insn_template (code, insn)
}
}
+/* Emit the appropriate declaration for an alternate-entry-point
+ symbol represented by INSN, to FILE. INSN is a CODE_LABEL with
+ LABEL_KIND != LABEL_NORMAL.
+
+ The case fall-through in this function is intentional. */
+static void
+output_alternate_entry_point (file, insn)
+ FILE *file;
+ rtx insn;
+{
+ const char *name = LABEL_NAME (insn);
+
+ switch (LABEL_KIND (insn))
+ {
+ case LABEL_WEAK_ENTRY:
+#ifdef ASM_WEAKEN_LABEL
+ ASM_WEAKEN_LABEL (file, name);
+#endif
+ case LABEL_GLOBAL_ENTRY:
+ (*targetm.asm_out.globalize_label) (file, name);
+ case LABEL_STATIC_ENTRY:
+#ifdef ASM_OUTPUT_TYPE_DIRECTIVE
+ ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
+#endif
+ ASM_OUTPUT_LABEL (file, name);
+ break;
+
+ case LABEL_NORMAL:
+ default:
+ abort ();
+ }
+}
+
/* The final scan for one insn, INSN.
Args are same as in `final', except that INSN
is the insn being scanned.
@@ -1850,9 +2023,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
case NOTE_INSN_LOOP_VTOP:
case NOTE_INSN_FUNCTION_END:
case NOTE_INSN_REPEATED_LINE_NUMBER:
- case NOTE_INSN_RANGE_BEG:
- case NOTE_INSN_RANGE_END:
- case NOTE_INSN_LIVE:
case NOTE_INSN_EXPECTED_VALUE:
break;
@@ -1886,7 +2056,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
case NOTE_INSN_FUNCTION_BEG:
app_disable ();
- (*debug_hooks->end_prologue) (last_linenum);
+ (*debug_hooks->end_prologue) (last_linenum, last_filename);
break;
case NOTE_INSN_BLOCK_BEG:
@@ -2016,8 +2186,12 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip);
#else
+#ifdef ASM_OUTPUT_ALIGN_WITH_NOP
+ ASM_OUTPUT_ALIGN_WITH_NOP (file, align);
+#else
ASM_OUTPUT_ALIGN (file, align);
#endif
+#endif
}
}
#ifdef HAVE_cc0
@@ -2100,17 +2274,14 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
NEXT_INSN (insn));
#else
- if (LABEL_ALTERNATE_NAME (insn))
- ASM_OUTPUT_ALTERNATE_LABEL_NAME (file, insn);
- else
- ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
#endif
#endif
break;
}
}
- if (LABEL_ALTERNATE_NAME (insn))
- ASM_OUTPUT_ALTERNATE_LABEL_NAME (file, insn);
+ if (LABEL_ALT_ENTRY_P (insn))
+ output_alternate_entry_point (file, insn);
else
ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
break;
@@ -2539,13 +2710,13 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
insn_code_number = recog_memoized (insn);
cleanup_subreg_operands (insn);
- /* Dump the insn in the assembly for debugging. */
- if (flag_dump_rtl_in_asm)
- {
- print_rtx_head = ASM_COMMENT_START;
- print_rtl_single (asm_out_file, insn);
- print_rtx_head = "";
- }
+ /* Dump the insn in the assembly for debugging. */
+ if (flag_dump_rtl_in_asm)
+ {
+ print_rtx_head = ASM_COMMENT_START;
+ print_rtl_single (asm_out_file, insn);
+ print_rtx_head = "";
+ }
if (! constrain_operands_cached (1))
fatal_insn_not_found (insn);
@@ -2755,7 +2926,7 @@ alter_subreg (xp)
ORIGINAL_REGNO (x) = ORIGINAL_REGNO (y);
/* This field has a different meaning for REGs and SUBREGs. Make
sure to clear it! */
- x->used = 0;
+ RTX_FLAG (x, used) = 0;
}
else
abort ();
@@ -2970,7 +3141,7 @@ output_operand_lossage VPARAMS ((const char *msgid, ...))
pfx_str = this_is_asm_operands ? _("invalid `asm': ") : "output_operand: ";
asprintf (&fmt_string, "%s%s", pfx_str, _(msgid));
vasprintf (&new_message, fmt_string, ap);
-
+
if (this_is_asm_operands)
error_for_asm (this_is_asm_operands, "%s", new_message);
else
@@ -3768,7 +3939,6 @@ split_double (value, first, second)
}
else
{
-#ifdef REAL_ARITHMETIC
REAL_VALUE_TYPE r;
long l[2];
REAL_VALUE_FROM_CONST_DOUBLE (r, value);
@@ -3797,30 +3967,6 @@ split_double (value, first, second)
*first = GEN_INT ((HOST_WIDE_INT) l[0]);
*second = GEN_INT ((HOST_WIDE_INT) l[1]);
-#else
- if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
- || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
- && ! flag_pretend_float)
- abort ();
-
- if (
-#ifdef HOST_WORDS_BIG_ENDIAN
- WORDS_BIG_ENDIAN
-#else
- ! WORDS_BIG_ENDIAN
-#endif
- )
- {
- /* Host and target agree => no need to swap. */
- *first = GEN_INT (CONST_DOUBLE_LOW (value));
- *second = GEN_INT (CONST_DOUBLE_HIGH (value));
- }
- else
- {
- *second = GEN_INT (CONST_DOUBLE_LOW (value));
- *first = GEN_INT (CONST_DOUBLE_HIGH (value));
- }
-#endif /* no REAL_ARITHMETIC */
}
}
@@ -3865,7 +4011,7 @@ leaf_function_p ()
return 1;
}
-/* Return 1 if branch is an forward branch.
+/* Return 1 if branch is a forward branch.
Uses insn_shuid array, so it works only in the final pass. May be used by
output templates to customary add branch prediction hints.
*/
diff --git a/contrib/gcc/fix-header.c b/contrib/gcc/fix-header.c
index 836e840..bce334d 100644
--- a/contrib/gcc/fix-header.c
+++ b/contrib/gcc/fix-header.c
@@ -372,8 +372,6 @@ int seen_errno = 0;
/* The following are only used when handling stdlib.h */
int seen_EXIT_FAILURE = 0, seen_EXIT_SUCCESS = 0;
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
struct obstack scan_file_obstack;
/* NOTE: If you edit this, also edit gen-protos.c !! */
@@ -411,10 +409,10 @@ int lbrac_line, rbrac_line;
int required_unseen_count = 0;
int required_other = 0;
-static void
+static void
write_lbrac ()
{
-
+
#if ADD_MISSING_EXTERN_C
if (missing_extern_C_count + required_unseen_count > 0)
fprintf (outf, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
@@ -546,7 +544,7 @@ recognized_function (fname, line, kind, have_arg_list)
/* If we have a full prototype, we're done. */
if (have_arg_list)
return;
-
+
if (kind == 'I') /* don't edit inline function */
return;
@@ -619,7 +617,7 @@ read_scan_file (in_fname, argc, argv)
int i;
struct symbol_list *cur_symbols;
- obstack_init (&scan_file_obstack);
+ obstack_init (&scan_file_obstack);
scan_in = cpp_create_reader (CLK_GNUC89);
cb = cpp_get_callbacks (scan_in);
@@ -632,10 +630,9 @@ read_scan_file (in_fname, argc, argv)
options->inhibit_errors = 1;
i = cpp_handle_options (scan_in, argc, argv);
- if (i < argc && ! CPP_FATAL_ERRORS (scan_in))
- cpp_fatal (scan_in, "Invalid option `%s'", argv[i]);
- cpp_post_options (scan_in);
- if (CPP_FATAL_ERRORS (scan_in))
+ if (i < argc)
+ cpp_error (scan_in, DL_ERROR, "invalid option `%s'", argv[i]);
+ if (cpp_errors (scan_in))
exit (FATAL_EXIT_CODE);
if (! cpp_read_main_file (scan_in, in_fname, NULL))
@@ -701,7 +698,7 @@ read_scan_file (in_fname, argc, argv)
if (required_unseen_count + partial_count + required_other
#if ADD_MISSING_EXTERN_C
+ missing_extern_C_count
-#endif
+#endif
== 0)
{
if (verbose)
@@ -1084,8 +1081,8 @@ main (argc, argv)
progname = 0;
for (p = argv[0]; *p; p++)
- if (*p == '/')
- progname = p;
+ if (*p == '/')
+ progname = p;
progname = progname ? progname+1 : argv[0];
}
@@ -1114,7 +1111,7 @@ main (argc, argv)
exit (SUCCESS_EXIT_CODE);
}
}
-
+
}
#endif
@@ -1148,7 +1145,7 @@ main (argc, argv)
else
symbol_table[0].names = NULL;
- /* Count and mark the prototypes required for this include file. */
+ /* Count and mark the prototypes required for this include file. */
for (cur_symbols = &symbol_table[0]; cur_symbols->names; cur_symbols++)
{
int name_len;
@@ -1313,7 +1310,7 @@ v_fatal (str, ap)
fprintf (stderr, "%s: %s: ", progname, inc_filename);
vfprintf (stderr, str, ap);
fprintf (stderr, "\n");
-
+
exit (FATAL_EXIT_CODE);
}
diff --git a/contrib/gcc/fixproto b/contrib/gcc/fixproto
index 3d65cbb..5f84880 100755
--- a/contrib/gcc/fixproto
+++ b/contrib/gcc/fixproto
@@ -4,7 +4,7 @@
# fixproto TARGET-DIR SOURCE-DIR-ALL SOURCE-DIR-STD
#
# COPYRIGHT
-# Copyright (C) 1993, 1994, 1997, 1998 Free Software Foundation, Inc.
+# Copyright (C) 1993, 1994, 1997, 1998, 2002 Free Software Foundation, Inc.
# This file is part of GCC.
#
# GCC is free software; you can redistribute it and/or modify
@@ -56,7 +56,7 @@
dirname=`echo "$0" | sed 's,^[^/]*$,.,;s,//*[^/]*$,,'`
progname=`echo "$0" | sed 's,.*/,,'`
-original_dir=`pwd`
+original_dir=`${PWDCMD-pwd}`
FIX_HEADER=${FIX_HEADER-$original_dir/fix-header}
DEFINES="-D__STDC__=0 -D__cplusplus ${FIXPROTO_DEFINES}"
diff --git a/contrib/gcc/flags.h b/contrib/gcc/flags.h
index 85e0792..0a8979d 100644
--- a/contrib/gcc/flags.h
+++ b/contrib/gcc/flags.h
@@ -1,5 +1,5 @@
/* Compilation switch flag definitions for GCC.
- Copyright (C) 1987, 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+ Copyright (C) 1987, 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002
Free Software Foundation, Inc.
This file is part of GCC.
@@ -126,10 +126,20 @@ extern int warn_unknown_pragmas;
extern int warn_shadow;
-/* Warn if a switch on an enum fails to have a case for every enum value. */
+/* Warn if a switch on an enum, that does not have a default case,
+ fails to have a case for every enum value. */
extern int warn_switch;
+/* Warn if a switch does not have a default case. */
+
+extern int warn_switch_default;
+
+/* Warn if a switch on an enum fails to have a case for every enum
+ value (regardless of the presence or otherwise of a default case). */
+
+extern int warn_switch_enum;
+
/* Nonzero means warn about function definitions that default the return type
or that use a null return and have a return-type other than void. */
@@ -174,6 +184,11 @@ extern int warn_disabled_optimization;
extern int warn_deprecated_decl;
+/* Nonzero means warn about constructs which might not be strict
+ aliasing safe. */
+
+extern int warn_strict_aliasing;
+
/* Nonzero if generating code to do profiling. */
extern int profile_flag;
@@ -194,6 +209,10 @@ extern int flag_branch_probabilities;
extern int flag_reorder_blocks;
+/* Nonzero if functions should be reordered. */
+
+extern int flag_reorder_functions;
+
/* Nonzero if registers should be renamed. */
extern int flag_rename_registers;
@@ -345,6 +364,10 @@ extern int flag_errno_math;
extern int flag_unsafe_math_optimizations;
+/* Nonzero means that no NaNs or +-Infs are expected. */
+
+extern int flag_finite_math_only;
+
/* Zero means that floating-point math operations cannot generate a
(user-visible) trap. This is the case, for example, in nonstop
IEEE 754 arithmetic. */
@@ -408,7 +431,7 @@ extern int flag_schedule_insns_after_reload;
/* The following flags have effect only for scheduling before register
allocation:
- flag_schedule_interblock means schedule insns accross basic blocks.
+ flag_schedule_interblock means schedule insns across basic blocks.
flag_schedule_speculative means allow speculative motion of non-load insns.
flag_schedule_speculative_load means allow speculative motion of some
load insns.
@@ -439,19 +462,13 @@ extern int flag_delayed_branch;
extern int flag_dump_unnumbered;
-/* Nonzero means pretend it is OK to examine bits of target floats,
- even if that isn't true. The resulting code will have incorrect constants,
- but the same series of instructions that the native compiler would make. */
-
-extern int flag_pretend_float;
-
/* Nonzero means change certain warnings into errors.
Usually these are warnings about failure to conform to some standard. */
extern int flag_pedantic_errors;
-/* Nonzero means generate position-independent code.
- This is not fully implemented yet. */
+/* Nonzero means generate position-independent code. 1 vs 2 for a
+ target-dependent "small" or "large" mode. */
extern int flag_pic;
@@ -546,19 +563,10 @@ extern int flag_peephole2;
/* Try to guess branch probablities. */
extern int flag_guess_branch_prob;
-/* -fbounded-pointers causes gcc to compile pointers as composite
- objects occupying three words: the pointer value, the base address
- of the referent object, and the address immediately beyond the end
- of the referent object. The base and extent allow us to perform
- runtime bounds checking. -fbounded-pointers implies -fcheck-bounds. */
-extern int flag_bounded_pointers;
-
/* -fcheck-bounds causes gcc to generate array bounds checks.
- For C, C++: defaults to value of flag_bounded_pointers.
- For ObjC: defaults to off.
+ For C, C++ and ObjC: defaults off.
For Java: defaults to on.
- For Fortran: defaults to off.
- For CHILL: defaults to off. */
+ For Fortran: defaults to off. */
extern int flag_bounds_check;
/* This will attempt to merge constant section constants, if 1 only
@@ -638,11 +646,48 @@ extern int flag_gcse_sm;
extern int flag_eliminate_dwarf2_dups;
-/* Non-zero means to collect statistics which might be expensive
+/* Nonzero means to collect statistics which might be expensive
and to print them when we are done. */
extern int flag_detailed_statistics;
/* Nonzero means enable synchronous exceptions for non-call instructions. */
extern int flag_non_call_exceptions;
+/* Nonzero means put zero initialized data in the bss section. */
+extern int flag_zero_initialized_in_bss;
+
+/* Nonzero means disable transformations observable by signaling NaNs. */
+extern int flag_signaling_nans;
+
+/* A string that's used when a random name is required. NULL means
+ to make it really random. */
+
+extern const char *flag_random_seed;
+
+/* True if the given mode has a NaN representation and the treatment of
+ NaN operands is important. Certain optimizations, such as folding
+ x * 0 into x, are not correct for NaN operands, and are normally
+ disabled for modes with NaNs. The user can ask for them to be
+ done anyway using the -funsafe-math-optimizations switch. */
+#define HONOR_NANS(MODE) \
+ (MODE_HAS_NANS (MODE) && !flag_finite_math_only)
+
+/* Like HONOR_NANs, but true if we honor signaling NaNs (or sNaNs). */
+#define HONOR_SNANS(MODE) (flag_signaling_nans && HONOR_NANS (MODE))
+
+/* As for HONOR_NANS, but true if the mode can represent infinity and
+ the treatment of infinite values is important. */
+#define HONOR_INFINITIES(MODE) \
+ (MODE_HAS_INFINITIES (MODE) && !flag_finite_math_only)
+
+/* Like HONOR_NANS, but true if the given mode distinguishes between
+ postive and negative zero, and the sign of zero is important. */
+#define HONOR_SIGNED_ZEROS(MODE) \
+ (MODE_HAS_SIGNED_ZEROS (MODE) && !flag_unsafe_math_optimizations)
+
+/* Like HONOR_NANS, but true if given mode supports sign-dependent rounding,
+ and the rounding mode is important. */
+#define HONOR_SIGN_DEPENDENT_ROUNDING(MODE) \
+ (MODE_HAS_SIGN_DEPENDENT_ROUNDING (MODE) && !flag_unsafe_math_optimizations)
+
#endif /* ! GCC_FLAGS_H */
diff --git a/contrib/gcc/flow.c b/contrib/gcc/flow.c
index 5b43c6b..3389766 100644
--- a/contrib/gcc/flow.c
+++ b/contrib/gcc/flow.c
@@ -1,6 +1,6 @@
/* Data flow analysis for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -140,9 +140,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "obstack.h"
#include "splay-tree.h"
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
the stack pointer does not matter. The value is tested only in
functions that have frame pointers.
@@ -272,13 +269,16 @@ struct propagate_block_info
/* The length of mem_set_list. */
int mem_set_list_len;
- /* Non-zero if the value of CC0 is live. */
+ /* Nonzero if the value of CC0 is live. */
int cc0_live;
/* Flags controling the set of information propagate_block collects. */
int flags;
};
+/* Number of dead insns removed. */
+static int ndead;
+
/* Maximum length of pbi->mem_set_list before we start dropping
new elements on the floor. */
#define MAX_MEM_SET_LIST_LEN 100
@@ -293,7 +293,7 @@ static void mark_reg PARAMS ((rtx, void *));
static void mark_regs_live_at_end PARAMS ((regset));
static int set_phi_alternative_reg PARAMS ((rtx, int, int, void *));
static void calculate_global_regs_live PARAMS ((sbitmap, sbitmap, int));
-static void propagate_block_delete_insn PARAMS ((basic_block, rtx));
+static void propagate_block_delete_insn PARAMS ((rtx));
static rtx propagate_block_delete_libcall PARAMS ((rtx, rtx));
static int insn_dead_p PARAMS ((struct propagate_block_info *,
rtx, int, rtx));
@@ -335,11 +335,9 @@ void dump_flow_info PARAMS ((FILE *));
void debug_flow_info PARAMS ((void));
static void add_to_mem_set_list PARAMS ((struct propagate_block_info *,
rtx));
-static void invalidate_mems_from_autoinc PARAMS ((struct propagate_block_info *,
- rtx));
+static int invalidate_mems_from_autoinc PARAMS ((rtx *, void *));
static void invalidate_mems_from_set PARAMS ((struct propagate_block_info *,
rtx));
-static void delete_dead_jumptables PARAMS ((void));
static void clear_log_links PARAMS ((sbitmap));
@@ -372,10 +370,14 @@ check_function_return_warnings ()
is no longer in the chain. */
if (INSN_UID (cfun->x_clobber_return_insn) < max_uid)
{
- /* Recompute insn->block mapping, since the initial mapping is
- set before we delete unreachable blocks. */
- if (BLOCK_FOR_INSN (cfun->x_clobber_return_insn) != NULL)
- warning ("control reaches end of non-void function");
+ rtx insn;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (insn == cfun->x_clobber_return_insn)
+ {
+ warning ("control reaches end of non-void function");
+ break;
+ }
}
}
}
@@ -429,6 +431,11 @@ life_analysis (f, file, flags)
SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM);
#endif
+
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ bitmap_initialize (&subregs_of_mode, 1);
+#endif
+
if (! optimize)
flags &= ~(PROP_LOG_LINKS | PROP_AUTOINC | PROP_ALLOW_CFG_CHANGES);
@@ -446,13 +453,12 @@ life_analysis (f, file, flags)
flags &= ~(PROP_REG_INFO | PROP_AUTOINC);
/* We want alias analysis information for local dead store elimination. */
- if (optimize && (flags & PROP_SCAN_DEAD_CODE))
+ if (optimize && (flags & PROP_SCAN_DEAD_STORES))
init_alias_analysis ();
/* Always remove no-op moves. Do this before other processing so
that we don't have to keep re-scanning them. */
delete_noop_moves (f);
- purge_all_dead_edges (false);
/* Some targets can emit simpler epilogues if they know that sp was
not ever modified during the function. After reload, of course,
@@ -477,7 +483,7 @@ life_analysis (f, file, flags)
update_life_info (NULL, UPDATE_LIFE_GLOBAL, flags);
/* Clean up. */
- if (optimize && (flags & PROP_SCAN_DEAD_CODE))
+ if (optimize && (flags & PROP_SCAN_DEAD_STORES))
end_alias_analysis ();
if (file)
@@ -485,23 +491,6 @@ life_analysis (f, file, flags)
free_basic_block_vars (1);
-#ifdef ENABLE_CHECKING
- {
- rtx insn;
-
- /* Search for any REG_LABEL notes which reference deleted labels. */
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- rtx inote = find_reg_note (insn, REG_LABEL, NULL_RTX);
-
- if (inote && GET_CODE (inote) == NOTE_INSN_DELETED_LABEL)
- abort ();
- }
- }
-#endif
-
- rebuild_jump_labels (get_insns ());
-
/* Removing dead insns should've made jumptables really dead. */
delete_dead_jumptables ();
}
@@ -595,7 +584,7 @@ verify_local_live_at_start (new_live_at_start, bb)
EXECUTE_IF_SET_IN_REG_SET (new_live_at_start, 0, i,
{
- /* No registers should die. */
+ /* No registers should die. */
if (REGNO_REG_SET_P (bb->global_live_at_start, i))
{
if (rtl_dump_file)
@@ -607,7 +596,7 @@ verify_local_live_at_start (new_live_at_start, bb)
abort ();
}
- /* Verify that the now-live register is wider than word_mode. */
+ /* Verify that the now-live register is wider than word_mode. */
verify_wide_reg (i, bb);
});
}
@@ -630,7 +619,7 @@ verify_local_live_at_start (new_live_at_start, bb)
Including PROP_REG_INFO does not properly refresh regs_ever_live
unless the caller resets it to zero. */
-void
+int
update_life_info (blocks, extent, prop_flags)
sbitmap blocks;
enum update_life_extent extent;
@@ -640,8 +629,10 @@ update_life_info (blocks, extent, prop_flags)
regset_head tmp_head;
int i;
int stabilized_prop_flags = prop_flags;
+ basic_block bb;
tmp = INITIALIZE_REG_SET (tmp_head);
+ ndead = 0;
timevar_push ((extent == UPDATE_LIFE_LOCAL || blocks)
? TV_LIFE_UPDATE : TV_LIFE);
@@ -652,10 +643,6 @@ update_life_info (blocks, extent, prop_flags)
&& (extent == UPDATE_LIFE_LOCAL || blocks))
abort ();
- /* Clear log links in case we are asked to (re)compute them. */
- if (prop_flags & PROP_LOG_LINKS)
- clear_log_links (blocks);
-
/* For a global update, we go through the relaxation process again. */
if (extent != UPDATE_LIFE_LOCAL)
{
@@ -665,6 +652,7 @@ update_life_info (blocks, extent, prop_flags)
calculate_global_regs_live (blocks, blocks,
prop_flags & (PROP_SCAN_DEAD_CODE
+ | PROP_SCAN_DEAD_STORES
| PROP_ALLOW_CFG_CHANGES));
if ((prop_flags & (PROP_KILL_DEAD_CODE | PROP_ALLOW_CFG_CHANGES))
@@ -673,13 +661,12 @@ update_life_info (blocks, extent, prop_flags)
/* Removing dead code may allow the CFG to be simplified which
in turn may allow for further dead code detection / removal. */
- for (i = n_basic_blocks - 1; i >= 0; --i)
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block bb = BASIC_BLOCK (i);
-
COPY_REG_SET (tmp, bb->global_live_at_end);
changed |= propagate_block (bb, tmp, NULL, NULL,
prop_flags & (PROP_SCAN_DEAD_CODE
+ | PROP_SCAN_DEAD_STORES
| PROP_KILL_DEAD_CODE));
}
@@ -688,7 +675,8 @@ update_life_info (blocks, extent, prop_flags)
removing dead code can affect global register liveness, which
is supposed to be finalized for this call after this loop. */
stabilized_prop_flags
- &= ~(PROP_SCAN_DEAD_CODE | PROP_KILL_DEAD_CODE);
+ &= ~(PROP_SCAN_DEAD_CODE | PROP_SCAN_DEAD_STORES
+ | PROP_KILL_DEAD_CODE);
if (! changed)
break;
@@ -705,11 +693,15 @@ update_life_info (blocks, extent, prop_flags)
count_or_remove_death_notes (blocks, 1);
}
+ /* Clear log links in case we are asked to (re)compute them. */
+ if (prop_flags & PROP_LOG_LINKS)
+ clear_log_links (blocks);
+
if (blocks)
{
EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
{
- basic_block bb = BASIC_BLOCK (i);
+ bb = BASIC_BLOCK (i);
COPY_REG_SET (tmp, bb->global_live_at_end);
propagate_block (bb, tmp, NULL, NULL, stabilized_prop_flags);
@@ -720,10 +712,8 @@ update_life_info (blocks, extent, prop_flags)
}
else
{
- for (i = n_basic_blocks - 1; i >= 0; --i)
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block bb = BASIC_BLOCK (i);
-
COPY_REG_SET (tmp, bb->global_live_at_end);
propagate_block (bb, tmp, NULL, NULL, stabilized_prop_flags);
@@ -765,11 +755,54 @@ update_life_info (blocks, extent, prop_flags)
}
timevar_pop ((extent == UPDATE_LIFE_LOCAL || blocks)
? TV_LIFE_UPDATE : TV_LIFE);
+ if (ndead && rtl_dump_file)
+ fprintf (rtl_dump_file, "deleted %i dead insns\n", ndead);
+ return ndead;
+}
+
+/* Update life information in all blocks where BB_DIRTY is set. */
+
+int
+update_life_info_in_dirty_blocks (extent, prop_flags)
+ enum update_life_extent extent;
+ int prop_flags;
+{
+ sbitmap update_life_blocks = sbitmap_alloc (last_basic_block);
+ int n = 0;
+ basic_block bb;
+ int retval = 0;
+
+ sbitmap_zero (update_life_blocks);
+ FOR_EACH_BB (bb)
+ {
+ if (extent == UPDATE_LIFE_LOCAL)
+ {
+ if (bb->flags & BB_DIRTY)
+ {
+ SET_BIT (update_life_blocks, bb->index);
+ n++;
+ }
+ }
+ else
+ {
+ /* ??? Bootstrap with -march=pentium4 fails to terminate
+ with only a partial life update. */
+ SET_BIT (update_life_blocks, bb->index);
+ if (bb->flags & BB_DIRTY)
+ n++;
+ }
+ }
+
+ if (n)
+ retval = update_life_info (update_life_blocks, extent, prop_flags);
+
+ sbitmap_free (update_life_blocks);
+ return retval;
}
/* Free the variables allocated by find_basic_blocks.
- KEEP_HEAD_END_P is non-zero if basic_block_info is not to be freed. */
+ KEEP_HEAD_END_P is nonzero if basic_block_info is not to be freed. */
void
free_basic_block_vars (keep_head_end_p)
@@ -783,6 +816,7 @@ free_basic_block_vars (keep_head_end_p)
VARRAY_FREE (basic_block_info);
}
n_basic_blocks = 0;
+ last_basic_block = 0;
ENTRY_BLOCK_PTR->aux = NULL;
ENTRY_BLOCK_PTR->global_live_at_end = NULL;
@@ -793,17 +827,16 @@ free_basic_block_vars (keep_head_end_p)
/* Delete any insns that copy a register to itself. */
-void
+int
delete_noop_moves (f)
rtx f ATTRIBUTE_UNUSED;
{
- int i;
rtx insn, next;
basic_block bb;
+ int nnoops = 0;
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- bb = BASIC_BLOCK (i);
for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = next)
{
next = NEXT_INSN (insn);
@@ -826,21 +859,21 @@ delete_noop_moves (f)
XEXP (retval_note, 0) = new_libcall_insn;
}
- /* Do not call delete_insn here since that may change
- the basic block boundaries which upsets some callers. */
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
+ delete_insn_and_edges (insn);
+ nnoops++;
}
}
}
+ if (nnoops && rtl_dump_file)
+ fprintf (rtl_dump_file, "deleted %i noop moves", nnoops);
+ return nnoops;
}
/* Delete any jump tables never referenced. We can't delete them at the
time of removing tablejump insn as they are referenced by the preceding
insns computing the destination, so we delay deleting and garbagecollect
them once life information is computed. */
-static void
+void
delete_dead_jumptables ()
{
rtx insn, next;
@@ -960,7 +993,7 @@ mark_regs_live_at_end (set)
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
/* If they are different, also mark the hard frame pointer as live. */
if (! LOCAL_REGNO (HARD_FRAME_POINTER_REGNUM))
- SET_REGNO_REG_SET (set, HARD_FRAME_POINTER_REGNUM);
+ SET_REGNO_REG_SET (set, HARD_FRAME_POINTER_REGNUM);
#endif
}
@@ -1050,20 +1083,28 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
sbitmap blocks_in, blocks_out;
int flags;
{
- basic_block *queue, *qhead, *qtail, *qend;
- regset tmp, new_live_at_end, call_used;
- regset_head tmp_head, call_used_head;
+ basic_block *queue, *qhead, *qtail, *qend, bb;
+ regset tmp, new_live_at_end, invalidated_by_call;
+ regset_head tmp_head, invalidated_by_call_head;
regset_head new_live_at_end_head;
int i;
+ /* Some passes used to forget clear aux field of basic block causing
+ sick behavior here. */
+#ifdef ENABLE_CHECKING
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ if (bb->aux)
+ abort ();
+#endif
+
tmp = INITIALIZE_REG_SET (tmp_head);
new_live_at_end = INITIALIZE_REG_SET (new_live_at_end_head);
- call_used = INITIALIZE_REG_SET (call_used_head);
+ invalidated_by_call = INITIALIZE_REG_SET (invalidated_by_call_head);
/* Inconveniently, this is only readily available in hard reg set form. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
- if (call_used_regs[i])
- SET_REGNO_REG_SET (call_used, i);
+ if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
+ SET_REGNO_REG_SET (invalidated_by_call, i);
/* Create a worklist. Allocate an extra slot for ENTRY_BLOCK, and one
because the `head == tail' style test for an empty queue doesn't
@@ -1077,22 +1118,17 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
useful work. We use AUX non-null to flag that the block is queued. */
if (blocks_in)
{
- /* Clear out the garbage that might be hanging out in bb->aux. */
- for (i = n_basic_blocks - 1; i >= 0; --i)
- BASIC_BLOCK (i)->aux = NULL;
-
- EXECUTE_IF_SET_IN_SBITMAP (blocks_in, 0, i,
- {
- basic_block bb = BASIC_BLOCK (i);
- *--qhead = bb;
- bb->aux = bb;
- });
+ FOR_EACH_BB (bb)
+ if (TEST_BIT (blocks_in, bb->index))
+ {
+ *--qhead = bb;
+ bb->aux = bb;
+ }
}
else
{
- for (i = 0; i < n_basic_blocks; ++i)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
*--qhead = bb;
bb->aux = bb;
}
@@ -1150,7 +1186,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
if (e->flags & EDGE_EH)
{
bitmap_operation (tmp, sb->global_live_at_start,
- call_used, BITMAP_AND_COMPL);
+ invalidated_by_call, BITMAP_AND_COMPL);
IOR_REG_SET (new_live_at_end, tmp);
}
else
@@ -1318,7 +1354,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
FREE_REG_SET (tmp);
FREE_REG_SET (new_live_at_end);
- FREE_REG_SET (call_used);
+ FREE_REG_SET (invalidated_by_call);
if (blocks_out)
{
@@ -1331,9 +1367,8 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
}
else
{
- for (i = n_basic_blocks - 1; i >= 0; --i)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
FREE_REG_SET (bb->local_set);
FREE_REG_SET (bb->cond_local_set);
}
@@ -1343,7 +1378,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
}
-/* This structure is used to pass parameters to an from the
+/* This structure is used to pass parameters to and from the
the function find_regno_partial(). It is used to pass in the
register number we are looking, as well as to return any rtx
we find. */
@@ -1436,8 +1471,11 @@ initialize_uninitialized_subregs ()
for_each_rtx (&i, find_regno_partial, &param);
if (param.retval != NULL_RTX)
{
- insn = gen_move_insn (param.retval,
- CONST0_RTX (GET_MODE (param.retval)));
+ start_sequence ();
+ emit_move_insn (param.retval,
+ CONST0_RTX (GET_MODE (param.retval)));
+ insn = get_insns ();
+ end_sequence ();
insert_insn_on_edge (insn, e);
did_something = 1;
}
@@ -1459,21 +1497,14 @@ initialize_uninitialized_subregs ()
void
allocate_bb_life_data ()
{
- int i;
+ basic_block bb;
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
{
- basic_block bb = BASIC_BLOCK (i);
-
bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
}
- ENTRY_BLOCK_PTR->global_live_at_end
- = OBSTACK_ALLOC_REG_SET (&flow_obstack);
- EXIT_BLOCK_PTR->global_live_at_start
- = OBSTACK_ALLOC_REG_SET (&flow_obstack);
-
regs_live_at_setjmp = OBSTACK_ALLOC_REG_SET (&flow_obstack);
}
@@ -1504,12 +1535,10 @@ allocate_reg_life_data ()
/* Delete dead instructions for propagate_block. */
static void
-propagate_block_delete_insn (bb, insn)
- basic_block bb;
+propagate_block_delete_insn (insn)
rtx insn;
{
rtx inote = find_reg_note (insn, REG_LABEL, NULL_RTX);
- bool purge = false;
/* If the insn referred to a label, and that label was attached to
an ADDR_VEC, it's safe to delete the ADDR_VEC. In fact, it's
@@ -1519,11 +1548,7 @@ propagate_block_delete_insn (bb, insn)
INSN may reference a deleted label, particularly when a jump
table has been optimized into a direct jump. There's no
real good way to fix up the reference to the deleted label
- when the label is deleted, so we just allow it here.
-
- After dead code elimination is complete, we do search for
- any REG_LABEL notes which reference deleted labels as a
- sanity check. */
+ when the label is deleted, so we just allow it here. */
if (inote && GET_CODE (inote) == CODE_LABEL)
{
@@ -1547,15 +1572,13 @@ propagate_block_delete_insn (bb, insn)
for (i = 0; i < len; i++)
LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0))--;
- delete_insn (next);
+ delete_insn_and_edges (next);
+ ndead++;
}
}
- if (bb->end == insn)
- purge = true;
- delete_insn (insn);
- if (purge)
- purge_dead_edges (bb);
+ delete_insn_and_edges (insn);
+ ndead++;
}
/* Delete dead libcalls for propagate_block. Return the insn
@@ -1568,7 +1591,8 @@ propagate_block_delete_libcall ( insn, note)
rtx first = XEXP (note, 0);
rtx before = PREV_INSN (first);
- delete_insn_chain (first, insn);
+ delete_insn_chain_and_edges (first, insn);
+ ndead++;
return before;
}
@@ -1631,27 +1655,27 @@ propagate_one_insn (pbi, insn)
else
{
- /* If INSN contains a RETVAL note and is dead, but the libcall
- as a whole is not dead, then we want to remove INSN, but
- not the whole libcall sequence.
+ /* If INSN contains a RETVAL note and is dead, but the libcall
+ as a whole is not dead, then we want to remove INSN, but
+ not the whole libcall sequence.
- However, we need to also remove the dangling REG_LIBCALL
- note so that we do not have mis-matched LIBCALL/RETVAL
- notes. In theory we could find a new location for the
- REG_RETVAL note, but it hardly seems worth the effort.
+ However, we need to also remove the dangling REG_LIBCALL
+ note so that we do not have mis-matched LIBCALL/RETVAL
+ notes. In theory we could find a new location for the
+ REG_RETVAL note, but it hardly seems worth the effort.
- NOTE at this point will be the RETVAL note if it exists. */
+ NOTE at this point will be the RETVAL note if it exists. */
if (note)
{
rtx libcall_note;
-
+
libcall_note
= find_reg_note (XEXP (note, 0), REG_LIBCALL, NULL_RTX);
remove_note (XEXP (note, 0), libcall_note);
}
/* Similarly if INSN contains a LIBCALL note, remove the
- dangling REG_RETVAL note. */
+ dnagling REG_RETVAL note. */
note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
if (note)
{
@@ -1663,7 +1687,7 @@ propagate_one_insn (pbi, insn)
}
/* Now delete INSN. */
- propagate_block_delete_insn (pbi->bb, insn);
+ propagate_block_delete_insn (insn);
}
return prev;
@@ -1713,8 +1737,9 @@ propagate_one_insn (pbi, insn)
/* We have an insn to pop a constant amount off the stack.
(Such insns use PLUS regardless of the direction of the stack,
and any insn to adjust the stack by a constant is always a pop.)
- These insns, if not dead stores, have no effect on life. */
- ;
+ These insns, if not dead stores, have no effect on life, though
+ they do have an effect on the memory stores we are tracking. */
+ invalidate_mems_from_set (pbi, stack_pointer_rtx);
else
{
rtx note;
@@ -1739,12 +1764,16 @@ propagate_one_insn (pbi, insn)
if (GET_CODE (PATTERN (insn)) == COND_EXEC)
cond = COND_EXEC_TEST (PATTERN (insn));
- /* Non-constant calls clobber memory. */
+ /* Non-constant calls clobber memory, constant calls do not
+ clobber memory, though they may clobber outgoing arguments
+ on the stack. */
if (! CONST_OR_PURE_CALL_P (insn))
{
free_EXPR_LIST_list (&pbi->mem_set_list);
pbi->mem_set_list_len = 0;
}
+ else
+ invalidate_mems_from_set (pbi, stack_pointer_rtx);
/* There may be extra registers to be clobbered. */
for (note = CALL_INSN_FUNCTION_USAGE (insn);
@@ -1759,8 +1788,7 @@ propagate_one_insn (pbi, insn)
if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
{
/* We do not want REG_UNUSED notes for these registers. */
- mark_set_1 (pbi, CLOBBER, gen_rtx_REG (reg_raw_mode[i], i),
- cond, insn,
+ mark_set_1 (pbi, CLOBBER, regno_reg_rtx[i], cond, insn,
pbi->flags & ~(PROP_DEATH_NOTES | PROP_REG_INFO));
}
}
@@ -1808,8 +1836,7 @@ propagate_one_insn (pbi, insn)
so they are made live. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (global_regs[i])
- mark_used_reg (pbi, gen_rtx_REG (reg_raw_mode[i], i),
- cond, insn);
+ mark_used_reg (pbi, regno_reg_rtx[i], cond, insn);
}
}
@@ -1953,7 +1980,7 @@ init_propagate_block_info (bb, live, local_set, cond_local_set, flags)
&& ! (TREE_CODE (TREE_TYPE (current_function_decl)) == FUNCTION_TYPE
&& (TYPE_RETURNS_STACK_DEPRESSED
(TREE_TYPE (current_function_decl))))
- && (flags & PROP_SCAN_DEAD_CODE)
+ && (flags & PROP_SCAN_DEAD_STORES)
&& (bb->succ == NULL
|| (bb->succ->succ_next == NULL
&& bb->succ->dest == EXIT_BLOCK_PTR
@@ -2023,7 +2050,7 @@ free_propagate_block_info (pbi)
case, the resulting set will be equal to the union of the two sets that
would otherwise be computed.
- Return non-zero if an INSN is deleted (i.e. by dead code removal). */
+ Return nonzero if an INSN is deleted (i.e. by dead code removal). */
int
propagate_block (bb, live, local_set, cond_local_set, flags)
@@ -2077,7 +2104,7 @@ propagate_block (bb, live, local_set, cond_local_set, flags)
(SET expressions whose destinations are registers dead after the insn).
NEEDED is the regset that says which regs are alive after the insn.
- Unless CALL_OK is non-zero, an insn is needed if it contains a CALL.
+ Unless CALL_OK is nonzero, an insn is needed if it contains a CALL.
If X is the entire body of an insn, NOTES contains the reg notes
pertaining to the insn. */
@@ -2091,6 +2118,10 @@ insn_dead_p (pbi, x, call_ok, notes)
{
enum rtx_code code = GET_CODE (x);
+ /* Don't eliminate insns that may trap. */
+ if (flag_non_call_exceptions && may_trap_p (x))
+ return 0;
+
#ifdef AUTO_INC_DEC
/* As flow is invoked after combine, we must take existing AUTO_INC
expressions into account. */
@@ -2343,7 +2374,7 @@ regno_uninitialized (regno)
|| FUNCTION_ARG_REGNO_P (regno))))
return 0;
- return REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, regno);
+ return REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno);
}
/* 1 if register REGNO was alive at a place where `setjmp' was called
@@ -2358,7 +2389,7 @@ regno_clobbered_at_setjmp (regno)
return 0;
return ((REG_N_SETS (regno) > 1
- || REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, regno))
+ || REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno))
&& REGNO_REG_SET_P (regs_live_at_setjmp, regno));
}
@@ -2413,15 +2444,21 @@ add_to_mem_set_list (pbi, mem)
Find any entries on the mem_set_list that need to be invalidated due
to an address change. */
-static void
-invalidate_mems_from_autoinc (pbi, insn)
- struct propagate_block_info *pbi;
- rtx insn;
+static int
+invalidate_mems_from_autoinc (px, data)
+ rtx *px;
+ void *data;
{
- rtx note = REG_NOTES (insn);
- for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
- if (REG_NOTE_KIND (note) == REG_INC)
- invalidate_mems_from_set (pbi, XEXP (note, 0));
+ rtx x = *px;
+ struct propagate_block_info *pbi = data;
+
+ if (GET_RTX_CLASS (GET_CODE (x)) == 'a')
+ {
+ invalidate_mems_from_set (pbi, XEXP (x, 0));
+ return -1;
+ }
+
+ return 0;
}
/* EXP is a REG. Remove any dependent entries from pbi->mem_set_list. */
@@ -2634,7 +2671,7 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
/* If this set is a MEM, then it kills any aliased writes.
If this set is a REG, then it kills any MEMs which use the reg. */
- if (optimize && (flags & PROP_SCAN_DEAD_CODE))
+ if (optimize && (flags & PROP_SCAN_DEAD_STORES))
{
if (GET_CODE (reg) == REG)
invalidate_mems_from_set (pbi, reg);
@@ -2643,16 +2680,12 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
address modes. Then we may need to kill some entries on the
memory set list. */
if (insn && GET_CODE (reg) == MEM)
- invalidate_mems_from_autoinc (pbi, insn);
+ for_each_rtx (&PATTERN (insn), invalidate_mems_from_autoinc, pbi);
if (GET_CODE (reg) == MEM && ! side_effects_p (reg)
/* ??? With more effort we could track conditional memory life. */
- && ! cond
- /* There are no REG_INC notes for SP, so we can't assume we'll see
- everything that invalidates it. To be safe, don't eliminate any
- stores though SP; none of them should be redundant anyway. */
- && ! reg_mentioned_p (stack_pointer_rtx, reg))
- add_to_mem_set_list (pbi, canon_rtx (reg));
+ && ! cond)
+ add_to_mem_set_list (pbi, canon_rtx (reg));
}
if (GET_CODE (reg) == REG
@@ -2807,7 +2840,7 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
if (! REGNO_REG_SET_P (pbi->reg_live, i))
REG_NOTES (insn)
= alloc_EXPR_LIST (REG_UNUSED,
- gen_rtx_REG (reg_raw_mode[i], i),
+ regno_reg_rtx[i],
REG_NOTES (insn));
}
}
@@ -3337,7 +3370,7 @@ attempt_auto_inc (pbi, inc, insn, mem, incr, incr_reg)
/* We now know we'll be doing this change, so emit the
new insn(s) and do the updates. */
- emit_insns_before (insns, insn);
+ emit_insn_before (insns, insn);
if (pbi->bb->head == insn)
pbi->bb->head = insns;
@@ -3615,7 +3648,7 @@ mark_used_reg (pbi, reg, cond, insn)
&& ! dead_or_set_regno_p (insn, i))
REG_NOTES (insn)
= alloc_EXPR_LIST (REG_DEAD,
- gen_rtx_REG (reg_raw_mode[i], i),
+ regno_reg_rtx[i],
REG_NOTES (insn));
}
}
@@ -3741,7 +3774,7 @@ mark_used_regs (pbi, x, cond, insn)
case MEM:
/* Don't bother watching stores to mems if this is not the
final pass. We'll not be deleting dead stores this round. */
- if (optimize && (flags & PROP_SCAN_DEAD_CODE))
+ if (optimize && (flags & PROP_SCAN_DEAD_STORES))
{
/* Invalidate the data for the last MEM stored, but only if MEM is
something that can be stored into. */
@@ -3778,22 +3811,22 @@ mark_used_regs (pbi, x, cond, insn)
address modes. Then we may need to kill some entries on the
memory set list. */
if (insn)
- invalidate_mems_from_autoinc (pbi, insn);
+ for_each_rtx (&PATTERN (insn), invalidate_mems_from_autoinc, pbi);
}
#ifdef AUTO_INC_DEC
if (flags & PROP_AUTOINC)
- find_auto_inc (pbi, x, insn);
+ find_auto_inc (pbi, x, insn);
#endif
break;
case SUBREG:
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
if (GET_CODE (SUBREG_REG (x)) == REG
- && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER
- && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (x),
- GET_MODE (SUBREG_REG (x))))
- REG_CHANGES_MODE (REGNO (SUBREG_REG (x))) = 1;
+ && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
+ bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (x))
+ * MAX_MACHINE_MODE
+ + GET_MODE (x));
#endif
/* While we're here, optimize this case. */
@@ -3837,13 +3870,13 @@ mark_used_regs (pbi, x, cond, insn)
|| GET_CODE (testreg) == SIGN_EXTRACT
|| GET_CODE (testreg) == SUBREG)
{
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
if (GET_CODE (testreg) == SUBREG
&& GET_CODE (SUBREG_REG (testreg)) == REG
- && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER
- && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (testreg)),
- GET_MODE (testreg)))
- REG_CHANGES_MODE (REGNO (SUBREG_REG (testreg))) = 1;
+ && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER)
+ bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (testreg))
+ * MAX_MACHINE_MODE
+ + GET_MODE (testreg));
#endif
/* Modifying a single register in an alternate mode
@@ -4000,7 +4033,7 @@ try_pre_increment_1 (pbi, insn)
{
/* We have found a suitable auto-increment and already changed
insn Y to do it. So flush this increment instruction. */
- propagate_block_delete_insn (pbi->bb, insn);
+ propagate_block_delete_insn (insn);
/* Count a reference to this reg for the increment insn we are
deleting. When a reg is incremented, spilling it is worse,
@@ -4238,18 +4271,16 @@ count_or_remove_death_notes (blocks, kill)
sbitmap blocks;
int kill;
{
- int i, count = 0;
+ int count = 0;
+ basic_block bb;
- for (i = n_basic_blocks - 1; i >= 0; --i)
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block bb;
rtx insn;
- if (blocks && ! TEST_BIT (blocks, i))
+ if (blocks && ! TEST_BIT (blocks, bb->index))
continue;
- bb = BASIC_BLOCK (i);
-
for (insn = bb->head;; insn = NEXT_INSN (insn))
{
if (INSN_P (insn))
diff --git a/contrib/gcc/fold-const.c b/contrib/gcc/fold-const.c
index ef24717..94682d4 100644
--- a/contrib/gcc/fold-const.c
+++ b/contrib/gcc/fold-const.c
@@ -1,5 +1,5 @@
/* Fold a constant sub-tree into a single node for C-compiler
- Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2002,
1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -46,12 +46,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "system.h"
#include "flags.h"
#include "tree.h"
+#include "real.h"
#include "rtl.h"
#include "expr.h"
#include "tm_p.h"
#include "toplev.h"
#include "ggc.h"
#include "hashtab.h"
+#include "langhooks.h"
static void encode PARAMS ((HOST_WIDE_INT *,
unsigned HOST_WIDE_INT,
@@ -59,22 +61,19 @@ static void encode PARAMS ((HOST_WIDE_INT *,
static void decode PARAMS ((HOST_WIDE_INT *,
unsigned HOST_WIDE_INT *,
HOST_WIDE_INT *));
-#ifndef REAL_ARITHMETIC
-static void exact_real_inverse_1 PARAMS ((PTR));
-#endif
static tree negate_expr PARAMS ((tree));
static tree split_tree PARAMS ((tree, enum tree_code, tree *, tree *,
tree *, int));
static tree associate_trees PARAMS ((tree, tree, enum tree_code, tree));
static tree int_const_binop PARAMS ((enum tree_code, tree, tree, int));
-static void const_binop_1 PARAMS ((PTR));
static tree const_binop PARAMS ((enum tree_code, tree, tree, int));
static hashval_t size_htab_hash PARAMS ((const void *));
static int size_htab_eq PARAMS ((const void *, const void *));
-static void fold_convert_1 PARAMS ((PTR));
static tree fold_convert PARAMS ((tree, tree));
static enum tree_code invert_tree_comparison PARAMS ((enum tree_code));
static enum tree_code swap_tree_comparison PARAMS ((enum tree_code));
+static int comparison_to_compcode PARAMS ((enum tree_code));
+static enum tree_code compcode_to_comparison PARAMS ((int));
static int truth_value_p PARAMS ((enum tree_code));
static int operand_equal_for_comparison_p PARAMS ((tree, tree, tree));
static int twoval_comparison_p PARAMS ((tree, tree *, tree *, int *));
@@ -90,6 +89,7 @@ static tree decode_field_reference PARAMS ((tree, HOST_WIDE_INT *,
enum machine_mode *, int *,
int *, tree *, tree *));
static int all_ones_mask_p PARAMS ((tree, int));
+static tree sign_bit_p PARAMS ((tree, tree));
static int simple_operand_p PARAMS ((tree));
static tree range_binop PARAMS ((enum tree_code, tree, tree, int,
tree, int));
@@ -102,19 +102,26 @@ static tree unextend PARAMS ((tree, int, int, tree));
static tree fold_truthop PARAMS ((enum tree_code, tree, tree, tree));
static tree optimize_minmax_comparison PARAMS ((tree));
static tree extract_muldiv PARAMS ((tree, tree, enum tree_code, tree));
+static tree extract_muldiv_1 PARAMS ((tree, tree, enum tree_code, tree));
static tree strip_compound_expr PARAMS ((tree, tree));
static int multiple_of_p PARAMS ((tree, tree, tree));
static tree constant_boolean_node PARAMS ((int, tree));
static int count_cond PARAMS ((tree, int));
-static tree fold_binary_op_with_conditional_arg
+static tree fold_binary_op_with_conditional_arg
PARAMS ((enum tree_code, tree, tree, tree, int));
-
-#if defined(HOST_EBCDIC)
-/* bit 8 is significant in EBCDIC */
-#define CHARMASK 0xff
-#else
-#define CHARMASK 0x7f
-#endif
+static bool fold_real_zero_addition_p PARAMS ((tree, tree, int));
+
+/* The following constants represent a bit based encoding of GCC's
+ comparison operators. This encoding simplifies transformations
+ on relational comparison operators, such as AND and OR. */
+#define COMPCODE_FALSE 0
+#define COMPCODE_LT 1
+#define COMPCODE_EQ 2
+#define COMPCODE_LE 3
+#define COMPCODE_GT 4
+#define COMPCODE_NE 5
+#define COMPCODE_GE 6
+#define COMPCODE_TRUE 7
/* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
overflow. Suppose A, B and SUM have the same respective signs as A1, B1,
@@ -172,10 +179,7 @@ decode (words, low, hi)
Return 1 if a signed overflow occurs, 0 otherwise. If OVERFLOW is
nonzero, a signed overflow has already occurred in calculating T, so
- propagate it.
-
- Make the real constant T valid for its type by calling CHECK_FLOAT_VALUE,
- if it exists. */
+ propagate it. */
int
force_fit_type (t, overflow)
@@ -188,10 +192,8 @@ force_fit_type (t, overflow)
if (TREE_CODE (t) == REAL_CST)
{
-#ifdef CHECK_FLOAT_VALUE
- CHECK_FLOAT_VALUE (TYPE_MODE (TREE_TYPE (t)), TREE_REAL_CST (t),
- overflow);
-#endif
+ /* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
+ Consider doing it via real_convert now. */
return overflow;
}
@@ -414,7 +416,8 @@ lshift_double (l1, h1, count, prec, lv, hv, arith)
/* Sign extend all bits that are beyond the precision. */
signmask = -((prec > HOST_BITS_PER_WIDE_INT
- ? (*hv >> (prec - HOST_BITS_PER_WIDE_INT - 1))
+ ? ((unsigned HOST_WIDE_INT) *hv
+ >> (prec - HOST_BITS_PER_WIDE_INT - 1))
: (*lv >> (prec - 1))) & 1);
if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
@@ -647,7 +650,7 @@ div_and_round_double (code, uns,
int num_hi_sig, den_hi_sig;
unsigned HOST_WIDE_INT quo_est, scale;
- /* Find the highest non-zero divisor digit. */
+ /* Find the highest nonzero divisor digit. */
for (i = 4 - 1;; i--)
if (den[i] != 0)
{
@@ -720,7 +723,7 @@ div_and_round_double (code, uns,
/* If quo_est was high by one, then num[i] went negative and
we need to correct things. */
- if (num[num_hi_sig] < carry)
+ if (num[num_hi_sig] < (HOST_WIDE_INT) carry)
{
quo_est--;
carry = 0; /* add divisor back in */
@@ -830,512 +833,6 @@ div_and_round_double (code, uns,
return overflow;
}
-#ifndef REAL_ARITHMETIC
-/* Effectively truncate a real value to represent the nearest possible value
- in a narrower mode. The result is actually represented in the same data
- type as the argument, but its value is usually different.
-
- A trap may occur during the FP operations and it is the responsibility
- of the calling function to have a handler established. */
-
-REAL_VALUE_TYPE
-real_value_truncate (mode, arg)
- enum machine_mode mode;
- REAL_VALUE_TYPE arg;
-{
- return REAL_VALUE_TRUNCATE (mode, arg);
-}
-
-#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-
-/* Check for infinity in an IEEE double precision number. */
-
-int
-target_isinf (x)
- REAL_VALUE_TYPE x;
-{
- /* The IEEE 64-bit double format. */
- union {
- REAL_VALUE_TYPE d;
- struct {
- unsigned sign : 1;
- unsigned exponent : 11;
- unsigned mantissa1 : 20;
- unsigned mantissa2 : 32;
- } little_endian;
- struct {
- unsigned mantissa2 : 32;
- unsigned mantissa1 : 20;
- unsigned exponent : 11;
- unsigned sign : 1;
- } big_endian;
- } u;
-
- u.d = dconstm1;
- if (u.big_endian.sign == 1)
- {
- u.d = x;
- return (u.big_endian.exponent == 2047
- && u.big_endian.mantissa1 == 0
- && u.big_endian.mantissa2 == 0);
- }
- else
- {
- u.d = x;
- return (u.little_endian.exponent == 2047
- && u.little_endian.mantissa1 == 0
- && u.little_endian.mantissa2 == 0);
- }
-}
-
-/* Check whether an IEEE double precision number is a NaN. */
-
-int
-target_isnan (x)
- REAL_VALUE_TYPE x;
-{
- /* The IEEE 64-bit double format. */
- union {
- REAL_VALUE_TYPE d;
- struct {
- unsigned sign : 1;
- unsigned exponent : 11;
- unsigned mantissa1 : 20;
- unsigned mantissa2 : 32;
- } little_endian;
- struct {
- unsigned mantissa2 : 32;
- unsigned mantissa1 : 20;
- unsigned exponent : 11;
- unsigned sign : 1;
- } big_endian;
- } u;
-
- u.d = dconstm1;
- if (u.big_endian.sign == 1)
- {
- u.d = x;
- return (u.big_endian.exponent == 2047
- && (u.big_endian.mantissa1 != 0
- || u.big_endian.mantissa2 != 0));
- }
- else
- {
- u.d = x;
- return (u.little_endian.exponent == 2047
- && (u.little_endian.mantissa1 != 0
- || u.little_endian.mantissa2 != 0));
- }
-}
-
-/* Check for a negative IEEE double precision number. */
-
-int
-target_negative (x)
- REAL_VALUE_TYPE x;
-{
- /* The IEEE 64-bit double format. */
- union {
- REAL_VALUE_TYPE d;
- struct {
- unsigned sign : 1;
- unsigned exponent : 11;
- unsigned mantissa1 : 20;
- unsigned mantissa2 : 32;
- } little_endian;
- struct {
- unsigned mantissa2 : 32;
- unsigned mantissa1 : 20;
- unsigned exponent : 11;
- unsigned sign : 1;
- } big_endian;
- } u;
-
- u.d = dconstm1;
- if (u.big_endian.sign == 1)
- {
- u.d = x;
- return u.big_endian.sign;
- }
- else
- {
- u.d = x;
- return u.little_endian.sign;
- }
-}
-#else /* Target not IEEE */
-
-/* Let's assume other float formats don't have infinity.
- (This can be overridden by redefining REAL_VALUE_ISINF.) */
-
-int
-target_isinf (x)
- REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
-{
- return 0;
-}
-
-/* Let's assume other float formats don't have NaNs.
- (This can be overridden by redefining REAL_VALUE_ISNAN.) */
-
-int
-target_isnan (x)
- REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
-{
- return 0;
-}
-
-/* Let's assume other float formats don't have minus zero.
- (This can be overridden by redefining REAL_VALUE_NEGATIVE.) */
-
-int
-target_negative (x)
- REAL_VALUE_TYPE x;
-{
- return x < 0;
-}
-#endif /* Target not IEEE */
-
-/* Try to change R into its exact multiplicative inverse in machine mode
- MODE. Return nonzero function value if successful. */
-struct exact_real_inverse_args
-{
- REAL_VALUE_TYPE *r;
- enum machine_mode mode;
- int success;
-};
-
-static void
-exact_real_inverse_1 (p)
- PTR p;
-{
- struct exact_real_inverse_args *args =
- (struct exact_real_inverse_args *) p;
-
- enum machine_mode mode = args->mode;
- REAL_VALUE_TYPE *r = args->r;
-
- union
- {
- double d;
- unsigned short i[4];
- }
- x, t, y;
-#ifdef CHECK_FLOAT_VALUE
- int i;
-#endif
-
- /* Set array index to the less significant bits in the unions, depending
- on the endian-ness of the host doubles. */
-#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT \
- || HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
-# define K 2
-#else
-# define K (2 * HOST_FLOAT_WORDS_BIG_ENDIAN)
-#endif
-
- /* Domain check the argument. */
- x.d = *r;
- if (x.d == 0.0)
- goto fail;
-
-#ifdef REAL_INFINITY
- if (REAL_VALUE_ISINF (x.d) || REAL_VALUE_ISNAN (x.d))
- goto fail;
-#endif
-
- /* Compute the reciprocal and check for numerical exactness.
- It is unnecessary to check all the significand bits to determine
- whether X is a power of 2. If X is not, then it is impossible for
- the bottom half significand of both X and 1/X to be all zero bits.
- Hence we ignore the data structure of the top half and examine only
- the low order bits of the two significands. */
- t.d = 1.0 / x.d;
- if (x.i[K] != 0 || x.i[K + 1] != 0 || t.i[K] != 0 || t.i[K + 1] != 0)
- goto fail;
-
- /* Truncate to the required mode and range-check the result. */
- y.d = REAL_VALUE_TRUNCATE (mode, t.d);
-#ifdef CHECK_FLOAT_VALUE
- i = 0;
- if (CHECK_FLOAT_VALUE (mode, y.d, i))
- goto fail;
-#endif
-
- /* Fail if truncation changed the value. */
- if (y.d != t.d || y.d == 0.0)
- goto fail;
-
-#ifdef REAL_INFINITY
- if (REAL_VALUE_ISINF (y.d) || REAL_VALUE_ISNAN (y.d))
- goto fail;
-#endif
-
- /* Output the reciprocal and return success flag. */
- *r = y.d;
- args->success = 1;
- return;
-
- fail:
- args->success = 0;
- return;
-
-#undef K
-}
-
-
-int
-exact_real_inverse (mode, r)
- enum machine_mode mode;
- REAL_VALUE_TYPE *r;
-{
- struct exact_real_inverse_args args;
-
- /* Disable if insufficient information on the data structure. */
-#if HOST_FLOAT_FORMAT == UNKNOWN_FLOAT_FORMAT
- return 0;
-#endif
-
- /* Usually disable if bounds checks are not reliable. */
- if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT) && !flag_pretend_float)
- return 0;
-
- args.mode = mode;
- args.r = r;
-
- if (do_float_handler (exact_real_inverse_1, (PTR) &args))
- return args.success;
- return 0;
-}
-
-/* Convert C99 hexadecimal floating point string constant S. Return
- real value type in mode MODE. This function uses the host computer's
- floating point arithmetic when there is no REAL_ARITHMETIC. */
-
-REAL_VALUE_TYPE
-real_hex_to_f (s, mode)
- const char *s;
- enum machine_mode mode;
-{
- REAL_VALUE_TYPE ip;
- const char *p = s;
- unsigned HOST_WIDE_INT low, high;
- int shcount, nrmcount, k;
- int sign, expsign, isfloat;
- int lost = 0;/* Nonzero low order bits shifted out and discarded. */
- int frexpon = 0; /* Bits after the decimal point. */
- int expon = 0; /* Value of exponent. */
- int decpt = 0; /* How many decimal points. */
- int gotp = 0; /* How many P's. */
- char c;
-
- isfloat = 0;
- expsign = 1;
- ip = 0.0;
-
- while (*p == ' ' || *p == '\t')
- ++p;
-
- /* Sign, if any, comes first. */
- sign = 1;
- if (*p == '-')
- {
- sign = -1;
- ++p;
- }
-
- /* The string is supposed to start with 0x or 0X . */
- if (*p == '0')
- {
- ++p;
- if (*p == 'x' || *p == 'X')
- ++p;
- else
- abort ();
- }
- else
- abort ();
-
- while (*p == '0')
- ++p;
-
- high = 0;
- low = 0;
- shcount = 0;
- while ((c = *p) != '\0')
- {
- if (ISXDIGIT (c))
- {
- k = hex_value (c & CHARMASK);
-
- if ((high & 0xf0000000) == 0)
- {
- high = (high << 4) + ((low >> 28) & 15);
- low = (low << 4) + k;
- shcount += 4;
- if (decpt)
- frexpon += 4;
- }
- else
- {
- /* Record nonzero lost bits. */
- lost |= k;
- if (! decpt)
- frexpon -= 4;
- }
- ++p;
- }
- else if (c == '.')
- {
- ++decpt;
- ++p;
- }
-
- else if (c == 'p' || c == 'P')
- {
- ++gotp;
- ++p;
- /* Sign of exponent. */
- if (*p == '-')
- {
- expsign = -1;
- ++p;
- }
-
- /* Value of exponent.
- The exponent field is a decimal integer. */
- while (ISDIGIT (*p))
- {
- k = (*p++ & CHARMASK) - '0';
- expon = 10 * expon + k;
- }
-
- expon *= expsign;
- /* F suffix is ambiguous in the significand part
- so it must appear after the decimal exponent field. */
- if (*p == 'f' || *p == 'F')
- {
- isfloat = 1;
- ++p;
- break;
- }
- }
-
- else if (c == 'l' || c == 'L')
- {
- ++p;
- break;
- }
- else
- break;
- }
-
- /* Abort if last character read was not legitimate. */
- c = *p;
- if ((c != '\0' && c != ' ' && c != '\n' && c != '\r') || (decpt > 1))
- abort ();
-
- /* There must be either one decimal point or one p. */
- if (decpt == 0 && gotp == 0)
- abort ();
-
- shcount -= 4;
- if (high == 0 && low == 0)
- return dconst0;
-
- /* Normalize. */
- nrmcount = 0;
- if (high == 0)
- {
- high = low;
- low = 0;
- nrmcount += 32;
- }
-
- /* Leave a high guard bit for carry-out. */
- if ((high & 0x80000000) != 0)
- {
- lost |= low & 1;
- low = (low >> 1) | (high << 31);
- high = high >> 1;
- nrmcount -= 1;
- }
-
- if ((high & 0xffff8000) == 0)
- {
- high = (high << 16) + ((low >> 16) & 0xffff);
- low = low << 16;
- nrmcount += 16;
- }
-
- while ((high & 0xc0000000) == 0)
- {
- high = (high << 1) + ((low >> 31) & 1);
- low = low << 1;
- nrmcount += 1;
- }
-
- if (isfloat || GET_MODE_SIZE (mode) == UNITS_PER_WORD)
- {
- /* Keep 24 bits precision, bits 0x7fffff80.
- Rounding bit is 0x40. */
- lost = lost | low | (high & 0x3f);
- low = 0;
- if (high & 0x40)
- {
- if ((high & 0x80) || lost)
- high += 0x40;
- }
- high &= 0xffffff80;
- }
- else
- {
- /* We need real.c to do long double formats, so here default
- to double precision. */
-#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
- /* IEEE double.
- Keep 53 bits precision, bits 0x7fffffff fffffc00.
- Rounding bit is low word 0x200. */
- lost = lost | (low & 0x1ff);
- if (low & 0x200)
- {
- if ((low & 0x400) || lost)
- {
- low = (low + 0x200) & 0xfffffc00;
- if (low == 0)
- high += 1;
- }
- }
- low &= 0xfffffc00;
-#else
- /* Assume it's a VAX with 56-bit significand,
- bits 0x7fffffff ffffff80. */
- lost = lost | (low & 0x7f);
- if (low & 0x40)
- {
- if ((low & 0x80) || lost)
- {
- low = (low + 0x40) & 0xffffff80;
- if (low == 0)
- high += 1;
- }
- }
- low &= 0xffffff80;
-#endif
- }
-
- ip = (double) high;
- ip = REAL_VALUE_LDEXP (ip, 32) + (double) low;
- /* Apply shifts and exponent value as power of 2. */
- ip = REAL_VALUE_LDEXP (ip, expon - (nrmcount + frexpon));
-
- if (sign < 0)
- ip = -ip;
- return ip;
-}
-
-#endif /* no REAL_ARITHMETIC */
-
/* Given T, an expression, return the negation of T. Allow for T to be
null, in which case return null. */
@@ -1709,69 +1206,6 @@ int_const_binop (code, arg1, arg2, notrunc)
return t;
}
-/* Define input and output argument for const_binop_1. */
-struct cb_args
-{
- enum tree_code code; /* Input: tree code for operation. */
- tree type; /* Input: tree type for operation. */
- REAL_VALUE_TYPE d1, d2; /* Input: floating point operands. */
- tree t; /* Output: constant for result. */
-};
-
-/* Do the real arithmetic for const_binop while protected by a
- float overflow handler. */
-
-static void
-const_binop_1 (data)
- PTR data;
-{
- struct cb_args *args = (struct cb_args *) data;
- REAL_VALUE_TYPE value;
-
-#ifdef REAL_ARITHMETIC
- REAL_ARITHMETIC (value, args->code, args->d1, args->d2);
-#else
- switch (args->code)
- {
- case PLUS_EXPR:
- value = args->d1 + args->d2;
- break;
-
- case MINUS_EXPR:
- value = args->d1 - args->d2;
- break;
-
- case MULT_EXPR:
- value = args->d1 * args->d2;
- break;
-
- case RDIV_EXPR:
-#ifndef REAL_INFINITY
- if (args->d2 == 0)
- abort ();
-#endif
-
- value = args->d1 / args->d2;
- break;
-
- case MIN_EXPR:
- value = MIN (args->d1, args->d2);
- break;
-
- case MAX_EXPR:
- value = MAX (args->d1, args->d2);
- break;
-
- default:
- abort ();
- }
-#endif /* no REAL_ARITHMETIC */
-
- args->t
- = build_real (args->type,
- real_value_truncate (TYPE_MODE (args->type), value));
-}
-
/* Combine two constants ARG1 and ARG2 under operation CODE to produce a new
constant. We assume ARG1 and ARG2 have the same data type, or at least
are the same kind of constant and the same machine mode.
@@ -1790,14 +1224,12 @@ const_binop (code, arg1, arg2, notrunc)
if (TREE_CODE (arg1) == INTEGER_CST)
return int_const_binop (code, arg1, arg2, notrunc);
-#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
if (TREE_CODE (arg1) == REAL_CST)
{
REAL_VALUE_TYPE d1;
REAL_VALUE_TYPE d2;
- int overflow = 0;
+ REAL_VALUE_TYPE value;
tree t;
- struct cb_args args;
d1 = TREE_REAL_CST (arg1);
d2 = TREE_REAL_CST (arg2);
@@ -1809,24 +1241,14 @@ const_binop (code, arg1, arg2, notrunc)
else if (REAL_VALUE_ISNAN (d2))
return arg2;
- /* Setup input for const_binop_1() */
- args.type = TREE_TYPE (arg1);
- args.d1 = d1;
- args.d2 = d2;
- args.code = code;
+ REAL_ARITHMETIC (value, code, d1, d2);
- if (do_float_handler (const_binop_1, (PTR) &args))
- /* Receive output from const_binop_1. */
- t = args.t;
- else
- {
- /* We got an exception from const_binop_1. */
- t = copy_node (arg1);
- overflow = 1;
- }
+ t = build_real (TREE_TYPE (arg1),
+ real_value_truncate (TYPE_MODE (TREE_TYPE (arg1)),
+ value));
TREE_OVERFLOW (t)
- = (force_fit_type (t, overflow)
+ = (force_fit_type (t, 0)
| TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
TREE_CONSTANT_OVERFLOW (t)
= TREE_OVERFLOW (t)
@@ -1834,7 +1256,6 @@ const_binop (code, arg1, arg2, notrunc)
| TREE_CONSTANT_OVERFLOW (arg2);
return t;
}
-#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
if (TREE_CODE (arg1) == COMPLEX_CST)
{
tree type = TREE_TYPE (arg1);
@@ -1926,11 +1347,11 @@ size_htab_hash (x)
tree t = (tree) x;
return (TREE_INT_CST_HIGH (t) ^ TREE_INT_CST_LOW (t)
- ^ (hashval_t) ((long) TREE_TYPE (t) >> 3)
+ ^ htab_hash_pointer (TREE_TYPE (t))
^ (TREE_OVERFLOW (t) << 20));
}
-/* Return non-zero if the value represented by *X (an INTEGER_CST tree node)
+/* Return nonzero if the value represented by *X (an INTEGER_CST tree node)
is the same as that given by *Y, which is the same. */
static int
@@ -1960,21 +1381,21 @@ size_int_wide (number, kind)
/* Likewise, but the desired type is specified explicitly. */
+static GTY (()) tree new_const;
+static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
+ htab_t size_htab;
+
tree
size_int_type_wide (number, type)
HOST_WIDE_INT number;
tree type;
{
- static htab_t size_htab = 0;
- static tree new_const = 0;
PTR *slot;
if (size_htab == 0)
{
size_htab = htab_create (1024, size_htab_hash, size_htab_eq, NULL);
- ggc_add_deletable_htab (size_htab, NULL, NULL);
new_const = make_node (INTEGER_CST);
- ggc_add_tree_root (&new_const, 1);
}
/* Adjust NEW_CONST to be the constant we want. If it's already in the
@@ -2079,27 +1500,6 @@ size_diffop (arg0, arg1)
convert (ctype, size_binop (MINUS_EXPR, arg1, arg0)));
}
-/* This structure is used to communicate arguments to fold_convert_1. */
-struct fc_args
-{
- tree arg1; /* Input: value to convert. */
- tree type; /* Input: type to convert value to. */
- tree t; /* Output: result of conversion. */
-};
-
-/* Function to convert floating-point constants, protected by floating
- point exception handler. */
-
-static void
-fold_convert_1 (data)
- PTR data;
-{
- struct fc_args *args = (struct fc_args *) data;
-
- args->t = build_real (args->type,
- real_value_truncate (TYPE_MODE (args->type),
- TREE_REAL_CST (args->arg1)));
-}
/* Given T, a tree representing type conversion of ARG1, a constant,
return a constant tree representing the result of conversion. */
@@ -2148,7 +1548,6 @@ fold_convert (t, arg1)
TREE_CONSTANT_OVERFLOW (t)
= TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
}
-#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
else if (TREE_CODE (arg1) == REAL_CST)
{
/* Don't initialize these, use assignments.
@@ -2169,15 +1568,9 @@ fold_convert (t, arg1)
/* See if X will be in range after truncation towards 0.
To compensate for truncation, move the bounds away from 0,
but reject if X exactly equals the adjusted bounds. */
-#ifdef REAL_ARITHMETIC
REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1);
if (!no_upper_bound)
REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);
-#else
- l--;
- if (!no_upper_bound)
- u++;
-#endif
/* If X is a NaN, use zero instead and show we have an overflow.
Otherwise, range check. */
if (REAL_VALUE_ISNAN (x))
@@ -2187,79 +1580,40 @@ fold_convert (t, arg1)
&& REAL_VALUES_LESS (x, u)))
overflow = 1;
-#ifndef REAL_ARITHMETIC
- {
- HOST_WIDE_INT low, high;
- HOST_WIDE_INT half_word
- = (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2);
-
- if (x < 0)
- x = -x;
-
- high = (HOST_WIDE_INT) (x / half_word / half_word);
- x -= (REAL_VALUE_TYPE) high * half_word * half_word;
- if (x >= (REAL_VALUE_TYPE) half_word * half_word / 2)
- {
- low = x - (REAL_VALUE_TYPE) half_word * half_word / 2;
- low |= (HOST_WIDE_INT) -1 << (HOST_BITS_PER_WIDE_INT - 1);
- }
- else
- low = (HOST_WIDE_INT) x;
- if (TREE_REAL_CST (arg1) < 0)
- neg_double (low, high, &low, &high);
- t = build_int_2 (low, high);
- }
-#else
{
HOST_WIDE_INT low, high;
REAL_VALUE_TO_INT (&low, &high, x);
t = build_int_2 (low, high);
}
-#endif
TREE_TYPE (t) = type;
TREE_OVERFLOW (t)
= TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
TREE_CONSTANT_OVERFLOW (t)
= TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
}
-#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
TREE_TYPE (t) = type;
}
else if (TREE_CODE (type) == REAL_TYPE)
{
-#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
if (TREE_CODE (arg1) == INTEGER_CST)
return build_real_from_int_cst (type, arg1);
-#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
if (TREE_CODE (arg1) == REAL_CST)
{
- struct fc_args args;
-
if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)))
{
- t = arg1;
- TREE_TYPE (arg1) = type;
+ /* We make a copy of ARG1 so that we don't modify an
+ existing constant tree. */
+ t = copy_node (arg1);
+ TREE_TYPE (t) = type;
return t;
}
- /* Setup input for fold_convert_1() */
- args.arg1 = arg1;
- args.type = type;
-
- if (do_float_handler (fold_convert_1, (PTR) &args))
- {
- /* Receive output from fold_convert_1() */
- t = args.t;
- }
- else
- {
- /* We got an exception from fold_convert_1() */
- overflow = 1;
- t = copy_node (arg1);
- }
+ t = build_real (type,
+ real_value_truncate (TYPE_MODE (type),
+ TREE_REAL_CST (arg1)));
TREE_OVERFLOW (t)
- = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
+ = TREE_OVERFLOW (arg1) | force_fit_type (t, 0);
TREE_CONSTANT_OVERFLOW (t)
= TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
return t;
@@ -2360,6 +1714,61 @@ swap_tree_comparison (code)
}
}
+
+/* Convert a comparison tree code from an enum tree_code representation
+ into a compcode bit-based encoding. This function is the inverse of
+ compcode_to_comparison. */
+
+static int
+comparison_to_compcode (code)
+ enum tree_code code;
+{
+ switch (code)
+ {
+ case LT_EXPR:
+ return COMPCODE_LT;
+ case EQ_EXPR:
+ return COMPCODE_EQ;
+ case LE_EXPR:
+ return COMPCODE_LE;
+ case GT_EXPR:
+ return COMPCODE_GT;
+ case NE_EXPR:
+ return COMPCODE_NE;
+ case GE_EXPR:
+ return COMPCODE_GE;
+ default:
+ abort ();
+ }
+}
+
+/* Convert a compcode bit-based encoding of a comparison operator back
+ to GCC's enum tree_code representation. This function is the
+ inverse of comparison_to_compcode. */
+
+static enum tree_code
+compcode_to_comparison (code)
+ int code;
+{
+ switch (code)
+ {
+ case COMPCODE_LT:
+ return LT_EXPR;
+ case COMPCODE_EQ:
+ return EQ_EXPR;
+ case COMPCODE_LE:
+ return LE_EXPR;
+ case COMPCODE_GT:
+ return GT_EXPR;
+ case COMPCODE_NE:
+ return NE_EXPR;
+ case COMPCODE_GE:
+ return GE_EXPR;
+ default:
+ abort ();
+ }
+}
+
/* Return nonzero if CODE is a tree code that represents a truth value. */
static int
@@ -2373,7 +1782,7 @@ truth_value_p (code)
}
/* Return nonzero if two operands are necessarily equal.
- If ONLY_CONST is non-zero, only return non-zero for constants.
+ If ONLY_CONST is nonzero, only return nonzero for constants.
This function tests whether the operands are indistinguishable;
it does not test whether they are equal using C's == operation.
The distinction is important for IEEE floating point, because
@@ -2594,9 +2003,8 @@ operand_equal_for_comparison_p (arg0, arg1, other)
/* Make sure shorter operand is extended the right way
to match the longer operand. */
- primarg1 = convert (signed_or_unsigned_type (unsignedp1,
- TREE_TYPE (primarg1)),
- primarg1);
+ primarg1 = convert ((*lang_hooks.types.signed_or_unsigned_type)
+ (unsignedp1, TREE_TYPE (primarg1)), primarg1);
if (operand_equal_p (arg0, convert (type, primarg1), 0))
return 1;
@@ -2608,7 +2016,7 @@ operand_equal_for_comparison_p (arg0, arg1, other)
/* See if ARG is an expression that is either a comparison or is performing
arithmetic on comparisons. The comparisons must only be comparing
two different values, which will be stored in *CVAL1 and *CVAL2; if
- they are non-zero it means that some operands have already been found.
+ they are nonzero it means that some operands have already been found.
No variables may be used anywhere else in the expression except in the
comparisons. If SAVE_P is true it means we removed a SAVE_EXPR around
the expression and save_expr needs to be called with CVAL1 and CVAL2.
@@ -2844,7 +2252,7 @@ invert_truthvalue (arg)
{
if (FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg, 0)))
&& !flag_unsafe_math_optimizations
- && code != NE_EXPR
+ && code != NE_EXPR
&& code != EQ_EXPR)
return build1 (TRUTH_NOT_EXPR, type, arg);
else
@@ -2993,7 +2401,7 @@ distribute_bit_expr (code, type, arg0, arg1)
}
/* Return a BIT_FIELD_REF of type TYPE to refer to BITSIZE bits of INNER
- starting at BITPOS. The field is unsigned if UNSIGNEDP is non-zero. */
+ starting at BITPOS. The field is unsigned if UNSIGNEDP is nonzero. */
static tree
make_bit_field_ref (inner, type, bitsize, bitpos, unsignedp)
@@ -3083,8 +2491,8 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
/* Set signed and unsigned types of the precision of this mode for the
shifts below. */
- signed_type = type_for_mode (nmode, 0);
- unsigned_type = type_for_mode (nmode, 1);
+ signed_type = (*lang_hooks.types.type_for_mode) (nmode, 0);
+ unsigned_type = (*lang_hooks.types.type_for_mode) (nmode, 1);
/* Compute the bit position and size for the new reference and our offset
within it. If the new reference is the same size as the original, we
@@ -3247,7 +2655,7 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
return 0;
/* Compute the mask to access the bitfield. */
- unsigned_type = type_for_size (*pbitsize, 1);
+ unsigned_type = (*lang_hooks.types.type_for_size) (*pbitsize, 1);
precision = TYPE_PRECISION (unsigned_type);
mask = build_int_2 (~0, ~0);
@@ -3266,7 +2674,7 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
return inner;
}
-/* Return non-zero if MASK represents a mask of SIZE ones in the low-order
+/* Return nonzero if MASK represents a mask of SIZE ones in the low-order
bit positions. */
static int
@@ -3279,7 +2687,7 @@ all_ones_mask_p (mask, size)
tree tmask;
tmask = build_int_2 (~0, ~0);
- TREE_TYPE (tmask) = signed_type (type);
+ TREE_TYPE (tmask) = (*lang_hooks.types.signed_type) (type);
force_fit_type (tmask, 0);
return
tree_int_cst_equal (mask,
@@ -3290,6 +2698,55 @@ all_ones_mask_p (mask, size)
size_int (precision - size), 0));
}
+/* Subroutine for fold: determine if VAL is the INTEGER_CONST that
+ represents the sign bit of EXP's type. If EXP represents a sign
+ or zero extension, also test VAL against the unextended type.
+ The return value is the (sub)expression whose sign bit is VAL,
+ or NULL_TREE otherwise. */
+
+static tree
+sign_bit_p (exp, val)
+ tree exp;
+ tree val;
+{
+ unsigned HOST_WIDE_INT lo;
+ HOST_WIDE_INT hi;
+ int width;
+ tree t;
+
+ /* Tree EXP must have an integral type. */
+ t = TREE_TYPE (exp);
+ if (! INTEGRAL_TYPE_P (t))
+ return NULL_TREE;
+
+ /* Tree VAL must be an integer constant. */
+ if (TREE_CODE (val) != INTEGER_CST
+ || TREE_CONSTANT_OVERFLOW (val))
+ return NULL_TREE;
+
+ width = TYPE_PRECISION (t);
+ if (width > HOST_BITS_PER_WIDE_INT)
+ {
+ hi = (unsigned HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT - 1);
+ lo = 0;
+ }
+ else
+ {
+ hi = 0;
+ lo = (unsigned HOST_WIDE_INT) 1 << (width - 1);
+ }
+
+ if (TREE_INT_CST_HIGH (val) == hi && TREE_INT_CST_LOW (val) == lo)
+ return exp;
+
+ /* Handle extension from a narrower type. */
+ if (TREE_CODE (exp) == NOP_EXPR
+ && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))) < width)
+ return sign_bit_p (TREE_OPERAND (exp, 0), val);
+
+ return NULL_TREE;
+}
+
/* Subroutine for fold_truthop: determine if an operand is simple enough
to be evaluated unconditionally. */
@@ -3617,7 +3074,8 @@ make_range (exp, pin_p, plow, phigh)
be interpreted as positive. */
if (TREE_UNSIGNED (type) && ! TREE_UNSIGNED (TREE_TYPE (exp)))
{
- tree equiv_type = type_for_mode (TYPE_MODE (type), 1);
+ tree equiv_type = (*lang_hooks.types.type_for_mode)
+ (TYPE_MODE (type), 1);
tree high_positive;
/* A range without an upper bound is, naturally, unbounded.
@@ -3627,9 +3085,10 @@ make_range (exp, pin_p, plow, phigh)
= TYPE_MAX_VALUE (equiv_type) ? TYPE_MAX_VALUE (equiv_type)
: TYPE_MAX_VALUE (type);
- high_positive = fold (build (RSHIFT_EXPR, type,
- convert (type, high_positive),
- convert (type, integer_one_node)));
+ if (TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (exp)))
+ high_positive = fold (build (RSHIFT_EXPR, type,
+ convert (type, high_positive),
+ convert (type, integer_one_node)));
/* If the low bound is specified, "and" the range with the
range for which the original unsigned value will be
@@ -3696,41 +3155,73 @@ build_range_check (type, exp, in_p, low, high)
tree low, high;
{
tree etype = TREE_TYPE (exp);
- tree utype, value;
+ tree value;
if (! in_p
&& (0 != (value = build_range_check (type, exp, 1, low, high))))
return invert_truthvalue (value);
- else if (low == 0 && high == 0)
+ if (low == 0 && high == 0)
return convert (type, integer_one_node);
- else if (low == 0)
+ if (low == 0)
return fold (build (LE_EXPR, type, exp, high));
- else if (high == 0)
+ if (high == 0)
return fold (build (GE_EXPR, type, exp, low));
- else if (operand_equal_p (low, high, 0))
+ if (operand_equal_p (low, high, 0))
return fold (build (EQ_EXPR, type, exp, low));
- else if (TREE_UNSIGNED (etype) && integer_zerop (low))
- return build_range_check (type, exp, 1, 0, high);
+ if (integer_zerop (low))
+ {
+ if (! TREE_UNSIGNED (etype))
+ {
+ etype = (*lang_hooks.types.unsigned_type) (etype);
+ high = convert (etype, high);
+ exp = convert (etype, exp);
+ }
+ return build_range_check (type, exp, 1, 0, high);
+ }
- else if (integer_zerop (low))
+ /* Optimize (c>=1) && (c<=127) into (signed char)c > 0. */
+ if (integer_onep (low) && TREE_CODE (high) == INTEGER_CST)
{
- utype = unsigned_type (etype);
- return build_range_check (type, convert (utype, exp), 1, 0,
- convert (utype, high));
+ unsigned HOST_WIDE_INT lo;
+ HOST_WIDE_INT hi;
+ int prec;
+
+ prec = TYPE_PRECISION (etype);
+ if (prec <= HOST_BITS_PER_WIDE_INT)
+ {
+ hi = 0;
+ lo = ((unsigned HOST_WIDE_INT) 1 << (prec - 1)) - 1;
+ }
+ else
+ {
+ hi = ((HOST_WIDE_INT) 1 << (prec - HOST_BITS_PER_WIDE_INT - 1)) - 1;
+ lo = (unsigned HOST_WIDE_INT) -1;
+ }
+
+ if (TREE_INT_CST_HIGH (high) == hi && TREE_INT_CST_LOW (high) == lo)
+ {
+ if (TREE_UNSIGNED (etype))
+ {
+ etype = (*lang_hooks.types.signed_type) (etype);
+ exp = convert (etype, exp);
+ }
+ return fold (build (GT_EXPR, type, exp,
+ convert (etype, integer_zero_node)));
+ }
}
- else if (0 != (value = const_binop (MINUS_EXPR, high, low, 0))
- && ! TREE_OVERFLOW (value))
+ if (0 != (value = const_binop (MINUS_EXPR, high, low, 0))
+ && ! TREE_OVERFLOW (value))
return build_range_check (type,
fold (build (MINUS_EXPR, etype, exp, low)),
1, convert (etype, integer_zero_node), value);
- else
- return 0;
+
+ return 0;
}
/* Given two ranges, see if we can merge them into one. Return 1 if we
@@ -3920,7 +3411,7 @@ fold_range_test (exp)
TREE_TYPE (exp), TREE_OPERAND (exp, 0),
TREE_OPERAND (exp, 1));
- else if (global_bindings_p () == 0
+ else if ((*lang_hooks.decls.global_bindings_p) () == 0
&& ! contains_placeholder_p (lhs))
{
tree common = save_expr (lhs);
@@ -3972,7 +3463,7 @@ unextend (c, p, unsignedp, mask)
zero or one, and the conversion to a signed type can never overflow.
We could get an overflow if this conversion is done anywhere else. */
if (TREE_UNSIGNED (type))
- temp = convert (signed_type (type), temp);
+ temp = convert ((*lang_hooks.types.signed_type) (type), temp);
temp = const_binop (LSHIFT_EXPR, temp, size_int (modesize - 1), 0);
temp = const_binop (RSHIFT_EXPR, temp, size_int (modesize - p - 1), 0);
@@ -4068,6 +3559,48 @@ fold_truthop (code, truth_type, lhs, rhs)
rl_arg = TREE_OPERAND (rhs, 0);
rr_arg = TREE_OPERAND (rhs, 1);
+ /* Simplify (x<y) && (x==y) into (x<=y) and related optimizations. */
+ if (simple_operand_p (ll_arg)
+ && simple_operand_p (lr_arg)
+ && !FLOAT_TYPE_P (TREE_TYPE (ll_arg)))
+ {
+ int compcode;
+
+ if (operand_equal_p (ll_arg, rl_arg, 0)
+ && operand_equal_p (lr_arg, rr_arg, 0))
+ {
+ int lcompcode, rcompcode;
+
+ lcompcode = comparison_to_compcode (lcode);
+ rcompcode = comparison_to_compcode (rcode);
+ compcode = (code == TRUTH_AND_EXPR)
+ ? lcompcode & rcompcode
+ : lcompcode | rcompcode;
+ }
+ else if (operand_equal_p (ll_arg, rr_arg, 0)
+ && operand_equal_p (lr_arg, rl_arg, 0))
+ {
+ int lcompcode, rcompcode;
+
+ rcode = swap_tree_comparison (rcode);
+ lcompcode = comparison_to_compcode (lcode);
+ rcompcode = comparison_to_compcode (rcode);
+ compcode = (code == TRUTH_AND_EXPR)
+ ? lcompcode & rcompcode
+ : lcompcode | rcompcode;
+ }
+ else
+ compcode = -1;
+
+ if (compcode == COMPCODE_TRUE)
+ return convert (truth_type, integer_one_node);
+ else if (compcode == COMPCODE_FALSE)
+ return convert (truth_type, integer_zero_node);
+ else if (compcode != -1)
+ return build (compcode_to_comparison (compcode),
+ truth_type, ll_arg, lr_arg);
+ }
+
/* If the RHS can be evaluated unconditionally and its operands are
simple, it wins to evaluate the RHS unconditionally on machines
with expensive branches. In this case, this isn't a comparison
@@ -4078,7 +3611,29 @@ fold_truthop (code, truth_type, lhs, rhs)
&& ! FLOAT_TYPE_P (TREE_TYPE (rl_arg))
&& simple_operand_p (rl_arg)
&& simple_operand_p (rr_arg))
- return build (code, truth_type, lhs, rhs);
+ {
+ /* Convert (a != 0) || (b != 0) into (a | b) != 0. */
+ if (code == TRUTH_OR_EXPR
+ && lcode == NE_EXPR && integer_zerop (lr_arg)
+ && rcode == NE_EXPR && integer_zerop (rr_arg)
+ && TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg))
+ return build (NE_EXPR, truth_type,
+ build (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
+ ll_arg, rl_arg),
+ integer_zero_node);
+
+ /* Convert (a == 0) && (b == 0) into (a | b) == 0. */
+ if (code == TRUTH_AND_EXPR
+ && lcode == EQ_EXPR && integer_zerop (lr_arg)
+ && rcode == EQ_EXPR && integer_zerop (rr_arg)
+ && TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg))
+ return build (EQ_EXPR, truth_type,
+ build (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
+ ll_arg, rl_arg),
+ integer_zero_node);
+
+ return build (code, truth_type, lhs, rhs);
+ }
/* See if the comparisons can be merged. Then get all the parameters for
each side. */
@@ -4153,6 +3708,11 @@ fold_truthop (code, truth_type, lhs, rhs)
return 0;
}
+ /* After this point all optimizations will generate bit-field
+ references, which we might not want. */
+ if (! (*lang_hooks.can_use_bit_fields_p) ())
+ return 0;
+
/* See if we can find a mode that contains both fields being compared on
the left. If we can't, fail. Otherwise, update all constants and masks
to be relative to a field of that size. */
@@ -4166,7 +3726,7 @@ fold_truthop (code, truth_type, lhs, rhs)
lnbitsize = GET_MODE_BITSIZE (lnmode);
lnbitpos = first_bit & ~ (lnbitsize - 1);
- lntype = type_for_size (lnbitsize, 1);
+ lntype = (*lang_hooks.types.type_for_size) (lnbitsize, 1);
xll_bitpos = ll_bitpos - lnbitpos, xrl_bitpos = rl_bitpos - lnbitpos;
if (BYTES_BIG_ENDIAN)
@@ -4237,7 +3797,7 @@ fold_truthop (code, truth_type, lhs, rhs)
rnbitsize = GET_MODE_BITSIZE (rnmode);
rnbitpos = first_bit & ~ (rnbitsize - 1);
- rntype = type_for_size (rnbitsize, 1);
+ rntype = (*lang_hooks.types.type_for_size) (rnbitsize, 1);
xlr_bitpos = lr_bitpos - rnbitpos, xrr_bitpos = rr_bitpos - rnbitpos;
if (BYTES_BIG_ENDIAN)
@@ -4485,6 +4045,31 @@ extract_muldiv (t, c, code, wide_type)
enum tree_code code;
tree wide_type;
{
+ /* To avoid exponential search depth, refuse to allow recursion past
+ three levels. Beyond that (1) it's highly unlikely that we'll find
+ something interesting and (2) we've probably processed it before
+ when we built the inner expression. */
+
+ static int depth;
+ tree ret;
+
+ if (depth > 3)
+ return NULL;
+
+ depth++;
+ ret = extract_muldiv_1 (t, c, code, wide_type);
+ depth--;
+
+ return ret;
+}
+
+static tree
+extract_muldiv_1 (t, c, code, wide_type)
+ tree t;
+ tree c;
+ enum tree_code code;
+ tree wide_type;
+{
tree type = TREE_TYPE (t);
enum tree_code tcode = TREE_CODE (t);
tree ctype = (wide_type != 0 && (GET_MODE_SIZE (TYPE_MODE (wide_type))
@@ -4517,22 +4102,27 @@ extract_muldiv (t, c, code, wide_type)
break;
case CONVERT_EXPR: case NON_LVALUE_EXPR: case NOP_EXPR:
- /* If op0 is an expression... */
+ /* If op0 is an expression ... */
if ((TREE_CODE_CLASS (TREE_CODE (op0)) == '<'
|| TREE_CODE_CLASS (TREE_CODE (op0)) == '1'
|| TREE_CODE_CLASS (TREE_CODE (op0)) == '2'
|| TREE_CODE_CLASS (TREE_CODE (op0)) == 'e')
- /* ...and is unsigned, and its type is smaller than ctype,
- then we cannot pass through this widening. */
+ /* ... and is unsigned, and its type is smaller than ctype,
+ then we cannot pass through as widening. */
&& ((TREE_UNSIGNED (TREE_TYPE (op0))
&& ! (TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE
&& TYPE_IS_SIZETYPE (TREE_TYPE (op0)))
&& (GET_MODE_SIZE (TYPE_MODE (ctype))
- > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))))
- /* ...and its type is larger than ctype,
+ > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))))
+ /* ... or its type is larger than ctype,
then we cannot pass through this truncation. */
|| (GET_MODE_SIZE (TYPE_MODE (ctype))
- < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0))))))
+ < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0))))
+ /* ... or signedness changes for division or modulus,
+ then we cannot pass through this conversion. */
+ || (code != MULT_EXPR
+ && (TREE_UNSIGNED (ctype)
+ != TREE_UNSIGNED (TREE_TYPE (op0))))))
break;
/* Pass the constant down and see if we can make a simplification. If
@@ -4572,25 +4162,6 @@ extract_muldiv (t, c, code, wide_type)
TREE_OPERAND (t, 1));
break;
- case SAVE_EXPR:
- /* If this has not been evaluated and the operand has no side effects,
- we can see if we can do something inside it and make a new one.
- Note that this test is overly conservative since we can do this
- if the only reason it had side effects is that it was another
- similar SAVE_EXPR, but that isn't worth bothering with. */
- if (SAVE_EXPR_RTL (t) == 0 && ! TREE_SIDE_EFFECTS (TREE_OPERAND (t, 0))
- && 0 != (t1 = extract_muldiv (TREE_OPERAND (t, 0), c, code,
- wide_type)))
- {
- t1 = save_expr (t1);
- if (SAVE_EXPR_PERSISTENT_P (t) && TREE_CODE (t1) == SAVE_EXPR)
- SAVE_EXPR_PERSISTENT_P (t1) = 1;
- if (is_pending_size (t))
- put_pending_size (t1);
- return t1;
- }
- break;
-
case LSHIFT_EXPR: case RSHIFT_EXPR:
/* If the second operand is constant, this is a multiplication
or floor division, by a power of two, so we can treat it that
@@ -4652,13 +4223,13 @@ extract_muldiv (t, c, code, wide_type)
of our constant, do the operation and verify it doesn't overflow. */
if (code == MULT_EXPR
|| integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
- {
- op1 = const_binop (code, convert (ctype, op1), convert (ctype, c), 0);
- if (op1 == 0 || TREE_OVERFLOW (op1))
- break;
- }
+ {
+ op1 = const_binop (code, convert (ctype, op1), convert (ctype, c), 0);
+ if (op1 == 0 || TREE_OVERFLOW (op1))
+ break;
+ }
else
- break;
+ break;
/* If we have an unsigned type is not a sizetype, we cannot widen
the operation since it will change the result if the original
@@ -4801,8 +4372,8 @@ constant_boolean_node (value, type)
if (type == integer_type_node)
return value ? integer_one_node : integer_zero_node;
else if (TREE_CODE (type) == BOOLEAN_TYPE)
- return truthvalue_conversion (value ? integer_one_node :
- integer_zero_node);
+ return (*lang_hooks.truthvalue_conversion) (value ? integer_one_node :
+ integer_zero_node);
else
{
tree t = build_int_2 (value, 0);
@@ -4833,10 +4404,10 @@ count_cond (expr, lim)
return MIN (lim, 1 + ctrue + cfalse);
}
-/* Transform `a + (b ? x : y)' into `x ? (a + b) : (a + y)'.
+/* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'. Here
CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)'
- expression, and ARG to `a'. If COND_FIRST_P is non-zero, then the
+ expression, and ARG to `a'. If COND_FIRST_P is nonzero, then the
COND is the first argument to CODE; otherwise (as in the example
given here), it is the second argument. TYPE is the type of the
original expression. */
@@ -4897,15 +4468,23 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
we simply build `a, throw 3'. */
if (VOID_TYPE_P (TREE_TYPE (true_value)))
{
- lhs_code = COMPOUND_EXPR;
- if (!cond_first_p)
- lhs_type = void_type_node;
+ if (! cond_first_p)
+ {
+ lhs_code = COMPOUND_EXPR;
+ lhs_type = void_type_node;
+ }
+ else
+ lhs = true_value;
}
if (VOID_TYPE_P (TREE_TYPE (false_value)))
{
- rhs_code = COMPOUND_EXPR;
- if (!cond_first_p)
- rhs_type = void_type_node;
+ if (! cond_first_p)
+ {
+ rhs_code = COMPOUND_EXPR;
+ rhs_type = void_type_node;
+ }
+ else
+ rhs = false_value;
}
}
else
@@ -4915,7 +4494,7 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
true_value = convert (testtype, integer_one_node);
false_value = convert (testtype, integer_zero_node);
}
-
+
/* If ARG is complex we want to make sure we only evaluate
it once. Though this is only required if it is volatile, it
might be more efficient even if it is not. However, if we
@@ -4924,25 +4503,26 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
primarily to see if we do end up with constant and this
SAVE_EXPR interferes with later optimizations, suppressing
it when we can is important.
-
+
If we are not in a function, we can't make a SAVE_EXPR, so don't
try to do so. Don't try to see if the result is a constant
if an arm is a COND_EXPR since we get exponential behavior
in that case. */
-
+
if (TREE_CODE (arg) == SAVE_EXPR)
save = 1;
- else if (! TREE_CONSTANT (arg)
- && global_bindings_p () == 0
+ else if (lhs == 0 && rhs == 0
+ && !TREE_CONSTANT (arg)
+ && (*lang_hooks.decls.global_bindings_p) () == 0
&& ((TREE_CODE (arg) != VAR_DECL && TREE_CODE (arg) != PARM_DECL)
|| TREE_SIDE_EFFECTS (arg)))
{
if (TREE_CODE (true_value) != COND_EXPR)
lhs = fold (build (lhs_code, lhs_type, *true_lhs, *true_rhs));
-
+
if (TREE_CODE (false_value) != COND_EXPR)
rhs = fold (build (rhs_code, rhs_type, *false_lhs, *false_rhs));
-
+
if ((lhs == 0 || ! TREE_CONSTANT (lhs))
&& (rhs == 0 || !TREE_CONSTANT (rhs)))
{
@@ -4951,14 +4531,14 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
save = 1;
}
}
-
+
if (lhs == 0)
lhs = fold (build (lhs_code, lhs_type, *true_lhs, *true_rhs));
if (rhs == 0)
rhs = fold (build (rhs_code, rhs_type, *false_lhs, *false_rhs));
-
+
test = fold (build (COND_EXPR, type, test, lhs, rhs));
-
+
if (save)
return build (COMPOUND_EXPR, type,
convert (void_type_node, arg),
@@ -4968,6 +4548,43 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
}
+/* Subroutine of fold() that checks for the addition of +/- 0.0.
+
+ If !NEGATE, return true if ADDEND is +/-0.0 and, for all X of type
+ TYPE, X + ADDEND is the same as X. If NEGATE, return true if X -
+ ADDEND is the same as X.
+
+ X + 0 and X - 0 both give X when X is NaN, infinite, or nonzero
+ and finite. The problematic cases are when X is zero, and its mode
+ has signed zeros. In the case of rounding towards -infinity,
+ X - 0 is not the same as X because 0 - 0 is -0. In other rounding
+ modes, X + 0 is not the same as X because -0 + 0 is 0. */
+
+static bool
+fold_real_zero_addition_p (type, addend, negate)
+ tree type, addend;
+ int negate;
+{
+ if (!real_zerop (addend))
+ return false;
+
+ /* Allow the fold if zeros aren't signed, or their sign isn't important. */
+ if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
+ return true;
+
+ /* Treat x + -0 as x - 0 and x - -0 as x + 0. */
+ if (TREE_CODE (addend) == REAL_CST
+ && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (addend)))
+ negate = !negate;
+
+ /* The mode has signed zeros, and we have to honor their sign.
+ In this situation, there is only one case we can return true for.
+ X - 0 is the same as X unless rounding towards -infinity is
+ supported. */
+ return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type));
+}
+
+
/* Perform constant folding and related simplification of EXPR.
The related simplifications include x*1 => x, x*0 => 0, etc.,
and application of the associative law.
@@ -5022,9 +4639,7 @@ fold (expr)
subop = arg0;
if (subop != 0 && TREE_CODE (subop) != INTEGER_CST
-#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
&& TREE_CODE (subop) != REAL_CST
-#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
)
/* Note that TREE_CONSTANT isn't enough:
static var addresses are constant but we can't
@@ -5059,10 +4674,7 @@ fold (expr)
subop = op;
if (TREE_CODE (subop) != INTEGER_CST
-#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
- && TREE_CODE (subop) != REAL_CST
-#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
- )
+ && TREE_CODE (subop) != REAL_CST)
/* Note that TREE_CONSTANT isn't enough:
static var addresses are constant but we can't
do arithmetic on them. */
@@ -5135,9 +4747,14 @@ fold (expr)
fold (build1 (code, type, TREE_OPERAND (arg0, 1))));
else if (TREE_CODE (arg0) == COND_EXPR)
{
+ tree arg01 = TREE_OPERAND (arg0, 1);
+ tree arg02 = TREE_OPERAND (arg0, 2);
+ if (! VOID_TYPE_P (TREE_TYPE (arg01)))
+ arg01 = fold (build1 (code, type, arg01));
+ if (! VOID_TYPE_P (TREE_TYPE (arg02)))
+ arg02 = fold (build1 (code, type, arg02));
t = fold (build (COND_EXPR, type, TREE_OPERAND (arg0, 0),
- fold (build1 (code, type, TREE_OPERAND (arg0, 1))),
- fold (build1 (code, type, TREE_OPERAND (arg0, 2)))));
+ arg01, arg02));
/* If this was a conversion, and all we did was to move into
inside the COND_EXPR, bring it back out. But leave it if
@@ -5153,6 +4770,8 @@ fold (expr)
&& TREE_CODE (t) == COND_EXPR
&& TREE_CODE (TREE_OPERAND (t, 1)) == code
&& TREE_CODE (TREE_OPERAND (t, 2)) == code
+ && ! VOID_TYPE_P (TREE_OPERAND (t, 1))
+ && ! VOID_TYPE_P (TREE_OPERAND (t, 2))
&& (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 1), 0))
== TREE_TYPE (TREE_OPERAND (TREE_OPERAND (t, 2), 0)))
&& ! (INTEGRAL_TYPE_P (TREE_TYPE (t))
@@ -5176,7 +4795,9 @@ fold (expr)
else if (TREE_CODE_CLASS (code) == '2'
|| TREE_CODE_CLASS (code) == '<')
{
- if (TREE_CODE (arg1) == COMPOUND_EXPR)
+ if (TREE_CODE (arg1) == COMPOUND_EXPR
+ && ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg1, 0))
+ && ! TREE_SIDE_EFFECTS (arg0))
return build (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
fold (build (code, type,
arg0, TREE_OPERAND (arg1, 1))));
@@ -5186,9 +4807,9 @@ fold (expr)
&& (TREE_CODE (arg0) != COND_EXPR
|| count_cond (arg0, 25) + count_cond (arg1, 25) <= 25)
&& (! TREE_SIDE_EFFECTS (arg0)
- || (global_bindings_p () == 0
+ || ((*lang_hooks.decls.global_bindings_p) () == 0
&& ! contains_placeholder_p (arg0))))
- return
+ return
fold_binary_op_with_conditional_arg (code, type, arg1, arg0,
/*cond_first_p=*/0);
else if (TREE_CODE (arg0) == COMPOUND_EXPR)
@@ -5200,9 +4821,9 @@ fold (expr)
&& (TREE_CODE (arg1) != COND_EXPR
|| count_cond (arg0, 25) + count_cond (arg1, 25) <= 25)
&& (! TREE_SIDE_EFFECTS (arg1)
- || (global_bindings_p () == 0
+ || ((*lang_hooks.decls.global_bindings_p) () == 0
&& ! contains_placeholder_p (arg1))))
- return
+ return
fold_binary_op_with_conditional_arg (code, type, arg0, arg1,
/*cond_first_p=*/1);
}
@@ -5331,6 +4952,50 @@ fold (expr)
TREE_USED (t) = 1;
return t;
}
+
+ /* Convert (T)(x & c) into (T)x & (T)c, if c is an integer
+ constants (if x has signed type, the sign bit cannot be set
+ in c). This folds extension into the BIT_AND_EXPR. */
+ if (INTEGRAL_TYPE_P (TREE_TYPE (t))
+ && TREE_CODE (TREE_TYPE (t)) != BOOLEAN_TYPE
+ && TREE_CODE (TREE_OPERAND (t, 0)) == BIT_AND_EXPR
+ && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) == INTEGER_CST)
+ {
+ tree and = TREE_OPERAND (t, 0);
+ tree and0 = TREE_OPERAND (and, 0), and1 = TREE_OPERAND (and, 1);
+ int change = 0;
+
+ if (TREE_UNSIGNED (TREE_TYPE (and))
+ || (TYPE_PRECISION (TREE_TYPE (t))
+ <= TYPE_PRECISION (TREE_TYPE (and))))
+ change = 1;
+ else if (TYPE_PRECISION (TREE_TYPE (and1))
+ <= HOST_BITS_PER_WIDE_INT
+ && host_integerp (and1, 1))
+ {
+ unsigned HOST_WIDE_INT cst;
+
+ cst = tree_low_cst (and1, 1);
+ cst &= (HOST_WIDE_INT) -1
+ << (TYPE_PRECISION (TREE_TYPE (and1)) - 1);
+ change = (cst == 0);
+#ifdef LOAD_EXTEND_OP
+ if (change
+ && (LOAD_EXTEND_OP (TYPE_MODE (TREE_TYPE (and0)))
+ == ZERO_EXTEND))
+ {
+ tree uns = (*lang_hooks.types.unsigned_type) (TREE_TYPE (and0));
+ and0 = convert (uns, and0);
+ and1 = convert (uns, and1);
+ }
+#endif
+ }
+ if (change)
+ return fold (build (BIT_AND_EXPR, TREE_TYPE (t),
+ convert (TREE_TYPE (t), and0),
+ convert (TREE_TYPE (t), and1)));
+ }
+
if (!wins)
{
TREE_CONSTANT (t) = TREE_CONSTANT (arg0);
@@ -5344,24 +5009,6 @@ fold (expr)
TREE_OPERAND (TREE_OPERAND (t, 0), 0));
return t;
-#if 0 /* This loses on &"foo"[0]. */
- case ARRAY_REF:
- {
- int i;
-
- /* Fold an expression like: "foo"[2] */
- if (TREE_CODE (arg0) == STRING_CST
- && TREE_CODE (arg1) == INTEGER_CST
- && compare_tree_int (arg1, TREE_STRING_LENGTH (arg0)) < 0)
- {
- t = build_int_2 (TREE_STRING_POINTER (arg0)[TREE_INT_CST_LOW (arg))], 0);
- TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (arg0));
- force_fit_type (t, 0);
- }
- }
- return t;
-#endif /* 0 */
-
case COMPONENT_REF:
if (TREE_CODE (arg0) == CONSTRUCTOR)
{
@@ -5602,16 +5249,15 @@ fold (expr)
same));
}
}
- /* In IEEE floating point, x+0 may not equal x. */
- else if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || flag_unsafe_math_optimizations)
- && real_zerop (arg1))
- return non_lvalue (convert (type, arg0));
- /* x+(-0) equals x, even for IEEE. */
- else if (TREE_CODE (arg1) == REAL_CST
- && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (arg1)))
+
+ /* See if ARG1 is zero and X + ARG1 reduces to X. */
+ else if (fold_real_zero_addition_p (TREE_TYPE (arg0), arg1, 0))
return non_lvalue (convert (type, arg0));
+ /* Likewise if the operands are reversed. */
+ else if (fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
+ return non_lvalue (convert (type, arg1));
+
bit_rotate:
/* (A << C1) + (A >> C2) if A is unsigned and C1+C2 is the size of A
is a rotate of A by C1 bits. */
@@ -5762,10 +5408,6 @@ fold (expr)
}
binary:
-#if defined (REAL_IS_NOT_DOUBLE) && ! defined (REAL_ARITHMETIC)
- if (TREE_CODE (arg1) == REAL_CST)
- return t;
-#endif /* REAL_IS_NOT_DOUBLE, and no REAL_ARITHMETIC */
if (wins)
t1 = const_binop (code, arg0, arg1, 0);
if (t1 != NULL_TREE)
@@ -5812,16 +5454,15 @@ fold (expr)
TREE_OPERAND (arg0, 1)));
}
- else if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || flag_unsafe_math_optimizations)
- {
- /* Except with IEEE floating point, 0-x equals -x. */
- if (! wins && real_zerop (arg0))
- return negate_expr (convert (type, arg1));
- /* Except with IEEE floating point, x-0 equals x. */
- if (real_zerop (arg1))
- return non_lvalue (convert (type, arg0));
- }
+ /* See if ARG1 is zero and X - ARG1 reduces to X. */
+ else if (fold_real_zero_addition_p (TREE_TYPE (arg0), arg1, 1))
+ return non_lvalue (convert (type, arg0));
+
+ /* (ARG0 - ARG1) is the same as (-ARG1 + ARG0). So check whether
+ ARG0 is zero and X + ARG0 reduces to X, since that would mean
+ (-ARG1 + ARG0) reduces to -ARG1. */
+ else if (!wins && fold_real_zero_addition_p (TREE_TYPE (arg1), arg0, 0))
+ return negate_expr (convert (type, arg1));
/* Fold &x - &x. This can happen from &x.foo - &x.
This is unsafe for certain floats even in non-IEEE formats.
@@ -5866,18 +5507,27 @@ fold (expr)
}
else
{
- /* x*0 is 0, except for IEEE floating point. */
- if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || flag_unsafe_math_optimizations)
+ /* Maybe fold x * 0 to 0. The expressions aren't the same
+ when x is NaN, since x * 0 is also NaN. Nor are they the
+ same in modes with signed zeros, since multiplying a
+ negative value by 0 gives -0, not +0. */
+ if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))
+ && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg0)))
&& real_zerop (arg1))
return omit_one_operand (type, arg1, arg0);
- /* In IEEE floating point, x*1 is not equivalent to x for snans.
- However, ANSI says we can drop signals,
- so we can do this anyway. */
- if (real_onep (arg1))
+ /* In IEEE floating point, x*1 is not equivalent to x for snans. */
+ if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+ && real_onep (arg1))
return non_lvalue (convert (type, arg0));
+
+ /* Transform x * -1.0 into -x. */
+ if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+ && real_minus_onep (arg1))
+ return fold (build1 (NEGATE_EXPR, type, arg0));
+
/* x*2 is x+x */
- if (! wins && real_twop (arg1) && global_bindings_p () == 0
+ if (! wins && real_twop (arg1)
+ && (*lang_hooks.decls.global_bindings_p) () == 0
&& ! contains_placeholder_p (arg0))
{
tree arg = save_expr (arg0);
@@ -5951,17 +5601,6 @@ fold (expr)
if (t1 != NULL_TREE)
return t1;
/* Simplify ((int)c & 0x377) into (int)c, if c is unsigned char. */
- if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == NOP_EXPR
- && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg1, 0))))
- {
- unsigned int prec
- = TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0)));
-
- if (prec < BITS_PER_WORD && prec < HOST_BITS_PER_WIDE_INT
- && (~TREE_INT_CST_LOW (arg0)
- & (((HOST_WIDE_INT) 1 << prec) - 1)) == 0)
- return build1 (NOP_EXPR, type, TREE_OPERAND (arg1, 0));
- }
if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR
&& TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
{
@@ -6005,22 +5644,21 @@ fold (expr)
goto binary;
case RDIV_EXPR:
- /* In most cases, do nothing with a divide by zero. */
-#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
-#ifndef REAL_INFINITY
- if (TREE_CODE (arg1) == REAL_CST && real_zerop (arg1))
+ /* Don't touch a floating-point divide by zero unless the mode
+ of the constant can represent infinity. */
+ if (TREE_CODE (arg1) == REAL_CST
+ && !MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (arg1)))
+ && real_zerop (arg1))
return t;
-#endif
-#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
/* (-A) / (-B) -> A / B */
if (TREE_CODE (arg0) == NEGATE_EXPR && TREE_CODE (arg1) == NEGATE_EXPR)
return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg1, 0)));
- /* In IEEE floating point, x/1 is not equivalent to x for snans.
- However, ANSI says we can drop signals, so we can do this anyway. */
- if (real_onep (arg1))
+ /* In IEEE floating point, x/1 is not equivalent to x for snans. */
+ if (!HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
+ && real_onep (arg1))
return non_lvalue (convert (type, arg0));
/* If ARG1 is a constant, we can convert this to a multiply by the
@@ -6323,6 +5961,20 @@ fold (expr)
case GT_EXPR:
case LE_EXPR:
case GE_EXPR:
+ /* If one arg is a real or integer constant, put it last. */
+ if ((TREE_CODE (arg0) == INTEGER_CST
+ && TREE_CODE (arg1) != INTEGER_CST)
+ || (TREE_CODE (arg0) == REAL_CST
+ && TREE_CODE (arg0) != REAL_CST))
+ {
+ TREE_OPERAND (t, 0) = arg1;
+ TREE_OPERAND (t, 1) = arg0;
+ arg0 = TREE_OPERAND (t, 0);
+ arg1 = TREE_OPERAND (t, 1);
+ code = swap_tree_comparison (code);
+ TREE_SET_CODE (t, code);
+ }
+
if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
{
/* (-a) CMP (-b) -> b CMP a */
@@ -6344,18 +5996,21 @@ fold (expr)
&& REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (arg1)))
return fold (build (code, type, arg0,
build_real (TREE_TYPE (arg1), dconst0)));
- }
- /* If one arg is a constant integer, put it last. */
- if (TREE_CODE (arg0) == INTEGER_CST
- && TREE_CODE (arg1) != INTEGER_CST)
- {
- TREE_OPERAND (t, 0) = arg1;
- TREE_OPERAND (t, 1) = arg0;
- arg0 = TREE_OPERAND (t, 0);
- arg1 = TREE_OPERAND (t, 1);
- code = swap_tree_comparison (code);
- TREE_SET_CODE (t, code);
+ /* If this is a comparison of a real constant with a PLUS_EXPR
+ or a MINUS_EXPR of a real constant, we can convert it into a
+ comparison with a revised real constant as long as no overflow
+ occurs when unsafe_math_optimizations are enabled. */
+ if (flag_unsafe_math_optimizations
+ && TREE_CODE (arg1) == REAL_CST
+ && (TREE_CODE (arg0) == PLUS_EXPR
+ || TREE_CODE (arg0) == MINUS_EXPR)
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
+ && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
+ ? MINUS_EXPR : PLUS_EXPR,
+ arg1, TREE_OPERAND (arg0, 1), 0))
+ && ! TREE_CONSTANT_OVERFLOW (tem))
+ return fold (build (code, type, TREE_OPERAND (arg0, 0), tem));
}
/* Convert foo++ == CONST into ++foo == CONST + INCR.
@@ -6421,7 +6076,7 @@ fold (expr)
|| integer_onep (folded_compare))
return omit_one_operand (type, folded_compare, varop);
- unsigned_type = type_for_size (size, 1);
+ unsigned_type = (*lang_hooks.types.type_for_size)(size, 1);
precision = TYPE_PRECISION (unsigned_type);
mask = build_int_2 (~0, ~0);
TREE_TYPE (mask) = unsigned_type;
@@ -6482,7 +6137,7 @@ fold (expr)
|| integer_onep (folded_compare))
return omit_one_operand (type, folded_compare, varop);
- unsigned_type = type_for_size (size, 1);
+ unsigned_type = (*lang_hooks.types.type_for_size)(size, 1);
precision = TYPE_PRECISION (unsigned_type);
mask = build_int_2 (~0, ~0);
TREE_TYPE (mask) = TREE_TYPE (varop);
@@ -6503,9 +6158,34 @@ fold (expr)
}
}
+ /* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0.
+ This transformation affects the cases which are handled in later
+ optimizations involving comparisons with non-negative constants. */
+ if (TREE_CODE (arg1) == INTEGER_CST
+ && TREE_CODE (arg0) != INTEGER_CST
+ && tree_int_cst_sgn (arg1) > 0)
+ {
+ switch (code)
+ {
+ case GE_EXPR:
+ code = GT_EXPR;
+ arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+ t = build (code, type, TREE_OPERAND (t, 0), arg1);
+ break;
+
+ case LT_EXPR:
+ code = LE_EXPR;
+ arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+ t = build (code, type, TREE_OPERAND (t, 0), arg1);
+ break;
+
+ default:
+ break;
+ }
+ }
+
/* Comparisons with the highest or lowest possible integer of
- the specified size will have known values and an unsigned
- <= 0x7fffffff can be simplified. */
+ the specified size will have known values. */
{
int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));
@@ -6515,43 +6195,76 @@ fold (expr)
&& (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
|| POINTER_TYPE_P (TREE_TYPE (arg1))))
{
+ unsigned HOST_WIDE_INT signed_max;
+ unsigned HOST_WIDE_INT max, min;
+
+ signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1;
+
+ if (TREE_UNSIGNED (TREE_TYPE (arg1)))
+ {
+ max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
+ min = 0;
+ }
+ else
+ {
+ max = signed_max;
+ min = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+ }
+
if (TREE_INT_CST_HIGH (arg1) == 0
- && (TREE_INT_CST_LOW (arg1)
- == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
- && ! TREE_UNSIGNED (TREE_TYPE (arg1)))
- switch (TREE_CODE (t))
+ && TREE_INT_CST_LOW (arg1) == max)
+ switch (code)
{
case GT_EXPR:
return omit_one_operand (type,
convert (type, integer_zero_node),
arg0);
case GE_EXPR:
+ code = EQ_EXPR;
TREE_SET_CODE (t, EQ_EXPR);
break;
-
case LE_EXPR:
return omit_one_operand (type,
convert (type, integer_one_node),
arg0);
case LT_EXPR:
+ code = NE_EXPR;
TREE_SET_CODE (t, NE_EXPR);
break;
+ /* The GE_EXPR and LT_EXPR cases above are not normally
+ reached because of previous transformations. */
+
default:
break;
}
-
- else if (TREE_INT_CST_HIGH (arg1) == -1
- && (TREE_INT_CST_LOW (arg1)
- == ((unsigned HOST_WIDE_INT) -1 << (width - 1)))
- && ! TREE_UNSIGNED (TREE_TYPE (arg1)))
- switch (TREE_CODE (t))
+ else if (TREE_INT_CST_HIGH (arg1) == 0
+ && TREE_INT_CST_LOW (arg1) == max - 1)
+ switch (code)
+ {
+ case GT_EXPR:
+ code = EQ_EXPR;
+ arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
+ t = build (code, type, TREE_OPERAND (t, 0), arg1);
+ break;
+ case LE_EXPR:
+ code = NE_EXPR;
+ arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
+ t = build (code, type, TREE_OPERAND (t, 0), arg1);
+ break;
+ default:
+ break;
+ }
+ else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
+ && TREE_INT_CST_LOW (arg1) == min)
+ switch (code)
{
case LT_EXPR:
return omit_one_operand (type,
convert (type, integer_zero_node),
arg0);
case LE_EXPR:
+ code = EQ_EXPR;
TREE_SET_CODE (t, EQ_EXPR);
break;
@@ -6560,120 +6273,53 @@ fold (expr)
convert (type, integer_one_node),
arg0);
case GT_EXPR:
+ code = NE_EXPR;
TREE_SET_CODE (t, NE_EXPR);
break;
default:
break;
}
-
- else if (TREE_INT_CST_HIGH (arg1) == 0
- && (TREE_INT_CST_LOW (arg1)
- == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
- && TREE_UNSIGNED (TREE_TYPE (arg1))
- /* signed_type does not work on pointer types. */
- && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
- switch (TREE_CODE (t))
+ else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
+ && TREE_INT_CST_LOW (arg1) == min + 1)
+ switch (code)
{
- case LE_EXPR:
- return fold (build (GE_EXPR, type,
- convert (signed_type (TREE_TYPE (arg0)),
- arg0),
- convert (signed_type (TREE_TYPE (arg1)),
- integer_zero_node)));
- case GT_EXPR:
- return fold (build (LT_EXPR, type,
- convert (signed_type (TREE_TYPE (arg0)),
- arg0),
- convert (signed_type (TREE_TYPE (arg1)),
- integer_zero_node)));
-
+ case GE_EXPR:
+ code = NE_EXPR;
+ arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+ t = build (code, type, TREE_OPERAND (t, 0), arg1);
+ break;
+ case LT_EXPR:
+ code = EQ_EXPR;
+ arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+ t = build (code, type, TREE_OPERAND (t, 0), arg1);
+ break;
default:
break;
}
- else if (TREE_INT_CST_HIGH (arg1) == 0
- && (TREE_INT_CST_LOW (arg1)
- == ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1)
- && TREE_UNSIGNED (TREE_TYPE (arg1)))
- switch (TREE_CODE (t))
- {
- case GT_EXPR:
- return omit_one_operand (type,
- convert (type, integer_zero_node),
- arg0);
- case GE_EXPR:
- TREE_SET_CODE (t, EQ_EXPR);
- break;
-
- case LE_EXPR:
- return omit_one_operand (type,
- convert (type, integer_one_node),
- arg0);
- case LT_EXPR:
- TREE_SET_CODE (t, NE_EXPR);
- break;
-
- default:
- break;
- }
+ else if (TREE_INT_CST_HIGH (arg1) == 0
+ && TREE_INT_CST_LOW (arg1) == signed_max
+ && TREE_UNSIGNED (TREE_TYPE (arg1))
+ /* signed_type does not work on pointer types. */
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
+ {
+ /* The following case also applies to X < signed_max+1
+ and X >= signed_max+1 because previous transformations. */
+ if (code == LE_EXPR || code == GT_EXPR)
+ {
+ tree st0, st1;
+ st0 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg0));
+ st1 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg1));
+ return fold
+ (build (code == LE_EXPR ? GE_EXPR: LT_EXPR,
+ type, convert (st0, arg0),
+ convert (st1, integer_zero_node)));
+ }
+ }
}
}
- /* Change X >= CST to X > (CST - 1) and X < CST to X <= (CST - 1)
- if CST is positive. */
- if (TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (arg0) != INTEGER_CST
- && tree_int_cst_sgn (arg1) > 0)
- {
- switch (TREE_CODE (t))
- {
- case GE_EXPR:
- code = GT_EXPR;
- arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- t = build (code, type, TREE_OPERAND (t, 0), arg1);
- break;
-
- case LT_EXPR:
- code = LE_EXPR;
- arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
- t = build (code, type, TREE_OPERAND (t, 0), arg1);
- break;
-
- default:
- break;
- }
- }
-
- /* An unsigned comparison against 0 can be simplified. */
- if (integer_zerop (arg1)
- && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
- || POINTER_TYPE_P (TREE_TYPE (arg1)))
- && TREE_UNSIGNED (TREE_TYPE (arg1)))
- {
- switch (TREE_CODE (t))
- {
- case GT_EXPR:
- code = NE_EXPR;
- TREE_SET_CODE (t, NE_EXPR);
- break;
- case LE_EXPR:
- code = EQ_EXPR;
- TREE_SET_CODE (t, EQ_EXPR);
- break;
- case GE_EXPR:
- return omit_one_operand (type,
- convert (type, integer_one_node),
- arg0);
- case LT_EXPR:
- return omit_one_operand (type,
- convert (type, integer_zero_node),
- arg0);
- default:
- break;
- }
- }
-
/* If this is an EQ or NE comparison of a constant with a PLUS_EXPR or
a MINUS_EXPR of a constant, we can convert it into a comparison with
a revised constant as long as no overflow occurs. */
@@ -6786,7 +6432,7 @@ fold (expr)
|| TREE_CODE (arg0) == ROUND_MOD_EXPR)
&& integer_pow2p (TREE_OPERAND (arg0, 1)))
{
- tree newtype = unsigned_type (TREE_TYPE (arg0));
+ tree newtype = (*lang_hooks.types.unsigned_type) (TREE_TYPE (arg0));
tree newmod = build (TREE_CODE (arg0), newtype,
convert (newtype, TREE_OPERAND (arg0, 0)),
convert (newtype, TREE_OPERAND (arg0, 1)));
@@ -6807,8 +6453,25 @@ fold (expr)
&& TREE_CODE (arg0) == BIT_AND_EXPR
&& integer_pow2p (TREE_OPERAND (arg0, 1))
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
- return build (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
- arg0, integer_zero_node);
+ return fold (build (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+ arg0, integer_zero_node));
+
+ /* If we have (A & C) != 0 where C is the sign bit of A, convert
+ this into A < 0. Similarly for (A & C) == 0 into A >= 0. */
+ if ((code == EQ_EXPR || code == NE_EXPR)
+ && TREE_CODE (arg0) == BIT_AND_EXPR
+ && integer_zerop (arg1))
+ {
+ tree arg00 = sign_bit_p (TREE_OPERAND (arg0, 0),
+ TREE_OPERAND (arg0, 1));
+ if (arg00 != NULL_TREE)
+ {
+ tree stype = (*lang_hooks.types.signed_type) (TREE_TYPE (arg00));
+ return fold (build (code == EQ_EXPR ? GE_EXPR : LT_EXPR, type,
+ convert (stype, arg00),
+ convert (stype, integer_zero_node)));
+ }
+ }
/* If X is unsigned, convert X < (1 << Y) into X >> Y == 0
and similarly for >= into !=. */
@@ -6964,7 +6627,8 @@ fold (expr)
}
/* If this is a comparison of a field, we may be able to simplify it. */
- if ((TREE_CODE (arg0) == COMPONENT_REF
+ if (((TREE_CODE (arg0) == COMPONENT_REF
+ && (*lang_hooks.can_use_bit_fields_p) ())
|| TREE_CODE (arg0) == BIT_FIELD_REF)
&& (code == EQ_EXPR || code == NE_EXPR)
/* Handle the constant case even without -O
@@ -7004,7 +6668,7 @@ fold (expr)
}
/* Optimize comparisons of strlen vs zero to a compare of the
- first character of the string vs zero. To wit,
+ first character of the string vs zero. To wit,
strlen(ptr) == 0 => *ptr == 0
strlen(ptr) != 0 => *ptr != 0
Other cases should reduce to one of these two (or a constant)
@@ -7114,7 +6778,7 @@ fold (expr)
TREE_TYPE (t1) = type;
if (TREE_CODE (type) == BOOLEAN_TYPE)
- return truthvalue_conversion (t1);
+ return (*lang_hooks.truthvalue_conversion) (t1);
return t1;
case COND_EXPR:
@@ -7156,23 +6820,38 @@ fold (expr)
/* If we have A op B ? A : C, we may be able to convert this to a
simpler expression, depending on the operation and the values
- of B and C. IEEE floating point prevents this though,
- because A or B might be -0.0 or a NaN. */
+ of B and C. Signed zeros prevent all of these transformations,
+ for reasons given above each one. */
if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
- && (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || ! FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0)))
- || flag_unsafe_math_optimizations)
&& operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
- arg1, TREE_OPERAND (arg0, 1)))
+ arg1, TREE_OPERAND (arg0, 1))
+ && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
{
tree arg2 = TREE_OPERAND (t, 2);
enum tree_code comp_code = TREE_CODE (arg0);
STRIP_NOPS (arg2);
- /* If we have A op 0 ? A : -A, this is A, -A, abs (A), or -abs (A),
- depending on the comparison operation. */
+ /* If we have A op 0 ? A : -A, consider applying the following
+ transformations:
+
+ A == 0? A : -A same as -A
+ A != 0? A : -A same as A
+ A >= 0? A : -A same as abs (A)
+ A > 0? A : -A same as abs (A)
+ A <= 0? A : -A same as -abs (A)
+ A < 0? A : -A same as -abs (A)
+
+ None of these transformations work for modes with signed
+ zeros. If A is +/-0, the first two transformations will
+ change the sign of the result (from +0 to -0, or vice
+ versa). The last four will fix the sign of the result,
+ even though the original expressions could be positive or
+ negative, depending on the sign of A.
+
+ Note that all these transformations are correct if A is
+ NaN, since the two alternatives (A and -A) are also NaNs. */
if ((FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 1)))
? real_zerop (TREE_OPERAND (arg0, 1))
: integer_zerop (TREE_OPERAND (arg0, 1)))
@@ -7187,20 +6866,21 @@ fold (expr)
negate_expr
(convert (TREE_TYPE (TREE_OPERAND (t, 1)),
arg1))));
-
case NE_EXPR:
return pedantic_non_lvalue (convert (type, arg1));
case GE_EXPR:
case GT_EXPR:
if (TREE_UNSIGNED (TREE_TYPE (arg1)))
- arg1 = convert (signed_type (TREE_TYPE (arg1)), arg1);
+ arg1 = convert ((*lang_hooks.types.signed_type)
+ (TREE_TYPE (arg1)), arg1);
return pedantic_non_lvalue
(convert (type, fold (build1 (ABS_EXPR,
TREE_TYPE (arg1), arg1))));
case LE_EXPR:
case LT_EXPR:
if (TREE_UNSIGNED (TREE_TYPE (arg1)))
- arg1 = convert (signed_type (TREE_TYPE (arg1)), arg1);
+ arg1 = convert ((lang_hooks.types.signed_type)
+ (TREE_TYPE (arg1)), arg1);
return pedantic_non_lvalue
(negate_expr (convert (type,
fold (build1 (ABS_EXPR,
@@ -7210,8 +6890,10 @@ fold (expr)
abort ();
}
- /* If this is A != 0 ? A : 0, this is simply A. For ==, it is
- always zero. */
+ /* A != 0 ? A : 0 is simply A, unless A is -0. Likewise
+ A == 0 ? A : 0 is always 0 unless A is -0. Note that
+ both transformations are correct when A is NaN: A != 0
+ is then true, and A == 0 is false. */
if (integer_zerop (TREE_OPERAND (arg0, 1)) && integer_zerop (arg2))
{
@@ -7221,9 +6903,32 @@ fold (expr)
return pedantic_non_lvalue (convert (type, integer_zero_node));
}
- /* If this is A op B ? A : B, this is either A, B, min (A, B),
- or max (A, B), depending on the operation. */
-
+ /* Try some transformations of A op B ? A : B.
+
+ A == B? A : B same as B
+ A != B? A : B same as A
+ A >= B? A : B same as max (A, B)
+ A > B? A : B same as max (B, A)
+ A <= B? A : B same as min (A, B)
+ A < B? A : B same as min (B, A)
+
+ As above, these transformations don't work in the presence
+ of signed zeros. For example, if A and B are zeros of
+ opposite sign, the first two transformations will change
+ the sign of the result. In the last four, the original
+ expressions give different results for (A=+0, B=-0) and
+ (A=-0, B=+0), but the transformed expressions do not.
+
+ The first two transformations are correct if either A or B
+ is a NaN. In the first transformation, the condition will
+ be false, and B will indeed be chosen. In the case of the
+ second transformation, the condition A != B will be true,
+ and A will be chosen.
+
+ The conversions to max() and min() are not correct if B is
+ a number and A is not. The conditions in the original
+ expressions will be false, so all four give B. The min()
+ and max() versions would give a NaN instead. */
if (operand_equal_for_comparison_p (TREE_OPERAND (arg0, 1),
arg2, TREE_OPERAND (arg0, 0)))
{
@@ -7247,21 +6952,23 @@ fold (expr)
operand which will be used if they are equal first
so that we can convert this back to the
corresponding COND_EXPR. */
- return pedantic_non_lvalue
- (convert (type, fold (build (MIN_EXPR, comp_type,
- (comp_code == LE_EXPR
- ? comp_op0 : comp_op1),
- (comp_code == LE_EXPR
- ? comp_op1 : comp_op0)))));
+ if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+ return pedantic_non_lvalue
+ (convert (type, fold (build (MIN_EXPR, comp_type,
+ (comp_code == LE_EXPR
+ ? comp_op0 : comp_op1),
+ (comp_code == LE_EXPR
+ ? comp_op1 : comp_op0)))));
break;
case GE_EXPR:
case GT_EXPR:
- return pedantic_non_lvalue
- (convert (type, fold (build (MAX_EXPR, comp_type,
- (comp_code == GE_EXPR
- ? comp_op0 : comp_op1),
- (comp_code == GE_EXPR
- ? comp_op1 : comp_op0)))));
+ if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+ return pedantic_non_lvalue
+ (convert (type, fold (build (MAX_EXPR, comp_type,
+ (comp_code == GE_EXPR
+ ? comp_op0 : comp_op1),
+ (comp_code == GE_EXPR
+ ? comp_op1 : comp_op0)))));
break;
default:
abort ();
@@ -7366,6 +7073,14 @@ fold (expr)
&& type == TREE_TYPE (arg0))
return pedantic_non_lvalue (arg0);
+ /* Convert A ? 0 : 1 to !A. This prefers the use of NOT_EXPR
+ over COND_EXPR in cases such as floating point comparisons. */
+ if (integer_zerop (TREE_OPERAND (t, 1))
+ && integer_onep (TREE_OPERAND (t, 2))
+ && truth_value_p (TREE_CODE (arg0)))
+ return pedantic_non_lvalue (convert (type,
+ invert_truthvalue (arg0)));
+
/* Look for expressions of the form A & 2 ? 2 : 0. The result of this
operation is simply A & 2. */
@@ -7378,6 +7093,25 @@ fold (expr)
arg1, 1))
return pedantic_non_lvalue (convert (type, TREE_OPERAND (arg0, 0)));
+ /* Convert A ? B : 0 into A && B if A and B are truth values. */
+ if (integer_zerop (TREE_OPERAND (t, 2))
+ && truth_value_p (TREE_CODE (arg0))
+ && truth_value_p (TREE_CODE (arg1)))
+ return pedantic_non_lvalue (fold (build (TRUTH_ANDIF_EXPR, type,
+ arg0, arg1)));
+
+ /* Convert A ? B : 1 into !A || B if A and B are truth values. */
+ if (integer_onep (TREE_OPERAND (t, 2))
+ && truth_value_p (TREE_CODE (arg0))
+ && truth_value_p (TREE_CODE (arg1)))
+ {
+ /* Only perform transformation if ARG0 is easily inverted. */
+ tem = invert_truthvalue (arg0);
+ if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
+ return pedantic_non_lvalue (fold (build (TRUTH_ORIF_EXPR, type,
+ tem, arg1)));
+ }
+
return t;
case COMPOUND_EXPR:
@@ -7612,7 +7346,7 @@ tree_expr_nonnegative_p (t)
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
- && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
case TRUNC_MOD_EXPR:
case CEIL_MOD_EXPR:
case FLOOR_MOD_EXPR:
@@ -7625,10 +7359,10 @@ tree_expr_nonnegative_p (t)
return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
case MIN_EXPR:
return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
- && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
case MAX_EXPR:
return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
- || tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+ || tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
case MODIFY_EXPR:
return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
case BIND_EXPR:
@@ -7639,7 +7373,7 @@ tree_expr_nonnegative_p (t)
return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
case RTL_EXPR:
return rtl_expr_nonnegative_p (RTL_EXPR_RTL (t));
-
+
default:
if (truth_value_p (TREE_CODE (t)))
/* Truth values evaluate to 0 or 1, which is nonnegative. */
@@ -7693,3 +7427,5 @@ rtl_expr_nonnegative_p (r)
return 0;
}
}
+
+#include "gt-fold-const.h"
diff --git a/contrib/gcc/function.c b/contrib/gcc/function.c
index f733076..daa2cab 100644
--- a/contrib/gcc/function.c
+++ b/contrib/gcc/function.c
@@ -53,9 +53,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "recog.h"
#include "output.h"
#include "basic-block.h"
-#include "obstack.h"
#include "toplev.h"
-#include "hash.h"
+#include "hashtab.h"
#include "ggc.h"
#include "tm_p.h"
#include "integrate.h"
@@ -75,7 +74,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
must define both, or neither. */
#ifndef NAME__MAIN
#define NAME__MAIN "__main"
-#define SYMBOL__MAIN __main
#endif
/* Round a value to the lowest integer less than it that is a multiple of
@@ -124,24 +122,12 @@ int current_function_uses_only_leaf_regs;
post-instantiation libcalls. */
int virtuals_instantiated;
-/* Assign unique numbers to labels generated for profiling. */
-static int profile_label_no;
+/* Assign unique numbers to labels generated for profiling, debugging, etc. */
+static int funcdef_no;
/* These variables hold pointers to functions to create and destroy
target specific, per-function data structures. */
-void (*init_machine_status) PARAMS ((struct function *));
-void (*free_machine_status) PARAMS ((struct function *));
-/* This variable holds a pointer to a function to register any
- data items in the target specific, per-function data structure
- that will need garbage collection. */
-void (*mark_machine_status) PARAMS ((struct function *));
-
-/* Likewise, but for language-specific data. */
-void (*init_lang_status) PARAMS ((struct function *));
-void (*save_lang_status) PARAMS ((struct function *));
-void (*restore_lang_status) PARAMS ((struct function *));
-void (*mark_lang_status) PARAMS ((struct function *));
-void (*free_lang_status) PARAMS ((struct function *));
+struct machine_function * (*init_machine_status) PARAMS ((void));
/* The FUNCTION_DECL for an inline function currently being expanded. */
tree inline_function_decl;
@@ -150,12 +136,12 @@ tree inline_function_decl;
struct function *cfun = 0;
/* These arrays record the INSN_UIDs of the prologue and epilogue insns. */
-static varray_type prologue;
-static varray_type epilogue;
+static GTY(()) varray_type prologue;
+static GTY(()) varray_type epilogue;
/* Array of INSN_UIDs to hold the INSN_UIDs for each sibcall epilogue
in this function. */
-static varray_type sibcall_epilogue;
+static GTY(()) varray_type sibcall_epilogue;
/* In order to evaluate some expressions, such as function calls returning
structures in memory, we need to temporarily allocate stack locations.
@@ -175,7 +161,7 @@ static varray_type sibcall_epilogue;
level where they are defined. They are marked a "kept" so that
free_temp_slots will not free them. */
-struct temp_slot
+struct temp_slot GTY(())
{
/* Points to next temporary slot. */
struct temp_slot *next;
@@ -195,13 +181,13 @@ struct temp_slot
tree type;
/* The value of `sequence_rtl_expr' when this temporary is allocated. */
tree rtl_expr;
- /* Non-zero if this temporary is currently in use. */
+ /* Nonzero if this temporary is currently in use. */
char in_use;
- /* Non-zero if this temporary has its address taken. */
+ /* Nonzero if this temporary has its address taken. */
char addr_taken;
/* Nesting level at which this slot is being used. */
int level;
- /* Non-zero if this should survive a call to free_temp_slots. */
+ /* Nonzero if this should survive a call to free_temp_slots. */
int keep;
/* The offset of the slot from the frame_pointer, including extra space
for alignment. This info is for combine_temp_slots. */
@@ -216,7 +202,7 @@ struct temp_slot
maintain this list in case two operands of an insn were required to match;
in that case we must ensure we use the same replacement. */
-struct fixup_replacement
+struct fixup_replacement GTY(())
{
rtx old;
rtx new;
@@ -225,9 +211,9 @@ struct fixup_replacement
struct insns_for_mem_entry
{
- /* The KEY in HE will be a MEM. */
- struct hash_entry he;
- /* These are the INSNS which reference the MEM. */
+ /* A MEM. */
+ rtx key;
+ /* These are the INSNs which reference the MEM. */
rtx insns;
};
@@ -239,25 +225,25 @@ static struct temp_slot *find_temp_slot_from_address PARAMS ((rtx));
static void put_reg_into_stack PARAMS ((struct function *, rtx, tree,
enum machine_mode, enum machine_mode,
int, unsigned int, int,
- struct hash_table *));
+ htab_t));
static void schedule_fixup_var_refs PARAMS ((struct function *, rtx, tree,
enum machine_mode,
- struct hash_table *));
+ htab_t));
static void fixup_var_refs PARAMS ((rtx, enum machine_mode, int, rtx,
- struct hash_table *));
+ htab_t));
static struct fixup_replacement
*find_fixup_replacement PARAMS ((struct fixup_replacement **, rtx));
static void fixup_var_refs_insns PARAMS ((rtx, rtx, enum machine_mode,
int, int, rtx));
static void fixup_var_refs_insns_with_hash
- PARAMS ((struct hash_table *, rtx,
+ PARAMS ((htab_t, rtx,
enum machine_mode, int, rtx));
static void fixup_var_refs_insn PARAMS ((rtx, rtx, enum machine_mode,
int, int, rtx));
static void fixup_var_refs_1 PARAMS ((rtx, enum machine_mode, rtx *, rtx,
struct fixup_replacement **, rtx));
static rtx fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode, int));
-static rtx walk_fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode,
+static rtx walk_fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode,
int));
static rtx fixup_stack_1 PARAMS ((rtx, rtx));
static void optimize_bit_field PARAMS ((rtx, rtx, rtx *));
@@ -269,10 +255,8 @@ static int instantiate_virtual_regs_1 PARAMS ((rtx *, rtx, int));
static void delete_handlers PARAMS ((void));
static void pad_to_arg_alignment PARAMS ((struct args_size *, int,
struct args_size *));
-#ifndef ARGS_GROW_DOWNWARD
static void pad_below PARAMS ((struct args_size *, enum machine_mode,
tree));
-#endif
static rtx round_trampoline_addr PARAMS ((rtx));
static rtx adjust_trampoline_addr PARAMS ((rtx));
static tree *identify_blocks_1 PARAMS ((rtx, tree *, tree *, tree *));
@@ -290,29 +274,25 @@ static int contains PARAMS ((rtx, varray_type));
#ifdef HAVE_return
static void emit_return_into_block PARAMS ((basic_block, rtx));
#endif
-static void put_addressof_into_stack PARAMS ((rtx, struct hash_table *));
+static void put_addressof_into_stack PARAMS ((rtx, htab_t));
static bool purge_addressof_1 PARAMS ((rtx *, rtx, int, int,
- struct hash_table *));
+ htab_t));
static void purge_single_hard_subreg_set PARAMS ((rtx));
#if defined(HAVE_epilogue) && defined(INCOMING_RETURN_ADDR_RTX)
static rtx keep_stack_depressed PARAMS ((rtx));
#endif
static int is_addressof PARAMS ((rtx *, void *));
-static struct hash_entry *insns_for_mem_newfunc PARAMS ((struct hash_entry *,
- struct hash_table *,
- hash_table_key));
-static unsigned long insns_for_mem_hash PARAMS ((hash_table_key));
-static bool insns_for_mem_comp PARAMS ((hash_table_key, hash_table_key));
+static hashval_t insns_for_mem_hash PARAMS ((const void *));
+static int insns_for_mem_comp PARAMS ((const void *, const void *));
static int insns_for_mem_walk PARAMS ((rtx *, void *));
-static void compute_insns_for_mem PARAMS ((rtx, rtx, struct hash_table *));
-static void mark_function_status PARAMS ((struct function *));
-static void maybe_mark_struct_function PARAMS ((void *));
+static void compute_insns_for_mem PARAMS ((rtx, rtx, htab_t));
static void prepare_function_start PARAMS ((void));
static void do_clobber_return_reg PARAMS ((rtx, void *));
static void do_use_return_reg PARAMS ((rtx, void *));
+static void instantiate_virtual_regs_lossage PARAMS ((rtx));
/* Pointer to chain of `struct function' for containing functions. */
-static struct function *outer_function_chain;
+static GTY(()) struct function *outer_function_chain;
/* Given a function decl for a containing function,
return the `struct function' for it. */
@@ -332,7 +312,7 @@ find_function_data (decl)
/* Save the current context for compilation of a nested function.
This is called from language-specific code. The caller should use
- the save_lang_status callback to save any language-specific state,
+ the enter_nested langhook to save any language-specific state,
since this function knows only about language-independent
variables. */
@@ -361,8 +341,7 @@ push_function_context_to (context)
outer_function_chain = p;
p->fixup_var_refs_queue = 0;
- if (save_lang_status)
- (*save_lang_status) (p);
+ (*lang_hooks.function.enter_nested) (p);
cfun = 0;
}
@@ -391,8 +370,7 @@ pop_function_context_from (context)
restore_emit_status (p);
- if (restore_lang_status)
- (*restore_lang_status) (p);
+ (*lang_hooks.function.leave_nested) (p);
/* Finish doing put_var_into_stack for any of our variables which became
addressable during the nested function. If only one entry has to be
@@ -445,9 +423,8 @@ free_after_parsing (f)
/* f->varasm is used by code generation. */
/* f->eh->eh_return_stub_label is used by code generation. */
- if (free_lang_status)
- (*free_lang_status) (f);
- free_stmt_status (f);
+ (*lang_hooks.function.final) (f);
+ f->stmt = NULL;
}
/* Clear out all parts of the state in F that can safely be discarded
@@ -458,16 +435,11 @@ void
free_after_compilation (f)
struct function *f;
{
- free_eh_status (f);
- free_expr_status (f);
- free_emit_status (f);
- free_varasm_status (f);
-
- if (free_machine_status)
- (*free_machine_status) (f);
-
- if (f->x_parm_reg_stack_loc)
- free (f->x_parm_reg_stack_loc);
+ f->eh = NULL;
+ f->expr = NULL;
+ f->emit = NULL;
+ f->varasm = NULL;
+ f->machine = NULL;
f->x_temp_slots = NULL;
f->arg_offset_rtx = NULL;
@@ -479,6 +451,8 @@ free_after_compilation (f)
f->x_nonlocal_goto_stack_level = NULL;
f->x_cleanup_label = NULL;
f->x_return_label = NULL;
+ f->computed_goto_common_label = NULL;
+ f->computed_goto_common_reg = NULL;
f->x_save_expr_regs = NULL;
f->x_stack_slot_list = NULL;
f->x_rtl_expr_chain = NULL;
@@ -560,7 +534,7 @@ assign_stack_local_1 (mode, size, align, function)
/* Allow the target to (possibly) increase the alignment of this
stack slot. */
- type = type_for_mode (mode, 0);
+ type = (*lang_hooks.types.type_for_mode) (mode, 0);
if (type)
alignment = LOCAL_ALIGNMENT (type, alignment);
@@ -680,7 +654,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
align = GET_MODE_ALIGNMENT (mode);
if (! type)
- type = type_for_mode (mode, 0);
+ type = (*lang_hooks.types.type_for_mode) (mode, 0);
if (type)
align = LOCAL_ALIGNMENT (type, align);
@@ -902,7 +876,7 @@ assign_temp (type_or_decl, keep, memory_required, dont_promote)
/* The size of the temporary may be too large to fit into an integer. */
/* ??? Not sure this should happen except for user silliness, so limit
- this to things that aren't compiler-generated temporaries. The
+ this to things that aren't compiler-generated temporaries. The
rest of the time we'll abort in assign_stack_temp_for_type. */
if (decl && size == -1
&& TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST)
@@ -1350,12 +1324,16 @@ init_temp_slots ()
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. */
+/* Retroactively move an auto variable from a register to a stack
+ slot. This is done when an address-reference to the variable is
+ seen. If RESCAN is true, all previously emitted instructions are
+ examined and modified to handle the fact that DECL is now
+ addressable. */
void
-put_var_into_stack (decl)
+put_var_into_stack (decl, rescan)
tree decl;
+ int rescan;
{
rtx reg;
enum machine_mode promoted_mode, decl_mode;
@@ -1369,8 +1347,8 @@ put_var_into_stack (decl)
context = decl_function_context (decl);
/* Get the current rtl used for this object and its original mode. */
- reg = (TREE_CODE (decl) == SAVE_EXPR
- ? SAVE_EXPR_RTL (decl)
+ reg = (TREE_CODE (decl) == SAVE_EXPR
+ ? SAVE_EXPR_RTL (decl)
: DECL_RTL_IF_SET (decl));
/* No need to do anything if decl has no rtx yet
@@ -1430,7 +1408,7 @@ put_var_into_stack (decl)
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);
+ gen_mem_addressof (reg, decl, rescan);
else
put_reg_into_stack (function, reg, TREE_TYPE (decl), promoted_mode,
decl_mode, volatilep, 0, usedp, 0);
@@ -1443,7 +1421,7 @@ put_var_into_stack (decl)
to the whole CONCAT, lest we do double fixups for the latter
references. */
enum machine_mode part_mode = GET_MODE (XEXP (reg, 0));
- tree part_type = type_for_mode (part_mode, 0);
+ tree part_type = (*lang_hooks.types.type_for_mode) (part_mode, 0);
rtx lopart = XEXP (reg, 0);
rtx hipart = XEXP (reg, 1);
#ifdef FRAME_GROWS_DOWNWARD
@@ -1477,7 +1455,7 @@ put_var_into_stack (decl)
/* Prevent sharing of rtl that might lose. */
if (GET_CODE (XEXP (reg, 0)) == PLUS)
XEXP (reg, 0) = copy_rtx (XEXP (reg, 0));
- if (usedp)
+ if (usedp && rescan)
{
schedule_fixup_var_refs (function, reg, TREE_TYPE (decl),
promoted_mode, 0);
@@ -1506,7 +1484,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
int volatile_p;
unsigned int original_regno;
int used_p;
- struct hash_table *ht;
+ htab_t ht;
{
struct function *func = function ? function : cfun;
rtx new = 0;
@@ -1554,7 +1532,7 @@ schedule_fixup_var_refs (function, reg, type, promoted_mode, ht)
rtx reg;
tree type;
enum machine_mode promoted_mode;
- struct hash_table *ht;
+ htab_t ht;
{
int unsigned_p = type ? TREE_UNSIGNED (type) : 0;
@@ -1580,7 +1558,7 @@ fixup_var_refs (var, promoted_mode, unsignedp, may_share, ht)
rtx var;
enum machine_mode promoted_mode;
int unsignedp;
- struct hash_table *ht;
+ htab_t ht;
rtx may_share;
{
tree pending;
@@ -1716,17 +1694,18 @@ fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel, may_share)
static void
fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp, may_share)
- struct hash_table *ht;
+ htab_t ht;
rtx var;
enum machine_mode promoted_mode;
int unsignedp;
rtx may_share;
{
- struct insns_for_mem_entry *ime
- = (struct insns_for_mem_entry *) hash_lookup (ht, var,
- /*create=*/0, /*copy=*/0);
+ struct insns_for_mem_entry tmp;
+ struct insns_for_mem_entry *ime;
rtx insn_list;
+ tmp.key = var;
+ ime = (struct insns_for_mem_entry *) htab_find (ht, &tmp);
for (insn_list = ime->insns; insn_list != 0; insn_list = XEXP (insn_list, 1))
if (INSN_P (XEXP (insn_list, 0)))
fixup_var_refs_insn (XEXP (insn_list, 0), var, promoted_mode,
@@ -1872,7 +1851,7 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel, no_share)
/* OLD might be a (subreg (mem)). */
if (GET_CODE (replacements->old) == SUBREG)
replacements->old
- = fixup_memory_subreg (replacements->old, insn,
+ = fixup_memory_subreg (replacements->old, insn,
promoted_mode, 0);
else
replacements->old
@@ -1890,7 +1869,7 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel, no_share)
start_sequence ();
convert_move (replacements->new,
replacements->old, unsignedp);
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
}
else
@@ -1972,7 +1951,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
start_sequence ();
new_insn = emit_insn (gen_rtx_SET (VOIDmode, y, sub));
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
if (recog_memoized (new_insn) < 0)
@@ -1983,7 +1962,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
sub = force_operand (sub, y);
if (sub != y)
emit_insn (gen_move_insn (y, sub));
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
}
@@ -2200,7 +2179,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
return;
}
- replacement->new = *loc = fixup_memory_subreg (x, insn,
+ replacement->new = *loc = fixup_memory_subreg (x, insn,
promoted_mode, 0);
INSN_CODE (insn) = -1;
@@ -2408,12 +2387,12 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
copy SET_SRC (x) to SET_DEST (x) in some way. So
we generate the move and see whether it requires more
than one insn. If it does, we emit those insns and
- delete INSN. Otherwise, we an just replace the pattern
+ delete INSN. Otherwise, we can just replace the pattern
of INSN; we have already verified above that INSN has
no other function that to do X. */
pat = gen_move_insn (SET_DEST (x), SET_SRC (x));
- if (GET_CODE (pat) == SEQUENCE)
+ if (NEXT_INSN (pat) != NULL_RTX)
{
last = emit_insn_before (pat, insn);
@@ -2431,7 +2410,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
delete_insn (last);
}
else
- PATTERN (insn) = pat;
+ PATTERN (insn) = PATTERN (pat);
return;
}
@@ -2448,7 +2427,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
rtx pat, last;
if (GET_CODE (SET_DEST (x)) == SUBREG)
- SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn,
+ SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn,
promoted_mode, 0);
else
SET_DEST (x) = fixup_stack_1 (SET_DEST (x), insn);
@@ -2457,7 +2436,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
return;
pat = gen_move_insn (SET_DEST (x), SET_SRC (x));
- if (GET_CODE (pat) == SEQUENCE)
+ if (NEXT_INSN (pat) != NULL_RTX)
{
last = emit_insn_before (pat, insn);
@@ -2475,7 +2454,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
delete_insn (last);
}
else
- PATTERN (insn) = pat;
+ PATTERN (insn) = PATTERN (pat);
return;
}
@@ -2502,7 +2481,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
/* Convert (SUBREG (MEM)) to a MEM in a changed mode. */
if (GET_CODE (fixeddest) == SUBREG)
{
- fixeddest = fixup_memory_subreg (fixeddest, insn,
+ fixeddest = fixup_memory_subreg (fixeddest, insn,
promoted_mode, 0);
temp_mode = GET_MODE (fixeddest);
}
@@ -2547,7 +2526,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
/* Previously, X had the form (SUBREG:m1 (REG:PROMOTED_MODE ...)).
The REG was placed on the stack, so X now has the form (SUBREG:m1
- (MEM:m2 ...)).
+ (MEM:m2 ...)).
Return an rtx (MEM:m1 newaddr) which is equivalent. If any insns
must be emitted to compute NEWADDR, put them before INSN.
@@ -2566,7 +2545,7 @@ fixup_memory_subreg (x, insn, promoted_mode, uncritical)
rtx mem = SUBREG_REG (x);
rtx addr = XEXP (mem, 0);
enum machine_mode mode = GET_MODE (x);
- rtx result;
+ rtx result, seq;
/* Paradoxical SUBREGs are usually invalid during RTL generation. */
if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (mem)) && ! uncritical)
@@ -2576,7 +2555,7 @@ fixup_memory_subreg (x, insn, promoted_mode, uncritical)
if (BYTES_BIG_ENDIAN)
/* If the PROMOTED_MODE is wider than the mode of the MEM, adjust
the offset so that it points to the right location within the
- MEM. */
+ MEM. */
offset -= (GET_MODE_SIZE (promoted_mode) - GET_MODE_SIZE (GET_MODE (mem)));
if (!flag_force_addr
@@ -2586,8 +2565,10 @@ fixup_memory_subreg (x, insn, promoted_mode, uncritical)
start_sequence ();
result = adjust_address (mem, mode, offset);
- emit_insn_before (gen_sequence (), insn);
+ seq = get_insns ();
end_sequence ();
+
+ emit_insn_before (seq, insn);
return result;
}
@@ -2596,7 +2577,7 @@ fixup_memory_subreg (x, insn, promoted_mode, uncritical)
If X itself is a (SUBREG (MEM ...) ...), return the replacement expression.
Otherwise return X, with its contents possibly altered.
- INSN, PROMOTED_MODE and UNCRITICAL are as for
+ INSN, PROMOTED_MODE and UNCRITICAL are as for
fixup_memory_subreg. */
static rtx
@@ -2624,14 +2605,14 @@ walk_fixup_memory_subreg (x, insn, promoted_mode, uncritical)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
- XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn,
+ XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn,
promoted_mode, uncritical);
else if (fmt[i] == 'E')
{
int j;
for (j = 0; j < XVECLEN (x, i); j++)
XVECEXP (x, i, j)
- = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn,
+ = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn,
promoted_mode, uncritical);
}
}
@@ -2677,7 +2658,7 @@ fixup_stack_1 (x, insn)
start_sequence ();
temp = copy_to_reg (ad);
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
emit_insn_before (seq, insn);
return replace_equiv_address (x, temp);
@@ -2788,7 +2769,7 @@ optimize_bit_field (body, insn, equiv_mem)
memref = adjust_address (memref, mode, offset);
insns = get_insns ();
end_sequence ();
- emit_insns_before (insns, insn);
+ emit_insn_before (insns, insn);
/* Store this memory reference where
we found the bit field reference. */
@@ -2856,7 +2837,7 @@ optimize_bit_field (body, insn, equiv_mem)
special; just let the optimization be suppressed. */
if (apply_change_group () && seq)
- emit_insns_before (seq, insn);
+ emit_insn_before (seq, insn);
}
}
}
@@ -2914,15 +2895,19 @@ static int cfa_offset;
#define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL)
#endif
-/* Build up a (MEM (ADDRESSOF (REG))) rtx for a register REG that just had its
- address taken. DECL is the decl or SAVE_EXPR 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. */
+/* Build up a (MEM (ADDRESSOF (REG))) rtx for a register REG that just
+ had its address taken. DECL is the decl or SAVE_EXPR 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. RESCAN is true if previously emitted
+ instructions must be rescanned and modified now that the REG has
+ been transformed. */
rtx
-gen_mem_addressof (reg, decl)
+gen_mem_addressof (reg, decl, rescan)
rtx reg;
tree decl;
+ int rescan;
{
rtx r = gen_rtx_ADDRESSOF (Pmode, gen_reg_rtx (GET_MODE (reg)),
REGNO (reg), decl);
@@ -2960,10 +2945,11 @@ gen_mem_addressof (reg, decl)
if (DECL_P (decl) && decl_rtl == reg)
SET_DECL_RTL (decl, reg);
- if (TREE_USED (decl) || (DECL_P (decl) && DECL_INITIAL (decl) != 0))
+ if (rescan
+ && (TREE_USED (decl) || (DECL_P (decl) && DECL_INITIAL (decl) != 0)))
fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), reg, 0);
}
- else
+ else if (rescan)
fixup_var_refs (reg, GET_MODE (reg), 0, reg, 0);
return reg;
@@ -2988,7 +2974,7 @@ flush_addressof (decl)
static void
put_addressof_into_stack (r, ht)
rtx r;
- struct hash_table *ht;
+ htab_t ht;
{
tree decl, type;
int volatile_p, used_p;
@@ -3040,7 +3026,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
rtx *loc;
rtx insn;
int force, store;
- struct hash_table *ht;
+ htab_t ht;
{
rtx x;
RTX_CODE code;
@@ -3072,7 +3058,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
if (GET_CODE (XEXP (x, 0)) != MEM)
put_addressof_into_stack (x, ht);
-
+
/* We must create a copy of the rtx because it was created by
overwriting a REG rtx which is always shared. */
sub = copy_rtx (XEXP (XEXP (x, 0), 0));
@@ -3086,7 +3072,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
&& ! validate_replace_rtx (x, sub, insn))
abort ();
- insns = gen_sequence ();
+ insns = get_insns ();
end_sequence ();
emit_insn_before (insns, insn);
return true;
@@ -3174,10 +3160,16 @@ purge_addressof_1 (loc, insn, force, store, ht)
size_x = GET_MODE_BITSIZE (GET_MODE (x));
size_sub = GET_MODE_BITSIZE (GET_MODE (sub));
+ /* Do not frob unchanging MEMs. If a later reference forces the
+ pseudo to the stack, we can wind up with multiple writes to
+ an unchanging memory, which is invalid. */
+ if (RTX_UNCHANGING_P (x) && size_x != size_sub)
+ ;
+
/* Don't even consider working with paradoxical subregs,
or the moral equivalent seen here. */
- if (size_x <= size_sub
- && int_mode_for_mode (GET_MODE (sub)) != BLKmode)
+ else if (size_x <= size_sub
+ && int_mode_for_mode (GET_MODE (sub)) != BLKmode)
{
/* Do a bitfield insertion to mirror what would happen
in memory. */
@@ -3197,7 +3189,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
end_sequence ();
goto give_up;
}
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
emit_insn_before (seq, insn);
compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (),
@@ -3211,7 +3203,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
might have created. */
unshare_all_rtl_again (get_insns ());
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
p = emit_insn_after (seq, insn);
if (NEXT_INSN (insn))
@@ -3236,7 +3228,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
goto give_up;
}
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
emit_insn_before (seq, insn);
compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (),
@@ -3297,50 +3289,34 @@ purge_addressof_1 (loc, insn, force, store, ht)
return result;
}
-/* Return a new hash table entry in HT. */
-
-static struct hash_entry *
-insns_for_mem_newfunc (he, ht, k)
- struct hash_entry *he;
- struct hash_table *ht;
- hash_table_key k ATTRIBUTE_UNUSED;
-{
- struct insns_for_mem_entry *ifmhe;
- if (he)
- return he;
-
- ifmhe = ((struct insns_for_mem_entry *)
- hash_allocate (ht, sizeof (struct insns_for_mem_entry)));
- ifmhe->insns = NULL_RTX;
-
- return &ifmhe->he;
-}
-
/* Return a hash value for K, a REG. */
-static unsigned long
+static hashval_t
insns_for_mem_hash (k)
- hash_table_key k;
+ const void * k;
{
- /* K is really a RTX. Just use the address as the hash value. */
- return (unsigned long) k;
+ /* Use the address of the key for the hash value. */
+ struct insns_for_mem_entry *m = (struct insns_for_mem_entry *) k;
+ return htab_hash_pointer (m->key);
}
-/* Return non-zero if K1 and K2 (two REGs) are the same. */
+/* Return nonzero if K1 and K2 (two REGs) are the same. */
-static bool
+static int
insns_for_mem_comp (k1, k2)
- hash_table_key k1;
- hash_table_key k2;
+ const void * k1;
+ const void * k2;
{
- return k1 == k2;
+ struct insns_for_mem_entry *m1 = (struct insns_for_mem_entry *) k1;
+ struct insns_for_mem_entry *m2 = (struct insns_for_mem_entry *) k2;
+ return m1->key == m2->key;
}
struct insns_for_mem_walk_info
{
/* The hash table that we are using to record which INSNs use which
MEMs. */
- struct hash_table *ht;
+ htab_t ht;
/* The INSN we are currently processing. */
rtx insn;
@@ -3362,18 +3338,26 @@ insns_for_mem_walk (r, data)
{
struct insns_for_mem_walk_info *ifmwi
= (struct insns_for_mem_walk_info *) data;
+ struct insns_for_mem_entry tmp;
+ tmp.insns = NULL_RTX;
if (ifmwi->pass == 0 && *r && GET_CODE (*r) == ADDRESSOF
&& GET_CODE (XEXP (*r, 0)) == REG)
- hash_lookup (ifmwi->ht, XEXP (*r, 0), /*create=*/1, /*copy=*/0);
+ {
+ PTR *e;
+ tmp.key = XEXP (*r, 0);
+ e = htab_find_slot (ifmwi->ht, &tmp, INSERT);
+ if (*e == NULL)
+ {
+ *e = ggc_alloc (sizeof (tmp));
+ memcpy (*e, &tmp, sizeof (tmp));
+ }
+ }
else if (ifmwi->pass == 1 && *r && GET_CODE (*r) == REG)
{
- /* Lookup this MEM in the hashtable, creating it if necessary. */
- struct insns_for_mem_entry *ifme
- = (struct insns_for_mem_entry *) hash_lookup (ifmwi->ht,
- *r,
- /*create=*/0,
- /*copy=*/0);
+ struct insns_for_mem_entry *ifme;
+ tmp.key = *r;
+ ifme = (struct insns_for_mem_entry *) htab_find (ifmwi->ht, &tmp);
/* If we have not already recorded this INSN, do so now. Since
we process the INSNs in order, we know that if we have
@@ -3393,7 +3377,7 @@ static void
compute_insns_for_mem (insns, last_insn, ht)
rtx insns;
rtx last_insn;
- struct hash_table *ht;
+ htab_t ht;
{
rtx insn;
struct insns_for_mem_walk_info ifmwi;
@@ -3428,7 +3412,7 @@ purge_addressof (insns)
rtx insns;
{
rtx insn;
- struct hash_table ht;
+ htab_t ht;
/* When we actually purge ADDRESSOFs, we turn REGs into MEMs. That
requires a fixup pass over the instruction stream to correct
@@ -3437,23 +3421,20 @@ purge_addressof (insns)
mentioned in very many instructions. So, we speed up the process
by pre-calculating which REGs occur in which INSNs; that allows
us to perform the fixup passes much more quickly. */
- hash_table_init (&ht,
- insns_for_mem_newfunc,
- insns_for_mem_hash,
- insns_for_mem_comp);
- compute_insns_for_mem (insns, NULL_RTX, &ht);
+ ht = htab_create_ggc (1000, insns_for_mem_hash, insns_for_mem_comp, NULL);
+ compute_insns_for_mem (insns, NULL_RTX, ht);
for (insn = insns; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
|| GET_CODE (insn) == CALL_INSN)
{
if (! purge_addressof_1 (&PATTERN (insn), insn,
- asm_noperands (PATTERN (insn)) > 0, 0, &ht))
+ asm_noperands (PATTERN (insn)) > 0, 0, ht))
/* If we could not replace the ADDRESSOFs in the insn,
something is wrong. */
abort ();
- if (! purge_addressof_1 (&REG_NOTES (insn), NULL_RTX, 0, 0, &ht))
+ if (! purge_addressof_1 (&REG_NOTES (insn), NULL_RTX, 0, 0, ht))
{
/* If we could not replace the ADDRESSOFs in the insn's notes,
we can just remove the offending notes instead. */
@@ -3474,7 +3455,6 @@ purge_addressof (insns)
}
/* Clean up. */
- hash_table_free (&ht);
purge_bitfield_addressof_replacements = 0;
purge_addressof_replacements = 0;
@@ -3514,7 +3494,7 @@ purge_single_hard_subreg_set (pattern)
reg = SUBREG_REG (reg);
}
-
+
if (GET_CODE (reg) == REG && REGNO (reg) < FIRST_PSEUDO_REGISTER)
{
reg = gen_rtx_REG (mode, REGNO (reg) + offset);
@@ -3543,7 +3523,7 @@ purge_hard_subreg_sets (insn)
case SET:
if (GET_CODE (SET_DEST (pattern)) == SUBREG)
purge_single_hard_subreg_set (pattern);
- break;
+ break;
case PARALLEL:
{
int j;
@@ -3597,11 +3577,19 @@ instantiate_virtual_regs (fndecl, insns)
|| GET_CODE (insn) == CALL_INSN)
{
instantiate_virtual_regs_1 (&PATTERN (insn), insn, 1);
+ if (INSN_DELETED_P (insn))
+ continue;
instantiate_virtual_regs_1 (&REG_NOTES (insn), NULL_RTX, 0);
/* Instantiate any virtual registers in CALL_INSN_FUNCTION_USAGE. */
if (GET_CODE (insn) == CALL_INSN)
instantiate_virtual_regs_1 (&CALL_INSN_FUNCTION_USAGE (insn),
NULL_RTX, 0);
+
+ /* Past this point all ASM statements should match. Verify that
+ to avoid failures later in the compilation process. */
+ if (asm_noperands (PATTERN (insn)) >= 0
+ && ! check_asm_operands (PATTERN (insn)))
+ instantiate_virtual_regs_lossage (insn);
}
/* Instantiate the stack slots for the parm registers, for later use in
@@ -3664,7 +3652,7 @@ instantiate_decls_1 (let, valid_only)
for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
if (DECL_RTL_SET_P (t))
- instantiate_decl (DECL_RTL (t),
+ instantiate_decl (DECL_RTL (t),
int_size_in_bytes (TREE_TYPE (t)),
valid_only);
@@ -3676,7 +3664,7 @@ instantiate_decls_1 (let, valid_only)
/* Subroutine of the preceding procedures: Given RTL representing a
decl and the size of the object, do any instantiation required.
- If VALID_ONLY is non-zero, it means that the RTL should only be
+ If VALID_ONLY is nonzero, it means that the RTL should only be
changed if the new address is valid. */
static void
@@ -3769,6 +3757,22 @@ instantiate_new_reg (x, poffset)
return new;
}
+
+/* Called when instantiate_virtual_regs has failed to update the instruction.
+ Usually this means that non-matching instruction has been emit, however for
+ asm statements it may be the problem in the constraints. */
+static void
+instantiate_virtual_regs_lossage (insn)
+ rtx insn;
+{
+ if (asm_noperands (PATTERN (insn)) >= 0)
+ {
+ error_for_asm (insn, "impossible constraint in `asm'");
+ delete_insn (insn);
+ }
+ else
+ abort ();
+}
/* Given a pointer to a piece of rtx and an optional pointer to the
containing object, instantiate any virtual registers present in it.
@@ -3805,6 +3809,10 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
if (x == 0)
return 1;
+ /* We may have detected and deleted invalid asm statements. */
+ if (object && INSN_P (object) && INSN_DELETED_P (object))
+ return 1;
+
code = GET_CODE (x);
/* Check for some special cases. */
@@ -3842,7 +3850,10 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
/* The only valid sources here are PLUS or REG. Just do
the simplest possible thing to handle them. */
if (GET_CODE (src) != REG && GET_CODE (src) != PLUS)
- abort ();
+ {
+ instantiate_virtual_regs_lossage (object);
+ return 1;
+ }
start_sequence ();
if (GET_CODE (src) != REG)
@@ -3853,12 +3864,12 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, object);
+ emit_insn_before (seq, object);
SET_DEST (x) = new;
if (! validate_change (object, &SET_SRC (x), temp, 0)
|| ! extra_insns)
- abort ();
+ instantiate_virtual_regs_lossage (object);
return 1;
}
@@ -3965,10 +3976,13 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, object);
+ emit_insn_before (seq, object);
if (! validate_change (object, loc, temp, 0)
&& ! validate_replace_rtx (x, temp, object))
- abort ();
+ {
+ instantiate_virtual_regs_lossage (object);
+ return 1;
+ }
}
}
@@ -4119,10 +4133,10 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, object);
+ emit_insn_before (seq, object);
if (! validate_change (object, loc, temp, 0)
&& ! validate_replace_rtx (x, temp, object))
- abort ();
+ instantiate_virtual_regs_lossage (object);
}
}
@@ -4322,17 +4336,6 @@ assign_parms (fndecl)
rtx conversion_insns = 0;
struct args_size alignment_pad;
- /* Nonzero if the last arg is named `__builtin_va_alist',
- which is used on some machines for old-fashioned non-ANSI varargs.h;
- this should be stuck onto the stack as if it had arrived there. */
- int hide_last_arg
- = (current_function_varargs
- && fnargs
- && (parm = tree_last (fnargs)) != 0
- && DECL_NAME (parm)
- && (! strcmp (IDENTIFIER_POINTER (DECL_NAME (parm)),
- "__builtin_va_alist")));
-
/* Nonzero if function takes extra anonymous args.
This means the last named arg must be on the stack
right before the anonymous ones. */
@@ -4376,7 +4379,7 @@ assign_parms (fndecl)
}
max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
- parm_reg_stack_loc = (rtx *) xcalloc (max_parm_reg, sizeof (rtx));
+ parm_reg_stack_loc = (rtx *) ggc_alloc_cleared (max_parm_reg * sizeof (rtx));
#ifdef INIT_CUMULATIVE_INCOMING_ARGS
INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, NULL_RTX);
@@ -4401,7 +4404,7 @@ assign_parms (fndecl)
/* Set LAST_NAMED if this is last named arg before last
anonymous args. */
- if (stdarg || current_function_varargs)
+ if (stdarg)
{
tree tem;
@@ -4429,11 +4432,6 @@ assign_parms (fndecl)
continue;
}
- /* For varargs.h function, save info about regs and stack space
- used by the individual args, not including the va_alist arg. */
- if (hide_last_arg && last_named)
- current_function_args_info = args_so_far;
-
/* Find mode of arg as it is passed, and mode of arg
as it should be during execution of this function. */
passed_mode = TYPE_MODE (passed_type);
@@ -4474,6 +4472,15 @@ assign_parms (fndecl)
passed_pointer = 1;
passed_mode = nominal_mode = Pmode;
}
+ /* See if the frontend wants to pass this by invisible reference. */
+ else if (passed_type != nominal_type
+ && POINTER_TYPE_P (passed_type)
+ && TREE_TYPE (passed_type) == nominal_type)
+ {
+ nominal_type = passed_type;
+ passed_pointer = 1;
+ passed_mode = nominal_mode = Pmode;
+ }
promoted_mode = passed_mode;
@@ -4581,6 +4588,12 @@ assign_parms (fndecl)
if (nregs > 0)
{
+#if defined (REG_PARM_STACK_SPACE) && !defined (MAYBE_REG_PARM_STACK_SPACE)
+ /* When REG_PARM_STACK_SPACE is nonzero, stack space for
+ split parameters was allocated by our caller, so we
+ won't be pushing it in the prolog. */
+ if (REG_PARM_STACK_SPACE (fndecl) == 0)
+#endif
current_function_pretend_args_size
= (((nregs * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
/ (PARM_BOUNDARY / BITS_PER_UNIT)
@@ -4615,8 +4628,8 @@ assign_parms (fndecl)
to indicate there is no preallocated stack slot for the parm. */
if (entry_parm == stack_parm
- || (GET_CODE (entry_parm) == PARALLEL
- && XEXP (XVECEXP (entry_parm, 0, 0), 0) == NULL_RTX)
+ || (GET_CODE (entry_parm) == PARALLEL
+ && XEXP (XVECEXP (entry_parm, 0, 0), 0) == NULL_RTX)
#if defined (REG_PARM_STACK_SPACE) && ! defined (MAYBE_REG_PARM_STACK_SPACE)
/* On some machines, even if a parm value arrives in a register
there is still an (uninitialized) stack slot allocated for it.
@@ -4770,7 +4783,7 @@ assign_parms (fndecl)
if (passed_pointer)
{
rtx x = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (passed_type)),
- parmreg);
+ parmreg);
set_mem_attributes (x, parm, 1);
SET_DECL_RTL (parm, x);
}
@@ -4779,7 +4792,7 @@ assign_parms (fndecl)
SET_DECL_RTL (parm, parmreg);
maybe_set_unchanging (DECL_RTL (parm), parm);
}
-
+
/* Copy the value into the register. */
if (nominal_mode != passed_mode
|| promoted_nominal_mode != promoted_mode)
@@ -4822,7 +4835,7 @@ assign_parms (fndecl)
/* The argument is already sign/zero extended, so note it
into the subreg. */
SUBREG_PROMOTED_VAR_P (tempreg) = 1;
- SUBREG_PROMOTED_UNSIGNED_P (tempreg) = unsignedp;
+ SUBREG_PROMOTED_UNSIGNED_SET (tempreg, unsignedp);
}
/* TREE_USED gets set erroneously during expand_assignment. */
@@ -4861,7 +4874,7 @@ assign_parms (fndecl)
push_to_sequence (conversion_insns);
emit_move_insn (tempreg, DECL_RTL (parm));
SET_DECL_RTL (parm,
- convert_to_mode (GET_MODE (parmreg),
+ convert_to_mode (GET_MODE (parmreg),
tempreg,
unsigned_p));
emit_move_insn (parmreg, DECL_RTL (parm));
@@ -4940,7 +4953,7 @@ assign_parms (fndecl)
but it's also rare and we need max_parm_reg to be
precisely correct. */
max_parm_reg = regno + 1;
- new = (rtx *) xrealloc (parm_reg_stack_loc,
+ new = (rtx *) ggc_realloc (parm_reg_stack_loc,
max_parm_reg * sizeof (rtx));
memset ((char *) (new + old_max_parm_reg), 0,
(max_parm_reg - old_max_parm_reg) * sizeof (rtx));
@@ -5031,7 +5044,7 @@ assign_parms (fndecl)
stack. So, we go back to that sequence, just so that
the fixups will happen. */
push_to_sequence (conversion_insns);
- put_var_into_stack (parm);
+ put_var_into_stack (parm, /*rescan=*/true);
conversion_insns = get_insns ();
end_sequence ();
}
@@ -5116,7 +5129,7 @@ assign_parms (fndecl)
/* Output all parameter conversion instructions (possibly including calls)
now that all parameters have been copied out of hard registers. */
- emit_insns (conversion_insns);
+ emit_insn (conversion_insns);
last_parm_insn = get_last_insn ();
@@ -5157,8 +5170,7 @@ assign_parms (fndecl)
/* For stdarg.h function, save info about
regs and stack space used by the named args. */
- if (!hide_last_arg)
- current_function_args_info = args_so_far;
+ current_function_args_info = args_so_far;
/* Set the rtx used for the function return value. Put this in its
own variable so any optimizers that need this information don't have
@@ -5248,7 +5260,7 @@ promoted_input_arg (regno, pmode, punsignedp)
The starting offset and size for this parm are returned in *OFFSET_PTR
and *ARG_SIZE_PTR, respectively.
- IN_REGS is non-zero if the argument will be passed in registers. It will
+ IN_REGS is nonzero if the argument will be passed in registers. It will
never be set if REG_PARM_STACK_SPACE is not defined.
FNDECL is the function in which the argument was defined.
@@ -5286,6 +5298,9 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
= type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode));
enum direction where_pad = FUNCTION_ARG_PADDING (passed_mode, type);
int boundary = FUNCTION_ARG_BOUNDARY (passed_mode, type);
+#ifdef ARGS_GROW_DOWNWARD
+ tree s2 = sizetree;
+#endif
#ifdef REG_PARM_STACK_SPACE
/* If we have found a stack parm before we reach the end of the
@@ -5331,13 +5346,20 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
offset_ptr->constant = -initial_offset_ptr->constant;
offset_ptr->var = 0;
}
+
if (where_pad != none
&& (!host_integerp (sizetree, 1)
|| (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % PARM_BOUNDARY))
- sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
- SUB_PARM_SIZE (*offset_ptr, sizetree);
- if (where_pad != downward)
+ s2 = round_up (s2, PARM_BOUNDARY / BITS_PER_UNIT);
+ SUB_PARM_SIZE (*offset_ptr, s2);
+
+ if (!in_regs
+#ifdef REG_PARM_STACK_SPACE
+ || REG_PARM_STACK_SPACE (fndecl) > 0
+#endif
+ )
pad_to_arg_alignment (offset_ptr, boundary, alignment_pad);
+
if (initial_offset_ptr->var)
arg_size_ptr->var = size_binop (MINUS_EXPR,
size_binop (MINUS_EXPR,
@@ -5349,6 +5371,13 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
arg_size_ptr->constant = (-initial_offset_ptr->constant
- offset_ptr->constant);
+ /* Pad_below needs the pre-rounded size to know how much to pad below.
+ We only pad parameters which are not in registers as they have their
+ padding done elsewhere. */
+ if (where_pad == downward
+ && !in_regs)
+ pad_below (offset_ptr, passed_mode, sizetree);
+
#else /* !ARGS_GROW_DOWNWARD */
if (!in_regs
#ifdef REG_PARM_STACK_SPACE
@@ -5416,8 +5445,8 @@ pad_to_arg_alignment (offset_ptr, boundary, alignment_pad)
(ARGS_SIZE_TREE (*offset_ptr),
boundary / BITS_PER_UNIT);
offset_ptr->constant = 0; /*?*/
- if (boundary > PARM_BOUNDARY && boundary > STACK_BOUNDARY)
- alignment_pad->var = size_binop (MINUS_EXPR, offset_ptr->var,
+ if (boundary > PARM_BOUNDARY && boundary > STACK_BOUNDARY)
+ alignment_pad->var = size_binop (MINUS_EXPR, offset_ptr->var,
save_var);
}
else
@@ -5434,7 +5463,6 @@ pad_to_arg_alignment (offset_ptr, boundary, alignment_pad)
}
}
-#ifndef ARGS_GROW_DOWNWARD
static void
pad_below (offset_ptr, passed_mode, sizetree)
struct args_size *offset_ptr;
@@ -5462,7 +5490,6 @@ pad_below (offset_ptr, passed_mode, sizetree)
}
}
}
-#endif
/* Walk the tree of blocks describing the binding levels within a function
and warn about uninitialized variables.
@@ -5477,7 +5504,7 @@ uninitialized_vars_warning (block)
for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
{
if (warn_uninitialized
- && TREE_CODE (decl) == VAR_DECL
+ && TREE_CODE (decl) == VAR_DECL
/* These warnings are unreliable for and aggregates
because assigning the fields one by one can fail to convince
flow.c that the entire aggregate was initialized.
@@ -5497,7 +5524,7 @@ uninitialized_vars_warning (block)
warning_with_decl (decl,
"`%s' might be used uninitialized in this function");
if (extra_warnings
- && TREE_CODE (decl) == VAR_DECL
+ && TREE_CODE (decl) == VAR_DECL
&& DECL_RTL (decl) != 0
&& GET_CODE (DECL_RTL (decl)) == REG
&& regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
@@ -5553,7 +5580,7 @@ setjmp_protect (block)
||
#endif
! DECL_REGISTER (decl)))
- put_var_into_stack (decl);
+ put_var_into_stack (decl, /*rescan=*/true);
for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub))
setjmp_protect (sub);
}
@@ -5580,7 +5607,7 @@ setjmp_protect_args ()
||
#endif
! DECL_REGISTER (decl)))
- put_var_into_stack (decl);
+ put_var_into_stack (decl, /*rescan=*/true);
}
/* Return the context-pointer register corresponding to DECL,
@@ -5739,12 +5766,8 @@ trampoline_address (function)
#else
/* 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 / BITS_PER_UNIT) - 1)
-#else
-#define TRAMPOLINE_REAL_SIZE (TRAMPOLINE_SIZE)
-#endif
tramp = assign_stack_local_1 (BLKmode, TRAMPOLINE_REAL_SIZE, 0,
fp ? fp : cfun);
#endif
@@ -5779,7 +5802,6 @@ static rtx
round_trampoline_addr (tramp)
rtx tramp;
{
-#ifdef TRAMPOLINE_ALIGNMENT
/* Round address up to desired boundary. */
rtx temp = gen_reg_rtx (Pmode);
rtx addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
@@ -5789,7 +5811,7 @@ round_trampoline_addr (tramp)
temp, 0, OPTAB_LIB_WIDEN);
tramp = expand_simple_binop (Pmode, AND, temp, mask,
temp, 0, OPTAB_LIB_WIDEN);
-#endif
+
return tramp;
}
@@ -5942,8 +5964,6 @@ reorder_blocks ()
/* Remove deleted blocks from the block fragment chains. */
reorder_fix_fragments (block);
-
- VARRAY_FREE (block_stack);
}
/* Helper function for reorder_blocks. Reset TREE_ASM_WRITTEN. */
@@ -6031,7 +6051,7 @@ reorder_blocks_1 (insns, current_block, p_block_stack)
static void
reorder_fix_fragments (block)
- tree block;
+ tree block;
{
while (block)
{
@@ -6043,7 +6063,7 @@ reorder_fix_fragments (block)
if (! TREE_ASM_WRITTEN (dup_origin))
{
new_origin = BLOCK_FRAGMENT_CHAIN (dup_origin);
-
+
/* Find the first of the remaining fragments. There must
be at least one -- the current block. */
while (! TREE_ASM_WRITTEN (new_origin))
@@ -6312,8 +6332,7 @@ prepare_function_start ()
/* Indicate we have no need of a frame pointer yet. */
frame_pointer_needed = 0;
- /* By default assume not varargs or stdarg. */
- current_function_varargs = 0;
+ /* By default assume not stdarg. */
current_function_stdarg = 0;
/* We haven't made any trampolines for this function yet. */
@@ -6324,10 +6343,19 @@ prepare_function_start ()
current_function_outgoing_args_size = 0;
- if (init_lang_status)
- (*init_lang_status) (cfun);
+ current_function_funcdef_no = funcdef_no++;
+
+ cfun->arc_profile = profile_arc_flag || flag_test_coverage;
+
+ cfun->arc_profile = profile_arc_flag || flag_test_coverage;
+
+ cfun->function_frequency = FUNCTION_FREQUENCY_NORMAL;
+
+ cfun->max_jumptable_ents = 0;
+
+ (*lang_hooks.function.init) (cfun);
if (init_machine_status)
- (*init_machine_status) (cfun);
+ cfun->machine = (*init_machine_status) ();
}
/* Initialize the rtl expansion mechanism so that we can do simple things
@@ -6351,7 +6379,7 @@ init_function_start (subr, filename, line)
{
prepare_function_start ();
- current_function_name = (*decl_printable_name) (subr, 2);
+ current_function_name = (*lang_hooks.decl_printable_name) (subr, 2);
cfun->decl = subr;
/* Nonzero if this is a nested function that uses a static chain. */
@@ -6406,15 +6434,6 @@ init_function_for_compilation ()
VARRAY_GROW (sibcall_epilogue, 0);
}
-/* Indicate that the current function uses extra args
- not explicitly mentioned in the argument list in any fashion. */
-
-void
-mark_varargs ()
-{
- current_function_varargs = 1;
-}
-
/* Expand a call to __main at the beginning of a possible main function. */
#if defined(INIT_SECTION_ASM_OP) && !defined(INVOKE__main)
@@ -6444,11 +6463,11 @@ expand_main_function ()
#endif
if (tmp != stack_pointer_rtx)
emit_move_insn (stack_pointer_rtx, tmp);
-
+
/* Enlist allocate_dynamic_stack_space to pick up the pieces. */
tmp = force_reg (Pmode, const0_rtx);
allocate_dynamic_stack_space (tmp, NULL_RTX, BIGGEST_ALIGNMENT);
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
for (tmp = get_last_insn (); tmp; tmp = PREV_INSN (tmp))
@@ -6467,8 +6486,6 @@ expand_main_function ()
#endif
}
-extern struct obstack permanent_obstack;
-
/* The PENDING_SIZES represent the sizes of variable-sized types.
Create RTL for the various sizes now (using temporary variables),
so that we can refer to the sizes from the RTL we are generating
@@ -6597,18 +6614,17 @@ expand_function_start (subr, parms_have_cleanups)
subr, 1);
/* Structures that are returned in registers are not aggregate_value_p,
- so we may see a PARALLEL. Don't play pseudo games with this. */
- if (! REG_P (hard_reg))
- SET_DECL_RTL (DECL_RESULT (subr), hard_reg);
+ so we may see a PARALLEL or a REG. */
+ if (REG_P (hard_reg))
+ SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg)));
+ else if (GET_CODE (hard_reg) == PARALLEL)
+ SET_DECL_RTL (DECL_RESULT (subr), gen_group_rtx (hard_reg));
else
- {
- /* Create the pseudo. */
- SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg)));
+ abort ();
- /* Needed because we may need to move this to memory
- in case it's a named return value whose address is taken. */
- DECL_REGISTER (DECL_RESULT (subr)) = 1;
- }
+ /* Set DECL_REGISTER flag so that expand_function_end will copy the
+ result to the real return register(s). */
+ DECL_REGISTER (DECL_RESULT (subr)) = 1;
}
/* Initialize rtx for parameters and local variables.
@@ -6620,8 +6636,8 @@ expand_function_start (subr, parms_have_cleanups)
avoid conflicts with the parameter passing registers. */
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);
+ if (GET_CODE (static_chain_incoming_rtx) != REG)
+ emit_move_insn (last_ptr, static_chain_incoming_rtx);
/* The following was moved from init_function_start.
The move is supposed to make sdb output more accurate. */
@@ -6696,9 +6712,8 @@ expand_function_start (subr, parms_have_cleanups)
if (current_function_profile)
{
- current_function_profile_label_no = profile_label_no++;
#ifdef PROFILE_HOOK
- PROFILE_HOOK (current_function_profile_label_no);
+ PROFILE_HOOK (current_function_funcdef_no);
#endif
}
@@ -6798,6 +6813,8 @@ use_return_register ()
diddle_return_value (do_use_return_reg, NULL);
}
+static GTY(()) rtx initial_trampoline;
+
/* Generate RTL for the end of the current function.
FILENAME and LINE are the current position in the source file.
@@ -6813,10 +6830,6 @@ expand_function_end (filename, line, end_bindings)
tree link;
rtx clobber_after;
-#ifdef TRAMPOLINE_TEMPLATE
- static rtx initial_trampoline;
-#endif
-
finish_expr_for_function ();
/* If arg_pointer_save_area was referenced only from a nested
@@ -6855,8 +6868,6 @@ expand_function_end (filename, line, end_bindings)
initial_trampoline
= gen_rtx_MEM (BLKmode, assemble_trampoline_template ());
set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT);
-
- ggc_add_rtx_root (&initial_trampoline, 1);
}
#endif
@@ -6866,14 +6877,14 @@ expand_function_end (filename, line, end_bindings)
#ifdef TRAMPOLINE_TEMPLATE
blktramp = replace_equiv_address (initial_trampoline, tramp);
emit_block_move (blktramp, initial_trampoline,
- GEN_INT (TRAMPOLINE_SIZE));
+ GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
#endif
INITIALIZE_TRAMPOLINE (tramp, XEXP (DECL_RTL (function), 0), context);
seq = get_insns ();
end_sequence ();
/* Put those insns at entry to the containing function (this one). */
- emit_insns_before (seq, tail_recursion_reentry);
+ emit_insn_before (seq, tail_recursion_reentry);
}
/* If we are doing stack checking and this function makes calls,
@@ -6891,7 +6902,7 @@ expand_function_end (filename, line, end_bindings)
GEN_INT (STACK_CHECK_MAX_FRAME_SIZE));
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, tail_recursion_reentry);
+ emit_insn_before (seq, tail_recursion_reentry);
break;
}
}
@@ -7021,13 +7032,13 @@ expand_function_end (filename, line, end_bindings)
/* If this is a BLKmode structure being returned in registers,
then use the mode computed in expand_return. Note that if
- decl_rtl is memory, then its mode may have been changed,
+ decl_rtl is memory, then its mode may have been changed,
but that current_function_return_rtx has not. */
if (GET_MODE (real_decl_rtl) == BLKmode)
PUT_MODE (real_decl_rtl, GET_MODE (decl_rtl));
/* If a named return value dumped decl_return to memory, then
- we may need to re-do the PROMOTE_MODE signed/unsigned
+ we may need to re-do the PROMOTE_MODE signed/unsigned
extension. */
if (GET_MODE (real_decl_rtl) != GET_MODE (decl_rtl))
{
@@ -7041,8 +7052,16 @@ expand_function_end (filename, line, end_bindings)
convert_move (real_decl_rtl, decl_rtl, unsignedp);
}
else if (GET_CODE (real_decl_rtl) == PARALLEL)
- emit_group_load (real_decl_rtl, decl_rtl,
- int_size_in_bytes (TREE_TYPE (decl_result)));
+ {
+ /* If expand_function_start has created a PARALLEL for decl_rtl,
+ move the result to the real return registers. Otherwise, do
+ a group load from decl_rtl for a named return. */
+ if (GET_CODE (decl_rtl) == PARALLEL)
+ emit_group_move (real_decl_rtl, decl_rtl);
+ else
+ emit_group_load (real_decl_rtl, decl_rtl,
+ int_size_in_bytes (TREE_TYPE (decl_result)));
+ }
else
emit_move_insn (real_decl_rtl, decl_rtl);
}
@@ -7094,14 +7113,14 @@ expand_function_end (filename, line, end_bindings)
/* Emit the actual code to clobber return register. */
{
rtx seq, after;
-
+
start_sequence ();
clobber_return_register ();
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
after = emit_insn_after (seq, clobber_after);
-
+
if (clobber_after != after)
cfun->x_clobber_return_insn = after;
}
@@ -7138,12 +7157,12 @@ get_arg_pointer_save_area (f)
{
rtx seq;
- /* Save the arg pointer at the beginning of the function. The
+ /* Save the arg pointer at the beginning of the function. The
generated stack slot may not be a valid memory address, so we
have to check it and fix it if necessary. */
start_sequence ();
emit_move_insn (validize_mem (ret), virtual_incoming_args_rtx);
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
push_topmost_sequence ();
@@ -7154,35 +7173,38 @@ get_arg_pointer_save_area (f)
return ret;
}
-/* Extend a vector that records the INSN_UIDs of INSNS (either a
- sequence or a single insn). */
+/* Extend a vector that records the INSN_UIDs of INSNS
+ (a list of one or more insns). */
static void
record_insns (insns, vecp)
rtx insns;
varray_type *vecp;
{
- if (GET_CODE (insns) == SEQUENCE)
- {
- int len = XVECLEN (insns, 0);
- int i = VARRAY_SIZE (*vecp);
+ int i, len;
+ rtx tmp;
- VARRAY_GROW (*vecp, i + len);
- while (--len >= 0)
- {
- VARRAY_INT (*vecp, i) = INSN_UID (XVECEXP (insns, 0, len));
- ++i;
- }
+ tmp = insns;
+ len = 0;
+ while (tmp != NULL_RTX)
+ {
+ len++;
+ tmp = NEXT_INSN (tmp);
}
- else
+
+ i = VARRAY_SIZE (*vecp);
+ VARRAY_GROW (*vecp, i + len);
+ tmp = insns;
+ while (tmp != NULL_RTX)
{
- int i = VARRAY_SIZE (*vecp);
- VARRAY_GROW (*vecp, i + 1);
- VARRAY_INT (*vecp, i) = INSN_UID (insns);
+ VARRAY_INT (*vecp, i) = INSN_UID (tmp);
+ i++;
+ tmp = NEXT_INSN (tmp);
}
}
-/* Determine how many INSN_UIDs in VEC are part of INSN. */
+/* Determine how many INSN_UIDs in VEC are part of INSN. Because we can
+ be running after reorg, SEQUENCE rtl is possible. */
static int
contains (insn, vec)
@@ -7294,20 +7316,21 @@ struct epi_info
static void handle_epilogue_set PARAMS ((rtx, struct epi_info *));
static void emit_equiv_load PARAMS ((struct epi_info *));
-/* Modify SEQ, a SEQUENCE that is part of the epilogue, to no modifications
- to the stack pointer. Return the new sequence. */
+/* Modify INSN, a list of one or more insns that is part of the epilogue, to
+ no modifications to the stack pointer. Return the new list of insns. */
static rtx
-keep_stack_depressed (seq)
- rtx seq;
+keep_stack_depressed (insns)
+ rtx insns;
{
- int i, j;
+ int j;
struct epi_info info;
+ rtx insn, next;
/* If the epilogue is just a single instruction, it ust be OK as is. */
- if (GET_CODE (seq) != SEQUENCE)
- return seq;
+ if (NEXT_INSN (insns) == NULL_RTX)
+ return insns;
/* Otherwise, start a sequence, initialize the information we have, and
process all the insns we were given. */
@@ -7317,13 +7340,16 @@ keep_stack_depressed (seq)
info.sp_offset = 0;
info.equiv_reg_src = 0;
- for (i = 0; i < XVECLEN (seq, 0); i++)
+ insn = insns;
+ next = NULL_RTX;
+ while (insn != NULL_RTX)
{
- rtx insn = XVECEXP (seq, 0, i);
+ next = NEXT_INSN (insn);
if (!INSN_P (insn))
{
add_insn (insn);
+ insn = next;
continue;
}
@@ -7359,6 +7385,7 @@ keep_stack_depressed (seq)
{
emit_equiv_load (&info);
add_insn (insn);
+ insn = next;
continue;
}
else if (GET_CODE (retaddr) == MEM
@@ -7459,16 +7486,18 @@ keep_stack_depressed (seq)
info.sp_equiv_reg = info.new_sp_equiv_reg;
info.sp_offset = info.new_sp_offset;
+
+ insn = next;
}
- seq = gen_sequence ();
+ insns = get_insns ();
end_sequence ();
- return seq;
+ return insns;
}
/* SET is a SET from an insn in the epilogue. P is a pointer to the epi_info
structure that contains information about what we've seen so far. We
- process this SET by either updating that data or by emitting one or
+ process this SET by either updating that data or by emitting one or
more insns. */
static void
@@ -7578,12 +7607,10 @@ thread_prologue_and_epilogue_insns (f)
emit_insn (seq);
/* Retain a map of the prologue insns. */
- if (GET_CODE (seq) != SEQUENCE)
- seq = get_insns ();
record_insns (seq, &prologue);
prologue_end = emit_note (NULL, NOTE_INSN_PROLOGUE_END);
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
/* Can't deal with multiple successors of the entry block
@@ -7674,19 +7701,8 @@ thread_prologue_and_epilogue_insns (f)
that with a conditional return instruction. */
else if (condjump_p (jump))
{
- rtx ret, *loc;
-
- ret = SET_SRC (PATTERN (jump));
- if (GET_CODE (XEXP (ret, 1)) == LABEL_REF)
- loc = &XEXP (ret, 1);
- else
- loc = &XEXP (ret, 2);
- ret = gen_rtx_RETURN (VOIDmode);
-
- if (! validate_change (jump, loc, ret, 0))
+ if (! redirect_jump (jump, 0, 0))
continue;
- if (JUMP_LABEL (jump))
- LABEL_NUSES (JUMP_LABEL (jump))--;
/* If this block has only one successor, it both jumps
and falls through to the fallthru block, so we can't
@@ -7742,11 +7758,9 @@ thread_prologue_and_epilogue_insns (f)
emit_jump_insn (seq);
/* Retain a map of the epilogue insns. */
- if (GET_CODE (seq) != SEQUENCE)
- seq = get_insns ();
record_insns (seq, &epilogue);
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
insert_insn_on_edge (seq, e);
@@ -7772,16 +7786,17 @@ epilogue_done:
continue;
start_sequence ();
- seq = gen_sibcall_epilogue ();
+ emit_insn (gen_sibcall_epilogue ());
+ seq = get_insns ();
end_sequence ();
+ /* Retain a map of the epilogue insns. Used in life analysis to
+ avoid getting rid of sibcall epilogue insns. Do this before we
+ actually emit the sequence. */
+ record_insns (seq, &sibcall_epilogue);
+
i = PREV_INSN (insn);
newinsn = emit_insn_before (seq, insn);
-
- /* Retain a map of the epilogue insns. Used in life analysis to
- avoid getting rid of sibcall epilogue insns. */
- record_insns (GET_CODE (seq) == SEQUENCE
- ? seq : newinsn, &sibcall_epilogue);
}
#endif
@@ -7797,7 +7812,7 @@ epilogue_done:
note before the end of the first basic block, if there isn't
one already there.
- ??? This behaviour is completely broken when dealing with
+ ??? This behavior is completely broken when dealing with
multiple entry functions. We simply place the note always
into first basic block and let alternate entry points
to be missed.
@@ -7818,7 +7833,7 @@ epilogue_done:
}
/* Find the last line number note in the first block. */
- for (insn = BASIC_BLOCK (0)->end;
+ for (insn = ENTRY_BLOCK_PTR->next_bb->end;
insn != prologue_end && insn;
insn = PREV_INSN (insn))
if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0)
@@ -7891,7 +7906,7 @@ reposition_prologue_and_epilogue_notes (f)
break;
}
}
-
+
if (last)
{
rtx next;
@@ -7956,122 +7971,14 @@ reposition_prologue_and_epilogue_notes (f)
#endif /* HAVE_prologue or HAVE_epilogue */
}
-/* Mark P for GC. */
-
-static void
-mark_function_status (p)
- struct function *p;
-{
- struct var_refs_queue *q;
- struct temp_slot *t;
- int i;
- rtx *r;
-
- if (p == 0)
- return;
-
- ggc_mark_rtx (p->arg_offset_rtx);
-
- if (p->x_parm_reg_stack_loc)
- for (i = p->x_max_parm_reg, r = p->x_parm_reg_stack_loc;
- i > 0; --i, ++r)
- ggc_mark_rtx (*r);
-
- ggc_mark_rtx (p->return_rtx);
- ggc_mark_rtx (p->x_cleanup_label);
- ggc_mark_rtx (p->x_return_label);
- ggc_mark_rtx (p->x_save_expr_regs);
- ggc_mark_rtx (p->x_stack_slot_list);
- ggc_mark_rtx (p->x_parm_birth_insn);
- ggc_mark_rtx (p->x_tail_recursion_label);
- ggc_mark_rtx (p->x_tail_recursion_reentry);
- ggc_mark_rtx (p->internal_arg_pointer);
- ggc_mark_rtx (p->x_arg_pointer_save_area);
- ggc_mark_tree (p->x_rtl_expr_chain);
- ggc_mark_rtx (p->x_last_parm_insn);
- ggc_mark_tree (p->x_context_display);
- ggc_mark_tree (p->x_trampoline_list);
- ggc_mark_rtx (p->epilogue_delay_list);
- ggc_mark_rtx (p->x_clobber_return_insn);
-
- for (t = p->x_temp_slots; t != 0; t = t->next)
- {
- ggc_mark (t);
- ggc_mark_rtx (t->slot);
- ggc_mark_rtx (t->address);
- ggc_mark_tree (t->rtl_expr);
- ggc_mark_tree (t->type);
- }
-
- for (q = p->fixup_var_refs_queue; q != 0; q = q->next)
- {
- ggc_mark (q);
- ggc_mark_rtx (q->modified);
- }
-
- ggc_mark_rtx (p->x_nonlocal_goto_handler_slots);
- ggc_mark_rtx (p->x_nonlocal_goto_handler_labels);
- ggc_mark_rtx (p->x_nonlocal_goto_stack_level);
- ggc_mark_tree (p->x_nonlocal_labels);
-
- mark_hard_reg_initial_vals (p);
-}
-
-/* Mark the struct function pointed to by *ARG for GC, if it is not
- NULL. This is used to mark the current function and the outer
- function chain. */
-
-static void
-maybe_mark_struct_function (arg)
- void *arg;
-{
- struct function *f = *(struct function **) arg;
-
- if (f == 0)
- return;
-
- ggc_mark_struct_function (f);
-}
-
-/* Mark a struct function * for GC. This is called from ggc-common.c. */
-
-void
-ggc_mark_struct_function (f)
- struct function *f;
-{
- ggc_mark (f);
- ggc_mark_tree (f->decl);
-
- mark_function_status (f);
- mark_eh_status (f->eh);
- mark_stmt_status (f->stmt);
- mark_expr_status (f->expr);
- mark_emit_status (f->emit);
- mark_varasm_status (f->varasm);
-
- if (mark_machine_status)
- (*mark_machine_status) (f);
- if (mark_lang_status)
- (*mark_lang_status) (f);
-
- if (f->original_arg_vector)
- ggc_mark_rtvec ((rtvec) f->original_arg_vector);
- if (f->original_decl_initial)
- ggc_mark_tree (f->original_decl_initial);
- if (f->outer)
- ggc_mark_struct_function (f->outer);
-}
-
/* Called once, at initialization, to initialize function.c. */
void
init_function_once ()
{
- ggc_add_root (&cfun, 1, sizeof cfun, maybe_mark_struct_function);
- ggc_add_root (&outer_function_chain, 1, sizeof outer_function_chain,
- maybe_mark_struct_function);
-
VARRAY_INT_INIT (prologue, 0, "prologue");
VARRAY_INT_INIT (epilogue, 0, "epilogue");
VARRAY_INT_INIT (sibcall_epilogue, 0, "sibcall_epilogue");
}
+
+#include "gt-function.h"
diff --git a/contrib/gcc/function.h b/contrib/gcc/function.h
index cddfce5..d3fb077 100644
--- a/contrib/gcc/function.h
+++ b/contrib/gcc/function.h
@@ -19,7 +19,7 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
-struct var_refs_queue
+struct var_refs_queue GTY(())
{
rtx modified;
enum machine_mode promoted_mode;
@@ -32,10 +32,11 @@ struct var_refs_queue
The main insn-chain is saved in the last element of the chain,
unless the chain is empty. */
-struct sequence_stack
+struct sequence_stack GTY(())
{
/* First and last insns in the chain of the saved sequence. */
- rtx first, last;
+ rtx first;
+ rtx last;
tree sequence_rtl_expr;
struct sequence_stack *next;
};
@@ -50,7 +51,7 @@ struct simple_obstack_stack
struct simple_obstack_stack *next;
};
-struct emit_status
+struct emit_status GTY(())
{
/* 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. */
@@ -96,15 +97,19 @@ struct emit_status
/* Indexed by pseudo register number, if nonzero gives the known alignment
for that pseudo (if REG_POINTER is set in x_regno_reg_rtx).
Allocated in parallel with x_regno_reg_rtx. */
- unsigned char *regno_pointer_align;
+ unsigned char * GTY ((length ("%h.regno_pointer_align_length")))
+ regno_pointer_align;
/* Indexed by pseudo register number, if nonzero gives the decl
corresponding to that register. */
- tree *regno_decl;
+ tree * GTY ((length ("%h.regno_pointer_align_length"))) regno_decl;
/* Indexed by pseudo register number, gives the rtx for that pseudo.
- Allocated in parallel with regno_pointer_align. */
- rtx *x_regno_reg_rtx;
+ Allocated in parallel with regno_pointer_align.
+
+ Note MEM expressions can appear in this array due to the actions
+ of put_var_into_stack. */
+ rtx * GTY ((length ("%h.regno_pointer_align_length"))) x_regno_reg_rtx;
};
/* For backward compatibility... eventually these should all go away. */
@@ -116,7 +121,7 @@ struct emit_status
#define REGNO_POINTER_ALIGN(REGNO) (cfun->emit->regno_pointer_align[REGNO])
#define REGNO_DECL(REGNO) (cfun->emit->regno_decl[REGNO])
-struct expr_status
+struct expr_status GTY(())
{
/* Number of units that we should eventually pop off the stack.
These are the arguments to function calls that have already returned. */
@@ -133,14 +138,14 @@ struct expr_status
since code outside the conditional won't know whether or not the
arguments need to be popped.)
- When INHIBIT_DEFER_POP is non-zero, however, the compiler does not
+ When INHIBIT_DEFER_POP is nonzero, however, the compiler does not
attempt to defer pops. Instead, the stack is popped immediately
after each call. Rather then setting this variable directly, use
NO_DEFER_POP and OK_DEFER_POP. */
int x_inhibit_defer_pop;
/* If PREFERRED_STACK_BOUNDARY and PUSH_ROUNDING are defined, the stack
- boundary can be momentairly unaligned while pushing the arguments.
+ boundary can be momentarily unaligned while pushing the arguments.
Record the delta since last aligned boundary here in order to get
stack alignment in the nested function calls working right. */
int x_stack_pointer_delta;
@@ -171,7 +176,7 @@ struct expr_status
/* This structure can save all the important global and static variables
describing the status of the current function. */
-struct function
+struct function GTY(())
{
struct eh_status *eh;
struct stmt_status *stmt;
@@ -217,7 +222,7 @@ struct function
used for the current function's args. */
CUMULATIVE_ARGS args_info;
- /* If non-zero, an RTL expression for the location at which the current
+ /* If nonzero, 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. */
@@ -268,6 +273,10 @@ struct function
on machines which require execution of the epilogue on all returns. */
rtx x_return_label;
+ /* Label and register for unswitching computed gotos. */
+ rtx computed_goto_common_label;
+ rtx computed_goto_common_reg;
+
/* 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. */
rtx x_save_expr_regs;
@@ -331,7 +340,7 @@ struct function
to put the parm which is nominally in pseudo register REGNO,
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 *x_parm_reg_stack_loc;
+ rtx * GTY ((length ("%h.x_max_parm_reg"))) x_parm_reg_stack_loc;
/* List of all temporaries allocated, both available and in use. */
struct temp_slot *x_temp_slots;
@@ -355,8 +364,7 @@ struct function
/* For integrate.c. */
int inlinable;
int no_debugging_symbols;
- /* This is in fact an rtvec. */
- void *original_arg_vector;
+ rtvec original_arg_vector;
tree original_decl_initial;
/* Last insn of those whose job was to put parms into their nominal
homes. */
@@ -364,20 +372,20 @@ struct function
/* Highest label number in current function. */
int inl_max_label_num;
- /* Profile label number. */
- int profile_label_no;
+ /* Function sequence number for profiling, debugging, etc. */
+ int funcdef_no;
/* For md files. */
/* tm.h can use this to store whatever it likes. */
- struct machine_function *machine;
+ struct machine_function * GTY ((maybe_undef (""))) machine;
/* The largest alignment of slot allocated on the stack. */
int stack_alignment_needed;
/* Preferred alignment of the end of stack frame. */
int preferred_stack_boundary;
/* Language-specific code can use this to store whatever it likes. */
- struct language_function *language;
+ struct language_function * language;
/* For reorg. */
@@ -433,10 +441,20 @@ struct function
we should try to cut corners where we can. */
unsigned int is_thunk : 1;
+ /* This bit is used by the exception handling logic. It is set if all
+ calls (if any) are sibling calls. Such functions do not have to
+ have EH tables generated, as they cannot throw. A call to such a
+ function, however, should be treated as throwing if any of its callees
+ can throw. */
+ unsigned int all_throwers_are_sibcalls : 1;
+
/* Nonzero if instrumentation calls for function entry and exit should be
generated. */
unsigned int instrument_entry_exit : 1;
+ /* Nonzero if arc profiling should be done for the function. */
+ unsigned int arc_profile : 1;
+
/* Nonzero if profiling code should be generated. */
unsigned int profile : 1;
@@ -444,12 +462,7 @@ struct function
function. */
unsigned int limit_stack : 1;
- /* Nonzero if current function uses varargs.h or equivalent.
- Zero for functions that use stdarg.h. */
- unsigned int varargs : 1;
-
- /* Nonzero if current function uses stdarg.h or equivalent.
- Zero for functions that use varargs.h. */
+ /* Nonzero if current function uses stdarg.h or equivalent. */
unsigned int stdarg : 1;
/* Nonzero if this function is being processed in function-at-a-time
@@ -478,10 +491,27 @@ struct function
/* Nonzero if code to initialize arg_pointer_save_area has been emited. */
unsigned int arg_pointer_save_area_init : 1;
+
+ /* How commonly executed the function is. Initialized during branch
+ probabilities pass. */
+ enum function_frequency {
+ /* This function most likely won't be executed at all.
+ (set only when profile feedback is available). */
+ FUNCTION_FREQUENCY_UNLIKELY_EXECUTED,
+ /* The default value. */
+ FUNCTION_FREQUENCY_NORMAL,
+ /* Optimize this function hard
+ (set only when profile feedback is available). */
+ FUNCTION_FREQUENCY_HOT
+ } function_frequency;
+
+ /* Maximal number of entities in the single jumptable. Used to estimate
+ final flowgraph size. */
+ int max_jumptable_ents;
};
/* The function currently being compiled. */
-extern struct function *cfun;
+extern GTY(()) struct function *cfun;
/* Nonzero if we've already converted virtual regs to hard regs. */
extern int virtuals_instantiated;
@@ -505,13 +535,12 @@ extern int virtuals_instantiated;
#define current_function_pretend_args_size (cfun->pretend_args_size)
#define current_function_outgoing_args_size (cfun->outgoing_args_size)
#define current_function_arg_offset_rtx (cfun->arg_offset_rtx)
-#define current_function_varargs (cfun->varargs)
#define current_function_stdarg (cfun->stdarg)
#define current_function_internal_arg_pointer (cfun->internal_arg_pointer)
#define current_function_return_rtx (cfun->return_rtx)
#define current_function_instrument_entry_exit (cfun->instrument_entry_exit)
#define current_function_profile (cfun->profile)
-#define current_function_profile_label_no (cfun->profile_label_no)
+#define current_function_funcdef_no (cfun->funcdef_no)
#define current_function_limit_stack (cfun->limit_stack)
#define current_function_uses_pic_offset_table (cfun->uses_pic_offset_table)
#define current_function_uses_const_pool (cfun->uses_const_pool)
@@ -569,21 +598,9 @@ extern HOST_WIDE_INT get_frame_size PARAMS ((void));
/* Likewise, but for a different than the current function. */
extern HOST_WIDE_INT get_func_frame_size PARAMS ((struct function *));
-/* These variables hold pointers to functions to create and destroy
- target specific, per-function data structures. */
-extern void (*init_machine_status) PARAMS ((struct function *));
-extern void (*free_machine_status) PARAMS ((struct function *));
-/* This variable holds a pointer to a function to register any
- data items in the target specific, per-function data structure
- that will need garbage collection. */
-extern void (*mark_machine_status) PARAMS ((struct function *));
-
-/* Likewise, but for language-specific data. */
-extern void (*init_lang_status) PARAMS ((struct function *));
-extern void (*mark_lang_status) PARAMS ((struct function *));
-extern void (*save_lang_status) PARAMS ((struct function *));
-extern void (*restore_lang_status) PARAMS ((struct function *));
-extern void (*free_lang_status) PARAMS ((struct function *));
+/* A pointer to a function to create target specific, per-function
+ data structures. */
+extern struct machine_function * (*init_machine_status) PARAMS ((void));
/* Save and restore status information for a nested function. */
extern void restore_emit_status PARAMS ((struct function *));
@@ -591,11 +608,6 @@ extern void free_after_parsing PARAMS ((struct function *));
extern void free_after_compilation PARAMS ((struct function *));
extern void init_varasm_status PARAMS ((struct function *));
-extern void free_varasm_status PARAMS ((struct function *));
-extern void free_emit_status PARAMS ((struct function *));
-extern void free_stmt_status PARAMS ((struct function *));
-extern void free_eh_status PARAMS ((struct function *));
-extern void free_expr_status PARAMS ((struct function *));
extern rtx get_first_block_beg PARAMS ((void));
diff --git a/contrib/gcc/gbl-ctors.h b/contrib/gcc/gbl-ctors.h
index 02e6835f..9ba79f0 100644
--- a/contrib/gcc/gbl-ctors.h
+++ b/contrib/gcc/gbl-ctors.h
@@ -23,6 +23,13 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
/* This file contains definitions and declarations of things
relating to the normal start-up-time invocation of C++
file-scope static object constructors. These declarations
@@ -78,6 +85,6 @@ do { \
for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++); \
for (i = nptrs; i >= 1; i--) \
__CTOR_LIST__[i] (); \
-} while (0)
+} while (0)
#endif
diff --git a/contrib/gcc/gcc.c b/contrib/gcc/gcc.c
index 7845fc3..c6a993f 100644
--- a/contrib/gcc/gcc.c
+++ b/contrib/gcc/gcc.c
@@ -93,9 +93,6 @@ extern int getrusage PARAMS ((int, struct rusage *));
/* FIXME: when autoconf is fixed, remove the host check - dj */
#if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX)
#define HAVE_TARGET_EXECUTABLE_SUFFIX
-#else
-#undef TARGET_EXECUTABLE_SUFFIX
-#define TARGET_EXECUTABLE_SUFFIX ""
#endif
/* By default there is no special suffix for host executables. */
@@ -122,13 +119,6 @@ extern int getrusage PARAMS ((int, struct rusage *));
static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-#ifndef GET_ENV_PATH_LIST
-#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
-#endif
-
/* Most every one is fine with LIBRARY_PATH. For some, it conflicts. */
#ifndef LIBRARY_PATH_ENV
#define LIBRARY_PATH_ENV "LIBRARY_PATH"
@@ -218,7 +208,7 @@ static const char *compiler_version;
/* The target version specified with -V */
-static const char *spec_version = DEFAULT_TARGET_VERSION;
+static const char *const spec_version = DEFAULT_TARGET_VERSION;
/* The target machine specified with -b. */
@@ -247,9 +237,9 @@ static const struct modify_target
}
modify_target[] = MODIFY_TARGET_NAME;
#endif
-
+
/* The number of errors that have occurred; the link phase will not be
- run if this is non-zero. */
+ run if this is nonzero. */
static int error_count = 0;
/* Greatest exit code of sub-processes that has been encountered up to
@@ -277,11 +267,6 @@ static struct rusage rus, prus;
struct path_prefix;
static void init_spec PARAMS ((void));
-#ifndef VMS
-static char **split_directories PARAMS ((const char *, int *));
-static void free_split_directories PARAMS ((char **));
-static char *make_relative_prefix PARAMS ((const char *, const char *, const char *));
-#endif /* VMS */
static void store_arg PARAMS ((const char *, int, int));
static char *load_specs PARAMS ((const char *));
static void read_specs PARAMS ((const char *, int));
@@ -302,9 +287,14 @@ static void delete_failure_queue PARAMS ((void));
static void clear_failure_queue PARAMS ((void));
static int check_live_switch PARAMS ((int, int));
static const char *handle_braces PARAMS ((const char *));
+static const struct spec_function *lookup_spec_function PARAMS ((const char *));
+static const char *eval_spec_function PARAMS ((const char *, const char *));
+static const char *handle_spec_function PARAMS ((const char *));
static char *save_string PARAMS ((const char *, int));
static void set_collect_gcc_options PARAMS ((void));
static int do_spec_1 PARAMS ((const char *, int, const char *));
+static int do_spec_2 PARAMS ((const char *));
+static void do_self_spec PARAMS ((const char *));
static const char *find_file PARAMS ((const char *));
static int is_directory PARAMS ((const char *, const char *, int));
static void validate_switches PARAMS ((const char *));
@@ -325,6 +315,7 @@ static void add_assembler_option PARAMS ((const char *, int));
static void add_linker_option PARAMS ((const char *, int));
static void process_command PARAMS ((int, const char *const *));
static int execute PARAMS ((void));
+static void alloc_args PARAMS ((void));
static void clear_args PARAMS ((void));
static void fatal_error PARAMS ((int));
#ifdef ENABLE_SHARED_LIBGCC
@@ -335,6 +326,9 @@ static void init_gcc_specs PARAMS ((struct obstack *,
#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
static const char *convert_filename PARAMS ((const char *, int, int));
#endif
+
+static const char *if_exists_spec_function PARAMS ((int, const char **));
+static const char *if_exists_else_spec_function PARAMS ((int, const char **));
/* The Specs Language
@@ -426,7 +420,7 @@ or with constant text in a single argument.
and substitute the full name found.
%eSTR Print STR as an error message. STR is terminated by a newline.
Use this when inconsistent options are detected.
- %nSTR Print STR as an notice. STR is terminated by a newline.
+ %nSTR Print STR as a notice. STR is terminated by a newline.
%x{OPTION} Accumulate an option for %X.
%X Output the accumulated linker options specified by compilations.
%Y Output the accumulated assembler options specified by compilations.
@@ -458,6 +452,12 @@ or with constant text in a single argument.
%* substitute the variable part of a matched option. (See below.)
Note that each comma in the substituted string is replaced by
a single space.
+ %:function(args)
+ Call the named function FUNCTION, passing it ARGS. ARGS is
+ first processed as a nested spec string, then split into an
+ argument vector in the usual fashion. The function returns
+ a string which is processed as if it had appeared literally
+ as part of the current spec.
%{S} substitutes the -S switch, if that switch was given to CC.
If that switch was not specified, this substitutes nothing.
Here S is a metasyntactic variable.
@@ -647,7 +647,11 @@ proper position among the other output files. */
# endif
#endif
-static const char *asm_debug = ASM_DEBUG_SPEC;
+#ifndef STARTFILE_PREFIX_SPEC
+# define STARTFILE_PREFIX_SPEC ""
+#endif
+
+static const char *asm_debug;
static const char *cpp_spec = CPP_SPEC;
static const char *cpp_predefines = CPP_PREDEFINES;
static const char *cc1_spec = CC1_SPEC;
@@ -664,6 +668,7 @@ static const char *switches_need_spaces = SWITCHES_NEED_SPACES;
static const char *linker_name_spec = LINKER_NAME;
static const char *link_command_spec = LINK_COMMAND_SPEC;
static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
+static const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
/* Standard options to cpp, cc1, and as, to reduce duplication in specs.
There should be no need to override these in target dependent files,
@@ -671,45 +676,48 @@ static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
of the GCC driver can correctly drive older tool chains with the
appropriate -B options. */
+/* When cpplib handles traditional preprocessing, get rid of this, and
+ call cc1 (or cc1obj in objc/lang-specs.h) from the main specs so
+ that we default the front end language better. */
static const char *trad_capable_cpp =
-"%{traditional|ftraditional|traditional-cpp:trad}cpp0";
+"cc1 -E %{traditional|ftraditional|traditional-cpp:-traditional-cpp}";
/* We don't wrap .d files in %W{} since a missing .d file, and
therefore no dependency entry, confuses make into thinking a .o
file that happens to exist is up-to-date. */
static const char *cpp_unique_options =
"%{C:%{!E:%eGNU C does not support -C without using -E}}\
- %{nostdinc*} %{C} %{v} %{I*} %{P} %{$} %I\
+ %{CC:%{!E:%eGNU C does not support -CC without using -E}}\
+ %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*} %{P} %I\
%{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
%{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
%{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
%{!E:%{!M:%{!MM:%{MD|MMD:%{o*:-MQ %*}}}}}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3 -D__GXX_ABI_VERSION=102}\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
%{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
- %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
- %{fno-inline|O0|!O*:-D__NO_INLINE__} %{ffast-math:-D__FAST_MATH__}\
- %{ffreestanding:-D__STDC_HOSTED__=0} %{fno-hosted:-D__STDC_HOSTED__=0}\
- %{!ffreestanding:%{!fno-hosted:-D__STDC_HOSTED__=1}} %{remap}\
- %{g3:-dD} %{H} %C\
- %{fshort-wchar:-U__WCHAR_TYPE__ -D__WCHAR_TYPE__=short\\ unsigned\\ int}\
- %{D*&U*&A*} %{i*} %Z %i\
+ %{remap} %{g3:-dD} %{H} %C %{D*&U*&A*} %{i*} %Z %i\
%{E|M|MM:%W{o*}}";
/* This contains cpp options which are common with cc1_options and are passed
- only when preprocessing only to avoid duplication. */
+ only when preprocessing only to avoid duplication. We pass the cc1 spec
+ options to the preprocessor so that it the cc1 spec may manipulate
+ options used to set target flags. Those special target flags settings may
+ in turn cause preprocessor symbols to be defined specially. */
static const char *cpp_options =
-"%(cpp_unique_options) %{std*} %{d*} %{W*} %{w} %{pedantic*}\
- %{fshow-column} %{fno-show-column}\
- %{fsigned-char&funsigned-char}\
- %{fleading-underscore} %{fno-leading-underscore}\
- %{fno-operator-names} %{ftabstop=*}";
+"%(cpp_unique_options) %1 %{m*} %{std*} %{ansi} %{W*&pedantic*} %{w} %{f*}\
+ %{O*} %{undef}";
+
+/* This contains cpp options which are not passed when the preprocessor
+ output will be used by another program. */
+static const char *cpp_debug_options = "%{d*}";
/* NB: This is shared amongst all front-ends. */
static const char *cc1_options =
"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%1 %{!Q:-quiet} -dumpbase %B %{d*} %{m*} %{a*}\
- %{g*} %{O*} %{W*} %{w} %{pedantic*} %{std*} %{ansi}\
- %{traditional} %{v:-version} %{pg:-p} %{p} %{f*}\
+ -auxbase%{c|S:%{o*:-strip %*}%{!o*: %b}}%{!c:%{!S: %b}}\
+ %{g*} %{O*} %{W*&pedantic*} %{w} %{std*} %{ansi}\
+ %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
%{Qn:-fno-ident} %{--help:--help}\
%{--target-help:--target-help}\
%{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
@@ -739,6 +747,12 @@ static const char *multilib_exclusions;
static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
+#ifndef DRIVER_SELF_SPECS
+#define DRIVER_SELF_SPECS ""
+#endif
+
+static const char *const driver_self_specs[] = { DRIVER_SELF_SPECS };
+
struct user_specs
{
struct user_specs *next;
@@ -747,31 +761,10 @@ struct user_specs
static struct user_specs *user_specs_head, *user_specs_tail;
-/* This defines which switch letters take arguments. */
-
-#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
- ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
- || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
- || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
- || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \
- || (CHAR) == 'B' || (CHAR) == 'b')
-
#ifndef SWITCH_TAKES_ARG
#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
#endif
-/* This defines which multi-letter switches take arguments. */
-
-#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR) \
- (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \
- || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \
- || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
- || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
- || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
- || !strcmp (STR, "isystem") || !strcmp (STR, "-param") \
- || !strcmp (STR, "specs") \
- || !strcmp (STR, "MF") || !strcmp (STR, "MT") || !strcmp (STR, "MQ"))
-
#ifndef WORD_SWITCH_TAKES_ARG
#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
#endif
@@ -839,26 +832,25 @@ static const struct compiler default_compilers[] =
{".c", "@c", 0},
{"@c",
/* cc1 has an integrated ISO C preprocessor. We should invoke the
- external preprocessor if -save-temps or -traditional is given. */
- "%{E|M|MM:%(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)}\
+ external preprocessor if -save-temps is given. */
+ "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
%{!E:%{!M:%{!MM:\
- %{save-temps|no-integrated-cpp:%(trad_capable_cpp) -lang-c %{ansi:-std=c89}\
+ %{traditional|ftraditional:\
+%eGNU C no longer supports -traditional without -E}\
+ %{save-temps|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
%(cpp_options) %{save-temps:%b.i} %{!save-temps:%g.i} \n\
cc1 -fpreprocessed %{save-temps:%b.i} %{!save-temps:%g.i} %(cc1_options)}\
- %{!save-temps:%{!no-integrated-cpp:\
- %{traditional|ftraditional|traditional-cpp:\
- tradcpp0 -lang-c %{ansi:-std=c89} %(cpp_options) %{!pipe:%g.i} |\n\
- cc1 -fpreprocessed %{!pipe:%g.i} %(cc1_options)}\
- %{!traditional:%{!ftraditional:%{!traditional-cpp:\
- cc1 -lang-c %{ansi:-std=c89} %(cpp_unique_options) %(cc1_options)}}}}}\
+ %{!save-temps:%{!traditional-cpp:%{!no-integrated-cpp:\
+ cc1 %(cpp_unique_options) %(cc1_options)}}}\
%{!fsyntax-only:%(invoke_as)}}}}", 0},
{"-",
"%{!E:%e-E required when input is from standard input}\
- %(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)", 0},
+ %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0},
{".h", "@c-header", 0},
{"@c-header",
"%{!E:%ecompilation of header file requested} \
- %(trad_capable_cpp) -lang-c %{ansi:-std=c89} %(cpp_options)", 0},
+ %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)",
+ 0},
{".i", "@cpp-output", 0},
{"@cpp-output",
"%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0},
@@ -868,6 +860,7 @@ static const struct compiler default_compilers[] =
{".S", "@assembler-with-cpp", 0},
{"@assembler-with-cpp",
"%(trad_capable_cpp) -lang-asm %(cpp_options)\
+ %{E|M|MM:%(cpp_debug_options)}\
%{!M:%{!MM:%{!E:%{!S:-o %{|!pipe:%g.s} |\n\
as %(asm_debug) %(asm_options) %{!pipe:%g.s} %A }}}}", 0},
#include "specs.h"
@@ -877,8 +870,7 @@ static const struct compiler default_compilers[] =
/* Number of elements in default_compilers, not counting the terminator. */
-static int n_default_compilers
- = (sizeof default_compilers / sizeof (struct compiler)) - 1;
+static const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1;
/* A vector of options to give to the linker.
These options are accumulated by %x,
@@ -928,6 +920,7 @@ static const struct option_map option_map[] =
{"--bootclasspath", "-fbootclasspath=", "aj"},
{"--CLASSPATH", "-fclasspath=", "aj"},
{"--comments", "-C", 0},
+ {"--comments-in-macros", "-CC", 0},
{"--compile", "-c", 0},
{"--debug", "-g", "oj"},
{"--define-macro", "-D", "aj"},
@@ -1197,7 +1190,7 @@ translate_options (argcp, argvp)
nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0);
else if (WORD_SWITCH_TAKES_ARG (p))
nskip += WORD_SWITCH_TAKES_ARG (p);
- else if ((c == 'B' || c == 'b' || c == 'V' || c == 'x')
+ else if ((c == 'B' || c == 'b' || c == 'x')
&& p[1] == 0)
nskip += 1;
else if (! strcmp (p, "Xlinker"))
@@ -1388,6 +1381,7 @@ static struct spec_list static_specs[] =
INIT_STATIC_SPEC ("invoke_as", &invoke_as),
INIT_STATIC_SPEC ("cpp", &cpp_spec),
INIT_STATIC_SPEC ("cpp_options", &cpp_options),
+ INIT_STATIC_SPEC ("cpp_debug_options", &cpp_debug_options),
INIT_STATIC_SPEC ("cpp_unique_options", &cpp_unique_options),
INIT_STATIC_SPEC ("trad_capable_cpp", &trad_capable_cpp),
INIT_STATIC_SPEC ("cc1", &cc1_spec),
@@ -1414,6 +1408,7 @@ static struct spec_list static_specs[] =
INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix),
INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix),
INIT_STATIC_SPEC ("md_startfile_prefix_1", &md_startfile_prefix_1),
+ INIT_STATIC_SPEC ("startfile_prefix_spec", &startfile_prefix_spec),
};
#ifdef EXTRA_SPECS /* additional specs needed */
@@ -1433,6 +1428,17 @@ static struct spec_list *extra_specs = (struct spec_list *) 0;
static struct spec_list *specs = (struct spec_list *) 0;
+/* List of static spec functions. */
+
+static const struct spec_function static_spec_functions[] =
+{
+ { "if-exists", if_exists_spec_function },
+ { "if-exists-else", if_exists_else_spec_function },
+ { 0, 0 }
+};
+
+static int processing_spec_function;
+
/* Add appropriate libgcc specs to OBSTACK, taking into account
various permutations of -shared-libgcc, -shared, and such. */
@@ -1495,6 +1501,10 @@ init_spec ()
}
#endif
+ /* Initialize here, not in definition. The IRIX 6 O32 cc sometimes chokes
+ on ?: in file-scope variable initializations. */
+ asm_debug = ASM_DEBUG_SPEC;
+
for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
{
sl = &static_specs[i];
@@ -1533,12 +1543,12 @@ init_spec ()
{
const char *p = libgcc_spec;
int in_sep = 1;
-
+
/* Transform the extant libgcc_spec into one that uses the shared libgcc
when given the proper command line arguments. */
while (*p)
{
- if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
+ if (in_sep && *p == '-' && strncmp (p, "-lgcc", 5) == 0)
{
init_gcc_specs (&obstack,
#ifdef NO_SHARED_LIBGCC_MULTILIB
@@ -1700,6 +1710,15 @@ static int signal_count;
static const char *programname;
+/* Allocate the argument vector. */
+
+static void
+alloc_args ()
+{
+ argbuf_length = 10;
+ argbuf = (const char **) xmalloc (argbuf_length * sizeof (const char *));
+}
+
/* Clear out the vector of arguments (after a command is executed). */
static void
@@ -1883,8 +1902,9 @@ read_specs (filename, main_p)
{
int name_len;
struct spec_list *sl;
+ struct spec_list *newsl;
- /* Get original name */
+ /* Get original name. */
p1 += sizeof "%rename";
while (*p1 == ' ' || *p1 == '\t')
p1++;
@@ -1930,6 +1950,11 @@ read_specs (filename, main_p)
if (strcmp (p1, p2) == 0)
continue;
+ for (newsl = specs; newsl; newsl = newsl->next)
+ if (strcmp (newsl->name, p2) == 0)
+ fatal ("%s: attempt to rename spec '%s' to already defined spec '%s'",
+ filename, p1, p2);
+
if (verbose_flag)
{
notice ("rename spec %s to %s\n", p1, p2);
@@ -2160,7 +2185,7 @@ clear_failure_queue ()
/* Build a list of search directories from PATHS.
PREFIX is a string to prepend to the list.
- If CHECK_DIR_P is non-zero we ensure the directory exists.
+ If CHECK_DIR_P is nonzero we ensure the directory exists.
This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
It is also used by the --print-search-dirs flag. */
@@ -2234,246 +2259,6 @@ putenv_from_prefixes (paths, env_var)
putenv (build_search_list (paths, env_var, 1));
}
-#ifndef VMS
-
-/* FIXME: the location independence code for VMS is hairier than this,
- and hasn't been written. */
-
-/* Split a filename into component directories. */
-
-static char **
-split_directories (name, ptr_num_dirs)
- const char *name;
- int *ptr_num_dirs;
-{
- int num_dirs = 0;
- char **dirs;
- const char *p, *q;
- int ch;
-
- /* Count the number of directories. Special case MSDOS disk names as part
- of the initial directory. */
- p = name;
-#ifdef HAVE_DOS_BASED_FILE_SYSTEM
- if (name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
- {
- p += 3;
- num_dirs++;
- }
-#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
-
- while ((ch = *p++) != '\0')
- {
- if (IS_DIR_SEPARATOR (ch))
- {
- num_dirs++;
- while (IS_DIR_SEPARATOR (*p))
- p++;
- }
- }
-
- dirs = (char **) xmalloc (sizeof (char *) * (num_dirs + 2));
-
- /* Now copy the directory parts. */
- num_dirs = 0;
- p = name;
-#ifdef HAVE_DOS_BASED_FILE_SYSTEM
- if (name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
- {
- dirs[num_dirs++] = save_string (p, 3);
- p += 3;
- }
-#endif /* HAVE_DOS_BASED_FILE_SYSTEM */
-
- q = p;
- while ((ch = *p++) != '\0')
- {
- if (IS_DIR_SEPARATOR (ch))
- {
- while (IS_DIR_SEPARATOR (*p))
- p++;
-
- dirs[num_dirs++] = save_string (q, p - q);
- q = p;
- }
- }
-
- if (p - 1 - q > 0)
- dirs[num_dirs++] = save_string (q, p - 1 - q);
-
- dirs[num_dirs] = NULL;
- if (ptr_num_dirs)
- *ptr_num_dirs = num_dirs;
-
- return dirs;
-}
-
-/* Release storage held by split directories. */
-
-static void
-free_split_directories (dirs)
- char **dirs;
-{
- int i = 0;
-
- while (dirs[i] != NULL)
- free (dirs[i++]);
-
- free ((char *) dirs);
-}
-
-/* Given three strings PROGNAME, BIN_PREFIX, PREFIX, return a string that gets
- to PREFIX starting with the directory portion of PROGNAME and a relative
- pathname of the difference between BIN_PREFIX and PREFIX.
-
- For example, if BIN_PREFIX is /alpha/beta/gamma/gcc/delta, PREFIX is
- /alpha/beta/gamma/omega/, and PROGNAME is /red/green/blue/gcc, then this
- function will return /red/green/blue/../omega.
-
- If no relative prefix can be found, return NULL. */
-
-static char *
-make_relative_prefix (progname, bin_prefix, prefix)
- const char *progname;
- const char *bin_prefix;
- const char *prefix;
-{
- char **prog_dirs, **bin_dirs, **prefix_dirs;
- int prog_num, bin_num, prefix_num, std_loc_p;
- int i, n, common;
-
- prog_dirs = split_directories (progname, &prog_num);
- bin_dirs = split_directories (bin_prefix, &bin_num);
-
- /* If there is no full pathname, try to find the program by checking in each
- of the directories specified in the PATH environment variable. */
- if (prog_num == 1)
- {
- char *temp;
-
- GET_ENV_PATH_LIST (temp, "PATH");
- if (temp)
- {
- char *startp, *endp, *nstore;
- size_t prefixlen = strlen (temp) + 1;
- if (prefixlen < 2)
- prefixlen = 2;
-
- nstore = (char *) alloca (prefixlen + strlen (progname) + 1);
-
- startp = endp = temp;
- while (1)
- {
- if (*endp == PATH_SEPARATOR || *endp == 0)
- {
- if (endp == startp)
- {
- nstore[0] = '.';
- nstore[1] = DIR_SEPARATOR;
- nstore[2] = '\0';
- }
- else
- {
- strncpy (nstore, startp, endp - startp);
- if (! IS_DIR_SEPARATOR (endp[-1]))
- {
- nstore[endp - startp] = DIR_SEPARATOR;
- nstore[endp - startp + 1] = 0;
- }
- else
- nstore[endp - startp] = 0;
- }
- strcat (nstore, progname);
- if (! access (nstore, X_OK)
-#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
- || ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK)
-#endif
- )
- {
- free_split_directories (prog_dirs);
- progname = nstore;
- prog_dirs = split_directories (progname, &prog_num);
- break;
- }
-
- if (*endp == 0)
- break;
- endp = startp = endp + 1;
- }
- else
- endp++;
- }
- }
- }
-
- /* Remove the program name from comparison of directory names. */
- prog_num--;
-
- /* Determine if the compiler is installed in the standard location, and if
- so, we don't need to specify relative directories. Also, if argv[0]
- doesn't contain any directory specifiers, there is not much we can do. */
- std_loc_p = 0;
- if (prog_num == bin_num)
- {
- for (i = 0; i < bin_num; i++)
- {
- if (strcmp (prog_dirs[i], bin_dirs[i]) != 0)
- break;
- }
-
- if (prog_num <= 0 || i == bin_num)
- {
- std_loc_p = 1;
- free_split_directories (prog_dirs);
- free_split_directories (bin_dirs);
- prog_dirs = bin_dirs = (char **) 0;
- return NULL;
- }
- }
-
- prefix_dirs = split_directories (prefix, &prefix_num);
-
- /* Find how many directories are in common between bin_prefix & prefix. */
- n = (prefix_num < bin_num) ? prefix_num : bin_num;
- for (common = 0; common < n; common++)
- {
- if (strcmp (bin_dirs[common], prefix_dirs[common]) != 0)
- break;
- }
-
- /* If there are no common directories, there can be no relative prefix. */
- if (common == 0)
- {
- free_split_directories (prog_dirs);
- free_split_directories (bin_dirs);
- free_split_directories (prefix_dirs);
- return NULL;
- }
-
- /* Build up the pathnames in argv[0]. */
- for (i = 0; i < prog_num; i++)
- obstack_grow (&obstack, prog_dirs[i], strlen (prog_dirs[i]));
-
- /* Now build up the ..'s. */
- for (i = common; i < n; i++)
- {
- obstack_grow (&obstack, DIR_UP, sizeof (DIR_UP) - 1);
- obstack_1grow (&obstack, DIR_SEPARATOR);
- }
-
- /* Put in directories to move over to prefix. */
- for (i = common; i < prefix_num; i++)
- obstack_grow (&obstack, prefix_dirs[i], strlen (prefix_dirs[i]));
-
- free_split_directories (prog_dirs);
- free_split_directories (bin_dirs);
- free_split_directories (prefix_dirs);
-
- obstack_1grow (&obstack, '\0');
- return obstack_finish (&obstack);
-}
-#endif /* VMS */
-
/* Check whether NAME can be accessed in MODE. This is like access,
except that it never considers directories to be executable. */
@@ -2737,6 +2522,9 @@ execute ()
struct command *commands; /* each command buffer with above info. */
+ if (processing_spec_function)
+ abort ();
+
/* Count # of piped commands. */
for (n_commands = 1, i = 0; i < argbuf_index; i++)
if (strcmp (argbuf[i], "|") == 0)
@@ -2787,8 +2575,8 @@ execute ()
{
const char *const *j;
- if (verbose_only_flag)
- {
+ if (verbose_only_flag)
+ {
for (j = commands[i].argv; *j; j++)
{
const char *p;
@@ -2801,8 +2589,8 @@ execute ()
}
fputc ('"', stderr);
}
- }
- else
+ }
+ else
for (j = commands[i].argv; *j; j++)
fprintf (stderr, " %s", *j);
@@ -2813,7 +2601,7 @@ execute ()
}
fflush (stderr);
if (verbose_only_flag != 0)
- return 0;
+ return 0;
#ifdef DEBUG
notice ("\nGo ahead? (y or n) ");
fflush (stderr);
@@ -2827,6 +2615,33 @@ execute ()
#endif /* DEBUG */
}
+#ifdef ENABLE_VALGRIND_CHECKING
+ /* Run the each command through valgrind. To simplifiy prepending the
+ path to valgrind and the option "-q" (for quiet operation unless
+ something triggers), we allocate a separate argv array. */
+
+ for (i = 0; i < n_commands; i++)
+ {
+ const char **argv;
+ int argc;
+ int j;
+
+ for (argc = 0; commands[i].argv[argc] != NULL; argc++)
+ ;
+
+ argv = alloca ((argc + 3) * sizeof (char *));
+
+ argv[0] = VALGRIND_PATH;
+ argv[1] = "-q";
+ for (j = 2; j < argc + 2; j++)
+ argv[j] = commands[i].argv[j - 2];
+ argv[j] = NULL;
+
+ commands[i].argv = argv;
+ commands[i].prog = argv[0];
+ }
+#endif
+
/* Run each piped subprocess. */
for (i = 0; i < n_commands; i++)
@@ -2919,7 +2734,7 @@ Internal error: %s (program %s)\n\
Please submit a full bug report.\n\
See %s for instructions.",
strsignal (WTERMSIG (status)), commands[j].prog,
- GCCBUGURL);
+ bug_report_url);
signal_count++;
ret_code = -1;
}
@@ -2997,9 +2812,6 @@ const char **outfiles;
/* Used to track if none of the -B paths are used. */
static int warn_B;
-/* Used to track if standard path isn't used and -b or -V is specified. */
-static int warn_std;
-
/* Gives value to pass as "warn" to add_prefix for standard prefixes. */
static int *warn_std_ptr = 0;
@@ -3105,7 +2917,7 @@ display_help ()
fputs (_(" -o <file> Place the output into <file>\n"), stdout);
fputs (_("\
-x <language> Specify the language of the following input files\n\
- Permissable languages include: c c++ assembler none\n\
+ Permissible languages include: c c++ assembler none\n\
'none' means revert to the default behavior of\n\
guessing the language based on the file's extension\n\
"), stdout);
@@ -3196,7 +3008,7 @@ process_command (argc, argv)
int j;
#endif
- GET_ENV_PATH_LIST (gcc_exec_prefix, "GCC_EXEC_PREFIX");
+ GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX");
n_switches = 0;
n_infiles = 0;
@@ -3215,6 +3027,61 @@ process_command (argc, argv)
}
}
+ /* If there is a -V or -b option (or both), process it now, before
+ trying to interpret the rest of the command line. */
+ if (argc > 1 && argv[1][0] == '-'
+ && (argv[1][1] == 'V' || argv[1][1] == 'b'))
+ {
+ const char *new_version = DEFAULT_TARGET_VERSION;
+ const char *new_machine = DEFAULT_TARGET_MACHINE;
+ const char *progname = argv[0];
+ char **new_argv;
+ char *new_argv0;
+ int baselen;
+
+ while (argc > 1 && argv[1][0] == '-'
+ && (argv[1][1] == 'V' || argv[1][1] == 'b'))
+ {
+ char opt = argv[1][1];
+ const char *arg;
+ if (argv[1][2] != '\0')
+ {
+ arg = argv[1] + 2;
+ argc -= 1;
+ argv += 1;
+ }
+ else if (argc > 2)
+ {
+ arg = argv[2];
+ argc -= 2;
+ argv += 2;
+ }
+ else
+ fatal ("`-%c' option must have argument", opt);
+ if (opt == 'V')
+ new_version = arg;
+ else
+ new_machine = arg;
+ }
+
+ for (baselen = strlen (progname); baselen > 0; baselen--)
+ if (IS_DIR_SEPARATOR (progname[baselen-1]))
+ break;
+ new_argv0 = xmemdup (progname, baselen,
+ baselen + concat_length (new_version, new_machine,
+ "-gcc-", NULL) + 1);
+ strcpy (new_argv0 + baselen, new_machine);
+ strcat (new_argv0, "-gcc-");
+ strcat (new_argv0, new_version);
+
+ new_argv = xmemdup (argv, (argc + 1) * sizeof (argv[0]),
+ (argc + 1) * sizeof (argv[0]));
+ new_argv[0] = new_argv0;
+
+ execvp (new_argv0, new_argv);
+ fatal ("couldn't run `%s': %s", new_argv0, xstrerror (errno));
+ }
+
/* Set up the default search paths. If there is no GCC_EXEC_PREFIX,
see if we can create it from the pathname specified in argv[0]. */
@@ -3254,7 +3121,7 @@ process_command (argc, argv)
/* COMPILER_PATH and LIBRARY_PATH have values
that are lists of directory names with colons. */
- GET_ENV_PATH_LIST (temp, "COMPILER_PATH");
+ GET_ENVIRONMENT (temp, "COMPILER_PATH");
if (temp)
{
const char *startp, *endp;
@@ -3289,7 +3156,7 @@ process_command (argc, argv)
}
}
- GET_ENV_PATH_LIST (temp, LIBRARY_PATH_ENV);
+ GET_ENVIRONMENT (temp, LIBRARY_PATH_ENV);
if (temp && *cross_compile == '0')
{
const char *startp, *endp;
@@ -3322,7 +3189,7 @@ process_command (argc, argv)
}
/* Use LPATH like LIBRARY_PATH (for the CMU build program). */
- GET_ENV_PATH_LIST (temp, "LPATH");
+ GET_ENVIRONMENT (temp, "LPATH");
if (temp && *cross_compile == '0')
{
const char *startp, *endp;
@@ -3362,7 +3229,6 @@ process_command (argc, argv)
/* Scan argv twice. Here, the first time, just count how many switches
there will be in their vector, and how many input files in theirs.
- Also parse any switches that determine the configuration name, such as -b.
Here we also parse the switches that cc itself uses (e.g. -v). */
for (i = 1; i < argc; i++)
@@ -3391,7 +3257,7 @@ process_command (argc, argv)
{
/* translate_options () has turned --version into -fversion. */
printf (_("%s (GCC) %s\n"), programname, version_string);
- fputs (_("Copyright (C) 2002 Free Software Foundation, Inc.\n"),
+ fputs (_("Copyright (C) 2003 Free Software Foundation, Inc.\n"),
stdout);
fputs (_("This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
@@ -3414,20 +3280,20 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
add_linker_option ("--help", 6);
}
else if (strcmp (argv[i], "-ftarget-help") == 0)
- {
- /* translate_options() has turned --target-help into -ftarget-help. */
- target_help_flag = 1;
+ {
+ /* translate_options() has turned --target-help into -ftarget-help. */
+ target_help_flag = 1;
- /* We will be passing a dummy file on to the sub-processes. */
- n_infiles++;
- n_switches++;
+ /* We will be passing a dummy file on to the sub-processes. */
+ n_infiles++;
+ n_switches++;
/* CPP driver cannot obtain switch from cc1_options. */
if (is_cpp_driver)
add_preprocessor_option ("--target-help", 13);
- add_assembler_option ("--target-help", 13);
- add_linker_option ("--target-help", 13);
- }
+ add_assembler_option ("--target-help", 13);
+ add_linker_option ("--target-help", 13);
+ }
else if (! strcmp (argv[i], "-pass-exit-codes"))
{
pass_exit_codes = 1;
@@ -3563,15 +3429,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
switch (c)
{
case 'b':
- n_switches++;
- if (p[1] == 0 && i + 1 == argc)
- fatal ("argument to `-b' is missing");
- if (p[1] == 0)
- spec_machine = argv[++i];
- else
- spec_machine = p + 1;
-
- warn_std_ptr = &warn_std;
+ case 'V':
+ fatal ("`-%c' must come at the start of the command line", c);
break;
case 'B':
@@ -3604,7 +3463,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
tmp[++ len] = 0;
value = tmp;
}
-
+
/* As a kludge, if the arg is "[foo/]stageN/", just
add "[foo/]include" to the include prefix. */
if ((len == 7
@@ -3647,48 +3506,6 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
verbose_flag++;
break;
- case 'V':
- n_switches++;
- if (p[1] == 0 && i + 1 == argc)
- fatal ("argument to `-V' is missing");
- if (p[1] == 0)
- spec_version = argv[++i];
- else
- spec_version = p + 1;
- compiler_version = spec_version;
- warn_std_ptr = &warn_std;
-
- /* Validate the version number. Use the same checks
- done when inserting it into a spec.
-
- The format of the version string is
- ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */
- {
- const char *v = compiler_version;
-
- /* Ignore leading non-digits. i.e. "foo-" in "foo-2.7.2". */
- while (! ISDIGIT (*v))
- v++;
-
- if (v > compiler_version && v[-1] != '-')
- fatal ("invalid version number format");
-
- /* Set V after the first period. */
- while (ISDIGIT (*v))
- v++;
-
- if (*v != '.')
- fatal ("invalid version number format");
-
- v++;
- while (ISDIGIT (*v))
- v++;
-
- if (*v != 0 && *v != ' ' && *v != '.' && *v != '-')
- fatal ("invalid version number format");
- }
- break;
-
case 'S':
case 'c':
if (p[1] == 0)
@@ -3744,8 +3561,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
#ifdef MODIFY_TARGET_NAME
is_modify_target_name = 0;
- for (j = 0;
- j < sizeof modify_target / sizeof modify_target[0]; j++)
+ for (j = 0; j < ARRAY_SIZE (modify_target); j++)
if (! strcmp (argv[i], modify_target[j].sw))
{
char *new_name
@@ -3778,7 +3594,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
if (is_modify_target_name)
break;
-#endif
+#endif
n_switches++;
@@ -3880,7 +3696,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
#ifdef MODIFY_TARGET_NAME
is_modify_target_name = 0;
- for (j = 0; j < sizeof modify_target / sizeof modify_target[0]; j++)
+ for (j = 0; j < ARRAY_SIZE (modify_target); j++)
if (! strcmp (argv[i], modify_target[j].sw))
is_modify_target_name = 1;
@@ -3970,7 +3786,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
/* -save-temps overrides -pipe, so that temp files are produced */
if (save_temps_flag)
error ("warning: -pipe ignored because -save-temps specified");
- /* -time overrides -pipe because we can't get correct stats when
+ /* -time overrides -pipe because we can't get correct stats when
multiple children are running at once. */
else if (report_times)
error ("warning: -pipe ignored because -time specified");
@@ -4049,7 +3865,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
else
{
char ch = switches[n_switches].part1[0];
- if (ch == 'V' || ch == 'b' || ch == 'B')
+ if (ch == 'B')
switches[n_switches].validated = 1;
}
n_switches++;
@@ -4225,15 +4041,7 @@ do_spec (spec)
{
int value;
- clear_args ();
- arg_going = 0;
- delete_this_arg = 0;
- this_is_output_file = 0;
- this_is_library_file = 0;
- input_from_pipe = 0;
- suffix_subst = NULL;
-
- value = do_spec_1 (spec, 0, NULL);
+ value = do_spec_2 (spec);
/* Force out any unfinished command.
If -pipe, this forces out the last command if it ended in `|'. */
@@ -4251,6 +4059,60 @@ do_spec (spec)
return value;
}
+static int
+do_spec_2 (spec)
+ const char *spec;
+{
+ clear_args ();
+ arg_going = 0;
+ delete_this_arg = 0;
+ this_is_output_file = 0;
+ this_is_library_file = 0;
+ input_from_pipe = 0;
+ suffix_subst = NULL;
+
+ return do_spec_1 (spec, 0, NULL);
+}
+
+
+/* Process the given spec string and add any new options to the end
+ of the switches/n_switches array. */
+
+static void
+do_self_spec (spec)
+ const char *spec;
+{
+ do_spec_2 (spec);
+ do_spec_1 (" ", 0, NULL);
+
+ if (argbuf_index > 0)
+ {
+ int i, first;
+
+ first = n_switches;
+ n_switches += argbuf_index;
+ switches = xrealloc (switches,
+ sizeof (struct switchstr) * (n_switches + 1));
+
+ switches[n_switches] = switches[first];
+ for (i = 0; i < argbuf_index; i++)
+ {
+ struct switchstr *sw;
+
+ /* Each switch should start with '-'. */
+ if (argbuf[i][0] != '-')
+ abort ();
+
+ sw = &switches[i + first];
+ sw->part1 = &argbuf[i][1];
+ sw->args = 0;
+ sw->live_cond = SWITCH_OK;
+ sw->validated = 0;
+ sw->ordering = 0;
+ }
+ }
+}
+
/* Process the sub-spec SPEC as a portion of a larger spec.
This is like processing a whole spec except that we do
not initialize at the beginning and we do not supply a
@@ -4518,7 +4380,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
}
break;
case 'n':
- /* %nfoo means report an notice with `foo' on stderr. */
+ /* %nfoo means report a notice with `foo' on stderr. */
{
const char *q = p;
char *buf;
@@ -4584,7 +4446,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
}
suffix_length += strlen (TARGET_OBJECT_SUFFIX);
}
-
+
/* If the input_filename has the same suffix specified
for the %g, %u, or %U, and -save-temps is specified,
we could end up using that file as an intermediate
@@ -4592,7 +4454,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
gcc -save-temps foo.s would clobber foo.s with the
output of cpp0). So check for this condition and
generate a temp file as the intermediate. */
-
+
if (save_temps_flag)
{
temp_filename_length = basename_length + suffix_length;
@@ -4604,7 +4466,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
if (strcmp (temp_filename, input_filename) != 0)
{
struct stat st_temp;
-
+
/* Note, set_input() resets input_stat_set to 0. */
if (input_stat_set == 0)
{
@@ -4612,22 +4474,23 @@ do_spec_1 (spec, inswitch, soft_matched_part)
if (input_stat_set >= 0)
input_stat_set = 1;
}
-
+
/* If we have the stat for the input_filename
and we can do the stat for the temp_filename
then the they could still refer to the same
file if st_dev/st_ino's are the same. */
-
+
if (input_stat_set != 1
|| stat (temp_filename, &st_temp) < 0
|| input_stat.st_dev != st_temp.st_dev
|| input_stat.st_ino != st_temp.st_ino)
- {
+ {
temp_filename = save_string (temp_filename,
temp_filename_length + 1);
obstack_grow (&obstack, temp_filename,
temp_filename_length);
arg_going = 1;
+ delete_this_arg = 0;
break;
}
}
@@ -4830,8 +4693,8 @@ do_spec_1 (spec, inswitch, soft_matched_part)
case 'C':
{
const char *const spec
- = (input_file_compiler->cpp_spec
- ? input_file_compiler->cpp_spec
+ = (input_file_compiler->cpp_spec
+ ? input_file_compiler->cpp_spec
: cpp_spec);
value = do_spec_1 (spec, 0, NULL);
if (value != 0)
@@ -5055,21 +4918,27 @@ do_spec_1 (spec, inswitch, soft_matched_part)
return -1;
break;
+ case ':':
+ p = handle_spec_function (p);
+ if (p == 0)
+ return -1;
+ break;
+
case '%':
obstack_1grow (&obstack, '%');
break;
- case '.':
- {
- unsigned len = 0;
+ case '.':
+ {
+ unsigned len = 0;
- while (p[len] && p[len] != ' ' && p[len] != '%')
- len++;
- suffix_subst = save_string (p - 1, len + 1);
- p += len;
- }
+ while (p[len] && p[len] != ' ' && p[len] != '%')
+ len++;
+ suffix_subst = save_string (p - 1, len + 1);
+ p += len;
+ }
break;
-
+
case '*':
if (soft_matched_part)
{
@@ -5248,10 +5117,179 @@ do_spec_1 (spec, inswitch, soft_matched_part)
arg_going = 1;
}
- /* End of string. */
+ /* End of string. If we are processing a spec function, we need to
+ end any pending argument. */
+ if (processing_spec_function && arg_going)
+ {
+ obstack_1grow (&obstack, 0);
+ string = obstack_finish (&obstack);
+ if (this_is_library_file)
+ string = find_file (string);
+ store_arg (string, delete_this_arg, this_is_output_file);
+ if (this_is_output_file)
+ outfiles[input_file_number] = string;
+ arg_going = 0;
+ }
+
return 0;
}
+/* Look up a spec function. */
+
+static const struct spec_function *
+lookup_spec_function (name)
+ const char *name;
+{
+ static const struct spec_function * const spec_function_tables[] =
+ {
+ static_spec_functions,
+ lang_specific_spec_functions,
+ };
+ const struct spec_function *sf;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE (spec_function_tables); i++)
+ {
+ for (sf = spec_function_tables[i]; sf->name != NULL; sf++)
+ if (strcmp (sf->name, name) == 0)
+ return sf;
+ }
+
+ return NULL;
+}
+
+/* Evaluate a spec function. */
+
+static const char *
+eval_spec_function (func, args)
+ const char *func, *args;
+{
+ const struct spec_function *sf;
+ const char *funcval;
+
+ /* Saved spec processing context. */
+ int save_argbuf_index;
+ int save_argbuf_length;
+ const char **save_argbuf;
+
+ int save_arg_going;
+ int save_delete_this_arg;
+ int save_this_is_output_file;
+ int save_this_is_library_file;
+ int save_input_from_pipe;
+ const char *save_suffix_subst;
+
+
+ sf = lookup_spec_function (func);
+ if (sf == NULL)
+ fatal ("unknown spec function `%s'", func);
+
+ /* Push the spec processing context. */
+ save_argbuf_index = argbuf_index;
+ save_argbuf_length = argbuf_length;
+ save_argbuf = argbuf;
+
+ save_arg_going = arg_going;
+ save_delete_this_arg = delete_this_arg;
+ save_this_is_output_file = this_is_output_file;
+ save_this_is_library_file = this_is_library_file;
+ save_input_from_pipe = input_from_pipe;
+ save_suffix_subst = suffix_subst;
+
+ /* Create a new spec processing context, and build the function
+ arguments. */
+
+ alloc_args ();
+ if (do_spec_2 (args) < 0)
+ fatal ("error in args to spec function `%s'", func);
+
+ /* argbuf_index is an index for the next argument to be inserted, and
+ so contains the count of the args already inserted. */
+
+ funcval = (*sf->func) (argbuf_index, argbuf);
+
+ /* Pop the spec processing context. */
+ argbuf_index = save_argbuf_index;
+ argbuf_length = save_argbuf_length;
+ free (argbuf);
+ argbuf = save_argbuf;
+
+ arg_going = save_arg_going;
+ delete_this_arg = save_delete_this_arg;
+ this_is_output_file = save_this_is_output_file;
+ this_is_library_file = save_this_is_library_file;
+ input_from_pipe = save_input_from_pipe;
+ suffix_subst = save_suffix_subst;
+
+ return funcval;
+}
+
+/* Handle a spec function call of the form:
+
+ %:function(args)
+
+ ARGS is processed as a spec in a separate context and split into an
+ argument vector in the normal fashion. The function returns a string
+ containing a spec which we then process in the caller's context, or
+ NULL if no processing is required. */
+
+static const char *
+handle_spec_function (p)
+ const char *p;
+{
+ char *func, *args;
+ const char *endp, *funcval;
+ int count;
+
+ processing_spec_function++;
+
+ /* Get the function name. */
+ for (endp = p; *endp != '\0'; endp++)
+ {
+ if (*endp == '(') /* ) */
+ break;
+ /* Only allow [A-Za-z0-9], -, and _ in function names. */
+ if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_'))
+ fatal ("malformed spec function name");
+ }
+ if (*endp != '(') /* ) */
+ fatal ("no arguments for spec function");
+ func = save_string (p, endp - p);
+ p = ++endp;
+
+ /* Get the arguments. */
+ for (count = 0; *endp != '\0'; endp++)
+ {
+ /* ( */
+ if (*endp == ')')
+ {
+ if (count == 0)
+ break;
+ count--;
+ }
+ else if (*endp == '(') /* ) */
+ count++;
+ }
+ /* ( */
+ if (*endp != ')')
+ fatal ("malformed spec function arguments");
+ args = save_string (p, endp - p);
+ p = ++endp;
+
+ /* p now points to just past the end of the spec function expression. */
+
+ funcval = eval_spec_function (func, args);
+ if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0)
+ p = NULL;
+
+ free (func);
+ free (args);
+
+ processing_spec_function--;
+
+ return p;
+}
+
/* Return 0 if we call do_spec_1 and that returns -1. */
static const char *
@@ -5766,7 +5804,7 @@ set_input (filename)
}
else
input_suffix = "";
-
+
/* If a spec for 'g', 'u', or 'U' is seen with -save-temps then
we will need to do a stat on the input_filename. The
INPUT_STAT_SET signals that the stat is needed. */
@@ -5834,8 +5872,8 @@ main (argc, argv)
signal (SIGCHLD, SIG_DFL);
#endif
- argbuf_length = 10;
- argbuf = (const char **) xmalloc (argbuf_length * sizeof (const char *));
+ /* Allocate the argument vector. */
+ alloc_args ();
obstack_init (&obstack);
@@ -5900,6 +5938,12 @@ main (argc, argv)
process_command (argc, argv);
+ /* Process DRIVER_SELF_SPECS, adding any new options to the end
+ of the command line. */
+
+ for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++)
+ do_self_spec (driver_self_specs[i]);
+
/* Initialize the vector of specs to just the default.
This means one element containing 0s, as a terminator. */
@@ -5933,8 +5977,10 @@ main (argc, argv)
if (access (specs_file, R_OK) == 0)
read_specs (specs_file, TRUE);
- /* If not cross-compiling, look for startfiles in the standard places. */
- if (*cross_compile == '0')
+ /* If not cross-compiling, look for startfiles in the standard places.
+ Similarly, don't add the standard prefixes if startfile handling
+ will be under control of startfile_prefix_spec. */
+ if (*cross_compile == '0' && *startfile_prefix_spec == 0)
{
if (*md_exec_prefix)
{
@@ -5992,6 +6038,16 @@ main (argc, argv)
"BINUTILS", PREFIX_PRIORITY_LAST, 0, NULL, 1);
}
+ if (*startfile_prefix_spec != 0
+ && do_spec_2 (startfile_prefix_spec) == 0
+ && do_spec_1 (" ", 0, NULL) == 0)
+ {
+ int ndx;
+ for (ndx = 0; ndx < argbuf_index; ndx++)
+ add_prefix (&startfile_prefixes, argbuf[ndx], "BINUTILS",
+ PREFIX_PRIORITY_LAST, 0, NULL, 1);
+ }
+
/* Process any user specified specs in the order given on the command
line. */
for (uptr = user_specs_head; uptr; uptr = uptr->next)
@@ -6085,7 +6141,7 @@ main (argc, argv)
if (! verbose_flag)
{
printf (_("\nFor bug reporting instructions, please see:\n"));
- printf ("%s.\n", GCCBUGURL);
+ printf ("%s.\n", bug_report_url);
return (0);
}
@@ -6166,7 +6222,7 @@ main (argc, argv)
input_file_compiler
= lookup_compiler (infiles[i].name, input_filename_length,
infiles[i].language);
-
+
if (input_file_compiler)
{
/* Ok, we found an applicable compiler. Run its spec. */
@@ -6260,7 +6316,7 @@ main (argc, argv)
if (print_help_list)
{
printf (("\nFor bug reporting instructions, please see:\n"));
- printf ("%s\n", GCCBUGURL);
+ printf ("%s\n", bug_report_url);
}
return (signal_count != 0 ? 2
@@ -6305,7 +6361,7 @@ lookup_compiler (name, length, language)
&& !strcmp (cp->suffix,
name + length - strlen (cp->suffix))
))
- break;
+ break;
}
#if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM)
@@ -7172,3 +7228,43 @@ print_multilib_info ()
++p;
}
}
+
+/* if-exists built-in spec function.
+
+ Checks to see if the file specified by the absolute pathname in
+ ARGS exists. Returns that pathname if found.
+
+ The usual use for this function is to check for a library file
+ (whose name has been expanded with %s). */
+
+static const char *
+if_exists_spec_function (argc, argv)
+ int argc;
+ const char **argv;
+{
+ /* Must have only one argument. */
+ if (argc == 1 && IS_ABSOLUTE_PATHNAME (argv[0]) && ! access (argv[0], R_OK))
+ return argv[0];
+
+ return NULL;
+}
+
+/* if-exists-else built-in spec function.
+
+ This is like if-exists, but takes an additional argument which
+ is returned if the first argument does not exist. */
+
+static const char *
+if_exists_else_spec_function (argc, argv)
+ int argc;
+ const char **argv;
+{
+ /* Must have exactly two arguments. */
+ if (argc != 2)
+ return NULL;
+
+ if (IS_ABSOLUTE_PATHNAME (argv[0]) && ! access (argv[0], R_OK))
+ return argv[0];
+
+ return argv[1];
+}
diff --git a/contrib/gcc/gcc.h b/contrib/gcc/gcc.h
index 7703387..06691bd 100644
--- a/contrib/gcc/gcc.h
+++ b/contrib/gcc/gcc.h
@@ -23,6 +23,36 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "version.h"
+/* The mapping of a spec function name to the C function that
+ implements it. */
+struct spec_function
+{
+ const char *name;
+ const char *(*func) PARAMS ((int, const char **));
+};
+
+/* This defines which switch letters take arguments. */
+
+#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
+ ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
+ || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
+ || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
+ || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \
+ || (CHAR) == 'B' || (CHAR) == 'b')
+
+/* This defines which multi-letter switches take arguments. */
+
+#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR) \
+ (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \
+ || !strcmp (STR, "Tbss") || !strcmp (STR, "include") \
+ || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
+ || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
+ || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
+ || !strcmp (STR, "isystem") || !strcmp (STR, "-param") \
+ || !strcmp (STR, "specs") \
+ || !strcmp (STR, "MF") || !strcmp (STR, "MT") || !strcmp (STR, "MQ"))
+
+
/* These are exported by gcc.c. */
extern int do_spec PARAMS ((const char *));
extern void record_temp_file PARAMS ((const char *, int, int));
@@ -48,6 +78,9 @@ extern int n_infiles;
/* Number of extra output files that lang_specific_pre_link may generate. */
extern int lang_specific_extra_outfiles;
+/* Table of language-specific spec functions. */
+extern const struct spec_function lang_specific_spec_functions[];
+
/* A vector of corresponding output files is made up later. */
extern const char **outfiles;
diff --git a/contrib/gcc/gccbug.in b/contrib/gcc/gccbug.in
index 9619e61..4da8415 100755
--- a/contrib/gcc/gccbug.in
+++ b/contrib/gcc/gccbug.in
@@ -198,7 +198,7 @@ EOF
done
# spam does not need to be listed here
-CATEGORIES="ada bootstrap c++ c debug fortran java libf2c libgcj libobjc libstdc++ middle-end objc optimization other preprocessor target web"
+CATEGORIES="ada bootstrap c++ c debug driver fortran inline-asm java libf2c libgcj libobjc libstdc++ middle-end objc optimization other preprocessor target web"
case "$FORMAT" in
lisp) echo "$CATEGORIES" | \
diff --git a/contrib/gcc/gccspec.c b/contrib/gcc/gccspec.c
index 867cbd5..6e538b1 100644
--- a/contrib/gcc/gccspec.c
+++ b/contrib/gcc/gccspec.c
@@ -57,7 +57,7 @@ lang_specific_driver (in_argc, in_argv, in_added_libraries)
}
else
{
- int len;
+ int len;
/* If the filename ends in .m or .mi, we are compiling ObjC
and want to pass -shared-libgcc. */
@@ -101,3 +101,9 @@ lang_specific_pre_link ()
/* Number of extra output files that lang_specific_pre_link may generate. */
int lang_specific_extra_outfiles = 0; /* Not used for C. */
+
+/* Table of language-specific spec functions. */
+const struct spec_function lang_specific_spec_functions[] =
+{
+ { 0, 0 }
+};
diff --git a/contrib/gcc/gcov-io.h b/contrib/gcc/gcov-io.h
index 7352429..50d04a3 100644
--- a/contrib/gcc/gcov-io.h
+++ b/contrib/gcc/gcov-io.h
@@ -19,23 +19,42 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
+/* 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. */
+
#ifndef GCC_GCOV_IO_H
#define GCC_GCOV_IO_H
#include <stdio.h>
#include <sys/types.h>
-static int __fetch_long PARAMS ((long *, char *, size_t)) ATTRIBUTE_UNUSED;
-static int __read_long PARAMS ((long *, FILE *, size_t)) ATTRIBUTE_UNUSED;
-static int __write_long PARAMS ((long, FILE *, size_t)) ATTRIBUTE_UNUSED;
-static int __fetch_gcov_type PARAMS ((gcov_type *, char *, size_t)) ATTRIBUTE_UNUSED;
-static int __store_gcov_type PARAMS ((gcov_type, char *, size_t)) ATTRIBUTE_UNUSED;
-static int __read_gcov_type PARAMS ((gcov_type *, FILE *, size_t)) ATTRIBUTE_UNUSED;
-static int __write_gcov_type PARAMS ((gcov_type, FILE *, size_t)) ATTRIBUTE_UNUSED;
+static int __fetch_long PARAMS ((long *, char *, size_t))
+ ATTRIBUTE_UNUSED;
+static int __read_long PARAMS ((long *, FILE *, size_t))
+ ATTRIBUTE_UNUSED;
+static int __write_long PARAMS ((long, FILE *, size_t))
+ ATTRIBUTE_UNUSED;
+static int __fetch_gcov_type PARAMS ((gcov_type *, char *, size_t))
+ ATTRIBUTE_UNUSED;
+static int __store_gcov_type PARAMS ((gcov_type, char *, size_t))
+ ATTRIBUTE_UNUSED;
+static int __read_gcov_type PARAMS ((gcov_type *, FILE *, size_t))
+ ATTRIBUTE_UNUSED;
+static int __write_gcov_type PARAMS ((gcov_type, FILE *, size_t))
+ ATTRIBUTE_UNUSED;
+static int __write_gcov_string PARAMS ((const char *, size_t, FILE*, long))
+ ATTRIBUTE_UNUSED;
+static int __read_gcov_string PARAMS ((char *, size_t, FILE*, long))
+ ATTRIBUTE_UNUSED;
/* These routines only work for signed values. */
/* Store a portable representation of VALUE in DEST using BYTES*8-1 bits.
- Return a non-zero value if VALUE requires more than BYTES*8-1 bits
+ Return a nonzero value if VALUE requires more than BYTES*8-1 bits
to store. */
static int
@@ -63,14 +82,14 @@ __store_gcov_type (value, dest, bytes)
if (value && value != -1)
return 1;
- for(; i < bytes ; i++)
+ for(; i < bytes ; i++)
dest[i] = 0;
dest[bytes - 1] |= upper_bit;
return 0;
}
/* Retrieve a quantity containing BYTES*8-1 bits from SOURCE and store
- the result in DEST. Returns a non-zero value if the value in SOURCE
+ the result in DEST. Returns a nonzero value if the value in SOURCE
will not fit in DEST. */
static int
@@ -119,7 +138,7 @@ __fetch_long (dest, source, bytes)
return 0;
}
-/* Write a BYTES*8-bit quantity to FILE, portably. Returns a non-zero
+/* Write a BYTES*8-bit quantity to FILE, portably. Returns a nonzero
value if the write fails, or if VALUE can't be stored in BYTES*8
bits.
@@ -157,7 +176,7 @@ __write_long (value, file, bytes)
}
/* Read a quantity containing BYTES bytes from FILE, portably. Return
- a non-zero value if the read fails or if the value will not fit
+ a nonzero value if the read fails or if the value will not fit
in DEST.
Note that DEST may not be large enough to hold all of the requested
@@ -193,4 +212,94 @@ __read_long (dest, file, bytes)
return __fetch_long (dest, c, bytes);
}
+
+/* Writes string in gcov format. */
+
+static int
+__write_gcov_string (string, length, file, delim)
+ const char *string;
+ size_t length;
+ FILE *file;
+ long delim;
+{
+ size_t temp = length + 1;
+
+ /* delimiter */
+ if (__write_long (delim, file, 4) != 0)
+ return 1;
+
+ if (__write_long (length, file, 4) != 0)
+ return 1;
+
+ if (fwrite (string, temp, 1, file) != 1)
+ return 1;
+
+ temp &= 3;
+
+ if (temp)
+ {
+ char c[4];
+
+ c[0] = c[1] = c[2] = c[3] = 0;
+
+ if (fwrite (c, sizeof (char), 4 - temp, file) != 4 - temp)
+ return 1;
+ }
+
+ if (__write_long (delim, file, 4) != 0)
+ return 1;
+
+ return 0;
+}
+
+/* Reads string in gcov format. */
+
+
+static int
+__read_gcov_string (string, max_length, file, delim)
+ char *string;
+ size_t max_length;
+ FILE *file;
+ long delim;
+{
+ long delim_from_file;
+ long length;
+ long read_length;
+ long tmp;
+
+ if (__read_long (&delim_from_file, file, 4) != 0)
+ return 1;
+
+ if (delim_from_file != delim)
+ return 1;
+
+ if (__read_long (&length, file, 4) != 0)
+ return 1;
+
+ if (length > (long) max_length)
+ read_length = max_length;
+ else
+ read_length = length;
+
+ tmp = (((length + 1) - 1) / 4 + 1) * 4;
+ /* This is the size occupied by the string in the file */
+
+ if (fread (string, read_length, 1, file) != 1)
+ return 1;
+
+ string[read_length] = 0;
+
+ if (fseek (file, tmp - read_length, SEEK_CUR) < 0)
+ return 1;
+
+ if (__read_long (&delim_from_file, file, 4) != 0)
+ return 1;
+
+ if (delim_from_file != delim)
+ return 1;
+
+ return 0;
+}
+
+
#endif /* ! GCC_GCOV_IO_H */
diff --git a/contrib/gcc/gcov.c b/contrib/gcc/gcov.c
index 3bb2ce1..94f9baa 100644
--- a/contrib/gcc/gcov.c
+++ b/contrib/gcc/gcov.c
@@ -103,7 +103,8 @@ struct sourcefile *sources;
/* One of these is dynamically created whenever we identify an arc in the
function. */
-struct adj_list {
+struct adj_list
+{
int source;
int target;
gcov_type arc_count;
@@ -122,7 +123,8 @@ struct adj_list {
/* Count the number of basic blocks, and create an array of these structures,
one for each bb in the function. */
-struct bb_info {
+struct bb_info
+{
struct adj_list *succ;
struct adj_list *pred;
gcov_type succ_count;
@@ -149,17 +151,45 @@ struct arcdata
/* Used to save the list of bb_graphs, one per function. */
-struct bb_info_list {
+struct bb_info_list
+{
/* Indexed by block number, holds the basic block graph for one function. */
struct bb_info *bb_graph;
int num_blocks;
struct bb_info_list *next;
};
+/* Used to hold information about each line. */
+struct line_info
+{
+ gcov_type count; /* execution count */
+ struct arcdata *branches; /* list of branch probabilities for line. */
+ unsigned exists : 1; /* has code associated with it. */
+};
+
+struct coverage
+{
+ int lines;
+ int lines_executed;
+
+ int branches;
+ int branches_executed;
+ int branches_taken;
+
+ int calls;
+ int calls_executed;
+
+ char *name;
+};
+
/* Holds a list of function basic block graphs. */
static struct bb_info_list *bb_graph_list = 0;
+/* Modification time of data files. */
+
+static time_t bb_file_time;
+
/* Name and file pointer of the input file for the basic block graph. */
static char *bbg_file_name;
@@ -183,11 +213,6 @@ static char *bb_data;
static long bb_data_size;
-/* Name and file pointer of the output file. */
-
-static char *gcov_file_name;
-static FILE *gcov_file;
-
/* Name of the file mentioned on the command line. */
static char *input_file_name = 0;
@@ -212,11 +237,15 @@ static int output_long_names = 0;
static int output_function_summary = 0;
-/* Object directory file prefix. This is the directory where .bb and .bbg
- files are looked for, if non-zero. */
+/* Object directory file prefix. This is the directory/file
+ where .bb and .bbg files are looked for, if nonzero. */
static char *object_directory = 0;
+/* Preserve all pathname components. Needed when object files and
+ source files are in subdirectories. */
+static int preserve_paths = 0;
+
/* Output the number of times a branch was taken as opposed to the percentage
of times it was taken. Turned on by the -c option */
@@ -227,16 +256,27 @@ static void process_args PARAMS ((int, char **));
static void open_files PARAMS ((void));
static void read_files PARAMS ((void));
static void scan_for_source_files PARAMS ((void));
-static void output_data PARAMS ((void));
+static void output_data PARAMS ((struct sourcefile *));
static void print_usage PARAMS ((int)) ATTRIBUTE_NORETURN;
static void print_version PARAMS ((void)) ATTRIBUTE_NORETURN;
static void init_arc PARAMS ((struct adj_list *, int, int, struct bb_info *));
static struct adj_list *reverse_arcs PARAMS ((struct adj_list *));
+static gcov_type *read_profile PARAMS ((char *, long, int));
static void create_program_flow_graph PARAMS ((struct bb_info_list *));
static void solve_program_flow_graph PARAMS ((struct bb_info_list *));
-static void calculate_branch_probs PARAMS ((struct bb_info_list *, int,
- struct arcdata **, int));
-static void function_summary PARAMS ((void));
+static void accumulate_branch_counts PARAMS ((struct coverage *,
+ struct arcdata *));
+static void calculate_branch_probs PARAMS ((struct bb_info *,
+ struct line_info *,
+ struct coverage *));
+static void function_summary PARAMS ((struct coverage *, const char *));
+static void init_line_info PARAMS ((struct line_info *,
+ struct coverage *, long));
+static void output_line_info PARAMS ((FILE *, const struct line_info *,
+ const struct coverage *, long));
+static char *make_gcov_file_name PARAMS ((char *));
+static const char *format_hwint PARAMS ((HOST_WIDEST_INT, HOST_WIDEST_INT,
+ int));
extern int main PARAMS ((int, char **));
@@ -245,6 +285,8 @@ main (argc, argv)
int argc;
char **argv;
{
+ struct sourcefile *s_ptr;
+
gcc_init_libintl ();
process_args (argc, argv);
@@ -255,7 +297,8 @@ main (argc, argv)
scan_for_source_files ();
- output_data ();
+ for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
+ output_data (s_ptr);
return 0;
}
@@ -303,9 +346,10 @@ print_usage (error_p)
fnotice (file, " -l, --long-file-names Use long output file names for included\n\
source files\n");
fnotice (file, " -f, --function-summaries Output summaries for each function\n");
- fnotice (file, " -o, --object-directory OBJDIR Search for object files in OBJDIR\n");
+ fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n");
+ fnotice (file, " -p, --preserve-paths Preserve all pathname components\n");
fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
- GCCBUGURL);
+ bug_report_url);
exit (status);
}
@@ -331,7 +375,9 @@ static const struct option options[] =
{ "no-output", no_argument, NULL, 'n' },
{ "long-file-names", no_argument, NULL, 'l' },
{ "function-summaries", no_argument, NULL, 'f' },
- { "object-directory", required_argument, NULL, 'o' }
+ { "preserve-paths", no_argument, NULL, 'p' },
+ { "object-directory", required_argument, NULL, 'o' },
+ { "object-file", required_argument, NULL, 'o' },
};
/* Parse the command line. */
@@ -343,7 +389,7 @@ process_args (argc, argv)
{
int opt;
- while ((opt = getopt_long (argc, argv, "hvbclnfo:", options, NULL)) != -1)
+ while ((opt = getopt_long (argc, argv, "hvbclnfo:p", options, NULL)) != -1)
{
switch (opt)
{
@@ -371,6 +417,9 @@ process_args (argc, argv)
case 'o':
object_directory = optarg;
break;
+ case 'p':
+ preserve_paths = 1;
+ break;
default:
print_usage (true);
/* print_usage will exit. */
@@ -384,77 +433,66 @@ process_args (argc, argv)
}
-/* Find and open the .bb, .da, and .bbg files. */
+/* Find and open the .bb, .da, and .bbg files. If OBJECT_DIRECTORY is
+ not specified, these are looked for in the current directory, and
+ named from the basename of the input_file_name sans extension. If
+ OBJECT_DIRECTORY is specified and is a directory, the files are in
+ that directory, but named from the basename of the input_file_name,
+ sans extension. Otherwise OBJECT_DIRECTORY is taken to be the name
+ of the object *file*, and the data files are named from that. */
static void
open_files ()
{
- int count, objdir_count;
char *cptr;
-
- /* Determine the names of the .bb, .bbg, and .da files. Strip off the
- extension, if any, and append the new extensions. */
- count = strlen (input_file_name);
- if (object_directory)
- objdir_count = strlen (object_directory);
- else
- objdir_count = 0;
-
- da_file_name = xmalloc (count + objdir_count + 4);
- bb_file_name = xmalloc (count + objdir_count + 4);
- bbg_file_name = xmalloc (count + objdir_count + 5);
-
- if (object_directory)
+ char *name;
+ int length = strlen (input_file_name);
+ int base;
+
+ if (object_directory && object_directory[0])
{
- strcpy (da_file_name, object_directory);
- strcpy (bb_file_name, object_directory);
- strcpy (bbg_file_name, object_directory);
-
- if (object_directory[objdir_count - 1] != '/')
- {
- strcat (da_file_name, "/");
- strcat (bb_file_name, "/");
- strcat (bbg_file_name, "/");
- }
-
- cptr = strrchr (input_file_name, '/');
- if (cptr)
- {
- strcat (da_file_name, cptr + 1);
- strcat (bb_file_name, cptr + 1);
- strcat (bbg_file_name, cptr + 1);
- }
- else
- {
- strcat (da_file_name, input_file_name);
- strcat (bb_file_name, input_file_name);
- strcat (bbg_file_name, input_file_name);
- }
+ struct stat status;
+
+ length += strlen (object_directory) + 2;
+ name = xmalloc (length);
+ name[0] = 0;
+
+ base = !stat (object_directory, &status) && S_ISDIR (status.st_mode);
+ strcat (name, object_directory);
+ if (base && name[strlen (name) - 1] != '/')
+ strcat (name, "/");
}
else
{
- strcpy (da_file_name, input_file_name);
- strcpy (bb_file_name, input_file_name);
- strcpy (bbg_file_name, input_file_name);
+ name = xmalloc (length + 1);
+ name[0] = 0;
+ base = 1;
}
+
+ if (base)
+ {
+ /* Append source file name */
+ cptr = strrchr (input_file_name, '/');
+ cptr = cptr ? cptr + 1 : input_file_name;
- cptr = strrchr (bb_file_name, '.');
- if (cptr)
- strcpy (cptr, ".bb");
- else
- strcat (bb_file_name, ".bb");
-
- cptr = strrchr (da_file_name, '.');
- if (cptr)
- strcpy (cptr, ".da");
- else
- strcat (da_file_name, ".da");
-
- cptr = strrchr (bbg_file_name, '.');
+ strcat (name, cptr);
+ }
+ /* Remove the extension. */
+ cptr = strrchr (name, '.');
if (cptr)
- strcpy (cptr, ".bbg");
- else
- strcat (bbg_file_name, ".bbg");
+ *cptr = 0;
+
+ length = strlen (name);
+ da_file_name = xmalloc (length + 4);
+ bb_file_name = xmalloc (length + 4);
+ bbg_file_name = xmalloc (length + 5);
+
+ strcpy (da_file_name, name);
+ strcpy (bb_file_name, name);
+ strcpy (bbg_file_name, name);
+ strcpy (da_file_name + length, ".da");
+ strcpy (bb_file_name + length, ".bb");
+ strcpy (bbg_file_name + length, ".bbg");
bb_file = fopen (bb_file_name, "rb");
if (bb_file == NULL)
@@ -463,6 +501,21 @@ open_files ()
exit (FATAL_EXIT_CODE);
}
+ bbg_file = fopen (bbg_file_name, "rb");
+ if (bbg_file == NULL)
+ {
+ fnotice (stderr, "Could not open program flow graph file %s.\n",
+ bbg_file_name);
+ exit (FATAL_EXIT_CODE);
+ }
+
+ {
+ struct stat status;
+
+ if (!fstat (fileno (bb_file), &status))
+ bb_file_time = status.st_mtime;
+ }
+
/* If none of the functions in the file were executed, then there won't
be a .da file. Just assume that all counts are zero in this case. */
da_file = fopen (da_file_name, "rb");
@@ -472,14 +525,6 @@ open_files ()
fnotice (stderr, "Assuming that all execution counts are zero.\n");
}
- bbg_file = fopen (bbg_file_name, "rb");
- if (bbg_file == NULL)
- {
- fnotice (stderr, "Could not open program flow graph file %s.\n",
- bbg_file_name);
- exit (FATAL_EXIT_CODE);
- }
-
/* Check for empty .bbg file. This indicates that there is no executable
code in this source file. */
/* Set the EOF condition if at the end of file. */
@@ -518,7 +563,6 @@ init_arc (arcptr, source, target, bb_graph)
bb_graph[target].pred_count++;
}
-
/* Reverse the arcs on an arc list. */
static struct adj_list *
@@ -538,6 +582,130 @@ reverse_arcs (arcptr)
return prev;
}
+/* Reads profiles from the .da file and compute a hybrid profile. */
+
+static gcov_type *
+read_profile (function_name, cfg_checksum, instr_arcs)
+ char *function_name;
+ long cfg_checksum;
+ int instr_arcs;
+{
+ int i;
+ int okay = 1;
+ gcov_type *profile;
+ char *function_name_buffer;
+ int function_name_buffer_len;
+
+ profile = xmalloc (sizeof (gcov_type) * instr_arcs);
+ function_name_buffer_len = strlen (function_name) + 1;
+ function_name_buffer = xmalloc (function_name_buffer_len + 1);
+
+ for (i = 0; i < instr_arcs; i++)
+ profile[i] = 0;
+
+ if (!da_file)
+ return profile;
+
+ rewind (da_file);
+ while (1)
+ {
+ long magic, extra_bytes;
+ long func_count;
+ int i;
+
+ if (__read_long (&magic, da_file, 4) != 0)
+ break;
+
+ if (magic != -123)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (__read_long (&func_count, da_file, 4) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (__read_long (&extra_bytes, da_file, 4) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ /* skip extra data emited by __bb_exit_func. */
+ fseek (da_file, extra_bytes, SEEK_CUR);
+
+ for (i = 0; i < func_count; i++)
+ {
+ long arc_count;
+ long chksum;
+ int j;
+
+ if (__read_gcov_string
+ (function_name_buffer, function_name_buffer_len, da_file,
+ -1) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (__read_long (&chksum, da_file, 4) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (__read_long (&arc_count, da_file, 4) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (strcmp (function_name_buffer, function_name) != 0
+ || arc_count != instr_arcs || chksum != cfg_checksum)
+ {
+ /* skip */
+ if (fseek (da_file, arc_count * 8, SEEK_CUR) < 0)
+ {
+ okay = 0;
+ break;
+ }
+ }
+ else
+ {
+ gcov_type tmp;
+
+ for (j = 0; j < arc_count; j++)
+ if (__read_gcov_type (&tmp, da_file, 8) != 0)
+ {
+ okay = 0;
+ break;
+ }
+ else
+ {
+ profile[j] += tmp;
+ }
+ }
+ }
+
+ if (!okay)
+ break;
+
+ }
+
+ free (function_name_buffer);
+
+ if (!okay)
+ {
+ fprintf (stderr, ".da file corrupted!\n");
+ free (profile);
+ abort ();
+ }
+
+ return profile;
+}
/* Construct the program flow graph from the .bbg file, and read in the data
in the .da file. */
@@ -550,6 +718,29 @@ create_program_flow_graph (bptr)
int i;
struct adj_list *arcptr;
struct bb_info *bb_graph;
+ long cfg_checksum;
+ long instr_arcs = 0;
+ gcov_type *profile;
+ int profile_pos = 0;
+ char *function_name;
+ long function_name_len, tmp;
+
+ /* Read function name. */
+ __read_long (&tmp, bbg_file, 4); /* ignore -1. */
+ __read_long (&function_name_len, bbg_file, 4);
+ function_name = xmalloc (function_name_len + 1);
+ fread (function_name, 1, function_name_len + 1, bbg_file);
+
+ /* Skip padding. */
+ tmp = (function_name_len + 1) % 4;
+
+ if (tmp)
+ fseek (bbg_file, 4 - tmp, SEEK_CUR);
+
+ __read_long (&tmp, bbg_file, 4); /* ignore -1. */
+
+ /* Read the cfg checksum. */
+ __read_long (&cfg_checksum, bbg_file, 4);
/* Read the number of blocks. */
__read_long (&num_blocks, bbg_file, 4);
@@ -579,7 +770,10 @@ create_program_flow_graph (bptr)
init_arc (arcptr, src, dest, bb_graph);
__read_long (&flag_bits, bbg_file, 4);
- arcptr->on_tree = flag_bits & 0x1;
+ if (flag_bits & 0x1)
+ arcptr->on_tree++;
+ else
+ instr_arcs++;
arcptr->fake = !! (flag_bits & 0x2);
arcptr->fall_through = !! (flag_bits & 0x4);
}
@@ -601,6 +795,10 @@ create_program_flow_graph (bptr)
if (bb_graph[i].succ)
bb_graph[i].succ = reverse_arcs (bb_graph[i].succ);
+ /* Read profile from the .da file. */
+
+ profile = read_profile (function_name, cfg_checksum, instr_arcs);
+
/* For each arc not on the spanning tree, set its execution count from
the .da file. */
@@ -613,15 +811,13 @@ create_program_flow_graph (bptr)
for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next)
if (! arcptr->on_tree)
{
- gcov_type tmp_count = 0;
- if (da_file && __read_gcov_type (&tmp_count, da_file, 8))
- abort ();
-
- arcptr->arc_count = tmp_count;
+ arcptr->arc_count = profile[profile_pos++];
arcptr->count_valid = 1;
bb_graph[i].succ_count--;
bb_graph[arcptr->target].pred_count--;
}
+ free (profile);
+ free (function_name);
}
static void
@@ -755,12 +951,6 @@ read_files ()
struct stat buf;
struct bb_info_list *list_end = 0;
struct bb_info_list *b_ptr;
- long total;
-
- /* Read and ignore the first word of the .da file, which is the count of
- how many numbers follow. */
- if (da_file && __read_long (&total, da_file, 8))
- abort ();
while (! feof (bbg_file))
{
@@ -781,17 +971,6 @@ read_files ()
ungetc (getc (bbg_file), bbg_file);
}
- /* Check to make sure the .da file data is valid. */
-
- if (da_file)
- {
- if (feof (da_file))
- fnotice (stderr, ".da file contents exhausted too early\n");
- /* Should be at end of file now. */
- if (__read_long (&total, da_file, 8) == 0)
- fnotice (stderr, ".da file contents not exhausted\n");
- }
-
/* Calculate all of the basic block execution counts and branch
taken probabilities. */
@@ -876,7 +1055,7 @@ scan_for_source_files ()
}
/* There will be a zero before the first file name, in which case s_ptr
will still be uninitialized. So, only try to set the maxlineno
- field if line_num is non-zero. */
+ field if line_num is nonzero. */
else if (line_num > 0)
{
if (s_ptr->maxlineno <= line_num)
@@ -890,593 +1069,566 @@ scan_for_source_files ()
}
}
-/* For calculating coverage at the function level. */
-static int function_source_lines;
-static int function_source_lines_executed;
-static int function_branches;
-static int function_branches_executed;
-static int function_branches_taken;
-static int function_calls;
-static int function_calls_executed;
-static char *function_name;
+/* Increment totals in FUNCTION according to arc A_PTR. */
+
+static void
+accumulate_branch_counts (function, a_ptr)
+ struct coverage *function;
+ struct arcdata *a_ptr;
+{
+ if (a_ptr->call_insn)
+ {
+ function->calls++;
+ if (a_ptr->total)
+ function->calls_executed++;
+ }
+ else
+ {
+ function->branches++;
+ if (a_ptr->total)
+ function->branches_executed++;
+ if (a_ptr->hits)
+ function->branches_taken++;
+ }
+}
/* Calculate the branch taken probabilities for all arcs branches at the
end of this block. */
static void
-calculate_branch_probs (current_graph, block_num, branch_probs, last_line_num)
- struct bb_info_list *current_graph;
- int block_num;
- struct arcdata **branch_probs;
- int last_line_num;
+calculate_branch_probs (block_ptr, line_info, function)
+ struct bb_info *block_ptr;
+ struct line_info *line_info;
+ struct coverage *function;
{
gcov_type total;
struct adj_list *arcptr;
- struct arcdata *end_ptr, *a_ptr;
- total = current_graph->bb_graph[block_num].exec_count;
- for (arcptr = current_graph->bb_graph[block_num].succ; arcptr;
- arcptr = arcptr->succ_next)
+ total = block_ptr->exec_count;
+ for (arcptr = block_ptr->succ; arcptr; arcptr = arcptr->succ_next)
{
+ struct arcdata *a_ptr;
+
/* Ignore fall through arcs as they aren't really branches. */
-
if (arcptr->fall_through)
continue;
a_ptr = (struct arcdata *) xmalloc (sizeof (struct arcdata));
a_ptr->total = total;
- if (total == 0)
- a_ptr->hits = 0;
- else
- a_ptr->hits = arcptr->arc_count;
+ a_ptr->hits = total ? arcptr->arc_count : 0;
a_ptr->call_insn = arcptr->fake;
- if (output_function_summary)
+ if (function)
+ accumulate_branch_counts (function, a_ptr);
+ /* Prepend the new branch to the list. */
+ a_ptr->next = line_info->branches;
+ line_info->branches = a_ptr;
+ }
+}
+
+/* Format a HOST_WIDE_INT as either a percent ratio, or absolute
+ count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
+ If DP is zero, no decimal point is printed. Only print 100% when
+ TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
+ format TOP. Return pointer to a static string. */
+
+static char const *
+format_hwint (top, bottom, dp)
+ HOST_WIDEST_INT top, bottom;
+ int dp;
+{
+ static char buffer[20];
+
+ if (dp >= 0)
+ {
+ float ratio = bottom ? (float)top / bottom : 0;
+ int ix;
+ unsigned limit = 100;
+ unsigned percent;
+
+ for (ix = dp; ix--; )
+ limit *= 10;
+
+ percent = (unsigned) (ratio * limit + (float)0.5);
+ if (percent <= 0 && top)
+ percent = 1;
+ else if (percent >= limit && top != bottom)
+ percent = limit - 1;
+ ix = sprintf (buffer, "%.*u%%", dp + 1, percent);
+ if (dp)
{
- if (a_ptr->call_insn)
+ dp++;
+ do
{
- function_calls++;
- if (a_ptr->total != 0)
- function_calls_executed++;
- }
- else
- {
- function_branches++;
- if (a_ptr->total != 0)
- function_branches_executed++;
- if (a_ptr->hits > 0)
- function_branches_taken++;
+ buffer[ix+1] = buffer[ix];
+ ix--;
}
- }
-
- /* Append the new branch to the end of the list. */
- a_ptr->next = 0;
- if (! branch_probs[last_line_num])
- branch_probs[last_line_num] = a_ptr;
- else
- {
- end_ptr = branch_probs[last_line_num];
- while (end_ptr->next != 0)
- end_ptr = end_ptr->next;
- end_ptr->next = a_ptr;
+ while (dp--);
+ buffer[ix + 1] = '.';
}
}
+ else
+ sprintf (buffer, HOST_WIDEST_INT_PRINT_DEC, top);
+
+ return buffer;
}
+
/* Output summary info for a function. */
static void
-function_summary ()
+function_summary (function, title)
+ struct coverage *function;
+ const char *title;
{
- if (function_source_lines)
- fnotice (stdout, "%6.2f%% of %d source lines executed in function %s\n",
- (((double) function_source_lines_executed / function_source_lines)
- * 100), function_source_lines, function_name);
+ if (function->lines)
+ fnotice (stdout, "%s of %d lines executed in %s %s\n",
+ format_hwint (function->lines_executed,
+ function->lines, 2),
+ function->lines, title, function->name);
else
- fnotice (stdout, "No executable source lines in function %s\n",
- function_name);
+ fnotice (stdout, "No executable lines in %s %s\n",
+ title, function->name);
if (output_branch_probs)
{
- if (function_branches)
+ if (function->branches)
{
- fnotice (stdout, "%6.2f%% of %d branches executed in function %s\n",
- (((double) function_branches_executed / function_branches)
- * 100), function_branches, function_name);
+ fnotice (stdout, "%s of %d branches executed in %s %s\n",
+ format_hwint (function->branches_executed,
+ function->branches, 2),
+ function->branches, title, function->name);
fnotice (stdout,
- "%6.2f%% of %d branches taken at least once in function %s\n",
- (((double) function_branches_taken / function_branches)
- * 100), function_branches, function_name);
+ "%s of %d branches taken at least once in %s %s\n",
+ format_hwint (function->branches_taken,
+ function->branches, 2),
+ function->branches, title, function->name);
}
else
- fnotice (stdout, "No branches in function %s\n", function_name);
- if (function_calls)
- fnotice (stdout, "%6.2f%% of %d calls executed in function %s\n",
- (((double) function_calls_executed / function_calls)
- * 100), function_calls, function_name);
+ fnotice (stdout, "No branches in %s %s\n", title, function->name);
+ if (function->calls)
+ fnotice (stdout, "%s of %d calls executed in %s %s\n",
+ format_hwint (function->calls_executed,
+ function->calls, 2),
+ function->calls, title, function->name);
else
- fnotice (stdout, "No calls in function %s\n", function_name);
+ fnotice (stdout, "No calls in %s %s\n", title, function->name);
+ }
+}
+
+/* Generate an output file name. LONG_OUTPUT_NAMES and PRESERVE_PATHS
+ affect name generation. With preserve_paths we create a filename
+ from all path components of the source file, replacing '/' with
+ '#', without it we simply take the basename component. With
+ long_output_names we prepend the processed name of the input file
+ to each output name (except when the current source file is the
+ input file, so you don't get a double concatenation). The two
+ components are separated by '##'. Also '.' filename components are
+ removed and '..' components are renamed to '^'. */
+
+static char *
+make_gcov_file_name (src_name)
+ char *src_name;
+{
+ char *cptr;
+ char *name = xmalloc (strlen (src_name) + strlen (input_file_name) + 10);
+
+ name[0] = 0;
+ if (output_long_names && strcmp (src_name, input_file_name))
+ {
+ /* Generate the input filename part. */
+ cptr = preserve_paths ? NULL : strrchr (input_file_name, '/');
+ cptr = cptr ? cptr + 1 : input_file_name;
+ strcat (name, cptr);
+ strcat (name, "##");
+ }
+
+ /* Generate the source filename part. */
+ cptr = preserve_paths ? NULL : strrchr (src_name, '/');
+ cptr = cptr ? cptr + 1 : src_name;
+ strcat (name, cptr);
+
+ if (preserve_paths)
+ {
+ /* Convert '/' to '#', remove '/./', convert '/../' to '/^/' */
+ char *prev;
+
+ for (cptr = name; (cptr = strchr ((prev = cptr), '/'));)
+ {
+ unsigned shift = 0;
+
+ if (prev + 1 == cptr && prev[0] == '.')
+ {
+ /* Remove '.' */
+ shift = 2;
+ }
+ else if (prev + 2 == cptr && prev[0] == '.' && prev[1] == '.')
+ {
+ /* Convert '..' */
+ shift = 1;
+ prev[1] = '^';
+ }
+ else
+ *cptr++ = '#';
+ if (shift)
+ {
+ cptr = prev;
+ do
+ prev[0] = prev[shift];
+ while (*prev++);
+ }
+ }
}
+
+ /* Don't strip off the ending for compatibility with tcov, since
+ this results in confusion if there is more than one file with the
+ same basename, e.g. tmp.c and tmp.h. */
+ strcat (name, ".gcov");
+ return name;
}
-/* Calculate line execution counts, and output the data to a .tcov file. */
+/* Scan through the bb_data, and when the file name matches the
+ source file name, then for each following line number, increment
+ the line number execution count indicated by the execution count of
+ the appropriate basic block. */
static void
-output_data ()
+init_line_info (line_info, total, maxlineno)
+ struct line_info *line_info;
+ struct coverage *total;
+ long maxlineno;
{
- /* When scanning data, this is true only if the data applies to the
- current source file. */
- int this_file;
- /* An array indexed by line number which indicates how many times that line
- was executed. */
- gcov_type *line_counts;
- /* An array indexed by line number which indicates whether the line was
- present in the bb file (i.e. whether it had code associate with it).
- Lines never executed are those which both exist, and have zero execution
- counts. */
- char *line_exists;
- /* An array indexed by line number, which contains a list of branch
- probabilities, one for each branch on that line. */
- struct arcdata **branch_probs = NULL;
- struct sourcefile *s_ptr;
- char *source_file_name;
- FILE *source_file;
- struct bb_info_list *current_graph;
+ long block_num = 0; /* current block number */
+ struct bb_info *block_ptr = NULL; /* current block ptr */
+ struct coverage function;
+ struct coverage *func_ptr = NULL;
+ struct bb_info_list *current_graph = NULL; /* Graph for current function. */
+ int is_this_file = 0; /* We're scanning a block from the desired file. */
+ char *ptr = bb_data;
long count;
- char *cptr;
- long block_num;
long line_num;
- long last_line_num = 0;
- int i;
- struct arcdata *a_ptr;
- /* Buffer used for reading in lines from the source file. */
- char string[STRING_SIZE];
- /* For calculating coverage at the file level. */
- int total_source_lines;
- int total_source_lines_executed;
- int total_branches;
- int total_branches_executed;
- int total_branches_taken;
- int total_calls;
- int total_calls_executed;
-
- /* Now, for each source file, allocate an array big enough to hold a count
- for each line. Scan through the bb_data, and when the file name matches
- the current file name, then for each following line number, increment
- the line number execution count indicated by the execution count of
- the appropriate basic block. */
-
- for (s_ptr = sources; s_ptr; s_ptr = s_ptr->next)
+ struct line_info *line_ptr = 0; /* line info ptr. */
+
+ memset (&function, 0, sizeof (function));
+ if (output_function_summary)
+ func_ptr = &function;
+
+ for (count = 0; count < bb_data_size; count++)
{
- /* If this is a relative file name, and an object directory has been
- specified, then make it relative to the object directory name. */
- if (! IS_ABSOLUTE_PATHNAME (s_ptr->name)
- && object_directory != 0
- && *object_directory != '\0')
- {
- int objdir_count = strlen (object_directory);
- source_file_name = xmalloc (objdir_count + strlen (s_ptr->name) + 2);
- strcpy (source_file_name, object_directory);
- if (object_directory[objdir_count - 1] != '/')
- source_file_name[objdir_count++] = '/';
- strcpy (source_file_name + objdir_count, s_ptr->name);
- }
- else
- source_file_name = s_ptr->name;
-
- line_counts = (gcov_type *) xcalloc (sizeof (gcov_type), s_ptr->maxlineno);
- line_exists = xcalloc (1, s_ptr->maxlineno);
- if (output_branch_probs)
- branch_probs = (struct arcdata **)
- xcalloc (sizeof (struct arcdata *), s_ptr->maxlineno);
-
- /* There will be a zero at the beginning of the bb info, before the
- first list of line numbers, so must initialize block_num to 0. */
- block_num = 0;
- this_file = 0;
- current_graph = 0;
- {
- /* Pointer into the bb_data, incremented while scanning the data. */
- char *ptr = bb_data;
- for (count = 0; count < bb_data_size; count++)
- {
- long delim;
-
- __fetch_long (&line_num, ptr, 4);
- ptr += 4;
- if (line_num == -1)
- {
- /* Marks the beginning of a file name. Check to see whether
- this is the filename we are currently collecting data for. */
-
- if (strcmp (s_ptr->name, ptr))
- this_file = 0;
- else
- this_file = 1;
-
- /* Scan past the file name. */
- do {
- count++;
- __fetch_long (&delim, ptr, 4);
- ptr += 4;
- } while (delim != line_num);
- }
- else if (line_num == -2)
- {
- /* Marks the start of a new function. Advance to the next
- program flow graph. */
-
- if (! current_graph)
- current_graph = bb_graph_list;
- else
- {
- if (block_num == current_graph->num_blocks - 1)
- /* Last block falls through to exit. */
- ;
- else if (block_num == current_graph->num_blocks - 2)
- {
- if (output_branch_probs && this_file)
- calculate_branch_probs (current_graph, block_num,
- branch_probs, last_line_num);
- }
- else
- {
- fnotice (stderr,
- "didn't use all bb entries of graph, function %s\n",
- function_name);
- fnotice (stderr, "block_num = %ld, num_blocks = %d\n",
- block_num, current_graph->num_blocks);
- }
-
- current_graph = current_graph->next;
- block_num = 0;
-
- if (output_function_summary && this_file)
- function_summary ();
- }
-
- if (output_function_summary)
- {
- function_source_lines = 0;
- function_source_lines_executed = 0;
- function_branches = 0;
- function_branches_executed = 0;
- function_branches_taken = 0;
- function_calls = 0;
- function_calls_executed = 0;
- }
-
- /* Save the function name for later use. */
- function_name = ptr;
-
- /* Scan past the file name. */
- do {
- count++;
- __fetch_long (&delim, ptr, 4);
- ptr += 4;
- } while (delim != line_num);
- }
- else if (line_num == 0)
- {
- /* Marks the end of a block. */
-
- if (block_num >= current_graph->num_blocks)
- {
- fnotice (stderr, "ERROR: too many basic blocks in .bb file %s\n",
- function_name);
- abort ();
- }
-
- if (output_branch_probs && this_file)
- calculate_branch_probs (current_graph, block_num,
- branch_probs, last_line_num);
-
- block_num++;
- }
- else if (this_file)
- {
- if (output_function_summary)
- {
- if (line_exists[line_num] == 0)
- function_source_lines++;
- if (line_counts[line_num] == 0
- && current_graph->bb_graph[block_num].exec_count != 0)
- function_source_lines_executed++;
- }
-
- /* Accumulate execution data for this line number. */
-
- line_counts[line_num]
- += current_graph->bb_graph[block_num].exec_count;
- line_exists[line_num] = 1;
- last_line_num = line_num;
- }
- }
- }
-
- if (output_function_summary && this_file)
- function_summary ();
-
- /* Calculate summary test coverage statistics. */
-
- total_source_lines = 0;
- total_source_lines_executed = 0;
- total_branches = 0;
- total_branches_executed = 0;
- total_branches_taken = 0;
- total_calls = 0;
- total_calls_executed = 0;
-
- for (count = 1; count < s_ptr->maxlineno; count++)
+ __fetch_long (&line_num, ptr, 4);
+ ptr += 4;
+ if (line_num < 0)
{
- if (line_exists[count])
+ long delim;
+
+ if (line_num == -1)
{
- total_source_lines++;
- if (line_counts[count])
- total_source_lines_executed++;
+ /* Marks the beginning of a file name. Check to see
+ whether this is the filename we are currently
+ collecting data for. */
+ is_this_file = !strcmp (total->name, ptr);
}
- if (output_branch_probs)
+ else if (line_num == -2)
{
- for (a_ptr = branch_probs[count]; a_ptr; a_ptr = a_ptr->next)
+ /* Marks the start of a new function. Advance to the
+ next program flow graph. */
+ if (!current_graph)
+ current_graph = bb_graph_list;
+ else
{
- if (a_ptr->call_insn)
+ if (block_num == current_graph->num_blocks - 1)
+ /* Last block falls through to exit. */
+ ;
+ else if (block_num == current_graph->num_blocks - 2)
{
- total_calls++;
- if (a_ptr->total != 0)
- total_calls_executed++;
+ if (output_branch_probs && is_this_file)
+ calculate_branch_probs (block_ptr, line_ptr, func_ptr);
}
else
{
- total_branches++;
- if (a_ptr->total != 0)
- total_branches_executed++;
- if (a_ptr->hits > 0)
- total_branches_taken++;
+ fnotice (stderr,
+ "didn't use all bb entries of graph, function %s\n",
+ function.name);
+ fnotice (stderr, "block_num = %ld, num_blocks = %d\n",
+ block_num, current_graph->num_blocks);
}
+ if (func_ptr && is_this_file)
+ function_summary (func_ptr, "function");
+ current_graph = current_graph->next;
}
+ block_num = 0;
+ block_ptr = current_graph->bb_graph;
+ memset (&function, 0, sizeof (function));
+ function.name = ptr;
+ }
+ else
+ {
+ fnotice (stderr, "ERROR: unexpected line number %ld\n", line_num);
+ abort ();
}
- }
-
- if (total_source_lines)
- fnotice (stdout,
- "%6.2f%% of %d source lines executed in file %s\n",
- (((double) total_source_lines_executed / total_source_lines)
- * 100), total_source_lines, source_file_name);
- else
- fnotice (stdout, "No executable source lines in file %s\n",
- source_file_name);
- if (output_branch_probs)
- {
- if (total_branches)
+ /* Scan past the string. */
+ for (delim = 0; delim != line_num; count++)
{
- fnotice (stdout, "%6.2f%% of %d branches executed in file %s\n",
- (((double) total_branches_executed / total_branches)
- * 100), total_branches, source_file_name);
- fnotice (stdout,
- "%6.2f%% of %d branches taken at least once in file %s\n",
- (((double) total_branches_taken / total_branches)
- * 100), total_branches, source_file_name);
+ __fetch_long (&delim, ptr, 4);
+ ptr += 4;
}
- else
- fnotice (stdout, "No branches in file %s\n", source_file_name);
- if (total_calls)
- fnotice (stdout, "%6.2f%% of %d calls executed in file %s\n",
- (((double) total_calls_executed / total_calls)
- * 100), total_calls, source_file_name);
- else
- fnotice (stdout, "No calls in file %s\n", source_file_name);
}
-
- if (output_gcov_file)
+ else if (!line_num)
{
- /* Now the statistics are ready. Read in the source file one line
- at a time, and output that line to the gcov file preceded by
- its execution count if non zero. */
-
- source_file = fopen (source_file_name, "r");
- if (source_file == NULL)
+ /* Marks the end of a block. */
+ if (block_num >= current_graph->num_blocks)
{
- fnotice (stderr, "Could not open source file %s.\n",
- source_file_name);
- free (line_counts);
- free (line_exists);
- continue;
+ fnotice (stderr, "ERROR: too many basic blocks in function %s\n",
+ function.name);
+ abort ();
}
-
- count = strlen (source_file_name);
- cptr = strrchr (s_ptr->name, '/');
- if (cptr)
- cptr = cptr + 1;
- else
- cptr = s_ptr->name;
- if (output_long_names && strcmp (cptr, input_file_name))
+
+ if (output_branch_probs && is_this_file)
+ calculate_branch_probs (block_ptr, line_ptr, func_ptr);
+
+ block_num++;
+ block_ptr++;
+ }
+ else if (is_this_file)
+ {
+ if (line_num >= maxlineno)
{
- gcov_file_name = xmalloc (count + 7 + strlen (input_file_name));
-
- cptr = strrchr (input_file_name, '/');
- if (cptr)
- strcpy (gcov_file_name, cptr + 1);
- else
- strcpy (gcov_file_name, input_file_name);
-
- strcat (gcov_file_name, ".");
-
- cptr = strrchr (source_file_name, '/');
- if (cptr)
- strcat (gcov_file_name, cptr + 1);
- else
- strcat (gcov_file_name, source_file_name);
+ fnotice (stderr, "ERROR: out of range line number in function %s\n",
+ function.name);
+ abort ();
}
- else
+
+ line_ptr = &line_info[line_num];
+ if (func_ptr)
{
- gcov_file_name = xmalloc (count + 6);
- cptr = strrchr (source_file_name, '/');
- if (cptr)
- strcpy (gcov_file_name, cptr + 1);
- else
- strcpy (gcov_file_name, source_file_name);
+ if (!line_ptr->exists)
+ func_ptr->lines++;
+ if (!line_ptr->count && block_ptr->exec_count)
+ func_ptr->lines_executed++;
}
+
+ /* Accumulate execution data for this line number. */
+ line_ptr->count += block_ptr->exec_count;
+ line_ptr->exists = 1;
+ }
+ }
+
+ if (func_ptr && is_this_file)
+ function_summary (func_ptr, "function");
+
+ /* Calculate summary test coverage statistics. */
+ for (line_num = 1, line_ptr = &line_info[line_num];
+ line_num < maxlineno; line_num++, line_ptr++)
+ {
+ struct arcdata *a_ptr, *prev, *next;
+
+ if (line_ptr->exists)
+ {
+ total->lines++;
+ if (line_ptr->count)
+ total->lines_executed++;
+ }
- /* Don't strip off the ending for compatibility with tcov, since
- this results in confusion if there is more than one file with
- the same basename, e.g. tmp.c and tmp.h. */
- strcat (gcov_file_name, ".gcov");
+ /* Total and reverse the branch information. */
+ for (a_ptr = line_ptr->branches, prev = NULL; a_ptr; a_ptr = next)
+ {
+ next = a_ptr->next;
+ a_ptr->next = prev;
+ prev = a_ptr;
- gcov_file = fopen (gcov_file_name, "w");
+ accumulate_branch_counts (total, a_ptr);
+ }
+ line_ptr->branches = prev;
+ }
+}
- if (gcov_file == NULL)
- {
- fnotice (stderr, "Could not open output file %s.\n",
- gcov_file_name);
- fclose (source_file);
- free (line_counts);
- free (line_exists);
- continue;
- }
+/* Read in the source file one line at a time, and output that line to
+ the gcov file preceded by its execution count and other
+ information. */
- fnotice (stdout, "Creating %s.\n", gcov_file_name);
+static void
+output_line_info (gcov_file, line_info, total, maxlineno)
+ FILE *gcov_file;
+ const struct line_info *line_info;
+ const struct coverage *total;
+ long maxlineno;
+{
+ FILE *source_file;
+ long line_num; /* current line number */
+ const struct line_info *line_ptr; /* current line info ptr. */
+ char string[STRING_SIZE]; /* line buffer. */
+ char const *retval = ""; /* status of source file reading. */
+
+ fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, total->name);
+ fprintf (gcov_file, "%9s:%5d:Object:%s\n", "-", 0, bb_file_name);
+
+ source_file = fopen (total->name, "r");
+ if (!source_file)
+ {
+ fnotice (stderr, "Could not open source file %s.\n", total->name);
+ retval = NULL;
+ }
+ else
+ {
+ struct stat status;
+
+ if (!fstat (fileno (source_file), &status)
+ && status.st_mtime > bb_file_time)
+ {
+ fnotice (stderr, "Warning: source file %s is newer than %s\n",
+ total->name, bb_file_name);
+ fprintf (gcov_file, "%9s:%5d:Source is newer than compiler output\n",
+ "-", 0);
+ }
+ }
- for (count = 1; count < s_ptr->maxlineno; count++)
+ for (line_num = 1, line_ptr = &line_info[line_num];
+ line_num < maxlineno; line_num++, line_ptr++)
+ {
+ /* For lines which don't exist in the .bb file, print '-' before
+ the source line. For lines which exist but were never
+ executed, print '#####' before the source line. Otherwise,
+ print the execution count before the source line. There are
+ 16 spaces of indentation added before the source line so that
+ tabs won't be messed up. */
+ fprintf (gcov_file, "%9s:%5ld:",
+ !line_ptr->exists ? "-"
+ : !line_ptr->count ? "#####"
+ : format_hwint (line_ptr->count, 0, -1), line_num);
+
+ if (retval)
+ {
+ /* Copy source line. */
+ do
{
- char *retval;
- int len;
-
retval = fgets (string, STRING_SIZE, source_file);
-
- /* For lines which don't exist in the .bb file, print nothing
- before the source line. For lines which exist but were never
- executed, print ###### before the source line. Otherwise,
- print the execution count before the source line. */
- /* There are 16 spaces of indentation added before the source
- line so that tabs won't be messed up. */
- if (line_exists[count])
+ if (!retval)
{
- if (line_counts[count])
- {
- char c[20];
- sprintf (c, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT)line_counts[count]);
- fprintf (gcov_file, "%12s %s", c,
- string);
- }
- else
- fprintf (gcov_file, " ###### %s", string);
+ fnotice (stderr,
+ "Unexpected EOF while reading source file %s.\n",
+ total->name);
+ break;
}
- else
- fprintf (gcov_file, "\t\t%s", string);
-
- /* In case the source file line is larger than our buffer, keep
- reading and outputting lines until we get a newline. */
- len = strlen (string);
- while ((len == 0 || string[strlen (string) - 1] != '\n')
- && retval != NULL)
+ fputs (retval, gcov_file);
+ }
+ while (!retval[0] || retval[strlen (retval) - 1] != '\n');
+ }
+ if (!retval)
+ fputs ("??\n", gcov_file);
+
+ if (output_branch_probs)
+ {
+ int i;
+ struct arcdata *a_ptr;
+
+ for (i = 0, a_ptr = line_ptr->branches; a_ptr;
+ a_ptr = a_ptr->next, i++)
+ {
+ if (a_ptr->call_insn)
{
- retval = fgets (string, STRING_SIZE, source_file);
- fputs (string, gcov_file);
+ if (a_ptr->total == 0)
+ fnotice (gcov_file, "call %2d never executed\n", i);
+ else
+ fnotice
+ (gcov_file, "call %2d returns %s\n", i,
+ format_hwint (a_ptr->total - a_ptr->hits,
+ a_ptr->total,
+ -output_branch_counts));
}
-
- if (output_branch_probs)
- {
- for (i = 0, a_ptr = branch_probs[count]; a_ptr;
- a_ptr = a_ptr->next, i++)
- {
- if (a_ptr->call_insn)
- {
- if (a_ptr->total == 0)
- fnotice (gcov_file, "call %d never executed\n", i);
- else
- {
- if (output_branch_counts)
- {
- char c[20];
- sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
- a_ptr->total - a_ptr->hits);
- fnotice (gcov_file,
- "call %d returns = %s\n", i, c);
- }
- else
- {
- char c[20];
- sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
- 100 - ((a_ptr->hits * 100)
- + (a_ptr->total >> 1))
- / a_ptr->total);
- fnotice (gcov_file,
- "call %d returns = %s%%\n", i, c);
- }
- }
- }
- else
- {
- if (a_ptr->total == 0)
- fnotice (gcov_file, "branch %d never executed\n",
- i);
- else
- {
- if (output_branch_counts)
- {
- char c[20];
- sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
- a_ptr->hits);
- fnotice (gcov_file,
- "branch %d taken = %s\n", i, c);
- }
- else
- {
- char c[20];
- sprintf (c, HOST_WIDEST_INT_PRINT_DEC,
- ((a_ptr->hits * 100)
- + (a_ptr->total >> 1))
- / a_ptr->total);
- fnotice (gcov_file,
- "branch %d taken = %s%%\n", i, c);
- }
- }
- }
- }
- }
-
- /* Gracefully handle errors while reading the source file. */
- if (retval == NULL)
+ else
{
- fnotice (stderr,
- "Unexpected EOF while reading source file %s.\n",
- source_file_name);
- break;
+ if (a_ptr->total == 0)
+ fnotice (gcov_file, "branch %2d never executed\n", i);
+ else
+ fnotice
+ (gcov_file, "branch %2d taken %s\n", i,
+ format_hwint (a_ptr->hits, a_ptr->total,
+ -output_branch_counts));
}
}
+ }
+ }
+
+ /* Handle all remaining source lines. There may be lines after the
+ last line of code. */
+ if (retval)
+ {
+ for (; (retval = fgets (string, STRING_SIZE, source_file)); line_num++)
+ {
+ fprintf (gcov_file, "%9s:%5ld:%s", "-", line_num, retval);
+
+ while (!retval[0] || retval[strlen (retval) - 1] != '\n')
+ {
+ retval = fgets (string, STRING_SIZE, source_file);
+ if (!retval)
+ break;
+ fputs (retval, gcov_file);
+ }
+ }
+ }
+
+ if (source_file)
+ fclose (source_file);
+}
- /* Handle all remaining source lines. There may be lines
- after the last line of code. */
-
- {
- char *retval = fgets (string, STRING_SIZE, source_file);
- while (retval != NULL)
- {
- int len;
-
- fprintf (gcov_file, "\t\t%s", string);
-
- /* In case the source file line is larger than our buffer, keep
- reading and outputting lines until we get a newline. */
- len = strlen (string);
- while ((len == 0 || string[strlen (string) - 1] != '\n')
- && retval != NULL)
- {
- retval = fgets (string, STRING_SIZE, source_file);
- fputs (string, gcov_file);
- }
-
- retval = fgets (string, STRING_SIZE, source_file);
- }
- }
+/* Calculate line execution counts, and output a .gcov file for source
+ file S_PTR. Allocate an array big enough to hold a count for each
+ line. Scan through the bb_data, and when the file name matches the
+ current file name, then for each following line number, increment
+ the line number execution count indicated by the execution count of
+ the appropriate basic block. */
- fclose (source_file);
+static void
+output_data (s_ptr)
+ struct sourcefile *s_ptr;
+{
+ struct line_info *line_info /* line info data */
+ = (struct line_info *) xcalloc (s_ptr->maxlineno,
+ sizeof (struct line_info));
+ long line_num;
+ struct coverage total;
+
+ memset (&total, 0, sizeof (total));
+ total.name = s_ptr->name;
+
+ init_line_info (line_info, &total, s_ptr->maxlineno);
+ function_summary (&total, "file");
+
+ if (output_gcov_file)
+ {
+ /* Now the statistics are ready. Read in the source file one
+ line at a time, and output that line to the gcov file
+ preceded by its execution information. */
+
+ char *gcov_file_name = make_gcov_file_name (total.name);
+ FILE *gcov_file = fopen (gcov_file_name, "w");
+
+ if (gcov_file)
+ {
+ fnotice (stdout, "Creating %s.\n", gcov_file_name);
+ output_line_info (gcov_file, line_info, &total, s_ptr->maxlineno);
+ if (ferror (gcov_file))
+ fnotice (stderr, "Error writing output file %s.\n",
+ gcov_file_name);
fclose (gcov_file);
}
+ else
+ fnotice (stderr, "Could not open output file %s.\n", gcov_file_name);
+ free (gcov_file_name);
+ }
- free (line_counts);
- free (line_exists);
+ /* Free data. */
+ for (line_num = 1; line_num != s_ptr->maxlineno; line_num++)
+ {
+ struct arcdata *branch, *next;
+
+ for (branch = line_info[line_num].branches; branch; branch = next)
+ {
+ next = branch->next;
+ free (branch);
+ }
}
+ free (line_info);
}
diff --git a/contrib/gcc/gcse.c b/contrib/gcc/gcse.c
index 8c6b87f..8c4e71b 100644
--- a/contrib/gcc/gcse.c
+++ b/contrib/gcc/gcse.c
@@ -158,14 +158,13 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "basic-block.h"
#include "output.h"
#include "function.h"
-#include "expr.h"
+#include "expr.h"
#include "except.h"
#include "ggc.h"
#include "params.h"
+#include "cselib.h"
#include "obstack.h"
-#define obstack_chunk_alloc gmalloc
-#define obstack_chunk_free free
/* Propagate flow information through back edges and thus enable PRE's
moving loop invariant calculations out of loops.
@@ -178,7 +177,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
be done by loop.c, which has more heuristics for when to move invariants
out of loops. At some point we might need to move some of those
heuristics into gcse.c. */
-#define FOLLOW_BACK_EDGES 1
/* We support GCSE via Partial Redundancy Elimination. PRE optimizations
are a superset of those done by GCSE.
@@ -299,12 +297,12 @@ static FILE *debug_stderr;
/* An obstack for our working variables. */
static struct obstack gcse_obstack;
-/* Non-zero for each mode that supports (set (reg) (reg)).
+/* Nonzero for each mode that supports (set (reg) (reg)).
This is trivially true for integer and floating point values.
It may or may not be true for condition codes. */
static char can_copy_p[(int) NUM_MACHINE_MODES];
-/* Non-zero if can_copy_p has been initialized. */
+/* Nonzero if can_copy_p has been initialized. */
static int can_copy_init_p;
struct reg_use {rtx reg_rtx; };
@@ -346,9 +344,9 @@ struct occr
struct occr *next;
/* The insn that computes the expression. */
rtx insn;
- /* Non-zero if this [anticipatable] occurrence has been deleted. */
+ /* Nonzero if this [anticipatable] occurrence has been deleted. */
char deleted_p;
- /* Non-zero if this [available] occurrence has been copied to
+ /* Nonzero if this [available] occurrence has been copied to
reaching_reg. */
/* ??? This is mutually exclusive with deleted_p, so they could share
the same byte. */
@@ -364,19 +362,27 @@ struct occr
[one could build a mapping table without holes afterwards though].
Someday I'll perform the computation and figure it out. */
-/* Total size of the expression hash table, in elements. */
-static unsigned int expr_hash_table_size;
+struct hash_table
+{
+ /* The table itself.
+ This is an array of `expr_hash_table_size' elements. */
+ struct expr **table;
+
+ /* Size of the hash table, in elements. */
+ unsigned int size;
-/* The table itself.
- This is an array of `expr_hash_table_size' elements. */
-static struct expr **expr_hash_table;
+ /* Number of hash table elements. */
+ unsigned int n_elems;
+
+ /* Whether the table is expression of copy propagation one. */
+ int set_p;
+};
-/* Total size of the copy propagation hash table, in elements. */
-static unsigned int set_hash_table_size;
+/* Expression hash table. */
+static struct hash_table expr_hash_table;
-/* The table itself.
- This is an array of `set_hash_table_size' elements. */
-static struct expr **set_hash_table;
+/* Copy propagation hash table. */
+static struct hash_table set_hash_table;
/* Mapping of uids to cuids.
Only real insns get cuids. */
@@ -406,12 +412,6 @@ static rtx *cuid_insn;
This is named with "gcse" to not collide with global of same name. */
static unsigned int max_gcse_regno;
-/* Maximum number of cse-able expressions found. */
-static int n_exprs;
-
-/* Maximum number of assignments for copy propagation found. */
-static int n_sets;
-
/* Table of registers that are modified.
For each register, each element is a list of places where the pseudo-reg
@@ -454,13 +454,13 @@ static int reg_set_table_size;
#define REG_SET_TABLE_SLOP 100
/* This is a list of expressions which are MEMs and will be used by load
- or store motion.
+ or store motion.
Load motion tracks MEMs which aren't killed by
anything except itself. (ie, loads and stores to a single location).
- We can then allow movement of these MEM refs with a little special
+ We can then allow movement of these MEM refs with a little special
allowance. (all stores copy the same value to the reaching reg used
for the loads). This means all values used to store into memory must have
- no side effects so we can re-issue the setter value.
+ no side effects so we can re-issue the setter value.
Store Motion uses this structure as an expression table to track stores
which look interesting, and might be moveable towards the exit block. */
@@ -541,7 +541,7 @@ static sbitmap *ae_kill, *ae_gen, *ae_in, *ae_out;
struct null_pointer_info
{
/* The basic block being processed. */
- int current_block;
+ basic_block current_block;
/* The first register to be handled in this pass. */
unsigned int min_reg;
/* One greater than the last register to be handled in this pass. */
@@ -562,17 +562,17 @@ static int get_bitmap_width PARAMS ((int, int, int));
static void record_one_set PARAMS ((int, rtx));
static void record_set_info PARAMS ((rtx, rtx, void *));
static void compute_sets PARAMS ((rtx));
-static void hash_scan_insn PARAMS ((rtx, int, int));
-static void hash_scan_set PARAMS ((rtx, rtx, int));
-static void hash_scan_clobber PARAMS ((rtx, rtx));
-static void hash_scan_call PARAMS ((rtx, rtx));
+static void hash_scan_insn PARAMS ((rtx, struct hash_table *, int));
+static void hash_scan_set PARAMS ((rtx, rtx, struct hash_table *));
+static void hash_scan_clobber PARAMS ((rtx, rtx, struct hash_table *));
+static void hash_scan_call PARAMS ((rtx, rtx, struct hash_table *));
static int want_to_gcse_p PARAMS ((rtx));
static int oprs_unchanged_p PARAMS ((rtx, rtx, int));
static int oprs_anticipatable_p PARAMS ((rtx, rtx));
static int oprs_available_p PARAMS ((rtx, rtx));
static void insert_expr_in_table PARAMS ((rtx, enum machine_mode, rtx,
- int, int));
-static void insert_set_in_table PARAMS ((rtx, rtx));
+ int, int, struct hash_table *));
+static void insert_set_in_table PARAMS ((rtx, rtx, struct hash_table *));
static unsigned int hash_expr PARAMS ((rtx, enum machine_mode, int *, int));
static unsigned int hash_expr_1 PARAMS ((rtx, enum machine_mode, int *));
static unsigned int hash_string_1 PARAMS ((const char *));
@@ -581,17 +581,14 @@ static int expr_equiv_p PARAMS ((rtx, rtx));
static void record_last_reg_set_info PARAMS ((rtx, int));
static void record_last_mem_set_info PARAMS ((rtx));
static void record_last_set_info PARAMS ((rtx, rtx, void *));
-static void compute_hash_table PARAMS ((int));
-static void alloc_set_hash_table PARAMS ((int));
-static void free_set_hash_table PARAMS ((void));
-static void compute_set_hash_table PARAMS ((void));
-static void alloc_expr_hash_table PARAMS ((unsigned int));
-static void free_expr_hash_table PARAMS ((void));
-static void compute_expr_hash_table PARAMS ((void));
-static void dump_hash_table PARAMS ((FILE *, const char *, struct expr **,
- int, int));
-static struct expr *lookup_expr PARAMS ((rtx));
-static struct expr *lookup_set PARAMS ((unsigned int, rtx));
+static void compute_hash_table PARAMS ((struct hash_table *));
+static void alloc_hash_table PARAMS ((int, struct hash_table *, int));
+static void free_hash_table PARAMS ((struct hash_table *));
+static void compute_hash_table_work PARAMS ((struct hash_table *));
+static void dump_hash_table PARAMS ((FILE *, const char *,
+ struct hash_table *));
+static struct expr *lookup_expr PARAMS ((rtx, struct hash_table *));
+static struct expr *lookup_set PARAMS ((unsigned int, rtx, struct hash_table *));
static struct expr *next_set PARAMS ((unsigned int, struct expr *));
static void reset_opr_set_tables PARAMS ((void));
static int oprs_not_set_p PARAMS ((rtx, rtx));
@@ -604,25 +601,27 @@ static void free_cprop_mem PARAMS ((void));
static void compute_transp PARAMS ((rtx, int, sbitmap *, int));
static void compute_transpout PARAMS ((void));
static void compute_local_properties PARAMS ((sbitmap *, sbitmap *, sbitmap *,
- int));
+ struct hash_table *));
static void compute_cprop_data PARAMS ((void));
static void find_used_regs PARAMS ((rtx *, void *));
static int try_replace_reg PARAMS ((rtx, rtx, rtx));
static struct expr *find_avail_set PARAMS ((int, rtx));
-static int cprop_jump PARAMS ((basic_block, rtx, rtx, rtx));
-#ifdef HAVE_cc0
-static int cprop_cc0_jump PARAMS ((basic_block, rtx, struct reg_use *, rtx));
-#endif
+static int cprop_jump PARAMS ((basic_block, rtx, rtx, rtx, rtx));
static void mems_conflict_for_gcse_p PARAMS ((rtx, rtx, void *));
static int load_killed_in_block_p PARAMS ((basic_block, int, rtx, int));
static void canon_list_insert PARAMS ((rtx, rtx, void *));
-static int cprop_insn PARAMS ((basic_block, rtx, int));
+static int cprop_insn PARAMS ((rtx, int));
static int cprop PARAMS ((int));
static int one_cprop_pass PARAMS ((int, int));
+static bool constprop_register PARAMS ((rtx, rtx, rtx, int));
+static struct expr *find_bypass_set PARAMS ((int, int));
+static bool reg_killed_on_edge PARAMS ((rtx, edge));
+static int bypass_block PARAMS ((basic_block, rtx, rtx));
+static int bypass_conditional_jumps PARAMS ((void));
static void alloc_pre_mem PARAMS ((int, int));
static void free_pre_mem PARAMS ((void));
static void compute_pre_data PARAMS ((void));
-static int pre_expr_reaches_here_p PARAMS ((basic_block, struct expr *,
+static int pre_expr_reaches_here_p PARAMS ((basic_block, struct expr *,
basic_block));
static void insert_insn_end_bb PARAMS ((struct expr *, basic_block, int));
static void pre_insert_copy_insn PARAMS ((struct expr *, rtx));
@@ -635,7 +634,7 @@ static void alloc_code_hoist_mem PARAMS ((int, int));
static void free_code_hoist_mem PARAMS ((void));
static void compute_code_hoist_vbeinout PARAMS ((void));
static void compute_code_hoist_data PARAMS ((void));
-static int hoist_expr_reaches_here_p PARAMS ((basic_block, int, basic_block,
+static int hoist_expr_reaches_here_p PARAMS ((basic_block, int, basic_block,
char *));
static void hoist_code PARAMS ((void));
static int one_code_hoisting_pass PARAMS ((void));
@@ -646,9 +645,9 @@ static void compute_kill_rd PARAMS ((void));
static void compute_rd PARAMS ((void));
static void alloc_avail_expr_mem PARAMS ((int, int));
static void free_avail_expr_mem PARAMS ((void));
-static void compute_ae_gen PARAMS ((void));
+static void compute_ae_gen PARAMS ((struct hash_table *));
static int expr_killed_p PARAMS ((rtx, basic_block));
-static void compute_ae_kill PARAMS ((sbitmap *, sbitmap *));
+static void compute_ae_kill PARAMS ((sbitmap *, sbitmap *, struct hash_table *));
static int expr_reaches_here_p PARAMS ((struct occr *, struct expr *,
basic_block, int));
static rtx computing_insn PARAMS ((struct expr *, rtx));
@@ -658,7 +657,7 @@ static int handle_avail_expr PARAMS ((rtx, struct expr *));
static int classic_gcse PARAMS ((void));
static int one_classic_gcse_pass PARAMS ((int));
static void invalidate_nonnull_info PARAMS ((rtx, rtx, void *));
-static void delete_null_pointer_checks_1 PARAMS ((unsigned int *,
+static int delete_null_pointer_checks_1 PARAMS ((unsigned int *,
sbitmap *, sbitmap *,
struct null_pointer_info *));
static rtx process_insert_insn PARAMS ((struct expr *));
@@ -677,7 +676,7 @@ static inline struct ls_expr * first_ls_expr PARAMS ((void));
static inline struct ls_expr * next_ls_expr PARAMS ((struct ls_expr *));
static int simple_mem PARAMS ((rtx));
static void invalidate_any_buried_refs PARAMS ((rtx));
-static void compute_ld_motion_mems PARAMS ((void));
+static void compute_ld_motion_mems PARAMS ((void));
static void trim_ld_motion_mems PARAMS ((void));
static void update_ld_motion_stores PARAMS ((struct expr *));
static void reg_set_info PARAMS ((rtx, rtx, void *));
@@ -693,13 +692,18 @@ static void build_store_vectors PARAMS ((void));
static void insert_insn_start_bb PARAMS ((rtx, basic_block));
static int insert_store PARAMS ((struct ls_expr *, edge));
static void replace_store_insn PARAMS ((rtx, rtx, basic_block));
-static void delete_store PARAMS ((struct ls_expr *,
+static void delete_store PARAMS ((struct ls_expr *,
basic_block));
static void free_store_memory PARAMS ((void));
static void store_motion PARAMS ((void));
static void free_insn_expr_list_list PARAMS ((rtx *));
static void clear_modify_mem_tables PARAMS ((void));
static void free_modify_mem_tables PARAMS ((void));
+static rtx gcse_emit_move_after PARAMS ((rtx, rtx, rtx));
+static void local_cprop_find_used_regs PARAMS ((rtx *, void *));
+static bool do_local_cprop PARAMS ((rtx, rtx, int, rtx*));
+static bool adjust_libcall_notes PARAMS ((rtx, rtx, rtx, rtx*));
+static void local_cprop_pass PARAMS ((int));
/* Entry point for global common subexpression elimination.
F is the first instruction in the function. */
@@ -725,7 +729,7 @@ gcse_main (f, file)
setjmp, so just punt to be safe. */
if (current_function_calls_setjmp)
return 0;
-
+
/* Assume that we do not need to run jump optimizations after gcse. */
run_jump_opt_after_gcse = 0;
@@ -763,7 +767,7 @@ gcse_main (f, file)
/* If allocating memory for the cprop bitmap would take up too much
storage it's better just to disable the optimization. */
- if ((n_basic_blocks
+ if ((n_basic_blocks
* SBITMAP_SET_SIZE (max_gcse_regno)
* sizeof (SBITMAP_ELT_TYPE)) > MAX_GCSE_MEMORY)
{
@@ -825,7 +829,7 @@ gcse_main (f, file)
if (optimize_size)
changed |= one_classic_gcse_pass (pass + 1);
else
- {
+ {
changed |= one_pre_gcse_pass (pass + 1);
/* We may have just created new basic blocks. Release and
recompute various things which are sized on the number of
@@ -834,11 +838,11 @@ gcse_main (f, file)
{
free_modify_mem_tables ();
modify_mem_list
- = (rtx *) gmalloc (n_basic_blocks * sizeof (rtx));
+ = (rtx *) gmalloc (last_basic_block * sizeof (rtx));
canon_modify_mem_list
- = (rtx *) gmalloc (n_basic_blocks * sizeof (rtx));
- memset ((char *) modify_mem_list, 0, n_basic_blocks * sizeof (rtx));
- memset ((char *) canon_modify_mem_list, 0, n_basic_blocks * sizeof (rtx));
+ = (rtx *) gmalloc (last_basic_block * sizeof (rtx));
+ memset ((char *) modify_mem_list, 0, last_basic_block * sizeof (rtx));
+ memset ((char *) canon_modify_mem_list, 0, last_basic_block * sizeof (rtx));
orig_bb_count = n_basic_blocks;
}
free_reg_set_mem ();
@@ -862,7 +866,7 @@ gcse_main (f, file)
for space, we use a classic gcse algorithm instead of partial
redundancy algorithms). */
if (optimize_size)
- {
+ {
max_gcse_regno = max_reg_num ();
alloc_gcse_mem (f);
changed |= one_code_hoisting_pass ();
@@ -870,7 +874,7 @@ gcse_main (f, file)
if (max_pass_bytes < bytes_used)
max_pass_bytes = bytes_used;
- }
+ }
if (file)
{
@@ -966,14 +970,13 @@ grealloc (ptr, size)
return xrealloc (ptr, size);
}
-/* Cover function to obstack_alloc.
- We don't need to record the bytes allocated here since
- obstack_chunk_alloc is set to gmalloc. */
+/* Cover function to obstack_alloc. */
static char *
gcse_alloc (size)
unsigned long size;
{
+ bytes_used += size;
return (char *) obstack_alloc (&gcse_obstack, size);
}
@@ -1019,14 +1022,14 @@ alloc_gcse_mem (f)
reg_set_bitmap = BITMAP_XMALLOC ();
/* Allocate vars to track sets of regs, memory per block. */
- reg_set_in_block = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks,
+ reg_set_in_block = (sbitmap *) sbitmap_vector_alloc (last_basic_block,
max_gcse_regno);
/* Allocate array to keep a list of insns which modify memory in each
basic block. */
- modify_mem_list = (rtx *) gmalloc (n_basic_blocks * sizeof (rtx));
- canon_modify_mem_list = (rtx *) gmalloc (n_basic_blocks * sizeof (rtx));
- memset ((char *) modify_mem_list, 0, n_basic_blocks * sizeof (rtx));
- memset ((char *) canon_modify_mem_list, 0, n_basic_blocks * sizeof (rtx));
+ modify_mem_list = (rtx *) gmalloc (last_basic_block * sizeof (rtx));
+ canon_modify_mem_list = (rtx *) gmalloc (last_basic_block * sizeof (rtx));
+ memset ((char *) modify_mem_list, 0, last_basic_block * sizeof (rtx));
+ memset ((char *) canon_modify_mem_list, 0, last_basic_block * sizeof (rtx));
modify_mem_list_set = BITMAP_XMALLOC ();
canon_modify_mem_list_set = BITMAP_XMALLOC ();
}
@@ -1113,46 +1116,38 @@ get_bitmap_width (n, x, y)
properties. If NULL, then it is not necessary to compute or record that
particular property.
- SETP controls which hash table to look at. If zero, this routine looks at
- the expr hash table; if nonzero this routine looks at the set hash table.
- Additionally, TRANSP is computed as ~TRANSP, since this is really cprop's
+ TABLE controls which hash table to look at. If it is set hash table,
+ additionally, TRANSP is computed as ~TRANSP, since this is really cprop's
ABSALTERED. */
-
+
static void
-compute_local_properties (transp, comp, antloc, setp)
+compute_local_properties (transp, comp, antloc, table)
sbitmap *transp;
sbitmap *comp;
sbitmap *antloc;
- int setp;
+ struct hash_table *table;
{
- unsigned int i, hash_table_size;
- struct expr **hash_table;
-
+ unsigned int i;
+
/* Initialize any bitmaps that were passed in. */
if (transp)
{
- if (setp)
- sbitmap_vector_zero (transp, n_basic_blocks);
+ if (table->set_p)
+ sbitmap_vector_zero (transp, last_basic_block);
else
- sbitmap_vector_ones (transp, n_basic_blocks);
+ sbitmap_vector_ones (transp, last_basic_block);
}
if (comp)
- sbitmap_vector_zero (comp, n_basic_blocks);
+ sbitmap_vector_zero (comp, last_basic_block);
if (antloc)
- sbitmap_vector_zero (antloc, n_basic_blocks);
-
- /* We use the same code for cprop, pre and hoisting. For cprop
- we care about the set hash table, for pre and hoisting we
- care about the expr hash table. */
- hash_table_size = setp ? set_hash_table_size : expr_hash_table_size;
- hash_table = setp ? set_hash_table : expr_hash_table;
+ sbitmap_vector_zero (antloc, last_basic_block);
- for (i = 0; i < hash_table_size; i++)
+ for (i = 0; i < table->size; i++)
{
struct expr *expr;
- for (expr = hash_table[i]; expr != NULL; expr = expr->next_same_hash)
+ for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
{
int indx = expr->bitmap_index;
struct occr *occr;
@@ -1161,10 +1156,10 @@ compute_local_properties (transp, comp, antloc, setp)
We start by assuming all are transparent [none are killed], and
then reset the bits for those that are. */
if (transp)
- compute_transp (expr->expr, indx, transp, setp);
+ compute_transp (expr->expr, indx, transp, table->set_p);
/* The occurrences recorded in antic_occr are exactly those that
- we want to set to non-zero in ANTLOC. */
+ we want to set to nonzero in ANTLOC. */
if (antloc)
for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
{
@@ -1176,7 +1171,7 @@ compute_local_properties (transp, comp, antloc, setp)
}
/* The occurrences recorded in avail_occr are exactly those that
- we want to set to non-zero in COMP. */
+ we want to set to nonzero in COMP. */
if (comp)
for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
{
@@ -1286,29 +1281,25 @@ compute_sets (f)
/* Hash table support. */
-/* For each register, the cuid of the first/last insn in the block
- that set it, or -1 if not set. */
-#define NEVER_SET -1
-
struct reg_avail_info
{
- int last_bb;
+ basic_block last_bb;
int first_set;
int last_set;
};
static struct reg_avail_info *reg_avail_info;
-static int current_bb;
+static basic_block current_bb;
/* See whether X, the source of a set, is something we want to consider for
GCSE. */
+static GTY(()) rtx test_insn;
static int
want_to_gcse_p (x)
rtx x;
{
- static rtx test_insn = 0;
int num_clobbers = 0;
int icode;
@@ -1342,7 +1333,6 @@ want_to_gcse_p (x)
FIRST_PSEUDO_REGISTER * 2),
const0_rtx));
NEXT_INSN (test_insn) = PREV_INSN (test_insn) = 0;
- ggc_add_rtx_root (&test_insn, 1);
}
/* Now make an insn like the one we would make when GCSE'ing and see if
@@ -1353,7 +1343,7 @@ want_to_gcse_p (x)
&& (num_clobbers == 0 || ! added_clobbers_hard_reg_p (icode)));
}
-/* Return non-zero if the operands of expression X are unchanged from the
+/* Return nonzero if the operands of expression X are unchanged from the
start of INSN's basic block up to but not including INSN (if AVAIL_P == 0),
or from INSN to the end of INSN's basic block (if AVAIL_P != 0). */
@@ -1378,14 +1368,14 @@ oprs_unchanged_p (x, insn, avail_p)
if (info->last_bb != current_bb)
return 1;
- if (avail_p)
+ if (avail_p)
return info->last_set < INSN_CUID (insn);
else
return info->first_set >= INSN_CUID (insn);
}
case MEM:
- if (load_killed_in_block_p (BASIC_BLOCK (current_bb), INSN_CUID (insn),
+ if (load_killed_in_block_p (current_bb, INSN_CUID (insn),
x, avail_p))
return 0;
else
@@ -1470,8 +1460,8 @@ mems_conflict_for_gcse_p (dest, setter, data)
return;
/* If we are setting a MEM in our list of specially recognized MEMs,
- don't mark as killed this time. */
-
+ don't mark as killed this time. */
+
if (dest == gcse_mem_operand && pre_ldst_mems != NULL)
{
if (!find_rtx_in_ldst (dest))
@@ -1522,7 +1512,7 @@ load_killed_in_block_p (bb, uid_limit, x, avail_p)
return 1;
/* SETTER must be an INSN of some kind that sets memory. Call
- note_stores to examine each hunk of memory that is modified.
+ note_stores to examine each hunk of memory that is modified.
The note_stores interface is pretty limited, so we have to
communicate via global variables. Yuk. */
@@ -1536,7 +1526,7 @@ load_killed_in_block_p (bb, uid_limit, x, avail_p)
return 0;
}
-/* Return non-zero if the operands of expression X are unchanged from
+/* Return nonzero if the operands of expression X are unchanged from
the start of INSN's basic block up to but not including INSN. */
static int
@@ -1546,7 +1536,7 @@ oprs_anticipatable_p (x, insn)
return oprs_unchanged_p (x, insn, 0);
}
-/* Return non-zero if the operands of expression X are unchanged from
+/* Return nonzero if the operands of expression X are unchanged from
INSN to the end of INSN's basic block. */
static int
@@ -1587,7 +1577,7 @@ hash_string_1 (ps)
{
unsigned hash = 0;
const unsigned char *p = (const unsigned char *) ps;
-
+
if (p)
while (*p)
hash += *p++;
@@ -1689,7 +1679,9 @@ hash_expr_1 (x, mode, do_not_record_p)
}
hash += (unsigned int) MEM;
- hash += MEM_ALIAS_SET (x);
+ /* We used alias set for hashing, but this is not good, since the alias
+ set may differ in -fprofile-arcs and -fbranch-probabilities compilation
+ causing the profiles to fail to match. */
x = XEXP (x, 0);
goto repeat;
@@ -1797,7 +1789,7 @@ hash_set (regno, hash_table_size)
return hash % hash_table_size;
}
-/* Return non-zero if exp1 is equivalent to exp2.
+/* Return nonzero if exp1 is equivalent to exp2.
??? Borrowed from cse.c. Might want to remerge with cse.c. Later. */
static int
@@ -1940,22 +1932,23 @@ expr_equiv_p (x, y)
return 1;
}
-/* Insert expression X in INSN in the hash table.
+/* Insert expression X in INSN in the hash TABLE.
If it is already present, record it as the last occurrence in INSN's
basic block.
MODE is the mode of the value X is being stored into.
It is only used if X is a CONST_INT.
- ANTIC_P is non-zero if X is an anticipatable expression.
- AVAIL_P is non-zero if X is an available expression. */
+ ANTIC_P is nonzero if X is an anticipatable expression.
+ AVAIL_P is nonzero if X is an available expression. */
static void
-insert_expr_in_table (x, mode, insn, antic_p, avail_p)
+insert_expr_in_table (x, mode, insn, antic_p, avail_p, table)
rtx x;
enum machine_mode mode;
rtx insn;
int antic_p, avail_p;
+ struct hash_table *table;
{
int found, do_not_record_p;
unsigned int hash;
@@ -1963,7 +1956,7 @@ insert_expr_in_table (x, mode, insn, antic_p, avail_p)
struct occr *antic_occr, *avail_occr;
struct occr *last_occr = NULL;
- hash = hash_expr (x, mode, &do_not_record_p, expr_hash_table_size);
+ hash = hash_expr (x, mode, &do_not_record_p, table->size);
/* Do not insert expression in table if it contains volatile operands,
or if hash_expr determines the expression is something we don't want
@@ -1971,7 +1964,7 @@ insert_expr_in_table (x, mode, insn, antic_p, avail_p)
if (do_not_record_p)
return;
- cur_expr = expr_hash_table[hash];
+ cur_expr = table->table[hash];
found = 0;
while (cur_expr && 0 == (found = expr_equiv_p (cur_expr->expr, x)))
@@ -1986,16 +1979,16 @@ insert_expr_in_table (x, mode, insn, antic_p, avail_p)
{
cur_expr = (struct expr *) gcse_alloc (sizeof (struct expr));
bytes_used += sizeof (struct expr);
- if (expr_hash_table[hash] == NULL)
+ if (table->table[hash] == NULL)
/* This is the first pattern that hashed to this index. */
- expr_hash_table[hash] = cur_expr;
+ table->table[hash] = cur_expr;
else
/* Add EXPR to end of this hash chain. */
last_expr->next_same_hash = cur_expr;
- /* Set the fields of the expr element. */
+ /* Set the fields of the expr element. */
cur_expr->expr = x;
- cur_expr->bitmap_index = n_exprs++;
+ cur_expr->bitmap_index = table->n_elems++;
cur_expr->next_same_hash = NULL;
cur_expr->antic_occr = NULL;
cur_expr->avail_occr = NULL;
@@ -2079,9 +2072,10 @@ insert_expr_in_table (x, mode, insn, antic_p, avail_p)
basic block. */
static void
-insert_set_in_table (x, insn)
+insert_set_in_table (x, insn, table)
rtx x;
rtx insn;
+ struct hash_table *table;
{
int found;
unsigned int hash;
@@ -2092,9 +2086,9 @@ insert_set_in_table (x, insn)
|| GET_CODE (SET_DEST (x)) != REG)
abort ();
- hash = hash_set (REGNO (SET_DEST (x)), set_hash_table_size);
+ hash = hash_set (REGNO (SET_DEST (x)), table->size);
- cur_expr = set_hash_table[hash];
+ cur_expr = table->table[hash];
found = 0;
while (cur_expr && 0 == (found = expr_equiv_p (cur_expr->expr, x)))
@@ -2109,9 +2103,9 @@ insert_set_in_table (x, insn)
{
cur_expr = (struct expr *) gcse_alloc (sizeof (struct expr));
bytes_used += sizeof (struct expr);
- if (set_hash_table[hash] == NULL)
+ if (table->table[hash] == NULL)
/* This is the first pattern that hashed to this index. */
- set_hash_table[hash] = cur_expr;
+ table->table[hash] = cur_expr;
else
/* Add EXPR to end of this hash chain. */
last_expr->next_same_hash = cur_expr;
@@ -2120,7 +2114,7 @@ insert_set_in_table (x, insn)
We must copy X because it can be modified when copy propagation is
performed on its operands. */
cur_expr->expr = copy_rtx (x);
- cur_expr->bitmap_index = n_sets++;
+ cur_expr->bitmap_index = table->n_elems++;
cur_expr->next_same_hash = NULL;
cur_expr->antic_occr = NULL;
cur_expr->avail_occr = NULL;
@@ -2160,21 +2154,20 @@ insert_set_in_table (x, insn)
}
}
-/* Scan pattern PAT of INSN and add an entry to the hash table. If SET_P is
- non-zero, this is for the assignment hash table, otherwise it is for the
- expression hash table. */
+/* Scan pattern PAT of INSN and add an entry to the hash TABLE (set or
+ expression one). */
static void
-hash_scan_set (pat, insn, set_p)
+hash_scan_set (pat, insn, table)
rtx pat, insn;
- int set_p;
+ struct hash_table *table;
{
rtx src = SET_SRC (pat);
rtx dest = SET_DEST (pat);
rtx note;
if (GET_CODE (src) == CALL)
- hash_scan_call (src, insn);
+ hash_scan_call (src, insn, table);
else if (GET_CODE (dest) == REG)
{
@@ -2183,19 +2176,19 @@ hash_scan_set (pat, insn, set_p)
/* If this is a single set and we are doing constant propagation,
see if a REG_NOTE shows this equivalent to a constant. */
- if (set_p && (note = find_reg_equal_equiv_note (insn)) != 0
+ if (table->set_p && (note = find_reg_equal_equiv_note (insn)) != 0
&& CONSTANT_P (XEXP (note, 0)))
src = XEXP (note, 0), pat = gen_rtx_SET (VOIDmode, dest, src);
/* Only record sets of pseudo-regs in the hash table. */
- if (! set_p
+ if (! table->set_p
&& regno >= FIRST_PSEUDO_REGISTER
/* Don't GCSE something if we can't do a reg/reg copy. */
&& can_copy_p [GET_MODE (dest)]
/* GCSE commonly inserts instruction after the insn. We can't
do that easily for EH_REGION notes so disable GCSE on these
for now. */
- && !can_throw_internal (insn)
+ && !find_reg_note (insn, REG_EH_REGION, NULL_RTX)
/* Is SET_SRC something we want to gcse? */
&& want_to_gcse_p (src)
/* Don't CSE a nop. */
@@ -2219,11 +2212,11 @@ hash_scan_set (pat, insn, set_p)
int avail_p = (oprs_available_p (src, insn)
&& ! JUMP_P (insn));
- insert_expr_in_table (src, GET_MODE (dest), insn, antic_p, avail_p);
+ insert_expr_in_table (src, GET_MODE (dest), insn, antic_p, avail_p, table);
}
/* Record sets for constant/copy propagation. */
- else if (set_p
+ else if (table->set_p
&& regno >= FIRST_PSEUDO_REGISTER
&& ((GET_CODE (src) == REG
&& REGNO (src) >= FIRST_PSEUDO_REGISTER
@@ -2236,20 +2229,22 @@ hash_scan_set (pat, insn, set_p)
&& (insn == BLOCK_END (BLOCK_NUM (insn))
|| ((tmp = next_nonnote_insn (insn)) != NULL_RTX
&& oprs_available_p (pat, tmp))))
- insert_set_in_table (pat, insn);
+ insert_set_in_table (pat, insn, table);
}
}
static void
-hash_scan_clobber (x, insn)
+hash_scan_clobber (x, insn, table)
rtx x ATTRIBUTE_UNUSED, insn ATTRIBUTE_UNUSED;
+ struct hash_table *table ATTRIBUTE_UNUSED;
{
/* Currently nothing to do. */
}
static void
-hash_scan_call (x, insn)
+hash_scan_call (x, insn, table)
rtx x ATTRIBUTE_UNUSED, insn ATTRIBUTE_UNUSED;
+ struct hash_table *table ATTRIBUTE_UNUSED;
{
/* Currently nothing to do. */
}
@@ -2262,15 +2257,15 @@ hash_scan_call (x, insn)
that isn't dealt with right now. The trick is handling the CLOBBERs that
are also in the PARALLEL. Later.
- If SET_P is non-zero, this is for the assignment hash table,
+ If SET_P is nonzero, this is for the assignment hash table,
otherwise it is for the expression hash table.
If IN_LIBCALL_BLOCK nonzero, we are in a libcall block, and should
not record any expressions. */
static void
-hash_scan_insn (insn, set_p, in_libcall_block)
+hash_scan_insn (insn, table, in_libcall_block)
rtx insn;
- int set_p;
+ struct hash_table *table;
int in_libcall_block;
{
rtx pat = PATTERN (insn);
@@ -2283,32 +2278,31 @@ hash_scan_insn (insn, set_p, in_libcall_block)
what's been modified. */
if (GET_CODE (pat) == SET)
- hash_scan_set (pat, insn, set_p);
+ hash_scan_set (pat, insn, table);
else if (GET_CODE (pat) == PARALLEL)
for (i = 0; i < XVECLEN (pat, 0); i++)
{
rtx x = XVECEXP (pat, 0, i);
if (GET_CODE (x) == SET)
- hash_scan_set (x, insn, set_p);
+ hash_scan_set (x, insn, table);
else if (GET_CODE (x) == CLOBBER)
- hash_scan_clobber (x, insn);
+ hash_scan_clobber (x, insn, table);
else if (GET_CODE (x) == CALL)
- hash_scan_call (x, insn);
+ hash_scan_call (x, insn, table);
}
else if (GET_CODE (pat) == CLOBBER)
- hash_scan_clobber (pat, insn);
+ hash_scan_clobber (pat, insn, table);
else if (GET_CODE (pat) == CALL)
- hash_scan_call (pat, insn);
+ hash_scan_call (pat, insn, table);
}
static void
-dump_hash_table (file, name, table, table_size, total_size)
+dump_hash_table (file, name, table)
FILE *file;
const char *name;
- struct expr **table;
- int table_size, total_size;
+ struct hash_table *table;
{
int i;
/* Flattened out table, so it's printed in proper order. */
@@ -2316,21 +2310,21 @@ dump_hash_table (file, name, table, table_size, total_size)
unsigned int *hash_val;
struct expr *expr;
- flat_table
- = (struct expr **) xcalloc (total_size, sizeof (struct expr *));
- hash_val = (unsigned int *) xmalloc (total_size * sizeof (unsigned int));
+ flat_table
+ = (struct expr **) xcalloc (table->n_elems, sizeof (struct expr *));
+ hash_val = (unsigned int *) xmalloc (table->n_elems * sizeof (unsigned int));
- for (i = 0; i < table_size; i++)
- for (expr = table[i]; expr != NULL; expr = expr->next_same_hash)
+ for (i = 0; i < (int) table->size; i++)
+ for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
{
flat_table[expr->bitmap_index] = expr;
hash_val[expr->bitmap_index] = i;
}
fprintf (file, "%s hash table (%d buckets, %d entries)\n",
- name, table_size, total_size);
+ name, table->size, table->n_elems);
- for (i = 0; i < total_size; i++)
+ for (i = 0; i < (int) table->n_elems; i++)
if (flat_table[i] != 0)
{
expr = flat_table[i];
@@ -2373,7 +2367,7 @@ record_last_reg_set_info (insn, regno)
{
info->last_bb = current_bb;
info->first_set = cuid;
- SET_BIT (reg_set_in_block[current_bb], regno);
+ SET_BIT (reg_set_in_block[current_bb->index], regno);
}
}
@@ -2382,7 +2376,7 @@ record_last_reg_set_info (insn, regno)
Note we store a pair of elements in the list, so they have to be
taken off pairwise. */
-static void
+static void
canon_list_insert (dest, unused1, v_insn)
rtx dest ATTRIBUTE_UNUSED;
rtx unused1 ATTRIBUTE_UNUSED;
@@ -2406,12 +2400,12 @@ canon_list_insert (dest, unused1, v_insn)
dest_addr = get_addr (XEXP (dest, 0));
dest_addr = canon_rtx (dest_addr);
- insn = (rtx) v_insn;
+ insn = (rtx) v_insn;
bb = BLOCK_NUM (insn);
- canon_modify_mem_list[bb] =
+ canon_modify_mem_list[bb] =
alloc_EXPR_LIST (VOIDmode, dest_addr, canon_modify_mem_list[bb]);
- canon_modify_mem_list[bb] =
+ canon_modify_mem_list[bb] =
alloc_EXPR_LIST (VOIDmode, dest, canon_modify_mem_list[bb]);
bitmap_set_bit (canon_modify_mem_list_set, bb);
}
@@ -2436,8 +2430,8 @@ record_last_mem_set_info (insn)
/* Note that traversals of this loop (other than for free-ing)
will break after encountering a CALL_INSN. So, there's no
need to insert a pair of items, as canon_list_insert does. */
- canon_modify_mem_list[bb] =
- alloc_INSN_LIST (insn, canon_modify_mem_list[bb]);
+ canon_modify_mem_list[bb] =
+ alloc_INSN_LIST (insn, canon_modify_mem_list[bb]);
bitmap_set_bit (canon_modify_mem_list_set, bb);
}
else
@@ -2481,11 +2475,11 @@ record_last_set_info (dest, setter, data)
Currently src must be a pseudo-reg or a const_int.
F is the first insn.
- SET_P is non-zero for computing the assignment hash table. */
+ TABLE is the table computed. */
static void
-compute_hash_table (set_p)
- int set_p;
+compute_hash_table_work (table)
+ struct hash_table *table;
{
unsigned int i;
@@ -2493,7 +2487,7 @@ compute_hash_table (set_p)
registers are set in which blocks.
??? This isn't needed during const/copy propagation, but it's cheap to
compute. Later. */
- sbitmap_vector_zero (reg_set_in_block, n_basic_blocks);
+ sbitmap_vector_zero (reg_set_in_block, last_basic_block);
/* re-Cache any INSN_LIST nodes we have allocated. */
clear_modify_mem_tables ();
@@ -2502,9 +2496,9 @@ compute_hash_table (set_p)
gmalloc (max_gcse_regno * sizeof (struct reg_avail_info));
for (i = 0; i < max_gcse_regno; ++i)
- reg_avail_info[i].last_bb = NEVER_SET;
+ reg_avail_info[i].last_bb = NULL;
- for (current_bb = 0; current_bb < n_basic_blocks; current_bb++)
+ FOR_EACH_BB (current_bb)
{
rtx insn;
unsigned int regno;
@@ -2515,8 +2509,8 @@ compute_hash_table (set_p)
??? hard-reg reg_set_in_block computation
could be moved to compute_sets since they currently don't change. */
- for (insn = BLOCK_HEAD (current_bb);
- insn && insn != NEXT_INSN (BLOCK_END (current_bb));
+ for (insn = current_bb->head;
+ insn && insn != NEXT_INSN (current_bb->end);
insn = NEXT_INSN (insn))
{
if (! INSN_P (insn))
@@ -2525,7 +2519,7 @@ compute_hash_table (set_p)
if (GET_CODE (insn) == CALL_INSN)
{
bool clobbers_all = false;
-#ifdef NON_SAVING_SETJMP
+#ifdef NON_SAVING_SETJMP
if (NON_SAVING_SETJMP
&& find_reg_note (insn, REG_SETJMP, NULL_RTX))
clobbers_all = true;
@@ -2544,18 +2538,18 @@ compute_hash_table (set_p)
/* The next pass builds the hash table. */
- for (insn = BLOCK_HEAD (current_bb), in_libcall_block = 0;
- insn && insn != NEXT_INSN (BLOCK_END (current_bb));
+ for (insn = current_bb->head, in_libcall_block = 0;
+ insn && insn != NEXT_INSN (current_bb->end);
insn = NEXT_INSN (insn))
if (INSN_P (insn))
{
if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
- in_libcall_block = 1;
- else if (set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
- in_libcall_block = 0;
- hash_scan_insn (insn, set_p, in_libcall_block);
- if (!set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
- in_libcall_block = 0;
+ in_libcall_block = 1;
+ else if (table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
+ in_libcall_block = 0;
+ hash_scan_insn (insn, table, in_libcall_block);
+ if (!table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
+ in_libcall_block = 0;
}
}
@@ -2563,111 +2557,76 @@ compute_hash_table (set_p)
reg_avail_info = NULL;
}
-/* Allocate space for the set hash table.
+/* Allocate space for the set/expr hash TABLE.
N_INSNS is the number of instructions in the function.
- It is used to determine the number of buckets to use. */
+ It is used to determine the number of buckets to use.
+ SET_P determines whether set or expression table will
+ be created. */
static void
-alloc_set_hash_table (n_insns)
+alloc_hash_table (n_insns, table, set_p)
int n_insns;
+ struct hash_table *table;
+ int set_p;
{
int n;
- set_hash_table_size = n_insns / 4;
- if (set_hash_table_size < 11)
- set_hash_table_size = 11;
-
- /* Attempt to maintain efficient use of hash table.
- Making it an odd number is simplest for now.
- ??? Later take some measurements. */
- set_hash_table_size |= 1;
- n = set_hash_table_size * sizeof (struct expr *);
- set_hash_table = (struct expr **) gmalloc (n);
-}
-
-/* Free things allocated by alloc_set_hash_table. */
-
-static void
-free_set_hash_table ()
-{
- free (set_hash_table);
-}
-
-/* Compute the hash table for doing copy/const propagation. */
-
-static void
-compute_set_hash_table ()
-{
- /* Initialize count of number of entries in hash table. */
- n_sets = 0;
- memset ((char *) set_hash_table, 0,
- set_hash_table_size * sizeof (struct expr *));
-
- compute_hash_table (1);
-}
-
-/* Allocate space for the expression hash table.
- N_INSNS is the number of instructions in the function.
- It is used to determine the number of buckets to use. */
-
-static void
-alloc_expr_hash_table (n_insns)
- unsigned int n_insns;
-{
- int n;
-
- expr_hash_table_size = n_insns / 2;
- /* Make sure the amount is usable. */
- if (expr_hash_table_size < 11)
- expr_hash_table_size = 11;
+ table->size = n_insns / 4;
+ if (table->size < 11)
+ table->size = 11;
/* Attempt to maintain efficient use of hash table.
Making it an odd number is simplest for now.
??? Later take some measurements. */
- expr_hash_table_size |= 1;
- n = expr_hash_table_size * sizeof (struct expr *);
- expr_hash_table = (struct expr **) gmalloc (n);
+ table->size |= 1;
+ n = table->size * sizeof (struct expr *);
+ table->table = (struct expr **) gmalloc (n);
+ table->set_p = set_p;
}
-/* Free things allocated by alloc_expr_hash_table. */
+/* Free things allocated by alloc_hash_table. */
static void
-free_expr_hash_table ()
+free_hash_table (table)
+ struct hash_table *table;
{
- free (expr_hash_table);
+ free (table->table);
}
-/* Compute the hash table for doing GCSE. */
+/* Compute the hash TABLE for doing copy/const propagation or
+ expression hash table. */
static void
-compute_expr_hash_table ()
+compute_hash_table (table)
+ struct hash_table *table;
{
/* Initialize count of number of entries in hash table. */
- n_exprs = 0;
- memset ((char *) expr_hash_table, 0,
- expr_hash_table_size * sizeof (struct expr *));
+ table->n_elems = 0;
+ memset ((char *) table->table, 0,
+ table->size * sizeof (struct expr *));
- compute_hash_table (0);
+ compute_hash_table_work (table);
}
/* Expression tracking support. */
-/* Lookup pattern PAT in the expression table.
+/* Lookup pattern PAT in the expression TABLE.
The result is a pointer to the table entry, or NULL if not found. */
static struct expr *
-lookup_expr (pat)
+lookup_expr (pat, table)
rtx pat;
+ struct hash_table *table;
{
int do_not_record_p;
unsigned int hash = hash_expr (pat, GET_MODE (pat), &do_not_record_p,
- expr_hash_table_size);
+ table->size);
struct expr *expr;
if (do_not_record_p)
return NULL;
- expr = expr_hash_table[hash];
+ expr = table->table[hash];
while (expr && ! expr_equiv_p (expr->expr, pat))
expr = expr->next_same_hash;
@@ -2675,19 +2634,20 @@ lookup_expr (pat)
return expr;
}
-/* Lookup REGNO in the set table. If PAT is non-NULL look for the entry that
+/* Lookup REGNO in the set TABLE. If PAT is non-NULL look for the entry that
matches it, otherwise return the first entry for REGNO. The result is a
pointer to the table entry, or NULL if not found. */
static struct expr *
-lookup_set (regno, pat)
+lookup_set (regno, pat, table)
unsigned int regno;
rtx pat;
+ struct hash_table *table;
{
- unsigned int hash = hash_set (regno, set_hash_table_size);
+ unsigned int hash = hash_set (regno, table->size);
struct expr *expr;
- expr = set_hash_table[hash];
+ expr = table->table[hash];
if (pat)
{
@@ -2782,7 +2742,7 @@ reset_opr_set_tables ()
clear_modify_mem_tables ();
}
-/* Return non-zero if the operands of X are not set before INSN in
+/* Return nonzero if the operands of X are not set before INSN in
INSN's basic block. */
static int
@@ -2812,7 +2772,7 @@ oprs_not_set_p (x, insn)
return 1;
case MEM:
- if (load_killed_in_block_p (BLOCK_FOR_INSN (insn),
+ if (load_killed_in_block_p (BLOCK_FOR_INSN (insn),
INSN_CUID (insn), x, 0))
return 0;
else
@@ -2938,16 +2898,16 @@ alloc_rd_mem (n_blocks, n_insns)
int n_blocks, n_insns;
{
rd_kill = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
- sbitmap_vector_zero (rd_kill, n_basic_blocks);
+ sbitmap_vector_zero (rd_kill, n_blocks);
rd_gen = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
- sbitmap_vector_zero (rd_gen, n_basic_blocks);
+ sbitmap_vector_zero (rd_gen, n_blocks);
reaching_defs = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
- sbitmap_vector_zero (reaching_defs, n_basic_blocks);
+ sbitmap_vector_zero (reaching_defs, n_blocks);
rd_out = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
- sbitmap_vector_zero (rd_out, n_basic_blocks);
+ sbitmap_vector_zero (rd_out, n_blocks);
}
/* Free reaching def variables. */
@@ -2981,9 +2941,10 @@ handle_rd_kill_set (insn, regno, bb)
static void
compute_kill_rd ()
{
- int bb, cuid;
+ int cuid;
unsigned int regno;
int i;
+ basic_block bb;
/* For each block
For each set bit in `gen' of the block (i.e each insn which
@@ -2993,9 +2954,9 @@ compute_kill_rd ()
For each setting of regx in the linked list, which is not in
this block
Set the bit in `kill' corresponding to that insn. */
- for (bb = 0; bb < n_basic_blocks; bb++)
+ FOR_EACH_BB (bb)
for (cuid = 0; cuid < max_cuid; cuid++)
- if (TEST_BIT (rd_gen[bb], cuid))
+ if (TEST_BIT (rd_gen[bb->index], cuid))
{
rtx insn = CUID_INSN (cuid);
rtx pat = PATTERN (insn);
@@ -3004,7 +2965,7 @@ compute_kill_rd ()
{
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
- handle_rd_kill_set (insn, regno, BASIC_BLOCK (bb));
+ handle_rd_kill_set (insn, regno, bb);
}
if (GET_CODE (pat) == PARALLEL)
@@ -3017,17 +2978,17 @@ compute_kill_rd ()
&& GET_CODE (XEXP (XVECEXP (pat, 0, i), 0)) == REG)
handle_rd_kill_set (insn,
REGNO (XEXP (XVECEXP (pat, 0, i), 0)),
- BASIC_BLOCK (bb));
+ bb);
}
}
else if (GET_CODE (pat) == SET && GET_CODE (SET_DEST (pat)) == REG)
/* Each setting of this register outside of this block
must be marked in the set of kills in this block. */
- handle_rd_kill_set (insn, REGNO (SET_DEST (pat)), BASIC_BLOCK (bb));
+ handle_rd_kill_set (insn, REGNO (SET_DEST (pat)), bb);
}
}
-/* Compute the reaching definitions as in
+/* Compute the reaching definitions as in
Compilers Principles, Techniques, and Tools. Aho, Sethi, Ullman,
Chapter 10. It is the same algorithm as used for computing available
expressions but applied to the gens and kills of reaching definitions. */
@@ -3035,21 +2996,22 @@ compute_kill_rd ()
static void
compute_rd ()
{
- int bb, changed, passes;
+ int changed, passes;
+ basic_block bb;
- for (bb = 0; bb < n_basic_blocks; bb++)
- sbitmap_copy (rd_out[bb] /*dst*/, rd_gen[bb] /*src*/);
+ FOR_EACH_BB (bb)
+ sbitmap_copy (rd_out[bb->index] /*dst*/, rd_gen[bb->index] /*src*/);
passes = 0;
changed = 1;
while (changed)
{
changed = 0;
- for (bb = 0; bb < n_basic_blocks; bb++)
+ FOR_EACH_BB (bb)
{
- sbitmap_union_of_preds (reaching_defs[bb], rd_out, bb);
- changed |= sbitmap_union_of_diff (rd_out[bb], rd_gen[bb],
- reaching_defs[bb], rd_kill[bb]);
+ sbitmap_union_of_preds (reaching_defs[bb->index], rd_out, bb->index);
+ changed |= sbitmap_union_of_diff_cg (rd_out[bb->index], rd_gen[bb->index],
+ reaching_defs[bb->index], rd_kill[bb->index]);
}
passes++;
}
@@ -3067,16 +3029,16 @@ alloc_avail_expr_mem (n_blocks, n_exprs)
int n_blocks, n_exprs;
{
ae_kill = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
- sbitmap_vector_zero (ae_kill, n_basic_blocks);
+ sbitmap_vector_zero (ae_kill, n_blocks);
ae_gen = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
- sbitmap_vector_zero (ae_gen, n_basic_blocks);
+ sbitmap_vector_zero (ae_gen, n_blocks);
ae_in = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
- sbitmap_vector_zero (ae_in, n_basic_blocks);
+ sbitmap_vector_zero (ae_in, n_blocks);
ae_out = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
- sbitmap_vector_zero (ae_out, n_basic_blocks);
+ sbitmap_vector_zero (ae_out, n_blocks);
}
static void
@@ -3091,7 +3053,8 @@ free_avail_expr_mem ()
/* Compute the set of available expressions generated in each basic block. */
static void
-compute_ae_gen ()
+compute_ae_gen (expr_hash_table)
+ struct hash_table *expr_hash_table;
{
unsigned int i;
struct expr *expr;
@@ -3101,13 +3064,13 @@ compute_ae_gen ()
This is all we have to do because an expression is not recorded if it
is not available, and the only expressions we want to work with are the
ones that are recorded. */
- for (i = 0; i < expr_hash_table_size; i++)
- for (expr = expr_hash_table[i]; expr != 0; expr = expr->next_same_hash)
+ for (i = 0; i < expr_hash_table->size; i++)
+ for (expr = expr_hash_table->table[i]; expr != 0; expr = expr->next_same_hash)
for (occr = expr->avail_occr; occr != 0; occr = occr->next)
SET_BIT (ae_gen[BLOCK_NUM (occr->insn)], expr->bitmap_index);
}
-/* Return non-zero if expression X is killed in BB. */
+/* Return nonzero if expression X is killed in BB. */
static int
expr_killed_p (x, bb)
@@ -3173,31 +3136,32 @@ expr_killed_p (x, bb)
/* Compute the set of available expressions killed in each basic block. */
static void
-compute_ae_kill (ae_gen, ae_kill)
+compute_ae_kill (ae_gen, ae_kill, expr_hash_table)
sbitmap *ae_gen, *ae_kill;
+ struct hash_table *expr_hash_table;
{
- int bb;
+ basic_block bb;
unsigned int i;
struct expr *expr;
- for (bb = 0; bb < n_basic_blocks; bb++)
- for (i = 0; i < expr_hash_table_size; i++)
- for (expr = expr_hash_table[i]; expr; expr = expr->next_same_hash)
+ FOR_EACH_BB (bb)
+ for (i = 0; i < expr_hash_table->size; i++)
+ for (expr = expr_hash_table->table[i]; expr; expr = expr->next_same_hash)
{
/* Skip EXPR if generated in this block. */
- if (TEST_BIT (ae_gen[bb], expr->bitmap_index))
+ if (TEST_BIT (ae_gen[bb->index], expr->bitmap_index))
continue;
- if (expr_killed_p (expr->expr, BASIC_BLOCK (bb)))
- SET_BIT (ae_kill[bb], expr->bitmap_index);
+ if (expr_killed_p (expr->expr, bb))
+ SET_BIT (ae_kill[bb->index], expr->bitmap_index);
}
}
/* Actually perform the Classic GCSE optimizations. */
-/* Return non-zero if occurrence OCCR of expression EXPR reaches block BB.
+/* Return nonzero if occurrence OCCR of expression EXPR reaches block BB.
- CHECK_SELF_LOOP is non-zero if we should consider a block reaching itself
+ CHECK_SELF_LOOP is nonzero if we should consider a block reaching itself
as a positive reach. We want to do this when there are two computations
of the expression in the block.
@@ -3259,7 +3223,7 @@ expr_reaches_here_p_work (occr, expr, bb, check_self_loop, visited)
else
{
visited[pred_bb->index] = 1;
- if (expr_reaches_here_p_work (occr, expr, pred_bb, check_self_loop,
+ if (expr_reaches_here_p_work (occr, expr, pred_bb, check_self_loop,
visited))
return 1;
@@ -3281,10 +3245,10 @@ expr_reaches_here_p (occr, expr, bb, check_self_loop)
int check_self_loop;
{
int rval;
- char *visited = (char *) xcalloc (n_basic_blocks, 1);
+ char *visited = (char *) xcalloc (last_basic_block, 1);
rval = expr_reaches_here_p_work (occr, expr, bb, check_self_loop, visited);
-
+
free (visited);
return rval;
}
@@ -3302,7 +3266,7 @@ computing_insn (expr, insn)
basic_block bb = BLOCK_FOR_INSN (insn);
if (expr->avail_occr->next == NULL)
- {
+ {
if (BLOCK_FOR_INSN (expr->avail_occr->insn) == bb)
/* The available expression is actually itself
(i.e. a loop in the flow graph) so do nothing. */
@@ -3315,7 +3279,7 @@ computing_insn (expr, insn)
else
{
/* Pattern is computed more than once.
- Search backwards from this insn to see how many of these
+ Search backwards from this insn to see how many of these
computations actually reach this insn. */
struct occr *occr;
rtx insn_computes_expr = NULL;
@@ -3356,7 +3320,7 @@ computing_insn (expr, insn)
}
}
-/* Return non-zero if the definition in DEF_INSN can reach INSN.
+/* Return nonzero if the definition in DEF_INSN can reach INSN.
Only called by can_disregard_other_sets. */
static int
@@ -3390,7 +3354,7 @@ def_reaches_here_p (insn, def_insn)
return 0;
}
-/* Return non-zero if *ADDR_THIS_REG can only have one value at INSN. The
+/* Return nonzero if *ADDR_THIS_REG can only have one value at INSN. The
value returned is the number of definitions that reach INSN. Returning a
value of zero means that [maybe] more than one definition reaches INSN and
the caller can't perform whatever optimization it is trying. i.e. it is
@@ -3433,7 +3397,7 @@ can_disregard_other_sets (addr_this_reg, insn, for_combine)
return 0;
}
- *addr_this_reg = this_reg;
+ *addr_this_reg = this_reg;
}
return number_of_reaching_defs;
@@ -3442,7 +3406,7 @@ can_disregard_other_sets (addr_this_reg, insn, for_combine)
/* Expression computed by insn is available and the substitution is legal,
so try to perform the substitution.
- The result is non-zero if any changes were made. */
+ The result is nonzero if any changes were made. */
static int
handle_avail_expr (insn, expr)
@@ -3589,7 +3553,7 @@ handle_avail_expr (insn, expr)
REGNO (SET_DEST (PATTERN (NEXT_INSN
(insn_computes_expr)))));
fprintf (gcse_file, "set in insn %d\n",
- INSN_UID (insn_computes_expr));
+ INSN_UID (insn_computes_expr));
}
}
}
@@ -3600,25 +3564,29 @@ handle_avail_expr (insn, expr)
/* Perform classic GCSE. This is called by one_classic_gcse_pass after all
the dataflow analysis has been done.
- The result is non-zero if a change was made. */
+ The result is nonzero if a change was made. */
static int
classic_gcse ()
{
- int bb, changed;
+ int changed;
rtx insn;
+ basic_block bb;
/* Note we start at block 1. */
+ if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
+ return 0;
+
changed = 0;
- for (bb = 1; bb < n_basic_blocks; bb++)
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb, EXIT_BLOCK_PTR, next_bb)
{
/* Reset tables used to keep track of what's still valid [since the
start of the block]. */
reset_opr_set_tables ();
- for (insn = BLOCK_HEAD (bb);
- insn != NULL && insn != NEXT_INSN (BLOCK_END (bb));
+ for (insn = bb->head;
+ insn != NULL && insn != NEXT_INSN (bb->end);
insn = NEXT_INSN (insn))
{
/* Is insn of form (set (pseudo-reg) ...)? */
@@ -3633,10 +3601,10 @@ classic_gcse ()
if (want_to_gcse_p (src)
/* Is the expression recorded? */
- && ((expr = lookup_expr (src)) != NULL)
+ && ((expr = lookup_expr (src, &expr_hash_table)) != NULL)
/* Is the expression available [at the start of the
block]? */
- && TEST_BIT (ae_in[bb], expr->bitmap_index)
+ && TEST_BIT (ae_in[bb->index], expr->bitmap_index)
/* Are the operands unchanged since the start of the
block? */
&& oprs_not_set_p (src, insn))
@@ -3655,7 +3623,7 @@ classic_gcse ()
/* Top level routine to perform one classic GCSE pass.
- Return non-zero if a change was made. */
+ Return nonzero if a change was made. */
static int
one_classic_gcse_pass (pass)
@@ -3666,27 +3634,26 @@ one_classic_gcse_pass (pass)
gcse_subst_count = 0;
gcse_create_count = 0;
- alloc_expr_hash_table (max_cuid);
- alloc_rd_mem (n_basic_blocks, max_cuid);
- compute_expr_hash_table ();
+ alloc_hash_table (max_cuid, &expr_hash_table, 0);
+ alloc_rd_mem (last_basic_block, max_cuid);
+ compute_hash_table (&expr_hash_table);
if (gcse_file)
- dump_hash_table (gcse_file, "Expression", expr_hash_table,
- expr_hash_table_size, n_exprs);
+ dump_hash_table (gcse_file, "Expression", &expr_hash_table);
- if (n_exprs > 0)
+ if (expr_hash_table.n_elems > 0)
{
compute_kill_rd ();
compute_rd ();
- alloc_avail_expr_mem (n_basic_blocks, n_exprs);
- compute_ae_gen ();
- compute_ae_kill (ae_gen, ae_kill);
+ alloc_avail_expr_mem (last_basic_block, expr_hash_table.n_elems);
+ compute_ae_gen (&expr_hash_table);
+ compute_ae_kill (ae_gen, ae_kill, &expr_hash_table);
compute_available (ae_gen, ae_kill, ae_out, ae_in);
changed = classic_gcse ();
free_avail_expr_mem ();
}
free_rd_mem ();
- free_expr_hash_table ();
+ free_hash_table (&expr_hash_table);
if (gcse_file)
{
@@ -3747,7 +3714,8 @@ compute_transp (x, indx, bmap, set_p)
sbitmap *bmap;
int set_p;
{
- int bb, i, j;
+ int i, j;
+ basic_block bb;
enum rtx_code code;
reg_set *r;
const char *fmt;
@@ -3767,9 +3735,9 @@ compute_transp (x, indx, bmap, set_p)
{
if (REGNO (x) < FIRST_PSEUDO_REGISTER)
{
- for (bb = 0; bb < n_basic_blocks; bb++)
- if (TEST_BIT (reg_set_in_block[bb], REGNO (x)))
- SET_BIT (bmap[bb], indx);
+ FOR_EACH_BB (bb)
+ if (TEST_BIT (reg_set_in_block[bb->index], REGNO (x)))
+ SET_BIT (bmap[bb->index], indx);
}
else
{
@@ -3781,9 +3749,9 @@ compute_transp (x, indx, bmap, set_p)
{
if (REGNO (x) < FIRST_PSEUDO_REGISTER)
{
- for (bb = 0; bb < n_basic_blocks; bb++)
- if (TEST_BIT (reg_set_in_block[bb], REGNO (x)))
- RESET_BIT (bmap[bb], indx);
+ FOR_EACH_BB (bb)
+ if (TEST_BIT (reg_set_in_block[bb->index], REGNO (x)))
+ RESET_BIT (bmap[bb->index], indx);
}
else
{
@@ -3795,9 +3763,9 @@ compute_transp (x, indx, bmap, set_p)
return;
case MEM:
- for (bb = 0; bb < n_basic_blocks; bb++)
+ FOR_EACH_BB (bb)
{
- rtx list_entry = canon_modify_mem_list[bb];
+ rtx list_entry = canon_modify_mem_list[bb->index];
while (list_entry)
{
@@ -3806,9 +3774,9 @@ compute_transp (x, indx, bmap, set_p)
if (GET_CODE (XEXP (list_entry, 0)) == CALL_INSN)
{
if (set_p)
- SET_BIT (bmap[bb], indx);
+ SET_BIT (bmap[bb->index], indx);
else
- RESET_BIT (bmap[bb], indx);
+ RESET_BIT (bmap[bb->index], indx);
break;
}
/* LIST_ENTRY must be an INSN of some kind that sets memory.
@@ -3817,14 +3785,14 @@ compute_transp (x, indx, bmap, set_p)
dest = XEXP (list_entry, 0);
list_entry = XEXP (list_entry, 1);
dest_addr = XEXP (list_entry, 0);
-
+
if (canon_true_dependence (dest, GET_MODE (dest), dest_addr,
x, rtx_addr_varies_p))
{
if (set_p)
- SET_BIT (bmap[bb], indx);
+ SET_BIT (bmap[bb->index], indx);
else
- RESET_BIT (bmap[bb], indx);
+ RESET_BIT (bmap[bb->index], indx);
break;
}
list_entry = XEXP (list_entry, 1);
@@ -3877,7 +3845,7 @@ compute_transp (x, indx, bmap, set_p)
static void
compute_cprop_data ()
{
- compute_local_properties (cprop_absaltered, cprop_pavloc, NULL, 1);
+ compute_local_properties (cprop_absaltered, cprop_pavloc, NULL, &set_hash_table);
compute_available (cprop_pavloc, cprop_absaltered,
cprop_avout, cprop_avin);
}
@@ -3951,7 +3919,7 @@ find_used_regs (xptr, data)
}
/* Try to replace all non-SET_DEST occurrences of FROM in INSN with TO.
- Returns non-zero is successful. */
+ Returns nonzero is successful. */
static int
try_replace_reg (from, to, insn)
@@ -3962,24 +3930,35 @@ try_replace_reg (from, to, insn)
int success = 0;
rtx set = single_set (insn);
- success = validate_replace_src (from, to, insn);
+ validate_replace_src_group (from, to, insn);
+ if (num_changes_pending () && apply_change_group ())
+ success = 1;
- /* If above failed and this is a single set, try to simplify the source of
- the set given our substitution. We could perhaps try this for multiple
- SETs, but it probably won't buy us anything. */
- if (!success && set != 0)
+ /* Try to simplify SET_SRC if we have substituted a constant. */
+ if (success && set && CONSTANT_P (to))
{
+ src = simplify_rtx (SET_SRC (set));
+
+ if (src)
+ validate_change (insn, &SET_SRC (set), src, 0);
+ }
+
+ if (!success && set && reg_mentioned_p (from, SET_SRC (set)))
+ {
+ /* If above failed and this is a single set, try to simplify the source of
+ the set given our substitution. We could perhaps try this for multiple
+ SETs, but it probably won't buy us anything. */
src = simplify_replace_rtx (SET_SRC (set), from, to);
if (!rtx_equal_p (src, SET_SRC (set))
&& validate_change (insn, &SET_SRC (set), src, 0))
success = 1;
- }
- /* If we've failed to do replacement, have a single SET, and don't already
- have a note, add a REG_EQUAL note to not lose information. */
- if (!success && note == 0 && set != 0)
- note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (src));
+ /* If we've failed to do replacement, have a single SET, and don't already
+ have a note, add a REG_EQUAL note to not lose information. */
+ if (!success && note == 0 && set != 0)
+ note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (src));
+ }
/* If there is already a NOTE, update the expression in it with our
replacement. */
@@ -4007,7 +3986,7 @@ find_avail_set (regno, insn)
/* SET1 contains the last set found that can be returned to the caller for
use in a substitution. */
struct expr *set1 = 0;
-
+
/* Loops are not possible here. To get a loop we would need two sets
available at the start of the block containing INSN. ie we would
need two sets like this available at the start of the block:
@@ -4020,7 +3999,7 @@ find_avail_set (regno, insn)
while (1)
{
rtx src;
- struct expr *set = lookup_set (regno, NULL_RTX);
+ struct expr *set = lookup_set (regno, NULL_RTX, &set_hash_table);
/* Find a set that is available at the start of the block
which contains INSN. */
@@ -4034,7 +4013,7 @@ find_avail_set (regno, insn)
/* If no available set was found we've reached the end of the
(possibly empty) copy chain. */
if (set == 0)
- break;
+ break;
if (GET_CODE (set->expr) != SET)
abort ();
@@ -4043,7 +4022,7 @@ find_avail_set (regno, insn)
/* We know the set is available.
Now check that SRC is ANTLOC (i.e. none of the source operands
- have changed since the start of the block).
+ have changed since the start of the block).
If the source operand changed, we may still use it for the next
iteration of this loop, but we may not use it for substitutions. */
@@ -4067,48 +4046,78 @@ find_avail_set (regno, insn)
}
/* Subroutine of cprop_insn that tries to propagate constants into
- JUMP_INSNS. INSN must be a conditional jump. FROM is what we will try to
- replace, SRC is the constant we will try to substitute for it. Returns
- nonzero if a change was made. We know INSN has just a SET. */
+ JUMP_INSNS. JUMP must be a conditional jump. If SETCC is non-NULL
+ it is the instruction that immediately preceeds JUMP, and must be a
+ single SET of a register. FROM is what we will try to replace,
+ SRC is the constant we will try to substitute for it. Returns nonzero
+ if a change was made. */
static int
-cprop_jump (bb, insn, from, src)
- rtx insn;
+cprop_jump (bb, setcc, jump, from, src)
+ basic_block bb;
+ rtx setcc;
+ rtx jump;
rtx from;
rtx src;
- basic_block bb;
{
- rtx set = PATTERN (insn);
- rtx new = simplify_replace_rtx (SET_SRC (set), from, src);
+ rtx new, new_set;
+ rtx set = pc_set (jump);
+
+ /* First substitute in the INSN condition as the SET_SRC of the JUMP,
+ then substitute that given values in this expanded JUMP. */
+ if (setcc != NULL
+ && !modified_between_p (from, setcc, jump)
+ && !modified_between_p (src, setcc, jump))
+ {
+ rtx setcc_set = single_set (setcc);
+ new_set = simplify_replace_rtx (SET_SRC (set),
+ SET_DEST (setcc_set),
+ SET_SRC (setcc_set));
+ }
+ else
+ new_set = set;
+
+ new = simplify_replace_rtx (new_set, from, src);
/* If no simplification can be made, then try the next
register. */
- if (rtx_equal_p (new, SET_SRC (set)))
+ if (rtx_equal_p (new, new_set) || rtx_equal_p (new, SET_SRC (set)))
return 0;
-
+
/* If this is now a no-op delete it, otherwise this must be a valid insn. */
if (new == pc_rtx)
- delete_insn (insn);
+ delete_insn (jump);
else
{
- if (! validate_change (insn, &SET_SRC (set), new, 0))
+ /* Ensure the value computed inside the jump insn to be equivalent
+ to one computed by setcc. */
+ if (setcc
+ && modified_in_p (new, setcc))
+ return 0;
+ if (! validate_change (jump, &SET_SRC (set), new, 0))
return 0;
/* If this has turned into an unconditional jump,
then put a barrier after it so that the unreachable
code will be deleted. */
if (GET_CODE (SET_SRC (set)) == LABEL_REF)
- emit_barrier_after (insn);
+ emit_barrier_after (jump);
}
+#ifdef HAVE_cc0
+ /* Delete the cc0 setter. */
+ if (setcc != NULL && CC0_P (SET_DEST (single_set (setcc))))
+ delete_insn (setcc);
+#endif
+
run_jump_opt_after_gcse = 1;
const_prop_count++;
if (gcse_file != NULL)
{
fprintf (gcse_file,
- "CONST-PROP: Replacing reg %d in insn %d with constant ",
- REGNO (from), INSN_UID (insn));
+ "CONST-PROP: Replacing reg %d in jump_insn %d with constant ",
+ REGNO (from), INSN_UID (jump));
print_rtl (gcse_file, src);
fprintf (gcse_file, "\n");
}
@@ -4117,43 +4126,49 @@ cprop_jump (bb, insn, from, src)
return 1;
}
-#ifdef HAVE_cc0
-
-/* Subroutine of cprop_insn that tries to propagate constants into JUMP_INSNS
- for machines that have CC0. INSN is a single set that stores into CC0;
- the insn following it is a conditional jump. REG_USED is the use we will
- try to replace, SRC is the constant we will try to substitute for it.
- Returns nonzero if a change was made. */
-
-static int
-cprop_cc0_jump (bb, insn, reg_used, src)
- basic_block bb;
+static bool
+constprop_register (insn, from, to, alter_jumps)
rtx insn;
- struct reg_use *reg_used;
- rtx src;
+ rtx from;
+ rtx to;
+ int alter_jumps;
{
- /* First substitute in the SET_SRC of INSN, then substitute that for
- CC0 in JUMP. */
- rtx jump = NEXT_INSN (insn);
- rtx new_src = simplify_replace_rtx (SET_SRC (PATTERN (insn)),
- reg_used->reg_rtx, src);
+ rtx sset;
- if (! cprop_jump (bb, jump, cc0_rtx, new_src))
- return 0;
+ /* Check for reg or cc0 setting instructions followed by
+ conditional branch instructions first. */
+ if (alter_jumps
+ && (sset = single_set (insn)) != NULL
+ && NEXT_INSN (insn)
+ && any_condjump_p (NEXT_INSN (insn)) && onlyjump_p (NEXT_INSN (insn)))
+ {
+ rtx dest = SET_DEST (sset);
+ if ((REG_P (dest) || CC0_P (dest))
+ && cprop_jump (BLOCK_FOR_INSN (insn), insn, NEXT_INSN (insn), from, to))
+ return 1;
+ }
+
+ /* Handle normal insns next. */
+ if (GET_CODE (insn) == INSN
+ && try_replace_reg (from, to, insn))
+ return 1;
- /* If we succeeded, delete the cc0 setter. */
- delete_insn (insn);
+ /* Try to propagate a CONST_INT into a conditional jump.
+ We're pretty specific about what we will handle in this
+ code, we can extend this as necessary over time.
- return 1;
+ Right now the insn in question must look like
+ (set (pc) (if_then_else ...)) */
+ else if (alter_jumps && any_condjump_p (insn) && onlyjump_p (insn))
+ return cprop_jump (BLOCK_FOR_INSN (insn), NULL, insn, from, to);
+ return 0;
}
-#endif
-
+
/* Perform constant and copy propagation on INSN.
- The result is non-zero if a change was made. */
+ The result is nonzero if a change was made. */
static int
-cprop_insn (bb, insn, alter_jumps)
- basic_block bb;
+cprop_insn (insn, alter_jumps)
rtx insn;
int alter_jumps;
{
@@ -4166,7 +4181,7 @@ cprop_insn (bb, insn, alter_jumps)
reg_use_count = 0;
note_uses (&PATTERN (insn), find_used_regs, NULL);
-
+
note = find_reg_equal_equiv_note (insn);
/* We may win even when propagating constants into notes. */
@@ -4195,7 +4210,7 @@ cprop_insn (bb, insn, alter_jumps)
set = find_avail_set (regno, insn);
if (! set)
continue;
-
+
pat = set->expr;
/* ??? We might be able to handle PARALLELs. Later. */
if (GET_CODE (pat) != SET)
@@ -4206,53 +4221,18 @@ cprop_insn (bb, insn, alter_jumps)
/* Constant propagation. */
if (CONSTANT_P (src))
{
- /* Handle normal insns first. */
- if (GET_CODE (insn) == INSN
- && try_replace_reg (reg_used->reg_rtx, src, insn))
+ if (constprop_register (insn, reg_used->reg_rtx, src, alter_jumps))
{
changed = 1;
const_prop_count++;
if (gcse_file != NULL)
{
- fprintf (gcse_file, "CONST-PROP: Replacing reg %d in ",
- regno);
- fprintf (gcse_file, "insn %d with constant ",
- INSN_UID (insn));
+ fprintf (gcse_file, "GLOBAL CONST-PROP: Replacing reg %d in ", regno);
+ fprintf (gcse_file, "insn %d with constant ", INSN_UID (insn));
print_rtl (gcse_file, src);
fprintf (gcse_file, "\n");
}
-
- /* The original insn setting reg_used may or may not now be
- deletable. We leave the deletion to flow. */
- }
-
- /* Try to propagate a CONST_INT into a conditional jump.
- We're pretty specific about what we will handle in this
- code, we can extend this as necessary over time.
-
- Right now the insn in question must look like
- (set (pc) (if_then_else ...)) */
- else if (alter_jumps
- && GET_CODE (insn) == JUMP_INSN
- && condjump_p (insn)
- && ! simplejump_p (insn))
- changed |= cprop_jump (bb, insn, reg_used->reg_rtx, src);
-
-#ifdef HAVE_cc0
- /* Similar code for machines that use a pair of CC0 setter and
- conditional jump insn. */
- else if (alter_jumps
- && GET_CODE (PATTERN (insn)) == SET
- && SET_DEST (PATTERN (insn)) == cc0_rtx
- && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
- && condjump_p (NEXT_INSN (insn))
- && ! simplejump_p (NEXT_INSN (insn))
- && cprop_cc0_jump (bb, insn, reg_used, src))
- {
- changed = 1;
- break;
}
-#endif
}
else if (GET_CODE (src) == REG
&& REGNO (src) >= FIRST_PSEUDO_REGISTER
@@ -4264,7 +4244,7 @@ cprop_insn (bb, insn, alter_jumps)
copy_prop_count++;
if (gcse_file != NULL)
{
- fprintf (gcse_file, "COPY-PROP: Replacing reg %d in insn %d",
+ fprintf (gcse_file, "GLOBAL COPY-PROP: Replacing reg %d in insn %d",
regno, INSN_UID (insn));
fprintf (gcse_file, " with reg %d\n", REGNO (src));
}
@@ -4281,31 +4261,267 @@ cprop_insn (bb, insn, alter_jumps)
return changed;
}
+/* Like find_used_regs, but avoid recording uses that appear in
+ input-output contexts such as zero_extract or pre_dec. This
+ restricts the cases we consider to those for which local cprop
+ can legitimately make replacements. */
+
+static void
+local_cprop_find_used_regs (xptr, data)
+ rtx *xptr;
+ void *data;
+{
+ rtx x = *xptr;
+
+ if (x == 0)
+ return;
+
+ switch (GET_CODE (x))
+ {
+ case ZERO_EXTRACT:
+ case SIGN_EXTRACT:
+ case STRICT_LOW_PART:
+ return;
+
+ case PRE_DEC:
+ case PRE_INC:
+ case POST_DEC:
+ case POST_INC:
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ /* Can only legitimately appear this early in the context of
+ stack pushes for function arguments, but handle all of the
+ codes nonetheless. */
+ return;
+
+ case SUBREG:
+ /* Setting a subreg of a register larger than word_mode leaves
+ the non-written words unchanged. */
+ if (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) > BITS_PER_WORD)
+ return;
+ break;
+
+ default:
+ break;
+ }
+
+ find_used_regs (xptr, data);
+}
+
+/* LIBCALL_SP is a zero-terminated array of insns at the end of a libcall;
+ their REG_EQUAL notes need updating. */
+
+static bool
+do_local_cprop (x, insn, alter_jumps, libcall_sp)
+ rtx x;
+ rtx insn;
+ int alter_jumps;
+ rtx *libcall_sp;
+{
+ rtx newreg = NULL, newcnst = NULL;
+
+ /* Rule out USE instructions and ASM statements as we don't want to
+ change the hard registers mentioned. */
+ if (GET_CODE (x) == REG
+ && (REGNO (x) >= FIRST_PSEUDO_REGISTER
+ || (GET_CODE (PATTERN (insn)) != USE
+ && asm_noperands (PATTERN (insn)) < 0)))
+ {
+ cselib_val *val = cselib_lookup (x, GET_MODE (x), 0);
+ struct elt_loc_list *l;
+
+ if (!val)
+ return false;
+ for (l = val->locs; l; l = l->next)
+ {
+ rtx this_rtx = l->loc;
+ rtx note;
+
+ if (l->in_libcall)
+ continue;
+
+ if (CONSTANT_P (this_rtx))
+ newcnst = this_rtx;
+ if (REG_P (this_rtx) && REGNO (this_rtx) >= FIRST_PSEUDO_REGISTER
+ /* Don't copy propagate if it has attached REG_EQUIV note.
+ At this point this only function parameters should have
+ REG_EQUIV notes and if the argument slot is used somewhere
+ explicitly, it means address of parameter has been taken,
+ so we should not extend the lifetime of the pseudo. */
+ && (!(note = find_reg_note (l->setting_insn, REG_EQUIV, NULL_RTX))
+ || GET_CODE (XEXP (note, 0)) != MEM))
+ newreg = this_rtx;
+ }
+ if (newcnst && constprop_register (insn, x, newcnst, alter_jumps))
+ {
+ /* If we find a case where we can't fix the retval REG_EQUAL notes
+ match the new register, we either have to abandom this replacement
+ or fix delete_trivially_dead_insns to preserve the setting insn,
+ or make it delete the REG_EUAQL note, and fix up all passes that
+ require the REG_EQUAL note there. */
+ if (!adjust_libcall_notes (x, newcnst, insn, libcall_sp))
+ abort ();
+ if (gcse_file != NULL)
+ {
+ fprintf (gcse_file, "LOCAL CONST-PROP: Replacing reg %d in ",
+ REGNO (x));
+ fprintf (gcse_file, "insn %d with constant ",
+ INSN_UID (insn));
+ print_rtl (gcse_file, newcnst);
+ fprintf (gcse_file, "\n");
+ }
+ const_prop_count++;
+ return true;
+ }
+ else if (newreg && newreg != x && try_replace_reg (x, newreg, insn))
+ {
+ adjust_libcall_notes (x, newreg, insn, libcall_sp);
+ if (gcse_file != NULL)
+ {
+ fprintf (gcse_file,
+ "LOCAL COPY-PROP: Replacing reg %d in insn %d",
+ REGNO (x), INSN_UID (insn));
+ fprintf (gcse_file, " with reg %d\n", REGNO (newreg));
+ }
+ copy_prop_count++;
+ return true;
+ }
+ }
+ return false;
+}
+
+/* LIBCALL_SP is a zero-terminated array of insns at the end of a libcall;
+ their REG_EQUAL notes need updating to reflect that OLDREG has been
+ replaced with NEWVAL in INSN. Return true if all substitutions could
+ be made. */
+static bool
+adjust_libcall_notes (oldreg, newval, insn, libcall_sp)
+ rtx oldreg, newval, insn, *libcall_sp;
+{
+ rtx end;
+
+ while ((end = *libcall_sp++))
+ {
+ rtx note = find_reg_equal_equiv_note (end);
+
+ if (! note)
+ continue;
+
+ if (REG_P (newval))
+ {
+ if (reg_set_between_p (newval, PREV_INSN (insn), end))
+ {
+ do
+ {
+ note = find_reg_equal_equiv_note (end);
+ if (! note)
+ continue;
+ if (reg_mentioned_p (newval, XEXP (note, 0)))
+ return false;
+ }
+ while ((end = *libcall_sp++));
+ return true;
+ }
+ }
+ XEXP (note, 0) = replace_rtx (XEXP (note, 0), oldreg, newval);
+ insn = end;
+ }
+ return true;
+}
+
+#define MAX_NESTED_LIBCALLS 9
+
+static void
+local_cprop_pass (alter_jumps)
+ int alter_jumps;
+{
+ rtx insn;
+ struct reg_use *reg_used;
+ rtx libcall_stack[MAX_NESTED_LIBCALLS + 1], *libcall_sp;
+ bool changed = false;
+
+ cselib_init ();
+ libcall_sp = &libcall_stack[MAX_NESTED_LIBCALLS];
+ *libcall_sp = 0;
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ if (INSN_P (insn))
+ {
+ rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
+
+ if (note)
+ {
+ if (libcall_sp == libcall_stack)
+ abort ();
+ *--libcall_sp = XEXP (note, 0);
+ }
+ note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
+ if (note)
+ libcall_sp++;
+ note = find_reg_equal_equiv_note (insn);
+ do
+ {
+ reg_use_count = 0;
+ note_uses (&PATTERN (insn), local_cprop_find_used_regs, NULL);
+ if (note)
+ local_cprop_find_used_regs (&XEXP (note, 0), NULL);
+
+ for (reg_used = &reg_use_table[0]; reg_use_count > 0;
+ reg_used++, reg_use_count--)
+ if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps,
+ libcall_sp))
+ {
+ changed = true;
+ break;
+ }
+ }
+ while (reg_use_count);
+ }
+ cselib_process_insn (insn);
+ }
+ cselib_finish ();
+ /* Global analysis may get into infinite loops for unreachable blocks. */
+ if (changed && alter_jumps)
+ {
+ delete_unreachable_blocks ();
+ free_reg_set_mem ();
+ alloc_reg_set_mem (max_reg_num ());
+ compute_sets (get_insns ());
+ }
+}
+
/* Forward propagate copies. This includes copies and constants. Return
- non-zero if a change was made. */
+ nonzero if a change was made. */
static int
cprop (alter_jumps)
int alter_jumps;
{
- int bb, changed;
+ int changed;
+ basic_block bb;
rtx insn;
/* Note we start at block 1. */
+ if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
+ {
+ if (gcse_file != NULL)
+ fprintf (gcse_file, "\n");
+ return 0;
+ }
changed = 0;
- for (bb = 1; bb < n_basic_blocks; bb++)
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb, EXIT_BLOCK_PTR, next_bb)
{
/* Reset tables used to keep track of what's still valid [since the
start of the block]. */
reset_opr_set_tables ();
- for (insn = BLOCK_HEAD (bb);
- insn != NULL && insn != NEXT_INSN (BLOCK_END (bb));
+ for (insn = bb->head;
+ insn != NULL && insn != NEXT_INSN (bb->end);
insn = NEXT_INSN (insn))
if (INSN_P (insn))
{
- changed |= cprop_insn (BASIC_BLOCK (bb), insn, alter_jumps);
+ changed |= cprop_insn (insn, alter_jumps);
/* Keep track of everything modified by this insn. */
/* ??? Need to be careful w.r.t. mods done to INSN. Don't
@@ -4335,20 +4551,23 @@ one_cprop_pass (pass, alter_jumps)
const_prop_count = 0;
copy_prop_count = 0;
- alloc_set_hash_table (max_cuid);
- compute_set_hash_table ();
+ local_cprop_pass (alter_jumps);
+
+ alloc_hash_table (max_cuid, &set_hash_table, 1);
+ compute_hash_table (&set_hash_table);
if (gcse_file)
- dump_hash_table (gcse_file, "SET", set_hash_table, set_hash_table_size,
- n_sets);
- if (n_sets > 0)
+ dump_hash_table (gcse_file, "SET", &set_hash_table);
+ if (set_hash_table.n_elems > 0)
{
- alloc_cprop_mem (n_basic_blocks, n_sets);
+ alloc_cprop_mem (last_basic_block, set_hash_table.n_elems);
compute_cprop_data ();
changed = cprop (alter_jumps);
+ if (alter_jumps)
+ changed |= bypass_conditional_jumps ();
free_cprop_mem ();
}
- free_set_hash_table ();
+ free_hash_table (&set_hash_table);
if (gcse_file)
{
@@ -4357,6 +4576,251 @@ one_cprop_pass (pass, alter_jumps)
fprintf (gcse_file, "%d const props, %d copy props\n\n",
const_prop_count, copy_prop_count);
}
+ /* Global analysis may get into infinite loops for unreachable blocks. */
+ if (changed && alter_jumps)
+ delete_unreachable_blocks ();
+
+ return changed;
+}
+
+/* Bypass conditional jumps. */
+
+/* Find a set of REGNO to a constant that is available at the end of basic
+ block BB. Returns NULL if no such set is found. Based heavily upon
+ find_avail_set. */
+
+static struct expr *
+find_bypass_set (regno, bb)
+ int regno;
+ int bb;
+{
+ struct expr *result = 0;
+
+ for (;;)
+ {
+ rtx src;
+ struct expr *set = lookup_set (regno, NULL_RTX, &set_hash_table);
+
+ while (set)
+ {
+ if (TEST_BIT (cprop_avout[bb], set->bitmap_index))
+ break;
+ set = next_set (regno, set);
+ }
+
+ if (set == 0)
+ break;
+
+ if (GET_CODE (set->expr) != SET)
+ abort ();
+
+ src = SET_SRC (set->expr);
+ if (CONSTANT_P (src))
+ result = set;
+
+ if (GET_CODE (src) != REG)
+ break;
+
+ regno = REGNO (src);
+ }
+ return result;
+}
+
+
+/* Subroutine of bypass_block that checks whether a pseudo is killed by
+ any of the instructions inserted on an edge. Jump bypassing places
+ condition code setters on CFG edges using insert_insn_on_edge. This
+ function is required to check that our data flow analysis is still
+ valid prior to commit_edge_insertions. */
+
+static bool
+reg_killed_on_edge (reg, e)
+ rtx reg;
+ edge e;
+{
+ rtx insn;
+
+ for (insn = e->insns; insn; insn = NEXT_INSN (insn))
+ if (INSN_P (insn) && reg_set_p (reg, insn))
+ return true;
+
+ return false;
+}
+
+/* Subroutine of bypass_conditional_jumps that attempts to bypass the given
+ basic block BB which has more than one predecessor. If not NULL, SETCC
+ is the first instruction of BB, which is immediately followed by JUMP_INSN
+ JUMP. Otherwise, SETCC is NULL, and JUMP is the first insn of BB.
+ Returns nonzero if a change was made.
+
+ During the jump bypassing pass, we may place copies of SETCC instuctions
+ on CFG edges. The following routine must be careful to pay attention to
+ these inserted insns when performing its transformations. */
+
+static int
+bypass_block (bb, setcc, jump)
+ basic_block bb;
+ rtx setcc, jump;
+{
+ rtx insn, note;
+ edge e, enext, edest;
+ int i, change;
+
+ insn = (setcc != NULL) ? setcc : jump;
+
+ /* Determine set of register uses in INSN. */
+ reg_use_count = 0;
+ note_uses (&PATTERN (insn), find_used_regs, NULL);
+ note = find_reg_equal_equiv_note (insn);
+ if (note)
+ find_used_regs (&XEXP (note, 0), NULL);
+
+ change = 0;
+ for (e = bb->pred; e; e = enext)
+ {
+ enext = e->pred_next;
+ for (i = 0; i < reg_use_count; i++)
+ {
+ struct reg_use *reg_used = &reg_use_table[i];
+ unsigned int regno = REGNO (reg_used->reg_rtx);
+ basic_block dest, old_dest;
+ struct expr *set;
+ rtx src, new;
+
+ if (regno >= max_gcse_regno)
+ continue;
+
+ set = find_bypass_set (regno, e->src->index);
+
+ if (! set)
+ continue;
+
+ /* Check the data flow is valid after edge insertions. */
+ if (e->insns && reg_killed_on_edge (reg_used->reg_rtx, e))
+ continue;
+
+ src = SET_SRC (pc_set (jump));
+
+ if (setcc != NULL)
+ src = simplify_replace_rtx (src,
+ SET_DEST (PATTERN (setcc)),
+ SET_SRC (PATTERN (setcc)));
+
+ new = simplify_replace_rtx (src, reg_used->reg_rtx,
+ SET_SRC (set->expr));
+
+ /* Jump bypassing may have already placed instructions on
+ edges of the CFG. We can't bypass an outgoing edge that
+ has instructions associated with it, as these insns won't
+ get executed if the incoming edge is redirected. */
+
+ if (new == pc_rtx)
+ {
+ edest = FALLTHRU_EDGE (bb);
+ dest = edest->insns ? NULL : edest->dest;
+ }
+ else if (GET_CODE (new) == LABEL_REF)
+ {
+ dest = BLOCK_FOR_INSN (XEXP (new, 0));
+ /* Don't bypass edges containing instructions. */
+ for (edest = bb->succ; edest; edest = edest->succ_next)
+ if (edest->dest == dest && edest->insns)
+ {
+ dest = NULL;
+ break;
+ }
+ }
+ else
+ dest = NULL;
+
+ /* Once basic block indices are stable, we should be able
+ to use redirect_edge_and_branch_force instead. */
+ old_dest = e->dest;
+ if (dest != NULL && dest != old_dest
+ && redirect_edge_and_branch (e, dest))
+ {
+ /* Copy the register setter to the redirected edge.
+ Don't copy CC0 setters, as CC0 is dead after jump. */
+ if (setcc)
+ {
+ rtx pat = PATTERN (setcc);
+ if (!CC0_P (SET_DEST (pat)))
+ insert_insn_on_edge (copy_insn (pat), e);
+ }
+
+ if (gcse_file != NULL)
+ {
+ fprintf (gcse_file, "JUMP-BYPASS: Proved reg %d in jump_insn %d equals constant ",
+ regno, INSN_UID (jump));
+ print_rtl (gcse_file, SET_SRC (set->expr));
+ fprintf (gcse_file, "\nBypass edge from %d->%d to %d\n",
+ e->src->index, old_dest->index, dest->index);
+ }
+ change = 1;
+ break;
+ }
+ }
+ }
+ return change;
+}
+
+/* Find basic blocks with more than one predecessor that only contain a
+ single conditional jump. If the result of the comparison is known at
+ compile-time from any incoming edge, redirect that edge to the
+ appropriate target. Returns nonzero if a change was made. */
+
+static int
+bypass_conditional_jumps ()
+{
+ basic_block bb;
+ int changed;
+ rtx setcc;
+ rtx insn;
+ rtx dest;
+
+ /* Note we start at block 1. */
+ if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
+ return 0;
+
+ changed = 0;
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb,
+ EXIT_BLOCK_PTR, next_bb)
+ {
+ /* Check for more than one predecessor. */
+ if (bb->pred && bb->pred->pred_next)
+ {
+ setcc = NULL_RTX;
+ for (insn = bb->head;
+ insn != NULL && insn != NEXT_INSN (bb->end);
+ insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == INSN)
+ {
+ if (setcc)
+ break;
+ if (GET_CODE (PATTERN (insn)) != SET)
+ break;
+
+ dest = SET_DEST (PATTERN (insn));
+ if (REG_P (dest) || CC0_P (dest))
+ setcc = insn;
+ else
+ break;
+ }
+ else if (GET_CODE (insn) == JUMP_INSN)
+ {
+ if (any_condjump_p (insn) && onlyjump_p (insn))
+ changed |= bypass_block (bb, setcc, insn);
+ break;
+ }
+ else if (INSN_P (insn))
+ break;
+ }
+ }
+
+ /* If we bypassed any register setting insns, we inserted a
+ copy on the redirected edge. These need to be commited. */
+ if (changed)
+ commit_edge_insertions();
return changed;
}
@@ -4452,19 +4916,19 @@ static void
compute_pre_data ()
{
sbitmap trapping_expr;
- int i;
+ basic_block bb;
unsigned int ui;
- compute_local_properties (transp, comp, antloc, 0);
- sbitmap_vector_zero (ae_kill, n_basic_blocks);
+ compute_local_properties (transp, comp, antloc, &expr_hash_table);
+ sbitmap_vector_zero (ae_kill, last_basic_block);
/* Collect expressions which might trap. */
- trapping_expr = sbitmap_alloc (n_exprs);
+ trapping_expr = sbitmap_alloc (expr_hash_table.n_elems);
sbitmap_zero (trapping_expr);
- for (ui = 0; ui < expr_hash_table_size; ui++)
+ for (ui = 0; ui < expr_hash_table.size; ui++)
{
struct expr *e;
- for (e = expr_hash_table[ui]; e != NULL; e = e->next_same_hash)
+ for (e = expr_hash_table.table[ui]; e != NULL; e = e->next_same_hash)
if (may_trap_p (e->expr))
SET_BIT (trapping_expr, e->bitmap_index);
}
@@ -4475,7 +4939,7 @@ compute_pre_data ()
This is significantly faster than compute_ae_kill. */
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
edge e;
@@ -4483,30 +4947,30 @@ compute_pre_data ()
kill all trapping expressions because we won't be able to properly
place the instruction on the edge. So make them neither
anticipatable nor transparent. This is fairly conservative. */
- for (e = BASIC_BLOCK (i)->pred; e ; e = e->pred_next)
+ for (e = bb->pred; e ; e = e->pred_next)
if (e->flags & EDGE_ABNORMAL)
{
- sbitmap_difference (antloc[i], antloc[i], trapping_expr);
- sbitmap_difference (transp[i], transp[i], trapping_expr);
+ sbitmap_difference (antloc[bb->index], antloc[bb->index], trapping_expr);
+ sbitmap_difference (transp[bb->index], transp[bb->index], trapping_expr);
break;
}
- sbitmap_a_or_b (ae_kill[i], transp[i], comp[i]);
- sbitmap_not (ae_kill[i], ae_kill[i]);
+ sbitmap_a_or_b (ae_kill[bb->index], transp[bb->index], comp[bb->index]);
+ sbitmap_not (ae_kill[bb->index], ae_kill[bb->index]);
}
- edge_list = pre_edge_lcm (gcse_file, n_exprs, transp, comp, antloc,
+ edge_list = pre_edge_lcm (gcse_file, expr_hash_table.n_elems, transp, comp, antloc,
ae_kill, &pre_insert_map, &pre_delete_map);
sbitmap_vector_free (antloc);
antloc = NULL;
sbitmap_vector_free (ae_kill);
- ae_kill = NULL;
+ ae_kill = NULL;
sbitmap_free (trapping_expr);
}
/* PRE utilities */
-/* Return non-zero if an occurrence of expression EXPR in OCCR_BB would reach
+/* Return nonzero if an occurrence of expression EXPR in OCCR_BB would reach
block BB.
VISITED is a pointer to a working buffer for tracking which BB's have
@@ -4575,7 +5039,7 @@ pre_expr_reaches_here_p (occr_bb, expr, bb)
basic_block bb;
{
int rval;
- char *visited = (char *) xcalloc (n_basic_blocks, 1);
+ char *visited = (char *) xcalloc (last_basic_block, 1);
rval = pre_expr_reaches_here_p_work (occr_bb, expr, bb, visited);
@@ -4585,7 +5049,7 @@ pre_expr_reaches_here_p (occr_bb, expr, bb)
/* Given an expr, generate RTL which we can insert at the end of a BB,
- or on an edge. Set the block number of any insns generated to
+ or on an edge. Set the block number of any insns generated to
the value of BB. */
static rtx
@@ -4608,13 +5072,13 @@ process_insert_insn (expr)
expression to make sure we don't have any sharing issues. */
else if (insn_invalid_p (emit_insn (gen_rtx_SET (VOIDmode, reg, exp))))
abort ();
-
- pat = gen_sequence ();
+
+ pat = get_insns ();
end_sequence ();
return pat;
}
-
+
/* Add EXPR to the end of basic block BB.
This is used by both the PRE and code hoisting.
@@ -4633,10 +5097,15 @@ insert_insn_end_bb (expr, bb, pre)
rtx new_insn;
rtx reg = expr->reaching_reg;
int regno = REGNO (reg);
- rtx pat;
- int i;
+ rtx pat, pat_end;
pat = process_insert_insn (expr);
+ if (pat == NULL_RTX || ! INSN_P (pat))
+ abort ();
+
+ pat_end = pat;
+ while (NEXT_INSN (pat_end) != NULL_RTX)
+ pat_end = NEXT_INSN (pat_end);
/* If the last insn is a jump, insert EXPR in front [taking care to
handle cc0, etc. properly]. Similary we need to care trapping
@@ -4654,7 +5123,7 @@ insert_insn_end_bb (expr, bb, pre)
Check this. */
if (GET_CODE (insn) == INSN && pre
&& !TEST_BIT (antloc[bb->index], expr->bitmap_index)
- && !TEST_BIT (transp[bb->index], expr->bitmap_index))
+ && !TEST_BIT (transp[bb->index], expr->bitmap_index))
abort ();
/* If this is a jump table, then we can't insert stuff here. Since
@@ -4691,7 +5160,7 @@ insert_insn_end_bb (expr, bb, pre)
/* Keeping in mind SMALL_REGISTER_CLASSES and parameters in registers,
we search backward and place the instructions before the first
parameter is loaded. Do this for everyone for consistency and a
- presumtion that we'll get better code elsewhere as well.
+ presumtion that we'll get better code elsewhere as well.
It should always be the case that we can put these instructions
anywhere in the basic block with performing PRE optimizations.
@@ -4699,7 +5168,7 @@ insert_insn_end_bb (expr, bb, pre)
if (pre
&& !TEST_BIT (antloc[bb->index], expr->bitmap_index)
- && !TEST_BIT (transp[bb->index], expr->bitmap_index))
+ && !TEST_BIT (transp[bb->index], expr->bitmap_index))
abort ();
/* Since different machines initialize their parameter registers
@@ -4724,26 +5193,16 @@ insert_insn_end_bb (expr, bb, pre)
else
new_insn = emit_insn_after (pat, insn);
- /* Keep block number table up to date.
- Note, PAT could be a multiple insn sequence, we have to make
- sure that each insn in the sequence is handled. */
- if (GET_CODE (pat) == SEQUENCE)
+ while (1)
{
- for (i = 0; i < XVECLEN (pat, 0); i++)
+ if (INSN_P (pat))
{
- rtx insn = XVECEXP (pat, 0, i);
- if (INSN_P (insn))
- add_label_notes (PATTERN (insn), new_insn);
-
- note_stores (PATTERN (insn), record_set_info, insn);
+ add_label_notes (PATTERN (pat), new_insn);
+ note_stores (PATTERN (pat), record_set_info, pat);
}
- }
- else
- {
- add_label_notes (pat, new_insn);
-
- /* Keep register set table up to date. */
- record_one_set (regno, new_insn);
+ if (pat == pat_end)
+ break;
+ pat = NEXT_INSN (pat);
}
gcse_create_count++;
@@ -4773,7 +5232,7 @@ pre_edge_insert (edge_list, index_map)
set_size = pre_insert_map[0]->size;
num_edges = NUM_EDGES (edge_list);
- inserted = sbitmap_vector_alloc (num_edges, n_exprs);
+ inserted = sbitmap_vector_alloc (num_edges, expr_hash_table.n_elems);
sbitmap_vector_zero (inserted, num_edges);
for (e = 0; e < num_edges; e++)
@@ -4785,7 +5244,7 @@ pre_edge_insert (edge_list, index_map)
{
SBITMAP_ELT_TYPE insert = pre_insert_map[e]->elms[i];
- for (j = indx; insert && j < n_exprs; j++, insert >>= 1)
+ for (j = indx; insert && j < (int) expr_hash_table.n_elems; j++, insert >>= 1)
if ((insert & 1) != 0 && index_map[j]->reaching_reg != NULL_RTX)
{
struct expr *expr = index_map[j];
@@ -4890,8 +5349,8 @@ pre_insert_copies ()
??? The current algorithm is rather brute force.
Need to do some profiling. */
- for (i = 0; i < expr_hash_table_size; i++)
- for (expr = expr_hash_table[i]; expr != NULL; expr = expr->next_same_hash)
+ for (i = 0; i < expr_hash_table.size; i++)
+ for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
{
/* If the basic block isn't reachable, PPOUT will be TRUE. However,
we don't want to insert a copy here because the expression may not
@@ -4919,7 +5378,7 @@ pre_insert_copies ()
continue;
/* Or if the expression doesn't reach the deleted one. */
- if (! pre_expr_reaches_here_p (BLOCK_FOR_INSN (avail->insn),
+ if (! pre_expr_reaches_here_p (BLOCK_FOR_INSN (avail->insn),
expr,
BLOCK_FOR_INSN (occr->insn)))
continue;
@@ -4932,12 +5391,42 @@ pre_insert_copies ()
}
}
+/* Emit move from SRC to DEST noting the equivalence with expression computed
+ in INSN. */
+static rtx
+gcse_emit_move_after (src, dest, insn)
+ rtx src, dest, insn;
+{
+ rtx new;
+ rtx set = single_set (insn), set2;
+ rtx note;
+ rtx eqv;
+
+ /* This should never fail since we're creating a reg->reg copy
+ we've verified to be valid. */
+
+ new = emit_insn_after (gen_move_insn (dest, src), insn);
+
+ /* Note the equivalence for local CSE pass. */
+ set2 = single_set (new);
+ if (!set2 || !rtx_equal_p (SET_DEST (set2), dest))
+ return new;
+ if ((note = find_reg_equal_equiv_note (insn)))
+ eqv = XEXP (note, 0);
+ else
+ eqv = SET_SRC (set);
+
+ set_unique_reg_note (new, REG_EQUAL, copy_insn_1 (eqv));
+
+ return new;
+}
+
/* Delete redundant computations.
Deletion is done by changing the insn to copy the `reaching_reg' of
the expression into the result of the SET. It is left to later passes
(cprop, cse2, flow, combine, regmove) to propagate the copy or eliminate it.
- Returns non-zero if a change is made. */
+ Returns nonzero if a change is made. */
static int
pre_delete ()
@@ -4948,8 +5437,8 @@ pre_delete ()
struct occr *occr;
changed = 0;
- for (i = 0; i < expr_hash_table_size; i++)
- for (expr = expr_hash_table[i]; expr != NULL; expr = expr->next_same_hash)
+ for (i = 0; i < expr_hash_table.size; i++)
+ for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
{
int indx = expr->bitmap_index;
@@ -4975,21 +5464,12 @@ pre_delete ()
expr->reaching_reg
= gen_reg_rtx (GET_MODE (SET_DEST (set)));
- /* In theory this should never fail since we're creating
- a reg->reg copy.
-
- However, on the x86 some of the movXX patterns actually
- contain clobbers of scratch regs. This may cause the
- insn created by validate_change to not match any pattern
- and thus cause validate_change to fail. */
- if (validate_change (insn, &SET_SRC (set),
- expr->reaching_reg, 0))
- {
- occr->deleted_p = 1;
- SET_BIT (pre_redundant_insns, INSN_CUID (insn));
- changed = 1;
- gcse_subst_count++;
- }
+ gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
+ delete_insn (insn);
+ occr->deleted_p = 1;
+ SET_BIT (pre_redundant_insns, INSN_CUID (insn));
+ changed = 1;
+ gcse_subst_count++;
if (gcse_file)
{
@@ -5037,9 +5517,9 @@ pre_gcse ()
/* Compute a mapping from expression number (`bitmap_index') to
hash table entry. */
- index_map = (struct expr **) xcalloc (n_exprs, sizeof (struct expr *));
- for (i = 0; i < expr_hash_table_size; i++)
- for (expr = expr_hash_table[i]; expr != NULL; expr = expr->next_same_hash)
+ index_map = (struct expr **) xcalloc (expr_hash_table.n_elems, sizeof (struct expr *));
+ for (i = 0; i < expr_hash_table.size; i++)
+ for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
index_map[expr->bitmap_index] = expr;
/* Reset bitmap used to track which insns are redundant. */
@@ -5071,7 +5551,7 @@ pre_gcse ()
/* Top level routine to perform one PRE GCSE pass.
- Return non-zero if a change was made. */
+ Return nonzero if a change was made. */
static int
one_pre_gcse_pass (pass)
@@ -5082,20 +5562,19 @@ one_pre_gcse_pass (pass)
gcse_subst_count = 0;
gcse_create_count = 0;
- alloc_expr_hash_table (max_cuid);
+ alloc_hash_table (max_cuid, &expr_hash_table, 0);
add_noreturn_fake_exit_edges ();
if (flag_gcse_lm)
compute_ld_motion_mems ();
- compute_expr_hash_table ();
+ compute_hash_table (&expr_hash_table);
trim_ld_motion_mems ();
if (gcse_file)
- dump_hash_table (gcse_file, "Expression", expr_hash_table,
- expr_hash_table_size, n_exprs);
+ dump_hash_table (gcse_file, "Expression", &expr_hash_table);
- if (n_exprs > 0)
+ if (expr_hash_table.n_elems > 0)
{
- alloc_pre_mem (n_basic_blocks, n_exprs);
+ alloc_pre_mem (last_basic_block, expr_hash_table.n_elems);
compute_pre_data ();
changed |= pre_gcse ();
free_edge_list (edge_list);
@@ -5104,7 +5583,7 @@ one_pre_gcse_pass (pass)
free_ldst_mems ();
remove_fake_edges ();
- free_expr_hash_table ();
+ free_hash_table (&expr_hash_table);
if (gcse_file)
{
@@ -5149,7 +5628,7 @@ add_label_notes (x, insn)
REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, XEXP (x, 0),
REG_NOTES (insn));
if (LABEL_P (XEXP (x, 0)))
- LABEL_NUSES (XEXP (x, 0))++;
+ LABEL_NUSES (XEXP (x, 0))++;
return;
}
@@ -5179,32 +5658,32 @@ add_label_notes (x, insn)
static void
compute_transpout ()
{
- int bb;
+ basic_block bb;
unsigned int i;
struct expr *expr;
- sbitmap_vector_ones (transpout, n_basic_blocks);
+ sbitmap_vector_ones (transpout, last_basic_block);
- for (bb = 0; bb < n_basic_blocks; ++bb)
+ FOR_EACH_BB (bb)
{
/* Note that flow inserted a nop a the end of basic blocks that
end in call instructions for reasons other than abnormal
control flow. */
- if (GET_CODE (BLOCK_END (bb)) != CALL_INSN)
+ if (GET_CODE (bb->end) != CALL_INSN)
continue;
- for (i = 0; i < expr_hash_table_size; i++)
- for (expr = expr_hash_table[i]; expr ; expr = expr->next_same_hash)
+ for (i = 0; i < expr_hash_table.size; i++)
+ for (expr = expr_hash_table.table[i]; expr ; expr = expr->next_same_hash)
if (GET_CODE (expr->expr) == MEM)
{
if (GET_CODE (XEXP (expr->expr, 0)) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (XEXP (expr->expr, 0)))
continue;
-
+
/* ??? Optimally, we would use interprocedural alias
analysis to determine if this mem is actually killed
by this call. */
- RESET_BIT (transpout[bb], expr->bitmap_index);
+ RESET_BIT (transpout[bb->index], expr->bitmap_index);
}
}
}
@@ -5237,15 +5716,15 @@ invalidate_nonnull_info (x, setter, data)
regno = REGNO (x) - npi->min_reg;
- RESET_BIT (npi->nonnull_local[npi->current_block], regno);
- SET_BIT (npi->nonnull_killed[npi->current_block], regno);
+ RESET_BIT (npi->nonnull_local[npi->current_block->index], regno);
+ SET_BIT (npi->nonnull_killed[npi->current_block->index], regno);
}
/* Do null-pointer check elimination for the registers indicated in
NPI. NONNULL_AVIN and NONNULL_AVOUT are pre-allocated sbitmaps;
they are not our responsibility to free. */
-static void
+static int
delete_null_pointer_checks_1 (block_reg, nonnull_avin,
nonnull_avout, npi)
unsigned int *block_reg;
@@ -5253,11 +5732,11 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
sbitmap *nonnull_avout;
struct null_pointer_info *npi;
{
- int bb;
- int current_block;
+ basic_block bb, current_block;
sbitmap *nonnull_local = npi->nonnull_local;
sbitmap *nonnull_killed = npi->nonnull_killed;
-
+ int something_changed = 0;
+
/* Compute local properties, nonnull and killed. A register will have
the nonnull property if at the end of the current block its value is
known to be nonnull. The killed property indicates that somewhere in
@@ -5266,10 +5745,10 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
Note that a register can have both properties in a single block. That
indicates that it's killed, then later in the block a new value is
computed. */
- sbitmap_vector_zero (nonnull_local, n_basic_blocks);
- sbitmap_vector_zero (nonnull_killed, n_basic_blocks);
+ sbitmap_vector_zero (nonnull_local, last_basic_block);
+ sbitmap_vector_zero (nonnull_killed, last_basic_block);
- for (current_block = 0; current_block < n_basic_blocks; current_block++)
+ FOR_EACH_BB (current_block)
{
rtx insn, stop_insn;
@@ -5278,8 +5757,8 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
/* Scan each insn in the basic block looking for memory references and
register sets. */
- stop_insn = NEXT_INSN (BLOCK_END (current_block));
- for (insn = BLOCK_HEAD (current_block);
+ stop_insn = NEXT_INSN (current_block->end);
+ for (insn = current_block->head;
insn != stop_insn;
insn = NEXT_INSN (insn))
{
@@ -5307,7 +5786,7 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
&& GET_CODE ((reg = XEXP (SET_SRC (set), 0))) == REG
&& REGNO (reg) >= npi->min_reg
&& REGNO (reg) < npi->max_reg)
- SET_BIT (nonnull_local[current_block],
+ SET_BIT (nonnull_local[current_block->index],
REGNO (reg) - npi->min_reg);
/* Now invalidate stuff clobbered by this insn. */
@@ -5320,7 +5799,7 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
&& GET_CODE ((reg = XEXP (SET_DEST (set), 0))) == REG
&& REGNO (reg) >= npi->min_reg
&& REGNO (reg) < npi->max_reg)
- SET_BIT (nonnull_local[current_block],
+ SET_BIT (nonnull_local[current_block->index],
REGNO (reg) - npi->min_reg);
}
}
@@ -5332,17 +5811,17 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
/* Now look at each bb and see if it ends with a compare of a value
against zero. */
- for (bb = 0; bb < n_basic_blocks; bb++)
+ FOR_EACH_BB (bb)
{
- rtx last_insn = BLOCK_END (bb);
+ rtx last_insn = bb->end;
rtx condition, earliest;
int compare_and_branch;
/* Since MIN_REG is always at least FIRST_PSEUDO_REGISTER, and
since BLOCK_REG[BB] is zero if this block did not end with a
comparison against zero, this condition works. */
- if (block_reg[bb] < npi->min_reg
- || block_reg[bb] >= npi->max_reg)
+ if (block_reg[bb->index] < npi->min_reg
+ || block_reg[bb->index] >= npi->max_reg)
continue;
/* LAST_INSN is a conditional jump. Get its condition. */
@@ -5353,7 +5832,7 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
continue;
/* Is the register known to have a nonzero value? */
- if (!TEST_BIT (nonnull_avout[bb], block_reg[bb] - npi->min_reg))
+ if (!TEST_BIT (nonnull_avout[bb->index], block_reg[bb->index] - npi->min_reg))
continue;
/* Try to compute whether the compare/branch at the loop end is one or
@@ -5371,23 +5850,26 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
{
rtx new_jump;
- new_jump = emit_jump_insn_before (gen_jump (JUMP_LABEL (last_insn)),
- last_insn);
+ new_jump = emit_jump_insn_after (gen_jump (JUMP_LABEL (last_insn)),
+ last_insn);
JUMP_LABEL (new_jump) = JUMP_LABEL (last_insn);
LABEL_NUSES (JUMP_LABEL (new_jump))++;
emit_barrier_after (new_jump);
}
+ something_changed = 1;
delete_insn (last_insn);
if (compare_and_branch == 2)
- delete_insn (earliest);
- purge_dead_edges (BASIC_BLOCK (bb));
+ delete_insn (earliest);
+ purge_dead_edges (bb);
/* Don't check this block again. (Note that BLOCK_END is
- invalid here; we deleted the last instruction in the
+ invalid here; we deleted the last instruction in the
block.) */
- block_reg[bb] = 0;
+ block_reg[bb->index] = 0;
}
+
+ return something_changed;
}
/* Find EQ/NE comparisons against zero which can be (indirectly) evaluated
@@ -5402,7 +5884,7 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
So, if every path leading to a conditional branch has an available memory
reference of that form, then we know the register can not have the value
- zero at the conditional branch.
+ zero at the conditional branch.
So we merely need to compute the local properies and propagate that data
around the cfg, then optimize where possible.
@@ -5414,21 +5896,22 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
This could probably be integrated with global cprop with a little work. */
-void
+int
delete_null_pointer_checks (f)
rtx f ATTRIBUTE_UNUSED;
{
sbitmap *nonnull_avin, *nonnull_avout;
unsigned int *block_reg;
- int bb;
+ basic_block bb;
int reg;
int regs_per_pass;
int max_reg;
struct null_pointer_info npi;
+ int something_changed = 0;
/* If we have only a single block, then there's nothing to do. */
if (n_basic_blocks <= 1)
- return;
+ return 0;
/* Trying to perform global optimizations on flow graphs which have
a high connectivity will take a long time and is unlikely to be
@@ -5439,26 +5922,26 @@ delete_null_pointer_checks (f)
a couple switch statements. So we require a relatively large number
of basic blocks and the ratio of edges to blocks to be high. */
if (n_basic_blocks > 1000 && n_edges / n_basic_blocks >= 20)
- return;
+ return 0;
/* We need four bitmaps, each with a bit for each register in each
basic block. */
max_reg = max_reg_num ();
- regs_per_pass = get_bitmap_width (4, n_basic_blocks, max_reg);
+ regs_per_pass = get_bitmap_width (4, last_basic_block, max_reg);
/* Allocate bitmaps to hold local and global properties. */
- npi.nonnull_local = sbitmap_vector_alloc (n_basic_blocks, regs_per_pass);
- npi.nonnull_killed = sbitmap_vector_alloc (n_basic_blocks, regs_per_pass);
- nonnull_avin = sbitmap_vector_alloc (n_basic_blocks, regs_per_pass);
- nonnull_avout = sbitmap_vector_alloc (n_basic_blocks, regs_per_pass);
+ npi.nonnull_local = sbitmap_vector_alloc (last_basic_block, regs_per_pass);
+ npi.nonnull_killed = sbitmap_vector_alloc (last_basic_block, regs_per_pass);
+ nonnull_avin = sbitmap_vector_alloc (last_basic_block, regs_per_pass);
+ nonnull_avout = sbitmap_vector_alloc (last_basic_block, regs_per_pass);
/* Go through the basic blocks, seeing whether or not each block
ends with a conditional branch whose condition is a comparison
against zero. Record the register compared in BLOCK_REG. */
- block_reg = (unsigned int *) xcalloc (n_basic_blocks, sizeof (int));
- for (bb = 0; bb < n_basic_blocks; bb++)
+ block_reg = (unsigned int *) xcalloc (last_basic_block, sizeof (int));
+ FOR_EACH_BB (bb)
{
- rtx last_insn = BLOCK_END (bb);
+ rtx last_insn = bb->end;
rtx condition, earliest, reg;
/* We only want conditional branches. */
@@ -5475,7 +5958,7 @@ delete_null_pointer_checks (f)
if (!condition
|| (GET_CODE (condition) != NE && GET_CODE (condition) != EQ)
|| GET_CODE (XEXP (condition, 1)) != CONST_INT
- || (XEXP (condition, 1)
+ || (XEXP (condition, 1)
!= CONST0_RTX (GET_MODE (XEXP (condition, 0)))))
continue;
@@ -5484,7 +5967,7 @@ delete_null_pointer_checks (f)
if (GET_CODE (reg) != REG)
continue;
- block_reg[bb] = REGNO (reg);
+ block_reg[bb->index] = REGNO (reg);
}
/* Go through the algorithm for each block of registers. */
@@ -5492,8 +5975,10 @@ delete_null_pointer_checks (f)
{
npi.min_reg = reg;
npi.max_reg = MIN (reg + regs_per_pass, max_reg);
- delete_null_pointer_checks_1 (block_reg, nonnull_avin,
- nonnull_avout, &npi);
+ something_changed |= delete_null_pointer_checks_1 (block_reg,
+ nonnull_avin,
+ nonnull_avout,
+ &npi);
}
/* Free the table of registers compared at the end of every block. */
@@ -5504,6 +5989,8 @@ delete_null_pointer_checks (f)
sbitmap_vector_free (npi.nonnull_killed);
sbitmap_vector_free (nonnull_avin);
sbitmap_vector_free (nonnull_avout);
+
+ return something_changed;
}
/* Code Hoisting variables and subroutines. */
@@ -5516,10 +6003,10 @@ static sbitmap *hoist_vbeout;
static sbitmap *hoist_exprs;
/* Dominator bitmaps. */
-static sbitmap *dominators;
+dominance_info dominators;
/* ??? We could compute post dominators and run this algorithm in
- reverse to to perform tail merging, doing so would probably be
+ reverse to perform tail merging, doing so would probably be
more effective than the tail merging code in jump.c.
It's unclear if tail merging could be run in parallel with
@@ -5539,8 +6026,6 @@ alloc_code_hoist_mem (n_blocks, n_exprs)
hoist_vbeout = sbitmap_vector_alloc (n_blocks, n_exprs);
hoist_exprs = sbitmap_vector_alloc (n_blocks, n_exprs);
transpout = sbitmap_vector_alloc (n_blocks, n_exprs);
-
- dominators = sbitmap_vector_alloc (n_blocks, n_blocks);
}
/* Free vars used for code hoisting analysis. */
@@ -5557,7 +6042,7 @@ free_code_hoist_mem ()
sbitmap_vector_free (hoist_exprs);
sbitmap_vector_free (transpout);
- sbitmap_vector_free (dominators);
+ free_dominance_info (dominators);
}
/* Compute the very busy expressions at entry/exit from each block.
@@ -5568,10 +6053,11 @@ free_code_hoist_mem ()
static void
compute_code_hoist_vbeinout ()
{
- int bb, changed, passes;
+ int changed, passes;
+ basic_block bb;
- sbitmap_vector_zero (hoist_vbeout, n_basic_blocks);
- sbitmap_vector_zero (hoist_vbein, n_basic_blocks);
+ sbitmap_vector_zero (hoist_vbeout, last_basic_block);
+ sbitmap_vector_zero (hoist_vbein, last_basic_block);
passes = 0;
changed = 1;
@@ -5582,12 +6068,12 @@ compute_code_hoist_vbeinout ()
/* We scan the blocks in the reverse order to speed up
the convergence. */
- for (bb = n_basic_blocks - 1; bb >= 0; bb--)
+ FOR_EACH_BB_REVERSE (bb)
{
- changed |= sbitmap_a_or_b_and_c (hoist_vbein[bb], antloc[bb],
- hoist_vbeout[bb], transp[bb]);
- if (bb != n_basic_blocks - 1)
- sbitmap_intersection_of_succs (hoist_vbeout[bb], hoist_vbein, bb);
+ changed |= sbitmap_a_or_b_and_c_cg (hoist_vbein[bb->index], antloc[bb->index],
+ hoist_vbeout[bb->index], transp[bb->index]);
+ if (bb->next_bb != EXIT_BLOCK_PTR)
+ sbitmap_intersection_of_succs (hoist_vbeout[bb->index], hoist_vbein, bb->index);
}
passes++;
@@ -5602,10 +6088,10 @@ compute_code_hoist_vbeinout ()
static void
compute_code_hoist_data ()
{
- compute_local_properties (transp, comp, antloc, 0);
+ compute_local_properties (transp, comp, antloc, &expr_hash_table);
compute_transpout ();
compute_code_hoist_vbeinout ();
- calculate_dominance_info (NULL, dominators, CDI_DOMINATORS);
+ dominators = calculate_dominance_info (CDI_DOMINATORS);
if (gcse_file)
fprintf (gcse_file, "\n");
}
@@ -5632,12 +6118,12 @@ hoist_expr_reaches_here_p (expr_bb, expr_index, bb, visited)
{
edge pred;
int visited_allocated_locally = 0;
-
+
if (visited == NULL)
{
visited_allocated_locally = 1;
- visited = xcalloc (n_basic_blocks, 1);
+ visited = xcalloc (last_basic_block, 1);
}
for (pred = bb->pred; pred != NULL; pred = pred->pred_next)
@@ -5646,6 +6132,8 @@ hoist_expr_reaches_here_p (expr_bb, expr_index, bb, visited)
if (pred->src == ENTRY_BLOCK_PTR)
break;
+ else if (pred_bb == expr_bb)
+ continue;
else if (visited[pred_bb->index])
continue;
@@ -5664,7 +6152,7 @@ hoist_expr_reaches_here_p (expr_bb, expr_index, bb, visited)
break;
}
}
- if (visited_allocated_locally)
+ if (visited_allocated_locally)
free (visited);
return (pred == NULL);
@@ -5675,59 +6163,61 @@ hoist_expr_reaches_here_p (expr_bb, expr_index, bb, visited)
static void
hoist_code ()
{
- int bb, dominated;
- unsigned int i;
+ basic_block bb, dominated;
+ basic_block *domby;
+ unsigned int domby_len;
+ unsigned int i,j;
struct expr **index_map;
struct expr *expr;
- sbitmap_vector_zero (hoist_exprs, n_basic_blocks);
+ sbitmap_vector_zero (hoist_exprs, last_basic_block);
/* Compute a mapping from expression number (`bitmap_index') to
hash table entry. */
- index_map = (struct expr **) xcalloc (n_exprs, sizeof (struct expr *));
- for (i = 0; i < expr_hash_table_size; i++)
- for (expr = expr_hash_table[i]; expr != NULL; expr = expr->next_same_hash)
+ index_map = (struct expr **) xcalloc (expr_hash_table.n_elems, sizeof (struct expr *));
+ for (i = 0; i < expr_hash_table.size; i++)
+ for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
index_map[expr->bitmap_index] = expr;
/* Walk over each basic block looking for potentially hoistable
expressions, nothing gets hoisted from the entry block. */
- for (bb = 0; bb < n_basic_blocks; bb++)
+ FOR_EACH_BB (bb)
{
int found = 0;
int insn_inserted_p;
+ domby_len = get_dominated_by (dominators, bb, &domby);
/* Examine each expression that is very busy at the exit of this
block. These are the potentially hoistable expressions. */
- for (i = 0; i < hoist_vbeout[bb]->n_bits; i++)
+ for (i = 0; i < hoist_vbeout[bb->index]->n_bits; i++)
{
int hoistable = 0;
- if (TEST_BIT (hoist_vbeout[bb], i) && TEST_BIT (transpout[bb], i))
+ if (TEST_BIT (hoist_vbeout[bb->index], i)
+ && TEST_BIT (transpout[bb->index], i))
{
/* We've found a potentially hoistable expression, now
we look at every block BB dominates to see if it
computes the expression. */
- for (dominated = 0; dominated < n_basic_blocks; dominated++)
+ for (j = 0; j < domby_len; j++)
{
+ dominated = domby[j];
/* Ignore self dominance. */
- if (bb == dominated
- || ! TEST_BIT (dominators[dominated], bb))
+ if (bb == dominated)
continue;
-
/* We've found a dominated block, now see if it computes
the busy expression and whether or not moving that
expression to the "beginning" of that block is safe. */
- if (!TEST_BIT (antloc[dominated], i))
+ if (!TEST_BIT (antloc[dominated->index], i))
continue;
/* Note if the expression would reach the dominated block
- unimpared if it was placed at the end of BB.
+ unimpared if it was placed at the end of BB.
Keep track of how many times this expression is hoistable
from a dominated block into BB. */
- if (hoist_expr_reaches_here_p (BASIC_BLOCK (bb), i,
- BASIC_BLOCK (dominated), NULL))
+ if (hoist_expr_reaches_here_p (bb, i, dominated, NULL))
hoistable++;
}
@@ -5743,40 +6233,42 @@ hoist_code ()
to nullify any benefit we get from code hoisting. */
if (hoistable > 1)
{
- SET_BIT (hoist_exprs[bb], i);
+ SET_BIT (hoist_exprs[bb->index], i);
found = 1;
}
}
}
-
/* If we found nothing to hoist, then quit now. */
if (! found)
+ {
+ free (domby);
continue;
+ }
/* Loop over all the hoistable expressions. */
- for (i = 0; i < hoist_exprs[bb]->n_bits; i++)
+ for (i = 0; i < hoist_exprs[bb->index]->n_bits; i++)
{
/* We want to insert the expression into BB only once, so
note when we've inserted it. */
insn_inserted_p = 0;
/* These tests should be the same as the tests above. */
- if (TEST_BIT (hoist_vbeout[bb], i))
+ if (TEST_BIT (hoist_vbeout[bb->index], i))
{
/* We've found a potentially hoistable expression, now
we look at every block BB dominates to see if it
computes the expression. */
- for (dominated = 0; dominated < n_basic_blocks; dominated++)
+ for (j = 0; j < domby_len; j++)
{
+ dominated = domby[j];
/* Ignore self dominance. */
- if (bb == dominated
- || ! TEST_BIT (dominators[dominated], bb))
+ if (bb == dominated)
continue;
/* We've found a dominated block, now see if it computes
the busy expression and whether or not moving that
expression to the "beginning" of that block is safe. */
- if (!TEST_BIT (antloc[dominated], i))
+ if (!TEST_BIT (antloc[dominated->index], i))
continue;
/* The expression is computed in the dominated block and
@@ -5784,8 +6276,7 @@ hoist_code ()
dominated block. Now we have to determine if the
expression would reach the dominated block if it was
placed at the end of BB. */
- if (hoist_expr_reaches_here_p (BASIC_BLOCK (bb), i,
- BASIC_BLOCK (dominated), NULL))
+ if (hoist_expr_reaches_here_p (bb, i, dominated, NULL))
{
struct expr *expr = index_map[i];
struct occr *occr = expr->antic_occr;
@@ -5793,7 +6284,7 @@ hoist_code ()
rtx set;
/* Find the right occurrence of this expression. */
- while (BLOCK_NUM (occr->insn) != dominated && occr)
+ while (BLOCK_FOR_INSN (occr->insn) != dominated && occr)
occr = occr->next;
/* Should never happen. */
@@ -5801,7 +6292,7 @@ hoist_code ()
abort ();
insn = occr->insn;
-
+
set = single_set (insn);
if (! set)
abort ();
@@ -5813,29 +6304,19 @@ hoist_code ()
expr->reaching_reg
= gen_reg_rtx (GET_MODE (SET_DEST (set)));
- /* In theory this should never fail since we're creating
- a reg->reg copy.
-
- However, on the x86 some of the movXX patterns
- actually contain clobbers of scratch regs. This may
- cause the insn created by validate_change to not
- match any pattern and thus cause validate_change to
- fail. */
- if (validate_change (insn, &SET_SRC (set),
- expr->reaching_reg, 0))
+ gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
+ delete_insn (insn);
+ occr->deleted_p = 1;
+ if (!insn_inserted_p)
{
- occr->deleted_p = 1;
- if (!insn_inserted_p)
- {
- insert_insn_end_bb (index_map[i],
- BASIC_BLOCK (bb), 0);
- insn_inserted_p = 1;
- }
+ insert_insn_end_bb (index_map[i], bb, 0);
+ insn_inserted_p = 1;
}
}
}
}
}
+ free (domby);
}
free (index_map);
@@ -5843,28 +6324,27 @@ hoist_code ()
/* Top level routine to perform one code hoisting (aka unification) pass
- Return non-zero if a change was made. */
+ Return nonzero if a change was made. */
static int
one_code_hoisting_pass ()
{
int changed = 0;
- alloc_expr_hash_table (max_cuid);
- compute_expr_hash_table ();
+ alloc_hash_table (max_cuid, &expr_hash_table, 0);
+ compute_hash_table (&expr_hash_table);
if (gcse_file)
- dump_hash_table (gcse_file, "Code Hosting Expressions", expr_hash_table,
- expr_hash_table_size, n_exprs);
+ dump_hash_table (gcse_file, "Code Hosting Expressions", &expr_hash_table);
- if (n_exprs > 0)
+ if (expr_hash_table.n_elems > 0)
{
- alloc_code_hoist_mem (n_basic_blocks, n_exprs);
+ alloc_code_hoist_mem (last_basic_block, expr_hash_table.n_elems);
compute_code_hoist_data ();
hoist_code ();
free_code_hoist_mem ();
}
- free_expr_hash_table ();
+ free_hash_table (&expr_hash_table);
return changed;
}
@@ -5883,10 +6363,10 @@ one_code_hoisting_pass ()
}
'i' is both loaded and stored to in the loop. Normally, gcse cannot move
- the load out since its live around the loop, and stored at the bottom
- of the loop.
+ the load out since its live around the loop, and stored at the bottom
+ of the loop.
- The 'Load Motion' referred to and implemented in this file is
+ The 'Load Motion' referred to and implemented in this file is
an enhancement to gcse which when using edge based lcm, recognizes
this situation and allows gcse to move the load out of the loop.
@@ -5922,13 +6402,13 @@ ldst_entry (x)
ptr->hash_index = 0;
pre_ldst_mems = ptr;
}
-
+
return ptr;
}
/* Free up an individual ldst entry. */
-static void
+static void
free_ldst_entry (ptr)
struct ls_expr * ptr;
{
@@ -5943,7 +6423,7 @@ free_ldst_entry (ptr)
static void
free_ldst_mems ()
{
- while (pre_ldst_mems)
+ while (pre_ldst_mems)
{
struct ls_expr * tmp = pre_ldst_mems;
@@ -5998,7 +6478,7 @@ find_rtx_in_ldst (x)
rtx x;
{
struct ls_expr * ptr;
-
+
for (ptr = pre_ldst_mems; ptr != NULL; ptr = ptr->next)
if (expr_equiv_p (ptr->pattern, x) && ! ptr->invalid)
return ptr;
@@ -6043,31 +6523,31 @@ next_ls_expr (ptr)
side effects. These are the types of loads we consider for the
ld_motion list, otherwise we let the usual aliasing take care of it. */
-static int
+static int
simple_mem (x)
rtx x;
{
if (GET_CODE (x) != MEM)
return 0;
-
+
if (MEM_VOLATILE_P (x))
return 0;
-
+
if (GET_MODE (x) == BLKmode)
return 0;
if (!rtx_varies_p (XEXP (x, 0), 0))
return 1;
-
+
return 0;
}
-/* Make sure there isn't a buried reference in this pattern anywhere.
- If there is, invalidate the entry for it since we're not capable
- of fixing it up just yet.. We have to be sure we know about ALL
+/* Make sure there isn't a buried reference in this pattern anywhere.
+ If there is, invalidate the entry for it since we're not capable
+ of fixing it up just yet.. We have to be sure we know about ALL
loads since the aliasing code will allow all entries in the
ld_motion list to not-alias itself. If we miss a load, we will get
- the wrong value since gcse might common it and we won't know to
+ the wrong value since gcse might common it and we won't know to
fix it up. */
static void
@@ -6087,7 +6567,7 @@ invalidate_any_buried_refs (x)
/* Recursively process the insn. */
fmt = GET_RTX_FORMAT (GET_CODE (x));
-
+
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
@@ -6100,23 +6580,23 @@ invalidate_any_buried_refs (x)
/* Find all the 'simple' MEMs which are used in LOADs and STORES. Simple
being defined as MEM loads and stores to symbols, with no
- side effects and no registers in the expression. If there are any
+ side effects and no registers in the expression. If there are any
uses/defs which don't match this criteria, it is invalidated and
trimmed out later. */
-static void
+static void
compute_ld_motion_mems ()
{
struct ls_expr * ptr;
- int bb;
+ basic_block bb;
rtx insn;
-
+
pre_ldst_mems = NULL;
- for (bb = 0; bb < n_basic_blocks; bb++)
+ FOR_EACH_BB (bb)
{
- for (insn = BLOCK_HEAD (bb);
- insn && insn != NEXT_INSN (BLOCK_END (bb));
+ for (insn = bb->head;
+ insn && insn != NEXT_INSN (bb->end);
insn = NEXT_INSN (insn))
{
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
@@ -6140,7 +6620,7 @@ compute_ld_motion_mems ()
/* Make sure there isn't a buried load somewhere. */
invalidate_any_buried_refs (src);
}
-
+
/* Check for stores. Don't worry about aliased ones, they
will block any movement we might do later. We only care
about this exact pattern since those are the only
@@ -6148,7 +6628,7 @@ compute_ld_motion_mems ()
if (GET_CODE (dest) == MEM && simple_mem (dest))
{
ptr = ldst_entry (dest);
-
+
if (GET_CODE (src) != MEM
&& GET_CODE (src) != ASM_OPERANDS)
ptr->stores = alloc_INSN_LIST (insn, ptr->stores);
@@ -6163,7 +6643,7 @@ compute_ld_motion_mems ()
}
}
-/* Remove any references that have been either invalidated or are not in the
+/* Remove any references that have been either invalidated or are not in the
expression list for pre gcse. */
static void
@@ -6176,18 +6656,18 @@ trim_ld_motion_mems ()
{
int del = ptr->invalid;
struct expr * expr = NULL;
-
+
/* Delete if entry has been made invalid. */
- if (!del)
+ if (!del)
{
unsigned int i;
-
+
del = 1;
/* Delete if we cannot find this mem in the expression list. */
- for (i = 0; i < expr_hash_table_size && del; i++)
+ for (i = 0; i < expr_hash_table.size && del; i++)
{
- for (expr = expr_hash_table[i];
- expr != NULL;
+ for (expr = expr_hash_table.table[i];
+ expr != NULL;
expr = expr->next_same_hash)
if (expr_equiv_p (expr->expr, ptr->pattern))
{
@@ -6196,7 +6676,7 @@ trim_ld_motion_mems ()
}
}
}
-
+
if (del)
{
if (last != NULL)
@@ -6241,16 +6721,16 @@ update_ld_motion_stores (expr)
if ((mem_ptr = find_rtx_in_ldst (expr->expr)))
{
- /* We can try to find just the REACHED stores, but is shouldn't
- matter to set the reaching reg everywhere... some might be
+ /* We can try to find just the REACHED stores, but is shouldn't
+ matter to set the reaching reg everywhere... some might be
dead and should be eliminated later. */
/* We replace SET mem = expr with
SET reg = expr
- SET mem = reg , where reg is the
+ SET mem = reg , where reg is the
reaching reg used in the load. */
rtx list = mem_ptr->stores;
-
+
for ( ; list != NULL_RTX; list = XEXP (list, 1))
{
rtx insn = XEXP (list, 0);
@@ -6262,7 +6742,7 @@ update_ld_motion_stores (expr)
/* If we've already copied it, continue. */
if (expr->reaching_reg == src)
continue;
-
+
if (gcse_file)
{
fprintf (gcse_file, "PRE: store updated with reaching reg ");
@@ -6271,7 +6751,7 @@ update_ld_motion_stores (expr)
print_inline_rtx (gcse_file, insn, 8);
fprintf (gcse_file, "\n");
}
-
+
copy = gen_move_insn ( reg, SET_SRC (pat));
new = emit_insn_before (copy, insn);
record_one_set (REGNO (reg), new);
@@ -6286,7 +6766,7 @@ update_ld_motion_stores (expr)
/* Store motion code. */
-/* This is used to communicate the target bitvector we want to use in the
+/* This is used to communicate the target bitvector we want to use in the
reg_set_info routine when called via the note_stores mechanism. */
static sbitmap * regvec;
@@ -6310,7 +6790,7 @@ reg_set_info (dest, setter, data)
SET_BIT (*regvec, REGNO (dest));
}
-/* Return non-zero if the register operands of expression X are killed
+/* Return nonzero if the register operands of expression X are killed
anywhere in basic block BB. */
static int
@@ -6364,7 +6844,7 @@ store_ops_ok (x, bb)
i = GET_RTX_LENGTH (code) - 1;
fmt = GET_RTX_FORMAT (code);
-
+
for (; i >= 0; i--)
{
if (fmt[i] == 'e')
@@ -6379,14 +6859,14 @@ store_ops_ok (x, bb)
x = tem;
goto repeat;
}
-
+
if (! store_ops_ok (tem, bb))
return 0;
}
else if (fmt[i] == 'E')
{
int j;
-
+
for (j = 0; j < XVECLEN (x, i); j++)
{
if (! store_ops_ok (XVECEXP (x, i, j), bb))
@@ -6412,7 +6892,7 @@ find_moveable_store (insn)
return;
dest = SET_DEST (dest);
-
+
if (GET_CODE (dest) != MEM || MEM_VOLATILE_P (dest)
|| GET_MODE (dest) == BLKmode)
return;
@@ -6433,23 +6913,24 @@ find_moveable_store (insn)
static int
compute_store_table ()
{
- int bb, ret;
+ int ret;
+ basic_block bb;
unsigned regno;
rtx insn, pat;
max_gcse_regno = max_reg_num ();
- reg_set_in_block = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks,
+ reg_set_in_block = (sbitmap *) sbitmap_vector_alloc (last_basic_block,
max_gcse_regno);
- sbitmap_vector_zero (reg_set_in_block, n_basic_blocks);
+ sbitmap_vector_zero (reg_set_in_block, last_basic_block);
pre_ldst_mems = 0;
/* Find all the stores we care about. */
- for (bb = 0; bb < n_basic_blocks; bb++)
+ FOR_EACH_BB (bb)
{
- regvec = & (reg_set_in_block[bb]);
- for (insn = BLOCK_END (bb);
- insn && insn != PREV_INSN (BLOCK_HEAD (bb));
+ regvec = & (reg_set_in_block[bb->index]);
+ for (insn = bb->end;
+ insn && insn != PREV_INSN (bb->end);
insn = PREV_INSN (insn))
{
/* Ignore anything that is not a normal insn. */
@@ -6459,7 +6940,7 @@ compute_store_table ()
if (GET_CODE (insn) == CALL_INSN)
{
bool clobbers_all = false;
-#ifdef NON_SAVING_SETJMP
+#ifdef NON_SAVING_SETJMP
if (NON_SAVING_SETJMP
&& find_reg_note (insn, REG_SETJMP, NULL_RTX))
clobbers_all = true;
@@ -6468,12 +6949,12 @@ compute_store_table ()
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (clobbers_all
|| TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
- SET_BIT (reg_set_in_block[bb], regno);
+ SET_BIT (reg_set_in_block[bb->index], regno);
}
-
+
pat = PATTERN (insn);
note_stores (pat, reg_set_info, NULL);
-
+
/* Now that we've marked regs, look for stores. */
if (GET_CODE (pat) == SET)
find_moveable_store (insn);
@@ -6481,13 +6962,13 @@ compute_store_table ()
}
ret = enumerate_ldsts ();
-
+
if (gcse_file)
{
fprintf (gcse_file, "Store Motion Expressions.\n");
print_ldst_list (gcse_file);
}
-
+
return ret;
}
@@ -6502,7 +6983,7 @@ load_kills_store (x, store_pattern)
return 0;
}
-/* Go through the entire insn X, looking for any loads which might alias
+/* Go through the entire insn X, looking for any loads which might alias
STORE_PATTERN. Return 1 if found. */
static int
@@ -6516,7 +6997,7 @@ find_loads (x, store_pattern)
if (!x)
return 0;
- if (GET_CODE (x) == SET)
+ if (GET_CODE (x) == SET)
x = SET_SRC (x);
if (GET_CODE (x) == MEM)
@@ -6527,7 +7008,7 @@ find_loads (x, store_pattern)
/* Recursively process the insn. */
fmt = GET_RTX_FORMAT (GET_CODE (x));
-
+
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0 && !ret; i--)
{
if (fmt[i] == 'e')
@@ -6539,23 +7020,23 @@ find_loads (x, store_pattern)
return ret;
}
-/* Check if INSN kills the store pattern X (is aliased with it).
+/* Check if INSN kills the store pattern X (is aliased with it).
Return 1 if it it does. */
-static int
+static int
store_killed_in_insn (x, insn)
rtx x, insn;
{
if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
return 0;
-
+
if (GET_CODE (insn) == CALL_INSN)
{
/* A normal or pure call might read from pattern,
but a const call will not. */
return ! CONST_OR_PURE_CALL_P (insn) || pure_call_p (insn);
}
-
+
if (GET_CODE (PATTERN (insn)) == SET)
{
rtx pat = PATTERN (insn);
@@ -6573,19 +7054,19 @@ store_killed_in_insn (x, insn)
/* Returns 1 if the expression X is loaded or clobbered on or after INSN
within basic block BB. */
-static int
+static int
store_killed_after (x, insn, bb)
rtx x, insn;
basic_block bb;
{
rtx last = bb->end;
-
+
if (insn == last)
return 0;
/* Check if the register operands of the store are OK in this block.
- Note that if registers are changed ANYWHERE in the block, we'll
- decide we can't move it, regardless of whether it changed above
+ Note that if registers are changed ANYWHERE in the block, we'll
+ decide we can't move it, regardless of whether it changed above
or below the store. This could be improved by checking the register
operands while lookinng for aliasing in each insn. */
if (!store_ops_ok (XEXP (x, 0), bb))
@@ -6594,13 +7075,13 @@ store_killed_after (x, insn, bb)
for ( ; insn && insn != NEXT_INSN (last); insn = NEXT_INSN (insn))
if (store_killed_in_insn (x, insn))
return 1;
-
+
return 0;
}
/* Returns 1 if the expression X is loaded or clobbered on or before INSN
within basic block BB. */
-static int
+static int
store_killed_before (x, insn, bb)
rtx x, insn;
basic_block bb;
@@ -6609,10 +7090,10 @@ store_killed_before (x, insn, bb)
if (insn == first)
return store_killed_in_insn (x, insn);
-
+
/* Check if the register operands of the store are OK in this block.
- Note that if registers are changed ANYWHERE in the block, we'll
- decide we can't move it, regardless of whether it changed above
+ Note that if registers are changed ANYWHERE in the block, we'll
+ decide we can't move it, regardless of whether it changed above
or below the store. This could be improved by checking the register
operands while lookinng for aliasing in each insn. */
if (!store_ops_ok (XEXP (x, 0), bb))
@@ -6621,7 +7102,7 @@ store_killed_before (x, insn, bb)
for ( ; insn && insn != PREV_INSN (first); insn = PREV_INSN (insn))
if (store_killed_in_insn (x, insn))
return 1;
-
+
return 0;
}
@@ -6632,23 +7113,22 @@ store_killed_before (x, insn, bb)
determine which ones are not killed by aliasing, and generate
the appropriate vectors for gen and killed. */
static void
-build_store_vectors ()
+build_store_vectors ()
{
- basic_block bb;
- int b;
+ basic_block bb, b;
rtx insn, st;
struct ls_expr * ptr;
/* Build the gen_vector. This is any store in the table which is not killed
by aliasing later in its block. */
- ae_gen = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, num_stores);
- sbitmap_vector_zero (ae_gen, n_basic_blocks);
+ ae_gen = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
+ sbitmap_vector_zero (ae_gen, last_basic_block);
- st_antloc = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, num_stores);
- sbitmap_vector_zero (st_antloc, n_basic_blocks);
+ st_antloc = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
+ sbitmap_vector_zero (st_antloc, last_basic_block);
for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
- {
+ {
/* Put all the stores into either the antic list, or the avail list,
or both. */
rtx store_list = ptr->stores;
@@ -6658,7 +7138,7 @@ build_store_vectors ()
{
insn = XEXP (st, 0);
bb = BLOCK_FOR_INSN (insn);
-
+
if (!store_killed_after (ptr->pattern, insn, bb))
{
/* If we've already seen an availale expression in this block,
@@ -6687,7 +7167,7 @@ build_store_vectors ()
AVAIL_STORE_LIST (ptr) = alloc_INSN_LIST (insn,
AVAIL_STORE_LIST (ptr));
}
-
+
if (!store_killed_before (ptr->pattern, insn, bb))
{
SET_BIT (st_antloc[BLOCK_NUM (insn)], ptr->index);
@@ -6695,25 +7175,25 @@ build_store_vectors ()
ANTIC_STORE_LIST (ptr));
}
}
-
+
/* Free the original list of store insns. */
free_INSN_LIST_list (&store_list);
}
-
- ae_kill = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, num_stores);
- sbitmap_vector_zero (ae_kill, n_basic_blocks);
- transp = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, num_stores);
- sbitmap_vector_zero (transp, n_basic_blocks);
+ ae_kill = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
+ sbitmap_vector_zero (ae_kill, last_basic_block);
+
+ transp = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
+ sbitmap_vector_zero (transp, last_basic_block);
for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
- for (b = 0; b < n_basic_blocks; b++)
+ FOR_EACH_BB (b)
{
- if (store_killed_after (ptr->pattern, BLOCK_HEAD (b), BASIC_BLOCK (b)))
+ if (store_killed_after (ptr->pattern, b->head, b))
{
/* The anticipatable expression is not killed if it's gen'd. */
/*
- We leave this check out for now. If we have a code sequence
+ We leave this check out for now. If we have a code sequence
in a block which looks like:
ST MEMa = x
L y = MEMa
@@ -6721,37 +7201,37 @@ build_store_vectors ()
We should flag this as having an ANTIC expression, NOT
transparent, NOT killed, and AVAIL.
Unfortunately, since we haven't re-written all loads to
- use the reaching reg, we'll end up doing an incorrect
+ use the reaching reg, we'll end up doing an incorrect
Load in the middle here if we push the store down. It happens in
gcc.c-torture/execute/960311-1.c with -O3
If we always kill it in this case, we'll sometimes do
uneccessary work, but it shouldn't actually hurt anything.
if (!TEST_BIT (ae_gen[b], ptr->index)). */
- SET_BIT (ae_kill[b], ptr->index);
+ SET_BIT (ae_kill[b->index], ptr->index);
}
else
- SET_BIT (transp[b], ptr->index);
+ SET_BIT (transp[b->index], ptr->index);
}
/* Any block with no exits calls some non-returning function, so
we better mark the store killed here, or we might not store to
it at all. If we knew it was abort, we wouldn't have to store,
but we don't know that for sure. */
- if (gcse_file)
+ if (gcse_file)
{
fprintf (gcse_file, "ST_avail and ST_antic (shown under loads..)\n");
print_ldst_list (gcse_file);
- dump_sbitmap_vector (gcse_file, "st_antloc", "", st_antloc, n_basic_blocks);
- dump_sbitmap_vector (gcse_file, "st_kill", "", ae_kill, n_basic_blocks);
- dump_sbitmap_vector (gcse_file, "Transpt", "", transp, n_basic_blocks);
- dump_sbitmap_vector (gcse_file, "st_avloc", "", ae_gen, n_basic_blocks);
+ dump_sbitmap_vector (gcse_file, "st_antloc", "", st_antloc, last_basic_block);
+ dump_sbitmap_vector (gcse_file, "st_kill", "", ae_kill, last_basic_block);
+ dump_sbitmap_vector (gcse_file, "Transpt", "", transp, last_basic_block);
+ dump_sbitmap_vector (gcse_file, "st_avloc", "", ae_gen, last_basic_block);
}
}
-/* Insert an instruction at the begining of a basic block, and update
+/* Insert an instruction at the begining of a basic block, and update
the BLOCK_HEAD if needed. */
-static void
+static void
insert_insn_start_bb (insn, bb)
rtx insn;
basic_block bb;
@@ -6783,7 +7263,7 @@ insert_insn_start_bb (insn, bb)
}
/* This routine will insert a store on an edge. EXPR is the ldst entry for
- the memory reference, and E is the edge to insert it on. Returns non-zero
+ the memory reference, and E is the edge to insert it on. Returns nonzero
if an edge insertion was performed. */
static int
@@ -6802,7 +7282,7 @@ insert_store (expr, e)
reg = expr->reaching_reg;
insn = gen_move_insn (expr->pattern, reg);
-
+
/* If we are inserting this expression on ALL predecessor edges of a BB,
insert it at the start of the BB, and reset the insert bits on the other
edges so we don't try to insert it on the other edges. */
@@ -6828,7 +7308,7 @@ insert_store (expr, e)
insert_insn_start_bb (insn, bb);
return 0;
}
-
+
/* We can't insert on this edge, so we'll insert at the head of the
successors block. See Morgan, sec 10.5. */
if ((e->flags & EDGE_ABNORMAL) == EDGE_ABNORMAL)
@@ -6838,7 +7318,7 @@ insert_store (expr, e)
}
insert_insn_on_edge (insn, e);
-
+
if (gcse_file)
{
fprintf (gcse_file, "STORE_MOTION insert insn on edge (%d, %d):\n",
@@ -6846,7 +7326,7 @@ insert_store (expr, e)
print_inline_rtx (gcse_file, insn, 6);
fprintf (gcse_file, "\n");
}
-
+
return 1;
}
@@ -6858,20 +7338,20 @@ replace_store_insn (reg, del, bb)
basic_block bb;
{
rtx insn;
-
+
insn = gen_move_insn (reg, SET_SRC (PATTERN (del)));
insn = emit_insn_after (insn, del);
-
+
if (gcse_file)
{
- fprintf (gcse_file,
+ fprintf (gcse_file,
"STORE_MOTION delete insn in BB %d:\n ", bb->index);
print_inline_rtx (gcse_file, del, 6);
fprintf (gcse_file, "\nSTORE MOTION replaced with insn:\n ");
print_inline_rtx (gcse_file, insn, 6);
fprintf (gcse_file, "\n");
}
-
+
delete_insn (del);
}
@@ -6888,18 +7368,18 @@ delete_store (expr, bb)
if (expr->reaching_reg == NULL_RTX)
expr->reaching_reg = gen_reg_rtx (GET_MODE (expr->pattern));
-
- /* If there is more than 1 store, the earlier ones will be dead,
- but it doesn't hurt to replace them here. */
+
+ /* If there is more than 1 store, the earlier ones will be dead,
+ but it doesn't hurt to replace them here. */
reg = expr->reaching_reg;
-
+
for (i = AVAIL_STORE_LIST (expr); i; i = XEXP (i, 1))
{
del = XEXP (i, 0);
if (BLOCK_FOR_INSN (del) == bb)
{
- /* We know there is only one since we deleted redundant
+ /* We know there is only one since we deleted redundant
ones during the available computation. */
replace_store_insn (reg, del, bb);
break;
@@ -6909,11 +7389,11 @@ delete_store (expr, bb)
/* Free memory used by store motion. */
-static void
+static void
free_store_memory ()
{
free_ldst_mems ();
-
+
if (ae_gen)
sbitmap_vector_free (ae_gen);
if (ae_kill)
@@ -6928,7 +7408,7 @@ free_store_memory ()
sbitmap_vector_free (pre_delete_map);
if (reg_set_in_block)
sbitmap_vector_free (reg_set_in_block);
-
+
ae_gen = ae_kill = transp = st_antloc = NULL;
pre_insert_map = pre_delete_map = reg_set_in_block = NULL;
}
@@ -6939,6 +7419,7 @@ free_store_memory ()
static void
store_motion ()
{
+ basic_block bb;
int x;
struct ls_expr * ptr;
int update_flow = 0;
@@ -6965,16 +7446,16 @@ store_motion ()
add_noreturn_fake_exit_edges ();
build_store_vectors ();
- edge_list = pre_edge_rev_lcm (gcse_file, num_stores, transp, ae_gen,
- st_antloc, ae_kill, &pre_insert_map,
+ edge_list = pre_edge_rev_lcm (gcse_file, num_stores, transp, ae_gen,
+ st_antloc, ae_kill, &pre_insert_map,
&pre_delete_map);
/* Now we want to insert the new stores which are going to be needed. */
for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
{
- for (x = 0; x < n_basic_blocks; x++)
- if (TEST_BIT (pre_delete_map[x], ptr->index))
- delete_store (ptr, BASIC_BLOCK (x));
+ FOR_EACH_BB (bb)
+ if (TEST_BIT (pre_delete_map[bb->index], ptr->index))
+ delete_store (ptr, bb);
for (x = 0; x < NUM_EDGES (edge_list); x++)
if (TEST_BIT (pre_insert_map[x], ptr->index))
@@ -6989,3 +7470,5 @@ store_motion ()
remove_fake_edges ();
end_alias_analysis ();
}
+
+#include "gt-gcse.h"
diff --git a/contrib/gcc/gdbinit.in b/contrib/gcc/gdbinit.in
index 5fae918..cee1131 100644
--- a/contrib/gcc/gdbinit.in
+++ b/contrib/gcc/gdbinit.in
@@ -31,6 +31,15 @@ Print the full structure of the tree that is $.
Works only when an inferior is executing.
end
+define pct
+set debug_c_tree ($)
+end
+
+document pct
+Print the tree that is $ in C syntax.
+Works only when an inferior is executing.
+end
+
define ptc
output (enum tree_code) $.common.code
echo \n
@@ -41,7 +50,7 @@ Print the tree-code of the tree node that is $.
end
define pdn
-output $.decl.name->identifier.pointer
+output $.decl.name->identifier.id.str
echo \n
end
@@ -50,7 +59,7 @@ Print the name of the decl-node that is $.
end
define ptn
-output $.type.name->decl.name->identifier.pointer
+output $.type.name->decl.name->identifier.id.str
echo \n
end
diff --git a/contrib/gcc/genattr.c b/contrib/gcc/genattr.c
index 4d53077..591e0d7 100644
--- a/contrib/gcc/genattr.c
+++ b/contrib/gcc/genattr.c
@@ -86,34 +86,31 @@ static void
gen_attr (attr)
rtx attr;
{
- const char *p;
+ const char *p, *tag;
int is_const = GET_CODE (XEXP (attr, 2)) == CONST;
printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0));
/* If numeric attribute, don't need to write an enum. */
- if (*XSTR (attr, 1) == '\0')
+ p = XSTR (attr, 1);
+ if (*p == '\0')
printf ("extern int get_attr_%s PARAMS ((%s));\n", XSTR (attr, 0),
(is_const ? "void" : "rtx"));
else
{
printf ("enum attr_%s {", XSTR (attr, 0));
- write_upcase (XSTR (attr, 0));
- printf ("_");
- for (p = XSTR (attr, 1); *p != '\0'; p++)
+ while ((tag = scan_comma_elt (&p)) != 0)
{
+ write_upcase (XSTR (attr, 0));
+ putchar ('_');
+ while (tag != p)
+ putchar (TOUPPER (*tag++));
if (*p == ',')
- {
- printf (", ");
- write_upcase (XSTR (attr, 0));
- printf ("_");
- }
- else
- putchar (TOUPPER(*p));
+ fputs (", ", stdout);
}
- printf ("};\n");
+ fputs ("};\n", stdout);
printf ("extern enum attr_%s get_attr_%s PARAMS ((%s));\n\n",
XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx"));
}
@@ -122,11 +119,12 @@ gen_attr (attr)
variables used by `insn_current_length'. */
if (! strcmp (XSTR (attr, 0), "length"))
{
- printf ("extern void shorten_branches PARAMS ((rtx));\n");
- printf ("extern int insn_default_length PARAMS ((rtx));\n");
- printf ("extern int insn_variable_length_p PARAMS ((rtx));\n");
- printf ("extern int insn_current_length PARAMS ((rtx));\n\n");
- printf ("#include \"insn-addr.h\"\n\n");
+ puts ("\
+extern void shorten_branches PARAMS ((rtx));\n\
+extern int insn_default_length PARAMS ((rtx));\n\
+extern int insn_variable_length_p PARAMS ((rtx));\n\
+extern int insn_current_length PARAMS ((rtx));\n\n\
+#include \"insn-addr.h\"\n");
}
}
@@ -193,6 +191,7 @@ main (argc, argv)
int have_delay = 0;
int have_annul_true = 0;
int have_annul_false = 0;
+ int num_insn_reservations = 0;
int num_units = 0;
struct range all_simultaneity, all_multiplicity;
struct range all_ready_cost, all_issue_delay, all_blockage;
@@ -308,10 +307,18 @@ main (argc, argv)
extend_range (&all_issue_delay,
unit->issue_delay.min, unit->issue_delay.max);
}
+ else if (GET_CODE (desc) == DEFINE_INSN_RESERVATION)
+ num_insn_reservations++;
}
- if (num_units > 0)
+ if (num_units > 0 || num_insn_reservations > 0)
{
+ if (num_units > 0)
+ printf ("#define TRADITIONAL_PIPELINE_INTERFACE 1\n");
+
+ if (num_insn_reservations > 0)
+ printf ("#define DFA_PIPELINE_INTERFACE 1\n");
+
/* Compute the range of blockage cost values. See genattrtab.c
for the derivation. BLOCKAGE (E,C) when SIMULTANEITY is zero is
@@ -348,6 +355,102 @@ main (argc, argv)
write_units (num_units, &all_multiplicity, &all_simultaneity,
&all_ready_cost, &all_issue_delay, &all_blockage);
+
+ /* Output interface for pipeline hazards recognition based on
+ DFA (deterministic finite state automata. */
+ printf ("\n/* DFA based pipeline interface. */");
+ printf ("\n#ifndef AUTOMATON_STATE_ALTS\n");
+ printf ("#define AUTOMATON_STATE_ALTS 0\n");
+ printf ("#endif\n\n");
+ printf ("#ifndef CPU_UNITS_QUERY\n");
+ printf ("#define CPU_UNITS_QUERY 0\n");
+ printf ("#endif\n\n");
+ /* Interface itself: */
+ printf ("extern int max_dfa_issue_rate;\n\n");
+ printf ("/* The following macro value is calculated from the\n");
+ printf (" automaton based pipeline description and is equal to\n");
+ printf (" maximal number of all insns described in constructions\n");
+ printf (" `define_insn_reservation' which can be issued on the\n");
+ printf (" same processor cycle. */\n");
+ printf ("#define MAX_DFA_ISSUE_RATE max_dfa_issue_rate\n\n");
+ printf ("/* Insn latency time defined in define_insn_reservation. */\n");
+ printf ("extern int insn_default_latency PARAMS ((rtx));\n\n");
+ printf ("/* Return nonzero if there is a bypass for given insn\n");
+ printf (" which is a data producer. */\n");
+ printf ("extern int bypass_p PARAMS ((rtx));\n\n");
+ printf ("/* Insn latency time on data consumed by the 2nd insn.\n");
+ printf (" Use the function if bypass_p returns nonzero for\n");
+ printf (" the 1st insn. */\n");
+ printf ("extern int insn_latency PARAMS ((rtx, rtx));\n\n");
+ printf ("/* The following function returns number of alternative\n");
+ printf (" reservations of given insn. It may be used for better\n");
+ printf (" insns scheduling heuristics. */\n");
+ printf ("extern int insn_alts PARAMS ((rtx));\n\n");
+ printf ("/* Maximal possible number of insns waiting results being\n");
+ printf (" produced by insns whose execution is not finished. */\n");
+ printf ("extern int max_insn_queue_index;\n\n");
+ printf ("/* Pointer to data describing current state of DFA. */\n");
+ printf ("typedef void *state_t;\n\n");
+ printf ("/* Size of the data in bytes. */\n");
+ printf ("extern int state_size PARAMS ((void));\n\n");
+ printf ("/* Initiate given DFA state, i.e. Set up the state\n");
+ printf (" as all functional units were not reserved. */\n");
+ printf ("extern void state_reset PARAMS ((state_t));\n");
+ printf ("/* The following function returns negative value if given\n");
+ printf (" insn can be issued in processor state described by given\n");
+ printf (" DFA state. In this case, the DFA state is changed to\n");
+ printf (" reflect the current and future reservations by given\n");
+ printf (" insn. Otherwise the function returns minimal time\n");
+ printf (" delay to issue the insn. This delay may be zero\n");
+ printf (" for superscalar or VLIW processors. If the second\n");
+ printf (" parameter is NULL the function changes given DFA state\n");
+ printf (" as new processor cycle started. */\n");
+ printf ("extern int state_transition PARAMS ((state_t, rtx));\n");
+ printf ("\n#if AUTOMATON_STATE_ALTS\n");
+ printf ("/* The following function returns number of possible\n");
+ printf (" alternative reservations of given insn in given\n");
+ printf (" DFA state. It may be used for better insns scheduling\n");
+ printf (" heuristics. By default the function is defined if\n");
+ printf (" macro AUTOMATON_STATE_ALTS is defined because its\n");
+ printf (" implementation may require much memory. */\n");
+ printf ("extern int state_alts PARAMS ((state_t, rtx));\n");
+ printf ("#endif\n\n");
+ printf ("extern int min_issue_delay PARAMS ((state_t, rtx));\n");
+ printf ("/* The following function returns nonzero if no one insn\n");
+ printf (" can be issued in current DFA state. */\n");
+ printf ("extern int state_dead_lock_p PARAMS ((state_t));\n");
+ printf ("/* The function returns minimal delay of issue of the 2nd\n");
+ printf (" insn after issuing the 1st insn in given DFA state.\n");
+ printf (" The 1st insn should be issued in given state (i.e.\n");
+ printf (" state_transition should return negative value for\n");
+ printf (" the insn and the state). Data dependencies between\n");
+ printf (" the insns are ignored by the function. */\n");
+ printf
+ ("extern int min_insn_conflict_delay PARAMS ((state_t, rtx, rtx));\n");
+ printf ("/* The following function outputs reservations for given\n");
+ printf (" insn as they are described in the corresponding\n");
+ printf (" define_insn_reservation. */\n");
+ printf ("extern void print_reservation PARAMS ((FILE *, rtx));\n");
+ printf ("\n#if CPU_UNITS_QUERY\n");
+ printf ("/* The following function returns code of functional unit\n");
+ printf (" with given name (see define_cpu_unit). */\n");
+ printf ("extern int get_cpu_unit_code PARAMS ((const char *));\n");
+ printf ("/* The following function returns nonzero if functional\n");
+ printf (" unit with given code is currently reserved in given\n");
+ printf (" DFA state. */\n");
+ printf ("extern int cpu_unit_reservation_p PARAMS ((state_t, int));\n");
+ printf ("#endif\n\n");
+ printf ("/* Initiate and finish work with DFA. They should be\n");
+ printf (" called as the first and the last interface\n");
+ printf (" functions. */\n");
+ printf ("extern void dfa_start PARAMS ((void));\n");
+ printf ("extern void dfa_finish PARAMS ((void));\n");
+ }
+ else
+ {
+ /* Otherwise we do no scheduling, but we need these typedefs
+ in order to avoid uglifying other code with more ifdefs. */
+ printf ("typedef void *state_t;\n\n");
}
/* Output flag masks for use by reorg.
diff --git a/contrib/gcc/genattrtab.c b/contrib/gcc/genattrtab.c
index a485dee..47a6f00 100644
--- a/contrib/gcc/genattrtab.c
+++ b/contrib/gcc/genattrtab.c
@@ -86,15 +86,20 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
definitions (each would be accessed through a pointer).
We use the flags in an RTX as follows:
- `unchanging' (RTX_UNCHANGING_P): This rtx is fully simplified
+ `unchanging' (ATTR_IND_SIMPLIFIED_P): This rtx is fully simplified
independent of the insn code.
- `in_struct' (MEM_IN_STRUCT_P): This rtx is fully simplified
+ `in_struct' (ATTR_CURR_SIMPLIFIED_P): This rtx is fully simplified
for the insn code currently being processed (see optimize_attrs).
- `integrated' (RTX_INTEGRATED_P): This rtx is permanent and unique
+ `integrated' (ATTR_PERMANENT_P): This rtx is permanent and unique
(see attr_rtx).
- `volatil' (MEM_VOLATILE_P): During simplify_by_exploding the value of an
+ `volatil' (ATTR_EQ_ATTR_P): During simplify_by_exploding the value of an
EQ_ATTR rtx is true if !volatil and false if volatil. */
+#define ATTR_IND_SIMPLIFIED_P(RTX) (RTX_FLAG((RTX), unchanging))
+#define ATTR_CURR_SIMPLIFIED_P(RTX) (RTX_FLAG((RTX), in_struct))
+#define ATTR_PERMANENT_P(RTX) (RTX_FLAG((RTX), integrated))
+#define ATTR_EQ_ATTR_P(RTX) (RTX_FLAG((RTX), volatil))
+
#include "hconfig.h"
#include "system.h"
#include "rtl.h"
@@ -110,13 +115,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "obstack.h"
#include "errors.h"
+#include "genattrtab.h"
+
static struct obstack obstack1, obstack2;
struct obstack *hash_obstack = &obstack1;
struct obstack *temp_obstack = &obstack2;
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
/* enough space to reserve for printing out ints */
#define MAX_DIGITS (HOST_BITS_PER_INT * 3 / 10 + 3)
@@ -262,7 +266,7 @@ static struct function_unit *units;
The algorithm relies on sharing EQ_ATTR nodes: if two nodes in an
expression are the same, the will also have the same address. We find
- all the EQ_ATTR nodes by marking them MEM_VOLATILE_P. This bit later
+ all the EQ_ATTR nodes by marking them ATTR_EQ_ATTR_P. This bit later
represents the value of an EQ_ATTR node, so once all nodes are marked,
they are also given an initial value of FALSE.
@@ -304,6 +308,8 @@ static int have_annul_true, have_annul_false;
static int num_units, num_unit_opclasses;
static int num_insn_ents;
+int num_dfa_decls;
+
/* Used as operand to `operate_exp': */
enum operator {PLUS_OP, MINUS_OP, POS_MINUS_OP, EQ_OP, OR_OP, ORX_OP, MAX_OP, MIN_OP, RANGE_OP};
@@ -344,7 +350,7 @@ int optimize = 0;
/* Simplify an expression. Only call the routine if there is something to
simplify. */
#define SIMPLIFY_TEST_EXP(EXP,INSN_CODE,INSN_INDEX) \
- (RTX_UNCHANGING_P (EXP) || MEM_IN_STRUCT_P (EXP) ? (EXP) \
+ (ATTR_IND_SIMPLIFIED_P (EXP) || ATTR_CURR_SIMPLIFIED_P (EXP) ? (EXP) \
: simplify_test_exp (EXP, INSN_CODE, INSN_INDEX))
/* Simplify (eq_attr ("alternative") ...)
@@ -366,10 +372,7 @@ static void attr_hash_add_rtx PARAMS ((int, rtx));
static void attr_hash_add_string PARAMS ((int, char *));
static rtx attr_rtx PARAMS ((enum rtx_code, ...));
static rtx attr_rtx_1 PARAMS ((enum rtx_code, va_list));
-static char *attr_printf PARAMS ((unsigned int, const char *, ...))
- ATTRIBUTE_PRINTF_2;
static char *attr_string PARAMS ((const char *, int));
-static rtx check_attr_test PARAMS ((rtx, int, int));
static rtx check_attr_value PARAMS ((rtx, struct attr_desc *));
static rtx convert_set_attr_alternative PARAMS ((rtx, struct insn_def *));
static rtx convert_set_attr PARAMS ((rtx, struct insn_def *));
@@ -387,7 +390,6 @@ static void expand_units PARAMS ((void));
static rtx simplify_knowing PARAMS ((rtx, rtx));
static rtx encode_units_mask PARAMS ((rtx));
static void fill_attr PARAMS ((struct attr_desc *));
-/* dpx2 compiler chokes if we specify the arg types of the args. */
static rtx substitute_address PARAMS ((rtx, rtx (*) (rtx), rtx (*) (rtx)));
static void make_length_attrs PARAMS ((void));
static rtx identity_fn PARAMS ((rtx));
@@ -450,13 +452,10 @@ static void write_complex_function PARAMS ((struct function_unit *, const char *
static int write_expr_attr_cache PARAMS ((rtx, struct attr_desc *));
static void write_toplevel_expr PARAMS ((rtx));
static void write_const_num_delay_slots PARAMS ((void));
-static int n_comma_elts PARAMS ((const char *));
static char *next_comma_elt PARAMS ((const char **));
static struct attr_desc *find_attr PARAMS ((const char *, int));
-static void make_internal_attr PARAMS ((const char *, rtx, int));
static struct attr_value *find_most_used PARAMS ((struct attr_desc *));
static rtx find_single_value PARAMS ((struct attr_desc *));
-static rtx make_numeric_value PARAMS ((int));
static void extend_range PARAMS ((struct range *, int, int));
static rtx attr_eq PARAMS ((const char *, const char *));
static const char *attr_numeral PARAMS ((int));
@@ -532,10 +531,10 @@ attr_hash_add_string (hashcode, str)
}
/* Generate an RTL expression, but avoid duplicates.
- Set the RTX_INTEGRATED_P flag for these permanent objects.
+ Set the ATTR_PERMANENT_P flag for these permanent objects.
In some cases we cannot uniquify; then we return an ordinary
- impermanent rtx with RTX_INTEGRATED_P clear.
+ impermanent rtx with ATTR_PERMANENT_P clear.
Args are like gen_rtx, but without the mode:
@@ -560,7 +559,7 @@ attr_rtx_1 (code, p)
rtx arg0 = va_arg (p, rtx);
/* A permanent object cannot point to impermanent ones. */
- if (! RTX_INTEGRATED_P (arg0))
+ if (! ATTR_PERMANENT_P (arg0))
{
rt_val = rtx_alloc (code);
XEXP (rt_val, 0) = arg0;
@@ -589,7 +588,7 @@ attr_rtx_1 (code, p)
rtx arg1 = va_arg (p, rtx);
/* A permanent object cannot point to impermanent ones. */
- if (! RTX_INTEGRATED_P (arg0) || ! RTX_INTEGRATED_P (arg1))
+ if (! ATTR_PERMANENT_P (arg0) || ! ATTR_PERMANENT_P (arg1))
{
rt_val = rtx_alloc (code);
XEXP (rt_val, 0) = arg0;
@@ -713,7 +712,7 @@ attr_rtx_1 (code, p)
rtl_obstack = old_obstack;
attr_hash_add_rtx (hashcode, rt_val);
- RTX_INTEGRATED_P (rt_val) = 1;
+ ATTR_PERMANENT_P (rt_val) = 1;
return rt_val;
}
@@ -734,7 +733,7 @@ attr_rtx VPARAMS ((enum rtx_code code, ...))
rtx attr_printf (len, format, [arg1, ..., argn]) */
-static char *
+char *
attr_printf VPARAMS ((unsigned int len, const char *fmt, ...))
{
char str[256];
@@ -810,7 +809,7 @@ static int
attr_equal_p (x, y)
rtx x, y;
{
- return (x == y || (! (RTX_INTEGRATED_P (x) && RTX_INTEGRATED_P (y))
+ return (x == y || (! (ATTR_PERMANENT_P (x) && ATTR_PERMANENT_P (y))
&& rtx_equal_p (x, y)));
}
@@ -828,7 +827,7 @@ attr_copy_rtx (orig)
const char *format_ptr;
/* No need to copy a permanent object. */
- if (RTX_INTEGRATED_P (orig))
+ if (ATTR_PERMANENT_P (orig))
return orig;
code = GET_CODE (orig);
@@ -852,10 +851,10 @@ attr_copy_rtx (orig)
copy = rtx_alloc (code);
PUT_MODE (copy, GET_MODE (orig));
- copy->in_struct = orig->in_struct;
- copy->volatil = orig->volatil;
- copy->unchanging = orig->unchanging;
- copy->integrated = orig->integrated;
+ ATTR_IND_SIMPLIFIED_P (copy) = ATTR_IND_SIMPLIFIED_P (orig);
+ ATTR_CURR_SIMPLIFIED_P (copy) = ATTR_CURR_SIMPLIFIED_P (orig);
+ ATTR_PERMANENT_P (copy) = ATTR_PERMANENT_P (orig);
+ ATTR_EQ_ATTR_P (copy) = ATTR_EQ_ATTR_P (orig);
format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
@@ -915,7 +914,7 @@ attr_copy_rtx (orig)
Return the new expression, if any. */
-static rtx
+rtx
check_attr_test (exp, is_const, lineno)
rtx exp;
int is_const;
@@ -945,7 +944,7 @@ check_attr_test (exp, is_const, lineno)
{
XSTR (exp, 0) = alternative_name;
/* This can't be simplified any further. */
- RTX_UNCHANGING_P (exp) = 1;
+ ATTR_IND_SIMPLIFIED_P (exp) = 1;
return exp;
}
else
@@ -964,7 +963,7 @@ check_attr_test (exp, is_const, lineno)
constant attribute, so don't expand this until it's time to
write the test expression. */
if (attr->is_const)
- RTX_UNCHANGING_P (exp) = 1;
+ ATTR_IND_SIMPLIFIED_P (exp) = 1;
if (attr->is_numeric)
{
@@ -1026,7 +1025,7 @@ check_attr_test (exp, is_const, lineno)
fatal ("RTL operator \"%s\" not valid in constant attribute test",
GET_RTX_NAME (GET_CODE (exp)));
/* These cases can't be simplified. */
- RTX_UNCHANGING_P (exp) = 1;
+ ATTR_IND_SIMPLIFIED_P (exp) = 1;
break;
case LE: case LT: case GT: case GE:
@@ -1038,7 +1037,7 @@ check_attr_test (exp, is_const, lineno)
attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 0), 0)),
attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 1), 0)));
/* These cases can't be simplified. */
- RTX_UNCHANGING_P (exp) = 1;
+ ATTR_IND_SIMPLIFIED_P (exp) = 1;
break;
case SYMBOL_REF:
@@ -1047,7 +1046,7 @@ check_attr_test (exp, is_const, lineno)
/* These cases are valid for constant attributes, but can't be
simplified. */
exp = attr_rtx (SYMBOL_REF, XSTR (exp, 0));
- RTX_UNCHANGING_P (exp) = 1;
+ ATTR_IND_SIMPLIFIED_P (exp) = 1;
break;
}
default:
@@ -1405,7 +1404,7 @@ convert_const_symbol_ref (exp, attr)
*p = TOUPPER (*p);
value = attr_rtx (SYMBOL_REF, string);
- RTX_UNCHANGING_P (value) = 1;
+ ATTR_IND_SIMPLIFIED_P (value) = 1;
XVECEXP (condexp, 0, 2 * i) = attr_rtx (EQ, exp, value);
@@ -1446,18 +1445,18 @@ make_canonical (attr, exp)
break;
case SYMBOL_REF:
- if (!attr->is_const || RTX_UNCHANGING_P (exp))
+ if (!attr->is_const || ATTR_IND_SIMPLIFIED_P (exp))
break;
/* The SYMBOL_REF is constant for a given run, so mark it as unchanging.
This makes the COND something that won't be considered an arbitrary
expression by walk_attr_value. */
- RTX_UNCHANGING_P (exp) = 1;
+ ATTR_IND_SIMPLIFIED_P (exp) = 1;
#if 0
/* ??? Why do we do this? With attribute values { A B C D E }, this
tends to generate (!(x==A) && !(x==B) && !(x==C) && !(x==D)) rather
than (x==E). */
exp = convert_const_symbol_ref (exp, attr);
- RTX_UNCHANGING_P (exp) = 1;
+ ATTR_IND_SIMPLIFIED_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 marked as
@@ -1839,7 +1838,7 @@ operate_exp (op, left, right)
The first produces a function `function_units_used' which is given an
insn and produces an encoding showing which function units are required
for the execution of that insn. If the value is non-negative, the insn
- uses that unit; otherwise, the value is a one's compliment mask of units
+ uses that unit; otherwise, the value is a one's complement mask of units
used.
The second produces a function `result_ready_cost' which is used to
@@ -2094,7 +2093,7 @@ expand_units ()
fill the unit given the minimum issue delay. FILL-TIME is the
constant "MIN (ISSUE-DELAY (*,*)) * (SIMULTANEITY - 1)", and
the simultaneity constraint is "READY-COST (E) - FILL-TIME"
- if SIMULTANEITY is non-zero and zero otherwise.
+ if SIMULTANEITY is nonzero and zero otherwise.
Thus, BLOCKAGE (E,C) when SIMULTANEITY is zero is
@@ -2247,7 +2246,7 @@ simplify_knowing (exp, known_true)
/* Translate the CONST_STRING expressions in X to change the encoding of
value. On input, the value is a bitmask with a one bit for each unit
used; on output, the value is the unit number (zero based) if one
- and only one unit is used or the one's compliment of the bitmask. */
+ and only one unit is used or the one's complement of the bitmask. */
static rtx
encode_units_mask (x)
@@ -2265,7 +2264,7 @@ encode_units_mask (x)
case CONST_STRING:
i = atoi (XSTR (x, 0));
if (i < 0)
- /* The sign bit encodes a one's compliment mask. */
+ /* The sign bit encodes a one's complement mask. */
abort ();
else if (i != 0 && i == (i & -i))
/* Only one bit is set, so yield that unit number. */
@@ -2824,7 +2823,7 @@ make_alternative_compare (mask)
;
newexp = attr_rtx (EQ_ATTR, alternative_name, attr_numeral (i));
- RTX_UNCHANGING_P (newexp) = 1;
+ ATTR_IND_SIMPLIFIED_P (newexp) = 1;
return newexp;
}
@@ -2932,7 +2931,7 @@ evaluate_eq_attr (exp, value, insn_code, insn_index)
abort ();
/* If uses an address, must return original expression. But set the
- RTX_UNCHANGING_P bit so we don't try to simplify it again. */
+ ATTR_IND_SIMPLIFIED_P bit so we don't try to simplify it again. */
address_used = 0;
walk_attr_value (newexp);
@@ -2940,7 +2939,7 @@ evaluate_eq_attr (exp, value, insn_code, insn_index)
if (address_used)
{
/* This had `&& current_alternative_string', which seems to be wrong. */
- if (! RTX_UNCHANGING_P (exp))
+ if (! ATTR_IND_SIMPLIFIED_P (exp))
return copy_rtx_unchanging (exp);
return exp;
}
@@ -3198,7 +3197,7 @@ attr_rtx_cost (x)
/* Simplify test expression and use temporary obstack in order to avoid
- memory bloat. Use RTX_UNCHANGING_P to avoid unnecesary simplifications
+ memory bloat. Use ATTR_IND_SIMPLIFIED to avoid unnecesary simplifications
and avoid unnecesary copying if possible. */
static rtx
@@ -3208,7 +3207,7 @@ simplify_test_exp_in_temp (exp, insn_code, insn_index)
{
rtx x;
struct obstack *old;
- if (RTX_UNCHANGING_P (exp))
+ if (ATTR_IND_SIMPLIFIED_P (exp))
return exp;
old = rtl_obstack;
rtl_obstack = temp_obstack;
@@ -3241,7 +3240,7 @@ simplify_test_exp (exp, insn_code, insn_index)
rtx newexp = exp;
/* Don't re-simplify something we already simplified. */
- if (RTX_UNCHANGING_P (exp) || MEM_IN_STRUCT_P (exp))
+ if (ATTR_IND_SIMPLIFIED_P (exp) || ATTR_CURR_SIMPLIFIED_P (exp))
return exp;
switch (GET_CODE (exp))
@@ -3491,7 +3490,7 @@ simplify_test_exp (exp, insn_code, insn_index)
won't buy anything unless we weren't given a valid insn code
to process (i.e., we are canonicalizing something.). */
if (insn_code != -2 /* Seems wrong: && current_alternative_string. */
- && ! RTX_UNCHANGING_P (newexp))
+ && ! ATTR_IND_SIMPLIFIED_P (newexp))
return copy_rtx_unchanging (newexp);
return newexp;
@@ -3559,7 +3558,7 @@ optimize_attrs ()
/* Process one insn code at a time. */
for (i = -2; i < insn_code_number; i++)
{
- /* Clear the MEM_IN_STRUCT_P flag everywhere relevant.
+ /* Clear the ATTR_CURR_SIMPLIFIED_P flag everywhere relevant.
We use it to mean "already simplified for this insn". */
for (iv = insn_code_values[i]; iv; iv = iv->next)
clear_struct_flag (iv->av->value);
@@ -3747,13 +3746,13 @@ simplify_by_exploding (exp)
most_tests = -1;
for (i = num_marks = 0; i < total; i++)
if (GET_CODE (condval[i]) == CONST_STRING
- && ! MEM_VOLATILE_P (condval[i]))
+ && ! ATTR_EQ_ATTR_P (condval[i]))
{
/* Mark the unmarked constant value and count how many are marked. */
- MEM_VOLATILE_P (condval[i]) = 1;
+ ATTR_EQ_ATTR_P (condval[i]) = 1;
for (j = new_marks = 0; j < total; j++)
if (GET_CODE (condval[j]) == CONST_STRING
- && MEM_VOLATILE_P (condval[j]))
+ && ATTR_EQ_ATTR_P (condval[j]))
new_marks++;
if (new_marks - num_marks > most_tests)
{
@@ -3764,7 +3763,7 @@ simplify_by_exploding (exp)
}
/* Clear all the marks. */
for (i = 0; i < total; i++)
- MEM_VOLATILE_P (condval[i]) = 0;
+ ATTR_EQ_ATTR_P (condval[i]) = 0;
/* Give up if nothing is constant. */
if (num_marks == 0)
@@ -3796,7 +3795,7 @@ simplify_by_exploding (exp)
return ret;
}
-/* Set the MEM_VOLATILE_P flag for all EQ_ATTR expressions in EXP and
+/* Set the ATTR_EQ_ATTR_P flag for all EQ_ATTR expressions in EXP and
verify that EXP can be simplified to a constant term if all the EQ_ATTR
tests have known value. */
@@ -3810,14 +3809,14 @@ find_and_mark_used_attributes (exp, terms, nterms)
switch (GET_CODE (exp))
{
case EQ_ATTR:
- if (! MEM_VOLATILE_P (exp))
+ if (! ATTR_EQ_ATTR_P (exp))
{
rtx link = rtx_alloc (EXPR_LIST);
XEXP (link, 0) = exp;
XEXP (link, 1) = *terms;
*terms = link;
*nterms += 1;
- MEM_VOLATILE_P (exp) = 1;
+ ATTR_EQ_ATTR_P (exp) = 1;
}
return 1;
@@ -3850,7 +3849,7 @@ find_and_mark_used_attributes (exp, terms, nterms)
}
}
-/* Clear the MEM_VOLATILE_P flag in all EQ_ATTR expressions on LIST and
+/* Clear the ATTR_EQ_ATTR_P flag in all EQ_ATTR expressions on LIST and
in the values of the NDIM-dimensional attribute space SPACE. */
static void
@@ -3869,7 +3868,7 @@ unmark_used_attributes (list, space, ndim)
{
exp = XEXP (link, 0);
if (GET_CODE (exp) == EQ_ATTR)
- MEM_VOLATILE_P (exp) = 0;
+ ATTR_EQ_ATTR_P (exp) = 0;
}
}
@@ -3905,7 +3904,7 @@ add_values_to_cover (dim)
if (GET_CODE (av->value) == CONST_STRING)
{
exp = attr_eq (dim->attr->name, XSTR (av->value, 0));
- if (MEM_VOLATILE_P (exp))
+ if (ATTR_EQ_ATTR_P (exp))
continue;
link = rtx_alloc (EXPR_LIST);
@@ -3995,7 +3994,7 @@ simplify_with_current_value (exp, space, ndim)
{
x = XEXP (space[i].current_value, 0);
if (GET_CODE (x) == EQ_ATTR)
- MEM_VOLATILE_P (x) = 0;
+ ATTR_EQ_ATTR_P (x) = 0;
}
exp = simplify_with_current_value_aux (exp);
@@ -4005,13 +4004,13 @@ simplify_with_current_value (exp, space, ndim)
{
x = XEXP (space[i].current_value, 0);
if (GET_CODE (x) == EQ_ATTR)
- MEM_VOLATILE_P (x) = 1;
+ ATTR_EQ_ATTR_P (x) = 1;
}
return exp;
}
-/* Reduce the expression EXP based on the MEM_VOLATILE_P settings of
+/* Reduce the expression EXP based on the ATTR_EQ_ATTR_P settings of
all EQ_ATTR expressions. */
static rtx
@@ -4024,7 +4023,7 @@ simplify_with_current_value_aux (exp)
switch (GET_CODE (exp))
{
case EQ_ATTR:
- if (MEM_VOLATILE_P (exp))
+ if (ATTR_EQ_ATTR_P (exp))
return false_rtx;
else
return true_rtx;
@@ -4091,7 +4090,7 @@ simplify_with_current_value_aux (exp)
}
}
-/* Clear the MEM_IN_STRUCT_P flag in EXP and its subexpressions. */
+/* Clear the ATTR_CURR_SIMPLIFIED_P flag in EXP and its subexpressions. */
static void
clear_struct_flag (x)
@@ -4102,8 +4101,8 @@ clear_struct_flag (x)
enum rtx_code code;
const char *fmt;
- MEM_IN_STRUCT_P (x) = 0;
- if (RTX_UNCHANGING_P (x))
+ ATTR_CURR_SIMPLIFIED_P (x) = 0;
+ if (ATTR_IND_SIMPLIFIED_P (x))
return;
code = GET_CODE (x);
@@ -4316,7 +4315,7 @@ count_alternatives (exp)
return 0;
}
-/* Returns non-zero if the given expression contains an EQ_ATTR with the
+/* Returns nonzero if the given expression contains an EQ_ATTR with the
`alternative' attribute. */
static int
@@ -4349,7 +4348,7 @@ compares_alternatives_p (exp)
return 0;
}
-/* Returns non-zero is INNER is contained in EXP. */
+/* Returns nonzero is INNER is contained in EXP. */
static int
contained_in_p (inner, exp)
@@ -4559,7 +4558,7 @@ gen_unit (def, lineno)
/* Given a piece of RTX, print a C expression to test its truth value.
We use AND and IOR both for logical and bit-wise operations, so
interpret them as logical unless they are inside a comparison expression.
- The first bit of FLAGS will be non-zero in that case.
+ The first bit of FLAGS will be nonzero in that case.
Set the second bit of FLAGS to make references to attribute values use
a cached local variable instead of calling a function. */
@@ -4914,7 +4913,7 @@ walk_attr_value (exp)
switch (code)
{
case SYMBOL_REF:
- if (! RTX_UNCHANGING_P (exp))
+ if (! ATTR_IND_SIMPLIFIED_P (exp))
/* Since this is an arbitrary expression, it can look at anything.
However, constant expressions do not depend on any particular
insn. */
@@ -5489,7 +5488,7 @@ write_indent (indent)
}
/* Write a subroutine that is given an insn that requires a delay slot, a
- delay slot ordinal, and a candidate insn. It returns non-zero if the
+ delay slot ordinal, and a candidate insn. It returns nonzero if the
candidate can be placed in the specified delay slot of the insn.
We can write as many as three subroutines. `eligible_for_delay'
@@ -5688,6 +5687,8 @@ write_function_unit_info ()
printf ("}, \n");
}
+ if (num_units == 0)
+ printf ("{\"dummy\", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* a dummy element */");
printf ("};\n\n");
}
@@ -5787,25 +5788,6 @@ write_complex_function (unit, name, connection)
/* This page contains miscellaneous utility routines. */
-/* Given a string, return the number of comma-separated elements in it.
- Return 0 for the null string. */
-
-static int
-n_comma_elts (s)
- const char *s;
-{
- int n;
-
- if (*s == '\0')
- return 0;
-
- for (n = 1; *s; s++)
- if (*s == ',')
- n++;
-
- return n;
-}
-
/* Given a pointer to a (char *), return a malloc'ed string containing the
next comma-separated element. Advance the pointer to after the string
scanned, or the end-of-string. Return NULL if at end of string. */
@@ -5814,27 +5796,18 @@ static char *
next_comma_elt (pstr)
const char **pstr;
{
- char *out_str;
- const char *p;
-
- if (**pstr == '\0')
- return NULL;
+ const char *start;
- /* Find end of string to compute length. */
- for (p = *pstr; *p != ',' && *p != '\0'; p++)
- ;
-
- out_str = attr_string (*pstr, p - *pstr);
- *pstr = p;
+ start = scan_comma_elt (pstr);
- if (**pstr == ',')
- (*pstr)++;
+ if (start == NULL)
+ return NULL;
- return out_str;
+ return attr_string (start, *pstr - start);
}
/* Return a `struct attr_desc' pointer for a given named attribute. If CREATE
- is non-zero, build a new attribute, if one does not exist. */
+ is nonzero, build a new attribute, if one does not exist. */
static struct attr_desc *
find_attr (name, create)
@@ -5875,7 +5848,7 @@ find_attr (name, create)
/* Create internal attribute with the given default value. */
-static void
+void
make_internal_attr (name, value, special)
const char *name;
rtx value;
@@ -5942,7 +5915,7 @@ find_single_value (attr)
/* Return (attr_value "n") */
-static rtx
+rtx
make_numeric_value (n)
int n;
{
@@ -5986,10 +5959,10 @@ copy_rtx_unchanging (orig)
RTX_CODE code;
#endif
- if (RTX_UNCHANGING_P (orig) || MEM_IN_STRUCT_P (orig))
+ if (ATTR_IND_SIMPLIFIED_P (orig) || ATTR_CURR_SIMPLIFIED_P (orig))
return orig;
- MEM_IN_STRUCT_P (orig) = 1;
+ ATTR_CURR_SIMPLIFIED_P (orig) = 1;
return orig;
#if 0
@@ -6008,7 +5981,7 @@ copy_rtx_unchanging (orig)
copy = rtx_alloc (code);
PUT_MODE (copy, GET_MODE (orig));
- RTX_UNCHANGING_P (copy) = 1;
+ ATTR_IND_SIMPLIFIED_P (copy) = 1;
memcpy (&XEXP (copy, 0), &XEXP (orig, 0),
GET_RTX_LENGTH (GET_CODE (copy)) * sizeof (rtx));
@@ -6082,8 +6055,8 @@ main (argc, argv)
XWINT (true_rtx, 0) = 1;
false_rtx = rtx_alloc (CONST_INT);
XWINT (false_rtx, 0) = 0;
- RTX_UNCHANGING_P (true_rtx) = RTX_UNCHANGING_P (false_rtx) = 1;
- RTX_INTEGRATED_P (true_rtx) = RTX_INTEGRATED_P (false_rtx) = 1;
+ ATTR_IND_SIMPLIFIED_P (true_rtx) = ATTR_IND_SIMPLIFIED_P (false_rtx) = 1;
+ ATTR_PERMANENT_P (true_rtx) = ATTR_PERMANENT_P (false_rtx) = 1;
alternative_name = attr_string ("alternative", strlen ("alternative"));
@@ -6092,6 +6065,7 @@ from the machine description file `md'. */\n\n");
/* Read the machine description. */
+ initiate_automaton_gen (argc, argv);
while (1)
{
int lineno;
@@ -6120,6 +6094,46 @@ from the machine description file `md'. */\n\n");
gen_unit (desc, lineno);
break;
+ case DEFINE_CPU_UNIT:
+ gen_cpu_unit (desc);
+ break;
+
+ case DEFINE_QUERY_CPU_UNIT:
+ gen_query_cpu_unit (desc);
+ break;
+
+ case DEFINE_BYPASS:
+ gen_bypass (desc);
+ break;
+
+ case EXCLUSION_SET:
+ gen_excl_set (desc);
+ break;
+
+ case PRESENCE_SET:
+ gen_presence_set (desc);
+ break;
+
+ case ABSENCE_SET:
+ gen_absence_set (desc);
+ break;
+
+ case DEFINE_AUTOMATON:
+ gen_automaton (desc);
+ break;
+
+ case AUTOMATA_OPTION:
+ gen_automata_option (desc);
+ break;
+
+ case DEFINE_RESERVATION:
+ gen_reserv (desc);
+ break;
+
+ case DEFINE_INSN_RESERVATION:
+ gen_insn_reserv (desc);
+ break;
+
default:
break;
}
@@ -6144,9 +6158,14 @@ from the machine description file `md'. */\n\n");
if (num_delays)
expand_delays ();
- /* Expand DEFINE_FUNCTION_UNIT information into new attributes. */
- if (num_units)
- expand_units ();
+ if (num_units || num_dfa_decls)
+ {
+ /* Expand DEFINE_FUNCTION_UNIT information into new attributes. */
+ expand_units ();
+ /* Build DFA, output some functions and expand DFA information
+ into new attributes. */
+ expand_automata ();
+ }
printf ("#include \"config.h\"\n");
printf ("#include \"system.h\"\n");
@@ -6160,6 +6179,7 @@ from the machine description file `md'. */\n\n");
printf ("#include \"insn-attr.h\"\n");
printf ("#include \"toplev.h\"\n");
printf ("#include \"flags.h\"\n");
+ printf ("#include \"function.h\"\n");
printf ("\n");
printf ("#define operands recog_data.operand\n\n");
@@ -6221,9 +6241,14 @@ from the machine description file `md'. */\n\n");
write_eligible_delay ("annul_false");
}
- /* Write out information about function units. */
- if (num_units)
- write_function_unit_info ();
+ if (num_units || num_dfa_decls)
+ {
+ /* Write out information about function units. */
+ write_function_unit_info ();
+ /* Output code for pipeline hazards recognition based on DFA
+ (deterministic finite state automata. */
+ write_automata ();
+ }
/* Write out constant delay slot info */
write_const_num_delay_slots ();
diff --git a/contrib/gcc/genattrtab.h b/contrib/gcc/genattrtab.h
new file mode 100644
index 0000000..ea1f239
--- /dev/null
+++ b/contrib/gcc/genattrtab.h
@@ -0,0 +1,43 @@
+/* External definitions of source files of genattrtab.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Defined in genattrtab.c: */
+extern rtx check_attr_test PARAMS ((rtx, int, int));
+extern rtx make_numeric_value PARAMS ((int));
+extern void make_internal_attr PARAMS ((const char *, rtx, int));
+extern char *attr_printf PARAMS ((unsigned int, const char *, ...))
+ ATTRIBUTE_PRINTF_2;
+
+extern int num_dfa_decls;
+
+/* Defined in genautomata.c: */
+extern void gen_cpu_unit PARAMS ((rtx));
+extern void gen_query_cpu_unit PARAMS ((rtx));
+extern void gen_bypass PARAMS ((rtx));
+extern void gen_excl_set PARAMS ((rtx));
+extern void gen_presence_set PARAMS ((rtx));
+extern void gen_absence_set PARAMS ((rtx));
+extern void gen_automaton PARAMS ((rtx));
+extern void gen_automata_option PARAMS ((rtx));
+extern void gen_reserv PARAMS ((rtx));
+extern void gen_insn_reserv PARAMS ((rtx));
+extern void initiate_automaton_gen PARAMS ((int, char **));
+extern void expand_automata PARAMS ((void));
+extern void write_automata PARAMS ((void));
diff --git a/contrib/gcc/genautomata.c b/contrib/gcc/genautomata.c
new file mode 100644
index 0000000..8c48d6a
--- /dev/null
+++ b/contrib/gcc/genautomata.c
@@ -0,0 +1,9742 @@
+/* Pipeline hazard description translator.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+
+ Written by Vladimir Makarov <vmakarov@redhat.com>
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU CC is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+/* References:
+
+ 1. Detecting pipeline structural hazards quickly. T. Proebsting,
+ C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
+ Principles of Programming Languages, pages 280--286, 1994.
+
+ This article is a good start point to understand usage of finite
+ state automata for pipeline hazard recognizers. But I'd
+ recommend the 2nd article for more deep understanding.
+
+ 2. Efficient Instruction Scheduling Using Finite State Automata:
+ V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
+ article about usage of finite state automata for pipeline hazard
+ recognizers.
+
+ The current implementation is different from the 2nd article in the
+ following:
+
+ 1. New operator `|' (alternative) is permitted in functional unit
+ reservation which can be treated deterministicly and
+ non-deterministicly.
+
+ 2. Possibility of usage of nondeterministic automata too.
+
+ 3. Possibility to query functional unit reservations for given
+ automaton state.
+
+ 4. Several constructions to describe impossible reservations
+ (`exclusion_set', `presence_set', and `absence_set').
+
+ 5. No reverse automata are generated. Trace instruction scheduling
+ requires this. It can be easily added in the future if we
+ really need this.
+
+ 6. Union of automaton states are not generated yet. It is planned
+ to be implemented. Such feature is needed to make more accurate
+ interlock insn scheduling to get state describing functional
+ unit reservation in a joint CFG point.
+*/
+
+/* This file code processes constructions of machine description file
+ which describes automaton used for recognition of processor pipeline
+ hazards by insn scheduler and can be used for other tasks (such as
+ VLIW insn packing.
+
+ The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
+ `gen_bypass', `gen_excl_set', `gen_presence_set',
+ `gen_absence_set', `gen_automaton', `gen_automata_option',
+ `gen_reserv', `gen_insn_reserv' are called from file
+ `genattrtab.c'. They transform RTL constructions describing
+ automata in .md file into internal representation convenient for
+ further processing.
+
+ The translator major function `expand_automata' processes the
+ description internal representation into finite state automaton.
+ It can be divided on:
+
+ o checking correctness of the automaton pipeline description
+ (major function is `check_all_description').
+
+ o generating automaton (automata) from the description (major
+ function is `make_automaton').
+
+ o optional transformation of nondeterministic finite state
+ automata into deterministic ones if the alternative operator
+ `|' is treated nondeterministicly in the description (major
+ function is NDFA_to_DFA).
+
+ o optional minimization of the finite state automata by merging
+ equivalent automaton states (major function is `minimize_DFA').
+
+ o forming tables (some as comb vectors) and attributes
+ representing the automata (functions output_..._table).
+
+ Function `write_automata' outputs the created finite state
+ automaton as different tables and functions which works with the
+ automata to inquire automaton state and to change its state. These
+ function are used by gcc instruction scheduler and may be some
+ other gcc code. */
+
+#include "hconfig.h"
+#include "system.h"
+#include "rtl.h"
+#include "obstack.h"
+#include "errors.h"
+
+#include <math.h>
+#include "hashtab.h"
+#include "varray.h"
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+#include "genattrtab.h"
+
+/* Positions in machine description file. Now they are not used. But
+ they could be used in the future for better diagnostic messages. */
+typedef int pos_t;
+
+/* The following is element of vector of current (and planned in the
+ future) functional unit reservations. */
+typedef unsigned HOST_WIDE_INT set_el_t;
+
+/* Reservations of function units are represented by value of the following
+ type. */
+typedef set_el_t *reserv_sets_t;
+
+/* The following structure represents variable length array (vla) of
+ pointers and HOST WIDE INTs. We could be use only varray. But we
+ add new lay because we add elements very frequently and this could
+ stress OS allocator when varray is used only. */
+typedef struct {
+ size_t length; /* current size of vla. */
+ varray_type varray; /* container for vla. */
+} vla_ptr_t;
+
+typedef vla_ptr_t vla_hwint_t;
+
+/* The following structure describes a ticker. */
+struct ticker
+{
+ /* The following member value is time of the ticker creation with
+ taking into account time when the ticker is off. Active time of
+ the ticker is current time minus the value. */
+ int modified_creation_time;
+ /* The following member value is time (incremented by one) when the
+ ticker was off. Zero value means that now the ticker is on. */
+ int incremented_off_time;
+};
+
+/* The ticker is represented by the following type. */
+typedef struct ticker ticker_t;
+
+/* The following type describes elements of output vectors. */
+typedef HOST_WIDE_INT vect_el_t;
+
+/* Forward declaration of structures of internal representation of
+ pipeline description based on NDFA. */
+
+struct unit_decl;
+struct bypass_decl;
+struct result_decl;
+struct automaton_decl;
+struct unit_rel_decl;
+struct reserv_decl;
+struct insn_reserv_decl;
+struct decl;
+struct unit_regexp;
+struct result_regexp;
+struct reserv_regexp;
+struct nothing_regexp;
+struct sequence_regexp;
+struct repeat_regexp;
+struct allof_regexp;
+struct oneof_regexp;
+struct regexp;
+struct description;
+struct unit_set_el;
+struct state;
+struct alt_state;
+struct arc;
+struct ainsn;
+struct automaton;
+struct state_ainsn_table;
+
+/* The following typedefs are for brevity. */
+typedef struct unit_decl *unit_decl_t;
+typedef struct decl *decl_t;
+typedef struct regexp *regexp_t;
+typedef struct unit_set_el *unit_set_el_t;
+typedef struct alt_state *alt_state_t;
+typedef struct state *state_t;
+typedef struct arc *arc_t;
+typedef struct ainsn *ainsn_t;
+typedef struct automaton *automaton_t;
+typedef struct automata_list_el *automata_list_el_t;
+typedef struct state_ainsn_table *state_ainsn_table_t;
+
+
+/* Prototypes of functions gen_cpu_unit, gen_query_cpu_unit,
+ gen_bypass, gen_excl_set, gen_presence_set, gen_absence_set,
+ gen_automaton, gen_automata_option, gen_reserv, gen_insn_reserv,
+ initiate_automaton_gen, expand_automata, write_automata are
+ described on the file top because the functions are called from
+ function `main'. */
+
+static void *create_node PARAMS ((size_t));
+static void *copy_node PARAMS ((const void *, size_t));
+static char *check_name PARAMS ((char *, pos_t));
+static char *next_sep_el PARAMS ((char **, int, int));
+static int n_sep_els PARAMS ((char *, int, int));
+static char **get_str_vect PARAMS ((char *, int *, int, int));
+static regexp_t gen_regexp_el PARAMS ((char *));
+static regexp_t gen_regexp_repeat PARAMS ((char *));
+static regexp_t gen_regexp_allof PARAMS ((char *));
+static regexp_t gen_regexp_oneof PARAMS ((char *));
+static regexp_t gen_regexp_sequence PARAMS ((char *));
+static regexp_t gen_regexp PARAMS ((char *));
+
+static unsigned string_hash PARAMS ((const char *));
+static hashval_t automaton_decl_hash PARAMS ((const void *));
+static int automaton_decl_eq_p PARAMS ((const void *,
+ const void *));
+static decl_t insert_automaton_decl PARAMS ((decl_t));
+static decl_t find_automaton_decl PARAMS ((char *));
+static void initiate_automaton_decl_table PARAMS ((void));
+static void finish_automaton_decl_table PARAMS ((void));
+
+static hashval_t insn_decl_hash PARAMS ((const void *));
+static int insn_decl_eq_p PARAMS ((const void *,
+ const void *));
+static decl_t insert_insn_decl PARAMS ((decl_t));
+static decl_t find_insn_decl PARAMS ((char *));
+static void initiate_insn_decl_table PARAMS ((void));
+static void finish_insn_decl_table PARAMS ((void));
+
+static hashval_t decl_hash PARAMS ((const void *));
+static int decl_eq_p PARAMS ((const void *,
+ const void *));
+static decl_t insert_decl PARAMS ((decl_t));
+static decl_t find_decl PARAMS ((char *));
+static void initiate_decl_table PARAMS ((void));
+static void finish_decl_table PARAMS ((void));
+
+static unit_set_el_t process_excls PARAMS ((char **, int, pos_t));
+static void add_excls PARAMS ((unit_set_el_t, unit_set_el_t,
+ pos_t));
+static unit_set_el_t process_presence_absence
+ PARAMS ((char **, int, pos_t, int));
+static void add_presence_absence PARAMS ((unit_set_el_t, unit_set_el_t,
+ pos_t, int));
+static void process_decls PARAMS ((void));
+static struct bypass_decl *find_bypass PARAMS ((struct bypass_decl *,
+ struct insn_reserv_decl *));
+static void check_automaton_usage PARAMS ((void));
+static regexp_t process_regexp PARAMS ((regexp_t));
+static void process_regexp_decls PARAMS ((void));
+static void check_usage PARAMS ((void));
+static int loop_in_regexp PARAMS ((regexp_t, decl_t));
+static void check_loops_in_regexps PARAMS ((void));
+static int process_regexp_cycles PARAMS ((regexp_t, int));
+static void evaluate_max_reserv_cycles PARAMS ((void));
+static void check_all_description PARAMS ((void));
+
+static ticker_t create_ticker PARAMS ((void));
+static void ticker_off PARAMS ((ticker_t *));
+static void ticker_on PARAMS ((ticker_t *));
+static int active_time PARAMS ((ticker_t));
+static void print_active_time PARAMS ((FILE *, ticker_t));
+
+static void add_advance_cycle_insn_decl PARAMS ((void));
+
+static alt_state_t get_free_alt_state PARAMS ((void));
+static void free_alt_state PARAMS ((alt_state_t));
+static void free_alt_states PARAMS ((alt_state_t));
+static int alt_state_cmp PARAMS ((const void *alt_state_ptr_1,
+ const void *alt_state_ptr_2));
+static alt_state_t uniq_sort_alt_states PARAMS ((alt_state_t));
+static int alt_states_eq PARAMS ((alt_state_t, alt_state_t));
+static void initiate_alt_states PARAMS ((void));
+static void finish_alt_states PARAMS ((void));
+
+static reserv_sets_t alloc_empty_reserv_sets PARAMS ((void));
+static unsigned reserv_sets_hash_value PARAMS ((reserv_sets_t));
+static int reserv_sets_cmp PARAMS ((reserv_sets_t, reserv_sets_t));
+static int reserv_sets_eq PARAMS ((reserv_sets_t, reserv_sets_t));
+static void set_unit_reserv PARAMS ((reserv_sets_t, int, int));
+static int test_unit_reserv PARAMS ((reserv_sets_t, int, int));
+static int it_is_empty_reserv_sets PARAMS ((reserv_sets_t))
+ ATTRIBUTE_UNUSED;
+static int reserv_sets_are_intersected PARAMS ((reserv_sets_t, reserv_sets_t));
+static void reserv_sets_shift PARAMS ((reserv_sets_t, reserv_sets_t));
+static void reserv_sets_or PARAMS ((reserv_sets_t, reserv_sets_t,
+ reserv_sets_t));
+static void reserv_sets_and PARAMS ((reserv_sets_t, reserv_sets_t,
+ reserv_sets_t))
+ ATTRIBUTE_UNUSED;
+static void output_cycle_reservs PARAMS ((FILE *, reserv_sets_t,
+ int, int));
+static void output_reserv_sets PARAMS ((FILE *, reserv_sets_t));
+static state_t get_free_state PARAMS ((int, automaton_t));
+static void free_state PARAMS ((state_t));
+static hashval_t state_hash PARAMS ((const void *));
+static int state_eq_p PARAMS ((const void *, const void *));
+static state_t insert_state PARAMS ((state_t));
+static void set_state_reserv PARAMS ((state_t, int, int));
+static int intersected_state_reservs_p PARAMS ((state_t, state_t));
+static state_t states_union PARAMS ((state_t, state_t));
+static state_t state_shift PARAMS ((state_t));
+static void initiate_states PARAMS ((void));
+static void finish_states PARAMS ((void));
+
+static void free_arc PARAMS ((arc_t));
+static void remove_arc PARAMS ((state_t, arc_t));
+static arc_t find_arc PARAMS ((state_t, state_t, ainsn_t));
+static arc_t add_arc PARAMS ((state_t, state_t, ainsn_t, int));
+static arc_t first_out_arc PARAMS ((state_t));
+static arc_t next_out_arc PARAMS ((arc_t));
+static void initiate_arcs PARAMS ((void));
+static void finish_arcs PARAMS ((void));
+
+static automata_list_el_t get_free_automata_list_el PARAMS ((void));
+static void free_automata_list_el PARAMS ((automata_list_el_t));
+static void free_automata_list PARAMS ((automata_list_el_t));
+static hashval_t automata_list_hash PARAMS ((const void *));
+static int automata_list_eq_p PARAMS ((const void *, const void *));
+static void initiate_automata_lists PARAMS ((void));
+static void automata_list_start PARAMS ((void));
+static void automata_list_add PARAMS ((automaton_t));
+static automata_list_el_t automata_list_finish PARAMS ((void));
+static void finish_automata_lists PARAMS ((void));
+
+static void initiate_excl_sets PARAMS ((void));
+static reserv_sets_t get_excl_set PARAMS ((reserv_sets_t));
+
+static void initiate_presence_absence_sets PARAMS ((void));
+static reserv_sets_t get_presence_absence_set PARAMS ((reserv_sets_t, int));
+
+static regexp_t copy_insn_regexp PARAMS ((regexp_t));
+static regexp_t transform_1 PARAMS ((regexp_t));
+static regexp_t transform_2 PARAMS ((regexp_t));
+static regexp_t transform_3 PARAMS ((regexp_t));
+static regexp_t regexp_transform_func
+ PARAMS ((regexp_t, regexp_t (*) (regexp_t)));
+static regexp_t transform_regexp PARAMS ((regexp_t));
+static void transform_insn_regexps PARAMS ((void));
+
+static void process_unit_to_form_the_same_automaton_unit_lists
+ PARAMS ((regexp_t, regexp_t, int));
+static void form_the_same_automaton_unit_lists_from_regexp PARAMS ((regexp_t));
+static void form_the_same_automaton_unit_lists PARAMS ((void));
+static void check_unit_distributions_to_automata PARAMS ((void));
+
+static int process_seq_for_forming_states PARAMS ((regexp_t, automaton_t,
+ int));
+static void finish_forming_alt_state PARAMS ((alt_state_t,
+ automaton_t));
+static void process_alts_for_forming_states PARAMS ((regexp_t,
+ automaton_t, int));
+static void create_alt_states PARAMS ((automaton_t));
+
+static void form_ainsn_with_same_reservs PARAMS ((automaton_t));
+
+static void make_automaton PARAMS ((automaton_t));
+static void form_arcs_marked_by_insn PARAMS ((state_t));
+static void create_composed_state PARAMS ((state_t, arc_t, vla_ptr_t *));
+static void NDFA_to_DFA PARAMS ((automaton_t));
+static void pass_state_graph PARAMS ((state_t, void (*) (state_t)));
+static void pass_states PARAMS ((automaton_t,
+ void (*) (state_t)));
+static void initiate_pass_states PARAMS ((void));
+static void add_achieved_state PARAMS ((state_t));
+static int set_out_arc_insns_equiv_num PARAMS ((state_t, int));
+static void clear_arc_insns_equiv_num PARAMS ((state_t));
+static void copy_equiv_class PARAMS ((vla_ptr_t *to,
+ const vla_ptr_t *from));
+static int state_is_differed PARAMS ((state_t, int, int));
+static state_t init_equiv_class PARAMS ((state_t *states, int));
+static int partition_equiv_class PARAMS ((state_t *, int,
+ vla_ptr_t *, int *));
+static void evaluate_equiv_classes PARAMS ((automaton_t, vla_ptr_t *));
+static void merge_states PARAMS ((automaton_t, vla_ptr_t *));
+static void set_new_cycle_flags PARAMS ((state_t));
+static void minimize_DFA PARAMS ((automaton_t));
+static void incr_states_and_arcs_nums PARAMS ((state_t));
+static void count_states_and_arcs PARAMS ((automaton_t, int *, int *));
+static void build_automaton PARAMS ((automaton_t));
+
+static void set_order_state_num PARAMS ((state_t));
+static void enumerate_states PARAMS ((automaton_t));
+
+static ainsn_t insert_ainsn_into_equiv_class PARAMS ((ainsn_t, ainsn_t));
+static void delete_ainsn_from_equiv_class PARAMS ((ainsn_t));
+static void process_insn_equiv_class PARAMS ((ainsn_t, arc_t *));
+static void process_state_for_insn_equiv_partition PARAMS ((state_t));
+static void set_insn_equiv_classes PARAMS ((automaton_t));
+
+static double estimate_one_automaton_bound PARAMS ((void));
+static int compare_max_occ_cycle_nums PARAMS ((const void *,
+ const void *));
+static void units_to_automata_heuristic_distr PARAMS ((void));
+static ainsn_t create_ainsns PARAMS ((void));
+static void units_to_automata_distr PARAMS ((void));
+static void create_automata PARAMS ((void));
+
+static void form_regexp PARAMS ((regexp_t));
+static const char *regexp_representation PARAMS ((regexp_t));
+static void finish_regexp_representation PARAMS ((void));
+
+static void output_range_type PARAMS ((FILE *, long int, long int));
+static int longest_path_length PARAMS ((state_t));
+static void process_state_longest_path_length PARAMS ((state_t));
+static void output_dfa_max_issue_rate PARAMS ((void));
+static void output_vect PARAMS ((vect_el_t *, int));
+static void output_chip_member_name PARAMS ((FILE *, automaton_t));
+static void output_temp_chip_member_name PARAMS ((FILE *, automaton_t));
+static void output_translate_vect_name PARAMS ((FILE *, automaton_t));
+static void output_trans_full_vect_name PARAMS ((FILE *, automaton_t));
+static void output_trans_comb_vect_name PARAMS ((FILE *, automaton_t));
+static void output_trans_check_vect_name PARAMS ((FILE *, automaton_t));
+static void output_trans_base_vect_name PARAMS ((FILE *, automaton_t));
+static void output_state_alts_full_vect_name PARAMS ((FILE *, automaton_t));
+static void output_state_alts_comb_vect_name PARAMS ((FILE *, automaton_t));
+static void output_state_alts_check_vect_name PARAMS ((FILE *, automaton_t));
+static void output_state_alts_base_vect_name PARAMS ((FILE *, automaton_t));
+static void output_min_issue_delay_vect_name PARAMS ((FILE *, automaton_t));
+static void output_dead_lock_vect_name PARAMS ((FILE *, automaton_t));
+static void output_reserved_units_table_name PARAMS ((FILE *, automaton_t));
+static void output_state_member_type PARAMS ((FILE *, automaton_t));
+static void output_chip_definitions PARAMS ((void));
+static void output_translate_vect PARAMS ((automaton_t));
+static int comb_vect_p PARAMS ((state_ainsn_table_t));
+static state_ainsn_table_t create_state_ainsn_table PARAMS ((automaton_t));
+static void output_state_ainsn_table
+ PARAMS ((state_ainsn_table_t, char *, void (*) (FILE *, automaton_t),
+ void (*) (FILE *, automaton_t), void (*) (FILE *, automaton_t),
+ void (*) (FILE *, automaton_t)));
+static void add_vect PARAMS ((state_ainsn_table_t,
+ int, vect_el_t *, int));
+static int out_state_arcs_num PARAMS ((state_t));
+static int compare_transition_els_num PARAMS ((const void *, const void *));
+static void add_vect_el PARAMS ((vla_hwint_t *,
+ ainsn_t, int));
+static void add_states_vect_el PARAMS ((state_t));
+static void output_trans_table PARAMS ((automaton_t));
+static void output_state_alts_table PARAMS ((automaton_t));
+static int min_issue_delay_pass_states PARAMS ((state_t, ainsn_t));
+static int min_issue_delay PARAMS ((state_t, ainsn_t));
+static void initiate_min_issue_delay_pass_states PARAMS ((void));
+static void output_min_issue_delay_table PARAMS ((automaton_t));
+static void output_dead_lock_vect PARAMS ((automaton_t));
+static void output_reserved_units_table PARAMS ((automaton_t));
+static void output_tables PARAMS ((void));
+static void output_max_insn_queue_index_def PARAMS ((void));
+static void output_insn_code_cases PARAMS ((void (*) (automata_list_el_t)));
+static void output_automata_list_min_issue_delay_code PARAMS ((automata_list_el_t));
+static void output_internal_min_issue_delay_func PARAMS ((void));
+static void output_automata_list_transition_code PARAMS ((automata_list_el_t));
+static void output_internal_trans_func PARAMS ((void));
+static void output_internal_insn_code_evaluation PARAMS ((const char *,
+ const char *, int));
+static void output_dfa_insn_code_func PARAMS ((void));
+static void output_trans_func PARAMS ((void));
+static void output_automata_list_state_alts_code PARAMS ((automata_list_el_t));
+static void output_internal_state_alts_func PARAMS ((void));
+static void output_state_alts_func PARAMS ((void));
+static void output_min_issue_delay_func PARAMS ((void));
+static void output_internal_dead_lock_func PARAMS ((void));
+static void output_dead_lock_func PARAMS ((void));
+static void output_internal_reset_func PARAMS ((void));
+static void output_size_func PARAMS ((void));
+static void output_reset_func PARAMS ((void));
+static void output_min_insn_conflict_delay_func PARAMS ((void));
+static void output_internal_insn_latency_func PARAMS ((void));
+static void output_insn_latency_func PARAMS ((void));
+static void output_print_reservation_func PARAMS ((void));
+static int units_cmp PARAMS ((const void *,
+ const void *));
+static void output_get_cpu_unit_code_func PARAMS ((void));
+static void output_cpu_unit_reservation_p PARAMS ((void));
+static void output_dfa_start_func PARAMS ((void));
+static void output_dfa_finish_func PARAMS ((void));
+
+static void output_regexp PARAMS ((regexp_t ));
+static void output_unit_set_el_list PARAMS ((unit_set_el_t));
+static void output_description PARAMS ((void));
+static void output_automaton_name PARAMS ((FILE *, automaton_t));
+static void output_automaton_units PARAMS ((automaton_t));
+static void add_state_reservs PARAMS ((state_t));
+static void output_state_arcs PARAMS ((state_t));
+static int state_reservs_cmp PARAMS ((const void *,
+ const void *));
+static void remove_state_duplicate_reservs PARAMS ((void));
+static void output_state PARAMS ((state_t));
+static void output_automaton_descriptions PARAMS ((void));
+static void output_statistics PARAMS ((FILE *));
+static void output_time_statistics PARAMS ((FILE *));
+static void generate PARAMS ((void));
+
+static void make_insn_alts_attr PARAMS ((void));
+static void make_internal_dfa_insn_code_attr PARAMS ((void));
+static void make_default_insn_latency_attr PARAMS ((void));
+static void make_bypass_attr PARAMS ((void));
+static const char *file_name_suffix PARAMS ((const char *));
+static const char *base_file_name PARAMS ((const char *));
+static void check_automata_insn_issues PARAMS ((void));
+static void add_automaton_state PARAMS ((state_t));
+static void form_important_insn_automata_lists PARAMS ((void));
+
+/* Undefined position. */
+static pos_t no_pos = 0;
+
+/* All IR is stored in the following obstack. */
+static struct obstack irp;
+
+
+
+/* This page contains code for work with variable length array (vla)
+ of pointers. We could be use only varray. But we add new lay
+ because we add elements very frequently and this could stress OS
+ allocator when varray is used only. */
+
+/* Start work with vla. */
+#define VLA_PTR_CREATE(vla, allocated_length, name) \
+ do \
+ { \
+ vla_ptr_t *const vla_ptr = &(vla); \
+ \
+ VARRAY_GENERIC_PTR_INIT (vla_ptr->varray, allocated_length, name);\
+ vla_ptr->length = 0; \
+ } \
+ while (0)
+
+/* Finish work with the vla. */
+#define VLA_PTR_DELETE(vla) VARRAY_FREE ((vla).varray)
+
+/* Return start address of the vla. */
+#define VLA_PTR_BEGIN(vla) ((void *) &VARRAY_GENERIC_PTR ((vla).varray, 0))
+
+/* Address of the last element of the vla. Do not use side effects in
+ the macro argument. */
+#define VLA_PTR_LAST(vla) (&VARRAY_GENERIC_PTR ((vla).varray, \
+ (vla).length - 1))
+/* Nullify the vla. */
+#define VLA_PTR_NULLIFY(vla) ((vla).length = 0)
+
+/* Shorten the vla on given number bytes. */
+#define VLA_PTR_SHORTEN(vla, n) ((vla).length -= (n))
+
+/* Expand the vla on N elements. The values of new elements are
+ undefined. */
+#define VLA_PTR_EXPAND(vla, n) \
+ do { \
+ vla_ptr_t *const expand_vla_ptr = &(vla); \
+ const size_t new_length = (n) + expand_vla_ptr->length; \
+ \
+ if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
+ VARRAY_GROW (expand_vla_ptr->varray, \
+ (new_length - expand_vla_ptr->length < 128 \
+ ? expand_vla_ptr->length + 128 : new_length)); \
+ expand_vla_ptr->length = new_length; \
+ } while (0)
+
+/* Add element to the end of the vla. */
+#define VLA_PTR_ADD(vla, ptr) \
+ do { \
+ vla_ptr_t *const vla_ptr = &(vla); \
+ \
+ VLA_PTR_EXPAND (*vla_ptr, 1); \
+ VARRAY_GENERIC_PTR (vla_ptr->varray, vla_ptr->length - 1) = (ptr);\
+ } while (0)
+
+/* Length of the vla in elements. */
+#define VLA_PTR_LENGTH(vla) ((vla).length)
+
+/* N-th element of the vla. */
+#define VLA_PTR(vla, n) VARRAY_GENERIC_PTR ((vla).varray, n)
+
+
+/* The following macros are analogous to the previous ones but for
+ VLAs of HOST WIDE INTs. */
+
+#define VLA_HWINT_CREATE(vla, allocated_length, name) \
+ do { \
+ vla_hwint_t *const vla_ptr = &(vla); \
+ \
+ VARRAY_WIDE_INT_INIT (vla_ptr->varray, allocated_length, name); \
+ vla_ptr->length = 0; \
+ } while (0)
+
+#define VLA_HWINT_DELETE(vla) VARRAY_FREE ((vla).varray)
+
+#define VLA_HWINT_BEGIN(vla) (&VARRAY_WIDE_INT ((vla).varray, 0))
+
+#define VLA_HWINT_NULLIFY(vla) ((vla).length = 0)
+
+#define VLA_HWINT_EXPAND(vla, n) \
+ do { \
+ vla_hwint_t *const expand_vla_ptr = &(vla); \
+ const size_t new_length = (n) + expand_vla_ptr->length; \
+ \
+ if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
+ VARRAY_GROW (expand_vla_ptr->varray, \
+ (new_length - expand_vla_ptr->length < 128 \
+ ? expand_vla_ptr->length + 128 : new_length)); \
+ expand_vla_ptr->length = new_length; \
+ } while (0)
+
+#define VLA_HWINT_ADD(vla, ptr) \
+ do { \
+ vla_hwint_t *const vla_ptr = &(vla); \
+ \
+ VLA_HWINT_EXPAND (*vla_ptr, 1); \
+ VARRAY_WIDE_INT (vla_ptr->varray, vla_ptr->length - 1) = (ptr); \
+ } while (0)
+
+#define VLA_HWINT_LENGTH(vla) ((vla).length)
+
+#define VLA_HWINT(vla, n) VARRAY_WIDE_INT ((vla).varray, n)
+
+
+
+/* Options with the following names can be set up in automata_option
+ construction. Because the strings occur more one time we use the
+ macros. */
+
+#define NO_MINIMIZATION_OPTION "-no-minimization"
+
+#define TIME_OPTION "-time"
+
+#define V_OPTION "-v"
+
+#define W_OPTION "-w"
+
+#define NDFA_OPTION "-ndfa"
+
+/* The following flags are set up by function `initiate_automaton_gen'. */
+
+/* Make automata with nondeterministic reservation by insns (`-ndfa'). */
+static int ndfa_flag;
+
+/* Do not make minimization of DFA (`-no-minimization'). */
+static int no_minimization_flag;
+
+/* Value of this variable is number of automata being generated. The
+ actual number of automata may be less this value if there is not
+ sufficient number of units. This value is defined by argument of
+ option `-split' or by constructions automaton if the value is zero
+ (it is default value of the argument). */
+static int split_argument;
+
+/* Flag of output time statistics (`-time'). */
+static int time_flag;
+
+/* Flag of creation of description file which contains description of
+ result automaton and statistics information (`-v'). */
+static int v_flag;
+
+/* Flag of generating warning instead of error for non-critical errors
+ (`-w'). */
+static int w_flag;
+
+
+/* Output file for pipeline hazard recognizer (PHR) being generated.
+ The value is NULL if the file is not defined. */
+static FILE *output_file;
+
+/* Description file of PHR. The value is NULL if the file is not
+ created. */
+static FILE *output_description_file;
+
+/* PHR description file name. */
+static char *output_description_file_name;
+
+/* Value of the following variable is node representing description
+ being processed. This is start point of IR. */
+static struct description *description;
+
+
+
+/* This page contains description of IR structure (nodes). */
+
+enum decl_mode
+{
+ dm_unit,
+ dm_bypass,
+ dm_automaton,
+ dm_excl,
+ dm_presence,
+ dm_absence,
+ dm_reserv,
+ dm_insn_reserv
+};
+
+/* This describes define_cpu_unit and define_query_cpu_unit (see file
+ rtl.def). */
+struct unit_decl
+{
+ char *name;
+ /* NULL if the automaton name is absent. */
+ char *automaton_name;
+ /* If the following value is not zero, the cpu unit reservation is
+ described in define_query_cpu_unit. */
+ char query_p;
+
+ /* The following fields are defined by checker. */
+
+ /* The following field value is nonzero if the unit is used in an
+ regexp. */
+ char unit_is_used;
+
+ /* The following field value is used to form cyclic lists of units
+ which should be in the same automaton because the unit is
+ reserved not on all alternatives of a regexp on a cycle. */
+ unit_decl_t the_same_automaton_unit;
+ /* The following field is TRUE if we already reported that the unit
+ is not in the same automaton. */
+ int the_same_automaton_message_reported_p;
+
+ /* The following field value is order number (0, 1, ...) of given
+ unit. */
+ int unit_num;
+ /* The following field value is corresponding declaration of
+ automaton which was given in description. If the field value is
+ NULL then automaton in the unit declaration was absent. */
+ struct automaton_decl *automaton_decl;
+ /* The following field value is maximal cycle number (1, ...) on
+ which given unit occurs in insns. Zero value means that given
+ unit is not used in insns. */
+ int max_occ_cycle_num;
+ /* The following list contains units which conflict with given
+ unit. */
+ unit_set_el_t excl_list;
+ /* The following list contains units which are required to
+ reservation of given unit. */
+ unit_set_el_t presence_list;
+ /* The following list contains units which should be not present in
+ reservation for given unit. */
+ unit_set_el_t absence_list;
+ /* The following is used only when `query_p' has nonzero value.
+ This is query number for the unit. */
+ int query_num;
+
+ /* The following fields are defined by automaton generator. */
+
+ /* The following field value is number of the automaton to which
+ given unit belongs. */
+ int corresponding_automaton_num;
+};
+
+/* This describes define_bypass (see file rtl.def). */
+struct bypass_decl
+{
+ int latency;
+ char *out_insn_name;
+ char *in_insn_name;
+ char *bypass_guard_name;
+
+ /* The following fields are defined by checker. */
+
+ /* output and input insns of given bypass. */
+ struct insn_reserv_decl *out_insn_reserv;
+ struct insn_reserv_decl *in_insn_reserv;
+ /* The next bypass for given output insn. */
+ struct bypass_decl *next;
+};
+
+/* This describes define_automaton (see file rtl.def). */
+struct automaton_decl
+{
+ char *name;
+
+ /* The following fields are defined by automaton generator. */
+
+ /* The following field value is nonzero if the automaton is used in
+ an regexp definition. */
+ char automaton_is_used;
+
+ /* The following fields are defined by checker. */
+
+ /* The following field value is the corresponding automaton. This
+ field is not NULL only if the automaton is present in unit
+ declarations and the automatic partition on automata is not
+ used. */
+ automaton_t corresponding_automaton;
+};
+
+/* This describes unit relations: exclusion_set, presence_set, or
+ absence_set (see file rtl.def). */
+struct unit_rel_decl
+{
+ int names_num;
+ int first_list_length;
+ char *names [1];
+};
+
+/* This describes define_reservation (see file rtl.def). */
+struct reserv_decl
+{
+ char *name;
+ regexp_t regexp;
+
+ /* The following fields are defined by checker. */
+
+ /* The following field value is nonzero if the unit is used in an
+ regexp. */
+ char reserv_is_used;
+ /* The following field is used to check up cycle in expression
+ definition. */
+ int loop_pass_num;
+};
+
+/* This describes define_insn_reservartion (see file rtl.def). */
+struct insn_reserv_decl
+{
+ rtx condexp;
+ int default_latency;
+ regexp_t regexp;
+ char *name;
+
+ /* The following fields are defined by checker. */
+
+ /* The following field value is order number (0, 1, ...) of given
+ insn. */
+ int insn_num;
+ /* The following field value is list of bypasses in which given insn
+ is output insn. */
+ struct bypass_decl *bypass_list;
+
+ /* The following fields are defined by automaton generator. */
+
+ /* The following field is the insn regexp transformed that
+ the regexp has not optional regexp, repetition regexp, and an
+ reservation name (i.e. reservation identifiers are changed by the
+ corresponding regexp) and all alternations are the topest level
+ of the regexp. The value can be NULL only if it is special
+ insn `cycle advancing'. */
+ regexp_t transformed_regexp;
+ /* The following field value is list of arcs marked given
+ insn. The field is used in transfromation NDFA -> DFA. */
+ arc_t arcs_marked_by_insn;
+ /* The two following fields are used during minimization of a finite state
+ automaton. */
+ /* The field value is number of equivalence class of state into
+ which arc marked by given insn enters from a state (fixed during
+ an automaton minimization). */
+ int equiv_class_num;
+ /* The field value is state_alts of arc leaving a state (fixed
+ during an automaton minimization) and marked by given insn
+ enters. */
+ int state_alts;
+ /* The following member value is the list to automata which can be
+ changed by the insn issue. */
+ automata_list_el_t important_automata_list;
+ /* The following member is used to process insn once for output. */
+ int processed_p;
+};
+
+/* This contains a declaration mentioned above. */
+struct decl
+{
+ /* What node in the union? */
+ enum decl_mode mode;
+ pos_t pos;
+ union
+ {
+ struct unit_decl unit;
+ struct bypass_decl bypass;
+ struct automaton_decl automaton;
+ struct unit_rel_decl excl;
+ struct unit_rel_decl presence;
+ struct unit_rel_decl absence;
+ struct reserv_decl reserv;
+ struct insn_reserv_decl insn_reserv;
+ } decl;
+};
+
+/* The following structures represent parsed reservation strings. */
+enum regexp_mode
+{
+ rm_unit,
+ rm_reserv,
+ rm_nothing,
+ rm_sequence,
+ rm_repeat,
+ rm_allof,
+ rm_oneof
+};
+
+/* Cpu unit in reservation. */
+struct unit_regexp
+{
+ char *name;
+ unit_decl_t unit_decl;
+};
+
+/* Define_reservation in a reservation. */
+struct reserv_regexp
+{
+ char *name;
+ struct reserv_decl *reserv_decl;
+};
+
+/* Absence of reservation (represented by string `nothing'). */
+struct nothing_regexp
+{
+ /* This used to be empty but ISO C doesn't allow that. */
+ char unused;
+};
+
+/* Representation of reservations separated by ',' (see file
+ rtl.def). */
+struct sequence_regexp
+{
+ int regexps_num;
+ regexp_t regexps [1];
+};
+
+/* Representation of construction `repeat' (see file rtl.def). */
+struct repeat_regexp
+{
+ int repeat_num;
+ regexp_t regexp;
+};
+
+/* Representation of reservations separated by '+' (see file
+ rtl.def). */
+struct allof_regexp
+{
+ int regexps_num;
+ regexp_t regexps [1];
+};
+
+/* Representation of reservations separated by '|' (see file
+ rtl.def). */
+struct oneof_regexp
+{
+ int regexps_num;
+ regexp_t regexps [1];
+};
+
+/* Representation of a reservation string. */
+struct regexp
+{
+ /* What node in the union? */
+ enum regexp_mode mode;
+ pos_t pos;
+ union
+ {
+ struct unit_regexp unit;
+ struct reserv_regexp reserv;
+ struct nothing_regexp nothing;
+ struct sequence_regexp sequence;
+ struct repeat_regexp repeat;
+ struct allof_regexp allof;
+ struct oneof_regexp oneof;
+ } regexp;
+};
+
+/* Reperesents description of pipeline hazard description based on
+ NDFA. */
+struct description
+{
+ int decls_num;
+
+ /* The following fields are defined by checker. */
+
+ /* The following fields values are correspondingly number of all
+ units, query units, and insns in the description. */
+ int units_num;
+ int query_units_num;
+ int insns_num;
+ /* The following field value is max length (in cycles) of
+ reservations of insns. The field value is defined only for
+ correct programs. */
+ int max_insn_reserv_cycles;
+
+ /* The following fields are defined by automaton generator. */
+
+ /* The following field value is the first automaton. */
+ automaton_t first_automaton;
+
+ /* The following field is created by pipeline hazard parser and
+ contains all declarations. We allocate additional entry for
+ special insn "cycle advancing" which is added by the automaton
+ generator. */
+ decl_t decls [1];
+};
+
+
+
+/* The following nodes are created in automaton checker. */
+
+/* The following nodes represent exclusion, presence, absence set for
+ cpu units. Each element are accessed through only one excl_list,
+ presence_list, absence_list. */
+struct unit_set_el
+{
+ unit_decl_t unit_decl;
+ unit_set_el_t next_unit_set_el;
+};
+
+
+
+/* The following nodes are created in automaton generator. */
+
+/* The following node type describes state automaton. The state may
+ be deterministic or non-deterministic. Non-deterministic state has
+ several component states which represent alternative cpu units
+ reservations. The state also is used for describing a
+ deterministic reservation of automaton insn. */
+struct state
+{
+ /* The following member value is nonzero if there is a transition by
+ cycle advancing. */
+ int new_cycle_p;
+ /* The following field is list of processor unit reservations on
+ each cycle. */
+ reserv_sets_t reservs;
+ /* The following field is unique number of given state between other
+ states. */
+ int unique_num;
+ /* The following field value is automaton to which given state
+ belongs. */
+ automaton_t automaton;
+ /* The following field value is the first arc output from given
+ state. */
+ arc_t first_out_arc;
+ /* The following field is used to form NDFA. */
+ char it_was_placed_in_stack_for_NDFA_forming;
+ /* The following field is used to form DFA. */
+ char it_was_placed_in_stack_for_DFA_forming;
+ /* The following field is used to transform NDFA to DFA. The field
+ value is not NULL if the state is a compound state. In this case
+ the value of field `unit_sets_list' is NULL. All states in the
+ list are in the hash table. The list is formed through field
+ `next_sorted_alt_state'. */
+ alt_state_t component_states;
+ /* The following field is used for passing graph of states. */
+ int pass_num;
+ /* The list of states belonging to one equivalence class is formed
+ with the aid of the following field. */
+ state_t next_equiv_class_state;
+ /* The two following fields are used during minimization of a finite
+ state automaton. */
+ int equiv_class_num_1, equiv_class_num_2;
+ /* The following field is used during minimization of a finite state
+ automaton. The field value is state corresponding to equivalence
+ class to which given state belongs. */
+ state_t equiv_class_state;
+ /* The following field value is the order number of given state.
+ The states in final DFA is enumerated with the aid of the
+ following field. */
+ int order_state_num;
+ /* This member is used for passing states for searching minimal
+ delay time. */
+ int state_pass_num;
+ /* The following member is used to evaluate min issue delay of insn
+ for a state. */
+ int min_insn_issue_delay;
+ /* The following member is used to evaluate max issue rate of the
+ processor. The value of the member is maximal length of the path
+ from given state no containing arcs marked by special insn `cycle
+ advancing'. */
+ int longest_path_length;
+};
+
+/* The following macro is an initial value of member
+ `longest_path_length' of a state. */
+#define UNDEFINED_LONGEST_PATH_LENGTH -1
+
+/* Automaton arc. */
+struct arc
+{
+ /* The following field refers for the state into which given arc
+ enters. */
+ state_t to_state;
+ /* The following field describes that the insn issue (with cycle
+ advancing for special insn `cycle advancing' and without cycle
+ advancing for others) makes transition from given state to
+ another given state. */
+ ainsn_t insn;
+ /* The following field value is the next arc output from the same
+ state. */
+ arc_t next_out_arc;
+ /* List of arcs marked given insn is formed with the following
+ field. The field is used in transfromation NDFA -> DFA. */
+ arc_t next_arc_marked_by_insn;
+ /* The following field is defined if NDFA_FLAG is zero. The member
+ value is number of alternative reservations which can be used for
+ transition for given state by given insn. */
+ int state_alts;
+};
+
+/* The following node type describes a deterministic alternative in
+ non-deterministic state which characterizes cpu unit reservations
+ of automaton insn or which is part of NDFA. */
+struct alt_state
+{
+ /* The following field is a determinist state which characterizes
+ unit reservations of the instruction. */
+ state_t state;
+ /* The following field refers to the next state which characterizes
+ unit reservations of the instruction. */
+ alt_state_t next_alt_state;
+ /* The following field refers to the next state in sorted list. */
+ alt_state_t next_sorted_alt_state;
+};
+
+/* The following node type describes insn of automaton. They are
+ labels of FA arcs. */
+struct ainsn
+{
+ /* The following field value is the corresponding insn declaration
+ of description. */
+ struct insn_reserv_decl *insn_reserv_decl;
+ /* The following field value is the next insn declaration for an
+ automaton. */
+ ainsn_t next_ainsn;
+ /* The following field is states which characterize automaton unit
+ reservations of the instruction. The value can be NULL only if it
+ is special insn `cycle advancing'. */
+ alt_state_t alt_states;
+ /* The following field is sorted list of states which characterize
+ automaton unit reservations of the instruction. The value can be
+ NULL only if it is special insn `cycle advancing'. */
+ alt_state_t sorted_alt_states;
+ /* The following field refers the next automaton insn with
+ the same reservations. */
+ ainsn_t next_same_reservs_insn;
+ /* The following field is flag of the first automaton insn with the
+ same reservations in the declaration list. Only arcs marked such
+ insn is present in the automaton. This significantly decreases
+ memory requirements especially when several automata are
+ formed. */
+ char first_insn_with_same_reservs;
+ /* The following member has nonzero value if there is arc from state of
+ the automaton marked by the ainsn. */
+ char arc_exists_p;
+ /* Cyclic list of insns of an equivalence class is formed with the
+ aid of the following field. */
+ ainsn_t next_equiv_class_insn;
+ /* The following field value is nonzero if the insn declaration is
+ the first insn declaration with given equivalence number. */
+ char first_ainsn_with_given_equialence_num;
+ /* The following field is number of class of equivalence of insns.
+ It is necessary because many insns may be equivalent with the
+ point of view of pipeline hazards. */
+ int insn_equiv_class_num;
+ /* The following member value is TRUE if there is an arc in the
+ automaton marked by the insn into another state. In other
+ words, the insn can change the state of the automaton. */
+ int important_p;
+};
+
+/* The folowing describes an automaton for PHR. */
+struct automaton
+{
+ /* The following field value is the list of insn declarations for
+ given automaton. */
+ ainsn_t ainsn_list;
+ /* The following field value is the corresponding automaton
+ declaration. This field is not NULL only if the automatic
+ partition on automata is not used. */
+ struct automaton_decl *corresponding_automaton_decl;
+ /* The following field value is the next automaton. */
+ automaton_t next_automaton;
+ /* The following field is start state of FA. There are not unit
+ reservations in the state. */
+ state_t start_state;
+ /* The following field value is number of equivalence classes of
+ insns (see field `insn_equiv_class_num' in
+ `insn_reserv_decl'). */
+ int insn_equiv_classes_num;
+ /* The following field value is number of states of final DFA. */
+ int achieved_states_num;
+ /* The following field value is the order number (0, 1, ...) of
+ given automaton. */
+ int automaton_order_num;
+ /* The following fields contain statistics information about
+ building automaton. */
+ int NDFA_states_num, DFA_states_num;
+ /* The following field value is defined only if minimization of DFA
+ is used. */
+ int minimal_DFA_states_num;
+ int NDFA_arcs_num, DFA_arcs_num;
+ /* The following field value is defined only if minimization of DFA
+ is used. */
+ int minimal_DFA_arcs_num;
+ /* The following two members refer for two table state x ainsn ->
+ int. */
+ state_ainsn_table_t trans_table;
+ state_ainsn_table_t state_alts_table;
+ /* The following member value is maximal value of min issue delay
+ for insns of the automaton. */
+ int max_min_delay;
+ /* Usually min issue delay is small and we can place several (2, 4,
+ 8) elements in one vector element. So the compression factor can
+ be 1 (no compression), 2, 4, 8. */
+ int min_issue_delay_table_compression_factor;
+};
+
+/* The following is the element of the list of automata. */
+struct automata_list_el
+{
+ /* The automaton itself. */
+ automaton_t automaton;
+ /* The next automata set element. */
+ automata_list_el_t next_automata_list_el;
+};
+
+/* The following structure describes a table state X ainsn -> int(>= 0). */
+struct state_ainsn_table
+{
+ /* Automaton to which given table belongs. */
+ automaton_t automaton;
+ /* The following tree vectors for comb vector implementation of the
+ table. */
+ vla_hwint_t comb_vect;
+ vla_hwint_t check_vect;
+ vla_hwint_t base_vect;
+ /* This is simple implementation of the table. */
+ vla_hwint_t full_vect;
+ /* Minimal and maximal values of the previous vectors. */
+ int min_comb_vect_el_value, max_comb_vect_el_value;
+ int min_base_vect_el_value, max_base_vect_el_value;
+};
+
+/* Macros to access members of unions. Use only them for access to
+ union members of declarations and regexps. */
+
+#if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
+
+#define DECL_UNIT(d) __extension__ \
+(({ struct decl *const _decl = (d); \
+ if (_decl->mode != dm_unit) \
+ decl_mode_check_failed (_decl->mode, "dm_unit", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &(_decl)->decl.unit; }))
+
+#define DECL_BYPASS(d) __extension__ \
+(({ struct decl *const _decl = (d); \
+ if (_decl->mode != dm_bypass) \
+ decl_mode_check_failed (_decl->mode, "dm_bypass", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &(_decl)->decl.bypass; }))
+
+#define DECL_AUTOMATON(d) __extension__ \
+(({ struct decl *const _decl = (d); \
+ if (_decl->mode != dm_automaton) \
+ decl_mode_check_failed (_decl->mode, "dm_automaton", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &(_decl)->decl.automaton; }))
+
+#define DECL_EXCL(d) __extension__ \
+(({ struct decl *const _decl = (d); \
+ if (_decl->mode != dm_excl) \
+ decl_mode_check_failed (_decl->mode, "dm_excl", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &(_decl)->decl.excl; }))
+
+#define DECL_PRESENCE(d) __extension__ \
+(({ struct decl *const _decl = (d); \
+ if (_decl->mode != dm_presence) \
+ decl_mode_check_failed (_decl->mode, "dm_presence", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &(_decl)->decl.presence; }))
+
+#define DECL_ABSENCE(d) __extension__ \
+(({ struct decl *const _decl = (d); \
+ if (_decl->mode != dm_absence) \
+ decl_mode_check_failed (_decl->mode, "dm_absence", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &(_decl)->decl.absence; }))
+
+#define DECL_RESERV(d) __extension__ \
+(({ struct decl *const _decl = (d); \
+ if (_decl->mode != dm_reserv) \
+ decl_mode_check_failed (_decl->mode, "dm_reserv", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &(_decl)->decl.reserv; }))
+
+#define DECL_INSN_RESERV(d) __extension__ \
+(({ struct decl *const _decl = (d); \
+ if (_decl->mode != dm_insn_reserv) \
+ decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &(_decl)->decl.insn_reserv; }))
+
+static const char *decl_name PARAMS ((enum decl_mode));
+static void decl_mode_check_failed PARAMS ((enum decl_mode, const char *,
+ const char *, int, const char *));
+
+/* Return string representation of declaration mode MODE. */
+static const char *
+decl_name (mode)
+ enum decl_mode mode;
+{
+ static char str [100];
+
+ if (mode == dm_unit)
+ return "dm_unit";
+ else if (mode == dm_bypass)
+ return "dm_bypass";
+ else if (mode == dm_automaton)
+ return "dm_automaton";
+ else if (mode == dm_excl)
+ return "dm_excl";
+ else if (mode == dm_presence)
+ return "dm_presence";
+ else if (mode == dm_absence)
+ return "dm_absence";
+ else if (mode == dm_reserv)
+ return "dm_reserv";
+ else if (mode == dm_insn_reserv)
+ return "dm_insn_reserv";
+ else
+ sprintf (str, "unknown (%d)", (int) mode);
+ return str;
+}
+
+/* The function prints message about unexpected declaration and finish
+ the program. */
+static void
+decl_mode_check_failed (mode, expected_mode_str, file, line, func)
+ enum decl_mode mode;
+ const char *expected_mode_str;
+ const char *file;
+ int line;
+ const char *func;
+{
+ fprintf
+ (stderr,
+ "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
+ file, line, func, expected_mode_str, decl_name (mode));
+ exit (1);
+}
+
+
+#define REGEXP_UNIT(r) __extension__ \
+(({ struct regexp *const _regexp = (r); \
+ if (_regexp->mode != rm_unit) \
+ regexp_mode_check_failed (_regexp->mode, "rm_unit", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &(_regexp)->regexp.unit; }))
+
+#define REGEXP_RESERV(r) __extension__ \
+(({ struct regexp *const _regexp = (r); \
+ if (_regexp->mode != rm_reserv) \
+ regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &(_regexp)->regexp.reserv; }))
+
+#define REGEXP_SEQUENCE(r) __extension__ \
+(({ struct regexp *const _regexp = (r); \
+ if (_regexp->mode != rm_sequence) \
+ regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &(_regexp)->regexp.sequence; }))
+
+#define REGEXP_REPEAT(r) __extension__ \
+(({ struct regexp *const _regexp = (r); \
+ if (_regexp->mode != rm_repeat) \
+ regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &(_regexp)->regexp.repeat; }))
+
+#define REGEXP_ALLOF(r) __extension__ \
+(({ struct regexp *const _regexp = (r); \
+ if (_regexp->mode != rm_allof) \
+ regexp_mode_check_failed (_regexp->mode, "rm_allof", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &(_regexp)->regexp.allof; }))
+
+#define REGEXP_ONEOF(r) __extension__ \
+(({ struct regexp *const _regexp = (r); \
+ if (_regexp->mode != rm_oneof) \
+ regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &(_regexp)->regexp.oneof; }))
+
+static const char *regexp_name PARAMS ((enum regexp_mode));
+static void regexp_mode_check_failed PARAMS ((enum regexp_mode, const char *,
+ const char *, int,
+ const char *));
+
+
+/* Return string representation of regexp mode MODE. */
+static const char *
+regexp_name (mode)
+ enum regexp_mode mode;
+{
+ static char str [100];
+
+ if (mode == rm_unit)
+ return "rm_unit";
+ else if (mode == rm_reserv)
+ return "rm_reserv";
+ else if (mode == rm_nothing)
+ return "rm_nothing";
+ else if (mode == rm_sequence)
+ return "rm_sequence";
+ else if (mode == rm_repeat)
+ return "rm_repeat";
+ else if (mode == rm_allof)
+ return "rm_allof";
+ else if (mode == rm_oneof)
+ return "rm_oneof";
+ else
+ sprintf (str, "unknown (%d)", (int) mode);
+ return str;
+}
+
+/* The function prints message about unexpected regexp and finish the
+ program. */
+static void
+regexp_mode_check_failed (mode, expected_mode_str, file, line, func)
+ enum regexp_mode mode;
+ const char *expected_mode_str;
+ const char *file;
+ int line;
+ const char *func;
+{
+ fprintf
+ (stderr,
+ "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
+ file, line, func, expected_mode_str, regexp_name (mode));
+ exit (1);
+}
+
+#else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
+
+#define DECL_UNIT(d) (&(d)->decl.unit)
+#define DECL_BYPASS(d) (&(d)->decl.bypass)
+#define DECL_AUTOMATON(d) (&(d)->decl.automaton)
+#define DECL_EXCL(d) (&(d)->decl.excl)
+#define DECL_PRESENCE(d) (&(d)->decl.presence)
+#define DECL_ABSENCE(d) (&(d)->decl.absence)
+#define DECL_RESERV(d) (&(d)->decl.reserv)
+#define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
+
+#define REGEXP_UNIT(r) (&(r)->regexp.unit)
+#define REGEXP_RESERV(r) (&(r)->regexp.reserv)
+#define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
+#define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
+#define REGEXP_ALLOF(r) (&(r)->regexp.allof)
+#define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
+
+#endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
+
+/* Create IR structure (node). */
+static void *
+create_node (size)
+ size_t size;
+{
+ void *result;
+
+ obstack_blank (&irp, size);
+ result = obstack_base (&irp);
+ obstack_finish (&irp);
+ /* Default values of members are NULL and zero. */
+ memset (result, 0, size);
+ return result;
+}
+
+/* Copy IR structure (node). */
+static void *
+copy_node (from, size)
+ const void *from;
+ size_t size;
+{
+ void *const result = create_node (size);
+ memcpy (result, from, size);
+ return result;
+}
+
+/* The function checks that NAME does not contain quotes (`"'). */
+static char *
+check_name (name, pos)
+ char * name;
+ pos_t pos ATTRIBUTE_UNUSED;
+{
+ const char *str;
+
+ for (str = name; *str != '\0'; str++)
+ if (*str == '\"')
+ error ("Name `%s' contains quotes", name);
+ return name;
+}
+
+/* Pointers top all declartions during IR generation are stored in the
+ following. */
+static vla_ptr_t decls;
+
+/* Given a pointer to a (char *) and a separator, return an alloc'ed
+ string containing the next separated element, taking parentheses
+ into account if PAR_FLAG has nonzero value. Advance the pointer to
+ after the string scanned, or the end-of-string. Return NULL if at
+ end of string. */
+static char *
+next_sep_el (pstr, sep, par_flag)
+ char **pstr;
+ int sep;
+ int par_flag;
+{
+ char *out_str;
+ char *p;
+ int pars_num;
+ int n_spaces;
+
+ /* Remove leading whitespaces. */
+ while (ISSPACE ((int) **pstr))
+ (*pstr)++;
+
+ if (**pstr == '\0')
+ return NULL;
+
+ n_spaces = 0;
+ for (pars_num = 0, p = *pstr; *p != '\0'; p++)
+ {
+ if (par_flag && *p == '(')
+ pars_num++;
+ else if (par_flag && *p == ')')
+ pars_num--;
+ else if (pars_num == 0 && *p == sep)
+ break;
+ if (pars_num == 0 && ISSPACE ((int) *p))
+ n_spaces++;
+ else
+ {
+ for (; n_spaces != 0; n_spaces--)
+ obstack_1grow (&irp, p [-n_spaces]);
+ obstack_1grow (&irp, *p);
+ }
+ }
+ obstack_1grow (&irp, '\0');
+ out_str = obstack_base (&irp);
+ obstack_finish (&irp);
+
+ *pstr = p;
+ if (**pstr == sep)
+ (*pstr)++;
+
+ return out_str;
+}
+
+/* Given a string and a separator, return the number of separated
+ elements in it, taking parentheses into account if PAR_FLAG has
+ nonzero value. Return 0 for the null string, -1 if parantheses is
+ not balanced. */
+static int
+n_sep_els (s, sep, par_flag)
+ char *s;
+ int sep;
+ int par_flag;
+{
+ int n;
+ int pars_num;
+
+ if (*s == '\0')
+ return 0;
+
+ for (pars_num = 0, n = 1; *s; s++)
+ if (par_flag && *s == '(')
+ pars_num++;
+ else if (par_flag && *s == ')')
+ pars_num--;
+ else if (pars_num == 0 && *s == sep)
+ n++;
+
+ return (pars_num != 0 ? -1 : n);
+}
+
+/* Given a string and a separator, return vector of strings which are
+ elements in the string and number of elements through els_num.
+ Take parentheses into account if PAR_FLAG has nonzero value.
+ Return 0 for the null string, -1 if parantheses are not balanced. */
+static char **
+get_str_vect (str, els_num, sep, par_flag)
+ char *str;
+ int *els_num;
+ int sep;
+ int par_flag;
+{
+ int i;
+ char **vect;
+ char **pstr;
+
+ *els_num = n_sep_els (str, sep, par_flag);
+ if (*els_num <= 0)
+ return NULL;
+ obstack_blank (&irp, sizeof (char *) * (*els_num));
+ vect = (char **) obstack_base (&irp);
+ obstack_finish (&irp);
+ pstr = &str;
+ for (i = 0; i < *els_num; i++)
+ vect [i] = next_sep_el (pstr, sep, par_flag);
+ if (next_sep_el (pstr, sep, par_flag) != NULL)
+ abort ();
+ return vect;
+}
+
+/* Process a DEFINE_CPU_UNIT.
+
+ This gives information about a unit contained in CPU. We fill a
+ struct unit_decl with information used later by `expand_automata'. */
+void
+gen_cpu_unit (def)
+ rtx def;
+{
+ decl_t decl;
+ char **str_cpu_units;
+ int vect_length;
+ int i;
+
+ str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
+ if (str_cpu_units == NULL)
+ fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
+ for (i = 0; i < vect_length; i++)
+ {
+ decl = create_node (sizeof (struct decl));
+ decl->mode = dm_unit;
+ decl->pos = 0;
+ DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
+ DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
+ DECL_UNIT (decl)->query_p = 0;
+ VLA_PTR_ADD (decls, decl);
+ num_dfa_decls++;
+ }
+}
+
+/* Process a DEFINE_QUERY_CPU_UNIT.
+
+ This gives information about a unit contained in CPU. We fill a
+ struct unit_decl with information used later by `expand_automata'. */
+void
+gen_query_cpu_unit (def)
+ rtx def;
+{
+ decl_t decl;
+ char **str_cpu_units;
+ int vect_length;
+ int i;
+
+ str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
+ if (str_cpu_units == NULL)
+ fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
+ for (i = 0; i < vect_length; i++)
+ {
+ decl = create_node (sizeof (struct decl));
+ decl->mode = dm_unit;
+ decl->pos = 0;
+ DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
+ DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
+ DECL_UNIT (decl)->query_p = 1;
+ VLA_PTR_ADD (decls, decl);
+ num_dfa_decls++;
+ }
+}
+
+/* Process a DEFINE_BYPASS.
+
+ This gives information about a unit contained in the CPU. We fill
+ in a struct bypass_decl with information used later by
+ `expand_automata'. */
+void
+gen_bypass (def)
+ rtx def;
+{
+ decl_t decl;
+ char **out_insns;
+ int out_length;
+ char **in_insns;
+ int in_length;
+ int i, j;
+
+ out_insns = get_str_vect ((char *) XSTR (def, 1), &out_length, ',', 0);
+ if (out_insns == NULL)
+ fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
+ in_insns = get_str_vect ((char *) XSTR (def, 2), &in_length, ',', 0);
+ if (in_insns == NULL)
+ fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
+ for (i = 0; i < out_length; i++)
+ for (j = 0; j < in_length; j++)
+ {
+ decl = create_node (sizeof (struct decl));
+ decl->mode = dm_bypass;
+ decl->pos = 0;
+ DECL_BYPASS (decl)->latency = XINT (def, 0);
+ DECL_BYPASS (decl)->out_insn_name = out_insns [i];
+ DECL_BYPASS (decl)->in_insn_name = in_insns [j];
+ DECL_BYPASS (decl)->bypass_guard_name = (char *) XSTR (def, 3);
+ VLA_PTR_ADD (decls, decl);
+ num_dfa_decls++;
+ }
+}
+
+/* Process an EXCLUSION_SET.
+
+ This gives information about a cpu unit conflicts. We fill a
+ struct unit_rel_decl (excl) with information used later by
+ `expand_automata'. */
+void
+gen_excl_set (def)
+ rtx def;
+{
+ decl_t decl;
+ char **first_str_cpu_units;
+ char **second_str_cpu_units;
+ int first_vect_length;
+ int length;
+ int i;
+
+ first_str_cpu_units
+ = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
+ if (first_str_cpu_units == NULL)
+ fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
+ second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
+ 0);
+ if (second_str_cpu_units == NULL)
+ fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
+ length += first_vect_length;
+ decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
+ decl->mode = dm_excl;
+ decl->pos = 0;
+ DECL_EXCL (decl)->names_num = length;
+ DECL_EXCL (decl)->first_list_length = first_vect_length;
+ for (i = 0; i < length; i++)
+ if (i < first_vect_length)
+ DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
+ else
+ DECL_EXCL (decl)->names [i]
+ = second_str_cpu_units [i - first_vect_length];
+ VLA_PTR_ADD (decls, decl);
+ num_dfa_decls++;
+}
+
+/* Process a PRESENCE_SET.
+
+ This gives information about a cpu unit reservation requirements.
+ We fill a struct unit_rel_decl (presence) with information used
+ later by `expand_automata'. */
+void
+gen_presence_set (def)
+ rtx def;
+{
+ decl_t decl;
+ char **first_str_cpu_units;
+ char **second_str_cpu_units;
+ int first_vect_length;
+ int length;
+ int i;
+
+ first_str_cpu_units
+ = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
+ if (first_str_cpu_units == NULL)
+ fatal ("invalid first string `%s' in presence_set", XSTR (def, 0));
+ second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
+ 0);
+ if (second_str_cpu_units == NULL)
+ fatal ("invalid second string `%s' in presence_set", XSTR (def, 1));
+ length += first_vect_length;
+ decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
+ decl->mode = dm_presence;
+ decl->pos = 0;
+ DECL_PRESENCE (decl)->names_num = length;
+ DECL_PRESENCE (decl)->first_list_length = first_vect_length;
+ for (i = 0; i < length; i++)
+ if (i < first_vect_length)
+ DECL_PRESENCE (decl)->names [i] = first_str_cpu_units [i];
+ else
+ DECL_PRESENCE (decl)->names [i]
+ = second_str_cpu_units [i - first_vect_length];
+ VLA_PTR_ADD (decls, decl);
+ num_dfa_decls++;
+}
+
+/* Process an ABSENCE_SET.
+
+ This gives information about a cpu unit reservation requirements.
+ We fill a struct unit_rel_decl (absence) with information used
+ later by `expand_automata'. */
+void
+gen_absence_set (def)
+ rtx def;
+{
+ decl_t decl;
+ char **first_str_cpu_units;
+ char **second_str_cpu_units;
+ int first_vect_length;
+ int length;
+ int i;
+
+ first_str_cpu_units
+ = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
+ if (first_str_cpu_units == NULL)
+ fatal ("invalid first string `%s' in absence_set", XSTR (def, 0));
+ second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
+ 0);
+ if (second_str_cpu_units == NULL)
+ fatal ("invalid second string `%s' in absence_set", XSTR (def, 1));
+ length += first_vect_length;
+ decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
+ decl->mode = dm_absence;
+ decl->pos = 0;
+ DECL_ABSENCE (decl)->names_num = length;
+ DECL_ABSENCE (decl)->first_list_length = first_vect_length;
+ for (i = 0; i < length; i++)
+ if (i < first_vect_length)
+ DECL_ABSENCE (decl)->names [i] = first_str_cpu_units [i];
+ else
+ DECL_ABSENCE (decl)->names [i]
+ = second_str_cpu_units [i - first_vect_length];
+ VLA_PTR_ADD (decls, decl);
+ num_dfa_decls++;
+}
+
+/* Process a DEFINE_AUTOMATON.
+
+ This gives information about a finite state automaton used for
+ recognizing pipeline hazards. We fill a struct automaton_decl
+ with information used later by `expand_automata'. */
+void
+gen_automaton (def)
+ rtx def;
+{
+ decl_t decl;
+ char **str_automata;
+ int vect_length;
+ int i;
+
+ str_automata = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
+ if (str_automata == NULL)
+ fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
+ for (i = 0; i < vect_length; i++)
+ {
+ decl = create_node (sizeof (struct decl));
+ decl->mode = dm_automaton;
+ decl->pos = 0;
+ DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
+ VLA_PTR_ADD (decls, decl);
+ num_dfa_decls++;
+ }
+}
+
+/* Process an AUTOMATA_OPTION.
+
+ This gives information how to generate finite state automaton used
+ for recognizing pipeline hazards. */
+void
+gen_automata_option (def)
+ rtx def;
+{
+ if (strcmp ((char *) XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
+ no_minimization_flag = 1;
+ else if (strcmp ((char *) XSTR (def, 0), TIME_OPTION + 1) == 0)
+ time_flag = 1;
+ else if (strcmp ((char *) XSTR (def, 0), V_OPTION + 1) == 0)
+ v_flag = 1;
+ else if (strcmp ((char *) XSTR (def, 0), W_OPTION + 1) == 0)
+ w_flag = 1;
+ else if (strcmp ((char *) XSTR (def, 0), NDFA_OPTION + 1) == 0)
+ ndfa_flag = 1;
+ else
+ fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
+}
+
+/* Name in reservation to denote absence reservation. */
+#define NOTHING_NAME "nothing"
+
+/* The following string contains original reservation string being
+ parsed. */
+static char *reserv_str;
+
+/* Parse an element in STR. */
+static regexp_t
+gen_regexp_el (str)
+ char *str;
+{
+ regexp_t regexp;
+ int len;
+
+ if (*str == '(')
+ {
+ len = strlen (str);
+ if (str [len - 1] != ')')
+ fatal ("garbage after ) in reservation `%s'", reserv_str);
+ str [len - 1] = '\0';
+ regexp = gen_regexp_sequence (str + 1);
+ }
+ else if (strcmp (str, NOTHING_NAME) == 0)
+ {
+ regexp = create_node (sizeof (struct decl));
+ regexp->mode = rm_nothing;
+ }
+ else
+ {
+ regexp = create_node (sizeof (struct decl));
+ regexp->mode = rm_unit;
+ REGEXP_UNIT (regexp)->name = str;
+ }
+ return regexp;
+}
+
+/* Parse construction `repeat' in STR. */
+static regexp_t
+gen_regexp_repeat (str)
+ char *str;
+{
+ regexp_t regexp;
+ regexp_t repeat;
+ char **repeat_vect;
+ int els_num;
+ int i;
+
+ repeat_vect = get_str_vect (str, &els_num, '*', 1);
+ if (repeat_vect == NULL)
+ fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
+ if (els_num > 1)
+ {
+ regexp = gen_regexp_el (repeat_vect [0]);
+ for (i = 1; i < els_num; i++)
+ {
+ repeat = create_node (sizeof (struct regexp));
+ repeat->mode = rm_repeat;
+ REGEXP_REPEAT (repeat)->regexp = regexp;
+ REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
+ if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
+ fatal ("repetition `%s' <= 1 in reservation `%s'",
+ str, reserv_str);
+ regexp = repeat;
+ }
+ return regexp;
+ }
+ else
+ return gen_regexp_el (str);
+}
+
+/* Parse reservation STR which possibly contains separator '+'. */
+static regexp_t
+gen_regexp_allof (str)
+ char *str;
+{
+ regexp_t allof;
+ char **allof_vect;
+ int els_num;
+ int i;
+
+ allof_vect = get_str_vect (str, &els_num, '+', 1);
+ if (allof_vect == NULL)
+ fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
+ if (els_num > 1)
+ {
+ allof = create_node (sizeof (struct regexp)
+ + sizeof (regexp_t) * (els_num - 1));
+ allof->mode = rm_allof;
+ REGEXP_ALLOF (allof)->regexps_num = els_num;
+ for (i = 0; i < els_num; i++)
+ REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
+ return allof;
+ }
+ else
+ return gen_regexp_repeat (str);
+}
+
+/* Parse reservation STR which possibly contains separator '|'. */
+static regexp_t
+gen_regexp_oneof (str)
+ char *str;
+{
+ regexp_t oneof;
+ char **oneof_vect;
+ int els_num;
+ int i;
+
+ oneof_vect = get_str_vect (str, &els_num, '|', 1);
+ if (oneof_vect == NULL)
+ fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
+ if (els_num > 1)
+ {
+ oneof = create_node (sizeof (struct regexp)
+ + sizeof (regexp_t) * (els_num - 1));
+ oneof->mode = rm_oneof;
+ REGEXP_ONEOF (oneof)->regexps_num = els_num;
+ for (i = 0; i < els_num; i++)
+ REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
+ return oneof;
+ }
+ else
+ return gen_regexp_allof (str);
+}
+
+/* Parse reservation STR which possibly contains separator ','. */
+static regexp_t
+gen_regexp_sequence (str)
+ char *str;
+{
+ regexp_t sequence;
+ char **sequence_vect;
+ int els_num;
+ int i;
+
+ sequence_vect = get_str_vect (str, &els_num, ',', 1);
+ if (els_num > 1)
+ {
+ sequence = create_node (sizeof (struct regexp)
+ + sizeof (regexp_t) * (els_num - 1));
+ sequence->mode = rm_sequence;
+ REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
+ for (i = 0; i < els_num; i++)
+ REGEXP_SEQUENCE (sequence)->regexps [i]
+ = gen_regexp_oneof (sequence_vect [i]);
+ return sequence;
+ }
+ else
+ return gen_regexp_oneof (str);
+}
+
+/* Parse construction reservation STR. */
+static regexp_t
+gen_regexp (str)
+ char *str;
+{
+ reserv_str = str;
+ return gen_regexp_sequence (str);;
+}
+
+/* Process a DEFINE_RESERVATION.
+
+ This gives information about a reservation of cpu units. We fill
+ in a struct reserv_decl with information used later by
+ `expand_automata'. */
+void
+gen_reserv (def)
+ rtx def;
+{
+ decl_t decl;
+
+ decl = create_node (sizeof (struct decl));
+ decl->mode = dm_reserv;
+ decl->pos = 0;
+ DECL_RESERV (decl)->name = check_name ((char *) XSTR (def, 0), decl->pos);
+ DECL_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 1));
+ VLA_PTR_ADD (decls, decl);
+ num_dfa_decls++;
+}
+
+/* Process a DEFINE_INSN_RESERVATION.
+
+ This gives information about the reservation of cpu units by an
+ insn. We fill a struct insn_reserv_decl with information used
+ later by `expand_automata'. */
+void
+gen_insn_reserv (def)
+ rtx def;
+{
+ decl_t decl;
+
+ decl = create_node (sizeof (struct decl));
+ decl->mode = dm_insn_reserv;
+ decl->pos = 0;
+ DECL_INSN_RESERV (decl)->name
+ = check_name ((char *) XSTR (def, 0), decl->pos);
+ DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
+ DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
+ DECL_INSN_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 3));
+ VLA_PTR_ADD (decls, decl);
+ num_dfa_decls++;
+}
+
+
+
+/* The function evaluates hash value (0..UINT_MAX) of string. */
+static unsigned
+string_hash (string)
+ const char *string;
+{
+ unsigned result, i;
+
+ for (result = i = 0;*string++ != '\0'; i++)
+ result += ((unsigned char) *string << (i % CHAR_BIT));
+ return result;
+}
+
+
+
+/* This page contains abstract data `table of automaton declarations'.
+ Elements of the table is nodes representing automaton declarations.
+ Key of the table elements is name of given automaton. Rememeber
+ that automaton names have own space. */
+
+/* The function evaluates hash value of an automaton declaration. The
+ function is used by abstract data `hashtab'. The function returns
+ hash value (0..UINT_MAX) of given automaton declaration. */
+static hashval_t
+automaton_decl_hash (automaton_decl)
+ const void *automaton_decl;
+{
+ const decl_t decl = (decl_t) automaton_decl;
+
+ if (decl->mode == dm_automaton && DECL_AUTOMATON (decl)->name == NULL)
+ abort ();
+ return string_hash (DECL_AUTOMATON (decl)->name);
+}
+
+/* The function tests automaton declarations on equality of their
+ keys. The function is used by abstract data `hashtab'. The
+ function returns 1 if the declarations have the same key, 0
+ otherwise. */
+static int
+automaton_decl_eq_p (automaton_decl_1, automaton_decl_2)
+ const void* automaton_decl_1;
+ const void* automaton_decl_2;
+{
+ const decl_t decl1 = (decl_t) automaton_decl_1;
+ const decl_t decl2 = (decl_t) automaton_decl_2;
+
+ if (decl1->mode != dm_automaton || DECL_AUTOMATON (decl1)->name == NULL
+ || decl2->mode != dm_automaton || DECL_AUTOMATON (decl2)->name == NULL)
+ abort ();
+ return strcmp (DECL_AUTOMATON (decl1)->name,
+ DECL_AUTOMATON (decl2)->name) == 0;
+}
+
+/* The automaton declaration table itself is represented by the
+ following variable. */
+static htab_t automaton_decl_table;
+
+/* The function inserts automaton declaration into the table. The
+ function does nothing if an automaton declaration with the same key
+ exists already in the table. The function returns automaton
+ declaration node in the table with the same key as given automaton
+ declaration node. */
+static decl_t
+insert_automaton_decl (automaton_decl)
+ decl_t automaton_decl;
+{
+ void **entry_ptr;
+
+ entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
+ if (*entry_ptr == NULL)
+ *entry_ptr = (void *) automaton_decl;
+ return (decl_t) *entry_ptr;
+}
+
+/* The following variable value is node representing automaton
+ declaration. The node used for searching automaton declaration
+ with given name. */
+static struct decl work_automaton_decl;
+
+/* The function searches for automaton declaration in the table with
+ the same key as node representing name of the automaton
+ declaration. The function returns node found in the table, NULL if
+ such node does not exist in the table. */
+static decl_t
+find_automaton_decl (name)
+ char *name;
+{
+ void *entry;
+
+ work_automaton_decl.mode = dm_automaton;
+ DECL_AUTOMATON (&work_automaton_decl)->name = name;
+ entry = htab_find (automaton_decl_table, &work_automaton_decl);
+ return (decl_t) entry;
+}
+
+/* The function creates empty automaton declaration table and node
+ representing automaton declaration and used for searching automaton
+ declaration with given name. The function must be called only once
+ before any work with the automaton declaration table. */
+static void
+initiate_automaton_decl_table ()
+{
+ work_automaton_decl.mode = dm_automaton;
+ automaton_decl_table = htab_create (10, automaton_decl_hash,
+ automaton_decl_eq_p, (htab_del) 0);
+}
+
+/* The function deletes the automaton declaration table. Only call of
+ function `initiate_automaton_decl_table' is possible immediately
+ after this function call. */
+static void
+finish_automaton_decl_table ()
+{
+ htab_delete (automaton_decl_table);
+}
+
+
+
+/* This page contains abstract data `table of insn declarations'.
+ Elements of the table is nodes representing insn declarations. Key
+ of the table elements is name of given insn (in corresponding
+ define_insn_reservation). Rememeber that insn names have own
+ space. */
+
+/* The function evaluates hash value of an insn declaration. The
+ function is used by abstract data `hashtab'. The function returns
+ hash value (0..UINT_MAX) of given insn declaration. */
+static hashval_t
+insn_decl_hash (insn_decl)
+ const void *insn_decl;
+{
+ const decl_t decl = (decl_t) insn_decl;
+
+ if (decl->mode != dm_insn_reserv || DECL_INSN_RESERV (decl)->name == NULL)
+ abort ();
+ return string_hash (DECL_INSN_RESERV (decl)->name);
+}
+
+/* The function tests insn declarations on equality of their keys.
+ The function is used by abstract data `hashtab'. The function
+ returns 1 if declarations have the same key, 0 otherwise. */
+static int
+insn_decl_eq_p (insn_decl_1, insn_decl_2)
+ const void *insn_decl_1;
+ const void *insn_decl_2;
+{
+ const decl_t decl1 = (decl_t) insn_decl_1;
+ const decl_t decl2 = (decl_t) insn_decl_2;
+
+ if (decl1->mode != dm_insn_reserv || DECL_INSN_RESERV (decl1)->name == NULL
+ || decl2->mode != dm_insn_reserv
+ || DECL_INSN_RESERV (decl2)->name == NULL)
+ abort ();
+ return strcmp (DECL_INSN_RESERV (decl1)->name,
+ DECL_INSN_RESERV (decl2)->name) == 0;
+}
+
+/* The insn declaration table itself is represented by the following
+ variable. The table does not contain insn reservation
+ declarations. */
+static htab_t insn_decl_table;
+
+/* The function inserts insn declaration into the table. The function
+ does nothing if an insn declaration with the same key exists
+ already in the table. The function returns insn declaration node
+ in the table with the same key as given insn declaration node. */
+static decl_t
+insert_insn_decl (insn_decl)
+ decl_t insn_decl;
+{
+ void **entry_ptr;
+
+ entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
+ if (*entry_ptr == NULL)
+ *entry_ptr = (void *) insn_decl;
+ return (decl_t) *entry_ptr;
+}
+
+/* The following variable value is node representing insn reservation
+ declaration. The node used for searching insn reservation
+ declaration with given name. */
+static struct decl work_insn_decl;
+
+/* The function searches for insn reservation declaration in the table
+ with the same key as node representing name of the insn reservation
+ declaration. The function returns node found in the table, NULL if
+ such node does not exist in the table. */
+static decl_t
+find_insn_decl (name)
+ char *name;
+{
+ void *entry;
+
+ work_insn_decl.mode = dm_insn_reserv;
+ DECL_INSN_RESERV (&work_insn_decl)->name = name;
+ entry = htab_find (insn_decl_table, &work_insn_decl);
+ return (decl_t) entry;
+}
+
+/* The function creates empty insn declaration table and node
+ representing insn declaration and used for searching insn
+ declaration with given name. The function must be called only once
+ before any work with the insn declaration table. */
+static void
+initiate_insn_decl_table ()
+{
+ work_insn_decl.mode = dm_insn_reserv;
+ insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
+ (htab_del) 0);
+}
+
+/* The function deletes the insn declaration table. Only call of
+ function `initiate_insn_decl_table' is possible immediately after
+ this function call. */
+static void
+finish_insn_decl_table ()
+{
+ htab_delete (insn_decl_table);
+}
+
+
+
+/* This page contains abstract data `table of declarations'. Elements
+ of the table is nodes representing declarations (of units and
+ reservations). Key of the table elements is names of given
+ declarations. */
+
+/* The function evaluates hash value of a declaration. The function
+ is used by abstract data `hashtab'. The function returns hash
+ value (0..UINT_MAX) of given declaration. */
+static hashval_t
+decl_hash (decl)
+ const void *decl;
+{
+ const decl_t d = (const decl_t) decl;
+
+ if ((d->mode != dm_unit || DECL_UNIT (d)->name == NULL)
+ && (d->mode != dm_reserv || DECL_RESERV (d)->name == NULL))
+ abort ();
+ return string_hash (d->mode == dm_unit
+ ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
+}
+
+/* The function tests declarations on equality of their keys. The
+ function is used by abstract data `hashtab'. The function
+ returns 1 if the declarations have the same key, 0 otherwise. */
+static int
+decl_eq_p (decl_1, decl_2)
+ const void *decl_1;
+ const void *decl_2;
+{
+ const decl_t d1 = (const decl_t) decl_1;
+ const decl_t d2 = (const decl_t) decl_2;
+
+ if (((d1->mode != dm_unit || DECL_UNIT (d1)->name == NULL)
+ && (d1->mode != dm_reserv || DECL_RESERV (d1)->name == NULL))
+ || ((d2->mode != dm_unit || DECL_UNIT (d2)->name == NULL)
+ && (d2->mode != dm_reserv || DECL_RESERV (d2)->name == NULL)))
+ abort ();
+ return strcmp ((d1->mode == dm_unit
+ ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
+ (d2->mode == dm_unit
+ ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
+}
+
+/* The declaration table itself is represented by the following
+ variable. */
+static htab_t decl_table;
+
+/* The function inserts declaration into the table. The function does
+ nothing if a declaration with the same key exists already in the
+ table. The function returns declaration node in the table with the
+ same key as given declaration node. */
+
+static decl_t
+insert_decl (decl)
+ decl_t decl;
+{
+ void **entry_ptr;
+
+ entry_ptr = htab_find_slot (decl_table, decl, 1);
+ if (*entry_ptr == NULL)
+ *entry_ptr = (void *) decl;
+ return (decl_t) *entry_ptr;
+}
+
+/* The following variable value is node representing declaration. The
+ node used for searching declaration with given name. */
+static struct decl work_decl;
+
+/* The function searches for declaration in the table with the same
+ key as node representing name of the declaration. The function
+ returns node found in the table, NULL if such node does not exist
+ in the table. */
+static decl_t
+find_decl (name)
+ char *name;
+{
+ void *entry;
+
+ work_decl.mode = dm_unit;
+ DECL_UNIT (&work_decl)->name = name;
+ entry = htab_find (decl_table, &work_decl);
+ return (decl_t) entry;
+}
+
+/* The function creates empty declaration table and node representing
+ declaration and used for searching declaration with given name.
+ The function must be called only once before any work with the
+ declaration table. */
+static void
+initiate_decl_table ()
+{
+ work_decl.mode = dm_unit;
+ decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
+}
+
+/* The function deletes the declaration table. Only call of function
+ `initiate_declaration_table' is possible immediately after this
+ function call. */
+static void
+finish_decl_table ()
+{
+ htab_delete (decl_table);
+}
+
+
+
+/* This page contains checker of pipeline hazard description. */
+
+/* Checking NAMES in an exclusion clause vector and returning formed
+ unit_set_el_list. */
+static unit_set_el_t
+process_excls (names, num, excl_pos)
+ char **names;
+ int num;
+ pos_t excl_pos ATTRIBUTE_UNUSED;
+{
+ unit_set_el_t el_list;
+ unit_set_el_t last_el;
+ unit_set_el_t new_el;
+ decl_t decl_in_table;
+ int i;
+
+ el_list = NULL;
+ last_el = NULL;
+ for (i = 0; i < num; i++)
+ {
+ decl_in_table = find_decl (names [i]);
+ if (decl_in_table == NULL)
+ error ("unit `%s' in exclusion is not declared", names [i]);
+ else if (decl_in_table->mode != dm_unit)
+ error ("`%s' in exclusion is not unit", names [i]);
+ else
+ {
+ new_el = create_node (sizeof (struct unit_set_el));
+ new_el->unit_decl = DECL_UNIT (decl_in_table);
+ new_el->next_unit_set_el = NULL;
+ if (last_el == NULL)
+ el_list = last_el = new_el;
+ else
+ {
+ last_el->next_unit_set_el = new_el;
+ last_el = last_el->next_unit_set_el;
+ }
+ }
+ }
+ return el_list;
+}
+
+/* The function adds each element from SOURCE_LIST to the exclusion
+ list of the each element from DEST_LIST. Checking situation "unit
+ excludes itself". */
+static void
+add_excls (dest_list, source_list, excl_pos)
+ unit_set_el_t dest_list;
+ unit_set_el_t source_list;
+ pos_t excl_pos ATTRIBUTE_UNUSED;
+{
+ unit_set_el_t dst;
+ unit_set_el_t src;
+ unit_set_el_t curr_el;
+ unit_set_el_t prev_el;
+ unit_set_el_t copy;
+
+ for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
+ for (src = source_list; src != NULL; src = src->next_unit_set_el)
+ {
+ if (dst->unit_decl == src->unit_decl)
+ {
+ error ("unit `%s' excludes itself", src->unit_decl->name);
+ continue;
+ }
+ if (dst->unit_decl->automaton_name != NULL
+ && src->unit_decl->automaton_name != NULL
+ && strcmp (dst->unit_decl->automaton_name,
+ src->unit_decl->automaton_name) != 0)
+ {
+ error ("units `%s' and `%s' in exclusion set belong to different automata",
+ src->unit_decl->name, dst->unit_decl->name);
+ continue;
+ }
+ for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
+ curr_el != NULL;
+ prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
+ if (curr_el->unit_decl == src->unit_decl)
+ break;
+ if (curr_el == NULL)
+ {
+ /* Element not found - insert. */
+ copy = copy_node (src, sizeof (*src));
+ copy->next_unit_set_el = NULL;
+ if (prev_el == NULL)
+ dst->unit_decl->excl_list = copy;
+ else
+ prev_el->next_unit_set_el = copy;
+ }
+ }
+}
+
+/* Checking NAMES in a presence clause vector and returning formed
+ unit_set_el_list. The function is called only after processing all
+ exclusion sets. */
+static unit_set_el_t
+process_presence_absence (names, num, req_pos, presence_p)
+ char **names;
+ int num;
+ pos_t req_pos ATTRIBUTE_UNUSED;
+ int presence_p;
+{
+ unit_set_el_t el_list;
+ unit_set_el_t last_el;
+ unit_set_el_t new_el;
+ decl_t decl_in_table;
+ int i;
+
+ el_list = NULL;
+ last_el = NULL;
+ for (i = 0; i < num; i++)
+ {
+ decl_in_table = find_decl (names [i]);
+ if (decl_in_table == NULL)
+ error ((presence_p
+ ? "unit `%s' in presence set is not declared"
+ : "unit `%s' in absence set is not declared"), names [i]);
+ else if (decl_in_table->mode != dm_unit)
+ error ((presence_p
+ ? "`%s' in presence set is not unit"
+ : "`%s' in absence set is not unit"), names [i]);
+ else
+ {
+ new_el = create_node (sizeof (struct unit_set_el));
+ new_el->unit_decl = DECL_UNIT (decl_in_table);
+ new_el->next_unit_set_el = NULL;
+ if (last_el == NULL)
+ el_list = last_el = new_el;
+ else
+ {
+ last_el->next_unit_set_el = new_el;
+ last_el = last_el->next_unit_set_el;
+ }
+ }
+ }
+ return el_list;
+}
+
+/* The function adds each element from SOURCE_LIST to presence (if
+ PRESENCE_P) or absence list of the each element from DEST_LIST.
+ Checking situations "unit requires own presence", "unit requires
+ own absence", and "unit excludes and requires presence of ...".
+ Remember that we process absence sets only after all presence
+ sets. */
+static void
+add_presence_absence (dest_list, source_list, req_pos, presence_p)
+ unit_set_el_t dest_list;
+ unit_set_el_t source_list;
+ pos_t req_pos ATTRIBUTE_UNUSED;
+ int presence_p;
+{
+ unit_set_el_t dst;
+ unit_set_el_t src;
+ unit_set_el_t curr_el;
+ unit_set_el_t prev_el;
+ unit_set_el_t copy;
+
+ for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
+ for (src = source_list; src != NULL; src = src->next_unit_set_el)
+ {
+ if (dst->unit_decl == src->unit_decl)
+ {
+ error ((presence_p
+ ? "unit `%s' requires own presence"
+ : "unit `%s' requires own absence"), src->unit_decl->name);
+ continue;
+ }
+ if (dst->unit_decl->automaton_name != NULL
+ && src->unit_decl->automaton_name != NULL
+ && strcmp (dst->unit_decl->automaton_name,
+ src->unit_decl->automaton_name) != 0)
+ {
+ error ((presence_p
+ ? "units `%s' and `%s' in presence set belong to different automata"
+ : "units `%s' and `%s' in absence set belong to different automata"),
+ src->unit_decl->name, dst->unit_decl->name);
+ continue;
+ }
+ for (curr_el = (presence_p
+ ? dst->unit_decl->presence_list
+ : dst->unit_decl->absence_list), prev_el = NULL;
+ curr_el != NULL;
+ prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
+ if (curr_el->unit_decl == src->unit_decl)
+ break;
+ if (curr_el == NULL)
+ {
+ /* Element not found - insert if there is no error. */
+ int no_error_flag = 1;
+
+ if (presence_p)
+ for (curr_el = dst->unit_decl->excl_list;
+ curr_el != NULL;
+ curr_el = curr_el->next_unit_set_el)
+ {
+ if (src->unit_decl == curr_el->unit_decl)
+ {
+ if (!w_flag)
+ {
+ error
+ ("unit `%s' excludes and requires presence of `%s'",
+ dst->unit_decl->name, src->unit_decl->name);
+ no_error_flag = 0;
+ }
+ else
+ warning
+ ("unit `%s' excludes and requires presence of `%s'",
+ dst->unit_decl->name, src->unit_decl->name);
+ }
+ }
+ else
+ for (curr_el = dst->unit_decl->presence_list;
+ curr_el != NULL;
+ curr_el = curr_el->next_unit_set_el)
+ {
+ if (src->unit_decl == curr_el->unit_decl)
+ {
+ if (!w_flag)
+ {
+ error
+ ("unit `%s' requires absence and presence of `%s'",
+ dst->unit_decl->name, src->unit_decl->name);
+ no_error_flag = 0;
+ }
+ else
+ warning
+ ("unit `%s' requires absence and presence of `%s'",
+ dst->unit_decl->name, src->unit_decl->name);
+ }
+ }
+ if (no_error_flag)
+ {
+ copy = copy_node (src, sizeof (*src));
+ copy->next_unit_set_el = NULL;
+ if (prev_el == NULL)
+ {
+ if (presence_p)
+ dst->unit_decl->presence_list = copy;
+ else
+ dst->unit_decl->absence_list = copy;
+ }
+ else
+ prev_el->next_unit_set_el = copy;
+ }
+ }
+ }
+}
+
+/* The function searches for bypass with given IN_INSN_RESERV in given
+ BYPASS_LIST. */
+static struct bypass_decl *
+find_bypass (bypass_list, in_insn_reserv)
+ struct bypass_decl *bypass_list;
+ struct insn_reserv_decl *in_insn_reserv;
+{
+ struct bypass_decl *bypass;
+
+ for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
+ if (bypass->in_insn_reserv == in_insn_reserv)
+ break;
+ return bypass;
+}
+
+/* The function processes pipeline description declarations, checks
+ their correctness, and forms exclusion/presence/absence sets. */
+static void
+process_decls ()
+{
+ decl_t decl;
+ decl_t automaton_decl;
+ decl_t decl_in_table;
+ decl_t out_insn_reserv;
+ decl_t in_insn_reserv;
+ struct bypass_decl *bypass;
+ int automaton_presence;
+ int i;
+
+ /* Checking repeated automata declarations. */
+ automaton_presence = 0;
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_automaton)
+ {
+ automaton_presence = 1;
+ decl_in_table = insert_automaton_decl (decl);
+ if (decl_in_table != decl)
+ {
+ if (!w_flag)
+ error ("repeated declaration of automaton `%s'",
+ DECL_AUTOMATON (decl)->name);
+ else
+ warning ("repeated declaration of automaton `%s'",
+ DECL_AUTOMATON (decl)->name);
+ }
+ }
+ }
+ /* Checking undeclared automata, repeated declarations (except for
+ automata) and correctness of their attributes (insn latency times
+ etc.). */
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv)
+ {
+ DECL_INSN_RESERV (decl)->condexp
+ = check_attr_test (DECL_INSN_RESERV (decl)->condexp, 0, 0);
+ if (DECL_INSN_RESERV (decl)->default_latency < 0)
+ error ("define_insn_reservation `%s' has negative latency time",
+ DECL_INSN_RESERV (decl)->name);
+ DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
+ description->insns_num++;
+ decl_in_table = insert_insn_decl (decl);
+ if (decl_in_table != decl)
+ error ("`%s' is already used as insn reservation name",
+ DECL_INSN_RESERV (decl)->name);
+ }
+ else if (decl->mode == dm_bypass)
+ {
+ if (DECL_BYPASS (decl)->latency < 0)
+ error ("define_bypass `%s - %s' has negative latency time",
+ DECL_BYPASS (decl)->out_insn_name,
+ DECL_BYPASS (decl)->in_insn_name);
+ }
+ else if (decl->mode == dm_unit || decl->mode == dm_reserv)
+ {
+ if (decl->mode == dm_unit)
+ {
+ DECL_UNIT (decl)->automaton_decl = NULL;
+ if (DECL_UNIT (decl)->automaton_name != NULL)
+ {
+ automaton_decl
+ = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
+ if (automaton_decl == NULL)
+ error ("automaton `%s' is not declared",
+ DECL_UNIT (decl)->automaton_name);
+ else
+ {
+ DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
+ DECL_UNIT (decl)->automaton_decl
+ = DECL_AUTOMATON (automaton_decl);
+ }
+ }
+ else if (automaton_presence)
+ error ("define_unit `%s' without automaton when one defined",
+ DECL_UNIT (decl)->name);
+ DECL_UNIT (decl)->unit_num = description->units_num;
+ description->units_num++;
+ if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
+ {
+ error ("`%s' is declared as cpu unit", NOTHING_NAME);
+ continue;
+ }
+ decl_in_table = find_decl (DECL_UNIT (decl)->name);
+ }
+ else
+ {
+ if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
+ {
+ error ("`%s' is declared as cpu reservation", NOTHING_NAME);
+ continue;
+ }
+ decl_in_table = find_decl (DECL_RESERV (decl)->name);
+ }
+ if (decl_in_table == NULL)
+ decl_in_table = insert_decl (decl);
+ else
+ {
+ if (decl->mode == dm_unit)
+ error ("repeated declaration of unit `%s'",
+ DECL_UNIT (decl)->name);
+ else
+ error ("repeated declaration of reservation `%s'",
+ DECL_RESERV (decl)->name);
+ }
+ }
+ }
+ /* Check bypasses and form list of bypasses for each (output)
+ insn. */
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_bypass)
+ {
+ out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
+ in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
+ if (out_insn_reserv == NULL)
+ error ("there is no insn reservation `%s'",
+ DECL_BYPASS (decl)->out_insn_name);
+ else if (in_insn_reserv == NULL)
+ error ("there is no insn reservation `%s'",
+ DECL_BYPASS (decl)->in_insn_name);
+ else
+ {
+ DECL_BYPASS (decl)->out_insn_reserv
+ = DECL_INSN_RESERV (out_insn_reserv);
+ DECL_BYPASS (decl)->in_insn_reserv
+ = DECL_INSN_RESERV (in_insn_reserv);
+ bypass
+ = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
+ DECL_BYPASS (decl)->in_insn_reserv);
+ if (bypass != NULL)
+ {
+ if (DECL_BYPASS (decl)->latency == bypass->latency)
+ {
+ if (!w_flag)
+ error
+ ("the same bypass `%s - %s' is already defined",
+ DECL_BYPASS (decl)->out_insn_name,
+ DECL_BYPASS (decl)->in_insn_name);
+ else
+ warning
+ ("the same bypass `%s - %s' is already defined",
+ DECL_BYPASS (decl)->out_insn_name,
+ DECL_BYPASS (decl)->in_insn_name);
+ }
+ else
+ error ("bypass `%s - %s' is already defined",
+ DECL_BYPASS (decl)->out_insn_name,
+ DECL_BYPASS (decl)->in_insn_name);
+ }
+ else
+ {
+ DECL_BYPASS (decl)->next
+ = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
+ DECL_INSN_RESERV (out_insn_reserv)->bypass_list
+ = DECL_BYPASS (decl);
+ }
+ }
+ }
+ }
+
+ /* Check exclusion set declarations and form exclussion sets. */
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_excl)
+ {
+ unit_set_el_t unit_set_el_list;
+ unit_set_el_t unit_set_el_list_2;
+
+ unit_set_el_list
+ = process_excls (DECL_EXCL (decl)->names,
+ DECL_EXCL (decl)->first_list_length, decl->pos);
+ unit_set_el_list_2
+ = process_excls (&DECL_EXCL (decl)->names
+ [DECL_EXCL (decl)->first_list_length],
+ DECL_EXCL (decl)->names_num
+ - DECL_EXCL (decl)->first_list_length,
+ decl->pos);
+ add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
+ add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
+ }
+ }
+
+ /* Check presence set declarations and form presence sets. */
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_presence)
+ {
+ unit_set_el_t unit_set_el_list;
+ unit_set_el_t unit_set_el_list_2;
+
+ unit_set_el_list
+ = process_presence_absence
+ (DECL_PRESENCE (decl)->names,
+ DECL_PRESENCE (decl)->first_list_length, decl->pos, 1);
+ unit_set_el_list_2
+ = process_presence_absence
+ (&DECL_PRESENCE (decl)->names
+ [DECL_PRESENCE (decl)->first_list_length],
+ DECL_PRESENCE (decl)->names_num
+ - DECL_PRESENCE (decl)->first_list_length,
+ decl->pos, 1);
+ add_presence_absence (unit_set_el_list, unit_set_el_list_2,
+ decl->pos, 1);
+ }
+ }
+
+ /* Check absence set declarations and form absence sets. */
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_absence)
+ {
+ unit_set_el_t unit_set_el_list;
+ unit_set_el_t unit_set_el_list_2;
+
+ unit_set_el_list
+ = process_presence_absence
+ (DECL_ABSENCE (decl)->names,
+ DECL_ABSENCE (decl)->first_list_length, decl->pos, 0);
+ unit_set_el_list_2
+ = process_presence_absence
+ (&DECL_ABSENCE (decl)->names
+ [DECL_ABSENCE (decl)->first_list_length],
+ DECL_ABSENCE (decl)->names_num
+ - DECL_ABSENCE (decl)->first_list_length,
+ decl->pos, 0);
+ add_presence_absence (unit_set_el_list, unit_set_el_list_2,
+ decl->pos, 0);
+ }
+ }
+}
+
+/* The following function checks that declared automaton is used. If
+ the automaton is not used, the function fixes error/warning. The
+ following function must be called only after `process_decls'. */
+static void
+check_automaton_usage ()
+{
+ decl_t decl;
+ int i;
+
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_automaton
+ && !DECL_AUTOMATON (decl)->automaton_is_used)
+ {
+ if (!w_flag)
+ error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
+ else
+ warning ("automaton `%s' is not used",
+ DECL_AUTOMATON (decl)->name);
+ }
+ }
+}
+
+/* The following recursive function processes all regexp in order to
+ fix usage of units or reservations and to fix errors of undeclared
+ name. The function may change unit_regexp onto reserv_regexp.
+ Remember that reserv_regexp does not exist before the function
+ call. */
+static regexp_t
+process_regexp (regexp)
+ regexp_t regexp;
+{
+ decl_t decl_in_table;
+ regexp_t new_regexp;
+ int i;
+
+ if (regexp->mode == rm_unit)
+ {
+ decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
+ if (decl_in_table == NULL)
+ error ("undeclared unit or reservation `%s'",
+ REGEXP_UNIT (regexp)->name);
+ else if (decl_in_table->mode == dm_unit)
+ {
+ DECL_UNIT (decl_in_table)->unit_is_used = 1;
+ REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
+ }
+ else if (decl_in_table->mode == dm_reserv)
+ {
+ DECL_RESERV (decl_in_table)->reserv_is_used = 1;
+ new_regexp = create_node (sizeof (struct regexp));
+ new_regexp->mode = rm_reserv;
+ new_regexp->pos = regexp->pos;
+ REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
+ REGEXP_RESERV (new_regexp)->reserv_decl
+ = DECL_RESERV (decl_in_table);
+ regexp = new_regexp;
+ }
+ else
+ abort ();
+ }
+ else if (regexp->mode == rm_sequence)
+ for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
+ REGEXP_SEQUENCE (regexp)->regexps [i]
+ = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
+ else if (regexp->mode == rm_allof)
+ for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
+ REGEXP_ALLOF (regexp)->regexps [i]
+ = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
+ else if (regexp->mode == rm_oneof)
+ for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
+ REGEXP_ONEOF (regexp)->regexps [i]
+ = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
+ else if (regexp->mode == rm_repeat)
+ REGEXP_REPEAT (regexp)->regexp
+ = process_regexp (REGEXP_REPEAT (regexp)->regexp);
+ else if (regexp->mode != rm_nothing)
+ abort ();
+ return regexp;
+}
+
+/* The following function processes regexp of define_reservation and
+ define_insn_reservation with the aid of function
+ `process_regexp'. */
+static void
+process_regexp_decls ()
+{
+ decl_t decl;
+ int i;
+
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_reserv)
+ DECL_RESERV (decl)->regexp
+ = process_regexp (DECL_RESERV (decl)->regexp);
+ else if (decl->mode == dm_insn_reserv)
+ DECL_INSN_RESERV (decl)->regexp
+ = process_regexp (DECL_INSN_RESERV (decl)->regexp);
+ }
+}
+
+/* The following function checks that declared unit is used. If the
+ unit is not used, the function fixes errors/warnings. The
+ following function must be called only after `process_decls',
+ `process_regexp_decls'. */
+static void
+check_usage ()
+{
+ decl_t decl;
+ int i;
+
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
+ {
+ if (!w_flag)
+ error ("unit `%s' is not used", DECL_UNIT (decl)->name);
+ else
+ warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
+ }
+ else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
+ {
+ if (!w_flag)
+ error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
+ else
+ warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
+ }
+ }
+}
+
+/* The following variable value is number of reservation being
+ processed on loop recognition. */
+static int curr_loop_pass_num;
+
+/* The following recursive function returns nonzero value if REGEXP
+ contains given decl or reservations in given regexp refers for
+ given decl. */
+static int
+loop_in_regexp (regexp, start_decl)
+ regexp_t regexp;
+ decl_t start_decl;
+{
+ int i;
+
+ if (regexp == NULL)
+ return 0;
+ if (regexp->mode == rm_unit)
+ return 0;
+ else if (regexp->mode == rm_reserv)
+ {
+ if (start_decl->mode == dm_reserv
+ && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
+ return 1;
+ else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
+ == curr_loop_pass_num)
+ /* declaration has been processed. */
+ return 0;
+ else
+ {
+ REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
+ = curr_loop_pass_num;
+ return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
+ start_decl);
+ }
+ }
+ else if (regexp->mode == rm_sequence)
+ {
+ for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
+ if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
+ return 1;
+ return 0;
+ }
+ else if (regexp->mode == rm_allof)
+ {
+ for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
+ if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
+ return 1;
+ return 0;
+ }
+ else if (regexp->mode == rm_oneof)
+ {
+ for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
+ if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
+ return 1;
+ return 0;
+ }
+ else if (regexp->mode == rm_repeat)
+ return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
+ else
+ {
+ if (regexp->mode != rm_nothing)
+ abort ();
+ return 0;
+ }
+}
+
+/* The following function fixes errors "cycle in definition ...". The
+ function uses function `loop_in_regexp' for that. */
+static void
+check_loops_in_regexps ()
+{
+ decl_t decl;
+ int i;
+
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_reserv)
+ DECL_RESERV (decl)->loop_pass_num = 0;
+ }
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ curr_loop_pass_num = i;
+
+ if (decl->mode == dm_reserv)
+ {
+ DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
+ if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
+ {
+ if (DECL_RESERV (decl)->regexp == NULL)
+ abort ();
+ error ("cycle in definition of reservation `%s'",
+ DECL_RESERV (decl)->name);
+ }
+ }
+ }
+}
+
+/* The function recursively processes IR of reservation and defines
+ max and min cycle for reservation of unit and for result in the
+ reservation. */
+static int
+process_regexp_cycles (regexp, start_cycle)
+ regexp_t regexp;
+ int start_cycle;
+{
+ int i;
+
+ if (regexp->mode == rm_unit)
+ {
+ if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < start_cycle)
+ REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = start_cycle;
+ return start_cycle;
+ }
+ else if (regexp->mode == rm_reserv)
+ return process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
+ start_cycle);
+ else if (regexp->mode == rm_repeat)
+ {
+ for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
+ start_cycle = process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
+ start_cycle) + 1;
+ return start_cycle;
+ }
+ else if (regexp->mode == rm_sequence)
+ {
+ for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
+ start_cycle
+ = process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
+ start_cycle) + 1;
+ return start_cycle;
+ }
+ else if (regexp->mode == rm_allof)
+ {
+ int finish_cycle = 0;
+ int cycle;
+
+ for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
+ {
+ cycle = process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
+ start_cycle);
+ if (finish_cycle < cycle)
+ finish_cycle = cycle;
+ }
+ return finish_cycle;
+ }
+ else if (regexp->mode == rm_oneof)
+ {
+ int finish_cycle = 0;
+ int cycle;
+
+ for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
+ {
+ cycle = process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
+ start_cycle);
+ if (finish_cycle < cycle)
+ finish_cycle = cycle;
+ }
+ return finish_cycle;
+ }
+ else
+ {
+ if (regexp->mode != rm_nothing)
+ abort ();
+ return start_cycle;
+ }
+}
+
+/* The following function is called only for correct program. The
+ function defines max reservation of insns in cycles. */
+static void
+evaluate_max_reserv_cycles ()
+{
+ int max_insn_cycles_num;
+ decl_t decl;
+ int i;
+
+ description->max_insn_reserv_cycles = 0;
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv)
+ {
+ max_insn_cycles_num
+ = process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0);
+ if (description->max_insn_reserv_cycles < max_insn_cycles_num)
+ description->max_insn_reserv_cycles = max_insn_cycles_num;
+ }
+ }
+ description->max_insn_reserv_cycles++;
+}
+
+/* The following function calls functions for checking all
+ description. */
+static void
+check_all_description ()
+{
+ process_decls ();
+ check_automaton_usage ();
+ process_regexp_decls ();
+ check_usage ();
+ check_loops_in_regexps ();
+ if (!have_error)
+ evaluate_max_reserv_cycles ();
+}
+
+
+
+/* The page contains abstract data `ticker'. This data is used to
+ report time of different phases of building automata. It is
+ possibly to write a description for which automata will be built
+ during several minutes even on fast machine. */
+
+/* The following function creates ticker and makes it active. */
+static ticker_t
+create_ticker ()
+{
+ ticker_t ticker;
+
+ ticker.modified_creation_time = get_run_time ();
+ ticker.incremented_off_time = 0;
+ return ticker;
+}
+
+/* The following function switches off given ticker. */
+static void
+ticker_off (ticker)
+ ticker_t *ticker;
+{
+ if (ticker->incremented_off_time == 0)
+ ticker->incremented_off_time = get_run_time () + 1;
+}
+
+/* The following function switches on given ticker. */
+static void
+ticker_on (ticker)
+ ticker_t *ticker;
+{
+ if (ticker->incremented_off_time != 0)
+ {
+ ticker->modified_creation_time
+ += get_run_time () - ticker->incremented_off_time + 1;
+ ticker->incremented_off_time = 0;
+ }
+}
+
+/* The following function returns current time in milliseconds since
+ the moment when given ticker was created. */
+static int
+active_time (ticker)
+ ticker_t ticker;
+{
+ if (ticker.incremented_off_time != 0)
+ return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
+ else
+ return get_run_time () - ticker.modified_creation_time;
+}
+
+/* The following function returns string representation of active time
+ of given ticker. The result is string representation of seconds
+ with accuracy of 1/100 second. Only result of the last call of the
+ function exists. Therefore the following code is not correct
+
+ printf ("parser time: %s\ngeneration time: %s\n",
+ active_time_string (parser_ticker),
+ active_time_string (generation_ticker));
+
+ Correct code has to be the following
+
+ printf ("parser time: %s\n", active_time_string (parser_ticker));
+ printf ("generation time: %s\n",
+ active_time_string (generation_ticker));
+
+*/
+static void
+print_active_time (f, ticker)
+ FILE *f;
+ ticker_t ticker;
+{
+ int msecs;
+
+ msecs = active_time (ticker);
+ fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
+}
+
+
+
+/* The following variable value is number of automaton which are
+ really being created. This value is defined on the base of
+ argument of option `-split'. If the variable has zero value the
+ number of automata is defined by the constructions `%automaton'.
+ This case occures when option `-split' is absent or has zero
+ argument. If constructions `define_automaton' is absent only one
+ automaton is created. */
+static int automata_num;
+
+/* The following variable values are times of
+ o transformation of regular expressions
+ o building NDFA (DFA if !ndfa_flag)
+ o NDFA -> DFA (simply the same automaton if !ndfa_flag)
+ o DFA minimization
+ o building insn equivalence classes
+ o all previous ones
+ o code output */
+static ticker_t transform_time;
+static ticker_t NDFA_time;
+static ticker_t NDFA_to_DFA_time;
+static ticker_t minimize_time;
+static ticker_t equiv_time;
+static ticker_t automaton_generation_time;
+static ticker_t output_time;
+
+/* The following variable values are times of
+ all checking
+ all generation
+ all pipeline hazard translator work */
+static ticker_t check_time;
+static ticker_t generation_time;
+static ticker_t all_time;
+
+
+
+/* Pseudo insn decl which denotes advancing cycle. */
+static decl_t advance_cycle_insn_decl;
+static void
+add_advance_cycle_insn_decl ()
+{
+ advance_cycle_insn_decl = create_node (sizeof (struct decl));
+ advance_cycle_insn_decl->mode = dm_insn_reserv;
+ advance_cycle_insn_decl->pos = no_pos;
+ DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
+ DECL_INSN_RESERV (advance_cycle_insn_decl)->name = (char *) "$advance_cycle";
+ DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
+ = description->insns_num;
+ description->decls [description->decls_num] = advance_cycle_insn_decl;
+ description->decls_num++;
+ description->insns_num++;
+ num_dfa_decls++;
+}
+
+
+/* Abstract data `alternative states' which reperesents
+ nondeterministic nature of the description (see comments for
+ structures alt_state and state). */
+
+/* List of free states. */
+static alt_state_t first_free_alt_state;
+
+#ifndef NDEBUG
+/* The following variables is maximal number of allocated nodes
+ alt_state. */
+static int allocated_alt_states_num = 0;
+#endif
+
+/* The following function returns free node alt_state. It may be new
+ allocated node or node freed eralier. */
+static alt_state_t
+get_free_alt_state ()
+{
+ alt_state_t result;
+
+ if (first_free_alt_state != NULL)
+ {
+ result = first_free_alt_state;
+ first_free_alt_state = first_free_alt_state->next_alt_state;
+ }
+ else
+ {
+#ifndef NDEBUG
+ allocated_alt_states_num++;
+#endif
+ result = create_node (sizeof (struct alt_state));
+ }
+ result->state = NULL;
+ result->next_alt_state = NULL;
+ result->next_sorted_alt_state = NULL;
+ return result;
+}
+
+/* The function frees node ALT_STATE. */
+static void
+free_alt_state (alt_state)
+ alt_state_t alt_state;
+{
+ if (alt_state == NULL)
+ return;
+ alt_state->next_alt_state = first_free_alt_state;
+ first_free_alt_state = alt_state;
+}
+
+/* The function frees list started with node ALT_STATE_LIST. */
+static void
+free_alt_states (alt_states_list)
+ alt_state_t alt_states_list;
+{
+ alt_state_t curr_alt_state;
+ alt_state_t next_alt_state;
+
+ for (curr_alt_state = alt_states_list;
+ curr_alt_state != NULL;
+ curr_alt_state = next_alt_state)
+ {
+ next_alt_state = curr_alt_state->next_alt_state;
+ free_alt_state (curr_alt_state);
+ }
+}
+
+/* The function compares unique numbers of alt states. */
+static int
+alt_state_cmp (alt_state_ptr_1, alt_state_ptr_2)
+ const void *alt_state_ptr_1;
+ const void *alt_state_ptr_2;
+{
+ if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
+ == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
+ return 0;
+ else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
+ < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
+ return -1;
+ else
+ return 1;
+}
+
+/* The function sorts ALT_STATES_LIST and removes duplicated alt
+ states from the list. The comparison key is alt state unique
+ number. */
+static alt_state_t
+uniq_sort_alt_states (alt_states_list)
+ alt_state_t alt_states_list;
+{
+ alt_state_t curr_alt_state;
+ vla_ptr_t alt_states;
+ size_t i;
+ size_t prev_unique_state_ind;
+ alt_state_t result;
+ alt_state_t *result_ptr;
+
+ VLA_PTR_CREATE (alt_states, 150, "alt_states");
+ for (curr_alt_state = alt_states_list;
+ curr_alt_state != NULL;
+ curr_alt_state = curr_alt_state->next_alt_state)
+ VLA_PTR_ADD (alt_states, curr_alt_state);
+ qsort (VLA_PTR_BEGIN (alt_states), VLA_PTR_LENGTH (alt_states),
+ sizeof (alt_state_t), alt_state_cmp);
+ if (VLA_PTR_LENGTH (alt_states) == 0)
+ result = NULL;
+ else
+ {
+ result_ptr = VLA_PTR_BEGIN (alt_states);
+ prev_unique_state_ind = 0;
+ for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
+ if (result_ptr [prev_unique_state_ind]->state != result_ptr [i]->state)
+ {
+ prev_unique_state_ind++;
+ result_ptr [prev_unique_state_ind] = result_ptr [i];
+ }
+#if 0
+ for (i = prev_unique_state_ind + 1; i < VLA_PTR_LENGTH (alt_states); i++)
+ free_alt_state (result_ptr [i]);
+#endif
+ VLA_PTR_SHORTEN (alt_states, i - prev_unique_state_ind - 1);
+ result_ptr = VLA_PTR_BEGIN (alt_states);
+ for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
+ result_ptr [i - 1]->next_sorted_alt_state = result_ptr [i];
+ result_ptr [i - 1]->next_sorted_alt_state = NULL;
+ result = *result_ptr;
+ }
+ VLA_PTR_DELETE (alt_states);
+ return result;
+}
+
+/* The function checks equality of alt state lists. Remember that the
+ lists must be already sorted by the previous function. */
+static int
+alt_states_eq (alt_states_1, alt_states_2)
+ alt_state_t alt_states_1;
+ alt_state_t alt_states_2;
+{
+ while (alt_states_1 != NULL && alt_states_2 != NULL
+ && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
+ {
+ alt_states_1 = alt_states_1->next_sorted_alt_state;
+ alt_states_2 = alt_states_2->next_sorted_alt_state;
+ }
+ return alt_states_1 == alt_states_2;
+}
+
+/* Initialization of the abstract data. */
+static void
+initiate_alt_states ()
+{
+ first_free_alt_state = NULL;
+}
+
+/* Finishing work with the abstract data. */
+static void
+finish_alt_states ()
+{
+}
+
+
+
+/* The page contains macros for work with bits strings. We could use
+ standard gcc bitmap or sbitmap but it would result in difficulties
+ of building canadian cross. */
+
+/* Set bit number bitno in the bit string. The macro is not side
+ effect proof. */
+#define SET_BIT(bitstring, bitno) \
+ (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
+
+/* Test if bit number bitno in the bitstring is set. The macro is not
+ side effect proof. */
+#define TEST_BIT(bitstring, bitno) \
+ (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
+
+
+
+/* This page contains abstract data `state'. */
+
+/* Maximal length of reservations in cycles (>= 1). */
+static int max_cycles_num;
+
+/* Number of set elements (see type set_el_t) needed for
+ representation of one cycle reservation. It is depended on units
+ number. */
+static int els_in_cycle_reserv;
+
+/* Number of set elements (see type set_el_t) needed for
+ representation of maximal length reservation. Deterministic
+ reservation is stored as set (bit string) of length equal to the
+ variable value * number of bits in set_el_t. */
+static int els_in_reservs;
+
+/* VLA for representation of array of pointers to unit
+ declarations. */
+static vla_ptr_t units_container;
+
+/* The start address of the array. */
+static unit_decl_t *units_array;
+
+/* Empty reservation of maximal length. */
+static reserv_sets_t empty_reserv;
+
+/* The state table itself is represented by the following variable. */
+static htab_t state_table;
+
+/* VLA for representation of array of pointers to free nodes
+ `state'. */
+static vla_ptr_t free_states;
+
+static int curr_unique_state_num;
+
+#ifndef NDEBUG
+/* The following variables is maximal number of allocated nodes
+ `state'. */
+static int allocated_states_num = 0;
+#endif
+
+/* Allocate new reservation set. */
+static reserv_sets_t
+alloc_empty_reserv_sets ()
+{
+ reserv_sets_t result;
+
+ obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
+ result = (reserv_sets_t) obstack_base (&irp);
+ obstack_finish (&irp);
+ memset (result, 0, els_in_reservs * sizeof (set_el_t));
+ return result;
+}
+
+/* Hash value of reservation set. */
+static unsigned
+reserv_sets_hash_value (reservs)
+ reserv_sets_t reservs;
+{
+ set_el_t hash_value;
+ unsigned result;
+ int reservs_num, i;
+ set_el_t *reserv_ptr;
+
+ hash_value = 0;
+ reservs_num = els_in_reservs;
+ reserv_ptr = reservs;
+ i = 0;
+ while (reservs_num != 0)
+ {
+ reservs_num--;
+ hash_value += ((*reserv_ptr >> i)
+ | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
+ i++;
+ if (i == sizeof (set_el_t) * CHAR_BIT)
+ i = 0;
+ reserv_ptr++;
+ }
+ if (sizeof (set_el_t) <= sizeof (unsigned))
+ return hash_value;
+ result = 0;
+ for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
+ {
+ result += (unsigned) hash_value;
+ hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
+ }
+ return result;
+}
+
+/* Comparison of given reservation sets. */
+static int
+reserv_sets_cmp (reservs_1, reservs_2)
+ reserv_sets_t reservs_1;
+ reserv_sets_t reservs_2;
+{
+ int reservs_num;
+ set_el_t *reserv_ptr_1;
+ set_el_t *reserv_ptr_2;
+
+ if (reservs_1 == NULL || reservs_2 == NULL)
+ abort ();
+ reservs_num = els_in_reservs;
+ reserv_ptr_1 = reservs_1;
+ reserv_ptr_2 = reservs_2;
+ while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
+ {
+ reservs_num--;
+ reserv_ptr_1++;
+ reserv_ptr_2++;
+ }
+ if (reservs_num == 0)
+ return 0;
+ else if (*reserv_ptr_1 < *reserv_ptr_2)
+ return -1;
+ else
+ return 1;
+}
+
+/* The function checks equality of the reservation sets. */
+static int
+reserv_sets_eq (reservs_1, reservs_2)
+ reserv_sets_t reservs_1;
+ reserv_sets_t reservs_2;
+{
+ return reserv_sets_cmp (reservs_1, reservs_2) == 0;
+}
+
+/* Set up in the reservation set that unit with UNIT_NUM is used on
+ CYCLE_NUM. */
+static void
+set_unit_reserv (reservs, cycle_num, unit_num)
+ reserv_sets_t reservs;
+ int cycle_num;
+ int unit_num;
+{
+ if (cycle_num >= max_cycles_num)
+ abort ();
+ SET_BIT (reservs, cycle_num * els_in_cycle_reserv
+ * sizeof (set_el_t) * CHAR_BIT + unit_num);
+}
+
+/* Set up in the reservation set RESERVS that unit with UNIT_NUM is
+ used on CYCLE_NUM. */
+static int
+test_unit_reserv (reservs, cycle_num, unit_num)
+ reserv_sets_t reservs;
+ int cycle_num;
+ int unit_num;
+{
+ if (cycle_num >= max_cycles_num)
+ abort ();
+ return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
+ * sizeof (set_el_t) * CHAR_BIT + unit_num);
+}
+
+/* The function checks that the reservation set represents no one unit
+ reservation. */
+static int
+it_is_empty_reserv_sets (operand)
+ reserv_sets_t operand;
+{
+ set_el_t *reserv_ptr;
+ int reservs_num;
+
+ if (operand == NULL)
+ abort ();
+ for (reservs_num = els_in_reservs, reserv_ptr = operand;
+ reservs_num != 0;
+ reserv_ptr++, reservs_num--)
+ if (*reserv_ptr != 0)
+ return 0;
+ return 1;
+}
+
+/* The function checks that the reservation sets are intersected,
+ i.e. there is a unit reservation on a cycle in both reservation
+ sets. */
+static int
+reserv_sets_are_intersected (operand_1, operand_2)
+ reserv_sets_t operand_1;
+ reserv_sets_t operand_2;
+{
+ set_el_t *el_ptr_1;
+ set_el_t *el_ptr_2;
+ set_el_t *cycle_ptr_1;
+ set_el_t *cycle_ptr_2;
+ int nonzero_p;
+
+ if (operand_1 == NULL || operand_2 == NULL)
+ abort ();
+ for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
+ el_ptr_1 < operand_1 + els_in_reservs;
+ el_ptr_1++, el_ptr_2++)
+ if (*el_ptr_1 & *el_ptr_2)
+ return 1;
+ for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
+ cycle_ptr_1 < operand_1 + els_in_reservs;
+ cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
+ {
+ for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
+ el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
+ el_ptr_1++, el_ptr_2++)
+ if (*el_ptr_1 & *el_ptr_2)
+ return 1;
+ nonzero_p = 0;
+ for (el_ptr_1 = cycle_ptr_1,
+ el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 1);
+ el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
+ el_ptr_1++, el_ptr_2++)
+ if (*el_ptr_1 & *el_ptr_2)
+ break;
+ else if (*el_ptr_2 != 0)
+ nonzero_p = 1;
+ if (nonzero_p && el_ptr_1 >= cycle_ptr_1 + els_in_cycle_reserv)
+ return 1;
+ for (el_ptr_1 = cycle_ptr_1,
+ el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 0);
+ el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
+ el_ptr_1++, el_ptr_2++)
+ /* It looks like code for exclusion but exclusion set is
+ made as symmetric relation preliminary. */
+ if (*el_ptr_1 & *el_ptr_2)
+ return 1;
+ }
+ return 0;
+}
+
+/* The function sets up RESULT bits by bits of OPERAND shifted on one
+ cpu cycle. The remaining bits of OPERAND (representing the last
+ cycle unit reservations) are not chenged. */
+static void
+reserv_sets_shift (result, operand)
+ reserv_sets_t result;
+ reserv_sets_t operand;
+{
+ int i;
+
+ if (result == NULL || operand == NULL || result == operand)
+ abort ();
+ for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
+ result [i - els_in_cycle_reserv] = operand [i];
+}
+
+/* OR of the reservation sets. */
+static void
+reserv_sets_or (result, operand_1, operand_2)
+ reserv_sets_t result;
+ reserv_sets_t operand_1;
+ reserv_sets_t operand_2;
+{
+ set_el_t *el_ptr_1;
+ set_el_t *el_ptr_2;
+ set_el_t *result_set_el_ptr;
+
+ if (result == NULL || operand_1 == NULL || operand_2 == NULL)
+ abort ();
+ for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
+ el_ptr_1 < operand_1 + els_in_reservs;
+ el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
+ *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
+}
+
+/* AND of the reservation sets. */
+static void
+reserv_sets_and (result, operand_1, operand_2)
+ reserv_sets_t result;
+ reserv_sets_t operand_1;
+ reserv_sets_t operand_2;
+{
+ set_el_t *el_ptr_1;
+ set_el_t *el_ptr_2;
+ set_el_t *result_set_el_ptr;
+
+ if (result == NULL || operand_1 == NULL || operand_2 == NULL)
+ abort ();
+ for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
+ el_ptr_1 < operand_1 + els_in_reservs;
+ el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
+ *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
+}
+
+/* The function outputs string representation of units reservation on
+ cycle START_CYCLE in the reservation set. The function uses repeat
+ construction if REPETITION_NUM > 1. */
+static void
+output_cycle_reservs (f, reservs, start_cycle, repetition_num)
+ FILE *f;
+ reserv_sets_t reservs;
+ int start_cycle;
+ int repetition_num;
+{
+ int unit_num;
+ int reserved_units_num;
+
+ reserved_units_num = 0;
+ for (unit_num = 0; unit_num < description->units_num; unit_num++)
+ if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
+ * sizeof (set_el_t) * CHAR_BIT + unit_num))
+ reserved_units_num++;
+ if (repetition_num <= 0)
+ abort ();
+ if (repetition_num != 1 && reserved_units_num > 1)
+ fprintf (f, "(");
+ reserved_units_num = 0;
+ for (unit_num = 0;
+ unit_num < description->units_num;
+ unit_num++)
+ if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
+ * sizeof (set_el_t) * CHAR_BIT + unit_num))
+ {
+ if (reserved_units_num != 0)
+ fprintf (f, "+");
+ reserved_units_num++;
+ fprintf (f, "%s", units_array [unit_num]->name);
+ }
+ if (reserved_units_num == 0)
+ fprintf (f, NOTHING_NAME);
+ if (repetition_num <= 0)
+ abort ();
+ if (reserved_units_num > 1)
+ fprintf (f, ")");
+ if (repetition_num != 1)
+ fprintf (f, "*%d", repetition_num);
+}
+
+/* The function outputs string representation of units reservation in
+ the reservation set. */
+static void
+output_reserv_sets (f, reservs)
+ FILE *f;
+ reserv_sets_t reservs;
+{
+ int start_cycle = 0;
+ int cycle;
+ int repetition_num;
+
+ repetition_num = 0;
+ for (cycle = 0; cycle < max_cycles_num; cycle++)
+ if (repetition_num == 0)
+ {
+ repetition_num++;
+ start_cycle = cycle;
+ }
+ else if (memcmp
+ ((char *) reservs + start_cycle * els_in_cycle_reserv
+ * sizeof (set_el_t),
+ (char *) reservs + cycle * els_in_cycle_reserv
+ * sizeof (set_el_t),
+ els_in_cycle_reserv * sizeof (set_el_t)) == 0)
+ repetition_num++;
+ else
+ {
+ if (start_cycle != 0)
+ fprintf (f, ", ");
+ output_cycle_reservs (f, reservs, start_cycle, repetition_num);
+ repetition_num = 1;
+ start_cycle = cycle;
+ }
+ if (start_cycle < max_cycles_num)
+ {
+ if (start_cycle != 0)
+ fprintf (f, ", ");
+ output_cycle_reservs (f, reservs, start_cycle, repetition_num);
+ }
+}
+
+/* The following function returns free node state for AUTOMATON. It
+ may be new allocated node or node freed eralier. The function also
+ allocates reservation set if WITH_RESERVS has nonzero value. */
+static state_t
+get_free_state (with_reservs, automaton)
+ int with_reservs;
+ automaton_t automaton;
+{
+ state_t result;
+
+ if (max_cycles_num <= 0 || automaton == NULL)
+ abort ();
+ if (VLA_PTR_LENGTH (free_states) != 0)
+ {
+ result = VLA_PTR (free_states, VLA_PTR_LENGTH (free_states) - 1);
+ VLA_PTR_SHORTEN (free_states, 1);
+ result->automaton = automaton;
+ result->first_out_arc = NULL;
+ result->it_was_placed_in_stack_for_NDFA_forming = 0;
+ result->it_was_placed_in_stack_for_DFA_forming = 0;
+ result->component_states = NULL;
+ result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
+ }
+ else
+ {
+#ifndef NDEBUG
+ allocated_states_num++;
+#endif
+ result = create_node (sizeof (struct state));
+ result->automaton = automaton;
+ result->first_out_arc = NULL;
+ result->unique_num = curr_unique_state_num;
+ result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
+ curr_unique_state_num++;
+ }
+ if (with_reservs)
+ {
+ if (result->reservs == NULL)
+ result->reservs = alloc_empty_reserv_sets ();
+ else
+ memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
+ }
+ return result;
+}
+
+/* The function frees node STATE. */
+static void
+free_state (state)
+ state_t state;
+{
+ free_alt_states (state->component_states);
+ VLA_PTR_ADD (free_states, state);
+}
+
+/* Hash value of STATE. If STATE represents deterministic state it is
+ simply hash value of the corresponding reservation set. Otherwise
+ it is formed from hash values of the component deterministic
+ states. One more key is order number of state automaton. */
+static hashval_t
+state_hash (state)
+ const void *state;
+{
+ unsigned int hash_value;
+ alt_state_t alt_state;
+
+ if (((state_t) state)->component_states == NULL)
+ hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
+ else
+ {
+ hash_value = 0;
+ for (alt_state = ((state_t) state)->component_states;
+ alt_state != NULL;
+ alt_state = alt_state->next_sorted_alt_state)
+ hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
+ | (hash_value << CHAR_BIT))
+ + alt_state->state->unique_num);
+ }
+ hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
+ | (hash_value << CHAR_BIT))
+ + ((state_t) state)->automaton->automaton_order_num);
+ return hash_value;
+}
+
+/* Return nonzero value if the states are the same. */
+static int
+state_eq_p (state_1, state_2)
+ const void *state_1;
+ const void *state_2;
+{
+ alt_state_t alt_state_1;
+ alt_state_t alt_state_2;
+
+ if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
+ return 0;
+ else if (((state_t) state_1)->component_states == NULL
+ && ((state_t) state_2)->component_states == NULL)
+ return reserv_sets_eq (((state_t) state_1)->reservs,
+ ((state_t) state_2)->reservs);
+ else if (((state_t) state_1)->component_states != NULL
+ && ((state_t) state_2)->component_states != NULL)
+ {
+ for (alt_state_1 = ((state_t) state_1)->component_states,
+ alt_state_2 = ((state_t) state_2)->component_states;
+ alt_state_1 != NULL && alt_state_2 != NULL;
+ alt_state_1 = alt_state_1->next_sorted_alt_state,
+ alt_state_2 = alt_state_2->next_sorted_alt_state)
+ /* All state in the list must be already in the hash table.
+ Also the lists must be sorted. */
+ if (alt_state_1->state != alt_state_2->state)
+ return 0;
+ return alt_state_1 == alt_state_2;
+ }
+ else
+ return 0;
+}
+
+/* Insert STATE into the state table. */
+static state_t
+insert_state (state)
+ state_t state;
+{
+ void **entry_ptr;
+
+ entry_ptr = htab_find_slot (state_table, (void *) state, 1);
+ if (*entry_ptr == NULL)
+ *entry_ptr = (void *) state;
+ return (state_t) *entry_ptr;
+}
+
+/* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
+ deterministic STATE. */
+static void
+set_state_reserv (state, cycle_num, unit_num)
+ state_t state;
+ int cycle_num;
+ int unit_num;
+{
+ set_unit_reserv (state->reservs, cycle_num, unit_num);
+}
+
+/* Return nonzero value if the deterministic states contains a
+ reservation of the same cpu unit on the same cpu cycle. */
+static int
+intersected_state_reservs_p (state1, state2)
+ state_t state1;
+ state_t state2;
+{
+ if (state1->automaton != state2->automaton)
+ abort ();
+ return reserv_sets_are_intersected (state1->reservs, state2->reservs);
+}
+
+/* Return deterministic state (inserted into the table) which
+ representing the automaton state whic is union of reservations of
+ deterministic states. */
+static state_t
+states_union (state1, state2)
+ state_t state1;
+ state_t state2;
+{
+ state_t result;
+ state_t state_in_table;
+
+ if (state1->automaton != state2->automaton)
+ abort ();
+ result = get_free_state (1, state1->automaton);
+ reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
+ state_in_table = insert_state (result);
+ if (result != state_in_table)
+ {
+ free_state (result);
+ result = state_in_table;
+ }
+ return result;
+}
+
+/* Return deterministic state (inserted into the table) which
+ represent the automaton state is obtained from deterministic STATE
+ by advancing cpu cycle. */
+static state_t
+state_shift (state)
+ state_t state;
+{
+ state_t result;
+ state_t state_in_table;
+
+ result = get_free_state (1, state->automaton);
+ reserv_sets_shift (result->reservs, state->reservs);
+ state_in_table = insert_state (result);
+ if (result != state_in_table)
+ {
+ free_state (result);
+ result = state_in_table;
+ }
+ return result;
+}
+
+/* Initialization of the abstract data. */
+static void
+initiate_states ()
+{
+ decl_t decl;
+ int i;
+
+ VLA_PTR_CREATE (units_container, description->units_num, "units_container");
+ units_array
+ = (description->decls_num && description->units_num
+ ? VLA_PTR_BEGIN (units_container) : NULL);
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_unit)
+ units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
+ }
+ max_cycles_num = description->max_insn_reserv_cycles;
+ els_in_cycle_reserv
+ = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
+ / (sizeof (set_el_t) * CHAR_BIT));
+ els_in_reservs = els_in_cycle_reserv * max_cycles_num;
+ curr_unique_state_num = 0;
+ initiate_alt_states ();
+ VLA_PTR_CREATE (free_states, 1500, "free states");
+ state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
+ empty_reserv = alloc_empty_reserv_sets ();
+}
+
+/* Finisging work with the abstract data. */
+static void
+finish_states ()
+{
+ VLA_PTR_DELETE (units_container);
+ htab_delete (state_table);
+ VLA_PTR_DELETE (free_states);
+ finish_alt_states ();
+}
+
+
+
+/* Abstract data `arcs'. */
+
+/* List of free arcs. */
+static arc_t first_free_arc;
+
+#ifndef NDEBUG
+/* The following variables is maximal number of allocated nodes
+ `arc'. */
+static int allocated_arcs_num = 0;
+#endif
+
+/* The function frees node ARC. */
+static void
+free_arc (arc)
+ arc_t arc;
+{
+ arc->next_out_arc = first_free_arc;
+ first_free_arc = arc;
+}
+
+/* The function removes and frees ARC staring from FROM_STATE. */
+static void
+remove_arc (from_state, arc)
+ state_t from_state;
+ arc_t arc;
+{
+ arc_t prev_arc;
+ arc_t curr_arc;
+
+ if (arc == NULL)
+ abort ();
+ for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
+ curr_arc != NULL;
+ prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
+ if (curr_arc == arc)
+ break;
+ if (curr_arc == NULL)
+ abort ();
+ if (prev_arc == NULL)
+ from_state->first_out_arc = arc->next_out_arc;
+ else
+ prev_arc->next_out_arc = arc->next_out_arc;
+ free_arc (arc);
+}
+
+/* The functions returns arc with given characteristics (or NULL if
+ the arc does not exist). */
+static arc_t
+find_arc (from_state, to_state, insn)
+ state_t from_state;
+ state_t to_state;
+ ainsn_t insn;
+{
+ arc_t arc;
+
+ for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
+ if (arc->to_state == to_state && arc->insn == insn)
+ return arc;
+ return NULL;
+}
+
+/* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
+ and with given STATE_ALTS. The function returns added arc (or
+ already existing arc). */
+static arc_t
+add_arc (from_state, to_state, ainsn, state_alts)
+ state_t from_state;
+ state_t to_state;
+ ainsn_t ainsn;
+ int state_alts;
+{
+ arc_t new_arc;
+
+ new_arc = find_arc (from_state, to_state, ainsn);
+ if (new_arc != NULL)
+ return new_arc;
+ if (first_free_arc == NULL)
+ {
+#ifndef NDEBUG
+ allocated_arcs_num++;
+#endif
+ new_arc = create_node (sizeof (struct arc));
+ new_arc->to_state = NULL;
+ new_arc->insn = NULL;
+ new_arc->next_out_arc = NULL;
+ }
+ else
+ {
+ new_arc = first_free_arc;
+ first_free_arc = first_free_arc->next_out_arc;
+ }
+ new_arc->to_state = to_state;
+ new_arc->insn = ainsn;
+ ainsn->arc_exists_p = 1;
+ new_arc->next_out_arc = from_state->first_out_arc;
+ from_state->first_out_arc = new_arc;
+ new_arc->next_arc_marked_by_insn = NULL;
+ new_arc->state_alts = state_alts;
+ return new_arc;
+}
+
+/* The function returns the first arc starting from STATE. */
+static arc_t
+first_out_arc (state)
+ state_t state;
+{
+ return state->first_out_arc;
+}
+
+/* The function returns next out arc after ARC. */
+static arc_t
+next_out_arc (arc)
+ arc_t arc;
+{
+ return arc->next_out_arc;
+}
+
+/* Initialization of the abstract data. */
+static void
+initiate_arcs ()
+{
+ first_free_arc = NULL;
+}
+
+/* Finishing work with the abstract data. */
+static void
+finish_arcs ()
+{
+}
+
+
+
+/* Abstract data `automata lists'. */
+
+/* List of free states. */
+static automata_list_el_t first_free_automata_list_el;
+
+/* The list being formed. */
+static automata_list_el_t current_automata_list;
+
+/* Hash table of automata lists. */
+static htab_t automata_list_table;
+
+/* The following function returns free automata list el. It may be
+ new allocated node or node freed earlier. */
+static automata_list_el_t
+get_free_automata_list_el ()
+{
+ automata_list_el_t result;
+
+ if (first_free_automata_list_el != NULL)
+ {
+ result = first_free_automata_list_el;
+ first_free_automata_list_el
+ = first_free_automata_list_el->next_automata_list_el;
+ }
+ else
+ result = create_node (sizeof (struct automata_list_el));
+ result->automaton = NULL;
+ result->next_automata_list_el = NULL;
+ return result;
+}
+
+/* The function frees node AUTOMATA_LIST_EL. */
+static void
+free_automata_list_el (automata_list_el)
+ automata_list_el_t automata_list_el;
+{
+ if (automata_list_el == NULL)
+ return;
+ automata_list_el->next_automata_list_el = first_free_automata_list_el;
+ first_free_automata_list_el = automata_list_el;
+}
+
+/* The function frees list AUTOMATA_LIST. */
+static void
+free_automata_list (automata_list)
+ automata_list_el_t automata_list;
+{
+ automata_list_el_t curr_automata_list_el;
+ automata_list_el_t next_automata_list_el;
+
+ for (curr_automata_list_el = automata_list;
+ curr_automata_list_el != NULL;
+ curr_automata_list_el = next_automata_list_el)
+ {
+ next_automata_list_el = curr_automata_list_el->next_automata_list_el;
+ free_automata_list_el (curr_automata_list_el);
+ }
+}
+
+/* Hash value of AUTOMATA_LIST. */
+static hashval_t
+automata_list_hash (automata_list)
+ const void *automata_list;
+{
+ unsigned int hash_value;
+ automata_list_el_t curr_automata_list_el;
+
+ hash_value = 0;
+ for (curr_automata_list_el = (automata_list_el_t) automata_list;
+ curr_automata_list_el != NULL;
+ curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
+ hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
+ | (hash_value << CHAR_BIT))
+ + curr_automata_list_el->automaton->automaton_order_num);
+ return hash_value;
+}
+
+/* Return nonzero value if the automata_lists are the same. */
+static int
+automata_list_eq_p (automata_list_1, automata_list_2)
+ const void *automata_list_1;
+ const void *automata_list_2;
+{
+ automata_list_el_t automata_list_el_1;
+ automata_list_el_t automata_list_el_2;
+
+ for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
+ automata_list_el_2 = (automata_list_el_t) automata_list_2;
+ automata_list_el_1 != NULL && automata_list_el_2 != NULL;
+ automata_list_el_1 = automata_list_el_1->next_automata_list_el,
+ automata_list_el_2 = automata_list_el_2->next_automata_list_el)
+ if (automata_list_el_1->automaton != automata_list_el_2->automaton)
+ return 0;
+ return automata_list_el_1 == automata_list_el_2;
+}
+
+/* Initialization of the abstract data. */
+static void
+initiate_automata_lists ()
+{
+ first_free_automata_list_el = NULL;
+ automata_list_table = htab_create (1500, automata_list_hash,
+ automata_list_eq_p, (htab_del) 0);
+}
+
+/* The following function starts new automata list and makes it the
+ current one. */
+static void
+automata_list_start ()
+{
+ current_automata_list = NULL;
+}
+
+/* The following function adds AUTOMATON to the current list. */
+static void
+automata_list_add (automaton)
+ automaton_t automaton;
+{
+ automata_list_el_t el;
+
+ el = get_free_automata_list_el ();
+ el->automaton = automaton;
+ el->next_automata_list_el = current_automata_list;
+ current_automata_list = el;
+}
+
+/* The following function finishes forming the current list, inserts
+ it into the table and returns it. */
+static automata_list_el_t
+automata_list_finish ()
+{
+ void **entry_ptr;
+
+ if (current_automata_list == NULL)
+ return NULL;
+ entry_ptr = htab_find_slot (automata_list_table,
+ (void *) current_automata_list, 1);
+ if (*entry_ptr == NULL)
+ *entry_ptr = (void *) current_automata_list;
+ else
+ free_automata_list (current_automata_list);
+ current_automata_list = NULL;
+ return (automata_list_el_t) *entry_ptr;
+}
+
+/* Finishing work with the abstract data. */
+static void
+finish_automata_lists ()
+{
+ htab_delete (automata_list_table);
+}
+
+
+
+/* The page contains abstract data for work with exclusion sets (see
+ exclusion_set in file rtl.def). */
+
+/* The following variable refers to an exclusion set returned by
+ get_excl_set. This is bit string of length equal to cpu units
+ number. If exclusion set for given unit contains 1 for a unit,
+ then simultaneous reservation of the units is prohibited. */
+static reserv_sets_t excl_set;
+
+/* The array contains exclusion sets for each unit. */
+static reserv_sets_t *unit_excl_set_table;
+
+/* The following function forms the array containing exclusion sets
+ for each unit. */
+static void
+initiate_excl_sets ()
+{
+ decl_t decl;
+ reserv_sets_t unit_excl_set;
+ unit_set_el_t el;
+ int i;
+
+ obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
+ excl_set = (reserv_sets_t) obstack_base (&irp);
+ obstack_finish (&irp);
+ obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
+ unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
+ obstack_finish (&irp);
+ /* Evaluate unit exclusion sets. */
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_unit)
+ {
+ obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
+ unit_excl_set = (reserv_sets_t) obstack_base (&irp);
+ obstack_finish (&irp);
+ memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
+ for (el = DECL_UNIT (decl)->excl_list;
+ el != NULL;
+ el = el->next_unit_set_el)
+ SET_BIT (unit_excl_set, el->unit_decl->unit_num);
+ unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
+ }
+ }
+}
+
+/* The function sets up and return EXCL_SET which is union of
+ exclusion sets for each unit in IN_SET. */
+static reserv_sets_t
+get_excl_set (in_set)
+ reserv_sets_t in_set;
+{
+ int excl_char_num;
+ int chars_num;
+ int i;
+ int start_unit_num;
+ int unit_num;
+
+ chars_num = els_in_cycle_reserv * sizeof (set_el_t);
+ memset (excl_set, 0, chars_num);
+ for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
+ if (((unsigned char *) in_set) [excl_char_num])
+ for (i = CHAR_BIT - 1; i >= 0; i--)
+ if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
+ {
+ start_unit_num = excl_char_num * CHAR_BIT + i;
+ if (start_unit_num >= description->units_num)
+ return excl_set;
+ for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
+ {
+ excl_set [unit_num]
+ |= unit_excl_set_table [start_unit_num] [unit_num];
+ }
+ }
+ return excl_set;
+}
+
+
+
+/* The page contains abstract data for work with presence/absence sets
+ (see presence_set/absence_set in file rtl.def). */
+
+/* The following variables refer to correspondingly a presence and an
+ absence set returned by get_presence_absence_set. This is bit
+ string of length equal to cpu units number. */
+static reserv_sets_t presence_set, absence_set;
+
+/* The following arrays contain correspondingly presence and absence
+ sets for each unit. */
+static reserv_sets_t *unit_presence_set_table, *unit_absence_set_table;
+
+/* The following function forms the array containing presence and
+ absence sets for each unit */
+static void
+initiate_presence_absence_sets ()
+{
+ decl_t decl;
+ reserv_sets_t unit_set;
+ unit_set_el_t el;
+ int i;
+
+ obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
+ presence_set = (reserv_sets_t) obstack_base (&irp);
+ obstack_finish (&irp);
+ obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
+ unit_presence_set_table = (reserv_sets_t *) obstack_base (&irp);
+ obstack_finish (&irp);
+ obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
+ absence_set = (reserv_sets_t) obstack_base (&irp);
+ obstack_finish (&irp);
+ obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
+ unit_absence_set_table = (reserv_sets_t *) obstack_base (&irp);
+ obstack_finish (&irp);
+ /* Evaluate unit presence/absence sets. */
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_unit)
+ {
+ obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
+ unit_set = (reserv_sets_t) obstack_base (&irp);
+ obstack_finish (&irp);
+ memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
+ for (el = DECL_UNIT (decl)->presence_list;
+ el != NULL;
+ el = el->next_unit_set_el)
+ SET_BIT (unit_set, el->unit_decl->unit_num);
+ unit_presence_set_table [DECL_UNIT (decl)->unit_num] = unit_set;
+
+ obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
+ unit_set = (reserv_sets_t) obstack_base (&irp);
+ obstack_finish (&irp);
+ memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
+ for (el = DECL_UNIT (decl)->absence_list;
+ el != NULL;
+ el = el->next_unit_set_el)
+ SET_BIT (unit_set, el->unit_decl->unit_num);
+ unit_absence_set_table [DECL_UNIT (decl)->unit_num] = unit_set;
+ }
+ }
+}
+
+/* The function sets up and return PRESENCE_SET (if PRESENCE_P) or
+ ABSENCE_SET which is union of corresponding sets for each unit in
+ IN_SET. */
+static reserv_sets_t
+get_presence_absence_set (in_set, presence_p)
+ reserv_sets_t in_set;
+ int presence_p;
+{
+ int char_num;
+ int chars_num;
+ int i;
+ int start_unit_num;
+ int unit_num;
+
+ chars_num = els_in_cycle_reserv * sizeof (set_el_t);
+ if (presence_p)
+ memset (presence_set, 0, chars_num);
+ else
+ memset (absence_set, 0, chars_num);
+ for (char_num = 0; char_num < chars_num; char_num++)
+ if (((unsigned char *) in_set) [char_num])
+ for (i = CHAR_BIT - 1; i >= 0; i--)
+ if ((((unsigned char *) in_set) [char_num] >> i) & 1)
+ {
+ start_unit_num = char_num * CHAR_BIT + i;
+ if (start_unit_num >= description->units_num)
+ return (presence_p ? presence_set : absence_set);
+ for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
+ if (presence_p)
+ presence_set [unit_num]
+ |= unit_presence_set_table [start_unit_num] [unit_num];
+ else
+ absence_set [unit_num]
+ |= unit_absence_set_table [start_unit_num] [unit_num];
+ }
+ return (presence_p ? presence_set : absence_set);
+}
+
+
+
+/* This page contains code for transformation of original reservations
+ described in .md file. The main goal of transformations is
+ simplifying reservation and lifting up all `|' on the top of IR
+ reservation representation. */
+
+
+/* The following function makes copy of IR representation of
+ reservation. The function also substitutes all reservations
+ defined by define_reservation by corresponding value during making
+ the copy. */
+static regexp_t
+copy_insn_regexp (regexp)
+ regexp_t regexp;
+{
+ regexp_t result;
+ int i;
+
+ if (regexp->mode == rm_reserv)
+ result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
+ else if (regexp->mode == rm_unit)
+ result = copy_node (regexp, sizeof (struct regexp));
+ else if (regexp->mode == rm_repeat)
+ {
+ result = copy_node (regexp, sizeof (struct regexp));
+ REGEXP_REPEAT (result)->regexp
+ = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
+ }
+ else if (regexp->mode == rm_sequence)
+ {
+ result = copy_node (regexp,
+ sizeof (struct regexp) + sizeof (regexp_t)
+ * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
+ for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
+ REGEXP_SEQUENCE (result)->regexps [i]
+ = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
+ }
+ else if (regexp->mode == rm_allof)
+ {
+ result = copy_node (regexp,
+ sizeof (struct regexp) + sizeof (regexp_t)
+ * (REGEXP_ALLOF (regexp)->regexps_num - 1));
+ for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
+ REGEXP_ALLOF (result)->regexps [i]
+ = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
+ }
+ else if (regexp->mode == rm_oneof)
+ {
+ result = copy_node (regexp,
+ sizeof (struct regexp) + sizeof (regexp_t)
+ * (REGEXP_ONEOF (regexp)->regexps_num - 1));
+ for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
+ REGEXP_ONEOF (result)->regexps [i]
+ = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
+ }
+ else
+ {
+ if (regexp->mode != rm_nothing)
+ abort ();
+ result = copy_node (regexp, sizeof (struct regexp));
+ }
+ return result;
+}
+
+/* The following variable is set up 1 if a transformation has been
+ applied. */
+static int regexp_transformed_p;
+
+/* The function makes transformation
+ A*N -> A, A, ... */
+static regexp_t
+transform_1 (regexp)
+ regexp_t regexp;
+{
+ int i;
+ int repeat_num;
+ regexp_t operand;
+ pos_t pos;
+
+ if (regexp->mode == rm_repeat)
+ {
+ repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
+ if (repeat_num <= 1)
+ abort ();
+ operand = REGEXP_REPEAT (regexp)->regexp;
+ pos = regexp->mode;
+ regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
+ * (repeat_num - 1));
+ regexp->mode = rm_sequence;
+ regexp->pos = pos;
+ REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
+ for (i = 0; i < repeat_num; i++)
+ REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
+ regexp_transformed_p = 1;
+ }
+ return regexp;
+}
+
+/* The function makes transformations
+ ...,(A,B,...),C,... -> ...,A,B,...,C,...
+ ...+(A+B+...)+C+... -> ...+A+B+...+C+...
+ ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
+static regexp_t
+transform_2 (regexp)
+ regexp_t regexp;
+{
+ if (regexp->mode == rm_sequence)
+ {
+ regexp_t sequence = NULL;
+ regexp_t result;
+ int sequence_index = 0;
+ int i, j;
+
+ for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
+ if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
+ {
+ sequence_index = i;
+ sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
+ break;
+ }
+ if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
+ {
+ if ( REGEXP_SEQUENCE (sequence)->regexps_num <= 1
+ || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
+ abort ();
+ result = create_node (sizeof (struct regexp)
+ + sizeof (regexp_t)
+ * (REGEXP_SEQUENCE (regexp)->regexps_num
+ + REGEXP_SEQUENCE (sequence)->regexps_num
+ - 2));
+ result->mode = rm_sequence;
+ result->pos = regexp->pos;
+ REGEXP_SEQUENCE (result)->regexps_num
+ = (REGEXP_SEQUENCE (regexp)->regexps_num
+ + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
+ for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
+ if (i < sequence_index)
+ REGEXP_SEQUENCE (result)->regexps [i]
+ = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
+ else if (i > sequence_index)
+ REGEXP_SEQUENCE (result)->regexps
+ [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
+ = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
+ else
+ for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
+ REGEXP_SEQUENCE (result)->regexps [i + j]
+ = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
+ regexp_transformed_p = 1;
+ regexp = result;
+ }
+ }
+ else if (regexp->mode == rm_allof)
+ {
+ regexp_t allof = NULL;
+ regexp_t result;
+ int allof_index = 0;
+ int i, j;
+
+ for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
+ if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
+ {
+ allof_index = i;
+ allof = REGEXP_ALLOF (regexp)->regexps [i];
+ break;
+ }
+ if (i < REGEXP_ALLOF (regexp)->regexps_num)
+ {
+ if (REGEXP_ALLOF (allof)->regexps_num <= 1
+ || REGEXP_ALLOF (regexp)->regexps_num <= 1)
+ abort ();
+ result = create_node (sizeof (struct regexp)
+ + sizeof (regexp_t)
+ * (REGEXP_ALLOF (regexp)->regexps_num
+ + REGEXP_ALLOF (allof)->regexps_num - 2));
+ result->mode = rm_allof;
+ result->pos = regexp->pos;
+ REGEXP_ALLOF (result)->regexps_num
+ = (REGEXP_ALLOF (regexp)->regexps_num
+ + REGEXP_ALLOF (allof)->regexps_num - 1);
+ for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
+ if (i < allof_index)
+ REGEXP_ALLOF (result)->regexps [i]
+ = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
+ else if (i > allof_index)
+ REGEXP_ALLOF (result)->regexps
+ [i + REGEXP_ALLOF (allof)->regexps_num - 1]
+ = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
+ else
+ for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
+ REGEXP_ALLOF (result)->regexps [i + j]
+ = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
+ regexp_transformed_p = 1;
+ regexp = result;
+ }
+ }
+ else if (regexp->mode == rm_oneof)
+ {
+ regexp_t oneof = NULL;
+ regexp_t result;
+ int oneof_index = 0;
+ int i, j;
+
+ for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
+ if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
+ {
+ oneof_index = i;
+ oneof = REGEXP_ONEOF (regexp)->regexps [i];
+ break;
+ }
+ if (i < REGEXP_ONEOF (regexp)->regexps_num)
+ {
+ if (REGEXP_ONEOF (oneof)->regexps_num <= 1
+ || REGEXP_ONEOF (regexp)->regexps_num <= 1)
+ abort ();
+ result = create_node (sizeof (struct regexp)
+ + sizeof (regexp_t)
+ * (REGEXP_ONEOF (regexp)->regexps_num
+ + REGEXP_ONEOF (oneof)->regexps_num - 2));
+ result->mode = rm_oneof;
+ result->pos = regexp->pos;
+ REGEXP_ONEOF (result)->regexps_num
+ = (REGEXP_ONEOF (regexp)->regexps_num
+ + REGEXP_ONEOF (oneof)->regexps_num - 1);
+ for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
+ if (i < oneof_index)
+ REGEXP_ONEOF (result)->regexps [i]
+ = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
+ else if (i > oneof_index)
+ REGEXP_ONEOF (result)->regexps
+ [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
+ = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
+ else
+ for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
+ REGEXP_ONEOF (result)->regexps [i + j]
+ = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
+ regexp_transformed_p = 1;
+ regexp = result;
+ }
+ }
+ return regexp;
+}
+
+/* The function makes transformations
+ ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
+ ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
+ ...+(A,B,...)+C+... -> (...+A+C+...),B,...
+ ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
+static regexp_t
+transform_3 (regexp)
+ regexp_t regexp;
+{
+ if (regexp->mode == rm_sequence)
+ {
+ regexp_t oneof = NULL;
+ int oneof_index = 0;
+ regexp_t result;
+ regexp_t sequence;
+ int i, j;
+
+ for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
+ if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
+ {
+ oneof_index = i;
+ oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
+ break;
+ }
+ if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
+ {
+ if (REGEXP_ONEOF (oneof)->regexps_num <= 1
+ || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
+ abort ();
+ result = create_node (sizeof (struct regexp)
+ + sizeof (regexp_t)
+ * (REGEXP_ONEOF (oneof)->regexps_num - 1));
+ result->mode = rm_oneof;
+ result->pos = regexp->pos;
+ REGEXP_ONEOF (result)->regexps_num
+ = REGEXP_ONEOF (oneof)->regexps_num;
+ for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
+ {
+ sequence
+ = create_node (sizeof (struct regexp)
+ + sizeof (regexp_t)
+ * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
+ sequence->mode = rm_sequence;
+ sequence->pos = regexp->pos;
+ REGEXP_SEQUENCE (sequence)->regexps_num
+ = REGEXP_SEQUENCE (regexp)->regexps_num;
+ REGEXP_ONEOF (result)->regexps [i] = sequence;
+ for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
+ if (j != oneof_index)
+ REGEXP_SEQUENCE (sequence)->regexps [j]
+ = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
+ else
+ REGEXP_SEQUENCE (sequence)->regexps [j]
+ = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
+ }
+ regexp_transformed_p = 1;
+ regexp = result;
+ }
+ }
+ else if (regexp->mode == rm_allof)
+ {
+ regexp_t oneof = NULL, seq;
+ int oneof_index = 0, max_seq_length, allof_length;
+ regexp_t result;
+ regexp_t allof = NULL, allof_op = NULL;
+ int i, j;
+
+ for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
+ if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
+ {
+ oneof_index = i;
+ oneof = REGEXP_ALLOF (regexp)->regexps [i];
+ break;
+ }
+ if (i < REGEXP_ALLOF (regexp)->regexps_num)
+ {
+ if (REGEXP_ONEOF (oneof)->regexps_num <= 1
+ || REGEXP_ALLOF (regexp)->regexps_num <= 1)
+ abort ();
+ result = create_node (sizeof (struct regexp)
+ + sizeof (regexp_t)
+ * (REGEXP_ONEOF (oneof)->regexps_num - 1));
+ result->mode = rm_oneof;
+ result->pos = regexp->pos;
+ REGEXP_ONEOF (result)->regexps_num
+ = REGEXP_ONEOF (oneof)->regexps_num;
+ for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
+ {
+ allof
+ = create_node (sizeof (struct regexp)
+ + sizeof (regexp_t)
+ * (REGEXP_ALLOF (regexp)->regexps_num - 1));
+ allof->mode = rm_allof;
+ allof->pos = regexp->pos;
+ REGEXP_ALLOF (allof)->regexps_num
+ = REGEXP_ALLOF (regexp)->regexps_num;
+ REGEXP_ONEOF (result)->regexps [i] = allof;
+ for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
+ if (j != oneof_index)
+ REGEXP_ALLOF (allof)->regexps [j]
+ = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
+ else
+ REGEXP_ALLOF (allof)->regexps [j]
+ = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
+ }
+ regexp_transformed_p = 1;
+ regexp = result;
+ }
+ max_seq_length = 0;
+ if (regexp->mode == rm_allof)
+ for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
+ {
+ if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_sequence)
+ {
+ seq = REGEXP_ALLOF (regexp)->regexps [i];
+ if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
+ max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
+ }
+ else if (REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_unit)
+ {
+ max_seq_length = 0;
+ break;
+ }
+ }
+ if (max_seq_length != 0)
+ {
+ if (max_seq_length == 1 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
+ abort ();
+ result = create_node (sizeof (struct regexp)
+ + sizeof (regexp_t) * (max_seq_length - 1));
+ result->mode = rm_sequence;
+ result->pos = regexp->pos;
+ REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
+ for (i = 0; i < max_seq_length; i++)
+ {
+ allof_length = 0;
+ for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
+ if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
+ && (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
+ ->regexps [j])->regexps_num)))
+ {
+ allof_op
+ = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)->regexps [j])
+ ->regexps [i]);
+ allof_length++;
+ }
+ else if (i == 0
+ && (REGEXP_ALLOF (regexp)->regexps [j]->mode
+ == rm_unit))
+ {
+ allof_op = REGEXP_ALLOF (regexp)->regexps [j];
+ allof_length++;
+ }
+ if (allof_length == 1)
+ REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
+ else
+ {
+ allof = create_node (sizeof (struct regexp)
+ + sizeof (regexp_t)
+ * (allof_length - 1));
+ allof->mode = rm_allof;
+ allof->pos = regexp->pos;
+ REGEXP_ALLOF (allof)->regexps_num = allof_length;
+ REGEXP_SEQUENCE (result)->regexps [i] = allof;
+ allof_length = 0;
+ for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
+ if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
+ && (i <
+ (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
+ ->regexps [j])->regexps_num)))
+ {
+ allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
+ ->regexps [j])
+ ->regexps [i]);
+ REGEXP_ALLOF (allof)->regexps [allof_length]
+ = allof_op;
+ allof_length++;
+ }
+ else if (i == 0
+ && (REGEXP_ALLOF (regexp)->regexps [j]->mode
+ == rm_unit))
+ {
+ allof_op = REGEXP_ALLOF (regexp)->regexps [j];
+ REGEXP_ALLOF (allof)->regexps [allof_length]
+ = allof_op;
+ allof_length++;
+ }
+ }
+ }
+ regexp_transformed_p = 1;
+ regexp = result;
+ }
+ }
+ return regexp;
+}
+
+/* The function traverses IR of reservation and applies transformations
+ implemented by FUNC. */
+static regexp_t
+regexp_transform_func (regexp, func)
+ regexp_t regexp;
+ regexp_t (*func) PARAMS ((regexp_t regexp));
+{
+ int i;
+
+ if (regexp->mode == rm_sequence)
+ for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
+ REGEXP_SEQUENCE (regexp)->regexps [i]
+ = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i], func);
+ else if (regexp->mode == rm_allof)
+ for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
+ REGEXP_ALLOF (regexp)->regexps [i]
+ = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
+ else if (regexp->mode == rm_oneof)
+ for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
+ REGEXP_ONEOF (regexp)->regexps [i]
+ = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
+ else if (regexp->mode == rm_repeat)
+ REGEXP_REPEAT (regexp)->regexp
+ = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
+ else if (regexp->mode != rm_nothing && regexp->mode != rm_unit)
+ abort ();
+ return (*func) (regexp);
+}
+
+/* The function applies all transformations for IR representation of
+ reservation REGEXP. */
+static regexp_t
+transform_regexp (regexp)
+ regexp_t regexp;
+{
+ regexp = regexp_transform_func (regexp, transform_1);
+ do
+ {
+ regexp_transformed_p = 0;
+ regexp = regexp_transform_func (regexp, transform_2);
+ regexp = regexp_transform_func (regexp, transform_3);
+ }
+ while (regexp_transformed_p);
+ return regexp;
+}
+
+/* The function applys all transformations for reservations of all
+ insn declarations. */
+static void
+transform_insn_regexps ()
+{
+ decl_t decl;
+ int i;
+
+ transform_time = create_ticker ();
+ add_advance_cycle_insn_decl ();
+ fprintf (stderr, "Reservation transformation...");
+ fflush (stderr);
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
+ DECL_INSN_RESERV (decl)->transformed_regexp
+ = transform_regexp (copy_insn_regexp
+ (DECL_INSN_RESERV (decl)->regexp));
+ }
+ fprintf (stderr, "done\n");
+ ticker_off (&transform_time);
+ fflush (stderr);
+}
+
+
+
+/* The following variable is an array indexed by cycle. Each element
+ contains cyclic list of units which should be in the same cycle. */
+static unit_decl_t *the_same_automaton_lists;
+
+/* The function processes all alternative reservations on CYCLE in
+ given REGEXP to check the UNIT is not reserved on the all
+ alternatives. If it is true, the unit should be in the same
+ automaton with other analogous units reserved on CYCLE in given
+ REGEXP. */
+static void
+process_unit_to_form_the_same_automaton_unit_lists (unit, regexp, cycle)
+ regexp_t unit;
+ regexp_t regexp;
+ int cycle;
+{
+ int i, k;
+ regexp_t seq, allof;
+ unit_decl_t unit_decl, last;
+
+ if (regexp == NULL || regexp->mode != rm_oneof)
+ abort ();
+ unit_decl = REGEXP_UNIT (unit)->unit_decl;
+ for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
+ {
+ seq = REGEXP_ONEOF (regexp)->regexps [i];
+ if (seq->mode == rm_sequence)
+ {
+ if (cycle >= REGEXP_SEQUENCE (seq)->regexps_num)
+ break;
+ allof = REGEXP_SEQUENCE (seq)->regexps [cycle];
+ if (allof->mode == rm_allof)
+ {
+ for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
+ if (REGEXP_ALLOF (allof)->regexps [k]->mode == rm_unit
+ && (REGEXP_UNIT (REGEXP_ALLOF (allof)->regexps [k])
+ ->unit_decl == unit_decl))
+ break;
+ if (k >= REGEXP_ALLOF (allof)->regexps_num)
+ break;
+ }
+ else if (allof->mode == rm_unit
+ && REGEXP_UNIT (allof)->unit_decl != unit_decl)
+ break;
+ }
+ else if (cycle != 0)
+ break;
+ else if (seq->mode == rm_allof)
+ {
+ for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
+ if (REGEXP_ALLOF (seq)->regexps [k]->mode == rm_unit
+ && (REGEXP_UNIT (REGEXP_ALLOF (seq)->regexps [k])->unit_decl
+ == unit_decl))
+ break;
+ if (k >= REGEXP_ALLOF (seq)->regexps_num)
+ break;
+ }
+ else if (seq->mode == rm_unit
+ && REGEXP_UNIT (seq)->unit_decl != unit_decl)
+ break;
+ }
+ if (i >= 0)
+ {
+ if (the_same_automaton_lists [cycle] == NULL)
+ the_same_automaton_lists [cycle] = unit_decl;
+ else
+ {
+ for (last = the_same_automaton_lists [cycle];;)
+ {
+ if (last == unit_decl)
+ return;
+ if (last->the_same_automaton_unit
+ == the_same_automaton_lists [cycle])
+ break;
+ last = last->the_same_automaton_unit;
+ }
+ last->the_same_automaton_unit = unit_decl->the_same_automaton_unit;
+ unit_decl->the_same_automaton_unit
+ = the_same_automaton_lists [cycle];
+ }
+ }
+}
+
+/* The function processes given REGEXP to find units which should be
+ in the same automaton. */
+static void
+form_the_same_automaton_unit_lists_from_regexp (regexp)
+ regexp_t regexp;
+{
+ int i, j, k;
+ regexp_t seq, allof, unit;
+
+ if (regexp == NULL || regexp->mode != rm_oneof)
+ return;
+ for (i = 0; i < description->max_insn_reserv_cycles; i++)
+ the_same_automaton_lists [i] = NULL;
+ for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
+ {
+ seq = REGEXP_ONEOF (regexp)->regexps [i];
+ if (seq->mode == rm_sequence)
+ for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
+ {
+ allof = REGEXP_SEQUENCE (seq)->regexps [j];
+ if (allof->mode == rm_allof)
+ for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
+ {
+ unit = REGEXP_ALLOF (allof)->regexps [k];
+ if (unit->mode == rm_unit)
+ process_unit_to_form_the_same_automaton_unit_lists
+ (unit, regexp, j);
+ else if (unit->mode != rm_nothing)
+ abort ();
+ }
+ else if (allof->mode == rm_unit)
+ process_unit_to_form_the_same_automaton_unit_lists
+ (allof, regexp, j);
+ else if (allof->mode != rm_nothing)
+ abort ();
+ }
+ else if (seq->mode == rm_allof)
+ for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
+ {
+ unit = REGEXP_ALLOF (seq)->regexps [k];
+ if (unit->mode == rm_unit)
+ process_unit_to_form_the_same_automaton_unit_lists
+ (unit, regexp, 0);
+ else if (unit->mode != rm_nothing)
+ abort ();
+ }
+ else if (seq->mode == rm_unit)
+ process_unit_to_form_the_same_automaton_unit_lists (seq, regexp, 0);
+ else if (seq->mode != rm_nothing)
+ abort ();
+ }
+}
+
+/* The function initializes data to search for units which should be
+ in the same automaton and call function
+ `form_the_same_automaton_unit_lists_from_regexp' for each insn
+ reservation regexp. */
+static void
+form_the_same_automaton_unit_lists ()
+{
+ decl_t decl;
+ int i;
+
+ the_same_automaton_lists
+ = (unit_decl_t *) xmalloc (description->max_insn_reserv_cycles
+ * sizeof (unit_decl_t));
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_unit)
+ {
+ DECL_UNIT (decl)->the_same_automaton_message_reported_p = FALSE;
+ DECL_UNIT (decl)->the_same_automaton_unit = DECL_UNIT (decl);
+ }
+ }
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv)
+ form_the_same_automaton_unit_lists_from_regexp
+ (DECL_INSN_RESERV (decl)->transformed_regexp);
+ }
+ free (the_same_automaton_lists);
+}
+
+/* The function finds units which should be in the same automaton and,
+ if they are not, reports about it. */
+static void
+check_unit_distributions_to_automata ()
+{
+ decl_t decl;
+ unit_decl_t start_unit_decl, unit_decl;
+ int i;
+
+ form_the_same_automaton_unit_lists ();
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_unit)
+ {
+ start_unit_decl = DECL_UNIT (decl);
+ if (!start_unit_decl->the_same_automaton_message_reported_p)
+ for (unit_decl = start_unit_decl->the_same_automaton_unit;
+ unit_decl != start_unit_decl;
+ unit_decl = unit_decl->the_same_automaton_unit)
+ if (start_unit_decl->automaton_decl != unit_decl->automaton_decl)
+ {
+ error ("Units `%s' and `%s' should be in the same automaton",
+ start_unit_decl->name, unit_decl->name);
+ unit_decl->the_same_automaton_message_reported_p = TRUE;
+ }
+ }
+ }
+}
+
+
+
+/* The page contains code for building alt_states (see comments for
+ IR) describing all possible insns reservations of an automaton. */
+
+/* Current state being formed for which the current alt_state
+ refers. */
+static state_t state_being_formed;
+
+/* Current alt_state being formed. */
+static alt_state_t alt_state_being_formed;
+
+/* This recursive function processes `,' and units in reservation
+ REGEXP for forming alt_states of AUTOMATON. It is believed that
+ CURR_CYCLE is start cycle of all reservation REGEXP. */
+static int
+process_seq_for_forming_states (regexp, automaton, curr_cycle)
+ regexp_t regexp;
+ automaton_t automaton;
+ int curr_cycle;
+{
+ int i;
+
+ if (regexp == NULL)
+ return curr_cycle;
+ else if (regexp->mode == rm_unit)
+ {
+ if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
+ == automaton->automaton_order_num)
+ set_state_reserv (state_being_formed, curr_cycle,
+ REGEXP_UNIT (regexp)->unit_decl->unit_num);
+ return curr_cycle;
+ }
+ else if (regexp->mode == rm_sequence)
+ {
+ for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
+ curr_cycle
+ = process_seq_for_forming_states
+ (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
+ return curr_cycle;
+ }
+ else if (regexp->mode == rm_allof)
+ {
+ int finish_cycle = 0;
+ int cycle;
+
+ for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
+ {
+ cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
+ ->regexps [i],
+ automaton, curr_cycle);
+ if (finish_cycle < cycle)
+ finish_cycle = cycle;
+ }
+ return finish_cycle;
+ }
+ else
+ {
+ if (regexp->mode != rm_nothing)
+ abort ();
+ return curr_cycle;
+ }
+}
+
+/* This recursive function finishes forming ALT_STATE of AUTOMATON and
+ inserts alt_state into the table. */
+static void
+finish_forming_alt_state (alt_state, automaton)
+ alt_state_t alt_state;
+ automaton_t automaton ATTRIBUTE_UNUSED;
+{
+ state_t state_in_table;
+ state_t corresponding_state;
+
+ corresponding_state = alt_state->state;
+ state_in_table = insert_state (corresponding_state);
+ if (state_in_table != corresponding_state)
+ {
+ free_state (corresponding_state);
+ alt_state->state = state_in_table;
+ }
+}
+
+/* The following variable value is current automaton insn for whose
+ reservation the alt states are created. */
+static ainsn_t curr_ainsn;
+
+/* This recursive function processes `|' in reservation REGEXP for
+ forming alt_states of AUTOMATON. List of the alt states should
+ have the same order as in the description. */
+static void
+process_alts_for_forming_states (regexp, automaton, inside_oneof_p)
+ regexp_t regexp;
+ automaton_t automaton;
+ int inside_oneof_p;
+{
+ int i;
+
+ if (regexp->mode != rm_oneof)
+ {
+ alt_state_being_formed = get_free_alt_state ();
+ state_being_formed = get_free_state (1, automaton);
+ alt_state_being_formed->state = state_being_formed;
+ /* We inserts in reverse order but we process alternatives also
+ in reverse order. So we have the same order of alternative
+ as in the description. */
+ alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
+ curr_ainsn->alt_states = alt_state_being_formed;
+ (void) process_seq_for_forming_states (regexp, automaton, 0);
+ finish_forming_alt_state (alt_state_being_formed, automaton);
+ }
+ else
+ {
+ if (inside_oneof_p)
+ abort ();
+ /* We processes it in reverse order to get list with the same
+ order as in the description. See also the previous
+ commentary. */
+ for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
+ process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
+ automaton, 1);
+ }
+}
+
+/* Create nodes alt_state for all AUTOMATON insns. */
+static void
+create_alt_states (automaton)
+ automaton_t automaton;
+{
+ struct insn_reserv_decl *reserv_decl;
+
+ for (curr_ainsn = automaton->ainsn_list;
+ curr_ainsn != NULL;
+ curr_ainsn = curr_ainsn->next_ainsn)
+ {
+ reserv_decl = curr_ainsn->insn_reserv_decl;
+ if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
+ {
+ curr_ainsn->alt_states = NULL;
+ process_alts_for_forming_states (reserv_decl->transformed_regexp,
+ automaton, 0);
+ curr_ainsn->sorted_alt_states
+ = uniq_sort_alt_states (curr_ainsn->alt_states);
+ }
+ }
+}
+
+
+
+/* The page contains major code for building DFA(s) for fast pipeline
+ hazards recognition. */
+
+/* The function forms list of ainsns of AUTOMATON with the same
+ reservation. */
+static void
+form_ainsn_with_same_reservs (automaton)
+ automaton_t automaton;
+{
+ ainsn_t curr_ainsn;
+ size_t i;
+ vla_ptr_t first_insns;
+ vla_ptr_t last_insns;
+
+ VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");
+ VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");
+ for (curr_ainsn = automaton->ainsn_list;
+ curr_ainsn != NULL;
+ curr_ainsn = curr_ainsn->next_ainsn)
+ if (curr_ainsn->insn_reserv_decl
+ == DECL_INSN_RESERV (advance_cycle_insn_decl))
+ {
+ curr_ainsn->next_same_reservs_insn = NULL;
+ curr_ainsn->first_insn_with_same_reservs = 1;
+ }
+ else
+ {
+ for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)
+ if (alt_states_eq
+ (curr_ainsn->sorted_alt_states,
+ ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))
+ break;
+ curr_ainsn->next_same_reservs_insn = NULL;
+ if (i < VLA_PTR_LENGTH (first_insns))
+ {
+ curr_ainsn->first_insn_with_same_reservs = 0;
+ ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn
+ = curr_ainsn;
+ VLA_PTR (last_insns, i) = curr_ainsn;
+ }
+ else
+ {
+ VLA_PTR_ADD (first_insns, curr_ainsn);
+ VLA_PTR_ADD (last_insns, curr_ainsn);
+ curr_ainsn->first_insn_with_same_reservs = 1;
+ }
+ }
+ VLA_PTR_DELETE (first_insns);
+ VLA_PTR_DELETE (last_insns);
+}
+
+/* The following function creates all states of nondeterministic (if
+ NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
+static void
+make_automaton (automaton)
+ automaton_t automaton;
+{
+ ainsn_t ainsn;
+ struct insn_reserv_decl *insn_reserv_decl;
+ alt_state_t alt_state;
+ state_t state;
+ state_t start_state;
+ state_t state2;
+ ainsn_t advance_cycle_ainsn;
+ arc_t added_arc;
+ vla_ptr_t state_stack;
+
+ VLA_PTR_CREATE (state_stack, 150, "state stack");
+ /* Create the start state (empty state). */
+ start_state = insert_state (get_free_state (1, automaton));
+ automaton->start_state = start_state;
+ start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
+ VLA_PTR_ADD (state_stack, start_state);
+ while (VLA_PTR_LENGTH (state_stack) != 0)
+ {
+ state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
+ VLA_PTR_SHORTEN (state_stack, 1);
+ advance_cycle_ainsn = NULL;
+ for (ainsn = automaton->ainsn_list;
+ ainsn != NULL;
+ ainsn = ainsn->next_ainsn)
+ if (ainsn->first_insn_with_same_reservs)
+ {
+ insn_reserv_decl = ainsn->insn_reserv_decl;
+ if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
+ {
+ /* We process alt_states in the same order as they are
+ present in the description. */
+ added_arc = NULL;
+ for (alt_state = ainsn->alt_states;
+ alt_state != NULL;
+ alt_state = alt_state->next_alt_state)
+ {
+ state2 = alt_state->state;
+ if (!intersected_state_reservs_p (state, state2))
+ {
+ state2 = states_union (state, state2);
+ if (!state2->it_was_placed_in_stack_for_NDFA_forming)
+ {
+ state2->it_was_placed_in_stack_for_NDFA_forming
+ = 1;
+ VLA_PTR_ADD (state_stack, state2);
+ }
+ added_arc = add_arc (state, state2, ainsn, 1);
+ if (!ndfa_flag)
+ break;
+ }
+ }
+ if (!ndfa_flag && added_arc != NULL)
+ {
+ added_arc->state_alts = 0;
+ for (alt_state = ainsn->alt_states;
+ alt_state != NULL;
+ alt_state = alt_state->next_alt_state)
+ {
+ state2 = alt_state->state;
+ if (!intersected_state_reservs_p (state, state2))
+ added_arc->state_alts++;
+ }
+ }
+ }
+ else
+ advance_cycle_ainsn = ainsn;
+ }
+ /* Add transition to advance cycle. */
+ state2 = state_shift (state);
+ if (!state2->it_was_placed_in_stack_for_NDFA_forming)
+ {
+ state2->it_was_placed_in_stack_for_NDFA_forming = 1;
+ VLA_PTR_ADD (state_stack, state2);
+ }
+ if (advance_cycle_ainsn == NULL)
+ abort ();
+ add_arc (state, state2, advance_cycle_ainsn, 1);
+ }
+ VLA_PTR_DELETE (state_stack);
+}
+
+/* Foms lists of all arcs of STATE marked by the same ainsn. */
+static void
+form_arcs_marked_by_insn (state)
+ state_t state;
+{
+ decl_t decl;
+ arc_t arc;
+ int i;
+
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv)
+ DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
+ }
+ for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
+ {
+ if (arc->insn == NULL)
+ abort ();
+ arc->next_arc_marked_by_insn
+ = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
+ arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
+ }
+}
+
+/* The function creates composed state (see comments for IR) from
+ ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
+ same insn. If the composed state is not in STATE_STACK yet, it is
+ popped to STATE_STACK. */
+static void
+create_composed_state (original_state, arcs_marked_by_insn, state_stack)
+ state_t original_state;
+ arc_t arcs_marked_by_insn;
+ vla_ptr_t *state_stack;
+{
+ state_t state;
+ alt_state_t curr_alt_state;
+ alt_state_t new_alt_state;
+ arc_t curr_arc;
+ arc_t next_arc;
+ state_t state_in_table;
+ state_t temp_state;
+ alt_state_t canonical_alt_states_list;
+ int alts_number;
+
+ if (arcs_marked_by_insn == NULL)
+ return;
+ if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
+ state = arcs_marked_by_insn->to_state;
+ else
+ {
+ if (!ndfa_flag)
+ abort ();
+ /* Create composed state. */
+ state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
+ curr_alt_state = NULL;
+ for (curr_arc = arcs_marked_by_insn;
+ curr_arc != NULL;
+ curr_arc = curr_arc->next_arc_marked_by_insn)
+ {
+ new_alt_state = get_free_alt_state ();
+ new_alt_state->next_alt_state = curr_alt_state;
+ new_alt_state->state = curr_arc->to_state;
+ if (curr_arc->to_state->component_states != NULL)
+ abort ();
+ curr_alt_state = new_alt_state;
+ }
+ /* There are not identical sets in the alt state list. */
+ canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
+ if (canonical_alt_states_list->next_sorted_alt_state == NULL)
+ {
+ temp_state = state;
+ state = canonical_alt_states_list->state;
+ free_state (temp_state);
+ }
+ else
+ {
+ state->component_states = canonical_alt_states_list;
+ state_in_table = insert_state (state);
+ if (state_in_table != state)
+ {
+ if (!state_in_table->it_was_placed_in_stack_for_DFA_forming)
+ abort ();
+ free_state (state);
+ state = state_in_table;
+ }
+ else
+ {
+ if (state->it_was_placed_in_stack_for_DFA_forming)
+ abort ();
+ for (curr_alt_state = state->component_states;
+ curr_alt_state != NULL;
+ curr_alt_state = curr_alt_state->next_sorted_alt_state)
+ for (curr_arc = first_out_arc (curr_alt_state->state);
+ curr_arc != NULL;
+ curr_arc = next_out_arc (curr_arc))
+ add_arc (state, curr_arc->to_state, curr_arc->insn, 1);
+ }
+ arcs_marked_by_insn->to_state = state;
+ for (alts_number = 0,
+ curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
+ curr_arc != NULL;
+ curr_arc = next_arc)
+ {
+ next_arc = curr_arc->next_arc_marked_by_insn;
+ remove_arc (original_state, curr_arc);
+ alts_number++;
+ }
+ arcs_marked_by_insn->state_alts = alts_number;
+ }
+ }
+ if (!state->it_was_placed_in_stack_for_DFA_forming)
+ {
+ state->it_was_placed_in_stack_for_DFA_forming = 1;
+ VLA_PTR_ADD (*state_stack, state);
+ }
+}
+
+/* The function transformes nondeterminstic AUTOMATON into
+ deterministic. */
+static void
+NDFA_to_DFA (automaton)
+ automaton_t automaton;
+{
+ state_t start_state;
+ state_t state;
+ decl_t decl;
+ vla_ptr_t state_stack;
+ int i;
+
+ VLA_PTR_CREATE (state_stack, 150, "state stack");
+ /* Create the start state (empty state). */
+ start_state = automaton->start_state;
+ start_state->it_was_placed_in_stack_for_DFA_forming = 1;
+ VLA_PTR_ADD (state_stack, start_state);
+ while (VLA_PTR_LENGTH (state_stack) != 0)
+ {
+ state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
+ VLA_PTR_SHORTEN (state_stack, 1);
+ form_arcs_marked_by_insn (state);
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv)
+ create_composed_state
+ (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
+ &state_stack);
+ }
+ }
+ VLA_PTR_DELETE (state_stack);
+}
+
+/* The following variable value is current number (1, 2, ...) of passing
+ graph of states. */
+static int curr_state_graph_pass_num;
+
+/* This recursive function passes all states achieved from START_STATE
+ and applies APPLIED_FUNC to them. */
+static void
+pass_state_graph (start_state, applied_func)
+ state_t start_state;
+ void (*applied_func) PARAMS ((state_t state));
+{
+ arc_t arc;
+
+ if (start_state->pass_num == curr_state_graph_pass_num)
+ return;
+ start_state->pass_num = curr_state_graph_pass_num;
+ (*applied_func) (start_state);
+ for (arc = first_out_arc (start_state);
+ arc != NULL;
+ arc = next_out_arc (arc))
+ pass_state_graph (arc->to_state, applied_func);
+}
+
+/* This recursive function passes all states of AUTOMATON and applies
+ APPLIED_FUNC to them. */
+static void
+pass_states (automaton, applied_func)
+ automaton_t automaton;
+ void (*applied_func) PARAMS ((state_t state));
+{
+ curr_state_graph_pass_num++;
+ pass_state_graph (automaton->start_state, applied_func);
+}
+
+/* The function initializes code for passing of all states. */
+static void
+initiate_pass_states ()
+{
+ curr_state_graph_pass_num = 0;
+}
+
+/* The following vla is used for storing pointers to all achieved
+ states. */
+static vla_ptr_t all_achieved_states;
+
+/* This function is called by function pass_states to add an achieved
+ STATE. */
+static void
+add_achieved_state (state)
+ state_t state;
+{
+ VLA_PTR_ADD (all_achieved_states, state);
+}
+
+/* The function sets up equivalence numbers of insns which mark all
+ out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
+ nonzero value) or by equiv_class_num_2 of the destination state.
+ The function returns number of out arcs of STATE. */
+static int
+set_out_arc_insns_equiv_num (state, odd_iteration_flag)
+ state_t state;
+ int odd_iteration_flag;
+{
+ int state_out_arcs_num;
+ arc_t arc;
+
+ state_out_arcs_num = 0;
+ for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
+ {
+ if (arc->insn->insn_reserv_decl->equiv_class_num != 0
+ || arc->insn->insn_reserv_decl->state_alts != 0)
+ abort ();
+ state_out_arcs_num++;
+ arc->insn->insn_reserv_decl->equiv_class_num
+ = (odd_iteration_flag
+ ? arc->to_state->equiv_class_num_1
+ : arc->to_state->equiv_class_num_2);
+ arc->insn->insn_reserv_decl->state_alts = arc->state_alts;
+ if (arc->insn->insn_reserv_decl->equiv_class_num == 0
+ || arc->insn->insn_reserv_decl->state_alts <= 0)
+ abort ();
+ }
+ return state_out_arcs_num;
+}
+
+/* The function clears equivalence numbers and alt_states in all insns
+ which mark all out arcs of STATE. */
+static void
+clear_arc_insns_equiv_num (state)
+ state_t state;
+{
+ arc_t arc;
+
+ for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
+ {
+ arc->insn->insn_reserv_decl->equiv_class_num = 0;
+ arc->insn->insn_reserv_decl->state_alts = 0;
+ }
+}
+
+/* The function copies pointers to equivalent states from vla FROM
+ into vla TO. */
+static void
+copy_equiv_class (to, from)
+ vla_ptr_t *to;
+ const vla_ptr_t *from;
+{
+ state_t *class_ptr;
+
+ VLA_PTR_NULLIFY (*to);
+ for (class_ptr = VLA_PTR_BEGIN (*from);
+ class_ptr <= (state_t *) VLA_PTR_LAST (*from);
+ class_ptr++)
+ VLA_PTR_ADD (*to, *class_ptr);
+}
+
+/* The function returns nonzero value if STATE is not equivalent to
+ another state from the same current partition on equivalence
+ classes Another state has ORIGINAL_STATE_OUT_ARCS_NUM number of
+ output arcs. Iteration of making equivalence partition is defined
+ by ODD_ITERATION_FLAG. */
+static int
+state_is_differed (state, original_state_out_arcs_num, odd_iteration_flag)
+ state_t state;
+ int original_state_out_arcs_num;
+ int odd_iteration_flag;
+{
+ arc_t arc;
+ int state_out_arcs_num;
+
+ state_out_arcs_num = 0;
+ for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
+ {
+ state_out_arcs_num++;
+ if ((odd_iteration_flag
+ ? arc->to_state->equiv_class_num_1
+ : arc->to_state->equiv_class_num_2)
+ != arc->insn->insn_reserv_decl->equiv_class_num
+ || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))
+ return 1;
+ }
+ return state_out_arcs_num != original_state_out_arcs_num;
+}
+
+/* The function makes initial partition of STATES on equivalent
+ classes. */
+static state_t
+init_equiv_class (states, states_num)
+ state_t *states;
+ int states_num;
+{
+ state_t *state_ptr;
+ state_t result_equiv_class;
+
+ result_equiv_class = NULL;
+ for (state_ptr = states; state_ptr < states + states_num; state_ptr++)
+ {
+ (*state_ptr)->equiv_class_num_1 = 1;
+ (*state_ptr)->next_equiv_class_state = result_equiv_class;
+ result_equiv_class = *state_ptr;
+ }
+ return result_equiv_class;
+}
+
+/* The function processes equivalence class given by its pointer
+ EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
+ are not equvalent states, the function partitions the class
+ removing nonequivalent states and placing them in
+ *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
+ assigns it to the state equivalence number. If the class has been
+ partitioned, the function returns nonzero value. */
+static int
+partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
+ next_iteration_classes, new_equiv_class_num_ptr)
+ state_t *equiv_class_ptr;
+ int odd_iteration_flag;
+ vla_ptr_t *next_iteration_classes;
+ int *new_equiv_class_num_ptr;
+{
+ state_t new_equiv_class;
+ int partition_p;
+ state_t first_state;
+ state_t curr_state;
+ state_t prev_state;
+ state_t next_state;
+ int out_arcs_num;
+
+ partition_p = 0;
+ if (*equiv_class_ptr == NULL)
+ abort ();
+ for (first_state = *equiv_class_ptr;
+ first_state != NULL;
+ first_state = new_equiv_class)
+ {
+ new_equiv_class = NULL;
+ if (first_state->next_equiv_class_state != NULL)
+ {
+ /* There are more one states in the class equivalence. */
+ out_arcs_num = set_out_arc_insns_equiv_num (first_state,
+ odd_iteration_flag);
+ for (prev_state = first_state,
+ curr_state = first_state->next_equiv_class_state;
+ curr_state != NULL;
+ curr_state = next_state)
+ {
+ next_state = curr_state->next_equiv_class_state;
+ if (state_is_differed (curr_state, out_arcs_num,
+ odd_iteration_flag))
+ {
+ /* Remove curr state from the class equivalence. */
+ prev_state->next_equiv_class_state = next_state;
+ /* Add curr state to the new class equivalence. */
+ curr_state->next_equiv_class_state = new_equiv_class;
+ if (new_equiv_class == NULL)
+ (*new_equiv_class_num_ptr)++;
+ if (odd_iteration_flag)
+ curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
+ else
+ curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
+ new_equiv_class = curr_state;
+ partition_p = 1;
+ }
+ else
+ prev_state = curr_state;
+ }
+ clear_arc_insns_equiv_num (first_state);
+ }
+ if (new_equiv_class != NULL)
+ VLA_PTR_ADD (*next_iteration_classes, new_equiv_class);
+ }
+ return partition_p;
+}
+
+/* The function finds equivalent states of AUTOMATON. */
+static void
+evaluate_equiv_classes (automaton, equiv_classes)
+ automaton_t automaton;
+ vla_ptr_t *equiv_classes;
+{
+ state_t new_equiv_class;
+ int new_equiv_class_num;
+ int odd_iteration_flag;
+ int finish_flag;
+ vla_ptr_t next_iteration_classes;
+ state_t *equiv_class_ptr;
+ state_t *state_ptr;
+
+ VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states");
+ pass_states (automaton, add_achieved_state);
+ new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states),
+ VLA_PTR_LENGTH (all_achieved_states));
+ odd_iteration_flag = 0;
+ new_equiv_class_num = 1;
+ VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");
+ VLA_PTR_ADD (next_iteration_classes, new_equiv_class);
+ do
+ {
+ odd_iteration_flag = !odd_iteration_flag;
+ finish_flag = 1;
+ copy_equiv_class (equiv_classes, &next_iteration_classes);
+ /* Transfer equiv numbers for the next iteration. */
+ for (state_ptr = VLA_PTR_BEGIN (all_achieved_states);
+ state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states);
+ state_ptr++)
+ if (odd_iteration_flag)
+ (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;
+ else
+ (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;
+ for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
+ equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
+ equiv_class_ptr++)
+ if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
+ &next_iteration_classes,
+ &new_equiv_class_num))
+ finish_flag = 0;
+ }
+ while (!finish_flag);
+ VLA_PTR_DELETE (next_iteration_classes);
+ VLA_PTR_DELETE (all_achieved_states);
+}
+
+/* The function merges equivalent states of AUTOMATON. */
+static void
+merge_states (automaton, equiv_classes)
+ automaton_t automaton;
+ vla_ptr_t *equiv_classes;
+{
+ state_t *equiv_class_ptr;
+ state_t curr_state;
+ state_t new_state;
+ state_t first_class_state;
+ alt_state_t alt_states;
+ alt_state_t new_alt_state;
+ arc_t curr_arc;
+ arc_t next_arc;
+
+ /* Create states corresponding to equivalence classes containing two
+ or more states. */
+ for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
+ equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
+ equiv_class_ptr++)
+ if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
+ {
+ /* There are more one states in the class equivalence. */
+ /* Create new compound state. */
+ new_state = get_free_state (0, automaton);
+ alt_states = NULL;
+ first_class_state = *equiv_class_ptr;
+ for (curr_state = first_class_state;
+ curr_state != NULL;
+ curr_state = curr_state->next_equiv_class_state)
+ {
+ curr_state->equiv_class_state = new_state;
+ new_alt_state = get_free_alt_state ();
+ new_alt_state->state = curr_state;
+ new_alt_state->next_sorted_alt_state = alt_states;
+ alt_states = new_alt_state;
+ }
+ new_state->component_states = alt_states;
+ }
+ else
+ (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;
+ for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
+ equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
+ equiv_class_ptr++)
+ if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
+ {
+ first_class_state = *equiv_class_ptr;
+ /* Create new arcs output from the state corresponding to
+ equiv class. */
+ for (curr_arc = first_out_arc (first_class_state);
+ curr_arc != NULL;
+ curr_arc = next_out_arc (curr_arc))
+ add_arc (first_class_state->equiv_class_state,
+ curr_arc->to_state->equiv_class_state,
+ curr_arc->insn, curr_arc->state_alts);
+ /* Delete output arcs from states of given class equivalence. */
+ for (curr_state = first_class_state;
+ curr_state != NULL;
+ curr_state = curr_state->next_equiv_class_state)
+ {
+ if (automaton->start_state == curr_state)
+ automaton->start_state = curr_state->equiv_class_state;
+ /* Delete the state and its output arcs. */
+ for (curr_arc = first_out_arc (curr_state);
+ curr_arc != NULL;
+ curr_arc = next_arc)
+ {
+ next_arc = next_out_arc (curr_arc);
+ free_arc (curr_arc);
+ }
+ }
+ }
+ else
+ {
+ /* Change `to_state' of arcs output from the state of given
+ equivalence class. */
+ for (curr_arc = first_out_arc (*equiv_class_ptr);
+ curr_arc != NULL;
+ curr_arc = next_out_arc (curr_arc))
+ curr_arc->to_state = curr_arc->to_state->equiv_class_state;
+ }
+}
+
+/* The function sets up new_cycle_p for states if there is arc to the
+ state marked by advance_cycle_insn_decl. */
+static void
+set_new_cycle_flags (state)
+ state_t state;
+{
+ arc_t arc;
+
+ for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
+ if (arc->insn->insn_reserv_decl
+ == DECL_INSN_RESERV (advance_cycle_insn_decl))
+ arc->to_state->new_cycle_p = 1;
+}
+
+/* The top level function for minimization of deterministic
+ AUTOMATON. */
+static void
+minimize_DFA (automaton)
+ automaton_t automaton;
+{
+ vla_ptr_t equiv_classes;
+
+ VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");
+ evaluate_equiv_classes (automaton, &equiv_classes);
+ merge_states (automaton, &equiv_classes);
+ pass_states (automaton, set_new_cycle_flags);
+ VLA_PTR_DELETE (equiv_classes);
+}
+
+/* Values of two variables are counted number of states and arcs in an
+ automaton. */
+static int curr_counted_states_num;
+static int curr_counted_arcs_num;
+
+/* The function is called by function `pass_states' to count states
+ and arcs of an automaton. */
+static void
+incr_states_and_arcs_nums (state)
+ state_t state;
+{
+ arc_t arc;
+
+ curr_counted_states_num++;
+ for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
+ curr_counted_arcs_num++;
+}
+
+/* The function counts states and arcs of AUTOMATON. */
+static void
+count_states_and_arcs (automaton, states_num, arcs_num)
+ automaton_t automaton;
+ int *states_num;
+ int *arcs_num;
+{
+ curr_counted_states_num = 0;
+ curr_counted_arcs_num = 0;
+ pass_states (automaton, incr_states_and_arcs_nums);
+ *states_num = curr_counted_states_num;
+ *arcs_num = curr_counted_arcs_num;
+}
+
+/* The function builds one DFA AUTOMATON for fast pipeline hazards
+ recognition after checking and simplifying IR of the
+ description. */
+static void
+build_automaton (automaton)
+ automaton_t automaton;
+{
+ int states_num;
+ int arcs_num;
+
+ ticker_on (&NDFA_time);
+ make_automaton (automaton);
+ ticker_off (&NDFA_time);
+ count_states_and_arcs (automaton, &states_num, &arcs_num);
+ automaton->NDFA_states_num = states_num;
+ automaton->NDFA_arcs_num = arcs_num;
+ ticker_on (&NDFA_to_DFA_time);
+ NDFA_to_DFA (automaton);
+ ticker_off (&NDFA_to_DFA_time);
+ count_states_and_arcs (automaton, &states_num, &arcs_num);
+ automaton->DFA_states_num = states_num;
+ automaton->DFA_arcs_num = arcs_num;
+ if (!no_minimization_flag)
+ {
+ ticker_on (&minimize_time);
+ minimize_DFA (automaton);
+ ticker_off (&minimize_time);
+ count_states_and_arcs (automaton, &states_num, &arcs_num);
+ automaton->minimal_DFA_states_num = states_num;
+ automaton->minimal_DFA_arcs_num = arcs_num;
+ }
+}
+
+
+
+/* The page contains code for enumeration of all states of an automaton. */
+
+/* Variable used for enumeration of all states of an automaton. Its
+ value is current number of automaton states. */
+static int curr_state_order_num;
+
+/* The function is called by function `pass_states' for enumerating
+ states. */
+static void
+set_order_state_num (state)
+ state_t state;
+{
+ state->order_state_num = curr_state_order_num;
+ curr_state_order_num++;
+}
+
+/* The function enumerates all states of AUTOMATON. */
+static void
+enumerate_states (automaton)
+ automaton_t automaton;
+{
+ curr_state_order_num = 0;
+ pass_states (automaton, set_order_state_num);
+ automaton->achieved_states_num = curr_state_order_num;
+}
+
+
+
+/* The page contains code for finding equivalent automaton insns
+ (ainsns). */
+
+/* The function inserts AINSN into cyclic list
+ CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
+static ainsn_t
+insert_ainsn_into_equiv_class (ainsn, cyclic_equiv_class_insn_list)
+ ainsn_t ainsn;
+ ainsn_t cyclic_equiv_class_insn_list;
+{
+ if (cyclic_equiv_class_insn_list == NULL)
+ ainsn->next_equiv_class_insn = ainsn;
+ else
+ {
+ ainsn->next_equiv_class_insn
+ = cyclic_equiv_class_insn_list->next_equiv_class_insn;
+ cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
+ }
+ return ainsn;
+}
+
+/* The function deletes equiv_class_insn into cyclic list of
+ equivalent ainsns. */
+static void
+delete_ainsn_from_equiv_class (equiv_class_insn)
+ ainsn_t equiv_class_insn;
+{
+ ainsn_t curr_equiv_class_insn;
+ ainsn_t prev_equiv_class_insn;
+
+ prev_equiv_class_insn = equiv_class_insn;
+ for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
+ curr_equiv_class_insn != equiv_class_insn;
+ curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
+ prev_equiv_class_insn = curr_equiv_class_insn;
+ if (prev_equiv_class_insn != equiv_class_insn)
+ prev_equiv_class_insn->next_equiv_class_insn
+ = equiv_class_insn->next_equiv_class_insn;
+}
+
+/* The function processes AINSN of a state in order to find equivalent
+ ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
+ state. */
+static void
+process_insn_equiv_class (ainsn, insn_arcs_array)
+ ainsn_t ainsn;
+ arc_t *insn_arcs_array;
+{
+ ainsn_t next_insn;
+ ainsn_t curr_insn;
+ ainsn_t cyclic_insn_list;
+ arc_t arc;
+
+ if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL)
+ abort ();
+ curr_insn = ainsn;
+ /* New class of ainsns which are not equivalent to given ainsn. */
+ cyclic_insn_list = NULL;
+ do
+ {
+ next_insn = curr_insn->next_equiv_class_insn;
+ arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
+ if (arc == NULL
+ || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
+ != arc->to_state))
+ {
+ delete_ainsn_from_equiv_class (curr_insn);
+ cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
+ cyclic_insn_list);
+ }
+ curr_insn = next_insn;
+ }
+ while (curr_insn != ainsn);
+}
+
+/* The function processes STATE in order to find equivalent ainsns. */
+static void
+process_state_for_insn_equiv_partition (state)
+ state_t state;
+{
+ arc_t arc;
+ arc_t *insn_arcs_array;
+ int i;
+ vla_ptr_t insn_arcs_vect;
+
+ VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");
+ VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num);
+ insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);
+ /* Process insns of the arcs. */
+ for (i = 0; i < description->insns_num; i++)
+ insn_arcs_array [i] = NULL;
+ for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
+ insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
+ for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
+ process_insn_equiv_class (arc->insn, insn_arcs_array);
+ VLA_PTR_DELETE (insn_arcs_vect);
+}
+
+/* The function searches for equivalent ainsns of AUTOMATON. */
+static void
+set_insn_equiv_classes (automaton)
+ automaton_t automaton;
+{
+ ainsn_t ainsn;
+ ainsn_t first_insn;
+ ainsn_t curr_insn;
+ ainsn_t cyclic_insn_list;
+ ainsn_t insn_with_same_reservs;
+ int equiv_classes_num;
+
+ /* All insns are included in one equivalence class. */
+ cyclic_insn_list = NULL;
+ for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
+ if (ainsn->first_insn_with_same_reservs)
+ cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
+ cyclic_insn_list);
+ /* Process insns in order to make equivalence partition. */
+ pass_states (automaton, process_state_for_insn_equiv_partition);
+ /* Enumerate equiv classes. */
+ for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
+ /* Set undefined value. */
+ ainsn->insn_equiv_class_num = -1;
+ equiv_classes_num = 0;
+ for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
+ if (ainsn->insn_equiv_class_num < 0)
+ {
+ first_insn = ainsn;
+ if (!first_insn->first_insn_with_same_reservs)
+ abort ();
+ first_insn->first_ainsn_with_given_equialence_num = 1;
+ curr_insn = first_insn;
+ do
+ {
+ for (insn_with_same_reservs = curr_insn;
+ insn_with_same_reservs != NULL;
+ insn_with_same_reservs
+ = insn_with_same_reservs->next_same_reservs_insn)
+ insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
+ curr_insn = curr_insn->next_equiv_class_insn;
+ }
+ while (curr_insn != first_insn);
+ equiv_classes_num++;
+ }
+ automaton->insn_equiv_classes_num = equiv_classes_num;
+}
+
+
+
+/* This page contains code for creating DFA(s) and calls functions
+ building them. */
+
+
+/* The following value is used to prevent floating point overflow for
+ estimating an automaton bound. The value should be less DBL_MAX on
+ the host machine. We use here approximate minimum of maximal
+ double floating point value required by ANSI C standard. It
+ will work for non ANSI sun compiler too. */
+
+#define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
+
+/* The function estimate size of the single DFA used by PHR (pipeline
+ hazards recognizer). */
+static double
+estimate_one_automaton_bound ()
+{
+ decl_t decl;
+ double one_automaton_estimation_bound;
+ double root_value;
+ int i;
+
+ one_automaton_estimation_bound = 1.0;
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_unit)
+ {
+ root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num + 1.0)
+ / automata_num);
+ if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
+ > one_automaton_estimation_bound)
+ one_automaton_estimation_bound *= root_value;
+ }
+ }
+ return one_automaton_estimation_bound;
+}
+
+/* The function compares unit declarations acoording to their maximal
+ cycle in reservations. */
+static int
+compare_max_occ_cycle_nums (unit_decl_1, unit_decl_2)
+ const void *unit_decl_1;
+ const void *unit_decl_2;
+{
+ if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
+ < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
+ return 1;
+ else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
+ == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
+ return 0;
+ else
+ return -1;
+}
+
+/* The function makes heuristic assigning automata to units. Actually
+ efficacy of the algorithm has been checked yet??? */
+static void
+units_to_automata_heuristic_distr ()
+{
+ double estimation_bound;
+ decl_t decl;
+ decl_t *unit_decl_ptr;
+ int automaton_num;
+ int rest_units_num;
+ double bound_value;
+ vla_ptr_t unit_decls;
+ int i;
+
+ if (description->units_num == 0)
+ return;
+ estimation_bound = estimate_one_automaton_bound ();
+ VLA_PTR_CREATE (unit_decls, 150, "unit decls");
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_unit)
+ VLA_PTR_ADD (unit_decls, decl);
+ }
+ qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls),
+ sizeof (decl_t), compare_max_occ_cycle_nums);
+ automaton_num = 0;
+ unit_decl_ptr = VLA_PTR_BEGIN (unit_decls);
+ bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
+ DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
+ for (unit_decl_ptr++;
+ unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls);
+ unit_decl_ptr++)
+ {
+ rest_units_num
+ = ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1);
+ if (automata_num - automaton_num - 1 > rest_units_num)
+ abort ();
+ if (automaton_num < automata_num - 1
+ && ((automata_num - automaton_num - 1 == rest_units_num)
+ || (bound_value
+ > (estimation_bound
+ / (DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num)))))
+ {
+ bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
+ automaton_num++;
+ }
+ else
+ bound_value *= DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
+ DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
+ }
+ if (automaton_num != automata_num - 1)
+ abort ();
+ VLA_PTR_DELETE (unit_decls);
+}
+
+/* The functions creates automaton insns for each automata. Automaton
+ insn is simply insn for given automaton which makes reservation
+ only of units of the automaton. */
+static ainsn_t
+create_ainsns ()
+{
+ decl_t decl;
+ ainsn_t first_ainsn;
+ ainsn_t curr_ainsn;
+ ainsn_t prev_ainsn;
+ int i;
+
+ first_ainsn = NULL;
+ prev_ainsn = NULL;
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv)
+ {
+ curr_ainsn = create_node (sizeof (struct ainsn));
+ curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
+ curr_ainsn->important_p = FALSE;
+ curr_ainsn->next_ainsn = NULL;
+ if (prev_ainsn == NULL)
+ first_ainsn = curr_ainsn;
+ else
+ prev_ainsn->next_ainsn = curr_ainsn;
+ prev_ainsn = curr_ainsn;
+ }
+ }
+ return first_ainsn;
+}
+
+/* The function assigns automata to units according to constructions
+ `define_automaton' in the description. */
+static void
+units_to_automata_distr ()
+{
+ decl_t decl;
+ int i;
+
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_unit)
+ {
+ if (DECL_UNIT (decl)->automaton_decl == NULL
+ || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
+ == NULL))
+ /* Distribute to the first automaton. */
+ DECL_UNIT (decl)->corresponding_automaton_num = 0;
+ else
+ DECL_UNIT (decl)->corresponding_automaton_num
+ = (DECL_UNIT (decl)->automaton_decl
+ ->corresponding_automaton->automaton_order_num);
+ }
+ }
+}
+
+/* The function creates DFA(s) for fast pipeline hazards recognition
+ after checking and simplifying IR of the description. */
+static void
+create_automata ()
+{
+ automaton_t curr_automaton;
+ automaton_t prev_automaton;
+ decl_t decl;
+ int curr_automaton_num;
+ int i;
+
+ if (automata_num != 0)
+ {
+ units_to_automata_heuristic_distr ();
+ for (prev_automaton = NULL, curr_automaton_num = 0;
+ curr_automaton_num < automata_num;
+ curr_automaton_num++, prev_automaton = curr_automaton)
+ {
+ curr_automaton = create_node (sizeof (struct automaton));
+ curr_automaton->ainsn_list = create_ainsns ();
+ curr_automaton->corresponding_automaton_decl = NULL;
+ curr_automaton->next_automaton = NULL;
+ curr_automaton->automaton_order_num = curr_automaton_num;
+ if (prev_automaton == NULL)
+ description->first_automaton = curr_automaton;
+ else
+ prev_automaton->next_automaton = curr_automaton;
+ }
+ }
+ else
+ {
+ curr_automaton_num = 0;
+ prev_automaton = NULL;
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_automaton
+ && DECL_AUTOMATON (decl)->automaton_is_used)
+ {
+ curr_automaton = create_node (sizeof (struct automaton));
+ curr_automaton->ainsn_list = create_ainsns ();
+ curr_automaton->corresponding_automaton_decl
+ = DECL_AUTOMATON (decl);
+ curr_automaton->next_automaton = NULL;
+ DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
+ curr_automaton->automaton_order_num = curr_automaton_num;
+ if (prev_automaton == NULL)
+ description->first_automaton = curr_automaton;
+ else
+ prev_automaton->next_automaton = curr_automaton;
+ curr_automaton_num++;
+ prev_automaton = curr_automaton;
+ }
+ }
+ if (curr_automaton_num == 0)
+ {
+ curr_automaton = create_node (sizeof (struct automaton));
+ curr_automaton->ainsn_list = create_ainsns ();
+ curr_automaton->corresponding_automaton_decl = NULL;
+ curr_automaton->next_automaton = NULL;
+ description->first_automaton = curr_automaton;
+ }
+ units_to_automata_distr ();
+ }
+ NDFA_time = create_ticker ();
+ ticker_off (&NDFA_time);
+ NDFA_to_DFA_time = create_ticker ();
+ ticker_off (&NDFA_to_DFA_time);
+ minimize_time = create_ticker ();
+ ticker_off (&minimize_time);
+ equiv_time = create_ticker ();
+ ticker_off (&equiv_time);
+ for (curr_automaton = description->first_automaton;
+ curr_automaton != NULL;
+ curr_automaton = curr_automaton->next_automaton)
+ {
+ if (curr_automaton->corresponding_automaton_decl == NULL)
+ fprintf (stderr, "Create anonymous automaton ...");
+ else
+ fprintf (stderr, "Create automaton `%s'...",
+ curr_automaton->corresponding_automaton_decl->name);
+ create_alt_states (curr_automaton);
+ form_ainsn_with_same_reservs (curr_automaton);
+ build_automaton (curr_automaton);
+ enumerate_states (curr_automaton);
+ ticker_on (&equiv_time);
+ set_insn_equiv_classes (curr_automaton);
+ ticker_off (&equiv_time);
+ fprintf (stderr, "done\n");
+ }
+}
+
+
+
+/* This page contains code for forming string representation of
+ regexp. The representation is formed on IR obstack. So you should
+ not work with IR obstack between regexp_representation and
+ finish_regexp_representation calls. */
+
+/* This recursive function forms string representation of regexp
+ (without tailing '\0'). */
+static void
+form_regexp (regexp)
+ regexp_t regexp;
+{
+ int i;
+
+ if (regexp->mode == rm_unit || regexp->mode == rm_reserv)
+ {
+ const char *name = (regexp->mode == rm_unit
+ ? REGEXP_UNIT (regexp)->name
+ : REGEXP_RESERV (regexp)->name);
+
+ obstack_grow (&irp, name, strlen (name));
+ }
+ else if (regexp->mode == rm_sequence)
+ for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
+ {
+ if (i != 0)
+ obstack_1grow (&irp, ',');
+ form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
+ }
+ else if (regexp->mode == rm_allof)
+ {
+ obstack_1grow (&irp, '(');
+ for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
+ {
+ if (i != 0)
+ obstack_1grow (&irp, '+');
+ if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
+ || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
+ obstack_1grow (&irp, '(');
+ form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
+ if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
+ || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
+ obstack_1grow (&irp, ')');
+ }
+ obstack_1grow (&irp, ')');
+ }
+ else if (regexp->mode == rm_oneof)
+ for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
+ {
+ if (i != 0)
+ obstack_1grow (&irp, '|');
+ if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
+ obstack_1grow (&irp, '(');
+ form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
+ if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
+ obstack_1grow (&irp, ')');
+ }
+ else if (regexp->mode == rm_repeat)
+ {
+ char digits [30];
+
+ if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
+ || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
+ || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
+ obstack_1grow (&irp, '(');
+ form_regexp (REGEXP_REPEAT (regexp)->regexp);
+ if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
+ || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
+ || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
+ obstack_1grow (&irp, ')');
+ sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
+ obstack_grow (&irp, digits, strlen (digits));
+ }
+ else if (regexp->mode == rm_nothing)
+ obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
+ else
+ abort ();
+}
+
+/* The function returns string representation of REGEXP on IR
+ obstack. */
+static const char *
+regexp_representation (regexp)
+ regexp_t regexp;
+{
+ form_regexp (regexp);
+ obstack_1grow (&irp, '\0');
+ return obstack_base (&irp);
+}
+
+/* The function frees memory allocated for last formed string
+ representation of regexp. */
+static void
+finish_regexp_representation ()
+{
+ int length = obstack_object_size (&irp);
+
+ obstack_blank_fast (&irp, -length);
+}
+
+
+
+/* This page contains code for output PHR (pipeline hazards recognizer). */
+
+/* The function outputs minimal C type which is sufficient for
+ representation numbers in range min_range_value and
+ max_range_value. Because host machine and build machine may be
+ different, we use here minimal values required by ANSI C standard
+ instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
+ approximation. */
+
+static void
+output_range_type (f, min_range_value, max_range_value)
+ FILE *f;
+ long int min_range_value;
+ long int max_range_value;
+{
+ if (min_range_value >= 0 && max_range_value <= 255)
+ fprintf (f, "unsigned char");
+ else if (min_range_value >= -127 && max_range_value <= 127)
+ fprintf (f, "signed char");
+ else if (min_range_value >= 0 && max_range_value <= 65535)
+ fprintf (f, "unsigned short");
+ else if (min_range_value >= -32767 && max_range_value <= 32767)
+ fprintf (f, "short");
+ else
+ fprintf (f, "int");
+}
+
+/* The following macro value is used as value of member
+ `longest_path_length' of state when we are processing path and the
+ state on the path. */
+
+#define ON_THE_PATH -2
+
+/* The following recursive function searches for the length of the
+ longest path starting from STATE which does not contain cycles and
+ `cycle advance' arcs. */
+
+static int
+longest_path_length (state)
+ state_t state;
+{
+ arc_t arc;
+ int length, result;
+
+ if (state->longest_path_length == ON_THE_PATH)
+ /* We don't expect the path cycle here. Our graph may contain
+ only cycles with one state on the path not containing `cycle
+ advance' arcs -- see comment below. */
+ abort ();
+ else if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
+ /* We alreday visited the state. */
+ return state->longest_path_length;
+
+ result = 0;
+ for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
+ /* Ignore cycles containing one state and `cycle advance' arcs. */
+ if (arc->to_state != state
+ && (arc->insn->insn_reserv_decl
+ != DECL_INSN_RESERV (advance_cycle_insn_decl)))
+ {
+ length = longest_path_length (arc->to_state);
+ if (length > result)
+ result = length;
+ }
+ state->longest_path_length = result + 1;
+ return result;
+}
+
+/* The following variable value is value of the corresponding global
+ variable in the automaton based pipeline interface. */
+
+static int max_dfa_issue_rate;
+
+/* The following function processes the longest path length staring
+ from STATE to find MAX_DFA_ISSUE_RATE. */
+
+static void
+process_state_longest_path_length (state)
+ state_t state;
+{
+ int value;
+
+ value = longest_path_length (state);
+ if (value > max_dfa_issue_rate)
+ max_dfa_issue_rate = value;
+}
+
+/* The following macro value is name of the corresponding global
+ variable in the automaton based pipeline interface. */
+
+#define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
+
+/* The following function calculates value of the corresponding
+ global variable and outputs its declaration. */
+
+static void
+output_dfa_max_issue_rate ()
+{
+ automaton_t automaton;
+
+ if (UNDEFINED_LONGEST_PATH_LENGTH == ON_THE_PATH || ON_THE_PATH >= 0)
+ abort ();
+ max_dfa_issue_rate = 0;
+ for (automaton = description->first_automaton;
+ automaton != NULL;
+ automaton = automaton->next_automaton)
+ pass_states (automaton, process_state_longest_path_length);
+ fprintf (output_file, "\nint %s = %d;\n",
+ MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);
+}
+
+/* The function outputs all initialization values of VECT with length
+ vect_length. */
+static void
+output_vect (vect, vect_length)
+ vect_el_t *vect;
+ int vect_length;
+{
+ int els_on_line;
+
+ els_on_line = 1;
+ if (vect_length == 0)
+ fprintf (output_file,
+ "0 /* This is dummy el because the vect is empty */");
+ else
+ {
+ do
+ {
+ fprintf (output_file, "%5ld", (long) *vect);
+ vect_length--;
+ if (els_on_line == 10)
+ {
+ els_on_line = 0;
+ fprintf (output_file, ",\n");
+ }
+ else if (vect_length != 0)
+ fprintf (output_file, ", ");
+ els_on_line++;
+ vect++;
+ }
+ while (vect_length != 0);
+ }
+}
+
+/* The following is name of the structure which represents DFA(s) for
+ PHR. */
+#define CHIP_NAME "DFA_chip"
+
+/* The following is name of member which represents state of a DFA for
+ PHR. */
+static void
+output_chip_member_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ if (automaton->corresponding_automaton_decl == NULL)
+ fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
+ else
+ fprintf (f, "%s_automaton_state",
+ automaton->corresponding_automaton_decl->name);
+}
+
+/* The following is name of temporary variable which stores state of a
+ DFA for PHR. */
+static void
+output_temp_chip_member_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ fprintf (f, "_");
+ output_chip_member_name (f, automaton);
+}
+
+/* This is name of macro value which is code of pseudo_insn
+ representing advancing cpu cycle. Its value is used as internal
+ code unknown insn. */
+#define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
+
+/* Output name of translate vector for given automaton. */
+static void
+output_translate_vect_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ if (automaton->corresponding_automaton_decl == NULL)
+ fprintf (f, "translate_%d", automaton->automaton_order_num);
+ else
+ fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
+}
+
+/* Output name for simple transition table representation. */
+static void
+output_trans_full_vect_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ if (automaton->corresponding_automaton_decl == NULL)
+ fprintf (f, "transitions_%d", automaton->automaton_order_num);
+ else
+ fprintf (f, "%s_transitions",
+ automaton->corresponding_automaton_decl->name);
+}
+
+/* Output name of comb vector of the transition table for given
+ automaton. */
+static void
+output_trans_comb_vect_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ if (automaton->corresponding_automaton_decl == NULL)
+ fprintf (f, "transitions_%d", automaton->automaton_order_num);
+ else
+ fprintf (f, "%s_transitions",
+ automaton->corresponding_automaton_decl->name);
+}
+
+/* Output name of check vector of the transition table for given
+ automaton. */
+static void
+output_trans_check_vect_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ if (automaton->corresponding_automaton_decl == NULL)
+ fprintf (f, "check_%d", automaton->automaton_order_num);
+ else
+ fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
+}
+
+/* Output name of base vector of the transition table for given
+ automaton. */
+static void
+output_trans_base_vect_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ if (automaton->corresponding_automaton_decl == NULL)
+ fprintf (f, "base_%d", automaton->automaton_order_num);
+ else
+ fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
+}
+
+/* Output name for simple alternatives number representation. */
+static void
+output_state_alts_full_vect_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ if (automaton->corresponding_automaton_decl == NULL)
+ fprintf (f, "state_alts_%d", automaton->automaton_order_num);
+ else
+ fprintf (f, "%s_state_alts",
+ automaton->corresponding_automaton_decl->name);
+}
+
+/* Output name of comb vector of the alternatives number table for given
+ automaton. */
+static void
+output_state_alts_comb_vect_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ if (automaton->corresponding_automaton_decl == NULL)
+ fprintf (f, "state_alts_%d", automaton->automaton_order_num);
+ else
+ fprintf (f, "%s_state_alts",
+ automaton->corresponding_automaton_decl->name);
+}
+
+/* Output name of check vector of the alternatives number table for given
+ automaton. */
+static void
+output_state_alts_check_vect_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ if (automaton->corresponding_automaton_decl == NULL)
+ fprintf (f, "check_state_alts_%d", automaton->automaton_order_num);
+ else
+ fprintf (f, "%s_check_state_alts",
+ automaton->corresponding_automaton_decl->name);
+}
+
+/* Output name of base vector of the alternatives number table for given
+ automaton. */
+static void
+output_state_alts_base_vect_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ if (automaton->corresponding_automaton_decl == NULL)
+ fprintf (f, "base_state_alts_%d", automaton->automaton_order_num);
+ else
+ fprintf (f, "%s_base_state_alts",
+ automaton->corresponding_automaton_decl->name);
+}
+
+/* Output name of simple min issue delay table representation. */
+static void
+output_min_issue_delay_vect_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ if (automaton->corresponding_automaton_decl == NULL)
+ fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
+ else
+ fprintf (f, "%s_min_issue_delay",
+ automaton->corresponding_automaton_decl->name);
+}
+
+/* Output name of deadlock vector for given automaton. */
+static void
+output_dead_lock_vect_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ if (automaton->corresponding_automaton_decl == NULL)
+ fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
+ else
+ fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
+}
+
+/* Output name of reserved units table for AUTOMATON into file F. */
+static void
+output_reserved_units_table_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ if (automaton->corresponding_automaton_decl == NULL)
+ fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
+ else
+ fprintf (f, "%s_reserved_units",
+ automaton->corresponding_automaton_decl->name);
+}
+
+/* Name of the PHR interface macro. */
+#define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
+
+/* Name of the PHR interface macro. */
+#define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
+
+/* Names of an internal functions: */
+#define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
+
+/* This is external type of DFA(s) state. */
+#define STATE_TYPE_NAME "state_t"
+
+#define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
+
+#define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
+
+#define INTERNAL_RESET_FUNC_NAME "internal_reset"
+
+#define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
+
+#define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
+
+/* Name of cache of insn dfa codes. */
+#define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
+
+/* Name of length of cache of insn dfa codes. */
+#define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
+
+/* Names of the PHR interface functions: */
+#define SIZE_FUNC_NAME "state_size"
+
+#define TRANSITION_FUNC_NAME "state_transition"
+
+#define STATE_ALTS_FUNC_NAME "state_alts"
+
+#define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
+
+#define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
+
+#define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
+
+#define RESET_FUNC_NAME "state_reset"
+
+#define INSN_LATENCY_FUNC_NAME "insn_latency"
+
+#define PRINT_RESERVATION_FUNC_NAME "print_reservation"
+
+#define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
+
+#define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
+
+#define DFA_START_FUNC_NAME "dfa_start"
+
+#define DFA_FINISH_FUNC_NAME "dfa_finish"
+
+/* Names of parameters of the PHR interface functions. */
+#define STATE_NAME "state"
+
+#define INSN_PARAMETER_NAME "insn"
+
+#define INSN2_PARAMETER_NAME "insn2"
+
+#define CHIP_PARAMETER_NAME "chip"
+
+#define FILE_PARAMETER_NAME "f"
+
+#define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
+
+#define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
+
+/* Names of the variables whose values are internal insn code of rtx
+ insn. */
+#define INTERNAL_INSN_CODE_NAME "insn_code"
+
+#define INTERNAL_INSN2_CODE_NAME "insn2_code"
+
+/* Names of temporary variables in some functions. */
+#define TEMPORARY_VARIABLE_NAME "temp"
+
+#define I_VARIABLE_NAME "i"
+
+/* Name of result variable in some functions. */
+#define RESULT_VARIABLE_NAME "res"
+
+/* Name of function (attribute) to translate insn into number of insn
+ alternatives reservation. */
+#define INSN_ALTS_FUNC_NAME "insn_alts"
+
+/* Name of function (attribute) to translate insn into internal insn
+ code. */
+#define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
+
+/* Name of function (attribute) to translate insn into internal insn
+ code with caching. */
+#define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
+
+/* Name of function (attribute) to translate insn into internal insn
+ code. */
+#define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
+
+/* Name of function (attribute) to translate insn into internal insn
+ code. */
+#define BYPASS_P_FUNC_NAME "bypass_p"
+
+/* Output C type which is used for representation of codes of states
+ of AUTOMATON. */
+static void
+output_state_member_type (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ output_range_type (f, 0, automaton->achieved_states_num);
+}
+
+/* Output definition of the structure representing current DFA(s)
+ state(s). */
+static void
+output_chip_definitions ()
+{
+ automaton_t automaton;
+
+ fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
+ for (automaton = description->first_automaton;
+ automaton != NULL;
+ automaton = automaton->next_automaton)
+ {
+ fprintf (output_file, " ");
+ output_state_member_type (output_file, automaton);
+ fprintf (output_file, " ");
+ output_chip_member_name (output_file, automaton);
+ fprintf (output_file, ";\n");
+ }
+ fprintf (output_file, "};\n\n");
+#if 0
+ fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
+#endif
+}
+
+
+/* The function outputs translate vector of internal insn code into
+ insn equivalence class number. The equivalence class number is
+ used to access to table and vectors reprewsenting DFA(s). */
+static void
+output_translate_vect (automaton)
+ automaton_t automaton;
+{
+ ainsn_t ainsn;
+ int insn_value;
+ vla_hwint_t translate_vect;
+
+ VLA_HWINT_CREATE (translate_vect, 250, "translate vector");
+ VLA_HWINT_EXPAND (translate_vect, description->insns_num);
+ for (insn_value = 0; insn_value <= description->insns_num; insn_value++)
+ /* Undefined value */
+ VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num;
+ for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
+ VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)
+ = ainsn->insn_equiv_class_num;
+ fprintf (output_file,
+ "/* Vector translating external insn codes to internal ones.*/\n");
+ fprintf (output_file, "static const ");
+ output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
+ fprintf (output_file, " ");
+ output_translate_vect_name (output_file, automaton);
+ fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
+ output_vect (VLA_HWINT_BEGIN (translate_vect),
+ VLA_HWINT_LENGTH (translate_vect));
+ fprintf (output_file, "};\n\n");
+ VLA_HWINT_DELETE (translate_vect);
+}
+
+/* The value in a table state x ainsn -> something which represents
+ undefined value. */
+static int undefined_vect_el_value;
+
+/* The following function returns nonzero value if the best
+ representation of the table is comb vector. */
+static int
+comb_vect_p (tab)
+ state_ainsn_table_t tab;
+{
+ return (2 * VLA_HWINT_LENGTH (tab->full_vect)
+ > 5 * VLA_HWINT_LENGTH (tab->comb_vect));
+}
+
+/* The following function creates new table for AUTOMATON. */
+static state_ainsn_table_t
+create_state_ainsn_table (automaton)
+ automaton_t automaton;
+{
+ state_ainsn_table_t tab;
+ int full_vect_length;
+ int i;
+
+ tab = create_node (sizeof (struct state_ainsn_table));
+ tab->automaton = automaton;
+ VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector");
+ VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector");
+ VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector");
+ VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num);
+ VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector");
+ full_vect_length = (automaton->insn_equiv_classes_num
+ * automaton->achieved_states_num);
+ VLA_HWINT_EXPAND (tab->full_vect, full_vect_length);
+ for (i = 0; i < full_vect_length; i++)
+ VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;
+ tab->min_base_vect_el_value = 0;
+ tab->max_base_vect_el_value = 0;
+ tab->min_comb_vect_el_value = 0;
+ tab->max_comb_vect_el_value = 0;
+ return tab;
+}
+
+/* The following function outputs the best C representation of the
+ table TAB of given TABLE_NAME. */
+static void
+output_state_ainsn_table (tab, table_name, output_full_vect_name_func,
+ output_comb_vect_name_func,
+ output_check_vect_name_func,
+ output_base_vect_name_func)
+ state_ainsn_table_t tab;
+ char *table_name;
+ void (*output_full_vect_name_func) PARAMS ((FILE *, automaton_t));
+ void (*output_comb_vect_name_func) PARAMS ((FILE *, automaton_t));
+ void (*output_check_vect_name_func) PARAMS ((FILE *, automaton_t));
+ void (*output_base_vect_name_func) PARAMS ((FILE *, automaton_t));
+{
+ if (!comb_vect_p (tab))
+ {
+ fprintf (output_file, "/* Vector for %s. */\n", table_name);
+ fprintf (output_file, "static const ");
+ output_range_type (output_file, tab->min_comb_vect_el_value,
+ tab->max_comb_vect_el_value);
+ fprintf (output_file, " ");
+ (*output_full_vect_name_func) (output_file, tab->automaton);
+ fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
+ output_vect (VLA_HWINT_BEGIN (tab->full_vect),
+ VLA_HWINT_LENGTH (tab->full_vect));
+ fprintf (output_file, "};\n\n");
+ }
+ else
+ {
+ fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
+ fprintf (output_file, "static const ");
+ output_range_type (output_file, tab->min_comb_vect_el_value,
+ tab->max_comb_vect_el_value);
+ fprintf (output_file, " ");
+ (*output_comb_vect_name_func) (output_file, tab->automaton);
+ fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
+ output_vect (VLA_HWINT_BEGIN (tab->comb_vect),
+ VLA_HWINT_LENGTH (tab->comb_vect));
+ fprintf (output_file, "};\n\n");
+ fprintf (output_file, "/* Check vector for %s. */\n", table_name);
+ fprintf (output_file, "static const ");
+ output_range_type (output_file, 0, tab->automaton->achieved_states_num);
+ fprintf (output_file, " ");
+ (*output_check_vect_name_func) (output_file, tab->automaton);
+ fprintf (output_file, "[] = {\n");
+ output_vect (VLA_HWINT_BEGIN (tab->check_vect),
+ VLA_HWINT_LENGTH (tab->check_vect));
+ fprintf (output_file, "};\n\n");
+ fprintf (output_file, "/* Base vector for %s. */\n", table_name);
+ fprintf (output_file, "static const ");
+ output_range_type (output_file, tab->min_base_vect_el_value,
+ tab->max_base_vect_el_value);
+ fprintf (output_file, " ");
+ (*output_base_vect_name_func) (output_file, tab->automaton);
+ fprintf (output_file, "[] = {\n");
+ output_vect (VLA_HWINT_BEGIN (tab->base_vect),
+ VLA_HWINT_LENGTH (tab->base_vect));
+ fprintf (output_file, "};\n\n");
+ }
+}
+
+/* The following function adds vector with length VECT_LENGTH and
+ elements pointed by VECT to table TAB as its line with number
+ VECT_NUM. */
+static void
+add_vect (tab, vect_num, vect, vect_length)
+ state_ainsn_table_t tab;
+ int vect_num;
+ vect_el_t *vect;
+ int vect_length;
+{
+ int real_vect_length;
+ vect_el_t *comb_vect_start;
+ vect_el_t *check_vect_start;
+ int comb_vect_index;
+ int comb_vect_els_num;
+ int vect_index;
+ int first_unempty_vect_index;
+ int additional_els_num;
+ int no_state_value;
+ vect_el_t vect_el;
+ int i;
+
+ if (vect_length == 0)
+ abort ();
+ real_vect_length = tab->automaton->insn_equiv_classes_num;
+ if (vect [vect_length - 1] == undefined_vect_el_value)
+ abort ();
+ /* Form full vector in the table: */
+ for (i = 0; i < vect_length; i++)
+ VLA_HWINT (tab->full_vect,
+ i + tab->automaton->insn_equiv_classes_num * vect_num)
+ = vect [i];
+ /* Form comb vector in the table: */
+ if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect))
+ abort ();
+ comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
+ comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect);
+ for (first_unempty_vect_index = 0;
+ first_unempty_vect_index < vect_length;
+ first_unempty_vect_index++)
+ if (vect [first_unempty_vect_index] != undefined_vect_el_value)
+ break;
+ /* Search for the place in comb vect for the inserted vect. */
+ for (comb_vect_index = 0;
+ comb_vect_index < comb_vect_els_num;
+ comb_vect_index++)
+ {
+ for (vect_index = first_unempty_vect_index;
+ vect_index < vect_length
+ && vect_index + comb_vect_index < comb_vect_els_num;
+ vect_index++)
+ if (vect [vect_index] != undefined_vect_el_value
+ && (comb_vect_start [vect_index + comb_vect_index]
+ != undefined_vect_el_value))
+ break;
+ if (vect_index >= vect_length
+ || vect_index + comb_vect_index >= comb_vect_els_num)
+ break;
+ }
+ /* Slot was found. */
+ additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
+ if (additional_els_num < 0)
+ additional_els_num = 0;
+ /* Expand comb and check vectors. */
+ vect_el = undefined_vect_el_value;
+ no_state_value = tab->automaton->achieved_states_num;
+ while (additional_els_num > 0)
+ {
+ VLA_HWINT_ADD (tab->comb_vect, vect_el);
+ VLA_HWINT_ADD (tab->check_vect, no_state_value);
+ additional_els_num--;
+ }
+ comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
+ check_vect_start = VLA_HWINT_BEGIN (tab->check_vect);
+ if (VLA_HWINT_LENGTH (tab->comb_vect)
+ < (size_t) (comb_vect_index + real_vect_length))
+ abort ();
+ /* Fill comb and check vectors. */
+ for (vect_index = 0; vect_index < vect_length; vect_index++)
+ if (vect [vect_index] != undefined_vect_el_value)
+ {
+ if (comb_vect_start [comb_vect_index + vect_index]
+ != undefined_vect_el_value)
+ abort ();
+ comb_vect_start [comb_vect_index + vect_index] = vect [vect_index];
+ if (vect [vect_index] < 0)
+ abort ();
+ if (tab->max_comb_vect_el_value < vect [vect_index])
+ tab->max_comb_vect_el_value = vect [vect_index];
+ if (tab->min_comb_vect_el_value > vect [vect_index])
+ tab->min_comb_vect_el_value = vect [vect_index];
+ check_vect_start [comb_vect_index + vect_index] = vect_num;
+ }
+ if (tab->max_base_vect_el_value < comb_vect_index)
+ tab->max_base_vect_el_value = comb_vect_index;
+ if (tab->min_base_vect_el_value > comb_vect_index)
+ tab->min_base_vect_el_value = comb_vect_index;
+ VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index;
+}
+
+/* Return number of out arcs of STATE. */
+static int
+out_state_arcs_num (state)
+ state_t state;
+{
+ int result;
+ arc_t arc;
+
+ result = 0;
+ for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
+ {
+ if (arc->insn == NULL)
+ abort ();
+ if (arc->insn->first_ainsn_with_given_equialence_num)
+ result++;
+ }
+ return result;
+}
+
+/* Compare number of possible transitions from the states. */
+static int
+compare_transition_els_num (state_ptr_1, state_ptr_2)
+ const void *state_ptr_1;
+ const void *state_ptr_2;
+{
+ int transition_els_num_1;
+ int transition_els_num_2;
+
+ transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
+ transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
+ if (transition_els_num_1 < transition_els_num_2)
+ return 1;
+ else if (transition_els_num_1 == transition_els_num_2)
+ return 0;
+ else
+ return -1;
+}
+
+/* The function adds element EL_VALUE to vector VECT for a table state
+ x AINSN. */
+static void
+add_vect_el (vect, ainsn, el_value)
+ vla_hwint_t *vect;
+ ainsn_t ainsn;
+ int el_value;
+{
+ int equiv_class_num;
+ int vect_index;
+
+ if (ainsn == NULL)
+ abort ();
+ equiv_class_num = ainsn->insn_equiv_class_num;
+ for (vect_index = VLA_HWINT_LENGTH (*vect);
+ vect_index <= equiv_class_num;
+ vect_index++)
+ VLA_HWINT_ADD (*vect, undefined_vect_el_value);
+ VLA_HWINT (*vect, equiv_class_num) = el_value;
+}
+
+/* This is for forming vector of states of an automaton. */
+static vla_ptr_t output_states_vect;
+
+/* The function is called by function pass_states. The function adds
+ STATE to `output_states_vect'. */
+static void
+add_states_vect_el (state)
+ state_t state;
+{
+ VLA_PTR_ADD (output_states_vect, state);
+}
+
+/* Form and output vectors (comb, check, base or full vector)
+ representing transition table of AUTOMATON. */
+static void
+output_trans_table (automaton)
+ automaton_t automaton;
+{
+ state_t *state_ptr;
+ arc_t arc;
+ vla_hwint_t transition_vect;
+
+ undefined_vect_el_value = automaton->achieved_states_num;
+ automaton->trans_table = create_state_ainsn_table (automaton);
+ /* Create vect of pointers to states ordered by num of transitions
+ from the state (state with the maximum num is the first). */
+ VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
+ pass_states (automaton, add_states_vect_el);
+ qsort (VLA_PTR_BEGIN (output_states_vect),
+ VLA_PTR_LENGTH (output_states_vect),
+ sizeof (state_t), compare_transition_els_num);
+ VLA_HWINT_CREATE (transition_vect, 500, "transition vector");
+ for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
+ state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
+ state_ptr++)
+ {
+ VLA_HWINT_NULLIFY (transition_vect);
+ for (arc = first_out_arc (*state_ptr);
+ arc != NULL;
+ arc = next_out_arc (arc))
+ {
+ if (arc->insn == NULL)
+ abort ();
+ if (arc->insn->first_ainsn_with_given_equialence_num)
+ add_vect_el (&transition_vect, arc->insn,
+ arc->to_state->order_state_num);
+ }
+ add_vect (automaton->trans_table, (*state_ptr)->order_state_num,
+ VLA_HWINT_BEGIN (transition_vect),
+ VLA_HWINT_LENGTH (transition_vect));
+ }
+ output_state_ainsn_table
+ (automaton->trans_table, (char *) "state transitions",
+ output_trans_full_vect_name, output_trans_comb_vect_name,
+ output_trans_check_vect_name, output_trans_base_vect_name);
+ VLA_PTR_DELETE (output_states_vect);
+ VLA_HWINT_DELETE (transition_vect);
+}
+
+/* Form and output vectors (comb, check, base or simple vect)
+ representing alts number table of AUTOMATON. The table is state x
+ ainsn -> number of possible alternative reservations by the
+ ainsn. */
+static void
+output_state_alts_table (automaton)
+ automaton_t automaton;
+{
+ state_t *state_ptr;
+ arc_t arc;
+ vla_hwint_t state_alts_vect;
+
+ undefined_vect_el_value = 0; /* no alts when transition is not possible */
+ automaton->state_alts_table = create_state_ainsn_table (automaton);
+ /* Create vect of pointers to states ordered by num of transitions
+ from the state (state with the maximum num is the first). */
+ VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
+ pass_states (automaton, add_states_vect_el);
+ qsort (VLA_PTR_BEGIN (output_states_vect),
+ VLA_PTR_LENGTH (output_states_vect),
+ sizeof (state_t), compare_transition_els_num);
+ /* Create base, comb, and check vectors. */
+ VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector");
+ for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
+ state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
+ state_ptr++)
+ {
+ VLA_HWINT_NULLIFY (state_alts_vect);
+ for (arc = first_out_arc (*state_ptr);
+ arc != NULL;
+ arc = next_out_arc (arc))
+ {
+ if (arc->insn == NULL)
+ abort ();
+ if (arc->insn->first_ainsn_with_given_equialence_num)
+ add_vect_el (&state_alts_vect, arc->insn, arc->state_alts);
+ }
+ add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num,
+ VLA_HWINT_BEGIN (state_alts_vect),
+ VLA_HWINT_LENGTH (state_alts_vect));
+ }
+ output_state_ainsn_table
+ (automaton->state_alts_table, (char *) "state insn alternatives",
+ output_state_alts_full_vect_name, output_state_alts_comb_vect_name,
+ output_state_alts_check_vect_name, output_state_alts_base_vect_name);
+ VLA_PTR_DELETE (output_states_vect);
+ VLA_HWINT_DELETE (state_alts_vect);
+}
+
+/* The current number of passing states to find minimal issue delay
+ value for an ainsn and state. */
+static int curr_state_pass_num;
+
+
+/* This recursive function passes states to find minimal issue delay
+ value for AINSN. The state being visited is STATE. The function
+ returns minimal issue delay value for AINSN in STATE or -1 if we
+ enter into a loop. */
+static int
+min_issue_delay_pass_states (state, ainsn)
+ state_t state;
+ ainsn_t ainsn;
+{
+ arc_t arc;
+ int min_insn_issue_delay, insn_issue_delay;
+
+ if (state->state_pass_num == curr_state_pass_num
+ || state->min_insn_issue_delay != -1)
+ /* We've entered into a loop or already have the correct value for
+ given state and ainsn. */
+ return state->min_insn_issue_delay;
+ state->state_pass_num = curr_state_pass_num;
+ min_insn_issue_delay = -1;
+ for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
+ if (arc->insn == ainsn)
+ {
+ min_insn_issue_delay = 0;
+ break;
+ }
+ else
+ {
+ insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
+ if (insn_issue_delay != -1)
+ {
+ if (arc->insn->insn_reserv_decl
+ == DECL_INSN_RESERV (advance_cycle_insn_decl))
+ insn_issue_delay++;
+ if (min_insn_issue_delay == -1
+ || min_insn_issue_delay > insn_issue_delay)
+ {
+ min_insn_issue_delay = insn_issue_delay;
+ if (insn_issue_delay == 0)
+ break;
+ }
+ }
+ }
+ return min_insn_issue_delay;
+}
+
+/* The function searches minimal issue delay value for AINSN in STATE.
+ The function can return negative value if we can not issue AINSN. We
+ will report about it later. */
+static int
+min_issue_delay (state, ainsn)
+ state_t state;
+ ainsn_t ainsn;
+{
+ curr_state_pass_num++;
+ state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
+ return state->min_insn_issue_delay;
+}
+
+/* The function initiates code for finding minimal issue delay values.
+ It should be called only once. */
+static void
+initiate_min_issue_delay_pass_states ()
+{
+ curr_state_pass_num = 0;
+}
+
+/* Form and output vectors representing minimal issue delay table of
+ AUTOMATON. The table is state x ainsn -> minimal issue delay of
+ the ainsn. */
+static void
+output_min_issue_delay_table (automaton)
+ automaton_t automaton;
+{
+ vla_hwint_t min_issue_delay_vect;
+ vla_hwint_t compressed_min_issue_delay_vect;
+ vect_el_t min_delay;
+ ainsn_t ainsn;
+ state_t *state_ptr;
+ int i;
+
+ /* Create vect of pointers to states ordered by num of transitions
+ from the state (state with the maximum num is the first). */
+ VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
+ pass_states (automaton, add_states_vect_el);
+ VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector");
+ VLA_HWINT_EXPAND (min_issue_delay_vect,
+ VLA_HWINT_LENGTH (output_states_vect)
+ * automaton->insn_equiv_classes_num);
+ for (i = 0;
+ i < ((int) VLA_HWINT_LENGTH (output_states_vect)
+ * automaton->insn_equiv_classes_num);
+ i++)
+ VLA_HWINT (min_issue_delay_vect, i) = 0;
+ automaton->max_min_delay = 0;
+ for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
+ if (ainsn->first_ainsn_with_given_equialence_num)
+ {
+ for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
+ state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
+ state_ptr++)
+ (*state_ptr)->min_insn_issue_delay = -1;
+ for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
+ state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
+ state_ptr++)
+ {
+ min_delay = min_issue_delay (*state_ptr, ainsn);
+ if (automaton->max_min_delay < min_delay)
+ automaton->max_min_delay = min_delay;
+ VLA_HWINT (min_issue_delay_vect,
+ (*state_ptr)->order_state_num
+ * automaton->insn_equiv_classes_num
+ + ainsn->insn_equiv_class_num) = min_delay;
+ }
+ }
+ fprintf (output_file, "/* Vector of min issue delay of insns.*/\n");
+ fprintf (output_file, "static const ");
+ output_range_type (output_file, 0, automaton->max_min_delay);
+ fprintf (output_file, " ");
+ output_min_issue_delay_vect_name (output_file, automaton);
+ fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
+ /* Compress the vector */
+ if (automaton->max_min_delay < 2)
+ automaton->min_issue_delay_table_compression_factor = 8;
+ else if (automaton->max_min_delay < 4)
+ automaton->min_issue_delay_table_compression_factor = 4;
+ else if (automaton->max_min_delay < 16)
+ automaton->min_issue_delay_table_compression_factor = 2;
+ else
+ automaton->min_issue_delay_table_compression_factor = 1;
+ VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500,
+ "compressed min issue delay vector");
+ VLA_HWINT_EXPAND (compressed_min_issue_delay_vect,
+ (VLA_HWINT_LENGTH (min_issue_delay_vect)
+ + automaton->min_issue_delay_table_compression_factor
+ - 1)
+ / automaton->min_issue_delay_table_compression_factor);
+ for (i = 0;
+ i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect);
+ i++)
+ VLA_HWINT (compressed_min_issue_delay_vect, i) = 0;
+ for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++)
+ VLA_HWINT (compressed_min_issue_delay_vect,
+ i / automaton->min_issue_delay_table_compression_factor)
+ |= (VLA_HWINT (min_issue_delay_vect, i)
+ << (8 - (i % automaton->min_issue_delay_table_compression_factor
+ + 1)
+ * (8 / automaton->min_issue_delay_table_compression_factor)));
+ output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect),
+ VLA_HWINT_LENGTH (compressed_min_issue_delay_vect));
+ fprintf (output_file, "};\n\n");
+ VLA_PTR_DELETE (output_states_vect);
+ VLA_HWINT_DELETE (min_issue_delay_vect);
+ VLA_HWINT_DELETE (compressed_min_issue_delay_vect);
+}
+
+#ifndef NDEBUG
+/* Number of states which contains transition only by advancing cpu
+ cycle. */
+static int locked_states_num;
+#endif
+
+/* Form and output vector representing the locked states of
+ AUTOMATON. */
+static void
+output_dead_lock_vect (automaton)
+ automaton_t automaton;
+{
+ state_t *state_ptr;
+ arc_t arc;
+ vla_hwint_t dead_lock_vect;
+
+ /* Create vect of pointers to states ordered by num of
+ transitions from the state (state with the maximum num is the
+ first). */
+ VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
+ pass_states (automaton, add_states_vect_el);
+ VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector");
+ VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect));
+ for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
+ state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
+ state_ptr++)
+ {
+ arc = first_out_arc (*state_ptr);
+ if (arc == NULL)
+ abort ();
+ VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)
+ = (next_out_arc (arc) == NULL
+ && (arc->insn->insn_reserv_decl
+ == DECL_INSN_RESERV (advance_cycle_insn_decl)) ? 1 : 0);
+#ifndef NDEBUG
+ if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num))
+ locked_states_num++;
+#endif
+ }
+ fprintf (output_file, "/* Vector for locked state flags. */\n");
+ fprintf (output_file, "static const ");
+ output_range_type (output_file, 0, 1);
+ fprintf (output_file, " ");
+ output_dead_lock_vect_name (output_file, automaton);
+ fprintf (output_file, "[] = {\n");
+ output_vect (VLA_HWINT_BEGIN (dead_lock_vect),
+ VLA_HWINT_LENGTH (dead_lock_vect));
+ fprintf (output_file, "};\n\n");
+ VLA_HWINT_DELETE (dead_lock_vect);
+ VLA_PTR_DELETE (output_states_vect);
+}
+
+/* Form and output vector representing reserved units of the states of
+ AUTOMATON. */
+static void
+output_reserved_units_table (automaton)
+ automaton_t automaton;
+{
+ state_t *curr_state_ptr;
+ vla_hwint_t reserved_units_table;
+ size_t state_byte_size;
+ int i;
+
+ /* Create vect of pointers to states. */
+ VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
+ pass_states (automaton, add_states_vect_el);
+ /* Create vector. */
+ VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector");
+ state_byte_size = (description->query_units_num + 7) / 8;
+ VLA_HWINT_EXPAND (reserved_units_table,
+ VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
+ for (i = 0;
+ i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
+ i++)
+ VLA_HWINT (reserved_units_table, i) = 0;
+ for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect);
+ curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
+ curr_state_ptr++)
+ {
+ for (i = 0; i < description->units_num; i++)
+ if (units_array [i]->query_p)
+ {
+ if (test_unit_reserv ((*curr_state_ptr)->reservs, 0, i))
+ VLA_HWINT (reserved_units_table,
+ (*curr_state_ptr)->order_state_num * state_byte_size
+ + units_array [i]->query_num / 8)
+ += (1 << (units_array [i]->query_num % 8));
+ }
+ }
+ fprintf (output_file, "/* Vector for reserved units of states. */\n");
+ fprintf (output_file, "static const ");
+ output_range_type (output_file, 0, 255);
+ fprintf (output_file, " ");
+ output_reserved_units_table_name (output_file, automaton);
+ fprintf (output_file, "[] = {\n");
+ output_vect (VLA_HWINT_BEGIN (reserved_units_table),
+ VLA_HWINT_LENGTH (reserved_units_table));
+ fprintf (output_file, "};\n\n");
+ VLA_HWINT_DELETE (reserved_units_table);
+ VLA_PTR_DELETE (output_states_vect);
+}
+
+/* The function outputs all tables representing DFA(s) used for fast
+ pipeline hazards recognition. */
+static void
+output_tables ()
+{
+ automaton_t automaton;
+
+#ifndef NDEBUG
+ locked_states_num = 0;
+#endif
+ initiate_min_issue_delay_pass_states ();
+ for (automaton = description->first_automaton;
+ automaton != NULL;
+ automaton = automaton->next_automaton)
+ {
+ output_translate_vect (automaton);
+ output_trans_table (automaton);
+ fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
+ output_state_alts_table (automaton);
+ fprintf (output_file, "\n#endif /* #if %s */\n\n",
+ AUTOMATON_STATE_ALTS_MACRO_NAME);
+ output_min_issue_delay_table (automaton);
+ output_dead_lock_vect (automaton);
+ if (no_minimization_flag)
+ {
+ fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
+ output_reserved_units_table (automaton);
+ fprintf (output_file, "\n#endif /* #if %s */\n\n",
+ CPU_UNITS_QUERY_MACRO_NAME);
+ }
+ }
+ fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
+ DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
+}
+
+/* The function outputs definition and value of PHR interface variable
+ `max_insn_queue_index'. Its value is not less than maximal queue
+ length needed for the insn scheduler. */
+static void
+output_max_insn_queue_index_def ()
+{
+ int i, max, latency;
+ decl_t decl;
+
+ max = description->max_insn_reserv_cycles;
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
+ {
+ latency = DECL_INSN_RESERV (decl)->default_latency;
+ if (latency > max)
+ max = latency;
+ }
+ else if (decl->mode == dm_bypass)
+ {
+ latency = DECL_BYPASS (decl)->latency;
+ if (latency > max)
+ max = latency;
+ }
+ }
+ for (i = 0; (1 << i) <= max; i++)
+ ;
+ if (i < 0)
+ abort ();
+ fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1);
+}
+
+
+/* The function outputs switch cases for insn reseravtions using
+ function *output_automata_list_code. */
+static void
+output_insn_code_cases (output_automata_list_code)
+ void (*output_automata_list_code) PARAMS ((automata_list_el_t));
+{
+ decl_t decl, decl2;
+ int i, j;
+
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv)
+ DECL_INSN_RESERV (decl)->processed_p = FALSE;
+ }
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv
+ && !DECL_INSN_RESERV (decl)->processed_p)
+ {
+ for (j = i; j < description->decls_num; j++)
+ {
+ decl2 = description->decls [j];
+ if (decl2->mode == dm_insn_reserv
+ && (DECL_INSN_RESERV (decl2)->important_automata_list
+ == DECL_INSN_RESERV (decl)->important_automata_list))
+ {
+ DECL_INSN_RESERV (decl2)->processed_p = TRUE;
+ fprintf (output_file, " case %d: /* %s */\n",
+ DECL_INSN_RESERV (decl2)->insn_num,
+ DECL_INSN_RESERV (decl2)->name);
+ }
+ }
+ (*output_automata_list_code)
+ (DECL_INSN_RESERV (decl)->important_automata_list);
+ }
+ }
+}
+
+
+/* The function outputs a code for evaluation of a minimal delay of
+ issue of insns which have reservations in given AUTOMATA_LIST. */
+static void
+output_automata_list_min_issue_delay_code (automata_list)
+ automata_list_el_t automata_list;
+{
+ automata_list_el_t el;
+ automaton_t automaton;
+
+ for (el = automata_list; el != NULL; el = el->next_automata_list_el)
+ {
+ automaton = el->automaton;
+ fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
+ output_min_issue_delay_vect_name (output_file, automaton);
+ fprintf (output_file,
+ (automaton->min_issue_delay_table_compression_factor != 1
+ ? " [(" : " ["));
+ output_translate_vect_name (output_file, automaton);
+ fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
+ fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, automaton);
+ fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
+ if (automaton->min_issue_delay_table_compression_factor == 1)
+ fprintf (output_file, "];\n");
+ else
+ {
+ fprintf (output_file, ") / %d];\n",
+ automaton->min_issue_delay_table_compression_factor);
+ fprintf (output_file, " %s = (%s >> (8 - (",
+ TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
+ output_translate_vect_name (output_file, automaton);
+ fprintf
+ (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
+ INTERNAL_INSN_CODE_NAME,
+ automaton->min_issue_delay_table_compression_factor,
+ 8 / automaton->min_issue_delay_table_compression_factor,
+ (1 << (8 / automaton->min_issue_delay_table_compression_factor))
+ - 1);
+ }
+ if (el == automata_list)
+ fprintf (output_file, " %s = %s;\n",
+ RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
+ else
+ {
+ fprintf (output_file, " if (%s > %s)\n",
+ TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
+ fprintf (output_file, " %s = %s;\n",
+ RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
+ }
+ }
+ fprintf (output_file, " break;\n\n");
+}
+
+/* Output function `internal_min_issue_delay'. */
+static void
+output_internal_min_issue_delay_func ()
+{
+ fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
+ INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, CHIP_NAME);
+ fprintf (output_file,
+ "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
+ INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
+ CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
+ CHIP_PARAMETER_NAME);
+ fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
+ TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
+ fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
+ output_insn_code_cases (output_automata_list_min_issue_delay_code);
+ fprintf (output_file,
+ "\n default:\n %s = -1;\n break;\n }\n",
+ RESULT_VARIABLE_NAME);
+ fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
+ fprintf (output_file, "}\n\n");
+}
+
+/* The function outputs a code changing state after issue of insns
+ which have reservations in given AUTOMATA_LIST. */
+static void
+output_automata_list_transition_code (automata_list)
+ automata_list_el_t automata_list;
+{
+ automata_list_el_t el, next_el;
+
+ fprintf (output_file, " {\n");
+ if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
+ for (el = automata_list;; el = next_el)
+ {
+ next_el = el->next_automata_list_el;
+ if (next_el == NULL)
+ break;
+ fprintf (output_file, " ");
+ output_state_member_type (output_file, el->automaton);
+ fprintf (output_file, " ");
+ output_temp_chip_member_name (output_file, el->automaton);
+ fprintf (output_file, ";\n");
+ }
+ for (el = automata_list; el != NULL; el = el->next_automata_list_el)
+ if (comb_vect_p (el->automaton->trans_table))
+ {
+ fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
+ output_trans_base_vect_name (output_file, el->automaton);
+ fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, el->automaton);
+ fprintf (output_file, "] + ");
+ output_translate_vect_name (output_file, el->automaton);
+ fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
+ fprintf (output_file, " if (");
+ output_trans_check_vect_name (output_file, el->automaton);
+ fprintf (output_file, " [%s] != %s->",
+ TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, el->automaton);
+ fprintf (output_file, ")\n");
+ fprintf (output_file, " return %s (%s, %s);\n",
+ INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
+ CHIP_PARAMETER_NAME);
+ fprintf (output_file, " else\n");
+ fprintf (output_file, " ");
+ if (el->next_automata_list_el != NULL)
+ output_temp_chip_member_name (output_file, el->automaton);
+ else
+ {
+ fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, el->automaton);
+ }
+ fprintf (output_file, " = ");
+ output_trans_comb_vect_name (output_file, el->automaton);
+ fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
+ }
+ else
+ {
+ fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
+ output_trans_full_vect_name (output_file, el->automaton);
+ fprintf (output_file, " [");
+ output_translate_vect_name (output_file, el->automaton);
+ fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
+ fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, el->automaton);
+ fprintf (output_file, " * %d];\n",
+ el->automaton->insn_equiv_classes_num);
+ fprintf (output_file, " if (%s >= %d)\n",
+ TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
+ fprintf (output_file, " return %s (%s, %s);\n",
+ INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
+ CHIP_PARAMETER_NAME);
+ fprintf (output_file, " else\n ");
+ if (el->next_automata_list_el != NULL)
+ output_temp_chip_member_name (output_file, el->automaton);
+ else
+ {
+ fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, el->automaton);
+ }
+ fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
+ }
+ if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
+ for (el = automata_list;; el = next_el)
+ {
+ next_el = el->next_automata_list_el;
+ if (next_el == NULL)
+ break;
+ fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, el->automaton);
+ fprintf (output_file, " = ");
+ output_temp_chip_member_name (output_file, el->automaton);
+ fprintf (output_file, ";\n");
+ }
+ fprintf (output_file, " return -1;\n");
+ fprintf (output_file, " }\n");
+}
+
+/* Output function `internal_state_transition'. */
+static void
+output_internal_trans_func ()
+{
+ fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
+ INTERNAL_TRANSITION_FUNC_NAME, CHIP_NAME);
+ fprintf (output_file,
+ "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
+ INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
+ CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME,
+ CHIP_NAME, CHIP_PARAMETER_NAME);
+ fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
+ fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
+ output_insn_code_cases (output_automata_list_transition_code);
+ fprintf (output_file, "\n default:\n return -1;\n }\n");
+ fprintf (output_file, "}\n\n");
+}
+
+/* Output code
+
+ if (insn != 0)
+ {
+ insn_code = dfa_insn_code (insn);
+ if (insn_code > DFA__ADVANCE_CYCLE)
+ return code;
+ }
+ else
+ insn_code = DFA__ADVANCE_CYCLE;
+
+ where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
+ code denotes CODE. */
+static void
+output_internal_insn_code_evaluation (insn_name, insn_code_name, code)
+ const char *insn_name;
+ const char *insn_code_name;
+ int code;
+{
+ fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
+ fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
+ DFA_INSN_CODE_FUNC_NAME, insn_name);
+ fprintf (output_file, " if (%s > %s)\n return %d;\n",
+ insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
+ fprintf (output_file, " }\n else\n %s = %s;\n\n",
+ insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
+}
+
+
+/* The function outputs function `dfa_insn_code'. */
+static void
+output_dfa_insn_code_func ()
+{
+ fprintf (output_file, "#ifdef __GNUC__\n__inline__\n#endif\n");
+ fprintf (output_file, "static int %s PARAMS ((rtx));\n",
+ DFA_INSN_CODE_FUNC_NAME);
+ fprintf (output_file, "static int\n%s (%s)\n\trtx %s;\n",
+ DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME, INSN_PARAMETER_NAME);
+ fprintf (output_file, "{\n int %s;\n int %s;\n\n",
+ INTERNAL_INSN_CODE_NAME, TEMPORARY_VARIABLE_NAME);
+ fprintf (output_file, " if (INSN_UID (%s) >= %s)\n {\n",
+ INSN_PARAMETER_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
+ fprintf (output_file, " %s = %s;\n %s = 2 * INSN_UID (%s);\n",
+ TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
+ DFA_INSN_CODES_LENGTH_VARIABLE_NAME, INSN_PARAMETER_NAME);
+ fprintf (output_file, " %s = xrealloc (%s, %s * sizeof (int));\n",
+ DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
+ DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
+ fprintf (output_file,
+ " for (; %s < %s; %s++)\n %s [%s] = -1;\n }\n",
+ TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
+ TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
+ TEMPORARY_VARIABLE_NAME);
+ fprintf (output_file, " if ((%s = %s [INSN_UID (%s)]) < 0)\n {\n",
+ INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
+ INSN_PARAMETER_NAME);
+ fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
+ INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
+ fprintf (output_file, " %s [INSN_UID (%s)] = %s;\n",
+ DFA_INSN_CODES_VARIABLE_NAME, INSN_PARAMETER_NAME,
+ INTERNAL_INSN_CODE_NAME);
+ fprintf (output_file, " }\n return %s;\n}\n\n",
+ INTERNAL_INSN_CODE_NAME);
+}
+
+/* The function outputs PHR interface function `state_transition'. */
+static void
+output_trans_func ()
+{
+ fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
+ TRANSITION_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
+ STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
+ fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
+ output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
+ INTERNAL_INSN_CODE_NAME, -1);
+ fprintf (output_file, " return %s (%s, %s);\n}\n\n",
+ INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
+}
+
+/* The function outputs a code for evaluation of alternative states
+ number for insns which have reservations in given AUTOMATA_LIST. */
+static void
+output_automata_list_state_alts_code (automata_list)
+ automata_list_el_t automata_list;
+{
+ automata_list_el_t el;
+ automaton_t automaton;
+
+ fprintf (output_file, " {\n");
+ for (el = automata_list; el != NULL; el = el->next_automata_list_el)
+ if (comb_vect_p (el->automaton->state_alts_table))
+ {
+ fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
+ break;
+ }
+ for (el = automata_list; el != NULL; el = el->next_automata_list_el)
+ {
+ automaton = el->automaton;
+ if (comb_vect_p (automaton->state_alts_table))
+ {
+ fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
+ output_state_alts_base_vect_name (output_file, automaton);
+ fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, automaton);
+ fprintf (output_file, "] + ");
+ output_translate_vect_name (output_file, automaton);
+ fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
+ fprintf (output_file, " if (");
+ output_state_alts_check_vect_name (output_file, automaton);
+ fprintf (output_file, " [%s] != %s->",
+ TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, automaton);
+ fprintf (output_file, ")\n");
+ fprintf (output_file, " return 0;\n");
+ fprintf (output_file, " else\n");
+ fprintf (output_file,
+ (el == automata_list
+ ? " %s = " : " %s += "),
+ RESULT_VARIABLE_NAME);
+ output_state_alts_comb_vect_name (output_file, automaton);
+ fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
+ }
+ else
+ {
+ fprintf (output_file,
+ (el == automata_list
+ ? "\n %s = " : " %s += "),
+ RESULT_VARIABLE_NAME);
+ output_state_alts_full_vect_name (output_file, automaton);
+ fprintf (output_file, " [");
+ output_translate_vect_name (output_file, automaton);
+ fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
+ fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, automaton);
+ fprintf (output_file, " * %d];\n",
+ automaton->insn_equiv_classes_num);
+ }
+ }
+ fprintf (output_file, " break;\n }\n\n");
+}
+
+/* Output function `internal_state_alts'. */
+static void
+output_internal_state_alts_func ()
+{
+ fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
+ INTERNAL_STATE_ALTS_FUNC_NAME, CHIP_NAME);
+ fprintf (output_file,
+ "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
+ INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
+ CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
+ CHIP_PARAMETER_NAME);
+ fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
+ fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
+ output_insn_code_cases (output_automata_list_state_alts_code);
+ fprintf (output_file,
+ "\n default:\n %s = 0;\n break;\n }\n",
+ RESULT_VARIABLE_NAME);
+ fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
+ fprintf (output_file, "}\n\n");
+}
+
+/* The function outputs PHR interface function `state_alts'. */
+static void
+output_state_alts_func ()
+{
+ fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
+ STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
+ STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
+ fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
+ output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
+ INTERNAL_INSN_CODE_NAME, 0);
+ fprintf (output_file, " return %s (%s, %s);\n}\n\n",
+ INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
+}
+
+/* Output function `min_issue_delay'. */
+static void
+output_min_issue_delay_func ()
+{
+ fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
+ MIN_ISSUE_DELAY_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
+ STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
+ fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
+ fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
+ fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
+ DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
+ fprintf (output_file, " if (%s > %s)\n return 0;\n",
+ INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
+ fprintf (output_file, " }\n else\n %s = %s;\n",
+ INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
+ fprintf (output_file, "\n return %s (%s, %s);\n",
+ INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
+ STATE_NAME);
+ fprintf (output_file, "}\n\n");
+}
+
+/* Output function `internal_dead_lock'. */
+static void
+output_internal_dead_lock_func ()
+{
+ automaton_t automaton;
+
+ fprintf (output_file, "static int %s PARAMS ((struct %s *));\n",
+ INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME);
+ fprintf (output_file, "static int\n%s (%s)\n\tstruct %s *%s;\n",
+ INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_PARAMETER_NAME, CHIP_NAME,
+ CHIP_PARAMETER_NAME);
+ fprintf (output_file, "{\n");
+ for (automaton = description->first_automaton;
+ automaton != NULL;
+ automaton = automaton->next_automaton)
+ {
+ fprintf (output_file, " if (");
+ output_dead_lock_vect_name (output_file, automaton);
+ fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
+ output_chip_member_name (output_file, automaton);
+ fprintf (output_file, "])\n return 1/* TRUE */;\n");
+ }
+ fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
+}
+
+/* The function outputs PHR interface function `state_dead_lock_p'. */
+static void
+output_dead_lock_func ()
+{
+ fprintf (output_file, "int\n%s (%s)\n\t%s %s;\n",
+ DEAD_LOCK_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
+ fprintf (output_file, "{\n return %s (%s);\n}\n\n",
+ INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
+}
+
+/* Output function `internal_reset'. */
+static void
+output_internal_reset_func ()
+{
+ fprintf (output_file, "static void %s PARAMS ((struct %s *));\n",
+ INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
+ fprintf (output_file, "static void\n%s (%s)\n\tstruct %s *%s;\n",
+ INTERNAL_RESET_FUNC_NAME, CHIP_PARAMETER_NAME,
+ CHIP_NAME, CHIP_PARAMETER_NAME);
+ fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
+ CHIP_PARAMETER_NAME, CHIP_NAME);
+}
+
+/* The function outputs PHR interface function `state_size'. */
+static void
+output_size_func ()
+{
+ fprintf (output_file, "int\n%s ()\n", SIZE_FUNC_NAME);
+ fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
+}
+
+/* The function outputs PHR interface function `state_reset'. */
+static void
+output_reset_func ()
+{
+ fprintf (output_file, "void\n%s (%s)\n\t %s %s;\n",
+ RESET_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
+ fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
+ STATE_NAME);
+}
+
+/* Output function `min_insn_conflict_delay'. */
+static void
+output_min_insn_conflict_delay_func ()
+{
+ fprintf (output_file,
+ "int\n%s (%s, %s, %s)\n\t%s %s;\n\trtx %s;\n\trtx %s;\n",
+ MIN_INSN_CONFLICT_DELAY_FUNC_NAME,
+ STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
+ STATE_TYPE_NAME, STATE_NAME,
+ INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
+ fprintf (output_file, "{\n struct %s %s;\n int %s, %s;\n",
+ CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
+ INTERNAL_INSN2_CODE_NAME);
+ output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
+ INTERNAL_INSN_CODE_NAME, 0);
+ output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
+ INTERNAL_INSN2_CODE_NAME, 0);
+ fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
+ CHIP_NAME, STATE_NAME, CHIP_NAME);
+ fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
+ fprintf (output_file, " if (%s (%s, &%s) > 0)\n abort ();\n",
+ INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
+ fprintf (output_file, " return %s (%s, &%s);\n",
+ INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
+ CHIP_NAME);
+ fprintf (output_file, "}\n\n");
+}
+
+/* Output function `internal_insn_latency'. */
+static void
+output_internal_insn_latency_func ()
+{
+ decl_t decl;
+ struct bypass_decl *bypass;
+ int i;
+
+ fprintf (output_file, "static int %s PARAMS ((int, int, rtx, rtx));\n",
+ INTERNAL_INSN_LATENCY_FUNC_NAME);
+ fprintf (output_file, "static int\n%s (%s, %s, %s, %s)",
+ INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
+ INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
+ INSN2_PARAMETER_NAME);
+ fprintf (output_file, "\n\tint %s;\n\tint %s;\n",
+ INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
+ fprintf (output_file,
+ "\trtx %s ATTRIBUTE_UNUSED;\n\trtx %s ATTRIBUTE_UNUSED;\n",
+ INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
+ fprintf (output_file, "{\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv)
+ {
+ fprintf (output_file, " case %d:\n",
+ DECL_INSN_RESERV (decl)->insn_num);
+ if (DECL_INSN_RESERV (decl)->bypass_list == NULL)
+ fprintf (output_file, " return (%s != %s ? %d : 0);\n",
+ INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
+ DECL_INSN_RESERV (decl)->default_latency);
+ else
+ {
+ fprintf (output_file, " switch (%s)\n {\n",
+ INTERNAL_INSN2_CODE_NAME);
+ for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
+ bypass != NULL;
+ bypass = bypass->next)
+ {
+ fprintf (output_file, " case %d:\n",
+ bypass->in_insn_reserv->insn_num);
+ if (bypass->bypass_guard_name == NULL)
+ fprintf (output_file, " return %d;\n",
+ bypass->latency);
+ else
+ fprintf (output_file,
+ " return (%s (%s, %s) ? %d : %d);\n",
+ bypass->bypass_guard_name, INSN_PARAMETER_NAME,
+ INSN2_PARAMETER_NAME, bypass->latency,
+ DECL_INSN_RESERV (decl)->default_latency);
+ }
+ fprintf (output_file, " default:\n");
+ fprintf (output_file,
+ " return (%s != %s ? %d : 0);\n }\n",
+ INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
+ DECL_INSN_RESERV (decl)->default_latency);
+
+ }
+ }
+ }
+ fprintf (output_file, " default:\n return 0;\n }\n}\n\n");
+}
+
+/* The function outputs PHR interface function `insn_latency'. */
+static void
+output_insn_latency_func ()
+{
+ fprintf (output_file, "int\n%s (%s, %s)\n\trtx %s;\n\trtx %s;\n",
+ INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
+ INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
+ fprintf (output_file, "{\n int %s, %s;\n",
+ INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
+ output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
+ INTERNAL_INSN_CODE_NAME, 0);
+ output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
+ INTERNAL_INSN2_CODE_NAME, 0);
+ fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
+ INTERNAL_INSN_LATENCY_FUNC_NAME,
+ INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
+ INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
+}
+
+/* The function outputs PHR interface function `print_reservation'. */
+static void
+output_print_reservation_func ()
+{
+ decl_t decl;
+ int i;
+
+ fprintf (output_file, "void\n%s (%s, %s)\n\tFILE *%s;\n\trtx %s;\n",
+ PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
+ INSN_PARAMETER_NAME, FILE_PARAMETER_NAME,
+ INSN_PARAMETER_NAME);
+ fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
+ fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
+ fprintf (output_file, " %s = %s (%s);\n",
+ INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
+ INSN_PARAMETER_NAME);
+ fprintf (output_file, " if (%s > %s)\n",
+ INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
+ fprintf (output_file, " {\n fprintf (%s, \"%s\");\n",
+ FILE_PARAMETER_NAME, NOTHING_NAME);
+ fprintf (output_file, " return;\n }\n");
+ fprintf (output_file, " }\n else\n");
+ fprintf (output_file,
+ " {\n fprintf (%s, \"%s\");\n return;\n }\n",
+ FILE_PARAMETER_NAME, NOTHING_NAME);
+ fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
+ {
+ fprintf (output_file,
+ " case %d:\n", DECL_INSN_RESERV (decl)->insn_num);
+ fprintf (output_file,
+ " fprintf (%s, \"%s\");\n break;\n",
+ FILE_PARAMETER_NAME,
+ regexp_representation (DECL_INSN_RESERV (decl)->regexp));
+ finish_regexp_representation ();
+ }
+ }
+ fprintf (output_file, " default:\n fprintf (%s, \"%s\");\n }\n",
+ FILE_PARAMETER_NAME, NOTHING_NAME);
+ fprintf (output_file, "}\n\n");
+}
+
+/* The following function is used to sort unit declaration by their
+ names. */
+static int
+units_cmp (unit1, unit2)
+ const void *unit1, *unit2;
+{
+ const unit_decl_t u1 = *(unit_decl_t *) unit1;
+ const unit_decl_t u2 = *(unit_decl_t *) unit2;
+
+ return strcmp (u1->name, u2->name);
+}
+
+/* The following macro value is name of struct containing unit name
+ and unit code. */
+#define NAME_CODE_STRUCT_NAME "name_code"
+
+/* The following macro value is name of table of struct name_code. */
+#define NAME_CODE_TABLE_NAME "name_code_table"
+
+/* The following macro values are member names for struct name_code. */
+#define NAME_MEMBER_NAME "name"
+#define CODE_MEMBER_NAME "code"
+
+/* The following macro values are local variable names for function
+ `get_cpu_unit_code'. */
+#define CMP_VARIABLE_NAME "cmp"
+#define LOW_VARIABLE_NAME "l"
+#define MIDDLE_VARIABLE_NAME "m"
+#define HIGH_VARIABLE_NAME "h"
+
+/* The following function outputs function to obtain internal cpu unit
+ code by the cpu unit name. */
+static void
+output_get_cpu_unit_code_func ()
+{
+ int i;
+ unit_decl_t *units;
+
+ fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
+ GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
+ CPU_UNIT_NAME_PARAMETER_NAME);
+ fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
+ NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
+ fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
+ LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
+ fprintf (output_file, " static struct %s %s [] =\n {\n",
+ NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
+ units = (unit_decl_t *) xmalloc (sizeof (unit_decl_t)
+ * description->units_num);
+ memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
+ qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
+ for (i = 0; i < description->units_num; i++)
+ if (units [i]->query_p)
+ fprintf (output_file, " {\"%s\", %d},\n",
+ units[i]->name, units[i]->query_num);
+ fprintf (output_file, " };\n\n");
+ fprintf (output_file, " /* The following is binary search: */\n");
+ fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
+ fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
+ HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
+ fprintf (output_file, " while (%s <= %s)\n {\n",
+ LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
+ fprintf (output_file, " %s = (%s + %s) / 2;\n",
+ MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
+ fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
+ CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
+ NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
+ fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
+ fprintf (output_file, " %s = %s - 1;\n",
+ HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
+ fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
+ fprintf (output_file, " %s = %s + 1;\n",
+ LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
+ fprintf (output_file, " else\n");
+ fprintf (output_file, " return %s [%s].%s;\n }\n",
+ NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
+ fprintf (output_file, " return -1;\n}\n\n");
+ free (units);
+}
+
+/* The following function outputs function to check reservation of cpu
+ unit (its internal code will be passed as the function argument) in
+ given cpu state. */
+static void
+output_cpu_unit_reservation_p ()
+{
+ automaton_t automaton;
+
+ fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
+ CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME,
+ CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME,
+ CPU_CODE_PARAMETER_NAME);
+ fprintf (output_file, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
+ CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
+ description->query_units_num);
+ for (automaton = description->first_automaton;
+ automaton != NULL;
+ automaton = automaton->next_automaton)
+ {
+ fprintf (output_file, " if ((");
+ output_reserved_units_table_name (output_file, automaton);
+ fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
+ output_chip_member_name (output_file, automaton);
+ fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
+ (description->query_units_num + 7) / 8,
+ CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
+ fprintf (output_file, " return 1;\n");
+ }
+ fprintf (output_file, " return 0;\n}\n\n");
+}
+
+/* The function outputs PHR interface function `dfa_start'. */
+static void
+output_dfa_start_func ()
+{
+ fprintf (output_file,
+ "void\n%s ()\n{\n int %s;\n\n %s = get_max_uid ();\n",
+ DFA_START_FUNC_NAME, I_VARIABLE_NAME,
+ DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
+ fprintf (output_file, " %s = (int *) xmalloc (%s * sizeof (int));\n",
+ DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
+ fprintf (output_file,
+ " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
+ I_VARIABLE_NAME, I_VARIABLE_NAME,
+ DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
+ DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
+}
+
+/* The function outputs PHR interface function `dfa_finish'. */
+static void
+output_dfa_finish_func ()
+{
+ fprintf (output_file, "void\n%s ()\n{\n free (%s);\n}\n\n",
+ DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
+}
+
+
+
+/* The page contains code for output description file (readable
+ representation of original description and generated DFA(s). */
+
+/* The function outputs string representation of IR reservation. */
+static void
+output_regexp (regexp)
+ regexp_t regexp;
+{
+ fprintf (output_description_file, "%s", regexp_representation (regexp));
+ finish_regexp_representation ();
+}
+
+/* Output names of units in LIST separated by comma. */
+static void
+output_unit_set_el_list (list)
+ unit_set_el_t list;
+{
+ unit_set_el_t el;
+
+ for (el = list; el != NULL; el = el->next_unit_set_el)
+ {
+ if (el != list)
+ fprintf (output_description_file, ",");
+ fprintf (output_description_file, "%s", el->unit_decl->name);
+ }
+}
+
+/* The function outputs string representation of IR define_reservation
+ and define_insn_reservation. */
+static void
+output_description ()
+{
+ decl_t decl;
+ int i;
+
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_unit)
+ {
+ if (DECL_UNIT (decl)->excl_list != NULL)
+ {
+ fprintf (output_description_file, "unit %s exlusion_set: ",
+ DECL_UNIT (decl)->name);
+ output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
+ fprintf (output_description_file, "\n");
+ }
+ if (DECL_UNIT (decl)->presence_list != NULL)
+ {
+ fprintf (output_description_file, "unit %s presence_set: ",
+ DECL_UNIT (decl)->name);
+ output_unit_set_el_list (DECL_UNIT (decl)->presence_list);
+ fprintf (output_description_file, "\n");
+ }
+ if (DECL_UNIT (decl)->absence_list != NULL)
+ {
+ fprintf (output_description_file, "unit %s absence_set: ",
+ DECL_UNIT (decl)->name);
+ output_unit_set_el_list (DECL_UNIT (decl)->absence_list);
+ fprintf (output_description_file, "\n");
+ }
+ }
+ }
+ fprintf (output_description_file, "\n");
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_reserv)
+ {
+ fprintf (output_description_file, "reservation ");
+ fprintf (output_description_file, DECL_RESERV (decl)->name);
+ fprintf (output_description_file, ": ");
+ output_regexp (DECL_RESERV (decl)->regexp);
+ fprintf (output_description_file, "\n");
+ }
+ else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
+ {
+ fprintf (output_description_file, "insn reservation %s ",
+ DECL_INSN_RESERV (decl)->name);
+ print_rtl (output_description_file,
+ DECL_INSN_RESERV (decl)->condexp);
+ fprintf (output_description_file, ": ");
+ output_regexp (DECL_INSN_RESERV (decl)->regexp);
+ fprintf (output_description_file, "\n");
+ }
+ else if (decl->mode == dm_bypass)
+ fprintf (output_description_file, "bypass %d %s %s\n",
+ DECL_BYPASS (decl)->latency,
+ DECL_BYPASS (decl)->out_insn_name,
+ DECL_BYPASS (decl)->in_insn_name);
+ }
+ fprintf (output_description_file, "\n\f\n");
+}
+
+/* The function outputs name of AUTOMATON. */
+static void
+output_automaton_name (f, automaton)
+ FILE *f;
+ automaton_t automaton;
+{
+ if (automaton->corresponding_automaton_decl == NULL)
+ fprintf (f, "#%d", automaton->automaton_order_num);
+ else
+ fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
+}
+
+/* Maximal length of line for pretty printing into description
+ file. */
+#define MAX_LINE_LENGTH 70
+
+/* The function outputs units name belonging to AUTOMATON. */
+static void
+output_automaton_units (automaton)
+ automaton_t automaton;
+{
+ decl_t decl;
+ char *name;
+ int curr_line_length;
+ int there_is_an_automaton_unit;
+ int i;
+
+ fprintf (output_description_file, "\n Coresponding units:\n");
+ fprintf (output_description_file, " ");
+ curr_line_length = 4;
+ there_is_an_automaton_unit = 0;
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_unit
+ && (DECL_UNIT (decl)->corresponding_automaton_num
+ == automaton->automaton_order_num))
+ {
+ there_is_an_automaton_unit = 1;
+ name = DECL_UNIT (decl)->name;
+ if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
+ {
+ curr_line_length = strlen (name) + 4;
+ fprintf (output_description_file, "\n ");
+ }
+ else
+ {
+ curr_line_length += strlen (name) + 1;
+ fprintf (output_description_file, " ");
+ }
+ fprintf (output_description_file, name);
+ }
+ }
+ if (!there_is_an_automaton_unit)
+ fprintf (output_description_file, "<None>");
+ fprintf (output_description_file, "\n\n");
+}
+
+/* The following variable is used for forming array of all possible cpu unit
+ reservations described by the current DFA state. */
+static vla_ptr_t state_reservs;
+
+/* The function forms `state_reservs' for STATE. */
+static void
+add_state_reservs (state)
+ state_t state;
+{
+ alt_state_t curr_alt_state;
+ reserv_sets_t reservs;
+
+ if (state->component_states != NULL)
+ for (curr_alt_state = state->component_states;
+ curr_alt_state != NULL;
+ curr_alt_state = curr_alt_state->next_sorted_alt_state)
+ add_state_reservs (curr_alt_state->state);
+ else
+ {
+ reservs = state->reservs;
+ VLA_PTR_ADD (state_reservs, reservs);
+ }
+}
+
+/* The function outputs readable represenatation of all out arcs of
+ STATE. */
+static void
+output_state_arcs (state)
+ state_t state;
+{
+ arc_t arc;
+ ainsn_t ainsn;
+ char *insn_name;
+ int curr_line_length;
+
+ for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
+ {
+ ainsn = arc->insn;
+ if (!ainsn->first_insn_with_same_reservs)
+ abort ();
+ fprintf (output_description_file, " ");
+ curr_line_length = 7;
+ fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
+ do
+ {
+ insn_name = ainsn->insn_reserv_decl->name;
+ if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
+ {
+ if (ainsn != arc->insn)
+ {
+ fprintf (output_description_file, ",\n ");
+ curr_line_length = strlen (insn_name) + 6;
+ }
+ else
+ curr_line_length += strlen (insn_name);
+ }
+ else
+ {
+ curr_line_length += strlen (insn_name);
+ if (ainsn != arc->insn)
+ {
+ curr_line_length += 2;
+ fprintf (output_description_file, ", ");
+ }
+ }
+ fprintf (output_description_file, insn_name);
+ ainsn = ainsn->next_same_reservs_insn;
+ }
+ while (ainsn != NULL);
+ fprintf (output_description_file, " %d (%d)\n",
+ arc->to_state->order_state_num, arc->state_alts);
+ }
+ fprintf (output_description_file, "\n");
+}
+
+/* The following function is used for sorting possible cpu unit
+ reservation of a DFA state. */
+static int
+state_reservs_cmp (reservs_ptr_1, reservs_ptr_2)
+ const void *reservs_ptr_1;
+ const void *reservs_ptr_2;
+{
+ return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
+ *(reserv_sets_t *) reservs_ptr_2);
+}
+
+/* The following function is used for sorting possible cpu unit
+ reservation of a DFA state. */
+static void
+remove_state_duplicate_reservs ()
+{
+ reserv_sets_t *reservs_ptr;
+ reserv_sets_t *last_formed_reservs_ptr;
+
+ last_formed_reservs_ptr = NULL;
+ for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
+ reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
+ reservs_ptr++)
+ if (last_formed_reservs_ptr == NULL)
+ last_formed_reservs_ptr = reservs_ptr;
+ else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0)
+ {
+ ++last_formed_reservs_ptr;
+ *last_formed_reservs_ptr = *reservs_ptr;
+ }
+ VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1);
+}
+
+/* The following function output readable representation of DFA(s)
+ state used for fast recognition of pipeline hazards. State is
+ described by possible (current and scehduled) cpu unit
+ reservations. */
+static void
+output_state (state)
+ state_t state;
+{
+ reserv_sets_t *reservs_ptr;
+
+ VLA_PTR_CREATE (state_reservs, 150, "state reservations");
+ fprintf (output_description_file, " State #%d", state->order_state_num);
+ fprintf (output_description_file,
+ state->new_cycle_p ? " (new cycle)\n" : "\n");
+ add_state_reservs (state);
+ qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs),
+ sizeof (reserv_sets_t), state_reservs_cmp);
+ remove_state_duplicate_reservs ();
+ for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
+ reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
+ reservs_ptr++)
+ {
+ fprintf (output_description_file, " ");
+ output_reserv_sets (output_description_file, *reservs_ptr);
+ fprintf (output_description_file, "\n");
+ }
+ fprintf (output_description_file, "\n");
+ output_state_arcs (state);
+ VLA_PTR_DELETE (state_reservs);
+}
+
+/* The following function output readable representation of
+ DFAs used for fast recognition of pipeline hazards. */
+static void
+output_automaton_descriptions ()
+{
+ automaton_t automaton;
+
+ for (automaton = description->first_automaton;
+ automaton != NULL;
+ automaton = automaton->next_automaton)
+ {
+ fprintf (output_description_file, "\nAutomaton ");
+ output_automaton_name (output_description_file, automaton);
+ fprintf (output_description_file, "\n");
+ output_automaton_units (automaton);
+ pass_states (automaton, output_state);
+ }
+}
+
+
+
+/* The page contains top level function for generation DFA(s) used for
+ PHR. */
+
+/* The function outputs statistics about work of different phases of
+ DFA generator. */
+static void
+output_statistics (f)
+ FILE *f;
+{
+ automaton_t automaton;
+#ifndef NDEBUG
+ int transition_comb_vect_els = 0;
+ int transition_full_vect_els = 0;
+ int state_alts_comb_vect_els = 0;
+ int state_alts_full_vect_els = 0;
+ int min_issue_delay_vect_els = 0;
+#endif
+
+ for (automaton = description->first_automaton;
+ automaton != NULL;
+ automaton = automaton->next_automaton)
+ {
+ fprintf (f, "\nAutomaton ");
+ output_automaton_name (f, automaton);
+ fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
+ automaton->NDFA_states_num, automaton->NDFA_arcs_num);
+ fprintf (f, " %5d DFA states, %5d DFA arcs\n",
+ automaton->DFA_states_num, automaton->DFA_arcs_num);
+ if (!no_minimization_flag)
+ fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
+ automaton->minimal_DFA_states_num,
+ automaton->minimal_DFA_arcs_num);
+ fprintf (f, " %5d all insns %5d insn equivalence classes\n",
+ description->insns_num, automaton->insn_equiv_classes_num);
+#ifndef NDEBUG
+ fprintf
+ (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
+ (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect),
+ (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect),
+ (comb_vect_p (automaton->trans_table)
+ ? "use comb vect" : "use simple vect"));
+ fprintf
+ (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
+ (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect),
+ (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect),
+ (comb_vect_p (automaton->state_alts_table)
+ ? "use comb vect" : "use simple vect"));
+ fprintf
+ (f, "%5ld min delay table els, compression factor %d\n",
+ (long) automaton->DFA_states_num * automaton->insn_equiv_classes_num,
+ automaton->min_issue_delay_table_compression_factor);
+ transition_comb_vect_els
+ += VLA_HWINT_LENGTH (automaton->trans_table->comb_vect);
+ transition_full_vect_els
+ += VLA_HWINT_LENGTH (automaton->trans_table->full_vect);
+ state_alts_comb_vect_els
+ += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect);
+ state_alts_full_vect_els
+ += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect);
+ min_issue_delay_vect_els
+ += automaton->DFA_states_num * automaton->insn_equiv_classes_num;
+#endif
+ }
+#ifndef NDEBUG
+ fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
+ allocated_states_num, allocated_arcs_num);
+ fprintf (f, "%5d all allocated alternative states\n",
+ allocated_alt_states_num);
+ fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
+ transition_comb_vect_els, transition_full_vect_els);
+ fprintf
+ (f, "%5d all state alts comb vector els, %5d all state alts table els\n",
+ state_alts_comb_vect_els, state_alts_full_vect_els);
+ fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
+ fprintf (f, "%5d locked states num\n", locked_states_num);
+#endif
+}
+
+/* The function output times of work of different phases of DFA
+ generator. */
+static void
+output_time_statistics (f)
+ FILE *f;
+{
+ fprintf (f, "\n transformation: ");
+ print_active_time (f, transform_time);
+ fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
+ print_active_time (f, NDFA_time);
+ if (ndfa_flag)
+ {
+ fprintf (f, ", NDFA -> DFA: ");
+ print_active_time (f, NDFA_to_DFA_time);
+ }
+ fprintf (f, "\n DFA minimization: ");
+ print_active_time (f, minimize_time);
+ fprintf (f, ", making insn equivalence: ");
+ print_active_time (f, equiv_time);
+ fprintf (f, "\n all automaton generation: ");
+ print_active_time (f, automaton_generation_time);
+ fprintf (f, ", output: ");
+ print_active_time (f, output_time);
+ fprintf (f, "\n");
+}
+
+/* The function generates DFA (deterministic finate state automaton)
+ for fast recognition of pipeline hazards. No errors during
+ checking must be fixed before this function call. */
+static void
+generate ()
+{
+ automata_num = split_argument;
+ if (description->units_num < automata_num)
+ automata_num = description->units_num;
+ initiate_states ();
+ initiate_arcs ();
+ initiate_automata_lists ();
+ initiate_pass_states ();
+ initiate_excl_sets ();
+ initiate_presence_absence_sets ();
+ automaton_generation_time = create_ticker ();
+ create_automata ();
+ ticker_off (&automaton_generation_time);
+}
+
+
+
+/* The following function creates insn attribute whose values are
+ number alternatives in insn reservations. */
+static void
+make_insn_alts_attr ()
+{
+ int i, insn_num;
+ decl_t decl;
+ rtx condexp;
+
+ condexp = rtx_alloc (COND);
+ XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
+ XEXP (condexp, 1) = make_numeric_value (0);
+ for (i = insn_num = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
+ {
+ XVECEXP (condexp, 0, 2 * insn_num)
+ = DECL_INSN_RESERV (decl)->condexp;
+ XVECEXP (condexp, 0, 2 * insn_num + 1)
+ = make_numeric_value
+ (DECL_INSN_RESERV (decl)->transformed_regexp->mode != rm_oneof
+ ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl)
+ ->transformed_regexp)->regexps_num);
+ insn_num++;
+ }
+ }
+ if (description->insns_num != insn_num + 1)
+ abort ();
+ make_internal_attr (attr_printf (sizeof ("*")
+ + strlen (INSN_ALTS_FUNC_NAME) + 1,
+ "*%s", INSN_ALTS_FUNC_NAME),
+ condexp, 0);
+}
+
+
+
+/* The following function creates attribute which is order number of
+ insn in pipeline hazard description translator. */
+static void
+make_internal_dfa_insn_code_attr ()
+{
+ int i, insn_num;
+ decl_t decl;
+ rtx condexp;
+
+ condexp = rtx_alloc (COND);
+ XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
+ XEXP (condexp, 1)
+ = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl)
+ ->insn_num + 1);
+ for (i = insn_num = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
+ {
+ XVECEXP (condexp, 0, 2 * insn_num)
+ = DECL_INSN_RESERV (decl)->condexp;
+ XVECEXP (condexp, 0, 2 * insn_num + 1)
+ = make_numeric_value (DECL_INSN_RESERV (decl)->insn_num);
+ insn_num++;
+ }
+ }
+ if (description->insns_num != insn_num + 1)
+ abort ();
+ make_internal_attr
+ (attr_printf (sizeof ("*")
+ + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1,
+ "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME),
+ condexp, 0);
+}
+
+
+
+/* The following function creates attribute which order number of insn
+ in pipeline hazard description translator. */
+static void
+make_default_insn_latency_attr ()
+{
+ int i, insn_num;
+ decl_t decl;
+ rtx condexp;
+
+ condexp = rtx_alloc (COND);
+ XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
+ XEXP (condexp, 1) = make_numeric_value (0);
+ for (i = insn_num = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
+ {
+ XVECEXP (condexp, 0, 2 * insn_num)
+ = DECL_INSN_RESERV (decl)->condexp;
+ XVECEXP (condexp, 0, 2 * insn_num + 1)
+ = make_numeric_value (DECL_INSN_RESERV (decl)->default_latency);
+ insn_num++;
+ }
+ }
+ if (description->insns_num != insn_num + 1)
+ abort ();
+ make_internal_attr (attr_printf (sizeof ("*")
+ + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME)
+ + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME),
+ condexp, 0);
+}
+
+
+
+/* The following function creates attribute which returns 1 if given
+ output insn has bypassing and 0 otherwise. */
+static void
+make_bypass_attr ()
+{
+ int i, bypass_insn;
+ int bypass_insns_num = 0;
+ decl_t decl;
+ rtx result_rtx;
+
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv
+ && DECL_INSN_RESERV (decl)->condexp != NULL
+ && DECL_INSN_RESERV (decl)->bypass_list != NULL)
+ bypass_insns_num++;
+ }
+ if (bypass_insns_num == 0)
+ result_rtx = make_numeric_value (0);
+ else
+ {
+ result_rtx = rtx_alloc (COND);
+ XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2);
+ XEXP (result_rtx, 1) = make_numeric_value (0);
+
+ for (i = bypass_insn = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv
+ && DECL_INSN_RESERV (decl)->condexp != NULL
+ && DECL_INSN_RESERV (decl)->bypass_list != NULL)
+ {
+ XVECEXP (result_rtx, 0, 2 * bypass_insn)
+ = DECL_INSN_RESERV (decl)->condexp;
+ XVECEXP (result_rtx, 0, 2 * bypass_insn + 1)
+ = make_numeric_value (1);
+ bypass_insn++;
+ }
+ }
+ }
+ make_internal_attr (attr_printf (sizeof ("*")
+ + strlen (BYPASS_P_FUNC_NAME) + 1,
+ "*%s", BYPASS_P_FUNC_NAME),
+ result_rtx, 0);
+}
+
+
+
+/* This page mainly contains top level functions of pipeline hazards
+ description translator. */
+
+/* The following macro value is suffix of name of description file of
+ pipeline hazards description translator. */
+#define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
+
+/* The function returns suffix of given file name. The returned
+ string can not be changed. */
+static const char *
+file_name_suffix (file_name)
+ const char *file_name;
+{
+ const char *last_period;
+
+ for (last_period = NULL; *file_name != '\0'; file_name++)
+ if (*file_name == '.')
+ last_period = file_name;
+ return (last_period == NULL ? file_name : last_period);
+}
+
+/* The function returns base name of given file name, i.e. pointer to
+ first char after last `/' (or `\' for WIN32) in given file name,
+ given file name itself if the directory name is absent. The
+ returned string can not be changed. */
+static const char *
+base_file_name (file_name)
+ const char *file_name;
+{
+ int directory_name_length;
+
+ directory_name_length = strlen (file_name);
+#ifdef WIN32
+ while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
+ && file_name[directory_name_length] != '\\')
+#else
+ while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
+#endif
+ directory_name_length--;
+ return file_name + directory_name_length + 1;
+}
+
+/* The following is top level function to initialize the work of
+ pipeline hazards description translator. */
+void
+initiate_automaton_gen (argc, argv)
+ int argc;
+ char **argv;
+{
+ const char *base_name;
+ int i;
+
+ ndfa_flag = 0;
+ split_argument = 0; /* default value */
+ no_minimization_flag = 0;
+ time_flag = 0;
+ v_flag = 0;
+ w_flag = 0;
+ for (i = 2; i < argc; i++)
+ if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
+ no_minimization_flag = 1;
+ else if (strcmp (argv [i], TIME_OPTION) == 0)
+ time_flag = 1;
+ else if (strcmp (argv [i], V_OPTION) == 0)
+ v_flag = 1;
+ else if (strcmp (argv [i], W_OPTION) == 0)
+ w_flag = 1;
+ else if (strcmp (argv [i], NDFA_OPTION) == 0)
+ ndfa_flag = 1;
+ else if (strcmp (argv [i], "-split") == 0)
+ {
+ if (i + 1 >= argc)
+ fatal ("-split has no argument.");
+ fatal ("option `-split' has not been implemented yet\n");
+ /* split_argument = atoi (argument_vect [i + 1]); */
+ }
+ VLA_PTR_CREATE (decls, 150, "decls");
+ /* Initialize IR storage. */
+ obstack_init (&irp);
+ initiate_automaton_decl_table ();
+ initiate_insn_decl_table ();
+ initiate_decl_table ();
+ output_file = stdout;
+ output_description_file = NULL;
+ base_name = base_file_name (argv[1]);
+ obstack_grow (&irp, base_name,
+ strlen (base_name) - strlen (file_name_suffix (base_name)));
+ obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
+ strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
+ obstack_1grow (&irp, '\0');
+ output_description_file_name = obstack_base (&irp);
+ obstack_finish (&irp);
+}
+
+/* The following function checks existence at least one arc marked by
+ each insn. */
+static void
+check_automata_insn_issues ()
+{
+ automaton_t automaton;
+ ainsn_t ainsn, reserv_ainsn;
+
+ for (automaton = description->first_automaton;
+ automaton != NULL;
+ automaton = automaton->next_automaton)
+ {
+ for (ainsn = automaton->ainsn_list;
+ ainsn != NULL;
+ ainsn = ainsn->next_ainsn)
+ if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
+ {
+ for (reserv_ainsn = ainsn;
+ reserv_ainsn != NULL;
+ reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
+ if (automaton->corresponding_automaton_decl != NULL)
+ {
+ if (!w_flag)
+ error ("Automaton `%s': Insn `%s' will never be issued",
+ automaton->corresponding_automaton_decl->name,
+ reserv_ainsn->insn_reserv_decl->name);
+ else
+ warning
+ ("Automaton `%s': Insn `%s' will never be issued",
+ automaton->corresponding_automaton_decl->name,
+ reserv_ainsn->insn_reserv_decl->name);
+ }
+ else
+ {
+ if (!w_flag)
+ error ("Insn `%s' will never be issued",
+ reserv_ainsn->insn_reserv_decl->name);
+ else
+ warning ("Insn `%s' will never be issued",
+ reserv_ainsn->insn_reserv_decl->name);
+ }
+ }
+ }
+}
+
+/* The following vla is used for storing pointers to all achieved
+ states. */
+static vla_ptr_t automaton_states;
+
+/* This function is called by function pass_states to add an achieved
+ STATE. */
+static void
+add_automaton_state (state)
+ state_t state;
+{
+ VLA_PTR_ADD (automaton_states, state);
+}
+
+/* The following function forms list of important automata (whose
+ states may be changed after the insn issue) for each insn. */
+static void
+form_important_insn_automata_lists ()
+{
+ automaton_t automaton;
+ state_t *state_ptr;
+ decl_t decl;
+ ainsn_t ainsn;
+ arc_t arc;
+ int i;
+
+ VLA_PTR_CREATE (automaton_states, 1500,
+ "automaton states for forming important insn automata sets");
+ /* Mark important ainsns. */
+ for (automaton = description->first_automaton;
+ automaton != NULL;
+ automaton = automaton->next_automaton)
+ {
+ VLA_PTR_NULLIFY (automaton_states);
+ pass_states (automaton, add_automaton_state);
+ for (state_ptr = VLA_PTR_BEGIN (automaton_states);
+ state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
+ state_ptr++)
+ {
+ for (arc = first_out_arc (*state_ptr);
+ arc != NULL;
+ arc = next_out_arc (arc))
+ if (arc->to_state != *state_ptr)
+ {
+ if (!arc->insn->first_insn_with_same_reservs)
+ abort ();
+ for (ainsn = arc->insn;
+ ainsn != NULL;
+ ainsn = ainsn->next_same_reservs_insn)
+ ainsn->important_p = TRUE;
+ }
+ }
+ }
+ VLA_PTR_DELETE (automaton_states);
+ /* Create automata sets for the insns. */
+ for (i = 0; i < description->decls_num; i++)
+ {
+ decl = description->decls [i];
+ if (decl->mode == dm_insn_reserv)
+ {
+ automata_list_start ();
+ for (automaton = description->first_automaton;
+ automaton != NULL;
+ automaton = automaton->next_automaton)
+ for (ainsn = automaton->ainsn_list;
+ ainsn != NULL;
+ ainsn = ainsn->next_ainsn)
+ if (ainsn->important_p
+ && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
+ {
+ automata_list_add (automaton);
+ break;
+ }
+ DECL_INSN_RESERV (decl)->important_automata_list
+ = automata_list_finish ();
+ }
+ }
+}
+
+
+/* The following is top level function to generate automat(a,on) for
+ fast recognition of pipeline hazards. */
+void
+expand_automata ()
+{
+ int i;
+
+ description = create_node (sizeof (struct description)
+ /* One entry for cycle advancing insn. */
+ + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
+ description->decls_num = VLA_PTR_LENGTH (decls);
+ description->query_units_num = 0;
+ for (i = 0; i < description->decls_num; i++)
+ {
+ description->decls [i] = VLA_PTR (decls, i);
+ if (description->decls [i]->mode == dm_unit
+ && DECL_UNIT (description->decls [i])->query_p)
+ DECL_UNIT (description->decls [i])->query_num
+ = description->query_units_num++;
+ }
+ all_time = create_ticker ();
+ check_time = create_ticker ();
+ fprintf (stderr, "Check description...");
+ fflush (stderr);
+ check_all_description ();
+ fprintf (stderr, "done\n");
+ ticker_off (&check_time);
+ generation_time = create_ticker ();
+ if (!have_error)
+ {
+ transform_insn_regexps ();
+ check_unit_distributions_to_automata ();
+ }
+ if (!have_error)
+ {
+ generate ();
+ check_automata_insn_issues ();
+ }
+ if (!have_error)
+ {
+ form_important_insn_automata_lists ();
+ fprintf (stderr, "Generation of attributes...");
+ fflush (stderr);
+ make_internal_dfa_insn_code_attr ();
+ make_insn_alts_attr ();
+ make_default_insn_latency_attr ();
+ make_bypass_attr ();
+ fprintf (stderr, "done\n");
+ }
+ ticker_off (&generation_time);
+ ticker_off (&all_time);
+ fprintf (stderr, "All other genattrtab stuff...");
+ fflush (stderr);
+}
+
+/* The following is top level function to output PHR and to finish
+ work with pipeline description translator. */
+void
+write_automata ()
+{
+ fprintf (stderr, "done\n");
+ if (have_error)
+ fatal ("Errors in DFA description");
+ ticker_on (&all_time);
+ output_time = create_ticker ();
+ fprintf (stderr, "Forming and outputing automata tables...");
+ fflush (stderr);
+ output_dfa_max_issue_rate ();
+ output_tables ();
+ fprintf (stderr, "done\n");
+ fprintf (stderr, "Output functions to work with automata...");
+ fflush (stderr);
+ output_chip_definitions ();
+ output_max_insn_queue_index_def ();
+ output_internal_min_issue_delay_func ();
+ output_internal_trans_func ();
+ /* Cache of insn dfa codes: */
+ fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
+ fprintf (output_file, "\nstatic int %s;\n\n",
+ DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
+ output_dfa_insn_code_func ();
+ output_trans_func ();
+ fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
+ output_internal_state_alts_func ();
+ output_state_alts_func ();
+ fprintf (output_file, "\n#endif /* #if %s */\n\n",
+ AUTOMATON_STATE_ALTS_MACRO_NAME);
+ output_min_issue_delay_func ();
+ output_internal_dead_lock_func ();
+ output_dead_lock_func ();
+ output_size_func ();
+ output_internal_reset_func ();
+ output_reset_func ();
+ output_min_insn_conflict_delay_func ();
+ output_internal_insn_latency_func ();
+ output_insn_latency_func ();
+ output_print_reservation_func ();
+ if (no_minimization_flag)
+ {
+ fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
+ output_get_cpu_unit_code_func ();
+ output_cpu_unit_reservation_p ();
+ fprintf (output_file, "\n#endif /* #if %s */\n\n",
+ CPU_UNITS_QUERY_MACRO_NAME);
+ }
+ output_dfa_start_func ();
+ output_dfa_finish_func ();
+ fprintf (stderr, "done\n");
+ if (v_flag)
+ {
+ output_description_file = fopen (output_description_file_name, "w");
+ if (output_description_file == NULL)
+ {
+ perror (output_description_file_name);
+ exit (FATAL_EXIT_CODE);
+ }
+ fprintf (stderr, "Output automata description...");
+ fflush (stderr);
+ output_description ();
+ output_automaton_descriptions ();
+ fprintf (stderr, "done\n");
+ output_statistics (output_description_file);
+ }
+ output_statistics (stderr);
+ ticker_off (&output_time);
+ output_time_statistics (stderr);
+ finish_states ();
+ finish_arcs ();
+ finish_automata_lists ();
+ if (time_flag)
+ {
+ fprintf (stderr, "Summary:\n");
+ fprintf (stderr, " check time ");
+ print_active_time (stderr, check_time);
+ fprintf (stderr, ", generation time ");
+ print_active_time (stderr, generation_time);
+ fprintf (stderr, ", all time ");
+ print_active_time (stderr, all_time);
+ fprintf (stderr, "\n");
+ }
+ /* Finish all work. */
+ if (output_description_file != NULL)
+ {
+ fflush (output_description_file);
+ if (ferror (stdout) != 0)
+ fatal ("Error in writing DFA description file %s",
+ output_description_file_name);
+ fclose (output_description_file);
+ }
+ finish_automaton_decl_table ();
+ finish_insn_decl_table ();
+ finish_decl_table ();
+ obstack_free (&irp, NULL);
+ if (have_error && output_description_file != NULL)
+ remove (output_description_file_name);
+}
diff --git a/contrib/gcc/gencodes.c b/contrib/gcc/gencodes.c
index 0611eec..5a29282 100644
--- a/contrib/gcc/gencodes.c
+++ b/contrib/gcc/gencodes.c
@@ -28,18 +28,26 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "errors.h"
#include "gensupport.h"
-static void gen_insn PARAMS ((const char *, int));
+static void gen_insn PARAMS ((rtx, int));
static void
-gen_insn (name, code)
- const char *name;
+gen_insn (insn, code)
+ rtx insn;
int code;
{
+ const char *name = XSTR (insn, 0);
+ int truth = maybe_eval_c_test (XSTR (insn, 2));
+
/* Don't mention instructions whose names are the null string
or begin with '*'. They are in the machine description just
to be recognized. */
if (name[0] != 0 && name[0] != '*')
- printf (" CODE_FOR_%s = %d,\n", name, code);
+ {
+ if (truth == 0)
+ printf ("#define CODE_FOR_%s CODE_FOR_nothing\n", name);
+ else
+ printf (" CODE_FOR_%s = %d,\n", name, code);
+ }
}
extern int main PARAMS ((int, char **));
@@ -53,6 +61,10 @@ main (argc, argv)
progname = "gencodes";
+ /* We need to see all the possibilities. Elided insns may have
+ direct references to CODE_FOR_xxx in C code. */
+ insn_elision = 0;
+
if (argc <= 1)
fatal ("no input file name");
@@ -80,10 +92,10 @@ enum insn_code {");
break;
if (GET_CODE (desc) == DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)
- gen_insn (XSTR (desc, 0), insn_code_number);
+ gen_insn (desc, insn_code_number);
}
- puts ("CODE_FOR_nothing\n\
+ puts (" CODE_FOR_nothing\n\
};\n\
\n\
#endif /* GCC_INSN_CODES_H */");
diff --git a/contrib/gcc/genconditions.c b/contrib/gcc/genconditions.c
new file mode 100644
index 0000000..02f80ee
--- /dev/null
+++ b/contrib/gcc/genconditions.c
@@ -0,0 +1,240 @@
+/* Process machine description and calculate constant conditions.
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* In a machine description, all of the insn patterns - define_insn,
+ define_expand, define_split, define_peephole, define_peephole2 -
+ contain an optional C expression which makes the final decision
+ about whether or not this pattern is usable. That expression may
+ turn out to be always false when the compiler is built. If it is,
+ most of the programs that generate code from the machine
+ description can simply ignore the entire pattern. */
+
+#include "hconfig.h"
+#include "system.h"
+#include "rtl.h"
+#include "errors.h"
+#include "hashtab.h"
+#include "gensupport.h"
+
+/* so we can include except.h in the generated file */
+static int saw_eh_return;
+
+static htab_t condition_table;
+
+static void add_condition PARAMS ((const char *));
+static void write_header PARAMS ((void));
+static void write_conditions PARAMS ((void));
+static int write_one_condition PARAMS ((PTR *, PTR));
+
+extern int main PARAMS ((int, char **));
+
+/* Record the C test expression EXPR in the condition_table.
+ Duplicates clobber previous entries, which leaks memory, but
+ we don't care for this application. */
+
+static void
+add_condition (expr)
+ const char *expr;
+{
+ struct c_test *test;
+
+ if (expr[0] == 0)
+ return;
+
+ test = (struct c_test *) xmalloc (sizeof (struct c_test));
+ test->expr = expr;
+
+ *(htab_find_slot (condition_table, test, INSERT)) = test;
+}
+
+/* Generate the header for insn-conditions.c. */
+
+static void
+write_header ()
+{
+ puts ("\
+/* Generated automatically by the program `genconditions' from the target\n\
+ machine description file. */\n\
+\n\
+#include \"hconfig.h\"\n\
+#include \"insn-constants.h\"\n");
+
+ puts ("\
+/* Do not allow checking to confuse the issue. */\n\
+#undef ENABLE_CHECKING\n\
+#undef ENABLE_TREE_CHECKING\n\
+#undef ENABLE_RTL_CHECKING\n\
+#undef ENABLE_RTL_FLAG_CHECKING\n\
+#undef ENABLE_GC_CHECKING\n\
+#undef ENABLE_GC_ALWAYS_COLLECT\n");
+
+ puts ("\
+#include \"system.h\"\n\
+#include \"rtl.h\"\n\
+#include \"tm_p.h\"\n\
+#include \"function.h\"\n");
+
+ puts ("\
+/* Fake - insn-config.h doesn't exist yet. */\n\
+#define MAX_RECOG_OPERANDS 10\n\
+#define MAX_DUP_OPERANDS 10\n\
+#define MAX_INSNS_PER_SPLIT 5\n");
+
+ puts ("\
+#include \"regs.h\"\n\
+#include \"recog.h\"\n\
+#include \"real.h\"\n\
+#include \"output.h\"\n\
+#include \"flags.h\"\n\
+#include \"hard-reg-set.h\"\n\
+#include \"resource.h\"\n\
+#include \"toplev.h\"\n\
+#include \"reload.h\"\n\
+#include \"gensupport.h\"\n");
+
+ if (saw_eh_return)
+ puts ("#define HAVE_eh_return 1");
+ puts ("#include \"except.h\"\n");
+
+ puts ("\
+/* Dummy external declarations. */\n\
+extern rtx insn;\n\
+extern rtx ins1;\n\
+extern rtx operands[];\n\
+extern int next_insn_tests_no_inequality PARAMS ((rtx));\n");
+
+ puts ("\
+/* If we don't have __builtin_constant_p, or it's not acceptable in\n\
+ array initializers, fall back to assuming that all conditions\n\
+ potentially vary at run time. It works in 3.0.1 and later; 3.0\n\
+ only when not optimizing. */\n\
+#if (GCC_VERSION >= 3001) || ((GCC_VERSION == 3000) && !__OPTIMIZE__)\n\
+# define MAYBE_EVAL(expr) (__builtin_constant_p(expr) ? (int) (expr) : -1)\n\
+#else\n\
+# define MAYBE_EVAL(expr) -1\n\
+#endif\n");
+}
+
+/* Write out one entry in the conditions table, using the data pointed
+ to by SLOT. Each entry looks like this:
+ { "! optimize_size && ! TARGET_READ_MODIFY_WRITE",
+ MAYBE_EVAL (! optimize_size && ! TARGET_READ_MODIFY_WRITE) }, */
+
+static int
+write_one_condition (slot, dummy)
+ PTR *slot;
+ PTR dummy ATTRIBUTE_UNUSED;
+{
+ const struct c_test *test = * (const struct c_test **) slot;
+ const char *p;
+
+ fputs (" { \"", stdout);
+ for (p = test->expr; *p; p++)
+ {
+ if (*p == '\n')
+ fputs ("\\n\\\n", stdout);
+ else if (*p == '"')
+ fputs ("\\\"", stdout);
+ else
+ putchar (*p);
+ }
+
+ printf ("\",\n MAYBE_EVAL (%s) },\n", test->expr);
+ return 1;
+}
+
+/* Write out the complete conditions table, its size, and a flag
+ indicating that gensupport.c can now do insn elision. */
+static void
+write_conditions ()
+{
+ puts ("\
+/* This table lists each condition found in the machine description.\n\
+ Each condition is mapped to its truth value (0 or 1), or -1 if that\n\
+ cannot be calculated at compile time. */\n\
+\n\
+const struct c_test insn_conditions[] = {");
+
+ htab_traverse (condition_table, write_one_condition, 0);
+
+ puts ("};\n");
+
+ printf ("const size_t n_insn_conditions = %lu;\n",
+ (unsigned long) htab_elements (condition_table));
+ puts ("const int insn_elision_unavailable = 0;");
+}
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ rtx desc;
+ int pattern_lineno; /* not used */
+ int code;
+
+ progname = "genconditions";
+
+ if (argc <= 1)
+ fatal ("No input file name.");
+
+ if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+ return (FATAL_EXIT_CODE);
+
+ condition_table = htab_create (1000, hash_c_test, cmp_c_test, NULL);
+
+ /* Read the machine description. */
+
+ while (1)
+ {
+ desc = read_md_rtx (&pattern_lineno, &code);
+ if (desc == NULL)
+ break;
+
+ /* N.B. define_insn_and_split, define_cond_exec are handled
+ entirely within read_md_rtx; we never see them. */
+ switch (GET_CODE (desc))
+ {
+ default:
+ break;
+
+ case DEFINE_INSN:
+ case DEFINE_EXPAND:
+ add_condition (XSTR (desc, 2));
+ /* except.h needs to know whether there is an eh_return
+ pattern in the machine description. */
+ if (!strcmp (XSTR (desc, 0), "eh_return"))
+ saw_eh_return = 1;
+ break;
+
+ case DEFINE_SPLIT:
+ case DEFINE_PEEPHOLE:
+ case DEFINE_PEEPHOLE2:
+ add_condition (XSTR (desc, 1));
+ break;
+ }
+ }
+
+ write_header ();
+ write_conditions ();
+
+ fflush (stdout);
+ return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
+}
diff --git a/contrib/gcc/genconfig.c b/contrib/gcc/genconfig.c
index d7709b0..795e312 100644
--- a/contrib/gcc/genconfig.c
+++ b/contrib/gcc/genconfig.c
@@ -55,10 +55,10 @@ static void gen_split PARAMS ((rtx));
static void gen_peephole PARAMS ((rtx));
static void gen_peephole2 PARAMS ((rtx));
-/* RECOG_P will be non-zero if this pattern was seen in a context where it will
+/* RECOG_P will be nonzero if this pattern was seen in a context where it will
be used to recognize, rather than just generate an insn.
- NON_PC_SET_SRC will be non-zero if this pattern was seen in a SET_SRC
+ NON_PC_SET_SRC will be nonzero if this pattern was seen in a SET_SRC
of a SET whose destination is not (pc). */
static void
diff --git a/contrib/gcc/genemit.c b/contrib/gcc/genemit.c
index 5a7f32a..cb6c06c 100644
--- a/contrib/gcc/genemit.c
+++ b/contrib/gcc/genemit.c
@@ -59,7 +59,7 @@ static void max_operand_1 PARAMS ((rtx));
static int max_operand_vec PARAMS ((rtx, int));
static void print_code PARAMS ((RTX_CODE));
static void gen_exp PARAMS ((rtx, enum rtx_code, char *));
-static void gen_insn PARAMS ((rtx));
+static void gen_insn PARAMS ((rtx, int));
static void gen_expand PARAMS ((rtx));
static void gen_split PARAMS ((rtx));
static void output_add_clobbers PARAMS ((void));
@@ -246,7 +246,7 @@ gen_exp (x, subroutine_type, used)
else
{
printf ("GEN_INT (");
- printf (HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+ printf (HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x));
printf (")");
}
return;
@@ -297,8 +297,9 @@ gen_exp (x, subroutine_type, used)
/* Generate the `gen_...' function for a DEFINE_INSN. */
static void
-gen_insn (insn)
+gen_insn (insn, lineno)
rtx insn;
+ int lineno;
{
int operands;
int i;
@@ -383,6 +384,8 @@ gen_insn (insn)
if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*')
return;
+ printf ("/* %s:%d */\n", read_rtx_filename, lineno);
+
/* Find out how many operands this function has,
and also whether any of them have register constraints. */
register_constraints = 0;
@@ -521,8 +524,9 @@ gen_expand (expand)
rtx next = XVECEXP (expand, 1, i);
if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
|| (GET_CODE (next) == PARALLEL
- && GET_CODE (XVECEXP (next, 0, 0)) == SET
- && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
+ && ((GET_CODE (XVECEXP (next, 0, 0)) == SET
+ && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
+ || GET_CODE (XVECEXP (next, 0, 0)) == RETURN))
|| GET_CODE (next) == RETURN)
printf (" emit_jump_insn (");
else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
@@ -552,15 +556,15 @@ gen_expand (expand)
printf (" emit_barrier ();");
}
- /* Call `gen_sequence' to make a SEQUENCE out of all the
+ /* Call `get_insns' to extract the list of all the
insns emitted within this gen_... function. */
- printf (" _val = gen_sequence ();\n");
+ printf (" _val = get_insns ();\n");
printf (" end_sequence ();\n");
printf (" return _val;\n}\n\n");
}
-/* Like gen_expand, but generates a SEQUENCE. */
+/* Like gen_expand, but generates insns resulting from splitting SPLIT. */
static void
gen_split (split)
@@ -664,10 +668,10 @@ gen_split (split)
printf (" emit_barrier ();");
}
- /* Call `gen_sequence' to make a SEQUENCE out of all the
+ /* Call `get_insns' to make a list of all the
insns emitted within this gen_... function. */
- printf (" _val = gen_sequence ();\n");
+ printf (" _val = get_insns ();\n");
printf (" end_sequence ();\n");
printf (" return _val;\n}\n\n");
@@ -838,7 +842,7 @@ from the machine description file `md'. */\n\n");
printf ("#include \"toplev.h\"\n");
printf ("#include \"ggc.h\"\n\n");
printf ("#define FAIL return (end_sequence (), _val)\n");
- printf ("#define DONE return (_val = gen_sequence (), end_sequence (), _val)\n");
+ printf ("#define DONE return (_val = get_insns (), end_sequence (), _val)\n\n");
/* Read the machine description. */
@@ -852,25 +856,28 @@ from the machine description file `md'. */\n\n");
switch (GET_CODE (desc))
{
- case DEFINE_INSN:
- gen_insn (desc);
- break;
-
- case DEFINE_EXPAND:
- gen_expand (desc);
- break;
-
- case DEFINE_SPLIT:
- gen_split (desc);
- break;
-
- case DEFINE_PEEPHOLE2:
- gen_split (desc);
- break;
-
- default:
- break;
- }
+ case DEFINE_INSN:
+ gen_insn (desc, line_no);
+ break;
+
+ case DEFINE_EXPAND:
+ printf ("/* %s:%d */\n", read_rtx_filename, line_no);
+ gen_expand (desc);
+ break;
+
+ case DEFINE_SPLIT:
+ printf ("/* %s:%d */\n", read_rtx_filename, line_no);
+ gen_split (desc);
+ break;
+
+ case DEFINE_PEEPHOLE2:
+ printf ("/* %s:%d */\n", read_rtx_filename, line_no);
+ gen_split (desc);
+ break;
+
+ default:
+ break;
+ }
++insn_index_number;
}
diff --git a/contrib/gcc/genflags.c b/contrib/gcc/genflags.c
index 010ac70..9480681 100644
--- a/contrib/gcc/genflags.c
+++ b/contrib/gcc/genflags.c
@@ -29,10 +29,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "errors.h"
#include "gensupport.h"
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
/* Obstack to remember insns with. */
static struct obstack obstack;
@@ -128,14 +124,18 @@ gen_macro (name, real, expect)
printf ("(%c))\n", i + 'A');
}
-/* Print out prototype information for a function. */
+/* Print out prototype information for a generator function. If the
+ insn pattern has been elided, print out a dummy generator that
+ does nothing. */
static void
gen_proto (insn)
rtx insn;
{
int num = num_operands (insn);
+ int i;
const char *name = XSTR (insn, 0);
+ int truth = maybe_eval_c_test (XSTR (insn, 2));
/* Many md files don't refer to the last two operands passed to the
call patterns. This means their generator functions will be two
@@ -156,19 +156,41 @@ gen_proto (insn)
gen_macro (name, num, 5);
}
- printf ("extern struct rtx_def *gen_%-*s PARAMS ((", max_id_len, name);
+ if (truth != 0)
+ printf ("extern rtx gen_%-*s PARAMS ((", max_id_len, name);
+ else
+ printf ("static inline rtx gen_%-*s PARAMS ((", max_id_len, name);
if (num == 0)
- printf ("void");
+ fputs ("void", stdout);
else
{
- while (num-- > 1)
- printf ("struct rtx_def *, ");
-
- printf ("struct rtx_def *");
+ for (i = 1; i < num; i++)
+ fputs ("rtx, ", stdout);
+
+ fputs ("rtx", stdout);
}
- printf ("));\n");
+ puts ("));");
+
+ /* Some back ends want to take the address of generator functions,
+ so we cannot simply use #define for these dummy definitions. */
+ if (truth == 0)
+ {
+ printf ("static inline rtx\ngen_%s", name);
+ if (num > 0)
+ {
+ putchar ('(');
+ for (i = 0; i < num-1; i++)
+ printf ("%c, ", 'a' + i);
+ printf ("%c)\n", 'a' + i);
+ for (i = 0; i < num; i++)
+ printf (" rtx %c ATTRIBUTE_UNUSED;\n", 'a' + i);
+ }
+ else
+ puts ("()");
+ puts ("{\n return 0;\n}");
+ }
}
@@ -179,6 +201,7 @@ gen_insn (insn)
const char *name = XSTR (insn, 0);
const char *p;
int len;
+ int truth = maybe_eval_c_test (XSTR (insn, 2));
/* Don't mention instructions whose names are the null string
or begin with '*'. They are in the machine description just
@@ -191,22 +214,23 @@ gen_insn (insn)
if (len > max_id_len)
max_id_len = len;
- printf ("#define HAVE_%s ", name);
- if (strlen (XSTR (insn, 2)) == 0)
- printf ("1\n");
+ if (truth == 0)
+ /* emit nothing */;
+ else if (truth == 1)
+ printf ("#define HAVE_%s 1\n", name);
else
{
/* Write the macro definition, putting \'s at the end of each line,
if more than one. */
- printf ("(");
+ printf ("#define HAVE_%s (", name);
for (p = XSTR (insn, 2); *p; p++)
{
if (IS_VSPACE (*p))
- printf (" \\\n");
+ fputs (" \\\n", stdout);
else
- printf ("%c", *p);
+ putchar (*p);
}
- printf (")\n");
+ fputs (")\n", stdout);
}
obstack_grow (&obstack, &insn, sizeof (rtx));
@@ -227,6 +251,10 @@ main (argc, argv)
progname = "genflags";
obstack_init (&obstack);
+ /* We need to see all the possibilities. Elided insns may have
+ direct calls to their generators in C code. */
+ insn_elision = 0;
+
if (argc <= 1)
fatal ("no input file name");
@@ -256,7 +284,6 @@ main (argc, argv)
obstack_grow (&obstack, &dummy, sizeof (rtx));
insns = (rtx *) obstack_finish (&obstack);
- printf ("struct rtx_def;\n");
for (insn_ptr = insns; *insn_ptr; insn_ptr++)
gen_proto (*insn_ptr);
diff --git a/contrib/gcc/gengenrtl.c b/contrib/gcc/gengenrtl.c
index 157baf1..6bfd0ff 100644
--- a/contrib/gcc/gengenrtl.c
+++ b/contrib/gcc/gengenrtl.c
@@ -1,5 +1,5 @@
/* Generate code to allocate RTL structures.
- Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -28,80 +28,15 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "real.h"
-/* Calculate the format for CONST_DOUBLE. This depends on the relative
- widths of HOST_WIDE_INT and REAL_VALUE_TYPE.
-
- We need to go out to e0wwwww, since REAL_ARITHMETIC assumes 16-bits
- per element in REAL_VALUE_TYPE.
-
- This is duplicated in rtl.c.
-
- A number of places assume that there are always at least two 'w'
- slots in a CONST_DOUBLE, so we provide them even if one would suffice. */
-
-#ifdef REAL_ARITHMETIC
-# if MAX_LONG_DOUBLE_TYPE_SIZE == 96
-# define REAL_WIDTH \
- (11*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
-# else
-# if MAX_LONG_DOUBLE_TYPE_SIZE == 128
-# define REAL_WIDTH \
- (19*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
-# else
-# if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
-# define REAL_WIDTH \
- (7*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
-# endif
-# endif
-# endif
-#endif /* REAL_ARITHMETIC */
-
-#ifndef REAL_WIDTH
-# if HOST_BITS_PER_WIDE_INT*2 >= MAX_LONG_DOUBLE_TYPE_SIZE
-# define REAL_WIDTH 2
-# else
-# if HOST_BITS_PER_WIDE_INT*3 >= MAX_LONG_DOUBLE_TYPE_SIZE
-# define REAL_WIDTH 3
-# else
-# if HOST_BITS_PER_WIDE_INT*4 >= MAX_LONG_DOUBLE_TYPE_SIZE
-# define REAL_WIDTH 4
-# endif
-# endif
-# endif
-#endif /* REAL_WIDTH */
-
-#if REAL_WIDTH == 1
-# define CONST_DOUBLE_FORMAT "0ww"
-#else
-# if REAL_WIDTH == 2
-# define CONST_DOUBLE_FORMAT "0ww"
-# else
-# if REAL_WIDTH == 3
-# define CONST_DOUBLE_FORMAT "0www"
-# else
-# if REAL_WIDTH == 4
-# define CONST_DOUBLE_FORMAT "0wwww"
-# else
-# if REAL_WIDTH == 5
-# define CONST_DOUBLE_FORMAT "0wwwww"
-# else
-# define CONST_DOUBLE_FORMAT /* nothing - will cause syntax error */
-# endif
-# endif
-# endif
-# endif
-#endif
-
-
-struct rtx_definition
+struct rtx_definition
{
const char *const enumname, *const name, *const format;
};
#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { STRINGX(ENUM), NAME, FORMAT },
-static const struct rtx_definition defs[] =
-{
+static const struct rtx_definition defs[] =
+{
#include "rtl.def" /* rtl expressions are documented here */
};
@@ -111,6 +46,7 @@ static const char *type_from_format PARAMS ((int));
static const char *accessor_from_format PARAMS ((int));
static int special_format PARAMS ((const char *));
static int special_rtx PARAMS ((int));
+static int excluded_rtx PARAMS ((int));
static void find_formats PARAMS ((void));
static void gendecl PARAMS ((const char *));
static void genmacro PARAMS ((int));
@@ -145,6 +81,8 @@ type_from_format (c)
return "struct bitmap_head_def *"; /* bitmap - typedef not available */
case 't':
return "union tree_node *"; /* tree - typedef not available */
+ case 'B':
+ return "struct basic_block_def *"; /* basic block - typedef not available */
default:
abort ();
}
@@ -179,6 +117,9 @@ accessor_from_format (c)
case 't':
return "XTREE";
+ case 'B':
+ return "XBBDEF";
+
default:
abort ();
}
@@ -197,19 +138,30 @@ special_format (fmt)
|| strchr (fmt, 'n') != 0);
}
-/* Return nonzero if the RTL code given by index IDX is one that we should not
- generate a gen_RTX_FOO function foo (because that function is present
- elsewhere in the compiler). */
+/* Return nonzero if the RTL code given by index IDX is one that we should
+ generate a gen_rtx_raw_FOO macro for, not gen_rtx_FOO (because gen_rtx_FOO
+ is a wrapper in emit-rtl.c). */
static int
special_rtx (idx)
int idx;
{
return (strcmp (defs[idx].enumname, "CONST_INT") == 0
- || strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0
|| strcmp (defs[idx].enumname, "REG") == 0
|| strcmp (defs[idx].enumname, "SUBREG") == 0
- || strcmp (defs[idx].enumname, "MEM") == 0);
+ || strcmp (defs[idx].enumname, "MEM") == 0
+ || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0);
+}
+
+/* Return nonzero if the RTL code given by index IDX is one that we should
+ generate no macro for at all (because gen_rtx_FOO is never used or
+ cannot have the obvious interface). */
+
+static int
+excluded_rtx (idx)
+ int idx;
+{
+ return (strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0);
}
/* Place a list of all format specifiers we use into the array FORMAT. */
@@ -243,7 +195,7 @@ gendecl (format)
{
const char *p;
int i, pos;
-
+
printf ("extern rtx gen_rtx_fmt_%s\tPARAMS ((RTX_CODE, ", format);
printf ("enum machine_mode mode");
@@ -268,7 +220,7 @@ gendecl (format)
/* Generate macros to generate RTL of code IDX using the functions we
write. */
-static void
+static void
genmacro (idx)
int idx;
{
@@ -278,6 +230,10 @@ genmacro (idx)
/* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to
gen_rtx_fmt_FORMAT where FORMAT is the RTX_FORMAT of RTLCODE. */
+ if (excluded_rtx (idx))
+ /* Don't define a macro for this code. */
+ return;
+
printf ("#define gen_rtx_%s%s(MODE",
special_rtx (idx) ? "raw_" : "", defs[idx].enumname);
@@ -304,7 +260,7 @@ gendef (format)
{
const char *p;
int i, j;
-
+
/* Start by writing the definition of the function name and the types
of the arguments. */
@@ -381,10 +337,6 @@ gencode ()
puts ("#include \"rtl.h\"");
puts ("#include \"ggc.h\"\n");
puts ("extern struct obstack *rtl_obstack;\n");
- puts ("#define obstack_alloc_rtx(n) \\");
- puts (" ((rtx) obstack_alloc (rtl_obstack, \\");
- puts (" sizeof (struct rtx_def) \\");
- puts (" + ((n) - 1) * sizeof (rtunion)))\n");
for (fmt = formats; *fmt != 0; fmt++)
gendef (*fmt);
diff --git a/contrib/gcc/gengtype-lex.l b/contrib/gcc/gengtype-lex.l
new file mode 100644
index 0000000..38e470d
--- /dev/null
+++ b/contrib/gcc/gengtype-lex.l
@@ -0,0 +1,328 @@
+/* -*- indented-text -*- */
+/* Process source files and output type information.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+%{
+#include "hconfig.h"
+#include "system.h"
+
+#define malloc xmalloc
+#define realloc xrealloc
+
+#include "gengtype.h"
+#include "gengtype-yacc.h"
+
+#undef YY_USE_PROTOS
+#define YY_DECL int yylex ()
+
+static void update_lineno PARAMS ((const char *l, size_t len));
+
+struct fileloc lexer_line;
+int lexer_toplevel_done;
+
+static void
+update_lineno (l, len)
+ const char *l;
+ size_t len;
+{
+ while (len-- > 0)
+ if (*l++ == '\n')
+ lexer_line.line++;
+}
+
+%}
+
+ID [[:alpha:]_][[:alnum:]_]*
+WS [[:space:]]+
+IWORD short|long|(un)?signed|char|int|HOST_WIDE_INT|bool|size_t
+ITYPE {IWORD}({WS}{IWORD})*
+
+%x in_struct in_struct_comment in_comment in_yacc_escape
+%option warn noyywrap nounput nodefault perf-report
+%option 8bit never-interactive
+%%
+
+[^[:alnum:]_]typedef{WS}(struct|union){WS}{ID}{WS}?[*[:space:]]{WS}?{ID}{WS}?";" {
+ char *tagstart;
+ size_t taglen;
+ char *namestart;
+ size_t namelen;
+ int is_pointer = 0;
+ struct type *t;
+ int union_p;
+
+ tagstart = yytext + strlen (" typedef ");
+ while (ISSPACE (*tagstart))
+ tagstart++;
+ union_p = tagstart[0] == 'u';
+ tagstart += strlen ("union ");
+ while (ISSPACE (*tagstart))
+ tagstart++;
+ for (taglen = 1; ISIDNUM (tagstart[taglen]); taglen++)
+ ;
+ for (namestart = tagstart + taglen;
+ ! ISIDNUM (*namestart);
+ namestart++)
+ if (*namestart == '*')
+ is_pointer = 1;
+ for (namelen = 1; ISIDNUM (namestart[namelen]); namelen++)
+ ;
+ t = find_structure (xmemdup (tagstart, taglen, taglen+1), union_p);
+ if (is_pointer)
+ t = create_pointer (t);
+ do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
+ update_lineno (yytext, yyleng);
+}
+
+[^[:alnum:]_]typedef{WS}{ITYPE}{WS}{ID}{WS}?";" {
+
+ char *namestart;
+ size_t namelen;
+ struct type *t;
+ char *typestart;
+ size_t typelen;
+
+ for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--)
+ ;
+ for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
+ ;
+ namestart -= namelen - 1;
+ for (typestart = yytext + strlen (" typedef ");
+ ISSPACE(*typestart);
+ typestart++)
+ ;
+ for (typelen = namestart - typestart;
+ ISSPACE(typestart[typelen-1]);
+ typelen--)
+ ;
+
+ t = create_scalar_type (typestart, typelen);
+ do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
+ update_lineno (yytext, yyleng);
+}
+
+[^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}PARAMS {
+ char *namestart;
+ size_t namelen;
+ struct type *t;
+
+ for (namestart = yytext + yyleng - 7; ISSPACE (*namestart); namestart--)
+ ;
+ for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
+ ;
+ namestart -= namelen - 1;
+
+ t = create_scalar_type ("function type", sizeof ("function type")-1);
+ do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
+ update_lineno (yytext, yyleng);
+}
+[^[:alnum:]_]typedef{WS}{ID}{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?PARAMS {
+ char *namestart;
+ size_t namelen;
+ struct type *t;
+
+ for (namestart = yytext + yyleng - 7; !ISIDNUM (*namestart); namestart--)
+ ;
+ for (namelen = 1; ISIDNUM (namestart[-namelen]); namelen++)
+ ;
+ namestart -= namelen - 1;
+
+ t = create_scalar_type ("function type", sizeof ("function type")-1);
+ do_typedef (xmemdup (namestart, namelen, namelen+1), t, &lexer_line);
+ update_lineno (yytext, yyleng);
+}
+
+[^[:alnum:]_](typedef{WS})?(struct|union){WS}{ID}{WS}/"GTY" {
+ char *tagstart;
+ size_t taglen;
+ int typedef_p;
+ int union_p;
+
+ typedef_p = yytext[1] == 't';
+ if (typedef_p)
+ for (tagstart = yytext + strlen (" typedef ");
+ ISSPACE(*tagstart);
+ tagstart++)
+ ;
+ else
+ tagstart = yytext + 1;
+
+ union_p = tagstart[0] == 'u';
+ tagstart += strlen ("union ");
+ while (ISSPACE (*tagstart))
+ tagstart++;
+ for (taglen = 1; ISIDNUM (tagstart[taglen]); taglen++)
+ ;
+
+ yylval.t = find_structure (xmemdup (tagstart, taglen, taglen + 1), union_p);
+ BEGIN(in_struct);
+ update_lineno (yytext, yyleng);
+ return typedef_p ? ENT_TYPEDEF_STRUCT : ENT_STRUCT;
+}
+
+[^[:alnum:]_](extern|static){WS}/"GTY" {
+ BEGIN(in_struct);
+ update_lineno (yytext, yyleng);
+ return ENT_EXTERNSTATIC;
+}
+
+^"%union"{WS}"{"{WS}/"GTY" {
+ BEGIN(in_struct);
+ update_lineno (yytext, yyleng);
+ return ENT_YACCUNION;
+}
+
+<in_struct>{
+
+"/*" { BEGIN(in_struct_comment); }
+
+^"%{" { BEGIN(in_yacc_escape); }
+
+{WS} { update_lineno (yytext, yyleng); }
+
+"const"/[^[:alnum:]_] /* don't care */
+
+"GTY"/[^[:alnum:]_] { return GTY_TOKEN; }
+"union"/[^[:alnum:]_] { return UNION; }
+"struct"/[^[:alnum:]_] { return STRUCT; }
+"enum"/[^[:alnum:]_] { return ENUM; }
+"ptr_alias"/[^[:alnum:]_] { return ALIAS; }
+[0-9]+ { return NUM; }
+"param"[0-9]*"_is"/[^[:alnum:]_] {
+ yylval.s = xmemdup (yytext, yyleng, yyleng+1);
+ return PARAM_IS;
+}
+
+{IWORD}({WS}{IWORD})*/[^[:alnum:]_] |
+"ENUM_BITFIELD"{WS}?"("{WS}?{ID}{WS}?")" {
+ size_t len;
+
+ for (len = yyleng; ISSPACE (yytext[len-1]); len--)
+ ;
+
+ yylval.t = create_scalar_type (yytext, len);
+ update_lineno (yytext, yyleng);
+ return SCALAR;
+}
+
+{ID}/[^[:alnum:]_] {
+ yylval.s = xmemdup (yytext, yyleng, yyleng+1);
+ return ID;
+}
+
+\"([^"\\]|\\.)*\" {
+ yylval.s = xmemdup (yytext+1, yyleng-2, yyleng-1);
+ return STRING;
+}
+"["[^\[\]]*"]" {
+ yylval.s = xmemdup (yytext+1, yyleng-2, yyleng-1);
+ return ARRAY;
+}
+^"%"{ID} {
+ yylval.s = xmemdup (yytext+1, yyleng-1, yyleng);
+ return PERCENT_ID;
+}
+"'"("\\".|[^\\])"'" {
+ yylval.s = xmemdup (yytext+1, yyleng-2, yyleng);
+ return CHAR;
+}
+
+[(){},*:<>] { return yytext[0]; }
+
+[;=] {
+ if (lexer_toplevel_done)
+ {
+ BEGIN(INITIAL);
+ lexer_toplevel_done = 0;
+ }
+ return yytext[0];
+}
+
+^"%%" {
+ BEGIN(INITIAL);
+ return PERCENTPERCENT;
+}
+
+. {
+ error_at_line (&lexer_line, "unexpected character `%s'", yytext);
+}
+}
+
+"/*" { BEGIN(in_comment); }
+\n { lexer_line.line++; }
+{ID} |
+"'"("\\".|[^\\])"'" |
+[^"/\n] /* do nothing */
+\"([^"\\]|\\.|\\\n)*\" { update_lineno (yytext, yyleng); }
+"/"/[^*] /* do nothing */
+
+<in_comment,in_struct_comment>{
+\n { lexer_line.line++; }
+[^*\n]{16} |
+[^*\n] /* do nothing */
+"*"/[^/] /* do nothing */
+}
+<in_comment>"*/" { BEGIN(INITIAL); }
+<in_struct_comment>"*/" { BEGIN(in_struct); }
+
+<in_yacc_escape>{
+\n { lexer_line.line++; }
+[^%]{16} |
+[^%] /* do nothing */
+"%"/[^}] /* do nothing */
+"%}" { BEGIN(in_struct); }
+"%" {
+ error_at_line (&lexer_line,
+ "unterminated %%{; unexpected EOF");
+}
+}
+
+
+["/] |
+<in_struct_comment,in_comment>"*" {
+ error_at_line (&lexer_line,
+ "unterminated comment or string; unexpected EOF");
+}
+
+%%
+
+void
+yyerror (s)
+ const char *s;
+{
+ error_at_line (&lexer_line, s);
+}
+
+void
+parse_file (fname)
+ const char *fname;
+{
+ yyin = fopen (fname, "r");
+ lexer_line.file = fname;
+ lexer_line.line = 1;
+ if (yyin == NULL)
+ {
+ perror (fname);
+ exit (1);
+ }
+ if (yyparse() != 0)
+ exit (1);
+ fclose (yyin);
+}
diff --git a/contrib/gcc/gengtype-yacc.y b/contrib/gcc/gengtype-yacc.y
new file mode 100644
index 0000000..9ccea1a
--- /dev/null
+++ b/contrib/gcc/gengtype-yacc.y
@@ -0,0 +1,300 @@
+/* -*- indented-text -*- */
+/* Process source files and output type information.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+%{
+#include "hconfig.h"
+#include "system.h"
+#include "gengtype.h"
+#define YYERROR_VERBOSE
+%}
+
+%union {
+ type_p t;
+ pair_p p;
+ options_p o;
+ const char *s;
+}
+
+%token <t>ENT_TYPEDEF_STRUCT
+%token <t>ENT_STRUCT
+%token ENT_EXTERNSTATIC
+%token ENT_YACCUNION
+%token GTY_TOKEN
+%token UNION
+%token STRUCT
+%token ENUM
+%token ALIAS
+%token <s>PARAM_IS
+%token NUM
+%token PERCENTPERCENT "%%"
+%token <t>SCALAR
+%token <s>ID
+%token <s>STRING
+%token <s>ARRAY
+%token <s>PERCENT_ID
+%token <s>CHAR
+
+%type <p> struct_fields yacc_ids yacc_typematch
+%type <t> type lasttype
+%type <o> optionsopt options option optionseq optionseqopt
+%type <s> type_option
+
+%%
+
+start: /* empty */
+ | typedef_struct start
+ | externstatic start
+ | yacc_union start
+ ;
+
+typedef_struct: ENT_TYPEDEF_STRUCT options '{' struct_fields '}' ID
+ {
+ new_structure ($1->u.s.tag, UNION_P ($1), &lexer_line,
+ $4, $2);
+ do_typedef ($6, $1, &lexer_line);
+ lexer_toplevel_done = 1;
+ }
+ ';'
+ {}
+ | ENT_STRUCT options '{' struct_fields '}'
+ {
+ new_structure ($1->u.s.tag, UNION_P ($1), &lexer_line,
+ $4, $2);
+ lexer_toplevel_done = 1;
+ }
+ ';'
+ {}
+ ;
+
+externstatic: ENT_EXTERNSTATIC options lasttype ID semiequal
+ {
+ note_variable ($4, adjust_field_type ($3, $2), $2,
+ &lexer_line);
+ }
+ | ENT_EXTERNSTATIC options lasttype ID ARRAY semiequal
+ {
+ note_variable ($4, create_array ($3, $5),
+ $2, &lexer_line);
+ }
+ | ENT_EXTERNSTATIC options lasttype ID ARRAY ARRAY semiequal
+ {
+ note_variable ($4, create_array (create_array ($3, $6),
+ $5),
+ $2, &lexer_line);
+ }
+ ;
+
+lasttype: type
+ {
+ lexer_toplevel_done = 1;
+ $$ = $1;
+ }
+ ;
+
+semiequal: ';'
+ | '='
+ ;
+
+yacc_union: ENT_YACCUNION options struct_fields '}' yacc_typematch
+ PERCENTPERCENT
+ {
+ note_yacc_type ($2, $3, $5, &lexer_line);
+ }
+ ;
+
+yacc_typematch: /* empty */
+ { $$ = NULL; }
+ | yacc_typematch PERCENT_ID yacc_ids
+ {
+ pair_p p;
+ for (p = $3; p->next != NULL; p = p->next)
+ {
+ p->name = NULL;
+ p->type = NULL;
+ }
+ p->name = NULL;
+ p->type = NULL;
+ p->next = $1;
+ $$ = $3;
+ }
+ | yacc_typematch PERCENT_ID '<' ID '>' yacc_ids
+ {
+ pair_p p;
+ type_p newtype = NULL;
+ if (strcmp ($2, "type") == 0)
+ newtype = (type_p) 1;
+ for (p = $6; p->next != NULL; p = p->next)
+ {
+ p->name = $4;
+ p->type = newtype;
+ }
+ p->name = $4;
+ p->next = $1;
+ p->type = newtype;
+ $$ = $6;
+ }
+ ;
+
+yacc_ids: /* empty */
+ { $$ = NULL; }
+ | yacc_ids ID
+ {
+ pair_p p = xcalloc (1, sizeof (*p));
+ p->next = $1;
+ p->line = lexer_line;
+ p->opt = xmalloc (sizeof (*(p->opt)));
+ p->opt->name = "tag";
+ p->opt->next = NULL;
+ p->opt->info = (char *)$2;
+ $$ = p;
+ }
+ | yacc_ids CHAR
+ {
+ pair_p p = xcalloc (1, sizeof (*p));
+ p->next = $1;
+ p->line = lexer_line;
+ p->opt = xmalloc (sizeof (*(p->opt)));
+ p->opt->name = "tag";
+ p->opt->next = NULL;
+ p->opt->info = xasprintf ("'%s'", $2);
+ $$ = p;
+ }
+ ;
+
+struct_fields: { $$ = NULL; }
+ | type optionsopt ID bitfieldopt ';' struct_fields
+ {
+ pair_p p = xmalloc (sizeof (*p));
+ p->type = adjust_field_type ($1, $2);
+ p->opt = $2;
+ p->name = $3;
+ p->next = $6;
+ p->line = lexer_line;
+ $$ = p;
+ }
+ | type optionsopt ID ARRAY ';' struct_fields
+ {
+ pair_p p = xmalloc (sizeof (*p));
+ p->type = adjust_field_type (create_array ($1, $4), $2);
+ p->opt = $2;
+ p->name = $3;
+ p->next = $6;
+ p->line = lexer_line;
+ $$ = p;
+ }
+ | type optionsopt ID ARRAY ARRAY ';' struct_fields
+ {
+ pair_p p = xmalloc (sizeof (*p));
+ p->type = create_array (create_array ($1, $5), $4);
+ p->opt = $2;
+ p->name = $3;
+ p->next = $7;
+ p->line = lexer_line;
+ $$ = p;
+ }
+ ;
+
+bitfieldopt: /* empty */
+ | ':' NUM
+ | ':' ID
+ ;
+
+type: SCALAR
+ { $$ = $1; }
+ | ID
+ { $$ = resolve_typedef ($1, &lexer_line); }
+ | type '*'
+ { $$ = create_pointer ($1); }
+ | STRUCT ID '{' struct_fields '}'
+ {
+ new_structure ($2, 0, &lexer_line, $4, NULL);
+ $$ = find_structure ($2, 0);
+ }
+ | STRUCT ID
+ { $$ = find_structure ($2, 0); }
+ | UNION ID '{' struct_fields '}'
+ {
+ new_structure ($2, 1, &lexer_line, $4, NULL);
+ $$ = find_structure ($2, 1);
+ }
+ | UNION ID
+ { $$ = find_structure ($2, 1); }
+ | ENUM ID
+ { $$ = create_scalar_type ($2, strlen ($2)); }
+ | ENUM ID '{' enum_items '}'
+ { $$ = create_scalar_type ($2, strlen ($2)); }
+ ;
+
+enum_items: /* empty */
+ | ID '=' NUM ',' enum_items
+ { }
+ | ID ',' enum_items
+ { }
+ | ID enum_items
+ { }
+ ;
+
+optionsopt: { $$ = NULL; }
+ | options { $$ = $1; }
+ ;
+
+options: GTY_TOKEN '(' '(' optionseqopt ')' ')'
+ { $$ = $4; }
+ ;
+
+type_option : ALIAS
+ { $$ = "ptr_alias"; }
+ | PARAM_IS
+ { $$ = $1; }
+ ;
+
+option: type_option '(' type ')'
+ {
+ options_p o = xmalloc (sizeof (*o));
+ o->name = $1;
+ o->info = adjust_field_type ($3, NULL);
+ $$ = o;
+ }
+ | ID '(' STRING ')'
+ {
+ options_p o = xmalloc (sizeof (*o));
+ o->name = $1;
+ o->info = (void *)$3;
+ $$ = o;
+ }
+ ;
+
+optionseq: option
+ {
+ $1->next = NULL;
+ $$ = $1;
+ }
+ | optionseq ',' option
+ {
+ $3->next = $1;
+ $$ = $3;
+ }
+ ;
+
+optionseqopt: { $$ = NULL; }
+ | optionseq { $$ = $1; }
+ ;
+%%
diff --git a/contrib/gcc/gengtype.c b/contrib/gcc/gengtype.c
new file mode 100644
index 0000000..dbd8995
--- /dev/null
+++ b/contrib/gcc/gengtype.c
@@ -0,0 +1,2625 @@
+/* Process source files and output type information.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include "hconfig.h"
+#include "system.h"
+#include "gengtype.h"
+#include "gtyp-gen.h"
+
+/* Nonzero iff an error has occurred. */
+static int hit_error = 0;
+
+static void gen_rtx_next PARAMS ((void));
+static void write_rtx_next PARAMS ((void));
+static void open_base_files PARAMS ((void));
+static void close_output_files PARAMS ((void));
+
+/* Report an error at POS, printing MSG. */
+
+void
+error_at_line VPARAMS ((struct fileloc *pos, const char *msg, ...))
+{
+ VA_OPEN (ap, msg);
+ VA_FIXEDARG (ap, struct fileloc *, pos);
+ VA_FIXEDARG (ap, const char *, msg);
+
+ fprintf (stderr, "%s:%d: ", pos->file, pos->line);
+ vfprintf (stderr, msg, ap);
+ fputc ('\n', stderr);
+ hit_error = 1;
+
+ VA_CLOSE (ap);
+}
+
+/* vasprintf, but produces fatal message on out-of-memory. */
+int
+xvasprintf (result, format, args)
+ char ** result;
+ const char *format;
+ va_list args;
+{
+ int ret = vasprintf (result, format, args);
+ if (*result == NULL || ret < 0)
+ {
+ fputs ("gengtype: out of memory", stderr);
+ xexit (1);
+ }
+ return ret;
+}
+
+/* Wrapper for xvasprintf. */
+char *
+xasprintf VPARAMS ((const char *format, ...))
+{
+ char *result;
+ VA_OPEN (ap, format);
+ VA_FIXEDARG (ap, const char *, format);
+ xvasprintf (&result, format, ap);
+ VA_CLOSE (ap);
+ return result;
+}
+
+/* The one and only TYPE_STRING. */
+
+struct type string_type = {
+ TYPE_STRING, NULL, NULL, GC_USED
+ UNION_INIT_ZERO
+};
+
+/* Lists of various things. */
+
+static pair_p typedefs;
+static type_p structures;
+static type_p param_structs;
+static pair_p variables;
+
+static void do_scalar_typedef PARAMS ((const char *, struct fileloc *));
+static type_p find_param_structure
+ PARAMS ((type_p t, type_p param[NUM_PARAM]));
+static type_p adjust_field_tree_exp PARAMS ((type_p t, options_p opt));
+static type_p adjust_field_rtx_def PARAMS ((type_p t, options_p opt));
+
+/* Define S as a typedef to T at POS. */
+
+void
+do_typedef (s, t, pos)
+ const char *s;
+ type_p t;
+ struct fileloc *pos;
+{
+ pair_p p;
+
+ for (p = typedefs; p != NULL; p = p->next)
+ if (strcmp (p->name, s) == 0)
+ {
+ if (p->type != t)
+ {
+ error_at_line (pos, "type `%s' previously defined", s);
+ error_at_line (&p->line, "previously defined here");
+ }
+ return;
+ }
+
+ p = xmalloc (sizeof (struct pair));
+ p->next = typedefs;
+ p->name = s;
+ p->type = t;
+ p->line = *pos;
+ typedefs = p;
+}
+
+/* Define S as a typename of a scalar. */
+
+static void
+do_scalar_typedef (s, pos)
+ const char *s;
+ struct fileloc *pos;
+{
+ do_typedef (s, create_scalar_type (s, strlen (s)), pos);
+}
+
+/* Return the type previously defined for S. Use POS to report errors. */
+
+type_p
+resolve_typedef (s, pos)
+ const char *s;
+ struct fileloc *pos;
+{
+ pair_p p;
+ for (p = typedefs; p != NULL; p = p->next)
+ if (strcmp (p->name, s) == 0)
+ return p->type;
+ error_at_line (pos, "unidentified type `%s'", s);
+ return create_scalar_type ("char", 4);
+}
+
+/* Create a new structure with tag NAME (or a union iff ISUNION is nonzero),
+ at POS with fields FIELDS and options O. */
+
+void
+new_structure (name, isunion, pos, fields, o)
+ const char *name;
+ int isunion;
+ struct fileloc *pos;
+ pair_p fields;
+ options_p o;
+{
+ type_p si;
+ type_p s = NULL;
+ lang_bitmap bitmap = get_base_file_bitmap (pos->file);
+
+ for (si = structures; si != NULL; si = si->next)
+ if (strcmp (name, si->u.s.tag) == 0
+ && UNION_P (si) == isunion)
+ {
+ type_p ls = NULL;
+ if (si->kind == TYPE_LANG_STRUCT)
+ {
+ ls = si;
+
+ for (si = ls->u.s.lang_struct; si != NULL; si = si->next)
+ if (si->u.s.bitmap == bitmap)
+ s = si;
+ }
+ else if (si->u.s.line.file != NULL && si->u.s.bitmap != bitmap)
+ {
+ ls = si;
+ si = xcalloc (1, sizeof (struct type));
+ memcpy (si, ls, sizeof (struct type));
+ ls->kind = TYPE_LANG_STRUCT;
+ ls->u.s.lang_struct = si;
+ ls->u.s.fields = NULL;
+ si->next = NULL;
+ si->pointer_to = NULL;
+ si->u.s.lang_struct = ls;
+ }
+ else
+ s = si;
+
+ if (ls != NULL && s == NULL)
+ {
+ s = xcalloc (1, sizeof (struct type));
+ s->next = ls->u.s.lang_struct;
+ ls->u.s.lang_struct = s;
+ s->u.s.lang_struct = ls;
+ }
+ break;
+ }
+
+ if (s == NULL)
+ {
+ s = xcalloc (1, sizeof (struct type));
+ s->next = structures;
+ structures = s;
+ }
+
+ if (s->u.s.line.file != NULL
+ || (s->u.s.lang_struct && (s->u.s.lang_struct->u.s.bitmap & bitmap)))
+ {
+ error_at_line (pos, "duplicate structure definition");
+ error_at_line (&s->u.s.line, "previous definition here");
+ }
+
+ s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
+ s->u.s.tag = name;
+ s->u.s.line = *pos;
+ s->u.s.fields = fields;
+ s->u.s.opt = o;
+ s->u.s.bitmap = bitmap;
+ if (s->u.s.lang_struct)
+ s->u.s.lang_struct->u.s.bitmap |= bitmap;
+}
+
+/* Return the previously-defined structure with tag NAME (or a union
+ iff ISUNION is nonzero), or a new empty structure or union if none
+ was defined previously. */
+
+type_p
+find_structure (name, isunion)
+ const char *name;
+ int isunion;
+{
+ type_p s;
+
+ for (s = structures; s != NULL; s = s->next)
+ if (strcmp (name, s->u.s.tag) == 0
+ && UNION_P (s) == isunion)
+ return s;
+
+ s = xcalloc (1, sizeof (struct type));
+ s->next = structures;
+ structures = s;
+ s->kind = isunion ? TYPE_UNION : TYPE_STRUCT;
+ s->u.s.tag = name;
+ structures = s;
+ return s;
+}
+
+/* Return the previously-defined parameterised structure for structure
+ T and parameters PARAM, or a new parameterised empty structure or
+ union if none was defined previously. */
+
+static type_p
+find_param_structure (t, param)
+ type_p t;
+ type_p param[NUM_PARAM];
+{
+ type_p res;
+
+ for (res = param_structs; res; res = res->next)
+ if (res->u.param_struct.stru == t
+ && memcmp (res->u.param_struct.param, param,
+ sizeof (type_p) * NUM_PARAM) == 0)
+ break;
+ if (res == NULL)
+ {
+ res = xcalloc (1, sizeof (*res));
+ res->kind = TYPE_PARAM_STRUCT;
+ res->next = param_structs;
+ param_structs = res;
+ res->u.param_struct.stru = t;
+ memcpy (res->u.param_struct.param, param, sizeof (type_p) * NUM_PARAM);
+ }
+ return res;
+}
+
+/* Return a scalar type with name NAME. */
+
+type_p
+create_scalar_type (name, name_len)
+ const char *name;
+ size_t name_len;
+{
+ type_p r = xcalloc (1, sizeof (struct type));
+ r->kind = TYPE_SCALAR;
+ r->u.sc = xmemdup (name, name_len, name_len + 1);
+ return r;
+}
+
+/* Return a pointer to T. */
+
+type_p
+create_pointer (t)
+ type_p t;
+{
+ if (! t->pointer_to)
+ {
+ type_p r = xcalloc (1, sizeof (struct type));
+ r->kind = TYPE_POINTER;
+ r->u.p = t;
+ t->pointer_to = r;
+ }
+ return t->pointer_to;
+}
+
+/* Return an array of length LEN. */
+
+type_p
+create_array (t, len)
+ type_p t;
+ const char *len;
+{
+ type_p v;
+
+ v = xcalloc (1, sizeof (*v));
+ v->kind = TYPE_ARRAY;
+ v->u.a.p = t;
+ v->u.a.len = len;
+ return v;
+}
+
+/* Add a variable named S of type T with options O defined at POS,
+ to `variables'. */
+
+void
+note_variable (s, t, o, pos)
+ const char *s;
+ type_p t;
+ options_p o;
+ struct fileloc *pos;
+{
+ pair_p n;
+ n = xmalloc (sizeof (*n));
+ n->name = s;
+ n->type = t;
+ n->line = *pos;
+ n->opt = o;
+ n->next = variables;
+ variables = n;
+}
+
+enum rtx_code {
+#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) ENUM ,
+#include "rtl.def"
+#undef DEF_RTL_EXPR
+ NUM_RTX_CODE
+};
+
+/* We really don't care how long a CONST_DOUBLE is. */
+#define CONST_DOUBLE_FORMAT "ww"
+static const char * const rtx_format[NUM_RTX_CODE] = {
+#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT ,
+#include "rtl.def"
+#undef DEF_RTL_EXPR
+};
+
+static int rtx_next[NUM_RTX_CODE];
+
+/* Generate the contents of the rtx_next array. This really doesn't belong
+ in gengtype at all, but it's needed for adjust_field_rtx_def. */
+
+static void
+gen_rtx_next ()
+{
+ int i;
+ for (i = 0; i < NUM_RTX_CODE; i++)
+ {
+ int k;
+
+ rtx_next[i] = -1;
+ if (strncmp (rtx_format[i], "iuu", 3) == 0)
+ rtx_next[i] = 2;
+ else if (i == COND_EXEC || i == SET || i == EXPR_LIST || i == INSN_LIST)
+ rtx_next[i] = 1;
+ else
+ for (k = strlen (rtx_format[i]) - 1; k >= 0; k--)
+ if (rtx_format[i][k] == 'e' || rtx_format[i][k] == 'u')
+ rtx_next[i] = k;
+ }
+}
+
+/* Write out the contents of the rtx_next array. */
+static void
+write_rtx_next ()
+{
+ outf_p f = get_output_file_with_visibility (NULL);
+ int i;
+
+ oprintf (f, "\n/* Used to implement the RTX_NEXT macro. */\n");
+ oprintf (f, "const unsigned char rtx_next[NUM_RTX_CODE] = {\n");
+ for (i = 0; i < NUM_RTX_CODE; i++)
+ if (rtx_next[i] == -1)
+ oprintf (f, " 0,\n");
+ else
+ oprintf (f,
+ " offsetof (struct rtx_def, fld) + %d * sizeof (rtunion),\n",
+ rtx_next[i]);
+ oprintf (f, "};\n");
+}
+
+/* Handle `special("rtx_def")'. This is a special case for field
+ `fld' of struct rtx_def, which is an array of unions whose values
+ are based in a complex way on the type of RTL. */
+
+static type_p
+adjust_field_rtx_def (t, opt)
+ type_p t;
+ options_p opt ATTRIBUTE_UNUSED;
+{
+ pair_p flds = NULL;
+ options_p nodot;
+ int i;
+ type_p rtx_tp, rtvec_tp, tree_tp, mem_attrs_tp, note_union_tp, scalar_tp;
+ type_p bitmap_tp, basic_block_tp;
+
+ static const char * const rtx_name[NUM_RTX_CODE] = {
+#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) NAME ,
+#include "rtl.def"
+#undef DEF_RTL_EXPR
+ };
+
+ if (t->kind != TYPE_ARRAY)
+ {
+ error_at_line (&lexer_line,
+ "special `rtx_def' must be applied to an array");
+ return &string_type;
+ }
+
+ nodot = xmalloc (sizeof (*nodot));
+ nodot->next = NULL;
+ nodot->name = "dot";
+ nodot->info = "";
+
+ rtx_tp = create_pointer (find_structure ("rtx_def", 0));
+ rtvec_tp = create_pointer (find_structure ("rtvec_def", 0));
+ tree_tp = create_pointer (find_structure ("tree_node", 1));
+ mem_attrs_tp = create_pointer (find_structure ("mem_attrs", 0));
+ bitmap_tp = create_pointer (find_structure ("bitmap_element_def", 0));
+ basic_block_tp = create_pointer (find_structure ("basic_block_def", 0));
+ scalar_tp = create_scalar_type ("rtunion scalar", 14);
+
+ {
+ pair_p note_flds = NULL;
+ int c;
+
+ for (c = 0; c < 3; c++)
+ {
+ pair_p old_note_flds = note_flds;
+
+ note_flds = xmalloc (sizeof (*note_flds));
+ note_flds->line.file = __FILE__;
+ note_flds->line.line = __LINE__;
+ note_flds->name = "rttree";
+ note_flds->type = tree_tp;
+ note_flds->opt = xmalloc (sizeof (*note_flds->opt));
+ note_flds->opt->next = nodot;
+ note_flds->opt->name = "tag";
+ note_flds->next = old_note_flds;
+ }
+
+ note_flds->type = rtx_tp;
+ note_flds->name = "rtx";
+ note_flds->opt->info = "NOTE_INSN_EXPECTED_VALUE";
+ note_flds->next->opt->info = "NOTE_INSN_BLOCK_BEG";
+ note_flds->next->next->opt->info = "NOTE_INSN_BLOCK_END";
+
+ new_structure ("rtx_def_note_subunion", 1, &lexer_line, note_flds, NULL);
+ }
+
+ note_union_tp = find_structure ("rtx_def_note_subunion", 1);
+
+ for (i = 0; i < NUM_RTX_CODE; i++)
+ {
+ pair_p old_flds = flds;
+ pair_p subfields = NULL;
+ size_t aindex, nmindex;
+ const char *sname;
+ char *ftag;
+
+ for (aindex = 0; aindex < strlen (rtx_format[i]); aindex++)
+ {
+ pair_p old_subf = subfields;
+ type_p t;
+ const char *subname;
+
+ switch (rtx_format[i][aindex])
+ {
+ case '*':
+ case 'i':
+ case 'n':
+ case 'w':
+ t = scalar_tp;
+ subname = "rtint";
+ break;
+
+ case '0':
+ if (i == MEM && aindex == 1)
+ t = mem_attrs_tp, subname = "rtmem";
+ else if (i == JUMP_INSN && aindex == 9)
+ t = rtx_tp, subname = "rtx";
+ else if (i == CODE_LABEL && aindex == 4)
+ t = scalar_tp, subname = "rtint";
+ else if (i == CODE_LABEL && aindex == 5)
+ t = rtx_tp, subname = "rtx";
+ else if (i == LABEL_REF
+ && (aindex == 1 || aindex == 2))
+ t = rtx_tp, subname = "rtx";
+ else if (i == NOTE && aindex == 4)
+ t = note_union_tp, subname = "";
+ else if (i == NOTE && aindex >= 7)
+ t = scalar_tp, subname = "rtint";
+ else if (i == ADDR_DIFF_VEC && aindex == 4)
+ t = scalar_tp, subname = "rtint";
+ else if (i == VALUE && aindex == 0)
+ t = scalar_tp, subname = "rtint";
+ else if (i == REG && aindex == 1)
+ t = scalar_tp, subname = "rtint";
+ else if (i == SCRATCH && aindex == 0)
+ t = scalar_tp, subname = "rtint";
+ else if (i == BARRIER && aindex >= 3)
+ t = scalar_tp, subname = "rtint";
+ else
+ {
+ error_at_line (&lexer_line,
+ "rtx type `%s' has `0' in position %lu, can't handle",
+ rtx_name[i], (unsigned long) aindex);
+ t = &string_type;
+ subname = "rtint";
+ }
+ break;
+
+ case 's':
+ case 'S':
+ case 'T':
+ t = &string_type;
+ subname = "rtstr";
+ break;
+
+ case 'e':
+ case 'u':
+ t = rtx_tp;
+ subname = "rtx";
+ break;
+
+ case 'E':
+ case 'V':
+ t = rtvec_tp;
+ subname = "rtvec";
+ break;
+
+ case 't':
+ t = tree_tp;
+ subname = "rttree";
+ break;
+
+ case 'b':
+ t = bitmap_tp;
+ subname = "rtbit";
+ break;
+
+ case 'B':
+ t = basic_block_tp;
+ subname = "bb";
+ break;
+
+ default:
+ error_at_line (&lexer_line,
+ "rtx type `%s' has `%c' in position %lu, can't handle",
+ rtx_name[i], rtx_format[i][aindex],
+ (unsigned long)aindex);
+ t = &string_type;
+ subname = "rtint";
+ break;
+ }
+
+ subfields = xmalloc (sizeof (*subfields));
+ subfields->next = old_subf;
+ subfields->type = t;
+ subfields->name = xasprintf ("[%lu].%s", (unsigned long)aindex,
+ subname);
+ subfields->line.file = __FILE__;
+ subfields->line.line = __LINE__;
+ if (t == note_union_tp)
+ {
+ subfields->opt = xmalloc (sizeof (*subfields->opt));
+ subfields->opt->next = nodot;
+ subfields->opt->name = "desc";
+ subfields->opt->info = "NOTE_LINE_NUMBER (&%0)";
+ }
+ else if (t == basic_block_tp)
+ {
+ /* We don't presently GC basic block structures... */
+ subfields->opt = xmalloc (sizeof (*subfields->opt));
+ subfields->opt->next = nodot;
+ subfields->opt->name = "skip";
+ subfields->opt->info = NULL;
+ }
+ else if ((size_t) rtx_next[i] == aindex)
+ {
+ /* The 'next' field will be marked by the chain_next option. */
+ subfields->opt = xmalloc (sizeof (*subfields->opt));
+ subfields->opt->next = nodot;
+ subfields->opt->name = "skip";
+ subfields->opt->info = NULL;
+ }
+ else
+ subfields->opt = nodot;
+ }
+
+ flds = xmalloc (sizeof (*flds));
+ flds->next = old_flds;
+ flds->name = "";
+ sname = xasprintf ("rtx_def_%s", rtx_name[i]);
+ new_structure (sname, 0, &lexer_line, subfields, NULL);
+ flds->type = find_structure (sname, 0);
+ flds->line.file = __FILE__;
+ flds->line.line = __LINE__;
+ flds->opt = xmalloc (sizeof (*flds->opt));
+ flds->opt->next = nodot;
+ flds->opt->name = "tag";
+ ftag = xstrdup (rtx_name[i]);
+ for (nmindex = 0; nmindex < strlen (ftag); nmindex++)
+ ftag[nmindex] = TOUPPER (ftag[nmindex]);
+ flds->opt->info = ftag;
+ }
+
+ new_structure ("rtx_def_subunion", 1, &lexer_line, flds, nodot);
+ return find_structure ("rtx_def_subunion", 1);
+}
+
+/* Handle `special("tree_exp")'. This is a special case for
+ field `operands' of struct tree_exp, which although it claims to contain
+ pointers to trees, actually sometimes contains pointers to RTL too.
+ Passed T, the old type of the field, and OPT its options. Returns
+ a new type for the field. */
+
+static type_p
+adjust_field_tree_exp (t, opt)
+ type_p t;
+ options_p opt ATTRIBUTE_UNUSED;
+{
+ pair_p flds;
+ options_p nodot;
+ size_t i;
+ static const struct {
+ const char *name;
+ int first_rtl;
+ int num_rtl;
+ } data[] = {
+ { "SAVE_EXPR", 2, 1 },
+ { "GOTO_SUBROUTINE_EXPR", 0, 2 },
+ { "RTL_EXPR", 0, 2 },
+ { "WITH_CLEANUP_EXPR", 2, 1 },
+ { "METHOD_CALL_EXPR", 3, 1 }
+ };
+
+ if (t->kind != TYPE_ARRAY)
+ {
+ error_at_line (&lexer_line,
+ "special `tree_exp' must be applied to an array");
+ return &string_type;
+ }
+
+ nodot = xmalloc (sizeof (*nodot));
+ nodot->next = NULL;
+ nodot->name = "dot";
+ nodot->info = "";
+
+ flds = xmalloc (sizeof (*flds));
+ flds->next = NULL;
+ flds->name = "";
+ flds->type = t;
+ flds->line.file = __FILE__;
+ flds->line.line = __LINE__;
+ flds->opt = xmalloc (sizeof (*flds->opt));
+ flds->opt->next = nodot;
+ flds->opt->name = "length";
+ flds->opt->info = "TREE_CODE_LENGTH (TREE_CODE ((tree) &%0))";
+ {
+ options_p oldopt = flds->opt;
+ flds->opt = xmalloc (sizeof (*flds->opt));
+ flds->opt->next = oldopt;
+ flds->opt->name = "default";
+ flds->opt->info = "";
+ }
+
+ for (i = 0; i < ARRAY_SIZE (data); i++)
+ {
+ pair_p old_flds = flds;
+ pair_p subfields = NULL;
+ int r_index;
+ const char *sname;
+
+ for (r_index = 0;
+ r_index < data[i].first_rtl + data[i].num_rtl;
+ r_index++)
+ {
+ pair_p old_subf = subfields;
+ subfields = xmalloc (sizeof (*subfields));
+ subfields->next = old_subf;
+ subfields->name = xasprintf ("[%d]", r_index);
+ if (r_index < data[i].first_rtl)
+ subfields->type = t->u.a.p;
+ else
+ subfields->type = create_pointer (find_structure ("rtx_def", 0));
+ subfields->line.file = __FILE__;
+ subfields->line.line = __LINE__;
+ subfields->opt = nodot;
+ }
+
+ flds = xmalloc (sizeof (*flds));
+ flds->next = old_flds;
+ flds->name = "";
+ sname = xasprintf ("tree_exp_%s", data[i].name);
+ new_structure (sname, 0, &lexer_line, subfields, NULL);
+ flds->type = find_structure (sname, 0);
+ flds->line.file = __FILE__;
+ flds->line.line = __LINE__;
+ flds->opt = xmalloc (sizeof (*flds->opt));
+ flds->opt->next = nodot;
+ flds->opt->name = "tag";
+ flds->opt->info = data[i].name;
+ }
+
+ new_structure ("tree_exp_subunion", 1, &lexer_line, flds, nodot);
+ return find_structure ("tree_exp_subunion", 1);
+}
+
+/* Perform any special processing on a type T, about to become the type
+ of a field. Return the appropriate type for the field.
+ At present:
+ - Converts pointer-to-char, with no length parameter, to TYPE_STRING;
+ - Similarly for arrays of pointer-to-char;
+ - Converts structures for which a parameter is provided to
+ TYPE_PARAM_STRUCT;
+ - Handles "special" options.
+*/
+
+type_p
+adjust_field_type (t, opt)
+ type_p t;
+ options_p opt;
+{
+ int length_p = 0;
+ const int pointer_p = t->kind == TYPE_POINTER;
+ type_p params[NUM_PARAM];
+ int params_p = 0;
+ int i;
+
+ for (i = 0; i < NUM_PARAM; i++)
+ params[i] = NULL;
+
+ for (; opt; opt = opt->next)
+ if (strcmp (opt->name, "length") == 0)
+ length_p = 1;
+ else if (strcmp (opt->name, "param_is") == 0
+ || (strncmp (opt->name, "param", 5) == 0
+ && ISDIGIT (opt->name[5])
+ && strcmp (opt->name + 6, "_is") == 0))
+ {
+ int num = ISDIGIT (opt->name[5]) ? opt->name[5] - '0' : 0;
+
+ if (! UNION_OR_STRUCT_P (t)
+ && (t->kind != TYPE_POINTER || ! UNION_OR_STRUCT_P (t->u.p)))
+ {
+ error_at_line (&lexer_line,
+ "option `%s' may only be applied to structures or structure pointers",
+ opt->name);
+ return t;
+ }
+
+ params_p = 1;
+ if (params[num] != NULL)
+ error_at_line (&lexer_line, "duplicate `%s' option", opt->name);
+ if (! ISDIGIT (opt->name[5]))
+ params[num] = create_pointer ((type_p) opt->info);
+ else
+ params[num] = (type_p) opt->info;
+ }
+ else if (strcmp (opt->name, "special") == 0)
+ {
+ const char *special_name = (const char *)opt->info;
+ if (strcmp (special_name, "tree_exp") == 0)
+ t = adjust_field_tree_exp (t, opt);
+ else if (strcmp (special_name, "rtx_def") == 0)
+ t = adjust_field_rtx_def (t, opt);
+ else
+ error_at_line (&lexer_line, "unknown special `%s'", special_name);
+ }
+
+ if (params_p)
+ {
+ type_p realt;
+
+ if (pointer_p)
+ t = t->u.p;
+ realt = find_param_structure (t, params);
+ t = pointer_p ? create_pointer (realt) : realt;
+ }
+
+ if (! length_p
+ && pointer_p
+ && t->u.p->kind == TYPE_SCALAR
+ && (strcmp (t->u.p->u.sc, "char") == 0
+ || strcmp (t->u.p->u.sc, "unsigned char") == 0))
+ return &string_type;
+ if (t->kind == TYPE_ARRAY && t->u.a.p->kind == TYPE_POINTER
+ && t->u.a.p->u.p->kind == TYPE_SCALAR
+ && (strcmp (t->u.a.p->u.p->u.sc, "char") == 0
+ || strcmp (t->u.a.p->u.p->u.sc, "unsigned char") == 0))
+ return create_array (&string_type, t->u.a.len);
+
+ return t;
+}
+
+/* Create a union for YYSTYPE, as yacc would do it, given a fieldlist FIELDS
+ and information about the correspondance between token types and fields
+ in TYPEINFO. POS is used for error messages. */
+
+void
+note_yacc_type (o, fields, typeinfo, pos)
+ options_p o;
+ pair_p fields;
+ pair_p typeinfo;
+ struct fileloc *pos;
+{
+ pair_p p;
+ pair_p *p_p;
+
+ for (p = typeinfo; p; p = p->next)
+ {
+ pair_p m;
+
+ if (p->name == NULL)
+ continue;
+
+ if (p->type == (type_p) 1)
+ {
+ pair_p pp;
+ int ok = 0;
+
+ for (pp = typeinfo; pp; pp = pp->next)
+ if (pp->type != (type_p) 1
+ && strcmp (pp->opt->info, p->opt->info) == 0)
+ {
+ ok = 1;
+ break;
+ }
+ if (! ok)
+ continue;
+ }
+
+ for (m = fields; m; m = m->next)
+ if (strcmp (m->name, p->name) == 0)
+ p->type = m->type;
+ if (p->type == NULL)
+ {
+ error_at_line (&p->line,
+ "couldn't match fieldname `%s'", p->name);
+ p->name = NULL;
+ }
+ }
+
+ p_p = &typeinfo;
+ while (*p_p)
+ {
+ pair_p p = *p_p;
+
+ if (p->name == NULL
+ || p->type == (type_p) 1)
+ *p_p = p->next;
+ else
+ p_p = &p->next;
+ }
+
+ new_structure ("yy_union", 1, pos, typeinfo, o);
+ do_typedef ("YYSTYPE", find_structure ("yy_union", 1), pos);
+}
+
+static void process_gc_options PARAMS ((options_p, enum gc_used_enum,
+ int *, int *, int *));
+static void set_gc_used_type PARAMS ((type_p, enum gc_used_enum, type_p *));
+static void set_gc_used PARAMS ((pair_p));
+
+/* Handle OPT for set_gc_used_type. */
+
+static void
+process_gc_options (opt, level, maybe_undef, pass_param, length)
+ options_p opt;
+ enum gc_used_enum level;
+ int *maybe_undef;
+ int *pass_param;
+ int *length;
+{
+ options_p o;
+ for (o = opt; o; o = o->next)
+ if (strcmp (o->name, "ptr_alias") == 0 && level == GC_POINTED_TO)
+ set_gc_used_type ((type_p) o->info, GC_POINTED_TO, NULL);
+ else if (strcmp (o->name, "maybe_undef") == 0)
+ *maybe_undef = 1;
+ else if (strcmp (o->name, "use_params") == 0)
+ *pass_param = 1;
+ else if (strcmp (o->name, "length") == 0)
+ *length = 1;
+}
+
+/* Set the gc_used field of T to LEVEL, and handle the types it references. */
+
+static void
+set_gc_used_type (t, level, param)
+ type_p t;
+ enum gc_used_enum level;
+ type_p param[NUM_PARAM];
+{
+ if (t->gc_used >= level)
+ return;
+
+ t->gc_used = level;
+
+ switch (t->kind)
+ {
+ case TYPE_STRUCT:
+ case TYPE_UNION:
+ {
+ pair_p f;
+ int dummy;
+
+ process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy);
+
+ for (f = t->u.s.fields; f; f = f->next)
+ {
+ int maybe_undef = 0;
+ int pass_param = 0;
+ int length = 0;
+ process_gc_options (f->opt, level, &maybe_undef, &pass_param,
+ &length);
+
+ if (length && f->type->kind == TYPE_POINTER)
+ set_gc_used_type (f->type->u.p, GC_USED, NULL);
+ else if (maybe_undef && f->type->kind == TYPE_POINTER)
+ set_gc_used_type (f->type->u.p, GC_MAYBE_POINTED_TO, NULL);
+ else if (pass_param && f->type->kind == TYPE_POINTER && param)
+ set_gc_used_type (find_param_structure (f->type->u.p, param),
+ GC_POINTED_TO, NULL);
+ else
+ set_gc_used_type (f->type, GC_USED, pass_param ? param : NULL);
+ }
+ break;
+ }
+
+ case TYPE_POINTER:
+ set_gc_used_type (t->u.p, GC_POINTED_TO, NULL);
+ break;
+
+ case TYPE_ARRAY:
+ set_gc_used_type (t->u.a.p, GC_USED, param);
+ break;
+
+ case TYPE_LANG_STRUCT:
+ for (t = t->u.s.lang_struct; t; t = t->next)
+ set_gc_used_type (t, level, param);
+ break;
+
+ case TYPE_PARAM_STRUCT:
+ {
+ int i;
+ for (i = 0; i < NUM_PARAM; i++)
+ if (t->u.param_struct.param[i] != 0)
+ set_gc_used_type (t->u.param_struct.param[i], GC_USED, NULL);
+ }
+ if (t->u.param_struct.stru->gc_used == GC_POINTED_TO)
+ level = GC_POINTED_TO;
+ else
+ level = GC_USED;
+ t->u.param_struct.stru->gc_used = GC_UNUSED;
+ set_gc_used_type (t->u.param_struct.stru, level,
+ t->u.param_struct.param);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Set the gc_used fields of all the types pointed to by VARIABLES. */
+
+static void
+set_gc_used (variables)
+ pair_p variables;
+{
+ pair_p p;
+ for (p = variables; p; p = p->next)
+ set_gc_used_type (p->type, GC_USED, NULL);
+}
+
+/* File mapping routines. For each input file, there is one output .c file
+ (but some output files have many input files), and there is one .h file
+ for the whole build. */
+
+/* The list of output files. */
+static outf_p output_files;
+
+/* The output header file that is included into pretty much every
+ source file. */
+outf_p header_file;
+
+/* Number of files specified in gtfiles. */
+#define NUM_GT_FILES (ARRAY_SIZE (all_files) - 1)
+
+/* Number of files in the language files array. */
+#define NUM_LANG_FILES (ARRAY_SIZE (lang_files) - 1)
+
+/* Length of srcdir name. */
+static int srcdir_len = 0;
+
+#define NUM_BASE_FILES (ARRAY_SIZE (lang_dir_names) - 1)
+outf_p base_files[NUM_BASE_FILES];
+
+static outf_p create_file PARAMS ((const char *, const char *));
+static const char * get_file_basename PARAMS ((const char *));
+
+/* Create and return an outf_p for a new file for NAME, to be called
+ ONAME. */
+
+static outf_p
+create_file (name, oname)
+ const char *name;
+ const char *oname;
+{
+ static const char *const hdr[] = {
+ " Copyright (C) 2002 Free Software Foundation, Inc.\n",
+ "\n",
+ "This file is part of GCC.\n",
+ "\n",
+ "GCC is free software; you can redistribute it and/or modify it under\n",
+ "the terms of the GNU General Public License as published by the Free\n",
+ "Software Foundation; either version 2, or (at your option) any later\n",
+ "version.\n",
+ "\n",
+ "GCC is distributed in the hope that it will be useful, but WITHOUT ANY\n",
+ "WARRANTY; without even the implied warranty of MERCHANTABILITY or\n",
+ "FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n",
+ "for more details.\n",
+ "\n",
+ "You should have received a copy of the GNU General Public License\n",
+ "along with GCC; see the file COPYING. If not, write to the Free\n",
+ "Software Foundation, 59 Temple Place - Suite 330, Boston, MA\n",
+ "02111-1307, USA. */\n",
+ "\n",
+ "/* This file is machine generated. Do not edit. */\n"
+ };
+ outf_p f;
+ size_t i;
+
+ f = xcalloc (sizeof (*f), 1);
+ f->next = output_files;
+ f->name = oname;
+ output_files = f;
+
+ oprintf (f, "/* Type information for %s.\n", name);
+ for (i = 0; i < ARRAY_SIZE (hdr); i++)
+ oprintf (f, "%s", hdr[i]);
+ return f;
+}
+
+/* Print, like fprintf, to O. */
+void
+oprintf VPARAMS ((outf_p o, const char *format, ...))
+{
+ char *s;
+ size_t slength;
+
+ VA_OPEN (ap, format);
+ VA_FIXEDARG (ap, outf_p, o);
+ VA_FIXEDARG (ap, const char *, format);
+ slength = xvasprintf (&s, format, ap);
+
+ if (o->bufused + slength > o->buflength)
+ {
+ size_t new_len = o->buflength;
+ if (new_len == 0)
+ new_len = 1024;
+ do {
+ new_len *= 2;
+ } while (o->bufused + slength >= new_len);
+ o->buf = xrealloc (o->buf, new_len);
+ o->buflength = new_len;
+ }
+ memcpy (o->buf + o->bufused, s, slength);
+ o->bufused += slength;
+ free (s);
+ VA_CLOSE (ap);
+}
+
+/* Open the global header file and the language-specific header files. */
+
+static void
+open_base_files ()
+{
+ size_t i;
+
+ header_file = create_file ("GCC", "gtype-desc.h");
+
+ for (i = 0; i < NUM_BASE_FILES; i++)
+ base_files[i] = create_file (lang_dir_names[i],
+ xasprintf ("gtype-%s.h", lang_dir_names[i]));
+
+ /* gtype-desc.c is a little special, so we create it here. */
+ {
+ /* The order of files here matters very much. */
+ static const char *const ifiles [] = {
+ "config.h", "system.h", "varray.h", "hashtab.h", "splay-tree.h",
+ "bitmap.h", "tree.h", "rtl.h", "function.h", "insn-config.h",
+ "expr.h", "hard-reg-set.h", "basic-block.h", "cselib.h",
+ "insn-addr.h", "ssa.h", "optabs.h", "libfuncs.h",
+ "debug.h", "ggc.h",
+ NULL
+ };
+ const char *const *ifp;
+ outf_p gtype_desc_c;
+
+ gtype_desc_c = create_file ("GCC", "gtype-desc.c");
+ for (ifp = ifiles; *ifp; ifp++)
+ oprintf (gtype_desc_c, "#include \"%s\"\n", *ifp);
+ }
+}
+
+/* Determine the pathname to F relative to $(srcdir). */
+
+static const char *
+get_file_basename (f)
+ const char *f;
+{
+ size_t len;
+ const char *basename;
+ unsigned i;
+
+ basename = strrchr (f, '/');
+
+ if (!basename)
+ return f;
+
+ len = strlen (f);
+ basename++;
+
+ for (i = 1; i < NUM_BASE_FILES; i++)
+ {
+ const char * s1;
+ const char * s2;
+ int l1;
+ int l2;
+ s1 = basename - strlen (lang_dir_names [i]) - 1;
+ s2 = lang_dir_names [i];
+ l1 = strlen (s1);
+ l2 = strlen (s2);
+ if (l1 >= l2 && !memcmp (s1, s2, l2))
+ {
+ basename -= l2 + 1;
+ if ((basename - f - 1) != srcdir_len)
+ abort (); /* Match is wrong - should be preceded by $srcdir. */
+ break;
+ }
+ }
+
+ return basename;
+}
+
+/* Return a bitmap which has bit `1 << BASE_FILE_<lang>' set iff
+ INPUT_FILE is used by <lang>.
+
+ This function should be written to assume that a file _is_ used
+ if the situation is unclear. If it wrongly assumes a file _is_ used,
+ a linker error will result. If it wrongly assumes a file _is not_ used,
+ some GC roots may be missed, which is a much harder-to-debug problem. */
+
+unsigned
+get_base_file_bitmap (input_file)
+ const char *input_file;
+{
+ const char *basename = get_file_basename (input_file);
+ const char *slashpos = strchr (basename, '/');
+ unsigned j;
+ unsigned k;
+ unsigned bitmap;
+
+ if (slashpos)
+ {
+ size_t i;
+ for (i = 1; i < NUM_BASE_FILES; i++)
+ if ((size_t)(slashpos - basename) == strlen (lang_dir_names [i])
+ && memcmp (basename, lang_dir_names[i], strlen (lang_dir_names[i])) == 0)
+ {
+ /* It's in a language directory, set that language. */
+ bitmap = 1 << i;
+ return bitmap;
+ }
+
+ abort (); /* Should have found the language. */
+ }
+
+ /* If it's in any config-lang.in, then set for the languages
+ specified. */
+
+ bitmap = 0;
+
+ for (j = 0; j < NUM_LANG_FILES; j++)
+ {
+ if (!strcmp(input_file, lang_files[j]))
+ {
+ for (k = 0; k < NUM_BASE_FILES; k++)
+ {
+ if (!strcmp(lang_dir_names[k], langs_for_lang_files[j]))
+ bitmap |= (1 << k);
+ }
+ }
+ }
+
+ /* Otherwise, set all languages. */
+ if (!bitmap)
+ bitmap = (1 << NUM_BASE_FILES) - 1;
+
+ return bitmap;
+}
+
+/* An output file, suitable for definitions, that can see declarations
+ made in INPUT_FILE and is linked into every language that uses
+ INPUT_FILE. */
+
+outf_p
+get_output_file_with_visibility (input_file)
+ const char *input_file;
+{
+ outf_p r;
+ size_t len;
+ const char *basename;
+ const char *for_name;
+ const char *output_name;
+
+ /* This can happen when we need a file with visibility on a
+ structure that we've never seen. We have to just hope that it's
+ globally visible. */
+ if (input_file == NULL)
+ input_file = "system.h";
+
+ /* Determine the output file name. */
+ basename = get_file_basename (input_file);
+
+ len = strlen (basename);
+ if ((len > 2 && memcmp (basename+len-2, ".c", 2) == 0)
+ || (len > 2 && memcmp (basename+len-2, ".y", 2) == 0)
+ || (len > 3 && memcmp (basename+len-3, ".in", 3) == 0))
+ {
+ char *s;
+
+ output_name = s = xasprintf ("gt-%s", basename);
+ for (; *s != '.'; s++)
+ if (! ISALNUM (*s) && *s != '-')
+ *s = '-';
+ memcpy (s, ".h", sizeof (".h"));
+ for_name = basename;
+ }
+ else if (strcmp (basename, "c-common.h") == 0)
+ output_name = "gt-c-common.h", for_name = "c-common.c";
+ else if (strcmp (basename, "c-tree.h") == 0)
+ output_name = "gt-c-decl.h", for_name = "c-decl.c";
+ else
+ {
+ size_t i;
+
+ for (i = 0; i < NUM_BASE_FILES; i++)
+ if (memcmp (basename, lang_dir_names[i], strlen (lang_dir_names[i])) == 0
+ && basename[strlen(lang_dir_names[i])] == '/')
+ return base_files[i];
+
+ output_name = "gtype-desc.c";
+ for_name = NULL;
+ }
+
+ /* Look through to see if we've ever seen this output filename before. */
+ for (r = output_files; r; r = r->next)
+ if (strcmp (r->name, output_name) == 0)
+ return r;
+
+ /* If not, create it. */
+ r = create_file (for_name, output_name);
+
+ return r;
+}
+
+/* The name of an output file, suitable for definitions, that can see
+ declarations made in INPUT_FILE and is linked into every language
+ that uses INPUT_FILE. */
+
+const char *
+get_output_file_name (input_file)
+ const char *input_file;
+{
+ return get_output_file_with_visibility (input_file)->name;
+}
+
+/* Copy the output to its final destination,
+ but don't unnecessarily change modification times. */
+
+static void close_output_files PARAMS ((void));
+
+static void
+close_output_files ()
+{
+ outf_p of;
+
+ for (of = output_files; of; of = of->next)
+ {
+ FILE * newfile;
+
+ newfile = fopen (of->name, "r");
+ if (newfile != NULL )
+ {
+ int no_write_p;
+ size_t i;
+
+ for (i = 0; i < of->bufused; i++)
+ {
+ int ch;
+ ch = fgetc (newfile);
+ if (ch == EOF || ch != (unsigned char) of->buf[i])
+ break;
+ }
+ no_write_p = i == of->bufused && fgetc (newfile) == EOF;
+ fclose (newfile);
+
+ if (no_write_p)
+ continue;
+ }
+
+ newfile = fopen (of->name, "w");
+ if (newfile == NULL)
+ {
+ perror ("opening output file");
+ exit (1);
+ }
+ if (fwrite (of->buf, 1, of->bufused, newfile) != of->bufused)
+ {
+ perror ("writing output file");
+ exit (1);
+ }
+ if (fclose (newfile) != 0)
+ {
+ perror ("closing output file");
+ exit (1);
+ }
+ }
+}
+
+struct flist {
+ struct flist *next;
+ int started_p;
+ const char *name;
+ outf_p f;
+};
+
+static void output_escaped_param PARAMS ((outf_p , const char *, const char *,
+ const char *, const char *,
+ struct fileloc *));
+static void output_mangled_typename PARAMS ((outf_p, type_p));
+static void write_gc_structure_fields
+ PARAMS ((outf_p , type_p, const char *, const char *, options_p,
+ int, struct fileloc *, lang_bitmap, type_p *));
+static void write_gc_marker_routine_for_structure PARAMS ((type_p, type_p,
+ type_p *));
+static void write_gc_types PARAMS ((type_p structures, type_p param_structs));
+static void write_enum_defn PARAMS ((type_p structures, type_p param_structs));
+static void put_mangled_filename PARAMS ((outf_p , const char *));
+static void finish_root_table PARAMS ((struct flist *flp, const char *pfx,
+ const char *tname, const char *lastname,
+ const char *name));
+static void write_gc_root PARAMS ((outf_p , pair_p, type_p, const char *, int,
+ struct fileloc *, const char *));
+static void write_gc_roots PARAMS ((pair_p));
+
+static int gc_counter;
+
+/* Print PARAM to OF processing escapes. VAL references the current object,
+ PREV_VAL the object containing the current object, ONAME is the name
+ of the option and LINE is used to print error messages. */
+
+static void
+output_escaped_param (of, param, val, prev_val, oname, line)
+ outf_p of;
+ const char *param;
+ const char *val;
+ const char *prev_val;
+ const char *oname;
+ struct fileloc *line;
+{
+ const char *p;
+
+ for (p = param; *p; p++)
+ if (*p != '%')
+ oprintf (of, "%c", *p);
+ else switch (*++p)
+ {
+ case 'h':
+ oprintf (of, "(%s)", val);
+ break;
+ case '0':
+ oprintf (of, "(*x)");
+ break;
+ case '1':
+ oprintf (of, "(%s)", prev_val);
+ break;
+ case 'a':
+ {
+ const char *pp = val + strlen (val);
+ while (pp[-1] == ']')
+ while (*pp != '[')
+ pp--;
+ oprintf (of, "%s", pp);
+ }
+ break;
+ default:
+ error_at_line (line, "`%s' option contains bad escape %c%c",
+ oname, '%', *p);
+ }
+}
+
+/* Print a mangled name representing T to OF. */
+
+static void
+output_mangled_typename (of, t)
+ outf_p of;
+ type_p t;
+{
+ if (t == NULL)
+ oprintf (of, "Z");
+ else switch (t->kind)
+ {
+ case TYPE_POINTER:
+ oprintf (of, "P");
+ output_mangled_typename (of, t->u.p);
+ break;
+ case TYPE_SCALAR:
+ oprintf (of, "I");
+ break;
+ case TYPE_STRING:
+ oprintf (of, "S");
+ break;
+ case TYPE_STRUCT:
+ case TYPE_UNION:
+ case TYPE_LANG_STRUCT:
+ oprintf (of, "%lu%s", (unsigned long) strlen (t->u.s.tag), t->u.s.tag);
+ break;
+ case TYPE_PARAM_STRUCT:
+ {
+ int i;
+ for (i = 0; i < NUM_PARAM; i++)
+ if (t->u.param_struct.param[i] != NULL)
+ output_mangled_typename (of, t->u.param_struct.param[i]);
+ output_mangled_typename (of, t->u.param_struct.stru);
+ }
+ break;
+ case TYPE_ARRAY:
+ abort ();
+ }
+}
+
+/* Write out code to OF which marks the fields of S. VAL references
+ the current object, PREV_VAL the object containing the current
+ object, OPTS is a list of options to apply, INDENT is the current
+ indentation level, LINE is used to print error messages, BITMAP
+ indicates which languages to print the structure for, and PARAM is
+ the current parameter (from an enclosing param_is option). */
+
+static void
+write_gc_structure_fields (of, s, val, prev_val, opts, indent, line, bitmap,
+ param)
+ outf_p of;
+ type_p s;
+ const char *val;
+ const char *prev_val;
+ options_p opts;
+ int indent;
+ struct fileloc *line;
+ lang_bitmap bitmap;
+ type_p * param;
+{
+ pair_p f;
+ int seen_default = 0;
+
+ if (! s->u.s.line.file)
+ error_at_line (line, "incomplete structure `%s'", s->u.s.tag);
+ else if ((s->u.s.bitmap & bitmap) != bitmap)
+ {
+ error_at_line (line, "structure defined for mismatching languages");
+ error_at_line (&s->u.s.line, "one structure defined here");
+ }
+
+ if (s->kind == TYPE_UNION)
+ {
+ const char *tagexpr = NULL;
+ options_p oo;
+
+ for (oo = opts; oo; oo = oo->next)
+ if (strcmp (oo->name, "desc") == 0)
+ tagexpr = (const char *)oo->info;
+ if (tagexpr == NULL)
+ {
+ tagexpr = "1";
+ error_at_line (line, "missing `desc' option");
+ }
+
+ oprintf (of, "%*sswitch (", indent, "");
+ output_escaped_param (of, tagexpr, val, prev_val, "desc", line);
+ oprintf (of, ")\n");
+ indent += 2;
+ oprintf (of, "%*s{\n", indent, "");
+ }
+
+ for (f = s->u.s.fields; f; f = f->next)
+ {
+ const char *tagid = NULL;
+ const char *length = NULL;
+ int skip_p = 0;
+ int default_p = 0;
+ int maybe_undef_p = 0;
+ int use_param_num = -1;
+ int use_params_p = 0;
+ int needs_cast_p = 0;
+ options_p oo;
+ type_p t = f->type;
+ const char *dot = ".";
+
+ for (oo = f->opt; oo; oo = oo->next)
+ if (strcmp (oo->name, "length") == 0)
+ length = (const char *)oo->info;
+ else if (strcmp (oo->name, "maybe_undef") == 0)
+ maybe_undef_p = 1;
+ else if (strcmp (oo->name, "tag") == 0)
+ tagid = (const char *)oo->info;
+ else if (strcmp (oo->name, "special") == 0)
+ ;
+ else if (strcmp (oo->name, "skip") == 0)
+ skip_p = 1;
+ else if (strcmp (oo->name, "default") == 0)
+ default_p = 1;
+ else if (strcmp (oo->name, "desc") == 0)
+ ;
+ else if (strcmp (oo->name, "descbits") == 0)
+ ;
+ else if (strcmp (oo->name, "param_is") == 0)
+ ;
+ else if (strncmp (oo->name, "use_param", 9) == 0
+ && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
+ use_param_num = oo->name[9] == '\0' ? 0 : oo->name[9] - '0';
+ else if (strcmp (oo->name, "use_params") == 0)
+ use_params_p = 1;
+ else if (strcmp (oo->name, "dot") == 0)
+ dot = (const char *)oo->info;
+ else
+ error_at_line (&f->line, "unknown field option `%s'\n", oo->name);
+
+ if (skip_p)
+ continue;
+
+ if (use_params_p)
+ {
+ int pointer_p = t->kind == TYPE_POINTER;
+
+ if (pointer_p)
+ t = t->u.p;
+ t = find_param_structure (t, param);
+ if (pointer_p)
+ t = create_pointer (t);
+ }
+
+ if (use_param_num != -1)
+ {
+ if (param != NULL && param[use_param_num] != NULL)
+ {
+ type_p nt = param[use_param_num];
+
+ if (t->kind == TYPE_ARRAY)
+ nt = create_array (nt, t->u.a.len);
+ else if (length != NULL && t->kind == TYPE_POINTER)
+ nt = create_pointer (nt);
+ needs_cast_p = (t->kind != TYPE_POINTER
+ && nt->kind == TYPE_POINTER);
+ t = nt;
+ }
+ else if (s->kind != TYPE_UNION)
+ error_at_line (&f->line, "no parameter defined");
+ }
+
+ if (t->kind == TYPE_SCALAR
+ || (t->kind == TYPE_ARRAY
+ && t->u.a.p->kind == TYPE_SCALAR))
+ continue;
+
+ seen_default |= default_p;
+
+ if (maybe_undef_p
+ && (t->kind != TYPE_POINTER
+ || t->u.p->kind != TYPE_STRUCT))
+ error_at_line (&f->line,
+ "field `%s' has invalid option `maybe_undef_p'\n",
+ f->name);
+ if (s->kind == TYPE_UNION)
+ {
+ if (tagid)
+ {
+ oprintf (of, "%*scase %s:\n", indent, "", tagid);
+
+ }
+ else if (default_p)
+ {
+ oprintf (of, "%*sdefault:\n", indent, "");
+ }
+ else
+ {
+ error_at_line (&f->line, "field `%s' has no tag", f->name);
+ continue;
+ }
+ indent += 2;
+ }
+
+ switch (t->kind)
+ {
+ case TYPE_STRING:
+ /* Do nothing; strings go in the string pool. */
+ break;
+
+ case TYPE_LANG_STRUCT:
+ {
+ type_p ti;
+ for (ti = t->u.s.lang_struct; ti; ti = ti->next)
+ if (ti->u.s.bitmap & bitmap)
+ {
+ t = ti;
+ break;
+ }
+ if (ti == NULL)
+ {
+ error_at_line (&f->line,
+ "structure not defined for this language");
+ break;
+ }
+ }
+ /* Fall through... */
+ case TYPE_STRUCT:
+ case TYPE_UNION:
+ {
+ char *newval;
+
+ newval = xasprintf ("%s%s%s", val, dot, f->name);
+ write_gc_structure_fields (of, t, newval, val, f->opt, indent,
+ &f->line, bitmap, param);
+ free (newval);
+ break;
+ }
+
+ case TYPE_POINTER:
+ if (! length)
+ {
+ if (maybe_undef_p
+ && t->u.p->u.s.line.file == NULL)
+ oprintf (of, "%*sif (%s%s%s) abort();\n", indent, "",
+ val, dot, f->name);
+ else if (UNION_OR_STRUCT_P (t->u.p)
+ || t->u.p->kind == TYPE_PARAM_STRUCT)
+ {
+ oprintf (of, "%*sgt_ggc_m_", indent, "");
+ output_mangled_typename (of, t->u.p);
+ oprintf (of, " (");
+ if (needs_cast_p)
+ oprintf (of, "(%s %s *)",
+ UNION_P (t->u.p) ? "union" : "struct",
+ t->u.p->u.s.tag);
+ oprintf (of, "%s%s%s);\n", val, dot, f->name);
+ }
+ else
+ error_at_line (&f->line, "field `%s' is pointer to scalar",
+ f->name);
+ break;
+ }
+ else if (t->u.p->kind == TYPE_SCALAR
+ || t->u.p->kind == TYPE_STRING)
+ oprintf (of, "%*sggc_mark (%s%s%s);\n", indent, "",
+ val, dot, f->name);
+ else
+ {
+ int loopcounter = ++gc_counter;
+
+ oprintf (of, "%*sif (%s%s%s != NULL) {\n", indent, "",
+ val, dot, f->name);
+ indent += 2;
+ oprintf (of, "%*ssize_t i%d;\n", indent, "", loopcounter);
+ oprintf (of, "%*sggc_set_mark (%s%s%s);\n", indent, "",
+ val, dot, f->name);
+ oprintf (of, "%*sfor (i%d = 0; i%d < (size_t)(", indent, "",
+ loopcounter, loopcounter);
+ output_escaped_param (of, length, val, prev_val, "length", line);
+ oprintf (of, "); i%d++) {\n", loopcounter);
+ indent += 2;
+ switch (t->u.p->kind)
+ {
+ case TYPE_STRUCT:
+ case TYPE_UNION:
+ {
+ char *newval;
+
+ newval = xasprintf ("%s%s%s[i%d]", val, dot, f->name,
+ loopcounter);
+ write_gc_structure_fields (of, t->u.p, newval, val,
+ f->opt, indent, &f->line,
+ bitmap, param);
+ free (newval);
+ break;
+ }
+ case TYPE_POINTER:
+ if (UNION_OR_STRUCT_P (t->u.p->u.p)
+ || t->u.p->u.p->kind == TYPE_PARAM_STRUCT)
+ {
+ oprintf (of, "%*sgt_ggc_m_", indent, "");
+ output_mangled_typename (of, t->u.p->u.p);
+ oprintf (of, " (%s%s%s[i%d]);\n", val, dot, f->name,
+ loopcounter);
+ }
+ else
+ error_at_line (&f->line,
+ "field `%s' is array of pointer to scalar",
+ f->name);
+ break;
+ default:
+ error_at_line (&f->line,
+ "field `%s' is array of unimplemented type",
+ f->name);
+ break;
+ }
+ indent -= 2;
+ oprintf (of, "%*s}\n", indent, "");
+ indent -= 2;
+ oprintf (of, "%*s}\n", indent, "");
+ }
+ break;
+
+ case TYPE_ARRAY:
+ {
+ int loopcounter = ++gc_counter;
+ type_p ta;
+ int i;
+
+ if (! length &&
+ (strcmp (t->u.a.len, "0") == 0
+ || strcmp (t->u.a.len, "1") == 0))
+ error_at_line (&f->line,
+ "field `%s' is array of size %s",
+ f->name, t->u.a.len);
+
+ /* Arrays of scalars can be ignored. */
+ for (ta = t; ta->kind == TYPE_ARRAY; ta = ta->u.a.p)
+ ;
+ if (ta->kind == TYPE_SCALAR
+ || ta->kind == TYPE_STRING)
+ break;
+
+ oprintf (of, "%*s{\n", indent, "");
+ indent += 2;
+
+ for (ta = t, i = 0; ta->kind == TYPE_ARRAY; ta = ta->u.a.p, i++)
+ {
+ oprintf (of, "%*ssize_t i%d_%d;\n",
+ indent, "", loopcounter, i);
+ oprintf (of, "%*sconst size_t ilimit%d_%d = (",
+ indent, "", loopcounter, i);
+ if (i == 0 && length != NULL)
+ output_escaped_param (of, length, val, prev_val,
+ "length", line);
+ else
+ oprintf (of, "%s", ta->u.a.len);
+ oprintf (of, ");\n");
+ }
+
+ for (ta = t, i = 0; ta->kind == TYPE_ARRAY; ta = ta->u.a.p, i++)
+ {
+ oprintf (of,
+ "%*sfor (i%d_%d = 0; i%d_%d < ilimit%d_%d; i%d_%d++) {\n",
+ indent, "", loopcounter, i, loopcounter, i,
+ loopcounter, i, loopcounter, i);
+ indent += 2;
+ }
+
+ if (ta->kind == TYPE_POINTER
+ && (UNION_OR_STRUCT_P (ta->u.p)
+ || ta->u.p->kind == TYPE_PARAM_STRUCT))
+ {
+ oprintf (of, "%*sgt_ggc_m_", indent, "");
+ output_mangled_typename (of, ta->u.p);
+ oprintf (of, " (%s%s%s", val, dot, f->name);
+ for (ta = t, i = 0;
+ ta->kind == TYPE_ARRAY;
+ ta = ta->u.a.p, i++)
+ oprintf (of, "[i%d_%d]", loopcounter, i);
+ oprintf (of, ");\n");
+ }
+ else if (ta->kind == TYPE_STRUCT || ta->kind == TYPE_UNION)
+ {
+ char *newval;
+ int len;
+
+ len = strlen (val) + strlen (f->name) + 2;
+ for (ta = t; ta->kind == TYPE_ARRAY; ta = ta->u.a.p)
+ len += sizeof ("[i_]") + 2*6;
+
+ newval = xmalloc (len);
+ sprintf (newval, "%s%s%s", val, dot, f->name);
+ for (ta = t, i = 0;
+ ta->kind == TYPE_ARRAY;
+ ta = ta->u.a.p, i++)
+ sprintf (newval + strlen (newval), "[i%d_%d]",
+ loopcounter, i);
+ write_gc_structure_fields (of, t->u.p, newval, val,
+ f->opt, indent, &f->line, bitmap,
+ param);
+ free (newval);
+ }
+ else if (ta->kind == TYPE_POINTER && ta->u.p->kind == TYPE_SCALAR
+ && use_param_num != -1 && param == NULL)
+ oprintf (of, "%*sabort();\n", indent, "");
+ else
+ error_at_line (&f->line,
+ "field `%s' is array of unimplemented type",
+ f->name);
+ for (ta = t, i = 0; ta->kind == TYPE_ARRAY; ta = ta->u.a.p, i++)
+ {
+ indent -= 2;
+ oprintf (of, "%*s}\n", indent, "");
+ }
+
+ indent -= 2;
+ oprintf (of, "%*s}\n", indent, "");
+ break;
+ }
+
+ default:
+ error_at_line (&f->line,
+ "field `%s' is unimplemented type",
+ f->name);
+ break;
+ }
+
+ if (s->kind == TYPE_UNION)
+ {
+ oprintf (of, "%*sbreak;\n", indent, "");
+ indent -= 2;
+ }
+ }
+ if (s->kind == TYPE_UNION)
+ {
+ if (! seen_default)
+ {
+ oprintf (of, "%*sdefault:\n", indent, "");
+ oprintf (of, "%*s break;\n", indent, "");
+ }
+ oprintf (of, "%*s}\n", indent, "");
+ indent -= 2;
+ }
+}
+
+/* Write out a marker routine for S. PARAM is the parameter from an
+ enclosing PARAM_IS option. */
+
+static void
+write_gc_marker_routine_for_structure (orig_s, s, param)
+ type_p orig_s;
+ type_p s;
+ type_p * param;
+{
+ outf_p f;
+ const char *fn = s->u.s.line.file;
+ int i;
+ const char *chain_next = NULL;
+ const char *chain_prev = NULL;
+ options_p opt;
+
+ /* This is a hack, and not the good kind either. */
+ for (i = NUM_PARAM - 1; i >= 0; i--)
+ if (param && param[i] && param[i]->kind == TYPE_POINTER
+ && UNION_OR_STRUCT_P (param[i]->u.p))
+ fn = param[i]->u.p->u.s.line.file;
+
+ f = get_output_file_with_visibility (fn);
+
+ for (opt = s->u.s.opt; opt; opt = opt->next)
+ if (strcmp (opt->name, "chain_next") == 0)
+ chain_next = (const char *) opt->info;
+ else if (strcmp (opt->name, "chain_prev") == 0)
+ chain_prev = (const char *) opt->info;
+
+ if (chain_prev != NULL && chain_next == NULL)
+ error_at_line (&s->u.s.line, "chain_prev without chain_next");
+
+ oprintf (f, "\n");
+ oprintf (f, "void\n");
+ if (param == NULL)
+ oprintf (f, "gt_ggc_mx_%s", s->u.s.tag);
+ else
+ {
+ oprintf (f, "gt_ggc_m_");
+ output_mangled_typename (f, orig_s);
+ }
+ oprintf (f, " (x_p)\n");
+ oprintf (f, " void *x_p;\n");
+ oprintf (f, "{\n");
+ oprintf (f, " %s %s * %sx = (%s %s *)x_p;\n",
+ s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
+ chain_next == NULL ? "const " : "",
+ s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
+ if (chain_next != NULL)
+ oprintf (f, " %s %s * xlimit = x;\n",
+ s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
+ if (chain_next == NULL)
+ oprintf (f, " if (ggc_test_and_set_mark (x))\n");
+ else
+ {
+ oprintf (f, " while (ggc_test_and_set_mark (xlimit))\n");
+ oprintf (f, " xlimit = (");
+ output_escaped_param (f, chain_next, "*xlimit", "*xlimit",
+ "chain_next", &s->u.s.line);
+ oprintf (f, ");\n");
+ if (chain_prev != NULL)
+ {
+ oprintf (f, " if (x != xlimit)\n");
+ oprintf (f, " for (;;)\n");
+ oprintf (f, " {\n");
+ oprintf (f, " %s %s * const xprev = (",
+ s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
+ output_escaped_param (f, chain_prev, "*x", "*x",
+ "chain_prev", &s->u.s.line);
+ oprintf (f, ");\n");
+ oprintf (f, " if (xprev == NULL) break;\n");
+ oprintf (f, " x = xprev;\n");
+ oprintf (f, " ggc_set_mark (xprev);\n");
+ oprintf (f, " }\n");
+ }
+ oprintf (f, " while (x != xlimit)\n");
+ }
+ oprintf (f, " {\n");
+
+ gc_counter = 0;
+ write_gc_structure_fields (f, s, "(*x)", "not valid postage",
+ s->u.s.opt, 6, &s->u.s.line, s->u.s.bitmap,
+ param);
+
+ if (chain_next != NULL)
+ {
+ oprintf (f, " x = (");
+ output_escaped_param (f, chain_next, "*x", "*x",
+ "chain_next", &s->u.s.line);
+ oprintf (f, ");\n");
+ }
+
+ oprintf (f, " }\n");
+ oprintf (f, "}\n");
+}
+
+/* Write out marker routines for STRUCTURES and PARAM_STRUCTS. */
+
+static void
+write_gc_types (structures, param_structs)
+ type_p structures;
+ type_p param_structs;
+{
+ type_p s;
+
+ oprintf (header_file, "\n/* GC marker procedures. */\n");
+ for (s = structures; s; s = s->next)
+ if (s->gc_used == GC_POINTED_TO
+ || s->gc_used == GC_MAYBE_POINTED_TO)
+ {
+ options_p opt;
+
+ if (s->gc_used == GC_MAYBE_POINTED_TO
+ && s->u.s.line.file == NULL)
+ continue;
+
+ oprintf (header_file, "#define gt_ggc_m_");
+ output_mangled_typename (header_file, s);
+ oprintf (header_file, "(X) do { \\\n");
+ oprintf (header_file,
+ " if (X != NULL) gt_ggc_mx_%s (X);\\\n", s->u.s.tag);
+ oprintf (header_file,
+ " } while (0)\n");
+
+ for (opt = s->u.s.opt; opt; opt = opt->next)
+ if (strcmp (opt->name, "ptr_alias") == 0)
+ {
+ type_p t = (type_p) opt->info;
+ if (t->kind == TYPE_STRUCT
+ || t->kind == TYPE_UNION
+ || t->kind == TYPE_LANG_STRUCT)
+ oprintf (header_file,
+ "#define gt_ggc_mx_%s gt_ggc_mx_%s\n",
+ s->u.s.tag, t->u.s.tag);
+ else
+ error_at_line (&s->u.s.line,
+ "structure alias is not a structure");
+ break;
+ }
+ if (opt)
+ continue;
+
+ /* Declare the marker procedure only once. */
+ oprintf (header_file,
+ "extern void gt_ggc_mx_%s PARAMS ((void *));\n",
+ s->u.s.tag);
+
+ if (s->u.s.line.file == NULL)
+ {
+ fprintf (stderr, "warning: structure `%s' used but not defined\n",
+ s->u.s.tag);
+ continue;
+ }
+
+ if (s->kind == TYPE_LANG_STRUCT)
+ {
+ type_p ss;
+ for (ss = s->u.s.lang_struct; ss; ss = ss->next)
+ write_gc_marker_routine_for_structure (s, ss, NULL);
+ }
+ else
+ write_gc_marker_routine_for_structure (s, s, NULL);
+ }
+
+ for (s = param_structs; s; s = s->next)
+ if (s->gc_used == GC_POINTED_TO)
+ {
+ type_p * param = s->u.param_struct.param;
+ type_p stru = s->u.param_struct.stru;
+
+ /* Declare the marker procedure. */
+ oprintf (header_file, "extern void gt_ggc_m_");
+ output_mangled_typename (header_file, s);
+ oprintf (header_file, " PARAMS ((void *));\n");
+
+ if (stru->u.s.line.file == NULL)
+ {
+ fprintf (stderr, "warning: structure `%s' used but not defined\n",
+ s->u.s.tag);
+ continue;
+ }
+
+ if (stru->kind == TYPE_LANG_STRUCT)
+ {
+ type_p ss;
+ for (ss = stru->u.s.lang_struct; ss; ss = ss->next)
+ write_gc_marker_routine_for_structure (s, ss, param);
+ }
+ else
+ write_gc_marker_routine_for_structure (s, stru, param);
+ }
+}
+
+/* Write out the 'enum' definition for gt_types_enum. */
+
+static void
+write_enum_defn (structures, param_structs)
+ type_p structures;
+ type_p param_structs;
+{
+ type_p s;
+
+ oprintf (header_file, "\n/* Enumeration of types known. */\n");
+ oprintf (header_file, "enum gt_types_enum {\n");
+ for (s = structures; s; s = s->next)
+ if (s->gc_used == GC_POINTED_TO
+ || s->gc_used == GC_MAYBE_POINTED_TO)
+ {
+ if (s->gc_used == GC_MAYBE_POINTED_TO
+ && s->u.s.line.file == NULL)
+ continue;
+
+ oprintf (header_file, " gt_ggc_e_");
+ output_mangled_typename (header_file, s);
+ oprintf (header_file, ", \n");
+ }
+ for (s = param_structs; s; s = s->next)
+ if (s->gc_used == GC_POINTED_TO)
+ {
+ oprintf (header_file, " gt_e_");
+ output_mangled_typename (header_file, s);
+ oprintf (header_file, ", \n");
+ }
+ oprintf (header_file, " gt_types_enum_last\n");
+ oprintf (header_file, "};\n");
+}
+
+
+/* Mangle FN and print it to F. */
+
+static void
+put_mangled_filename (f, fn)
+ outf_p f;
+ const char *fn;
+{
+ const char *name = get_output_file_name (fn);
+ for (; *name != 0; name++)
+ if (ISALNUM (*name))
+ oprintf (f, "%c", *name);
+ else
+ oprintf (f, "%c", '_');
+}
+
+/* Finish off the currently-created root tables in FLP. PFX, TNAME,
+ LASTNAME, and NAME are all strings to insert in various places in
+ the resulting code. */
+
+static void
+finish_root_table (flp, pfx, lastname, tname, name)
+ struct flist *flp;
+ const char *pfx;
+ const char *tname;
+ const char *lastname;
+ const char *name;
+{
+ struct flist *fli2;
+ unsigned started_bitmap = 0;
+
+ for (fli2 = flp; fli2; fli2 = fli2->next)
+ if (fli2->started_p)
+ {
+ oprintf (fli2->f, " %s\n", lastname);
+ oprintf (fli2->f, "};\n\n");
+ }
+
+ for (fli2 = flp; fli2; fli2 = fli2->next)
+ if (fli2->started_p)
+ {
+ lang_bitmap bitmap = get_base_file_bitmap (fli2->name);
+ int fnum;
+
+ for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
+ if (bitmap & 1)
+ {
+ oprintf (base_files[fnum],
+ "extern const struct %s gt_ggc_%s_",
+ tname, pfx);
+ put_mangled_filename (base_files[fnum], fli2->name);
+ oprintf (base_files[fnum], "[];\n");
+ }
+ }
+
+ for (fli2 = flp; fli2; fli2 = fli2->next)
+ if (fli2->started_p)
+ {
+ lang_bitmap bitmap = get_base_file_bitmap (fli2->name);
+ int fnum;
+
+ fli2->started_p = 0;
+
+ for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
+ if (bitmap & 1)
+ {
+ if (! (started_bitmap & (1 << fnum)))
+ {
+ oprintf (base_files [fnum],
+ "const struct %s * const %s[] = {\n",
+ tname, name);
+ started_bitmap |= 1 << fnum;
+ }
+ oprintf (base_files[fnum], " gt_ggc_%s_", pfx);
+ put_mangled_filename (base_files[fnum], fli2->name);
+ oprintf (base_files[fnum], ",\n");
+ }
+ }
+
+ {
+ unsigned bitmap;
+ int fnum;
+
+ for (bitmap = started_bitmap, fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
+ if (bitmap & 1)
+ {
+ oprintf (base_files[fnum], " NULL\n");
+ oprintf (base_files[fnum], "};\n");
+ }
+ }
+}
+
+/* Write out to F the table entry and any marker routines needed to
+ mark NAME as TYPE. The original variable is V, at LINE.
+ HAS_LENGTH is nonzero iff V was a variable-length array. IF_MARKED
+ is nonzero iff we are building the root table for hash table caches. */
+
+static void
+write_gc_root (f, v, type, name, has_length, line, if_marked)
+ outf_p f;
+ pair_p v;
+ type_p type;
+ const char *name;
+ int has_length;
+ struct fileloc *line;
+ const char *if_marked;
+{
+ switch (type->kind)
+ {
+ case TYPE_STRUCT:
+ {
+ pair_p fld;
+ for (fld = type->u.s.fields; fld; fld = fld->next)
+ {
+ int skip_p = 0;
+ const char *desc = NULL;
+ options_p o;
+
+ for (o = fld->opt; o; o = o->next)
+ if (strcmp (o->name, "skip") == 0)
+ skip_p = 1;
+ else if (strcmp (o->name, "desc") == 0)
+ desc = (const char *)o->info;
+ else
+ error_at_line (line,
+ "field `%s' of global `%s' has unknown option `%s'",
+ fld->name, name, o->name);
+
+ if (skip_p)
+ continue;
+ else if (desc && fld->type->kind == TYPE_UNION)
+ {
+ pair_p validf = NULL;
+ pair_p ufld;
+
+ for (ufld = fld->type->u.s.fields; ufld; ufld = ufld->next)
+ {
+ const char *tag = NULL;
+ options_p oo;
+
+ for (oo = ufld->opt; oo; oo = oo->next)
+ if (strcmp (oo->name, "tag") == 0)
+ tag = (const char *)oo->info;
+ if (tag == NULL || strcmp (tag, desc) != 0)
+ continue;
+ if (validf != NULL)
+ error_at_line (line,
+ "both `%s.%s.%s' and `%s.%s.%s' have tag `%s'",
+ name, fld->name, validf->name,
+ name, fld->name, ufld->name,
+ tag);
+ validf = ufld;
+ }
+ if (validf != NULL)
+ {
+ char *newname;
+ newname = xasprintf ("%s.%s.%s",
+ name, fld->name, validf->name);
+ write_gc_root (f, v, validf->type, newname, 0, line,
+ if_marked);
+ free (newname);
+ }
+ }
+ else if (desc)
+ error_at_line (line,
+ "global `%s.%s' has `desc' option but is not union",
+ name, fld->name);
+ else
+ {
+ char *newname;
+ newname = xasprintf ("%s.%s", name, fld->name);
+ write_gc_root (f, v, fld->type, newname, 0, line, if_marked);
+ free (newname);
+ }
+ }
+ }
+ break;
+
+ case TYPE_ARRAY:
+ {
+ char *newname;
+ newname = xasprintf ("%s[0]", name);
+ write_gc_root (f, v, type->u.a.p, newname, has_length, line, if_marked);
+ free (newname);
+ }
+ break;
+
+ case TYPE_POINTER:
+ {
+ type_p ap, tp;
+
+ oprintf (f, " {\n");
+ oprintf (f, " &%s,\n", name);
+ oprintf (f, " 1");
+
+ for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p)
+ if (ap->u.a.len[0])
+ oprintf (f, " * (%s)", ap->u.a.len);
+ else if (ap == v->type)
+ oprintf (f, " * ARRAY_SIZE (%s)", v->name);
+ oprintf (f, ",\n");
+ oprintf (f, " sizeof (%s", v->name);
+ for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p)
+ oprintf (f, "[0]");
+ oprintf (f, "),\n");
+
+ tp = type->u.p;
+
+ if (! has_length && UNION_OR_STRUCT_P (tp))
+ {
+ oprintf (f, " &gt_ggc_mx_%s\n", tp->u.s.tag);
+ }
+ else if (! has_length && tp->kind == TYPE_PARAM_STRUCT)
+ {
+ oprintf (f, " &gt_ggc_m_");
+ output_mangled_typename (f, tp);
+ }
+ else if (has_length
+ && (tp->kind == TYPE_POINTER || UNION_OR_STRUCT_P (tp)))
+ {
+ oprintf (f, " &gt_ggc_ma_%s", name);
+ }
+ else
+ {
+ error_at_line (line,
+ "global `%s' is pointer to unimplemented type",
+ name);
+ }
+ if (if_marked)
+ oprintf (f, ",\n &%s", if_marked);
+ oprintf (f, "\n },\n");
+ }
+ break;
+
+ case TYPE_SCALAR:
+ case TYPE_STRING:
+ break;
+
+ default:
+ error_at_line (line,
+ "global `%s' is unimplemented type",
+ name);
+ }
+}
+
+/* Output a table describing the locations and types of VARIABLES. */
+
+static void
+write_gc_roots (variables)
+ pair_p variables;
+{
+ pair_p v;
+ struct flist *flp = NULL;
+
+ for (v = variables; v; v = v->next)
+ {
+ outf_p f = get_output_file_with_visibility (v->line.file);
+ struct flist *fli;
+ const char *length = NULL;
+ int deletable_p = 0;
+ options_p o;
+
+ for (o = v->opt; o; o = o->next)
+ if (strcmp (o->name, "length") == 0)
+ length = (const char *)o->info;
+ else if (strcmp (o->name, "deletable") == 0)
+ deletable_p = 1;
+ else if (strcmp (o->name, "param_is") == 0)
+ ;
+ else if (strncmp (o->name, "param", 5) == 0
+ && ISDIGIT (o->name[5])
+ && strcmp (o->name + 6, "_is") == 0)
+ ;
+ else if (strcmp (o->name, "if_marked") == 0)
+ ;
+ else
+ error_at_line (&v->line,
+ "global `%s' has unknown option `%s'",
+ v->name, o->name);
+
+ for (fli = flp; fli; fli = fli->next)
+ if (fli->f == f)
+ break;
+ if (fli == NULL)
+ {
+ fli = xmalloc (sizeof (*fli));
+ fli->f = f;
+ fli->next = flp;
+ fli->started_p = 0;
+ fli->name = v->line.file;
+ flp = fli;
+
+ oprintf (f, "\n/* GC roots. */\n\n");
+ }
+
+ if (! deletable_p
+ && length
+ && v->type->kind == TYPE_POINTER
+ && (v->type->u.p->kind == TYPE_POINTER
+ || v->type->u.p->kind == TYPE_STRUCT))
+ {
+ oprintf (f, "static void gt_ggc_ma_%s PARAMS ((void *));\n",
+ v->name);
+ oprintf (f, "static void\ngt_ggc_ma_%s (x_p)\n void *x_p;\n",
+ v->name);
+ oprintf (f, "{\n");
+ oprintf (f, " size_t i;\n");
+
+ if (v->type->u.p->kind == TYPE_POINTER)
+ {
+ type_p s = v->type->u.p->u.p;
+
+ oprintf (f, " %s %s ** const x = (%s %s **)x_p;\n",
+ s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
+ s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
+ oprintf (f, " if (ggc_test_and_set_mark (x))\n");
+ oprintf (f, " for (i = 0; i < (%s); i++)\n", length);
+ if (! UNION_OR_STRUCT_P (s)
+ && ! s->kind == TYPE_PARAM_STRUCT)
+ {
+ error_at_line (&v->line,
+ "global `%s' has unsupported ** type",
+ v->name);
+ continue;
+ }
+
+ oprintf (f, " gt_ggc_m_");
+ output_mangled_typename (f, s);
+ oprintf (f, " (x[i]);\n");
+ }
+ else
+ {
+ type_p s = v->type->u.p;
+
+ oprintf (f, " %s %s * const x = (%s %s *)x_p;\n",
+ s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag,
+ s->kind == TYPE_UNION ? "union" : "struct", s->u.s.tag);
+ oprintf (f, " if (ggc_test_and_set_mark (x))\n");
+ oprintf (f, " for (i = 0; i < (%s); i++)\n", length);
+ oprintf (f, " {\n");
+ write_gc_structure_fields (f, s, "x[i]", "x[i]",
+ v->opt, 8, &v->line, s->u.s.bitmap,
+ NULL);
+ oprintf (f, " }\n");
+ }
+
+ oprintf (f, "}\n\n");
+ }
+ }
+
+ for (v = variables; v; v = v->next)
+ {
+ outf_p f = get_output_file_with_visibility (v->line.file);
+ struct flist *fli;
+ int skip_p = 0;
+ int length_p = 0;
+ options_p o;
+
+ for (o = v->opt; o; o = o->next)
+ if (strcmp (o->name, "length") == 0)
+ length_p = 1;
+ else if (strcmp (o->name, "deletable") == 0
+ || strcmp (o->name, "if_marked") == 0)
+ skip_p = 1;
+
+ if (skip_p)
+ continue;
+
+ for (fli = flp; fli; fli = fli->next)
+ if (fli->f == f)
+ break;
+ if (! fli->started_p)
+ {
+ fli->started_p = 1;
+
+ oprintf (f, "const struct ggc_root_tab gt_ggc_r_");
+ put_mangled_filename (f, v->line.file);
+ oprintf (f, "[] = {\n");
+ }
+
+ write_gc_root (f, v, v->type, v->name, length_p, &v->line, NULL);
+ }
+
+ finish_root_table (flp, "r", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
+ "gt_ggc_rtab");
+
+ for (v = variables; v; v = v->next)
+ {
+ outf_p f = get_output_file_with_visibility (v->line.file);
+ struct flist *fli;
+ int skip_p = 1;
+ options_p o;
+
+ for (o = v->opt; o; o = o->next)
+ if (strcmp (o->name, "deletable") == 0)
+ skip_p = 0;
+ else if (strcmp (o->name, "if_marked") == 0)
+ skip_p = 1;
+
+ if (skip_p)
+ continue;
+
+ for (fli = flp; fli; fli = fli->next)
+ if (fli->f == f)
+ break;
+ if (! fli->started_p)
+ {
+ fli->started_p = 1;
+
+ oprintf (f, "const struct ggc_root_tab gt_ggc_rd_");
+ put_mangled_filename (f, v->line.file);
+ oprintf (f, "[] = {\n");
+ }
+
+ oprintf (f, " { &%s, 1, sizeof (%s), NULL },\n",
+ v->name, v->name);
+ }
+
+ finish_root_table (flp, "rd", "LAST_GGC_ROOT_TAB", "ggc_root_tab",
+ "gt_ggc_deletable_rtab");
+
+ for (v = variables; v; v = v->next)
+ {
+ outf_p f = get_output_file_with_visibility (v->line.file);
+ struct flist *fli;
+ const char *if_marked = NULL;
+ int length_p = 0;
+ options_p o;
+
+ for (o = v->opt; o; o = o->next)
+ if (strcmp (o->name, "length") == 0)
+ length_p = 1;
+ else if (strcmp (o->name, "if_marked") == 0)
+ if_marked = (const char *) o->info;
+
+ if (if_marked == NULL)
+ continue;
+
+ if (v->type->kind != TYPE_POINTER
+ || v->type->u.p->kind != TYPE_PARAM_STRUCT
+ || v->type->u.p->u.param_struct.stru != find_structure ("htab", 0))
+ {
+ error_at_line (&v->line, "if_marked option used but not hash table");
+ continue;
+ }
+
+ for (fli = flp; fli; fli = fli->next)
+ if (fli->f == f)
+ break;
+ if (! fli->started_p)
+ {
+ fli->started_p = 1;
+
+ oprintf (f, "const struct ggc_cache_tab gt_ggc_rc_");
+ put_mangled_filename (f, v->line.file);
+ oprintf (f, "[] = {\n");
+ }
+
+ write_gc_root (f, v, v->type->u.p->u.param_struct.param[0],
+ v->name, length_p, &v->line, if_marked);
+ }
+
+ finish_root_table (flp, "rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
+ "gt_ggc_cache_rtab");
+}
+
+
+extern int main PARAMS ((int argc, char **argv));
+int
+main(argc, argv)
+ int argc ATTRIBUTE_UNUSED;
+ char **argv ATTRIBUTE_UNUSED;
+{
+ unsigned i;
+ static struct fileloc pos = { __FILE__, __LINE__ };
+ unsigned j;
+
+ gen_rtx_next ();
+
+ srcdir_len = strlen (srcdir);
+
+ do_scalar_typedef ("CUMULATIVE_ARGS", &pos);
+ do_scalar_typedef ("REAL_VALUE_TYPE", &pos);
+ do_scalar_typedef ("uint8", &pos);
+ do_scalar_typedef ("jword", &pos);
+ do_scalar_typedef ("JCF_u2", &pos);
+
+ do_typedef ("PTR", create_pointer (create_scalar_type ("void",
+ strlen ("void"))),
+ &pos);
+ do_typedef ("HARD_REG_SET", create_array (
+ create_scalar_type ("unsigned long", strlen ("unsigned long")),
+ "2"), &pos);
+
+ for (i = 0; i < NUM_GT_FILES; i++)
+ {
+ int dupflag = 0;
+ /* Omit if already seen. */
+ for (j = 0; j < i; j++)
+ {
+ if (!strcmp (all_files[i], all_files[j]))
+ {
+ dupflag = 1;
+ break;
+ }
+ }
+ if (!dupflag)
+ parse_file (all_files[i]);
+ }
+
+ if (hit_error != 0)
+ exit (1);
+
+ set_gc_used (variables);
+
+ open_base_files ();
+ write_enum_defn (structures, param_structs);
+ write_gc_types (structures, param_structs);
+ write_gc_roots (variables);
+ write_rtx_next ();
+ close_output_files ();
+
+ return (hit_error != 0);
+}
diff --git a/contrib/gcc/gengtype.h b/contrib/gcc/gengtype.h
new file mode 100644
index 0000000..0c23d95
--- /dev/null
+++ b/contrib/gcc/gengtype.h
@@ -0,0 +1,181 @@
+/* Process source files and output type information.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+/* A file position, mostly for error messages.
+ The FILE element may be compared using pointer equality. */
+struct fileloc {
+ const char *file;
+ int line;
+};
+
+/* Kinds of types we can understand. */
+enum typekind {
+ TYPE_SCALAR,
+ TYPE_STRING,
+ TYPE_STRUCT,
+ TYPE_UNION,
+ TYPE_POINTER,
+ TYPE_ARRAY,
+ TYPE_LANG_STRUCT,
+ TYPE_PARAM_STRUCT
+};
+
+/* A way to pass data through to the output end. */
+typedef struct options {
+ struct options *next;
+ const char *name;
+ const void *info;
+} *options_p;
+
+typedef struct pair *pair_p;
+typedef struct type *type_p;
+typedef unsigned lang_bitmap;
+
+/* A name and a type. */
+struct pair {
+ pair_p next;
+ const char *name;
+ type_p type;
+ struct fileloc line;
+ options_p opt;
+};
+
+#define NUM_PARAM 10
+
+/* A description of a type. */
+struct type {
+ enum typekind kind;
+ type_p next;
+ type_p pointer_to;
+ enum gc_used_enum {
+ GC_UNUSED = 0,
+ GC_USED,
+ GC_MAYBE_POINTED_TO,
+ GC_POINTED_TO
+ } gc_used;
+ union {
+ type_p p;
+ struct {
+ const char *tag;
+ struct fileloc line;
+ pair_p fields;
+ options_p opt;
+ lang_bitmap bitmap;
+ type_p lang_struct;
+ } s;
+ char *sc;
+ struct {
+ type_p p;
+ const char *len;
+ } a;
+ struct {
+ type_p stru;
+ type_p param[NUM_PARAM];
+ struct fileloc line;
+ } param_struct;
+ } u;
+};
+
+#define UNION_P(x) \
+ ((x)->kind == TYPE_UNION || \
+ ((x)->kind == TYPE_LANG_STRUCT \
+ && (x)->u.s.lang_struct->kind == TYPE_UNION))
+#define UNION_OR_STRUCT_P(x) \
+ ((x)->kind == TYPE_UNION \
+ || (x)->kind == TYPE_STRUCT \
+ || (x)->kind == TYPE_LANG_STRUCT)
+
+/* The one and only TYPE_STRING. */
+extern struct type string_type;
+
+/* Variables used to communicate between the lexer and the parser. */
+extern int lexer_toplevel_done;
+extern struct fileloc lexer_line;
+
+/* Print an error message. */
+extern void error_at_line
+ PARAMS ((struct fileloc *pos, const char *msg, ...)) ATTRIBUTE_PRINTF_2;
+
+/* Combines xmalloc() and vasprintf(). */
+extern int xvasprintf PARAMS ((char **, const char *, va_list))
+ ATTRIBUTE_PRINTF (2, 0);
+/* Like the above, but more convenient for quick coding. */
+extern char * xasprintf PARAMS ((const char *, ...))
+ ATTRIBUTE_PRINTF_1;
+
+/* Constructor routines for types. */
+extern void do_typedef PARAMS ((const char *s, type_p t, struct fileloc *pos));
+extern type_p resolve_typedef PARAMS ((const char *s, struct fileloc *pos));
+extern void new_structure PARAMS ((const char *name, int isunion,
+ struct fileloc *pos, pair_p fields,
+ options_p o));
+extern type_p find_structure PARAMS ((const char *s, int isunion));
+extern type_p create_scalar_type PARAMS ((const char *name, size_t name_len));
+extern type_p create_pointer PARAMS ((type_p t));
+extern type_p create_array PARAMS ((type_p t, const char *len));
+extern type_p adjust_field_type PARAMS ((type_p, options_p));
+extern void note_variable PARAMS ((const char *s, type_p t, options_p o,
+ struct fileloc *pos));
+extern void note_yacc_type PARAMS ((options_p o, pair_p fields,
+ pair_p typeinfo, struct fileloc *pos));
+
+/* Lexer and parser routines, most automatically generated. */
+extern int yylex PARAMS((void));
+extern void yyerror PARAMS ((const char *));
+extern int yyparse PARAMS ((void));
+extern void parse_file PARAMS ((const char *name));
+
+/* Output file handling. */
+
+/* Structure representing an output file. */
+struct outf
+{
+ struct outf *next;
+ const char *name;
+ size_t buflength;
+ size_t bufused;
+ char *buf;
+};
+
+typedef struct outf * outf_p;
+
+/* The output header file that is included into pretty much every
+ source file. */
+extern outf_p header_file;
+
+/* An output file, suitable for definitions, that can see declarations
+ made in INPUT_FILE and is linked into every language that uses
+ INPUT_FILE. */
+extern outf_p get_output_file_with_visibility
+ PARAMS ((const char *input_file));
+const char *get_output_file_name PARAMS ((const char *));
+
+/* A list of output files suitable for definitions. There is one
+ BASE_FILES entry for each language. */
+extern outf_p base_files[];
+
+/* A bitmap that specifies which of BASE_FILES should be used to
+ output a definition that is different for each language and must be
+ defined once in each language that uses INPUT_FILE. */
+extern lang_bitmap get_base_file_bitmap PARAMS ((const char *input_file));
+
+/* Print, like fprintf, to O. */
+extern void oprintf PARAMS ((outf_p o, const char *S, ...))
+ ATTRIBUTE_PRINTF_2;
diff --git a/contrib/gcc/genopinit.c b/contrib/gcc/genopinit.c
index 384a066..ef4242a 100644
--- a/contrib/gcc/genopinit.c
+++ b/contrib/gcc/genopinit.c
@@ -114,6 +114,8 @@ static const char * const optabs[] =
"sqrt_optab->handlers[$A].insn_code = CODE_FOR_$(sqrt$a2$)",
"sin_optab->handlers[$A].insn_code = CODE_FOR_$(sin$a2$)",
"cos_optab->handlers[$A].insn_code = CODE_FOR_$(cos$a2$)",
+ "exp_optab->handlers[$A].insn_code = CODE_FOR_$(exp$a2$)",
+ "log_optab->handlers[$A].insn_code = CODE_FOR_$(log$a2$)",
"strlen_optab->handlers[$A].insn_code = CODE_FOR_$(strlen$a$)",
"one_cmpl_optab->handlers[$A].insn_code = CODE_FOR_$(one_cmpl$a2$)",
"ffs_optab->handlers[$A].insn_code = CODE_FOR_$(ffs$a2$)",
diff --git a/contrib/gcc/genpreds.c b/contrib/gcc/genpreds.c
index f4ba1f9..cf8c0bd 100644
--- a/contrib/gcc/genpreds.c
+++ b/contrib/gcc/genpreds.c
@@ -43,7 +43,7 @@ output_predicate_decls ()
size_t i;
puts ("#ifdef RTX_CODE\n");
- for (i = 0; i < sizeof predicate / sizeof *predicate; i++)
+ for (i = 0; i < ARRAY_SIZE (predicate); i++)
printf ("extern int %s PARAMS ((rtx, enum machine_mode));\n",
predicate[i].name);
puts ("\n#endif /* RTX_CODE */\n");
diff --git a/contrib/gcc/genrecog.c b/contrib/gcc/genrecog.c
index 1e8f854..56b2680 100644
--- a/contrib/gcc/genrecog.c
+++ b/contrib/gcc/genrecog.c
@@ -43,11 +43,11 @@
This program also generates the function `split_insns', which
returns 0 if the rtl could not be split, or it returns the split
- rtl in a SEQUENCE.
+ rtl as an INSN list.
This program also generates the function `peephole2_insns', which
returns 0 if the rtl could not be matched. If there was a match,
- the new rtl is returned in a SEQUENCE, and LAST_INSN will point
+ the new rtl is returned in an INSN list, and LAST_INSN will point
to the last recognized insn in the old sequence. */
#include "hconfig.h"
@@ -187,22 +187,23 @@ static const struct pred_table
const RTX_CODE codes[NUM_RTX_CODE];
} preds[] = {
{"general_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
- LABEL_REF, SUBREG, REG, MEM}},
+ LABEL_REF, SUBREG, REG, MEM, ADDRESSOF}},
#ifdef PREDICATE_CODES
PREDICATE_CODES
#endif
{"address_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
- LABEL_REF, SUBREG, REG, MEM, PLUS, MINUS, MULT}},
- {"register_operand", {SUBREG, REG}},
- {"pmode_register_operand", {SUBREG, REG}},
+ LABEL_REF, SUBREG, REG, MEM, ADDRESSOF,
+ PLUS, MINUS, MULT}},
+ {"register_operand", {SUBREG, REG, ADDRESSOF}},
+ {"pmode_register_operand", {SUBREG, REG, ADDRESSOF}},
{"scratch_operand", {SCRATCH, REG}},
{"immediate_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
LABEL_REF}},
{"const_int_operand", {CONST_INT}},
{"const_double_operand", {CONST_INT, CONST_DOUBLE}},
- {"nonimmediate_operand", {SUBREG, REG, MEM}},
+ {"nonimmediate_operand", {SUBREG, REG, MEM, ADDRESSOF}},
{"nonmemory_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
- LABEL_REF, SUBREG, REG}},
+ LABEL_REF, SUBREG, REG, ADDRESSOF}},
{"push_operand", {MEM}},
{"pop_operand", {MEM}},
{"memory_operand", {SUBREG, MEM}},
@@ -211,7 +212,7 @@ static const struct pred_table
UNORDERED, ORDERED, UNEQ, UNGE, UNGT, UNLE,
UNLT, LTGT}},
{"mode_independent_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
- LABEL_REF, SUBREG, REG, MEM}}
+ LABEL_REF, SUBREG, REG, MEM, ADDRESSOF}}
};
#define NUM_KNOWN_PREDS ARRAY_SIZE (preds)
@@ -520,6 +521,7 @@ validate_pattern (pattern, insn, set, set_code)
if (c != REG
&& c != SUBREG
&& c != MEM
+ && c != ADDRESSOF
&& c != CONCAT
&& c != PARALLEL
&& c != STRICT_LOW_PART)
@@ -1200,7 +1202,7 @@ maybe_both_true_1 (d1, d2)
D1 and D2. Otherwise, return 1 (it may be that there is an RTL that
can match both or just that we couldn't prove there wasn't such an RTL).
- TOPLEVEL is non-zero if we are to only look at the top level and not
+ TOPLEVEL is nonzero if we are to only look at the top level and not
recursively descend. */
static int
@@ -1677,7 +1679,7 @@ find_afterward (head, real_afterward)
/* Assuming that the state of argument is denoted by OLDPOS, take whatever
actions are necessary to move to NEWPOS. If we fail to move to the
- new state, branch to node AFTERWARD if non-zero, otherwise return.
+ new state, branch to node AFTERWARD if nonzero, otherwise return.
Failure to move to the new state can only occur if we are trying to
match multiple insns and we try to step past the end of the stream. */
@@ -1944,7 +1946,7 @@ write_switch (start, depth)
case DT_elt_one_int:
case DT_elt_zero_wide:
case DT_elt_zero_wide_safe:
- printf (HOST_WIDE_INT_PRINT_DEC, p->tests->u.intval);
+ printf (HOST_WIDE_INT_PRINT_DEC_C, p->tests->u.intval);
break;
default:
abort ();
@@ -2003,7 +2005,7 @@ write_cond (p, depth, subroutine_type)
case DT_elt_zero_wide:
case DT_elt_zero_wide_safe:
printf ("XWINT (x%d, 0) == ", depth);
- printf (HOST_WIDE_INT_PRINT_DEC, p->u.intval);
+ printf (HOST_WIDE_INT_PRINT_DEC_C, p->u.intval);
break;
case DT_veclen_ge:
@@ -2431,10 +2433,10 @@ write_header ()
puts ("\n\
The function split_insns returns 0 if the rtl could not\n\
- be split or the split rtl in a SEQUENCE if it can be.\n\
+ be split or the split rtl as an INSN list if it can be.\n\
\n\
The function peephole2_insns returns 0 if the rtl could not\n\
- be matched. If there was a match, the new rtl is returned in a SEQUENCE,\n\
+ be matched. If there was a match, the new rtl is returned in an INSN list,\n\
and LAST_INSN will point to the last recognized insn in the old sequence.\n\
*/\n\n");
}
@@ -2452,11 +2454,16 @@ make_insn_sequence (insn, type)
{
rtx x;
const char *c_test = XSTR (insn, type == RECOG ? 2 : 1);
+ int truth = maybe_eval_c_test (c_test);
struct decision *last;
struct decision_test *test, **place;
struct decision_head head;
char c_test_pos[2];
+ /* We should never see an insn whose C test is false at compile time. */
+ if (truth == 0)
+ abort ();
+
record_insn_name (next_insn_code, (type == RECOG ? XSTR (insn, 0) : NULL));
c_test_pos[0] = '\0';
@@ -2504,7 +2511,8 @@ make_insn_sequence (insn, type)
continue;
place = &test->next;
- if (c_test[0])
+ /* Skip the C test if it's known to be true at compile time. */
+ if (truth == -1)
{
/* Need a new node if we have another test to add. */
if (test->type == DT_accept_op)
@@ -2577,7 +2585,9 @@ make_insn_sequence (insn, type)
place = &last->tests;
}
- if (c_test[0])
+ /* Skip the C test if it's known to be true at compile
+ time. */
+ if (truth == -1)
{
test = new_decision_test (DT_c_test, &place);
test->u.c_test = c_test;
diff --git a/contrib/gcc/gensupport.c b/contrib/gcc/gensupport.c
index 415df01..53172dd 100644
--- a/contrib/gcc/gensupport.c
+++ b/contrib/gcc/gensupport.c
@@ -1,5 +1,5 @@
/* Support routines for the various generation passes.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -23,18 +23,18 @@
#include "rtl.h"
#include "obstack.h"
#include "errors.h"
+#include "hashtab.h"
#include "gensupport.h"
/* In case some macros used by files we include need it, define this here. */
int target_flags;
+int insn_elision = 1;
+
static struct obstack obstack;
struct obstack *rtl_obstack = &obstack;
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
static int sequence_num;
static int errors;
@@ -42,6 +42,8 @@ static int predicable_default;
static const char *predicable_true;
static const char *predicable_false;
+static htab_t condition_table;
+
static char *base_dir = NULL;
/* We initially queue all patterns, process the define_insn and
@@ -50,6 +52,7 @@ static char *base_dir = NULL;
struct queue_elem
{
rtx data;
+ const char *filename;
int lineno;
struct queue_elem *next;
};
@@ -63,7 +66,8 @@ static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
static struct queue_elem *other_queue;
static struct queue_elem **other_tail = &other_queue;
-static void queue_pattern PARAMS ((rtx, struct queue_elem ***, int));
+static void queue_pattern PARAMS ((rtx, struct queue_elem ***,
+ const char *, int));
/* Current maximum length of directory names in the search path
for include files. (Altered as we get more of them.) */
@@ -76,10 +80,10 @@ struct file_name_list
const char *fname;
};
-struct file_name_list *include = 0; /* First dir to search */
+struct file_name_list *first_dir_md_include = 0; /* First dir to search */
/* First dir to search for <file> */
struct file_name_list *first_bracket_include = 0;
-struct file_name_list *last_include = 0; /* Last in chain */
+struct file_name_list *last_dir_md_include = 0; /* Last in chain */
static void remove_constraints PARAMS ((rtx));
static void process_rtx PARAMS ((rtx, int));
@@ -97,9 +101,8 @@ static const char *alter_output_for_insn PARAMS ((struct queue_elem *,
int, int));
static void process_one_cond_exec PARAMS ((struct queue_elem *));
static void process_define_cond_exec PARAMS ((void));
-static int process_include PARAMS ((rtx, int));
+static void process_include PARAMS ((rtx, int));
static char *save_string PARAMS ((const char *, int));
-static int init_include_reader PARAMS ((FILE *));
void
message_with_line VPARAMS ((int lineno, const char *msg, ...))
@@ -132,13 +135,15 @@ gen_rtx_CONST_INT (mode, arg)
/* Queue PATTERN on LIST_TAIL. */
static void
-queue_pattern (pattern, list_tail, lineno)
+queue_pattern (pattern, list_tail, filename, lineno)
rtx pattern;
struct queue_elem ***list_tail;
+ const char *filename;
int lineno;
{
struct queue_elem *e = (struct queue_elem *) xmalloc (sizeof (*e));
e->data = pattern;
+ e->filename = filename;
e->lineno = lineno;
e->next = NULL;
**list_tail = e;
@@ -179,142 +184,83 @@ remove_constraints (part)
}
}
-/* The entry point for initializing the reader. */
-
-static int
-init_include_reader (inf)
- FILE *inf;
-{
- int c;
-
- errors = 0;
-
- /* Read the entire file. */
- while (1)
- {
- rtx desc;
- int lineno;
-
- c = read_skip_spaces (inf);
- if (c == EOF)
- break;
-
- ungetc (c, inf);
- lineno = read_rtx_lineno;
- desc = read_rtx (inf);
- process_rtx (desc, lineno);
- }
- fclose (inf);
-
- /* Process define_cond_exec patterns. */
- if (define_cond_exec_queue != NULL)
- process_define_cond_exec ();
-
- return errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
-}
-
/* Process an include file assuming that it lives in gcc/config/{target}/
- if the include looks line (include "file" ) */
-static int
+ if the include looks like (include "file"). */
+
+static void
process_include (desc, lineno)
rtx desc;
int lineno;
{
const char *filename = XSTR (desc, 0);
- char *pathname = NULL;
+ const char *old_filename;
+ int old_lineno;
+ char *pathname;
FILE *input_file;
- char *fname = NULL;
- struct file_name_list *stackp;
- int flen;
- stackp = include;
-
- /* If specified file name is absolute, just open it. */
- if (IS_ABSOLUTE_PATHNAME (filename) || !stackp)
+ /* If specified file name is absolute, skip the include stack. */
+ if (! IS_ABSOLUTE_PATHNAME (filename))
{
- if (base_dir)
- {
- pathname = xmalloc (strlen (base_dir) + strlen (filename) + 1);
- pathname = strcpy (pathname, base_dir);
- strcat (pathname, filename);
- strcat (pathname, "\0");
- }
- else
- {
- pathname = xstrdup (filename);
- }
- read_rtx_filename = pathname;
- input_file = fopen (pathname, "r");
+ struct file_name_list *stackp;
- if (input_file == 0)
+ /* Search directory path, trying to open the file. */
+ for (stackp = first_dir_md_include; stackp; stackp = stackp->next)
{
- perror (pathname);
- return FATAL_EXIT_CODE;
+ static const char sep[2] = { DIR_SEPARATOR, '\0' };
+
+ pathname = concat (stackp->fname, sep, filename, NULL);
+ input_file = fopen (pathname, "r");
+ if (input_file != NULL)
+ goto success;
+ free (pathname);
}
}
- else if (stackp)
- {
-
- flen = strlen (filename);
-
- fname = (char *) xmalloc (max_include_len + flen + 2);
- /* + 2 above for slash and terminating null. */
+ if (base_dir)
+ pathname = concat (base_dir, filename, NULL);
+ else
+ pathname = xstrdup (filename);
+ input_file = fopen (pathname, "r");
+ if (input_file == NULL)
+ {
+ free (pathname);
+ message_with_line (lineno, "include file `%s' not found", filename);
+ errors = 1;
+ return;
+ }
+ success:
- /* Search directory path, trying to open the file.
- Copy each filename tried into FNAME. */
+ /* Save old cursor; setup new for the new file. Note that "lineno" the
+ argument to this function is the beginning of the include statement,
+ while read_rtx_lineno has already been advanced. */
+ old_filename = read_rtx_filename;
+ old_lineno = read_rtx_lineno;
+ read_rtx_filename = pathname;
+ read_rtx_lineno = 1;
- for (; stackp; stackp = stackp->next)
- {
- if (stackp->fname)
- {
- strcpy (fname, stackp->fname);
- strcat (fname, "/");
- fname[strlen (fname) + flen] = 0;
- }
- else
- {
- fname[0] = 0;
- }
- strncat (fname, (const char *) filename, flen);
- read_rtx_filename = fname;
- input_file = fopen (fname, "r");
- if (input_file != NULL)
- break;
- }
- if (stackp == NULL)
- {
- if (strchr (fname, '/') == NULL || strchr (fname, '\\' ) || base_dir)
- {
- if (base_dir)
- {
- pathname =
- xmalloc (strlen (base_dir) + strlen (filename) + 1);
- pathname = strcpy (pathname, base_dir);
- strcat (pathname, filename);
- strcat (pathname, "\0");
- }
- else
- pathname = xstrdup (filename);
- }
- read_rtx_filename = pathname;
- input_file = fopen (pathname, "r");
+ /* Read the entire file. */
+ while (1)
+ {
+ rtx desc;
+ int c;
- if (input_file == 0)
- {
- perror (filename);
- return FATAL_EXIT_CODE;
- }
- }
+ c = read_skip_spaces (input_file);
+ if (c == EOF)
+ break;
+ ungetc (c, input_file);
+ lineno = read_rtx_lineno;
+ desc = read_rtx (input_file);
+ process_rtx (desc, lineno);
}
- if (init_include_reader (input_file) == FATAL_EXIT_CODE)
- message_with_line (lineno, "read errors found in include file %s\n", pathname);
+ /* Do not free pathname. It is attached to the various rtx queue
+ elements. */
+
+ read_rtx_filename = old_filename;
+ read_rtx_lineno = old_lineno;
- if (fname)
- free (fname);
- return SUCCESS_EXIT_CODE;
+ fclose (input_file);
}
/* Process a top level rtx in some way, queueing as appropriate. */
@@ -327,24 +273,19 @@ process_rtx (desc, lineno)
switch (GET_CODE (desc))
{
case DEFINE_INSN:
- queue_pattern (desc, &define_insn_tail, lineno);
+ queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
break;
case DEFINE_COND_EXEC:
- queue_pattern (desc, &define_cond_exec_tail, lineno);
+ queue_pattern (desc, &define_cond_exec_tail, read_rtx_filename, lineno);
break;
case DEFINE_ATTR:
- queue_pattern (desc, &define_attr_tail, lineno);
+ queue_pattern (desc, &define_attr_tail, read_rtx_filename, lineno);
break;
case INCLUDE:
- if (process_include (desc, lineno) == FATAL_EXIT_CODE)
- {
- const char *filename = XSTR (desc, 0);
- message_with_line (lineno, "include file at %s not found\n",
- filename);
- }
+ process_include (desc, lineno);
break;
case DEFINE_INSN_AND_SPLIT:
@@ -369,18 +310,7 @@ process_rtx (desc, lineno)
insn condition to create the new split condition. */
split_cond = XSTR (desc, 4);
if (split_cond[0] == '&' && split_cond[1] == '&')
- {
- const char *insn_cond = XSTR (desc, 2);
- size_t insn_cond_len = strlen (insn_cond);
- size_t split_cond_len = strlen (split_cond);
- char *combined;
-
- combined = (char *) xmalloc (insn_cond_len + split_cond_len + 1);
- memcpy (combined, insn_cond, insn_cond_len);
- memcpy (combined + insn_cond_len, split_cond, split_cond_len + 1);
-
- split_cond = combined;
- }
+ split_cond = concat (XSTR (desc, 2), split_cond, NULL);
XSTR (split, 1) = split_cond;
XVEC (split, 2) = XVEC (desc, 5);
XSTR (split, 3) = XSTR (desc, 6);
@@ -391,13 +321,13 @@ process_rtx (desc, lineno)
XVEC (desc, 4) = attr;
/* Queue them. */
- queue_pattern (desc, &define_insn_tail, lineno);
- queue_pattern (split, &other_tail, lineno);
+ queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
+ queue_pattern (split, &other_tail, read_rtx_filename, lineno);
break;
}
default:
- queue_pattern (desc, &other_tail, lineno);
+ queue_pattern (desc, &other_tail, read_rtx_filename, lineno);
break;
}
}
@@ -500,7 +430,6 @@ identify_predicable_attribute ()
struct queue_elem *elem;
char *p_true, *p_false;
const char *value;
- size_t len;
/* Look for the DEFINE_ATTR for `predicable', which must exist. */
for (elem = define_attr_queue; elem ; elem = elem->next)
@@ -514,10 +443,7 @@ identify_predicable_attribute ()
found:
value = XSTR (elem->data, 1);
- len = strlen (value);
- p_false = (char *) xmalloc (len + 1);
- memcpy (p_false, value, len + 1);
-
+ p_false = xstrdup (value);
p_true = strchr (p_false, ',');
if (p_true == NULL || strchr (++p_true, ',') != NULL)
{
@@ -735,8 +661,6 @@ alter_test_for_insn (ce_elem, insn_elem)
struct queue_elem *ce_elem, *insn_elem;
{
const char *ce_test, *insn_test;
- char *new_test;
- size_t len, ce_len, insn_len;
ce_test = XSTR (ce_elem->data, 1);
insn_test = XSTR (insn_elem->data, 2);
@@ -745,14 +669,7 @@ alter_test_for_insn (ce_elem, insn_elem)
if (!insn_test || *insn_test == '\0')
return ce_test;
- ce_len = strlen (ce_test);
- insn_len = strlen (insn_test);
- len = 1 + ce_len + 1 + 4 + 1 + insn_len + 1 + 1;
- new_test = (char *) xmalloc (len);
-
- sprintf (new_test, "(%s) && (%s)", ce_test, insn_test);
-
- return new_test;
+ return concat ("(", ce_test, ") && (", insn_test, ")", NULL);
}
/* Adjust all of the operand numbers in OLD to match the shift they'll
@@ -917,7 +834,8 @@ process_one_cond_exec (ce_elem)
patterns into the define_insn chain just after their generator
is something we'll have to experiment with. */
- queue_pattern (insn, &other_tail, insn_elem->lineno);
+ queue_pattern (insn, &other_tail, insn_elem->filename,
+ insn_elem->lineno);
}
}
@@ -981,11 +899,11 @@ init_md_reader_args (argc, argv)
dirtmp = (struct file_name_list *)
xmalloc (sizeof (struct file_name_list));
dirtmp->next = 0; /* New one goes on the end */
- if (include == 0)
- include = dirtmp;
+ if (first_dir_md_include == 0)
+ first_dir_md_include = dirtmp;
else
- last_include->next = dirtmp;
- last_include = dirtmp; /* Tail follows the last one */
+ last_dir_md_include->next = dirtmp;
+ last_dir_md_include = dirtmp; /* Tail follows the last one */
if (argv[i][1] == 'I' && argv[i][2] != 0)
dirtmp->fname = argv[i] + 2;
else if (i + 1 == argc)
@@ -1013,14 +931,12 @@ init_md_reader (filename)
{
FILE *input_file;
int c;
+ size_t i;
char *lastsl;
- if (!IS_ABSOLUTE_PATHNAME (filename))
- {
- lastsl = strrchr (filename, '/');
- if (lastsl != NULL)
- base_dir = save_string (filename, lastsl - filename + 1 );
- }
+ lastsl = strrchr (filename, '/');
+ if (lastsl != NULL)
+ base_dir = save_string (filename, lastsl - filename + 1 );
read_rtx_filename = filename;
input_file = fopen (filename, "r");
@@ -1030,6 +946,14 @@ init_md_reader (filename)
return FATAL_EXIT_CODE;
}
+ /* Initialize the table of insn conditions. */
+ condition_table = htab_create (n_insn_conditions,
+ hash_c_test, cmp_c_test, NULL);
+
+ for (i = 0; i < n_insn_conditions; i++)
+ *(htab_find_slot (condition_table, (PTR) &insn_conditions[i], INSERT))
+ = (PTR) &insn_conditions[i];
+
obstack_init (rtl_obstack);
errors = 0;
sequence_num = 0;
@@ -1068,6 +992,8 @@ read_md_rtx (lineno, seqnr)
struct queue_elem **queue, *elem;
rtx desc;
+ discard:
+
/* Read all patterns from a given queue before moving on to the next. */
if (define_attr_queue != NULL)
queue = &define_attr_queue;
@@ -1081,19 +1007,35 @@ read_md_rtx (lineno, seqnr)
elem = *queue;
*queue = elem->next;
desc = elem->data;
+ read_rtx_filename = elem->filename;
*lineno = elem->lineno;
*seqnr = sequence_num;
free (elem);
+ /* Discard insn patterns which we know can never match (because
+ their C test is provably always false). If insn_elision is
+ false, our caller needs to see all the patterns. Note that the
+ elided patterns are never counted by the sequence numbering; it
+ it is the caller's responsibility, when insn_elision is false, not
+ to use elided pattern numbers for anything. */
switch (GET_CODE (desc))
{
case DEFINE_INSN:
case DEFINE_EXPAND:
+ if (maybe_eval_c_test (XSTR (desc, 2)) != 0)
+ sequence_num++;
+ else if (insn_elision)
+ goto discard;
+ break;
+
case DEFINE_SPLIT:
case DEFINE_PEEPHOLE:
case DEFINE_PEEPHOLE2:
- sequence_num++;
+ if (maybe_eval_c_test (XSTR (desc, 1)) != 0)
+ sequence_num++;
+ else if (insn_elision)
+ goto discard;
break;
default:
@@ -1102,3 +1044,118 @@ read_md_rtx (lineno, seqnr)
return desc;
}
+
+/* Helper functions for insn elision. */
+
+/* Compute a hash function of a c_test structure, which is keyed
+ by its ->expr field. */
+hashval_t
+hash_c_test (x)
+ const PTR x;
+{
+ const struct c_test *a = (const struct c_test *) x;
+ const unsigned char *base, *s = (const unsigned char *) a->expr;
+ hashval_t hash;
+ unsigned char c;
+ unsigned int len;
+
+ base = s;
+ hash = 0;
+
+ while ((c = *s++) != '\0')
+ {
+ hash += c + (c << 17);
+ hash ^= hash >> 2;
+ }
+
+ len = s - base;
+ hash += len + (len << 17);
+ hash ^= hash >> 2;
+
+ return hash;
+}
+
+/* Compare two c_test expression structures. */
+int
+cmp_c_test (x, y)
+ const PTR x;
+ const PTR y;
+{
+ const struct c_test *a = (const struct c_test *) x;
+ const struct c_test *b = (const struct c_test *) y;
+
+ return !strcmp (a->expr, b->expr);
+}
+
+/* Given a string representing a C test expression, look it up in the
+ condition_table and report whether or not its value is known
+ at compile time. Returns a tristate: 1 for known true, 0 for
+ known false, -1 for unknown. */
+int
+maybe_eval_c_test (expr)
+ const char *expr;
+{
+ const struct c_test *test;
+ struct c_test dummy;
+
+ if (expr[0] == 0)
+ return 1;
+
+ if (insn_elision_unavailable)
+ return -1;
+
+ dummy.expr = expr;
+ test = (const struct c_test *) htab_find (condition_table, &dummy);
+ if (!test)
+ abort ();
+
+ return test->value;
+}
+
+/* Given a string, return the number of comma-separated elements in it.
+ Return 0 for the null string. */
+int
+n_comma_elts (s)
+ const char *s;
+{
+ int n;
+
+ if (*s == '\0')
+ return 0;
+
+ for (n = 1; *s; s++)
+ if (*s == ',')
+ n++;
+
+ return n;
+}
+
+/* Given a pointer to a (char *), return a pointer to the beginning of the
+ next comma-separated element in the string. Advance the pointer given
+ to the end of that element. Return NULL if at end of string. Caller
+ is responsible for copying the string if necessary. White space between
+ a comma and an element is ignored. */
+
+const char *
+scan_comma_elt (pstr)
+ const char **pstr;
+{
+ const char *start;
+ const char *p = *pstr;
+
+ if (*p == ',')
+ p++;
+ while (ISSPACE(*p))
+ p++;
+
+ if (*p == '\0')
+ return NULL;
+
+ start = p;
+
+ while (*p != ',' && *p != '\0')
+ p++;
+
+ *pstr = p;
+ return start;
+}
diff --git a/contrib/gcc/gensupport.h b/contrib/gcc/gensupport.h
index 96c8c87..8dbd0b7 100644
--- a/contrib/gcc/gensupport.h
+++ b/contrib/gcc/gensupport.h
@@ -1,5 +1,5 @@
/* Declarations for rtx-reader support for gen* routines.
- Copyright (C) 2000 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -18,6 +18,9 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
+#ifndef GCC_GENSUPPORT_H
+#define GCC_GENSUPPORT_H
+
struct obstack;
extern struct obstack *rtl_obstack;
@@ -27,3 +30,40 @@ extern rtx read_md_rtx PARAMS ((int *, int *));
extern void message_with_line PARAMS ((int, const char *, ...))
ATTRIBUTE_PRINTF_2;
+
+/* Set this to 0 to disable automatic elision of insn patterns which
+ can never be used in this configuration. See genconditions.c.
+ Must be set before calling init_md_reader. */
+extern int insn_elision;
+
+/* If this is 1, the insn elision table doesn't even exist yet;
+ maybe_eval_c_test will always return -1. This is distinct from
+ insn_elision because genflags and gencodes need to see all the
+ patterns, but treat elided patterns differently. */
+extern const int insn_elision_unavailable;
+
+/* If the C test passed as the argument can be evaluated at compile
+ time, return its truth value; else return -1. The test must have
+ appeared somewhere in the machine description when genconditions
+ was run. */
+extern int maybe_eval_c_test PARAMS ((const char *));
+
+/* This table should not be accessed directly; use maybe_eval_c_test. */
+struct c_test
+{
+ const char *expr;
+ int value;
+};
+
+extern const struct c_test insn_conditions[];
+extern const size_t n_insn_conditions;
+
+#ifdef __HASHTAB_H__
+extern hashval_t hash_c_test PARAMS ((const PTR));
+extern int cmp_c_test PARAMS ((const PTR, const PTR));
+#endif
+
+extern int n_comma_elts PARAMS ((const char *));
+extern const char *scan_comma_elt PARAMS ((const char **));
+
+#endif /* GCC_GENSUPPORT_H */
diff --git a/contrib/gcc/getopt.c b/contrib/gcc/getopt.c
index 2402a39..a1e4827 100644
--- a/contrib/gcc/getopt.c
+++ b/contrib/gcc/getopt.c
@@ -333,8 +333,8 @@ exchange (argv)
nonoption_flags_len = nonoption_flags_max_len = 0;
else
{
- memset (__mempcpy (new_str, __getopt_nonoption_flags,
- nonoption_flags_max_len),
+ 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;
@@ -444,7 +444,7 @@ _getopt_initialize (argc, argv, optstring)
if (__getopt_nonoption_flags == NULL)
nonoption_flags_max_len = -1;
else
- memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+ memset (mempcpy (__getopt_nonoption_flags, orig_str, len),
'\0', nonoption_flags_max_len - len);
}
}
diff --git a/contrib/gcc/getopt.h b/contrib/gcc/getopt.h
index 04346dd..a99a229 100644
--- a/contrib/gcc/getopt.h
+++ b/contrib/gcc/getopt.h
@@ -1,6 +1,6 @@
/* Declarations for getopt.
- Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 2000
- Free Software Foundation, Inc.
+ Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 2000,
+ 2002 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@gnu.org.
@@ -105,16 +105,19 @@ struct option
declaration without arguments. If it is 0, we checked and failed
to find the declaration so provide a fully prototyped one. If it
is 1, we found it so don't provide any declaration at all. */
-#if defined (__GNU_LIBRARY__) || (defined (HAVE_DECL_GETOPT) && !HAVE_DECL_GETOPT)
+#if !HAVE_DECL_GETOPT
+#if defined (__GNU_LIBRARY__) || defined (HAVE_DECL_GETOPT)
/* Many other libraries have conflicting prototypes for getopt, with
- differences in the consts, in stdlib.h. To avoid compilation
+ differences in the consts, in unistd.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int argc, char *const *argv, const char *shortopts);
-#else /* not __GNU_LIBRARY__ */
-# if !defined (HAVE_DECL_GETOPT) && !defined (__cplusplus)
+#else
+#ifndef __cplusplus
extern int getopt ();
-# endif
-#endif /* __GNU_LIBRARY__ */
+#endif /* __cplusplus */
+#endif
+#endif /* !HAVE_DECL_GETOPT */
+
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
diff --git a/contrib/gcc/getruntime.c b/contrib/gcc/getruntime.c
new file mode 100644
index 0000000..3f7dc0d
--- /dev/null
+++ b/contrib/gcc/getruntime.c
@@ -0,0 +1,116 @@
+/* Return time used so far, in microseconds.
+ Copyright (C) 1994, 1999, 2002 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+
+#include "ansidecl.h"
+#include "libiberty.h"
+
+/* On some systems (such as WindISS), you must include <sys/types.h>
+ to get the definition of "time_t" before you include <time.h>. */
+#include <sys/types.h>
+
+/* There are several ways to get elapsed execution time; unfortunately no
+ single way is available for all host systems, nor are there reliable
+ ways to find out which way is correct for a given host. */
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# ifdef HAVE_TIME_H
+# include <time.h>
+# endif
+# endif
+#endif
+
+#if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
+#include <sys/resource.h>
+#endif
+
+#ifdef HAVE_TIMES
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <sys/times.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* This is a fallback; if wrong, it will likely make obviously wrong
+ results. */
+
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1
+#endif
+
+#ifdef _SC_CLK_TCK
+#define GNU_HZ sysconf(_SC_CLK_TCK)
+#else
+#ifdef HZ
+#define GNU_HZ HZ
+#else
+#ifdef CLOCKS_PER_SEC
+#define GNU_HZ CLOCKS_PER_SEC
+#endif
+#endif
+#endif
+
+/*
+
+@deftypefn Replacement long get_run_time (void)
+
+Returns the time used so far, in microseconds. If possible, this is
+the time used by this process, else it is the elapsed time since the
+process started.
+
+@end deftypefn
+
+*/
+
+long
+get_run_time ()
+{
+#if defined (HAVE_GETRUSAGE) && defined (HAVE_SYS_RESOURCE_H)
+ struct rusage rusage;
+
+ getrusage (0, &rusage);
+ return (rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec
+ + rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec);
+#else /* ! HAVE_GETRUSAGE */
+#ifdef HAVE_TIMES
+ struct tms tms;
+
+ times (&tms);
+ return (tms.tms_utime + tms.tms_stime) * (1000000 / GNU_HZ);
+#else /* ! HAVE_TIMES */
+ /* Fall back on clock and hope it's correctly implemented. */
+ const long clocks_per_sec = CLOCKS_PER_SEC;
+ if (clocks_per_sec <= 1000000)
+ return clock () * (1000000 / clocks_per_sec);
+ else
+ return clock () / clocks_per_sec;
+#endif /* HAVE_TIMES */
+#endif /* HAVE_GETRUSAGE */
+}
diff --git a/contrib/gcc/ggc-common.c b/contrib/gcc/ggc-common.c
index b0676b2..528b3f2 100644
--- a/contrib/gcc/ggc-common.c
+++ b/contrib/gcc/ggc-common.c
@@ -26,33 +26,26 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "rtl.h"
#include "tree.h"
#include "tm_p.h"
-#include "hash.h"
#include "hashtab.h"
#include "varray.h"
#include "ggc.h"
+#include "langhooks.h"
+#include "params.h"
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+#endif
+#ifdef ENABLE_VALGRIND_CHECKING
+#include <valgrind.h>
+#else
+/* Avoid #ifdef:s when we can help it. */
+#define VALGRIND_DISCARD(x)
+#endif
/* Statistics about the allocation. */
static ggc_statistics *ggc_stats;
-/* The FALSE_LABEL_STACK, declared in except.h, has language-dependent
- semantics. If a front-end needs to mark the false label stack, it
- should set this pointer to a non-NULL value. Otherwise, no marking
- will be done. */
-void (*lang_mark_false_label_stack) PARAMS ((struct label_node *));
-
-/* Trees that have been marked, but whose children still need marking. */
-varray_type ggc_pending_trees;
-
-static void ggc_mark_rtx_children_1 PARAMS ((rtx));
-static void ggc_mark_rtx_ptr PARAMS ((void *));
-static void ggc_mark_tree_ptr PARAMS ((void *));
-static void ggc_mark_rtx_varray_ptr PARAMS ((void *));
-static void ggc_mark_tree_varray_ptr PARAMS ((void *));
-static void ggc_mark_tree_hash_table_ptr PARAMS ((void *));
static int ggc_htab_delete PARAMS ((void **, void *));
-static void ggc_mark_trees PARAMS ((void));
-static bool ggc_mark_tree_hash_table_entry PARAMS ((struct hash_entry *,
- hash_table_key));
+static double ggc_rlimit_bound PARAMS ((double));
/* Maintain global roots that are preserved during GC. */
@@ -70,7 +63,7 @@ struct ggc_root
static struct ggc_root *roots;
/* Add BASE as a new garbage collection root. It is an array of
- length NELT with each element SIZE bytes long. CB is a
+ length NELT with each element SIZE bytes long. CB is a
function that will be called with a pointer to each element
of the array; it is the intention that CB call the appropriate
routine to mark gc-able memory for that element. */
@@ -92,132 +85,6 @@ ggc_add_root (base, nelt, size, cb)
roots = x;
}
-/* Register an array of rtx as a GC root. */
-
-void
-ggc_add_rtx_root (base, nelt)
- rtx *base;
- int nelt;
-{
- ggc_add_root (base, nelt, sizeof (rtx), ggc_mark_rtx_ptr);
-}
-
-/* Register an array of trees as a GC root. */
-
-void
-ggc_add_tree_root (base, nelt)
- tree *base;
- int nelt;
-{
- ggc_add_root (base, nelt, sizeof (tree), ggc_mark_tree_ptr);
-}
-
-/* Register a varray of rtxs as a GC root. */
-
-void
-ggc_add_rtx_varray_root (base, nelt)
- varray_type *base;
- int nelt;
-{
- ggc_add_root (base, nelt, sizeof (varray_type),
- ggc_mark_rtx_varray_ptr);
-}
-
-/* Register a varray of trees as a GC root. */
-
-void
-ggc_add_tree_varray_root (base, nelt)
- varray_type *base;
- int nelt;
-{
- ggc_add_root (base, nelt, sizeof (varray_type),
- ggc_mark_tree_varray_ptr);
-}
-
-/* Register a hash table of trees as a GC root. */
-
-void
-ggc_add_tree_hash_table_root (base, nelt)
- struct hash_table **base;
- int nelt;
-{
- ggc_add_root (base, nelt, sizeof (struct hash_table *),
- ggc_mark_tree_hash_table_ptr);
-}
-
-/* Remove the previously registered GC root at BASE. */
-
-void
-ggc_del_root (base)
- void *base;
-{
- struct ggc_root *x, **p;
-
- p = &roots, x = roots;
- while (x)
- {
- if (x->base == base)
- {
- *p = x->next;
- free (x);
- return;
- }
- p = &x->next;
- x = x->next;
- }
-
- abort ();
-}
-
-/* Add a hash table to be scanned when all roots have been processed. We
- delete any entry in the table that has not been marked. */
-
-struct d_htab_root
-{
- struct d_htab_root *next;
- htab_t htab;
- ggc_htab_marked_p marked_p;
- ggc_htab_mark mark;
-};
-
-static struct d_htab_root *d_htab_roots;
-
-/* Add X, an htab, to a list of htabs that contain objects which are allocated
- from GC memory. Once all other roots are marked, we check each object in
- the htab to see if it has already been marked. If not, it is deleted.
-
- MARKED_P, if specified, is a function that returns 1 if the entry is to
- be considered as "marked". If not present, the data structure pointed to
- by the htab slot is tested. This function should be supplied if some
- other object (such as something pointed to by that object) should be tested
- in which case the function tests whether that object (or objects) are
- marked (using ggc_marked_p) and returns nonzero if it is.
-
- MARK, if specified, is a function that is passed the contents of a slot
- that has been determined to have been "marked" (via the above function)
- and marks any other objects pointed to by that object. For example,
- we might have a hash table of memory attribute blocks, which are pointed
- to by a MEM RTL but have a pointer to a DECL. MARKED_P in that case will
- not be specified because we want to know if the attribute block is pointed
- to by the MEM, but MARK must be specified because if the block has been
- marked, we need to mark the DECL. */
-
-void
-ggc_add_deletable_htab (x, marked_p, mark)
- PTR x;
- ggc_htab_marked_p marked_p;
- ggc_htab_mark mark;
-{
- struct d_htab_root *r
- = (struct d_htab_root *) xmalloc (sizeof (struct d_htab_root));
-
- r->next = d_htab_roots;
- r->htab = (htab_t) x;
- r->marked_p = marked_p ? marked_p : ggc_marked_p;
- r->mark = mark;
- d_htab_roots = r;
-}
-
/* Process a slot of an htab by deleting it if it has not been marked. */
static int
@@ -225,12 +92,12 @@ ggc_htab_delete (slot, info)
void **slot;
void *info;
{
- struct d_htab_root *r = (struct d_htab_root *) info;
+ const struct ggc_cache_tab *r = (const struct ggc_cache_tab *) info;
if (! (*r->marked_p) (*slot))
- htab_clear_slot (r->htab, slot);
- else if (r->mark)
- (*r->mark) (*slot);
+ htab_clear_slot (*r->base, slot);
+ else
+ (*r->cb) (*slot);
return 1;
}
@@ -241,9 +108,20 @@ void
ggc_mark_roots ()
{
struct ggc_root *x;
- struct d_htab_root *y;
-
- VARRAY_TREE_INIT (ggc_pending_trees, 4096, "ggc_pending_trees");
+ const struct ggc_root_tab *const *rt;
+ const struct ggc_root_tab *rti;
+ const struct ggc_cache_tab *const *ct;
+ const struct ggc_cache_tab *cti;
+ size_t i;
+
+ for (rt = gt_ggc_deletable_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ memset (rti->base, 0, rti->stride);
+
+ for (rt = gt_ggc_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ (*rti->cb)(*(void **)((char *)rti->base + rti->stride * i));
for (x = roots; x != NULL; x = x->next)
{
@@ -256,417 +134,77 @@ ggc_mark_roots ()
(*cb)(elt);
}
- /* Mark all the queued up trees, and their children. */
- ggc_mark_trees ();
- VARRAY_FREE (ggc_pending_trees);
-
/* Now scan all hash tables that have objects which are to be deleted if
- they are not already marked. Since these may mark more trees, we need
- to reinitialize that varray. */
- VARRAY_TREE_INIT (ggc_pending_trees, 1024, "ggc_pending_trees");
-
- for (y = d_htab_roots; y != NULL; y = y->next)
- htab_traverse (y->htab, ggc_htab_delete, (PTR) y);
- ggc_mark_trees ();
- VARRAY_FREE (ggc_pending_trees);
+ they are not already marked. */
+ for (ct = gt_ggc_cache_rtab; *ct; ct++)
+ for (cti = *ct; cti->base != NULL; cti++)
+ if (*cti->base)
+ htab_traverse (*cti->base, ggc_htab_delete, (PTR) cti);
}
-/* R had not been previously marked, but has now been marked via
- ggc_set_mark. Now recurse and process the children. */
-
-void
-ggc_mark_rtx_children (r)
- rtx r;
-{
- rtx i, last;
-
- /* Special case the instruction chain. This is a data structure whose
- chain length is potentially unbounded, and which contain references
- within the chain (e.g. label_ref and insn_list). If do nothing here,
- we risk blowing the stack recursing through a long chain of insns.
-
- Combat this by marking all of the instructions in the chain before
- marking the contents of those instructions. */
-
- switch (GET_CODE (r))
- {
- case INSN:
- case JUMP_INSN:
- case CALL_INSN:
- case NOTE:
- case CODE_LABEL:
- case BARRIER:
- for (i = NEXT_INSN (r); ; i = NEXT_INSN (i))
- if (! ggc_test_and_set_mark (i))
- break;
- last = i;
-
- for (i = NEXT_INSN (r); i != last; i = NEXT_INSN (i))
- ggc_mark_rtx_children_1 (i);
-
- default:
- break;
- }
-
- ggc_mark_rtx_children_1 (r);
-}
-
-static void
-ggc_mark_rtx_children_1 (r)
- rtx r;
+/* Allocate a block of memory, then clear it. */
+void *
+ggc_alloc_cleared (size)
+ size_t size;
{
- const char *fmt;
- int i;
- rtx next_rtx;
-
- do
- {
- enum rtx_code code = GET_CODE (r);
- /* This gets set to a child rtx to eliminate tail recursion. */
- next_rtx = NULL;
-
- /* Collect statistics, if appropriate. */
- if (ggc_stats)
- {
- ++ggc_stats->num_rtxs[(int) code];
- ggc_stats->size_rtxs[(int) code] += ggc_get_size (r);
- }
-
- /* ??? If (some of) these are really pass-dependent info, do we
- have any right poking our noses in? */
- switch (code)
- {
- case MEM:
- ggc_mark (MEM_ATTRS (r));
- break;
- case JUMP_INSN:
- ggc_mark_rtx (JUMP_LABEL (r));
- break;
- case CODE_LABEL:
- ggc_mark_rtx (LABEL_REFS (r));
- break;
- case LABEL_REF:
- ggc_mark_rtx (LABEL_NEXTREF (r));
- ggc_mark_rtx (CONTAINING_INSN (r));
- break;
- case ADDRESSOF:
- ggc_mark_tree (ADDRESSOF_DECL (r));
- break;
- case CONST_DOUBLE:
- ggc_mark_rtx (CONST_DOUBLE_CHAIN (r));
- break;
- case NOTE:
- switch (NOTE_LINE_NUMBER (r))
- {
- case NOTE_INSN_RANGE_BEG:
- case NOTE_INSN_RANGE_END:
- case NOTE_INSN_LIVE:
- case NOTE_INSN_EXPECTED_VALUE:
- ggc_mark_rtx (NOTE_RANGE_INFO (r));
- break;
-
- case NOTE_INSN_BLOCK_BEG:
- case NOTE_INSN_BLOCK_END:
- ggc_mark_tree (NOTE_BLOCK (r));
- break;
-
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-
- for (fmt = GET_RTX_FORMAT (GET_CODE (r)), i = 0; *fmt ; ++fmt, ++i)
- {
- rtx exp;
- switch (*fmt)
- {
- case 'e': case 'u':
- exp = XEXP (r, i);
- if (ggc_test_and_set_mark (exp))
- {
- if (next_rtx == NULL)
- next_rtx = exp;
- else
- ggc_mark_rtx_children (exp);
- }
- break;
- case 'V': case 'E':
- ggc_mark_rtvec (XVEC (r, i));
- break;
- }
- }
- }
- while ((r = next_rtx) != NULL);
+ void *buf = ggc_alloc (size);
+ memset (buf, 0, size);
+ return buf;
}
-/* V had not been previously marked, but has now been marked via
- ggc_set_mark. Now recurse and process the children. */
-
-void
-ggc_mark_rtvec_children (v)
- rtvec v;
+/* Resize a block of memory, possibly re-allocating it. */
+void *
+ggc_realloc (x, size)
+ void *x;
+ size_t size;
{
- int i;
+ void *r;
+ size_t old_size;
- i = GET_NUM_ELEM (v);
- while (--i >= 0)
- ggc_mark_rtx (RTVEC_ELT (v, i));
-}
-
-/* Recursively set marks on all of the children of the
- GCC_PENDING_TREES. */
+ if (x == NULL)
+ return ggc_alloc (size);
-static void
-ggc_mark_trees ()
-{
- while (ggc_pending_trees->elements_used)
+ old_size = ggc_get_size (x);
+ if (size <= old_size)
{
- tree t;
- enum tree_code code;
-
- t = VARRAY_TOP_TREE (ggc_pending_trees);
- VARRAY_POP (ggc_pending_trees);
- code = TREE_CODE (t);
-
- /* Collect statistics, if appropriate. */
- if (ggc_stats)
- {
- ++ggc_stats->num_trees[(int) code];
- ggc_stats->size_trees[(int) code] += ggc_get_size (t);
- }
-
- /* Bits from common. */
- ggc_mark_tree (TREE_TYPE (t));
- ggc_mark_tree (TREE_CHAIN (t));
-
- /* Some nodes require special handling. */
- switch (code)
- {
- case TREE_LIST:
- ggc_mark_tree (TREE_PURPOSE (t));
- ggc_mark_tree (TREE_VALUE (t));
- continue;
-
- case TREE_VEC:
- {
- int i = TREE_VEC_LENGTH (t);
-
- while (--i >= 0)
- ggc_mark_tree (TREE_VEC_ELT (t, i));
- continue;
- }
-
- case COMPLEX_CST:
- ggc_mark_tree (TREE_REALPART (t));
- ggc_mark_tree (TREE_IMAGPART (t));
- break;
-
- case PARM_DECL:
- ggc_mark_rtx (DECL_INCOMING_RTL (t));
- break;
-
- case FIELD_DECL:
- ggc_mark_tree (DECL_FIELD_BIT_OFFSET (t));
- break;
-
- case IDENTIFIER_NODE:
- lang_mark_tree (t);
- continue;
-
- default:
- break;
- }
-
- /* But in general we can handle them by class. */
- switch (TREE_CODE_CLASS (code))
- {
- case 'd': /* A decl node. */
- ggc_mark_tree (DECL_SIZE (t));
- ggc_mark_tree (DECL_SIZE_UNIT (t));
- ggc_mark_tree (DECL_NAME (t));
- ggc_mark_tree (DECL_CONTEXT (t));
- ggc_mark_tree (DECL_ARGUMENTS (t));
- ggc_mark_tree (DECL_RESULT_FLD (t));
- ggc_mark_tree (DECL_INITIAL (t));
- ggc_mark_tree (DECL_ABSTRACT_ORIGIN (t));
- ggc_mark_tree (DECL_SECTION_NAME (t));
- ggc_mark_tree (DECL_ATTRIBUTES (t));
- if (DECL_RTL_SET_P (t))
- ggc_mark_rtx (DECL_RTL (t));
- ggc_mark_rtx (DECL_LIVE_RANGE_RTL (t));
- ggc_mark_tree (DECL_VINDEX (t));
- if (DECL_ASSEMBLER_NAME_SET_P (t))
- ggc_mark_tree (DECL_ASSEMBLER_NAME (t));
- if (TREE_CODE (t) == FUNCTION_DECL)
- {
- ggc_mark_tree (DECL_SAVED_TREE (t));
- ggc_mark_tree (DECL_INLINED_FNS (t));
- if (DECL_SAVED_INSNS (t))
- ggc_mark_struct_function (DECL_SAVED_INSNS (t));
- }
- lang_mark_tree (t);
- break;
-
- case 't': /* A type node. */
- ggc_mark_tree (TYPE_SIZE (t));
- ggc_mark_tree (TYPE_SIZE_UNIT (t));
- ggc_mark_tree (TYPE_ATTRIBUTES (t));
- ggc_mark_tree (TYPE_VALUES (t));
- ggc_mark_tree (TYPE_POINTER_TO (t));
- ggc_mark_tree (TYPE_REFERENCE_TO (t));
- ggc_mark_tree (TYPE_NAME (t));
- ggc_mark_tree (TYPE_MIN_VALUE (t));
- ggc_mark_tree (TYPE_MAX_VALUE (t));
- ggc_mark_tree (TYPE_NEXT_VARIANT (t));
- ggc_mark_tree (TYPE_MAIN_VARIANT (t));
- ggc_mark_tree (TYPE_BINFO (t));
- ggc_mark_tree (TYPE_CONTEXT (t));
- lang_mark_tree (t);
- break;
-
- case 'b': /* A lexical block. */
- ggc_mark_tree (BLOCK_VARS (t));
- ggc_mark_tree (BLOCK_SUBBLOCKS (t));
- ggc_mark_tree (BLOCK_SUPERCONTEXT (t));
- ggc_mark_tree (BLOCK_ABSTRACT_ORIGIN (t));
- break;
-
- case 'c': /* A constant. */
- ggc_mark_rtx (TREE_CST_RTL (t));
- break;
-
- case 'r': case '<': case '1':
- case '2': case 'e': case 's': /* Expressions. */
- {
- int i = TREE_CODE_LENGTH (TREE_CODE (t));
- int first_rtl = first_rtl_op (TREE_CODE (t));
-
- while (--i >= 0)
- {
- if (i >= first_rtl)
- ggc_mark_rtx ((rtx) TREE_OPERAND (t, i));
- else
- ggc_mark_tree (TREE_OPERAND (t, i));
- }
- break;
- }
-
- case 'x':
- lang_mark_tree (t);
- break;
- }
+ /* Mark the unwanted memory as unaccessible. We also need to make
+ the "new" size accessible, since ggc_get_size returns the size of
+ the pool, not the size of the individually allocated object, the
+ size which was previously made accessible. Unfortunately, we
+ don't know that previously allocated size. Without that
+ knowledge we have to lose some initialization-tracking for the
+ old parts of the object. An alternative is to mark the whole
+ old_size as reachable, but that would lose tracking of writes
+ after the end of the object (by small offsets). Discard the
+ handle to avoid handle leak. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS ((char *) x + size,
+ old_size - size));
+ VALGRIND_DISCARD (VALGRIND_MAKE_READABLE (x, size));
+ return x;
}
-}
-
-/* Mark all the elements of the varray V, which contains rtxs. */
-
-void
-ggc_mark_rtx_varray (v)
- varray_type v;
-{
- int i;
-
- if (v)
- for (i = v->num_elements - 1; i >= 0; --i)
- ggc_mark_rtx (VARRAY_RTX (v, i));
-}
-
-/* Mark all the elements of the varray V, which contains trees. */
-
-void
-ggc_mark_tree_varray (v)
- varray_type v;
-{
- int i;
-
- if (v)
- for (i = v->num_elements - 1; i >= 0; --i)
- ggc_mark_tree (VARRAY_TREE (v, i));
-}
-
-/* Mark the hash table-entry HE. Its key field is really a tree. */
-
-static bool
-ggc_mark_tree_hash_table_entry (he, k)
- struct hash_entry *he;
- hash_table_key k ATTRIBUTE_UNUSED;
-{
- ggc_mark_tree ((tree) he->key);
- return true;
-}
-
-/* Mark all the elements of the hash-table H, which contains trees. */
-
-void
-ggc_mark_tree_hash_table (ht)
- struct hash_table *ht;
-{
- hash_traverse (ht, ggc_mark_tree_hash_table_entry, /*info=*/0);
-}
-
-/* Type-correct function to pass to ggc_add_root. It just forwards
- *ELT (which is an rtx) to ggc_mark_rtx. */
-
-static void
-ggc_mark_rtx_ptr (elt)
- void *elt;
-{
- ggc_mark_rtx (*(rtx *) elt);
-}
-/* Type-correct function to pass to ggc_add_root. It just forwards
- *ELT (which is a tree) to ggc_mark_tree. */
+ r = ggc_alloc (size);
-static void
-ggc_mark_tree_ptr (elt)
- void *elt;
-{
- ggc_mark_tree (*(tree *) elt);
-}
-
-/* Type-correct function to pass to ggc_add_root. It just forwards
- ELT (which is really a varray_type *) to ggc_mark_rtx_varray. */
+ /* Since ggc_get_size returns the size of the pool, not the size of the
+ individually allocated object, we'd access parts of the old object
+ that were marked invalid with the memcpy below. We lose a bit of the
+ initialization-tracking since some of it may be uninitialized. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_READABLE (x, old_size));
-static void
-ggc_mark_rtx_varray_ptr (elt)
- void *elt;
-{
- ggc_mark_rtx_varray (*(varray_type *) elt);
-}
-
-/* Type-correct function to pass to ggc_add_root. It just forwards
- ELT (which is really a varray_type *) to ggc_mark_tree_varray. */
-
-static void
-ggc_mark_tree_varray_ptr (elt)
- void *elt;
-{
- ggc_mark_tree_varray (*(varray_type *) elt);
-}
+ memcpy (r, x, old_size);
-/* Type-correct function to pass to ggc_add_root. It just forwards
- ELT (which is really a struct hash_table **) to
- ggc_mark_tree_hash_table. */
+ /* The old object is not supposed to be used anymore. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (x, old_size));
-static void
-ggc_mark_tree_hash_table_ptr (elt)
- void *elt;
-{
- ggc_mark_tree_hash_table (*(struct hash_table **) elt);
+ return r;
}
-/* Allocate a block of memory, then clear it. */
+/* Like ggc_alloc_cleared, but performs a multiplication. */
void *
-ggc_alloc_cleared (size)
- size_t size;
+ggc_calloc (s1, s2)
+ size_t s1, s2;
{
- void *buf = ggc_alloc (size);
- memset (buf, 0, size);
- return buf;
+ return ggc_alloc_cleared (s1 * s2);
}
/* Print statistics that are independent of the collector in use. */
@@ -704,17 +242,17 @@ ggc_print_common_statistics (stream, stats)
}
/* Print the statistics for trees. */
- fprintf (stream, "\n%-17s%10s %16s %10s\n", "Tree",
+ fprintf (stream, "\n%-17s%10s %16s %10s\n", "Tree",
"Number", "Bytes", "% Total");
for (code = 0; code < MAX_TREE_CODES; ++code)
- if (ggc_stats->num_trees[code])
+ if (ggc_stats->num_trees[code])
{
fprintf (stream, "%-17s%10u%16ld%c %10.3f\n",
tree_code_name[code],
ggc_stats->num_trees[code],
SCALE (ggc_stats->size_trees[code]),
LABEL (ggc_stats->size_trees[code]),
- (100 * ((double) ggc_stats->size_trees[code])
+ (100 * ((double) ggc_stats->size_trees[code])
/ ggc_stats->total_size_trees));
}
fprintf (stream,
@@ -724,17 +262,17 @@ ggc_print_common_statistics (stream, stats)
LABEL (ggc_stats->total_size_trees));
/* Print the statistics for RTL. */
- fprintf (stream, "\n%-17s%10s %16s %10s\n", "RTX",
+ fprintf (stream, "\n%-17s%10s %16s %10s\n", "RTX",
"Number", "Bytes", "% Total");
for (code = 0; code < NUM_RTX_CODE; ++code)
- if (ggc_stats->num_rtxs[code])
+ if (ggc_stats->num_rtxs[code])
{
fprintf (stream, "%-17s%10u%16ld%c %10.3f\n",
rtx_name[code],
ggc_stats->num_rtxs[code],
SCALE (ggc_stats->size_rtxs[code]),
LABEL (ggc_stats->size_rtxs[code]),
- (100 * ((double) ggc_stats->size_rtxs[code])
+ (100 * ((double) ggc_stats->size_rtxs[code])
/ ggc_stats->total_size_rtxs));
}
fprintf (stream,
@@ -746,3 +284,81 @@ ggc_print_common_statistics (stream, stats)
/* Don't gather statistics any more. */
ggc_stats = NULL;
}
+
+/* Modify the bound based on rlimits. Keep the smallest number found. */
+static double
+ggc_rlimit_bound (limit)
+ double limit;
+{
+#if defined(HAVE_GETRLIMIT)
+ struct rlimit rlim;
+# ifdef RLIMIT_RSS
+ if (getrlimit (RLIMIT_RSS, &rlim) == 0
+ && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
+ && rlim.rlim_cur < limit)
+ limit = rlim.rlim_cur;
+# endif
+# ifdef RLIMIT_DATA
+ if (getrlimit (RLIMIT_DATA, &rlim) == 0
+ && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
+ && rlim.rlim_cur < limit)
+ limit = rlim.rlim_cur;
+# endif
+# ifdef RLIMIT_AS
+ if (getrlimit (RLIMIT_AS, &rlim) == 0
+ && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
+ && rlim.rlim_cur < limit)
+ limit = rlim.rlim_cur;
+# endif
+#endif /* HAVE_GETRLIMIT */
+
+ return limit;
+}
+
+/* Heuristic to set a default for GGC_MIN_EXPAND. */
+int
+ggc_min_expand_heuristic()
+{
+ double min_expand = physmem_total();
+
+ /* Adjust for rlimits. */
+ min_expand = ggc_rlimit_bound (min_expand);
+
+ /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding
+ a lower bound of 30% and an upper bound of 100% (when RAM >= 1GB). */
+ min_expand /= 1024*1024*1024;
+ min_expand *= 70;
+ min_expand = MIN (min_expand, 70);
+ min_expand += 30;
+
+ return min_expand;
+}
+
+/* Heuristic to set a default for GGC_MIN_HEAPSIZE. */
+int
+ggc_min_heapsize_heuristic()
+{
+ double min_heap_kbytes = physmem_total();
+
+ /* Adjust for rlimits. */
+ min_heap_kbytes = ggc_rlimit_bound (min_heap_kbytes);
+
+ min_heap_kbytes /= 1024; /* convert to Kbytes. */
+
+ /* The heuristic is RAM/8, with a lower bound of 4M and an upper
+ bound of 128M (when RAM >= 1GB). */
+ min_heap_kbytes /= 8;
+ min_heap_kbytes = MAX (min_heap_kbytes, 4 * 1024);
+ min_heap_kbytes = MIN (min_heap_kbytes, 128 * 1024);
+
+ return min_heap_kbytes;
+}
+
+void
+init_ggc_heuristics ()
+{
+#ifndef ENABLE_GC_ALWAYS_COLLECT
+ set_param_value ("ggc-min-expand", ggc_min_expand_heuristic());
+ set_param_value ("ggc-min-heapsize", ggc_min_heapsize_heuristic());
+#endif
+}
diff --git a/contrib/gcc/ggc-none.c b/contrib/gcc/ggc-none.c
index ae3f6e9..3711475 100644
--- a/contrib/gcc/ggc-none.c
+++ b/contrib/gcc/ggc-none.c
@@ -32,3 +32,18 @@ ggc_alloc (size)
{
return xmalloc (size);
}
+
+void *
+ggc_alloc_cleared (size)
+ size_t size;
+{
+ return xcalloc (size, 1);
+}
+
+void *
+ggc_realloc (x, size)
+ void *x;
+ size_t size;
+{
+ return xrealloc (x, size);
+}
diff --git a/contrib/gcc/ggc-page.c b/contrib/gcc/ggc-page.c
index ad3f815..3f5194a 100644
--- a/contrib/gcc/ggc-page.c
+++ b/contrib/gcc/ggc-page.c
@@ -24,10 +24,16 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "rtl.h"
#include "tm_p.h"
#include "toplev.h"
-#include "varray.h"
#include "flags.h"
#include "ggc.h"
#include "timevar.h"
+#include "params.h"
+#ifdef ENABLE_VALGRIND_CHECKING
+#include <valgrind.h>
+#else
+/* Avoid #ifdef:s when we can help it. */
+#define VALGRIND_DISCARD(x)
+#endif
/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
file open. Prefer either to valloc. */
@@ -59,7 +65,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define USING_MALLOC_PAGE_GROUPS
#endif
-/* Stategy:
+/* Stategy:
This garbage-collecting allocator allocates objects on one of a set
of pages. Each page can allocate objects of a single size only;
@@ -74,7 +80,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
Each page-entry also has a context depth, which is used to track
pushing and popping of allocation contexts. Only objects allocated
- in the current (highest-numbered) context may be collected.
+ in the current (highest-numbered) context may be collected.
Page entries are arranged in an array of singly-linked lists. The
array is indexed by the allocation size, in bits, of the pages on
@@ -88,23 +94,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
deallocated at the start of the next collection if they haven't
been recycled by then. */
-
-/* Define GGC_POISON to poison memory marked unused by the collector. */
-#undef GGC_POISON
-
-/* Define GGC_ALWAYS_COLLECT to perform collection every time
- ggc_collect is invoked. Otherwise, collection is performed only
- when a significant amount of memory has been allocated since the
- last collection. */
-#undef GGC_ALWAYS_COLLECT
-
-#ifdef ENABLE_GC_CHECKING
-#define GGC_POISON
-#endif
-#ifdef ENABLE_GC_ALWAYS_COLLECT
-#define GGC_ALWAYS_COLLECT
-#endif
-
/* Define GGC_DEBUG_LEVEL to print debugging information.
0: No debugging output.
1: GC statistics only.
@@ -133,7 +122,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
The bottommost HOST_PAGE_SIZE_BITS are ignored, since page-entry
pages are aligned on system page boundaries. The next most
significant PAGE_L2_BITS and PAGE_L1_BITS are the second and first
- index values in the lookup table, respectively.
+ index values in the lookup table, respectively.
For 32-bit architectures and the settings below, there are no
leftover bits. For architectures with wider pointers, the lookup
@@ -158,11 +147,22 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* The size of an object on a page of the indicated ORDER. */
#define OBJECT_SIZE(ORDER) object_size_table[ORDER]
+/* For speed, we avoid doing a general integer divide to locate the
+ offset in the allocation bitmap, by precalculating numbers M, S
+ such that (O * M) >> S == O / Z (modulo 2^32), for any offset O
+ within the page which is evenly divisible by the object size Z. */
+#define DIV_MULT(ORDER) inverse_table[ORDER].mult
+#define DIV_SHIFT(ORDER) inverse_table[ORDER].shift
+#define OFFSET_TO_BIT(OFFSET, ORDER) \
+ (((OFFSET) * DIV_MULT (ORDER)) >> DIV_SHIFT (ORDER))
+
/* The number of extra orders, not corresponding to power-of-two sized
objects. */
-#define NUM_EXTRA_ORDERS \
- (sizeof (extra_order_size_table) / sizeof (extra_order_size_table[0]))
+#define NUM_EXTRA_ORDERS ARRAY_SIZE (extra_order_size_table)
+
+#define RTL_SIZE(NSLOTS) \
+ (sizeof (struct rtx_def) + ((NSLOTS) - 1) * sizeof (rtunion))
/* The Ith entry is the maximum size of an object to be stored in the
Ith extra order. Adding a new entry to this array is the *only*
@@ -170,7 +170,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
static const size_t extra_order_size_table[] = {
sizeof (struct tree_decl),
- sizeof (struct tree_list)
+ sizeof (struct tree_list),
+ RTL_SIZE (2), /* REG, MEM, PLUS, etc. */
+ RTL_SIZE (10), /* INSN, CALL_INSN, JUMP_INSN */
};
/* The total number of orders. */
@@ -205,9 +207,20 @@ static unsigned objects_per_page_table[NUM_ORDERS];
static size_t object_size_table[NUM_ORDERS];
+/* The Ith entry is a pair of numbers (mult, shift) such that
+ ((k * mult) >> shift) mod 2^32 == (k / OBJECT_SIZE(I)) mod 2^32,
+ for all k evenly divisible by OBJECT_SIZE(I). */
+
+static struct
+{
+ unsigned int mult;
+ unsigned int shift;
+}
+inverse_table[NUM_ORDERS];
+
/* A page_entry records the status of an allocation page. This
structure is dynamically sized to fit the bitmap in_use_p. */
-typedef struct page_entry
+typedef struct page_entry
{
/* The next page-entry with objects of the same size, or NULL if
this is the last page-entry. */
@@ -225,9 +238,9 @@ typedef struct page_entry
struct page_group *group;
#endif
- /* Saved in-use bit vector for pages that aren't in the topmost
- context during collection. */
- unsigned long *save_in_use_p;
+ /* This is the index in the by_depth varray where this page table
+ can be found. */
+ unsigned long index_by_depth;
/* Context depth of this page. */
unsigned short context_depth;
@@ -316,6 +329,12 @@ static struct globals
/* Total amount of memory mapped. */
size_t bytes_mapped;
+ /* Bit N set if any allocations have been done at context depth N. */
+ unsigned long context_depth_allocations;
+
+ /* Bit N set if any collections have been done at context depth N. */
+ unsigned long context_depth_collections;
+
/* The current depth in the context stack. */
unsigned short context_depth;
@@ -333,6 +352,36 @@ static struct globals
/* The file descriptor for debugging output. */
FILE *debug_file;
+
+ /* Current number of elements in use in depth below. */
+ unsigned int depth_in_use;
+
+ /* Maximum number of elements that can be used before resizing. */
+ unsigned int depth_max;
+
+ /* Each element of this arry is an index in by_depth where the given
+ depth starts. This structure is indexed by that given depth we
+ are interested in. */
+ unsigned int *depth;
+
+ /* Current number of elements in use in by_depth below. */
+ unsigned int by_depth_in_use;
+
+ /* Maximum number of elements that can be used before resizing. */
+ unsigned int by_depth_max;
+
+ /* Each element of this array is a pointer to a page_entry, all
+ page_entries can be found in here by increasing depth.
+ index_by_depth in the page_entry is the index into this data
+ structure where that page_entry can be found. This is used to
+ speed up finding all page_entries at a particular depth. */
+ page_entry **by_depth;
+
+ /* Each element is a pointer to the saved in_use_p bits, if any,
+ zero otherwise. We allocate them all together, to enable a
+ better runtime data access pattern. */
+ unsigned long **save_in_use;
+
} G;
/* The size in bytes required to maintain a bitmap for the objects
@@ -340,21 +389,14 @@ static struct globals
#define BITMAP_SIZE(Num_objects) \
(CEIL ((Num_objects), HOST_BITS_PER_LONG) * sizeof(long))
-/* Skip garbage collection if the current allocation is not at least
- this factor times the allocation at the end of the last collection.
- In other words, total allocation must expand by (this factor minus
- one) before collection is performed. */
-#define GGC_MIN_EXPAND_FOR_GC (1.3)
-
-/* Bound `allocated_last_gc' to 4MB, to prevent the memory expansion
- test from triggering too often when the heap is small. */
-#define GGC_MIN_LAST_ALLOCATED (4 * 1024 * 1024)
-
/* Allocate pages in chunks of this size, to throttle calls to memory
allocation routines. The first page is used, the rest go onto the
free list. This cannot be larger than HOST_BITS_PER_INT for the
in_use bitmask for page_group. */
#define GGC_QUIRE_SIZE 16
+
+/* Initial guess as to how many page table entries we might need. */
+#define INITIAL_PTE_COUNT 128
static int ggc_allocated_p PARAMS ((const void *));
static page_entry *lookup_page_table_entry PARAMS ((const void *));
@@ -373,14 +415,60 @@ static void release_pages PARAMS ((void));
static void clear_marks PARAMS ((void));
static void sweep_pages PARAMS ((void));
static void ggc_recalculate_in_use_p PARAMS ((page_entry *));
+static void compute_inverse PARAMS ((unsigned));
+static inline void adjust_depth PARAMS ((void));
-#ifdef GGC_POISON
+#ifdef ENABLE_GC_CHECKING
static void poison_pages PARAMS ((void));
#endif
void debug_print_page_list PARAMS ((int));
+static void push_depth PARAMS ((unsigned int));
+static void push_by_depth PARAMS ((page_entry *, unsigned long *));
-/* Returns non-zero if P was allocated in GC'able memory. */
+/* Push an entry onto G.depth. */
+
+inline static void
+push_depth (i)
+ unsigned int i;
+{
+ if (G.depth_in_use >= G.depth_max)
+ {
+ G.depth_max *= 2;
+ G.depth = (unsigned int *) xrealloc ((char *) G.depth,
+ G.depth_max * sizeof (unsigned int));
+ }
+ G.depth[G.depth_in_use++] = i;
+}
+
+/* Push an entry onto G.by_depth and G.save_in_use. */
+
+inline static void
+push_by_depth (p, s)
+ page_entry *p;
+ unsigned long *s;
+{
+ if (G.by_depth_in_use >= G.by_depth_max)
+ {
+ G.by_depth_max *= 2;
+ G.by_depth = (page_entry **) xrealloc ((char *) G.by_depth,
+ G.by_depth_max * sizeof (page_entry *));
+ G.save_in_use = (unsigned long **) xrealloc ((char *) G.save_in_use,
+ G.by_depth_max * sizeof (unsigned long *));
+ }
+ G.by_depth[G.by_depth_in_use] = p;
+ G.save_in_use[G.by_depth_in_use++] = s;
+}
+
+/* For the 3.3 release, we will avoid prefetch, as it isn't tested widely. */
+#define prefetch(X) ((void) X)
+
+#define save_in_use_p_i(__i) \
+ (G.save_in_use[__i])
+#define save_in_use_p(__p) \
+ (save_in_use_p_i (__p->index_by_depth))
+
+/* Returns nonzero if P was allocated in GC'able memory. */
static inline int
ggc_allocated_p (p)
@@ -412,7 +500,7 @@ ggc_allocated_p (p)
return base[L1] && base[L1][L2];
}
-/* Traverse the page table and find the entry for a page.
+/* Traverse the page table and find the entry for a page.
Die (probably) if the object wasn't allocated via GC. */
static inline page_entry *
@@ -525,6 +613,11 @@ alloc_anon (pref, size)
/* Remember that we allocated this memory. */
G.bytes_mapped += size;
+ /* Pretend we don't have access to the allocated pages. We'll enable
+ access to smaller pieces of the area in ggc_alloc. Discard the
+ handle to avoid handle leak. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (page, size));
+
return page;
}
#endif
@@ -719,6 +812,8 @@ alloc_page (order)
entry->num_free_objects = num_objects;
entry->next_bit_hint = 1;
+ G.context_depth_allocations |= (unsigned long)1 << G.context_depth;
+
#ifdef USING_MALLOC_PAGE_GROUPS
entry->group = group;
set_page_group_in_use (group, page);
@@ -732,14 +827,34 @@ alloc_page (order)
set_page_table_entry (page, entry);
if (GGC_DEBUG_LEVEL >= 2)
- fprintf (G.debug_file,
- "Allocating page at %p, object size=%ld, data %p-%p\n",
- (PTR) entry, (long) OBJECT_SIZE (order), page,
+ fprintf (G.debug_file,
+ "Allocating page at %p, object size=%lu, data %p-%p\n",
+ (PTR) entry, (unsigned long) OBJECT_SIZE (order), page,
page + entry_size - 1);
return entry;
}
+/* Adjust the size of G.depth so that no index greater than the one
+ used by the top of the G.by_depth is used. */
+
+static inline void
+adjust_depth ()
+{
+ page_entry *top;
+
+ if (G.by_depth_in_use)
+ {
+ top = G.by_depth[G.by_depth_in_use-1];
+
+ /* Peel back indicies in depth that index into by_depth, so that
+ as new elements are added to by_depth, we note the indicies
+ of those elements, if they are for new context depths. */
+ while (G.depth_in_use > (size_t)top->context_depth+1)
+ --G.depth_in_use;
+ }
+}
+
/* For a page that is no longer needed, put it on the free page list. */
static inline void
@@ -747,16 +862,44 @@ free_page (entry)
page_entry *entry;
{
if (GGC_DEBUG_LEVEL >= 2)
- fprintf (G.debug_file,
+ fprintf (G.debug_file,
"Deallocating page at %p, data %p-%p\n", (PTR) entry,
entry->page, entry->page + entry->bytes - 1);
+ /* Mark the page as inaccessible. Discard the handle to avoid handle
+ leak. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (entry->page, entry->bytes));
+
set_page_table_entry (entry->page, NULL);
#ifdef USING_MALLOC_PAGE_GROUPS
clear_page_group_in_use (entry->group, entry->page);
#endif
+ if (G.by_depth_in_use > 1)
+ {
+ page_entry *top = G.by_depth[G.by_depth_in_use-1];
+
+ /* If they are at the same depth, put top element into freed
+ slot. */
+ if (entry->context_depth == top->context_depth)
+ {
+ int i = entry->index_by_depth;
+ G.by_depth[i] = top;
+ G.save_in_use[i] = G.save_in_use[G.by_depth_in_use-1];
+ top->index_by_depth = i;
+ }
+ else
+ {
+ /* We cannot free a page from a context deeper than the
+ current one. */
+ abort ();
+ }
+ }
+ --G.by_depth_in_use;
+
+ adjust_depth ();
+
entry->next = G.free_pages;
G.free_pages = entry;
}
@@ -817,7 +960,7 @@ release_pages ()
if (g->in_use == 0)
{
*gp = g->next;
- G.bytes_mapped -= g->alloc_size;
+ G.bytes_mapped -= g->alloc_size;
free (g->allocation);
}
else
@@ -828,16 +971,16 @@ release_pages ()
/* This table provides a fast way to determine ceil(log_2(size)) for
allocation requests. The minimum allocation size is eight bytes. */
-static unsigned char size_lookup[257] =
+static unsigned char size_lookup[257] =
{
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
- 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
+ 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
@@ -849,7 +992,7 @@ static unsigned char size_lookup[257] =
8
};
-/* Allocate a chunk of memory of SIZE bytes. If ZERO is non-zero, the
+/* Allocate a chunk of memory of SIZE bytes. If ZERO is nonzero, the
memory is zeroed; otherwise, its contents are undefined. */
void *
@@ -879,11 +1022,19 @@ ggc_alloc (size)
{
struct page_entry *new_entry;
new_entry = alloc_page (order);
-
+
+ new_entry->index_by_depth = G.by_depth_in_use;
+ push_by_depth (new_entry, 0);
+
+ /* We can skip context depths, if we do, make sure we go all the
+ way to the new depth. */
+ while (new_entry->context_depth >= G.depth_in_use)
+ push_depth (G.by_depth_in_use-1);
+
/* If this is the only entry, it's also the tail. */
if (entry == NULL)
G.page_tails[order] = new_entry;
-
+
/* Put new pages at the head of the page list. */
new_entry->next = entry;
entry = new_entry;
@@ -905,7 +1056,7 @@ ggc_alloc (size)
unsigned hint = entry->next_bit_hint;
word = hint / HOST_BITS_PER_LONG;
bit = hint % HOST_BITS_PER_LONG;
-
+
/* If the hint didn't work, scan the bitmap from the beginning. */
if ((entry->in_use_p[word] >> bit) & 1)
{
@@ -943,20 +1094,37 @@ ggc_alloc (size)
/* Calculate the object's address. */
result = entry->page + object_offset;
-#ifdef GGC_POISON
+#ifdef ENABLE_GC_CHECKING
+ /* Keep poisoning-by-writing-0xaf the object, in an attempt to keep the
+ exact same semantics in presence of memory bugs, regardless of
+ ENABLE_VALGRIND_CHECKING. We override this request below. Drop the
+ handle to avoid handle leak. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_WRITABLE (result, OBJECT_SIZE (order)));
+
/* `Poison' the entire allocated object, including any padding at
the end. */
memset (result, 0xaf, OBJECT_SIZE (order));
+
+ /* Make the bytes after the end of the object unaccessible. Discard the
+ handle to avoid handle leak. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS ((char *) result + size,
+ OBJECT_SIZE (order) - size));
#endif
+ /* Tell Valgrind that the memory is there, but its content isn't
+ defined. The bytes at the end of the object are still marked
+ unaccessible. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_WRITABLE (result, size));
+
/* Keep track of how many bytes are being allocated. This
information is used in deciding when to collect. */
G.allocated += OBJECT_SIZE (order);
if (GGC_DEBUG_LEVEL >= 3)
- fprintf (G.debug_file,
- "Allocating object, requested size=%ld, actual=%ld at %p on %p\n",
- (long) size, (long) OBJECT_SIZE (order), result, (PTR) entry);
+ fprintf (G.debug_file,
+ "Allocating object, requested size=%lu, actual=%lu at %p on %p\n",
+ (unsigned long) size, (unsigned long) OBJECT_SIZE (order), result,
+ (PTR) entry);
return result;
}
@@ -983,10 +1151,10 @@ ggc_set_mark (p)
/* Calculate the index of the object on the page; this is its bit
position in the in_use_p bitmap. */
- bit = (((const char *) p) - entry->page) / OBJECT_SIZE (entry->order);
+ bit = OFFSET_TO_BIT (((const char *) p) - entry->page, entry->order);
word = bit / HOST_BITS_PER_LONG;
mask = (unsigned long) 1 << (bit % HOST_BITS_PER_LONG);
-
+
/* If the bit was previously set, skip it. */
if (entry->in_use_p[word] & mask)
return 1;
@@ -1001,7 +1169,7 @@ ggc_set_mark (p)
return 0;
}
-/* Return 1 if P has been marked, zero otherwise.
+/* Return 1 if P has been marked, zero otherwise.
P must have been allocated by the GC allocator; it mustn't point to
static objects, stack variables, or memory allocated with malloc. */
@@ -1023,10 +1191,10 @@ ggc_marked_p (p)
/* Calculate the index of the object on the page; this is its bit
position in the in_use_p bitmap. */
- bit = (((const char *) p) - entry->page) / OBJECT_SIZE (entry->order);
+ bit = OFFSET_TO_BIT (((const char *) p) - entry->page, entry->order);
word = bit / HOST_BITS_PER_LONG;
mask = (unsigned long) 1 << (bit % HOST_BITS_PER_LONG);
-
+
return (entry->in_use_p[word] & mask) != 0;
}
@@ -1040,8 +1208,49 @@ ggc_get_size (p)
return OBJECT_SIZE (pe->order);
}
-/* Initialize the ggc-mmap allocator. */
+/* Subroutine of init_ggc which computes the pair of numbers used to
+ perform division by OBJECT_SIZE (order) and fills in inverse_table[].
+
+ This algorithm is taken from Granlund and Montgomery's paper
+ "Division by Invariant Integers using Multiplication"
+ (Proc. SIGPLAN PLDI, 1994), section 9 (Exact division by
+ constants). */
+
+static void
+compute_inverse (order)
+ unsigned order;
+{
+ unsigned size, inv, e;
+
+ /* There can be only one object per "page" in a bucket for sizes
+ larger than half a machine page; it will always have offset zero. */
+ if (OBJECT_SIZE (order) > G.pagesize/2)
+ {
+ if (OBJECTS_PER_PAGE (order) != 1)
+ abort ();
+
+ DIV_MULT (order) = 1;
+ DIV_SHIFT (order) = 0;
+ return;
+ }
+
+ size = OBJECT_SIZE (order);
+ e = 0;
+ while (size % 2 == 0)
+ {
+ e++;
+ size >>= 1;
+ }
+
+ inv = size;
+ while (inv * size != 1)
+ inv = inv * (2 - inv*size);
+
+ DIV_MULT (order) = inv;
+ DIV_SHIFT (order) = e;
+}
+/* Initialize the ggc-mmap allocator. */
void
init_ggc ()
{
@@ -1053,7 +1262,7 @@ init_ggc ()
#ifdef HAVE_MMAP_DEV_ZERO
G.dev_zero_fd = open ("/dev/zero", O_RDONLY);
if (G.dev_zero_fd == -1)
- abort ();
+ fatal_io_error ("open /dev/zero");
#endif
#if 0
@@ -1062,8 +1271,6 @@ init_ggc ()
G.debug_file = stdout;
#endif
- G.allocated_last_gc = GGC_MIN_LAST_ALLOCATED;
-
#ifdef USING_MMAP
/* StunOS has an amazing off-by-one error for the first mmap allocation
after fiddling with RLIMIT_STACK. The result, as hard as it is to
@@ -1104,12 +1311,13 @@ init_ggc ()
object_size_table[order] = s;
}
- /* Initialize the objects-per-page table. */
+ /* Initialize the objects-per-page and inverse tables. */
for (order = 0; order < NUM_ORDERS; ++order)
{
objects_per_page_table[order] = G.pagesize / OBJECT_SIZE (order);
if (objects_per_page_table[order] == 0)
objects_per_page_table[order] = 1;
+ compute_inverse (order);
}
/* Reset the size_lookup array to put appropriately sized objects in
@@ -1125,6 +1333,15 @@ init_ggc ()
for (i = OBJECT_SIZE (order); size_lookup [i] == o; --i)
size_lookup[i] = order;
}
+
+ G.depth_in_use = 0;
+ G.depth_max = 10;
+ G.depth = (unsigned int *) xmalloc (G.depth_max * sizeof (unsigned int));
+
+ G.by_depth_in_use = 0;
+ G.by_depth_max = INITIAL_PTE_COUNT;
+ G.by_depth = (page_entry **) xmalloc (G.by_depth_max * sizeof (page_entry *));
+ G.save_in_use = (unsigned long **) xmalloc (G.by_depth_max * sizeof (unsigned long *));
}
/* Increment the `GC context'. Objects allocated in an outer context
@@ -1136,7 +1353,7 @@ ggc_push_context ()
++G.context_depth;
/* Die on wrap. */
- if (G.context_depth == 0)
+ if (G.context_depth >= HOST_BITS_PER_LONG)
abort ();
}
@@ -1150,7 +1367,7 @@ ggc_recalculate_in_use_p (p)
unsigned int i;
size_t num_objects;
- /* Because the past-the-end bit in in_use_p is always set, we
+ /* Because the past-the-end bit in in_use_p is always set, we
pretend there is one additional object. */
num_objects = OBJECTS_PER_PAGE (p->order) + 1;
@@ -1158,7 +1375,7 @@ ggc_recalculate_in_use_p (p)
p->num_free_objects = num_objects;
/* Combine the IN_USE_P and SAVE_IN_USE_P arrays. */
- for (i = 0;
+ for (i = 0;
i < CEIL (BITMAP_SIZE (num_objects),
sizeof (*p->in_use_p));
++i)
@@ -1167,7 +1384,7 @@ ggc_recalculate_in_use_p (p)
/* Something is in use if it is marked, or if it was in use in a
context further down the context stack. */
- p->in_use_p[i] |= p->save_in_use_p[i];
+ p->in_use_p[i] |= save_in_use_p (p)[i];
/* Decrement the free object count for every object allocated. */
for (j = p->in_use_p[i]; j; j >>= 1)
@@ -1178,19 +1395,88 @@ ggc_recalculate_in_use_p (p)
abort ();
}
-/* Decrement the `GC context'. All objects allocated since the
+/* Decrement the `GC context'. All objects allocated since the
previous ggc_push_context are migrated to the outer context. */
void
ggc_pop_context ()
{
- unsigned order, depth;
+ unsigned long omask;
+ unsigned int depth, i, e;
+#ifdef ENABLE_CHECKING
+ unsigned int order;
+#endif
depth = --G.context_depth;
+ omask = (unsigned long)1 << (depth + 1);
+
+ if (!((G.context_depth_allocations | G.context_depth_collections) & omask))
+ return;
+
+ G.context_depth_allocations |= (G.context_depth_allocations & omask) >> 1;
+ G.context_depth_allocations &= omask - 1;
+ G.context_depth_collections &= omask - 1;
+
+ /* The G.depth array is shortend so that the last index is the
+ context_depth of the top element of by_depth. */
+ if (depth+1 < G.depth_in_use)
+ e = G.depth[depth+1];
+ else
+ e = G.by_depth_in_use;
+
+ /* We might not have any PTEs of depth depth. */
+ if (depth < G.depth_in_use)
+ {
+
+ /* First we go through all the pages at depth depth to
+ recalculate the in use bits. */
+ for (i = G.depth[depth]; i < e; ++i)
+ {
+ page_entry *p;
+
+#ifdef ENABLE_CHECKING
+ p = G.by_depth[i];
+
+ /* Check that all of the pages really are at the depth that
+ we expect. */
+ if (p->context_depth != depth)
+ abort ();
+ if (p->index_by_depth != i)
+ abort ();
+#endif
+
+ prefetch (&save_in_use_p_i (i+8));
+ prefetch (&save_in_use_p_i (i+16));
+ if (save_in_use_p_i (i))
+ {
+ p = G.by_depth[i];
+ ggc_recalculate_in_use_p (p);
+ free (save_in_use_p_i (i));
+ save_in_use_p_i (i) = 0;
+ }
+ }
+ }
- /* Any remaining pages in the popped context are lowered to the new
- current context; i.e. objects allocated in the popped context and
- left over are imported into the previous context. */
+ /* Then, we reset all page_entries with a depth greater than depth
+ to be at depth. */
+ for (i = e; i < G.by_depth_in_use; ++i)
+ {
+ page_entry *p = G.by_depth[i];
+
+ /* Check that all of the pages really are at the depth we
+ expect. */
+#ifdef ENABLE_CHECKING
+ if (p->context_depth <= depth)
+ abort ();
+ if (p->index_by_depth != i)
+ abort ();
+#endif
+ p->context_depth = depth;
+ }
+
+ adjust_depth ();
+
+#ifdef ENABLE_CHECKING
for (order = 2; order < NUM_ORDERS; order++)
{
page_entry *p;
@@ -1198,18 +1484,12 @@ ggc_pop_context ()
for (p = G.pages[order]; p != NULL; p = p->next)
{
if (p->context_depth > depth)
- p->context_depth = depth;
-
- /* If this page is now in the topmost context, and we'd
- saved its allocation state, restore it. */
- else if (p->context_depth == depth && p->save_in_use_p)
- {
- ggc_recalculate_in_use_p (p);
- free (p->save_in_use_p);
- p->save_in_use_p = 0;
- }
+ abort ();
+ else if (p->context_depth == depth && save_in_use_p (p))
+ abort ();
}
}
+#endif
}
/* Unmark all objects. */
@@ -1238,9 +1518,9 @@ clear_marks ()
marks. So, back them up first. */
if (p->context_depth < G.context_depth)
{
- if (! p->save_in_use_p)
- p->save_in_use_p = xmalloc (bitmap_size);
- memcpy (p->save_in_use_p, p->in_use_p, bitmap_size);
+ if (! save_in_use_p (p))
+ save_in_use_p (p) = xmalloc (bitmap_size);
+ memcpy (save_in_use_p (p), p->in_use_p, bitmap_size);
}
/* Reset reset the number of free objects and clear the
@@ -1249,7 +1529,7 @@ clear_marks ()
memset (p->in_use_p, 0, bitmap_size);
/* Make sure the one-past-the-end bit is always set. */
- p->in_use_p[num_objects / HOST_BITS_PER_LONG]
+ p->in_use_p[num_objects / HOST_BITS_PER_LONG]
= ((unsigned long) 1 << (num_objects % HOST_BITS_PER_LONG));
}
}
@@ -1273,7 +1553,7 @@ sweep_pages ()
size_t live_objects;
page_entry *p, *previous;
int done;
-
+
p = G.pages[order];
if (p == NULL)
continue;
@@ -1351,7 +1631,7 @@ sweep_pages ()
previous = p;
p = next;
- }
+ }
while (! done);
/* Now, restore the in_use_p vectors for any pages from contexts
@@ -1362,7 +1642,7 @@ sweep_pages ()
}
}
-#ifdef GGC_POISON
+#ifdef ENABLE_GC_CHECKING
/* Clobber all free objects. */
static inline void
@@ -1393,7 +1673,19 @@ poison_pages ()
word = i / HOST_BITS_PER_LONG;
bit = i % HOST_BITS_PER_LONG;
if (((p->in_use_p[word] >> bit) & 1) == 0)
- memset (p->page + i * size, 0xa5, size);
+ {
+ char *object = p->page + i * size;
+
+ /* Keep poison-by-write when we expect to use Valgrind,
+ so the exact same memory semantics is kept, in case
+ there are memory errors. We override this request
+ below. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_WRITABLE (object, size));
+ memset (object, 0xa5, size);
+
+ /* Drop the handle to avoid handle leak. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_NOACCESS (object, size));
+ }
}
}
}
@@ -1408,10 +1700,13 @@ ggc_collect ()
/* Avoid frequent unnecessary work by skipping collection if the
total allocations haven't expanded much since the last
collection. */
-#ifndef GGC_ALWAYS_COLLECT
- if (G.allocated < GGC_MIN_EXPAND_FOR_GC * G.allocated_last_gc)
+ float allocated_last_gc =
+ MAX (G.allocated_last_gc, (size_t)PARAM_VALUE (GGC_MIN_HEAPSIZE) * 1024);
+
+ float min_expand = allocated_last_gc * PARAM_VALUE (GGC_MIN_EXPAND) / 100;
+
+ if (G.allocated < allocated_last_gc + min_expand)
return;
-#endif
timevar_push (TV_GC);
if (!quiet_flag)
@@ -1421,22 +1716,23 @@ ggc_collect ()
sweep phase. */
G.allocated = 0;
- /* Release the pages we freed the last time we collected, but didn't
+ /* Release the pages we freed the last time we collected, but didn't
reuse in the interim. */
release_pages ();
+ /* Indicate that we've seen collections at this context depth. */
+ G.context_depth_collections = ((unsigned long)1 << (G.context_depth + 1)) - 1;
+
clear_marks ();
ggc_mark_roots ();
-
-#ifdef GGC_POISON
+
+#ifdef ENABLE_GC_CHECKING
poison_pages ();
#endif
sweep_pages ();
G.allocated_last_gc = G.allocated;
- if (G.allocated_last_gc < GGC_MIN_LAST_ALLOCATED)
- G.allocated_last_gc = GGC_MIN_LAST_ALLOCATED;
timevar_pop (TV_GC);
@@ -1461,7 +1757,7 @@ ggc_print_statistics ()
/* Clear the statistics. */
memset (&stats, 0, sizeof (stats));
-
+
/* Make sure collection will really occur. */
G.allocated_last_gc = 0;
@@ -1472,7 +1768,7 @@ ggc_print_statistics ()
there as part of the total allocated memory. */
release_pages ();
- /* Collect some information about the various sizes of
+ /* Collect some information about the various sizes of
allocation. */
fprintf (stderr, "\n%-5s %10s %10s %10s\n",
"Size", "Allocated", "Used", "Overhead");
@@ -1495,19 +1791,20 @@ ggc_print_statistics ()
for (p = G.pages[i]; p; p = p->next)
{
allocated += p->bytes;
- in_use +=
+ in_use +=
(OBJECTS_PER_PAGE (i) - p->num_free_objects) * OBJECT_SIZE (i);
overhead += (sizeof (page_entry) - sizeof (long)
+ BITMAP_SIZE (OBJECTS_PER_PAGE (i) + 1));
}
- fprintf (stderr, "%-5d %10ld%c %10ld%c %10ld%c\n", OBJECT_SIZE (i),
+ fprintf (stderr, "%-5lu %10lu%c %10lu%c %10lu%c\n",
+ (unsigned long) OBJECT_SIZE (i),
SCALE (allocated), LABEL (allocated),
SCALE (in_use), LABEL (in_use),
SCALE (overhead), LABEL (overhead));
total_overhead += overhead;
}
- fprintf (stderr, "%-5s %10ld%c %10ld%c %10ld%c\n", "Total",
+ fprintf (stderr, "%-5s %10lu%c %10lu%c %10lu%c\n", "Total",
SCALE (G.bytes_mapped), LABEL (G.bytes_mapped),
SCALE (G.allocated), LABEL(G.allocated),
SCALE (total_overhead), LABEL (total_overhead));
diff --git a/contrib/gcc/ggc-simple.c b/contrib/gcc/ggc-simple.c
index 81d2c36..30b8725 100644
--- a/contrib/gcc/ggc-simple.c
+++ b/contrib/gcc/ggc-simple.c
@@ -27,20 +27,16 @@
#include "varray.h"
#include "ggc.h"
#include "timevar.h"
+#include "params.h"
/* Debugging flags. */
/* Zap memory before freeing to catch dangling pointers. */
-#define GGC_POISON
+#undef GGC_POISON
/* Collect statistics on how bushy the search tree is. */
#undef GGC_BALANCE
-/* Perform collection every time ggc_collect is invoked. Otherwise,
- collection is performed only when a significant amount of memory
- has been allocated since the last collection. */
-#undef GGC_ALWAYS_COLLECT
-
/* Always verify that the to-be-marked memory is collectable. */
#undef GGC_ALWAYS_VERIFY
@@ -48,9 +44,6 @@
#define GGC_POISON
#define GGC_ALWAYS_VERIFY
#endif
-#ifdef ENABLE_GC_ALWAYS_COLLECT
-#define GGC_ALWAYS_COLLECT
-#endif
#ifndef HOST_BITS_PER_PTR
#define HOST_BITS_PER_PTR HOST_BITS_PER_LONG
@@ -115,16 +108,6 @@ static struct globals
int context;
} G;
-/* Skip garbage collection if the current allocation is not at least
- this factor times the allocation at the end of the last collection.
- In other words, total allocation must expand by (this factor minus
- one) before collection is performed. */
-#define GGC_MIN_EXPAND_FOR_GC (1.3)
-
-/* Bound `allocated_last_gc' to 4MB, to prevent the memory expansion
- test from triggering too often when the heap is small. */
-#define GGC_MIN_LAST_ALLOCATED (4 * 1024 * 1024)
-
/* Local function prototypes. */
static void tree_insert PARAMS ((struct ggc_mem *));
@@ -251,7 +234,7 @@ size_t
ggc_get_size (p)
const void *p;
{
- struct ggc_mem *x
+ struct ggc_mem *x
= (struct ggc_mem *) ((const char *)p - offsetof (struct ggc_mem, u));
return x->size;
}
@@ -324,10 +307,16 @@ sweep_objs (root)
void
ggc_collect ()
{
-#ifndef GGC_ALWAYS_COLLECT
- if (G.allocated < GGC_MIN_EXPAND_FOR_GC * G.allocated_last_gc)
+ /* Avoid frequent unnecessary work by skipping collection if the
+ total allocations haven't expanded much since the last
+ collection. */
+ size_t allocated_last_gc =
+ MAX (G.allocated_last_gc, (size_t)PARAM_VALUE (GGC_MIN_HEAPSIZE) * 1024);
+
+ size_t min_expand = allocated_last_gc * PARAM_VALUE (GGC_MIN_EXPAND) / 100;
+
+ if (G.allocated < allocated_last_gc + min_expand)
return;
-#endif
#ifdef GGC_BALANCE
debug_ggc_balance ();
@@ -345,8 +334,6 @@ ggc_collect ()
sweep_objs (&G.root);
G.allocated_last_gc = G.allocated;
- if (G.allocated_last_gc < GGC_MIN_LAST_ALLOCATED)
- G.allocated_last_gc = GGC_MIN_LAST_ALLOCATED;
timevar_pop (TV_GC);
@@ -360,10 +347,9 @@ ggc_collect ()
/* Called once to initialize the garbage collector. */
-void
+void
init_ggc ()
{
- G.allocated_last_gc = GGC_MIN_LAST_ALLOCATED;
}
/* Start a new GGC context. Memory allocated in previous contexts
@@ -383,7 +369,7 @@ ggc_push_context ()
/* Finish a GC context. Any uncollected memory in the new context
will be merged with the old context. */
-void
+void
ggc_pop_context ()
{
G.context--;
@@ -425,7 +411,7 @@ debug_ggc_tree (p, indent)
for (i = 0; i < indent; ++i)
putc (' ', stderr);
fprintf (stderr, "%lx %p\n", (unsigned long)PTR_KEY (p), p);
-
+
if (p->sub[1])
debug_ggc_tree (p->sub[1], indent + 1);
}
@@ -490,7 +476,7 @@ ggc_print_statistics ()
/* Clear the statistics. */
memset (&stats, 0, sizeof (stats));
-
+
/* Make sure collection will really occur. */
G.allocated_last_gc = 0;
diff --git a/contrib/gcc/ggc.h b/contrib/gcc/ggc.h
index ae021fc..69f2f62 100644
--- a/contrib/gcc/ggc.h
+++ b/contrib/gcc/ggc.h
@@ -1,5 +1,5 @@
/* Garbage collection for the GNU compiler.
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -19,105 +19,61 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
#include "varray.h"
+#include "gtype-desc.h"
/* Symbols are marked with `ggc' for `gcc gc' so as not to interfere with
an external gc library that might be linked in. */
-/* These structures are defined in various headers throughout the
- compiler. However, rather than force everyone who includes this
- header to include all the headers in which they are declared, we
- just forward-declare them here. */
-struct eh_status;
-struct emit_status;
-struct expr_status;
-struct hash_table;
-struct label_node;
-struct rtx_def;
-struct rtvec_def;
-struct stmt_status;
-union tree_node;
-struct varasm_status;
-
/* Constants for general use. */
extern const char empty_string[]; /* empty string */
extern const char digit_vector[]; /* "0" .. "9" */
#define digit_string(d) (digit_vector + ((d) * 2))
-/* Trees that have been marked, but whose children still need marking. */
-extern varray_type ggc_pending_trees;
-
-/* Manipulate global roots that are needed between calls to gc. */
+/* Manipulate global roots that are needed between calls to gc.
+ THIS ROUTINE IS OBSOLETE, do not use it for new code. */
extern void ggc_add_root PARAMS ((void *base, int nelt,
int size, void (*)(void *)));
-extern void ggc_add_rtx_root PARAMS ((struct rtx_def **, int nelt));
-extern void ggc_add_tree_root PARAMS ((union tree_node **,
- int nelt));
-extern void ggc_add_rtx_varray_root PARAMS ((struct varray_head_tag **,
- int nelt));
-extern void ggc_add_tree_varray_root PARAMS ((struct varray_head_tag **,
- int nelt));
-extern void ggc_add_tree_hash_table_root PARAMS ((struct hash_table **,
- int nelt));
-extern void ggc_del_root PARAMS ((void *base));
-
-/* Types used for mark test and marking functions, if specified, in call
- below. */
-typedef int (*ggc_htab_marked_p) PARAMS ((const void *));
-typedef void (*ggc_htab_mark) PARAMS ((const void *));
-
-/* Add a hash table to be scanned when all roots have been processed. We
- delete any entry in the table that has not been marked. The argument is
- really htab_t. */
-extern void ggc_add_deletable_htab PARAMS ((PTR, ggc_htab_marked_p,
- ggc_htab_mark));
-
-/* Mark nodes from the gc_add_root callback. These functions follow
- pointers to mark other objects too. */
-extern void ggc_mark_rtx_varray PARAMS ((struct varray_head_tag *));
-extern void ggc_mark_tree_varray PARAMS ((struct varray_head_tag *));
-extern void ggc_mark_tree_hash_table PARAMS ((struct hash_table *));
-extern void ggc_mark_roots PARAMS ((void));
-extern void ggc_mark_rtx_children PARAMS ((struct rtx_def *));
-extern void ggc_mark_rtvec_children PARAMS ((struct rtvec_def *));
+/* Structures for the easy way to mark roots.
+ In an array, terminated by having base == NULL.*/
+struct ggc_root_tab {
+ void *base;
+ size_t nelt;
+ size_t stride;
+ void (*cb) PARAMS ((void *));
+};
+#define LAST_GGC_ROOT_TAB { NULL, 0, 0, NULL }
+/* Pointers to arrays of ggc_root_tab, terminated by NULL. */
+extern const struct ggc_root_tab * const gt_ggc_rtab[];
+extern const struct ggc_root_tab * const gt_ggc_deletable_rtab[];
+
+/* Structure for hash table cache marking. */
+struct htab;
+struct ggc_cache_tab {
+ struct htab * *base;
+ size_t nelt;
+ size_t stride;
+ void (*cb) PARAMS ((void *));
+ int (*marked_p) PARAMS ((const void *));
+};
+#define LAST_GGC_CACHE_TAB { NULL, 0, 0, NULL, NULL }
+/* Pointers to arrays of ggc_cache_tab, terminated by NULL. */
+extern const struct ggc_cache_tab * const gt_ggc_cache_rtab[];
+
+extern void ggc_mark_roots PARAMS ((void));
/* If EXPR is not NULL and previously unmarked, mark it and evaluate
to true. Otherwise evaluate to false. */
#define ggc_test_and_set_mark(EXPR) \
- ((EXPR) != NULL && ! ggc_set_mark (EXPR))
+ ((EXPR) != NULL && ((void *) (EXPR)) != (void *) 1 && ! ggc_set_mark (EXPR))
-#define ggc_mark_rtx(EXPR) \
- do { \
- rtx r__ = (EXPR); \
- if (ggc_test_and_set_mark (r__)) \
- ggc_mark_rtx_children (r__); \
- } while (0)
-
-#define ggc_mark_tree(EXPR) \
- do { \
- tree t__ = (EXPR); \
- if (ggc_test_and_set_mark (t__)) \
- VARRAY_PUSH_TREE (ggc_pending_trees, t__); \
- } while (0)
-
-#define ggc_mark_nonnull_tree(EXPR) \
- do { \
- tree t__ = (EXPR); \
- if (! ggc_set_mark (t__)) \
- VARRAY_PUSH_TREE (ggc_pending_trees, t__); \
- } while (0)
-
-#define ggc_mark_rtvec(EXPR) \
- do { \
- rtvec v__ = (EXPR); \
- if (ggc_test_and_set_mark (v__)) \
- ggc_mark_rtvec_children (v__); \
- } while (0)
+#define ggc_mark_rtx gt_ggc_m_7rtx_def
+#define ggc_mark_tree gt_ggc_m_9tree_node
#define ggc_mark(EXPR) \
do { \
- const void *a__ = (EXPR); \
- if (a__ != NULL) \
+ const void *const a__ = (EXPR); \
+ if (a__ != NULL && a__ != (void *) 1) \
ggc_set_mark (a__); \
} while (0)
@@ -141,6 +97,10 @@ extern void ggc_pop_context PARAMS ((void));
extern void *ggc_alloc PARAMS ((size_t));
/* Like ggc_alloc, but allocates cleared memory. */
extern void *ggc_alloc_cleared PARAMS ((size_t));
+/* Resize a block. */
+extern void *ggc_realloc PARAMS ((void *, size_t));
+/* Like ggc_alloc_cleared, but performs a multiplication. */
+extern void *ggc_calloc PARAMS ((size_t, size_t));
#define ggc_alloc_rtx(NSLOTS) \
((struct rtx_def *) ggc_alloc (sizeof (struct rtx_def) \
@@ -152,6 +112,9 @@ extern void *ggc_alloc_cleared PARAMS ((size_t));
#define ggc_alloc_tree(LENGTH) ((union tree_node *) ggc_alloc (LENGTH))
+#define htab_create_ggc(SIZE, HASH, EQ, DEL) \
+ htab_create_alloc (SIZE, HASH, EQ, DEL, ggc_calloc, NULL)
+
/* Allocate a gc-able string, and fill it with LENGTH bytes from CONTENTS.
If LENGTH is -1, then CONTENTS is assumed to be a
null-terminated string and the memory sized accordingly. */
@@ -167,51 +130,30 @@ extern void ggc_collect PARAMS ((void));
/* Actually set the mark on a particular region of memory, but don't
follow pointers. This function is called by ggc_mark_*. It
- returns zero if the object was not previously marked; non-zero if
+ returns zero if the object was not previously marked; nonzero if
the object was already marked, or if, for any other reason,
pointers in this data structure should not be traversed. */
extern int ggc_set_mark PARAMS ((const void *));
-/* Return 1 if P has been marked, zero otherwise.
+/* Return 1 if P has been marked, zero otherwise.
P must have been allocated by the GC allocator; it mustn't point to
static objects, stack variables, or memory allocated with malloc. */
extern int ggc_marked_p PARAMS ((const void *));
-/* Callbacks to the languages. */
-
-/* This is the language's opportunity to mark nodes held through
- the lang_specific hooks in the tree. */
-extern void lang_mark_tree PARAMS ((union tree_node *));
-
-/* The FALSE_LABEL_STACK, declared in except.h, has language-dependent
- semantics. If a front-end needs to mark the false label stack, it
- should set this pointer to a non-NULL value. Otherwise, no marking
- will be done. */
-extern void (*lang_mark_false_label_stack) PARAMS ((struct label_node *));
-
-/* Mark functions for various structs scattered about. */
-
-void mark_eh_status PARAMS ((struct eh_status *));
-void mark_emit_status PARAMS ((struct emit_status *));
-void mark_expr_status PARAMS ((struct expr_status *));
-void mark_stmt_status PARAMS ((struct stmt_status *));
-void mark_varasm_status PARAMS ((struct varasm_status *));
-void mark_optab PARAMS ((void *));
-
/* Statistics. */
/* This structure contains the statistics common to all collectors.
Particular collectors can extend this structure. */
-typedef struct ggc_statistics
+typedef struct ggc_statistics
{
/* The Ith element is the number of nodes allocated with code I. */
unsigned num_trees[256];
- /* The Ith element is the number of bytes allocated by nodes with
+ /* The Ith element is the number of bytes allocated by nodes with
code I. */
size_t size_trees[256];
/* The Ith element is the number of nodes allocated with code I. */
unsigned num_rtxs[256];
- /* The Ith element is the number of bytes allocated by nodes with
+ /* The Ith element is the number of bytes allocated by nodes with
code I. */
size_t size_rtxs[256];
/* The total size of the tree nodes allocated. */
@@ -234,3 +176,8 @@ extern void ggc_print_common_statistics PARAMS ((FILE *, ggc_statistics *));
/* Print allocation statistics. */
extern void ggc_print_statistics PARAMS ((void));
extern void stringpool_statistics PARAMS ((void));
+
+/* Heuristics. */
+extern int ggc_min_expand_heuristic PARAMS ((void));
+extern int ggc_min_heapsize_heuristic PARAMS ((void));
+extern void init_ggc_heuristics PARAMS ((void));
diff --git a/contrib/gcc/ginclude/float.h b/contrib/gcc/ginclude/float.h
new file mode 100644
index 0000000..f501a8a
--- /dev/null
+++ b/contrib/gcc/ginclude/float.h
@@ -0,0 +1,162 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you include this header file into source
+ files compiled by GCC, this header file 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. */
+
+/*
+ * ISO C Standard: 5.2.4.2.2 Characteristics of floating types <float.h>
+ */
+
+#ifndef _FLOAT_H___
+#define _FLOAT_H___
+
+/* Radix of exponent representation, b. */
+#undef FLT_RADIX
+#define FLT_RADIX __FLT_RADIX__
+
+/* Number of base-FLT_RADIX digits in the significand, p. */
+#undef FLT_MANT_DIG
+#undef DBL_MANT_DIG
+#undef LDBL_MANT_DIG
+#define FLT_MANT_DIG __FLT_MANT_DIG__
+#define DBL_MANT_DIG __DBL_MANT_DIG__
+#define LDBL_MANT_DIG __LDBL_MANT_DIG__
+
+/* Number of decimal digits, q, such that any floating-point number with q
+ decimal digits can be rounded into a floating-point number with p radix b
+ digits and back again without change to the q decimal digits,
+
+ p * log10(b) if b is a power of 10
+ floor((p - 1) * log10(b)) otherwise
+*/
+#undef FLT_DIG
+#undef DBL_DIG
+#undef LDBL_DIG
+#define FLT_DIG __FLT_DIG__
+#define DBL_DIG __DBL_DIG__
+#define LDBL_DIG __LDBL_DIG__
+
+/* Minimum int x such that FLT_RADIX**(x-1) is a normalized float, emin */
+#undef FLT_MIN_EXP
+#undef DBL_MIN_EXP
+#undef LDBL_MIN_EXP
+#define FLT_MIN_EXP __FLT_MIN_EXP__
+#define DBL_MIN_EXP __DBL_MIN_EXP__
+#define LDBL_MIN_EXP __LDBL_MIN_EXP__
+
+/* Minimum negative integer such that 10 raised to that power is in the
+ range of normalized floating-point numbers,
+
+ ceil(log10(b) * (emin - 1))
+*/
+#undef FLT_MIN_10_EXP
+#undef DBL_MIN_10_EXP
+#undef LDBL_MIN_10_EXP
+#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__
+#define DBL_MIN_10_EXP __DBL_MIN_10_EXP__
+#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__
+
+/* Maximum int x such that FLT_RADIX**(x-1) is a representable float, emax. */
+#undef FLT_MAX_EXP
+#undef DBL_MAX_EXP
+#undef LDBL_MAX_EXP
+#define FLT_MAX_EXP __FLT_MAX_EXP__
+#define DBL_MAX_EXP __DBL_MAX_EXP__
+#define LDBL_MAX_EXP __LDBL_MAX_EXP__
+
+/* Maximum integer such that 10 raised to that power is in the range of
+ representable finite floating-point numbers,
+
+ floor(log10((1 - b**-p) * b**emax))
+*/
+#undef FLT_MAX_10_EXP
+#undef DBL_MAX_10_EXP
+#undef LDBL_MAX_10_EXP
+#define FLT_MAX_10_EXP __FLT_MAX_10_EXP__
+#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__
+#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__
+
+/* Maximum representable finite floating-point number,
+
+ (1 - b**-p) * b**emax
+*/
+#undef FLT_MAX
+#undef DBL_MAX
+#undef LDBL_MAX
+#define FLT_MAX __FLT_MAX__
+#define DBL_MAX __DBL_MAX__
+#define LDBL_MAX __LDBL_MAX__
+
+/* The difference between 1 and the least value greater than 1 that is
+ representable in the given floating point type, b**1-p. */
+#undef FLT_EPSILON
+#undef DBL_EPSILON
+#undef LDBL_EPSILON
+#define FLT_EPSILON __FLT_EPSILON__
+#define DBL_EPSILON __DBL_EPSILON__
+#define LDBL_EPSILON __LDBL_EPSILON__
+
+/* Minimum normalized positive floating-point number, b**(emin - 1). */
+#undef FLT_MIN
+#undef DBL_MIN
+#undef LDBL_MIN
+#define FLT_MIN __FLT_MIN__
+#define DBL_MIN __DBL_MIN__
+#define LDBL_MIN __LDBL_MIN__
+
+/* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown. */
+/* ??? This is supposed to change with calls to fesetround in <fenv.h>. */
+#undef FLT_ROUNDS
+#define FLT_ROUNDS 1
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+/* The floating-point expression evaluation method.
+ -1 indeterminate
+ 0 evaluate all operations and constants just to the range and
+ precision of the type
+ 1 evaluate operations and constants of type float and double
+ to the range and precision of the double type, evaluate
+ long double operations and constants to the range and
+ precision of the long double type
+ 2 evaluate all operations and constants to the range and
+ precision of the long double type
+
+ ??? This ought to change with the setting of the fp control word;
+ the value provided by the compiler assumes the widest setting. */
+#undef FLT_EVAL_METHOD
+#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+
+/* Number of decimal digits, n, such that any floating-point number in the
+ widest supported floating type with pmax radix b digits can be rounded
+ to a floating-point number with n decimal digits and back again without
+ change to the value,
+
+ pmax * log10(b) if b is a power of 10
+ ceil(1 + pmax * log10(b)) otherwise
+*/
+#undef DECIMAL_DIG
+#define DECIMAL_DIG __DECIMAL_DIG__
+
+#endif /* C99 */
+#endif /* _FLOAT_H___ */
diff --git a/contrib/gcc/ginclude/stdarg.h b/contrib/gcc/ginclude/stdarg.h
index 9f6215d..e451c31 100644
--- a/contrib/gcc/ginclude/stdarg.h
+++ b/contrib/gcc/ginclude/stdarg.h
@@ -47,18 +47,13 @@ typedef __builtin_va_list __gnuc_va_list;
if this invocation was from the user program. */
#ifdef _STDARG_H
-/* Note that the type used in va_arg is supposed to match the
- actual type **after default promotions**.
- Thus, va_arg (..., short) is not valid. */
-
-#define va_start(v,l) __builtin_stdarg_start((v),l)
-#define va_end __builtin_va_end
-#define va_arg __builtin_va_arg
+#define va_start(v,l) __builtin_va_start(v,l)
+#define va_end(v) __builtin_va_end(v)
+#define va_arg(v,l) __builtin_va_arg(v,l)
#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L
-#define va_copy(d,s) __builtin_va_copy((d),(s))
+#define va_copy(d,s) __builtin_va_copy(d,s)
#endif
-#define __va_copy(d,s) __builtin_va_copy((d),(s))
-
+#define __va_copy(d,s) __builtin_va_copy(d,s)
/* Define va_list, if desired, from __gnuc_va_list. */
/* We deliberately do not define va_list when called from
diff --git a/contrib/gcc/ginclude/varargs.h b/contrib/gcc/ginclude/varargs.h
index 098094c..4b9803e 100644
--- a/contrib/gcc/ginclude/varargs.h
+++ b/contrib/gcc/ginclude/varargs.h
@@ -1,144 +1,7 @@
-/* Copyright (C) 1989, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* As a special exception, if you include this header file into source
- files compiled by GCC, this header file 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. */
-
#ifndef _VARARGS_H
#define _VARARGS_H
-#ifdef __NeXT__
-
-/* On Next, erase any vestiges of stdarg.h. */
-
-#ifdef _ANSI_STDARG_H_
-#define _VA_LIST_
-#endif
-#define _ANSI_STDARG_H_
-
-#undef va_alist
-#undef va_dcl
-#undef va_list
-#undef va_start
-#undef va_end
-#undef va_arg
-#endif /* __NeXT__ */
-
-/* These macros implement traditional (non-ANSI) varargs
- for GNU C. */
-
-#define va_alist __builtin_va_alist
-
-/* ??? We don't process attributes correctly in K&R argument context. */
-typedef int __builtin_va_alist_t __attribute__((__mode__(__word__)));
-
-/* ??? It would be nice to get rid of the ellipsis here. It causes
- current_function_varargs to be set in cc1. */
-#define va_dcl __builtin_va_alist_t __builtin_va_alist; ...
-
-/* Define __gnuc_va_list, just as in stdarg.h. */
-
-#ifndef __GNUC_VA_LIST
-#define __GNUC_VA_LIST
-typedef __builtin_va_list __gnuc_va_list;
-#endif
-
-#define va_start(v) __builtin_varargs_start((v))
-#define va_end __builtin_va_end
-#define va_arg __builtin_va_arg
-#define __va_copy(d,s) __builtin_va_copy((d),(s))
-
-/* Define va_list from __gnuc_va_list. */
+#error "GCC no longer implements <varargs.h>."
+#error "Revise your code to use <stdarg.h>."
-#ifdef _HIDDEN_VA_LIST /* On OSF1, this means varargs.h is "half-loaded". */
-#undef _VA_LIST
-#endif
-
-#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
- have no conflict with that. */
-#ifndef _VA_LIST_
-#define _VA_LIST_
-#ifdef __i860__
-#ifndef _VA_LIST
-#define _VA_LIST va_list
-#endif
-#endif /* __i860__ */
-typedef __gnuc_va_list va_list;
-#ifdef _SCO_DS
-#define __VA_LIST
-#endif
-#endif /* _VA_LIST_ */
-
-#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.
- (Note that the comments in NET 2's ansi.h
- are incorrect for _VA_LIST_--see stdio.h!) */
-/* Michael Eriksson <mer@sics.se> at Thu Sep 30 11:00:57 1993:
- Sequent defines _VA_LIST_ in <machine/machtypes.h> to be the type to
- use for va_list (``typedef _VA_LIST_ va_list'') */
-#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT)
-/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */
-#ifndef _VA_LIST_DEFINED
-/* The macro _VA_LIST is used in SCO Unix 3.2. */
-#ifndef _VA_LIST
-/* The macro _VA_LIST_T_H is used in the Bull dpx2 */
-#ifndef _VA_LIST_T_H
-/* The macro __va_list__ is used by BeOS. */
-#ifndef __va_list__
-typedef __gnuc_va_list va_list;
-#endif /* not __va_list__ */
-#endif /* not _VA_LIST_T_H */
-#endif /* not _VA_LIST */
-#endif /* not _VA_LIST_DEFINED */
-#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__))
-#define _VA_LIST_
-#endif
-#ifndef _VA_LIST
-#define _VA_LIST
#endif
-#ifndef _VA_LIST_DEFINED
-#define _VA_LIST_DEFINED
-#endif
-#ifndef _VA_LIST_T_H
-#define _VA_LIST_T_H
-#endif
-#ifndef __va_list__
-#define __va_list__
-#endif
-
-#endif /* not _VA_LIST_, except on certain systems */
-
-#endif /* not __svr4__ */
-
-/* The next BSD release (if there is one) wants this symbol to be
- undefined instead of _VA_LIST_. */
-#ifdef _BSD_VA_LIST
-#undef _BSD_VA_LIST
-#endif
-
-#endif /* _VARARGS_H */
diff --git a/contrib/gcc/glimits.h b/contrib/gcc/glimits.h
index c3b83da..710cbb5 100644
--- a/contrib/gcc/glimits.h
+++ b/contrib/gcc/glimits.h
@@ -3,7 +3,7 @@
/* Number of bits in a `char'. */
#undef CHAR_BIT
-#define CHAR_BIT 8
+#define CHAR_BIT __CHAR_BIT__
/* Maximum length of a multibyte character. */
#ifndef MB_LEN_MAX
@@ -12,102 +12,92 @@
/* Minimum and maximum values a `signed char' can hold. */
#undef SCHAR_MIN
-#define SCHAR_MIN (-128)
+#define SCHAR_MIN (-SCHAR_MAX - 1)
#undef SCHAR_MAX
-#define SCHAR_MAX 127
+#define SCHAR_MAX __SCHAR_MAX__
/* Maximum value an `unsigned char' can hold. (Minimum is 0). */
#undef UCHAR_MAX
-#define UCHAR_MAX 255
+#if __SCHAR_MAX__ == __INT_MAX__
+# define UCHAR_MAX (SCHAR_MAX * 2U + 1U)
+#else
+# define UCHAR_MAX (SCHAR_MAX * 2 + 1)
+#endif
/* Minimum and maximum values a `char' can hold. */
#ifdef __CHAR_UNSIGNED__
-#undef CHAR_MIN
-#define CHAR_MIN 0
-#undef CHAR_MAX
-#define CHAR_MAX 255
+# undef CHAR_MIN
+# if __SCHAR_MAX__ == __INT_MAX__
+# define CHAR_MIN 0U
+# else
+# define CHAR_MIN 0
+# endif
+# undef CHAR_MAX
+# define CHAR_MAX UCHAR_MAX
#else
-#undef CHAR_MIN
-#define CHAR_MIN (-128)
-#undef CHAR_MAX
-#define CHAR_MAX 127
-#endif
-
-#ifndef __SHRT_MAX__
-#define __SHRT_MAX__ 32767
+# undef CHAR_MIN
+# define CHAR_MIN SCHAR_MIN
+# undef CHAR_MAX
+# define CHAR_MAX SCHAR_MAX
#endif
/* Minimum and maximum values a `signed short int' can hold. */
#undef SHRT_MIN
-#define SHRT_MIN (-SHRT_MAX-1)
+#define SHRT_MIN (-SHRT_MAX - 1)
#undef SHRT_MAX
#define SHRT_MAX __SHRT_MAX__
-/* Minimum and maximum values a `signed int' can hold. */
-#ifndef __INT_MAX__
-#define __INT_MAX__ 2147483647
-#endif
-#undef INT_MIN
-#define INT_MIN (-INT_MAX-1)
-#undef INT_MAX
-#define INT_MAX __INT_MAX__
-
/* Maximum value an `unsigned short int' can hold. (Minimum is 0). */
#undef USHRT_MAX
#if __SHRT_MAX__ == __INT_MAX__
-#define USHRT_MAX (SHRT_MAX * 2U + 1U)
+# define USHRT_MAX (SHRT_MAX * 2U + 1U)
#else
-#define USHRT_MAX (SHRT_MAX * 2 + 1)
+# define USHRT_MAX (SHRT_MAX * 2 + 1)
#endif
+/* Minimum and maximum values a `signed int' can hold. */
+#undef INT_MIN
+#define INT_MIN (-INT_MAX - 1)
+#undef INT_MAX
+#define INT_MAX __INT_MAX__
+
/* Maximum value an `unsigned int' can hold. (Minimum is 0). */
#undef UINT_MAX
-#define UINT_MAX (INT_MAX * 2U + 1)
+#define UINT_MAX (INT_MAX * 2U + 1U)
/* Minimum and maximum values a `signed long int' can hold.
(Same as `int'). */
-#ifndef __LONG_MAX__
-#if defined (__alpha__) || (defined (__sparc__) && defined(__arch64__)) || defined (__sparcv9)
-#define __LONG_MAX__ 9223372036854775807L
-#else
-#define __LONG_MAX__ 2147483647L
-#endif /* __alpha__ || sparc64 */
-#endif
#undef LONG_MIN
-#define LONG_MIN (-LONG_MAX-1)
+#define LONG_MIN (-LONG_MAX - 1L)
#undef LONG_MAX
#define LONG_MAX __LONG_MAX__
/* Maximum value an `unsigned long int' can hold. (Minimum is 0). */
#undef ULONG_MAX
-#define ULONG_MAX (LONG_MAX * 2UL + 1)
-
-#ifndef __LONG_LONG_MAX__
-#define __LONG_LONG_MAX__ 9223372036854775807LL
-#endif
+#define ULONG_MAX (LONG_MAX * 2UL + 1UL)
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* Minimum and maximum values a `signed long long int' can hold. */
-#undef LLONG_MIN
-#define LLONG_MIN (-LLONG_MAX-1)
-#undef LLONG_MAX
-#define LLONG_MAX __LONG_LONG_MAX__
+# undef LLONG_MIN
+# define LLONG_MIN (-LLONG_MAX - 1LL)
+# undef LLONG_MAX
+# define LLONG_MAX __LONG_LONG_MAX__
/* Maximum value an `unsigned long long int' can hold. (Minimum is 0). */
-#undef ULLONG_MAX
-#define ULLONG_MAX (LLONG_MAX * 2ULL + 1)
+# undef ULLONG_MAX
+# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
#endif
#if defined (__GNU_LIBRARY__) ? defined (__USE_GNU) : !defined (__STRICT_ANSI__)
/* Minimum and maximum values a `signed long long int' can hold. */
-#undef LONG_LONG_MIN
-#define LONG_LONG_MIN (-LONG_LONG_MAX-1)
-#undef LONG_LONG_MAX
-#define LONG_LONG_MAX __LONG_LONG_MAX__
+# undef LONG_LONG_MIN
+# define LONG_LONG_MIN (-LONG_LONG_MAX - 1LL)
+# undef LONG_LONG_MAX
+# define LONG_LONG_MAX __LONG_LONG_MAX__
/* Maximum value an `unsigned long long int' can hold. (Minimum is 0). */
-#undef ULONG_LONG_MAX
-#define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1)
+# undef ULONG_LONG_MAX
+# define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1ULL)
#endif
#endif /* _LIMITS_H___ */
diff --git a/contrib/gcc/global.c b/contrib/gcc/global.c
index 383f6c4..0840b87 100644
--- a/contrib/gcc/global.c
+++ b/contrib/gcc/global.c
@@ -52,7 +52,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
1. Assign allocation-numbers (allocnos) to the pseudo-registers
still needing allocations and to the pseudo-registers currently
allocated by local-alloc which may be spilled by reload.
- Set up tables reg_allocno and allocno_reg to map
+ Set up tables reg_allocno and allocno_reg to map
reg numbers to allocnos and vice versa.
max_allocno gets the number of allocnos in use.
@@ -176,10 +176,6 @@ static int allocno_row_words;
(conflicts[(I) * allocno_row_words + (unsigned) (J) / INT_BITS] \
& ((INT_TYPE) 1 << ((unsigned) (J) % INT_BITS)))
-#define SET_CONFLICT(I, J) \
- (conflicts[(I) * allocno_row_words + (unsigned) (J) / INT_BITS] \
- |= ((INT_TYPE) 1 << ((unsigned) (J) % INT_BITS)))
-
/* For any allocno set in ALLOCNO_SET, set ALLOCNO to that allocno,
and execute CODE. */
#define EXECUTE_IF_SET_IN_ALLOCNO_SET(ALLOCNO_SET, ALLOCNO, CODE) \
@@ -236,12 +232,8 @@ static int local_reg_freq[FIRST_PSEUDO_REGISTER];
static int local_reg_live_length[FIRST_PSEUDO_REGISTER];
-/* Test a bit in TABLE, a vector of HARD_REG_SETs,
- for vector element I, and hard register number J. */
-
-#define REGBITP(TABLE, I, J) TEST_HARD_REG_BIT (allocno[I].TABLE, J)
-
-/* Set to 1 a bit in a vector of HARD_REG_SETs. Works like REGBITP. */
+/* Set to 1 a bit in a vector TABLE of HARD_REG_SETs, for vector
+ element I, and hard register number J. */
#define SET_REGBIT(TABLE, I, J) SET_HARD_REG_BIT (allocno[I].TABLE, J)
@@ -252,10 +244,6 @@ static INT_TYPE *allocnos_live;
/* Test, set or clear bit number I in allocnos_live,
a bit vector indexed by allocno. */
-#define ALLOCNO_LIVE_P(I) \
- (allocnos_live[(unsigned) (I) / INT_BITS] \
- & ((INT_TYPE) 1 << ((unsigned) (I) % INT_BITS)))
-
#define SET_ALLOCNO_LIVE(I) \
(allocnos_live[(unsigned) (I) / INT_BITS] \
|= ((INT_TYPE) 1 << ((unsigned) (I) % INT_BITS)))
@@ -384,8 +372,8 @@ global_alloc (file)
that need a register window. So prefer the ones that can be used in
a leaf function. */
{
- char *cheap_regs;
- char *leaf_regs = LEAF_REGISTERS;
+ const char *cheap_regs;
+ const char *const leaf_regs = LEAF_REGISTERS;
if (only_leaf_regs_used () && leaf_function_p ())
cheap_regs = leaf_regs;
@@ -488,7 +476,7 @@ global_alloc (file)
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (regs_ever_live[i])
local_reg_n_refs[i] = 0, local_reg_freq[i] = 0;
-
+
allocno_row_words = (max_allocno + INT_BITS - 1) / INT_BITS;
/* We used to use alloca here, but the size of what it would try to
@@ -554,7 +542,7 @@ global_alloc (file)
}
qsort (allocno_order, max_allocno, sizeof (int), allocno_compare);
-
+
prune_preferences ();
if (file)
@@ -641,7 +629,8 @@ allocno_compare (v1p, v2p)
static void
global_conflicts ()
{
- int b, i;
+ int i;
+ basic_block b;
rtx insn;
int *block_start_allocnos;
@@ -650,7 +639,7 @@ global_conflicts ()
block_start_allocnos = (int *) xmalloc (max_allocno * sizeof (int));
- for (b = 0; b < n_basic_blocks; b++)
+ FOR_EACH_BB (b)
{
memset ((char *) allocnos_live, 0, allocno_row_words * sizeof (INT_TYPE));
@@ -669,7 +658,7 @@ global_conflicts ()
are explicitly marked in basic_block_live_at_start. */
{
- regset old = BASIC_BLOCK (b)->global_live_at_start;
+ regset old = b->global_live_at_start;
int ax = 0;
REG_SET_TO_HARD_REG_SET (hard_regs_live, old);
@@ -718,23 +707,23 @@ global_conflicts ()
that is reached by an abnormal edge. */
edge e;
- for (e = BASIC_BLOCK (b)->pred; e ; e = e->pred_next)
+ for (e = b->pred; e ; e = e->pred_next)
if (e->flags & EDGE_ABNORMAL)
break;
if (e != NULL)
- {
- EXECUTE_IF_SET_IN_ALLOCNO_SET (allocnos_live, ax,
- {
- allocno[ax].no_stack_reg = 1;
- });
- for (ax = FIRST_STACK_REG; ax <= LAST_STACK_REG; ax++)
- record_one_conflict (ax);
- }
+ {
+ EXECUTE_IF_SET_IN_ALLOCNO_SET (allocnos_live, ax,
+ {
+ allocno[ax].no_stack_reg = 1;
+ });
+ for (ax = FIRST_STACK_REG; ax <= LAST_STACK_REG; ax++)
+ record_one_conflict (ax);
+ }
}
#endif
}
- insn = BLOCK_HEAD (b);
+ insn = b->head;
/* Scan the code of this basic block, noting which allocnos
and hard regs are born or die. When one is born,
@@ -834,7 +823,7 @@ global_conflicts ()
}
}
- if (insn == BLOCK_END (b))
+ if (insn == b->end)
break;
insn = NEXT_INSN (insn);
}
@@ -894,18 +883,18 @@ expand_preferences ()
/* Prune the preferences for global registers to exclude registers that cannot
be used.
-
+
Compute `regs_someone_prefers', which is a bitmask of the hard registers
that are preferred by conflicting registers of lower priority. If possible,
we will avoid using these registers. */
-
+
static void
prune_preferences ()
{
int i;
int num;
int *allocno_to_order = (int *) xmalloc (max_allocno * sizeof (int));
-
+
/* Scan least most important to most important.
For each allocno, remove from preferences registers that cannot be used,
either because of conflicts or register type. Then compute all registers
@@ -973,7 +962,7 @@ prune_preferences ()
of a long enough stretch of hard regs none of which conflicts with ALLOCNO.
The registers marked in PREFREGS are tried first.
- LOSERS, if non-zero, is a HARD_REG_SET indicating registers that cannot
+ LOSERS, if nonzero, is a HARD_REG_SET indicating registers that cannot
be used for this allocation.
If ALT_REGS_P is zero, consider only the preferred class of ALLOCNO's reg.
@@ -996,10 +985,7 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
int retrying;
{
int i, best_reg, pass;
-#ifdef HARD_REG_SET
- register /* Declare it register if it's a scalar. */
-#endif
- HARD_REG_SET used, used1, used2;
+ HARD_REG_SET used, used1, used2;
enum reg_class class = (alt_regs_p
? reg_alternate_class (allocno[num].reg)
@@ -1023,10 +1009,8 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
IOR_HARD_REG_SET (used1, allocno[num].hard_reg_conflicts);
-#ifdef CLASS_CANNOT_CHANGE_MODE
- if (REG_CHANGES_MODE (allocno[num].reg))
- IOR_HARD_REG_SET (used1,
- reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]);
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ cannot_change_mode_set_regs (&used1, mode, allocno[num].reg);
#endif
/* Try each hard reg to see if it fits. Do this in two passes.
@@ -1038,7 +1022,7 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
COPY_HARD_REG_SET (used, used1);
IOR_COMPL_HARD_REG_SET (used, regs_used_so_far);
IOR_HARD_REG_SET (used, allocno[num].regs_someone_prefers);
-
+
best_reg = -1;
for (i = FIRST_PSEUDO_REGISTER, pass = 0;
pass <= 1 && i >= FIRST_PSEUDO_REGISTER;
@@ -1083,7 +1067,7 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
Remove from the preferred registers and conflicting registers. Note that
additional conflicts may have been added after `prune_preferences' was
- called.
+ called.
First do this for those register with copy preferences, then all
preferred registers. */
@@ -1166,7 +1150,7 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
}
no_prefs:
- /* If we haven't succeeded yet, try with caller-saves.
+ /* If we haven't succeeded yet, try with caller-saves.
We need not check to see if the current function has nonlocal
labels because we don't put any pseudos that are live over calls in
registers in that case. */
@@ -1186,7 +1170,7 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
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 (num, new_losers, alt_regs_p, 1, retrying);
if (reg_renumber[allocno[num].reg] >= 0)
@@ -1219,25 +1203,28 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
/* Don't use a reg no good for this pseudo. */
&& ! TEST_HARD_REG_BIT (used2, regno)
&& HARD_REGNO_MODE_OK (regno, mode)
+ /* The code below assumes that we need only a single
+ register, but the check of allocno[num].size above
+ was not enough. Sometimes we need more than one
+ register for a single-word value. */
+ && HARD_REGNO_NREGS (regno, mode) == 1
&& (allocno[num].calls_crossed == 0
|| accept_call_clobbered
|| ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
-#ifdef CLASS_CANNOT_CHANGE_MODE
- && ! (REG_CHANGES_MODE (allocno[num].reg)
- && (TEST_HARD_REG_BIT
- (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
- regno)))
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ && ! invalid_mode_change_p (regno, REGNO_REG_CLASS (regno),
+ mode)
#endif
#ifdef STACK_REGS
- && (!allocno[num].no_stack_reg
- || regno < FIRST_STACK_REG || regno > LAST_STACK_REG)
+ && (!allocno[num].no_stack_reg
+ || regno < FIRST_STACK_REG || regno > LAST_STACK_REG)
#endif
)
{
/* We explicitly evaluate the divide results into temporary
variables so as to avoid excess precision problems that occur
on an i386-unknown-sysv4.2 (unixware) host. */
-
+
double tmp1 = ((double) local_reg_freq[regno]
/ local_reg_live_length[regno]);
double tmp2 = ((double) allocno[num].freq
@@ -1607,7 +1594,7 @@ mark_reg_live_nc (regno, mode)
that SRC is a register. If SRC or the first operand of SRC is a register,
try to set a preference. If one of the two is a hard register and the other
is a pseudo-register, mark the preference.
-
+
Note that we are not as aggressive as local-alloc in trying to tie a
pseudo-register to a hard register. */
@@ -1723,11 +1710,11 @@ void
mark_elimination (from, to)
int from, to;
{
- int i;
+ basic_block bb;
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- regset r = BASIC_BLOCK (i)->global_live_at_start;
+ regset r = bb->global_live_at_start;
if (REGNO_REG_SET_P (r, from))
{
CLEAR_REGNO_REG_SET (r, from);
@@ -1755,7 +1742,7 @@ reg_becomes_live (reg, setter, regs_set)
if (GET_CODE (reg) != REG)
return;
-
+
regno = REGNO (reg);
if (regno < FIRST_PSEUDO_REGISTER)
{
@@ -1809,7 +1796,7 @@ build_insn_chain (first)
{
struct insn_chain **p = &reload_insn_chain;
struct insn_chain *prev = 0;
- int b = 0;
+ basic_block b = ENTRY_BLOCK_PTR->next_bb;
regset_head live_relevant_regs_head;
live_relevant_regs = INITIALIZE_REG_SET (live_relevant_regs_head);
@@ -1818,21 +1805,21 @@ build_insn_chain (first)
{
struct insn_chain *c;
- if (first == BLOCK_HEAD (b))
+ if (first == b->head)
{
int i;
CLEAR_REG_SET (live_relevant_regs);
EXECUTE_IF_SET_IN_BITMAP
- (BASIC_BLOCK (b)->global_live_at_start, 0, i,
+ (b->global_live_at_start, 0, i,
{
if (i < FIRST_PSEUDO_REGISTER
? ! TEST_HARD_REG_BIT (eliminable_regset, i)
: reg_renumber[i] >= 0)
SET_REGNO_REG_SET (live_relevant_regs, i);
});
- }
+ }
if (GET_CODE (first) != NOTE && GET_CODE (first) != BARRIER)
{
@@ -1842,7 +1829,7 @@ build_insn_chain (first)
*p = c;
p = &c->next;
c->insn = first;
- c->block = b;
+ c->block = b->index;
if (INSN_P (first))
{
@@ -1880,8 +1867,8 @@ build_insn_chain (first)
}
}
- if (first == BLOCK_END (b))
- b++;
+ if (first == b->end)
+ b = b->next_bb;
/* Stop after we pass the end of the last basic block. Verify that
no real insns are after the end of the last basic block.
@@ -1889,7 +1876,7 @@ build_insn_chain (first)
We may want to reorganize the loop somewhat since this test should
always be the right exit test. Allow an ADDR_VEC or ADDR_DIF_VEC if
the previous real insn is a JUMP_INSN. */
- if (b == n_basic_blocks)
+ if (b == EXIT_BLOCK_PTR)
{
for (first = NEXT_INSN (first) ; first; first = NEXT_INSN (first))
if (INSN_P (first)
@@ -1920,7 +1907,7 @@ dump_conflicts (file)
for (i = 0; i < max_allocno; i++)
{
if (reg_renumber[allocno[allocno_order[i]].reg] >= 0)
- continue;
+ continue;
nregs++;
}
fprintf (file, ";; %d regs to allocate:", nregs);
@@ -1972,13 +1959,13 @@ dump_global_regs (file)
FILE *file;
{
int i, j;
-
+
fprintf (file, ";; Register dispositions:\n");
for (i = FIRST_PSEUDO_REGISTER, j = 0; i < max_regno; i++)
if (reg_renumber[i] >= 0)
{
fprintf (file, "%d in %d ", i, reg_renumber[i]);
- if (++j % 6 == 0)
+ if (++j % 6 == 0)
fprintf (file, "\n");
}
diff --git a/contrib/gcc/graph.c b/contrib/gcc/graph.c
index 8723047..572c6b2 100644
--- a/contrib/gcc/graph.c
+++ b/contrib/gcc/graph.c
@@ -258,7 +258,6 @@ print_rtl_graph_with_bb (base, suffix, rtx_first)
fprintf (fp, "(nil)\n");
else
{
- int i;
enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
int max_uid = get_max_uid ();
int *start = (int *) xmalloc (max_uid * sizeof (int));
@@ -266,6 +265,7 @@ print_rtl_graph_with_bb (base, suffix, rtx_first)
enum bb_state *in_bb_p = (enum bb_state *)
xmalloc (max_uid * sizeof (enum bb_state));
basic_block bb;
+ int i;
for (i = 0; i < max_uid; ++i)
{
@@ -273,12 +273,11 @@ print_rtl_graph_with_bb (base, suffix, rtx_first)
in_bb_p[i] = NOT_IN_BB;
}
- for (i = n_basic_blocks - 1; i >= 0; --i)
+ FOR_EACH_BB_REVERSE (bb)
{
rtx x;
- bb = BASIC_BLOCK (i);
- start[INSN_UID (bb->head)] = i;
- end[INSN_UID (bb->end)] = i;
+ start[INSN_UID (bb->head)] = bb->index;
+ end[INSN_UID (bb->end)] = bb->index;
for (x = bb->head; x != NULL_RTX; x = NEXT_INSN (x))
{
in_bb_p[INSN_UID (x)]
diff --git a/contrib/gcc/graph.h b/contrib/gcc/graph.h
index 9df4555..1033df3 100644
--- a/contrib/gcc/graph.h
+++ b/contrib/gcc/graph.h
@@ -1,4 +1,4 @@
-/* Header file for graph routines.
+/* Header file for graph routines.
Copyright (C) 1999 Free Software Foundation, Inc.
This file is part of GCC.
diff --git a/contrib/gcc/gthr-dce.h b/contrib/gcc/gthr-dce.h
index 957f227..622e465 100644
--- a/contrib/gcc/gthr-dce.h
+++ b/contrib/gcc/gthr-dce.h
@@ -74,7 +74,7 @@ typedef pthread_mutex_t __gthread_mutex_t;
#pragma weak pthread_mutex_unlock
#ifdef _LIBOBJC
-/* Objective C. */
+/* Objective-C. */
#pragma weak pthread_cond_broadcast
#pragma weak pthread_cond_destroy
#pragma weak pthread_cond_init
@@ -116,7 +116,7 @@ static void *thread_local_storage = NULL;
/* Initialize the threads subsystem. */
static inline int
-__gthread_objc_init_thread_system(void)
+__gthread_objc_init_thread_system (void)
{
if (__gthread_active_p ())
/* Initialize the thread storage key */
@@ -127,7 +127,7 @@ __gthread_objc_init_thread_system(void)
/* Close the threads subsystem. */
static inline int
-__gthread_objc_close_thread_system(void)
+__gthread_objc_close_thread_system (void)
{
if (__gthread_active_p ())
return 0;
@@ -139,30 +139,30 @@ __gthread_objc_close_thread_system(void)
/* Create a new thread of execution. */
static inline objc_thread_t
-__gthread_objc_thread_detach(void (*func)(void *), void *arg)
+__gthread_objc_thread_detach (void (*func)(void *), void *arg)
{
objc_thread_t thread_id;
pthread_t new_thread_handle;
if (!__gthread_active_p ())
return NULL;
-
- if ( !(pthread_create(&new_thread_handle, pthread_attr_default,
- (void *)func, arg)) )
+
+ if (!(pthread_create (&new_thread_handle, pthread_attr_default,
+ (void *) func, arg)))
{
/* ??? May not work! (64bit) */
- thread_id = *(objc_thread_t *)&new_thread_handle;
- pthread_detach(&new_thread_handle); /* Fully detach thread. */
+ thread_id = *(objc_thread_t *) &new_thread_handle;
+ pthread_detach (&new_thread_handle); /* Fully detach thread. */
}
else
thread_id = NULL;
-
+
return thread_id;
}
/* Set the current thread's priority. */
static inline int
-__gthread_objc_thread_set_priority(int priority)
+__gthread_objc_thread_set_priority (int priority)
{
int sys_priority = 0;
@@ -182,9 +182,9 @@ __gthread_objc_thread_set_priority(int priority)
sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2;
break;
}
-
+
/* Change the priority. */
- if (pthread_setprio(pthread_self(), sys_priority) >= 0)
+ if (pthread_setprio (pthread_self (), sys_priority) >= 0)
return 0;
else
/* Failed */
@@ -193,14 +193,14 @@ __gthread_objc_thread_set_priority(int priority)
/* Return the current thread's priority. */
static inline int
-__gthread_objc_thread_get_priority(void)
+__gthread_objc_thread_get_priority (void)
{
int sys_priority;
if (__gthread_active_p ())
{
- if ((sys_priority = pthread_getprio(pthread_self())) >= 0)
- {
+ if ((sys_priority = pthread_getprio (pthread_self ())) >= 0)
+ {
if (sys_priority >= PRI_FG_MIN_NP
&& sys_priority <= PRI_FG_MAX_NP)
return OBJC_THREAD_INTERACTIVE_PRIORITY;
@@ -219,19 +219,19 @@ __gthread_objc_thread_get_priority(void)
/* Yield our process time to another thread. */
static inline void
-__gthread_objc_thread_yield(void)
+__gthread_objc_thread_yield (void)
{
if (__gthread_active_p ())
- pthread_yield();
+ pthread_yield ();
}
/* Terminate the current thread. */
static inline int
-__gthread_objc_thread_exit(void)
+__gthread_objc_thread_exit (void)
{
if (__gthread_active_p ())
/* exit the thread */
- pthread_exit(&__objc_thread_exit_status);
+ pthread_exit (&__objc_thread_exit_status);
/* Failed if we reached here */
return -1;
@@ -239,24 +239,24 @@ __gthread_objc_thread_exit(void)
/* Returns an integer value which uniquely describes a thread. */
static inline objc_thread_t
-__gthread_objc_thread_id(void)
+__gthread_objc_thread_id (void)
{
if (__gthread_active_p ())
{
- pthread_t self = pthread_self();
+ pthread_t self = pthread_self ();
return (objc_thread_t) pthread_getunique_np (&self);
}
else
- return (objc_thread_t)1;
+ return (objc_thread_t) 1;
}
/* Sets the thread's local storage pointer. */
static inline int
-__gthread_objc_thread_set_data(void *value)
+__gthread_objc_thread_set_data (void *value)
{
if (__gthread_active_p ())
- return pthread_setspecific(_objc_thread_storage, value);
+ return pthread_setspecific (_objc_thread_storage, value);
else
{
thread_local_storage = value;
@@ -266,13 +266,13 @@ __gthread_objc_thread_set_data(void *value)
/* Returns the thread's local storage pointer. */
static inline void *
-__gthread_objc_thread_get_data(void)
+__gthread_objc_thread_get_data (void)
{
void *value = NULL;
if (__gthread_active_p ())
{
- if ( !(pthread_getspecific(_objc_thread_storage, &value)) )
+ if (!(pthread_getspecific (_objc_thread_storage, &value)))
return value;
return NULL;
@@ -285,19 +285,19 @@ __gthread_objc_thread_get_data(void)
/* Allocate a mutex. */
static inline int
-__gthread_objc_mutex_allocate(objc_mutex_t mutex)
+__gthread_objc_mutex_allocate (objc_mutex_t mutex)
{
if (__gthread_active_p ())
{
- mutex->backend = objc_malloc(sizeof(pthread_mutex_t));
-
- if (pthread_mutex_init((pthread_mutex_t *)mutex->backend,
- pthread_mutexattr_default))
- {
- objc_free(mutex->backend);
- mutex->backend = NULL;
- return -1;
- }
+ mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
+
+ if (pthread_mutex_init ((pthread_mutex_t *) mutex->backend,
+ pthread_mutexattr_default))
+ {
+ objc_free (mutex->backend);
+ mutex->backend = NULL;
+ return -1;
+ }
}
return 0;
@@ -305,14 +305,14 @@ __gthread_objc_mutex_allocate(objc_mutex_t mutex)
/* Deallocate a mutex. */
static inline int
-__gthread_objc_mutex_deallocate(objc_mutex_t mutex)
+__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
{
if (__gthread_active_p ())
{
- if (pthread_mutex_destroy((pthread_mutex_t *)mutex->backend))
- return -1;
+ if (pthread_mutex_destroy ((pthread_mutex_t *) mutex->backend))
+ return -1;
- objc_free(mutex->backend);
+ objc_free (mutex->backend);
mutex->backend = NULL;
}
@@ -321,20 +321,20 @@ __gthread_objc_mutex_deallocate(objc_mutex_t mutex)
/* Grab a lock on a mutex. */
static inline int
-__gthread_objc_mutex_lock(objc_mutex_t mutex)
+__gthread_objc_mutex_lock (objc_mutex_t mutex)
{
if (__gthread_active_p ())
- return pthread_mutex_lock((pthread_mutex_t *)mutex->backend);
+ return pthread_mutex_lock ((pthread_mutex_t *) mutex->backend);
else
return 0;
}
/* Try to grab a lock on a mutex. */
static inline int
-__gthread_objc_mutex_trylock(objc_mutex_t mutex)
+__gthread_objc_mutex_trylock (objc_mutex_t mutex)
{
if (__gthread_active_p ()
- && pthread_mutex_trylock((pthread_mutex_t *)mutex->backend) != 1)
+ && pthread_mutex_trylock ((pthread_mutex_t *) mutex->backend) != 1)
return -1;
return 0;
@@ -342,10 +342,10 @@ __gthread_objc_mutex_trylock(objc_mutex_t mutex)
/* Unlock the mutex */
static inline int
-__gthread_objc_mutex_unlock(objc_mutex_t mutex)
+__gthread_objc_mutex_unlock (objc_mutex_t mutex)
{
if (__gthread_active_p ())
- return pthread_mutex_unlock((pthread_mutex_t *)mutex->backend);
+ return pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend);
else
return 0;
}
@@ -354,7 +354,7 @@ __gthread_objc_mutex_unlock(objc_mutex_t mutex)
/* Allocate a condition. */
static inline int
-__gthread_objc_condition_allocate(objc_condition_t condition)
+__gthread_objc_condition_allocate (objc_condition_t condition)
{
if (__gthread_active_p ())
/* Unimplemented. */
@@ -365,7 +365,7 @@ __gthread_objc_condition_allocate(objc_condition_t condition)
/* Deallocate a condition. */
static inline int
-__gthread_objc_condition_deallocate(objc_condition_t condition)
+__gthread_objc_condition_deallocate (objc_condition_t condition)
{
if (__gthread_active_p ())
/* Unimplemented. */
@@ -376,7 +376,7 @@ __gthread_objc_condition_deallocate(objc_condition_t condition)
/* Wait on the condition */
static inline int
-__gthread_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
+__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
{
if (__gthread_active_p ())
/* Unimplemented. */
@@ -387,7 +387,7 @@ __gthread_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
/* Wake up all threads waiting on this condition. */
static inline int
-__gthread_objc_condition_broadcast(objc_condition_t condition)
+__gthread_objc_condition_broadcast (objc_condition_t condition)
{
if (__gthread_active_p ())
/* Unimplemented. */
@@ -398,7 +398,7 @@ __gthread_objc_condition_broadcast(objc_condition_t condition)
/* Wake up one thread waiting on this condition. */
static inline int
-__gthread_objc_condition_signal(objc_condition_t condition)
+__gthread_objc_condition_signal (objc_condition_t condition)
{
if (__gthread_active_p ())
/* Unimplemented. */
diff --git a/contrib/gcc/gthr-posix.h b/contrib/gcc/gthr-posix.h
index 58bfcb3..9149e64 100644
--- a/contrib/gcc/gthr-posix.h
+++ b/contrib/gcc/gthr-posix.h
@@ -35,6 +35,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define __GTHREADS 1
#include <pthread.h>
+#include <unistd.h>
typedef pthread_key_t __gthread_key_t;
typedef pthread_once_t __gthread_once_t;
@@ -52,12 +53,12 @@ typedef pthread_mutex_t __gthread_mutex_t;
#pragma weak pthread_setspecific
#pragma weak pthread_create
-#pragma weak pthread_mutex_lock
-#pragma weak pthread_mutex_trylock
-#pragma weak pthread_mutex_unlock
+#pragma weak pthread_mutex_lock
+#pragma weak pthread_mutex_trylock
+#pragma weak pthread_mutex_unlock
#ifdef _LIBOBJC
-/* Objective C. */
+/* Objective-C. */
#pragma weak pthread_cond_broadcast
#pragma weak pthread_cond_destroy
#pragma weak pthread_cond_init
@@ -67,15 +68,21 @@ typedef pthread_mutex_t __gthread_mutex_t;
#pragma weak pthread_mutex_init
#pragma weak pthread_mutex_destroy
#pragma weak pthread_self
+/* These really should be protected by _POSIX_PRIORITY_SCHEDULING, but
+ we use them inside a _POSIX_THREAD_PRIORITY_SCHEDULING block. */
+#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
#pragma weak sched_get_priority_max
#pragma weak sched_get_priority_min
+#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
#pragma weak sched_yield
#pragma weak pthread_attr_destroy
#pragma weak pthread_attr_init
#pragma weak pthread_attr_setdetachstate
+#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
#pragma weak pthread_getschedparam
#pragma weak pthread_setschedparam
-#endif
+#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
+#endif /* _LIBOBJC */
static inline int
__gthread_active_p (void)
@@ -114,21 +121,21 @@ static void *thread_local_storage = NULL;
/* Initialize the threads subsystem. */
static inline int
-__gthread_objc_init_thread_system(void)
+__gthread_objc_init_thread_system (void)
{
if (__gthread_active_p ())
{
/* Initialize the thread storage key */
- if (pthread_key_create(&_objc_thread_storage, NULL) == 0)
- {
- /* The normal default detach state for threads is
- * PTHREAD_CREATE_JOINABLE which causes threads to not die
- * when you think they should. */
- if (pthread_attr_init(&_objc_thread_attribs) == 0
- && pthread_attr_setdetachstate(&_objc_thread_attribs,
- PTHREAD_CREATE_DETACHED) == 0)
- return 0;
- }
+ if (pthread_key_create (&_objc_thread_storage, NULL) == 0)
+ {
+ /* The normal default detach state for threads is
+ * PTHREAD_CREATE_JOINABLE which causes threads to not die
+ * when you think they should. */
+ if (pthread_attr_init (&_objc_thread_attribs) == 0
+ && pthread_attr_setdetachstate (&_objc_thread_attribs,
+ PTHREAD_CREATE_DETACHED) == 0)
+ return 0;
+ }
}
return -1;
@@ -136,11 +143,11 @@ __gthread_objc_init_thread_system(void)
/* Close the threads subsystem. */
static inline int
-__gthread_objc_close_thread_system(void)
+__gthread_objc_close_thread_system (void)
{
if (__gthread_active_p ()
- && pthread_key_delete(_objc_thread_storage) == 0
- && pthread_attr_destroy(&_objc_thread_attribs) == 0)
+ && pthread_key_delete (_objc_thread_storage) == 0
+ && pthread_attr_destroy (&_objc_thread_attribs) == 0)
return 0;
return -1;
@@ -150,93 +157,98 @@ __gthread_objc_close_thread_system(void)
/* Create a new thread of execution. */
static inline objc_thread_t
-__gthread_objc_thread_detach(void (*func)(void *), void *arg)
+__gthread_objc_thread_detach (void (*func)(void *), void *arg)
{
objc_thread_t thread_id;
pthread_t new_thread_handle;
if (!__gthread_active_p ())
return NULL;
-
- if ( !(pthread_create(&new_thread_handle, NULL, (void *)func, arg)) )
+
+ if (!(pthread_create (&new_thread_handle, NULL, (void *) func, arg)))
thread_id = (objc_thread_t) new_thread_handle;
else
thread_id = NULL;
-
+
return thread_id;
}
/* Set the current thread's priority. */
static inline int
-__gthread_objc_thread_set_priority(int priority)
+__gthread_objc_thread_set_priority (int priority)
{
- if (!__gthread_active_p())
- return -1;
- else {
- pthread_t thread_id = pthread_self();
- int policy;
- struct sched_param params;
- int priority_min, priority_max;
-
- if (pthread_getschedparam(thread_id, &policy, &params) == 0)
- {
- if ((priority_max = sched_get_priority_max(policy)) != 0)
- return -1;
-
- if ((priority_min = sched_get_priority_min(policy)) != 0)
- return -1;
-
- if (priority > priority_max)
- priority = priority_max;
- else if (priority < priority_min)
- priority = priority_min;
- params.sched_priority = priority;
-
- /*
- * The solaris 7 and several other man pages incorrectly state that
- * this should be a pointer to policy but pthread.h is universally
- * at odds with this.
- */
- if (pthread_setschedparam(thread_id, policy, &params) == 0)
- return 0;
- }
+ if (!__gthread_active_p ())
return -1;
- }
+ else
+ {
+#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
+ pthread_t thread_id = pthread_self ();
+ int policy;
+ struct sched_param params;
+ int priority_min, priority_max;
+
+ if (pthread_getschedparam (thread_id, &policy, &params) == 0)
+ {
+ if ((priority_max = sched_get_priority_max (policy)) == -1)
+ return -1;
+
+ if ((priority_min = sched_get_priority_min (policy)) == -1)
+ return -1;
+
+ if (priority > priority_max)
+ priority = priority_max;
+ else if (priority < priority_min)
+ priority = priority_min;
+ params.sched_priority = priority;
+
+ /*
+ * The solaris 7 and several other man pages incorrectly state that
+ * this should be a pointer to policy but pthread.h is universally
+ * at odds with this.
+ */
+ if (pthread_setschedparam (thread_id, policy, &params) == 0)
+ return 0;
+ }
+#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
+ return -1;
+ }
}
/* Return the current thread's priority. */
static inline int
-__gthread_objc_thread_get_priority(void)
+__gthread_objc_thread_get_priority (void)
{
+#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
if (__gthread_active_p ())
{
int policy;
struct sched_param params;
- if (pthread_getschedparam(pthread_self(), &policy, &params) == 0)
- return params.sched_priority;
+ if (pthread_getschedparam (pthread_self (), &policy, &params) == 0)
+ return params.sched_priority;
else
- return -1;
+ return -1;
}
else
+#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
return OBJC_THREAD_INTERACTIVE_PRIORITY;
}
/* Yield our process time to another thread. */
static inline void
-__gthread_objc_thread_yield(void)
+__gthread_objc_thread_yield (void)
{
if (__gthread_active_p ())
- sched_yield();
+ sched_yield ();
}
/* Terminate the current thread. */
static inline int
-__gthread_objc_thread_exit(void)
+__gthread_objc_thread_exit (void)
{
if (__gthread_active_p ())
/* exit the thread */
- pthread_exit(&__objc_thread_exit_status);
+ pthread_exit (&__objc_thread_exit_status);
/* Failed if we reached here */
return -1;
@@ -244,20 +256,20 @@ __gthread_objc_thread_exit(void)
/* Returns an integer value which uniquely describes a thread. */
static inline objc_thread_t
-__gthread_objc_thread_id(void)
+__gthread_objc_thread_id (void)
{
if (__gthread_active_p ())
- return (objc_thread_t) pthread_self();
+ return (objc_thread_t) pthread_self ();
else
return (objc_thread_t) 1;
}
/* Sets the thread's local storage pointer. */
static inline int
-__gthread_objc_thread_set_data(void *value)
+__gthread_objc_thread_set_data (void *value)
{
if (__gthread_active_p ())
- return pthread_setspecific(_objc_thread_storage, value);
+ return pthread_setspecific (_objc_thread_storage, value);
else
{
thread_local_storage = value;
@@ -267,10 +279,10 @@ __gthread_objc_thread_set_data(void *value)
/* Returns the thread's local storage pointer. */
static inline void *
-__gthread_objc_thread_get_data(void)
+__gthread_objc_thread_get_data (void)
{
if (__gthread_active_p ())
- return pthread_getspecific(_objc_thread_storage);
+ return pthread_getspecific (_objc_thread_storage);
else
return thread_local_storage;
}
@@ -279,15 +291,15 @@ __gthread_objc_thread_get_data(void)
/* Allocate a mutex. */
static inline int
-__gthread_objc_mutex_allocate(objc_mutex_t mutex)
+__gthread_objc_mutex_allocate (objc_mutex_t mutex)
{
if (__gthread_active_p ())
{
- mutex->backend = objc_malloc(sizeof(pthread_mutex_t));
+ mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
- if (pthread_mutex_init((pthread_mutex_t *)mutex->backend, NULL))
+ if (pthread_mutex_init ((pthread_mutex_t *) mutex->backend, NULL))
{
- objc_free(mutex->backend);
+ objc_free (mutex->backend);
mutex->backend = NULL;
return -1;
}
@@ -298,7 +310,7 @@ __gthread_objc_mutex_allocate(objc_mutex_t mutex)
/* Deallocate a mutex. */
static inline int
-__gthread_objc_mutex_deallocate(objc_mutex_t mutex)
+__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
{
if (__gthread_active_p ())
{
@@ -311,16 +323,16 @@ __gthread_objc_mutex_deallocate(objc_mutex_t mutex)
do
{
- count = pthread_mutex_unlock((pthread_mutex_t *)mutex->backend);
+ count = pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend);
if (count < 0)
return -1;
}
while (count);
- if (pthread_mutex_destroy((pthread_mutex_t *)mutex->backend))
+ if (pthread_mutex_destroy ((pthread_mutex_t *) mutex->backend))
return -1;
- objc_free(mutex->backend);
+ objc_free (mutex->backend);
mutex->backend = NULL;
}
return 0;
@@ -328,10 +340,10 @@ __gthread_objc_mutex_deallocate(objc_mutex_t mutex)
/* Grab a lock on a mutex. */
static inline int
-__gthread_objc_mutex_lock(objc_mutex_t mutex)
+__gthread_objc_mutex_lock (objc_mutex_t mutex)
{
- if (__gthread_active_p ()
- && pthread_mutex_lock((pthread_mutex_t *)mutex->backend) != 0)
+ if (__gthread_active_p ()
+ && pthread_mutex_lock ((pthread_mutex_t *) mutex->backend) != 0)
{
return -1;
}
@@ -341,10 +353,10 @@ __gthread_objc_mutex_lock(objc_mutex_t mutex)
/* Try to grab a lock on a mutex. */
static inline int
-__gthread_objc_mutex_trylock(objc_mutex_t mutex)
+__gthread_objc_mutex_trylock (objc_mutex_t mutex)
{
- if (__gthread_active_p ()
- && pthread_mutex_trylock((pthread_mutex_t *)mutex->backend) != 0)
+ if (__gthread_active_p ()
+ && pthread_mutex_trylock ((pthread_mutex_t *) mutex->backend) != 0)
{
return -1;
}
@@ -354,10 +366,10 @@ __gthread_objc_mutex_trylock(objc_mutex_t mutex)
/* Unlock the mutex */
static inline int
-__gthread_objc_mutex_unlock(objc_mutex_t mutex)
+__gthread_objc_mutex_unlock (objc_mutex_t mutex)
{
- if (__gthread_active_p ()
- && pthread_mutex_unlock((pthread_mutex_t *)mutex->backend) != 0)
+ if (__gthread_active_p ()
+ && pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend) != 0)
{
return -1;
}
@@ -369,15 +381,15 @@ __gthread_objc_mutex_unlock(objc_mutex_t mutex)
/* Allocate a condition. */
static inline int
-__gthread_objc_condition_allocate(objc_condition_t condition)
+__gthread_objc_condition_allocate (objc_condition_t condition)
{
if (__gthread_active_p ())
{
- condition->backend = objc_malloc(sizeof(pthread_cond_t));
+ condition->backend = objc_malloc (sizeof (pthread_cond_t));
- if (pthread_cond_init((pthread_cond_t *)condition->backend, NULL))
+ if (pthread_cond_init ((pthread_cond_t *) condition->backend, NULL))
{
- objc_free(condition->backend);
+ objc_free (condition->backend);
condition->backend = NULL;
return -1;
}
@@ -388,14 +400,14 @@ __gthread_objc_condition_allocate(objc_condition_t condition)
/* Deallocate a condition. */
static inline int
-__gthread_objc_condition_deallocate(objc_condition_t condition)
+__gthread_objc_condition_deallocate (objc_condition_t condition)
{
if (__gthread_active_p ())
{
- if (pthread_cond_destroy((pthread_cond_t *)condition->backend))
+ if (pthread_cond_destroy ((pthread_cond_t *) condition->backend))
return -1;
- objc_free(condition->backend);
+ objc_free (condition->backend);
condition->backend = NULL;
}
return 0;
@@ -403,31 +415,31 @@ __gthread_objc_condition_deallocate(objc_condition_t condition)
/* Wait on the condition */
static inline int
-__gthread_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
+__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
{
if (__gthread_active_p ())
- return pthread_cond_wait((pthread_cond_t *)condition->backend,
- (pthread_mutex_t *)mutex->backend);
+ return pthread_cond_wait ((pthread_cond_t *) condition->backend,
+ (pthread_mutex_t *) mutex->backend);
else
return 0;
}
/* Wake up all threads waiting on this condition. */
static inline int
-__gthread_objc_condition_broadcast(objc_condition_t condition)
+__gthread_objc_condition_broadcast (objc_condition_t condition)
{
if (__gthread_active_p ())
- return pthread_cond_broadcast((pthread_cond_t *)condition->backend);
+ return pthread_cond_broadcast ((pthread_cond_t *) condition->backend);
else
return 0;
}
/* Wake up one thread waiting on this condition. */
static inline int
-__gthread_objc_condition_signal(objc_condition_t condition)
+__gthread_objc_condition_signal (objc_condition_t condition)
{
if (__gthread_active_p ())
- return pthread_cond_signal((pthread_cond_t *)condition->backend);
+ return pthread_cond_signal ((pthread_cond_t *) condition->backend);
else
return 0;
}
diff --git a/contrib/gcc/gthr-rtems.h b/contrib/gcc/gthr-rtems.h
index 3c6c0c5..8cb951e 100644
--- a/contrib/gcc/gthr-rtems.h
+++ b/contrib/gcc/gthr-rtems.h
@@ -46,7 +46,7 @@ typedef int __gthread_once_t;
typedef void *__gthread_mutex_t;
/*
- * External functions provided by RTEMS. They are very similar to their POSIX
+ * External functions provided by RTEMS. They are very similar to their POSIX
* counterparts. A "Wrapper API" is being use to avoid dependency on any RTEMS
* header files.
*/
diff --git a/contrib/gcc/gthr-single.h b/contrib/gcc/gthr-single.h
index 64ff354..0bb4682 100644
--- a/contrib/gcc/gthr-single.h
+++ b/contrib/gcc/gthr-single.h
@@ -50,7 +50,7 @@ static void *thread_local_storage = NULL;
/* Initialize the threads subsystem. */
static inline int
-__gthread_objc_init_thread_system(void)
+__gthread_objc_init_thread_system (void)
{
/* No thread support available */
return -1;
@@ -58,7 +58,7 @@ __gthread_objc_init_thread_system(void)
/* Close the threads subsystem. */
static inline int
-__gthread_objc_close_thread_system(void)
+__gthread_objc_close_thread_system (void)
{
/* No thread support available */
return -1;
@@ -68,7 +68,7 @@ __gthread_objc_close_thread_system(void)
/* Create a new thread of execution. */
static inline objc_thread_t
-__gthread_objc_thread_detach(void (* func)(void *), void * UNUSED(arg))
+__gthread_objc_thread_detach (void (* func)(void *), void * UNUSED(arg))
{
/* No thread support available */
return NULL;
@@ -76,7 +76,7 @@ __gthread_objc_thread_detach(void (* func)(void *), void * UNUSED(arg))
/* Set the current thread's priority. */
static inline int
-__gthread_objc_thread_set_priority(int UNUSED(priority))
+__gthread_objc_thread_set_priority (int UNUSED(priority))
{
/* No thread support available */
return -1;
@@ -84,39 +84,39 @@ __gthread_objc_thread_set_priority(int UNUSED(priority))
/* Return the current thread's priority. */
static inline int
-__gthread_objc_thread_get_priority(void)
+__gthread_objc_thread_get_priority (void)
{
return OBJC_THREAD_INTERACTIVE_PRIORITY;
}
/* Yield our process time to another thread. */
static inline void
-__gthread_objc_thread_yield(void)
+__gthread_objc_thread_yield (void)
{
return;
}
/* Terminate the current thread. */
static inline int
-__gthread_objc_thread_exit(void)
+__gthread_objc_thread_exit (void)
{
/* No thread support available */
/* Should we really exit the program */
- /* exit(&__objc_thread_exit_status); */
+ /* exit (&__objc_thread_exit_status); */
return -1;
}
/* Returns an integer value which uniquely describes a thread. */
static inline objc_thread_t
-__gthread_objc_thread_id(void)
+__gthread_objc_thread_id (void)
{
/* No thread support, use 1. */
- return (objc_thread_t)1;
+ return (objc_thread_t) 1;
}
/* Sets the thread's local storage pointer. */
static inline int
-__gthread_objc_thread_set_data(void *value)
+__gthread_objc_thread_set_data (void *value)
{
thread_local_storage = value;
return 0;
@@ -124,7 +124,7 @@ __gthread_objc_thread_set_data(void *value)
/* Returns the thread's local storage pointer. */
static inline void *
-__gthread_objc_thread_get_data(void)
+__gthread_objc_thread_get_data (void)
{
return thread_local_storage;
}
@@ -133,21 +133,21 @@ __gthread_objc_thread_get_data(void)
/* Allocate a mutex. */
static inline int
-__gthread_objc_mutex_allocate(objc_mutex_t UNUSED(mutex))
+__gthread_objc_mutex_allocate (objc_mutex_t UNUSED(mutex))
{
return 0;
}
/* Deallocate a mutex. */
static inline int
-__gthread_objc_mutex_deallocate(objc_mutex_t UNUSED(mutex))
+__gthread_objc_mutex_deallocate (objc_mutex_t UNUSED(mutex))
{
return 0;
}
/* Grab a lock on a mutex. */
static inline int
-__gthread_objc_mutex_lock(objc_mutex_t UNUSED(mutex))
+__gthread_objc_mutex_lock (objc_mutex_t UNUSED(mutex))
{
/* There can only be one thread, so we always get the lock */
return 0;
@@ -155,7 +155,7 @@ __gthread_objc_mutex_lock(objc_mutex_t UNUSED(mutex))
/* Try to grab a lock on a mutex. */
static inline int
-__gthread_objc_mutex_trylock(objc_mutex_t UNUSED(mutex))
+__gthread_objc_mutex_trylock (objc_mutex_t UNUSED(mutex))
{
/* There can only be one thread, so we always get the lock */
return 0;
@@ -163,7 +163,7 @@ __gthread_objc_mutex_trylock(objc_mutex_t UNUSED(mutex))
/* Unlock the mutex */
static inline int
-__gthread_objc_mutex_unlock(objc_mutex_t UNUSED(mutex))
+__gthread_objc_mutex_unlock (objc_mutex_t UNUSED(mutex))
{
return 0;
}
@@ -172,36 +172,36 @@ __gthread_objc_mutex_unlock(objc_mutex_t UNUSED(mutex))
/* Allocate a condition. */
static inline int
-__gthread_objc_condition_allocate(objc_condition_t UNUSED(condition))
+__gthread_objc_condition_allocate (objc_condition_t UNUSED(condition))
{
return 0;
}
/* Deallocate a condition. */
static inline int
-__gthread_objc_condition_deallocate(objc_condition_t UNUSED(condition))
+__gthread_objc_condition_deallocate (objc_condition_t UNUSED(condition))
{
return 0;
}
/* Wait on the condition */
static inline int
-__gthread_objc_condition_wait(objc_condition_t UNUSED(condition),
- objc_mutex_t UNUSED(mutex))
+__gthread_objc_condition_wait (objc_condition_t UNUSED(condition),
+ objc_mutex_t UNUSED(mutex))
{
return 0;
}
/* Wake up all threads waiting on this condition. */
static inline int
-__gthread_objc_condition_broadcast(objc_condition_t UNUSED(condition))
+__gthread_objc_condition_broadcast (objc_condition_t UNUSED(condition))
{
return 0;
}
/* Wake up one thread waiting on this condition. */
static inline int
-__gthread_objc_condition_signal(objc_condition_t UNUSED(condition))
+__gthread_objc_condition_signal (objc_condition_t UNUSED(condition))
{
return 0;
}
diff --git a/contrib/gcc/gthr-solaris.h b/contrib/gcc/gthr-solaris.h
index 6d7ff25..726223d 100644
--- a/contrib/gcc/gthr-solaris.h
+++ b/contrib/gcc/gthr-solaris.h
@@ -39,8 +39,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include <errno.h>
typedef thread_key_t __gthread_key_t;
-typedef struct
-{
+typedef struct {
mutex_t mutex;
int once;
} __gthread_once_t;
@@ -110,11 +109,11 @@ static void *thread_local_storage = NULL;
/* Initialize the threads subsystem. */
static inline int
-__gthread_objc_init_thread_system(void)
+__gthread_objc_init_thread_system (void)
{
/* Initialize the thread storage key */
if (__gthread_active_p ()
- && thr_keycreate(&_objc_thread_storage, NULL) == 0)
+ && thr_keycreate (&_objc_thread_storage, NULL) == 0)
return 0;
return -1;
@@ -122,7 +121,7 @@ __gthread_objc_init_thread_system(void)
/* Close the threads subsystem. */
static inline int
-__gthread_objc_close_thread_system(void)
+__gthread_objc_close_thread_system (void)
{
if (__gthread_active_p ())
return 0;
@@ -134,27 +133,27 @@ __gthread_objc_close_thread_system(void)
/* Create a new thread of execution. */
static inline objc_thread_t
-__gthread_objc_thread_detach(void (*func)(void *), void *arg)
+__gthread_objc_thread_detach (void (*func)(void *), void *arg)
{
objc_thread_t thread_id;
thread_t new_thread_id = 0;
if (!__gthread_active_p ())
return NULL;
-
- if (thr_create(NULL, 0, (void *)func, arg,
- THR_DETACHED | THR_NEW_LWP,
- &new_thread_id) == 0)
- thread_id = *(objc_thread_t *)&new_thread_id;
+
+ if (thr_create (NULL, 0, (void *) func, arg,
+ THR_DETACHED | THR_NEW_LWP,
+ &new_thread_id) == 0)
+ thread_id = *(objc_thread_t *) &new_thread_id;
else
thread_id = NULL;
-
+
return thread_id;
}
/* Set the current thread's priority. */
static inline int
-__gthread_objc_thread_set_priority(int priority)
+__gthread_objc_thread_set_priority (int priority)
{
int sys_priority = 0;
@@ -176,7 +175,7 @@ __gthread_objc_thread_set_priority(int priority)
}
/* Change priority */
- if (thr_setprio(thr_self(), sys_priority) == 0)
+ if (thr_setprio (thr_self (), sys_priority) == 0)
return 0;
else
return -1;
@@ -184,14 +183,14 @@ __gthread_objc_thread_set_priority(int priority)
/* Return the current thread's priority. */
static inline int
-__gthread_objc_thread_get_priority(void)
+__gthread_objc_thread_get_priority (void)
{
int sys_priority;
if (!__gthread_active_p ())
return OBJC_THREAD_INTERACTIVE_PRIORITY;
-
- if (thr_getprio(thr_self(), &sys_priority) == 0)
+
+ if (thr_getprio (thr_self (), &sys_priority) == 0)
{
if (sys_priority >= 250)
return OBJC_THREAD_INTERACTIVE_PRIORITY;
@@ -206,19 +205,19 @@ __gthread_objc_thread_get_priority(void)
/* Yield our process time to another thread. */
static inline void
-__gthread_objc_thread_yield(void)
+__gthread_objc_thread_yield (void)
{
if (__gthread_active_p ())
- thr_yield();
+ thr_yield ();
}
/* Terminate the current thread. */
static inline int
-__gthread_objc_thread_exit(void)
+__gthread_objc_thread_exit (void)
{
if (__gthread_active_p ())
/* exit the thread */
- thr_exit(&__objc_thread_exit_status);
+ thr_exit (&__objc_thread_exit_status);
/* Failed if we reached here */
return -1;
@@ -226,21 +225,21 @@ __gthread_objc_thread_exit(void)
/* Returns an integer value which uniquely describes a thread. */
static inline objc_thread_t
-__gthread_objc_thread_id(void)
+__gthread_objc_thread_id (void)
{
if (__gthread_active_p ())
- return (objc_thread_t)thr_self();
+ return (objc_thread_t) thr_self ();
else
- return (objc_thread_t)1;
+ return (objc_thread_t) 1;
}
/* Sets the thread's local storage pointer. */
static inline int
-__gthread_objc_thread_set_data(void *value)
+__gthread_objc_thread_set_data (void *value)
{
if (__gthread_active_p ())
{
- if (thr_setspecific(_objc_thread_storage, value) == 0)
+ if (thr_setspecific (_objc_thread_storage, value) == 0)
return 0;
else
return -1;
@@ -254,13 +253,13 @@ __gthread_objc_thread_set_data(void *value)
/* Returns the thread's local storage pointer. */
static inline void *
-__gthread_objc_thread_get_data(void)
+__gthread_objc_thread_get_data (void)
{
void *value = NULL;
if (__gthread_active_p ())
{
- if (thr_getspecific(_objc_thread_storage, &value) == 0)
+ if (thr_getspecific (_objc_thread_storage, &value) == 0)
return value;
else
return NULL;
@@ -273,10 +272,10 @@ __gthread_objc_thread_get_data(void)
/* Allocate a mutex. */
static inline int
-__gthread_objc_mutex_allocate(objc_mutex_t mutex)
+__gthread_objc_mutex_allocate (objc_mutex_t mutex)
{
if (__gthread_active_p ()
- && mutex_init( (mutex_t *)(&(mutex->backend)), USYNC_THREAD, 0))
+ && mutex_init ((mutex_t *) (&(mutex->backend)), USYNC_THREAD, 0))
return -1;
return 0;
@@ -284,20 +283,20 @@ __gthread_objc_mutex_allocate(objc_mutex_t mutex)
/* Deallocate a mutex. */
static inline int
-__gthread_objc_mutex_deallocate(objc_mutex_t mutex)
+__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
{
if (__gthread_active_p ())
- mutex_destroy((mutex_t *)(&(mutex->backend)));
+ mutex_destroy ((mutex_t *) (&(mutex->backend)));
return 0;
}
/* Grab a lock on a mutex. */
static inline int
-__gthread_objc_mutex_lock(objc_mutex_t mutex)
+__gthread_objc_mutex_lock (objc_mutex_t mutex)
{
if (__gthread_active_p ()
- && mutex_lock((mutex_t *)(&(mutex->backend))) != 0)
+ && mutex_lock ((mutex_t *) (&(mutex->backend))) != 0)
return -1;
return 0;
@@ -305,10 +304,10 @@ __gthread_objc_mutex_lock(objc_mutex_t mutex)
/* Try to grab a lock on a mutex. */
static inline int
-__gthread_objc_mutex_trylock(objc_mutex_t mutex)
+__gthread_objc_mutex_trylock (objc_mutex_t mutex)
{
if (__gthread_active_p ()
- && mutex_trylock((mutex_t *)(&(mutex->backend))) != 0)
+ && mutex_trylock ((mutex_t *) (&(mutex->backend))) != 0)
return -1;
return 0;
@@ -316,10 +315,10 @@ __gthread_objc_mutex_trylock(objc_mutex_t mutex)
/* Unlock the mutex */
static inline int
-__gthread_objc_mutex_unlock(objc_mutex_t mutex)
+__gthread_objc_mutex_unlock (objc_mutex_t mutex)
{
if (__gthread_active_p ()
- && mutex_unlock((mutex_t *)(&(mutex->backend))) != 0)
+ && mutex_unlock ((mutex_t *) (&(mutex->backend))) != 0)
return -1;
return 0;
@@ -329,52 +328,52 @@ __gthread_objc_mutex_unlock(objc_mutex_t mutex)
/* Allocate a condition. */
static inline int
-__gthread_objc_condition_allocate(objc_condition_t condition)
+__gthread_objc_condition_allocate (objc_condition_t condition)
{
if (__gthread_active_p ())
- return cond_init((cond_t *)(&(condition->backend)), USYNC_THREAD,
- NULL);
+ return cond_init ((cond_t *) (&(condition->backend)), USYNC_THREAD,
+ NULL);
else
return 0;
}
/* Deallocate a condition. */
static inline int
-__gthread_objc_condition_deallocate(objc_condition_t condition)
+__gthread_objc_condition_deallocate (objc_condition_t condition)
{
if (__gthread_active_p ())
- return cond_destroy((cond_t *)(&(condition->backend)));
+ return cond_destroy ((cond_t *) (&(condition->backend)));
else
return 0;
}
/* Wait on the condition */
static inline int
-__gthread_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
+__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
{
if (__gthread_active_p ())
- return cond_wait((cond_t *)(&(condition->backend)),
- (mutex_t *)(&(mutex->backend)));
+ return cond_wait ((cond_t *) (&(condition->backend)),
+ (mutex_t *) (&(mutex->backend)));
else
return 0;
}
/* Wake up all threads waiting on this condition. */
static inline int
-__gthread_objc_condition_broadcast(objc_condition_t condition)
+__gthread_objc_condition_broadcast (objc_condition_t condition)
{
if (__gthread_active_p ())
- return cond_broadcast((cond_t *)(&(condition->backend)));
+ return cond_broadcast ((cond_t *) (&(condition->backend)));
else
return 0;
}
/* Wake up one thread waiting on this condition. */
static inline int
-__gthread_objc_condition_signal(objc_condition_t condition)
+__gthread_objc_condition_signal (objc_condition_t condition)
{
if (__gthread_active_p ())
- return cond_signal((cond_t *)(&(condition->backend)));
+ return cond_signal ((cond_t *) (&(condition->backend)));
else
return 0;
}
@@ -398,7 +397,7 @@ __gthread_once (__gthread_once_t *once, void (*func) (void))
if (once->once == 0)
{
(*func) ();
- once->once ++;
+ once->once++;
}
mutex_unlock (&once->mutex);
}
diff --git a/contrib/gcc/gthr-vxworks.h b/contrib/gcc/gthr-vxworks.h
index 1474853..c85b5e5 100644
--- a/contrib/gcc/gthr-vxworks.h
+++ b/contrib/gcc/gthr-vxworks.h
@@ -39,7 +39,7 @@ static void *thread_local_storage = NULL;
/* Initialize the threads subsystem. */
int
-__gthread_objc_init_thread_system(void)
+__gthread_objc_init_thread_system (void)
{
/* No thread support available */
return -1;
@@ -47,7 +47,7 @@ __gthread_objc_init_thread_system(void)
/* Close the threads subsystem. */
int
-__gthread_objc_close_thread_system(void)
+__gthread_objc_close_thread_system (void)
{
/* No thread support available */
return -1;
@@ -57,7 +57,7 @@ __gthread_objc_close_thread_system(void)
/* Create a new thread of execution. */
objc_thread_t
-__gthread_objc_thread_detach(void (*func)(void *arg), void *arg)
+__gthread_objc_thread_detach (void (*func)(void *arg), void *arg)
{
/* No thread support available */
return NULL;
@@ -65,7 +65,7 @@ __gthread_objc_thread_detach(void (*func)(void *arg), void *arg)
/* Set the current thread's priority. */
int
-__gthread_objc_thread_set_priority(int priority)
+__gthread_objc_thread_set_priority (int priority)
{
/* No thread support available */
return -1;
@@ -73,39 +73,39 @@ __gthread_objc_thread_set_priority(int priority)
/* Return the current thread's priority. */
int
-__gthread_objc_thread_get_priority(void)
+__gthread_objc_thread_get_priority (void)
{
return OBJC_THREAD_INTERACTIVE_PRIORITY;
}
/* Yield our process time to another thread. */
void
-__gthread_objc_thread_yield(void)
+__gthread_objc_thread_yield (void)
{
return;
}
/* Terminate the current thread. */
int
-__gthread_objc_thread_exit(void)
+__gthread_objc_thread_exit (void)
{
/* No thread support available */
/* Should we really exit the program */
- /* exit(&__objc_thread_exit_status); */
+ /* exit (&__objc_thread_exit_status); */
return -1;
}
/* Returns an integer value which uniquely describes a thread. */
objc_thread_t
-__gthread_objc_thread_id(void)
+__gthread_objc_thread_id (void)
{
/* No thread support, use 1. */
- return (objc_thread_t)1;
+ return (objc_thread_t) 1;
}
/* Sets the thread's local storage pointer. */
int
-__gthread_objc_thread_set_data(void *value)
+__gthread_objc_thread_set_data (void *value)
{
thread_local_storage = value;
return 0;
@@ -113,7 +113,7 @@ __gthread_objc_thread_set_data(void *value)
/* Returns the thread's local storage pointer. */
void *
-__gthread_objc_thread_get_data(void)
+__gthread_objc_thread_get_data (void)
{
return thread_local_storage;
}
@@ -122,21 +122,21 @@ __gthread_objc_thread_get_data(void)
/* Allocate a mutex. */
int
-__gthread_objc_mutex_allocate(objc_mutex_t mutex)
+__gthread_objc_mutex_allocate (objc_mutex_t mutex)
{
return 0;
}
/* Deallocate a mutex. */
int
-__gthread_objc_mutex_deallocate(objc_mutex_t mutex)
+__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
{
return 0;
}
/* Grab a lock on a mutex. */
int
-__gthread_objc_mutex_lock(objc_mutex_t mutex)
+__gthread_objc_mutex_lock (objc_mutex_t mutex)
{
/* There can only be one thread, so we always get the lock */
return 0;
@@ -144,7 +144,7 @@ __gthread_objc_mutex_lock(objc_mutex_t mutex)
/* Try to grab a lock on a mutex. */
int
-__gthread_objc_mutex_trylock(objc_mutex_t mutex)
+__gthread_objc_mutex_trylock (objc_mutex_t mutex)
{
/* There can only be one thread, so we always get the lock */
return 0;
@@ -152,7 +152,7 @@ __gthread_objc_mutex_trylock(objc_mutex_t mutex)
/* Unlock the mutex */
int
-__gthread_objc_mutex_unlock(objc_mutex_t mutex)
+__gthread_objc_mutex_unlock (objc_mutex_t mutex)
{
return 0;
}
@@ -161,35 +161,35 @@ __gthread_objc_mutex_unlock(objc_mutex_t mutex)
/* Allocate a condition. */
int
-__gthread_objc_condition_allocate(objc_condition_t condition)
+__gthread_objc_condition_allocate (objc_condition_t condition)
{
return 0;
}
/* Deallocate a condition. */
int
-__gthread_objc_condition_deallocate(objc_condition_t condition)
+__gthread_objc_condition_deallocate (objc_condition_t condition)
{
return 0;
}
/* Wait on the condition */
int
-__gthread_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
+__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
{
return 0;
}
/* Wake up all threads waiting on this condition. */
int
-__gthread_objc_condition_broadcast(objc_condition_t condition)
+__gthread_objc_condition_broadcast (objc_condition_t condition)
{
return 0;
}
/* Wake up one thread waiting on this condition. */
int
-__gthread_objc_condition_signal(objc_condition_t condition)
+__gthread_objc_condition_signal (objc_condition_t condition)
{
return 0;
}
@@ -229,12 +229,12 @@ static void
__ehdtor (void *pTcb)
{
int tid = (int) pTcb;
- void *p = (void*)taskVarGet(tid, &eh_context_key);
- if (p != (void*)-1)
+ void *p = (void *) taskVarGet (tid, &eh_context_key);
+ if (p != (void *) -1)
{
if (p)
free (p);
- taskVarSet(tid, &eh_context_key, 0);
+ taskVarSet (tid, &eh_context_key, 0);
}
}
@@ -248,7 +248,7 @@ __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
/* Do this first so that the task variables are visible during the
running of the delete hook. */
- taskVarInit();
+ taskVarInit ();
/* We don't have a way to track dtor here, so instead, we
register a generic routine that can cleanup any task. */
@@ -277,9 +277,9 @@ __gthread_key_dtor (__gthread_key_t key, void *ptr)
#define __gthread_getspecific(key) \
((key == 0) \
? ((taskVarAdd (taskIdSelf (), &key) != OK) \
- ? (__terminate (), (void*)0) \
- : (void*)0) \
- : (void*)key)
+ ? (__terminate (), (void *) 0) \
+ : (void *) 0) \
+ : (void *) key)
#endif
static inline int
diff --git a/contrib/gcc/gthr-win32.h b/contrib/gcc/gthr-win32.h
index 97d5a82..38b8f04 100644
--- a/contrib/gcc/gthr-win32.h
+++ b/contrib/gcc/gthr-win32.h
@@ -31,12 +31,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define GCC_GTHR_WIN32_H
/* Windows32 threads specific definitions. The windows32 threading model
- does not map well into pthread-inspired gcc's threading model, and so
+ does not map well into pthread-inspired gcc's threading model, and so
there are caveats one needs to be aware of.
1. The destructor supplied to __gthread_key_create is ignored for
- generic x86-win32 ports. This will certainly cause memory leaks
- due to unreclaimed eh contexts (sizeof (eh_context) is at least
+ generic x86-win32 ports. This will certainly cause memory leaks
+ due to unreclaimed eh contexts (sizeof (eh_context) is at least
24 bytes for x86 currently).
This memory leak may be significant for long-running applications
@@ -47,18 +47,18 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
linked in if -mthreads option is specified, that runs the dtors in
the reverse order of registration when each thread exits. If
-mthreads option is not given, a stub is linked in instead of the
- DLL, which results in memory leak. Other x86-win32 ports can use
+ DLL, which results in memory leak. Other x86-win32 ports can use
the same technique of course to avoid the leak.
2. The error codes returned are non-POSIX like, and cast into ints.
- This may cause incorrect error return due to truncation values on
+ This may cause incorrect error return due to truncation values on
hw where sizeof (DWORD) > sizeof (int).
-
- 3. We might consider using Critical Sections instead of Windows32
- mutexes for better performance, but emulating __gthread_mutex_trylock
+
+ 3. We might consider using Critical Sections instead of Windows32
+ mutexes for better performance, but emulating __gthread_mutex_trylock
interface becomes more complicated (Win9x does not support
TryEnterCriticalSectioni, while NT does).
-
+
The basic framework should work well enough. In the long term, GCC
needs to use Structured Exception Handling on Windows32. */
@@ -72,25 +72,25 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#ifdef _LIBOBJC
/* This is necessary to prevent windef.h (included from windows.h) from
- defining it's own BOOL as a typedef. */
+ defining it's own BOOL as a typedef. */
#ifndef __OBJC__
#define __OBJC__
#endif
#include <windows.h>
-/* Now undef the windows BOOL. */
+/* Now undef the windows BOOL. */
#undef BOOL
/* Key structure for maintaining thread specific storage */
-static DWORD __gthread_objc_data_tls = (DWORD)-1;
+static DWORD __gthread_objc_data_tls = (DWORD) -1;
/* Backend initialization functions */
/* Initialize the threads subsystem. */
int
-__gthread_objc_init_thread_system(void)
+__gthread_objc_init_thread_system (void)
{
/* Initialize the thread storage key */
- if ((__gthread_objc_data_tls = TlsAlloc()) != (DWORD)-1)
+ if ((__gthread_objc_data_tls = TlsAlloc ()) != (DWORD) -1)
return 0;
else
return -1;
@@ -98,10 +98,10 @@ __gthread_objc_init_thread_system(void)
/* Close the threads subsystem. */
int
-__gthread_objc_close_thread_system(void)
+__gthread_objc_close_thread_system (void)
{
- if (__gthread_objc_data_tls != (DWORD)-1)
- TlsFree(__gthread_objc_data_tls);
+ if (__gthread_objc_data_tls != (DWORD) -1)
+ TlsFree (__gthread_objc_data_tls);
return 0;
}
@@ -109,21 +109,21 @@ __gthread_objc_close_thread_system(void)
/* Create a new thread of execution. */
objc_thread_t
-__gthread_objc_thread_detach(void (*func)(void *arg), void *arg)
+__gthread_objc_thread_detach (void (*func)(void *arg), void *arg)
{
DWORD thread_id = 0;
HANDLE win32_handle;
- if (!(win32_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func,
- arg, 0, &thread_id)))
+ if (!(win32_handle = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) func,
+ arg, 0, &thread_id)))
thread_id = 0;
-
- return (objc_thread_t)thread_id;
+
+ return (objc_thread_t) thread_id;
}
/* Set the current thread's priority. */
int
-__gthread_objc_thread_set_priority(int priority)
+__gthread_objc_thread_set_priority (int priority)
{
int sys_priority = 0;
@@ -142,7 +142,7 @@ __gthread_objc_thread_set_priority(int priority)
}
/* Change priority */
- if (SetThreadPriority(GetCurrentThread(), sys_priority))
+ if (SetThreadPriority (GetCurrentThread (), sys_priority))
return 0;
else
return -1;
@@ -150,12 +150,12 @@ __gthread_objc_thread_set_priority(int priority)
/* Return the current thread's priority. */
int
-__gthread_objc_thread_get_priority(void)
+__gthread_objc_thread_get_priority (void)
{
int sys_priority;
- sys_priority = GetThreadPriority(GetCurrentThread());
-
+ sys_priority = GetThreadPriority (GetCurrentThread ());
+
switch (sys_priority)
{
case THREAD_PRIORITY_HIGHEST:
@@ -167,7 +167,7 @@ __gthread_objc_thread_get_priority(void)
default:
case THREAD_PRIORITY_BELOW_NORMAL:
return OBJC_THREAD_BACKGROUND_PRIORITY;
-
+
case THREAD_PRIORITY_IDLE:
case THREAD_PRIORITY_LOWEST:
return OBJC_THREAD_LOW_PRIORITY;
@@ -179,17 +179,17 @@ __gthread_objc_thread_get_priority(void)
/* Yield our process time to another thread. */
void
-__gthread_objc_thread_yield(void)
+__gthread_objc_thread_yield (void)
{
- Sleep(0);
+ Sleep (0);
}
/* Terminate the current thread. */
int
-__gthread_objc_thread_exit(void)
+__gthread_objc_thread_exit (void)
{
/* exit the thread */
- ExitThread(__objc_thread_exit_status);
+ ExitThread (__objc_thread_exit_status);
/* Failed if we reached here */
return -1;
@@ -197,16 +197,16 @@ __gthread_objc_thread_exit(void)
/* Returns an integer value which uniquely describes a thread. */
objc_thread_t
-__gthread_objc_thread_id(void)
+__gthread_objc_thread_id (void)
{
- return (objc_thread_t)GetCurrentThreadId();
+ return (objc_thread_t) GetCurrentThreadId ();
}
/* Sets the thread's local storage pointer. */
int
-__gthread_objc_thread_set_data(void *value)
+__gthread_objc_thread_set_data (void *value)
{
- if (TlsSetValue(__gthread_objc_data_tls, value))
+ if (TlsSetValue (__gthread_objc_data_tls, value))
return 0;
else
return -1;
@@ -214,16 +214,16 @@ __gthread_objc_thread_set_data(void *value)
/* Returns the thread's local storage pointer. */
void *
-__gthread_objc_thread_get_data(void)
+__gthread_objc_thread_get_data (void)
{
DWORD lasterror;
void *ptr;
- lasterror = GetLastError();
+ lasterror = GetLastError ();
- ptr = TlsGetValue(__gthread_objc_data_tls); /* Return thread data. */
+ ptr = TlsGetValue (__gthread_objc_data_tls); /* Return thread data. */
- SetLastError( lasterror );
+ SetLastError (lasterror);
return ptr;
}
@@ -232,9 +232,9 @@ __gthread_objc_thread_get_data(void)
/* Allocate a mutex. */
int
-__gthread_objc_mutex_allocate(objc_mutex_t mutex)
+__gthread_objc_mutex_allocate (objc_mutex_t mutex)
{
- if ((mutex->backend = (void *)CreateMutex(NULL, 0, NULL)) == NULL)
+ if ((mutex->backend = (void *) CreateMutex (NULL, 0, NULL)) == NULL)
return -1;
else
return 0;
@@ -242,19 +242,19 @@ __gthread_objc_mutex_allocate(objc_mutex_t mutex)
/* Deallocate a mutex. */
int
-__gthread_objc_mutex_deallocate(objc_mutex_t mutex)
+__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
{
- CloseHandle((HANDLE)(mutex->backend));
+ CloseHandle ((HANDLE) (mutex->backend));
return 0;
}
/* Grab a lock on a mutex. */
int
-__gthread_objc_mutex_lock(objc_mutex_t mutex)
+__gthread_objc_mutex_lock (objc_mutex_t mutex)
{
int status;
- status = WaitForSingleObject((HANDLE)(mutex->backend), INFINITE);
+ status = WaitForSingleObject ((HANDLE) (mutex->backend), INFINITE);
if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED)
return -1;
else
@@ -263,11 +263,11 @@ __gthread_objc_mutex_lock(objc_mutex_t mutex)
/* Try to grab a lock on a mutex. */
int
-__gthread_objc_mutex_trylock(objc_mutex_t mutex)
+__gthread_objc_mutex_trylock (objc_mutex_t mutex)
{
int status;
- status = WaitForSingleObject((HANDLE)(mutex->backend), 0);
+ status = WaitForSingleObject ((HANDLE) (mutex->backend), 0);
if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED)
return -1;
else
@@ -276,9 +276,9 @@ __gthread_objc_mutex_trylock(objc_mutex_t mutex)
/* Unlock the mutex */
int
-__gthread_objc_mutex_unlock(objc_mutex_t mutex)
+__gthread_objc_mutex_unlock (objc_mutex_t mutex)
{
- if (ReleaseMutex((HANDLE)(mutex->backend)) == 0)
+ if (ReleaseMutex ((HANDLE) (mutex->backend)) == 0)
return -1;
else
return 0;
@@ -288,7 +288,7 @@ __gthread_objc_mutex_unlock(objc_mutex_t mutex)
/* Allocate a condition. */
int
-__gthread_objc_condition_allocate(objc_condition_t condition)
+__gthread_objc_condition_allocate (objc_condition_t condition)
{
/* Unimplemented. */
return -1;
@@ -296,7 +296,7 @@ __gthread_objc_condition_allocate(objc_condition_t condition)
/* Deallocate a condition. */
int
-__gthread_objc_condition_deallocate(objc_condition_t condition)
+__gthread_objc_condition_deallocate (objc_condition_t condition)
{
/* Unimplemented. */
return -1;
@@ -304,7 +304,7 @@ __gthread_objc_condition_deallocate(objc_condition_t condition)
/* Wait on the condition */
int
-__gthread_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
+__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
{
/* Unimplemented. */
return -1;
@@ -312,7 +312,7 @@ __gthread_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
/* Wake up all threads waiting on this condition. */
int
-__gthread_objc_condition_broadcast(objc_condition_t condition)
+__gthread_objc_condition_broadcast (objc_condition_t condition)
{
/* Unimplemented. */
return -1;
@@ -320,7 +320,7 @@ __gthread_objc_condition_broadcast(objc_condition_t condition)
/* Wake up one thread waiting on this condition. */
int
-__gthread_objc_condition_signal(objc_condition_t condition)
+__gthread_objc_condition_signal (objc_condition_t condition)
{
/* Unimplemented. */
return -1;
@@ -328,36 +328,32 @@ __gthread_objc_condition_signal(objc_condition_t condition)
#else /* _LIBOBJC */
-#include <windows.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
-typedef DWORD __gthread_key_t;
+typedef unsigned long __gthread_key_t;
typedef struct {
int done;
long started;
} __gthread_once_t;
-typedef HANDLE __gthread_mutex_t;
+typedef void* __gthread_mutex_t;
-#define __GTHREAD_ONCE_INIT {FALSE, -1}
+#define __GTHREAD_ONCE_INIT {0, -1}
#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
+#define __GTHREAD_MUTEX_INIT_DEFAULT 0
#if __MINGW32_MAJOR_VERSION >= 1 || \
(__MINGW32_MAJOR_VERSION == 0 && __MINGW32_MINOR_VERSION > 2)
#define MINGW32_SUPPORTS_MT_EH 1
-#ifdef __cplusplus
-extern "C" {
-#endif
-extern int __mingwthr_key_dtor (DWORD, void (*) (void *));
-#ifdef __cplusplus
-}
-#endif
-
-/* Mingw runtime >= v0.3 provides a magic variable that is set to non-zero
- if -mthreads option was specified, or 0 otherwise. This is to get around
+/* Mingw runtime >= v0.3 provides a magic variable that is set to nonzero
+ if -mthreads option was specified, or 0 otherwise. This is to get around
the lack of weak symbols in PE-COFF. */
extern int _CRT_MT;
-#endif
+extern int __mingwthr_key_dtor (unsigned long, void (*) (void *));
+#endif /* __MINGW32__ version */
static inline int
__gthread_active_p (void)
@@ -369,6 +365,100 @@ __gthread_active_p (void)
#endif
}
+#ifdef __GTHREAD_HIDE_WIN32API
+
+/* The implementations are in config/i386/gthr-win32.c in libgcc.a.
+ Only stubs are exposed to avoid polluting the C++ namespace with
+ windows api definitions. */
+
+extern int __gthr_win32_once (__gthread_once_t *, void (*) (void));
+extern int __gthr_win32_key_create (__gthread_key_t *, void (*) (void*));
+extern int __gthr_win32_key_delete (__gthread_key_t);
+extern void * __gthr_win32_getspecific (__gthread_key_t);
+extern int __gthr_win32_setspecific (__gthread_key_t, const void *);
+extern void __gthr_win32_mutex_init_function (__gthread_mutex_t *);
+extern int __gthr_win32_mutex_lock (__gthread_mutex_t *);
+extern int __gthr_win32_mutex_trylock (__gthread_mutex_t *);
+extern int __gthr_win32_mutex_unlock (__gthread_mutex_t *);
+
+static inline int
+__gthread_once (__gthread_once_t *once, void (*func) (void))
+{
+ if (__gthread_active_p ())
+ return __gthr_win32_once (once, func);
+ else
+ return -1;
+}
+
+static inline int
+__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
+{
+ return __gthr_win32_key_create (key, dtor);
+}
+
+static inline int
+__gthread_key_dtor (__gthread_key_t key, void *ptr)
+{
+ /* Nothing needed. */
+ return 0;
+}
+
+static inline int
+__gthread_key_delete (__gthread_key_t key)
+{
+ return __gthr_win32_key_delete (key);
+}
+
+static inline void *
+__gthread_getspecific (__gthread_key_t key)
+{
+ return __gthr_win32_getspecific (key);
+}
+
+static inline int
+__gthread_setspecific (__gthread_key_t key, const void *ptr)
+{
+ return __gthr_win32_setspecific (key, ptr);
+}
+
+static inline void
+__gthread_mutex_init_function (__gthread_mutex_t *mutex)
+{
+ __gthr_win32_mutex_init_function (mutex);
+}
+
+static inline int
+__gthread_mutex_lock (__gthread_mutex_t *mutex)
+{
+ if (__gthread_active_p ())
+ return __gthr_win32_mutex_lock (mutex);
+ else
+ return 0;
+}
+
+static inline int
+__gthread_mutex_trylock (__gthread_mutex_t *mutex)
+{
+ if (__gthread_active_p ())
+ return __gthr_win32_mutex_trylock (mutex);
+ else
+ return 0;
+}
+
+static inline int
+__gthread_mutex_unlock (__gthread_mutex_t *mutex)
+{
+ if (__gthread_active_p ())
+ return __gthr_win32_mutex_unlock (mutex);
+ else
+ return 0;
+}
+
+#else /* ! __GTHREAD_HIDE_WIN32API */
+
+#include <windows.h>
+#include <errno.h>
+
static inline int
__gthread_once (__gthread_once_t *once, void (*func) (void))
{
@@ -380,27 +470,27 @@ __gthread_once (__gthread_once_t *once, void (*func) (void))
if (! once->done)
{
if (InterlockedIncrement (&(once->started)) == 0)
- {
+ {
(*func) ();
once->done = TRUE;
}
else
{
- /* Another thread is currently executing the code, so wait for it
- to finish; yield the CPU in the meantime. If performance
- does become an issue, the solution is to use an Event that
- we wait on here (and set above), but that implies a place to
- create the event before this routine is called. */
+ /* Another thread is currently executing the code, so wait for it
+ to finish; yield the CPU in the meantime. If performance
+ does become an issue, the solution is to use an Event that
+ we wait on here (and set above), but that implies a place to
+ create the event before this routine is called. */
while (! once->done)
Sleep (0);
}
}
-
+
return 0;
}
/* Windows32 thread local keys don't support destructors; this leads to
- leaks, especially in threaded applications making extensive use of
+ leaks, especially in threaded applications making extensive use of
C++ EH. Mingw uses a thread-support DLL to work-around this problem. */
static inline int
__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
@@ -422,7 +512,7 @@ __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
}
/* Currently, this routine is called only for Mingw runtime, and if
- -mthreads option is chosen to link in the thread support DLL. */
+ -mthreads option is chosen to link in the thread support DLL. */
static inline int
__gthread_key_dtor (__gthread_key_t key, void *ptr)
{
@@ -442,11 +532,11 @@ __gthread_getspecific (__gthread_key_t key)
DWORD lasterror;
void *ptr;
- lasterror = GetLastError();
+ lasterror = GetLastError ();
- ptr = TlsGetValue(key);
+ ptr = TlsGetValue (key);
- SetLastError( lasterror );
+ SetLastError (lasterror);
return ptr;
}
@@ -460,7 +550,7 @@ __gthread_setspecific (__gthread_key_t key, const void *ptr)
static inline void
__gthread_mutex_init_function (__gthread_mutex_t *mutex)
{
- /* Create unnamed mutex with default security attr and no initial owner. */
+ /* Create unnamed mutex with default security attr and no initial owner. */
*mutex = CreateMutex (NULL, 0, NULL);
}
@@ -503,7 +593,12 @@ __gthread_mutex_unlock (__gthread_mutex_t *mutex)
return 0;
}
+#endif /* __GTHREAD_HIDE_WIN32API */
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _LIBOBJC */
#endif /* ! GCC_GTHR_WIN32_H */
-
diff --git a/contrib/gcc/gthr.h b/contrib/gcc/gthr.h
index ba3a3be..b436bb6 100644
--- a/contrib/gcc/gthr.h
+++ b/contrib/gcc/gthr.h
@@ -32,7 +32,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* If this file is compiled with threads support, it must
#define __GTHREADS 1
to indicate that threads support is present. Also it has define
- function
+ function
int __gthread_active_p ()
that returns 1 if thread system is active, 0 if not.
diff --git a/contrib/gcc/haifa-sched.c b/contrib/gcc/haifa-sched.c
index 1d67afb..5c9ab50 100644
--- a/contrib/gcc/haifa-sched.c
+++ b/contrib/gcc/haifa-sched.c
@@ -158,6 +158,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
static int issue_rate;
+/* If the following variable value is nonzero, the scheduler inserts
+ bubbles (nop insns). The value of variable affects on scheduler
+ behavior only if automaton pipeline interface with multipass
+ scheduling is used and hook dfa_bubble is defined. */
+int insert_schedule_bubbles_p = 0;
+
/* sched-verbose controls the amount of debugging output the
scheduler prints. It is controlled by -fsched-verbose=N:
N>0 and no -DSR : the output is directed to stderr.
@@ -192,13 +198,6 @@ fix_sched_param (param, val)
struct haifa_insn_data *h_i_d;
-#define DONE_PRIORITY -1
-#define MAX_PRIORITY 0x7fffffff
-#define TAIL_PRIORITY 0x7ffffffe
-#define LAUNCH_PRIORITY 0x7f000001
-#define DONE_PRIORITY_P(INSN) (INSN_PRIORITY (INSN) < 0)
-#define LOW_PRIORITY_P(INSN) ((INSN_PRIORITY (INSN) & 0x7f000000) == 0)
-
#define LINE_NOTE(INSN) (h_i_d[INSN_UID (INSN)].line_note)
#define INSN_TICK(INSN) (h_i_d[INSN_UID (INSN)].tick)
@@ -254,14 +253,39 @@ static rtx note_list;
passes or stalls are introduced. */
/* Implement a circular buffer to delay instructions until sufficient
- time has passed. INSN_QUEUE_SIZE is a power of two larger than
- MAX_BLOCKAGE and MAX_READY_COST computed by genattr.c. This is the
- longest time an isnsn may be queued. */
-static rtx insn_queue[INSN_QUEUE_SIZE];
+ time has passed. For the old pipeline description interface,
+ INSN_QUEUE_SIZE is a power of two larger than MAX_BLOCKAGE and
+ MAX_READY_COST computed by genattr.c. For the new pipeline
+ description interface, MAX_INSN_QUEUE_INDEX is a power of two minus
+ one which is larger than maximal time of instruction execution
+ computed by genattr.c on the base maximal time of functional unit
+ reservations and geting a result. This is the longest time an
+ insn may be queued. */
+
+#define MAX_INSN_QUEUE_INDEX max_insn_queue_index_macro_value
+
+static rtx *insn_queue;
static int q_ptr = 0;
static int q_size = 0;
-#define NEXT_Q(X) (((X)+1) & (INSN_QUEUE_SIZE-1))
-#define NEXT_Q_AFTER(X, C) (((X)+C) & (INSN_QUEUE_SIZE-1))
+#define NEXT_Q(X) (((X)+1) & MAX_INSN_QUEUE_INDEX)
+#define NEXT_Q_AFTER(X, C) (((X)+C) & MAX_INSN_QUEUE_INDEX)
+
+/* The following variable defines value for macro
+ MAX_INSN_QUEUE_INDEX. */
+static int max_insn_queue_index_macro_value;
+
+/* The following variable value refers for all current and future
+ reservations of the processor units. */
+state_t curr_state;
+
+/* The following variable value is size of memory representing all
+ current and future reservations of the processor units. It is used
+ only by DFA based scheduler. */
+static size_t dfa_state_size;
+
+/* The following array is used to find the best insn from ready when
+ the automaton pipeline interface is used. */
+static char *ready_try;
/* Describe the ready list of the scheduler.
VEC holds space enough for all insns in the current region. VECLEN
@@ -280,11 +304,15 @@ struct ready_list
};
/* Forward declarations. */
+
+/* The scheduler using only DFA description should never use the
+ following five functions: */
static unsigned int blockage_range PARAMS ((int, rtx));
static void clear_units PARAMS ((void));
static void schedule_unit PARAMS ((int, rtx, int));
static int actual_hazard PARAMS ((int, rtx, int, int));
static int potential_hazard PARAMS ((int, rtx, int));
+
static int priority PARAMS ((rtx));
static int rank_for_schedule PARAMS ((const PTR, const PTR));
static void swap_sort PARAMS ((rtx *, int));
@@ -292,6 +320,7 @@ static void queue_insn PARAMS ((rtx, int));
static void schedule_insn PARAMS ((rtx, struct ready_list *, int));
static void find_insn_reg_weight PARAMS ((int));
static void adjust_priority PARAMS ((rtx));
+static void advance_one_cycle PARAMS ((void));
/* Notes handling mechanism:
=========================
@@ -331,6 +360,14 @@ static void debug_ready_list PARAMS ((struct ready_list *));
static rtx move_insn1 PARAMS ((rtx, rtx));
static rtx move_insn PARAMS ((rtx, rtx));
+/* The following functions are used to implement multi-pass scheduling
+ on the first cycle. It is used only for DFA based scheduler. */
+static rtx ready_element PARAMS ((struct ready_list *, int));
+static rtx ready_remove PARAMS ((struct ready_list *, int));
+static int max_issue PARAMS ((struct ready_list *, int *));
+
+static rtx choose_ready PARAMS ((struct ready_list *));
+
#endif /* INSN_SCHEDULING */
/* Point to state used for the current scheduling pass. */
@@ -352,9 +389,10 @@ static rtx last_scheduled_insn;
/* Compute the function units used by INSN. This caches the value
returned by function_units_used. A function unit is encoded as the
- unit number if the value is non-negative and the compliment of a
+ unit number if the value is non-negative and the complement of a
mask if the value is negative. A function unit index is the
- non-negative encoding. */
+ non-negative encoding. The scheduler using only DFA description
+ should never use the following function. */
HAIFA_INLINE int
insn_unit (insn)
@@ -391,7 +429,9 @@ insn_unit (insn)
/* Compute the blockage range for executing INSN on UNIT. This caches
the value returned by the blockage_range_function for the unit.
These values are encoded in an int where the upper half gives the
- minimum value and the lower half gives the maximum value. */
+ minimum value and the lower half gives the maximum value. The
+ scheduler using only DFA description should never use the following
+ function. */
HAIFA_INLINE static unsigned int
blockage_range (unit, insn)
@@ -415,20 +455,38 @@ blockage_range (unit, insn)
return range;
}
-/* A vector indexed by function unit instance giving the last insn to use
- the unit. The value of the function unit instance index for unit U
- instance I is (U + I * FUNCTION_UNITS_SIZE). */
+/* A vector indexed by function unit instance giving the last insn to
+ use the unit. The value of the function unit instance index for
+ unit U instance I is (U + I * FUNCTION_UNITS_SIZE). The scheduler
+ using only DFA description should never use the following variable. */
+#if FUNCTION_UNITS_SIZE
static rtx unit_last_insn[FUNCTION_UNITS_SIZE * MAX_MULTIPLICITY];
+#else
+static rtx unit_last_insn[1];
+#endif
-/* A vector indexed by function unit instance giving the minimum time when
- the unit will unblock based on the maximum blockage cost. */
+/* A vector indexed by function unit instance giving the minimum time
+ when the unit will unblock based on the maximum blockage cost. The
+ scheduler using only DFA description should never use the following
+ variable. */
+#if FUNCTION_UNITS_SIZE
static int unit_tick[FUNCTION_UNITS_SIZE * MAX_MULTIPLICITY];
+#else
+static int unit_tick[1];
+#endif
/* A vector indexed by function unit number giving the number of insns
- that remain to use the unit. */
+ that remain to use the unit. The scheduler using only DFA
+ description should never use the following variable. */
+#if FUNCTION_UNITS_SIZE
static int unit_n_insns[FUNCTION_UNITS_SIZE];
+#else
+static int unit_n_insns[1];
+#endif
-/* Access the unit_last_insn array. Used by the visualization code. */
+/* Access the unit_last_insn array. Used by the visualization code.
+ The scheduler using only DFA description should never use the
+ following function. */
rtx
get_unit_last_insn (instance)
@@ -447,7 +505,8 @@ clear_units ()
memset ((char *) unit_n_insns, 0, sizeof (unit_n_insns));
}
-/* Return the issue-delay of an insn. */
+/* Return the issue-delay of an insn. The scheduler using only DFA
+ description should never use the following function. */
HAIFA_INLINE int
insn_issue_delay (insn)
@@ -477,7 +536,8 @@ insn_issue_delay (insn)
/* Return the actual hazard cost of executing INSN on the unit UNIT,
instance INSTANCE at time CLOCK if the previous actual hazard cost
- was COST. */
+ was COST. The scheduler using only DFA description should never
+ use the following function. */
HAIFA_INLINE int
actual_hazard_this_instance (unit, instance, insn, clock, cost)
@@ -513,8 +573,9 @@ actual_hazard_this_instance (unit, instance, insn, clock, cost)
return cost;
}
-/* Record INSN as having begun execution on the units encoded by UNIT at
- time CLOCK. */
+/* Record INSN as having begun execution on the units encoded by UNIT
+ at time CLOCK. The scheduler using only DFA description should
+ never use the following function. */
HAIFA_INLINE static void
schedule_unit (unit, insn, clock)
@@ -545,8 +606,10 @@ schedule_unit (unit, insn, clock)
schedule_unit (i, insn, clock);
}
-/* Return the actual hazard cost of executing INSN on the units encoded by
- UNIT at time CLOCK if the previous actual hazard cost was COST. */
+/* Return the actual hazard cost of executing INSN on the units
+ encoded by UNIT at time CLOCK if the previous actual hazard cost
+ was COST. The scheduler using only DFA description should never
+ use the following function. */
HAIFA_INLINE static int
actual_hazard (unit, insn, clock, cost)
@@ -591,11 +654,13 @@ actual_hazard (unit, insn, clock, cost)
}
/* Return the potential hazard cost of executing an instruction on the
- units encoded by UNIT if the previous potential hazard cost was COST.
- An insn with a large blockage time is chosen in preference to one
- with a smaller time; an insn that uses a unit that is more likely
- to be used is chosen in preference to one with a unit that is less
- used. We are trying to minimize a subsequent actual hazard. */
+ units encoded by UNIT if the previous potential hazard cost was
+ COST. An insn with a large blockage time is chosen in preference
+ to one with a smaller time; an insn that uses a unit that is more
+ likely to be used is chosen in preference to one with a unit that
+ is less used. We are trying to minimize a subsequent actual
+ hazard. The scheduler using only DFA description should never use
+ the following function. */
HAIFA_INLINE static int
potential_hazard (unit, insn, cost)
@@ -648,62 +713,69 @@ insn_cost (insn, link, used)
{
int cost = INSN_COST (insn);
- if (cost == 0)
+ if (cost < 0)
{
- recog_memoized (insn);
-
- /* A USE insn, or something else we don't need to understand.
- We can't pass these directly to result_ready_cost because it will
- trigger a fatal error for unrecognizable insns. */
- if (INSN_CODE (insn) < 0)
+ /* A USE insn, or something else we don't need to
+ understand. We can't pass these directly to
+ result_ready_cost or insn_default_latency because it will
+ trigger a fatal error for unrecognizable insns. */
+ if (recog_memoized (insn) < 0)
{
- INSN_COST (insn) = 1;
- return 1;
+ INSN_COST (insn) = 0;
+ return 0;
}
else
{
- cost = result_ready_cost (insn);
-
- if (cost < 1)
- cost = 1;
-
+ if (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ())
+ cost = insn_default_latency (insn);
+ else
+ cost = result_ready_cost (insn);
+
+ if (cost < 0)
+ cost = 0;
+
INSN_COST (insn) = cost;
}
}
/* In this case estimate cost without caring how insn is used. */
- if (link == 0 && used == 0)
+ if (link == 0 || used == 0)
return cost;
- /* A USE insn should never require the value used to be computed. This
- allows the computation of a function's result and parameter values to
- overlap the return and call. */
- recog_memoized (used);
- if (INSN_CODE (used) < 0)
- LINK_COST_FREE (link) = 1;
-
- /* If some dependencies vary the cost, compute the adjustment. Most
- commonly, the adjustment is complete: either the cost is ignored
- (in the case of an output- or anti-dependence), or the cost is
- unchanged. These values are cached in the link as LINK_COST_FREE
- and LINK_COST_ZERO. */
-
- if (LINK_COST_FREE (link))
+ /* A USE insn should never require the value used to be computed.
+ This allows the computation of a function's result and parameter
+ values to overlap the return and call. */
+ if (recog_memoized (used) < 0)
cost = 0;
- else if (!LINK_COST_ZERO (link) && targetm.sched.adjust_cost)
+ else
{
- int ncost = (*targetm.sched.adjust_cost) (used, link, insn, cost);
-
- if (ncost < 1)
+ if (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ())
{
- LINK_COST_FREE (link) = 1;
- ncost = 0;
+ if (INSN_CODE (insn) >= 0)
+ {
+ if (REG_NOTE_KIND (link) == REG_DEP_ANTI)
+ cost = 0;
+ else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
+ {
+ cost = (insn_default_latency (insn)
+ - insn_default_latency (used));
+ if (cost <= 0)
+ cost = 1;
+ }
+ else if (bypass_p (insn))
+ cost = insn_latency (insn, used);
+ }
}
- if (cost == ncost)
- LINK_COST_ZERO (link) = 1;
- cost = ncost;
- }
+ if (targetm.sched.adjust_cost)
+ cost = (*targetm.sched.adjust_cost) (used, link, insn, cost);
+
+ if (cost < 0)
+ cost = 0;
+ }
+
return cost;
}
@@ -930,6 +1002,48 @@ ready_remove_first (ready)
return t;
}
+/* The following code implements multi-pass scheduling for the first
+ cycle. In other words, we will try to choose ready insn which
+ permits to start maximum number of insns on the same cycle. */
+
+/* Return a pointer to the element INDEX from the ready. INDEX for
+ insn with the highest priority is 0, and the lowest priority has
+ N_READY - 1. */
+
+HAIFA_INLINE static rtx
+ready_element (ready, index)
+ struct ready_list *ready;
+ int index;
+{
+ if (ready->n_ready == 0 || index >= ready->n_ready)
+ abort ();
+ return ready->vec[ready->first - index];
+}
+
+/* Remove the element INDEX from the ready list and return it. INDEX
+ for insn with the highest priority is 0, and the lowest priority
+ has N_READY - 1. */
+
+HAIFA_INLINE static rtx
+ready_remove (ready, index)
+ struct ready_list *ready;
+ int index;
+{
+ rtx t;
+ int i;
+
+ if (index == 0)
+ return ready_remove_first (ready);
+ if (ready->n_ready == 0 || index >= ready->n_ready)
+ abort ();
+ t = ready->vec[ready->first - index];
+ ready->n_ready--;
+ for (i = index; i < ready->n_ready; i++)
+ ready->vec[ready->first - i] = ready->vec[ready->first - i - 1];
+ return t;
+}
+
+
/* Sort the ready list READY by ascending priority, using the SCHED_SORT
macro. */
@@ -961,6 +1075,25 @@ adjust_priority (prev)
(*targetm.sched.adjust_priority) (prev, INSN_PRIORITY (prev));
}
+/* Advance time on one cycle. */
+HAIFA_INLINE static void
+advance_one_cycle ()
+{
+ if (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ())
+ {
+ if (targetm.sched.dfa_pre_cycle_insn)
+ state_transition (curr_state,
+ (*targetm.sched.dfa_pre_cycle_insn) ());
+
+ state_transition (curr_state, NULL);
+
+ if (targetm.sched.dfa_post_cycle_insn)
+ state_transition (curr_state,
+ (*targetm.sched.dfa_post_cycle_insn) ());
+ }
+}
+
/* Clock at which the previous instruction was issued. */
static int last_clock_var;
@@ -976,26 +1109,49 @@ schedule_insn (insn, ready, clock)
int clock;
{
rtx link;
- int unit;
+ int unit = 0;
- unit = insn_unit (insn);
+ if (!targetm.sched.use_dfa_pipeline_interface
+ || !(*targetm.sched.use_dfa_pipeline_interface) ())
+ unit = insn_unit (insn);
- if (sched_verbose >= 2)
+ if (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ()
+ && sched_verbose >= 1)
+ {
+ char buf[2048];
+
+ print_insn (buf, insn, 0);
+ buf[40]=0;
+ fprintf (sched_dump, ";;\t%3i--> %-40s:", clock, buf);
+
+ if (recog_memoized (insn) < 0)
+ fprintf (sched_dump, "nothing");
+ else
+ print_reservation (sched_dump, insn);
+ fputc ('\n', sched_dump);
+ }
+ else if (sched_verbose >= 2)
{
fprintf (sched_dump, ";;\t\t--> scheduling insn <<<%d>>> on unit ",
INSN_UID (insn));
insn_print_units (insn);
- fprintf (sched_dump, "\n");
+ fputc ('\n', sched_dump);
}
- if (sched_verbose && unit == -1)
- visualize_no_unit (insn);
+ if (!targetm.sched.use_dfa_pipeline_interface
+ || !(*targetm.sched.use_dfa_pipeline_interface) ())
+ {
+ if (sched_verbose && unit == -1)
+ visualize_no_unit (insn);
- if (MAX_BLOCKAGE > 1 || issue_rate > 1 || sched_verbose)
- schedule_unit (unit, insn, clock);
- if (INSN_DEPEND (insn) == 0)
- return;
+ if (MAX_BLOCKAGE > 1 || issue_rate > 1 || sched_verbose)
+ schedule_unit (unit, insn, clock);
+
+ if (INSN_DEPEND (insn) == 0)
+ return;
+ }
for (link = INSN_DEPEND (insn); link != 0; link = XEXP (link, 1))
{
@@ -1037,7 +1193,9 @@ schedule_insn (insn, ready, clock)
to issue on the same cycle as the previous insn. A machine
may use this information to decide how the instruction should
be aligned. */
- if (reload_completed && issue_rate > 1)
+ if (reload_completed && issue_rate > 1
+ && GET_CODE (PATTERN (insn)) != USE
+ && GET_CODE (PATTERN (insn)) != CLOBBER)
{
PUT_MODE (insn, clock > last_clock_var ? TImode : VOIDmode);
last_clock_var = clock;
@@ -1068,8 +1226,6 @@ unlink_other_notes (insn, tail)
/* See sched_analyze to see how these are handled. */
if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_END
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_RANGE_BEG
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_RANGE_END
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_END)
{
@@ -1464,7 +1620,7 @@ queue_to_ready (ready)
{
int stalls;
- for (stalls = 1; stalls < INSN_QUEUE_SIZE; stalls++)
+ for (stalls = 1; stalls <= MAX_INSN_QUEUE_INDEX; stalls++)
{
if ((link = insn_queue[NEXT_Q_AFTER (q_ptr, stalls)]))
{
@@ -1483,13 +1639,19 @@ queue_to_ready (ready)
}
insn_queue[NEXT_Q_AFTER (q_ptr, stalls)] = 0;
- if (ready->n_ready)
- break;
+ advance_one_cycle ();
+
+ break;
}
+
+ advance_one_cycle ();
}
- if (sched_verbose && stalls)
+ if ((!targetm.sched.use_dfa_pipeline_interface
+ || !(*targetm.sched.use_dfa_pipeline_interface) ())
+ && sched_verbose && stalls)
visualize_stall_cycles (stalls);
+
q_ptr = NEXT_Q_AFTER (q_ptr, stalls);
clock_var += stalls;
}
@@ -1505,7 +1667,10 @@ debug_ready_list (ready)
int i;
if (ready->n_ready == 0)
- return;
+ {
+ fprintf (sched_dump, "\n");
+ return;
+ }
p = ready_lastpos (ready);
for (i = 0; i < ready->n_ready; i++)
@@ -1552,23 +1717,12 @@ reemit_notes (insn, last)
{
enum insn_note note_type = INTVAL (XEXP (note, 0));
- if (note_type == NOTE_INSN_RANGE_BEG
- || note_type == NOTE_INSN_RANGE_END)
- {
- last = emit_note_before (note_type, last);
- remove_note (insn, note);
- note = XEXP (note, 1);
- NOTE_RANGE_INFO (last) = XEXP (note, 0);
- }
- else
- {
- last = emit_note_before (note_type, last);
- remove_note (insn, note);
- note = XEXP (note, 1);
- if (note_type == NOTE_INSN_EH_REGION_BEG
- || note_type == NOTE_INSN_EH_REGION_END)
- NOTE_EH_HANDLER (last) = INTVAL (XEXP (note, 0));
- }
+ last = emit_note_before (note_type, last);
+ remove_note (insn, note);
+ note = XEXP (note, 1);
+ if (note_type == NOTE_INSN_EH_REGION_BEG
+ || note_type == NOTE_INSN_EH_REGION_END)
+ NOTE_EH_HANDLER (last) = INTVAL (XEXP (note, 0));
remove_note (insn, note);
}
}
@@ -1619,6 +1773,172 @@ move_insn (insn, last)
return retval;
}
+/* The following structure describe an entry of the stack of choices. */
+struct choice_entry
+{
+ /* Ordinal number of the issued insn in the ready queue. */
+ int index;
+ /* The number of the rest insns whose issues we should try. */
+ int rest;
+ /* The number of issued essential insns. */
+ int n;
+ /* State after issuing the insn. */
+ state_t state;
+};
+
+/* The following array is used to implement a stack of choices used in
+ function max_issue. */
+static struct choice_entry *choice_stack;
+
+/* The following variable value is number of essential insns issued on
+ the current cycle. An insn is essential one if it changes the
+ processors state. */
+static int cycle_issued_insns;
+
+/* The following variable value is maximal number of tries of issuing
+ insns for the first cycle multipass insn scheduling. We define
+ this value as constant*(DFA_LOOKAHEAD**ISSUE_RATE). We would not
+ need this constraint if all real insns (with non-negative codes)
+ had reservations because in this case the algorithm complexity is
+ O(DFA_LOOKAHEAD**ISSUE_RATE). Unfortunately, the dfa descriptions
+ might be incomplete and such insn might occur. For such
+ descriptions, the complexity of algorithm (without the constraint)
+ could achieve DFA_LOOKAHEAD ** N , where N is the queue length. */
+static int max_lookahead_tries;
+
+/* The following value is value of hook
+ `first_cycle_multipass_dfa_lookahead' at the last call of
+ `max_issue'. */
+static int cached_first_cycle_multipass_dfa_lookahead = 0;
+
+/* The following value is value of `issue_rate' at the last call of
+ `sched_init'. */
+static int cached_issue_rate = 0;
+
+/* The following function returns maximal (or close to maximal) number
+ of insns which can be issued on the same cycle and one of which
+ insns is insns with the best rank (the first insn in READY). To
+ make this function tries different samples of ready insns. READY
+ is current queue `ready'. Global array READY_TRY reflects what
+ insns are already issued in this try. INDEX will contain index
+ of the best insn in READY. The following function is used only for
+ first cycle multipass scheduling. */
+static int
+max_issue (ready, index)
+ struct ready_list *ready;
+ int *index;
+{
+ int n, i, all, n_ready, best, delay, tries_num;
+ struct choice_entry *top;
+ rtx insn;
+
+ best = 0;
+ memcpy (choice_stack->state, curr_state, dfa_state_size);
+ top = choice_stack;
+ top->rest = cached_first_cycle_multipass_dfa_lookahead;
+ top->n = 0;
+ n_ready = ready->n_ready;
+ for (all = i = 0; i < n_ready; i++)
+ if (!ready_try [i])
+ all++;
+ i = 0;
+ tries_num = 0;
+ for (;;)
+ {
+ if (top->rest == 0 || i >= n_ready)
+ {
+ if (top == choice_stack)
+ break;
+ if (best < top - choice_stack && ready_try [0])
+ {
+ best = top - choice_stack;
+ *index = choice_stack [1].index;
+ if (top->n == issue_rate - cycle_issued_insns || best == all)
+ break;
+ }
+ i = top->index;
+ ready_try [i] = 0;
+ top--;
+ memcpy (curr_state, top->state, dfa_state_size);
+ }
+ else if (!ready_try [i])
+ {
+ tries_num++;
+ if (tries_num > max_lookahead_tries)
+ break;
+ insn = ready_element (ready, i);
+ delay = state_transition (curr_state, insn);
+ if (delay < 0)
+ {
+ if (state_dead_lock_p (curr_state))
+ top->rest = 0;
+ else
+ top->rest--;
+ n = top->n;
+ if (memcmp (top->state, curr_state, dfa_state_size) != 0)
+ n++;
+ top++;
+ top->rest = cached_first_cycle_multipass_dfa_lookahead;
+ top->index = i;
+ top->n = n;
+ memcpy (top->state, curr_state, dfa_state_size);
+ ready_try [i] = 1;
+ i = -1;
+ }
+ }
+ i++;
+ }
+ while (top != choice_stack)
+ {
+ ready_try [top->index] = 0;
+ top--;
+ }
+ memcpy (curr_state, choice_stack->state, dfa_state_size);
+ return best;
+}
+
+/* The following function chooses insn from READY and modifies
+ *N_READY and READY. The following function is used only for first
+ cycle multipass scheduling. */
+
+static rtx
+choose_ready (ready)
+ struct ready_list *ready;
+{
+ int lookahead = 0;
+
+ if (targetm.sched.first_cycle_multipass_dfa_lookahead)
+ lookahead = (*targetm.sched.first_cycle_multipass_dfa_lookahead) ();
+ if (lookahead <= 0 || SCHED_GROUP_P (ready_element (ready, 0)))
+ return ready_remove_first (ready);
+ else
+ {
+ /* Try to choose the better insn. */
+ int index, i;
+ rtx insn;
+
+ if (cached_first_cycle_multipass_dfa_lookahead != lookahead)
+ {
+ cached_first_cycle_multipass_dfa_lookahead = lookahead;
+ max_lookahead_tries = 100;
+ for (i = 0; i < issue_rate; i++)
+ max_lookahead_tries *= lookahead;
+ }
+ insn = ready_element (ready, 0);
+ if (INSN_CODE (insn) < 0)
+ return ready_remove_first (ready);
+ for (i = 1; i < ready->n_ready; i++)
+ {
+ insn = ready_element (ready, i);
+ ready_try [i] = INSN_CODE (insn) < 0;
+ }
+ if (max_issue (ready, &index) == 0)
+ return ready_remove_first (ready);
+ else
+ return ready_remove (ready, index);
+ }
+}
+
/* Called from backends from targetm.sched.reorder to emit stuff into
the instruction stream. */
@@ -1640,7 +1960,10 @@ schedule_block (b, rgn_n_insns)
int rgn_n_insns;
{
struct ready_list ready;
+ int i;
+ int first_cycle_insn_p;
int can_issue_more;
+ state_t temp_state = NULL; /* It is used for multipass scheduling. */
/* Head/tail info for this block. */
rtx prev_head = current_sched_info->prev_head;
@@ -1673,7 +1996,11 @@ schedule_block (b, rgn_n_insns)
init_block_visualization ();
}
- clear_units ();
+ if (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ())
+ state_reset (curr_state);
+ else
+ clear_units ();
/* Allocate the ready list. */
ready.veclen = rgn_n_insns + 1 + issue_rate;
@@ -1681,6 +2008,20 @@ schedule_block (b, rgn_n_insns)
ready.vec = (rtx *) xmalloc (ready.veclen * sizeof (rtx));
ready.n_ready = 0;
+ if (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ())
+ {
+ /* It is used for first cycle multipass scheduling. */
+ temp_state = alloca (dfa_state_size);
+ ready_try = (char *) xmalloc ((rgn_n_insns + 1) * sizeof (char));
+ memset (ready_try, 0, (rgn_n_insns + 1) * sizeof (char));
+ choice_stack
+ = (struct choice_entry *) xmalloc ((rgn_n_insns + 1)
+ * sizeof (struct choice_entry));
+ for (i = 0; i <= rgn_n_insns; i++)
+ choice_stack[i].state = (state_t) xmalloc (dfa_state_size);
+ }
+
(*current_sched_info->init_ready_list) (&ready);
if (targetm.sched.md_init)
@@ -1693,8 +2034,16 @@ schedule_block (b, rgn_n_insns)
queue. */
q_ptr = 0;
q_size = 0;
- last_clock_var = 0;
- memset ((char *) insn_queue, 0, sizeof (insn_queue));
+
+ if (!targetm.sched.use_dfa_pipeline_interface
+ || !(*targetm.sched.use_dfa_pipeline_interface) ())
+ max_insn_queue_index_macro_value = INSN_QUEUE_SIZE - 1;
+ else
+ max_insn_queue_index_macro_value = max_insn_queue_index;
+
+ insn_queue = (rtx *) alloca ((MAX_INSN_QUEUE_INDEX + 1) * sizeof (rtx));
+ memset ((char *) insn_queue, 0, (MAX_INSN_QUEUE_INDEX + 1) * sizeof (rtx));
+ last_clock_var = -1;
/* Start just before the beginning of time. */
clock_var = -1;
@@ -1704,6 +2053,8 @@ schedule_block (b, rgn_n_insns)
{
clock_var++;
+ advance_one_cycle ();
+
/* Add to the ready list all pending insns that can be issued now.
If there are no ready insns, increment clock until one
is ready and add all pending insns at that point to the ready
@@ -1732,24 +2083,128 @@ schedule_block (b, rgn_n_insns)
else
can_issue_more = issue_rate;
- if (sched_verbose && targetm.sched.cycle_display)
- last_scheduled_insn
- = (*targetm.sched.cycle_display) (clock_var, last_scheduled_insn);
-
- if (sched_verbose)
+ first_cycle_insn_p = 1;
+ cycle_issued_insns = 0;
+ for (;;)
{
- fprintf (sched_dump, "\n;;\tReady list (t =%3d): ", clock_var);
- debug_ready_list (&ready);
- }
+ rtx insn;
+ int cost;
+
+ if (sched_verbose >= 2)
+ {
+ fprintf (sched_dump, ";;\tReady list (t =%3d): ",
+ clock_var);
+ debug_ready_list (&ready);
+ }
+
+ if (!targetm.sched.use_dfa_pipeline_interface
+ || !(*targetm.sched.use_dfa_pipeline_interface) ())
+ {
+ if (ready.n_ready == 0 || !can_issue_more
+ || !(*current_sched_info->schedule_more_p) ())
+ break;
+ insn = choose_ready (&ready);
+ cost = actual_hazard (insn_unit (insn), insn, clock_var, 0);
+ }
+ else
+ {
+ if (ready.n_ready == 0 || !can_issue_more
+ || state_dead_lock_p (curr_state)
+ || !(*current_sched_info->schedule_more_p) ())
+ break;
+
+ /* Select and remove the insn from the ready list. */
+ insn = choose_ready (&ready);
+
+ memcpy (temp_state, curr_state, dfa_state_size);
+ if (recog_memoized (insn) < 0)
+ {
+ if (!first_cycle_insn_p
+ && (GET_CODE (PATTERN (insn)) == ASM_INPUT
+ || asm_noperands (PATTERN (insn)) >= 0))
+ /* This is asm insn which is tryed to be issued on the
+ cycle not first. Issue it on the next cycle. */
+ cost = 1;
+ else
+ /* A USE insn, or something else we don't need to
+ understand. We can't pass these directly to
+ state_transition because it will trigger a
+ fatal error for unrecognizable insns. */
+ cost = 0;
+ }
+ else
+ {
+ cost = state_transition (temp_state, insn);
+
+ if (targetm.sched.first_cycle_multipass_dfa_lookahead
+ && targetm.sched.dfa_bubble)
+ {
+ if (cost == 0)
+ {
+ int j;
+ rtx bubble;
+
+ for (j = 0;
+ (bubble = (*targetm.sched.dfa_bubble) (j))
+ != NULL_RTX;
+ j++)
+ {
+ memcpy (temp_state, curr_state, dfa_state_size);
+
+ if (state_transition (temp_state, bubble) < 0
+ && state_transition (temp_state, insn) < 0)
+ break;
+ }
+
+ if (bubble != NULL_RTX)
+ {
+ if (insert_schedule_bubbles_p)
+ {
+ rtx copy;
+
+ copy = copy_rtx (PATTERN (bubble));
+ emit_insn_after (copy, last_scheduled_insn);
+ last_scheduled_insn
+ = NEXT_INSN (last_scheduled_insn);
+ INSN_CODE (last_scheduled_insn)
+ = INSN_CODE (bubble);
+
+ /* Annotate the same for the first insns
+ scheduling by using mode. */
+ PUT_MODE (last_scheduled_insn,
+ (clock_var > last_clock_var
+ ? clock_var - last_clock_var
+ : VOIDmode));
+ last_clock_var = clock_var;
+
+ if (sched_verbose >= 2)
+ {
+ fprintf (sched_dump,
+ ";;\t\t--> scheduling bubble insn <<<%d>>>:reservation ",
+ INSN_UID (last_scheduled_insn));
+
+ if (recog_memoized (last_scheduled_insn)
+ < 0)
+ fprintf (sched_dump, "nothing");
+ else
+ print_reservation
+ (sched_dump, last_scheduled_insn);
+
+ fprintf (sched_dump, "\n");
+ }
+ }
+ cost = -1;
+ }
+ }
+ }
+
+ if (cost < 0)
+ cost = 0;
+ else if (cost == 0)
+ cost = 1;
+ }
+ }
- /* Issue insns from ready list. */
- while (ready.n_ready != 0
- && can_issue_more
- && (*current_sched_info->schedule_more_p) ())
- {
- /* Select and remove the insn from the ready list. */
- rtx insn = ready_remove_first (&ready);
- int cost = actual_hazard (insn_unit (insn), insn, clock_var, 0);
if (cost >= 1)
{
@@ -1762,6 +2217,14 @@ schedule_block (b, rgn_n_insns)
last_scheduled_insn = move_insn (insn, last_scheduled_insn);
+ if (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ())
+ {
+ if (memcmp (curr_state, temp_state, dfa_state_size) != 0)
+ cycle_issued_insns++;
+ memcpy (curr_state, temp_state, dfa_state_size);
+ }
+
if (targetm.sched.variable_issue)
can_issue_more =
(*targetm.sched.variable_issue) (sched_dump, sched_verbose,
@@ -1775,6 +2238,8 @@ schedule_block (b, rgn_n_insns)
schedule_insn (insn, &ready, clock_var);
next:
+ first_cycle_insn_p = 0;
+
if (targetm.sched.reorder2)
{
/* Sort the ready list based on priority. */
@@ -1788,8 +2253,10 @@ schedule_block (b, rgn_n_insns)
}
}
- /* Debug info. */
- if (sched_verbose)
+ if ((!targetm.sched.use_dfa_pipeline_interface
+ || !(*targetm.sched.use_dfa_pipeline_interface) ())
+ && sched_verbose)
+ /* Debug info. */
visualize_scheduled_insns (clock_var);
}
@@ -1801,7 +2268,9 @@ schedule_block (b, rgn_n_insns)
{
fprintf (sched_dump, ";;\tReady list (final): ");
debug_ready_list (&ready);
- print_block_visualization ("");
+ if (!targetm.sched.use_dfa_pipeline_interface
+ || !(*targetm.sched.use_dfa_pipeline_interface) ())
+ print_block_visualization ("");
}
/* Sanity check -- queue must be empty now. Meaningless if region has
@@ -1846,6 +2315,15 @@ schedule_block (b, rgn_n_insns)
current_sched_info->tail = tail;
free (ready.vec);
+
+ if (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ())
+ {
+ free (ready_try);
+ for (i = 0; i <= rgn_n_insns; i++)
+ free (choice_stack [i].state);
+ free (choice_stack);
+ }
}
/* Set_priorities: compute priority of each insn in the block. */
@@ -1885,8 +2363,10 @@ void
sched_init (dump_file)
FILE *dump_file;
{
- int luid, b;
+ int luid;
+ basic_block b;
rtx insn;
+ int i;
/* Disable speculative loads in their presence if cc0 defined. */
#ifdef HAVE_cc0
@@ -1908,16 +2388,44 @@ sched_init (dump_file)
else
issue_rate = 1;
+ if (cached_issue_rate != issue_rate)
+ {
+ cached_issue_rate = issue_rate;
+ /* To invalidate max_lookahead_tries: */
+ cached_first_cycle_multipass_dfa_lookahead = 0;
+ }
+
/* We use LUID 0 for the fake insn (UID 0) which holds dependencies for
pseudos which do not cross calls. */
old_max_uid = get_max_uid () + 1;
h_i_d = (struct haifa_insn_data *) xcalloc (old_max_uid, sizeof (*h_i_d));
+ for (i = 0; i < old_max_uid; i++)
+ h_i_d [i].cost = -1;
+
+ if (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ())
+ {
+ if (targetm.sched.init_dfa_pre_cycle_insn)
+ (*targetm.sched.init_dfa_pre_cycle_insn) ();
+
+ if (targetm.sched.init_dfa_post_cycle_insn)
+ (*targetm.sched.init_dfa_post_cycle_insn) ();
+
+ if (targetm.sched.first_cycle_multipass_dfa_lookahead
+ && targetm.sched.init_dfa_bubbles)
+ (*targetm.sched.init_dfa_bubbles) ();
+
+ dfa_start ();
+ dfa_state_size = state_size ();
+ curr_state = xmalloc (dfa_state_size);
+ }
+
h_i_d[0].luid = 0;
luid = 1;
- for (b = 0; b < n_basic_blocks; b++)
- for (insn = BLOCK_HEAD (b);; insn = NEXT_INSN (insn))
+ FOR_EACH_BB (b)
+ for (insn = b->head;; insn = NEXT_INSN (insn))
{
INSN_LUID (insn) = luid;
@@ -1929,21 +2437,19 @@ sched_init (dump_file)
if (GET_CODE (insn) != NOTE)
++luid;
- if (insn == BLOCK_END (b))
+ if (insn == b->end)
break;
}
init_dependency_caches (luid);
- compute_bb_for_insn (old_max_uid);
-
init_alias_analysis ();
if (write_symbols != NO_DEBUG)
{
rtx line;
- line_note_head = (rtx *) xcalloc (n_basic_blocks, sizeof (rtx));
+ line_note_head = (rtx *) xcalloc (last_basic_block, sizeof (rtx));
/* Save-line-note-head:
Determine the line-number at the start of each basic block.
@@ -1951,49 +2457,51 @@ sched_init (dump_file)
predecessor has been scheduled, it is impossible to accurately
determine the correct line number for the first insn of the block. */
- for (b = 0; b < n_basic_blocks; b++)
+ FOR_EACH_BB (b)
{
- for (line = BLOCK_HEAD (b); line; line = PREV_INSN (line))
+ for (line = b->head; line; line = PREV_INSN (line))
if (GET_CODE (line) == NOTE && NOTE_LINE_NUMBER (line) > 0)
{
- line_note_head[b] = line;
+ line_note_head[b->index] = line;
break;
}
/* Do a forward search as well, since we won't get to see the first
notes in a basic block. */
- for (line = BLOCK_HEAD (b); line; line = NEXT_INSN (line))
+ for (line = b->head; line; line = NEXT_INSN (line))
{
if (INSN_P (line))
break;
if (GET_CODE (line) == NOTE && NOTE_LINE_NUMBER (line) > 0)
- line_note_head[b] = line;
+ line_note_head[b->index] = line;
}
}
}
- /* Find units used in this function, for visualization. */
- if (sched_verbose)
+ if ((!targetm.sched.use_dfa_pipeline_interface
+ || !(*targetm.sched.use_dfa_pipeline_interface) ())
+ && sched_verbose)
+ /* Find units used in this function, for visualization. */
init_target_units ();
/* ??? Add a NOTE after the last insn of the last basic block. It is not
known why this is done. */
- insn = BLOCK_END (n_basic_blocks - 1);
+ insn = EXIT_BLOCK_PTR->prev_bb->end;
if (NEXT_INSN (insn) == 0
|| (GET_CODE (insn) != NOTE
&& GET_CODE (insn) != CODE_LABEL
/* Don't emit a NOTE if it would end up before a BARRIER. */
&& GET_CODE (NEXT_INSN (insn)) != BARRIER))
{
- emit_note_after (NOTE_INSN_DELETED, BLOCK_END (n_basic_blocks - 1));
+ emit_note_after (NOTE_INSN_DELETED, EXIT_BLOCK_PTR->prev_bb->end);
/* Make insn to appear outside BB. */
- BLOCK_END (n_basic_blocks - 1) = PREV_INSN (BLOCK_END (n_basic_blocks - 1));
+ EXIT_BLOCK_PTR->prev_bb->end = PREV_INSN (EXIT_BLOCK_PTR->prev_bb->end);
}
/* Compute INSN_REG_WEIGHT for all blocks. We must do this before
removing death notes. */
- for (b = n_basic_blocks - 1; b >= 0; b--)
- find_insn_reg_weight (b);
+ FOR_EACH_BB_REVERSE (b)
+ find_insn_reg_weight (b->index);
}
/* Free global data used during insn scheduling. */
@@ -2002,6 +2510,13 @@ void
sched_finish ()
{
free (h_i_d);
+
+ if (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ())
+ {
+ free (curr_state);
+ dfa_finish ();
+ }
free_dependency_caches ();
end_alias_analysis ();
if (write_symbols != NO_DEBUG)
diff --git a/contrib/gcc/hard-reg-set.h b/contrib/gcc/hard-reg-set.h
index db96aa9..53330cf 100644
--- a/contrib/gcc/hard-reg-set.h
+++ b/contrib/gcc/hard-reg-set.h
@@ -92,7 +92,7 @@ typedef HARD_REG_ELT_TYPE HARD_REG_SET[HARD_REG_SET_LONGS];
#define CLEAR_HARD_REG_BIT(SET, BIT) \
((SET) &= ~(HARD_CONST (1) << (BIT)))
#define TEST_HARD_REG_BIT(SET, BIT) \
- ((SET) & (HARD_CONST (1) << (BIT)))
+ (!!((SET) & (HARD_CONST (1) << (BIT))))
#define CLEAR_HARD_REG_SET(TO) ((TO) = HARD_CONST (0))
#define SET_HARD_REG_SET(TO) ((TO) = ~ HARD_CONST (0))
@@ -122,8 +122,8 @@ typedef HARD_REG_ELT_TYPE HARD_REG_SET[HARD_REG_SET_LONGS];
&= ~(HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT)))
#define TEST_HARD_REG_BIT(SET, BIT) \
- ((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \
- & (HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT)))
+ (!!((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) \
@@ -405,6 +405,10 @@ extern HARD_REG_SET fixed_reg_set;
extern char call_used_regs[FIRST_PSEUDO_REGISTER];
+#ifdef CALL_REALLY_USED_REGISTERS
+extern char call_really_used_regs[];
+#endif
+
/* The same info as a HARD_REG_SET. */
extern HARD_REG_SET call_used_reg_set;
@@ -484,4 +488,9 @@ extern int n_non_fixed_regs;
extern const char * reg_names[FIRST_PSEUDO_REGISTER];
+/* Given a hard REGN a FROM mode and a TO mode, return nonzero if
+ REGN cannot change modes between the specified modes. */
+#define REG_CANNOT_CHANGE_MODE_P(REGN, FROM, TO) \
+ CANNOT_CHANGE_MODE_CLASS (FROM, TO, REGNO_REG_CLASS (REGN))
+
#endif /* ! GCC_HARD_REG_SET_H */
diff --git a/contrib/gcc/hashtab.c b/contrib/gcc/hashtab.c
index 37230d9..9426a18 100644
--- a/contrib/gcc/hashtab.c
+++ b/contrib/gcc/hashtab.c
@@ -45,6 +45,10 @@ Boston, MA 02111-1307, USA. */
#include <string.h>
#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
#include <stdio.h>
#include "libiberty.h"
@@ -158,60 +162,60 @@ eq_pointer (p1, p2)
/* This function creates table with length slightly longer than given
source length. Created hash table is initiated as empty (all the
hash table entries are EMPTY_ENTRY). The function returns the
- created hash table. Memory allocation must not fail. */
+ created hash table, or NULL if memory allocation fails. */
htab_t
-htab_create (size, hash_f, eq_f, del_f)
+htab_create_alloc (size, hash_f, eq_f, del_f, alloc_f, free_f)
size_t size;
htab_hash hash_f;
htab_eq eq_f;
htab_del del_f;
+ htab_alloc alloc_f;
+ htab_free free_f;
{
htab_t result;
size = higher_prime_number (size);
- result = (htab_t) xcalloc (1, sizeof (struct htab));
- result->entries = (PTR *) xcalloc (size, sizeof (PTR));
+ result = (htab_t) (*alloc_f) (1, sizeof (struct htab));
+ if (result == NULL)
+ return NULL;
+ result->entries = (PTR *) (*alloc_f) (size, sizeof (PTR));
+ if (result->entries == NULL)
+ {
+ if (free_f != NULL)
+ (*free_f) (result);
+ return NULL;
+ }
result->size = size;
result->hash_f = hash_f;
result->eq_f = eq_f;
result->del_f = del_f;
- result->return_allocation_failure = 0;
+ result->alloc_f = alloc_f;
+ result->free_f = free_f;
return result;
}
-/* This function creates table with length slightly longer than given
- source length. The created hash table is initiated as empty (all the
- hash table entries are EMPTY_ENTRY). The function returns the created
- hash table. Memory allocation may fail; it may return NULL. */
+/* These functions exist solely for backward compatibility. */
+#undef htab_create
htab_t
-htab_try_create (size, hash_f, eq_f, del_f)
+htab_create (size, hash_f, eq_f, del_f)
size_t size;
htab_hash hash_f;
htab_eq eq_f;
htab_del del_f;
{
- htab_t result;
-
- size = higher_prime_number (size);
- result = (htab_t) calloc (1, sizeof (struct htab));
- if (result == NULL)
- return NULL;
-
- result->entries = (PTR *) calloc (size, sizeof (PTR));
- if (result->entries == NULL)
- {
- free (result);
- return NULL;
- }
+ return htab_create_alloc (size, hash_f, eq_f, del_f, xcalloc, free);
+}
- result->size = size;
- result->hash_f = hash_f;
- result->eq_f = eq_f;
- result->del_f = del_f;
- result->return_allocation_failure = 1;
- return result;
+htab_t
+htab_try_create (size, hash_f, eq_f, del_f)
+ size_t size;
+ htab_hash hash_f;
+ htab_eq eq_f;
+ htab_del del_f;
+{
+ return htab_create_alloc (size, hash_f, eq_f, del_f, calloc, free);
}
/* This function frees all memory allocated for given hash table.
@@ -229,8 +233,11 @@ htab_delete (htab)
&& htab->entries[i] != DELETED_ENTRY)
(*htab->del_f) (htab->entries[i]);
- free (htab->entries);
- free (htab);
+ if (htab->free_f != NULL)
+ {
+ (*htab->free_f) (htab->entries);
+ (*htab->free_f) (htab);
+ }
}
/* This function clears all entries in the given hash table. */
@@ -302,6 +309,7 @@ htab_expand (htab)
PTR *oentries;
PTR *olimit;
PTR *p;
+ PTR *nentries;
size_t nsize;
oentries = htab->entries;
@@ -309,17 +317,12 @@ htab_expand (htab)
nsize = higher_prime_number (htab->size * 2);
- if (htab->return_allocation_failure)
- {
- PTR *nentries = (PTR *) calloc (nsize, sizeof (PTR));
- if (nentries == NULL)
- return 0;
- htab->entries = nentries;
- }
- else
- htab->entries = (PTR *) xcalloc (nsize, sizeof (PTR));
-
+ nentries = (PTR *) (*htab->alloc_f) (nsize, sizeof (PTR));
+ if (nentries == NULL)
+ return 0;
+ htab->entries = nentries;
htab->size = nsize;
+
htab->n_elements -= htab->n_deleted;
htab->n_deleted = 0;
@@ -339,7 +342,8 @@ htab_expand (htab)
}
while (p < olimit);
- free (oentries);
+ if (htab->free_f != NULL)
+ (*htab->free_f) (oentries);
return 1;
}
diff --git a/contrib/gcc/hashtab.h b/contrib/gcc/hashtab.h
index 8871710..be866b5 100644
--- a/contrib/gcc/hashtab.h
+++ b/contrib/gcc/hashtab.h
@@ -1,5 +1,5 @@
/* An expandable hash tables datatype.
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
Contributed by Vladimir Makarov (vmakarov@cygnus.com).
This program is free software; you can redistribute it and/or modify
@@ -36,7 +36,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
extern "C" {
#endif /* __cplusplus */
-#include <ansidecl.h>
+#include "ansidecl.h"
+
+#ifndef GTY
+#define GTY(X)
+#endif
/* The type for a hash code. */
typedef unsigned int hashval_t;
@@ -63,12 +67,21 @@ typedef void (*htab_del) PARAMS ((void *));
htab_traverse. Return 1 to continue scan, 0 to stop. */
typedef int (*htab_trav) PARAMS ((void **, void *));
+/* Memory-allocation function, with the same functionality as calloc().
+ Iff it returns NULL, the hash table implementation will pass an error
+ code back to the user, so if your code doesn't handle errors,
+ best if you use xcalloc instead. */
+typedef PTR (*htab_alloc) PARAMS ((size_t, size_t));
+
+/* We also need a free() routine. */
+typedef void (*htab_free) PARAMS ((PTR));
+
/* Hash tables are of the following type. The structure
(implementation) of this type is not needed for using the hash
tables. All work with hash table should be executed only through
functions mentioned below. */
-struct htab
+struct htab GTY(())
{
/* Pointer to hash function. */
htab_hash hash_f;
@@ -80,7 +93,7 @@ struct htab
htab_del del_f;
/* Table itself. */
- PTR *entries;
+ PTR * GTY ((use_param (""), length ("%h.size"))) entries;
/* Current size (in entries) of the hash table */
size_t size;
@@ -99,9 +112,9 @@ struct htab
of collisions fixed for time of work with the hash table. */
unsigned int collisions;
- /* This is non-zero if we are allowed to return NULL for function calls
- that allocate memory. */
- int return_allocation_failure;
+ /* Pointers to allocate/free functions. */
+ htab_alloc alloc_f;
+ htab_free free_f;
};
typedef struct htab *htab_t;
@@ -111,14 +124,14 @@ enum insert_option {NO_INSERT, INSERT};
/* The prototypes of the package functions. */
-extern htab_t htab_create PARAMS ((size_t, htab_hash,
- htab_eq, htab_del));
+extern htab_t htab_create_alloc PARAMS ((size_t, htab_hash,
+ htab_eq, htab_del,
+ htab_alloc, htab_free));
+
+/* Backward-compatibility functions. */
+extern htab_t htab_create PARAMS ((size_t, htab_hash, htab_eq, htab_del));
+extern htab_t htab_try_create PARAMS ((size_t, htab_hash, htab_eq, htab_del));
-/* This function is like htab_create, but may return NULL if memory
- allocation fails, and also signals that htab_find_slot_with_hash and
- htab_find_slot are allowed to return NULL when inserting. */
-extern htab_t htab_try_create PARAMS ((size_t, htab_hash,
- htab_eq, htab_del));
extern void htab_delete PARAMS ((htab_t));
extern void htab_empty PARAMS ((htab_t));
diff --git a/contrib/gcc/hashtable.c b/contrib/gcc/hashtable.c
index bd2b137..ed1e81f 100644
--- a/contrib/gcc/hashtable.c
+++ b/contrib/gcc/hashtable.c
@@ -45,7 +45,7 @@ static void ht_expand PARAMS ((hash_table *));
#define OBSTACK_CHUNK_FREE free
#endif
-/* Initialise an obstack. */
+/* Initialize an obstack. */
void
gcc_obstack_init (obstack)
struct obstack *obstack;
@@ -141,7 +141,8 @@ ht_lookup (table, str, len, insert)
if (node == NULL)
break;
- if (HT_LEN (node) == len && !memcmp (HT_STR (node), str, len))
+ if (node->hash_value == hash && HT_LEN (node) == len
+ && !memcmp (HT_STR (node), str, len))
{
if (insert == HT_ALLOCED)
/* The string we search for was placed at the end of the
@@ -161,6 +162,7 @@ ht_lookup (table, str, len, insert)
table->entries[index] = node;
HT_LEN (node) = len;
+ node->hash_value = hash;
if (insert == HT_ALLOC)
HT_STR (node) = obstack_copy0 (&table->stack, str, len);
else
@@ -193,7 +195,7 @@ ht_expand (table)
{
unsigned int index, hash, hash2;
- hash = calc_hash (HT_STR (*p), HT_LEN (*p));
+ hash = (*p)->hash_value;
hash2 = ((hash * 17) & sizemask) | 1;
index = hash & sizemask;
diff --git a/contrib/gcc/hashtable.h b/contrib/gcc/hashtable.h
index cd6c7f0..0649ad2 100644
--- a/contrib/gcc/hashtable.h
+++ b/contrib/gcc/hashtable.h
@@ -23,10 +23,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This is what each hash table entry points to. It may be embedded
deeply within another object. */
typedef struct ht_identifier ht_identifier;
-struct ht_identifier
+struct ht_identifier GTY(())
{
- unsigned int len;
const unsigned char *str;
+ unsigned int len;
+ unsigned int hash_value;
};
#define HT_LEN(NODE) ((NODE)->len)
@@ -65,7 +66,7 @@ struct ht
extern void gcc_obstack_init PARAMS ((struct obstack *));
-/* Initialise the hashtable with 2 ^ order entries. */
+/* Initialize the hashtable with 2 ^ order entries. */
extern hash_table *ht_create PARAMS ((unsigned int order));
/* Frees all memory associated with a hash table. */
diff --git a/contrib/gcc/hex.c b/contrib/gcc/hex.c
index 3ba04ba..5f82292 100644
--- a/contrib/gcc/hex.c
+++ b/contrib/gcc/hex.c
@@ -20,11 +20,40 @@ Boston, MA 02111-1307, USA. */
#include <stdio.h> /* for EOF */
#include "libiberty.h"
-/* Provided for ABI compatibility. */
-void
-hex_init ()
-{
-}
+/*
+
+@deftypefn Extension void hex_init (void)
+
+Initializes the array mapping the current character set to
+corresponding hex values. This function must be called before any
+call to @code{hex_p} or @code{hex_value}. If you fail to call it, a
+default ASCII-based table will normally be used on ASCII systems.
+
+@end deftypefn
+
+@deftypefn Extension int hex_p (int @var{c})
+
+Evaluates to non-zero if the given character is a valid hex character,
+or zero if it is not. Note that the value you pass will be cast to
+@code{unsigned char} within the macro.
+
+@end deftypefn
+
+@deftypefn Extension int hex_value (int @var{c})
+
+Returns the numeric equivalent of the given character when interpreted
+as a hexidecimal digit. The result is undefined if you pass an
+invalid hex digit. Note that the value you pass will be cast to
+@code{unsigned char} within the macro.
+
+@end deftypefn
+
+@undocumented _hex_array_size
+@undocumented _hex_bad
+@undocumented _hex_value
+
+*/
+
/* Are we ASCII? */
#if '\n' == 0x0A && ' ' == 0x20 && '0' == 0x30 \
@@ -106,6 +135,46 @@ const char _hex_value[_hex_array_size] =
_hex_bad, _hex_bad, _hex_bad, _hex_bad,
_hex_bad, _hex_bad, _hex_bad, _hex_bad,
};
+#define HEX_TABLE_INITIALIZED
+
#else
- #error "Unsupported host character set"
+
+char _hex_value[_hex_array_size];
+
#endif /* not ASCII */
+
+void
+hex_init ()
+{
+#ifndef HEX_TABLE_INITIALIZED
+ int i;
+
+ for (i=0; i<_hex_array_size; i++)
+ {
+ switch (i)
+ {
+ case '0': _hex_value[i] = 0; break;
+ case '1': _hex_value[i] = 1; break;
+ case '2': _hex_value[i] = 2; break;
+ case '3': _hex_value[i] = 3; break;
+ case '4': _hex_value[i] = 4; break;
+ case '5': _hex_value[i] = 5; break;
+ case '6': _hex_value[i] = 6; break;
+ case '7': _hex_value[i] = 7; break;
+ case '8': _hex_value[i] = 8; break;
+ case '9': _hex_value[i] = 9; break;
+
+ case 'a': case 'A': _hex_value[i] = 10; break;
+ case 'b': case 'B': _hex_value[i] = 11; break;
+ case 'c': case 'C': _hex_value[i] = 12; break;
+ case 'd': case 'D': _hex_value[i] = 13; break;
+ case 'e': case 'E': _hex_value[i] = 14; break;
+ case 'f': case 'F': _hex_value[i] = 15; break;
+
+ default:
+ _hex_value[i] = _hex_bad;
+ break;
+ }
+ }
+#endif
+}
diff --git a/contrib/gcc/hooks.c b/contrib/gcc/hooks.c
index 2f71873..3f212ef 100644
--- a/contrib/gcc/hooks.c
+++ b/contrib/gcc/hooks.c
@@ -34,15 +34,90 @@ hook_void_void ()
/* Generic hook that takes no arguments and returns false. */
bool
-hook_void_bool_false ()
+hook_bool_void_false ()
{
return false;
}
-/* Generic hook that takes (tree) and returns false. */
+/* Generic hook that takes (tree, int) and does nothing. */
+void
+hook_void_tree_int (a, b)
+ tree a ATTRIBUTE_UNUSED;
+ int b ATTRIBUTE_UNUSED;
+{
+}
+
+/* Generic hook that takes (FILE *, const char *) and does nothing. */
+void
+hook_void_FILEptr_constcharptr (a, b)
+ FILE *a ATTRIBUTE_UNUSED;
+ const char *b ATTRIBUTE_UNUSED;
+{
+}
+
+/* Used for the TARGET_ASM_CAN_OUTPUT_MI_THUNK hook. */
+bool
+hook_bool_tree_hwi_hwi_tree_false (a, b, c, d)
+ tree a ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT b ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT c ATTRIBUTE_UNUSED;
+ tree d ATTRIBUTE_UNUSED;
+{
+ return false;
+}
+
+bool
+hook_bool_tree_hwi_hwi_tree_true (a, b, c, d)
+ tree a ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT b ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT c ATTRIBUTE_UNUSED;
+ tree d ATTRIBUTE_UNUSED;
+{
+ return true;
+}
+
+bool
+default_can_output_mi_thunk_no_vcall (a, b, c, d)
+ tree a ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT b ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT c;
+ tree d ATTRIBUTE_UNUSED;
+{
+ return c == 0;
+}
+
+/* ??? Used for comp_type_attributes, which ought to return bool. */
+int
+hook_int_tree_tree_1 (a, b)
+ tree a ATTRIBUTE_UNUSED;
+ tree b ATTRIBUTE_UNUSED;
+{
+ return 1;
+}
+
+void
+hook_void_tree (a)
+ tree a ATTRIBUTE_UNUSED;
+{
+}
+
+void
+hook_void_tree_treeptr (a, b)
+ tree a ATTRIBUTE_UNUSED;
+ tree *b ATTRIBUTE_UNUSED;
+{
+}
+
bool
-hook_tree_bool_false (a)
+hook_bool_tree_false (a)
tree a ATTRIBUTE_UNUSED;
{
return false;
}
+
+bool
+hook_bool_rtx_false (a)
+ rtx a ATTRIBUTE_UNUSED;
+{
+ return false;
+}
diff --git a/contrib/gcc/hooks.h b/contrib/gcc/hooks.h
index d91aca8..8c28194 100644
--- a/contrib/gcc/hooks.h
+++ b/contrib/gcc/hooks.h
@@ -22,8 +22,23 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef GCC_HOOKS_H
#define GCC_HOOKS_H
-bool hook_void_bool_false PARAMS ((void));
+bool hook_bool_void_false PARAMS ((void));
+bool hook_bool_tree_false PARAMS ((tree));
+bool hook_bool_tree_hwi_hwi_tree_false
+ PARAMS ((tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
+bool hook_bool_tree_hwi_hwi_tree_true
+ PARAMS ((tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
+bool hook_bool_rtx_false PARAMS ((rtx));
+
+void hook_void_tree_int PARAMS ((tree, int));
void hook_void_void PARAMS ((void));
-bool hook_tree_bool_false PARAMS ((tree));
+void hook_void_FILEptr_constcharptr PARAMS ((FILE *, const char *));
+void hook_void_tree PARAMS ((tree));
+void hook_void_tree_treeptr PARAMS ((tree, tree *));
+
+int hook_int_tree_tree_1 PARAMS ((tree, tree));
+
+bool default_can_output_mi_thunk_no_vcall
+ PARAMS ((tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));
#endif
diff --git a/contrib/gcc/hwint.h b/contrib/gcc/hwint.h
index 57d7edf..6d645a0 100644
--- a/contrib/gcc/hwint.h
+++ b/contrib/gcc/hwint.h
@@ -1,5 +1,5 @@
/* HOST_WIDE_INT definitions for the GNU compiler.
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -72,11 +72,17 @@
#ifndef HOST_WIDE_INT_PRINT_DEC
# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
# define HOST_WIDE_INT_PRINT_DEC "%d"
+# define HOST_WIDE_INT_PRINT_DEC_C "%d"
+# define HOST_WIDE_INT_PRINT_DEC_SPACE "% *d"
# else
# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
# define HOST_WIDE_INT_PRINT_DEC "%ld"
+# define HOST_WIDE_INT_PRINT_DEC_C "%ldL"
+# define HOST_WIDE_INT_PRINT_DEC_SPACE "% *ld"
# else
# define HOST_WIDE_INT_PRINT_DEC "%lld"
+# define HOST_WIDE_INT_PRINT_DEC_C "%lldLL"
+# define HOST_WIDE_INT_PRINT_DEC_SPACE "% *lld"
# endif
# endif
#endif /* ! HOST_WIDE_INT_PRINT_DEC */
@@ -84,11 +90,14 @@
#ifndef HOST_WIDE_INT_PRINT_UNSIGNED
# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
# define HOST_WIDE_INT_PRINT_UNSIGNED "%u"
+# define HOST_WIDE_INT_PRINT_UNSIGNED_SPACE "% *u"
# else
# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
# define HOST_WIDE_INT_PRINT_UNSIGNED "%lu"
+# define HOST_WIDE_INT_PRINT_UNSIGNED_SPACE "% *lu"
# else
# define HOST_WIDE_INT_PRINT_UNSIGNED "%llu"
+# define HOST_WIDE_INT_PRINT_UNSIGNED_SPACE "% *llu"
# endif
# endif
#endif /* ! HOST_WIDE_INT_PRINT_UNSIGNED */
@@ -139,13 +148,17 @@
# define HOST_BITS_PER_WIDEST_INT HOST_BITS_PER_LONGLONG
# define HOST_WIDEST_INT long long
# define HOST_WIDEST_INT_PRINT_DEC "%lld"
+# define HOST_WIDEST_INT_PRINT_DEC_SPACE "% *lld"
# define HOST_WIDEST_INT_PRINT_UNSIGNED "%llu"
+# define HOST_WIDEST_INT_PRINT_UNSIGNED_SPACE "% *llu"
# define HOST_WIDEST_INT_PRINT_HEX "0x%llx"
# else
# define HOST_BITS_PER_WIDEST_INT HOST_BITS_PER_LONG
# define HOST_WIDEST_INT long
# define HOST_WIDEST_INT_PRINT_DEC "%ld"
+# define HOST_WIDEST_INT_PRINT_DEC_SPACE "% *ld"
# define HOST_WIDEST_INT_PRINT_UNSIGNED "%lu"
+# define HOST_WIDEST_INT_PRINT_UNSIGNED_SPACE "% *lu"
# define HOST_WIDEST_INT_PRINT_HEX "0x%lx"
# endif /* long long wider than long */
#endif /* ! HOST_WIDEST_INT */
diff --git a/contrib/gcc/ifcvt.c b/contrib/gcc/ifcvt.c
index 166c59c..c336004 100644
--- a/contrib/gcc/ifcvt.c
+++ b/contrib/gcc/ifcvt.c
@@ -1,5 +1,5 @@
/* If-conversion support.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -73,53 +73,41 @@ static int num_updated_if_blocks;
/* # of basic blocks that were removed. */
static int num_removed_blocks;
+/* Whether conditional execution changes were made. */
+static int cond_exec_changed_p;
+
/* True if life data ok at present. */
static bool life_data_ok;
/* The post-dominator relation on the original block numbers. */
-static sbitmap *post_dominators;
+static dominance_info post_dominators;
/* Forward references. */
static int count_bb_insns PARAMS ((basic_block));
static rtx first_active_insn PARAMS ((basic_block));
-static int last_active_insn_p PARAMS ((basic_block, rtx));
+static rtx last_active_insn PARAMS ((basic_block, int));
static int seq_contains_jump PARAMS ((rtx));
-
-static int cond_exec_process_insns PARAMS ((rtx, rtx, rtx, rtx, int));
+static basic_block block_fallthru PARAMS ((basic_block));
+static int cond_exec_process_insns PARAMS ((ce_if_block_t *,
+ rtx, rtx, rtx, rtx, int));
static rtx cond_exec_get_condition PARAMS ((rtx));
-static int cond_exec_process_if_block PARAMS ((basic_block, basic_block,
- basic_block, basic_block));
-
+static int cond_exec_process_if_block PARAMS ((ce_if_block_t *, int));
static rtx noce_get_condition PARAMS ((rtx, rtx *));
static int noce_operand_ok PARAMS ((rtx));
-static int noce_process_if_block PARAMS ((basic_block, basic_block,
- basic_block, basic_block));
-
-static int process_if_block PARAMS ((basic_block, basic_block,
- basic_block, basic_block));
-static void merge_if_block PARAMS ((basic_block, basic_block,
- basic_block, basic_block));
-
-static int find_if_header PARAMS ((basic_block));
-static int find_if_block PARAMS ((basic_block, edge, edge));
+static int noce_process_if_block PARAMS ((ce_if_block_t *));
+static int process_if_block PARAMS ((ce_if_block_t *));
+static void merge_if_block PARAMS ((ce_if_block_t *));
+static int find_cond_trap PARAMS ((basic_block, edge, edge));
+static basic_block find_if_header PARAMS ((basic_block, int));
+static int block_jumps_and_fallthru_p PARAMS ((basic_block, basic_block));
+static int find_if_block PARAMS ((ce_if_block_t *));
static int find_if_case_1 PARAMS ((basic_block, edge, edge));
static int find_if_case_2 PARAMS ((basic_block, edge, edge));
-static int find_cond_trap PARAMS ((basic_block, edge, edge));
-static rtx block_has_only_trap PARAMS ((basic_block));
static int find_memory PARAMS ((rtx *, void *));
static int dead_or_predicable PARAMS ((basic_block, basic_block,
basic_block, basic_block, int));
static void noce_emit_move_insn PARAMS ((rtx, rtx));
-
-/* Abuse the basic_block AUX field to store the original block index,
- as well as a flag indicating that the block should be rescaned for
- life analysis. */
-
-#define SET_ORIG_INDEX(BB,I) ((BB)->aux = (void *)((size_t)(I) << 1))
-#define ORIG_INDEX(BB) ((size_t)(BB)->aux >> 1)
-#define SET_UPDATE_LIFE(BB) ((BB)->aux = (void *)((size_t)(BB)->aux | 1))
-#define UPDATE_LIFE(BB) ((size_t)(BB)->aux & 1)
-
+static rtx block_has_only_trap PARAMS ((basic_block));
/* Count the number of non-jump active insns in BB. */
@@ -171,22 +159,31 @@ first_active_insn (bb)
return insn;
}
-/* Return true if INSN is the last active non-jump insn in BB. */
+/* Return the last non-jump active (non-jump) insn in the basic block. */
-static int
-last_active_insn_p (bb, insn)
+static rtx
+last_active_insn (bb, skip_use_p)
basic_block bb;
- rtx insn;
+ int skip_use_p;
{
- do
+ rtx insn = bb->end;
+ rtx head = bb->head;
+
+ while (GET_CODE (insn) == NOTE
+ || GET_CODE (insn) == JUMP_INSN
+ || (skip_use_p
+ && GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == USE))
{
- if (insn == bb->end)
- return TRUE;
- insn = NEXT_INSN (insn);
+ if (insn == head)
+ return NULL_RTX;
+ insn = PREV_INSN (insn);
}
- while (GET_CODE (insn) == NOTE);
- return GET_CODE (insn) == JUMP_INSN;
+ if (GET_CODE (insn) == CODE_LABEL)
+ return NULL_RTX;
+
+ return insn;
}
/* It is possible, especially when having dealt with multi-word
@@ -206,13 +203,28 @@ seq_contains_jump (insn)
}
return 0;
}
+
+static basic_block
+block_fallthru (bb)
+ basic_block bb;
+{
+ edge e;
+
+ for (e = bb->succ;
+ e != NULL_EDGE && (e->flags & EDGE_FALLTHRU) == 0;
+ e = e->succ_next)
+ ;
+
+ return (e) ? e->dest : NULL_BLOCK;
+}
/* Go through a bunch of insns, converting them to conditional
execution format if possible. Return TRUE if all of the non-note
insns were processed. */
static int
-cond_exec_process_insns (start, end, test, prob_val, mod_ok)
+cond_exec_process_insns (ce_info, start, end, test, prob_val, mod_ok)
+ ce_if_block_t *ce_info ATTRIBUTE_UNUSED; /* if block information */
rtx start; /* first insn to look at */
rtx end; /* last insn to look at */
rtx test; /* conditional execution test */
@@ -221,8 +233,12 @@ cond_exec_process_insns (start, end, test, prob_val, mod_ok)
{
int must_be_last = FALSE;
rtx insn;
+ rtx xtest;
rtx pattern;
+ if (!start || !end)
+ return FALSE;
+
for (insn = start; ; insn = NEXT_INSN (insn))
{
if (GET_CODE (insn) == NOTE)
@@ -255,19 +271,32 @@ cond_exec_process_insns (start, end, test, prob_val, mod_ok)
/* Now build the conditional form of the instruction. */
pattern = PATTERN (insn);
+ xtest = copy_rtx (test);
+
+ /* If this is already a COND_EXEC, rewrite the test to be an AND of the
+ two conditions. */
+ if (GET_CODE (pattern) == COND_EXEC)
+ {
+ if (GET_MODE (xtest) != GET_MODE (COND_EXEC_TEST (pattern)))
+ return FALSE;
+
+ xtest = gen_rtx_AND (GET_MODE (xtest), xtest,
+ COND_EXEC_TEST (pattern));
+ pattern = COND_EXEC_CODE (pattern);
+ }
+
+ pattern = gen_rtx_COND_EXEC (VOIDmode, xtest, pattern);
/* If the machine needs to modify the insn being conditionally executed,
say for example to force a constant integer operand into a temp
register, do so here. */
#ifdef IFCVT_MODIFY_INSN
- IFCVT_MODIFY_INSN (pattern, insn);
+ IFCVT_MODIFY_INSN (ce_info, pattern, insn);
if (! pattern)
return FALSE;
#endif
- validate_change (insn, &PATTERN (insn),
- gen_rtx_COND_EXEC (VOIDmode, copy_rtx (test),
- pattern), 1);
+ validate_change (insn, &PATTERN (insn), pattern, 1);
if (GET_CODE (insn) == CALL_INSN && prob_val)
validate_change (insn, &REG_NOTES (insn),
@@ -314,15 +343,16 @@ cond_exec_get_condition (jump)
/* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it
to conditional execution. Return TRUE if we were successful at
- converting the the block. */
+ converting the block. */
static int
-cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
- basic_block test_bb; /* Basic block test is in */
- basic_block then_bb; /* Basic block for THEN block */
- basic_block else_bb; /* Basic block for ELSE block */
- basic_block join_bb; /* Basic block the join label is in */
+cond_exec_process_if_block (ce_info, do_multiple_p)
+ ce_if_block_t * ce_info; /* if block information */
+ int do_multiple_p; /* != 0 if we should handle && and || blocks */
{
+ basic_block test_bb = ce_info->test_bb; /* last test block */
+ basic_block then_bb = ce_info->then_bb; /* THEN */
+ basic_block else_bb = ce_info->else_bb; /* ELSE or NULL */
rtx test_expr; /* expression in IF_THEN_ELSE that is tested */
rtx then_start; /* first insn in THEN block */
rtx then_end; /* last insn + 1 in THEN block */
@@ -337,6 +367,20 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
int n_insns;
enum rtx_code false_code;
+ /* If test is comprised of && or || elements, and we've failed at handling
+ all of them together, just use the last test if it is the special case of
+ && elements without an ELSE block. */
+ if (!do_multiple_p && ce_info->num_multiple_test_blocks)
+ {
+ if (else_bb || ! ce_info->and_and_p)
+ return FALSE;
+
+ ce_info->test_bb = test_bb = ce_info->last_test_bb;
+ ce_info->num_multiple_test_blocks = 0;
+ ce_info->num_and_and_blocks = 0;
+ ce_info->num_or_or_blocks = 0;
+ }
+
/* Find the conditional jump to the ELSE or JOIN part, and isolate
the test. */
test_expr = cond_exec_get_condition (test_bb->end);
@@ -345,51 +389,25 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
/* If the conditional jump is more than just a conditional jump,
then we can not do conditional execution conversion on this block. */
- if (!onlyjump_p (test_bb->end))
+ if (! onlyjump_p (test_bb->end))
return FALSE;
- /* Collect the bounds of where we're to search. */
-
- then_start = then_bb->head;
- then_end = then_bb->end;
-
- /* Skip a label heading THEN block. */
- if (GET_CODE (then_start) == CODE_LABEL)
- then_start = NEXT_INSN (then_start);
-
- /* Skip a (use (const_int 0)) or branch as the final insn. */
- if (GET_CODE (then_end) == INSN
- && GET_CODE (PATTERN (then_end)) == USE
- && GET_CODE (XEXP (PATTERN (then_end), 0)) == CONST_INT)
- then_end = PREV_INSN (then_end);
- else if (GET_CODE (then_end) == JUMP_INSN)
- then_end = PREV_INSN (then_end);
+ /* Collect the bounds of where we're to search, skipping any labels, jumps
+ and notes at the beginning and end of the block. Then count the total
+ number of insns and see if it is small enough to convert. */
+ then_start = first_active_insn (then_bb);
+ then_end = last_active_insn (then_bb, TRUE);
+ n_insns = ce_info->num_then_insns = count_bb_insns (then_bb);
+ max = MAX_CONDITIONAL_EXECUTE;
if (else_bb)
{
- /* Skip the ELSE block's label. */
- else_start = NEXT_INSN (else_bb->head);
- else_end = else_bb->end;
-
- /* Skip a (use (const_int 0)) or branch as the final insn. */
- if (GET_CODE (else_end) == INSN
- && GET_CODE (PATTERN (else_end)) == USE
- && GET_CODE (XEXP (PATTERN (else_end), 0)) == CONST_INT)
- else_end = PREV_INSN (else_end);
- else if (GET_CODE (else_end) == JUMP_INSN)
- else_end = PREV_INSN (else_end);
+ max *= 2;
+ else_start = first_active_insn (else_bb);
+ else_end = last_active_insn (else_bb, TRUE);
+ n_insns += ce_info->num_else_insns = count_bb_insns (else_bb);
}
- /* How many instructions should we convert in total? */
- n_insns = 0;
- if (else_bb)
- {
- max = 2 * MAX_CONDITIONAL_EXECUTE;
- n_insns = count_bb_insns (else_bb);
- }
- else
- max = MAX_CONDITIONAL_EXECUTE;
- n_insns += count_bb_insns (then_bb);
if (n_insns > max)
return FALSE;
@@ -408,8 +426,7 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
#ifdef IFCVT_MODIFY_TESTS
/* If the machine description needs to modify the tests, such as setting a
conditional execution register from a comparison, it can do so here. */
- IFCVT_MODIFY_TESTS (true_expr, false_expr, test_bb, then_bb, else_bb,
- join_bb);
+ IFCVT_MODIFY_TESTS (ce_info, true_expr, false_expr);
/* See if the conversion failed */
if (!true_expr || !false_expr)
@@ -425,6 +442,72 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
else
false_prob_val = NULL_RTX;
+ /* If we have && or || tests, do them here. These tests are in the adjacent
+ blocks after the first block containing the test. */
+ if (ce_info->num_multiple_test_blocks > 0)
+ {
+ basic_block bb = test_bb;
+ basic_block last_test_bb = ce_info->last_test_bb;
+
+ if (! false_expr)
+ goto fail;
+
+ do
+ {
+ rtx start, end;
+ rtx t, f;
+
+ bb = block_fallthru (bb);
+ start = first_active_insn (bb);
+ end = last_active_insn (bb, TRUE);
+ if (start
+ && ! cond_exec_process_insns (ce_info, start, end, false_expr,
+ false_prob_val, FALSE))
+ goto fail;
+
+ /* If the conditional jump is more than just a conditional jump, then
+ we can not do conditional execution conversion on this block. */
+ if (! onlyjump_p (bb->end))
+ goto fail;
+
+ /* Find the conditional jump and isolate the test. */
+ t = cond_exec_get_condition (bb->end);
+ if (! t)
+ goto fail;
+
+ f = gen_rtx_fmt_ee (reverse_condition (GET_CODE (t)),
+ GET_MODE (t),
+ XEXP (t, 0),
+ XEXP (t, 1));
+
+ if (ce_info->and_and_p)
+ {
+ t = gen_rtx_AND (GET_MODE (t), true_expr, t);
+ f = gen_rtx_IOR (GET_MODE (t), false_expr, f);
+ }
+ else
+ {
+ t = gen_rtx_IOR (GET_MODE (t), true_expr, t);
+ f = gen_rtx_AND (GET_MODE (t), false_expr, f);
+ }
+
+ /* If the machine description needs to modify the tests, such as
+ setting a conditional execution register from a comparison, it can
+ do so here. */
+#ifdef IFCVT_MODIFY_MULTIPLE_TESTS
+ IFCVT_MODIFY_MULTIPLE_TESTS (ce_info, bb, t, f);
+
+ /* See if the conversion failed */
+ if (!t || !f)
+ goto fail;
+#endif
+
+ true_expr = t;
+ false_expr = f;
+ }
+ while (bb != last_test_bb);
+ }
+
/* For IF-THEN-ELSE blocks, we don't allow modifications of the test
on then THEN block. */
then_mod_ok = (else_bb == NULL_BLOCK);
@@ -434,21 +517,30 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
if (then_end
&& (! false_expr
- || ! cond_exec_process_insns (then_start, then_end, false_expr,
- false_prob_val, then_mod_ok)))
+ || ! cond_exec_process_insns (ce_info, then_start, then_end,
+ false_expr, false_prob_val,
+ then_mod_ok)))
goto fail;
- if (else_bb
- && ! cond_exec_process_insns (else_start, else_end,
+ if (else_bb && else_end
+ && ! cond_exec_process_insns (ce_info, else_start, else_end,
true_expr, true_prob_val, TRUE))
goto fail;
+ /* If we cannot apply the changes, fail. Do not go through the normal fail
+ processing, since apply_change_group will call cancel_changes. */
if (! apply_change_group ())
- return FALSE;
+ {
+#ifdef IFCVT_MODIFY_CANCEL
+ /* Cancel any machine dependent changes. */
+ IFCVT_MODIFY_CANCEL (ce_info);
+#endif
+ return FALSE;
+ }
#ifdef IFCVT_MODIFY_FINAL
/* Do any machine dependent final modifications */
- IFCVT_MODIFY_FINAL (test_bb, then_bb, else_bb, join_bb);
+ IFCVT_MODIFY_FINAL (ce_info);
#endif
/* Conversion succeeded. */
@@ -457,13 +549,14 @@ cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb)
n_insns, (n_insns == 1) ? " was" : "s were");
/* Merge the blocks! */
- merge_if_block (test_bb, then_bb, else_bb, join_bb);
+ merge_if_block (ce_info);
+ cond_exec_changed_p = TRUE;
return TRUE;
fail:
#ifdef IFCVT_MODIFY_CANCEL
/* Cancel any machine dependent changes. */
- IFCVT_MODIFY_CANCEL (test_bb, then_bb, else_bb, join_bb);
+ IFCVT_MODIFY_CANCEL (ce_info);
#endif
cancel_changes (0);
@@ -542,7 +635,7 @@ noce_emit_store_flag (if_info, x, reversep, normalize)
{
tmp = get_insns ();
end_sequence ();
- emit_insns (tmp);
+ emit_insn (tmp);
if_info->cond_earliest = if_info->jump;
@@ -552,8 +645,8 @@ noce_emit_store_flag (if_info, x, reversep, normalize)
end_sequence ();
}
- /* Don't even try if the comparison operands are weird. */
- if (cond_complex)
+ /* Don't even try if the comparison operands or the mode of X are weird. */
+ if (cond_complex || !SCALAR_INT_MODE_P (GET_MODE (x)))
return NULL_RTX;
return emit_store_flag (x, code, XEXP (cond, 0),
@@ -622,7 +715,7 @@ noce_try_store_flag (if_info)
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, if_info->jump);
+ emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
return TRUE;
}
@@ -757,7 +850,7 @@ noce_try_store_flag_constants (if_info)
if (seq_contains_jump (seq))
return FALSE;
- emit_insns_before (seq, if_info->jump);
+ emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
return TRUE;
}
@@ -817,7 +910,8 @@ noce_try_store_flag_inc (if_info)
if (seq_contains_jump (seq))
return FALSE;
- emit_insns_before (seq, if_info->jump);
+ emit_insn_before_scope (seq, if_info->jump,
+ INSN_SCOPE (if_info->insn_a));
return TRUE;
}
@@ -869,7 +963,8 @@ noce_try_store_flag_mask (if_info)
if (seq_contains_jump (seq))
return FALSE;
- emit_insns_before (seq, if_info->jump);
+ emit_insn_before_scope (seq, if_info->jump,
+ INSN_SCOPE (if_info->insn_a));
return TRUE;
}
@@ -908,7 +1003,7 @@ noce_emit_cmove (if_info, x, code, cmp_a, cmp_b, vfalse, vtrue)
{
tmp = get_insns ();
end_sequence ();
- emit_insns (tmp);
+ emit_insn (tmp);
return x;
}
@@ -964,7 +1059,8 @@ noce_try_cmove (if_info)
seq = get_insns ();
end_sequence ();
- emit_insns_before (seq, if_info->jump);
+ emit_insn_before_scope (seq, if_info->jump,
+ INSN_SCOPE (if_info->insn_a));
return TRUE;
}
else
@@ -1082,7 +1178,16 @@ noce_try_cmove_arith (if_info)
tmp = gen_reg_rtx (GET_MODE (b));
tmp = emit_insn (gen_rtx_SET (VOIDmode, tmp, b));
}
- else if (! insn_b)
+ else if (! insn_b
+#if 0
+ /* In the case we are going to duplicate insn originally
+ present in the front of comparsion, verify that the
+ comparsion didn't clobbered the operands. */
+ || modified_between_p (SET_SRC (single_set (insn_b)),
+ if_info->cond_earliest,
+ NEXT_INSN (if_info->jump)))
+#endif
+ )
goto end_seq_and_fail;
else
{
@@ -1126,7 +1231,7 @@ noce_try_cmove_arith (if_info)
tmp = get_insns ();
end_sequence ();
- emit_insns_before (tmp, if_info->jump);
+ emit_insn_before_scope (tmp, if_info->jump, INSN_SCOPE (if_info->insn_a));
return TRUE;
end_seq_and_fail:
@@ -1272,7 +1377,7 @@ noce_get_alt_condition (if_info, target, earliest)
/* X may not be mentioned in the range (cond_earliest, jump]. */
for (insn = if_info->jump; insn != *earliest; insn = PREV_INSN (insn))
- if (INSN_P (insn) && reg_mentioned_p (if_info->x, insn))
+ if (INSN_P (insn) && reg_overlap_mentioned_p (if_info->x, PATTERN (insn)))
return NULL;
/* A and B may not be modified in the range [cond_earliest, jump). */
@@ -1299,12 +1404,11 @@ noce_try_minmax (if_info)
if (no_new_pseudos)
return FALSE;
- /* ??? Reject FP modes since we don't know how 0 vs -0 or NaNs
- will be resolved with an SMIN/SMAX. It wouldn't be too hard
+ /* ??? Reject modes with NaNs or signed zeros since we don't know how
+ they will be resolved with an SMIN/SMAX. It wouldn't be too hard
to get the target to tell us... */
- if (FLOAT_MODE_P (GET_MODE (if_info->x))
- && TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
- && ! flag_unsafe_math_optimizations)
+ if (HONOR_SIGNED_ZEROS (GET_MODE (if_info->x))
+ || HONOR_NANS (GET_MODE (if_info->x)))
return FALSE;
cond = noce_get_alt_condition (if_info, if_info->a, &earliest);
@@ -1379,7 +1483,7 @@ noce_try_minmax (if_info)
if (seq_contains_jump (seq))
return FALSE;
- emit_insns_before (seq, if_info->jump);
+ emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
if_info->cond = cond;
if_info->cond_earliest = earliest;
@@ -1497,7 +1601,7 @@ noce_try_abs (if_info)
if (seq_contains_jump (seq))
return FALSE;
- emit_insns_before (seq, if_info->jump);
+ emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
if_info->cond = cond;
if_info->cond_earliest = earliest;
@@ -1587,49 +1691,26 @@ noce_operand_ok (op)
if (side_effects_p (op))
return FALSE;
- /* ??? Unfortuantely may_trap_p can't look at flag_trapping_math, due to
- being linked into the genfoo programs. This is probably a mistake.
- With finite operands, most fp operations don't trap. */
- if (!flag_trapping_math && FLOAT_MODE_P (GET_MODE (op)))
- switch (GET_CODE (op))
- {
- case DIV:
- case MOD:
- case UDIV:
- case UMOD:
- /* ??? This is kinda lame -- almost every target will have forced
- the constant into a register first. But given the expense of
- division, this is probably for the best. */
- return (CONSTANT_P (XEXP (op, 1))
- && XEXP (op, 1) != CONST0_RTX (GET_MODE (op))
- && ! may_trap_p (XEXP (op, 0)));
-
- default:
- switch (GET_RTX_CLASS (GET_CODE (op)))
- {
- case '1':
- return ! may_trap_p (XEXP (op, 0));
- case 'c':
- case '2':
- return ! may_trap_p (XEXP (op, 0)) && ! may_trap_p (XEXP (op, 1));
- }
- break;
- }
-
return ! may_trap_p (op);
}
/* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it
without using conditional execution. Return TRUE if we were
- successful at converting the the block. */
+ successful at converting the block. */
static int
-noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
- basic_block test_bb; /* Basic block test is in */
- basic_block then_bb; /* Basic block for THEN block */
- basic_block else_bb; /* Basic block for ELSE block */
- basic_block join_bb; /* Basic block the join label is in */
+noce_process_if_block (ce_info)
+ struct ce_if_block * ce_info;
{
+ basic_block test_bb = ce_info->test_bb; /* test block */
+ basic_block then_bb = ce_info->then_bb; /* THEN */
+ basic_block else_bb = ce_info->else_bb; /* ELSE or NULL */
+ struct noce_if_info if_info;
+ rtx insn_a, insn_b;
+ rtx set_a, set_b;
+ rtx orig_x, x, a, b;
+ rtx jump, cond;
+
/* We're looking for patterns of the form
(1) if (...) x = a; else x = b;
@@ -1640,11 +1721,18 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
??? For future expansion, look for multiple X in such patterns. */
- struct noce_if_info if_info;
- rtx insn_a, insn_b;
- rtx set_a, set_b;
- rtx orig_x, x, a, b;
- rtx jump, cond, insn;
+ /* If test is comprised of && or || elements, don't handle it unless it is
+ the special case of && elements without an ELSE block. */
+ if (ce_info->num_multiple_test_blocks)
+ {
+ if (else_bb || ! ce_info->and_and_p)
+ return FALSE;
+
+ ce_info->test_bb = test_bb = ce_info->last_test_bb;
+ ce_info->num_multiple_test_blocks = 0;
+ ce_info->num_and_and_blocks = 0;
+ ce_info->num_or_or_blocks = 0;
+ }
/* If this is not a standard conditional jump, we can't parse it. */
jump = test_bb->end;
@@ -1652,8 +1740,8 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
if (! cond)
return FALSE;
- /* If the conditional jump is more than just a conditional jump,
- then we can not do if-conversion on this block. */
+ /* If the conditional jump is more than just a conditional
+ jump, then we can not do if-conversion on this block. */
if (! onlyjump_p (jump))
return FALSE;
@@ -1664,7 +1752,7 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
/* Look for one of the potential sets. */
insn_a = first_active_insn (then_bb);
if (! insn_a
- || ! last_active_insn_p (then_bb, insn_a)
+ || insn_a != last_active_insn (then_bb, FALSE)
|| (set_a = single_set (insn_a)) == NULL_RTX)
return FALSE;
@@ -1683,7 +1771,7 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
{
insn_b = first_active_insn (else_bb);
if (! insn_b
- || ! last_active_insn_p (else_bb, insn_b)
+ || insn_b != last_active_insn (else_bb, FALSE)
|| (set_b = single_set (insn_b)) == NULL_RTX
|| ! rtx_equal_p (x, SET_DEST (set_b)))
return FALSE;
@@ -1691,27 +1779,34 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
else
{
insn_b = prev_nonnote_insn (if_info.cond_earliest);
+ /* We're going to be moving the evaluation of B down from above
+ COND_EARLIEST to JUMP. Make sure the relevant data is still
+ intact. */
if (! insn_b
|| GET_CODE (insn_b) != INSN
|| (set_b = single_set (insn_b)) == NULL_RTX
|| ! rtx_equal_p (x, SET_DEST (set_b))
- || reg_mentioned_p (x, cond)
- || reg_mentioned_p (x, a)
- || reg_mentioned_p (x, SET_SRC (set_b)))
+ || reg_overlap_mentioned_p (x, SET_SRC (set_b))
+ || modified_between_p (SET_SRC (set_b),
+ PREV_INSN (if_info.cond_earliest), jump)
+ /* Likewise with X. In particular this can happen when
+ noce_get_condition looks farther back in the instruction
+ stream than one might expect. */
+ || reg_overlap_mentioned_p (x, cond)
+ || reg_overlap_mentioned_p (x, a)
+ || modified_between_p (x, PREV_INSN (if_info.cond_earliest), jump))
insn_b = set_b = NULL_RTX;
}
- b = (set_b ? SET_SRC (set_b) : x);
- /* X may not be mentioned in the range (cond_earliest, jump]. */
- for (insn = jump; insn != if_info.cond_earliest; insn = PREV_INSN (insn))
- if (INSN_P (insn) && reg_mentioned_p (x, insn))
- return FALSE;
+ /* If x has side effects then only the if-then-else form is safe to
+ convert. But even in that case we would need to restore any notes
+ (such as REG_INC) at then end. That can be tricky if
+ noce_emit_move_insn expands to more than one insn, so disable the
+ optimization entirely for now if there are side effects. */
+ if (side_effects_p (x))
+ return FALSE;
- /* A and B may not be modified in the range [cond_earliest, jump). */
- for (insn = if_info.cond_earliest; insn != jump; insn = NEXT_INSN (insn))
- if (INSN_P (insn)
- && (modified_in_p (a, insn) || modified_in_p (b, insn)))
- return FALSE;
+ b = (set_b ? SET_SRC (set_b) : x);
/* Only operate on register destinations, and even then avoid extending
the lifetime of hard registers on small register class machines. */
@@ -1758,7 +1853,7 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
if (else_bb && insn_b == else_bb->end)
else_bb->end = PREV_INSN (insn_b);
- reorder_insns (insn_b, insn_b, PREV_INSN (if_info.cond_earliest));
+ reorder_insns (insn_b, insn_b, PREV_INSN (jump));
/* If there was a REG_EQUAL note, delete it since it may have been
true due to this insn being after a jump. */
@@ -1813,9 +1908,9 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
if (insn_b && else_bb)
delete_insn (insn_b);
- /* The new insns will have been inserted just before the jump. We should
- be able to remove the jump with impunity, but the condition itself may
- have been modified by gcse to be shared across basic blocks. */
+ /* The new insns will have been inserted immediately before the jump. We
+ should be able to remove the jump with impunity, but the condition itself
+ may have been modified by gcse to be shared across basic blocks. */
delete_insn (jump);
/* If we used a temporary, fix it up now. */
@@ -1823,14 +1918,14 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
{
start_sequence ();
noce_emit_move_insn (copy_rtx (orig_x), x);
- insn_b = gen_sequence ();
+ insn_b = get_insns ();
end_sequence ();
- emit_insn_after (insn_b, test_bb->end);
+ emit_insn_after_scope (insn_b, test_bb->end, INSN_SCOPE (insn_a));
}
/* Merge the blocks! */
- merge_if_block (test_bb, then_bb, else_bb, join_bb);
+ merge_if_block (ce_info);
return TRUE;
}
@@ -1839,20 +1934,30 @@ noce_process_if_block (test_bb, then_bb, else_bb, join_bb)
straight line code. Return true if successful. */
static int
-process_if_block (test_bb, then_bb, else_bb, join_bb)
- basic_block test_bb; /* Basic block test is in */
- basic_block then_bb; /* Basic block for THEN block */
- basic_block else_bb; /* Basic block for ELSE block */
- basic_block join_bb; /* Basic block the join label is in */
+process_if_block (ce_info)
+ struct ce_if_block * ce_info;
{
if (! reload_completed
- && noce_process_if_block (test_bb, then_bb, else_bb, join_bb))
+ && noce_process_if_block (ce_info))
return TRUE;
- if (HAVE_conditional_execution
- && reload_completed
- && cond_exec_process_if_block (test_bb, then_bb, else_bb, join_bb))
- return TRUE;
+ if (HAVE_conditional_execution && reload_completed)
+ {
+ /* If we have && and || tests, try to first handle combining the && and
+ || tests into the conditional code, and if that fails, go back and
+ handle it without the && and ||, which at present handles the && case
+ if there was no ELSE block. */
+ if (cond_exec_process_if_block (ce_info, TRUE))
+ return TRUE;
+
+ if (ce_info->num_multiple_test_blocks)
+ {
+ cancel_changes (0);
+
+ if (cond_exec_process_if_block (ce_info, FALSE))
+ return TRUE;
+ }
+ }
return FALSE;
}
@@ -1860,25 +1965,50 @@ process_if_block (test_bb, then_bb, else_bb, join_bb)
/* Merge the blocks and mark for local life update. */
static void
-merge_if_block (test_bb, then_bb, else_bb, join_bb)
- basic_block test_bb; /* Basic block test is in */
- basic_block then_bb; /* Basic block for THEN block */
- basic_block else_bb; /* Basic block for ELSE block */
- basic_block join_bb; /* Basic block the join label is in */
+merge_if_block (ce_info)
+ struct ce_if_block * ce_info;
{
+ basic_block test_bb = ce_info->test_bb; /* last test block */
+ basic_block then_bb = ce_info->then_bb; /* THEN */
+ basic_block else_bb = ce_info->else_bb; /* ELSE or NULL */
+ basic_block join_bb = ce_info->join_bb; /* join block */
basic_block combo_bb;
/* All block merging is done into the lower block numbers. */
combo_bb = test_bb;
- /* First merge TEST block into THEN block. This is a no-brainer since
- the THEN block did not have a code label to begin with. */
+ /* Merge any basic blocks to handle && and || subtests. Each of
+ the blocks are on the fallthru path from the predecessor block. */
+ if (ce_info->num_multiple_test_blocks > 0)
+ {
+ basic_block bb = test_bb;
+ basic_block last_test_bb = ce_info->last_test_bb;
+ basic_block fallthru = block_fallthru (bb);
+
+ do
+ {
+ bb = fallthru;
+ fallthru = block_fallthru (bb);
+ if (post_dominators)
+ delete_from_dominance_info (post_dominators, bb);
+ merge_blocks_nomove (combo_bb, bb);
+ num_removed_blocks++;
+ }
+ while (bb != last_test_bb);
+ }
+
+ /* Merge TEST block into THEN block. Normally the THEN block won't have a
+ label, but it might if there were || tests. That label's count should be
+ zero, and it normally should be removed. */
+
if (then_bb)
{
- if (life_data_ok)
- COPY_REG_SET (combo_bb->global_live_at_end,
+ if (combo_bb->global_live_at_end)
+ COPY_REG_SET (combo_bb->global_live_at_end,
then_bb->global_live_at_end);
+ if (post_dominators)
+ delete_from_dominance_info (post_dominators, then_bb);
merge_blocks_nomove (combo_bb, then_bb);
num_removed_blocks++;
}
@@ -1888,6 +2018,8 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
get their addresses taken. */
if (else_bb)
{
+ if (post_dominators)
+ delete_from_dominance_info (post_dominators, else_bb);
merge_blocks_nomove (combo_bb, else_bb);
num_removed_blocks++;
}
@@ -1939,9 +2071,12 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
&& join_bb != EXIT_BLOCK_PTR)
{
/* We can merge the JOIN. */
- if (life_data_ok)
+ if (combo_bb->global_live_at_end)
COPY_REG_SET (combo_bb->global_live_at_end,
join_bb->global_live_at_end);
+
+ if (post_dominators)
+ delete_from_dominance_info (post_dominators, join_bb);
merge_blocks_nomove (combo_bb, join_bb);
num_removed_blocks++;
}
@@ -1957,22 +2092,23 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
/* Remove the jump and cruft from the end of the COMBO block. */
if (join_bb != EXIT_BLOCK_PTR)
- tidy_fallthru_edge (combo_bb->succ, combo_bb, join_bb);
+ tidy_fallthru_edge (combo_bb->succ, combo_bb, join_bb);
}
- /* Make sure we update life info properly. */
- SET_UPDATE_LIFE (combo_bb);
-
num_updated_if_blocks++;
}
-/* Find a block ending in a simple IF condition. Return TRUE if
- we were able to transform it in some way. */
+/* Find a block ending in a simple IF condition and try to transform it
+ in some way. When converting a multi-block condition, put the new code
+ in the first such block and delete the rest. Return a pointer to this
+ first block if some transformation was done. Return NULL otherwise. */
-static int
-find_if_header (test_bb)
+static basic_block
+find_if_header (test_bb, pass)
basic_block test_bb;
+ int pass;
{
+ ce_if_block_t ce_info;
edge then_edge;
edge else_edge;
@@ -1980,12 +2116,12 @@ find_if_header (test_bb)
if ((then_edge = test_bb->succ) == NULL_EDGE
|| (else_edge = then_edge->succ_next) == NULL_EDGE
|| else_edge->succ_next != NULL_EDGE)
- return FALSE;
+ return NULL;
/* Neither edge should be abnormal. */
if ((then_edge->flags & EDGE_COMPLEX)
|| (else_edge->flags & EDGE_COMPLEX))
- return FALSE;
+ return NULL;
/* The THEN edge is canonically the one that falls through. */
if (then_edge->flags & EDGE_FALLTHRU)
@@ -1998,13 +2134,25 @@ find_if_header (test_bb)
}
else
/* Otherwise this must be a multiway branch of some sort. */
- return FALSE;
+ return NULL;
+
+ memset ((PTR) &ce_info, '\0', sizeof (ce_info));
+ ce_info.test_bb = test_bb;
+ ce_info.then_bb = then_edge->dest;
+ ce_info.else_bb = else_edge->dest;
+ ce_info.pass = pass;
+
+#ifdef IFCVT_INIT_EXTRA_FIELDS
+ IFCVT_INIT_EXTRA_FIELDS (&ce_info);
+#endif
- if (find_if_block (test_bb, then_edge, else_edge))
+ if (find_if_block (&ce_info))
goto success;
+
if (HAVE_trap && HAVE_conditional_trap
&& find_cond_trap (test_bb, then_edge, else_edge))
goto success;
+
if (post_dominators
&& (! HAVE_conditional_execution || reload_completed))
{
@@ -2014,38 +2162,197 @@ find_if_header (test_bb)
goto success;
}
- return FALSE;
+ return NULL;
success:
if (rtl_dump_file)
- fprintf (rtl_dump_file, "Conversion succeeded.\n");
- return TRUE;
+ fprintf (rtl_dump_file, "Conversion succeeded on pass %d.\n", pass);
+ return ce_info.test_bb;
+}
+
+/* Return true if a block has two edges, one of which falls through to the next
+ block, and the other jumps to a specific block, so that we can tell if the
+ block is part of an && test or an || test. Returns either -1 or the number
+ of non-note, non-jump, non-USE/CLOBBER insns in the block. */
+
+static int
+block_jumps_and_fallthru_p (cur_bb, target_bb)
+ basic_block cur_bb;
+ basic_block target_bb;
+{
+ edge cur_edge;
+ int fallthru_p = FALSE;
+ int jump_p = FALSE;
+ rtx insn;
+ rtx end;
+ int n_insns = 0;
+
+ if (!cur_bb || !target_bb)
+ return -1;
+
+ /* If no edges, obviously it doesn't jump or fallthru. */
+ if (cur_bb->succ == NULL_EDGE)
+ return FALSE;
+
+ for (cur_edge = cur_bb->succ;
+ cur_edge != NULL_EDGE;
+ cur_edge = cur_edge->succ_next)
+ {
+ if (cur_edge->flags & EDGE_COMPLEX)
+ /* Anything complex isn't what we want. */
+ return -1;
+
+ else if (cur_edge->flags & EDGE_FALLTHRU)
+ fallthru_p = TRUE;
+
+ else if (cur_edge->dest == target_bb)
+ jump_p = TRUE;
+
+ else
+ return -1;
+ }
+
+ if ((jump_p & fallthru_p) == 0)
+ return -1;
+
+ /* Don't allow calls in the block, since this is used to group && and ||
+ together for conditional execution support. ??? we should support
+ conditional execution support across calls for IA-64 some day, but
+ for now it makes the code simpler. */
+ end = cur_bb->end;
+ insn = cur_bb->head;
+
+ while (insn != NULL_RTX)
+ {
+ if (GET_CODE (insn) == CALL_INSN)
+ return -1;
+
+ if (INSN_P (insn)
+ && GET_CODE (insn) != JUMP_INSN
+ && GET_CODE (PATTERN (insn)) != USE
+ && GET_CODE (PATTERN (insn)) != CLOBBER)
+ n_insns++;
+
+ if (insn == end)
+ break;
+
+ insn = NEXT_INSN (insn);
+ }
+
+ return n_insns;
}
/* Determine if a given basic block heads a simple IF-THEN or IF-THEN-ELSE
block. If so, we'll try to convert the insns to not require the branch.
- Return TRUE if we were successful at converting the the block. */
+ Return TRUE if we were successful at converting the block. */
static int
-find_if_block (test_bb, then_edge, else_edge)
- basic_block test_bb;
- edge then_edge, else_edge;
+find_if_block (ce_info)
+ struct ce_if_block * ce_info;
{
- basic_block then_bb = then_edge->dest;
- basic_block else_bb = else_edge->dest;
+ basic_block test_bb = ce_info->test_bb;
+ basic_block then_bb = ce_info->then_bb;
+ basic_block else_bb = ce_info->else_bb;
basic_block join_bb = NULL_BLOCK;
edge then_succ = then_bb->succ;
edge else_succ = else_bb->succ;
- int next_index;
+ int then_predecessors;
+ int else_predecessors;
+ edge cur_edge;
+ basic_block next;
+
+ ce_info->last_test_bb = test_bb;
+
+ /* Discover if any fall through predecessors of the current test basic block
+ were && tests (which jump to the else block) or || tests (which jump to
+ the then block). */
+ if (HAVE_conditional_execution && reload_completed
+ && test_bb->pred != NULL_EDGE
+ && test_bb->pred->pred_next == NULL_EDGE
+ && test_bb->pred->flags == EDGE_FALLTHRU)
+ {
+ basic_block bb = test_bb->pred->src;
+ basic_block target_bb;
+ int max_insns = MAX_CONDITIONAL_EXECUTE;
+ int n_insns;
+
+ /* Determine if the preceeding block is an && or || block. */
+ if ((n_insns = block_jumps_and_fallthru_p (bb, else_bb)) >= 0)
+ {
+ ce_info->and_and_p = TRUE;
+ target_bb = else_bb;
+ }
+ else if ((n_insns = block_jumps_and_fallthru_p (bb, then_bb)) >= 0)
+ {
+ ce_info->and_and_p = FALSE;
+ target_bb = then_bb;
+ }
+ else
+ target_bb = NULL_BLOCK;
+
+ if (target_bb && n_insns <= max_insns)
+ {
+ int total_insns = 0;
+ int blocks = 0;
- /* The THEN block of an IF-THEN combo must have exactly one predecessor. */
- if (then_bb->pred->pred_next != NULL_EDGE)
+ ce_info->last_test_bb = test_bb;
+
+ /* Found at least one && or || block, look for more. */
+ do
+ {
+ ce_info->test_bb = test_bb = bb;
+ total_insns += n_insns;
+ blocks++;
+
+ if (bb->pred == NULL_EDGE || bb->pred->pred_next != NULL_EDGE)
+ break;
+
+ bb = bb->pred->src;
+ n_insns = block_jumps_and_fallthru_p (bb, target_bb);
+ }
+ while (n_insns >= 0 && (total_insns + n_insns) <= max_insns);
+
+ ce_info->num_multiple_test_blocks = blocks;
+ ce_info->num_multiple_test_insns = total_insns;
+
+ if (ce_info->and_and_p)
+ ce_info->num_and_and_blocks = blocks;
+ else
+ ce_info->num_or_or_blocks = blocks;
+ }
+ }
+
+ /* Count the number of edges the THEN and ELSE blocks have. */
+ then_predecessors = 0;
+ for (cur_edge = then_bb->pred;
+ cur_edge != NULL_EDGE;
+ cur_edge = cur_edge->pred_next)
+ {
+ then_predecessors++;
+ if (cur_edge->flags & EDGE_COMPLEX)
+ return FALSE;
+ }
+
+ else_predecessors = 0;
+ for (cur_edge = else_bb->pred;
+ cur_edge != NULL_EDGE;
+ cur_edge = cur_edge->pred_next)
+ {
+ else_predecessors++;
+ if (cur_edge->flags & EDGE_COMPLEX)
+ return FALSE;
+ }
+
+ /* The THEN block of an IF-THEN combo must have exactly one predecessor,
+ other than any || blocks which jump to the THEN block. */
+ if ((then_predecessors - ce_info->num_or_or_blocks) != 1)
return FALSE;
/* The THEN block of an IF-THEN combo must have zero or one successors. */
if (then_succ != NULL_EDGE
&& (then_succ->succ_next != NULL_EDGE
- || (then_succ->flags & EDGE_COMPLEX)))
+ || (then_succ->flags & EDGE_COMPLEX)
+ || (flow2_completed && tablejump_p (then_bb->end))))
return FALSE;
/* If the THEN block has no successors, conditional execution can still
@@ -2053,7 +2360,7 @@ find_if_block (test_bb, then_edge, else_edge)
only one incoming edge -- the CFG manipulation is too ugly otherwise.
Check for the last insn of the THEN block being an indirect jump, which
is listed as not having any successors, but confuses the rest of the CE
- code processing. XXX we should fix this in the future. */
+ code processing. ??? we should fix this in the future. */
if (then_succ == NULL)
{
if (else_bb->pred->pred_next == NULL_EDGE)
@@ -2092,7 +2399,8 @@ find_if_block (test_bb, then_edge, else_edge)
&& then_succ->dest == else_succ->dest
&& else_bb->pred->pred_next == NULL_EDGE
&& else_succ->succ_next == NULL_EDGE
- && ! (else_succ->flags & EDGE_COMPLEX))
+ && ! (else_succ->flags & EDGE_COMPLEX)
+ && ! (flow2_completed && tablejump_p (else_bb->end)))
join_bb = else_succ->dest;
/* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination. */
@@ -2103,27 +2411,44 @@ find_if_block (test_bb, then_edge, else_edge)
if (rtl_dump_file)
{
- if (else_bb)
- fprintf (rtl_dump_file,
- "\nIF-THEN-ELSE block found, start %d, then %d, else %d, join %d\n",
- test_bb->index, then_bb->index, else_bb->index,
- join_bb->index);
- else
- fprintf (rtl_dump_file,
- "\nIF-THEN block found, start %d, then %d, join %d\n",
- test_bb->index, then_bb->index, join_bb->index);
- }
+ fprintf (rtl_dump_file, "\nIF-THEN%s block found, pass %d, start block %d [insn %d], then %d [%d]",
+ (else_bb) ? "-ELSE" : "",
+ ce_info->pass,
+ test_bb->index, (test_bb->head) ? (int)INSN_UID (test_bb->head) : -1,
+ then_bb->index, (then_bb->head) ? (int)INSN_UID (then_bb->head) : -1);
- /* Make sure IF, THEN, and ELSE, blocks are adjacent. Actually, we
- get the first condition for free, since we've already asserted that
- there's a fallthru edge from IF to THEN. */
+ if (else_bb)
+ fprintf (rtl_dump_file, ", else %d [%d]",
+ else_bb->index, (else_bb->head) ? (int)INSN_UID (else_bb->head) : -1);
+
+ fprintf (rtl_dump_file, ", join %d [%d]",
+ join_bb->index, (join_bb->head) ? (int)INSN_UID (join_bb->head) : -1);
+
+ if (ce_info->num_multiple_test_blocks > 0)
+ fprintf (rtl_dump_file, ", %d %s block%s last test %d [%d]",
+ ce_info->num_multiple_test_blocks,
+ (ce_info->and_and_p) ? "&&" : "||",
+ (ce_info->num_multiple_test_blocks == 1) ? "" : "s",
+ ce_info->last_test_bb->index,
+ ((ce_info->last_test_bb->head)
+ ? (int)INSN_UID (ce_info->last_test_bb->head)
+ : -1));
+
+ fputc ('\n', rtl_dump_file);
+ }
+
+ /* Make sure IF, THEN, and ELSE, blocks are adjacent. Actually, we get the
+ first condition for free, since we've already asserted that there's a
+ fallthru edge from IF to THEN. Likewise for the && and || blocks, since
+ we checked the FALLTHRU flag, those are already adjacent to the last IF
+ block. */
/* ??? As an enhancement, move the ELSE block. Have to deal with
BLOCK notes, if by no other means than aborting the merge if they
exist. Sticky enough I don't want to think about it now. */
- next_index = then_bb->index;
- if (else_bb && ++next_index != else_bb->index)
+ next = then_bb;
+ if (else_bb && (next = next->next_bb) != else_bb)
return FALSE;
- if (++next_index != join_bb->index && join_bb->index != EXIT_BLOCK)
+ if ((next = next->next_bb) != join_bb && join_bb != EXIT_BLOCK_PTR)
{
if (else_bb)
join_bb = NULL;
@@ -2132,24 +2457,26 @@ find_if_block (test_bb, then_edge, else_edge)
}
/* Do the real work. */
- return process_if_block (test_bb, then_bb, else_bb, join_bb);
+ ce_info->else_bb = else_bb;
+ ce_info->join_bb = join_bb;
+
+ return process_if_block (ce_info);
}
-/* Convert a branch over a trap, or a branch to a trap,
- into a conditional trap. */
+/* Convert a branch over a trap, or a branch
+ to a trap, into a conditional trap. */
static int
find_cond_trap (test_bb, then_edge, else_edge)
basic_block test_bb;
edge then_edge, else_edge;
{
- basic_block then_bb, else_bb, trap_bb, other_bb;
+ basic_block then_bb = then_edge->dest;
+ basic_block else_bb = else_edge->dest;
+ basic_block other_bb, trap_bb;
rtx trap, jump, cond, cond_earliest, seq;
enum rtx_code code;
- then_bb = then_edge->dest;
- else_bb = else_edge->dest;
-
/* Locate the block with the trap instruction. */
/* ??? While we look for no successors, we really ought to allow
EH successors. Need to fix merge_if_block for that to work. */
@@ -2172,8 +2499,8 @@ find_cond_trap (test_bb, then_edge, else_edge)
if (! cond)
return FALSE;
- /* If the conditional jump is more than just a conditional jump,
- then we can not do if-conversion on this block. */
+ /* If the conditional jump is more than just a conditional jump, then
+ we can not do if-conversion on this block. */
if (! onlyjump_p (jump))
return FALSE;
@@ -2197,22 +2524,30 @@ find_cond_trap (test_bb, then_edge, else_edge)
return FALSE;
/* Emit the new insns before cond_earliest. */
- emit_insn_before (seq, cond_earliest);
+ emit_insn_before_scope (seq, cond_earliest, INSN_SCOPE (trap));
/* Delete the trap block if possible. */
remove_edge (trap_bb == then_bb ? then_edge : else_edge);
if (trap_bb->pred == NULL)
{
+ if (post_dominators)
+ delete_from_dominance_info (post_dominators, trap_bb);
flow_delete_block (trap_bb);
num_removed_blocks++;
}
/* If the non-trap block and the test are now adjacent, merge them.
Otherwise we must insert a direct branch. */
- if (test_bb->index + 1 == other_bb->index)
+ if (test_bb->next_bb == other_bb)
{
+ struct ce_if_block new_ce_info;
delete_insn (jump);
- merge_if_block (test_bb, NULL, NULL, other_bb);
+ memset ((PTR) &new_ce_info, '\0', sizeof (new_ce_info));
+ new_ce_info.test_bb = test_bb;
+ new_ce_info.then_bb = NULL;
+ new_ce_info.else_bb = NULL;
+ new_ce_info.join_bb = other_bb;
+ merge_if_block (&new_ce_info);
}
else
{
@@ -2261,7 +2596,7 @@ block_has_only_trap (bb)
transformable, but not necessarily the other. There need be no
JOIN block.
- Return TRUE if we were successful at converting the the block.
+ Return TRUE if we were successful at converting the block.
Cases we'd like to look at:
@@ -2342,6 +2677,7 @@ find_if_case_1 (test_bb, then_edge, else_edge)
basic_block then_bb = then_edge->dest;
basic_block else_bb = else_edge->dest, new_bb;
edge then_succ = then_bb->succ;
+ int then_bb_index;
/* THEN has one successor. */
if (!then_succ || then_succ->succ_next != NULL)
@@ -2377,20 +2713,25 @@ find_if_case_1 (test_bb, then_edge, else_edge)
/* Conversion went ok, including moving the insns and fixing up the
jump. Adjust the CFG to match. */
- SET_UPDATE_LIFE (test_bb);
bitmap_operation (test_bb->global_live_at_end,
else_bb->global_live_at_start,
then_bb->global_live_at_end, BITMAP_IOR);
new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb), else_bb);
+ then_bb_index = then_bb->index;
+ if (post_dominators)
+ delete_from_dominance_info (post_dominators, then_bb);
+ flow_delete_block (then_bb);
+
/* Make rest of code believe that the newly created block is the THEN_BB
- block we are going to remove. */
+ block we removed. */
if (new_bb)
{
- new_bb->aux = then_bb->aux;
- SET_UPDATE_LIFE (then_bb);
+ new_bb->index = then_bb_index;
+ BASIC_BLOCK (then_bb_index) = new_bb;
+ if (post_dominators)
+ add_to_dominance_info (post_dominators, new_bb);
}
- flow_delete_block (then_bb);
/* We've possibly created jump to next insn, cleanup_cfg will solve that
later. */
@@ -2433,8 +2774,8 @@ find_if_case_2 (test_bb, then_edge, else_edge)
if (note && INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2)
;
else if (else_succ->dest->index < 0
- || TEST_BIT (post_dominators[ORIG_INDEX (then_bb)],
- ORIG_INDEX (else_succ->dest)))
+ || dominated_by_p (post_dominators, then_bb,
+ else_succ->dest))
;
else
return FALSE;
@@ -2446,7 +2787,7 @@ find_if_case_2 (test_bb, then_edge, else_edge)
test_bb->index, else_bb->index);
/* ELSE is small. */
- if (count_bb_insns (then_bb) > BRANCH_COST)
+ if (count_bb_insns (else_bb) > BRANCH_COST)
return FALSE;
/* Registers set are dead, or are predicable. */
@@ -2456,11 +2797,12 @@ find_if_case_2 (test_bb, then_edge, else_edge)
/* Conversion went ok, including moving the insns and fixing up the
jump. Adjust the CFG to match. */
- SET_UPDATE_LIFE (test_bb);
bitmap_operation (test_bb->global_live_at_end,
then_bb->global_live_at_start,
else_bb->global_live_at_end, BITMAP_IOR);
+ if (post_dominators)
+ delete_from_dominance_info (post_dominators, else_bb);
flow_delete_block (else_bb);
num_removed_blocks++;
@@ -2519,11 +2861,28 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
if (GET_CODE (end) == JUMP_INSN)
{
+ rtx tmp, insn, label;
+
if (head == end)
{
head = end = NULL_RTX;
goto no_body;
}
+
+ /* If there is a jump table following merge_bb, fail
+ if there are any insn between head and PREV_INSN (end)
+ references it. */
+ if ((label = JUMP_LABEL (end)) != NULL_RTX
+ && (tmp = NEXT_INSN (label)) != NULL_RTX
+ && GET_CODE (tmp) == JUMP_INSN
+ && (GET_CODE (PATTERN (tmp)) == ADDR_VEC
+ || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC))
+ {
+ for (insn = head; insn != PREV_INSN (end); insn = NEXT_INSN (insn))
+ if (find_reg_note (insn, REG_LABEL, label))
+ return FALSE;
+ }
+
end = PREV_INSN (end);
}
@@ -2559,7 +2918,8 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (prob_val));
}
- if (! cond_exec_process_insns (head, end, cond, prob_val, 0))
+ if (! cond_exec_process_insns ((ce_if_block_t *)0, head, end, cond,
+ prob_val, 0))
goto cancel;
earliest = jump;
@@ -2753,14 +3113,15 @@ void
if_convert (x_life_data_ok)
int x_life_data_ok;
{
- int block_num;
+ basic_block bb;
+ int pass;
num_possible_if_blocks = 0;
num_updated_if_blocks = 0;
num_removed_blocks = 0;
life_data_ok = (x_life_data_ok != 0);
- /* Free up basic_block_for_insn so that we don't have to keep it
+ /* Free up basic_block_for_insn so that we don't have to keep it
up to date, either here or in merge_blocks_nomove. */
free_basic_block_vars (1);
@@ -2768,59 +3129,65 @@ if_convert (x_life_data_ok)
post_dominators = NULL;
if (HAVE_conditional_execution || life_data_ok)
{
- post_dominators = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
- calculate_dominance_info (NULL, post_dominators, CDI_POST_DOMINATORS);
+ post_dominators = calculate_dominance_info (CDI_POST_DOMINATORS);
}
+ if (life_data_ok)
+ clear_bb_flags ();
- /* Record initial block numbers. */
- for (block_num = 0; block_num < n_basic_blocks; block_num++)
- SET_ORIG_INDEX (BASIC_BLOCK (block_num), block_num);
-
- /* Go through each of the basic blocks looking for things to convert. */
- for (block_num = 0; block_num < n_basic_blocks; )
+ /* Go through each of the basic blocks looking for things to convert. If we
+ have conditional execution, we make multiple passes to allow us to handle
+ IF-THEN{-ELSE} blocks within other IF-THEN{-ELSE} blocks. */
+ pass = 0;
+ do
{
- basic_block bb = BASIC_BLOCK (block_num);
- if (find_if_header (bb))
- block_num = bb->index;
- else
- block_num++;
+ cond_exec_changed_p = FALSE;
+ pass++;
+
+#ifdef IFCVT_MULTIPLE_DUMPS
+ if (rtl_dump_file && pass > 1)
+ fprintf (rtl_dump_file, "\n\n========== Pass %d ==========\n", pass);
+#endif
+
+ FOR_EACH_BB (bb)
+ {
+ basic_block new_bb;
+ while ((new_bb = find_if_header (bb, pass)))
+ bb = new_bb;
+ }
+
+#ifdef IFCVT_MULTIPLE_DUMPS
+ if (rtl_dump_file && cond_exec_changed_p)
+ print_rtl_with_bb (rtl_dump_file, get_insns ());
+#endif
}
+ while (cond_exec_changed_p);
+
+#ifdef IFCVT_MULTIPLE_DUMPS
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "\n\n========== no more changes\n");
+#endif
if (post_dominators)
- sbitmap_vector_free (post_dominators);
+ free_dominance_info (post_dominators);
if (rtl_dump_file)
fflush (rtl_dump_file);
+ clear_aux_for_blocks ();
+
/* Rebuild life info for basic blocks that require it. */
if (num_removed_blocks && life_data_ok)
{
- sbitmap update_life_blocks = sbitmap_alloc (n_basic_blocks);
- sbitmap_zero (update_life_blocks);
-
/* If we allocated new pseudos, we must resize the array for sched1. */
if (max_regno < max_reg_num ())
{
max_regno = max_reg_num ();
allocate_reg_info (max_regno, FALSE, FALSE);
}
-
- for (block_num = 0; block_num < n_basic_blocks; block_num++)
- if (UPDATE_LIFE (BASIC_BLOCK (block_num)))
- SET_BIT (update_life_blocks, block_num);
-
- clear_aux_for_blocks ();
- count_or_remove_death_notes (update_life_blocks, 1);
- /* ??? See about adding a mode that verifies that the initial
- set of blocks don't let registers come live. */
- update_life_info (update_life_blocks, UPDATE_LIFE_GLOBAL,
- PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
- | PROP_KILL_DEAD_CODE);
-
- sbitmap_free (update_life_blocks);
+ update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
+ PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
+ | PROP_KILL_DEAD_CODE);
}
- else
- clear_aux_for_blocks ();
/* Write the final stats. */
if (rtl_dump_file && num_possible_if_blocks > 0)
diff --git a/contrib/gcc/input.h b/contrib/gcc/input.h
index 7ef5d94..28bb648 100644
--- a/contrib/gcc/input.h
+++ b/contrib/gcc/input.h
@@ -36,7 +36,6 @@ struct file_stack
const char *name;
struct file_stack *next;
int line;
- int indent_level;
};
/* Stack of currently pending input files.
diff --git a/contrib/gcc/insn-addr.h b/contrib/gcc/insn-addr.h
index 214df19..4403b0b 100644
--- a/contrib/gcc/insn-addr.h
+++ b/contrib/gcc/insn-addr.h
@@ -23,14 +23,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "varray.h"
-extern varray_type insn_addresses_;
+extern GTY(()) varray_type insn_addresses_;
extern int insn_current_address;
#define INSN_ADDRESSES_DEFN() varray_type insn_addresses_
#define INSN_ADDRESSES(id) VARRAY_INT (insn_addresses_, (id))
#define INSN_ADDRESSES_ALLOC(size) \
VARRAY_INT_INIT (insn_addresses_, (size), "insn_addresses")
-#define INSN_ADDRESSES_FREE() VARRAY_FREE (insn_addresses_)
+#define INSN_ADDRESSES_FREE() (insn_addresses_ = 0)
#define INSN_ADDRESSES_SET_P() (insn_addresses_ != 0)
#define INSN_ADDRESSES_SIZE() VARRAY_SIZE (insn_addresses_)
#define INSN_ADDRESSES_NEW(insn, addr) do \
diff --git a/contrib/gcc/integrate.c b/contrib/gcc/integrate.c
index ce2962d..d1be237 100644
--- a/contrib/gcc/integrate.c
+++ b/contrib/gcc/integrate.c
@@ -43,12 +43,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "params.h"
#include "ggc.h"
#include "target.h"
-
-#include "obstack.h"
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-extern struct obstack *function_maybepermanent_obstack;
+#include "langhooks.h"
/* Similar, but round to the next highest integer that meets the
alignment. */
@@ -67,14 +62,14 @@ extern struct obstack *function_maybepermanent_obstack;
/* Private type used by {get/has}_func_hard_reg_initial_val. */
-typedef struct initial_value_pair {
+typedef struct initial_value_pair GTY(()) {
rtx hard_reg;
rtx pseudo;
} initial_value_pair;
-typedef struct initial_value_struct {
+typedef struct initial_value_struct GTY(()) {
int num_entries;
int max_entries;
- initial_value_pair *entries;
+ initial_value_pair * GTY ((length ("%h.num_entries"))) entries;
} initial_value_struct;
static void setup_initial_hard_reg_value_integration PARAMS ((struct function *, struct inline_remap *));
@@ -131,30 +126,22 @@ bool
function_attribute_inlinable_p (fndecl)
tree fndecl;
{
- bool has_machine_attr = false;
- tree a;
-
- for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a))
+ if (targetm.attribute_table)
{
- tree name = TREE_PURPOSE (a);
- int i;
+ tree a;
- for (i = 0; targetm.attribute_table[i].name != NULL; i++)
+ for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a))
{
- if (is_attribute_p (targetm.attribute_table[i].name, name))
- {
- has_machine_attr = true;
- break;
- }
+ tree name = TREE_PURPOSE (a);
+ int i;
+
+ for (i = 0; targetm.attribute_table[i].name != NULL; i++)
+ if (is_attribute_p (targetm.attribute_table[i].name, name))
+ return (*targetm.function_attribute_inlinable_p) (fndecl);
}
- if (has_machine_attr)
- break;
}
- if (has_machine_attr)
- return (*targetm.function_attribute_inlinable_p) (fndecl);
- else
- return true;
+ return true;
}
/* Zero if the current function (whose FUNCTION_DECL is FNDECL)
@@ -170,11 +157,13 @@ function_cannot_inline_p (fndecl)
tree last = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
/* For functions marked as inline increase the maximum size to
- MAX_INLINE_INSNS (-finline-limit-<n>). For regular functions
- use the limit given by INTEGRATE_THRESHOLD. */
+ MAX_INLINE_INSNS_RTL (--param max-inline-insn-rtl=<n>). For
+ regular functions use the limit given by INTEGRATE_THRESHOLD.
+ Note that the RTL inliner is not used by the languages that use
+ the tree inliner (C, C++). */
int max_insns = (DECL_INLINE (fndecl))
- ? (MAX_INLINE_INSNS
+ ? (MAX_INLINE_INSNS_RTL
+ 8 * list_length (DECL_ARGUMENTS (fndecl)))
: INTEGRATE_THRESHOLD (fndecl);
@@ -185,8 +174,7 @@ function_cannot_inline_p (fndecl)
return N_("function cannot be inline");
/* No inlines with varargs. */
- if ((last && TREE_VALUE (last) != void_type_node)
- || current_function_varargs)
+ if (last && TREE_VALUE (last) != void_type_node)
return N_("varargs function cannot be inline");
if (current_function_calls_alloca)
@@ -259,7 +247,7 @@ function_cannot_inline_p (fndecl)
/* We will not inline a function which uses computed goto. The addresses of
its local labels, which may be tucked into global storage, are of course
- not constant across instantiations, which causes unexpected behaviour. */
+ not constant across instantiations, which causes unexpected behavior. */
if (current_function_has_computed_jump)
return N_("function with computed jump cannot inline");
@@ -358,18 +346,41 @@ copy_decl_for_inlining (decl, from_fn, to_fn)
/* Copy the declaration. */
if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL)
{
+ tree type;
+ int invisiref = 0;
+
+ /* See if the frontend wants to pass this by invisible reference. */
+ if (TREE_CODE (decl) == PARM_DECL
+ && DECL_ARG_TYPE (decl) != TREE_TYPE (decl)
+ && POINTER_TYPE_P (DECL_ARG_TYPE (decl))
+ && TREE_TYPE (DECL_ARG_TYPE (decl)) == TREE_TYPE (decl))
+ {
+ invisiref = 1;
+ type = DECL_ARG_TYPE (decl);
+ }
+ else
+ type = TREE_TYPE (decl);
+
/* For a parameter, we must make an equivalent VAR_DECL, not a
new PARM_DECL. */
- copy = build_decl (VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
- TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
- TREE_READONLY (copy) = TREE_READONLY (decl);
- TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
+ copy = build_decl (VAR_DECL, DECL_NAME (decl), type);
+ if (!invisiref)
+ {
+ TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
+ TREE_READONLY (copy) = TREE_READONLY (decl);
+ TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
+ }
+ else
+ {
+ TREE_ADDRESSABLE (copy) = 0;
+ TREE_READONLY (copy) = 1;
+ TREE_THIS_VOLATILE (copy) = 0;
+ }
}
else
{
copy = copy_node (decl);
- if (DECL_LANG_SPECIFIC (copy))
- copy_lang_decl (copy);
+ (*lang_hooks.dup_lang_specific_decl) (copy);
/* TREE_ADDRESSABLE isn't used to indicate that a label's
address has been taken; it's for internal bookkeeping in
@@ -671,7 +682,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
rtx stack_save = 0;
rtx temp;
struct inline_remap *map = 0;
- rtvec arg_vector = (rtvec) inl_f->original_arg_vector;
+ rtvec arg_vector = inl_f->original_arg_vector;
rtx static_chain_value = 0;
int inl_max_uid;
int eh_region_offset;
@@ -852,7 +863,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
??? These numbers are quite arbitrary and were obtained by
experimentation. At some point, we should try to allocate the
- table after all the parameters are set up so we an more accurately
+ table after all the parameters are set up so we can more accurately
estimate the number of pseudos we will need. */
VARRAY_CONST_EQUIV_INIT (map->const_equiv_varray,
@@ -1248,7 +1259,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
this block to the list of blocks at this binding level. We
can't do it the way it's done for function-at-a-time mode the
superblocks have not been created yet. */
- insert_block (block);
+ (*lang_hooks.decls.insert_block) (block);
else
{
BLOCK_CHAIN (block)
@@ -1294,7 +1305,6 @@ expand_inline_function (fndecl, parms, target, ignore, type,
free (real_label_map);
VARRAY_FREE (map->const_equiv_varray);
free (map->reg_map);
- VARRAY_FREE (map->block_map);
free (map->insn_map);
free (map);
free (arg_vals);
@@ -1311,7 +1321,7 @@ expand_inline_function (fndecl, parms, target, ignore, type,
Copying is done in two passes, first the insns and then their REG_NOTES.
- If static_chain_value is non-zero, it represents the context-pointer
+ If static_chain_value is nonzero, it represents the context-pointer
register for the function. */
static void
@@ -1404,7 +1414,7 @@ copy_insn_list (insns, map, static_chain_value)
memory references via that register can then be
identified as static chain references. We assume that
the register is only assigned once, and that the static
- chain address is only live in one register at a time. */
+ chain address is only live in one register at a time. */
else if (static_chain_value != 0
&& set != 0
@@ -1512,6 +1522,7 @@ copy_insn_list (insns, map, static_chain_value)
#else
try_constants (copy, map);
#endif
+ INSN_SCOPE (copy) = INSN_SCOPE (insn);
break;
case JUMP_INSN:
@@ -1532,6 +1543,7 @@ copy_insn_list (insns, map, static_chain_value)
cc0_insn = 0;
#endif
try_constants (copy, map);
+ INSN_SCOPE (copy) = INSN_SCOPE (insn);
/* If this used to be a conditional jump insn but whose branch
direction is now know, we must do something special. */
@@ -1599,6 +1611,7 @@ copy_insn_list (insns, map, static_chain_value)
SIBLING_CALL_P (copy) = SIBLING_CALL_P (insn);
CONST_OR_PURE_CALL_P (copy) = CONST_OR_PURE_CALL_P (insn);
+ INSN_SCOPE (copy) = INSN_SCOPE (insn);
/* Because the USAGE information potentially contains objects other
than hard registers, we need to copy it. */
@@ -1948,7 +1961,7 @@ copy_rtx_and_substitute (orig, map, for_lhs)
SET_CONST_EQUIV_DATA (map, temp, loc, CONST_AGE_PARM);
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
emit_insn_after (seq, map->insns_at_start);
return temp;
@@ -1981,7 +1994,7 @@ copy_rtx_and_substitute (orig, map, for_lhs)
SET_CONST_EQUIV_DATA (map, temp, loc, CONST_AGE_PARM);
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
emit_insn_after (seq, map->insns_at_start);
return temp;
@@ -2068,7 +2081,17 @@ copy_rtx_and_substitute (orig, map, for_lhs)
RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (temp);
/* A reg with REG_FUNCTION_VALUE_P true will never reach here. */
- if (REG_POINTER (map->x_regno_reg_rtx[regno]))
+ /* Objects may initially be represented as registers, but
+ but turned into a MEM if their address is taken by
+ put_var_into_stack. Therefore, the register table may have
+ entries which are MEMs.
+
+ We briefly tried to clear such entries, but that ended up
+ cascading into many changes due to the optimizers not being
+ prepared for empty entries in the register table. So we've
+ decided to allow the MEMs in the register table for now. */
+ if (REG_P (map->x_regno_reg_rtx[regno])
+ && REG_POINTER (map->x_regno_reg_rtx[regno]))
mark_reg_pointer (map->reg_map[regno],
map->regno_pointer_align[regno]);
regno = REGNO (map->reg_map[regno]);
@@ -2209,7 +2232,7 @@ copy_rtx_and_substitute (orig, map, for_lhs)
if (map->orig_asm_operands_vector == ASM_OPERANDS_INPUT_VEC (orig))
{
copy = rtx_alloc (ASM_OPERANDS);
- copy->volatil = orig->volatil;
+ RTX_FLAG (copy, volatil) = RTX_FLAG (orig, volatil);
PUT_MODE (copy, GET_MODE (orig));
ASM_OPERANDS_TEMPLATE (copy) = ASM_OPERANDS_TEMPLATE (orig);
ASM_OPERANDS_OUTPUT_CONSTRAINT (copy)
@@ -2335,9 +2358,9 @@ copy_rtx_and_substitute (orig, map, for_lhs)
copy = rtx_alloc (code);
PUT_MODE (copy, mode);
- copy->in_struct = orig->in_struct;
- copy->volatil = orig->volatil;
- copy->unchanging = orig->unchanging;
+ RTX_FLAG (copy, in_struct) = RTX_FLAG (orig, in_struct);
+ RTX_FLAG (copy, volatil) = RTX_FLAG (orig, volatil);
+ RTX_FLAG (copy, unchanging) = RTX_FLAG (orig, unchanging);
format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
@@ -2703,6 +2726,7 @@ subst_constants (loc, insn, map, memonly)
case 'w':
case 'n':
case 't':
+ case 'B':
break;
case 'E':
@@ -2980,18 +3004,19 @@ set_decl_abstract_flags (decl, setting)
from its DECL_SAVED_INSNS. Used for inline functions that are output
at end of compilation instead of where they came in the source. */
+static GTY(()) struct function *old_cfun;
+
void
output_inline_function (fndecl)
tree fndecl;
{
- struct function *old_cfun = cfun;
enum debug_info_type old_write_symbols = write_symbols;
- struct gcc_debug_hooks *old_debug_hooks = debug_hooks;
+ const struct gcc_debug_hooks *const old_debug_hooks = debug_hooks;
struct function *f = DECL_SAVED_INSNS (fndecl);
+ old_cfun = cfun;
cfun = f;
current_function_decl = fndecl;
- clear_emit_caches ();
set_new_last_label_num (f->inl_max_label_num);
@@ -3005,6 +3030,11 @@ output_inline_function (fndecl)
debug_hooks = &do_nothing_debug_hooks;
}
+ /* Make sure warnings emitted by the optimizers (e.g. control reaches
+ end of non-void function) is not wildly incorrect. */
+ input_filename = DECL_SOURCE_FILE (fndecl);
+ lineno = DECL_SOURCE_LINE (fndecl);
+
/* Compile this function all the way down to assembly code. As a
side effect this destroys the saved RTL representation, but
that's okay, because we don't need to inline this anymore. */
@@ -3070,20 +3100,20 @@ get_func_hard_reg_initial_val (fun, reg)
if (ivs == 0)
{
- fun->hard_reg_initial_vals = (void *) xmalloc (sizeof (initial_value_struct));
+ fun->hard_reg_initial_vals = (void *) ggc_alloc (sizeof (initial_value_struct));
ivs = fun->hard_reg_initial_vals;
ivs->num_entries = 0;
ivs->max_entries = 5;
- ivs->entries = (initial_value_pair *) xmalloc (5 * sizeof (initial_value_pair));
+ ivs->entries = (initial_value_pair *) ggc_alloc (5 * sizeof (initial_value_pair));
}
if (ivs->num_entries >= ivs->max_entries)
{
ivs->max_entries += 5;
ivs->entries =
- (initial_value_pair *) xrealloc (ivs->entries,
- ivs->max_entries
- * sizeof (initial_value_pair));
+ (initial_value_pair *) ggc_realloc (ivs->entries,
+ ivs->max_entries
+ * sizeof (initial_value_pair));
}
ivs->entries[ivs->num_entries].hard_reg = reg;
@@ -3108,23 +3138,6 @@ has_hard_reg_initial_val (mode, regno)
return has_func_hard_reg_initial_val (cfun, gen_rtx_REG (mode, regno));
}
-void
-mark_hard_reg_initial_vals (fun)
- struct function *fun;
-{
- struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
- int i;
-
- if (ivs == 0)
- return;
-
- for (i = 0; i < ivs->num_entries; i ++)
- {
- ggc_mark_rtx (ivs->entries[i].hard_reg);
- ggc_mark_rtx (ivs->entries[i].pseudo);
- }
-}
-
static void
setup_initial_hard_reg_value_integration (inl_f, remap)
struct function *inl_f;
@@ -3158,7 +3171,7 @@ emit_initial_value_sets ()
seq = get_insns ();
end_sequence ();
- emit_insns_after (seq, get_insns ());
+ emit_insn_after (seq, get_insns ());
}
/* If the backend knows where to allocate pseudos for hard
@@ -3194,3 +3207,5 @@ allocate_initial_values (reg_equiv_memory_loc)
}
#endif
}
+
+#include "gt-integrate.h"
diff --git a/contrib/gcc/integrate.h b/contrib/gcc/integrate.h
index 9ddefef..b4d6227 100644
--- a/contrib/gcc/integrate.h
+++ b/contrib/gcc/integrate.h
@@ -143,8 +143,6 @@ extern rtx has_hard_reg_initial_val PARAMS ((enum machine_mode, int));
/* If a pseudo represents an initial hard reg (or expression), return
it, else return NULL_RTX. */
extern rtx get_hard_reg_initial_reg PARAMS ((struct function *, rtx));
-/* This is for GC. */
-extern void mark_hard_reg_initial_vals PARAMS ((struct function *));
/* Called from rest_of_compilation. */
extern void emit_initial_value_sets PARAMS ((void));
extern void allocate_initial_values PARAMS ((rtx *));
diff --git a/contrib/gcc/jump.c b/contrib/gcc/jump.c
index f60e169..fffc8e7 100644
--- a/contrib/gcc/jump.c
+++ b/contrib/gcc/jump.c
@@ -1,6 +1,6 @@
/* Optimize jump instructions, for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
- 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -328,8 +328,6 @@ duplicate_loop_exit_test (loop_start)
is a CODE_LABEL
has a REG_RETVAL or REG_LIBCALL note (hard to adjust)
is a NOTE_INSN_LOOP_BEG because this means we have a nested loop
- is a NOTE_INSN_BLOCK_{BEG,END} because duplicating these notes
- is not valid.
We also do not do this if we find an insn with ASM_OPERANDS. While
this restriction should not be necessary, copying an insn with
@@ -349,18 +347,6 @@ duplicate_loop_exit_test (loop_start)
case CALL_INSN:
return 0;
case NOTE:
- /* We could be in front of the wrong NOTE_INSN_LOOP_END if there is
- a jump immediately after the loop start that branches outside
- the loop but within an outer loop, near the exit test.
- If we copied this exit test and created a phony
- NOTE_INSN_LOOP_VTOP, this could make instructions immediately
- before the exit test look like these could be safely moved
- out of the loop even if they actually may be never executed.
- This can be avoided by checking here for NOTE_INSN_LOOP_CONT. */
-
- if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
- || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT)
- return 0;
if (optimize < 2
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
@@ -446,6 +432,7 @@ duplicate_loop_exit_test (loop_start)
replace_regs (PATTERN (copy), reg_map, max_reg, 1);
mark_jump_label (PATTERN (copy), copy, 0);
+ INSN_SCOPE (copy) = INSN_SCOPE (insn);
/* Copy all REG_NOTES except REG_LABEL since mark_jump_label will
make them. */
@@ -471,6 +458,7 @@ duplicate_loop_exit_test (loop_start)
case JUMP_INSN:
copy = emit_jump_insn_before (copy_insn (PATTERN (insn)),
loop_start);
+ INSN_SCOPE (copy) = INSN_SCOPE (insn);
if (reg_map)
replace_regs (PATTERN (copy), reg_map, max_reg, 1);
mark_jump_label (PATTERN (copy), copy, 0);
@@ -720,11 +708,6 @@ reversed_comparison_code_parts (code, arg0, arg1, insn)
break;
}
- /* In case we give up IEEE compatibility, all comparisons are reversible. */
- if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || flag_unsafe_math_optimizations)
- return reverse_condition (code);
-
if (GET_MODE_CLASS (mode) == MODE_CC
#ifdef HAVE_cc0
|| arg0 == cc0_rtx
@@ -773,11 +756,12 @@ reversed_comparison_code_parts (code, arg0, arg1, insn)
}
}
- /* An integer condition. */
+ /* Test for an integer condition, or a floating-point comparison
+ in which NaNs can be ignored. */
if (GET_CODE (arg0) == CONST_INT
|| (GET_MODE (arg0) != VOIDmode
&& GET_MODE_CLASS (mode) != MODE_CC
- && ! FLOAT_MODE_P (mode)))
+ && !HONOR_NANS (mode)))
return reverse_condition (code);
return UNKNOWN;
@@ -856,10 +840,6 @@ enum rtx_code
reverse_condition_maybe_unordered (code)
enum rtx_code code;
{
- /* Non-IEEE formats don't have unordered conditions. */
- if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
- return reverse_condition (code);
-
switch (code)
{
case EQ:
@@ -1005,7 +985,7 @@ signed_condition (code)
}
}
-/* Return non-zero if CODE1 is more strict than CODE2, i.e., if the
+/* Return nonzero if CODE1 is more strict than CODE2, i.e., if the
truth of CODE1 implies the truth of CODE2. */
int
@@ -1099,6 +1079,7 @@ simplejump_p (insn)
&& GET_CODE (SET_DEST (PATTERN (insn))) == PC
&& GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF);
}
+
/* Return 1 if INSN is an tablejump. */
int
@@ -1107,12 +1088,12 @@ tablejump_p (insn)
{
rtx table;
return (GET_CODE (insn) == JUMP_INSN
- && JUMP_LABEL (insn)
- && NEXT_INSN (JUMP_LABEL (insn))
- && (table = next_active_insn (JUMP_LABEL (insn)))
- && GET_CODE (table) == JUMP_INSN
- && (GET_CODE (PATTERN (table)) == ADDR_VEC
- || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC));
+ && JUMP_LABEL (insn)
+ && NEXT_INSN (JUMP_LABEL (insn))
+ && (table = next_active_insn (JUMP_LABEL (insn)))
+ && GET_CODE (table) == JUMP_INSN
+ && (GET_CODE (PATTERN (table)) == ADDR_VEC
+ || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC));
}
/* Return nonzero if INSN is a (possibly) conditional jump
@@ -1313,7 +1294,7 @@ onlyjump_p (insn)
#ifdef HAVE_cc0
-/* Return non-zero if X is an RTX that only sets the condition codes
+/* Return nonzero if X is an RTX that only sets the condition codes
and has no side effects. */
int
@@ -1455,7 +1436,6 @@ mark_jump_label (x, insn, in_mem)
case PC:
case CC0:
case REG:
- case SUBREG:
case CONST_INT:
case CONST_DOUBLE:
case CLOBBER:
@@ -1598,7 +1578,9 @@ delete_prior_computation (note, insn)
break;
/* If we reach a SEQUENCE, it is too complex to try to
- do anything with it, so give up. */
+ do anything with it, so give up. We can be run during
+ and after reorg, so SEQUENCE rtl can legitimately show
+ up here. */
if (GET_CODE (pat) == SEQUENCE)
break;
@@ -1934,14 +1916,14 @@ delete_for_peephole (from, to)
is also an unconditional jump in that case. */
}
-/* We have determined that INSN is never reached, and are about to
- delete it. Print a warning if the user asked for one.
+/* We have determined that AVOIDED_INSN is never reached, and are
+ about to delete it. If the insn chain between AVOIDED_INSN and
+ FINISH contains more than one line from the current function, and
+ contains at least one operation, print a warning if the user asked
+ for it. If FINISH is NULL, look between AVOIDED_INSN and a LABEL.
- To try to make this warning more useful, this should only be called
- once per basic block not reached, and it only warns when the basic
- block contains more than one line from the current function, and
- contains at least one operation. CSE and inlining can duplicate insns,
- so it's possible to get spurious warnings from this. */
+ CSE and inlining can duplicate insns, so it's possible to get
+ spurious warnings from this. */
void
never_reached_warning (avoided_insn, finish)
@@ -1951,15 +1933,29 @@ never_reached_warning (avoided_insn, finish)
rtx a_line_note = NULL;
int two_avoided_lines = 0, contains_insn = 0, reached_end = 0;
- if (! warn_notreached)
+ if (!warn_notreached)
return;
- /* Scan forwards, looking at LINE_NUMBER notes, until
- we hit a LABEL or we run out of insns. */
+ /* Back up to the first of any NOTEs preceding avoided_insn; flow passes
+ us the head of a block, a NOTE_INSN_BASIC_BLOCK, which often follows
+ the line note. */
+ insn = avoided_insn;
+ while (1)
+ {
+ rtx prev = PREV_INSN (insn);
+ if (prev == NULL_RTX
+ || GET_CODE (prev) != NOTE)
+ break;
+ insn = prev;
+ }
+
+ /* Scan forwards, looking at LINE_NUMBER notes, until we hit a LABEL
+ in case FINISH is NULL, otherwise until we run out of insns. */
- for (insn = avoided_insn; insn != NULL; insn = NEXT_INSN (insn))
+ for (; insn != NULL; insn = NEXT_INSN (insn))
{
- if (finish == NULL && GET_CODE (insn) == CODE_LABEL)
+ if ((finish == NULL && GET_CODE (insn) == CODE_LABEL)
+ || GET_CODE (insn) == BARRIER)
break;
if (GET_CODE (insn) == NOTE /* A line number note? */
diff --git a/contrib/gcc/langhooks-def.h b/contrib/gcc/langhooks-def.h
index 0132117..83b8b45 100644
--- a/contrib/gcc/langhooks-def.h
+++ b/contrib/gcc/langhooks-def.h
@@ -1,5 +1,5 @@
/* Default macros to initialize the lang_hooks data structure.
- Copyright 2001 Free Software Foundation, Inc.
+ Copyright 2001, 2002 Free Software Foundation, Inc.
Contributed by Alexandre Oliva <aoliva@redhat.com>
This file is part of GNU CC.
@@ -24,6 +24,8 @@ Boston, MA 02111-1307, USA. */
#include "hooks.h"
+struct diagnostic_context;
+
/* Provide a hook routine for alias sets that always returns 1. This is
used by languages that haven't deal with alias sets yet. */
extern HOST_WIDE_INT hook_get_alias_set_0 PARAMS ((tree));
@@ -40,14 +42,28 @@ extern HOST_WIDE_INT hook_get_alias_set_0 PARAMS ((tree));
/* See langhooks.h for the definition and documentation of each hook. */
extern void lhd_do_nothing PARAMS ((void));
+extern void lhd_do_nothing_t PARAMS ((tree));
+extern void lhd_do_nothing_i PARAMS ((int));
+extern void lhd_do_nothing_f PARAMS ((struct function *));
extern int lhd_decode_option PARAMS ((int, char **));
extern HOST_WIDE_INT lhd_get_alias_set PARAMS ((tree));
extern tree lhd_return_tree PARAMS ((tree));
+extern tree lhd_return_null_tree PARAMS ((tree));
extern int lhd_safe_from_p PARAMS ((rtx, tree));
extern int lhd_staticp PARAMS ((tree));
+extern int lhd_unsafe_for_reeval PARAMS ((tree));
extern void lhd_clear_binding_stack PARAMS ((void));
extern void lhd_print_tree_nothing PARAMS ((FILE *, tree, int));
-extern void lhd_set_yydebug PARAMS ((int));
+extern const char *lhd_decl_printable_name PARAMS ((tree, int));
+extern rtx lhd_expand_expr PARAMS ((tree, rtx, enum machine_mode, int));
+extern void lhd_print_error_function PARAMS ((struct diagnostic_context *,
+ const char *));
+extern void lhd_set_decl_assembler_name PARAMS ((tree));
+extern bool lhd_can_use_bit_fields_p PARAMS ((void));
+extern bool lhd_warn_unused_global_decl PARAMS ((tree));
+extern void lhd_incomplete_type_error PARAMS ((tree, tree));
+extern tree lhd_type_promotes_to PARAMS ((tree));
+extern bool lhd_decl_ok_for_sibcall PARAMS ((tree));
extern tree lhd_expr_size PARAMS ((tree));
/* Declarations of default tree inlining hooks. */
@@ -67,27 +83,50 @@ int lhd_tree_inlining_start_inlining PARAMS ((tree));
void lhd_tree_inlining_end_inlining PARAMS ((tree));
tree lhd_tree_inlining_convert_parm_for_inlining PARAMS ((tree, tree, tree));
+void write_global_declarations PARAMS ((void));
+
#define LANG_HOOKS_NAME "GNU unknown"
#define LANG_HOOKS_IDENTIFIER_SIZE sizeof (struct lang_identifier)
#define LANG_HOOKS_INIT lhd_do_nothing
#define LANG_HOOKS_FINISH lhd_do_nothing
+#define LANG_HOOKS_PARSE_FILE lhd_do_nothing_i
#define LANG_HOOKS_CLEAR_BINDING_STACK lhd_clear_binding_stack
#define LANG_HOOKS_INIT_OPTIONS lhd_do_nothing
#define LANG_HOOKS_DECODE_OPTION lhd_decode_option
-#define LANG_HOOKS_POST_OPTIONS hook_void_void
+#define LANG_HOOKS_POST_OPTIONS hook_bool_void_false
#define LANG_HOOKS_GET_ALIAS_SET lhd_get_alias_set
#define LANG_HOOKS_EXPAND_CONSTANT lhd_return_tree
+#define LANG_HOOKS_EXPAND_EXPR lhd_expand_expr
#define LANG_HOOKS_SAFE_FROM_P lhd_safe_from_p
+#define LANG_HOOKS_FINISH_INCOMPLETE_DECL lhd_do_nothing_t
+#define LANG_HOOKS_UNSAFE_FOR_REEVAL lhd_unsafe_for_reeval
#define LANG_HOOKS_STATICP lhd_staticp
+#define LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES lhd_do_nothing_t
+#define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL lhd_do_nothing_t
+#define LANG_HOOKS_UNSAVE_EXPR_NOW lhd_unsave_expr_now
+#define LANG_HOOKS_MAYBE_BUILD_CLEANUP lhd_return_null_tree
+#define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME lhd_set_decl_assembler_name
+#define LANG_HOOKS_CAN_USE_BIT_FIELDS_P lhd_can_use_bit_fields_p
#define LANG_HOOKS_HONOR_READONLY false
#define LANG_HOOKS_PRINT_STATISTICS lhd_do_nothing
#define LANG_HOOKS_PRINT_XNODE lhd_print_tree_nothing
#define LANG_HOOKS_PRINT_DECL lhd_print_tree_nothing
#define LANG_HOOKS_PRINT_TYPE lhd_print_tree_nothing
#define LANG_HOOKS_PRINT_IDENTIFIER lhd_print_tree_nothing
-#define LANG_HOOKS_SET_YYDEBUG lhd_set_yydebug
+#define LANG_HOOKS_PRINT_ERROR_FUNCTION lhd_print_error_function
+#define LANG_HOOKS_DECL_PRINTABLE_NAME lhd_decl_printable_name
#define LANG_HOOKS_EXPR_SIZE lhd_expr_size
+#define LANG_HOOKS_FUNCTION_INIT lhd_do_nothing_f
+#define LANG_HOOKS_FUNCTION_FINAL lhd_do_nothing_f
+#define LANG_HOOKS_FUNCTION_ENTER_NESTED lhd_do_nothing_f
+#define LANG_HOOKS_FUNCTION_LEAVE_NESTED lhd_do_nothing_f
+
+/* Attribute hooks. */
+#define LANG_HOOKS_ATTRIBUTE_TABLE NULL
+#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE NULL
+#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE NULL
+
/* Tree inlining hooks. */
#define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES lhd_tree_inlining_walk_subtrees
#define LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN \
@@ -105,7 +144,7 @@ tree lhd_tree_inlining_convert_parm_for_inlining PARAMS ((tree, tree, tree));
#define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
lhd_tree_inlining_anon_aggr_type_p
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P \
- hook_tree_bool_false
+ hook_bool_tree_false
#define LANG_HOOKS_TREE_INLINING_START_INLINING \
lhd_tree_inlining_start_inlining
#define LANG_HOOKS_TREE_INLINING_END_INLINING \
@@ -128,6 +167,13 @@ tree lhd_tree_inlining_convert_parm_for_inlining PARAMS ((tree, tree, tree));
LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
} \
+#define LANG_HOOKS_FUNCTION_INITIALIZER { \
+ LANG_HOOKS_FUNCTION_INIT, \
+ LANG_HOOKS_FUNCTION_FINAL, \
+ LANG_HOOKS_FUNCTION_ENTER_NESTED, \
+ LANG_HOOKS_FUNCTION_LEAVE_NESTED \
+}
+
/* Tree dump hooks. */
int lhd_tree_dump_dump_tree PARAMS ((void *, tree));
int lhd_tree_dump_type_quals PARAMS ((tree));
@@ -138,7 +184,49 @@ int lhd_tree_dump_type_quals PARAMS ((tree));
#define LANG_HOOKS_TREE_DUMP_INITIALIZER { \
LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN, \
LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN \
-} \
+}
+
+/* Types hooks. There are no reasonable defaults for most of them,
+ so we create a compile-time error instead. */
+#define LANG_HOOKS_MAKE_TYPE make_node
+#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR lhd_incomplete_type_error
+#define LANG_HOOKS_TYPE_PROMOTES_TO lhd_type_promotes_to
+
+#define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
+ LANG_HOOKS_MAKE_TYPE, \
+ LANG_HOOKS_TYPE_FOR_MODE, \
+ LANG_HOOKS_TYPE_FOR_SIZE, \
+ LANG_HOOKS_UNSIGNED_TYPE, \
+ LANG_HOOKS_SIGNED_TYPE, \
+ LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE, \
+ LANG_HOOKS_TYPE_PROMOTES_TO, \
+ LANG_HOOKS_INCOMPLETE_TYPE_ERROR \
+}
+
+/* Declaration hooks. */
+#define LANG_HOOKS_PUSHLEVEL pushlevel
+#define LANG_HOOKS_POPLEVEL poplevel
+#define LANG_HOOKS_GLOBAL_BINDINGS_P global_bindings_p
+#define LANG_HOOKS_INSERT_BLOCK insert_block
+#define LANG_HOOKS_SET_BLOCK set_block
+#define LANG_HOOKS_PUSHDECL pushdecl
+#define LANG_HOOKS_GETDECLS getdecls
+#define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL lhd_warn_unused_global_decl
+#define LANG_HOOKS_WRITE_GLOBALS write_global_declarations
+#define LANG_HOOKS_DECL_OK_FOR_SIBCALL lhd_decl_ok_for_sibcall
+
+#define LANG_HOOKS_DECLS { \
+ LANG_HOOKS_PUSHLEVEL, \
+ LANG_HOOKS_POPLEVEL, \
+ LANG_HOOKS_GLOBAL_BINDINGS_P, \
+ LANG_HOOKS_INSERT_BLOCK, \
+ LANG_HOOKS_SET_BLOCK, \
+ LANG_HOOKS_PUSHDECL, \
+ LANG_HOOKS_GETDECLS, \
+ LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, \
+ LANG_HOOKS_WRITE_GLOBALS, \
+ LANG_HOOKS_DECL_OK_FOR_SIBCALL, \
+}
/* The whole thing. The structure is defined in langhooks.h. */
#define LANG_HOOKS_INITIALIZER { \
@@ -149,21 +237,40 @@ int lhd_tree_dump_type_quals PARAMS ((tree));
LANG_HOOKS_POST_OPTIONS, \
LANG_HOOKS_INIT, \
LANG_HOOKS_FINISH, \
+ LANG_HOOKS_PARSE_FILE, \
LANG_HOOKS_CLEAR_BINDING_STACK, \
LANG_HOOKS_GET_ALIAS_SET, \
LANG_HOOKS_EXPAND_CONSTANT, \
+ LANG_HOOKS_EXPAND_EXPR, \
+ LANG_HOOKS_TRUTHVALUE_CONVERSION, \
+ LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES, \
LANG_HOOKS_SAFE_FROM_P, \
+ LANG_HOOKS_FINISH_INCOMPLETE_DECL, \
+ LANG_HOOKS_UNSAFE_FOR_REEVAL, \
+ LANG_HOOKS_MARK_ADDRESSABLE, \
LANG_HOOKS_STATICP, \
+ LANG_HOOKS_DUP_LANG_SPECIFIC_DECL, \
+ LANG_HOOKS_UNSAVE_EXPR_NOW, \
+ LANG_HOOKS_MAYBE_BUILD_CLEANUP, \
+ LANG_HOOKS_SET_DECL_ASSEMBLER_NAME, \
+ LANG_HOOKS_CAN_USE_BIT_FIELDS_P, \
LANG_HOOKS_HONOR_READONLY, \
LANG_HOOKS_PRINT_STATISTICS, \
LANG_HOOKS_PRINT_XNODE, \
LANG_HOOKS_PRINT_DECL, \
LANG_HOOKS_PRINT_TYPE, \
LANG_HOOKS_PRINT_IDENTIFIER, \
- LANG_HOOKS_SET_YYDEBUG, \
+ LANG_HOOKS_DECL_PRINTABLE_NAME, \
+ LANG_HOOKS_PRINT_ERROR_FUNCTION, \
LANG_HOOKS_EXPR_SIZE, \
+ LANG_HOOKS_ATTRIBUTE_TABLE, \
+ LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, \
+ LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE, \
+ LANG_HOOKS_FUNCTION_INITIALIZER, \
LANG_HOOKS_TREE_INLINING_INITIALIZER, \
- LANG_HOOKS_TREE_DUMP_INITIALIZER \
+ LANG_HOOKS_TREE_DUMP_INITIALIZER, \
+ LANG_HOOKS_DECLS, \
+ LANG_HOOKS_FOR_TYPES_INITIALIZER \
}
#endif /* GCC_LANG_HOOKS_DEF_H */
diff --git a/contrib/gcc/langhooks.c b/contrib/gcc/langhooks.c
index e50ebc9..8721121 100644
--- a/contrib/gcc/langhooks.c
+++ b/contrib/gcc/langhooks.c
@@ -1,5 +1,5 @@
/* Default language-specific hooks.
- Copyright 2001 Free Software Foundation, Inc.
+ Copyright 2001, 2002 Free Software Foundation, Inc.
Contributed by Alexandre Oliva <aoliva@redhat.com>
This file is part of GNU CC.
@@ -39,6 +39,30 @@ lhd_do_nothing ()
{
}
+/* Do nothing (tree). */
+
+void
+lhd_do_nothing_t (t)
+ tree t ATTRIBUTE_UNUSED;
+{
+}
+
+/* Do nothing (int). */
+
+void
+lhd_do_nothing_i (i)
+ int i ATTRIBUTE_UNUSED;
+{
+}
+
+/* Do nothing (function). */
+
+void
+lhd_do_nothing_f (f)
+ struct function *f ATTRIBUTE_UNUSED;
+{
+}
+
/* Do nothing (return the tree node passed). */
tree
@@ -48,6 +72,15 @@ lhd_return_tree (t)
return t;
}
+/* Do nothing (return NULL_TREE). */
+
+tree
+lhd_return_null_tree (t)
+ tree t ATTRIBUTE_UNUSED;
+{
+ return NULL_TREE;
+}
+
/* Do nothing; the default hook to decode an option. */
int
@@ -78,6 +111,15 @@ lhd_safe_from_p (x, exp)
return 1;
}
+/* Called from unsafe_for_reeval. */
+
+int
+lhd_unsafe_for_reeval (t)
+ tree t ATTRIBUTE_UNUSED;
+{
+ return -1;
+}
+
/* Called from staticp. */
int
@@ -87,14 +129,57 @@ lhd_staticp (exp)
return 0;
}
-/* Called when -dy is given on the command line. */
+/* Called from check_global_declarations. */
+
+bool
+lhd_warn_unused_global_decl (decl)
+ tree decl;
+{
+ /* This is what used to exist in check_global_declarations. Probably
+ not many of these actually apply to non-C languages. */
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
+ return false;
+ if (TREE_CODE (decl) == VAR_DECL && TREE_READONLY (decl))
+ return false;
+ if (DECL_IN_SYSTEM_HEADER (decl))
+ return false;
+
+ return true;
+}
+
+/* Set the DECL_ASSEMBLER_NAME for DECL. */
void
-lhd_set_yydebug (value)
- int value;
+lhd_set_decl_assembler_name (decl)
+ tree decl;
{
- if (value)
- fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
+ /* The language-independent code should never use the
+ DECL_ASSEMBLER_NAME for lots of DECLs. Only FUNCTION_DECLs and
+ VAR_DECLs for variables with static storage duration need a real
+ DECL_ASSEMBLER_NAME. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ || (TREE_CODE (decl) == VAR_DECL
+ && (TREE_STATIC (decl)
+ || DECL_EXTERNAL (decl)
+ || TREE_PUBLIC (decl))))
+ /* By default, assume the name to use in assembly code is the
+ same as that used in the source language. (That's correct
+ for C, and GCC used to set DECL_ASSEMBLER_NAME to the same
+ value as DECL_NAME in build_decl, so this choice provides
+ backwards compatibility with existing front-ends. */
+ SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
+ else
+ /* Nobody should ever be asking for the DECL_ASSEMBLER_NAME of
+ these DECLs -- unless they're in language-dependent code, in
+ which case set_decl_assembler_name hook should handle things. */
+ abort ();
+}
+
+/* By default we always allow bit-field based optimizations. */
+bool
+lhd_can_use_bit_fields_p ()
+{
+ return true;
}
/* Provide a default routine to clear the binding stack. This is used
@@ -102,10 +187,29 @@ lhd_set_yydebug (value)
void
lhd_clear_binding_stack ()
{
- while (! global_bindings_p ())
+ while (! (*lang_hooks.decls.global_bindings_p) ())
poplevel (0, 0, 0);
}
+/* Type promotion for variable arguments. */
+tree
+lhd_type_promotes_to (type)
+ tree type ATTRIBUTE_UNUSED;
+{
+ abort ();
+}
+
+/* Invalid use of an incomplete type. */
+void
+lhd_incomplete_type_error (value, type)
+ tree value ATTRIBUTE_UNUSED, type;
+{
+ if (TREE_CODE (type) == ERROR_MARK)
+ return;
+
+ abort ();
+}
+
/* Provide a default routine for alias sets that always returns -1. This
is used by languages that don't need to do anything special. */
@@ -126,6 +230,28 @@ hook_get_alias_set_0 (t)
return 0;
}
+/* This is the default expand_expr function. */
+
+rtx
+lhd_expand_expr (t, r, mm, em)
+ tree t ATTRIBUTE_UNUSED;
+ rtx r ATTRIBUTE_UNUSED;
+ enum machine_mode mm ATTRIBUTE_UNUSED;
+ int em ATTRIBUTE_UNUSED;
+{
+ abort ();
+}
+
+/* This is the default decl_printable_name function. */
+
+const char *
+lhd_decl_printable_name (decl, verbosity)
+ tree decl;
+ int verbosity ATTRIBUTE_UNUSED;
+{
+ return IDENTIFIER_POINTER (DECL_NAME (decl));
+}
+
/* lang_hooks.tree_inlining.walk_subtrees is called by walk_tree()
after handling common cases, but before walking code-specific
sub-trees. If this hook is overridden for a language, it should
@@ -134,7 +260,7 @@ hook_get_alias_set_0 (t)
completely handled within this function, it should set *SUBTREES to
0, so that generic handling isn't attempted. For language-specific
tree codes, generic handling would abort(), so make sure it is set
- properly. Both SUBTREES and *SUBTREES is guaranteed to be non-zero
+ properly. Both SUBTREES and *SUBTREES is guaranteed to be nonzero
when the function is called. */
tree
@@ -250,7 +376,7 @@ lhd_tree_inlining_anon_aggr_type_p (t)
/* lang_hooks.tree_inlining.start_inlining and end_inlining perform any
language-specific bookkeeping necessary for processing
- FN. start_inlining returns non-zero if inlining should proceed, zero if
+ FN. start_inlining returns nonzero if inlining should proceed, zero if
not.
For instance, the C++ version keeps track of template instantiations to
@@ -281,8 +407,8 @@ lhd_tree_inlining_convert_parm_for_inlining (parm, value, fndecl)
return value;
}
-/* lang_hooks.tree_dump.dump_tree: Dump language-specific parts of tree
- nodes. Returns non-zero if it does not want the usual dumping of the
+/* lang_hooks.tree_dump.dump_tree: Dump language-specific parts of tree
+ nodes. Returns nonzero if it does not want the usual dumping of the
second argument. */
int
@@ -293,7 +419,7 @@ lhd_tree_dump_dump_tree (di, t)
return 0;
}
-/* lang_hooks.tree_dump.type_qual: Determine type qualifiers in a
+/* lang_hooks.tree_dump.type_qual: Determine type qualifiers in a
language-specific way. */
int
@@ -316,3 +442,42 @@ lhd_expr_size (exp)
else
return size_in_bytes (TREE_TYPE (exp));
}
+
+/* Return true if decl, which is a function decl, may be called by a
+ sibcall. */
+
+bool
+lhd_decl_ok_for_sibcall (decl)
+ tree decl ATTRIBUTE_UNUSED;
+{
+ return true;
+}
+
+/* lang_hooks.decls.final_write_globals: perform final processing on
+ global variables. */
+void
+write_global_declarations ()
+{
+ /* Really define vars that have had only a tentative definition.
+ Really output inline functions that must actually be callable
+ and have not been output so far. */
+
+ tree globals = (*lang_hooks.decls.getdecls) ();
+ int len = list_length (globals);
+ tree *vec = (tree *) xmalloc (sizeof (tree) * len);
+ int i;
+ tree decl;
+
+ /* Process the decls in reverse order--earliest first.
+ Put them into VEC from back to front, then take out from front. */
+
+ for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
+ vec[len - i - 1] = decl;
+
+ wrapup_global_declarations (vec, len);
+
+ check_global_declarations (vec, len);
+
+ /* Clean up. */
+ free (vec);
+}
diff --git a/contrib/gcc/langhooks.h b/contrib/gcc/langhooks.h
index a77ddee..546e50e 100644
--- a/contrib/gcc/langhooks.h
+++ b/contrib/gcc/langhooks.h
@@ -1,5 +1,5 @@
/* The lang_hooks data structure.
- Copyright 2001 Free Software Foundation, Inc.
+ Copyright 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -21,6 +21,10 @@ Boston, MA 02111-1307, USA. */
#ifndef GCC_LANG_HOOKS_H
#define GCC_LANG_HOOKS_H
+/* This file should be #include-d after tree.h. */
+
+struct diagnostic_context;
+
/* A print hook for print_tree (). */
typedef void (*lang_print_tree_hook) PARAMS ((FILE *, tree, int indent));
@@ -54,11 +58,28 @@ struct lang_hooks_for_tree_inlining
union tree_node *));
};
+/* Lang hooks for management of language-specific data or status
+ when entering / leaving functions etc. */
+struct lang_hooks_for_functions
+{
+ /* Called when entering a function. */
+ void (*init) PARAMS ((struct function *));
+
+ /* Called when leaving a function. */
+ void (*final) PARAMS ((struct function *));
+
+ /* Called when entering a nested function. */
+ void (*enter_nested) PARAMS ((struct function *));
+
+ /* Called when leaving a nested function. */
+ void (*leave_nested) PARAMS ((struct function *));
+};
+
/* The following hooks are used by tree-dump.c. */
struct lang_hooks_for_tree_dump
{
- /* Dump language-specific parts of tree nodes. Returns non-zero if it
+ /* Dump language-specific parts of tree nodes. Returns nonzero if it
does not want the usual dumping of the second argument. */
int (*dump_tree) PARAMS ((void *, tree));
@@ -66,6 +87,95 @@ struct lang_hooks_for_tree_dump
int (*type_quals) PARAMS ((tree));
};
+/* Hooks related to types. */
+
+struct lang_hooks_for_types
+{
+ /* Return a new type (with the indicated CODE), doing whatever
+ language-specific processing is required. */
+ tree (*make_type) PARAMS ((enum tree_code));
+
+ /* Given MODE and UNSIGNEDP, return a suitable type-tree with that
+ mode. */
+ tree (*type_for_mode) PARAMS ((enum machine_mode, int));
+
+ /* Given PRECISION and UNSIGNEDP, return a suitable type-tree for an
+ integer type with at least that precision. */
+ tree (*type_for_size) PARAMS ((unsigned, int));
+
+ /* Given an integer type T, return a type like T but unsigned.
+ If T is unsigned, the value is T. */
+ tree (*unsigned_type) PARAMS ((tree));
+
+ /* Given an integer type T, return a type like T but signed.
+ If T is signed, the value is T. */
+ tree (*signed_type) PARAMS ((tree));
+
+ /* Return a type the same as TYPE except unsigned or signed
+ according to UNSIGNEDP. */
+ tree (*signed_or_unsigned_type) PARAMS ((int, tree));
+
+ /* Given a type, apply default promotions to unnamed function
+ arguments and return the new type. Return the same type if no
+ change. Required by any language that supports variadic
+ arguments. The default hook aborts. */
+ tree (*type_promotes_to) PARAMS ((tree));
+
+ /* This routine is called in tree.c to print an error message for
+ invalid use of an incomplete type. VALUE is the expression that
+ was used (or 0 if that isn't known) and TYPE is the type that was
+ invalid. */
+ void (*incomplete_type_error) PARAMS ((tree value, tree type));
+};
+
+/* Language hooks related to decls and the symbol table. */
+
+struct lang_hooks_for_decls
+{
+ /* Enter a new lexical scope. Argument is always zero when called
+ from outside the front end. */
+ void (*pushlevel) PARAMS ((int));
+
+ /* Exit a lexical scope and return a BINDING for that scope.
+ Takes three arguments:
+ KEEP -- nonzero if there were declarations in this scope.
+ REVERSE -- reverse the order of decls before returning them.
+ FUNCTIONBODY -- nonzero if this level is the body of a function. */
+ tree (*poplevel) PARAMS ((int, int, int));
+
+ /* Returns nonzero if we are in the global binding level. Ada
+ returns -1 for an undocumented reason used in stor-layout.c. */
+ int (*global_bindings_p) PARAMS ((void));
+
+ /* Insert BLOCK at the end of the list of subblocks of the
+ current binding level. This is used when a BIND_EXPR is expanded,
+ to handle the BLOCK node inside the BIND_EXPR. */
+ void (*insert_block) PARAMS ((tree));
+
+ /* Set the BLOCK node for the current scope level. */
+ void (*set_block) PARAMS ((tree));
+
+ /* Function to add a decl to the current scope level. Takes one
+ argument, a decl to add. Returns that decl, or, if the same
+ symbol is already declared, may return a different decl for that
+ name. */
+ tree (*pushdecl) PARAMS ((tree));
+
+ /* Returns the chain of decls so far in the current scope level. */
+ tree (*getdecls) PARAMS ((void));
+
+ /* Returns true when we should warn for an unused global DECL.
+ We will already have checked that it has static binding. */
+ bool (*warn_unused_global) PARAMS ((tree));
+
+ /* Obtain a list of globals and do final output on them at end
+ of compilation */
+ void (*final_write_globals) PARAMS ((void));
+
+ /* True if this decl may be called via a sibcall. */
+ bool (*ok_for_sibcall) PARAMS ((tree));
+};
+
/* Language-specific hooks. See langhooks-def.h for defaults. */
struct lang_hooks
@@ -84,7 +194,7 @@ struct lang_hooks
/* Function called with an option vector as argument, to decode a
single option (typically starting with -f or -W or +). It should
return the number of command-line arguments it uses if it handles
- the option, or 0 and not complain if it does not recognise the
+ the option, or 0 and not complain if it does not recognize the
option. If this function returns a negative number, then its
absolute value is the number of command-line arguments used, but,
in addition, no language-independent option processing should be
@@ -96,9 +206,12 @@ struct lang_hooks
initialization should be left to the "init" callback, since GC
and the identifier hashes are set up between now and then.
- If errorcount is non-zero after this call the compiler exits
+ Should return zero unless the compiler back-end does not need to
+ be initialized, such as with the -E option.
+
+ If errorcount is nonzero after this call the compiler exits
immediately and the finish hook is not called. */
- void (*post_options) PARAMS ((void));
+ bool (*post_options) PARAMS ((void));
/* Called after post_options, to initialize the front end. The main
input filename is passed, which may be NULL; the front end should
@@ -111,6 +224,10 @@ struct lang_hooks
/* Called at the end of compilation, as a finalizer. */
void (*finish) PARAMS ((void));
+ /* Parses the entire file. The argument is nonzero to cause bison
+ parsers to dump debugging information during parsing. */
+ void (*parse_file) PARAMS ((int));
+
/* Called immediately after parsing to clear the binding stack. */
void (*clear_binding_stack) PARAMS ((void));
@@ -123,6 +240,27 @@ struct lang_hooks
constant equivalent to its input. */
tree (*expand_constant) PARAMS ((tree));
+ /* Called by expand_expr for language-specific tree codes.
+ Fourth argument is actually an enum expand_modifier. */
+ rtx (*expand_expr) PARAMS ((tree, rtx, enum machine_mode, int));
+
+ /* Prepare expr to be an argument of a TRUTH_NOT_EXPR or other logical
+ operation.
+
+ This preparation consists of taking the ordinary representation
+ of an expression expr and producing a valid tree boolean
+ expression describing whether expr is nonzero. We could simply
+ always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
+ but we optimize comparisons, &&, ||, and !.
+
+ The result should be an expression of boolean type (if not an
+ error_mark_node). */
+ tree (*truthvalue_conversion) PARAMS ((tree));
+
+ /* Possibly apply default attributes to a function (represented by
+ a FUNCTION_DECL). */
+ void (*insert_default_attributes) PARAMS ((tree));
+
/* Hook called by safe_from_p for language-specific tree codes. It is
up to the language front-end to install a hook if it has any such
codes that safe_from_p needs to know about. Since same_from_p will
@@ -132,9 +270,47 @@ struct lang_hooks
parameter. */
int (*safe_from_p) PARAMS ((rtx, tree));
+ /* Function to finish handling an incomplete decl at the end of
+ compilation. Default hook is does nothing. */
+ void (*finish_incomplete_decl) PARAMS ((tree));
+
+ /* Function used by unsafe_for_reeval. A non-negative number is
+ returned directly from unsafe_for_reeval, a negative number falls
+ through. The default hook returns a negative number. */
+ int (*unsafe_for_reeval) PARAMS ((tree));
+
+ /* Mark EXP saying that we need to be able to take the address of
+ it; it should not be allocated in a register. Return true if
+ successful. */
+ bool (*mark_addressable) PARAMS ((tree));
+
/* Hook called by staticp for language-specific tree codes. */
int (*staticp) PARAMS ((tree));
+ /* Replace the DECL_LANG_SPECIFIC data, which may be NULL, of the
+ DECL_NODE with a newly GC-allocated copy. */
+ void (*dup_lang_specific_decl) PARAMS ((tree));
+
+ /* Called before its argument, an UNSAVE_EXPR, is to be
+ unsaved. Modify it in-place so that all the evaluate only once
+ things are cleared out. */
+ tree (*unsave_expr_now) PARAMS ((tree));
+
+ /* Called by expand_expr to build and return the cleanup-expression
+ for the passed TARGET_EXPR. Return NULL if there is none. */
+ tree (*maybe_build_cleanup) PARAMS ((tree));
+
+ /* Set the DECL_ASSEMBLER_NAME for a node. If it is the sort of
+ thing that the assembler should talk about, set
+ DECL_ASSEMBLER_NAME to an appropriate IDENTIFIER_NODE.
+ Otherwise, set it to the ERROR_MARK_NODE to ensure that the
+ assembler does not talk about it. */
+ void (*set_decl_assembler_name) PARAMS ((tree));
+
+ /* Return nonzero if fold-const is free to use bit-field
+ optimizations, for instance in fold_truthop(). */
+ bool (*can_use_bit_fields_p) PARAMS ((void));
+
/* Nonzero if TYPE_READONLY and TREE_READONLY should always be honored. */
bool honor_readonly;
@@ -152,10 +328,17 @@ struct lang_hooks
lang_print_tree_hook print_type;
lang_print_tree_hook print_identifier;
- /* Set yydebug for bison-based parsers, when -dy is given on the
- command line. By default, if the parameter is non-zero, prints a
- warning that the front end does not use such a parser. */
- void (*set_yydebug) PARAMS ((int));
+ /* Computes the name to use to print a declaration. DECL is the
+ non-NULL 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++. */
+ const char *(*decl_printable_name) PARAMS ((tree decl, int verbosity));
+
+ /* Called by report_error_function to print out function name. */
+ void (*print_error_function) PARAMS ((struct diagnostic_context *,
+ const char *));
/* Called from expr_size to calculate the size of the value of an
expression in a language-dependent way. Returns a tree for the size
@@ -163,10 +346,26 @@ struct lang_hooks
semantics in cases that it doesn't want to handle specially. */
tree (*expr_size) PARAMS ((tree));
+ /* Pointers to machine-independent attribute tables, for front ends
+ using attribs.c. If one is NULL, it is ignored. Respectively, a
+ table of attributes specific to the language, a table of
+ attributes common to two or more languages (to allow easy
+ sharing), and a table of attributes for checking formats. */
+ const struct attribute_spec *attribute_table;
+ const struct attribute_spec *common_attribute_table;
+ const struct attribute_spec *format_attribute_table;
+
+ /* Function-related language hooks. */
+ struct lang_hooks_for_functions function;
+
struct lang_hooks_for_tree_inlining tree_inlining;
-
+
struct lang_hooks_for_tree_dump tree_dump;
+ struct lang_hooks_for_decls decls;
+
+ struct lang_hooks_for_types types;
+
/* Whenever you add entries here, make sure you adjust langhooks-def.h
and langhooks.c accordingly. */
};
diff --git a/contrib/gcc/lbasename.c b/contrib/gcc/lbasename.c
index cea0253..43cb73f 100644
--- a/contrib/gcc/lbasename.c
+++ b/contrib/gcc/lbasename.c
@@ -1,6 +1,6 @@
/* Libiberty basename. Like basename, but is not overridden by the
system C library.
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
This file is part of the libiberty library.
Libiberty is free software; you can redistribute it and/or
@@ -53,19 +53,11 @@ and a path ending in @code{/} returns the empty string after it.
# endif
#endif
-/* Define IS_DIR_SEPARATOR. VMS uses '::', ':', '[...]' and '<...>' to
- separate the different components of a file specification. It's a
- bit of a stretch to call ':', ']' and '>' directory separators, so
- just define the test to find the file name component. */
-#ifdef VMS
-# define IS_DIR_SEPARATOR(ch) ((ch) == ':' || (ch) == ']' || (ch) == '>')
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
#else
-# ifndef DIR_SEPARATOR_2
-# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
-# else
-# define IS_DIR_SEPARATOR(ch) \
+# define IS_DIR_SEPARATOR(ch) \
(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
-# endif
#endif
const char *
diff --git a/contrib/gcc/lcm.c b/contrib/gcc/lcm.c
index 0a8a7ce..bdbae42 100644
--- a/contrib/gcc/lcm.c
+++ b/contrib/gcc/lcm.c
@@ -1,5 +1,5 @@
/* Generic partial redundancy elimination with lazy code motion support.
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -59,6 +59,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "insn-config.h"
#include "recog.h"
#include "basic-block.h"
+#include "output.h"
#include "tm_p.h"
/* We want target macros for the mode switching code to be able to refer
@@ -106,7 +107,7 @@ compute_antinout_edge (antloc, transp, antin, antout)
sbitmap *antin;
sbitmap *antout;
{
- int bb;
+ basic_block bb;
edge e;
basic_block *worklist, *qin, *qout, *qend;
unsigned int qlen;
@@ -119,14 +120,14 @@ compute_antinout_edge (antloc, transp, antin, antout)
/* We want a maximal solution, so make an optimistic initialization of
ANTIN. */
- sbitmap_vector_ones (antin, n_basic_blocks);
+ sbitmap_vector_ones (antin, last_basic_block);
/* Put every block on the worklist; this is necessary because of the
optimistic initialization of ANTIN above. */
- for (bb = n_basic_blocks - 1; bb >= 0; bb--)
+ FOR_EACH_BB_REVERSE (bb)
{
- *qin++ = BASIC_BLOCK (bb);
- BASIC_BLOCK (bb)->aux = BASIC_BLOCK (bb);
+ *qin++ =bb;
+ bb->aux = bb;
}
qin = worklist;
@@ -142,38 +143,38 @@ compute_antinout_edge (antloc, transp, antin, antout)
while (qlen)
{
/* Take the first entry off the worklist. */
- basic_block b = *qout++;
- bb = b->index;
+ bb = *qout++;
qlen--;
if (qout >= qend)
- qout = worklist;
+ qout = worklist;
- if (b->aux == EXIT_BLOCK_PTR)
+ if (bb->aux == EXIT_BLOCK_PTR)
/* Do not clear the aux field for blocks which are predecessors of
the EXIT block. That way we never add then to the worklist
again. */
- sbitmap_zero (antout[bb]);
+ sbitmap_zero (antout[bb->index]);
else
{
/* Clear the aux field of this block so that it can be added to
the worklist again if necessary. */
- b->aux = NULL;
- sbitmap_intersection_of_succs (antout[bb], antin, bb);
+ bb->aux = NULL;
+ sbitmap_intersection_of_succs (antout[bb->index], antin, bb->index);
}
- if (sbitmap_a_or_b_and_c (antin[bb], antloc[bb], transp[bb], antout[bb]))
+ if (sbitmap_a_or_b_and_c_cg (antin[bb->index], antloc[bb->index],
+ transp[bb->index], antout[bb->index]))
/* If the in state of this block changed, then we need
to add the predecessors of this block to the worklist
if they are not already on the worklist. */
- for (e = b->pred; e; e = e->pred_next)
+ for (e = bb->pred; e; e = e->pred_next)
if (!e->src->aux && e->src != ENTRY_BLOCK_PTR)
{
*qin++ = e->src;
e->src->aux = e;
qlen++;
if (qin >= qend)
- qin = worklist;
+ qin = worklist;
}
}
@@ -206,12 +207,8 @@ compute_earliest (edge_list, n_exprs, antin, antout, avout, kill, earliest)
if (pred == ENTRY_BLOCK_PTR)
sbitmap_copy (earliest[x], antin[succ->index]);
else
- {
- /* We refer to the EXIT_BLOCK index, instead of testing for
- EXIT_BLOCK_PTR, so that EXIT_BLOCK_PTR's index can be
- changed so as to pretend it's a regular block, so that
- its antin can be taken into account. */
- if (succ->index == EXIT_BLOCK)
+ {
+ if (succ == EXIT_BLOCK_PTR)
sbitmap_zero (earliest[x]);
else
{
@@ -262,9 +259,9 @@ compute_laterin (edge_list, earliest, antloc, later, laterin)
struct edge_list *edge_list;
sbitmap *earliest, *antloc, *later, *laterin;
{
- int bb, num_edges, i;
+ int num_edges, i;
edge e;
- basic_block *worklist, *qin, *qout, *qend;
+ basic_block *worklist, *qin, *qout, *qend, bb;
unsigned int qlen;
num_edges = NUM_EDGES (edge_list);
@@ -300,11 +297,10 @@ compute_laterin (edge_list, earliest, antloc, later, laterin)
/* Add all the blocks to the worklist. This prevents an early exit from
the loop given our optimistic initialization of LATER above. */
- for (bb = 0; bb < n_basic_blocks; bb++)
+ FOR_EACH_BB (bb)
{
- basic_block b = BASIC_BLOCK (bb);
- *qin++ = b;
- b->aux = b;
+ *qin++ = bb;
+ bb->aux = bb;
}
qin = worklist;
/* Note that we do not use the last allocated element for our queue,
@@ -317,24 +313,23 @@ compute_laterin (edge_list, earliest, antloc, later, laterin)
while (qlen)
{
/* Take the first entry off the worklist. */
- basic_block b = *qout++;
- b->aux = NULL;
+ bb = *qout++;
+ bb->aux = NULL;
qlen--;
if (qout >= qend)
- qout = worklist;
+ qout = worklist;
/* Compute the intersection of LATERIN for each incoming edge to B. */
- bb = b->index;
- sbitmap_ones (laterin[bb]);
- for (e = b->pred; e != NULL; e = e->pred_next)
- sbitmap_a_and_b (laterin[bb], laterin[bb], later[(size_t)e->aux]);
+ sbitmap_ones (laterin[bb->index]);
+ for (e = bb->pred; e != NULL; e = e->pred_next)
+ sbitmap_a_and_b (laterin[bb->index], laterin[bb->index], later[(size_t)e->aux]);
/* Calculate LATER for all outgoing edges. */
- for (e = b->succ; e != NULL; e = e->succ_next)
- if (sbitmap_union_of_diff (later[(size_t) e->aux],
- earliest[(size_t) e->aux],
- laterin[e->src->index],
- antloc[e->src->index])
+ for (e = bb->succ; e != NULL; e = e->succ_next)
+ if (sbitmap_union_of_diff_cg (later[(size_t) e->aux],
+ earliest[(size_t) e->aux],
+ laterin[e->src->index],
+ antloc[e->src->index])
/* If LATER for an outgoing edge was changed, then we need
to add the target of the outgoing edge to the worklist. */
&& e->dest != EXIT_BLOCK_PTR && e->dest->aux == 0)
@@ -350,10 +345,10 @@ compute_laterin (edge_list, earliest, antloc, later, laterin)
/* Computation of insertion and deletion points requires computing LATERIN
for the EXIT block. We allocated an extra entry in the LATERIN array
for just this purpose. */
- sbitmap_ones (laterin[n_basic_blocks]);
+ sbitmap_ones (laterin[last_basic_block]);
for (e = EXIT_BLOCK_PTR->pred; e != NULL; e = e->pred_next)
- sbitmap_a_and_b (laterin[n_basic_blocks],
- laterin[n_basic_blocks],
+ sbitmap_a_and_b (laterin[last_basic_block],
+ laterin[last_basic_block],
later[(size_t) e->aux]);
clear_aux_for_edges ();
@@ -369,16 +364,17 @@ compute_insert_delete (edge_list, antloc, later, laterin,
sbitmap *antloc, *later, *laterin, *insert, *delete;
{
int x;
+ basic_block bb;
- for (x = 0; x < n_basic_blocks; x++)
- sbitmap_difference (delete[x], antloc[x], laterin[x]);
+ FOR_EACH_BB (bb)
+ sbitmap_difference (delete[bb->index], antloc[bb->index], laterin[bb->index]);
for (x = 0; x < NUM_EDGES (edge_list); x++)
{
basic_block b = INDEX_EDGE_SUCC_BB (edge_list, x);
if (b == EXIT_BLOCK_PTR)
- sbitmap_difference (insert[x], later[x], laterin[n_basic_blocks]);
+ sbitmap_difference (insert[x], later[x], laterin[last_basic_block]);
else
sbitmap_difference (insert[x], later[x], laterin[b->index]);
}
@@ -414,29 +410,29 @@ pre_edge_lcm (file, n_exprs, transp, avloc, antloc, kill, insert, delete)
fprintf (file, "Edge List:\n");
verify_edge_list (file, edge_list);
print_edge_list (file, edge_list);
- dump_sbitmap_vector (file, "transp", "", transp, n_basic_blocks);
- dump_sbitmap_vector (file, "antloc", "", antloc, n_basic_blocks);
- dump_sbitmap_vector (file, "avloc", "", avloc, n_basic_blocks);
- dump_sbitmap_vector (file, "kill", "", kill, n_basic_blocks);
+ dump_sbitmap_vector (file, "transp", "", transp, last_basic_block);
+ dump_sbitmap_vector (file, "antloc", "", antloc, last_basic_block);
+ dump_sbitmap_vector (file, "avloc", "", avloc, last_basic_block);
+ dump_sbitmap_vector (file, "kill", "", kill, last_basic_block);
}
#endif
/* Compute global availability. */
- avin = sbitmap_vector_alloc (n_basic_blocks, n_exprs);
- avout = sbitmap_vector_alloc (n_basic_blocks, n_exprs);
+ avin = sbitmap_vector_alloc (last_basic_block, n_exprs);
+ avout = sbitmap_vector_alloc (last_basic_block, n_exprs);
compute_available (avloc, kill, avout, avin);
sbitmap_vector_free (avin);
/* Compute global anticipatability. */
- antin = sbitmap_vector_alloc (n_basic_blocks, n_exprs);
- antout = sbitmap_vector_alloc (n_basic_blocks, n_exprs);
+ antin = sbitmap_vector_alloc (last_basic_block, n_exprs);
+ antout = sbitmap_vector_alloc (last_basic_block, n_exprs);
compute_antinout_edge (antloc, transp, antin, antout);
#ifdef LCM_DEBUG_INFO
if (file)
{
- dump_sbitmap_vector (file, "antin", "", antin, n_basic_blocks);
- dump_sbitmap_vector (file, "antout", "", antout, n_basic_blocks);
+ dump_sbitmap_vector (file, "antin", "", antin, last_basic_block);
+ dump_sbitmap_vector (file, "antout", "", antout, last_basic_block);
}
#endif
@@ -456,13 +452,13 @@ pre_edge_lcm (file, n_exprs, transp, avloc, antloc, kill, insert, delete)
later = sbitmap_vector_alloc (num_edges, n_exprs);
/* Allocate an extra element for the exit block in the laterin vector. */
- laterin = sbitmap_vector_alloc (n_basic_blocks + 1, n_exprs);
+ laterin = sbitmap_vector_alloc (last_basic_block + 1, n_exprs);
compute_laterin (edge_list, earliest, antloc, later, laterin);
#ifdef LCM_DEBUG_INFO
if (file)
{
- dump_sbitmap_vector (file, "laterin", "", laterin, n_basic_blocks + 1);
+ dump_sbitmap_vector (file, "laterin", "", laterin, last_basic_block + 1);
dump_sbitmap_vector (file, "later", "", later, num_edges);
}
#endif
@@ -470,7 +466,7 @@ pre_edge_lcm (file, n_exprs, transp, avloc, antloc, kill, insert, delete)
sbitmap_vector_free (earliest);
*insert = sbitmap_vector_alloc (num_edges, n_exprs);
- *delete = sbitmap_vector_alloc (n_basic_blocks, n_exprs);
+ *delete = sbitmap_vector_alloc (last_basic_block, n_exprs);
compute_insert_delete (edge_list, antloc, later, laterin, *insert, *delete);
sbitmap_vector_free (laterin);
@@ -481,7 +477,7 @@ pre_edge_lcm (file, n_exprs, transp, avloc, antloc, kill, insert, delete)
{
dump_sbitmap_vector (file, "pre_insert_map", "", *insert, num_edges);
dump_sbitmap_vector (file, "pre_delete_map", "", *delete,
- n_basic_blocks);
+ last_basic_block);
}
#endif
@@ -495,9 +491,8 @@ void
compute_available (avloc, kill, avout, avin)
sbitmap *avloc, *kill, *avout, *avin;
{
- int bb;
edge e;
- basic_block *worklist, *qin, *qout, *qend;
+ basic_block *worklist, *qin, *qout, *qend, bb;
unsigned int qlen;
/* Allocate a worklist array/queue. Entries are only added to the
@@ -507,14 +502,14 @@ compute_available (avloc, kill, avout, avin)
= (basic_block *) xmalloc (sizeof (basic_block) * n_basic_blocks);
/* We want a maximal solution. */
- sbitmap_vector_ones (avout, n_basic_blocks);
+ sbitmap_vector_ones (avout, last_basic_block);
/* Put every block on the worklist; this is necessary because of the
optimistic initialization of AVOUT above. */
- for (bb = 0; bb < n_basic_blocks; bb++)
+ FOR_EACH_BB (bb)
{
- *qin++ = BASIC_BLOCK (bb);
- BASIC_BLOCK (bb)->aux = BASIC_BLOCK (bb);
+ *qin++ = bb;
+ bb->aux = bb;
}
qin = worklist;
@@ -530,33 +525,32 @@ compute_available (avloc, kill, avout, avin)
while (qlen)
{
/* Take the first entry off the worklist. */
- basic_block b = *qout++;
- bb = b->index;
+ bb = *qout++;
qlen--;
if (qout >= qend)
- qout = worklist;
+ qout = worklist;
/* If one of the predecessor blocks is the ENTRY block, then the
intersection of avouts is the null set. We can identify such blocks
by the special value in the AUX field in the block structure. */
- if (b->aux == ENTRY_BLOCK_PTR)
+ if (bb->aux == ENTRY_BLOCK_PTR)
/* Do not clear the aux field for blocks which are successors of the
ENTRY block. That way we never add then to the worklist again. */
- sbitmap_zero (avin[bb]);
+ sbitmap_zero (avin[bb->index]);
else
{
/* Clear the aux field of this block so that it can be added to
the worklist again if necessary. */
- b->aux = NULL;
- sbitmap_intersection_of_preds (avin[bb], avout, bb);
+ bb->aux = NULL;
+ sbitmap_intersection_of_preds (avin[bb->index], avout, bb->index);
}
- if (sbitmap_union_of_diff (avout[bb], avloc[bb], avin[bb], kill[bb]))
+ if (sbitmap_union_of_diff_cg (avout[bb->index], avloc[bb->index], avin[bb->index], kill[bb->index]))
/* If the out state of this block changed, then we need
to add the successors of this block to the worklist
if they are not already on the worklist. */
- for (e = b->succ; e; e = e->succ_next)
+ for (e = bb->succ; e; e = e->succ_next)
if (!e->dest->aux && e->dest != EXIT_BLOCK_PTR)
{
*qin++ = e->dest;
@@ -564,7 +558,7 @@ compute_available (avloc, kill, avout, avin)
qlen++;
if (qin >= qend)
- qin = worklist;
+ qin = worklist;
}
}
@@ -626,9 +620,9 @@ compute_nearerout (edge_list, farthest, st_avloc, nearer, nearerout)
struct edge_list *edge_list;
sbitmap *farthest, *st_avloc, *nearer, *nearerout;
{
- int bb, num_edges, i;
+ int num_edges, i;
edge e;
- basic_block *worklist, *tos;
+ basic_block *worklist, *tos, bb;
num_edges = NUM_EDGES (edge_list);
@@ -655,33 +649,31 @@ compute_nearerout (edge_list, farthest, st_avloc, nearer, nearerout)
/* Add all the blocks to the worklist. This prevents an early exit
from the loop given our optimistic initialization of NEARER. */
- for (bb = 0; bb < n_basic_blocks; bb++)
+ FOR_EACH_BB (bb)
{
- basic_block b = BASIC_BLOCK (bb);
- *tos++ = b;
- b->aux = b;
+ *tos++ = bb;
+ bb->aux = bb;
}
/* Iterate until the worklist is empty. */
while (tos != worklist)
{
/* Take the first entry off the worklist. */
- basic_block b = *--tos;
- b->aux = NULL;
+ bb = *--tos;
+ bb->aux = NULL;
/* Compute the intersection of NEARER for each outgoing edge from B. */
- bb = b->index;
- sbitmap_ones (nearerout[bb]);
- for (e = b->succ; e != NULL; e = e->succ_next)
- sbitmap_a_and_b (nearerout[bb], nearerout[bb],
+ sbitmap_ones (nearerout[bb->index]);
+ for (e = bb->succ; e != NULL; e = e->succ_next)
+ sbitmap_a_and_b (nearerout[bb->index], nearerout[bb->index],
nearer[(size_t) e->aux]);
/* Calculate NEARER for all incoming edges. */
- for (e = b->pred; e != NULL; e = e->pred_next)
- if (sbitmap_union_of_diff (nearer[(size_t) e->aux],
- farthest[(size_t) e->aux],
- nearerout[e->dest->index],
- st_avloc[e->dest->index])
+ for (e = bb->pred; e != NULL; e = e->pred_next)
+ if (sbitmap_union_of_diff_cg (nearer[(size_t) e->aux],
+ farthest[(size_t) e->aux],
+ nearerout[e->dest->index],
+ st_avloc[e->dest->index])
/* If NEARER for an incoming edge was changed, then we need
to add the source of the incoming edge to the worklist. */
&& e->src != ENTRY_BLOCK_PTR && e->src->aux == 0)
@@ -694,10 +686,10 @@ compute_nearerout (edge_list, farthest, st_avloc, nearer, nearerout)
/* Computation of insertion and deletion points requires computing NEAREROUT
for the ENTRY block. We allocated an extra entry in the NEAREROUT array
for just this purpose. */
- sbitmap_ones (nearerout[n_basic_blocks]);
+ sbitmap_ones (nearerout[last_basic_block]);
for (e = ENTRY_BLOCK_PTR->succ; e != NULL; e = e->succ_next)
- sbitmap_a_and_b (nearerout[n_basic_blocks],
- nearerout[n_basic_blocks],
+ sbitmap_a_and_b (nearerout[last_basic_block],
+ nearerout[last_basic_block],
nearer[(size_t) e->aux]);
clear_aux_for_edges ();
@@ -713,15 +705,16 @@ compute_rev_insert_delete (edge_list, st_avloc, nearer, nearerout,
sbitmap *st_avloc, *nearer, *nearerout, *insert, *delete;
{
int x;
+ basic_block bb;
- for (x = 0; x < n_basic_blocks; x++)
- sbitmap_difference (delete[x], st_avloc[x], nearerout[x]);
+ FOR_EACH_BB (bb)
+ sbitmap_difference (delete[bb->index], st_avloc[bb->index], nearerout[bb->index]);
for (x = 0; x < NUM_EDGES (edge_list); x++)
{
basic_block b = INDEX_EDGE_PRED_BB (edge_list, x);
if (b == ENTRY_BLOCK_PTR)
- sbitmap_difference (insert[x], nearer[x], nearerout[n_basic_blocks]);
+ sbitmap_difference (insert[x], nearer[x], nearerout[last_basic_block]);
else
sbitmap_difference (insert[x], nearer[x], nearerout[b->index]);
}
@@ -753,15 +746,15 @@ pre_edge_rev_lcm (file, n_exprs, transp, st_avloc, st_antloc, kill,
edge_list = create_edge_list ();
num_edges = NUM_EDGES (edge_list);
- st_antin = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, n_exprs);
- st_antout = (sbitmap *) sbitmap_vector_alloc (n_basic_blocks, n_exprs);
- sbitmap_vector_zero (st_antin, n_basic_blocks);
- sbitmap_vector_zero (st_antout, n_basic_blocks);
+ st_antin = (sbitmap *) sbitmap_vector_alloc (last_basic_block, n_exprs);
+ st_antout = (sbitmap *) sbitmap_vector_alloc (last_basic_block, n_exprs);
+ sbitmap_vector_zero (st_antin, last_basic_block);
+ sbitmap_vector_zero (st_antout, last_basic_block);
compute_antinout_edge (st_antloc, transp, st_antin, st_antout);
/* Compute global anticipatability. */
- st_avout = sbitmap_vector_alloc (n_basic_blocks, n_exprs);
- st_avin = sbitmap_vector_alloc (n_basic_blocks, n_exprs);
+ st_avout = sbitmap_vector_alloc (last_basic_block, n_exprs);
+ st_avin = sbitmap_vector_alloc (last_basic_block, n_exprs);
compute_available (st_avloc, kill, st_avout, st_avin);
#ifdef LCM_DEBUG_INFO
@@ -770,20 +763,20 @@ pre_edge_rev_lcm (file, n_exprs, transp, st_avloc, st_antloc, kill,
fprintf (file, "Edge List:\n");
verify_edge_list (file, edge_list);
print_edge_list (file, edge_list);
- dump_sbitmap_vector (file, "transp", "", transp, n_basic_blocks);
- dump_sbitmap_vector (file, "st_avloc", "", st_avloc, n_basic_blocks);
- dump_sbitmap_vector (file, "st_antloc", "", st_antloc, n_basic_blocks);
- dump_sbitmap_vector (file, "st_antin", "", st_antin, n_basic_blocks);
- dump_sbitmap_vector (file, "st_antout", "", st_antout, n_basic_blocks);
- dump_sbitmap_vector (file, "st_kill", "", kill, n_basic_blocks);
+ dump_sbitmap_vector (file, "transp", "", transp, last_basic_block);
+ dump_sbitmap_vector (file, "st_avloc", "", st_avloc, last_basic_block);
+ dump_sbitmap_vector (file, "st_antloc", "", st_antloc, last_basic_block);
+ dump_sbitmap_vector (file, "st_antin", "", st_antin, last_basic_block);
+ dump_sbitmap_vector (file, "st_antout", "", st_antout, last_basic_block);
+ dump_sbitmap_vector (file, "st_kill", "", kill, last_basic_block);
}
#endif
#ifdef LCM_DEBUG_INFO
if (file)
{
- dump_sbitmap_vector (file, "st_avout", "", st_avout, n_basic_blocks);
- dump_sbitmap_vector (file, "st_avin", "", st_avin, n_basic_blocks);
+ dump_sbitmap_vector (file, "st_avout", "", st_avout, last_basic_block);
+ dump_sbitmap_vector (file, "st_avin", "", st_avin, last_basic_block);
}
#endif
@@ -806,14 +799,14 @@ pre_edge_rev_lcm (file, n_exprs, transp, st_avloc, st_antloc, kill,
nearer = sbitmap_vector_alloc (num_edges, n_exprs);
/* Allocate an extra element for the entry block. */
- nearerout = sbitmap_vector_alloc (n_basic_blocks + 1, n_exprs);
+ nearerout = sbitmap_vector_alloc (last_basic_block + 1, n_exprs);
compute_nearerout (edge_list, farthest, st_avloc, nearer, nearerout);
#ifdef LCM_DEBUG_INFO
if (file)
{
dump_sbitmap_vector (file, "nearerout", "", nearerout,
- n_basic_blocks + 1);
+ last_basic_block + 1);
dump_sbitmap_vector (file, "nearer", "", nearer, num_edges);
}
#endif
@@ -821,7 +814,7 @@ pre_edge_rev_lcm (file, n_exprs, transp, st_avloc, st_antloc, kill,
sbitmap_vector_free (farthest);
*insert = sbitmap_vector_alloc (num_edges, n_exprs);
- *delete = sbitmap_vector_alloc (n_basic_blocks, n_exprs);
+ *delete = sbitmap_vector_alloc (last_basic_block, n_exprs);
compute_rev_insert_delete (edge_list, st_avloc, nearer, nearerout,
*insert, *delete);
@@ -833,7 +826,7 @@ pre_edge_rev_lcm (file, n_exprs, transp, st_avloc, st_antloc, kill,
{
dump_sbitmap_vector (file, "pre_insert_map", "", *insert, num_edges);
dump_sbitmap_vector (file, "pre_delete_map", "", *delete,
- n_basic_blocks);
+ last_basic_block);
}
#endif
return edge_list;
@@ -937,7 +930,7 @@ add_seginfo (head, info)
{
ptr = head->seginfo;
while (ptr->next != NULL)
- ptr = ptr->next;
+ ptr = ptr->next;
ptr->next = info;
}
}
@@ -1018,63 +1011,76 @@ optimize_mode_switching (file)
FILE *file;
{
rtx insn;
- int bb, e;
+ int e;
+ basic_block bb;
int need_commit = 0;
sbitmap *kill;
struct edge_list *edge_list;
static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING;
-#define N_ENTITIES (sizeof num_modes / sizeof (int))
+#define N_ENTITIES ARRAY_SIZE (num_modes)
int entity_map[N_ENTITIES];
struct bb_info *bb_info[N_ENTITIES];
int i, j;
int n_entities;
int max_num_modes = 0;
bool emited = false;
+ basic_block post_entry ATTRIBUTE_UNUSED, pre_exit ATTRIBUTE_UNUSED;
-#ifdef NORMAL_MODE
- /* Increment n_basic_blocks before allocating bb_info. */
- n_basic_blocks++;
-#endif
+ clear_bb_flags ();
for (e = N_ENTITIES - 1, n_entities = 0; e >= 0; e--)
if (OPTIMIZE_MODE_SWITCHING (e))
{
- /* Create the list of segments within each basic block. */
+ int entry_exit_extra = 0;
+
+ /* Create the list of segments within each basic block.
+ If NORMAL_MODE is defined, allow for two extra
+ blocks split from the entry and exit block. */
+#ifdef NORMAL_MODE
+ entry_exit_extra = 2;
+#endif
bb_info[n_entities]
- = (struct bb_info *) xcalloc (n_basic_blocks, sizeof **bb_info);
+ = (struct bb_info *) xcalloc (last_basic_block + entry_exit_extra,
+ sizeof **bb_info);
entity_map[n_entities++] = e;
if (num_modes[e] > max_num_modes)
max_num_modes = num_modes[e];
}
-#ifdef NORMAL_MODE
- /* Decrement it back in case we return below. */
- n_basic_blocks--;
-#endif
-
if (! n_entities)
return 0;
#ifdef NORMAL_MODE
- /* We're going to pretend the EXIT_BLOCK is a regular basic block,
- so that switching back to normal mode when entering the
- EXIT_BLOCK isn't optimized away. We do this by incrementing the
- basic block count, growing the VARRAY of basic_block_info and
- appending the EXIT_BLOCK_PTR to it. */
- n_basic_blocks++;
- if (VARRAY_SIZE (basic_block_info) < n_basic_blocks)
- VARRAY_GROW (basic_block_info, n_basic_blocks);
- BASIC_BLOCK (n_basic_blocks - 1) = EXIT_BLOCK_PTR;
- EXIT_BLOCK_PTR->index = n_basic_blocks - 1;
+ {
+ /* Split the edge from the entry block and the fallthrough edge to the
+ exit block, so that we can note that there NORMAL_MODE is supplied /
+ required. */
+ edge eg;
+ post_entry = split_edge (ENTRY_BLOCK_PTR->succ);
+ /* The only non-call predecessor at this stage is a block with a
+ fallthrough edge; there can be at most one, but there could be
+ none at all, e.g. when exit is called. */
+ for (pre_exit = 0, eg = EXIT_BLOCK_PTR->pred; eg; eg = eg->pred_next)
+ if (eg->flags & EDGE_FALLTHRU)
+ {
+ regset live_at_end = eg->src->global_live_at_end;
+
+ if (pre_exit)
+ abort ();
+ pre_exit = split_edge (eg);
+ COPY_REG_SET (pre_exit->global_live_at_start, live_at_end);
+ COPY_REG_SET (pre_exit->global_live_at_end, live_at_end);
+ }
+ }
#endif
/* Create the bitmap vectors. */
- antic = sbitmap_vector_alloc (n_basic_blocks, n_entities);
- transp = sbitmap_vector_alloc (n_basic_blocks, n_entities);
- comp = sbitmap_vector_alloc (n_basic_blocks, n_entities);
+ antic = sbitmap_vector_alloc (last_basic_block, n_entities);
+ transp = sbitmap_vector_alloc (last_basic_block, n_entities);
+ comp = sbitmap_vector_alloc (last_basic_block, n_entities);
- sbitmap_vector_ones (transp, n_basic_blocks);
+ sbitmap_vector_ones (transp, last_basic_block);
for (j = n_entities - 1; j >= 0; j--)
{
@@ -1085,16 +1091,16 @@ optimize_mode_switching (file)
/* Determine what the first use (if any) need for a mode of entity E is.
This will be the mode that is anticipatable for this block.
Also compute the initial transparency settings. */
- for (bb = 0 ; bb < n_basic_blocks; bb++)
+ FOR_EACH_BB (bb)
{
struct seginfo *ptr;
int last_mode = no_mode;
HARD_REG_SET live_now;
REG_SET_TO_HARD_REG_SET (live_now,
- BASIC_BLOCK (bb)->global_live_at_start);
- for (insn = BLOCK_HEAD (bb);
- insn != NULL && insn != NEXT_INSN (BLOCK_END (bb));
+ bb->global_live_at_start);
+ for (insn = bb->head;
+ insn != NULL && insn != NEXT_INSN (bb->end);
insn = NEXT_INSN (insn))
{
if (INSN_P (insn))
@@ -1105,9 +1111,9 @@ optimize_mode_switching (file)
if (mode != no_mode && mode != last_mode)
{
last_mode = mode;
- ptr = new_seginfo (mode, insn, bb, live_now);
- add_seginfo (info + bb, ptr);
- RESET_BIT (transp[bb], j);
+ ptr = new_seginfo (mode, insn, bb->index, live_now);
+ add_seginfo (info + bb->index, ptr);
+ RESET_BIT (transp[bb->index], j);
}
/* Update LIVE_NOW. */
@@ -1122,12 +1128,12 @@ optimize_mode_switching (file)
}
}
- info[bb].computing = last_mode;
+ info[bb->index].computing = last_mode;
/* Check for blocks without ANY mode requirements. */
if (last_mode == no_mode)
{
- ptr = new_seginfo (no_mode, insn, bb, live_now);
- add_seginfo (info + bb, ptr);
+ ptr = new_seginfo (no_mode, bb->end, bb->index, live_now);
+ add_seginfo (info + bb->index, ptr);
}
}
#ifdef NORMAL_MODE
@@ -1136,69 +1142,54 @@ optimize_mode_switching (file)
if (mode != no_mode)
{
- edge eg;
+ bb = post_entry;
- for (eg = ENTRY_BLOCK_PTR->succ; eg; eg = eg->succ_next)
- {
- bb = eg->dest->index;
-
- /* By always making this nontransparent, we save
- an extra check in make_preds_opaque. We also
- need this to avoid confusing pre_edge_lcm when
- antic is cleared but transp and comp are set. */
- RESET_BIT (transp[bb], j);
-
- /* If the block already has MODE, pretend it
- has none (because we don't need to set it),
- but retain whatever mode it computes. */
- if (info[bb].seginfo->mode == mode)
- info[bb].seginfo->mode = no_mode;
-
- /* Insert a fake computing definition of MODE into entry
- blocks which compute no mode. This represents the mode on
- entry. */
- else if (info[bb].computing == no_mode)
- {
- info[bb].computing = mode;
- info[bb].seginfo->mode = no_mode;
- }
- }
+ /* By always making this nontransparent, we save
+ an extra check in make_preds_opaque. We also
+ need this to avoid confusing pre_edge_lcm when
+ antic is cleared but transp and comp are set. */
+ RESET_BIT (transp[bb->index], j);
- bb = n_basic_blocks - 1;
- info[bb].seginfo->mode = mode;
+ /* Insert a fake computing definition of MODE into entry
+ blocks which compute no mode. This represents the mode on
+ entry. */
+ info[bb->index].computing = mode;
+
+ if (pre_exit)
+ info[pre_exit->index].seginfo->mode = mode;
}
}
#endif /* NORMAL_MODE */
}
- kill = sbitmap_vector_alloc (n_basic_blocks, n_entities);
+ kill = sbitmap_vector_alloc (last_basic_block, n_entities);
for (i = 0; i < max_num_modes; i++)
{
int current_mode[N_ENTITIES];
/* Set the anticipatable and computing arrays. */
- sbitmap_vector_zero (antic, n_basic_blocks);
- sbitmap_vector_zero (comp, n_basic_blocks);
+ sbitmap_vector_zero (antic, last_basic_block);
+ sbitmap_vector_zero (comp, last_basic_block);
for (j = n_entities - 1; j >= 0; j--)
{
int m = current_mode[j] = MODE_PRIORITY_TO_MODE (entity_map[j], i);
struct bb_info *info = bb_info[j];
- for (bb = 0 ; bb < n_basic_blocks; bb++)
+ FOR_EACH_BB (bb)
{
- if (info[bb].seginfo->mode == m)
- SET_BIT (antic[bb], j);
+ if (info[bb->index].seginfo->mode == m)
+ SET_BIT (antic[bb->index], j);
- if (info[bb].computing == m)
- SET_BIT (comp[bb], j);
+ if (info[bb->index].computing == m)
+ SET_BIT (comp[bb->index], j);
}
}
/* Calculate the optimal locations for the
placement mode switches to modes with priority I. */
- for (bb = n_basic_blocks - 1; bb >= 0; bb--)
- sbitmap_not (kill[bb], transp[bb]);
+ FOR_EACH_BB (bb)
+ sbitmap_not (kill[bb->index], transp[bb->index]);
edge_list = pre_edge_lcm (file, 1, transp, comp, antic,
kill, &insert, &delete);
@@ -1237,12 +1228,11 @@ optimize_mode_switching (file)
start_sequence ();
EMIT_MODE_SET (entity_map[j], mode, live_at_edge);
- mode_set = gen_sequence ();
+ mode_set = get_insns ();
end_sequence ();
/* Do not bother to insert empty sequence. */
- if (GET_CODE (mode_set) == SEQUENCE
- && !XVECLEN (mode_set, 0))
+ if (mode_set == NULL_RTX)
continue;
/* If this is an abnormal edge, we'll insert at the end
@@ -1277,12 +1267,12 @@ optimize_mode_switching (file)
}
}
- for (bb = n_basic_blocks - 1; bb >= 0; bb--)
- if (TEST_BIT (delete[bb], j))
+ FOR_EACH_BB_REVERSE (bb)
+ if (TEST_BIT (delete[bb->index], j))
{
- make_preds_opaque (BASIC_BLOCK (bb), j);
+ make_preds_opaque (bb, j);
/* Cancel the 'deleted' mode set. */
- bb_info[j][bb].seginfo->mode = no_mode;
+ bb_info[j][bb->index].seginfo->mode = no_mode;
}
}
@@ -1290,67 +1280,15 @@ optimize_mode_switching (file)
free_edge_list (edge_list);
}
-#ifdef NORMAL_MODE
- /* Restore the special status of EXIT_BLOCK. */
- n_basic_blocks--;
- VARRAY_POP (basic_block_info);
- EXIT_BLOCK_PTR->index = EXIT_BLOCK;
-#endif
-
/* Now output the remaining mode sets in all the segments. */
for (j = n_entities - 1; j >= 0; j--)
{
int no_mode = num_modes[entity_map[j]];
-#ifdef NORMAL_MODE
- if (bb_info[j][n_basic_blocks].seginfo->mode != no_mode)
- {
- edge eg;
- struct seginfo *ptr = bb_info[j][n_basic_blocks].seginfo;
-
- for (eg = EXIT_BLOCK_PTR->pred; eg; eg = eg->pred_next)
- {
- rtx mode_set;
-
- if (bb_info[j][eg->src->index].computing == ptr->mode)
- continue;
-
- start_sequence ();
- EMIT_MODE_SET (entity_map[j], ptr->mode, ptr->regs_live);
- mode_set = gen_sequence ();
- end_sequence ();
-
- /* Do not bother to insert empty sequence. */
- if (GET_CODE (mode_set) == SEQUENCE
- && !XVECLEN (mode_set, 0))
- continue;
-
- /* If this is an abnormal edge, we'll insert at the end of the
- previous block. */
- if (eg->flags & EDGE_ABNORMAL)
- {
- emited = true;
- if (GET_CODE (eg->src->end) == JUMP_INSN)
- emit_insn_before (mode_set, eg->src->end);
- else if (GET_CODE (eg->src->end) == INSN)
- emit_insn_after (mode_set, eg->src->end);
- else
- abort ();
- }
- else
- {
- need_commit = 1;
- insert_insn_on_edge (mode_set, eg);
- }
- }
-
- }
-#endif
-
- for (bb = n_basic_blocks - 1; bb >= 0; bb--)
+ FOR_EACH_BB_REVERSE (bb)
{
struct seginfo *ptr, *next;
- for (ptr = bb_info[j][bb].seginfo; ptr; ptr = next)
+ for (ptr = bb_info[j][bb->index].seginfo; ptr; ptr = next)
{
next = ptr->next;
if (ptr->mode != no_mode)
@@ -1359,12 +1297,11 @@ optimize_mode_switching (file)
start_sequence ();
EMIT_MODE_SET (entity_map[j], ptr->mode, ptr->regs_live);
- mode_set = gen_sequence ();
+ mode_set = get_insns ();
end_sequence ();
/* Do not bother to insert empty sequence. */
- if (GET_CODE (mode_set) == SEQUENCE
- && !XVECLEN (mode_set, 0))
+ if (mode_set == NULL_RTX)
continue;
emited = true;
@@ -1395,19 +1332,18 @@ optimize_mode_switching (file)
if (need_commit)
commit_edge_insertions ();
+#ifdef NORMAL_MODE
+ cleanup_cfg (CLEANUP_NO_INSN_DEL);
+#else
if (!need_commit && !emited)
return 0;
+#endif
- /* Ideally we'd figure out what blocks were affected and start from
- there, but this is enormously complicated by commit_edge_insertions,
- which would screw up any indices we'd collected, and also need to
- be involved in the update. Bail and recompute global life info for
- everything. */
-
- allocate_reg_life_data ();
- update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
- (PROP_DEATH_NOTES | PROP_KILL_DEAD_CODE
- | PROP_SCAN_DEAD_CODE | PROP_REG_INFO));
+ max_regno = max_reg_num ();
+ allocate_reg_info (max_regno, FALSE, FALSE);
+ update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
+ (PROP_DEATH_NOTES | PROP_KILL_DEAD_CODE
+ | PROP_SCAN_DEAD_CODE));
return 1;
}
diff --git a/contrib/gcc/libfuncs.h b/contrib/gcc/libfuncs.h
index c3fa09e..bb2aa17 100644
--- a/contrib/gcc/libfuncs.h
+++ b/contrib/gcc/libfuncs.h
@@ -148,7 +148,7 @@ enum libfunc_index
/* SYMBOL_REF rtx's for the library functions that are called
implicitly and not via optabs. */
-extern rtx libfunc_table[LTI_MAX];
+extern GTY(()) rtx libfunc_table[LTI_MAX];
/* Accessor macros for libfunc_table. */
#define extendsfdf2_libfunc (libfunc_table[LTI_extendsfdf2])
diff --git a/contrib/gcc/libgcc-std.ver b/contrib/gcc/libgcc-std.ver
index 6bc4221..fc686c4 100644
--- a/contrib/gcc/libgcc-std.ver
+++ b/contrib/gcc/libgcc-std.ver
@@ -175,3 +175,12 @@ GCC_3.0 {
_Unwind_SjLj_ForcedUnwind
_Unwind_SjLj_Resume
}
+
+%inherit GCC_3.3 GCC_3.0
+GCC_3.3 {
+ _Unwind_FindEnclosingFunction
+ _Unwind_GetCFA
+ _Unwind_Backtrace
+ _Unwind_Resume_or_Rethrow
+ _Unwind_SjLj_Resume_or_Rethrow
+}
diff --git a/contrib/gcc/libgcc2.c b/contrib/gcc/libgcc2.c
index dd5eee7..dea803d 100644
--- a/contrib/gcc/libgcc2.c
+++ b/contrib/gcc/libgcc2.c
@@ -43,10 +43,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "libgcc2.h"
-#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
-#if defined (L_divdi3) || defined (L_moddi3)
-static inline
+#ifdef DECLARE_LIBRARY_RENAMES
+ DECLARE_LIBRARY_RENAMES
#endif
+
+#if defined (L_negdi2)
DWtype
__negdi2 (DWtype u)
{
@@ -149,9 +150,9 @@ __mulvsi3 (Wtype a, Wtype b)
Wtype
__negvsi2 (Wtype a)
{
- Wtype w;
+ Wtype w;
- w = -a;
+ w = -a;
if (a >= 0 ? w > 0 : w < 0)
abort ();
@@ -164,14 +165,14 @@ __negvsi2 (Wtype a)
DWtype
__negvdi2 (DWtype a)
{
- DWtype w;
+ DWtype w;
- w = -a;
+ w = -a;
if (a >= 0 ? w > 0 : w < 0)
abort ();
- return w;
+ return w;
}
#endif
@@ -179,16 +180,16 @@ __negvdi2 (DWtype a)
Wtype
__absvsi2 (Wtype a)
{
- Wtype w = a;
+ Wtype w = a;
- if (a < 0)
+ if (a < 0)
#ifdef L_negvsi2
- w = __negvsi2 (a);
+ w = __negvsi2 (a);
#else
- w = -a;
+ w = -a;
- if (w < 0)
- abort ();
+ if (w < 0)
+ abort ();
#endif
return w;
@@ -199,19 +200,19 @@ __absvsi2 (Wtype a)
DWtype
__absvdi2 (DWtype a)
{
- DWtype w = a;
+ DWtype w = a;
- if (a < 0)
+ if (a < 0)
#ifdef L_negvsi2
- w = __negvsi2 (a);
+ w = __negvsi2 (a);
#else
- w = -a;
+ w = -a;
- if (w < 0)
- abort ();
+ if (w < 0)
+ abort ();
#endif
- return w;
+ return w;
}
#endif
@@ -219,7 +220,7 @@ __absvdi2 (DWtype a)
DWtype
__mulvdi3 (DWtype u, DWtype v)
{
- DWtype w;
+ DWtype w;
w = u * v;
@@ -365,8 +366,19 @@ __muldi3 (DWtype u, DWtype v)
}
#endif
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+ defined (L_umoddi3) || defined (L_moddi3))
+#if defined (sdiv_qrnnd)
+#define L_udiv_w_sdiv
+#endif
+#endif
+
#ifdef L_udiv_w_sdiv
#if defined (sdiv_qrnnd)
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+ defined (L_umoddi3) || defined (L_moddi3))
+static inline __attribute__ ((__always_inline__))
+#endif
UWtype
__udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d)
{
@@ -499,7 +511,7 @@ const UQItype __clz_tab[] =
#if (defined (L_udivdi3) || defined (L_divdi3) || \
defined (L_umoddi3) || defined (L_moddi3))
-static inline
+static inline __attribute__ ((__always_inline__))
#endif
UDWtype
__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
@@ -732,14 +744,14 @@ __divdi3 (DWtype u, DWtype v)
if (uu.s.high < 0)
c = ~c,
- uu.ll = __negdi2 (uu.ll);
+ uu.ll = -uu.ll;
if (vv.s.high < 0)
c = ~c,
- vv.ll = __negdi2 (vv.ll);
+ vv.ll = -vv.ll;
w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
if (c)
- w = __negdi2 (w);
+ w = -w;
return w;
}
@@ -758,13 +770,13 @@ __moddi3 (DWtype u, DWtype v)
if (uu.s.high < 0)
c = ~c,
- uu.ll = __negdi2 (uu.ll);
+ uu.ll = -uu.ll;
if (vv.s.high < 0)
- vv.ll = __negdi2 (vv.ll);
+ vv.ll = -vv.ll;
(void) __udivmoddi4 (uu.ll, vv.ll, &w);
if (c)
- w = __negdi2 (w);
+ w = -w;
return w;
}
@@ -1063,35 +1075,10 @@ __floatdidf (DWtype u)
#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
-
-/* Define codes for all the float formats that we know of. Note
- that this is copied from real.h. */
-
-#define UNKNOWN_FLOAT_FORMAT 0
-#define IEEE_FLOAT_FORMAT 1
-#define VAX_FLOAT_FORMAT 2
-#define IBM_FLOAT_FORMAT 3
-
-/* Default to IEEE float if not specified. Nearly all machines use it. */
-#ifndef HOST_FLOAT_FORMAT
-#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-#endif
-#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-#define DF_SIZE 53
-#define SF_SIZE 24
-#endif
-
-#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
-#define DF_SIZE 56
-#define SF_SIZE 24
-#endif
-
-#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
-#define DF_SIZE 56
-#define SF_SIZE 24
-#endif
+#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
+#define DF_SIZE DBL_MANT_DIG
+#define SF_SIZE FLT_MANT_DIG
SFtype
__floatdisf (DWtype u)
@@ -1264,14 +1251,13 @@ __eprintf (const char *string, const char *expression,
#ifdef L_bb
-#if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
-typedef long gcov_type;
-#else
-typedef long long gcov_type;
-#endif
-
+struct bb_function_info {
+ long checksum;
+ int arc_count;
+ const char *name;
+};
-/* Structure emitted by -a */
+/* Structure emitted by --profile-arcs */
struct bb
{
long zero_word;
@@ -1279,26 +1265,19 @@ struct bb
gcov_type *counts;
long ncounts;
struct bb *next;
- const unsigned long *addresses;
/* Older GCC's did not emit these fields. */
- long nwords;
- const char **functions;
- const long *line_nums;
- const char **filenames;
- char *flags;
+ long sizeof_bb;
+ struct bb_function_info *function_infos;
};
#ifndef inhibit_libc
-/* Simple minded basic block profiling output dumper for
- systems that don't provide tcov support. At present,
- it requires atexit and stdio. */
+/* Arc profile dumper. Requires atexit and stdio. */
#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
#include <stdio.h>
-#include "gbl-ctors.h"
#include "gcov-io.h"
#include <string.h>
#ifdef TARGET_HAS_F_SETLKW
@@ -1306,162 +1285,272 @@ struct bb
#include <errno.h>
#endif
+/* Chain of per-object file bb structures. */
static struct bb *bb_head;
+/* Dump the coverage counts. We merge with existing counts when
+ possible, to avoid growing the .da files ad infinitum. */
+
void
__bb_exit_func (void)
{
- FILE *da_file;
- int i;
struct bb *ptr;
+ int i;
+ gcov_type program_sum = 0;
+ gcov_type program_max = 0;
+ long program_arcs = 0;
+ gcov_type merged_sum = 0;
+ gcov_type merged_max = 0;
+ long merged_arcs = 0;
+
+#if defined (TARGET_HAS_F_SETLKW)
+ struct flock s_flock;
- if (bb_head == 0)
- return;
-
- i = strlen (bb_head->filename) - 3;
-
+ s_flock.l_type = F_WRLCK;
+ s_flock.l_whence = SEEK_SET;
+ s_flock.l_start = 0;
+ s_flock.l_len = 0; /* Until EOF. */
+ s_flock.l_pid = getpid ();
+#endif
- for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
+ /* Non-merged stats for this program. */
+ for (ptr = bb_head; ptr; ptr = ptr->next)
{
- int firstchar;
-
- /* Make sure the output file exists -
- but don't clobber exiting data. */
- if ((da_file = fopen (ptr->filename, "a")) != 0)
- fclose (da_file);
+ for (i = 0; i < ptr->ncounts; i++)
+ {
+ program_sum += ptr->counts[i];
- /* Need to re-open in order to be able to write from the start. */
+ if (ptr->counts[i] > program_max)
+ program_max = ptr->counts[i];
+ }
+ program_arcs += ptr->ncounts;
+ }
+
+ for (ptr = bb_head; ptr; ptr = ptr->next)
+ {
+ FILE *da_file;
+ gcov_type object_max = 0;
+ gcov_type object_sum = 0;
+ long object_functions = 0;
+ int merging = 0;
+ int error = 0;
+ struct bb_function_info *fn_info;
+ gcov_type *count_ptr;
+
+ /* Open for modification */
da_file = fopen (ptr->filename, "r+b");
- /* Some old systems might not allow the 'b' mode modifier.
- Therefore, try to open without it. This can lead to a race
- condition so that when you delete and re-create the file, the
- file might be opened in text mode, but then, you shouldn't
- delete the file in the first place. */
- if (da_file == 0)
- da_file = fopen (ptr->filename, "r+");
- if (da_file == 0)
+
+ if (da_file)
+ merging = 1;
+ else
+ {
+ /* Try for appending */
+ da_file = fopen (ptr->filename, "ab");
+ /* Some old systems might not allow the 'b' mode modifier.
+ Therefore, try to open without it. This can lead to a
+ race condition so that when you delete and re-create the
+ file, the file might be opened in text mode, but then,
+ you shouldn't delete the file in the first place. */
+ if (!da_file)
+ da_file = fopen (ptr->filename, "a");
+ }
+
+ if (!da_file)
{
fprintf (stderr, "arc profiling: Can't open output file %s.\n",
ptr->filename);
+ ptr->filename = 0;
continue;
}
+#if defined (TARGET_HAS_F_SETLKW)
/* After a fork, another process might try to read and/or write
the same file simultanously. So if we can, lock the file to
avoid race conditions. */
-#if defined (TARGET_HAS_F_SETLKW)
- {
- struct flock s_flock;
-
- s_flock.l_type = F_WRLCK;
- s_flock.l_whence = SEEK_SET;
- s_flock.l_start = 0;
- s_flock.l_len = 1;
- s_flock.l_pid = getpid ();
-
- while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
- && errno == EINTR);
- }
+ while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
+ && errno == EINTR)
+ continue;
#endif
+ for (fn_info = ptr->function_infos; fn_info->arc_count != -1; fn_info++)
+ object_functions++;
- /* If the file is not empty, and the number of counts in it is the
- same, then merge them in. */
- firstchar = fgetc (da_file);
- if (firstchar == EOF)
+ if (merging)
{
- if (ferror (da_file))
+ /* Merge data from file. */
+ long tmp_long;
+ gcov_type tmp_gcov;
+
+ if (/* magic */
+ (__read_long (&tmp_long, da_file, 4) || tmp_long != -123l)
+ /* functions in object file. */
+ || (__read_long (&tmp_long, da_file, 4)
+ || tmp_long != object_functions)
+ /* extension block, skipped */
+ || (__read_long (&tmp_long, da_file, 4)
+ || fseek (da_file, tmp_long, SEEK_CUR)))
{
- fprintf (stderr, "arc profiling: Can't read output file ");
- perror (ptr->filename);
- }
- }
- else
- {
- long n_counts = 0;
-
- if (ungetc (firstchar, da_file) == EOF)
- rewind (da_file);
- if (__read_long (&n_counts, da_file, 8) != 0)
- {
- fprintf (stderr, "arc profiling: Can't read output file %s.\n",
+ read_error:;
+ fprintf (stderr, "arc profiling: Error merging output file %s.\n",
ptr->filename);
- continue;
+ clearerr (da_file);
}
-
- if (n_counts == ptr->ncounts)
+ else
{
- int i;
-
- for (i = 0; i < n_counts; i++)
+ /* Merge execution counts for each function. */
+ count_ptr = ptr->counts;
+
+ for (fn_info = ptr->function_infos; fn_info->arc_count != -1;
+ fn_info++)
{
- gcov_type v = 0;
-
- if (__read_gcov_type (&v, da_file, 8) != 0)
- {
- fprintf (stderr,
- "arc profiling: Can't read output file %s.\n",
- ptr->filename);
- break;
- }
- ptr->counts[i] += v;
+ if (/* function name delim */
+ (__read_long (&tmp_long, da_file, 4)
+ || tmp_long != -1)
+ /* function name length */
+ || (__read_long (&tmp_long, da_file, 4)
+ || tmp_long != (long) strlen (fn_info->name))
+ /* skip string */
+ || fseek (da_file, ((tmp_long + 1) + 3) & ~3, SEEK_CUR)
+ /* function name delim */
+ || (__read_long (&tmp_long, da_file, 4)
+ || tmp_long != -1))
+ goto read_error;
+
+ if (/* function checksum */
+ (__read_long (&tmp_long, da_file, 4)
+ || tmp_long != fn_info->checksum)
+ /* arc count */
+ || (__read_long (&tmp_long, da_file, 4)
+ || tmp_long != fn_info->arc_count))
+ goto read_error;
+
+ for (i = fn_info->arc_count; i > 0; i--, count_ptr++)
+ if (__read_gcov_type (&tmp_gcov, da_file, 8))
+ goto read_error;
+ else
+ *count_ptr += tmp_gcov;
}
}
-
+ fseek (da_file, 0, SEEK_SET);
}
-
- rewind (da_file);
-
- /* ??? 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_gcov_type (ptr->ncounts, da_file, 8) != 0)
+
+ /* Calculate the per-object statistics. */
+ for (i = 0; i < ptr->ncounts; i++)
{
+ object_sum += ptr->counts[i];
+ if (ptr->counts[i] > object_max)
+ object_max = ptr->counts[i];
+ }
+ merged_sum += object_sum;
+ if (merged_max < object_max)
+ merged_max = object_max;
+ merged_arcs += ptr->ncounts;
+
+ /* Write out the data. */
+ if (/* magic */
+ __write_long (-123, da_file, 4)
+ /* number of functions in object file. */
+ || __write_long (object_functions, da_file, 4)
+ /* length of extra data in bytes. */
+ || __write_long ((4 + 8 + 8) + (4 + 8 + 8), da_file, 4)
+
+ /* whole program statistics. If merging write per-object
+ now, rewrite later */
+ /* number of instrumented arcs. */
+ || __write_long (merging ? ptr->ncounts : program_arcs, da_file, 4)
+ /* sum of counters. */
+ || __write_gcov_type (merging ? object_sum : program_sum, da_file, 8)
+ /* maximal counter. */
+ || __write_gcov_type (merging ? object_max : program_max, da_file, 8)
+
+ /* per-object statistics. */
+ /* number of counters. */
+ || __write_long (ptr->ncounts, da_file, 4)
+ /* sum of counters. */
+ || __write_gcov_type (object_sum, da_file, 8)
+ /* maximal counter. */
+ || __write_gcov_type (object_max, da_file, 8))
+ {
+ write_error:;
fprintf (stderr, "arc profiling: Error writing output file %s.\n",
ptr->filename);
+ error = 1;
}
else
{
- int j;
- gcov_type *count_ptr = ptr->counts;
- int ret = 0;
- for (j = ptr->ncounts; j > 0; j--)
+ /* Write execution counts for each function. */
+ count_ptr = ptr->counts;
+
+ for (fn_info = ptr->function_infos; fn_info->arc_count != -1;
+ fn_info++)
{
- if (__write_gcov_type (*count_ptr, da_file, 8) != 0)
- {
- ret = 1;
- break;
- }
- count_ptr++;
+ if (__write_gcov_string (fn_info->name,
+ strlen (fn_info->name), da_file, -1)
+ || __write_long (fn_info->checksum, da_file, 4)
+ || __write_long (fn_info->arc_count, da_file, 4))
+ goto write_error;
+
+ for (i = fn_info->arc_count; i > 0; i--, count_ptr++)
+ if (__write_gcov_type (*count_ptr, da_file, 8))
+ goto write_error; /* RIP Edsger Dijkstra */
}
- 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);
+ if (fclose (da_file))
+ {
+ fprintf (stderr, "arc profiling: Error closing output file %s.\n",
+ ptr->filename);
+ error = 1;
+ }
+ if (error || !merging)
+ ptr->filename = 0;
}
- return;
+ /* Upate whole program statistics. */
+ for (ptr = bb_head; ptr; ptr = ptr->next)
+ if (ptr->filename)
+ {
+ FILE *da_file;
+
+ da_file = fopen (ptr->filename, "r+b");
+ if (!da_file)
+ {
+ fprintf (stderr, "arc profiling: Cannot reopen %s.\n",
+ ptr->filename);
+ continue;
+ }
+
+#if defined (TARGET_HAS_F_SETLKW)
+ while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
+ && errno == EINTR)
+ continue;
+#endif
+
+ if (fseek (da_file, 4 * 3, SEEK_SET)
+ /* number of instrumented arcs. */
+ || __write_long (merged_arcs, da_file, 4)
+ /* sum of counters. */
+ || __write_gcov_type (merged_sum, da_file, 8)
+ /* maximal counter. */
+ || __write_gcov_type (merged_max, da_file, 8))
+ fprintf (stderr, "arc profiling: Error updating program header %s.\n",
+ ptr->filename);
+ if (fclose (da_file))
+ fprintf (stderr, "arc profiling: Error reclosing %s\n",
+ ptr->filename);
+ }
}
+/* Add a new object file onto the bb chain. Invoked automatically
+ when running an object file's global ctors. */
+
void
__bb_init_func (struct bb *blocks)
{
- /* User is supposed to check whether the first word is non-0,
- but just in case.... */
-
if (blocks->zero_word)
return;
- /* Initialize destructor. */
+ /* Initialize destructor and per-thread data. */
if (!bb_head)
atexit (__bb_exit_func);
@@ -1474,6 +1563,7 @@ __bb_init_func (struct bb *blocks)
/* Called before fork or exec - write out profile information gathered so
far and reset it to zero. This avoids duplication or loss of the
profile information gathered so far. */
+
void
__bb_fork_func (void)
{
@@ -1656,102 +1746,6 @@ mprotect (char *addr, int len, int prot)
TRANSFER_FROM_TRAMPOLINE
#endif
-#if defined (NeXT) && defined (__MACH__)
-
-/* Make stack executable so we can call trampolines on stack.
- This is called from INITIALIZE_TRAMPOLINE in next.h. */
-#ifdef NeXTStep21
- #include <mach.h>
-#else
- #include <mach/mach.h>
-#endif
-
-void
-__enable_execute_stack (char *addr)
-{
- kern_return_t r;
- char *eaddr = addr + TRAMPOLINE_SIZE;
- vm_address_t a = (vm_address_t) addr;
-
- /* turn on execute access on stack */
- r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
- if (r != KERN_SUCCESS)
- {
- mach_error("vm_protect VM_PROT_ALL", r);
- exit(1);
- }
-
- /* We inline the i-cache invalidation for speed */
-
-#ifdef CLEAR_INSN_CACHE
- CLEAR_INSN_CACHE (addr, eaddr);
-#else
- __clear_cache ((int) addr, (int) eaddr);
-#endif
-}
-
-#endif /* defined (NeXT) && defined (__MACH__) */
-
-#ifdef __convex__
-
-/* Make stack executable so we can call trampolines on stack.
- This is called from INITIALIZE_TRAMPOLINE in convex.h. */
-
-#include <sys/mman.h>
-#include <sys/vmparam.h>
-#include <machine/machparam.h>
-
-void
-__enable_execute_stack (void)
-{
- int fp;
- static unsigned lowest = USRSTACK;
- unsigned current = (unsigned) &fp & -NBPG;
-
- if (lowest > current)
- {
- unsigned len = lowest - current;
- mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
- lowest = current;
- }
-
- /* Clear instruction cache in case an old trampoline is in it. */
- asm ("pich");
-}
-#endif /* __convex__ */
-
-#ifdef __sysV88__
-
-/* Modified from the convex -code above. */
-
-#include <sys/param.h>
-#include <errno.h>
-#include <sys/m88kbcs.h>
-
-void
-__enable_execute_stack (void)
-{
- int save_errno;
- static unsigned long lowest = USRSTACK;
- unsigned long current = (unsigned long) &save_errno & -NBPC;
-
- /* Ignore errno being set. memctl sets errno to EINVAL whenever the
- address is seen as 'negative'. That is the case with the stack. */
-
- save_errno=errno;
- if (lowest > current)
- {
- unsigned len=lowest-current;
- memctl(current,len,MCT_TEXT);
- lowest = current;
- }
- else
- memctl(current,NBPC,MCT_TEXT);
- errno=save_errno;
-}
-
-#endif /* __sysV88__ */
-
#ifdef __sysV68__
#include <sys/signal.h>
@@ -1796,57 +1790,6 @@ __clear_insn_cache (void)
}
#endif /* __sysV68__ */
-
-#ifdef __pyr__
-
-#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
-#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/vmmac.h>
-
-/* Modified from the convex -code above.
- mremap promises to clear the i-cache. */
-
-void
-__enable_execute_stack (void)
-{
- int fp;
- if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
- PROT_READ|PROT_WRITE|PROT_EXEC))
- {
- perror ("mprotect in __enable_execute_stack");
- fflush (stderr);
- abort ();
- }
-}
-#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 */
#ifndef __CYGWIN__
diff --git a/contrib/gcc/libgcc2.h b/contrib/gcc/libgcc2.h
index 715ccfc..f2dcb7c 100644
--- a/contrib/gcc/libgcc2.h
+++ b/contrib/gcc/libgcc2.h
@@ -19,6 +19,14 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
+/* 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. */
+
+
#ifndef GCC_LIBGCC2_H
#define GCC_LIBGCC2_H
@@ -31,9 +39,14 @@ struct bb;
extern void __bb_exit_func (void);
extern void __bb_init_func (struct bb *);
extern void __bb_fork_func (void);
-extern void __bb_trace_func (void);
-extern void __bb_trace_ret (void);
-extern void __bb_init_trace_func (struct bb *, unsigned long);
+
+#if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
+typedef long gcov_type;
+#else
+typedef long long gcov_type;
+#endif
+
+extern gcov_type *__bb_find_arc_counters (void);
struct exception_descriptor;
extern short int __get_eh_table_language (struct exception_descriptor *);
diff --git a/contrib/gcc/libiberty.h b/contrib/gcc/libiberty.h
index 3e0ca09..53cfc21 100644
--- a/contrib/gcc/libiberty.h
+++ b/contrib/gcc/libiberty.h
@@ -73,12 +73,12 @@ extern char **dupargv PARAMS ((char **)) ATTRIBUTE_MALLOC;
declaration without arguments. If it is 0, we checked and failed
to find the declaration so provide a fully prototyped one. If it
is 1, we found it so don't provide any declaration at all. */
-#if defined (__GNU_LIBRARY__ ) || defined (__linux__) || defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__CYGWIN__) || defined (__CYGWIN32__) || (defined (HAVE_DECL_BASENAME) && !HAVE_DECL_BASENAME)
+#if !HAVE_DECL_BASENAME
+#if defined (__GNU_LIBRARY__ ) || defined (__linux__) || defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__) || defined (__CYGWIN__) || defined (__CYGWIN32__) || defined (HAVE_DECL_BASENAME)
extern char *basename PARAMS ((const char *));
#else
-# if !defined (HAVE_DECL_BASENAME)
extern char *basename ();
-# endif
+#endif
#endif
/* A well-defined basename () that is always compiled in. */
@@ -145,6 +145,12 @@ extern char * getpwd PARAMS ((void));
extern long get_run_time PARAMS ((void));
+/* Generate a relocated path to some installation directory. Allocates
+ return value using malloc. */
+
+extern char *make_relative_prefix PARAMS ((const char *, const char *,
+ const char *));
+
/* Choose a temporary directory to use for scratch files. */
extern char *choose_temp_base PARAMS ((void)) ATTRIBUTE_MALLOC;
@@ -236,6 +242,10 @@ extern char *xstrdup PARAMS ((const char *)) ATTRIBUTE_MALLOC;
extern PTR xmemdup PARAMS ((const PTR, size_t, size_t)) ATTRIBUTE_MALLOC;
+/* Physical memory routines. Return values are in BYTES. */
+extern double physmem_total PARAMS ((void));
+extern double physmem_available PARAMS ((void));
+
/* hex character manipulation routines */
#define _hex_array_size 256
@@ -264,16 +274,20 @@ extern int pexecute PARAMS ((const char *, char * const *, const char *,
extern int pwait PARAMS ((int, int *, int));
+#if !HAVE_DECL_ASPRINTF
/* Like sprintf but provides a pointer to malloc'd storage, which must
be freed by the caller. */
extern int asprintf PARAMS ((char **, const char *, ...)) ATTRIBUTE_PRINTF_2;
+#endif
+#if !HAVE_DECL_VASPRINTF
/* Like vsprintf but provides a pointer to malloc'd storage, which
must be freed by the caller. */
extern int vasprintf PARAMS ((char **, const char *, va_list))
ATTRIBUTE_PRINTF(2,0);
+#endif
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
diff --git a/contrib/gcc/line-map.h b/contrib/gcc/line-map.h
index 835cb31..6020188 100644
--- a/contrib/gcc/line-map.h
+++ b/contrib/gcc/line-map.h
@@ -109,7 +109,7 @@ extern void print_containing_files
/* Returns the map a given map was included from. */
#define INCLUDED_FROM(SET, MAP) (&(SET)->maps[(MAP)->included_from])
-/* Non-zero if the map is at the bottom of the include stack. */
+/* Nonzero if the map is at the bottom of the include stack. */
#define MAIN_FILE_P(MAP) ((MAP)->included_from < 0)
/* The current line map. Saves a call to lookup_line if the caller is
diff --git a/contrib/gcc/lists.c b/contrib/gcc/lists.c
index 0adacfb..58d90d3 100644
--- a/contrib/gcc/lists.c
+++ b/contrib/gcc/lists.c
@@ -26,19 +26,18 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ggc.h"
static void free_list PARAMS ((rtx *, rtx *));
-static void zap_lists PARAMS ((void *));
/* Functions for maintaining cache-able lists of EXPR_LIST and INSN_LISTs. */
/* An INSN_LIST containing all INSN_LISTs allocated but currently unused. */
-static rtx unused_insn_list;
+static GTY ((deletable (""))) rtx unused_insn_list;
/* An EXPR_LIST containing all EXPR_LISTs allocated but currently unused. */
-static rtx unused_expr_list;
+static GTY ((deletable (""))) rtx unused_expr_list;
/* This function will free an entire list of either EXPR_LIST or INSN_LIST
- nodes. This is to be used only only lists that consist exclusively of
+ nodes. This is to be used only on lists that consist exclusively of
nodes of one type only. This is only called by free_EXPR_LIST_list
and free_INSN_LIST_list. */
static void
@@ -62,7 +61,7 @@ free_list (listp, unused_listp)
}
/* This call is used in place of a gen_rtx_INSN_LIST. If there is a cached
- node available, we'll use it, otherwise a call to gen_rtx_INSN_LIST
+ node available, we'll use it, otherwise a call to gen_rtx_INSN_LIST
is made. */
rtx
alloc_INSN_LIST (val, next)
@@ -85,7 +84,7 @@ alloc_INSN_LIST (val, next)
}
/* This call is used in place of a gen_rtx_EXPR_LIST. If there is a cached
- node available, we'll use it, otherwise a call to gen_rtx_EXPR_LIST
+ node available, we'll use it, otherwise a call to gen_rtx_EXPR_LIST
is made. */
rtx
alloc_EXPR_LIST (kind, val, next)
@@ -108,24 +107,8 @@ alloc_EXPR_LIST (kind, val, next)
return r;
}
-/* This function will initialize the EXPR_LIST and INSN_LIST caches. */
-
-static void
-zap_lists (dummy)
- void *dummy ATTRIBUTE_UNUSED;
-{
- unused_expr_list = NULL;
- unused_insn_list = NULL;
-}
-
-void
-init_EXPR_INSN_LIST_cache ()
-{
- ggc_add_root (&unused_expr_list, 1, 1, zap_lists);
-}
-
/* This function will free up an entire list of EXPR_LIST nodes. */
-void
+void
free_EXPR_LIST_list (listp)
rtx *listp;
{
@@ -135,7 +118,7 @@ free_EXPR_LIST_list (listp)
}
/* This function will free up an entire list of INSN_LIST nodes. */
-void
+void
free_INSN_LIST_list (listp)
rtx *listp;
{
@@ -145,7 +128,7 @@ free_INSN_LIST_list (listp)
}
/* This function will free up an individual EXPR_LIST node. */
-void
+void
free_EXPR_LIST_node (ptr)
rtx ptr;
{
@@ -154,10 +137,12 @@ free_EXPR_LIST_node (ptr)
}
/* This function will free up an individual INSN_LIST node. */
-void
+void
free_INSN_LIST_node (ptr)
rtx ptr;
{
XEXP (ptr, 1) = unused_insn_list;
unused_insn_list = ptr;
}
+
+#include "gt-lists.h"
diff --git a/contrib/gcc/local-alloc.c b/contrib/gcc/local-alloc.c
index 05d0bde..c2d6c0c 100644
--- a/contrib/gcc/local-alloc.c
+++ b/contrib/gcc/local-alloc.c
@@ -61,10 +61,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
+#include "hard-reg-set.h"
#include "rtl.h"
#include "tm_p.h"
#include "flags.h"
-#include "hard-reg-set.h"
#include "basic-block.h"
#include "regs.h"
#include "function.h"
@@ -144,12 +144,6 @@ struct qty
or -1 if none was found. */
short phys_reg;
-
- /* Nonzero if this quantity has been used in a SUBREG in some
- way that is illegal. */
-
- char changes_mode;
-
};
static struct qty *qty;
@@ -328,7 +322,6 @@ alloc_qty (regno, mode, size, birth)
qty[qtyno].alternate_class = reg_alternate_class (regno);
qty[qtyno].n_refs = REG_N_REFS (regno);
qty[qtyno].freq = REG_FREQ (regno);
- qty[qtyno].changes_mode = REG_CHANGES_MODE (regno);
}
/* Main entry point of this file. */
@@ -336,8 +329,9 @@ alloc_qty (regno, mode, size, birth)
int
local_alloc ()
{
- int b, i;
+ int i;
int max_qty;
+ basic_block b;
/* We need to keep track of whether or not we recorded a LABEL_REF so
that we know if the jump optimizer needs to be rerun. */
@@ -352,7 +346,8 @@ local_alloc ()
/* Promote REG_EQUAL notes to REG_EQUIV notes and adjust status of affected
registers. */
- update_equiv_regs ();
+ if (optimize)
+ update_equiv_regs ();
/* This sets the maximum number of quantities we can have. Quantity
numbers start at zero and we can have one for each pseudo. */
@@ -393,7 +388,7 @@ local_alloc ()
/* Allocate each block's local registers, block by block. */
- for (b = 0; b < n_basic_blocks; b++)
+ FOR_EACH_BB (b)
{
/* NEXT_QTY indicates which elements of the `qty_...'
vectors might need to be initialized because they were used
@@ -425,7 +420,7 @@ local_alloc ()
next_qty = 0;
- block_alloc (b);
+ block_alloc (b->index);
}
free (qty);
@@ -575,7 +570,7 @@ equiv_init_varies_p (x)
return 0;
}
-/* Returns non-zero if X (used to initialize register REGNO) is movable.
+/* Returns nonzero if X (used to initialize register REGNO) is movable.
X is only movable if the registers it uses have equivalent initializations
which appear to be within the same loop (or in an inner loop) and movable
or if they are not candidates for local_alloc and don't vary. */
@@ -814,7 +809,7 @@ static void
update_equiv_regs ()
{
rtx insn;
- int block;
+ basic_block bb;
int loop_depth;
regset_head cleared_regs;
int clear_regnos = 0;
@@ -827,9 +822,8 @@ update_equiv_regs ()
/* Scan the insns and find which registers have equivalences. Do this
in a separate scan of the insns because (due to -fcse-follow-jumps)
a register can be set below its use. */
- for (block = 0; block < n_basic_blocks; block++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (block);
loop_depth = bb->loop_depth;
for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = NEXT_INSN (insn))
@@ -1043,10 +1037,8 @@ update_equiv_regs ()
within the same loop (or in an inner loop), then move the register
initialization just before the use, so that they are in the same
basic block. */
- for (block = n_basic_blocks - 1; block >= 0; block--)
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block bb = BASIC_BLOCK (block);
-
loop_depth = bb->loop_depth;
for (insn = bb->end; insn != PREV_INSN (bb->head); insn = PREV_INSN (insn))
{
@@ -1116,7 +1108,7 @@ update_equiv_regs ()
REG_N_REFS (regno) = 0;
REG_FREQ (regno) = 0;
delete_insn (equiv_insn);
-
+
reg_equiv[regno].init_insns
= XEXP (reg_equiv[regno].init_insns, 1);
}
@@ -1138,12 +1130,12 @@ update_equiv_regs ()
XEXP (reg_equiv[regno].init_insns, 0) = new_insn;
- REG_BASIC_BLOCK (regno) = block >= 0 ? block : 0;
+ REG_BASIC_BLOCK (regno) = bb->index;
REG_N_CALLS_CROSSED (regno) = 0;
REG_LIVE_LENGTH (regno) = 2;
- if (block >= 0 && insn == BLOCK_HEAD (block))
- BLOCK_HEAD (block) = PREV_INSN (insn);
+ if (insn == bb->head)
+ bb->head = PREV_INSN (insn);
/* Remember to clear REGNO from all basic block's live
info. */
@@ -1158,24 +1150,22 @@ update_equiv_regs ()
/* Clear all dead REGNOs from all basic block's live info. */
if (clear_regnos)
{
- int j, l;
+ int j;
if (clear_regnos > 8)
- {
- for (l = 0; l < n_basic_blocks; l++)
+ {
+ FOR_EACH_BB (bb)
{
- AND_COMPL_REG_SET (BASIC_BLOCK (l)->global_live_at_start,
- &cleared_regs);
- AND_COMPL_REG_SET (BASIC_BLOCK (l)->global_live_at_end,
- &cleared_regs);
+ AND_COMPL_REG_SET (bb->global_live_at_start, &cleared_regs);
+ AND_COMPL_REG_SET (bb->global_live_at_end, &cleared_regs);
}
}
else
- EXECUTE_IF_SET_IN_REG_SET (&cleared_regs, 0, j,
- {
- for (l = 0; l < n_basic_blocks; l++)
+ EXECUTE_IF_SET_IN_REG_SET (&cleared_regs, 0, j,
+ {
+ FOR_EACH_BB (bb)
{
- CLEAR_REGNO_REG_SET (BASIC_BLOCK (l)->global_live_at_start, j);
- CLEAR_REGNO_REG_SET (BASIC_BLOCK (l)->global_live_at_end, j);
+ CLEAR_REGNO_REG_SET (bb->global_live_at_start, j);
+ CLEAR_REGNO_REG_SET (bb->global_live_at_end, j);
}
});
}
@@ -1345,7 +1335,8 @@ block_alloc (b)
/* If the operand is an address, find a register in it.
There may be more than one register, but we only try one
of them. */
- if (recog_data.constraints[i][0] == 'p')
+ if (recog_data.constraints[i][0] == 'p'
+ || EXTRA_ADDRESS_CONSTRAINT (recog_data.constraints[i][0]))
while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
r1 = XEXP (r1, 0);
@@ -1780,11 +1771,11 @@ qty_sugg_compare_1 (q1p, q2p)
If we really combined them, we could lose if the pseudo lives
across an insn that clobbers the hard reg (eg, movstr).
- ALREADY_DEAD is non-zero if USEDREG is known to be dead even though
+ ALREADY_DEAD is nonzero if USEDREG is known to be dead even though
there is no REG_DEAD note on INSN. This occurs during the processing
of REG_NO_CONFLICT blocks.
- MAY_SAVE_COPYCOPY is non-zero if this insn is simply copying USEDREG to
+ MAY_SAVE_COPYCOPY is nonzero if this insn is simply copying USEDREG to
SETREG or if the input and output must share a register.
In that case, we record a hard reg suggestion in QTY_PHYS_COPY_SUGG.
@@ -2028,9 +2019,6 @@ update_qty_class (qtyno, reg)
rclass = reg_alternate_class (reg);
if (reg_class_subset_p (rclass, qty[qtyno].alternate_class))
qty[qtyno].alternate_class = rclass;
-
- if (REG_CHANGES_MODE (reg))
- qty[qtyno].changes_mode = 1;
}
/* Handle something which alters the value of an rtx REG.
@@ -2101,7 +2089,7 @@ reg_is_born (reg, birth)
}
}
-/* Record the death of REG in the current insn. If OUTPUT_P is non-zero,
+/* Record the death of REG in the current insn. If OUTPUT_P is nonzero,
REG is an output that is dying (i.e., it is never used), otherwise it
is an input (the normal case).
If OUTPUT_P is 1, then we extend the life past the end of this insn. */
@@ -2170,7 +2158,7 @@ wipe_dead_reg (reg, output_p)
If QTYNO crosses calls, insist on a register preserved by calls,
unless ACCEPT_CALL_CLOBBERED is nonzero.
- If JUST_TRY_SUGGESTED is non-zero, only try to see if the suggested
+ If JUST_TRY_SUGGESTED is nonzero, only try to see if the suggested
register is available. If not, return -1. */
static int
@@ -2184,11 +2172,7 @@ find_free_reg (class, mode, qtyno, accept_call_clobbered, just_try_suggested,
int born_index, dead_index;
{
int i, ins;
-#ifdef HARD_REG_SET
- /* Declare it register if it's a scalar. */
- register
-#endif
- HARD_REG_SET used, first_used;
+ HARD_REG_SET first_used, used;
#ifdef ELIMINABLE_REGS
static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
#endif
@@ -2236,10 +2220,8 @@ find_free_reg (class, mode, qtyno, accept_call_clobbered, just_try_suggested,
SET_HARD_REG_BIT (used, FRAME_POINTER_REGNUM);
#endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
- if (qty[qtyno].changes_mode)
- IOR_HARD_REG_SET (used,
- reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]);
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ cannot_change_mode_set_regs (&used, mode, qty[qtyno].first_reg);
#endif
/* Normally, the registers that can be used for the first register in
@@ -2329,7 +2311,7 @@ find_free_reg (class, mode, qtyno, accept_call_clobbered, just_try_suggested,
}
/* Mark that REGNO with machine-mode MODE is live starting from the current
- insn (if LIFE is non-zero) or dead starting at the current insn (if LIFE
+ insn (if LIFE is nonzero) or dead starting at the current insn (if LIFE
is zero). */
static void
@@ -2348,7 +2330,7 @@ mark_life (regno, mode, life)
}
/* Mark register number REGNO (with machine-mode MODE) as live (if LIFE
- is non-zero) or dead (if LIFE is zero) from insn number BIRTH (inclusive)
+ is nonzero) or dead (if LIFE is zero) from insn number BIRTH (inclusive)
to insn number DEATH (exclusive). */
static void
@@ -2475,7 +2457,8 @@ requires_inout (p)
break;
default:
- if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
+ if (REG_CLASS_FROM_LETTER (c) == NO_REGS
+ && !EXTRA_ADDRESS_CONSTRAINT (c))
break;
/* FALLTHRU */
case 'p':
diff --git a/contrib/gcc/location.h b/contrib/gcc/location.h
new file mode 100644
index 0000000..1864f29
--- /dev/null
+++ b/contrib/gcc/location.h
@@ -0,0 +1,38 @@
+/* Definition of location data type used in various part of GCC
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+#ifndef GCC_LOCATION_H
+#define GCC_LOCATION_H
+
+/* The data structure used to record a location in a translation unit. */
+struct location_s GTY (())
+{
+ /* The name of the source file involved. */
+ const char *file;
+
+ /* The line-location in the source file. */
+ int line;
+};
+typedef struct location_s location_t;
+
+#endif
+
diff --git a/contrib/gcc/longlong.h b/contrib/gcc/longlong.h
index c8b9aee..b886f2b 100644
--- a/contrib/gcc/longlong.h
+++ b/contrib/gcc/longlong.h
@@ -66,7 +66,7 @@
is rounded towards 0.
5) count_leading_zeros(count, x) counts the number of zero-bits from the
- msb to the first non-zero bit in the UWtype X. This is the number of
+ msb to the first nonzero bit in the UWtype X. This is the number of
steps X needs to be shifted left to set the msb. Undefined for X == 0,
unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value.
@@ -107,49 +107,6 @@
#define __AND_CLOBBER_CC , "cc"
#endif /* __GNUC__ < 2 */
-#if (defined (__a29k__) || defined (_AM29K)) && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("add %1,%4,%5\n\taddc %0,%2,%3" \
- : "=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\n\tsubc %0,%2,%3" \
- : "=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" (__m0), \
- "r" (__m1)); \
- __asm__ ("multmu %0,%1,%2" \
- : "=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)))
-#define count_leading_zeros(count, x) \
- __asm__ ("clz %0,%1" \
- : "=r" ((USItype) (count)) \
- : "r" ((USItype) (x)))
-#define COUNT_LEADING_ZEROS_0 32
-#endif /* __a29k__ */
-
#if defined (__alpha) && W_TYPE_SIZE == 64
#define umul_ppmm(ph, pl, m0, m1) \
do { \
@@ -167,7 +124,7 @@
(q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
(r) = __r; \
} while (0)
-extern UDItype __udiv_qrnnd PARAMS ((UDItype *, UDItype, UDItype, UDItype));
+extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype);
#define UDIV_TIME 220
#endif /* LONGLONG_STANDALONE */
#ifdef __alpha_cix__
@@ -275,71 +232,6 @@ UDItype __umulsidi3 (USItype, USItype);
#define UDIV_TIME 100
#endif /* __arm__ */
-#if defined (__clipper__) && W_TYPE_SIZE == 32
-#define umul_ppmm(w1, w0, u, v) \
- ({union {UDItype __ll; \
- struct {USItype __l, __h;} __i; \
- } __xx; \
- __asm__ ("mulwux %2,%0" \
- : "=r" (__xx.__ll) \
- : "%0" ((USItype) (u)), \
- "r" ((USItype) (v))); \
- (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
-#define smul_ppmm(w1, w0, u, v) \
- ({union {DItype __ll; \
- struct {SItype __l, __h;} __i; \
- } __xx; \
- __asm__ ("mulwx %2,%0" \
- : "=r" (__xx.__ll) \
- : "%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))); \
- __w; })
-#endif /* __clipper__ */
-
-#if defined (__gmicro__) && W_TYPE_SIZE == 32
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("add.w %5,%1\n\taddx %3,%0" \
- : "=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\n\tsubx %3,%0" \
- : "=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)))
-#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)))
-#define count_leading_zeros(count, x) \
- __asm__ ("bsch/1 %1,%0" \
- : "=g" (count) \
- : "g" ((USItype) (x)), \
- "0" ((USItype) 0))
-#endif
-
#if defined (__hppa) && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("add %4,%5,%1\n\taddc %2,%3,%0" \
@@ -400,44 +292,27 @@ UDItype __umulsidi3 (USItype, USItype);
} while (0)
#endif
-#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32
-#define umul_ppmm(xh, xl, m0, m1) \
- do { \
- union {UDItype __ll; \
- struct {USItype __h, __l;} __i; \
- } __xx; \
- USItype __m0 = (m0), __m1 = (m1); \
- __asm__ ("mr %0,%3" \
- : "=r" (__xx.__i.__h), \
- "=r" (__xx.__i.__l) \
- : "%1" (__m0), \
- "r" (__m1)); \
- (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
- (xh) += ((((SItype) __m0 >> 31) & __m1) \
- + (((SItype) __m1 >> 31) & __m0)); \
- } while (0)
+#if (defined (__i370__) || defined (__s390__) || defined (__mvs__)) && W_TYPE_SIZE == 32
#define smul_ppmm(xh, xl, m0, m1) \
do { \
union {DItype __ll; \
struct {USItype __h, __l;} __i; \
- } __xx; \
- __asm__ ("mr %0,%3" \
- : "=r" (__xx.__i.__h), \
- "=r" (__xx.__i.__l) \
- : "%1" (m0), \
- "r" (m1)); \
- (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
+ } __x; \
+ __asm__ ("lr %N0,%1\n\tmr %0,%2" \
+ : "=&r" (__x.__ll) \
+ : "r" (m0), "r" (m1)); \
+ (xh) = __x.__i.__h; (xl) = __x.__i.__l; \
} while (0)
#define sdiv_qrnnd(q, r, n1, n0, d) \
do { \
union {DItype __ll; \
struct {USItype __h, __l;} __i; \
- } __xx; \
- __xx.__i.__h = n1; __xx.__i.__l = n0; \
+ } __x; \
+ __x.__i.__h = n1; __x.__i.__l = n0; \
__asm__ ("dr %0,%2" \
- : "=r" (__xx.__ll) \
- : "0" (__xx.__ll), "r" (d)); \
- (q) = __xx.__i.__l; (r) = __xx.__i.__h; \
+ : "=r" (__x.__ll) \
+ : "0" (__x.__ll), "r" (d)); \
+ (q) = __x.__i.__l; (r) = __x.__i.__h; \
} while (0)
#endif
@@ -484,47 +359,6 @@ UDItype __umulsidi3 (USItype, USItype);
#define UDIV_TIME 40
#endif /* 80x86 */
-#if defined (__i860__) && W_TYPE_SIZE == 32
-#if 0
-/* Make sure these patterns really improve the code before
- switching them on. */
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- do { \
- union \
- { \
- DItype __ll; \
- struct {USItype __l, __h;} __i; \
- } __a, __b, __s; \
- __a.__i.__l = (al); \
- __a.__i.__h = (ah); \
- __b.__i.__l = (bl); \
- __b.__i.__h = (bh); \
- __asm__ ("fiadd.dd %1,%2,%0" \
- : "=f" (__s.__ll) \
- : "%f" (__a.__ll), "f" (__b.__ll)); \
- (sh) = __s.__i.__h; \
- (sl) = __s.__i.__l; \
- } while (0)
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- do { \
- union \
- { \
- DItype __ll; \
- struct {USItype __l, __h;} __i; \
- } __a, __b, __s; \
- __a.__i.__l = (al); \
- __a.__i.__h = (ah); \
- __b.__i.__l = (bl); \
- __b.__i.__h = (bh); \
- __asm__ ("fisub.dd %1,%2,%0" \
- : "=f" (__s.__ll) \
- : "%f" (__a.__ll), "f" (__b.__ll)); \
- (sh) = __s.__i.__h; \
- (sl) = __s.__i.__l; \
- } while (0)
-#endif
-#endif /* __i860__ */
-
#if defined (__i960__) && W_TYPE_SIZE == 32
#define umul_ppmm(w1, w0, u, v) \
({union {UDItype __ll; \
@@ -589,8 +423,7 @@ UDItype __umulsidi3 (USItype, USItype);
#if defined (__mc68020__) || defined(mc68020) \
|| defined(__mc68030__) || defined(mc68030) \
|| defined(__mc68040__) || defined(mc68040) \
- || defined(__mcpu32__) || defined(mcpu32) \
- || defined(__NeXT__)
+ || defined(__mcpu32__) || defined(mcpu32)
#define umul_ppmm(w1, w0, u, v) \
__asm__ ("mulu%.l %3,%1:%0" \
: "=d" ((USItype) (w0)), \
@@ -658,8 +491,7 @@ UDItype __umulsidi3 (USItype, USItype);
#if defined (__mc68020__) || defined(mc68020) \
|| defined(__mc68030__) || defined(mc68030) \
|| defined(__mc68040__) || defined(mc68040) \
- || defined(__mc68060__) || defined(mc68060) \
- || defined(__NeXT__)
+ || defined(__mc68060__) || defined(mc68060)
#define count_leading_zeros(count, x) \
__asm__ ("bfffo %1{%b2:%b2},%0" \
: "=d" ((USItype) (count)) \
@@ -764,164 +596,143 @@ UDItype __umulsidi3 (USItype, USItype);
"g" ((USItype) (d))); \
(r) = __xx.__i.__l; (q) = __xx.__i.__h; })
#define count_trailing_zeros(count,x) \
- do {
- __asm__ ("ffsd %2,%0" \
- : "=r" ((USItype) (count)) \
- : "0" ((USItype) 0), \
- "r" ((USItype) (x))); \
+ do { \
+ __asm__ ("ffsd %2,%0" \
+ : "=r" ((USItype) (count)) \
+ : "0" ((USItype) 0), \
+ "r" ((USItype) (x))); \
} while (0)
#endif /* __ns32000__ */
-#if (defined (_ARCH_PPC) || defined (_IBMR2))
-#if W_TYPE_SIZE == 32
+/* FIXME: We should test _IBMR2 here when we add assembly support for the
+ system vendor compilers.
+ FIXME: What's needed for gcc PowerPC VxWorks? __vxworks__ is not good
+ enough, since that hits ARM and m68k too. */
+#if (defined (_ARCH_PPC) /* AIX */ \
+ || defined (_ARCH_PWR) /* AIX */ \
+ || defined (_ARCH_COM) /* AIX */ \
+ || defined (__powerpc__) /* gcc */ \
+ || defined (__POWERPC__) /* BEOS */ \
+ || defined (__ppc__) /* Darwin */ \
+ || defined (PPC) /* GNU/Linux, SysV */ \
+ ) && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
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))); \
- else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (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" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (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" (sh), "=&r" (sl) \
+ : "%r" (ah), "r" (bh), "%r" (al), "rI" (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))); \
- else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \
+ : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (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" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (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))); \
- else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (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" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (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" (sh), "=&r" (sl) \
+ : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \
} while (0)
-#endif /* W_TYPE_SIZE */
#define count_leading_zeros(count, x) \
- __asm__ ("{cntlz|cntlzw} %0,%1" \
- : "=r" ((USItype) (count)) \
- : "r" ((USItype) (x)))
+ __asm__ ("{cntlz|cntlzw} %0,%1" : "=r" (count) : "r" (x))
#define COUNT_LEADING_ZEROS_0 32
-#if defined (_ARCH_PPC)
+#if defined (_ARCH_PPC) || defined (__powerpc__) || defined (__POWERPC__) \
+ || defined (__ppc__) || defined (PPC) || defined (__vxworks__)
#define umul_ppmm(ph, pl, m0, m1) \
do { \
USItype __m0 = (m0), __m1 = (m1); \
- __asm__ ("mulhwu %0,%1,%2" \
- : "=r" ((USItype) ph) \
- : "%r" (__m0), \
- "r" (__m1)); \
+ __asm__ ("mulhwu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
(pl) = __m0 * __m1; \
} while (0)
#define UMUL_TIME 15
#define smul_ppmm(ph, pl, m0, m1) \
do { \
SItype __m0 = (m0), __m1 = (m1); \
- __asm__ ("mulhw %0,%1,%2" \
- : "=r" ((SItype) ph) \
- : "%r" (__m0), \
- "r" (__m1)); \
+ __asm__ ("mulhw %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
(pl) = __m0 * __m1; \
} while (0)
#define SMUL_TIME 14
#define UDIV_TIME 120
#elif defined (_ARCH_PWR)
-#define umul_ppmm(xh, xl, m0, m1) \
- do { \
- USItype __m0 = (m0), __m1 = (m1); \
- __asm__ ("mul %0,%2,%3" \
- : "=r" ((USItype) (xh)), \
- "=q" ((USItype) (xl)) \
- : "r" (__m0), \
- "r" (__m1)); \
- (xh) += ((((SItype) __m0 >> 31) & __m1) \
- + (((SItype) __m1 >> 31) & __m0)); \
- } while (0)
#define UMUL_TIME 8
#define smul_ppmm(xh, xl, m0, m1) \
- __asm__ ("mul %0,%2,%3" \
- : "=r" ((SItype) (xh)), \
- "=q" ((SItype) (xl)) \
- : "r" (m0), \
- "r" (m1))
+ __asm__ ("mul %0,%2,%3" : "=r" (xh), "=q" (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)))
+ __asm__ ("div %0,%2,%4" : "=r" (q), "=q" (r) : "r" (nh), "1" (nl), "r" (d))
#define UDIV_TIME 100
#endif
-#endif /* Power architecture variants. */
+#endif /* 32-bit POWER architecture variants. */
-#if defined (__pyr__) && W_TYPE_SIZE == 32
+/* We should test _IBMR2 here when we add assembly support for the system
+ vendor compilers. */
+#if (defined (_ARCH_PPC64) || defined (__powerpc64__)) && W_TYPE_SIZE == 64
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
- __asm__ ("addw %5,%1\n\taddwc %3,%0" \
- : "=r" ((USItype) (sh)), \
- "=&r" ((USItype) (sl)) \
- : "%0" ((USItype) (ah)), \
- "g" ((USItype) (bh)), \
- "%1" ((USItype) (al)), \
- "g" ((USItype) (bl)))
+ do { \
+ if (__builtin_constant_p (bh) && (bh) == 0) \
+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
+ else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \
+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
+ else \
+ __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
+ : "=r" (sh), "=&r" (sl) \
+ : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \
+ } while (0)
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("subw %5,%1\n\tsubwb %3,%0" \
- : "=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; \
- struct {USItype __h, __l;} __i; \
- } __xx; \
- __asm__ ("movw %1,%R0\n\tuemul %2,%0" \
- : "=&r" (__xx.__ll) \
- : "g" ((USItype) (u)), \
- "g" ((USItype) (v))); \
- (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
-#endif /* __pyr__ */
+ do { \
+ if (__builtin_constant_p (ah) && (ah) == 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
+ else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
+ else if (__builtin_constant_p (bh) && (bh) == 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
+ else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
+ else \
+ __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
+ : "=r" (sh), "=&r" (sl) \
+ : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \
+ } while (0)
+#define count_leading_zeros(count, x) \
+ __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x))
+#define COUNT_LEADING_ZEROS_0 64
+#define umul_ppmm(ph, pl, m0, m1) \
+ do { \
+ UDItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define UMUL_TIME 15
+#define smul_ppmm(ph, pl, m0, m1) \
+ do { \
+ DItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define SMUL_TIME 14 /* ??? */
+#define UDIV_TIME 120 /* ??? */
+#endif /* 64-bit PowerPC. */
#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
@@ -1373,6 +1184,20 @@ UDItype __umulsidi3 (USItype, USItype);
} while (0)
#endif
+/* If we lack umul_ppmm but have smul_ppmm, define umul_ppmm in terms of
+ smul_ppmm. */
+#if !defined (umul_ppmm) && defined (smul_ppmm)
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ UWtype __w1; \
+ UWtype __xm0 = (u), __xm1 = (v); \
+ smul_ppmm (__w1, w0, __xm0, __xm1); \
+ (w1) = __w1 + (-(__xm0 >> (W_TYPE_SIZE - 1)) & __xm1) \
+ + (-(__xm1 >> (W_TYPE_SIZE - 1)) & __xm0); \
+ } while (0)
+#endif
+
+/* If we still don't have umul_ppmm, define it using plain C. */
#if !defined (umul_ppmm)
#define umul_ppmm(w1, w0, u, v) \
do { \
diff --git a/contrib/gcc/loop.c b/contrib/gcc/loop.c
index 58e0255..8e6f9b5 100644
--- a/contrib/gcc/loop.c
+++ b/contrib/gcc/loop.c
@@ -1,6 +1,6 @@
/* Perform various loop optimizations, including strength reduction.
Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -38,7 +38,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "system.h"
#include "rtl.h"
#include "tm_p.h"
-#include "obstack.h"
#include "function.h"
#include "expr.h"
#include "hard-reg-set.h"
@@ -79,9 +78,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* For very tiny loops it is not worthwhile to prefetch even before the loop,
since it is likely that the data are already in the cache. */
#define PREFETCH_BLOCKS_BEFORE_LOOP_MIN 2
-/* The minimal number of prefetch blocks that a loop must consume to make
- the emitting of prefetch instruction in the body of loop worthwhile. */
-#define PREFETCH_BLOCKS_IN_LOOP_MIN 6
/* Parameterize some prefetch heuristics so they can be turned on and off
easily for performance testing on new architecures. These can be
@@ -124,20 +120,26 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define PREFETCH_EXTREME_STRIDE 4096
#endif
+/* Define a limit to how far apart indices can be and still be merged
+ into a single prefetch. */
+#ifndef PREFETCH_EXTREME_DIFFERENCE
+#define PREFETCH_EXTREME_DIFFERENCE 4096
+#endif
+
+/* Issue prefetch instructions before the loop to fetch data to be used
+ in the first few loop iterations. */
+#ifndef PREFETCH_BEFORE_LOOP
+#define PREFETCH_BEFORE_LOOP 1
+#endif
+
/* Do not handle reversed order prefetches (negative stride). */
#ifndef PREFETCH_NO_REVERSE_ORDER
#define PREFETCH_NO_REVERSE_ORDER 1
#endif
-/* Prefetch even if the GIV is not always executed. */
-#ifndef PREFETCH_NOT_ALWAYS
-#define PREFETCH_NOT_ALWAYS 0
-#endif
-
-/* If the loop requires more prefetches than the target can process in
- parallel then don't prefetch anything in that loop. */
-#ifndef PREFETCH_LIMIT_TO_SIMULTANEOUS
-#define PREFETCH_LIMIT_TO_SIMULTANEOUS 1
+/* Prefetch even if the GIV is in conditional code. */
+#ifndef PREFETCH_CONDITIONAL
+#define PREFETCH_CONDITIONAL 1
#endif
#define LOOP_REG_LIFETIME(LOOP, REGNO) \
@@ -149,7 +151,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define LOOP_REGNO_NREGS(REGNO, SET_DEST) \
((REGNO) < FIRST_PSEUDO_REGISTER \
- ? HARD_REGNO_NREGS ((REGNO), GET_MODE (SET_DEST)) : 1)
+ ? (int) HARD_REGNO_NREGS ((REGNO), GET_MODE (SET_DEST)) : 1)
/* Vector mapping INSN_UIDs to luids.
@@ -182,9 +184,6 @@ unsigned int max_reg_before_loop;
/* The value to pass to the next call of reg_scan_update. */
static int loop_max_reg;
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
/* During the analysis of a loop, a chain of `struct movable's
is made to record all the movable insns found.
@@ -327,10 +326,12 @@ static void update_reg_last_use PARAMS ((rtx, rtx));
static rtx next_insn_in_loop PARAMS ((const struct loop *, rtx));
static void loop_regs_scan PARAMS ((const struct loop *, int));
static int count_insns_in_loop PARAMS ((const struct loop *));
+static int find_mem_in_note_1 PARAMS ((rtx *, void *));
+static rtx find_mem_in_note PARAMS ((rtx));
static void load_mems PARAMS ((const struct loop *));
static int insert_loop_mem PARAMS ((rtx *, void *));
static int replace_loop_mem PARAMS ((rtx *, void *));
-static void replace_loop_mems PARAMS ((rtx, rtx, rtx));
+static void replace_loop_mems PARAMS ((rtx, rtx, rtx, int));
static int replace_loop_reg PARAMS ((rtx *, void *));
static void replace_loop_regs PARAMS ((rtx insn, rtx, rtx));
static void note_reg_stored PARAMS ((rtx, rtx, void *));
@@ -354,6 +355,7 @@ static rtx loop_insn_sink_or_swim PARAMS((const struct loop *, rtx));
static void loop_dump_aux PARAMS ((const struct loop *, FILE *, int));
static void loop_delete_insns PARAMS ((rtx, rtx));
static HOST_WIDE_INT remove_constant_addition PARAMS ((rtx *));
+static rtx gen_load_of_final_value PARAMS ((rtx, rtx));
void debug_ivs PARAMS ((const struct loop *));
void debug_iv_class PARAMS ((const struct iv_class *));
void debug_biv PARAMS ((const struct induction *));
@@ -553,13 +555,6 @@ loop_optimize (f, dumpfile, flags)
scan_loop (loop, flags);
}
- /* If there were lexical blocks inside the loop, they have been
- replicated. We will now have more than one NOTE_INSN_BLOCK_BEG
- and NOTE_INSN_BLOCK_END for each such block. We must duplicate
- the BLOCKs as well. */
- if (write_symbols != NO_DEBUG)
- reorder_blocks ();
-
end_alias_analysis ();
/* Clean up. */
@@ -822,11 +817,17 @@ scan_loop (loop, flags)
}
}
+ /* Don't try to optimize a MODE_CC set with a constant
+ source. It probably will be combined with a conditional
+ jump. */
+ if (GET_MODE_CLASS (GET_MODE (SET_DEST (set))) == MODE_CC
+ && CONSTANT_P (src))
+ ;
/* Don't try to optimize a register that was made
by loop-optimization for an inner loop.
We don't know its life-span, so we can't compute
the benefit. */
- if (REGNO (SET_DEST (set)) >= max_reg_before_loop)
+ else if (REGNO (SET_DEST (set)) >= max_reg_before_loop)
;
else if (/* The register is used in basic blocks other
than the one where it is set (meaning that
@@ -837,7 +838,7 @@ scan_loop (loop, flags)
the loop starts, or the value before the set is
needed before the set occurs...
- ??? Note we have quadratic behaviour here, mitigated
+ ??? Note we have quadratic behavior here, mitigated
by the fact that the previous test will often fail for
large loops. Rather than re-scanning the entire loop
each time for register usage, we should build tables
@@ -1056,7 +1057,8 @@ scan_loop (loop, flags)
m->match = 0;
m->lifetime = LOOP_REG_LIFETIME (loop, regno);
m->savings = 1;
- for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set));
+ for (i = 0;
+ i < LOOP_REGNO_NREGS (regno, SET_DEST (set));
i++)
regs->array[regno+i].set_in_loop = -1;
/* Add M to the end of the chain MOVABLES. */
@@ -1082,7 +1084,7 @@ scan_loop (loop, flags)
unconditional jump, otherwise the code at the top of the
loop might never be executed. Unconditional jumps are
followed by a barrier then the loop_end. */
- && ! (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == loop->top
+ && ! (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == loop->top
&& NEXT_INSN (NEXT_INSN (p)) == loop_end
&& any_uncondjump_p (p)))
maybe_never = 1;
@@ -1469,10 +1471,13 @@ combine_movables (movables, regs)
/* Regs that are set more than once are not allowed to match
or be matched. I'm no longer sure why not. */
+ /* Only pseudo registers are allowed to match or be matched,
+ since move_movables does not validate the change. */
/* Perhaps testing m->consec_sets would be more appropriate here? */
for (m = movables->head; m; m = m->next)
if (m->match == 0 && regs->array[m->regno].n_times_set == 1
+ && m->regno >= FIRST_PSEUDO_REGISTER
&& !m->partial)
{
struct movable *m1;
@@ -1484,11 +1489,9 @@ combine_movables (movables, regs)
/* We want later insns to match the first one. Don't make the first
one match any later ones. So start this loop at m->next. */
for (m1 = m->next; m1; m1 = m1->next)
- /* ??? HACK! move_movables does not verify that the replacement
- is valid, which can have disasterous effects with hard regs
- and match_dup. Turn combination off for now. */
- if (0 && m != m1 && m1->match == 0
+ if (m != m1 && m1->match == 0
&& regs->array[m1->regno].n_times_set == 1
+ && m1->regno >= FIRST_PSEUDO_REGISTER
/* A reg used outside the loop mustn't be eliminated. */
&& !m1->global
/* A reg used for zero-extending mustn't be eliminated. */
@@ -1964,11 +1967,10 @@ move_movables (loop, movables, threshold, insn_count)
start_sequence ();
emit_move_insn (m->set_dest, m->set_src);
- temp = get_insns ();
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
- add_label_notes (m->set_src, temp);
+ add_label_notes (m->set_src, seq);
i1 = loop_insn_hoist (loop, seq);
if (! find_reg_note (i1, REG_EQUAL, NULL_RTX))
@@ -2103,7 +2105,7 @@ move_movables (loop, movables, threshold, insn_count)
abort ();
if (tem != reg)
emit_move_insn (reg, tem);
- sequence = gen_sequence ();
+ sequence = get_insns ();
end_sequence ();
i1 = loop_insn_hoist (loop, sequence);
}
@@ -2124,11 +2126,10 @@ move_movables (loop, movables, threshold, insn_count)
use the REG_EQUAL note. */
start_sequence ();
emit_move_insn (m->set_dest, m->set_src);
- temp = get_insns ();
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
- add_label_notes (m->set_src, temp);
+ add_label_notes (m->set_src, seq);
i1 = loop_insn_hoist (loop, seq);
if (! find_reg_note (i1, REG_EQUAL, NULL_RTX))
@@ -2470,6 +2471,7 @@ prescan_loop (loop)
loop_info->pre_header_has_call = 0;
loop_info->has_call = 0;
loop_info->has_nonconst_call = 0;
+ loop_info->has_prefetch = 0;
loop_info->has_volatile = 0;
loop_info->has_tablejump = 0;
loop_info->has_multiple_exit_targets = 0;
@@ -2481,7 +2483,8 @@ prescan_loop (loop)
loop_info->first_loop_store_insn = NULL_RTX;
loop_info->mems_idx = 0;
loop_info->num_mem_sets = 0;
-
+ /* If loop opts run twice, this was set on 1st pass for 2nd. */
+ loop_info->preconditioned = NOTE_PRECONDITIONED (end);
for (insn = start; insn && GET_CODE (insn) != CODE_LABEL;
insn = PREV_INSN (insn))
@@ -2889,7 +2892,7 @@ find_and_verify_loops (f, loops)
/* If no suitable BARRIER was found, create a suitable
one before TARGET. Since TARGET is a fall through
- path, we'll need to insert an jump around our block
+ path, we'll need to insert a jump around our block
and add a BARRIER before TARGET.
This creates an extra unconditional jump outside
@@ -3278,6 +3281,13 @@ loop_invariant_p (loop, x)
&& REGNO (x) < FIRST_PSEUDO_REGISTER && call_used_regs[REGNO (x)])
return 0;
+ /* Out-of-range regs can occur when we are called from unrolling.
+ These have always been created by the unroller and are set in
+ the loop, hence are never invariant. */
+
+ if (REGNO (x) >= (unsigned) regs->num)
+ return 0;
+
if (regs->array[REGNO (x)].set_in_loop < 0)
return 2;
@@ -3589,17 +3599,15 @@ struct prefetch_info
HOST_WIDE_INT index;
HOST_WIDE_INT stride; /* Prefetch stride in bytes in each
iteration. */
- unsigned int bytes_accesed; /* Sum of sizes of all acceses to this
+ unsigned int bytes_accessed; /* Sum of sizes of all accesses to this
prefetch area in one iteration. */
unsigned int total_bytes; /* Total bytes loop will access in this block.
This is set only for loops with known
iteration counts and is 0xffffffff
otherwise. */
+ int prefetch_in_loop; /* Number of prefetch insns in loop. */
+ int prefetch_before_loop; /* Number of prefetch insns before loop. */
unsigned int write : 1; /* 1 for read/write prefetches. */
- unsigned int prefetch_in_loop : 1;
- /* 1 for those chosen for prefetching. */
- unsigned int prefetch_before_loop : 1;
- /* 1 for those chosen for prefetching. */
};
/* Data used by check_store function. */
@@ -3751,9 +3759,9 @@ remove_constant_addition (x)
/* In case our parameter was constant, remove extra zero from the
expression. */
if (XEXP (exp, 0) == const0_rtx)
- *x = XEXP (exp, 1);
+ *x = XEXP (exp, 1);
else if (XEXP (exp, 1) == const0_rtx)
- *x = XEXP (exp, 0);
+ *x = XEXP (exp, 0);
}
return addval;
@@ -3786,7 +3794,9 @@ emit_prefetch_instructions (loop)
int num_prefetches = 0;
int num_real_prefetches = 0;
int num_real_write_prefetches = 0;
- int ahead;
+ int num_prefetches_before = 0;
+ int num_write_prefetches_before = 0;
+ int ahead = 0;
int i;
struct iv_class *bl;
struct induction *iv;
@@ -3801,18 +3811,19 @@ emit_prefetch_instructions (loop)
if (PREFETCH_NO_CALL && LOOP_INFO (loop)->has_call)
{
if (loop_dump_stream)
- fprintf (loop_dump_stream, "Prefetch: ignoring loop - has call.\n");
+ fprintf (loop_dump_stream, "Prefetch: ignoring loop: has call.\n");
return;
}
+ /* Don't prefetch in loops known to have few iterations. */
if (PREFETCH_NO_LOW_LOOPCNT
&& LOOP_INFO (loop)->n_iterations
&& LOOP_INFO (loop)->n_iterations <= PREFETCH_LOW_LOOPCNT)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
- "Prefetch: ignoring loop - not enought iterations.\n");
+ "Prefetch: ignoring loop: not enough iterations.\n");
return;
}
@@ -3833,14 +3844,13 @@ emit_prefetch_instructions (loop)
BIVs that are executed multiple times; such BIVs ought to be
handled in the nested loop. We accept not_every_iteration BIVs,
since these only result in larger strides and make our
- heuristics more conservative.
- ??? What does the last sentence mean? */
+ heuristics more conservative. */
if (GET_CODE (biv->add_val) != CONST_INT)
{
if (loop_dump_stream)
{
fprintf (loop_dump_stream,
- "Prefetch: biv %i ignored: non-constant addition at insn %i:",
+ "Prefetch: ignoring biv %d: non-constant addition at insn %d:",
REGNO (biv->src_reg), INSN_UID (biv->insn));
print_rtl (loop_dump_stream, biv->add_val);
fprintf (loop_dump_stream, "\n");
@@ -3853,7 +3863,7 @@ emit_prefetch_instructions (loop)
if (loop_dump_stream)
{
fprintf (loop_dump_stream,
- "Prefetch: biv %i ignored: maybe_multiple at insn %i:",
+ "Prefetch: ignoring biv %d: maybe_multiple at insn %i:",
REGNO (biv->src_reg), INSN_UID (biv->insn));
print_rtl (loop_dump_stream, biv->add_val);
fprintf (loop_dump_stream, "\n");
@@ -3874,55 +3884,84 @@ emit_prefetch_instructions (loop)
rtx temp;
HOST_WIDE_INT index = 0;
int add = 1;
- HOST_WIDE_INT stride;
+ HOST_WIDE_INT stride = 0;
+ int stride_sign = 1;
struct check_store_data d;
+ const char *ignore_reason = NULL;
int size = GET_MODE_SIZE (GET_MODE (iv));
- /* There are several reasons why an induction variable is not
- interesting to us. */
- if (iv->giv_type != DEST_ADDR
- /* We are interested only in constant stride memory references
- in order to be able to compute density easily. */
- || GET_CODE (iv->mult_val) != CONST_INT
- /* Don't handle reversed order prefetches, since they are usually
- ineffective. Later we may be able to reverse such BIVs. */
- || (PREFETCH_NO_REVERSE_ORDER
- && (stride = INTVAL (iv->mult_val) * basestride) < 0)
- /* Prefetching of accesses with such an extreme stride is probably
- not worthwhile, either. */
- || (PREFETCH_NO_EXTREME_STRIDE
- && stride > PREFETCH_EXTREME_STRIDE)
+ /* See whether an induction variable is interesting to us and if
+ not, report the reason. */
+ if (iv->giv_type != DEST_ADDR)
+ ignore_reason = "giv is not a destination address";
+
+ /* We are interested only in constant stride memory references
+ in order to be able to compute density easily. */
+ else if (GET_CODE (iv->mult_val) != CONST_INT)
+ ignore_reason = "stride is not constant";
+
+ else
+ {
+ stride = INTVAL (iv->mult_val) * basestride;
+ if (stride < 0)
+ {
+ stride = -stride;
+ stride_sign = -1;
+ }
+
+ /* On some targets, reversed order prefetches are not
+ worthwhile. */
+ if (PREFETCH_NO_REVERSE_ORDER && stride_sign < 0)
+ ignore_reason = "reversed order stride";
+
+ /* Prefetch of accesses with an extreme stride might not be
+ worthwhile, either. */
+ else if (PREFETCH_NO_EXTREME_STRIDE
+ && stride > PREFETCH_EXTREME_STRIDE)
+ ignore_reason = "extreme stride";
+
/* Ignore GIVs with varying add values; we can't predict the
value for the next iteration. */
- || !loop_invariant_p (loop, iv->add_val)
+ else if (!loop_invariant_p (loop, iv->add_val))
+ ignore_reason = "giv has varying add value";
+
/* Ignore GIVs in the nested loops; they ought to have been
handled already. */
- || iv->maybe_multiple)
+ else if (iv->maybe_multiple)
+ ignore_reason = "giv is in nested loop";
+ }
+
+ if (ignore_reason != NULL)
{
if (loop_dump_stream)
- fprintf (loop_dump_stream, "Prefetch: Ignoring giv at %i\n",
- INSN_UID (iv->insn));
+ fprintf (loop_dump_stream,
+ "Prefetch: ignoring giv at %d: %s.\n",
+ INSN_UID (iv->insn), ignore_reason);
continue;
}
/* Determine the pointer to the basic array we are examining. It is
the sum of the BIV's initial value and the GIV's add_val. */
- index = 0;
-
address = copy_rtx (iv->add_val);
temp = copy_rtx (bl->initial_value);
address = simplify_gen_binary (PLUS, Pmode, temp, address);
index = remove_constant_addition (&address);
- index += size;
d.mem_write = 0;
d.mem_address = *iv->location;
/* When the GIV is not always executed, we might be better off by
not dirtying the cache pages. */
- if (PREFETCH_NOT_ALWAYS || iv->always_executed)
+ if (PREFETCH_CONDITIONAL || iv->always_executed)
note_stores (PATTERN (iv->insn), check_store, &d);
+ else
+ {
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream, "Prefetch: Ignoring giv at %d: %s\n",
+ INSN_UID (iv->insn), "in conditional code.");
+ continue;
+ }
/* Attempt to find another prefetch to the same array and see if we
can merge this one. */
@@ -3934,13 +3973,14 @@ emit_prefetch_instructions (loop)
just with small difference in constant indexes), merge
the prefetches. Just do the later and the earlier will
get prefetched from previous iteration.
- 4096 is artificial threshold. It should not be too small,
+ The artificial threshold should not be too small,
but also not bigger than small portion of memory usually
traversed by single loop. */
- if (index >= info[i].index && index - info[i].index < 4096)
+ if (index >= info[i].index
+ && index - info[i].index < PREFETCH_EXTREME_DIFFERENCE)
{
info[i].write |= d.mem_write;
- info[i].bytes_accesed += size;
+ info[i].bytes_accessed += size;
info[i].index = index;
info[i].giv = iv;
info[i].class = bl;
@@ -3949,10 +3989,11 @@ emit_prefetch_instructions (loop)
break;
}
- if (index < info[i].index && info[i].index - index < 4096)
+ if (index < info[i].index
+ && info[i].index - index < PREFETCH_EXTREME_DIFFERENCE)
{
info[i].write |= d.mem_write;
- info[i].bytes_accesed += size;
+ info[i].bytes_accessed += size;
add = 0;
break;
}
@@ -3967,7 +4008,7 @@ emit_prefetch_instructions (loop)
info[num_prefetches].stride = stride;
info[num_prefetches].base_address = address;
info[num_prefetches].write = d.mem_write;
- info[num_prefetches].bytes_accesed = size;
+ info[num_prefetches].bytes_accessed = size;
num_prefetches++;
if (num_prefetches >= MAX_PREFETCHES)
{
@@ -3982,133 +4023,183 @@ emit_prefetch_instructions (loop)
for (i = 0; i < num_prefetches; i++)
{
- /* Attempt to calculate the number of bytes fetched by the loop.
- Avoid overflow. */
+ int density;
+
+ /* Attempt to calculate the total number of bytes fetched by all
+ iterations of the loop. Avoid overflow. */
if (LOOP_INFO (loop)->n_iterations
- && ((unsigned HOST_WIDE_INT) (0xffffffff / info[i].stride)
+ && ((unsigned HOST_WIDE_INT) (0xffffffff / info[i].stride)
>= LOOP_INFO (loop)->n_iterations))
info[i].total_bytes = info[i].stride * LOOP_INFO (loop)->n_iterations;
else
info[i].total_bytes = 0xffffffff;
- /* Prefetch is worthwhile only when the loads/stores are dense. */
- if (PREFETCH_ONLY_DENSE_MEM
- && info[i].bytes_accesed * 256 / info[i].stride > PREFETCH_DENSE_MEM
- && (info[i].total_bytes / PREFETCH_BLOCK
- >= PREFETCH_BLOCKS_BEFORE_LOOP_MIN))
- {
- info[i].prefetch_before_loop = 1;
- info[i].prefetch_in_loop
- = (info[i].total_bytes / PREFETCH_BLOCK
- > PREFETCH_BLOCKS_BEFORE_LOOP_MAX);
- }
+ density = info[i].bytes_accessed * 100 / info[i].stride;
+
+ /* Prefetch might be worthwhile only when the loads/stores are dense. */
+ if (PREFETCH_ONLY_DENSE_MEM)
+ if (density * 256 > PREFETCH_DENSE_MEM * 100
+ && (info[i].total_bytes / PREFETCH_BLOCK
+ >= PREFETCH_BLOCKS_BEFORE_LOOP_MIN))
+ {
+ info[i].prefetch_before_loop = 1;
+ info[i].prefetch_in_loop
+ = (info[i].total_bytes / PREFETCH_BLOCK
+ > PREFETCH_BLOCKS_BEFORE_LOOP_MAX);
+ }
+ else
+ {
+ info[i].prefetch_in_loop = 0, info[i].prefetch_before_loop = 0;
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "Prefetch: ignoring giv at %d: %d%% density is too low.\n",
+ INSN_UID (info[i].giv->insn), density);
+ }
else
- info[i].prefetch_in_loop = 0, info[i].prefetch_before_loop = 0;
+ info[i].prefetch_in_loop = 1, info[i].prefetch_before_loop = 1;
- if (info[i].prefetch_in_loop)
+ /* Find how many prefetch instructions we'll use within the loop. */
+ if (info[i].prefetch_in_loop != 0)
{
- num_real_prefetches += ((info[i].stride + PREFETCH_BLOCK - 1)
+ info[i].prefetch_in_loop = ((info[i].stride + PREFETCH_BLOCK - 1)
/ PREFETCH_BLOCK);
+ num_real_prefetches += info[i].prefetch_in_loop;
if (info[i].write)
- num_real_write_prefetches
- += (info[i].stride + PREFETCH_BLOCK - 1) / PREFETCH_BLOCK;
+ num_real_write_prefetches += info[i].prefetch_in_loop;
}
}
- if (loop_dump_stream)
+ /* Determine how many iterations ahead to prefetch within the loop, based
+ on how many prefetches we currently expect to do within the loop. */
+ if (num_real_prefetches != 0)
+ {
+ if ((ahead = SIMULTANEOUS_PREFETCHES / num_real_prefetches) == 0)
+ {
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "Prefetch: ignoring prefetches within loop: ahead is zero; %d < %d\n",
+ SIMULTANEOUS_PREFETCHES, num_real_prefetches);
+ num_real_prefetches = 0, num_real_write_prefetches = 0;
+ }
+ }
+ /* We'll also use AHEAD to determine how many prefetch instructions to
+ emit before a loop, so don't leave it zero. */
+ if (ahead == 0)
+ ahead = PREFETCH_BLOCKS_BEFORE_LOOP_MAX;
+
+ for (i = 0; i < num_prefetches; i++)
{
- for (i = 0; i < num_prefetches; i++)
+ /* Update if we've decided not to prefetch anything within the loop. */
+ if (num_real_prefetches == 0)
+ info[i].prefetch_in_loop = 0;
+
+ /* Find how many prefetch instructions we'll use before the loop. */
+ if (info[i].prefetch_before_loop != 0)
{
- fprintf (loop_dump_stream, "Prefetch insn %i address: ",
+ int n = info[i].total_bytes / PREFETCH_BLOCK;
+ if (n > ahead)
+ n = ahead;
+ info[i].prefetch_before_loop = n;
+ num_prefetches_before += n;
+ if (info[i].write)
+ num_write_prefetches_before += n;
+ }
+
+ if (loop_dump_stream)
+ {
+ if (info[i].prefetch_in_loop == 0
+ && info[i].prefetch_before_loop == 0)
+ continue;
+ fprintf (loop_dump_stream, "Prefetch insn: %d",
INSN_UID (info[i].giv->insn));
- print_rtl (loop_dump_stream, info[i].base_address);
- fprintf (loop_dump_stream, " Index: ");
+ fprintf (loop_dump_stream,
+ "; in loop: %d; before: %d; %s\n",
+ info[i].prefetch_in_loop,
+ info[i].prefetch_before_loop,
+ info[i].write ? "read/write" : "read only");
+ fprintf (loop_dump_stream,
+ " density: %d%%; bytes_accessed: %u; total_bytes: %u\n",
+ (int) (info[i].bytes_accessed * 100 / info[i].stride),
+ info[i].bytes_accessed, info[i].total_bytes);
+ fprintf (loop_dump_stream, " index: ");
fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, info[i].index);
- fprintf (loop_dump_stream, " stride: ");
+ fprintf (loop_dump_stream, "; stride: ");
fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, info[i].stride);
- fprintf (loop_dump_stream,
- " density: %i%% total_bytes: %u%sin loop: %s before: %s\n",
- (int) (info[i].bytes_accesed * 100 / info[i].stride),
- info[i].total_bytes,
- info[i].write ? " read/write " : " read only ",
- info[i].prefetch_in_loop ? "yes" : "no",
- info[i].prefetch_before_loop ? "yes" : "no");
+ fprintf (loop_dump_stream, "; address: ");
+ print_rtl (loop_dump_stream, info[i].base_address);
+ fprintf (loop_dump_stream, "\n");
}
-
- fprintf (loop_dump_stream, "Real prefetches needed: %i (write: %i)\n",
- num_real_prefetches, num_real_write_prefetches);
}
- if (!num_real_prefetches)
- return;
-
- ahead = SIMULTANEOUS_PREFETCHES / num_real_prefetches;
+ if (num_real_prefetches + num_prefetches_before > 0)
+ {
+ /* Record that this loop uses prefetch instructions. */
+ LOOP_INFO (loop)->has_prefetch = 1;
- if (!ahead)
- return;
+ if (loop_dump_stream)
+ {
+ fprintf (loop_dump_stream, "Real prefetches needed within loop: %d (write: %d)\n",
+ num_real_prefetches, num_real_write_prefetches);
+ fprintf (loop_dump_stream, "Real prefetches needed before loop: %d (write: %d)\n",
+ num_prefetches_before, num_write_prefetches_before);
+ }
+ }
for (i = 0; i < num_prefetches; i++)
{
- if (info[i].prefetch_in_loop)
- {
- int y;
+ int y;
- for (y = 0; y < ((info[i].stride + PREFETCH_BLOCK - 1)
- / PREFETCH_BLOCK); y++)
+ for (y = 0; y < info[i].prefetch_in_loop; y++)
+ {
+ rtx loc = copy_rtx (*info[i].giv->location);
+ rtx insn;
+ int bytes_ahead = PREFETCH_BLOCK * (ahead + y);
+ rtx before_insn = info[i].giv->insn;
+ rtx prev_insn = PREV_INSN (info[i].giv->insn);
+ rtx seq;
+
+ /* We can save some effort by offsetting the address on
+ architectures with offsettable memory references. */
+ if (offsettable_address_p (0, VOIDmode, loc))
+ loc = plus_constant (loc, bytes_ahead);
+ else
{
- rtx loc = copy_rtx (*info[i].giv->location);
- rtx insn;
- int bytes_ahead = PREFETCH_BLOCK * (ahead + y);
- rtx before_insn = info[i].giv->insn;
- rtx prev_insn = PREV_INSN (info[i].giv->insn);
- rtx seq;
-
- /* We can save some effort by offsetting the address on
- architectures with offsettable memory references. */
- if (offsettable_address_p (0, VOIDmode, loc))
- loc = plus_constant (loc, bytes_ahead);
- else
- {
- rtx reg = gen_reg_rtx (Pmode);
- loop_iv_add_mult_emit_before (loop, loc, const1_rtx,
- GEN_INT (bytes_ahead), reg,
- 0, before_insn);
- loc = reg;
- }
-
- start_sequence ();
- /* Make sure the address operand is valid for prefetch. */
- if (! (*insn_data[(int)CODE_FOR_prefetch].operand[0].predicate)
- (loc,
- insn_data[(int)CODE_FOR_prefetch].operand[0].mode))
- loc = force_reg (Pmode, loc);
- emit_insn (gen_prefetch (loc, GEN_INT (info[i].write),
- GEN_INT (3)));
- seq = gen_sequence ();
- end_sequence ();
- emit_insn_before (seq, before_insn);
+ rtx reg = gen_reg_rtx (Pmode);
+ loop_iv_add_mult_emit_before (loop, loc, const1_rtx,
+ GEN_INT (bytes_ahead), reg,
+ 0, before_insn);
+ loc = reg;
+ }
- /* Check all insns emitted and record the new GIV
- information. */
- insn = NEXT_INSN (prev_insn);
- while (insn != before_insn)
- {
- insn = check_insn_for_givs (loop, insn,
- info[i].giv->always_executed,
- info[i].giv->maybe_multiple);
- insn = NEXT_INSN (insn);
- }
+ start_sequence ();
+ /* Make sure the address operand is valid for prefetch. */
+ if (! (*insn_data[(int)CODE_FOR_prefetch].operand[0].predicate)
+ (loc, insn_data[(int)CODE_FOR_prefetch].operand[0].mode))
+ loc = force_reg (Pmode, loc);
+ emit_insn (gen_prefetch (loc, GEN_INT (info[i].write),
+ GEN_INT (3)));
+ seq = get_insns ();
+ end_sequence ();
+ emit_insn_before (seq, before_insn);
+
+ /* Check all insns emitted and record the new GIV
+ information. */
+ insn = NEXT_INSN (prev_insn);
+ while (insn != before_insn)
+ {
+ insn = check_insn_for_givs (loop, insn,
+ info[i].giv->always_executed,
+ info[i].giv->maybe_multiple);
+ insn = NEXT_INSN (insn);
}
}
- if (info[i].prefetch_before_loop)
+ if (PREFETCH_BEFORE_LOOP)
{
- int y;
-
- /* Emit INSNs before the loop to fetch the first cache lines. */
- for (y = 0;
- (!info[i].prefetch_in_loop || y < ahead)
- && y * PREFETCH_BLOCK < (int) info[i].total_bytes; y ++)
+ /* Emit insns before the loop to fetch the first cache lines or,
+ if we're not prefetching within the loop, everything we expect
+ to need. */
+ for (y = 0; y < info[i].prefetch_before_loop; y++)
{
rtx reg = gen_reg_rtx (Pmode);
rtx loop_start = loop->start;
@@ -4121,10 +4212,18 @@ emit_prefetch_instructions (loop)
non-constant INIT_VAL to have the same mode as REG, which
in this case we know to be Pmode. */
if (GET_MODE (init_val) != Pmode && !CONSTANT_P (init_val))
- init_val = convert_to_mode (Pmode, init_val, 0);
+ {
+ rtx seq;
+
+ start_sequence ();
+ init_val = convert_to_mode (Pmode, init_val, 0);
+ seq = get_insns ();
+ end_sequence ();
+ loop_insn_emit_before (loop, 0, loop_start, seq);
+ }
loop_iv_add_mult_emit_before (loop, init_val,
info[i].giv->mult_val,
- add_val, reg, 0, loop_start);
+ add_val, reg, 0, loop_start);
emit_insn_before (gen_prefetch (reg, GEN_INT (info[i].write),
GEN_INT (3)),
loop_start);
@@ -4147,7 +4246,7 @@ emit_prefetch_instructions (loop)
static rtx note_insn;
-/* Dummy register to have non-zero DEST_REG for DEST_ADDR type givs. */
+/* Dummy register to have nonzero DEST_REG for DEST_ADDR type givs. */
static rtx addr_placeholder;
@@ -4182,8 +4281,8 @@ static rtx addr_placeholder;
LOOP and INSN parameters pass MAYBE_MULTIPLE and NOT_EVERY_ITERATION to the
callback.
- NOT_EVERY_ITERATION if current insn is not executed at least once for every
- loop iteration except for the last one.
+ NOT_EVERY_ITERATION is 1 if current insn is not known to be executed at
+ least once for every loop iteration except for the last one.
MAYBE_MULTIPLE is 1 if current insn may be executed more than once for every
loop iteration.
@@ -4193,8 +4292,6 @@ for_each_insn_in_loop (loop, fncall)
struct loop *loop;
loop_insn_callback fncall;
{
- /* This is 1 if current insn is not executed at least once for every loop
- iteration. */
int not_every_iteration = 0;
int maybe_multiple = 0;
int past_loop_latch = 0;
@@ -4206,8 +4303,7 @@ for_each_insn_in_loop (loop, fncall)
if (prev_nonnote_insn (loop->scan_start) != prev_nonnote_insn (loop->start))
maybe_multiple = back_branch_in_range_p (loop, loop->scan_start);
- /* Scan through loop to find all possible bivs. */
-
+ /* Scan through loop and update NOT_EVERY_ITERATION and MAYBE_MULTIPLE. */
for (p = next_insn_in_loop (loop, loop->scan_start);
p != NULL_RTX;
p = next_insn_in_loop (loop, p))
@@ -4264,9 +4360,9 @@ for_each_insn_in_loop (loop, fncall)
This can be any kind of jump, since we want to know if insns
will be executed if the loop is executed. */
&& !(JUMP_LABEL (p) == loop->top
- && ((NEXT_INSN (NEXT_INSN (p)) == loop->end
- && any_uncondjump_p (p))
- || (NEXT_INSN (p) == loop->end && any_condjump_p (p)))))
+ && ((NEXT_INSN (NEXT_INSN (p)) == loop->end
+ && any_uncondjump_p (p))
+ || (NEXT_INSN (p) == loop->end && any_condjump_p (p)))))
{
rtx label = 0;
@@ -4378,7 +4474,7 @@ loop_bivs_find (loop)
}
-/* Determine how BIVS are initialised by looking through pre-header
+/* Determine how BIVS are initialized by looking through pre-header
extended basic block. */
static void
loop_bivs_init_find (loop)
@@ -4522,7 +4618,7 @@ loop_givs_check (loop)
}
-/* Return non-zero if it is possible to eliminate the biv BL provided
+/* Return nonzero if it is possible to eliminate the biv BL provided
all givs are reduced. This is possible if either the reg is not
used outside the loop, or we can compute what its final value will
be. */
@@ -4681,8 +4777,11 @@ loop_givs_reduce (loop, bl)
{
rtx insert_before;
+ /* Skip if location is the same as a previous one. */
+ if (tv->same)
+ continue;
if (! auto_inc_opt)
- insert_before = tv->insn;
+ insert_before = NEXT_INSN (tv->insn);
else if (auto_inc_opt == 1)
insert_before = NEXT_INSN (v->insn);
else
@@ -4812,10 +4911,22 @@ loop_givs_rescan (loop, bl, reg_map)
}
else
{
+ rtx original_insn = v->insn;
+ rtx note;
+
/* Not replaceable; emit an insn to set the original giv reg from
the reduced giv, same as above. */
- loop_insn_emit_after (loop, 0, v->insn,
- gen_move_insn (v->dest_reg, v->new_reg));
+ v->insn = loop_insn_emit_after (loop, 0, original_insn,
+ gen_move_insn (v->dest_reg,
+ v->new_reg));
+
+ /* The original insn may have a REG_EQUAL note. This note is
+ now incorrect and may result in invalid substitutions later.
+ The original insn is dead, but may be part of a libcall
+ sequence, which doesn't seem worth the bother of handling. */
+ note = find_reg_note (original_insn, REG_EQUAL, NULL_RTX);
+ if (note)
+ remove_note (original_insn, note);
}
/* When a loop is reversed, givs which depend on the reversed
@@ -4829,7 +4940,8 @@ loop_givs_rescan (loop, bl, reg_map)
v->mult_val, v->add_val, v->dest_reg);
else if (v->final_value)
loop_insn_sink_or_swim (loop,
- gen_move_insn (v->dest_reg, v->final_value));
+ gen_load_of_final_value (v->dest_reg,
+ v->final_value));
if (loop_dump_stream)
{
@@ -5004,7 +5116,7 @@ strength_reduce (loop, flags)
return;
}
- /* Determine how BIVS are initialised by looking through pre-header
+ /* Determine how BIVS are initialized by looking through pre-header
extended basic block. */
loop_bivs_init_find (loop);
@@ -5186,8 +5298,9 @@ strength_reduce (loop, flags)
value, so we don't need another one. We can't calculate the
proper final value for such a biv here anyways. */
if (bl->final_value && ! bl->reversed)
- loop_insn_sink_or_swim (loop, gen_move_insn
- (bl->biv->dest_reg, bl->final_value));
+ loop_insn_sink_or_swim (loop,
+ gen_load_of_final_value (bl->biv->dest_reg,
+ bl->final_value));
if (loop_dump_stream)
fprintf (loop_dump_stream, "Reg %d: biv eliminated\n",
@@ -5196,8 +5309,8 @@ strength_reduce (loop, flags)
/* See above note wrt final_value. But since we couldn't eliminate
the biv, we must set the value after the loop instead of before. */
else if (bl->final_value && ! bl->reversed)
- loop_insn_sink (loop, gen_move_insn (bl->biv->dest_reg,
- bl->final_value));
+ loop_insn_sink (loop, gen_load_of_final_value (bl->biv->dest_reg,
+ bl->final_value));
}
/* Go through all the instructions in the loop, making all the
@@ -5244,7 +5357,7 @@ strength_reduce (loop, flags)
collected. Always unroll loops that would be as small or smaller
unrolled than when rolled. */
if ((flags & LOOP_UNROLL)
- || (!(flags & LOOP_FIRST_PASS)
+ || ((flags & LOOP_AUTO_UNROLL)
&& loop_info->n_iterations > 0
&& unrolled_insn_copies <= insn_count))
unroll_loop (loop, insn_count, 1);
@@ -5257,13 +5370,13 @@ strength_reduce (loop, flags)
/* In case number of iterations is known, drop branch prediction note
in the branch. Do that only in second loop pass, as loop unrolling
may change the number of iterations performed. */
- if ((flags & LOOP_BCT)
- && loop_info->n_iterations / loop_info->unroll_number > 1)
+ if (flags & LOOP_BCT)
{
- int n = loop_info->n_iterations / loop_info->unroll_number;
- predict_insn (PREV_INSN (loop->end),
- PRED_LOOP_ITERATIONS,
- REG_BR_PROB_BASE - REG_BR_PROB_BASE / n);
+ unsigned HOST_WIDE_INT n
+ = loop_info->n_iterations / loop_info->unroll_number;
+ if (n > 1)
+ predict_insn (prev_nonnote_insn (loop->end), PRED_LOOP_ITERATIONS,
+ REG_BR_PROB_BASE - REG_BR_PROB_BASE / n);
}
if (loop_dump_stream)
@@ -5574,6 +5687,7 @@ record_biv (loop, v, insn, dest_reg, inc_val, mult_val, location,
v->always_computable = ! not_every_iteration;
v->always_executed = ! not_every_iteration;
v->maybe_multiple = maybe_multiple;
+ v->same = 0;
/* Add this to the reg's iv_class, creating a class
if this is the first incrementation of the reg. */
@@ -5611,6 +5725,17 @@ record_biv (loop, v, insn, dest_reg, inc_val, mult_val, location,
/* Put it in the array of biv register classes. */
REG_IV_CLASS (ivs, REGNO (dest_reg)) = bl;
}
+ else
+ {
+ /* Check if location is the same as a previous one. */
+ struct induction *induction;
+ for (induction = bl->biv; induction; induction = induction->next_iv)
+ if (location == induction->location)
+ {
+ v->same = induction;
+ break;
+ }
+ }
/* Update IV_CLASS entry for this biv. */
v->next_iv = bl->biv;
@@ -5741,7 +5866,10 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val,
abort ();
if (type == DEST_ADDR)
- v->replaceable = 1;
+ {
+ v->replaceable = 1;
+ v->not_replaceable = 0;
+ }
else
{
/* The giv can be replaced outright by the reduced register only if all
@@ -5776,6 +5904,7 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val,
using this biv anyways. */
v->replaceable = 1;
+ v->not_replaceable = 0;
for (b = bl->biv; b; b = b->next_iv)
{
if (INSN_UID (b->insn) >= max_uid_for_loop
@@ -5879,13 +6008,15 @@ check_final_value (loop, v)
#endif
if ((final_value = final_giv_value (loop, v))
- && (v->always_executed || last_use_this_basic_block (v->dest_reg, v->insn)))
+ && (v->always_executed
+ || last_use_this_basic_block (v->dest_reg, v->insn)))
{
int biv_increment_seen = 0, before_giv_insn = 0;
rtx p = v->insn;
rtx last_giv_use;
v->replaceable = 1;
+ v->not_replaceable = 0;
/* When trying to determine whether or not a biv increment occurs
during the lifetime of the giv, we can ignore uses of the variable
@@ -6411,7 +6542,7 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, ext_val,
expression that is neither invariant nor a biv or giv), this routine
returns 0.
- For a non-zero return, the result will have a code of CONST_INT, USE,
+ For a nonzero return, the result will have a code of CONST_INT, USE,
REG (for a BIV), PLUS, or MULT. No other codes will occur.
*BENEFIT will be incremented by the benefit of any sub-giv encountered. */
@@ -6764,7 +6895,7 @@ simplify_giv_expr (loop, x, ext_val, benefit)
return simplify_giv_expr (loop, m->match->set_dest,
ext_val, benefit);
- /* If consec is non-zero, this is a member of a group of
+ /* If consec is nonzero, this is a member of a group of
instructions that were moved together. We handle this
case only to the point of seeking to the last insn and
looking for a REG_EQUAL. Fail if we don't find one. */
@@ -7666,7 +7797,7 @@ gen_add_mult (b, m, a, reg)
result = expand_mult_add (b, reg, m, a, GET_MODE (reg), 1);
if (reg != result)
emit_move_insn (reg, result);
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
return seq;
@@ -7680,24 +7811,29 @@ loop_regs_update (loop, seq)
const struct loop *loop ATTRIBUTE_UNUSED;
rtx seq;
{
+ rtx insn;
+
/* Update register info for alias analysis. */
- if (GET_CODE (seq) == SEQUENCE)
+ if (seq == NULL_RTX)
+ return;
+
+ if (INSN_P (seq))
{
- int i;
- for (i = 0; i < XVECLEN (seq, 0); ++i)
+ insn = seq;
+ while (insn != NULL_RTX)
{
- rtx set = single_set (XVECEXP (seq, 0, i));
+ rtx set = single_set (insn);
+
if (set && GET_CODE (SET_DEST (set)) == REG)
record_base_value (REGNO (SET_DEST (set)), SET_SRC (set), 0);
+
+ insn = NEXT_INSN (insn);
}
}
- else
- {
- if (GET_CODE (seq) == SET
- && GET_CODE (SET_DEST (seq)) == REG)
- record_base_value (REGNO (SET_DEST (seq)), SET_SRC (seq), 0);
- }
+ else if (GET_CODE (seq) == SET
+ && GET_CODE (SET_DEST (seq)) == REG)
+ record_base_value (REGNO (SET_DEST (seq)), SET_SRC (seq), 0);
}
@@ -7820,16 +7956,20 @@ iv_add_mult_cost (b, m, a, reg)
}
/* Test whether A * B can be computed without
- an actual multiply insn. Value is 1 if so. */
+ an actual multiply insn. Value is 1 if so.
+
+ ??? This function stinks because it generates a ton of wasted RTL
+ ??? and as a result fragments GC memory to no end. There are other
+ ??? places in the compiler which are invoked a lot and do the same
+ ??? thing, generate wasted RTL just to see if something is possible. */
static int
product_cheap_p (a, b)
rtx a;
rtx b;
{
- int i;
rtx tmp;
- int win = 1;
+ int win, n_insns;
/* If only one is constant, make it B. */
if (GET_CODE (a) == CONST_INT)
@@ -7849,31 +7989,31 @@ product_cheap_p (a, b)
start_sequence ();
expand_mult (GET_MODE (a), a, b, NULL_RTX, 1);
- tmp = gen_sequence ();
+ tmp = get_insns ();
end_sequence ();
- if (GET_CODE (tmp) == SEQUENCE)
+ win = 1;
+ if (INSN_P (tmp))
{
- if (XVEC (tmp, 0) == 0)
- win = 1;
- else if (XVECLEN (tmp, 0) > 3)
- win = 0;
- else
- for (i = 0; i < XVECLEN (tmp, 0); i++)
- {
- rtx insn = XVECEXP (tmp, 0, i);
-
- if (GET_CODE (insn) != INSN
- || (GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_SRC (PATTERN (insn))) == MULT)
- || (GET_CODE (PATTERN (insn)) == PARALLEL
- && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET
- && GET_CODE (SET_SRC (XVECEXP (PATTERN (insn), 0, 0))) == MULT))
- {
- win = 0;
- break;
- }
- }
+ n_insns = 0;
+ while (tmp != NULL_RTX)
+ {
+ rtx next = NEXT_INSN (tmp);
+
+ if (++n_insns > 3
+ || GET_CODE (tmp) != INSN
+ || (GET_CODE (PATTERN (tmp)) == SET
+ && GET_CODE (SET_SRC (PATTERN (tmp))) == MULT)
+ || (GET_CODE (PATTERN (tmp)) == PARALLEL
+ && GET_CODE (XVECEXP (PATTERN (tmp), 0, 0)) == SET
+ && GET_CODE (SET_SRC (XVECEXP (PATTERN (tmp), 0, 0))) == MULT))
+ {
+ win = 0;
+ break;
+ }
+
+ tmp = next;
+ }
}
else if (GET_CODE (tmp) == SET
&& GET_CODE (SET_SRC (tmp)) == MULT)
@@ -8161,12 +8301,13 @@ check_dbra_loop (loop, insn_count)
if ((num_nonfixed_reads <= 1
&& ! loop_info->has_nonconst_call
+ && ! loop_info->has_prefetch
&& ! loop_info->has_volatile
&& reversible_mem_store
&& (bl->giv_count + bl->biv_count + loop_info->num_mem_sets
+ num_unmoved_movables (loop) + compare_and_branch == insn_count)
&& (bl == ivs->list && bl->next == 0))
- || no_use_except_counting)
+ || (no_use_except_counting && ! loop_info->has_prefetch))
{
rtx tem;
@@ -8363,7 +8504,7 @@ check_dbra_loop (loop, insn_count)
create a sequence to hold all the insns from expand_inc. */
start_sequence ();
expand_inc (reg, new_add_val);
- tem = gen_sequence ();
+ tem = get_insns ();
end_sequence ();
p = loop_insn_emit_before (loop, 0, bl->biv->insn, tem);
@@ -8392,7 +8533,7 @@ check_dbra_loop (loop, insn_count)
if ((REGNO_LAST_UID (bl->regno) != INSN_UID (first_compare))
|| ! bl->init_insn
|| REGNO_FIRST_UID (bl->regno) != INSN_UID (bl->init_insn))
- loop_insn_sink (loop, gen_move_insn (reg, final_value));
+ loop_insn_sink (loop, gen_load_of_final_value (reg, final_value));
/* Delete compare/branch at end of loop. */
delete_related_insns (PREV_INSN (loop_end));
@@ -8404,7 +8545,7 @@ check_dbra_loop (loop, insn_count)
emit_cmp_and_jump_insns (reg, const0_rtx, cmp_code, NULL_RTX,
GET_MODE (reg), 0,
XEXP (jump_label, 0));
- tem = gen_sequence ();
+ tem = get_insns ();
end_sequence ();
emit_jump_insn_before (tem, loop_end);
@@ -8489,7 +8630,7 @@ check_dbra_loop (loop, insn_count)
/* Verify whether the biv BL appears to be eliminable,
based on the insns in the loop that refer to it.
- If ELIMINATE_P is non-zero, actually do the elimination.
+ If ELIMINATE_P is nonzero, actually do the elimination.
THRESHOLD and INSN_COUNT are from loop_optimize and are used to
determine whether invariant insns should be placed inside or at the
@@ -8570,7 +8711,7 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
}
/* INSN and REFERENCE are instructions in the same insn chain.
- Return non-zero if INSN is first. */
+ Return nonzero if INSN is first. */
int
loop_insn_first_p (insn, reference)
@@ -8583,9 +8724,9 @@ loop_insn_first_p (insn, reference)
/* Start with test for not first so that INSN == REFERENCE yields not
first. */
if (q == insn || ! p)
- return 0;
+ return 0;
if (p == reference || ! q)
- return 1;
+ return 1;
/* Either of P or Q might be a NOTE. Notes have the same LUID as the
previous insn, hence the <= comparison below does not work if
@@ -8603,7 +8744,7 @@ loop_insn_first_p (insn, reference)
}
}
-/* We are trying to eliminate BIV in INSN using GIV. Return non-zero if
+/* We are trying to eliminate BIV in INSN using GIV. Return nonzero if
the offset that we have to take into account due to auto-increment /
div derivation is zero. */
static int
@@ -8630,10 +8771,10 @@ biv_elimination_giv_has_0_offset (biv, giv, insn)
If BIV does not appear in X, return 1.
- If ELIMINATE_P is non-zero, actually do the elimination.
+ If ELIMINATE_P is nonzero, actually do the elimination.
WHERE_INSN/WHERE_BB indicate where extra insns should be added.
Depending on how many items have been moved out of the loop, it
- will either be before INSN (when WHERE_INSN is non-zero) or at the
+ will either be before INSN (when WHERE_INSN is nonzero) or at the
start of the loop (when WHERE_INSN is zero). */
static int
@@ -8799,6 +8940,22 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
if (! biv_elimination_giv_has_0_offset (bl->biv, v, insn))
continue;
+ /* Don't eliminate if the linear combination that makes up
+ the giv overflows when it is applied to ARG. */
+ if (GET_CODE (arg) == CONST_INT)
+ {
+ rtx add_val;
+
+ if (GET_CODE (v->add_val) == CONST_INT)
+ add_val = v->add_val;
+ else
+ add_val = const0_rtx;
+
+ if (const_mult_add_overflow_p (arg, v->mult_val,
+ add_val, mode, 1))
+ continue;
+ }
+
if (! eliminate_p)
return 1;
@@ -8809,13 +8966,10 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
the derived constant can be directly placed in the COMPARE,
do so. */
if (GET_CODE (arg) == CONST_INT
- && GET_CODE (v->mult_val) == CONST_INT
&& GET_CODE (v->add_val) == CONST_INT)
{
- validate_change (insn, &XEXP (x, arg_operand),
- GEN_INT (INTVAL (arg)
- * INTVAL (v->mult_val)
- + INTVAL (v->add_val)), 1);
+ tem = expand_mult_add (arg, NULL_RTX, v->mult_val,
+ v->add_val, mode, 1);
}
else
{
@@ -8824,8 +8978,10 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
loop_iv_add_mult_emit_before (loop, arg,
v->mult_val, v->add_val,
tem, where_bb, where_insn);
- validate_change (insn, &XEXP (x, arg_operand), tem, 1);
}
+
+ validate_change (insn, &XEXP (x, arg_operand), tem, 1);
+
if (apply_change_group ())
return 1;
}
@@ -9088,14 +9244,14 @@ update_reg_last_use (x, insn)
If the condition cannot be understood, or is an inequality floating-point
comparison which needs to be reversed, 0 will be returned.
- If REVERSE is non-zero, then reverse the condition prior to canonizing it.
+ If REVERSE is nonzero, then reverse the condition prior to canonizing it.
- If EARLIEST is non-zero, it is a pointer to a place where the earliest
+ If EARLIEST is nonzero, it is a pointer to a place where the earliest
insn used in locating the condition was found. If a replacement test
of the condition is desired, it should be placed in front of that
insn and we will be sure that the inputs are still valid.
- If WANT_REG is non-zero, we wish the condition to be relative to that
+ If WANT_REG is nonzero, we wish the condition to be relative to that
register, if possible. Therefore, do not canonicalize the condition
further. */
@@ -9137,7 +9293,7 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
&& op1 == CONST0_RTX (GET_MODE (op0))
&& op0 != want_reg)
{
- /* Set non-zero when we find something of interest. */
+ /* Set nonzero when we find something of interest. */
rtx x = 0;
#ifdef HAVE_cc0
@@ -9189,6 +9345,9 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
if (set)
{
enum machine_mode inner_mode = GET_MODE (SET_DEST (set));
+#ifdef FLOAT_STORE_FLAG_VALUE
+ REAL_VALUE_TYPE fsfv;
+#endif
/* ??? We may not combine comparisons done in a CCmode with
comparisons not done in a CCmode. This is to aid targets
@@ -9216,8 +9375,8 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (code == LT
&& GET_MODE_CLASS (inner_mode) == MODE_FLOAT
- && (REAL_VALUE_NEGATIVE
- (FLOAT_STORE_FLAG_VALUE (inner_mode))))
+ && (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode),
+ REAL_VALUE_NEGATIVE (fsfv)))
#endif
))
&& GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<'))
@@ -9236,8 +9395,8 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (code == GE
&& GET_MODE_CLASS (inner_mode) == MODE_FLOAT
- && (REAL_VALUE_NEGATIVE
- (FLOAT_STORE_FLAG_VALUE (inner_mode))))
+ && (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode),
+ REAL_VALUE_NEGATIVE (fsfv)))
#endif
))
&& GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<'
@@ -9342,7 +9501,7 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
inequality floating-point comparison which needs to be reversed, 0 will
be returned.
- If EARLIEST is non-zero, it is a pointer to a place where the earliest
+ If EARLIEST is nonzero, it is a pointer to a place where the earliest
insn used in locating the condition was found. If a replacement test
of the condition is desired, it should be placed in front of that
insn and we will be sure that the inputs are still valid. */
@@ -9597,11 +9756,11 @@ loop_regs_scan (loop, extra_size)
if (LOOP_INFO (loop)->has_call)
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i)
- && rtx_varies_p (gen_rtx_REG (Pmode, i), /*for_alias=*/1))
- {
- regs->array[i].may_not_optimize = 1;
- regs->array[i].set_in_loop = 1;
- }
+ && rtx_varies_p (regno_reg_rtx[i], 1))
+ {
+ regs->array[i].may_not_optimize = 1;
+ regs->array[i].set_in_loop = 1;
+ }
#ifdef AVOID_CCMODE_COPIES
/* Don't try to move insns which set CC registers if we should not
@@ -9840,9 +9999,20 @@ load_mems (loop)
&& rtx_equal_p (SET_DEST (set), mem))
SET_REGNO_REG_SET (&store_copies, REGNO (SET_SRC (set)));
- /* Replace the memory reference with the shadow register. */
- replace_loop_mems (p, loop_info->mems[i].mem,
- loop_info->mems[i].reg);
+ /* If this is a call which uses / clobbers this memory
+ location, we must not change the interface here. */
+ if (GET_CODE (p) == CALL_INSN
+ && reg_mentioned_p (loop_info->mems[i].mem,
+ CALL_INSN_FUNCTION_USAGE (p)))
+ {
+ cancel_changes (0);
+ loop_info->mems[i].optimize = 0;
+ break;
+ }
+ else
+ /* Replace the memory reference with the shadow register. */
+ replace_loop_mems (p, loop_info->mems[i].mem,
+ loop_info->mems[i].reg, written);
}
if (GET_CODE (p) == CODE_LABEL
@@ -9850,7 +10020,9 @@ load_mems (loop)
maybe_never = 1;
}
- if (! apply_change_group ())
+ if (! loop_info->mems[i].optimize)
+ ; /* We found we couldn't do the replacement, so do nothing. */
+ else if (! apply_change_group ())
/* We couldn't replace all occurrences of the MEM. */
loop_info->mems[i].optimize = 0;
else
@@ -10213,6 +10385,33 @@ try_swap_copy_prop (loop, replacement, regno)
}
}
+/* Worker function for find_mem_in_note, called via for_each_rtx. */
+
+static int
+find_mem_in_note_1 (x, data)
+ rtx *x;
+ void *data;
+{
+ if (*x != NULL_RTX && GET_CODE (*x) == MEM)
+ {
+ rtx *res = (rtx *) data;
+ *res = *x;
+ return 1;
+ }
+ return 0;
+}
+
+/* Returns the first MEM found in NOTE by depth-first search. */
+
+static rtx
+find_mem_in_note (note)
+ rtx note;
+{
+ if (note && for_each_rtx (&note, find_mem_in_note_1, &note))
+ return note;
+ return NULL_RTX;
+}
+
/* Replace MEM with its associated pseudo register. This function is
called from load_mems via for_each_rtx. DATA is actually a pointer
to a structure describing the instruction currently being scanned
@@ -10255,10 +10454,11 @@ replace_loop_mem (mem, data)
}
static void
-replace_loop_mems (insn, mem, reg)
+replace_loop_mems (insn, mem, reg, written)
rtx insn;
rtx mem;
rtx reg;
+ int written;
{
loop_replace_args args;
@@ -10267,6 +10467,26 @@ replace_loop_mems (insn, mem, reg)
args.replacement = reg;
for_each_rtx (&insn, replace_loop_mem, &args);
+
+ /* If we hoist a mem write out of the loop, then REG_EQUAL
+ notes referring to the mem are no longer valid. */
+ if (written)
+ {
+ rtx note, sub;
+ rtx *link;
+
+ for (link = &REG_NOTES (insn); (note = *link); link = &XEXP (note, 1))
+ {
+ if (REG_NOTE_KIND (note) == REG_EQUAL
+ && (sub = find_mem_in_note (note))
+ && true_dependence (mem, VOIDmode, sub, rtx_varies_p))
+ {
+ /* Remove the note. */
+ validate_change (NULL_RTX, link, XEXP (note, 1), 1);
+ break;
+ }
+ }
+ }
}
/* Replace one register with another. Called through for_each_rtx; PX points
@@ -10348,7 +10568,7 @@ loop_insn_emit_after (loop, where_bb, where_insn, pattern)
}
-/* If WHERE_INSN is non-zero emit insn for PATTERN before WHERE_INSN
+/* If WHERE_INSN is nonzero emit insn for PATTERN before WHERE_INSN
in basic block WHERE_BB (ignored in the interim) within the loop
otherwise hoist PATTERN into the loop pre-header. */
@@ -10411,6 +10631,21 @@ loop_insn_sink (loop, pattern)
return loop_insn_emit_before (loop, 0, loop->sink, pattern);
}
+/* bl->final_value can be eighter general_operand or PLUS of general_operand
+ and constant. Emit sequence of intructions to load it into REG */
+static rtx
+gen_load_of_final_value (reg, final_value)
+ rtx reg, final_value;
+{
+ rtx seq;
+ start_sequence ();
+ final_value = force_operand (final_value, reg);
+ if (final_value != reg)
+ emit_move_insn (reg, final_value);
+ seq = get_insns ();
+ end_sequence ();
+ return seq;
+}
/* If the loop has multiple exits, emit insn for PATTERN before the
loop to ensure that it will always be executed no matter how the
@@ -10510,9 +10745,9 @@ loop_iv_class_dump (bl, file, verbose)
fprintf (file, " Giv%d: insn %d, benefit %d, ",
i, INSN_UID (v->insn), v->benefit);
if (v->giv_type == DEST_ADDR)
- print_simple_rtl (file, v->mem);
+ print_simple_rtl (file, v->mem);
else
- print_simple_rtl (file, single_set (v->insn));
+ print_simple_rtl (file, single_set (v->insn));
fputc ('\n', file);
}
}
@@ -10555,7 +10790,7 @@ loop_giv_dump (v, file, verbose)
if (v->giv_type == DEST_REG)
fprintf (file, "Giv %d: insn %d",
- REGNO (v->dest_reg), INSN_UID (v->insn));
+ REGNO (v->dest_reg), INSN_UID (v->insn));
else
fprintf (file, "Dest address: insn %d",
INSN_UID (v->insn));
diff --git a/contrib/gcc/loop.h b/contrib/gcc/loop.h
index 6d18b01..362013f 100644
--- a/contrib/gcc/loop.h
+++ b/contrib/gcc/loop.h
@@ -28,7 +28,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define LOOP_UNROLL 1
#define LOOP_BCT 2
#define LOOP_PREFETCH 4
-#define LOOP_FIRST_PASS 8
+#define LOOP_AUTO_UNROLL 8
/* Get the loop info pointer of a loop. */
#define LOOP_INFO(LOOP) ((struct loop_info *) (LOOP)->aux)
@@ -145,7 +145,7 @@ struct induction
same biv register. */
struct induction *same; /* If this giv has been combined with another
giv, this points to the base giv. The base
- giv will have COMBINED_WITH non-zero. */
+ giv will have COMBINED_WITH nonzero. */
HOST_WIDE_INT const_adjust; /* Used by loop unrolling, when an address giv
is split, and a constant is eliminated from
the address, the -constant is stored here
@@ -205,7 +205,7 @@ enum iv_mode
struct iv
{
enum iv_mode type;
- union
+ union
{
struct iv_class *class;
struct induction *info;
@@ -248,7 +248,7 @@ struct loop_reg
During code motion, a negative value indicates a reg that has
been made a candidate; in particular -2 means that it is an
candidate that we know is equal to a constant and -1 means that
- it is an candidate not known equal to a constant. After code
+ it is a candidate not known equal to a constant. After code
motion, regs moved have 0 (which is accurate now) while the
failed candidates have the original number of times set.
@@ -304,6 +304,8 @@ struct loop_info
int has_libcall;
/* Nonzero if there is a non constant call in the current loop. */
int has_nonconst_call;
+ /* Nonzero if there is a prefetch instruction in the current loop. */
+ int has_prefetch;
/* Nonzero if there is a volatile memory reference in the current
loop. */
int has_volatile;
@@ -375,7 +377,7 @@ struct loop_info
struct loop_regs regs;
/* The induction variable information in loop. */
struct loop_ivs ivs;
- /* Non-zero if call is in pre_header extended basic block. */
+ /* Nonzero if call is in pre_header extended basic block. */
int pre_header_has_call;
};
@@ -395,7 +397,7 @@ int loop_invariant_p PARAMS ((const struct loop *, rtx));
rtx get_condition_for_loop PARAMS ((const struct loop *, rtx));
void loop_iv_add_mult_hoist PARAMS ((const struct loop *, rtx, rtx, rtx, rtx));
void loop_iv_add_mult_sink PARAMS ((const struct loop *, rtx, rtx, rtx, rtx));
-void loop_iv_add_mult_emit_before PARAMS ((const struct loop *, rtx,
+void loop_iv_add_mult_emit_before PARAMS ((const struct loop *, rtx,
rtx, rtx, rtx,
basic_block, rtx));
rtx express_from PARAMS ((struct induction *, struct induction *));
@@ -415,7 +417,7 @@ int back_branch_in_range_p PARAMS ((const struct loop *, rtx));
int loop_insn_first_p PARAMS ((rtx, rtx));
typedef rtx (*loop_insn_callback) PARAMS ((struct loop *, rtx, int, int));
void for_each_insn_in_loop PARAMS ((struct loop *, loop_insn_callback));
-rtx loop_insn_emit_before PARAMS((const struct loop *, basic_block,
+rtx loop_insn_emit_before PARAMS((const struct loop *, basic_block,
rtx, rtx));
rtx loop_insn_sink PARAMS((const struct loop *, rtx));
rtx loop_insn_hoist PARAMS((const struct loop *, rtx));
diff --git a/contrib/gcc/machmode.def b/contrib/gcc/machmode.def
index 6212334..5013e1f 100644
--- a/contrib/gcc/machmode.def
+++ b/contrib/gcc/machmode.def
@@ -113,11 +113,10 @@ DEF_MACHMODE (CTImode, "CTI", MODE_COMPLEX_INT, BITS_PER_UNIT*32, 32, 16, COImod
DEF_MACHMODE (COImode, "COI", MODE_COMPLEX_INT, BITS_PER_UNIT*64, 64, 32, VOIDmode, OImode)
/* Vector modes. */
-/* There are no V1xx vector modes. These are equivalent to normal
- scalar modes. */
/* The wider mode field for vectors follows in order of increasing bit
size with QI coming before HI, HI before SI, and SI before DI
within same bit sizes. */
+DEF_MACHMODE (V1DImode, "V1DI", MODE_VECTOR_INT, BITS_PER_UNIT*8, 8, 8, V2QImode, DImode)
DEF_MACHMODE (V2QImode, "V2QI", MODE_VECTOR_INT, BITS_PER_UNIT*2, 2, 1, V4QImode, QImode)
DEF_MACHMODE (V2HImode, "V2HI", MODE_VECTOR_INT, BITS_PER_UNIT*4, 4, 2, V8QImode, HImode)
DEF_MACHMODE (V2SImode, "V2SI", MODE_VECTOR_INT, BITS_PER_UNIT*8, 8, 4, V16QImode, SImode)
@@ -151,18 +150,20 @@ DEF_MACHMODE (BLKmode, "BLK", MODE_RANDOM, 0, 0, 0, VOIDmode, VOIDmode)
/* The modes for representing the condition codes come last. CCmode
is always defined. Additional modes for the condition code can be
- specified in the EXTRA_CC_MODES macro. All MODE_CC modes are the
+ specified in the EXTRA_CC_MODES header. All MODE_CC modes are the
same width as SImode and have VOIDmode as their next wider mode. */
-#define CC(E, M) DEF_MACHMODE (E, M, MODE_CC, BITS_PER_UNIT*4, 4, 4, VOIDmode, VOIDmode)
-
-CC (CCmode, "CC")
-
-#ifdef EXTRA_CC_MODES
-EXTRA_CC_MODES
-#endif
+/* We do not use CC() for CCmode to avoid a warning about use of
+ function-like macros with no arguments. */
+DEF_MACHMODE (CCmode, "CC", MODE_CC, BITS_PER_UNIT*4, 4, 4, VOIDmode, VOIDmode)
+#ifdef EXTRA_MODES_FILE
+#define CC(N) \
+ DEF_MACHMODE (CONCAT2 (N,mode), STRINGX (N), \
+ MODE_CC, BITS_PER_UNIT*4, 4, 4, VOIDmode, VOIDmode)
+#include EXTRA_MODES_FILE
#undef CC
+#endif
/* The symbol Pmode stands for one of the above machine modes (usually SImode).
The tm file specifies which one. It is not a distinct mode. */
diff --git a/contrib/gcc/machmode.h b/contrib/gcc/machmode.h
index f581cd0..46247d5 100644
--- a/contrib/gcc/machmode.h
+++ b/contrib/gcc/machmode.h
@@ -75,6 +75,15 @@ extern const enum mode_class mode_class[NUM_MACHINE_MODES];
(GET_MODE_CLASS (MODE) == MODE_VECTOR_INT \
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT)
+/* Nonzero if MODE is a scalar integral mode. */
+#define SCALAR_INT_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_INT \
+ || GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT)
+
+/* Nonzero if MODE is a scalar floating point mode. */
+#define SCALAR_FLOAT_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_FLOAT)
+
/* Get the size in bytes of an object of mode MODE. */
extern const unsigned char mode_size[NUM_MACHINE_MODES];
diff --git a/contrib/gcc/mbchar.c b/contrib/gcc/mbchar.c
index 5c86dbf..4251736 100644
--- a/contrib/gcc/mbchar.c
+++ b/contrib/gcc/mbchar.c
@@ -51,7 +51,7 @@ typedef enum {COPYA, COPYJ, COPYJ2, MAKE_A, MAKE_J, NOOP,
Thus, maximum returned length is:
2 (switch to JIS) + 2 (JIS characters) + 2 (switch back to ASCII) = 6. */
-static JIS_STATE JIS_state_table[JIS_S_NUM][JIS_C_NUM] = {
+static const JIS_STATE JIS_state_table[JIS_S_NUM][JIS_C_NUM] = {
/* ESCAPE DOLLAR BRACKET AT B J NUL JIS_CHAR OTH*/
/*ASCII*/ { A_ESC, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,ASCII,ASCII},
/*A_ESC*/ { ASCII, A_ESC_DL,ASCII, ASCII, ASCII, ASCII, ASCII,ASCII,ASCII},
@@ -65,7 +65,7 @@ static JIS_STATE JIS_state_table[JIS_S_NUM][JIS_C_NUM] = {
/*J2_ESC_BR*/{INV, INV, INV, INV, ASCII, ASCII, INV, INV, INV },
};
-static JIS_ACTION JIS_action_table[JIS_S_NUM][JIS_C_NUM] = {
+static const JIS_ACTION JIS_action_table[JIS_S_NUM][JIS_C_NUM] = {
/* ESCAPE DOLLAR BRACKET AT B J NUL JIS_CHAR OTH */
/*ASCII */ {NOOP, COPYA, COPYA, COPYA, COPYA, COPYA, EMPTY, COPYA, COPYA},
/*A_ESC */ {COPYA, NOOP, COPYA, COPYA, COPYA, COPYA, COPYA, COPYA, COPYA},
diff --git a/contrib/gcc/md5.c b/contrib/gcc/md5.c
index 9450586..e458f2a 100644
--- a/contrib/gcc/md5.c
+++ b/contrib/gcc/md5.c
@@ -229,7 +229,7 @@ md5_process_bytes (buffer, len, ctx)
ctx->buflen = (left_over + add) & 63;
}
- buffer = (const char *) buffer + add;
+ buffer = (const void *) ((const char *) buffer + add);
len -= add;
}
@@ -237,7 +237,7 @@ md5_process_bytes (buffer, len, ctx)
if (len > 64)
{
md5_process_block (buffer, len & ~63, ctx);
- buffer = (const char *) buffer + (len & ~63);
+ buffer = (const void *) ((const char *) buffer + (len & ~63));
len &= 63;
}
@@ -269,7 +269,7 @@ md5_process_block (buffer, len, ctx)
struct md5_ctx *ctx;
{
md5_uint32 correct_words[16];
- const md5_uint32 *words = buffer;
+ const md5_uint32 *words = (const md5_uint32 *) buffer;
size_t nwords = len / sizeof (md5_uint32);
const md5_uint32 *endp = words + nwords;
md5_uint32 A = ctx->A;
@@ -343,68 +343,76 @@ md5_process_block (buffer, len, ctx)
in CORRECT_WORDS. Redefine the macro to take an additional first
argument specifying the function to use. */
#undef OP
-#define OP(f, a, b, c, d, k, s, T) \
+#define OP(a, b, c, d, k, s, T) \
do \
{ \
- a += f (b, c, d) + correct_words[k] + T; \
+ a += FX (b, c, d) + correct_words[k] + T; \
CYCLIC (a, s); \
a += b; \
} \
while (0)
+#define FX(b, c, d) FG (b, c, d)
+
/* Round 2. */
- OP (FG, A, B, C, D, 1, 5, (md5_uint32) 0xf61e2562);
- OP (FG, D, A, B, C, 6, 9, (md5_uint32) 0xc040b340);
- OP (FG, C, D, A, B, 11, 14, (md5_uint32) 0x265e5a51);
- OP (FG, B, C, D, A, 0, 20, (md5_uint32) 0xe9b6c7aa);
- OP (FG, A, B, C, D, 5, 5, (md5_uint32) 0xd62f105d);
- OP (FG, D, A, B, C, 10, 9, (md5_uint32) 0x02441453);
- OP (FG, C, D, A, B, 15, 14, (md5_uint32) 0xd8a1e681);
- OP (FG, B, C, D, A, 4, 20, (md5_uint32) 0xe7d3fbc8);
- OP (FG, A, B, C, D, 9, 5, (md5_uint32) 0x21e1cde6);
- OP (FG, D, A, B, C, 14, 9, (md5_uint32) 0xc33707d6);
- OP (FG, C, D, A, B, 3, 14, (md5_uint32) 0xf4d50d87);
- OP (FG, B, C, D, A, 8, 20, (md5_uint32) 0x455a14ed);
- OP (FG, A, B, C, D, 13, 5, (md5_uint32) 0xa9e3e905);
- OP (FG, D, A, B, C, 2, 9, (md5_uint32) 0xfcefa3f8);
- OP (FG, C, D, A, B, 7, 14, (md5_uint32) 0x676f02d9);
- OP (FG, B, C, D, A, 12, 20, (md5_uint32) 0x8d2a4c8a);
+ OP (A, B, C, D, 1, 5, (md5_uint32) 0xf61e2562);
+ OP (D, A, B, C, 6, 9, (md5_uint32) 0xc040b340);
+ OP (C, D, A, B, 11, 14, (md5_uint32) 0x265e5a51);
+ OP (B, C, D, A, 0, 20, (md5_uint32) 0xe9b6c7aa);
+ OP (A, B, C, D, 5, 5, (md5_uint32) 0xd62f105d);
+ OP (D, A, B, C, 10, 9, (md5_uint32) 0x02441453);
+ OP (C, D, A, B, 15, 14, (md5_uint32) 0xd8a1e681);
+ OP (B, C, D, A, 4, 20, (md5_uint32) 0xe7d3fbc8);
+ OP (A, B, C, D, 9, 5, (md5_uint32) 0x21e1cde6);
+ OP (D, A, B, C, 14, 9, (md5_uint32) 0xc33707d6);
+ OP (C, D, A, B, 3, 14, (md5_uint32) 0xf4d50d87);
+ OP (B, C, D, A, 8, 20, (md5_uint32) 0x455a14ed);
+ OP (A, B, C, D, 13, 5, (md5_uint32) 0xa9e3e905);
+ OP (D, A, B, C, 2, 9, (md5_uint32) 0xfcefa3f8);
+ OP (C, D, A, B, 7, 14, (md5_uint32) 0x676f02d9);
+ OP (B, C, D, A, 12, 20, (md5_uint32) 0x8d2a4c8a);
+
+#undef FX
+#define FX(b, c, d) FH (b, c, d)
/* Round 3. */
- OP (FH, A, B, C, D, 5, 4, (md5_uint32) 0xfffa3942);
- OP (FH, D, A, B, C, 8, 11, (md5_uint32) 0x8771f681);
- OP (FH, C, D, A, B, 11, 16, (md5_uint32) 0x6d9d6122);
- OP (FH, B, C, D, A, 14, 23, (md5_uint32) 0xfde5380c);
- OP (FH, A, B, C, D, 1, 4, (md5_uint32) 0xa4beea44);
- OP (FH, D, A, B, C, 4, 11, (md5_uint32) 0x4bdecfa9);
- OP (FH, C, D, A, B, 7, 16, (md5_uint32) 0xf6bb4b60);
- OP (FH, B, C, D, A, 10, 23, (md5_uint32) 0xbebfbc70);
- OP (FH, A, B, C, D, 13, 4, (md5_uint32) 0x289b7ec6);
- OP (FH, D, A, B, C, 0, 11, (md5_uint32) 0xeaa127fa);
- OP (FH, C, D, A, B, 3, 16, (md5_uint32) 0xd4ef3085);
- OP (FH, B, C, D, A, 6, 23, (md5_uint32) 0x04881d05);
- OP (FH, A, B, C, D, 9, 4, (md5_uint32) 0xd9d4d039);
- OP (FH, D, A, B, C, 12, 11, (md5_uint32) 0xe6db99e5);
- OP (FH, C, D, A, B, 15, 16, (md5_uint32) 0x1fa27cf8);
- OP (FH, B, C, D, A, 2, 23, (md5_uint32) 0xc4ac5665);
+ OP (A, B, C, D, 5, 4, (md5_uint32) 0xfffa3942);
+ OP (D, A, B, C, 8, 11, (md5_uint32) 0x8771f681);
+ OP (C, D, A, B, 11, 16, (md5_uint32) 0x6d9d6122);
+ OP (B, C, D, A, 14, 23, (md5_uint32) 0xfde5380c);
+ OP (A, B, C, D, 1, 4, (md5_uint32) 0xa4beea44);
+ OP (D, A, B, C, 4, 11, (md5_uint32) 0x4bdecfa9);
+ OP (C, D, A, B, 7, 16, (md5_uint32) 0xf6bb4b60);
+ OP (B, C, D, A, 10, 23, (md5_uint32) 0xbebfbc70);
+ OP (A, B, C, D, 13, 4, (md5_uint32) 0x289b7ec6);
+ OP (D, A, B, C, 0, 11, (md5_uint32) 0xeaa127fa);
+ OP (C, D, A, B, 3, 16, (md5_uint32) 0xd4ef3085);
+ OP (B, C, D, A, 6, 23, (md5_uint32) 0x04881d05);
+ OP (A, B, C, D, 9, 4, (md5_uint32) 0xd9d4d039);
+ OP (D, A, B, C, 12, 11, (md5_uint32) 0xe6db99e5);
+ OP (C, D, A, B, 15, 16, (md5_uint32) 0x1fa27cf8);
+ OP (B, C, D, A, 2, 23, (md5_uint32) 0xc4ac5665);
+
+#undef FX
+#define FX(b, c, d) FI (b, c, d)
/* Round 4. */
- OP (FI, A, B, C, D, 0, 6, (md5_uint32) 0xf4292244);
- OP (FI, D, A, B, C, 7, 10, (md5_uint32) 0x432aff97);
- OP (FI, C, D, A, B, 14, 15, (md5_uint32) 0xab9423a7);
- OP (FI, B, C, D, A, 5, 21, (md5_uint32) 0xfc93a039);
- OP (FI, A, B, C, D, 12, 6, (md5_uint32) 0x655b59c3);
- OP (FI, D, A, B, C, 3, 10, (md5_uint32) 0x8f0ccc92);
- OP (FI, C, D, A, B, 10, 15, (md5_uint32) 0xffeff47d);
- OP (FI, B, C, D, A, 1, 21, (md5_uint32) 0x85845dd1);
- OP (FI, A, B, C, D, 8, 6, (md5_uint32) 0x6fa87e4f);
- OP (FI, D, A, B, C, 15, 10, (md5_uint32) 0xfe2ce6e0);
- OP (FI, C, D, A, B, 6, 15, (md5_uint32) 0xa3014314);
- OP (FI, B, C, D, A, 13, 21, (md5_uint32) 0x4e0811a1);
- OP (FI, A, B, C, D, 4, 6, (md5_uint32) 0xf7537e82);
- OP (FI, D, A, B, C, 11, 10, (md5_uint32) 0xbd3af235);
- OP (FI, C, D, A, B, 2, 15, (md5_uint32) 0x2ad7d2bb);
- OP (FI, B, C, D, A, 9, 21, (md5_uint32) 0xeb86d391);
+ OP (A, B, C, D, 0, 6, (md5_uint32) 0xf4292244);
+ OP (D, A, B, C, 7, 10, (md5_uint32) 0x432aff97);
+ OP (C, D, A, B, 14, 15, (md5_uint32) 0xab9423a7);
+ OP (B, C, D, A, 5, 21, (md5_uint32) 0xfc93a039);
+ OP (A, B, C, D, 12, 6, (md5_uint32) 0x655b59c3);
+ OP (D, A, B, C, 3, 10, (md5_uint32) 0x8f0ccc92);
+ OP (C, D, A, B, 10, 15, (md5_uint32) 0xffeff47d);
+ OP (B, C, D, A, 1, 21, (md5_uint32) 0x85845dd1);
+ OP (A, B, C, D, 8, 6, (md5_uint32) 0x6fa87e4f);
+ OP (D, A, B, C, 15, 10, (md5_uint32) 0xfe2ce6e0);
+ OP (C, D, A, B, 6, 15, (md5_uint32) 0xa3014314);
+ OP (B, C, D, A, 13, 21, (md5_uint32) 0x4e0811a1);
+ OP (A, B, C, D, 4, 6, (md5_uint32) 0xf7537e82);
+ OP (D, A, B, C, 11, 10, (md5_uint32) 0xbd3af235);
+ OP (C, D, A, B, 2, 15, (md5_uint32) 0x2ad7d2bb);
+ OP (B, C, D, A, 9, 21, (md5_uint32) 0xeb86d391);
/* Add the starting values of the context. */
A += A_save;
diff --git a/contrib/gcc/mkconfig.sh b/contrib/gcc/mkconfig.sh
index f0d97ec..cc87ccb 100644
--- a/contrib/gcc/mkconfig.sh
+++ b/contrib/gcc/mkconfig.sh
@@ -2,11 +2,11 @@
# Generate gcc's config.h, which is not your normal autoconf-generated
# config.h (that's auto-(host|build).h). $1 is the file to generate.
-# HEADERS, DEFINES, and possibly TARGET_CPU_DEFAULT are expected to be
-# set in the environment.
+# TM_DEFINES, HEADERS, XM_DEFINES, and possibly TARGET_CPU_DEFAULT are
+# expected to be set in the environment.
if [ -z "$1" ]; then
- echo "Usage: HEADERS='list' DEFINES='list' mkconfig.sh FILE" >&2
+ echo "Usage: TM_DEFINES='list' HEADERS='list' XM_DEFINES='list' mkconfig.sh FILE" >&2
exit 1
fi
@@ -19,6 +19,13 @@ if [ "$TARGET_CPU_DEFAULT" != "" ]; then
echo "#define TARGET_CPU_DEFAULT ($TARGET_CPU_DEFAULT)" >> ${output}T
fi
+# Provide defines for other target machine macros to be used everywhere.
+for def in $TM_DEFINES; do
+ echo "#ifndef $def" | sed 's/=.*//' >> ${output}T
+ echo "# define $def" | sed 's/=/ /' >> ${output}T
+ echo "#endif" >> ${output}T
+done
+
# The first entry in HEADERS may be auto-host.h or auto-build.h;
# it wants to be included even when not -DIN_GCC.
if [ -n "$HEADERS" ]; then
@@ -50,6 +57,7 @@ typedef struct rtvec_def *rtvec;
union tree_node;
typedef union tree_node *tree;
#endif
+#define GTY(x)
EOF
;;
esac
@@ -62,7 +70,7 @@ if [ -n "$HEADERS" ]; then
echo '#endif' >> ${output}T
fi
-for def in $DEFINES; do
+for def in $XM_DEFINES; do
echo "#ifndef $def" | sed 's/=.*//' >> ${output}T
echo "# define $def" | sed 's/=/ /' >> ${output}T
echo "#endif" >> ${output}T
diff --git a/contrib/gcc/mkheaders.in b/contrib/gcc/mkheaders.in
new file mode 100644
index 0000000..a97c49e
--- /dev/null
+++ b/contrib/gcc/mkheaders.in
@@ -0,0 +1,101 @@
+#!/bin/sh
+
+# Copyright (C) 2002 Free Software Foundation, Inc.
+
+#This file is part of GCC.
+
+#GCC is free software; you can redistribute it and/or modify it under
+#the terms of the GNU General Public License as published by the Free
+#Software Foundation; either version 2, or (at your option) any later
+#version.
+
+#GCC is distributed in the hope that it will be useful, but WITHOUT
+#ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+#FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+#for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with GCC; see the file COPYING. If not, write to the Free
+#Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+#02111-1307, USA.
+
+# Basic information
+target=@target@
+target_alias=@target_alias@
+version=@gcc_version@
+
+VERBOSE=0
+while [ x$1 = x-v ] ; do
+ shift
+ VERBOSE=`expr $VERBOSE + 1`
+done
+export VERBOSE
+
+if [ x$1 = x--help ] ; then
+ echo "Usage: mkheaders [options] [prefix]"
+ echo "Options:"
+ echo " -v Print more output (may be repeated for even more output)"
+ echo " --help This help"
+ echo " --version Print version information"
+ exit 0
+fi
+
+if [ x$1 = x--version ] ; then
+ echo "mkheaders (GCC) version $version"
+ echo "Copyright 2002 Free Software Foundation, Inc."
+ echo "This program is free software; you may redistribute it under the"
+ echo "terms of the GNU General Public License. This program has"
+ echo "absolutely no warranty."
+ exit 0
+fi
+
+# Common prefix for installation directories.
+if [ x$1 != x ] ; then
+ prefix=$1
+else
+ prefix=@prefix@
+fi
+# Directory in which to put localized header files. On the systems with
+# gcc as the native cc, `local_prefix' may not be `prefix' which is
+# `/usr'.
+# NOTE: local_prefix *should not* default from prefix.
+local_prefix=@local_prefix@
+# Directory in which to put host dependent programs and libraries
+exec_prefix=@exec_prefix@
+# Directory in which to put the directories used by the compiler.
+libdir=@libdir@
+# Directory in which the compiler finds executables, libraries, etc.
+libsubdir=${libdir}/gcc-lib/${target_alias}/${version}
+# Since gcc_tooldir does not exist at build-time, use -B${build_tooldir}/bin/
+build_tooldir=${exec_prefix}/${target_alias}
+# Directory to search for site-specific includes.
+local_includedir=${local_prefix}/include
+includedir=${prefix}/include
+
+itoolsdir=${libsubdir}/install-tools
+incdir=${libsubdir}/include
+
+. ${itoolsdir}/mkheaders.conf
+
+cd ${itoolsdir}
+rm -rf ${incdir}/*
+
+if [ x${STMP_FIXINC} != x ] ; then
+ TARGET_MACHINE="${target}" target_canonical="${target}" \
+ ${SHELL} ./fixinc.sh ${incdir} \
+ ${SYSTEM_HEADER_DIR} ${OTHER_FIXINCLUDES_DIRS}
+ rm -f ${incdir}/syslimits.h
+ if [ -f ${incdir}/limits.h ]; then
+ mv ${incdir}/limits.h ${incdir}/syslimits.h
+ else
+ cp gsyslimits.h ${incdir}/syslimits.h
+ fi
+fi
+
+cp include/* ${incdir}
+
+if [ x${STMP_FIXPROTO} != x ] ; then
+ mkinstalldirs="${SHELL} ${itoolsdir}/mkinstalldirs"
+ export FIXPROTO_DEFINES mkinstalldirs
+ ${SHELL} fixproto ${incdir} ${incdir} ${SYSTEM_HEADER_DIR} || exit 1
+fi
diff --git a/contrib/gcc/mklibgcc.in b/contrib/gcc/mklibgcc.in
index cde9443..3c3358a 100644
--- a/contrib/gcc/mklibgcc.in
+++ b/contrib/gcc/mklibgcc.in
@@ -1,6 +1,6 @@
#!/bin/sh
# Construct makefile for libgcc.
-# Copyright (C) 2000, 2002 Free Software Foundation, Inc.
+# Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
#
# This file is part of GCC.
@@ -21,6 +21,8 @@
# LIB2_DIVMOD_FUNCS
# DPBIT
# DPBIT_FUNCS
+# TPBIT
+# TPBIT_FUNCS
# LIBGCC
# MULTILIBS
# EXTRA_MULTILIB_PARTS
@@ -56,8 +58,8 @@ make_compile='$(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
AR_EXTRACT_FOR_TARGET="$(AR_EXTRACT_FOR_TARGET)" \
AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \
CC="$(CC)" CFLAGS="$(CFLAGS)" \
- HOST_PREFIX="$(HOST_PREFIX)" \
- HOST_PREFIX_1="$(HOST_PREFIX_1)" \
+ BUILD_PREFIX="$(BUILD_PREFIX)" \
+ BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
LANGUAGES="$(LANGUAGES)"'
# Dependencies for libgcc2.c
@@ -174,6 +176,21 @@ if [ "$DPBIT" ]; then
done
fi
+if [ "$TPBIT" ]; then
+ for name in $TPBIT_FUNCS; do
+ for ml in $MULTILIBS; do
+ dir=`echo ${ml} | sed -e 's/;.*$//' -e 's/=/$(EQ)/g'`
+ flags=`echo ${ml} | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`;
+ out="libgcc/${dir}/${name}${objext}"
+
+ echo $out: $TPBIT $fpbit_c_dep
+ echo " $gcc_compile" -DFINE_GRAINED_LIBRARIES $flags -DL$name \
+ -c $TPBIT -o $out
+ done
+ libgcc2_objs="$libgcc2_objs ${name}${objext}"
+ done
+fi
+
for file in $LIB2ADD; do
name=`echo $file | sed -e 's/[.][cSo]$//' -e 's/[.]asm$//' -e 's/[.]txt$//'`
oname=`echo $name | sed -e 's,.*/,,'`
diff --git a/contrib/gcc/mkmap-symver.awk b/contrib/gcc/mkmap-symver.awk
index 51b6df2..e4bc58e 100644
--- a/contrib/gcc/mkmap-symver.awk
+++ b/contrib/gcc/mkmap-symver.awk
@@ -20,6 +20,7 @@
BEGIN {
state = "nm";
+ sawsymbol = 0;
}
# Remove comment and blank lines.
@@ -42,6 +43,7 @@ state == "nm" && ($1 == "U" || $2 == "U") {
state == "nm" && NF == 3 {
def[$3] = 1;
+ sawsymbol = 1;
next;
}
@@ -77,6 +79,11 @@ $1 == "}" {
}
END {
+ if (!sawsymbol)
+ {
+ print "No symbols seen -- broken or mis-installed nm?" | "cat 1>&2";
+ exit 1;
+ }
for (l in libs)
output(l);
}
@@ -89,10 +96,15 @@ function output(lib) {
output(inherit[lib]);
printf("%s {\n", lib);
- printf(" global:\n");
+ sawglobal = 0;
for (sym in ver)
if ((ver[sym] == lib) && (sym in def))
{
+ if (!sawglobal)
+ {
+ printf(" global:\n");
+ sawglobal = 1;
+ }
printf("\t%s;\n", sym);
if (dotsyms)
printf("\t.%s;\n", sym);
diff --git a/contrib/gcc/objc/Make-lang.in b/contrib/gcc/objc/Make-lang.in
index 379a16c..480f96b 100644
--- a/contrib/gcc/objc/Make-lang.in
+++ b/contrib/gcc/objc/Make-lang.in
@@ -63,10 +63,10 @@ objc-lang.o : $(srcdir)/objc/objc-lang.c \
-c $(srcdir)/objc/objc-lang.c $(OUTPUT_OPTION)
objc-parse.o : $(srcdir)/objc/objc-parse.c \
- $(CONFIG_H) $(TREE_H) $(srcdir)/toplev.h $(srcdir)/ggc.h \
- $(srcdir)/c-lex.h $(srcdir)/c-tree.h $(srcdir)/c-common.h \
+ $(CONFIG_H) $(TREE_H) $(C_COMMON_H) $(srcdir)/toplev.h $(srcdir)/ggc.h \
+ $(srcdir)/c-pragma.h $(srcdir)/c-tree.h \
$(srcdir)/input.h $(srcdir)/flags.h $(srcdir)/output.h \
- $(srcdir)/objc/objc-act.h $(SYSTEM_H) $(CPPLIB_H)
+ $(srcdir)/objc/objc-act.h $(SYSTEM_H)
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -I$(srcdir)/objc \
-c $(srcdir)/objc/objc-parse.c $(OUTPUT_OPTION)
@@ -90,13 +90,15 @@ $(srcdir)/objc/objc-parse.y: $(srcdir)/c-parse.in
objc-act.o : $(srcdir)/objc/objc-act.c \
$(CONFIG_H) $(TREE_H) $(RTL_H) $(SYSTEM_H) $(EXPR_H) $(TARGET_H) \
- $(srcdir)/c-tree.h $(srcdir)/c-common.h $(srcdir)/c-lex.h \
+ $(C_COMMON_H) $(srcdir)/c-tree.h $(srcdir)/diagnostic.h \
$(srcdir)/toplev.h $(srcdir)/flags.h $(srcdir)/objc/objc-act.h \
$(srcdir)/input.h $(srcdir)/function.h $(srcdir)/output.h $(srcdir)/debug.h \
- $(srcdir)/langhooks.h $(LANGHOOKS_DEF_H)
+ $(srcdir)/langhooks.h $(LANGHOOKS_DEF_H) gtype-objc.h
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -I$(srcdir)/objc \
-c $(srcdir)/objc/objc-act.c
+gtype-objc.h : s-gtype ; @true
+
#
# Build hooks:
@@ -129,6 +131,7 @@ objc.uninstall:
objc.mostlyclean:
-rm -f tmp-objc-prs.y
-rm -f objc/*$(objext) objc/xforward objc/fflags
+ -rm -f objc/*$(coverageexts)
objc.clean: objc.mostlyclean
-rm -rf objc-headers
objc.distclean:
diff --git a/contrib/gcc/objc/config-lang.in b/contrib/gcc/objc/config-lang.in
index 57066a4..d79ac13 100644
--- a/contrib/gcc/objc/config-lang.in
+++ b/contrib/gcc/objc/config-lang.in
@@ -32,3 +32,5 @@ compilers="cc1obj\$(exeext)"
stagestuff=""
target_libs=target-libobjc
+
+gtfiles="\$(srcdir)/objc/objc-act.h \$(srcdir)/c-parse.in \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c \$(srcdir)/c-parse.in"
diff --git a/contrib/gcc/objc/lang-specs.h b/contrib/gcc/objc/lang-specs.h
index 66e705b..540a9ae 100644
--- a/contrib/gcc/objc/lang-specs.h
+++ b/contrib/gcc/objc/lang-specs.h
@@ -25,17 +25,15 @@ Boston, MA 02111-1307, USA. */
{"@objective-c",
/* cc1obj has an integrated ISO C preprocessor. We should invoke the
external preprocessor if -save-temps or -traditional is given. */
- "%{E|M|MM:%(trad_capable_cpp) -lang-objc %{ansi:-std=c89} %(cpp_options)}\
+ "%{E|M|MM:%(trad_capable_cpp)\
+ -lang-objc %(cpp_options) %(cpp_debug_options)}\
%{!E:%{!M:%{!MM:\
- %{save-temps|no-integrated-cpp:%(trad_capable_cpp) -lang-objc %{ansi:-std=c89}\
- %(cpp_options) %{save-temps:%b.mi} %{!save-temps:%g.mi} \n\
+ %{traditional|ftraditional|traditional-cpp:\
+%eGNU Objective C no longer supports traditional compilation}\
+ %{save-temps|no-integrated-cpp:cc1obj -E %(cpp_options) %{save-temps:%b.mi} %{!save-temps:%g.mi} \n\
cc1obj -fpreprocessed %{save-temps:%b.mi} %{!save-temps:%g.mi} %(cc1_options) %{gen-decls}}\
%{!save-temps:%{!no-integrated-cpp:\
- %{traditional|ftraditional|traditional-cpp:\
- tradcpp0 -lang-objc %{ansi:-std=c89} %(cpp_options) %{!pipe:%g.mi} |\n\
- cc1obj -fpreprocessed %{!pipe:%g.mi} %(cc1_options) %{gen-decls}}\
- %{!traditional:%{!ftraditional:%{!traditional-cpp:\
- cc1obj %{ansi:-std=c89} %(cpp_unique_options) %(cc1_options) %{gen-decls}}}}}}\
+ cc1obj %(cpp_unique_options) %(cc1_options) %{gen-decls}}}\
%{!fsyntax-only:%(invoke_as)}}}}", 0},
{".mi", "@objc-cpp-output", 0},
{"@objc-cpp-output",
diff --git a/contrib/gcc/objc/objc-act.c b/contrib/gcc/objc/objc-act.c
index 02cb099..018ba04 100644
--- a/contrib/gcc/objc/objc-act.c
+++ b/contrib/gcc/objc/objc-act.c
@@ -45,7 +45,6 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "expr.h"
#include "c-tree.h"
-#include "c-lex.h"
#include "c-common.h"
#include "flags.h"
#include "objc-act.h"
@@ -55,9 +54,9 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "toplev.h"
#include "ggc.h"
-#include "cpplib.h"
#include "debug.h"
#include "target.h"
+#include "diagnostic.h"
/* This is the default way of generating a method name. */
/* I am not sure it is really correct.
@@ -86,48 +85,11 @@ Boston, MA 02111-1307, USA. */
#define OBJC_FORWARDING_MIN_OFFSET 0
#endif
-/* Define the special tree codes that we use. */
-
-/* Table indexed by tree code giving a string containing a character
- classifying the tree code. */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
-
-static const char objc_tree_code_type[] = {
- 'x',
-#include "objc-tree.def"
-};
-#undef DEFTREECODE
-
-/* Table indexed by tree code giving number of expression
- operands beyond the fixed part of the node structure.
- Not used for types or decls. */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
-
-static const int objc_tree_code_length[] = {
- 0,
-#include "objc-tree.def"
-};
-#undef DEFTREECODE
-
-/* Names of tree components.
- Used for printing out the tree and error messages. */
-#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
-
-static const char * const objc_tree_code_name[] = {
- "@@dummy",
-#include "objc-tree.def"
-};
-#undef DEFTREECODE
/* Set up for use of obstacks. */
#include "obstack.h"
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
/* This obstack is used to accumulate the encoding of a data type. */
static struct obstack util_obstack;
/* This points to the beginning of obstack contents,
@@ -166,7 +128,6 @@ static tree build_objc_method_call PARAMS ((int, tree, tree,
static void generate_strings PARAMS ((void));
static tree get_proto_encoding PARAMS ((tree));
static void build_selector_translation_table PARAMS ((void));
-static tree build_ivar_chain PARAMS ((tree, int));
static tree objc_add_static_instance PARAMS ((tree, tree));
@@ -199,7 +160,6 @@ static int check_methods_accessible PARAMS ((tree, tree,
static void encode_aggregate_within PARAMS ((tree, int, int,
int, int));
static const char *objc_demangle PARAMS ((const char *));
-static const char *objc_printable_name PARAMS ((tree, int));
static void objc_expand_function_end PARAMS ((void));
/* Hash tables to manage the global pool of method prototypes. */
@@ -270,7 +230,6 @@ static void dump_interface PARAMS ((FILE *, tree));
/* Everything else. */
-static void add_objc_tree_codes PARAMS ((void));
static tree define_decl PARAMS ((tree, tree));
static tree lookup_method_in_protocol_list PARAMS ((tree, tree, int));
static tree lookup_protocol_in_reflist PARAMS ((tree, tree));
@@ -289,7 +248,6 @@ static tree build_typed_selector_reference PARAMS ((tree, tree));
static tree build_selector_reference PARAMS ((tree));
static tree build_class_reference_decl PARAMS ((void));
static void add_class_reference PARAMS ((tree));
-static tree objc_copy_list PARAMS ((tree, tree *));
static tree build_protocol_template PARAMS ((void));
static tree build_descriptor_table_initializer PARAMS ((tree, tree));
static tree build_method_prototype_list_template PARAMS ((tree, int));
@@ -332,9 +290,7 @@ static void generate_classref_translation_entry PARAMS ((tree));
static void handle_class_ref PARAMS ((tree));
static void generate_struct_by_value_array PARAMS ((void))
ATTRIBUTE_NORETURN;
-static void objc_act_parse_init PARAMS ((void));
-static void ggc_mark_imp_list PARAMS ((void *));
-static void ggc_mark_hash_table PARAMS ((void *));
+static void encode_complete_bitfield PARAMS ((int, tree, int));
/*** Private Interface (data) ***/
@@ -353,13 +309,11 @@ static void ggc_mark_hash_table PARAMS ((void *));
#define UTAG_METHOD_LIST "_objc_method_list"
#define UTAG_CATEGORY "_objc_category"
#define UTAG_MODULE "_objc_module"
-#define UTAG_STATICS "_objc_statics"
#define UTAG_SYMTAB "_objc_symtab"
#define UTAG_SUPER "_objc_super"
#define UTAG_SELECTOR "_objc_selector"
#define UTAG_PROTOCOL "_objc_protocol"
-#define UTAG_PROTOCOL_LIST "_objc_protocol_list"
#define UTAG_METHOD_PROTOTYPE "_objc_method_prototype"
#define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
@@ -369,8 +323,6 @@ static void ggc_mark_hash_table PARAMS ((void *));
#define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
-static const char *constant_string_class_name = NULL;
-
static const char *TAG_GETCLASS;
static const char *TAG_GETMETACLASS;
static const char *TAG_MSGSEND;
@@ -381,8 +333,6 @@ static const char *default_constant_string_class_name;
/* The OCTI_... enumeration itself is in objc/objc-act.h. */
tree objc_global_trees[OCTI_MAX];
-int objc_receiver_context;
-
static void handle_impent PARAMS ((struct imp_entry *));
struct imp_entry *imp_list = 0;
@@ -403,33 +353,10 @@ extern enum debug_info_type write_symbols;
extern const char *dump_base_name;
-/* Generate code for GNU or NeXT runtime environment. */
-
-#ifdef NEXT_OBJC_RUNTIME
-int flag_next_runtime = 1;
-#else
-int flag_next_runtime = 0;
-#endif
-
-int flag_typed_selectors;
-
-/* Open and close the file for outputting class declarations, if requested. */
-
-int flag_gen_declaration = 0;
+static int flag_typed_selectors;
FILE *gen_declaration_file;
-/* Warn if multiple methods are seen for the same selector, but with
- different argument types. */
-
-int warn_selector = 0;
-
-/* Warn if methods required by a protocol are not implemented in the
- class adopting it. When turned off, methods inherited to that
- class are also considered implemented */
-
-int flag_warn_protocol = 1;
-
/* Tells "encode_pointer/encode_aggregate" whether we are generating
type descriptors for instance variables (as opposed to methods).
Type descriptors for instance variables contain more information
@@ -437,12 +364,6 @@ int flag_warn_protocol = 1;
static int generating_instance_variables = 0;
-/* Tells the compiler that this is a special run. Do not perform any
- compiling, instead we are to test some platform dependent features
- and output a C header file with appropriate definitions. */
-
-static int print_struct_values = 0;
-
/* Some platforms pass small structures through registers versus
through an invisible pointer. Determine at what size structure is
the transition point between the two possibilities. */
@@ -511,9 +432,8 @@ objc_init (filename)
const char *filename;
{
filename = c_objc_common_init (filename);
- add_objc_tree_codes ();
-
- decl_printable_name = objc_printable_name;
+ if (filename == NULL)
+ return filename;
/* Force the line number back to 0; check_newline will have
raised it to 1, which will make the builtin functions appear
@@ -557,8 +477,6 @@ objc_init (filename)
if (print_struct_values)
generate_struct_by_value_array ();
- objc_act_parse_init ();
-
return filename;
}
@@ -567,52 +485,14 @@ finish_file ()
{
c_objc_common_finish_file ();
- finish_objc (); /* Objective-C finalization */
+ /* Finalize Objective-C runtime data. No need to generate tables
+ and code if only checking syntax. */
+ if (!flag_syntax_only)
+ finish_objc ();
if (gen_declaration_file)
fclose (gen_declaration_file);
}
-
-int
-objc_decode_option (argc, argv)
- int argc;
- char **argv;
-{
- const char *p = argv[0];
-
- if (!strcmp (p, "-gen-decls"))
- flag_gen_declaration = 1;
- else if (!strcmp (p, "-Wselector"))
- warn_selector = 1;
- else if (!strcmp (p, "-Wno-selector"))
- warn_selector = 0;
- else if (!strcmp (p, "-Wprotocol"))
- flag_warn_protocol = 1;
- else if (!strcmp (p, "-Wno-protocol"))
- flag_warn_protocol = 0;
- else if (!strcmp (p, "-fgnu-runtime"))
- flag_next_runtime = 0;
- else if (!strcmp (p, "-fno-next-runtime"))
- flag_next_runtime = 0;
- else if (!strcmp (p, "-fno-gnu-runtime"))
- flag_next_runtime = 1;
- else if (!strcmp (p, "-fnext-runtime"))
- flag_next_runtime = 1;
- else if (!strcmp (p, "-print-objc-runtime-info"))
- print_struct_values = 1;
-#define CSTSTRCLASS "-fconstant-string-class="
- else if (!strncmp (p, CSTSTRCLASS, sizeof(CSTSTRCLASS) - 2)) {
- if (strlen (argv[0]) <= strlen (CSTSTRCLASS))
- error ("no class name specified as argument to -fconstant-string-class");
- constant_string_class_name = xstrdup(argv[0] + sizeof(CSTSTRCLASS) - 1);
- }
-#undef CSTSTRCLASS
- else
- return c_decode_option (argc, argv);
-
- return 1;
-}
-
static tree
define_decl (declarator, declspecs)
@@ -636,14 +516,6 @@ define_decl (declarator, declspecs)
`a' and `b' are the same class type, or
`a' and `b' are of class types A and B such that B is a descendant of A. */
-int
-maybe_objc_comptypes (lhs, rhs, reflexive)
- tree lhs, rhs;
- int reflexive;
-{
- return objc_comptypes (lhs, rhs, reflexive);
-}
-
static tree
lookup_method_in_protocol_list (rproto_list, sel_name, class_meth)
tree rproto_list;
@@ -715,10 +587,24 @@ lookup_protocol_in_reflist (rproto_list, lproto)
return 0;
}
-/* Return 1 if LHS and RHS are compatible types for assignment
- or various other operations. Return 0 if they are incompatible,
- and return -1 if we choose to not decide. When the operation
- is REFLEXIVE, check for compatibility in either direction. */
+/* Return 1 if LHS and RHS are compatible types for assignment or
+ various other operations. Return 0 if they are incompatible, and
+ return -1 if we choose to not decide (because the types are really
+ just C types, not ObjC specific ones). When the operation is
+ REFLEXIVE (typically comparisons), check for compatibility in
+ either direction; when it's not (typically assignments), don't.
+
+ This function is called in two cases: when both lhs and rhs are
+ pointers to records (in which case we check protocols too), and
+ when both lhs and rhs are records (in which case we check class
+ inheritance only).
+
+ Warnings about classes/protocols not implementing a protocol are
+ emitted here (multiple of those warnings might be emitted for a
+ single line!); generic warnings about incompatible assignments and
+ lacks of casts in comparisons are/must be emitted by the caller if
+ we return 0.
+*/
int
objc_comptypes (lhs, rhs, reflexive)
@@ -728,6 +614,8 @@ objc_comptypes (lhs, rhs, reflexive)
{
/* New clause for protocols. */
+ /* Here we manage the case of a POINTER_TYPE = POINTER_TYPE. We only
+ manage the ObjC ones, and leave the rest to the C code. */
if (TREE_CODE (lhs) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (lhs)) == RECORD_TYPE
&& TREE_CODE (rhs) == POINTER_TYPE
@@ -742,29 +630,75 @@ objc_comptypes (lhs, rhs, reflexive)
tree rproto, rproto_list;
tree p;
+ /* <Protocol> = <Protocol> */
if (rhs_is_proto)
{
rproto_list = TYPE_PROTOCOL_LIST (rhs);
-
- /* Make sure the protocol is supported by the object
- on the rhs. */
- for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
+
+ if (!reflexive)
{
- p = TREE_VALUE (lproto);
- rproto = lookup_protocol_in_reflist (rproto_list, p);
+ /* An assignment between objects of type 'id
+ <Protocol>'; make sure the protocol on the lhs is
+ supported by the object on the rhs. */
+ for (lproto = lproto_list; lproto;
+ lproto = TREE_CHAIN (lproto))
+ {
+ p = TREE_VALUE (lproto);
+ rproto = lookup_protocol_in_reflist (rproto_list, p);
- if (!rproto)
- warning ("object does not conform to the `%s' protocol",
- IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
+ if (!rproto)
+ warning
+ ("object does not conform to the `%s' protocol",
+ IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
+ }
+ return 1;
+ }
+ else
+ {
+ /* Obscure case - a comparison between two objects
+ of type 'id <Protocol>'. Check that either the
+ protocol on the lhs is supported by the object on
+ the rhs, or viceversa. */
+
+ /* Check if the protocol on the lhs is supported by the
+ object on the rhs. */
+ for (lproto = lproto_list; lproto;
+ lproto = TREE_CHAIN (lproto))
+ {
+ p = TREE_VALUE (lproto);
+ rproto = lookup_protocol_in_reflist (rproto_list, p);
+
+ if (!rproto)
+ {
+ /* Check failed - check if the protocol on the rhs
+ is supported by the object on the lhs. */
+ for (rproto = rproto_list; rproto;
+ rproto = TREE_CHAIN (rproto))
+ {
+ p = TREE_VALUE (rproto);
+ lproto = lookup_protocol_in_reflist (lproto_list,
+ p);
+
+ if (!lproto)
+ {
+ /* This check failed too: incompatible */
+ return 0;
+ }
+ }
+ return 1;
+ }
+ }
+ return 1;
}
}
+ /* <Protocol> = <class> * */
else if (TYPED_OBJECT (TREE_TYPE (rhs)))
{
tree rname = TYPE_NAME (TREE_TYPE (rhs));
tree rinter;
- /* Make sure the protocol is supported by the object
- on the rhs. */
+ /* Make sure the protocol is supported by the object on
+ the rhs. */
for (lproto = lproto_list; lproto; lproto = TREE_CHAIN (lproto))
{
p = TREE_VALUE (lproto);
@@ -776,13 +710,16 @@ objc_comptypes (lhs, rhs, reflexive)
tree cat;
rproto_list = CLASS_PROTOCOL_LIST (rinter);
- /* If the underlying ObjC class does not have
- protocols attached to it, perhaps there are
- "one-off" protocols attached to the rhs?
- E.g., 'id<MyProt> foo;'. */
- if (!rproto_list)
- rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
rproto = lookup_protocol_in_reflist (rproto_list, p);
+ /* If the underlying ObjC class does not have
+ the protocol we're looking for, check for "one-off"
+ protocols (e.g., `NSObject<MyProt> *foo;') attached
+ to the rhs. */
+ if (!rproto)
+ {
+ rproto_list = TYPE_PROTOCOL_LIST (TREE_TYPE (rhs));
+ rproto = lookup_protocol_in_reflist (rproto_list, p);
+ }
/* Check for protocols adopted by categories. */
cat = CLASS_CATEGORY_LIST (rinter);
@@ -790,7 +727,6 @@ objc_comptypes (lhs, rhs, reflexive)
{
rproto_list = CLASS_PROTOCOL_LIST (cat);
rproto = lookup_protocol_in_reflist (rproto_list, p);
-
cat = CLASS_CATEGORY_LIST (cat);
}
@@ -799,31 +735,127 @@ objc_comptypes (lhs, rhs, reflexive)
if (!rproto)
warning ("class `%s' does not implement the `%s' protocol",
- IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
- IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
+ IDENTIFIER_POINTER (TYPE_NAME (TREE_TYPE (rhs))),
+ IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
}
+ return 1;
}
-
- /* May change...based on whether there was any mismatch */
- return 1;
+ /* <Protocol> = id */
+ else if (TYPE_NAME (TREE_TYPE (rhs)) == objc_object_id)
+ {
+ return 1;
+ }
+ /* <Protocol> = Class */
+ else if (TYPE_NAME (TREE_TYPE (rhs)) == objc_class_id)
+ {
+ return 0;
+ }
+ /* <Protocol> = ?? : let comptypes decide. */
+ return -1;
}
else if (rhs_is_proto)
- /* Lhs is not a protocol...warn if it is statically typed */
- return (TYPED_OBJECT (TREE_TYPE (lhs)) != 0);
+ {
+ /* <class> * = <Protocol> */
+ if (TYPED_OBJECT (TREE_TYPE (lhs)))
+ {
+ if (reflexive)
+ {
+ tree rname = TYPE_NAME (TREE_TYPE (lhs));
+ tree rinter;
+ tree rproto, rproto_list = TYPE_PROTOCOL_LIST (rhs);
+
+ /* Make sure the protocol is supported by the object on
+ the lhs. */
+ for (rproto = rproto_list; rproto;
+ rproto = TREE_CHAIN (rproto))
+ {
+ tree p = TREE_VALUE (rproto);
+ tree lproto = 0;
+ rinter = lookup_interface (rname);
+ while (rinter && !lproto)
+ {
+ tree cat;
+
+ tree lproto_list = CLASS_PROTOCOL_LIST (rinter);
+ lproto = lookup_protocol_in_reflist (lproto_list, p);
+ /* If the underlying ObjC class does not
+ have the protocol we're looking for,
+ check for "one-off" protocols (e.g.,
+ `NSObject<MyProt> *foo;') attached to the
+ lhs. */
+ if (!lproto)
+ {
+ lproto_list = TYPE_PROTOCOL_LIST
+ (TREE_TYPE (lhs));
+ lproto = lookup_protocol_in_reflist
+ (lproto_list, p);
+ }
+
+ /* Check for protocols adopted by categories. */
+ cat = CLASS_CATEGORY_LIST (rinter);
+ while (cat && !lproto)
+ {
+ lproto_list = CLASS_PROTOCOL_LIST (cat);
+ lproto = lookup_protocol_in_reflist (lproto_list,
+ p);
+ cat = CLASS_CATEGORY_LIST (cat);
+ }
+
+ rinter = lookup_interface (CLASS_SUPER_NAME
+ (rinter));
+ }
+
+ if (!lproto)
+ warning ("class `%s' does not implement the `%s' protocol",
+ IDENTIFIER_POINTER (TYPE_NAME
+ (TREE_TYPE (lhs))),
+ IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
+ }
+ return 1;
+ }
+ else
+ return 0;
+ }
+ /* id = <Protocol> */
+ else if (TYPE_NAME (TREE_TYPE (lhs)) == objc_object_id)
+ {
+ return 1;
+ }
+ /* Class = <Protocol> */
+ else if (TYPE_NAME (TREE_TYPE (lhs)) == objc_class_id)
+ {
+ return 0;
+ }
+ /* ??? = <Protocol> : let comptypes decide */
+ else
+ {
+ return -1;
+ }
+ }
else
- /* Defer to comptypes. */
- return -1;
+ {
+ /* Attention: we shouldn't defer to comptypes here. One bad
+ side effect would be that we might loose the REFLEXIVE
+ information.
+ */
+ lhs = TREE_TYPE (lhs);
+ rhs = TREE_TYPE (rhs);
+ }
}
- else if (TREE_CODE (lhs) == RECORD_TYPE && TREE_CODE (rhs) == RECORD_TYPE)
- ; /* Fall thru. This is the case we have been handling all along */
- else
- /* Defer to comptypes. */
- return -1;
-
- /* `id' = `<class> *', `<class> *' = `id' */
+ if (TREE_CODE (lhs) != RECORD_TYPE || TREE_CODE (rhs) != RECORD_TYPE)
+ {
+ /* Nothing to do with ObjC - let immediately comptypes take
+ responsibility for checking. */
+ return -1;
+ }
+ /* `id' = `<class> *' `<class> *' = `id': always allow it.
+ Please note that
+ 'Object *o = [[Object alloc] init]; falls
+ in the case <class> * = `id'.
+ */
if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
|| (TYPE_NAME (rhs) == objc_object_id && TYPED_OBJECT (lhs)))
return 1;
@@ -864,7 +896,7 @@ objc_comptypes (lhs, rhs, reflexive)
return 0;
}
else
- /* Defer to comptypes. */
+ /* Not an ObjC type - let comptypes do the check. */
return -1;
}
@@ -882,13 +914,6 @@ objc_check_decl (decl)
error_with_decl (decl, "`%s' cannot be statically allocated");
}
-void
-maybe_objc_check_decl (decl)
- tree decl;
-{
- objc_check_decl (decl);
-}
-
/* Implement static typing. At this point, we know we have an interface. */
tree
@@ -903,7 +928,6 @@ get_static_reference (interface, protocols)
tree t, m = TYPE_MAIN_VARIANT (type);
t = copy_node (type);
- TYPE_BINFO (t) = make_tree_vec (2);
/* Add this type to the chain of variants of TYPE. */
TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
@@ -954,7 +978,6 @@ get_object_reference (protocols)
tree t, m = TYPE_MAIN_VARIANT (type);
t = copy_node (type);
- TYPE_BINFO (t) = make_tree_vec (2);
/* Add this type to the chain of variants of TYPE. */
TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
@@ -1131,14 +1154,12 @@ synth_module_prologue ()
DECL_INLINE (umsg_decl) = 1;
DECL_ARTIFICIAL (umsg_decl) = 1;
- if (flag_traditional && TAG_MSGSEND[0] != '_')
- DECL_BUILT_IN_NONANSI (umsg_decl) = 1;
-
make_decl_rtl (umsg_decl, NULL);
pushdecl (umsg_decl);
}
else
- umsg_decl = builtin_function (TAG_MSGSEND, temp_type, 0, NOT_BUILT_IN, 0);
+ umsg_decl = builtin_function (TAG_MSGSEND, temp_type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
/* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
@@ -1149,7 +1170,8 @@ synth_module_prologue ()
NULL_TREE)));
umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
- temp_type, 0, NOT_BUILT_IN, 0);
+ temp_type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
/* id objc_getClass (const char *); */
@@ -1160,12 +1182,14 @@ synth_module_prologue ()
NULL_TREE)));
objc_get_class_decl
- = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN, 0);
+ = builtin_function (TAG_GETCLASS, temp_type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
/* id objc_getMetaClass (const char *); */
objc_get_meta_class_decl
- = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN, 0);
+ = builtin_function (TAG_GETMETACLASS, temp_type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
/* static SEL _OBJC_SELECTOR_TABLE[]; */
@@ -1176,7 +1200,7 @@ synth_module_prologue ()
/* Suppress outputting debug symbols, because
dbxout_init hasn'r been called yet. */
enum debug_info_type save_write_symbols = write_symbols;
- struct gcc_debug_hooks *save_hooks = debug_hooks;
+ const struct gcc_debug_hooks *const save_hooks = debug_hooks;
write_symbols = NO_DEBUG;
debug_hooks = &do_nothing_debug_hooks;
@@ -1243,21 +1267,7 @@ my_build_string (len, str)
int len;
const char *str;
{
- int wide_flag = 0;
- tree a_string = build_string (len, str);
-
- /* Some code from combine_strings, which is local to c-parse.y. */
- if (TREE_TYPE (a_string) == int_array_type_node)
- wide_flag = 1;
-
- TREE_TYPE (a_string)
- = build_array_type (wide_flag ? integer_type_node : char_type_node,
- build_index_type (build_int_2 (len - 1, 0)));
-
- TREE_CONSTANT (a_string) = 1; /* Puts string in the readonly segment */
- TREE_STATIC (a_string) = 1;
-
- return a_string;
+ return fix_string_type (build_string (len, str));
}
/* Given a chain of STRING_CST's, build a static instance of
@@ -1283,7 +1293,21 @@ build_objc_string_object (strings)
add_class_reference (constant_string_id);
- string = combine_strings (strings);
+ if (TREE_CHAIN (strings))
+ {
+ varray_type vstrings;
+ VARRAY_TREE_INIT (vstrings, 32, "strings");
+
+ for (; strings ; strings = TREE_CHAIN (strings))
+ VARRAY_PUSH_TREE (vstrings, strings);
+
+ string = combine_strings (vstrings);
+ }
+ else
+ string = strings;
+
+ string = fix_string_type (string);
+
TREE_SET_CODE (string, STRING_CST);
length = TREE_STRING_LENGTH (string) - 1;
@@ -1390,7 +1414,7 @@ build_constructor (type, elts)
else
{
f = TYPE_FIELDS (type);
- for (e = elts; e ; e = TREE_CHAIN (e), f = TREE_CHAIN (f))
+ for (e = elts; e && f; e = TREE_CHAIN (e), f = TREE_CHAIN (f))
if (TREE_CODE (TREE_TYPE (f)) == POINTER_TYPE
|| TREE_CODE (TREE_TYPE (f)) == INTEGER_TYPE)
TREE_VALUE (e) = convert (TREE_TYPE (f), TREE_VALUE (e));
@@ -1813,7 +1837,7 @@ get_objc_string_decl (ident, section)
else
abort ();
- for (; chain != 0; chain = TREE_VALUE (chain))
+ for (; chain != 0; chain = TREE_CHAIN (chain))
if (TREE_VALUE (chain) == ident)
return (TREE_PURPOSE (chain));
@@ -2003,6 +2027,32 @@ build_selector_translation_table ()
{
tree expr;
+ if (warn_selector && objc_implementation_context)
+ {
+ tree method_chain;
+ bool found = false;
+ for (method_chain = meth_var_names_chain;
+ method_chain;
+ method_chain = TREE_CHAIN (method_chain))
+ {
+ if (TREE_VALUE (method_chain) == TREE_VALUE (chain))
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ /* Adjust line number for warning message. */
+ int save_lineno = lineno;
+ if (flag_next_runtime && TREE_PURPOSE (chain))
+ lineno = DECL_SOURCE_LINE (TREE_PURPOSE (chain));
+ warning ("creating selector for non existant method %s",
+ IDENTIFIER_POINTER (TREE_VALUE (chain)));
+ lineno = save_lineno;
+ }
+ }
+
expr = build_selector (TREE_VALUE (chain));
if (flag_next_runtime)
@@ -2086,8 +2136,8 @@ get_proto_encoding (proto)
identifier_node that represent the selector. */
static tree
-build_typed_selector_reference (ident, proto)
- tree ident, proto;
+build_typed_selector_reference (ident, prototype)
+ tree ident, prototype;
{
tree *chain = &sel_ref_chain;
tree expr;
@@ -2095,14 +2145,14 @@ build_typed_selector_reference (ident, proto)
while (*chain)
{
- if (TREE_PURPOSE (*chain) == ident && TREE_VALUE (*chain) == proto)
+ if (TREE_PURPOSE (*chain) == prototype && TREE_VALUE (*chain) == ident)
goto return_at_index;
index++;
chain = &TREE_CHAIN (*chain);
}
- *chain = tree_cons (proto, ident, NULL_TREE);
+ *chain = tree_cons (prototype, ident, NULL_TREE);
return_at_index:
expr = build_unary_op (ADDR_EXPR,
@@ -2370,6 +2420,17 @@ is_class_name (ident)
}
tree
+objc_is_id (ident)
+ tree ident;
+{
+ /* NB: This function may be called before the ObjC front-end
+ has been initialized, in which case ID_TYPE will be NULL. */
+ return (id_type && ident && TYPE_P (ident) && IS_ID (ident))
+ ? id_type
+ : NULL_TREE;
+}
+
+tree
lookup_interface (ident)
tree ident;
{
@@ -2383,51 +2444,23 @@ lookup_interface (ident)
return NULL_TREE;
}
-static tree
-objc_copy_list (list, head)
- tree list;
- tree *head;
-{
- tree newlist = NULL_TREE, tail = NULL_TREE;
-
- while (list)
- {
- tail = copy_node (list);
-
- /* The following statement fixes a bug when inheriting instance
- variables that are declared to be bitfields. finish_struct
- expects to find the width of the bitfield in DECL_INITIAL. */
- if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
- DECL_INITIAL (tail) = DECL_SIZE (tail);
-
- newlist = chainon (newlist, tail);
- list = TREE_CHAIN (list);
- }
-
- *head = newlist;
- return tail;
-}
-
-/* Used by: build_private_template, get_class_ivars, and
- continue_class. COPY is 1 when called from @defs. In this case
- copy all fields. Otherwise don't copy leaf ivars since we rely on
- them being side-effected exactly once by finish_struct. */
+/* Used by: build_private_template, continue_class,
+ and for @defs constructs. */
-static tree
-build_ivar_chain (interface, copy)
+tree
+get_class_ivars (interface)
tree interface;
- int copy;
{
tree my_name, super_name, ivar_chain;
my_name = CLASS_NAME (interface);
super_name = CLASS_SUPER_NAME (interface);
+ ivar_chain = CLASS_IVARS (interface);
- /* Possibly copy leaf ivars. */
- if (copy)
- objc_copy_list (CLASS_IVARS (interface), &ivar_chain);
- else
- ivar_chain = CLASS_IVARS (interface);
+ /* Save off a pristine copy of the leaf ivars (i.e, those not
+ inherited from a super class). */
+ if (!CLASS_OWN_IVARS (interface))
+ CLASS_OWN_IVARS (interface) = copy_list (ivar_chain);
while (super_name)
{
@@ -2451,14 +2484,14 @@ build_ivar_chain (interface, copy)
my_name = CLASS_NAME (interface);
super_name = CLASS_SUPER_NAME (interface);
- op1 = CLASS_IVARS (interface);
+ op1 = CLASS_OWN_IVARS (interface);
if (op1)
{
- tree head, tail = objc_copy_list (op1, &head);
+ tree head = copy_list (op1);
/* Prepend super class ivars...make a copy of the list, we
do not want to alter the original. */
- TREE_CHAIN (tail) = ivar_chain;
+ chainon (head, ivar_chain);
ivar_chain = head;
}
}
@@ -2485,7 +2518,7 @@ build_private_template (class)
{
uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
- ivar_context = build_ivar_chain (class, 0);
+ ivar_context = get_class_ivars (class);
finish_struct (uprivate_record, ivar_context, NULL_TREE);
@@ -3003,6 +3036,43 @@ generate_protocol_references (plist)
}
}
+/* For each protocol which was referenced either from a @protocol()
+ expression, or because a class/category implements it (then a
+ pointer to the protocol is stored in the struct describing the
+ class/category), we create a statically allocated instance of the
+ Protocol class. The code is written in such a way as to generate
+ as few Protocol objects as possible; we generate a unique Protocol
+ instance for each protocol, and we don't generate a Protocol
+ instance if the protocol is never referenced (either from a
+ @protocol() or from a class/category implementation). These
+ statically allocated objects can be referred to via the static
+ (that is, private to this module) symbols _OBJC_PROTOCOL_n.
+
+ The statically allocated Protocol objects that we generate here
+ need to be fixed up at runtime in order to be used: the 'isa'
+ pointer of the objects need to be set up to point to the 'Protocol'
+ class, as known at runtime.
+
+ The NeXT runtime fixes up all protocols at program startup time,
+ before main() is entered. It uses a low-level trick to look up all
+ those symbols, then loops on them and fixes them up.
+
+ The GNU runtime as well fixes up all protocols before user code
+ from the module is executed; it requires pointers to those symbols
+ to be put in the objc_symtab (which is then passed as argument to
+ the function __objc_exec_class() which the compiler sets up to be
+ executed automatically when the module is loaded); setup of those
+ Protocol objects happen in two ways in the GNU runtime: all
+ Protocol objects referred to by a class or category implementation
+ are fixed up when the class/category is loaded; all Protocol
+ objects referred to by a @protocol() expression are added by the
+ compiler to the list of statically allocated instances to fixup
+ (the same list holding the statically allocated constant string
+ objects). Because, as explained above, the compiler generates as
+ few Protocol objects as possible, some Protocol object might end up
+ being referenced multiple times when compiled with the GNU runtime,
+ and end up being fixed up multiple times at runtime inizialization.
+ But that doesn't hurt, it's just a little inefficient. */
static void
generate_protocols ()
{
@@ -3464,9 +3534,9 @@ error_with_ivar (message, decl, rawdecl)
tree decl;
tree rawdecl;
{
- count_error (0);
+ diagnostic_count_diagnostic (global_dc, DK_ERROR);
- report_error_function (DECL_SOURCE_FILE (decl));
+ diagnostic_report_current_function (global_dc);
error_with_file_and_line (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl),
@@ -3475,10 +3545,6 @@ error_with_ivar (message, decl, rawdecl)
}
-#define USERTYPE(t) \
- (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE \
- || TREE_CODE (t) == ENUMERAL_TYPE)
-
static void
check_ivars (inter, imp)
tree inter;
@@ -4508,6 +4574,10 @@ adjust_type_for_id_default (type)
chain;
chain = TREE_CHAIN (chain))
{
+ if (TYPED_OBJECT (TREE_VALUE (chain))
+ && !(TREE_VALUE (type)
+ && TREE_CODE (TREE_VALUE (type)) == INDIRECT_REF))
+ error ("can not use an object as parameter to a method\n");
if (!is_objc_type_qualifier (TREE_VALUE (chain)))
return type;
}
@@ -4778,12 +4848,12 @@ receiver_is_class_object (receiver)
the identifier of the selector of the message. This is
used when printing warnings about argument mismatches. */
-static tree building_objc_message_expr = 0;
+static tree current_objc_message_selector = 0;
tree
-maybe_building_objc_message_expr ()
+objc_message_selector ()
{
- return building_objc_message_expr;
+ return current_objc_message_selector;
}
/* Construct an expression for sending a message.
@@ -4924,7 +4994,7 @@ finish_message_expr (receiver, sel_name, method_params)
if (iface)
method_prototype = lookup_instance_method_static (iface, sel_name);
- if (! method_prototype && TYPE_PROTOCOL_LIST (ctype))
+ if (! method_prototype && ctype && TYPE_PROTOCOL_LIST (ctype))
method_prototype
= lookup_method_in_protocol_list (TYPE_PROTOCOL_LIST (ctype),
sel_name, 0);
@@ -5059,7 +5129,7 @@ finish_message_expr (receiver, sel_name, method_params)
}
/* Save the selector name for printing error messages. */
- building_objc_message_expr = sel_name;
+ current_objc_message_selector = sel_name;
/* Build the parameters list for looking up the method.
These are the object itself and the selector. */
@@ -5073,7 +5143,7 @@ finish_message_expr (receiver, sel_name, method_params)
receiver, self_object,
selector, method_params);
- building_objc_message_expr = 0;
+ current_objc_message_selector = 0;
return retval;
}
@@ -5217,6 +5287,8 @@ build_protocol_reference (p)
PROTOCOL_FORWARD_DECL (p) = decl;
}
+/* This function is called by the parser when (and only when) a
+ @protocol() expression is found, in order to compile it. */
tree
build_protocol_expr (protoname)
tree protoname;
@@ -5238,9 +5310,56 @@ build_protocol_expr (protoname)
TREE_TYPE (expr) = protocol_type;
+ /* The @protocol() expression is being compiled into a pointer to a
+ statically allocated instance of the Protocol class. To become
+ usable at runtime, the 'isa' pointer of the instance need to be
+ fixed up at runtime by the runtime library, to point to the
+ actual 'Protocol' class. */
+
+ /* For the GNU runtime, put the static Protocol instance in the list
+ of statically allocated instances, so that we make sure that its
+ 'isa' pointer is fixed up at runtime by the GNU runtime library
+ to point to the Protocol class (at runtime, when loading the
+ module, the GNU runtime library loops on the statically allocated
+ instances (as found in the defs field in objc_symtab) and fixups
+ all the 'isa' pointers of those objects). */
+ if (! flag_next_runtime)
+ {
+ /* This type is a struct containing the fields of a Protocol
+ object. (Cfr. protocol_type instead is the type of a pointer
+ to such a struct). */
+ tree protocol_struct_type = xref_tag
+ (RECORD_TYPE, get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
+ tree *chain;
+
+ /* Look for the list of Protocol statically allocated instances
+ to fixup at runtime. Create a new list to hold Protocol
+ statically allocated instances, if the list is not found. At
+ present there is only another list, holding NSConstantString
+ static instances to be fixed up at runtime. */
+ for (chain = &objc_static_instances;
+ *chain && TREE_VALUE (*chain) != protocol_struct_type;
+ chain = &TREE_CHAIN (*chain));
+ if (!*chain)
+ {
+ *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
+ add_objc_string (TYPE_NAME (protocol_struct_type),
+ class_names);
+ }
+
+ /* Add this statically allocated instance to the Protocol list. */
+ TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
+ PROTOCOL_FORWARD_DECL (p),
+ TREE_PURPOSE (*chain));
+ }
+
+
return expr;
}
+/* This function is called by the parser when a @selector() expression
+ is found, in order to compile it. It is only called by the parser
+ and only to compile a @selector(). */
tree
build_selector_expr (selnamelist)
tree selnamelist;
@@ -5256,6 +5375,32 @@ build_selector_expr (selnamelist)
else
abort ();
+ /* If we are required to check @selector() expressions as they
+ are found, check that the selector has been declared. */
+ if (warn_undeclared_selector)
+ {
+ /* Look the selector up in the list of all known class and
+ instance methods (up to this line) to check that the selector
+ exists. */
+ hash hsh;
+
+ /* First try with instance methods. */
+ hsh = hash_lookup (nst_method_hash_list, selname);
+
+ /* If not found, try with class methods. */
+ if (!hsh)
+ {
+ hsh = hash_lookup (cls_method_hash_list, selname);
+ }
+
+ /* If still not found, print out a warning. */
+ if (!hsh)
+ {
+ warning ("undeclared selector `%s'", IDENTIFIER_POINTER (selname));
+ }
+ }
+
+
if (flag_typed_selectors)
return build_typed_selector_reference (selname, 0);
else
@@ -5321,8 +5466,8 @@ hash_func (sel_name)
static void
hash_init ()
{
- nst_method_hash_list = (hash *) xcalloc (SIZEHASHTABLE, sizeof (hash));
- cls_method_hash_list = (hash *) xcalloc (SIZEHASHTABLE, sizeof (hash));
+ nst_method_hash_list = (hash *) ggc_calloc (SIZEHASHTABLE, sizeof (hash));
+ cls_method_hash_list = (hash *) ggc_calloc (SIZEHASHTABLE, sizeof (hash));
}
/* WARNING!!!! hash_enter is called with a method, and will peek
@@ -5335,18 +5480,10 @@ hash_enter (hashlist, method)
hash *hashlist;
tree method;
{
- static hash hash_alloc_list = 0;
- static int hash_alloc_index = 0;
hash obj;
int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
- if (! hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
- {
- hash_alloc_index = 0;
- hash_alloc_list = (hash) xmalloc (sizeof (struct hashed_entry)
- * HASH_ALLOC_LIST_SIZE);
- }
- obj = &hash_alloc_list[hash_alloc_index++];
+ obj = (hash) ggc_alloc (sizeof (struct hashed_entry));
obj->list = 0;
obj->next = hashlist[slot];
obj->key = method;
@@ -5378,17 +5515,9 @@ hash_add_attr (entry, value)
hash entry;
tree value;
{
- static attr attr_alloc_list = 0;
- static int attr_alloc_index = 0;
attr obj;
- if (! attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
- {
- attr_alloc_index = 0;
- attr_alloc_list = (attr) xmalloc (sizeof (struct hashed_attribute)
- * ATTR_ALLOC_LIST_SIZE);
- }
- obj = &attr_alloc_list[attr_alloc_index++];
+ obj = (attr) ggc_alloc (sizeof (struct hashed_attribute));
obj->next = entry->list;
obj->value = value;
@@ -5411,6 +5540,7 @@ lookup_method (mchain, method)
{
if (METHOD_SEL_NAME (mchain) == key)
return mchain;
+
mchain = TREE_CHAIN (mchain);
}
return NULL_TREE;
@@ -5782,18 +5912,6 @@ is_public (expr, identifier)
return 1;
}
-
-/* Implement @defs (<classname>) within struct bodies. */
-
-tree
-get_class_ivars (interface)
- tree interface;
-{
- /* Make sure we copy the leaf ivars in case @defs is used in a local
- context. Otherwise finish_struct will overwrite the layout info
- using temporary storage. */
- return build_ivar_chain (interface, 1);
-}
/* Make sure all entries in CHAIN are also in LIST. */
@@ -5940,7 +6058,7 @@ check_protocol (p, type, name)
int f1, f2;
/* Ensure that all protocols have bodies! */
- if (flag_warn_protocol)
+ if (warn_protocol)
{
f1 = check_methods (PROTOCOL_CLS_METHODS (p),
CLASS_CLS_METHODS (objc_implementation_context),
@@ -6025,7 +6143,7 @@ start_class (code, class_name, super_name, protocol_list)
}
class = make_node (code);
- TYPE_BINFO (class) = make_tree_vec (5);
+ TYPE_BINFO (class) = make_tree_vec (6);
CLASS_NAME (class) = class_name;
CLASS_SUPER_NAME (class) = super_name;
@@ -6189,7 +6307,7 @@ continue_class (class)
if (!objc_class_template)
build_class_template ();
- imp_entry = (struct imp_entry *) xmalloc (sizeof (struct imp_entry));
+ imp_entry = (struct imp_entry *) ggc_alloc (sizeof (struct imp_entry));
imp_entry->next = imp_list;
imp_entry->imp_context = class;
@@ -6215,7 +6333,7 @@ continue_class (class)
if (!TYPE_FIELDS (record))
{
- finish_struct (record, build_ivar_chain (class, 0), NULL_TREE);
+ finish_struct (record, get_class_ivars (class), NULL_TREE);
CLASS_STATIC_TEMPLATE (class) = record;
/* Mark this record as a class template for static typing. */
@@ -6766,7 +6884,10 @@ encode_type (type, curtype, format)
}
static void
-encode_complete_bitfield (int position, tree type, int size)
+encode_complete_bitfield (position, type, size)
+ int position;
+ tree type;
+ int size;
{
enum tree_code code = TREE_CODE (type);
char buffer[40];
@@ -6836,14 +6957,14 @@ encode_field_decl (field_decl, curtype, format)
the bitfield typing information. */
if (flag_next_runtime)
{
- if (DECL_BIT_FIELD (field_decl))
+ if (DECL_BIT_FIELD_TYPE (field_decl))
encode_bitfield (tree_low_cst (DECL_SIZE (field_decl), 1));
else
encode_type (TREE_TYPE (field_decl), curtype, format);
}
else
{
- if (DECL_BIT_FIELD (field_decl))
+ if (DECL_BIT_FIELD_TYPE (field_decl))
encode_complete_bitfield (int_bit_position (field_decl),
DECL_BIT_FIELD_TYPE (field_decl),
tree_low_cst (DECL_SIZE (field_decl), 1));
@@ -6959,10 +7080,10 @@ warn_with_method (message, mtype, method)
int mtype;
tree method;
{
- if (count_error (1) == 0)
+ if (!diagnostic_count_diagnostic (global_dc, DK_WARNING))
return;
- report_error_function (DECL_SOURCE_FILE (method));
+ diagnostic_report_current_function (global_dc);
/* Add a readable method name to the warning. */
warning_with_file_and_line (DECL_SOURCE_FILE (method),
@@ -7203,9 +7324,13 @@ get_super_receiver ()
{
super_class = get_class_reference (super_name);
if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
+ /* Cast the super class to 'id', since the user may not have
+ included <objc/objc-class.h>, leaving 'struct objc_class'
+ an incomplete type. */
super_class
- = build_component_ref (build_indirect_ref (super_class, "->"),
- get_identifier ("isa"));
+ = build_component_ref (build_indirect_ref
+ (build_c_cast (id_type, super_class), "->"),
+ get_identifier ("isa"));
}
else
{
@@ -7963,12 +8088,21 @@ gen_method_decl (method, buf)
/* Debug info. */
+
+/* Dump an @interface declaration of the supplied class CHAIN to the
+ supplied file FP. Used to implement the -gen-decls option (which
+ prints out an @interface declaration of all classes compiled in
+ this run); potentially useful for debugging the compiler too. */
static void
dump_interface (fp, chain)
FILE *fp;
tree chain;
{
- char *buf = (char *) xmalloc (256);
+ /* FIXME: A heap overflow here whenever a method (or ivar)
+ declaration is so long that it doesn't fit in the buffer. The
+ code and all the related functions should be rewritten to avoid
+ using fixed size buffers. */
+ char *buf = (char *) xmalloc (1024 * 10);
const char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
tree ivar_decls = CLASS_RAW_IVARS (chain);
tree nst_methods = CLASS_NST_METHODS (chain);
@@ -7976,14 +8110,26 @@ dump_interface (fp, chain)
fprintf (fp, "\n@interface %s", my_name);
+ /* CLASS_SUPER_NAME is used to store the superclass name for
+ classes, and the category name for categories. */
if (CLASS_SUPER_NAME (chain))
{
- const char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
- fprintf (fp, " : %s\n", super_name);
+ const char *name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
+
+ if (TREE_CODE (chain) == CATEGORY_IMPLEMENTATION_TYPE
+ || TREE_CODE (chain) == CATEGORY_INTERFACE_TYPE)
+ {
+ fprintf (fp, " (%s)\n", name);
+ }
+ else
+ {
+ fprintf (fp, " : %s\n", name);
+ }
}
else
fprintf (fp, "\n");
+ /* FIXME - the following doesn't seem to work at the moment. */
if (ivar_decls)
{
fprintf (fp, "{\n");
@@ -8007,7 +8153,8 @@ dump_interface (fp, chain)
fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
cls_methods = TREE_CHAIN (cls_methods);
}
- fprintf (fp, "\n@end");
+
+ fprintf (fp, "@end\n");
}
/* Demangle function for Objective-C */
@@ -8067,7 +8214,7 @@ objc_demangle (mangled)
return mangled; /* not an objc mangled name */
}
-static const char *
+const char *
objc_printable_name (decl, kind)
tree decl;
int kind ATTRIBUTE_UNUSED;
@@ -8075,22 +8222,6 @@ objc_printable_name (decl, kind)
return objc_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)));
}
-/* Adds the tree codes specific to the ObjC/ObjC++ front end to the
- list of all tree codes. */
-
-static void
-add_objc_tree_codes ()
-{
- int add = (int) LAST_OBJC_TREE_CODE - (int) LAST_BASE_TREE_CODE;
-
- memcpy (tree_code_type + (int) LAST_BASE_TREE_CODE,
- objc_tree_code_type, add);
- memcpy (tree_code_length + (int) LAST_BASE_TREE_CODE,
- objc_tree_code_length, add * sizeof (int));
- memcpy (tree_code_name + (int) LAST_BASE_TREE_CODE,
- objc_tree_code_name, add * sizeof (char *));
-}
-
static void
init_objc ()
{
@@ -8143,7 +8274,16 @@ finish_objc ()
UOBJC_CLASS_decl = impent->class_decl;
UOBJC_METACLASS_decl = impent->meta_decl;
-
+
+ /* Dump the @interface of each class as we compile it, if the
+ -gen-decls option is in use. TODO: Dump the classes in the
+ order they were found, rather than in reverse order as we
+ are doing now. */
+ if (flag_gen_declaration)
+ {
+ dump_interface (gen_declaration_file, objc_implementation_context);
+ }
+
if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
{
/* all of the following reference the string pool... */
@@ -8194,12 +8334,6 @@ finish_objc ()
generate_strings ();
- if (flag_gen_declaration)
- {
- add_class (objc_implementation_context);
- dump_interface (gen_declaration_file, objc_implementation_context);
- }
-
if (warn_selector)
{
int slot;
@@ -8364,7 +8498,7 @@ handle_impent (impent)
tree decl, init;
init = build_int_2 (0, 0);
- TREE_TYPE (init) = type_for_size (BITS_PER_WORD, 1);
+ TREE_TYPE (init) = c_common_type_for_size (BITS_PER_WORD, 1);
decl = build_decl (VAR_DECL, get_identifier (string), TREE_TYPE (init));
TREE_PUBLIC (decl) = 1;
TREE_READONLY (decl) = 1;
@@ -8377,51 +8511,6 @@ handle_impent (impent)
}
}
-static void
-ggc_mark_imp_list (arg)
- void *arg;
-{
- struct imp_entry *impent;
-
- for (impent = *(struct imp_entry **)arg; impent; impent = impent->next)
- {
- ggc_mark_tree (impent->imp_context);
- ggc_mark_tree (impent->imp_template);
- ggc_mark_tree (impent->class_decl);
- ggc_mark_tree (impent->meta_decl);
- }
-}
-
-static void
-ggc_mark_hash_table (arg)
- void *arg;
-{
- hash *hash_table = *(hash **)arg;
- hash hst;
- attr list;
- int i;
-
- if (hash_table == NULL)
- return;
- for (i = 0; i < SIZEHASHTABLE; i++)
- for (hst = hash_table [i]; hst; hst = hst->next)
- {
- ggc_mark_tree (hst->key);
- for (list = hst->list; list; list = list->next)
- ggc_mark_tree (list->value);
- }
-}
-
-/* Add GC roots for variables local to this file. */
-static void
-objc_act_parse_init ()
-{
- ggc_add_tree_root (objc_global_trees, OCTI_MAX);
- ggc_add_root (&imp_list, 1, sizeof imp_list, ggc_mark_imp_list);
- ggc_add_root (&nst_method_hash_list, 1, sizeof nst_method_hash_list, ggc_mark_hash_table);
- ggc_add_root (&cls_method_hash_list, 1, sizeof cls_method_hash_list, ggc_mark_hash_table);
-}
-
/* Look up ID as an instance variable. */
tree
lookup_objc_ivar (id)
@@ -8429,8 +8518,8 @@ lookup_objc_ivar (id)
{
tree decl;
- if (objc_receiver_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
- /* we have a message to super */
+ if (objc_method_context && !strcmp (IDENTIFIER_POINTER (id), "super"))
+ /* We have a message to super. */
return get_super_receiver ();
else if (objc_method_context && (decl = is_ivar (objc_ivar_chain, id)))
{
@@ -8442,3 +8531,5 @@ lookup_objc_ivar (id)
else
return 0;
}
+
+#include "gtype-objc.h"
diff --git a/contrib/gcc/objc/objc-act.h b/contrib/gcc/objc/objc-act.h
index 72b8b3e..af10387 100644
--- a/contrib/gcc/objc/objc-act.h
+++ b/contrib/gcc/objc/objc-act.h
@@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA. */
/*** Public Interface (procedures) ***/
const char *objc_init PARAMS ((const char *));
-int objc_decode_option PARAMS ((int, char **));
+const char *objc_printable_name PARAMS ((tree, int));
/* used by yyparse */
@@ -63,8 +63,6 @@ void objc_declare_alias PARAMS ((tree, tree));
void objc_declare_class PARAMS ((tree));
void objc_declare_protocols PARAMS ((tree));
-extern int objc_receiver_context;
-
/* the following routines are used to implement statically typed objects */
int objc_comptypes PARAMS ((tree, tree, int));
@@ -99,6 +97,7 @@ tree build_encode_expr PARAMS ((tree));
#define CLASS_STATIC_TEMPLATE(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 2)
#define CLASS_CATEGORY_LIST(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 3)
#define CLASS_PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 4)
+#define CLASS_OWN_IVARS(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 5)
#define PROTOCOL_NAME(CLASS) ((CLASS)->type.name)
#define PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_BINFO (CLASS), 0)
#define PROTOCOL_NST_METHODS(CLASS) ((CLASS)->type.minval)
@@ -132,28 +131,26 @@ enum objc_tree_code {
typedef struct hashed_entry *hash;
typedef struct hashed_attribute *attr;
-struct hashed_attribute
+struct hashed_attribute GTY(())
{
attr next;
tree value;
};
-struct hashed_entry
+struct hashed_entry GTY(())
{
attr list;
hash next;
tree key;
};
-extern hash *nst_method_hash_list;
-extern hash *cls_method_hash_list;
+extern GTY ((length ("SIZEHASHTABLE"))) hash *nst_method_hash_list;
+extern GTY ((length ("SIZEHASHTABLE"))) hash *cls_method_hash_list;
-#define HASH_ALLOC_LIST_SIZE 170
-#define ATTR_ALLOC_LIST_SIZE 170
#define SIZEHASHTABLE 257
/* Objective-C/Objective-C++ @implementation list. */
-struct imp_entry
+struct imp_entry GTY(())
{
struct imp_entry *next;
tree imp_context;
@@ -162,7 +159,7 @@ struct imp_entry
tree meta_decl; /* _OBJC_METACLASS_<my_name>; */
};
-extern struct imp_entry *imp_list;
+extern GTY(()) struct imp_entry *imp_list;
extern int imp_count; /* `@implementation' */
extern int cat_count; /* `@category' */
@@ -247,7 +244,7 @@ enum objc_tree_index
OCTI_MAX
};
-extern tree objc_global_trees[OCTI_MAX];
+extern GTY(()) tree objc_global_trees[OCTI_MAX];
/* List of classes with list of their static instances. */
#define objc_static_instances objc_global_trees[OCTI_STATIC_NST]
diff --git a/contrib/gcc/objc/objc-lang.c b/contrib/gcc/objc/objc-lang.c
index 9effd14..73e6204 100644
--- a/contrib/gcc/objc/objc-lang.c
+++ b/contrib/gcc/objc/objc-lang.c
@@ -40,19 +40,49 @@ static void objc_init_options PARAMS ((void));
#undef LANG_HOOKS_INIT_OPTIONS
#define LANG_HOOKS_INIT_OPTIONS objc_init_options
#undef LANG_HOOKS_DECODE_OPTION
-#define LANG_HOOKS_DECODE_OPTION objc_decode_option
+#define LANG_HOOKS_DECODE_OPTION c_common_decode_option
#undef LANG_HOOKS_POST_OPTIONS
#define LANG_HOOKS_POST_OPTIONS c_common_post_options
#undef LANG_HOOKS_GET_ALIAS_SET
#define LANG_HOOKS_GET_ALIAS_SET c_common_get_alias_set
#undef LANG_HOOKS_SAFE_FROM_P
#define LANG_HOOKS_SAFE_FROM_P c_safe_from_p
+#undef LANG_HOOKS_PARSE_FILE
+#define LANG_HOOKS_PARSE_FILE c_common_parse_file
+#undef LANG_HOOKS_EXPAND_EXPR
+#define LANG_HOOKS_EXPAND_EXPR c_expand_expr
+#undef LANG_HOOKS_MARK_ADDRESSABLE
+#define LANG_HOOKS_MARK_ADDRESSABLE c_mark_addressable
+#undef LANG_HOOKS_TRUTHVALUE_CONVERSION
+#define LANG_HOOKS_TRUTHVALUE_CONVERSION c_common_truthvalue_conversion
+#undef LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES
+#define LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES c_insert_default_attributes
+#undef LANG_HOOKS_FINISH_INCOMPLETE_DECL
+#define LANG_HOOKS_FINISH_INCOMPLETE_DECL c_finish_incomplete_decl
+#undef LANG_HOOKS_UNSAFE_FOR_REEVAL
+#define LANG_HOOKS_UNSAFE_FOR_REEVAL c_common_unsafe_for_reeval
#undef LANG_HOOKS_STATICP
#define LANG_HOOKS_STATICP c_staticp
+#undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL
+#define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL c_dup_lang_specific_decl
#undef LANG_HOOKS_PRINT_IDENTIFIER
#define LANG_HOOKS_PRINT_IDENTIFIER c_print_identifier
-#undef LANG_HOOKS_SET_YYDEBUG
-#define LANG_HOOKS_SET_YYDEBUG c_set_yydebug
+#undef LANG_HOOKS_DECL_PRINTABLE_NAME
+#define LANG_HOOKS_DECL_PRINTABLE_NAME objc_printable_name
+#undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL
+#define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL c_warn_unused_global_decl
+
+#undef LANG_HOOKS_FUNCTION_ENTER_NESTED
+#define LANG_HOOKS_FUNCTION_ENTER_NESTED c_push_function_context
+#undef LANG_HOOKS_FUNCTION_LEAVE_NESTED
+#define LANG_HOOKS_FUNCTION_LEAVE_NESTED c_pop_function_context
+
+/* Attribute hooks. */
+#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
+#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
+#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table
+
/* Inlining hooks same as the C front end. */
#undef LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN
#define LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN \
@@ -67,11 +97,71 @@ static void objc_init_options PARAMS ((void));
#define LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
c_convert_parm_for_inlining
+#undef LANG_HOOKS_TYPE_FOR_MODE
+#define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode
+#undef LANG_HOOKS_TYPE_FOR_SIZE
+#define LANG_HOOKS_TYPE_FOR_SIZE c_common_type_for_size
+#undef LANG_HOOKS_SIGNED_TYPE
+#define LANG_HOOKS_SIGNED_TYPE c_common_signed_type
+#undef LANG_HOOKS_UNSIGNED_TYPE
+#define LANG_HOOKS_UNSIGNED_TYPE c_common_unsigned_type
+#undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
+#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE c_common_signed_or_unsigned_type
+#undef LANG_HOOKS_INCOMPLETE_TYPE_ERROR
+#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR c_incomplete_type_error
+#undef LANG_HOOKS_TYPE_PROMOTES_TO
+#define LANG_HOOKS_TYPE_PROMOTES_TO c_type_promotes_to
+
/* Each front end provides its own hooks, for toplev.c. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+/* Define the special tree codes that we use. */
+
+/* Table indexed by tree code giving a string containing a character
+ classifying the tree code. */
+
+#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
+
+const char tree_code_type[] = {
+#include "tree.def"
+ 'x',
+#include "c-common.def"
+ 'x',
+#include "objc-tree.def"
+};
+#undef DEFTREECODE
+
+/* Table indexed by tree code giving number of expression
+ operands beyond the fixed part of the node structure.
+ Not used for types or decls. */
+
+#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
+
+const unsigned char tree_code_length[] = {
+#include "tree.def"
+ 0,
+#include "c-common.def"
+ 0,
+#include "objc-tree.def"
+};
+#undef DEFTREECODE
+
+/* Names of tree components.
+ Used for printing out the tree and error messages. */
+#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
+
+const char * const tree_code_name[] = {
+#include "tree.def"
+ "@@dummy",
+#include "c-common.def"
+ "@@dummy",
+#include "objc-tree.def"
+};
+#undef DEFTREECODE
+
static void
objc_init_options ()
{
- c_common_init_options (clk_objective_c);
-}
+ flag_objc = 1;
+ c_common_init_options (clk_c);
+}
diff --git a/contrib/gcc/optabs.c b/contrib/gcc/optabs.c
index 7e14ceb..c9eb3e6 100644
--- a/contrib/gcc/optabs.c
+++ b/contrib/gcc/optabs.c
@@ -1,6 +1,6 @@
/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -40,7 +40,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "reload.h"
#include "ggc.h"
#include "real.h"
-#include "hard-reg-set.h"
#include "basic-block.h"
/* Each optab contains info on how this target machine
@@ -87,6 +86,11 @@ enum insn_code setcc_gen_code[NUM_RTX_CODE];
enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
#endif
+/* The insn generating function can not take an rtx_code argument.
+ TRAP_RTX is used as an rtx argument. Its code is replaced with
+ the code to be used in the trap insn and all other fields are ignored. */
+static GTY(()) rtx trap_rtx;
+
static int add_equal_note PARAMS ((rtx, rtx, enum rtx_code, rtx, rtx));
static rtx widen_operand PARAMS ((rtx, enum machine_mode,
enum machine_mode, int, int));
@@ -113,15 +117,22 @@ static inline optab init_optabv PARAMS ((enum rtx_code));
static void init_libfuncs PARAMS ((optab, int, int, const char *, int));
static void init_integral_libfuncs PARAMS ((optab, const char *, int));
static void init_floating_libfuncs PARAMS ((optab, const char *, int));
-#ifdef HAVE_conditional_trap
-static void init_traps PARAMS ((void));
-#endif
static void emit_cmp_and_jump_insn_1 PARAMS ((rtx, rtx, enum machine_mode,
enum rtx_code, int, rtx));
static void prepare_float_lib_cmp PARAMS ((rtx *, rtx *, enum rtx_code *,
enum machine_mode *, int *));
+static rtx expand_vector_binop PARAMS ((enum machine_mode, optab,
+ rtx, rtx, rtx, int,
+ enum optab_methods));
+static rtx expand_vector_unop PARAMS ((enum machine_mode, optab, rtx, rtx,
+ int));
+
+#ifndef HAVE_conditional_trap
+#define HAVE_conditional_trap 0
+#define gen_conditional_trap(a,b) (abort (), NULL_RTX)
+#endif
-/* Add a REG_EQUAL note to the last insn in SEQ. TARGET is being set to
+/* Add a REG_EQUAL note to the last insn in INSNS. TARGET is being set to
the result of operation CODE applied to OP0 (and OP1 if it is a binary
operation).
@@ -132,43 +143,65 @@ static void prepare_float_lib_cmp PARAMS ((rtx *, rtx *, enum rtx_code *,
again, ensuring that TARGET is not one of the operands. */
static int
-add_equal_note (seq, target, code, op0, op1)
- rtx seq;
+add_equal_note (insns, target, code, op0, op1)
+ rtx insns;
rtx target;
enum rtx_code code;
rtx op0, op1;
{
- rtx set;
- int i;
+ rtx last_insn, insn, set;
rtx note;
- if ((GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
- && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
- || GET_CODE (seq) != SEQUENCE
- || (set = single_set (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1))) == 0
- || GET_CODE (target) == ZERO_EXTRACT
- || (! rtx_equal_p (SET_DEST (set), target)
- /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
- SUBREG. */
- && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
- || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
- target))))
+ if (! insns
+ || ! INSN_P (insns)
+ || NEXT_INSN (insns) == NULL_RTX)
+ abort ();
+
+ if (GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
+ && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
+ return 1;
+
+ if (GET_CODE (target) == ZERO_EXTRACT)
+ return 1;
+
+ for (last_insn = insns;
+ NEXT_INSN (last_insn) != NULL_RTX;
+ last_insn = NEXT_INSN (last_insn))
+ ;
+
+ set = single_set (last_insn);
+ if (set == NULL_RTX)
+ return 1;
+
+ if (! rtx_equal_p (SET_DEST (set), target)
+ /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
+ SUBREG. */
+ && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
+ || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
+ target)))
return 1;
/* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
besides the last insn. */
if (reg_overlap_mentioned_p (target, op0)
|| (op1 && reg_overlap_mentioned_p (target, op1)))
- for (i = XVECLEN (seq, 0) - 2; i >= 0; i--)
- if (reg_set_p (target, XVECEXP (seq, 0, i)))
- return 0;
+ {
+ insn = PREV_INSN (last_insn);
+ while (insn != NULL_RTX)
+ {
+ if (reg_set_p (target, insn))
+ return 0;
+
+ insn = PREV_INSN (insn);
+ }
+ }
if (GET_RTX_CLASS (code) == '1')
note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
else
note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
- set_unique_reg_note (XVECEXP (seq, 0, XVECLEN (seq, 0) - 1), REG_EQUAL, note);
+ set_unique_reg_note (last_insn, REG_EQUAL, note);
return 1;
}
@@ -219,12 +252,12 @@ widen_operand (op, mode, oldmode, unsignedp, no_extend)
static int
expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
unsignedp, methods, class, binoptab)
- rtx real0, real1, imag0, imag1, realr, imagr;
- enum machine_mode submode;
- int unsignedp;
- enum optab_methods methods;
- enum mode_class class;
- optab binoptab;
+ rtx real0, real1, imag0, imag1, realr, imagr;
+ enum machine_mode submode;
+ int unsignedp;
+ enum optab_methods methods;
+ enum mode_class class;
+ optab binoptab;
{
rtx divisor;
rtx real_t, imag_t;
@@ -351,12 +384,12 @@ expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
static int
expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
unsignedp, methods, class, binoptab)
- rtx real0, real1, imag0, imag1, realr, imagr;
- enum machine_mode submode;
- int unsignedp;
- enum optab_methods methods;
- enum mode_class class;
- optab binoptab;
+ rtx real0, real1, imag0, imag1, realr, imagr;
+ enum machine_mode submode;
+ int unsignedp;
+ enum optab_methods methods;
+ enum mode_class class;
+ optab binoptab;
{
rtx ratio, divisor;
rtx real_t, imag_t;
@@ -621,7 +654,7 @@ expand_simple_binop (mode, code, op0, op1, target, unsignedp, methods)
int unsignedp;
enum optab_methods methods;
{
- optab binop = code_to_optab [(int) code];
+ optab binop = code_to_optab[(int) code];
if (binop == 0)
abort ();
@@ -655,7 +688,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
enum machine_mode wider_mode;
rtx temp;
int commutative_op = 0;
- int shift_op = (binoptab->code == ASHIFT
+ int shift_op = (binoptab->code == ASHIFT
|| binoptab->code == ASHIFTRT
|| binoptab->code == LSHIFTRT
|| binoptab->code == ROTATE
@@ -759,16 +792,14 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
that they're properly zero-extended, sign-extended or truncated
for their mode. */
- if (GET_MODE (op0) != mode0
- && mode0 != VOIDmode)
+ if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
xop0 = convert_modes (mode0,
GET_MODE (op0) != VOIDmode
? GET_MODE (op0)
: mode,
xop0, unsignedp);
- if (GET_MODE (xop1) != mode1
- && mode1 != VOIDmode)
+ if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
xop1 = convert_modes (mode1,
GET_MODE (op1) != VOIDmode
? GET_MODE (op1)
@@ -792,10 +823,10 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
pat = GEN_FCN (icode) (temp, xop0, xop1);
if (pat)
{
- /* If PAT is a multi-insn sequence, try to add an appropriate
+ /* If PAT is composed of more than one insn, try to add an appropriate
REG_EQUAL note to it. If we can't because TEMP conflicts with an
operand, call ourselves again, this time without a target. */
- if (GET_CODE (pat) == SEQUENCE
+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
&& ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
{
delete_insns_since (last);
@@ -1114,7 +1145,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
if (shift_count > BITS_PER_WORD)
{
first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
- second_shift_count = GEN_INT (2*BITS_PER_WORD - shift_count);
+ second_shift_count = GEN_INT (2 * BITS_PER_WORD - shift_count);
}
else
{
@@ -1127,7 +1158,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
NULL_RTX, unsignedp, next_methods);
into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
into_input, second_shift_count,
- into_target, unsignedp, next_methods);
+ NULL_RTX, unsignedp, next_methods);
if (into_temp1 != 0 && into_temp2 != 0)
inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
@@ -1143,7 +1174,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
NULL_RTX, unsignedp, next_methods);
outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
outof_input, second_shift_count,
- outof_target, unsignedp, next_methods);
+ NULL_RTX, unsignedp, next_methods);
if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
inter = expand_binop (word_mode, ior_optab,
@@ -1170,7 +1201,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
if (shift_count != BITS_PER_WORD)
emit_no_conflict_block (insns, target, op0, op1, equiv_value);
else
- emit_insns (insns);
+ emit_insn (insns);
return target;
@@ -1183,9 +1214,9 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
&& GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
&& binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
{
- int i;
+ unsigned int i;
optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
- int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
+ const unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
rtx xop0, xop1, xtarget;
@@ -1271,7 +1302,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
carry_in = carry_out;
}
- if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
+ if (i == GET_MODE_BITSIZE (mode) / (unsigned) BITS_PER_WORD)
{
if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
@@ -1283,6 +1314,8 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
copy_rtx (xop0),
copy_rtx (xop1)));
}
+ else
+ target = xtarget;
return target;
}
@@ -1484,6 +1517,12 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
delete_insns_since (last);
}
+ /* Open-code the vector operations if we have no hardware support
+ for them. */
+ if (class == MODE_VECTOR_INT || class == MODE_VECTOR_FLOAT)
+ return expand_vector_binop (mode, binoptab, op0, op1, target,
+ unsignedp, methods);
+
/* We need to open-code the complex type operations: '+, -, * and /' */
/* At this point we allow operations between two similar complex
@@ -1502,10 +1541,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
int ok = 0;
/* Find the correct mode for the real and imaginary parts */
- enum machine_mode submode
- = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
- class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
- 0);
+ enum machine_mode submode = GET_MODE_INNER(mode);
if (submode == BLKmode)
abort ();
@@ -1534,7 +1570,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
else
real1 = op1;
- if (real0 == 0 || real1 == 0 || ! (imag0 != 0|| imag1 != 0))
+ if (real0 == 0 || real1 == 0 || ! (imag0 != 0 || imag1 != 0))
abort ();
switch (binoptab->code)
@@ -1551,10 +1587,10 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
else if (res != realr)
emit_move_insn (realr, res);
- if (imag0 && imag1)
+ if (imag0 != 0 && imag1 != 0)
res = expand_binop (submode, binoptab, imag0, imag1,
imagr, unsignedp, methods);
- else if (imag0)
+ else if (imag0 != 0)
res = imag0;
else if (binoptab->code == MINUS)
res = expand_unop (submode,
@@ -1574,7 +1610,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
case MULT:
/* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
- if (imag0 && imag1)
+ if (imag0 != 0 && imag1 != 0)
{
rtx temp1, temp2;
@@ -1610,7 +1646,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
NULL_RTX, unsignedp, methods);
if (temp1 == 0 || temp2 == 0)
- break;
+ break;
res = (expand_binop
(submode,
@@ -1851,6 +1887,232 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
delete_insns_since (entry_last);
return 0;
}
+
+/* Like expand_binop, but for open-coding vectors binops. */
+
+static rtx
+expand_vector_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
+ enum machine_mode mode;
+ optab binoptab;
+ rtx op0, op1;
+ rtx target;
+ int unsignedp;
+ enum optab_methods methods;
+{
+ enum machine_mode submode, tmode;
+ int size, elts, subsize, subbitsize, i;
+ rtx t, a, b, res, seq;
+ enum mode_class class;
+
+ class = GET_MODE_CLASS (mode);
+
+ size = GET_MODE_SIZE (mode);
+ submode = GET_MODE_INNER (mode);
+
+ /* Search for the widest vector mode with the same inner mode that is
+ still narrower than MODE and that allows to open-code this operator.
+ Note, if we find such a mode and the handler later decides it can't
+ do the expansion, we'll be called recursively with the narrower mode. */
+ for (tmode = GET_CLASS_NARROWEST_MODE (class);
+ GET_MODE_SIZE (tmode) < GET_MODE_SIZE (mode);
+ tmode = GET_MODE_WIDER_MODE (tmode))
+ {
+ if (GET_MODE_INNER (tmode) == GET_MODE_INNER (mode)
+ && binoptab->handlers[(int) tmode].insn_code != CODE_FOR_nothing)
+ submode = tmode;
+ }
+
+ switch (binoptab->code)
+ {
+ case AND:
+ case IOR:
+ case XOR:
+ tmode = int_mode_for_mode (mode);
+ if (tmode != BLKmode)
+ submode = tmode;
+ case PLUS:
+ case MINUS:
+ case MULT:
+ case DIV:
+ subsize = GET_MODE_SIZE (submode);
+ subbitsize = GET_MODE_BITSIZE (submode);
+ elts = size / subsize;
+
+ /* If METHODS is OPTAB_DIRECT, we don't insist on the exact mode,
+ but that we operate on more than one element at a time. */
+ if (subsize == GET_MODE_UNIT_SIZE (mode) && methods == OPTAB_DIRECT)
+ return 0;
+
+ start_sequence ();
+
+ /* Errors can leave us with a const0_rtx as operand. */
+ if (GET_MODE (op0) != mode)
+ op0 = copy_to_mode_reg (mode, op0);
+ if (GET_MODE (op1) != mode)
+ op1 = copy_to_mode_reg (mode, op1);
+
+ if (!target)
+ target = gen_reg_rtx (mode);
+
+ for (i = 0; i < elts; ++i)
+ {
+ /* If this is part of a register, and not the first item in the
+ word, we can't store using a SUBREG - that would clobber
+ previous results.
+ And storing with a SUBREG is only possible for the least
+ significant part, hence we can't do it for big endian
+ (unless we want to permute the evaluation order. */
+ if (GET_CODE (target) == REG
+ && (BYTES_BIG_ENDIAN
+ ? subsize < UNITS_PER_WORD
+ : ((i * subsize) % UNITS_PER_WORD) != 0))
+ t = NULL_RTX;
+ else
+ t = simplify_gen_subreg (submode, target, mode, i * subsize);
+ if (CONSTANT_P (op0))
+ a = simplify_gen_subreg (submode, op0, mode, i * subsize);
+ else
+ a = extract_bit_field (op0, subbitsize, i * subbitsize, unsignedp,
+ NULL_RTX, submode, submode, size);
+ if (CONSTANT_P (op1))
+ b = simplify_gen_subreg (submode, op1, mode, i * subsize);
+ else
+ b = extract_bit_field (op1, subbitsize, i * subbitsize, unsignedp,
+ NULL_RTX, submode, submode, size);
+
+ if (binoptab->code == DIV)
+ {
+ if (class == MODE_VECTOR_FLOAT)
+ res = expand_binop (submode, binoptab, a, b, t,
+ unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ a, b, t, unsignedp);
+ }
+ else
+ res = expand_binop (submode, binoptab, a, b, t,
+ unsignedp, methods);
+
+ if (res == 0)
+ break;
+
+ if (t)
+ emit_move_insn (t, res);
+ else
+ store_bit_field (target, subbitsize, i * subbitsize, submode, res,
+ size);
+ }
+ break;
+
+ default:
+ abort ();
+ }
+
+ seq = get_insns ();
+ end_sequence ();
+ emit_insn (seq);
+
+ return target;
+}
+
+/* Like expand_unop but for open-coding vector unops. */
+
+static rtx
+expand_vector_unop (mode, unoptab, op0, target, unsignedp)
+ enum machine_mode mode;
+ optab unoptab;
+ rtx op0;
+ rtx target;
+ int unsignedp;
+{
+ enum machine_mode submode, tmode;
+ int size, elts, subsize, subbitsize, i;
+ rtx t, a, res, seq;
+
+ size = GET_MODE_SIZE (mode);
+ submode = GET_MODE_INNER (mode);
+
+ /* Search for the widest vector mode with the same inner mode that is
+ still narrower than MODE and that allows to open-code this operator.
+ Note, if we find such a mode and the handler later decides it can't
+ do the expansion, we'll be called recursively with the narrower mode. */
+ for (tmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (mode));
+ GET_MODE_SIZE (tmode) < GET_MODE_SIZE (mode);
+ tmode = GET_MODE_WIDER_MODE (tmode))
+ {
+ if (GET_MODE_INNER (tmode) == GET_MODE_INNER (mode)
+ && unoptab->handlers[(int) tmode].insn_code != CODE_FOR_nothing)
+ submode = tmode;
+ }
+ /* If there is no negate operation, try doing a subtract from zero. */
+ if (unoptab == neg_optab && GET_MODE_CLASS (submode) == MODE_INT
+ /* Avoid infinite recursion when an
+ error has left us with the wrong mode. */
+ && GET_MODE (op0) == mode)
+ {
+ rtx temp;
+ temp = expand_binop (mode, sub_optab, CONST0_RTX (mode), op0,
+ target, unsignedp, OPTAB_DIRECT);
+ if (temp)
+ return temp;
+ }
+
+ if (unoptab == one_cmpl_optab)
+ {
+ tmode = int_mode_for_mode (mode);
+ if (tmode != BLKmode)
+ submode = tmode;
+ }
+
+ subsize = GET_MODE_SIZE (submode);
+ subbitsize = GET_MODE_BITSIZE (submode);
+ elts = size / subsize;
+
+ /* Errors can leave us with a const0_rtx as operand. */
+ if (GET_MODE (op0) != mode)
+ op0 = copy_to_mode_reg (mode, op0);
+
+ if (!target)
+ target = gen_reg_rtx (mode);
+
+ start_sequence ();
+
+ for (i = 0; i < elts; ++i)
+ {
+ /* If this is part of a register, and not the first item in the
+ word, we can't store using a SUBREG - that would clobber
+ previous results.
+ And storing with a SUBREG is only possible for the least
+ significant part, hence we can't do it for big endian
+ (unless we want to permute the evaluation order. */
+ if (GET_CODE (target) == REG
+ && (BYTES_BIG_ENDIAN
+ ? subsize < UNITS_PER_WORD
+ : ((i * subsize) % UNITS_PER_WORD) != 0))
+ t = NULL_RTX;
+ else
+ t = simplify_gen_subreg (submode, target, mode, i * subsize);
+ if (CONSTANT_P (op0))
+ a = simplify_gen_subreg (submode, op0, mode, i * subsize);
+ else
+ a = extract_bit_field (op0, subbitsize, i * subbitsize, unsignedp,
+ t, submode, submode, size);
+
+ res = expand_unop (submode, unoptab, a, t, unsignedp);
+
+ if (t)
+ emit_move_insn (t, res);
+ else
+ store_bit_field (target, subbitsize, i * subbitsize, submode, res,
+ size);
+ }
+
+ seq = get_insns ();
+ end_sequence ();
+ emit_insn (seq);
+
+ return target;
+}
/* Expand a binary operator which has both signed and unsigned forms.
UOPTAB is the optab for unsigned operations, and SOPTAB is for
@@ -1861,11 +2123,11 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
rtx
sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
- enum machine_mode mode;
- optab uoptab, soptab;
- rtx op0, op1, target;
- int unsignedp;
- enum optab_methods methods;
+ enum machine_mode mode;
+ optab uoptab, soptab;
+ rtx op0, op1, target;
+ int unsignedp;
+ enum optab_methods methods;
{
rtx temp;
optab direct_optab = unsignedp ? uoptab : soptab;
@@ -1975,13 +2237,25 @@ expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
rtx pat;
rtx xop0 = op0, xop1 = op1;
- /* In case this insn wants input operands in modes different from the
- result, convert the operands. */
- if (GET_MODE (op0) != VOIDmode && GET_MODE (op0) != mode0)
- xop0 = convert_to_mode (mode0, xop0, unsignedp);
+ /* In case the insn wants input operands in modes different from
+ those of the actual operands, convert the operands. It would
+ seem that we don't need to convert CONST_INTs, but we do, so
+ that they're properly zero-extended, sign-extended or truncated
+ for their mode. */
- if (GET_MODE (op1) != VOIDmode && GET_MODE (op1) != mode1)
- xop1 = convert_to_mode (mode1, xop1, unsignedp);
+ if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
+ xop0 = convert_modes (mode0,
+ GET_MODE (op0) != VOIDmode
+ ? GET_MODE (op0)
+ : mode,
+ xop0, unsignedp);
+
+ if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
+ xop1 = convert_modes (mode1,
+ GET_MODE (op1) != VOIDmode
+ ? GET_MODE (op1)
+ : mode,
+ xop1, unsignedp);
/* Now, if insn doesn't accept these operands, put them into pseudos. */
if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
@@ -2049,7 +2323,7 @@ expand_simple_unop (mode, code, op0, target, unsignedp)
rtx target;
int unsignedp;
{
- optab unop = code_to_optab [(int) code];
+ optab unop = code_to_optab[(int) code];
if (unop == 0)
abort ();
@@ -2119,7 +2393,7 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
pat = GEN_FCN (icode) (temp, xop0);
if (pat)
{
- if (GET_CODE (pat) == SEQUENCE
+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
&& ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
{
delete_insns_since (last);
@@ -2217,10 +2491,7 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
rtx seq;
/* Find the correct mode for the real and imaginary parts */
- enum machine_mode submode
- = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
- class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
- 0);
+ enum machine_mode submode = GET_MODE_INNER (mode);
if (submode == BLKmode)
abort ();
@@ -2275,6 +2546,9 @@ expand_unop (mode, unoptab, op0, target, unsignedp)
return target;
}
+ if (class == MODE_VECTOR_FLOAT || class == MODE_VECTOR_INT)
+ return expand_vector_unop (mode, unoptab, op0, target, unsignedp);
+
/* It can't be done in this mode. Can we do it in a wider mode? */
if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
@@ -2461,10 +2735,7 @@ expand_complex_abs (mode, op0, target, unsignedp)
optab this_abs_optab;
/* Find the correct mode for the real and imaginary parts. */
- enum machine_mode submode
- = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
- class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,
- 0);
+ enum machine_mode submode = GET_MODE_INNER (mode);
if (submode == BLKmode)
abort ();
@@ -2511,7 +2782,7 @@ expand_complex_abs (mode, op0, target, unsignedp)
pat = GEN_FCN (icode) (temp, xop0);
if (pat)
{
- if (GET_CODE (pat) == SEQUENCE
+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
&& ! add_equal_note (pat, temp, this_abs_optab->code, xop0,
NULL_RTX))
{
@@ -2680,7 +2951,7 @@ emit_unop_insn (icode, target, op0, code)
pat = GEN_FCN (icode) (temp, op0);
- if (GET_CODE (pat) == SEQUENCE && code != UNKNOWN)
+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX && code != UNKNOWN)
add_equal_note (pat, temp, code, op0, NULL_RTX);
emit_insn (pat);
@@ -2708,7 +2979,7 @@ emit_unop_insn (icode, target, op0, code)
TARGET, OP0, and OP1 are the output and inputs of the operations,
respectively. OP1 may be zero for a unary operation.
- EQUIV, if non-zero, is an expression to be placed into a REG_EQUAL note
+ EQUIV, if nonzero, is an expression to be placed into a REG_EQUAL note
on the last insn.
If TARGET is not a register, INSNS is simply emitted with no special
@@ -2727,12 +2998,12 @@ emit_no_conflict_block (insns, target, op0, op1, equiv)
rtx prev, next, first, last, insn;
if (GET_CODE (target) != REG || reload_in_progress)
- return emit_insns (insns);
+ return emit_insn (insns);
else
for (insn = insns; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) != INSN
|| find_reg_note (insn, REG_LIBCALL, NULL_RTX))
- return emit_insns (insns);
+ return emit_insn (insns);
/* First emit all insns that do not store into words of the output and remove
these from the list. */
@@ -3038,24 +3309,24 @@ can_compare_p (code, mode, purpose)
{
do
{
- if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+ if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
{
if (purpose == ccp_jump)
- return bcc_gen_fctn[(int)code] != NULL;
+ return bcc_gen_fctn[(int) code] != NULL;
else if (purpose == ccp_store_flag)
- return setcc_gen_code[(int)code] != CODE_FOR_nothing;
+ return setcc_gen_code[(int) code] != CODE_FOR_nothing;
else
/* There's only one cmov entry point, and it's allowed to fail. */
return 1;
}
if (purpose == ccp_jump
- && cbranch_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+ && cbranch_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
return 1;
if (purpose == ccp_cmov
- && cmov_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+ && cmov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
return 1;
if (purpose == ccp_store_flag
- && cstore_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+ && cstore_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
return 1;
mode = GET_MODE_WIDER_MODE (mode);
@@ -3123,7 +3394,7 @@ prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, purpose)
states that canonical comparisons are required only for targets which
have cc0. */
if (CONSTANT_P (x) && ! CONSTANT_P (y))
- abort();
+ abort ();
#endif
/* Don't let both operands fail to indicate the mode. */
@@ -3181,29 +3452,23 @@ prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, purpose)
#endif
{
#ifdef TARGET_MEM_FUNCTIONS
- emit_library_call (memcmp_libfunc, LCT_PURE_MAKE_BLOCK,
- TYPE_MODE (integer_type_node), 3,
- XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
- convert_to_mode (TYPE_MODE (sizetype), size,
- TREE_UNSIGNED (sizetype)),
- TYPE_MODE (sizetype));
+ result = emit_library_call_value (memcmp_libfunc, NULL_RTX, LCT_PURE_MAKE_BLOCK,
+ TYPE_MODE (integer_type_node), 3,
+ XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
+ convert_to_mode (TYPE_MODE (sizetype), size,
+ TREE_UNSIGNED (sizetype)),
+ TYPE_MODE (sizetype));
#else
- emit_library_call (bcmp_libfunc, LCT_PURE_MAKE_BLOCK,
- TYPE_MODE (integer_type_node), 3,
- XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
- convert_to_mode (TYPE_MODE (integer_type_node),
- size,
- TREE_UNSIGNED (integer_type_node)),
- TYPE_MODE (integer_type_node));
+ result = emit_library_call_value (bcmp_libfunc, NULL_RTX, LCT_PURE_MAKE_BLOCK,
+ TYPE_MODE (integer_type_node), 3,
+ XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
+ convert_to_mode (TYPE_MODE (integer_type_node),
+ size,
+ TREE_UNSIGNED (integer_type_node)),
+ TYPE_MODE (integer_type_node));
#endif
- /* 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));
result_mode = TYPE_MODE (integer_type_node);
- emit_move_insn (result,
- hard_libcall_value (result_mode));
}
*px = result;
*py = const0_rtx;
@@ -3228,14 +3493,8 @@ prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, purpose)
if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
libfunc = ucmp_optab->handlers[(int) mode].libfunc;
- emit_library_call (libfunc, LCT_CONST_MAKE_BLOCK, 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));
+ result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK,
+ word_mode, 2, x, mode, y, mode);
/* Integer comparison returns a result that must be compared against 1,
so that even if we do an unsigned compare afterward,
@@ -3302,7 +3561,7 @@ emit_cmp_and_jump_insn_1 (x, y, mode, comparison, unsignedp, label)
if (label)
{
- icode = cbranch_optab->handlers[(int)wider_mode].insn_code;
+ icode = cbranch_optab->handlers[(int) wider_mode].insn_code;
if (icode != CODE_FOR_nothing
&& (*insn_data[icode].operand[0].predicate) (test, wider_mode))
@@ -3343,7 +3602,8 @@ emit_cmp_and_jump_insn_1 (x, y, mode, comparison, unsignedp, label)
break;
wider_mode = GET_MODE_WIDER_MODE (wider_mode);
- } while (wider_mode != VOIDmode);
+ }
+ while (wider_mode != VOIDmode);
abort ();
}
@@ -3429,6 +3689,7 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
int *punsignedp;
{
enum rtx_code comparison = *pcomparison;
+ rtx tmp;
rtx x = *px = protect_from_queue (*px, 0);
rtx y = *py = protect_from_queue (*py, 0);
enum machine_mode mode = GET_MODE (x);
@@ -3448,18 +3709,42 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
case GT:
libfunc = gthf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = LT;
+ libfunc = lthf2_libfunc;
+ }
break;
case GE:
libfunc = gehf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = LE;
+ libfunc = lehf2_libfunc;
+ }
break;
case LT:
libfunc = lthf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = GT;
+ libfunc = gthf2_libfunc;
+ }
break;
case LE:
libfunc = lehf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = GE;
+ libfunc = gehf2_libfunc;
+ }
break;
case UNORDERED:
@@ -3482,18 +3767,42 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
case GT:
libfunc = gtsf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = LT;
+ libfunc = ltsf2_libfunc;
+ }
break;
case GE:
libfunc = gesf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = LE;
+ libfunc = lesf2_libfunc;
+ }
break;
case LT:
libfunc = ltsf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = GT;
+ libfunc = gtsf2_libfunc;
+ }
break;
case LE:
libfunc = lesf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = GE;
+ libfunc = gesf2_libfunc;
+ }
break;
case UNORDERED:
@@ -3516,18 +3825,42 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
case GT:
libfunc = gtdf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = LT;
+ libfunc = ltdf2_libfunc;
+ }
break;
case GE:
libfunc = gedf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = LE;
+ libfunc = ledf2_libfunc;
+ }
break;
case LT:
libfunc = ltdf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = GT;
+ libfunc = gtdf2_libfunc;
+ }
break;
case LE:
libfunc = ledf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = GE;
+ libfunc = gedf2_libfunc;
+ }
break;
case UNORDERED:
@@ -3550,18 +3883,42 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
case GT:
libfunc = gtxf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = LT;
+ libfunc = ltxf2_libfunc;
+ }
break;
case GE:
libfunc = gexf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = LE;
+ libfunc = lexf2_libfunc;
+ }
break;
case LT:
libfunc = ltxf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = GT;
+ libfunc = gtxf2_libfunc;
+ }
break;
case LE:
libfunc = lexf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = GE;
+ libfunc = gexf2_libfunc;
+ }
break;
case UNORDERED:
@@ -3584,18 +3941,42 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
case GT:
libfunc = gttf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = LT;
+ libfunc = lttf2_libfunc;
+ }
break;
case GE:
libfunc = getf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = LE;
+ libfunc = letf2_libfunc;
+ }
break;
case LT:
libfunc = lttf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = GT;
+ libfunc = gttf2_libfunc;
+ }
break;
case LE:
libfunc = letf2_libfunc;
+ if (libfunc == NULL_RTX)
+ {
+ tmp = x; x = y; y = tmp;
+ *pcomparison = GE;
+ libfunc = getf2_libfunc;
+ }
break;
case UNORDERED:
@@ -3630,14 +4011,8 @@ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
if (libfunc == 0)
abort ();
- emit_library_call (libfunc, LCT_CONST_MAKE_BLOCK, 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));
+ result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK,
+ word_mode, 2, x, mode, y, mode);
*px = result;
*py = const0_rtx;
*pmode = word_mode;
@@ -3656,7 +4031,7 @@ void
emit_indirect_jump (loc)
rtx loc;
{
- if (! ((*insn_data[(int)CODE_FOR_indirect_jump].operand[0].predicate)
+ if (! ((*insn_data[(int) CODE_FOR_indirect_jump].operand[0].predicate)
(loc, Pmode)))
loc = copy_to_mode_reg (Pmode, loc);
@@ -3794,7 +4169,7 @@ emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
return target;
}
-/* Return non-zero if a conditional move of mode MODE is supported.
+/* Return nonzero if a conditional move of mode MODE is supported.
This function is for combine so it can tell whether an insn that looks
like a conditional move is actually supported by the hardware. If we
@@ -3848,7 +4223,7 @@ gen_add3_insn (r0, r1, c)
{
int icode = (int) add_optab->handlers[(int) GET_MODE (r0)].insn_code;
- if (icode == CODE_FOR_nothing
+ if (icode == CODE_FOR_nothing
|| ! ((*insn_data[icode].operand[0].predicate)
(r0, insn_data[icode].operand[0].mode))
|| ! ((*insn_data[icode].operand[1].predicate)
@@ -3912,7 +4287,7 @@ gen_sub3_insn (r0, r1, c)
{
int icode = (int) sub_optab->handlers[(int) GET_MODE (r0)].insn_code;
- if (icode == CODE_FOR_nothing
+ if (icode == CODE_FOR_nothing
|| ! ((*insn_data[icode].operand[0].predicate)
(r0, insn_data[icode].operand[0].mode))
|| ! ((*insn_data[icode].operand[1].predicate)
@@ -3950,7 +4325,7 @@ have_sub2_insn (x, y)
}
/* Generate the body of an instruction to copy Y into X.
- It may be a SEQUENCE, if one insn isn't enough. */
+ It may be a list of insns, if one insn isn't enough. */
rtx
gen_move_insn (x, y)
@@ -4021,7 +4396,7 @@ gen_move_insn (x, y)
start_sequence ();
emit_move_insn_1 (x, y);
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
return seq;
}
@@ -4115,10 +4490,10 @@ expand_float (to, from, unsignedp)
wider mode. If the integer mode is wider than the mode of FROM,
we can do the conversion signed even if the input is unsigned. */
- for (imode = GET_MODE (from); imode != VOIDmode;
- imode = GET_MODE_WIDER_MODE (imode))
- for (fmode = GET_MODE (to); fmode != VOIDmode;
- fmode = GET_MODE_WIDER_MODE (fmode))
+ for (fmode = GET_MODE (to); fmode != VOIDmode;
+ fmode = GET_MODE_WIDER_MODE (fmode))
+ for (imode = GET_MODE (from); imode != VOIDmode;
+ imode = GET_MODE_WIDER_MODE (imode))
{
int doing_unsigned = unsignedp;
@@ -4148,9 +4523,7 @@ expand_float (to, from, unsignedp)
convert_move (to, target, 0);
return;
}
- }
-
-#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
+ }
/* Unsigned integer, and no way to convert directly.
Convert as signed, then conditionally adjust the result. */
@@ -4225,7 +4598,7 @@ expand_float (to, from, unsignedp)
/* Multiply by 2 to undo the shift above. */
temp = expand_binop (fmode, add_optab, target, target,
- target, 0, OPTAB_LIB_WIDEN);
+ target, 0, OPTAB_LIB_WIDEN);
if (temp != target)
emit_move_insn (target, temp);
@@ -4252,10 +4625,8 @@ expand_float (to, from, unsignedp)
emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
0, label);
- /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
- Rather than setting up a dconst_dot_5, let's hope SCO
- fixes the bug. */
- offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
+
+ real_2expN (&offset, GET_MODE_BITSIZE (GET_MODE (from)));
temp = expand_binop (fmode, add_optab, target,
CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
target, 0, OPTAB_LIB_WIDEN);
@@ -4266,7 +4637,6 @@ expand_float (to, from, unsignedp)
emit_label (label);
goto done;
}
-#endif
/* No hardware instruction available; call a library routine to convert from
SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
@@ -4417,7 +4787,6 @@ expand_fix (to, from, unsignedp)
}
}
-#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
/* For an unsigned conversion, there is one more way to do it.
If we have a signed conversion, we generate code that compares
the real value to the largest representable positive number. If if
@@ -4440,7 +4809,7 @@ expand_fix (to, from, unsignedp)
rtx limit, lab1, lab2, insn;
bitsize = GET_MODE_BITSIZE (GET_MODE (to));
- offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
+ real_2expN (&offset, bitsize - 1);
limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
lab1 = gen_label_rtx ();
lab2 = gen_label_rtx ();
@@ -4473,9 +4842,9 @@ expand_fix (to, from, unsignedp)
NULL_RTX, 0, OPTAB_LIB_WIDEN);
expand_fix (to, target, 0);
target = expand_binop (GET_MODE (to), xor_optab, to,
- GEN_INT (trunc_int_for_mode
- ((HOST_WIDE_INT) 1 << (bitsize - 1),
- GET_MODE (to))),
+ gen_int_mode
+ ((HOST_WIDE_INT) 1 << (bitsize - 1),
+ GET_MODE (to)),
to, 1, OPTAB_LIB_WIDEN);
if (target != to)
@@ -4497,7 +4866,6 @@ expand_fix (to, from, unsignedp)
return;
}
-#endif
/* We can't do it with an insn, so use a library call. But first ensure
that the mode of TO is at least as wide as SImode, since those are the
@@ -4606,7 +4974,7 @@ static optab
new_optab ()
{
int i;
- optab op = (optab) xmalloc (sizeof (struct optab));
+ optab op = (optab) ggc_alloc (sizeof (struct optab));
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
op->handlers[i].insn_code = CODE_FOR_nothing;
@@ -4658,11 +5026,11 @@ init_optabv (code)
static void
init_libfuncs (optable, first_mode, last_mode, opname, suffix)
- optab optable;
- int first_mode;
- int last_mode;
- const char *opname;
- int suffix;
+ optab optable;
+ int first_mode;
+ int last_mode;
+ const char *opname;
+ int suffix;
{
int mode;
unsigned opname_len = strlen (opname);
@@ -4670,7 +5038,7 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
for (mode = first_mode; (int) mode <= (int) last_mode;
mode = (enum machine_mode) ((int) mode + 1))
{
- const char *mname = GET_MODE_NAME(mode);
+ const char *mname = GET_MODE_NAME (mode);
unsigned mname_len = strlen (mname);
char *libfunc_name = alloca (2 + opname_len + mname_len + 1 + 1);
char *p;
@@ -4699,9 +5067,9 @@ init_libfuncs (optable, first_mode, last_mode, opname, suffix)
static void
init_integral_libfuncs (optable, opname, suffix)
- optab optable;
- const char *opname;
- int suffix;
+ optab optable;
+ const char *opname;
+ int suffix;
{
init_libfuncs (optable, SImode, TImode, opname, suffix);
}
@@ -4713,9 +5081,9 @@ init_integral_libfuncs (optable, opname, suffix)
static void
init_floating_libfuncs (optable, opname, suffix)
- optab optable;
- const char *opname;
- int suffix;
+ optab optable;
+ const char *opname;
+ int suffix;
{
init_libfuncs (optable, SFmode, TFmode, opname, suffix);
}
@@ -4724,7 +5092,8 @@ rtx
init_one_libfunc (name)
const char *name;
{
- /* Create a FUNCTION_DECL that can be passed to ENCODE_SECTION_INFO. */
+ /* Create a FUNCTION_DECL that can be passed to
+ targetm.encode_section_info. */
/* ??? We don't have any type information except for this is
a function. Pretend this is "int foo()". */
tree decl = build_decl (FUNCTION_DECL, get_identifier (name),
@@ -4737,19 +5106,6 @@ init_one_libfunc (name)
return XEXP (DECL_RTL (decl), 0);
}
-/* Mark ARG (which is really an OPTAB *) for GC. */
-
-void
-mark_optab (arg)
- void *arg;
-{
- optab o = *(optab *) arg;
- int i;
-
- for (i = 0; i < NUM_MACHINE_MODES; ++i)
- ggc_mark_rtx (o->handlers[i].libfunc);
-}
-
/* Call this once to initialize the contents of the optabs
appropriately for the current target machine. */
@@ -4836,6 +5192,8 @@ init_optabs ()
sqrt_optab = init_optab (SQRT);
sin_optab = init_optab (UNKNOWN);
cos_optab = init_optab (UNKNOWN);
+ exp_optab = init_optab (UNKNOWN);
+ log_optab = init_optab (UNKNOWN);
strlen_optab = init_optab (UNKNOWN);
cbranch_optab = init_optab (UNKNOWN);
cmov_optab = init_optab (UNKNOWN);
@@ -5092,69 +5450,52 @@ init_optabs ()
profile_function_exit_libfunc
= init_one_libfunc ("__cyg_profile_func_exit");
-#ifdef HAVE_conditional_trap
- init_traps ();
-#endif
+ if (HAVE_conditional_trap)
+ trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
#ifdef INIT_TARGET_OPTABS
/* Allow the target to add more libcalls or rename some, etc. */
INIT_TARGET_OPTABS;
#endif
-
- /* Add these GC roots. */
- ggc_add_root (optab_table, OTI_MAX, sizeof(optab), mark_optab);
- ggc_add_rtx_root (libfunc_table, LTI_MAX);
}
-#ifdef HAVE_conditional_trap
-/* The insn generating function can not take an rtx_code argument.
- TRAP_RTX is used as an rtx argument. Its code is replaced with
- the code to be used in the trap insn and all other fields are
- ignored. */
-static rtx trap_rtx;
-
-static void
-init_traps ()
-{
- if (HAVE_conditional_trap)
- {
- trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
- ggc_add_rtx_root (&trap_rtx, 1);
- }
-}
-#endif
-
/* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
CODE. Return 0 on failure. */
rtx
gen_cond_trap (code, op1, op2, tcode)
- enum rtx_code code ATTRIBUTE_UNUSED;
- rtx op1, op2 ATTRIBUTE_UNUSED, tcode ATTRIBUTE_UNUSED;
+ enum rtx_code code ATTRIBUTE_UNUSED;
+ rtx op1, op2 ATTRIBUTE_UNUSED, tcode ATTRIBUTE_UNUSED;
{
enum machine_mode mode = GET_MODE (op1);
+ enum insn_code icode;
+ rtx insn;
+
+ if (!HAVE_conditional_trap)
+ return 0;
if (mode == VOIDmode)
return 0;
-#ifdef HAVE_conditional_trap
- if (HAVE_conditional_trap
- && cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+ icode = cmp_optab->handlers[(int) mode].insn_code;
+ if (icode == CODE_FOR_nothing)
+ return 0;
+
+ start_sequence ();
+ op1 = prepare_operand (icode, op1, 0, mode, mode, 0);
+ op2 = prepare_operand (icode, op2, 0, mode, mode, 0);
+ emit_insn (GEN_FCN (icode) (op1, op2));
+
+ PUT_CODE (trap_rtx, code);
+ insn = gen_conditional_trap (trap_rtx, tcode);
+ if (insn)
{
- rtx insn;
- start_sequence();
- emit_insn (GEN_FCN (cmp_optab->handlers[(int) mode].insn_code) (op1, op2));
- PUT_CODE (trap_rtx, code);
- insn = gen_conditional_trap (trap_rtx, tcode);
- if (insn)
- {
- emit_insn (insn);
- insn = gen_sequence ();
- }
- end_sequence();
- return insn;
+ emit_insn (insn);
+ insn = get_insns ();
}
-#endif
+ end_sequence ();
- return 0;
+ return insn;
}
+
+#include "gt-optabs.h"
diff --git a/contrib/gcc/optabs.h b/contrib/gcc/optabs.h
index 0c488b8..fd80d82 100644
--- a/contrib/gcc/optabs.h
+++ b/contrib/gcc/optabs.h
@@ -38,14 +38,15 @@ Boston, MA 02111-1307, USA. */
A few optabs, such as move_optab and cmp_optab, are used
by special code. */
-typedef struct optab
+struct optab GTY(())
{
enum rtx_code code;
- struct {
+ struct optab_handlers {
enum insn_code insn_code;
rtx libfunc;
} handlers [NUM_MACHINE_MODES];
-} * optab;
+};
+typedef struct optab * optab;
/* Given an enum insn_code, access the function to construct
the body of that kind of insn. */
@@ -130,6 +131,10 @@ enum optab_index
OTI_sin,
/* Cosine */
OTI_cos,
+ /* Exponential */
+ OTI_exp,
+ /* Natural Logarithm */
+ OTI_log,
/* Compare insn; two operands. */
OTI_cmp,
@@ -152,7 +157,7 @@ enum optab_index
OTI_MAX
};
-extern optab optab_table[OTI_MAX];
+extern GTY(()) optab optab_table[OTI_MAX];
#define add_optab (optab_table[OTI_add])
#define sub_optab (optab_table[OTI_sub])
@@ -197,6 +202,8 @@ extern optab optab_table[OTI_MAX];
#define sqrt_optab (optab_table[OTI_sqrt])
#define sin_optab (optab_table[OTI_sin])
#define cos_optab (optab_table[OTI_cos])
+#define exp_optab (optab_table[OTI_exp])
+#define log_optab (optab_table[OTI_log])
#define cmp_optab (optab_table[OTI_cmp])
#define ucmp_optab (optab_table[OTI_ucmp])
diff --git a/contrib/gcc/output.h b/contrib/gcc/output.h
index 0e11df3..0f08971 100644
--- a/contrib/gcc/output.h
+++ b/contrib/gcc/output.h
@@ -46,7 +46,6 @@ extern int dbr_sequence_length PARAMS ((void));
/* Indicate that branch shortening hasn't yet been done. */
extern void init_insn_lengths PARAMS ((void));
-#ifdef RTX_CODE
/* Obtain the current length of an insn. If branch shortening has been done,
get its actual length. Otherwise, get its maximum length. */
extern int get_attr_length PARAMS ((rtx));
@@ -119,7 +118,7 @@ extern void split_double PARAMS ((rtx, rtx *, rtx *));
/* Return nonzero if this function has no function calls. */
extern int leaf_function_p PARAMS ((void));
-/* Return 1 if branch is an forward branch.
+/* Return 1 if branch is a forward branch.
Uses insn_shuid array, so it works only in the final pass. May be used by
output templates to add branch prediction hints, for example. */
extern int final_forward_branch_p PARAMS ((rtx));
@@ -137,7 +136,7 @@ extern const char *get_insn_template PARAMS ((int, rtx));
/* Add function NAME to the weak symbols list. VALUE is a weak alias
associated with NAME. */
-extern int add_weak PARAMS ((const char *, const char *));
+extern int add_weak PARAMS ((tree, const char *, const char *));
/* Functions in flow.c */
extern void allocate_for_life_analysis PARAMS ((void));
@@ -145,8 +144,8 @@ extern int regno_uninitialized PARAMS ((unsigned int));
extern int regno_clobbered_at_setjmp PARAMS ((int));
extern void find_basic_blocks PARAMS ((rtx, int, FILE *));
extern bool cleanup_cfg PARAMS ((int));
+extern bool delete_unreachable_blocks PARAMS ((void));
extern void check_function_return_warnings PARAMS ((void));
-#endif
/* Functions in varasm.c. */
@@ -210,7 +209,6 @@ extern void sdata_section PARAMS ((void));
extern void rdata_section PARAMS ((void));
#endif
-#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.
@@ -233,7 +231,6 @@ extern void mergeable_constant_section PARAMS ((enum machine_mode,
extern void declare_weak PARAMS ((tree));
/* Merge weak status. */
extern void merge_weak PARAMS ((tree, tree));
-#endif /* TREE_CODE */
/* Emit any pending weak declarations. */
extern void weak_finish PARAMS ((void));
@@ -247,7 +244,6 @@ extern void weak_finish PARAMS ((void));
Prefixes such as % are optional. */
extern int decode_reg_name PARAMS ((const char *));
-#ifdef TREE_CODE
/* Make the rtl for variable VAR be volatile.
Use this only for static variables. */
extern void make_var_volatile PARAMS ((tree));
@@ -257,6 +253,8 @@ extern void assemble_constant_align PARAMS ((tree));
extern void assemble_alias PARAMS ((tree, tree));
+extern void default_assemble_visibility PARAMS ((tree, int));
+
/* Output a string of literal assembler code
for an `asm' keyword used between functions. */
extern void assemble_asm PARAMS ((tree));
@@ -286,7 +284,6 @@ extern void assemble_variable PARAMS ((tree, int, int, int));
(Most assemblers don't need this, so we normally output nothing.)
Do nothing if DECL is not external. */
extern void assemble_external PARAMS ((tree));
-#endif /* TREE_CODE */
/* Assemble code to leave SIZE bytes of zeros. */
extern void assemble_zeros PARAMS ((int));
@@ -298,13 +295,8 @@ extern void assemble_eh_align PARAMS ((int));
/* Assemble a string constant with the specified C string as contents. */
extern void assemble_string PARAMS ((const char *, int));
-#ifdef RTX_CODE
/* Similar, for calling a library function FUN. */
extern void assemble_external_libcall PARAMS ((rtx));
-#endif
-
-/* Declare the label NAME global. */
-extern void assemble_global PARAMS ((const char *));
/* Assemble a label named NAME. */
extern void assemble_label PARAMS ((const char *));
@@ -326,7 +318,6 @@ extern void assemble_name PARAMS ((FILE *, const char *));
be followed immediately by the object's initial value. */
extern const char *integer_asm_op PARAMS ((int, int));
-#ifdef RTX_CODE
/* Use directive OP to assemble an integer object X. Print OP at the
start of the line, followed immediately by the value of X. */
extern void assemble_integer_with_op PARAMS ((const char *, rtx));
@@ -336,7 +327,7 @@ extern bool default_assemble_integer PARAMS ((rtx, unsigned int, int));
/* Assemble the integer constant X into an object of SIZE bytes. ALIGN is
the alignment of the integer in bits. Return 1 if we were able to output
- the constant, otherwise 0. If FORCE is non-zero, abort if we can't output
+ the constant, otherwise 0. If FORCE is nonzero, abort if we can't output
the constant. */
extern bool assemble_integer PARAMS ((rtx, unsigned, unsigned, int));
@@ -346,18 +337,12 @@ extern bool assemble_integer PARAMS ((rtx, unsigned, unsigned, int));
#define assemble_aligned_integer(SIZE, VALUE) \
assemble_integer (VALUE, SIZE, (SIZE) * BITS_PER_UNIT, 1)
-#ifdef REAL_VALUE_TYPE
+#ifdef REAL_VALUE_TYPE_SIZE
/* Assemble the floating-point constant D into an object of size MODE. */
extern void assemble_real PARAMS ((REAL_VALUE_TYPE,
enum machine_mode,
unsigned));
#endif
-#endif
-
-/* At the end of a function, forget the memory-constants
- previously made for CONST_DOUBLEs. Mark them as not on real_constant_chain.
- Also clear out real_constant_chain and clear out all the chain-pointers. */
-extern void clear_const_double_mem PARAMS ((void));
/* Start deferring output of subconstants. */
extern void defer_addressed_constants PARAMS ((void));
@@ -373,7 +358,6 @@ extern int get_pool_size PARAMS ((void));
extern rtx peephole PARAMS ((rtx));
#endif
-#ifdef TREE_CODE
/* Write all the constants in the constant pool. */
extern void output_constant_pool PARAMS ((const char *, tree));
@@ -398,9 +382,7 @@ extern tree initializer_constant_valid_p PARAMS ((tree, tree));
ALIGN is the alignment in bits that may be assumed for the data. */
extern void output_constant PARAMS ((tree, HOST_WIDE_INT,
unsigned int));
-#endif
-#ifdef RTX_CODE
/* When outputting delayed branch sequences, this rtx holds the
sequence being output. It is null when no delayed branch
sequence is being output, so it can be used as a test in the
@@ -408,7 +390,6 @@ extern void output_constant PARAMS ((tree, HOST_WIDE_INT,
This variable is defined in final.c. */
extern rtx final_sequence;
-#endif
/* The line number of the beginning of the current function. Various
md code needs this so that it can output relative linenumbers. */
@@ -465,28 +446,19 @@ extern struct rtx_def *current_insn_predicate;
/* Last insn processed by final_scan_insn. */
extern struct rtx_def *current_output_insn;
-/* Decide whether DECL needs to be in a writable section. RELOC is the same
- as for SELECT_SECTION. */
+/* 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. */
+extern rtx this_is_asm_operands;
-#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))))
+/* Decide whether DECL needs to be in a writable section.
+ RELOC is the same as for SELECT_SECTION. */
+extern bool decl_readonly_section PARAMS ((tree, int));
+extern bool decl_readonly_section_1 PARAMS ((tree, int, int));
/* User label prefix in effect for this compilation. */
extern const char *user_label_prefix;
-/* This macro gets just the user-specified name
- out of the string in a SYMBOL_REF. On most machines,
- we discard the * if any and that's all. */
-#ifndef STRIP_NAME_ENCODING
-#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
- (VAR) = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*'))
-#endif
-
/* Default target function prologue and epilogue assembler output. */
extern void default_function_pro_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
@@ -512,7 +484,9 @@ extern void no_asm_to_stream PARAMS ((FILE *));
#define SECTION_STRINGS 0x10000 /* contains zero terminated strings without
embedded zeros */
#define SECTION_OVERRIDE 0x20000 /* allow override of default flags */
-#define SECTION_MACH_DEP 0x40000 /* subsequent bits reserved for target */
+#define SECTION_TLS 0x40000 /* contains thread-local storage */
+#define SECTION_NOTYPE 0x80000 /* don't output @progbits */
+#define SECTION_MACH_DEP 0x100000 /* subsequent bits reserved for target */
extern unsigned int get_named_section_flags PARAMS ((const char *));
extern bool set_named_section_flags PARAMS ((const char *, unsigned int));
@@ -522,6 +496,9 @@ extern bool named_section_first_declaration PARAMS((const char *));
union tree_node;
extern unsigned int default_section_type_flags PARAMS ((union tree_node *,
const char *, int));
+extern unsigned int default_section_type_flags_1 PARAMS ((union tree_node *,
+ const char *,
+ int, int));
extern void default_no_named_section PARAMS ((const char *, unsigned int));
extern void default_elf_asm_named_section PARAMS ((const char *, unsigned int));
@@ -540,6 +517,23 @@ extern void default_named_section_asm_out_constructor PARAMS ((struct rtx_def *,
extern void default_ctor_section_asm_out_constructor PARAMS ((struct rtx_def *,
int));
+extern void default_select_section PARAMS ((tree, int,
+ unsigned HOST_WIDE_INT));
+extern void default_elf_select_section PARAMS ((tree, int,
+ unsigned HOST_WIDE_INT));
+extern void default_elf_select_section_1 PARAMS ((tree, int,
+ unsigned HOST_WIDE_INT, int));
+extern void default_unique_section PARAMS ((tree, int));
+extern void default_unique_section_1 PARAMS ((tree, int, int));
+extern void default_select_rtx_section PARAMS ((enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT));
+extern void default_elf_select_rtx_section PARAMS ((enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT));
+extern const char *default_strip_name_encoding PARAMS ((const char *));
+extern bool default_binds_local_p PARAMS ((tree));
+extern bool default_binds_local_p_1 PARAMS ((tree, int));
+extern void default_globalize_label PARAMS ((FILE *, const char *));
+
/* Emit data for vtable gc for GNU binutils. */
extern void assemble_vtable_entry PARAMS ((struct rtx_def *, HOST_WIDE_INT));
extern void assemble_vtable_inherit PARAMS ((struct rtx_def *,
diff --git a/contrib/gcc/params.c b/contrib/gcc/params.c
index b32f9b6..72c67be 100644
--- a/contrib/gcc/params.c
+++ b/contrib/gcc/params.c
@@ -37,14 +37,14 @@ static size_t num_compiler_params;
/* Add the N PARAMS to the current list of compiler parameters. */
-void
+void
add_params (params, n)
const param_info params[];
size_t n;
{
/* Allocate enough space for the new parameters. */
- compiler_params =
- ((param_info *)
+ compiler_params =
+ ((param_info *)
xrealloc (compiler_params,
(num_compiler_params + n) * sizeof (param_info)));
/* Copy them into the table. */
@@ -79,6 +79,3 @@ set_param_value (name, value)
/* If we didn't find this parameter, issue an error message. */
error ("invalid parameter `%s'", name);
}
-
-
-
diff --git a/contrib/gcc/params.def b/contrib/gcc/params.def
index 2a1d3a3..977d740 100644
--- a/contrib/gcc/params.def
+++ b/contrib/gcc/params.def
@@ -1,5 +1,5 @@
/* params.def - Run-time parameters.
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
Written by Mark Mitchell <mark@codesourcery.com>.
This file is part of GCC.
@@ -35,15 +35,89 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
Be sure to add an entry to invoke.texi summarizing the parameter. */
-/* The maximum number of instructions accepted for inlining a
- function. Increasing values mean more agressive inlining.
- This affects currently only functions explicitly marked as
- inline (or methods defined within the class definition for C++).
- The original default value of 10000 was arbitrary and caused
- significant compile-time performance regressions. */
+/* The single function inlining limit. This is the maximum size
+ of a function counted in internal gcc instructions (not in
+ real machine instructions) that is eligible for inlining
+ by the tree inliner.
+ The default value is 300.
+ Only functions marked inline (or methods defined in the class
+ definition for C++) are affected by this, unless you set the
+ -finline-functions (included in -O3) compiler option.
+ There are more restrictions to inlining: If inlined functions
+ call other functions, the already inlined instructions are
+ counted and once the recursive inline limit (see
+ "max-inline-insns" parameter) is exceeded, the acceptable size
+ gets decreased. */
+DEFPARAM (PARAM_MAX_INLINE_INSNS_SINGLE,
+ "max-inline-insns-single",
+ "The maximum number of instructions in a single function eligible for inlining",
+ 300)
+
+/* The single function inlining limit for functions that are
+ inlined by virtue of -finline-functions (-O3).
+ This limit should be chosen to be below or equal to the limit
+ that is applied to functions marked inlined (or defined in the
+ class declaration in C++) given by the "max-inline-insns-single"
+ parameter.
+ The default value is 300. */
+DEFPARAM (PARAM_MAX_INLINE_INSNS_AUTO,
+ "max-inline-insns-auto",
+ "The maximum number of instructions when automatically inlining",
+ 300)
+
+/* The repeated inlining limit. After this number of instructions
+ (in the internal gcc representation, not real machine instructions)
+ got inlined by repeated inlining, gcc starts to decrease the maximum
+ number of inlinable instructions in the tree inliner.
+ This is done by a linear function, see "max-inline-slope" parameter.
+ It is necessary in order to limit the compile-time resources, that
+ could otherwise become very high.
+ It is recommended to set this value to twice the value of the single
+ function limit (set by the "max-inline-insns-single" parameter) or
+ higher. The default value is 600.
+ Higher values mean that more inlining is done, resulting in
+ better performance of the code, at the expense of higher
+ compile-time resource (time, memory) requirements and larger
+ binaries. */
DEFPARAM (PARAM_MAX_INLINE_INSNS,
"max-inline-insns",
- "The maximum number of instructions in a function that is eligible for inlining",
+ "The maximum number of instructions by repeated inlining before gcc starts to throttle inlining",
+ 600)
+
+/* After the repeated inline limit has been exceeded (see
+ "max-inline-insns" parameter), a linear function is used to
+ decrease the size of single functions eligible for inlining.
+ The slope of this linear function is given the negative
+ reciprocal value (-1/x) of this parameter.
+ The default value is 32.
+ This linear function is used until it falls below a minimum
+ value specified by the "min-inline-insns" parameter. */
+DEFPARAM (PARAM_MAX_INLINE_SLOPE,
+ "max-inline-slope",
+ "The slope of the linear function throttling inlining after the recursive inlining limit has been reached is given by the negative reciprocal value of this parameter",
+ 32)
+
+/* When gcc has inlined so many instructions (by repeated
+ inlining) that the throttling limits the inlining very much,
+ inlining for very small functions is still desirable to
+ achieve good runtime performance. The size of single functions
+ (measured in gcc instructions) which will still be eligible for
+ inlining then is given by this parameter. It defaults to 130.
+ Only much later (after exceeding 128 times the recursive limit)
+ inlining is cut down completely. */
+DEFPARAM (PARAM_MIN_INLINE_INSNS,
+ "min-inline-insns",
+ "The number of instructions in a single functions still eligible to inlining after a lot recursive inlining",
+ 130)
+
+/* For languages that (still) use the RTL inliner, we can specify
+ limits for the RTL inliner separately.
+ The parameter here defines the maximum number of RTL instructions
+ a function may have to be eligible for inlining in the RTL inliner.
+ The default value is 600. */
+DEFPARAM (PARAM_MAX_INLINE_INSNS_RTL,
+ "max-inline-insns-rtl",
+ "The maximum number of instructions for the RTL inliner",
600)
/* The maximum number of instructions to consider when looking for an
@@ -84,11 +158,87 @@ DEFPARAM(PARAM_MAX_GCSE_MEMORY,
"max-gcse-memory",
"The maximum amount of memory to be allocated by GCSE",
50 * 1024 * 1024)
-/* The number of repetitions of copy/const prop and PRE to run. */
+/* The number of repetitions of copy/const prop and PRE to run. */
DEFPARAM(PARAM_MAX_GCSE_PASSES,
"max-gcse-passes",
"The maximum number of passes to make when doing GCSE",
1)
+
+/* This parameter limits the number of insns in a loop that will be unrolled,
+ and by how much the loop is unrolled. */
+DEFPARAM(PARAM_MAX_UNROLLED_INSNS,
+ "max-unrolled-insns",
+ "The maximum number of instructions to consider to unroll in a loop",
+ 100)
+
+DEFPARAM(HOT_BB_COUNT_FRACTION,
+ "hot-bb-count-fraction",
+ "Select fraction of the maximal count of repetitions of basic block in \
+program given basic block needs to have to be considered hot",
+ 10000)
+DEFPARAM(HOT_BB_FREQUENCY_FRACTION,
+ "hot-bb-frequency-fraction",
+ "Select fraction of the maximal frequency of executions of basic \
+block in function given basic block needs to have to be considered hot",
+ 1000)
+DEFPARAM(TRACER_DYNAMIC_COVERAGE_FEEDBACK,
+ "tracer-dynamic-coverage-feedback",
+ "The percentage of function, weighted by execution frequency, that \
+must be covered by trace formation. Used when profile feedback is available",
+ 95)
+DEFPARAM(TRACER_DYNAMIC_COVERAGE,
+ "tracer-dynamic-coverage",
+ "The percentage of function, weighted by execution frequency, that \
+must be covered by trace formation. Used when profile feedback is not available",
+ 75)
+DEFPARAM(TRACER_MAX_CODE_GROWTH,
+ "tracer-max-code-growth",
+ "Maximal code growth caused by tail duplication (in percents)",
+ 100)
+DEFPARAM(TRACER_MIN_BRANCH_RATIO,
+ "tracer-min-branch-ratio",
+ "Stop reverse growth if the reverse probability of best edge is less \
+than this threshold (in percents)",
+ 10)
+DEFPARAM(TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK,
+ "tracer-min-branch-probability-feedback",
+ "Stop forward growth if the probability of best edge is less than \
+this threshold (in percents). Used when profile feedback is available",
+ 30)
+DEFPARAM(TRACER_MIN_BRANCH_PROBABILITY,
+ "tracer-min-branch-probability",
+ "Stop forward growth if the probability of best edge is less than \
+this threshold (in percents). Used when profile feedback is not available",
+ 50)
+
+/* The maximum number of incoming edges to consider for crossjumping. */
+DEFPARAM(PARAM_MAX_CROSSJUMP_EDGES,
+ "max-crossjump-edges",
+ "The maximum number of incoming edges to consider for crossjumping",
+ 100)
+
+#ifdef ENABLE_GC_ALWAYS_COLLECT
+# define GGC_MIN_EXPAND_DEFAULT 0
+# define GGC_MIN_HEAPSIZE_DEFAULT 0
+#else
+# define GGC_MIN_EXPAND_DEFAULT 30
+# define GGC_MIN_HEAPSIZE_DEFAULT 4096
+#endif
+
+DEFPARAM(GGC_MIN_EXPAND,
+ "ggc-min-expand",
+ "Minimum heap expansion to trigger garbage collection, as \
+a percentage of the total size of the heap.",
+ GGC_MIN_EXPAND_DEFAULT)
+
+DEFPARAM(GGC_MIN_HEAPSIZE,
+ "ggc-min-heapsize",
+ "Minimum heap size before we start collecting garbage, in kilobytes.",
+ GGC_MIN_HEAPSIZE_DEFAULT)
+
+#undef GGC_MIN_EXPAND_DEFAULT
+#undef GGC_MIN_HEAPSIZE_DEFAULT
+
/*
Local variables:
mode:c
diff --git a/contrib/gcc/params.h b/contrib/gcc/params.h
index 33eec39..caddf85 100644
--- a/contrib/gcc/params.h
+++ b/contrib/gcc/params.h
@@ -59,7 +59,7 @@ extern param_info *compiler_params;
/* Add the N PARAMS to the current list of compiler parameters. */
-extern void add_params
+extern void add_params
PARAMS ((const param_info params[], size_t n));
/* Set the VALUE associated with the parameter given by NAME. */
@@ -75,17 +75,27 @@ typedef enum compiler_param
#define DEFPARAM(enumerator, option, msgid, default) \
enumerator,
#include "params.def"
-#undef DEFPARAM
+#undef DEFPARAM
LAST_PARAM
} compiler_param;
/* The value of the parameter given by ENUM. */
#define PARAM_VALUE(ENUM) \
(compiler_params[(int) ENUM].value)
-
+
/* Macros for the various parameters. */
+#define MAX_INLINE_INSNS_SINGLE \
+ PARAM_VALUE (PARAM_MAX_INLINE_INSNS_SINGLE)
#define MAX_INLINE_INSNS \
PARAM_VALUE (PARAM_MAX_INLINE_INSNS)
+#define MAX_INLINE_SLOPE \
+ PARAM_VALUE (PARAM_MAX_INLINE_SLOPE)
+#define MIN_INLINE_INSNS \
+ PARAM_VALUE (PARAM_MIN_INLINE_INSNS)
+#define MAX_INLINE_INSNS_AUTO \
+ PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO)
+#define MAX_INLINE_INSNS_RTL \
+ PARAM_VALUE (PARAM_MAX_INLINE_INSNS_RTL)
#define MAX_DELAY_SLOT_INSN_SEARCH \
PARAM_VALUE (PARAM_MAX_DELAY_SLOT_INSN_SEARCH)
#define MAX_DELAY_SLOT_LIVE_SEARCH \
@@ -96,4 +106,6 @@ typedef enum compiler_param
((size_t) PARAM_VALUE (PARAM_MAX_GCSE_MEMORY))
#define MAX_GCSE_PASSES \
PARAM_VALUE (PARAM_MAX_GCSE_PASSES)
+#define MAX_UNROLLED_INSNS \
+ PARAM_VALUE (PARAM_MAX_UNROLLED_INSNS)
#endif /* ! GCC_PARAMS_H */
diff --git a/contrib/gcc/partition.h b/contrib/gcc/partition.h
index 851422a..5d3623f 100644
--- a/contrib/gcc/partition.h
+++ b/contrib/gcc/partition.h
@@ -1,5 +1,5 @@
/* List implementation of a partition of consecutive integers.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by CodeSourcery, LLC.
This file is part of GCC.
@@ -40,7 +40,7 @@
extern "C" {
#endif /* __cplusplus */
-#include <ansidecl.h>
+#include "ansidecl.h"
#include <stdio.h>
struct partition_elem
@@ -78,4 +78,8 @@ extern void partition_print PARAMS((partition,
#define partition_find(partition__, element__) \
((partition__)->elements[(element__)].class_element)
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
#endif /* _PARTITION_H */
diff --git a/contrib/gcc/physmem.c b/contrib/gcc/physmem.c
new file mode 100644
index 0000000..f64e07c
--- /dev/null
+++ b/contrib/gcc/physmem.c
@@ -0,0 +1,305 @@
+/* Calculate the size of physical memory.
+ Copyright 2000, 2001, 2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if HAVE_SYS_PSTAT_H
+# include <sys/pstat.h>
+#endif
+
+#if HAVE_SYS_SYSMP_H
+# include <sys/sysmp.h>
+#endif
+
+#if HAVE_SYS_SYSINFO_H && HAVE_MACHINE_HAL_SYSINFO_H
+# include <sys/sysinfo.h>
+# include <machine/hal_sysinfo.h>
+#endif
+
+#if HAVE_SYS_TABLE_H
+# include <sys/table.h>
+#endif
+
+#include <sys/types.h>
+
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#if HAVE_SYS_SYSCTL_H
+# include <sys/sysctl.h>
+#endif
+
+#if HAVE_SYS_SYSTEMCFG_H
+# include <sys/systemcfg.h>
+#endif
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+/* MEMORYSTATUSEX is missing from older windows headers, so define
+ a local replacement. */
+typedef struct
+{
+ DWORD dwLength;
+ DWORD dwMemoryLoad;
+ DWORDLONG ullTotalPhys;
+ DWORDLONG ullAvailPhys;
+ DWORDLONG ullTotalPageFile;
+ DWORDLONG ullAvailPageFile;
+ DWORDLONG ullTotalVirtual;
+ DWORDLONG ullAvailVirtual;
+ DWORDLONG ullAvailExtendedVirtual;
+} lMEMORYSTATUSEX;
+typedef WINBOOL (WINAPI *PFN_MS_EX) (lMEMORYSTATUSEX*);
+#endif
+
+#include "libiberty.h"
+
+/* Return the total amount of physical memory. */
+double
+physmem_total ()
+{
+#if defined _SC_PHYS_PAGES && defined _SC_PAGESIZE
+ { /* This works on linux-gnu, solaris2 and cygwin. */
+ double pages = sysconf (_SC_PHYS_PAGES);
+ double pagesize = sysconf (_SC_PAGESIZE);
+ if (0 <= pages && 0 <= pagesize)
+ return pages * pagesize;
+ }
+#endif
+
+#if HAVE_PSTAT_GETSTATIC
+ { /* This works on hpux11. */
+ struct pst_static pss;
+ if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0))
+ {
+ double pages = pss.physical_memory;
+ double pagesize = pss.page_size;
+ if (0 <= pages && 0 <= pagesize)
+ return pages * pagesize;
+ }
+ }
+#endif
+
+#if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
+ { /* This works on irix6. */
+ struct rminfo realmem;
+ if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0)
+ {
+ double pagesize = sysconf (_SC_PAGESIZE);
+ double pages = realmem.physmem;
+ if (0 <= pages && 0 <= pagesize)
+ return pages * pagesize;
+ }
+ }
+#endif
+
+#if HAVE_GETSYSINFO && defined GSI_PHYSMEM
+ { /* This works on Tru64 UNIX V4/5. */
+ int physmem;
+
+ if (getsysinfo (GSI_PHYSMEM, (caddr_t) &physmem, sizeof (physmem),
+ NULL, NULL, NULL) == 1)
+ {
+ double kbytes = physmem;
+
+ if (0 <= kbytes)
+ return kbytes * 1024.0;
+ }
+ }
+#endif
+
+#if HAVE_SYSCTL && defined HW_PHYSMEM
+ { /* This works on *bsd and darwin. */
+ unsigned int physmem;
+ size_t len = sizeof physmem;
+ static int mib[2] = { CTL_HW, HW_PHYSMEM };
+
+ if (sysctl (mib, ARRAY_SIZE (mib), &physmem, &len, NULL, 0) == 0
+ && len == sizeof (physmem))
+ return (double) physmem;
+ }
+#endif
+
+#if HAVE__SYSTEM_CONFIGURATION
+ /* This works on AIX 4.3.3+. */
+ return _system_configuration.physmem;
+#endif
+
+#if defined _WIN32
+ { /* this works on windows */
+ PFN_MS_EX pfnex;
+ HMODULE h = GetModuleHandle ("kernel32.dll");
+
+ if (!h)
+ return 0.0;
+
+ /* Use GlobalMemoryStatusEx if available. */
+ if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx")))
+ {
+ lMEMORYSTATUSEX lms_ex;
+ lms_ex.dwLength = sizeof lms_ex;
+ if (!pfnex (&lms_ex))
+ return 0.0;
+ return (double) lms_ex.ullTotalPhys;
+ }
+
+ /* Fall back to GlobalMemoryStatus which is always available.
+ but returns wrong results for physical memory > 4GB. */
+ else
+ {
+ MEMORYSTATUS ms;
+ GlobalMemoryStatus (&ms);
+ return (double) ms.dwTotalPhys;
+ }
+ }
+#endif
+
+ /* Return 0 if we can't determine the value. */
+ return 0;
+}
+
+/* Return the amount of physical memory available. */
+double
+physmem_available ()
+{
+#if defined _SC_AVPHYS_PAGES && defined _SC_PAGESIZE
+ { /* This works on linux-gnu, solaris2 and cygwin. */
+ double pages = sysconf (_SC_AVPHYS_PAGES);
+ double pagesize = sysconf (_SC_PAGESIZE);
+ if (0 <= pages && 0 <= pagesize)
+ return pages * pagesize;
+ }
+#endif
+
+#if HAVE_PSTAT_GETSTATIC && HAVE_PSTAT_GETDYNAMIC
+ { /* This works on hpux11. */
+ struct pst_static pss;
+ struct pst_dynamic psd;
+ if (0 <= pstat_getstatic (&pss, sizeof pss, 1, 0)
+ && 0 <= pstat_getdynamic (&psd, sizeof psd, 1, 0))
+ {
+ double pages = psd.psd_free;
+ double pagesize = pss.page_size;
+ if (0 <= pages && 0 <= pagesize)
+ return pages * pagesize;
+ }
+ }
+#endif
+
+#if HAVE_SYSMP && defined MP_SAGET && defined MPSA_RMINFO && defined _SC_PAGESIZE
+ { /* This works on irix6. */
+ struct rminfo realmem;
+ if (sysmp (MP_SAGET, MPSA_RMINFO, &realmem, sizeof realmem) == 0)
+ {
+ double pagesize = sysconf (_SC_PAGESIZE);
+ double pages = realmem.availrmem;
+ if (0 <= pages && 0 <= pagesize)
+ return pages * pagesize;
+ }
+ }
+#endif
+
+#if HAVE_TABLE && defined TBL_VMSTATS
+ { /* This works on Tru64 UNIX V4/5. */
+ struct tbl_vmstats vmstats;
+
+ if (table (TBL_VMSTATS, 0, &vmstats, 1, sizeof (vmstats)) == 1)
+ {
+ double pages = vmstats.free_count;
+ double pagesize = vmstats.pagesize;
+
+ if (0 <= pages && 0 <= pagesize)
+ return pages * pagesize;
+ }
+ }
+#endif
+
+#if HAVE_SYSCTL && defined HW_USERMEM
+ { /* This works on *bsd and darwin. */
+ unsigned int usermem;
+ size_t len = sizeof usermem;
+ static int mib[2] = { CTL_HW, HW_USERMEM };
+
+ if (sysctl (mib, ARRAY_SIZE (mib), &usermem, &len, NULL, 0) == 0
+ && len == sizeof (usermem))
+ return (double) usermem;
+ }
+#endif
+
+#if defined _WIN32
+ { /* this works on windows */
+ PFN_MS_EX pfnex;
+ HMODULE h = GetModuleHandle ("kernel32.dll");
+
+ if (!h)
+ return 0.0;
+
+ /* Use GlobalMemoryStatusEx if available. */
+ if ((pfnex = (PFN_MS_EX) GetProcAddress (h, "GlobalMemoryStatusEx")))
+ {
+ lMEMORYSTATUSEX lms_ex;
+ lms_ex.dwLength = sizeof lms_ex;
+ if (!pfnex (&lms_ex))
+ return 0.0;
+ return (double) lms_ex.ullAvailPhys;
+ }
+
+ /* Fall back to GlobalMemoryStatus which is always available.
+ but returns wrong results for physical memory > 4GB */
+ else
+ {
+ MEMORYSTATUS ms;
+ GlobalMemoryStatus (&ms);
+ return (double) ms.dwAvailPhys;
+ }
+ }
+#endif
+
+ /* Guess 25% of physical memory. */
+ return physmem_total () / 4;
+}
+
+
+#if DEBUG
+
+# include <stdio.h>
+# include <stdlib.h>
+
+int
+main ()
+{
+ printf ("%12.f %12.f\n", physmem_total (), physmem_available ());
+ exit (0);
+}
+
+#endif /* DEBUG */
+
+/*
+Local Variables:
+compile-command: "gcc -DDEBUG -DHAVE_CONFIG_H -I.. -g -O -Wall -W physmem.c"
+End:
+*/
diff --git a/contrib/gcc/predict.c b/contrib/gcc/predict.c
index bcafef2..3ad11e7 100644
--- a/contrib/gcc/predict.c
+++ b/contrib/gcc/predict.c
@@ -45,23 +45,42 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "recog.h"
#include "expr.h"
#include "predict.h"
+#include "profile.h"
+#include "real.h"
+#include "params.h"
+#include "target.h"
+#include "loop.h"
+
+/* real constants: 0, 1, 1-1/REG_BR_PROB_BASE, REG_BR_PROB_BASE,
+ 1/REG_BR_PROB_BASE, 0.5, BB_FREQ_MAX. */
+static REAL_VALUE_TYPE real_zero, real_one, real_almost_one, real_br_prob_base,
+ real_inv_br_prob_base, real_one_half, real_bb_freq_max;
/* Random guesstimation given names. */
-#define PROB_NEVER (0)
#define PROB_VERY_UNLIKELY (REG_BR_PROB_BASE / 10 - 1)
-#define PROB_UNLIKELY (REG_BR_PROB_BASE * 4 / 10 - 1)
#define PROB_EVEN (REG_BR_PROB_BASE / 2)
-#define PROB_LIKELY (REG_BR_PROB_BASE - PROB_UNLIKELY)
#define PROB_VERY_LIKELY (REG_BR_PROB_BASE - PROB_VERY_UNLIKELY)
#define PROB_ALWAYS (REG_BR_PROB_BASE)
+static bool predicted_by_p PARAMS ((basic_block,
+ enum br_predictor));
static void combine_predictions_for_insn PARAMS ((rtx, basic_block));
static void dump_prediction PARAMS ((enum br_predictor, int,
basic_block, int));
static void estimate_loops_at_level PARAMS ((struct loop *loop));
-static void propagate_freq PARAMS ((basic_block));
+static void propagate_freq PARAMS ((struct loop *));
static void estimate_bb_frequencies PARAMS ((struct loops *));
static void counts_to_freqs PARAMS ((void));
+static void process_note_predictions PARAMS ((basic_block, int *,
+ dominance_info,
+ dominance_info));
+static void process_note_prediction PARAMS ((basic_block, int *,
+ dominance_info,
+ dominance_info, int, int));
+static bool last_basic_block_p PARAMS ((basic_block));
+static void compute_function_frequency PARAMS ((void));
+static void choose_function_section PARAMS ((void));
+static bool can_predict_insn_p PARAMS ((rtx));
/* Information we hold about each branch predictor.
Filled using information from predict.def. */
@@ -91,6 +110,71 @@ static const struct predictor_info predictor_info[]= {
};
#undef DEF_PREDICTOR
+/* Return true in case BB can be CPU intensive and should be optimized
+ for maximal perofmrance. */
+
+bool
+maybe_hot_bb_p (bb)
+ basic_block bb;
+{
+ if (profile_info.count_profiles_merged
+ && flag_branch_probabilities
+ && (bb->count
+ < profile_info.max_counter_in_program
+ / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
+ return false;
+ if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
+ return false;
+ return true;
+}
+
+/* Return true in case BB is cold and should be optimized for size. */
+
+bool
+probably_cold_bb_p (bb)
+ basic_block bb;
+{
+ if (profile_info.count_profiles_merged
+ && flag_branch_probabilities
+ && (bb->count
+ < profile_info.max_counter_in_program
+ / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
+ return true;
+ if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
+ return true;
+ return false;
+}
+
+/* Return true in case BB is probably never executed. */
+bool
+probably_never_executed_bb_p (bb)
+ basic_block bb;
+{
+ if (profile_info.count_profiles_merged
+ && flag_branch_probabilities)
+ return ((bb->count + profile_info.count_profiles_merged / 2)
+ / profile_info.count_profiles_merged) == 0;
+ return false;
+}
+
+/* Return true if the one of outgoing edges is already predicted by
+ PREDICTOR. */
+
+static bool
+predicted_by_p (bb, predictor)
+ basic_block bb;
+ enum br_predictor predictor;
+{
+ rtx note;
+ if (!INSN_P (bb->end))
+ return false;
+ for (note = REG_NOTES (bb->end); note; note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_BR_PRED
+ && INTVAL (XEXP (XEXP (note, 0), 0)) == (int)predictor)
+ return true;
+ return false;
+}
+
void
predict_insn (insn, predictor, probability)
rtx insn;
@@ -99,6 +183,8 @@ predict_insn (insn, predictor, probability)
{
if (!any_condjump_p (insn))
abort ();
+ if (!flag_guess_branch_prob)
+ return;
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_BR_PRED,
@@ -147,6 +233,18 @@ predict_edge (e, predictor, probability)
predict_insn (last_insn, predictor, probability);
}
+/* Return true when we can store prediction on insn INSN.
+ At the moment we represent predictions only on conditional
+ jumps, not at computed jump or other complicated cases. */
+static bool
+can_predict_insn_p (insn)
+ rtx insn;
+{
+ return (GET_CODE (insn) == JUMP_INSN
+ && any_condjump_p (insn)
+ && BLOCK_FOR_INSN (insn)->succ->succ_next);
+}
+
/* Predict edge E by given predictor if possible. */
void
@@ -194,7 +292,7 @@ dump_prediction (predictor, probability, bb, used)
if (!rtl_dump_file)
return;
- while (e->flags & EDGE_FALLTHRU)
+ while (e && (e->flags & EDGE_FALLTHRU))
e = e->succ_next;
fprintf (rtl_dump_file, " %s heuristics%s: %.1f%%",
@@ -205,9 +303,12 @@ dump_prediction (predictor, probability, bb, used)
{
fprintf (rtl_dump_file, " exec ");
fprintf (rtl_dump_file, HOST_WIDEST_INT_PRINT_DEC, bb->count);
- fprintf (rtl_dump_file, " hit ");
- fprintf (rtl_dump_file, HOST_WIDEST_INT_PRINT_DEC, e->count);
- fprintf (rtl_dump_file, " (%.1f%%)", e->count * 100.0 / bb->count);
+ if (e)
+ {
+ fprintf (rtl_dump_file, " hit ");
+ fprintf (rtl_dump_file, HOST_WIDEST_INT_PRINT_DEC, e->count);
+ fprintf (rtl_dump_file, " (%.1f%%)", e->count * 100.0 / bb->count);
+ }
}
fprintf (rtl_dump_file, "\n");
@@ -289,10 +390,10 @@ combine_predictions_for_insn (insn, bb)
dump_prediction (predictor, probability, bb,
!first_match || best_predictor == predictor);
- *pnote = XEXP (*pnote, 1);
+ *pnote = XEXP (*pnote, 1);
}
else
- pnote = &XEXP (*pnote, 1);
+ pnote = &XEXP (*pnote, 1);
}
if (!prob_note)
@@ -322,101 +423,95 @@ void
estimate_probability (loops_info)
struct loops *loops_info;
{
- sbitmap *dominators, *post_dominators;
+ dominance_info dominators, post_dominators;
+ basic_block bb;
int i;
- int found_noreturn = 0;
- dominators = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
- post_dominators = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
- calculate_dominance_info (NULL, dominators, CDI_DOMINATORS);
- calculate_dominance_info (NULL, post_dominators, CDI_POST_DOMINATORS);
+ connect_infinite_loops_to_exit ();
+ dominators = calculate_dominance_info (CDI_DOMINATORS);
+ post_dominators = calculate_dominance_info (CDI_POST_DOMINATORS);
/* Try to predict out blocks in a loop that are not part of a
natural loop. */
- for (i = 0; i < loops_info->num; i++)
+ for (i = 1; i < loops_info->num; i++)
{
+ basic_block bb, *bbs;
int j;
int exits;
- struct loop *loop = &loops_info->array[i];
+ struct loop *loop = loops_info->parray[i];
flow_loop_scan (loops_info, loop, LOOP_EXIT_EDGES);
exits = loop->num_exits;
- for (j = loop->first->index; j <= loop->last->index; ++j)
- if (TEST_BIT (loop->nodes, j))
- {
- int header_found = 0;
- edge e;
-
- /* Loop branch heuristics - predict an edge back to a
- loop's head as taken. */
- for (e = BASIC_BLOCK(j)->succ; e; e = e->succ_next)
- if (e->dest == loop->header
- && e->src == loop->latch)
- {
- header_found = 1;
- predict_edge_def (e, PRED_LOOP_BRANCH, TAKEN);
- }
+ bbs = get_loop_body (loop);
+ for (j = 0; j < loop->num_nodes; j++)
+ {
+ int header_found = 0;
+ edge e;
- /* Loop exit heuristics - predict an edge exiting the loop if the
- conditinal has no loop header successors as not taken. */
- if (!header_found)
- for (e = BASIC_BLOCK(j)->succ; e; e = e->succ_next)
- if (e->dest->index < 0
- || !TEST_BIT (loop->nodes, e->dest->index))
- predict_edge
- (e, PRED_LOOP_EXIT,
- (REG_BR_PROB_BASE
- - predictor_info [(int) PRED_LOOP_EXIT].hitrate)
- / exits);
- }
+ bb = bbs[j];
+
+ /* Bypass loop heuristics on continue statement. These
+ statements construct loops via "non-loop" constructs
+ in the source language and are better to be handled
+ separately. */
+ if (!can_predict_insn_p (bb->end)
+ || predicted_by_p (bb, PRED_CONTINUE))
+ continue;
+
+ /* Loop branch heuristics - predict an edge back to a
+ loop's head as taken. */
+ for (e = bb->succ; e; e = e->succ_next)
+ if (e->dest == loop->header
+ && e->src == loop->latch)
+ {
+ header_found = 1;
+ predict_edge_def (e, PRED_LOOP_BRANCH, TAKEN);
+ }
+
+ /* Loop exit heuristics - predict an edge exiting the loop if the
+ conditinal has no loop header successors as not taken. */
+ if (!header_found)
+ for (e = bb->succ; e; e = e->succ_next)
+ if (e->dest->index < 0
+ || !flow_bb_inside_loop_p (loop, e->dest))
+ predict_edge
+ (e, PRED_LOOP_EXIT,
+ (REG_BR_PROB_BASE
+ - predictor_info [(int) PRED_LOOP_EXIT].hitrate)
+ / exits);
+ }
}
/* Attempt to predict conditional jumps using a number of heuristics. */
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
rtx last_insn = bb->end;
rtx cond, earliest;
edge e;
- /* If block has no successor, predict all possible paths to it as
- improbable, as the block contains a call to a noreturn function and
- thus can be executed only once. */
- if (bb->succ == NULL && !found_noreturn)
- {
- int y;
-
- /* ??? Postdominator claims each noreturn block to be postdominated
- by each, so we need to run only once. This needs to be changed
- once postdominace algorithm is updated to say something more
- sane. */
- found_noreturn = 1;
- for (y = 0; y < n_basic_blocks; y++)
- if (!TEST_BIT (post_dominators[y], i))
- for (e = BASIC_BLOCK (y)->succ; e; e = e->succ_next)
- if (e->dest->index >= 0
- && TEST_BIT (post_dominators[e->dest->index], i))
- predict_edge_def (e, PRED_NORETURN, NOT_TAKEN);
- }
-
- if (GET_CODE (last_insn) != JUMP_INSN || ! any_condjump_p (last_insn))
+ if (! can_predict_insn_p (last_insn))
continue;
for (e = bb->succ; e; e = e->succ_next)
{
- /* Predict edges to blocks that return immediately to be
- improbable. These are usually used to signal error states. */
- if (e->dest == EXIT_BLOCK_PTR
- || (e->dest->succ && !e->dest->succ->succ_next
- && e->dest->succ->dest == EXIT_BLOCK_PTR))
- predict_edge_def (e, PRED_ERROR_RETURN, NOT_TAKEN);
+ /* Predict early returns to be probable, as we've already taken
+ care for error returns and other are often used for fast paths
+ trought function. */
+ if ((e->dest == EXIT_BLOCK_PTR
+ || (e->dest->succ && !e->dest->succ->succ_next
+ && e->dest->succ->dest == EXIT_BLOCK_PTR))
+ && !predicted_by_p (bb, PRED_NULL_RETURN)
+ && !predicted_by_p (bb, PRED_CONST_RETURN)
+ && !predicted_by_p (bb, PRED_NEGATIVE_RETURN)
+ && !last_basic_block_p (e->dest))
+ predict_edge_def (e, PRED_EARLY_RETURN, TAKEN);
/* Look for block we are guarding (ie we dominate it,
but it doesn't postdominate us). */
if (e->dest != EXIT_BLOCK_PTR && e->dest != bb
- && TEST_BIT (dominators[e->dest->index], e->src->index)
- && !TEST_BIT (post_dominators[e->src->index], e->dest->index))
+ && dominated_by_p (dominators, e->dest, e->src)
+ && !dominated_by_p (post_dominators, e->src, e->dest))
{
rtx insn;
@@ -527,14 +622,16 @@ estimate_probability (loops_info)
}
/* Attach the combined probability to each conditional jump. */
- for (i = 0; i < n_basic_blocks; i++)
- if (GET_CODE (BLOCK_END (i)) == JUMP_INSN
- && any_condjump_p (BLOCK_END (i)))
- combine_predictions_for_insn (BLOCK_END (i), BASIC_BLOCK (i));
+ FOR_EACH_BB (bb)
+ if (GET_CODE (bb->end) == JUMP_INSN
+ && any_condjump_p (bb->end)
+ && bb->succ->succ_next != NULL)
+ combine_predictions_for_insn (bb->end, bb);
- sbitmap_vector_free (post_dominators);
- sbitmap_vector_free (dominators);
+ free_dominance_info (post_dominators);
+ free_dominance_info (dominators);
+ remove_fake_edges ();
estimate_bb_frequencies (loops_info);
}
@@ -611,13 +708,188 @@ expected_value_to_br_prob ()
}
}
+/* Check whether this is the last basic block of function. Commonly tehre
+ is one extra common cleanup block. */
+static bool
+last_basic_block_p (bb)
+ basic_block bb;
+{
+ if (bb == EXIT_BLOCK_PTR)
+ return false;
+
+ return (bb->next_bb == EXIT_BLOCK_PTR
+ || (bb->next_bb->next_bb == EXIT_BLOCK_PTR
+ && bb->succ && !bb->succ->succ_next
+ && bb->succ->dest->next_bb == EXIT_BLOCK_PTR));
+}
+
+/* Sets branch probabilities according to PREDiction and FLAGS. HEADS[bb->index]
+ should be index of basic block in that we need to alter branch predictions
+ (i.e. the first of our dominators such that we do not post-dominate it)
+ (but we fill this information on demand, so -1 may be there in case this
+ was not needed yet). */
+
+static void
+process_note_prediction (bb, heads, dominators, post_dominators, pred, flags)
+ basic_block bb;
+ int *heads;
+ dominance_info dominators;
+ dominance_info post_dominators;
+ int pred;
+ int flags;
+{
+ edge e;
+ int y;
+ bool taken;
+
+ taken = flags & IS_TAKEN;
+
+ if (heads[bb->index] < 0)
+ {
+ /* This is first time we need this field in heads array; so
+ find first dominator that we do not post-dominate (we are
+ using already known members of heads array). */
+ basic_block ai = bb;
+ basic_block next_ai = get_immediate_dominator (dominators, bb);
+ int head;
+
+ while (heads[next_ai->index] < 0)
+ {
+ if (!dominated_by_p (post_dominators, next_ai, bb))
+ break;
+ heads[next_ai->index] = ai->index;
+ ai = next_ai;
+ next_ai = get_immediate_dominator (dominators, next_ai);
+ }
+ if (!dominated_by_p (post_dominators, next_ai, bb))
+ head = next_ai->index;
+ else
+ head = heads[next_ai->index];
+ while (next_ai != bb)
+ {
+ next_ai = ai;
+ if (heads[ai->index] == ENTRY_BLOCK)
+ ai = ENTRY_BLOCK_PTR;
+ else
+ ai = BASIC_BLOCK (heads[ai->index]);
+ heads[next_ai->index] = head;
+ }
+ }
+ y = heads[bb->index];
+
+ /* Now find the edge that leads to our branch and aply the prediction. */
+
+ if (y == last_basic_block || !can_predict_insn_p (BASIC_BLOCK (y)->end))
+ return;
+ for (e = BASIC_BLOCK (y)->succ; e; e = e->succ_next)
+ if (e->dest->index >= 0
+ && dominated_by_p (post_dominators, e->dest, bb))
+ predict_edge_def (e, pred, taken);
+}
+
+/* Gathers NOTE_INSN_PREDICTIONs in given basic block and turns them
+ into branch probabilities. For description of heads array, see
+ process_note_prediction. */
+
+static void
+process_note_predictions (bb, heads, dominators, post_dominators)
+ basic_block bb;
+ int *heads;
+ dominance_info dominators;
+ dominance_info post_dominators;
+{
+ rtx insn;
+ edge e;
+
+ /* Additionaly, we check here for blocks with no successors. */
+ int contained_noreturn_call = 0;
+ int was_bb_head = 0;
+ int noreturn_block = 1;
+
+ for (insn = bb->end; insn;
+ was_bb_head |= (insn == bb->head), insn = PREV_INSN (insn))
+ {
+ if (GET_CODE (insn) != NOTE)
+ {
+ if (was_bb_head)
+ break;
+ else
+ {
+ /* Noreturn calls cause program to exit, therefore they are
+ always predicted as not taken. */
+ if (GET_CODE (insn) == CALL_INSN
+ && find_reg_note (insn, REG_NORETURN, NULL))
+ contained_noreturn_call = 1;
+ continue;
+ }
+ }
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PREDICTION)
+ {
+ int alg = (int) NOTE_PREDICTION_ALG (insn);
+ /* Process single prediction note. */
+ process_note_prediction (bb,
+ heads,
+ dominators,
+ post_dominators,
+ alg, (int) NOTE_PREDICTION_FLAGS (insn));
+ delete_insn (insn);
+ }
+ }
+ for (e = bb->succ; e; e = e->succ_next)
+ if (!(e->flags & EDGE_FAKE))
+ noreturn_block = 0;
+ if (contained_noreturn_call)
+ {
+ /* This block ended from other reasons than because of return.
+ If it is because of noreturn call, this should certainly not
+ be taken. Otherwise it is probably some error recovery. */
+ process_note_prediction (bb,
+ heads,
+ dominators,
+ post_dominators, PRED_NORETURN, NOT_TAKEN);
+ }
+}
+
+/* Gathers NOTE_INSN_PREDICTIONs and turns them into
+ branch probabilities. */
+
+void
+note_prediction_to_br_prob ()
+{
+ basic_block bb;
+ dominance_info post_dominators, dominators;
+ int *heads;
+
+ /* To enable handling of noreturn blocks. */
+ add_noreturn_fake_exit_edges ();
+ connect_infinite_loops_to_exit ();
+
+ post_dominators = calculate_dominance_info (CDI_POST_DOMINATORS);
+ dominators = calculate_dominance_info (CDI_DOMINATORS);
+
+ heads = xmalloc (sizeof (int) * last_basic_block);
+ memset (heads, -1, sizeof (int) * last_basic_block);
+ heads[ENTRY_BLOCK_PTR->next_bb->index] = last_basic_block;
+
+ /* Process all prediction notes. */
+
+ FOR_EACH_BB (bb)
+ process_note_predictions (bb, heads, dominators, post_dominators);
+
+ free_dominance_info (post_dominators);
+ free_dominance_info (dominators);
+ free (heads);
+
+ remove_fake_edges ();
+}
+
/* This is used to carry information about basic blocks. It is
attached to the AUX field of the standard CFG block. */
typedef struct block_info_def
{
/* Estimated frequency of execution of basic_block. */
- volatile double frequency;
+ REAL_VALUE_TYPE frequency;
/* To keep queue of basic blocks to process. */
basic_block next;
@@ -634,11 +906,8 @@ typedef struct edge_info_def
{
/* In case edge is an loopback edge, the probability edge will be reached
in case header is. Estimated number of iterations of the loop can be
- then computed as 1 / (1 - back_edge_prob).
-
- Volatile is needed to avoid differences in the optimized and unoptimized
- builds on machines where FP registers are wider than double. */
- volatile double back_edge_prob;
+ then computed as 1 / (1 - back_edge_prob). */
+ REAL_VALUE_TYPE back_edge_prob;
/* True if the edge is an loopback edge in the natural loop. */
int back_edge:1;
} *edge_info;
@@ -647,23 +916,22 @@ typedef struct edge_info_def
#define EDGE_INFO(E) ((edge_info) (E)->aux)
/* Helper function for estimate_bb_frequencies.
- Propagate the frequencies for loops headed by HEAD. */
+ Propagate the frequencies for LOOP. */
static void
-propagate_freq (head)
- basic_block head;
+propagate_freq (loop)
+ struct loop *loop;
{
- basic_block bb = head;
- basic_block last = bb;
+ basic_block head = loop->header;
+ basic_block bb;
+ basic_block last;
edge e;
basic_block nextbb;
- int n;
/* For each basic block we need to visit count number of his predecessors
we need to visit first. */
- for (n = 0; n < n_basic_blocks; n++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (n);
if (BLOCK_INFO (bb)->tovisit)
{
int count = 0;
@@ -680,10 +948,14 @@ propagate_freq (head)
}
}
- BLOCK_INFO (head)->frequency = 1;
- for (; bb; bb = nextbb)
+ memcpy (&BLOCK_INFO (head)->frequency, &real_one, sizeof (real_one));
+ last = head;
+ for (bb = head; bb; bb = nextbb)
{
- double cyclic_probability = 0, frequency = 0;
+ REAL_VALUE_TYPE cyclic_probability, frequency;
+
+ memcpy (&cyclic_probability, &real_zero, sizeof (real_zero));
+ memcpy (&frequency, &real_zero, sizeof (real_zero));
nextbb = BLOCK_INFO (bb)->next;
BLOCK_INFO (bb)->next = NULL;
@@ -699,16 +971,42 @@ propagate_freq (head)
for (e = bb->pred; e; e = e->pred_next)
if (EDGE_INFO (e)->back_edge)
- cyclic_probability += EDGE_INFO (e)->back_edge_prob;
+ {
+ REAL_ARITHMETIC (cyclic_probability, PLUS_EXPR,
+ cyclic_probability,
+ EDGE_INFO (e)->back_edge_prob);
+ }
else if (!(e->flags & EDGE_DFS_BACK))
- frequency += (e->probability
- * BLOCK_INFO (e->src)->frequency /
- REG_BR_PROB_BASE);
+ {
+ REAL_VALUE_TYPE tmp;
+
+ /* frequency += (e->probability
+ * BLOCK_INFO (e->src)->frequency /
+ REG_BR_PROB_BASE); */
+
+ REAL_VALUE_FROM_INT (tmp, e->probability, 0,
+ TYPE_MODE (double_type_node));
+ REAL_ARITHMETIC (tmp, MULT_EXPR, tmp,
+ BLOCK_INFO (e->src)->frequency);
+ REAL_ARITHMETIC (tmp, MULT_EXPR, tmp, real_inv_br_prob_base);
+ REAL_ARITHMETIC (frequency, PLUS_EXPR, frequency, tmp);
+ }
+
+ if (REAL_VALUES_IDENTICAL (cyclic_probability, real_zero))
+ memcpy (&BLOCK_INFO (bb)->frequency, &frequency, sizeof (frequency));
+ else
+ {
+ if (REAL_VALUES_LESS (real_almost_one, cyclic_probability))
+ memcpy (&cyclic_probability, &real_almost_one, sizeof (real_zero));
- if (cyclic_probability > 1.0 - 1.0 / REG_BR_PROB_BASE)
- cyclic_probability = 1.0 - 1.0 / REG_BR_PROB_BASE;
+ /* BLOCK_INFO (bb)->frequency = frequency / (1 - cyclic_probability)
+ */
- BLOCK_INFO (bb)->frequency = frequency / (1 - cyclic_probability);
+ REAL_ARITHMETIC (cyclic_probability, MINUS_EXPR, real_one,
+ cyclic_probability);
+ REAL_ARITHMETIC (BLOCK_INFO (bb)->frequency,
+ RDIV_EXPR, frequency, cyclic_probability);
+ }
}
BLOCK_INFO (bb)->tovisit = 0;
@@ -716,9 +1014,20 @@ propagate_freq (head)
/* Compute back edge frequencies. */
for (e = bb->succ; e; e = e->succ_next)
if (e->dest == head)
- EDGE_INFO (e)->back_edge_prob
- = ((e->probability * BLOCK_INFO (bb)->frequency)
- / REG_BR_PROB_BASE);
+ {
+ REAL_VALUE_TYPE tmp;
+
+ /* EDGE_INFO (e)->back_edge_prob
+ = ((e->probability * BLOCK_INFO (bb)->frequency)
+ / REG_BR_PROB_BASE); */
+ REAL_VALUE_FROM_INT (tmp, e->probability, 0,
+ TYPE_MODE (double_type_node));
+ REAL_ARITHMETIC (tmp, MULT_EXPR, tmp,
+ BLOCK_INFO (bb)->frequency);
+ REAL_ARITHMETIC (EDGE_INFO (e)->back_edge_prob,
+ MULT_EXPR, tmp, real_inv_br_prob_base);
+
+ }
/* Propagate to successor blocks. */
for (e = bb->succ; e; e = e->succ_next)
@@ -745,41 +1054,28 @@ static void
estimate_loops_at_level (first_loop)
struct loop *first_loop;
{
- struct loop *l, *loop = first_loop;
+ struct loop *loop;
for (loop = first_loop; loop; loop = loop->next)
{
- int n;
edge e;
+ basic_block *bbs;
+ int i;
estimate_loops_at_level (loop->inner);
-
- /* Find current loop back edge and mark it. */
- for (e = loop->latch->succ; e->dest != loop->header; e = e->succ_next)
- ;
-
- EDGE_INFO (e)->back_edge = 1;
-
- /* In case the loop header is shared, ensure that it is the last
- one sharing the same header, so we avoid redundant work. */
- if (loop->shared)
+
+ if (loop->latch->succ) /* Do not do this for dummy function loop. */
{
- for (l = loop->next; l; l = l->next)
- if (l->header == loop->header)
- break;
-
- if (l)
- continue;
- }
-
- /* Now merge all nodes of all loops with given header as not visited. */
- for (l = loop->shared ? first_loop : loop; l != loop->next; l = l->next)
- if (loop->header == l->header)
- EXECUTE_IF_SET_IN_SBITMAP (l->nodes, 0, n,
- BLOCK_INFO (BASIC_BLOCK (n))->tovisit = 1
- );
-
- propagate_freq (loop->header);
+ /* Find current loop back edge and mark it. */
+ e = loop_latch_edge (loop);
+ EDGE_INFO (e)->back_edge = 1;
+ }
+
+ bbs = get_loop_body (loop);
+ for (i = 0; i < loop->num_nodes; i++)
+ BLOCK_INFO (bbs[i])->tovisit = 1;
+ free (bbs);
+ propagate_freq (loop);
}
}
@@ -789,24 +1085,13 @@ static void
counts_to_freqs ()
{
HOST_WIDEST_INT count_max = 1;
- int i;
-
- for (i = 0; i < n_basic_blocks; i++)
- count_max = MAX (BASIC_BLOCK (i)->count, count_max);
-
- for (i = -2; i < n_basic_blocks; i++)
- {
- basic_block bb;
+ basic_block bb;
- if (i == -2)
- bb = ENTRY_BLOCK_PTR;
- else if (i == -1)
- bb = EXIT_BLOCK_PTR;
- else
- bb = BASIC_BLOCK (i);
+ FOR_EACH_BB (bb)
+ count_max = MAX (bb->count, count_max);
- bb->frequency = (bb->count * BB_FREQ_MAX + count_max / 2) / count_max;
- }
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ bb->frequency = (bb->count * BB_FREQ_MAX + count_max / 2) / count_max;
}
/* Return true if function is likely to be expensive, so there is no point to
@@ -819,7 +1104,7 @@ expensive_function_p (threshold)
int threshold;
{
unsigned int sum = 0;
- int i;
+ basic_block bb;
unsigned int limit;
/* We can not compute accurately for large thresholds due to scaled
@@ -832,12 +1117,11 @@ expensive_function_p (threshold)
is available and function has not been executed at all. */
if (ENTRY_BLOCK_PTR->frequency == 0)
return true;
-
+
/* Maximally BB_FREQ_MAX^2 so overflow won't happen. */
limit = ENTRY_BLOCK_PTR->frequency * threshold;
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
rtx insn;
for (insn = bb->head; insn != NEXT_INSN (bb->end);
@@ -859,118 +1143,140 @@ static void
estimate_bb_frequencies (loops)
struct loops *loops;
{
- int i;
- double freq_max = 0;
+ basic_block bb;
+ REAL_VALUE_TYPE freq_max;
+ enum machine_mode double_mode = TYPE_MODE (double_type_node);
- mark_dfs_back_edges ();
if (flag_branch_probabilities)
+ counts_to_freqs ();
+ else
{
- counts_to_freqs ();
- return;
- }
+ REAL_VALUE_FROM_INT (real_zero, 0, 0, double_mode);
+ REAL_VALUE_FROM_INT (real_one, 1, 0, double_mode);
+ REAL_VALUE_FROM_INT (real_br_prob_base, REG_BR_PROB_BASE, 0, double_mode);
+ REAL_VALUE_FROM_INT (real_bb_freq_max, BB_FREQ_MAX, 0, double_mode);
+ REAL_VALUE_FROM_INT (real_one_half, 2, 0, double_mode);
+ REAL_ARITHMETIC (real_one_half, RDIV_EXPR, real_one, real_one_half);
+ REAL_ARITHMETIC (real_inv_br_prob_base, RDIV_EXPR, real_one, real_br_prob_base);
+ REAL_ARITHMETIC (real_almost_one, MINUS_EXPR, real_one, real_inv_br_prob_base);
+
+ mark_dfs_back_edges ();
+ /* Fill in the probability values in flowgraph based on the REG_BR_PROB
+ notes. */
+ FOR_EACH_BB (bb)
+ {
+ rtx last_insn = bb->end;
- /* Fill in the probability values in flowgraph based on the REG_BR_PROB
- notes. */
- for (i = 0; i < n_basic_blocks; i++)
- {
- rtx last_insn = BLOCK_END (i);
- int probability;
- edge fallthru, branch;
+ if (!can_predict_insn_p (last_insn))
+ {
+ /* We can predict only conditional jumps at the moment.
+ Expect each edge to be equally probable.
+ ?? In the future we want to make abnormal edges improbable. */
+ int nedges = 0;
+ edge e;
+
+ for (e = bb->succ; e; e = e->succ_next)
+ {
+ nedges++;
+ if (e->probability != 0)
+ break;
+ }
+ if (!e)
+ for (e = bb->succ; e; e = e->succ_next)
+ e->probability = (REG_BR_PROB_BASE + nedges / 2) / nedges;
+ }
+ }
+
+ ENTRY_BLOCK_PTR->succ->probability = REG_BR_PROB_BASE;
- if (GET_CODE (last_insn) != JUMP_INSN || !any_condjump_p (last_insn)
- /* Avoid handling of conditional jumps jumping to fallthru edge. */
- || BASIC_BLOCK (i)->succ->succ_next == NULL)
+ /* Set up block info for each basic block. */
+ alloc_aux_for_blocks (sizeof (struct block_info_def));
+ alloc_aux_for_edges (sizeof (struct edge_info_def));
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
{
- /* We can predict only conditional jumps at the moment.
- Expect each edge to be equally probable.
- ?? In the future we want to make abnormal edges improbable. */
- int nedges = 0;
edge e;
- for (e = BASIC_BLOCK (i)->succ; e; e = e->succ_next)
+ BLOCK_INFO (bb)->tovisit = 0;
+ for (e = bb->succ; e; e = e->succ_next)
{
- nedges++;
- if (e->probability != 0)
- break;
+ REAL_VALUE_FROM_INT (EDGE_INFO (e)->back_edge_prob,
+ e->probability, 0, double_mode);
+ REAL_ARITHMETIC (EDGE_INFO (e)->back_edge_prob,
+ MULT_EXPR, EDGE_INFO (e)->back_edge_prob,
+ real_inv_br_prob_base);
}
- if (!e)
- for (e = BASIC_BLOCK (i)->succ; e; e = e->succ_next)
- e->probability = (REG_BR_PROB_BASE + nedges / 2) / nedges;
}
- else
- {
- probability = INTVAL (XEXP (find_reg_note (last_insn,
- REG_BR_PROB, 0), 0));
- fallthru = BASIC_BLOCK (i)->succ;
- if (!fallthru->flags & EDGE_FALLTHRU)
- fallthru = fallthru->succ_next;
- branch = BASIC_BLOCK (i)->succ;
- if (branch->flags & EDGE_FALLTHRU)
- branch = branch->succ_next;
-
- branch->probability = probability;
- fallthru->probability = REG_BR_PROB_BASE - probability;
- }
- }
-
- ENTRY_BLOCK_PTR->succ->probability = REG_BR_PROB_BASE;
- /* Set up block info for each basic block. */
- alloc_aux_for_blocks (sizeof (struct block_info_def));
- alloc_aux_for_edges (sizeof (struct edge_info_def));
- for (i = -2; i < n_basic_blocks; i++)
- {
- edge e;
- basic_block bb;
+ /* First compute probabilities locally for each loop from innermost
+ to outermost to examine probabilities for back edges. */
+ estimate_loops_at_level (loops->tree_root);
- if (i == -2)
- bb = ENTRY_BLOCK_PTR;
- else if (i == -1)
- bb = EXIT_BLOCK_PTR;
- else
- bb = BASIC_BLOCK (i);
+ memcpy (&freq_max, &real_zero, sizeof (real_zero));
+ FOR_EACH_BB (bb)
+ if (REAL_VALUES_LESS
+ (freq_max, BLOCK_INFO (bb)->frequency))
+ memcpy (&freq_max, &BLOCK_INFO (bb)->frequency,
+ sizeof (freq_max));
- BLOCK_INFO (bb)->tovisit = 0;
- for (e = bb->succ; e; e = e->succ_next)
- EDGE_INFO (e)->back_edge_prob = ((double) e->probability
- / REG_BR_PROB_BASE);
- }
+ REAL_ARITHMETIC (freq_max, RDIV_EXPR, real_bb_freq_max, freq_max);
- /* First compute probabilities locally for each loop from innermost
- to outermost to examine probabilities for back edges. */
- estimate_loops_at_level (loops->tree_root);
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ {
+ REAL_VALUE_TYPE tmp;
- /* Now fake loop around whole function to finalize probabilities. */
- for (i = 0; i < n_basic_blocks; i++)
- BLOCK_INFO (BASIC_BLOCK (i))->tovisit = 1;
+ REAL_ARITHMETIC (tmp, MULT_EXPR, BLOCK_INFO (bb)->frequency,
+ freq_max);
+ REAL_ARITHMETIC (tmp, PLUS_EXPR, tmp, real_one_half);
+ bb->frequency = REAL_VALUE_UNSIGNED_FIX (tmp);
+ }
- BLOCK_INFO (ENTRY_BLOCK_PTR)->tovisit = 1;
- BLOCK_INFO (EXIT_BLOCK_PTR)->tovisit = 1;
- propagate_freq (ENTRY_BLOCK_PTR);
+ free_aux_for_blocks ();
+ free_aux_for_edges ();
+ }
+ compute_function_frequency ();
+ if (flag_reorder_functions)
+ choose_function_section ();
+}
- for (i = 0; i < n_basic_blocks; i++)
- if (BLOCK_INFO (BASIC_BLOCK (i))->frequency > freq_max)
- freq_max = BLOCK_INFO (BASIC_BLOCK (i))->frequency;
+/* Decide whether function is hot, cold or unlikely executed. */
+static void
+compute_function_frequency ()
+{
+ basic_block bb;
- for (i = -2; i < n_basic_blocks; i++)
+ if (!profile_info.count_profiles_merged
+ || !flag_branch_probabilities)
+ return;
+ cfun->function_frequency = FUNCTION_FREQUENCY_UNLIKELY_EXECUTED;
+ FOR_EACH_BB (bb)
{
- basic_block bb;
- volatile double tmp;
-
- if (i == -2)
- bb = ENTRY_BLOCK_PTR;
- else if (i == -1)
- bb = EXIT_BLOCK_PTR;
- else
- bb = BASIC_BLOCK (i);
-
- /* ??? Prevent rounding differences due to optimization on x86. */
- tmp = BLOCK_INFO (bb)->frequency * BB_FREQ_MAX;
- tmp /= freq_max;
- tmp += 0.5;
- bb->frequency = tmp;
+ if (maybe_hot_bb_p (bb))
+ {
+ cfun->function_frequency = FUNCTION_FREQUENCY_HOT;
+ return;
+ }
+ if (!probably_never_executed_bb_p (bb))
+ cfun->function_frequency = FUNCTION_FREQUENCY_NORMAL;
}
+}
- free_aux_for_blocks ();
- free_aux_for_edges ();
+/* Choose appropriate section for the function. */
+static void
+choose_function_section ()
+{
+ if (DECL_SECTION_NAME (current_function_decl)
+ || !targetm.have_named_sections
+ /* Theoretically we can split the gnu.linkonce text section too,
+ but this requires more work as the frequency needs to match
+ for all generated objects so we need to merge the frequency
+ of all instances. For now just never set frequency for these. */
+ || DECL_ONE_ONLY (current_function_decl))
+ return;
+ if (cfun->function_frequency == FUNCTION_FREQUENCY_HOT)
+ DECL_SECTION_NAME (current_function_decl) =
+ build_string (strlen (HOT_TEXT_SECTION_NAME), HOT_TEXT_SECTION_NAME);
+ if (cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
+ DECL_SECTION_NAME (current_function_decl) =
+ build_string (strlen (UNLIKELY_EXECUTED_TEXT_SECTION_NAME),
+ UNLIKELY_EXECUTED_TEXT_SECTION_NAME);
}
diff --git a/contrib/gcc/predict.def b/contrib/gcc/predict.def
index 1201625..238e0f2 100644
--- a/contrib/gcc/predict.def
+++ b/contrib/gcc/predict.def
@@ -63,6 +63,9 @@ DEF_PREDICTOR (PRED_LOOP_ITERATIONS, "loop iterations", PROB_ALWAYS,
DEF_PREDICTOR (PRED_BUILTIN_EXPECT, "__builtin_expect", PROB_VERY_LIKELY,
PRED_FLAG_FIRST_MATCH)
+/* Branch containing goto is probably not taken. */
+DEF_PREDICTOR (PRED_CONTINUE, "continue", HITRATE (56), 0)
+
/* Branch to basic block containing call marked by noreturn attribute. */
DEF_PREDICTOR (PRED_NORETURN, "noreturn call", HITRATE (99),
PRED_FLAG_FIRST_MATCH)
@@ -71,7 +74,7 @@ DEF_PREDICTOR (PRED_NORETURN, "noreturn call", HITRATE (99),
DEF_PREDICTOR (PRED_LOOP_BRANCH, "loop branch", HITRATE (89),
PRED_FLAG_FIRST_MATCH)
-/* Edge causing loop to terminate is probably not taken. */
+/* Edge causing loop to terminate is probably not taken. */
DEF_PREDICTOR (PRED_LOOP_EXIT, "loop exit", HITRATE (90),
PRED_FLAG_FIRST_MATCH)
@@ -97,4 +100,16 @@ DEF_PREDICTOR (PRED_FPOPCODE, "fp_opcode", HITRATE (90), 0)
DEF_PREDICTOR (PRED_CALL, "call", HITRATE (70), 0)
/* Branch causing function to terminate is probably not taken. */
-DEF_PREDICTOR (PRED_ERROR_RETURN, "error return", HITRATE (52), 0)
+DEF_PREDICTOR (PRED_EARLY_RETURN, "early return", HITRATE (67), 0)
+
+/* Branch containing goto is probably not taken. */
+DEF_PREDICTOR (PRED_GOTO, "goto", HITRATE (70), 0)
+
+/* Branch ending with return constant is probably not taken. */
+DEF_PREDICTOR (PRED_CONST_RETURN, "const return", HITRATE (95), 0)
+
+/* Branch ending with return negative constant is probably not taken. */
+DEF_PREDICTOR (PRED_NEGATIVE_RETURN, "negative return", HITRATE (96), 0)
+
+/* Branch ending with return; is probably not taken */
+DEF_PREDICTOR (PRED_NULL_RETURN, "null return", HITRATE (90), 0)
diff --git a/contrib/gcc/predict.h b/contrib/gcc/predict.h
index 6af5f8d..a936b56 100644
--- a/contrib/gcc/predict.h
+++ b/contrib/gcc/predict.h
@@ -34,6 +34,9 @@ enum prediction
TAKEN
};
+/* Flags for NOTE_PREDICTION */
+#define IS_TAKEN 1 /* Predict edges to the block as taken. */
+
extern void predict_insn_def PARAMS ((rtx, enum br_predictor,
enum prediction));
extern void predict_insn PARAMS ((rtx, enum br_predictor, int));
diff --git a/contrib/gcc/prefix.c b/contrib/gcc/prefix.c
index 8890673..06930fe 100644
--- a/contrib/gcc/prefix.c
+++ b/contrib/gcc/prefix.c
@@ -1,5 +1,6 @@
/* Utility to update paths from internal to external forms.
- Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -42,7 +43,7 @@ Boston, MA 02111-1307, USA. */
be considered a "key" and looked up as follows:
-- If this is a Win32 OS, then the Registry will be examined for
- an entry of "key" in
+ an entry of "key" in
HKEY_LOCAL_MACHINE\SOFTWARE\Free Software Foundation\<KEY>
@@ -58,7 +59,7 @@ Boston, MA 02111-1307, USA. */
as an environment variable, whose value will be returned.
Once all this is done, any '/' will be converted to DIR_SEPARATOR,
- if they are different.
+ if they are different.
NOTE: using resolve_keyed_path under Win32 requires linking with
advapi32.dll. */
@@ -149,10 +150,10 @@ lookup_key (key)
KEY_READ, &reg_key);
if (res != ERROR_SUCCESS)
- {
- reg_key = (HKEY) INVALID_HANDLE_VALUE;
- return 0;
- }
+ {
+ reg_key = (HKEY) INVALID_HANDLE_VALUE;
+ return 0;
+ }
}
size = 32;
@@ -251,7 +252,7 @@ update_path (path, key)
const char *path;
const char *key;
{
- char *result;
+ char *result, *p;
if (! strncmp (path, std_prefix, strlen (std_prefix)) && key != 0)
{
@@ -271,9 +272,66 @@ update_path (path, key)
else
result = xstrdup (path);
+#ifndef ALWAYS_STRIP_DOTDOT
+#define ALWAYS_STRIP_DOTDOT 0
+#endif
+
+ p = result;
+ while (1)
+ {
+ char *src, *dest;
+
+ p = strchr (p, '.');
+ if (p == NULL)
+ break;
+ /* Look for `/../' */
+ if (p[1] == '.'
+ && IS_DIR_SEPARATOR (p[2])
+ && (p != result && IS_DIR_SEPARATOR (p[-1])))
+ {
+ *p = 0;
+ if (!ALWAYS_STRIP_DOTDOT && access (result, X_OK) == 0)
+ {
+ *p = '.';
+ break;
+ }
+ else
+ {
+ /* We can't access the dir, so we won't be able to
+ access dir/.. either. Strip out `dir/../'. If `dir'
+ turns out to be `.', strip one more path component. */
+ dest = p;
+ do
+ {
+ --dest;
+ while (dest != result && IS_DIR_SEPARATOR (*dest))
+ --dest;
+ while (dest != result && !IS_DIR_SEPARATOR (dest[-1]))
+ --dest;
+ }
+ while (dest != result && *dest == '.');
+ /* If we have something like `./..' or `/..', don't
+ strip anything more. */
+ if (*dest == '.' || IS_DIR_SEPARATOR (*dest))
+ {
+ *p = '.';
+ break;
+ }
+ src = p + 3;
+ while (IS_DIR_SEPARATOR (*src))
+ ++src;
+ p = dest;
+ while ((*dest++ = *src++) != 0)
+ ;
+ }
+ }
+ else
+ ++p;
+ }
+
#ifdef UPDATE_PATH_HOST_CANONICALIZE
/* Perform host dependent canonicalization when needed. */
- UPDATE_PATH_HOST_CANONICALIZE (path);
+ UPDATE_PATH_HOST_CANONICALIZE (result);
#endif
#ifdef DIR_SEPARATOR_2
diff --git a/contrib/gcc/pretty-print.h b/contrib/gcc/pretty-print.h
new file mode 100644
index 0000000..5efb9e7
--- /dev/null
+++ b/contrib/gcc/pretty-print.h
@@ -0,0 +1,100 @@
+/* Various declarations for language-independent pretty-print subroutines.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#ifndef GCC_PRETTY_PRINT_H
+#define GCC_PRETTY_PRINT_H
+
+#include "diagnostic.h"
+
+/* The type of pretty-printer flags passed to clients. */
+typedef unsigned int pp_flags;
+
+typedef enum
+{
+ pp_none, pp_before, pp_after
+} pp_padding;
+
+struct pretty_print_info
+{
+ /* Where we print external representation of ENTITY. */
+ output_buffer *buffer;
+ pp_flags flags;
+ /* Where to put whitespace around the entity being formatted. */
+ pp_padding padding;
+};
+
+#define pp_left_paren(PPI) output_add_character (pp_buffer (PPI), '(')
+#define pp_right_paren(PPI) output_add_character (pp_buffer (PPI), ')')
+#define pp_left_bracket(PPI) output_add_character (pp_buffer (PPI), '[')
+#define pp_right_bracket(PPI) output_add_character (pp_buffer (PPI), ']')
+#define pp_left_brace(PPI) output_add_character (pp_buffer (PPI), '{')
+#define pp_right_brace(PPI) output_add_character (pp_buffer (PPI), '}')
+#define pp_semicolon(PPI) output_add_character (pp_buffer (PPI), ';')
+#define pp_comma(PPI) output_add_string (pp_buffer (PPI), ", ")
+#define pp_dot(PPI) output_add_character (pp_buffer (PPI), '.')
+#define pp_colon(PPI) output_add_character (pp_buffer (PPI), ':')
+#define pp_colon_colon(PPI) output_add_string (pp_buffer (PPI), "::")
+#define pp_arrow(PPI) output_add_string (pp_buffer (PPI), "->")
+#define pp_equal(PPI) output_add_character (pp_buffer (PPI), '=')
+#define pp_question(PPI) output_add_character (pp_buffer (PPI), '?')
+#define pp_bar(PPI) output_add_character (pp_buffer (PPI), '|')
+#define pp_carret(PPI) output_add_character (pp_buffer (PPI), '^')
+#define pp_ampersand(PPI) output_add_character (pp_buffer (PPI), '&')
+#define pp_less(PPI) output_add_character (pp_buffer (PPI), '<')
+#define pp_greater(PPI) output_add_character (pp_buffer (PPI), '>')
+#define pp_plus(PPI) output_add_character (pp_buffer (PPI), '+')
+#define pp_minus(PPI) output_add_character (pp_buffer (PPI), '-')
+#define pp_star(PPI) output_add_character (pp_buffer (PPI), '*')
+#define pp_slash(PPI) output_add_character (pp_buffer (PPI), '/')
+#define pp_modulo(PPI) output_add_character (pp_buffer (PPI), '%')
+#define pp_exclamation(PPI) output_add_character (pp_buffer (PPI), '!')
+#define pp_complement(PPI) output_add_character (pp_buffer (PPI), '~')
+#define pp_quote(PPI) output_add_character (pp_buffer (PPI), '\'')
+#define pp_backquote(PPI) output_add_character (pp_buffer (PPI), '`')
+#define pp_doublequote(PPI) output_add_character (pp_buffer (PPI), '"')
+#define pp_newline(PPI) output_add_newline (pp_buffer (PPI))
+#define pp_character(PPI, C) output_add_character (pp_buffer (PPI), C)
+#define pp_whitespace(PPI) output_add_space (pp_buffer (PPI))
+#define pp_indentation(PPI) output_indentation (pp_buffer (PPI))
+#define pp_newline_and_indent(PPI, N) \
+ do { \
+ pp_indentation (PPI) += N; \
+ pp_newline (PPI); \
+ } while (0)
+#define pp_separate_with(PPI, C) \
+ do { \
+ pp_character (PPI, C); \
+ pp_whitespace (PPI); \
+ } while (0)
+#define pp_format_scalar(PPI, F, S) \
+ output_formatted_scalar (pp_buffer (PPI), F, S)
+#define pp_wide_integer(PPI, I) \
+ pp_format_scalar (PPI, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) I)
+#define pp_pointer(PPI, P) pp_format_scalar (PPI, "%p", p)
+
+#define pp_identifier(PPI, ID) output_add_string (pp_buffer (PPI), ID)
+#define pp_tree_identifier(PPI, T) pp_identifier(PPI, IDENTIFIER_POINTER (T))
+
+#define pp_unsupported_tree(PPI, T) \
+ output_verbatim (pp_buffer(PPI), "#`%s' not supported by %s#",\
+ tree_code_name[(int) TREE_CODE (T)], __FUNCTION__)
+
+#endif /* GCC_PRETTY_PRINT_H */
diff --git a/contrib/gcc/print-rtl.c b/contrib/gcc/print-rtl.c
index 28f6066..0a0ac9e 100644
--- a/contrib/gcc/print-rtl.c
+++ b/contrib/gcc/print-rtl.c
@@ -1,5 +1,5 @@
/* Print RTL for GNU C Compiler.
- Copyright (C) 1987, 1988, 1992, 1997, 1998, 1999, 2000
+ Copyright (C) 1987, 1988, 1992, 1997, 1998, 1999, 2000, 2002, 2003
Free Software Foundation, Inc.
This file is part of GCC.
@@ -85,7 +85,7 @@ print_mem_expr (outfile, expr)
if (TREE_CODE (expr) == COMPONENT_REF)
{
if (TREE_OPERAND (expr, 0))
- print_mem_expr (outfile, TREE_OPERAND (expr, 0));
+ print_mem_expr (outfile, TREE_OPERAND (expr, 0));
else
fputs (" <variable>", outfile);
if (DECL_NAME (TREE_OPERAND (expr, 1)))
@@ -158,34 +158,34 @@ print_rtx (in_rtx)
fputc ('(', outfile);
else
fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
-
+
if (! flag_simple)
{
- if (in_rtx->in_struct)
+ if (RTX_FLAG (in_rtx, in_struct))
fputs ("/s", outfile);
- if (in_rtx->volatil)
+ if (RTX_FLAG (in_rtx, volatil))
fputs ("/v", outfile);
-
- if (in_rtx->unchanging)
+
+ if (RTX_FLAG (in_rtx, unchanging))
fputs ("/u", outfile);
-
- if (in_rtx->integrated)
+
+ if (RTX_FLAG (in_rtx, integrated))
fputs ("/i", outfile);
-
- if (in_rtx->frame_related)
+
+ if (RTX_FLAG (in_rtx, frame_related))
fputs ("/f", outfile);
-
- if (in_rtx->jump)
+
+ if (RTX_FLAG (in_rtx, jump))
fputs ("/j", outfile);
-
- if (in_rtx->call)
+
+ if (RTX_FLAG (in_rtx, call))
fputs ("/c", outfile);
if (GET_MODE (in_rtx) != VOIDmode)
{
/* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */
- if (GET_CODE (in_rtx) == EXPR_LIST
+ if (GET_CODE (in_rtx) == EXPR_LIST
|| GET_CODE (in_rtx) == INSN_LIST)
fprintf (outfile, ":%s",
GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
@@ -195,6 +195,11 @@ print_rtx (in_rtx)
}
}
+#ifndef GENERATOR_FILE
+ if (GET_CODE (in_rtx) == CONST_DOUBLE && FLOAT_MODE_P (GET_MODE (in_rtx)))
+ i = 5;
+#endif
+
/* Get the format string and skip the first elements if we have handled
them already. */
format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i;
@@ -234,7 +239,7 @@ print_rtx (in_rtx)
fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx));
break;
}
- if (i == 3 && GET_CODE (in_rtx) == NOTE)
+ if (i == 4 && GET_CODE (in_rtx) == NOTE)
{
switch (NOTE_LINE_NUMBER (in_rtx))
{
@@ -253,21 +258,11 @@ print_rtx (in_rtx)
if (flag_dump_unnumbered)
fprintf (outfile, "#");
else
- fprintf (outfile, HOST_PTR_PRINTF,
+ fprintf (outfile, HOST_PTR_PRINTF,
(char *) NOTE_BLOCK (in_rtx));
sawclose = 1;
break;
- case NOTE_INSN_RANGE_BEG:
- case NOTE_INSN_RANGE_END:
- case NOTE_INSN_LIVE:
- indent += 2;
- if (!sawclose)
- fprintf (outfile, " ");
- print_rtx (NOTE_RANGE_INFO (in_rtx));
- indent -= 2;
- break;
-
case NOTE_INSN_BASIC_BLOCK:
{
basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
@@ -291,6 +286,15 @@ print_rtx (in_rtx)
fprintf (outfile, " \"\"");
break;
+ case NOTE_INSN_PREDICTION:
+ if (NOTE_PREDICTION (in_rtx))
+ fprintf (outfile, " [ %d %d ] ",
+ (int)NOTE_PREDICTION_ALG (in_rtx),
+ (int) NOTE_PREDICTION_FLAGS (in_rtx));
+ else
+ fprintf (outfile, " [ ERROR ]");
+ break;
+
default:
{
const char * const str = X0STR (in_rtx, i);
@@ -327,10 +331,10 @@ print_rtx (in_rtx)
if (sawclose)
{
fprintf (outfile, "\n%s%*s",
- print_rtx_head, indent * 2, "");
+ print_rtx_head, indent * 2, "");
sawclose = 0;
}
- fputs ("[ ", outfile);
+ fputs (" [", outfile);
if (NULL != XVEC (in_rtx, i))
{
indent += 2;
@@ -345,7 +349,7 @@ print_rtx (in_rtx)
if (sawclose)
fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, "");
- fputs ("] ", outfile);
+ fputs ("]", outfile);
sawclose = 1;
indent -= 2;
break;
@@ -363,7 +367,7 @@ print_rtx (in_rtx)
break;
case 'i':
- if (i == 5 && GET_CODE (in_rtx) == NOTE)
+ if (i == 6 && GET_CODE (in_rtx) == NOTE)
{
/* This field is only used for NOTE_INSN_DELETED_LABEL, and
other times often contains garbage from INSN->NOTE death. */
@@ -473,6 +477,11 @@ print_rtx (in_rtx)
sawclose = 0;
break;
+ case 'B':
+ if (XBBDEF (in_rtx, i))
+ fprintf (outfile, " %i", XBBDEF (in_rtx, i)->index);
+ break;
+
default:
fprintf (stderr,
"switch format wrong in rtl.print_rtx(). format was: %c.\n",
@@ -482,6 +491,7 @@ print_rtx (in_rtx)
switch (GET_CODE (in_rtx))
{
+#ifndef GENERATOR_FILE
case MEM:
fputs (" [", outfile);
fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, MEM_ALIAS_SET (in_rtx));
@@ -509,22 +519,32 @@ print_rtx (in_rtx)
fputc (']', outfile);
break;
-#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT && MAX_LONG_DOUBLE_TYPE_SIZE == 64
case CONST_DOUBLE:
if (FLOAT_MODE_P (GET_MODE (in_rtx)))
{
- double val;
- REAL_VALUE_FROM_CONST_DOUBLE (val, in_rtx);
- fprintf (outfile, " [%.16g]", val);
+ char s[60];
+
+ real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
+ sizeof (s), 0, 1);
+ fprintf (outfile, " %s", s);
+
+ real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
+ sizeof (s), 0, 1);
+ fprintf (outfile, " [%s]", s);
}
break;
#endif
case CODE_LABEL:
fprintf (outfile, " [%d uses]", LABEL_NUSES (in_rtx));
- if (LABEL_ALTERNATE_NAME (in_rtx))
- fprintf (outfile, " [alternate name: %s]",
- LABEL_ALTERNATE_NAME (in_rtx));
+ switch (LABEL_KIND (in_rtx))
+ {
+ case LABEL_NORMAL: break;
+ case LABEL_STATIC_ENTRY: fputs (" [entry]", outfile); break;
+ case LABEL_GLOBAL_ENTRY: fputs (" [global entry]", outfile); break;
+ case LABEL_WEAK_ENTRY: fputs (" [weak entry]", outfile); break;
+ default: abort();
+ }
break;
case CALL_PLACEHOLDER:
@@ -612,6 +632,7 @@ debug_rtx (x)
rtx x;
{
outfile = stderr;
+ sawclose = 0;
print_rtx (x);
fprintf (stderr, "\n");
}
@@ -648,7 +669,10 @@ debug_rtx_list (x, n)
}
for (i = count, insn = x; i > 0 && insn != 0; i--, insn = NEXT_INSN (insn))
- debug_rtx (insn);
+ {
+ debug_rtx (insn);
+ fprintf (stderr, "\n");
+ }
}
/* Call this function to print an rtx list from START to END inclusive. */
@@ -660,6 +684,7 @@ debug_rtx_range (start, end)
while (1)
{
debug_rtx (start);
+ fprintf (stderr, "\n");
if (!start || start == end)
break;
start = NEXT_INSN (start);
@@ -723,14 +748,14 @@ print_rtl (outf, rtx_first)
if (! flag_dump_unnumbered
|| GET_CODE (tmp_rtx) != NOTE || NOTE_LINE_NUMBER (tmp_rtx) < 0)
{
- fputs (print_rtx_head, outfile);
+ fputs (print_rtx_head, outfile);
print_rtx (tmp_rtx);
fprintf (outfile, "\n");
}
break;
default:
- fputs (print_rtx_head, outfile);
+ fputs (print_rtx_head, outfile);
print_rtx (rtx_first);
}
}
diff --git a/contrib/gcc/print-tree.c b/contrib/gcc/print-tree.c
index f535373..05ca52b 100644
--- a/contrib/gcc/print-tree.c
+++ b/contrib/gcc/print-tree.c
@@ -23,6 +23,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
#include "tree.h"
+#include "real.h"
#include "ggc.h"
#include "langhooks.h"
@@ -47,8 +48,7 @@ void
debug_tree (node)
tree node;
{
- table = (struct bucket **) permalloc (HASH_SIZE * sizeof (struct bucket *));
- memset ((char *) table, 0, HASH_SIZE * sizeof (struct bucket *));
+ table = (struct bucket **) xcalloc (HASH_SIZE, sizeof (struct bucket *));
print_node (stderr, "", node, 0);
table = 0;
fprintf (stderr, "\n");
@@ -124,7 +124,6 @@ print_node_brief (file, prefix, node, indent)
if (TREE_OVERFLOW (node))
fprintf (file, " overflow");
-#if !defined(REAL_IS_NOT_DOUBLE) || defined(REAL_ARITHMETIC)
d = TREE_REAL_CST (node);
if (REAL_VALUE_ISINF (d))
fprintf (file, " Inf");
@@ -132,21 +131,10 @@ print_node_brief (file, prefix, node, indent)
fprintf (file, " Nan");
else
{
- char string[100];
-
- REAL_VALUE_TO_DECIMAL (d, "%e", string);
+ char string[60];
+ real_to_decimal (string, &d, sizeof (string), 0, 1);
fprintf (file, " %s", string);
}
-#else
- {
- int i;
- unsigned char *p = (unsigned char *) &TREE_REAL_CST (node);
- fprintf (file, " 0x");
- for (i = 0; i < sizeof TREE_REAL_CST (node); i++)
- fprintf (file, "%02x", *p++);
- fprintf (file, "");
- }
-#endif
}
fprintf (file, ">");
@@ -223,7 +211,7 @@ print_node (file, prefix, node, indent)
}
/* Add this node to the table. */
- b = (struct bucket *) permalloc (sizeof (struct bucket));
+ b = (struct bucket *) xmalloc (sizeof (struct bucket));
b->node = node;
b->next = table[hash];
table[hash] = b;
@@ -340,7 +328,9 @@ print_node (file, prefix, node, indent)
if (TREE_CODE (node) == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (node))
fputs (" suppress-debug", file);
- if (TREE_CODE (node) == FUNCTION_DECL && DECL_INLINE (node))
+ if (TREE_CODE (node) == FUNCTION_DECL && DID_INLINE_FUNC (node))
+ fputs (" autoinline", file);
+ else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INLINE (node))
fputs (" inline", file);
if (TREE_CODE (node) == FUNCTION_DECL && DECL_BUILT_IN (node))
fputs (" built-in", file);
@@ -363,6 +353,8 @@ print_node (file, prefix, node, indent)
if (TREE_CODE (node) == VAR_DECL && DECL_IN_TEXT_SECTION (node))
fputs (" in-text-section", file);
+ if (TREE_CODE (node) == VAR_DECL && DECL_THREAD_LOCAL (node))
+ fputs (" thread-local", file);
if (TREE_CODE (node) == PARM_DECL && DECL_TRANSPARENT_UNION (node))
fputs (" transparent-union", file);
@@ -395,7 +387,7 @@ print_node (file, prefix, node, indent)
print_node (file, "size", DECL_SIZE (node), indent + 4);
print_node (file, "unit size", DECL_SIZE_UNIT (node), indent + 4);
-
+
if (TREE_CODE (node) != FUNCTION_DECL
|| DECL_INLINE (node) || DECL_BUILT_IN (node))
indent_to (file, indent + 3);
@@ -426,7 +418,7 @@ print_node (file, prefix, node, indent)
if (DECL_POINTER_ALIAS_SET_KNOWN_P (node))
{
fprintf (file, " alias set ");
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC,
DECL_POINTER_ALIAS_SET (node));
}
@@ -517,6 +509,9 @@ print_node (file, prefix, node, indent)
if (TYPE_PACKED (node))
fputs (" packed", file);
+ if (TYPE_RESTRICT (node))
+ fputs (" restrict", file);
+
if (TYPE_LANG_FLAG_0 (node))
fputs (" type_0", file);
if (TYPE_LANG_FLAG_1 (node))
@@ -644,7 +639,7 @@ print_node (file, prefix, node, indent)
if (TREE_CODE (node) == EXPR_WITH_FILE_LOCATION)
{
indent_to (file, indent+4);
- fprintf (file, "%s:%d:%d",
+ fprintf (file, "%s:%d:%d",
(EXPR_WFL_FILENAME_NODE (node ) ?
EXPR_WFL_FILENAME (node) : "(no file info)"),
EXPR_WFL_LINENO (node), EXPR_WFL_COLNO (node));
@@ -683,7 +678,6 @@ print_node (file, prefix, node, indent)
if (TREE_OVERFLOW (node))
fprintf (file, " overflow");
-#if !defined(REAL_IS_NOT_DOUBLE) || defined(REAL_ARITHMETIC)
d = TREE_REAL_CST (node);
if (REAL_VALUE_ISINF (d))
fprintf (file, " Inf");
@@ -691,21 +685,10 @@ print_node (file, prefix, node, indent)
fprintf (file, " Nan");
else
{
- char string[100];
-
- REAL_VALUE_TO_DECIMAL (d, "%e", string);
+ char string[64];
+ real_to_decimal (string, &d, sizeof (string), 0, 1);
fprintf (file, " %s", string);
}
-#else
- {
- int i;
- unsigned char *p = (unsigned char *) &TREE_REAL_CST (node);
- fprintf (file, " 0x");
- for (i = 0; i < sizeof TREE_REAL_CST (node); i++)
- fprintf (file, "%02x", *p++);
- fprintf (file, "");
- }
-#endif
}
break;
@@ -731,7 +714,20 @@ print_node (file, prefix, node, indent)
break;
case STRING_CST:
- fprintf (file, " \"%s\"", TREE_STRING_POINTER (node));
+ {
+ const char *p = TREE_STRING_POINTER (node);
+ int i = TREE_STRING_LENGTH (node);
+ fputs (" \"", file);
+ while (--i >= 0)
+ {
+ char ch = *p++;
+ if (ch >= ' ' && ch < 127)
+ putc (ch, file);
+ else
+ fprintf(file, "\\%03o", ch & 0xFF);
+ }
+ fputc ('\"', file);
+ }
/* Print the chain at second level. */
if (indent == 4)
print_node (file, "chain", TREE_CHAIN (node), indent + 4);
diff --git a/contrib/gcc/profile.c b/contrib/gcc/profile.c
index 0c4acdf..a70dc61 100644
--- a/contrib/gcc/profile.c
+++ b/contrib/gcc/profile.c
@@ -22,6 +22,40 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
+/* Generate basic block profile instrumentation and auxiliary files.
+ Profile generation is optimized, so that not all arcs in the basic
+ block graph need instrumenting. First, the BB graph is closed with
+ one entry (function start), and one exit (function exit). Any
+ ABNORMAL_EDGE cannot be instrumented (because there is no control
+ path to place the code). We close the graph by inserting fake
+ EDGE_FAKE edges to the EXIT_BLOCK, from the sources of abnormal
+ edges that do not go to the exit_block. We ignore such abnormal
+ edges. Naturally these fake edges are never directly traversed,
+ and so *cannot* be directly instrumented. Some other graph
+ massaging is done. To optimize the instrumentation we generate the
+ BB minimal span tree, only edges that are not on the span tree
+ (plus the entry point) need instrumenting. From that information
+ all other edge counts can be deduced. By construction all fake
+ edges must be on the spanning tree. We also attempt to place
+ EDGE_CRITICAL edges on the spanning tree.
+
+ The two auxiliary files generated are <dumpbase>.bb and
+ <dumpbase>.bbg. The former contains the BB->linenumber
+ mappings, and the latter describes the BB graph.
+
+ The BB file contains line numbers for each block. For each basic
+ block, a zero count is output (to mark the start of a block), then
+ the line numbers of that block are listed. A zero ends the file
+ too.
+
+ The BBG file contains a count of the blocks, followed by edge
+ information, for every edge in the graph. The edge information
+ lists the source and target block numbers, and a bit mask
+ describing the type of edge.
+
+ The BB and BBG file formats are fully described in the gcov
+ documentation. */
+
/* ??? Register allocation should use basic block execution counts to
give preference to the most commonly executed blocks. */
@@ -49,32 +83,42 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "basic-block.h"
#include "gcov-io.h"
#include "target.h"
+#include "profile.h"
+#include "libfuncs.h"
+#include "langhooks.h"
/* Additional information about the edges we need. */
-struct edge_info
- {
- unsigned int count_valid : 1;
- unsigned int on_tree : 1;
- unsigned int ignore : 1;
- };
-struct bb_info
- {
- unsigned int count_valid : 1;
- gcov_type succ_count;
- gcov_type pred_count;
- };
+struct edge_info {
+ unsigned int count_valid : 1;
+
+ /* Is on the spanning tree. */
+ unsigned int on_tree : 1;
+
+ /* Pretend this edge does not exist (it is abnormal and we've
+ inserted a fake to compensate). */
+ unsigned int ignore : 1;
+};
+
+struct bb_info {
+ unsigned int count_valid : 1;
+
+ /* Number of successor and predecessor edges. */
+ gcov_type succ_count;
+ gcov_type pred_count;
+};
#define EDGE_INFO(e) ((struct edge_info *) (e)->aux)
#define BB_INFO(b) ((struct bb_info *) (b)->aux)
/* Keep all basic block indexes nonnegative in the gcov output. Index 0
is used for entry block, last block exit block. */
-#define GCOV_INDEX_TO_BB(i) ((i) == 0 ? ENTRY_BLOCK_PTR \
- : (((i) == n_basic_blocks + 1) \
- ? EXIT_BLOCK_PTR : BASIC_BLOCK ((i)-1)))
#define BB_TO_GCOV_INDEX(bb) ((bb) == ENTRY_BLOCK_PTR ? 0 \
: ((bb) == EXIT_BLOCK_PTR \
- ? n_basic_blocks + 1 : (bb)->index + 1))
+ ? last_basic_block + 1 : (bb)->index + 1))
+
+/* Instantiate the profile info structure. */
+
+struct profile_info profile_info;
/* Name and file pointer of the output file for the basic block graph. */
@@ -83,6 +127,7 @@ static FILE *bbg_file;
/* Name and file pointer of the input file for the arc count data. */
static FILE *da_file;
+static char *da_file_name;
/* Pointer of the output file for the basic block/line number map. */
static FILE *bb_file;
@@ -91,11 +136,6 @@ static FILE *bb_file;
static char *last_bb_file_name;
-/* Used by final, for allocating the proper amount of storage for the
- instrumented arc execution counts. */
-
-int count_instrumented_edges;
-
/* Collect statistics on the performance of this pass for the entire source
file. */
@@ -117,10 +157,12 @@ static rtx gen_edge_profiler PARAMS ((int));
static void instrument_edges PARAMS ((struct edge_list *));
static void output_gcov_string PARAMS ((const char *, long));
static void compute_branch_probabilities PARAMS ((void));
+static gcov_type * get_exec_counts PARAMS ((void));
+static long compute_checksum PARAMS ((void));
static basic_block find_group PARAMS ((basic_block));
static void union_groups PARAMS ((basic_block, basic_block));
-/* If non-zero, we need to output a constructor to set up the
+/* If nonzero, we need to output a constructor to set up the
per-object-file data. */
static int need_func_profiler = 0;
@@ -133,14 +175,13 @@ static void
instrument_edges (el)
struct edge_list *el;
{
- int i;
int num_instr_edges = 0;
int num_edges = NUM_EDGES (el);
+ basic_block bb;
remove_fake_edges ();
- for (i = 0; i < n_basic_blocks + 2; i++)
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
{
- basic_block bb = GCOV_INDEX_TO_BB (i);
edge e = bb->succ;
while (e)
{
@@ -162,14 +203,15 @@ instrument_edges (el)
}
}
+ profile_info.count_edges_instrumented_now = num_instr_edges;
total_num_edges_instrumented += num_instr_edges;
- count_instrumented_edges = total_num_edges_instrumented;
+ profile_info.count_instrumented_edges = total_num_edges_instrumented;
total_num_blocks_created += num_edges;
if (rtl_dump_file)
fprintf (rtl_dump_file, "%d edges instrumented\n", num_instr_edges);
- commit_edge_insertions ();
+ commit_edge_insertions_watch_calls ();
}
/* Output STRING to bb_file, surrounded by DELIMITER. */
@@ -179,7 +221,7 @@ output_gcov_string (string, delimiter)
const char *string;
long delimiter;
{
- long temp;
+ size_t temp;
/* Write a delimiter to indicate that a file name follows. */
__write_long (delimiter, bb_file, 4);
@@ -204,12 +246,179 @@ output_gcov_string (string, delimiter)
}
+/* Computes hybrid profile for all matching entries in da_file.
+ Sets max_counter_in_program as a side effect. */
+
+static gcov_type *
+get_exec_counts ()
+{
+ int num_edges = 0;
+ basic_block bb;
+ int okay = 1, i;
+ int mismatch = 0;
+ gcov_type *profile;
+ char *function_name_buffer;
+ int function_name_buffer_len;
+ gcov_type max_counter_in_run;
+ const char *name = IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (current_function_decl));
+
+ profile_info.max_counter_in_program = 0;
+ profile_info.count_profiles_merged = 0;
+
+ /* No .da file, no execution counts. */
+ if (!da_file)
+ return 0;
+
+ /* Count the edges to be (possibly) instrumented. */
+
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ {
+ edge e;
+ for (e = bb->succ; e; e = e->succ_next)
+ if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
+ num_edges++;
+ }
+
+ /* now read and combine all matching profiles. */
+
+ profile = xmalloc (sizeof (gcov_type) * num_edges);
+ rewind (da_file);
+ function_name_buffer_len = strlen (name) + 1;
+ function_name_buffer = xmalloc (function_name_buffer_len + 1);
+
+ for (i = 0; i < num_edges; i++)
+ profile[i] = 0;
+
+ while (1)
+ {
+ long magic, extra_bytes;
+ long func_count;
+ int i;
+
+ if (__read_long (&magic, da_file, 4) != 0)
+ break;
+
+ if (magic != -123)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (__read_long (&func_count, da_file, 4) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (__read_long (&extra_bytes, da_file, 4) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ fseek (da_file, 4 + 8, SEEK_CUR);
+
+ /* read the maximal counter. */
+ __read_gcov_type (&max_counter_in_run, da_file, 8);
+
+ /* skip the rest of "statistics" emited by __bb_exit_func. */
+ fseek (da_file, extra_bytes - (4 + 8 + 8), SEEK_CUR);
+
+ for (i = 0; i < func_count; i++)
+ {
+ long arc_count;
+ long chksum;
+ int j;
+
+ if (__read_gcov_string
+ (function_name_buffer, function_name_buffer_len, da_file,
+ -1) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (__read_long (&chksum, da_file, 4) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (__read_long (&arc_count, da_file, 4) != 0)
+ {
+ okay = 0;
+ break;
+ }
+
+ if (strcmp (function_name_buffer, name) != 0)
+ {
+ /* skip */
+ if (fseek (da_file, arc_count * 8, SEEK_CUR) < 0)
+ {
+ okay = 0;
+ break;
+ }
+ }
+ else if (arc_count != num_edges
+ || chksum != profile_info.current_function_cfg_checksum)
+ okay = 0, mismatch = 1;
+ else
+ {
+ gcov_type tmp;
+
+ profile_info.max_counter_in_program += max_counter_in_run;
+ profile_info.count_profiles_merged++;
+
+ for (j = 0; j < arc_count; j++)
+ if (__read_gcov_type (&tmp, da_file, 8) != 0)
+ {
+ okay = 0;
+ break;
+ }
+ else
+ {
+ profile[j] += tmp;
+ }
+ }
+ }
+
+ if (!okay)
+ break;
+
+ }
+
+ free (function_name_buffer);
+
+ if (!okay)
+ {
+ if (mismatch)
+ error
+ ("Profile does not match flowgraph of function %s (out of date?)",
+ current_function_name);
+ else
+ error (".da file corrupted");
+ free (profile);
+ return 0;
+ }
+ if (rtl_dump_file)
+ {
+ fprintf(rtl_dump_file, "Merged %i profiles with maximal count %i.\n",
+ profile_info.count_profiles_merged,
+ (int)profile_info.max_counter_in_program);
+ }
+
+ return profile;
+}
+
+
/* Compute the branch probabilities for the various branches.
Annotate them accordingly. */
static void
compute_branch_probabilities ()
{
+ basic_block bb;
int i;
int num_edges = 0;
int changes;
@@ -217,13 +426,14 @@ compute_branch_probabilities ()
int hist_br_prob[20];
int num_never_executed;
int num_branches;
+ gcov_type *exec_counts = get_exec_counts ();
+ int exec_counts_pos = 0;
/* Attach extra info block to each bb. */
alloc_aux_for_blocks (sizeof (struct bb_info));
- for (i = 0; i < n_basic_blocks + 2; i++)
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
{
- basic_block bb = GCOV_INDEX_TO_BB (i);
edge e;
for (e = bb->succ; e; e = e->succ_next)
@@ -244,22 +454,20 @@ compute_branch_probabilities ()
/* The first count in the .da file is the number of times that the function
was entered. This is the exec_count for block zero. */
- for (i = 0; i < n_basic_blocks + 2; i++)
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
{
- basic_block bb = GCOV_INDEX_TO_BB (i);
edge e;
for (e = bb->succ; e; e = e->succ_next)
if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
{
num_edges++;
- if (da_file)
+ if (exec_counts)
{
- gcov_type value;
- __read_gcov_type (&value, da_file, 8);
- e->count = value;
+ e->count = exec_counts[exec_counts_pos++];
}
else
e->count = 0;
+
EDGE_INFO (e)->count_valid = 1;
BB_INFO (bb)->succ_count--;
BB_INFO (e->dest)->pred_count--;
@@ -299,9 +507,8 @@ compute_branch_probabilities ()
{
passes++;
changes = 0;
- for (i = n_basic_blocks + 1; i >= 0; i--)
+ FOR_BB_BETWEEN (bb, EXIT_BLOCK_PTR, NULL, prev_bb)
{
- basic_block bb = GCOV_INDEX_TO_BB (i);
struct bb_info *bi = BB_INFO (bb);
if (! bi->count_valid)
{
@@ -396,9 +603,8 @@ compute_branch_probabilities ()
/* If the graph has been correctly solved, every block will have a
succ and pred count of zero. */
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
if (BB_INFO (bb)->succ_count || BB_INFO (bb)->pred_count)
abort ();
}
@@ -411,9 +617,8 @@ compute_branch_probabilities ()
num_never_executed = 0;
num_branches = 0;
- for (i = 0; i <= n_basic_blocks + 1; i++)
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
{
- basic_block bb = GCOV_INDEX_TO_BB (i);
edge e;
gcov_type total;
rtx note;
@@ -516,6 +721,34 @@ compute_branch_probabilities ()
}
free_aux_for_blocks ();
+ if (exec_counts)
+ free (exec_counts);
+}
+
+/* Compute checksum for the current function. */
+
+#define CHSUM_HASH 500000003
+#define CHSUM_SHIFT 2
+
+static long
+compute_checksum ()
+{
+ long chsum = 0;
+ basic_block bb;
+
+ FOR_EACH_BB (bb)
+ {
+ edge e;
+
+ for (e = bb->succ; e; e = e->succ_next)
+ {
+ chsum = ((chsum << CHSUM_SHIFT) + (BB_TO_GCOV_INDEX (e->dest) + 1)) % CHSUM_HASH;
+ }
+
+ chsum = (chsum << CHSUM_SHIFT) % CHSUM_HASH;
+ }
+
+ return chsum;
}
/* Instrument and/or analyze program behavior based on program flow graph.
@@ -537,13 +770,22 @@ compute_branch_probabilities ()
void
branch_prob ()
{
+ basic_block bb;
int i;
int num_edges, ignored_edges;
struct edge_list *el;
+ const char *name = IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (current_function_decl));
+
+ profile_info.current_function_cfg_checksum = compute_checksum ();
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "CFG checksum is %ld\n",
+ profile_info.current_function_cfg_checksum);
/* Start of a function. */
if (flag_test_coverage)
- output_gcov_string (current_function_name, (long) -2);
+ output_gcov_string (name, (long) -2);
total_num_times_called++;
@@ -559,11 +801,10 @@ branch_prob ()
We also add fake exit edges for each call and asm statement in the
basic, since it may not return. */
- for (i = 0; i < n_basic_blocks ; i++)
+ FOR_EACH_BB (bb)
{
int need_exit_edge = 0, need_entry_edge = 0;
int have_exit_edge = 0, have_entry_edge = 0;
- basic_block bb = BASIC_BLOCK (i);
rtx insn;
edge e;
@@ -588,7 +829,7 @@ branch_prob ()
{
/* We should not get abort here, as call to setjmp should not
be the very first instruction of function. */
- if (!i)
+ if (bb == ENTRY_BLOCK_PTR)
abort ();
make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
}
@@ -617,14 +858,14 @@ branch_prob ()
if (rtl_dump_file)
fprintf (rtl_dump_file, "Adding fake exit edge to bb %i\n",
bb->index);
- make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
+ make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
}
if (need_entry_edge && !have_entry_edge)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, "Adding fake entry edge to bb %i\n",
bb->index);
- make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
+ make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
}
}
@@ -632,6 +873,9 @@ branch_prob ()
num_edges = NUM_EDGES (el);
alloc_aux_for_edges (sizeof (struct edge_info));
+ /* The basic blocks are expected to be numbered sequentially. */
+ compact_blocks ();
+
ignored_edges = 0;
for (i = 0 ; i < num_edges ; i++)
{
@@ -641,10 +885,10 @@ branch_prob ()
/* Mark edges we've replaced by fake edges above as ignored. */
if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
&& e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR)
- {
+ {
EDGE_INFO (e)->ignore = 1;
ignored_edges++;
- }
+ }
}
#ifdef ENABLE_CHECKING
@@ -655,12 +899,10 @@ branch_prob ()
GCOV utility. */
if (flag_test_coverage)
{
- int i = 0;
- for (i = 0 ; i < n_basic_blocks; i++)
- {
- basic_block bb = BASIC_BLOCK (i);
+ FOR_EACH_BB (bb)
+ {
rtx insn = bb->head;
- static int ignore_next_note = 0;
+ static int ignore_next_note = 0;
/* We are looking for line number notes. Search backward before
basic block to find correct ones. */
@@ -713,7 +955,7 @@ branch_prob ()
}
insn = NEXT_INSN (insn);
}
- }
+ }
__write_long (0, bb_file, 4);
}
@@ -730,10 +972,10 @@ branch_prob ()
edge e = INDEX_EDGE (el, i);
struct edge_info *inf = EDGE_INFO (e);
if ((e->flags & EDGE_FAKE) && !inf->ignore && !inf->on_tree)
- {
- inf->ignore = 1;
- ignored_edges++;
- }
+ {
+ inf->ignore = 1;
+ ignored_edges++;
+ }
}
total_num_blocks += n_basic_blocks + 2;
@@ -757,13 +999,17 @@ branch_prob ()
{
int flag_bits;
+ __write_gcov_string (name, strlen (name), bbg_file, -1);
+
+ /* write checksum. */
+ __write_long (profile_info.current_function_cfg_checksum, bbg_file, 4);
+
/* The plus 2 stands for entry and exit block. */
__write_long (n_basic_blocks + 2, bbg_file, 4);
__write_long (num_edges - ignored_edges + 1, bbg_file, 4);
- for (i = 0; i < n_basic_blocks + 1; i++)
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
{
- basic_block bb = GCOV_INDEX_TO_BB (i);
edge e;
long count = 0;
@@ -863,7 +1109,7 @@ union_groups (bb1, bb2)
/* This function searches all of the edges in the program flow graph, and puts
as many bad edges as possible onto the spanning tree. Bad edges include
abnormals edges, which can't be instrumented at the moment. Since it is
- possible for fake edges to form an cycle, we will have to develop some
+ possible for fake edges to form a cycle, we will have to develop some
better way in the future. Also put critical edges to the tree, since they
are more expensive to instrument. */
@@ -873,30 +1119,36 @@ find_spanning_tree (el)
{
int i;
int num_edges = NUM_EDGES (el);
+ basic_block bb;
/* We use aux field for standard union-find algorithm. */
- EXIT_BLOCK_PTR->aux = EXIT_BLOCK_PTR;
- ENTRY_BLOCK_PTR->aux = ENTRY_BLOCK_PTR;
- for (i = 0; i < n_basic_blocks; i++)
- BASIC_BLOCK (i)->aux = BASIC_BLOCK (i);
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ bb->aux = bb;
/* Add fake edge exit to entry we can't instrument. */
union_groups (EXIT_BLOCK_PTR, ENTRY_BLOCK_PTR);
- /* First add all abnormal edges to the tree unless they form an cycle. */
+ /* First add all abnormal edges to the tree unless they form a cycle. Also
+ add all edges to EXIT_BLOCK_PTR to avoid inserting profiling code behind
+ setting return value from function. */
for (i = 0; i < num_edges; i++)
{
edge e = INDEX_EDGE (el, i);
- if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_FAKE))
+ if (((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_FAKE))
+ || e->dest == EXIT_BLOCK_PTR
+ )
&& !EDGE_INFO (e)->ignore
&& (find_group (e->src) != find_group (e->dest)))
{
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Abnormal edge %d to %d put to tree\n",
+ e->src->index, e->dest->index);
EDGE_INFO (e)->on_tree = 1;
union_groups (e->src, e->dest);
}
}
- /* Now insert all critical edges to the tree unless they form an cycle. */
+ /* Now insert all critical edges to the tree unless they form a cycle. */
for (i = 0; i < num_edges; i++)
{
edge e = INDEX_EDGE (el, i);
@@ -904,6 +1156,9 @@ find_spanning_tree (el)
&& !EDGE_INFO (e)->ignore
&& (find_group (e->src) != find_group (e->dest)))
{
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Critical edge %d to %d put to tree\n",
+ e->src->index, e->dest->index);
EDGE_INFO (e)->on_tree = 1;
union_groups (e->src, e->dest);
}
@@ -916,15 +1171,16 @@ find_spanning_tree (el)
if (find_group (e->src) != find_group (e->dest)
&& !EDGE_INFO (e)->ignore)
{
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Normal edge %d to %d put to tree\n",
+ e->src->index, e->dest->index);
EDGE_INFO (e)->on_tree = 1;
union_groups (e->src, e->dest);
}
}
- EXIT_BLOCK_PTR->aux = NULL;
- ENTRY_BLOCK_PTR->aux = NULL;
- for (i = 0; i < n_basic_blocks; i++)
- BASIC_BLOCK (i)->aux = NULL;
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ bb->aux = NULL;
}
/* Perform file-level initialization for branch-prob processing. */
@@ -933,18 +1189,16 @@ void
init_branch_prob (filename)
const char *filename;
{
- long len;
+ int len = strlen (filename);
int i;
if (flag_test_coverage)
{
- int len = strlen (filename);
char *data_file, *bbg_file_name;
/* Open an output file for the basic block/line number map. */
data_file = (char *) alloca (len + 4);
strcpy (data_file, filename);
- strip_off_ending (data_file, len);
strcat (data_file, ".bb");
if ((bb_file = fopen (data_file, "wb")) == 0)
fatal_io_error ("can't open %s", data_file);
@@ -952,7 +1206,6 @@ init_branch_prob (filename)
/* Open an output file for the program flow graph. */
bbg_file_name = (char *) alloca (len + 5);
strcpy (bbg_file_name, filename);
- strip_off_ending (bbg_file_name, len);
strcat (bbg_file_name, ".bbg");
if ((bbg_file = fopen (bbg_file_name, "wb")) == 0)
fatal_io_error ("can't open %s", bbg_file_name);
@@ -962,24 +1215,16 @@ init_branch_prob (filename)
last_bb_file_name = 0;
}
+ da_file_name = (char *) xmalloc (len + 4);
+ strcpy (da_file_name, filename);
+ strcat (da_file_name, ".da");
+
if (flag_branch_probabilities)
{
- char *da_file_name;
-
- len = strlen (filename);
- da_file_name = (char *) alloca (len + 4);
- strcpy (da_file_name, filename);
- strip_off_ending (da_file_name, len);
- strcat (da_file_name, ".da");
- if ((da_file = fopen (da_file_name, "rb")) == 0)
+ da_file = fopen (da_file_name, "rb");
+ if (!da_file)
warning ("file %s not found, execution counts assumed to be zero",
da_file_name);
-
- /* The first word in the .da file gives the number of instrumented
- edges, which is not needed for our purposes. */
-
- if (da_file)
- __read_long (&len, da_file, 8);
}
if (profile_arc_flag)
@@ -1008,24 +1253,11 @@ end_branch_prob ()
{
fclose (bb_file);
fclose (bbg_file);
+ unlink (da_file_name);
}
- if (flag_branch_probabilities)
- {
- if (da_file)
- {
- long temp;
- /* This seems slightly dangerous, as it presumes the EOF
- flag will not be set until an attempt is made to read
- past the end of the file. */
- if (feof (da_file))
- error (".da file contents exhausted too early");
- /* Should be at end of file now. */
- if (__read_long (&temp, da_file, 8) == 0)
- error (".da file contents not exhausted");
- fclose (da_file);
- }
- }
+ if (flag_branch_probabilities && da_file)
+ fclose (da_file);
if (rtl_dump_file)
{
@@ -1063,7 +1295,7 @@ end_branch_prob ()
/* The label used by the edge profiling code. */
-static rtx profiler_label;
+static GTY(()) rtx profiler_label;
/* Initialize the profiler_label. */
@@ -1074,7 +1306,6 @@ init_edge_profiler ()
char buf[20];
ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", 2);
profiler_label = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
- ggc_add_rtx_root (&profiler_label, 1);
}
/* Output instructions as RTL to increment the edge execution count. */
@@ -1093,13 +1324,15 @@ gen_edge_profiler (edgeno)
tmp = plus_constant (tmp, GCOV_TYPE_SIZE / BITS_PER_UNIT * edgeno);
mem_ref = validize_mem (gen_rtx_MEM (mode, tmp));
+ set_mem_alias_set (mem_ref, new_alias_set ());
+
tmp = expand_simple_binop (mode, PLUS, mem_ref, const1_rtx,
mem_ref, 0, OPTAB_WIDEN);
if (tmp != mem_ref)
emit_move_insn (copy_rtx (mem_ref), tmp);
- sequence = gen_sequence ();
+ sequence = get_insns ();
end_sequence ();
return sequence;
}
@@ -1117,9 +1350,6 @@ output_func_start_profiler ()
rtx table_address;
enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
int save_flag_inline_functions = flag_inline_functions;
- int save_flag_test_coverage = flag_test_coverage;
- int save_profile_arc_flag = profile_arc_flag;
- int save_flag_branch_probabilities = flag_branch_probabilities;
/* It's either already been output, or we don't need it because we're
not doing profile-edges. */
@@ -1153,15 +1383,16 @@ output_func_start_profiler ()
DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
- fndecl = pushdecl (fndecl);
+ fndecl = (*lang_hooks.decls.pushdecl) (fndecl);
rest_of_decl_compilation (fndecl, 0, 1, 0);
announce_function (fndecl);
current_function_decl = fndecl;
DECL_INITIAL (fndecl) = error_mark_node;
make_decl_rtl (fndecl, NULL);
init_function_start (fndecl, input_filename, lineno);
- pushlevel (0);
+ (*lang_hooks.decls.pushlevel) (0);
expand_function_start (fndecl, 0);
+ cfun->arc_profile = 0;
/* Actually generate the code to call __bb_init_func. */
ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", 0);
@@ -1171,27 +1402,17 @@ output_func_start_profiler ()
mode, 1, table_address, Pmode);
expand_function_end (input_filename, lineno, 0);
- poplevel (1, 0, 1);
+ (*lang_hooks.decls.poplevel) (1, 0, 1);
/* Since fndecl isn't in the list of globals, it would never be emitted
when it's considered to be 'safe' for inlining, so turn off
flag_inline_functions. */
flag_inline_functions = 0;
- /* Don't instrument the function that turns on instrumentation. Which
- is also handy since we'd get silly warnings about not consuming all
- of our da_file input. */
- flag_test_coverage = 0;
- profile_arc_flag = 0;
- flag_branch_probabilities = 0;
-
rest_of_compilation (fndecl);
/* Reset flag_inline_functions to its original value. */
flag_inline_functions = save_flag_inline_functions;
- flag_test_coverage = save_flag_test_coverage;
- profile_arc_flag = save_profile_arc_flag;
- flag_branch_probabilities = save_flag_branch_probabilities;
if (! quiet_flag)
fflush (asm_out_file);
@@ -1201,3 +1422,5 @@ output_func_start_profiler ()
(* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
DEFAULT_INIT_PRIORITY);
}
+
+#include "gt-profile.h"
diff --git a/contrib/gcc/profile.h b/contrib/gcc/profile.h
new file mode 100644
index 0000000..609b0d3
--- /dev/null
+++ b/contrib/gcc/profile.h
@@ -0,0 +1,54 @@
+/* profile.h - Defines data exported from profile.c to other passes.
+ Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#ifndef GCC_PROFILE_H
+#define GCC_PROFILE_H
+
+struct profile_info
+ {
+ /* Used by final, for allocating the proper amount of storage for the
+ instrumented arc execution counts. */
+
+ int count_instrumented_edges;
+
+ /* Used by final, for writing correct # of instrumented edges
+ in this function. */
+
+ int count_edges_instrumented_now;
+
+ /* Checksum of the cfg. Used for 'identification' of code.
+ Used by final. */
+
+ long current_function_cfg_checksum;
+
+ /* Max. value of counter in program corresponding to the profile data
+ for the current function. */
+
+ gcov_type max_counter_in_program;
+
+ /* The number of profiles merged to form the profile data for the current
+ function. */
+ int count_profiles_merged;
+
+ };
+
+extern struct profile_info profile_info;
+
+#endif
diff --git a/contrib/gcc/protoize.c b/contrib/gcc/protoize.c
index 3b710a5..e039d6d 100644
--- a/contrib/gcc/protoize.c
+++ b/contrib/gcc/protoize.c
@@ -128,10 +128,6 @@ static const char * const standard_exec_prefix = STANDARD_EXEC_PREFIX;
static const char * const target_machine = DEFAULT_TARGET_MACHINE;
static const char * const target_version = DEFAULT_TARGET_VERSION;
-#ifndef GET_ENV_PATH_LIST
-#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
-#endif
-
#endif /* !defined (UNPROTOIZE) */
/* Suffix of aux_info files. */
@@ -367,7 +363,7 @@ struct def_dec_info_struct {
static const char *pname;
-/* Error counter. Will be non-zero if we should give up at the next convenient
+/* Error counter. Will be nonzero if we should give up at the next convenient
stopping point. */
static int errors = 0;
@@ -577,8 +573,8 @@ substr (s1, s2)
int c;
for (p1 = s1, p2 = s2; (c = *p2); p1++, p2++)
- if (*p1 != c)
- goto outer;
+ if (*p1 != c)
+ goto outer;
return s1;
outer:
;
@@ -673,7 +669,7 @@ is_id_char (ch)
}
/* Give a message indicating the proper way to invoke this program and then
- exit with non-zero status. */
+ exit with nonzero status. */
static void
usage ()
@@ -730,8 +726,8 @@ file_could_be_converted (const char *path)
{
char *slash;
- slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
- DIR_SEPARATOR_2);
+ slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
+ DIR_SEPARATOR_2);
if (slash)
dir_last_slash = slash;
}
@@ -774,8 +770,8 @@ file_normally_convertible (const char *path)
{
char *slash;
- slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
- DIR_SEPARATOR_2);
+ slash = strrchr (dir_last_slash ? dir_last_slash : dir_name,
+ DIR_SEPARATOR_2);
if (slash)
dir_last_slash = slash;
}
@@ -789,7 +785,7 @@ file_normally_convertible (const char *path)
if (access (path, R_OK))
{
if (!quiet_flag)
- notice ("%s: warning: no read access for file `%s'\n",
+ notice ("%s: warning: no read access for file `%s'\n",
pname, shortpath (NULL, path));
return 0;
}
@@ -797,7 +793,7 @@ file_normally_convertible (const char *path)
if (access (path, W_OK))
{
if (!quiet_flag)
- notice ("%s: warning: no write access for file `%s'\n",
+ notice ("%s: warning: no write access for file `%s'\n",
pname, shortpath (NULL, path));
return 0;
}
@@ -805,7 +801,7 @@ file_normally_convertible (const char *path)
if (access (dir_name, W_OK))
{
if (!quiet_flag)
- notice ("%s: warning: no write access for dir containing `%s'\n",
+ notice ("%s: warning: no write access for dir containing `%s'\n",
pname, shortpath (NULL, path));
return 0;
}
@@ -870,8 +866,8 @@ needs_to_be_converted (file_p)
#endif /* defined (UNPROTOIZE) */
)
- /* ... then the containing file needs converting. */
- return -1;
+ /* ... then the containing file needs converting. */
+ return -1;
return 0;
}
@@ -955,11 +951,11 @@ visit_each_hash_node (hash_tab_p, func)
for (primary = hash_tab_p; primary < &hash_tab_p[HASH_TABLE_SIZE]; primary++)
if (primary->symbol)
{
- hash_table_entry *second;
+ hash_table_entry *second;
- (*func)(primary);
- for (second = primary->hash_next; second; second = second->hash_next)
- (*func) (second);
+ (*func)(primary);
+ for (second = primary->hash_next; second; second = second->hash_next)
+ (*func) (second);
}
}
@@ -1006,7 +1002,7 @@ lookup (hash_tab_p, search_symbol)
{
p = p->hash_next;
if (!strcmp (p->symbol, search_symbol))
- return p;
+ return p;
}
p->hash_next = (hash_table_entry *) xmalloc (sizeof (hash_table_entry));
p = p->hash_next;
@@ -1031,8 +1027,8 @@ free_def_dec (p)
for (curr = p->f_list_chain; curr; curr = next)
{
- next = curr->chain_next;
- free ((NONCONST PTR) curr);
+ next = curr->chain_next;
+ free ((NONCONST PTR) curr);
}
}
#endif /* !defined (UNPROTOIZE) */
@@ -1069,14 +1065,14 @@ unexpand_if_needed (aux_info_line)
for (s = aux_info_line; *s != '\n'; )
{
for (unexp_p = unexpansions; unexp_p->expanded; unexp_p++)
- {
- const char *in_p = unexp_p->expanded;
- size_t len = strlen (in_p);
+ {
+ const char *in_p = unexp_p->expanded;
+ size_t len = strlen (in_p);
- if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len]))
- {
+ if (*s == *in_p && !strncmp (s, in_p, len) && !is_id_char (s[len]))
+ {
int size = strlen (unexp_p->contracted);
- got_unexpanded = 1;
+ got_unexpanded = 1;
if (copy_p + size - line_buf >= line_buf_size)
{
int offset = copy_p - line_buf;
@@ -1085,16 +1081,16 @@ unexpand_if_needed (aux_info_line)
line_buf = (char *) xrealloc (line_buf, line_buf_size);
copy_p = line_buf + offset;
}
- strcpy (copy_p, unexp_p->contracted);
- copy_p += size;
+ strcpy (copy_p, unexp_p->contracted);
+ copy_p += size;
- /* Assume that there will not be another replacement required
- within the text just replaced. */
+ /* Assume that there will not be another replacement required
+ within the text just replaced. */
- s += len;
- goto continue_outer;
- }
- }
+ s += len;
+ goto continue_outer;
+ }
+ }
if (copy_p - line_buf == line_buf_size)
{
int offset = copy_p - line_buf;
@@ -1126,10 +1122,10 @@ is_abspath (path)
{
return (IS_DIR_SEPARATOR (path[0])
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
- /* Check for disk name on MS-DOS-based systems. */
- || (path[0] && path[1] == ':' && IS_DIR_SEPARATOR (path[2]))
+ /* Check for disk name on MS-DOS-based systems. */
+ || (path[0] && path[1] == ':' && IS_DIR_SEPARATOR (path[2]))
#endif
- );
+ );
}
/* Return the absolutized filename for the given relative
@@ -1162,16 +1158,16 @@ abspath (cwd, rel_filename)
if (! is_abspath (rel_filename))
{
- src_p = cwd2;
- while ((*endp++ = *src_p++))
- continue;
- *(endp-1) = DIR_SEPARATOR; /* overwrite null */
+ src_p = cwd2;
+ while ((*endp++ = *src_p++))
+ continue;
+ *(endp-1) = DIR_SEPARATOR; /* overwrite null */
}
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
else if (IS_DIR_SEPARATOR (rel_filename[0]))
{
- /* A path starting with a directory separator is considered absolute
- for dos based filesystems, but it's really not -- it's just the
+ /* A path starting with a directory separator is considered absolute
+ for dos based filesystems, but it's really not -- it's just the
convention used throughout GCC and it works. However, in this
case, we still need to prepend the drive spec from cwd_buffer. */
*endp++ = cwd2[0];
@@ -1195,42 +1191,42 @@ abspath (cwd, rel_filename)
for (;;)
{
if (!inp[0])
- break;
+ break;
else if (IS_DIR_SEPARATOR (inp[0]) && IS_DIR_SEPARATOR (outp[-1]))
- {
- inp++;
- continue;
- }
+ {
+ inp++;
+ continue;
+ }
else if (inp[0] == '.' && IS_DIR_SEPARATOR (outp[-1]))
- {
- if (!inp[1])
- break;
- else if (IS_DIR_SEPARATOR (inp[1]))
- {
- inp += 2;
- continue;
- }
- else if ((inp[1] == '.') && (inp[2] == 0
+ {
+ if (!inp[1])
+ break;
+ else if (IS_DIR_SEPARATOR (inp[1]))
+ {
+ inp += 2;
+ continue;
+ }
+ else if ((inp[1] == '.') && (inp[2] == 0
|| IS_DIR_SEPARATOR (inp[2])))
- {
- inp += (IS_DIR_SEPARATOR (inp[2])) ? 3 : 2;
- outp -= 2;
- while (outp >= abs_buffer && ! IS_DIR_SEPARATOR (*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. */
-
- notice ("%s: invalid file name: %s\n",
- pname, rel_filename);
- exit (FATAL_EXIT_CODE);
- }
- *++outp = '\0';
- continue;
- }
- }
+ {
+ inp += (IS_DIR_SEPARATOR (inp[2])) ? 3 : 2;
+ outp -= 2;
+ while (outp >= abs_buffer && ! IS_DIR_SEPARATOR (*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. */
+
+ notice ("%s: invalid file name: %s\n",
+ pname, rel_filename);
+ exit (FATAL_EXIT_CODE);
+ }
+ *++outp = '\0';
+ continue;
+ }
+ }
*outp++ = *inp++;
}
@@ -1285,29 +1281,29 @@ shortpath (cwd, filename)
{
/* whole pwd matched */
if (!*path_p) /* input *is* the current path! */
- return ".";
+ return ".";
else
- return ++path_p;
+ return ++path_p;
}
else
{
if (*path_p)
- {
- --cwd_p;
- --path_p;
- while (! IS_DIR_SEPARATOR (*cwd_p)) /* backup to last slash */
- {
- --cwd_p;
- --path_p;
- }
- cwd_p++;
- path_p++;
- unmatched_slash_count++;
- }
+ {
+ --cwd_p;
+ --path_p;
+ while (! IS_DIR_SEPARATOR (*cwd_p)) /* backup to last slash */
+ {
+ --cwd_p;
+ --path_p;
+ }
+ cwd_p++;
+ path_p++;
+ unmatched_slash_count++;
+ }
/* Find out how many directory levels in cwd were *not* matched. */
while (*cwd_p++)
- if (IS_DIR_SEPARATOR (*(cwd_p-1)))
+ if (IS_DIR_SEPARATOR (*(cwd_p-1)))
unmatched_slash_count++;
/* Now we know how long the "short name" will be.
@@ -1317,15 +1313,15 @@ shortpath (cwd, filename)
/* For each of them, put a `../' at the beginning of the short name. */
while (unmatched_slash_count--)
- {
+ {
/* Give up if the result gets to be longer
than the absolute path name. */
if (rel_buffer + filename_len <= rel_buf_p + 3)
return filename;
- *rel_buf_p++ = '.';
- *rel_buf_p++ = '.';
- *rel_buf_p++ = DIR_SEPARATOR;
- }
+ *rel_buf_p++ = '.';
+ *rel_buf_p++ = '.';
+ *rel_buf_p++ = DIR_SEPARATOR;
+ }
/* Then tack on the unmatched part of the desired file's name. */
do
@@ -1337,7 +1333,7 @@ shortpath (cwd, filename)
--rel_buf_p;
if (IS_DIR_SEPARATOR (*(rel_buf_p-1)))
- *--rel_buf_p = '\0';
+ *--rel_buf_p = '\0';
return rel_buffer;
}
}
@@ -1366,21 +1362,21 @@ find_file (filename, do_not_stat)
file_info *file_p = (file_info *) xmalloc (sizeof (file_info));
/* If we cannot get status on any given source file, give a warning
- and then just set its time of last modification to infinity. */
+ and then just set its time of last modification to infinity. */
if (do_not_stat)
- stat_buf.st_mtime = (time_t) 0;
+ stat_buf.st_mtime = (time_t) 0;
else
- {
- if (stat (filename, &stat_buf) == -1)
- {
+ {
+ if (stat (filename, &stat_buf) == -1)
+ {
int errno_val = errno;
- notice ("%s: %s: can't get status: %s\n",
+ notice ("%s: %s: can't get status: %s\n",
pname, shortpath (NULL, filename),
xstrerror (errno_val));
- stat_buf.st_mtime = (time_t) -1;
- }
- }
+ stat_buf.st_mtime = (time_t) -1;
+ }
+ }
hash_entry_p->fip = file_p;
file_p->hash_entry = hash_entry_p;
@@ -1426,14 +1422,14 @@ find_corresponding_lparen (p)
for (paren_depth = 1, q = p-1; paren_depth; q--)
{
switch (*q)
- {
- case ')':
- paren_depth++;
- break;
- case '(':
- paren_depth--;
- break;
- }
+ {
+ case ')':
+ paren_depth++;
+ break;
+ case '(':
+ paren_depth--;
+ break;
+ }
}
return ++q;
}
@@ -1441,7 +1437,7 @@ find_corresponding_lparen (p)
/* Given a line from an aux info file, and a time at which the aux info
file it came from was created, check to see if the item described in
the line comes from a file which has been modified since the aux info
- file was created. If so, return non-zero, else return zero. */
+ file was created. If so, return nonzero, else return zero. */
static int
referenced_file_is_newer (l, aux_info_mtime)
@@ -1461,9 +1457,9 @@ referenced_file_is_newer (l, aux_info_mtime)
while (*p != ':'
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
- || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
+ || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
#endif
- )
+ )
p++;
filename = (char *) alloca ((size_t) (p - filename_start) + 1);
strncpy (filename, filename_start, (size_t) (p - filename_start));
@@ -1523,9 +1519,9 @@ save_def_or_dec (l, is_syscalls)
while (*p != ':'
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
- || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
+ || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
#endif
- )
+ )
p++;
filename = (char *) alloca ((size_t) (p - filename_start) + 1);
strncpy (filename, filename_start, (size_t) (p - filename_start));
@@ -1535,7 +1531,7 @@ save_def_or_dec (l, is_syscalls)
which contained this particular def or dec item. Note that this call
may cause a new file_info record to be created if this is the first time
that we have ever known about this particular file.
-
+
Note that we started out by forcing all of the base source file names
(i.e. the names of the aux_info files with the .X stripped off) into the
filenames hash table, and we simultaneously setup file_info records for
@@ -1544,7 +1540,7 @@ save_def_or_dec (l, is_syscalls)
act as file_info records for the "original" (i.e. un-included) files
which were submitted to gcc for compilation (when the -aux-info
option was used). */
-
+
def_dec_p->file = find_file (abspath (invocation_filename, filename), is_syscalls);
}
@@ -1554,9 +1550,9 @@ save_def_or_dec (l, is_syscalls)
while (*p != ':'
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
- || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
+ || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
#endif
- )
+ )
p++;
strncpy (line_number, line_number_start, (size_t) (p - line_number_start));
line_number[p-line_number_start] = '\0';
@@ -1657,16 +1653,16 @@ 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 *cip
= (f_list_chain_item *) xmalloc (sizeof (f_list_chain_item));
- cip->formals_list
+ cip->formals_list
= dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1)));
-
- /* Add the new chain item at the head of the current list. */
- cip->chain_next = def_dec_p->f_list_chain;
- def_dec_p->f_list_chain = cip;
+ /* Add the new chain item at the head of the current list. */
+
+ cip->chain_next = def_dec_p->f_list_chain;
+ def_dec_p->f_list_chain = cip;
}
#endif /* !defined (UNPROTOIZE) */
def_dec_p->f_list_count++;
@@ -1674,15 +1670,15 @@ save_def_or_dec (l, is_syscalls)
p = left_paren_p - 2;
/* p must now point either to another right paren, or to the last
- character of the name of the function that was declared/defined.
- If p points to another right paren, then this indicates that we
- are dealing with multiple formals lists. In that case, there
- really should be another right paren preceding this right paren. */
+ character of the name of the function that was declared/defined.
+ If p points to another right paren, then this indicates that we
+ are dealing with multiple formals lists. In that case, there
+ really should be another right paren preceding this right paren. */
if (*p != ')')
- break;
+ break;
else
- check_aux_info (*--p == ')');
+ check_aux_info (*--p == ')');
}
@@ -1728,19 +1724,19 @@ save_def_or_dec (l, is_syscalls)
for (other = def_dec_p->hash_entry->ddip; other; other = other->next_for_func)
{
- if (def_dec_p->line == other->line && def_dec_p->file == other->file)
- {
- if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
- {
- notice ("%s:%d: declaration of function `%s' takes different forms\n",
+ if (def_dec_p->line == other->line && def_dec_p->file == other->file)
+ {
+ if (strcmp (def_dec_p->ansi_decl, other->ansi_decl))
+ {
+ notice ("%s:%d: declaration of function `%s' takes different forms\n",
def_dec_p->file->hash_entry->symbol,
def_dec_p->line,
def_dec_p->hash_entry->symbol);
- exit (FATAL_EXIT_CODE);
- }
- free_def_dec (def_dec_p);
- return;
- }
+ exit (FATAL_EXIT_CODE);
+ }
+ free_def_dec (def_dec_p);
+ return;
+ }
}
}
@@ -1772,15 +1768,15 @@ 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;
- p--; /* point to closing right paren */
+ while (*p++ != ')')
+ continue;
+ p--; /* point to closing right paren */
- /* Make a copy of the K&R parameter names list. */
+ /* Make a copy of the K&R parameter names list. */
- def_dec_p->formal_names
+ def_dec_p->formal_names
= dupnstr (kr_names_start, (size_t) (p - kr_names_start));
}
@@ -1788,42 +1784,42 @@ save_def_or_dec (l, is_syscalls)
p++;
/* p now points to the first character of the K&R style declarations
- list (if there is one) or to the star-slash combination that ends
- the comment in which such lists get embedded. */
+ list (if there is one) or to the star-slash combination that ends
+ the comment in which such lists get embedded. */
/* Make a copy of the K&R formal decls list and set the def_dec record
- to point to it. */
+ to point to it. */
if (*p == '*') /* Are there no K&R declarations? */
- {
- check_aux_info (*++p == '/');
- def_dec_p->formal_decls = "";
- }
+ {
+ check_aux_info (*++p == '/');
+ def_dec_p->formal_decls = "";
+ }
else
- {
- const char *kr_decls_start = p;
+ {
+ const char *kr_decls_start = p;
- while (p[0] != '*' || p[1] != '/')
- p++;
- p--;
+ while (p[0] != '*' || p[1] != '/')
+ p++;
+ p--;
- check_aux_info (*p == ' ');
+ check_aux_info (*p == ' ');
- def_dec_p->formal_decls
+ def_dec_p->formal_decls
= dupnstr (kr_decls_start, (size_t) (p - kr_decls_start));
- }
+ }
/* Handle a special case. If we have a function definition marked as
- being in "old" style, and if its formal names list is empty, then
- it may actually have the string "void" in its real formals list
- in the original source code. Just to make sure, we will get setup
- to convert such things anyway.
+ being in "old" style, and if its formal names list is empty, then
+ it may actually have the string "void" in its real formals list
+ in the original source code. Just to make sure, we will get setup
+ to convert such things anyway.
- This kludge only needs to be here because of an insurmountable
- problem with generating .X files. */
+ This kludge only needs to be here because of an insurmountable
+ problem with generating .X files. */
if (!def_dec_p->prototyped && !*def_dec_p->formal_names)
- def_dec_p->prototyped = 1;
+ def_dec_p->prototyped = 1;
}
/* Since we are unprotoizing, if this item is already in old (K&R) style,
@@ -1861,25 +1857,25 @@ save_def_or_dec (l, is_syscalls)
const def_dec_info *next = curr->next_in_file;
while (next && (line < curr->line))
- {
- prev = curr;
- curr = next;
- next = next->next_in_file;
- }
+ {
+ prev = curr;
+ curr = next;
+ next = next->next_in_file;
+ }
if (line >= curr->line)
- {
- def_dec_p->next_in_file = curr;
- if (prev)
- ((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p;
- else
- def_dec_p->file->defs_decs = def_dec_p;
- }
+ {
+ def_dec_p->next_in_file = curr;
+ if (prev)
+ ((NONCONST def_dec_info *) prev)->next_in_file = def_dec_p;
+ else
+ def_dec_p->file->defs_decs = def_dec_p;
+ }
else /* assert (next == NULL); */
- {
- ((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p;
- /* assert (next == NULL); */
- def_dec_p->next_in_file = next;
- }
+ {
+ ((NONCONST def_dec_info *) curr)->next_in_file = def_dec_p;
+ /* assert (next == NULL); */
+ def_dec_p->next_in_file = next;
+ }
}
}
@@ -1906,38 +1902,38 @@ munge_compile_params (params_list)
for (;;)
{
while (ISSPACE ((const unsigned char)*params_list))
- params_list++;
+ params_list++;
if (!*params_list)
- break;
+ break;
param = params_list;
while (*params_list && !ISSPACE ((const unsigned char)*params_list))
- params_list++;
+ params_list++;
if (param[0] != '-')
- temp_params[param_count++]
+ temp_params[param_count++]
= dupnstr (param, (size_t) (params_list - param));
else
- {
- switch (param[1])
- {
- case 'g':
- case 'O':
- case 'S':
- case 'c':
- break; /* Don't copy these. */
- case 'o':
- while (ISSPACE ((const unsigned char)*params_list))
- params_list++;
- while (*params_list
- && !ISSPACE ((const unsigned char)*params_list))
- params_list++;
- break;
- default:
- temp_params[param_count++]
- = dupnstr (param, (size_t) (params_list - param));
- }
- }
+ {
+ switch (param[1])
+ {
+ case 'g':
+ case 'O':
+ case 'S':
+ case 'c':
+ break; /* Don't copy these. */
+ case 'o':
+ while (ISSPACE ((const unsigned char)*params_list))
+ params_list++;
+ while (*params_list
+ && !ISSPACE ((const unsigned char)*params_list))
+ params_list++;
+ break;
+ default:
+ temp_params[param_count++]
+ = dupnstr (param, (size_t) (params_list - param));
+ }
+ }
if (!*params_list)
- break;
+ break;
}
temp_params[param_count++] = "-aux-info";
@@ -1947,7 +1943,7 @@ munge_compile_params (params_list)
temp_params[param_count++] = "-S";
temp_params[param_count++] = "-o";
-
+
if ((stat (HOST_BIT_BUCKET, &st) == 0)
&& (!S_ISDIR (st.st_mode))
&& (access (HOST_BIT_BUCKET, W_OK) == 0))
@@ -1988,7 +1984,7 @@ gen_aux_info_file (base_filename)
/* Add .X to source file name to get aux-info file name. */
compile_params[aux_info_file_name_index] =
concat (compile_params[input_file_name_index], aux_info_suffix, NULL);
-
+
if (!quiet_flag)
notice ("%s: compiling `%s'\n",
pname, compile_params[input_file_name_index]);
@@ -2128,27 +2124,27 @@ start_over: ;
struct stat stat_buf;
/* Get some status information about this aux_info file. */
-
+
if (stat (aux_info_filename, &stat_buf) == -1)
{
int errno_val = errno;
- notice ("%s: can't get status of aux info file `%s': %s\n",
+ notice ("%s: can't get status of aux info file `%s': %s\n",
pname, shortpath (NULL, aux_info_filename),
xstrerror (errno_val));
- errors++;
- return;
+ errors++;
+ return;
}
-
+
/* Check on whether or not this aux_info file is zero length. If it is,
then just ignore it and return. */
-
+
if ((aux_info_size = stat_buf.st_size) == 0)
return;
-
+
/* Get the date/time of last modification for this aux_info file and
remember it. We will have to check that any source files that it
contains information about are at least this old or older. */
-
+
aux_info_mtime = stat_buf.st_mtime;
if (!is_syscalls)
@@ -2179,7 +2175,7 @@ start_over: ;
int fd_flags;
/* Open the aux_info file. */
-
+
fd_flags = O_RDONLY;
#ifdef O_BINARY
/* Use binary mode to avoid having to deal with different EOL characters. */
@@ -2188,43 +2184,43 @@ start_over: ;
if ((aux_info_file = open (aux_info_filename, fd_flags, 0444 )) == -1)
{
int errno_val = errno;
- notice ("%s: can't open aux info file `%s' for reading: %s\n",
+ notice ("%s: can't open aux info file `%s' for reading: %s\n",
pname, shortpath (NULL, aux_info_filename),
xstrerror (errno_val));
- return;
+ return;
}
-
+
/* Allocate space to hold the aux_info file in memory. */
-
+
aux_info_base = xmalloc (aux_info_size + 1);
aux_info_limit = aux_info_base + aux_info_size;
*aux_info_limit = '\0';
-
+
/* Read the aux_info file into memory. */
-
+
if (safe_read (aux_info_file, aux_info_base, aux_info_size) !=
(int) aux_info_size)
{
int errno_val = errno;
- notice ("%s: error reading aux info file `%s': %s\n",
+ notice ("%s: error reading aux info file `%s': %s\n",
pname, shortpath (NULL, aux_info_filename),
xstrerror (errno_val));
- free (aux_info_base);
- close (aux_info_file);
- return;
+ free (aux_info_base);
+ close (aux_info_file);
+ return;
}
-
+
/* Close the aux info file. */
-
+
if (close (aux_info_file))
{
int errno_val = errno;
- notice ("%s: error closing aux info file `%s': %s\n",
+ notice ("%s: error closing aux info file `%s': %s\n",
pname, shortpath (NULL, aux_info_filename),
xstrerror (errno_val));
- free (aux_info_base);
- close (aux_info_file);
- return;
+ free (aux_info_base);
+ close (aux_info_file);
+ return;
}
}
@@ -2252,9 +2248,9 @@ start_over: ;
while (*p != ':'
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
- || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
+ || (*p == ':' && *p && *(p+1) && IS_DIR_SEPARATOR (*(p+1)))
#endif
- )
+ )
p++;
p++;
while (*p == ' ')
@@ -2280,8 +2276,8 @@ start_over: ;
{
char *slash;
- slash = strrchr (dir_end ? dir_end : aux_info_relocated_name,
- DIR_SEPARATOR_2);
+ slash = strrchr (dir_end ? dir_end : aux_info_relocated_name,
+ DIR_SEPARATOR_2);
if (slash)
dir_end = slash;
}
@@ -2306,58 +2302,58 @@ start_over: ;
if (!is_syscalls)
{
- current_aux_info_lineno = 2;
-
- for (aux_info_p = aux_info_second_line; *aux_info_p; )
- {
- if (referenced_file_is_newer (aux_info_p, aux_info_mtime))
- {
- free (aux_info_base);
+ current_aux_info_lineno = 2;
+
+ for (aux_info_p = aux_info_second_line; *aux_info_p; )
+ {
+ if (referenced_file_is_newer (aux_info_p, aux_info_mtime))
+ {
+ free (aux_info_base);
free (aux_info_relocated_name);
- if (keep_it && unlink (aux_info_filename) == -1)
- {
+ if (keep_it && unlink (aux_info_filename) == -1)
+ {
int errno_val = errno;
- notice ("%s: can't delete file `%s': %s\n",
+ notice ("%s: can't delete file `%s': %s\n",
pname, shortpath (NULL, aux_info_filename),
xstrerror (errno_val));
- return;
- }
+ return;
+ }
must_create = 1;
- goto start_over;
- }
-
- /* Skip over the rest of this line to start of next line. */
-
- while (*aux_info_p != '\n')
- aux_info_p++;
- aux_info_p++;
- current_aux_info_lineno++;
- }
+ goto start_over;
+ }
+
+ /* Skip over the rest of this line to start of next line. */
+
+ while (*aux_info_p != '\n')
+ aux_info_p++;
+ aux_info_p++;
+ current_aux_info_lineno++;
+ }
}
/* Now do the real pass on the aux_info lines. Save their information in
the in-core data base. */
-
+
current_aux_info_lineno = 2;
-
+
for (aux_info_p = aux_info_second_line; *aux_info_p;)
{
- char *unexpanded_line = unexpand_if_needed (aux_info_p);
-
- if (unexpanded_line)
- {
- save_def_or_dec (unexpanded_line, is_syscalls);
- free (unexpanded_line);
- }
- else
- save_def_or_dec (aux_info_p, is_syscalls);
-
- /* Skip over the rest of this line and get to start of next line. */
-
- while (*aux_info_p != '\n')
- aux_info_p++;
- aux_info_p++;
- current_aux_info_lineno++;
+ char *unexpanded_line = unexpand_if_needed (aux_info_p);
+
+ if (unexpanded_line)
+ {
+ save_def_or_dec (unexpanded_line, is_syscalls);
+ free (unexpanded_line);
+ }
+ else
+ save_def_or_dec (aux_info_p, is_syscalls);
+
+ /* Skip over the rest of this line and get to start of next line. */
+
+ while (*aux_info_p != '\n')
+ aux_info_p++;
+ aux_info_p++;
+ current_aux_info_lineno++;
}
}
@@ -2377,8 +2373,8 @@ rename_c_file (hp)
{
const char *filename = hp->symbol;
int last_char_index = strlen (filename) - 1;
- char *const new_filename = (char *) alloca (strlen (filename)
- + strlen (cplus_suffix) + 1);
+ char *const new_filename = (char *) alloca (strlen (filename)
+ + strlen (cplus_suffix) + 1);
/* Note that we don't care here if the given file was converted or not. It
is possible that the given file was *not* converted, simply because there
@@ -2496,51 +2492,51 @@ find_extern_def (head, user)
for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
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. */
- else
- {
- /* Ignore definition just found if it came from SYSCALLS.c.X. */
-
- if (is_syscalls_file (dd_p->file))
- continue;
-
- /* Quietly replace the definition previously found with the one
- just found if the previous one was from SYSCALLS.c.X. */
-
- if (is_syscalls_file (extern_def_p->file))
- {
- extern_def_p = dd_p;
- continue;
- }
-
- /* If we get here, then there is a conflict between two function
- declarations for the same function, both of which came from the
- user's own code. */
-
- if (!conflict_noted) /* first time we noticed? */
- {
- conflict_noted = 1;
- notice ("%s: conflicting extern definitions of '%s'\n",
+ if (!extern_def_p) /* Previous definition? */
+ extern_def_p = dd_p; /* Remember the first definition found. */
+ else
+ {
+ /* Ignore definition just found if it came from SYSCALLS.c.X. */
+
+ if (is_syscalls_file (dd_p->file))
+ continue;
+
+ /* Quietly replace the definition previously found with the one
+ just found if the previous one was from SYSCALLS.c.X. */
+
+ if (is_syscalls_file (extern_def_p->file))
+ {
+ extern_def_p = dd_p;
+ continue;
+ }
+
+ /* If we get here, then there is a conflict between two function
+ declarations for the same function, both of which came from the
+ user's own code. */
+
+ if (!conflict_noted) /* first time we noticed? */
+ {
+ conflict_noted = 1;
+ notice ("%s: conflicting extern definitions of '%s'\n",
pname, head->hash_entry->symbol);
- if (!quiet_flag)
- {
- notice ("%s: declarations of '%s' will not be converted\n",
+ if (!quiet_flag)
+ {
+ notice ("%s: declarations of '%s' will not be converted\n",
pname, head->hash_entry->symbol);
- notice ("%s: conflict list for '%s' follows:\n",
+ notice ("%s: conflict list for '%s' follows:\n",
pname, head->hash_entry->symbol);
- fprintf (stderr, "%s: %s(%d): %s\n",
+ fprintf (stderr, "%s: %s(%d): %s\n",
pname,
shortpath (NULL, extern_def_p->file->hash_entry->symbol),
extern_def_p->line, extern_def_p->ansi_decl);
- }
- }
- if (!quiet_flag)
- fprintf (stderr, "%s: %s(%d): %s\n",
+ }
+ }
+ if (!quiet_flag)
+ fprintf (stderr, "%s: %s(%d): %s\n",
pname,
shortpath (NULL, dd_p->file->hash_entry->symbol),
dd_p->line, dd_p->ansi_decl);
- }
+ }
}
/* We want to err on the side of caution, so if we found multiple conflicting
@@ -2553,64 +2549,64 @@ find_extern_def (head, user)
if (!extern_def_p)
{
/* We have no definitions for this function so do the next best thing.
- Search for an extern declaration already in prototype form. */
+ Search for an extern declaration already in prototype form. */
for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
- if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped)
- {
- extern_def_p = dd_p; /* save a pointer to the definition */
- if (!quiet_flag)
- notice ("%s: warning: using formals list from %s(%d) for function `%s'\n",
+ if (!dd_p->is_func_def && !dd_p->is_static && dd_p->prototyped)
+ {
+ extern_def_p = dd_p; /* save a pointer to the definition */
+ if (!quiet_flag)
+ notice ("%s: warning: using formals list from %s(%d) for function `%s'\n",
pname,
shortpath (NULL, dd_p->file->hash_entry->symbol),
dd_p->line, dd_p->hash_entry->symbol);
- break;
- }
+ break;
+ }
/* Gripe about unprototyped function declarations that we found no
- corresponding definition (or other source of prototype information)
- for.
+ corresponding definition (or other source of prototype information)
+ for.
- Gripe even if the unprototyped declaration we are worried about
- exists in a file in one of the "system" include directories. We
- can gripe about these because we should have at least found a
- corresponding (pseudo) definition in the SYSCALLS.c.X file. If we
+ Gripe even if the unprototyped declaration we are worried about
+ exists in a file in one of the "system" include directories. We
+ can gripe about these because we should have at least found a
+ corresponding (pseudo) definition in the SYSCALLS.c.X file. If we
didn't, then that means that the SYSCALLS.c.X file is missing some
- needed prototypes for this particular system. That is worth telling
- the user about! */
+ needed prototypes for this particular system. That is worth telling
+ the user about! */
if (!extern_def_p)
- {
- const char *file = user->file->hash_entry->symbol;
+ {
+ const char *file = user->file->hash_entry->symbol;
- if (!quiet_flag)
- if (in_system_include_dir (file))
- {
+ if (!quiet_flag)
+ if (in_system_include_dir (file))
+ {
/* Why copy this string into `needed' at all?
Why not just use user->ansi_decl without copying? */
char *needed = (char *) alloca (strlen (user->ansi_decl) + 1);
- char *p;
+ char *p;
- strcpy (needed, user->ansi_decl);
- p = (NONCONST char *) substr (needed, user->hash_entry->symbol)
- + strlen (user->hash_entry->symbol) + 2;
+ strcpy (needed, user->ansi_decl);
+ p = (NONCONST char *) substr (needed, user->hash_entry->symbol)
+ + strlen (user->hash_entry->symbol) + 2;
/* Avoid having ??? in the string. */
*p++ = '?';
*p++ = '?';
*p++ = '?';
- strcpy (p, ");");
+ strcpy (p, ");");
- notice ("%s: %d: `%s' used but missing from SYSCALLS\n",
+ notice ("%s: %d: `%s' used but missing from SYSCALLS\n",
shortpath (NULL, file), user->line,
needed+7); /* Don't print "extern " */
- }
+ }
#if 0
- else
- notice ("%s: %d: warning: no extern definition for `%s'\n",
+ else
+ notice ("%s: %d: warning: no extern definition for `%s'\n",
shortpath (NULL, file), user->line,
user->hash_entry->symbol);
#endif
- }
+ }
}
return extern_def_p;
}
@@ -2631,13 +2627,13 @@ find_static_definition (user)
for (dd_p = head; dd_p; dd_p = dd_p->next_for_func)
if (dd_p->is_func_def && dd_p->is_static && (dd_p->file == user->file))
{
- static_def_p = dd_p; /* save a pointer to the definition */
- num_static_defs++;
+ static_def_p = dd_p; /* save a pointer to the definition */
+ num_static_defs++;
}
if (num_static_defs == 0)
{
if (!quiet_flag)
- notice ("%s: warning: no static definition for `%s' in file `%s'\n",
+ notice ("%s: warning: no static definition for `%s' in file `%s'\n",
pname, head->hash_entry->symbol,
shortpath (NULL, user->file->hash_entry->symbol));
}
@@ -2717,12 +2713,12 @@ connect_defs_and_decs (hp)
for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
if (!dd_p->is_func_def && !dd_p->is_static && !dd_p->definition)
{
- if (first_extern_reference)
- {
- extern_def_p = find_extern_def (hp->ddip, dd_p);
- first_extern_reference = 0;
- }
- ((NONCONST def_dec_info *) dd_p)->definition = extern_def_p;
+ if (first_extern_reference)
+ {
+ extern_def_p = find_extern_def (hp->ddip, dd_p);
+ first_extern_reference = 0;
+ }
+ ((NONCONST def_dec_info *) dd_p)->definition = extern_def_p;
}
/* Traverse the list of definitions and declarations for this particular
@@ -2748,37 +2744,37 @@ connect_defs_and_decs (hp)
for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
if (!dd_p->is_func_def && dd_p->is_static && !dd_p->definition)
{
- const def_dec_info *dd_p2;
- const def_dec_info *static_def;
-
- /* We have now found a single static declaration for which we need to
- find a matching definition. We want to minimize the work (and the
- number of warnings), so we will find an appropriate (matching)
- static definition for this declaration, and then distribute it
- (as the definition for) any and all other static declarations
- for this function name which occur within the same file, and which
- do not already have definitions.
-
- Note that a trick is used here to prevent subsequent attempts to
- call find_static_definition for a given function-name & file
- if the first such call returns NULL. Essentially, we convert
- these NULL return values to -1, and put the -1 into the definition
- field for each other static declaration from the same file which
- does not already have an associated definition.
- This makes these other static declarations look like they are
- actually defined already when the outer loop here revisits them
- later on. Thus, the outer loop will skip over them. Later, we
- turn the -1's back to NULL's. */
-
- ((NONCONST def_dec_info *) dd_p)->definition =
- (static_def = find_static_definition (dd_p))
- ? static_def
- : (const def_dec_info *) -1;
-
- for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func)
- if (!dd_p2->is_func_def && dd_p2->is_static
- && !dd_p2->definition && (dd_p2->file == dd_p->file))
- ((NONCONST def_dec_info *) dd_p2)->definition = dd_p->definition;
+ const def_dec_info *dd_p2;
+ const def_dec_info *static_def;
+
+ /* We have now found a single static declaration for which we need to
+ find a matching definition. We want to minimize the work (and the
+ number of warnings), so we will find an appropriate (matching)
+ static definition for this declaration, and then distribute it
+ (as the definition for) any and all other static declarations
+ for this function name which occur within the same file, and which
+ do not already have definitions.
+
+ Note that a trick is used here to prevent subsequent attempts to
+ call find_static_definition for a given function-name & file
+ if the first such call returns NULL. Essentially, we convert
+ these NULL return values to -1, and put the -1 into the definition
+ field for each other static declaration from the same file which
+ does not already have an associated definition.
+ This makes these other static declarations look like they are
+ actually defined already when the outer loop here revisits them
+ later on. Thus, the outer loop will skip over them. Later, we
+ turn the -1's back to NULL's. */
+
+ ((NONCONST def_dec_info *) dd_p)->definition =
+ (static_def = find_static_definition (dd_p))
+ ? static_def
+ : (const def_dec_info *) -1;
+
+ for (dd_p2 = dd_p->next_for_func; dd_p2; dd_p2 = dd_p2->next_for_func)
+ if (!dd_p2->is_func_def && dd_p2->is_static
+ && !dd_p2->definition && (dd_p2->file == dd_p->file))
+ ((NONCONST def_dec_info *) dd_p2)->definition = dd_p->definition;
}
/* Convert any dummy (-1) definitions we created in the step above back to
@@ -2816,10 +2812,10 @@ declare_source_confusing (clean_p)
if (!quiet_flag)
{
if (clean_p == 0)
- notice ("%s: %d: warning: source too confusing\n",
+ notice ("%s: %d: warning: source too confusing\n",
shortpath (NULL, convert_filename), last_known_line_number);
else
- notice ("%s: %d: warning: source too confusing\n",
+ notice ("%s: %d: warning: source too confusing\n",
shortpath (NULL, convert_filename),
identify_lineno (clean_p));
}
@@ -2864,7 +2860,7 @@ seek_to_line (n)
while (n > last_known_line_number)
{
while (*last_known_line_start != '\n')
- check_source (++last_known_line_start < clean_text_limit, 0);
+ check_source (++last_known_line_start < clean_text_limit, 0);
last_known_line_start++;
last_known_line_number++;
}
@@ -2979,12 +2975,12 @@ other_variable_style_function (ansi_header)
const char *candidate;
if ((candidate = substr (p, varargs_style_indicator)) == 0)
- return 0;
+ return 0;
else
- if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len]))
- return 1;
- else
- p = candidate + 1;
+ if (!is_id_char (candidate[-1]) && !is_id_char (candidate[len]))
+ return 1;
+ else
+ p = candidate + 1;
}
return 0;
#endif /* !defined (UNPROTOIZE) */
@@ -3025,7 +3021,7 @@ edit_fn_declaration (def_dec_p, clean_text_p)
if (other_variable_style_function (definition->ansi_decl))
{
if (!quiet_flag)
- notice ("%s: %d: warning: varargs function declaration not converted\n",
+ notice ("%s: %d: warning: varargs function declaration not converted\n",
shortpath (NULL, def_dec_p->file->hash_entry->symbol),
def_dec_p->line);
return;
@@ -3065,47 +3061,47 @@ edit_fn_declaration (def_dec_p, clean_text_p)
do
{
for (;;)
- {
- /* Scan leftwards until we find some character which can be
- part of an identifier. */
+ {
+ /* Scan leftwards until we find some character which can be
+ part of an identifier. */
+
+ while (!is_id_char (*clean_text_p))
+ check_source (--clean_text_p > clean_read_ptr, 0);
- while (!is_id_char (*clean_text_p))
- check_source (--clean_text_p > clean_read_ptr, 0);
+ /* Scan backwards until we find a char that cannot be part of an
+ identifier. */
- /* Scan backwards until we find a char that cannot be part of an
- identifier. */
+ while (is_id_char (*clean_text_p))
+ check_source (--clean_text_p > clean_read_ptr, 0);
- while (is_id_char (*clean_text_p))
- check_source (--clean_text_p > clean_read_ptr, 0);
+ /* Having found an "id break", see if the following id is the one
+ that we are looking for. If so, then exit from this loop. */
- /* Having found an "id break", see if the following id is the one
- that we are looking for. If so, then exit from this loop. */
+ if (!strncmp (clean_text_p+1, function_to_edit, func_name_len))
+ {
+ char ch = *(clean_text_p + 1 + func_name_len);
- if (!strncmp (clean_text_p+1, function_to_edit, func_name_len))
- {
- char ch = *(clean_text_p + 1 + func_name_len);
+ /* Must also check to see that the name in the source text
+ ends where it should (in order to prevent bogus matches
+ on similar but longer identifiers. */
- /* Must also check to see that the name in the source text
- ends where it should (in order to prevent bogus matches
- on similar but longer identifiers. */
+ if (! is_id_char (ch))
+ break; /* exit from loop */
+ }
+ }
- if (! is_id_char (ch))
- break; /* exit from loop */
- }
- }
-
/* We have now found the first perfect match for the function name in
- our backward search. This may or may not be the actual function
- name at the start of the actual function declaration (i.e. we could
- have easily been mislead). We will try to avoid getting fooled too
- often by looking forward for the open paren which should follow the
- identifier we just found. We ignore whitespace while hunting. If
- the next non-whitespace byte we see is *not* an open left paren,
- then we must assume that we have been fooled and we start over
- again accordingly. Note that there is no guarantee, that even if
- we do see the open paren, that we are in the right place.
- Programmers do the strangest things sometimes! */
-
+ our backward search. This may or may not be the actual function
+ name at the start of the actual function declaration (i.e. we could
+ have easily been mislead). We will try to avoid getting fooled too
+ often by looking forward for the open paren which should follow the
+ identifier we just found. We ignore whitespace while hunting. If
+ the next non-whitespace byte we see is *not* an open left paren,
+ then we must assume that we have been fooled and we start over
+ again accordingly. Note that there is no guarantee, that even if
+ we do see the open paren, that we are in the right place.
+ Programmers do the strangest things sometimes! */
+
end_of_fn_name = clean_text_p + strlen (def_dec_p->hash_entry->symbol);
start_formals = forward_to_next_token_char (end_of_fn_name);
}
@@ -3126,76 +3122,76 @@ edit_fn_declaration (def_dec_p, clean_text_p)
for (;;)
{
{
- int depth;
-
- end_formals = start_formals + 1;
- depth = 1;
- for (; depth; check_source (++end_formals < clean_text_limit, 0))
- {
- switch (*end_formals)
- {
- case '(':
- depth++;
- break;
- case ')':
- depth--;
- break;
- }
- }
- end_formals--;
+ int depth;
+
+ end_formals = start_formals + 1;
+ depth = 1;
+ for (; depth; check_source (++end_formals < clean_text_limit, 0))
+ {
+ switch (*end_formals)
+ {
+ case '(':
+ depth++;
+ break;
+ case ')':
+ depth--;
+ break;
+ }
+ }
+ end_formals--;
}
/* end_formals now points to the closing right paren of the formals
- list whose left paren is pointed to by start_formals. */
-
+ list whose left paren is pointed to by start_formals. */
+
/* Now, if we are protoizing, we insert the new ANSI-style formals list
- attached to the associated definition of this function. If however
- we are unprotoizing, then we simply delete any formals list which
- may be present. */
-
+ attached to the associated definition of this function. If however
+ we are unprotoizing, then we simply delete any formals list which
+ may be present. */
+
output_up_to (start_formals);
#ifndef UNPROTOIZE
if (this_f_list_chain_item)
- {
- output_string (this_f_list_chain_item->formals_list);
- this_f_list_chain_item = this_f_list_chain_item->chain_next;
- }
+ {
+ output_string (this_f_list_chain_item->formals_list);
+ this_f_list_chain_item = this_f_list_chain_item->chain_next;
+ }
else
- {
- if (!quiet_flag)
- notice ("%s: warning: too many parameter lists in declaration of `%s'\n",
+ {
+ if (!quiet_flag)
+ notice ("%s: warning: too many parameter lists in declaration of `%s'\n",
pname, def_dec_p->hash_entry->symbol);
- check_source (0, end_formals); /* leave the declaration intact */
- }
+ check_source (0, end_formals); /* leave the declaration intact */
+ }
#endif /* !defined (UNPROTOIZE) */
clean_read_ptr = end_formals - 1;
/* Now see if it looks like there may be another formals list associated
- with the function declaration that we are converting (following the
- formals list that we just converted. */
+ with the function declaration that we are converting (following the
+ formals list that we just converted. */
{
- const char *another_r_paren = forward_to_next_token_char (end_formals);
+ const char *another_r_paren = forward_to_next_token_char (end_formals);
- if ((*another_r_paren != ')')
- || (*(start_formals = forward_to_next_token_char (another_r_paren)) != '('))
- {
+ if ((*another_r_paren != ')')
+ || (*(start_formals = forward_to_next_token_char (another_r_paren)) != '('))
+ {
#ifndef UNPROTOIZE
- if (this_f_list_chain_item)
- {
- if (!quiet_flag)
- notice ("\n%s: warning: too few parameter lists in declaration of `%s'\n",
+ if (this_f_list_chain_item)
+ {
+ if (!quiet_flag)
+ notice ("\n%s: warning: too few parameter lists in declaration of `%s'\n",
pname, def_dec_p->hash_entry->symbol);
- check_source (0, start_formals); /* leave the decl intact */
- }
+ check_source (0, start_formals); /* leave the decl intact */
+ }
#endif /* !defined (UNPROTOIZE) */
- break;
-
- }
+ break;
+
+ }
}
/* There does appear to be yet another formals list, so loop around
- again, and convert it also. */
+ again, and convert it also. */
}
}
@@ -3206,7 +3202,7 @@ edit_fn_declaration (def_dec_p, clean_text_p)
list that lies to the left of the one it was originally called to work
on. Thus, a whole set gets done in right-to-left order.
- This routine returns non-zero if it thinks that it should not be trying
+ This routine returns nonzero if it thinks that it should not be trying
to convert this particular function definition (because the name of the
function doesn't match the one expected). */
@@ -3224,14 +3220,14 @@ edit_formals_lists (end_formals, f_list_count, def_dec_p)
for (; depth; check_source (--start_formals > clean_read_ptr, 0))
{
switch (*start_formals)
- {
- case '(':
- depth--;
- break;
- case ')':
- depth++;
- break;
- }
+ {
+ case '(':
+ depth--;
+ break;
+ case ')':
+ depth++;
+ break;
+ }
}
start_formals++;
@@ -3248,17 +3244,17 @@ edit_formals_lists (end_formals, f_list_count, def_dec_p)
next_end = start_formals - 1;
check_source (next_end > clean_read_ptr, 0);
while (ISSPACE ((const unsigned char)*next_end))
- check_source (--next_end > clean_read_ptr, 0);
+ check_source (--next_end > clean_read_ptr, 0);
check_source (*next_end == ')', next_end);
check_source (--next_end > clean_read_ptr, 0);
check_source (*next_end == ')', next_end);
if (edit_formals_lists (next_end, f_list_count, def_dec_p))
- return 1;
+ return 1;
}
/* Check that the function name in the header we are working on is the same
as the one we would expect to find. If not, issue a warning and return
- non-zero. */
+ nonzero. */
if (f_list_count == 0)
{
@@ -3269,26 +3265,26 @@ edit_formals_lists (end_formals, f_list_count, def_dec_p)
for (func_name_limit = start_formals-1;
ISSPACE ((const unsigned char)*func_name_limit); )
- check_source (--func_name_limit > clean_read_ptr, 0);
+ check_source (--func_name_limit > clean_read_ptr, 0);
for (func_name_start = func_name_limit++;
- is_id_char (*func_name_start);
- func_name_start--)
- check_source (func_name_start > clean_read_ptr, 0);
+ is_id_char (*func_name_start);
+ func_name_start--)
+ check_source (func_name_start > clean_read_ptr, 0);
func_name_start++;
func_name_len = func_name_limit - func_name_start;
if (func_name_len == 0)
- check_source (0, func_name_start);
+ check_source (0, func_name_start);
if (func_name_len != strlen (expected)
|| strncmp (func_name_start, expected, func_name_len))
- {
- notice ("%s: %d: warning: found `%s' but expected `%s'\n",
+ {
+ notice ("%s: %d: warning: found `%s' but expected `%s'\n",
shortpath (NULL, def_dec_p->file->hash_entry->symbol),
identify_lineno (func_name_start),
dupnstr (func_name_start, func_name_len),
expected);
- return 1;
- }
+ return 1;
+ }
}
output_up_to (start_formals);
@@ -3393,32 +3389,32 @@ find_rightmost_formals_list (clean_text_p)
/* Look leftward and try to find a right-paren. */
while (*end_formals != ')')
- {
- if (ISSPACE ((const unsigned char)*end_formals))
- while (ISSPACE ((const unsigned char)*end_formals))
- check_source (--end_formals > clean_read_ptr, 0);
- else
- check_source (--end_formals > clean_read_ptr, 0);
- }
+ {
+ if (ISSPACE ((const unsigned char)*end_formals))
+ while (ISSPACE ((const unsigned char)*end_formals))
+ check_source (--end_formals > clean_read_ptr, 0);
+ else
+ check_source (--end_formals > clean_read_ptr, 0);
+ }
ch = *(l_brace_p = forward_to_next_token_char (end_formals));
/* Since it is possible that we found a right paren before the starting
- '{' of the body which IS NOT the one at the end of the real K&R
- formals list (say for instance, we found one embedded inside one of
- the old K&R formal parameter declarations) we have to check to be
- sure that this is in fact the right paren that we were looking for.
+ '{' of the body which IS NOT the one at the end of the real K&R
+ formals list (say for instance, we found one embedded inside one of
+ the old K&R formal parameter declarations) we have to check to be
+ sure that this is in fact the right paren that we were looking for.
- The one we were looking for *must* be followed by either a '{' or
- by an alphabetic character, while others *cannot* validly be followed
- by such characters. */
+ The one we were looking for *must* be followed by either a '{' or
+ by an alphabetic character, while others *cannot* validly be followed
+ by such characters. */
if ((ch == '{') || ISALPHA ((unsigned char) ch))
- break;
+ break;
/* At this point, we have found a right paren, but we know that it is
- not the one we were looking for, so backup one character and keep
- looking. */
+ not the one we were looking for, so backup one character and keep
+ looking. */
check_source (--end_formals > clean_read_ptr, 0);
}
@@ -3487,9 +3483,9 @@ add_local_decl (def_dec_p, clean_text_p)
if (*start_of_block != '{')
{
if (!quiet_flag)
- notice ("\n%s: %d: warning: can't add declaration of `%s' into macro call\n",
- def_dec_p->file->hash_entry->symbol, def_dec_p->line,
- def_dec_p->hash_entry->symbol);
+ notice ("\n%s: %d: warning: can't add declaration of `%s' into macro call\n",
+ def_dec_p->file->hash_entry->symbol, def_dec_p->line,
+ def_dec_p->hash_entry->symbol);
return;
}
@@ -3516,18 +3512,18 @@ add_local_decl (def_dec_p, clean_text_p)
we just found. */
output_up_to (ep);
-
+
/* Now we go ahead and insert the new declaration at this point.
If the definition of the given function is in the same file that we
are currently editing, and if its full ANSI declaration normally
would start with the keyword `extern', suppress the `extern'. */
-
+
{
const char *decl = def_dec_p->definition->ansi_decl;
-
+
if ((*decl == 'e') && (def_dec_p->file == def_dec_p->definition->file))
- decl += 7;
+ decl += 7;
output_string (decl);
}
@@ -3575,10 +3571,10 @@ add_global_decls (file_p, clean_text_p)
for (;; --scan_p)
{
if (scan_p < clean_text_base)
- break;
+ break;
check_source (scan_p > clean_read_ptr, 0);
if (*scan_p == ';')
- break;
+ break;
}
/* scan_p now points either to a semicolon, or to just before the start
@@ -3602,24 +3598,24 @@ add_global_decls (file_p, clean_text_p)
{
int some_decls_added = 0;
-
+
for (dd_p = file_p->defs_decs; dd_p; dd_p = dd_p->next_in_file)
if (dd_p->is_implicit && dd_p->definition && !dd_p->definition->written)
- {
- const char *decl = dd_p->definition->ansi_decl;
-
- /* If the function for which we are inserting a declaration is
- actually defined later in the same file, then suppress the
- leading `extern' keyword (if there is one). */
-
- if (*decl == 'e' && (dd_p->file == dd_p->definition->file))
- decl += 7;
-
- output_string ("\n");
- output_string (decl);
- some_decls_added = 1;
- ((NONCONST def_dec_info *) dd_p->definition)->written = 1;
- }
+ {
+ const char *decl = dd_p->definition->ansi_decl;
+
+ /* If the function for which we are inserting a declaration is
+ actually defined later in the same file, then suppress the
+ leading `extern' keyword (if there is one). */
+
+ if (*decl == 'e' && (dd_p->file == dd_p->definition->file))
+ decl += 7;
+
+ output_string ("\n");
+ output_string (decl);
+ some_decls_added = 1;
+ ((NONCONST def_dec_info *) dd_p->definition)->written = 1;
+ }
if (some_decls_added)
output_string ("\n\n");
}
@@ -3667,13 +3663,13 @@ edit_fn_definition (def_dec_p, clean_text_p)
function with a variable number of arguments, and if the way it does
that is different from that way we would like it (i.e. varargs vs.
stdarg) then issue a warning and leave the header unconverted. */
-
+
if (other_variable_style_function (def_dec_p->ansi_decl))
{
if (!quiet_flag)
- notice ("%s: %d: warning: definition of %s not converted\n",
+ notice ("%s: %d: warning: definition of %s not converted\n",
shortpath (NULL, def_dec_p->file->hash_entry->symbol),
- identify_lineno (end_formals),
+ identify_lineno (end_formals),
other_var_style);
output_up_to (end_formals);
return;
@@ -3706,11 +3702,11 @@ edit_fn_definition (def_dec_p, clean_text_p)
limit_p = decl_p + strlen (decl_p);
for (;decl_p < limit_p; decl_p = semicolon_p + 2)
{
- for (semicolon_p = decl_p; *semicolon_p != ';'; semicolon_p++)
- continue;
- output_string ("\n");
- output_string (indent_string);
- output_bytes (decl_p, (size_t) ((semicolon_p + 1) - decl_p));
+ for (semicolon_p = decl_p; *semicolon_p != ';'; semicolon_p++)
+ continue;
+ output_string ("\n");
+ output_string (indent_string);
+ output_bytes (decl_p, (size_t) ((semicolon_p + 1) - decl_p));
}
/* If there are no newlines between the end of the formals list and the
@@ -3718,12 +3714,12 @@ edit_fn_definition (def_dec_p, clean_text_p)
for (scan_p = end_formals+1; *scan_p != '{'; )
{
- if (*scan_p == '\n')
- {
- had_newlines = 1;
- break;
- }
- check_source (++scan_p < clean_text_limit, 0);
+ if (*scan_p == '\n')
+ {
+ had_newlines = 1;
+ break;
+ }
+ check_source (++scan_p < clean_text_limit, 0);
}
if (!had_newlines)
output_string ("\n");
@@ -3754,24 +3750,24 @@ edit_fn_definition (def_dec_p, clean_text_p)
scan_orig = end_formals_orig + 1;
for (; scan < start_body; scan++, scan_orig++)
{
- if (*scan == *scan_orig)
- {
- have_newlines |= (*scan_orig == '\n');
- /* Leave identical whitespace alone. */
- if (!ISSPACE ((const unsigned char)*scan_orig))
- *((NONCONST char *) scan_orig) = ' '; /* identical - so whiteout */
- }
- else
- have_flotsam = 1;
+ if (*scan == *scan_orig)
+ {
+ have_newlines |= (*scan_orig == '\n');
+ /* Leave identical whitespace alone. */
+ if (!ISSPACE ((const unsigned char)*scan_orig))
+ *((NONCONST char *) scan_orig) = ' '; /* identical - so whiteout */
+ }
+ else
+ have_flotsam = 1;
}
if (have_flotsam)
output_bytes (end_formals_orig + 1,
(size_t) (start_body_orig - end_formals_orig) - 1);
else
if (have_newlines)
- output_string ("\n");
+ output_string ("\n");
else
- output_string (" ");
+ output_string (" ");
clean_read_ptr = start_body - 1;
}
#endif /* !defined (UNPROTOIZE) */
@@ -3792,94 +3788,94 @@ do_cleaning (new_clean_text_base, new_clean_text_limit)
for (scan_p = new_clean_text_base; scan_p < new_clean_text_limit; scan_p++)
{
switch (*scan_p)
- {
- case '/': /* Handle comments. */
- if (scan_p[1] != '*')
- goto regular;
- non_whitespace_since_newline = 1;
- scan_p[0] = ' ';
- scan_p[1] = ' ';
- scan_p += 2;
- while (scan_p[1] != '/' || scan_p[0] != '*')
- {
- if (!ISSPACE ((const unsigned char)*scan_p))
- *scan_p = ' ';
- if (++scan_p >= new_clean_text_limit)
- abort ();
- }
- *scan_p++ = ' ';
- *scan_p = ' ';
- break;
-
- case '#': /* Handle pp directives. */
- if (non_whitespace_since_newline)
- goto regular;
- *scan_p = ' ';
- while (scan_p[1] != '\n' || scan_p[0] == '\\')
- {
- if (!ISSPACE ((const unsigned char)*scan_p))
- *scan_p = ' ';
- if (++scan_p >= new_clean_text_limit)
- abort ();
- }
- *scan_p++ = ' ';
- break;
-
- case '\'': /* Handle character literals. */
- non_whitespace_since_newline = 1;
- while (scan_p[1] != '\'' || scan_p[0] == '\\')
- {
- if (scan_p[0] == '\\'
- && !ISSPACE ((const unsigned char) scan_p[1]))
- scan_p[1] = ' ';
- if (!ISSPACE ((const unsigned char)*scan_p))
- *scan_p = ' ';
- if (++scan_p >= new_clean_text_limit)
- abort ();
- }
- *scan_p++ = ' ';
- break;
-
- case '"': /* Handle string literals. */
- non_whitespace_since_newline = 1;
- while (scan_p[1] != '"' || scan_p[0] == '\\')
- {
- if (scan_p[0] == '\\'
- && !ISSPACE ((const unsigned char) scan_p[1]))
- scan_p[1] = ' ';
- if (!ISSPACE ((const unsigned char)*scan_p))
- *scan_p = ' ';
- if (++scan_p >= new_clean_text_limit)
- abort ();
- }
- if (!ISSPACE ((const unsigned char)*scan_p))
- *scan_p = ' ';
- scan_p++;
- break;
-
- case '\\': /* Handle line continuations. */
- if (scan_p[1] != '\n')
- goto regular;
- *scan_p = ' ';
- break;
-
- case '\n':
- non_whitespace_since_newline = 0; /* Reset. */
- break;
-
- case ' ':
- case '\v':
- case '\t':
- case '\r':
- case '\f':
- case '\b':
- break; /* Whitespace characters. */
-
- default:
+ {
+ case '/': /* Handle comments. */
+ if (scan_p[1] != '*')
+ goto regular;
+ non_whitespace_since_newline = 1;
+ scan_p[0] = ' ';
+ scan_p[1] = ' ';
+ scan_p += 2;
+ while (scan_p[1] != '/' || scan_p[0] != '*')
+ {
+ if (!ISSPACE ((const unsigned char)*scan_p))
+ *scan_p = ' ';
+ if (++scan_p >= new_clean_text_limit)
+ abort ();
+ }
+ *scan_p++ = ' ';
+ *scan_p = ' ';
+ break;
+
+ case '#': /* Handle pp directives. */
+ if (non_whitespace_since_newline)
+ goto regular;
+ *scan_p = ' ';
+ while (scan_p[1] != '\n' || scan_p[0] == '\\')
+ {
+ if (!ISSPACE ((const unsigned char)*scan_p))
+ *scan_p = ' ';
+ if (++scan_p >= new_clean_text_limit)
+ abort ();
+ }
+ *scan_p++ = ' ';
+ break;
+
+ case '\'': /* Handle character literals. */
+ non_whitespace_since_newline = 1;
+ while (scan_p[1] != '\'' || scan_p[0] == '\\')
+ {
+ if (scan_p[0] == '\\'
+ && !ISSPACE ((const unsigned char) scan_p[1]))
+ scan_p[1] = ' ';
+ if (!ISSPACE ((const unsigned char)*scan_p))
+ *scan_p = ' ';
+ if (++scan_p >= new_clean_text_limit)
+ abort ();
+ }
+ *scan_p++ = ' ';
+ break;
+
+ case '"': /* Handle string literals. */
+ non_whitespace_since_newline = 1;
+ while (scan_p[1] != '"' || scan_p[0] == '\\')
+ {
+ if (scan_p[0] == '\\'
+ && !ISSPACE ((const unsigned char) scan_p[1]))
+ scan_p[1] = ' ';
+ if (!ISSPACE ((const unsigned char)*scan_p))
+ *scan_p = ' ';
+ if (++scan_p >= new_clean_text_limit)
+ abort ();
+ }
+ if (!ISSPACE ((const unsigned char)*scan_p))
+ *scan_p = ' ';
+ scan_p++;
+ break;
+
+ case '\\': /* Handle line continuations. */
+ if (scan_p[1] != '\n')
+ goto regular;
+ *scan_p = ' ';
+ break;
+
+ case '\n':
+ non_whitespace_since_newline = 0; /* Reset. */
+ break;
+
+ case ' ':
+ case '\v':
+ case '\t':
+ case '\r':
+ case '\f':
+ case '\b':
+ break; /* Whitespace characters. */
+
+ default:
regular:
- non_whitespace_since_newline = 1;
- break;
- }
+ non_whitespace_since_newline = 1;
+ break;
+ }
}
}
@@ -3897,14 +3893,14 @@ careful_find_l_paren (p)
for (paren_depth = 1, q = p-1; paren_depth; check_source (--q >= clean_text_base, 0))
{
switch (*q)
- {
- case ')':
- paren_depth++;
- break;
- case '(':
- paren_depth--;
- break;
- }
+ {
+ case ')':
+ paren_depth++;
+ break;
+ case '(':
+ paren_depth--;
+ break;
+ }
}
return ++q;
}
@@ -3939,50 +3935,50 @@ scan_for_missed_items (file_p)
for (scan_p = clean_text_base; scan_p < limit; scan_p++)
{
if (*scan_p == ')')
- {
- static const char *last_r_paren;
- const char *ahead_p;
+ {
+ static const char *last_r_paren;
+ const char *ahead_p;
- last_r_paren = scan_p;
+ last_r_paren = scan_p;
- for (ahead_p = scan_p + 1; ISSPACE ((const unsigned char)*ahead_p); )
- check_source (++ahead_p < limit, limit);
+ for (ahead_p = scan_p + 1; ISSPACE ((const unsigned char)*ahead_p); )
+ check_source (++ahead_p < limit, limit);
- scan_p = ahead_p - 1;
+ scan_p = ahead_p - 1;
- if (ISALPHA ((const unsigned char)*ahead_p) || *ahead_p == '{')
- {
- const char *last_l_paren;
- const int lineno = identify_lineno (ahead_p);
+ if (ISALPHA ((const unsigned char)*ahead_p) || *ahead_p == '{')
+ {
+ const char *last_l_paren;
+ const int lineno = identify_lineno (ahead_p);
- if (setjmp (source_confusion_recovery))
- continue;
+ if (setjmp (source_confusion_recovery))
+ continue;
- /* We know we have a function definition header. Now skip
- leftwards over all of its associated formals lists. */
+ /* We know we have a function definition header. Now skip
+ leftwards over all of its associated formals lists. */
- do
- {
- last_l_paren = careful_find_l_paren (last_r_paren);
- for (last_r_paren = last_l_paren-1;
+ do
+ {
+ last_l_paren = careful_find_l_paren (last_r_paren);
+ for (last_r_paren = last_l_paren-1;
ISSPACE ((const unsigned char)*last_r_paren); )
- check_source (--last_r_paren >= backup_limit, backup_limit);
- }
- while (*last_r_paren == ')');
-
- if (is_id_char (*last_r_paren))
- {
- const char *id_limit = last_r_paren + 1;
- const char *id_start;
- size_t id_length;
- const def_dec_info *dd_p;
-
- for (id_start = id_limit-1; is_id_char (*id_start); )
- check_source (--id_start >= backup_limit, backup_limit);
- id_start++;
- backup_limit = id_start;
- if ((id_length = (size_t) (id_limit - id_start)) == 0)
- goto not_missed;
+ check_source (--last_r_paren >= backup_limit, backup_limit);
+ }
+ while (*last_r_paren == ')');
+
+ if (is_id_char (*last_r_paren))
+ {
+ const char *id_limit = last_r_paren + 1;
+ const char *id_start;
+ size_t id_length;
+ const def_dec_info *dd_p;
+
+ for (id_start = id_limit-1; is_id_char (*id_start); )
+ check_source (--id_start >= backup_limit, backup_limit);
+ id_start++;
+ backup_limit = id_start;
+ if ((id_length = (size_t) (id_limit - id_start)) == 0)
+ goto not_missed;
{
char *func_name = (char *) alloca (id_length + 1);
@@ -4024,9 +4020,9 @@ scan_for_missed_items (file_p)
pname);
}
not_missed: ;
- }
- }
- }
+ }
+ }
+ }
}
}
@@ -4041,7 +4037,7 @@ scan_for_missed_items (file_p)
Note that the trick of making a copy of the original sans comments &
preprocessing directives make the editing a whole lot easier. */
-
+
static void
edit_file (hp)
const hash_table_entry *hp;
@@ -4072,14 +4068,14 @@ edit_file (hp)
{
if (!quiet_flag
#ifdef UNPROTOIZE
- /* Don't even mention "system" include files unless we are
- protoizing. If we are protoizing, we mention these as a
- gentle way of prodding the user to convert his "system"
- include files to prototype format. */
- && !in_system_include_dir (convert_filename)
+ /* Don't even mention "system" include files unless we are
+ protoizing. If we are protoizing, we mention these as a
+ gentle way of prodding the user to convert his "system"
+ include files to prototype format. */
+ && !in_system_include_dir (convert_filename)
#endif /* defined (UNPROTOIZE) */
- )
- notice ("%s: `%s' not converted\n",
+ )
+ notice ("%s: `%s' not converted\n",
pname, shortpath (NULL, convert_filename));
return;
}
@@ -4142,10 +4138,10 @@ edit_file (hp)
if ((input_file = open (convert_filename, fd_flags, 0444)) == -1)
{
int errno_val = errno;
- notice ("%s: can't open file `%s' for reading: %s\n",
+ notice ("%s: can't open file `%s' for reading: %s\n",
pname, shortpath (NULL, convert_filename),
xstrerror (errno_val));
- return;
+ return;
}
/* Read the entire original source text file into the original text buffer
@@ -4156,11 +4152,11 @@ edit_file (hp)
(int) orig_size)
{
int errno_val = errno;
- close (input_file);
- notice ("\n%s: error reading input file `%s': %s\n",
+ close (input_file);
+ notice ("\n%s: error reading input file `%s': %s\n",
pname, shortpath (NULL, convert_filename),
xstrerror (errno_val));
- return;
+ return;
}
close (input_file);
@@ -4185,22 +4181,22 @@ edit_file (hp)
char *const clean_filename = (char *) alloca (strlen (convert_filename) + 6 + 1);
/* Open (and create) the clean file. */
-
+
strcpy (clean_filename, convert_filename);
strcat (clean_filename, ".clean");
if ((clean_file = creat (clean_filename, 0666)) == -1)
{
int errno_val = errno;
- notice ("%s: can't create/open clean file `%s': %s\n",
+ notice ("%s: can't create/open clean file `%s': %s\n",
pname, shortpath (NULL, clean_filename),
xstrerror (errno_val));
- return;
+ return;
}
-
+
/* Write the clean file. */
-
+
safe_write (clean_file, new_clean_text_base, clean_size, clean_filename);
-
+
close (clean_file);
}
#endif /* 0 */
@@ -4226,39 +4222,39 @@ edit_file (hp)
def_dec_p = file_p->defs_decs;
for (; def_dec_p; def_dec_p = def_dec_p->next_in_file)
{
- const char *clean_text_p = seek_to_line (def_dec_p->line);
-
- /* clean_text_p now points to the first character of the line which
- contains the `terminator' for the declaration or definition that
- we are about to process. */
-
+ const char *clean_text_p = seek_to_line (def_dec_p->line);
+
+ /* clean_text_p now points to the first character of the line which
+ contains the `terminator' for the declaration or definition that
+ we are about to process. */
+
#ifndef UNPROTOIZE
-
- if (global_flag && def_dec_p->is_func_def && first_definition_in_file)
- {
- add_global_decls (def_dec_p->file, clean_text_p);
- first_definition_in_file = 0;
- }
- /* Don't edit this item if it is already in prototype format or if it
- is a function declaration and we have found no corresponding
- definition. */
+ if (global_flag && def_dec_p->is_func_def && first_definition_in_file)
+ {
+ add_global_decls (def_dec_p->file, clean_text_p);
+ first_definition_in_file = 0;
+ }
- if (def_dec_p->prototyped
- || (!def_dec_p->is_func_def && !def_dec_p->definition))
- continue;
+ /* Don't edit this item if it is already in prototype format or if it
+ is a function declaration and we have found no corresponding
+ definition. */
+
+ if (def_dec_p->prototyped
+ || (!def_dec_p->is_func_def && !def_dec_p->definition))
+ continue;
#endif /* !defined (UNPROTOIZE) */
- if (def_dec_p->is_func_def)
- edit_fn_definition (def_dec_p, clean_text_p);
- else
+ if (def_dec_p->is_func_def)
+ edit_fn_definition (def_dec_p, clean_text_p);
+ else
#ifndef UNPROTOIZE
- if (def_dec_p->is_implicit)
- add_local_decl (def_dec_p, clean_text_p);
- else
+ if (def_dec_p->is_implicit)
+ add_local_decl (def_dec_p, clean_text_p);
+ else
#endif /* !defined (UNPROTOIZE) */
- edit_fn_declaration (def_dec_p, clean_text_p);
+ edit_fn_declaration (def_dec_p, clean_text_p);
}
}
@@ -4283,11 +4279,11 @@ edit_file (hp)
{
char *new_filename
= (char *) xmalloc (strlen (convert_filename) + strlen (save_suffix) + 2);
-
+
strcpy (new_filename, convert_filename);
#ifdef __MSDOS__
/* MSDOS filenames are restricted to 8.3 format, so we save `foo.c'
- as `foo.<save_suffix>'. */
+ as `foo.<save_suffix>'. */
new_filename[(strlen (convert_filename) - 1] = '\0';
#endif
strcat (new_filename, save_suffix);
@@ -4302,7 +4298,7 @@ edit_file (hp)
shortpath (NULL, new_filename));
}
else if (rename (convert_filename, new_filename) == -1)
- {
+ {
int errno_val = errno;
notice ("%s: can't link file `%s' to `%s': %s\n",
pname,
@@ -4310,7 +4306,7 @@ edit_file (hp)
shortpath (NULL, new_filename),
xstrerror (errno_val));
return;
- }
+ }
}
if (unlink (convert_filename) == -1)
@@ -4318,7 +4314,7 @@ edit_file (hp)
int errno_val = errno;
/* The file may have already been renamed. */
if (errno_val != ENOENT)
- {
+ {
notice ("%s: can't delete file `%s': %s\n",
pname, shortpath (NULL, convert_filename),
xstrerror (errno_val));
@@ -4330,28 +4326,28 @@ edit_file (hp)
int output_file;
/* Open (and create) the output file. */
-
+
if ((output_file = creat (convert_filename, 0666)) == -1)
{
int errno_val = errno;
- notice ("%s: can't create/open output file `%s': %s\n",
+ notice ("%s: can't create/open output file `%s': %s\n",
pname, shortpath (NULL, convert_filename),
xstrerror (errno_val));
- return;
+ return;
}
#ifdef O_BINARY
/* Use binary mode to avoid changing the existing EOL character. */
setmode (output_file, O_BINARY);
#endif
-
+
/* Write the output file. */
-
+
{
unsigned int out_size = (repl_write_ptr + 1) - repl_text_base;
-
+
safe_write (output_file, repl_text_base, out_size, convert_filename);
}
-
+
close (output_file);
}
@@ -4409,22 +4405,22 @@ do_processing ()
if (nondefault_syscalls_dir)
{
syscalls_absolute_filename
- = (char *) xmalloc (strlen (nondefault_syscalls_dir) + 1
- + sizeof (syscalls_filename));
+ = (char *) xmalloc (strlen (nondefault_syscalls_dir) + 1
+ + sizeof (syscalls_filename));
strcpy (syscalls_absolute_filename, nondefault_syscalls_dir);
}
else
{
- GET_ENV_PATH_LIST (default_syscalls_dir, "GCC_EXEC_PREFIX");
+ GET_ENVIRONMENT (default_syscalls_dir, "GCC_EXEC_PREFIX");
if (!default_syscalls_dir)
{
default_syscalls_dir = standard_exec_prefix;
}
syscalls_absolute_filename
- = (char *) xmalloc (strlen (default_syscalls_dir) + 0
+ = (char *) xmalloc (strlen (default_syscalls_dir) + 0
+ strlen (target_machine) + 1
+ strlen (target_version) + 1
- + sizeof (syscalls_filename));
+ + sizeof (syscalls_filename));
strcpy (syscalls_absolute_filename, default_syscalls_dir);
strcat (syscalls_absolute_filename, target_machine);
strcat (syscalls_absolute_filename, "/");
@@ -4439,7 +4435,7 @@ do_processing ()
*(syscalls_absolute_filename + syscalls_len) = '\0';
}
strcat (syscalls_absolute_filename, syscalls_filename);
-
+
/* Call process_aux_info_file in such a way that it does not try to
delete the SYSCALLS aux_info file. */
@@ -4572,7 +4568,7 @@ main (argc, argv)
case 'x':
exclude_list = string_list_cons (optarg, exclude_list);
break;
-
+
case 'v':
case 'V':
version_flag = 1;
@@ -4620,7 +4616,7 @@ main (argc, argv)
usage ();
}
}
-
+
/* Set up compile_params based on -p and -c options. */
munge_compile_params (params);
@@ -4666,7 +4662,7 @@ main (argc, argv)
else
{
if (version_flag)
- fprintf (stderr, "%s: %s\n", pname, version_string);
+ fprintf (stderr, "%s: %s\n", pname, version_string);
do_processing ();
}
diff --git a/contrib/gcc/ra-build.c b/contrib/gcc/ra-build.c
new file mode 100644
index 0000000..db2979a
--- /dev/null
+++ b/contrib/gcc/ra-build.c
@@ -0,0 +1,3274 @@
+/* Graph coloring register allocator
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Contributed by Michael Matz <matz@suse.de>
+ and Daniel Berlin <dan@cgsoftware.com>
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along
+ with GCC; see the file COPYING. If not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "insn-config.h"
+#include "recog.h"
+#include "reload.h"
+#include "function.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
+#include "df.h"
+#include "output.h"
+#include "ggc.h"
+#include "ra.h"
+
+/* This file is part of the graph coloring register alloctor.
+ It deals with building the interference graph. When rebuilding
+ the graph for a function after spilling, we rebuild only those
+ parts needed, i.e. it works incrementally.
+
+ The first part (the functions called from build_web_parts_and_conflicts()
+ ) constructs a web_part for each pseudo register reference in the insn
+ stream, then goes backward from each use, until it reaches defs for that
+ pseudo. While going back it remember seen defs for other registers as
+ conflicts. By connecting the uses and defs, which reach each other, webs
+ (or live ranges) are built conceptually.
+
+ The second part (make_webs() and childs) deals with converting that
+ structure to the nodes and edges, on which our interference graph is
+ built. For each root web part constructed above, an instance of struct
+ web is created. For all subregs of pseudos, which matter for allocation,
+ a subweb of the corresponding super web is built. Finally all the
+ conflicts noted in the first part (as bitmaps) are transformed into real
+ edges.
+
+ As part of that process the webs are also classified (their spill cost
+ is calculated, and if they are spillable at all, and if not, for what
+ reason; or if they are rematerializable), and move insns are collected,
+ which are potentially coalescable.
+
+ The top-level entry of this file (build_i_graph) puts it all together,
+ and leaves us with a complete interference graph, which just has to
+ be colored. */
+
+
+struct curr_use;
+
+static unsigned HOST_WIDE_INT rtx_to_undefined PARAMS ((rtx));
+static bitmap find_sub_conflicts PARAMS ((struct web_part *, unsigned int));
+static bitmap get_sub_conflicts PARAMS ((struct web_part *, unsigned int));
+static unsigned int undef_to_size_word PARAMS ((rtx, unsigned HOST_WIDE_INT *));
+static bitmap undef_to_bitmap PARAMS ((struct web_part *,
+ unsigned HOST_WIDE_INT *));
+static struct web_part * find_web_part_1 PARAMS ((struct web_part *));
+static struct web_part * union_web_part_roots
+ PARAMS ((struct web_part *, struct web_part *));
+static int defuse_overlap_p_1 PARAMS ((rtx, struct curr_use *));
+static int live_out_1 PARAMS ((struct df *, struct curr_use *, rtx));
+static int live_out PARAMS ((struct df *, struct curr_use *, rtx));
+static rtx live_in_edge PARAMS (( struct df *, struct curr_use *, edge));
+static void live_in PARAMS ((struct df *, struct curr_use *, rtx));
+static int copy_insn_p PARAMS ((rtx, rtx *, rtx *));
+static void remember_move PARAMS ((rtx));
+static void handle_asm_insn PARAMS ((struct df *, rtx));
+static void prune_hardregs_for_mode PARAMS ((HARD_REG_SET *,
+ enum machine_mode));
+static void init_one_web_common PARAMS ((struct web *, rtx));
+static void init_one_web PARAMS ((struct web *, rtx));
+static void reinit_one_web PARAMS ((struct web *, rtx));
+static struct web * add_subweb PARAMS ((struct web *, rtx));
+static struct web * add_subweb_2 PARAMS ((struct web *, unsigned int));
+static void init_web_parts PARAMS ((struct df *));
+static void copy_conflict_list PARAMS ((struct web *));
+static void add_conflict_edge PARAMS ((struct web *, struct web *));
+static void build_inverse_webs PARAMS ((struct web *));
+static void copy_web PARAMS ((struct web *, struct web_link **));
+static void compare_and_free_webs PARAMS ((struct web_link **));
+static void init_webs_defs_uses PARAMS ((void));
+static unsigned int parts_to_webs_1 PARAMS ((struct df *, struct web_link **,
+ struct df_link *));
+static void parts_to_webs PARAMS ((struct df *));
+static void reset_conflicts PARAMS ((void));
+#if 0
+static void check_conflict_numbers PARAMS ((void));
+#endif
+static void conflicts_between_webs PARAMS ((struct df *));
+static void remember_web_was_spilled PARAMS ((struct web *));
+static void detect_spill_temps PARAMS ((void));
+static int contains_pseudo PARAMS ((rtx));
+static int want_to_remat PARAMS ((rtx x));
+static void detect_remat_webs PARAMS ((void));
+static void determine_web_costs PARAMS ((void));
+static void detect_webs_set_in_cond_jump PARAMS ((void));
+static void make_webs PARAMS ((struct df *));
+static void moves_to_webs PARAMS ((struct df *));
+static void connect_rmw_web_parts PARAMS ((struct df *));
+static void update_regnos_mentioned PARAMS ((void));
+static void livethrough_conflicts_bb PARAMS ((basic_block));
+static void init_bb_info PARAMS ((void));
+static void free_bb_info PARAMS ((void));
+static void build_web_parts_and_conflicts PARAMS ((struct df *));
+
+
+/* A sbitmap of DF_REF_IDs of uses, which are live over an abnormal
+ edge. */
+static sbitmap live_over_abnormal;
+
+/* To cache if we already saw a certain edge while analyzing one
+ use, we use a tick count incremented per use. */
+static unsigned int visited_pass;
+
+/* A sbitmap of UIDs of move insns, which we already analyzed. */
+static sbitmap move_handled;
+
+/* One such structed is allocated per insn, and traces for the currently
+ analyzed use, which web part belongs to it, and how many bytes of
+ it were still undefined when that insn was reached. */
+struct visit_trace
+{
+ struct web_part *wp;
+ unsigned HOST_WIDE_INT undefined;
+};
+/* Indexed by UID. */
+static struct visit_trace *visit_trace;
+
+/* Per basic block we have one such structure, used to speed up
+ the backtracing of uses. */
+struct ra_bb_info
+{
+ /* The value of visited_pass, as the first insn of this BB was reached
+ the last time. If this equals the current visited_pass, then
+ undefined is valid. Otherwise not. */
+ unsigned int pass;
+ /* The still undefined bytes at that time. The use to which this is
+ relative is the current use. */
+ unsigned HOST_WIDE_INT undefined;
+ /* Bit regno is set, if that regno is mentioned in this BB as a def, or
+ the source of a copy insn. In these cases we can not skip the whole
+ block if we reach it from the end. */
+ bitmap regnos_mentioned;
+ /* If a use reaches the end of a BB, and that BB doesn't mention its
+ regno, we skip the block, and remember the ID of that use
+ as living throughout the whole block. */
+ bitmap live_throughout;
+ /* The content of the aux field before placing a pointer to this
+ structure there. */
+ void *old_aux;
+};
+
+/* We need a fast way to describe a certain part of a register.
+ Therefore we put together the size and offset (in bytes) in one
+ integer. */
+#define BL_TO_WORD(b, l) ((((b) & 0xFFFF) << 16) | ((l) & 0xFFFF))
+#define BYTE_BEGIN(i) (((unsigned int)(i) >> 16) & 0xFFFF)
+#define BYTE_LENGTH(i) ((unsigned int)(i) & 0xFFFF)
+
+/* For a REG or SUBREG expression X return the size/offset pair
+ as an integer. */
+
+unsigned int
+rtx_to_bits (x)
+ rtx x;
+{
+ unsigned int len, beg;
+ len = GET_MODE_SIZE (GET_MODE (x));
+ beg = (GET_CODE (x) == SUBREG) ? SUBREG_BYTE (x) : 0;
+ return BL_TO_WORD (beg, len);
+}
+
+/* X is a REG or SUBREG rtx. Return the bytes it touches as a bitmask. */
+
+static unsigned HOST_WIDE_INT
+rtx_to_undefined (x)
+ rtx x;
+{
+ unsigned int len, beg;
+ unsigned HOST_WIDE_INT ret;
+ len = GET_MODE_SIZE (GET_MODE (x));
+ beg = (GET_CODE (x) == SUBREG) ? SUBREG_BYTE (x) : 0;
+ ret = ~ ((unsigned HOST_WIDE_INT) 0);
+ ret = (~(ret << len)) << beg;
+ return ret;
+}
+
+/* We remember if we've analyzed an insn for being a move insn, and if yes
+ between which operands. */
+struct copy_p_cache
+{
+ int seen;
+ rtx source;
+ rtx target;
+};
+
+/* On demand cache, for if insns are copy insns, and if yes, what
+ source/target they have. */
+static struct copy_p_cache * copy_cache;
+
+int *number_seen;
+
+/* For INSN, return nonzero, if it's a move insn, we consider to coalesce
+ later, and place the operands in *SOURCE and *TARGET, if they are
+ not NULL. */
+
+static int
+copy_insn_p (insn, source, target)
+ rtx insn;
+ rtx *source;
+ rtx *target;
+{
+ rtx d, s;
+ unsigned int d_regno, s_regno;
+ int uid = INSN_UID (insn);
+
+ if (!INSN_P (insn))
+ abort ();
+
+ /* First look, if we already saw this insn. */
+ if (copy_cache[uid].seen)
+ {
+ /* And if we saw it, if it's actually a copy insn. */
+ if (copy_cache[uid].seen == 1)
+ {
+ if (source)
+ *source = copy_cache[uid].source;
+ if (target)
+ *target = copy_cache[uid].target;
+ return 1;
+ }
+ return 0;
+ }
+
+ /* Mark it as seen, but not being a copy insn. */
+ copy_cache[uid].seen = 2;
+ insn = single_set (insn);
+ if (!insn)
+ return 0;
+ d = SET_DEST (insn);
+ s = SET_SRC (insn);
+
+ /* We recognize moves between subreg's as copy insns. This is used to avoid
+ conflicts of those subwebs. But they are currently _not_ used for
+ coalescing (the check for this is in remember_move() below). */
+ while (GET_CODE (d) == STRICT_LOW_PART)
+ d = XEXP (d, 0);
+ if (GET_CODE (d) != REG
+ && (GET_CODE (d) != SUBREG || GET_CODE (SUBREG_REG (d)) != REG))
+ return 0;
+ while (GET_CODE (s) == STRICT_LOW_PART)
+ s = XEXP (s, 0);
+ if (GET_CODE (s) != REG
+ && (GET_CODE (s) != SUBREG || GET_CODE (SUBREG_REG (s)) != REG))
+ return 0;
+
+ s_regno = (unsigned) REGNO (GET_CODE (s) == SUBREG ? SUBREG_REG (s) : s);
+ d_regno = (unsigned) REGNO (GET_CODE (d) == SUBREG ? SUBREG_REG (d) : d);
+
+ /* Copies between hardregs are useless for us, as not coalesable anyway. */
+ if ((s_regno < FIRST_PSEUDO_REGISTER
+ && d_regno < FIRST_PSEUDO_REGISTER)
+ || s_regno >= max_normal_pseudo
+ || d_regno >= max_normal_pseudo)
+ return 0;
+
+ if (source)
+ *source = s;
+ if (target)
+ *target = d;
+
+ /* Still mark it as seen, but as a copy insn this time. */
+ copy_cache[uid].seen = 1;
+ copy_cache[uid].source = s;
+ copy_cache[uid].target = d;
+ return 1;
+}
+
+/* We build webs, as we process the conflicts. For each use we go upward
+ the insn stream, noting any defs as potentially conflicting with the
+ current use. We stop at defs of the current regno. The conflicts are only
+ potentially, because we may never reach a def, so this is an undefined use,
+ which conflicts with nothing. */
+
+
+/* Given a web part WP, and the location of a reg part SIZE_WORD
+ return the conflict bitmap for that reg part, or NULL if it doesn't
+ exist yet in WP. */
+
+static bitmap
+find_sub_conflicts (wp, size_word)
+ struct web_part *wp;
+ unsigned int size_word;
+{
+ struct tagged_conflict *cl;
+ cl = wp->sub_conflicts;
+ for (; cl; cl = cl->next)
+ if (cl->size_word == size_word)
+ return cl->conflicts;
+ return NULL;
+}
+
+/* Similar to find_sub_conflicts(), but creates that bitmap, if it
+ doesn't exist. I.e. this never returns NULL. */
+
+static bitmap
+get_sub_conflicts (wp, size_word)
+ struct web_part *wp;
+ unsigned int size_word;
+{
+ bitmap b = find_sub_conflicts (wp, size_word);
+ if (!b)
+ {
+ struct tagged_conflict *cl =
+ (struct tagged_conflict *) ra_alloc (sizeof *cl);
+ cl->conflicts = BITMAP_XMALLOC ();
+ cl->size_word = size_word;
+ cl->next = wp->sub_conflicts;
+ wp->sub_conflicts = cl;
+ b = cl->conflicts;
+ }
+ return b;
+}
+
+/* Helper table for undef_to_size_word() below for small values
+ of UNDEFINED. Offsets and lengths are byte based. */
+static struct undef_table_s {
+ unsigned int new_undef;
+ /* size | (byte << 16) */
+ unsigned int size_word;
+} const undef_table [] = {
+ { 0, BL_TO_WORD (0, 0)}, /* 0 */
+ { 0, BL_TO_WORD (0, 1)},
+ { 0, BL_TO_WORD (1, 1)},
+ { 0, BL_TO_WORD (0, 2)},
+ { 0, BL_TO_WORD (2, 1)}, /* 4 */
+ { 1, BL_TO_WORD (2, 1)},
+ { 2, BL_TO_WORD (2, 1)},
+ { 3, BL_TO_WORD (2, 1)},
+ { 0, BL_TO_WORD (3, 1)}, /* 8 */
+ { 1, BL_TO_WORD (3, 1)},
+ { 2, BL_TO_WORD (3, 1)},
+ { 3, BL_TO_WORD (3, 1)},
+ { 0, BL_TO_WORD (2, 2)}, /* 12 */
+ { 1, BL_TO_WORD (2, 2)},
+ { 2, BL_TO_WORD (2, 2)},
+ { 0, BL_TO_WORD (0, 4)}};
+
+/* Interpret *UNDEFINED as bitmask where each bit corresponds to a byte.
+ A set bit means an undefined byte. Factor all undefined bytes into
+ groups, and return a size/ofs pair of consecutive undefined bytes,
+ but according to certain borders. Clear out those bits corrsponding
+ to bytes overlaid by that size/ofs pair. REG is only used for
+ the mode, to detect if it's a floating mode or not.
+
+ For example: *UNDEFINED size+ofs new *UNDEFINED
+ 1111 4+0 0
+ 1100 2+2 0
+ 1101 2+2 1
+ 0001 1+0 0
+ 10101 1+4 101
+
+ */
+
+static unsigned int
+undef_to_size_word (reg, undefined)
+ rtx reg;
+ unsigned HOST_WIDE_INT *undefined;
+{
+ /* When only the lower four bits are possibly set, we use
+ a fast lookup table. */
+ if (*undefined <= 15)
+ {
+ struct undef_table_s u;
+ u = undef_table[*undefined];
+ *undefined = u.new_undef;
+ return u.size_word;
+ }
+
+ /* Otherwise we handle certain cases directly. */
+ switch (*undefined)
+ {
+ case 0x00f0 : *undefined = 0; return BL_TO_WORD (4, 4);
+ case 0x00ff : *undefined = 0; return BL_TO_WORD (0, 8);
+ case 0x0f00 : *undefined = 0; return BL_TO_WORD (8, 4);
+ case 0x0ff0 : *undefined = 0xf0; return BL_TO_WORD (8, 4);
+ case 0x0fff :
+ if (INTEGRAL_MODE_P (GET_MODE (reg)))
+ { *undefined = 0xff; return BL_TO_WORD (8, 4); }
+ else
+ { *undefined = 0; return BL_TO_WORD (0, 12); /* XFmode */ }
+ case 0xf000 : *undefined = 0; return BL_TO_WORD (12, 4);
+ case 0xff00 : *undefined = 0; return BL_TO_WORD (8, 8);
+ case 0xfff0 : *undefined = 0xf0; return BL_TO_WORD (8, 8);
+ case 0xffff : *undefined = 0; return BL_TO_WORD (0, 16);
+
+ /* And if nothing matched fall back to the general solution.
+ For now unknown undefined bytes are converted to sequences
+ of maximal length 4 bytes. We could make this larger if
+ necessary. */
+ default :
+ {
+ unsigned HOST_WIDE_INT u = *undefined;
+ int word;
+ struct undef_table_s tab;
+ for (word = 0; (u & 15) == 0; word += 4)
+ u >>= 4;
+ u = u & 15;
+ tab = undef_table[u];
+ u = tab.new_undef;
+ u = (*undefined & ~((unsigned HOST_WIDE_INT)15 << word))
+ | (u << word);
+ *undefined = u;
+ /* Size remains the same, only the begin is moved up move bytes. */
+ return tab.size_word + BL_TO_WORD (word, 0);
+ }
+ break;
+ }
+}
+
+/* Put the above three functions together. For a set of undefined bytes
+ as bitmap *UNDEFINED, look for (create if necessary) and return the
+ corresponding conflict bitmap. Change *UNDEFINED to remove the bytes
+ covered by the part for that bitmap. */
+
+static bitmap
+undef_to_bitmap (wp, undefined)
+ struct web_part *wp;
+ unsigned HOST_WIDE_INT *undefined;
+{
+ unsigned int size_word = undef_to_size_word (DF_REF_REAL_REG (wp->ref),
+ undefined);
+ return get_sub_conflicts (wp, size_word);
+}
+
+/* Returns the root of the web part P is a member of. Additionally
+ it compresses the path. P may not be NULL. */
+
+static struct web_part *
+find_web_part_1 (p)
+ struct web_part *p;
+{
+ struct web_part *r = p;
+ struct web_part *p_next;
+ while (r->uplink)
+ r = r->uplink;
+ for (; p != r; p = p_next)
+ {
+ p_next = p->uplink;
+ p->uplink = r;
+ }
+ return r;
+}
+
+/* Fast macro for the common case (WP either being the root itself, or
+ the end of an already compressed path. */
+
+#define find_web_part(wp) ((! (wp)->uplink) ? (wp) \
+ : (! (wp)->uplink->uplink) ? (wp)->uplink : find_web_part_1 (wp))
+
+/* Unions together the parts R1 resp. R2 is a root of.
+ All dynamic information associated with the parts (number of spanned insns
+ and so on) is also merged.
+ The root of the resulting (possibly larger) web part is returned. */
+
+static struct web_part *
+union_web_part_roots (r1, r2)
+ struct web_part *r1, *r2;
+{
+ if (r1 != r2)
+ {
+ /* The new root is the smaller (pointerwise) of both. This is crucial
+ to make the construction of webs from web parts work (so, when
+ scanning all parts, we see the roots before all it's childs).
+ Additionally this ensures, that if the web has a def at all, than
+ the root is a def (because all def parts are before use parts in the
+ web_parts[] array), or put another way, as soon, as the root of a
+ web part is not a def, this is an uninitialized web part. The
+ way we construct the I-graph ensures, that if a web is initialized,
+ then the first part we find (besides trivial 1 item parts) has a
+ def. */
+ if (r1 > r2)
+ {
+ struct web_part *h = r1;
+ r1 = r2;
+ r2 = h;
+ }
+ r2->uplink = r1;
+ num_webs--;
+
+ /* Now we merge the dynamic information of R1 and R2. */
+ r1->spanned_deaths += r2->spanned_deaths;
+
+ if (!r1->sub_conflicts)
+ r1->sub_conflicts = r2->sub_conflicts;
+ else if (r2->sub_conflicts)
+ /* We need to merge the conflict bitmaps from R2 into R1. */
+ {
+ struct tagged_conflict *cl1, *cl2;
+ /* First those from R2, which are also contained in R1.
+ We union the bitmaps, and free those from R2, resetting them
+ to 0. */
+ for (cl1 = r1->sub_conflicts; cl1; cl1 = cl1->next)
+ for (cl2 = r2->sub_conflicts; cl2; cl2 = cl2->next)
+ if (cl1->size_word == cl2->size_word)
+ {
+ bitmap_operation (cl1->conflicts, cl1->conflicts,
+ cl2->conflicts, BITMAP_IOR);
+ BITMAP_XFREE (cl2->conflicts);
+ cl2->conflicts = NULL;
+ }
+ /* Now the conflict lists from R2 which weren't in R1.
+ We simply copy the entries from R2 into R1' list. */
+ for (cl2 = r2->sub_conflicts; cl2;)
+ {
+ struct tagged_conflict *cl_next = cl2->next;
+ if (cl2->conflicts)
+ {
+ cl2->next = r1->sub_conflicts;
+ r1->sub_conflicts = cl2;
+ }
+ cl2 = cl_next;
+ }
+ }
+ r2->sub_conflicts = NULL;
+ r1->crosses_call |= r2->crosses_call;
+ }
+ return r1;
+}
+
+/* Convenience macro, that is cabable of unioning also non-roots. */
+#define union_web_parts(p1, p2) \
+ ((p1 == p2) ? find_web_part (p1) \
+ : union_web_part_roots (find_web_part (p1), find_web_part (p2)))
+
+/* Remember that we've handled a given move, so we don't reprocess it. */
+
+static void
+remember_move (insn)
+ rtx insn;
+{
+ if (!TEST_BIT (move_handled, INSN_UID (insn)))
+ {
+ rtx s, d;
+ SET_BIT (move_handled, INSN_UID (insn));
+ if (copy_insn_p (insn, &s, &d))
+ {
+ /* Some sanity test for the copy insn. */
+ struct df_link *slink = DF_INSN_USES (df, insn);
+ struct df_link *link = DF_INSN_DEFS (df, insn);
+ if (!link || !link->ref || !slink || !slink->ref)
+ abort ();
+ /* The following (link->next != 0) happens when a hardreg
+ is used in wider mode (REG:DI %eax). Then df.* creates
+ a def/use for each hardreg contained therein. We only
+ allow hardregs here. */
+ if (link->next
+ && DF_REF_REGNO (link->next->ref) >= FIRST_PSEUDO_REGISTER)
+ abort ();
+ }
+ else
+ abort ();
+ /* XXX for now we don't remember move insns involving any subregs.
+ Those would be difficult to coalesce (we would need to implement
+ handling of all the subwebs in the allocator, including that such
+ subwebs could be source and target of coalesing). */
+ if (GET_CODE (s) == REG && GET_CODE (d) == REG)
+ {
+ struct move *m = (struct move *) ra_calloc (sizeof (struct move));
+ struct move_list *ml;
+ m->insn = insn;
+ ml = (struct move_list *) ra_alloc (sizeof (struct move_list));
+ ml->move = m;
+ ml->next = wl_moves;
+ wl_moves = ml;
+ }
+ }
+}
+
+/* This describes the USE currently looked at in the main-loop in
+ build_web_parts_and_conflicts(). */
+struct curr_use {
+ struct web_part *wp;
+ /* This has a 1-bit for each byte in the USE, which is still undefined. */
+ unsigned HOST_WIDE_INT undefined;
+ /* For easy access. */
+ unsigned int regno;
+ rtx x;
+ /* If some bits of this USE are live over an abnormal edge. */
+ unsigned int live_over_abnormal;
+};
+
+/* Returns nonzero iff rtx DEF and USE have bits in common (but see below).
+ It is only called with DEF and USE being (reg:M a) or (subreg:M1 (reg:M2 a)
+ x) rtx's. Furthermore if it's a subreg rtx M1 is at least one word wide,
+ and a is a multi-word pseudo. If DEF or USE are hardregs, they are in
+ word_mode, so we don't need to check for further hardregs which would result
+ from wider references. We are never called with paradoxical subregs.
+
+ This returns:
+ 0 for no common bits,
+ 1 if DEF and USE exactly cover the same bytes,
+ 2 if the DEF only covers a part of the bits of USE
+ 3 if the DEF covers more than the bits of the USE, and
+ 4 if both are SUBREG's of different size, but have bytes in common.
+ -1 is a special case, for when DEF and USE refer to the same regno, but
+ have for other reasons no bits in common (can only happen with
+ subregs refering to different words, or to words which already were
+ defined for this USE).
+ Furthermore it modifies use->undefined to clear the bits which get defined
+ by DEF (only for cases with partial overlap).
+ I.e. if bit 1 is set for the result != -1, the USE was completely covered,
+ otherwise a test is needed to track the already defined bytes. */
+
+static int
+defuse_overlap_p_1 (def, use)
+ rtx def;
+ struct curr_use *use;
+{
+ int mode = 0;
+ if (def == use->x)
+ return 1;
+ if (!def)
+ return 0;
+ if (GET_CODE (def) == SUBREG)
+ {
+ if (REGNO (SUBREG_REG (def)) != use->regno)
+ return 0;
+ mode |= 1;
+ }
+ else if (REGNO (def) != use->regno)
+ return 0;
+ if (GET_CODE (use->x) == SUBREG)
+ mode |= 2;
+ switch (mode)
+ {
+ case 0: /* REG, REG */
+ return 1;
+ case 1: /* SUBREG, REG */
+ {
+ unsigned HOST_WIDE_INT old_u = use->undefined;
+ use->undefined &= ~ rtx_to_undefined (def);
+ return (old_u != use->undefined) ? 2 : -1;
+ }
+ case 2: /* REG, SUBREG */
+ return 3;
+ case 3: /* SUBREG, SUBREG */
+ if (GET_MODE_SIZE (GET_MODE (def)) == GET_MODE_SIZE (GET_MODE (use->x)))
+ /* If the size of both things is the same, the subreg's overlap
+ if they refer to the same word. */
+ if (SUBREG_BYTE (def) == SUBREG_BYTE (use->x))
+ return 1;
+ /* Now the more difficult part: the same regno is refered, but the
+ sizes of the references or the words differ. E.g.
+ (subreg:SI (reg:CDI a) 0) and (subreg:DI (reg:CDI a) 2) do not
+ overlap, wereas the latter overlaps with (subreg:SI (reg:CDI a) 3).
+ */
+ {
+ unsigned HOST_WIDE_INT old_u;
+ int b1, e1, b2, e2;
+ unsigned int bl1, bl2;
+ bl1 = rtx_to_bits (def);
+ bl2 = rtx_to_bits (use->x);
+ b1 = BYTE_BEGIN (bl1);
+ b2 = BYTE_BEGIN (bl2);
+ e1 = b1 + BYTE_LENGTH (bl1) - 1;
+ e2 = b2 + BYTE_LENGTH (bl2) - 1;
+ if (b1 > e2 || b2 > e1)
+ return -1;
+ old_u = use->undefined;
+ use->undefined &= ~ rtx_to_undefined (def);
+ return (old_u != use->undefined) ? 4 : -1;
+ }
+ default:
+ abort ();
+ }
+}
+
+/* Macro for the common case of either def and use having the same rtx,
+ or based on different regnos. */
+#define defuse_overlap_p(def, use) \
+ ((def) == (use)->x ? 1 : \
+ (REGNO (GET_CODE (def) == SUBREG \
+ ? SUBREG_REG (def) : def) != use->regno \
+ ? 0 : defuse_overlap_p_1 (def, use)))
+
+
+/* The use USE flows into INSN (backwards). Determine INSNs effect on it,
+ and return nonzero, if (parts of) that USE are also live before it.
+ This also notes conflicts between the USE and all DEFS in that insn,
+ and modifies the undefined bits of USE in case parts of it were set in
+ this insn. */
+
+static int
+live_out_1 (df, use, insn)
+ struct df *df ATTRIBUTE_UNUSED;
+ struct curr_use *use;
+ rtx insn;
+{
+ int defined = 0;
+ int uid = INSN_UID (insn);
+ struct web_part *wp = use->wp;
+
+ /* Mark, that this insn needs this webpart live. */
+ visit_trace[uid].wp = wp;
+ visit_trace[uid].undefined = use->undefined;
+
+ if (INSN_P (insn))
+ {
+ unsigned int source_regno = ~0;
+ unsigned int regno = use->regno;
+ unsigned HOST_WIDE_INT orig_undef = use->undefined;
+ unsigned HOST_WIDE_INT final_undef = use->undefined;
+ rtx s = NULL;
+ unsigned int n, num_defs = insn_df[uid].num_defs;
+ struct ref **defs = insn_df[uid].defs;
+
+ /* We want to access the root webpart. */
+ wp = find_web_part (wp);
+ if (GET_CODE (insn) == CALL_INSN)
+ wp->crosses_call = 1;
+ else if (copy_insn_p (insn, &s, NULL))
+ source_regno = REGNO (GET_CODE (s) == SUBREG ? SUBREG_REG (s) : s);
+
+ /* Look at all DEFS in this insn. */
+ for (n = 0; n < num_defs; n++)
+ {
+ struct ref *ref = defs[n];
+ int lap;
+
+ /* Reset the undefined bits for each iteration, in case this
+ insn has more than one set, and one of them sets this regno.
+ But still the original undefined part conflicts with the other
+ sets. */
+ use->undefined = orig_undef;
+ if ((lap = defuse_overlap_p (DF_REF_REG (ref), use)) != 0)
+ {
+ if (lap == -1)
+ /* Same regnos but non-overlapping or already defined bits,
+ so ignore this DEF, or better said make the yet undefined
+ part and this DEF conflicting. */
+ {
+ unsigned HOST_WIDE_INT undef;
+ undef = use->undefined;
+ while (undef)
+ bitmap_set_bit (undef_to_bitmap (wp, &undef),
+ DF_REF_ID (ref));
+ continue;
+ }
+ if ((lap & 1) != 0)
+ /* The current DEF completely covers the USE, so we can
+ stop traversing the code looking for further DEFs. */
+ defined = 1;
+ else
+ /* We have a partial overlap. */
+ {
+ final_undef &= use->undefined;
+ if (final_undef == 0)
+ /* Now the USE is completely defined, which means, that
+ we can stop looking for former DEFs. */
+ defined = 1;
+ /* If this is a partial overlap, which left some bits
+ in USE undefined, we normally would need to create
+ conflicts between that undefined part and the part of
+ this DEF which overlapped with some of the formerly
+ undefined bits. We don't need to do this, because both
+ parts of this DEF (that which overlaps, and that which
+ doesn't) are written together in this one DEF, and can
+ not be colored in a way which would conflict with
+ the USE. This is only true for partial overlap,
+ because only then the DEF and USE have bits in common,
+ which makes the DEF move, if the USE moves, making them
+ aligned.
+ If they have no bits in common (lap == -1), they are
+ really independent. Therefore we there made a
+ conflict above. */
+ }
+ /* This is at least a partial overlap, so we need to union
+ the web parts. */
+ wp = union_web_parts (wp, &web_parts[DF_REF_ID (ref)]);
+ }
+ else
+ {
+ /* The DEF and the USE don't overlap at all, different
+ regnos. I.e. make conflicts between the undefined bits,
+ and that DEF. */
+ unsigned HOST_WIDE_INT undef = use->undefined;
+
+ if (regno == source_regno)
+ /* This triggers only, when this was a copy insn and the
+ source is at least a part of the USE currently looked at.
+ In this case only the bits of the USE conflict with the
+ DEF, which are not covered by the source of this copy
+ insn, and which are still undefined. I.e. in the best
+ case (the whole reg being the source), _no_ conflicts
+ between that USE and this DEF (the target of the move)
+ are created by this insn (though they might be by
+ others). This is a super case of the normal copy insn
+ only between full regs. */
+ {
+ undef &= ~ rtx_to_undefined (s);
+ }
+ if (undef)
+ {
+ /*struct web_part *cwp;
+ cwp = find_web_part (&web_parts[DF_REF_ID
+ (ref)]);*/
+
+ /* TODO: somehow instead of noting the ID of the LINK
+ use an ID nearer to the root webpart of that LINK.
+ We can't use the root itself, because we later use the
+ ID to look at the form (reg or subreg, and if yes,
+ which subreg) of this conflict. This means, that we
+ need to remember in the root an ID for each form, and
+ maintaining this, when merging web parts. This makes
+ the bitmaps smaller. */
+ do
+ bitmap_set_bit (undef_to_bitmap (wp, &undef),
+ DF_REF_ID (ref));
+ while (undef);
+ }
+ }
+ }
+ if (defined)
+ use->undefined = 0;
+ else
+ {
+ /* If this insn doesn't completely define the USE, increment also
+ it's spanned deaths count (if this insn contains a death). */
+ if (uid >= death_insns_max_uid)
+ abort ();
+ if (TEST_BIT (insns_with_deaths, uid))
+ wp->spanned_deaths++;
+ use->undefined = final_undef;
+ }
+ }
+
+ return !defined;
+}
+
+/* Same as live_out_1() (actually calls it), but caches some information.
+ E.g. if we reached this INSN with the current regno already, and the
+ current undefined bits are a subset of those as we came here, we
+ simply connect the web parts of the USE, and the one cached for this
+ INSN, and additionally return zero, indicating we don't need to traverse
+ this path any longer (all effect were already seen, as we first reached
+ this insn). */
+
+static inline int
+live_out (df, use, insn)
+ struct df *df;
+ struct curr_use *use;
+ rtx insn;
+{
+ unsigned int uid = INSN_UID (insn);
+ if (visit_trace[uid].wp
+ && DF_REF_REGNO (visit_trace[uid].wp->ref) == use->regno
+ && (use->undefined & ~visit_trace[uid].undefined) == 0)
+ {
+ union_web_parts (visit_trace[uid].wp, use->wp);
+ /* Don't search any further, as we already were here with this regno. */
+ return 0;
+ }
+ else
+ return live_out_1 (df, use, insn);
+}
+
+/* The current USE reached a basic block head. The edge E is one
+ of the predecessors edges. This evaluates the effect of the predecessor
+ block onto the USE, and returns the next insn, which should be looked at.
+ This either is the last insn of that pred. block, or the first one.
+ The latter happens, when the pred. block has no possible effect on the
+ USE, except for conflicts. In that case, it's remembered, that the USE
+ is live over that whole block, and it's skipped. Otherwise we simply
+ continue with the last insn of the block.
+
+ This also determines the effects of abnormal edges, and remembers
+ which uses are live at the end of that basic block. */
+
+static rtx
+live_in_edge (df, use, e)
+ struct df *df;
+ struct curr_use *use;
+ edge e;
+{
+ struct ra_bb_info *info_pred;
+ rtx next_insn;
+ /* Call used hard regs die over an exception edge, ergo
+ they don't reach the predecessor block, so ignore such
+ uses. And also don't set the live_over_abnormal flag
+ for them. */
+ if ((e->flags & EDGE_EH) && use->regno < FIRST_PSEUDO_REGISTER
+ && call_used_regs[use->regno])
+ return NULL_RTX;
+ if (e->flags & EDGE_ABNORMAL)
+ use->live_over_abnormal = 1;
+ bitmap_set_bit (live_at_end[e->src->index], DF_REF_ID (use->wp->ref));
+ info_pred = (struct ra_bb_info *) e->src->aux;
+ next_insn = e->src->end;
+
+ /* If the last insn of the pred. block doesn't completely define the
+ current use, we need to check the block. */
+ if (live_out (df, use, next_insn))
+ {
+ /* If the current regno isn't mentioned anywhere in the whole block,
+ and the complete use is still undefined... */
+ if (!bitmap_bit_p (info_pred->regnos_mentioned, use->regno)
+ && (rtx_to_undefined (use->x) & ~use->undefined) == 0)
+ {
+ /* ...we can hop over the whole block and defer conflict
+ creation to later. */
+ bitmap_set_bit (info_pred->live_throughout,
+ DF_REF_ID (use->wp->ref));
+ next_insn = e->src->head;
+ }
+ return next_insn;
+ }
+ else
+ return NULL_RTX;
+}
+
+/* USE flows into the end of the insns preceding INSN. Determine
+ their effects (in live_out()) and possibly loop over the preceding INSN,
+ or call itself recursively on a basic block border. When a topleve
+ call of this function returns the USE is completely analyzed. I.e.
+ its def-use chain (at least) is built, possibly connected with other
+ def-use chains, and all defs during that chain are noted. */
+
+static void
+live_in (df, use, insn)
+ struct df *df;
+ struct curr_use *use;
+ rtx insn;
+{
+ unsigned int loc_vpass = visited_pass;
+
+ /* Note, that, even _if_ we are called with use->wp a root-part, this might
+ become non-root in the for() loop below (due to live_out() unioning
+ it). So beware, not to change use->wp in a way, for which only root-webs
+ are allowed. */
+ while (1)
+ {
+ int uid = INSN_UID (insn);
+ basic_block bb = BLOCK_FOR_INSN (insn);
+ number_seen[uid]++;
+
+ /* We want to be as fast as possible, so explicitely write
+ this loop. */
+ for (insn = PREV_INSN (insn); insn && !INSN_P (insn);
+ insn = PREV_INSN (insn))
+ ;
+ if (!insn)
+ return;
+ if (bb != BLOCK_FOR_INSN (insn))
+ {
+ edge e;
+ unsigned HOST_WIDE_INT undef = use->undefined;
+ struct ra_bb_info *info = (struct ra_bb_info *) bb->aux;
+ if ((e = bb->pred) == NULL)
+ return;
+ /* We now check, if we already traversed the predecessors of this
+ block for the current pass and the current set of undefined
+ bits. If yes, we don't need to check the predecessors again.
+ So, conceptually this information is tagged to the first
+ insn of a basic block. */
+ if (info->pass == loc_vpass && (undef & ~info->undefined) == 0)
+ return;
+ info->pass = loc_vpass;
+ info->undefined = undef;
+ /* All but the last predecessor are handled recursively. */
+ for (; e->pred_next; e = e->pred_next)
+ {
+ insn = live_in_edge (df, use, e);
+ if (insn)
+ live_in (df, use, insn);
+ use->undefined = undef;
+ }
+ insn = live_in_edge (df, use, e);
+ if (!insn)
+ return;
+ }
+ else if (!live_out (df, use, insn))
+ return;
+ }
+}
+
+/* Determine all regnos which are mentioned in a basic block, in an
+ interesting way. Interesting here means either in a def, or as the
+ source of a move insn. We only look at insns added since the last
+ pass. */
+
+static void
+update_regnos_mentioned ()
+{
+ int last_uid = last_max_uid;
+ rtx insn;
+ basic_block bb;
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ {
+ /* Don't look at old insns. */
+ if (INSN_UID (insn) < last_uid)
+ {
+ /* XXX We should also remember moves over iterations (we already
+ save the cache, but not the movelist). */
+ if (copy_insn_p (insn, NULL, NULL))
+ remember_move (insn);
+ }
+ else if ((bb = BLOCK_FOR_INSN (insn)) != NULL)
+ {
+ rtx source;
+ struct ra_bb_info *info = (struct ra_bb_info *) bb->aux;
+ bitmap mentioned = info->regnos_mentioned;
+ struct df_link *link;
+ if (copy_insn_p (insn, &source, NULL))
+ {
+ remember_move (insn);
+ bitmap_set_bit (mentioned,
+ REGNO (GET_CODE (source) == SUBREG
+ ? SUBREG_REG (source) : source));
+ }
+ for (link = DF_INSN_DEFS (df, insn); link; link = link->next)
+ if (link->ref)
+ bitmap_set_bit (mentioned, DF_REF_REGNO (link->ref));
+ }
+ }
+}
+
+/* Handle the uses which reach a block end, but were defered due
+ to it's regno not being mentioned in that block. This adds the
+ remaining conflicts and updates also the crosses_call and
+ spanned_deaths members. */
+
+static void
+livethrough_conflicts_bb (bb)
+ basic_block bb;
+{
+ struct ra_bb_info *info = (struct ra_bb_info *) bb->aux;
+ rtx insn;
+ bitmap all_defs;
+ int first, use_id;
+ unsigned int deaths = 0;
+ unsigned int contains_call = 0;
+
+ /* If there are no defered uses, just return. */
+ if ((first = bitmap_first_set_bit (info->live_throughout)) < 0)
+ return;
+
+ /* First collect the IDs of all defs, count the number of death
+ containing insns, and if there's some call_insn here. */
+ all_defs = BITMAP_XMALLOC ();
+ for (insn = bb->head; insn; insn = NEXT_INSN (insn))
+ {
+ if (INSN_P (insn))
+ {
+ unsigned int n;
+ struct ra_insn_info info;
+
+ info = insn_df[INSN_UID (insn)];
+ for (n = 0; n < info.num_defs; n++)
+ bitmap_set_bit (all_defs, DF_REF_ID (info.defs[n]));
+ if (TEST_BIT (insns_with_deaths, INSN_UID (insn)))
+ deaths++;
+ if (GET_CODE (insn) == CALL_INSN)
+ contains_call = 1;
+ }
+ if (insn == bb->end)
+ break;
+ }
+
+ /* And now, if we have found anything, make all live_through
+ uses conflict with all defs, and update their other members. */
+ if (deaths > 0 || bitmap_first_set_bit (all_defs) >= 0)
+ EXECUTE_IF_SET_IN_BITMAP (info->live_throughout, first, use_id,
+ {
+ struct web_part *wp = &web_parts[df->def_id + use_id];
+ unsigned int bl = rtx_to_bits (DF_REF_REG (wp->ref));
+ bitmap conflicts;
+ wp = find_web_part (wp);
+ wp->spanned_deaths += deaths;
+ wp->crosses_call |= contains_call;
+ conflicts = get_sub_conflicts (wp, bl);
+ bitmap_operation (conflicts, conflicts, all_defs, BITMAP_IOR);
+ });
+
+ BITMAP_XFREE (all_defs);
+}
+
+/* Allocate the per basic block info for traversing the insn stream for
+ building live ranges. */
+
+static void
+init_bb_info ()
+{
+ basic_block bb;
+ FOR_ALL_BB (bb)
+ {
+ struct ra_bb_info *info =
+ (struct ra_bb_info *) xcalloc (1, sizeof *info);
+ info->regnos_mentioned = BITMAP_XMALLOC ();
+ info->live_throughout = BITMAP_XMALLOC ();
+ info->old_aux = bb->aux;
+ bb->aux = (void *) info;
+ }
+}
+
+/* Free that per basic block info. */
+
+static void
+free_bb_info ()
+{
+ basic_block bb;
+ FOR_ALL_BB (bb)
+ {
+ struct ra_bb_info *info = (struct ra_bb_info *) bb->aux;
+ BITMAP_XFREE (info->regnos_mentioned);
+ BITMAP_XFREE (info->live_throughout);
+ bb->aux = info->old_aux;
+ free (info);
+ }
+}
+
+/* Toplevel function for the first part of this file.
+ Connect web parts, thereby implicitely building webs, and remember
+ their conflicts. */
+
+static void
+build_web_parts_and_conflicts (df)
+ struct df *df;
+{
+ struct df_link *link;
+ struct curr_use use;
+ basic_block bb;
+
+ number_seen = (int *) xcalloc (get_max_uid (), sizeof (int));
+ visit_trace = (struct visit_trace *) xcalloc (get_max_uid (),
+ sizeof (visit_trace[0]));
+ update_regnos_mentioned ();
+
+ /* Here's the main loop.
+ It goes through all insn's, connects web parts along the way, notes
+ conflicts between webparts, and remembers move instructions. */
+ visited_pass = 0;
+ for (use.regno = 0; use.regno < (unsigned int)max_regno; use.regno++)
+ if (use.regno >= FIRST_PSEUDO_REGISTER || !fixed_regs[use.regno])
+ for (link = df->regs[use.regno].uses; link; link = link->next)
+ if (link->ref)
+ {
+ struct ref *ref = link->ref;
+ rtx insn = DF_REF_INSN (ref);
+ /* Only recheck marked or new uses, or uses from hardregs. */
+ if (use.regno >= FIRST_PSEUDO_REGISTER
+ && DF_REF_ID (ref) < last_use_id
+ && !TEST_BIT (last_check_uses, DF_REF_ID (ref)))
+ continue;
+ use.wp = &web_parts[df->def_id + DF_REF_ID (ref)];
+ use.x = DF_REF_REG (ref);
+ use.live_over_abnormal = 0;
+ use.undefined = rtx_to_undefined (use.x);
+ visited_pass++;
+ live_in (df, &use, insn);
+ if (use.live_over_abnormal)
+ SET_BIT (live_over_abnormal, DF_REF_ID (ref));
+ }
+
+ dump_number_seen ();
+ FOR_ALL_BB (bb)
+ {
+ struct ra_bb_info *info = (struct ra_bb_info *) bb->aux;
+ livethrough_conflicts_bb (bb);
+ bitmap_zero (info->live_throughout);
+ info->pass = 0;
+ }
+ free (visit_trace);
+ free (number_seen);
+}
+
+/* Here we look per insn, for DF references being in uses _and_ defs.
+ This means, in the RTL a (REG xx) expression was seen as a
+ read/modify/write, as happens for (set (subreg:SI (reg:DI xx)) (...))
+ e.g. Our code has created two webs for this, as it should. Unfortunately,
+ as the REG reference is only one time in the RTL we can't color
+ both webs different (arguably this also would be wrong for a real
+ read-mod-write instruction), so we must reconnect such webs. */
+
+static void
+connect_rmw_web_parts (df)
+ struct df *df;
+{
+ unsigned int i;
+
+ for (i = 0; i < df->use_id; i++)
+ {
+ struct web_part *wp1 = &web_parts[df->def_id + i];
+ rtx reg;
+ struct df_link *link;
+ if (!wp1->ref)
+ continue;
+ /* If it's an uninitialized web, we don't want to connect it to others,
+ as the read cycle in read-mod-write had probably no effect. */
+ if (find_web_part (wp1) >= &web_parts[df->def_id])
+ continue;
+ reg = DF_REF_REAL_REG (wp1->ref);
+ link = DF_INSN_DEFS (df, DF_REF_INSN (wp1->ref));
+ for (; link; link = link->next)
+ if (reg == DF_REF_REAL_REG (link->ref))
+ {
+ struct web_part *wp2 = &web_parts[DF_REF_ID (link->ref)];
+ union_web_parts (wp1, wp2);
+ }
+ }
+}
+
+/* Deletes all hardregs from *S which are not allowed for MODE. */
+
+static void
+prune_hardregs_for_mode (s, mode)
+ HARD_REG_SET *s;
+ enum machine_mode mode;
+{
+ AND_HARD_REG_SET (*s, hardregs_for_mode[(int) mode]);
+}
+
+/* Initialize the members of a web, which are deducible from REG. */
+
+static void
+init_one_web_common (web, reg)
+ struct web *web;
+ rtx reg;
+{
+ if (GET_CODE (reg) != REG)
+ abort ();
+ /* web->id isn't initialized here. */
+ web->regno = REGNO (reg);
+ web->orig_x = reg;
+ if (!web->dlink)
+ {
+ web->dlink = (struct dlist *) ra_calloc (sizeof (struct dlist));
+ DLIST_WEB (web->dlink) = web;
+ }
+ /* XXX
+ the former (superunion) doesn't constrain the graph enough. E.g.
+ on x86 QImode _requires_ QI_REGS, but as alternate class usually
+ GENERAL_REGS is given. So the graph is not constrained enough,
+ thinking it has more freedom then it really has, which leads
+ to repeated spill tryings. OTOH the latter (only using preferred
+ class) is too constrained, as normally (e.g. with all SImode
+ pseudos), they can be allocated also in the alternate class.
+ What we really want, are the _exact_ hard regs allowed, not
+ just a class. Later. */
+ /*web->regclass = reg_class_superunion
+ [reg_preferred_class (web->regno)]
+ [reg_alternate_class (web->regno)];*/
+ /*web->regclass = reg_preferred_class (web->regno);*/
+ web->regclass = reg_class_subunion
+ [reg_preferred_class (web->regno)] [reg_alternate_class (web->regno)];
+ web->regclass = reg_preferred_class (web->regno);
+ if (web->regno < FIRST_PSEUDO_REGISTER)
+ {
+ web->color = web->regno;
+ put_web (web, PRECOLORED);
+ web->num_conflicts = UINT_MAX;
+ web->add_hardregs = 0;
+ CLEAR_HARD_REG_SET (web->usable_regs);
+ SET_HARD_REG_BIT (web->usable_regs, web->regno);
+ web->num_freedom = 1;
+ }
+ else
+ {
+ HARD_REG_SET alternate;
+ web->color = -1;
+ put_web (web, INITIAL);
+ /* add_hardregs is wrong in multi-length classes, e.g.
+ using a DFmode pseudo on x86 can result in class FLOAT_INT_REGS,
+ where, if it finally is allocated to GENERAL_REGS it needs two,
+ if allocated to FLOAT_REGS only one hardreg. XXX */
+ web->add_hardregs =
+ CLASS_MAX_NREGS (web->regclass, PSEUDO_REGNO_MODE (web->regno)) - 1;
+ web->num_conflicts = 0 * web->add_hardregs;
+ COPY_HARD_REG_SET (web->usable_regs,
+ reg_class_contents[reg_preferred_class (web->regno)]);
+ COPY_HARD_REG_SET (alternate,
+ reg_class_contents[reg_alternate_class (web->regno)]);
+ IOR_HARD_REG_SET (web->usable_regs, alternate);
+ /*IOR_HARD_REG_SET (web->usable_regs,
+ reg_class_contents[reg_alternate_class
+ (web->regno)]);*/
+ AND_COMPL_HARD_REG_SET (web->usable_regs, never_use_colors);
+ prune_hardregs_for_mode (&web->usable_regs,
+ PSEUDO_REGNO_MODE (web->regno));
+#ifdef CLASS_CANNOT_CHANGE_MODE
+ if (web->mode_changed)
+ AND_COMPL_HARD_REG_SET (web->usable_regs, reg_class_contents[
+ (int) CLASS_CANNOT_CHANGE_MODE]);
+#endif
+ web->num_freedom = hard_regs_count (web->usable_regs);
+ web->num_freedom -= web->add_hardregs;
+ if (!web->num_freedom)
+ abort();
+ }
+ COPY_HARD_REG_SET (web->orig_usable_regs, web->usable_regs);
+}
+
+/* Initializes WEBs members from REG or zero them. */
+
+static void
+init_one_web (web, reg)
+ struct web *web;
+ rtx reg;
+{
+ memset (web, 0, sizeof (struct web));
+ init_one_web_common (web, reg);
+ web->useless_conflicts = BITMAP_XMALLOC ();
+}
+
+/* WEB is an old web, meaning it came from the last pass, and got a
+ color. We want to remember some of it's info, so zero only some
+ members. */
+
+static void
+reinit_one_web (web, reg)
+ struct web *web;
+ rtx reg;
+{
+ web->old_color = web->color + 1;
+ init_one_web_common (web, reg);
+ web->span_deaths = 0;
+ web->spill_temp = 0;
+ web->orig_spill_temp = 0;
+ web->use_my_regs = 0;
+ web->spill_cost = 0;
+ web->was_spilled = 0;
+ web->is_coalesced = 0;
+ web->artificial = 0;
+ web->live_over_abnormal = 0;
+ web->mode_changed = 0;
+ web->move_related = 0;
+ web->in_load = 0;
+ web->target_of_spilled_move = 0;
+ web->num_aliased = 0;
+ if (web->type == PRECOLORED)
+ {
+ web->num_defs = 0;
+ web->num_uses = 0;
+ web->orig_spill_cost = 0;
+ }
+ CLEAR_HARD_REG_SET (web->bias_colors);
+ CLEAR_HARD_REG_SET (web->prefer_colors);
+ web->reg_rtx = NULL;
+ web->stack_slot = NULL;
+ web->pattern = NULL;
+ web->alias = NULL;
+ if (web->moves)
+ abort ();
+ if (!web->useless_conflicts)
+ abort ();
+}
+
+/* Insert and returns a subweb corresponding to REG into WEB (which
+ becomes its super web). It must not exist already. */
+
+static struct web *
+add_subweb (web, reg)
+ struct web *web;
+ rtx reg;
+{
+ struct web *w;
+ if (GET_CODE (reg) != SUBREG)
+ abort ();
+ w = (struct web *) xmalloc (sizeof (struct web));
+ /* Copy most content from parent-web. */
+ *w = *web;
+ /* And initialize the private stuff. */
+ w->orig_x = reg;
+ w->add_hardregs = CLASS_MAX_NREGS (web->regclass, GET_MODE (reg)) - 1;
+ w->num_conflicts = 0 * w->add_hardregs;
+ w->num_defs = 0;
+ w->num_uses = 0;
+ w->dlink = NULL;
+ w->parent_web = web;
+ w->subreg_next = web->subreg_next;
+ web->subreg_next = w;
+ return w;
+}
+
+/* Similar to add_subweb(), but instead of relying on a given SUBREG,
+ we have just a size and an offset of the subpart of the REG rtx.
+ In difference to add_subweb() this marks the new subweb as artificial. */
+
+static struct web *
+add_subweb_2 (web, size_word)
+ struct web *web;
+ unsigned int size_word;
+{
+ /* To get a correct mode for the to be produced subreg, we don't want to
+ simply do a mode_for_size() for the mode_class of the whole web.
+ Suppose we deal with a CDImode web, but search for a 8 byte part.
+ Now mode_for_size() would only search in the class MODE_COMPLEX_INT
+ and would find CSImode which probably is not what we want. Instead
+ we want DImode, which is in a completely other class. For this to work
+ we instead first search the already existing subwebs, and take
+ _their_ modeclasses as base for a search for ourself. */
+ rtx ref_rtx = (web->subreg_next ? web->subreg_next : web)->orig_x;
+ unsigned int size = BYTE_LENGTH (size_word) * BITS_PER_UNIT;
+ enum machine_mode mode;
+ mode = mode_for_size (size, GET_MODE_CLASS (GET_MODE (ref_rtx)), 0);
+ if (mode == BLKmode)
+ mode = mode_for_size (size, MODE_INT, 0);
+ if (mode == BLKmode)
+ abort ();
+ web = add_subweb (web, gen_rtx_SUBREG (mode, web->orig_x,
+ BYTE_BEGIN (size_word)));
+ web->artificial = 1;
+ return web;
+}
+
+/* Initialize all the web parts we are going to need. */
+
+static void
+init_web_parts (df)
+ struct df *df;
+{
+ int regno;
+ unsigned int no;
+ num_webs = 0;
+ for (no = 0; no < df->def_id; no++)
+ {
+ if (df->defs[no])
+ {
+ if (no < last_def_id && web_parts[no].ref != df->defs[no])
+ abort ();
+ web_parts[no].ref = df->defs[no];
+ /* Uplink might be set from the last iteration. */
+ if (!web_parts[no].uplink)
+ num_webs++;
+ }
+ else
+ /* The last iteration might have left .ref set, while df_analyse()
+ removed that ref (due to a removed copy insn) from the df->defs[]
+ array. As we don't check for that in realloc_web_parts()
+ we do that here. */
+ web_parts[no].ref = NULL;
+ }
+ for (no = 0; no < df->use_id; no++)
+ {
+ if (df->uses[no])
+ {
+ if (no < last_use_id
+ && web_parts[no + df->def_id].ref != df->uses[no])
+ abort ();
+ web_parts[no + df->def_id].ref = df->uses[no];
+ if (!web_parts[no + df->def_id].uplink)
+ num_webs++;
+ }
+ else
+ web_parts[no + df->def_id].ref = NULL;
+ }
+
+ /* We want to have only one web for each precolored register. */
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ {
+ struct web_part *r1 = NULL;
+ struct df_link *link;
+ /* Here once was a test, if there is any DEF at all, and only then to
+ merge all the parts. This was incorrect, we really also want to have
+ only one web-part for hardregs, even if there is no explicit DEF. */
+ /* Link together all defs... */
+ for (link = df->regs[regno].defs; link; link = link->next)
+ if (link->ref)
+ {
+ struct web_part *r2 = &web_parts[DF_REF_ID (link->ref)];
+ if (!r1)
+ r1 = r2;
+ else
+ r1 = union_web_parts (r1, r2);
+ }
+ /* ... and all uses. */
+ for (link = df->regs[regno].uses; link; link = link->next)
+ if (link->ref)
+ {
+ struct web_part *r2 = &web_parts[df->def_id
+ + DF_REF_ID (link->ref)];
+ if (!r1)
+ r1 = r2;
+ else
+ r1 = union_web_parts (r1, r2);
+ }
+ }
+}
+
+/* In case we want to remember the conflict list of a WEB, before adding
+ new conflicts, we copy it here to orig_conflict_list. */
+
+static void
+copy_conflict_list (web)
+ struct web *web;
+{
+ struct conflict_link *cl;
+ if (web->orig_conflict_list || web->have_orig_conflicts)
+ abort ();
+ web->have_orig_conflicts = 1;
+ for (cl = web->conflict_list; cl; cl = cl->next)
+ {
+ struct conflict_link *ncl;
+ ncl = (struct conflict_link *) ra_alloc (sizeof *ncl);
+ ncl->t = cl->t;
+ ncl->sub = NULL;
+ ncl->next = web->orig_conflict_list;
+ web->orig_conflict_list = ncl;
+ if (cl->sub)
+ {
+ struct sub_conflict *sl, *nsl;
+ for (sl = cl->sub; sl; sl = sl->next)
+ {
+ nsl = (struct sub_conflict *) ra_alloc (sizeof *nsl);
+ nsl->s = sl->s;
+ nsl->t = sl->t;
+ nsl->next = ncl->sub;
+ ncl->sub = nsl;
+ }
+ }
+ }
+}
+
+/* Possibly add an edge from web FROM to TO marking a conflict between
+ those two. This is one half of marking a complete conflict, which notes
+ in FROM, that TO is a conflict. Adding TO to FROM's conflicts might
+ make other conflicts superflous, because the current TO overlaps some web
+ already being in conflict with FROM. In this case the smaller webs are
+ deleted from the conflict list. Likewise if TO is overlapped by a web
+ already in the list, it isn't added at all. Note, that this can only
+ happen, if SUBREG webs are involved. */
+
+static void
+add_conflict_edge (from, to)
+ struct web *from, *to;
+{
+ if (from->type != PRECOLORED)
+ {
+ struct web *pfrom = find_web_for_subweb (from);
+ struct web *pto = find_web_for_subweb (to);
+ struct sub_conflict *sl;
+ struct conflict_link *cl = pfrom->conflict_list;
+ int may_delete = 1;
+
+ /* This can happen when subwebs of one web conflict with each
+ other. In live_out_1() we created such conflicts between yet
+ undefined webparts and defs of parts which didn't overlap with the
+ undefined bits. Then later they nevertheless could have merged into
+ one web, and then we land here. */
+ if (pfrom == pto)
+ return;
+ if (remember_conflicts && !pfrom->have_orig_conflicts)
+ copy_conflict_list (pfrom);
+ if (!TEST_BIT (sup_igraph, (pfrom->id * num_webs + pto->id)))
+ {
+ cl = (struct conflict_link *) ra_alloc (sizeof (*cl));
+ cl->t = pto;
+ cl->sub = NULL;
+ cl->next = pfrom->conflict_list;
+ pfrom->conflict_list = cl;
+ if (pto->type != SELECT && pto->type != COALESCED)
+ pfrom->num_conflicts += 1 + pto->add_hardregs;
+ SET_BIT (sup_igraph, (pfrom->id * num_webs + pto->id));
+ may_delete = 0;
+ }
+ else
+ /* We don't need to test for cl==NULL, because at this point
+ a cl with cl->t==pto is guaranteed to exist. */
+ while (cl->t != pto)
+ cl = cl->next;
+ if (pfrom != from || pto != to)
+ {
+ /* This is a subconflict which should be added.
+ If we inserted cl in this invocation, we really need to add this
+ subconflict. If we did _not_ add it here, we only add the
+ subconflict, if cl already had subconflicts, because otherwise
+ this indicated, that the whole webs already conflict, which
+ means we are not interested in this subconflict. */
+ if (!may_delete || cl->sub != NULL)
+ {
+ sl = (struct sub_conflict *) ra_alloc (sizeof (*sl));
+ sl->s = from;
+ sl->t = to;
+ sl->next = cl->sub;
+ cl->sub = sl;
+ }
+ }
+ else
+ /* pfrom == from && pto == to means, that we are not interested
+ anymore in the subconflict list for this pair, because anyway
+ the whole webs conflict. */
+ cl->sub = NULL;
+ }
+}
+
+/* Record a conflict between two webs, if we haven't recorded it
+ already. */
+
+void
+record_conflict (web1, web2)
+ struct web *web1, *web2;
+{
+ unsigned int id1 = web1->id, id2 = web2->id;
+ unsigned int index = igraph_index (id1, id2);
+ /* Trivial non-conflict or already recorded conflict. */
+ if (web1 == web2 || TEST_BIT (igraph, index))
+ return;
+ if (id1 == id2)
+ abort ();
+ /* As fixed_regs are no targets for allocation, conflicts with them
+ are pointless. */
+ if ((web1->regno < FIRST_PSEUDO_REGISTER && fixed_regs[web1->regno])
+ || (web2->regno < FIRST_PSEUDO_REGISTER && fixed_regs[web2->regno]))
+ return;
+ /* Conflicts with hardregs, which are not even a candidate
+ for this pseudo are also pointless. */
+ if ((web1->type == PRECOLORED
+ && ! TEST_HARD_REG_BIT (web2->usable_regs, web1->regno))
+ || (web2->type == PRECOLORED
+ && ! TEST_HARD_REG_BIT (web1->usable_regs, web2->regno)))
+ return;
+ /* Similar if the set of possible hardregs don't intersect. This iteration
+ those conflicts are useless (and would make num_conflicts wrong, because
+ num_freedom is calculated from the set of possible hardregs).
+ But in presence of spilling and incremental building of the graph we
+ need to note all uses of webs conflicting with the spilled ones.
+ Because the set of possible hardregs can change in the next round for
+ spilled webs, we possibly have then conflicts with webs which would
+ be excluded now (because then hardregs intersect). But we actually
+ need to check those uses, and to get hold of them, we need to remember
+ also webs conflicting with this one, although not conflicting in this
+ round because of non-intersecting hardregs. */
+ if (web1->type != PRECOLORED && web2->type != PRECOLORED
+ && ! hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs))
+ {
+ struct web *p1 = find_web_for_subweb (web1);
+ struct web *p2 = find_web_for_subweb (web2);
+ /* We expect these to be rare enough to justify bitmaps. And because
+ we have only a special use for it, we note only the superwebs. */
+ bitmap_set_bit (p1->useless_conflicts, p2->id);
+ bitmap_set_bit (p2->useless_conflicts, p1->id);
+ return;
+ }
+ SET_BIT (igraph, index);
+ add_conflict_edge (web1, web2);
+ add_conflict_edge (web2, web1);
+}
+
+/* For each web W this produces the missing subwebs Wx, such that it's
+ possible to exactly specify (W-Wy) for all already existing subwebs Wy. */
+
+static void
+build_inverse_webs (web)
+ struct web *web;
+{
+ struct web *sweb = web->subreg_next;
+ unsigned HOST_WIDE_INT undef;
+
+ undef = rtx_to_undefined (web->orig_x);
+ for (; sweb; sweb = sweb->subreg_next)
+ /* Only create inverses of non-artificial webs. */
+ if (!sweb->artificial)
+ {
+ unsigned HOST_WIDE_INT bits;
+ bits = undef & ~ rtx_to_undefined (sweb->orig_x);
+ while (bits)
+ {
+ unsigned int size_word = undef_to_size_word (web->orig_x, &bits);
+ if (!find_subweb_2 (web, size_word))
+ add_subweb_2 (web, size_word);
+ }
+ }
+}
+
+/* Copies the content of WEB to a new one, and link it into WL.
+ Used for consistency checking. */
+
+static void
+copy_web (web, wl)
+ struct web *web;
+ struct web_link **wl;
+{
+ struct web *cweb = (struct web *) xmalloc (sizeof *cweb);
+ struct web_link *link = (struct web_link *) ra_alloc (sizeof *link);
+ link->next = *wl;
+ *wl = link;
+ link->web = cweb;
+ *cweb = *web;
+}
+
+/* Given a list of webs LINK, compare the content of the webs therein
+ with the global webs of the same ID. For consistency checking. */
+
+static void
+compare_and_free_webs (link)
+ struct web_link **link;
+{
+ struct web_link *wl;
+ for (wl = *link; wl; wl = wl->next)
+ {
+ struct web *web1 = wl->web;
+ struct web *web2 = ID2WEB (web1->id);
+ if (web1->regno != web2->regno
+ || web1->crosses_call != web2->crosses_call
+ || web1->live_over_abnormal != web2->live_over_abnormal
+ || web1->mode_changed != web2->mode_changed
+ || !rtx_equal_p (web1->orig_x, web2->orig_x)
+ || web1->type != web2->type
+ /* Only compare num_defs/num_uses with non-hardreg webs.
+ E.g. the number of uses of the framepointer changes due to
+ inserting spill code. */
+ || (web1->type != PRECOLORED &&
+ (web1->num_uses != web2->num_uses
+ || web1->num_defs != web2->num_defs)))
+ abort ();
+ if (web1->type != PRECOLORED)
+ {
+ unsigned int i;
+ for (i = 0; i < web1->num_defs; i++)
+ if (web1->defs[i] != web2->defs[i])
+ abort ();
+ for (i = 0; i < web1->num_uses; i++)
+ if (web1->uses[i] != web2->uses[i])
+ abort ();
+ }
+ if (web1->type == PRECOLORED)
+ {
+ if (web1->defs)
+ free (web1->defs);
+ if (web1->uses)
+ free (web1->uses);
+ }
+ free (web1);
+ }
+ *link = NULL;
+}
+
+/* Setup and fill uses[] and defs[] arrays of the webs. */
+
+static void
+init_webs_defs_uses ()
+{
+ struct dlist *d;
+ for (d = WEBS(INITIAL); d; d = d->next)
+ {
+ struct web *web = DLIST_WEB (d);
+ unsigned int def_i, use_i;
+ struct df_link *link;
+ if (web->old_web)
+ continue;
+ if (web->type == PRECOLORED)
+ {
+ web->num_defs = web->num_uses = 0;
+ continue;
+ }
+ if (web->num_defs)
+ web->defs = (struct ref **) xmalloc (web->num_defs *
+ sizeof (web->defs[0]));
+ if (web->num_uses)
+ web->uses = (struct ref **) xmalloc (web->num_uses *
+ sizeof (web->uses[0]));
+ def_i = use_i = 0;
+ for (link = web->temp_refs; link; link = link->next)
+ {
+ if (DF_REF_REG_DEF_P (link->ref))
+ web->defs[def_i++] = link->ref;
+ else
+ web->uses[use_i++] = link->ref;
+ }
+ web->temp_refs = NULL;
+ if (def_i != web->num_defs || use_i != web->num_uses)
+ abort ();
+ }
+}
+
+/* Called by parts_to_webs(). This creates (or recreates) the webs (and
+ subwebs) from web parts, gives them IDs (only to super webs), and sets
+ up use2web and def2web arrays. */
+
+static unsigned int
+parts_to_webs_1 (df, copy_webs, all_refs)
+ struct df *df;
+ struct web_link **copy_webs;
+ struct df_link *all_refs;
+{
+ unsigned int i;
+ unsigned int webnum;
+ unsigned int def_id = df->def_id;
+ unsigned int use_id = df->use_id;
+ struct web_part *wp_first_use = &web_parts[def_id];
+
+ /* For each root web part: create and initialize a new web,
+ setup def2web[] and use2web[] for all defs and uses, and
+ id2web for all new webs. */
+
+ webnum = 0;
+ for (i = 0; i < def_id + use_id; i++)
+ {
+ struct web *subweb, *web = 0; /* Initialize web to silence warnings. */
+ struct web_part *wp = &web_parts[i];
+ struct ref *ref = wp->ref;
+ unsigned int ref_id;
+ rtx reg;
+ if (!ref)
+ continue;
+ ref_id = i;
+ if (i >= def_id)
+ ref_id -= def_id;
+ all_refs[i].ref = ref;
+ reg = DF_REF_REG (ref);
+ if (! wp->uplink)
+ {
+ /* If we have a web part root, create a new web. */
+ unsigned int newid = ~(unsigned)0;
+ unsigned int old_web = 0;
+
+ /* In the first pass, there are no old webs, so unconditionally
+ allocate a new one. */
+ if (ra_pass == 1)
+ {
+ web = (struct web *) xmalloc (sizeof (struct web));
+ newid = last_num_webs++;
+ init_one_web (web, GET_CODE (reg) == SUBREG
+ ? SUBREG_REG (reg) : reg);
+ }
+ /* Otherwise, we look for an old web. */
+ else
+ {
+ /* Remember, that use2web == def2web + def_id.
+ Ergo is def2web[i] == use2web[i - def_id] for i >= def_id.
+ So we only need to look into def2web[] array.
+ Try to look at the web, which formerly belonged to this
+ def (or use). */
+ web = def2web[i];
+ /* Or which belonged to this hardreg. */
+ if (!web && DF_REF_REGNO (ref) < FIRST_PSEUDO_REGISTER)
+ web = hardreg2web[DF_REF_REGNO (ref)];
+ if (web)
+ {
+ /* If we found one, reuse it. */
+ web = find_web_for_subweb (web);
+ remove_list (web->dlink, &WEBS(INITIAL));
+ old_web = 1;
+ copy_web (web, copy_webs);
+ }
+ else
+ {
+ /* Otherwise use a new one. First from the free list. */
+ if (WEBS(FREE))
+ web = DLIST_WEB (pop_list (&WEBS(FREE)));
+ else
+ {
+ /* Else allocate a new one. */
+ web = (struct web *) xmalloc (sizeof (struct web));
+ newid = last_num_webs++;
+ }
+ }
+ /* The id is zeroed in init_one_web(). */
+ if (newid == ~(unsigned)0)
+ newid = web->id;
+ if (old_web)
+ reinit_one_web (web, GET_CODE (reg) == SUBREG
+ ? SUBREG_REG (reg) : reg);
+ else
+ init_one_web (web, GET_CODE (reg) == SUBREG
+ ? SUBREG_REG (reg) : reg);
+ web->old_web = (old_web && web->type != PRECOLORED) ? 1 : 0;
+ }
+ web->span_deaths = wp->spanned_deaths;
+ web->crosses_call = wp->crosses_call;
+ web->id = newid;
+ web->temp_refs = NULL;
+ webnum++;
+ if (web->regno < FIRST_PSEUDO_REGISTER && !hardreg2web[web->regno])
+ hardreg2web[web->regno] = web;
+ else if (web->regno < FIRST_PSEUDO_REGISTER
+ && hardreg2web[web->regno] != web)
+ abort ();
+ }
+
+ /* If this reference already had a web assigned, we are done.
+ This test better is equivalent to the web being an old web.
+ Otherwise something is screwed. (This is tested) */
+ if (def2web[i] != NULL)
+ {
+ web = def2web[i];
+ web = find_web_for_subweb (web);
+ /* But if this ref includes a mode change, or was a use live
+ over an abnormal call, set appropriate flags in the web. */
+ if ((DF_REF_FLAGS (ref) & DF_REF_MODE_CHANGE) != 0
+ && web->regno >= FIRST_PSEUDO_REGISTER)
+ web->mode_changed = 1;
+ if (i >= def_id
+ && TEST_BIT (live_over_abnormal, ref_id))
+ web->live_over_abnormal = 1;
+ /* And check, that it's not a newly allocated web. This would be
+ an inconsistency. */
+ if (!web->old_web || web->type == PRECOLORED)
+ abort ();
+ continue;
+ }
+ /* In case this was no web part root, we need to initialize WEB
+ from the ref2web array belonging to the root. */
+ if (wp->uplink)
+ {
+ struct web_part *rwp = find_web_part (wp);
+ unsigned int j = DF_REF_ID (rwp->ref);
+ if (rwp < wp_first_use)
+ web = def2web[j];
+ else
+ web = use2web[j];
+ web = find_web_for_subweb (web);
+ }
+
+ /* Remember all references for a web in a single linked list. */
+ all_refs[i].next = web->temp_refs;
+ web->temp_refs = &all_refs[i];
+
+ /* And the test, that if def2web[i] was NULL above, that we are _not_
+ an old web. */
+ if (web->old_web && web->type != PRECOLORED)
+ abort ();
+
+ /* Possible create a subweb, if this ref was a subreg. */
+ if (GET_CODE (reg) == SUBREG)
+ {
+ subweb = find_subweb (web, reg);
+ if (!subweb)
+ {
+ subweb = add_subweb (web, reg);
+ if (web->old_web)
+ abort ();
+ }
+ }
+ else
+ subweb = web;
+
+ /* And look, if the ref involves an invalid mode change. */
+ if ((DF_REF_FLAGS (ref) & DF_REF_MODE_CHANGE) != 0
+ && web->regno >= FIRST_PSEUDO_REGISTER)
+ web->mode_changed = 1;
+
+ /* Setup def2web, or use2web, and increment num_defs or num_uses. */
+ if (i < def_id)
+ {
+ /* Some sanity checks. */
+ if (ra_pass > 1)
+ {
+ struct web *compare = def2web[i];
+ if (i < last_def_id)
+ {
+ if (web->old_web && compare != subweb)
+ abort ();
+ }
+ if (!web->old_web && compare)
+ abort ();
+ if (compare && compare != subweb)
+ abort ();
+ }
+ def2web[i] = subweb;
+ web->num_defs++;
+ }
+ else
+ {
+ if (ra_pass > 1)
+ {
+ struct web *compare = use2web[ref_id];
+ if (ref_id < last_use_id)
+ {
+ if (web->old_web && compare != subweb)
+ abort ();
+ }
+ if (!web->old_web && compare)
+ abort ();
+ if (compare && compare != subweb)
+ abort ();
+ }
+ use2web[ref_id] = subweb;
+ web->num_uses++;
+ if (TEST_BIT (live_over_abnormal, ref_id))
+ web->live_over_abnormal = 1;
+ }
+ }
+
+ /* We better now have exactly as many webs as we had web part roots. */
+ if (webnum != num_webs)
+ abort ();
+
+ return webnum;
+}
+
+/* This builds full webs out of web parts, without relating them to each
+ other (i.e. without creating the conflict edges). */
+
+static void
+parts_to_webs (df)
+ struct df *df;
+{
+ unsigned int i;
+ unsigned int webnum;
+ struct web_link *copy_webs = NULL;
+ struct dlist *d;
+ struct df_link *all_refs;
+ num_subwebs = 0;
+
+ /* First build webs and ordinary subwebs. */
+ all_refs = (struct df_link *) xcalloc (df->def_id + df->use_id,
+ sizeof (all_refs[0]));
+ webnum = parts_to_webs_1 (df, &copy_webs, all_refs);
+
+ /* Setup the webs for hardregs which are still missing (weren't
+ mentioned in the code). */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (!hardreg2web[i])
+ {
+ struct web *web = (struct web *) xmalloc (sizeof (struct web));
+ init_one_web (web, gen_rtx_REG (reg_raw_mode[i], i));
+ web->id = last_num_webs++;
+ hardreg2web[web->regno] = web;
+ }
+ num_webs = last_num_webs;
+
+ /* Now create all artificial subwebs, i.e. those, which do
+ not correspond to a real subreg in the current function's RTL, but
+ which nevertheless is a target of a conflict.
+ XXX we need to merge this loop with the one above, which means, we need
+ a way to later override the artificiality. Beware: currently
+ add_subweb_2() relies on the existence of normal subwebs for deducing
+ a sane mode to use for the artificial subwebs. */
+ for (i = 0; i < df->def_id + df->use_id; i++)
+ {
+ struct web_part *wp = &web_parts[i];
+ struct tagged_conflict *cl;
+ struct web *web;
+ if (wp->uplink || !wp->ref)
+ {
+ if (wp->sub_conflicts)
+ abort ();
+ continue;
+ }
+ web = def2web[i];
+ web = find_web_for_subweb (web);
+ for (cl = wp->sub_conflicts; cl; cl = cl->next)
+ if (!find_subweb_2 (web, cl->size_word))
+ add_subweb_2 (web, cl->size_word);
+ }
+
+ /* And now create artificial subwebs needed for representing the inverse
+ of some subwebs. This also gives IDs to all subwebs. */
+ webnum = last_num_webs;
+ for (d = WEBS(INITIAL); d; d = d->next)
+ {
+ struct web *web = DLIST_WEB (d);
+ if (web->subreg_next)
+ {
+ struct web *sweb;
+ build_inverse_webs (web);
+ for (sweb = web->subreg_next; sweb; sweb = sweb->subreg_next)
+ sweb->id = webnum++;
+ }
+ }
+
+ /* Now that everyone has an ID, we can setup the id2web array. */
+ id2web = (struct web **) xcalloc (webnum, sizeof (id2web[0]));
+ for (d = WEBS(INITIAL); d; d = d->next)
+ {
+ struct web *web = DLIST_WEB (d);
+ ID2WEB (web->id) = web;
+ for (web = web->subreg_next; web; web = web->subreg_next)
+ ID2WEB (web->id) = web;
+ }
+ num_subwebs = webnum - last_num_webs;
+ num_allwebs = num_webs + num_subwebs;
+ num_webs += num_subwebs;
+
+ /* Allocate and clear the conflict graph bitmaps. */
+ igraph = sbitmap_alloc (num_webs * num_webs / 2);
+ sup_igraph = sbitmap_alloc (num_webs * num_webs);
+ sbitmap_zero (igraph);
+ sbitmap_zero (sup_igraph);
+
+ /* Distibute the references to their webs. */
+ init_webs_defs_uses ();
+ /* And do some sanity checks if old webs, and those recreated from the
+ really are the same. */
+ compare_and_free_webs (&copy_webs);
+ free (all_refs);
+}
+
+/* This deletes all conflicts to and from webs which need to be renewed
+ in this pass of the allocator, i.e. those which were spilled in the
+ last pass. Furthermore it also rebuilds the bitmaps for the remaining
+ conflicts. */
+
+static void
+reset_conflicts ()
+{
+ unsigned int i;
+ bitmap newwebs = BITMAP_XMALLOC ();
+ for (i = 0; i < num_webs - num_subwebs; i++)
+ {
+ struct web *web = ID2WEB (i);
+ /* Hardreg webs and non-old webs are new webs (which
+ need rebuilding). */
+ if (web->type == PRECOLORED || !web->old_web)
+ bitmap_set_bit (newwebs, web->id);
+ }
+
+ for (i = 0; i < num_webs - num_subwebs; i++)
+ {
+ struct web *web = ID2WEB (i);
+ struct conflict_link *cl;
+ struct conflict_link **pcl;
+ pcl = &(web->conflict_list);
+
+ /* First restore the conflict list to be like it was before
+ coalescing. */
+ if (web->have_orig_conflicts)
+ {
+ web->conflict_list = web->orig_conflict_list;
+ web->orig_conflict_list = NULL;
+ }
+ if (web->orig_conflict_list)
+ abort ();
+
+ /* New non-precolored webs, have no conflict list. */
+ if (web->type != PRECOLORED && !web->old_web)
+ {
+ *pcl = NULL;
+ /* Useless conflicts will be rebuilt completely. But check
+ for cleanlyness, as the web might have come from the
+ free list. */
+ if (bitmap_first_set_bit (web->useless_conflicts) >= 0)
+ abort ();
+ }
+ else
+ {
+ /* Useless conflicts with new webs will be rebuilt if they
+ are still there. */
+ bitmap_operation (web->useless_conflicts, web->useless_conflicts,
+ newwebs, BITMAP_AND_COMPL);
+ /* Go through all conflicts, and retain those to old webs. */
+ for (cl = web->conflict_list; cl; cl = cl->next)
+ {
+ if (cl->t->old_web || cl->t->type == PRECOLORED)
+ {
+ *pcl = cl;
+ pcl = &(cl->next);
+
+ /* Also restore the entries in the igraph bitmaps. */
+ web->num_conflicts += 1 + cl->t->add_hardregs;
+ SET_BIT (sup_igraph, (web->id * num_webs + cl->t->id));
+ /* No subconflicts mean full webs conflict. */
+ if (!cl->sub)
+ SET_BIT (igraph, igraph_index (web->id, cl->t->id));
+ else
+ /* Else only the parts in cl->sub must be in the
+ bitmap. */
+ {
+ struct sub_conflict *sl;
+ for (sl = cl->sub; sl; sl = sl->next)
+ SET_BIT (igraph, igraph_index (sl->s->id, sl->t->id));
+ }
+ }
+ }
+ *pcl = NULL;
+ }
+ web->have_orig_conflicts = 0;
+ }
+ BITMAP_XFREE (newwebs);
+}
+
+/* For each web check it's num_conflicts member against that
+ number, as calculated from scratch from all neighbors. */
+
+#if 0
+static void
+check_conflict_numbers ()
+{
+ unsigned int i;
+ for (i = 0; i < num_webs; i++)
+ {
+ struct web *web = ID2WEB (i);
+ int new_conf = 0 * web->add_hardregs;
+ struct conflict_link *cl;
+ for (cl = web->conflict_list; cl; cl = cl->next)
+ if (cl->t->type != SELECT && cl->t->type != COALESCED)
+ new_conf += 1 + cl->t->add_hardregs;
+ if (web->type != PRECOLORED && new_conf != web->num_conflicts)
+ abort ();
+ }
+}
+#endif
+
+/* Convert the conflicts between web parts to conflicts between full webs.
+
+ This can't be done in parts_to_webs(), because for recording conflicts
+ between webs we need to know their final usable_regs set, which is used
+ to discard non-conflicts (between webs having no hard reg in common).
+ But this is set for spill temporaries only after the webs itself are
+ built. Until then the usable_regs set is based on the pseudo regno used
+ in this web, which may contain far less registers than later determined.
+ This would result in us loosing conflicts (due to record_conflict()
+ thinking that a web can only be allocated to the current usable_regs,
+ whereas later this is extended) leading to colorings, where some regs which
+ in reality conflict get the same color. */
+
+static void
+conflicts_between_webs (df)
+ struct df *df;
+{
+ unsigned int i;
+#ifdef STACK_REGS
+ struct dlist *d;
+#endif
+ bitmap ignore_defs = BITMAP_XMALLOC ();
+ unsigned int have_ignored;
+ unsigned int *pass_cache = (unsigned int *) xcalloc (num_webs, sizeof (int));
+ unsigned int pass = 0;
+
+ if (ra_pass > 1)
+ reset_conflicts ();
+
+ /* It is possible, that in the conflict bitmaps still some defs I are noted,
+ which have web_parts[I].ref being NULL. This can happen, when from the
+ last iteration the conflict bitmap for this part wasn't deleted, but a
+ conflicting move insn was removed. It's DEF is still in the conflict
+ bitmap, but it doesn't exist anymore in df->defs. To not have to check
+ it in the tight loop below, we instead remember the ID's of them in a
+ bitmap, and loop only over IDs which are not in it. */
+ for (i = 0; i < df->def_id; i++)
+ if (web_parts[i].ref == NULL)
+ bitmap_set_bit (ignore_defs, i);
+ have_ignored = (bitmap_first_set_bit (ignore_defs) >= 0);
+
+ /* Now record all conflicts between webs. Note that we only check
+ the conflict bitmaps of all defs. Conflict bitmaps are only in
+ webpart roots. If they are in uses, those uses are roots, which
+ means, that this is an uninitialized web, whose conflicts
+ don't matter. Nevertheless for hardregs we also need to check uses.
+ E.g. hardregs used for argument passing have no DEF in the RTL,
+ but if they have uses, they indeed conflict with all DEFs they
+ overlap. */
+ for (i = 0; i < df->def_id + df->use_id; i++)
+ {
+ struct tagged_conflict *cl = web_parts[i].sub_conflicts;
+ struct web *supweb1;
+ if (!cl
+ || (i >= df->def_id
+ && DF_REF_REGNO (web_parts[i].ref) >= FIRST_PSEUDO_REGISTER))
+ continue;
+ supweb1 = def2web[i];
+ supweb1 = find_web_for_subweb (supweb1);
+ for (; cl; cl = cl->next)
+ if (cl->conflicts)
+ {
+ int j;
+ struct web *web1 = find_subweb_2 (supweb1, cl->size_word);
+ if (have_ignored)
+ bitmap_operation (cl->conflicts, cl->conflicts, ignore_defs,
+ BITMAP_AND_COMPL);
+ /* We reduce the number of calls to record_conflict() with this
+ pass thing. record_conflict() itself also has some early-out
+ optimizations, but here we can use the special properties of
+ the loop (constant web1) to reduce that even more.
+ We once used an sbitmap of already handled web indices,
+ but sbitmaps are slow to clear and bitmaps are slow to
+ set/test. The current approach needs more memory, but
+ locality is large. */
+ pass++;
+
+ /* Note, that there are only defs in the conflicts bitset. */
+ EXECUTE_IF_SET_IN_BITMAP (
+ cl->conflicts, 0, j,
+ {
+ struct web *web2 = def2web[j];
+ unsigned int id2 = web2->id;
+ if (pass_cache[id2] != pass)
+ {
+ pass_cache[id2] = pass;
+ record_conflict (web1, web2);
+ }
+ });
+ }
+ }
+
+ free (pass_cache);
+ BITMAP_XFREE (ignore_defs);
+
+#ifdef STACK_REGS
+ /* Pseudos can't go in stack regs if they are live at the beginning of
+ a block that is reached by an abnormal edge. */
+ for (d = WEBS(INITIAL); d; d = d->next)
+ {
+ struct web *web = DLIST_WEB (d);
+ int j;
+ if (web->live_over_abnormal)
+ for (j = FIRST_STACK_REG; j <= LAST_STACK_REG; j++)
+ record_conflict (web, hardreg2web[j]);
+ }
+#endif
+}
+
+/* Remember that a web was spilled, and change some characteristics
+ accordingly. */
+
+static void
+remember_web_was_spilled (web)
+ struct web *web;
+{
+ int i;
+ unsigned int found_size = 0;
+ int adjust;
+ web->spill_temp = 1;
+
+ /* From now on don't use reg_pref/alt_class (regno) anymore for
+ this web, but instead usable_regs. We can't use spill_temp for
+ this, as it might get reset later, when we are coalesced to a
+ non-spill-temp. In that case we still want to use usable_regs. */
+ web->use_my_regs = 1;
+
+ /* We don't constrain spill temporaries in any way for now.
+ It's wrong sometimes to have the same constraints or
+ preferences as the original pseudo, esp. if they were very narrow.
+ (E.g. there once was a reg wanting class AREG (only one register)
+ without alternative class. As long, as also the spill-temps for
+ this pseudo had the same constraints it was spilled over and over.
+ Ideally we want some constraints also on spill-temps: Because they are
+ not only loaded/stored, but also worked with, any constraints from insn
+ alternatives needs applying. Currently this is dealt with by reload, as
+ many other things, but at some time we want to integrate that
+ functionality into the allocator. */
+ if (web->regno >= max_normal_pseudo)
+ {
+ COPY_HARD_REG_SET (web->usable_regs,
+ reg_class_contents[reg_preferred_class (web->regno)]);
+ IOR_HARD_REG_SET (web->usable_regs,
+ reg_class_contents[reg_alternate_class (web->regno)]);
+ }
+ else
+ COPY_HARD_REG_SET (web->usable_regs,
+ reg_class_contents[(int) GENERAL_REGS]);
+ AND_COMPL_HARD_REG_SET (web->usable_regs, never_use_colors);
+ prune_hardregs_for_mode (&web->usable_regs, PSEUDO_REGNO_MODE (web->regno));
+#ifdef CLASS_CANNOT_CHANGE_MODE
+ if (web->mode_changed)
+ AND_COMPL_HARD_REG_SET (web->usable_regs, reg_class_contents[
+ (int) CLASS_CANNOT_CHANGE_MODE]);
+#endif
+ web->num_freedom = hard_regs_count (web->usable_regs);
+ if (!web->num_freedom)
+ abort();
+ COPY_HARD_REG_SET (web->orig_usable_regs, web->usable_regs);
+ /* Now look for a class, which is subset of our constraints, to
+ setup add_hardregs, and regclass for debug output. */
+ web->regclass = NO_REGS;
+ for (i = (int) ALL_REGS - 1; i > 0; i--)
+ {
+ unsigned int size;
+ HARD_REG_SET test;
+ COPY_HARD_REG_SET (test, reg_class_contents[i]);
+ AND_COMPL_HARD_REG_SET (test, never_use_colors);
+ GO_IF_HARD_REG_SUBSET (test, web->usable_regs, found);
+ continue;
+ found:
+ /* Measure the actual number of bits which really are overlapping
+ the target regset, not just the reg_class_size. */
+ size = hard_regs_count (test);
+ if (found_size < size)
+ {
+ web->regclass = (enum reg_class) i;
+ found_size = size;
+ }
+ }
+
+ adjust = 0 * web->add_hardregs;
+ web->add_hardregs =
+ CLASS_MAX_NREGS (web->regclass, PSEUDO_REGNO_MODE (web->regno)) - 1;
+ web->num_freedom -= web->add_hardregs;
+ if (!web->num_freedom)
+ abort();
+ adjust -= 0 * web->add_hardregs;
+ web->num_conflicts -= adjust;
+}
+
+/* Look at each web, if it is used as spill web. Or better said,
+ if it will be spillable in this pass. */
+
+static void
+detect_spill_temps ()
+{
+ struct dlist *d;
+ bitmap already = BITMAP_XMALLOC ();
+
+ /* Detect webs used for spill temporaries. */
+ for (d = WEBS(INITIAL); d; d = d->next)
+ {
+ struct web *web = DLIST_WEB (d);
+
+ /* Below only the detection of spill temporaries. We never spill
+ precolored webs, so those can't be spill temporaries. The code above
+ (remember_web_was_spilled) can't currently cope with hardregs
+ anyway. */
+ if (web->regno < FIRST_PSEUDO_REGISTER)
+ continue;
+ /* Uninitialized webs can't be spill-temporaries. */
+ if (web->num_defs == 0)
+ continue;
+
+ /* A web with only defs and no uses can't be spilled. Nevertheless
+ it must get a color, as it takes away an register from all webs
+ live at these defs. So we make it a short web. */
+ if (web->num_uses == 0)
+ web->spill_temp = 3;
+ /* A web which was spilled last time, but for which no insns were
+ emitted (can happen with IR spilling ignoring sometimes
+ all deaths). */
+ else if (web->changed)
+ web->spill_temp = 1;
+ /* A spill temporary has one def, one or more uses, all uses
+ are in one insn, and either the def or use insn was inserted
+ by the allocator. */
+ /* XXX not correct currently. There might also be spill temps
+ involving more than one def. Usually that's an additional
+ clobber in the using instruction. We might also constrain
+ ourself to that, instead of like currently marking all
+ webs involving any spill insns at all. */
+ else
+ {
+ unsigned int i;
+ int spill_involved = 0;
+ for (i = 0; i < web->num_uses && !spill_involved; i++)
+ if (DF_REF_INSN_UID (web->uses[i]) >= orig_max_uid)
+ spill_involved = 1;
+ for (i = 0; i < web->num_defs && !spill_involved; i++)
+ if (DF_REF_INSN_UID (web->defs[i]) >= orig_max_uid)
+ spill_involved = 1;
+
+ if (spill_involved/* && ra_pass > 2*/)
+ {
+ int num_deaths = web->span_deaths;
+ /* Mark webs involving at least one spill insn as
+ spill temps. */
+ remember_web_was_spilled (web);
+ /* Search for insns which define and use the web in question
+ at the same time, i.e. look for rmw insns. If these insns
+ are also deaths of other webs they might have been counted
+ as such into web->span_deaths. But because of the rmw nature
+ of this insn it is no point where a load/reload could be
+ placed successfully (it would still conflict with the
+ dead web), so reduce the number of spanned deaths by those
+ insns. Note that sometimes such deaths are _not_ counted,
+ so negative values can result. */
+ bitmap_zero (already);
+ for (i = 0; i < web->num_defs; i++)
+ {
+ rtx insn = web->defs[i]->insn;
+ if (TEST_BIT (insns_with_deaths, INSN_UID (insn))
+ && !bitmap_bit_p (already, INSN_UID (insn)))
+ {
+ unsigned int j;
+ bitmap_set_bit (already, INSN_UID (insn));
+ /* Only decrement it once for each insn. */
+ for (j = 0; j < web->num_uses; j++)
+ if (web->uses[j]->insn == insn)
+ {
+ num_deaths--;
+ break;
+ }
+ }
+ }
+ /* But mark them specially if they could possibly be spilled,
+ either because they cross some deaths (without the above
+ mentioned ones) or calls. */
+ if (web->crosses_call || num_deaths > 0)
+ web->spill_temp = 1 * 2;
+ }
+ /* A web spanning no deaths can't be spilled either. No loads
+ would be created for it, ergo no defs. So the insns wouldn't
+ change making the graph not easier to color. Make this also
+ a short web. Don't do this if it crosses calls, as these are
+ also points of reloads. */
+ else if (web->span_deaths == 0 && !web->crosses_call)
+ web->spill_temp = 3;
+ }
+ web->orig_spill_temp = web->spill_temp;
+ }
+ BITMAP_XFREE (already);
+}
+
+/* Returns nonzero if the rtx MEM refers somehow to a stack location. */
+
+int
+memref_is_stack_slot (mem)
+ rtx mem;
+{
+ rtx ad = XEXP (mem, 0);
+ rtx x;
+ if (GET_CODE (ad) != PLUS || GET_CODE (XEXP (ad, 1)) != CONST_INT)
+ return 0;
+ x = XEXP (ad, 0);
+ if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
+ || (x == arg_pointer_rtx && fixed_regs[ARG_POINTER_REGNUM])
+ || x == stack_pointer_rtx)
+ return 1;
+ return 0;
+}
+
+/* Returns nonzero, if rtx X somewhere contains any pseudo register. */
+
+static int
+contains_pseudo (x)
+ rtx x;
+{
+ const char *fmt;
+ int i;
+ if (GET_CODE (x) == SUBREG)
+ x = SUBREG_REG (x);
+ if (GET_CODE (x) == REG)
+ {
+ if (REGNO (x) >= FIRST_PSEUDO_REGISTER)
+ return 1;
+ else
+ return 0;
+ }
+
+ fmt = GET_RTX_FORMAT (GET_CODE (x));
+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+ if (fmt[i] == 'e')
+ {
+ if (contains_pseudo (XEXP (x, i)))
+ return 1;
+ }
+ else if (fmt[i] == 'E')
+ {
+ int j;
+ for (j = 0; j < XVECLEN (x, i); j++)
+ if (contains_pseudo (XVECEXP (x, i, j)))
+ return 1;
+ }
+ return 0;
+}
+
+/* Returns nonzero, if we are able to rematerialize something with
+ value X. If it's not a general operand, we test if we can produce
+ a valid insn which set a pseudo to that value, and that insn doesn't
+ clobber anything. */
+
+static GTY(()) rtx remat_test_insn;
+static int
+want_to_remat (x)
+ rtx x;
+{
+ int num_clobbers = 0;
+ int icode;
+
+ /* If this is a valid operand, we are OK. If it's VOIDmode, we aren't. */
+ if (general_operand (x, GET_MODE (x)))
+ return 1;
+
+ /* Otherwise, check if we can make a valid insn from it. First initialize
+ our test insn if we haven't already. */
+ if (remat_test_insn == 0)
+ {
+ remat_test_insn
+ = make_insn_raw (gen_rtx_SET (VOIDmode,
+ gen_rtx_REG (word_mode,
+ FIRST_PSEUDO_REGISTER * 2),
+ const0_rtx));
+ NEXT_INSN (remat_test_insn) = PREV_INSN (remat_test_insn) = 0;
+ }
+
+ /* Now make an insn like the one we would make when rematerializing
+ the value X and see if valid. */
+ PUT_MODE (SET_DEST (PATTERN (remat_test_insn)), GET_MODE (x));
+ SET_SRC (PATTERN (remat_test_insn)) = x;
+ /* XXX For now we don't allow any clobbers to be added, not just no
+ hardreg clobbers. */
+ return ((icode = recog (PATTERN (remat_test_insn), remat_test_insn,
+ &num_clobbers)) >= 0
+ && (num_clobbers == 0
+ /*|| ! added_clobbers_hard_reg_p (icode)*/));
+}
+
+/* Look at all webs, if they perhaps are rematerializable.
+ They are, if all their defs are simple sets to the same value,
+ and that value is simple enough, and want_to_remat() holds for it. */
+
+static void
+detect_remat_webs ()
+{
+ struct dlist *d;
+ for (d = WEBS(INITIAL); d; d = d->next)
+ {
+ struct web *web = DLIST_WEB (d);
+ unsigned int i;
+ rtx pat = NULL_RTX;
+ /* Hardregs and useless webs aren't spilled -> no remat necessary.
+ Defless webs obviously also can't be rematerialized. */
+ if (web->regno < FIRST_PSEUDO_REGISTER || !web->num_defs
+ || !web->num_uses)
+ continue;
+ for (i = 0; i < web->num_defs; i++)
+ {
+ rtx insn;
+ rtx set = single_set (insn = DF_REF_INSN (web->defs[i]));
+ rtx src;
+ if (!set)
+ break;
+ src = SET_SRC (set);
+ /* When only subregs of the web are set it isn't easily
+ rematerializable. */
+ if (!rtx_equal_p (SET_DEST (set), web->orig_x))
+ break;
+ /* If we already have a pattern it must be equal to the current. */
+ if (pat && !rtx_equal_p (pat, src))
+ break;
+ /* Don't do the expensive checks multiple times. */
+ if (pat)
+ continue;
+ /* For now we allow only constant sources. */
+ if ((CONSTANT_P (src)
+ /* If the whole thing is stable already, it is a source for
+ remat, no matter how complicated (probably all needed
+ resources for it are live everywhere, and don't take
+ additional register resources). */
+ /* XXX Currently we can't use patterns which contain
+ pseudos, _even_ if they are stable. The code simply isn't
+ prepared for that. All those operands can't be spilled (or
+ the dependent remat webs are not remat anymore), so they
+ would be oldwebs in the next iteration. But currently
+ oldwebs can't have their references changed. The
+ incremental machinery barfs on that. */
+ || (!rtx_unstable_p (src) && !contains_pseudo (src))
+ /* Additionally also memrefs to stack-slots are usefull, when
+ we created them ourself. They might not have set their
+ unchanging flag set, but nevertheless they are stable across
+ the livetime in question. */
+ || (GET_CODE (src) == MEM
+ && INSN_UID (insn) >= orig_max_uid
+ && memref_is_stack_slot (src)))
+ /* And we must be able to construct an insn without
+ side-effects to actually load that value into a reg. */
+ && want_to_remat (src))
+ pat = src;
+ else
+ break;
+ }
+ if (pat && i == web->num_defs)
+ web->pattern = pat;
+ }
+}
+
+/* Determine the spill costs of all webs. */
+
+static void
+determine_web_costs ()
+{
+ struct dlist *d;
+ for (d = WEBS(INITIAL); d; d = d->next)
+ {
+ unsigned int i, num_loads;
+ int load_cost, store_cost;
+ unsigned HOST_WIDE_INT w;
+ struct web *web = DLIST_WEB (d);
+ if (web->type == PRECOLORED)
+ continue;
+ /* Get costs for one load/store. Note that we offset them by 1,
+ because some patterns have a zero rtx_cost(), but we of course
+ still need the actual load/store insns. With zero all those
+ webs would be the same, no matter how often and where
+ they are used. */
+ if (web->pattern)
+ {
+ /* This web is rematerializable. Beware, we set store_cost to
+ zero optimistically assuming, that we indeed don't emit any
+ stores in the spill-code addition. This might be wrong if
+ at the point of the load not all needed resources are
+ available, in which case we emit a stack-based load, for
+ which we in turn need the according stores. */
+ load_cost = 1 + rtx_cost (web->pattern, 0);
+ store_cost = 0;
+ }
+ else
+ {
+ load_cost = 1 + MEMORY_MOVE_COST (GET_MODE (web->orig_x),
+ web->regclass, 1);
+ store_cost = 1 + MEMORY_MOVE_COST (GET_MODE (web->orig_x),
+ web->regclass, 0);
+ }
+ /* We create only loads at deaths, whose number is in span_deaths. */
+ num_loads = MIN (web->span_deaths, web->num_uses);
+ for (w = 0, i = 0; i < web->num_uses; i++)
+ w += DF_REF_BB (web->uses[i])->frequency + 1;
+ if (num_loads < web->num_uses)
+ w = (w * num_loads + web->num_uses - 1) / web->num_uses;
+ web->spill_cost = w * load_cost;
+ if (store_cost)
+ {
+ for (w = 0, i = 0; i < web->num_defs; i++)
+ w += DF_REF_BB (web->defs[i])->frequency + 1;
+ web->spill_cost += w * store_cost;
+ }
+ web->orig_spill_cost = web->spill_cost;
+ }
+}
+
+/* Detect webs which are set in a conditional jump insn (possibly a
+ decrement-and-branch type of insn), and mark them not to be
+ spillable. The stores for them would need to be placed on edges,
+ which destroys the CFG. (Somewhen we want to deal with that XXX) */
+
+static void
+detect_webs_set_in_cond_jump ()
+{
+ basic_block bb;
+ FOR_EACH_BB (bb)
+ if (GET_CODE (bb->end) == JUMP_INSN)
+ {
+ struct df_link *link;
+ for (link = DF_INSN_DEFS (df, bb->end); link; link = link->next)
+ if (link->ref && DF_REF_REGNO (link->ref) >= FIRST_PSEUDO_REGISTER)
+ {
+ struct web *web = def2web[DF_REF_ID (link->ref)];
+ web->orig_spill_temp = web->spill_temp = 3;
+ }
+ }
+}
+
+/* Second top-level function of this file.
+ Converts the connected web parts to full webs. This means, it allocates
+ all webs, and initializes all fields, including detecting spill
+ temporaries. It does not distribute moves to their corresponding webs,
+ though. */
+
+static void
+make_webs (df)
+ struct df *df;
+{
+ /* First build all the webs itself. They are not related with
+ others yet. */
+ parts_to_webs (df);
+ /* Now detect spill temporaries to initialize their usable_regs set. */
+ detect_spill_temps ();
+ detect_webs_set_in_cond_jump ();
+ /* And finally relate them to each other, meaning to record all possible
+ conflicts between webs (see the comment there). */
+ conflicts_between_webs (df);
+ detect_remat_webs ();
+ determine_web_costs ();
+}
+
+/* Distribute moves to the corresponding webs. */
+
+static void
+moves_to_webs (df)
+ struct df *df;
+{
+ struct df_link *link;
+ struct move_list *ml;
+
+ /* Distribute all moves to their corresponding webs, making sure,
+ each move is in a web maximally one time (happens on some strange
+ insns). */
+ for (ml = wl_moves; ml; ml = ml->next)
+ {
+ struct move *m = ml->move;
+ struct web *web;
+ struct move_list *newml;
+ if (!m)
+ continue;
+ m->type = WORKLIST;
+ m->dlink = NULL;
+ /* Multiple defs/uses can happen in moves involving hard-regs in
+ a wider mode. For those df.* creates use/def references for each
+ real hard-reg involved. For coalescing we are interested in
+ the smallest numbered hard-reg. */
+ for (link = DF_INSN_DEFS (df, m->insn); link; link = link->next)
+ if (link->ref)
+ {
+ web = def2web[DF_REF_ID (link->ref)];
+ web = find_web_for_subweb (web);
+ if (!m->target_web || web->regno < m->target_web->regno)
+ m->target_web = web;
+ }
+ for (link = DF_INSN_USES (df, m->insn); link; link = link->next)
+ if (link->ref)
+ {
+ web = use2web[DF_REF_ID (link->ref)];
+ web = find_web_for_subweb (web);
+ if (!m->source_web || web->regno < m->source_web->regno)
+ m->source_web = web;
+ }
+ if (m->source_web && m->target_web
+ /* If the usable_regs don't intersect we can't coalesce the two
+ webs anyway, as this is no simple copy insn (it might even
+ need an intermediate stack temp to execute this "copy" insn). */
+ && hard_regs_intersect_p (&m->source_web->usable_regs,
+ &m->target_web->usable_regs))
+ {
+ if (!flag_ra_optimistic_coalescing)
+ {
+ struct move_list *test = m->source_web->moves;
+ for (; test && test->move != m; test = test->next);
+ if (! test)
+ {
+ newml = (struct move_list*)
+ ra_alloc (sizeof (struct move_list));
+ newml->move = m;
+ newml->next = m->source_web->moves;
+ m->source_web->moves = newml;
+ }
+ test = m->target_web->moves;
+ for (; test && test->move != m; test = test->next);
+ if (! test)
+ {
+ newml = (struct move_list*)
+ ra_alloc (sizeof (struct move_list));
+ newml->move = m;
+ newml->next = m->target_web->moves;
+ m->target_web->moves = newml;
+ }
+ }
+ }
+ else
+ /* Delete this move. */
+ ml->move = NULL;
+ }
+}
+
+/* Handle tricky asm insns.
+ Supposed to create conflicts to hardregs which aren't allowed in
+ the constraints. Doesn't actually do that, as it might confuse
+ and constrain the allocator too much. */
+
+static void
+handle_asm_insn (df, insn)
+ struct df *df;
+ rtx insn;
+{
+ const char *constraints[MAX_RECOG_OPERANDS];
+ enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
+ int i, noperands, in_output;
+ HARD_REG_SET clobbered, allowed, conflict;
+ rtx pat;
+ if (! INSN_P (insn)
+ || (noperands = asm_noperands (PATTERN (insn))) < 0)
+ return;
+ pat = PATTERN (insn);
+ CLEAR_HARD_REG_SET (clobbered);
+
+ if (GET_CODE (pat) == PARALLEL)
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ {
+ rtx t = XVECEXP (pat, 0, i);
+ if (GET_CODE (t) == CLOBBER && GET_CODE (XEXP (t, 0)) == REG
+ && REGNO (XEXP (t, 0)) < FIRST_PSEUDO_REGISTER)
+ SET_HARD_REG_BIT (clobbered, REGNO (XEXP (t, 0)));
+ }
+
+ decode_asm_operands (pat, recog_data.operand, recog_data.operand_loc,
+ constraints, operand_mode);
+ in_output = 1;
+ for (i = 0; i < noperands; i++)
+ {
+ const char *p = constraints[i];
+ int cls = (int) NO_REGS;
+ struct df_link *link;
+ rtx reg;
+ struct web *web;
+ int nothing_allowed = 1;
+ reg = recog_data.operand[i];
+
+ /* Look, if the constraints apply to a pseudo reg, and not to
+ e.g. a mem. */
+ while (GET_CODE (reg) == SUBREG
+ || GET_CODE (reg) == ZERO_EXTRACT
+ || GET_CODE (reg) == SIGN_EXTRACT
+ || GET_CODE (reg) == STRICT_LOW_PART)
+ reg = XEXP (reg, 0);
+ if (GET_CODE (reg) != REG || REGNO (reg) < FIRST_PSEUDO_REGISTER)
+ continue;
+
+ /* Search the web corresponding to this operand. We depend on
+ that decode_asm_operands() places the output operands
+ before the input operands. */
+ while (1)
+ {
+ if (in_output)
+ link = df->insns[INSN_UID (insn)].defs;
+ else
+ link = df->insns[INSN_UID (insn)].uses;
+ while (link && link->ref && DF_REF_REAL_REG (link->ref) != reg)
+ link = link->next;
+ if (!link || !link->ref)
+ {
+ if (in_output)
+ in_output = 0;
+ else
+ abort ();
+ }
+ else
+ break;
+ }
+ if (in_output)
+ web = def2web[DF_REF_ID (link->ref)];
+ else
+ web = use2web[DF_REF_ID (link->ref)];
+ reg = DF_REF_REG (link->ref);
+
+ /* Find the constraints, noting the allowed hardregs in allowed. */
+ CLEAR_HARD_REG_SET (allowed);
+ while (1)
+ {
+ char c = *p++;
+
+ if (c == '\0' || c == ',' || c == '#')
+ {
+ /* End of one alternative - mark the regs in the current
+ class, and reset the class.
+ */
+ IOR_HARD_REG_SET (allowed, reg_class_contents[cls]);
+ if (cls != NO_REGS)
+ nothing_allowed = 0;
+ cls = NO_REGS;
+ if (c == '#')
+ do {
+ c = *p++;
+ } while (c != '\0' && c != ',');
+ if (c == '\0')
+ break;
+ continue;
+ }
+
+ switch (c)
+ {
+ case '=': case '+': case '*': case '%': case '?': case '!':
+ case '0': case '1': case '2': case '3': case '4': case 'm':
+ case '<': case '>': case 'V': case 'o': case '&': case 'E':
+ case 'F': case 's': case 'i': case 'n': case 'X': case 'I':
+ case 'J': case 'K': case 'L': case 'M': case 'N': case 'O':
+ case 'P':
+ break;
+
+ case 'p':
+ cls = (int) reg_class_subunion[cls][(int) BASE_REG_CLASS];
+ nothing_allowed = 0;
+ break;
+
+ case 'g':
+ case 'r':
+ cls = (int) reg_class_subunion[cls][(int) GENERAL_REGS];
+ nothing_allowed = 0;
+ break;
+
+ default:
+ cls =
+ (int) reg_class_subunion[cls][(int)
+ REG_CLASS_FROM_LETTER (c)];
+ }
+ }
+
+ /* Now make conflicts between this web, and all hardregs, which
+ are not allowed by the constraints. */
+ if (nothing_allowed)
+ {
+ /* If we had no real constraints nothing was explicitely
+ allowed, so we allow the whole class (i.e. we make no
+ additional conflicts). */
+ CLEAR_HARD_REG_SET (conflict);
+ }
+ else
+ {
+ COPY_HARD_REG_SET (conflict, usable_regs
+ [reg_preferred_class (web->regno)]);
+ IOR_HARD_REG_SET (conflict, usable_regs
+ [reg_alternate_class (web->regno)]);
+ AND_COMPL_HARD_REG_SET (conflict, allowed);
+ /* We can't yet establish these conflicts. Reload must go first
+ (or better said, we must implement some functionality of reload).
+ E.g. if some operands must match, and they need the same color
+ we don't see yet, that they do not conflict (because they match).
+ For us it looks like two normal references with different DEFs,
+ so they conflict, and as they both need the same color, the
+ graph becomes uncolorable. */
+#if 0
+ for (c = 0; c < FIRST_PSEUDO_REGISTER; c++)
+ if (TEST_HARD_REG_BIT (conflict, c))
+ record_conflict (web, hardreg2web[c]);
+#endif
+ }
+ if (rtl_dump_file)
+ {
+ int c;
+ ra_debug_msg (DUMP_ASM, " ASM constrain Web %d conflicts with:", web->id);
+ for (c = 0; c < FIRST_PSEUDO_REGISTER; c++)
+ if (TEST_HARD_REG_BIT (conflict, c))
+ ra_debug_msg (DUMP_ASM, " %d", c);
+ ra_debug_msg (DUMP_ASM, "\n");
+ }
+ }
+}
+
+/* The real toplevel function in this file.
+ Build (or rebuilds) the complete interference graph with webs
+ and conflicts. */
+
+void
+build_i_graph (df)
+ struct df *df;
+{
+ rtx insn;
+
+ init_web_parts (df);
+
+ sbitmap_zero (move_handled);
+ wl_moves = NULL;
+
+ build_web_parts_and_conflicts (df);
+
+ /* For read-modify-write instructions we may have created two webs.
+ Reconnect them here. (s.a.) */
+ connect_rmw_web_parts (df);
+
+ /* The webs are conceptually complete now, but still scattered around as
+ connected web parts. Collect all information and build the webs
+ including all conflicts between webs (instead web parts). */
+ make_webs (df);
+ moves_to_webs (df);
+
+ /* Look for additional constraints given by asms. */
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ handle_asm_insn (df, insn);
+}
+
+/* Allocates or reallocates most memory for the interference graph and
+ assiciated structures. If it reallocates memory (meaning, this is not
+ the first pass), this also changes some structures to reflect the
+ additional entries in various array, and the higher number of
+ defs and uses. */
+
+void
+ra_build_realloc (df)
+ struct df *df;
+{
+ struct web_part *last_web_parts = web_parts;
+ struct web **last_def2web = def2web;
+ struct web **last_use2web = use2web;
+ sbitmap last_live_over_abnormal = live_over_abnormal;
+ unsigned int i;
+ struct dlist *d;
+ move_handled = sbitmap_alloc (get_max_uid () );
+ web_parts = (struct web_part *) xcalloc (df->def_id + df->use_id,
+ sizeof web_parts[0]);
+ def2web = (struct web **) xcalloc (df->def_id + df->use_id,
+ sizeof def2web[0]);
+ use2web = &def2web[df->def_id];
+ live_over_abnormal = sbitmap_alloc (df->use_id);
+ sbitmap_zero (live_over_abnormal);
+
+ /* First go through all old defs and uses. */
+ for (i = 0; i < last_def_id + last_use_id; i++)
+ {
+ /* And relocate them to the new array. This is made ugly by the
+ fact, that defs and uses are placed consecutive into one array. */
+ struct web_part *dest = &web_parts[i < last_def_id
+ ? i : (df->def_id + i - last_def_id)];
+ struct web_part *up;
+ *dest = last_web_parts[i];
+ up = dest->uplink;
+ dest->uplink = NULL;
+
+ /* Also relocate the uplink to point into the new array. */
+ if (up && up->ref)
+ {
+ unsigned int id = DF_REF_ID (up->ref);
+ if (up < &last_web_parts[last_def_id])
+ {
+ if (df->defs[id])
+ dest->uplink = &web_parts[DF_REF_ID (up->ref)];
+ }
+ else if (df->uses[id])
+ dest->uplink = &web_parts[df->def_id + DF_REF_ID (up->ref)];
+ }
+ }
+
+ /* Also set up the def2web and use2web arrays, from the last pass.i
+ Remember also the state of live_over_abnormal. */
+ for (i = 0; i < last_def_id; i++)
+ {
+ struct web *web = last_def2web[i];
+ if (web)
+ {
+ web = find_web_for_subweb (web);
+ if (web->type != FREE && web->type != PRECOLORED)
+ def2web[i] = last_def2web[i];
+ }
+ }
+ for (i = 0; i < last_use_id; i++)
+ {
+ struct web *web = last_use2web[i];
+ if (web)
+ {
+ web = find_web_for_subweb (web);
+ if (web->type != FREE && web->type != PRECOLORED)
+ use2web[i] = last_use2web[i];
+ }
+ if (TEST_BIT (last_live_over_abnormal, i))
+ SET_BIT (live_over_abnormal, i);
+ }
+
+ /* We don't have any subwebs for now. Somewhen we might want to
+ remember them too, instead of recreating all of them every time.
+ The problem is, that which subwebs we need, depends also on what
+ other webs and subwebs exist, and which conflicts are there.
+ OTOH it should be no problem, if we had some more subwebs than strictly
+ needed. Later. */
+ for (d = WEBS(FREE); d; d = d->next)
+ {
+ struct web *web = DLIST_WEB (d);
+ struct web *wnext;
+ for (web = web->subreg_next; web; web = wnext)
+ {
+ wnext = web->subreg_next;
+ free (web);
+ }
+ DLIST_WEB (d)->subreg_next = NULL;
+ }
+
+ /* The uses we anyway are going to check, are not yet live over an abnormal
+ edge. In fact, they might actually not anymore, due to added
+ loads. */
+ if (last_check_uses)
+ sbitmap_difference (live_over_abnormal, live_over_abnormal,
+ last_check_uses);
+
+ if (last_def_id || last_use_id)
+ {
+ sbitmap_free (last_live_over_abnormal);
+ free (last_web_parts);
+ free (last_def2web);
+ }
+ if (!last_max_uid)
+ {
+ /* Setup copy cache, for copy_insn_p (). */
+ copy_cache = (struct copy_p_cache *)
+ xcalloc (get_max_uid (), sizeof (copy_cache[0]));
+ init_bb_info ();
+ }
+ else
+ {
+ copy_cache = (struct copy_p_cache *)
+ xrealloc (copy_cache, get_max_uid () * sizeof (copy_cache[0]));
+ memset (&copy_cache[last_max_uid], 0,
+ (get_max_uid () - last_max_uid) * sizeof (copy_cache[0]));
+ }
+}
+
+/* Free up/clear some memory, only needed for one pass. */
+
+void
+ra_build_free ()
+{
+ struct dlist *d;
+ unsigned int i;
+
+ /* Clear the moves associated with a web (we also need to look into
+ subwebs here). */
+ for (i = 0; i < num_webs; i++)
+ {
+ struct web *web = ID2WEB (i);
+ if (!web)
+ abort ();
+ if (i >= num_webs - num_subwebs
+ && (web->conflict_list || web->orig_conflict_list))
+ abort ();
+ web->moves = NULL;
+ }
+ /* All webs in the free list have no defs or uses anymore. */
+ for (d = WEBS(FREE); d; d = d->next)
+ {
+ struct web *web = DLIST_WEB (d);
+ if (web->defs)
+ free (web->defs);
+ web->defs = NULL;
+ if (web->uses)
+ free (web->uses);
+ web->uses = NULL;
+ /* We can't free the subwebs here, as they are referenced from
+ def2web[], and possibly needed in the next ra_build_realloc().
+ We free them there (or in free_all_mem()). */
+ }
+
+ /* Free all conflict bitmaps from web parts. Note that we clear
+ _all_ these conflicts, and don't rebuild them next time for uses
+ which aren't rechecked. This mean, that those conflict bitmaps
+ only contain the incremental information. The cumulative one
+ is still contained in the edges of the I-graph, i.e. in
+ conflict_list (or orig_conflict_list) of the webs. */
+ for (i = 0; i < df->def_id + df->use_id; i++)
+ {
+ struct tagged_conflict *cl;
+ for (cl = web_parts[i].sub_conflicts; cl; cl = cl->next)
+ {
+ if (cl->conflicts)
+ BITMAP_XFREE (cl->conflicts);
+ }
+ web_parts[i].sub_conflicts = NULL;
+ }
+
+ wl_moves = NULL;
+
+ free (id2web);
+ free (move_handled);
+ sbitmap_free (sup_igraph);
+ sbitmap_free (igraph);
+}
+
+/* Free all memory for the interference graph structures. */
+
+void
+ra_build_free_all (df)
+ struct df *df;
+{
+ unsigned int i;
+
+ free_bb_info ();
+ free (copy_cache);
+ copy_cache = NULL;
+ for (i = 0; i < df->def_id + df->use_id; i++)
+ {
+ struct tagged_conflict *cl;
+ for (cl = web_parts[i].sub_conflicts; cl; cl = cl->next)
+ {
+ if (cl->conflicts)
+ BITMAP_XFREE (cl->conflicts);
+ }
+ web_parts[i].sub_conflicts = NULL;
+ }
+ sbitmap_free (live_over_abnormal);
+ free (web_parts);
+ web_parts = NULL;
+ if (last_check_uses)
+ sbitmap_free (last_check_uses);
+ last_check_uses = NULL;
+ free (def2web);
+ use2web = NULL;
+ def2web = NULL;
+}
+
+#include "gt-ra-build.h"
+
+/*
+vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
+*/
diff --git a/contrib/gcc/ra-colorize.c b/contrib/gcc/ra-colorize.c
new file mode 100644
index 0000000..5db6474
--- /dev/null
+++ b/contrib/gcc/ra-colorize.c
@@ -0,0 +1,2742 @@
+/* Graph coloring register allocator
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Contributed by Michael Matz <matz@suse.de>
+ and Daniel Berlin <dan@cgsoftware.com>.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along
+ with GCC; see the file COPYING. If not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "function.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
+#include "df.h"
+#include "output.h"
+#include "ra.h"
+
+/* This file is part of the graph coloring register allocator.
+ It contains the graph colorizer. Given an interference graph
+ as set up in ra-build.c the toplevel function in this file
+ (ra_colorize_graph) colorizes the graph, leaving a list
+ of colored, coalesced and spilled nodes.
+
+ The algorithm used is a merge of George & Appels iterative coalescing
+ and optimistic coalescing, switchable at runtime. The current default
+ is "optimistic coalescing +", which is based on the normal Briggs/Cooper
+ framework. We can also use biased coloring. Most of the structure
+ here follows the different papers.
+
+ Additionally there is a custom step to locally improve the overall
+ spill cost of the colored graph (recolor_spills). */
+
+static void push_list PARAMS ((struct dlist *, struct dlist **));
+static void push_list_end PARAMS ((struct dlist *, struct dlist **));
+static void free_dlist PARAMS ((struct dlist **));
+static void put_web_at_end PARAMS ((struct web *, enum node_type));
+static void put_move PARAMS ((struct move *, enum move_type));
+static void build_worklists PARAMS ((struct df *));
+static void enable_move PARAMS ((struct web *));
+static void decrement_degree PARAMS ((struct web *, int));
+static void simplify PARAMS ((void));
+static void remove_move_1 PARAMS ((struct web *, struct move *));
+static void remove_move PARAMS ((struct web *, struct move *));
+static void add_worklist PARAMS ((struct web *));
+static int ok PARAMS ((struct web *, struct web *));
+static int conservative PARAMS ((struct web *, struct web *));
+static inline unsigned int simplify_p PARAMS ((enum node_type));
+static void combine PARAMS ((struct web *, struct web *));
+static void coalesce PARAMS ((void));
+static void freeze_moves PARAMS ((struct web *));
+static void freeze PARAMS ((void));
+static void select_spill PARAMS ((void));
+static int color_usable_p PARAMS ((int, HARD_REG_SET, HARD_REG_SET,
+ enum machine_mode));
+int get_free_reg PARAMS ((HARD_REG_SET, HARD_REG_SET, enum machine_mode));
+static int get_biased_reg PARAMS ((HARD_REG_SET, HARD_REG_SET, HARD_REG_SET,
+ HARD_REG_SET, enum machine_mode));
+static int count_long_blocks PARAMS ((HARD_REG_SET, int));
+static char * hardregset_to_string PARAMS ((HARD_REG_SET));
+static void calculate_dont_begin PARAMS ((struct web *, HARD_REG_SET *));
+static void colorize_one_web PARAMS ((struct web *, int));
+static void assign_colors PARAMS ((void));
+static void try_recolor_web PARAMS ((struct web *));
+static void insert_coalesced_conflicts PARAMS ((void));
+static int comp_webs_maxcost PARAMS ((const void *, const void *));
+static void recolor_spills PARAMS ((void));
+static void check_colors PARAMS ((void));
+static void restore_conflicts_from_coalesce PARAMS ((struct web *));
+static void break_coalesced_spills PARAMS ((void));
+static void unalias_web PARAMS ((struct web *));
+static void break_aliases_to_web PARAMS ((struct web *));
+static void break_precolored_alias PARAMS ((struct web *));
+static void init_web_pairs PARAMS ((void));
+static void add_web_pair_cost PARAMS ((struct web *, struct web *,
+ unsigned HOST_WIDE_INT, unsigned int));
+static int comp_web_pairs PARAMS ((const void *, const void *));
+static void sort_and_combine_web_pairs PARAMS ((int));
+static void aggressive_coalesce PARAMS ((void));
+static void extended_coalesce_2 PARAMS ((void));
+static void check_uncoalesced_moves PARAMS ((void));
+
+static struct dlist *mv_worklist, *mv_coalesced, *mv_constrained;
+static struct dlist *mv_frozen, *mv_active;
+
+/* Push a node onto the front of the list. */
+
+static void
+push_list (x, list)
+ struct dlist *x;
+ struct dlist **list;
+{
+ if (x->next || x->prev)
+ abort ();
+ x->next = *list;
+ if (*list)
+ (*list)->prev = x;
+ *list = x;
+}
+
+static void
+push_list_end (x, list)
+ struct dlist *x;
+ struct dlist **list;
+{
+ if (x->prev || x->next)
+ abort ();
+ if (!*list)
+ {
+ *list = x;
+ return;
+ }
+ while ((*list)->next)
+ list = &((*list)->next);
+ x->prev = *list;
+ (*list)->next = x;
+}
+
+/* Remove a node from the list. */
+
+void
+remove_list (x, list)
+ struct dlist *x;
+ struct dlist **list;
+{
+ struct dlist *y = x->prev;
+ if (y)
+ y->next = x->next;
+ else
+ *list = x->next;
+ y = x->next;
+ if (y)
+ y->prev = x->prev;
+ x->next = x->prev = NULL;
+}
+
+/* Pop the front of the list. */
+
+struct dlist *
+pop_list (list)
+ struct dlist **list;
+{
+ struct dlist *r = *list;
+ if (r)
+ remove_list (r, list);
+ return r;
+}
+
+/* Free the given double linked list. */
+
+static void
+free_dlist (list)
+ struct dlist **list;
+{
+ *list = NULL;
+}
+
+/* The web WEB should get the given new TYPE. Put it onto the
+ appropriate list.
+ Inline, because it's called with constant TYPE every time. */
+
+inline void
+put_web (web, type)
+ struct web *web;
+ enum node_type type;
+{
+ switch (type)
+ {
+ case INITIAL:
+ case FREE:
+ case FREEZE:
+ case SPILL:
+ case SPILLED:
+ case COALESCED:
+ case COLORED:
+ case SELECT:
+ push_list (web->dlink, &WEBS(type));
+ break;
+ case PRECOLORED:
+ push_list (web->dlink, &WEBS(INITIAL));
+ break;
+ case SIMPLIFY:
+ if (web->spill_temp)
+ push_list (web->dlink, &WEBS(type = SIMPLIFY_SPILL));
+ else if (web->add_hardregs)
+ push_list (web->dlink, &WEBS(type = SIMPLIFY_FAT));
+ else
+ push_list (web->dlink, &WEBS(SIMPLIFY));
+ break;
+ default:
+ abort ();
+ }
+ web->type = type;
+}
+
+/* After we are done with the whole pass of coloring/spilling,
+ we reset the lists of webs, in preparation of the next pass.
+ The spilled webs become free, colored webs go to the initial list,
+ coalesced webs become free or initial, according to what type of web
+ they are coalesced to. */
+
+void
+reset_lists ()
+{
+ struct dlist *d;
+ unsigned int i;
+ if (WEBS(SIMPLIFY) || WEBS(SIMPLIFY_SPILL) || WEBS(SIMPLIFY_FAT)
+ || WEBS(FREEZE) || WEBS(SPILL) || WEBS(SELECT))
+ abort ();
+
+ while ((d = pop_list (&WEBS(COALESCED))) != NULL)
+ {
+ struct web *web = DLIST_WEB (d);
+ struct web *aweb = alias (web);
+ /* Note, how alias() becomes invalid through the two put_web()'s
+ below. It might set the type of a web to FREE (from COALESCED),
+ which itself is a target of aliasing (i.e. in the middle of
+ an alias chain). We can handle this by checking also for
+ type == FREE. Note nevertheless, that alias() is invalid
+ henceforth. */
+ if (aweb->type == SPILLED || aweb->type == FREE)
+ put_web (web, FREE);
+ else
+ put_web (web, INITIAL);
+ }
+ while ((d = pop_list (&WEBS(SPILLED))) != NULL)
+ put_web (DLIST_WEB (d), FREE);
+ while ((d = pop_list (&WEBS(COLORED))) != NULL)
+ put_web (DLIST_WEB (d), INITIAL);
+
+ /* All free webs have no conflicts anymore. */
+ for (d = WEBS(FREE); d; d = d->next)
+ {
+ struct web *web = DLIST_WEB (d);
+ BITMAP_XFREE (web->useless_conflicts);
+ web->useless_conflicts = NULL;
+ }
+
+ /* Sanity check, that we only have free, initial or precolored webs. */
+ for (i = 0; i < num_webs; i++)
+ {
+ struct web *web = ID2WEB (i);
+ if (web->type != INITIAL && web->type != FREE && web->type != PRECOLORED)
+ abort ();
+ }
+ free_dlist (&mv_worklist);
+ free_dlist (&mv_coalesced);
+ free_dlist (&mv_constrained);
+ free_dlist (&mv_frozen);
+ free_dlist (&mv_active);
+}
+
+/* Similar to put_web(), but add the web to the end of the appropriate
+ list. Additionally TYPE may not be SIMPLIFY. */
+
+static void
+put_web_at_end (web, type)
+ struct web *web;
+ enum node_type type;
+{
+ if (type == PRECOLORED)
+ type = INITIAL;
+ else if (type == SIMPLIFY)
+ abort ();
+ push_list_end (web->dlink, &WEBS(type));
+ web->type = type;
+}
+
+/* Unlink WEB from the list it's currently on (which corresponds to
+ its current type). */
+
+void
+remove_web_from_list (web)
+ struct web *web;
+{
+ if (web->type == PRECOLORED)
+ remove_list (web->dlink, &WEBS(INITIAL));
+ else
+ remove_list (web->dlink, &WEBS(web->type));
+}
+
+/* Give MOVE the TYPE, and link it into the correct list. */
+
+static inline void
+put_move (move, type)
+ struct move *move;
+ enum move_type type;
+{
+ switch (type)
+ {
+ case WORKLIST:
+ push_list (move->dlink, &mv_worklist);
+ break;
+ case MV_COALESCED:
+ push_list (move->dlink, &mv_coalesced);
+ break;
+ case CONSTRAINED:
+ push_list (move->dlink, &mv_constrained);
+ break;
+ case FROZEN:
+ push_list (move->dlink, &mv_frozen);
+ break;
+ case ACTIVE:
+ push_list (move->dlink, &mv_active);
+ break;
+ default:
+ abort ();
+ }
+ move->type = type;
+}
+
+/* Build the worklists we are going to process. */
+
+static void
+build_worklists (df)
+ struct df *df ATTRIBUTE_UNUSED;
+{
+ struct dlist *d, *d_next;
+ struct move_list *ml;
+
+ /* If we are not the first pass, put all stackwebs (which are still
+ backed by a new pseudo, but conceptually can stand for a stackslot,
+ i.e. it doesn't really matter if they get a color or not), on
+ the SELECT stack first, those with lowest cost first. This way
+ they will be colored last, so do not contrain the coloring of the
+ normal webs. But still those with the highest count are colored
+ before, i.e. get a color more probable. The use of stackregs is
+ a pure optimization, and all would work, if we used real stackslots
+ from the begin. */
+ if (ra_pass > 1)
+ {
+ unsigned int i, num, max_num;
+ struct web **order2web;
+ max_num = num_webs - num_subwebs;
+ order2web = (struct web **) xmalloc (max_num * sizeof (order2web[0]));
+ for (i = 0, num = 0; i < max_num; i++)
+ if (id2web[i]->regno >= max_normal_pseudo)
+ order2web[num++] = id2web[i];
+ if (num)
+ {
+ qsort (order2web, num, sizeof (order2web[0]), comp_webs_maxcost);
+ for (i = num - 1;; i--)
+ {
+ struct web *web = order2web[i];
+ struct conflict_link *wl;
+ remove_list (web->dlink, &WEBS(INITIAL));
+ put_web (web, SELECT);
+ for (wl = web->conflict_list; wl; wl = wl->next)
+ {
+ struct web *pweb = wl->t;
+ pweb->num_conflicts -= 1 + web->add_hardregs;
+ }
+ if (i == 0)
+ break;
+ }
+ }
+ free (order2web);
+ }
+
+ /* For all remaining initial webs, classify them. */
+ for (d = WEBS(INITIAL); d; d = d_next)
+ {
+ struct web *web = DLIST_WEB (d);
+ d_next = d->next;
+ if (web->type == PRECOLORED)
+ continue;
+
+ remove_list (d, &WEBS(INITIAL));
+ if (web->num_conflicts >= NUM_REGS (web))
+ put_web (web, SPILL);
+ else if (web->moves)
+ put_web (web, FREEZE);
+ else
+ put_web (web, SIMPLIFY);
+ }
+
+ /* And put all moves on the worklist for iterated coalescing.
+ Note, that if iterated coalescing is off, then wl_moves doesn't
+ contain any moves. */
+ for (ml = wl_moves; ml; ml = ml->next)
+ if (ml->move)
+ {
+ struct move *m = ml->move;
+ d = (struct dlist *) ra_calloc (sizeof (struct dlist));
+ DLIST_MOVE (d) = m;
+ m->dlink = d;
+ put_move (m, WORKLIST);
+ }
+}
+
+/* Enable the active moves, in which WEB takes part, to be processed. */
+
+static void
+enable_move (web)
+ struct web *web;
+{
+ struct move_list *ml;
+ for (ml = web->moves; ml; ml = ml->next)
+ if (ml->move->type == ACTIVE)
+ {
+ remove_list (ml->move->dlink, &mv_active);
+ put_move (ml->move, WORKLIST);
+ }
+}
+
+/* Decrement the degree of node WEB by the amount DEC.
+ Possibly change the type of WEB, if the number of conflicts is
+ now smaller than its freedom. */
+
+static void
+decrement_degree (web, dec)
+ struct web *web;
+ int dec;
+{
+ int before = web->num_conflicts;
+ web->num_conflicts -= dec;
+ if (web->num_conflicts < NUM_REGS (web) && before >= NUM_REGS (web))
+ {
+ struct conflict_link *a;
+ enable_move (web);
+ for (a = web->conflict_list; a; a = a->next)
+ {
+ struct web *aweb = a->t;
+ if (aweb->type != SELECT && aweb->type != COALESCED)
+ enable_move (aweb);
+ }
+ if (web->type != FREEZE)
+ {
+ remove_web_from_list (web);
+ if (web->moves)
+ put_web (web, FREEZE);
+ else
+ put_web (web, SIMPLIFY);
+ }
+ }
+}
+
+/* Repeatedly simplify the nodes on the simplify worklists. */
+
+static void
+simplify ()
+{
+ struct dlist *d;
+ struct web *web;
+ struct conflict_link *wl;
+ while (1)
+ {
+ /* We try hard to color all the webs resulting from spills first.
+ Without that on register starved machines (x86 e.g) with some live
+ DImode pseudos, -fPIC, and an asm requiring %edx, it might be, that
+ we do rounds over rounds, because the conflict graph says, we can
+ simplify those short webs, but later due to irregularities we can't
+ color those pseudos. So we have to spill them, which in later rounds
+ leads to other spills. */
+ d = pop_list (&WEBS(SIMPLIFY));
+ if (!d)
+ d = pop_list (&WEBS(SIMPLIFY_FAT));
+ if (!d)
+ d = pop_list (&WEBS(SIMPLIFY_SPILL));
+ if (!d)
+ break;
+ web = DLIST_WEB (d);
+ ra_debug_msg (DUMP_PROCESS, " simplifying web %3d, conflicts = %d\n",
+ web->id, web->num_conflicts);
+ put_web (web, SELECT);
+ for (wl = web->conflict_list; wl; wl = wl->next)
+ {
+ struct web *pweb = wl->t;
+ if (pweb->type != SELECT && pweb->type != COALESCED)
+ {
+ decrement_degree (pweb, 1 + web->add_hardregs);
+ }
+ }
+ }
+}
+
+/* Helper function to remove a move from the movelist of the web. */
+
+static void
+remove_move_1 (web, move)
+ struct web *web;
+ struct move *move;
+{
+ struct move_list *ml = web->moves;
+ if (!ml)
+ return;
+ if (ml->move == move)
+ {
+ web->moves = ml->next;
+ return;
+ }
+ for (; ml->next && ml->next->move != move; ml = ml->next) ;
+ if (!ml->next)
+ return;
+ ml->next = ml->next->next;
+}
+
+/* Remove a move from the movelist of the web. Actually this is just a
+ wrapper around remove_move_1(), making sure, the removed move really is
+ not in the list anymore. */
+
+static void
+remove_move (web, move)
+ struct web *web;
+ struct move *move;
+{
+ struct move_list *ml;
+ remove_move_1 (web, move);
+ for (ml = web->moves; ml; ml = ml->next)
+ if (ml->move == move)
+ abort ();
+}
+
+/* Merge the moves for the two webs into the first web's movelist. */
+
+void
+merge_moves (u, v)
+ struct web *u, *v;
+{
+ regset seen;
+ struct move_list *ml, *ml_next;
+
+ seen = BITMAP_XMALLOC ();
+ for (ml = u->moves; ml; ml = ml->next)
+ bitmap_set_bit (seen, INSN_UID (ml->move->insn));
+ for (ml = v->moves; ml; ml = ml_next)
+ {
+ ml_next = ml->next;
+ if (! bitmap_bit_p (seen, INSN_UID (ml->move->insn)))
+ {
+ ml->next = u->moves;
+ u->moves = ml;
+ }
+ }
+ BITMAP_XFREE (seen);
+ v->moves = NULL;
+}
+
+/* Add a web to the simplify worklist, from the freeze worklist. */
+
+static void
+add_worklist (web)
+ struct web *web;
+{
+ if (web->type != PRECOLORED && !web->moves
+ && web->num_conflicts < NUM_REGS (web))
+ {
+ remove_list (web->dlink, &WEBS(FREEZE));
+ put_web (web, SIMPLIFY);
+ }
+}
+
+/* Precolored node coalescing heuristic. */
+
+static int
+ok (target, source)
+ struct web *target, *source;
+{
+ struct conflict_link *wl;
+ int i;
+ int color = source->color;
+ int size;
+
+ /* Normally one would think, the next test wouldn't be needed.
+ We try to coalesce S and T, and S has already a color, and we checked
+ when processing the insns, that both have the same mode. So naively
+ we could conclude, that of course that mode was valid for this color.
+ Hah. But there is sparc. Before reload there are copy insns
+ (e.g. the ones copying arguments to locals) which happily refer to
+ colors in invalid modes. We can't coalesce those things. */
+ if (! HARD_REGNO_MODE_OK (source->color, GET_MODE (target->orig_x)))
+ return 0;
+
+ /* Sanity for funny modes. */
+ size = HARD_REGNO_NREGS (color, GET_MODE (target->orig_x));
+ if (!size)
+ return 0;
+
+ /* We can't coalesce target with a precolored register which isn't in
+ usable_regs. */
+ for (i = size; i--;)
+ if (TEST_HARD_REG_BIT (never_use_colors, color + i)
+ || !TEST_HARD_REG_BIT (target->usable_regs, color + i)
+ /* Before usually calling ok() at all, we already test, if the
+ candidates conflict in sup_igraph. But when wide webs are
+ coalesced to hardregs, we only test the hardweb coalesced into.
+ This is only the begin color. When actually coalescing both,
+ it will also take the following size colors, i.e. their webs.
+ We nowhere checked if the candidate possibly conflicts with
+ one of _those_, which is possible with partial conflicts,
+ so we simply do it here (this does one bit-test more than
+ necessary, the first color). Note, that if X is precolored
+ bit [X*num_webs + Y] can't be set (see add_conflict_edge()). */
+ || TEST_BIT (sup_igraph,
+ target->id * num_webs + hardreg2web[color + i]->id))
+ return 0;
+
+ for (wl = target->conflict_list; wl; wl = wl->next)
+ {
+ struct web *pweb = wl->t;
+ if (pweb->type == SELECT || pweb->type == COALESCED)
+ continue;
+
+ /* Coalescing target (T) and source (S) is o.k, if for
+ all conflicts C of T it is true, that:
+ 1) C will be colored, or
+ 2) C is a hardreg (precolored), or
+ 3) C already conflicts with S too, or
+ 4) a web which contains C conflicts already with S.
+ XXX: we handle here only the special case of 4), that C is
+ a subreg, and the containing thing is the reg itself, i.e.
+ we dont handle the situation, were T conflicts with
+ (subreg:SI x 1), and S conflicts with (subreg:DI x 0), which
+ would be allowed also, as the S-conflict overlaps
+ the T-conflict.
+ So, we first test the whole web for any of these conditions, and
+ continue with the next C, if 1, 2 or 3 is true. */
+ if (pweb->num_conflicts < NUM_REGS (pweb)
+ || pweb->type == PRECOLORED
+ || TEST_BIT (igraph, igraph_index (source->id, pweb->id)) )
+ continue;
+
+ /* This is reached, if not one of 1, 2 or 3 was true. In the case C has
+ no subwebs, 4 can't be true either, so we can't coalesce S and T. */
+ if (wl->sub == NULL)
+ return 0;
+ else
+ {
+ /* The main webs do _not_ conflict, only some parts of both. This
+ means, that 4 is possibly true, so we need to check this too.
+ For this we go thru all sub conflicts between T and C, and see if
+ the target part of C already conflicts with S. When this is not
+ the case we disallow coalescing. */
+ struct sub_conflict *sl;
+ for (sl = wl->sub; sl; sl = sl->next)
+ {
+ if (!TEST_BIT (igraph, igraph_index (source->id, sl->t->id)))
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+/* Non-precolored node coalescing heuristic. */
+
+static int
+conservative (target, source)
+ struct web *target, *source;
+{
+ unsigned int k;
+ unsigned int loop;
+ regset seen;
+ struct conflict_link *wl;
+ unsigned int num_regs = NUM_REGS (target); /* XXX */
+
+ /* k counts the resulting conflict weight, if target and source
+ would be merged, and all low-degree neighbors would be
+ removed. */
+ k = 0 * MAX (target->add_hardregs, source->add_hardregs);
+ seen = BITMAP_XMALLOC ();
+ for (loop = 0; loop < 2; loop++)
+ for (wl = ((loop == 0) ? target : source)->conflict_list;
+ wl; wl = wl->next)
+ {
+ struct web *pweb = wl->t;
+ if (pweb->type != SELECT && pweb->type != COALESCED
+ && pweb->num_conflicts >= NUM_REGS (pweb)
+ && ! REGNO_REG_SET_P (seen, pweb->id))
+ {
+ SET_REGNO_REG_SET (seen, pweb->id);
+ k += 1 + pweb->add_hardregs;
+ }
+ }
+ BITMAP_XFREE (seen);
+
+ if (k >= num_regs)
+ return 0;
+ return 1;
+}
+
+/* If the web is coalesced, return it's alias. Otherwise, return what
+ was passed in. */
+
+struct web *
+alias (web)
+ struct web *web;
+{
+ while (web->type == COALESCED)
+ web = web->alias;
+ return web;
+}
+
+/* Returns nonzero, if the TYPE belongs to one of those representing
+ SIMPLIFY types. */
+
+static inline unsigned int
+simplify_p (type)
+ enum node_type type;
+{
+ return type == SIMPLIFY || type == SIMPLIFY_SPILL || type == SIMPLIFY_FAT;
+}
+
+/* Actually combine two webs, that can be coalesced. */
+
+static void
+combine (u, v)
+ struct web *u, *v;
+{
+ int i;
+ struct conflict_link *wl;
+ if (u == v || v->type == COALESCED)
+ abort ();
+ if ((u->regno >= max_normal_pseudo) != (v->regno >= max_normal_pseudo))
+ abort ();
+ remove_web_from_list (v);
+ put_web (v, COALESCED);
+ v->alias = u;
+ u->is_coalesced = 1;
+ v->is_coalesced = 1;
+ u->num_aliased += 1 + v->num_aliased;
+ if (flag_ra_merge_spill_costs && u->type != PRECOLORED)
+ u->spill_cost += v->spill_cost;
+ /*u->spill_cost = MAX (u->spill_cost, v->spill_cost);*/
+ merge_moves (u, v);
+ /* combine add_hardregs's of U and V. */
+
+ for (wl = v->conflict_list; wl; wl = wl->next)
+ {
+ struct web *pweb = wl->t;
+ /* We don't strictly need to move conflicts between webs which are
+ already coalesced or selected, if we do iterated coalescing, or
+ better if we need not to be able to break aliases again.
+ I.e. normally we would use the condition
+ (pweb->type != SELECT && pweb->type != COALESCED).
+ But for now we simply merge all conflicts. It doesn't take that
+ much time. */
+ if (1)
+ {
+ struct web *web = u;
+ int nregs = 1 + v->add_hardregs;
+ if (u->type == PRECOLORED)
+ nregs = HARD_REGNO_NREGS (u->color, GET_MODE (v->orig_x));
+
+ /* For precolored U's we need to make conflicts between V's
+ neighbors and as many hardregs from U as V needed if it gets
+ color U. For now we approximate this by V->add_hardregs, which
+ could be too much in multi-length classes. We should really
+ count how many hardregs are needed for V with color U. When U
+ isn't precolored this loop breaks out after one iteration. */
+ for (i = 0; i < nregs; i++)
+ {
+ if (u->type == PRECOLORED)
+ web = hardreg2web[i + u->color];
+ if (wl->sub == NULL)
+ record_conflict (web, pweb);
+ else
+ {
+ struct sub_conflict *sl;
+ /* So, between V and PWEB there are sub_conflicts. We
+ need to relocate those conflicts to be between WEB (==
+ U when it wasn't precolored) and PWEB. In the case
+ only a part of V conflicted with (part of) PWEB we
+ nevertheless make the new conflict between the whole U
+ and the (part of) PWEB. Later we might try to find in
+ U the correct subpart corresponding (by size and
+ offset) to the part of V (sl->s) which was the source
+ of the conflict. */
+ for (sl = wl->sub; sl; sl = sl->next)
+ {
+ /* Beware: sl->s is no subweb of web (== U) but of V.
+ We try to search a corresponding subpart of U.
+ If we found none we let it conflict with the whole U.
+ Note that find_subweb() only looks for mode and
+ subreg_byte of the REG rtx but not for the pseudo
+ reg number (otherwise it would be guaranteed to
+ _not_ find any subpart). */
+ struct web *sweb = NULL;
+ if (SUBWEB_P (sl->s))
+ sweb = find_subweb (web, sl->s->orig_x);
+ if (!sweb)
+ sweb = web;
+ record_conflict (sweb, sl->t);
+ }
+ }
+ if (u->type != PRECOLORED)
+ break;
+ }
+ if (pweb->type != SELECT && pweb->type != COALESCED)
+ decrement_degree (pweb, 1 + v->add_hardregs);
+ }
+ }
+
+ /* Now merge the usable_regs together. */
+ /* XXX That merging might normally make it necessary to
+ adjust add_hardregs, which also means to adjust neighbors. This can
+ result in making some more webs trivially colorable, (or the opposite,
+ if this increases our add_hardregs). Because we intersect the
+ usable_regs it should only be possible to decrease add_hardregs. So a
+ conservative solution for now is to simply don't change it. */
+ u->use_my_regs = 1;
+ AND_HARD_REG_SET (u->usable_regs, v->usable_regs);
+ u->regclass = reg_class_subunion[u->regclass][v->regclass];
+ /* Count number of possible hardregs. This might make U a spillweb,
+ but that could also happen, if U and V together had too many
+ conflicts. */
+ u->num_freedom = hard_regs_count (u->usable_regs);
+ u->num_freedom -= u->add_hardregs;
+ /* The next would mean an invalid coalesced move (both webs have no
+ possible hardreg in common), so abort. */
+ if (!u->num_freedom)
+ abort();
+
+ if (u->num_conflicts >= NUM_REGS (u)
+ && (u->type == FREEZE || simplify_p (u->type)))
+ {
+ remove_web_from_list (u);
+ put_web (u, SPILL);
+ }
+
+ /* We want the most relaxed combination of spill_temp state.
+ I.e. if any was no spilltemp or a spilltemp2, the result is so too,
+ otherwise if any is short, the result is too. It remains, when both
+ are normal spilltemps. */
+ if (v->spill_temp == 0)
+ u->spill_temp = 0;
+ else if (v->spill_temp == 2 && u->spill_temp != 0)
+ u->spill_temp = 2;
+ else if (v->spill_temp == 3 && u->spill_temp == 1)
+ u->spill_temp = 3;
+}
+
+/* Attempt to coalesce the first thing on the move worklist.
+ This is used only for iterated coalescing. */
+
+static void
+coalesce ()
+{
+ struct dlist *d = pop_list (&mv_worklist);
+ struct move *m = DLIST_MOVE (d);
+ struct web *source = alias (m->source_web);
+ struct web *target = alias (m->target_web);
+
+ if (target->type == PRECOLORED)
+ {
+ struct web *h = source;
+ source = target;
+ target = h;
+ }
+ if (source == target)
+ {
+ remove_move (source, m);
+ put_move (m, MV_COALESCED);
+ add_worklist (source);
+ }
+ else if (target->type == PRECOLORED
+ || TEST_BIT (sup_igraph, source->id * num_webs + target->id)
+ || TEST_BIT (sup_igraph, target->id * num_webs + source->id))
+ {
+ remove_move (source, m);
+ remove_move (target, m);
+ put_move (m, CONSTRAINED);
+ add_worklist (source);
+ add_worklist (target);
+ }
+ else if ((source->type == PRECOLORED && ok (target, source))
+ || (source->type != PRECOLORED
+ && conservative (target, source)))
+ {
+ remove_move (source, m);
+ remove_move (target, m);
+ put_move (m, MV_COALESCED);
+ combine (source, target);
+ add_worklist (source);
+ }
+ else
+ put_move (m, ACTIVE);
+}
+
+/* Freeze the moves associated with the web. Used for iterated coalescing. */
+
+static void
+freeze_moves (web)
+ struct web *web;
+{
+ struct move_list *ml, *ml_next;
+ for (ml = web->moves; ml; ml = ml_next)
+ {
+ struct move *m = ml->move;
+ struct web *src, *dest;
+ ml_next = ml->next;
+ if (m->type == ACTIVE)
+ remove_list (m->dlink, &mv_active);
+ else
+ remove_list (m->dlink, &mv_worklist);
+ put_move (m, FROZEN);
+ remove_move (web, m);
+ src = alias (m->source_web);
+ dest = alias (m->target_web);
+ src = (src == web) ? dest : src;
+ remove_move (src, m);
+ /* XXX GA use the original v, instead of alias(v) */
+ if (!src->moves && src->num_conflicts < NUM_REGS (src))
+ {
+ remove_list (src->dlink, &WEBS(FREEZE));
+ put_web (src, SIMPLIFY);
+ }
+ }
+}
+
+/* Freeze the first thing on the freeze worklist (only for iterated
+ coalescing). */
+
+static void
+freeze ()
+{
+ struct dlist *d = pop_list (&WEBS(FREEZE));
+ put_web (DLIST_WEB (d), SIMPLIFY);
+ freeze_moves (DLIST_WEB (d));
+}
+
+/* The current spill heuristic. Returns a number for a WEB.
+ Webs with higher numbers are selected later. */
+
+static unsigned HOST_WIDE_INT (*spill_heuristic) PARAMS ((struct web *));
+
+static unsigned HOST_WIDE_INT default_spill_heuristic PARAMS ((struct web *));
+
+/* Our default heuristic is similar to spill_cost / num_conflicts.
+ Just scaled for integer arithmetic, and it favors coalesced webs,
+ and webs which span more insns with deaths. */
+
+static unsigned HOST_WIDE_INT
+default_spill_heuristic (web)
+ struct web *web;
+{
+ unsigned HOST_WIDE_INT ret;
+ unsigned int divisor = 1;
+ /* Make coalesce targets cheaper to spill, because they will be broken
+ up again into smaller parts. */
+ if (flag_ra_break_aliases)
+ divisor += web->num_aliased;
+ divisor += web->num_conflicts;
+ ret = ((web->spill_cost << 8) + divisor - 1) / divisor;
+ /* It is better to spill webs that span more insns (deaths in our
+ case) than other webs with the otherwise same spill_cost. So make
+ them a little bit cheaper. Remember that spill_cost is unsigned. */
+ if (web->span_deaths < ret)
+ ret -= web->span_deaths;
+ return ret;
+}
+
+/* Select the cheapest spill to be potentially spilled (we don't
+ *actually* spill until we need to). */
+
+static void
+select_spill ()
+{
+ unsigned HOST_WIDE_INT best = (unsigned HOST_WIDE_INT) -1;
+ struct dlist *bestd = NULL;
+ unsigned HOST_WIDE_INT best2 = (unsigned HOST_WIDE_INT) -1;
+ struct dlist *bestd2 = NULL;
+ struct dlist *d;
+ for (d = WEBS(SPILL); d; d = d->next)
+ {
+ struct web *w = DLIST_WEB (d);
+ unsigned HOST_WIDE_INT cost = spill_heuristic (w);
+ if ((!w->spill_temp) && cost < best)
+ {
+ best = cost;
+ bestd = d;
+ }
+ /* Specially marked spill temps can be spilled. Also coalesce
+ targets can. Eventually they will be broken up later in the
+ colorizing process, so if we have nothing better take that. */
+ else if ((w->spill_temp == 2 || w->is_coalesced) && cost < best2)
+ {
+ best2 = cost;
+ bestd2 = d;
+ }
+ }
+ if (!bestd)
+ {
+ bestd = bestd2;
+ best = best2;
+ }
+ if (!bestd)
+ abort ();
+
+ /* Note the potential spill. */
+ DLIST_WEB (bestd)->was_spilled = 1;
+ remove_list (bestd, &WEBS(SPILL));
+ put_web (DLIST_WEB (bestd), SIMPLIFY);
+ freeze_moves (DLIST_WEB (bestd));
+ ra_debug_msg (DUMP_PROCESS, " potential spill web %3d, conflicts = %d\n",
+ DLIST_WEB (bestd)->id, DLIST_WEB (bestd)->num_conflicts);
+}
+
+/* Given a set of forbidden colors to begin at, and a set of still
+ free colors, and MODE, returns nonzero of color C is still usable. */
+
+static int
+color_usable_p (c, dont_begin_colors, free_colors, mode)
+ int c;
+ HARD_REG_SET dont_begin_colors, free_colors;
+ enum machine_mode mode;
+{
+ if (!TEST_HARD_REG_BIT (dont_begin_colors, c)
+ && TEST_HARD_REG_BIT (free_colors, c)
+ && HARD_REGNO_MODE_OK (c, mode))
+ {
+ int i, size;
+ size = HARD_REGNO_NREGS (c, mode);
+ for (i = 1; i < size && TEST_HARD_REG_BIT (free_colors, c + i); i++);
+ if (i == size)
+ return 1;
+ }
+ return 0;
+}
+
+/* I don't want to clutter up the actual code with ifdef's. */
+#ifdef REG_ALLOC_ORDER
+#define INV_REG_ALLOC_ORDER(c) inv_reg_alloc_order[c]
+#else
+#define INV_REG_ALLOC_ORDER(c) c
+#endif
+
+/* Searches in FREE_COLORS for a block of hardregs of the right length
+ for MODE, which doesn't begin at a hardreg mentioned in DONT_BEGIN_COLORS.
+ If it needs more than one hardreg it prefers blocks beginning
+ at an even hardreg, and only gives an odd begin reg if no other
+ block could be found. */
+
+int
+get_free_reg (dont_begin_colors, free_colors, mode)
+ HARD_REG_SET dont_begin_colors, free_colors;
+ enum machine_mode mode;
+{
+ int c;
+ int last_resort_reg = -1;
+ int pref_reg = -1;
+ int pref_reg_order = INT_MAX;
+ int last_resort_reg_order = INT_MAX;
+
+ for (c = 0; c < FIRST_PSEUDO_REGISTER; c++)
+ if (!TEST_HARD_REG_BIT (dont_begin_colors, c)
+ && TEST_HARD_REG_BIT (free_colors, c)
+ && HARD_REGNO_MODE_OK (c, mode))
+ {
+ int i, size;
+ size = HARD_REGNO_NREGS (c, mode);
+ for (i = 1; i < size && TEST_HARD_REG_BIT (free_colors, c + i); i++);
+ if (i != size)
+ {
+ c += i;
+ continue;
+ }
+ if (i == size)
+ {
+ if (size < 2 || (c & 1) == 0)
+ {
+ if (INV_REG_ALLOC_ORDER (c) < pref_reg_order)
+ {
+ pref_reg = c;
+ pref_reg_order = INV_REG_ALLOC_ORDER (c);
+ }
+ }
+ else if (INV_REG_ALLOC_ORDER (c) < last_resort_reg_order)
+ {
+ last_resort_reg = c;
+ last_resort_reg_order = INV_REG_ALLOC_ORDER (c);
+ }
+ }
+ else
+ c += i;
+ }
+ return pref_reg >= 0 ? pref_reg : last_resort_reg;
+}
+
+/* Similar to get_free_reg(), but first search in colors provided
+ by BIAS _and_ PREFER_COLORS, then in BIAS alone, then in PREFER_COLORS
+ alone, and only then for any free color. If flag_ra_biased is zero
+ only do the last two steps. */
+
+static int
+get_biased_reg (dont_begin_colors, bias, prefer_colors, free_colors, mode)
+ HARD_REG_SET dont_begin_colors, bias, prefer_colors, free_colors;
+ enum machine_mode mode;
+{
+ int c = -1;
+ HARD_REG_SET s;
+ if (flag_ra_biased)
+ {
+ COPY_HARD_REG_SET (s, dont_begin_colors);
+ IOR_COMPL_HARD_REG_SET (s, bias);
+ IOR_COMPL_HARD_REG_SET (s, prefer_colors);
+ c = get_free_reg (s, free_colors, mode);
+ if (c >= 0)
+ return c;
+ COPY_HARD_REG_SET (s, dont_begin_colors);
+ IOR_COMPL_HARD_REG_SET (s, bias);
+ c = get_free_reg (s, free_colors, mode);
+ if (c >= 0)
+ return c;
+ }
+ COPY_HARD_REG_SET (s, dont_begin_colors);
+ IOR_COMPL_HARD_REG_SET (s, prefer_colors);
+ c = get_free_reg (s, free_colors, mode);
+ if (c >= 0)
+ return c;
+ c = get_free_reg (dont_begin_colors, free_colors, mode);
+ return c;
+}
+
+/* Counts the number of non-overlapping bitblocks of length LEN
+ in FREE_COLORS. */
+
+static int
+count_long_blocks (free_colors, len)
+ HARD_REG_SET free_colors;
+ int len;
+{
+ int i, j;
+ int count = 0;
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ if (!TEST_HARD_REG_BIT (free_colors, i))
+ continue;
+ for (j = 1; j < len; j++)
+ if (!TEST_HARD_REG_BIT (free_colors, i + j))
+ break;
+ /* Bits [i .. i+j-1] are free. */
+ if (j == len)
+ count++;
+ i += j - 1;
+ }
+ return count;
+}
+
+/* Given a hardreg set S, return a string representing it.
+ Either as 0/1 string, or as hex value depending on the implementation
+ of hardreg sets. Note that this string is statically allocated. */
+
+static char *
+hardregset_to_string (s)
+ HARD_REG_SET s;
+{
+ static char string[/*FIRST_PSEUDO_REGISTER + 30*/1024];
+#if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_WIDE_INT
+ sprintf (string, HOST_WIDE_INT_PRINT_HEX, s);
+#else
+ char *c = string;
+ int i,j;
+ c += sprintf (c, "{ ");
+ for (i = 0;i < HARD_REG_SET_LONGS; i++)
+ {
+ for (j = 0; j < HOST_BITS_PER_WIDE_INT; j++)
+ c += sprintf (c, "%s", ( 1 << j) & s[i] ? "1" : "0");
+ c += sprintf (c, "%s", i ? ", " : "");
+ }
+ c += sprintf (c, " }");
+#endif
+ return string;
+}
+
+/* For WEB, look at its already colored neighbors, and calculate
+ the set of hardregs which is not allowed as color for WEB. Place
+ that set int *RESULT. Note that the set of forbidden begin colors
+ is not the same as all colors taken up by neighbors. E.g. suppose
+ two DImode webs, but only the lo-part from one conflicts with the
+ hipart from the other, and suppose the other gets colors 2 and 3
+ (it needs two SImode hardregs). Now the first can take also color
+ 1 or 2, although in those cases there's a partial overlap. Only
+ 3 can't be used as begin color. */
+
+static void
+calculate_dont_begin (web, result)
+ struct web *web;
+ HARD_REG_SET *result;
+{
+ struct conflict_link *wl;
+ HARD_REG_SET dont_begin;
+ /* The bits set in dont_begin correspond to the hardregs, at which
+ WEB may not begin. This differs from the set of _all_ hardregs which
+ are taken by WEB's conflicts in the presence of wide webs, where only
+ some parts conflict with others. */
+ CLEAR_HARD_REG_SET (dont_begin);
+ for (wl = web->conflict_list; wl; wl = wl->next)
+ {
+ struct web *w;
+ struct web *ptarget = alias (wl->t);
+ struct sub_conflict *sl = wl->sub;
+ w = sl ? sl->t : wl->t;
+ while (w)
+ {
+ if (ptarget->type == COLORED || ptarget->type == PRECOLORED)
+ {
+ struct web *source = (sl) ? sl->s : web;
+ unsigned int tsize = HARD_REGNO_NREGS (ptarget->color,
+ GET_MODE (w->orig_x));
+ /* ssize is only a first guess for the size. */
+ unsigned int ssize = HARD_REGNO_NREGS (ptarget->color, GET_MODE
+ (source->orig_x));
+ unsigned int tofs = 0;
+ unsigned int sofs = 0;
+ /* C1 and C2 can become negative, so unsigned
+ would be wrong. */
+ int c1, c2;
+
+ if (SUBWEB_P (w)
+ && GET_MODE_SIZE (GET_MODE (w->orig_x)) >= UNITS_PER_WORD)
+ tofs = (SUBREG_BYTE (w->orig_x) / UNITS_PER_WORD);
+ if (SUBWEB_P (source)
+ && GET_MODE_SIZE (GET_MODE (source->orig_x))
+ >= UNITS_PER_WORD)
+ sofs = (SUBREG_BYTE (source->orig_x) / UNITS_PER_WORD);
+ c1 = ptarget->color + tofs - sofs - ssize + 1;
+ c2 = ptarget->color + tofs + tsize - 1 - sofs;
+ if (c2 >= 0)
+ {
+ if (c1 < 0)
+ c1 = 0;
+ /* Because ssize was only guessed above, which influenced our
+ begin color (c1), we need adjustment, if for that color
+ another size would be needed. This is done by moving
+ c1 to a place, where the last of sources hardregs does not
+ overlap the first of targets colors. */
+ while (c1 + sofs
+ + HARD_REGNO_NREGS (c1, GET_MODE (source->orig_x)) - 1
+ < ptarget->color + tofs)
+ c1++;
+ while (c1 > 0 && c1 + sofs
+ + HARD_REGNO_NREGS (c1, GET_MODE (source->orig_x)) - 1
+ > ptarget->color + tofs)
+ c1--;
+ for (; c1 <= c2; c1++)
+ SET_HARD_REG_BIT (dont_begin, c1);
+ }
+ }
+ /* The next if() only gets true, if there was no wl->sub at all, in
+ which case we are only making one go thru this loop with W being
+ a whole web. */
+ if (!sl)
+ break;
+ sl = sl->next;
+ w = sl ? sl->t : NULL;
+ }
+ }
+ COPY_HARD_REG_SET (*result, dont_begin);
+}
+
+/* Try to assign a color to WEB. If HARD if nonzero, we try many
+ tricks to get it one color, including respilling already colored
+ neighbors.
+
+ We also trie very hard, to not constrain the uncolored non-spill
+ neighbors, which need more hardregs than we. Consider a situation, 2
+ hardregs free for us (0 and 1), and one of our neighbors needs 2
+ hardregs, and only conflicts with us. There are 3 hardregs at all. Now
+ a simple minded method might choose 1 as color for us. Then our neighbor
+ has two free colors (0 and 2) as it should, but they are not consecutive,
+ so coloring it later would fail. This leads to nasty problems on
+ register starved machines, so we try to avoid this. */
+
+static void
+colorize_one_web (web, hard)
+ struct web *web;
+ int hard;
+{
+ struct conflict_link *wl;
+ HARD_REG_SET colors, dont_begin;
+ int c = -1;
+ int bestc = -1;
+ int neighbor_needs= 0;
+ struct web *fat_neighbor = NULL;
+ struct web *fats_parent = NULL;
+ int num_fat = 0;
+ int long_blocks = 0;
+ int best_long_blocks = -1;
+ HARD_REG_SET fat_colors;
+ HARD_REG_SET bias;
+
+ if (web->regno >= max_normal_pseudo)
+ hard = 0;
+
+ /* First we want to know the colors at which we can't begin. */
+ calculate_dont_begin (web, &dont_begin);
+ CLEAR_HARD_REG_SET (bias);
+
+ /* Now setup the set of colors used by our neighbors neighbors,
+ and search the biggest noncolored neighbor. */
+ neighbor_needs = web->add_hardregs + 1;
+ for (wl = web->conflict_list; wl; wl = wl->next)
+ {
+ struct web *w;
+ struct web *ptarget = alias (wl->t);
+ struct sub_conflict *sl = wl->sub;
+ IOR_HARD_REG_SET (bias, ptarget->bias_colors);
+ w = sl ? sl->t : wl->t;
+ if (ptarget->type != COLORED && ptarget->type != PRECOLORED
+ && !ptarget->was_spilled)
+ while (w)
+ {
+ if (find_web_for_subweb (w)->type != COALESCED
+ && w->add_hardregs >= neighbor_needs)
+ {
+ neighbor_needs = w->add_hardregs;
+ fat_neighbor = w;
+ fats_parent = ptarget;
+ num_fat++;
+ }
+ if (!sl)
+ break;
+ sl = sl->next;
+ w = sl ? sl->t : NULL;
+ }
+ }
+
+ ra_debug_msg (DUMP_COLORIZE, "colorize web %d [don't begin at %s]", web->id,
+ hardregset_to_string (dont_begin));
+
+ /* If there are some fat neighbors, remember their usable regs,
+ and how many blocks are free in it for that neighbor. */
+ if (num_fat)
+ {
+ COPY_HARD_REG_SET (fat_colors, fats_parent->usable_regs);
+ long_blocks = count_long_blocks (fat_colors, neighbor_needs + 1);
+ }
+
+ /* We break out, if we found a color which doesn't constrain
+ neighbors, or if we can't find any colors. */
+ while (1)
+ {
+ HARD_REG_SET call_clobbered;
+
+ /* Here we choose a hard-reg for the current web. For non spill
+ temporaries we first search in the hardregs for it's prefered
+ class, then, if we found nothing appropriate, in those of the
+ alternate class. For spill temporaries we only search in
+ usable_regs of this web (which is probably larger than that of
+ the preferred or alternate class). All searches first try to
+ find a non-call-clobbered hard-reg.
+ XXX this should be more finegraned... First look into preferred
+ non-callclobbered hardregs, then _if_ the web crosses calls, in
+ alternate non-cc hardregs, and only _then_ also in preferred cc
+ hardregs (and alternate ones). Currently we don't track the number
+ of calls crossed for webs. We should. */
+ if (web->use_my_regs)
+ {
+ COPY_HARD_REG_SET (colors, web->usable_regs);
+ AND_HARD_REG_SET (colors,
+ usable_regs[reg_preferred_class (web->regno)]);
+ }
+ else
+ COPY_HARD_REG_SET (colors,
+ usable_regs[reg_preferred_class (web->regno)]);
+#ifdef CLASS_CANNOT_CHANGE_MODE
+ if (web->mode_changed)
+ AND_COMPL_HARD_REG_SET (colors, reg_class_contents[
+ (int) CLASS_CANNOT_CHANGE_MODE]);
+#endif
+ COPY_HARD_REG_SET (call_clobbered, colors);
+ AND_HARD_REG_SET (call_clobbered, call_used_reg_set);
+
+ /* If this web got a color in the last pass, try to give it the
+ same color again. This will to much better colorization
+ down the line, as we spilled for a certain coloring last time. */
+ if (web->old_color)
+ {
+ c = web->old_color - 1;
+ if (!color_usable_p (c, dont_begin, colors,
+ PSEUDO_REGNO_MODE (web->regno)))
+ c = -1;
+ }
+ else
+ c = -1;
+ if (c < 0)
+ c = get_biased_reg (dont_begin, bias, web->prefer_colors,
+ call_clobbered, PSEUDO_REGNO_MODE (web->regno));
+ if (c < 0)
+ c = get_biased_reg (dont_begin, bias, web->prefer_colors,
+ colors, PSEUDO_REGNO_MODE (web->regno));
+
+ if (c < 0)
+ {
+ if (web->use_my_regs)
+ IOR_HARD_REG_SET (colors, web->usable_regs);
+ else
+ IOR_HARD_REG_SET (colors, usable_regs
+ [reg_alternate_class (web->regno)]);
+#ifdef CLASS_CANNOT_CHANGE_MODE
+ if (web->mode_changed)
+ AND_COMPL_HARD_REG_SET (colors, reg_class_contents[
+ (int) CLASS_CANNOT_CHANGE_MODE]);
+#endif
+ COPY_HARD_REG_SET (call_clobbered, colors);
+ AND_HARD_REG_SET (call_clobbered, call_used_reg_set);
+
+ c = get_biased_reg (dont_begin, bias, web->prefer_colors,
+ call_clobbered, PSEUDO_REGNO_MODE (web->regno));
+ if (c < 0)
+ c = get_biased_reg (dont_begin, bias, web->prefer_colors,
+ colors, PSEUDO_REGNO_MODE (web->regno));
+ }
+ if (c < 0)
+ break;
+ if (bestc < 0)
+ bestc = c;
+ /* If one of the yet uncolored neighbors, which is not a potential
+ spill needs a block of hardregs be sure, not to destroy such a block
+ by coloring one reg in the middle. */
+ if (num_fat)
+ {
+ int i;
+ int new_long;
+ HARD_REG_SET colors1;
+ COPY_HARD_REG_SET (colors1, fat_colors);
+ for (i = 0; i < 1 + web->add_hardregs; i++)
+ CLEAR_HARD_REG_BIT (colors1, c + i);
+ new_long = count_long_blocks (colors1, neighbor_needs + 1);
+ /* If we changed the number of long blocks, and it's now smaller
+ than needed, we try to avoid this color. */
+ if (long_blocks != new_long && new_long < num_fat)
+ {
+ if (new_long > best_long_blocks)
+ {
+ best_long_blocks = new_long;
+ bestc = c;
+ }
+ SET_HARD_REG_BIT (dont_begin, c);
+ ra_debug_msg (DUMP_COLORIZE, " avoid %d", c);
+ }
+ else
+ /* We found a color which doesn't destroy a block. */
+ break;
+ }
+ /* If we havee no fat neighbors, the current color won't become
+ "better", so we've found it. */
+ else
+ break;
+ }
+ ra_debug_msg (DUMP_COLORIZE, " --> got %d", c < 0 ? bestc : c);
+ if (bestc >= 0 && c < 0 && !web->was_spilled)
+ {
+ /* This is a non-potential-spill web, which got a color, which did
+ destroy a hardreg block for one of it's neighbors. We color
+ this web anyway and hope for the best for the neighbor, if we are
+ a spill temp. */
+ if (1 || web->spill_temp)
+ c = bestc;
+ ra_debug_msg (DUMP_COLORIZE, " [constrains neighbors]");
+ }
+ ra_debug_msg (DUMP_COLORIZE, "\n");
+
+ if (c < 0)
+ {
+ /* Guard against a simplified node being spilled. */
+ /* Don't abort. This can happen, when e.g. enough registers
+ are available in colors, but they are not consecutive. This is a
+ very serious issue if this web is a short live one, because
+ even if we spill this one here, the situation won't become better
+ in the next iteration. It probably will have the same conflicts,
+ those will have the same colors, and we would come here again, for
+ all parts, in which this one gets splitted by the spill. This
+ can result in endless iteration spilling the same register again and
+ again. That's why we try to find a neighbor, which spans more
+ instructions that ourself, and got a color, and try to spill _that_.
+
+ if (DLIST_WEB (d)->was_spilled < 0)
+ abort (); */
+ if (hard && (!web->was_spilled || web->spill_temp))
+ {
+ unsigned int loop;
+ struct web *try = NULL;
+ struct web *candidates[8];
+
+ ra_debug_msg (DUMP_COLORIZE, " *** %d spilled, although %s ***\n",
+ web->id, web->spill_temp ? "spilltemp" : "non-spill");
+ /* We make multiple passes over our conflicts, first trying to
+ spill those webs, which only got a color by chance, but
+ were potential spill ones, and if that isn't enough, in a second
+ pass also to spill normal colored webs. If we still didn't find
+ a candidate, but we are a spill-temp, we make a third pass
+ and include also webs, which were targets for coalescing, and
+ spill those. */
+ memset (candidates, 0, sizeof candidates);
+#define set_cand(i, w) \
+ do { \
+ if (!candidates[(i)] \
+ || (candidates[(i)]->spill_cost < (w)->spill_cost)) \
+ candidates[(i)] = (w); \
+ } while (0)
+ for (wl = web->conflict_list; wl; wl = wl->next)
+ {
+ struct web *w = wl->t;
+ struct web *aw = alias (w);
+ /* If we are a spill-temp, we also look at webs coalesced
+ to precolored ones. Otherwise we only look at webs which
+ themself were colored, or coalesced to one. */
+ if (aw->type == PRECOLORED && w != aw && web->spill_temp
+ && flag_ra_optimistic_coalescing)
+ {
+ if (!w->spill_temp)
+ set_cand (4, w);
+ else if (web->spill_temp == 2
+ && w->spill_temp == 2
+ && w->spill_cost < web->spill_cost)
+ set_cand (5, w);
+ else if (web->spill_temp != 2
+ && (w->spill_temp == 2
+ || w->spill_cost < web->spill_cost))
+ set_cand (6, w);
+ continue;
+ }
+ if (aw->type != COLORED)
+ continue;
+ if (w->type == COLORED && !w->spill_temp && !w->is_coalesced
+ && w->was_spilled)
+ {
+ if (w->spill_cost < web->spill_cost)
+ set_cand (0, w);
+ else if (web->spill_temp)
+ set_cand (1, w);
+ }
+ if (w->type == COLORED && !w->spill_temp && !w->is_coalesced
+ && !w->was_spilled)
+ {
+ if (w->spill_cost < web->spill_cost)
+ set_cand (2, w);
+ else if (web->spill_temp && web->spill_temp != 2)
+ set_cand (3, w);
+ }
+ if (web->spill_temp)
+ {
+ if (w->type == COLORED && w->spill_temp == 2
+ && !w->is_coalesced
+ && (w->spill_cost < web->spill_cost
+ || web->spill_temp != 2))
+ set_cand (4, w);
+ if (!aw->spill_temp)
+ set_cand (5, aw);
+ if (aw->spill_temp == 2
+ && (aw->spill_cost < web->spill_cost
+ || web->spill_temp != 2))
+ set_cand (6, aw);
+ /* For boehm-gc/misc.c. If we are a difficult spilltemp,
+ also coalesced neighbors are a chance, _even_ if they
+ too are spilltemps. At least their coalscing can be
+ broken up, which may be reset usable_regs, and makes
+ it easier colorable. */
+ if (web->spill_temp != 2 && aw->is_coalesced
+ && flag_ra_optimistic_coalescing)
+ set_cand (7, aw);
+ }
+ }
+ for (loop = 0; try == NULL && loop < 8; loop++)
+ if (candidates[loop])
+ try = candidates[loop];
+#undef set_cand
+ if (try)
+ {
+ int old_c = try->color;
+ if (try->type == COALESCED)
+ {
+ if (alias (try)->type != PRECOLORED)
+ abort ();
+ ra_debug_msg (DUMP_COLORIZE, " breaking alias %d -> %d\n",
+ try->id, alias (try)->id);
+ break_precolored_alias (try);
+ colorize_one_web (web, hard);
+ }
+ else
+ {
+ remove_list (try->dlink, &WEBS(COLORED));
+ put_web (try, SPILLED);
+ /* Now try to colorize us again. Can recursively make other
+ webs also spill, until there are no more unspilled
+ neighbors. */
+ ra_debug_msg (DUMP_COLORIZE, " trying to spill %d\n", try->id);
+ colorize_one_web (web, hard);
+ if (web->type != COLORED)
+ {
+ /* We tried recursively to spill all already colored
+ neighbors, but we are still uncolorable. So it made
+ no sense to spill those neighbors. Recolor them. */
+ remove_list (try->dlink, &WEBS(SPILLED));
+ put_web (try, COLORED);
+ try->color = old_c;
+ ra_debug_msg (DUMP_COLORIZE,
+ " spilling %d was useless\n", try->id);
+ }
+ else
+ {
+ ra_debug_msg (DUMP_COLORIZE,
+ " to spill %d was a good idea\n",
+ try->id);
+ remove_list (try->dlink, &WEBS(SPILLED));
+ if (try->was_spilled)
+ colorize_one_web (try, 0);
+ else
+ colorize_one_web (try, hard - 1);
+ }
+ }
+ }
+ else
+ /* No more chances to get a color, so give up hope and
+ spill us. */
+ put_web (web, SPILLED);
+ }
+ else
+ put_web (web, SPILLED);
+ }
+ else
+ {
+ put_web (web, COLORED);
+ web->color = c;
+ if (flag_ra_biased)
+ {
+ int nregs = HARD_REGNO_NREGS (c, GET_MODE (web->orig_x));
+ for (wl = web->conflict_list; wl; wl = wl->next)
+ {
+ struct web *ptarget = alias (wl->t);
+ int i;
+ for (i = 0; i < nregs; i++)
+ SET_HARD_REG_BIT (ptarget->bias_colors, c + i);
+ }
+ }
+ }
+ if (web->regno >= max_normal_pseudo && web->type == SPILLED)
+ {
+ web->color = an_unusable_color;
+ remove_list (web->dlink, &WEBS(SPILLED));
+ put_web (web, COLORED);
+ }
+ if (web->type == SPILLED && flag_ra_optimistic_coalescing
+ && web->is_coalesced)
+ {
+ ra_debug_msg (DUMP_COLORIZE, "breaking aliases to web %d:", web->id);
+ restore_conflicts_from_coalesce (web);
+ break_aliases_to_web (web);
+ insert_coalesced_conflicts ();
+ ra_debug_msg (DUMP_COLORIZE, "\n");
+ remove_list (web->dlink, &WEBS(SPILLED));
+ put_web (web, SELECT);
+ web->color = -1;
+ }
+}
+
+/* Assign the colors to all nodes on the select stack. And update the
+ colors of coalesced webs. */
+
+static void
+assign_colors ()
+{
+ struct dlist *d;
+
+ while (WEBS(SELECT))
+ {
+ struct web *web;
+ d = pop_list (&WEBS(SELECT));
+ web = DLIST_WEB (d);
+ colorize_one_web (DLIST_WEB (d), 1);
+ }
+
+ for (d = WEBS(COALESCED); d; d = d->next)
+ {
+ struct web *a = alias (DLIST_WEB (d));
+ DLIST_WEB (d)->color = a->color;
+ }
+}
+
+/* WEB is a spilled web. Look if we can improve the cost of the graph,
+ by coloring WEB, even if we then need to spill some of it's neighbors.
+ For this we calculate the cost for each color C, that results when we
+ _would_ give WEB color C (i.e. the cost of the then spilled neighbors).
+ If the lowest cost among them is smaller than the spillcost of WEB, we
+ do that recoloring, and instead spill the neighbors.
+
+ This can sometime help, when due to irregularities in register file,
+ and due to multi word pseudos, the colorization is suboptimal. But
+ be aware, that currently this pass is quite slow. */
+
+static void
+try_recolor_web (web)
+ struct web *web;
+{
+ struct conflict_link *wl;
+ unsigned HOST_WIDE_INT *cost_neighbors;
+ unsigned int *min_color;
+ int newcol, c;
+ HARD_REG_SET precolored_neighbors, spill_temps;
+ HARD_REG_SET possible_begin, wide_seen;
+ cost_neighbors = (unsigned HOST_WIDE_INT *)
+ xcalloc (FIRST_PSEUDO_REGISTER, sizeof (cost_neighbors[0]));
+ /* For each hard-regs count the number of preceding hardregs, which
+ would overlap this color, if used in WEB's mode. */
+ min_color = (unsigned int *) xcalloc (FIRST_PSEUDO_REGISTER, sizeof (int));
+ CLEAR_HARD_REG_SET (possible_begin);
+ for (c = 0; c < FIRST_PSEUDO_REGISTER; c++)
+ {
+ int i, nregs;
+ if (!HARD_REGNO_MODE_OK (c, GET_MODE (web->orig_x)))
+ continue;
+ nregs = HARD_REGNO_NREGS (c, GET_MODE (web->orig_x));
+ for (i = 0; i < nregs; i++)
+ if (!TEST_HARD_REG_BIT (web->usable_regs, c + i))
+ break;
+ if (i < nregs || nregs == 0)
+ continue;
+ SET_HARD_REG_BIT (possible_begin, c);
+ for (; nregs--;)
+ if (!min_color[c + nregs])
+ min_color[c + nregs] = 1 + c;
+ }
+ CLEAR_HARD_REG_SET (precolored_neighbors);
+ CLEAR_HARD_REG_SET (spill_temps);
+ CLEAR_HARD_REG_SET (wide_seen);
+ for (wl = web->conflict_list; wl; wl = wl->next)
+ {
+ HARD_REG_SET dont_begin;
+ struct web *web2 = alias (wl->t);
+ struct conflict_link *nn;
+ int c1, c2;
+ int wide_p = 0;
+ if (wl->t->type == COALESCED || web2->type != COLORED)
+ {
+ if (web2->type == PRECOLORED)
+ {
+ c1 = min_color[web2->color];
+ c1 = (c1 == 0) ? web2->color : (c1 - 1);
+ c2 = web2->color;
+ for (; c1 <= c2; c1++)
+ SET_HARD_REG_BIT (precolored_neighbors, c1);
+ }
+ continue;
+ }
+ /* Mark colors for which some wide webs are involved. For
+ those the independent sets are not simply one-node graphs, so
+ they can't be recolored independ from their neighborhood. This
+ means, that our cost calculation can be incorrect (assuming it
+ can avoid spilling a web because it thinks some colors are available,
+ although it's neighbors which itself need recoloring might take
+ away exactly those colors). */
+ if (web2->add_hardregs)
+ wide_p = 1;
+ for (nn = web2->conflict_list; nn && !wide_p; nn = nn->next)
+ if (alias (nn->t)->add_hardregs)
+ wide_p = 1;
+ calculate_dont_begin (web2, &dont_begin);
+ c1 = min_color[web2->color];
+ /* Note that min_color[] contains 1-based values (zero means
+ undef). */
+ c1 = c1 == 0 ? web2->color : (c1 - 1);
+ c2 = web2->color + HARD_REGNO_NREGS (web2->color, GET_MODE
+ (web2->orig_x)) - 1;
+ for (; c1 <= c2; c1++)
+ if (TEST_HARD_REG_BIT (possible_begin, c1))
+ {
+ int nregs;
+ HARD_REG_SET colors;
+ nregs = HARD_REGNO_NREGS (c1, GET_MODE (web->orig_x));
+ COPY_HARD_REG_SET (colors, web2->usable_regs);
+ for (; nregs--;)
+ CLEAR_HARD_REG_BIT (colors, c1 + nregs);
+ if (wide_p)
+ SET_HARD_REG_BIT (wide_seen, c1);
+ if (get_free_reg (dont_begin, colors,
+ GET_MODE (web2->orig_x)) < 0)
+ {
+ if (web2->spill_temp)
+ SET_HARD_REG_BIT (spill_temps, c1);
+ else
+ cost_neighbors[c1] += web2->spill_cost;
+ }
+ }
+ }
+ newcol = -1;
+ for (c = 0; c < FIRST_PSEUDO_REGISTER; c++)
+ if (TEST_HARD_REG_BIT (possible_begin, c)
+ && !TEST_HARD_REG_BIT (precolored_neighbors, c)
+ && !TEST_HARD_REG_BIT (spill_temps, c)
+ && (newcol == -1
+ || cost_neighbors[c] < cost_neighbors[newcol]))
+ newcol = c;
+ if (newcol >= 0 && cost_neighbors[newcol] < web->spill_cost)
+ {
+ int nregs = HARD_REGNO_NREGS (newcol, GET_MODE (web->orig_x));
+ unsigned HOST_WIDE_INT cost = 0;
+ int *old_colors;
+ struct conflict_link *wl_next;
+ ra_debug_msg (DUMP_COLORIZE, "try to set web %d to color %d\n", web->id,
+ newcol);
+ remove_list (web->dlink, &WEBS(SPILLED));
+ put_web (web, COLORED);
+ web->color = newcol;
+ old_colors = (int *) xcalloc (num_webs, sizeof (int));
+ for (wl = web->conflict_list; wl; wl = wl_next)
+ {
+ struct web *web2 = alias (wl->t);
+ /* If web2 is a coalesce-target, and will become spilled
+ below in colorize_one_web(), and the current conflict wl
+ between web and web2 was only the result of that coalescing
+ this conflict will be deleted, making wl invalid. So save
+ the next conflict right now. Note that if web2 has indeed
+ such state, then wl->next can not be deleted in this
+ iteration. */
+ wl_next = wl->next;
+ if (web2->type == COLORED)
+ {
+ int nregs2 = HARD_REGNO_NREGS (web2->color, GET_MODE
+ (web2->orig_x));
+ if (web->color >= web2->color + nregs2
+ || web2->color >= web->color + nregs)
+ continue;
+ old_colors[web2->id] = web2->color + 1;
+ web2->color = -1;
+ remove_list (web2->dlink, &WEBS(COLORED));
+ web2->type = SELECT;
+ /* Allow webs to be spilled. */
+ if (web2->spill_temp == 0 || web2->spill_temp == 2)
+ web2->was_spilled = 1;
+ colorize_one_web (web2, 1);
+ if (web2->type == SPILLED)
+ cost += web2->spill_cost;
+ }
+ }
+ /* The actual cost may be smaller than the guessed one, because
+ partial conflicts could result in some conflicting webs getting
+ a color, where we assumed it must be spilled. See the comment
+ above what happens, when wide webs are involved, and why in that
+ case there might actually be some webs spilled although thought to
+ be colorable. */
+ if (cost > cost_neighbors[newcol]
+ && nregs == 1 && !TEST_HARD_REG_BIT (wide_seen, newcol))
+ abort ();
+ /* But if the new spill-cost is higher than our own, then really loose.
+ Respill us and recolor neighbors as before. */
+ if (cost > web->spill_cost)
+ {
+ ra_debug_msg (DUMP_COLORIZE,
+ "reset coloring of web %d, too expensive\n", web->id);
+ remove_list (web->dlink, &WEBS(COLORED));
+ web->color = -1;
+ put_web (web, SPILLED);
+ for (wl = web->conflict_list; wl; wl = wl->next)
+ {
+ struct web *web2 = alias (wl->t);
+ if (old_colors[web2->id])
+ {
+ if (web2->type == SPILLED)
+ {
+ remove_list (web2->dlink, &WEBS(SPILLED));
+ web2->color = old_colors[web2->id] - 1;
+ put_web (web2, COLORED);
+ }
+ else if (web2->type == COLORED)
+ web2->color = old_colors[web2->id] - 1;
+ else if (web2->type == SELECT)
+ /* This means, that WEB2 once was a part of a coalesced
+ web, which got spilled in the above colorize_one_web()
+ call, and whose parts then got splitted and put back
+ onto the SELECT stack. As the cause for that splitting
+ (the coloring of WEB) was worthless, we should again
+ coalesce the parts, as they were before. For now we
+ simply leave them SELECTed, for our caller to take
+ care. */
+ ;
+ else
+ abort ();
+ }
+ }
+ }
+ free (old_colors);
+ }
+ free (min_color);
+ free (cost_neighbors);
+}
+
+/* This ensures that all conflicts of coalesced webs are seen from
+ the webs coalesced into. combine() only adds the conflicts which
+ at the time of combining were not already SELECTed or COALESCED
+ to not destroy num_conflicts. Here we add all remaining conflicts
+ and thereby destroy num_conflicts. This should be used when num_conflicts
+ isn't used anymore, e.g. on a completely colored graph. */
+
+static void
+insert_coalesced_conflicts ()
+{
+ struct dlist *d;
+ for (d = WEBS(COALESCED); 0 && d; d = d->next)
+ {
+ struct web *web = DLIST_WEB (d);
+ struct web *aweb = alias (web);
+ struct conflict_link *wl;
+ for (wl = web->conflict_list; wl; wl = wl->next)
+ {
+ struct web *tweb = aweb;
+ int i;
+ int nregs = 1 + web->add_hardregs;
+ if (aweb->type == PRECOLORED)
+ nregs = HARD_REGNO_NREGS (aweb->color, GET_MODE (web->orig_x));
+ for (i = 0; i < nregs; i++)
+ {
+ if (aweb->type == PRECOLORED)
+ tweb = hardreg2web[i + aweb->color];
+ /* There might be some conflict edges laying around
+ where the usable_regs don't intersect. This can happen
+ when first some webs were coalesced and conflicts
+ propagated, then some combining narrowed usable_regs and
+ further coalescing ignored those conflicts. Now there are
+ some edges to COALESCED webs but not to it's alias.
+ So abort only when they really should conflict. */
+ if ((!(tweb->type == PRECOLORED
+ || TEST_BIT (sup_igraph, tweb->id * num_webs + wl->t->id))
+ || !(wl->t->type == PRECOLORED
+ || TEST_BIT (sup_igraph,
+ wl->t->id * num_webs + tweb->id)))
+ && hard_regs_intersect_p (&tweb->usable_regs,
+ &wl->t->usable_regs))
+ abort ();
+ /*if (wl->sub == NULL)
+ record_conflict (tweb, wl->t);
+ else
+ {
+ struct sub_conflict *sl;
+ for (sl = wl->sub; sl; sl = sl->next)
+ record_conflict (tweb, sl->t);
+ }*/
+ if (aweb->type != PRECOLORED)
+ break;
+ }
+ }
+ }
+}
+
+/* A function suitable to pass to qsort(). Compare the spill costs
+ of webs W1 and W2. When used by qsort, this would order webs with
+ largest cost first. */
+
+static int
+comp_webs_maxcost (w1, w2)
+ const void *w1, *w2;
+{
+ struct web *web1 = *(struct web **)w1;
+ struct web *web2 = *(struct web **)w2;
+ if (web1->spill_cost > web2->spill_cost)
+ return -1;
+ else if (web1->spill_cost < web2->spill_cost)
+ return 1;
+ else
+ return 0;
+}
+
+/* This tries to recolor all spilled webs. See try_recolor_web()
+ how this is done. This just calls it for each spilled web. */
+
+static void
+recolor_spills ()
+{
+ unsigned int i, num;
+ struct web **order2web;
+ num = num_webs - num_subwebs;
+ order2web = (struct web **) xmalloc (num * sizeof (order2web[0]));
+ for (i = 0; i < num; i++)
+ {
+ order2web[i] = id2web[i];
+ /* If we aren't breaking aliases, combine() wasn't merging the
+ spill_costs. So do that here to have sane measures. */
+ if (!flag_ra_merge_spill_costs && id2web[i]->type == COALESCED)
+ alias (id2web[i])->spill_cost += id2web[i]->spill_cost;
+ }
+ qsort (order2web, num, sizeof (order2web[0]), comp_webs_maxcost);
+ insert_coalesced_conflicts ();
+ dump_graph_cost (DUMP_COSTS, "before spill-recolor");
+ for (i = 0; i < num; i++)
+ {
+ struct web *web = order2web[i];
+ if (web->type == SPILLED)
+ try_recolor_web (web);
+ }
+ /* It might have been decided in try_recolor_web() (in colorize_one_web())
+ that a coalesced web should be spilled, so it was put on the
+ select stack. Those webs need recoloring again, and all remaining
+ coalesced webs might need their color updated, so simply call
+ assign_colors() again. */
+ assign_colors ();
+ free (order2web);
+}
+
+/* This checks the current color assignment for obvious errors,
+ like two conflicting webs overlapping in colors, or the used colors
+ not being in usable regs. */
+
+static void
+check_colors ()
+{
+ unsigned int i;
+ for (i = 0; i < num_webs - num_subwebs; i++)
+ {
+ struct web *web = id2web[i];
+ struct web *aweb = alias (web);
+ struct conflict_link *wl;
+ int nregs, c;
+ if (aweb->type == SPILLED || web->regno >= max_normal_pseudo)
+ continue;
+ else if (aweb->type == COLORED)
+ nregs = HARD_REGNO_NREGS (aweb->color, GET_MODE (web->orig_x));
+ else if (aweb->type == PRECOLORED)
+ nregs = 1;
+ else
+ abort ();
+ /* The color must be valid for the original usable_regs. */
+ for (c = 0; c < nregs; c++)
+ if (!TEST_HARD_REG_BIT (web->usable_regs, aweb->color + c))
+ abort ();
+ /* Search the original (pre-coalesce) conflict list. In the current
+ one some inprecise conflicts may be noted (due to combine() or
+ insert_coalesced_conflicts() relocating partial conflicts) making
+ it look like some wide webs are in conflict and having the same
+ color. */
+ wl = (web->have_orig_conflicts ? web->orig_conflict_list
+ : web->conflict_list);
+ for (; wl; wl = wl->next)
+ if (wl->t->regno >= max_normal_pseudo)
+ continue;
+ else if (!wl->sub)
+ {
+ struct web *web2 = alias (wl->t);
+ int nregs2;
+ if (web2->type == COLORED)
+ nregs2 = HARD_REGNO_NREGS (web2->color, GET_MODE (web2->orig_x));
+ else if (web2->type == PRECOLORED)
+ nregs2 = 1;
+ else
+ continue;
+ if (aweb->color >= web2->color + nregs2
+ || web2->color >= aweb->color + nregs)
+ continue;
+ abort ();
+ }
+ else
+ {
+ struct sub_conflict *sl;
+ int scol = aweb->color;
+ int tcol = alias (wl->t)->color;
+ if (alias (wl->t)->type == SPILLED)
+ continue;
+ for (sl = wl->sub; sl; sl = sl->next)
+ {
+ int ssize = HARD_REGNO_NREGS (scol, GET_MODE (sl->s->orig_x));
+ int tsize = HARD_REGNO_NREGS (tcol, GET_MODE (sl->t->orig_x));
+ int sofs = 0, tofs = 0;
+ if (SUBWEB_P (sl->t)
+ && GET_MODE_SIZE (GET_MODE (sl->t->orig_x)) >= UNITS_PER_WORD)
+ tofs = (SUBREG_BYTE (sl->t->orig_x) / UNITS_PER_WORD);
+ if (SUBWEB_P (sl->s)
+ && GET_MODE_SIZE (GET_MODE (sl->s->orig_x))
+ >= UNITS_PER_WORD)
+ sofs = (SUBREG_BYTE (sl->s->orig_x) / UNITS_PER_WORD);
+ if ((tcol + tofs >= scol + sofs + ssize)
+ || (scol + sofs >= tcol + tofs + tsize))
+ continue;
+ abort ();
+ }
+ }
+ }
+}
+
+/* WEB was a coalesced web. Make it unaliased again, and put it
+ back onto SELECT stack. */
+
+static void
+unalias_web (web)
+ struct web *web;
+{
+ web->alias = NULL;
+ web->is_coalesced = 0;
+ web->color = -1;
+ /* Well, initially everything was spilled, so it isn't incorrect,
+ that also the individual parts can be spilled.
+ XXX this isn't entirely correct, as we also relaxed the
+ spill_temp flag in combine(), which might have made components
+ spill, although they were a short or spilltemp web. */
+ web->was_spilled = 1;
+ remove_list (web->dlink, &WEBS(COALESCED));
+ /* Spilltemps must be colored right now (i.e. as early as possible),
+ other webs can be deferred to the end (the code building the
+ stack assumed that in this stage only one web was colored). */
+ if (web->spill_temp && web->spill_temp != 2)
+ put_web (web, SELECT);
+ else
+ put_web_at_end (web, SELECT);
+}
+
+/* WEB is a _target_ for coalescing which got spilled.
+ Break all aliases to WEB, and restore some of its member to the state
+ they were before coalescing. Due to the suboptimal structure of
+ the interference graph we need to go through all coalesced webs.
+ Somewhen we'll change this to be more sane. */
+
+static void
+break_aliases_to_web (web)
+ struct web *web;
+{
+ struct dlist *d, *d_next;
+ if (web->type != SPILLED)
+ abort ();
+ for (d = WEBS(COALESCED); d; d = d_next)
+ {
+ struct web *other = DLIST_WEB (d);
+ d_next = d->next;
+ /* Beware: Don't use alias() here. We really want to check only
+ one level of aliasing, i.e. only break up webs directly
+ aliased to WEB, not also those aliased through other webs. */
+ if (other->alias == web)
+ {
+ unalias_web (other);
+ ra_debug_msg (DUMP_COLORIZE, " %d", other->id);
+ }
+ }
+ web->spill_temp = web->orig_spill_temp;
+ web->spill_cost = web->orig_spill_cost;
+ /* Beware: The following possibly widens usable_regs again. While
+ it was narrower there might have been some conflicts added which got
+ ignored because of non-intersecting hardregsets. All those conflicts
+ would now matter again. Fortunately we only add conflicts when
+ coalescing, which is also the time of narrowing. And we remove all
+ those added conflicts again now that we unalias this web.
+ Therefore this is safe to do. */
+ COPY_HARD_REG_SET (web->usable_regs, web->orig_usable_regs);
+ web->is_coalesced = 0;
+ web->num_aliased = 0;
+ web->was_spilled = 1;
+ /* Reset is_coalesced flag for webs which itself are target of coalescing.
+ It was cleared above if it was coalesced to WEB. */
+ for (d = WEBS(COALESCED); d; d = d->next)
+ DLIST_WEB (d)->alias->is_coalesced = 1;
+}
+
+/* WEB is a web coalesced into a precolored one. Break that alias,
+ making WEB SELECTed again. Also restores the conflicts which resulted
+ from initially coalescing both. */
+
+static void
+break_precolored_alias (web)
+ struct web *web;
+{
+ struct web *pre = web->alias;
+ struct conflict_link *wl;
+ unsigned int c = pre->color;
+ unsigned int nregs = HARD_REGNO_NREGS (c, GET_MODE (web->orig_x));
+ if (pre->type != PRECOLORED)
+ abort ();
+ unalias_web (web);
+ /* Now we need to look at each conflict X of WEB, if it conflicts
+ with [PRE, PRE+nregs), and remove such conflicts, of X has not other
+ conflicts, which are coalesced into those precolored webs. */
+ for (wl = web->conflict_list; wl; wl = wl->next)
+ {
+ struct web *x = wl->t;
+ struct web *y;
+ unsigned int i;
+ struct conflict_link *wl2;
+ struct conflict_link **pcl;
+ HARD_REG_SET regs;
+ if (!x->have_orig_conflicts)
+ continue;
+ /* First look at which colors can not go away, due to other coalesces
+ still existing. */
+ CLEAR_HARD_REG_SET (regs);
+ for (i = 0; i < nregs; i++)
+ SET_HARD_REG_BIT (regs, c + i);
+ for (wl2 = x->conflict_list; wl2; wl2 = wl2->next)
+ if (wl2->t->type == COALESCED && alias (wl2->t)->type == PRECOLORED)
+ CLEAR_HARD_REG_BIT (regs, alias (wl2->t)->color);
+ /* Now also remove the colors of those conflicts which already
+ were there before coalescing at all. */
+ for (wl2 = x->orig_conflict_list; wl2; wl2 = wl2->next)
+ if (wl2->t->type == PRECOLORED)
+ CLEAR_HARD_REG_BIT (regs, wl2->t->color);
+ /* The colors now still set are those for which WEB was the last
+ cause, i.e. those which can be removed. */
+ y = NULL;
+ for (i = 0; i < nregs; i++)
+ if (TEST_HARD_REG_BIT (regs, c + i))
+ {
+ struct web *sub;
+ y = hardreg2web[c + i];
+ RESET_BIT (sup_igraph, x->id * num_webs + y->id);
+ RESET_BIT (sup_igraph, y->id * num_webs + x->id);
+ RESET_BIT (igraph, igraph_index (x->id, y->id));
+ for (sub = x->subreg_next; sub; sub = sub->subreg_next)
+ RESET_BIT (igraph, igraph_index (sub->id, y->id));
+ }
+ if (!y)
+ continue;
+ pcl = &(x->conflict_list);
+ while (*pcl)
+ {
+ struct web *y = (*pcl)->t;
+ if (y->type != PRECOLORED || !TEST_HARD_REG_BIT (regs, y->color))
+ pcl = &((*pcl)->next);
+ else
+ *pcl = (*pcl)->next;
+ }
+ }
+}
+
+/* WEB is a spilled web which was target for coalescing.
+ Delete all interference edges which were added due to that coalescing,
+ and break up the coalescing. */
+
+static void
+restore_conflicts_from_coalesce (web)
+ struct web *web;
+{
+ struct conflict_link **pcl;
+ struct conflict_link *wl;
+ pcl = &(web->conflict_list);
+ /* No original conflict list means no conflict was added at all
+ after building the graph. So neither we nor any neighbors have
+ conflicts due to this coalescing. */
+ if (!web->have_orig_conflicts)
+ return;
+ while (*pcl)
+ {
+ struct web *other = (*pcl)->t;
+ for (wl = web->orig_conflict_list; wl; wl = wl->next)
+ if (wl->t == other)
+ break;
+ if (wl)
+ {
+ /* We found this conflict also in the original list, so this
+ was no new conflict. */
+ pcl = &((*pcl)->next);
+ }
+ else
+ {
+ /* This is a new conflict, so delete it from us and
+ the neighbor. */
+ struct conflict_link **opcl;
+ struct conflict_link *owl;
+ struct sub_conflict *sl;
+ wl = *pcl;
+ *pcl = wl->next;
+ if (!other->have_orig_conflicts && other->type != PRECOLORED)
+ abort ();
+ for (owl = other->orig_conflict_list; owl; owl = owl->next)
+ if (owl->t == web)
+ break;
+ if (owl)
+ abort ();
+ opcl = &(other->conflict_list);
+ while (*opcl)
+ {
+ if ((*opcl)->t == web)
+ {
+ owl = *opcl;
+ *opcl = owl->next;
+ break;
+ }
+ else
+ {
+ opcl = &((*opcl)->next);
+ }
+ }
+ if (!owl && other->type != PRECOLORED)
+ abort ();
+ /* wl and owl contain the edge data to be deleted. */
+ RESET_BIT (sup_igraph, web->id * num_webs + other->id);
+ RESET_BIT (sup_igraph, other->id * num_webs + web->id);
+ RESET_BIT (igraph, igraph_index (web->id, other->id));
+ for (sl = wl->sub; sl; sl = sl->next)
+ RESET_BIT (igraph, igraph_index (sl->s->id, sl->t->id));
+ if (other->type != PRECOLORED)
+ {
+ for (sl = owl->sub; sl; sl = sl->next)
+ RESET_BIT (igraph, igraph_index (sl->s->id, sl->t->id));
+ }
+ }
+ }
+
+ /* We must restore usable_regs because record_conflict will use it. */
+ COPY_HARD_REG_SET (web->usable_regs, web->orig_usable_regs);
+ /* We might have deleted some conflicts above, which really are still
+ there (diamond pattern coalescing). This is because we don't reference
+ count interference edges but some of them were the result of different
+ coalesces. */
+ for (wl = web->conflict_list; wl; wl = wl->next)
+ if (wl->t->type == COALESCED)
+ {
+ struct web *tweb;
+ for (tweb = wl->t->alias; tweb; tweb = tweb->alias)
+ {
+ if (wl->sub == NULL)
+ record_conflict (web, tweb);
+ else
+ {
+ struct sub_conflict *sl;
+ for (sl = wl->sub; sl; sl = sl->next)
+ {
+ struct web *sweb = NULL;
+ if (SUBWEB_P (sl->t))
+ sweb = find_subweb (tweb, sl->t->orig_x);
+ if (!sweb)
+ sweb = tweb;
+ record_conflict (sl->s, sweb);
+ }
+ }
+ if (tweb->type != COALESCED)
+ break;
+ }
+ }
+}
+
+/* Repeatedly break aliases for spilled webs, which were target for
+ coalescing, and recolorize the resulting parts. Do this as long as
+ there are any spilled coalesce targets. */
+
+static void
+break_coalesced_spills ()
+{
+ int changed = 0;
+ while (1)
+ {
+ struct dlist *d;
+ struct web *web;
+ for (d = WEBS(SPILLED); d; d = d->next)
+ if (DLIST_WEB (d)->is_coalesced)
+ break;
+ if (!d)
+ break;
+ changed = 1;
+ web = DLIST_WEB (d);
+ ra_debug_msg (DUMP_COLORIZE, "breaking aliases to web %d:", web->id);
+ restore_conflicts_from_coalesce (web);
+ break_aliases_to_web (web);
+ /* WEB was a spilled web and isn't anymore. Everything coalesced
+ to WEB is now SELECTed and might potentially get a color.
+ If those other webs were itself targets of coalescing it might be
+ that there are still some conflicts from aliased webs missing,
+ because they were added in combine() right into the now
+ SELECTed web. So we need to add those missing conflicts here. */
+ insert_coalesced_conflicts ();
+ ra_debug_msg (DUMP_COLORIZE, "\n");
+ remove_list (d, &WEBS(SPILLED));
+ put_web (web, SELECT);
+ web->color = -1;
+ while (WEBS(SELECT))
+ {
+ d = pop_list (&WEBS(SELECT));
+ colorize_one_web (DLIST_WEB (d), 1);
+ }
+ }
+ if (changed)
+ {
+ struct dlist *d;
+ for (d = WEBS(COALESCED); d; d = d->next)
+ {
+ struct web *a = alias (DLIST_WEB (d));
+ DLIST_WEB (d)->color = a->color;
+ }
+ }
+ dump_graph_cost (DUMP_COSTS, "after alias-breaking");
+}
+
+/* A structure for fast hashing of a pair of webs.
+ Used to cumulate savings (from removing copy insns) for coalesced webs.
+ All the pairs are also put into a single linked list. */
+struct web_pair
+{
+ struct web_pair *next_hash;
+ struct web_pair *next_list;
+ struct web *smaller;
+ struct web *larger;
+ unsigned int conflicts;
+ unsigned HOST_WIDE_INT cost;
+};
+
+/* The actual hash table. */
+#define WEB_PAIR_HASH_SIZE 8192
+static struct web_pair *web_pair_hash[WEB_PAIR_HASH_SIZE];
+static struct web_pair *web_pair_list;
+static unsigned int num_web_pairs;
+
+/* Clear the hash table of web pairs. */
+
+static void
+init_web_pairs ()
+{
+ memset (web_pair_hash, 0, sizeof web_pair_hash);
+ num_web_pairs = 0;
+ web_pair_list = NULL;
+}
+
+/* Given two webs connected by a move with cost COST which together
+ have CONFLICTS conflicts, add that pair to the hash table, or if
+ already in, cumulate the costs and conflict number. */
+
+static void
+add_web_pair_cost (web1, web2, cost, conflicts)
+ struct web *web1, *web2;
+ unsigned HOST_WIDE_INT cost;
+ unsigned int conflicts;
+{
+ unsigned int hash;
+ struct web_pair *p;
+ if (web1->id > web2->id)
+ {
+ struct web *h = web1;
+ web1 = web2;
+ web2 = h;
+ }
+ hash = (web1->id * num_webs + web2->id) % WEB_PAIR_HASH_SIZE;
+ for (p = web_pair_hash[hash]; p; p = p->next_hash)
+ if (p->smaller == web1 && p->larger == web2)
+ {
+ p->cost += cost;
+ p->conflicts += conflicts;
+ return;
+ }
+ p = (struct web_pair *) ra_alloc (sizeof *p);
+ p->next_hash = web_pair_hash[hash];
+ p->next_list = web_pair_list;
+ p->smaller = web1;
+ p->larger = web2;
+ p->conflicts = conflicts;
+ p->cost = cost;
+ web_pair_hash[hash] = p;
+ web_pair_list = p;
+ num_web_pairs++;
+}
+
+/* Suitable to be passed to qsort(). Sort web pairs so, that those
+ with more conflicts and higher cost (which actually is a saving
+ when the moves are removed) come first. */
+
+static int
+comp_web_pairs (w1, w2)
+ const void *w1, *w2;
+{
+ struct web_pair *p1 = *(struct web_pair **)w1;
+ struct web_pair *p2 = *(struct web_pair **)w2;
+ if (p1->conflicts > p2->conflicts)
+ return -1;
+ else if (p1->conflicts < p2->conflicts)
+ return 1;
+ else if (p1->cost > p2->cost)
+ return -1;
+ else if (p1->cost < p2->cost)
+ return 1;
+ else
+ return 0;
+}
+
+/* Given the list of web pairs, begin to combine them from the one
+ with the most savings. */
+
+static void
+sort_and_combine_web_pairs (for_move)
+ int for_move;
+{
+ unsigned int i;
+ struct web_pair **sorted;
+ struct web_pair *p;
+ if (!num_web_pairs)
+ return;
+ sorted = (struct web_pair **) xmalloc (num_web_pairs * sizeof (sorted[0]));
+ for (p = web_pair_list, i = 0; p; p = p->next_list)
+ sorted[i++] = p;
+ if (i != num_web_pairs)
+ abort ();
+ qsort (sorted, num_web_pairs, sizeof (sorted[0]), comp_web_pairs);
+
+ /* After combining one pair, we actually should adjust the savings
+ of the other pairs, if they are connected to one of the just coalesced
+ pair. Later. */
+ for (i = 0; i < num_web_pairs; i++)
+ {
+ struct web *w1, *w2;
+ p = sorted[i];
+ w1 = alias (p->smaller);
+ w2 = alias (p->larger);
+ if (!for_move && (w1->type == PRECOLORED || w2->type == PRECOLORED))
+ continue;
+ else if (w2->type == PRECOLORED)
+ {
+ struct web *h = w1;
+ w1 = w2;
+ w2 = h;
+ }
+ if (w1 != w2
+ && !TEST_BIT (sup_igraph, w1->id * num_webs + w2->id)
+ && !TEST_BIT (sup_igraph, w2->id * num_webs + w1->id)
+ && w2->type != PRECOLORED
+ && hard_regs_intersect_p (&w1->usable_regs, &w2->usable_regs))
+ {
+ if (w1->type != PRECOLORED
+ || (w1->type == PRECOLORED && ok (w2, w1)))
+ combine (w1, w2);
+ else if (w1->type == PRECOLORED)
+ SET_HARD_REG_BIT (w2->prefer_colors, w1->color);
+ }
+ }
+ free (sorted);
+}
+
+/* Greedily coalesce all moves possible. Begin with the web pair
+ giving the most saving if coalesced. */
+
+static void
+aggressive_coalesce ()
+{
+ struct dlist *d;
+ struct move *m;
+ init_web_pairs ();
+ while ((d = pop_list (&mv_worklist)) != NULL)
+ if ((m = DLIST_MOVE (d)))
+ {
+ struct web *s = alias (m->source_web);
+ struct web *t = alias (m->target_web);
+ if (t->type == PRECOLORED)
+ {
+ struct web *h = s;
+ s = t;
+ t = h;
+ }
+ if (s != t
+ && t->type != PRECOLORED
+ && !TEST_BIT (sup_igraph, s->id * num_webs + t->id)
+ && !TEST_BIT (sup_igraph, t->id * num_webs + s->id))
+ {
+ if ((s->type == PRECOLORED && ok (t, s))
+ || s->type != PRECOLORED)
+ {
+ put_move (m, MV_COALESCED);
+ add_web_pair_cost (s, t, BLOCK_FOR_INSN (m->insn)->frequency,
+ 0);
+ }
+ else if (s->type == PRECOLORED)
+ /* It is !ok(t, s). But later when coloring the graph it might
+ be possible to take that color. So we remember the preferred
+ color to try that first. */
+ {
+ put_move (m, CONSTRAINED);
+ SET_HARD_REG_BIT (t->prefer_colors, s->color);
+ }
+ }
+ else
+ {
+ put_move (m, CONSTRAINED);
+ }
+ }
+ sort_and_combine_web_pairs (1);
+}
+
+/* This is the difference between optimistic coalescing and
+ optimistic coalescing+. Extended coalesce tries to coalesce also
+ non-conflicting nodes, not related by a move. The criteria here is,
+ the one web must be a source, the other a destination of the same insn.
+ This actually makes sense, as (because they are in the same insn) they
+ share many of their neighbors, and if they are coalesced, reduce the
+ number of conflicts of those neighbors by one. For this we sort the
+ candidate pairs again according to savings (and this time also conflict
+ number).
+
+ This is also a comparatively slow operation, as we need to go through
+ all insns, and for each insn, through all defs and uses. */
+
+static void
+extended_coalesce_2 ()
+{
+ rtx insn;
+ struct ra_insn_info info;
+ unsigned int n;
+ init_web_pairs ();
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (INSN_P (insn) && (info = insn_df[INSN_UID (insn)]).num_defs)
+ for (n = 0; n < info.num_defs; n++)
+ {
+ struct web *dest = def2web[DF_REF_ID (info.defs[n])];
+ dest = alias (find_web_for_subweb (dest));
+ if (dest->type != PRECOLORED && dest->regno < max_normal_pseudo)
+ {
+ unsigned int n2;
+ for (n2 = 0; n2 < info.num_uses; n2++)
+ {
+ struct web *source = use2web[DF_REF_ID (info.uses[n2])];
+ source = alias (find_web_for_subweb (source));
+ if (source->type != PRECOLORED
+ && source != dest
+ && source->regno < max_normal_pseudo
+ /* Coalesced webs end up using the same REG rtx in
+ emit_colors(). So we can only coalesce something
+ of equal modes. */
+ && GET_MODE (source->orig_x) == GET_MODE (dest->orig_x)
+ && !TEST_BIT (sup_igraph,
+ dest->id * num_webs + source->id)
+ && !TEST_BIT (sup_igraph,
+ source->id * num_webs + dest->id)
+ && hard_regs_intersect_p (&source->usable_regs,
+ &dest->usable_regs))
+ add_web_pair_cost (dest, source,
+ BLOCK_FOR_INSN (insn)->frequency,
+ dest->num_conflicts
+ + source->num_conflicts);
+ }
+ }
+ }
+ sort_and_combine_web_pairs (0);
+}
+
+/* Check if we forgot to coalesce some moves. */
+
+static void
+check_uncoalesced_moves ()
+{
+ struct move_list *ml;
+ struct move *m;
+ for (ml = wl_moves; ml; ml = ml->next)
+ if ((m = ml->move))
+ {
+ struct web *s = alias (m->source_web);
+ struct web *t = alias (m->target_web);
+ if (t->type == PRECOLORED)
+ {
+ struct web *h = s;
+ s = t;
+ t = h;
+ }
+ if (s != t
+ && m->type != CONSTRAINED
+ /* Following can happen when a move was coalesced, but later
+ broken up again. Then s!=t, but m is still MV_COALESCED. */
+ && m->type != MV_COALESCED
+ && t->type != PRECOLORED
+ && ((s->type == PRECOLORED && ok (t, s))
+ || s->type != PRECOLORED)
+ && !TEST_BIT (sup_igraph, s->id * num_webs + t->id)
+ && !TEST_BIT (sup_igraph, t->id * num_webs + s->id))
+ abort ();
+ }
+}
+
+/* The toplevel function in this file. Precondition is, that
+ the interference graph is built completely by ra-build.c. This
+ produces a list of spilled, colored and coalesced nodes. */
+
+void
+ra_colorize_graph (df)
+ struct df *df;
+{
+ if (rtl_dump_file)
+ dump_igraph (df);
+ build_worklists (df);
+
+ /* With optimistic coalescing we coalesce everything we can. */
+ if (flag_ra_optimistic_coalescing)
+ {
+ aggressive_coalesce ();
+ extended_coalesce_2 ();
+ }
+
+ /* Now build the select stack. */
+ do
+ {
+ simplify ();
+ if (mv_worklist)
+ coalesce ();
+ else if (WEBS(FREEZE))
+ freeze ();
+ else if (WEBS(SPILL))
+ select_spill ();
+ }
+ while (WEBS(SIMPLIFY) || WEBS(SIMPLIFY_FAT) || WEBS(SIMPLIFY_SPILL)
+ || mv_worklist || WEBS(FREEZE) || WEBS(SPILL));
+ if (flag_ra_optimistic_coalescing)
+ check_uncoalesced_moves ();
+
+ /* Actually colorize the webs from the select stack. */
+ assign_colors ();
+ check_colors ();
+ dump_graph_cost (DUMP_COSTS, "initially");
+ if (flag_ra_break_aliases)
+ break_coalesced_spills ();
+ check_colors ();
+
+ /* And try to improve the cost by recoloring spilled webs. */
+ recolor_spills ();
+ dump_graph_cost (DUMP_COSTS, "after spill-recolor");
+ check_colors ();
+}
+
+/* Initialize this module. */
+
+void ra_colorize_init ()
+{
+ /* FIXME: Choose spill heuristic for platform if we have one */
+ spill_heuristic = default_spill_heuristic;
+}
+
+/* Free all memory. (Note that we don't need to free any per pass
+ memory). */
+
+void
+ra_colorize_free_all ()
+{
+ struct dlist *d;
+ while ((d = pop_list (&WEBS(FREE))) != NULL)
+ put_web (DLIST_WEB (d), INITIAL);
+ while ((d = pop_list (&WEBS(INITIAL))) != NULL)
+ {
+ struct web *web =DLIST_WEB (d);
+ struct web *wnext;
+ web->orig_conflict_list = NULL;
+ web->conflict_list = NULL;
+ for (web = web->subreg_next; web; web = wnext)
+ {
+ wnext = web->subreg_next;
+ free (web);
+ }
+ free (DLIST_WEB (d));
+ }
+}
+
+/*
+vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
+*/
diff --git a/contrib/gcc/ra-debug.c b/contrib/gcc/ra-debug.c
new file mode 100644
index 0000000..8daa63d
--- /dev/null
+++ b/contrib/gcc/ra-debug.c
@@ -0,0 +1,1120 @@
+/* Graph coloring register allocator
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Contributed by Michael Matz <matz@suse.de>
+ and Daniel Berlin <dan@cgsoftware.com>.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along
+ with GCC; see the file COPYING. If not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "rtl.h"
+#include "insn-config.h"
+#include "recog.h"
+#include "function.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
+#include "df.h"
+#include "output.h"
+#include "ra.h"
+#include "tm_p.h"
+
+/* This file contains various dumping and debug functions for
+ the graph coloring register allocator. */
+
+static void ra_print_rtx_1op PARAMS ((FILE *, rtx));
+static void ra_print_rtx_2op PARAMS ((FILE *, rtx));
+static void ra_print_rtx_3op PARAMS ((FILE *, rtx));
+static void ra_print_rtx_object PARAMS ((FILE *, rtx));
+
+/* The hardregs as names, for debugging. */
+static const char *const reg_class_names[] = REG_CLASS_NAMES;
+
+/* Print a message to the dump file, if debug_new_regalloc and LEVEL
+ have any bits in common. */
+
+void
+ra_debug_msg VPARAMS ((unsigned int level, const char *format, ...))
+{
+ VA_OPEN (ap, format);
+ VA_FIXEDARG (ap, unsigned int, level);
+ VA_FIXEDARG (ap, const char *, format);
+ if ((debug_new_regalloc & level) != 0 && rtl_dump_file != NULL)
+ vfprintf (rtl_dump_file, format, ap);
+ VA_CLOSE (ap);
+}
+
+
+/* The following ra_print_xxx() functions print RTL expressions
+ in concise infix form. If the mode can be seen from context it's
+ left out. Most operators are represented by their graphical
+ characters, e.g. LE as "<=". Unknown constructs are currently
+ printed with print_inline_rtx(), which disrupts the nice layout.
+ Currently only the inline asm things are written this way. */
+
+/* Print rtx X, which is a one operand rtx (op:mode (Y)), as
+ "op(Y)" to FILE. */
+
+static void
+ra_print_rtx_1op (file, x)
+ FILE *file;
+ rtx x;
+{
+ enum rtx_code code = GET_CODE (x);
+ rtx op0 = XEXP (x, 0);
+ switch (code)
+ {
+ case NEG:
+ case NOT:
+ fputs ((code == NEG) ? "-(" : "~(", file);
+ ra_print_rtx (file, op0, 0);
+ fputs (")", file);
+ break;
+ case HIGH:
+ fputs ("hi(", file);
+ ra_print_rtx (file, op0, 0);
+ fputs (")", file);
+ break;
+ default:
+ fprintf (file, "%s", GET_RTX_NAME (code));
+ if (GET_MODE (x) != VOIDmode)
+ fprintf (file, ":%s(", GET_MODE_NAME (GET_MODE (x)));
+ else
+ fputs ("(", file);
+ ra_print_rtx (file, op0, 0);
+ fputs (")", file);
+ break;
+ }
+}
+
+/* Print rtx X, which is a two operand rtx (op:mode (Y) (Z))
+ as "(Y op Z)", if the operand is know, or as "op(Y, Z)", if not,
+ to FILE. */
+
+static void
+ra_print_rtx_2op (file, x)
+ FILE *file;
+ rtx x;
+{
+ int infix = 1;
+ const char *opname = "shitop";
+ enum rtx_code code = GET_CODE (x);
+ rtx op0 = XEXP (x, 0);
+ rtx op1 = XEXP (x, 1);
+ switch (code)
+ {
+ /* class '2' */
+ case COMPARE: opname = "?"; break;
+ case MINUS: opname = "-"; break;
+ case DIV: opname = "/"; break;
+ case UDIV: opname = "u/"; break;
+ case MOD: opname = "%"; break;
+ case UMOD: opname = "u%"; break;
+ case ASHIFT: opname = "<<"; break;
+ case ASHIFTRT: opname = "a>>"; break;
+ case LSHIFTRT: opname = "l>>"; break;
+ /* class 'c' */
+ case PLUS: opname = "+"; break;
+ case MULT: opname = "*"; break;
+ case AND: opname = "&"; break;
+ case IOR: opname = "|"; break;
+ case XOR: opname = "^"; break;
+ /* class '<' */
+ case NE: opname = "!="; break;
+ case EQ: opname = "=="; break;
+ case GE: opname = "s>="; break;
+ case GT: opname = "s>"; break;
+ case LE: opname = "s<="; break;
+ case LT: opname = "s<"; break;
+ case GEU: opname = "u>="; break;
+ case GTU: opname = "u>"; break;
+ case LEU: opname = "u<="; break;
+ case LTU: opname = "u<"; break;
+ default:
+ infix = 0;
+ opname = GET_RTX_NAME (code);
+ break;
+ }
+ if (infix)
+ {
+ fputs ("(", file);
+ ra_print_rtx (file, op0, 0);
+ fprintf (file, " %s ", opname);
+ ra_print_rtx (file, op1, 0);
+ fputs (")", file);
+ }
+ else
+ {
+ fprintf (file, "%s(", opname);
+ ra_print_rtx (file, op0, 0);
+ fputs (", ", file);
+ ra_print_rtx (file, op1, 0);
+ fputs (")", file);
+ }
+}
+
+/* Print rtx X, which a three operand rtx to FILE.
+ I.e. X is either an IF_THEN_ELSE, or a bitmap operation. */
+
+static void
+ra_print_rtx_3op (file, x)
+ FILE *file;
+ rtx x;
+{
+ enum rtx_code code = GET_CODE (x);
+ rtx op0 = XEXP (x, 0);
+ rtx op1 = XEXP (x, 1);
+ rtx op2 = XEXP (x, 2);
+ if (code == IF_THEN_ELSE)
+ {
+ ra_print_rtx (file, op0, 0);
+ fputs (" ? ", file);
+ ra_print_rtx (file, op1, 0);
+ fputs (" : ", file);
+ ra_print_rtx (file, op2, 0);
+ }
+ else
+ {
+ /* Bitmap-operation */
+ fprintf (file, "%s:%s(", GET_RTX_NAME (code),
+ GET_MODE_NAME (GET_MODE (x)));
+ ra_print_rtx (file, op0, 0);
+ fputs (", ", file);
+ ra_print_rtx (file, op1, 0);
+ fputs (", ", file);
+ ra_print_rtx (file, op2, 0);
+ fputs (")", file);
+ }
+}
+
+/* Print rtx X, which represents an object (class 'o' or some constructs
+ of class 'x' (e.g. subreg)), to FILE.
+ (reg XX) rtl is represented as "pXX", of XX was a pseudo,
+ as "name" it name is the nonnull hardreg name, or as "hXX", if XX
+ is a hardreg, whose name is NULL, or empty. */
+
+static void
+ra_print_rtx_object (file, x)
+ FILE *file;
+ rtx x;
+{
+ enum rtx_code code = GET_CODE (x);
+ enum machine_mode mode = GET_MODE (x);
+ switch (code)
+ {
+ case CONST_INT:
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, XWINT (x, 0));
+ break;
+ case CONST_DOUBLE:
+ {
+ int i, num = 0;
+ const char *fmt = GET_RTX_FORMAT (code);
+ fputs ("dbl(", file);
+ for (i = 0; i < GET_RTX_LENGTH (code); i++)
+ {
+ if (num)
+ fputs (", ", file);
+ if (fmt[i] == 'e' && XEXP (x, i))
+ /* The MEM or other stuff */
+ {
+ ra_print_rtx (file, XEXP (x, i), 0);
+ num++;
+ }
+ else if (fmt[i] == 'w')
+ {
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, XWINT (x, i));
+ num++;
+ }
+ }
+ break;
+ }
+ case CONST_STRING: fprintf (file, "\"%s\"", XSTR (x, 0)); break;
+ case CONST: fputs ("const(", file);
+ ra_print_rtx (file, XEXP (x, 0), 0);
+ fputs (")", file);
+ break;
+ case PC: fputs ("pc", file); break;
+ case REG:
+ {
+ int regno = REGNO (x);
+ if (regno < FIRST_PSEUDO_REGISTER)
+ {
+ int i, nregs = HARD_REGNO_NREGS (regno, mode);
+ if (nregs > 1)
+ fputs ("[", file);
+ for (i = 0; i < nregs; i++)
+ {
+ if (i)
+ fputs (", ", file);
+ if (reg_names[regno+i] && *reg_names[regno + i])
+ fprintf (file, "%s", reg_names[regno + i]);
+ else
+ fprintf (file, "h%d", regno + i);
+ }
+ if (nregs > 1)
+ fputs ("]", file);
+ }
+ else
+ fprintf (file, "p%d", regno);
+ break;
+ }
+ case SUBREG:
+ {
+ rtx sub = SUBREG_REG (x);
+ int ofs = SUBREG_BYTE (x);
+ if (GET_CODE (sub) == REG
+ && REGNO (sub) < FIRST_PSEUDO_REGISTER)
+ {
+ int regno = REGNO (sub);
+ int i, nregs = HARD_REGNO_NREGS (regno, mode);
+ regno += subreg_regno_offset (regno, GET_MODE (sub),
+ ofs, mode);
+ if (nregs > 1)
+ fputs ("[", file);
+ for (i = 0; i < nregs; i++)
+ {
+ if (i)
+ fputs (", ", file);
+ if (reg_names[regno+i])
+ fprintf (file, "%s", reg_names[regno + i]);
+ else
+ fprintf (file, "h%d", regno + i);
+ }
+ if (nregs > 1)
+ fputs ("]", file);
+ }
+ else
+ {
+ ra_print_rtx (file, sub, 0);
+ fprintf (file, ":[%s+%d]", GET_MODE_NAME (mode), ofs);
+ }
+ break;
+ }
+ case SCRATCH: fputs ("scratch", file); break;
+ case CONCAT: ra_print_rtx_2op (file, x); break;
+ case HIGH: ra_print_rtx_1op (file, x); break;
+ case LO_SUM:
+ fputs ("(", file);
+ ra_print_rtx (file, XEXP (x, 0), 0);
+ fputs (" + lo(", file);
+ ra_print_rtx (file, XEXP (x, 1), 0);
+ fputs ("))", file);
+ break;
+ case MEM: fputs ("[", file);
+ ra_print_rtx (file, XEXP (x, 0), 0);
+ fprintf (file, "]:%s", GET_MODE_NAME (GET_MODE (x)));
+ /* XXX print alias set too ?? */
+ break;
+ case LABEL_REF:
+ {
+ rtx sub = XEXP (x, 0);
+ if (GET_CODE (sub) == NOTE
+ && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
+ fprintf (file, "(deleted uid=%d)", INSN_UID (sub));
+ else if (GET_CODE (sub) == CODE_LABEL)
+ fprintf (file, "L%d", CODE_LABEL_NUMBER (sub));
+ else
+ fprintf (file, "(nonlabel uid=%d)", INSN_UID (sub));
+ }
+ break;
+ case SYMBOL_REF:
+ fprintf (file, "sym(\"%s\")", XSTR (x, 0)); break;
+ case CC0: fputs ("cc0", file); break;
+ default: print_inline_rtx (file, x, 0); break;
+ }
+}
+
+/* Print a general rtx X to FILE in nice infix form.
+ If WITH_PN is set, and X is one of the toplevel constructs
+ (insns, notes, labels or barriers), then print also the UIDs of
+ the preceding and following insn. */
+
+void
+ra_print_rtx (file, x, with_pn)
+ FILE *file;
+ rtx x;
+ int with_pn;
+{
+ enum rtx_code code;
+ char class;
+ int unhandled = 0;
+ if (!x)
+ return;
+ code = GET_CODE (x);
+ class = GET_RTX_CLASS (code);
+
+ /* First handle the insn like constructs. */
+ if (INSN_P (x) || code == NOTE || code == CODE_LABEL || code == BARRIER)
+ {
+ if (INSN_P (x))
+ fputs (" ", file);
+ /* Non-insns are prefixed by a ';'. */
+ if (code == BARRIER)
+ fputs ("; ", file);
+ else if (code == NOTE)
+ /* But notes are indented very far right. */
+ fprintf (file, "\t\t\t\t\t; ");
+ else if (code == CODE_LABEL)
+ /* And labels have their Lxx name first, before the actual UID. */
+ {
+ fprintf (file, "L%d:\t; ", CODE_LABEL_NUMBER (x));
+ if (LABEL_NAME (x))
+ fprintf (file, "(%s) ", LABEL_NAME (x));
+ switch (LABEL_KIND (x))
+ {
+ case LABEL_NORMAL: break;
+ case LABEL_STATIC_ENTRY: fputs (" (entry)", file); break;
+ case LABEL_GLOBAL_ENTRY: fputs (" (global entry)", file); break;
+ case LABEL_WEAK_ENTRY: fputs (" (weak entry)", file); break;
+ default: abort();
+ }
+ fprintf (file, " [%d uses] uid=(", LABEL_NUSES (x));
+ }
+ fprintf (file, "%d", INSN_UID (x));
+ if (with_pn)
+ fprintf (file, " %d %d", PREV_INSN (x) ? INSN_UID (PREV_INSN (x)) : 0,
+ NEXT_INSN (x) ? INSN_UID (NEXT_INSN (x)) : 0);
+ if (code == BARRIER)
+ fputs (" -------- barrier ---------", file);
+ else if (code == CODE_LABEL)
+ fputs (")", file);
+ else if (code == NOTE)
+ {
+ int ln = NOTE_LINE_NUMBER (x);
+ if (ln >= (int) NOTE_INSN_BIAS && ln < (int) NOTE_INSN_MAX)
+ fprintf (file, " %s", GET_NOTE_INSN_NAME (ln));
+ else
+ {
+ fprintf (file, " line %d", ln);
+ if (NOTE_SOURCE_FILE (x))
+ fprintf (file, ":%s", NOTE_SOURCE_FILE (x));
+ }
+ }
+ else
+ {
+ fprintf (file, "\t");
+ ra_print_rtx (file, PATTERN (x), 0);
+ }
+ return;
+ }
+ switch (code)
+ {
+ /* Top-level stuff. */
+ case PARALLEL:
+ {
+ int j;
+ for (j = 0; j < XVECLEN (x, 0); j++)
+ {
+ if (j)
+ fputs ("\t;; ", file);
+ ra_print_rtx (file, XVECEXP (x, 0, j), 0);
+ }
+ break;
+ }
+ case UNSPEC: case UNSPEC_VOLATILE:
+ {
+ int j;
+ fprintf (file, "unspec%s(%d",
+ (code == UNSPEC) ? "" : "_vol", XINT (x, 1));
+ for (j = 0; j < XVECLEN (x, 0); j++)
+ {
+ fputs (", ", file);
+ ra_print_rtx (file, XVECEXP (x, 0, j), 0);
+ }
+ fputs (")", file);
+ break;
+ }
+ case SET:
+ if (GET_CODE (SET_DEST (x)) == PC)
+ {
+ if (GET_CODE (SET_SRC (x)) == IF_THEN_ELSE
+ && GET_CODE (XEXP (SET_SRC(x), 2)) == PC)
+ {
+ fputs ("if ", file);
+ ra_print_rtx (file, XEXP (SET_SRC (x), 0), 0);
+ fputs (" jump ", file);
+ ra_print_rtx (file, XEXP (SET_SRC (x), 1), 0);
+ }
+ else
+ {
+ fputs ("jump ", file);
+ ra_print_rtx (file, SET_SRC (x), 0);
+ }
+ }
+ else
+ {
+ ra_print_rtx (file, SET_DEST (x), 0);
+ fputs (" <= ", file);
+ ra_print_rtx (file, SET_SRC (x), 0);
+ }
+ break;
+ case USE:
+ fputs ("use <= ", file);
+ ra_print_rtx (file, XEXP (x, 0), 0);
+ break;
+ case CLOBBER:
+ ra_print_rtx (file, XEXP (x, 0), 0);
+ fputs (" <= clobber", file);
+ break;
+ case CALL:
+ fputs ("call ", file);
+ ra_print_rtx (file, XEXP (x, 0), 0); /* Address */
+ fputs (" numargs=", file);
+ ra_print_rtx (file, XEXP (x, 1), 0); /* Num arguments */
+ break;
+ case RETURN:
+ fputs ("return", file);
+ break;
+ case TRAP_IF:
+ fputs ("if (", file);
+ ra_print_rtx (file, XEXP (x, 0), 0);
+ fputs (") trap ", file);
+ ra_print_rtx (file, XEXP (x, 1), 0);
+ break;
+ case RESX:
+ fprintf (file, "resx from region %d", XINT (x, 0));
+ break;
+
+ /* Different things of class 'x' */
+ case SUBREG: ra_print_rtx_object (file, x); break;
+ case STRICT_LOW_PART:
+ fputs ("low(", file);
+ ra_print_rtx (file, XEXP (x, 0), 0);
+ fputs (")", file);
+ break;
+ default:
+ unhandled = 1;
+ break;
+ }
+ if (!unhandled)
+ return;
+ if (class == '1')
+ ra_print_rtx_1op (file, x);
+ else if (class == '2' || class == 'c' || class == '<')
+ ra_print_rtx_2op (file, x);
+ else if (class == '3' || class == 'b')
+ ra_print_rtx_3op (file, x);
+ else if (class == 'o')
+ ra_print_rtx_object (file, x);
+ else
+ print_inline_rtx (file, x, 0);
+}
+
+/* This only calls ra_print_rtx(), but emits a final newline. */
+
+void
+ra_print_rtx_top (file, x, with_pn)
+ FILE *file;
+ rtx x;
+ int with_pn;
+{
+ ra_print_rtx (file, x, with_pn);
+ fprintf (file, "\n");
+}
+
+/* Callable from gdb. This prints rtx X onto stderr. */
+
+void
+ra_debug_rtx (x)
+ rtx x;
+{
+ ra_print_rtx_top (stderr, x, 1);
+}
+
+/* This prints the content of basic block with index BBI.
+ The first and last insn are emitted with UIDs of prev and next insns. */
+
+void
+ra_debug_bbi (bbi)
+ int bbi;
+{
+ basic_block bb = BASIC_BLOCK (bbi);
+ rtx insn;
+ for (insn = bb->head; insn; insn = NEXT_INSN (insn))
+ {
+ ra_print_rtx_top (stderr, insn, (insn == bb->head || insn == bb->end));
+ fprintf (stderr, "\n");
+ if (insn == bb->end)
+ break;
+ }
+}
+
+/* Beginning from INSN, emit NUM insns (if NUM is non-negative)
+ or emit a window of NUM insns around INSN, to stderr. */
+
+void
+ra_debug_insns (insn, num)
+ rtx insn;
+ int num;
+{
+ int i, count = (num == 0 ? 1 : num < 0 ? -num : num);
+ if (num < 0)
+ for (i = count / 2; i > 0 && PREV_INSN (insn); i--)
+ insn = PREV_INSN (insn);
+ for (i = count; i > 0 && insn; insn = NEXT_INSN (insn), i--)
+ {
+ if (GET_CODE (insn) == CODE_LABEL)
+ fprintf (stderr, "\n");
+ ra_print_rtx_top (stderr, insn, (i == count || i == 1));
+ }
+}
+
+/* Beginning with INSN, emit the whole insn chain into FILE.
+ This also outputs comments when basic blocks start or end and omits
+ some notes, if flag_ra_dump_notes is zero. */
+
+void
+ra_print_rtl_with_bb (file, insn)
+ FILE *file;
+ rtx insn;
+{
+ basic_block last_bb, bb;
+ unsigned int num = 0;
+ if (!insn)
+ fputs ("nil", file);
+ last_bb = NULL;
+ for (; insn; insn = NEXT_INSN (insn))
+ {
+ if (GET_CODE (insn) == BARRIER)
+ bb = NULL;
+ else
+ bb = BLOCK_FOR_INSN (insn);
+ if (bb != last_bb)
+ {
+ if (last_bb)
+ fprintf (file, ";; End of basic block %d\n", last_bb->index);
+ if (bb)
+ fprintf (file, ";; Begin of basic block %d\n", bb->index);
+ last_bb = bb;
+ }
+ if (GET_CODE (insn) == CODE_LABEL)
+ fputc ('\n', file);
+ if (GET_CODE (insn) == NOTE)
+ {
+ /* Ignore basic block and maybe other notes not referencing
+ deleted things. */
+ if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
+ && (flag_ra_dump_notes
+ || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED
+ || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
+ {
+ ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
+ num++;
+ }
+ }
+ else
+ {
+ ra_print_rtx_top (file, insn, (num == 0 || !NEXT_INSN (insn)));
+ num++;
+ }
+ }
+}
+
+/* Count how many insns were seen how often, while building the interference
+ graph, and prints the findings. */
+
+void
+dump_number_seen ()
+{
+#define N 17
+ int num[N];
+ int i;
+
+ for (i = 0; i < N; i++)
+ num[i] = 0;
+ for (i = 0; i < get_max_uid (); i++)
+ if (number_seen[i] < N - 1)
+ num[number_seen[i]]++;
+ else
+ num[N - 1]++;
+ for (i = 0; i < N - 1; i++)
+ if (num[i])
+ ra_debug_msg (DUMP_PROCESS, "%d insns seen %d times\n", num[i], i);
+ if (num[N - 1])
+ ra_debug_msg (DUMP_PROCESS, "%d insns seen %d and more times\n", num[i],
+ N - 1);
+ ra_debug_msg (DUMP_PROCESS, "from overall %d insns\n", get_max_uid ());
+#undef N
+}
+
+/* Dump the interference graph, the move list and the webs. */
+
+void
+dump_igraph (df)
+ struct df *df ATTRIBUTE_UNUSED;
+{
+ struct move_list *ml;
+ unsigned int def1, def2;
+ int num = 0;
+ int num2;
+ unsigned int i;
+ if (!rtl_dump_file || (debug_new_regalloc & (DUMP_IGRAPH | DUMP_WEBS)) == 0)
+ return;
+ ra_debug_msg (DUMP_IGRAPH, "conflicts:\n ");
+ for (def1 = 0; def1 < num_webs; def1++)
+ {
+ int num1 = num;
+ for (num2=0, def2 = 0; def2 < num_webs; def2++)
+ if (def1 != def2 && TEST_BIT (igraph, igraph_index (def1, def2)))
+ {
+ if (num1 == num)
+ {
+ if (SUBWEB_P (ID2WEB (def1)))
+ ra_debug_msg (DUMP_IGRAPH, "%d (SUBREG %d, %d) with ", def1,
+ ID2WEB (def1)->regno,
+ SUBREG_BYTE (ID2WEB (def1)->orig_x));
+ else
+ ra_debug_msg (DUMP_IGRAPH, "%d (REG %d) with ", def1,
+ ID2WEB (def1)->regno);
+ }
+ if ((num2 % 9) == 8)
+ ra_debug_msg (DUMP_IGRAPH, "\n ");
+ num++;
+ num2++;
+ if (SUBWEB_P (ID2WEB (def2)))
+ ra_debug_msg (DUMP_IGRAPH, "%d(%d,%d) ", def2, ID2WEB (def2)->regno,
+ SUBREG_BYTE (ID2WEB (def2)->orig_x));
+ else
+ ra_debug_msg (DUMP_IGRAPH, "%d(%d) ", def2, ID2WEB (def2)->regno);
+ }
+ if (num1 != num)
+ ra_debug_msg (DUMP_IGRAPH, "\n ");
+ }
+ ra_debug_msg (DUMP_IGRAPH, "\n");
+ for (ml = wl_moves; ml; ml = ml->next)
+ if (ml->move)
+ {
+ ra_debug_msg (DUMP_IGRAPH, "move: insn %d: Web %d <-- Web %d\n",
+ INSN_UID (ml->move->insn), ml->move->target_web->id,
+ ml->move->source_web->id);
+ }
+ ra_debug_msg (DUMP_WEBS, "\nWebs:\n");
+ for (i = 0; i < num_webs; i++)
+ {
+ struct web *web = ID2WEB (i);
+
+ ra_debug_msg (DUMP_WEBS, " %4d : regno %3d", i, web->regno);
+ if (SUBWEB_P (web))
+ {
+ ra_debug_msg (DUMP_WEBS, " sub %d", SUBREG_BYTE (web->orig_x));
+ ra_debug_msg (DUMP_WEBS, " par %d", find_web_for_subweb (web)->id);
+ }
+ ra_debug_msg (DUMP_WEBS, " +%d (span %d, cost ",
+ web->add_hardregs, web->span_deaths);
+ ra_debug_msg (DUMP_WEBS, HOST_WIDE_INT_PRINT_DEC, web->spill_cost);
+ ra_debug_msg (DUMP_WEBS, ") (%s)", reg_class_names[web->regclass]);
+ if (web->spill_temp == 1)
+ ra_debug_msg (DUMP_WEBS, " (spilltemp)");
+ else if (web->spill_temp == 2)
+ ra_debug_msg (DUMP_WEBS, " (spilltem2)");
+ else if (web->spill_temp == 3)
+ ra_debug_msg (DUMP_WEBS, " (short)");
+ if (web->type == PRECOLORED)
+ ra_debug_msg (DUMP_WEBS, " (precolored, color=%d)", web->color);
+ else if (find_web_for_subweb (web)->num_uses == 0)
+ ra_debug_msg (DUMP_WEBS, " dead");
+ if (web->crosses_call)
+ ra_debug_msg (DUMP_WEBS, " xcall");
+ if (web->regno >= max_normal_pseudo)
+ ra_debug_msg (DUMP_WEBS, " stack");
+ ra_debug_msg (DUMP_WEBS, "\n");
+ }
+}
+
+/* Dump the interference graph and webs in a format easily
+ parsable by programs. Used to emit real world interference graph
+ to my custom graph colorizer. */
+
+void
+dump_igraph_machine ()
+{
+ unsigned int i;
+
+ if (!rtl_dump_file || (debug_new_regalloc & DUMP_IGRAPH_M) == 0)
+ return;
+ ra_debug_msg (DUMP_IGRAPH_M, "g %d %d\n", num_webs - num_subwebs,
+ FIRST_PSEUDO_REGISTER);
+ for (i = 0; i < num_webs - num_subwebs; i++)
+ {
+ struct web *web = ID2WEB (i);
+ struct conflict_link *cl;
+ int flags = 0;
+ int numc = 0;
+ int col = 0;
+ flags = web->spill_temp & 0xF;
+ flags |= ((web->type == PRECOLORED) ? 1 : 0) << 4;
+ flags |= (web->add_hardregs & 0xF) << 5;
+ for (cl = web->conflict_list; cl; cl = cl->next)
+ if (cl->t->id < web->id)
+ numc++;
+ ra_debug_msg (DUMP_IGRAPH_M, "n %d %d %d %d %d %d %d\n",
+ web->id, web->color, flags,
+ (unsigned int)web->spill_cost, web->num_defs, web->num_uses,
+ numc);
+ if (web->type != PRECOLORED)
+ {
+ ra_debug_msg (DUMP_IGRAPH_M, "s %d", web->id);
+ while (1)
+ {
+ unsigned int u = 0;
+ int n;
+ for (n = 0; n < 32 && col < FIRST_PSEUDO_REGISTER; n++, col++)
+ if (TEST_HARD_REG_BIT (web->usable_regs, col))
+ u |= 1 << n;
+ ra_debug_msg (DUMP_IGRAPH_M, " %u", u);
+ if (col >= FIRST_PSEUDO_REGISTER)
+ break;
+ }
+ ra_debug_msg (DUMP_IGRAPH_M, "\n");
+ }
+ if (numc)
+ {
+ ra_debug_msg (DUMP_IGRAPH_M, "c %d", web->id);
+ for (cl = web->conflict_list; cl; cl = cl->next)
+ {
+ if (cl->t->id < web->id)
+ ra_debug_msg (DUMP_IGRAPH_M, " %d", cl->t->id);
+ }
+ ra_debug_msg (DUMP_IGRAPH_M, "\n");
+ }
+ }
+ ra_debug_msg (DUMP_IGRAPH_M, "e\n");
+}
+
+/* This runs after colorization and changing the insn stream.
+ It temporarily replaces all pseudo registers with their colors,
+ and emits information, if the resulting insns are strictly valid. */
+
+void
+dump_constraints ()
+{
+ rtx insn;
+ int i;
+ if (!rtl_dump_file || (debug_new_regalloc & DUMP_CONSTRAINTS) == 0)
+ return;
+ for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
+ if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
+ REGNO (regno_reg_rtx[i])
+ = ra_reg_renumber[i] >= 0 ? ra_reg_renumber[i] : i;
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ {
+ int code;
+ int uid = INSN_UID (insn);
+ int o;
+ /* Don't simply force rerecognition, as combine might left us
+ with some unrecongnizable ones, which later leads to aborts
+ in regclass, if we now destroy the remembered INSN_CODE(). */
+ /*INSN_CODE (insn) = -1;*/
+ code = recog_memoized (insn);
+ if (code < 0)
+ {
+ ra_debug_msg (DUMP_CONSTRAINTS,
+ "%d: asm insn or not recognizable.\n", uid);
+ continue;
+ }
+ ra_debug_msg (DUMP_CONSTRAINTS,
+ "%d: code %d {%s}, %d operands, constraints: ",
+ uid, code, insn_data[code].name, recog_data.n_operands);
+ extract_insn (insn);
+ /*preprocess_constraints ();*/
+ for (o = 0; o < recog_data.n_operands; o++)
+ {
+ ra_debug_msg (DUMP_CONSTRAINTS,
+ "%d:%s ", o, recog_data.constraints[o]);
+ }
+ if (constrain_operands (1))
+ ra_debug_msg (DUMP_CONSTRAINTS, "matches strictly alternative %d",
+ which_alternative);
+ else
+ ra_debug_msg (DUMP_CONSTRAINTS, "doesn't match strictly");
+ ra_debug_msg (DUMP_CONSTRAINTS, "\n");
+ }
+ for (i = FIRST_PSEUDO_REGISTER; i < ra_max_regno; i++)
+ if (regno_reg_rtx[i] && GET_CODE (regno_reg_rtx[i]) == REG)
+ REGNO (regno_reg_rtx[i]) = i;
+}
+
+/* This counts and emits the cumulated cost of all spilled webs,
+ preceded by a custom message MSG, with debug level LEVEL. */
+
+void
+dump_graph_cost (level, msg)
+ unsigned int level;
+ const char *msg;
+{
+ unsigned int i;
+ unsigned HOST_WIDE_INT cost;
+ if (!rtl_dump_file || (debug_new_regalloc & level) == 0)
+ return;
+
+ cost = 0;
+ for (i = 0; i < num_webs; i++)
+ {
+ struct web *web = id2web[i];
+ if (alias (web)->type == SPILLED)
+ cost += web->orig_spill_cost;
+ }
+ ra_debug_msg (level, " spill cost of graph (%s) = ", msg ? msg : "");
+ ra_debug_msg (level, HOST_WIDE_INT_PRINT_UNSIGNED, cost);
+ ra_debug_msg (level, "\n");
+}
+
+/* Dump the color assignment per web, the coalesced and spilled webs. */
+
+void
+dump_ra (df)
+ struct df *df ATTRIBUTE_UNUSED;
+{
+ struct web *web;
+ struct dlist *d;
+ if (!rtl_dump_file || (debug_new_regalloc & DUMP_RESULTS) == 0)
+ return;
+
+ ra_debug_msg (DUMP_RESULTS, "\nColored:\n");
+ for (d = WEBS(COLORED); d; d = d->next)
+ {
+ web = DLIST_WEB (d);
+ ra_debug_msg (DUMP_RESULTS, " %4d : color %d\n", web->id, web->color);
+ }
+ ra_debug_msg (DUMP_RESULTS, "\nCoalesced:\n");
+ for (d = WEBS(COALESCED); d; d = d->next)
+ {
+ web = DLIST_WEB (d);
+ ra_debug_msg (DUMP_RESULTS, " %4d : to web %d, color %d\n", web->id,
+ alias (web)->id, web->color);
+ }
+ ra_debug_msg (DUMP_RESULTS, "\nSpilled:\n");
+ for (d = WEBS(SPILLED); d; d = d->next)
+ {
+ web = DLIST_WEB (d);
+ ra_debug_msg (DUMP_RESULTS, " %4d\n", web->id);
+ }
+ ra_debug_msg (DUMP_RESULTS, "\n");
+ dump_cost (DUMP_RESULTS);
+}
+
+/* Calculate and dump the cumulated costs of certain types of insns
+ (loads, stores and copies). */
+
+void
+dump_static_insn_cost (file, message, prefix)
+ FILE *file;
+ const char *message;
+ const char *prefix;
+{
+ struct cost
+ {
+ unsigned HOST_WIDE_INT cost;
+ unsigned int count;
+ };
+ basic_block bb;
+ struct cost load, store, regcopy, selfcopy, overall;
+ memset (&load, 0, sizeof(load));
+ memset (&store, 0, sizeof(store));
+ memset (&regcopy, 0, sizeof(regcopy));
+ memset (&selfcopy, 0, sizeof(selfcopy));
+ memset (&overall, 0, sizeof(overall));
+
+ if (!file)
+ return;
+
+ FOR_EACH_BB (bb)
+ {
+ unsigned HOST_WIDE_INT block_cost = bb->frequency;
+ rtx insn, set;
+ for (insn = bb->head; insn; insn = NEXT_INSN (insn))
+ {
+ /* Yes, yes. We don't calculate the costs precisely.
+ Only for "simple enough" insns. Those containing single
+ sets only. */
+ if (INSN_P (insn) && ((set = single_set (insn)) != NULL))
+ {
+ rtx src = SET_SRC (set);
+ rtx dest = SET_DEST (set);
+ struct cost *pcost = NULL;
+ overall.cost += block_cost;
+ overall.count++;
+ if (rtx_equal_p (src, dest))
+ pcost = &selfcopy;
+ else if (GET_CODE (src) == GET_CODE (dest)
+ && ((GET_CODE (src) == REG)
+ || (GET_CODE (src) == SUBREG
+ && GET_CODE (SUBREG_REG (src)) == REG
+ && GET_CODE (SUBREG_REG (dest)) == REG)))
+ pcost = &regcopy;
+ else
+ {
+ if (GET_CODE (src) == SUBREG)
+ src = SUBREG_REG (src);
+ if (GET_CODE (dest) == SUBREG)
+ dest = SUBREG_REG (dest);
+ if (GET_CODE (src) == MEM && GET_CODE (dest) != MEM
+ && memref_is_stack_slot (src))
+ pcost = &load;
+ else if (GET_CODE (src) != MEM && GET_CODE (dest) == MEM
+ && memref_is_stack_slot (dest))
+ pcost = &store;
+ }
+ if (pcost)
+ {
+ pcost->cost += block_cost;
+ pcost->count++;
+ }
+ }
+ if (insn == bb->end)
+ break;
+ }
+ }
+
+ if (!prefix)
+ prefix = "";
+ fprintf (file, "static insn cost %s\n", message ? message : "");
+ fprintf (file, " %soverall:\tnum=%6d\tcost=", prefix, overall.count);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, overall.cost);
+ fprintf (file, "\n");
+ fprintf (file, " %sloads:\tnum=%6d\tcost=", prefix, load.count);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, load.cost);
+ fprintf (file, "\n");
+ fprintf (file, " %sstores:\tnum=%6d\tcost=", prefix, store.count);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, store.cost);
+ fprintf (file, "\n");
+ fprintf (file, " %sregcopy:\tnum=%6d\tcost=", prefix, regcopy.count);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, regcopy.cost);
+ fprintf (file, "\n");
+ fprintf (file, " %sselfcpy:\tnum=%6d\tcost=", prefix, selfcopy.count);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC_SPACE, 8, selfcopy.cost);
+ fprintf (file, "\n");
+}
+
+/* Returns nonzero, if WEB1 and WEB2 have some possible
+ hardregs in common. */
+
+int
+web_conflicts_p (web1, web2)
+ struct web *web1;
+ struct web *web2;
+{
+ if (web1->type == PRECOLORED && web2->type == PRECOLORED)
+ return 0;
+
+ if (web1->type == PRECOLORED)
+ return TEST_HARD_REG_BIT (web2->usable_regs, web1->regno);
+
+ if (web2->type == PRECOLORED)
+ return TEST_HARD_REG_BIT (web1->usable_regs, web2->regno);
+
+ return hard_regs_intersect_p (&web1->usable_regs, &web2->usable_regs);
+}
+
+/* Dump all uids of insns in which WEB is mentioned. */
+
+void
+dump_web_insns (web)
+ struct web *web;
+{
+ unsigned int i;
+
+ ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
+ web->id, web->regno, web->add_hardregs,
+ reg_class_names[web->regclass],
+ web->num_freedom, web->num_conflicts);
+ ra_debug_msg (DUMP_EVER, " def insns:");
+
+ for (i = 0; i < web->num_defs; ++i)
+ {
+ ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->defs[i]->insn));
+ }
+
+ ra_debug_msg (DUMP_EVER, "\n use insns:");
+ for (i = 0; i < web->num_uses; ++i)
+ {
+ ra_debug_msg (DUMP_EVER, " %d ", INSN_UID (web->uses[i]->insn));
+ }
+ ra_debug_msg (DUMP_EVER, "\n");
+}
+
+/* Dump conflicts for web WEB. */
+
+void
+dump_web_conflicts (web)
+ struct web *web;
+{
+ int num = 0;
+ unsigned int def2;
+
+ ra_debug_msg (DUMP_EVER, "Web: %i(%i)+%i class: %s freedom: %i degree %i\n",
+ web->id, web->regno, web->add_hardregs,
+ reg_class_names[web->regclass],
+ web->num_freedom, web->num_conflicts);
+
+ for (def2 = 0; def2 < num_webs; def2++)
+ if (TEST_BIT (igraph, igraph_index (web->id, def2)) && web->id != def2)
+ {
+ if ((num % 9) == 5)
+ ra_debug_msg (DUMP_EVER, "\n ");
+ num++;
+
+ ra_debug_msg (DUMP_EVER, " %d(%d)", def2, id2web[def2]->regno);
+ if (id2web[def2]->add_hardregs)
+ ra_debug_msg (DUMP_EVER, "+%d", id2web[def2]->add_hardregs);
+
+ if (web_conflicts_p (web, id2web[def2]))
+ ra_debug_msg (DUMP_EVER, "/x");
+
+ if (id2web[def2]->type == SELECT)
+ ra_debug_msg (DUMP_EVER, "/s");
+
+ if (id2web[def2]->type == COALESCED)
+ ra_debug_msg (DUMP_EVER,"/c/%d", alias (id2web[def2])->id);
+ }
+ ra_debug_msg (DUMP_EVER, "\n");
+ {
+ struct conflict_link *wl;
+ num = 0;
+ ra_debug_msg (DUMP_EVER, "By conflicts: ");
+ for (wl = web->conflict_list; wl; wl = wl->next)
+ {
+ struct web* w = wl->t;
+ if ((num % 9) == 8)
+ ra_debug_msg (DUMP_EVER, "\n ");
+ num++;
+ ra_debug_msg (DUMP_EVER, "%d(%d)%s ", w->id, w->regno,
+ web_conflicts_p (web, w) ? "+" : "");
+ }
+ ra_debug_msg (DUMP_EVER, "\n");
+ }
+}
+
+/* Output HARD_REG_SET to stderr. */
+
+void
+debug_hard_reg_set (set)
+ HARD_REG_SET set;
+{
+ int i;
+ for (i=0; i < FIRST_PSEUDO_REGISTER; ++i)
+ {
+ if (TEST_HARD_REG_BIT (set, i))
+ {
+ fprintf (stderr, "%s ", reg_names[i]);
+ }
+ }
+ fprintf (stderr, "\n");
+}
+
+/*
+vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
+*/
diff --git a/contrib/gcc/ra-rewrite.c b/contrib/gcc/ra-rewrite.c
new file mode 100644
index 0000000..61645e2
--- /dev/null
+++ b/contrib/gcc/ra-rewrite.c
@@ -0,0 +1,1987 @@
+/* Graph coloring register allocator
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Contributed by Michael Matz <matz@suse.de>
+ and Daniel Berlin <dan@cgsoftware.com>.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along
+ with GCC; see the file COPYING. If not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "function.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
+#include "df.h"
+#include "expr.h"
+#include "output.h"
+#include "except.h"
+#include "ra.h"
+#include "insn-config.h"
+#include "reload.h"
+
+/* This file is part of the graph coloring register allocator, and
+ contains the functions to change the insn stream. I.e. it adds
+ spill code, rewrites insns to use the new registers after
+ coloring and deletes coalesced moves. */
+
+struct rewrite_info;
+struct rtx_list;
+
+static void spill_coalescing PARAMS ((sbitmap, sbitmap));
+static unsigned HOST_WIDE_INT spill_prop_savings PARAMS ((struct web *,
+ sbitmap));
+static void spill_prop_insert PARAMS ((struct web *, sbitmap, sbitmap));
+static int spill_propagation PARAMS ((sbitmap, sbitmap, sbitmap));
+static void spill_coalprop PARAMS ((void));
+static void allocate_spill_web PARAMS ((struct web *));
+static void choose_spill_colors PARAMS ((void));
+static void rewrite_program PARAMS ((bitmap));
+static void remember_slot PARAMS ((struct rtx_list **, rtx));
+static int slots_overlap_p PARAMS ((rtx, rtx));
+static void delete_overlapping_slots PARAMS ((struct rtx_list **, rtx));
+static int slot_member_p PARAMS ((struct rtx_list *, rtx));
+static void insert_stores PARAMS ((bitmap));
+static int spill_same_color_p PARAMS ((struct web *, struct web *));
+static bool is_partly_live_1 PARAMS ((sbitmap, struct web *));
+static void update_spill_colors PARAMS ((HARD_REG_SET *, struct web *, int));
+static int spill_is_free PARAMS ((HARD_REG_SET *, struct web *));
+static void emit_loads PARAMS ((struct rewrite_info *, int, rtx));
+static void reloads_to_loads PARAMS ((struct rewrite_info *, struct ref **,
+ unsigned int, struct web **));
+static void rewrite_program2 PARAMS ((bitmap));
+static void mark_refs_for_checking PARAMS ((struct web *, bitmap));
+static void detect_web_parts_to_rebuild PARAMS ((void));
+static void delete_useless_defs PARAMS ((void));
+static void detect_non_changed_webs PARAMS ((void));
+static void reset_changed_flag PARAMS ((void));
+
+/* For tracking some statistics, we count the number (and cost)
+ of deleted move insns. */
+static unsigned int deleted_move_insns;
+static unsigned HOST_WIDE_INT deleted_move_cost;
+
+/* This is the spill coalescing phase. In SPILLED the IDs of all
+ already spilled webs are noted. In COALESCED the IDs of webs still
+ to check for coalescing. This tries to coalesce two webs, which were
+ spilled, are connected by a move, and don't conflict. Greatly
+ reduces memory shuffling. */
+
+static void
+spill_coalescing (coalesce, spilled)
+ sbitmap coalesce, spilled;
+{
+ struct move_list *ml;
+ struct move *m;
+ for (ml = wl_moves; ml; ml = ml->next)
+ if ((m = ml->move) != NULL)
+ {
+ struct web *s = alias (m->source_web);
+ struct web *t = alias (m->target_web);
+ if ((TEST_BIT (spilled, s->id) && TEST_BIT (coalesce, t->id))
+ || (TEST_BIT (spilled, t->id) && TEST_BIT (coalesce, s->id)))
+ {
+ struct conflict_link *wl;
+ if (TEST_BIT (sup_igraph, s->id * num_webs + t->id)
+ || TEST_BIT (sup_igraph, t->id * num_webs + s->id)
+ || s->pattern || t->pattern)
+ continue;
+
+ deleted_move_insns++;
+ deleted_move_cost += BLOCK_FOR_INSN (m->insn)->frequency + 1;
+ PUT_CODE (m->insn, NOTE);
+ NOTE_LINE_NUMBER (m->insn) = NOTE_INSN_DELETED;
+ df_insn_modify (df, BLOCK_FOR_INSN (m->insn), m->insn);
+
+ m->target_web->target_of_spilled_move = 1;
+ if (s == t)
+ /* May be, already coalesced due to a former move. */
+ continue;
+ /* Merge the nodes S and T in the I-graph. Beware: the merging
+ of conflicts relies on the fact, that in the conflict list
+ of T all of it's conflicts are noted. This is currently not
+ the case if T would be the target of a coalesced web, because
+ then (in combine () above) only those conflicts were noted in
+ T from the web which was coalesced into T, which at the time
+ of combine() were not already on the SELECT stack or were
+ itself coalesced to something other. */
+ if (t->type != SPILLED || s->type != SPILLED)
+ abort ();
+ remove_list (t->dlink, &WEBS(SPILLED));
+ put_web (t, COALESCED);
+ t->alias = s;
+ s->is_coalesced = 1;
+ t->is_coalesced = 1;
+ merge_moves (s, t);
+ for (wl = t->conflict_list; wl; wl = wl->next)
+ {
+ struct web *pweb = wl->t;
+ if (wl->sub == NULL)
+ record_conflict (s, pweb);
+ else
+ {
+ struct sub_conflict *sl;
+ for (sl = wl->sub; sl; sl = sl->next)
+ {
+ struct web *sweb = NULL;
+ if (SUBWEB_P (sl->s))
+ sweb = find_subweb (s, sl->s->orig_x);
+ if (!sweb)
+ sweb = s;
+ record_conflict (sweb, sl->t);
+ }
+ }
+ /* No decrement_degree here, because we already have colored
+ the graph, and don't want to insert pweb into any other
+ list. */
+ pweb->num_conflicts -= 1 + t->add_hardregs;
+ }
+ }
+ }
+}
+
+/* Returns the probable saving of coalescing WEB with webs from
+ SPILLED, in terms of removed move insn cost. */
+
+static unsigned HOST_WIDE_INT
+spill_prop_savings (web, spilled)
+ struct web *web;
+ sbitmap spilled;
+{
+ unsigned HOST_WIDE_INT savings = 0;
+ struct move_list *ml;
+ struct move *m;
+ unsigned int cost;
+ if (web->pattern)
+ return 0;
+ cost = 1 + MEMORY_MOVE_COST (GET_MODE (web->orig_x), web->regclass, 1);
+ cost += 1 + MEMORY_MOVE_COST (GET_MODE (web->orig_x), web->regclass, 0);
+ for (ml = wl_moves; ml; ml = ml->next)
+ if ((m = ml->move) != NULL)
+ {
+ struct web *s = alias (m->source_web);
+ struct web *t = alias (m->target_web);
+ if (s != web)
+ {
+ struct web *h = s;
+ s = t;
+ t = h;
+ }
+ if (s != web || !TEST_BIT (spilled, t->id) || t->pattern
+ || TEST_BIT (sup_igraph, s->id * num_webs + t->id)
+ || TEST_BIT (sup_igraph, t->id * num_webs + s->id))
+ continue;
+ savings += BLOCK_FOR_INSN (m->insn)->frequency * cost;
+ }
+ return savings;
+}
+
+/* This add all IDs of colored webs, which are connected to WEB by a move
+ to LIST and PROCESSED. */
+
+static void
+spill_prop_insert (web, list, processed)
+ struct web *web;
+ sbitmap list, processed;
+{
+ struct move_list *ml;
+ struct move *m;
+ for (ml = wl_moves; ml; ml = ml->next)
+ if ((m = ml->move) != NULL)
+ {
+ struct web *s = alias (m->source_web);
+ struct web *t = alias (m->target_web);
+ if (s != web)
+ {
+ struct web *h = s;
+ s = t;
+ t = h;
+ }
+ if (s != web || t->type != COLORED || TEST_BIT (processed, t->id))
+ continue;
+ SET_BIT (list, t->id);
+ SET_BIT (processed, t->id);
+ }
+}
+
+/* The spill propagation pass. If we have to spilled webs, the first
+ connected through a move to a colored one, and the second also connected
+ to that colored one, and this colored web is only used to connect both
+ spilled webs, it might be worthwhile to spill that colored one.
+ This is the case, if the cost of the removed copy insns (all three webs
+ could be placed into the same stack slot) is higher than the spill cost
+ of the web.
+ TO_PROP are the webs we try to propagate from (i.e. spilled ones),
+ SPILLED the set of all spilled webs so far and PROCESSED the set
+ of all webs processed so far, so we don't do work twice. */
+
+static int
+spill_propagation (to_prop, spilled, processed)
+ sbitmap to_prop, spilled, processed;
+{
+ int id;
+ int again = 0;
+ sbitmap list = sbitmap_alloc (num_webs);
+ sbitmap_zero (list);
+
+ /* First insert colored move neighbors into the candidate list. */
+ EXECUTE_IF_SET_IN_SBITMAP (to_prop, 0, id,
+ {
+ spill_prop_insert (ID2WEB (id), list, processed);
+ });
+ sbitmap_zero (to_prop);
+
+ /* For all candidates, see, if the savings are higher than it's
+ spill cost. */
+ while ((id = sbitmap_first_set_bit (list)) >= 0)
+ {
+ struct web *web = ID2WEB (id);
+ RESET_BIT (list, id);
+ if (spill_prop_savings (web, spilled) >= web->spill_cost)
+ {
+ /* If so, we found a new spilled web. Insert it's colored
+ move neighbors again, and mark, that we need to repeat the
+ whole mainloop of spillprog/coalescing again. */
+ remove_web_from_list (web);
+ web->color = -1;
+ put_web (web, SPILLED);
+ SET_BIT (spilled, id);
+ SET_BIT (to_prop, id);
+ spill_prop_insert (web, list, processed);
+ again = 1;
+ }
+ }
+ sbitmap_free (list);
+ return again;
+}
+
+/* The main phase to improve spill costs. This repeatedly runs
+ spill coalescing and spill propagation, until nothing changes. */
+
+static void
+spill_coalprop ()
+{
+ sbitmap spilled, processed, to_prop;
+ struct dlist *d;
+ int again;
+ spilled = sbitmap_alloc (num_webs);
+ processed = sbitmap_alloc (num_webs);
+ to_prop = sbitmap_alloc (num_webs);
+ sbitmap_zero (spilled);
+ for (d = WEBS(SPILLED); d; d = d->next)
+ SET_BIT (spilled, DLIST_WEB (d)->id);
+ sbitmap_copy (to_prop, spilled);
+ sbitmap_zero (processed);
+ do
+ {
+ spill_coalescing (to_prop, spilled);
+ /* XXX Currently (with optimistic coalescing) spill_propagation()
+ doesn't give better code, sometimes it gives worse (but not by much)
+ code. I believe this is because of slightly wrong cost
+ measurements. Anyway right now it isn't worth the time it takes,
+ so deactivate it for now. */
+ again = 0 && spill_propagation (to_prop, spilled, processed);
+ }
+ while (again);
+ sbitmap_free (to_prop);
+ sbitmap_free (processed);
+ sbitmap_free (spilled);
+}
+
+/* Allocate a spill slot for a WEB. Currently we spill to pseudo
+ registers, to be able to track also webs for "stack slots", and also
+ to possibly colorize them. These pseudos are sometimes handled
+ in a special way, where we know, that they also can represent
+ MEM references. */
+
+static void
+allocate_spill_web (web)
+ struct web *web;
+{
+ int regno = web->regno;
+ rtx slot;
+ if (web->stack_slot)
+ return;
+ slot = gen_reg_rtx (PSEUDO_REGNO_MODE (regno));
+ web->stack_slot = slot;
+}
+
+/* This chooses a color for all SPILLED webs for interference region
+ spilling. The heuristic isn't good in any way. */
+
+static void
+choose_spill_colors ()
+{
+ struct dlist *d;
+ unsigned HOST_WIDE_INT *costs = (unsigned HOST_WIDE_INT *)
+ xmalloc (FIRST_PSEUDO_REGISTER * sizeof (costs[0]));
+ for (d = WEBS(SPILLED); d; d = d->next)
+ {
+ struct web *web = DLIST_WEB (d);
+ struct conflict_link *wl;
+ int bestc, c;
+ HARD_REG_SET avail;
+ memset (costs, 0, FIRST_PSEUDO_REGISTER * sizeof (costs[0]));
+ for (wl = web->conflict_list; wl; wl = wl->next)
+ {
+ struct web *pweb = wl->t;
+ if (pweb->type == COLORED || pweb->type == PRECOLORED)
+ costs[pweb->color] += pweb->spill_cost;
+ }
+
+ COPY_HARD_REG_SET (avail, web->usable_regs);
+ if (web->crosses_call)
+ {
+ /* Add an arbitrary constant cost to colors not usable by
+ call-crossing webs without saves/loads. */
+ for (c = 0; c < FIRST_PSEUDO_REGISTER; c++)
+ if (TEST_HARD_REG_BIT (call_used_reg_set, c))
+ costs[c] += 1000;
+ }
+ bestc = -1;
+ for (c = 0; c < FIRST_PSEUDO_REGISTER; c++)
+ if ((bestc < 0 || costs[bestc] > costs[c])
+ && TEST_HARD_REG_BIT (avail, c)
+ && HARD_REGNO_MODE_OK (c, PSEUDO_REGNO_MODE (web->regno)))
+ {
+ int i, size;
+ size = HARD_REGNO_NREGS (c, PSEUDO_REGNO_MODE (web->regno));
+ for (i = 1; i < size
+ && TEST_HARD_REG_BIT (avail, c + i); i++);
+ if (i == size)
+ bestc = c;
+ }
+ web->color = bestc;
+ ra_debug_msg (DUMP_PROCESS, "choosing color %d for spilled web %d\n",
+ bestc, web->id);
+ }
+
+ free (costs);
+}
+
+/* For statistics sake we count the number and cost of all new loads,
+ stores and emitted rematerializations. */
+static unsigned int emitted_spill_loads;
+static unsigned int emitted_spill_stores;
+static unsigned int emitted_remat;
+static unsigned HOST_WIDE_INT spill_load_cost;
+static unsigned HOST_WIDE_INT spill_store_cost;
+static unsigned HOST_WIDE_INT spill_remat_cost;
+
+/* In rewrite_program2() we detect if some def us useless, in the sense,
+ that the pseudo set is not live anymore at that point. The REF_IDs
+ of such defs are noted here. */
+static bitmap useless_defs;
+
+/* This is the simple and fast version of rewriting the program to
+ include spill code. It spills at every insn containing spilled
+ defs or uses. Loads are added only if flag_ra_spill_every_use is
+ nonzero, otherwise only stores will be added. This doesn't
+ support rematerialization.
+ NEW_DEATHS is filled with uids for insns, which probably contain
+ deaths. */
+
+static void
+rewrite_program (new_deaths)
+ bitmap new_deaths;
+{
+ unsigned int i;
+ struct dlist *d;
+ bitmap b = BITMAP_XMALLOC ();
+
+ /* We walk over all webs, over all uses/defs. For all webs, we need
+ to look at spilled webs, and webs coalesced to spilled ones, in case
+ their alias isn't broken up, or they got spill coalesced. */
+ for (i = 0; i < 2; i++)
+ for (d = (i == 0) ? WEBS(SPILLED) : WEBS(COALESCED); d; d = d->next)
+ {
+ struct web *web = DLIST_WEB (d);
+ struct web *aweb = alias (web);
+ unsigned int j;
+ rtx slot;
+
+ /* Is trivially true for spilled webs, but not for coalesced ones. */
+ if (aweb->type != SPILLED)
+ continue;
+
+ /* First add loads before every use, if we have to. */
+ if (flag_ra_spill_every_use)
+ {
+ bitmap_clear (b);
+ allocate_spill_web (aweb);
+ slot = aweb->stack_slot;
+ for (j = 0; j < web->num_uses; j++)
+ {
+ rtx insns, target, source;
+ rtx insn = DF_REF_INSN (web->uses[j]);
+ rtx prev = PREV_INSN (insn);
+ basic_block bb = BLOCK_FOR_INSN (insn);
+ /* Happens when spill_coalescing() deletes move insns. */
+ if (!INSN_P (insn))
+ continue;
+
+ /* Check that we didn't already added a load for this web
+ and insn. Happens, when the an insn uses the same web
+ multiple times. */
+ if (bitmap_bit_p (b, INSN_UID (insn)))
+ continue;
+ bitmap_set_bit (b, INSN_UID (insn));
+ target = DF_REF_REG (web->uses[j]);
+ source = slot;
+ start_sequence ();
+ if (GET_CODE (target) == SUBREG)
+ source = simplify_gen_subreg (GET_MODE (target), source,
+ GET_MODE (source),
+ SUBREG_BYTE (target));
+ ra_emit_move_insn (target, source);
+ insns = get_insns ();
+ end_sequence ();
+ emit_insn_before (insns, insn);
+
+ if (bb->head == insn)
+ bb->head = NEXT_INSN (prev);
+ for (insn = PREV_INSN (insn); insn != prev;
+ insn = PREV_INSN (insn))
+ {
+ set_block_for_insn (insn, bb);
+ df_insn_modify (df, bb, insn);
+ }
+
+ emitted_spill_loads++;
+ spill_load_cost += bb->frequency + 1;
+ }
+ }
+
+ /* Now emit the stores after each def.
+ If any uses were loaded from stackslots (compared to
+ rematerialized or not reloaded due to IR spilling),
+ aweb->stack_slot will be set. If not, we don't need to emit
+ any stack stores. */
+ slot = aweb->stack_slot;
+ bitmap_clear (b);
+ if (slot)
+ for (j = 0; j < web->num_defs; j++)
+ {
+ rtx insns, source, dest;
+ rtx insn = DF_REF_INSN (web->defs[j]);
+ rtx following = NEXT_INSN (insn);
+ basic_block bb = BLOCK_FOR_INSN (insn);
+ /* Happens when spill_coalescing() deletes move insns. */
+ if (!INSN_P (insn))
+ continue;
+ if (bitmap_bit_p (b, INSN_UID (insn)))
+ continue;
+ bitmap_set_bit (b, INSN_UID (insn));
+ start_sequence ();
+ source = DF_REF_REG (web->defs[j]);
+ dest = slot;
+ if (GET_CODE (source) == SUBREG)
+ dest = simplify_gen_subreg (GET_MODE (source), dest,
+ GET_MODE (dest),
+ SUBREG_BYTE (source));
+ ra_emit_move_insn (dest, source);
+
+ insns = get_insns ();
+ end_sequence ();
+ if (insns)
+ {
+ emit_insn_after (insns, insn);
+ if (bb->end == insn)
+ bb->end = PREV_INSN (following);
+ for (insn = insns; insn != following; insn = NEXT_INSN (insn))
+ {
+ set_block_for_insn (insn, bb);
+ df_insn_modify (df, bb, insn);
+ }
+ }
+ else
+ df_insn_modify (df, bb, insn);
+ emitted_spill_stores++;
+ spill_store_cost += bb->frequency + 1;
+ /* XXX we should set new_deaths for all inserted stores
+ whose pseudo dies here.
+ Note, that this isn't the case for _all_ stores. */
+ /* I.e. the next is wrong, and might cause some spilltemps
+ to be categorized as spilltemp2's (i.e. live over a death),
+ although they aren't. This might make them spill again,
+ which causes endlessness in the case, this insn is in fact
+ _no_ death. */
+ bitmap_set_bit (new_deaths, INSN_UID (PREV_INSN (following)));
+ }
+ }
+
+ BITMAP_XFREE (b);
+}
+
+/* A simple list of rtx's. */
+struct rtx_list
+{
+ struct rtx_list *next;
+ rtx x;
+};
+
+/* Adds X to *LIST. */
+
+static void
+remember_slot (list, x)
+ struct rtx_list **list;
+ rtx x;
+{
+ struct rtx_list *l;
+ /* PRE: X is not already in LIST. */
+ l = (struct rtx_list *) ra_alloc (sizeof (*l));
+ l->next = *list;
+ l->x = x;
+ *list = l;
+}
+
+/* Given two rtx' S1 and S2, either being REGs or MEMs (or SUBREGs
+ thereof), return nonzero, if they overlap. REGs and MEMs don't
+ overlap, and if they are MEMs they must have an easy address
+ (plus (basereg) (const_inst x)), otherwise they overlap. */
+
+static int
+slots_overlap_p (s1, s2)
+ rtx s1, s2;
+{
+ rtx base1, base2;
+ HOST_WIDE_INT ofs1 = 0, ofs2 = 0;
+ int size1 = GET_MODE_SIZE (GET_MODE (s1));
+ int size2 = GET_MODE_SIZE (GET_MODE (s2));
+ if (GET_CODE (s1) == SUBREG)
+ ofs1 = SUBREG_BYTE (s1), s1 = SUBREG_REG (s1);
+ if (GET_CODE (s2) == SUBREG)
+ ofs2 = SUBREG_BYTE (s2), s2 = SUBREG_REG (s2);
+
+ if (s1 == s2)
+ return 1;
+
+ if (GET_CODE (s1) != GET_CODE (s2))
+ return 0;
+
+ if (GET_CODE (s1) == REG && GET_CODE (s2) == REG)
+ {
+ if (REGNO (s1) != REGNO (s2))
+ return 0;
+ if (ofs1 >= ofs2 + size2 || ofs2 >= ofs1 + size1)
+ return 0;
+ return 1;
+ }
+ if (GET_CODE (s1) != MEM || GET_CODE (s2) != MEM)
+ abort ();
+ s1 = XEXP (s1, 0);
+ s2 = XEXP (s2, 0);
+ if (GET_CODE (s1) != PLUS || GET_CODE (XEXP (s1, 0)) != REG
+ || GET_CODE (XEXP (s1, 1)) != CONST_INT)
+ return 1;
+ if (GET_CODE (s2) != PLUS || GET_CODE (XEXP (s2, 0)) != REG
+ || GET_CODE (XEXP (s2, 1)) != CONST_INT)
+ return 1;
+ base1 = XEXP (s1, 0);
+ base2 = XEXP (s2, 0);
+ if (!rtx_equal_p (base1, base2))
+ return 1;
+ ofs1 += INTVAL (XEXP (s1, 1));
+ ofs2 += INTVAL (XEXP (s2, 1));
+ if (ofs1 >= ofs2 + size2 || ofs2 >= ofs1 + size1)
+ return 0;
+ return 1;
+}
+
+/* This deletes from *LIST all rtx's which overlap with X in the sense
+ of slots_overlap_p(). */
+
+static void
+delete_overlapping_slots (list, x)
+ struct rtx_list **list;
+ rtx x;
+{
+ while (*list)
+ {
+ if (slots_overlap_p ((*list)->x, x))
+ *list = (*list)->next;
+ else
+ list = &((*list)->next);
+ }
+}
+
+/* Returns nonzero, of X is member of LIST. */
+
+static int
+slot_member_p (list, x)
+ struct rtx_list *list;
+ rtx x;
+{
+ for (;list; list = list->next)
+ if (rtx_equal_p (list->x, x))
+ return 1;
+ return 0;
+}
+
+/* A more sophisticated (and slower) method of adding the stores, than
+ rewrite_program(). This goes backward the insn stream, adding
+ stores as it goes, but only if it hasn't just added a store to the
+ same location. NEW_DEATHS is a bitmap filled with uids of insns
+ containing deaths. */
+
+static void
+insert_stores (new_deaths)
+ bitmap new_deaths;
+{
+ rtx insn;
+ rtx last_slot = NULL_RTX;
+ struct rtx_list *slots = NULL;
+
+ /* We go simply backwards over basic block borders. */
+ for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
+ {
+ int uid = INSN_UID (insn);
+
+ /* If we reach a basic block border, which has more than one
+ outgoing edge, we simply forget all already emitted stores. */
+ if (GET_CODE (insn) == BARRIER
+ || JUMP_P (insn) || can_throw_internal (insn))
+ {
+ last_slot = NULL_RTX;
+ slots = NULL;
+ }
+ if (!INSN_P (insn))
+ continue;
+
+ /* If this insn was not just added in this pass. */
+ if (uid < insn_df_max_uid)
+ {
+ unsigned int n;
+ rtx following = NEXT_INSN (insn);
+ basic_block bb = BLOCK_FOR_INSN (insn);
+ struct ra_insn_info info;
+
+ info = insn_df[uid];
+ for (n = 0; n < info.num_defs; n++)
+ {
+ struct web *web = def2web[DF_REF_ID (info.defs[n])];
+ struct web *aweb = alias (find_web_for_subweb (web));
+ rtx slot, source;
+ if (aweb->type != SPILLED || !aweb->stack_slot)
+ continue;
+ slot = aweb->stack_slot;
+ source = DF_REF_REG (info.defs[n]);
+ /* adjust_address() might generate code. */
+ start_sequence ();
+ if (GET_CODE (source) == SUBREG)
+ slot = simplify_gen_subreg (GET_MODE (source), slot,
+ GET_MODE (slot),
+ SUBREG_BYTE (source));
+ /* If we have no info about emitted stores, or it didn't
+ contain the location we intend to use soon, then
+ add the store. */
+ if ((!last_slot || !rtx_equal_p (slot, last_slot))
+ && ! slot_member_p (slots, slot))
+ {
+ rtx insns, ni;
+ last_slot = slot;
+ remember_slot (&slots, slot);
+ ra_emit_move_insn (slot, source);
+ insns = get_insns ();
+ end_sequence ();
+ if (insns)
+ {
+ emit_insn_after (insns, insn);
+ if (bb->end == insn)
+ bb->end = PREV_INSN (following);
+ for (ni = insns; ni != following; ni = NEXT_INSN (ni))
+ {
+ set_block_for_insn (ni, bb);
+ df_insn_modify (df, bb, ni);
+ }
+ }
+ else
+ df_insn_modify (df, bb, insn);
+ emitted_spill_stores++;
+ spill_store_cost += bb->frequency + 1;
+ bitmap_set_bit (new_deaths, INSN_UID (PREV_INSN (following)));
+ }
+ else
+ {
+ /* Otherwise ignore insns from adjust_address() above. */
+ end_sequence ();
+ }
+ }
+ }
+ /* If we look at a load generated by the allocator, forget
+ the last emitted slot, and additionally clear all slots
+ overlapping it's source (after all, we need it again). */
+ /* XXX If we emit the stack-ref directly into the using insn the
+ following needs a change, because that is no new insn. Preferably
+ we would add some notes to the insn, what stackslots are needed
+ for it. */
+ if (uid >= last_max_uid)
+ {
+ rtx set = single_set (insn);
+ last_slot = NULL_RTX;
+ /* If this was no simple set, give up, and forget everything. */
+ if (!set)
+ slots = NULL;
+ else
+ {
+ if (1 || GET_CODE (SET_SRC (set)) == MEM)
+ delete_overlapping_slots (&slots, SET_SRC (set));
+ }
+ }
+ }
+}
+
+/* Returns 1 if both colored webs have some hardregs in common, even if
+ they are not the same width. */
+
+static int
+spill_same_color_p (web1, web2)
+ struct web *web1, *web2;
+{
+ int c1, size1, c2, size2;
+ if ((c1 = alias (web1)->color) < 0 || c1 == an_unusable_color)
+ return 0;
+ if ((c2 = alias (web2)->color) < 0 || c2 == an_unusable_color)
+ return 0;
+
+ size1 = web1->type == PRECOLORED
+ ? 1 : HARD_REGNO_NREGS (c1, PSEUDO_REGNO_MODE (web1->regno));
+ size2 = web2->type == PRECOLORED
+ ? 1 : HARD_REGNO_NREGS (c2, PSEUDO_REGNO_MODE (web2->regno));
+ if (c1 >= c2 + size2 || c2 >= c1 + size1)
+ return 0;
+ return 1;
+}
+
+/* Given the set of live web IDs LIVE, returns nonzero, if any of WEBs
+ subwebs (or WEB itself) is live. */
+
+static bool
+is_partly_live_1 (live, web)
+ sbitmap live;
+ struct web *web;
+{
+ do
+ if (TEST_BIT (live, web->id))
+ return 1;
+ while ((web = web->subreg_next));
+ return 0;
+}
+
+/* Fast version in case WEB has no subwebs. */
+#define is_partly_live(live, web) ((!web->subreg_next) \
+ ? TEST_BIT (live, web->id) \
+ : is_partly_live_1 (live, web))
+
+/* Change the set of currently IN_USE colors according to
+ WEB's color. Either add those colors to the hardreg set (if ADD
+ is nonzero), or remove them. */
+
+static void
+update_spill_colors (in_use, web, add)
+ HARD_REG_SET *in_use;
+ struct web *web;
+ int add;
+{
+ int c, size;
+ if ((c = alias (find_web_for_subweb (web))->color) < 0
+ || c == an_unusable_color)
+ return;
+ size = HARD_REGNO_NREGS (c, GET_MODE (web->orig_x));
+ if (SUBWEB_P (web))
+ {
+ c += subreg_regno_offset (c, GET_MODE (SUBREG_REG (web->orig_x)),
+ SUBREG_BYTE (web->orig_x),
+ GET_MODE (web->orig_x));
+ }
+ else if (web->type == PRECOLORED)
+ size = 1;
+ if (add)
+ for (; size--;)
+ SET_HARD_REG_BIT (*in_use, c + size);
+ else
+ for (; size--;)
+ CLEAR_HARD_REG_BIT (*in_use, c + size);
+}
+
+/* Given a set of hardregs currently IN_USE and the color C of WEB,
+ return -1 if WEB has no color, 1 of it has the unusable color,
+ 0 if one of it's used hardregs are in use, and 1 otherwise.
+ Generally, if WEB can't be left colorized return 1. */
+
+static int
+spill_is_free (in_use, web)
+ HARD_REG_SET *in_use;
+ struct web *web;
+{
+ int c, size;
+ if ((c = alias (web)->color) < 0)
+ return -1;
+ if (c == an_unusable_color)
+ return 1;
+ size = web->type == PRECOLORED
+ ? 1 : HARD_REGNO_NREGS (c, PSEUDO_REGNO_MODE (web->regno));
+ for (; size--;)
+ if (TEST_HARD_REG_BIT (*in_use, c + size))
+ return 0;
+ return 1;
+}
+
+
+/* Structure for passing between rewrite_program2() and emit_loads(). */
+struct rewrite_info
+{
+ /* The web IDs which currently would need a reload. These are
+ currently live spilled webs, whose color was still free. */
+ bitmap need_reload;
+ /* We need a scratch bitmap, but don't want to allocate one a zillion
+ times. */
+ bitmap scratch;
+ /* Web IDs of currently live webs. This are the precise IDs,
+ not just those of the superwebs. If only on part is live, only
+ that ID is placed here. */
+ sbitmap live;
+ /* An array of webs, which currently need a load added.
+ They will be emitted when seeing the first death. */
+ struct web **needed_loads;
+ /* The current number of entries in needed_loads. */
+ int nl_size;
+ /* The number of bits set in need_reload. */
+ int num_reloads;
+ /* The current set of hardregs not available. */
+ HARD_REG_SET colors_in_use;
+ /* Nonzero, if we just added some spill temps to need_reload or
+ needed_loads. In this case we don't wait for the next death
+ to emit their loads. */
+ int any_spilltemps_spilled;
+ /* Nonzero, if we currently need to emit the loads. E.g. when we
+ saw an insn containing deaths. */
+ int need_load;
+};
+
+/* The needed_loads list of RI contains some webs for which
+ we add the actual load insns here. They are added just before
+ their use last seen. NL_FIRST_RELOAD is the index of the first
+ load which is a converted reload, all other entries are normal
+ loads. LAST_BLOCK_INSN is the last insn of the current basic block. */
+
+static void
+emit_loads (ri, nl_first_reload, last_block_insn)
+ struct rewrite_info *ri;
+ int nl_first_reload;
+ rtx last_block_insn;
+{
+ int j;
+ for (j = ri->nl_size; j;)
+ {
+ struct web *web = ri->needed_loads[--j];
+ struct web *supweb;
+ struct web *aweb;
+ rtx ni, slot, reg;
+ rtx before = NULL_RTX, after = NULL_RTX;
+ basic_block bb;
+ /* When spilltemps were spilled for the last insns, their
+ loads already are emitted, which is noted by setting
+ needed_loads[] for it to 0. */
+ if (!web)
+ continue;
+ supweb = find_web_for_subweb (web);
+ if (supweb->regno >= max_normal_pseudo)
+ abort ();
+ /* Check for web being a spilltemp, if we only want to
+ load spilltemps. Also remember, that we emitted that
+ load, which we don't need to do when we have a death,
+ because then all of needed_loads[] is emptied. */
+ if (!ri->need_load)
+ {
+ if (!supweb->spill_temp)
+ continue;
+ else
+ ri->needed_loads[j] = 0;
+ }
+ web->in_load = 0;
+ /* The adding of reloads doesn't depend on liveness. */
+ if (j < nl_first_reload && !TEST_BIT (ri->live, web->id))
+ continue;
+ aweb = alias (supweb);
+ aweb->changed = 1;
+ start_sequence ();
+ if (supweb->pattern)
+ {
+ /* XXX If we later allow non-constant sources for rematerialization
+ we must also disallow coalescing _to_ rematerialized webs
+ (at least then disallow spilling them, which we already ensure
+ when flag_ra_break_aliases), or not take the pattern but a
+ stackslot. */
+ if (aweb != supweb)
+ abort ();
+ slot = copy_rtx (supweb->pattern);
+ reg = copy_rtx (supweb->orig_x);
+ /* Sanity check. orig_x should be a REG rtx, which should be
+ shared over all RTL, so copy_rtx should have no effect. */
+ if (reg != supweb->orig_x)
+ abort ();
+ }
+ else
+ {
+ allocate_spill_web (aweb);
+ slot = aweb->stack_slot;
+
+ /* If we don't copy the RTL there might be some SUBREG
+ rtx shared in the next iteration although being in
+ different webs, which leads to wrong code. */
+ reg = copy_rtx (web->orig_x);
+ if (GET_CODE (reg) == SUBREG)
+ /*slot = adjust_address (slot, GET_MODE (reg), SUBREG_BYTE
+ (reg));*/
+ slot = simplify_gen_subreg (GET_MODE (reg), slot, GET_MODE (slot),
+ SUBREG_BYTE (reg));
+ }
+ ra_emit_move_insn (reg, slot);
+ ni = get_insns ();
+ end_sequence ();
+ before = web->last_use_insn;
+ web->last_use_insn = NULL_RTX;
+ if (!before)
+ {
+ if (JUMP_P (last_block_insn))
+ before = last_block_insn;
+ else
+ after = last_block_insn;
+ }
+ if (after)
+ {
+ rtx foll = NEXT_INSN (after);
+ bb = BLOCK_FOR_INSN (after);
+ emit_insn_after (ni, after);
+ if (bb->end == after)
+ bb->end = PREV_INSN (foll);
+ for (ni = NEXT_INSN (after); ni != foll; ni = NEXT_INSN (ni))
+ {
+ set_block_for_insn (ni, bb);
+ df_insn_modify (df, bb, ni);
+ }
+ }
+ else
+ {
+ rtx prev = PREV_INSN (before);
+ bb = BLOCK_FOR_INSN (before);
+ emit_insn_before (ni, before);
+ if (bb->head == before)
+ bb->head = NEXT_INSN (prev);
+ for (; ni != before; ni = NEXT_INSN (ni))
+ {
+ set_block_for_insn (ni, bb);
+ df_insn_modify (df, bb, ni);
+ }
+ }
+ if (supweb->pattern)
+ {
+ emitted_remat++;
+ spill_remat_cost += bb->frequency + 1;
+ }
+ else
+ {
+ emitted_spill_loads++;
+ spill_load_cost += bb->frequency + 1;
+ }
+ RESET_BIT (ri->live, web->id);
+ /* In the special case documented above only emit the reloads and
+ one load. */
+ if (ri->need_load == 2 && j < nl_first_reload)
+ break;
+ }
+ if (ri->need_load)
+ ri->nl_size = j;
+}
+
+/* Given a set of reloads in RI, an array of NUM_REFS references (either
+ uses or defs) in REFS, and REF2WEB to translate ref IDs to webs
+ (either use2web or def2web) convert some reloads to loads.
+ This looks at the webs referenced, and how they change the set of
+ available colors. Now put all still live webs, which needed reloads,
+ and whose colors isn't free anymore, on the needed_loads list. */
+
+static void
+reloads_to_loads (ri, refs, num_refs, ref2web)
+ struct rewrite_info *ri;
+ struct ref **refs;
+ unsigned int num_refs;
+ struct web **ref2web;
+{
+ unsigned int n;
+ int num_reloads = ri->num_reloads;
+ for (n = 0; n < num_refs && num_reloads; n++)
+ {
+ struct web *web = ref2web[DF_REF_ID (refs[n])];
+ struct web *supweb = find_web_for_subweb (web);
+ int is_death;
+ int j;
+ /* Only emit reloads when entering their interference
+ region. A use of a spilled web never opens an
+ interference region, independent of it's color. */
+ if (alias (supweb)->type == SPILLED)
+ continue;
+ if (supweb->type == PRECOLORED
+ && TEST_HARD_REG_BIT (never_use_colors, supweb->color))
+ continue;
+ /* Note, that if web (and supweb) are DEFs, we already cleared
+ the corresponding bits in live. I.e. is_death becomes true, which
+ is what we want. */
+ is_death = !TEST_BIT (ri->live, supweb->id);
+ is_death &= !TEST_BIT (ri->live, web->id);
+ if (is_death)
+ {
+ int old_num_r = num_reloads;
+ bitmap_clear (ri->scratch);
+ EXECUTE_IF_SET_IN_BITMAP (ri->need_reload, 0, j,
+ {
+ struct web *web2 = ID2WEB (j);
+ struct web *aweb2 = alias (find_web_for_subweb (web2));
+ if (spill_is_free (&(ri->colors_in_use), aweb2) == 0)
+ abort ();
+ if (spill_same_color_p (supweb, aweb2)
+ /* && interfere (web, web2) */)
+ {
+ if (!web2->in_load)
+ {
+ ri->needed_loads[ri->nl_size++] = web2;
+ web2->in_load = 1;
+ }
+ bitmap_set_bit (ri->scratch, j);
+ num_reloads--;
+ }
+ });
+ if (num_reloads != old_num_r)
+ bitmap_operation (ri->need_reload, ri->need_reload, ri->scratch,
+ BITMAP_AND_COMPL);
+ }
+ }
+ ri->num_reloads = num_reloads;
+}
+
+/* This adds loads for spilled webs to the program. It uses a kind of
+ interference region spilling. If flag_ra_ir_spilling is zero it
+ only uses improved chaitin spilling (adding loads only at insns
+ containing deaths). */
+
+static void
+rewrite_program2 (new_deaths)
+ bitmap new_deaths;
+{
+ basic_block bb;
+ int nl_first_reload;
+ struct rewrite_info ri;
+ rtx insn;
+ ri.needed_loads = (struct web **) xmalloc (num_webs * sizeof (struct web *));
+ ri.need_reload = BITMAP_XMALLOC ();
+ ri.scratch = BITMAP_XMALLOC ();
+ ri.live = sbitmap_alloc (num_webs);
+ ri.nl_size = 0;
+ ri.num_reloads = 0;
+ for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
+ {
+ basic_block last_bb = NULL;
+ rtx last_block_insn;
+ int i, j;
+ if (!INSN_P (insn))
+ insn = prev_real_insn (insn);
+ while (insn && !(bb = BLOCK_FOR_INSN (insn)))
+ insn = prev_real_insn (insn);
+ if (!insn)
+ break;
+ i = bb->index + 2;
+ last_block_insn = insn;
+
+ sbitmap_zero (ri.live);
+ CLEAR_HARD_REG_SET (ri.colors_in_use);
+ EXECUTE_IF_SET_IN_BITMAP (live_at_end[i - 2], 0, j,
+ {
+ struct web *web = use2web[j];
+ struct web *aweb = alias (find_web_for_subweb (web));
+ /* A web is only live at end, if it isn't spilled. If we wouldn't
+ check this, the last uses of spilled web per basic block
+ wouldn't be detected as deaths, although they are in the final
+ code. This would lead to cumulating many loads without need,
+ only increasing register pressure. */
+ /* XXX do add also spilled webs which got a color for IR spilling.
+ Remember to not add to colors_in_use in that case. */
+ if (aweb->type != SPILLED /*|| aweb->color >= 0*/)
+ {
+ SET_BIT (ri.live, web->id);
+ if (aweb->type != SPILLED)
+ update_spill_colors (&(ri.colors_in_use), web, 1);
+ }
+ });
+
+ bitmap_clear (ri.need_reload);
+ ri.num_reloads = 0;
+ ri.any_spilltemps_spilled = 0;
+ if (flag_ra_ir_spilling)
+ {
+ struct dlist *d;
+ int pass;
+ /* XXX If we don't add spilled nodes into live above, the following
+ becomes an empty loop. */
+ for (pass = 0; pass < 2; pass++)
+ for (d = (pass) ? WEBS(SPILLED) : WEBS(COALESCED); d; d = d->next)
+ {
+ struct web *web = DLIST_WEB (d);
+ struct web *aweb = alias (web);
+ if (aweb->type != SPILLED)
+ continue;
+ if (is_partly_live (ri.live, web)
+ && spill_is_free (&(ri.colors_in_use), web) > 0)
+ {
+ ri.num_reloads++;
+ bitmap_set_bit (ri.need_reload, web->id);
+ /* Last using insn is somewhere in another block. */
+ web->last_use_insn = NULL_RTX;
+ }
+ }
+ }
+
+ last_bb = bb;
+ for (; insn; insn = PREV_INSN (insn))
+ {
+ struct ra_insn_info info;
+ unsigned int n;
+
+ if (INSN_P (insn) && BLOCK_FOR_INSN (insn) != last_bb)
+ {
+ int index = BLOCK_FOR_INSN (insn)->index + 2;
+ EXECUTE_IF_SET_IN_BITMAP (live_at_end[index - 2], 0, j,
+ {
+ struct web *web = use2web[j];
+ struct web *aweb = alias (find_web_for_subweb (web));
+ if (aweb->type != SPILLED)
+ {
+ SET_BIT (ri.live, web->id);
+ update_spill_colors (&(ri.colors_in_use), web, 1);
+ }
+ });
+ bitmap_clear (ri.scratch);
+ EXECUTE_IF_SET_IN_BITMAP (ri.need_reload, 0, j,
+ {
+ struct web *web2 = ID2WEB (j);
+ struct web *supweb2 = find_web_for_subweb (web2);
+ struct web *aweb2 = alias (supweb2);
+ if (spill_is_free (&(ri.colors_in_use), aweb2) <= 0)
+ {
+ if (!web2->in_load)
+ {
+ ri.needed_loads[ri.nl_size++] = web2;
+ web2->in_load = 1;
+ }
+ bitmap_set_bit (ri.scratch, j);
+ ri.num_reloads--;
+ }
+ });
+ bitmap_operation (ri.need_reload, ri.need_reload, ri.scratch,
+ BITMAP_AND_COMPL);
+ last_bb = BLOCK_FOR_INSN (insn);
+ last_block_insn = insn;
+ if (!INSN_P (last_block_insn))
+ last_block_insn = prev_real_insn (last_block_insn);
+ }
+
+ ri.need_load = 0;
+ if (INSN_P (insn))
+ info = insn_df[INSN_UID (insn)];
+
+ if (INSN_P (insn))
+ for (n = 0; n < info.num_defs; n++)
+ {
+ struct ref *ref = info.defs[n];
+ struct web *web = def2web[DF_REF_ID (ref)];
+ struct web *supweb = find_web_for_subweb (web);
+ int is_non_def = 0;
+ unsigned int n2;
+
+ supweb = find_web_for_subweb (web);
+ /* Webs which are defined here, but also used in the same insn
+ are rmw webs, or this use isn't a death because of looping
+ constructs. In neither case makes this def available it's
+ resources. Reloads for it are still needed, it's still
+ live and it's colors don't become free. */
+ for (n2 = 0; n2 < info.num_uses; n2++)
+ {
+ struct web *web2 = use2web[DF_REF_ID (info.uses[n2])];
+ if (supweb == find_web_for_subweb (web2))
+ {
+ is_non_def = 1;
+ break;
+ }
+ }
+ if (is_non_def)
+ continue;
+
+ if (!is_partly_live (ri.live, supweb))
+ bitmap_set_bit (useless_defs, DF_REF_ID (ref));
+
+ RESET_BIT (ri.live, web->id);
+ if (bitmap_bit_p (ri.need_reload, web->id))
+ {
+ ri.num_reloads--;
+ bitmap_clear_bit (ri.need_reload, web->id);
+ }
+ if (web != supweb)
+ {
+ /* XXX subwebs aren't precisely tracked here. We have
+ everything we need (inverse webs), but the code isn't
+ yet written. We need to make all completely
+ overlapping web parts non-live here. */
+ /* If by luck now the whole web isn't live anymore, no
+ reloads for it are needed. */
+ if (!is_partly_live (ri.live, supweb)
+ && bitmap_bit_p (ri.need_reload, supweb->id))
+ {
+ ri.num_reloads--;
+ bitmap_clear_bit (ri.need_reload, supweb->id);
+ }
+ }
+ else
+ {
+ struct web *sweb;
+ /* If the whole web is defined here, no parts of it are
+ live anymore and no reloads are needed for them. */
+ for (sweb = supweb->subreg_next; sweb;
+ sweb = sweb->subreg_next)
+ {
+ RESET_BIT (ri.live, sweb->id);
+ if (bitmap_bit_p (ri.need_reload, sweb->id))
+ {
+ ri.num_reloads--;
+ bitmap_clear_bit (ri.need_reload, sweb->id);
+ }
+ }
+ }
+ if (alias (supweb)->type != SPILLED)
+ update_spill_colors (&(ri.colors_in_use), web, 0);
+ }
+
+ nl_first_reload = ri.nl_size;
+
+ /* CALL_INSNs are not really deaths, but still more registers
+ are free after a call, than before.
+ XXX Note, that sometimes reload barfs when we emit insns between
+ a call and the insn which copies the return register into a
+ pseudo. */
+ if (GET_CODE (insn) == CALL_INSN)
+ ri.need_load = 1;
+ else if (INSN_P (insn))
+ for (n = 0; n < info.num_uses; n++)
+ {
+ struct web *web = use2web[DF_REF_ID (info.uses[n])];
+ struct web *supweb = find_web_for_subweb (web);
+ int is_death;
+ if (supweb->type == PRECOLORED
+ && TEST_HARD_REG_BIT (never_use_colors, supweb->color))
+ continue;
+ is_death = !TEST_BIT (ri.live, supweb->id);
+ is_death &= !TEST_BIT (ri.live, web->id);
+ if (is_death)
+ {
+ ri.need_load = 1;
+ bitmap_set_bit (new_deaths, INSN_UID (insn));
+ break;
+ }
+ }
+
+ if (INSN_P (insn) && ri.num_reloads)
+ {
+ int old_num_reloads = ri.num_reloads;
+ reloads_to_loads (&ri, info.uses, info.num_uses, use2web);
+
+ /* If this insn sets a pseudo, which isn't used later
+ (i.e. wasn't live before) it is a dead store. We need
+ to emit all reloads which have the same color as this def.
+ We don't need to check for non-liveness here to detect
+ the deadness (it anyway is too late, as we already cleared
+ the liveness in the first loop over the defs), because if it
+ _would_ be live here, no reload could have that color, as
+ they would already have been converted to a load. */
+ if (ri.num_reloads)
+ reloads_to_loads (&ri, info.defs, info.num_defs, def2web);
+ if (ri.num_reloads != old_num_reloads && !ri.need_load)
+ ri.need_load = 1;
+ }
+
+ if (ri.nl_size && (ri.need_load || ri.any_spilltemps_spilled))
+ emit_loads (&ri, nl_first_reload, last_block_insn);
+
+ if (INSN_P (insn) && flag_ra_ir_spilling)
+ for (n = 0; n < info.num_uses; n++)
+ {
+ struct web *web = use2web[DF_REF_ID (info.uses[n])];
+ struct web *aweb = alias (find_web_for_subweb (web));
+ if (aweb->type != SPILLED)
+ update_spill_colors (&(ri.colors_in_use), web, 1);
+ }
+
+ ri.any_spilltemps_spilled = 0;
+ if (INSN_P (insn))
+ for (n = 0; n < info.num_uses; n++)
+ {
+ struct web *web = use2web[DF_REF_ID (info.uses[n])];
+ struct web *supweb = find_web_for_subweb (web);
+ struct web *aweb = alias (supweb);
+ SET_BIT (ri.live, web->id);
+ if (aweb->type != SPILLED)
+ continue;
+ if (supweb->spill_temp)
+ ri.any_spilltemps_spilled = 1;
+ web->last_use_insn = insn;
+ if (!web->in_load)
+ {
+ if (spill_is_free (&(ri.colors_in_use), aweb) <= 0
+ || !flag_ra_ir_spilling)
+ {
+ ri.needed_loads[ri.nl_size++] = web;
+ web->in_load = 1;
+ web->one_load = 1;
+ }
+ else if (!bitmap_bit_p (ri.need_reload, web->id))
+ {
+ bitmap_set_bit (ri.need_reload, web->id);
+ ri.num_reloads++;
+ web->one_load = 1;
+ }
+ else
+ web->one_load = 0;
+ }
+ else
+ web->one_load = 0;
+ }
+
+ if (GET_CODE (insn) == CODE_LABEL)
+ break;
+ }
+
+ nl_first_reload = ri.nl_size;
+ if (ri.num_reloads)
+ {
+ int in_ir = 0;
+ edge e;
+ int num = 0;
+ HARD_REG_SET cum_colors, colors;
+ CLEAR_HARD_REG_SET (cum_colors);
+ for (e = bb->pred; e && num < 5; e = e->pred_next, num++)
+ {
+ int j;
+ CLEAR_HARD_REG_SET (colors);
+ EXECUTE_IF_SET_IN_BITMAP (live_at_end[e->src->index], 0, j,
+ {
+ struct web *web = use2web[j];
+ struct web *aweb = alias (find_web_for_subweb (web));
+ if (aweb->type != SPILLED)
+ update_spill_colors (&colors, web, 1);
+ });
+ IOR_HARD_REG_SET (cum_colors, colors);
+ }
+ if (num == 5)
+ in_ir = 1;
+
+ bitmap_clear (ri.scratch);
+ EXECUTE_IF_SET_IN_BITMAP (ri.need_reload, 0, j,
+ {
+ struct web *web2 = ID2WEB (j);
+ struct web *supweb2 = find_web_for_subweb (web2);
+ struct web *aweb2 = alias (supweb2);
+ /* block entry is IR boundary for aweb2?
+ Currently more some tries for good conditions. */
+ if (((ra_pass > 0 || supweb2->target_of_spilled_move)
+ && (1 || in_ir || spill_is_free (&cum_colors, aweb2) <= 0))
+ || (ra_pass == 1
+ && (in_ir
+ || spill_is_free (&cum_colors, aweb2) <= 0)))
+ {
+ if (!web2->in_load)
+ {
+ ri.needed_loads[ri.nl_size++] = web2;
+ web2->in_load = 1;
+ }
+ bitmap_set_bit (ri.scratch, j);
+ ri.num_reloads--;
+ }
+ });
+ bitmap_operation (ri.need_reload, ri.need_reload, ri.scratch,
+ BITMAP_AND_COMPL);
+ }
+
+ ri.need_load = 1;
+ emit_loads (&ri, nl_first_reload, last_block_insn);
+ if (ri.nl_size != 0 /*|| ri.num_reloads != 0*/)
+ abort ();
+ if (!insn)
+ break;
+ }
+ free (ri.needed_loads);
+ sbitmap_free (ri.live);
+ BITMAP_XFREE (ri.scratch);
+ BITMAP_XFREE (ri.need_reload);
+}
+
+/* WEBS is a web conflicting with a spilled one. Prepare it
+ to be able to rescan it in the next pass. Mark all it's uses
+ for checking, and clear the some members of their web parts
+ (of defs and uses). Notably don't clear the uplink. We don't
+ change the layout of this web, just it's conflicts.
+ Also remember all IDs of its uses in USES_AS_BITMAP. */
+
+static void
+mark_refs_for_checking (web, uses_as_bitmap)
+ struct web *web;
+ bitmap uses_as_bitmap;
+{
+ unsigned int i;
+ for (i = 0; i < web->num_uses; i++)
+ {
+ unsigned int id = DF_REF_ID (web->uses[i]);
+ SET_BIT (last_check_uses, id);
+ bitmap_set_bit (uses_as_bitmap, id);
+ web_parts[df->def_id + id].spanned_deaths = 0;
+ web_parts[df->def_id + id].crosses_call = 0;
+ }
+ for (i = 0; i < web->num_defs; i++)
+ {
+ unsigned int id = DF_REF_ID (web->defs[i]);
+ web_parts[id].spanned_deaths = 0;
+ web_parts[id].crosses_call = 0;
+ }
+}
+
+/* The last step of the spill phase is to set up the structures for
+ incrementally rebuilding the interference graph. We break up
+ the web part structure of all spilled webs, mark their uses for
+ rechecking, look at their neighbors, and clean up some global
+ information, we will rebuild. */
+
+static void
+detect_web_parts_to_rebuild ()
+{
+ bitmap uses_as_bitmap;
+ unsigned int i, pass;
+ struct dlist *d;
+ sbitmap already_webs = sbitmap_alloc (num_webs);
+
+ uses_as_bitmap = BITMAP_XMALLOC ();
+ if (last_check_uses)
+ sbitmap_free (last_check_uses);
+ last_check_uses = sbitmap_alloc (df->use_id);
+ sbitmap_zero (last_check_uses);
+ sbitmap_zero (already_webs);
+ /* We need to recheck all uses of all webs involved in spilling (and the
+ uses added by spill insns, but those are not analyzed yet).
+ Those are the spilled webs themself, webs coalesced to spilled ones,
+ and webs conflicting with any of them. */
+ for (pass = 0; pass < 2; pass++)
+ for (d = (pass == 0) ? WEBS(SPILLED) : WEBS(COALESCED); d; d = d->next)
+ {
+ struct web *web = DLIST_WEB (d);
+ struct conflict_link *wl;
+ unsigned int j;
+ /* This check is only needed for coalesced nodes, but hey. */
+ if (alias (web)->type != SPILLED)
+ continue;
+
+ /* For the spilled web itself we also need to clear it's
+ uplink, to be able to rebuild smaller webs. After all
+ spilling has split the web. */
+ for (i = 0; i < web->num_uses; i++)
+ {
+ unsigned int id = DF_REF_ID (web->uses[i]);
+ SET_BIT (last_check_uses, id);
+ bitmap_set_bit (uses_as_bitmap, id);
+ web_parts[df->def_id + id].uplink = NULL;
+ web_parts[df->def_id + id].spanned_deaths = 0;
+ web_parts[df->def_id + id].crosses_call = 0;
+ }
+ for (i = 0; i < web->num_defs; i++)
+ {
+ unsigned int id = DF_REF_ID (web->defs[i]);
+ web_parts[id].uplink = NULL;
+ web_parts[id].spanned_deaths = 0;
+ web_parts[id].crosses_call = 0;
+ }
+
+ /* Now look at all neighbors of this spilled web. */
+ if (web->have_orig_conflicts)
+ wl = web->orig_conflict_list;
+ else
+ wl = web->conflict_list;
+ for (; wl; wl = wl->next)
+ {
+ if (TEST_BIT (already_webs, wl->t->id))
+ continue;
+ SET_BIT (already_webs, wl->t->id);
+ mark_refs_for_checking (wl->t, uses_as_bitmap);
+ }
+ EXECUTE_IF_SET_IN_BITMAP (web->useless_conflicts, 0, j,
+ {
+ struct web *web2 = ID2WEB (j);
+ if (TEST_BIT (already_webs, web2->id))
+ continue;
+ SET_BIT (already_webs, web2->id);
+ mark_refs_for_checking (web2, uses_as_bitmap);
+ });
+ }
+
+ /* We also recheck unconditionally all uses of any hardregs. This means
+ we _can_ delete all these uses from the live_at_end[] bitmaps.
+ And because we sometimes delete insn refering to hardregs (when
+ they became useless because they setup a rematerializable pseudo, which
+ then was rematerialized), some of those uses will go away with the next
+ df_analyse(). This means we even _must_ delete those uses from
+ the live_at_end[] bitmaps. For simplicity we simply delete
+ all of them. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (!fixed_regs[i])
+ {
+ struct df_link *link;
+ for (link = df->regs[i].uses; link; link = link->next)
+ if (link->ref)
+ bitmap_set_bit (uses_as_bitmap, DF_REF_ID (link->ref));
+ }
+
+ /* The information in live_at_end[] will be rebuild for all uses
+ we recheck, so clear it here (the uses of spilled webs, might
+ indeed not become member of it again). */
+ live_at_end -= 2;
+ for (i = 0; i < (unsigned int) last_basic_block + 2; i++)
+ bitmap_operation (live_at_end[i], live_at_end[i], uses_as_bitmap,
+ BITMAP_AND_COMPL);
+ live_at_end += 2;
+
+ if (rtl_dump_file && (debug_new_regalloc & DUMP_REBUILD) != 0)
+ {
+ ra_debug_msg (DUMP_REBUILD, "need to check these uses:\n");
+ dump_sbitmap_file (rtl_dump_file, last_check_uses);
+ }
+ sbitmap_free (already_webs);
+ BITMAP_XFREE (uses_as_bitmap);
+}
+
+/* Statistics about deleted insns, which are useless now. */
+static unsigned int deleted_def_insns;
+static unsigned HOST_WIDE_INT deleted_def_cost;
+
+/* In rewrite_program2() we noticed, when a certain insn set a pseudo
+ which wasn't live. Try to delete all those insns. */
+
+static void
+delete_useless_defs ()
+{
+ unsigned int i;
+ /* If the insn only sets the def without any sideeffect (besides
+ clobbers or uses), we can delete it. single_set() also tests
+ for INSN_P(insn). */
+ EXECUTE_IF_SET_IN_BITMAP (useless_defs, 0, i,
+ {
+ rtx insn = DF_REF_INSN (df->defs[i]);
+ rtx set = single_set (insn);
+ struct web *web = find_web_for_subweb (def2web[i]);
+ if (set && web->type == SPILLED && web->stack_slot == NULL)
+ {
+ deleted_def_insns++;
+ deleted_def_cost += BLOCK_FOR_INSN (insn)->frequency + 1;
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ df_insn_modify (df, BLOCK_FOR_INSN (insn), insn);
+ }
+ });
+}
+
+/* Look for spilled webs, on whose behalf no insns were emitted.
+ We inversify (sp?) the changed flag of the webs, so after this function
+ a nonzero changed flag means, that this web was not spillable (at least
+ in this pass). */
+
+static void
+detect_non_changed_webs ()
+{
+ struct dlist *d, *d_next;
+ for (d = WEBS(SPILLED); d; d = d_next)
+ {
+ struct web *web = DLIST_WEB (d);
+ d_next = d->next;
+ if (!web->changed)
+ {
+ ra_debug_msg (DUMP_PROCESS, "no insns emitted for spilled web %d\n",
+ web->id);
+ remove_web_from_list (web);
+ put_web (web, COLORED);
+ web->changed = 1;
+ }
+ else
+ web->changed = 0;
+ /* From now on web->changed is used as the opposite flag.
+ I.e. colored webs, which have changed set were formerly
+ spilled webs for which no insns were emitted. */
+ }
+}
+
+/* Before spilling we clear the changed flags for all spilled webs. */
+
+static void
+reset_changed_flag ()
+{
+ struct dlist *d;
+ for (d = WEBS(SPILLED); d; d = d->next)
+ DLIST_WEB(d)->changed = 0;
+}
+
+/* The toplevel function for this file. Given a colorized graph,
+ and lists of spilled, coalesced and colored webs, we add some
+ spill code. This also sets up the structures for incrementally
+ building the interference graph in the next pass. */
+
+void
+actual_spill ()
+{
+ int i;
+ bitmap new_deaths = BITMAP_XMALLOC ();
+ reset_changed_flag ();
+ spill_coalprop ();
+ choose_spill_colors ();
+ useless_defs = BITMAP_XMALLOC ();
+ if (flag_ra_improved_spilling)
+ rewrite_program2 (new_deaths);
+ else
+ rewrite_program (new_deaths);
+ insert_stores (new_deaths);
+ delete_useless_defs ();
+ BITMAP_XFREE (useless_defs);
+ sbitmap_free (insns_with_deaths);
+ insns_with_deaths = sbitmap_alloc (get_max_uid ());
+ death_insns_max_uid = get_max_uid ();
+ sbitmap_zero (insns_with_deaths);
+ EXECUTE_IF_SET_IN_BITMAP (new_deaths, 0, i,
+ { SET_BIT (insns_with_deaths, i);});
+ detect_non_changed_webs ();
+ detect_web_parts_to_rebuild ();
+ BITMAP_XFREE (new_deaths);
+}
+
+/* A bitmap of pseudo reg numbers which are coalesced directly
+ to a hardreg. Set in emit_colors(), used and freed in
+ remove_suspicious_death_notes(). */
+static bitmap regnos_coalesced_to_hardregs;
+
+/* Create new pseudos for each web we colored, change insns to
+ use those pseudos and set up ra_reg_renumber. */
+
+void
+emit_colors (df)
+ struct df *df;
+{
+ unsigned int i;
+ int si;
+ struct web *web;
+ int old_max_regno = max_reg_num ();
+ regset old_regs;
+ basic_block bb;
+
+ /* This bitmap is freed in remove_suspicious_death_notes(),
+ which is also the user of it. */
+ regnos_coalesced_to_hardregs = BITMAP_XMALLOC ();
+ /* First create the (REG xx) rtx's for all webs, as we need to know
+ the number, to make sure, flow has enough memory for them in the
+ various tables. */
+ for (i = 0; i < num_webs - num_subwebs; i++)
+ {
+ web = ID2WEB (i);
+ if (web->type != COLORED && web->type != COALESCED)
+ continue;
+ if (web->type == COALESCED && alias (web)->type == COLORED)
+ continue;
+ if (web->reg_rtx || web->regno < FIRST_PSEUDO_REGISTER)
+ abort ();
+
+ if (web->regno >= max_normal_pseudo)
+ {
+ rtx place;
+ if (web->color == an_unusable_color)
+ {
+ unsigned int inherent_size = PSEUDO_REGNO_BYTES (web->regno);
+ unsigned int total_size = MAX (inherent_size, 0);
+ place = assign_stack_local (PSEUDO_REGNO_MODE (web->regno),
+ total_size,
+ inherent_size == total_size ? 0 : -1);
+ RTX_UNCHANGING_P (place) =
+ RTX_UNCHANGING_P (regno_reg_rtx[web->regno]);
+ set_mem_alias_set (place, new_alias_set ());
+ }
+ else
+ {
+ place = gen_reg_rtx (PSEUDO_REGNO_MODE (web->regno));
+ }
+ web->reg_rtx = place;
+ }
+ else
+ {
+ /* Special case for i386 'fix_truncdi_nomemory' insn.
+ We must choose mode from insns not from PSEUDO_REGNO_MODE.
+ Actual only for clobbered register. */
+ if (web->num_uses == 0 && web->num_defs == 1)
+ web->reg_rtx = gen_reg_rtx (GET_MODE (DF_REF_REAL_REG (web->defs[0])));
+ else
+ web->reg_rtx = gen_reg_rtx (PSEUDO_REGNO_MODE (web->regno));
+ /* Remember the different parts directly coalesced to a hardreg. */
+ if (web->type == COALESCED)
+ bitmap_set_bit (regnos_coalesced_to_hardregs, REGNO (web->reg_rtx));
+ }
+ }
+ ra_max_regno = max_regno = max_reg_num ();
+ allocate_reg_info (max_regno, FALSE, FALSE);
+ ra_reg_renumber = (short *) xmalloc (max_regno * sizeof (short));
+ for (si = 0; si < max_regno; si++)
+ ra_reg_renumber[si] = -1;
+
+ /* Then go through all references, and replace them by a new
+ pseudoreg for each web. All uses. */
+ /* XXX
+ Beware: The order of replacements (first uses, then defs) matters only
+ for read-mod-write insns, where the RTL expression for the REG is
+ shared between def and use. For normal rmw insns we connected all such
+ webs, i.e. both the use and the def (which are the same memory)
+ there get the same new pseudo-reg, so order would not matter.
+ _However_ we did not connect webs, were the read cycle was an
+ uninitialized read. If we now would first replace the def reference
+ and then the use ref, we would initialize it with a REG rtx, which
+ gets never initialized, and yet more wrong, which would overwrite
+ the definition of the other REG rtx. So we must replace the defs last.
+ */
+ for (i = 0; i < df->use_id; i++)
+ if (df->uses[i])
+ {
+ regset rs = DF_REF_BB (df->uses[i])->global_live_at_start;
+ rtx regrtx;
+ web = use2web[i];
+ web = find_web_for_subweb (web);
+ if (web->type != COLORED && web->type != COALESCED)
+ continue;
+ regrtx = alias (web)->reg_rtx;
+ if (!regrtx)
+ regrtx = web->reg_rtx;
+ *DF_REF_REAL_LOC (df->uses[i]) = regrtx;
+ if (REGNO_REG_SET_P (rs, web->regno) && REG_P (regrtx))
+ {
+ /*CLEAR_REGNO_REG_SET (rs, web->regno);*/
+ SET_REGNO_REG_SET (rs, REGNO (regrtx));
+ }
+ }
+
+ /* And all defs. */
+ for (i = 0; i < df->def_id; i++)
+ {
+ regset rs;
+ rtx regrtx;
+ if (!df->defs[i])
+ continue;
+ rs = DF_REF_BB (df->defs[i])->global_live_at_start;
+ web = def2web[i];
+ web = find_web_for_subweb (web);
+ if (web->type != COLORED && web->type != COALESCED)
+ continue;
+ regrtx = alias (web)->reg_rtx;
+ if (!regrtx)
+ regrtx = web->reg_rtx;
+ *DF_REF_REAL_LOC (df->defs[i]) = regrtx;
+ if (REGNO_REG_SET_P (rs, web->regno) && REG_P (regrtx))
+ {
+ /* Don't simply clear the current regno, as it might be
+ replaced by two webs. */
+ /*CLEAR_REGNO_REG_SET (rs, web->regno);*/
+ SET_REGNO_REG_SET (rs, REGNO (regrtx));
+ }
+ }
+
+ /* And now set up the ra_reg_renumber array for reload with all the new
+ pseudo-regs. */
+ for (i = 0; i < num_webs - num_subwebs; i++)
+ {
+ web = ID2WEB (i);
+ if (web->reg_rtx && REG_P (web->reg_rtx))
+ {
+ int r = REGNO (web->reg_rtx);
+ ra_reg_renumber[r] = web->color;
+ ra_debug_msg (DUMP_COLORIZE, "Renumber pseudo %d (== web %d) to %d\n",
+ r, web->id, ra_reg_renumber[r]);
+ }
+ }
+
+ old_regs = BITMAP_XMALLOC ();
+ for (si = FIRST_PSEUDO_REGISTER; si < old_max_regno; si++)
+ SET_REGNO_REG_SET (old_regs, si);
+ FOR_EACH_BB (bb)
+ {
+ AND_COMPL_REG_SET (bb->global_live_at_start, old_regs);
+ AND_COMPL_REG_SET (bb->global_live_at_end, old_regs);
+ }
+ BITMAP_XFREE (old_regs);
+}
+
+/* Delete some coalesced moves from the insn stream. */
+
+void
+delete_moves ()
+{
+ struct move_list *ml;
+ struct web *s, *t;
+ /* XXX Beware: We normally would test here each copy insn, if
+ source and target got the same color (either by coalescing or by pure
+ luck), and then delete it.
+ This will currently not work. One problem is, that we don't color
+ the regs ourself, but instead defer to reload. So the colorization
+ is only a kind of suggestion, which reload doesn't have to follow.
+ For webs which are coalesced to a normal colored web, we only have one
+ new pseudo, so in this case we indeed can delete copy insns involving
+ those (because even if reload colors them different from our suggestion,
+ it still has to color them the same, as only one pseudo exists). But for
+ webs coalesced to precolored ones, we have not a single pseudo, but
+ instead one for each coalesced web. This means, that we can't delete
+ copy insns, where source and target are webs coalesced to precolored
+ ones, because then the connection between both webs is destroyed. Note
+ that this not only means copy insns, where one side is the precolored one
+ itself, but also those between webs which are coalesced to one color.
+ Also because reload we can't delete copy insns which involve any
+ precolored web at all. These often have also special meaning (e.g.
+ copying a return value of a call to a pseudo, or copying pseudo to the
+ return register), and the deletion would confuse reload in thinking the
+ pseudo isn't needed. One of those days reload will get away and we can
+ do everything we want.
+ In effect because of the later reload, we can't base our deletion on the
+ colors itself, but instead need to base them on the newly created
+ pseudos. */
+ for (ml = wl_moves; ml; ml = ml->next)
+ /* The real condition we would ideally use is: s->color == t->color.
+ Additionally: s->type != PRECOLORED && t->type != PRECOLORED, in case
+ we want to prevent deletion of "special" copies. */
+ if (ml->move
+ && (s = alias (ml->move->source_web))->reg_rtx
+ == (t = alias (ml->move->target_web))->reg_rtx
+ && s->type != PRECOLORED && t->type != PRECOLORED)
+ {
+ basic_block bb = BLOCK_FOR_INSN (ml->move->insn);
+ df_insn_delete (df, bb, ml->move->insn);
+ deleted_move_insns++;
+ deleted_move_cost += bb->frequency + 1;
+ }
+}
+
+/* Due to resons documented elsewhere we create different pseudos
+ for all webs coalesced to hardregs. For these parts life_analysis()
+ might have added REG_DEAD notes without considering, that only this part
+ but not the whole coalesced web dies. The RTL is correct, there is no
+ coalescing yet. But if later reload's alter_reg() substitutes the
+ hardreg into the REG rtx it looks like that particular hardreg dies here,
+ although (due to coalescing) it still is live. This might make different
+ places of reload think, it can use that hardreg for reload regs,
+ accidentally overwriting it. So we need to remove those REG_DEAD notes.
+ (Or better teach life_analysis() and reload about our coalescing, but
+ that comes later) Bah. */
+
+void
+remove_suspicious_death_notes ()
+{
+ rtx insn;
+ for (insn = get_insns(); insn; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ {
+ rtx *pnote = &REG_NOTES (insn);
+ while (*pnote)
+ {
+ rtx note = *pnote;
+ if ((REG_NOTE_KIND (note) == REG_DEAD
+ || REG_NOTE_KIND (note) == REG_UNUSED)
+ && (GET_CODE (XEXP (note, 0)) == REG
+ && bitmap_bit_p (regnos_coalesced_to_hardregs,
+ REGNO (XEXP (note, 0)))))
+ *pnote = XEXP (note, 1);
+ else
+ pnote = &XEXP (*pnote, 1);
+ }
+ }
+ BITMAP_XFREE (regnos_coalesced_to_hardregs);
+ regnos_coalesced_to_hardregs = NULL;
+}
+
+/* Allocate space for max_reg_num() pseudo registers, and
+ fill reg_renumber[] from ra_reg_renumber[]. If FREE_IT
+ is nonzero, also free ra_reg_renumber and reset ra_max_regno. */
+
+void
+setup_renumber (free_it)
+ int free_it;
+{
+ int i;
+ max_regno = max_reg_num ();
+ allocate_reg_info (max_regno, FALSE, TRUE);
+ for (i = 0; i < max_regno; i++)
+ {
+ reg_renumber[i] = (i < ra_max_regno) ? ra_reg_renumber[i] : -1;
+ }
+ if (free_it)
+ {
+ free (ra_reg_renumber);
+ ra_reg_renumber = NULL;
+ ra_max_regno = 0;
+ }
+}
+
+/* Dump the costs and savings due to spilling, i.e. of added spill insns
+ and removed moves or useless defs. */
+
+void
+dump_cost (level)
+ unsigned int level;
+{
+ ra_debug_msg (level, "Instructions for spilling\n added:\n");
+ ra_debug_msg (level, " loads =%d cost=", emitted_spill_loads);
+ ra_debug_msg (level, HOST_WIDE_INT_PRINT_UNSIGNED, spill_load_cost);
+ ra_debug_msg (level, "\n stores=%d cost=", emitted_spill_stores);
+ ra_debug_msg (level, HOST_WIDE_INT_PRINT_UNSIGNED, spill_store_cost);
+ ra_debug_msg (level, "\n remat =%d cost=", emitted_remat);
+ ra_debug_msg (level, HOST_WIDE_INT_PRINT_UNSIGNED, spill_remat_cost);
+ ra_debug_msg (level, "\n removed:\n moves =%d cost=", deleted_move_insns);
+ ra_debug_msg (level, HOST_WIDE_INT_PRINT_UNSIGNED, deleted_move_cost);
+ ra_debug_msg (level, "\n others=%d cost=", deleted_def_insns);
+ ra_debug_msg (level, HOST_WIDE_INT_PRINT_UNSIGNED, deleted_def_cost);
+ ra_debug_msg (level, "\n");
+}
+
+/* Initialization of the rewrite phase. */
+
+void
+ra_rewrite_init ()
+{
+ emitted_spill_loads = 0;
+ emitted_spill_stores = 0;
+ emitted_remat = 0;
+ spill_load_cost = 0;
+ spill_store_cost = 0;
+ spill_remat_cost = 0;
+ deleted_move_insns = 0;
+ deleted_move_cost = 0;
+ deleted_def_insns = 0;
+ deleted_def_cost = 0;
+}
+
+/*
+vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
+*/
diff --git a/contrib/gcc/ra.c b/contrib/gcc/ra.c
new file mode 100644
index 0000000..ab52b42
--- /dev/null
+++ b/contrib/gcc/ra.c
@@ -0,0 +1,899 @@
+/* Graph coloring register allocator
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Contributed by Michael Matz <matz@suse.de>
+ and Daniel Berlin <dan@cgsoftware.com>.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along
+ with GCC; see the file COPYING. If not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "insn-config.h"
+#include "recog.h"
+#include "reload.h"
+#include "integrate.h"
+#include "function.h"
+#include "regs.h"
+#include "obstack.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
+#include "df.h"
+#include "expr.h"
+#include "output.h"
+#include "toplev.h"
+#include "flags.h"
+#include "ra.h"
+
+/* This is the toplevel file of a graph coloring register allocator.
+ It is able to act like a George & Appel allocator, i.e. with iterative
+ coalescing plus spill coalescing/propagation.
+ And it can act as a traditional Briggs allocator, although with
+ optimistic coalescing. Additionally it has a custom pass, which
+ tries to reduce the overall cost of the colored graph.
+
+ We support two modes of spilling: spill-everywhere, which is extremely
+ fast, and interference region spilling, which reduces spill code to a
+ large extent, but is slower.
+
+ Helpful documents:
+
+ Briggs, P., Cooper, K. D., and Torczon, L. 1994. Improvements to graph
+ coloring register allocation. ACM Trans. Program. Lang. Syst. 16, 3 (May),
+ 428-455.
+
+ Bergner, P., Dahl, P., Engebretsen, D., and O'Keefe, M. 1997. Spill code
+ minimization via interference region spilling. In Proc. ACM SIGPLAN '97
+ Conf. on Prog. Language Design and Implementation. ACM, 287-295.
+
+ George, L., Appel, A.W. 1996. Iterated register coalescing.
+ ACM Trans. Program. Lang. Syst. 18, 3 (May), 300-324.
+
+*/
+
+/* This file contains the main entry point (reg_alloc), some helper routines
+ used by more than one file of the register allocator, and the toplevel
+ driver procedure (one_pass). */
+
+/* Things, one might do somewhen:
+
+ * Lattice based rematerialization
+ * create definitions of ever-life regs at the beginning of
+ the insn chain
+ * insert loads as soon, stores as late as possile
+ * insert spill insns as outward as possible (either looptree, or LCM)
+ * reuse stack-slots
+ * delete coalesced insns. Partly done. The rest can only go, when we get
+ rid of reload.
+ * don't destroy coalescing information completely when spilling
+ * use the constraints from asms
+ */
+
+static struct obstack ra_obstack;
+static void create_insn_info PARAMS ((struct df *));
+static void free_insn_info PARAMS ((void));
+static void alloc_mem PARAMS ((struct df *));
+static void free_mem PARAMS ((struct df *));
+static void free_all_mem PARAMS ((struct df *df));
+static int one_pass PARAMS ((struct df *, int));
+static void check_df PARAMS ((struct df *));
+static void init_ra PARAMS ((void));
+
+void reg_alloc PARAMS ((void));
+
+/* These global variables are "internal" to the register allocator.
+ They are all documented at their declarations in ra.h. */
+
+/* Somewhen we want to get rid of one of those sbitmaps.
+ (for now I need the sup_igraph to note if there is any conflict between
+ parts of webs at all. I can't use igraph for this, as there only the real
+ conflicts are noted.) This is only used to prevent coalescing two
+ conflicting webs, were only parts of them are in conflict. */
+sbitmap igraph;
+sbitmap sup_igraph;
+
+/* Note the insns not inserted by the allocator, where we detected any
+ deaths of pseudos. It is used to detect closeness of defs and uses.
+ In the first pass this is empty (we could initialize it from REG_DEAD
+ notes), in the other passes it is left from the pass before. */
+sbitmap insns_with_deaths;
+int death_insns_max_uid;
+
+struct web_part *web_parts;
+
+unsigned int num_webs;
+unsigned int num_subwebs;
+unsigned int num_allwebs;
+struct web **id2web;
+struct web *hardreg2web[FIRST_PSEUDO_REGISTER];
+struct web **def2web;
+struct web **use2web;
+struct move_list *wl_moves;
+int ra_max_regno;
+short *ra_reg_renumber;
+struct df *df;
+bitmap *live_at_end;
+int ra_pass;
+unsigned int max_normal_pseudo;
+int an_unusable_color;
+
+/* The different lists on which a web can be (based on the type). */
+struct dlist *web_lists[(int) LAST_NODE_TYPE];
+
+unsigned int last_def_id;
+unsigned int last_use_id;
+unsigned int last_num_webs;
+int last_max_uid;
+sbitmap last_check_uses;
+unsigned int remember_conflicts;
+
+int orig_max_uid;
+
+HARD_REG_SET never_use_colors;
+HARD_REG_SET usable_regs[N_REG_CLASSES];
+unsigned int num_free_regs[N_REG_CLASSES];
+HARD_REG_SET hardregs_for_mode[NUM_MACHINE_MODES];
+unsigned char byte2bitcount[256];
+
+unsigned int debug_new_regalloc = -1;
+int flag_ra_biased = 0;
+int flag_ra_improved_spilling = 0;
+int flag_ra_ir_spilling = 0;
+int flag_ra_optimistic_coalescing = 0;
+int flag_ra_break_aliases = 0;
+int flag_ra_merge_spill_costs = 0;
+int flag_ra_spill_every_use = 0;
+int flag_ra_dump_notes = 0;
+
+/* Fast allocation of small objects, which live until the allocator
+ is done. Allocate an object of SIZE bytes. */
+
+void *
+ra_alloc (size)
+ size_t size;
+{
+ return obstack_alloc (&ra_obstack, size);
+}
+
+/* Like ra_alloc(), but clear the returned memory. */
+
+void *
+ra_calloc (size)
+ size_t size;
+{
+ void *p = obstack_alloc (&ra_obstack, size);
+ memset (p, 0, size);
+ return p;
+}
+
+/* Returns the number of hardregs in HARD_REG_SET RS. */
+
+int
+hard_regs_count (rs)
+ HARD_REG_SET rs;
+{
+ int count = 0;
+#ifdef HARD_REG_SET
+ while (rs)
+ {
+ unsigned char byte = rs & 0xFF;
+ rs >>= 8;
+ /* Avoid memory access, if nothing is set. */
+ if (byte)
+ count += byte2bitcount[byte];
+ }
+#else
+ unsigned int ofs;
+ for (ofs = 0; ofs < HARD_REG_SET_LONGS; ofs++)
+ {
+ HARD_REG_ELT_TYPE elt = rs[ofs];
+ while (elt)
+ {
+ unsigned char byte = elt & 0xFF;
+ elt >>= 8;
+ if (byte)
+ count += byte2bitcount[byte];
+ }
+ }
+#endif
+ return count;
+}
+
+/* Basically like emit_move_insn (i.e. validifies constants and such),
+ but also handle MODE_CC moves (but then the operands must already
+ be basically valid. */
+
+rtx
+ra_emit_move_insn (x, y)
+ rtx x, y;
+{
+ enum machine_mode mode = GET_MODE (x);
+ if (GET_MODE_CLASS (mode) == MODE_CC)
+ return emit_insn (gen_move_insn (x, y));
+ else
+ return emit_move_insn (x, y);
+}
+
+int insn_df_max_uid;
+struct ra_insn_info *insn_df;
+static struct ref **refs_for_insn_df;
+
+/* Create the insn_df structure for each insn to have fast access to
+ all valid defs and uses in an insn. */
+
+static void
+create_insn_info (df)
+ struct df *df;
+{
+ rtx insn;
+ struct ref **act_refs;
+ insn_df_max_uid = get_max_uid ();
+ insn_df = xcalloc (insn_df_max_uid, sizeof (insn_df[0]));
+ refs_for_insn_df = xcalloc (df->def_id + df->use_id, sizeof (struct ref *));
+ act_refs = refs_for_insn_df;
+ /* We create those things backwards to mimic the order in which
+ the insns are visited in rewrite_program2() and live_in(). */
+ for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
+ {
+ int uid = INSN_UID (insn);
+ unsigned int n;
+ struct df_link *link;
+ if (!INSN_P (insn))
+ continue;
+ for (n = 0, link = DF_INSN_DEFS (df, insn); link; link = link->next)
+ if (link->ref
+ && (DF_REF_REGNO (link->ref) >= FIRST_PSEUDO_REGISTER
+ || !TEST_HARD_REG_BIT (never_use_colors,
+ DF_REF_REGNO (link->ref))))
+ {
+ if (n == 0)
+ insn_df[uid].defs = act_refs;
+ insn_df[uid].defs[n++] = link->ref;
+ }
+ act_refs += n;
+ insn_df[uid].num_defs = n;
+ for (n = 0, link = DF_INSN_USES (df, insn); link; link = link->next)
+ if (link->ref
+ && (DF_REF_REGNO (link->ref) >= FIRST_PSEUDO_REGISTER
+ || !TEST_HARD_REG_BIT (never_use_colors,
+ DF_REF_REGNO (link->ref))))
+ {
+ if (n == 0)
+ insn_df[uid].uses = act_refs;
+ insn_df[uid].uses[n++] = link->ref;
+ }
+ act_refs += n;
+ insn_df[uid].num_uses = n;
+ }
+ if (refs_for_insn_df + (df->def_id + df->use_id) < act_refs)
+ abort ();
+}
+
+/* Free the insn_df structures. */
+
+static void
+free_insn_info ()
+{
+ free (refs_for_insn_df);
+ refs_for_insn_df = NULL;
+ free (insn_df);
+ insn_df = NULL;
+ insn_df_max_uid = 0;
+}
+
+/* Search WEB for a subweb, which represents REG. REG needs to
+ be a SUBREG, and the inner reg of it needs to be the one which is
+ represented by WEB. Returns the matching subweb or NULL. */
+
+struct web *
+find_subweb (web, reg)
+ struct web *web;
+ rtx reg;
+{
+ struct web *w;
+ if (GET_CODE (reg) != SUBREG)
+ abort ();
+ for (w = web->subreg_next; w; w = w->subreg_next)
+ if (GET_MODE (w->orig_x) == GET_MODE (reg)
+ && SUBREG_BYTE (w->orig_x) == SUBREG_BYTE (reg))
+ return w;
+ return NULL;
+}
+
+/* Similar to find_subweb(), but matches according to SIZE_WORD,
+ a collection of the needed size and offset (in bytes). */
+
+struct web *
+find_subweb_2 (web, size_word)
+ struct web *web;
+ unsigned int size_word;
+{
+ struct web *w = web;
+ if (size_word == GET_MODE_SIZE (GET_MODE (web->orig_x)))
+ /* size_word == size means BYTE_BEGIN(size_word) == 0. */
+ return web;
+ for (w = web->subreg_next; w; w = w->subreg_next)
+ {
+ unsigned int bl = rtx_to_bits (w->orig_x);
+ if (size_word == bl)
+ return w;
+ }
+ return NULL;
+}
+
+/* Returns the superweb for SUBWEB. */
+
+struct web *
+find_web_for_subweb_1 (subweb)
+ struct web *subweb;
+{
+ while (subweb->parent_web)
+ subweb = subweb->parent_web;
+ return subweb;
+}
+
+/* Determine if two hard register sets intersect.
+ Return 1 if they do. */
+
+int
+hard_regs_intersect_p (a, b)
+ HARD_REG_SET *a, *b;
+{
+ HARD_REG_SET c;
+ COPY_HARD_REG_SET (c, *a);
+ AND_HARD_REG_SET (c, *b);
+ GO_IF_HARD_REG_SUBSET (c, reg_class_contents[(int) NO_REGS], lose);
+ return 1;
+lose:
+ return 0;
+}
+
+/* Allocate and initialize the memory necessary for one pass of the
+ register allocator. */
+
+static void
+alloc_mem (df)
+ struct df *df;
+{
+ int i;
+ ra_build_realloc (df);
+ if (!live_at_end)
+ {
+ live_at_end = (bitmap *) xmalloc ((last_basic_block + 2)
+ * sizeof (bitmap));
+ for (i = 0; i < last_basic_block + 2; i++)
+ live_at_end[i] = BITMAP_XMALLOC ();
+ live_at_end += 2;
+ }
+ create_insn_info (df);
+}
+
+/* Free the memory which isn't necessary for the next pass. */
+
+static void
+free_mem (df)
+ struct df *df ATTRIBUTE_UNUSED;
+{
+ free_insn_info ();
+ ra_build_free ();
+}
+
+/* Free all memory allocated for the register allocator. Used, when
+ it's done. */
+
+static void
+free_all_mem (df)
+ struct df *df;
+{
+ unsigned int i;
+ live_at_end -= 2;
+ for (i = 0; i < (unsigned)last_basic_block + 2; i++)
+ BITMAP_XFREE (live_at_end[i]);
+ free (live_at_end);
+
+ ra_colorize_free_all ();
+ ra_build_free_all (df);
+ obstack_free (&ra_obstack, NULL);
+}
+
+static long ticks_build;
+static long ticks_rebuild;
+
+/* Perform one pass of allocation. Returns nonzero, if some spill code
+ was added, i.e. if the allocator needs to rerun. */
+
+static int
+one_pass (df, rebuild)
+ struct df *df;
+ int rebuild;
+{
+ long ticks = clock ();
+ int something_spilled;
+ remember_conflicts = 0;
+
+ /* Build the complete interference graph, or if this is not the first
+ pass, rebuild it incrementally. */
+ build_i_graph (df);
+
+ /* From now on, if we create new conflicts, we need to remember the
+ initial list of conflicts per web. */
+ remember_conflicts = 1;
+ if (!rebuild)
+ dump_igraph_machine ();
+
+ /* Colorize the I-graph. This results in either a list of
+ spilled_webs, in which case we need to run the spill phase, and
+ rerun the allocator, or that list is empty, meaning we are done. */
+ ra_colorize_graph (df);
+
+ last_max_uid = get_max_uid ();
+ /* actual_spill() might change WEBS(SPILLED) and even empty it,
+ so we need to remember it's state. */
+ something_spilled = !!WEBS(SPILLED);
+
+ /* Add spill code if necessary. */
+ if (something_spilled)
+ actual_spill ();
+
+ ticks = clock () - ticks;
+ if (rebuild)
+ ticks_rebuild += ticks;
+ else
+ ticks_build += ticks;
+ return something_spilled;
+}
+
+/* Initialize various arrays for the register allocator. */
+
+static void
+init_ra ()
+{
+ int i;
+ HARD_REG_SET rs;
+#ifdef ELIMINABLE_REGS
+ static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
+ unsigned int j;
+#endif
+ int need_fp
+ = (! flag_omit_frame_pointer
+#ifdef EXIT_IGNORE_STACK
+ || (current_function_calls_alloca && EXIT_IGNORE_STACK)
+#endif
+ || FRAME_POINTER_REQUIRED);
+
+ ra_colorize_init ();
+
+ /* We can't ever use any of the fixed regs. */
+ COPY_HARD_REG_SET (never_use_colors, fixed_reg_set);
+
+ /* Additionally don't even try to use hardregs, which we already
+ know are not eliminable. This includes also either the
+ hard framepointer or all regs which are eliminable into the
+ stack pointer, if need_fp is set. */
+#ifdef ELIMINABLE_REGS
+ for (j = 0; j < ARRAY_SIZE (eliminables); j++)
+ {
+ if (! CAN_ELIMINATE (eliminables[j].from, eliminables[j].to)
+ || (eliminables[j].to == STACK_POINTER_REGNUM && need_fp))
+ for (i = HARD_REGNO_NREGS (eliminables[j].from, Pmode); i--;)
+ SET_HARD_REG_BIT (never_use_colors, eliminables[j].from + i);
+ }
+#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+ if (need_fp)
+ for (i = HARD_REGNO_NREGS (HARD_FRAME_POINTER_REGNUM, Pmode); i--;)
+ SET_HARD_REG_BIT (never_use_colors, HARD_FRAME_POINTER_REGNUM + i);
+#endif
+
+#else
+ if (need_fp)
+ for (i = HARD_REGNO_NREGS (FRAME_POINTER_REGNUM, Pmode); i--;)
+ SET_HARD_REG_BIT (never_use_colors, FRAME_POINTER_REGNUM + i);
+#endif
+
+ /* Stack and argument pointer are also rather useless to us. */
+ for (i = HARD_REGNO_NREGS (STACK_POINTER_REGNUM, Pmode); i--;)
+ SET_HARD_REG_BIT (never_use_colors, STACK_POINTER_REGNUM + i);
+
+ for (i = HARD_REGNO_NREGS (ARG_POINTER_REGNUM, Pmode); i--;)
+ SET_HARD_REG_BIT (never_use_colors, ARG_POINTER_REGNUM + i);
+
+ for (i = 0; i < 256; i++)
+ {
+ unsigned char byte = ((unsigned) i) & 0xFF;
+ unsigned char count = 0;
+ while (byte)
+ {
+ if (byte & 1)
+ count++;
+ byte >>= 1;
+ }
+ byte2bitcount[i] = count;
+ }
+
+ for (i = 0; i < N_REG_CLASSES; i++)
+ {
+ int size;
+ COPY_HARD_REG_SET (rs, reg_class_contents[i]);
+ AND_COMPL_HARD_REG_SET (rs, never_use_colors);
+ size = hard_regs_count (rs);
+ num_free_regs[i] = size;
+ COPY_HARD_REG_SET (usable_regs[i], rs);
+ }
+
+ /* Setup hardregs_for_mode[].
+ We are not interested only in the beginning of a multi-reg, but in
+ all the hardregs involved. Maybe HARD_REGNO_MODE_OK() only ok's
+ for beginnings. */
+ for (i = 0; i < NUM_MACHINE_MODES; i++)
+ {
+ int reg, size;
+ CLEAR_HARD_REG_SET (rs);
+ for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
+ if (HARD_REGNO_MODE_OK (reg, i)
+ /* Ignore VOIDmode and similar things. */
+ && (size = HARD_REGNO_NREGS (reg, i)) != 0
+ && (reg + size) <= FIRST_PSEUDO_REGISTER)
+ {
+ while (size--)
+ SET_HARD_REG_BIT (rs, reg + size);
+ }
+ COPY_HARD_REG_SET (hardregs_for_mode[i], rs);
+ }
+
+ for (an_unusable_color = 0; an_unusable_color < FIRST_PSEUDO_REGISTER;
+ an_unusable_color++)
+ if (TEST_HARD_REG_BIT (never_use_colors, an_unusable_color))
+ break;
+ if (an_unusable_color == FIRST_PSEUDO_REGISTER)
+ abort ();
+
+ orig_max_uid = get_max_uid ();
+ compute_bb_for_insn ();
+ ra_reg_renumber = NULL;
+ insns_with_deaths = sbitmap_alloc (orig_max_uid);
+ death_insns_max_uid = orig_max_uid;
+ sbitmap_ones (insns_with_deaths);
+ gcc_obstack_init (&ra_obstack);
+}
+
+/* Check the consistency of DF. This aborts if it violates some
+ invariances we expect. */
+
+static void
+check_df (df)
+ struct df *df;
+{
+ struct df_link *link;
+ rtx insn;
+ int regno;
+ unsigned int ui;
+ bitmap b = BITMAP_XMALLOC ();
+ bitmap empty_defs = BITMAP_XMALLOC ();
+ bitmap empty_uses = BITMAP_XMALLOC ();
+
+ /* Collect all the IDs of NULL references in the ID->REF arrays,
+ as df.c leaves them when updating the df structure. */
+ for (ui = 0; ui < df->def_id; ui++)
+ if (!df->defs[ui])
+ bitmap_set_bit (empty_defs, ui);
+ for (ui = 0; ui < df->use_id; ui++)
+ if (!df->uses[ui])
+ bitmap_set_bit (empty_uses, ui);
+
+ /* For each insn we check if the chain of references contain each
+ ref only once, doesn't contain NULL refs, or refs whose ID is invalid
+ (it df->refs[id] element is NULL). */
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ {
+ bitmap_clear (b);
+ for (link = DF_INSN_DEFS (df, insn); link; link = link->next)
+ if (!link->ref || bitmap_bit_p (empty_defs, DF_REF_ID (link->ref))
+ || bitmap_bit_p (b, DF_REF_ID (link->ref)))
+ abort ();
+ else
+ bitmap_set_bit (b, DF_REF_ID (link->ref));
+
+ bitmap_clear (b);
+ for (link = DF_INSN_USES (df, insn); link; link = link->next)
+ if (!link->ref || bitmap_bit_p (empty_uses, DF_REF_ID (link->ref))
+ || bitmap_bit_p (b, DF_REF_ID (link->ref)))
+ abort ();
+ else
+ bitmap_set_bit (b, DF_REF_ID (link->ref));
+ }
+
+ /* Now the same for the chains per register number. */
+ for (regno = 0; regno < max_reg_num (); regno++)
+ {
+ bitmap_clear (b);
+ for (link = df->regs[regno].defs; link; link = link->next)
+ if (!link->ref || bitmap_bit_p (empty_defs, DF_REF_ID (link->ref))
+ || bitmap_bit_p (b, DF_REF_ID (link->ref)))
+ abort ();
+ else
+ bitmap_set_bit (b, DF_REF_ID (link->ref));
+
+ bitmap_clear (b);
+ for (link = df->regs[regno].uses; link; link = link->next)
+ if (!link->ref || bitmap_bit_p (empty_uses, DF_REF_ID (link->ref))
+ || bitmap_bit_p (b, DF_REF_ID (link->ref)))
+ abort ();
+ else
+ bitmap_set_bit (b, DF_REF_ID (link->ref));
+ }
+
+ BITMAP_XFREE (empty_uses);
+ BITMAP_XFREE (empty_defs);
+ BITMAP_XFREE (b);
+}
+
+/* Main register allocator entry point. */
+
+void
+reg_alloc ()
+{
+ int changed;
+ FILE *ra_dump_file = rtl_dump_file;
+ rtx last = get_last_insn ();
+
+ if (! INSN_P (last))
+ last = prev_real_insn (last);
+ /* If this is an empty function we shouldn't do all the following,
+ but instead just setup what's necessary, and return. */
+
+ /* We currently rely on the existance of the return value USE as
+ one of the last insns. Add it if it's not there anymore. */
+ if (last)
+ {
+ edge e;
+ for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
+ {
+ basic_block bb = e->src;
+ last = bb->end;
+ if (!INSN_P (last) || GET_CODE (PATTERN (last)) != USE)
+ {
+ rtx insns;
+ start_sequence ();
+ use_return_register ();
+ insns = get_insns ();
+ end_sequence ();
+ emit_insn_after (insns, last);
+ }
+ }
+ }
+
+ /* Setup debugging levels. */
+ switch (0)
+ {
+ /* Some usefull presets of the debug level, I often use. */
+ case 0: debug_new_regalloc = DUMP_EVER; break;
+ case 1: debug_new_regalloc = DUMP_COSTS; break;
+ case 2: debug_new_regalloc = DUMP_IGRAPH_M; break;
+ case 3: debug_new_regalloc = DUMP_COLORIZE + DUMP_COSTS; break;
+ case 4: debug_new_regalloc = DUMP_COLORIZE + DUMP_COSTS + DUMP_WEBS;
+ break;
+ case 5: debug_new_regalloc = DUMP_FINAL_RTL + DUMP_COSTS +
+ DUMP_CONSTRAINTS;
+ break;
+ case 6: debug_new_regalloc = DUMP_VALIDIFY; break;
+ }
+ if (!rtl_dump_file)
+ debug_new_regalloc = 0;
+
+ /* Run regclass first, so we know the preferred and alternate classes
+ for each pseudo. Deactivate emitting of debug info, if it's not
+ explicitely requested. */
+ if ((debug_new_regalloc & DUMP_REGCLASS) == 0)
+ rtl_dump_file = NULL;
+ regclass (get_insns (), max_reg_num (), rtl_dump_file);
+ rtl_dump_file = ra_dump_file;
+
+ /* We don't use those NOTEs, and as we anyway change all registers,
+ they only make problems later. */
+ count_or_remove_death_notes (NULL, 1);
+
+ /* Initialize the different global arrays and regsets. */
+ init_ra ();
+
+ /* And some global variables. */
+ ra_pass = 0;
+ no_new_pseudos = 0;
+ max_normal_pseudo = (unsigned) max_reg_num ();
+ ra_rewrite_init ();
+ last_def_id = 0;
+ last_use_id = 0;
+ last_num_webs = 0;
+ last_max_uid = 0;
+ last_check_uses = NULL;
+ live_at_end = NULL;
+ WEBS(INITIAL) = NULL;
+ WEBS(FREE) = NULL;
+ memset (hardreg2web, 0, sizeof (hardreg2web));
+ ticks_build = ticks_rebuild = 0;
+
+ /* The default is to use optimistic coalescing with interference
+ region spilling, without biased coloring. */
+ flag_ra_biased = 0;
+ flag_ra_spill_every_use = 0;
+ flag_ra_improved_spilling = 1;
+ flag_ra_ir_spilling = 1;
+ flag_ra_break_aliases = 0;
+ flag_ra_optimistic_coalescing = 1;
+ flag_ra_merge_spill_costs = 1;
+ if (flag_ra_optimistic_coalescing)
+ flag_ra_break_aliases = 1;
+ flag_ra_dump_notes = 0;
+
+ /* Allocate the global df structure. */
+ df = df_init ();
+
+ /* This is the main loop, calling one_pass as long as there are still
+ some spilled webs. */
+ do
+ {
+ ra_debug_msg (DUMP_NEARLY_EVER, "RegAlloc Pass %d\n\n", ra_pass);
+ if (ra_pass++ > 40)
+ internal_error ("Didn't find a coloring.\n");
+
+ /* First collect all the register refs and put them into
+ chains per insn, and per regno. In later passes only update
+ that info from the new and modified insns. */
+ df_analyse (df, (ra_pass == 1) ? 0 : (bitmap) -1,
+ DF_HARD_REGS | DF_RD_CHAIN | DF_RU_CHAIN);
+
+ if ((debug_new_regalloc & DUMP_DF) != 0)
+ {
+ rtx insn;
+ df_dump (df, DF_HARD_REGS, rtl_dump_file);
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ df_insn_debug_regno (df, insn, rtl_dump_file);
+ }
+ check_df (df);
+
+ /* Now allocate the memory needed for this pass, or (if it's not the
+ first pass), reallocate only additional memory. */
+ alloc_mem (df);
+
+ /* Build and colorize the interference graph, and possibly emit
+ spill insns. This also might delete certain move insns. */
+ changed = one_pass (df, ra_pass > 1);
+
+ /* If that produced no changes, the graph was colorizable. */
+ if (!changed)
+ {
+ /* Change the insns to refer to the new pseudos (one per web). */
+ emit_colors (df);
+ /* Already setup a preliminary reg_renumber[] array, but don't
+ free our own version. reg_renumber[] will again be destroyed
+ later. We right now need it in dump_constraints() for
+ constrain_operands(1) whose subproc sometimes reference
+ it (because we are checking strictly, i.e. as if
+ after reload). */
+ setup_renumber (0);
+ /* Delete some more of the coalesced moves. */
+ delete_moves ();
+ dump_constraints ();
+ }
+ else
+ {
+ /* If there were changes, this means spill code was added,
+ therefore repeat some things, including some initialization
+ of global data structures. */
+ if ((debug_new_regalloc & DUMP_REGCLASS) == 0)
+ rtl_dump_file = NULL;
+ /* We have new pseudos (the stackwebs). */
+ allocate_reg_info (max_reg_num (), FALSE, FALSE);
+ /* And new insns. */
+ compute_bb_for_insn ();
+ /* Some of them might be dead. */
+ delete_trivially_dead_insns (get_insns (), max_reg_num ());
+ /* Those new pseudos need to have their REFS count set. */
+ reg_scan_update (get_insns (), NULL, max_regno);
+ max_regno = max_reg_num ();
+ /* And they need usefull classes too. */
+ regclass (get_insns (), max_reg_num (), rtl_dump_file);
+ rtl_dump_file = ra_dump_file;
+
+ /* Remember the number of defs and uses, so we can distinguish
+ new from old refs in the next pass. */
+ last_def_id = df->def_id;
+ last_use_id = df->use_id;
+ }
+
+ /* Output the graph, and possibly the current insn sequence. */
+ dump_ra (df);
+ if (changed && (debug_new_regalloc & DUMP_RTL) != 0)
+ {
+ ra_print_rtl_with_bb (rtl_dump_file, get_insns ());
+ fflush (rtl_dump_file);
+ }
+
+ /* Reset the web lists. */
+ reset_lists ();
+ free_mem (df);
+ }
+ while (changed);
+
+ /* We are done with allocation, free all memory and output some
+ debug info. */
+ free_all_mem (df);
+ df_finish (df);
+ if ((debug_new_regalloc & DUMP_RESULTS) == 0)
+ dump_cost (DUMP_COSTS);
+ ra_debug_msg (DUMP_COSTS, "ticks for build-phase: %ld\n", ticks_build);
+ ra_debug_msg (DUMP_COSTS, "ticks for rebuild-phase: %ld\n", ticks_rebuild);
+ if ((debug_new_regalloc & (DUMP_FINAL_RTL | DUMP_RTL)) != 0)
+ ra_print_rtl_with_bb (rtl_dump_file, get_insns ());
+
+ /* We might have new pseudos, so allocate the info arrays for them. */
+ if ((debug_new_regalloc & DUMP_SM) == 0)
+ rtl_dump_file = NULL;
+ no_new_pseudos = 0;
+ allocate_reg_info (max_reg_num (), FALSE, FALSE);
+ no_new_pseudos = 1;
+ rtl_dump_file = ra_dump_file;
+
+ /* Some spill insns could've been inserted after trapping calls, i.e.
+ at the end of a basic block, which really ends at that call.
+ Fixup that breakages by adjusting basic block boundaries. */
+ fixup_abnormal_edges ();
+
+ /* Cleanup the flow graph. */
+ if ((debug_new_regalloc & DUMP_LAST_FLOW) == 0)
+ rtl_dump_file = NULL;
+ life_analysis (get_insns (), rtl_dump_file,
+ PROP_DEATH_NOTES | PROP_LOG_LINKS | PROP_REG_INFO);
+ cleanup_cfg (CLEANUP_EXPENSIVE);
+ recompute_reg_usage (get_insns (), TRUE);
+ if (rtl_dump_file)
+ dump_flow_info (rtl_dump_file);
+ rtl_dump_file = ra_dump_file;
+
+ /* update_equiv_regs() can't be called after register allocation.
+ It might delete some pseudos, and insert other insns setting
+ up those pseudos in different places. This of course screws up
+ the allocation because that may destroy a hardreg for another
+ pseudo.
+ XXX we probably should do something like that on our own. I.e.
+ creating REG_EQUIV notes. */
+ /*update_equiv_regs ();*/
+
+ /* Setup the reg_renumber[] array for reload. */
+ setup_renumber (1);
+ sbitmap_free (insns_with_deaths);
+
+ /* Remove REG_DEAD notes which are incorrectly set. See the docu
+ of that function. */
+ remove_suspicious_death_notes ();
+
+ if ((debug_new_regalloc & DUMP_LAST_RTL) != 0)
+ ra_print_rtl_with_bb (rtl_dump_file, get_insns ());
+ dump_static_insn_cost (rtl_dump_file,
+ "after allocation/spilling, before reload", NULL);
+
+ /* Allocate the reg_equiv_memory_loc array for reload. */
+ reg_equiv_memory_loc = (rtx *) xcalloc (max_regno, sizeof (rtx));
+ /* And possibly initialize it. */
+ allocate_initial_values (reg_equiv_memory_loc);
+ /* And one last regclass pass just before reload. */
+ regclass (get_insns (), max_reg_num (), rtl_dump_file);
+}
+
+/*
+vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
+*/
diff --git a/contrib/gcc/ra.h b/contrib/gcc/ra.h
new file mode 100644
index 0000000..d3c1f1a
--- /dev/null
+++ b/contrib/gcc/ra.h
@@ -0,0 +1,624 @@
+/* Graph coloring register allocator
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Contributed by Michael Matz <matz@suse.de>
+ and Daniel Berlin <dan@cgsoftware.com>.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 2, or (at your option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along
+ with GCC; see the file COPYING. If not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Double linked list to implement the per-type lists of webs
+ and moves. */
+struct dlist
+{
+ struct dlist *prev;
+ struct dlist *next;
+ union
+ {
+ struct web *web;
+ struct move *move;
+ } value;
+};
+/* Simple helper macros for ease of misuse. */
+#define DLIST_WEB(l) ((l)->value.web)
+#define DLIST_MOVE(l) ((l)->value.move)
+
+/* Classification of a given node (i.e. what state it's in). */
+enum node_type
+{
+ INITIAL = 0, FREE,
+ PRECOLORED,
+ SIMPLIFY, SIMPLIFY_SPILL, SIMPLIFY_FAT, FREEZE, SPILL,
+ SELECT,
+ SPILLED, COALESCED, COLORED,
+ LAST_NODE_TYPE
+};
+
+/* A list of conflict bitmaps, factorized on the exact part of
+ the source, which conflicts with the DEFs, whose ID are noted in
+ the bitmap. This is used while building web-parts with conflicts. */
+struct tagged_conflict
+{
+ struct tagged_conflict *next;
+ bitmap conflicts;
+
+ /* If the part of source identified by size S, byteoffset O conflicts,
+ then size_word == S | (O << 16). */
+ unsigned int size_word;
+};
+
+/* Such a structure is allocated initially for each def and use.
+ In the process of building the interference graph web parts are
+ connected together, if they have common instructions and reference the
+ same register. That way live ranges are build (by connecting defs and
+ uses) and implicitely complete webs (by connecting web parts in common
+ uses). */
+struct web_part
+{
+ /* The def or use for this web part. */
+ struct ref *ref;
+ /* The uplink implementing the disjoint set. */
+ struct web_part *uplink;
+
+ /* Here dynamic information associated with each def/use is saved.
+ This all is only valid for root web parts (uplink==NULL).
+ That's the information we need to merge, if web parts are unioned. */
+
+ /* Number of spanned insns containing any deaths. */
+ unsigned int spanned_deaths;
+ /* The list of bitmaps of DEF ID's with which this part conflicts. */
+ struct tagged_conflict *sub_conflicts;
+ /* If there's any call_insn, while this part is live. */
+ unsigned int crosses_call : 1;
+};
+
+/* Web structure used to store info about connected live ranges.
+ This represents the nodes of the interference graph, which gets
+ colored. It can also hold subwebs, which are contained in webs
+ and represent subregs. */
+struct web
+{
+ /* Unique web ID. */
+ unsigned int id;
+
+ /* Register number of the live range's variable. */
+ unsigned int regno;
+
+ /* How many insns containing deaths do we span? */
+ unsigned int span_deaths;
+
+ /* Spill_temp indicates if this web was part of a web spilled in the
+ last iteration, or or reasons why this shouldn't be spilled again.
+ 1 spill web, can't be spilled.
+ 2 big spill web (live over some deaths). Discouraged, but not
+ impossible to spill again.
+ 3 short web (spans no deaths), can't be spilled. */
+ unsigned int spill_temp;
+
+ /* When coalescing we might change spill_temp. If breaking aliases we
+ need to restore it. */
+ unsigned int orig_spill_temp;
+
+ /* Cost of spilling. */
+ unsigned HOST_WIDE_INT spill_cost;
+ unsigned HOST_WIDE_INT orig_spill_cost;
+
+ /* How many webs are aliased to us? */
+ unsigned int num_aliased;
+
+ /* The color we got. This is a hardreg number. */
+ int color;
+ /* 1 + the color this web got in the last pass. If it hadn't got a color,
+ or we are in the first pass, or this web is a new one, this is zero. */
+ int old_color;
+
+ /* Now follow some flags characterizing the web. */
+
+ /* Nonzero, if we should use usable_regs for this web, instead of
+ preferred_class() or alternate_class(). */
+ unsigned int use_my_regs:1;
+
+ /* Nonzero if we selected this web as possible spill candidate in
+ select_spill(). */
+ unsigned int was_spilled:1;
+
+ /* We need to distinguish also webs which are targets of coalescing
+ (all x with some y, so that x==alias(y)), but the alias field is
+ only set for sources of coalescing. This flag is set for all webs
+ involved in coalescing in some way. */
+ unsigned int is_coalesced:1;
+
+ /* Nonzero, if this web (or subweb) doesn't correspond with any of
+ the current functions actual use of reg rtx. Happens e.g. with
+ conflicts to a web, of which only a part was still undefined at the
+ point of that conflict. In this case we construct a subweb
+ representing these yet undefined bits to have a target for the
+ conflict. Suppose e.g. this sequence:
+ (set (reg:DI x) ...)
+ (set (reg:SI y) ...)
+ (set (subreg:SI (reg:DI x) 0) ...)
+ (use (reg:DI x))
+ Here x only partly conflicts with y. Namely only (subreg:SI (reg:DI x)
+ 1) conflicts with it, but this rtx doesn't show up in the program. For
+ such things an "artificial" subweb is built, and this flag is true for
+ them. */
+ unsigned int artificial:1;
+
+ /* Nonzero if we span a call_insn. */
+ unsigned int crosses_call:1;
+
+ /* Wether the web is involved in a move insn. */
+ unsigned int move_related:1;
+
+ /* 1 when this web (or parts thereof) are live over an abnormal edge. */
+ unsigned int live_over_abnormal:1;
+
+ /* Nonzero if this web is used in subregs where the mode change
+ was illegal for hardregs in CLASS_CANNOT_CHANGE_MODE. */
+ unsigned int mode_changed:1;
+
+ /* Nonzero, when this web stems from the last pass of the allocator,
+ and all info is still valid (i.e. it wasn't spilled). */
+ unsigned int old_web:1;
+
+ /* Used in rewrite_program2() to remember webs, which
+ are already marked for (re)loading. */
+ unsigned int in_load:1;
+
+ /* If in_load is != 0, then this is nonzero, if only one use was seen
+ since insertion in loadlist. Zero if more uses currently need a
+ reload. Used to differentiate between inserting register loads or
+ directly substituting the stackref. */
+ unsigned int one_load:1;
+
+ /* When using rewrite_program2() this flag gets set if some insns
+ were inserted on behalf of this web. IR spilling might ignore some
+ deaths up to the def, so no code might be emitted and we need not to
+ spill such a web again. */
+ unsigned int changed:1;
+
+ /* With interference region spilling it's sometimes the case, that a
+ bb border is also an IR border for webs, which were targets of moves,
+ which are already removed due to coalescing. All webs, which are
+ a destination of such a removed move, have this flag set. */
+ unsigned int target_of_spilled_move:1;
+
+ /* For optimistic coalescing we need to be able to break aliases, which
+ includes restoring conflicts to those before coalescing. This flag
+ is set, if we have a list of conflicts before coalescing. It's needed
+ because that list is lazily constructed only when actually needed. */
+ unsigned int have_orig_conflicts:1;
+
+ /* Current state of the node. */
+ ENUM_BITFIELD(node_type) type:5;
+
+ /* A regclass, combined from preferred and alternate class, or calculated
+ from usable_regs. Used only for debugging, and to determine
+ add_hardregs. */
+ ENUM_BITFIELD(reg_class) regclass:10;
+
+ /* Additional consecutive hardregs needed for this web. */
+ int add_hardregs;
+
+ /* Number of conflicts currently. */
+ int num_conflicts;
+
+ /* Numbers of uses and defs, which belong to this web. */
+ unsigned int num_uses;
+ unsigned int num_defs;
+
+ /* The (reg:M a) or (subreg:M1 (reg:M2 a) x) rtx which this
+ web is based on. This is used to distinguish subreg webs
+ from it's reg parents, and to get hold of the mode. */
+ rtx orig_x;
+
+ /* If this web is a subweb, this point to the super web. Otherwise
+ it's NULL. */
+ struct web *parent_web;
+
+ /* If this web is a subweb, but not the last one, this points to the
+ next subweb of the same super web. Otherwise it's NULL. */
+ struct web *subreg_next;
+
+ /* The set of webs (or subwebs), this web conflicts with. */
+ struct conflict_link *conflict_list;
+
+ /* If have_orig_conflicts is set this contains a copy of conflict_list,
+ as it was right after building the interference graph.
+ It's used for incremental i-graph building and for breaking
+ coalescings again. */
+ struct conflict_link *orig_conflict_list;
+
+ /* Bitmap of all conflicts which don't count this pass, because of
+ non-intersecting hardregs of the conflicting webs. See also
+ record_conflict(). */
+ bitmap useless_conflicts;
+
+ /* Different sets of hard registers, for all usable registers, ... */
+ HARD_REG_SET usable_regs;
+ /* ... the same before coalescing, ... */
+ HARD_REG_SET orig_usable_regs;
+ /* ... colors of all already colored neighbors (used when biased coloring
+ is active), and ... */
+ HARD_REG_SET bias_colors;
+ /* ... colors of PRECOLORED webs this web is connected to by a move. */
+ HARD_REG_SET prefer_colors;
+
+ /* Number of usable colors in usable_regs. */
+ int num_freedom;
+
+ /* After successfull coloring the graph each web gets a new reg rtx,
+ with which the original uses and defs are replaced. This is it. */
+ rtx reg_rtx;
+
+ /* While spilling this is the rtx of the home of spilled webs.
+ It can be a mem ref (a stack slot), or a pseudo register. */
+ rtx stack_slot;
+
+ /* Used in rewrite_program2() to remember the using
+ insn last seen for webs needing (re)loads. */
+ rtx last_use_insn;
+
+ /* If this web is rematerializable, this contains the RTL pattern
+ usable as source for that. Otherwise it's NULL. */
+ rtx pattern;
+
+ /* All the defs and uses. There are num_defs, resp.
+ num_uses elements. */
+ struct ref **defs; /* [0..num_defs-1] */
+ struct ref **uses; /* [0..num_uses-1] */
+
+ /* The web to which this web is aliased (coalesced). If NULL, this
+ web is not coalesced into some other (but might still be a target
+ for other webs). */
+ struct web *alias;
+
+ /* With iterated coalescing this is a list of active moves this web
+ is involved in. */
+ struct move_list *moves;
+
+ /* The list implementation. */
+ struct dlist *dlink;
+
+ /* While building webs, out of web-parts, this holds a (partial)
+ list of all refs for this web seen so far. */
+ struct df_link *temp_refs;
+};
+
+/* For implementing a single linked list. */
+struct web_link
+{
+ struct web_link *next;
+ struct web *web;
+};
+
+/* A subconflict is part of a conflict edge to track precisely,
+ which parts of two webs conflict, in case not all of both webs do. */
+struct sub_conflict
+{
+ /* The next partial conflict. For one such list the parent-web of
+ all the S webs, resp. the parent of all the T webs are constant. */
+ struct sub_conflict *next;
+ struct web *s;
+ struct web *t;
+};
+
+/* This represents an edge in the conflict graph. */
+struct conflict_link
+{
+ struct conflict_link *next;
+
+ /* The web we conflict with (the Target of the edge). */
+ struct web *t;
+
+ /* If not the complete source web and T conflict, this points to
+ the list of parts which really conflict. */
+ struct sub_conflict *sub;
+};
+
+/* For iterated coalescing the moves can be in these states. */
+enum move_type
+{
+ WORKLIST, MV_COALESCED, CONSTRAINED, FROZEN, ACTIVE,
+ LAST_MOVE_TYPE
+};
+
+/* Structure of a move we are considering coalescing. */
+struct move
+{
+ rtx insn;
+ struct web *source_web;
+ struct web *target_web;
+ enum move_type type;
+ struct dlist *dlink;
+};
+
+/* List of moves. */
+struct move_list
+{
+ struct move_list *next;
+ struct move *move;
+};
+
+/* To have fast access to the defs and uses per insn, we have one such
+ structure per insn. The difference to the normal df.c structures is,
+ that it doesn't contain any NULL refs, which df.c produces in case
+ an insn was modified and it only contains refs to pseudo regs, or to
+ hardregs which matter for allocation, i.e. those not in
+ never_use_colors. */
+struct ra_insn_info
+{
+ unsigned int num_defs, num_uses;
+ struct ref **defs, **uses;
+};
+
+/* The above structures are stored in this array, indexed by UID... */
+extern struct ra_insn_info *insn_df;
+/* ... and the size of that array, as we add insn after setting it up. */
+extern int insn_df_max_uid;
+
+/* The interference graph. */
+extern sbitmap igraph;
+/* And how to access it. I and J are web indices. If the bit
+ igraph_index(I, J) is set, then they conflict. Note, that
+ if only parts of webs conflict, then also only those parts
+ are noted in the I-graph (i.e. the parent webs not). */
+#define igraph_index(i, j) ((i) < (j) ? ((j)*((j)-1)/2)+(i) : ((i)*((i)-1)/2)+(j))
+/* This is the bitmap of all (even partly) conflicting super webs.
+ If bit I*num_webs+J or J*num_webs+I is set, then I and J (both being
+ super web indices) conflict, maybe only partially. Note the
+ assymetry. */
+extern sbitmap sup_igraph;
+
+/* After the first pass, and when interference region spilling is
+ activated, bit I is set, when the insn with UID I contains some
+ refs to pseudos which die at the insn. */
+extern sbitmap insns_with_deaths;
+/* The size of that sbitmap. */
+extern int death_insns_max_uid;
+
+/* All the web-parts. There are exactly as many web-parts as there
+ are register refs in the insn stream. */
+extern struct web_part *web_parts;
+
+/* The number of all webs, including subwebs. */
+extern unsigned int num_webs;
+/* The number of just the subwebs. */
+extern unsigned int num_subwebs;
+/* The number of all webs, including subwebs. */
+extern unsigned int num_allwebs;
+
+/* For easy access when given a web ID: id2web[W->id] == W. */
+extern struct web **id2web;
+/* For each hardreg, the web which represents it. */
+extern struct web *hardreg2web[FIRST_PSEUDO_REGISTER];
+
+/* Given the ID of a df_ref, which represent a DEF, def2web[ID] is
+ the web, to which this def belongs. */
+extern struct web **def2web;
+/* The same as def2web, just for uses. */
+extern struct web **use2web;
+
+/* The list of all recognized and coalescable move insns. */
+extern struct move_list *wl_moves;
+
+
+/* Some parts of the compiler which we run after colorizing
+ clean reg_renumber[], so we need another place for the colors.
+ This is copied to reg_renumber[] just before returning to toplev. */
+extern short *ra_reg_renumber;
+/* The size of that array. Some passes after coloring might have created
+ new pseudos, which will get no color. */
+extern int ra_max_regno;
+
+/* The dataflow structure of the current function, while regalloc
+ runs. */
+extern struct df *df;
+
+/* For each basic block B we have a bitmap of DF_REF_ID's of uses,
+ which backward reach the end of B. */
+extern bitmap *live_at_end;
+
+/* One pass is: collecting registers refs, buiding I-graph, spilling.
+ And this is how often we already ran that for the current function. */
+extern int ra_pass;
+
+/* The maximum pseudo regno, just before register allocation starts.
+ While regalloc runs all pseudos with a larger number represent
+ potentially stack slots or hardregs. I call them stackwebs or
+ stackpseudos. */
+extern unsigned int max_normal_pseudo;
+
+/* One of the fixed colors. It must be < FIRST_PSEUDO_REGISTER, because
+ we sometimes want to check the color against a HARD_REG_SET. It must
+ be >= 0, because negative values mean "no color".
+ This color is used for the above stackwebs, when they can't be colored.
+ I.e. normally they would be spilled, but they already represent
+ stackslots. So they are colored with an invalid color. It has
+ the property that even webs which conflict can have that color at the
+ same time. I.e. a stackweb with that color really represents a
+ stackslot. */
+extern int an_unusable_color;
+
+/* While building the I-graph, every time insn UID is looked at,
+ number_seen[UID] is incremented. For debugging. */
+extern int *number_seen;
+
+/* The different lists on which a web can be (based on the type). */
+extern struct dlist *web_lists[(int) LAST_NODE_TYPE];
+#define WEBS(type) (web_lists[(int)(type)])
+
+/* The largest DF_REF_ID of defs resp. uses, as it was in the
+ last pass. In the first pass this is zero. Used to distinguish new
+ from old refrences. */
+extern unsigned int last_def_id;
+extern unsigned int last_use_id;
+
+/* Similar for UIDs and number of webs. */
+extern int last_max_uid;
+extern unsigned int last_num_webs;
+
+/* If I is the ID of an old use, and last_check_uses[I] is set,
+ then we must reevaluate it's flow while building the new I-graph. */
+extern sbitmap last_check_uses;
+
+/* If nonzero, record_conflict() saves the current conflict list of
+ webs in orig_conflict_list, when not already done so, and the conflict
+ list is going to be changed. It is set, after initially building the
+ I-graph. I.e. new conflicts due to coalescing trigger that copying. */
+extern unsigned int remember_conflicts;
+
+/* The maximum UID right before calling regalloc().
+ Used to detect any instructions inserted by the allocator. */
+extern int orig_max_uid;
+
+/* A HARD_REG_SET of those color, which can't be used for coalescing.
+ Includes e.g. fixed_regs. */
+extern HARD_REG_SET never_use_colors;
+/* For each class C this is reg_class_contents[C] \ never_use_colors. */
+extern HARD_REG_SET usable_regs[N_REG_CLASSES];
+/* For each class C the count of hardregs in usable_regs[C]. */
+extern unsigned int num_free_regs[N_REG_CLASSES];
+/* For each mode M the hardregs, which are MODE_OK for M, and have
+ enough space behind them to hold an M value. Additinally
+ if reg R is OK for mode M, but it needs two hardregs, then R+1 will
+ also be set here, even if R+1 itself is not OK for M. I.e. this
+ represent the possible resources which could be taken away be a value
+ in mode M. */
+extern HARD_REG_SET hardregs_for_mode[NUM_MACHINE_MODES];
+/* For 0 <= I <= 255, the number of bits set in I. Used to calculate
+ the number of set bits in a HARD_REG_SET. */
+extern unsigned char byte2bitcount[256];
+
+/* Expressive helper macros. */
+#define ID2WEB(I) id2web[I]
+#define NUM_REGS(W) (((W)->type == PRECOLORED) ? 1 : (W)->num_freedom)
+#define SUBWEB_P(W) (GET_CODE ((W)->orig_x) == SUBREG)
+
+/* Constant usable as debug area to ra_debug_msg. */
+#define DUMP_COSTS 0x0001
+#define DUMP_WEBS 0x0002
+#define DUMP_IGRAPH 0x0004
+#define DUMP_PROCESS 0x0008
+#define DUMP_COLORIZE 0x0010
+#define DUMP_ASM 0x0020
+#define DUMP_CONSTRAINTS 0x0040
+#define DUMP_RESULTS 0x0080
+#define DUMP_DF 0x0100
+#define DUMP_RTL 0x0200
+#define DUMP_FINAL_RTL 0x0400
+#define DUMP_REGCLASS 0x0800
+#define DUMP_SM 0x1000
+#define DUMP_LAST_FLOW 0x2000
+#define DUMP_LAST_RTL 0x4000
+#define DUMP_REBUILD 0x8000
+#define DUMP_IGRAPH_M 0x10000
+#define DUMP_VALIDIFY 0x20000
+#define DUMP_EVER ((unsigned int)-1)
+#define DUMP_NEARLY_EVER (DUMP_EVER - DUMP_COSTS - DUMP_IGRAPH_M)
+
+/* All the wanted debug levels as ORing of the various DUMP_xxx
+ constants. */
+extern unsigned int debug_new_regalloc;
+
+/* Nonzero means we want biased coloring. */
+extern int flag_ra_biased;
+
+/* Nonzero if we want to use improved (and slow) spilling. This
+ includes also interference region spilling (see below). */
+extern int flag_ra_improved_spilling;
+
+/* Nonzero for using interference region spilling. Zero for improved
+ Chaintin style spilling (only at deaths). */
+extern int flag_ra_ir_spilling;
+
+/* Nonzero if we use optimistic coalescing, zero for iterated
+ coalescing. */
+extern int flag_ra_optimistic_coalescing;
+
+/* Nonzero if we want to break aliases of spilled webs. Forced to
+ nonzero, when flag_ra_optimistic_coalescing is. */
+extern int flag_ra_break_aliases;
+
+/* Nonzero if we want to merge the spill costs of webs which
+ are coalesced. */
+extern int flag_ra_merge_spill_costs;
+
+/* Nonzero if we want to spill at every use, instead of at deaths,
+ or intereference region borders. */
+extern int flag_ra_spill_every_use;
+
+/* Nonzero to output all notes in the debug dumps. */
+extern int flag_ra_dump_notes;
+
+extern inline void * ra_alloc PARAMS ((size_t));
+extern inline void * ra_calloc PARAMS ((size_t));
+extern int hard_regs_count PARAMS ((HARD_REG_SET));
+extern rtx ra_emit_move_insn PARAMS ((rtx, rtx));
+extern void ra_debug_msg PARAMS ((unsigned int,
+ const char *, ...)) ATTRIBUTE_PRINTF_2;
+extern int hard_regs_intersect_p PARAMS ((HARD_REG_SET *, HARD_REG_SET *));
+extern unsigned int rtx_to_bits PARAMS ((rtx));
+extern struct web * find_subweb PARAMS ((struct web *, rtx));
+extern struct web * find_subweb_2 PARAMS ((struct web *, unsigned int));
+extern struct web * find_web_for_subweb_1 PARAMS ((struct web *));
+
+#define find_web_for_subweb(w) (((w)->parent_web) \
+ ? find_web_for_subweb_1 ((w)->parent_web) \
+ : (w))
+
+extern void ra_build_realloc PARAMS ((struct df *));
+extern void ra_build_free PARAMS ((void));
+extern void ra_build_free_all PARAMS ((struct df *));
+extern void ra_colorize_init PARAMS ((void));
+extern void ra_colorize_free_all PARAMS ((void));
+extern void ra_rewrite_init PARAMS ((void));
+
+extern void ra_print_rtx PARAMS ((FILE *, rtx, int));
+extern void ra_print_rtx_top PARAMS ((FILE *, rtx, int));
+extern void ra_debug_rtx PARAMS ((rtx));
+extern void ra_debug_insns PARAMS ((rtx, int));
+extern void ra_debug_bbi PARAMS ((int));
+extern void ra_print_rtl_with_bb PARAMS ((FILE *, rtx));
+extern void dump_igraph PARAMS ((struct df *));
+extern void dump_igraph_machine PARAMS ((void));
+extern void dump_constraints PARAMS ((void));
+extern void dump_cost PARAMS ((unsigned int));
+extern void dump_graph_cost PARAMS ((unsigned int, const char *));
+extern void dump_ra PARAMS ((struct df *));
+extern void dump_number_seen PARAMS ((void));
+extern void dump_static_insn_cost PARAMS ((FILE *, const char *,
+ const char *));
+extern void dump_web_conflicts PARAMS ((struct web *));
+extern void dump_web_insns PARAMS ((struct web*));
+extern int web_conflicts_p PARAMS ((struct web *, struct web *));
+extern void debug_hard_reg_set PARAMS ((HARD_REG_SET));
+
+extern void remove_list PARAMS ((struct dlist *, struct dlist **));
+extern struct dlist * pop_list PARAMS ((struct dlist **));
+extern void record_conflict PARAMS ((struct web *, struct web *));
+extern int memref_is_stack_slot PARAMS ((rtx));
+extern void build_i_graph PARAMS ((struct df *));
+extern void put_web PARAMS ((struct web *, enum node_type));
+extern void remove_web_from_list PARAMS ((struct web *));
+extern void reset_lists PARAMS ((void));
+extern struct web * alias PARAMS ((struct web *));
+extern void merge_moves PARAMS ((struct web *, struct web *));
+extern void ra_colorize_graph PARAMS ((struct df *));
+
+extern void actual_spill PARAMS ((void));
+extern void emit_colors PARAMS ((struct df *));
+extern void delete_moves PARAMS ((void));
+extern void setup_renumber PARAMS ((int));
+extern void remove_suspicious_death_notes PARAMS ((void));
diff --git a/contrib/gcc/read-rtl.c b/contrib/gcc/read-rtl.c
index 5b937ec..5efd5dc 100644
--- a/contrib/gcc/read-rtl.c
+++ b/contrib/gcc/read-rtl.c
@@ -25,15 +25,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "obstack.h"
#include "hashtab.h"
-#ifndef ISDIGIT
-#include <ctype.h>
-#define ISDIGIT isdigit
-#define ISSPACE isspace
-#endif
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
static htab_t md_constants;
static void fatal_with_file_and_line PARAMS ((FILE *, const char *, ...))
@@ -44,7 +35,7 @@ static char *read_string PARAMS ((struct obstack *, FILE *, int));
static char *read_quoted_string PARAMS ((struct obstack *, FILE *));
static char *read_braced_string PARAMS ((struct obstack *, FILE *));
static void read_escape PARAMS ((struct obstack *, FILE *));
-static unsigned def_hash PARAMS ((const void *));
+static hashval_t def_hash PARAMS ((const void *));
static int def_name_eq_p PARAMS ((const void *, const void *));
static void read_constants PARAMS ((FILE *infile, char *tmp_char));
static void validate_const_int PARAMS ((FILE *, const char *));
@@ -265,7 +256,7 @@ read_escape (ob, infile)
obstack_1grow (ob, c);
}
-
+
/* Read a double-quoted string onto the obstack. Caller has scanned
the leading quote. */
@@ -325,7 +316,7 @@ read_braced_string (ob, infile)
obstack_1grow (ob, c);
}
-
+
obstack_1grow (ob, 0);
return obstack_finish (ob);
}
@@ -361,7 +352,7 @@ read_string (ob, infile, star_if_braced)
}
else
fatal_with_file_and_line (infile, "expected `\"' or `{', found `%c'", c);
-
+
if (saw_paren)
{
c = read_skip_spaces (infile);
@@ -410,7 +401,7 @@ atoll (p)
#endif
/* Given a constant definition, return a hash code for its name. */
-static unsigned
+static hashval_t
def_hash (def)
const void *def;
{
@@ -639,7 +630,7 @@ again:
{
XVEC (return_rtx, i) = 0;
break;
- }
+ }
/* Now process the vector. */
case 'E':
@@ -694,7 +685,7 @@ again:
gets a star inserted as its first character, if it is
written with a brace block instead of a string constant. */
int star_if_braced = (format_ptr[-1] == 'T');
-
+
stringbuf = read_string (&rtl_obstack, infile, star_if_braced);
/* For insn patterns, we want to provide a default name
diff --git a/contrib/gcc/real.c b/contrib/gcc/real.c
index 7b8879b..61cbf2e 100644
--- a/contrib/gcc/real.c
+++ b/contrib/gcc/real.c
@@ -1,6995 +1,4415 @@
-/* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF,
- and support for XFmode IEEE extended real floating point arithmetic.
+/* real.c - software floating point emulation.
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
Contributed by Stephen L. Moshier (moshier@world.std.com).
+ Re-written by Richard Henderson <rth@redhat.com>
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
-version.
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "tree.h"
#include "toplev.h"
+#include "real.h"
#include "tm_p.h"
-/* To enable support of XFmode extended real floating point, define
-LONG_DOUBLE_TYPE_SIZE 96 in the tm.h file (m68k.h or i386.h).
-
-To support cross compilation between IEEE, VAX and IBM floating
-point formats, define REAL_ARITHMETIC in the tm.h file.
-
-In either case the machine files (tm.h) must not contain any code
-that tries to use host floating point arithmetic to convert
-REAL_VALUE_TYPEs from `double' to `float', pass them to fprintf,
-etc. In cross-compile situations a REAL_VALUE_TYPE may not
-be intelligible to the host computer's native arithmetic.
-
-The emulator defaults to the host's floating point format so that
-its decimal conversion functions can be used if desired (see
-real.h).
-
-The first part of this file interfaces gcc to a floating point
-arithmetic suite that was not written with gcc in mind. Avoid
-changing the low-level arithmetic routines unless you have suitable
-test programs available. A special version of the PARANOIA floating
-point arithmetic tester, modified for this purpose, can be found on
-usc.edu: /pub/C-numanal/ieeetest.zoo. Other tests, and libraries of
-XFmode and TFmode transcendental functions, can be obtained by ftp from
-netlib.att.com: netlib/cephes. */
+/* The floating point model used internally is not exactly IEEE 754
+ compliant, and close to the description in the ISO C standard,
+ section 5.2.4.2.2 Characteristics of floating types.
+
+ Specifically
+
+ x = s * b^e * \sum_{k=1}^p f_k * b^{-k}
+
+ where
+ s = sign (+- 1)
+ b = base or radix, here always 2
+ e = exponent
+ p = precision (the number of base-b digits in the significand)
+ f_k = the digits of the significand.
+
+ We differ from typical IEEE 754 encodings in that the entire
+ significand is fractional. Normalized significands are in the
+ range [0.5, 1.0).
+
+ A requirement of the model is that P be larger than than the
+ largest supported target floating-point type by at least 2 bits.
+ This gives us proper rounding when we truncate to the target type.
+ In addition, E must be large enough to hold the smallest supported
+ denormal number in a normalized form.
+
+ Both of these requirements are easily satisfied. The largest target
+ significand is 113 bits; we store at least 160. The smallest
+ denormal number fits in 17 exponent bits; we store 29.
+
+ Note that the decimal string conversion routines are sensitive to
+ rounding error. Since the raw arithmetic routines do not themselves
+ have guard digits or rounding, the computation of 10**exp can
+ accumulate more than a few digits of error. The previous incarnation
+ of real.c successfully used a 144 bit fraction; given the current
+ layout of REAL_VALUE_TYPE we're forced to expand to at least 160 bits.
+
+ Target floating point models that use base 16 instead of base 2
+ (i.e. IBM 370), are handled during round_for_format, in which we
+ canonicalize the exponent to be a multiple of 4 (log2(16)), and
+ adjust the significand to match. */
+
+
+/* Used to classify two numbers simultaneously. */
+#define CLASS2(A, B) ((A) << 2 | (B))
+
+#if HOST_BITS_PER_LONG != 64 && HOST_BITS_PER_LONG != 32
+ #error "Some constant folding done by hand to avoid shift count warnings"
+#endif
+
+static void get_zero PARAMS ((REAL_VALUE_TYPE *, int));
+static void get_canonical_qnan PARAMS ((REAL_VALUE_TYPE *, int));
+static void get_canonical_snan PARAMS ((REAL_VALUE_TYPE *, int));
+static void get_inf PARAMS ((REAL_VALUE_TYPE *, int));
+static bool sticky_rshift_significand PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *,
+ unsigned int));
+static void rshift_significand PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *,
+ unsigned int));
+static void lshift_significand PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *,
+ unsigned int));
+static void lshift_significand_1 PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+static bool add_significands PARAMS ((REAL_VALUE_TYPE *r,
+ const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+static bool sub_significands PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *, int));
+static void neg_significand PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+static int cmp_significands PARAMS ((const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+static int cmp_significand_0 PARAMS ((const REAL_VALUE_TYPE *));
+static void set_significand_bit PARAMS ((REAL_VALUE_TYPE *, unsigned int));
+static void clear_significand_bit PARAMS ((REAL_VALUE_TYPE *, unsigned int));
+static bool test_significand_bit PARAMS ((REAL_VALUE_TYPE *, unsigned int));
+static void clear_significand_below PARAMS ((REAL_VALUE_TYPE *,
+ unsigned int));
+static bool div_significands PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+static void normalize PARAMS ((REAL_VALUE_TYPE *));
+
+static void do_add PARAMS ((REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *, int));
+static void do_multiply PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+static void do_divide PARAMS ((REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+static int do_compare PARAMS ((const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *, int));
+static void do_fix_trunc PARAMS ((REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *));
+
+static unsigned long rtd_divmod PARAMS ((REAL_VALUE_TYPE *,
+ REAL_VALUE_TYPE *));
+
+static const REAL_VALUE_TYPE * ten_to_ptwo PARAMS ((int));
+static const REAL_VALUE_TYPE * ten_to_mptwo PARAMS ((int));
+static const REAL_VALUE_TYPE * real_digit PARAMS ((int));
+static void times_pten PARAMS ((REAL_VALUE_TYPE *, int));
+
+static void round_for_format PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *));
-/* Type of computer arithmetic.
- Only one of DEC, IBM, IEEE, C4X, or UNK should get defined.
-
- `IEEE', when REAL_WORDS_BIG_ENDIAN is non-zero, refers generically
- to big-endian IEEE floating-point data structure. This definition
- should work in SFmode `float' type and DFmode `double' type on
- virtually all big-endian IEEE machines. If LONG_DOUBLE_TYPE_SIZE
- has been defined to be 96, then IEEE also invokes the particular
- XFmode (`long double' type) data structure used by the Motorola
- 680x0 series processors.
-
- `IEEE', when REAL_WORDS_BIG_ENDIAN is zero, refers generally to
- little-endian IEEE machines. In this case, if LONG_DOUBLE_TYPE_SIZE
- has been defined to be 96, then IEEE also invokes the particular
- XFmode `long double' data structure used by the Intel 80x86 series
- processors.
-
- `DEC' refers specifically to the Digital Equipment Corp PDP-11
- and VAX floating point data structure. This model currently
- supports no type wider than DFmode.
-
- `IBM' refers specifically to the IBM System/370 and compatible
- floating point data structure. This model currently supports
- no type wider than DFmode. The IBM conversions were contributed by
- frank@atom.ansto.gov.au (Frank Crawford).
-
- `C4X' refers specifically to the floating point format used on
- Texas Instruments TMS320C3x and TMS320C4x digital signal
- processors. This supports QFmode (32-bit float, double) and HFmode
- (40-bit long double) where BITS_PER_BYTE is 32. Unlike IEEE
- floats, C4x floats are not rounded to be even. The C4x conversions
- were contributed by m.hayes@elec.canterbury.ac.nz (Michael Hayes) and
- Haj.Ten.Brugge@net.HCC.nl (Herman ten Brugge).
-
- If LONG_DOUBLE_TYPE_SIZE = 64 (the default, unless tm.h defines it)
- then `long double' and `double' are both implemented, but they
- both mean DFmode. In this case, the software floating-point
- support available here is activated by writing
- #define REAL_ARITHMETIC
- in tm.h.
-
- The case LONG_DOUBLE_TYPE_SIZE = 128 activates TFmode support
- and may deactivate XFmode since `long double' is used to refer
- to both modes. Defining INTEL_EXTENDED_IEEE_FORMAT to non-zero
- at the same time enables 80387-style 80-bit floats in a 128-bit
- padded image, as seen on IA-64.
-
- The macros FLOAT_WORDS_BIG_ENDIAN, HOST_FLOAT_WORDS_BIG_ENDIAN,
- contributed by Richard Earnshaw <Richard.Earnshaw@cl.cam.ac.uk>,
- separate the floating point unit's endian-ness from that of
- the integer addressing. This permits one to define a big-endian
- FPU on a little-endian machine (e.g., ARM). An extension to
- BYTES_BIG_ENDIAN may be required for some machines in the future.
- These optional macros may be defined in tm.h. In real.h, they
- default to WORDS_BIG_ENDIAN, etc., so there is no need to define
- them for any normal host or target machine on which the floats
- and the integers have the same endian-ness. */
-
-
-/* The following converts gcc macros into the ones used by this file. */
-
-/* REAL_ARITHMETIC defined means that macros in real.h are
- defined to call emulator functions. */
-#ifdef REAL_ARITHMETIC
-
-#if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT
-/* PDP-11, Pro350, VAX: */
-#define DEC 1
-#else /* it's not VAX */
-#if TARGET_FLOAT_FORMAT == IBM_FLOAT_FORMAT
-/* IBM System/370 style */
-#define IBM 1
-#else /* it's also not an IBM */
-#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
-/* TMS320C3x/C4x style */
-#define C4X 1
-#else /* it's also not a C4X */
-#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-#define IEEE
-#else /* it's not IEEE either */
-/* UNKnown arithmetic. We don't support this and can't go on. */
-unknown arithmetic type
-#define UNK 1
-#endif /* not IEEE */
-#endif /* not C4X */
-#endif /* not IBM */
-#endif /* not VAX */
-
-#define REAL_WORDS_BIG_ENDIAN FLOAT_WORDS_BIG_ENDIAN
-
-#else
-/* REAL_ARITHMETIC not defined means that the *host's* data
- structure will be used. It may differ by endian-ness from the
- target machine's structure and will get its ends swapped
- accordingly (but not here). Probably only the decimal <-> binary
- functions in this file will actually be used in this case. */
-
-#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
-#define DEC 1
-#else /* it's not VAX */
-#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
-/* IBM System/370 style */
-#define IBM 1
-#else /* it's also not an IBM */
-#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-#define IEEE
-#else /* it's not IEEE either */
-unknown arithmetic type
-#define UNK 1
-#endif /* not IEEE */
-#endif /* not IBM */
-#endif /* not VAX */
-
-#define REAL_WORDS_BIG_ENDIAN HOST_FLOAT_WORDS_BIG_ENDIAN
-
-#endif /* REAL_ARITHMETIC not defined */
-
-/* Define INFINITY for support of infinity.
- Define NANS for support of Not-a-Number's (NaN's). */
-#if !defined(DEC) && !defined(IBM) && !defined(C4X)
-#define INFINITY
-#define NANS
-#endif
-
-/* Support of NaNs requires support of infinity. */
-#ifdef NANS
-#ifndef INFINITY
-#define INFINITY
-#endif
-#endif
-
-/* Find a host integer type that is at least 16 bits wide,
- and another type at least twice whatever that size is. */
-
-#if HOST_BITS_PER_CHAR >= 16
-#define EMUSHORT char
-#define EMUSHORT_SIZE HOST_BITS_PER_CHAR
-#define EMULONG_SIZE (2 * HOST_BITS_PER_CHAR)
-#else
-#if HOST_BITS_PER_SHORT >= 16
-#define EMUSHORT short
-#define EMUSHORT_SIZE HOST_BITS_PER_SHORT
-#define EMULONG_SIZE (2 * HOST_BITS_PER_SHORT)
-#else
-#if HOST_BITS_PER_INT >= 16
-#define EMUSHORT int
-#define EMUSHORT_SIZE HOST_BITS_PER_INT
-#define EMULONG_SIZE (2 * HOST_BITS_PER_INT)
-#else
-#if HOST_BITS_PER_LONG >= 16
-#define EMUSHORT long
-#define EMUSHORT_SIZE HOST_BITS_PER_LONG
-#define EMULONG_SIZE (2 * HOST_BITS_PER_LONG)
-#else
-/* You will have to modify this program to have a smaller unit size. */
-#define EMU_NON_COMPILE
-#endif
-#endif
-#endif
-#endif
+/* Initialize R with a positive zero. */
-/* If no 16-bit type has been found and the compiler is GCC, try HImode. */
-#if defined(__GNUC__) && EMUSHORT_SIZE != 16
-typedef int HItype __attribute__ ((mode (HI)));
-typedef unsigned int UHItype __attribute__ ((mode (HI)));
-#undef EMUSHORT
-#undef EMUSHORT_SIZE
-#undef EMULONG_SIZE
-#define EMUSHORT HItype
-#define UEMUSHORT UHItype
-#define EMUSHORT_SIZE 16
-#define EMULONG_SIZE 32
-#else
-#define UEMUSHORT unsigned EMUSHORT
-#endif
-
-#if HOST_BITS_PER_SHORT >= EMULONG_SIZE
-#define EMULONG short
-#else
-#if HOST_BITS_PER_INT >= EMULONG_SIZE
-#define EMULONG int
-#else
-#if HOST_BITS_PER_LONG >= EMULONG_SIZE
-#define EMULONG long
-#else
-#if HOST_BITS_PER_LONGLONG >= EMULONG_SIZE
-#define EMULONG long long int
-#else
-/* You will have to modify this program to have a smaller unit size. */
-#define EMU_NON_COMPILE
-#endif
-#endif
-#endif
-#endif
+static inline void
+get_zero (r, sign)
+ REAL_VALUE_TYPE *r;
+ int sign;
+{
+ memset (r, 0, sizeof (*r));
+ r->sign = sign;
+}
+/* Initialize R with the canonical quiet NaN. */
-/* The host interface doesn't work if no 16-bit size exists. */
-#if EMUSHORT_SIZE != 16
-#define EMU_NON_COMPILE
-#endif
+static inline void
+get_canonical_qnan (r, sign)
+ REAL_VALUE_TYPE *r;
+ int sign;
+{
+ memset (r, 0, sizeof (*r));
+ r->class = rvc_nan;
+ r->sign = sign;
+ r->sig[SIGSZ-1] = SIG_MSB >> 1;
+}
-/* OK to continue compilation. */
-#ifndef EMU_NON_COMPILE
-
-/* Construct macros to translate between REAL_VALUE_TYPE and e type.
- In GET_REAL and PUT_REAL, r and e are pointers.
- A REAL_VALUE_TYPE is guaranteed to occupy contiguous locations
- in memory, with no holes. */
-
-#if MAX_LONG_DOUBLE_TYPE_SIZE == 96 || \
- ((INTEL_EXTENDED_IEEE_FORMAT != 0) && MAX_LONG_DOUBLE_TYPE_SIZE == 128)
-/* Number of 16 bit words in external e type format */
-# define NE 6
-# define MAXDECEXP 4932
-# define MINDECEXP -4956
-# define GET_REAL(r,e) memcpy ((e), (r), 2*NE)
-# define PUT_REAL(e,r) \
- do { \
- memcpy ((r), (e), 2*NE); \
- if (2*NE < sizeof (*r)) \
- memset ((char *) (r) + 2*NE, 0, sizeof (*r) - 2*NE); \
- } while (0)
-# else /* no XFmode */
-# if MAX_LONG_DOUBLE_TYPE_SIZE == 128
-# define NE 10
-# define MAXDECEXP 4932
-# define MINDECEXP -4977
-# define GET_REAL(r,e) memcpy ((e), (r), 2*NE)
-# define PUT_REAL(e,r) \
- do { \
- memcpy ((r), (e), 2*NE); \
- if (2*NE < sizeof (*r)) \
- memset ((char *) (r) + 2*NE, 0, sizeof (*r) - 2*NE); \
- } while (0)
-#else
-#define NE 6
-#define MAXDECEXP 4932
-#define MINDECEXP -4956
-#ifdef REAL_ARITHMETIC
-/* Emulator uses target format internally
- but host stores it in host endian-ness. */
-
-#define GET_REAL(r,e) \
-do { \
- if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN) \
- e53toe ((const UEMUSHORT *) (r), (e)); \
- else \
- { \
- UEMUSHORT w[4]; \
- memcpy (&w[3], ((const EMUSHORT *) r), sizeof (EMUSHORT)); \
- memcpy (&w[2], ((const EMUSHORT *) r) + 1, sizeof (EMUSHORT)); \
- memcpy (&w[1], ((const EMUSHORT *) r) + 2, sizeof (EMUSHORT)); \
- memcpy (&w[0], ((const EMUSHORT *) r) + 3, sizeof (EMUSHORT)); \
- e53toe (w, (e)); \
- } \
- } while (0)
-
-#define PUT_REAL(e,r) \
-do { \
- if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN) \
- etoe53 ((e), (UEMUSHORT *) (r)); \
- else \
- { \
- UEMUSHORT w[4]; \
- etoe53 ((e), w); \
- memcpy (((EMUSHORT *) r), &w[3], sizeof (EMUSHORT)); \
- memcpy (((EMUSHORT *) r) + 1, &w[2], sizeof (EMUSHORT)); \
- memcpy (((EMUSHORT *) r) + 2, &w[1], sizeof (EMUSHORT)); \
- memcpy (((EMUSHORT *) r) + 3, &w[0], sizeof (EMUSHORT)); \
- } \
- } while (0)
-
-#else /* not REAL_ARITHMETIC */
-
-/* emulator uses host format */
-#define GET_REAL(r,e) e53toe ((const UEMUSHORT *) (r), (e))
-#define PUT_REAL(e,r) etoe53 ((e), (UEMUSHORT *) (r))
-
-#endif /* not REAL_ARITHMETIC */
-#endif /* not TFmode */
-#endif /* not XFmode */
-
-
-/* Number of 16 bit words in internal format */
-#define NI (NE+3)
-
-/* Array offset to exponent */
-#define E 1
-
-/* Array offset to high guard word */
-#define M 2
-
-/* Number of bits of precision */
-#define NBITS ((NI-4)*16)
-
-/* Maximum number of decimal digits in ASCII conversion
- * = NBITS*log10(2)
- */
-#define NDEC (NBITS*8/27)
-
-/* The exponent of 1.0 */
-#define EXONE (0x3fff)
-
-#if defined(HOST_EBCDIC)
-/* bit 8 is significant in EBCDIC */
-#define CHARMASK 0xff
-#else
-#define CHARMASK 0x7f
-#endif
+static inline void
+get_canonical_snan (r, sign)
+ REAL_VALUE_TYPE *r;
+ int sign;
+{
+ memset (r, 0, sizeof (*r));
+ r->class = rvc_nan;
+ r->sign = sign;
+ r->sig[SIGSZ-1] = SIG_MSB >> 2;
+}
-extern int extra_warnings;
-extern const UEMUSHORT ezero[NE], ehalf[NE], eone[NE], etwo[NE];
-extern const UEMUSHORT elog2[NE], esqrt2[NE];
+static inline void
+get_inf (r, sign)
+ REAL_VALUE_TYPE *r;
+ int sign;
+{
+ memset (r, 0, sizeof (*r));
+ r->class = rvc_inf;
+ r->sign = sign;
+}
-static void endian PARAMS ((const UEMUSHORT *, long *,
- enum machine_mode));
-static void eclear PARAMS ((UEMUSHORT *));
-static void emov PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-#if 0
-static void eabs PARAMS ((UEMUSHORT *));
-#endif
-static void eneg PARAMS ((UEMUSHORT *));
-static int eisneg PARAMS ((const UEMUSHORT *));
-static int eisinf PARAMS ((const UEMUSHORT *));
-static int eisnan PARAMS ((const UEMUSHORT *));
-static void einfin PARAMS ((UEMUSHORT *));
-#ifdef NANS
-static void enan PARAMS ((UEMUSHORT *, int));
-static void einan PARAMS ((UEMUSHORT *));
-static int eiisnan PARAMS ((const UEMUSHORT *));
-static int eiisneg PARAMS ((const UEMUSHORT *));
-static void make_nan PARAMS ((UEMUSHORT *, int, enum machine_mode));
-#endif
-static void emovi PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void emovo PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void ecleaz PARAMS ((UEMUSHORT *));
-static void ecleazs PARAMS ((UEMUSHORT *));
-static void emovz PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-#if 0
-static void eiinfin PARAMS ((UEMUSHORT *));
-#endif
-#ifdef INFINITY
-static int eiisinf PARAMS ((const UEMUSHORT *));
-#endif
-static int ecmpm PARAMS ((const UEMUSHORT *, const UEMUSHORT *));
-static void eshdn1 PARAMS ((UEMUSHORT *));
-static void eshup1 PARAMS ((UEMUSHORT *));
-static void eshdn8 PARAMS ((UEMUSHORT *));
-static void eshup8 PARAMS ((UEMUSHORT *));
-static void eshup6 PARAMS ((UEMUSHORT *));
-static void eshdn6 PARAMS ((UEMUSHORT *));
-static void eaddm PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void esubm PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void m16m PARAMS ((unsigned int, const UEMUSHORT *, UEMUSHORT *));
-static int edivm PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static int emulm PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void emdnorm PARAMS ((UEMUSHORT *, int, int, EMULONG, int));
-static void esub PARAMS ((const UEMUSHORT *, const UEMUSHORT *,
- UEMUSHORT *));
-static void eadd PARAMS ((const UEMUSHORT *, const UEMUSHORT *,
- UEMUSHORT *));
-static void eadd1 PARAMS ((const UEMUSHORT *, const UEMUSHORT *,
- UEMUSHORT *));
-static void ediv PARAMS ((const UEMUSHORT *, const UEMUSHORT *,
- UEMUSHORT *));
-static void emul PARAMS ((const UEMUSHORT *, const UEMUSHORT *,
- UEMUSHORT *));
-static void e53toe PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void e64toe PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
-static void e113toe PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-#endif
-static void e24toe PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
-static void etoe113 PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void toe113 PARAMS ((UEMUSHORT *, UEMUSHORT *));
-#endif
-static void etoe64 PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void toe64 PARAMS ((UEMUSHORT *, UEMUSHORT *));
-static void etoe53 PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void toe53 PARAMS ((UEMUSHORT *, UEMUSHORT *));
-static void etoe24 PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void toe24 PARAMS ((UEMUSHORT *, UEMUSHORT *));
-static int ecmp PARAMS ((const UEMUSHORT *, const UEMUSHORT *));
-#if 0
-static void eround PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-#endif
-static void ltoe PARAMS ((const HOST_WIDE_INT *, UEMUSHORT *));
-static void ultoe PARAMS ((const unsigned HOST_WIDE_INT *, UEMUSHORT *));
-static void eifrac PARAMS ((const UEMUSHORT *, HOST_WIDE_INT *,
- UEMUSHORT *));
-static void euifrac PARAMS ((const UEMUSHORT *, unsigned HOST_WIDE_INT *,
- UEMUSHORT *));
-static int eshift PARAMS ((UEMUSHORT *, int));
-static int enormlz PARAMS ((UEMUSHORT *));
-#if 0
-static void e24toasc PARAMS ((const UEMUSHORT *, char *, int));
-static void e53toasc PARAMS ((const UEMUSHORT *, char *, int));
-static void e64toasc PARAMS ((const UEMUSHORT *, char *, int));
-static void e113toasc PARAMS ((const UEMUSHORT *, char *, int));
-#endif /* 0 */
-static void etoasc PARAMS ((const UEMUSHORT *, char *, int));
-static void asctoe24 PARAMS ((const char *, UEMUSHORT *));
-static void asctoe53 PARAMS ((const char *, UEMUSHORT *));
-static void asctoe64 PARAMS ((const char *, UEMUSHORT *));
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
-static void asctoe113 PARAMS ((const char *, UEMUSHORT *));
-#endif
-static void asctoe PARAMS ((const char *, UEMUSHORT *));
-static void asctoeg PARAMS ((const char *, UEMUSHORT *, int));
-static void efloor PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-#if 0
-static void efrexp PARAMS ((const UEMUSHORT *, int *,
- UEMUSHORT *));
-#endif
-static void eldexp PARAMS ((const UEMUSHORT *, int, UEMUSHORT *));
-#if 0
-static void eremain PARAMS ((const UEMUSHORT *, const UEMUSHORT *,
- UEMUSHORT *));
-#endif
-static void eiremain PARAMS ((UEMUSHORT *, UEMUSHORT *));
-static void mtherr PARAMS ((const char *, int));
-#ifdef DEC
-static void dectoe PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void etodec PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void todec PARAMS ((UEMUSHORT *, UEMUSHORT *));
-#endif
-#ifdef IBM
-static void ibmtoe PARAMS ((const UEMUSHORT *, UEMUSHORT *,
- enum machine_mode));
-static void etoibm PARAMS ((const UEMUSHORT *, UEMUSHORT *,
- enum machine_mode));
-static void toibm PARAMS ((UEMUSHORT *, UEMUSHORT *,
- enum machine_mode));
-#endif
-#ifdef C4X
-static void c4xtoe PARAMS ((const UEMUSHORT *, UEMUSHORT *,
- enum machine_mode));
-static void etoc4x PARAMS ((const UEMUSHORT *, UEMUSHORT *,
- enum machine_mode));
-static void toc4x PARAMS ((UEMUSHORT *, UEMUSHORT *,
- enum machine_mode));
-#endif
-#if 0
-static void uditoe PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void ditoe PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void etoudi PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void etodi PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-static void esqrt PARAMS ((const UEMUSHORT *, UEMUSHORT *));
-#endif
-/* Copy 32-bit numbers obtained from array containing 16-bit numbers,
- swapping ends if required, into output array of longs. The
- result is normally passed to fprintf by the ASM_OUTPUT_ macros. */
+/* Right-shift the significand of A by N bits; put the result in the
+ significand of R. If any one bits are shifted out, return true. */
-static void
-endian (e, x, mode)
- const UEMUSHORT e[];
- long x[];
- enum machine_mode mode;
+static bool
+sticky_rshift_significand (r, a, n)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a;
+ unsigned int n;
{
- unsigned long th, t;
+ unsigned long sticky = 0;
+ unsigned int i, ofs = 0;
- if (REAL_WORDS_BIG_ENDIAN)
+ if (n >= HOST_BITS_PER_LONG)
{
- switch (mode)
- {
- case TFmode:
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
- /* Swap halfwords in the fourth long. */
- th = (unsigned long) e[6] & 0xffff;
- t = (unsigned long) e[7] & 0xffff;
- t |= th << 16;
- x[3] = (long) t;
-#else
- x[3] = 0;
-#endif
- /* FALLTHRU */
-
- case XFmode:
- /* Swap halfwords in the third long. */
- th = (unsigned long) e[4] & 0xffff;
- t = (unsigned long) e[5] & 0xffff;
- t |= th << 16;
- x[2] = (long) t;
- /* FALLTHRU */
-
- case DFmode:
- /* Swap halfwords in the second word. */
- th = (unsigned long) e[2] & 0xffff;
- t = (unsigned long) e[3] & 0xffff;
- t |= th << 16;
- x[1] = (long) t;
- /* FALLTHRU */
-
- case SFmode:
- case HFmode:
- /* Swap halfwords in the first word. */
- th = (unsigned long) e[0] & 0xffff;
- t = (unsigned long) e[1] & 0xffff;
- t |= th << 16;
- x[0] = (long) t;
- break;
+ for (i = 0, ofs = n / HOST_BITS_PER_LONG; i < ofs; ++i)
+ sticky |= a->sig[i];
+ n &= HOST_BITS_PER_LONG - 1;
+ }
- default:
- abort ();
+ if (n != 0)
+ {
+ sticky |= a->sig[ofs] & (((unsigned long)1 << n) - 1);
+ for (i = 0; i < SIGSZ; ++i)
+ {
+ r->sig[i]
+ = (((ofs + i >= SIGSZ ? 0 : a->sig[ofs + i]) >> n)
+ | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[ofs + i + 1])
+ << (HOST_BITS_PER_LONG - n)));
}
}
else
{
- /* Pack the output array without swapping. */
-
- switch (mode)
- {
- case TFmode:
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
- /* Pack the fourth long. */
- th = (unsigned long) e[7] & 0xffff;
- t = (unsigned long) e[6] & 0xffff;
- t |= th << 16;
- x[3] = (long) t;
-#else
- x[3] = 0;
-#endif
- /* FALLTHRU */
-
- case XFmode:
- /* Pack the third long.
- Each element of the input REAL_VALUE_TYPE array has 16 useful bits
- in it. */
- th = (unsigned long) e[5] & 0xffff;
- t = (unsigned long) e[4] & 0xffff;
- t |= th << 16;
- x[2] = (long) t;
- /* FALLTHRU */
-
- case DFmode:
- /* Pack the second long */
- th = (unsigned long) e[3] & 0xffff;
- t = (unsigned long) e[2] & 0xffff;
- t |= th << 16;
- x[1] = (long) t;
- /* FALLTHRU */
-
- case SFmode:
- case HFmode:
- /* Pack the first long */
- th = (unsigned long) e[1] & 0xffff;
- t = (unsigned long) e[0] & 0xffff;
- t |= th << 16;
- x[0] = (long) t;
- break;
-
- default:
- abort ();
- }
+ for (i = 0; ofs + i < SIGSZ; ++i)
+ r->sig[i] = a->sig[ofs + i];
+ for (; i < SIGSZ; ++i)
+ r->sig[i] = 0;
}
-}
+ return sticky != 0;
+}
-/* This is the implementation of the REAL_ARITHMETIC macro. */
+/* Right-shift the significand of A by N bits; put the result in the
+ significand of R. */
-void
-earith (value, icode, r1, r2)
- REAL_VALUE_TYPE *value;
- int icode;
- REAL_VALUE_TYPE *r1;
- REAL_VALUE_TYPE *r2;
+static void
+rshift_significand (r, a, n)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a;
+ unsigned int n;
{
- UEMUSHORT d1[NE], d2[NE], v[NE];
- enum tree_code code;
-
- GET_REAL (r1, d1);
- GET_REAL (r2, d2);
-#ifdef NANS
-/* Return NaN input back to the caller. */
- if (eisnan (d1))
- {
- PUT_REAL (d1, value);
- return;
- }
- if (eisnan (d2))
- {
- PUT_REAL (d2, value);
- return;
- }
-#endif
- code = (enum tree_code) icode;
- switch (code)
- {
- case PLUS_EXPR:
- eadd (d2, d1, v);
- break;
+ unsigned int i, ofs = n / HOST_BITS_PER_LONG;
- case MINUS_EXPR:
- esub (d2, d1, v); /* d1 - d2 */
- break;
-
- case MULT_EXPR:
- emul (d2, d1, v);
- break;
-
- case RDIV_EXPR:
-#ifndef REAL_INFINITY
- if (ecmp (d2, ezero) == 0)
+ n &= HOST_BITS_PER_LONG - 1;
+ if (n != 0)
+ {
+ for (i = 0; i < SIGSZ; ++i)
{
-#ifdef NANS
- enan (v, eisneg (d1) ^ eisneg (d2));
- break;
-#else
- abort ();
-#endif
+ r->sig[i]
+ = (((ofs + i >= SIGSZ ? 0 : a->sig[ofs + i]) >> n)
+ | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[ofs + i + 1])
+ << (HOST_BITS_PER_LONG - n)));
}
-#endif
- ediv (d2, d1, v); /* d1/d2 */
- break;
-
- case MIN_EXPR: /* min (d1,d2) */
- if (ecmp (d1, d2) < 0)
- emov (d1, v);
- else
- emov (d2, v);
- break;
-
- case MAX_EXPR: /* max (d1,d2) */
- if (ecmp (d1, d2) > 0)
- emov (d1, v);
- else
- emov (d2, v);
- break;
- default:
- emov (ezero, v);
- break;
}
-PUT_REAL (v, value);
+ else
+ {
+ for (i = 0; ofs + i < SIGSZ; ++i)
+ r->sig[i] = a->sig[ofs + i];
+ for (; i < SIGSZ; ++i)
+ r->sig[i] = 0;
+ }
}
+/* Left-shift the significand of A by N bits; put the result in the
+ significand of R. */
-/* Truncate REAL_VALUE_TYPE toward zero to signed HOST_WIDE_INT.
- implements REAL_VALUE_RNDZINT (x) (etrunci (x)). */
-
-REAL_VALUE_TYPE
-etrunci (x)
- REAL_VALUE_TYPE x;
+static void
+lshift_significand (r, a, n)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a;
+ unsigned int n;
{
- UEMUSHORT f[NE], g[NE];
- REAL_VALUE_TYPE r;
- HOST_WIDE_INT l;
+ unsigned int i, ofs = n / HOST_BITS_PER_LONG;
- GET_REAL (&x, g);
-#ifdef NANS
- if (eisnan (g))
- return (x);
-#endif
- eifrac (g, &l, f);
- ltoe (&l, g);
- PUT_REAL (g, &r);
- return (r);
+ n &= HOST_BITS_PER_LONG - 1;
+ if (n == 0)
+ {
+ for (i = 0; ofs + i < SIGSZ; ++i)
+ r->sig[SIGSZ-1-i] = a->sig[SIGSZ-1-i-ofs];
+ for (; i < SIGSZ; ++i)
+ r->sig[SIGSZ-1-i] = 0;
+ }
+ else
+ for (i = 0; i < SIGSZ; ++i)
+ {
+ r->sig[SIGSZ-1-i]
+ = (((ofs + i >= SIGSZ ? 0 : a->sig[SIGSZ-1-i-ofs]) << n)
+ | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[SIGSZ-1-i-ofs-1])
+ >> (HOST_BITS_PER_LONG - n)));
+ }
}
+/* Likewise, but N is specialized to 1. */
-/* Truncate REAL_VALUE_TYPE toward zero to unsigned HOST_WIDE_INT;
- implements REAL_VALUE_UNSIGNED_RNDZINT (x) (etruncui (x)). */
-
-REAL_VALUE_TYPE
-etruncui (x)
- REAL_VALUE_TYPE x;
+static inline void
+lshift_significand_1 (r, a)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a;
{
- UEMUSHORT f[NE], g[NE];
- REAL_VALUE_TYPE r;
- unsigned HOST_WIDE_INT l;
+ unsigned int i;
- GET_REAL (&x, g);
-#ifdef NANS
- if (eisnan (g))
- return (x);
-#endif
- euifrac (g, &l, f);
- ultoe (&l, g);
- PUT_REAL (g, &r);
- return (r);
+ for (i = SIGSZ - 1; i > 0; --i)
+ r->sig[i] = (a->sig[i] << 1) | (a->sig[i-1] >> (HOST_BITS_PER_LONG - 1));
+ r->sig[0] = a->sig[0] << 1;
}
+/* Add the significands of A and B, placing the result in R. Return
+ true if there was carry out of the most significant word. */
-/* This is the REAL_VALUE_ATOF function. It converts a decimal or hexadecimal
- string to binary, rounding off as indicated by the machine_mode argument.
- Then it promotes the rounded value to REAL_VALUE_TYPE. */
-
-REAL_VALUE_TYPE
-ereal_atof (s, t)
- const char *s;
- enum machine_mode t;
+static inline bool
+add_significands (r, a, b)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a, *b;
{
- UEMUSHORT tem[NE], e[NE];
- REAL_VALUE_TYPE r;
+ bool carry = false;
+ int i;
- switch (t)
+ for (i = 0; i < SIGSZ; ++i)
{
-#ifdef C4X
- case QFmode:
- case HFmode:
- asctoe53 (s, tem);
- e53toe (tem, e);
- break;
-#else
- case HFmode:
-#endif
-
- case SFmode:
- asctoe24 (s, tem);
- e24toe (tem, e);
- break;
-
- case DFmode:
- asctoe53 (s, tem);
- e53toe (tem, e);
- break;
-
- case TFmode:
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
- asctoe113 (s, tem);
- e113toe (tem, e);
- break;
-#endif
- /* FALLTHRU */
+ unsigned long ai = a->sig[i];
+ unsigned long ri = ai + b->sig[i];
- case XFmode:
- asctoe64 (s, tem);
- e64toe (tem, e);
- break;
+ if (carry)
+ {
+ carry = ri < ai;
+ carry |= ++ri == 0;
+ }
+ else
+ carry = ri < ai;
- default:
- asctoe (s, e);
+ r->sig[i] = ri;
}
- PUT_REAL (e, &r);
- return (r);
-}
-
-
-/* Expansion of REAL_NEGATE. */
-
-REAL_VALUE_TYPE
-ereal_negate (x)
- REAL_VALUE_TYPE x;
-{
- UEMUSHORT e[NE];
- REAL_VALUE_TYPE r;
- GET_REAL (&x, e);
- eneg (e);
- PUT_REAL (e, &r);
- return (r);
+ return carry;
}
+/* Subtract the significands of A and B, placing the result in R. CARRY is
+ true if there's a borrow incoming to the least significant word.
+ Return true if there was borrow out of the most significant word. */
-/* Round real toward zero to HOST_WIDE_INT;
- implements REAL_VALUE_FIX (x). */
-
-HOST_WIDE_INT
-efixi (x)
- REAL_VALUE_TYPE x;
+static inline bool
+sub_significands (r, a, b, carry)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a, *b;
+ int carry;
{
- UEMUSHORT f[NE], g[NE];
- HOST_WIDE_INT l;
+ int i;
- GET_REAL (&x, f);
-#ifdef NANS
- if (eisnan (f))
+ for (i = 0; i < SIGSZ; ++i)
{
- warning ("conversion from NaN to int");
- return (-1);
- }
-#endif
- eifrac (f, &l, g);
- return l;
-}
+ unsigned long ai = a->sig[i];
+ unsigned long ri = ai - b->sig[i];
-/* Round real toward zero to unsigned HOST_WIDE_INT
- implements REAL_VALUE_UNSIGNED_FIX (x).
- Negative input returns zero. */
-
-unsigned HOST_WIDE_INT
-efixui (x)
- REAL_VALUE_TYPE x;
-{
- UEMUSHORT f[NE], g[NE];
- unsigned HOST_WIDE_INT l;
+ if (carry)
+ {
+ carry = ri > ai;
+ carry |= ~--ri == 0;
+ }
+ else
+ carry = ri > ai;
- GET_REAL (&x, f);
-#ifdef NANS
- if (eisnan (f))
- {
- warning ("conversion from NaN to unsigned int");
- return (-1);
+ r->sig[i] = ri;
}
-#endif
- euifrac (f, &l, g);
- return l;
-}
+ return carry;
+}
-/* REAL_VALUE_FROM_INT macro. */
+/* Negate the significand A, placing the result in R. */
-void
-ereal_from_int (d, i, j, mode)
- REAL_VALUE_TYPE *d;
- HOST_WIDE_INT i, j;
- enum machine_mode mode;
+static inline void
+neg_significand (r, a)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a;
{
- UEMUSHORT df[NE], dg[NE];
- HOST_WIDE_INT low, high;
- int sign;
-
- if (GET_MODE_CLASS (mode) != MODE_FLOAT)
- abort ();
- sign = 0;
- low = i;
- if ((high = j) < 0)
- {
- sign = 1;
- /* complement and add 1 */
- high = ~high;
- if (low)
- low = -low;
- else
- high += 1;
- }
- eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
- ultoe ((unsigned HOST_WIDE_INT *) &high, dg);
- emul (dg, df, dg);
- ultoe ((unsigned HOST_WIDE_INT *) &low, df);
- eadd (df, dg, dg);
- if (sign)
- eneg (dg);
+ bool carry = true;
+ int i;
- /* A REAL_VALUE_TYPE may not be wide enough to hold the two HOST_WIDE_INTS.
- Avoid double-rounding errors later by rounding off now from the
- extra-wide internal format to the requested precision. */
- switch (GET_MODE_BITSIZE (mode))
+ for (i = 0; i < SIGSZ; ++i)
{
- case 32:
- etoe24 (dg, df);
- e24toe (df, dg);
- break;
-
- case 64:
- etoe53 (dg, df);
- e53toe (df, dg);
- break;
+ unsigned long ri, ai = a->sig[i];
- case 96:
- etoe64 (dg, df);
- e64toe (df, dg);
- break;
-
- case 128:
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
- etoe113 (dg, df);
- e113toe (df, dg);
-#else
- etoe64 (dg, df);
- e64toe (df, dg);
-#endif
- break;
-
- default:
- abort ();
- }
-
- PUT_REAL (dg, d);
-}
+ if (carry)
+ {
+ if (ai)
+ {
+ ri = -ai;
+ carry = false;
+ }
+ else
+ ri = ai;
+ }
+ else
+ ri = ~ai;
+ r->sig[i] = ri;
+ }
+}
-/* REAL_VALUE_FROM_UNSIGNED_INT macro. */
+/* Compare significands. Return tri-state vs zero. */
-void
-ereal_from_uint (d, i, j, mode)
- REAL_VALUE_TYPE *d;
- unsigned HOST_WIDE_INT i, j;
- enum machine_mode mode;
+static inline int
+cmp_significands (a, b)
+ const REAL_VALUE_TYPE *a, *b;
{
- UEMUSHORT df[NE], dg[NE];
- unsigned HOST_WIDE_INT low, high;
+ int i;
- if (GET_MODE_CLASS (mode) != MODE_FLOAT)
- abort ();
- low = i;
- high = j;
- eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
- ultoe (&high, dg);
- emul (dg, df, dg);
- ultoe (&low, df);
- eadd (df, dg, dg);
-
- /* A REAL_VALUE_TYPE may not be wide enough to hold the two HOST_WIDE_INTS.
- Avoid double-rounding errors later by rounding off now from the
- extra-wide internal format to the requested precision. */
- switch (GET_MODE_BITSIZE (mode))
+ for (i = SIGSZ - 1; i >= 0; --i)
{
- case 32:
- etoe24 (dg, df);
- e24toe (df, dg);
- break;
-
- case 64:
- etoe53 (dg, df);
- e53toe (df, dg);
- break;
-
- case 96:
- etoe64 (dg, df);
- e64toe (df, dg);
- break;
-
- case 128:
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
- etoe113 (dg, df);
- e113toe (df, dg);
-#else
- etoe64 (dg, df);
- e64toe (df, dg);
-#endif
- break;
+ unsigned long ai = a->sig[i];
+ unsigned long bi = b->sig[i];
- default:
- abort ();
- }
+ if (ai > bi)
+ return 1;
+ if (ai < bi)
+ return -1;
+ }
- PUT_REAL (dg, d);
+ return 0;
}
+/* Return true if A is nonzero. */
-/* REAL_VALUE_TO_INT macro. */
-
-void
-ereal_to_int (low, high, rr)
- HOST_WIDE_INT *low, *high;
- REAL_VALUE_TYPE rr;
+static inline int
+cmp_significand_0 (a)
+ const REAL_VALUE_TYPE *a;
{
- UEMUSHORT d[NE], df[NE], dg[NE], dh[NE];
- int s;
-
- GET_REAL (&rr, d);
-#ifdef NANS
- if (eisnan (d))
- {
- warning ("conversion from NaN to int");
- *low = -1;
- *high = -1;
- return;
- }
-#endif
- /* convert positive value */
- s = 0;
- if (eisneg (d))
- {
- eneg (d);
- s = 1;
- }
- eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
- ediv (df, d, dg); /* dg = d / 2^32 is the high word */
- euifrac (dg, (unsigned HOST_WIDE_INT *) high, dh);
- emul (df, dh, dg); /* fractional part is the low word */
- euifrac (dg, (unsigned HOST_WIDE_INT *) low, dh);
- if (s)
- {
- /* complement and add 1 */
- *high = ~(*high);
- if (*low)
- *low = -(*low);
- else
- *high += 1;
- }
-}
-
-
-/* REAL_VALUE_LDEXP macro. */
+ int i;
-REAL_VALUE_TYPE
-ereal_ldexp (x, n)
- REAL_VALUE_TYPE x;
- int n;
-{
- UEMUSHORT e[NE], y[NE];
- REAL_VALUE_TYPE r;
+ for (i = SIGSZ - 1; i >= 0; --i)
+ if (a->sig[i])
+ return 1;
- GET_REAL (&x, e);
-#ifdef NANS
- if (eisnan (e))
- return (x);
-#endif
- eldexp (e, n, y);
- PUT_REAL (y, &r);
- return (r);
+ return 0;
}
-/* These routines are conditionally compiled because functions
- of the same names may be defined in fold-const.c. */
-
-#ifdef REAL_ARITHMETIC
-
-/* Check for infinity in a REAL_VALUE_TYPE. */
+/* Set bit N of the significand of R. */
-int
-target_isinf (x)
- REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
+static inline void
+set_significand_bit (r, n)
+ REAL_VALUE_TYPE *r;
+ unsigned int n;
{
-#ifdef INFINITY
- UEMUSHORT e[NE];
-
- GET_REAL (&x, e);
- return (eisinf (e));
-#else
- return 0;
-#endif
+ r->sig[n / HOST_BITS_PER_LONG]
+ |= (unsigned long)1 << (n % HOST_BITS_PER_LONG);
}
-/* Check whether a REAL_VALUE_TYPE item is a NaN. */
+/* Clear bit N of the significand of R. */
-int
-target_isnan (x)
- REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
+static inline void
+clear_significand_bit (r, n)
+ REAL_VALUE_TYPE *r;
+ unsigned int n;
{
-#ifdef NANS
- UEMUSHORT e[NE];
-
- GET_REAL (&x, e);
- return (eisnan (e));
-#else
- return (0);
-#endif
+ r->sig[n / HOST_BITS_PER_LONG]
+ &= ~((unsigned long)1 << (n % HOST_BITS_PER_LONG));
}
+/* Test bit N of the significand of R. */
-/* Check for a negative REAL_VALUE_TYPE number.
- This just checks the sign bit, so that -0 counts as negative. */
-
-int
-target_negative (x)
- REAL_VALUE_TYPE x;
+static inline bool
+test_significand_bit (r, n)
+ REAL_VALUE_TYPE *r;
+ unsigned int n;
{
- return ereal_isneg (x);
+ /* ??? Compiler bug here if we return this expression directly.
+ The conversion to bool strips the "&1" and we wind up testing
+ e.g. 2 != 0 -> true. Seen in gcc version 3.2 20020520. */
+ int t = (r->sig[n / HOST_BITS_PER_LONG] >> (n % HOST_BITS_PER_LONG)) & 1;
+ return t;
}
-/* Expansion of REAL_VALUE_TRUNCATE.
- The result is in floating point, rounded to nearest or even. */
+/* Clear bits 0..N-1 of the significand of R. */
-REAL_VALUE_TYPE
-real_value_truncate (mode, arg)
- enum machine_mode mode;
- REAL_VALUE_TYPE arg;
+static void
+clear_significand_below (r, n)
+ REAL_VALUE_TYPE *r;
+ unsigned int n;
{
- UEMUSHORT e[NE], t[NE];
- REAL_VALUE_TYPE r;
+ int i, w = n / HOST_BITS_PER_LONG;
- GET_REAL (&arg, e);
-#ifdef NANS
- if (eisnan (e))
- return (arg);
-#endif
- eclear (t);
- switch (mode)
- {
- case TFmode:
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
- etoe113 (e, t);
- e113toe (t, t);
- break;
-#endif
- /* FALLTHRU */
+ for (i = 0; i < w; ++i)
+ r->sig[i] = 0;
- case XFmode:
- etoe64 (e, t);
- e64toe (t, t);
- break;
+ r->sig[w] &= ~(((unsigned long)1 << (n % HOST_BITS_PER_LONG)) - 1);
+}
- case DFmode:
- etoe53 (e, t);
- e53toe (t, t);
- break;
+/* Divide the significands of A and B, placing the result in R. Return
+ true if the division was inexact. */
- case SFmode:
-#ifndef C4X
- case HFmode:
-#endif
- etoe24 (e, t);
- e24toe (t, t);
- break;
+static inline bool
+div_significands (r, a, b)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a, *b;
+{
+ REAL_VALUE_TYPE u;
+ int i, bit = SIGNIFICAND_BITS - 1;
+ unsigned long msb, inexact;
-#ifdef C4X
- case HFmode:
- case QFmode:
- etoe53 (e, t);
- e53toe (t, t);
- break;
-#endif
+ u = *a;
+ memset (r->sig, 0, sizeof (r->sig));
- case SImode:
- r = etrunci (arg);
- return (r);
+ msb = 0;
+ goto start;
+ do
+ {
+ msb = u.sig[SIGSZ-1] & SIG_MSB;
+ lshift_significand_1 (&u, &u);
+ start:
+ if (msb || cmp_significands (&u, b) >= 0)
+ {
+ sub_significands (&u, &u, b, 0);
+ set_significand_bit (r, bit);
+ }
+ }
+ while (--bit >= 0);
- /* If an unsupported type was requested, presume that
- the machine files know something useful to do with
- the unmodified value. */
+ for (i = 0, inexact = 0; i < SIGSZ; i++)
+ inexact |= u.sig[i];
- default:
- return (arg);
- }
- PUT_REAL (t, &r);
- return (r);
+ return inexact != 0;
}
-/* Try to change R into its exact multiplicative inverse in machine mode
- MODE. Return nonzero function value if successful. */
+/* Adjust the exponent and significand of R such that the most
+ significant bit is set. We underflow to zero and overflow to
+ infinity here, without denormals. (The intermediate representation
+ exponent is large enough to handle target denormals normalized.) */
-int
-exact_real_inverse (mode, r)
- enum machine_mode mode;
+static void
+normalize (r)
REAL_VALUE_TYPE *r;
{
- UEMUSHORT e[NE], einv[NE];
- REAL_VALUE_TYPE rinv;
- int i;
-
- GET_REAL (r, e);
-
- /* Test for input in range. Don't transform IEEE special values. */
- if (eisinf (e) || eisnan (e) || (ecmp (e, ezero) == 0))
- return 0;
+ int shift = 0, exp;
+ int i, j;
- /* Test for a power of 2: all significand bits zero except the MSB.
- We are assuming the target has binary (or hex) arithmetic. */
- if (e[NE - 2] != 0x8000)
- return 0;
+ /* Find the first word that is nonzero. */
+ for (i = SIGSZ - 1; i >= 0; i--)
+ if (r->sig[i] == 0)
+ shift += HOST_BITS_PER_LONG;
+ else
+ break;
- for (i = 0; i < NE - 2; i++)
+ /* Zero significand flushes to zero. */
+ if (i < 0)
{
- if (e[i] != 0)
- return 0;
+ r->class = rvc_zero;
+ r->exp = 0;
+ return;
}
- /* Compute the inverse and truncate it to the required mode. */
- ediv (e, eone, einv);
- PUT_REAL (einv, &rinv);
- rinv = real_value_truncate (mode, rinv);
-
-#ifdef CHECK_FLOAT_VALUE
- /* This check is not redundant. It may, for example, flush
- a supposedly IEEE denormal value to zero. */
- i = 0;
- if (CHECK_FLOAT_VALUE (mode, rinv, i))
- return 0;
-#endif
- GET_REAL (&rinv, einv);
-
- /* Check the bits again, because the truncation might have
- generated an arbitrary saturation value on overflow. */
- if (einv[NE - 2] != 0x8000)
- return 0;
+ /* Find the first bit that is nonzero. */
+ for (j = 0; ; j++)
+ if (r->sig[i] & ((unsigned long)1 << (HOST_BITS_PER_LONG - 1 - j)))
+ break;
+ shift += j;
- for (i = 0; i < NE - 2; i++)
+ if (shift > 0)
{
- if (einv[i] != 0)
- return 0;
+ exp = r->exp - shift;
+ if (exp > MAX_EXP)
+ get_inf (r, r->sign);
+ else if (exp < -MAX_EXP)
+ get_zero (r, r->sign);
+ else
+ {
+ r->exp = exp;
+ lshift_significand (r, r, shift);
+ }
}
-
- /* Fail if the computed inverse is out of range. */
- if (eisinf (einv) || eisnan (einv) || (ecmp (einv, ezero) == 0))
- return 0;
-
- /* Output the reciprocal and return success flag. */
- PUT_REAL (einv, r);
- return 1;
}
-#endif /* REAL_ARITHMETIC defined */
-
-/* Used for debugging--print the value of R in human-readable format
- on stderr. */
-
-void
-debug_real (r)
- REAL_VALUE_TYPE r;
-{
- char dstr[30];
-
- REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr);
- fprintf (stderr, "%s", dstr);
-}
-
-/* The following routines convert REAL_VALUE_TYPE to the various floating
- point formats that are meaningful to supported computers.
+/* Return R = A + (SUBTRACT_P ? -B : B). */
- The results are returned in 32-bit pieces, each piece stored in a `long'.
- This is so they can be printed by statements like
-
- fprintf (file, "%lx, %lx", L[0], L[1]);
-
- that will work on both narrow- and wide-word host computers. */
-
-/* Convert R to a 128-bit long double precision value. The output array L
- contains four 32-bit pieces of the result, in the order they would appear
- in memory. */
-
-void
-etartdouble (r, l)
- REAL_VALUE_TYPE r;
- long l[];
+static void
+do_add (r, a, b, subtract_p)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a, *b;
+ int subtract_p;
{
- UEMUSHORT e[NE];
+ int dexp, sign, exp;
+ REAL_VALUE_TYPE t;
+ bool inexact = false;
- GET_REAL (&r, e);
-#if INTEL_EXTENDED_IEEE_FORMAT == 0
- etoe113 (e, e);
-#else
- etoe64 (e, e);
-#endif
- endian (e, l, TFmode);
-}
+ /* Determine if we need to add or subtract. */
+ sign = a->sign;
+ subtract_p = (sign ^ b->sign) ^ subtract_p;
-/* Convert R to a double extended precision value. The output array L
- contains three 32-bit pieces of the result, in the order they would
- appear in memory. */
+ switch (CLASS2 (a->class, b->class))
+ {
+ case CLASS2 (rvc_zero, rvc_zero):
+ /* -0 + -0 = -0, -0 - +0 = -0; all other cases yield +0. */
+ get_zero (r, sign & !subtract_p);
+ return;
-void
-etarldouble (r, l)
- REAL_VALUE_TYPE r;
- long l[];
-{
- UEMUSHORT e[NE];
+ case CLASS2 (rvc_zero, rvc_normal):
+ case CLASS2 (rvc_zero, rvc_inf):
+ case CLASS2 (rvc_zero, rvc_nan):
+ /* 0 + ANY = ANY. */
+ case CLASS2 (rvc_normal, rvc_nan):
+ case CLASS2 (rvc_inf, rvc_nan):
+ case CLASS2 (rvc_nan, rvc_nan):
+ /* ANY + NaN = NaN. */
+ case CLASS2 (rvc_normal, rvc_inf):
+ /* R + Inf = Inf. */
+ *r = *b;
+ r->sign = sign ^ subtract_p;
+ return;
- GET_REAL (&r, e);
- etoe64 (e, e);
- endian (e, l, XFmode);
-}
+ case CLASS2 (rvc_normal, rvc_zero):
+ case CLASS2 (rvc_inf, rvc_zero):
+ case CLASS2 (rvc_nan, rvc_zero):
+ /* ANY + 0 = ANY. */
+ case CLASS2 (rvc_nan, rvc_normal):
+ case CLASS2 (rvc_nan, rvc_inf):
+ /* NaN + ANY = NaN. */
+ case CLASS2 (rvc_inf, rvc_normal):
+ /* Inf + R = Inf. */
+ *r = *a;
+ return;
-/* Convert R to a double precision value. The output array L contains two
- 32-bit pieces of the result, in the order they would appear in memory. */
+ case CLASS2 (rvc_inf, rvc_inf):
+ if (subtract_p)
+ /* Inf - Inf = NaN. */
+ get_canonical_qnan (r, 0);
+ else
+ /* Inf + Inf = Inf. */
+ *r = *a;
+ return;
-void
-etardouble (r, l)
- REAL_VALUE_TYPE r;
- long l[];
-{
- UEMUSHORT e[NE];
+ case CLASS2 (rvc_normal, rvc_normal):
+ break;
- GET_REAL (&r, e);
- etoe53 (e, e);
- endian (e, l, DFmode);
-}
+ default:
+ abort ();
+ }
-/* Convert R to a single precision float value stored in the least-significant
- bits of a `long'. */
+ /* Swap the arguments such that A has the larger exponent. */
+ dexp = a->exp - b->exp;
+ if (dexp < 0)
+ {
+ const REAL_VALUE_TYPE *t;
+ t = a, a = b, b = t;
+ dexp = -dexp;
+ sign ^= subtract_p;
+ }
+ exp = a->exp;
-long
-etarsingle (r)
- REAL_VALUE_TYPE r;
-{
- UEMUSHORT e[NE];
- long l;
+ /* If the exponents are not identical, we need to shift the
+ significand of B down. */
+ if (dexp > 0)
+ {
+ /* If the exponents are too far apart, the significands
+ do not overlap, which makes the subtraction a noop. */
+ if (dexp >= SIGNIFICAND_BITS)
+ {
+ *r = *a;
+ r->sign = sign;
+ return;
+ }
- GET_REAL (&r, e);
- etoe24 (e, e);
- endian (e, &l, SFmode);
- return ((long) l);
-}
+ inexact |= sticky_rshift_significand (&t, b, dexp);
+ b = &t;
+ }
-/* Convert X to a decimal ASCII string S for output to an assembly
- language file. Note, there is no standard way to spell infinity or
- a NaN, so these values may require special treatment in the tm.h
- macros. */
+ if (subtract_p)
+ {
+ if (sub_significands (r, a, b, inexact))
+ {
+ /* We got a borrow out of the subtraction. That means that
+ A and B had the same exponent, and B had the larger
+ significand. We need to swap the sign and negate the
+ significand. */
+ sign ^= 1;
+ neg_significand (r, r);
+ }
+ }
+ else
+ {
+ if (add_significands (r, a, b))
+ {
+ /* We got carry out of the addition. This means we need to
+ shift the significand back down one bit and increase the
+ exponent. */
+ inexact |= sticky_rshift_significand (r, r, 1);
+ r->sig[SIGSZ-1] |= SIG_MSB;
+ if (++exp > MAX_EXP)
+ {
+ get_inf (r, sign);
+ return;
+ }
+ }
+ }
-void
-ereal_to_decimal (x, s)
- REAL_VALUE_TYPE x;
- char *s;
-{
- UEMUSHORT e[NE];
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp;
- GET_REAL (&x, e);
- etoasc (e, s, 20);
+ /* Re-normalize the result. */
+ normalize (r);
+
+ /* Special case: if the subtraction results in zero, the result
+ is positive. */
+ if (r->class == rvc_zero)
+ r->sign = 0;
+ else
+ r->sig[0] |= inexact;
}
-/* Compare X and Y. Return 1 if X > Y, 0 if X == Y, -1 if X < Y,
- or -2 if either is a NaN. */
+/* Return R = A * B. */
-int
-ereal_cmp (x, y)
- REAL_VALUE_TYPE x, y;
+static void
+do_multiply (r, a, b)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a, *b;
{
- UEMUSHORT ex[NE], ey[NE];
+ REAL_VALUE_TYPE u, t, *rr;
+ unsigned int i, j, k;
+ int sign = a->sign ^ b->sign;
- GET_REAL (&x, ex);
- GET_REAL (&y, ey);
- return (ecmp (ex, ey));
-}
+ switch (CLASS2 (a->class, b->class))
+ {
+ case CLASS2 (rvc_zero, rvc_zero):
+ case CLASS2 (rvc_zero, rvc_normal):
+ case CLASS2 (rvc_normal, rvc_zero):
+ /* +-0 * ANY = 0 with appropriate sign. */
+ get_zero (r, sign);
+ return;
-/* Return 1 if the sign bit of X is set, else return 0. */
+ case CLASS2 (rvc_zero, rvc_nan):
+ case CLASS2 (rvc_normal, rvc_nan):
+ case CLASS2 (rvc_inf, rvc_nan):
+ case CLASS2 (rvc_nan, rvc_nan):
+ /* ANY * NaN = NaN. */
+ *r = *b;
+ r->sign = sign;
+ return;
-int
-ereal_isneg (x)
- REAL_VALUE_TYPE x;
-{
- UEMUSHORT ex[NE];
+ case CLASS2 (rvc_nan, rvc_zero):
+ case CLASS2 (rvc_nan, rvc_normal):
+ case CLASS2 (rvc_nan, rvc_inf):
+ /* NaN * ANY = NaN. */
+ *r = *a;
+ r->sign = sign;
+ return;
- GET_REAL (&x, ex);
- return (eisneg (ex));
-}
+ case CLASS2 (rvc_zero, rvc_inf):
+ case CLASS2 (rvc_inf, rvc_zero):
+ /* 0 * Inf = NaN */
+ get_canonical_qnan (r, sign);
+ return;
-/* End of REAL_ARITHMETIC interface */
-
-/*
- Extended precision IEEE binary floating point arithmetic routines
+ case CLASS2 (rvc_inf, rvc_inf):
+ case CLASS2 (rvc_normal, rvc_inf):
+ case CLASS2 (rvc_inf, rvc_normal):
+ /* Inf * Inf = Inf, R * Inf = Inf */
+ overflow:
+ get_inf (r, sign);
+ return;
- Numbers are stored in C language as arrays of 16-bit unsigned
- short integers. The arguments of the routines are pointers to
- the arrays.
+ case CLASS2 (rvc_normal, rvc_normal):
+ break;
- External e type data structure, similar to Intel 8087 chip
- temporary real format but possibly with a larger significand:
+ default:
+ abort ();
+ }
- NE-1 significand words (least significant word first,
- most significant bit is normally set)
- exponent (value = EXONE for 1.0,
- top bit is the sign)
+ if (r == a || r == b)
+ rr = &t;
+ else
+ rr = r;
+ get_zero (rr, 0);
+ /* Collect all the partial products. Since we don't have sure access
+ to a widening multiply, we split each long into two half-words.
- Internal exploded e-type data structure of a number (a "word" is 16 bits):
+ Consider the long-hand form of a four half-word multiplication:
- ei[0] sign word (0 for positive, 0xffff for negative)
- ei[1] biased exponent (value = EXONE for the number 1.0)
- ei[2] high guard word (always zero after normalization)
- ei[3]
- to ei[NI-2] significand (NI-4 significand words,
- most significant word first,
- most significant bit is set)
- ei[NI-1] low guard word (0x8000 bit is rounding place)
+ A B C D
+ * E F G H
+ --------------
+ DE DF DG DH
+ CE CF CG CH
+ BE BF BG BH
+ AE AF AG AH
+ We construct partial products of the widened half-word products
+ that are known to not overlap, e.g. DF+DH. Each such partial
+ product is given its proper exponent, which allows us to sum them
+ and obtain the finished product. */
+ for (i = 0; i < SIGSZ * 2; ++i)
+ {
+ unsigned long ai = a->sig[i / 2];
+ if (i & 1)
+ ai >>= HOST_BITS_PER_LONG / 2;
+ else
+ ai &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1;
- Routines for external format e-type numbers
+ if (ai == 0)
+ continue;
- asctoe (string, e) ASCII string to extended double e type
- asctoe64 (string, &d) ASCII string to long double
- asctoe53 (string, &d) ASCII string to double
- asctoe24 (string, &f) ASCII string to single
- asctoeg (string, e, prec) ASCII string to specified precision
- e24toe (&f, e) IEEE single precision to e type
- e53toe (&d, e) IEEE double precision to e type
- e64toe (&d, e) IEEE long double precision to e type
- e113toe (&d, e) 128-bit long double precision to e type
-#if 0
- eabs (e) absolute value
-#endif
- eadd (a, b, c) c = b + a
- eclear (e) e = 0
- ecmp (a, b) Returns 1 if a > b, 0 if a == b,
- -1 if a < b, -2 if either a or b is a NaN.
- ediv (a, b, c) c = b / a
- efloor (a, b) truncate to integer, toward -infinity
- efrexp (a, exp, s) extract exponent and significand
- eifrac (e, &l, frac) e to HOST_WIDE_INT and e type fraction
- euifrac (e, &l, frac) e to unsigned HOST_WIDE_INT and e type fraction
- einfin (e) set e to infinity, leaving its sign alone
- eldexp (a, n, b) multiply by 2**n
- emov (a, b) b = a
- emul (a, b, c) c = b * a
- eneg (e) e = -e
-#if 0
- eround (a, b) b = nearest integer value to a
-#endif
- esub (a, b, c) c = b - a
-#if 0
- e24toasc (&f, str, n) single to ASCII string, n digits after decimal
- e53toasc (&d, str, n) double to ASCII string, n digits after decimal
- e64toasc (&d, str, n) 80-bit long double to ASCII string
- e113toasc (&d, str, n) 128-bit long double to ASCII string
-#endif
- etoasc (e, str, n) e to ASCII string, n digits after decimal
- etoe24 (e, &f) convert e type to IEEE single precision
- etoe53 (e, &d) convert e type to IEEE double precision
- etoe64 (e, &d) convert e type to IEEE long double precision
- ltoe (&l, e) HOST_WIDE_INT to e type
- ultoe (&l, e) unsigned HOST_WIDE_INT to e type
- eisneg (e) 1 if sign bit of e != 0, else 0
- eisinf (e) 1 if e has maximum exponent (non-IEEE)
- or is infinite (IEEE)
- eisnan (e) 1 if e is a NaN
-
-
- Routines for internal format exploded e-type numbers
-
- eaddm (ai, bi) add significands, bi = bi + ai
- ecleaz (ei) ei = 0
- ecleazs (ei) set ei = 0 but leave its sign alone
- ecmpm (ai, bi) compare significands, return 1, 0, or -1
- edivm (ai, bi) divide significands, bi = bi / ai
- emdnorm (ai,l,s,exp) normalize and round off
- emovi (a, ai) convert external a to internal ai
- emovo (ai, a) convert internal ai to external a
- emovz (ai, bi) bi = ai, low guard word of bi = 0
- emulm (ai, bi) multiply significands, bi = bi * ai
- enormlz (ei) left-justify the significand
- eshdn1 (ai) shift significand and guards down 1 bit
- eshdn8 (ai) shift down 8 bits
- eshdn6 (ai) shift down 16 bits
- eshift (ai, n) shift ai n bits up (or down if n < 0)
- eshup1 (ai) shift significand and guards up 1 bit
- eshup8 (ai) shift up 8 bits
- eshup6 (ai) shift up 16 bits
- esubm (ai, bi) subtract significands, bi = bi - ai
- eiisinf (ai) 1 if infinite
- eiisnan (ai) 1 if a NaN
- eiisneg (ai) 1 if sign bit of ai != 0, else 0
- einan (ai) set ai = NaN
-#if 0
- eiinfin (ai) set ai = infinity
-#endif
+ for (j = 0; j < 2; ++j)
+ {
+ int exp = (a->exp - (2*SIGSZ-1-i)*(HOST_BITS_PER_LONG/2)
+ + (b->exp - (1-j)*(HOST_BITS_PER_LONG/2)));
- The result is always normalized and rounded to NI-4 word precision
- after each arithmetic operation.
-
- Exception flags are NOT fully supported.
-
- Signaling NaN's are NOT supported; they are treated the same
- as quiet NaN's.
-
- Define INFINITY for support of infinity; otherwise a
- saturation arithmetic is implemented.
-
- Define NANS for support of Not-a-Number items; otherwise the
- arithmetic will never produce a NaN output, and might be confused
- by a NaN input.
- If NaN's are supported, the output of `ecmp (a,b)' is -2 if
- either a or b is a NaN. This means asking `if (ecmp (a,b) < 0)'
- may not be legitimate. Use `if (ecmp (a,b) == -1)' for `less than'
- if in doubt.
-
- Denormals are always supported here where appropriate (e.g., not
- for conversion to DEC numbers). */
-
-/* Definitions for error codes that are passed to the common error handling
- routine mtherr.
-
- For Digital Equipment PDP-11 and VAX computers, certain
- IBM systems, and others that use numbers with a 56-bit
- significand, the symbol DEC should be defined. In this
- mode, most floating point constants are given as arrays
- of octal integers to eliminate decimal to binary conversion
- errors that might be introduced by the compiler.
-
- For computers, such as IBM PC, that follow the IEEE
- Standard for Binary Floating Point Arithmetic (ANSI/IEEE
- Std 754-1985), the symbol IEEE should be defined.
- These numbers have 53-bit significands. In this mode, constants
- are provided as arrays of hexadecimal 16 bit integers.
- The endian-ness of generated values is controlled by
- REAL_WORDS_BIG_ENDIAN.
-
- To accommodate other types of computer arithmetic, all
- constants are also provided in a normal decimal radix
- which one can hope are correctly converted to a suitable
- format by the available C language compiler. To invoke
- this mode, the symbol UNK is defined.
-
- An important difference among these modes is a predefined
- set of machine arithmetic constants for each. The numbers
- MACHEP (the machine roundoff error), MAXNUM (largest number
- represented), and several other parameters are preset by
- the configuration symbol. Check the file const.c to
- ensure that these values are correct for your computer.
-
- For ANSI C compatibility, define ANSIC equal to 1. Currently
- this affects only the atan2 function and others that use it. */
-
-/* Constant definitions for math error conditions. */
-
-#define DOMAIN 1 /* argument domain error */
-#define SING 2 /* argument singularity */
-#define OVERFLOW 3 /* overflow range error */
-#define UNDERFLOW 4 /* underflow range error */
-#define TLOSS 5 /* total loss of precision */
-#define PLOSS 6 /* partial loss of precision */
-#define INVALID 7 /* NaN-producing operation */
-
-/* e type constants used by high precision check routines */
-
-#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && (INTEL_EXTENDED_IEEE_FORMAT == 0)
-/* 0.0 */
-const UEMUSHORT ezero[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,};
-
-/* 5.0E-1 */
-const UEMUSHORT ehalf[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3ffe,};
-
-/* 1.0E0 */
-const UEMUSHORT eone[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3fff,};
-
-/* 2.0E0 */
-const UEMUSHORT etwo[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4000,};
-
-/* 3.2E1 */
-const UEMUSHORT e32[NE] =
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4004,};
-
-/* 6.93147180559945309417232121458176568075500134360255E-1 */
-const UEMUSHORT elog2[NE] =
- {0x40f3, 0xf6af, 0x03f2, 0xb398,
- 0xc9e3, 0x79ab, 0150717, 0013767, 0130562, 0x3ffe,};
-
-/* 1.41421356237309504880168872420969807856967187537695E0 */
-const UEMUSHORT esqrt2[NE] =
- {0x1d6f, 0xbe9f, 0x754a, 0x89b3,
- 0x597d, 0x6484, 0174736, 0171463, 0132404, 0x3fff,};
-
-/* 3.14159265358979323846264338327950288419716939937511E0 */
-const UEMUSHORT epi[NE] =
- {0x2902, 0x1cd1, 0x80dc, 0x628b,
- 0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,};
-
-#else
-/* LONG_DOUBLE_TYPE_SIZE is other than 128 */
-const UEMUSHORT ezero[NE] =
- {0, 0000000, 0000000, 0000000, 0000000, 0000000,};
-const UEMUSHORT ehalf[NE] =
- {0, 0000000, 0000000, 0000000, 0100000, 0x3ffe,};
-const UEMUSHORT eone[NE] =
- {0, 0000000, 0000000, 0000000, 0100000, 0x3fff,};
-const UEMUSHORT etwo[NE] =
- {0, 0000000, 0000000, 0000000, 0100000, 0040000,};
-const UEMUSHORT e32[NE] =
- {0, 0000000, 0000000, 0000000, 0100000, 0040004,};
-const UEMUSHORT elog2[NE] =
- {0xc9e4, 0x79ab, 0150717, 0013767, 0130562, 0x3ffe,};
-const UEMUSHORT esqrt2[NE] =
- {0x597e, 0x6484, 0174736, 0171463, 0132404, 0x3fff,};
-const UEMUSHORT epi[NE] =
- {0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,};
-#endif
+ if (exp > MAX_EXP)
+ goto overflow;
+ if (exp < -MAX_EXP)
+ /* Would underflow to zero, which we shouldn't bother adding. */
+ continue;
-/* Control register for rounding precision.
- This can be set to 113 (if NE=10), 80 (if NE=6), 64, 56, 53, or 24 bits. */
+ u.class = rvc_normal;
+ u.sign = 0;
+ u.exp = exp;
-int rndprc = NBITS;
-extern int rndprc;
+ for (k = j; k < SIGSZ * 2; k += 2)
+ {
+ unsigned long bi = b->sig[k / 2];
+ if (k & 1)
+ bi >>= HOST_BITS_PER_LONG / 2;
+ else
+ bi &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1;
-/* Clear out entire e-type number X. */
+ u.sig[k / 2] = ai * bi;
+ }
-static void
-eclear (x)
- UEMUSHORT *x;
-{
- int i;
+ normalize (&u);
+ do_add (rr, rr, &u, 0);
+ }
+ }
- for (i = 0; i < NE; i++)
- *x++ = 0;
+ rr->sign = sign;
+ if (rr != r)
+ *r = t;
}
-/* Move e-type number from A to B. */
+/* Return R = A / B. */
static void
-emov (a, b)
- const UEMUSHORT *a;
- UEMUSHORT *b;
+do_divide (r, a, b)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a, *b;
{
- int i;
-
- for (i = 0; i < NE; i++)
- *b++ = *a++;
-}
+ int exp, sign = a->sign ^ b->sign;
+ REAL_VALUE_TYPE t, *rr;
+ bool inexact;
+ switch (CLASS2 (a->class, b->class))
+ {
+ case CLASS2 (rvc_zero, rvc_zero):
+ /* 0 / 0 = NaN. */
+ case CLASS2 (rvc_inf, rvc_inf):
+ /* Inf / Inf = NaN. */
+ get_canonical_qnan (r, sign);
+ return;
-#if 0
-/* Absolute value of e-type X. */
+ case CLASS2 (rvc_zero, rvc_normal):
+ case CLASS2 (rvc_zero, rvc_inf):
+ /* 0 / ANY = 0. */
+ case CLASS2 (rvc_normal, rvc_inf):
+ /* R / Inf = 0. */
+ underflow:
+ get_zero (r, sign);
+ return;
-static void
-eabs (x)
- UEMUSHORT x[];
-{
- /* sign is top bit of last word of external format */
- x[NE - 1] &= 0x7fff;
-}
-#endif /* 0 */
+ case CLASS2 (rvc_normal, rvc_zero):
+ /* R / 0 = Inf. */
+ case CLASS2 (rvc_inf, rvc_zero):
+ /* Inf / 0 = Inf. */
+ get_inf (r, sign);
+ return;
-/* Negate the e-type number X. */
+ case CLASS2 (rvc_zero, rvc_nan):
+ case CLASS2 (rvc_normal, rvc_nan):
+ case CLASS2 (rvc_inf, rvc_nan):
+ case CLASS2 (rvc_nan, rvc_nan):
+ /* ANY / NaN = NaN. */
+ *r = *b;
+ r->sign = sign;
+ return;
-static void
-eneg (x)
- UEMUSHORT x[];
-{
+ case CLASS2 (rvc_nan, rvc_zero):
+ case CLASS2 (rvc_nan, rvc_normal):
+ case CLASS2 (rvc_nan, rvc_inf):
+ /* NaN / ANY = NaN. */
+ *r = *a;
+ r->sign = sign;
+ return;
- x[NE - 1] ^= 0x8000; /* Toggle the sign bit */
-}
+ case CLASS2 (rvc_inf, rvc_normal):
+ /* Inf / R = Inf. */
+ overflow:
+ get_inf (r, sign);
+ return;
-/* Return 1 if sign bit of e-type number X is nonzero, else zero. */
+ case CLASS2 (rvc_normal, rvc_normal):
+ break;
-static int
-eisneg (x)
- const UEMUSHORT x[];
-{
+ default:
+ abort ();
+ }
- if (x[NE - 1] & 0x8000)
- return (1);
+ if (r == a || r == b)
+ rr = &t;
else
- return (0);
-}
+ rr = r;
-/* Return 1 if e-type number X is infinity, else return zero. */
+ rr->class = rvc_normal;
+ rr->sign = sign;
-static int
-eisinf (x)
- const UEMUSHORT x[];
-{
+ exp = a->exp - b->exp + 1;
+ if (exp > MAX_EXP)
+ goto overflow;
+ if (exp < -MAX_EXP)
+ goto underflow;
+ rr->exp = exp;
-#ifdef NANS
- if (eisnan (x))
- return (0);
-#endif
- if ((x[NE - 1] & 0x7fff) == 0x7fff)
- return (1);
- else
- return (0);
+ inexact = div_significands (rr, a, b);
+
+ /* Re-normalize the result. */
+ normalize (rr);
+ rr->sig[0] |= inexact;
+
+ if (rr != r)
+ *r = t;
}
-/* Check if e-type number is not a number. The bit pattern is one that we
- defined, so we know for sure how to detect it. */
+/* Return a tri-state comparison of A vs B. Return NAN_RESULT if
+ one of the two operands is a NaN. */
static int
-eisnan (x)
- const UEMUSHORT x[] ATTRIBUTE_UNUSED;
+do_compare (a, b, nan_result)
+ const REAL_VALUE_TYPE *a, *b;
+ int nan_result;
{
-#ifdef NANS
- int i;
+ int ret;
- /* NaN has maximum exponent */
- if ((x[NE - 1] & 0x7fff) != 0x7fff)
- return (0);
- /* ... and non-zero significand field. */
- for (i = 0; i < NE - 1; i++)
+ switch (CLASS2 (a->class, b->class))
{
- if (*x++ != 0)
- return (1);
- }
-#endif
+ case CLASS2 (rvc_zero, rvc_zero):
+ /* Sign of zero doesn't matter for compares. */
+ return 0;
- return (0);
-}
+ case CLASS2 (rvc_inf, rvc_zero):
+ case CLASS2 (rvc_inf, rvc_normal):
+ case CLASS2 (rvc_normal, rvc_zero):
+ return (a->sign ? -1 : 1);
-/* Fill e-type number X with infinity pattern (IEEE)
- or largest possible number (non-IEEE). */
+ case CLASS2 (rvc_inf, rvc_inf):
+ return -a->sign - -b->sign;
-static void
-einfin (x)
- UEMUSHORT *x;
-{
- int i;
+ case CLASS2 (rvc_zero, rvc_normal):
+ case CLASS2 (rvc_zero, rvc_inf):
+ case CLASS2 (rvc_normal, rvc_inf):
+ return (b->sign ? 1 : -1);
-#ifdef INFINITY
- for (i = 0; i < NE - 1; i++)
- *x++ = 0;
- *x |= 32767;
-#else
- for (i = 0; i < NE - 1; i++)
- *x++ = 0xffff;
- *x |= 32766;
- if (rndprc < NBITS)
- {
- if (rndprc == 113)
- {
- *(x - 9) = 0;
- *(x - 8) = 0;
- }
- if (rndprc == 64)
- {
- *(x - 5) = 0;
- }
- if (rndprc == 53)
- {
- *(x - 4) = 0xf800;
- }
- else
- {
- *(x - 4) = 0;
- *(x - 3) = 0;
- *(x - 2) = 0xff00;
- }
+ case CLASS2 (rvc_zero, rvc_nan):
+ case CLASS2 (rvc_normal, rvc_nan):
+ case CLASS2 (rvc_inf, rvc_nan):
+ case CLASS2 (rvc_nan, rvc_nan):
+ case CLASS2 (rvc_nan, rvc_zero):
+ case CLASS2 (rvc_nan, rvc_normal):
+ case CLASS2 (rvc_nan, rvc_inf):
+ return nan_result;
+
+ case CLASS2 (rvc_normal, rvc_normal):
+ break;
+
+ default:
+ abort ();
}
-#endif
-}
-/* Output an e-type NaN.
- This generates Intel's quiet NaN pattern for extended real.
- The exponent is 7fff, the leading mantissa word is c000. */
+ if (a->sign != b->sign)
+ return -a->sign - -b->sign;
-#ifdef NANS
-static void
-enan (x, sign)
- UEMUSHORT *x;
- int sign;
-{
- int i;
+ if (a->exp > b->exp)
+ ret = 1;
+ else if (a->exp < b->exp)
+ ret = -1;
+ else
+ ret = cmp_significands (a, b);
- for (i = 0; i < NE - 2; i++)
- *x++ = 0;
- *x++ = 0xc000;
- *x = (sign << 15) | 0x7fff;
+ return (a->sign ? -ret : ret);
}
-#endif /* NANS */
-/* Move in an e-type number A, converting it to exploded e-type B. */
+/* Return A truncated to an integral value toward zero. */
static void
-emovi (a, b)
- const UEMUSHORT *a;
- UEMUSHORT *b;
+do_fix_trunc (r, a)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a;
{
- const UEMUSHORT *p;
- UEMUSHORT *q;
- int i;
+ *r = *a;
- q = b;
- p = a + (NE - 1); /* point to last word of external number */
- /* get the sign bit */
- if (*p & 0x8000)
- *q++ = 0xffff;
- else
- *q++ = 0;
- /* get the exponent */
- *q = *p--;
- *q++ &= 0x7fff; /* delete the sign bit */
-#ifdef INFINITY
- if ((*(q - 1) & 0x7fff) == 0x7fff)
+ switch (r->class)
{
-#ifdef NANS
- if (eisnan (a))
- {
- *q++ = 0;
- for (i = 3; i < NI; i++)
- *q++ = *p--;
- return;
- }
-#endif
+ case rvc_zero:
+ case rvc_inf:
+ case rvc_nan:
+ break;
- for (i = 2; i < NI; i++)
- *q++ = 0;
- return;
- }
-#endif
+ case rvc_normal:
+ if (r->exp <= 0)
+ get_zero (r, r->sign);
+ else if (r->exp < SIGNIFICAND_BITS)
+ clear_significand_below (r, SIGNIFICAND_BITS - r->exp);
+ break;
- /* clear high guard word */
- *q++ = 0;
- /* move in the significand */
- for (i = 0; i < NE - 1; i++)
- *q++ = *p--;
- /* clear low guard word */
- *q = 0;
+ default:
+ abort ();
+ }
}
-/* Move out exploded e-type number A, converting it to e type B. */
+/* Perform the binary or unary operation described by CODE.
+ For a unary operation, leave OP1 NULL. */
-static void
-emovo (a, b)
- const UEMUSHORT *a;
- UEMUSHORT *b;
+void
+real_arithmetic (r, icode, op0, op1)
+ REAL_VALUE_TYPE *r;
+ int icode;
+ const REAL_VALUE_TYPE *op0, *op1;
{
- const UEMUSHORT *p;
- UEMUSHORT *q;
- UEMUSHORT i;
- int j;
-
- p = a;
- q = b + (NE - 1); /* point to output exponent */
- /* combine sign and exponent */
- i = *p++;
- if (i)
- *q-- = *p++ | 0x8000;
- else
- *q-- = *p++;
-#ifdef INFINITY
- if (*(p - 1) == 0x7fff)
+ enum tree_code code = icode;
+
+ switch (code)
{
-#ifdef NANS
- if (eiisnan (a))
- {
- enan (b, eiisneg (a));
- return;
- }
-#endif
- einfin (b);
- return;
- }
-#endif
- /* skip over guard word */
- ++p;
- /* move the significand */
- for (j = 0; j < NE - 1; j++)
- *q-- = *p++;
-}
+ case PLUS_EXPR:
+ do_add (r, op0, op1, 0);
+ break;
-/* Clear out exploded e-type number XI. */
+ case MINUS_EXPR:
+ do_add (r, op0, op1, 1);
+ break;
-static void
-ecleaz (xi)
- UEMUSHORT *xi;
-{
- int i;
+ case MULT_EXPR:
+ do_multiply (r, op0, op1);
+ break;
- for (i = 0; i < NI; i++)
- *xi++ = 0;
-}
+ case RDIV_EXPR:
+ do_divide (r, op0, op1);
+ break;
-/* Clear out exploded e-type XI, but don't touch the sign. */
+ case MIN_EXPR:
+ if (op1->class == rvc_nan)
+ *r = *op1;
+ else if (do_compare (op0, op1, -1) < 0)
+ *r = *op0;
+ else
+ *r = *op1;
+ break;
-static void
-ecleazs (xi)
- UEMUSHORT *xi;
-{
- int i;
+ case MAX_EXPR:
+ if (op1->class == rvc_nan)
+ *r = *op1;
+ else if (do_compare (op0, op1, 1) < 0)
+ *r = *op1;
+ else
+ *r = *op0;
+ break;
- ++xi;
- for (i = 0; i < NI - 1; i++)
- *xi++ = 0;
-}
+ case NEGATE_EXPR:
+ *r = *op0;
+ r->sign ^= 1;
+ break;
-/* Move exploded e-type number from A to B. */
+ case ABS_EXPR:
+ *r = *op0;
+ r->sign = 0;
+ break;
-static void
-emovz (a, b)
- const UEMUSHORT *a;
- UEMUSHORT *b;
-{
- int i;
+ case FIX_TRUNC_EXPR:
+ do_fix_trunc (r, op0);
+ break;
- for (i = 0; i < NI - 1; i++)
- *b++ = *a++;
- /* clear low guard word */
- *b = 0;
+ default:
+ abort ();
+ }
}
-/* Generate exploded e-type NaN.
- The explicit pattern for this is maximum exponent and
- top two significant bits set. */
+/* Legacy. Similar, but return the result directly. */
-#ifdef NANS
-static void
-einan (x)
- UEMUSHORT x[];
+REAL_VALUE_TYPE
+real_arithmetic2 (icode, op0, op1)
+ int icode;
+ const REAL_VALUE_TYPE *op0, *op1;
{
-
- ecleaz (x);
- x[E] = 0x7fff;
- x[M + 1] = 0xc000;
+ REAL_VALUE_TYPE r;
+ real_arithmetic (&r, icode, op0, op1);
+ return r;
}
-#endif /* NANS */
-/* Return nonzero if exploded e-type X is a NaN. */
-
-#ifdef NANS
-static int
-eiisnan (x)
- const UEMUSHORT x[];
+bool
+real_compare (icode, op0, op1)
+ int icode;
+ const REAL_VALUE_TYPE *op0, *op1;
{
- int i;
+ enum tree_code code = icode;
- if ((x[E] & 0x7fff) == 0x7fff)
+ switch (code)
{
- for (i = M + 1; i < NI; i++)
- {
- if (x[i] != 0)
- return (1);
- }
+ case LT_EXPR:
+ return do_compare (op0, op1, 1) < 0;
+ case LE_EXPR:
+ return do_compare (op0, op1, 1) <= 0;
+ case GT_EXPR:
+ return do_compare (op0, op1, -1) > 0;
+ case GE_EXPR:
+ return do_compare (op0, op1, -1) >= 0;
+ case EQ_EXPR:
+ return do_compare (op0, op1, -1) == 0;
+ case NE_EXPR:
+ return do_compare (op0, op1, -1) != 0;
+ case UNORDERED_EXPR:
+ return op0->class == rvc_nan || op1->class == rvc_nan;
+ case ORDERED_EXPR:
+ return op0->class != rvc_nan && op1->class != rvc_nan;
+ case UNLT_EXPR:
+ return do_compare (op0, op1, -1) < 0;
+ case UNLE_EXPR:
+ return do_compare (op0, op1, -1) <= 0;
+ case UNGT_EXPR:
+ return do_compare (op0, op1, 1) > 0;
+ case UNGE_EXPR:
+ return do_compare (op0, op1, 1) >= 0;
+ case UNEQ_EXPR:
+ return do_compare (op0, op1, 0) == 0;
+
+ default:
+ abort ();
}
- return (0);
}
-#endif /* NANS */
-/* Return nonzero if sign of exploded e-type X is nonzero. */
+/* Return floor log2(R). */
-#ifdef NANS
-static int
-eiisneg (x)
- const UEMUSHORT x[];
-{
-
- return x[0] != 0;
+int
+real_exponent (r)
+ const REAL_VALUE_TYPE *r;
+{
+ switch (r->class)
+ {
+ case rvc_zero:
+ return 0;
+ case rvc_inf:
+ case rvc_nan:
+ return (unsigned int)-1 >> 1;
+ case rvc_normal:
+ return r->exp;
+ default:
+ abort ();
+ }
}
-#endif /* NANS */
-#if 0
-/* Fill exploded e-type X with infinity pattern.
- This has maximum exponent and significand all zeros. */
+/* R = OP0 * 2**EXP. */
-static void
-eiinfin (x)
- UEMUSHORT x[];
+void
+real_ldexp (r, op0, exp)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *op0;
+ int exp;
{
+ *r = *op0;
+ switch (r->class)
+ {
+ case rvc_zero:
+ case rvc_inf:
+ case rvc_nan:
+ break;
- ecleaz (x);
- x[E] = 0x7fff;
-}
-#endif /* 0 */
-
-/* Return nonzero if exploded e-type X is infinite. */
-
-#ifdef INFINITY
-static int
-eiisinf (x)
- const UEMUSHORT x[];
-{
+ case rvc_normal:
+ exp += op0->exp;
+ if (exp > MAX_EXP)
+ get_inf (r, r->sign);
+ else if (exp < -MAX_EXP)
+ get_zero (r, r->sign);
+ else
+ r->exp = exp;
+ break;
-#ifdef NANS
- if (eiisnan (x))
- return (0);
-#endif
- if ((x[E] & 0x7fff) == 0x7fff)
- return (1);
- return (0);
+ default:
+ abort ();
+ }
}
-#endif /* INFINITY */
-/* Compare significands of numbers in internal exploded e-type format.
- Guard words are included in the comparison.
+/* Determine whether a floating-point value X is infinite. */
- Returns +1 if a > b
- 0 if a == b
- -1 if a < b */
-
-static int
-ecmpm (a, b)
- const UEMUSHORT *a, *b;
+bool
+real_isinf (r)
+ const REAL_VALUE_TYPE *r;
{
- int i;
-
- a += M; /* skip up to significand area */
- b += M;
- for (i = M; i < NI; i++)
- {
- if (*a++ != *b++)
- goto difrnt;
- }
- return (0);
-
- difrnt:
- if (*(--a) > *(--b))
- return (1);
- else
- return (-1);
+ return (r->class == rvc_inf);
}
-/* Shift significand of exploded e-type X down by 1 bit. */
+/* Determine whether a floating-point value X is a NaN. */
-static void
-eshdn1 (x)
- UEMUSHORT *x;
+bool
+real_isnan (r)
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT bits;
- int i;
-
- x += M; /* point to significand area */
-
- bits = 0;
- for (i = M; i < NI; i++)
- {
- if (*x & 1)
- bits |= 1;
- *x >>= 1;
- if (bits & 2)
- *x |= 0x8000;
- bits <<= 1;
- ++x;
- }
+ return (r->class == rvc_nan);
}
-/* Shift significand of exploded e-type X up by 1 bit. */
+/* Determine whether a floating-point value X is negative. */
-static void
-eshup1 (x)
- UEMUSHORT *x;
+bool
+real_isneg (r)
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT bits;
- int i;
-
- x += NI - 1;
- bits = 0;
-
- for (i = M; i < NI; i++)
- {
- if (*x & 0x8000)
- bits |= 1;
- *x <<= 1;
- if (bits & 2)
- *x |= 1;
- bits <<= 1;
- --x;
- }
+ return r->sign;
}
+/* Determine whether a floating-point value X is minus zero. */
-/* Shift significand of exploded e-type X down by 8 bits. */
-
-static void
-eshdn8 (x)
- UEMUSHORT *x;
+bool
+real_isnegzero (r)
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT newbyt, oldbyt;
- int i;
-
- x += M;
- oldbyt = 0;
- for (i = M; i < NI; i++)
- {
- newbyt = *x << 8;
- *x >>= 8;
- *x |= oldbyt;
- oldbyt = newbyt;
- ++x;
- }
+ return r->sign && r->class == rvc_zero;
}
-/* Shift significand of exploded e-type X up by 8 bits. */
+/* Compare two floating-point objects for bitwise identity. */
-static void
-eshup8 (x)
- UEMUSHORT *x;
+extern bool
+real_identical (a, b)
+ const REAL_VALUE_TYPE *a, *b;
{
int i;
- UEMUSHORT newbyt, oldbyt;
- x += NI - 1;
- oldbyt = 0;
+ if (a->class != b->class)
+ return false;
+ if (a->sign != b->sign)
+ return false;
- for (i = M; i < NI; i++)
+ switch (a->class)
{
- newbyt = *x >> 8;
- *x <<= 8;
- *x |= oldbyt;
- oldbyt = newbyt;
- --x;
- }
-}
-
-/* Shift significand of exploded e-type X up by 16 bits. */
-
-static void
-eshup6 (x)
- UEMUSHORT *x;
-{
- int i;
- UEMUSHORT *p;
+ case rvc_zero:
+ case rvc_inf:
+ break;
- p = x + M;
- x += M + 1;
+ case rvc_normal:
+ if (a->exp != b->exp)
+ return false;
+ /* FALLTHRU */
+ case rvc_nan:
+ for (i = 0; i < SIGSZ; ++i)
+ if (a->sig[i] != b->sig[i])
+ return false;
+ break;
- for (i = M; i < NI - 1; i++)
- *p++ = *x++;
+ default:
+ abort ();
+ }
- *p = 0;
+ return true;
}
-/* Shift significand of exploded e-type X down by 16 bits. */
+/* Try to change R into its exact multiplicative inverse in machine
+ mode MODE. Return true if successful. */
-static void
-eshdn6 (x)
- UEMUSHORT *x;
+bool
+exact_real_inverse (mode, r)
+ enum machine_mode mode;
+ REAL_VALUE_TYPE *r;
{
+ const REAL_VALUE_TYPE *one = real_digit (1);
+ REAL_VALUE_TYPE u;
int i;
- UEMUSHORT *p;
-
- x += NI - 1;
- p = x + 1;
-
- for (i = M; i < NI - 1; i++)
- *(--p) = *(--x);
-
- *(--p) = 0;
+
+ if (r->class != rvc_normal)
+ return false;
+
+ /* Check for a power of two: all significand bits zero except the MSB. */
+ for (i = 0; i < SIGSZ-1; ++i)
+ if (r->sig[i] != 0)
+ return false;
+ if (r->sig[SIGSZ-1] != SIG_MSB)
+ return false;
+
+ /* Find the inverse and truncate to the required mode. */
+ do_divide (&u, one, r);
+ real_convert (&u, mode, &u);
+
+ /* The rounding may have overflowed. */
+ if (u.class != rvc_normal)
+ return false;
+ for (i = 0; i < SIGSZ-1; ++i)
+ if (u.sig[i] != 0)
+ return false;
+ if (u.sig[SIGSZ-1] != SIG_MSB)
+ return false;
+
+ *r = u;
+ return true;
}
+
+/* Render R as an integer. */
-/* Add significands of exploded e-type X and Y. X + Y replaces Y. */
-
-static void
-eaddm (x, y)
- const UEMUSHORT *x;
- UEMUSHORT *y;
-{
- unsigned EMULONG a;
- int i;
- unsigned int carry;
-
- x += NI - 1;
- y += NI - 1;
- carry = 0;
- for (i = M; i < NI; i++)
- {
- a = (unsigned EMULONG) (*x) + (unsigned EMULONG) (*y) + carry;
- if (a & 0x10000)
- carry = 1;
+HOST_WIDE_INT
+real_to_integer (r)
+ const REAL_VALUE_TYPE *r;
+{
+ unsigned HOST_WIDE_INT i;
+
+ switch (r->class)
+ {
+ case rvc_zero:
+ underflow:
+ return 0;
+
+ case rvc_inf:
+ case rvc_nan:
+ overflow:
+ i = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
+ if (!r->sign)
+ i--;
+ return i;
+
+ case rvc_normal:
+ if (r->exp <= 0)
+ goto underflow;
+ if (r->exp > HOST_BITS_PER_WIDE_INT)
+ goto overflow;
+
+ if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
+ i = r->sig[SIGSZ-1];
+ else if (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG)
+ {
+ i = r->sig[SIGSZ-1];
+ i = i << (HOST_BITS_PER_LONG - 1) << 1;
+ i |= r->sig[SIGSZ-2];
+ }
else
- carry = 0;
- *y = (UEMUSHORT) a;
- --x;
- --y;
- }
-}
+ abort ();
-/* Subtract significands of exploded e-type X and Y. Y - X replaces Y. */
+ i >>= HOST_BITS_PER_WIDE_INT - r->exp;
-static void
-esubm (x, y)
- const UEMUSHORT *x;
- UEMUSHORT *y;
-{
- unsigned EMULONG a;
- int i;
- unsigned int carry;
+ if (r->sign)
+ i = -i;
+ return i;
- x += NI - 1;
- y += NI - 1;
- carry = 0;
- for (i = M; i < NI; i++)
- {
- a = (unsigned EMULONG) (*y) - (unsigned EMULONG) (*x) - carry;
- if (a & 0x10000)
- carry = 1;
- else
- carry = 0;
- *y = (UEMUSHORT) a;
- --x;
- --y;
+ default:
+ abort ();
}
}
+/* Likewise, but to an integer pair, HI+LOW. */
-static UEMUSHORT equot[NI];
-
-
-#if 0
-/* Radix 2 shift-and-add versions of multiply and divide */
-
-
-/* Divide significands */
-
-int
-edivm (den, num)
- UEMUSHORT den[], num[];
+void
+real_to_integer2 (plow, phigh, r)
+ HOST_WIDE_INT *plow, *phigh;
+ const REAL_VALUE_TYPE *r;
{
- int i;
- UEMUSHORT *p, *q;
- UEMUSHORT j;
-
- p = &equot[0];
- *p++ = num[0];
- *p++ = num[1];
+ REAL_VALUE_TYPE t;
+ HOST_WIDE_INT low, high;
+ int exp;
- for (i = M; i < NI; i++)
+ switch (r->class)
{
- *p++ = 0;
- }
-
- /* Use faster compare and subtraction if denominator has only 15 bits of
- significance. */
+ case rvc_zero:
+ underflow:
+ low = high = 0;
+ break;
- p = &den[M + 2];
- if (*p++ == 0)
- {
- for (i = M + 3; i < NI; i++)
+ case rvc_inf:
+ case rvc_nan:
+ overflow:
+ high = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1);
+ if (r->sign)
+ low = 0;
+ else
{
- if (*p++ != 0)
- goto fulldiv;
+ high--;
+ low = -1;
}
- if ((den[M + 1] & 1) != 0)
- goto fulldiv;
- eshdn1 (num);
- eshdn1 (den);
+ break;
- p = &den[M + 1];
- q = &num[M + 1];
+ case rvc_normal:
+ exp = r->exp;
+ if (exp <= 0)
+ goto underflow;
+ if (exp > 2*HOST_BITS_PER_WIDE_INT)
+ goto overflow;
- for (i = 0; i < NBITS + 2; i++)
+ rshift_significand (&t, r, 2*HOST_BITS_PER_WIDE_INT - exp);
+ if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
{
- if (*p <= *q)
- {
- *q -= *p;
- j = 1;
- }
- else
- {
- j = 0;
- }
- eshup1 (equot);
- equot[NI - 2] |= j;
- eshup1 (num);
+ high = t.sig[SIGSZ-1];
+ low = t.sig[SIGSZ-2];
}
- goto divdon;
- }
-
- /* The number of quotient bits to calculate is NBITS + 1 scaling guard
- bit + 1 roundoff bit. */
-
- fulldiv:
-
- p = &equot[NI - 2];
- for (i = 0; i < NBITS + 2; i++)
- {
- if (ecmpm (den, num) <= 0)
+ else if (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG)
{
- esubm (den, num);
- j = 1; /* quotient bit = 1 */
+ high = t.sig[SIGSZ-1];
+ high = high << (HOST_BITS_PER_LONG - 1) << 1;
+ high |= t.sig[SIGSZ-2];
+
+ low = t.sig[SIGSZ-3];
+ low = low << (HOST_BITS_PER_LONG - 1) << 1;
+ low |= t.sig[SIGSZ-4];
}
else
- j = 0;
- eshup1 (equot);
- *p |= j;
- eshup1 (num);
- }
-
- divdon:
+ abort ();
- eshdn1 (equot);
- eshdn1 (equot);
+ if (r->sign)
+ {
+ if (low == 0)
+ high = -high;
+ else
+ low = -low, high = ~high;
+ }
+ break;
- /* test for nonzero remainder after roundoff bit */
- p = &num[M];
- j = 0;
- for (i = M; i < NI; i++)
- {
- j |= *p++;
+ default:
+ abort ();
}
- if (j)
- j = 1;
-
- for (i = 0; i < NI; i++)
- num[i] = equot[i];
- return ((int) j);
+ *plow = low;
+ *phigh = high;
}
+/* A subroutine of real_to_decimal. Compute the quotient and remainder
+ of NUM / DEN. Return the quotient and place the remainder in NUM.
+ It is expected that NUM / DEN are close enough that the quotient is
+ small. */
-/* Multiply significands */
-
-int
-emulm (a, b)
- UEMUSHORT a[], b[];
+static unsigned long
+rtd_divmod (num, den)
+ REAL_VALUE_TYPE *num, *den;
{
- UEMUSHORT *p, *q;
- int i, j, k;
-
- equot[0] = b[0];
- equot[1] = b[1];
- for (i = M; i < NI; i++)
- equot[i] = 0;
+ unsigned long q, msb;
+ int expn = num->exp, expd = den->exp;
- p = &a[NI - 2];
- k = NBITS;
- while (*p == 0) /* significand is not supposed to be zero */
- {
- eshdn6 (a);
- k -= 16;
- }
- if ((*p & 0xff) == 0)
- {
- eshdn8 (a);
- k -= 8;
- }
+ if (expn < expd)
+ return 0;
- q = &equot[NI - 1];
- j = 0;
- for (i = 0; i < k; i++)
+ q = msb = 0;
+ goto start;
+ do
{
- if (*p & 1)
- eaddm (b, equot);
- /* remember if there were any nonzero bits shifted out */
- if (*q & 1)
- j |= 1;
- eshdn1 (a);
- eshdn1 (equot);
+ msb = num->sig[SIGSZ-1] & SIG_MSB;
+ q <<= 1;
+ lshift_significand_1 (num, num);
+ start:
+ if (msb || cmp_significands (num, den) >= 0)
+ {
+ sub_significands (num, num, den, 0);
+ q |= 1;
+ }
}
+ while (--expn >= expd);
- for (i = 0; i < NI; i++)
- b[i] = equot[i];
+ num->exp = expd;
+ normalize (num);
- /* return flag for lost nonzero bits */
- return (j);
+ return q;
}
-#else
+/* Render R as a decimal floating point constant. Emit DIGITS significant
+ digits in the result, bounded by BUF_SIZE. If DIGITS is 0, choose the
+ maximum for the representation. If CROP_TRAILING_ZEROS, strip trailing
+ zeros. */
-/* Radix 65536 versions of multiply and divide. */
+#define M_LOG10_2 0.30102999566398119521
-/* Multiply significand of e-type number B
- by 16-bit quantity A, return e-type result to C. */
+void
+real_to_decimal (str, r_orig, buf_size, digits, crop_trailing_zeros)
+ char *str;
+ const REAL_VALUE_TYPE *r_orig;
+ size_t buf_size, digits;
+ int crop_trailing_zeros;
+{
+ const REAL_VALUE_TYPE *one, *ten;
+ REAL_VALUE_TYPE r, pten, u, v;
+ int dec_exp, cmp_one, digit;
+ size_t max_digits;
+ char *p, *first, *last;
+ bool sign;
+
+ r = *r_orig;
+ switch (r.class)
+ {
+ case rvc_zero:
+ strcpy (str, (r.sign ? "-0.0" : "0.0"));
+ return;
+ case rvc_normal:
+ break;
+ case rvc_inf:
+ strcpy (str, (r.sign ? "-Inf" : "+Inf"));
+ return;
+ case rvc_nan:
+ /* ??? Print the significand as well, if not canonical? */
+ strcpy (str, (r.sign ? "-NaN" : "+NaN"));
+ return;
+ default:
+ abort ();
+ }
-static void
-m16m (a, b, c)
- unsigned int a;
- const UEMUSHORT b[];
- UEMUSHORT c[];
-{
- UEMUSHORT *pp;
- unsigned EMULONG carry;
- const UEMUSHORT *ps;
- UEMUSHORT p[NI];
- unsigned EMULONG aa, m;
- int i;
+ /* Bound the number of digits printed by the size of the representation. */
+ max_digits = SIGNIFICAND_BITS * M_LOG10_2;
+ if (digits == 0 || digits > max_digits)
+ digits = max_digits;
- aa = a;
- pp = &p[NI-2];
- *pp++ = 0;
- *pp = 0;
- ps = &b[NI-1];
+ /* Estimate the decimal exponent, and compute the length of the string it
+ will print as. Be conservative and add one to account for possible
+ overflow or rounding error. */
+ dec_exp = r.exp * M_LOG10_2;
+ for (max_digits = 1; dec_exp ; max_digits++)
+ dec_exp /= 10;
- for (i=M+1; i<NI; i++)
- {
- if (*ps == 0)
- {
- --ps;
- --pp;
- *(pp-1) = 0;
- }
- else
- {
- m = (unsigned EMULONG) aa * *ps--;
- carry = (m & 0xffff) + *pp;
- *pp-- = (UEMUSHORT) carry;
- carry = (carry >> 16) + (m >> 16) + *pp;
- *pp = (UEMUSHORT) carry;
- *(pp-1) = carry >> 16;
- }
- }
- for (i=M; i<NI; i++)
- c[i] = p[i];
-}
+ /* Bound the number of digits printed by the size of the output buffer. */
+ max_digits = buf_size - 1 - 1 - 2 - max_digits - 1;
+ if (max_digits > buf_size)
+ abort ();
+ if (digits > max_digits)
+ digits = max_digits;
-/* Divide significands of exploded e-types NUM / DEN. Neither the
- numerator NUM nor the denominator DEN is permitted to have its high guard
- word nonzero. */
+ one = real_digit (1);
+ ten = ten_to_ptwo (0);
-static int
-edivm (den, num)
- const UEMUSHORT den[];
- UEMUSHORT num[];
-{
- int i;
- UEMUSHORT *p;
- unsigned EMULONG tnum;
- UEMUSHORT j, tdenm, tquot;
- UEMUSHORT tprod[NI+1];
+ sign = r.sign;
+ r.sign = 0;
- p = &equot[0];
- *p++ = num[0];
- *p++ = num[1];
+ dec_exp = 0;
+ pten = *one;
- for (i=M; i<NI; i++)
- {
- *p++ = 0;
- }
- eshdn1 (num);
- tdenm = den[M+1];
- for (i=M; i<NI; i++)
+ cmp_one = do_compare (&r, one, 0);
+ if (cmp_one > 0)
{
- /* Find trial quotient digit (the radix is 65536). */
- tnum = (((unsigned EMULONG) num[M]) << 16) + num[M+1];
+ int m;
- /* Do not execute the divide instruction if it will overflow. */
- if ((tdenm * (unsigned long) 0xffff) < tnum)
- tquot = 0xffff;
- else
- tquot = tnum / tdenm;
- /* Multiply denominator by trial quotient digit. */
- m16m ((unsigned int) tquot, den, tprod);
- /* The quotient digit may have been overestimated. */
- if (ecmpm (tprod, num) > 0)
- {
- tquot -= 1;
- esubm (den, tprod);
- if (ecmpm (tprod, num) > 0)
- {
- tquot -= 1;
- esubm (den, tprod);
- }
- }
- esubm (tprod, num);
- equot[i] = tquot;
- eshup6 (num);
- }
- /* test for nonzero remainder after roundoff bit */
- p = &num[M];
- j = 0;
- for (i=M; i<NI; i++)
- {
- j |= *p++;
- }
- if (j)
- j = 1;
+ /* Number is greater than one. Convert significand to an integer
+ and strip trailing decimal zeros. */
- for (i=0; i<NI; i++)
- num[i] = equot[i];
+ u = r;
+ u.exp = SIGNIFICAND_BITS - 1;
- return ((int) j);
-}
+ /* Largest M, such that 10**2**M fits within SIGNIFICAND_BITS. */
+ m = floor_log2 (max_digits);
-/* Multiply significands of exploded e-type A and B, result in B. */
+ /* Iterate over the bits of the possible powers of 10 that might
+ be present in U and eliminate them. That is, if we find that
+ 10**2**M divides U evenly, keep the division and increase
+ DEC_EXP by 2**M. */
+ do
+ {
+ REAL_VALUE_TYPE t;
-static int
-emulm (a, b)
- const UEMUSHORT a[];
- UEMUSHORT b[];
-{
- const UEMUSHORT *p;
- UEMUSHORT *q;
- UEMUSHORT pprod[NI];
- UEMUSHORT j;
- int i;
+ do_divide (&t, &u, ten_to_ptwo (m));
+ do_fix_trunc (&v, &t);
+ if (cmp_significands (&v, &t) == 0)
+ {
+ u = t;
+ dec_exp += 1 << m;
+ }
+ }
+ while (--m >= 0);
- equot[0] = b[0];
- equot[1] = b[1];
- for (i=M; i<NI; i++)
- equot[i] = 0;
+ /* Revert the scaling to integer that we performed earlier. */
+ u.exp += r.exp - (SIGNIFICAND_BITS - 1);
+ r = u;
- j = 0;
- p = &a[NI-1];
- q = &equot[NI-1];
- for (i=M+1; i<NI; i++)
- {
- if (*p == 0)
+ /* Find power of 10. Do this by dividing out 10**2**M when
+ this is larger than the current remainder. Fill PTEN with
+ the power of 10 that we compute. */
+ if (r.exp > 0)
{
- --p;
+ m = floor_log2 ((int)(r.exp * M_LOG10_2)) + 1;
+ do
+ {
+ const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m);
+ if (do_compare (&u, ptentwo, 0) >= 0)
+ {
+ do_divide (&u, &u, ptentwo);
+ do_multiply (&pten, &pten, ptentwo);
+ dec_exp += 1 << m;
+ }
+ }
+ while (--m >= 0);
}
else
- {
- m16m ((unsigned int) *p--, b, pprod);
- eaddm (pprod, equot);
- }
- j |= *q;
- eshdn6 (equot);
+ /* We managed to divide off enough tens in the above reduction
+ loop that we've now got a negative exponent. Fall into the
+ less-than-one code to compute the proper value for PTEN. */
+ cmp_one = -1;
}
+ if (cmp_one < 0)
+ {
+ int m;
- for (i=0; i<NI; i++)
- b[i] = equot[i];
+ /* Number is less than one. Pad significand with leading
+ decimal zeros. */
- /* return flag for lost nonzero bits */
- return ((int) j);
-}
-#endif
+ v = r;
+ while (1)
+ {
+ /* Stop if we'd shift bits off the bottom. */
+ if (v.sig[0] & 7)
+ break;
+ do_multiply (&u, &v, ten);
-/* Normalize and round off.
+ /* Stop if we're now >= 1. */
+ if (u.exp > 0)
+ break;
- The internal format number to be rounded is S.
- Input LOST is 0 if the value is exact. This is the so-called sticky bit.
+ v = u;
+ dec_exp -= 1;
+ }
+ r = v;
- Input SUBFLG indicates whether the number was obtained
- by a subtraction operation. In that case if LOST is nonzero
- then the number is slightly smaller than indicated.
+ /* Find power of 10. Do this by multiplying in P=10**2**M when
+ the current remainder is smaller than 1/P. Fill PTEN with the
+ power of 10 that we compute. */
+ m = floor_log2 ((int)(-r.exp * M_LOG10_2)) + 1;
+ do
+ {
+ const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m);
+ const REAL_VALUE_TYPE *ptenmtwo = ten_to_mptwo (m);
- Input EXP is the biased exponent, which may be negative.
- the exponent field of S is ignored but is replaced by
- EXP as adjusted by normalization and rounding.
+ if (do_compare (&v, ptenmtwo, 0) <= 0)
+ {
+ do_multiply (&v, &v, ptentwo);
+ do_multiply (&pten, &pten, ptentwo);
+ dec_exp -= 1 << m;
+ }
+ }
+ while (--m >= 0);
- Input RCNTRL is the rounding control. If it is nonzero, the
- returned value will be rounded to RNDPRC bits.
+ /* Invert the positive power of 10 that we've collected so far. */
+ do_divide (&pten, one, &pten);
+ }
- For future reference: In order for emdnorm to round off denormal
- significands at the right point, the input exponent must be
- adjusted to be the actual value it would have after conversion to
- the final floating point type. This adjustment has been
- implemented for all type conversions (etoe53, etc.) and decimal
- conversions, but not for the arithmetic functions (eadd, etc.).
- Data types having standard 15-bit exponents are not affected by
- this, but SFmode and DFmode are affected. For example, ediv with
- rndprc = 24 will not round correctly to 24-bit precision if the
- result is denormal. */
+ p = str;
+ if (sign)
+ *p++ = '-';
+ first = p++;
-static int rlast = -1;
-static int rw = 0;
-static UEMUSHORT rmsk = 0;
-static UEMUSHORT rmbit = 0;
-static UEMUSHORT rebit = 0;
-static int re = 0;
-static UEMUSHORT rbit[NI];
+ /* At this point, PTEN should contain the nearest power of 10 smaller
+ than R, such that this division produces the first digit.
-static void
-emdnorm (s, lost, subflg, exp, rcntrl)
- UEMUSHORT s[];
- int lost;
- int subflg;
- EMULONG exp;
- int rcntrl;
-{
- int i, j;
- UEMUSHORT r;
+ Using a divide-step primitive that returns the complete integral
+ remainder avoids the rounding error that would be produced if
+ we were to use do_divide here and then simply multiply by 10 for
+ each subsequent digit. */
- /* Normalize */
- j = enormlz (s);
+ digit = rtd_divmod (&r, &pten);
- /* a blank significand could mean either zero or infinity. */
-#ifndef INFINITY
- if (j > NBITS)
+ /* Be prepared for error in that division via underflow ... */
+ if (digit == 0 && cmp_significand_0 (&r))
{
- ecleazs (s);
- return;
+ /* Multiply by 10 and try again. */
+ do_multiply (&r, &r, ten);
+ digit = rtd_divmod (&r, &pten);
+ dec_exp -= 1;
+ if (digit == 0)
+ abort ();
}
-#endif
- exp -= j;
-#ifndef INFINITY
- if (exp >= 32767L)
- goto overf;
-#else
- if ((j > NBITS) && (exp < 32767))
+
+ /* ... or overflow. */
+ if (digit == 10)
{
- ecleazs (s);
- return;
+ *p++ = '1';
+ if (--digits > 0)
+ *p++ = '0';
+ dec_exp += 1;
}
-#endif
- if (exp < 0L)
+ else if (digit > 10)
+ abort ();
+ else
+ *p++ = digit + '0';
+
+ /* Generate subsequent digits. */
+ while (--digits > 0)
{
- if (exp > (EMULONG) (-NBITS - 1))
- {
- j = (int) exp;
- i = eshift (s, j);
- if (i)
- lost = 1;
- }
- else
- {
- ecleazs (s);
- return;
- }
+ do_multiply (&r, &r, ten);
+ digit = rtd_divmod (&r, &pten);
+ *p++ = digit + '0';
}
- /* Round off, unless told not to by rcntrl. */
- if (rcntrl == 0)
- goto mdfin;
- /* Set up rounding parameters if the control register changed. */
- if (rndprc != rlast)
- {
- ecleaz (rbit);
- switch (rndprc)
- {
- default:
- case NBITS:
- rw = NI - 1; /* low guard word */
- rmsk = 0xffff;
- rmbit = 0x8000;
- re = rw - 1;
- rebit = 1;
- break;
-
- case 113:
- rw = 10;
- rmsk = 0x7fff;
- rmbit = 0x4000;
- rebit = 0x8000;
- re = rw;
- break;
-
- case 64:
- rw = 7;
- rmsk = 0xffff;
- rmbit = 0x8000;
- re = rw - 1;
- rebit = 1;
- break;
-
- /* For DEC or IBM arithmetic */
- case 56:
- rw = 6;
- rmsk = 0xff;
- rmbit = 0x80;
- rebit = 0x100;
- re = rw;
- break;
+ last = p;
- case 53:
- rw = 6;
- rmsk = 0x7ff;
- rmbit = 0x0400;
- rebit = 0x800;
- re = rw;
- break;
+ /* Generate one more digit with which to do rounding. */
+ do_multiply (&r, &r, ten);
+ digit = rtd_divmod (&r, &pten);
- /* For C4x arithmetic */
- case 32:
- rw = 5;
- rmsk = 0xffff;
- rmbit = 0x8000;
- rebit = 1;
- re = rw - 1;
- break;
-
- case 24:
- rw = 4;
- rmsk = 0xff;
- rmbit = 0x80;
- rebit = 0x100;
- re = rw;
- break;
- }
- rbit[re] = rebit;
- rlast = rndprc;
- }
-
- /* Shift down 1 temporarily if the data structure has an implied
- most significant bit and the number is denormal.
- Intel long double denormals also lose one bit of precision. */
- if ((exp <= 0) && (rndprc != NBITS)
- && ((rndprc != 64) || ((rndprc == 64) && ! REAL_WORDS_BIG_ENDIAN)))
- {
- lost |= s[NI - 1] & 1;
- eshdn1 (s);
- }
- /* Clear out all bits below the rounding bit,
- remembering in r if any were nonzero. */
- r = s[rw] & rmsk;
- if (rndprc < NBITS)
+ /* Round the result. */
+ if (digit == 5)
{
- i = rw + 1;
- while (i < NI)
- {
- if (s[i])
- r |= 1;
- s[i] = 0;
- ++i;
- }
+ /* Round to nearest. If R is nonzero there are additional
+ nonzero digits to be extracted. */
+ if (cmp_significand_0 (&r))
+ digit++;
+ /* Round to even. */
+ else if ((p[-1] - '0') & 1)
+ digit++;
}
- s[rw] &= ~rmsk;
- if ((r & rmbit) != 0)
+ if (digit > 5)
{
-#ifndef C4X
- if (r == rmbit)
+ while (p > first)
{
- if (lost == 0)
- { /* round to even */
- if ((s[re] & rebit) == 0)
- goto mddone;
- }
+ digit = *--p;
+ if (digit == '9')
+ *p = '0';
else
{
- if (subflg != 0)
- goto mddone;
+ *p = digit + 1;
+ break;
}
}
-#endif
- eaddm (rbit, s);
- }
- mddone:
-/* Undo the temporary shift for denormal values. */
- if ((exp <= 0) && (rndprc != NBITS)
- && ((rndprc != 64) || ((rndprc == 64) && ! REAL_WORDS_BIG_ENDIAN)))
- {
- eshup1 (s);
- }
- if (s[2] != 0)
- { /* overflow on roundoff */
- eshdn1 (s);
- exp += 1;
- }
- mdfin:
- s[NI - 1] = 0;
- if (exp >= 32767L)
- {
-#ifndef INFINITY
- overf:
-#endif
-#ifdef INFINITY
- s[1] = 32767;
- for (i = 2; i < NI - 1; i++)
- s[i] = 0;
- if (extra_warnings)
- warning ("floating point overflow");
-#else
- s[1] = 32766;
- s[2] = 0;
- for (i = M + 1; i < NI - 1; i++)
- s[i] = 0xffff;
- s[NI - 1] = 0;
- if ((rndprc < 64) || (rndprc == 113))
+
+ /* Carry out of the first digit. This means we had all 9's and
+ now have all 0's. "Prepend" a 1 by overwriting the first 0. */
+ if (p == first)
{
- s[rw] &= ~rmsk;
- if (rndprc == 24)
- {
- s[5] = 0;
- s[6] = 0;
- }
+ first[1] = '1';
+ dec_exp++;
}
-#endif
- return;
}
- if (exp < 0)
- s[1] = 0;
- else
- s[1] = (UEMUSHORT) exp;
-}
+
+ /* Insert the decimal point. */
+ first[0] = first[1];
+ first[1] = '.';
-/* Subtract. C = B - A, all e type numbers. */
+ /* If requested, drop trailing zeros. Never crop past "1.0". */
+ if (crop_trailing_zeros)
+ while (last > first + 3 && last[-1] == '0')
+ last--;
-static int subflg = 0;
+ /* Append the exponent. */
+ sprintf (last, "e%+d", dec_exp);
+}
-static void
-esub (a, b, c)
- const UEMUSHORT *a, *b;
- UEMUSHORT *c;
+/* Render R as a hexadecimal floating point constant. Emit DIGITS
+ significant digits in the result, bounded by BUF_SIZE. If DIGITS is 0,
+ choose the maximum for the representation. If CROP_TRAILING_ZEROS,
+ strip trailing zeros. */
+
+void
+real_to_hexadecimal (str, r, buf_size, digits, crop_trailing_zeros)
+ char *str;
+ const REAL_VALUE_TYPE *r;
+ size_t buf_size, digits;
+ int crop_trailing_zeros;
{
+ int i, j, exp = r->exp;
+ char *p, *first;
+ char exp_buf[16];
+ size_t max_digits;
-#ifdef NANS
- if (eisnan (a))
- {
- emov (a, c);
- return;
- }
- if (eisnan (b))
+ switch (r->class)
{
- emov (b, c);
+ case rvc_zero:
+ exp = 0;
+ break;
+ case rvc_normal:
+ break;
+ case rvc_inf:
+ strcpy (str, (r->sign ? "-Inf" : "+Inf"));
return;
- }
-/* Infinity minus infinity is a NaN.
- Test for subtracting infinities of the same sign. */
- if (eisinf (a) && eisinf (b)
- && ((eisneg (a) ^ eisneg (b)) == 0))
- {
- mtherr ("esub", INVALID);
- enan (c, 0);
+ case rvc_nan:
+ /* ??? Print the significand as well, if not canonical? */
+ strcpy (str, (r->sign ? "-NaN" : "+NaN"));
return;
+ default:
+ abort ();
}
-#endif
- subflg = 1;
- eadd1 (a, b, c);
-}
-/* Add. C = A + B, all e type. */
+ if (digits == 0)
+ digits = SIGNIFICAND_BITS / 4;
-static void
-eadd (a, b, c)
- const UEMUSHORT *a, *b;
- UEMUSHORT *c;
-{
+ /* Bound the number of digits printed by the size of the output buffer. */
-#ifdef NANS
-/* NaN plus anything is a NaN. */
- if (eisnan (a))
- {
- emov (a, c);
- return;
- }
- if (eisnan (b))
- {
- emov (b, c);
- return;
- }
-/* Infinity minus infinity is a NaN.
- Test for adding infinities of opposite signs. */
- if (eisinf (a) && eisinf (b)
- && ((eisneg (a) ^ eisneg (b)) != 0))
- {
- mtherr ("esub", INVALID);
- enan (c, 0);
- return;
- }
-#endif
- subflg = 0;
- eadd1 (a, b, c);
+ sprintf (exp_buf, "p%+d", exp);
+ max_digits = buf_size - strlen (exp_buf) - r->sign - 4 - 1;
+ if (max_digits > buf_size)
+ abort ();
+ if (digits > max_digits)
+ digits = max_digits;
+
+ p = str;
+ if (r->sign)
+ *p++ = '-';
+ *p++ = '0';
+ *p++ = 'x';
+ *p++ = '0';
+ *p++ = '.';
+ first = p;
+
+ for (i = SIGSZ - 1; i >= 0; --i)
+ for (j = HOST_BITS_PER_LONG - 4; j >= 0; j -= 4)
+ {
+ *p++ = "0123456789abcdef"[(r->sig[i] >> j) & 15];
+ if (--digits == 0)
+ goto out;
+ }
+
+ out:
+ if (crop_trailing_zeros)
+ while (p > first + 1 && p[-1] == '0')
+ p--;
+
+ sprintf (p, "p%+d", exp);
}
-/* Arithmetic common to both addition and subtraction. */
+/* Initialize R from a decimal or hexadecimal string. The string is
+ assumed to have been syntax checked already. */
-static void
-eadd1 (a, b, c)
- const UEMUSHORT *a, *b;
- UEMUSHORT *c;
+void
+real_from_string (r, str)
+ REAL_VALUE_TYPE *r;
+ const char *str;
{
- UEMUSHORT ai[NI], bi[NI], ci[NI];
- int i, lost, j, k;
- EMULONG lt, lta, ltb;
+ int exp = 0;
+ bool sign = false;
-#ifdef INFINITY
- if (eisinf (a))
- {
- emov (a, c);
- if (subflg)
- eneg (c);
- return;
- }
- if (eisinf (b))
- {
- emov (b, c);
- return;
- }
-#endif
- emovi (a, ai);
- emovi (b, bi);
- if (subflg)
- ai[0] = ~ai[0];
-
- /* compare exponents */
- lta = ai[E];
- ltb = bi[E];
- lt = lta - ltb;
- if (lt > 0L)
- { /* put the larger number in bi */
- emovz (bi, ci);
- emovz (ai, bi);
- emovz (ci, ai);
- ltb = bi[E];
- lt = -lt;
- }
- lost = 0;
- if (lt != 0L)
+ get_zero (r, 0);
+
+ if (*str == '-')
{
- if (lt < (EMULONG) (-NBITS - 1))
- goto done; /* answer same as larger addend */
- k = (int) lt;
- lost = eshift (ai, k); /* shift the smaller number down */
+ sign = true;
+ str++;
}
- else
+ else if (*str == '+')
+ str++;
+
+ if (str[0] == '0' && str[1] == 'x')
{
- /* exponents were the same, so must compare significands */
- i = ecmpm (ai, bi);
- if (i == 0)
- { /* the numbers are identical in magnitude */
- /* if different signs, result is zero */
- if (ai[0] != bi[0])
+ /* Hexadecimal floating point. */
+ int pos = SIGNIFICAND_BITS - 4, d;
+
+ str += 2;
+
+ while (*str == '0')
+ str++;
+ while (1)
+ {
+ d = hex_value (*str);
+ if (d == _hex_bad)
+ break;
+ if (pos >= 0)
{
- eclear (c);
- return;
+ r->sig[pos / HOST_BITS_PER_LONG]
+ |= (unsigned long) d << (pos % HOST_BITS_PER_LONG);
+ pos -= 4;
}
- /* if same sign, result is double */
- /* double denormalized tiny number */
- if ((bi[E] == 0) && ((bi[3] & 0x8000) == 0))
+ exp += 4;
+ str++;
+ }
+ if (*str == '.')
+ {
+ str++;
+ if (pos == SIGNIFICAND_BITS - 4)
{
- eshup1 (bi);
- goto done;
+ while (*str == '0')
+ str++, exp -= 4;
}
- /* add 1 to exponent unless both are zero! */
- for (j = 1; j < NI - 1; j++)
+ while (1)
{
- if (bi[j] != 0)
+ d = hex_value (*str);
+ if (d == _hex_bad)
+ break;
+ if (pos >= 0)
{
- ltb += 1;
- if (ltb >= 0x7fff)
- {
- eclear (c);
- if (ai[0] != 0)
- eneg (c);
- einfin (c);
- return;
- }
- break;
+ r->sig[pos / HOST_BITS_PER_LONG]
+ |= (unsigned long) d << (pos % HOST_BITS_PER_LONG);
+ pos -= 4;
}
+ str++;
}
- bi[E] = (UEMUSHORT) ltb;
- goto done;
}
- if (i > 0)
- { /* put the larger number in bi */
- emovz (bi, ci);
- emovz (ai, bi);
- emovz (ci, ai);
- }
- }
- if (ai[0] == bi[0])
- {
- eaddm (ai, bi);
- subflg = 0;
- }
- else
- {
- esubm (ai, bi);
- subflg = 1;
- }
- emdnorm (bi, lost, subflg, ltb, 64);
+ if (*str == 'p' || *str == 'P')
+ {
+ bool exp_neg = false;
- done:
- emovo (bi, c);
-}
+ str++;
+ if (*str == '-')
+ {
+ exp_neg = true;
+ str++;
+ }
+ else if (*str == '+')
+ str++;
-/* Divide: C = B/A, all e type. */
+ d = 0;
+ while (ISDIGIT (*str))
+ {
+ d *= 10;
+ d += *str - '0';
+ if (d > MAX_EXP)
+ {
+ /* Overflowed the exponent. */
+ if (exp_neg)
+ goto underflow;
+ else
+ goto overflow;
+ }
+ str++;
+ }
+ if (exp_neg)
+ d = -d;
-static void
-ediv (a, b, c)
- const UEMUSHORT *a, *b;
- UEMUSHORT *c;
-{
- UEMUSHORT ai[NI], bi[NI];
- int i, sign;
- EMULONG lt, lta, ltb;
+ exp += d;
+ }
-/* IEEE says if result is not a NaN, the sign is "-" if and only if
- operands have opposite signs -- but flush -0 to 0 later if not IEEE. */
- sign = eisneg (a) ^ eisneg (b);
+ r->class = rvc_normal;
+ r->exp = exp;
-#ifdef NANS
-/* Return any NaN input. */
- if (eisnan (a))
- {
- emov (a, c);
- return;
- }
- if (eisnan (b))
- {
- emov (b, c);
- return;
- }
-/* Zero over zero, or infinity over infinity, is a NaN. */
- if (((ecmp (a, ezero) == 0) && (ecmp (b, ezero) == 0))
- || (eisinf (a) && eisinf (b)))
- {
- mtherr ("ediv", INVALID);
- enan (c, sign);
- return;
+ normalize (r);
}
-#endif
-/* Infinity over anything else is infinity. */
-#ifdef INFINITY
- if (eisinf (b))
- {
- einfin (c);
- goto divsign;
- }
-/* Anything else over infinity is zero. */
- if (eisinf (a))
+ else
{
- eclear (c);
- goto divsign;
- }
-#endif
- emovi (a, ai);
- emovi (b, bi);
- lta = ai[E];
- ltb = bi[E];
- if (bi[E] == 0)
- { /* See if numerator is zero. */
- for (i = 1; i < NI - 1; i++)
+ /* Decimal floating point. */
+ const REAL_VALUE_TYPE *ten = ten_to_ptwo (0);
+ int d;
+
+ while (*str == '0')
+ str++;
+ while (ISDIGIT (*str))
{
- if (bi[i] != 0)
- {
- ltb -= enormlz (bi);
- goto dnzro1;
- }
+ d = *str++ - '0';
+ do_multiply (r, r, ten);
+ if (d)
+ do_add (r, r, real_digit (d), 0);
}
- eclear (c);
- goto divsign;
- }
- dnzro1:
-
- if (ai[E] == 0)
- { /* possible divide by zero */
- for (i = 1; i < NI - 1; i++)
+ if (*str == '.')
{
- if (ai[i] != 0)
+ str++;
+ if (r->class == rvc_zero)
{
- lta -= enormlz (ai);
- goto dnzro2;
+ while (*str == '0')
+ str++, exp--;
+ }
+ while (ISDIGIT (*str))
+ {
+ d = *str++ - '0';
+ do_multiply (r, r, ten);
+ if (d)
+ do_add (r, r, real_digit (d), 0);
+ exp--;
}
}
-/* Divide by zero is not an invalid operation.
- It is a divide-by-zero operation! */
- einfin (c);
- mtherr ("ediv", SING);
- goto divsign;
- }
- dnzro2:
-
- i = edivm (ai, bi);
- /* calculate exponent */
- lt = ltb - lta + EXONE;
- emdnorm (bi, i, 0, lt, 64);
- emovo (bi, c);
-
- divsign:
-
- if (sign
-#ifndef IEEE
- && (ecmp (c, ezero) != 0)
-#endif
- )
- *(c+(NE-1)) |= 0x8000;
- else
- *(c+(NE-1)) &= ~0x8000;
-}
-/* Multiply e-types A and B, return e-type product C. */
-
-static void
-emul (a, b, c)
- const UEMUSHORT *a, *b;
- UEMUSHORT *c;
-{
- UEMUSHORT ai[NI], bi[NI];
- int i, j, sign;
- EMULONG lt, lta, ltb;
-
-/* IEEE says if result is not a NaN, the sign is "-" if and only if
- operands have opposite signs -- but flush -0 to 0 later if not IEEE. */
- sign = eisneg (a) ^ eisneg (b);
-
-#ifdef NANS
-/* NaN times anything is the same NaN. */
- if (eisnan (a))
- {
- emov (a, c);
- return;
- }
- if (eisnan (b))
- {
- emov (b, c);
- return;
- }
-/* Zero times infinity is a NaN. */
- if ((eisinf (a) && (ecmp (b, ezero) == 0))
- || (eisinf (b) && (ecmp (a, ezero) == 0)))
- {
- mtherr ("emul", INVALID);
- enan (c, sign);
- return;
- }
-#endif
-/* Infinity times anything else is infinity. */
-#ifdef INFINITY
- if (eisinf (a) || eisinf (b))
- {
- einfin (c);
- goto mulsign;
- }
-#endif
- emovi (a, ai);
- emovi (b, bi);
- lta = ai[E];
- ltb = bi[E];
- if (ai[E] == 0)
- {
- for (i = 1; i < NI - 1; i++)
+ if (*str == 'e' || *str == 'E')
{
- if (ai[i] != 0)
+ bool exp_neg = false;
+
+ str++;
+ if (*str == '-')
{
- lta -= enormlz (ai);
- goto mnzer1;
+ exp_neg = true;
+ str++;
}
- }
- eclear (c);
- goto mulsign;
- }
- mnzer1:
+ else if (*str == '+')
+ str++;
- if (bi[E] == 0)
- {
- for (i = 1; i < NI - 1; i++)
- {
- if (bi[i] != 0)
+ d = 0;
+ while (ISDIGIT (*str))
{
- ltb -= enormlz (bi);
- goto mnzer2;
+ d *= 10;
+ d += *str - '0';
+ if (d > MAX_EXP)
+ {
+ /* Overflowed the exponent. */
+ if (exp_neg)
+ goto underflow;
+ else
+ goto overflow;
+ }
+ str++;
}
+ if (exp_neg)
+ d = -d;
+ exp += d;
}
- eclear (c);
- goto mulsign;
+
+ if (exp)
+ times_pten (r, exp);
}
- mnzer2:
- /* Multiply significands */
- j = emulm (ai, bi);
- /* calculate exponent */
- lt = lta + ltb - (EXONE - 1);
- emdnorm (bi, j, 0, lt, 64);
- emovo (bi, c);
+ r->sign = sign;
+ return;
- mulsign:
+ underflow:
+ get_zero (r, sign);
+ return;
- if (sign
-#ifndef IEEE
- && (ecmp (c, ezero) != 0)
-#endif
- )
- *(c+(NE-1)) |= 0x8000;
- else
- *(c+(NE-1)) &= ~0x8000;
+ overflow:
+ get_inf (r, sign);
+ return;
}
-/* Convert double precision PE to e-type Y. */
+/* Legacy. Similar, but return the result directly. */
-static void
-e53toe (pe, y)
- const UEMUSHORT *pe;
- UEMUSHORT *y;
+REAL_VALUE_TYPE
+real_from_string2 (s, mode)
+ const char *s;
+ enum machine_mode mode;
{
-#ifdef DEC
-
- dectoe (pe, y);
-
-#else
-#ifdef IBM
-
- ibmtoe (pe, y, DFmode);
-
-#else
-#ifdef C4X
-
- c4xtoe (pe, y, HFmode);
-
-#else
- UEMUSHORT r;
- const UEMUSHORT *e;
- UEMUSHORT *p;
- UEMUSHORT yy[NI];
- int denorm, k;
-
- e = pe;
- denorm = 0; /* flag if denormalized number */
- ecleaz (yy);
- if (! REAL_WORDS_BIG_ENDIAN)
- e += 3;
- r = *e;
- yy[0] = 0;
- if (r & 0x8000)
- yy[0] = 0xffff;
- yy[M] = (r & 0x0f) | 0x10;
- r &= ~0x800f; /* strip sign and 4 significand bits */
-#ifdef INFINITY
- if (r == 0x7ff0)
- {
-#ifdef NANS
- if (! REAL_WORDS_BIG_ENDIAN)
- {
- if (((pe[3] & 0xf) != 0) || (pe[2] != 0)
- || (pe[1] != 0) || (pe[0] != 0))
- {
- enan (y, yy[0] != 0);
- return;
- }
- }
- else
- {
- if (((pe[0] & 0xf) != 0) || (pe[1] != 0)
- || (pe[2] != 0) || (pe[3] != 0))
- {
- enan (y, yy[0] != 0);
- return;
- }
- }
-#endif /* NANS */
- eclear (y);
- einfin (y);
- if (yy[0])
- eneg (y);
- return;
- }
-#endif /* INFINITY */
- r >>= 4;
- /* If zero exponent, then the significand is denormalized.
- So take back the understood high significand bit. */
+ REAL_VALUE_TYPE r;
- if (r == 0)
- {
- denorm = 1;
- yy[M] &= ~0x10;
- }
- r += EXONE - 01777;
- yy[E] = r;
- p = &yy[M + 1];
-#ifdef IEEE
- if (! REAL_WORDS_BIG_ENDIAN)
- {
- *p++ = *(--e);
- *p++ = *(--e);
- *p++ = *(--e);
- }
- else
- {
- ++e;
- *p++ = *e++;
- *p++ = *e++;
- *p++ = *e++;
- }
-#endif
- eshift (yy, -5);
- if (denorm)
- {
- /* If zero exponent, then normalize the significand. */
- if ((k = enormlz (yy)) > NBITS)
- ecleazs (yy);
- else
- yy[E] -= (UEMUSHORT) (k - 1);
- }
- emovo (yy, y);
-#endif /* not C4X */
-#endif /* not IBM */
-#endif /* not DEC */
+ real_from_string (&r, s);
+ if (mode != VOIDmode)
+ real_convert (&r, mode, &r);
+
+ return r;
}
-/* Convert double extended precision float PE to e type Y. */
+/* Initialize R from the integer pair HIGH+LOW. */
-static void
-e64toe (pe, y)
- const UEMUSHORT *pe;
- UEMUSHORT *y;
+void
+real_from_integer (r, mode, low, high, unsigned_p)
+ REAL_VALUE_TYPE *r;
+ enum machine_mode mode;
+ unsigned HOST_WIDE_INT low;
+ HOST_WIDE_INT high;
+ int unsigned_p;
{
- UEMUSHORT yy[NI];
- const UEMUSHORT *e;
- UEMUSHORT *p, *q;
- int i;
-
- e = pe;
- p = yy;
- for (i = 0; i < NE - 5; i++)
- *p++ = 0;
-/* This precision is not ordinarily supported on DEC or IBM. */
-#ifdef DEC
- for (i = 0; i < 5; i++)
- *p++ = *e++;
-#endif
-#ifdef IBM
- p = &yy[0] + (NE - 1);
- *p-- = *e++;
- ++e;
- for (i = 0; i < 5; i++)
- *p-- = *e++;
-#endif
-#ifdef IEEE
- if (! REAL_WORDS_BIG_ENDIAN)
+ if (low == 0 && high == 0)
+ get_zero (r, 0);
+ else
{
- for (i = 0; i < 5; i++)
- *p++ = *e++;
+ r->class = rvc_normal;
+ r->sign = high < 0 && !unsigned_p;
+ r->exp = 2 * HOST_BITS_PER_WIDE_INT;
- /* For denormal long double Intel format, shift significand up one
- -- but only if the top significand bit is zero. A top bit of 1
- is "pseudodenormal" when the exponent is zero. */
- if ((yy[NE-1] & 0x7fff) == 0 && (yy[NE-2] & 0x8000) == 0)
+ if (r->sign)
{
- UEMUSHORT temp[NI];
-
- emovi (yy, temp);
- eshup1 (temp);
- emovo (temp,y);
- return;
+ high = ~high;
+ if (low == 0)
+ high += 1;
+ else
+ low = -low;
}
- }
- else
- {
- p = &yy[0] + (NE - 1);
-#ifdef ARM_EXTENDED_IEEE_FORMAT
- /* For ARMs, the exponent is in the lowest 15 bits of the word. */
- *p-- = (e[0] & 0x8000) | (e[1] & 0x7ffff);
- e += 2;
-#else
- *p-- = *e++;
- ++e;
-#endif
- for (i = 0; i < 4; i++)
- *p-- = *e++;
- }
-#endif
-#ifdef INFINITY
- /* Point to the exponent field and check max exponent cases. */
- p = &yy[NE - 1];
- if ((*p & 0x7fff) == 0x7fff)
- {
-#ifdef NANS
- if (! REAL_WORDS_BIG_ENDIAN)
+
+ if (HOST_BITS_PER_LONG == HOST_BITS_PER_WIDE_INT)
{
- for (i = 0; i < 4; i++)
- {
- if ((i != 3 && pe[i] != 0)
- /* Anything but 0x8000 here, including 0, is a NaN. */
- || (i == 3 && pe[i] != 0x8000))
- {
- enan (y, (*p & 0x8000) != 0);
- return;
- }
- }
+ r->sig[SIGSZ-1] = high;
+ r->sig[SIGSZ-2] = low;
+ memset (r->sig, 0, sizeof(long)*(SIGSZ-2));
}
- else
+ else if (HOST_BITS_PER_LONG*2 == HOST_BITS_PER_WIDE_INT)
{
-#ifdef ARM_EXTENDED_IEEE_FORMAT
- for (i = 2; i <= 5; i++)
- {
- if (pe[i] != 0)
- {
- enan (y, (*p & 0x8000) != 0);
- return;
- }
- }
-#else /* not ARM */
- /* In Motorola extended precision format, the most significant
- bit of an infinity mantissa could be either 1 or 0. It is
- the lower order bits that tell whether the value is a NaN. */
- if ((pe[2] & 0x7fff) != 0)
- goto bigend_nan;
-
- for (i = 3; i <= 5; i++)
- {
- if (pe[i] != 0)
- {
-bigend_nan:
- enan (y, (*p & 0x8000) != 0);
- return;
- }
- }
-#endif /* not ARM */
+ r->sig[SIGSZ-1] = high >> (HOST_BITS_PER_LONG - 1) >> 1;
+ r->sig[SIGSZ-2] = high;
+ r->sig[SIGSZ-3] = low >> (HOST_BITS_PER_LONG - 1) >> 1;
+ r->sig[SIGSZ-4] = low;
+ if (SIGSZ > 4)
+ memset (r->sig, 0, sizeof(long)*(SIGSZ-4));
}
-#endif /* NANS */
- eclear (y);
- einfin (y);
- if (*p & 0x8000)
- eneg (y);
- return;
+ else
+ abort ();
+
+ normalize (r);
}
-#endif /* INFINITY */
- p = yy;
- q = y;
- for (i = 0; i < NE; i++)
- *q++ = *p++;
+
+ if (mode != VOIDmode)
+ real_convert (r, mode, r);
}
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
-/* Convert 128-bit long double precision float PE to e type Y. */
+/* Returns 10**2**N. */
-static void
-e113toe (pe, y)
- const UEMUSHORT *pe;
- UEMUSHORT *y;
+static const REAL_VALUE_TYPE *
+ten_to_ptwo (n)
+ int n;
{
- UEMUSHORT r;
- const UEMUSHORT *e;
- UEMUSHORT *p;
- UEMUSHORT yy[NI];
- int denorm, i;
-
- e = pe;
- denorm = 0;
- ecleaz (yy);
-#ifdef IEEE
- if (! REAL_WORDS_BIG_ENDIAN)
- e += 7;
-#endif
- r = *e;
- yy[0] = 0;
- if (r & 0x8000)
- yy[0] = 0xffff;
- r &= 0x7fff;
-#ifdef INFINITY
- if (r == 0x7fff)
+ static REAL_VALUE_TYPE tens[EXP_BITS];
+
+ if (n < 0 || n >= EXP_BITS)
+ abort ();
+
+ if (tens[n].class == rvc_zero)
{
-#ifdef NANS
- if (! REAL_WORDS_BIG_ENDIAN)
+ if (n < (HOST_BITS_PER_WIDE_INT == 64 ? 5 : 4))
{
- for (i = 0; i < 7; i++)
- {
- if (pe[i] != 0)
- {
- enan (y, yy[0] != 0);
- return;
- }
- }
+ HOST_WIDE_INT t = 10;
+ int i;
+
+ for (i = 0; i < n; ++i)
+ t *= t;
+
+ real_from_integer (&tens[n], VOIDmode, t, 0, 1);
}
else
{
- for (i = 1; i < 8; i++)
- {
- if (pe[i] != 0)
- {
- enan (y, yy[0] != 0);
- return;
- }
- }
+ const REAL_VALUE_TYPE *t = ten_to_ptwo (n - 1);
+ do_multiply (&tens[n], t, t);
}
-#endif /* NANS */
- eclear (y);
- einfin (y);
- if (yy[0])
- eneg (y);
- return;
}
-#endif /* INFINITY */
- yy[E] = r;
- p = &yy[M + 1];
-#ifdef IEEE
- if (! REAL_WORDS_BIG_ENDIAN)
- {
- for (i = 0; i < 7; i++)
- *p++ = *(--e);
- }
- else
- {
- ++e;
- for (i = 0; i < 7; i++)
- *p++ = *e++;
- }
-#endif
-/* If denormal, remove the implied bit; else shift down 1. */
- if (r == 0)
- {
- yy[M] = 0;
- }
- else
- {
- yy[M] = 1;
- eshift (yy, -1);
- }
- emovo (yy, y);
+
+ return &tens[n];
}
-#endif
-/* Convert single precision float PE to e type Y. */
+/* Returns 10**(-2**N). */
-static void
-e24toe (pe, y)
- const UEMUSHORT *pe;
- UEMUSHORT *y;
+static const REAL_VALUE_TYPE *
+ten_to_mptwo (n)
+ int n;
{
-#ifdef IBM
-
- ibmtoe (pe, y, SFmode);
-
-#else
+ static REAL_VALUE_TYPE tens[EXP_BITS];
-#ifdef C4X
-
- c4xtoe (pe, y, QFmode);
-
-#else
+ if (n < 0 || n >= EXP_BITS)
+ abort ();
- UEMUSHORT r;
- const UEMUSHORT *e;
- UEMUSHORT *p;
- UEMUSHORT yy[NI];
- int denorm, k;
+ if (tens[n].class == rvc_zero)
+ do_divide (&tens[n], real_digit (1), ten_to_ptwo (n));
- e = pe;
- denorm = 0; /* flag if denormalized number */
- ecleaz (yy);
-#ifdef IEEE
- if (! REAL_WORDS_BIG_ENDIAN)
- e += 1;
-#endif
-#ifdef DEC
- e += 1;
-#endif
- r = *e;
- yy[0] = 0;
- if (r & 0x8000)
- yy[0] = 0xffff;
- yy[M] = (r & 0x7f) | 0200;
- r &= ~0x807f; /* strip sign and 7 significand bits */
-#ifdef INFINITY
- if (r == 0x7f80)
- {
-#ifdef NANS
- if (REAL_WORDS_BIG_ENDIAN)
- {
- if (((pe[0] & 0x7f) != 0) || (pe[1] != 0))
- {
- enan (y, yy[0] != 0);
- return;
- }
- }
- else
- {
- if (((pe[1] & 0x7f) != 0) || (pe[0] != 0))
- {
- enan (y, yy[0] != 0);
- return;
- }
- }
-#endif /* NANS */
- eclear (y);
- einfin (y);
- if (yy[0])
- eneg (y);
- return;
- }
-#endif /* INFINITY */
- r >>= 7;
- /* If zero exponent, then the significand is denormalized.
- So take back the understood high significand bit. */
- if (r == 0)
- {
- denorm = 1;
- yy[M] &= ~0200;
- }
- r += EXONE - 0177;
- yy[E] = r;
- p = &yy[M + 1];
-#ifdef DEC
- *p++ = *(--e);
-#endif
-#ifdef IEEE
- if (! REAL_WORDS_BIG_ENDIAN)
- *p++ = *(--e);
- else
- {
- ++e;
- *p++ = *e++;
- }
-#endif
- eshift (yy, -8);
- if (denorm)
- { /* if zero exponent, then normalize the significand */
- if ((k = enormlz (yy)) > NBITS)
- ecleazs (yy);
- else
- yy[E] -= (UEMUSHORT) (k - 1);
- }
- emovo (yy, y);
-#endif /* not C4X */
-#endif /* not IBM */
+ return &tens[n];
}
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
-/* Convert e-type X to IEEE 128-bit long double format E. */
+/* Returns N. */
-static void
-etoe113 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
+static const REAL_VALUE_TYPE *
+real_digit (n)
+ int n;
{
- UEMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
+ static REAL_VALUE_TYPE num[10];
-#ifdef NANS
- if (eisnan (x))
- {
- make_nan (e, eisneg (x), TFmode);
- return;
- }
-#endif
- emovi (x, xi);
- exp = (EMULONG) xi[E];
-#ifdef INFINITY
- if (eisinf (x))
- goto nonorm;
-#endif
- /* round off to nearest or even */
- rndsav = rndprc;
- rndprc = 113;
- emdnorm (xi, 0, 0, exp, 64);
- rndprc = rndsav;
-#ifdef INFINITY
- nonorm:
-#endif
- toe113 (xi, e);
+ if (n < 0 || n > 9)
+ abort ();
+
+ if (n > 0 && num[n].class == rvc_zero)
+ real_from_integer (&num[n], VOIDmode, n, 0, 1);
+
+ return &num[n];
}
-/* Convert exploded e-type X, that has already been rounded to
- 113-bit precision, to IEEE 128-bit long double format Y. */
+/* Multiply R by 10**EXP. */
static void
-toe113 (a, b)
- UEMUSHORT *a, *b;
+times_pten (r, exp)
+ REAL_VALUE_TYPE *r;
+ int exp;
{
- UEMUSHORT *p, *q;
- UEMUSHORT i;
+ REAL_VALUE_TYPE pten, *rr;
+ bool negative = (exp < 0);
+ int i;
-#ifdef NANS
- if (eiisnan (a))
+ if (negative)
{
- make_nan (b, eiisneg (a), TFmode);
- return;
+ exp = -exp;
+ pten = *real_digit (1);
+ rr = &pten;
}
-#endif
- p = a;
- if (REAL_WORDS_BIG_ENDIAN)
- q = b;
else
- q = b + 7; /* point to output exponent */
+ rr = r;
- /* If not denormal, delete the implied bit. */
- if (a[E] != 0)
- {
- eshup1 (a);
- }
- /* combine sign and exponent */
- i = *p++;
- if (REAL_WORDS_BIG_ENDIAN)
- {
- if (i)
- *q++ = *p++ | 0x8000;
- else
- *q++ = *p++;
- }
- else
- {
- if (i)
- *q-- = *p++ | 0x8000;
- else
- *q-- = *p++;
- }
- /* skip over guard word */
- ++p;
- /* move the significand */
- if (REAL_WORDS_BIG_ENDIAN)
- {
- for (i = 0; i < 7; i++)
- *q++ = *p++;
- }
- else
- {
- for (i = 0; i < 7; i++)
- *q-- = *p++;
- }
+ for (i = 0; exp > 0; ++i, exp >>= 1)
+ if (exp & 1)
+ do_multiply (rr, rr, ten_to_ptwo (i));
+
+ if (negative)
+ do_divide (r, r, &pten);
}
-#endif
-/* Convert e-type X to IEEE double extended format E. */
+/* Fills R with +Inf. */
-static void
-etoe64 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
+void
+real_inf (r)
+ REAL_VALUE_TYPE *r;
{
- UEMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
-
-#ifdef NANS
- if (eisnan (x))
- {
- make_nan (e, eisneg (x), XFmode);
- return;
- }
-#endif
- emovi (x, xi);
- /* adjust exponent for offset */
- exp = (EMULONG) xi[E];
-#ifdef INFINITY
- if (eisinf (x))
- goto nonorm;
-#endif
- /* round off to nearest or even */
- rndsav = rndprc;
- rndprc = 64;
- emdnorm (xi, 0, 0, exp, 64);
- rndprc = rndsav;
-#ifdef INFINITY
- nonorm:
-#endif
- toe64 (xi, e);
+ get_inf (r, 0);
}
-/* Convert exploded e-type X, that has already been rounded to
- 64-bit precision, to IEEE double extended format Y. */
+/* Fills R with a NaN whose significand is described by STR. If QUIET,
+ we force a QNaN, else we force an SNaN. The string, if not empty,
+ is parsed as a number and placed in the significand. Return true
+ if the string was successfully parsed. */
-static void
-toe64 (a, b)
- UEMUSHORT *a, *b;
+bool
+real_nan (r, str, quiet, mode)
+ REAL_VALUE_TYPE *r;
+ const char *str;
+ int quiet;
+ enum machine_mode mode;
{
- UEMUSHORT *p, *q;
- UEMUSHORT i;
+ const struct real_format *fmt;
-#ifdef NANS
- if (eiisnan (a))
- {
- make_nan (b, eiisneg (a), XFmode);
- return;
- }
-#endif
- /* Shift denormal long double Intel format significand down one bit. */
- if ((a[E] == 0) && ! REAL_WORDS_BIG_ENDIAN)
- eshdn1 (a);
- p = a;
-#ifdef IBM
- q = b;
-#endif
-#ifdef DEC
- q = b + 4;
-#endif
-#ifdef IEEE
- if (REAL_WORDS_BIG_ENDIAN)
- q = b;
- else
- {
- q = b + 4; /* point to output exponent */
- /* Clear the last two bytes of 12-byte Intel format. q is pointing
- into an array of size 6 (e.g. x[NE]), so the last two bytes are
- always there, and there are never more bytes, even when we are using
- INTEL_EXTENDED_IEEE_FORMAT. */
- *(q+1) = 0;
- }
-#endif
+ fmt = real_format_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ abort ();
- /* combine sign and exponent */
- i = *p++;
-#ifdef IBM
- if (i)
- *q++ = *p++ | 0x8000;
- else
- *q++ = *p++;
- *q++ = 0;
-#endif
-#ifdef DEC
- if (i)
- *q-- = *p++ | 0x8000;
- else
- *q-- = *p++;
-#endif
-#ifdef IEEE
- if (REAL_WORDS_BIG_ENDIAN)
+ if (*str == 0)
{
-#ifdef ARM_EXTENDED_IEEE_FORMAT
- /* The exponent is in the lowest 15 bits of the first word. */
- *q++ = i ? 0x8000 : 0;
- *q++ = *p++;
-#else
- if (i)
- *q++ = *p++ | 0x8000;
+ if (quiet)
+ get_canonical_qnan (r, 0);
else
- *q++ = *p++;
- *q++ = 0;
-#endif
+ get_canonical_snan (r, 0);
}
else
{
- if (i)
- *q-- = *p++ | 0x8000;
- else
- *q-- = *p++;
- }
-#endif
- /* skip over guard word */
- ++p;
- /* move the significand */
-#ifdef IBM
- for (i = 0; i < 4; i++)
- *q++ = *p++;
-#endif
-#ifdef DEC
- for (i = 0; i < 4; i++)
- *q-- = *p++;
-#endif
-#ifdef IEEE
- if (REAL_WORDS_BIG_ENDIAN)
- {
- for (i = 0; i < 4; i++)
- *q++ = *p++;
- }
- else
- {
-#ifdef INFINITY
- if (eiisinf (a))
+ int base = 10, d;
+ bool neg = false;
+
+ memset (r, 0, sizeof (*r));
+ r->class = rvc_nan;
+
+ /* Parse akin to strtol into the significand of R. */
+
+ while (ISSPACE (*str))
+ str++;
+ if (*str == '-')
+ str++, neg = true;
+ else if (*str == '+')
+ str++;
+ if (*str == '0')
{
- /* Intel long double infinity significand. */
- *q-- = 0x8000;
- *q-- = 0;
- *q-- = 0;
- *q = 0;
- return;
+ if (*++str == 'x')
+ str++, base = 16;
+ else
+ base = 8;
}
-#endif
- for (i = 0; i < 4; i++)
- *q-- = *p++;
- }
-#endif
-}
-/* e type to double precision. */
+ while ((d = hex_value (*str)) < base)
+ {
+ REAL_VALUE_TYPE u;
-#ifdef DEC
-/* Convert e-type X to DEC-format double E. */
+ switch (base)
+ {
+ case 8:
+ lshift_significand (r, r, 3);
+ break;
+ case 16:
+ lshift_significand (r, r, 4);
+ break;
+ case 10:
+ lshift_significand_1 (&u, r);
+ lshift_significand (r, r, 3);
+ add_significands (r, r, &u);
+ break;
+ default:
+ abort ();
+ }
-static void
-etoe53 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
-{
- etodec (x, e); /* see etodec.c */
-}
+ get_zero (&u, 0);
+ u.sig[0] = d;
+ add_significands (r, r, &u);
-/* Convert exploded e-type X, that has already been rounded to
- 56-bit double precision, to DEC double Y. */
+ str++;
+ }
-static void
-toe53 (x, y)
- UEMUSHORT *x, *y;
-{
- todec (x, y);
-}
+ /* Must have consumed the entire string for success. */
+ if (*str != 0)
+ return false;
-#else
-#ifdef IBM
-/* Convert e-type X to IBM 370-format double E. */
+ /* Shift the significand into place such that the bits
+ are in the most significant bits for the format. */
+ lshift_significand (r, r, SIGNIFICAND_BITS - fmt->p);
-static void
-etoe53 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
-{
- etoibm (x, e, DFmode);
-}
+ /* Our MSB is always unset for NaNs. */
+ r->sig[SIGSZ-1] &= ~SIG_MSB;
-/* Convert exploded e-type X, that has already been rounded to
- 56-bit precision, to IBM 370 double Y. */
+ /* Force quiet or signalling NaN. */
+ if (quiet)
+ r->sig[SIGSZ-1] |= SIG_MSB >> 1;
+ else
+ r->sig[SIGSZ-1] &= ~(SIG_MSB >> 1);
-static void
-toe53 (x, y)
- UEMUSHORT *x, *y;
-{
- toibm (x, y, DFmode);
-}
+ /* Force at least one bit of the significand set. */
+ for (d = 0; d < SIGSZ; ++d)
+ if (r->sig[d])
+ break;
+ if (d == SIGSZ)
+ r->sig[SIGSZ-1] |= SIG_MSB >> 2;
-#else /* it's neither DEC nor IBM */
-#ifdef C4X
-/* Convert e-type X to C4X-format long double E. */
+ /* Our intermediate format forces QNaNs to have MSB-1 set.
+ If the target format has QNaNs with the top bit unset,
+ mirror the output routines and invert the top two bits. */
+ if (!fmt->qnan_msb_set)
+ r->sig[SIGSZ-1] ^= (SIG_MSB >> 1) | (SIG_MSB >> 2);
+ }
-static void
-etoe53 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
-{
- etoc4x (x, e, HFmode);
+ return true;
}
-/* Convert exploded e-type X, that has already been rounded to
- 56-bit precision, to IBM 370 double Y. */
+/* Fills R with 2**N. */
-static void
-toe53 (x, y)
- UEMUSHORT *x, *y;
+void
+real_2expN (r, n)
+ REAL_VALUE_TYPE *r;
+ int n;
{
- toc4x (x, y, HFmode);
-}
+ memset (r, 0, sizeof (*r));
-#else /* it's neither DEC nor IBM nor C4X */
-
-/* Convert e-type X to IEEE double E. */
+ n++;
+ if (n > MAX_EXP)
+ r->class = rvc_inf;
+ else if (n < -MAX_EXP)
+ ;
+ else
+ {
+ r->class = rvc_normal;
+ r->exp = n;
+ r->sig[SIGSZ-1] = SIG_MSB;
+ }
+}
+
static void
-etoe53 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
+round_for_format (fmt, r)
+ const struct real_format *fmt;
+ REAL_VALUE_TYPE *r;
{
- UEMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
+ int p2, np2, i, w;
+ unsigned long sticky;
+ bool guard, lsb;
+ int emin2m1, emax2;
-#ifdef NANS
- if (eisnan (x))
+ p2 = fmt->p * fmt->log2_b;
+ emin2m1 = (fmt->emin - 1) * fmt->log2_b;
+ emax2 = fmt->emax * fmt->log2_b;
+
+ np2 = SIGNIFICAND_BITS - p2;
+ switch (r->class)
{
- make_nan (e, eisneg (x), DFmode);
+ underflow:
+ get_zero (r, r->sign);
+ case rvc_zero:
+ if (!fmt->has_signed_zero)
+ r->sign = 0;
return;
- }
-#endif
- emovi (x, xi);
- /* adjust exponent for offsets */
- exp = (EMULONG) xi[E] - (EXONE - 0x3ff);
-#ifdef INFINITY
- if (eisinf (x))
- goto nonorm;
-#endif
- /* round off to nearest or even */
- rndsav = rndprc;
- rndprc = 53;
- emdnorm (xi, 0, 0, exp, 64);
- rndprc = rndsav;
-#ifdef INFINITY
- nonorm:
-#endif
- toe53 (xi, e);
-}
-/* Convert exploded e-type X, that has already been rounded to
- 53-bit precision, to IEEE double Y. */
+ overflow:
+ get_inf (r, r->sign);
+ case rvc_inf:
+ return;
-static void
-toe53 (x, y)
- UEMUSHORT *x, *y;
-{
- UEMUSHORT i;
- UEMUSHORT *p;
+ case rvc_nan:
+ clear_significand_below (r, np2);
-#ifdef NANS
- if (eiisnan (x))
- {
- make_nan (y, eiisneg (x), DFmode);
+ /* If we've cleared the entire significand, we need one bit
+ set for this to continue to be a NaN. */
+ for (i = 0; i < SIGSZ; ++i)
+ if (r->sig[i])
+ break;
+ if (i == SIGSZ)
+ r->sig[SIGSZ-1] = SIG_MSB >> 2;
return;
+
+ case rvc_normal:
+ break;
+
+ default:
+ abort ();
}
-#endif
- p = &x[0];
-#ifdef IEEE
- if (! REAL_WORDS_BIG_ENDIAN)
- y += 3;
-#endif
- *y = 0; /* output high order */
- if (*p++)
- *y = 0x8000; /* output sign bit */
- i = *p++;
- if (i >= (unsigned int) 2047)
+ /* If we're not base2, normalize the exponent to a multiple of
+ the true base. */
+ if (fmt->log2_b != 1)
{
- /* Saturate at largest number less than infinity. */
-#ifdef INFINITY
- *y |= 0x7ff0;
- if (! REAL_WORDS_BIG_ENDIAN)
- {
- *(--y) = 0;
- *(--y) = 0;
- *(--y) = 0;
- }
- else
+ int shift = r->exp & (fmt->log2_b - 1);
+ if (shift)
{
- ++y;
- *y++ = 0;
- *y++ = 0;
- *y++ = 0;
+ shift = fmt->log2_b - shift;
+ r->sig[0] |= sticky_rshift_significand (r, r, shift);
+ r->exp += shift;
}
-#else
- *y |= (UEMUSHORT) 0x7fef;
- if (! REAL_WORDS_BIG_ENDIAN)
+ }
+
+ /* Check the range of the exponent. If we're out of range,
+ either underflow or overflow. */
+ if (r->exp > emax2)
+ goto overflow;
+ else if (r->exp <= emin2m1)
+ {
+ int diff;
+
+ if (!fmt->has_denorm)
{
- *(--y) = 0xffff;
- *(--y) = 0xffff;
- *(--y) = 0xffff;
+ /* Don't underflow completely until we've had a chance to round. */
+ if (r->exp < emin2m1)
+ goto underflow;
}
else
{
- ++y;
- *y++ = 0xffff;
- *y++ = 0xffff;
- *y++ = 0xffff;
+ diff = emin2m1 - r->exp + 1;
+ if (diff > p2)
+ goto underflow;
+
+ /* De-normalize the significand. */
+ r->sig[0] |= sticky_rshift_significand (r, r, diff);
+ r->exp += diff;
}
-#endif
- return;
}
- if (i == 0)
- {
- eshift (x, 4);
- }
- else
- {
- i <<= 4;
- eshift (x, 5);
- }
- i |= *p++ & (UEMUSHORT) 0x0f; /* *p = xi[M] */
- *y |= (UEMUSHORT) i; /* high order output already has sign bit set */
- if (! REAL_WORDS_BIG_ENDIAN)
- {
- *(--y) = *p++;
- *(--y) = *p++;
- *(--y) = *p;
- }
- else
- {
- ++y;
- *y++ = *p++;
- *y++ = *p++;
- *y++ = *p++;
- }
-}
-#endif /* not C4X */
-#endif /* not IBM */
-#endif /* not DEC */
+ /* There are P2 true significand bits, followed by one guard bit,
+ followed by one sticky bit, followed by stuff. Fold nonzero
+ stuff into the sticky bit. */
+ sticky = 0;
+ for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i)
+ sticky |= r->sig[i];
+ sticky |=
+ r->sig[w] & (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1);
+ guard = test_significand_bit (r, np2 - 1);
+ lsb = test_significand_bit (r, np2);
-/* e type to single precision. */
+ /* Round to even. */
+ if (guard && (sticky || lsb))
+ {
+ REAL_VALUE_TYPE u;
+ get_zero (&u, 0);
+ set_significand_bit (&u, np2);
-#ifdef IBM
-/* Convert e-type X to IBM 370 float E. */
+ if (add_significands (r, r, &u))
+ {
+ /* Overflow. Means the significand had been all ones, and
+ is now all zeros. Need to increase the exponent, and
+ possibly re-normalize it. */
+ if (++r->exp > emax2)
+ goto overflow;
+ r->sig[SIGSZ-1] = SIG_MSB;
+
+ if (fmt->log2_b != 1)
+ {
+ int shift = r->exp & (fmt->log2_b - 1);
+ if (shift)
+ {
+ shift = fmt->log2_b - shift;
+ rshift_significand (r, r, shift);
+ r->exp += shift;
+ if (r->exp > emax2)
+ goto overflow;
+ }
+ }
+ }
+ }
-static void
-etoe24 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
-{
- etoibm (x, e, SFmode);
+ /* Catch underflow that we deferred until after rounding. */
+ if (r->exp <= emin2m1)
+ goto underflow;
+
+ /* Clear out trailing garbage. */
+ clear_significand_below (r, np2);
}
-/* Convert exploded e-type X, that has already been rounded to
- float precision, to IBM 370 float Y. */
+/* Extend or truncate to a new mode. */
-static void
-toe24 (x, y)
- UEMUSHORT *x, *y;
+void
+real_convert (r, mode, a)
+ REAL_VALUE_TYPE *r;
+ enum machine_mode mode;
+ const REAL_VALUE_TYPE *a;
{
- toibm (x, y, SFmode);
-}
+ const struct real_format *fmt;
-#else
+ fmt = real_format_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ abort ();
-#ifdef C4X
-/* Convert e-type X to C4X float E. */
+ *r = *a;
+ round_for_format (fmt, r);
-static void
-etoe24 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
+ /* round_for_format de-normalizes denormals. Undo just that part. */
+ if (r->class == rvc_normal)
+ normalize (r);
+}
+
+/* Legacy. Likewise, except return the struct directly. */
+
+REAL_VALUE_TYPE
+real_value_truncate (mode, a)
+ enum machine_mode mode;
+ REAL_VALUE_TYPE a;
{
- etoc4x (x, e, QFmode);
+ REAL_VALUE_TYPE r;
+ real_convert (&r, mode, &a);
+ return r;
}
-/* Convert exploded e-type X, that has already been rounded to
- float precision, to IBM 370 float Y. */
+/* Return true if truncating to MODE is exact. */
-static void
-toe24 (x, y)
- UEMUSHORT *x, *y;
+bool
+exact_real_truncate (mode, a)
+ enum machine_mode mode;
+ const REAL_VALUE_TYPE *a;
{
- toc4x (x, y, QFmode);
+ REAL_VALUE_TYPE t;
+ real_convert (&t, mode, a);
+ return real_identical (&t, a);
}
-#else
+/* Write R to the given target format. Place the words of the result
+ in target word order in BUF. There are always 32 bits in each
+ long, no matter the size of the host long.
-/* Convert e-type X to IEEE float E. DEC float is the same as IEEE float. */
+ Legacy: return word 0 for implementing REAL_VALUE_TO_TARGET_SINGLE. */
-static void
-etoe24 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
+long
+real_to_target_fmt (buf, r_orig, fmt)
+ long *buf;
+ const REAL_VALUE_TYPE *r_orig;
+ const struct real_format *fmt;
{
- EMULONG exp;
- UEMUSHORT xi[NI];
- int rndsav;
+ REAL_VALUE_TYPE r;
+ long buf1;
-#ifdef NANS
- if (eisnan (x))
- {
- make_nan (e, eisneg (x), SFmode);
- return;
- }
-#endif
- emovi (x, xi);
- /* adjust exponent for offsets */
- exp = (EMULONG) xi[E] - (EXONE - 0177);
-#ifdef INFINITY
- if (eisinf (x))
- goto nonorm;
-#endif
- /* round off to nearest or even */
- rndsav = rndprc;
- rndprc = 24;
- emdnorm (xi, 0, 0, exp, 64);
- rndprc = rndsav;
-#ifdef INFINITY
- nonorm:
-#endif
- toe24 (xi, e);
+ r = *r_orig;
+ round_for_format (fmt, &r);
+
+ if (!buf)
+ buf = &buf1;
+ (*fmt->encode) (fmt, buf, &r);
+
+ return *buf;
}
-/* Convert exploded e-type X, that has already been rounded to
- float precision, to IEEE float Y. */
+/* Similar, but look up the format from MODE. */
-static void
-toe24 (x, y)
- UEMUSHORT *x, *y;
+long
+real_to_target (buf, r, mode)
+ long *buf;
+ const REAL_VALUE_TYPE *r;
+ enum machine_mode mode;
{
- UEMUSHORT i;
- UEMUSHORT *p;
+ const struct real_format *fmt;
-#ifdef NANS
- if (eiisnan (x))
- {
- make_nan (y, eiisneg (x), SFmode);
- return;
- }
-#endif
- p = &x[0];
-#ifdef IEEE
- if (! REAL_WORDS_BIG_ENDIAN)
- y += 1;
-#endif
-#ifdef DEC
- y += 1;
-#endif
- *y = 0; /* output high order */
- if (*p++)
- *y = 0x8000; /* output sign bit */
+ fmt = real_format_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ abort ();
- i = *p++;
-/* Handle overflow cases. */
- if (i >= 255)
- {
-#ifdef INFINITY
- *y |= (UEMUSHORT) 0x7f80;
-#ifdef DEC
- *(--y) = 0;
-#endif
-#ifdef IEEE
- if (! REAL_WORDS_BIG_ENDIAN)
- *(--y) = 0;
- else
- {
- ++y;
- *y = 0;
- }
-#endif
-#else /* no INFINITY */
- *y |= (UEMUSHORT) 0x7f7f;
-#ifdef DEC
- *(--y) = 0xffff;
-#endif
-#ifdef IEEE
- if (! REAL_WORDS_BIG_ENDIAN)
- *(--y) = 0xffff;
- else
- {
- ++y;
- *y = 0xffff;
- }
-#endif
-#ifdef ERANGE
- errno = ERANGE;
-#endif
-#endif /* no INFINITY */
- return;
- }
- if (i == 0)
- {
- eshift (x, 7);
- }
- else
- {
- i <<= 7;
- eshift (x, 8);
- }
- i |= *p++ & (UEMUSHORT) 0x7f; /* *p = xi[M] */
- /* High order output already has sign bit set. */
- *y |= i;
-#ifdef DEC
- *(--y) = *p;
-#endif
-#ifdef IEEE
- if (! REAL_WORDS_BIG_ENDIAN)
- *(--y) = *p;
- else
- {
- ++y;
- *y = *p;
- }
-#endif
+ return real_to_target_fmt (buf, r, fmt);
}
-#endif /* not C4X */
-#endif /* not IBM */
-/* Compare two e type numbers.
- Return +1 if a > b
- 0 if a == b
- -1 if a < b
- -2 if either a or b is a NaN. */
+/* Read R from the given target format. Read the words of the result
+ in target word order in BUF. There are always 32 bits in each
+ long, no matter the size of the host long. */
-static int
-ecmp (a, b)
- const UEMUSHORT *a, *b;
+void
+real_from_target_fmt (r, buf, fmt)
+ REAL_VALUE_TYPE *r;
+ const long *buf;
+ const struct real_format *fmt;
{
- UEMUSHORT ai[NI], bi[NI];
- UEMUSHORT *p, *q;
- int i;
- int msign;
+ (*fmt->decode) (fmt, r, buf);
+}
-#ifdef NANS
- if (eisnan (a) || eisnan (b))
- return (-2);
-#endif
- emovi (a, ai);
- p = ai;
- emovi (b, bi);
- q = bi;
-
- if (*p != *q)
- { /* the signs are different */
- /* -0 equals + 0 */
- for (i = 1; i < NI - 1; i++)
- {
- if (ai[i] != 0)
- goto nzro;
- if (bi[i] != 0)
- goto nzro;
- }
- return (0);
- nzro:
- if (*p == 0)
- return (1);
- else
- return (-1);
- }
- /* both are the same sign */
- if (*p == 0)
- msign = 1;
- else
- msign = -1;
- i = NI - 1;
- do
- {
- if (*p++ != *q++)
- {
- goto diff;
- }
- }
- while (--i > 0);
+/* Similar, but look up the format from MODE. */
- return (0); /* equality */
+void
+real_from_target (r, buf, mode)
+ REAL_VALUE_TYPE *r;
+ const long *buf;
+ enum machine_mode mode;
+{
+ const struct real_format *fmt;
- diff:
+ fmt = real_format_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ abort ();
- if (*(--p) > *(--q))
- return (msign); /* p is bigger */
- else
- return (-msign); /* p is littler */
-}
+ (*fmt->decode) (fmt, r, buf);
+}
-#if 0
-/* Find e-type nearest integer to X, as floor (X + 0.5). */
+/* Return the number of bits in the significand for MODE. */
+/* ??? Legacy. Should get access to real_format directly. */
-static void
-eround (x, y)
- const UEMUSHORT *x;
- UEMUSHORT *y;
+int
+significand_size (mode)
+ enum machine_mode mode;
{
- eadd (ehalf, x, y);
- efloor (y, y);
+ const struct real_format *fmt;
+
+ fmt = real_format_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ return 0;
+
+ return fmt->p * fmt->log2_b;
}
-#endif /* 0 */
-/* Convert HOST_WIDE_INT LP to e type Y. */
+/* Return a hash value for the given real value. */
+/* ??? The "unsigned int" return value is intended to be hashval_t,
+ but I didn't want to pull hashtab.h into real.h. */
-static void
-ltoe (lp, y)
- const HOST_WIDE_INT *lp;
- UEMUSHORT *y;
+unsigned int
+real_hash (r)
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT yi[NI];
- unsigned HOST_WIDE_INT ll;
- int k;
+ unsigned int h;
+ size_t i;
- ecleaz (yi);
- if (*lp < 0)
+ h = r->class | (r->sign << 2);
+ switch (r->class)
{
- /* make it positive */
- ll = (unsigned HOST_WIDE_INT) (-(*lp));
- yi[0] = 0xffff; /* put correct sign in the e type number */
- }
- else
- {
- ll = (unsigned HOST_WIDE_INT) (*lp);
- }
- /* move the long integer to yi significand area */
-#if HOST_BITS_PER_WIDE_INT == 64
- yi[M] = (UEMUSHORT) (ll >> 48);
- yi[M + 1] = (UEMUSHORT) (ll >> 32);
- yi[M + 2] = (UEMUSHORT) (ll >> 16);
- yi[M + 3] = (UEMUSHORT) ll;
- yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */
-#else
- yi[M] = (UEMUSHORT) (ll >> 16);
- yi[M + 1] = (UEMUSHORT) ll;
- yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */
-#endif
+ case rvc_zero:
+ case rvc_inf:
+ break;
- if ((k = enormlz (yi)) > NBITS)/* normalize the significand */
- ecleaz (yi); /* it was zero */
- else
- yi[E] -= (UEMUSHORT) k;/* subtract shift count from exponent */
- emovo (yi, y); /* output the answer */
-}
+ case rvc_normal:
+ h |= r->exp << 3;
+ /* FALLTHRU */
-/* Convert unsigned HOST_WIDE_INT LP to e type Y. */
+ case rvc_nan:
+ if (sizeof(unsigned long) > sizeof(unsigned int))
+ for (i = 0; i < SIGSZ; ++i)
+ {
+ unsigned long s = r->sig[i];
+ h ^= s ^ (s >> (HOST_BITS_PER_LONG / 2));
+ }
+ else
+ for (i = 0; i < SIGSZ; ++i)
+ h ^= r->sig[i];
+ break;
-static void
-ultoe (lp, y)
- const unsigned HOST_WIDE_INT *lp;
- UEMUSHORT *y;
-{
- UEMUSHORT yi[NI];
- unsigned HOST_WIDE_INT ll;
- int k;
-
- ecleaz (yi);
- ll = *lp;
-
- /* move the long integer to ayi significand area */
-#if HOST_BITS_PER_WIDE_INT == 64
- yi[M] = (UEMUSHORT) (ll >> 48);
- yi[M + 1] = (UEMUSHORT) (ll >> 32);
- yi[M + 2] = (UEMUSHORT) (ll >> 16);
- yi[M + 3] = (UEMUSHORT) ll;
- yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */
-#else
- yi[M] = (UEMUSHORT) (ll >> 16);
- yi[M + 1] = (UEMUSHORT) ll;
- yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */
-#endif
+ default:
+ abort ();
+ }
- if ((k = enormlz (yi)) > NBITS)/* normalize the significand */
- ecleaz (yi); /* it was zero */
- else
- yi[E] -= (UEMUSHORT) k; /* subtract shift count from exponent */
- emovo (yi, y); /* output the answer */
+ return h;
}
+
+/* IEEE single-precision format. */
-
-/* Find signed HOST_WIDE_INT integer I and floating point fractional
- part FRAC of e-type (packed internal format) floating point input X.
- The integer output I has the sign of the input, except that
- positive overflow is permitted if FIXUNS_TRUNC_LIKE_FIX_TRUNC.
- The output e-type fraction FRAC is the positive fractional
- part of abs (X). */
+static void encode_ieee_single PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_ieee_single PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
static void
-eifrac (x, i, frac)
- const UEMUSHORT *x;
- HOST_WIDE_INT *i;
- UEMUSHORT *frac;
+encode_ieee_single (fmt, buf, r)
+ const struct real_format *fmt;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT xi[NI];
- int j, k;
- unsigned HOST_WIDE_INT ll;
+ unsigned long image, sig, exp;
+ bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
- emovi (x, xi);
- k = (int) xi[E] - (EXONE - 1);
- if (k <= 0)
- {
- /* if exponent <= 0, integer = 0 and real output is fraction */
- *i = 0L;
- emovo (xi, frac);
- return;
- }
- if (k > (HOST_BITS_PER_WIDE_INT - 1))
+ image = r->sign << 31;
+ sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
+
+ switch (r->class)
{
- /* long integer overflow: output large integer
- and correct fraction */
- if (xi[0])
- *i = ((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1);
+ case rvc_zero:
+ break;
+
+ case rvc_inf:
+ if (fmt->has_inf)
+ image |= 255 << 23;
else
+ image |= 0x7fffffff;
+ break;
+
+ case rvc_nan:
+ if (fmt->has_nans)
{
-#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
- /* In this case, let it overflow and convert as if unsigned. */
- euifrac (x, &ll, frac);
- *i = (HOST_WIDE_INT) ll;
- return;
-#else
- /* In other cases, return the largest positive integer. */
- *i = (((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1)) - 1;
-#endif
- }
- eshift (xi, k);
- if (extra_warnings)
- warning ("overflow on truncation to integer");
- }
- else if (k > 16)
- {
- /* Shift more than 16 bits: first shift up k-16 mod 16,
- then shift up by 16's. */
- j = k - ((k >> 4) << 4);
- eshift (xi, j);
- ll = xi[M];
- k -= j;
- do
- {
- eshup6 (xi);
- ll = (ll << 16) | xi[M];
+ image |= 255 << 23;
+ image |= sig;
+ if (!fmt->qnan_msb_set)
+ image ^= 1 << 23 | 1 << 22;
}
- while ((k -= 16) > 0);
- *i = ll;
- if (xi[0])
- *i = -(*i);
- }
- else
- {
- /* shift not more than 16 bits */
- eshift (xi, k);
- *i = (HOST_WIDE_INT) xi[M] & 0xffff;
- if (xi[0])
- *i = -(*i);
- }
- xi[0] = 0;
- xi[E] = EXONE - 1;
- xi[M] = 0;
- if ((k = enormlz (xi)) > NBITS)
- ecleaz (xi);
- else
- xi[E] -= (UEMUSHORT) k;
+ else
+ image |= 0x7fffffff;
+ break;
- emovo (xi, frac);
-}
+ case rvc_normal:
+ /* Recall that IEEE numbers are interpreted as 1.F x 2**exp,
+ whereas the intermediate representation is 0.F x 2**exp.
+ Which means we're off by one. */
+ if (denormal)
+ exp = 0;
+ else
+ exp = r->exp + 127 - 1;
+ image |= exp << 23;
+ image |= sig;
+ break;
+ default:
+ abort ();
+ }
-/* Find unsigned HOST_WIDE_INT integer I and floating point fractional part
- FRAC of e-type X. A negative input yields integer output = 0 but
- correct fraction. */
+ buf[0] = image;
+}
static void
-euifrac (x, i, frac)
- const UEMUSHORT *x;
- unsigned HOST_WIDE_INT *i;
- UEMUSHORT *frac;
+decode_ieee_single (fmt, r, buf)
+ const struct real_format *fmt;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- unsigned HOST_WIDE_INT ll;
- UEMUSHORT xi[NI];
- int j, k;
+ unsigned long image = buf[0] & 0xffffffff;
+ bool sign = (image >> 31) & 1;
+ int exp = (image >> 23) & 0xff;
- emovi (x, xi);
- k = (int) xi[E] - (EXONE - 1);
- if (k <= 0)
- {
- /* if exponent <= 0, integer = 0 and argument is fraction */
- *i = 0L;
- emovo (xi, frac);
- return;
- }
- if (k > HOST_BITS_PER_WIDE_INT)
+ memset (r, 0, sizeof (*r));
+ image <<= HOST_BITS_PER_LONG - 24;
+ image &= ~SIG_MSB;
+
+ if (exp == 0)
{
- /* Long integer overflow: output large integer
- and correct fraction.
- Note, the BSD MicroVAX compiler says that ~(0UL)
- is a syntax error. */
- *i = ~(0L);
- eshift (xi, k);
- if (extra_warnings)
- warning ("overflow on truncation to unsigned integer");
+ if (image && fmt->has_denorm)
+ {
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = -126;
+ r->sig[SIGSZ-1] = image << 1;
+ normalize (r);
+ }
+ else if (fmt->has_signed_zero)
+ r->sign = sign;
}
- else if (k > 16)
+ else if (exp == 255 && (fmt->has_nans || fmt->has_inf))
{
- /* Shift more than 16 bits: first shift up k-16 mod 16,
- then shift up by 16's. */
- j = k - ((k >> 4) << 4);
- eshift (xi, j);
- ll = xi[M];
- k -= j;
- do
+ if (image)
{
- eshup6 (xi);
- ll = (ll << 16) | xi[M];
+ r->class = rvc_nan;
+ r->sign = sign;
+ if (!fmt->qnan_msb_set)
+ image ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
+ r->sig[SIGSZ-1] = image;
+ }
+ else
+ {
+ r->class = rvc_inf;
+ r->sign = sign;
}
- while ((k -= 16) > 0);
- *i = ll;
}
else
{
- /* shift not more than 16 bits */
- eshift (xi, k);
- *i = (HOST_WIDE_INT) xi[M] & 0xffff;
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp - 127 + 1;
+ r->sig[SIGSZ-1] = image | SIG_MSB;
}
+}
- if (xi[0]) /* A negative value yields unsigned integer 0. */
- *i = 0L;
-
- xi[0] = 0;
- xi[E] = EXONE - 1;
- xi[M] = 0;
- if ((k = enormlz (xi)) > NBITS)
- ecleaz (xi);
- else
- xi[E] -= (UEMUSHORT) k;
+const struct real_format ieee_single_format =
+ {
+ encode_ieee_single,
+ decode_ieee_single,
+ 2,
+ 1,
+ 24,
+ -125,
+ 128,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
- emovo (xi, frac);
-}
+
+/* IEEE double-precision format. */
-/* Shift the significand of exploded e-type X up or down by SC bits. */
+static void encode_ieee_double PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_ieee_double PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
-static int
-eshift (x, sc)
- UEMUSHORT *x;
- int sc;
+static void
+encode_ieee_double (fmt, buf, r)
+ const struct real_format *fmt;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT lost;
- UEMUSHORT *p;
+ unsigned long image_lo, image_hi, sig_lo, sig_hi, exp;
+ bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
- if (sc == 0)
- return (0);
+ image_hi = r->sign << 31;
+ image_lo = 0;
- lost = 0;
- p = x + NI - 1;
+ if (HOST_BITS_PER_LONG == 64)
+ {
+ sig_hi = r->sig[SIGSZ-1];
+ sig_lo = (sig_hi >> (64 - 53)) & 0xffffffff;
+ sig_hi = (sig_hi >> (64 - 53 + 1) >> 31) & 0xfffff;
+ }
+ else
+ {
+ sig_hi = r->sig[SIGSZ-1];
+ sig_lo = r->sig[SIGSZ-2];
+ sig_lo = (sig_hi << 21) | (sig_lo >> 11);
+ sig_hi = (sig_hi >> 11) & 0xfffff;
+ }
- if (sc < 0)
+ switch (r->class)
{
- sc = -sc;
- while (sc >= 16)
- {
- lost |= *p; /* remember lost bits */
- eshdn6 (x);
- sc -= 16;
- }
+ case rvc_zero:
+ break;
- while (sc >= 8)
+ case rvc_inf:
+ if (fmt->has_inf)
+ image_hi |= 2047 << 20;
+ else
{
- lost |= *p & 0xff;
- eshdn8 (x);
- sc -= 8;
+ image_hi |= 0x7fffffff;
+ image_lo = 0xffffffff;
}
+ break;
- while (sc > 0)
+ case rvc_nan:
+ if (fmt->has_nans)
{
- lost |= *p & 1;
- eshdn1 (x);
- sc -= 1;
+ image_hi |= 2047 << 20;
+ image_hi |= sig_hi;
+ if (!fmt->qnan_msb_set)
+ image_hi ^= 1 << 19 | 1 << 18;
+ image_lo = sig_lo;
}
- }
- else
- {
- while (sc >= 16)
+ else
{
- eshup6 (x);
- sc -= 16;
+ image_hi |= 0x7fffffff;
+ image_lo = 0xffffffff;
}
+ break;
- while (sc >= 8)
- {
- eshup8 (x);
- sc -= 8;
- }
+ case rvc_normal:
+ /* Recall that IEEE numbers are interpreted as 1.F x 2**exp,
+ whereas the intermediate representation is 0.F x 2**exp.
+ Which means we're off by one. */
+ if (denormal)
+ exp = 0;
+ else
+ exp = r->exp + 1023 - 1;
+ image_hi |= exp << 20;
+ image_hi |= sig_hi;
+ image_lo = sig_lo;
+ break;
- while (sc > 0)
- {
- eshup1 (x);
- sc -= 1;
- }
+ default:
+ abort ();
}
- if (lost)
- lost = 1;
- return ((int) lost);
-}
-/* Shift normalize the significand area of exploded e-type X.
- Return the shift count (up = positive). */
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = image_hi, buf[1] = image_lo;
+ else
+ buf[0] = image_lo, buf[1] = image_hi;
+}
-static int
-enormlz (x)
- UEMUSHORT x[];
+static void
+decode_ieee_double (fmt, r, buf)
+ const struct real_format *fmt;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- UEMUSHORT *p;
- int sc;
-
- sc = 0;
- p = &x[M];
- if (*p != 0)
- goto normdn;
- ++p;
- if (*p & 0x8000)
- return (0); /* already normalized */
- while (*p == 0)
- {
- eshup6 (x);
- sc += 16;
+ unsigned long image_hi, image_lo;
+ bool sign;
+ int exp;
- /* With guard word, there are NBITS+16 bits available.
- Return true if all are zero. */
- if (sc > NBITS)
- return (sc);
- }
- /* see if high byte is zero */
- while ((*p & 0xff00) == 0)
- {
- eshup8 (x);
- sc += 8;
- }
- /* now shift 1 bit at a time */
- while ((*p & 0x8000) == 0)
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ image_hi = buf[0], image_lo = buf[1];
+ else
+ image_lo = buf[0], image_hi = buf[1];
+ image_lo &= 0xffffffff;
+ image_hi &= 0xffffffff;
+
+ sign = (image_hi >> 31) & 1;
+ exp = (image_hi >> 20) & 0x7ff;
+
+ memset (r, 0, sizeof (*r));
+
+ image_hi <<= 32 - 21;
+ image_hi |= image_lo >> 21;
+ image_hi &= 0x7fffffff;
+ image_lo <<= 32 - 21;
+
+ if (exp == 0)
{
- eshup1 (x);
- sc += 1;
- if (sc > NBITS)
+ if ((image_hi || image_lo) && fmt->has_denorm)
{
- mtherr ("enormlz", UNDERFLOW);
- return (sc);
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = -1022;
+ if (HOST_BITS_PER_LONG == 32)
+ {
+ image_hi = (image_hi << 1) | (image_lo >> 31);
+ image_lo <<= 1;
+ r->sig[SIGSZ-1] = image_hi;
+ r->sig[SIGSZ-2] = image_lo;
+ }
+ else
+ {
+ image_hi = (image_hi << 31 << 2) | (image_lo << 1);
+ r->sig[SIGSZ-1] = image_hi;
+ }
+ normalize (r);
}
+ else if (fmt->has_signed_zero)
+ r->sign = sign;
}
- return (sc);
-
- /* Normalize by shifting down out of the high guard word
- of the significand */
- normdn:
-
- if (*p & 0xff00)
+ else if (exp == 2047 && (fmt->has_nans || fmt->has_inf))
{
- eshdn8 (x);
- sc -= 8;
+ if (image_hi || image_lo)
+ {
+ r->class = rvc_nan;
+ r->sign = sign;
+ if (HOST_BITS_PER_LONG == 32)
+ {
+ r->sig[SIGSZ-1] = image_hi;
+ r->sig[SIGSZ-2] = image_lo;
+ }
+ else
+ r->sig[SIGSZ-1] = (image_hi << 31 << 1) | image_lo;
+
+ if (!fmt->qnan_msb_set)
+ r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
+ }
+ else
+ {
+ r->class = rvc_inf;
+ r->sign = sign;
+ }
}
- while (*p != 0)
+ else
{
- eshdn1 (x);
- sc -= 1;
-
- if (sc < -NBITS)
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp - 1023 + 1;
+ if (HOST_BITS_PER_LONG == 32)
{
- mtherr ("enormlz", OVERFLOW);
- return (sc);
+ r->sig[SIGSZ-1] = image_hi | SIG_MSB;
+ r->sig[SIGSZ-2] = image_lo;
}
+ else
+ r->sig[SIGSZ-1] = (image_hi << 31 << 1) | image_lo | SIG_MSB;
}
- return (sc);
}
-/* Powers of ten used in decimal <-> binary conversions. */
-
-#define NTEN 12
-#define MAXP 4096
-
-#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && (INTEL_EXTENDED_IEEE_FORMAT == 0)
-static const UEMUSHORT etens[NTEN + 1][NE] =
-{
- {0x6576, 0x4a92, 0x804a, 0x153f,
- 0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,}, /* 10**4096 */
- {0x6a32, 0xce52, 0x329a, 0x28ce,
- 0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,}, /* 10**2048 */
- {0x526c, 0x50ce, 0xf18b, 0x3d28,
- 0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,},
- {0x9c66, 0x58f8, 0xbc50, 0x5c54,
- 0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,},
- {0x851e, 0xeab7, 0x98fe, 0x901b,
- 0xddbb, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,},
- {0x0235, 0x0137, 0x36b1, 0x336c,
- 0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,},
- {0x50f8, 0x25fb, 0xc76b, 0x6b71,
- 0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,},
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,},
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,},
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,},
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,},
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,},
- {0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,}, /* 10**1 */
-};
+const struct real_format ieee_double_format =
+ {
+ encode_ieee_double,
+ decode_ieee_double,
+ 2,
+ 1,
+ 53,
+ -1021,
+ 1024,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
-static const UEMUSHORT emtens[NTEN + 1][NE] =
-{
- {0x2030, 0xcffc, 0xa1c3, 0x8123,
- 0x2de3, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,}, /* 10**-4096 */
- {0x8264, 0xd2cb, 0xf2ea, 0x12d4,
- 0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,}, /* 10**-2048 */
- {0xf53f, 0xf698, 0x6bd3, 0x0158,
- 0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,},
- {0xe731, 0x04d4, 0xe3f2, 0xd332,
- 0x7132, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,},
- {0xa23e, 0x5308, 0xfefb, 0x1155,
- 0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,},
- {0xe26d, 0xdbde, 0xd05d, 0xb3f6,
- 0xac7c, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,},
- {0x2a20, 0x6224, 0x47b3, 0x98d7,
- 0x3f23, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,},
- {0x0b5b, 0x4af2, 0xa581, 0x18ed,
- 0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,},
- {0xbf71, 0xa9b3, 0x7989, 0xbe68,
- 0x4c2e, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,},
- {0x3d4d, 0x7c3d, 0x36ba, 0x0d2b,
- 0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,},
- {0xc155, 0xa4a8, 0x404e, 0x6113,
- 0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,},
- {0xd70a, 0x70a3, 0x0a3d, 0xa3d7,
- 0x3d70, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,},
- {0xcccd, 0xcccc, 0xcccc, 0xcccc,
- 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,}, /* 10**-1 */
-};
-#else
-/* LONG_DOUBLE_TYPE_SIZE is other than 128 */
-static const UEMUSHORT etens[NTEN + 1][NE] =
-{
- {0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,}, /* 10**4096 */
- {0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,}, /* 10**2048 */
- {0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,},
- {0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,},
- {0xddbc, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,},
- {0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,},
- {0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,},
- {0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,},
- {0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,},
- {0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,},
- {0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,},
- {0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,},
- {0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,}, /* 10**1 */
-};
+
+/* IEEE extended double precision format. This comes in three
+ flavours: Intel's as a 12 byte image, Intel's as a 16 byte image,
+ and Motorola's. */
+
+static void encode_ieee_extended PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_ieee_extended PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
+
+static void encode_ieee_extended_128 PARAMS ((const struct real_format *fmt,
+ long *,
+ const REAL_VALUE_TYPE *));
+static void decode_ieee_extended_128 PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *,
+ const long *));
-static const UEMUSHORT emtens[NTEN + 1][NE] =
+static void
+encode_ieee_extended (fmt, buf, r)
+ const struct real_format *fmt;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- {0x2de4, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,}, /* 10**-4096 */
- {0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,}, /* 10**-2048 */
- {0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,},
- {0x7133, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,},
- {0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,},
- {0xac7d, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,},
- {0x3f24, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,},
- {0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,},
- {0x4c2f, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,},
- {0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,},
- {0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,},
- {0x3d71, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,},
- {0xcccd, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,}, /* 10**-1 */
-};
-#endif
+ unsigned long image_hi, sig_hi, sig_lo;
+ bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
-#if 0
-/* Convert float value X to ASCII string STRING with NDIG digits after
- the decimal point. */
+ image_hi = r->sign << 15;
+ sig_hi = sig_lo = 0;
-static void
-e24toasc (x, string, ndigs)
- const UEMUSHORT x[];
- char *string;
- int ndigs;
-{
- UEMUSHORT w[NI];
+ switch (r->class)
+ {
+ case rvc_zero:
+ break;
- e24toe (x, w);
- etoasc (w, string, ndigs);
-}
+ case rvc_inf:
+ if (fmt->has_inf)
+ {
+ image_hi |= 32767;
-/* Convert double value X to ASCII string STRING with NDIG digits after
- the decimal point. */
+ /* Intel requires the explicit integer bit to be set, otherwise
+ it considers the value a "pseudo-infinity". Motorola docs
+ say it doesn't care. */
+ sig_hi = 0x80000000;
+ }
+ else
+ {
+ image_hi |= 32767;
+ sig_lo = sig_hi = 0xffffffff;
+ }
+ break;
-static void
-e53toasc (x, string, ndigs)
- const UEMUSHORT x[];
- char *string;
- int ndigs;
-{
- UEMUSHORT w[NI];
+ case rvc_nan:
+ if (fmt->has_nans)
+ {
+ image_hi |= 32767;
+ if (HOST_BITS_PER_LONG == 32)
+ {
+ sig_hi = r->sig[SIGSZ-1];
+ sig_lo = r->sig[SIGSZ-2];
+ }
+ else
+ {
+ sig_lo = r->sig[SIGSZ-1];
+ sig_hi = sig_lo >> 31 >> 1;
+ sig_lo &= 0xffffffff;
+ }
+ if (!fmt->qnan_msb_set)
+ sig_hi ^= 1 << 30 | 1 << 29;
- e53toe (x, w);
- etoasc (w, string, ndigs);
-}
+ /* Intel requires the explicit integer bit to be set, otherwise
+ it considers the value a "pseudo-nan". Motorola docs say it
+ doesn't care. */
+ sig_hi |= 0x80000000;
+ }
+ else
+ {
+ image_hi |= 32767;
+ sig_lo = sig_hi = 0xffffffff;
+ }
+ break;
-/* Convert double extended value X to ASCII string STRING with NDIG digits
- after the decimal point. */
+ case rvc_normal:
+ {
+ int exp = r->exp;
+
+ /* Recall that IEEE numbers are interpreted as 1.F x 2**exp,
+ whereas the intermediate representation is 0.F x 2**exp.
+ Which means we're off by one.
+
+ Except for Motorola, which consider exp=0 and explicit
+ integer bit set to continue to be normalized. In theory
+ this descrepency has been taken care of by the difference
+ in fmt->emin in round_for_format. */
+
+ if (denormal)
+ exp = 0;
+ else
+ {
+ exp += 16383 - 1;
+ if (exp < 0)
+ abort ();
+ }
+ image_hi |= exp;
+
+ if (HOST_BITS_PER_LONG == 32)
+ {
+ sig_hi = r->sig[SIGSZ-1];
+ sig_lo = r->sig[SIGSZ-2];
+ }
+ else
+ {
+ sig_lo = r->sig[SIGSZ-1];
+ sig_hi = sig_lo >> 31 >> 1;
+ sig_lo &= 0xffffffff;
+ }
+ }
+ break;
-static void
-e64toasc (x, string, ndigs)
- const UEMUSHORT x[];
- char *string;
- int ndigs;
-{
- UEMUSHORT w[NI];
+ default:
+ abort ();
+ }
- e64toe (x, w);
- etoasc (w, string, ndigs);
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = image_hi << 16, buf[1] = sig_hi, buf[2] = sig_lo;
+ else
+ buf[0] = sig_lo, buf[1] = sig_hi, buf[2] = image_hi;
}
-/* Convert 128-bit long double value X to ASCII string STRING with NDIG digits
- after the decimal point. */
-
static void
-e113toasc (x, string, ndigs)
- const UEMUSHORT x[];
- char *string;
- int ndigs;
+encode_ieee_extended_128 (fmt, buf, r)
+ const struct real_format *fmt;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT w[NI];
-
- e113toe (x, w);
- etoasc (w, string, ndigs);
+ buf[3 * !FLOAT_WORDS_BIG_ENDIAN] = 0;
+ encode_ieee_extended (fmt, buf+!!FLOAT_WORDS_BIG_ENDIAN, r);
}
-#endif /* 0 */
-
-/* Convert e-type X to ASCII string STRING with NDIGS digits after
- the decimal point. */
-
-static char wstring[80]; /* working storage for ASCII output */
static void
-etoasc (x, string, ndigs)
- const UEMUSHORT x[];
- char *string;
- int ndigs;
+decode_ieee_extended (fmt, r, buf)
+ const struct real_format *fmt;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- EMUSHORT digit;
- UEMUSHORT y[NI], t[NI], u[NI], w[NI];
- const UEMUSHORT *p, *r, *ten;
- UEMUSHORT sign;
- int i, j, k, expon, rndsav;
- char *s, *ss;
- UEMUSHORT m;
-
-
- rndsav = rndprc;
- ss = string;
- s = wstring;
- *ss = '\0';
- *s = '\0';
-#ifdef NANS
- if (eisnan (x))
- {
- sprintf (wstring, " NaN ");
- goto bxit;
- }
-#endif
- rndprc = NBITS; /* set to full precision */
- emov (x, y); /* retain external format */
- if (y[NE - 1] & 0x8000)
- {
- sign = 0xffff;
- y[NE - 1] &= 0x7fff;
- }
- else
- {
- sign = 0;
- }
- expon = 0;
- ten = &etens[NTEN][0];
- emov (eone, t);
- /* Test for zero exponent */
- if (y[NE - 1] == 0)
- {
- for (k = 0; k < NE - 1; k++)
- {
- if (y[k] != 0)
- goto tnzro; /* denormalized number */
- }
- goto isone; /* valid all zeros */
- }
- tnzro:
-
- /* Test for infinity. */
- if (y[NE - 1] == 0x7fff)
- {
- if (sign)
- sprintf (wstring, " -Infinity ");
- else
- sprintf (wstring, " Infinity ");
- goto bxit;
- }
-
- /* Test for exponent nonzero but significand denormalized.
- * This is an error condition.
- */
- if ((y[NE - 1] != 0) && ((y[NE - 2] & 0x8000) == 0))
- {
- mtherr ("etoasc", DOMAIN);
- sprintf (wstring, "NaN");
- goto bxit;
- }
+ unsigned long image_hi, sig_hi, sig_lo;
+ bool sign;
+ int exp;
- /* Compare to 1.0 */
- i = ecmp (eone, y);
- if (i == 0)
- goto isone;
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ image_hi = buf[0] >> 16, sig_hi = buf[1], sig_lo = buf[2];
+ else
+ sig_lo = buf[0], sig_hi = buf[1], image_hi = buf[2];
+ sig_lo &= 0xffffffff;
+ sig_hi &= 0xffffffff;
+ image_hi &= 0xffffffff;
- if (i == -2)
- abort ();
+ sign = (image_hi >> 15) & 1;
+ exp = image_hi & 0x7fff;
- if (i < 0)
- { /* Number is greater than 1 */
- /* Convert significand to an integer and strip trailing decimal zeros. */
- emov (y, u);
- u[NE - 1] = EXONE + NBITS - 1;
+ memset (r, 0, sizeof (*r));
- p = &etens[NTEN - 4][0];
- m = 16;
- do
- {
- ediv (p, u, t);
- efloor (t, w);
- for (j = 0; j < NE - 1; j++)
- {
- if (t[j] != w[j])
- goto noint;
- }
- emov (t, u);
- expon += (int) m;
- noint:
- p += NE;
- m >>= 1;
- }
- while (m != 0);
-
- /* Rescale from integer significand */
- u[NE - 1] += y[NE - 1] - (unsigned int) (EXONE + NBITS - 1);
- emov (u, y);
- /* Find power of 10 */
- emov (eone, t);
- m = MAXP;
- p = &etens[0][0];
- /* An unordered compare result shouldn't happen here. */
- while (ecmp (ten, u) <= 0)
+ if (exp == 0)
+ {
+ if ((sig_hi || sig_lo) && fmt->has_denorm)
{
- if (ecmp (p, u) <= 0)
+ r->class = rvc_normal;
+ r->sign = sign;
+
+ /* When the IEEE format contains a hidden bit, we know that
+ it's zero at this point, and so shift up the significand
+ and decrease the exponent to match. In this case, Motorola
+ defines the explicit integer bit to be valid, so we don't
+ know whether the msb is set or not. */
+ r->exp = fmt->emin;
+ if (HOST_BITS_PER_LONG == 32)
{
- ediv (p, u, u);
- emul (p, t, t);
- expon += (int) m;
+ r->sig[SIGSZ-1] = sig_hi;
+ r->sig[SIGSZ-2] = sig_lo;
}
- m >>= 1;
- if (m == 0)
- break;
- p += NE;
+ else
+ r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo;
+
+ normalize (r);
}
+ else if (fmt->has_signed_zero)
+ r->sign = sign;
}
- else
- { /* Number is less than 1.0 */
- /* Pad significand with trailing decimal zeros. */
- if (y[NE - 1] == 0)
+ else if (exp == 32767 && (fmt->has_nans || fmt->has_inf))
+ {
+ /* See above re "pseudo-infinities" and "pseudo-nans".
+ Short summary is that the MSB will likely always be
+ set, and that we don't care about it. */
+ sig_hi &= 0x7fffffff;
+
+ if (sig_hi || sig_lo)
{
- while ((y[NE - 2] & 0x8000) == 0)
+ r->class = rvc_nan;
+ r->sign = sign;
+ if (HOST_BITS_PER_LONG == 32)
{
- emul (ten, y, y);
- expon -= 1;
+ r->sig[SIGSZ-1] = sig_hi;
+ r->sig[SIGSZ-2] = sig_lo;
}
+ else
+ r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo;
+
+ if (!fmt->qnan_msb_set)
+ r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
}
else
{
- emovi (y, w);
- for (i = 0; i < NDEC + 1; i++)
- {
- if ((w[NI - 1] & 0x7) != 0)
- break;
- /* multiply by 10 */
- emovz (w, u);
- eshdn1 (u);
- eshdn1 (u);
- eaddm (w, u);
- u[1] += 3;
- while (u[2] != 0)
- {
- eshdn1 (u);
- u[1] += 1;
- }
- if (u[NI - 1] != 0)
- break;
- if (eone[NE - 1] <= u[1])
- break;
- emovz (u, w);
- expon -= 1;
- }
- emovo (w, y);
+ r->class = rvc_inf;
+ r->sign = sign;
}
- k = -MAXP;
- p = &emtens[0][0];
- r = &etens[0][0];
- emov (y, w);
- emov (eone, t);
- while (ecmp (eone, w) > 0)
- {
- if (ecmp (p, w) >= 0)
- {
- emul (r, w, w);
- emul (r, t, t);
- expon += k;
- }
- k /= 2;
- if (k == 0)
- break;
- p += NE;
- r += NE;
- }
- ediv (t, eone, t);
}
- isone:
- /* Find the first (leading) digit. */
- emovi (t, w);
- emovz (w, t);
- emovi (y, w);
- emovz (w, y);
- eiremain (t, y);
- digit = equot[NI - 1];
- while ((digit == 0) && (ecmp (y, ezero) != 0))
- {
- eshup1 (y);
- emovz (y, u);
- eshup1 (u);
- eshup1 (u);
- eaddm (u, y);
- eiremain (t, y);
- digit = equot[NI - 1];
- expon -= 1;
- }
- s = wstring;
- if (sign)
- *s++ = '-';
else
- *s++ = ' ';
- /* Examine number of digits requested by caller. */
- if (ndigs < 0)
- ndigs = 0;
- if (ndigs > NDEC)
- ndigs = NDEC;
- if (digit == 10)
{
- *s++ = '1';
- *s++ = '.';
- if (ndigs > 0)
- {
- *s++ = '0';
- ndigs -= 1;
- }
- expon += 1;
- }
- else
- {
- *s++ = (char) digit + '0';
- *s++ = '.';
- }
- /* Generate digits after the decimal point. */
- for (k = 0; k <= ndigs; k++)
- {
- /* multiply current number by 10, without normalizing */
- eshup1 (y);
- emovz (y, u);
- eshup1 (u);
- eshup1 (u);
- eaddm (u, y);
- eiremain (t, y);
- *s++ = (char) equot[NI - 1] + '0';
- }
- digit = equot[NI - 1];
- --s;
- ss = s;
- /* round off the ASCII string */
- if (digit > 4)
- {
- /* Test for critical rounding case in ASCII output. */
- if (digit == 5)
- {
- emovo (y, t);
- if (ecmp (t, ezero) != 0)
- goto roun; /* round to nearest */
-#ifndef C4X
- if ((*(s - 1) & 1) == 0)
- goto doexp; /* round to even */
-#endif
- }
- /* Round up and propagate carry-outs */
- roun:
- --s;
- k = *s & CHARMASK;
- /* Carry out to most significant digit? */
- if (k == '.')
- {
- --s;
- k = *s;
- k += 1;
- *s = (char) k;
- /* Most significant digit carries to 10? */
- if (k > '9')
- {
- expon += 1;
- *s = '1';
- }
- goto doexp;
- }
- /* Round up and carry out from less significant digits */
- k += 1;
- *s = (char) k;
- if (k > '9')
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp - 16383 + 1;
+ if (HOST_BITS_PER_LONG == 32)
{
- *s = '0';
- goto roun;
+ r->sig[SIGSZ-1] = sig_hi;
+ r->sig[SIGSZ-2] = sig_lo;
}
+ else
+ r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo;
}
- doexp:
- /*
- if (expon >= 0)
- sprintf (ss, "e+%d", expon);
- else
- sprintf (ss, "e%d", expon);
- */
- sprintf (ss, "e%d", expon);
- bxit:
- rndprc = rndsav;
- /* copy out the working string */
- s = string;
- ss = wstring;
- while (*ss == ' ') /* strip possible leading space */
- ++ss;
- while ((*s++ = *ss++) != '\0')
- ;
}
-
-/* Convert ASCII string to floating point.
-
- Numeric input is a free format decimal number of any length, with
- or without decimal point. Entering E after the number followed by an
- integer number causes the second number to be interpreted as a power of
- 10 to be multiplied by the first number (i.e., "scientific" notation). */
-
-/* Convert ASCII string S to single precision float value Y. */
-
static void
-asctoe24 (s, y)
- const char *s;
- UEMUSHORT *y;
+decode_ieee_extended_128 (fmt, r, buf)
+ const struct real_format *fmt;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- asctoeg (s, y, 24);
+ decode_ieee_extended (fmt, r, buf+!!FLOAT_WORDS_BIG_ENDIAN);
}
-
-/* Convert ASCII string S to double precision value Y. */
+const struct real_format ieee_extended_motorola_format =
+ {
+ encode_ieee_extended,
+ decode_ieee_extended,
+ 2,
+ 1,
+ 64,
+ -16382,
+ 16384,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+const struct real_format ieee_extended_intel_96_format =
+ {
+ encode_ieee_extended,
+ decode_ieee_extended,
+ 2,
+ 1,
+ 64,
+ -16381,
+ 16384,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+const struct real_format ieee_extended_intel_128_format =
+ {
+ encode_ieee_extended_128,
+ decode_ieee_extended_128,
+ 2,
+ 1,
+ 64,
+ -16381,
+ 16384,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+/* The following caters to i386 systems that set the rounding precision
+ to 53 bits instead of 64, e.g. FreeBSD. */
+const struct real_format ieee_extended_intel_96_round_53_format =
+ {
+ encode_ieee_extended,
+ decode_ieee_extended,
+ 2,
+ 1,
+ 53,
+ -16381,
+ 16384,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+/* IBM 128-bit extended precision format: a pair of IEEE double precision
+ numbers whose sum is equal to the extended precision value. The number
+ with greater magnitude is first. This format has the same magnitude
+ range as an IEEE double precision value, but effectively 106 bits of
+ significand precision. Infinity and NaN are represented by their IEEE
+ double precision value stored in the first number, the second number is
+ ignored. Zeroes, Infinities, and NaNs are set in both doubles
+ due to precedent. */
+
+static void encode_ibm_extended PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_ibm_extended PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
static void
-asctoe53 (s, y)
- const char *s;
- UEMUSHORT *y;
+encode_ibm_extended (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
-#if defined(DEC) || defined(IBM)
- asctoeg (s, y, 56);
-#else
-#if defined(C4X)
- asctoeg (s, y, 32);
-#else
- asctoeg (s, y, 53);
-#endif
-#endif
-}
+ REAL_VALUE_TYPE u, v;
+ switch (r->class)
+ {
+ case rvc_zero:
+ /* Both doubles have sign bit set. */
+ buf[0] = FLOAT_WORDS_BIG_ENDIAN ? r->sign << 31 : 0;
+ buf[1] = FLOAT_WORDS_BIG_ENDIAN ? 0 : r->sign << 31;
+ buf[2] = buf[0];
+ buf[3] = buf[1];
+ break;
-/* Convert ASCII string S to double extended value Y. */
+ case rvc_inf:
+ case rvc_nan:
+ /* Both doubles set to Inf / NaN. */
+ encode_ieee_double (&ieee_double_format, &buf[0], r);
+ buf[2] = buf[0];
+ buf[3] = buf[1];
+ return;
+
+ case rvc_normal:
+ /* u = IEEE double precision portion of significand. */
+ u = *r;
+ clear_significand_below (&u, SIGNIFICAND_BITS - 53);
+
+ normalize (&u);
+ /* If the upper double is zero, we have a denormal double, so
+ move it to the first double and leave the second as zero. */
+ if (u.class == rvc_zero)
+ {
+ v = u;
+ u = *r;
+ normalize (&u);
+ }
+ else
+ {
+ /* v = remainder containing additional 53 bits of significand. */
+ do_add (&v, r, &u, 1);
+ round_for_format (&ieee_double_format, &v);
+ }
-static void
-asctoe64 (s, y)
- const char *s;
- UEMUSHORT *y;
-{
- asctoeg (s, y, 64);
-}
+ round_for_format (&ieee_double_format, &u);
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
-/* Convert ASCII string S to 128-bit long double Y. */
+ encode_ieee_double (&ieee_double_format, &buf[0], &u);
+ encode_ieee_double (&ieee_double_format, &buf[2], &v);
+ break;
-static void
-asctoe113 (s, y)
- const char *s;
- UEMUSHORT *y;
-{
- asctoeg (s, y, 113);
+ default:
+ abort ();
+ }
}
-#endif
-
-/* Convert ASCII string S to e type Y. */
static void
-asctoe (s, y)
- const char *s;
- UEMUSHORT *y;
+decode_ibm_extended (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- asctoeg (s, y, NBITS);
+ REAL_VALUE_TYPE u, v;
+
+ decode_ieee_double (&ieee_double_format, &u, &buf[0]);
+
+ if (u.class != rvc_zero && u.class != rvc_inf && u.class != rvc_nan)
+ {
+ decode_ieee_double (&ieee_double_format, &v, &buf[2]);
+ do_add (r, &u, &v, 0);
+ }
+ else
+ *r = u;
}
-/* Convert ASCII string SS to e type Y, with a specified rounding precision
- of OPREC bits. BASE is 16 for C99 hexadecimal floating constants. */
+const struct real_format ibm_extended_format =
+ {
+ encode_ibm_extended,
+ decode_ibm_extended,
+ 2,
+ 1,
+ 53 + 53,
+ -1021 + 53,
+ 1024,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+
+/* IEEE quad precision format. */
+
+static void encode_ieee_quad PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_ieee_quad PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
static void
-asctoeg (ss, y, oprec)
- const char *ss;
- UEMUSHORT *y;
- int oprec;
+encode_ieee_quad (fmt, buf, r)
+ const struct real_format *fmt;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT yy[NI], xt[NI], tt[NI];
- int esign, decflg, sgnflg, nexp, exp, prec, lost;
- int i, k, trail, c, rndsav;
- EMULONG lexp;
- UEMUSHORT nsign;
- char *sp, *s, *lstr;
- int base = 10;
-
- /* Copy the input string. */
- lstr = (char *) alloca (strlen (ss) + 1);
-
- while (*ss == ' ') /* skip leading spaces */
- ++ss;
-
- sp = lstr;
- while ((*sp++ = *ss++) != '\0')
- ;
- s = lstr;
+ unsigned long image3, image2, image1, image0, exp;
+ bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
+ REAL_VALUE_TYPE u;
- if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
- {
- base = 16;
- s += 2;
- }
+ image3 = r->sign << 31;
+ image2 = 0;
+ image1 = 0;
+ image0 = 0;
- rndsav = rndprc;
- rndprc = NBITS; /* Set to full precision */
- lost = 0;
- nsign = 0;
- decflg = 0;
- sgnflg = 0;
- nexp = 0;
- exp = 0;
- prec = 0;
- ecleaz (yy);
- trail = 0;
-
- nxtcom:
- k = hex_value (*s);
- if ((k >= 0) && (k < base))
+ rshift_significand (&u, r, SIGNIFICAND_BITS - 113);
+
+ switch (r->class)
{
- /* Ignore leading zeros */
- if ((prec == 0) && (decflg == 0) && (k == 0))
- goto donchr;
- /* Identify and strip trailing zeros after the decimal point. */
- if ((trail == 0) && (decflg != 0))
+ case rvc_zero:
+ break;
+
+ case rvc_inf:
+ if (fmt->has_inf)
+ image3 |= 32767 << 16;
+ else
{
- sp = s;
- while (ISDIGIT (*sp) || (base == 16 && ISXDIGIT (*sp)))
- ++sp;
- /* Check for syntax error */
- c = *sp & CHARMASK;
- if ((base != 10 || ((c != 'e') && (c != 'E')))
- && (base != 16 || ((c != 'p') && (c != 'P')))
- && (c != '\0')
- && (c != '\n') && (c != '\r') && (c != ' ')
- && (c != ','))
- goto unexpected_char_error;
- --sp;
- while (*sp == '0')
- *sp-- = 'z';
- trail = 1;
- if (*s == 'z')
- goto donchr;
+ image3 |= 0x7fffffff;
+ image2 = 0xffffffff;
+ image1 = 0xffffffff;
+ image0 = 0xffffffff;
}
+ break;
- /* If enough digits were given to more than fill up the yy register,
- continuing until overflow into the high guard word yy[2]
- guarantees that there will be a roundoff bit at the top
- of the low guard word after normalization. */
-
- if (yy[2] == 0)
+ case rvc_nan:
+ if (fmt->has_nans)
{
- if (base == 16)
- {
- if (decflg)
- nexp += 4; /* count digits after decimal point */
+ image3 |= 32767 << 16;
- eshup1 (yy); /* multiply current number by 16 */
- eshup1 (yy);
- eshup1 (yy);
- eshup1 (yy);
+ if (HOST_BITS_PER_LONG == 32)
+ {
+ image0 = u.sig[0];
+ image1 = u.sig[1];
+ image2 = u.sig[2];
+ image3 |= u.sig[3] & 0xffff;
}
else
{
- if (decflg)
- nexp += 1; /* count digits after decimal point */
-
- eshup1 (yy); /* multiply current number by 10 */
- emovz (yy, xt);
- eshup1 (xt);
- eshup1 (xt);
- eaddm (xt, yy);
+ image0 = u.sig[0];
+ image1 = image0 >> 31 >> 1;
+ image2 = u.sig[1];
+ image3 |= (image2 >> 31 >> 1) & 0xffff;
+ image0 &= 0xffffffff;
+ image2 &= 0xffffffff;
}
- /* Insert the current digit. */
- ecleaz (xt);
- xt[NI - 2] = (UEMUSHORT) k;
- eaddm (xt, yy);
+
+ if (!fmt->qnan_msb_set)
+ image3 ^= 1 << 15 | 1 << 14;
}
else
{
- /* Mark any lost non-zero digit. */
- lost |= k;
- /* Count lost digits before the decimal point. */
- if (decflg == 0)
- {
- if (base == 10)
- nexp -= 1;
- else
- nexp -= 4;
- }
+ image3 |= 0x7fffffff;
+ image2 = 0xffffffff;
+ image1 = 0xffffffff;
+ image0 = 0xffffffff;
}
- prec += 1;
- goto donchr;
- }
-
- switch (*s)
- {
- case 'z':
- break;
- case 'E':
- case 'e':
- case 'P':
- case 'p':
- goto expnt;
- case '.': /* decimal point */
- if (decflg)
- goto unexpected_char_error;
- ++decflg;
- break;
- case '-':
- nsign = 0xffff;
- if (sgnflg)
- goto unexpected_char_error;
- ++sgnflg;
break;
- case '+':
- if (sgnflg)
- goto unexpected_char_error;
- ++sgnflg;
- break;
- case ',':
- case ' ':
- case '\0':
- case '\n':
- case '\r':
- goto daldone;
- case 'i':
- case 'I':
- goto infinite;
- default:
- unexpected_char_error:
-#ifdef NANS
- einan (yy);
-#else
- mtherr ("asctoe", DOMAIN);
- eclear (yy);
-#endif
- goto aexit;
- }
- donchr:
- ++s;
- goto nxtcom;
-
- /* Exponent interpretation */
- expnt:
- /* 0.0eXXX is zero, regardless of XXX. Check for the 0.0. */
- for (k = 0; k < NI; k++)
- {
- if (yy[k] != 0)
- goto read_expnt;
- }
- goto aexit;
-
-read_expnt:
- esign = 1;
- exp = 0;
- ++s;
- /* check for + or - */
- if (*s == '-')
- {
- esign = -1;
- ++s;
- }
- if (*s == '+')
- ++s;
- while (ISDIGIT (*s))
- {
- exp *= 10;
- exp += *s++ - '0';
- if (exp > 999999)
- break;
- }
- if (esign < 0)
- exp = -exp;
- if ((exp > MAXDECEXP) && (base == 10))
- {
- infinite:
- ecleaz (yy);
- yy[E] = 0x7fff; /* infinity */
- goto aexit;
- }
- if ((exp < MINDECEXP) && (base == 10))
- {
- zero:
- ecleaz (yy);
- goto aexit;
- }
- daldone:
- if (base == 16)
- {
- /* Base 16 hexadecimal floating constant. */
- if ((k = enormlz (yy)) > NBITS)
+ case rvc_normal:
+ /* Recall that IEEE numbers are interpreted as 1.F x 2**exp,
+ whereas the intermediate representation is 0.F x 2**exp.
+ Which means we're off by one. */
+ if (denormal)
+ exp = 0;
+ else
+ exp = r->exp + 16383 - 1;
+ image3 |= exp << 16;
+
+ if (HOST_BITS_PER_LONG == 32)
{
- ecleaz (yy);
- goto aexit;
+ image0 = u.sig[0];
+ image1 = u.sig[1];
+ image2 = u.sig[2];
+ image3 |= u.sig[3] & 0xffff;
}
- /* Adjust the exponent. NEXP is the number of hex digits,
- EXP is a power of 2. */
- lexp = (EXONE - 1 + NBITS) - k + yy[E] + exp - nexp;
- if (lexp > 0x7fff)
- goto infinite;
- if (lexp < 0)
- goto zero;
- yy[E] = lexp;
- goto expdon;
- }
+ else
+ {
+ image0 = u.sig[0];
+ image1 = image0 >> 31 >> 1;
+ image2 = u.sig[1];
+ image3 |= (image2 >> 31 >> 1) & 0xffff;
+ image0 &= 0xffffffff;
+ image2 &= 0xffffffff;
+ }
+ break;
- nexp = exp - nexp;
- /* Pad trailing zeros to minimize power of 10, per IEEE spec. */
- while ((nexp > 0) && (yy[2] == 0))
- {
- emovz (yy, xt);
- eshup1 (xt);
- eshup1 (xt);
- eaddm (yy, xt);
- eshup1 (xt);
- if (xt[2] != 0)
- break;
- nexp -= 1;
- emovz (xt, yy);
- }
- if ((k = enormlz (yy)) > NBITS)
- {
- ecleaz (yy);
- goto aexit;
+ default:
+ abort ();
}
- lexp = (EXONE - 1 + NBITS) - k;
- emdnorm (yy, lost, 0, lexp, 64);
- lost = 0;
-
- /* Convert to external format:
- Multiply by 10**nexp. If precision is 64 bits,
- the maximum relative error incurred in forming 10**n
- for 0 <= n <= 324 is 8.2e-20, at 10**180.
- For 0 <= n <= 999, the peak relative error is 1.4e-19 at 10**947.
- For 0 >= n >= -999, it is -1.55e-19 at 10**-435. */
-
- lexp = yy[E];
- if (nexp == 0)
- {
- k = 0;
- goto expdon;
- }
- esign = 1;
- if (nexp < 0)
+ if (FLOAT_WORDS_BIG_ENDIAN)
{
- nexp = -nexp;
- esign = -1;
- if (nexp > 4096)
- {
- /* Punt. Can't handle this without 2 divides. */
- emovi (etens[0], tt);
- lexp -= tt[E];
- k = edivm (tt, yy);
- lexp += EXONE;
- nexp -= 4096;
- }
+ buf[0] = image3;
+ buf[1] = image2;
+ buf[2] = image1;
+ buf[3] = image0;
}
- emov (eone, xt);
- exp = 1;
- i = NTEN;
- do
+ else
{
- if (exp & nexp)
- emul (etens[i], xt, xt);
- i--;
- exp = exp + exp;
+ buf[0] = image0;
+ buf[1] = image1;
+ buf[2] = image2;
+ buf[3] = image3;
}
- while (exp <= MAXP);
+}
- emovi (xt, tt);
- if (esign < 0)
+static void
+decode_ieee_quad (fmt, r, buf)
+ const struct real_format *fmt;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
+{
+ unsigned long image3, image2, image1, image0;
+ bool sign;
+ int exp;
+
+ if (FLOAT_WORDS_BIG_ENDIAN)
{
- lexp -= tt[E];
- k = edivm (tt, yy);
- lexp += EXONE;
+ image3 = buf[0];
+ image2 = buf[1];
+ image1 = buf[2];
+ image0 = buf[3];
}
else
{
- lexp += tt[E];
- k = emulm (tt, yy);
- lexp -= EXONE - 1;
+ image0 = buf[0];
+ image1 = buf[1];
+ image2 = buf[2];
+ image3 = buf[3];
}
- lost = k;
-
- expdon:
-
- /* Round and convert directly to the destination type */
- if (oprec == 53)
- lexp -= EXONE - 0x3ff;
-#ifdef C4X
- else if (oprec == 24 || oprec == 32)
- lexp -= (EXONE - 0x7f);
-#else
-#ifdef IBM
- else if (oprec == 24 || oprec == 56)
- lexp -= EXONE - (0x41 << 2);
-#else
- else if (oprec == 24)
- lexp -= EXONE - 0177;
-#endif /* IBM */
-#endif /* C4X */
-#ifdef DEC
- else if (oprec == 56)
- lexp -= EXONE - 0201;
-#endif
- rndprc = oprec;
- emdnorm (yy, lost, 0, lexp, 64);
+ image0 &= 0xffffffff;
+ image1 &= 0xffffffff;
+ image2 &= 0xffffffff;
- aexit:
+ sign = (image3 >> 31) & 1;
+ exp = (image3 >> 16) & 0x7fff;
+ image3 &= 0xffff;
- rndprc = rndsav;
- yy[0] = nsign;
- switch (oprec)
- {
-#ifdef DEC
- case 56:
- todec (yy, y); /* see etodec.c */
- break;
-#endif
-#ifdef IBM
- case 56:
- toibm (yy, y, DFmode);
- break;
-#endif
-#ifdef C4X
- case 32:
- toc4x (yy, y, HFmode);
- break;
-#endif
-
- case 53:
- toe53 (yy, y);
- break;
- case 24:
- toe24 (yy, y);
- break;
- case 64:
- toe64 (yy, y);
- break;
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
- case 113:
- toe113 (yy, y);
- break;
-#endif
- case NBITS:
- emovo (yy, y);
- break;
- }
-}
+ memset (r, 0, sizeof (*r));
+ if (exp == 0)
+ {
+ if ((image3 | image2 | image1 | image0) && fmt->has_denorm)
+ {
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = -16382 + (SIGNIFICAND_BITS - 112);
+ if (HOST_BITS_PER_LONG == 32)
+ {
+ r->sig[0] = image0;
+ r->sig[1] = image1;
+ r->sig[2] = image2;
+ r->sig[3] = image3;
+ }
+ else
+ {
+ r->sig[0] = (image1 << 31 << 1) | image0;
+ r->sig[1] = (image3 << 31 << 1) | image2;
+ }
-/* Return Y = largest integer not greater than X (truncated toward minus
- infinity). */
+ normalize (r);
+ }
+ else if (fmt->has_signed_zero)
+ r->sign = sign;
+ }
+ else if (exp == 32767 && (fmt->has_nans || fmt->has_inf))
+ {
+ if (image3 | image2 | image1 | image0)
+ {
+ r->class = rvc_nan;
+ r->sign = sign;
-static const UEMUSHORT bmask[] =
-{
- 0xffff,
- 0xfffe,
- 0xfffc,
- 0xfff8,
- 0xfff0,
- 0xffe0,
- 0xffc0,
- 0xff80,
- 0xff00,
- 0xfe00,
- 0xfc00,
- 0xf800,
- 0xf000,
- 0xe000,
- 0xc000,
- 0x8000,
- 0x0000,
-};
+ if (HOST_BITS_PER_LONG == 32)
+ {
+ r->sig[0] = image0;
+ r->sig[1] = image1;
+ r->sig[2] = image2;
+ r->sig[3] = image3;
+ }
+ else
+ {
+ r->sig[0] = (image1 << 31 << 1) | image0;
+ r->sig[1] = (image3 << 31 << 1) | image2;
+ }
+ lshift_significand (r, r, SIGNIFICAND_BITS - 113);
-static void
-efloor (x, y)
- const UEMUSHORT x[];
- UEMUSHORT y[];
-{
- UEMUSHORT *p;
- int e, expon, i;
- UEMUSHORT f[NE];
-
- emov (x, f); /* leave in external format */
- expon = (int) f[NE - 1];
- e = (expon & 0x7fff) - (EXONE - 1);
- if (e <= 0)
- {
- eclear (y);
- goto isitneg;
+ if (!fmt->qnan_msb_set)
+ r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
+ }
+ else
+ {
+ r->class = rvc_inf;
+ r->sign = sign;
+ }
}
- /* number of bits to clear out */
- e = NBITS - e;
- emov (f, y);
- if (e <= 0)
- return;
-
- p = &y[0];
- while (e >= 16)
+ else
{
- *p++ = 0;
- e -= 16;
- }
- /* clear the remaining bits */
- *p &= bmask[e];
- /* truncate negatives toward minus infinity */
- isitneg:
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp - 16383 + 1;
- if ((UEMUSHORT) expon & (UEMUSHORT) 0x8000)
- {
- for (i = 0; i < NE - 1; i++)
+ if (HOST_BITS_PER_LONG == 32)
{
- if (f[i] != y[i])
- {
- esub (eone, y, y);
- break;
- }
+ r->sig[0] = image0;
+ r->sig[1] = image1;
+ r->sig[2] = image2;
+ r->sig[3] = image3;
+ }
+ else
+ {
+ r->sig[0] = (image1 << 31 << 1) | image0;
+ r->sig[1] = (image3 << 31 << 1) | image2;
}
+ lshift_significand (r, r, SIGNIFICAND_BITS - 113);
+ r->sig[SIGSZ-1] |= SIG_MSB;
}
}
-
-#if 0
-/* Return S and EXP such that S * 2^EXP = X and .5 <= S < 1.
- For example, 1.1 = 0.55 * 2^1. */
+const struct real_format ieee_quad_format =
+ {
+ encode_ieee_quad,
+ decode_ieee_quad,
+ 2,
+ 1,
+ 113,
+ -16381,
+ 16384,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+/* Descriptions of VAX floating point formats can be found beginning at
+
+ http://www.openvms.compaq.com:8000/73final/4515/4515pro_013.html#f_floating_point_format
+
+ The thing to remember is that they're almost IEEE, except for word
+ order, exponent bias, and the lack of infinities, nans, and denormals.
+
+ We don't implement the H_floating format here, simply because neither
+ the VAX or Alpha ports use it. */
+
+static void encode_vax_f PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_vax_f PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
+static void encode_vax_d PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_vax_d PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
+static void encode_vax_g PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_vax_g PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
static void
-efrexp (x, exp, s)
- const UEMUSHORT x[];
- int *exp;
- UEMUSHORT s[];
+encode_vax_f (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT xi[NI];
- EMULONG li;
+ unsigned long sign, exp, sig, image;
- emovi (x, xi);
- /* Handle denormalized numbers properly using long integer exponent. */
- li = (EMULONG) ((EMUSHORT) xi[1]);
+ sign = r->sign << 15;
- if (li == 0)
+ switch (r->class)
{
- li -= enormlz (xi);
- }
- xi[1] = 0x3ffe;
- emovo (xi, s);
- *exp = (int) (li - 0x3ffe);
-}
-#endif
+ case rvc_zero:
+ image = 0;
+ break;
-/* Return e type Y = X * 2^PWR2. */
+ case rvc_inf:
+ case rvc_nan:
+ image = 0xffff7fff | sign;
+ break;
-static void
-eldexp (x, pwr2, y)
- const UEMUSHORT x[];
- int pwr2;
- UEMUSHORT y[];
-{
- UEMUSHORT xi[NI];
- EMULONG li;
- int i;
+ case rvc_normal:
+ sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
+ exp = r->exp + 128;
- emovi (x, xi);
- li = xi[1];
- li += pwr2;
- i = 0;
- emdnorm (xi, i, i, li, 64);
- emovo (xi, y);
-}
+ image = (sig << 16) & 0xffff0000;
+ image |= sign;
+ image |= exp << 7;
+ image |= sig >> 16;
+ break;
+ default:
+ abort ();
+ }
-#if 0
-/* C = remainder after dividing B by A, all e type values.
- Least significant integer quotient bits left in EQUOT. */
+ buf[0] = image;
+}
static void
-eremain (a, b, c)
- const UEMUSHORT a[], b[];
- UEMUSHORT c[];
+decode_vax_f (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- UEMUSHORT den[NI], num[NI];
+ unsigned long image = buf[0] & 0xffffffff;
+ int exp = (image >> 7) & 0xff;
-#ifdef NANS
- if (eisinf (b)
- || (ecmp (a, ezero) == 0)
- || eisnan (a)
- || eisnan (b))
- {
- enan (c, 0);
- return;
- }
-#endif
- if (ecmp (a, ezero) == 0)
+ memset (r, 0, sizeof (*r));
+
+ if (exp != 0)
{
- mtherr ("eremain", SING);
- eclear (c);
- return;
+ r->class = rvc_normal;
+ r->sign = (image >> 15) & 1;
+ r->exp = exp - 128;
+
+ image = ((image & 0x7f) << 16) | ((image >> 16) & 0xffff);
+ r->sig[SIGSZ-1] = (image << (HOST_BITS_PER_LONG - 24)) | SIG_MSB;
}
- emovi (a, den);
- emovi (b, num);
- eiremain (den, num);
- /* Sign of remainder = sign of quotient */
- if (a[0] == b[0])
- num[0] = 0;
- else
- num[0] = 0xffff;
- emovo (num, c);
}
-#endif
-
-/* Return quotient of exploded e-types NUM / DEN in EQUOT,
- remainder in NUM. */
static void
-eiremain (den, num)
- UEMUSHORT den[], num[];
+encode_vax_d (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- EMULONG ld, ln;
- UEMUSHORT j;
-
- ld = den[E];
- ld -= enormlz (den);
- ln = num[E];
- ln -= enormlz (num);
- ecleaz (equot);
- while (ln >= ld)
+ unsigned long image0, image1, sign = r->sign << 15;
+
+ switch (r->class)
{
- if (ecmpm (den, num) <= 0)
+ case rvc_zero:
+ image0 = image1 = 0;
+ break;
+
+ case rvc_inf:
+ case rvc_nan:
+ image0 = 0xffff7fff | sign;
+ image1 = 0xffffffff;
+ break;
+
+ case rvc_normal:
+ /* Extract the significand into straight hi:lo. */
+ if (HOST_BITS_PER_LONG == 64)
{
- esubm (den, num);
- j = 1;
+ image0 = r->sig[SIGSZ-1];
+ image1 = (image0 >> (64 - 56)) & 0xffffffff;
+ image0 = (image0 >> (64 - 56 + 1) >> 31) & 0x7fffff;
}
else
- j = 0;
- eshup1 (equot);
- equot[NI - 1] |= j;
- eshup1 (num);
- ln -= 1;
- }
- emdnorm (num, 0, 0, ln, 0);
-}
-
-/* Report an error condition CODE encountered in function NAME.
-
- Mnemonic Value Significance
-
- DOMAIN 1 argument domain error
- SING 2 function singularity
- OVERFLOW 3 overflow range error
- UNDERFLOW 4 underflow range error
- TLOSS 5 total loss of precision
- PLOSS 6 partial loss of precision
- INVALID 7 NaN - producing operation
- EDOM 33 Unix domain error code
- ERANGE 34 Unix range error code
-
- The order of appearance of the following messages is bound to the
- error codes defined above. */
-
-int merror = 0;
-extern int merror;
-
-static void
-mtherr (name, code)
- const char *name;
- int code;
-{
- /* The string passed by the calling program is supposed to be the
- name of the function in which the error occurred.
- The code argument selects which error message string will be printed. */
-
- if (strcmp (name, "esub") == 0)
- name = "subtraction";
- else if (strcmp (name, "ediv") == 0)
- name = "division";
- else if (strcmp (name, "emul") == 0)
- name = "multiplication";
- else if (strcmp (name, "enormlz") == 0)
- name = "normalization";
- else if (strcmp (name, "etoasc") == 0)
- name = "conversion to text";
- else if (strcmp (name, "asctoe") == 0)
- name = "parsing";
- else if (strcmp (name, "eremain") == 0)
- name = "modulus";
- else if (strcmp (name, "esqrt") == 0)
- name = "square root";
- if (extra_warnings)
- {
- switch (code)
{
- case DOMAIN: warning ("%s: argument domain error" , name); break;
- case SING: warning ("%s: function singularity" , name); break;
- case OVERFLOW: warning ("%s: overflow range error" , name); break;
- case UNDERFLOW: warning ("%s: underflow range error" , name); break;
- case TLOSS: warning ("%s: total loss of precision" , name); break;
- case PLOSS: warning ("%s: partial loss of precision", name); break;
- case INVALID: warning ("%s: NaN - producing operation", name); break;
- default: abort ();
+ image0 = r->sig[SIGSZ-1];
+ image1 = r->sig[SIGSZ-2];
+ image1 = (image0 << 24) | (image1 >> 8);
+ image0 = (image0 >> 8) & 0xffffff;
}
- }
-
- /* Set global error message word */
- merror = code + 1;
-}
-
-#ifdef DEC
-/* Convert DEC double precision D to e type E. */
-
-static void
-dectoe (d, e)
- const UEMUSHORT *d;
- UEMUSHORT *e;
-{
- UEMUSHORT y[NI];
- UEMUSHORT r, *p;
-
- ecleaz (y); /* start with a zero */
- p = y; /* point to our number */
- r = *d; /* get DEC exponent word */
- if (*d & (unsigned int) 0x8000)
- *p = 0xffff; /* fill in our sign */
- ++p; /* bump pointer to our exponent word */
- r &= 0x7fff; /* strip the sign bit */
- if (r == 0) /* answer = 0 if high order DEC word = 0 */
- goto done;
-
-
- r >>= 7; /* shift exponent word down 7 bits */
- r += EXONE - 0201; /* subtract DEC exponent offset */
- /* add our e type exponent offset */
- *p++ = r; /* to form our exponent */
-
- r = *d++; /* now do the high order mantissa */
- r &= 0177; /* strip off the DEC exponent and sign bits */
- r |= 0200; /* the DEC understood high order mantissa bit */
- *p++ = r; /* put result in our high guard word */
-
- *p++ = *d++; /* fill in the rest of our mantissa */
- *p++ = *d++;
- *p = *d;
-
- eshdn8 (y); /* shift our mantissa down 8 bits */
- done:
- emovo (y, e);
-}
-
-/* Convert e type X to DEC double precision D. */
-static void
-etodec (x, d)
- const UEMUSHORT *x;
- UEMUSHORT *d;
-{
- UEMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
-
- emovi (x, xi);
- /* Adjust exponent for offsets. */
- exp = (EMULONG) xi[E] - (EXONE - 0201);
- /* Round off to nearest or even. */
- rndsav = rndprc;
- rndprc = 56;
- emdnorm (xi, 0, 0, exp, 64);
- rndprc = rndsav;
- todec (xi, d);
-}
+ /* Rearrange the half-words of the significand to match the
+ external format. */
+ image0 = ((image0 << 16) | (image0 >> 16)) & 0xffff007f;
+ image1 = ((image1 << 16) | (image1 >> 16)) & 0xffffffff;
-/* Convert exploded e-type X, that has already been rounded to
- 56-bit precision, to DEC format double Y. */
+ /* Add the sign and exponent. */
+ image0 |= sign;
+ image0 |= (r->exp + 128) << 7;
+ break;
-static void
-todec (x, y)
- UEMUSHORT *x, *y;
-{
- UEMUSHORT i;
- UEMUSHORT *p;
-
- p = x;
- *y = 0;
- if (*p++)
- *y = 0100000;
- i = *p++;
- if (i == 0)
- {
- *y++ = 0;
- *y++ = 0;
- *y++ = 0;
- *y++ = 0;
- return;
- }
- if (i > 0377)
- {
- *y++ |= 077777;
- *y++ = 0xffff;
- *y++ = 0xffff;
- *y++ = 0xffff;
-#ifdef ERANGE
- errno = ERANGE;
-#endif
- return;
+ default:
+ abort ();
}
- i &= 0377;
- i <<= 7;
- eshup8 (x);
- x[M] &= 0177;
- i |= x[M];
- *y++ |= i;
- *y++ = x[M + 1];
- *y++ = x[M + 2];
- *y++ = x[M + 3];
-}
-#endif /* DEC */
-#ifdef IBM
-/* Convert IBM single/double precision to e type. */
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = image1, buf[1] = image0;
+ else
+ buf[0] = image0, buf[1] = image1;
+}
static void
-ibmtoe (d, e, mode)
- const UEMUSHORT *d;
- UEMUSHORT *e;
- enum machine_mode mode;
+decode_vax_d (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- UEMUSHORT y[NI];
- UEMUSHORT r, *p;
-
- ecleaz (y); /* start with a zero */
- p = y; /* point to our number */
- r = *d; /* get IBM exponent word */
- if (*d & (unsigned int) 0x8000)
- *p = 0xffff; /* fill in our sign */
- ++p; /* bump pointer to our exponent word */
- r &= 0x7f00; /* strip the sign bit */
- r >>= 6; /* shift exponent word down 6 bits */
- /* in fact shift by 8 right and 2 left */
- r += EXONE - (0x41 << 2); /* subtract IBM exponent offset */
- /* add our e type exponent offset */
- *p++ = r; /* to form our exponent */
-
- *p++ = *d++ & 0xff; /* now do the high order mantissa */
- /* strip off the IBM exponent and sign bits */
- if (mode != SFmode) /* there are only 2 words in SFmode */
- {
- *p++ = *d++; /* fill in the rest of our mantissa */
- *p++ = *d++;
- }
- *p = *d;
+ unsigned long image0, image1;
+ int exp;
- if (y[M] == 0 && y[M+1] == 0 && y[M+2] == 0 && y[M+3] == 0)
- y[0] = y[E] = 0;
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ image1 = buf[0], image0 = buf[1];
else
- y[E] -= 5 + enormlz (y); /* now normalise the mantissa */
- /* handle change in RADIX */
- emovo (y, e);
-}
+ image0 = buf[0], image1 = buf[1];
+ image0 &= 0xffffffff;
+ image1 &= 0xffffffff;
+ exp = (image0 >> 7) & 0x7f;
+ memset (r, 0, sizeof (*r));
-/* Convert e type to IBM single/double precision. */
+ if (exp != 0)
+ {
+ r->class = rvc_normal;
+ r->sign = (image0 >> 15) & 1;
+ r->exp = exp - 128;
-static void
-etoibm (x, d, mode)
- const UEMUSHORT *x;
- UEMUSHORT *d;
- enum machine_mode mode;
-{
- UEMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
-
- emovi (x, xi);
- exp = (EMULONG) xi[E] - (EXONE - (0x41 << 2)); /* adjust exponent for offsets */
- /* round off to nearest or even */
- rndsav = rndprc;
- rndprc = 56;
- emdnorm (xi, 0, 0, exp, 64);
- rndprc = rndsav;
- toibm (xi, d, mode);
-}
+ /* Rearrange the half-words of the external format into
+ proper ascending order. */
+ image0 = ((image0 & 0x7f) << 16) | ((image0 >> 16) & 0xffff);
+ image1 = ((image1 & 0xffff) << 16) | ((image1 >> 16) & 0xffff);
-static void
-toibm (x, y, mode)
- UEMUSHORT *x, *y;
- enum machine_mode mode;
-{
- UEMUSHORT i;
- UEMUSHORT *p;
- int r;
-
- p = x;
- *y = 0;
- if (*p++)
- *y = 0x8000;
- i = *p++;
- if (i == 0)
- {
- *y++ = 0;
- *y++ = 0;
- if (mode != SFmode)
+ if (HOST_BITS_PER_LONG == 64)
{
- *y++ = 0;
- *y++ = 0;
+ image0 = (image0 << 31 << 1) | image1;
+ image0 <<= 64 - 56;
+ image0 |= SIG_MSB;
+ r->sig[SIGSZ-1] = image0;
}
- return;
- }
- r = i & 0x3;
- i >>= 2;
- if (i > 0x7f)
- {
- *y++ |= 0x7fff;
- *y++ = 0xffff;
- if (mode != SFmode)
+ else
{
- *y++ = 0xffff;
- *y++ = 0xffff;
+ r->sig[SIGSZ-1] = image0;
+ r->sig[SIGSZ-2] = image1;
+ lshift_significand (r, r, 2*HOST_BITS_PER_LONG - 56);
+ r->sig[SIGSZ-1] |= SIG_MSB;
}
-#ifdef ERANGE
- errno = ERANGE;
-#endif
- return;
- }
- i &= 0x7f;
- *y |= (i << 8);
- eshift (x, r + 5);
- *y++ |= x[M];
- *y++ = x[M + 1];
- if (mode != SFmode)
- {
- *y++ = x[M + 2];
- *y++ = x[M + 3];
}
}
-#endif /* IBM */
-
-
-#ifdef C4X
-/* Convert C4X single/double precision to e type. */
static void
-c4xtoe (d, e, mode)
- const UEMUSHORT *d;
- UEMUSHORT *e;
- enum machine_mode mode;
+encode_vax_g (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT y[NI];
- UEMUSHORT dn[4];
- int r;
- int isnegative;
- int size;
- int i;
- int carry;
+ unsigned long image0, image1, sign = r->sign << 15;
- dn[0] = d[0];
- dn[1] = d[1];
- if (mode != QFmode)
+ switch (r->class)
{
- dn[2] = d[3] << 8;
- dn[3] = 0;
- }
-
- /* Short-circuit the zero case. */
- if ((dn[0] == 0x8000)
- && (dn[1] == 0x0000)
- && ((mode == QFmode) || ((dn[2] == 0x0000) && (dn[3] == 0x0000))))
- {
- e[0] = 0;
- e[1] = 0;
- e[2] = 0;
- e[3] = 0;
- e[4] = 0;
- e[5] = 0;
- return;
- }
-
- ecleaz (y); /* start with a zero */
- r = dn[0]; /* get sign/exponent part */
- if (r & (unsigned int) 0x0080)
- {
- y[0] = 0xffff; /* fill in our sign */
- isnegative = TRUE;
- }
- else
- isnegative = FALSE;
+ case rvc_zero:
+ image0 = image1 = 0;
+ break;
- r >>= 8; /* Shift exponent word down 8 bits. */
- if (r & 0x80) /* Make the exponent negative if it is. */
- r = r | (~0 & ~0xff);
+ case rvc_inf:
+ case rvc_nan:
+ image0 = 0xffff7fff | sign;
+ image1 = 0xffffffff;
+ break;
- if (isnegative)
- {
- /* Now do the high order mantissa. We don't "or" on the high bit
- because it is 2 (not 1) and is handled a little differently
- below. */
- y[M] = dn[0] & 0x7f;
-
- y[M+1] = dn[1];
- if (mode != QFmode) /* There are only 2 words in QFmode. */
- {
- y[M+2] = dn[2]; /* Fill in the rest of our mantissa. */
- y[M+3] = dn[3];
- size = 4;
- }
+ case rvc_normal:
+ /* Extract the significand into straight hi:lo. */
+ if (HOST_BITS_PER_LONG == 64)
+ {
+ image0 = r->sig[SIGSZ-1];
+ image1 = (image0 >> (64 - 53)) & 0xffffffff;
+ image0 = (image0 >> (64 - 53 + 1) >> 31) & 0xfffff;
+ }
else
- size = 2;
- eshift (y, -8);
+ {
+ image0 = r->sig[SIGSZ-1];
+ image1 = r->sig[SIGSZ-2];
+ image1 = (image0 << 21) | (image1 >> 11);
+ image0 = (image0 >> 11) & 0xfffff;
+ }
- /* Now do the two's complement on the data. */
+ /* Rearrange the half-words of the significand to match the
+ external format. */
+ image0 = ((image0 << 16) | (image0 >> 16)) & 0xffff000f;
+ image1 = ((image1 << 16) | (image1 >> 16)) & 0xffffffff;
- carry = 1; /* Initially add 1 for the two's complement. */
- for (i=size + M; i > M; i--)
- {
- if (carry && (y[i] == 0x0000))
- /* We overflowed into the next word, carry is the same. */
- y[i] = carry ? 0x0000 : 0xffff;
- else
- {
- /* No overflow, just invert and add carry. */
- y[i] = ((~y[i]) + carry) & 0xffff;
- carry = 0;
- }
- }
+ /* Add the sign and exponent. */
+ image0 |= sign;
+ image0 |= (r->exp + 1024) << 4;
+ break;
- if (carry)
- {
- eshift (y, -1);
- y[M+1] |= 0x8000;
- r++;
- }
- y[1] = r + EXONE;
- }
- else
- {
- /* Add our e type exponent offset to form our exponent. */
- r += EXONE;
- y[1] = r;
-
- /* Now do the high order mantissa strip off the exponent and sign
- bits and add the high 1 bit. */
- y[M] = (dn[0] & 0x7f) | 0x80;
-
- y[M+1] = dn[1];
- if (mode != QFmode) /* There are only 2 words in QFmode. */
- {
- y[M+2] = dn[2]; /* Fill in the rest of our mantissa. */
- y[M+3] = dn[3];
- }
- eshift (y, -8);
+ default:
+ abort ();
}
- emovo (y, e);
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = image1, buf[1] = image0;
+ else
+ buf[0] = image0, buf[1] = image1;
}
-
-/* Convert e type to C4X single/double precision. */
-
static void
-etoc4x (x, d, mode)
- const UEMUSHORT *x;
- UEMUSHORT *d;
- enum machine_mode mode;
+decode_vax_g (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- UEMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
-
- emovi (x, xi);
+ unsigned long image0, image1;
+ int exp;
- /* Adjust exponent for offsets. */
- exp = (EMULONG) xi[E] - (EXONE - 0x7f);
-
- /* Round off to nearest or even. */
- rndsav = rndprc;
- rndprc = mode == QFmode ? 24 : 32;
- emdnorm (xi, 0, 0, exp, 64);
- rndprc = rndsav;
- toc4x (xi, d, mode);
-}
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ image1 = buf[0], image0 = buf[1];
+ else
+ image0 = buf[0], image1 = buf[1];
+ image0 &= 0xffffffff;
+ image1 &= 0xffffffff;
-static void
-toc4x (x, y, mode)
- UEMUSHORT *x, *y;
- enum machine_mode mode;
-{
- int i;
- int v;
- int carry;
-
- /* Short-circuit the zero case */
- if ((x[0] == 0) /* Zero exponent and sign */
- && (x[1] == 0)
- && (x[M] == 0) /* The rest is for zero mantissa */
- && (x[M+1] == 0)
- /* Only check for double if necessary */
- && ((mode == QFmode) || ((x[M+2] == 0) && (x[M+3] == 0))))
- {
- /* We have a zero. Put it into the output and return. */
- *y++ = 0x8000;
- *y++ = 0x0000;
- if (mode != QFmode)
- {
- *y++ = 0x0000;
- *y++ = 0x0000;
- }
- return;
- }
+ exp = (image0 >> 4) & 0x7ff;
- *y = 0;
+ memset (r, 0, sizeof (*r));
- /* Negative number require a two's complement conversion of the
- mantissa. */
- if (x[0])
+ if (exp != 0)
{
- *y = 0x0080;
+ r->class = rvc_normal;
+ r->sign = (image0 >> 15) & 1;
+ r->exp = exp - 1024;
- i = ((int) x[1]) - 0x7f;
+ /* Rearrange the half-words of the external format into
+ proper ascending order. */
+ image0 = ((image0 & 0xf) << 16) | ((image0 >> 16) & 0xffff);
+ image1 = ((image1 & 0xffff) << 16) | ((image1 >> 16) & 0xffff);
- /* Now add 1 to the inverted data to do the two's complement. */
- if (mode != QFmode)
- v = 4 + M;
- else
- v = 2 + M;
- carry = 1;
- while (v > M)
+ if (HOST_BITS_PER_LONG == 64)
{
- if (x[v] == 0x0000)
- x[v] = carry ? 0x0000 : 0xffff;
- else
- {
- x[v] = ((~x[v]) + carry) & 0xffff;
- carry = 0;
- }
- v--;
+ image0 = (image0 << 31 << 1) | image1;
+ image0 <<= 64 - 53;
+ image0 |= SIG_MSB;
+ r->sig[SIGSZ-1] = image0;
}
-
- /* The following is a special case. The C4X negative float requires
- a zero in the high bit (because the format is (2 - x) x 2^m), so
- if a one is in that bit, we have to shift left one to get rid
- of it. This only occurs if the number is -1 x 2^m. */
- if (x[M+1] & 0x8000)
+ else
{
- /* This is the case of -1 x 2^m, we have to rid ourselves of the
- high sign bit and shift the exponent. */
- eshift (x, 1);
- i--;
+ r->sig[SIGSZ-1] = image0;
+ r->sig[SIGSZ-2] = image1;
+ lshift_significand (r, r, 64 - 53);
+ r->sig[SIGSZ-1] |= SIG_MSB;
}
}
- else
- i = ((int) x[1]) - 0x7f;
+}
- if ((i < -128) || (i > 127))
- {
- y[0] |= 0xff7f;
- y[1] = 0xffff;
- if (mode != QFmode)
- {
- y[2] = 0xffff;
- y[3] = 0xffff;
- y[3] = (y[1] << 8) | ((y[2] >> 8) & 0xff);
- y[2] = (y[0] << 8) | ((y[1] >> 8) & 0xff);
- }
-#ifdef ERANGE
- errno = ERANGE;
-#endif
- return;
- }
+const struct real_format vax_f_format =
+ {
+ encode_vax_f,
+ decode_vax_f,
+ 2,
+ 1,
+ 24,
+ -127,
+ 127,
+ false,
+ false,
+ false,
+ false,
+ false
+ };
+
+const struct real_format vax_d_format =
+ {
+ encode_vax_d,
+ decode_vax_d,
+ 2,
+ 1,
+ 56,
+ -127,
+ 127,
+ false,
+ false,
+ false,
+ false,
+ false
+ };
+
+const struct real_format vax_g_format =
+ {
+ encode_vax_g,
+ decode_vax_g,
+ 2,
+ 1,
+ 53,
+ -1023,
+ 1023,
+ false,
+ false,
+ false,
+ false,
+ false
+ };
+
+/* A good reference for these can be found in chapter 9 of
+ "ESA/390 Principles of Operation", IBM document number SA22-7201-01.
+ An on-line version can be found here:
+
+ http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/DZ9AR001/9.1?DT=19930923083613
+*/
+
+static void encode_i370_single PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_i370_single PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
+static void encode_i370_double PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_i370_double PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
- y[0] |= ((i & 0xff) << 8);
+static void
+encode_i370_single (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
+{
+ unsigned long sign, exp, sig, image;
- eshift (x, 8);
+ sign = r->sign << 31;
- y[0] |= x[M] & 0x7f;
- y[1] = x[M + 1];
- if (mode != QFmode)
+ switch (r->class)
{
- y[2] = x[M + 2];
- y[3] = x[M + 3];
- y[3] = (y[1] << 8) | ((y[2] >> 8) & 0xff);
- y[2] = (y[0] << 8) | ((y[1] >> 8) & 0xff);
+ case rvc_zero:
+ image = 0;
+ break;
+
+ case rvc_inf:
+ case rvc_nan:
+ image = 0x7fffffff | sign;
+ break;
+
+ case rvc_normal:
+ sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0xffffff;
+ exp = ((r->exp / 4) + 64) << 24;
+ image = sign | exp | sig;
+ break;
+
+ default:
+ abort ();
}
+
+ buf[0] = image;
}
-#endif /* C4X */
-
-/* Output a binary NaN bit pattern in the target machine's format. */
-
-/* If special NaN bit patterns are required, define them in tm.h
- as arrays of unsigned 16-bit shorts. Otherwise, use the default
- patterns here. */
-#ifdef TFMODE_NAN
-TFMODE_NAN;
-#else
-#ifdef IEEE
-static const UEMUSHORT TFbignan[8] =
- {0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
-static const UEMUSHORT TFlittlenan[8] = {0, 0, 0, 0, 0, 0, 0x8000, 0xffff};
-#endif
-#endif
-#ifdef XFMODE_NAN
-XFMODE_NAN;
-#else
-#ifdef IEEE
-static const UEMUSHORT XFbignan[6] =
- {0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
-static const UEMUSHORT XFlittlenan[6] = {0, 0, 0, 0xc000, 0xffff, 0};
-#endif
-#endif
+static void
+decode_i370_single (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
+{
+ unsigned long sign, sig, image = buf[0];
+ int exp;
-#ifdef DFMODE_NAN
-DFMODE_NAN;
-#else
-#ifdef IEEE
-static const UEMUSHORT DFbignan[4] = {0x7fff, 0xffff, 0xffff, 0xffff};
-static const UEMUSHORT DFlittlenan[4] = {0, 0, 0, 0xfff8};
-#endif
-#endif
+ sign = (image >> 31) & 1;
+ exp = (image >> 24) & 0x7f;
+ sig = image & 0xffffff;
-#ifdef SFMODE_NAN
-SFMODE_NAN;
-#else
-#ifdef IEEE
-static const UEMUSHORT SFbignan[2] = {0x7fff, 0xffff};
-static const UEMUSHORT SFlittlenan[2] = {0, 0xffc0};
-#endif
-#endif
+ memset (r, 0, sizeof (*r));
+ if (exp || sig)
+ {
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = (exp - 64) * 4;
+ r->sig[SIGSZ-1] = sig << (HOST_BITS_PER_LONG - 24);
+ normalize (r);
+ }
+}
-#ifdef NANS
static void
-make_nan (nan, sign, mode)
- UEMUSHORT *nan;
- int sign;
- enum machine_mode mode;
+encode_i370_double (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- int n;
- const UEMUSHORT *p;
+ unsigned long sign, exp, image_hi, image_lo;
+
+ sign = r->sign << 31;
- switch (mode)
+ switch (r->class)
{
-/* Possibly the `reserved operand' patterns on a VAX can be
- used like NaN's, but probably not in the same way as IEEE. */
-#if !defined(DEC) && !defined(IBM) && !defined(C4X)
- case TFmode:
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
- n = 8;
- if (REAL_WORDS_BIG_ENDIAN)
- p = TFbignan;
- else
- p = TFlittlenan;
+ case rvc_zero:
+ image_hi = image_lo = 0;
break;
-#endif
- /* FALLTHRU */
- case XFmode:
- n = 6;
- if (REAL_WORDS_BIG_ENDIAN)
- p = XFbignan;
- else
- p = XFlittlenan;
+ case rvc_inf:
+ case rvc_nan:
+ image_hi = 0x7fffffff | sign;
+ image_lo = 0xffffffff;
break;
- case DFmode:
- n = 4;
- if (REAL_WORDS_BIG_ENDIAN)
- p = DFbignan;
+ case rvc_normal:
+ if (HOST_BITS_PER_LONG == 64)
+ {
+ image_hi = r->sig[SIGSZ-1];
+ image_lo = (image_hi >> (64 - 56)) & 0xffffffff;
+ image_hi = (image_hi >> (64 - 56 + 1) >> 31) & 0xffffff;
+ }
else
- p = DFlittlenan;
- break;
+ {
+ image_hi = r->sig[SIGSZ-1];
+ image_lo = r->sig[SIGSZ-2];
+ image_lo = (image_lo >> 8) | (image_hi << 24);
+ image_hi >>= 8;
+ }
- case SFmode:
- case HFmode:
- n = 2;
- if (REAL_WORDS_BIG_ENDIAN)
- p = SFbignan;
- else
- p = SFlittlenan;
+ exp = ((r->exp / 4) + 64) << 24;
+ image_hi |= sign | exp;
break;
-#endif
default:
abort ();
}
- if (REAL_WORDS_BIG_ENDIAN)
- *nan++ = (sign << 15) | (*p++ & 0x7fff);
- while (--n != 0)
- *nan++ = *p++;
- if (! REAL_WORDS_BIG_ENDIAN)
- *nan = (sign << 15) | (*p & 0x7fff);
-}
-#endif /* NANS */
-/* This is the inverse of the function `etarsingle' invoked by
- REAL_VALUE_TO_TARGET_SINGLE. */
-
-REAL_VALUE_TYPE
-ereal_unto_float (f)
- long f;
-{
- REAL_VALUE_TYPE r;
- UEMUSHORT s[2];
- UEMUSHORT e[NE];
-
- /* Convert 32 bit integer to array of 16 bit pieces in target machine order.
- This is the inverse operation to what the function `endian' does. */
- if (REAL_WORDS_BIG_ENDIAN)
- {
- s[0] = (UEMUSHORT) (f >> 16);
- s[1] = (UEMUSHORT) f;
- }
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = image_hi, buf[1] = image_lo;
else
- {
- s[0] = (UEMUSHORT) f;
- s[1] = (UEMUSHORT) (f >> 16);
- }
- /* Convert and promote the target float to E-type. */
- e24toe (s, e);
- /* Output E-type to REAL_VALUE_TYPE. */
- PUT_REAL (e, &r);
- return r;
+ buf[0] = image_lo, buf[1] = image_hi;
}
-
-/* This is the inverse of the function `etardouble' invoked by
- REAL_VALUE_TO_TARGET_DOUBLE. */
-
-REAL_VALUE_TYPE
-ereal_unto_double (d)
- long d[];
+static void
+decode_i370_double (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- REAL_VALUE_TYPE r;
- UEMUSHORT s[4];
- UEMUSHORT e[NE];
+ unsigned long sign, image_hi, image_lo;
+ int exp;
- /* Convert array of HOST_WIDE_INT to equivalent array of 16-bit pieces. */
- if (REAL_WORDS_BIG_ENDIAN)
- {
- s[0] = (UEMUSHORT) (d[0] >> 16);
- s[1] = (UEMUSHORT) d[0];
- s[2] = (UEMUSHORT) (d[1] >> 16);
- s[3] = (UEMUSHORT) d[1];
- }
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ image_hi = buf[0], image_lo = buf[1];
else
- {
- /* Target float words are little-endian. */
- s[0] = (UEMUSHORT) d[0];
- s[1] = (UEMUSHORT) (d[0] >> 16);
- s[2] = (UEMUSHORT) d[1];
- s[3] = (UEMUSHORT) (d[1] >> 16);
- }
- /* Convert target double to E-type. */
- e53toe (s, e);
- /* Output E-type to REAL_VALUE_TYPE. */
- PUT_REAL (e, &r);
- return r;
-}
-
+ image_lo = buf[0], image_hi = buf[1];
-/* Convert an SFmode target `float' value to a REAL_VALUE_TYPE.
- This is somewhat like ereal_unto_float, but the input types
- for these are different. */
+ sign = (image_hi >> 31) & 1;
+ exp = (image_hi >> 24) & 0x7f;
+ image_hi &= 0xffffff;
+ image_lo &= 0xffffffff;
-REAL_VALUE_TYPE
-ereal_from_float (f)
- HOST_WIDE_INT f;
-{
- REAL_VALUE_TYPE r;
- UEMUSHORT s[2];
- UEMUSHORT e[NE];
+ memset (r, 0, sizeof (*r));
- /* Convert 32 bit integer to array of 16 bit pieces in target machine order.
- This is the inverse operation to what the function `endian' does. */
- if (REAL_WORDS_BIG_ENDIAN)
- {
- s[0] = (UEMUSHORT) (f >> 16);
- s[1] = (UEMUSHORT) f;
- }
- else
+ if (exp || image_hi || image_lo)
{
- s[0] = (UEMUSHORT) f;
- s[1] = (UEMUSHORT) (f >> 16);
- }
- /* Convert and promote the target float to E-type. */
- e24toe (s, e);
- /* Output E-type to REAL_VALUE_TYPE. */
- PUT_REAL (e, &r);
- return r;
-}
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = (exp - 64) * 4 + (SIGNIFICAND_BITS - 56);
+ if (HOST_BITS_PER_LONG == 32)
+ {
+ r->sig[0] = image_lo;
+ r->sig[1] = image_hi;
+ }
+ else
+ r->sig[0] = image_lo | (image_hi << 31 << 1);
-/* Convert a DFmode target `double' value to a REAL_VALUE_TYPE.
- This is somewhat like ereal_unto_double, but the input types
- for these are different.
+ normalize (r);
+ }
+}
- The DFmode is stored as an array of HOST_WIDE_INT in the target's
- data format, with no holes in the bit packing. The first element
- of the input array holds the bits that would come first in the
- target computer's memory. */
+const struct real_format i370_single_format =
+ {
+ encode_i370_single,
+ decode_i370_single,
+ 16,
+ 4,
+ 6,
+ -64,
+ 63,
+ false,
+ false,
+ false, /* ??? The encoding does allow for "unnormals". */
+ false, /* ??? The encoding does allow for "unnormals". */
+ false
+ };
+
+const struct real_format i370_double_format =
+ {
+ encode_i370_double,
+ decode_i370_double,
+ 16,
+ 4,
+ 14,
+ -64,
+ 63,
+ false,
+ false,
+ false, /* ??? The encoding does allow for "unnormals". */
+ false, /* ??? The encoding does allow for "unnormals". */
+ false
+ };
+
+/* The "twos-complement" c4x format is officially defined as
-REAL_VALUE_TYPE
-ereal_from_double (d)
- HOST_WIDE_INT d[];
-{
- REAL_VALUE_TYPE r;
- UEMUSHORT s[4];
- UEMUSHORT e[NE];
+ x = s(~s).f * 2**e
- /* Convert array of HOST_WIDE_INT to equivalent array of 16-bit pieces. */
- if (REAL_WORDS_BIG_ENDIAN)
- {
-#if HOST_BITS_PER_WIDE_INT == 32
- s[0] = (UEMUSHORT) (d[0] >> 16);
- s[1] = (UEMUSHORT) d[0];
- s[2] = (UEMUSHORT) (d[1] >> 16);
- s[3] = (UEMUSHORT) d[1];
-#else
- /* In this case the entire target double is contained in the
- first array element. The second element of the input is
- ignored. */
- s[0] = (UEMUSHORT) (d[0] >> 48);
- s[1] = (UEMUSHORT) (d[0] >> 32);
- s[2] = (UEMUSHORT) (d[0] >> 16);
- s[3] = (UEMUSHORT) d[0];
-#endif
- }
- else
- {
- /* Target float words are little-endian. */
- s[0] = (UEMUSHORT) d[0];
- s[1] = (UEMUSHORT) (d[0] >> 16);
-#if HOST_BITS_PER_WIDE_INT == 32
- s[2] = (UEMUSHORT) d[1];
- s[3] = (UEMUSHORT) (d[1] >> 16);
-#else
- s[2] = (UEMUSHORT) (d[0] >> 32);
- s[3] = (UEMUSHORT) (d[0] >> 48);
-#endif
- }
- /* Convert target double to E-type. */
- e53toe (s, e);
- /* Output E-type to REAL_VALUE_TYPE. */
- PUT_REAL (e, &r);
- return r;
-}
+ This is rather misleading. One must remember that F is signed.
+ A better description would be
+ x = -1**s * ((s + 1 + .f) * 2**e
-#if 0
-/* Convert target computer unsigned 64-bit integer to e-type.
- The endian-ness of DImode follows the convention for integers,
- so we use WORDS_BIG_ENDIAN here, not REAL_WORDS_BIG_ENDIAN. */
+ So if we have a (4 bit) fraction of .1000 with a sign bit of 1,
+ that's -1 * (1+1+(-.5)) == -1.5. I think.
-static void
-uditoe (di, e)
- const UEMUSHORT *di; /* Address of the 64-bit int. */
- UEMUSHORT *e;
-{
- UEMUSHORT yi[NI];
- int k;
+ The constructions here are taken from Tables 5-1 and 5-2 of the
+ TMS320C4x User's Guide wherein step-by-step instructions for
+ conversion from IEEE are presented. That's close enough to our
+ internal representation so as to make things easy.
- ecleaz (yi);
- if (WORDS_BIG_ENDIAN)
- {
- for (k = M; k < M + 4; k++)
- yi[k] = *di++;
- }
- else
- {
- for (k = M + 3; k >= M; k--)
- yi[k] = *di++;
- }
- yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */
- if ((k = enormlz (yi)) > NBITS)/* normalize the significand */
- ecleaz (yi); /* it was zero */
- else
- yi[E] -= (UEMUSHORT) k;/* subtract shift count from exponent */
- emovo (yi, e);
-}
+ See http://www-s.ti.com/sc/psheets/spru063c/spru063c.pdf */
-/* Convert target computer signed 64-bit integer to e-type. */
+static void encode_c4x_single PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_c4x_single PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
+static void encode_c4x_extended PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_c4x_extended PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
static void
-ditoe (di, e)
- const UEMUSHORT *di; /* Address of the 64-bit int. */
- UEMUSHORT *e;
-{
- unsigned EMULONG acc;
- UEMUSHORT yi[NI];
- UEMUSHORT carry;
- int k, sign;
+encode_c4x_single (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
+{
+ unsigned long image, exp, sig;
+
+ switch (r->class)
+ {
+ case rvc_zero:
+ exp = -128;
+ sig = 0;
+ break;
- ecleaz (yi);
- if (WORDS_BIG_ENDIAN)
- {
- for (k = M; k < M + 4; k++)
- yi[k] = *di++;
- }
- else
- {
- for (k = M + 3; k >= M; k--)
- yi[k] = *di++;
- }
- /* Take absolute value */
- sign = 0;
- if (yi[M] & 0x8000)
- {
- sign = 1;
- carry = 0;
- for (k = M + 3; k >= M; k--)
+ case rvc_inf:
+ case rvc_nan:
+ exp = 127;
+ sig = 0x800000 - r->sign;
+ break;
+
+ case rvc_normal:
+ exp = r->exp - 1;
+ sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
+ if (r->sign)
{
- acc = (unsigned EMULONG) (~yi[k] & 0xffff) + carry;
- yi[k] = acc;
- carry = 0;
- if (acc & 0x10000)
- carry = 1;
+ if (sig)
+ sig = -sig;
+ else
+ exp--;
+ sig |= 0x800000;
}
- }
- yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */
- if ((k = enormlz (yi)) > NBITS)/* normalize the significand */
- ecleaz (yi); /* it was zero */
- else
- yi[E] -= (UEMUSHORT) k;/* subtract shift count from exponent */
- emovo (yi, e);
- if (sign)
- eneg (e);
-}
+ break;
+ default:
+ abort ();
+ }
-/* Convert e-type to unsigned 64-bit int. */
+ image = ((exp & 0xff) << 24) | (sig & 0xffffff);
+ buf[0] = image;
+}
static void
-etoudi (x, i)
- const UEMUSHORT *x;
- UEMUSHORT *i;
+decode_c4x_single (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- UEMUSHORT xi[NI];
- int j, k;
+ unsigned long image = buf[0];
+ unsigned long sig;
+ int exp, sf;
- emovi (x, xi);
- if (xi[0])
- {
- xi[M] = 0;
- goto noshift;
- }
- k = (int) xi[E] - (EXONE - 1);
- if (k <= 0)
- {
- for (j = 0; j < 4; j++)
- *i++ = 0;
- return;
- }
- if (k > 64)
- {
- for (j = 0; j < 4; j++)
- *i++ = 0xffff;
- if (extra_warnings)
- warning ("overflow on truncation to integer");
- return;
- }
- if (k > 16)
+ exp = (((image >> 24) & 0xff) ^ 0x80) - 0x80;
+ sf = ((image & 0xffffff) ^ 0x800000) - 0x800000;
+
+ memset (r, 0, sizeof (*r));
+
+ if (exp != -128)
{
- /* Shift more than 16 bits: first shift up k-16 mod 16,
- then shift up by 16's. */
- j = k - ((k >> 4) << 4);
- if (j == 0)
- j = 16;
- eshift (xi, j);
- if (WORDS_BIG_ENDIAN)
- *i++ = xi[M];
- else
- {
- i += 3;
- *i-- = xi[M];
- }
- k -= j;
- do
+ r->class = rvc_normal;
+
+ sig = sf & 0x7fffff;
+ if (sf < 0)
{
- eshup6 (xi);
- if (WORDS_BIG_ENDIAN)
- *i++ = xi[M];
+ r->sign = 1;
+ if (sig)
+ sig = -sig;
else
- *i-- = xi[M];
+ exp++;
}
- while ((k -= 16) > 0);
- }
- else
- {
- /* shift not more than 16 bits */
- eshift (xi, k);
+ sig = (sig << (HOST_BITS_PER_LONG - 24)) | SIG_MSB;
-noshift:
-
- if (WORDS_BIG_ENDIAN)
- {
- i += 3;
- *i-- = xi[M];
- *i-- = 0;
- *i-- = 0;
- *i = 0;
- }
- else
- {
- *i++ = xi[M];
- *i++ = 0;
- *i++ = 0;
- *i = 0;
- }
+ r->exp = exp + 1;
+ r->sig[SIGSZ-1] = sig;
}
}
+static void
+encode_c4x_extended (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
+{
+ unsigned long exp, sig;
+
+ switch (r->class)
+ {
+ case rvc_zero:
+ exp = -128;
+ sig = 0;
+ break;
-/* Convert e-type to signed 64-bit int. */
+ case rvc_inf:
+ case rvc_nan:
+ exp = 127;
+ sig = 0x80000000 - r->sign;
+ break;
-static void
-etodi (x, i)
- const UEMUSHORT *x;
- UEMUSHORT *i;
-{
- unsigned EMULONG acc;
- UEMUSHORT xi[NI];
- UEMUSHORT carry;
- UEMUSHORT *isave;
- int j, k;
-
- emovi (x, xi);
- k = (int) xi[E] - (EXONE - 1);
- if (k <= 0)
- {
- for (j = 0; j < 4; j++)
- *i++ = 0;
- return;
- }
- if (k > 64)
- {
- for (j = 0; j < 4; j++)
- *i++ = 0xffff;
- if (extra_warnings)
- warning ("overflow on truncation to integer");
- return;
- }
- isave = i;
- if (k > 16)
- {
- /* Shift more than 16 bits: first shift up k-16 mod 16,
- then shift up by 16's. */
- j = k - ((k >> 4) << 4);
- if (j == 0)
- j = 16;
- eshift (xi, j);
- if (WORDS_BIG_ENDIAN)
- *i++ = xi[M];
- else
- {
- i += 3;
- *i-- = xi[M];
- }
- k -= j;
- do
- {
- eshup6 (xi);
- if (WORDS_BIG_ENDIAN)
- *i++ = xi[M];
- else
- *i-- = xi[M];
- }
- while ((k -= 16) > 0);
- }
- else
- {
- /* shift not more than 16 bits */
- eshift (xi, k);
+ case rvc_normal:
+ exp = r->exp - 1;
- if (WORDS_BIG_ENDIAN)
- {
- i += 3;
- *i = xi[M];
- *i-- = 0;
- *i-- = 0;
- *i = 0;
- }
- else
- {
- *i++ = xi[M];
- *i++ = 0;
- *i++ = 0;
- *i = 0;
- }
- }
- /* Negate if negative */
- if (xi[0])
- {
- carry = 0;
- if (WORDS_BIG_ENDIAN)
- isave += 3;
- for (k = 0; k < 4; k++)
+ sig = r->sig[SIGSZ-1];
+ if (HOST_BITS_PER_LONG == 64)
+ sig = sig >> 1 >> 31;
+ sig &= 0x7fffffff;
+
+ if (r->sign)
{
- acc = (unsigned EMULONG) (~(*isave) & 0xffff) + carry;
- if (WORDS_BIG_ENDIAN)
- *isave-- = acc;
+ if (sig)
+ sig = -sig;
else
- *isave++ = acc;
- carry = 0;
- if (acc & 0x10000)
- carry = 1;
+ exp--;
+ sig |= 0x80000000;
}
- }
-}
-
+ break;
-/* Longhand square root routine. */
+ default:
+ abort ();
+ }
+ exp = (exp & 0xff) << 24;
+ sig &= 0xffffffff;
-static int esqinited = 0;
-static unsigned short sqrndbit[NI];
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = exp, buf[1] = sig;
+ else
+ buf[0] = sig, buf[0] = exp;
+}
static void
-esqrt (x, y)
- const UEMUSHORT *x;
- UEMUSHORT *y;
+decode_c4x_extended (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- UEMUSHORT temp[NI], num[NI], sq[NI], xx[NI];
- EMULONG m, exp;
- int i, j, k, n, nlups;
+ unsigned long sig;
+ int exp, sf;
- if (esqinited == 0)
- {
- ecleaz (sqrndbit);
- sqrndbit[NI - 2] = 1;
- esqinited = 1;
- }
- /* Check for arg <= 0 */
- i = ecmp (x, ezero);
- if (i <= 0)
- {
- if (i == -1)
- {
- mtherr ("esqrt", DOMAIN);
- eclear (y);
- }
- else
- emov (x, y);
- return;
- }
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ exp = buf[0], sf = buf[1];
+ else
+ sf = buf[0], exp = buf[1];
-#ifdef INFINITY
- if (eisinf (x))
- {
- eclear (y);
- einfin (y);
- return;
- }
-#endif
- /* Bring in the arg and renormalize if it is denormal. */
- emovi (x, xx);
- m = (EMULONG) xx[1]; /* local long word exponent */
- if (m == 0)
- m -= enormlz (xx);
-
- /* Divide exponent by 2 */
- m -= 0x3ffe;
- exp = (unsigned short) ((m / 2) + 0x3ffe);
-
- /* Adjust if exponent odd */
- if ((m & 1) != 0)
- {
- if (m > 0)
- exp += 1;
- eshdn1 (xx);
- }
+ exp = (((exp >> 24) & 0xff) & 0x80) - 0x80;
+ sf = ((sf & 0xffffffff) ^ 0x80000000) - 0x80000000;
- ecleaz (sq);
- ecleaz (num);
- n = 8; /* get 8 bits of result per inner loop */
- nlups = rndprc;
- j = 0;
+ memset (r, 0, sizeof (*r));
- while (nlups > 0)
+ if (exp != -128)
{
- /* bring in next word of arg */
- if (j < NE)
- num[NI - 1] = xx[j + 3];
- /* Do additional bit on last outer loop, for roundoff. */
- if (nlups <= 8)
- n = nlups + 1;
- for (i = 0; i < n; i++)
+ r->class = rvc_normal;
+
+ sig = sf & 0x7fffffff;
+ if (sf < 0)
{
- /* Next 2 bits of arg */
- eshup1 (num);
- eshup1 (num);
- /* Shift up answer */
- eshup1 (sq);
- /* Make trial divisor */
- for (k = 0; k < NI; k++)
- temp[k] = sq[k];
- eshup1 (temp);
- eaddm (sqrndbit, temp);
- /* Subtract and insert answer bit if it goes in */
- if (ecmpm (temp, num) <= 0)
- {
- esubm (temp, num);
- sq[NI - 2] |= 1;
- }
+ r->sign = 1;
+ if (sig)
+ sig = -sig;
+ else
+ exp++;
}
- nlups -= n;
- j += 1;
- }
+ if (HOST_BITS_PER_LONG == 64)
+ sig = sig << 1 << 31;
+ sig |= SIG_MSB;
- /* Adjust for extra, roundoff loop done. */
- exp += (NBITS - 1) - rndprc;
+ r->exp = exp + 1;
+ r->sig[SIGSZ-1] = sig;
+ }
+}
- /* Sticky bit = 1 if the remainder is nonzero. */
- k = 0;
- for (i = 3; i < NI; i++)
- k |= (int) num[i];
+const struct real_format c4x_single_format =
+ {
+ encode_c4x_single,
+ decode_c4x_single,
+ 2,
+ 1,
+ 24,
+ -126,
+ 128,
+ false,
+ false,
+ false,
+ false,
+ false
+ };
+
+const struct real_format c4x_extended_format =
+ {
+ encode_c4x_extended,
+ decode_c4x_extended,
+ 2,
+ 1,
+ 32,
+ -126,
+ 128,
+ false,
+ false,
+ false,
+ false,
+ false
+ };
- /* Renormalize and round off. */
- emdnorm (sq, k, 0, exp, 64);
- emovo (sq, y);
-}
-#endif
-#endif /* EMU_NON_COMPILE not defined */
-/* Return the binary precision of the significand for a given
- floating point mode. The mode can hold an integer value
- that many bits wide, without losing any bits. */
+/* A synthetic "format" for internal arithmetic. It's the size of the
+ internal significand minus the two bits needed for proper rounding.
+ The encode and decode routines exist only to satisfy our paranoia
+ harness. */
-unsigned int
-significand_size (mode)
- enum machine_mode mode;
+static void encode_internal PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_internal PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
+
+static void
+encode_internal (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
+ memcpy (buf, r, sizeof (*r));
+}
-/* Don't test the modes, but their sizes, lest this
- code won't work for BITS_PER_UNIT != 8 . */
+static void
+decode_internal (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
+{
+ memcpy (r, buf, sizeof (*r));
+}
-switch (GET_MODE_BITSIZE (mode))
+const struct real_format real_internal_format =
{
- case 32:
-
-#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
- return 56;
-#endif
-
- return 24;
-
- case 64:
-#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
- return 53;
-#else
-#if TARGET_FLOAT_FORMAT == IBM_FLOAT_FORMAT
- return 56;
-#else
-#if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT
- return 56;
-#else
-#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
- return 56;
-#else
- abort ();
-#endif
-#endif
-#endif
-#endif
-
- case 96:
- return 64;
+ encode_internal,
+ decode_internal,
+ 2,
+ 1,
+ SIGNIFICAND_BITS - 2,
+ -MAX_EXP,
+ MAX_EXP,
+ true,
+ true,
+ false,
+ true,
+ true
+ };
+
+/* Set up default mode to format mapping for IEEE. Everyone else has
+ to set these values in OVERRIDE_OPTIONS. */
- case 128:
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
- return 113;
-#else
- return 64;
-#endif
+const struct real_format *real_format_for_mode[TFmode - QFmode + 1] =
+{
+ NULL, /* QFmode */
+ NULL, /* HFmode */
+ NULL, /* TQFmode */
+ &ieee_single_format, /* SFmode */
+ &ieee_double_format, /* DFmode */
- default:
- abort ();
- }
-}
+ /* We explicitly don't handle XFmode. There are two formats,
+ pretty much equally common. Choose one in OVERRIDE_OPTIONS. */
+ NULL, /* XFmode */
+ &ieee_quad_format /* TFmode */
+};
diff --git a/contrib/gcc/real.h b/contrib/gcc/real.h
index 2d3a909..7568a9e 100644
--- a/contrib/gcc/real.h
+++ b/contrib/gcc/real.h
@@ -2,435 +2,322 @@
Copyright (C) 1989, 1991, 1994, 1996, 1997, 1998,
1999, 2000, 2002 Free Software Foundation, Inc.
-This file is part of GCC.
+ This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
-version.
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
#ifndef GCC_REAL_H
#define GCC_REAL_H
-/* Define codes for all the float formats that we know of. */
-#define UNKNOWN_FLOAT_FORMAT 0
-#define IEEE_FLOAT_FORMAT 1
-#define VAX_FLOAT_FORMAT 2
-#define IBM_FLOAT_FORMAT 3
-#define C4X_FLOAT_FORMAT 4
+#include "machmode.h"
-/* Default to IEEE float if not specified. Nearly all machines use it. */
+/* An expanded form of the represented number. */
-#ifndef TARGET_FLOAT_FORMAT
-#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-#endif
+/* Enumerate the special cases of numbers that we encounter. */
+enum real_value_class {
+ rvc_zero,
+ rvc_normal,
+ rvc_inf,
+ rvc_nan
+};
-#ifndef HOST_FLOAT_FORMAT
-#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-#endif
+#define SIGNIFICAND_BITS (128 + HOST_BITS_PER_LONG)
+#define EXP_BITS (32 - 3)
+#define MAX_EXP ((1 << (EXP_BITS - 1)) - 1)
+#define SIGSZ (SIGNIFICAND_BITS / HOST_BITS_PER_LONG)
+#define SIG_MSB ((unsigned long)1 << (HOST_BITS_PER_LONG - 1))
-#ifndef INTEL_EXTENDED_IEEE_FORMAT
-#define INTEL_EXTENDED_IEEE_FORMAT 0
-#endif
+struct real_value GTY(())
+{
+ ENUM_BITFIELD (real_value_class) class : 2;
+ unsigned int sign : 1;
+ signed int exp : EXP_BITS;
+ unsigned long sig[SIGSZ];
+};
-#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-#define REAL_INFINITY
-#endif
+/* Various headers condition prototypes on #ifdef REAL_VALUE_TYPE, so it
+ needs to be a macro. We do need to continue to have a structure tag
+ so that other headers can forward declare it. */
+#define REAL_VALUE_TYPE struct real_value
-/* If FLOAT_WORDS_BIG_ENDIAN and HOST_FLOAT_WORDS_BIG_ENDIAN are not defined
- in the header files, then this implies the word-endianness is the same as
- for integers. */
+/* We store a REAL_VALUE_TYPE into an rtx, and we do this by putting it in
+ consecutive "w" slots. Moreover, we've got to compute the number of "w"
+ slots at preprocessor time, which means we can't use sizeof. Guess. */
-/* This is defined 0 or 1, like WORDS_BIG_ENDIAN. */
-#ifndef FLOAT_WORDS_BIG_ENDIAN
-#define FLOAT_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
-#endif
+#define REAL_VALUE_TYPE_SIZE (SIGNIFICAND_BITS + 32)
+#define REAL_WIDTH \
+ (REAL_VALUE_TYPE_SIZE/HOST_BITS_PER_WIDE_INT \
+ + (REAL_VALUE_TYPE_SIZE%HOST_BITS_PER_WIDE_INT ? 1 : 0)) /* round up */
-/* This is defined 0 or 1, unlike HOST_WORDS_BIG_ENDIAN. */
-#ifndef HOST_FLOAT_WORDS_BIG_ENDIAN
-#ifdef HOST_WORDS_BIG_ENDIAN
-#define HOST_FLOAT_WORDS_BIG_ENDIAN 1
-#else
-#define HOST_FLOAT_WORDS_BIG_ENDIAN 0
-#endif
-#endif
+/* Verify the guess. */
+extern char test_real_width
+ [sizeof(REAL_VALUE_TYPE) <= REAL_WIDTH*sizeof(HOST_WIDE_INT) ? 1 : -1];
-/* Defining REAL_ARITHMETIC invokes a floating point emulator
- that can produce a target machine format differing by more
- than just endian-ness from the host's format. The emulator
- is also used to support extended real XFmode. */
-#ifndef LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE 64
-#endif
-/* MAX_LONG_DOUBLE_TYPE_SIZE is a constant tested by #if.
- LONG_DOUBLE_TYPE_SIZE can vary at compiler run time.
- So long as macros like REAL_VALUE_TO_TARGET_LONG_DOUBLE cannot
- vary too, however, then XFmode and TFmode long double
- cannot both be supported at the same time. */
-#ifndef MAX_LONG_DOUBLE_TYPE_SIZE
-#define MAX_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
-#endif
-#if (MAX_LONG_DOUBLE_TYPE_SIZE == 96) || (MAX_LONG_DOUBLE_TYPE_SIZE == 128)
-#ifndef REAL_ARITHMETIC
-#define REAL_ARITHMETIC
-#endif
-#endif
-#ifdef REAL_ARITHMETIC
-/* **** Start of software floating point emulator interface macros **** */
-
-/* Support 80-bit extended real XFmode if LONG_DOUBLE_TYPE_SIZE
- has been defined to be 96 in the tm.h machine file. */
-#if (MAX_LONG_DOUBLE_TYPE_SIZE == 96)
-#define REAL_IS_NOT_DOUBLE
-#define REAL_ARITHMETIC
-typedef struct {
- HOST_WIDE_INT r[(11 + sizeof (HOST_WIDE_INT))/(sizeof (HOST_WIDE_INT))];
-} realvaluetype;
-#define REAL_VALUE_TYPE realvaluetype
-
-#else /* no XFmode support */
-
-#if (MAX_LONG_DOUBLE_TYPE_SIZE == 128)
-
-#define REAL_IS_NOT_DOUBLE
-#define REAL_ARITHMETIC
-typedef struct {
- HOST_WIDE_INT r[(19 + sizeof (HOST_WIDE_INT))/(sizeof (HOST_WIDE_INT))];
-} realvaluetype;
-#define REAL_VALUE_TYPE realvaluetype
-
-#else /* not TFmode */
-
-#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
-/* If no XFmode support, then a REAL_VALUE_TYPE is 64 bits wide
- but it is not necessarily a host machine double. */
-#define REAL_IS_NOT_DOUBLE
-typedef struct {
- HOST_WIDE_INT r[(7 + sizeof (HOST_WIDE_INT))/(sizeof (HOST_WIDE_INT))];
-} realvaluetype;
-#define REAL_VALUE_TYPE realvaluetype
+/* Calculate the format for CONST_DOUBLE. We need as many slots as
+ are necessary to overlay a REAL_VALUE_TYPE on them. This could be
+ as many as four (32-bit HOST_WIDE_INT, 128-bit REAL_VALUE_TYPE).
+
+ A number of places assume that there are always at least two 'w'
+ slots in a CONST_DOUBLE, so we provide them even if one would suffice. */
+
+#if REAL_WIDTH == 1
+# define CONST_DOUBLE_FORMAT "ww"
#else
-/* If host and target formats are compatible, then a REAL_VALUE_TYPE
- is actually a host machine double. */
-#define REAL_VALUE_TYPE double
-#endif
+# if REAL_WIDTH == 2
+# define CONST_DOUBLE_FORMAT "ww"
+# else
+# if REAL_WIDTH == 3
+# define CONST_DOUBLE_FORMAT "www"
+# else
+# if REAL_WIDTH == 4
+# define CONST_DOUBLE_FORMAT "wwww"
+# else
+# if REAL_WIDTH == 5
+# define CONST_DOUBLE_FORMAT "wwwww"
+# else
+# if REAL_WIDTH == 6
+# define CONST_DOUBLE_FORMAT "wwwwww"
+# else
+ #error "REAL_WIDTH > 6 not supported"
+# endif
+# endif
+# endif
+# endif
+# endif
+#endif
+
+
+/* Describes the properties of the specific target format in use. */
+struct real_format
+{
+ /* Move to and from the target bytes. */
+ void (*encode) PARAMS ((const struct real_format *, long *,
+ const REAL_VALUE_TYPE *));
+ void (*decode) PARAMS ((const struct real_format *, REAL_VALUE_TYPE *,
+ const long *));
-#endif /* no TFmode support */
-#endif /* no XFmode support */
+ /* The radix of the exponent and digits of the significand. */
+ int b;
-extern unsigned int significand_size PARAMS ((enum machine_mode));
+ /* log2(b). */
+ int log2_b;
+
+ /* Size of the significand in digits of radix B. */
+ int p;
+
+ /* The minimum negative integer, x, such that b**(x-1) is normalized. */
+ int emin;
+
+ /* The maximum integer, x, such that b**(x-1) is representable. */
+ int emax;
+
+ /* Properties of the format. */
+ bool has_nans;
+ bool has_inf;
+ bool has_denorm;
+ bool has_signed_zero;
+ bool qnan_msb_set;
+};
+
+
+/* The target format used for each floating floating point mode.
+ Indexed by MODE - QFmode. */
+extern const struct real_format *real_format_for_mode[TFmode - QFmode + 1];
-/* If emulation has been enabled by defining REAL_ARITHMETIC or by
- setting LONG_DOUBLE_TYPE_SIZE to 96 or 128, then define macros so that
- they invoke emulator functions. This will succeed only if the machine
- files have been updated to use these macros in place of any
- references to host machine `double' or `float' types. */
-#ifdef REAL_ARITHMETIC
-#undef REAL_ARITHMETIC
-#define REAL_ARITHMETIC(value, code, d1, d2) \
- earith (&(value), (code), &(d1), &(d2))
/* Declare functions in real.c. */
-extern void earith PARAMS ((REAL_VALUE_TYPE *, int,
- REAL_VALUE_TYPE *, REAL_VALUE_TYPE *));
-extern REAL_VALUE_TYPE etrunci PARAMS ((REAL_VALUE_TYPE));
-extern REAL_VALUE_TYPE etruncui PARAMS ((REAL_VALUE_TYPE));
-extern REAL_VALUE_TYPE ereal_negate PARAMS ((REAL_VALUE_TYPE));
-extern HOST_WIDE_INT efixi PARAMS ((REAL_VALUE_TYPE));
-extern unsigned HOST_WIDE_INT efixui PARAMS ((REAL_VALUE_TYPE));
-extern void ereal_from_int PARAMS ((REAL_VALUE_TYPE *,
- HOST_WIDE_INT, HOST_WIDE_INT,
- enum machine_mode));
-extern void ereal_from_uint PARAMS ((REAL_VALUE_TYPE *,
- unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT,
- enum machine_mode));
-extern void ereal_to_int PARAMS ((HOST_WIDE_INT *, HOST_WIDE_INT *,
- REAL_VALUE_TYPE));
-extern REAL_VALUE_TYPE ereal_ldexp PARAMS ((REAL_VALUE_TYPE, int));
-
-extern void etartdouble PARAMS ((REAL_VALUE_TYPE, long *));
-extern void etarldouble PARAMS ((REAL_VALUE_TYPE, long *));
-extern void etardouble PARAMS ((REAL_VALUE_TYPE, long *));
-extern long etarsingle PARAMS ((REAL_VALUE_TYPE));
-extern void ereal_to_decimal PARAMS ((REAL_VALUE_TYPE, char *));
-extern int ereal_cmp PARAMS ((REAL_VALUE_TYPE, REAL_VALUE_TYPE));
-extern int ereal_isneg PARAMS ((REAL_VALUE_TYPE));
-extern REAL_VALUE_TYPE ereal_unto_float PARAMS ((long));
-extern REAL_VALUE_TYPE ereal_unto_double PARAMS ((long *));
-extern REAL_VALUE_TYPE ereal_from_float PARAMS ((HOST_WIDE_INT));
-extern REAL_VALUE_TYPE ereal_from_double PARAMS ((HOST_WIDE_INT *));
-
-#define REAL_VALUES_EQUAL(x, y) (ereal_cmp ((x), (y)) == 0)
-/* true if x < y : */
-#define REAL_VALUES_LESS(x, y) (ereal_cmp ((x), (y)) == -1)
-#define REAL_VALUE_LDEXP(x, n) ereal_ldexp (x, n)
-
-/* These return REAL_VALUE_TYPE: */
-#define REAL_VALUE_RNDZINT(x) (etrunci (x))
-#define REAL_VALUE_UNSIGNED_RNDZINT(x) (etruncui (x))
-#define REAL_VALUE_TRUNCATE(mode, x) real_value_truncate (mode, x)
-
-/* These return HOST_WIDE_INT: */
-/* Convert a floating-point value to integer, rounding toward zero. */
-#define REAL_VALUE_FIX(x) (efixi (x))
-/* Convert a floating-point value to unsigned integer, rounding
- toward zero. */
-#define REAL_VALUE_UNSIGNED_FIX(x) (efixui (x))
-
-/* Convert ASCII string S to floating point in mode M.
- Decimal input uses ATOF. Hexadecimal uses HTOF. */
-#define REAL_VALUE_ATOF(s,m) ereal_atof(s,m)
-#define REAL_VALUE_HTOF(s,m) ereal_atof(s,m)
-
-#define REAL_VALUE_NEGATE ereal_negate
-
-#define REAL_VALUE_MINUS_ZERO(x) \
- ((ereal_cmp (x, dconst0) == 0) && (ereal_isneg (x) != 0 ))
-
-#define REAL_VALUE_TO_INT ereal_to_int
-
-/* Here the cast to HOST_WIDE_INT sign-extends arguments such as ~0. */
-#define REAL_VALUE_FROM_INT(d, lo, hi, mode) \
- ereal_from_int (&d, (HOST_WIDE_INT) (lo), (HOST_WIDE_INT) (hi), mode)
-
-#define REAL_VALUE_FROM_UNSIGNED_INT(d, lo, hi, mode) \
- ereal_from_uint (&d, lo, hi, mode)
-/* IN is a REAL_VALUE_TYPE. OUT is an array of longs. */
-#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) \
- (LONG_DOUBLE_TYPE_SIZE == 64 ? etardouble ((IN), (OUT)) \
- : LONG_DOUBLE_TYPE_SIZE == 96 ? etarldouble ((IN), (OUT)) \
- : LONG_DOUBLE_TYPE_SIZE == 128 ? etartdouble ((IN), (OUT)) \
- : abort ())
-#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) (etardouble ((IN), (OUT)))
+/* Binary or unary arithmetic on tree_code. */
+extern void real_arithmetic PARAMS ((REAL_VALUE_TYPE *, int,
+ const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
-/* IN is a REAL_VALUE_TYPE. OUT is a long. */
-#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) ((OUT) = etarsingle ((IN)))
+/* Compare reals by tree_code. */
+extern bool real_compare PARAMS ((int, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
-/* Inverse of REAL_VALUE_TO_TARGET_DOUBLE. */
-#define REAL_VALUE_UNTO_TARGET_DOUBLE(d) (ereal_unto_double (d))
+/* Determine whether a floating-point value X is infinite. */
+extern bool real_isinf PARAMS ((const REAL_VALUE_TYPE *));
-/* Inverse of REAL_VALUE_TO_TARGET_SINGLE. */
-#define REAL_VALUE_UNTO_TARGET_SINGLE(f) (ereal_unto_float (f))
+/* Determine whether a floating-point value X is a NaN. */
+extern bool real_isnan PARAMS ((const REAL_VALUE_TYPE *));
-/* d is an array of HOST_WIDE_INT that holds a double precision
- value in the target computer's floating point format. */
-#define REAL_VALUE_FROM_TARGET_DOUBLE(d) (ereal_from_double (d))
+/* Determine whether a floating-point value X is negative. */
+extern bool real_isneg PARAMS ((const REAL_VALUE_TYPE *));
-/* f is a HOST_WIDE_INT containing a single precision target float value. */
-#define REAL_VALUE_FROM_TARGET_SINGLE(f) (ereal_from_float (f))
+/* Determine whether a floating-point value X is minus zero. */
+extern bool real_isnegzero PARAMS ((const REAL_VALUE_TYPE *));
-/* Conversions to decimal ASCII string. */
-#define REAL_VALUE_TO_DECIMAL(r, fmt, s) (ereal_to_decimal (r, s))
+/* Compare two floating-point objects for bitwise identity. */
+extern bool real_identical PARAMS ((const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
-#endif /* REAL_ARITHMETIC defined */
+/* Extend or truncate to a new mode. */
+extern void real_convert PARAMS ((REAL_VALUE_TYPE *,
+ enum machine_mode,
+ const REAL_VALUE_TYPE *));
-/* **** End of software floating point emulator interface macros **** */
-#else /* No XFmode or TFmode and REAL_ARITHMETIC not defined */
-
-/* old interface */
-#ifdef REAL_ARITHMETIC
-/* Defining REAL_IS_NOT_DOUBLE breaks certain initializations
- when REAL_ARITHMETIC etc. are not defined. */
-
-/* Now see if the host and target machines use the same format.
- If not, define REAL_IS_NOT_DOUBLE (even if we end up representing
- reals as doubles because we have no better way in this cross compiler.)
- This turns off various optimizations that can happen when we know the
- compiler's float format matches the target's float format.
- */
-#if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
-#define REAL_IS_NOT_DOUBLE
-#ifndef REAL_VALUE_TYPE
-typedef struct {
- HOST_WIDE_INT r[sizeof (double)/sizeof (HOST_WIDE_INT)];
- } realvaluetype;
-#define REAL_VALUE_TYPE realvaluetype
-#endif /* no REAL_VALUE_TYPE */
-#endif /* formats differ */
-#endif /* 0 */
-
-#endif /* emulator not used */
-
-/* If we are not cross-compiling, use a `double' to represent the
- floating-point value. Otherwise, use some other type
- (probably a struct containing an array of longs). */
-#ifndef REAL_VALUE_TYPE
-#define REAL_VALUE_TYPE double
-#else
-#define REAL_IS_NOT_DOUBLE
-#endif
+/* Return true if truncating to NEW is exact. */
+extern bool exact_real_truncate PARAMS ((enum machine_mode,
+ const REAL_VALUE_TYPE *));
-#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
-
-/* Convert a type `double' value in host format first to a type `float'
- value in host format and then to a single type `long' value which
- is the bitwise equivalent of the `float' value. */
-#ifndef REAL_VALUE_TO_TARGET_SINGLE
-#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) \
-do { \
- union { \
- float f; \
- HOST_WIDE_INT l; \
- } u; \
- if (sizeof(HOST_WIDE_INT) < sizeof(float)) \
- abort (); \
- u.l = 0; \
- u.f = (IN); \
- (OUT) = u.l; \
-} while (0)
-#endif
+/* Render R as a decimal floating point constant. */
+extern void real_to_decimal PARAMS ((char *, const REAL_VALUE_TYPE *,
+ size_t, size_t, int));
-/* Convert a type `double' value in host format to a pair of type `long'
- values which is its bitwise equivalent, but put the two words into
- proper word order for the target. */
-#ifndef REAL_VALUE_TO_TARGET_DOUBLE
-#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \
-do { \
- union { \
- REAL_VALUE_TYPE f; \
- HOST_WIDE_INT l[2]; \
- } u; \
- if (sizeof(HOST_WIDE_INT) * 2 < sizeof(REAL_VALUE_TYPE)) \
- abort (); \
- u.l[0] = u.l[1] = 0; \
- u.f = (IN); \
- if (HOST_FLOAT_WORDS_BIG_ENDIAN == FLOAT_WORDS_BIG_ENDIAN) \
- (OUT)[0] = u.l[0], (OUT)[1] = u.l[1]; \
- else \
- (OUT)[1] = u.l[0], (OUT)[0] = u.l[1]; \
-} while (0)
-#endif
-#endif /* HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT */
+/* Render R as a hexadecimal floating point constant. */
+extern void real_to_hexadecimal PARAMS ((char *, const REAL_VALUE_TYPE *,
+ size_t, size_t, int));
-/* In this configuration, double and long double are the same. */
-#ifndef REAL_VALUE_TO_TARGET_LONG_DOUBLE
-#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(a, b) REAL_VALUE_TO_TARGET_DOUBLE (a, b)
-#endif
+/* Render R as an integer. */
+extern HOST_WIDE_INT real_to_integer PARAMS ((const REAL_VALUE_TYPE *));
+extern void real_to_integer2 PARAMS ((HOST_WIDE_INT *, HOST_WIDE_INT *,
+ const REAL_VALUE_TYPE *));
-/* Compare two floating-point objects for bitwise identity.
- This is not the same as comparing for equality on IEEE hosts:
- -0.0 equals 0.0 but they are not identical, and conversely
- two NaNs might be identical but they cannot be equal. */
-#define REAL_VALUES_IDENTICAL(x, y) \
- (!memcmp ((char *) &(x), (char *) &(y), sizeof (REAL_VALUE_TYPE)))
+/* Initialize R from a decimal or hexadecimal string. */
+extern void real_from_string PARAMS ((REAL_VALUE_TYPE *, const char *));
-/* Compare two floating-point values for equality. */
-#ifndef REAL_VALUES_EQUAL
-#define REAL_VALUES_EQUAL(x, y) ((x) == (y))
-#endif
+/* Initialize R from an integer pair HIGH/LOW. */
+extern void real_from_integer PARAMS ((REAL_VALUE_TYPE *,
+ enum machine_mode,
+ unsigned HOST_WIDE_INT,
+ HOST_WIDE_INT, int));
-/* Compare two floating-point values for less than. */
-#ifndef REAL_VALUES_LESS
-#define REAL_VALUES_LESS(x, y) ((x) < (y))
-#endif
+extern long real_to_target_fmt PARAMS ((long *, const REAL_VALUE_TYPE *,
+ const struct real_format *));
+extern long real_to_target PARAMS ((long *, const REAL_VALUE_TYPE *,
+ enum machine_mode));
-/* Truncate toward zero to an integer floating-point value. */
-#ifndef REAL_VALUE_RNDZINT
-#define REAL_VALUE_RNDZINT(x) ((double) ((int) (x)))
-#endif
+extern void real_from_target_fmt PARAMS ((REAL_VALUE_TYPE *, const long *,
+ const struct real_format *));
+extern void real_from_target PARAMS ((REAL_VALUE_TYPE *, const long *,
+ enum machine_mode));
-/* Truncate toward zero to an unsigned integer floating-point value. */
-#ifndef REAL_VALUE_UNSIGNED_RNDZINT
-#define REAL_VALUE_UNSIGNED_RNDZINT(x) ((double) ((unsigned int) (x)))
-#endif
+extern void real_inf PARAMS ((REAL_VALUE_TYPE *));
-/* Convert a floating-point value to integer, rounding toward zero. */
-#ifndef REAL_VALUE_FIX
-#define REAL_VALUE_FIX(x) ((int) (x))
-#endif
+extern bool real_nan PARAMS ((REAL_VALUE_TYPE *, const char *,
+ int, enum machine_mode));
-/* Convert a floating-point value to unsigned integer, rounding
- toward zero. */
-#ifndef REAL_VALUE_UNSIGNED_FIX
-#define REAL_VALUE_UNSIGNED_FIX(x) ((unsigned int) (x))
-#endif
+extern void real_2expN PARAMS ((REAL_VALUE_TYPE *, int));
-/* Scale X by Y powers of 2. */
-#ifndef REAL_VALUE_LDEXP
-#define REAL_VALUE_LDEXP(x, y) ldexp (x, y)
-extern double ldexp PARAMS ((double, int));
-#endif
+extern unsigned int real_hash PARAMS ((const REAL_VALUE_TYPE *));
-/* Convert the string X to a floating-point value. */
-#ifndef REAL_VALUE_ATOF
-#if 1
-/* Use real.c to convert decimal numbers to binary, ... */
-#define REAL_VALUE_ATOF(x, s) ereal_atof (x, s)
-/* Could use ereal_atof here for hexadecimal floats too, but real_hex_to_f
- is OK and it uses faster native fp arithmetic. */
-/* #define REAL_VALUE_HTOF(x, s) ereal_atof (x, s) */
-#else
-/* ... or, if you like the host computer's atof, go ahead and use it: */
-#define REAL_VALUE_ATOF(x, s) atof (x)
-#if defined (MIPSEL) || defined (MIPSEB)
-/* MIPS compiler can't handle parens around the function name.
- This problem *does not* appear to be connected with any
- macro definition for atof. It does not seem there is one. */
-extern double atof ();
-#else
-extern double (atof) ();
-#endif
-#endif
-#endif
-/* Hexadecimal floating constant input for use with host computer's
- fp arithmetic. */
-#ifndef REAL_VALUE_HTOF
-extern REAL_VALUE_TYPE real_hex_to_f PARAMS ((const char *,
- enum machine_mode));
-#define REAL_VALUE_HTOF(s,m) real_hex_to_f(s,m)
-#endif
+/* Target formats defined in real.c. */
+extern const struct real_format ieee_single_format;
+extern const struct real_format ieee_double_format;
+extern const struct real_format ieee_extended_motorola_format;
+extern const struct real_format ieee_extended_intel_96_format;
+extern const struct real_format ieee_extended_intel_96_round_53_format;
+extern const struct real_format ieee_extended_intel_128_format;
+extern const struct real_format ibm_extended_format;
+extern const struct real_format ieee_quad_format;
+extern const struct real_format vax_f_format;
+extern const struct real_format vax_d_format;
+extern const struct real_format vax_g_format;
+extern const struct real_format i370_single_format;
+extern const struct real_format i370_double_format;
+extern const struct real_format c4x_single_format;
+extern const struct real_format c4x_extended_format;
+extern const struct real_format real_internal_format;
-/* Negate the floating-point value X. */
-#ifndef REAL_VALUE_NEGATE
-#define REAL_VALUE_NEGATE(x) (- (x))
-#endif
-/* Truncate the floating-point value X to mode MODE. This is correct only
- for the most common case where the host and target have objects of the same
- size and where `float' is SFmode. */
+/* ====================================================================== */
+/* Crap. */
-/* Don't use REAL_VALUE_TRUNCATE directly--always call real_value_truncate. */
-extern REAL_VALUE_TYPE real_value_truncate PARAMS ((enum machine_mode,
- REAL_VALUE_TYPE));
+#define REAL_ARITHMETIC(value, code, d1, d2) \
+ real_arithmetic (&(value), code, &(d1), &(d2))
-#ifndef REAL_VALUE_TRUNCATE
-#define REAL_VALUE_TRUNCATE(mode, x) \
- (GET_MODE_BITSIZE (mode) == sizeof (float) * HOST_BITS_PER_CHAR \
- ? (float) (x) : (x))
-#endif
+#define REAL_VALUES_IDENTICAL(x, y) real_identical (&(x), &(y))
+#define REAL_VALUES_EQUAL(x, y) real_compare (EQ_EXPR, &(x), &(y))
+#define REAL_VALUES_LESS(x, y) real_compare (LT_EXPR, &(x), &(y))
/* Determine whether a floating-point value X is infinite. */
-#ifndef REAL_VALUE_ISINF
-#define REAL_VALUE_ISINF(x) (target_isinf (x))
-#endif
+#define REAL_VALUE_ISINF(x) real_isinf (&(x))
/* Determine whether a floating-point value X is a NaN. */
-#ifndef REAL_VALUE_ISNAN
-#define REAL_VALUE_ISNAN(x) (target_isnan (x))
-#endif
+#define REAL_VALUE_ISNAN(x) real_isnan (&(x))
/* Determine whether a floating-point value X is negative. */
-#ifndef REAL_VALUE_NEGATIVE
-#define REAL_VALUE_NEGATIVE(x) (target_negative (x))
-#endif
+#define REAL_VALUE_NEGATIVE(x) real_isneg (&(x))
-/* Determine whether a floating-point value X is minus 0. */
-#ifndef REAL_VALUE_MINUS_ZERO
-#define REAL_VALUE_MINUS_ZERO(x) ((x) == 0 && REAL_VALUE_NEGATIVE (x))
-#endif
+/* Determine whether a floating-point value X is minus zero. */
+#define REAL_VALUE_MINUS_ZERO(x) real_isnegzero (&(x))
+
+/* IN is a REAL_VALUE_TYPE. OUT is an array of longs. */
+#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) \
+ real_to_target (OUT, &(IN), \
+ mode_for_size (LONG_DOUBLE_TYPE_SIZE, MODE_FLOAT, 0))
+
+#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \
+ real_to_target (OUT, &(IN), mode_for_size (64, MODE_FLOAT, 0))
+
+/* IN is a REAL_VALUE_TYPE. OUT is a long. */
+#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) \
+ ((OUT) = real_to_target (NULL, &(IN), mode_for_size (32, MODE_FLOAT, 0)))
+
+#define REAL_VALUE_FROM_INT(r, lo, hi, mode) \
+ real_from_integer (&(r), mode, lo, hi, 0)
+
+#define REAL_VALUE_FROM_UNSIGNED_INT(r, lo, hi, mode) \
+ real_from_integer (&(r), mode, lo, hi, 1)
+
+extern REAL_VALUE_TYPE real_value_truncate PARAMS ((enum machine_mode,
+ REAL_VALUE_TYPE));
+
+#define REAL_VALUE_TO_INT(plow, phigh, r) \
+ real_to_integer2 (plow, phigh, &(r))
+
+extern REAL_VALUE_TYPE real_arithmetic2 PARAMS ((int, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+
+#define REAL_VALUE_NEGATE(X) \
+ real_arithmetic2 (NEGATE_EXPR, &(X), NULL)
+
+#define REAL_VALUE_ABS(X) \
+ real_arithmetic2 (ABS_EXPR, &(X), NULL)
+
+extern int significand_size PARAMS ((enum machine_mode));
+
+extern REAL_VALUE_TYPE real_from_string2 PARAMS ((const char *,
+ enum machine_mode));
+
+#define REAL_VALUE_ATOF(s, m) \
+ real_from_string2 (s, m)
+
+#define CONST_DOUBLE_ATOF(s, m) \
+ CONST_DOUBLE_FROM_REAL_VALUE (real_from_string2 (s, m), m)
+
+#define REAL_VALUE_FIX(r) \
+ real_to_integer (&(r))
+
+/* ??? Not quite right. */
+#define REAL_VALUE_UNSIGNED_FIX(r) \
+ real_to_integer (&(r))
+
+/* ??? These were added for Paranoia support. */
+
+/* Return floor log2(R). */
+extern int real_exponent PARAMS ((const REAL_VALUE_TYPE *));
+
+/* R = A * 2**EXP. */
+extern void real_ldexp PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *, int));
+
+/* **** End of software floating point emulator interface macros **** */
/* Constant real values 0, 1, 2, and -1. */
@@ -439,47 +326,26 @@ extern REAL_VALUE_TYPE dconst1;
extern REAL_VALUE_TYPE dconst2;
extern REAL_VALUE_TYPE dconstm1;
-/* Union type used for extracting real values from CONST_DOUBLEs
- or putting them in. */
-
-union real_extract
-{
- REAL_VALUE_TYPE d;
- HOST_WIDE_INT i[sizeof (REAL_VALUE_TYPE) / sizeof (HOST_WIDE_INT)];
-};
-
-/* Given a CONST_DOUBLE in FROM, store into TO the value it represents. */
/* Function to return a real value (not a tree node)
from a given integer constant. */
-union tree_node;
REAL_VALUE_TYPE real_value_from_int_cst PARAMS ((union tree_node *,
- union tree_node *));
+ union tree_node *));
-#define REAL_VALUE_FROM_CONST_DOUBLE(to, from) \
-do { union real_extract u; \
- memcpy (&u, &CONST_DOUBLE_LOW ((from)), sizeof u); \
- to = u.d; } while (0)
+/* Given a CONST_DOUBLE in FROM, store into TO the value it represents. */
+#define REAL_VALUE_FROM_CONST_DOUBLE(to, from) \
+ memcpy (&(to), &CONST_DOUBLE_LOW ((from)), sizeof (REAL_VALUE_TYPE))
/* Return a CONST_DOUBLE with value R and mode M. */
+#define CONST_DOUBLE_FROM_REAL_VALUE(r, m) \
+ const_double_from_real_value (r, m)
+extern rtx const_double_from_real_value PARAMS ((REAL_VALUE_TYPE,
+ enum machine_mode));
-#define CONST_DOUBLE_FROM_REAL_VALUE(r, m) immed_real_const_1 (r, m)
-extern struct rtx_def *immed_real_const_1 PARAMS ((REAL_VALUE_TYPE,
- enum machine_mode));
+/* Replace R by 1/R in the given machine mode, if the result is exact. */
+extern bool exact_real_inverse PARAMS ((enum machine_mode, REAL_VALUE_TYPE *));
+/* In tree.c: wrap up a REAL_VALUE_TYPE in a tree node. */
+extern tree build_real PARAMS ((tree, REAL_VALUE_TYPE));
-/* Convert a floating point value `r', that can be interpreted
- as a host machine float or double, to a decimal ASCII string `s'
- using printf format string `fmt'. */
-#ifndef REAL_VALUE_TO_DECIMAL
-#define REAL_VALUE_TO_DECIMAL(r, fmt, s) (sprintf (s, fmt, r))
-#endif
-
-/* Replace R by 1/R in the given machine mode, if the result is exact. */
-extern int exact_real_inverse PARAMS ((enum machine_mode, REAL_VALUE_TYPE *));
-extern int target_isnan PARAMS ((REAL_VALUE_TYPE));
-extern int target_isinf PARAMS ((REAL_VALUE_TYPE));
-extern int target_negative PARAMS ((REAL_VALUE_TYPE));
-extern void debug_real PARAMS ((REAL_VALUE_TYPE));
-extern REAL_VALUE_TYPE ereal_atof PARAMS ((const char *, enum machine_mode));
#endif /* ! GCC_REAL_H */
diff --git a/contrib/gcc/recog.c b/contrib/gcc/recog.c
index 41193db..bd42a5b 100644
--- a/contrib/gcc/recog.c
+++ b/contrib/gcc/recog.c
@@ -161,7 +161,7 @@ check_asm_operands (x)
c = constraints[c[0] - '0'];
if (! asm_operand_ok (operands[i], c))
- return 0;
+ return 0;
}
return 1;
@@ -191,7 +191,7 @@ static int num_changes = 0;
an INSN, CALL_INSN, or JUMP_INSN, the insn will be re-recognized with
the change in place.
- IN_GROUP is non-zero if this is part of a group of changes that must be
+ IN_GROUP is nonzero if this is part of a group of changes that must be
performed as a group. In that case, the changes will be stored. The
function `apply_change_group' will validate and apply the changes.
@@ -227,11 +227,11 @@ validate_change (object, loc, new, in_group)
else
changes_allocated *= 2;
- changes =
- (change_t*) xrealloc (changes,
- sizeof (change_t) * changes_allocated);
+ changes =
+ (change_t*) xrealloc (changes,
+ sizeof (change_t) * changes_allocated);
}
-
+
changes[num_changes].object = object;
changes[num_changes].loc = loc;
changes[num_changes].old = old;
@@ -272,7 +272,7 @@ insn_invalid_p (insn)
? &num_clobbers : 0);
int is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0;
-
+
/* If this is an asm and the operand aren't legal, then fail. Likewise if
this is not an asm and the insn wasn't recognized. */
if ((is_asm && ! check_asm_operands (PATTERN (insn)))
@@ -308,6 +308,13 @@ insn_invalid_p (insn)
return 0;
}
+/* Return number of changes made and not validated yet. */
+int
+num_changes_pending ()
+{
+ return num_changes;
+}
+
/* Apply a group of changes previously issued with `validate_change'.
Return 1 if all changes are valid, zero otherwise. */
@@ -362,7 +369,7 @@ apply_change_group ()
int j;
newpat
- = gen_rtx_PARALLEL (VOIDmode,
+ = gen_rtx_PARALLEL (VOIDmode,
rtvec_alloc (XVECLEN (pat, 0) - 1));
for (j = 0; j < XVECLEN (newpat, 0); j++)
XVECEXP (newpat, 0, j) = XVECEXP (pat, 0, j);
@@ -392,6 +399,14 @@ apply_change_group ()
if (i == num_changes)
{
+ basic_block bb;
+
+ for (i = 0; i < num_changes; i++)
+ if (changes[i].object
+ && INSN_P (changes[i].object)
+ && (bb = BLOCK_FOR_INSN (changes[i].object)))
+ bb->flags |= BB_DIRTY;
+
num_changes = 0;
return 1;
}
@@ -663,11 +678,10 @@ validate_replace_src_1 (x, data)
}
/* Try replacing every occurrence of FROM in INSN with TO, avoiding
- SET_DESTs. After all changes have been made, validate by seeing if
- INSN is still valid. */
+ SET_DESTs. */
-int
-validate_replace_src (from, to, insn)
+void
+validate_replace_src_group (from, to, insn)
rtx from, to, insn;
{
struct validate_replace_src_data d;
@@ -676,6 +690,15 @@ validate_replace_src (from, to, insn)
d.to = to;
d.insn = insn;
note_uses (&PATTERN (insn), validate_replace_src_1, &d);
+}
+
+/* Same as validate_repalace_src_group, but validate by seeing if
+ INSN is still valid. */
+int
+validate_replace_src (from, to, insn)
+ rtx from, to, insn;
+{
+ validate_replace_src_group (from, to, insn);
return apply_change_group ();
}
@@ -778,7 +801,7 @@ find_single_use_1 (dest, loc)
case MEM:
case SUBREG:
return find_single_use_1 (dest, &XEXP (x, 0));
-
+
default:
break;
}
@@ -833,7 +856,7 @@ find_single_use_1 (dest, loc)
sequel. If so, return a pointer to the innermost rtx expression in which
it is used.
- If PLOC is non-zero, *PLOC is set to the insn containing the single use.
+ If PLOC is nonzero, *PLOC is set to the insn containing the single use.
This routine will return usually zero either before flow is called (because
there will be no LOG_LINKS notes) or after reload (because the REG_DEAD
@@ -931,6 +954,7 @@ general_operand (op, mode)
return 0;
if (GET_CODE (op) == CONST_INT
+ && mode != VOIDmode
&& trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
return 0;
@@ -962,15 +986,15 @@ general_operand (op, mode)
/* Avoid memories with nonzero SUBREG_BYTE, as offsetting the memory
may result in incorrect reference. We should simplify all valid
subregs of MEM anyway. But allow this after reload because we
- might be called from cleanup_subreg_operands.
+ might be called from cleanup_subreg_operands.
??? This is a kludge. */
if (!reload_completed && SUBREG_BYTE (op) != 0
&& GET_CODE (sub) == MEM)
- return 0;
+ return 0;
/* FLOAT_MODE subregs can't be paradoxical. Combine will occasionally
- create such rtl, and we must reject it. */
+ create such rtl, and we must reject it. */
if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
&& GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
return 0;
@@ -1059,13 +1083,10 @@ register_operand (op, mode)
if (! reload_completed && GET_CODE (sub) == MEM)
return general_operand (op, mode);
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
if (GET_CODE (sub) == REG
&& REGNO (sub) < FIRST_PSEUDO_REGISTER
- && (TEST_HARD_REG_BIT
- (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
- REGNO (sub)))
- && CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (sub))
+ && REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
return 0;
@@ -1136,6 +1157,7 @@ immediate_operand (op, mode)
return 0;
if (GET_CODE (op) == CONST_INT
+ && mode != VOIDmode
&& trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
return 0;
@@ -1218,6 +1240,7 @@ nonmemory_operand (op, mode)
return 0;
if (GET_CODE (op) == CONST_INT
+ && mode != VOIDmode
&& trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
return 0;
@@ -1334,7 +1357,7 @@ memory_address_p (mode, addr)
{
if (GET_CODE (addr) == ADDRESSOF)
return 1;
-
+
GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
return 0;
@@ -1588,7 +1611,7 @@ decode_asm_operands (body, operands, operand_locs, constraints, modes)
{
if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
break; /* Past last SET */
-
+
if (operands)
operands[i] = SET_DEST (XVECEXP (body, 0, i));
if (operand_locs)
@@ -1640,7 +1663,7 @@ decode_asm_operands (body, operands, operand_locs, constraints, modes)
return template;
}
-/* Check if an asm_operand matches it's constraints.
+/* Check if an asm_operand matches it's constraints.
Return > 0 if ok, = 0 if bad, < 0 if inconclusive. */
int
@@ -1708,7 +1731,7 @@ asm_operand_ok (op, constraint)
if (GET_CODE (op) == MEM
&& (1
|| GET_CODE (XEXP (op, 0)) == PRE_DEC
- || GET_CODE (XEXP (op, 0)) == POST_DEC))
+ || GET_CODE (XEXP (op, 0)) == POST_DEC))
return 1;
break;
@@ -1716,23 +1739,15 @@ asm_operand_ok (op, constraint)
if (GET_CODE (op) == MEM
&& (1
|| GET_CODE (XEXP (op, 0)) == PRE_INC
- || GET_CODE (XEXP (op, 0)) == POST_INC))
+ || GET_CODE (XEXP (op, 0)) == POST_INC))
return 1;
break;
case 'E':
-#ifndef REAL_ARITHMETIC
- /* Match any floating double constant, but only if
- we can examine the bits of it reliably. */
- if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
- || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
- && GET_MODE (op) != VOIDmode && ! flag_pretend_float)
- break;
-#endif
- /* FALLTHRU */
-
case 'F':
- if (GET_CODE (op) == CONST_DOUBLE)
+ if (GET_CODE (op) == CONST_DOUBLE
+ || (GET_CODE (op) == CONST_VECTOR
+ && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
return 1;
break;
@@ -1833,6 +1848,18 @@ asm_operand_ok (op, constraint)
#ifdef EXTRA_CONSTRAINT
if (EXTRA_CONSTRAINT (op, c))
return 1;
+ if (EXTRA_MEMORY_CONSTRAINT (c))
+ {
+ /* Every memory operand can be reloaded to fit. */
+ if (memory_operand (op, VOIDmode))
+ return 1;
+ }
+ if (EXTRA_ADDRESS_CONSTRAINT (c))
+ {
+ /* Every address operand can be reloaded to fit. */
+ if (address_operand (op, VOIDmode))
+ return 1;
+ }
#endif
break;
}
@@ -2230,7 +2257,7 @@ preprocess_constraints ()
break;
case '&':
op_alt[j].earlyclobber = 1;
- break;
+ break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
@@ -2272,6 +2299,19 @@ preprocess_constraints ()
break;
default:
+ if (EXTRA_MEMORY_CONSTRAINT (c))
+ {
+ op_alt[j].memory_ok = 1;
+ break;
+ }
+ if (EXTRA_ADDRESS_CONSTRAINT (c))
+ {
+ op_alt[j].is_address = 1;
+ op_alt[j].class = reg_class_subunion[(int) op_alt[j].class]
+ [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+ break;
+ }
+
op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)];
break;
}
@@ -2279,7 +2319,7 @@ preprocess_constraints ()
}
}
}
-
+
/* Check the operands of an insn against the insn's operand constraints
and return 1 if they are valid.
The information about the insn's operands, constraints, operand modes
@@ -2298,7 +2338,7 @@ preprocess_constraints ()
This is used in final, just before printing the assembler code and by
the routines that determine an insn's attribute.
- If STRICT is a positive non-zero value, it means that we have been
+ If STRICT is a positive nonzero value, it means that we have been
called after reload has been completed. In that case, we must
do all checks strictly. If it is zero, it means that we have been called
before reload has completed. In that case, we first try to see if we can
@@ -2499,20 +2539,10 @@ constrain_operands (strict)
break;
case 'E':
-#ifndef REAL_ARITHMETIC
- /* Match any CONST_DOUBLE, but only if
- we can examine the bits of it reliably. */
- if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
- || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
- && GET_MODE (op) != VOIDmode && ! flag_pretend_float)
- break;
-#endif
- if (GET_CODE (op) == CONST_DOUBLE)
- win = 1;
- break;
-
case 'F':
- if (GET_CODE (op) == CONST_DOUBLE)
+ if (GET_CODE (op) == CONST_DOUBLE
+ || (GET_CODE (op) == CONST_VECTOR
+ && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
win = 1;
break;
@@ -2595,6 +2625,28 @@ constrain_operands (strict)
#ifdef EXTRA_CONSTRAINT
else if (EXTRA_CONSTRAINT (op, c))
win = 1;
+
+ if (EXTRA_MEMORY_CONSTRAINT (c))
+ {
+ /* Every memory operand can be reloaded to fit. */
+ if (strict < 0 && GET_CODE (op) == MEM)
+ win = 1;
+
+ /* Before reload, accept what reload can turn into mem. */
+ if (strict < 0 && CONSTANT_P (op))
+ win = 1;
+
+ /* During reload, accept a pseudo */
+ if (reload_in_progress && GET_CODE (op) == REG
+ && REGNO (op) >= FIRST_PSEUDO_REGISTER)
+ win = 1;
+ }
+ if (EXTRA_ADDRESS_CONSTRAINT (c))
+ {
+ /* Every address operand can be reloaded to fit. */
+ if (strict < 0)
+ win = 1;
+ }
#endif
break;
}
@@ -2711,11 +2763,7 @@ split_insn (insn)
allocation, and there are unlikely to be very many
nops then anyways. */
if (reload_completed)
- {
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- }
+ delete_insn_and_edges (insn);
}
else
{
@@ -2731,7 +2779,7 @@ split_insn (insn)
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
/* ??? Coddle to md files that generate subregs in post-
- reload splitters instead of computing the proper
+ reload splitters instead of computing the proper
hard register. */
if (reload_completed && first != last)
{
@@ -2757,25 +2805,26 @@ split_all_insns (upd_life)
int upd_life;
{
sbitmap blocks;
- int changed;
- int i;
+ bool changed;
+ basic_block bb;
- blocks = sbitmap_alloc (n_basic_blocks);
+ blocks = sbitmap_alloc (last_basic_block);
sbitmap_zero (blocks);
- changed = 0;
+ changed = false;
- for (i = n_basic_blocks - 1; i >= 0; --i)
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block bb = BASIC_BLOCK (i);
rtx insn, next;
+ bool finish = false;
- for (insn = bb->head; insn ; insn = next)
+ for (insn = bb->head; !finish ; insn = next)
{
rtx last;
/* Can't use `next_real_insn' because that might go across
CODE_LABELS and short-out basic blocks. */
next = NEXT_INSN (insn);
+ finish = (insn == bb->end);
last = split_insn (insn);
if (last)
{
@@ -2785,29 +2834,27 @@ split_all_insns (upd_life)
while (GET_CODE (last) == BARRIER)
last = PREV_INSN (last);
- SET_BIT (blocks, i);
- changed = 1;
+ SET_BIT (blocks, bb->index);
+ changed = true;
insn = last;
}
-
- if (insn == bb->end)
- break;
}
-
- if (insn == NULL)
- abort ();
}
if (changed)
{
+ int old_last_basic_block = last_basic_block;
+
find_many_sub_basic_blocks (blocks);
+
+ if (old_last_basic_block != last_basic_block && upd_life)
+ blocks = sbitmap_resize (blocks, last_basic_block, 1);
}
if (changed && upd_life)
- {
- count_or_remove_death_notes (blocks, 1);
- update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES);
- }
+ update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
+ PROP_DEATH_NOTES | PROP_REG_INFO);
+
#ifdef ENABLE_CHECKING
verify_flow_info ();
#endif
@@ -2815,7 +2862,7 @@ split_all_insns (upd_life)
sbitmap_free (blocks);
}
-/* Same as split_all_insns, but do not expect CFG to be available.
+/* Same as split_all_insns, but do not expect CFG to be available.
Used by machine depedent reorg passes. */
void
@@ -3034,7 +3081,8 @@ peephole2_optimize (dump_file)
regset_head rs_heads[MAX_INSNS_PER_PEEP2 + 2];
rtx insn, prev;
regset live;
- int i, b;
+ int i;
+ basic_block bb;
#ifdef HAVE_conditional_execution
sbitmap blocks;
bool changed;
@@ -3048,16 +3096,15 @@ peephole2_optimize (dump_file)
live = INITIALIZE_REG_SET (rs_heads[i]);
#ifdef HAVE_conditional_execution
- blocks = sbitmap_alloc (n_basic_blocks);
+ blocks = sbitmap_alloc (last_basic_block);
sbitmap_zero (blocks);
changed = false;
#else
count_or_remove_death_notes (NULL, 1);
#endif
- for (b = n_basic_blocks - 1; b >= 0; --b)
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block bb = BASIC_BLOCK (b);
struct propagate_block_info *pbi;
/* Indicate that all slots except the last holds invalid data. */
@@ -3086,6 +3133,7 @@ peephole2_optimize (dump_file)
rtx try, before_try, x;
int match_len;
rtx note;
+ bool was_call = false;
/* Record this insn. */
if (--peep2_current < 0)
@@ -3103,7 +3151,7 @@ peephole2_optimize (dump_file)
cfg-related call notes. */
for (i = 0; i <= match_len; ++i)
{
- int j, k;
+ int j;
rtx old_insn, new_insn, note;
j = i + peep2_current;
@@ -3112,21 +3160,17 @@ peephole2_optimize (dump_file)
old_insn = peep2_insn_data[j].insn;
if (GET_CODE (old_insn) != CALL_INSN)
continue;
+ was_call = true;
- new_insn = NULL_RTX;
- if (GET_CODE (try) == SEQUENCE)
- for (k = XVECLEN (try, 0) - 1; k >= 0; k--)
- {
- rtx x = XVECEXP (try, 0, k);
- if (GET_CODE (x) == CALL_INSN)
- {
- new_insn = x;
- break;
- }
- }
- else if (GET_CODE (try) == CALL_INSN)
- new_insn = try;
- if (! new_insn)
+ new_insn = try;
+ while (new_insn != NULL_RTX)
+ {
+ if (GET_CODE (new_insn) == CALL_INSN)
+ break;
+ new_insn = NEXT_INSN (new_insn);
+ }
+
+ if (new_insn == NULL_RTX)
abort ();
CALL_INSN_FUNCTION_USAGE (new_insn)
@@ -3166,22 +3210,23 @@ peephole2_optimize (dump_file)
if (i >= MAX_INSNS_PER_PEEP2 + 1)
i -= MAX_INSNS_PER_PEEP2 + 1;
- note = find_reg_note (peep2_insn_data[i].insn,
+ note = find_reg_note (peep2_insn_data[i].insn,
REG_EH_REGION, NULL_RTX);
/* Replace the old sequence with the new. */
- try = emit_insn_after (try, peep2_insn_data[i].insn);
+ try = emit_insn_after_scope (try, peep2_insn_data[i].insn,
+ INSN_SCOPE (peep2_insn_data[i].insn));
before_try = PREV_INSN (insn);
delete_insn_chain (insn, peep2_insn_data[i].insn);
/* Re-insert the EH_REGION notes. */
- if (note)
+ if (note || (was_call && nonlocal_goto_handler_labels))
{
edge eh_edge;
for (eh_edge = bb->succ; eh_edge
; eh_edge = eh_edge->succ_next)
- if (eh_edge->flags & EDGE_EH)
+ if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
break;
for (x = try ; x != before_try ; x = PREV_INSN (x))
@@ -3190,10 +3235,11 @@ peephole2_optimize (dump_file)
&& may_trap_p (PATTERN (x))
&& !find_reg_note (x, REG_EH_REGION, NULL)))
{
- REG_NOTES (x)
- = gen_rtx_EXPR_LIST (REG_EH_REGION,
- XEXP (note, 0),
- REG_NOTES (x));
+ if (note)
+ REG_NOTES (x)
+ = gen_rtx_EXPR_LIST (REG_EH_REGION,
+ XEXP (note, 0),
+ REG_NOTES (x));
if (x != bb->end && eh_edge)
{
@@ -3201,7 +3247,8 @@ peephole2_optimize (dump_file)
int flags;
nfte = split_block (bb, x);
- flags = EDGE_EH | EDGE_ABNORMAL;
+ flags = (eh_edge->flags
+ & (EDGE_EH | EDGE_ABNORMAL));
if (GET_CODE (x) == CALL_INSN)
flags |= EDGE_ABNORMAL_CALL;
nehe = make_edge (nfte->src, eh_edge->dest,
@@ -3232,7 +3279,7 @@ peephole2_optimize (dump_file)
death data structures are not so self-contained.
So record that we've made a modification to this
block and update life information at the end. */
- SET_BIT (blocks, b);
+ SET_BIT (blocks, bb->index);
changed = true;
for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
@@ -3310,3 +3357,114 @@ peephole2_optimize (dump_file)
#endif
}
#endif /* HAVE_peephole2 */
+
+/* Common predicates for use with define_bypass. */
+
+/* True if the dependency between OUT_INSN and IN_INSN is on the store
+ data not the address operand(s) of the store. IN_INSN must be
+ single_set. OUT_INSN must be either a single_set or a PARALLEL with
+ SETs inside. */
+
+int
+store_data_bypass_p (out_insn, in_insn)
+ rtx out_insn, in_insn;
+{
+ rtx out_set, in_set;
+
+ in_set = single_set (in_insn);
+ if (! in_set)
+ abort ();
+
+ if (GET_CODE (SET_DEST (in_set)) != MEM)
+ return false;
+
+ out_set = single_set (out_insn);
+ if (out_set)
+ {
+ if (reg_mentioned_p (SET_DEST (out_set), SET_DEST (in_set)))
+ return false;
+ }
+ else
+ {
+ rtx out_pat;
+ int i;
+
+ out_pat = PATTERN (out_insn);
+ if (GET_CODE (out_pat) != PARALLEL)
+ abort ();
+
+ for (i = 0; i < XVECLEN (out_pat, 0); i++)
+ {
+ rtx exp = XVECEXP (out_pat, 0, i);
+
+ if (GET_CODE (exp) == CLOBBER)
+ continue;
+
+ if (GET_CODE (exp) != SET)
+ abort ();
+
+ if (reg_mentioned_p (SET_DEST (exp), SET_DEST (in_set)))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* True if the dependency between OUT_INSN and IN_INSN is in the IF_THEN_ELSE
+ condition, and not the THEN or ELSE branch. OUT_INSN may be either a single
+ or multiple set; IN_INSN should be single_set for truth, but for convenience
+ of insn categorization may be any JUMP or CALL insn. */
+
+int
+if_test_bypass_p (out_insn, in_insn)
+ rtx out_insn, in_insn;
+{
+ rtx out_set, in_set;
+
+ in_set = single_set (in_insn);
+ if (! in_set)
+ {
+ if (GET_CODE (in_insn) == JUMP_INSN || GET_CODE (in_insn) == CALL_INSN)
+ return false;
+ abort ();
+ }
+
+ if (GET_CODE (SET_SRC (in_set)) != IF_THEN_ELSE)
+ return false;
+ in_set = SET_SRC (in_set);
+
+ out_set = single_set (out_insn);
+ if (out_set)
+ {
+ if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1))
+ || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2)))
+ return false;
+ }
+ else
+ {
+ rtx out_pat;
+ int i;
+
+ out_pat = PATTERN (out_insn);
+ if (GET_CODE (out_pat) != PARALLEL)
+ abort ();
+
+ for (i = 0; i < XVECLEN (out_pat, 0); i++)
+ {
+ rtx exp = XVECEXP (out_pat, 0, i);
+
+ if (GET_CODE (exp) == CLOBBER)
+ continue;
+
+ if (GET_CODE (exp) != SET)
+ abort ();
+
+ if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1))
+ || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2)))
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/contrib/gcc/recog.h b/contrib/gcc/recog.h
index ff96e47..86af35f 100644
--- a/contrib/gcc/recog.h
+++ b/contrib/gcc/recog.h
@@ -89,6 +89,8 @@ extern int validate_replace_rtx_subexp PARAMS ((rtx, rtx, rtx, rtx *));
extern int validate_replace_rtx PARAMS ((rtx, rtx, rtx));
extern void validate_replace_rtx_group PARAMS ((rtx, rtx, rtx));
extern int validate_replace_src PARAMS ((rtx, rtx, rtx));
+extern void validate_replace_src_group PARAMS ((rtx, rtx, rtx));
+extern int num_changes_pending PARAMS ((void));
#ifdef HAVE_cc0
extern int next_insn_tests_no_inequality PARAMS ((rtx));
#endif
@@ -137,6 +139,9 @@ extern rtx peep2_find_free_register PARAMS ((int, int, const char *,
extern void peephole2_optimize PARAMS ((FILE *));
extern rtx peephole2_insns PARAMS ((rtx, rtx, int *));
+extern int store_data_bypass_p PARAMS ((rtx, rtx));
+extern int if_test_bypass_p PARAMS ((rtx, rtx));
+
/* Nonzero means volatile operands are recognized. */
extern int volatile_ok;
diff --git a/contrib/gcc/reg-stack.c b/contrib/gcc/reg-stack.c
index 8329829..1537c07 100644
--- a/contrib/gcc/reg-stack.c
+++ b/contrib/gcc/reg-stack.c
@@ -167,6 +167,15 @@
#include "basic-block.h"
#include "varray.h"
#include "reload.h"
+#include "ggc.h"
+
+/* We use this array to cache info about insns, because otherwise we
+ spend too much time in stack_regs_mentioned_p.
+
+ Indexed by insn UIDs. A value of zero is uninitialized, one indicates
+ the insn uses stack registers, two indicates the insn does not use
+ stack registers. */
+static GTY(()) varray_type stack_regs_mentioned_data;
#ifdef STACK_REGS
@@ -188,7 +197,7 @@ typedef struct stack_def
unsigned char reg[REG_STACK_SIZE];/* register - stack mapping */
} *stack;
-/* This is used to carry information about basic blocks. It is
+/* This is used to carry information about basic blocks. It is
attached to the AUX field of the standard CFG block. */
typedef struct block_info_def
@@ -210,18 +219,10 @@ enum emit_where
EMIT_BEFORE
};
-/* We use this array to cache info about insns, because otherwise we
- spend too much time in stack_regs_mentioned_p.
-
- Indexed by insn UIDs. A value of zero is uninitialized, one indicates
- the insn uses stack registers, two indicates the insn does not use
- stack registers. */
-static varray_type stack_regs_mentioned_data;
-
/* The block we're currently working on. */
static basic_block current_block;
-/* This is the register file for all register after conversion */
+/* This is the register file for all register after conversion. */
static rtx
FP_mode_reg[LAST_STACK_REG+1-FIRST_STACK_REG][(int) MAX_MACHINE_MODE];
@@ -267,7 +268,7 @@ static rtx next_flags_user PARAMS ((rtx));
static void record_label_references PARAMS ((rtx, rtx));
static bool compensate_edge PARAMS ((edge, FILE *));
-/* Return non-zero if any stack register is mentioned somewhere within PAT. */
+/* Return nonzero if any stack register is mentioned somewhere within PAT. */
static int
stack_regs_mentioned_p (pat)
@@ -336,7 +337,7 @@ static rtx
next_flags_user (insn)
rtx insn;
{
- /* Search forward looking for the first use of this value.
+ /* Search forward looking for the first use of this value.
Stop at block boundaries. */
while (insn != current_block->end)
@@ -344,7 +345,7 @@ next_flags_user (insn)
insn = NEXT_INSN (insn);
if (INSN_P (insn) && reg_mentioned_p (ix86_flags_rtx, PATTERN (insn)))
- return insn;
+ return insn;
if (GET_CODE (insn) == CALL_INSN)
return NULL_RTX;
@@ -352,7 +353,7 @@ next_flags_user (insn)
return NULL_RTX;
}
-/* Reorganise the stack into ascending numbers,
+/* Reorganize the stack into ascending numbers,
after this insn. */
static void
@@ -374,11 +375,11 @@ straighten_stack (insn, regstack)
for (top = temp_stack.top = regstack->top; top >= 0; top--)
temp_stack.reg[top] = FIRST_STACK_REG + temp_stack.top - top;
-
+
change_stack (insn, regstack, &temp_stack, EMIT_AFTER);
}
-/* Pop a register from the stack */
+/* Pop a register from the stack. */
static void
pop_stack (regstack, regno)
@@ -389,7 +390,7 @@ pop_stack (regstack, regno)
CLEAR_HARD_REG_BIT (regstack->reg_set, regno);
regstack->top--;
- /* If regno was not at the top of stack then adjust stack */
+ /* If regno was not at the top of stack then adjust stack. */
if (regstack->reg [top] != regno)
{
int i;
@@ -418,18 +419,12 @@ reg_to_stack (first, file)
rtx first;
FILE *file;
{
+ basic_block bb;
int i;
int max_uid;
/* Clean up previous run. */
- if (stack_regs_mentioned_data)
- {
- VARRAY_FREE (stack_regs_mentioned_data);
- stack_regs_mentioned_data = 0;
- }
-
- if (!optimize)
- split_all_insns (0);
+ stack_regs_mentioned_data = 0;
/* See if there is something to do. Flow analysis is quite
expensive so we might save some compilation time. */
@@ -439,11 +434,10 @@ reg_to_stack (first, file)
if (i > LAST_STACK_REG)
return;
- /* Ok, floating point instructions exist. If not optimizing,
+ /* Ok, floating point instructions exist. If not optimizing,
build the CFG and run life analysis. */
if (!optimize)
{
- find_basic_blocks (first, max_reg_num (), file);
count_or_remove_death_notes (NULL, 1);
life_analysis (first, file, PROP_DEATH_NOTES);
}
@@ -451,10 +445,9 @@ reg_to_stack (first, file)
/* Set up block info for each basic block. */
alloc_aux_for_blocks (sizeof (struct block_info_def));
- for (i = n_basic_blocks - 1; i >= 0; --i)
+ FOR_EACH_BB_REVERSE (bb)
{
edge e;
- basic_block bb = BASIC_BLOCK (i);
for (e = bb->pred; e; e=e->pred_next)
if (!(e->flags & EDGE_DFS_BACK)
&& e->src != ENTRY_BLOCK_PTR)
@@ -477,7 +470,7 @@ reg_to_stack (first, file)
ix86_flags_rtx = gen_rtx_REG (CCmode, FLAGS_REG);
- /* A QNaN for initializing uninitialized variables.
+ /* A QNaN for initializing uninitialized variables.
??? We can't load from constant memory in PIC mode, because
we're insertting these instructions before the prologue and
@@ -568,7 +561,7 @@ get_true_reg (pat)
switch (GET_CODE (*pat))
{
case SUBREG:
- /* Eliminate FP subregister accesses in favour of the
+ /* Eliminate FP subregister accesses in favor of the
actual FP register in use. */
{
rtx subreg;
@@ -591,6 +584,9 @@ get_true_reg (pat)
}
}
+/* Set if we find any malformed asms in a block. */
+static bool any_malformed_asm;
+
/* 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. */
@@ -677,7 +673,7 @@ check_asm_stack_operands (insn)
error_for_asm (insn, "output constraint %d must specify a single register", i);
malformed_asm = 1;
}
- else
+ else
{
int j;
@@ -772,6 +768,7 @@ check_asm_stack_operands (insn)
{
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
+ any_malformed_asm = true;
return 0;
}
@@ -823,7 +820,7 @@ stack_result (decl)
{
#ifdef FUNCTION_OUTGOING_VALUE
result
- = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (decl)), decl);
+ = FUNCTION_OUTGOING_VALUE (TREE_TYPE (DECL_RESULT (decl)), decl);
#else
result = FUNCTION_VALUE (TREE_TYPE (DECL_RESULT (decl)), decl);
#endif
@@ -932,9 +929,9 @@ emit_pop_insn (insn, regstack, reg, where)
pop_insn = NULL_RTX;
if (get_hard_regnum (regstack, reg1) >= 0)
- pop_insn = emit_pop_insn (insn, regstack, reg1, where);
+ pop_insn = emit_pop_insn (insn, regstack, reg1, where);
if (get_hard_regnum (regstack, reg2) >= 0)
- pop_insn = emit_pop_insn (insn, regstack, reg2, where);
+ pop_insn = emit_pop_insn (insn, regstack, reg2, where);
if (!pop_insn)
abort ();
return pop_insn;
@@ -1129,7 +1126,7 @@ move_for_stack_reg (insn, regstack, pat)
return;
}
- /* The destination ought to be dead */
+ /* The destination ought to be dead. */
if (get_hard_regnum (regstack, dest) >= FIRST_STACK_REG)
abort ();
@@ -1185,7 +1182,7 @@ move_for_stack_reg (insn, regstack, pat)
stack. The stack mapping is changed to reflect that DEST is
now at top of stack. */
- /* The destination ought to be dead */
+ /* The destination ought to be dead. */
if (get_hard_regnum (regstack, dest) >= FIRST_STACK_REG)
abort ();
@@ -1260,11 +1257,11 @@ swap_rtx_condition (insn)
if (GET_CODE (pat) == SET
&& GET_CODE (SET_SRC (pat)) == UNSPEC
- && XINT (SET_SRC (pat), 1) == 9)
+ && XINT (SET_SRC (pat), 1) == UNSPEC_FNSTSW)
{
rtx dest = SET_DEST (pat);
- /* Search forward looking for the first use of this value.
+ /* Search forward looking for the first use of this value.
Stop at block boundaries. */
while (insn != current_block->end)
{
@@ -1281,7 +1278,7 @@ swap_rtx_condition (insn)
pat = PATTERN (insn);
if (GET_CODE (pat) != SET
|| GET_CODE (SET_SRC (pat)) != UNSPEC
- || XINT (SET_SRC (pat), 1) != 10
+ || XINT (SET_SRC (pat), 1) != UNSPEC_SAHF
|| ! dead_or_set_p (insn, dest))
return 0;
@@ -1430,12 +1427,12 @@ subst_stack_regs_pat (insn, regstack, pat)
/* Deaths in USE insns can happen in non optimizing compilation.
Handle them by popping the dying register. */
src = get_true_reg (&XEXP (pat, 0));
- if (STACK_REG_P (*src)
- && find_regno_note (insn, REG_DEAD, REGNO (*src)))
- {
- emit_pop_insn (insn, regstack, *src, EMIT_AFTER);
- return;
- }
+ if (STACK_REG_P (*src)
+ && find_regno_note (insn, REG_DEAD, REGNO (*src)))
+ {
+ emit_pop_insn (insn, regstack, *src, EMIT_AFTER);
+ return;
+ }
/* ??? Uninitialized USE should not happen. */
else if (get_hard_regnum (regstack, *src) == -1)
abort ();
@@ -1455,7 +1452,7 @@ subst_stack_regs_pat (insn, regstack, pat)
/* The fix_truncdi_1 pattern wants to be able to allocate
it's own scratch register. It does this by clobbering
an fp reg so that it is assured of an empty reg-stack
- register. If the register is live, kill it now.
+ register. If the register is live, kill it now.
Remove the DEAD/UNUSED note so we don't try to kill it
later too. */
@@ -1474,7 +1471,7 @@ subst_stack_regs_pat (insn, regstack, pat)
{
/* A top-level clobber with no REG_DEAD, and no hard-regnum
indicates an uninitialized value. Because reload removed
- all other clobbers, this must be due to a function
+ all other clobbers, this must be due to a function
returning without a value. Load up a NaN. */
if (! note
@@ -1705,8 +1702,8 @@ subst_stack_regs_pat (insn, regstack, pat)
case UNSPEC:
switch (XINT (pat_src, 1))
{
- case 1: /* sin */
- case 2: /* cos */
+ case UNSPEC_SIN:
+ case UNSPEC_COS:
/* These insns only operate on the top of the stack. */
src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
@@ -1728,19 +1725,17 @@ subst_stack_regs_pat (insn, regstack, pat)
replace_reg (src1, FIRST_STACK_REG);
break;
- case 10:
- /* (unspec [(unspec [(compare ..)] 9)] 10)
- Unspec 9 is fnstsw; unspec 10 is sahf. The combination
- matches the PPRO fcomi instruction. */
+ case UNSPEC_SAHF:
+ /* (unspec [(unspec [(compare)] UNSPEC_FNSTSW)] UNSPEC_SAHF)
+ The combination matches the PPRO fcomi instruction. */
pat_src = XVECEXP (pat_src, 0, 0);
if (GET_CODE (pat_src) != UNSPEC
- || XINT (pat_src, 1) != 9)
+ || XINT (pat_src, 1) != UNSPEC_FNSTSW)
abort ();
/* FALLTHRU */
- case 9:
- /* (unspec [(compare ..)] 9) */
+ case UNSPEC_FNSTSW:
/* Combined fcomp+fnstsw generated for doing well with
CSE. When optimizing this would have been broken
up before now. */
@@ -1775,8 +1770,8 @@ subst_stack_regs_pat (insn, regstack, pat)
&& REGNO (*dest) != regstack->reg[regstack->top])
{
/* In case one of operands is the top of stack and the operands
- dies, it is safe to make it the destination operand by reversing
- the direction of cmove and avoid fxch. */
+ dies, it is safe to make it the destination operand by
+ reversing the direction of cmove and avoid fxch. */
if ((REGNO (*src1) == regstack->reg[regstack->top]
&& src1_note)
|| (REGNO (*src2) == regstack->reg[regstack->top]
@@ -1798,7 +1793,7 @@ subst_stack_regs_pat (insn, regstack, pat)
reversed_comparison_code (XEXP (pat_src, 0), insn));
}
else
- emit_swap_insn (insn, regstack, *dest);
+ emit_swap_insn (insn, regstack, *dest);
}
{
@@ -1837,7 +1832,7 @@ subst_stack_regs_pat (insn, regstack, pat)
/* 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);
+ regstack->reg[++regstack->top] = REGNO (*dest);
SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
replace_reg (dest, FIRST_STACK_REG);
break;
@@ -1899,7 +1894,7 @@ subst_asm_stack_regs (insn, regstack)
n_inputs = get_asm_operand_n_inputs (body);
n_outputs = recog_data.n_operands - n_inputs;
-
+
if (alt < 0)
abort ();
@@ -2296,7 +2291,7 @@ change_stack (insn, old, new, where)
abort ();
/* If the stack is not empty (new->top != -1), loop here emitting
- swaps until the stack is correct.
+ swaps until the stack is correct.
The worst case number of swaps emitted is N + 2, where N is the
depth of the stack. In some cases, the reg at the top of
@@ -2372,7 +2367,7 @@ print_stack (file, s)
}
/* This function was doing life analysis. We now let the regular live
- code do it's job, so we only need to check some extra invariants
+ code do it's job, so we only need to check some extra invariants
that reg-stack expects. Primary among these being that all registers
are initialized before use.
@@ -2382,18 +2377,18 @@ print_stack (file, s)
static int
convert_regs_entry ()
{
- int inserted = 0, i;
+ int inserted = 0;
edge e;
+ basic_block block;
- for (i = n_basic_blocks - 1; i >= 0; --i)
+ FOR_EACH_BB_REVERSE (block)
{
- basic_block block = BASIC_BLOCK (i);
block_info bi = BLOCK_INFO (block);
int reg;
-
+
/* Set current register status at last instruction `uninitialized'. */
bi->stack_in.top = -2;
-
+
/* Copy live_at_end and live_at_start into temporaries. */
for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; reg++)
{
@@ -2404,11 +2399,11 @@ convert_regs_entry ()
}
}
- /* Load something into each stack register live at function entry.
+ /* Load something into each stack register live at function entry.
Such live registers can be caused by uninitialized variables or
- functions not returning values on all paths. In order to keep
+ functions not returning values on all paths. In order to keep
the push/pop code happy, and to not scrog the register stack, we
- must put something in these registers. Use a QNaN.
+ must put something in these registers. Use a QNaN.
Note that we are insertting converted code here. This code is
never seen by the convert_regs pass. */
@@ -2510,7 +2505,7 @@ compensate_edge (e, file)
tmpstack = regstack;
change_stack (block->end, &tmpstack, target_stack, EMIT_AFTER);
- return false;
+ return false;
}
if (file)
@@ -2559,7 +2554,11 @@ compensate_edge (e, file)
abort ();
eh1:
+ /* We are sure that there is st(0) live, otherwise we won't compensate.
+ For complex return values, we may have st(1) live as well. */
SET_HARD_REG_BIT (tmp, FIRST_STACK_REG);
+ if (TEST_HARD_REG_BIT (regstack.reg_set, FIRST_STACK_REG + 1))
+ SET_HARD_REG_BIT (tmp, FIRST_STACK_REG + 1);
GO_IF_HARD_REG_EQUAL (regstack.reg_set, tmp, eh2);
abort ();
eh2:
@@ -2593,16 +2592,13 @@ compensate_edge (e, file)
current_block = NULL;
start_sequence ();
- /* ??? change_stack needs some point to emit insns after.
- Also needed to keep gen_sequence from returning a
- pattern as opposed to a sequence, which would lose
- REG_DEAD notes. */
+ /* ??? change_stack needs some point to emit insns after. */
after = emit_note (NULL, NOTE_INSN_DELETED);
tmpstack = regstack;
change_stack (after, &tmpstack, target_stack, EMIT_BEFORE);
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
insert_insn_on_edge (seq, e);
@@ -2625,6 +2621,7 @@ convert_regs_1 (file, block)
edge e, beste = NULL;
inserted = 0;
+ any_malformed_asm = false;
/* Find the edge we will copy stack from. It should be the most frequent
one as it will get cheapest after compensation code is generated,
@@ -2660,7 +2657,7 @@ convert_regs_1 (file, block)
inserted |= compensate_edge (beste, file);
else
beste = NULL;
-
+
current_block = block;
if (file)
@@ -2738,9 +2735,12 @@ convert_regs_1 (file, block)
}
}
- /* Something failed if the stack lives don't match. */
+ /* Something failed if the stack lives don't match. If we had malformed
+ asms, we zapped the instruction itself, but that didn't produce the
+ same pattern of register kills as before. */
GO_IF_HARD_REG_EQUAL (regstack.reg_set, bi->out_reg_set, win);
- abort ();
+ if (!any_malformed_asm)
+ abort ();
win:
bi->stack_out = regstack;
@@ -2753,7 +2753,7 @@ convert_regs_1 (file, block)
if (!BLOCK_INFO (e->dest)->done
&& e->dest != block)
abort ();
- inserted |= compensate_edge (e, file);
+ inserted |= compensate_edge (e, file);
}
}
for (e = block->pred; e ; e = e->pred_next)
@@ -2763,7 +2763,7 @@ convert_regs_1 (file, block)
{
if (!BLOCK_INFO (e->src)->done)
abort ();
- inserted |= compensate_edge (e, file);
+ inserted |= compensate_edge (e, file);
}
}
@@ -2815,7 +2815,8 @@ static int
convert_regs (file)
FILE *file;
{
- int inserted, i;
+ int inserted;
+ basic_block b;
edge e;
/* Initialize uninitialized registers on function entry. */
@@ -2832,12 +2833,11 @@ convert_regs (file)
/* Process all blocks reachable from all entry points. */
for (e = ENTRY_BLOCK_PTR->succ; e ; e = e->succ_next)
inserted |= convert_regs_2 (file, e->dest);
-
- /* ??? Process all unreachable blocks. Though there's no excuse
+
+ /* ??? Process all unreachable blocks. Though there's no excuse
for keeping these even when not optimizing. */
- for (i = 0; i < n_basic_blocks; ++i)
+ FOR_EACH_BB (b)
{
- basic_block b = BASIC_BLOCK (i);
block_info bi = BLOCK_INFO (b);
if (! bi->done)
@@ -2853,6 +2853,7 @@ convert_regs (file)
inserted |= convert_regs_2 (file, b);
}
}
+ clear_aux_for_blocks ();
fixup_abnormal_edges ();
if (inserted)
@@ -2864,3 +2865,5 @@ convert_regs (file)
return inserted;
}
#endif /* STACK_REGS */
+
+#include "gt-reg-stack.h"
diff --git a/contrib/gcc/regclass.c b/contrib/gcc/regclass.c
index 74594cb..45c69d8 100644
--- a/contrib/gcc/regclass.c
+++ b/contrib/gcc/regclass.c
@@ -26,10 +26,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
+#include "hard-reg-set.h"
#include "rtl.h"
#include "expr.h"
#include "tm_p.h"
-#include "hard-reg-set.h"
#include "flags.h"
#include "basic-block.h"
#include "regs.h"
@@ -48,6 +48,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
static void init_reg_sets_1 PARAMS ((void));
static void init_reg_modes PARAMS ((void));
+static void init_reg_autoinc PARAMS ((void));
/* If we have auto-increment or auto-decrement and we can have secondary
reloads, we are not allowed to use classes requiring secondary
@@ -97,13 +98,13 @@ static const char initial_call_used_regs[] = CALL_USED_REGISTERS;
/* This is much like call_used_regs, except it doesn't have to
be a superset of FIXED_REGISTERS. This vector indicates
- what is really call clobbered, and is used when defining
+ what is really call clobbered, and is used when defining
regs_invalidated_by_call. */
#ifdef CALL_REALLY_USED_REGISTERS
char call_really_used_regs[] = CALL_REALLY_USED_REGISTERS;
#endif
-
+
/* Indexed by hard register number, contains 1 for registers that are
fixed use or call used registers that cannot hold quantities across
calls even if we are willing to save and restore them. call fixed
@@ -155,7 +156,7 @@ HARD_REG_SET reg_class_contents[N_REG_CLASSES];
#define N_REG_INTS \
((FIRST_PSEUDO_REGISTER + (32 - 1)) / 32)
-static const unsigned int_reg_class_contents[N_REG_CLASSES][N_REG_INTS]
+static const unsigned int_reg_class_contents[N_REG_CLASSES][N_REG_INTS]
= REG_CLASS_CONTENTS;
/* For each reg class, number of regs it contains. */
@@ -220,35 +221,22 @@ static int may_move_out_cost[MAX_MACHINE_MODE][N_REG_CLASSES][N_REG_CLASSES];
static int forbidden_inc_dec_class[N_REG_CLASSES];
-/* Indexed by n, is non-zero if (REG n) is used in an auto-inc or auto-dec
+/* Indexed by n, is nonzero if (REG n) is used in an auto-inc or auto-dec
context. */
static char *in_inc_dec;
#endif /* FORBIDDEN_INC_DEC_CLASSES */
-#ifdef CLASS_CANNOT_CHANGE_MODE
-
-/* These are the classes containing only registers that can be used in
- a SUBREG expression that changes the mode of the register in some
- way that is illegal. */
-
-static int class_can_change_mode[N_REG_CLASSES];
-
-/* Registers, including pseudos, which change modes in some way that
- is illegal. */
-
-static regset reg_changes_mode;
-
-#endif /* CLASS_CANNOT_CHANGE_MODE */
-
-#ifdef HAVE_SECONDARY_RELOADS
+#ifdef CANNOT_CHANGE_MODE_CLASS
+/* All registers that have been subreged. Indexed by regno * MAX_MACHINE_MODE
+ + mode. */
+bitmap_head subregs_of_mode;
+#endif
/* Sample MEM values for use by memory_move_secondary_cost. */
-static rtx top_of_stack[MAX_MACHINE_MODE];
-
-#endif /* HAVE_SECONDARY_RELOADS */
+static GTY(()) rtx top_of_stack[MAX_MACHINE_MODE];
/* Linked list of reg_info structures allocated for reg_n_info array.
Grouping all of the allocated structures together in one lump
@@ -258,7 +246,7 @@ struct reg_info_data {
struct reg_info_data *next; /* next set of reg_info structures */
size_t min_index; /* minimum index # */
size_t max_index; /* maximum index # */
- char used_p; /* non-zero if this has been used previously */
+ char used_p; /* nonzero if this has been used previously */
reg_info data[1]; /* beginning of the reg_info data */
};
@@ -296,7 +284,7 @@ init_reg_sets ()
memcpy (call_used_regs, initial_call_used_regs, sizeof call_used_regs);
memset (global_regs, 0, sizeof global_regs);
- /* Do any additional initialization regsets may need */
+ /* Do any additional initialization regsets may need. */
INIT_ONCE_REG_SET ();
#ifdef REG_ALLOC_ORDER
@@ -458,7 +446,7 @@ init_reg_sets_1 ()
RETURN_POPS_ARGS, in which case an explicit CLOBBER will be present.
If we are generating PIC code, the PIC offset table register is
preserved across calls, though the target can override that. */
-
+
if (i == STACK_POINTER_REGNUM || i == FRAME_POINTER_REGNUM)
;
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
@@ -487,7 +475,7 @@ init_reg_sets_1 ()
memset (allocatable_regs_of_mode, 0, sizeof (allocatable_regs_of_mode));
for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
for (i = 0; i < N_REG_CLASSES; i++)
- if (CLASS_MAX_NREGS (i, m) <= reg_class_size[i])
+ if ((unsigned) CLASS_MAX_NREGS (i, m) <= reg_class_size[i])
for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
if (!fixed_regs [j] && TEST_HARD_REG_BIT (reg_class_contents[i], j)
&& HARD_REGNO_MODE_OK (j, m))
@@ -553,22 +541,6 @@ init_reg_sets_1 ()
may_move_out_cost[m][i][j] = 65536;
}
}
-
-#ifdef CLASS_CANNOT_CHANGE_MODE
- {
- HARD_REG_SET c;
- COMPL_HARD_REG_SET (c, reg_class_contents[CLASS_CANNOT_CHANGE_MODE]);
-
- for (i = 0; i < N_REG_CLASSES; i++)
- {
- GO_IF_HARD_REG_SUBSET (reg_class_contents[i], c, ok_class);
- class_can_change_mode [i] = 0;
- continue;
- ok_class:
- class_can_change_mode [i] = 1;
- }
- }
-#endif /* CLASS_CANNOT_CHANGE_MODE */
}
/* Compute the table of register modes.
@@ -606,15 +578,21 @@ init_regs ()
init_reg_modes ();
+ init_reg_autoinc ();
+}
+
+/* Initialize some fake stack-frame MEM references for use in
+ memory_move_secondary_cost. */
+
+void
+init_fake_stack_mems ()
+{
#ifdef HAVE_SECONDARY_RELOADS
{
- /* Make some fake stack-frame MEM references for use in
- memory_move_secondary_cost. */
int i;
for (i = 0; i < MAX_MACHINE_MODE; i++)
top_of_stack[i] = gen_rtx_MEM (i, stack_pointer_rtx);
- ggc_add_rtx_root (top_of_stack, MAX_MACHINE_MODE);
}
#endif
}
@@ -696,7 +674,7 @@ choose_hard_reg_mode (regno, nregs)
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
- if (HARD_REGNO_NREGS (regno, mode) == nregs
+ if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
&& HARD_REGNO_MODE_OK (regno, mode))
found_mode = mode;
@@ -706,7 +684,7 @@ choose_hard_reg_mode (regno, nregs)
for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
- if (HARD_REGNO_NREGS (regno, mode) == nregs
+ if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
&& HARD_REGNO_MODE_OK (regno, mode))
found_mode = mode;
@@ -716,7 +694,7 @@ choose_hard_reg_mode (regno, nregs)
for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
- if (HARD_REGNO_NREGS (regno, mode) == nregs
+ if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
&& HARD_REGNO_MODE_OK (regno, mode))
found_mode = mode;
@@ -726,7 +704,7 @@ choose_hard_reg_mode (regno, nregs)
for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
- if (HARD_REGNO_NREGS (regno, mode) == nregs
+ if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
&& HARD_REGNO_MODE_OK (regno, mode))
found_mode = mode;
@@ -737,7 +715,7 @@ choose_hard_reg_mode (regno, nregs)
for (m = (unsigned int) CCmode; m < (unsigned int) NUM_MACHINE_MODES; ++m)
{
mode = (enum machine_mode) m;
- if (HARD_REGNO_NREGS (regno, mode) == nregs
+ if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
&& HARD_REGNO_MODE_OK (regno, mode))
return mode;
}
@@ -774,8 +752,8 @@ fix_register (name, fixed, call_used)
static const char * const what_option[2][2] = {
{ "call-saved", "call-used" },
{ "no-such-option", "fixed" }};
-
- error ("can't use '%s' as a %s register", name,
+
+ error ("can't use '%s' as a %s register", name,
what_option[fixed][call_used]);
}
else
@@ -883,7 +861,7 @@ static void dump_regclass PARAMS ((FILE *));
static void record_reg_classes PARAMS ((int, int, rtx *, enum machine_mode *,
const char **, rtx,
struct costs *, struct reg_pref *));
-static int copy_cost PARAMS ((rtx, enum machine_mode,
+static int copy_cost PARAMS ((rtx, enum machine_mode,
enum reg_class, int));
static void record_address_regs PARAMS ((rtx, enum reg_class, int));
#ifdef FORBIDDEN_INC_DEC_CLASSES
@@ -952,9 +930,9 @@ dump_regclass (dump)
&& (!in_inc_dec[i]
|| !forbidden_inc_dec_class[(enum reg_class) class])
#endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
- && (!REGNO_REG_SET_P (reg_changes_mode, i)
- || class_can_change_mode [(enum reg_class) class])
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ && ! invalid_mode_change_p (i, (enum reg_class) class,
+ PSEUDO_REGNO_MODE (i))
#endif
)
fprintf (dump, " %s:%i", reg_class_names[class],
@@ -988,26 +966,19 @@ record_operand_costs (insn, op_costs, reg_pref)
Then handle any address registers. Finally record the desired
classes for any pseudos, doing it twice if some pair of
operands are commutative. */
-
+
for (i = 0; i < recog_data.n_operands; i++)
{
op_costs[i] = init_cost;
if (GET_CODE (recog_data.operand[i]) == SUBREG)
- {
- rtx inner = SUBREG_REG (recog_data.operand[i]);
-#ifdef CLASS_CANNOT_CHANGE_MODE
- if (GET_CODE (inner) == REG
- && CLASS_CANNOT_CHANGE_MODE_P (modes[i], GET_MODE (inner)))
- SET_REGNO_REG_SET (reg_changes_mode, REGNO (inner));
-#endif
- recog_data.operand[i] = inner;
- }
+ recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]);
if (GET_CODE (recog_data.operand[i]) == MEM)
record_address_regs (XEXP (recog_data.operand[i], 0),
MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
- else if (constraints[i][0] == 'p')
+ else if (constraints[i][0] == 'p'
+ || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0]))
record_address_regs (recog_data.operand[i],
MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
}
@@ -1031,12 +1002,12 @@ record_operand_costs (insn, op_costs, reg_pref)
xconstraints[i] = constraints[i+1];
xconstraints[i+1] = constraints[i];
record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
- recog_data.operand, modes,
+ recog_data.operand, modes,
xconstraints, insn, op_costs, reg_pref);
}
record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
- recog_data.operand, modes,
+ recog_data.operand, modes,
constraints, insn, op_costs, reg_pref);
}
@@ -1128,10 +1099,10 @@ scan_one_insn (insn, pass)
INSN could not be at the beginning of that block. */
if (previnsn == 0 || GET_CODE (previnsn) == JUMP_INSN)
{
- int b;
- for (b = 0; b < n_basic_blocks; b++)
- if (insn == BLOCK_HEAD (b))
- BLOCK_HEAD (b) = newinsn;
+ basic_block b;
+ FOR_EACH_BB (b)
+ if (insn == b->head)
+ b->head = newinsn;
}
/* This makes one more setting of new insns's dest. */
@@ -1173,41 +1144,18 @@ scan_one_insn (insn, pass)
return insn;
}
-/* This is a pass of the compiler that scans all instructions
- and calculates the preferred class for each pseudo-register.
- This information can be accessed later by calling `reg_preferred_class'.
- This pass comes just before local register allocation. */
+/* Initialize information about which register classes can be used for
+ pseudos that are auto-incremented or auto-decremented. */
-void
-regclass (f, nregs, dump)
- rtx f;
- int nregs;
- FILE *dump;
+static void
+init_reg_autoinc ()
{
- rtx insn;
- int i;
- int pass;
-
- init_recog ();
-
- costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
-
-#ifdef CLASS_CANNOT_CHANGE_MODE
- reg_changes_mode = BITMAP_XMALLOC ();
-#endif
-
#ifdef FORBIDDEN_INC_DEC_CLASSES
-
- in_inc_dec = (char *) xmalloc (nregs);
-
- /* Initialize information about which register classes can be used for
- pseudos that are auto-incremented or auto-decremented. It would
- seem better to put this in init_reg_sets, but we need to be able
- to allocate rtx, which we can't do that early. */
+ int i;
for (i = 0; i < N_REG_CLASSES; i++)
{
- rtx r = gen_rtx_REG (VOIDmode, 0);
+ rtx r = gen_rtx_raw_REG (VOIDmode, 0);
enum machine_mode m;
int j;
@@ -1248,6 +1196,32 @@ regclass (f, nregs, dump)
}
}
#endif /* FORBIDDEN_INC_DEC_CLASSES */
+}
+
+/* This is a pass of the compiler that scans all instructions
+ and calculates the preferred class for each pseudo-register.
+ This information can be accessed later by calling `reg_preferred_class'.
+ This pass comes just before local register allocation. */
+
+void
+regclass (f, nregs, dump)
+ rtx f;
+ int nregs;
+ FILE *dump;
+{
+ rtx insn;
+ int i;
+ int pass;
+
+ init_recog ();
+
+ costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
+
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+
+ in_inc_dec = (char *) xmalloc (nregs);
+
+#endif /* FORBIDDEN_INC_DEC_CLASSES */
/* Normally we scan the insns once and determine the best class to use for
each register. However, if -fexpensive_optimizations are on, we do so
@@ -1256,10 +1230,10 @@ regclass (f, nregs, dump)
for (pass = 0; pass <= flag_expensive_optimizations; pass++)
{
- int index;
+ basic_block bb;
if (dump)
- fprintf (dump, "\n\nPass %i\n\n",pass);
+ fprintf (dump, "\n\nPass %i\n\n",pass);
/* Zero out our accumulation of the cost of each class for each reg. */
memset ((char *) costs, 0, nregs * sizeof (struct costs));
@@ -1278,10 +1252,8 @@ regclass (f, nregs, dump)
insn = scan_one_insn (insn, pass);
}
else
- for (index = 0; index < n_basic_blocks; index++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (index);
-
/* Show that an insn inside a loop is likely to be executed three
times more than insns outside a loop. This is much more
aggressive than the assumptions made elsewhere and is being
@@ -1294,17 +1266,17 @@ regclass (f, nregs, dump)
break;
}
}
-
+
/* Now for each register look at how desirable each class is
and find which class is preferred. Store that in
`prefclass'. Record in `altclass' the largest register
class any of whose registers is better than memory. */
-
+
if (pass == 0)
reg_pref = reg_pref_buffer;
if (dump)
- {
+ {
dump_regclass (dump);
fprintf (dump,"\n");
}
@@ -1319,7 +1291,7 @@ regclass (f, nregs, dump)
/* In non-optimizing compilation REG_N_REFS is not initialized
yet. */
- if (optimize && !REG_N_REFS (i))
+ if (optimize && !REG_N_REFS (i) && !REG_N_SETS (i))
continue;
for (class = (int) ALL_REGS - 1; class > 0; class--)
@@ -1330,9 +1302,9 @@ regclass (f, nregs, dump)
#ifdef FORBIDDEN_INC_DEC_CLASSES
|| (in_inc_dec[i] && forbidden_inc_dec_class[class])
#endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
- || (REGNO_REG_SET_P (reg_changes_mode, i)
- && ! class_can_change_mode [class])
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ || invalid_mode_change_p (i, (enum reg_class) class,
+ PSEUDO_REGNO_MODE (i))
#endif
)
;
@@ -1360,18 +1332,18 @@ regclass (f, nregs, dump)
#ifdef FORBIDDEN_INC_DEC_CLASSES
&& ! (in_inc_dec[i] && forbidden_inc_dec_class[class])
#endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
- && ! (REGNO_REG_SET_P (reg_changes_mode, i)
- && ! class_can_change_mode [class])
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ && ! invalid_mode_change_p (i, (enum reg_class) class,
+ PSEUDO_REGNO_MODE (i))
#endif
)
alt = reg_class_subunion[(int) alt][class];
-
+
/* If we don't add any classes, nothing to try. */
if (alt == best)
alt = NO_REGS;
- if (dump
+ if (dump
&& (reg_pref[i].prefclass != (int) best
|| reg_pref[i].altclass != (int) alt))
{
@@ -1396,9 +1368,6 @@ regclass (f, nregs, dump)
#ifdef FORBIDDEN_INC_DEC_CLASSES
free (in_inc_dec);
#endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
- BITMAP_XFREE (reg_changes_mode);
-#endif
free (costs);
}
@@ -1419,7 +1388,7 @@ regclass (f, nregs, dump)
This procedure works alternative by alternative. For each alternative
we assume that we will be able to allocate all pseudos to their ideal
register class and calculate the cost of using that alternative. Then
- we compute for each operand that is a pseudo-register, the cost of
+ we compute for each operand that is a pseudo-register, the cost of
having the pseudo allocated to each register class and using it in that
alternative. To this cost is added the cost of the alternative.
@@ -1467,7 +1436,7 @@ record_reg_classes (n_alts, n_ops, ops, modes,
classes[i] = NO_REGS;
allows_mem[i] = 0;
- /* If this operand has no constraints at all, we can conclude
+ /* If this operand has no constraints at all, we can conclude
nothing about it since anything is valid. */
if (*p == 0)
@@ -1513,7 +1482,7 @@ record_reg_classes (n_alts, n_ops, ops, modes,
|| REGNO (ops[j]) < FIRST_PSEUDO_REGISTER)
{
/* This op is a pseudo but the one it matches is not. */
-
+
/* If we can't put the other operand into a register, this
alternative can't be used. */
@@ -1544,7 +1513,7 @@ record_reg_classes (n_alts, n_ops, ops, modes,
+ (recog_data.operand_type[i] != OP_IN
? may_move_out_cost[mode][(int) classes[i]][class]
: 0));
-
+
/* If the alternative actually allows memory, make things
a bit cheaper since we won't need an extra insn to
load it. */
@@ -1636,20 +1605,11 @@ record_reg_classes (n_alts, n_ops, ops, modes,
break;
case 'E':
-#ifndef REAL_ARITHMETIC
- /* Match any floating double constant, but only if
- we can examine the bits of it reliably. */
- if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
- || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
- && GET_MODE (op) != VOIDmode && ! flag_pretend_float)
- break;
-#endif
- if (GET_CODE (op) == CONST_DOUBLE)
- win = 1;
- break;
-
case 'F':
- if (GET_CODE (op) == CONST_DOUBLE)
+ if (GET_CODE (op) == CONST_DOUBLE
+ || (GET_CODE (op) == CONST_VECTOR
+ && (GET_MODE_CLASS (GET_MODE (op))
+ == MODE_VECTOR_FLOAT)))
win = 1;
break;
@@ -1720,6 +1680,27 @@ record_reg_classes (n_alts, n_ops, ops, modes,
#ifdef EXTRA_CONSTRAINT
else if (EXTRA_CONSTRAINT (op, c))
win = 1;
+
+ if (EXTRA_MEMORY_CONSTRAINT (c))
+ {
+ /* Every MEM can be reloaded to fit. */
+ allows_mem[i] = 1;
+ if (GET_CODE (op) == MEM)
+ win = 1;
+ }
+ if (EXTRA_ADDRESS_CONSTRAINT (c))
+ {
+ /* Every address can be reloaded to fit. */
+ allows_addr = 1;
+ if (address_operand (op, GET_MODE (op)))
+ win = 1;
+ /* We know this operand is an address, so we want it to be
+ allocated to a register that can be the base of an
+ address, ie BASE_REG_CLASS. */
+ classes[i]
+ = reg_class_subunion[(int) classes[i]]
+ [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+ }
#endif
break;
}
@@ -1739,7 +1720,7 @@ record_reg_classes (n_alts, n_ops, ops, modes,
{
/* We must always fail if the operand is a REG, but
we did not find a suitable class.
-
+
Otherwise we may perform an uninitialized read
from this_op_costs after the `continue' statement
below. */
@@ -1839,7 +1820,7 @@ record_reg_classes (n_alts, n_ops, ops, modes,
and one operand is a pseudo with the other a hard reg or a pseudo
that prefers a register that is in its own register class then
we may want to adjust the cost of that register class to -1.
-
+
Avoid the adjustment if the source does not die to avoid stressing of
register allocator by preferrencing two coliding registers into single
class.
@@ -1866,34 +1847,34 @@ record_reg_classes (n_alts, n_ops, ops, modes,
enum reg_class pref = reg_pref[regno].prefclass;
if ((reg_class_size[(unsigned char) pref]
- == CLASS_MAX_NREGS (pref, mode))
+ == (unsigned) CLASS_MAX_NREGS (pref, mode))
&& REGISTER_MOVE_COST (mode, pref, pref) < 10 * 2)
op_costs[i].cost[(unsigned char) pref] = -1;
}
else if (regno < FIRST_PSEUDO_REGISTER)
for (class = 0; class < N_REG_CLASSES; class++)
if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
- && reg_class_size[class] == CLASS_MAX_NREGS (class, mode))
+ && reg_class_size[class] == (unsigned) CLASS_MAX_NREGS (class, mode))
{
if (reg_class_size[class] == 1)
op_costs[i].cost[class] = -1;
else
{
- for (nr = 0; nr < HARD_REGNO_NREGS (regno, mode); nr++)
+ for (nr = 0; nr < (unsigned) HARD_REGNO_NREGS (regno, mode); nr++)
{
if (! TEST_HARD_REG_BIT (reg_class_contents[class],
regno + nr))
break;
}
- if (nr == HARD_REGNO_NREGS (regno,mode))
+ if (nr == (unsigned) HARD_REGNO_NREGS (regno,mode))
op_costs[i].cost[class] = -1;
}
}
}
}
-/* Compute the cost of loading X into (if TO_P is non-zero) or from (if
+/* Compute the cost of loading X into (if TO_P is nonzero) or from (if
TO_P is zero) a register of class CLASS in mode MODE.
X must not be a pseudo. */
@@ -1919,7 +1900,7 @@ copy_cost (x, mode, class, to_p)
class = PREFERRED_RELOAD_CLASS (x, class);
#ifdef HAVE_SECONDARY_RELOADS
- /* If we need a secondary reload (we assume here that we are using
+ /* If we need a secondary reload (we assume here that we are using
the secondary reload as an intermediate, not a scratch register), the
cost is that to load the input into the intermediate register, then
to copy them. We use a special value of TO_P to avoid recursion. */
@@ -2014,7 +1995,7 @@ record_address_regs (x, class, scale)
/* If index and base registers are the same on this machine, just
record registers in any non-constant operands. We assume here,
- as well as in the tests below, that all addresses are in
+ as well as in the tests below, that all addresses are in
canonical form. */
else if (INDEX_REG_CLASS == MODE_BASE_REG_CLASS (VOIDmode))
@@ -2178,10 +2159,10 @@ static unsigned int reg_n_max;
/* 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
+ NEW_P is nonzero, 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. */
+ RENUMBER_P is nonzero, allocate the reg_renumber array also. */
void
allocate_reg_info (num_regs, new_p, renumber_p)
@@ -2205,7 +2186,7 @@ allocate_reg_info (num_regs, new_p, renumber_p)
{
VARRAY_REG_INIT (reg_n_info, regno_allocated, "reg_n_info");
renumber = (short *) xmalloc (size_renumber);
- reg_pref_buffer = (struct reg_pref *) xmalloc (regno_allocated
+ reg_pref_buffer = (struct reg_pref *) xmalloc (regno_allocated
* sizeof (struct reg_pref));
}
@@ -2218,7 +2199,7 @@ allocate_reg_info (num_regs, new_p, renumber_p)
free ((char *) renumber);
free ((char *) reg_pref);
renumber = (short *) xmalloc (size_renumber);
- reg_pref_buffer = (struct reg_pref *) xmalloc (regno_allocated
+ reg_pref_buffer = (struct reg_pref *) xmalloc (regno_allocated
* sizeof (struct reg_pref));
}
@@ -2226,7 +2207,7 @@ allocate_reg_info (num_regs, new_p, renumber_p)
{
renumber = (short *) xrealloc ((char *) renumber, size_renumber);
reg_pref_buffer = (struct reg_pref *) xrealloc ((char *) reg_pref_buffer,
- regno_allocated
+ regno_allocated
* sizeof (struct reg_pref));
}
}
@@ -2245,7 +2226,7 @@ allocate_reg_info (num_regs, new_p, renumber_p)
{
/* Loop through each of the segments allocated for the actual
reg_info pages, and set up the pointers, zero the pages, etc. */
- for (reg_data = reg_info_head;
+ for (reg_data = reg_info_head;
reg_data && reg_data->max_index >= min;
reg_data = reg_data->next)
{
@@ -2285,7 +2266,7 @@ allocate_reg_info (num_regs, new_p, renumber_p)
if (renumber_p)
reg_renumber = renumber;
- /* Tell the regset code about the new number of registers */
+ /* Tell the regset code about the new number of registers. */
MAX_REGNO_REG_SET (num_regs, new_p, renumber_p);
}
@@ -2331,7 +2312,7 @@ free_reg_info ()
int max_parallel;
-/* Used as a temporary to record the largest number of registers in
+/* Used as a temporary to record the largest number of registers in
PARALLEL in a SET_DEST. This is added to max_parallel. */
static int max_set_parallel;
@@ -2411,6 +2392,8 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
rtx dest;
rtx note;
+ if (!x)
+ return;
code = GET_CODE (x);
switch (code)
{
@@ -2437,6 +2420,10 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
REGNO_LAST_UID (regno) = INSN_UID (insn);
if (REGNO_FIRST_UID (regno) == 0)
REGNO_FIRST_UID (regno) = INSN_UID (insn);
+ /* If we are called by reg_scan_update() (indicated by min_regno
+ being set), we also need to update the reference count. */
+ if (min_regno)
+ REG_N_REFS (regno)++;
}
}
break;
@@ -2453,6 +2440,18 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
reg_scan_mark_refs (XEXP (x, 1), insn, note_flag, min_regno);
break;
+ case CLOBBER:
+ {
+ rtx reg = XEXP (x, 0);
+ if (REG_P (reg)
+ && REGNO (reg) >= min_regno)
+ {
+ REG_N_SETS (REGNO (reg))++;
+ REG_N_REFS (REGNO (reg))++;
+ }
+ }
+ break;
+
case SET:
/* Count a set of the destination if it is a register. */
for (dest = SET_DEST (x);
@@ -2480,7 +2479,7 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
Likewise if it is setting the destination from an address or from a
value equivalent to an address or to the sum of an address and
something else.
-
+
But don't do any of this if the pseudo corresponds to a user
variable since it should have already been set as a pointer based
on the type. */
@@ -2613,3 +2612,54 @@ regset_release_memory ()
{
bitmap_release_memory ();
}
+
+#ifdef CANNOT_CHANGE_MODE_CLASS
+/* Set bits in *USED which correspond to registers which can't change
+ their mode from FROM to any mode in which REGNO was encountered. */
+
+void
+cannot_change_mode_set_regs (used, from, regno)
+ HARD_REG_SET *used;
+ enum machine_mode from;
+ unsigned int regno;
+{
+ enum machine_mode to;
+ int n, i;
+ int start = regno * MAX_MACHINE_MODE;
+
+ EXECUTE_IF_SET_IN_BITMAP (&subregs_of_mode, start, n,
+ if (n >= MAX_MACHINE_MODE + start)
+ return;
+ to = n - start;
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (! TEST_HARD_REG_BIT (*used, i)
+ && REG_CANNOT_CHANGE_MODE_P (i, from, to))
+ SET_HARD_REG_BIT (*used, i);
+ );
+}
+
+/* Return 1 if REGNO has had an invalid mode change in CLASS from FROM
+ mode. */
+
+bool
+invalid_mode_change_p (regno, class, from_mode)
+ unsigned int regno;
+ enum reg_class class;
+ enum machine_mode from_mode;
+{
+ enum machine_mode to_mode;
+ int n;
+ int start = regno * MAX_MACHINE_MODE;
+
+ EXECUTE_IF_SET_IN_BITMAP (&subregs_of_mode, start, n,
+ if (n >= MAX_MACHINE_MODE + start)
+ return 0;
+ to_mode = n - start;
+ if (CANNOT_CHANGE_MODE_CLASS (from_mode, to_mode, class))
+ return 1;
+ );
+ return 0;
+}
+#endif /* CANNOT_CHANGE_MODE_CLASS */
+
+#include "gt-regclass.h"
diff --git a/contrib/gcc/regmove.c b/contrib/gcc/regmove.c
index 048cfb6..cb5e547 100644
--- a/contrib/gcc/regmove.c
+++ b/contrib/gcc/regmove.c
@@ -80,7 +80,7 @@ static int regclass_compatible_p PARAMS ((int, int));
static int replacement_quality PARAMS ((rtx));
static int fixup_match_2 PARAMS ((rtx, rtx, rtx, rtx, FILE *));
-/* Return non-zero if registers with CLASS1 and CLASS2 can be merged without
+/* Return nonzero if registers with CLASS1 and CLASS2 can be merged without
causing too much register allocation problems. */
static int
regclass_compatible_p (class0, class1)
@@ -223,7 +223,7 @@ mark_flags_life_zones (flags)
{
int flags_regno;
int flags_nregs;
- int block;
+ basic_block block;
#ifdef HAVE_cc0
/* If we found a flags register on a cc0 host, bail. */
@@ -254,13 +254,13 @@ mark_flags_life_zones (flags)
flags_set_1_rtx = flags;
/* Process each basic block. */
- for (block = n_basic_blocks - 1; block >= 0; block--)
+ FOR_EACH_BB_REVERSE (block)
{
rtx insn, end;
int live;
- insn = BLOCK_HEAD (block);
- end = BLOCK_END (block);
+ insn = block->head;
+ end = block->end;
/* Look out for the (unlikely) case of flags being live across
basic block boundaries. */
@@ -269,7 +269,7 @@ mark_flags_life_zones (flags)
{
int i;
for (i = 0; i < flags_nregs; ++i)
- live |= REGNO_REG_SET_P (BASIC_BLOCK (block)->global_live_at_start,
+ live |= REGNO_REG_SET_P (block->global_live_at_start,
flags_regno + i);
}
#endif
@@ -431,6 +431,16 @@ optimize_reg_copy_1 (insn, dest, src)
continue;
if (reg_set_p (src, p) || reg_set_p (dest, p)
+ /* If SRC is an asm-declared register, it must not be replaced
+ in any asm. Unfortunately, the REG_EXPR tree for the asm
+ variable may be absent in the SRC rtx, so we can't check the
+ actual register declaration easily (the asm operand will have
+ it, though). To avoid complicating the test for a rare case,
+ we just don't perform register replacement for a hard reg
+ mentioned in an asm. */
+ || (sregno < FIRST_PSEUDO_REGISTER
+ && asm_noperands (PATTERN (p)) >= 0
+ && reg_overlap_mentioned_p (src, PATTERN (p)))
/* Don't change a USE of a register. */
|| (GET_CODE (PATTERN (p)) == USE
&& reg_overlap_mentioned_p (src, XEXP (PATTERN (p), 0))))
@@ -776,7 +786,7 @@ copy_src_to_dest (insn, src, dest, old_max_uid)
/* Generate the src->dest move. */
start_sequence ();
emit_move_insn (dest, src);
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
/* If this sequence uses new registers, we may not use it. */
if (old_num_regs != reg_rtx_no
@@ -793,7 +803,7 @@ copy_src_to_dest (insn, src, dest, old_max_uid)
p_move_notes = &REG_NOTES (move_insn);
p_insn_notes = &REG_NOTES (insn);
- /* Move any notes mentioning src to the move instruction */
+ /* Move any notes mentioning src to the move instruction. */
for (link = REG_NOTES (insn); link != NULL_RTX; link = next)
{
next = XEXP (link, 1);
@@ -812,7 +822,7 @@ copy_src_to_dest (insn, src, dest, old_max_uid)
*p_move_notes = NULL_RTX;
*p_insn_notes = NULL_RTX;
- /* Is the insn the head of a basic block? If so extend it */
+ /* Is the insn the head of a basic block? If so extend it. */
insn_uid = INSN_UID (insn);
move_uid = INSN_UID (move_insn);
if (insn_uid < old_max_uid)
@@ -951,7 +961,7 @@ fixup_match_2 (insn, dst, src, offset, regmove_dump_file)
if (perhaps_ends_bb_p (p))
break;
else if (! INSN_P (p))
- continue;
+ continue;
if (find_regno_note (p, REG_DEAD, REGNO (dst)))
dst_death = p;
@@ -963,7 +973,7 @@ fixup_match_2 (insn, dst, src, offset, regmove_dump_file)
&& GET_CODE (SET_SRC (pset)) == PLUS
&& XEXP (SET_SRC (pset), 0) == src
&& GET_CODE (XEXP (SET_SRC (pset), 1)) == CONST_INT)
- {
+ {
HOST_WIDE_INT newconst
= INTVAL (offset) - INTVAL (XEXP (SET_SRC (pset), 1));
rtx add = gen_add3_insn (dst, dst, GEN_INT (newconst));
@@ -1014,10 +1024,10 @@ fixup_match_2 (insn, dst, src, offset, regmove_dump_file)
#endif
return 1;
}
- }
+ }
if (reg_set_p (dst, PATTERN (p)))
- break;
+ break;
/* If we have passed a call instruction, and the
pseudo-reg SRC is not already live across a call,
@@ -1026,19 +1036,19 @@ fixup_match_2 (insn, dst, src, offset, regmove_dump_file)
hard regs are clobbered. Thus, we only use it for src for
non-call insns. */
if (GET_CODE (p) == CALL_INSN)
- {
+ {
if (! dst_death)
num_calls++;
- if (REG_N_CALLS_CROSSED (REGNO (src)) == 0)
- break;
+ if (REG_N_CALLS_CROSSED (REGNO (src)) == 0)
+ break;
if (call_used_regs [REGNO (dst)]
|| find_reg_fusage (p, CLOBBER, dst))
break;
- }
+ }
else if (reg_set_p (src, PATTERN (p)))
- break;
+ break;
}
return 0;
@@ -1062,6 +1072,7 @@ regmove_optimize (f, nregs, regmove_dump_file)
int pass;
int i;
rtx copy_src, copy_dst;
+ basic_block bb;
/* ??? Hack. Regmove doesn't examine the CFG, and gets mightily
confused by non-call exceptions ending blocks. */
@@ -1077,8 +1088,8 @@ regmove_optimize (f, nregs, regmove_dump_file)
regmove_bb_head = (int *) xmalloc (sizeof (int) * (old_max_uid + 1));
for (i = old_max_uid; i >= 0; i--) regmove_bb_head[i] = -1;
- for (i = 0; i < n_basic_blocks; i++)
- regmove_bb_head[INSN_UID (BLOCK_HEAD (i))] = i;
+ FOR_EACH_BB (bb)
+ regmove_bb_head[INSN_UID (bb->head)] = bb->index;
/* A forward/backward pass. Replace output operands with input operands. */
@@ -1132,8 +1143,8 @@ regmove_optimize (f, nregs, regmove_dump_file)
}
}
}
- if (! flag_regmove)
- continue;
+ if (! flag_regmove)
+ continue;
if (! find_matches (insn, &match))
continue;
@@ -1371,7 +1382,7 @@ regmove_optimize (f, nregs, regmove_dump_file)
it for this optimization, as this would make it
no longer equivalent to a constant. */
- if (reg_is_remote_constant_p (src, insn, f))
+ if (reg_is_remote_constant_p (src, insn, f))
{
if (!copy_src)
{
@@ -1505,15 +1516,15 @@ regmove_optimize (f, nregs, regmove_dump_file)
/* In fixup_match_1, some insns may have been inserted after basic block
ends. Fix that here. */
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- rtx end = BLOCK_END (i);
+ rtx end = bb->end;
rtx new = end;
rtx next = NEXT_INSN (new);
while (next != 0 && INSN_UID (next) >= old_max_uid
- && (i == n_basic_blocks - 1 || BLOCK_HEAD (i + 1) != next))
+ && (bb->next_bb == EXIT_BLOCK_PTR || bb->next_bb->head != next))
new = next, next = NEXT_INSN (new);
- BLOCK_END (i) = new;
+ bb->end = new;
}
done:
@@ -2139,10 +2150,10 @@ static int record_stack_memrefs PARAMS ((rtx *, void *));
void
combine_stack_adjustments ()
{
- int i;
+ basic_block bb;
- for (i = 0; i < n_basic_blocks; ++i)
- combine_stack_adjustments_for_block (BASIC_BLOCK (i));
+ FOR_EACH_BB (bb)
+ combine_stack_adjustments_for_block (bb);
}
/* Recognize a MEM of the form (sp) or (plus sp const). */
diff --git a/contrib/gcc/regrename.c b/contrib/gcc/regrename.c
index efdd9f9..9b7dfd6 100644
--- a/contrib/gcc/regrename.c
+++ b/contrib/gcc/regrename.c
@@ -36,13 +36,6 @@
#include "toplev.h"
#include "obstack.h"
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-#ifndef REGNO_MODE_OK_FOR_BASE_P
-#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) REGNO_OK_FOR_BASE_P (REGNO)
-#endif
-
#ifndef REG_MODE_OK_FOR_BASE_P
#define REG_MODE_OK_FOR_BASE_P(REGNO, MODE) REG_OK_FOR_BASE_P (REGNO)
#endif
@@ -177,7 +170,7 @@ merge_overlapping_regs (b, pset, chain)
reg's live range. */
if (t != chain)
IOR_HARD_REG_SET (*pset, live);
- clear_dead_regs (&live, REG_UNUSED, REG_NOTES (insn));
+ clear_dead_regs (&live, REG_UNUSED, REG_NOTES (insn));
}
insn = NEXT_INSN (insn);
}
@@ -201,7 +194,7 @@ regrename_optimize ()
{
int tick[FIRST_PSEUDO_REGISTER];
int this_tick = 0;
- int b;
+ basic_block bb;
char *first_obj;
memset (tick, 0, sizeof tick);
@@ -209,9 +202,8 @@ regrename_optimize ()
gcc_obstack_init (&rename_obstack);
first_obj = (char *) obstack_alloc (&rename_obstack, 0);
- for (b = 0; b < n_basic_blocks; b++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (b);
struct du_chain *all_chains = 0;
HARD_REG_SET unavailable;
HARD_REG_SET regs_seen;
@@ -219,7 +211,7 @@ regrename_optimize ()
CLEAR_HARD_REG_SET (unavailable);
if (rtl_dump_file)
- fprintf (rtl_dump_file, "\nBasic block %d:\n", b);
+ fprintf (rtl_dump_file, "\nBasic block %d:\n", bb->index);
all_chains = build_def_use (bb);
@@ -231,10 +223,10 @@ regrename_optimize ()
if (frame_pointer_needed)
{
int i;
-
+
for (i = HARD_REGNO_NREGS (FRAME_POINTER_REGNUM, Pmode); i--;)
SET_HARD_REG_BIT (unavailable, FRAME_POINTER_REGNUM + i);
-
+
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
for (i = HARD_REGNO_NREGS (HARD_FRAME_POINTER_REGNUM, Pmode); i--;)
SET_HARD_REG_BIT (unavailable, HARD_FRAME_POINTER_REGNUM + i);
@@ -253,7 +245,7 @@ regrename_optimize ()
int i;
all_chains = this->next_chain;
-
+
#if 0 /* This just disables optimization opportunities. */
/* Only rename once we've seen the reg more than once. */
if (! TEST_HARD_REG_BIT (regs_seen, reg))
@@ -309,9 +301,9 @@ regrename_optimize ()
|| (! regs_ever_live[new_reg + i]
&& ! call_used_regs[new_reg + i])
#ifdef LEAF_REGISTERS
- /* We can't use a non-leaf register if we're in a
+ /* We can't use a non-leaf register if we're in a
leaf function. */
- || (current_function_is_leaf
+ || (current_function_is_leaf
&& !LEAF_REGISTERS[new_reg + i])
#endif
#ifdef HARD_REGNO_RENAME_OK
@@ -346,7 +338,7 @@ regrename_optimize ()
reg_names[reg], INSN_UID (last->insn));
if (last->need_caller_save_reg)
fprintf (rtl_dump_file, " crosses a call");
- }
+ }
if (best_new_reg == -1)
{
@@ -445,7 +437,7 @@ scan_rtx_reg (insn, loc, class, action, type, earlyclobber)
if (*this->loc == cc0_rtx)
p = &this->next_chain;
else
- {
+ {
int regno = REGNO (*this->loc);
int nregs = HARD_REGNO_NREGS (regno, GET_MODE (*this->loc));
int exact_match = (regno == this_regno && nregs == this_nregs);
@@ -462,7 +454,7 @@ scan_rtx_reg (insn, loc, class, action, type, earlyclobber)
if (! exact_match)
abort ();
- /* ??? Class NO_REGS can happen if the md file makes use of
+ /* ??? Class NO_REGS can happen if the md file makes use of
EXTRA_CONSTRAINTS to match registers. Which is arguably
wrong, but there we are. Since we know not what this may
be replaced with, terminate the chain. */
@@ -705,7 +697,7 @@ scan_rtx (insn, loc, class, action, type, earlyclobber)
return;
case ZERO_EXTRACT:
- case SIGN_EXTRACT:
+ case SIGN_EXTRACT:
scan_rtx (insn, &XEXP (x, 0), class, action,
type == OP_IN ? OP_IN : OP_INOUT, earlyclobber);
scan_rtx (insn, &XEXP (x, 1), class, action, OP_IN, 0);
@@ -746,7 +738,7 @@ scan_rtx (insn, loc, class, action, type, earlyclobber)
}
}
-/* Build def/use chain */
+/* Build def/use chain. */
static struct du_chain *
build_def_use (bb)
@@ -786,7 +778,8 @@ build_def_use (bb)
icode = recog_memoized (insn);
extract_insn (insn);
- constrain_operands (1);
+ if (! constrain_operands (1))
+ fatal_insn_not_found (insn);
preprocess_constraints ();
alt = which_alternative;
n_ops = recog_data.n_operands;
@@ -813,14 +806,14 @@ build_def_use (bb)
recog_data.operand_type[i], 0);
/* Step 2: Close chains for which we have reads outside operands.
- We do this by munging all operands into CC0, and closing
+ We do this by munging all operands into CC0, and closing
everything remaining. */
for (i = 0; i < n_ops; i++)
{
old_operands[i] = recog_data.operand[i];
/* Don't squash match_operator or match_parallel here, since
- we don't know that all of the contained registers are
+ we don't know that all of the contained registers are
reachable by proper operands. */
if (recog_data.constraints[i][0] == '\0')
continue;
@@ -952,7 +945,7 @@ build_def_use (bb)
enum reg_class class = recog_op_alt[i][alt].class;
if (GET_CODE (op) == REG
- && REGNO (op) == ORIGINAL_REGNO (op))
+ && REGNO (op) == ORIGINAL_REGNO (op))
continue;
scan_rtx (insn, loc, class, mark_write, OP_OUT,
@@ -1016,11 +1009,11 @@ dump_def_use_chain (chains)
/* The following code does forward propagation of hard register copies.
The object is to eliminate as many dependencies as possible, so that
we have the most scheduling freedom. As a side effect, we also clean
- up some silly register allocation decisions made by reload. This
+ up some silly register allocation decisions made by reload. This
code may be obsoleted by a new register allocator. */
/* For each register, we have a list of registers that contain the same
- value. The OLDEST_REGNO field points to the head of the list, and
+ value. The OLDEST_REGNO field points to the head of the list, and
the NEXT_REGNO field runs through the list. The MODE field indicates
what mode the data is known to be in; this field is VOIDmode when the
register is not known to contain valid data. */
@@ -1049,6 +1042,9 @@ static int kill_autoinc_value PARAMS ((rtx *, void *));
static void copy_value PARAMS ((rtx, rtx, struct value_data *));
static bool mode_change_ok PARAMS ((enum machine_mode, enum machine_mode,
unsigned int));
+static rtx maybe_mode_change PARAMS ((enum machine_mode, enum machine_mode,
+ enum machine_mode, unsigned int,
+ unsigned int));
static rtx find_oldest_value_reg PARAMS ((enum reg_class, rtx,
struct value_data *));
static bool replace_oldest_value_reg PARAMS ((rtx *, enum reg_class, rtx,
@@ -1058,7 +1054,7 @@ static bool replace_oldest_value_addr PARAMS ((rtx *, enum reg_class,
struct value_data *));
static bool replace_oldest_value_mem PARAMS ((rtx, rtx, struct value_data *));
static bool copyprop_hardreg_forward_1 PARAMS ((basic_block,
- struct value_data *));
+ struct value_data *));
extern void debug_value_data PARAMS ((struct value_data *));
#ifdef ENABLE_CHECKING
static void validate_value_data PARAMS ((struct value_data *));
@@ -1085,7 +1081,7 @@ kill_value_regno (regno, vd)
else if ((next = vd->e[regno].next_regno) != INVALID_REGNUM)
{
for (i = next; i != INVALID_REGNUM; i = vd->e[i].next_regno)
- vd->e[i].oldest_regno = next;
+ vd->e[i].oldest_regno = next;
}
vd->e[regno].mode = VOIDmode;
@@ -1108,7 +1104,7 @@ kill_value (x, vd)
/* SUBREGS are supposed to have been eliminated by now. But some
ports, e.g. i386 sse, use them to smuggle vector type information
through to instruction selection. Each such SUBREG should simplify,
- so if we get a NULL we've done something wrong elsewhere. */
+ so if we get a NULL we've done something wrong elsewhere. */
if (GET_CODE (x) == SUBREG)
x = simplify_subreg (GET_MODE (x), SUBREG_REG (x),
@@ -1186,7 +1182,7 @@ kill_clobbered_value (x, set, data)
kill_value (x, vd);
}
-/* Called through note_stores. If X is set, not clobbered, kill its
+/* Called through note_stores. If X is set, not clobbered, kill its
current value and install it as the root of its own value list. */
static void
@@ -1200,7 +1196,7 @@ kill_set_value (x, set, data)
{
kill_value (x, vd);
if (REG_P (x))
- set_value_regno (REGNO (x), GET_MODE (x), vd);
+ set_value_regno (REGNO (x), GET_MODE (x), vd);
}
}
@@ -1247,7 +1243,7 @@ copy_value (dest, src, vd)
return;
/* Do not propagate copies to the stack pointer, as that can leave
- memory accesses with no scheduling dependancy on the stack update. */
+ memory accesses with no scheduling dependency on the stack update. */
if (dr == STACK_POINTER_REGNUM)
return;
@@ -1268,6 +1264,26 @@ copy_value (dest, src, vd)
if (vd->e[sr].mode == VOIDmode)
set_value_regno (sr, vd->e[dr].mode, vd);
+ /* If we are narrowing the input to a smaller number of hard regs,
+ and it is in big endian, we are really extracting a high part.
+ Since we generally associate a low part of a value with the value itself,
+ we must not do the same for the high part.
+ Note we can still get low parts for the same mode combination through
+ a two-step copy involving differently sized hard regs.
+ Assume hard regs fr* are 32 bits bits each, while r* are 64 bits each:
+ (set (reg:DI r0) (reg:DI fr0))
+ (set (reg:SI fr2) (reg:SI r0))
+ loads the low part of (reg:DI fr0) - i.e. fr1 - into fr2, while:
+ (set (reg:SI fr2) (reg:SI fr0))
+ loads the high part of (reg:DI fr0) into fr2.
+
+ We can't properly represent the latter case in our tables, so don't
+ record anything then. */
+ else if (sn < (unsigned int) HARD_REGNO_NREGS (sr, vd->e[sr].mode)
+ && (GET_MODE_SIZE (vd->e[sr].mode) > UNITS_PER_WORD
+ ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
+ return;
+
/* If SRC had been assigned a mode narrower than the copy, we can't
link DEST into the chain, because not all of the pieces of the
copy came from oldest_regno. */
@@ -1297,15 +1313,46 @@ mode_change_ok (orig_mode, new_mode, regno)
if (GET_MODE_SIZE (orig_mode) < GET_MODE_SIZE (new_mode))
return false;
-#ifdef CLASS_CANNOT_CHANGE_MODE
- if (TEST_HARD_REG_BIT (reg_class_contents[CLASS_CANNOT_CHANGE_MODE], regno)
- && CLASS_CANNOT_CHANGE_MODE_P (orig_mode, new_mode))
- return false;
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ return !REG_CANNOT_CHANGE_MODE_P (regno, orig_mode, new_mode);
#endif
return true;
}
+/* Register REGNO was originally set in ORIG_MODE. It - or a copy of it -
+ was copied in COPY_MODE to COPY_REGNO, and then COPY_REGNO was accessed
+ in NEW_MODE.
+ Return a NEW_MODE rtx for REGNO if that's OK, otherwise return NULL_RTX. */
+
+static rtx
+maybe_mode_change (orig_mode, copy_mode, new_mode, regno, copy_regno)
+ enum machine_mode orig_mode, copy_mode, new_mode;
+ unsigned int regno, copy_regno;
+{
+ if (orig_mode == new_mode)
+ return gen_rtx_raw_REG (new_mode, regno);
+ else if (mode_change_ok (orig_mode, new_mode, regno))
+ {
+ int copy_nregs = HARD_REGNO_NREGS (copy_regno, copy_mode);
+ int use_nregs = HARD_REGNO_NREGS (copy_regno, new_mode);
+ int copy_offset
+ = GET_MODE_SIZE (copy_mode) / copy_nregs * (copy_nregs - use_nregs);
+ int offset
+ = GET_MODE_SIZE (orig_mode) - GET_MODE_SIZE (new_mode) - copy_offset;
+ int byteoffset = offset % UNITS_PER_WORD;
+ int wordoffset = offset - byteoffset;
+
+ offset = ((WORDS_BIG_ENDIAN ? wordoffset : 0)
+ + (BYTES_BIG_ENDIAN ? byteoffset : 0));
+ return gen_rtx_raw_REG (new_mode,
+ regno + subreg_regno_offset (regno, orig_mode,
+ offset,
+ new_mode));
+ }
+ return NULL_RTX;
+}
+
/* Find the oldest copy of the value contained in REGNO that is in
register class CLASS and has mode MODE. If found, return an rtx
of that oldest register, otherwise return NULL. */
@@ -1335,14 +1382,18 @@ find_oldest_value_reg (class, reg, vd)
}
for (i = vd->e[regno].oldest_regno; i != regno; i = vd->e[i].next_regno)
+ {
+ enum machine_mode oldmode = vd->e[i].mode;
+ rtx new;
+
if (TEST_HARD_REG_BIT (reg_class_contents[class], i)
- && (vd->e[i].mode == mode
- || mode_change_ok (vd->e[i].mode, mode, i)))
+ && (new = maybe_mode_change (oldmode, vd->e[regno].mode, mode, i,
+ regno)))
{
- rtx new = gen_rtx_raw_REG (mode, i);
ORIGINAL_REGNO (new) = ORIGINAL_REGNO (reg);
return new;
}
+ }
return NULL_RTX;
}
@@ -1466,7 +1517,7 @@ replace_oldest_value_addr (loc, class, mode, insn, vd)
if (locI)
changed |= replace_oldest_value_addr (locI, INDEX_REG_CLASS, mode,
- insn, vd);
+ insn, vd);
if (locB)
changed |= replace_oldest_value_addr (locB,
MODE_BASE_REG_CLASS (mode),
@@ -1501,7 +1552,7 @@ replace_oldest_value_addr (loc, class, mode, insn, vd)
else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
changed |= replace_oldest_value_addr (&XVECEXP (x, i, j), class,
- mode, insn, vd);
+ mode, insn, vd);
}
return changed;
@@ -1546,7 +1597,8 @@ copyprop_hardreg_forward_1 (bb, vd)
set = single_set (insn);
extract_insn (insn);
- constrain_operands (1);
+ if (! constrain_operands (1))
+ fatal_insn_not_found (insn);
preprocess_constraints ();
alt = which_alternative;
n_ops = recog_data.n_operands;
@@ -1616,7 +1668,7 @@ copyprop_hardreg_forward_1 (bb, vd)
fprintf (rtl_dump_file,
"insn %u: replaced reg %u with %u\n",
INSN_UID (insn), regno, REGNO (new));
- changed = true;
+ changed = true;
goto did_replacement;
}
}
@@ -1624,21 +1676,23 @@ copyprop_hardreg_forward_1 (bb, vd)
/* Otherwise, try all valid registers and see if its valid. */
for (i = vd->e[regno].oldest_regno; i != regno;
i = vd->e[i].next_regno)
- if (vd->e[i].mode == mode
- || mode_change_ok (vd->e[i].mode, mode, i))
- {
- new = gen_rtx_raw_REG (mode, i);
- if (validate_change (insn, &SET_SRC (set), new, 0))
- {
- ORIGINAL_REGNO (new) = ORIGINAL_REGNO (src);
- if (rtl_dump_file)
- fprintf (rtl_dump_file,
- "insn %u: replaced reg %u with %u\n",
- INSN_UID (insn), regno, REGNO (new));
- changed = true;
- goto did_replacement;
- }
- }
+ {
+ new = maybe_mode_change (vd->e[i].mode, vd->e[regno].mode,
+ mode, i, regno);
+ if (new != NULL_RTX)
+ {
+ if (validate_change (insn, &SET_SRC (set), new, 0))
+ {
+ ORIGINAL_REGNO (new) = ORIGINAL_REGNO (src);
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file,
+ "insn %u: replaced reg %u with %u\n",
+ INSN_UID (insn), regno, REGNO (new));
+ changed = true;
+ goto did_replacement;
+ }
+ }
+ }
}
no_move_special_case:
@@ -1678,7 +1732,7 @@ copyprop_hardreg_forward_1 (bb, vd)
}
else if (GET_CODE (recog_data.operand[i]) == MEM)
replaced = replace_oldest_value_mem (recog_data.operand[i],
- insn, vd);
+ insn, vd);
/* If we performed any replacement, update match_dups. */
if (replaced)
@@ -1724,30 +1778,30 @@ copyprop_hardreg_forward ()
{
struct value_data *all_vd;
bool need_refresh;
- int b;
+ basic_block bb, bbp = 0;
need_refresh = false;
- all_vd = xmalloc (sizeof (struct value_data) * n_basic_blocks);
+ all_vd = xmalloc (sizeof (struct value_data) * last_basic_block);
- for (b = 0; b < n_basic_blocks; b++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (b);
-
/* If a block has a single predecessor, that we've already
processed, begin with the value data that was live at
the end of the predecessor block. */
/* ??? Ought to use more intelligent queueing of blocks. */
+ if (bb->pred)
+ for (bbp = bb; bbp && bbp != bb->pred->src; bbp = bbp->prev_bb);
if (bb->pred
- && ! bb->pred->pred_next
+ && ! bb->pred->pred_next
&& ! (bb->pred->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
- && bb->pred->src->index != ENTRY_BLOCK
- && bb->pred->src->index < b)
- all_vd[b] = all_vd[bb->pred->src->index];
+ && bb->pred->src != ENTRY_BLOCK_PTR
+ && bbp)
+ all_vd[bb->index] = all_vd[bb->pred->src->index];
else
- init_value_data (all_vd + b);
+ init_value_data (all_vd + bb->index);
- if (copyprop_hardreg_forward_1 (bb, all_vd + b))
+ if (copyprop_hardreg_forward_1 (bb, all_vd + bb->index))
need_refresh = true;
}
diff --git a/contrib/gcc/regs.h b/contrib/gcc/regs.h
index 0b35f07..2e838e3 100644
--- a/contrib/gcc/regs.h
+++ b/contrib/gcc/regs.h
@@ -21,6 +21,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "varray.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
#define REG_BYTES(R) mode_size[(int) GET_MODE (R)]
@@ -64,6 +66,8 @@ typedef struct reg_info_def
extern varray_type reg_n_info;
+extern bitmap_head subregs_of_mode;
+
/* Indexed by n, gives number of times (REG n) is used or set. */
#define REG_N_REFS(N) (VARRAY_REG (reg_n_info, N)->refs)
@@ -104,13 +108,6 @@ extern varray_type reg_n_info;
#define REG_N_DEATHS(N) (VARRAY_REG (reg_n_info, N)->deaths)
-/* Indexed by N; says whether a pseudo register N was ever used
- within a SUBREG that changes the mode of the reg in some way
- that is illegal for a given class (usually floating-point)
- of registers. */
-
-#define REG_CHANGES_MODE(N) (VARRAY_REG (reg_n_info, N)->changes_mode)
-
/* Get the number of consecutive words required to hold pseudo-reg N. */
#define PSEUDO_REGNO_SIZE(N) \
diff --git a/contrib/gcc/reload.c b/contrib/gcc/reload.c
index 71ed1d6..b151af7 100644
--- a/contrib/gcc/reload.c
+++ b/contrib/gcc/reload.c
@@ -244,6 +244,7 @@ static enum reg_class find_valid_class PARAMS ((enum machine_mode, int,
unsigned int));
static int reload_inner_reg_of_subreg PARAMS ((rtx, enum machine_mode, int));
static void push_replacement PARAMS ((rtx *, int, enum machine_mode));
+static void dup_replacements PARAMS ((rtx *, rtx *));
static void combine_reloads PARAMS ((void));
static int find_reusable_reload PARAMS ((rtx *, rtx, enum reg_class,
enum reload_type, int, int));
@@ -257,6 +258,7 @@ static int alternative_allows_memconst PARAMS ((const char *, int));
static rtx find_reloads_toplev PARAMS ((rtx, int, enum reload_type, int,
int, rtx, int *));
static rtx make_memloc PARAMS ((rtx, int));
+static int maybe_memory_address_p PARAMS ((enum machine_mode, rtx, rtx *));
static int find_reloads_address PARAMS ((enum machine_mode, rtx *, rtx, rtx *,
int, enum reload_type, int, rtx));
static rtx subst_reg_equivs PARAMS ((rtx, rtx));
@@ -275,7 +277,7 @@ static int find_inc_amount PARAMS ((rtx, rtx));
#ifdef HAVE_SECONDARY_RELOADS
/* Determine if any secondary reloads are needed for loading (if IN_P is
- non-zero) or storing (if IN_P is zero) X to or from a reload register of
+ nonzero) or storing (if IN_P is zero) X to or from a reload register of
register class RELOAD_CLASS in mode RELOAD_MODE. If secondary reloads
are needed, push them.
@@ -367,7 +369,7 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
if (icode != CODE_FOR_nothing)
{
- /* If IN_P is non-zero, the reload register will be the output in
+ /* If IN_P is nonzero, the reload register will be the output in
operand 0. If IN_P is zero, the reload register will be the input
in operand 1. Outputs should have an initial "=", which we must
skip. */
@@ -644,7 +646,7 @@ get_secondary_mem (x, mode, opnum, type)
: type == RELOAD_FOR_OUTPUT ? RELOAD_FOR_OUTPUT_ADDRESS
: RELOAD_OTHER);
- find_reloads_address (mode, (rtx*) 0, XEXP (loc, 0), &XEXP (loc, 0),
+ find_reloads_address (mode, &loc, XEXP (loc, 0), &XEXP (loc, 0),
opnum, type, 0, 0);
}
@@ -817,6 +819,13 @@ reload_inner_reg_of_subreg (x, mode, output)
|| REGNO (inner) >= FIRST_PSEUDO_REGISTER)
return 0;
+ if (!subreg_offset_representable_p
+ (REGNO (SUBREG_REG (x)),
+ GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x),
+ GET_MODE (x)))
+ return 1;
+
/* If INNER is not ok for MODE, then INNER will need reloading. */
if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode))
return 1;
@@ -828,7 +837,7 @@ reload_inner_reg_of_subreg (x, mode, output)
&& output
&& GET_MODE_SIZE (GET_MODE (inner)) > UNITS_PER_WORD
&& ((GET_MODE_SIZE (GET_MODE (inner)) / UNITS_PER_WORD)
- != HARD_REGNO_NREGS (REGNO (inner), GET_MODE (inner))));
+ != (int) HARD_REGNO_NREGS (REGNO (inner), GET_MODE (inner))));
}
/* Record one reload that needs to be performed.
@@ -837,7 +846,7 @@ reload_inner_reg_of_subreg (x, mode, output)
(IN is zero for data not read, and OUT is zero for data not written.)
INLOC and OUTLOC point to the places in the instructions where
IN and OUT were found.
- If IN and OUT are both non-zero, it means the same register must be used
+ If IN and OUT are both nonzero, it means the same register must be used
to reload both IN and OUT.
CLASS is a register class required for the reloaded data.
@@ -966,9 +975,8 @@ push_reload (in, out, inloc, outloc, class,
if (in != 0 && GET_CODE (in) == SUBREG
&& (subreg_lowpart_p (in) || strict_low)
-#ifdef CLASS_CANNOT_CHANGE_MODE
- && (class != CLASS_CANNOT_CHANGE_MODE
- || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), inmode))
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, class)
#endif
&& (CONSTANT_P (SUBREG_REG (in))
|| GET_CODE (SUBREG_REG (in)) == PLUS
@@ -1005,8 +1013,8 @@ push_reload (in, out, inloc, outloc, class,
> UNITS_PER_WORD)
&& ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
/ UNITS_PER_WORD)
- != HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
- GET_MODE (SUBREG_REG (in)))))
+ != (int) HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
+ GET_MODE (SUBREG_REG (in)))))
|| ! HARD_REGNO_MODE_OK (subreg_regno (in), inmode)))
#ifdef SECONDARY_INPUT_RELOAD_CLASS
|| (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS
@@ -1015,14 +1023,11 @@ push_reload (in, out, inloc, outloc, class,
SUBREG_REG (in))
== NO_REGS))
#endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
|| (GET_CODE (SUBREG_REG (in)) == REG
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
- && (TEST_HARD_REG_BIT
- (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
- REGNO (SUBREG_REG (in))))
- && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)),
- inmode))
+ && REG_CANNOT_CHANGE_MODE_P
+ (REGNO (SUBREG_REG (in)), GET_MODE (SUBREG_REG (in)), inmode))
#endif
))
{
@@ -1080,10 +1085,8 @@ push_reload (in, out, inloc, outloc, class,
and in that case the constraint should label it input-output.) */
if (out != 0 && GET_CODE (out) == SUBREG
&& (subreg_lowpart_p (out) || strict_low)
-#ifdef CLASS_CANNOT_CHANGE_MODE
- && (class != CLASS_CANNOT_CHANGE_MODE
- || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
- outmode))
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, class)
#endif
&& (CONSTANT_P (SUBREG_REG (out))
|| strict_low
@@ -1107,8 +1110,8 @@ push_reload (in, out, inloc, outloc, class,
> UNITS_PER_WORD)
&& ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
/ UNITS_PER_WORD)
- != HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
- GET_MODE (SUBREG_REG (out)))))
+ != (int) HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
+ GET_MODE (SUBREG_REG (out)))))
|| ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
|| (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS
@@ -1117,14 +1120,12 @@ push_reload (in, out, inloc, outloc, class,
SUBREG_REG (out))
== NO_REGS))
#endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
|| (GET_CODE (SUBREG_REG (out)) == REG
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
- && (TEST_HARD_REG_BIT
- (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
- REGNO (SUBREG_REG (out))))
- && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
- outmode))
+ && REG_CANNOT_CHANGE_MODE_P (REGNO (SUBREG_REG (out)),
+ GET_MODE (SUBREG_REG (out)),
+ outmode))
#endif
))
{
@@ -1285,17 +1286,12 @@ push_reload (in, out, inloc, outloc, class,
So add an additional reload. */
#ifdef SECONDARY_MEMORY_NEEDED
- {
- int regnum;
-
- /* If a memory location is needed for the copy, make one. */
- if (in != 0
- && ((regnum = true_regnum (in)) >= 0)
- && regnum < FIRST_PSEUDO_REGISTER
- && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (regnum),
- class, inmode))
- get_secondary_mem (in, inmode, opnum, type);
- }
+ /* If a memory location is needed for the copy, make one. */
+ if (in != 0 && (GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
+ && reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
+ && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
+ class, inmode))
+ get_secondary_mem (in, inmode, opnum, type);
#endif
i = n_reloads;
@@ -1321,16 +1317,12 @@ push_reload (in, out, inloc, outloc, class,
n_reloads++;
#ifdef SECONDARY_MEMORY_NEEDED
- {
- int regnum;
-
- if (out != 0
- && ((regnum = true_regnum (out)) >= 0)
- && regnum < FIRST_PSEUDO_REGISTER
- && SECONDARY_MEMORY_NEEDED (class, REGNO_REG_CLASS (regnum),
- outmode))
- get_secondary_mem (out, outmode, opnum, type);
- }
+ if (out != 0 && (GET_CODE (out) == REG || GET_CODE (out) == SUBREG)
+ && reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
+ && SECONDARY_MEMORY_NEEDED (class,
+ REGNO_REG_CLASS (reg_or_subregno (out)),
+ outmode))
+ get_secondary_mem (out, outmode, opnum, type);
#endif
}
else
@@ -1575,6 +1567,25 @@ push_replacement (loc, reloadnum, mode)
r->mode = mode;
}
}
+
+/* Duplicate any replacement we have recorded to apply at
+ location ORIG_LOC to also be performed at DUP_LOC.
+ This is used in insn patterns that use match_dup. */
+
+static void
+dup_replacements (dup_loc, orig_loc)
+ rtx *dup_loc;
+ rtx *orig_loc;
+{
+ int i, n = n_replacements;
+
+ for (i = 0; i < n; i++)
+ {
+ struct replacement *r = &replacements[i];
+ if (r->where == orig_loc)
+ push_replacement (dup_loc, r->what, r->mode);
+ }
+}
/* Transfer all replacements that used to be in reload FROM to be in
reload TO. */
@@ -1593,7 +1604,7 @@ transfer_replacements (to, from)
/* IN_RTX is the value loaded by a reload that we now decided to inherit,
or a subpart of it. If we have any replacements registered for IN_RTX,
cancel the reloads that were supposed to load them.
- Return non-zero if we canceled any reloads. */
+ Return nonzero if we canceled any reloads. */
int
remove_address_replacements (in_rtx)
rtx in_rtx;
@@ -1833,7 +1844,7 @@ combine_reloads ()
If FOR_REAL is -1, this should not be done, because this call
is just to see if a register can be found, not to find and install it.
- EARLYCLOBBER is non-zero if OUT is an earlyclobber operand. This
+ EARLYCLOBBER is nonzero if OUT is an earlyclobber operand. This
puts an additional constraint on being able to use IN for OUT since
IN must not appear elsewhere in the insn (it is assumed that IN itself
is safe from the earlyclobber). */
@@ -2136,13 +2147,13 @@ operands_match_p (x, y)
/* If two operands must match, because they are really a single
operand of an assembler insn, then two postincrements are invalid
because the assembler insn would increment only once.
- On the other hand, an postincrement matches ordinary indexing
+ On the other hand, a postincrement matches ordinary indexing
if the postincrement is the output operand. */
if (code == POST_DEC || code == POST_INC || code == POST_MODIFY)
return operands_match_p (XEXP (x, 0), y);
/* Two preincrements are invalid
because the assembler insn would increment only once.
- On the other hand, an preincrement matches ordinary indexing
+ On the other hand, a preincrement matches ordinary indexing
if the preincrement is the input operand.
In this case, return 2, since some callers need to do special
things when this happens. */
@@ -2465,6 +2476,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
char pref_or_nothing[MAX_RECOG_OPERANDS];
/* Nonzero for a MEM operand whose entire address needs a reload. */
int address_reloaded[MAX_RECOG_OPERANDS];
+ /* Nonzero for an address operand that needs to be completely reloaded. */
+ int address_operand_reloaded[MAX_RECOG_OPERANDS];
/* Value of enum reload_type to use for operand. */
enum reload_type operand_type[MAX_RECOG_OPERANDS];
/* Value of enum reload_type to use within address of operand. */
@@ -2643,6 +2656,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
RTX_CODE code = GET_CODE (recog_data.operand[i]);
address_reloaded[i] = 0;
+ address_operand_reloaded[i] = 0;
operand_type[i] = (modified[i] == RELOAD_READ ? RELOAD_FOR_INPUT
: modified[i] == RELOAD_WRITE ? RELOAD_FOR_OUTPUT
: RELOAD_OTHER);
@@ -2654,12 +2668,14 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
if (*constraints[i] == 0)
/* Ignore things like match_operator operands. */
;
- else if (constraints[i][0] == 'p')
+ else if (constraints[i][0] == 'p'
+ || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0]))
{
- find_reloads_address (recog_data.operand_mode[i], (rtx*) 0,
- recog_data.operand[i],
- recog_data.operand_loc[i],
- i, operand_type[i], ind_levels, insn);
+ address_operand_reloaded[i]
+ = find_reloads_address (recog_data.operand_mode[i], (rtx*) 0,
+ recog_data.operand[i],
+ recog_data.operand_loc[i],
+ i, operand_type[i], ind_levels, insn);
/* If we now have a simple operand where we used to have a
PLUS or MULT, re-recognize and try again. */
@@ -2676,6 +2692,10 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
recog_data.operand[i] = *recog_data.operand_loc[i];
substed_operand[i] = recog_data.operand[i];
+
+ /* Address operands are reloaded in their existing mode,
+ no matter what is specified in the machine description. */
+ operand_mode[i] = GET_MODE (recog_data.operand[i]);
}
else if (code == MEM)
{
@@ -2856,6 +2876,12 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
if (GET_CODE (SUBREG_REG (operand)) == REG
&& REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
{
+ if (!subreg_offset_representable_p
+ (REGNO (SUBREG_REG (operand)),
+ GET_MODE (SUBREG_REG (operand)),
+ SUBREG_BYTE (operand),
+ GET_MODE (operand)))
+ force_reload = 1;
offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
GET_MODE (SUBREG_REG (operand)),
SUBREG_BYTE (operand),
@@ -2911,26 +2937,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
)
#endif
)
- /* This following hunk of code should no longer be
- needed at all with SUBREG_BYTE. If you need this
- code back, please explain to me why so I can
- fix the real problem. -DaveM */
-#if 0
- /* Subreg of a hard reg which can't handle the subreg's mode
- or which would handle that mode in the wrong number of
- registers for subregging to work. */
- || (GET_CODE (operand) == REG
- && REGNO (operand) < FIRST_PSEUDO_REGISTER
- && ((GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
- && (GET_MODE_SIZE (GET_MODE (operand))
- > UNITS_PER_WORD)
- && ((GET_MODE_SIZE (GET_MODE (operand))
- / UNITS_PER_WORD)
- != HARD_REGNO_NREGS (REGNO (operand),
- GET_MODE (operand))))
- || ! HARD_REGNO_MODE_OK (REGNO (operand) + offset,
- operand_mode[i])))
-#endif
)
force_reload = 1;
}
@@ -3154,20 +3160,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
break;
case 'E':
-#ifndef REAL_ARITHMETIC
- /* Match any floating double constant, but only if
- we can examine the bits of it reliably. */
- if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
- || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
- && GET_MODE (operand) != VOIDmode && ! flag_pretend_float)
- break;
-#endif
- if (GET_CODE (operand) == CONST_DOUBLE)
- win = 1;
- break;
-
case 'F':
- if (GET_CODE (operand) == CONST_DOUBLE)
+ if (GET_CODE (operand) == CONST_DOUBLE
+ || (GET_CODE (operand) == CONST_VECTOR
+ && (GET_MODE_CLASS (GET_MODE (operand))
+ == MODE_VECTOR_FLOAT)))
win = 1;
break;
@@ -3244,6 +3241,49 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
{
#ifdef EXTRA_CONSTRAINT
+ if (EXTRA_MEMORY_CONSTRAINT (c))
+ {
+ if (force_reload)
+ break;
+ if (EXTRA_CONSTRAINT (operand, c))
+ win = 1;
+ /* If the address was already reloaded,
+ we win as well. */
+ if (GET_CODE (operand) == MEM && address_reloaded[i])
+ win = 1;
+ /* Likewise if the address will be reloaded because
+ reg_equiv_address is nonzero. For reg_equiv_mem
+ we have to check. */
+ if (GET_CODE (operand) == REG
+ && REGNO (operand) >= FIRST_PSEUDO_REGISTER
+ && reg_renumber[REGNO (operand)] < 0
+ && ((reg_equiv_mem[REGNO (operand)] != 0
+ && EXTRA_CONSTRAINT (reg_equiv_mem[REGNO (operand)], c))
+ || (reg_equiv_address[REGNO (operand)] != 0)))
+ win = 1;
+
+ /* If we didn't already win, we can reload
+ constants via force_const_mem, and other
+ MEMs by reloading the address like for 'o'. */
+ if ((CONSTANT_P (operand) && GET_CODE (operand) != HIGH)
+ || GET_CODE (operand) == MEM)
+ badop = 0;
+ constmemok = 1;
+ offmemok = 1;
+ break;
+ }
+ if (EXTRA_ADDRESS_CONSTRAINT (c))
+ {
+ if (EXTRA_CONSTRAINT (operand, c))
+ win = 1;
+
+ /* If we didn't already win, we can reload
+ the address into a base register. */
+ this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode);
+ badop = 0;
+ break;
+ }
+
if (EXTRA_CONSTRAINT (operand, c))
win = 1;
#endif
@@ -3606,7 +3646,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
for (i = 0; i < noperands; i++)
goal_alternative_matched[i] = -1;
-
+
for (i = 0; i < noperands; i++)
if (! goal_alternative_win[i]
&& goal_alternative_matches[i] >= 0)
@@ -3810,6 +3850,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
}
else if (goal_alternative_matched[i] < 0
&& goal_alternative_matches[i] < 0
+ && !address_operand_reloaded[i]
&& optimize)
{
/* For each non-matching operand that's a MEM or a pseudo-register
@@ -3957,9 +3998,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
{
int opno = recog_data.dup_num[i];
*recog_data.dup_loc[i] = *recog_data.operand_loc[opno];
- if (operand_reloadnum[opno] >= 0)
- push_replacement (recog_data.dup_loc[i], operand_reloadnum[opno],
- insn_data[insn_code_number].operand[opno].mode);
+ dup_replacements (recog_data.dup_loc[i], recog_data.operand_loc[opno]);
}
#if 0
@@ -4313,7 +4352,7 @@ alternative_allows_memconst (constraint, altnum)
/* Scan the requested alternative for 'm' or 'o'.
If one of them is present, this alternative accepts memory constants. */
while ((c = *constraint++) && c != ',' && c != '#')
- if (c == 'm' || c == 'o')
+ if (c == 'm' || c == 'o' || EXTRA_MEMORY_CONSTRAINT (c))
return 1;
return 0;
}
@@ -4438,34 +4477,6 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn,
return tem;
}
- /* If the SUBREG is wider than a word, the above test will fail.
- For example, we might have a SImode SUBREG of a DImode SUBREG_REG
- for a 16 bit target, or a DImode SUBREG of a TImode SUBREG_REG for
- a 32 bit target. We still can - and have to - handle this
- for non-paradoxical subregs of CONST_INTs. */
- if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
- && reg_equiv_constant[regno] != 0
- && GET_CODE (reg_equiv_constant[regno]) == CONST_INT
- && (GET_MODE_SIZE (GET_MODE (x))
- < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
- {
- int shift = SUBREG_BYTE (x) * BITS_PER_UNIT;
- if (WORDS_BIG_ENDIAN)
- shift = (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
- - GET_MODE_BITSIZE (GET_MODE (x))
- - shift);
- /* Here we use the knowledge that CONST_INTs have a
- HOST_WIDE_INT field. */
- if (shift >= HOST_BITS_PER_WIDE_INT)
- shift = HOST_BITS_PER_WIDE_INT - 1;
- return GEN_INT (INTVAL (reg_equiv_constant[regno]) >> shift);
- }
-
- if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
- && reg_equiv_constant[regno] != 0
- && GET_MODE (reg_equiv_constant[regno]) == VOIDmode)
- abort ();
-
/* If the subreg contains a reg that will be converted to a mem,
convert the subreg to a narrower memref now.
Otherwise, we would get (subreg (mem ...) ...),
@@ -4545,6 +4556,27 @@ make_memloc (ad, regno)
return tem;
}
+/* Returns true if AD could be turned into a valid memory reference
+ to mode MODE by reloading the part pointed to by PART into a
+ register. */
+
+static int
+maybe_memory_address_p (mode, ad, part)
+ enum machine_mode mode;
+ rtx ad;
+ rtx *part;
+{
+ int retv;
+ rtx tem = *part;
+ rtx reg = gen_rtx_REG (GET_MODE (tem), max_reg_num ());
+
+ *part = reg;
+ retv = memory_address_p (mode, ad);
+ *part = tem;
+
+ return retv;
+}
+
/* Record all reloads needed for handling memory address AD
which appears in *LOC in a memory reference to mode MODE
which itself is found in location *MEMREFLOC.
@@ -4611,9 +4643,9 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
tem = make_memloc (ad, regno);
if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
{
- find_reloads_address (GET_MODE (tem), (rtx*) 0, XEXP (tem, 0),
- &XEXP (tem, 0), opnum, ADDR_TYPE (type),
- ind_levels, insn);
+ find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
+ &XEXP (tem, 0), opnum,
+ ADDR_TYPE (type), ind_levels, insn);
}
/* We can avoid a reload if the register's equivalent memory
expression is valid as an indirect memory address.
@@ -4825,26 +4857,24 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
that the index needs a reload and find_reloads_address_1 will take care
of it.
- If we decide to do something here, it must be that
- `double_reg_address_ok' is true and that this address rtl was made by
- eliminate_regs. We generate a reload of the fp/sp/ap + constant and
+ Handle all base registers here, not just fp/ap/sp, because on some
+ targets (namely Sparc) we can also get invalid addresses from preventive
+ subreg big-endian corrections made by find_reloads_toplev.
+
+ If we decide to do something, it must be that `double_reg_address_ok'
+ is true. We generate a reload of the base register + constant and
rework the sum so that the reload register will be added to the index.
This is safe because we know the address isn't shared.
- We check for fp/ap/sp as both the first and second operand of the
- innermost PLUS. */
+ We check for the base register as both the first and second operand of
+ the innermost PLUS. */
else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
&& GET_CODE (XEXP (ad, 0)) == PLUS
- && (XEXP (XEXP (ad, 0), 0) == frame_pointer_rtx
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 0) == hard_frame_pointer_rtx
-#endif
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 0) == arg_pointer_rtx
-#endif
- || XEXP (XEXP (ad, 0), 0) == stack_pointer_rtx)
- && ! memory_address_p (mode, ad))
+ && GET_CODE (XEXP (XEXP (ad, 0), 0)) == REG
+ && REGNO (XEXP (XEXP (ad, 0), 0)) < FIRST_PSEUDO_REGISTER
+ && REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 0), mode)
+ && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 1)))
{
*loc = ad = gen_rtx_PLUS (GET_MODE (ad),
plus_constant (XEXP (XEXP (ad, 0), 0),
@@ -4861,15 +4891,10 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
&& GET_CODE (XEXP (ad, 0)) == PLUS
- && (XEXP (XEXP (ad, 0), 1) == frame_pointer_rtx
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 1) == hard_frame_pointer_rtx
-#endif
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 1) == arg_pointer_rtx
-#endif
- || XEXP (XEXP (ad, 0), 1) == stack_pointer_rtx)
- && ! memory_address_p (mode, ad))
+ && GET_CODE (XEXP (XEXP (ad, 0), 1)) == REG
+ && REGNO (XEXP (XEXP (ad, 0), 1)) < FIRST_PSEUDO_REGISTER
+ && REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 1), mode)
+ && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 0)))
{
*loc = ad = gen_rtx_PLUS (GET_MODE (ad),
XEXP (XEXP (ad, 0), 0),
@@ -5214,6 +5239,19 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
SUBREG_BYTE (orig_op1),
GET_MODE (orig_op1))));
}
+ /* Plus in the index register may be created only as a result of
+ register remateralization for expresion like &localvar*4. Reload it.
+ It may be possible to combine the displacement on the outer level,
+ but it is probably not worthwhile to do so. */
+ if (context)
+ {
+ find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
+ opnum, ADDR_TYPE (type), ind_levels, insn);
+ push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
+ (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+ GET_MODE (x), VOIDmode, 0, 0, opnum, type);
+ return 1;
+ }
if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
|| code0 == ZERO_EXTEND || code1 == MEM)
@@ -5341,7 +5379,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
We can't use ADDR_TYPE (type) here, because we need to
write back the value after reading it, hence we actually
need two registers. */
- find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
+ find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
&XEXP (tem, 0), opnum,
RELOAD_OTHER,
ind_levels, insn);
@@ -5644,7 +5682,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
{
enum reg_class class = (context ? INDEX_REG_CLASS
: MODE_BASE_REG_CLASS (mode));
- if (CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
+ if ((unsigned) CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
> reg_class_size[class])
{
x = find_reloads_subreg_address (x, 0, opnum, type,
@@ -5988,7 +6026,7 @@ copy_replacements_1 (px, py, orig_replacements)
}
}
-/* Change any replacements being done to *X to be done to *Y */
+/* Change any replacements being done to *X to be done to *Y. */
void
move_replacements (x, y)
@@ -6859,7 +6897,7 @@ regno_clobbered_p (regno, insn, mode, sets)
&& GET_CODE (XEXP (elt, 0)) == REG)
{
unsigned int test = REGNO (XEXP (elt, 0));
-
+
if (test >= regno && test < endregno)
return 1;
}
diff --git a/contrib/gcc/reload.h b/contrib/gcc/reload.h
index e832ed9..0463224 100644
--- a/contrib/gcc/reload.h
+++ b/contrib/gcc/reload.h
@@ -205,7 +205,7 @@ struct needs
must be examined for register elimination. */
struct insn_chain
{
- /* Links to the neighbour instructions. */
+ /* Links to the neighbor instructions. */
struct insn_chain *next, *prev;
/* Link through a chains set up by calculate_needs_all_insns, containing
@@ -270,7 +270,7 @@ extern void transfer_replacements PARAMS ((int, int));
/* IN_RTX is the value loaded by a reload that we now decided to inherit,
or a subpart of it. If we have any replacements registered for IN_RTX,
chancel the reloads that were supposed to load them.
- Return non-zero if we chanceled any reloads. */
+ Return nonzero if we chanceled any reloads. */
extern int remove_address_replacements PARAMS ((rtx in_rtx));
/* Like rtx_equal_p except that it allows a REG and a SUBREG to match
diff --git a/contrib/gcc/reload1.c b/contrib/gcc/reload1.c
index 5928a68..3000f61 100644
--- a/contrib/gcc/reload1.c
+++ b/contrib/gcc/reload1.c
@@ -1,6 +1,6 @@
/* Reload pseudo regs into hard regs for insns that require hard regs.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -139,7 +139,7 @@ static int reg_reloaded_contents[FIRST_PSEUDO_REGISTER];
when reg_reloaded_valid is set for this register. */
static rtx reg_reloaded_insn[FIRST_PSEUDO_REGISTER];
-/* Indicate if reg_reloaded_insn / reg_reloaded_contents is valid */
+/* Indicate if reg_reloaded_insn / reg_reloaded_contents is valid. */
static HARD_REG_SET reg_reloaded_valid;
/* Indicate if the register was dead at the end of the reload.
This is only valid if reg_reloaded_contents is set and valid. */
@@ -280,9 +280,6 @@ char *reload_firstobj;
Used to quickly free all memory after processing one insn. */
static char *reload_insn_firstobj;
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
/* List of insn_chain instructions, one for every insn that reload needs to
examine. */
struct insn_chain *reload_insn_chain;
@@ -343,7 +340,7 @@ static const struct elim_table_1
#define NUM_ELIMINABLE_REGS ARRAY_SIZE (reg_eliminate_1)
/* Record the number of pending eliminations that have an offset not equal
- to their initial offset. If non-zero, we use a new copy of each
+ to their initial offset. If nonzero, we use a new copy of each
replacement result in any insns encountered. */
int num_not_at_initial_offset;
@@ -355,11 +352,14 @@ static int num_eliminable_invariants;
/* For each label, we record the offset of each elimination. If we reach
a label by more than one path and an offset differs, we cannot do the
- elimination. This information is indexed by the number of the label.
- The first table is an array of flags that records whether we have yet
- encountered a label and the second table is an array of arrays, one
- entry in the latter array for each elimination. */
-
+ elimination. This information is indexed by the difference of the
+ number of the label and the first label number. We can't offset the
+ pointer itself as this can cause problems on machines with segmented
+ memory. The first table is an array of flags that records whether we
+ have yet encountered a label and the second table is an array of arrays,
+ one entry in the latter array for each elimination. */
+
+static int first_label_num;
static char *offsets_known_at;
static int (*offsets_at)[NUM_ELIMINABLE_REGS];
@@ -443,7 +443,7 @@ static rtx inc_for_reload PARAMS ((rtx, rtx, rtx, int));
static void reload_cse_regs_1 PARAMS ((rtx));
static int reload_cse_noop_set_p PARAMS ((rtx));
static int reload_cse_simplify_set PARAMS ((rtx, rtx));
-static int reload_cse_simplify_operands PARAMS ((rtx));
+static int reload_cse_simplify_operands PARAMS ((rtx, rtx));
static void reload_combine PARAMS ((void));
static void reload_combine_note_use PARAMS ((rtx *, rtx));
static void reload_combine_note_store PARAMS ((rtx, rtx, void *));
@@ -457,8 +457,7 @@ static HOST_WIDE_INT sext_for_mode PARAMS ((enum machine_mode,
HOST_WIDE_INT));
static void failed_reload PARAMS ((rtx, int));
static int set_reload_reg PARAMS ((int, int));
-static void reload_cse_delete_noop_set PARAMS ((rtx, rtx));
-static void reload_cse_simplify PARAMS ((rtx));
+static void reload_cse_simplify PARAMS ((rtx, rtx));
void fixup_abnormal_edges PARAMS ((void));
extern void dump_needs PARAMS ((struct insn_chain *));
@@ -675,11 +674,7 @@ reload (first, global)
int i;
rtx insn;
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;
- int (*real_at_ptr)[NUM_ELIMINABLE_REGS];
+ basic_block bb;
/* Make sure even insns with volatile mem refs are recognizable. */
init_recog ();
@@ -820,8 +815,12 @@ reload (first, global)
else if (LEGITIMATE_CONSTANT_P (x))
reg_equiv_constant[i] = x;
else
- reg_equiv_memory_loc[i]
- = force_const_mem (GET_MODE (SET_DEST (set)), x);
+ {
+ reg_equiv_memory_loc[i]
+ = force_const_mem (GET_MODE (SET_DEST (set)), x);
+ if (!reg_equiv_memory_loc[i])
+ continue;
+ }
}
else
continue;
@@ -855,21 +854,18 @@ reload (first, global)
init_elim_table ();
- num_labels = max_label_num () - get_first_label_num ();
+ first_label_num = get_first_label_num ();
+ num_labels = max_label_num () - first_label_num;
/* Allocate the tables used to store offset information at labels. */
/* 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
+ offsets_known_at = xmalloc (num_labels);
+ offsets_at
= (int (*)[NUM_ELIMINABLE_REGS])
xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (int));
- 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.
Do not touch virtual registers. */
@@ -1026,7 +1022,7 @@ reload (first, global)
did_spill = 1;
/* Regardless of the state of spills, if we previously had
- a register that we thought we could eliminate, but no can
+ a register that we thought we could eliminate, but now can
not eliminate, we must run another pass.
Consider pseudos which have an entry in reg_equiv_* which
@@ -1122,8 +1118,8 @@ reload (first, global)
pseudo. */
if (! frame_pointer_needed)
- for (i = 0; i < n_basic_blocks; i++)
- CLEAR_REGNO_REG_SET (BASIC_BLOCK (i)->global_live_at_start,
+ FOR_EACH_BB (bb)
+ CLEAR_REGNO_REG_SET (bb->global_live_at_start,
HARD_FRAME_POINTER_REGNUM);
/* Come here (with failure set nonzero) if we can't get enough spill regs
@@ -1159,9 +1155,9 @@ reload (first, global)
{
rtx reg = regno_reg_rtx[i];
+ REG_USERVAR_P (reg) = 0;
PUT_CODE (reg, MEM);
XEXP (reg, 0) = addr;
- REG_USERVAR_P (reg) = 0;
if (reg_equiv_memory_loc[i])
MEM_COPY_ATTRIBUTES (reg, reg_equiv_memory_loc[i]);
else
@@ -1183,10 +1179,12 @@ reload (first, global)
/* Make a pass over all the insns and delete all USEs which we inserted
only to tag a REG_EQUAL note on them. Remove all REG_DEAD and REG_UNUSED
- notes. Delete all CLOBBER insns that don't refer to the return value
- and simplify (subreg (reg)) operands. Also remove all REG_RETVAL and
- REG_LIBCALL notes since they are no longer useful or accurate. Strip
- and regenerate REG_INC notes that may have been moved around. */
+ notes. Delete all CLOBBER insns, except those that refer to the return
+ value and the special mem:BLK CLOBBERs added to prevent the scheduler
+ from misarranging variable-array code, and simplify (subreg (reg))
+ operands. Also remove all REG_RETVAL and REG_LIBCALL notes since they
+ are no longer useful or accurate. Strip and regenerate REG_INC notes
+ that may have been moved around. */
for (insn = first; insn; insn = NEXT_INSN (insn))
if (INSN_P (insn))
@@ -1203,6 +1201,11 @@ reload (first, global)
&& (GET_MODE (insn) == QImode
|| find_reg_note (insn, REG_EQUAL, NULL_RTX)))
|| (GET_CODE (PATTERN (insn)) == CLOBBER
+ && (GET_CODE (XEXP (PATTERN (insn), 0)) != MEM
+ || GET_MODE (XEXP (PATTERN (insn), 0)) != BLKmode
+ || (GET_CODE (XEXP (XEXP (PATTERN (insn), 0), 0)) != SCRATCH
+ && XEXP (XEXP (PATTERN (insn), 0), 0)
+ != stack_pointer_rtx))
&& (GET_CODE (XEXP (PATTERN (insn), 0)) != REG
|| ! REG_FUNCTION_VALUE_P (XEXP (PATTERN (insn), 0)))))
{
@@ -1261,10 +1264,10 @@ reload (first, global)
free (reg_equiv_memory_loc);
reg_equiv_memory_loc = 0;
- if (real_known_ptr)
- free (real_known_ptr);
- if (real_at_ptr)
- free (real_at_ptr);
+ if (offsets_known_at)
+ free (offsets_known_at);
+ if (offsets_at)
+ free (offsets_at);
free (reg_equiv_mem);
free (reg_equiv_init);
@@ -1383,8 +1386,12 @@ maybe_fix_stack_asms ()
break;
default:
- cls = (int) reg_class_subunion[cls][(int) REG_CLASS_FROM_LETTER (c)];
-
+ if (EXTRA_ADDRESS_CONSTRAINT (c))
+ cls = (int) reg_class_subunion[cls]
+ [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+ else
+ cls = (int) reg_class_subunion[cls]
+ [(int) REG_CLASS_FROM_LETTER (c)];
}
}
}
@@ -1489,7 +1496,7 @@ calculate_needs_all_insns (global)
&& REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER)
{
delete_insn (insn);
- /* Delete it from the reload chain */
+ /* Delete it from the reload chain. */
if (chain->prev)
chain->prev->next = next;
else
@@ -2110,7 +2117,7 @@ mark_home_live (regno)
INSN is the insn that it came from, if any.
- INITIAL_P is non-zero if we are to set the offset to be the initial
+ INITIAL_P is nonzero if we are to set the offset to be the initial
offset and zero if we are setting the offset of the label to be the
current offset. */
@@ -2143,13 +2150,13 @@ set_label_offsets (x, insn, initial_p)
we guessed wrong, we will suppress an elimination that might have
been possible had we been able to guess correctly. */
- if (! offsets_known_at[CODE_LABEL_NUMBER (x)])
+ if (! offsets_known_at[CODE_LABEL_NUMBER (x) - first_label_num])
{
for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
- offsets_at[CODE_LABEL_NUMBER (x)][i]
+ offsets_at[CODE_LABEL_NUMBER (x) - first_label_num][i]
= (initial_p ? reg_eliminate[i].initial_offset
: reg_eliminate[i].offset);
- offsets_known_at[CODE_LABEL_NUMBER (x)] = 1;
+ offsets_known_at[CODE_LABEL_NUMBER (x) - first_label_num] = 1;
}
/* Otherwise, if this is the definition of a label and it is
@@ -2166,7 +2173,7 @@ set_label_offsets (x, insn, initial_p)
where the offsets disagree. */
for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
- if (offsets_at[CODE_LABEL_NUMBER (x)][i]
+ if (offsets_at[CODE_LABEL_NUMBER (x) - first_label_num][i]
!= (initial_p ? reg_eliminate[i].initial_offset
: reg_eliminate[i].offset))
reg_eliminate[i].can_eliminate = 0;
@@ -2265,7 +2272,7 @@ set_label_offsets (x, insn, initial_p)
to record the fact that a register is referenced outside a MEM.
If INSN is an insn, it is the insn containing X. If we replace a REG
- in a SET_DEST with an equivalent MEM and INSN is non-zero, write a
+ in a SET_DEST with an equivalent MEM and INSN is nonzero, write a
CLOBBER of the pseudo after INSN so find_equiv_regs will know that
the REG is being modified.
@@ -3221,7 +3228,7 @@ eliminate_regs_in_insn (insn, replace)
insn. The changes we make were determined by the earlier call to
elimination_effects.
- We also detect a cases where register elimination cannot be done,
+ We also detect cases where register elimination cannot be done,
namely, if a register would be both changed and referenced outside a MEM
in the resulting insn since such an insn is often undefined and, even if
not, we cannot know what meaning will be given to it. Note that it is
@@ -3375,7 +3382,7 @@ static void
set_initial_label_offsets ()
{
rtx x;
- memset ((char *) &offsets_known_at[get_first_label_num ()], 0, num_labels);
+ memset (offsets_known_at, 0, num_labels);
for (x = forced_labels; x; x = XEXP (x, 1))
if (XEXP (x, 0))
@@ -3396,14 +3403,15 @@ set_offsets_for_label (insn)
num_not_at_initial_offset = 0;
for (i = 0, ep = reg_eliminate; i < NUM_ELIMINABLE_REGS; ep++, i++)
{
- ep->offset = ep->previous_offset = offsets_at[label_nr][i];
+ ep->offset = ep->previous_offset
+ = offsets_at[label_nr - first_label_num][i];
if (ep->can_eliminate && ep->offset != ep->initial_offset)
num_not_at_initial_offset++;
}
}
/* See if anything that happened changes which eliminations are valid.
- For example, on the Sparc, whether or not the frame pointer can
+ For example, on the SPARC, whether or not the frame pointer can
be eliminated can depend on what registers have been used. We need
not check some conditions again (such as flag_omit_frame_pointer)
since they can't have changed. */
@@ -3412,9 +3420,7 @@ static void
update_eliminables (pset)
HARD_REG_SET *pset;
{
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
int previous_frame_pointer_needed = frame_pointer_needed;
-#endif
struct elim_table *ep;
for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
@@ -3479,12 +3485,10 @@ update_eliminables (pset)
}
}
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
/* If we didn't need a frame pointer last time, but we do now, spill
the hard frame pointer. */
if (frame_pointer_needed && ! previous_frame_pointer_needed)
SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM);
-#endif
}
/* Initialize the table of registers to eliminate. */
@@ -3842,7 +3846,7 @@ reload_as_needed (live_known)
else if (INSN_P (insn))
{
- rtx oldpat = PATTERN (insn);
+ rtx oldpat = copy_rtx (PATTERN (insn));
/* If this is a USE and CLOBBER of a MEM, ensure that any
references to eliminable registers have been removed. */
@@ -3926,6 +3930,7 @@ reload_as_needed (live_known)
if (asm_noperands (PATTERN (insn)) >= 0)
for (p = NEXT_INSN (prev); p != next; p = NEXT_INSN (p))
if (p != insn && INSN_P (p)
+ && GET_CODE (PATTERN (p)) != USE
&& (recog_memoized (p) < 0
|| (extract_insn (p), ! constrain_operands (1))))
{
@@ -4097,23 +4102,21 @@ forget_old_reloads_1 (x, ignored, data)
{
unsigned int regno;
unsigned int nr;
- int offset = 0;
/* note_stores does give us subregs of hard regs,
subreg_regno_offset will abort if it is not a hard reg. */
while (GET_CODE (x) == SUBREG)
{
- offset += subreg_regno_offset (REGNO (SUBREG_REG (x)),
- GET_MODE (SUBREG_REG (x)),
- SUBREG_BYTE (x),
- GET_MODE (x));
+ /* We ignore the subreg offset when calculating the regno,
+ because we are using the entire underlying hard register
+ below. */
x = SUBREG_REG (x);
}
if (GET_CODE (x) != REG)
return;
- regno = REGNO (x) + offset;
+ regno = REGNO (x);
if (regno >= FIRST_PSEUDO_REGISTER)
nr = 1;
@@ -4326,7 +4329,7 @@ clear_reload_reg_in_use (regno, opnum, type, mode)
abort ();
}
/* We resolve conflicts with remaining reloads of the same type by
- excluding the intervals of of reload registers by them from the
+ excluding the intervals of reload registers by them from the
interval of freed reload registers. Since we only keep track of
one set of interval bounds, we might have to exclude somewhat
more than what would be necessary if we used a HARD_REG_SET here.
@@ -4746,7 +4749,7 @@ char reload_inherited[MAX_RELOADS];
if we know it. Otherwise, this is 0. */
rtx reload_inheritance_insn[MAX_RELOADS];
-/* If non-zero, this is a place to get the value of the reload,
+/* If nonzero, this is a place to get the value of the reload,
rather than using reload_in. */
rtx reload_override_in[MAX_RELOADS];
@@ -4987,7 +4990,7 @@ reload_reg_free_for_value_p (start_regno, regno, opnum, type, value, out,
determine how many hard regs to test.
Other read-only reloads with the same value do not conflict
- unless OUT is non-zero and these other reloads have to live while
+ unless OUT is nonzero and these other reloads have to live while
output reloads live.
If OUT is CONST0_RTX, this is a special case: it means that the
test should not be for using register REGNO as reload register, but
@@ -5110,7 +5113,7 @@ set_reload_reg (i, r)
}
/* Find a spill register to use as a reload register for reload R.
- LAST_RELOAD is non-zero if this is the last reload for the insn being
+ LAST_RELOAD is nonzero if this is the last reload for the insn being
processed.
Set rld[R].reg_rtx to the register allocated.
@@ -5488,16 +5491,15 @@ choose_reload_regs (chain)
GET_MODE_CLASS (mode));
if (
-#ifdef CLASS_CANNOT_CHANGE_MODE
- (TEST_HARD_REG_BIT
- (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], i)
- ? ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (last_reg),
- need_mode)
- : (GET_MODE_SIZE (GET_MODE (last_reg))
- >= GET_MODE_SIZE (need_mode)))
-#else
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ (!REG_CANNOT_CHANGE_MODE_P (i, GET_MODE (last_reg),
+ need_mode)
+ &&
+#endif
(GET_MODE_SIZE (GET_MODE (last_reg))
>= GET_MODE_SIZE (need_mode))
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ )
#endif
&& reg_reloaded_contents[i] == regno
&& TEST_HARD_REG_BIT (reg_reloaded_valid, i)
@@ -5745,8 +5747,8 @@ choose_reload_regs (chain)
/* If we found an equivalent reg, say no code need be generated
to load it, and use it as our reload reg. */
- if (equiv != 0
- && (regno != HARD_FRAME_POINTER_REGNUM
+ if (equiv != 0
+ && (regno != HARD_FRAME_POINTER_REGNUM
|| !frame_pointer_needed))
{
int nr = HARD_REGNO_NREGS (regno, rld[r].mode);
@@ -6003,7 +6005,7 @@ deallocate_reload_reg (r)
reload_spill_index[r] = -1;
}
-/* If SMALL_REGISTER_CLASSES is non-zero, we may not have merged two
+/* If SMALL_REGISTER_CLASSES is nonzero, 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.
@@ -6098,17 +6100,41 @@ merge_assigned_reloads (insn)
if they were for inputs, RELOAD_OTHER for outputs. Note that
this test is equivalent to looking for reloads for this operand
number. */
+ /* We must take special care when there are two or more reloads to
+ be merged and a RELOAD_FOR_OUTPUT_ADDRESS reload that loads the
+ same value or a part of it; we must not change its type if there
+ is a conflicting input. */
if (rld[i].when_needed == RELOAD_OTHER)
for (j = 0; j < n_reloads; j++)
if (rld[j].in != 0
&& rld[j].when_needed != RELOAD_OTHER
+ && rld[j].when_needed != RELOAD_FOR_OTHER_ADDRESS
+ && (! conflicting_input
+ || rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
+ || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
&& reg_overlap_mentioned_for_reload_p (rld[j].in,
rld[i].in))
- rld[j].when_needed
- = ((rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
- || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
- ? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER);
+ {
+ int k;
+
+ rld[j].when_needed
+ = ((rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
+ || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
+ ? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER);
+
+ /* Check to see if we accidentally converted two reloads
+ that use the same reload register with different inputs
+ to the same type. If so, the resulting code won't work,
+ so abort. */
+ if (rld[j].reg_rtx)
+ for (k = 0; k < j; k++)
+ if (rld[k].in != 0 && rld[k].reg_rtx != 0
+ && rld[k].when_needed == rld[j].when_needed
+ && rtx_equal_p (rld[k].reg_rtx, rld[j].reg_rtx)
+ && ! rtx_equal_p (rld[k].in, rld[j].in))
+ abort ();
+ }
}
}
}
@@ -6615,7 +6641,7 @@ emit_input_reload_insns (chain, rl, old, j)
/* End this sequence. */
*where = get_insns ();
end_sequence ();
-
+
/* Update reload_override_in so that delete_address_reloads_1
can see the actual register usage. */
if (oldequiv_reg)
@@ -6824,7 +6850,7 @@ emit_output_reload_insns (chain, rl, j)
if (rl->when_needed == RELOAD_OTHER)
{
- emit_insns (other_output_reload_insns[rl->opnum]);
+ emit_insn (other_output_reload_insns[rl->opnum]);
other_output_reload_insns[rl->opnum] = get_insns ();
}
else
@@ -7040,25 +7066,25 @@ emit_reload_insns (chain)
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, insn);
- emit_insns_before (other_input_reload_insns, insn);
+ emit_insn_before (other_input_address_reload_insns, insn);
+ emit_insn_before (other_input_reload_insns, insn);
for (j = 0; j < reload_n_operands; j++)
{
- emit_insns_before (inpaddr_address_reload_insns[j], insn);
- emit_insns_before (input_address_reload_insns[j], insn);
- emit_insns_before (input_reload_insns[j], insn);
+ emit_insn_before (inpaddr_address_reload_insns[j], insn);
+ emit_insn_before (input_address_reload_insns[j], insn);
+ emit_insn_before (input_reload_insns[j], insn);
}
- emit_insns_before (other_operand_reload_insns, insn);
- emit_insns_before (operand_reload_insns, insn);
+ emit_insn_before (other_operand_reload_insns, insn);
+ emit_insn_before (operand_reload_insns, insn);
for (j = 0; j < reload_n_operands; j++)
{
- rtx x = emit_insns_after (outaddr_address_reload_insns[j], insn);
- x = emit_insns_after (output_address_reload_insns[j], x);
- x = emit_insns_after (output_reload_insns[j], x);
- emit_insns_after (other_output_reload_insns[j], x);
+ rtx x = emit_insn_after (outaddr_address_reload_insns[j], insn);
+ x = emit_insn_after (output_address_reload_insns[j], x);
+ x = emit_insn_after (output_reload_insns[j], x);
+ emit_insn_after (other_output_reload_insns[j], x);
}
/* For all the spill regs newly reloaded in this instruction,
@@ -7165,8 +7191,7 @@ emit_reload_insns (chain)
for (k = 1; k < nnr; k++)
reg_last_reload_reg[nregno + k]
= (nr == nnr
- ? gen_rtx_REG (reg_raw_mode[REGNO (rld[r].reg_rtx) + k],
- REGNO (rld[r].reg_rtx) + k)
+ ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k]
: 0);
/* Now do the inverse operation. */
@@ -7215,8 +7240,7 @@ emit_reload_insns (chain)
for (k = 1; k < nnr; k++)
reg_last_reload_reg[nregno + k]
= (nr == nnr
- ? gen_rtx_REG (reg_raw_mode[REGNO (rld[r].reg_rtx) + k],
- REGNO (rld[r].reg_rtx) + k)
+ ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k]
: 0);
/* Unless we inherited this reload, show we haven't
@@ -7358,9 +7382,6 @@ gen_reload (out, in, opnum, type)
{
rtx last = get_last_insn ();
rtx tem;
-#ifdef SECONDARY_MEMORY_NEEDED
- int in_regnum, out_regnum;
-#endif
/* If IN is a paradoxical SUBREG, remove it and try to put the
opposite SUBREG on OUT. Likewise for a paradoxical SUBREG on OUT. */
@@ -7523,22 +7544,22 @@ gen_reload (out, in, opnum, type)
#ifdef SECONDARY_MEMORY_NEEDED
/* If we need a memory location to do the move, do it that way. */
- else if ((in_regnum = true_regnum (in)) >= 0
- && in_regnum < FIRST_PSEUDO_REGISTER
- && (out_regnum = true_regnum (out)) >= 0
- && out_regnum < FIRST_PSEUDO_REGISTER
- && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (in_regnum),
- REGNO_REG_CLASS (out_regnum),
+ else if ((GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
+ && reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
+ && (GET_CODE (out) == REG || GET_CODE (out) == SUBREG)
+ && reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
+ && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
+ REGNO_REG_CLASS (reg_or_subregno (out)),
GET_MODE (out)))
{
/* Get the memory to use and rewrite both registers to its mode. */
rtx loc = get_secondary_mem (in, GET_MODE (out), opnum, type);
if (GET_MODE (loc) != GET_MODE (out))
- out = gen_rtx_REG (GET_MODE (loc), out_regnum);
+ out = gen_rtx_REG (GET_MODE (loc), REGNO (out));
if (GET_MODE (loc) != GET_MODE (in))
- in = gen_rtx_REG (GET_MODE (loc), in_regnum);
+ in = gen_rtx_REG (GET_MODE (loc), REGNO (in));
gen_reload (loc, in, opnum, type);
gen_reload (out, loc, opnum, type);
@@ -7920,7 +7941,7 @@ inc_for_reload (reloadreg, in, value, inc_amount)
rtx real_in = in == value ? XEXP (in, 0) : in;
/* No hard register is equivalent to this register after
- inc/dec operation. If REG_LAST_RELOAD_REG were non-zero,
+ inc/dec operation. If REG_LAST_RELOAD_REG were nonzero,
we could inc/dec that register as well (maybe even using it for
the source), but I'm not sure it's worth worrying about. */
if (GET_CODE (incloc) == REG)
@@ -7995,30 +8016,6 @@ inc_for_reload (reloadreg, in, value, inc_amount)
return store;
}
-/* INSN is a no-op; delete it.
- If this sets the return value of the function, we must keep a USE around,
- in case this is in a different basic block than the final USE. Otherwise,
- we could loose important register lifeness information on
- SMALL_REGISTER_CLASSES machines, where return registers might be used as
- spills: subsequent passes assume that spill registers are dead at the end
- of a basic block.
- VALUE must be the return value in such a case, NULL otherwise. */
-static void
-reload_cse_delete_noop_set (insn, value)
- rtx insn, value;
-{
- bool purge = BLOCK_FOR_INSN (insn)->end == insn;
- if (value)
- {
- PATTERN (insn) = gen_rtx_USE (VOIDmode, value);
- INSN_CODE (insn) = -1;
- REG_NOTES (insn) = NULL_RTX;
- }
- else
- delete_insn (insn);
- if (purge)
- purge_dead_edges (BLOCK_FOR_INSN (insn));
-}
/* See whether a single set SET is a noop. */
static int
@@ -8030,8 +8027,9 @@ reload_cse_noop_set_p (set)
/* Try to simplify INSN. */
static void
-reload_cse_simplify (insn)
+reload_cse_simplify (insn, testreg)
rtx insn;
+ rtx testreg;
{
rtx body = PATTERN (insn);
@@ -8049,16 +8047,17 @@ reload_cse_simplify (insn)
if (!count && reload_cse_noop_set_p (body))
{
rtx value = SET_DEST (body);
- if (! REG_FUNCTION_VALUE_P (SET_DEST (body)))
+ if (REG_P (value)
+ && ! REG_FUNCTION_VALUE_P (value))
value = 0;
- reload_cse_delete_noop_set (insn, value);
+ delete_insn_and_edges (insn);
return;
}
if (count > 0)
apply_change_group ();
else
- reload_cse_simplify_operands (insn);
+ reload_cse_simplify_operands (insn, testreg);
}
else if (GET_CODE (body) == PARALLEL)
{
@@ -8075,7 +8074,8 @@ reload_cse_simplify (insn)
{
if (! reload_cse_noop_set_p (part))
break;
- if (REG_FUNCTION_VALUE_P (SET_DEST (part)))
+ if (REG_P (SET_DEST (part))
+ && REG_FUNCTION_VALUE_P (SET_DEST (part)))
{
if (value)
break;
@@ -8088,7 +8088,7 @@ reload_cse_simplify (insn)
if (i < 0)
{
- reload_cse_delete_noop_set (insn, value);
+ delete_insn_and_edges (insn);
/* We're done with this insn. */
return;
}
@@ -8101,7 +8101,7 @@ reload_cse_simplify (insn)
if (count > 0)
apply_change_group ();
else
- reload_cse_simplify_operands (insn);
+ reload_cse_simplify_operands (insn, testreg);
}
}
@@ -8127,6 +8127,7 @@ reload_cse_regs_1 (first)
rtx first;
{
rtx insn;
+ rtx testreg = gen_rtx_REG (VOIDmode, -1);
cselib_init ();
init_alias_analysis ();
@@ -8134,7 +8135,7 @@ reload_cse_regs_1 (first)
for (insn = first; insn; insn = NEXT_INSN (insn))
{
if (INSN_P (insn))
- reload_cse_simplify (insn);
+ reload_cse_simplify (insn, testreg);
cselib_process_insn (insn);
}
@@ -8192,7 +8193,7 @@ reload_cse_simplify_set (set, insn)
#ifdef LOAD_EXTEND_OP
/* When replacing a memory with a register, we need to honor assumptions
that combine made wrt the contents of sign bits. We'll do this by
- generating an extend instruction instead of a reg->reg copy. Thus
+ generating an extend instruction instead of a reg->reg copy. Thus
the destination must be a register that we can widen. */
if (GET_CODE (src) == MEM
&& GET_MODE_BITSIZE (GET_MODE (src)) < BITS_PER_WORD
@@ -8277,7 +8278,13 @@ reload_cse_simplify_set (set, insn)
{
#ifdef LOAD_EXTEND_OP
if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) < BITS_PER_WORD
- && extend_op != NIL)
+ && extend_op != NIL
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
+ word_mode,
+ REGNO_REG_CLASS (REGNO (SET_DEST (set))))
+#endif
+ )
{
rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
@@ -8305,8 +8312,9 @@ reload_cse_simplify_set (set, insn)
hard registers. */
static int
-reload_cse_simplify_operands (insn)
+reload_cse_simplify_operands (insn, testreg)
rtx insn;
+ rtx testreg;
{
int i, j;
@@ -8326,7 +8334,6 @@ reload_cse_simplify_operands (insn)
int *op_alt_regno[MAX_RECOG_OPERANDS];
/* Array of alternatives, sorted in order of decreasing desirability. */
int *alternative_order;
- rtx reg = gen_rtx_REG (VOIDmode, -1);
extract_insn (insn);
@@ -8410,8 +8417,8 @@ reload_cse_simplify_operands (insn)
if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
continue;
- REGNO (reg) = regno;
- PUT_MODE (reg, mode);
+ REGNO (testreg) = regno;
+ PUT_MODE (testreg, mode);
/* We found a register equal to this operand. Now look for all
alternatives that can accept this register and have not been
@@ -8453,10 +8460,10 @@ reload_cse_simplify_operands (insn)
alternative yet and the operand being replaced is not
a cheap CONST_INT. */
if (op_alt_regno[i][j] == -1
- && reg_fits_class_p (reg, class, 0, mode)
+ && reg_fits_class_p (testreg, class, 0, mode)
&& (GET_CODE (recog_data.operand[i]) != CONST_INT
|| (rtx_cost (recog_data.operand[i], SET)
- > rtx_cost (reg, SET))))
+ > rtx_cost (testreg, SET))))
{
alternative_nregs[j]++;
op_alt_regno[i][j] = regno;
@@ -8583,6 +8590,7 @@ reload_combine ()
int first_index_reg = -1;
int last_index_reg = 0;
int i;
+ basic_block bb;
unsigned int r;
int last_label_ruid;
int min_labelno, n_labels;
@@ -8618,17 +8626,17 @@ reload_combine ()
label_live = (HARD_REG_SET *) xmalloc (n_labels * sizeof (HARD_REG_SET));
CLEAR_HARD_REG_SET (ever_live_at_start);
- for (i = n_basic_blocks - 1; i >= 0; i--)
+ FOR_EACH_BB_REVERSE (bb)
{
- insn = BLOCK_HEAD (i);
+ insn = bb->head;
if (GET_CODE (insn) == CODE_LABEL)
{
HARD_REG_SET live;
REG_SET_TO_HARD_REG_SET (live,
- BASIC_BLOCK (i)->global_live_at_start);
+ bb->global_live_at_start);
compute_use_by_pseudos (&live,
- BASIC_BLOCK (i)->global_live_at_start);
+ bb->global_live_at_start);
COPY_HARD_REG_SET (LABEL_LIVE (insn), live);
IOR_HARD_REG_SET (ever_live_at_start, live);
}
@@ -9357,7 +9365,7 @@ move2add_note_store (dst, set, data)
reg_set_luid[regno] = move2add_last_label_luid + 1;
reg_mode[regno] = mode;
return;
-
+
default:
invalidate:
/* Invalidate the contents of the register. */
@@ -9443,7 +9451,7 @@ copy_eh_notes (insn, x)
for (; x != 0; x = NEXT_INSN (x))
{
if (may_trap_p (PATTERN (x)))
- REG_NOTES (x)
+ REG_NOTES (x)
= gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (eh_note, 0),
REG_NOTES (x));
}
@@ -9454,20 +9462,19 @@ copy_eh_notes (insn, x)
abnormal calls moving basic block end, but in fact it wants to emit
them on the edge. Looks for abnormal call edges, find backward the
proper call and fix the damage.
-
+
Similar handle instructions throwing exceptions internally. */
void
fixup_abnormal_edges ()
{
- int i;
bool inserted = false;
+ basic_block bb;
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
edge e;
- /* Look for cases we are interested in - an calls or instructions causing
+ /* Look for cases we are interested in - calls or instructions causing
exceptions. */
for (e = bb->succ; e; e = e->succ_next)
{
@@ -9500,19 +9507,22 @@ fixup_abnormal_edges ()
next = NEXT_INSN (insn);
if (INSN_P (insn))
{
- rtx seq;
-
delete_insn (insn);
- /* We're not deleting it, we're moving it. */
- INSN_DELETED_P (insn) = 0;
+ /* Sometimes there's still the return value USE.
+ If it's placed after a trapping call (i.e. that
+ call is the last insn anyway), we have no fallthru
+ edge. Simply delete this use and don't try to insert
+ on the non-existant edge. */
+ if (GET_CODE (PATTERN (insn)) != USE)
+ {
+ /* We're not deleting it, we're moving it. */
+ INSN_DELETED_P (insn) = 0;
+ PREV_INSN (insn) = NULL_RTX;
+ NEXT_INSN (insn) = NULL_RTX;
- /* Emit a sequence, rather than scarfing the pattern, so
- that we don't lose REG_NOTES etc. */
- /* ??? Could copy the test from gen_sequence, but don't
- think it's worth the bother. */
- seq = gen_rtx_SEQUENCE (VOIDmode, gen_rtvec (1, insn));
- insert_insn_on_edge (seq, e);
+ insert_insn_on_edge (insn, e);
+ }
}
insn = next;
}
diff --git a/contrib/gcc/reorg.c b/contrib/gcc/reorg.c
index 659fc00..31918ec 100644
--- a/contrib/gcc/reorg.c
+++ b/contrib/gcc/reorg.c
@@ -143,9 +143,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#ifdef DELAY_SLOTS
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
#ifndef ANNUL_IFTRUE_SLOTS
#define eligible_for_annul_true(INSN, SLOTS, TRIAL, FLAGS) 0
#endif
@@ -617,7 +614,9 @@ delete_from_delay_slot (insn)
annul flag. */
if (delay_list)
trial = emit_delay_sequence (trial, delay_list, XVECLEN (seq, 0) - 2);
- else
+ else if (GET_CODE (trial) == JUMP_INSN
+ || GET_CODE (trial) == CALL_INSN
+ || GET_CODE (trial) == INSN)
INSN_ANNULLED_BRANCH_P (trial) = 0;
INSN_FROM_TARGET_P (insn) = 0;
@@ -929,7 +928,7 @@ rare_destination (insn)
taken, return 1. If the branch is slightly less likely to be taken,
return 0 and if the branch is highly unlikely to be taken, return -1.
- CONDITION, if non-zero, is the condition that JUMP_INSN is testing. */
+ CONDITION, if nonzero, is the condition that JUMP_INSN is testing. */
static int
mostly_true_jump (jump_insn, condition)
@@ -1099,7 +1098,7 @@ get_branch_condition (insn, target)
return 0;
}
-/* Return non-zero if CONDITION is more strict than the condition of
+/* Return nonzero if CONDITION is more strict than the condition of
INSN, i.e., if INSN will always branch if CONDITION is true. */
static int
@@ -1127,7 +1126,7 @@ condition_dominates_p (condition, insn)
return comparison_dominates_p (code, other_code);
}
-/* Return non-zero if redirecting JUMP to NEWLABEL does not invalidate
+/* Return nonzero if redirecting JUMP to NEWLABEL does not invalidate
any insns already in the delay slot of JUMP. */
static int
@@ -1139,7 +1138,7 @@ redirect_with_delay_slots_safe_p (jump, newlabel, seq)
/* Make sure all the delay slots of this jump would still
be valid after threading the jump. If they are still
- valid, then return non-zero. */
+ valid, then return nonzero. */
flags = get_jump_flags (jump, newlabel);
for (i = 1; i < XVECLEN (pat, 0); i++)
@@ -1162,7 +1161,7 @@ redirect_with_delay_slots_safe_p (jump, newlabel, seq)
return (i == XVECLEN (pat, 0));
}
-/* Return non-zero if redirecting JUMP to NEWLABEL does not invalidate
+/* Return nonzero if redirecting JUMP to NEWLABEL does not invalidate
any insns we wish to place in the delay slot of JUMP. */
static int
@@ -1174,7 +1173,7 @@ redirect_with_delay_list_safe_p (jump, newlabel, delay_list)
/* Make sure all the insns in DELAY_LIST would still be
valid after threading the jump. If they are still
- valid, then return non-zero. */
+ valid, then return nonzero. */
flags = get_jump_flags (jump, newlabel);
for (li = delay_list, i = 0; li; li = XEXP (li, 1), i++)
@@ -1234,9 +1233,9 @@ check_annul_list_true_false (annul_true_p, delay_list)
insns in DELAY_LIST). It is updated with the number that have been
filled from the SEQUENCE, if any.
- PANNUL_P points to a non-zero value if we already know that we need
+ PANNUL_P points to a nonzero value if we already know that we need
to annul INSN. If this routine determines that annulling is needed,
- it may set that value non-zero.
+ it may set that value nonzero.
PNEW_THREAD points to a location that is to receive the place at which
execution should continue. */
@@ -1857,9 +1856,9 @@ redundant_insn (insn, target, delay_list)
return 0;
}
-/* Return 1 if THREAD can only be executed in one way. If LABEL is non-zero,
+/* Return 1 if THREAD can only be executed in one way. If LABEL is nonzero,
it is the target of the branch insn being scanned. If ALLOW_FALLTHROUGH
- is non-zero, we are allowed to fall into this thread; otherwise, we are
+ is nonzero, we are allowed to fall into this thread; otherwise, we are
not.
If LABEL is used more than one or we pass a label other than LABEL before
@@ -2041,7 +2040,7 @@ update_reg_unused_notes (insn, redundant_insn)
/* Scan a function looking for insns that need a delay slot and find insns to
put into the delay slot.
- NON_JUMPS_P is non-zero if we are to only try to fill non-jump insns (such
+ NON_JUMPS_P is nonzero if we are to only try to fill non-jump insns (such
as calls). We do these first since we don't want jump insns (that are
easier to fill) to get the only insns that could be used for non-jump insns.
When it is zero, only try to fill JUMP_INSNs.
@@ -2544,7 +2543,7 @@ fill_simple_delay_slots (non_jumps_p)
OPPOSITE_THREAD is the thread in the opposite direction. It is used
to see if any potential delay slot insns set things needed there.
- LIKELY is non-zero if it is extremely likely that the branch will be
+ LIKELY is nonzero if it is extremely likely that the branch will be
taken and THREAD_IF_TRUE is set. This is used for the branch at the
end of a loop back up to the top.
@@ -3238,6 +3237,7 @@ relax_delay_slots (first)
&& GET_CODE (next) == JUMP_INSN
&& GET_CODE (PATTERN (next)) == RETURN)
{
+ rtx after;
int i;
/* Delete the RETURN and just execute the delay list insns.
@@ -3254,7 +3254,15 @@ relax_delay_slots (first)
trial = PREV_INSN (insn);
delete_related_insns (insn);
- emit_insn_after (pat, trial);
+ if (GET_CODE (pat) != SEQUENCE)
+ abort ();
+ after = trial;
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ {
+ rtx this_insn = XVECEXP (pat, 0, i);
+ add_insn_after (this_insn, after);
+ after = this_insn;
+ }
delete_scheduled_jump (delay_insn);
continue;
}
@@ -3350,6 +3358,7 @@ relax_delay_slots (first)
#endif
)
{
+ rtx after;
int i;
/* All this insn does is execute its delay list and jump to the
@@ -3368,7 +3377,15 @@ relax_delay_slots (first)
trial = PREV_INSN (insn);
delete_related_insns (insn);
- emit_insn_after (pat, trial);
+ if (GET_CODE (pat) != SEQUENCE)
+ abort ();
+ after = trial;
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ {
+ rtx this_insn = XVECEXP (pat, 0, i);
+ add_insn_after (this_insn, after);
+ after = this_insn;
+ }
delete_scheduled_jump (delay_insn);
continue;
}
@@ -3465,6 +3482,17 @@ make_return_insns (first)
rtx real_return_label = end_of_function_label;
int slots, i;
+#ifdef DELAY_SLOTS_FOR_EPILOGUE
+ /* If a previous pass filled delay slots in the epilogue, things get a
+ bit more complicated, as those filler insns would generally (without
+ data flow analysis) have to be executed after any existing branch
+ delay slot filler insns. It is also unknown whether such a
+ transformation would actually be profitable. Note that the existing
+ code only cares for branches with (some) filled delay slots. */
+ if (current_function_epilogue_delay_list != NULL)
+ return;
+#endif
+
/* See if there is a RETURN insn in the function other than the one we
made for END_OF_FUNCTION_LABEL. If so, set up anything we can't change
into a RETURN to jump to it. */
diff --git a/contrib/gcc/resource.c b/contrib/gcc/resource.c
index f306abb..a72dd9c 100644
--- a/contrib/gcc/resource.c
+++ b/contrib/gcc/resource.c
@@ -1,5 +1,5 @@
/* Definitions for computing resource usage of specific insns.
- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -133,7 +133,7 @@ find_basic_block (insn, search_limit)
rtx insn;
int search_limit;
{
- int i;
+ basic_block bb;
/* Scan backwards to the previous BARRIER. Then see if we can find a
label that starts a basic block. Return the basic block number. */
@@ -146,9 +146,9 @@ find_basic_block (insn, search_limit)
if (search_limit == 0)
return -1;
- /* The start of the function is basic block zero. */
+ /* The start of the function. */
else if (insn == 0)
- return 0;
+ return ENTRY_BLOCK_PTR->next_bb->index;
/* See if any of the upcoming CODE_LABELs start a basic block. If we reach
anything other than a CODE_LABEL or note, we can't find this code. */
@@ -156,9 +156,9 @@ find_basic_block (insn, search_limit)
insn && GET_CODE (insn) == CODE_LABEL;
insn = next_nonnote_insn (insn))
{
- for (i = 0; i < n_basic_blocks; i++)
- if (insn == BLOCK_HEAD (i))
- return i;
+ FOR_EACH_BB (bb)
+ if (insn == bb->head)
+ return bb->index;
}
return -1;
@@ -175,10 +175,23 @@ next_insn_no_annul (insn)
{
/* If INSN is an annulled branch, skip any insns from the target
of the branch. */
- if (INSN_ANNULLED_BRANCH_P (insn)
+ if ((GET_CODE (insn) == JUMP_INSN
+ || GET_CODE (insn) == CALL_INSN
+ || GET_CODE (insn) == INSN)
+ && INSN_ANNULLED_BRANCH_P (insn)
&& NEXT_INSN (PREV_INSN (insn)) != insn)
- while (INSN_FROM_TARGET_P (NEXT_INSN (insn)))
- insn = NEXT_INSN (insn);
+ {
+ rtx next = NEXT_INSN (insn);
+ enum rtx_code code = GET_CODE (next);
+
+ while ((code == INSN || code == JUMP_INSN || code == CALL_INSN)
+ && INSN_FROM_TARGET_P (next))
+ {
+ insn = next;
+ next = NEXT_INSN (insn);
+ code = GET_CODE (next);
+ }
+ }
insn = NEXT_INSN (insn);
if (insn && GET_CODE (insn) == INSN
@@ -281,7 +294,7 @@ mark_referenced_resources (x, res, include_delayed_effects)
We can not just fall through here since then we would be confused
by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
traditional asms unlike their normal usage. */
-
+
for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
mark_referenced_resources (ASM_OPERANDS_INPUT (x, i), res, 0);
return;
@@ -359,7 +372,7 @@ mark_referenced_resources (x, res, include_delayed_effects)
We assume that they both use and set all registers. Using all
registers ensures that a register will not be considered dead
just because it crosses a setjmp call. A register should be
- considered dead only if the setjmp call returns non-zero. */
+ considered dead only if the setjmp call returns nonzero. */
if (find_reg_note (x, REG_SETJMP, NULL))
SET_HARD_REG_SET (res->regs);
@@ -423,7 +436,7 @@ mark_referenced_resources (x, res, include_delayed_effects)
}
/* A subroutine of mark_target_live_regs. Search forward from TARGET
- looking for registers that are set before they are used. These are dead.
+ 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. */
@@ -721,7 +734,7 @@ mark_set_resources (x, res, in_dest, mark_type)
case CLOBBER:
mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST);
return;
-
+
case SEQUENCE:
for (i = 0; i < XVECLEN (x, 0); i++)
if (! (INSN_ANNULLED_BRANCH_P (XVECEXP (x, 0, 0))
@@ -821,7 +834,7 @@ mark_set_resources (x, res, in_dest, mark_type)
We can not just fall through here since then we would be confused
by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
traditional asms unlike their normal usage. */
-
+
for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
mark_set_resources (ASM_OPERANDS_INPUT (x, i), res, in_dest,
MARK_SRC_DEST);
@@ -946,7 +959,7 @@ mark_target_live_regs (insns, target, res)
}
else
{
- /* Allocate a place to put our results and chain it into the
+ /* Allocate a place to put our results and chain it into the
hash table. */
tinfo = (struct target_info *) xmalloc (sizeof (struct target_info));
tinfo->uid = INSN_UID (target);
@@ -1007,16 +1020,18 @@ mark_target_live_regs (insns, target, res)
{
rtx link;
rtx real_insn = insn;
+ enum rtx_code code = GET_CODE (insn);
/* If this insn is from the target of a branch, it isn't going to
be used in the sequel. If it is used in both cases, this
test will not be true. */
- if (INSN_FROM_TARGET_P (insn))
+ if ((code == INSN || code == JUMP_INSN || code == CALL_INSN)
+ && INSN_FROM_TARGET_P (insn))
continue;
/* If this insn is a USE made by update_block, we care about the
underlying insn. */
- if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == USE
+ if (code == INSN && GET_CODE (PATTERN (insn)) == USE
&& INSN_P (XEXP (PATTERN (insn), 0)))
real_insn = XEXP (PATTERN (insn), 0);
@@ -1056,7 +1071,7 @@ mark_target_live_regs (insns, target, res)
= (first_regno
+ HARD_REGNO_NREGS (first_regno,
GET_MODE (XEXP (link, 0))));
-
+
for (i = first_regno; i < last_regno; i++)
SET_HARD_REG_BIT (pending_dead_regs, i);
}
@@ -1075,7 +1090,7 @@ mark_target_live_regs (insns, target, res)
= (first_regno
+ HARD_REGNO_NREGS (first_regno,
GET_MODE (XEXP (link, 0))));
-
+
for (i = first_regno; i < last_regno; i++)
CLEAR_HARD_REG_BIT (current_live_regs, i);
}
@@ -1093,7 +1108,7 @@ mark_target_live_regs (insns, target, res)
RTL chain when there are no epilogue insns. Certain resources
are implicitly required at that point. */
else if (GET_CODE (real_insn) == NOTE
- && NOTE_LINE_NUMBER (real_insn) == NOTE_INSN_EPILOGUE_BEG)
+ && NOTE_LINE_NUMBER (real_insn) == NOTE_INSN_EPILOGUE_BEG)
IOR_HARD_REG_SET (current_live_regs, start_of_epilogue_needs.regs);
}
@@ -1163,7 +1178,7 @@ init_resource_info (epilogue_insn)
/* Indicate what resources are required to be valid at the end of the current
function. The condition code never is and memory always is. If the
frame pointer is needed, it is and so is the stack pointer unless
- EXIT_IGNORE_STACK is non-zero. If the frame pointer is not needed, the
+ EXIT_IGNORE_STACK is nonzero. If the frame pointer is not needed, the
stack pointer is. Registers used to return the function value are
needed. Registers holding global variables are needed. */
@@ -1225,7 +1240,7 @@ init_resource_info (epilogue_insn)
/* Allocate and initialize the tables used by mark_target_live_regs. */
target_hash_table = (struct target_info **)
xcalloc (TARGET_HASH_PRIME, sizeof (struct target_info *));
- bb_ticks = (int *) xcalloc (n_basic_blocks, sizeof (int));
+ bb_ticks = (int *) xcalloc (last_basic_block, sizeof (int));
}
/* Free up the resources allcated to mark_target_live_regs (). This
@@ -1237,12 +1252,12 @@ free_resource_info ()
if (target_hash_table != NULL)
{
int i;
-
- for (i = 0; i < TARGET_HASH_PRIME; ++i)
+
+ for (i = 0; i < TARGET_HASH_PRIME; ++i)
{
struct target_info *ti = target_hash_table[i];
- while (ti)
+ while (ti)
{
struct target_info *next = ti->next;
free (ti);
@@ -1268,7 +1283,7 @@ clear_hashed_info_for_insn (insn)
rtx insn;
{
struct target_info *tinfo;
-
+
if (target_hash_table != NULL)
{
for (tinfo = target_hash_table[INSN_UID (insn) % TARGET_HASH_PRIME];
diff --git a/contrib/gcc/rtl-error.c b/contrib/gcc/rtl-error.c
index 031fa2b..2b660c9 100644
--- a/contrib/gcc/rtl-error.c
+++ b/contrib/gcc/rtl-error.c
@@ -1,5 +1,5 @@
/* RTL specific diagnostic subroutines for the GNU C compiler
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
This file is part of GCC.
@@ -32,7 +32,8 @@ Boston, MA 02111-1307, USA. */
#include "diagnostic.h"
static void file_and_line_for_asm PARAMS ((rtx, const char **, int *));
-static void diagnostic_for_asm PARAMS ((rtx, const char *, va_list *, int));
+static void diagnostic_for_asm PARAMS ((rtx, const char *, va_list *,
+ diagnostic_t));
/* Figure file and line of the given INSN. */
static void
@@ -74,18 +75,18 @@ file_and_line_for_asm (insn, pfile, pline)
of the insn INSN. This is used only when INSN is an `asm' with operands,
and each ASM_OPERANDS records its own source file and line. */
static void
-diagnostic_for_asm (insn, msg, args_ptr, warn)
+diagnostic_for_asm (insn, msg, args_ptr, kind)
rtx insn;
const char *msg;
va_list *args_ptr;
- int warn;
+ diagnostic_t kind;
{
- diagnostic_context dc;
+ diagnostic_info diagnostic;
- set_diagnostic_context (&dc, msg, args_ptr, NULL, 0, warn);
- file_and_line_for_asm (insn, &diagnostic_file_location (&dc),
- &diagnostic_line_location (&dc));
- report_diagnostic (&dc);
+ diagnostic_set_info (&diagnostic, msg, args_ptr, NULL, 0, kind);
+ file_and_line_for_asm (insn, &diagnostic.location.file,
+ &diagnostic.location.line);
+ report_diagnostic (&diagnostic);
}
void
@@ -95,7 +96,7 @@ error_for_asm VPARAMS ((rtx insn, const char *msgid, ...))
VA_FIXEDARG (ap, rtx, insn);
VA_FIXEDARG (ap, const char *, msgid);
- diagnostic_for_asm (insn, msgid, &ap, /* warn = */ 0);
+ diagnostic_for_asm (insn, msgid, &ap, DK_ERROR);
VA_CLOSE (ap);
}
@@ -106,7 +107,7 @@ warning_for_asm VPARAMS ((rtx insn, const char *msgid, ...))
VA_FIXEDARG (ap, rtx, insn);
VA_FIXEDARG (ap, const char *, msgid);
- diagnostic_for_asm (insn, msgid, &ap, /* warn = */ 1);
+ diagnostic_for_asm (insn, msgid, &ap, DK_WARNING);
VA_CLOSE (ap);
}
diff --git a/contrib/gcc/rtl.c b/contrib/gcc/rtl.c
index c50201b..8c6de3c 100644
--- a/contrib/gcc/rtl.c
+++ b/contrib/gcc/rtl.c
@@ -1,6 +1,6 @@
/* RTL utility routines.
- Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002
- Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002,
+ 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -27,70 +27,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "errors.h"
-/* Calculate the format for CONST_DOUBLE. This depends on the relative
- widths of HOST_WIDE_INT and REAL_VALUE_TYPE.
-
- We need to go out to 0wwwww, since REAL_ARITHMETIC assumes 16-bits
- per element in REAL_VALUE_TYPE.
-
- This is duplicated in gengenrtl.c.
-
- A number of places assume that there are always at least two 'w'
- slots in a CONST_DOUBLE, so we provide them even if one would suffice. */
-
-#ifdef REAL_ARITHMETIC
-# if MAX_LONG_DOUBLE_TYPE_SIZE == 96
-# define REAL_WIDTH \
- (11*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
-# else
-# if MAX_LONG_DOUBLE_TYPE_SIZE == 128
-# define REAL_WIDTH \
- (19*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
-# else
-# if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
-# define REAL_WIDTH \
- (7*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
-# endif
-# endif
-# endif
-#endif /* REAL_ARITHMETIC */
-
-#ifndef REAL_WIDTH
-# if HOST_BITS_PER_WIDE_INT*2 >= MAX_LONG_DOUBLE_TYPE_SIZE
-# define REAL_WIDTH 2
-# else
-# if HOST_BITS_PER_WIDE_INT*3 >= MAX_LONG_DOUBLE_TYPE_SIZE
-# define REAL_WIDTH 3
-# else
-# if HOST_BITS_PER_WIDE_INT*4 >= MAX_LONG_DOUBLE_TYPE_SIZE
-# define REAL_WIDTH 4
-# endif
-# endif
-# endif
-#endif /* REAL_WIDTH */
-
-#if REAL_WIDTH == 1
-# define CONST_DOUBLE_FORMAT "0ww"
-#else
-# if REAL_WIDTH == 2
-# define CONST_DOUBLE_FORMAT "0ww"
-# else
-# if REAL_WIDTH == 3
-# define CONST_DOUBLE_FORMAT "0www"
-# else
-# if REAL_WIDTH == 4
-# define CONST_DOUBLE_FORMAT "0wwww"
-# else
-# if REAL_WIDTH == 5
-# define CONST_DOUBLE_FORMAT "0wwwww"
-# else
-# define CONST_DOUBLE_FORMAT /* nothing - will cause syntax error */
-# endif
-# endif
-# endif
-# endif
-#endif
-
/* Indexed by rtx code, gives number of operands for an rtx with that code.
Does NOT include rtx header data (code and links). */
@@ -216,7 +152,7 @@ const enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS] = {
/* MODE_CC */ CCmode,
/* MODE_COMPLEX_INT */ CQImode,
/* MODE_COMPLEX_FLOAT */ QCmode,
- /* MODE_VECTOR_INT */ V2QImode,
+ /* MODE_VECTOR_INT */ V1DImode,
/* MODE_VECTOR_FLOAT */ V2SFmode
};
@@ -250,6 +186,7 @@ const char * const rtx_format[NUM_RTX_CODE] = {
"u" a pointer to another insn
prints the uid of the insn.
"b" is a pointer to a bitmap header.
+ "B" is a basic block pointer.
"t" is a tree pointer. */
#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT ,
@@ -278,9 +215,9 @@ const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS] =
"NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG",
"NOTE_INSN_DELETED_LABEL", "NOTE_INSN_FUNCTION_BEG",
"NOTE_INSN_EH_REGION_BEG", "NOTE_INSN_EH_REGION_END",
- "NOTE_INSN_REPEATED_LINE_NUMBER", "NOTE_INSN_RANGE_BEG",
- "NOTE_INSN_RANGE_END", "NOTE_INSN_LIVE",
- "NOTE_INSN_BASIC_BLOCK", "NOTE_INSN_EXPECTED_VALUE"
+ "NOTE_INSN_REPEATED_LINE_NUMBER",
+ "NOTE_INSN_BASIC_BLOCK", "NOTE_INSN_EXPECTED_VALUE",
+ "NOTE_INSN_PREDICTION"
};
const char * const reg_note_name[] =
@@ -289,7 +226,7 @@ const char * const reg_note_name[] =
"REG_WAS_0", "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_BR_PROB",
- "REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA", "REG_BR_PRED",
+ "REG_NOALIAS", "REG_SAVE_AREA", "REG_BR_PRED",
"REG_FRAME_RELATED_EXPR", "REG_EH_CONTEXT", "REG_EH_REGION",
"REG_SAVE_NOTE", "REG_MAYBE_DEAD", "REG_NORETURN",
"REG_NON_LOCAL_GOTO", "REG_SETJMP", "REG_ALWAYS_RETURN",
@@ -395,13 +332,13 @@ copy_rtx (orig)
/* We do not copy the USED flag, which is used as a mark bit during
walks over the RTL. */
- copy->used = 0;
+ RTX_FLAG (copy, used) = 0;
/* We do not copy FRAME_RELATED for INSNs. */
if (GET_RTX_CLASS (code) == 'i')
- copy->frame_related = 0;
- copy->jump = orig->jump;
- copy->call = orig->call;
+ RTX_FLAG (copy, frame_related) = 0;
+ RTX_FLAG (copy, jump) = RTX_FLAG (orig, jump);
+ RTX_FLAG (copy, call) = RTX_FLAG (orig, call);
format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
@@ -432,6 +369,7 @@ copy_rtx (orig)
case 'S':
case 'T':
case 'u':
+ case 'B':
case '0':
/* These are left unchanged. */
break;
@@ -449,45 +387,15 @@ rtx
shallow_copy_rtx (orig)
rtx orig;
{
- int i;
RTX_CODE code = GET_CODE (orig);
- rtx copy = rtx_alloc (code);
+ size_t n = GET_RTX_LENGTH (code);
+ rtx copy = ggc_alloc_rtx (n);
- PUT_MODE (copy, GET_MODE (orig));
- copy->in_struct = orig->in_struct;
- copy->volatil = orig->volatil;
- copy->unchanging = orig->unchanging;
- copy->integrated = orig->integrated;
- copy->frame_related = orig->frame_related;
-
- for (i = 0; i < GET_RTX_LENGTH (code); i++)
- copy->fld[i] = orig->fld[i];
+ memcpy (copy, orig,
+ sizeof (struct rtx_def) + sizeof (rtunion) * (n - 1));
return copy;
}
-
-/* Return the alignment of MODE. This will be bounded by 1 and
- BIGGEST_ALIGNMENT. */
-
-unsigned int
-get_mode_alignment (mode)
- enum machine_mode mode;
-{
- unsigned int alignment;
-
- if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
- || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
- alignment = GET_MODE_UNIT_SIZE (mode);
- else
- alignment = GET_MODE_SIZE (mode);
-
- /* Extract the LSB of the size. */
- alignment = alignment & -alignment;
- alignment *= BITS_PER_UNIT;
-
- alignment = MIN (BIGGEST_ALIGNMENT, MAX (1, alignment));
- return alignment;
-}
/* This is 1 until after the rtl generation pass. */
int rtx_equal_function_value_matters;
@@ -701,3 +609,18 @@ rtvec_check_failed_bounds (r, n, file, line, func)
n, GET_NUM_ELEM (r) - 1, func, trim_filename (file), line);
}
#endif /* ENABLE_RTL_CHECKING */
+
+#if defined ENABLE_RTL_FLAG_CHECKING
+void
+rtl_check_failed_flag (name, r, file, line, func)
+ const char *name;
+ rtx r;
+ const char *file;
+ int line;
+ const char *func;
+{
+ internal_error
+ ("RTL flag check: %s used with unexpected rtx code `%s' in %s, at %s:%d",
+ name, GET_RTX_NAME (GET_CODE (r)), func, trim_filename (file), line);
+}
+#endif /* ENABLE_RTL_FLAG_CHECKING */
diff --git a/contrib/gcc/rtl.def b/contrib/gcc/rtl.def
index 8fad650..d281406 100644
--- a/contrib/gcc/rtl.def
+++ b/contrib/gcc/rtl.def
@@ -207,7 +207,7 @@ DEF_RTL_EXPR(DEFINE_PEEPHOLE, "define_peephole", "EsTV", 'x')
insns. This might, for example, create some RTX's and store them in
elements of `recog_data.operand' for use by the vector of
insn-patterns.
- (`operands' is an alias here for `recog_data.operand'). */
+ (`operands' is an alias here for `recog_data.operand'). */
DEF_RTL_EXPR(DEFINE_SPLIT, "define_split", "EsES", 'x')
/* Definition of an insn and associated split.
@@ -342,6 +342,154 @@ DEF_RTL_EXPR(SEQUENCE, "sequence", "E", 'x')
DEF_RTL_EXPR(ADDRESS, "address", "e", 'm')
/* ----------------------------------------------------------------------
+ Constructions for CPU pipeline description described by NDFAs.
+ These do not appear in actual rtl code in the compiler.
+ ---------------------------------------------------------------------- */
+
+/* (define_cpu_unit string [string]) describes cpu functional
+ units (separated by comma).
+
+ 1st operand: Names of cpu functional units.
+ 2nd operand: Name of automaton (see comments for DEFINE_AUTOMATON).
+
+ All define_reservations, define_cpu_units, and
+ define_query_cpu_units should have unique names which may not be
+ "nothing". */
+DEF_RTL_EXPR(DEFINE_CPU_UNIT, "define_cpu_unit", "sS", 'x')
+
+/* (define_query_cpu_unit string [string]) describes cpu functional
+ units analogously to define_cpu_unit. If we use automaton without
+ minimization, the reservation of such units can be queried for
+ automaton state. */
+DEF_RTL_EXPR(DEFINE_QUERY_CPU_UNIT, "define_query_cpu_unit", "sS", 'x')
+
+/* (exclusion_set string string) means that each CPU functional unit
+ in the first string can not be reserved simultaneously with any
+ unit whose name is in the second string and vise versa. CPU units
+ in the string are separated by commas. For example, it is useful
+ for description CPU with fully pipelined floating point functional
+ unit which can execute simultaneously only single floating point
+ insns or only double floating point insns. All CPU functional
+ units in a set should belong the same automaton. */
+DEF_RTL_EXPR(EXCLUSION_SET, "exclusion_set", "ss", 'x')
+
+/* (presence_set string string) means that each CPU functional unit in
+ the first string can not be reserved unless at least one of units
+ whose names are in the second string is reserved. This is an
+ asymmetric relation. CPU units in the string are separated by
+ commas. For example, it is useful for description that slot1 is
+ reserved after slot0 reservation for VLIW processor. All CPU
+ functional units in a set should belong the same automaton. */
+DEF_RTL_EXPR(PRESENCE_SET, "presence_set", "ss", 'x')
+
+/* (absence_set string string) means that each CPU functional unit in
+ the first string can not be reserved only if each unit whose name
+ is in the second string is not reserved. This is an asymmetric
+ relation (actually exclusion set is analogous to this one but it is
+ symmetric). CPU units in the string are separated by commas. For
+ example, it is useful for description that slot0 can not be
+ reserved after slot1 or slot2 reservation for VLIW processor. All
+ CPU functional units in a set should belong the same automaton. */
+DEF_RTL_EXPR(ABSENCE_SET, "absence_set", "ss", 'x')
+
+/* (define_bypass number out_insn_names in_insn_names) names bypass
+ with given latency (the first number) from insns given by the first
+ string (see define_insn_reservation) into insns given by the second
+ string. Insn names in the strings are separated by commas. The
+ third operand is optional name of function which is additional
+ guard for the bypass. The function will get the two insns as
+ parameters. If the function returns zero the bypass will be
+ ignored for this case. Additional guard is necessary to recognize
+ complicated bypasses, e.g. when consumer is load address. */
+DEF_RTL_EXPR(DEFINE_BYPASS, "define_bypass", "issS", 'x')
+
+/* (define_automaton string) describes names of automata generated and
+ used for pipeline hazards recognition. The names are separated by
+ comma. Actually it is possibly to generate the single automaton
+ but unfortunately it can be very large. If we use more one
+ automata, the summary size of the automata usually is less than the
+ single one. The automaton name is used in define_cpu_unit and
+ define_query_cpu_unit. All automata should have unique names. */
+DEF_RTL_EXPR(DEFINE_AUTOMATON, "define_automaton", "s", 'x')
+
+/* (automata_option string) describes option for generation of
+ automata. Currently there are the following options:
+
+ o "no-minimization" which makes no minimization of automata. This
+ is only worth to do when we are going to query CPU functional
+ unit reservations in an automaton state.
+
+ o "time" which means printing additional time statistics about
+ generation of automata.
+
+ o "v" which means generation of file describing the result
+ automata. The file has suffix `.dfa' and can be used for the
+ description verification and debugging.
+
+ o "w" which means generation of warning instead of error for
+ non-critical errors.
+
+ o "ndfa" which makes nondeterministic finite state automata. */
+DEF_RTL_EXPR(AUTOMATA_OPTION, "automata_option", "s", 'x')
+
+/* (define_reservation string string) names reservation (the first
+ string) of cpu functional units (the 2nd string). Sometimes unit
+ reservations for different insns contain common parts. In such
+ case, you can describe common part and use its name (the 1st
+ parameter) in regular expression in define_insn_reservation. All
+ define_reservations, define_cpu_units, and define_query_cpu_units
+ should have unique names which may not be "nothing". */
+DEF_RTL_EXPR(DEFINE_RESERVATION, "define_reservation", "ss", 'x')
+
+/* (define_insn_reservation name default_latency condition regexpr)
+ describes reservation of cpu functional units (the 3nd operand) for
+ instruction which is selected by the condition (the 2nd parameter).
+ The first parameter is used for output of debugging information.
+ The reservations are described by a regular expression according
+ the following syntax:
+
+ regexp = regexp "," oneof
+ | oneof
+
+ oneof = oneof "|" allof
+ | allof
+
+ allof = allof "+" repeat
+ | repeat
+
+ repeat = element "*" number
+ | element
+
+ element = cpu_function_unit_name
+ | reservation_name
+ | result_name
+ | "nothing"
+ | "(" regexp ")"
+
+ 1. "," is used for describing start of the next cycle in
+ reservation.
+
+ 2. "|" is used for describing the reservation described by the
+ first regular expression *or* the reservation described by the
+ second regular expression *or* etc.
+
+ 3. "+" is used for describing the reservation described by the
+ first regular expression *and* the reservation described by the
+ second regular expression *and* etc.
+
+ 4. "*" is used for convinience and simply means sequence in
+ which the regular expression are repeated NUMBER times with
+ cycle advancing (see ",").
+
+ 5. cpu functional unit name which means its reservation.
+
+ 6. reservation name -- see define_reservation.
+
+ 7. string "nothing" means no units reservation. */
+
+DEF_RTL_EXPR(DEFINE_INSN_RESERVATION, "define_insn_reservation", "sies", 'x')
+
+/* ----------------------------------------------------------------------
Expressions used for insn attributes. These also do not appear in
actual rtl code in the compiler.
---------------------------------------------------------------------- */
@@ -349,10 +497,10 @@ DEF_RTL_EXPR(ADDRESS, "address", "e", 'm')
/* Definition of an insn attribute.
1st operand: name of the attribute
2nd operand: comma-separated list of possible attribute values
- 3rd operand: expression for the default value of the attribute. */
+ 3rd operand: expression for the default value of the attribute. */
DEF_RTL_EXPR(DEFINE_ATTR, "define_attr", "sse", 'x')
-/* Marker for the name of an attribute. */
+/* Marker for the name of an attribute. */
DEF_RTL_EXPR(ATTR, "attr", "s", 'x')
/* For use in the last (optional) operand of DEFINE_INSN or DEFINE_PEEPHOLE and
@@ -404,37 +552,38 @@ DEF_RTL_EXPR (ATTR_FLAG, "attr_flag", "s", 'x')
---------------------------------------------------------------------- */
/* An instruction that cannot jump. */
-DEF_RTL_EXPR(INSN, "insn", "iuueiee", 'i')
+DEF_RTL_EXPR(INSN, "insn", "iuuBteiee", 'i')
/* An instruction that can possibly jump.
Fields ( rtx->fld[] ) have exact same meaning as INSN's. */
-DEF_RTL_EXPR(JUMP_INSN, "jump_insn", "iuueiee0", 'i')
+DEF_RTL_EXPR(JUMP_INSN, "jump_insn", "iuuBteiee0", 'i')
/* An instruction that can possibly call a subroutine
but which will not change which instruction comes next
in the current function.
- Field ( rtx->fld[7] ) is CALL_INSN_FUNCTION_USAGE.
+ Field ( rtx->fld[9] ) is CALL_INSN_FUNCTION_USAGE.
All other fields ( rtx->fld[] ) have exact same meaning as INSN's. */
-DEF_RTL_EXPR(CALL_INSN, "call_insn", "iuueieee", 'i')
+DEF_RTL_EXPR(CALL_INSN, "call_insn", "iuuBteieee", 'i')
/* A marker that indicates that control will not flow through. */
-DEF_RTL_EXPR(BARRIER, "barrier", "iuu", 'x')
+DEF_RTL_EXPR(BARRIER, "barrier", "iuu000000", 'x')
/* Holds a label that is followed by instructions.
Operand:
- 3: is used in jump.c for the use-count of the label.
- 4: is used in flow.c to point to the chain of label_ref's to this label.
- 5: is a number that is unique in the entire compilation.
- 6: is the user-given name of the label, if any.
- 7: is the alternate label name. */
-DEF_RTL_EXPR(CODE_LABEL, "code_label", "iuu00iss", 'x')
-
+ 5: is used in jump.c for the use-count of the label.
+ 6: is used in flow.c to point to the chain of label_ref's to this label.
+ 7: is a number that is unique in the entire compilation.
+ 8: is the user-given name of the label, if any. */
+DEF_RTL_EXPR(CODE_LABEL, "code_label", "iuuB00is", 'x')
+
/* Say where in the code a source line starts, for symbol table's sake.
Operand:
- 3: filename, if line number > 0, note-specific data otherwise.
- 4: line number if > 0, enum note_insn otherwise.
- 5: unique number if line number == note_insn_deleted_label. */
-DEF_RTL_EXPR(NOTE, "note", "iuu0ni", 'x')
+ 5: filename, if line number > 0, note-specific data otherwise.
+ 6: line number if > 0, enum note_insn otherwise.
+ 7: unique number if line number == note_insn_deleted_label.
+ 8-9: padding so that notes and insns are the same size, and thus
+ allocated from the same page ordering. */
+DEF_RTL_EXPR(NOTE, "note", "iuuB0ni00", 'x')
/* ----------------------------------------------------------------------
Top level constituents of INSN, JUMP_INSN and CALL_INSN.
@@ -579,10 +728,8 @@ DEF_RTL_EXPR(RESX, "resx", "i", 'x')
DEF_RTL_EXPR(CONST_INT, "const_int", "w", 'o')
/* numeric floating point constant.
- Operand 0 ('0') is a chain of all CONST_DOUBLEs in use in the
- current function.
- Remaining operands hold the actual value. They are all 'w' and
- there may be from 1 to 4; see rtl.c. */
+ Operands hold the value. They are all 'w' and there may be from 2 to 6;
+ see real.h. */
DEF_RTL_EXPR(CONST_DOUBLE, "const_double", CONST_DOUBLE_FORMAT, 'o')
/* Describes a vector constant. */
@@ -715,7 +862,7 @@ DEF_RTL_EXPR(IF_THEN_ELSE, "if_then_else", "eee", '3')
/* General conditional. The first operand is a vector composed of pairs of
expressions. The first element of each pair is evaluated, in turn.
The value of the conditional is the second expression of the first pair
- whose first expression evaluates non-zero. If none of the expressions is
+ whose first expression evaluates nonzero. If none of the expressions is
true, the second operand will be used as the value of the conditional.
This should be replaced with use of IF_THEN_ELSE. */
@@ -815,7 +962,7 @@ DEF_RTL_EXPR(LTU, "ltu", "ee", '<')
DEF_RTL_EXPR(UNORDERED, "unordered", "ee", '<')
DEF_RTL_EXPR(ORDERED, "ordered", "ee", '<')
-/* These are equivalent to unordered or ... */
+/* These are equivalent to unordered or ... */
DEF_RTL_EXPR(UNEQ, "uneq", "ee", '<')
DEF_RTL_EXPR(UNGE, "unge", "ee", '<')
DEF_RTL_EXPR(UNGT, "ungt", "ee", '<')
@@ -918,7 +1065,7 @@ DEF_RTL_EXPR(RANGE_INFO, "range_info", "uuEiiiiiibbii", 'x')
live length. Operand 7 is the number of calls that this register is live
across. Operand 8 is the symbol node of the variable if the register is a
user variable. Operand 9 is the block node that the variable is declared
- in if the register is a user variable. */
+ in if the register is a user variable. */
DEF_RTL_EXPR(RANGE_REG, "range_reg", "iiiiiiiitt", 'x')
/* Information about a local variable's ranges. Operand 0 is an EXPR_LIST of
@@ -933,7 +1080,7 @@ DEF_RTL_EXPR(RANGE_LIVE, "range_live", "bi", 'x')
/* A unary `__builtin_constant_p' expression. These are only emitted
during RTL generation, and then only if optimize > 0. They are
- eliminated by the first CSE pass. */
+ eliminated by the first CSE pass. */
DEF_RTL_EXPR(CONSTANT_P_RTX, "constant_p_rtx", "e", 'x')
/* A placeholder for a CALL_INSN which may be turned into a normal call,
@@ -962,24 +1109,24 @@ DEF_RTL_EXPR(CALL_PLACEHOLDER, "call_placeholder", "uuuu", 'x')
that specifies where the parts of the result are taken from. Set bits
indicate operand 0, clear bits indicate operand 1. The parts are defined
by the mode of the vectors. */
-DEF_RTL_EXPR(VEC_MERGE, "vec_merge", "eee", 'x')
+DEF_RTL_EXPR(VEC_MERGE, "vec_merge", "eee", '3')
/* Describes an operation that selects parts of a vector.
Operands 0 is the source vector, operand 1 is a PARALLEL that contains
a CONST_INT for each of the subparts of the result vector, giving the
number of the source subpart that should be stored into it. */
-DEF_RTL_EXPR(VEC_SELECT, "vec_select", "ee", 'x')
+DEF_RTL_EXPR(VEC_SELECT, "vec_select", "ee", '2')
/* Describes a vector concat operation. Operands 0 and 1 are the source
vectors, the result is a vector that is as long as operands 0 and 1
combined and is the concatenation of the two source vectors. */
-DEF_RTL_EXPR(VEC_CONCAT, "vec_concat", "ee", 'x')
+DEF_RTL_EXPR(VEC_CONCAT, "vec_concat", "ee", '2')
/* Describes an operation that converts a small vector into a larger one by
duplicating the input values. The output vector mode must have the same
submodes as the input vector mode, and the number of output parts must be
an integer multiple of the number of input parts. */
-DEF_RTL_EXPR(VEC_DUPLICATE, "vec_duplicate", "e", 'x')
+DEF_RTL_EXPR(VEC_DUPLICATE, "vec_duplicate", "e", '1')
/* Addition with signed saturation */
DEF_RTL_EXPR(SS_PLUS, "ss_plus", "ee", 'c')
diff --git a/contrib/gcc/rtl.h b/contrib/gcc/rtl.h
index 388d381..a2cb1db 100644
--- a/contrib/gcc/rtl.h
+++ b/contrib/gcc/rtl.h
@@ -62,6 +62,8 @@ extern const char * const rtx_format[NUM_RTX_CODE];
extern const char rtx_class[NUM_RTX_CODE];
#define GET_RTX_CLASS(CODE) (rtx_class[(int) (CODE)])
+
+extern const unsigned char rtx_next[NUM_RTX_CODE];
/* The flags and bitfields of an ADDR_DIFF_VEC. BASE is the base label
relative to which the offsets are calculated, as explained in rtl.def. */
@@ -89,7 +91,10 @@ typedef struct
so MEMs that the same attributes share a data structure. This means
they cannot be modified in place. If any element is nonzero, it means
the value of the corresponding attribute is unknown. */
-typedef struct
+/* ALIGN and SIZE are the alignment and size of the MEM itself,
+ while EXPR can describe a larger underlying object, which might have a
+ stricter alignment; OFFSET is the offset of the MEM within that object. */
+typedef struct mem_attrs GTY(())
{
HOST_WIDE_INT alias; /* Memory alias set. */
tree expr; /* expr corresponding to MEM. */
@@ -100,7 +105,7 @@ typedef struct
/* Common union for an element of an rtx. */
-typedef union rtunion_def
+union rtunion_def
{
HOST_WIDE_INT rtwint;
int rtint;
@@ -115,11 +120,13 @@ typedef union rtunion_def
tree rttree;
struct basic_block_def *bb;
mem_attrs *rtmem;
-} rtunion;
+};
+typedef union rtunion_def rtunion;
/* RTL expression ("rtx"). */
-struct rtx_def
+struct rtx_def GTY((chain_next ("RTX_NEXT (&%h)"),
+ chain_prev ("RTX_PREV (&%h)")))
{
/* The kind of expression this is. */
ENUM_BITFIELD(rtx_code) code: 16;
@@ -127,33 +134,31 @@ struct rtx_def
/* The kind of value the expression has. */
ENUM_BITFIELD(machine_mode) mode : 8;
- /* 1 in an INSN if it can alter flow of control
- within this function.
- MEM_KEEP_ALIAS_SET_P in a MEM.
- LINK_COST_ZERO in an INSN_LIST.
- SET_IS_RETURN_P in a SET. */
+ /* 1 in a MEM if we should keep the alias set for this mem unchanged
+ when we access a component.
+ 1 in a CALL_INSN if it is a sibling call.
+ 1 in a SET that is for a return.
+ In a CODE_LABEL, part of the two-bit alternate entry field. */
unsigned int jump : 1;
- /* 1 in an INSN if it can call another function.
- LINK_COST_FREE in an INSN_LIST. */
+ /* In a CODE_LABEL, part of the two-bit alternate entry field.
+ 1 in a MEM if it cannot trap. */
unsigned int call : 1;
- /* 1 in a REG if value of this expression will never change during
- the current function, even though it is not manifestly constant.
- 1 in a MEM if contents of memory are constant. This does not
- necessarily mean that the value of this expression is constant.
- 1 in a SUBREG if it is from a promoted variable that is unsigned.
+ /* 1 in a REG, MEM, or CONCAT if the value is set at most once, anywhere.
+ 1 in a SUBREG if it references an unsigned object whose mode has been
+ from a promoted to a wider mode.
1 in a SYMBOL_REF if it addresses something in the per-function
constants pool.
- 1 in a CALL_INSN if it is a const call.
- 1 in a JUMP_INSN if it is a branch that should be annulled. Valid from
- reorg until end of compilation; cleared before used. */
+ 1 in a CALL_INSN, NOTE, or EXPR_LIST for a const or pure call.
+ 1 in a JUMP_INSN, CALL_INSN, or INSN of an annulling branch. */
unsigned int unchanging : 1;
- /* 1 in a MEM expression if contents of memory are volatile.
- 1 in an INSN, CALL_INSN, JUMP_INSN, CODE_LABEL or BARRIER
- if it is deleted.
- 1 in a REG expression if corresponds to a variable declared by the user.
+ /* 1 in a MEM or ASM_OPERANDS expression if the memory reference is volatile.
+ 1 in an INSN, CALL_INSN, JUMP_INSN, CODE_LABEL, BARRIER, or NOTE
+ if it has been deleted.
+ 1 in a REG expression if corresponds to a variable declared by the user,
0 for an internally generated temporary.
- In a SYMBOL_REF, this flag is used for machine-specific purposes.
- In a LABEL_REF or in a REG_LABEL note, this is LABEL_REF_NONLOCAL_P. */
+ 1 in a SUBREG with a negative value.
+ 1 in a LABEL_REF or in a REG_LABEL note for a non-local label.
+ In a SYMBOL_REF, this flag is used for machine-specific purposes. */
unsigned int volatil : 1;
/* 1 in a MEM referring to a field of an aggregate.
0 if the MEM was a variable or the result of a * operator in C;
@@ -165,23 +170,23 @@ struct rtx_def
and must not be deleted even if its count is zero.
1 in a LABEL_REF if this is a reference to a label outside the
current loop.
- 1 in an INSN, JUMP_INSN, or CALL_INSN if this insn must be scheduled
+ 1 in an INSN, JUMP_INSN or CALL_INSN if this insn must be scheduled
together with the preceding insn. Valid only within sched.
1 in an INSN, JUMP_INSN, or CALL_INSN if insn is in a delay slot and
from the target of a branch. Valid from reorg until end of compilation;
cleared before used.
- 1 in an INSN if this insn is dead code. Valid only during
+ 1 in an INSN or related rtx if this insn is dead code. Valid only during
dead-code elimination phase; cleared before use. */
unsigned int in_struct : 1;
- /* 1 if this rtx is used. This is used for copying shared structure.
- See `unshare_all_rtl'.
+ /* At the end of RTL generation, 1 if this rtx is used. This is used for
+ copying shared structure. See `unshare_all_rtl'.
In a REG, this is not needed for that purpose, and used instead
in `leaf_renumber_regs_insn'.
- In a SYMBOL_REF, means that emit_library_call
+ 1 in a SYMBOL_REF, means that emit_library_call
has used it as the function. */
unsigned int used : 1;
/* Nonzero if this rtx came from procedure integration.
- In a REG, nonzero means this reg refers to the return value
+ 1 in a REG or PARALLEL means this rtx refers to the return value
of the current function.
1 in a SYMBOL_REF if the symbol is weak. */
unsigned integrated : 1;
@@ -198,11 +203,29 @@ struct rtx_def
/* The first element of the operands of this rtx.
The number of operands and their types are controlled
by the `code' field, according to rtl.def. */
- rtunion fld[1];
+ rtunion GTY ((special ("rtx_def"),
+ desc ("GET_CODE (&%0)"))) fld[1];
};
#define NULL_RTX (rtx) 0
+/* The "next" and "previous" RTX, relative to this one. */
+
+#define RTX_NEXT(X) (rtx_next[GET_CODE (X)] == 0 ? NULL \
+ : *(rtx *)(((char *)X) + rtx_next[GET_CODE (X)]))
+
+/* FIXME: the "NEXT_INSN (PREV_INSN (X)) == X" condition shouldn't be needed.
+ */
+#define RTX_PREV(X) ((GET_CODE (X) == INSN \
+ || GET_CODE (X) == CALL_INSN \
+ || GET_CODE (X) == JUMP_INSN \
+ || GET_CODE (X) == NOTE \
+ || GET_CODE (X) == BARRIER \
+ || GET_CODE (X) == CODE_LABEL) \
+ && PREV_INSN (X) != NULL \
+ && NEXT_INSN (PREV_INSN (X)) == X \
+ ? PREV_INSN (X) : NULL)
+
/* Define macros to access the `code' field of the rtx. */
#define GET_CODE(RTX) ((enum rtx_code) (RTX)->code)
@@ -211,17 +234,13 @@ struct rtx_def
#define GET_MODE(RTX) ((enum machine_mode) (RTX)->mode)
#define PUT_MODE(RTX, MODE) ((RTX)->mode = (ENUM_BITFIELD(machine_mode)) (MODE))
-#define RTX_INTEGRATED_P(RTX) ((RTX)->integrated)
-#define RTX_UNCHANGING_P(RTX) ((RTX)->unchanging)
-#define RTX_FRAME_RELATED_P(RTX) ((RTX)->frame_related)
-
/* RTL vector. These appear inside RTX's when there is a need
for a variable number of things. The principle use is inside
PARALLEL expressions. */
-struct rtvec_def {
+struct rtvec_def GTY(()) {
int num_elem; /* number of elements */
- rtx elem[1];
+ rtx GTY ((length ("%h.num_elem"))) elem[1];
};
#define NULL_RTVEC (rtvec) 0
@@ -244,6 +263,13 @@ struct rtvec_def {
/* Predicate yielding nonzero iff X is a barrier insn. */
#define BARRIER_P(X) (GET_CODE (X) == BARRIER)
+/* Predicate yielding nonzero iff X is cc0. */
+#ifdef HAVE_cc0
+#define CC0_P(X) ((X) == cc0_rtx)
+#else
+#define CC0_P(X) 0
+#endif
+
/* Predicate yielding nonzero iff X is a data for a jump table. */
#define JUMP_TABLE_DATA_P(INSN) \
(JUMP_P (INSN) && (GET_CODE (PATTERN (INSN)) == ADDR_VEC || \
@@ -264,8 +290,8 @@ struct rtvec_def {
/* The bit with a star outside the statement expr and an & inside is
so that N can be evaluated only once. */
#define RTL_CHECK1(RTX, N, C1) __extension__ \
-(*({ rtx _rtx = (RTX); int _n = (N); \
- enum rtx_code _code = GET_CODE (_rtx); \
+(*({ rtx const _rtx = (RTX); const int _n = (N); \
+ const enum rtx_code _code = GET_CODE (_rtx); \
if (_n < 0 || _n >= GET_RTX_LENGTH (_code)) \
rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__, \
__FUNCTION__); \
@@ -275,8 +301,8 @@ struct rtvec_def {
&_rtx->fld[_n]; }))
#define RTL_CHECK2(RTX, N, C1, C2) __extension__ \
-(*({ rtx _rtx = (RTX); int _n = (N); \
- enum rtx_code _code = GET_CODE (_rtx); \
+(*({ rtx const _rtx = (RTX); const int _n = (N); \
+ const enum rtx_code _code = GET_CODE (_rtx); \
if (_n < 0 || _n >= GET_RTX_LENGTH (_code)) \
rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__, \
__FUNCTION__); \
@@ -287,22 +313,22 @@ struct rtvec_def {
&_rtx->fld[_n]; }))
#define RTL_CHECKC1(RTX, N, C) __extension__ \
-(*({ rtx _rtx = (RTX); int _n = (N); \
+(*({ rtx const _rtx = (RTX); const int _n = (N); \
if (GET_CODE (_rtx) != (C)) \
rtl_check_failed_code1 (_rtx, (C), __FILE__, __LINE__, \
__FUNCTION__); \
&_rtx->fld[_n]; }))
#define RTL_CHECKC2(RTX, N, C1, C2) __extension__ \
-(*({ rtx _rtx = (RTX); int _n = (N); \
- enum rtx_code _code = GET_CODE (_rtx); \
+(*({ rtx const _rtx = (RTX); const int _n = (N); \
+ const enum rtx_code _code = GET_CODE (_rtx); \
if (_code != (C1) && _code != (C2)) \
rtl_check_failed_code2 (_rtx, (C1), (C2), __FILE__, __LINE__, \
__FUNCTION__); \
&_rtx->fld[_n]; }))
#define RTVEC_ELT(RTVEC, I) __extension__ \
-(*({ rtvec _rtvec = (RTVEC); int _i = (I); \
+(*({ rtvec const _rtvec = (RTVEC); const int _i = (I); \
if (_i < 0 || _i >= GET_NUM_ELEM (_rtvec)) \
rtvec_check_failed_bounds (_rtvec, _i, __FILE__, __LINE__, \
__FUNCTION__); \
@@ -337,6 +363,113 @@ extern void rtvec_check_failed_bounds PARAMS ((rtvec, int,
#endif
+/* General accessor macros for accessing the flags of an rtx. */
+
+/* Access an individual rtx flag, with no checking of any kind. */
+#define RTX_FLAG(RTX, FLAG) ((RTX)->FLAG)
+
+#if defined ENABLE_RTL_FLAG_CHECKING && (GCC_VERSION >= 2007)
+#define RTL_FLAG_CHECK1(NAME, RTX, C1) __extension__ \
+({ rtx const _rtx = (RTX); \
+ if (GET_CODE(_rtx) != C1) \
+ rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+#define RTL_FLAG_CHECK2(NAME, RTX, C1, C2) __extension__ \
+({ rtx const _rtx = (RTX); \
+ if (GET_CODE(_rtx) != C1 && GET_CODE(_rtx) != C2) \
+ rtl_check_failed_flag (NAME,_rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+#define RTL_FLAG_CHECK3(NAME, RTX, C1, C2, C3) __extension__ \
+({ rtx const _rtx = (RTX); \
+ if (GET_CODE(_rtx) != C1 && GET_CODE(_rtx) != C2 \
+ && GET_CODE(_rtx) != C3) \
+ rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+#define RTL_FLAG_CHECK4(NAME, RTX, C1, C2, C3, C4) __extension__ \
+({ rtx const _rtx = (RTX); \
+ if (GET_CODE(_rtx) != C1 && GET_CODE(_rtx) != C2 \
+ && GET_CODE(_rtx) != C3 && GET_CODE(_rtx) != C4) \
+ rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+#define RTL_FLAG_CHECK5(NAME, RTX, C1, C2, C3, C4, C5) __extension__ \
+({ rtx const _rtx = (RTX); \
+ if (GET_CODE(_rtx) != C1 && GET_CODE(_rtx) != C2 \
+ && GET_CODE(_rtx) != C3 && GET_CODE(_rtx) != C4 \
+ && GET_CODE(_rtx) != C5) \
+ rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+#define RTL_FLAG_CHECK6(NAME, RTX, C1, C2, C3, C4, C5, C6) \
+ __extension__ \
+({ rtx const _rtx = (RTX); \
+ if (GET_CODE(_rtx) != C1 && GET_CODE(_rtx) != C2 \
+ && GET_CODE(_rtx) != C3 && GET_CODE(_rtx) != C4 \
+ && GET_CODE(_rtx) != C5 && GET_CODE(_rtx) != C6) \
+ rtl_check_failed_flag (NAME,_rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+#define RTL_FLAG_CHECK7(NAME, RTX, C1, C2, C3, C4, C5, C6, C7) \
+ __extension__ \
+({ rtx const _rtx = (RTX); \
+ if (GET_CODE(_rtx) != C1 && GET_CODE(_rtx) != C2 \
+ && GET_CODE(_rtx) != C3 && GET_CODE(_rtx) != C4 \
+ && GET_CODE(_rtx) != C5 && GET_CODE(_rtx) != C6 \
+ && GET_CODE(_rtx) != C7) \
+ rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+#define RTL_FLAG_CHECK8(NAME, RTX, C1, C2, C3, C4, C5, C6, C7, C8) \
+ __extension__ \
+({ rtx const _rtx = (RTX); \
+ if (GET_CODE(_rtx) != C1 && GET_CODE(_rtx) != C2 \
+ && GET_CODE(_rtx) != C3 && GET_CODE(_rtx) != C4 \
+ && GET_CODE(_rtx) != C5 && GET_CODE(_rtx) != C6 \
+ && GET_CODE(_rtx) != C7 && GET_CODE(_rtx) != C8) \
+ rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+extern void rtl_check_failed_flag PARAMS ((const char *, rtx, const char *,
+ int, const char *))
+ ATTRIBUTE_NORETURN
+ ;
+
+#else /* not ENABLE_RTL_FLAG_CHECKING */
+
+#define RTL_FLAG_CHECK1(NAME, RTX, C1) (RTX)
+#define RTL_FLAG_CHECK2(NAME, RTX, C1, C2) (RTX)
+#define RTL_FLAG_CHECK3(NAME, RTX, C1, C2, C3) (RTX)
+#define RTL_FLAG_CHECK4(NAME, RTX, C1, C2, C3, C4) (RTX)
+#define RTL_FLAG_CHECK5(NAME, RTX, C1, C2, C3, C4, C5) (RTX)
+#define RTL_FLAG_CHECK6(NAME, RTX, C1, C2, C3, C4, C5, C6) (RTX)
+#define RTL_FLAG_CHECK7(NAME, RTX, C1, C2, C3, C4, C5, C6, C7) (RTX)
+#define RTL_FLAG_CHECK8(NAME, RTX, C1, C2, C3, C4, C5, C6, C7, C8) (RTX)
+#endif
+
+#define CLEAR_RTX_FLAGS(RTX) \
+do { \
+ rtx const _rtx = (RTX); \
+ _rtx->call = 0; \
+ _rtx->frame_related = 0; \
+ _rtx->in_struct = 0; \
+ _rtx->integrated = 0; \
+ _rtx->jump = 0; \
+ _rtx->unchanging = 0; \
+ _rtx->used = 0; \
+ _rtx->volatil = 0; \
+} while (0)
+
#define XWINT(RTX, N) (RTL_CHECK1 (RTX, N, 'w').rtwint)
#define XINT(RTX, N) (RTL_CHECK2 (RTX, N, 'i', 'n').rtint)
#define XSTR(RTX, N) (RTL_CHECK2 (RTX, N, 's', 'S').rtstr)
@@ -399,41 +532,61 @@ extern void rtvec_check_failed_bounds PARAMS ((rtvec, int,
#define PREV_INSN(INSN) XEXP (INSN, 1)
#define NEXT_INSN(INSN) XEXP (INSN, 2)
+#define BLOCK_FOR_INSN(INSN) XBBDEF (INSN, 3)
+#define INSN_SCOPE(INSN) XTREE (INSN, 4)
/* The body of an insn. */
-#define PATTERN(INSN) XEXP (INSN, 3)
+#define PATTERN(INSN) XEXP (INSN, 5)
/* Code number of instruction, from when it was recognized.
-1 means this instruction has not been recognized yet. */
-#define INSN_CODE(INSN) XINT (INSN, 4)
+#define INSN_CODE(INSN) XINT (INSN, 6)
/* Set up in flow.c; empty before then.
Holds a chain of INSN_LIST rtx's whose first operands point at
previous insns with direct data-flow connections to this one.
That means that those insns set variables whose next use is in this insn.
They are always in the same basic block as this insn. */
-#define LOG_LINKS(INSN) XEXP(INSN, 5)
-
-/* 1 if insn has been deleted. */
-#define INSN_DELETED_P(INSN) ((INSN)->volatil)
-
-/* 1 if insn is a call to a const or pure function. */
-#define CONST_OR_PURE_CALL_P(INSN) ((INSN)->unchanging)
-
-/* 1 if insn (assumed to be a CALL_INSN) is a sibling call. */
-#define SIBLING_CALL_P(INSN) ((INSN)->jump)
-
-/* 1 if insn is a branch that should not unconditionally execute its
- delay slots, i.e., it is an annulled branch. */
-#define INSN_ANNULLED_BRANCH_P(INSN) ((INSN)->unchanging)
-
-/* 1 if insn is a dead code. Valid only for dead-code elimination phase. */
-#define INSN_DEAD_CODE_P(INSN) ((INSN)->in_struct)
-
-/* 1 if insn is in a delay slot and is from the target of the branch. If
- the branch insn has INSN_ANNULLED_BRANCH_P set, this insn should only be
+#define LOG_LINKS(INSN) XEXP(INSN, 7)
+
+#define RTX_INTEGRATED_P(RTX) \
+ (RTL_FLAG_CHECK8("RTX_INTEGRATED_P", (RTX), INSN, CALL_INSN, \
+ JUMP_INSN, INSN_LIST, BARRIER, CODE_LABEL, CONST, \
+ NOTE)->integrated)
+#define RTX_UNCHANGING_P(RTX) \
+ (RTL_FLAG_CHECK3("RTX_UNCHANGING_P", (RTX), REG, MEM, CONCAT)->unchanging)
+#define RTX_FRAME_RELATED_P(RTX) \
+ (RTL_FLAG_CHECK5("RTX_FRAME_RELATED_P", (RTX), INSN, CALL_INSN, \
+ JUMP_INSN, BARRIER, SET)->frame_related)
+
+/* 1 if RTX is an insn that has been deleted. */
+#define INSN_DELETED_P(RTX) \
+ (RTL_FLAG_CHECK6("INSN_DELETED_P", (RTX), INSN, CALL_INSN, JUMP_INSN, \
+ CODE_LABEL, BARRIER, NOTE)->volatil)
+
+/* 1 if RTX is a call to a const or pure function. */
+#define CONST_OR_PURE_CALL_P(RTX) \
+ (RTL_FLAG_CHECK3("CONST_OR_PURE_CALL_P", (RTX), CALL_INSN, NOTE, \
+ EXPR_LIST)->unchanging)
+
+/* 1 if RTX is a call_insn for a sibling call. */
+#define SIBLING_CALL_P(RTX) \
+ (RTL_FLAG_CHECK1("SIBLING_CALL_P", (RTX), CALL_INSN)->jump)
+
+/* 1 if RTX is a jump_insn, call_insn, or insn that is an annulling branch. */
+#define INSN_ANNULLED_BRANCH_P(RTX) \
+ (RTL_FLAG_CHECK3("INSN_ANNULLED_BRANCH_P", (RTX), JUMP_INSN, CALL_INSN, INSN)->unchanging)
+
+/* 1 if RTX is an insn that is dead code. Valid only for dead-code
+ elimination phase. */
+#define INSN_DEAD_CODE_P(RTX) \
+ (RTL_FLAG_CHECK1("INSN_DEAD_CODE_P", (RTX), INSN)->in_struct)
+
+/* 1 if RTX is an insn in a delay slot and is from the target of the branch.
+ If the branch insn has INSN_ANNULLED_BRANCH_P set, this insn should only be
executed if the branch is taken. For annulled branches with this bit
clear, the insn should be executed only if the branch is not taken. */
-#define INSN_FROM_TARGET_P(INSN) ((INSN)->in_struct)
+#define INSN_FROM_TARGET_P(RTX) \
+ (RTL_FLAG_CHECK3("INSN_FROM_TARGET_P", (RTX), INSN, JUMP_INSN, CALL_INSN)->in_struct)
#define ADDR_DIFF_VEC_FLAGS(RTX) X0ADVFLAGS(RTX, 4)
@@ -445,7 +598,7 @@ extern void rtvec_check_failed_bounds PARAMS ((rtvec, int,
The mode field of the EXPR_LIST contains not a real machine mode
but a value from enum reg_note. */
-#define REG_NOTES(INSN) XEXP(INSN, 6)
+#define REG_NOTES(INSN) XEXP(INSN, 8)
/* Don't forget to change reg_note_name in rtl.c. */
enum reg_note
@@ -531,11 +684,6 @@ enum reg_note
return. */
REG_BR_PROB,
- /* REG_EXEC_COUNT is attached to the first insn of each basic block, and
- the first insn after each CALL_INSN. It indicates how many times this
- block was executed. */
- REG_EXEC_COUNT,
-
/* Attached to a call insn; indicates that the call is malloc-like and
that the pointer returned cannot alias anything else. */
REG_NOALIAS,
@@ -614,12 +762,12 @@ extern const char * const reg_note_name[];
CLOBBER expressions document the registers explicitly clobbered
by this CALL_INSN.
Pseudo registers can not be mentioned in this list. */
-#define CALL_INSN_FUNCTION_USAGE(INSN) XEXP(INSN, 7)
+#define CALL_INSN_FUNCTION_USAGE(INSN) XEXP(INSN, 9)
/* The label-number of a code-label. The assembler label
is made from `L' and the label-number printed in decimal.
Label numbers are unique in a compilation. */
-#define CODE_LABEL_NUMBER(INSN) XINT (INSN, 5)
+#define CODE_LABEL_NUMBER(INSN) XINT (INSN, 6)
#define LINE_NUMBER NOTE
@@ -627,26 +775,30 @@ extern const char * const reg_note_name[];
line is in. We use the same field to record block numbers temporarily in
NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes. (We avoid lots of casts
between ints and pointers if we use a different macro for the block number.)
- The NOTE_INSN_RANGE_{START,END} and NOTE_INSN_LIVE notes record their
- information as an rtx in the field. */
+ */
-#define NOTE_SOURCE_FILE(INSN) XCSTR (INSN, 3, NOTE)
-#define NOTE_BLOCK(INSN) XCTREE (INSN, 3, NOTE)
-#define NOTE_EH_HANDLER(INSN) XCINT (INSN, 3, NOTE)
-#define NOTE_RANGE_INFO(INSN) XCEXP (INSN, 3, NOTE)
-#define NOTE_LIVE_INFO(INSN) XCEXP (INSN, 3, NOTE)
-#define NOTE_BASIC_BLOCK(INSN) XCBBDEF (INSN, 3, NOTE)
-#define NOTE_EXPECTED_VALUE(INSN) XCEXP (INSN, 3, NOTE)
+#define NOTE_SOURCE_FILE(INSN) XCSTR (INSN, 4, NOTE)
+#define NOTE_BLOCK(INSN) XCTREE (INSN, 4, NOTE)
+#define NOTE_EH_HANDLER(INSN) XCINT (INSN, 4, NOTE)
+#define NOTE_BASIC_BLOCK(INSN) XCBBDEF (INSN, 4, NOTE)
+#define NOTE_EXPECTED_VALUE(INSN) XCEXP (INSN, 4, NOTE)
+#define NOTE_PREDICTION(INSN) XCINT (INSN, 4, NOTE)
+#define NOTE_PRECONDITIONED(INSN) XCINT (INSN, 4, NOTE)
/* In a NOTE that is a line number, this is the line number.
Other kinds of NOTEs are identified by negative numbers here. */
-#define NOTE_LINE_NUMBER(INSN) XCINT (INSN, 4, NOTE)
+#define NOTE_LINE_NUMBER(INSN) XCINT (INSN, 5, NOTE)
/* Nonzero if INSN is a note marking the beginning of a basic block. */
#define NOTE_INSN_BASIC_BLOCK_P(INSN) \
(GET_CODE (INSN) == NOTE \
&& NOTE_LINE_NUMBER (INSN) == NOTE_INSN_BASIC_BLOCK)
+/* Algorithm and flags for prediction. */
+#define NOTE_PREDICTION_ALG(INSN) (XCINT(INSN, 4, NOTE)>>8)
+#define NOTE_PREDICTION_FLAGS(INSN) (XCINT(INSN, 4, NOTE)&0xff)
+#define NOTE_PREDICT(ALG,FLAGS) ((ALG<<8)+(FLAGS))
+
/* Codes that appear in the NOTE_LINE_NUMBER field
for kinds of notes that are not line numbers.
@@ -720,14 +872,6 @@ enum insn_note
the line containing the inline call from being counted twice in gcov. */
NOTE_INSN_REPEATED_LINE_NUMBER,
- /* Start/end of a live range region, where pseudos allocated on the stack
- can be allocated to temporary registers. Uses NOTE_RANGE_INFO. */
- NOTE_INSN_RANGE_BEG,
- NOTE_INSN_RANGE_END,
-
- /* Record which registers are currently live. Uses NOTE_LIVE_INFO. */
- NOTE_INSN_LIVE,
-
/* Record the struct for the following basic block. Uses NOTE_BASIC_BLOCK. */
NOTE_INSN_BASIC_BLOCK,
@@ -735,6 +879,9 @@ enum insn_note
NOTE_EXPECTED_VALUE; stored as (eq (reg) (const_int)). */
NOTE_INSN_EXPECTED_VALUE,
+ /* Record a prediction. Uses NOTE_PREDICTION. */
+ NOTE_INSN_PREDICTION,
+
NOTE_INSN_MAX
};
@@ -746,14 +893,61 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
/* The name of a label, in case it corresponds to an explicit label
in the input source code. */
-#define LABEL_NAME(RTX) XCSTR (RTX, 6, CODE_LABEL)
+#define LABEL_NAME(RTX) XCSTR (RTX, 7, CODE_LABEL)
/* In jump.c, each label contains a count of the number
of LABEL_REFs that point at it, so unused labels can be deleted. */
-#define LABEL_NUSES(RTX) XCINT (RTX, 3, CODE_LABEL)
+#define LABEL_NUSES(RTX) XCINT (RTX, 4, CODE_LABEL)
+
+/* Labels carry a two-bit field composed of the ->jump and ->call
+ bits. This field indicates whether the label is an alternate
+ entry point, and if so, what kind. */
+enum label_kind
+{
+ LABEL_NORMAL = 0, /* ordinary label */
+ LABEL_STATIC_ENTRY, /* alternate entry point, not exported */
+ LABEL_GLOBAL_ENTRY, /* alternate entry point, exported */
+ LABEL_WEAK_ENTRY /* alternate entry point, exported as weak symbol */
+};
+
+#if defined ENABLE_RTL_FLAG_CHECKING && (GCC_VERSION > 2007)
+
+/* Retrieve the kind of LABEL. */
+#define LABEL_KIND(LABEL) __extension__ \
+({ rtx const _label = (LABEL); \
+ if (GET_CODE (_label) != CODE_LABEL) \
+ rtl_check_failed_flag ("LABEL_KIND", _label, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ (enum label_kind) ((_label->jump << 1) | _label->call); })
+
+/* Set the kind of LABEL. */
+#define SET_LABEL_KIND(LABEL, KIND) do { \
+ rtx _label = (LABEL); \
+ unsigned int _kind = (KIND); \
+ if (GET_CODE (_label) != CODE_LABEL) \
+ rtl_check_failed_flag ("SET_LABEL_KIND", _label, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _label->jump = ((_kind >> 1) & 1); \
+ _label->call = (_kind & 1); \
+} while (0)
+
+#else
+
+/* Retrieve the kind of LABEL. */
+#define LABEL_KIND(LABEL) \
+ ((enum label_kind) (((LABEL)->jump << 1) | (LABEL)->call))
+
+/* Set the kind of LABEL. */
+#define SET_LABEL_KIND(LABEL, KIND) do { \
+ rtx _label = (LABEL); \
+ unsigned int _kind = (KIND); \
+ _label->jump = ((_kind >> 1) & 1); \
+ _label->call = (_kind & 1); \
+} while (0)
+
+#endif /* rtl flag checking */
-/* Associate a name with a CODE_LABEL. */
-#define LABEL_ALTERNATE_NAME(RTX) XCSTR (RTX, 7, CODE_LABEL)
+#define LABEL_ALT_ENTRY_P(LABEL) (LABEL_KIND (LABEL) != LABEL_NORMAL)
/* The original regno this ADDRESSOF was built for. */
#define ADDRESSOF_REGNO(RTX) XCUINT (RTX, 1, ADDRESSOF)
@@ -764,13 +958,13 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
/* In jump.c, each JUMP_INSN can point to a label that it can jump to,
so that if the JUMP_INSN is deleted, the label's LABEL_NUSES can
be decremented and possibly the label can be deleted. */
-#define JUMP_LABEL(INSN) XCEXP (INSN, 7, JUMP_INSN)
+#define JUMP_LABEL(INSN) XCEXP (INSN, 9, JUMP_INSN)
/* Once basic blocks are found in flow.c,
each CODE_LABEL starts a chain that goes through
all the LABEL_REFs that jump to that label.
The chain eventually winds up at the CODE_LABEL: it is circular. */
-#define LABEL_REFS(LABEL) XCEXP (LABEL, 4, CODE_LABEL)
+#define LABEL_REFS(LABEL) XCEXP (LABEL, 5, CODE_LABEL)
/* This is the field in the LABEL_REF through which the circular chain
of references to a particular label is linked.
@@ -790,16 +984,18 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
#define REGNO(RTX) XCUINT (RTX, 0, REG)
#define ORIGINAL_REGNO(RTX) X0UINT (RTX, 1)
-/* For a REG rtx, REG_FUNCTION_VALUE_P is nonzero if the reg
- is the current function's return value. */
+/* 1 if RTX is a reg or parallel that is the current function's return
+ value. */
+#define REG_FUNCTION_VALUE_P(RTX) \
+ (RTL_FLAG_CHECK2("REG_FUNCTION_VALUE_P", (RTX), REG, PARALLEL)->integrated)
-#define REG_FUNCTION_VALUE_P(RTX) ((RTX)->integrated)
+/* 1 if RTX is a reg that corresponds to a variable declared by the user. */
+#define REG_USERVAR_P(RTX) \
+ (RTL_FLAG_CHECK1("REG_USERVAR_P", (RTX), REG)->volatil)
-/* 1 in a REG rtx if it corresponds to a variable declared by the user. */
-#define REG_USERVAR_P(RTX) ((RTX)->volatil)
-
-/* 1 in a REG rtx if the register is a pointer. */
-#define REG_POINTER(RTX) ((RTX)->frame_related)
+/* 1 if RTX is a reg that holds a pointer value. */
+#define REG_POINTER(RTX) \
+ (RTL_FLAG_CHECK1("REG_POINTER", (RTX), REG)->frame_related)
/* 1 if the given register REG corresponds to a hard register. */
#define HARD_REGISTER_P(REG) (HARD_REGISTER_NUM_P (REGNO (REG)))
@@ -812,17 +1008,13 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
#define INTVAL(RTX) XCWINT(RTX, 0, CONST_INT)
/* For a CONST_DOUBLE:
- The usual two ints that hold the value.
- For a DImode, that is all there are;
- and CONST_DOUBLE_LOW is the low-order word and ..._HIGH the high-order.
- For a float, the number of ints varies,
- and CONST_DOUBLE_LOW is the one that should come first *in memory*.
- So use &CONST_DOUBLE_LOW(r) as the address of an array of ints. */
-#define CONST_DOUBLE_LOW(r) XCWINT (r, 1, CONST_DOUBLE)
-#define CONST_DOUBLE_HIGH(r) XCWINT (r, 2, CONST_DOUBLE)
-
-/* Link for chain of all CONST_DOUBLEs in use in current function. */
-#define CONST_DOUBLE_CHAIN(r) XCEXP (r, 0, CONST_DOUBLE)
+ For a DImode, there are two integers CONST_DOUBLE_LOW is the
+ low-order word and ..._HIGH the high-order.
+ For a float, there is a REAL_VALUE_TYPE structure, and
+ CONST_DOUBLE_REAL_VALUE(r) is a pointer to it. */
+#define CONST_DOUBLE_LOW(r) XCWINT (r, 0, CONST_DOUBLE)
+#define CONST_DOUBLE_HIGH(r) XCWINT (r, 1, CONST_DOUBLE)
+#define CONST_DOUBLE_REAL_VALUE(r) ((struct real_value *)&CONST_DOUBLE_LOW(r))
/* For a CONST_VECTOR, return element #n. */
#define CONST_VECTOR_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR)
@@ -842,18 +1034,36 @@ extern unsigned int subreg_regno_offset PARAMS ((unsigned int,
enum machine_mode,
unsigned int,
enum machine_mode));
+extern bool subreg_offset_representable_p PARAMS ((unsigned int,
+ enum machine_mode,
+ unsigned int,
+ enum machine_mode));
extern unsigned int subreg_regno PARAMS ((rtx));
-/* 1 if the REG contained in SUBREG_REG is already known to be
- sign- or zero-extended from the mode of the SUBREG to the mode of
+/* 1 if RTX is a subreg containing a reg that is already known to be
+ sign- or zero-extended from the mode of the subreg to the mode of
the reg. SUBREG_PROMOTED_UNSIGNED_P gives the signedness of the
extension.
When used as a LHS, is means that this extension must be done
when assigning to SUBREG_REG. */
-#define SUBREG_PROMOTED_VAR_P(RTX) ((RTX)->in_struct)
-#define SUBREG_PROMOTED_UNSIGNED_P(RTX) ((RTX)->unchanging)
+#define SUBREG_PROMOTED_VAR_P(RTX) \
+ (RTL_FLAG_CHECK1("SUBREG_PROMOTED", (RTX), SUBREG)->in_struct)
+
+#define SUBREG_PROMOTED_UNSIGNED_SET(RTX, VAL) \
+do { \
+ rtx const _rtx = RTL_FLAG_CHECK1("SUBREG_PROMOTED_UNSIGNED_SET", (RTX), SUBREG); \
+ if ((VAL) < 0) \
+ _rtx->volatil = 1; \
+ else { \
+ _rtx->volatil = 0; \
+ _rtx->unchanging = (VAL); \
+ } \
+} while (0)
+#define SUBREG_PROMOTED_UNSIGNED_P(RTX) \
+ ((RTL_FLAG_CHECK1("SUBREG_PROMOTED_UNSIGNED_P", (RTX), SUBREG)->volatil) \
+ ? -1 : (RTX)->unchanging)
/* Access various components of an ASM_OPERANDS rtx. */
@@ -873,25 +1083,33 @@ extern unsigned int subreg_regno PARAMS ((rtx));
#define ASM_OPERANDS_SOURCE_FILE(RTX) XCSTR (RTX, 5, ASM_OPERANDS)
#define ASM_OPERANDS_SOURCE_LINE(RTX) XCINT (RTX, 6, ASM_OPERANDS)
-/* For a MEM RTX, 1 if we should keep the alias set for this mem
+/* 1 if RTX is a mem and we should keep the alias set for this mem
unchanged when we access a component. Set to 1, or example, when we
are already in a non-addressable component of an aggregate. */
-#define MEM_KEEP_ALIAS_SET_P(RTX) ((RTX)->jump)
+#define MEM_KEEP_ALIAS_SET_P(RTX) \
+ (RTL_FLAG_CHECK1("MEM_KEEP_ALIAS_SET_P", (RTX), MEM)->jump)
-/* For a MEM rtx, 1 if it's a volatile reference.
- Also in an ASM_OPERANDS rtx. */
-#define MEM_VOLATILE_P(RTX) ((RTX)->volatil)
+/* 1 if RTX is a mem or asm_operand for a volatile reference. */
+#define MEM_VOLATILE_P(RTX) \
+ (RTL_FLAG_CHECK3("MEM_VOLATILE_P", (RTX), MEM, ASM_OPERANDS, \
+ ASM_INPUT)->volatil)
-/* For a MEM rtx, 1 if it refers to an aggregate, either to the
+/* 1 if RTX is a mem that refers to an aggregate, either to the
aggregate itself of to a field of the aggregate. If zero, RTX may
or may not be such a reference. */
-#define MEM_IN_STRUCT_P(RTX) ((RTX)->in_struct)
+#define MEM_IN_STRUCT_P(RTX) \
+ (RTL_FLAG_CHECK1("MEM_IN_STRUCT_P", (RTX), MEM)->in_struct)
-/* For a MEM rtx, 1 if it refers to a scalar. If zero, RTX may or may
+/* 1 if RTX is a mem that refers to a scalar. If zero, RTX may or may
not refer to a scalar. */
-#define MEM_SCALAR_P(RTX) ((RTX)->frame_related)
+#define MEM_SCALAR_P(RTX) \
+ (RTL_FLAG_CHECK1("MEM_SCALAR_P", (RTX), MEM)->frame_related)
-/* If VAL is non-zero, set MEM_IN_STRUCT_P and clear MEM_SCALAR_P in
+/* 1 if RTX is a mem that cannot trap. */
+#define MEM_NOTRAP_P(RTX) \
+ (RTL_FLAG_CHECK1("MEM_NOTRAP_P", (RTX), MEM)->call)
+
+/* If VAL is nonzero, set MEM_IN_STRUCT_P and clear MEM_SCALAR_P in
RTX. Otherwise, vice versa. Use this macro only when you are
*sure* that you know that the MEM is in a structure, or is a
scalar. VAL is evaluated only once. */
@@ -951,43 +1169,42 @@ do { \
(MEM_VOLATILE_P (LHS) = MEM_VOLATILE_P (RHS), \
MEM_IN_STRUCT_P (LHS) = MEM_IN_STRUCT_P (RHS), \
MEM_SCALAR_P (LHS) = MEM_SCALAR_P (RHS), \
+ MEM_NOTRAP_P (LHS) = MEM_NOTRAP_P (RHS), \
RTX_UNCHANGING_P (LHS) = RTX_UNCHANGING_P (RHS), \
MEM_KEEP_ALIAS_SET_P (LHS) = MEM_KEEP_ALIAS_SET_P (RHS), \
MEM_ATTRS (LHS) = MEM_ATTRS (RHS))
-/* For a LABEL_REF, 1 means that this reference is to a label outside the
- loop containing the reference. */
-#define LABEL_OUTSIDE_LOOP_P(RTX) ((RTX)->in_struct)
+/* 1 if RTX is a label_ref to a label outside the loop containing the
+ reference. */
+#define LABEL_OUTSIDE_LOOP_P(RTX) \
+ (RTL_FLAG_CHECK1("LABEL_OUTSIDE_LOOP_P", (RTX), LABEL_REF)->in_struct)
-/* For a LABEL_REF, 1 means it is for a nonlocal label. */
-/* Likewise in an EXPR_LIST for a REG_LABEL note. */
-#define LABEL_REF_NONLOCAL_P(RTX) ((RTX)->volatil)
+/* 1 if RTX is a label_ref for a nonlocal label. */
+/* Likewise in an expr_list for a reg_label note. */
+#define LABEL_REF_NONLOCAL_P(RTX) \
+ (RTL_FLAG_CHECK2("LABEL_REF_NONLOCAL_P", (RTX), LABEL_REF, \
+ REG_LABEL)->volatil)
-/* For a CODE_LABEL, 1 means always consider this label to be needed. */
-#define LABEL_PRESERVE_P(RTX) ((RTX)->in_struct)
+/* 1 if RTX is a code_label that should always be considered to be needed. */
+#define LABEL_PRESERVE_P(RTX) \
+ (RTL_FLAG_CHECK2("LABEL_PRESERVE_P", (RTX), CODE_LABEL, NOTE)->in_struct)
-/* For a REG, 1 means the register is used only in an exit test of a loop. */
-#define REG_LOOP_TEST_P(RTX) ((RTX)->in_struct)
+/* 1 if RTX is a reg that is used only in an exit test of a loop. */
+#define REG_LOOP_TEST_P(RTX) \
+ (RTL_FLAG_CHECK1("REG_LOOP_TEST_P", (RTX), REG)->in_struct)
-/* During sched, for an insn, 1 means that the insn must be scheduled together
+/* During sched, 1 if RTX is an insn that must be scheduled together
with the preceding insn. */
-#define SCHED_GROUP_P(INSN) ((INSN)->in_struct)
-
-/* During sched, for the LOG_LINKS of an insn, these cache the adjusted
- cost of the dependence link. The cost of executing an instruction
- may vary based on how the results are used. LINK_COST_ZERO is 1 when
- the cost through the link varies and is unchanged (i.e., the link has
- zero additional cost). LINK_COST_FREE is 1 when the cost through the
- link is zero (i.e., the link makes the cost free). In other cases,
- the adjustment to the cost is recomputed each time it is needed. */
-#define LINK_COST_ZERO(X) ((X)->jump)
-#define LINK_COST_FREE(X) ((X)->call)
+#define SCHED_GROUP_P(RTX) \
+ (RTL_FLAG_CHECK3("SCHED_GROUP_P", (RTX), INSN, JUMP_INSN, CALL_INSN \
+ )->in_struct)
/* For a SET rtx, SET_DEST is the place that is set
and SET_SRC is the value it is set to. */
#define SET_DEST(RTX) XC2EXP(RTX, 0, SET, CLOBBER)
#define SET_SRC(RTX) XCEXP(RTX, 1, SET)
-#define SET_IS_RETURN_P(RTX) ((RTX)->jump)
+#define SET_IS_RETURN_P(RTX) \
+ (RTL_FLAG_CHECK1("SET_IS_RETURN_P", (RTX), SET)->jump)
/* For a TRAP_IF rtx, TRAP_CONDITION is an expression. */
#define TRAP_CONDITION(RTX) XCEXP (RTX, 0, TRAP_IF)
@@ -999,25 +1216,31 @@ do { \
#define COND_EXEC_TEST(RTX) XCEXP (RTX, 0, COND_EXEC)
#define COND_EXEC_CODE(RTX) XCEXP (RTX, 1, COND_EXEC)
-/* 1 in a SYMBOL_REF if it addresses this function's constants pool. */
-#define CONSTANT_POOL_ADDRESS_P(RTX) ((RTX)->unchanging)
+/* 1 if RTX is a symbol_ref that addresses this function's constants pool. */
+#define CONSTANT_POOL_ADDRESS_P(RTX) \
+ (RTL_FLAG_CHECK1("CONSTANT_POOL_ADDRESS_P", (RTX), SYMBOL_REF)->unchanging)
-/* 1 in a SYMBOL_REF if it addresses this function's string constant pool. */
-#define STRING_POOL_ADDRESS_P(RTX) ((RTX)->frame_related)
+/* 1 if RTX is a symbol_ref that addresses this function's string constant
+ pool */
+#define STRING_POOL_ADDRESS_P(RTX) \
+ (RTL_FLAG_CHECK1("STRING_POOL_ADDRESS_P", (RTX), SYMBOL_REF)->frame_related)
-/* Flag in a SYMBOL_REF for machine-specific purposes. */
-#define SYMBOL_REF_FLAG(RTX) ((RTX)->volatil)
+/* Used if RTX is a symbol_ref, for machine-specific purposes. */
+#define SYMBOL_REF_FLAG(RTX) \
+ (RTL_FLAG_CHECK1("SYMBOL_REF_FLAG", (RTX), SYMBOL_REF)->volatil)
-/* 1 means a SYMBOL_REF has been the library function in emit_library_call. */
-#define SYMBOL_REF_USED(RTX) ((RTX)->used)
+/* 1 if RTX is a symbol_ref that has been the library function in
+ emit_library_call. */
+#define SYMBOL_REF_USED(RTX) \
+ (RTL_FLAG_CHECK1("SYMBOL_REF_USED", (RTX), SYMBOL_REF)->used)
-/* 1 means a SYMBOL_REF is weak. */
-#define SYMBOL_REF_WEAK(RTX) ((RTX)->integrated)
+/* 1 if RTX is a symbol_ref for a weak symbol. */
+#define SYMBOL_REF_WEAK(RTX) \
+ (RTL_FLAG_CHECK1("SYMBOL_REF_WEAK", (RTX), SYMBOL_REF)->integrated)
/* Define a macro to look for REG_INC notes,
but save time on machines where they never exist. */
-/* Don't continue this line--convex cc version 4.1 would lose. */
#if (defined (HAVE_PRE_INCREMENT) || defined (HAVE_PRE_DECREMENT) || defined (HAVE_POST_INCREMENT) || defined (HAVE_POST_DECREMENT))
#define FIND_REG_INC_NOTE(INSN, REG) \
((REG) != NULL_RTX && REG_P ((REG)) \
@@ -1030,7 +1253,6 @@ do { \
/* Indicate whether the machine has any sort of auto increment addressing.
If not, we can avoid checking for REG_INC notes. */
-/* Don't continue this line--convex cc version 4.1 would lose. */
#if (defined (HAVE_PRE_INCREMENT) || defined (HAVE_PRE_DECREMENT) || defined (HAVE_POST_INCREMENT) || defined (HAVE_POST_DECREMENT))
#define AUTO_INC_DEC
#endif
@@ -1104,100 +1326,6 @@ do { \
#define USE_STORE_PRE_DECREMENT(MODE) HAVE_PRE_DECREMENT
#endif
-
-/* Accessors for RANGE_INFO. */
-/* For RANGE_{START,END} notes return the RANGE_START note. */
-#define RANGE_INFO_NOTE_START(INSN) XCEXP (INSN, 0, RANGE_INFO)
-
-/* For RANGE_{START,END} notes return the RANGE_START note. */
-#define RANGE_INFO_NOTE_END(INSN) XCEXP (INSN, 1, RANGE_INFO)
-
-/* For RANGE_{START,END} notes, return the vector containing the registers used
- in the range. */
-#define RANGE_INFO_REGS(INSN) XCVEC (INSN, 2, RANGE_INFO)
-#define RANGE_INFO_REGS_REG(INSN, N) XCVECEXP (INSN, 2, N, RANGE_INFO)
-#define RANGE_INFO_NUM_REGS(INSN) XCVECLEN (INSN, 2, RANGE_INFO)
-
-/* For RANGE_{START,END} notes, the number of calls within the range. */
-#define RANGE_INFO_NCALLS(INSN) XCINT (INSN, 3, RANGE_INFO)
-
-/* For RANGE_{START,END} notes, the number of insns within the range. */
-#define RANGE_INFO_NINSNS(INSN) XCINT (INSN, 4, RANGE_INFO)
-
-/* For RANGE_{START,END} notes, a unique # to identify this range. */
-#define RANGE_INFO_UNIQUE(INSN) XCINT (INSN, 5, RANGE_INFO)
-
-/* For RANGE_{START,END} notes, the basic block # the range starts with. */
-#define RANGE_INFO_BB_START(INSN) XCINT (INSN, 6, RANGE_INFO)
-
-/* For RANGE_{START,END} notes, the basic block # the range ends with. */
-#define RANGE_INFO_BB_END(INSN) XCINT (INSN, 7, RANGE_INFO)
-
-/* For RANGE_{START,END} notes, the loop depth the range is in. */
-#define RANGE_INFO_LOOP_DEPTH(INSN) XCINT (INSN, 8, RANGE_INFO)
-
-/* For RANGE_{START,END} notes, the bitmap of live registers at the start
- of the range. */
-#define RANGE_INFO_LIVE_START(INSN) XCBITMAP (INSN, 9, RANGE_INFO)
-
-/* For RANGE_{START,END} notes, the bitmap of live registers at the end
- of the range. */
-#define RANGE_INFO_LIVE_END(INSN) XCBITMAP (INSN, 10, RANGE_INFO)
-
-/* For RANGE_START notes, the marker # of the start of the range. */
-#define RANGE_INFO_MARKER_START(INSN) XCINT (INSN, 11, RANGE_INFO)
-
-/* For RANGE_START notes, the marker # of the end of the range. */
-#define RANGE_INFO_MARKER_END(INSN) XCINT (INSN, 12, RANGE_INFO)
-
-/* Original pseudo register # for a live range note. */
-#define RANGE_REG_PSEUDO(INSN,N) XCINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 0, REG)
-
-/* Pseudo register # original register is copied into or -1. */
-#define RANGE_REG_COPY(INSN,N) XCINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 1, REG)
-
-/* How many times a register in a live range note was referenced. */
-#define RANGE_REG_REFS(INSN,N) XINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 2)
-
-/* How many times a register in a live range note was set. */
-#define RANGE_REG_SETS(INSN,N) XINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 3)
-
-/* How many times a register in a live range note died. */
-#define RANGE_REG_DEATHS(INSN,N) XINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 4)
-
-/* Whether the original value is needed to be copied into the range register at
- the start of the range. */
-#define RANGE_REG_COPY_FLAGS(INSN,N) XINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 5)
-
-/* # of insns the register copy is live over. */
-#define RANGE_REG_LIVE_LENGTH(INSN,N) XINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 6)
-
-/* # of calls the register copy is live over. */
-#define RANGE_REG_N_CALLS(INSN,N) XINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 7)
-
-/* DECL_NODE pointer of the declaration if the register is a user defined
- variable. */
-#define RANGE_REG_SYMBOL_NODE(INSN,N) XTREE (XCVECEXP (INSN, 2, N, RANGE_INFO), 8)
-
-/* BLOCK_NODE pointer to the block the variable is declared in if the
- register is a user defined variable. */
-#define RANGE_REG_BLOCK_NODE(INSN,N) XTREE (XCVECEXP (INSN, 2, N, RANGE_INFO), 9)
-
-/* EXPR_LIST of the distinct ranges a variable is in. */
-#define RANGE_VAR_LIST(INSN) (XEXP (INSN, 0))
-
-/* Block a variable is declared in. */
-#define RANGE_VAR_BLOCK(INSN) (XTREE (INSN, 1))
-
-/* # of distinct ranges a variable is in. */
-#define RANGE_VAR_NUM(INSN) (XINT (INSN, 2))
-
-/* For a NOTE_INSN_LIVE note, the registers which are currently live. */
-#define RANGE_LIVE_BITMAP(INSN) (XBITMAP (INSN, 0))
-
-/* For a NOTE_INSN_LIVE note, the original basic block number. */
-#define RANGE_LIVE_ORIG_BLOCK(INSN) (XINT (INSN, 1))
-
/* Determine if the insn is a PHI node. */
#define PHI_NODE_P(X) \
((X) && GET_CODE (X) == INSN \
@@ -1239,6 +1367,7 @@ extern rtx copy_insn_1 PARAMS ((rtx));
extern rtx copy_insn PARAMS ((rtx));
extern rtx gen_int_mode PARAMS ((HOST_WIDE_INT,
enum machine_mode));
+extern rtx emit_copy_of_insn_after PARAMS ((rtx, rtx));
/* In rtl.c */
extern rtx rtx_alloc PARAMS ((RTX_CODE));
@@ -1289,12 +1418,13 @@ extern rtx get_insns PARAMS ((void));
extern const char *get_insn_name PARAMS ((int));
extern rtx get_last_insn PARAMS ((void));
extern rtx get_last_insn_anywhere PARAMS ((void));
+extern rtx get_first_nonnote_insn PARAMS ((void));
+extern rtx get_last_nonnote_insn PARAMS ((void));
extern void start_sequence PARAMS ((void));
extern void push_to_sequence PARAMS ((rtx));
extern void end_sequence PARAMS ((void));
extern void push_to_full_sequence PARAMS ((rtx, rtx));
extern void end_full_sequence PARAMS ((rtx*, rtx*));
-extern rtx gen_sequence PARAMS ((void));
/* In varasm.c */
extern rtx immed_double_const PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT, enum machine_mode));
@@ -1320,21 +1450,25 @@ extern rtx assign_stack_temp_for_type PARAMS ((enum machine_mode,
extern rtx assign_temp PARAMS ((tree, int, int, int));
/* In emit-rtl.c */
extern rtx emit_insn_before PARAMS ((rtx, rtx));
+extern rtx emit_insn_before_scope PARAMS ((rtx, rtx, tree));
extern rtx emit_jump_insn_before PARAMS ((rtx, rtx));
+extern rtx emit_jump_insn_before_scope PARAMS ((rtx, rtx, tree));
extern rtx emit_call_insn_before PARAMS ((rtx, rtx));
+extern rtx emit_call_insn_before_scope PARAMS ((rtx, rtx, tree));
extern rtx emit_barrier_before PARAMS ((rtx));
extern rtx emit_label_before PARAMS ((rtx, rtx));
extern rtx emit_note_before PARAMS ((int, rtx));
extern rtx emit_insn_after PARAMS ((rtx, rtx));
+extern rtx emit_insn_after_scope PARAMS ((rtx, rtx, tree));
extern rtx emit_jump_insn_after PARAMS ((rtx, rtx));
+extern rtx emit_jump_insn_after_scope PARAMS ((rtx, rtx, tree));
+extern rtx emit_call_insn_after PARAMS ((rtx, rtx));
+extern rtx emit_call_insn_after_scope PARAMS ((rtx, rtx, tree));
extern rtx emit_barrier_after PARAMS ((rtx));
extern rtx emit_label_after PARAMS ((rtx, rtx));
extern rtx emit_note_after PARAMS ((int, rtx));
extern rtx emit_line_note_after PARAMS ((const char *, int, rtx));
extern rtx emit_insn PARAMS ((rtx));
-extern rtx emit_insns PARAMS ((rtx));
-extern rtx emit_insns_before PARAMS ((rtx, rtx));
-extern rtx emit_insns_after PARAMS ((rtx, rtx));
extern rtx emit_jump_insn PARAMS ((rtx));
extern rtx emit_call_insn PARAMS ((rtx));
extern rtx emit_label PARAMS ((rtx));
@@ -1357,6 +1491,9 @@ extern rtx next_label PARAMS ((rtx));
extern rtx next_cc0_user PARAMS ((rtx));
extern rtx prev_cc0_setter PARAMS ((rtx));
+/* In cfglayout.c */
+extern tree choose_inner_scope PARAMS ((tree, tree));
+
/* In jump.c */
extern rtx next_nondeleted_insn PARAMS ((rtx));
extern enum rtx_code reverse_condition PARAMS ((enum rtx_code));
@@ -1427,7 +1564,7 @@ extern rtx simplify_rtx PARAMS ((rtx));
extern rtx avoid_constant_pool_reference PARAMS ((rtx));
/* In function.c */
-extern rtx gen_mem_addressof PARAMS ((rtx, tree));
+extern rtx gen_mem_addressof PARAMS ((rtx, tree, int));
/* In regclass.c */
extern enum machine_mode choose_hard_reg_mode PARAMS ((unsigned int,
@@ -1452,6 +1589,7 @@ extern int rtx_addr_varies_p PARAMS ((rtx, int));
extern HOST_WIDE_INT get_integer_term PARAMS ((rtx));
extern rtx get_related_value PARAMS ((rtx));
extern rtx get_jump_table_offset PARAMS ((rtx, rtx *));
+extern int global_reg_mentioned_p PARAMS ((rtx));
extern int reg_mentioned_p PARAMS ((rtx, rtx));
extern int count_occurrences PARAMS ((rtx, rtx, int));
extern int reg_referenced_p PARAMS ((rtx, rtx));
@@ -1512,11 +1650,14 @@ extern void remove_node_from_expr_list PARAMS ((rtx, rtx *));
extern int insns_safe_to_move_p PARAMS ((rtx, rtx, rtx *));
extern int loc_mentioned_in_p PARAMS ((rtx *, rtx));
extern rtx find_first_parameter_load PARAMS ((rtx, rtx));
+extern bool keep_with_call_p PARAMS ((rtx));
/* flow.c */
extern rtx find_use_as_address PARAMS ((rtx, rtx, HOST_WIDE_INT));
-void init_EXPR_INSN_LIST_cache PARAMS ((void));
+
+/* lists.c */
+
void free_EXPR_LIST_list PARAMS ((rtx *));
void free_INSN_LIST_list PARAMS ((rtx *));
void free_EXPR_LIST_node PARAMS ((rtx));
@@ -1550,15 +1691,15 @@ extern void split_all_insns PARAMS ((int));
extern void split_all_insns_noflow PARAMS ((void));
#define MAX_SAVED_CONST_INT 64
-extern rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
+extern GTY(()) rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
#define const0_rtx (const_int_rtx[MAX_SAVED_CONST_INT])
#define const1_rtx (const_int_rtx[MAX_SAVED_CONST_INT+1])
#define const2_rtx (const_int_rtx[MAX_SAVED_CONST_INT+2])
#define constm1_rtx (const_int_rtx[MAX_SAVED_CONST_INT-1])
-extern rtx const_true_rtx;
+extern GTY(()) rtx const_true_rtx;
-extern rtx const_tiny_rtx[3][(int) MAX_MACHINE_MODE];
+extern GTY(()) rtx const_tiny_rtx[3][(int) MAX_MACHINE_MODE];
/* Returns a constant 0 rtx in mode MODE. Integer modes are treated the
same as VOIDmode. */
@@ -1615,7 +1756,7 @@ enum global_rtl_index
};
/* Pointers to standard pieces of rtx are stored here. */
-extern rtx global_rtl[GR_MAX];
+extern GTY(()) rtx global_rtl[GR_MAX];
/* Standard pieces of rtx, to be substituted directly into things. */
#define pc_rtx (global_rtl[GR_PC])
@@ -1629,12 +1770,12 @@ extern rtx global_rtl[GR_MAX];
#define hard_frame_pointer_rtx (global_rtl[GR_HARD_FRAME_POINTER])
#define arg_pointer_rtx (global_rtl[GR_ARG_POINTER])
-extern rtx pic_offset_table_rtx;
-extern rtx struct_value_rtx;
-extern rtx struct_value_incoming_rtx;
-extern rtx static_chain_rtx;
-extern rtx static_chain_incoming_rtx;
-extern rtx return_address_pointer_rtx;
+extern GTY(()) rtx pic_offset_table_rtx;
+extern GTY(()) rtx struct_value_rtx;
+extern GTY(()) rtx struct_value_incoming_rtx;
+extern GTY(()) rtx static_chain_rtx;
+extern GTY(()) rtx static_chain_incoming_rtx;
+extern GTY(()) rtx return_address_pointer_rtx;
/* Include the RTL generation functions. */
@@ -1647,11 +1788,10 @@ extern rtx return_address_pointer_rtx;
add to this list, modify special_rtx in gengenrtl.c as well. You
should also modify gen_rtx to use the special function. */
-extern rtx gen_rtx_CONST_DOUBLE PARAMS ((enum machine_mode,
- HOST_WIDE_INT, HOST_WIDE_INT));
extern rtx gen_rtx_CONST_INT PARAMS ((enum machine_mode, HOST_WIDE_INT));
+extern rtx gen_rtx_CONST_VECTOR PARAMS ((enum machine_mode, rtvec));
extern rtx gen_raw_REG PARAMS ((enum machine_mode, int));
-extern rtx gen_rtx_REG PARAMS ((enum machine_mode, int));
+extern rtx gen_rtx_REG PARAMS ((enum machine_mode, unsigned));
extern rtx gen_rtx_SUBREG PARAMS ((enum machine_mode, rtx, int));
extern rtx gen_rtx_MEM PARAMS ((enum machine_mode, rtx));
@@ -1728,7 +1868,6 @@ extern rtx gen_lowpart_SUBREG PARAMS ((enum machine_mode, rtx));
extern rtx find_next_ref PARAMS ((rtx, rtx));
extern rtx output_constant_def PARAMS ((tree, int));
-extern rtx immed_real_const PARAMS ((tree));
/* Define a default value for STORE_FLAG_VALUE. */
@@ -1786,7 +1925,7 @@ struct cse_basic_block_data;
extern int rtx_cost PARAMS ((rtx, enum rtx_code));
extern int address_cost PARAMS ((rtx, enum machine_mode));
-extern void delete_trivially_dead_insns PARAMS ((rtx, int, int));
+extern int delete_trivially_dead_insns PARAMS ((rtx, int));
#ifdef BUFSIZ
extern int cse_main PARAMS ((rtx, int, int, FILE *));
#endif
@@ -1803,8 +1942,8 @@ extern int safe_to_remove_jump_p PARAMS ((rtx));
extern rtx pc_set PARAMS ((rtx));
extern rtx condjump_label PARAMS ((rtx));
extern int simplejump_p PARAMS ((rtx));
-extern int returnjump_p PARAMS ((rtx));
extern int tablejump_p PARAMS ((rtx));
+extern int returnjump_p PARAMS ((rtx));
extern int onlyjump_p PARAMS ((rtx));
extern int only_sets_cc0_p PARAMS ((rtx));
extern int sets_cc0_p PARAMS ((rtx));
@@ -1838,7 +1977,6 @@ extern void reorder_insns_nobb PARAMS ((rtx, rtx, rtx));
extern int get_max_uid PARAMS ((void));
extern int in_sequence_p PARAMS ((void));
extern void force_next_line_note PARAMS ((void));
-extern void clear_emit_caches PARAMS ((void));
extern void init_emit PARAMS ((void));
extern void init_emit_once PARAMS ((int));
extern void push_topmost_sequence PARAMS ((void));
@@ -1849,6 +1987,7 @@ extern void set_new_first_and_last_insn PARAMS ((rtx, rtx));
extern void set_new_first_and_last_label_num PARAMS ((int, int));
extern void set_new_last_label_num PARAMS ((int));
extern void unshare_all_rtl_again PARAMS ((rtx));
+extern void set_first_insn PARAMS ((rtx));
extern void set_last_insn PARAMS ((rtx));
extern void link_cc0_insns PARAMS ((rtx));
extern void add_insn PARAMS ((rtx));
@@ -1868,6 +2007,8 @@ extern void renumber_insns PARAMS ((FILE *));
extern void remove_unnecessary_notes PARAMS ((void));
extern rtx delete_insn PARAMS ((rtx));
extern void delete_insn_chain PARAMS ((rtx, rtx));
+extern rtx delete_insn_and_edges PARAMS ((rtx));
+extern void delete_insn_chain_and_edges PARAMS ((rtx, rtx));
/* In combine.c */
extern int combine_instructions PARAMS ((rtx, unsigned int));
@@ -1932,6 +2073,7 @@ extern void move_by_pieces PARAMS ((rtx, rtx,
/* In flow.c */
extern void recompute_reg_usage PARAMS ((rtx, int));
extern int initialize_uninitialized_subregs PARAMS ((void));
+extern void delete_dead_jumptables PARAMS ((void));
#ifdef BUFSIZ
extern void print_rtl_with_bb PARAMS ((FILE *, rtx));
extern void dump_flow_info PARAMS ((FILE *));
@@ -1957,6 +2099,7 @@ extern int global_alloc PARAMS ((FILE *));
extern void dump_global_regs PARAMS ((FILE *));
#endif
#ifdef HARD_CONST
+/* Yes, this ifdef is silly, but HARD_REG_SET is not always defined. */
extern void retry_global_alloc PARAMS ((int, HARD_REG_SET));
#endif
extern void build_insn_chain PARAMS ((rtx));
@@ -1966,6 +2109,7 @@ extern int reg_classes_intersect_p PARAMS ((enum reg_class, enum reg_class));
extern int reg_class_subset_p PARAMS ((enum reg_class, enum reg_class));
extern void globalize_reg PARAMS ((int));
extern void init_regs PARAMS ((void));
+extern void init_fake_stack_mems PARAMS ((void));
extern void init_reg_sets PARAMS ((void));
extern void regset_release_memory PARAMS ((void));
extern void regclass_init PARAMS ((void));
@@ -1973,8 +2117,16 @@ extern void regclass PARAMS ((rtx, int, FILE *));
extern void reg_scan PARAMS ((rtx, unsigned int, int));
extern void reg_scan_update PARAMS ((rtx, rtx, unsigned int));
extern void fix_register PARAMS ((const char *, int, int));
+#ifdef HARD_CONST
+extern void cannot_change_mode_set_regs PARAMS ((HARD_REG_SET *,
+ enum machine_mode,
+ unsigned int));
+#endif
+extern bool invalid_mode_change_p PARAMS ((unsigned int,
+ enum reg_class,
+ enum machine_mode));
-extern void delete_null_pointer_checks PARAMS ((rtx));
+extern int delete_null_pointer_checks PARAMS ((rtx));
/* In regmove.c */
#ifdef BUFSIZ
@@ -2119,7 +2271,7 @@ extern int stack_regs_mentioned PARAMS ((rtx insn));
#endif
/* In toplev.c */
-extern rtx stack_limit_rtx;
+extern GTY(()) rtx stack_limit_rtx;
/* In regrename.c */
extern void regrename_optimize PARAMS ((void));
@@ -2131,4 +2283,7 @@ extern void if_convert PARAMS ((int));
/* In predict.c */
extern void invert_br_probabilities PARAMS ((rtx));
extern bool expensive_function_p PARAMS ((int));
+/* In tracer.c */
+extern void tracer PARAMS ((void));
+
#endif /* ! GCC_RTL_H */
diff --git a/contrib/gcc/rtlanal.c b/contrib/gcc/rtlanal.c
index 2380599..57b210e 100644
--- a/contrib/gcc/rtlanal.c
+++ b/contrib/gcc/rtlanal.c
@@ -25,13 +25,21 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "toplev.h"
#include "rtl.h"
#include "hard-reg-set.h"
+#include "insn-config.h"
+#include "recog.h"
#include "tm_p.h"
+#include "flags.h"
+#include "basic-block.h"
+#include "real.h"
/* Forward declarations */
+static int global_reg_mentioned_p_1 PARAMS ((rtx *, void *));
static void set_of_1 PARAMS ((rtx, rtx, void *));
static void insn_dependent_p_1 PARAMS ((rtx, rtx, void *));
static int computed_jump_p_1 PARAMS ((rtx));
static void parms_set PARAMS ((rtx, rtx, void *));
+static bool hoist_test_store PARAMS ((rtx, rtx, regset));
+static void hoist_update_store PARAMS ((rtx, rtx *, rtx, rtx));
/* Bit flags that specify the machine subtype we are compiling for.
Bits are tested using macros TARGET_... defined in the tm.h file
@@ -172,7 +180,7 @@ rtx_varies_p (x, for_alias)
during alias analysis. */
return (! for_alias && rtx_varies_p (XEXP (x, 0), for_alias))
|| rtx_varies_p (XEXP (x, 1), for_alias);
-
+
case ASM_OPERANDS:
if (MEM_VOLATILE_P (x))
return 1;
@@ -261,9 +269,9 @@ rtx_addr_can_trap_p (x)
return 1;
}
-/* Return 1 if X refers to a memory location whose address
+/* Return 1 if X refers to a memory location whose address
cannot be compared reliably with constant addresses,
- or if X refers to a BLKmode memory object.
+ or if X refers to a BLKmode memory object.
FOR_ALIAS is nonzero if we are called from alias analysis; if it is
zero, we are slightly more conservative. */
@@ -345,7 +353,7 @@ get_related_value (x)
into the jump table. If the offset cannot be determined, then return
NULL_RTX.
- If EARLIEST is non-zero, it is a pointer to a place where the earliest
+ If EARLIEST is nonzero, it is a pointer to a place where the earliest
insn used in locating the offset was found. */
rtx
@@ -481,6 +489,82 @@ get_jump_table_offset (insn, earliest)
return x;
}
+/* A subroutine of global_reg_mentioned_p, returns 1 if *LOC mentions
+ a global register. */
+
+static int
+global_reg_mentioned_p_1 (loc, data)
+ rtx *loc;
+ void *data ATTRIBUTE_UNUSED;
+{
+ int regno;
+ rtx x = *loc;
+
+ if (! x)
+ return 0;
+
+ switch (GET_CODE (x))
+ {
+ case SUBREG:
+ if (GET_CODE (SUBREG_REG (x)) == REG)
+ {
+ if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
+ && global_regs[subreg_regno (x)])
+ return 1;
+ return 0;
+ }
+ break;
+
+ case REG:
+ regno = REGNO (x);
+ if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
+ return 1;
+ return 0;
+
+ case SCRATCH:
+ case PC:
+ case CC0:
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case CONST:
+ case LABEL_REF:
+ return 0;
+
+ case CALL:
+ /* A non-constant call might use a global register. */
+ return 1;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* Returns nonzero if X mentions a global register. */
+
+int
+global_reg_mentioned_p (x)
+ rtx x;
+{
+
+ if (INSN_P (x))
+ {
+ if (GET_CODE (x) == CALL_INSN)
+ {
+ if (! CONST_OR_PURE_CALL_P (x))
+ return 1;
+ x = CALL_INSN_FUNCTION_USAGE (x);
+ if (x == 0)
+ return 0;
+ }
+ else
+ x = PATTERN (x);
+ }
+
+ return for_each_rtx (&x, global_reg_mentioned_p_1, NULL);
+}
+
/* Return the number of places FIND appears within X. If COUNT_DEST is
zero, we do not count occurrences inside the destination of a SET. */
@@ -588,7 +672,7 @@ reg_mentioned_p (reg, in)
case CONST_DOUBLE:
/* These are kept unique for a given value. */
return 0;
-
+
default:
break;
}
@@ -728,7 +812,7 @@ reg_referenced_p (x, body)
if (reg_referenced_p (x, XVECEXP (body, 0, i)))
return 1;
return 0;
-
+
case CLOBBER:
if (GET_CODE (XEXP (body, 0)) == MEM)
if (reg_overlap_mentioned_p (x, XEXP (XEXP (body, 0), 0)))
@@ -843,7 +927,7 @@ regs_set_between_p (x, start, end)
case REG:
return reg_set_between_p (x, start, end);
-
+
default:
break;
}
@@ -899,7 +983,7 @@ modified_between_p (x, start, end)
case REG:
return reg_set_between_p (x, start, end);
-
+
default:
break;
}
@@ -1110,7 +1194,7 @@ multiple_sets (insn)
{
int found;
int i;
-
+
/* INSN must be an insn. */
if (! INSN_P (insn))
return 0;
@@ -1128,7 +1212,7 @@ multiple_sets (insn)
found = 1;
}
}
-
+
/* Either zero or one SET. */
return 0;
}
@@ -1260,14 +1344,14 @@ find_last_value (x, pinsn, valid_to, allow_hwreg)
return src;
}
}
-
+
/* If set in non-simple way, we don't have a value. */
if (reg_set_p (x, p))
break;
}
return x;
-}
+}
/* Return nonzero if register in range [REGNO, ENDREGNO)
appears either explicitly or implicitly in X
@@ -1312,7 +1396,7 @@ refers_to_regno_p (regno, endregno, x, loc)
return 1;
return (endregno > x_regno
- && regno < x_regno + (x_regno < FIRST_PSEUDO_REGISTER
+ && regno < x_regno + (x_regno < FIRST_PSEUDO_REGISTER
? HARD_REGNO_NREGS (x_regno, GET_MODE (x))
: 1));
@@ -1397,7 +1481,9 @@ reg_overlap_mentioned_p (x, in)
unsigned int regno, endregno;
/* Overly conservative. */
- if (GET_CODE (x) == STRICT_LOW_PART)
+ if (GET_CODE (x) == STRICT_LOW_PART
+ || GET_CODE (x) == ZERO_EXTRACT
+ || GET_CODE (x) == SIGN_EXTRACT)
x = XEXP (x, 0);
/* If either argument is a constant, then modifying X can not affect IN. */
@@ -1517,7 +1603,7 @@ reg_set_last (x, insn)
If the item being stored in or clobbered is a SUBREG of a hard register,
the SUBREG will be passed. */
-
+
void
note_stores (x, fun, data)
rtx x;
@@ -1714,8 +1800,8 @@ dead_or_set_regno_p (insn, test_regno)
if (GET_CODE (pattern) == SET)
{
- rtx dest = SET_DEST (PATTERN (insn));
-
+ rtx dest = SET_DEST (pattern);
+
/* A value is totally replaced if it is the destination or the
destination is a SUBREG of REGNO that does not change the number of
words in it. */
@@ -1866,11 +1952,11 @@ find_reg_fusage (insn, code, datum)
rtx link;
for (link = CALL_INSN_FUNCTION_USAGE (insn);
- link;
+ link;
link = XEXP (link, 1))
- if (GET_CODE (XEXP (link, 0)) == code
+ if (GET_CODE (XEXP (link, 0)) == code
&& rtx_equal_p (datum, XEXP (XEXP (link, 0), 0)))
- return 1;
+ return 1;
}
else
{
@@ -1880,7 +1966,7 @@ find_reg_fusage (insn, code, datum)
to pseudo registers, so don't bother checking. */
if (regno < FIRST_PSEUDO_REGISTER)
- {
+ {
unsigned int end_regno
= regno + HARD_REGNO_NREGS (regno, GET_MODE (datum));
unsigned int i;
@@ -1888,7 +1974,7 @@ find_reg_fusage (insn, code, datum)
for (i = regno; i < end_regno; i++)
if (find_regno_fusage (insn, code, i))
return 1;
- }
+ }
}
return 0;
@@ -2078,7 +2164,7 @@ volatile_insn_p (x)
{
const char *fmt = GET_RTX_FORMAT (code);
int i;
-
+
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
@@ -2125,9 +2211,7 @@ volatile_refs_p (x)
case ADDR_DIFF_VEC:
return 0;
- case CALL:
case UNSPEC_VOLATILE:
- /* case TRAP_IF: This isn't clear yet. */
return 1;
case MEM:
@@ -2145,7 +2229,7 @@ volatile_refs_p (x)
{
const char *fmt = GET_RTX_FORMAT (code);
int i;
-
+
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
@@ -2223,7 +2307,7 @@ side_effects_p (x)
{
const char *fmt = GET_RTX_FORMAT (code);
int i;
-
+
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
@@ -2281,6 +2365,8 @@ may_trap_p (x)
/* Memory ref can trap unless it's a static var or a stack slot. */
case MEM:
+ if (MEM_NOTRAP_P (x))
+ return 0;
return rtx_addr_can_trap_p (XEXP (x, 0));
/* Division by a non-constant might trap. */
@@ -2288,8 +2374,11 @@ may_trap_p (x)
case MOD:
case UDIV:
case UMOD:
+ if (HONOR_SNANS (GET_MODE (x)))
+ return 1;
if (! CONSTANT_P (XEXP (x, 1))
- || GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+ || (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
+ && flag_trapping_math))
return 1;
/* This was const0_rtx, but by not using that,
we can link this file into other programs. */
@@ -2308,16 +2397,34 @@ may_trap_p (x)
case LT:
case COMPARE:
/* Some floating point comparisons may trap. */
+ if (!flag_trapping_math)
+ break;
/* ??? There is no machine independent way to check for tests that trap
when COMPARE is used, though many targets do make this distinction.
For instance, sparc uses CCFPE for compares which generate exceptions
and CCFP for compares which do not generate exceptions. */
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+ if (HONOR_NANS (GET_MODE (x)))
return 1;
/* But often the compare has some CC mode, so check operand
modes as well. */
- if (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) == MODE_FLOAT
- || GET_MODE_CLASS (GET_MODE (XEXP (x, 1))) == MODE_FLOAT)
+ if (HONOR_NANS (GET_MODE (XEXP (x, 0)))
+ || HONOR_NANS (GET_MODE (XEXP (x, 1))))
+ return 1;
+ break;
+
+ case EQ:
+ case NE:
+ if (HONOR_SNANS (GET_MODE (x)))
+ return 1;
+ /* Often comparison is CC mode, so check operand modes. */
+ if (HONOR_SNANS (GET_MODE (XEXP (x, 0)))
+ || HONOR_SNANS (GET_MODE (XEXP (x, 1))))
+ return 1;
+ break;
+
+ case FIX:
+ /* Conversion of floating point might trap. */
+ if (flag_trapping_math && HONOR_NANS (GET_MODE (XEXP (x, 0))))
return 1;
break;
@@ -2328,7 +2435,8 @@ may_trap_p (x)
default:
/* Any floating arithmetic may trap. */
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+ if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
+ && flag_trapping_math)
return 1;
}
@@ -2385,7 +2493,7 @@ inequality_comparisons_p (x)
case GE:
case GEU:
return 1;
-
+
default:
break;
}
@@ -2408,7 +2516,7 @@ inequality_comparisons_p (x)
return 1;
}
}
-
+
return 0;
}
@@ -2482,12 +2590,12 @@ replace_rtx (x, from, to)
}
return x;
-}
+}
/* Throughout the rtx X, replace many registers according to REG_MAP.
Return the replacement for X (which may be X with altered contents).
REG_MAP[R] is the replacement for register R, or 0 for don't replace.
- NREGS is the length of REG_MAP; regs >= NREGS are not mapped.
+ NREGS is the length of REG_MAP; regs >= NREGS are not mapped.
We only support REG_MAP entries of REG or SUBREG. Also, hard registers
should not be mapped to pseudos or vice versa since validate_change
@@ -2545,7 +2653,7 @@ replace_regs (x, reg_map, nregs, replace_dest)
{
rtx map_val = reg_map[REGNO (SUBREG_REG (x))];
return simplify_gen_subreg (GET_MODE (x), map_val,
- GET_MODE (SUBREG_REG (x)),
+ GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x));
}
break;
@@ -2567,7 +2675,7 @@ replace_regs (x, reg_map, nregs, replace_dest)
SET_SRC (x) = replace_regs (SET_SRC (x), reg_map, nregs, 0);
return x;
-
+
default:
break;
}
@@ -2688,7 +2796,7 @@ computed_jump_p (insn)
sub-expression (including X itself). F is also passed the DATA.
If F returns -1, do not traverse sub-expressions, but continue
traversing the rest of the tree. If F ever returns any other
- non-zero value, stop the traversal, and return the value returned
+ nonzero value, stop the traversal, and return the value returned
by F. Otherwise, return 0. This function does not traverse inside
tree structure that contains RTX_EXPRs, or into sub-expressions
whose format code is `0' since it is not known whether or not those
@@ -2724,9 +2832,9 @@ for_each_rtx (x, f, data)
length = GET_RTX_LENGTH (GET_CODE (*x));
format = GET_RTX_FORMAT (GET_CODE (*x));
- for (i = 0; i < length; ++i)
+ for (i = 0; i < length; ++i)
{
- switch (format[i])
+ switch (format[i])
{
case 'e':
result = for_each_rtx (&XEXP (*x, i), f, data);
@@ -2736,7 +2844,7 @@ for_each_rtx (x, f, data)
case 'V':
case 'E':
- if (XVEC (*x, i) != 0)
+ if (XVEC (*x, i) != 0)
{
int j;
for (j = 0; j < XVECLEN (*x, i); ++j)
@@ -2746,7 +2854,7 @@ for_each_rtx (x, f, data)
return result;
}
}
- break;
+ break;
default:
/* Nothing to do. */
@@ -2866,8 +2974,8 @@ auto_inc_p (x)
to and including TO is safe to move. If NEW_TO is non-NULL, and
the sequence is not already safe to move, but can be easily
extended to a sequence which is safe, then NEW_TO will point to the
- end of the extended sequence.
-
+ end of the extended sequence.
+
For now, this function only checks that the region contains whole
exception regions, but it could be extended to check additional
conditions as well. */
@@ -2922,7 +3030,7 @@ insns_safe_to_move_p (from, to, new_to)
/* It's OK to move the sequence if there were matched sets of
exception region notes. */
return eh_region_count == 0;
-
+
past_to_p = 1;
}
@@ -2937,11 +3045,11 @@ insns_safe_to_move_p (from, to, new_to)
/* Go to the next instruction. */
r = NEXT_INSN (r);
}
-
+
return 0;
}
-/* Return non-zero if IN contains a piece of rtl that has the address LOC */
+/* Return nonzero if IN contains a piece of rtl that has the address LOC */
int
loc_mentioned_in_p (loc, in)
rtx *loc, in;
@@ -3032,9 +3140,19 @@ subreg_regno_offset (xregno, xmode, offset, ymode)
nregs_xmode = HARD_REGNO_NREGS (xregno, xmode);
nregs_ymode = HARD_REGNO_NREGS (xregno, ymode);
+
+ /* If this is a big endian paradoxical subreg, which uses more actual
+ hard registers than the original register, we must return a negative
+ offset so that we find the proper highpart of the register. */
+ if (offset == 0
+ && nregs_ymode > nregs_xmode
+ && (GET_MODE_SIZE (ymode) > UNITS_PER_WORD
+ ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
+ return nregs_xmode - nregs_ymode;
+
if (offset == 0 || nregs_xmode == nregs_ymode)
return 0;
-
+
/* size of ymode must not be greater than the size of xmode. */
mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
if (mode_multiple == 0)
@@ -3045,8 +3163,76 @@ subreg_regno_offset (xregno, xmode, offset, ymode)
return (y_offset / (mode_multiple / nregs_multiple)) * nregs_ymode;
}
+/* This function returns true when the offset is representable via
+ subreg_offset in the given regno.
+ xregno - A regno of an inner hard subreg_reg (or what will become one).
+ xmode - The mode of xregno.
+ offset - The byte offset.
+ ymode - The mode of a top level SUBREG (or what may become one).
+ RETURN - The regno offset which would be used. */
+bool
+subreg_offset_representable_p (xregno, xmode, offset, ymode)
+ unsigned int xregno;
+ enum machine_mode xmode;
+ unsigned int offset;
+ enum machine_mode ymode;
+{
+ int nregs_xmode, nregs_ymode;
+ int mode_multiple, nregs_multiple;
+ int y_offset;
+
+ if (xregno >= FIRST_PSEUDO_REGISTER)
+ abort ();
+
+ nregs_xmode = HARD_REGNO_NREGS (xregno, xmode);
+ nregs_ymode = HARD_REGNO_NREGS (xregno, ymode);
+
+ /* paradoxical subregs are always valid. */
+ if (offset == 0
+ && nregs_ymode > nregs_xmode
+ && (GET_MODE_SIZE (ymode) > UNITS_PER_WORD
+ ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
+ return true;
+
+ /* Lowpart subregs are always valid. */
+ if (offset == subreg_lowpart_offset (ymode, xmode))
+ return true;
+
+#ifdef ENABLE_CHECKING
+ /* This should always pass, otherwise we don't know how to verify the
+ constraint. These conditions may be relaxed but subreg_offset would
+ need to be redesigned. */
+ if (GET_MODE_SIZE (xmode) % GET_MODE_SIZE (ymode)
+ || GET_MODE_SIZE (ymode) % nregs_ymode
+ || nregs_xmode % nregs_ymode)
+ abort ();
+#endif
+
+ /* The XMODE value can be seen as an vector of NREGS_XMODE
+ values. The subreg must represent an lowpart of given field.
+ Compute what field it is. */
+ offset -= subreg_lowpart_offset (ymode,
+ mode_for_size (GET_MODE_BITSIZE (xmode)
+ / nregs_xmode,
+ MODE_INT, 0));
+
+ /* size of ymode must not be greater than the size of xmode. */
+ mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
+ if (mode_multiple == 0)
+ abort ();
+
+ y_offset = offset / GET_MODE_SIZE (ymode);
+ nregs_multiple = nregs_xmode / nregs_ymode;
+#ifdef ENABLE_CHECKING
+ if (offset % GET_MODE_SIZE (ymode)
+ || mode_multiple % nregs_multiple)
+ abort ();
+#endif
+ return (!(y_offset % (mode_multiple / nregs_multiple)));
+}
+
/* Return the final regno that a subreg expression refers to. */
-unsigned int
+unsigned int
subreg_regno (x)
rtx x;
{
@@ -3054,8 +3240,8 @@ subreg_regno (x)
rtx subreg = SUBREG_REG (x);
int regno = REGNO (subreg);
- ret = regno + subreg_regno_offset (regno,
- GET_MODE (subreg),
+ ret = regno + subreg_regno_offset (regno,
+ GET_MODE (subreg),
SUBREG_BYTE (x),
GET_MODE (x));
return ret;
@@ -3082,7 +3268,7 @@ parms_set (x, pat, data)
}
}
-/* Look backward for first parameter to be loaded.
+/* Look backward for first parameter to be loaded.
Do not skip BOUNDARY. */
rtx
find_first_parameter_load (call_insn, boundary)
@@ -3135,7 +3321,304 @@ find_first_parameter_load (call_insn, boundary)
}
if (INSN_P (before))
- note_stores (PATTERN (before), parms_set, &parm);
+ note_stores (PATTERN (before), parms_set, &parm);
}
return before;
}
+
+/* Return true if we should avoid inserting code between INSN and preceeding
+ call instruction. */
+
+bool
+keep_with_call_p (insn)
+ rtx insn;
+{
+ rtx set;
+
+ if (INSN_P (insn) && (set = single_set (insn)) != NULL)
+ {
+ if (GET_CODE (SET_DEST (set)) == REG
+ && REGNO (SET_DEST (set)) < FIRST_PSEUDO_REGISTER
+ && fixed_regs[REGNO (SET_DEST (set))]
+ && general_operand (SET_SRC (set), VOIDmode))
+ return true;
+ if (GET_CODE (SET_SRC (set)) == REG
+ && FUNCTION_VALUE_REGNO_P (REGNO (SET_SRC (set)))
+ && GET_CODE (SET_DEST (set)) == REG
+ && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
+ return true;
+ /* There may be a stack pop just after the call and before the store
+ of the return register. Search for the actual store when deciding
+ if we can break or not. */
+ if (SET_DEST (set) == stack_pointer_rtx)
+ {
+ rtx i2 = next_nonnote_insn (insn);
+ if (i2 && keep_with_call_p (i2))
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Return true when store to register X can be hoisted to the place
+ with LIVE registers (can be NULL). Value VAL contains destination
+ whose value will be used. */
+
+static bool
+hoist_test_store (x, val, live)
+ rtx x, val;
+ regset live;
+{
+ if (GET_CODE (x) == SCRATCH)
+ return true;
+
+ if (rtx_equal_p (x, val))
+ return true;
+
+ /* Allow subreg of X in case it is not writting just part of multireg pseudo.
+ Then we would need to update all users to care hoisting the store too.
+ Caller may represent that by specifying whole subreg as val. */
+
+ if (GET_CODE (x) == SUBREG && rtx_equal_p (SUBREG_REG (x), val))
+ {
+ if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD
+ && GET_MODE_BITSIZE (GET_MODE (x)) <
+ GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))))
+ return false;
+ return true;
+ }
+ if (GET_CODE (x) == SUBREG)
+ x = SUBREG_REG (x);
+
+ /* Anything except register store is not hoistable. This includes the
+ partial stores to registers. */
+
+ if (!REG_P (x))
+ return false;
+
+ /* Pseudo registers can be allways replaced by another pseudo to avoid
+ the side effect, for hard register we must ensure that they are dead.
+ Eventually we may want to add code to try turn pseudos to hards, but it
+ is unlikely usefull. */
+
+ if (REGNO (x) < FIRST_PSEUDO_REGISTER)
+ {
+ int regno = REGNO (x);
+ int n = HARD_REGNO_NREGS (regno, GET_MODE (x));
+
+ if (!live)
+ return false;
+ if (REGNO_REG_SET_P (live, regno))
+ return false;
+ while (--n > 0)
+ if (REGNO_REG_SET_P (live, regno + n))
+ return false;
+ }
+ return true;
+}
+
+
+/* Return true if INSN can be hoisted to place with LIVE hard registers
+ (LIVE can be NULL when unknown). VAL is expected to be stored by the insn
+ and used by the hoisting pass. */
+
+bool
+can_hoist_insn_p (insn, val, live)
+ rtx insn, val;
+ regset live;
+{
+ rtx pat = PATTERN (insn);
+ int i;
+
+ /* It probably does not worth the complexity to handle multiple
+ set stores. */
+ if (!single_set (insn))
+ return false;
+ /* We can move CALL_INSN, but we need to check that all caller clobbered
+ regs are dead. */
+ if (GET_CODE (insn) == CALL_INSN)
+ return false;
+ /* In future we will handle hoisting of libcall sequences, but
+ give up for now. */
+ if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
+ return false;
+ switch (GET_CODE (pat))
+ {
+ case SET:
+ if (!hoist_test_store (SET_DEST (pat), val, live))
+ return false;
+ break;
+ case USE:
+ /* USES do have sick semantics, so do not move them. */
+ return false;
+ break;
+ case CLOBBER:
+ if (!hoist_test_store (XEXP (pat, 0), val, live))
+ return false;
+ break;
+ case PARALLEL:
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ {
+ rtx x = XVECEXP (pat, 0, i);
+ switch (GET_CODE (x))
+ {
+ case SET:
+ if (!hoist_test_store (SET_DEST (x), val, live))
+ return false;
+ break;
+ case USE:
+ /* We need to fix callers to really ensure availability
+ of all values inisn uses, but for now it is safe to prohibit
+ hoisting of any insn having such a hiden uses. */
+ return false;
+ break;
+ case CLOBBER:
+ if (!hoist_test_store (SET_DEST (x), val, live))
+ return false;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ abort ();
+ }
+ return true;
+}
+
+/* Update store after hoisting - replace all stores to pseudo registers
+ by new ones to avoid clobbering of values except for store to VAL that will
+ be updated to NEW. */
+
+static void
+hoist_update_store (insn, xp, val, new)
+ rtx insn, *xp, val, new;
+{
+ rtx x = *xp;
+
+ if (GET_CODE (x) == SCRATCH)
+ return;
+
+ if (GET_CODE (x) == SUBREG && SUBREG_REG (x) == val)
+ validate_change (insn, xp,
+ simplify_gen_subreg (GET_MODE (x), new, GET_MODE (new),
+ SUBREG_BYTE (x)), 1);
+ if (rtx_equal_p (x, val))
+ {
+ validate_change (insn, xp, new, 1);
+ return;
+ }
+ if (GET_CODE (x) == SUBREG)
+ {
+ xp = &SUBREG_REG (x);
+ x = *xp;
+ }
+
+ if (!REG_P (x))
+ abort ();
+
+ /* We've verified that hard registers are dead, so we may keep the side
+ effect. Otherwise replace it by new pseudo. */
+ if (REGNO (x) >= FIRST_PSEUDO_REGISTER)
+ validate_change (insn, xp, gen_reg_rtx (GET_MODE (x)), 1);
+ REG_NOTES (insn)
+ = alloc_EXPR_LIST (REG_UNUSED, *xp, REG_NOTES (insn));
+}
+
+/* Create a copy of INSN after AFTER replacing store of VAL to NEW
+ and each other side effect to pseudo register by new pseudo register. */
+
+rtx
+hoist_insn_after (insn, after, val, new)
+ rtx insn, after, val, new;
+{
+ rtx pat;
+ int i;
+ rtx note;
+
+ insn = emit_copy_of_insn_after (insn, after);
+ pat = PATTERN (insn);
+
+ /* Remove REG_UNUSED notes as we will re-emit them. */
+ while ((note = find_reg_note (insn, REG_UNUSED, NULL_RTX)))
+ remove_note (insn, note);
+
+ /* To get this working callers must ensure to move everything referenced
+ by REG_EQUAL/REG_EQUIV notes too. Lets remove them, it is probably
+ easier. */
+ while ((note = find_reg_note (insn, REG_EQUAL, NULL_RTX)))
+ remove_note (insn, note);
+ while ((note = find_reg_note (insn, REG_EQUIV, NULL_RTX)))
+ remove_note (insn, note);
+
+ /* Remove REG_DEAD notes as they might not be valid anymore in case
+ we create redundancy. */
+ while ((note = find_reg_note (insn, REG_DEAD, NULL_RTX)))
+ remove_note (insn, note);
+ switch (GET_CODE (pat))
+ {
+ case SET:
+ hoist_update_store (insn, &SET_DEST (pat), val, new);
+ break;
+ case USE:
+ break;
+ case CLOBBER:
+ hoist_update_store (insn, &XEXP (pat, 0), val, new);
+ break;
+ case PARALLEL:
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ {
+ rtx x = XVECEXP (pat, 0, i);
+ switch (GET_CODE (x))
+ {
+ case SET:
+ hoist_update_store (insn, &SET_DEST (x), val, new);
+ break;
+ case USE:
+ break;
+ case CLOBBER:
+ hoist_update_store (insn, &SET_DEST (x), val, new);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ abort ();
+ }
+ if (!apply_change_group ())
+ abort ();
+
+ return insn;
+}
+
+rtx
+hoist_insn_to_edge (insn, e, val, new)
+ rtx insn, val, new;
+ edge e;
+{
+ rtx new_insn;
+
+ /* We cannot insert instructions on an abnormal critical edge.
+ It will be easier to find the culprit if we die now. */
+ if ((e->flags & EDGE_ABNORMAL) && EDGE_CRITICAL_P (e))
+ abort ();
+
+ /* Do not use emit_insn_on_edge as we want to preserve notes and similar
+ stuff. We also emit CALL_INSNS and firends. */
+ if (e->insns == NULL_RTX)
+ {
+ start_sequence ();
+ emit_note (NULL, NOTE_INSN_DELETED);
+ }
+ else
+ push_to_sequence (e->insns);
+
+ new_insn = hoist_insn_after (insn, get_last_insn (), val, new);
+
+ e->insns = get_insns ();
+ end_sequence ();
+ return new_insn;
+}
diff --git a/contrib/gcc/sbitmap.c b/contrib/gcc/sbitmap.c
index cd9deba..74c24c9 100644
--- a/contrib/gcc/sbitmap.c
+++ b/contrib/gcc/sbitmap.c
@@ -1,5 +1,5 @@
/* Simple bitmaps.
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -47,6 +47,64 @@ sbitmap_alloc (n_elms)
return bmap;
}
+/* Resize a simple bitmap BMAP to N_ELMS bits. If increasing the
+ size of BMAP, clear the new bits to zero if the DEF argument
+ is zero, and set them to one otherwise. */
+
+sbitmap
+sbitmap_resize (bmap, n_elms, def)
+ sbitmap bmap;
+ unsigned int n_elms;
+ int def;
+{
+ unsigned int bytes, size, amt;
+ unsigned int last_bit;
+
+ size = SBITMAP_SET_SIZE (n_elms);
+ bytes = size * sizeof (SBITMAP_ELT_TYPE);
+ if (bytes > bmap->bytes)
+ {
+ amt = (sizeof (struct simple_bitmap_def)
+ + bytes - sizeof (SBITMAP_ELT_TYPE));
+ bmap = (sbitmap) xrealloc ((PTR) bmap, amt);
+ }
+
+ if (n_elms > bmap->n_bits)
+ {
+ if (def)
+ {
+ memset ((PTR) (bmap->elms + bmap->size), -1, bytes - bmap->bytes);
+
+ /* Set the new bits if the original last element. */
+ last_bit = bmap->n_bits % SBITMAP_ELT_BITS;
+ if (last_bit)
+ bmap->elms[bmap->size - 1]
+ |= ~((SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit));
+
+ /* Clear the unused bit in the new last element. */
+ last_bit = n_elms % SBITMAP_ELT_BITS;
+ if (last_bit)
+ bmap->elms[size - 1]
+ &= (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
+ }
+ else
+ memset ((PTR) (bmap->elms + bmap->size), 0, bytes - bmap->bytes);
+ }
+ else if (n_elms < bmap->n_bits)
+ {
+ /* Clear the surplus bits in the last word. */
+ last_bit = n_elms % SBITMAP_ELT_BITS;
+ if (last_bit)
+ bmap->elms[size - 1]
+ &= (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
+ }
+
+ bmap->n_bits = n_elms;
+ bmap->size = size;
+ bmap->bytes = bytes;
+ return bmap;
+}
+
/* Allocate a vector of N_VECS bitmaps of N_ELMS bits. */
sbitmap *
@@ -106,6 +164,7 @@ sbitmap_equal (a, b)
{
return !memcmp (a->elms, b->elms, sizeof (SBITMAP_ELT_TYPE) * a->size);
}
+
/* Zero all elements in a bitmap. */
void
@@ -159,29 +218,41 @@ sbitmap_vector_ones (bmap, n_vecs)
/* Set DST to be A union (B - C).
DST = A | (B & ~C).
- Return non-zero if any change is made. */
+ Returns true if any change is made. */
-int
-sbitmap_union_of_diff (dst, a, b, c)
+bool
+sbitmap_union_of_diff_cg (dst, a, b, c)
sbitmap dst, a, b, c;
{
- unsigned int i;
- sbitmap_ptr dstp, ap, bp, cp;
- int changed = 0;
-
- for (dstp = dst->elms, ap = a->elms, bp = b->elms, cp = c->elms, i = 0;
- i < dst->size; i++, dstp++)
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ sbitmap_ptr ap = a->elms;
+ sbitmap_ptr bp = b->elms;
+ sbitmap_ptr cp = c->elms;
+ SBITMAP_ELT_TYPE changed = 0;
+
+ for (i = 0; i < n; i++)
{
SBITMAP_ELT_TYPE tmp = *ap++ | (*bp++ & ~*cp++);
-
- if (*dstp != tmp)
- {
- changed = 1;
- *dstp = tmp;
- }
+ changed |= *dstp ^ tmp;
+ *dstp++ = tmp;
}
- return changed;
+ return changed != 0;
+}
+
+void
+sbitmap_union_of_diff (dst, a, b, c)
+ sbitmap dst, a, b, c;
+{
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ sbitmap_ptr ap = a->elms;
+ sbitmap_ptr bp = b->elms;
+ sbitmap_ptr cp = c->elms;
+
+ for (i = 0; i < n; i++)
+ *dstp++ = *ap++ | (*bp++ & ~*cp++);
}
/* Set bitmap DST to the bitwise negation of the bitmap SRC. */
@@ -190,11 +261,12 @@ void
sbitmap_not (dst, src)
sbitmap dst, src;
{
- unsigned int i;
- sbitmap_ptr dstp, srcp;
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ sbitmap_ptr srcp = src->elms;
- for (dstp = dst->elms, srcp = src->elms, i = 0; i < dst->size; i++)
- *dstp++ = ~(*srcp++);
+ for (i = 0; i < n; i++)
+ *dstp++ = ~*srcp++;
}
/* Set the bits in DST to be the difference between the bits
@@ -204,156 +276,226 @@ void
sbitmap_difference (dst, a, b)
sbitmap dst, a, b;
{
- unsigned int i;
- sbitmap_ptr dstp, ap, bp;
+ unsigned int i, dst_size = dst->size;
+ unsigned int min_size = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ sbitmap_ptr ap = a->elms;
+ sbitmap_ptr bp = b->elms;
- for (dstp = dst->elms, ap = a->elms, bp = b->elms, i = 0; i < dst->size; i++)
+ /* A should be at least as large as DEST, to have a defined source. */
+ if (a->size < dst_size)
+ abort ();
+ /* If minuend is smaller, we simply pretend it to be zero bits, i.e.
+ only copy the subtrahend into dest. */
+ if (b->size < min_size)
+ min_size = b->size;
+ for (i = 0; i < min_size; i++)
*dstp++ = *ap++ & (~*bp++);
+ /* Now fill the rest of dest from A, if B was too short.
+ This makes sense only when destination and A differ. */
+ if (dst != a && i != dst_size)
+ for (; i < dst_size; i++)
+ *dstp++ = *ap++;
}
/* Set DST to be (A and B).
- Return non-zero if any change is made. */
+ Return nonzero if any change is made. */
-int
-sbitmap_a_and_b (dst, a, b)
+bool
+sbitmap_a_and_b_cg (dst, a, b)
sbitmap dst, a, b;
{
- unsigned int i;
- sbitmap_ptr dstp, ap, bp;
- int changed = 0;
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ sbitmap_ptr ap = a->elms;
+ sbitmap_ptr bp = b->elms;
+ SBITMAP_ELT_TYPE changed = 0;
- for (dstp = dst->elms, ap = a->elms, bp = b->elms, i = 0; i < dst->size;
- i++, dstp++)
+ for (i = 0; i < n; i++)
{
SBITMAP_ELT_TYPE tmp = *ap++ & *bp++;
-
- if (*dstp != tmp)
- {
- changed = 1;
- *dstp = tmp;
- }
+ changed = *dstp ^ tmp;
+ *dstp++ = tmp;
}
- return changed;
+ return changed != 0;
+}
+
+void
+sbitmap_a_and_b (dst, a, b)
+ sbitmap dst, a, b;
+{
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ sbitmap_ptr ap = a->elms;
+ sbitmap_ptr bp = b->elms;
+
+ for (i = 0; i < n; i++)
+ *dstp++ = *ap++ & *bp++;
}
/* Set DST to be (A xor B)).
- Return non-zero if any change is made. */
+ Return nonzero if any change is made. */
-int
-sbitmap_a_xor_b (dst, a, b)
+bool
+sbitmap_a_xor_b_cg (dst, a, b)
sbitmap dst, a, b;
{
- unsigned int i;
- sbitmap_ptr dstp, ap, bp;
- int changed = 0;
-
- for (dstp = dst->elms, ap = a->elms, bp = b->elms, i = 0; i < dst->size;
- i++, dstp++)
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ sbitmap_ptr ap = a->elms;
+ sbitmap_ptr bp = b->elms;
+ SBITMAP_ELT_TYPE changed = 0;
+
+ for (i = 0; i < n; i++)
{
SBITMAP_ELT_TYPE tmp = *ap++ ^ *bp++;
-
- if (*dstp != tmp)
- {
- changed = 1;
- *dstp = tmp;
- }
+ changed = *dstp ^ tmp;
+ *dstp++ = tmp;
}
- return changed;
+
+ return changed != 0;
+}
+
+void
+sbitmap_a_xor_b (dst, a, b)
+ sbitmap dst, a, b;
+{
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ sbitmap_ptr ap = a->elms;
+ sbitmap_ptr bp = b->elms;
+
+ for (i = 0; i < n; i++)
+ *dstp++ = *ap++ ^ *bp++;
}
/* Set DST to be (A or B)).
- Return non-zero if any change is made. */
+ Return nonzero if any change is made. */
-int
-sbitmap_a_or_b (dst, a, b)
+bool
+sbitmap_a_or_b_cg (dst, a, b)
sbitmap dst, a, b;
{
- unsigned int i;
- sbitmap_ptr dstp, ap, bp;
- int changed = 0;
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ sbitmap_ptr ap = a->elms;
+ sbitmap_ptr bp = b->elms;
+ SBITMAP_ELT_TYPE changed = 0;
- for (dstp = dst->elms, ap = a->elms, bp = b->elms, i = 0; i < dst->size;
- i++, dstp++)
+ for (i = 0; i < n; i++)
{
SBITMAP_ELT_TYPE tmp = *ap++ | *bp++;
-
- if (*dstp != tmp)
- {
- changed = 1;
- *dstp = tmp;
- }
+ changed = *dstp ^ tmp;
+ *dstp++ = tmp;
}
- return changed;
+ return changed != 0;
}
-/* Return non-zero if A is a subset of B. */
+void
+sbitmap_a_or_b (dst, a, b)
+ sbitmap dst, a, b;
+{
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ sbitmap_ptr ap = a->elms;
+ sbitmap_ptr bp = b->elms;
+
+ for (i = 0; i < n; i++)
+ *dstp++ = *ap++ | *bp++;
+}
-int
+/* Return nonzero if A is a subset of B. */
+
+bool
sbitmap_a_subset_b_p (a, b)
sbitmap a, b;
{
- unsigned int i;
+ unsigned int i, n = a->size;
sbitmap_ptr ap, bp;
- for (ap = a->elms, bp = b->elms, i = 0; i < a->size; i++, ap++, bp++)
+ for (ap = a->elms, bp = b->elms, i = 0; i < n; i++, ap++, bp++)
if ((*ap | *bp) != *bp)
- return 0;
+ return false;
- return 1;
+ return true;
}
/* Set DST to be (A or (B and C)).
- Return non-zero if any change is made. */
+ Return nonzero if any change is made. */
-int
-sbitmap_a_or_b_and_c (dst, a, b, c)
+bool
+sbitmap_a_or_b_and_c_cg (dst, a, b, c)
sbitmap dst, a, b, c;
{
- unsigned int i;
- sbitmap_ptr dstp, ap, bp, cp;
- int changed = 0;
-
- for (dstp = dst->elms, ap = a->elms, bp = b->elms, cp = c->elms, i = 0;
- i < dst->size; i++, dstp++)
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ sbitmap_ptr ap = a->elms;
+ sbitmap_ptr bp = b->elms;
+ sbitmap_ptr cp = c->elms;
+ SBITMAP_ELT_TYPE changed = 0;
+
+ for (i = 0; i < n; i++)
{
SBITMAP_ELT_TYPE tmp = *ap++ | (*bp++ & *cp++);
-
- if (*dstp != tmp)
- {
- changed = 1;
- *dstp = tmp;
- }
+ changed |= *dstp ^ tmp;
+ *dstp++ = tmp;
}
- return changed;
+ return changed != 0;
+}
+
+void
+sbitmap_a_or_b_and_c (dst, a, b, c)
+ sbitmap dst, a, b, c;
+{
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ sbitmap_ptr ap = a->elms;
+ sbitmap_ptr bp = b->elms;
+ sbitmap_ptr cp = c->elms;
+
+ for (i = 0; i < n; i++)
+ *dstp++ = *ap++ | (*bp++ & *cp++);
}
/* Set DST to be (A and (B or C)).
- Return non-zero if any change is made. */
+ Return nonzero if any change is made. */
-int
-sbitmap_a_and_b_or_c (dst, a, b, c)
+bool
+sbitmap_a_and_b_or_c_cg (dst, a, b, c)
sbitmap dst, a, b, c;
{
- unsigned int i;
- sbitmap_ptr dstp, ap, bp, cp;
- int changed = 0;
-
- for (dstp = dst->elms, ap = a->elms, bp = b->elms, cp = c->elms, i = 0;
- i < dst->size; i++, dstp++)
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ sbitmap_ptr ap = a->elms;
+ sbitmap_ptr bp = b->elms;
+ sbitmap_ptr cp = c->elms;
+ SBITMAP_ELT_TYPE changed = 0;
+
+ for (i = 0; i < n; i++)
{
SBITMAP_ELT_TYPE tmp = *ap++ & (*bp++ | *cp++);
-
- if (*dstp != tmp)
- {
- changed = 1;
- *dstp = tmp;
- }
+ changed |= *dstp ^ tmp;
+ *dstp++ = tmp;
}
- return changed;
+ return changed != 0;
+}
+
+void
+sbitmap_a_and_b_or_c (dst, a, b, c)
+ sbitmap dst, a, b, c;
+{
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ sbitmap_ptr ap = a->elms;
+ sbitmap_ptr bp = b->elms;
+ sbitmap_ptr cp = c->elms;
+
+ for (i = 0; i < n; i++)
+ *dstp++ = *ap++ & (*bp++ | *cp++);
}
#ifdef IN_GCC
@@ -373,7 +515,7 @@ sbitmap_intersection_of_succs (dst, src, bb)
for (e = b->succ; e != 0; e = e->succ_next)
{
if (e->dest == EXIT_BLOCK_PTR)
- continue;
+ continue;
sbitmap_copy (dst, src[e->dest->index]);
break;
@@ -413,7 +555,7 @@ sbitmap_intersection_of_preds (dst, src, bb)
for (e = b->pred; e != 0; e = e->pred_next)
{
if (e->src == ENTRY_BLOCK_PTR)
- continue;
+ continue;
sbitmap_copy (dst, src[e->src->index]);
break;
@@ -453,7 +595,7 @@ sbitmap_union_of_succs (dst, src, bb)
for (e = b->succ; e != 0; e = e->succ_next)
{
if (e->dest == EXIT_BLOCK_PTR)
- continue;
+ continue;
sbitmap_copy (dst, src[e->dest->index]);
break;
@@ -493,7 +635,7 @@ sbitmap_union_of_preds (dst, src, bb)
for (e = b->pred; e != 0; e = e->pred_next)
{
if (e->src== ENTRY_BLOCK_PTR)
- continue;
+ continue;
sbitmap_copy (dst, src[e->src->index]);
break;
@@ -509,7 +651,7 @@ sbitmap_union_of_preds (dst, src, bb)
if (e->src == ENTRY_BLOCK_PTR)
continue;
-
+
p = src[e->src->index]->elms;
r = dst->elms;
for (i = 0; i < set_size; i++)
@@ -587,27 +729,35 @@ dump_sbitmap (file, bmap)
}
void
-debug_sbitmap (bmap)
+dump_sbitmap_file (file, bmap)
+ FILE *file;
sbitmap bmap;
{
unsigned int i, pos;
- fprintf (stderr, "n_bits = %d, set = {", bmap->n_bits);
+ fprintf (file, "n_bits = %d, set = {", bmap->n_bits);
for (pos = 30, i = 0; i < bmap->n_bits; i++)
if (TEST_BIT (bmap, i))
{
if (pos > 70)
{
- fprintf (stderr, "\n");
+ fprintf (file, "\n ");
pos = 0;
}
- fprintf (stderr, "%d ", i);
- pos += 1 + (i >= 10) + (i >= 100);
+ fprintf (file, "%d ", i);
+ pos += 2 + (i >= 10) + (i >= 100) + (i >= 1000);
}
- fprintf (stderr, "}\n");
+ fprintf (file, "}\n");
+}
+
+void
+debug_sbitmap (bmap)
+ sbitmap bmap;
+{
+ dump_sbitmap_file (stderr, bmap);
}
void
diff --git a/contrib/gcc/sbitmap.h b/contrib/gcc/sbitmap.h
index 8896801..42e466e 100644
--- a/contrib/gcc/sbitmap.h
+++ b/contrib/gcc/sbitmap.h
@@ -1,5 +1,5 @@
/* Simple bitmaps.
- Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -85,17 +85,47 @@ do { \
} \
} while (0)
+#define EXECUTE_IF_SET_IN_SBITMAP_REV(SBITMAP, N, CODE) \
+do { \
+ unsigned int word_num_; \
+ unsigned int bit_num_; \
+ unsigned int size_ = (SBITMAP)->size; \
+ SBITMAP_ELT_TYPE *ptr_ = (SBITMAP)->elms; \
+ \
+ for (word_num_ = size_; word_num_ > 0; word_num_--) \
+ { \
+ SBITMAP_ELT_TYPE word_ = ptr_[word_num_ - 1]; \
+ \
+ if (word_ != 0) \
+ for (bit_num_ = SBITMAP_ELT_BITS; bit_num_ > 0; bit_num_--) \
+ { \
+ SBITMAP_ELT_TYPE _mask = (SBITMAP_ELT_TYPE)1 << (bit_num_ - 1);\
+ \
+ if ((word_ & _mask) != 0) \
+ { \
+ word_ &= ~ _mask; \
+ (N) = (word_num_ - 1) * SBITMAP_ELT_BITS + bit_num_ - 1;\
+ CODE; \
+ if (word_ == 0) \
+ break; \
+ } \
+ } \
+ } \
+} while (0)
+
#define sbitmap_free(MAP) free(MAP)
#define sbitmap_vector_free(VEC) free(VEC)
struct int_list;
extern void dump_sbitmap PARAMS ((FILE *, sbitmap));
+extern void dump_sbitmap_file PARAMS ((FILE *, sbitmap));
extern void dump_sbitmap_vector PARAMS ((FILE *, const char *,
const char *, sbitmap *,
int));
extern sbitmap sbitmap_alloc PARAMS ((unsigned int));
extern sbitmap *sbitmap_vector_alloc PARAMS ((unsigned int, unsigned int));
+extern sbitmap sbitmap_resize PARAMS ((sbitmap, unsigned int, int));
extern void sbitmap_copy PARAMS ((sbitmap, sbitmap));
extern int sbitmap_equal PARAMS ((sbitmap, sbitmap));
extern void sbitmap_zero PARAMS ((sbitmap));
@@ -103,18 +133,27 @@ extern void sbitmap_ones PARAMS ((sbitmap));
extern void sbitmap_vector_zero PARAMS ((sbitmap *, unsigned int));
extern void sbitmap_vector_ones PARAMS ((sbitmap *, unsigned int));
-extern int sbitmap_union_of_diff PARAMS ((sbitmap, sbitmap, sbitmap,
+extern void sbitmap_union_of_diff PARAMS ((sbitmap, sbitmap, sbitmap,
+ sbitmap));
+extern bool sbitmap_union_of_diff_cg PARAMS ((sbitmap, sbitmap, sbitmap,
sbitmap));
extern void sbitmap_difference PARAMS ((sbitmap, sbitmap, sbitmap));
extern void sbitmap_not PARAMS ((sbitmap, sbitmap));
-extern int sbitmap_a_or_b_and_c PARAMS ((sbitmap, sbitmap, sbitmap,
+extern void sbitmap_a_or_b_and_c PARAMS ((sbitmap, sbitmap, sbitmap,
+ sbitmap));
+extern bool sbitmap_a_or_b_and_c_cg PARAMS ((sbitmap, sbitmap, sbitmap,
+ sbitmap));
+extern void sbitmap_a_and_b_or_c PARAMS ((sbitmap, sbitmap, sbitmap,
sbitmap));
-extern int sbitmap_a_and_b_or_c PARAMS ((sbitmap, sbitmap, sbitmap,
+extern bool sbitmap_a_and_b_or_c_cg PARAMS ((sbitmap, sbitmap, sbitmap,
sbitmap));
-extern int sbitmap_a_and_b PARAMS ((sbitmap, sbitmap, sbitmap));
-extern int sbitmap_a_or_b PARAMS ((sbitmap, sbitmap, sbitmap));
-extern int sbitmap_a_xor_b PARAMS ((sbitmap, sbitmap, sbitmap));
-extern int sbitmap_a_subset_b_p PARAMS ((sbitmap, sbitmap));
+extern void sbitmap_a_and_b PARAMS ((sbitmap, sbitmap, sbitmap));
+extern bool sbitmap_a_and_b_cg PARAMS ((sbitmap, sbitmap, sbitmap));
+extern void sbitmap_a_or_b PARAMS ((sbitmap, sbitmap, sbitmap));
+extern bool sbitmap_a_or_b_cg PARAMS ((sbitmap, sbitmap, sbitmap));
+extern void sbitmap_a_xor_b PARAMS ((sbitmap, sbitmap, sbitmap));
+extern bool sbitmap_a_xor_b_cg PARAMS ((sbitmap, sbitmap, sbitmap));
+extern bool sbitmap_a_subset_b_p PARAMS ((sbitmap, sbitmap));
extern int sbitmap_first_set_bit PARAMS ((sbitmap));
extern int sbitmap_last_set_bit PARAMS ((sbitmap));
diff --git a/contrib/gcc/scan-decls.c b/contrib/gcc/scan-decls.c
index cbd9900..e56401d 100644
--- a/contrib/gcc/scan-decls.c
+++ b/contrib/gcc/scan-decls.c
@@ -72,7 +72,7 @@ skip_to_closing_brace (pfile)
/* This function scans a C source file (actually, the output of cpp),
reading from FP. It looks for function declarations, and
- external variable declarations.
+ external variable declarations.
The following grammar (as well as some extra stuff) is recognized:
@@ -155,7 +155,7 @@ scan_decls (pfile, argc, argv)
/* ... fall through ... */
case CPP_OPEN_BRACE: case CPP_CLOSE_BRACE:
goto new_statement;
-
+
case CPP_EOF:
return 0;
diff --git a/contrib/gcc/scan.c b/contrib/gcc/scan.c
index ee2607c..ac6b809 100644
--- a/contrib/gcc/scan.c
+++ b/contrib/gcc/scan.c
@@ -34,7 +34,7 @@ make_sstring_space (str, count)
if (new_size <= cur_size)
return;
-
+
str->base = xrealloc (str->base, new_size);
str->ptr = str->base + cur_size;
str->limit = str->base + new_size;
@@ -53,7 +53,7 @@ sstring_append (dst, src)
s = src->base;
while (--count >= 0) *d++ = *s++;
dst->ptr = d;
- *d = 0;
+ *d = 0;
}
int
diff --git a/contrib/gcc/sched-deps.c b/contrib/gcc/sched-deps.c
index 4e14ee2..98b0732 100644
--- a/contrib/gcc/sched-deps.c
+++ b/contrib/gcc/sched-deps.c
@@ -222,8 +222,7 @@ add_dependence (insn, elem, dep_type)
setters of the condition codes, so we must skip past notes here.
Otherwise, NOTEs are impossible here. */
next = next_nonnote_insn (elem);
- if (next && SCHED_GROUP_P (next)
- && GET_CODE (next) != CODE_LABEL)
+ if (next && INSN_P (next) && SCHED_GROUP_P (next))
{
/* Notes will never intervene here though, so don't bother checking
for them. */
@@ -235,8 +234,8 @@ add_dependence (insn, elem, dep_type)
rtx nnext;
while ((nnext = next_nonnote_insn (next)) != NULL
- && SCHED_GROUP_P (nnext)
- && GET_CODE (nnext) != CODE_LABEL)
+ && INSN_P (nnext)
+ && SCHED_GROUP_P (nnext))
next = nnext;
/* Again, don't depend an insn on itself. */
@@ -280,7 +279,7 @@ add_dependence (insn, elem, dep_type)
else if (TEST_BIT (output_dependency_cache[INSN_LUID (insn)],
INSN_LUID (elem)))
present_dep_type = REG_DEP_OUTPUT;
- else
+ else
present_p = 0;
if (present_p && (int) dep_type >= (int) present_dep_type)
return;
@@ -313,7 +312,7 @@ add_dependence (insn, elem, dep_type)
one, then change the existing dependence to this type. */
if ((int) dep_type < (int) REG_NOTE_KIND (link))
PUT_REG_NOTE_KIND (link, dep_type);
-
+
#ifdef INSN_SCHEDULING
/* If we are adding a dependency to INSN's LOG_LINKs, then
note that in the bitmap caches of dependency information. */
@@ -448,7 +447,7 @@ group_leader (insn)
prev = insn;
insn = next_nonnote_insn (insn);
}
- while (insn && SCHED_GROUP_P (insn) && (GET_CODE (insn) != CODE_LABEL));
+ while (insn && INSN_P (insn) && SCHED_GROUP_P (insn));
return prev;
}
@@ -1040,7 +1039,7 @@ sched_analyze_insn (deps, x, insn, loop_notes)
}
/* If this instruction can throw an exception, then moving it changes
- where block boundaries fall. This is mighty confusing elsewhere.
+ where block boundaries fall. This is mighty confusing elsewhere.
Therefore, prevent such an instruction from being moved. */
if (can_throw_internal (insn))
reg_pending_barrier = true;
@@ -1243,16 +1242,13 @@ sched_analyze (deps, head, tail)
for (insn = head;; insn = NEXT_INSN (insn))
{
- rtx link, end_seq, r0, set, note;
+ rtx link, end_seq, r0, set;
if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
{
/* Clear out the stale LOG_LINKS from flow. */
free_INSN_LIST_list (&LOG_LINKS (insn));
- /* Clear out stale SCHED_GROUP_P. */
- SCHED_GROUP_P (insn) = 0;
-
/* Make each JUMP_INSN a scheduling barrier for memory
references. */
if (GET_CODE (insn) == JUMP_INSN)
@@ -1291,8 +1287,12 @@ sched_analyze (deps, head, tail)
SET_REGNO_REG_SET (reg_pending_sets, i);
SET_REGNO_REG_SET (reg_pending_uses, i);
}
- /* Other call-clobbered hard regs may be clobbered. */
- else if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
+ /* Other call-clobbered hard regs may be clobbered.
+ Since we only have a choice between 'might be clobbered'
+ and 'definitely not clobbered', we must include all
+ partly call-clobbered registers here. */
+ else if (HARD_REGNO_CALL_PART_CLOBBERED (i, reg_raw_mode[i])
+ || TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
SET_REGNO_REG_SET (reg_pending_clobbers, i);
/* We don't know what set of fixed registers might be used
by the function, but it is certain that the stack pointer
@@ -1337,17 +1337,7 @@ sched_analyze (deps, head, tail)
/* See comments on reemit_notes as to why we do this.
??? Actually, the reemit_notes just say what is done, not why. */
- else if (GET_CODE (insn) == NOTE
- && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_RANGE_BEG
- || NOTE_LINE_NUMBER (insn) == NOTE_INSN_RANGE_END))
- {
- loop_notes = alloc_EXPR_LIST (REG_SAVE_NOTE, NOTE_RANGE_INFO (insn),
- loop_notes);
- loop_notes = alloc_EXPR_LIST (REG_SAVE_NOTE,
- GEN_INT (NOTE_LINE_NUMBER (insn)),
- loop_notes);
- }
- else if (GET_CODE (insn) == NOTE
+ if (GET_CODE (insn) == NOTE
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
@@ -1528,9 +1518,12 @@ free_deps (deps)
EXECUTE_IF_SET_IN_REG_SET (&deps->reg_last_in_use, 0, i,
{
struct deps_reg *reg_last = &deps->reg_last[i];
- free_INSN_LIST_list (&reg_last->uses);
- free_INSN_LIST_list (&reg_last->sets);
- free_INSN_LIST_list (&reg_last->clobbers);
+ if (reg_last->uses)
+ free_INSN_LIST_list (&reg_last->uses);
+ if (reg_last->sets)
+ free_INSN_LIST_list (&reg_last->sets);
+ if (reg_last->clobbers)
+ free_INSN_LIST_list (&reg_last->clobbers);
});
CLEAR_REG_SET (&deps->reg_last_in_use);
diff --git a/contrib/gcc/sched-ebb.c b/contrib/gcc/sched-ebb.c
index 31b5f3c..e9d7482 100644
--- a/contrib/gcc/sched-ebb.c
+++ b/contrib/gcc/sched-ebb.c
@@ -1,6 +1,6 @@
/* Instruction scheduling pass.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
and currently maintained by, Jim Wilson (wilson@cygnus.com)
@@ -49,7 +49,7 @@ static void init_ready_list PARAMS ((struct ready_list *));
static int can_schedule_ready_p PARAMS ((rtx));
static int new_ready PARAMS ((rtx));
static int schedule_more_p PARAMS ((void));
-static const char *print_insn PARAMS ((rtx, int));
+static const char *ebb_print_insn PARAMS ((rtx, int));
static int rank PARAMS ((rtx, rtx));
static int contributes_to_priority PARAMS ((rtx, rtx));
static void compute_jump_reg_dependencies PARAMS ((rtx, regset));
@@ -94,7 +94,7 @@ init_ready_list (ready)
next = NEXT_INSN (insn);
if (INSN_DEP_COUNT (insn) == 0
- && (SCHED_GROUP_P (next) == 0 || ! INSN_P (next)))
+ && (! INSN_P (next) || SCHED_GROUP_P (next) == 0))
ready_add (ready, insn);
if (!(SCHED_GROUP_P (insn)))
target_n_insns++;
@@ -128,7 +128,7 @@ new_ready (next)
to be formatted so that multiple output lines will line up nicely. */
static const char *
-print_insn (insn, aligned)
+ebb_print_insn (insn, aligned)
rtx insn;
int aligned ATTRIBUTE_UNUSED;
{
@@ -188,7 +188,7 @@ static struct sched_info ebb_sched_info =
schedule_more_p,
new_ready,
rank,
- print_insn,
+ ebb_print_insn,
contributes_to_priority,
compute_jump_reg_dependencies,
@@ -279,37 +279,34 @@ void
schedule_ebbs (dump_file)
FILE *dump_file;
{
- int i;
+ basic_block bb;
/* Taking care of this degenerate case makes the rest of
this code simpler. */
if (n_basic_blocks == 0)
return;
- scope_to_insns_initialize ();
-
sched_init (dump_file);
current_sched_info = &ebb_sched_info;
allocate_reg_life_data ();
- compute_bb_for_insn (get_max_uid ());
+ compute_bb_for_insn ();
/* Schedule every region in the subroutine. */
- for (i = 0; i < n_basic_blocks; i++)
- {
- rtx head = BASIC_BLOCK (i)->head;
+ FOR_EACH_BB (bb)
+ {
+ rtx head = bb->head;
rtx tail;
for (;;)
{
- basic_block b = BASIC_BLOCK (i);
edge e;
- tail = b->end;
- if (i + 1 == n_basic_blocks
- || GET_CODE (BLOCK_HEAD (i + 1)) == CODE_LABEL)
+ tail = bb->end;
+ if (bb->next_bb == EXIT_BLOCK_PTR
+ || GET_CODE (bb->next_bb->head) == CODE_LABEL)
break;
- for (e = b->succ; e; e = e->succ_next)
+ for (e = bb->succ; e; e = e->succ_next)
if ((e->flags & EDGE_FALLTHRU) != 0)
break;
if (! e)
@@ -325,7 +322,7 @@ schedule_ebbs (dump_file)
}
}
- i++;
+ bb = bb->next_bb;
}
/* Blah. We should fix the rest of the code not to get confused by
@@ -356,7 +353,5 @@ schedule_ebbs (dump_file)
if (write_symbols != NO_DEBUG)
rm_redundant_line_notes ();
- scope_to_insns_finalize ();
-
sched_finish ();
}
diff --git a/contrib/gcc/sched-int.h b/contrib/gcc/sched-int.h
index 725bf2a..1b19656 100644
--- a/contrib/gcc/sched-int.h
+++ b/contrib/gcc/sched-int.h
@@ -20,6 +20,9 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
+/* Pointer to data describing the current DFA state. */
+extern state_t curr_state;
+
/* Forward declaration. */
struct ready_list;
@@ -106,7 +109,7 @@ struct deps
int clobbers_length;
} *reg_last;
- /* Element N is set for each register that has any non-zero element
+ /* Element N is set for each register that has any nonzero element
in reg_last[N].{uses,sets,clobbers}. */
regset_head reg_last_in_use;
};
@@ -190,7 +193,7 @@ struct haifa_insn_data
int dep_count;
/* An encoding of the blockage range function. Both unit and range
- are coded. */
+ are coded. This member is used only for old pipeline interface. */
unsigned int blockage;
/* Number of instructions referring to this insn. */
@@ -202,7 +205,8 @@ struct haifa_insn_data
short cost;
- /* An encoding of the function units used. */
+ /* An encoding of the function units used. This member is used only
+ for old pipeline interface. */
short units;
/* This weight is an estimation of the insn's contribution to
@@ -313,4 +317,4 @@ extern int insn_unit PARAMS ((rtx));
extern int insn_cost PARAMS ((rtx, rtx, rtx));
extern rtx get_unit_last_insn PARAMS ((int));
extern int actual_hazard_this_instance PARAMS ((int, int, rtx, int, int));
-
+extern void print_insn PARAMS ((char *, rtx, int));
diff --git a/contrib/gcc/sched-rgn.c b/contrib/gcc/sched-rgn.c
index ab65e2c..88545b2 100644
--- a/contrib/gcc/sched-rgn.c
+++ b/contrib/gcc/sched-rgn.c
@@ -62,6 +62,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "recog.h"
#include "cfglayout.h"
#include "sched-int.h"
+#include "target.h"
/* Define when we want to do count REG_DEAD notes before and after scheduling
for sanity checking. We can't do that when conditional execution is used,
@@ -152,7 +153,7 @@ static int *containing_rgn;
void debug_regions PARAMS ((void));
static void find_single_block_region PARAMS ((void));
-static void find_rgns PARAMS ((struct edge_list *, sbitmap *));
+static void find_rgns PARAMS ((struct edge_list *, dominance_info));
static int too_large PARAMS ((int, int *, int *));
extern void debug_live PARAMS ((int, int));
@@ -269,16 +270,13 @@ static edgeset *ancestor_edges;
static void compute_dom_prob_ps PARAMS ((int));
-#define ABS_VALUE(x) (((x)<0)?(-(x)):(x))
#define INSN_PROBABILITY(INSN) (SRC_PROB (BLOCK_TO_BB (BLOCK_NUM (INSN))))
#define IS_SPECULATIVE_INSN(INSN) (IS_SPECULATIVE (BLOCK_TO_BB (BLOCK_NUM (INSN))))
#define INSN_BB(INSN) (BLOCK_TO_BB (BLOCK_NUM (INSN)))
/* Parameters affecting the decision of rank_for_schedule().
??? Nope. But MIN_PROBABILITY is used in copmute_trg_info. */
-#define MIN_DIFF_PRIORITY 2
#define MIN_PROBABILITY 40
-#define MIN_PROB_DIFF 10
/* Speculative scheduling functions. */
static int check_live_1 PARAMS ((int, rtx));
@@ -318,7 +316,7 @@ static void free_pending_lists PARAMS ((void));
static int
is_cfg_nonregular ()
{
- int b;
+ basic_block b;
rtx insn;
RTX_CODE code;
@@ -345,8 +343,8 @@ is_cfg_nonregular ()
/* If we have non-jumping insns which refer to labels, then we consider
the cfg not well structured. */
/* Check for labels referred to other thn by jumps. */
- for (b = 0; b < n_basic_blocks; b++)
- for (insn = BLOCK_HEAD (b);; insn = NEXT_INSN (insn))
+ FOR_EACH_BB (b)
+ for (insn = b->head;; insn = NEXT_INSN (insn))
{
code = GET_CODE (insn);
if (GET_RTX_CLASS (code) == 'i' && code != JUMP_INSN)
@@ -360,7 +358,7 @@ is_cfg_nonregular ()
return 1;
}
- if (insn == BLOCK_END (b))
+ if (insn == b->end)
break;
}
@@ -381,6 +379,7 @@ build_control_flow (edge_list)
struct edge_list *edge_list;
{
int i, unreachable, num_edges;
+ basic_block b;
/* This already accounts for entry/exit edges. */
num_edges = NUM_EDGES (edge_list);
@@ -392,10 +391,8 @@ build_control_flow (edge_list)
test is redundant with the one in find_rgns, but it's much
cheaper to go ahead and catch the trivial case here. */
unreachable = 0;
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (b)
{
- basic_block b = BASIC_BLOCK (i);
-
if (b->pred == NULL
|| (b->pred->src == b
&& b->pred->pred_next == NULL))
@@ -403,8 +400,8 @@ build_control_flow (edge_list)
}
/* ??? We can kill these soon. */
- in_edges = (int *) xcalloc (n_basic_blocks, sizeof (int));
- out_edges = (int *) xcalloc (n_basic_blocks, sizeof (int));
+ in_edges = (int *) xcalloc (last_basic_block, sizeof (int));
+ out_edges = (int *) xcalloc (last_basic_block, sizeof (int));
edge_table = (haifa_edge *) xcalloc (num_edges, sizeof (haifa_edge));
nr_edges = 0;
@@ -543,17 +540,19 @@ debug_regions ()
static void
find_single_block_region ()
{
- int i;
+ basic_block bb;
+
+ nr_regions = 0;
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- rgn_bb_table[i] = i;
- RGN_NR_BLOCKS (i) = 1;
- RGN_BLOCKS (i) = i;
- CONTAINING_RGN (i) = i;
- BLOCK_TO_BB (i) = 0;
+ rgn_bb_table[nr_regions] = bb->index;
+ RGN_NR_BLOCKS (nr_regions) = 1;
+ RGN_BLOCKS (nr_regions) = nr_regions;
+ CONTAINING_RGN (bb->index) = nr_regions;
+ BLOCK_TO_BB (bb->index) = 0;
+ nr_regions++;
}
- nr_regions = n_basic_blocks;
}
/* Update number of blocks and the estimate for number of insns
@@ -576,17 +575,17 @@ too_large (block, num_bbs, num_insns)
/* Update_loop_relations(blk, hdr): Check if the loop headed by max_hdr[blk]
is still an inner loop. Put in max_hdr[blk] the header of the most inner
loop containing blk. */
-#define UPDATE_LOOP_RELATIONS(blk, hdr) \
-{ \
- if (max_hdr[blk] == -1) \
- max_hdr[blk] = hdr; \
- else if (dfs_nr[max_hdr[blk]] > dfs_nr[hdr]) \
- RESET_BIT (inner, hdr); \
- else if (dfs_nr[max_hdr[blk]] < dfs_nr[hdr]) \
- { \
- RESET_BIT (inner,max_hdr[blk]); \
- max_hdr[blk] = hdr; \
- } \
+#define UPDATE_LOOP_RELATIONS(blk, hdr) \
+{ \
+ if (max_hdr[blk] == -1) \
+ max_hdr[blk] = hdr; \
+ else if (dfs_nr[max_hdr[blk]] > dfs_nr[hdr]) \
+ RESET_BIT (inner, hdr); \
+ else if (dfs_nr[max_hdr[blk]] < dfs_nr[hdr]) \
+ { \
+ RESET_BIT (inner,max_hdr[blk]); \
+ max_hdr[blk] = hdr; \
+ } \
}
/* Find regions for interblock scheduling.
@@ -622,7 +621,7 @@ too_large (block, num_bbs, num_insns)
static void
find_rgns (edge_list, dom)
struct edge_list *edge_list;
- sbitmap *dom;
+ dominance_info dom;
{
int *max_hdr, *dfs_nr, *stack, *degree;
char no_loops = 1;
@@ -630,6 +629,7 @@ find_rgns (edge_list, dom)
int count = 0, sp, idx = 0, current_edge = out_edges[0];
int num_bbs, num_insns, unreachable;
int too_large_failure;
+ basic_block bb;
/* Note if an edge has been passed. */
sbitmap passed;
@@ -637,7 +637,7 @@ find_rgns (edge_list, dom)
/* Note if a block is a natural loop header. */
sbitmap header;
- /* Note if a block is an natural inner loop header. */
+ /* Note if a block is a natural inner loop header. */
sbitmap inner;
/* Note if a block is in the block queue. */
@@ -658,26 +658,26 @@ find_rgns (edge_list, dom)
STACK, SP and DFS_NR are only used during the first traversal. */
/* Allocate and initialize variables for the first traversal. */
- max_hdr = (int *) xmalloc (n_basic_blocks * sizeof (int));
- dfs_nr = (int *) xcalloc (n_basic_blocks, sizeof (int));
+ max_hdr = (int *) xmalloc (last_basic_block * sizeof (int));
+ dfs_nr = (int *) xcalloc (last_basic_block, sizeof (int));
stack = (int *) xmalloc (nr_edges * sizeof (int));
- inner = sbitmap_alloc (n_basic_blocks);
+ inner = sbitmap_alloc (last_basic_block);
sbitmap_ones (inner);
- header = sbitmap_alloc (n_basic_blocks);
+ header = sbitmap_alloc (last_basic_block);
sbitmap_zero (header);
passed = sbitmap_alloc (nr_edges);
sbitmap_zero (passed);
- in_queue = sbitmap_alloc (n_basic_blocks);
+ in_queue = sbitmap_alloc (last_basic_block);
sbitmap_zero (in_queue);
- in_stack = sbitmap_alloc (n_basic_blocks);
+ in_stack = sbitmap_alloc (last_basic_block);
sbitmap_zero (in_stack);
- for (i = 0; i < n_basic_blocks; i++)
+ for (i = 0; i < last_basic_block; i++)
max_hdr[i] = -1;
/* DFS traversal to find inner loops in the cfg. */
@@ -771,8 +771,8 @@ find_rgns (edge_list, dom)
the entry node by placing a nonzero value in dfs_nr. Thus if
dfs_nr is zero for any block, then it must be unreachable. */
unreachable = 0;
- for (i = 0; i < n_basic_blocks; i++)
- if (dfs_nr[i] == 0)
+ FOR_EACH_BB (bb)
+ if (dfs_nr[bb->index] == 0)
{
unreachable = 1;
break;
@@ -782,8 +782,8 @@ find_rgns (edge_list, dom)
to hold degree counts. */
degree = dfs_nr;
- for (i = 0; i < n_basic_blocks; i++)
- degree[i] = 0;
+ FOR_EACH_BB (bb)
+ degree[bb->index] = 0;
for (i = 0; i < num_edges; i++)
{
edge e = INDEX_EDGE (edge_list, i);
@@ -808,12 +808,12 @@ find_rgns (edge_list, dom)
/* Find blocks which are inner loop headers. We still have non-reducible
loops to consider at this point. */
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- if (TEST_BIT (header, i) && TEST_BIT (inner, i))
+ if (TEST_BIT (header, bb->index) && TEST_BIT (inner, bb->index))
{
edge e;
- int j;
+ basic_block jbb;
/* Now check that the loop is reducible. We do this separate
from finding inner loops so that we do not find a reducible
@@ -826,15 +826,15 @@ find_rgns (edge_list, dom)
If there exists a block that is not dominated by the loop
header, then the block is reachable from outside the loop
and thus the loop is not a natural loop. */
- for (j = 0; j < n_basic_blocks; j++)
+ FOR_EACH_BB (jbb)
{
/* First identify blocks in the loop, except for the loop
entry block. */
- if (i == max_hdr[j] && i != j)
+ if (bb->index == max_hdr[jbb->index] && bb != jbb)
{
/* Now verify that the block is dominated by the loop
header. */
- if (!TEST_BIT (dom[j], i))
+ if (!dominated_by_p (dom, jbb, bb))
break;
}
}
@@ -842,25 +842,25 @@ find_rgns (edge_list, dom)
/* If we exited the loop early, then I is the header of
a non-reducible loop and we should quit processing it
now. */
- if (j != n_basic_blocks)
+ if (jbb != EXIT_BLOCK_PTR)
continue;
/* I is a header of an inner loop, or block 0 in a subroutine
with no loops at all. */
head = tail = -1;
too_large_failure = 0;
- loop_head = max_hdr[i];
+ loop_head = max_hdr[bb->index];
/* Decrease degree of all I's successors for topological
ordering. */
- for (e = BASIC_BLOCK (i)->succ; e; e = e->succ_next)
+ for (e = bb->succ; e; e = e->succ_next)
if (e->dest != EXIT_BLOCK_PTR)
--degree[e->dest->index];
/* Estimate # insns, and count # blocks in the region. */
num_bbs = 1;
- num_insns = (INSN_LUID (BLOCK_END (i))
- - INSN_LUID (BLOCK_HEAD (i)));
+ num_insns = (INSN_LUID (bb->end)
+ - INSN_LUID (bb->head));
/* Find all loop latches (blocks with back edges to the loop
header) or all the leaf blocks in the cfg has no loops.
@@ -868,17 +868,17 @@ find_rgns (edge_list, dom)
Place those blocks into the queue. */
if (no_loops)
{
- for (j = 0; j < n_basic_blocks; j++)
+ FOR_EACH_BB (jbb)
/* Leaf nodes have only a single successor which must
be EXIT_BLOCK. */
- if (BASIC_BLOCK (j)->succ
- && BASIC_BLOCK (j)->succ->dest == EXIT_BLOCK_PTR
- && BASIC_BLOCK (j)->succ->succ_next == NULL)
+ if (jbb->succ
+ && jbb->succ->dest == EXIT_BLOCK_PTR
+ && jbb->succ->succ_next == NULL)
{
- queue[++tail] = j;
- SET_BIT (in_queue, j);
+ queue[++tail] = jbb->index;
+ SET_BIT (in_queue, jbb->index);
- if (too_large (j, &num_bbs, &num_insns))
+ if (too_large (jbb->index, &num_bbs, &num_insns))
{
too_large_failure = 1;
break;
@@ -889,14 +889,14 @@ find_rgns (edge_list, dom)
{
edge e;
- for (e = BASIC_BLOCK (i)->pred; e; e = e->pred_next)
+ for (e = bb->pred; e; e = e->pred_next)
{
if (e->src == ENTRY_BLOCK_PTR)
continue;
node = e->src->index;
- if (max_hdr[node] == loop_head && node != i)
+ if (max_hdr[node] == loop_head && node != bb->index)
{
/* This is a loop latch. */
queue[++tail] = node;
@@ -958,7 +958,7 @@ find_rgns (edge_list, dom)
tail = -1;
break;
}
- else if (!TEST_BIT (in_queue, node) && node != i)
+ else if (!TEST_BIT (in_queue, node) && node != bb->index)
{
queue[++tail] = node;
SET_BIT (in_queue, node);
@@ -975,12 +975,12 @@ find_rgns (edge_list, dom)
if (tail >= 0 && !too_large_failure)
{
/* Place the loop header into list of region blocks. */
- degree[i] = -1;
- rgn_bb_table[idx] = i;
+ degree[bb->index] = -1;
+ rgn_bb_table[idx] = bb->index;
RGN_NR_BLOCKS (nr_regions) = num_bbs;
RGN_BLOCKS (nr_regions) = idx++;
- CONTAINING_RGN (i) = nr_regions;
- BLOCK_TO_BB (i) = count = 0;
+ CONTAINING_RGN (bb->index) = nr_regions;
+ BLOCK_TO_BB (bb->index) = count = 0;
/* Remove blocks from queue[] when their in degree
becomes zero. Repeat until no blocks are left on the
@@ -1019,14 +1019,14 @@ find_rgns (edge_list, dom)
/* Any block that did not end up in a region is placed into a region
by itself. */
- for (i = 0; i < n_basic_blocks; i++)
- if (degree[i] >= 0)
+ FOR_EACH_BB (bb)
+ if (degree[bb->index] >= 0)
{
- rgn_bb_table[idx] = i;
+ rgn_bb_table[idx] = bb->index;
RGN_NR_BLOCKS (nr_regions) = 1;
RGN_BLOCKS (nr_regions) = idx++;
- CONTAINING_RGN (i) = nr_regions++;
- BLOCK_TO_BB (i) = 0;
+ CONTAINING_RGN (bb->index) = nr_regions++;
+ BLOCK_TO_BB (bb->index) = 0;
}
free (max_hdr);
@@ -1093,7 +1093,7 @@ compute_dom_prob_ps (bb)
if (CONTAINING_RGN (TO_BLOCK (nxt_out_edge)) !=
CONTAINING_RGN (BB_TO_BLOCK (bb)))
++nr_rgn_out_edges;
- SET_BIT (pot_split[bb], EDGE_TO_BIT (nxt_out_edge));
+ SET_BIT (pot_split[bb], EDGE_TO_BIT (nxt_out_edge));
nxt_out_edge = NEXT_OUT (nxt_out_edge);
}
@@ -1194,8 +1194,8 @@ compute_trg_info (trg)
add the TO block to the update block list. This list can end
up with a lot of duplicates. We need to weed them out to avoid
overrunning the end of the bblst_table. */
- update_blocks = (char *) alloca (n_basic_blocks);
- memset (update_blocks, 0, n_basic_blocks);
+ update_blocks = (char *) alloca (last_basic_block);
+ memset (update_blocks, 0, last_basic_block);
update_idx = 0;
for (j = 0; j < el.nr_members; j++)
@@ -1561,17 +1561,17 @@ enum INSN_TRAP_CLASS
/* Non-zero if block bb_to is equal to, or reachable from block bb_from. */
#define IS_REACHABLE(bb_from, bb_to) \
-(bb_from == bb_to \
+ (bb_from == bb_to \
|| IS_RGN_ENTRY (bb_from) \
- || (TEST_BIT (ancestor_edges[bb_to], \
- EDGE_TO_BIT (IN_EDGES (BB_TO_BLOCK (bb_from))))))
+ || (TEST_BIT (ancestor_edges[bb_to], \
+ EDGE_TO_BIT (IN_EDGES (BB_TO_BLOCK (bb_from))))))
/* Non-zero iff the address is comprised from at most 1 register. */
#define CONST_BASED_ADDRESS_P(x) \
(GET_CODE (x) == REG \
- || ((GET_CODE (x) == PLUS || GET_CODE (x) == MINUS \
- || (GET_CODE (x) == LO_SUM)) \
- && (CONSTANT_P (XEXP (x, 0)) \
+ || ((GET_CODE (x) == PLUS || GET_CODE (x) == MINUS \
+ || (GET_CODE (x) == LO_SUM)) \
+ && (CONSTANT_P (XEXP (x, 0)) \
|| CONSTANT_P (XEXP (x, 1)))))
/* Turns on the fed_by_spec_load flag for insns fed by load_insn. */
@@ -2030,7 +2030,7 @@ init_ready_list (ready)
next = NEXT_INSN (insn);
if (INSN_DEP_COUNT (insn) == 0
- && (SCHED_GROUP_P (next) == 0 || ! INSN_P (next)))
+ && (! INSN_P (next) || SCHED_GROUP_P (next) == 0))
ready_add (ready, insn);
if (!(SCHED_GROUP_P (insn)))
target_n_insns++;
@@ -2057,7 +2057,14 @@ init_ready_list (ready)
if (!CANT_MOVE (insn)
&& (!IS_SPECULATIVE_INSN (insn)
- || (insn_issue_delay (insn) <= 3
+ || ((((!targetm.sched.use_dfa_pipeline_interface
+ || !(*targetm.sched.use_dfa_pipeline_interface) ())
+ && insn_issue_delay (insn) <= 3)
+ || (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ()
+ && (recog_memoized (insn) < 0
+ || min_insn_conflict_delay (curr_state,
+ insn, insn) <= 3)))
&& check_live (insn, bb_src)
&& is_exception_free (insn, bb_src, target_bb))))
{
@@ -2069,8 +2076,8 @@ init_ready_list (ready)
next = next_nonnote_insn (insn);
if (INSN_DEP_COUNT (insn) == 0
&& (! next
- || SCHED_GROUP_P (next) == 0
- || ! INSN_P (next)))
+ || ! INSN_P (next)
+ || SCHED_GROUP_P (next) == 0))
ready_add (ready, insn);
}
}
@@ -2165,7 +2172,15 @@ new_ready (next)
&& (!IS_VALID (INSN_BB (next))
|| CANT_MOVE (next)
|| (IS_SPECULATIVE_INSN (next)
- && (insn_issue_delay (next) > 3
+ && (0
+ || (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ()
+ && recog_memoized (next) >= 0
+ && min_insn_conflict_delay (curr_state, next,
+ next) > 3)
+ || ((!targetm.sched.use_dfa_pipeline_interface
+ || !(*targetm.sched.use_dfa_pipeline_interface) ())
+ && insn_issue_delay (next) > 3)
|| !check_live (next, INSN_BB (next))
|| !is_exception_free (next, INSN_BB (next), target_bb)))))
return 0;
@@ -2481,7 +2496,7 @@ propagate_deps (bb, pred_deps)
succ_deps->last_pending_memory_flush
= concat_INSN_LIST (pred_deps->last_pending_memory_flush,
succ_deps->last_pending_memory_flush);
-
+
succ_deps->pending_lists_length += pred_deps->pending_lists_length;
succ_deps->pending_flush_length += pred_deps->pending_flush_length;
@@ -2589,14 +2604,27 @@ debug_dependencies ()
fprintf (sched_dump, "\n;; --- Region Dependences --- b %d bb %d \n",
BB_TO_BLOCK (bb), bb);
- fprintf (sched_dump, ";; %7s%6s%6s%6s%6s%6s%11s%6s\n",
- "insn", "code", "bb", "dep", "prio", "cost", "blockage", "units");
- fprintf (sched_dump, ";; %7s%6s%6s%6s%6s%6s%11s%6s\n",
- "----", "----", "--", "---", "----", "----", "--------", "-----");
+ if (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ())
+ {
+ fprintf (sched_dump, ";; %7s%6s%6s%6s%6s%6s%14s\n",
+ "insn", "code", "bb", "dep", "prio", "cost",
+ "reservation");
+ fprintf (sched_dump, ";; %7s%6s%6s%6s%6s%6s%14s\n",
+ "----", "----", "--", "---", "----", "----",
+ "-----------");
+ }
+ else
+ {
+ fprintf (sched_dump, ";; %7s%6s%6s%6s%6s%6s%11s%6s\n",
+ "insn", "code", "bb", "dep", "prio", "cost", "blockage", "units");
+ fprintf (sched_dump, ";; %7s%6s%6s%6s%6s%6s%11s%6s\n",
+ "----", "----", "--", "---", "----", "----", "--------", "-----");
+ }
+
for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
{
rtx link;
- int unit, range;
if (! INSN_P (insn))
{
@@ -2616,22 +2644,46 @@ debug_dependencies ()
continue;
}
- unit = insn_unit (insn);
- range = (unit < 0
- || function_units[unit].blockage_range_function == 0) ? 0 :
- function_units[unit].blockage_range_function (insn);
- fprintf (sched_dump,
- ";; %s%5d%6d%6d%6d%6d%6d %3d -%3d ",
- (SCHED_GROUP_P (insn) ? "+" : " "),
- INSN_UID (insn),
- INSN_CODE (insn),
- INSN_BB (insn),
- INSN_DEP_COUNT (insn),
- INSN_PRIORITY (insn),
- insn_cost (insn, 0, 0),
- (int) MIN_BLOCKAGE_COST (range),
- (int) MAX_BLOCKAGE_COST (range));
- insn_print_units (insn);
+ if (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ())
+ {
+ fprintf (sched_dump,
+ ";; %s%5d%6d%6d%6d%6d%6d ",
+ (SCHED_GROUP_P (insn) ? "+" : " "),
+ INSN_UID (insn),
+ INSN_CODE (insn),
+ INSN_BB (insn),
+ INSN_DEP_COUNT (insn),
+ INSN_PRIORITY (insn),
+ insn_cost (insn, 0, 0));
+
+ if (recog_memoized (insn) < 0)
+ fprintf (sched_dump, "nothing");
+ else
+ print_reservation (sched_dump, insn);
+ }
+ else
+ {
+ int unit = insn_unit (insn);
+ int range
+ = (unit < 0
+ || function_units[unit].blockage_range_function == 0
+ ? 0
+ : function_units[unit].blockage_range_function (insn));
+ fprintf (sched_dump,
+ ";; %s%5d%6d%6d%6d%6d%6d %3d -%3d ",
+ (SCHED_GROUP_P (insn) ? "+" : " "),
+ INSN_UID (insn),
+ INSN_CODE (insn),
+ INSN_BB (insn),
+ INSN_DEP_COUNT (insn),
+ INSN_PRIORITY (insn),
+ insn_cost (insn, 0, 0),
+ (int) MIN_BLOCKAGE_COST (range),
+ (int) MAX_BLOCKAGE_COST (range));
+ insn_print_units (insn);
+ }
+
fprintf (sched_dump, "\t: ");
for (link = INSN_DEPEND (insn); link; link = XEXP (link, 1))
fprintf (sched_dump, "%d ", INSN_UID (XEXP (link, 0)));
@@ -2835,8 +2887,8 @@ init_regions ()
nr_regions = 0;
rgn_table = (region *) xmalloc ((n_basic_blocks) * sizeof (region));
rgn_bb_table = (int *) xmalloc ((n_basic_blocks) * sizeof (int));
- block_to_bb = (int *) xmalloc ((n_basic_blocks) * sizeof (int));
- containing_rgn = (int *) xmalloc ((n_basic_blocks) * sizeof (int));
+ block_to_bb = (int *) xmalloc ((last_basic_block) * sizeof (int));
+ containing_rgn = (int *) xmalloc ((last_basic_block) * sizeof (int));
/* Compute regions for scheduling. */
if (reload_completed
@@ -2854,11 +2906,9 @@ init_regions ()
}
else
{
- sbitmap *dom;
+ dominance_info dom;
struct edge_list *edge_list;
- dom = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
-
/* The scheduler runs after flow; therefore, we can't blindly call
back into find_basic_blocks since doing so could invalidate the
info in global_live_at_start.
@@ -2873,7 +2923,7 @@ init_regions ()
edge_list = create_edge_list ();
/* Compute the dominators and post dominators. */
- calculate_dominance_info (NULL, dom, CDI_DOMINATORS);
+ dom = calculate_dominance_info (CDI_DOMINATORS);
/* build_control_flow will return nonzero if it detects unreachable
blocks or any other irregularity with the cfg which prevents
@@ -2891,14 +2941,14 @@ init_regions ()
/* For now. This will move as more and more of haifa is converted
to using the cfg code in flow.c. */
- free (dom);
+ free_dominance_info (dom);
}
}
if (CHECK_DEAD_NOTES)
{
- blocks = sbitmap_alloc (n_basic_blocks);
+ blocks = sbitmap_alloc (last_basic_block);
deaths_in_region = (int *) xmalloc (sizeof (int) * nr_regions);
/* Remove all death notes from the subroutine. */
for (rgn = 0; rgn < nr_regions; rgn++)
@@ -2927,14 +2977,13 @@ schedule_insns (dump_file)
sbitmap large_region_blocks, blocks;
int rgn;
int any_large_regions;
+ basic_block bb;
/* Taking care of this degenerate case makes the rest of
this code simpler. */
if (n_basic_blocks == 0)
return;
- scope_to_insns_initialize ();
-
nr_inter = 0;
nr_spec = 0;
@@ -2943,7 +2992,7 @@ schedule_insns (dump_file)
init_regions ();
current_sched_info = &region_sched_info;
-
+
/* Schedule every region in the subroutine. */
for (rgn = 0; rgn < nr_regions; rgn++)
schedule_region (rgn);
@@ -2952,7 +3001,7 @@ schedule_insns (dump_file)
first so that we can verify that live_at_start didn't change. Then
do all other blocks. */
/* ??? There is an outside possibility that update_life_info, or more
- to the point propagate_block, could get called with non-zero flags
+ to the point propagate_block, could get called with nonzero flags
more than once for one basic block. This would be kinda bad if it
were to happen, since REG_INFO would be accumulated twice for the
block, and we'd have twice the REG_DEAD notes.
@@ -2962,13 +3011,15 @@ schedule_insns (dump_file)
best way to test for this kind of thing... */
allocate_reg_life_data ();
- compute_bb_for_insn (get_max_uid ());
+ compute_bb_for_insn ();
any_large_regions = 0;
- large_region_blocks = sbitmap_alloc (n_basic_blocks);
- sbitmap_ones (large_region_blocks);
+ large_region_blocks = sbitmap_alloc (last_basic_block);
+ sbitmap_zero (large_region_blocks);
+ FOR_EACH_BB (bb)
+ SET_BIT (large_region_blocks, bb->index);
- blocks = sbitmap_alloc (n_basic_blocks);
+ blocks = sbitmap_alloc (last_basic_block);
sbitmap_zero (blocks);
/* Update life information. For regions consisting of multiple blocks
@@ -3021,8 +3072,6 @@ schedule_insns (dump_file)
if (write_symbols != NO_DEBUG)
rm_redundant_line_notes ();
- scope_to_insns_finalize ();
-
if (sched_verbose)
{
if (reload_completed == 0 && flag_schedule_interblock)
diff --git a/contrib/gcc/sched-vis.c b/contrib/gcc/sched-vis.c
index 2dd20d0..237d446 100644
--- a/contrib/gcc/sched-vis.c
+++ b/contrib/gcc/sched-vis.c
@@ -30,7 +30,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "hard-reg-set.h"
#include "basic-block.h"
#include "insn-attr.h"
+#include "real.h"
#include "sched-int.h"
+#include "target.h"
#ifdef INSN_SCHEDULING
/* target_units bitmask has 1 for each unit in the cpu. It should be
@@ -38,7 +40,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
But currently it is computed by examining the insn list. Since
this is only needed for visualization, it seems an acceptable
solution. (For understanding the mapping of bits to units, see
- definition of function_units[] in "insn-attrtab.c".) */
+ definition of function_units[] in "insn-attrtab.c".) The scheduler
+ using only DFA description should never use the following variable. */
static int target_units = 0;
@@ -47,7 +50,6 @@ static int get_visual_tbl_length PARAMS ((void));
static void print_exp PARAMS ((char *, rtx, int));
static void print_value PARAMS ((char *, rtx, int));
static void print_pattern PARAMS ((char *, rtx, int));
-static void print_insn PARAMS ((char *, rtx, int));
/* Print names of units on which insn can/should execute, for debugging. */
@@ -122,6 +124,14 @@ get_visual_tbl_length ()
int n, n1;
char *s;
+ if (targetm.sched.use_dfa_pipeline_interface
+ && (*targetm.sched.use_dfa_pipeline_interface) ())
+ {
+ visual_tbl_line_length = 1;
+ return 1; /* Can't return 0 because that will cause problems
+ with alloca. */
+ }
+
/* Compute length of one field in line. */
s = (char *) alloca (INSN_LEN + 6);
sprintf (s, " %33s", "uname");
@@ -551,7 +561,10 @@ print_value (buf, x, verbose)
cur = safe_concat (buf, cur, t);
break;
case CONST_DOUBLE:
- sprintf (t, "<0x%lx,0x%lx>", (long) XWINT (x, 2), (long) XWINT (x, 3));
+ if (FLOAT_MODE_P (GET_MODE (x)))
+ real_to_decimal (t, CONST_DOUBLE_REAL_VALUE (x), sizeof (t), 0, 1);
+ else
+ sprintf (t, "<0x%lx,0x%lx>", (long) XWINT (x, 2), (long) XWINT (x, 3));
cur = safe_concat (buf, cur, t);
break;
case CONST_STRING:
@@ -659,13 +672,13 @@ print_pattern (buf, x, verbose)
&& XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
print_value (t1, XEXP (COND_EXEC_TEST (x), 0), verbose);
else if (GET_CODE (COND_EXEC_TEST (x)) == EQ
- && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
- {
+ && XEXP (COND_EXEC_TEST (x), 1) == const0_rtx)
+ {
t1[0] = '!';
print_value (t1 + 1, XEXP (COND_EXEC_TEST (x), 0), verbose);
}
else
- print_value (t1, COND_EXEC_TEST (x), verbose);
+ print_value (t1, COND_EXEC_TEST (x), verbose);
print_pattern (t2, COND_EXEC_CODE (x), verbose);
sprintf (buf, "(%s) %s", t1, t2);
break;
@@ -684,18 +697,8 @@ print_pattern (buf, x, verbose)
}
break;
case SEQUENCE:
- {
- int i;
-
- sprintf (t1, "%%{");
- for (i = 0; i < XVECLEN (x, 0); i++)
- {
- print_insn (t2, XVECEXP (x, 0, i), verbose);
- sprintf (t3, "%s%s;", t1, t2);
- strcpy (t1, t3);
- }
- sprintf (buf, "%s%%}", t1);
- }
+ /* Should never see SEQUENCE codes until after reorg. */
+ abort ();
break;
case ASM_INPUT:
sprintf (buf, "asm {%s}", XSTR (x, 0));
@@ -749,7 +752,7 @@ print_pattern (buf, x, verbose)
(Probably the last "option" should be extended somehow, since it
depends now on sched.c inner variables ...) */
-static void
+void
print_insn (buf, x, verbose)
char *buf;
rtx x;
@@ -815,7 +818,8 @@ print_insn (buf, x, verbose)
}
} /* print_insn */
-/* Print visualization debugging info. */
+/* Print visualization debugging info. The scheduler using only DFA
+ description should never use the following function. */
void
print_block_visualization (s)
diff --git a/contrib/gcc/sdbout.c b/contrib/gcc/sdbout.c
index 8405c0a..9d5effd 100644
--- a/contrib/gcc/sdbout.c
+++ b/contrib/gcc/sdbout.c
@@ -42,11 +42,15 @@ AT&T C compiler. From the example below I would conclude the following:
*/
#include "config.h"
+#include "system.h"
+#include "debug.h"
+#include "tree.h"
+#include "ggc.h"
+
+static GTY(()) tree anonymous_types;
#ifdef SDB_DEBUGGING_INFO
-#include "system.h"
-#include "tree.h"
#include "rtl.h"
#include "regs.h"
#include "flags.h"
@@ -54,10 +58,9 @@ AT&T C compiler. From the example below I would conclude the following:
#include "reload.h"
#include "output.h"
#include "toplev.h"
-#include "ggc.h"
#include "tm_p.h"
#include "gsyms.h"
-#include "debug.h"
+#include "langhooks.h"
/* 1 if PARM is passed to this function in memory. */
@@ -99,12 +102,12 @@ static void sdbout_end_source_file PARAMS ((unsigned int));
static void sdbout_begin_block PARAMS ((unsigned int, unsigned int));
static void sdbout_end_block PARAMS ((unsigned int, unsigned int));
static void sdbout_source_line PARAMS ((unsigned int, const char *));
-static void sdbout_end_epilogue PARAMS ((void));
+static void sdbout_end_epilogue PARAMS ((unsigned int, const char *));
static void sdbout_global_decl PARAMS ((tree));
#ifndef MIPS_DEBUGGING_INFO
static void sdbout_begin_prologue PARAMS ((unsigned int, const char *));
#endif
-static void sdbout_end_prologue PARAMS ((unsigned int));
+static void sdbout_end_prologue PARAMS ((unsigned int, const char *));
static void sdbout_begin_function PARAMS ((tree));
static void sdbout_end_function PARAMS ((unsigned int));
static void sdbout_toplevel_data PARAMS ((tree));
@@ -299,7 +302,7 @@ static struct sdb_file *current_file;
#endif /* MIPS_DEBUGGING_INFO */
/* The debug hooks structure. */
-struct gcc_debug_hooks sdb_debug_hooks =
+const struct gcc_debug_hooks sdb_debug_hooks =
{
sdbout_init, /* init */
sdbout_finish, /* finish */
@@ -318,7 +321,7 @@ struct gcc_debug_hooks sdb_debug_hooks =
sdbout_end_prologue, /* end_prologue */
#else
sdbout_begin_prologue, /* begin_prologue */
- debug_nothing_int, /* end_prologue */
+ debug_nothing_int_charstar, /* end_prologue */
#endif
sdbout_end_epilogue, /* end_epilogue */
sdbout_begin_function, /* begin_function */
@@ -358,8 +361,7 @@ gen_fake_label ()
char *labelstr;
SDB_GENERATE_FAKE (label, unnamed_struct_number);
unnamed_struct_number++;
- labelstr = (char *) permalloc (strlen (label) + 1);
- strcpy (labelstr, label);
+ labelstr = xstrdup (label);
return labelstr;
}
@@ -781,7 +783,7 @@ sdbout_symbol (decl, local)
if (!DECL_RTL_SET_P (decl))
return;
- SET_DECL_RTL (decl,
+ SET_DECL_RTL (decl,
eliminate_regs (DECL_RTL (decl), 0, NULL_RTX));
#ifdef LEAF_REG_REMAP
if (current_function_uses_only_leaf_regs)
@@ -857,12 +859,12 @@ sdbout_symbol (decl, local)
if (TREE_PUBLIC (decl))
{
PUT_SDB_VAL (XEXP (value, 0));
- PUT_SDB_SCL (C_EXT);
+ PUT_SDB_SCL (C_EXT);
}
else
{
PUT_SDB_VAL (XEXP (value, 0));
- PUT_SDB_SCL (C_STAT);
+ PUT_SDB_SCL (C_STAT);
}
}
else if (regno >= 0)
@@ -922,23 +924,6 @@ sdbout_symbol (decl, local)
PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET (XEXP (value, 0)));
PUT_SDB_SCL (C_AUTO);
}
- else if (GET_CODE (value) == MEM && GET_CODE (XEXP (value, 0)) == CONST)
- {
- /* Handle an obscure case which can arise when optimizing and
- when there are few available registers. (This is *always*
- the case for i386/i486 targets). The DECL_RTL looks like
- (MEM (CONST ...)) even though this variable is a local `auto'
- or a local `register' variable. In effect, what has happened
- is that the reload pass has seen that all assignments and
- references for one such a local variable can be replaced by
- equivalent assignments and references to some static storage
- variable, thereby avoiding the need for a register. In such
- cases we're forced to lie to debuggers and tell them that
- this variable was itself `static'. */
- PUT_SDB_DEF (name);
- PUT_SDB_VAL (XEXP (XEXP (value, 0), 0));
- PUT_SDB_SCL (C_STAT);
- }
else
{
/* It is something we don't know how to represent for SDB. */
@@ -988,8 +973,6 @@ sdbout_toplevel_data (decl)
/* Machinery to record and output anonymous types. */
-static tree anonymous_types;
-
static void
sdbout_queue_anonymous_type (type)
tree type;
@@ -1516,7 +1499,7 @@ static void
sdbout_finish (main_filename)
const char *main_filename ATTRIBUTE_UNUSED;
{
- tree decl = getdecls ();
+ tree decl = (*lang_hooks.decls.getdecls) ();
unsigned int len = list_length (decl);
tree *vec = (tree *) xmalloc (sizeof (tree) * len);
unsigned int i;
@@ -1642,13 +1625,14 @@ sdbout_begin_prologue (line, file)
unsigned int line;
const char *file ATTRIBUTE_UNUSED;
{
- sdbout_end_prologue (line);
+ sdbout_end_prologue (line, file);
}
#endif
static void
-sdbout_end_prologue (line)
+sdbout_end_prologue (line, file)
unsigned int line;
+ const char *file ATTRIBUTE_UNUSED;
{
sdb_begin_function_line = line - 1;
PUT_SDB_FUNCTION_START (line);
@@ -1678,7 +1662,9 @@ sdbout_end_function (line)
Called after the epilogue is output. */
static void
-sdbout_end_epilogue ()
+sdbout_end_epilogue (line, file)
+ unsigned int line ATTRIBUTE_UNUSED;
+ const char *file ATTRIBUTE_UNUSED;
{
const char *const name ATTRIBUTE_UNUSED
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
@@ -1754,15 +1740,18 @@ sdbout_init (input_file_name)
#ifdef RMS_QUICK_HACK_1
tree t;
- for (t = getdecls (); t; t = TREE_CHAIN (t))
+ for (t = (*lang_hooks.decls.getdecls) (); t; t = TREE_CHAIN (t))
if (DECL_NAME (t) && IDENTIFIER_POINTER (DECL_NAME (t)) != 0
&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__vtbl_ptr_type"))
sdbout_symbol (t, 0);
#endif
-
-#ifdef SDB_ALLOW_FORWARD_REFERENCES
- ggc_add_tree_root (&anonymous_types, 1);
-#endif
}
+#else /* SDB_DEBUGGING_INFO */
+
+/* This should never be used, but its address is needed for comparisons. */
+const struct gcc_debug_hooks sdb_debug_hooks;
+
#endif /* SDB_DEBUGGING_INFO */
+
+#include "gt-sdbout.h"
diff --git a/contrib/gcc/sibcall.c b/contrib/gcc/sibcall.c
index fca451f..90863b7 100644
--- a/contrib/gcc/sibcall.c
+++ b/contrib/gcc/sibcall.c
@@ -54,7 +54,7 @@ static rtx skip_unreturned_value PARAMS ((rtx));
/* Examine a CALL_PLACEHOLDER pattern and determine where the call's
return value is located. P_HARD_RETURN receives the hard register
that the function used; P_SOFT_RETURN receives the pseudo register
- that the sequence used. Return non-zero if the values were located. */
+ that the sequence used. Return nonzero if the values were located. */
static int
identify_call_return_value (cp, p_hard_return, p_soft_return)
@@ -86,7 +86,7 @@ identify_call_return_value (cp, p_hard_return, p_soft_return)
/* If we didn't get a single hard register (e.g. a parallel), give up. */
if (GET_CODE (hard) != REG)
return 0;
-
+
/* Stack adjustment done after call may appear here. */
insn = skip_stack_adjustment (insn);
if (! insn)
@@ -101,7 +101,7 @@ identify_call_return_value (cp, p_hard_return, p_soft_return)
insn = NEXT_INSN (insn);
if (! insn)
return 0;
-
+
/* We're looking for a source of the hard return register. */
set = single_set (insn);
if (! set || SET_SRC (set) != hard)
@@ -168,7 +168,7 @@ skip_copy_to_return_value (orig_insn)
/* The destination must be the same as the called function's return
value to ensure that any return value is put in the same place by the
- current function and the function we're calling.
+ current function and the function we're calling.
Further, the source must be the same as the pseudo into which the
called function's return value was copied. Otherwise we're returning
@@ -541,11 +541,11 @@ replace_call_placeholder (insn, use)
sibcall_use_t use;
{
if (use == sibcall_use_tail_recursion)
- emit_insns_before (XEXP (PATTERN (insn), 2), insn);
+ emit_insn_before (XEXP (PATTERN (insn), 2), insn);
else if (use == sibcall_use_sibcall)
- emit_insns_before (XEXP (PATTERN (insn), 1), insn);
+ emit_insn_before (XEXP (PATTERN (insn), 1), insn);
else if (use == sibcall_use_normal)
- emit_insns_before (XEXP (PATTERN (insn), 0), insn);
+ emit_insn_before (XEXP (PATTERN (insn), 0), insn);
else
abort ();
@@ -554,7 +554,7 @@ replace_call_placeholder (insn, use)
pass above from deleting it as unused. */
if (XEXP (PATTERN (insn), 3))
LABEL_PRESERVE_P (XEXP (PATTERN (insn), 3)) = 0;
-
+
/* "Delete" the placeholder insn. */
remove_insn (insn);
}
@@ -580,23 +580,13 @@ optimize_sibling_and_tail_recursive_calls ()
insns = get_insns ();
- /* We do not perform these calls when flag_exceptions is true, so this
- is probably a NOP at the current time. However, we may want to support
- sibling and tail recursion optimizations in the future, so let's plan
- ahead and find all the EH labels. */
- find_exception_handler_labels ();
-
- rebuild_jump_labels (insns);
- /* We need cfg information to determine which blocks are succeeded
- only by the epilogue. */
- find_basic_blocks (insns, max_reg_num (), 0);
cleanup_cfg (CLEANUP_PRE_SIBCALL | CLEANUP_PRE_LOOP);
/* If there are no basic blocks, then there is nothing to do. */
if (n_basic_blocks == 0)
return;
- /* If we are using sjlj exceptions, we may need to add a call to
+ /* If we are using sjlj exceptions, we may need to add a call to
_Unwind_SjLj_Unregister at exit of the function. Which means
that we cannot do any sibcall transformations. */
if (USING_SJLJ_EXCEPTIONS && current_function_has_exception_handlers ())
@@ -620,7 +610,7 @@ optimize_sibling_and_tail_recursive_calls ()
/* Walk forwards through the last normal block and see if it
does nothing except fall into the exit block. */
- for (insn = BLOCK_HEAD (n_basic_blocks - 1);
+ for (insn = EXIT_BLOCK_PTR->prev_bb->head;
insn;
insn = NEXT_INSN (insn))
{
@@ -686,8 +676,7 @@ optimize_sibling_and_tail_recursive_calls ()
sibling call optimizations, but not tail recursion.
Similarly if we use varargs or stdarg since they implicitly
may take the address of an argument. */
- if (current_function_calls_alloca
- || current_function_varargs || current_function_stdarg)
+ if (current_function_calls_alloca || current_function_stdarg)
sibcall = 0;
/* See if there are any reasons we can't perform either sibling or
@@ -720,8 +709,8 @@ optimize_sibling_and_tail_recursive_calls ()
successful_replacement = true;
replaced_call_placeholder = true;
- replace_call_placeholder (insn,
- tailrecursion != 0
+ replace_call_placeholder (insn,
+ tailrecursion != 0
? sibcall_use_tail_recursion
: sibcall != 0
? sibcall_use_sibcall
@@ -735,11 +724,11 @@ optimize_sibling_and_tail_recursive_calls ()
tree arg;
/* A sibling call sequence invalidates any REG_EQUIV notes made for
- this function's incoming arguments.
+ this function's incoming arguments.
At the start of RTL generation we know the only REG_EQUIV notes
in the rtl chain are those for incoming arguments, so we can safely
- flush any REG_EQUIV note.
+ flush any REG_EQUIV note.
This is (slight) overkill. We could keep track of the highest
argument we clobber and be more selective in removing notes, but it
@@ -749,7 +738,7 @@ optimize_sibling_and_tail_recursive_calls ()
/* A sibling call sequence also may invalidate RTX_UNCHANGING_P
flag of some incoming arguments MEM RTLs, because it can write into
those slots. We clear all those bits now.
-
+
This is (slight) overkill, we could keep track of which arguments
we actually write into. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
@@ -759,9 +748,9 @@ optimize_sibling_and_tail_recursive_calls ()
}
/* Similarly, invalidate RTX_UNCHANGING_P for any incoming
- arguments passed in registers. */
- for (arg = DECL_ARGUMENTS (current_function_decl);
- arg;
+ arguments passed in registers. */
+ for (arg = DECL_ARGUMENTS (current_function_decl);
+ arg;
arg = TREE_CHAIN (arg))
{
if (REG_P (DECL_RTL (arg)))
@@ -769,7 +758,7 @@ optimize_sibling_and_tail_recursive_calls ()
}
}
- /* There may have been NOTE_INSN_BLOCK_{BEGIN,END} notes in the
+ /* There may have been NOTE_INSN_BLOCK_{BEGIN,END} notes in the
CALL_PLACEHOLDER alternatives that we didn't emit. Rebuild the
lexical block tree to correspond to the notes that still exist. */
if (replaced_call_placeholder)
@@ -777,4 +766,5 @@ optimize_sibling_and_tail_recursive_calls ()
/* This information will be invalid after inline expansion. Kill it now. */
free_basic_block_vars (0);
+ free_EXPR_LIST_list (&tail_recursion_label_list);
}
diff --git a/contrib/gcc/simplify-rtx.c b/contrib/gcc/simplify-rtx.c
index 2896041..eca2945 100644
--- a/contrib/gcc/simplify-rtx.c
+++ b/contrib/gcc/simplify-rtx.c
@@ -1,6 +1,6 @@
/* RTL simplification functions for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -22,8 +22,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
-
#include "rtl.h"
+#include "tree.h"
#include "tm_p.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -43,26 +43,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
virtual regs here because the simplify_*_operation routines are called
by integrate.c, which is called before virtual register instantiation.
- ?!? FIXED_BASE_PLUS_P and NONZERO_BASE_PLUS_P need to move into
+ ?!? NONZERO_BASE_PLUS_P needs to move into
a header file so that their definitions can be shared with the
simplification routines in simplify-rtx.c. Until then, do not
- change these macros without also changing the copy in simplify-rtx.c. */
-
-#define FIXED_BASE_PLUS_P(X) \
- ((X) == frame_pointer_rtx || (X) == hard_frame_pointer_rtx \
- || ((X) == arg_pointer_rtx && fixed_regs[ARG_POINTER_REGNUM])\
- || (X) == virtual_stack_vars_rtx \
- || (X) == virtual_incoming_args_rtx \
- || (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && (XEXP (X, 0) == frame_pointer_rtx \
- || XEXP (X, 0) == hard_frame_pointer_rtx \
- || ((X) == arg_pointer_rtx \
- && fixed_regs[ARG_POINTER_REGNUM]) \
- || XEXP (X, 0) == virtual_stack_vars_rtx \
- || XEXP (X, 0) == virtual_incoming_args_rtx)) \
- || GET_CODE (X) == ADDRESSOF)
+ change this macro without also changing the copy in simplify-rtx.c. */
-/* Similar, but also allows reference to the stack pointer.
+/* Allows reference to the stack pointer.
This used to include FIXED_BASE_PLUS_P, however, we can't assume that
arg_pointer_rtx by itself is nonzero, because on at least one machine,
@@ -101,13 +87,6 @@ static int simplify_plus_minus_op_data_cmp PARAMS ((const void *,
static rtx simplify_plus_minus PARAMS ((enum rtx_code,
enum machine_mode, rtx,
rtx, int));
-static void check_fold_consts PARAMS ((PTR));
-#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
-static void simplify_unary_real PARAMS ((PTR));
-static void simplify_binary_real PARAMS ((PTR));
-#endif
-static void simplify_binary_is2orm1 PARAMS ((PTR));
-
/* Negate a CONST_INT rtx, truncating (because a conversion from a
maximally negative number can overflow). */
@@ -116,11 +95,11 @@ neg_const_int (mode, i)
enum machine_mode mode;
rtx i;
{
- return GEN_INT (trunc_int_for_mode (- INTVAL (i), mode));
+ return gen_int_mode (- INTVAL (i), mode);
}
-/* Make a binary operation by properly ordering the operands and
+/* Make a binary operation by properly ordering the operands and
seeing if the expression folds. */
rtx
@@ -167,6 +146,9 @@ avoid_constant_pool_reference (x)
return x;
addr = XEXP (x, 0);
+ if (GET_CODE (addr) == LO_SUM)
+ addr = XEXP (addr, 1);
+
if (GET_CODE (addr) != SYMBOL_REF
|| ! CONSTANT_POOL_ADDRESS_P (addr))
return x;
@@ -239,6 +221,31 @@ simplify_gen_relational (code, mode, cmp_mode, op0, op1)
if ((tem = simplify_relational_operation (code, cmp_mode, op0, op1)) != 0)
return tem;
+ /* For the following tests, ensure const0_rtx is op1. */
+ if (op0 == const0_rtx && swap_commutative_operands_p (op0, op1))
+ tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);
+
+ /* If op0 is a compare, extract the comparison arguments from it. */
+ if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
+ op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
+
+ /* If op0 is a comparison, extract the comparison arguments form it. */
+ if (code == NE && op1 == const0_rtx
+ && GET_RTX_CLASS (GET_CODE (op0)) == '<')
+ return op0;
+ else if (code == EQ && op1 == const0_rtx)
+ {
+ /* The following tests GET_RTX_CLASS (GET_CODE (op0)) == '<'. */
+ enum rtx_code new = reversed_comparison_code (op0, NULL_RTX);
+ if (new != UNKNOWN)
+ {
+ code = new;
+ mode = cmp_mode;
+ op1 = XEXP (op0, 1);
+ op0 = XEXP (op0, 0);
+ }
+ }
+
/* Put complex operands first and constants second. */
if (swap_commutative_operands_p (op0, op1))
tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);
@@ -307,7 +314,7 @@ simplify_replace_rtx (x, old, new)
rtx op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
return
- simplify_gen_ternary (code, mode,
+ simplify_gen_ternary (code, mode,
(op_mode != VOIDmode
? op_mode
: GET_MODE (op0)),
@@ -331,79 +338,36 @@ simplify_replace_rtx (x, old, new)
}
return x;
- default:
- if (GET_CODE (x) == MEM)
- return
- replace_equiv_address_nv (x,
- simplify_replace_rtx (XEXP (x, 0),
- old, new));
-
- return x;
- }
- return x;
-}
-
-#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
-/* Subroutine of simplify_unary_operation, called via do_float_handler.
- Handles simplification of unary ops on floating point values. */
-struct simplify_unary_real_args
-{
- rtx operand;
- rtx result;
- enum machine_mode mode;
- enum rtx_code code;
- bool want_integer;
-};
-#define REAL_VALUE_ABS(d_) \
- (REAL_VALUE_NEGATIVE (d_) ? REAL_VALUE_NEGATE (d_) : (d_))
-
-static void
-simplify_unary_real (p)
- PTR p;
-{
- REAL_VALUE_TYPE d;
-
- struct simplify_unary_real_args *args =
- (struct simplify_unary_real_args *) p;
-
- REAL_VALUE_FROM_CONST_DOUBLE (d, args->operand);
+ case 'o':
+ if (code == MEM)
+ return replace_equiv_address_nv (x,
+ simplify_replace_rtx (XEXP (x, 0),
+ old, new));
+ else if (code == LO_SUM)
+ {
+ rtx op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
+ rtx op1 = simplify_replace_rtx (XEXP (x, 1), old, new);
- if (args->want_integer)
- {
- HOST_WIDE_INT i;
+ /* (lo_sum (high x) x) -> x */
+ if (GET_CODE (op0) == HIGH && rtx_equal_p (XEXP (op0, 0), op1))
+ return op1;
- switch (args->code)
- {
- case FIX: i = REAL_VALUE_FIX (d); break;
- case UNSIGNED_FIX: i = REAL_VALUE_UNSIGNED_FIX (d); break;
- default:
- abort ();
+ return gen_rtx_LO_SUM (mode, op0, op1);
}
- args->result = GEN_INT (trunc_int_for_mode (i, args->mode));
- }
- else
- {
- switch (args->code)
+ else if (code == REG)
{
- case SQRT:
- /* We don't attempt to optimize this. */
- args->result = 0;
- return;
-
- case ABS: d = REAL_VALUE_ABS (d); break;
- case NEG: d = REAL_VALUE_NEGATE (d); break;
- case FLOAT_TRUNCATE: d = real_value_truncate (args->mode, d); break;
- case FLOAT_EXTEND: /* All this does is change the mode. */ break;
- case FIX: d = REAL_VALUE_RNDZINT (d); break;
- case UNSIGNED_FIX: d = REAL_VALUE_UNSIGNED_RNDZINT (d); break;
- default:
- abort ();
+ if (REG_P (old) && REGNO (x) == REGNO (old))
+ return new;
}
- args->result = CONST_DOUBLE_FROM_REAL_VALUE (d, args->mode);
+
+ return x;
+
+ default:
+ return x;
}
+ return x;
}
-#endif
-
+
/* Try to simplify a unary operation CODE whose output mode is to be
MODE with input operand OP whose mode was originally OP_MODE.
Return zero if no simplification can be made. */
@@ -417,12 +381,48 @@ simplify_unary_operation (code, mode, op, op_mode)
unsigned int width = GET_MODE_BITSIZE (mode);
rtx trueop = avoid_constant_pool_reference (op);
+ if (code == VEC_DUPLICATE)
+ {
+ if (!VECTOR_MODE_P (mode))
+ abort ();
+ if (GET_MODE (trueop) != VOIDmode
+ && !VECTOR_MODE_P (GET_MODE (trueop))
+ && GET_MODE_INNER (mode) != GET_MODE (trueop))
+ abort ();
+ if (GET_MODE (trueop) != VOIDmode
+ && VECTOR_MODE_P (GET_MODE (trueop))
+ && GET_MODE_INNER (mode) != GET_MODE_INNER (GET_MODE (trueop)))
+ abort ();
+ if (GET_CODE (trueop) == CONST_INT || GET_CODE (trueop) == CONST_DOUBLE
+ || GET_CODE (trueop) == CONST_VECTOR)
+ {
+ int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
+ unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
+ rtvec v = rtvec_alloc (n_elts);
+ unsigned int i;
+
+ if (GET_CODE (trueop) != CONST_VECTOR)
+ for (i = 0; i < n_elts; i++)
+ RTVEC_ELT (v, i) = trueop;
+ else
+ {
+ enum machine_mode inmode = GET_MODE (trueop);
+ int in_elt_size = GET_MODE_SIZE (GET_MODE_INNER (inmode));
+ unsigned in_n_elts = (GET_MODE_SIZE (inmode) / in_elt_size);
+
+ if (in_n_elts >= n_elts || n_elts % in_n_elts)
+ abort ();
+ for (i = 0; i < n_elts; i++)
+ RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop, i % in_n_elts);
+ }
+ return gen_rtx_CONST_VECTOR (mode, v);
+ }
+ }
+
/* The order of these tests is critical so that, for example, we don't
check the wrong mode (input vs. output) for a conversion operation,
such as FIX. At some point, this should be simplified. */
-#if !defined(REAL_IS_NOT_DOUBLE) || defined(REAL_ARITHMETIC)
-
if (code == FLOAT && GET_MODE (trueop) == VOIDmode
&& (GET_CODE (trueop) == CONST_DOUBLE || GET_CODE (trueop) == CONST_INT))
{
@@ -434,25 +434,7 @@ simplify_unary_operation (code, mode, op, op_mode)
else
lv = CONST_DOUBLE_LOW (trueop), hv = CONST_DOUBLE_HIGH (trueop);
-#ifdef REAL_ARITHMETIC
REAL_VALUE_FROM_INT (d, lv, hv, mode);
-#else
- if (hv < 0)
- {
- d = (double) (~ hv);
- d *= ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))
- * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)));
- d += (double) (unsigned HOST_WIDE_INT) (~ lv);
- d = (- d - 1.0);
- }
- else
- {
- d = (double) hv;
- d *= ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))
- * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)));
- d += (double) (unsigned HOST_WIDE_INT) lv;
- }
-#endif /* REAL_ARITHMETIC */
d = real_value_truncate (mode, d);
return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
}
@@ -480,19 +462,10 @@ simplify_unary_operation (code, mode, op, op_mode)
else
hv = 0, lv &= GET_MODE_MASK (op_mode);
-#ifdef REAL_ARITHMETIC
REAL_VALUE_FROM_UNSIGNED_INT (d, lv, hv, mode);
-#else
-
- d = (double) (unsigned HOST_WIDE_INT) hv;
- d *= ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))
- * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)));
- d += (double) (unsigned HOST_WIDE_INT) lv;
-#endif /* REAL_ARITHMETIC */
d = real_value_truncate (mode, d);
return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
}
-#endif
if (GET_CODE (trueop) == CONST_INT
&& width <= HOST_BITS_PER_WIDE_INT && width > 0)
@@ -668,20 +641,38 @@ simplify_unary_operation (code, mode, op, op_mode)
return immed_double_const (lv, hv, mode);
}
-#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
else if (GET_CODE (trueop) == CONST_DOUBLE
&& GET_MODE_CLASS (mode) == MODE_FLOAT)
{
- struct simplify_unary_real_args args;
- args.operand = trueop;
- args.mode = mode;
- args.code = code;
- args.want_integer = false;
+ REAL_VALUE_TYPE d;
+ REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
- if (do_float_handler (simplify_unary_real, (PTR) &args))
- return args.result;
+ switch (code)
+ {
+ case SQRT:
+ /* We don't attempt to optimize this. */
+ return 0;
- return 0;
+ case ABS:
+ d = REAL_VALUE_ABS (d);
+ break;
+ case NEG:
+ d = REAL_VALUE_NEGATE (d);
+ break;
+ case FLOAT_TRUNCATE:
+ d = real_value_truncate (mode, d);
+ break;
+ case FLOAT_EXTEND:
+ /* All this does is change the mode. */
+ break;
+ case FIX:
+ real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL);
+ break;
+
+ default:
+ abort ();
+ }
+ return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
}
else if (GET_CODE (trueop) == CONST_DOUBLE
@@ -689,18 +680,19 @@ simplify_unary_operation (code, mode, op, op_mode)
&& GET_MODE_CLASS (mode) == MODE_INT
&& width <= HOST_BITS_PER_WIDE_INT && width > 0)
{
- struct simplify_unary_real_args args;
- args.operand = trueop;
- args.mode = mode;
- args.code = code;
- args.want_integer = true;
-
- if (do_float_handler (simplify_unary_real, (PTR) &args))
- return args.result;
-
- return 0;
+ HOST_WIDE_INT i;
+ REAL_VALUE_TYPE d;
+ REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
+ switch (code)
+ {
+ case FIX: i = REAL_VALUE_FIX (d); break;
+ case UNSIGNED_FIX: i = REAL_VALUE_UNSIGNED_FIX (d); break;
+ default:
+ abort ();
+ }
+ return gen_int_mode (i, mode);
}
-#endif
+
/* This was formerly used only for non-IEEE float.
eggert@twinsun.com says it is safe for IEEE also. */
else
@@ -765,7 +757,7 @@ simplify_unary_operation (code, mode, op, op_mode)
return convert_memory_address (Pmode, op);
break;
#endif
-
+
default:
break;
}
@@ -774,96 +766,6 @@ simplify_unary_operation (code, mode, op, op_mode)
}
}
-#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
-/* Subroutine of simplify_binary_operation, called via do_float_handler.
- Handles simplification of binary ops on floating point values. */
-struct simplify_binary_real_args
-{
- rtx trueop0, trueop1;
- rtx result;
- enum rtx_code code;
- enum machine_mode mode;
-};
-
-static void
-simplify_binary_real (p)
- PTR p;
-{
- REAL_VALUE_TYPE f0, f1, value;
- struct simplify_binary_real_args *args =
- (struct simplify_binary_real_args *) p;
-
- REAL_VALUE_FROM_CONST_DOUBLE (f0, args->trueop0);
- REAL_VALUE_FROM_CONST_DOUBLE (f1, args->trueop1);
- f0 = real_value_truncate (args->mode, f0);
- f1 = real_value_truncate (args->mode, f1);
-
-#ifdef REAL_ARITHMETIC
-#ifndef REAL_INFINITY
- if (args->code == DIV && REAL_VALUES_EQUAL (f1, dconst0))
- {
- args->result = 0;
- return;
- }
-#endif
- REAL_ARITHMETIC (value, rtx_to_tree_code (args->code), f0, f1);
-#else
- switch (args->code)
- {
- case PLUS:
- value = f0 + f1;
- break;
- case MINUS:
- value = f0 - f1;
- break;
- case MULT:
- value = f0 * f1;
- break;
- case DIV:
-#ifndef REAL_INFINITY
- if (f1 == 0)
- return 0;
-#endif
- value = f0 / f1;
- break;
- case SMIN:
- value = MIN (f0, f1);
- break;
- case SMAX:
- value = MAX (f0, f1);
- break;
- default:
- abort ();
- }
-#endif
-
- value = real_value_truncate (args->mode, value);
- args->result = CONST_DOUBLE_FROM_REAL_VALUE (value, args->mode);
-}
-#endif
-
-/* Another subroutine called via do_float_handler. This one tests
- the floating point value given against 2. and -1. */
-struct simplify_binary_is2orm1_args
-{
- rtx value;
- bool is_2;
- bool is_m1;
-};
-
-static void
-simplify_binary_is2orm1 (p)
- PTR p;
-{
- REAL_VALUE_TYPE d;
- struct simplify_binary_is2orm1_args *args =
- (struct simplify_binary_is2orm1_args *) p;
-
- REAL_VALUE_FROM_CONST_DOUBLE (d, args->value);
- args->is_2 = REAL_VALUES_EQUAL (d, dconst2);
- args->is_m1 = REAL_VALUES_EQUAL (d, dconstm1);
-}
-
/* Simplify a binary operation CODE with result mode MODE, operating on OP0
and OP1. Return 0 if no simplification is possible.
@@ -898,23 +800,28 @@ simplify_binary_operation (code, mode, op0, op1)
tem = trueop0, trueop0 = trueop1, trueop1 = tem;
}
-#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
if (GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_CODE (trueop0) == CONST_DOUBLE
&& GET_CODE (trueop1) == CONST_DOUBLE
&& mode == GET_MODE (op0) && mode == GET_MODE (op1))
{
- struct simplify_binary_real_args args;
- args.trueop0 = trueop0;
- args.trueop1 = trueop1;
- args.mode = mode;
- args.code = code;
-
- if (do_float_handler (simplify_binary_real, (PTR) &args))
- return args.result;
- return 0;
+ REAL_VALUE_TYPE f0, f1, value;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (f0, trueop0);
+ REAL_VALUE_FROM_CONST_DOUBLE (f1, trueop1);
+ f0 = real_value_truncate (mode, f0);
+ f1 = real_value_truncate (mode, f1);
+
+ if (code == DIV
+ && !MODE_HAS_INFINITIES (mode)
+ && REAL_VALUES_EQUAL (f1, dconst0))
+ return 0;
+
+ REAL_ARITHMETIC (value, rtx_to_tree_code (code), f0, f1);
+
+ value = real_value_truncate (mode, value);
+ return CONST_DOUBLE_FROM_REAL_VALUE (value, mode);
}
-#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
/* We can fold some multi-word operations. */
if (GET_MODE_CLASS (mode) == MODE_INT
@@ -1049,16 +956,15 @@ simplify_binary_operation (code, mode, op0, op1)
switch (code)
{
case PLUS:
- /* In IEEE floating point, x+0 is not the same as x. Similarly
- for the other optimizations below. */
- if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
- && FLOAT_MODE_P (mode) && ! flag_unsafe_math_optimizations)
- break;
-
- if (trueop1 == CONST0_RTX (mode))
+ /* Maybe simplify x + 0 to x. The two expressions are equivalent
+ when x is NaN, infinite, or finite and nonzero. They aren't
+ when x is -0 and the rounding mode is not towards -infinity,
+ since (-0) + 0 is then 0. */
+ if (!HONOR_SIGNED_ZEROS (mode) && trueop1 == CONST0_RTX (mode))
return op0;
- /* ((-a) + b) -> (b - a) and similarly for (a + (-b)) */
+ /* ((-a) + b) -> (b - a) and similarly for (a + (-b)). These
+ transformations are safe even for IEEE. */
if (GET_CODE (op0) == NEG)
return simplify_gen_binary (MINUS, mode, op1, XEXP (op0, 0));
else if (GET_CODE (op1) == NEG)
@@ -1138,7 +1044,7 @@ simplify_binary_operation (code, mode, op0, op1)
}
/* If one of the operands is a PLUS or a MINUS, see if we can
- simplify this by the associative law.
+ simplify this by the associative law.
Don't use the associative law for floating point.
The inaccuracy makes it nonassociative,
and subtle programs can break if operations are associated. */
@@ -1187,15 +1093,9 @@ simplify_binary_operation (code, mode, op0, op1)
#endif
return xop00;
}
- break;
+ break;
case MINUS:
- /* None of these optimizations can be done for IEEE
- floating point. */
- if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
- && FLOAT_MODE_P (mode) && ! flag_unsafe_math_optimizations)
- break;
-
/* We can't assume x-x is 0 even with non-IEEE floating point,
but since it is zero except in very strange circumstances, we
will treat it as zero with -funsafe-math-optimizations. */
@@ -1204,16 +1104,23 @@ simplify_binary_operation (code, mode, op0, op1)
&& (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations))
return CONST0_RTX (mode);
- /* Change subtraction from zero into negation. */
- if (trueop0 == CONST0_RTX (mode))
+ /* Change subtraction from zero into negation. (0 - x) is the
+ same as -x when x is NaN, infinite, or finite and nonzero.
+ But if the mode has signed zeros, and does not round towards
+ -infinity, then 0 - 0 is 0, not -0. */
+ if (!HONOR_SIGNED_ZEROS (mode) && trueop0 == CONST0_RTX (mode))
return gen_rtx_NEG (mode, op1);
/* (-1 - a) is ~a. */
if (trueop0 == constm1_rtx)
return gen_rtx_NOT (mode, op1);
- /* Subtracting 0 has no effect. */
- if (trueop1 == CONST0_RTX (mode))
+ /* Subtracting 0 has no effect unless the mode has signed zeros
+ and supports rounding towards -infinity. In such a case,
+ 0 - 0 is -0. */
+ if (!(HONOR_SIGNED_ZEROS (mode)
+ && HONOR_SIGN_DEPENDENT_ROUNDING (mode))
+ && trueop1 == CONST0_RTX (mode))
return op0;
/* See if this is something like X * C - X or vice versa or
@@ -1270,12 +1177,12 @@ simplify_binary_operation (code, mode, op0, op1)
}
}
- /* (a - (-b)) -> (a + b). */
+ /* (a - (-b)) -> (a + b). True even for IEEE. */
if (GET_CODE (op1) == NEG)
return simplify_gen_binary (PLUS, mode, op0, XEXP (op1, 0));
/* If one of the operands is a PLUS or a MINUS, see if we can
- simplify this by the associative law.
+ simplify this by the associative law.
Don't use the associative law for floating point.
The inaccuracy makes it nonassociative,
and subtle programs can break if operations are associated. */
@@ -1316,17 +1223,20 @@ simplify_binary_operation (code, mode, op0, op1)
return tem ? tem : gen_rtx_NEG (mode, op0);
}
- /* In IEEE floating point, x*0 is not always 0. */
- if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
+ /* Maybe simplify x * 0 to 0. The reduction is not valid if
+ x is NaN, since x * 0 is then also NaN. Nor is it valid
+ when the mode has signed zeros, since multiplying a negative
+ number by 0 will give -0, not 0. */
+ if (!HONOR_NANS (mode)
+ && !HONOR_SIGNED_ZEROS (mode)
&& trueop1 == CONST0_RTX (mode)
&& ! side_effects_p (op0))
return op1;
- /* In IEEE floating point, x*1 is not equivalent to x for nans.
- However, ANSI says we can drop signals,
- so we can do this anyway. */
- if (trueop1 == CONST1_RTX (mode))
+ /* In IEEE floating point, x*1 is not equivalent to x for
+ signalling NaNs. */
+ if (!HONOR_SNANS (mode)
+ && trueop1 == CONST1_RTX (mode))
return op0;
/* Convert multiply by constant power of two into shift unless
@@ -1341,20 +1251,18 @@ simplify_binary_operation (code, mode, op0, op1)
&& ! rtx_equal_function_value_matters)
return gen_rtx_ASHIFT (mode, op0, GEN_INT (val));
+ /* x*2 is x+x and x*(-1) is -x */
if (GET_CODE (trueop1) == CONST_DOUBLE
- && GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT)
+ && GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT
+ && GET_MODE (op0) == mode)
{
- struct simplify_binary_is2orm1_args args;
-
- args.value = trueop1;
- if (! do_float_handler (simplify_binary_is2orm1, (PTR) &args))
- return 0;
+ REAL_VALUE_TYPE d;
+ REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
- /* x*2 is x+x and x*(-1) is -x */
- if (args.is_2 && GET_MODE (op0) == mode)
+ if (REAL_VALUES_EQUAL (d, dconst2))
return gen_rtx_PLUS (mode, op0, copy_rtx (op0));
- else if (args.is_m1 && GET_MODE (op0) == mode)
+ if (REAL_VALUES_EQUAL (d, dconstm1))
return gen_rtx_NEG (mode, op0);
}
break;
@@ -1429,14 +1337,16 @@ simplify_binary_operation (code, mode, op0, op1)
return op0;
}
- /* In IEEE floating point, 0/x is not always 0. */
- if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
+ /* Maybe change 0 / x to 0. This transformation isn't safe for
+ modes with NaNs, since 0 / 0 will then be NaN rather than 0.
+ Nor is it safe for modes with signed zeros, since dividing
+ 0 by a negative number gives -0, not 0. */
+ if (!HONOR_NANS (mode)
+ && !HONOR_SIGNED_ZEROS (mode)
&& trueop0 == CONST0_RTX (mode)
&& ! side_effects_p (op1))
return op0;
-#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
/* Change division by a constant into multiplication. Only do
this with -funsafe-math-optimizations. */
else if (GET_CODE (trueop1) == CONST_DOUBLE
@@ -1449,18 +1359,11 @@ simplify_binary_operation (code, mode, op0, op1)
if (! REAL_VALUES_EQUAL (d, dconst0))
{
-#if defined (REAL_ARITHMETIC)
REAL_ARITHMETIC (d, rtx_to_tree_code (DIV), dconst1, d);
- return gen_rtx_MULT (mode, op0,
+ return gen_rtx_MULT (mode, op0,
CONST_DOUBLE_FROM_REAL_VALUE (d, mode));
-#else
- return
- gen_rtx_MULT (mode, op0,
- CONST_DOUBLE_FROM_REAL_VALUE (1./d, mode));
-#endif
}
}
-#endif
break;
case UMOD:
@@ -1497,14 +1400,14 @@ simplify_binary_operation (code, mode, op0, op1)
break;
case SMIN:
- if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT
+ if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT
&& INTVAL (trueop1) == (HOST_WIDE_INT) 1 << (width -1)
&& ! side_effects_p (op0))
return op1;
else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
return op0;
break;
-
+
case SMAX:
if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT
&& ((unsigned HOST_WIDE_INT) INTVAL (trueop1)
@@ -1521,7 +1424,7 @@ simplify_binary_operation (code, mode, op0, op1)
else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
return op0;
break;
-
+
case UMAX:
if (trueop1 == constm1_rtx && ! side_effects_p (op0))
return op1;
@@ -1536,10 +1439,14 @@ simplify_binary_operation (code, mode, op0, op1)
/* ??? There are simplifications that can be done. */
return 0;
+ case VEC_SELECT:
+ case VEC_CONCAT:
+ return 0;
+
default:
abort ();
}
-
+
return 0;
}
@@ -1726,9 +1633,9 @@ simplify_binary_operation (code, mode, op0, op1)
Rather than test for specific case, we do this by a brute-force method
and do all possible simplifications until no more changes occur. Then
- we rebuild the operation.
+ we rebuild the operation.
- If FORCE is true, then always generate the rtx. This is used to
+ If FORCE is true, then always generate the rtx. This is used to
canonicalize stuff emitted from simplify_gen_binary. Note that this
can still fail if the rtx is too complex. It won't fail just because
the result is not 'simpler' than the input, however. */
@@ -1765,7 +1672,7 @@ simplify_plus_minus (code, mode, op0, op1, force)
int i, j;
memset ((char *) ops, 0, sizeof ops);
-
+
/* Set up the two operands and then expand them until nothing has been
changed. If we run out of room in our array, give up; this should
almost never happen. */
@@ -1889,7 +1796,7 @@ simplify_plus_minus (code, mode, op0, op1, force)
tem = simplify_binary_operation (ncode, mode, lhs, rhs);
- /* Reject "simplifications" that just wrap the two
+ /* Reject "simplifications" that just wrap the two
arguments in a CONST. Failure to do so can result
in infinite recursion with simplify_binary_operation
when it calls us to simplify CONST operations. */
@@ -1961,7 +1868,7 @@ simplify_plus_minus (code, mode, op0, op1, force)
is also an improvement, so accept it. */
if (!force
&& (n_ops + n_consts > input_ops
- || (n_ops + n_consts == input_ops && n_consts <= input_consts)))
+ || (n_ops + n_consts == input_ops && n_consts <= input_consts)))
return NULL_RTX;
/* Put a non-negated operand first. If there aren't any, make all
@@ -1993,35 +1900,6 @@ simplify_plus_minus (code, mode, op0, op1, force)
return negate ? gen_rtx_NEG (mode, result) : result;
}
-struct cfc_args
-{
- rtx op0, op1; /* Input */
- int equal, op0lt, op1lt; /* Output */
- int unordered;
-};
-
-static void
-check_fold_consts (data)
- PTR data;
-{
- struct cfc_args *args = (struct cfc_args *) data;
- REAL_VALUE_TYPE d0, d1;
-
- /* We may possibly raise an exception while reading the value. */
- args->unordered = 1;
- REAL_VALUE_FROM_CONST_DOUBLE (d0, args->op0);
- REAL_VALUE_FROM_CONST_DOUBLE (d1, args->op1);
-
- /* Comparisons of Inf versus Inf are ordered. */
- if (REAL_VALUE_ISNAN (d0)
- || REAL_VALUE_ISNAN (d1))
- return;
- args->equal = REAL_VALUES_EQUAL (d0, d1);
- args->op0lt = REAL_VALUES_LESS (d0, d1);
- args->op1lt = REAL_VALUES_LESS (d1, d0);
- args->unordered = 0;
-}
-
/* Like simplify_binary_operation except used for relational operators.
MODE is the mode of the operands, not that of the result. If MODE
is VOIDmode, both operands must also be VOIDmode and we compare the
@@ -2094,32 +1972,26 @@ simplify_relational_operation (code, mode, op0, op1)
if (flag_unsafe_math_optimizations && code == UNORDERED)
return const0_rtx;
- /* For non-IEEE floating-point, if the two operands are equal, we know the
- result. */
- if (rtx_equal_p (trueop0, trueop1)
- && (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
- || ! FLOAT_MODE_P (GET_MODE (trueop0))
- || flag_unsafe_math_optimizations))
+ /* For modes without NaNs, if the two operands are equal, we know the
+ result. Nevertheless, don't discard them if they have side-effects. */
+ if (!HONOR_NANS (GET_MODE (trueop0))
+ && rtx_equal_p (trueop0, trueop1)
+ && ! side_effects_p (trueop0))
equal = 1, op0lt = 0, op0ltu = 0, op1lt = 0, op1ltu = 0;
/* If the operands are floating-point constants, see if we can fold
the result. */
-#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
else if (GET_CODE (trueop0) == CONST_DOUBLE
&& GET_CODE (trueop1) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (trueop0)) == MODE_FLOAT)
{
- struct cfc_args args;
+ REAL_VALUE_TYPE d0, d1;
- /* Setup input for check_fold_consts() */
- args.op0 = trueop0;
- args.op1 = trueop1;
-
-
- if (!do_float_handler (check_fold_consts, (PTR) &args))
- args.unordered = 1;
+ REAL_VALUE_FROM_CONST_DOUBLE (d0, trueop0);
+ REAL_VALUE_FROM_CONST_DOUBLE (d1, trueop1);
- if (args.unordered)
+ /* Comparisons are unordered iff at least one of the values is NaN. */
+ if (REAL_VALUE_ISNAN (d0) || REAL_VALUE_ISNAN (d1))
switch (code)
{
case UNEQ:
@@ -2142,12 +2014,10 @@ simplify_relational_operation (code, mode, op0, op1)
return 0;
}
- /* Receive output from check_fold_consts() */
- equal = args.equal;
- op0lt = op0ltu = args.op0lt;
- op1lt = op1ltu = args.op1lt;
+ equal = REAL_VALUES_EQUAL (d0, d1);
+ op0lt = op0ltu = REAL_VALUES_LESS (d0, d1);
+ op1lt = op1ltu = REAL_VALUES_LESS (d1, d0);
}
-#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
/* Otherwise, see if the operands are both integers. */
else if ((GET_MODE_CLASS (mode) == MODE_INT || mode == VOIDmode)
@@ -2171,7 +2041,7 @@ simplify_relational_operation (code, mode, op0, op1)
l0u = l0s = INTVAL (trueop0);
h0u = h0s = HWI_SIGN_EXTEND (l0s);
}
-
+
if (GET_CODE (trueop1) == CONST_DOUBLE)
{
l1u = l1s = CONST_DOUBLE_LOW (trueop1);
@@ -2260,7 +2130,29 @@ simplify_relational_operation (code, mode, op0, op1)
&& INTEGRAL_MODE_P (mode))
return const0_rtx;
break;
-
+
+ case LT:
+ /* Optimize abs(x) < 0.0. */
+ if (trueop1 == CONST0_RTX (mode) && !HONOR_SNANS (mode))
+ {
+ tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
+ : trueop0;
+ if (GET_CODE (tem) == ABS)
+ return const0_rtx;
+ }
+ break;
+
+ case GE:
+ /* Optimize abs(x) >= 0.0. */
+ if (trueop1 == CONST0_RTX (mode) && !HONOR_NANS (mode))
+ {
+ tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
+ : trueop0;
+ if (GET_CODE (tem) == ABS)
+ return const1_rtx;
+ }
+ break;
+
default:
break;
}
@@ -2371,12 +2263,12 @@ simplify_ternary_operation (code, mode, op0_mode, op0, op1, op2)
/* Convert a == b ? b : a to "a". */
if (GET_CODE (op0) == NE && ! side_effects_p (op0)
- && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
+ && !HONOR_NANS (mode)
&& rtx_equal_p (XEXP (op0, 0), op1)
&& rtx_equal_p (XEXP (op0, 1), op2))
return op1;
else if (GET_CODE (op0) == EQ && ! side_effects_p (op0)
- && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
+ && !HONOR_NANS (mode)
&& rtx_equal_p (XEXP (op0, 1), op1)
&& rtx_equal_p (XEXP (op0, 0), op2))
return op2;
@@ -2404,7 +2296,7 @@ simplify_ternary_operation (code, mode, op0_mode, op0, op1, op2)
{
HOST_WIDE_INT t = INTVAL (op1);
HOST_WIDE_INT f = INTVAL (op2);
-
+
if (t == STORE_FLAG_VALUE && f == 0)
code = GET_CODE (op0);
else if (t == 0 && f == STORE_FLAG_VALUE)
@@ -2422,6 +2314,30 @@ simplify_ternary_operation (code, mode, op0_mode, op0, op1, op2)
}
}
break;
+ case VEC_MERGE:
+ if (GET_MODE (op0) != mode
+ || GET_MODE (op1) != mode
+ || !VECTOR_MODE_P (mode))
+ abort ();
+ op0 = avoid_constant_pool_reference (op0);
+ op1 = avoid_constant_pool_reference (op1);
+ op2 = avoid_constant_pool_reference (op2);
+ if (GET_CODE (op0) == CONST_VECTOR
+ && GET_CODE (op1) == CONST_VECTOR
+ && GET_CODE (op2) == CONST_INT)
+ {
+ int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
+ unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
+ rtvec v = rtvec_alloc (n_elts);
+ unsigned int i;
+
+ for (i = 0; i < n_elts; i++)
+ RTVEC_ELT (v, i) = (INTVAL (op2) & (1 << i)
+ ? CONST_VECTOR_ELT (op0, i)
+ : CONST_VECTOR_ELT (op1, i));
+ return gen_rtx_CONST_VECTOR (mode, v);
+ }
+ break;
default:
abort ();
@@ -2454,18 +2370,124 @@ simplify_subreg (outermode, op, innermode, byte)
if (outermode == innermode && !byte)
return op;
+ /* Simplify subregs of vector constants. */
+ if (GET_CODE (op) == CONST_VECTOR)
+ {
+ int elt_size = GET_MODE_SIZE (GET_MODE_INNER (innermode));
+ const unsigned int offset = byte / elt_size;
+ rtx elt;
+
+ if (GET_MODE_INNER (innermode) == outermode)
+ {
+ elt = CONST_VECTOR_ELT (op, offset);
+
+ /* ?? We probably don't need this copy_rtx because constants
+ can be shared. ?? */
+
+ return copy_rtx (elt);
+ }
+ else if (GET_MODE_INNER (innermode) == GET_MODE_INNER (outermode)
+ && GET_MODE_SIZE (innermode) > GET_MODE_SIZE (outermode))
+ {
+ return (gen_rtx_CONST_VECTOR
+ (outermode,
+ gen_rtvec_v (GET_MODE_NUNITS (outermode),
+ &CONST_VECTOR_ELT (op, offset))));
+ }
+ else if (GET_MODE_CLASS (outermode) == MODE_INT
+ && (GET_MODE_SIZE (outermode) % elt_size == 0))
+ {
+ /* This happens when the target register size is smaller then
+ the vector mode, and we synthesize operations with vectors
+ of elements that are smaller than the register size. */
+ HOST_WIDE_INT sum = 0, high = 0;
+ unsigned n_elts = (GET_MODE_SIZE (outermode) / elt_size);
+ unsigned i = BYTES_BIG_ENDIAN ? offset : offset + n_elts - 1;
+ unsigned step = BYTES_BIG_ENDIAN ? 1 : -1;
+ int shift = BITS_PER_UNIT * elt_size;
+
+ for (; n_elts--; i += step)
+ {
+ elt = CONST_VECTOR_ELT (op, i);
+ if (GET_CODE (elt) == CONST_DOUBLE
+ && GET_MODE_CLASS (GET_MODE (elt)) == MODE_FLOAT)
+ {
+ elt = gen_lowpart_common (int_mode_for_mode (GET_MODE (elt)),
+ elt);
+ if (! elt)
+ return NULL_RTX;
+ }
+ if (GET_CODE (elt) != CONST_INT)
+ return NULL_RTX;
+ /* Avoid overflow. */
+ if (high >> (HOST_BITS_PER_WIDE_INT - shift))
+ return NULL_RTX;
+ high = high << shift | sum >> (HOST_BITS_PER_WIDE_INT - shift);
+ sum = (sum << shift) + INTVAL (elt);
+ }
+ if (GET_MODE_BITSIZE (outermode) <= HOST_BITS_PER_WIDE_INT)
+ return GEN_INT (trunc_int_for_mode (sum, outermode));
+ else if (GET_MODE_BITSIZE (outermode) == 2* HOST_BITS_PER_WIDE_INT)
+ return immed_double_const (sum, high, outermode);
+ else
+ return NULL_RTX;
+ }
+ else if (GET_MODE_CLASS (outermode) == MODE_INT
+ && (elt_size % GET_MODE_SIZE (outermode) == 0))
+ {
+ enum machine_mode new_mode
+ = int_mode_for_mode (GET_MODE_INNER (innermode));
+ int subbyte = byte % elt_size;
+
+ op = simplify_subreg (new_mode, op, innermode, byte - subbyte);
+ if (! op)
+ return NULL_RTX;
+ return simplify_subreg (outermode, op, new_mode, subbyte);
+ }
+ else if (GET_MODE_CLASS (outermode) == MODE_INT)
+ /* This shouldn't happen, but let's not do anything stupid. */
+ return NULL_RTX;
+ }
+
/* Attempt to simplify constant to non-SUBREG expression. */
if (CONSTANT_P (op))
{
int offset, part;
unsigned HOST_WIDE_INT val = 0;
+ if (GET_MODE_CLASS (outermode) == MODE_VECTOR_INT
+ || GET_MODE_CLASS (outermode) == MODE_VECTOR_FLOAT)
+ {
+ /* Construct a CONST_VECTOR from individual subregs. */
+ enum machine_mode submode = GET_MODE_INNER (outermode);
+ int subsize = GET_MODE_UNIT_SIZE (outermode);
+ int i, elts = GET_MODE_NUNITS (outermode);
+ rtvec v = rtvec_alloc (elts);
+ rtx elt;
+
+ for (i = 0; i < elts; i++, byte += subsize)
+ {
+ /* This might fail, e.g. if taking a subreg from a SYMBOL_REF. */
+ /* ??? It would be nice if we could actually make such subregs
+ on targets that allow such relocations. */
+ if (byte >= GET_MODE_UNIT_SIZE (innermode))
+ elt = CONST0_RTX (submode);
+ else
+ elt = simplify_subreg (submode, op, innermode, byte);
+ if (! elt)
+ return NULL_RTX;
+ RTVEC_ELT (v, i) = elt;
+ }
+ return gen_rtx_CONST_VECTOR (outermode, v);
+ }
+
/* ??? This code is partly redundant with code below, but can handle
the subregs of floats and similar corner cases.
Later it we should move all simplification code here and rewrite
GEN_LOWPART_IF_POSSIBLE, GEN_HIGHPART, OPERAND_SUBWORD and friends
using SIMPLIFY_SUBREG. */
- if (subreg_lowpart_offset (outermode, innermode) == byte)
+ if (subreg_lowpart_offset (outermode, innermode) == byte
+ && GET_CODE (op) != CONST_VECTOR)
{
rtx new = gen_lowpart_if_possible (outermode, op);
if (new)
@@ -2484,6 +2506,20 @@ simplify_subreg (outermode, op, innermode, byte)
return new;
}
+ if (GET_MODE_CLASS (outermode) != MODE_INT
+ && GET_MODE_CLASS (outermode) != MODE_CC)
+ {
+ enum machine_mode new_mode = int_mode_for_mode (outermode);
+
+ if (new_mode != innermode || byte != 0)
+ {
+ op = simplify_subreg (new_mode, op, innermode, byte);
+ if (! op)
+ return NULL_RTX;
+ return simplify_subreg (outermode, op, new_mode, 0);
+ }
+ }
+
offset = byte * BITS_PER_UNIT;
switch (GET_CODE (op))
{
@@ -2504,7 +2540,7 @@ simplify_subreg (outermode, op, innermode, byte)
val = part ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op);
offset %= HOST_BITS_PER_WIDE_INT;
- /* We've already picked the word we want from a double, so
+ /* We've already picked the word we want from a double, so
pretend this is actually an integer. */
innermode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);
@@ -2621,15 +2657,12 @@ simplify_subreg (outermode, op, innermode, byte)
if (REG_P (op)
&& (! REG_FUNCTION_VALUE_P (op)
|| ! rtx_equal_function_value_matters)
-#ifdef CLASS_CANNOT_CHANGE_MODE
- && ! (CLASS_CANNOT_CHANGE_MODE_P (outermode, innermode)
+ && REGNO (op) < FIRST_PSEUDO_REGISTER
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ && ! (REG_CANNOT_CHANGE_MODE_P (REGNO (op), innermode, outermode)
&& GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT
- && GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT
- && (TEST_HARD_REG_BIT
- (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
- REGNO (op))))
+ && GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT)
#endif
- && REGNO (op) < FIRST_PSEUDO_REGISTER
&& ((reload_completed && !frame_pointer_needed)
|| (REGNO (op) != FRAME_POINTER_REGNUM
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
@@ -2646,7 +2679,7 @@ simplify_subreg (outermode, op, innermode, byte)
/* ??? We do allow it if the current REG is not valid for
its mode. This is a kludge to work around how float/complex
- arguments are passed on 32-bit Sparc and should be fixed. */
+ arguments are passed on 32-bit SPARC and should be fixed. */
if (HARD_REGNO_MODE_OK (final_regno, outermode)
|| ! HARD_REGNO_MODE_OK (REGNO (op), innermode))
{
@@ -2769,7 +2802,7 @@ simplify_gen_subreg (outermode, op, innermode, byte)
maintain and improve. It's totally silly that when we add a
simplification that it needs to be added to 4 places (3 for RTL
simplification and 1 for tree simplification. */
-
+
rtx
simplify_rtx (x)
rtx x;
@@ -2813,7 +2846,7 @@ simplify_rtx (x)
case 'x':
/* The only case we try to handle is a SUBREG. */
if (code == SUBREG)
- return simplify_gen_subreg (mode, SUBREG_REG (x),
+ return simplify_gen_subreg (mode, SUBREG_REG (x),
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x));
return NULL;
diff --git a/contrib/gcc/splay-tree.c b/contrib/gcc/splay-tree.c
index 7999447..6f90fde 100644
--- a/contrib/gcc/splay-tree.c
+++ b/contrib/gcc/splay-tree.c
@@ -234,7 +234,7 @@ splay_tree_xmalloc_allocate (size, data)
int size;
void *data ATTRIBUTE_UNUSED;
{
- return xmalloc (size);
+ return (void *) xmalloc (size);
}
static void
@@ -482,7 +482,7 @@ splay_tree_predecessor (sp, key)
}
/* Return the immediate successor KEY, or NULL if there is no
- predecessor. KEY need not be present in the tree. */
+ successor. KEY need not be present in the tree. */
splay_tree_node
splay_tree_successor (sp, key)
@@ -492,7 +492,7 @@ splay_tree_successor (sp, key)
int comparison;
splay_tree_node node;
- /* If the tree is empty, there is certainly no predecessor. */
+ /* If the tree is empty, there is certainly no successor. */
if (!sp->root)
return NULL;
diff --git a/contrib/gcc/splay-tree.h b/contrib/gcc/splay-tree.h
index 4b7a7bf..23f7ac6 100644
--- a/contrib/gcc/splay-tree.h
+++ b/contrib/gcc/splay-tree.h
@@ -1,5 +1,5 @@
/* A splay-tree datatype.
- Copyright 1998, 1999, 2000 Free Software Foundation, Inc.
+ Copyright 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
Contributed by Mark Mitchell (mark@markmitchell.com).
This file is part of GCC.
@@ -34,7 +34,7 @@ Boston, MA 02111-1307, USA. */
extern "C" {
#endif /* __cplusplus */
-#include <ansidecl.h>
+#include "ansidecl.h"
/* Use typedefs for the key and data types to facilitate changing
these types, if necessary. These types should be sufficiently wide
diff --git a/contrib/gcc/ssa-ccp.c b/contrib/gcc/ssa-ccp.c
index 4dc0aa9..44f4921 100644
--- a/contrib/gcc/ssa-ccp.c
+++ b/contrib/gcc/ssa-ccp.c
@@ -2,19 +2,19 @@
Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
Original framework by Daniel Berlin <dan@cgsoftware.com>
Fleshed out and major cleanups by Jeff Law <law@redhat.com>
-
+
This file is part of GCC.
-
+
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
-
+
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
-
+
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
@@ -44,7 +44,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
5. Another simple SSA DCE pass to remove dead code exposed
by CCP.
- When we exit, we are still in SSA form.
+ When we exit, we are still in SSA form.
Potential further enhancements:
@@ -83,7 +83,7 @@ typedef enum
VARYING
} latticevalue;
-/* Main structure for CCP.
+/* Main structure for CCP.
Contains the lattice value and, if it's a constant, the constant
value. */
@@ -120,7 +120,6 @@ static sbitmap ssa_edges;
/* Simple macros to simplify code */
#define SSA_NAME(x) REGNO (SET_DEST (x))
-#define PHI_PARMS(x) XVEC (SET_SRC (x), 0)
#define EIE(x,y) EDGE_INDEX (edges, x, y)
static void visit_phi_node PARAMS ((rtx, basic_block));
@@ -185,7 +184,7 @@ visit_phi_node (phi_node, block)
/* If the current value of PHI_NODE is UNDEFINED and one
node in PHI_NODE is CONSTANT, then the new value of the
PHI is that CONSTANT. Note this can turn into VARYING
- if we find another distinct constant later. */
+ if we find another distinct constant later. */
if (phi_node_lattice_val == UNDEFINED
&& phi_node_expr == NULL
&& current_parm_lattice_val == CONSTANT)
@@ -288,7 +287,7 @@ visit_expression (insn, block)
}
/* Hard registers are not put in SSA form and thus we must consider
- them varying. All the more reason to avoid hard registers in
+ them varying. All the more reason to avoid hard registers in
RTL until as late as possible in the compilation. */
if (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER)
{
@@ -451,7 +450,7 @@ visit_expression (insn, block)
rtx simplified = NULL;
/* We've got some kind of INSN. If it's simple, try to evaluate
- it and record the results.
+ it and record the results.
We already know this insn is a single_set and that it sets
a pseudo register. So we just need to extract the source
@@ -511,7 +510,7 @@ visit_expression (insn, block)
defs_to_undefined (insn);
break;
}
-
+
/* Simplify source operands to whatever known values they
may have. */
if (GET_CODE (src0) == REG
@@ -542,7 +541,7 @@ visit_expression (insn, block)
defs_to_undefined (insn);
break;
}
-
+
/* Simplify source operands to whatever known values they
may have. */
if (GET_CODE (src0) == REG
@@ -579,7 +578,7 @@ visit_expression (insn, block)
defs_to_undefined (insn);
break;
}
-
+
/* Simplify source operands to whatever known values they
may have. */
if (GET_CODE (src0) == REG
@@ -602,7 +601,7 @@ visit_expression (insn, block)
src0, src1, src2);
break;
}
-
+
default:
defs_to_varying (insn);
}
@@ -617,7 +616,7 @@ visit_expression (insn, block)
values[REGNO (dest)].const_value = simplified;
}
else
- defs_to_varying (insn);
+ defs_to_varying (insn);
}
}
@@ -665,11 +664,11 @@ examine_flow_edges ()
currinsn = NEXT_INSN (currinsn);
}
-
+
/* Don't forget the last insn in the block. */
if (INSN_P (currinsn))
visit_expression (currinsn, succ_block);
-
+
/* If we haven't looked at the next block, and it has a
single successor, add it onto the worklist. This is because
if we only have one successor, we know it gets executed,
@@ -702,7 +701,7 @@ follow_def_use_chains ()
/* Pick an entry off the worklist (it does not matter which
entry we pick). */
- member = sbitmap_first_set_bit (ssa_edges);
+ member = sbitmap_first_set_bit (ssa_edges);
RESET_BIT (ssa_edges, member);
/* Iterate through all the uses of this entry. */
@@ -716,7 +715,7 @@ follow_def_use_chains ()
{
if (TEST_BIT (executable_blocks, BLOCK_NUM (useinsn)))
visit_phi_node (useinsn, BLOCK_FOR_INSN (useinsn));
- }
+ }
else
{
if (TEST_BIT (executable_blocks, BLOCK_NUM (useinsn)))
@@ -727,7 +726,7 @@ follow_def_use_chains ()
}
/* Examine each edge to see if we were able to prove any were
- not executable.
+ not executable.
If an edge is not executable, then we can remove its alternative
in PHI nodes as the destination of the edge, we can simplify the
@@ -740,6 +739,7 @@ optimize_unexecutable_edges (edges, executable_edges)
sbitmap executable_edges;
{
int i;
+ basic_block bb;
for (i = 0; i < NUM_EDGES (edges); i++)
{
@@ -761,7 +761,7 @@ optimize_unexecutable_edges (edges, executable_edges)
remove_phi_alternative (PATTERN (insn), edge->src);
if (rtl_dump_file)
fprintf (rtl_dump_file,
- "Removing alternative for bb %d of phi %d\n",
+ "Removing alternative for bb %d of phi %d\n",
edge->src->index, SSA_NAME (PATTERN (insn)));
insn = NEXT_INSN (insn);
}
@@ -797,9 +797,8 @@ optimize_unexecutable_edges (edges, executable_edges)
In cases B & C we are removing uses of registers, so make sure
to note those changes for the DF analyzer. */
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
rtx insn = bb->end;
edge edge = bb->succ;
@@ -834,7 +833,7 @@ optimize_unexecutable_edges (edges, executable_edges)
}
}
}
-
+
/* Perform substitution of known values for pseudo registers.
??? Note we do not do simplifications or constant folding here, it
@@ -842,7 +841,7 @@ optimize_unexecutable_edges (edges, executable_edges)
anyway. Consider that if the simplification would result in an
expression that produces a constant value that the value would
have been discovered and recorded already.
-
+
We perform two transformations. First, we initialize pseudos to their
known constant values at their definition point. Second, we try to
replace uses with the known constant value. */
@@ -901,13 +900,13 @@ ssa_ccp_substitute_constants ()
&& (GET_CODE (useinsn) == INSN
|| GET_CODE (useinsn) == JUMP_INSN))
{
-
+
if (validate_replace_src (regno_reg_rtx [i],
values[i].const_value,
useinsn))
{
if (rtl_dump_file)
- fprintf (rtl_dump_file,
+ fprintf (rtl_dump_file,
"Register %d in insn %d replaced with constant\n",
i, INSN_UID (useinsn));
INSN_CODE (useinsn) = -1;
@@ -915,7 +914,7 @@ ssa_ccp_substitute_constants ()
BLOCK_FOR_INSN (useinsn),
useinsn);
}
-
+
}
}
}
@@ -929,7 +928,7 @@ ssa_ccp_substitute_constants ()
static void
ssa_ccp_df_delete_unreachable_insns ()
{
- int i;
+ basic_block b;
/* Use the CFG to find all the reachable blocks. */
find_unreachable_blocks ();
@@ -937,10 +936,8 @@ ssa_ccp_df_delete_unreachable_insns ()
/* Now we know what blocks are not reachable. Mark all the insns
in those blocks as deleted for the DF analyzer. We'll let the
normal flow code actually remove the unreachable blocks. */
- for (i = n_basic_blocks - 1; i >= 0; --i)
+ FOR_EACH_BB_REVERSE (b)
{
- basic_block b = BASIC_BLOCK (i);
-
if (!(b->flags & BB_REACHABLE))
{
rtx start = b->head;
@@ -993,9 +990,6 @@ ssa_const_prop ()
df_analyse (df_analyzer, 0,
DF_RD_CHAIN | DF_RU_CHAIN | DF_REG_INFO | DF_HARD_REGS);
- /* We need mappings from insn to its containing block. */
- compute_bb_for_insn (get_max_uid ());
-
/* Perform a quick and dirty dead code elimination pass. This is not
as aggressive as it could be, but it's good enough to clean up a
lot of unwanted junk and it is fast. */
@@ -1009,7 +1003,7 @@ ssa_const_prop ()
for (i = 0; i < VARRAY_SIZE (ssa_definition); i++)
{
if (i < FIRST_PSEUDO_REGISTER)
- values[i].lattice_val = VARYING;
+ values[i].lattice_val = VARYING;
else
values[i].lattice_val = UNDEFINED;
values[i].const_value = NULL;
@@ -1018,7 +1012,7 @@ ssa_const_prop ()
ssa_edges = sbitmap_alloc (VARRAY_SIZE (ssa_definition));
sbitmap_zero (ssa_edges);
- executable_blocks = sbitmap_alloc (n_basic_blocks);
+ executable_blocks = sbitmap_alloc (last_basic_block);
sbitmap_zero (executable_blocks);
executable_edges = sbitmap_alloc (NUM_EDGES (edges));
@@ -1085,7 +1079,7 @@ ssa_const_prop ()
sbitmap_free (ssa_edges);
ssa_edges = NULL;
-
+
free_edge_list (edges);
edges = NULL;
@@ -1178,7 +1172,7 @@ ssa_fast_dce (df)
== NOTE_INSN_DELETED))
|| side_effects_p (PATTERN (VARRAY_RTX (ssa_definition, reg))))
continue;
-
+
/* Iterate over the uses of this register. If we can not find
any uses that have not been deleted, then the definition of
this register is dead. */
@@ -1200,7 +1194,7 @@ ssa_fast_dce (df)
/* If we did not find a use of this register, then the definition
of this register is dead. */
-
+
if (! found_use)
{
rtx def = VARRAY_RTX (ssa_definition, reg);
@@ -1221,5 +1215,5 @@ ssa_fast_dce (df)
/* Update the use-def chains in the df_analyzer as needed. */
df_analyse (df_analyzer, 0,
- DF_RD_CHAIN | DF_RU_CHAIN | DF_REG_INFO | DF_HARD_REGS);
+ DF_RD_CHAIN | DF_RU_CHAIN | DF_REG_INFO | DF_HARD_REGS);
}
diff --git a/contrib/gcc/ssa-dce.c b/contrib/gcc/ssa-dce.c
index 83b4e44..09fcc7a 100644
--- a/contrib/gcc/ssa-dce.c
+++ b/contrib/gcc/ssa-dce.c
@@ -98,13 +98,13 @@ static void set_control_dependent_block_to_edge_map_bit
static void control_dependent_block_to_edge_map_free
PARAMS ((control_dependent_block_to_edge_map c));
static void find_all_control_dependences
- PARAMS ((struct edge_list *el, int *pdom,
+ PARAMS ((struct edge_list *el, dominance_info pdom,
control_dependent_block_to_edge_map cdbte));
static void find_control_dependence
- PARAMS ((struct edge_list *el, int edge_index, int *pdom,
+ PARAMS ((struct edge_list *el, int edge_index, dominance_info pdom,
control_dependent_block_to_edge_map cdbte));
static basic_block find_pdom
- PARAMS ((int *pdom, basic_block block));
+ PARAMS ((dominance_info pdom, basic_block block));
static int inherently_necessary_register_1
PARAMS ((rtx *current_rtx, void *data));
static int inherently_necessary_register
@@ -218,7 +218,7 @@ control_dependent_block_to_edge_map_free (c)
static void
find_all_control_dependences (el, pdom, cdbte)
struct edge_list *el;
- int *pdom;
+ dominance_info pdom;
control_dependent_block_to_edge_map cdbte;
{
int i;
@@ -237,7 +237,7 @@ static void
find_control_dependence (el, edge_index, pdom, cdbte)
struct edge_list *el;
int edge_index;
- int *pdom;
+ dominance_info pdom;
control_dependent_block_to_edge_map cdbte;
{
basic_block current_block;
@@ -247,7 +247,7 @@ find_control_dependence (el, edge_index, pdom, cdbte)
abort ();
ending_block =
(INDEX_EDGE_PRED_BB (el, edge_index) == ENTRY_BLOCK_PTR)
- ? BASIC_BLOCK (0)
+ ? ENTRY_BLOCK_PTR->next_bb
: find_pdom (pdom, INDEX_EDGE_PRED_BB (el, edge_index));
for (current_block = INDEX_EDGE_SUCC_BB (el, edge_index);
@@ -266,7 +266,7 @@ find_control_dependence (el, edge_index, pdom, cdbte)
static basic_block
find_pdom (pdom, block)
- int *pdom;
+ dominance_info pdom;
basic_block block;
{
if (!block)
@@ -275,11 +275,16 @@ find_pdom (pdom, block)
abort ();
if (block == ENTRY_BLOCK_PTR)
- return BASIC_BLOCK (0);
- else if (block == EXIT_BLOCK_PTR || pdom[block->index] == EXIT_BLOCK)
+ return ENTRY_BLOCK_PTR->next_bb;
+ else if (block == EXIT_BLOCK_PTR)
return EXIT_BLOCK_PTR;
else
- return BASIC_BLOCK (pdom[block->index]);
+ {
+ basic_block bb = get_immediate_dominator (pdom, block);
+ if (!bb)
+ return EXIT_BLOCK_PTR;
+ return bb;
+ }
}
/* Determine if the given CURRENT_RTX uses a hard register not
@@ -370,7 +375,7 @@ find_inherently_necessary (x)
return !0;
else
switch (GET_CODE (x))
- {
+ {
case CALL_INSN:
case BARRIER:
case PREFETCH:
@@ -488,39 +493,28 @@ delete_insn_bb (insn)
void
ssa_eliminate_dead_code ()
{
- int i;
rtx insn;
+ basic_block bb;
/* Necessary instructions with operands to explore. */
varray_type unprocessed_instructions;
/* Map element (b,e) is nonzero if the block is control dependent on
edge. "cdbte" abbreviates control dependent block to edge. */
control_dependent_block_to_edge_map cdbte;
/* Element I is the immediate postdominator of block I. */
- int *pdom;
+ dominance_info pdom;
struct edge_list *el;
- int max_insn_uid = get_max_uid ();
-
/* Initialize the data structures. */
mark_all_insn_unnecessary ();
VARRAY_RTX_INIT (unprocessed_instructions, 64,
"unprocessed instructions");
- cdbte = control_dependent_block_to_edge_map_create (n_basic_blocks);
+ cdbte = control_dependent_block_to_edge_map_create (last_basic_block);
/* Prepare for use of BLOCK_NUM (). */
connect_infinite_loops_to_exit ();
- /* Be careful not to clear the added edges. */
- compute_bb_for_insn (max_insn_uid);
/* Compute control dependence. */
- pdom = (int *) xmalloc (n_basic_blocks * sizeof (int));
- for (i = 0; i < n_basic_blocks; ++i)
- pdom[i] = INVALID_BLOCK;
- calculate_dominance_info (pdom, NULL, CDI_POST_DOMINATORS);
- /* Assume there is a path from each node to the exit block. */
- for (i = 0; i < n_basic_blocks; ++i)
- if (pdom[i] == INVALID_BLOCK)
- pdom[i] = EXIT_BLOCK;
+ pdom = calculate_dominance_info (CDI_POST_DOMINATORS);
el = create_edge_list ();
find_all_control_dependences (el, pdom, cdbte);
@@ -691,7 +685,7 @@ ssa_eliminate_dead_code ()
remove_edge (temp);
}
- /* Create an edge from this block to the post dominator.
+ /* Create an edge from this block to the post dominator.
What about the PHI nodes at the target? */
make_edge (bb, pdom_bb, 0);
@@ -711,17 +705,15 @@ ssa_eliminate_dead_code ()
else if (!JUMP_P (insn))
delete_insn_bb (insn);
});
-
+
/* Remove fake edges from the CFG. */
remove_fake_edges ();
/* Find any blocks with no successors and ensure they are followed
by a BARRIER. delete_insn has the nasty habit of deleting barriers
when deleting insns. */
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
-
if (bb->succ == NULL)
{
rtx next = NEXT_INSN (bb->end);
@@ -735,7 +727,6 @@ ssa_eliminate_dead_code ()
RESURRECT_INSN (insn);
if (VARRAY_ACTIVE_SIZE (unprocessed_instructions) != 0)
abort ();
- VARRAY_FREE (unprocessed_instructions);
control_dependent_block_to_edge_map_free (cdbte);
free ((PTR) pdom);
free_edge_list (el);
diff --git a/contrib/gcc/ssa.c b/contrib/gcc/ssa.c
index c97b35c..b5c4992 100644
--- a/contrib/gcc/ssa.c
+++ b/contrib/gcc/ssa.c
@@ -49,7 +49,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "output.h"
#include "ssa.h"
-/* TODO:
+/* TODO:
Handle subregs better, maybe. For now, if a reg that's set in a
subreg expression is duplicated going into SSA form, an extra copy
@@ -78,7 +78,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
the same hard register in the same machine mode are in the same
class. */
-/* If conservative_reg_partition is non-zero, use a conservative
+/* If conservative_reg_partition is nonzero, use a conservative
register partitioning algorithm (which leaves more regs after
emerging from SSA) instead of the coalescing one. This is being
left in for a limited time only, as a debugging tool until the
@@ -124,6 +124,8 @@ struct ssa_rename_from_hash_table_data {
partition reg_partition;
};
+static rtx gen_sequence
+ PARAMS ((void));
static void ssa_rename_from_initialize
PARAMS ((void));
static rtx ssa_rename_from_lookup
@@ -163,7 +165,7 @@ struct rename_context;
static inline rtx * phi_alternative
PARAMS ((rtx, int));
static void compute_dominance_frontiers_1
- PARAMS ((sbitmap *frontiers, int *idom, int bb, sbitmap done));
+ PARAMS ((sbitmap *frontiers, dominance_info idom, int bb, sbitmap done));
static void find_evaluations_1
PARAMS ((rtx dest, rtx set, void *data));
static void find_evaluations
@@ -174,16 +176,16 @@ static void insert_phi_node
PARAMS ((int regno, int b));
static void insert_phi_nodes
PARAMS ((sbitmap *idfs, sbitmap *evals, int nregs));
-static void create_delayed_rename
+static void create_delayed_rename
PARAMS ((struct rename_context *, rtx *));
-static void apply_delayed_renames
+static void apply_delayed_renames
PARAMS ((struct rename_context *));
-static int rename_insn_1
+static int rename_insn_1
PARAMS ((rtx *ptr, void *data));
-static void rename_block
- PARAMS ((int b, int *idom));
-static void rename_registers
- PARAMS ((int nregs, int *idom));
+static void rename_block
+ PARAMS ((int b, dominance_info dom));
+static void rename_registers
+ PARAMS ((int nregs, dominance_info idom));
static inline int ephi_add_node
PARAMS ((rtx reg, rtx *nodes, int *n_nodes));
@@ -195,20 +197,20 @@ static void ephi_create
PARAMS ((int t, sbitmap visited, sbitmap *pred, sbitmap *succ, rtx *nodes));
static void eliminate_phi
PARAMS ((edge e, partition reg_partition));
-static int make_regs_equivalent_over_bad_edges
+static int make_regs_equivalent_over_bad_edges
PARAMS ((int bb, partition reg_partition));
/* These are used only in the conservative register partitioning
algorithms. */
-static int make_equivalent_phi_alternatives_equivalent
+static int make_equivalent_phi_alternatives_equivalent
PARAMS ((int bb, partition reg_partition));
-static partition compute_conservative_reg_partition
+static partition compute_conservative_reg_partition
PARAMS ((void));
static int record_canonical_element_1
PARAMS ((void **srfp, void *data));
static int check_hard_regs_in_partition
PARAMS ((partition reg_partition));
-static int rename_equivalent_regs_in_insn
+static int rename_equivalent_regs_in_insn
PARAMS ((rtx *ptr, void *data));
/* These are used in the register coalescing algorithm. */
@@ -222,14 +224,14 @@ static int coalesce_regs_in_successor_phi_nodes
PARAMS ((basic_block bb, partition p, conflict_graph conflicts));
static partition compute_coalesced_reg_partition
PARAMS ((void));
-static int mark_reg_in_phi
+static int mark_reg_in_phi
PARAMS ((rtx *ptr, void *data));
static void mark_phi_and_copy_regs
PARAMS ((regset phi_set));
-static int rename_equivalent_regs_in_insn
+static int rename_equivalent_regs_in_insn
PARAMS ((rtx *ptr, void *data));
-static void rename_equivalent_regs
+static void rename_equivalent_regs
PARAMS ((partition reg_partition));
/* Deal with hard registers. */
@@ -418,7 +420,7 @@ phi_alternative (set, c)
}
/* Given the SET of a phi node, remove the alternative for predecessor
- block C. Return non-zero on success, or zero if no alternative is
+ block C. Return nonzero on success, or zero if no alternative is
found for C. */
int
@@ -470,18 +472,18 @@ find_evaluations (evals, nregs)
sbitmap *evals;
int nregs;
{
- int bb;
+ basic_block bb;
sbitmap_vector_zero (evals, nregs);
fe_evals = evals;
- for (bb = n_basic_blocks; --bb >= 0; )
+ FOR_EACH_BB_REVERSE (bb)
{
rtx p, last;
- fe_current_bb = bb;
- p = BLOCK_HEAD (bb);
- last = BLOCK_END (bb);
+ fe_current_bb = bb->index;
+ p = bb->head;
+ last = bb->end;
while (1)
{
if (INSN_P (p))
@@ -495,8 +497,8 @@ find_evaluations (evals, nregs)
}
/* Computing the Dominance Frontier:
-
- As decribed in Morgan, section 3.5, this may be done simply by
+
+ As decribed in Morgan, section 3.5, this may be done simply by
walking the dominator tree bottom-up, computing the frontier for
the children before the parent. When considering a block B,
there are two cases:
@@ -514,13 +516,13 @@ find_evaluations (evals, nregs)
static void
compute_dominance_frontiers_1 (frontiers, idom, bb, done)
sbitmap *frontiers;
- int *idom;
+ dominance_info idom;
int bb;
sbitmap done;
{
basic_block b = BASIC_BLOCK (bb);
edge e;
- int c;
+ basic_block c;
SET_BIT (done, bb);
sbitmap_zero (frontiers[bb]);
@@ -528,27 +530,28 @@ compute_dominance_frontiers_1 (frontiers, idom, bb, done)
/* Do the frontier of the children first. Not all children in the
dominator tree (blocks dominated by this one) are children in the
CFG, so check all blocks. */
- for (c = 0; c < n_basic_blocks; ++c)
- if (idom[c] == bb && ! TEST_BIT (done, c))
- compute_dominance_frontiers_1 (frontiers, idom, c, done);
+ FOR_EACH_BB (c)
+ if (get_immediate_dominator (idom, c)->index == bb
+ && ! TEST_BIT (done, c->index))
+ compute_dominance_frontiers_1 (frontiers, idom, c->index, done);
/* Find blocks conforming to rule (1) above. */
for (e = b->succ; e; e = e->succ_next)
{
if (e->dest == EXIT_BLOCK_PTR)
continue;
- if (idom[e->dest->index] != bb)
+ if (get_immediate_dominator (idom, e->dest)->index != bb)
SET_BIT (frontiers[bb], e->dest->index);
}
/* Find blocks conforming to rule (2). */
- for (c = 0; c < n_basic_blocks; ++c)
- if (idom[c] == bb)
+ FOR_EACH_BB (c)
+ if (get_immediate_dominator (idom, c)->index == bb)
{
int x;
- EXECUTE_IF_SET_IN_SBITMAP (frontiers[c], 0, x,
+ EXECUTE_IF_SET_IN_SBITMAP (frontiers[c->index], 0, x,
{
- if (idom[x] != bb)
+ if (get_immediate_dominator (idom, BASIC_BLOCK (x))->index != bb)
SET_BIT (frontiers[bb], x);
});
}
@@ -557,9 +560,9 @@ compute_dominance_frontiers_1 (frontiers, idom, bb, done)
void
compute_dominance_frontiers (frontiers, idom)
sbitmap *frontiers;
- int *idom;
+ dominance_info idom;
{
- sbitmap done = sbitmap_alloc (n_basic_blocks);
+ sbitmap done = sbitmap_alloc (last_basic_block);
sbitmap_zero (done);
compute_dominance_frontiers_1 (frontiers, idom, 0, done);
@@ -585,7 +588,7 @@ compute_iterated_dominance_frontiers (idfs, frontiers, evals, nregs)
sbitmap worklist;
int reg, passes = 0;
- worklist = sbitmap_alloc (n_basic_blocks);
+ worklist = sbitmap_alloc (last_basic_block);
for (reg = 0; reg < nregs; ++reg)
{
@@ -698,10 +701,10 @@ insert_phi_nodes (idfs, evals, nregs)
}
}
-/* Rename the registers to conform to SSA.
+/* Rename the registers to conform to SSA.
This is essentially the algorithm presented in Figure 7.8 of Morgan,
- with a few changes to reduce pattern search time in favour of a bit
+ with a few changes to reduce pattern search time in favor of a bit
more memory usage. */
/* One of these is created for each set. It will live in a list local
@@ -740,7 +743,7 @@ create_delayed_rename (c, reg_loc)
{
struct rename_set_data *r;
r = (struct rename_set_data *) xmalloc (sizeof(*r));
-
+
if (GET_CODE (*reg_loc) != REG
|| !CONVERT_REGISTER_TO_SSA_P (REGNO (*reg_loc)))
abort ();
@@ -756,7 +759,7 @@ create_delayed_rename (c, reg_loc)
/* This is part of a rather ugly hack to allow the pre-ssa regno to be
reused. If, during processing, a register has not yet been touched,
ssa_rename_to[regno][machno] will be NULL. Now, in the course of pushing
- and popping values from ssa_rename_to, when we would ordinarily
+ and popping values from ssa_rename_to, when we would ordinarily
pop NULL back in, we pop RENAME_NO_RTX. We treat this exactly the
same as NULL, except that it signals that the original regno has
already been reused. */
@@ -775,7 +778,7 @@ apply_delayed_renames (c)
for (r = c->new_renames; r != NULL; r = r->next)
{
int new_regno;
-
+
/* Failure here means that someone has a PARALLEL that sets
a register twice (bad!). */
if (ssa_rename_to_lookup (r->old_reg) != r->prev_reg)
@@ -812,7 +815,7 @@ apply_delayed_renames (c)
}
}
-/* Part one of the first step of rename_block, called through for_each_rtx.
+/* Part one of the first step of rename_block, called through for_each_rtx.
Mark pseudos that are set for later update. Transform uses of pseudos. */
static int
@@ -855,7 +858,7 @@ rename_insn_1 (ptr, data)
(set (subreg (reg foo)) ...)
into
(sequence [(set (reg foo_1) (reg foo))
- (set (subreg (reg foo_1)) ...)])
+ (set (subreg (reg foo_1)) ...)])
FIXME: Much of the time this is too much. For some constructs
we know that the output register is strictly an output
@@ -870,13 +873,13 @@ rename_insn_1 (ptr, data)
{
rtx i, reg;
reg = dest;
-
+
while (GET_CODE (reg) == STRICT_LOW_PART
|| GET_CODE (reg) == SUBREG
|| GET_CODE (reg) == SIGN_EXTRACT
|| GET_CODE (reg) == ZERO_EXTRACT)
reg = XEXP (reg, 0);
-
+
if (GET_CODE (reg) == REG
&& CONVERT_REGISTER_TO_SSA_P (REGNO (reg)))
{
@@ -916,18 +919,23 @@ rename_insn_1 (ptr, data)
}
case REG:
- if (CONVERT_REGISTER_TO_SSA_P (REGNO (x)) &&
- REGNO (x) < ssa_max_reg_num)
+ if (CONVERT_REGISTER_TO_SSA_P (REGNO (x))
+ && REGNO (x) < ssa_max_reg_num)
{
rtx new_reg = ssa_rename_to_lookup (x);
- if (new_reg != NULL_RTX && new_reg != RENAME_NO_RTX)
+ if (new_reg != RENAME_NO_RTX && new_reg != NULL_RTX)
{
if (GET_MODE (x) != GET_MODE (new_reg))
abort ();
*ptr = new_reg;
}
- /* Else this is a use before a set. Warn? */
+ else
+ {
+ /* Undefined value used, rename it to a new pseudo register so
+ that it cannot conflict with an existing register. */
+ *ptr = gen_reg_rtx (GET_MODE (x));
+ }
}
return -1;
@@ -950,7 +958,7 @@ rename_insn_1 (ptr, data)
}
/* Stop traversing. */
return -1;
- }
+ }
else
/* Continue traversing. */
return 0;
@@ -966,20 +974,42 @@ rename_insn_1 (ptr, data)
}
}
+static rtx
+gen_sequence ()
+{
+ rtx first_insn = get_insns ();
+ rtx result;
+ rtx tem;
+ int i;
+ int len;
+
+ /* Count the insns in the chain. */
+ len = 0;
+ for (tem = first_insn; tem; tem = NEXT_INSN (tem))
+ len++;
+
+ result = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (len));
+
+ for (i = 0, tem = first_insn; tem; tem = NEXT_INSN (tem), i++)
+ XVECEXP (result, 0, i) = tem;
+
+ return result;
+}
+
static void
rename_block (bb, idom)
int bb;
- int *idom;
+ dominance_info idom;
{
basic_block b = BASIC_BLOCK (bb);
edge e;
rtx insn, next, last;
struct rename_set_data *set_data = NULL;
- int c;
+ basic_block c;
/* Step One: Walk the basic block, adding new names for sets and
replacing uses. */
-
+
next = b->head;
last = b->end;
do
@@ -1004,7 +1034,7 @@ rename_block (bb, idom)
{
rtx seq;
int i;
-
+
emit (PATTERN (insn));
seq = gen_sequence ();
/* We really want a SEQUENCE of SETs, not a SEQUENCE
@@ -1014,7 +1044,7 @@ rename_block (bb, idom)
PATTERN (insn) = seq;
}
end_sequence ();
-
+
apply_delayed_renames (&context);
set_data = context.done_renames;
}
@@ -1078,9 +1108,9 @@ rename_block (bb, idom)
/* Step Three: Do the same to the children of this block in
dominator order. */
- for (c = 0; c < n_basic_blocks; ++c)
- if (idom[c] == bb)
- rename_block (c, idom);
+ FOR_EACH_BB (c)
+ if (get_immediate_dominator (idom, c)->index == bb)
+ rename_block (c->index, idom);
/* Step Four: Update the sets to refer to their new register,
and restore ssa_rename_to to its previous state. */
@@ -1099,25 +1129,25 @@ rename_block (bb, idom)
next = set_data->next;
free (set_data);
set_data = next;
- }
+ }
}
static void
rename_registers (nregs, idom)
int nregs;
- int *idom;
+ dominance_info idom;
{
VARRAY_RTX_INIT (ssa_definition, nregs * 3, "ssa_definition");
ssa_rename_from_initialize ();
ssa_rename_to_pseudo = (rtx *) alloca (nregs * sizeof(rtx));
memset ((char *) ssa_rename_to_pseudo, 0, nregs * sizeof(rtx));
- memset ((char *) ssa_rename_to_hard, 0,
+ memset ((char *) ssa_rename_to_hard, 0,
FIRST_PSEUDO_REGISTER * NUM_MACHINE_MODES * sizeof (rtx));
rename_block (0, idom);
- /* ??? Update basic_block_live_at_start, and other flow info
+ /* ??? Update basic_block_live_at_start, and other flow info
as needed. */
ssa_rename_to_pseudo = NULL;
@@ -1136,10 +1166,12 @@ convert_to_ssa ()
sbitmap *idfs;
/* Element I is the immediate dominator of block I. */
- int *idom;
+ dominance_info idom;
int nregs;
+ basic_block bb;
+
/* Don't do it twice. */
if (in_ssa_form)
abort ();
@@ -1148,28 +1180,26 @@ convert_to_ssa ()
dead code. We'll let the SSA optimizers do that. */
life_analysis (get_insns (), NULL, 0);
- idom = (int *) alloca (n_basic_blocks * sizeof (int));
- memset ((void *) idom, -1, (size_t) n_basic_blocks * sizeof (int));
- calculate_dominance_info (idom, NULL, CDI_DOMINATORS);
+ idom = calculate_dominance_info (CDI_DOMINATORS);
if (rtl_dump_file)
{
- int i;
fputs (";; Immediate Dominators:\n", rtl_dump_file);
- for (i = 0; i < n_basic_blocks; ++i)
- fprintf (rtl_dump_file, ";\t%3d = %3d\n", i, idom[i]);
+ FOR_EACH_BB (bb)
+ fprintf (rtl_dump_file, ";\t%3d = %3d\n", bb->index,
+ get_immediate_dominator (idom, bb)->index);
fflush (rtl_dump_file);
}
/* Compute dominance frontiers. */
- dfs = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
+ dfs = sbitmap_vector_alloc (last_basic_block, last_basic_block);
compute_dominance_frontiers (dfs, idom);
if (rtl_dump_file)
{
dump_sbitmap_vector (rtl_dump_file, ";; Dominance Frontiers:",
- "; Basic Block", dfs, n_basic_blocks);
+ "; Basic Block", dfs, last_basic_block);
fflush (rtl_dump_file);
}
@@ -1177,12 +1207,12 @@ convert_to_ssa ()
ssa_max_reg_num = max_reg_num ();
nregs = ssa_max_reg_num;
- evals = sbitmap_vector_alloc (nregs, n_basic_blocks);
+ evals = sbitmap_vector_alloc (nregs, last_basic_block);
find_evaluations (evals, nregs);
/* Compute the iterated dominance frontier for each register. */
- idfs = sbitmap_vector_alloc (nregs, n_basic_blocks);
+ idfs = sbitmap_vector_alloc (nregs, last_basic_block);
compute_iterated_dominance_frontiers (idfs, dfs, evals, nregs);
if (rtl_dump_file)
@@ -1208,6 +1238,7 @@ convert_to_ssa ()
in_ssa_form = 1;
reg_scan (get_insns (), max_reg_num (), 1);
+ free_dominance_info (idom);
}
/* REG is the representative temporary of its partition. Add it to the
@@ -1247,7 +1278,7 @@ ephi_forward (t, visited, succ, tstack)
EXECUTE_IF_SET_IN_SBITMAP (succ[t], 0, s,
{
if (! TEST_BIT (visited, s))
- tstack = ephi_forward (s, visited, succ, tstack);
+ tstack = ephi_forward (s, visited, succ, tstack);
});
*tstack++ = t;
@@ -1291,7 +1322,7 @@ ephi_create (t, visited, pred, succ, nodes)
int p;
/* Iterate through the predecessor list looking for unvisited nodes.
- If there are any, we have a cycle, and must deal with that. At
+ If there are any, we have a cycle, and must deal with that. At
the same time, look for a visited predecessor. If there is one,
we won't need to create a temporary. */
@@ -1322,8 +1353,8 @@ ephi_create (t, visited, pred, succ, nodes)
emit_move_insn (nodes[p], reg_u);
}
});
- }
- else
+ }
+ else
{
/* No cycle. Just copy the value from a successor. */
@@ -1366,7 +1397,7 @@ eliminate_phi (e, reg_partition)
if (n_nodes == 0)
return;
- /* Build the auxiliary graph R(B).
+ /* Build the auxiliary graph R(B).
The nodes of the graph are the members of the register partition
present in Phi(B). There is an edge from FIND(T0)->FIND(T1) for
@@ -1399,7 +1430,7 @@ eliminate_phi (e, reg_partition)
reg = regno_reg_rtx[partition_find (reg_partition, REGNO (reg))];
tgt = regno_reg_rtx[partition_find (reg_partition, REGNO (tgt))];
- /* If the two registers are already in the same partition,
+ /* If the two registers are already in the same partition,
nothing will need to be done. */
if (reg != tgt)
{
@@ -1429,10 +1460,10 @@ eliminate_phi (e, reg_partition)
sbitmap_zero (visited);
- /* As we find a solution to the tsort, collect the implementation
+ /* As we find a solution to the tsort, collect the implementation
insns in a sequence. */
start_sequence ();
-
+
while (tstack != stack)
{
i = *--tstack;
@@ -1440,7 +1471,7 @@ eliminate_phi (e, reg_partition)
ephi_create (i, visited, pred, succ, nodes);
}
- insn = gen_sequence ();
+ insn = get_insns ();
end_sequence ();
insert_insn_on_edge (insn, e);
if (rtl_dump_file)
@@ -1456,16 +1487,16 @@ out:
/* For basic block B, consider all phi insns which provide an
alternative corresponding to an incoming abnormal critical edge.
Place the phi alternative corresponding to that abnormal critical
- edge in the same register class as the destination of the set.
+ edge in the same register class as the destination of the set.
From Morgan, p. 178:
- For each abnormal critical edge (C, B),
- if T0 = phi (T1, ..., Ti, ..., Tm) is a phi node in B,
- and C is the ith predecessor of B,
- then T0 and Ti must be equivalent.
+ For each abnormal critical edge (C, B),
+ if T0 = phi (T1, ..., Ti, ..., Tm) is a phi node in B,
+ and C is the ith predecessor of B,
+ then T0 and Ti must be equivalent.
- Return non-zero iff any such cases were found for which the two
+ Return nonzero iff any such cases were found for which the two
regs were not already in the same class. */
static int
@@ -1481,7 +1512,7 @@ make_regs_equivalent_over_bad_edges (bb, reg_partition)
phi = first_insn_after_basic_block_note (b);
/* Scan all the phi nodes. */
- for (;
+ for (;
PHI_NODE_P (phi);
phi = next_nonnote_insn (phi))
{
@@ -1491,7 +1522,7 @@ make_regs_equivalent_over_bad_edges (bb, reg_partition)
rtx tgt = SET_DEST (set);
/* The set target is expected to be an SSA register. */
- if (GET_CODE (tgt) != REG
+ if (GET_CODE (tgt) != REG
|| !CONVERT_REGISTER_TO_SSA_P (REGNO (tgt)))
abort ();
tgt_regno = REGNO (tgt);
@@ -1509,14 +1540,14 @@ make_regs_equivalent_over_bad_edges (bb, reg_partition)
continue;
/* The phi alternative is expected to be an SSA register. */
- if (GET_CODE (*alt) != REG
+ if (GET_CODE (*alt) != REG
|| !CONVERT_REGISTER_TO_SSA_P (REGNO (*alt)))
abort ();
alt_regno = REGNO (*alt);
/* If the set destination and the phi alternative aren't
already in the same class... */
- if (partition_find (reg_partition, tgt_regno)
+ if (partition_find (reg_partition, tgt_regno)
!= partition_find (reg_partition, alt_regno))
{
/* ... make them such. */
@@ -1524,8 +1555,8 @@ make_regs_equivalent_over_bad_edges (bb, reg_partition)
/* It is illegal to unify a hard register with a
different register. */
abort ();
-
- partition_union (reg_partition,
+
+ partition_union (reg_partition,
tgt_regno, alt_regno);
++changed;
}
@@ -1554,7 +1585,7 @@ make_equivalent_phi_alternatives_equivalent (bb, reg_partition)
phi = first_insn_after_basic_block_note (b);
/* Scan all the phi nodes. */
- for (;
+ for (;
PHI_NODE_P (phi);
phi = next_nonnote_insn (phi))
{
@@ -1572,7 +1603,7 @@ make_equivalent_phi_alternatives_equivalent (bb, reg_partition)
rtx set2 = PATTERN (phi2);
/* The regno of the destination of the set. */
int tgt2_regno = REGNO (SET_DEST (set2));
-
+
/* Are the set destinations equivalent regs? */
if (partition_find (reg_partition, tgt_regno) ==
partition_find (reg_partition, tgt2_regno))
@@ -1602,7 +1633,7 @@ make_equivalent_phi_alternatives_equivalent (bb, reg_partition)
/* If the alternatives aren't already in the same
class ... */
- if (partition_find (reg_partition, REGNO (*alt))
+ if (partition_find (reg_partition, REGNO (*alt))
!= partition_find (reg_partition, REGNO (*alt2)))
{
/* ... make them so. */
@@ -1611,7 +1642,7 @@ make_equivalent_phi_alternatives_equivalent (bb, reg_partition)
a different register. */
abort ();
- partition_union (reg_partition,
+ partition_union (reg_partition,
REGNO (*alt), REGNO (*alt2));
++changed;
}
@@ -1629,30 +1660,30 @@ make_equivalent_phi_alternatives_equivalent (bb, reg_partition)
static partition
compute_conservative_reg_partition ()
{
- int bb;
+ basic_block bb;
int changed = 0;
/* We don't actually work with hard registers, but it's easier to
carry them around anyway rather than constantly doing register
number arithmetic. */
- partition p =
+ partition p =
partition_new (ssa_definition->num_elements);
/* The first priority is to make sure registers that might have to
be copied on abnormal critical edges are placed in the same
partition. This saves us from having to split abnormal critical
edges. */
- for (bb = n_basic_blocks; --bb >= 0; )
- changed += make_regs_equivalent_over_bad_edges (bb, p);
-
+ FOR_EACH_BB_REVERSE (bb)
+ changed += make_regs_equivalent_over_bad_edges (bb->index, p);
+
/* Now we have to insure that corresponding arguments of phi nodes
assigning to corresponding regs are equivalent. Iterate until
nothing changes. */
while (changed > 0)
{
changed = 0;
- for (bb = n_basic_blocks; --bb >= 0; )
- changed += make_equivalent_phi_alternatives_equivalent (bb, p);
+ FOR_EACH_BB_REVERSE (bb)
+ changed += make_equivalent_phi_alternatives_equivalent (bb->index, p);
}
return p;
@@ -1667,13 +1698,13 @@ compute_conservative_reg_partition ()
abnormal critical edges (which isn't possible).
2. Figure out which regs are involved (in the LHS or RHS) of
- copies and phi nodes. Compute conflicts among these regs.
+ copies and phi nodes. Compute conflicts among these regs.
3. Walk around the instruction stream, placing two regs in the
same class of the partition if one appears on the LHS and the
other on the RHS of a copy or phi node and the two regs don't
conflict. The conflict information of course needs to be
- updated.
+ updated.
4. If anything has changed, there may be new opportunities to
coalesce regs, so go back to 2.
@@ -1681,14 +1712,14 @@ compute_conservative_reg_partition ()
/* If REG1 and REG2 don't conflict in CONFLICTS, place them in the
same class of partition P, if they aren't already. Update
- CONFLICTS appropriately.
+ CONFLICTS appropriately.
Returns one if REG1 and REG2 were placed in the same class but were
- not previously; zero otherwise.
+ not previously; zero otherwise.
See Morgan figure 11.15. */
-static int
+static int
coalesce_if_unconflicting (p, conflicts, reg1, reg2)
partition p;
conflict_graph conflicts;
@@ -1705,7 +1736,7 @@ coalesce_if_unconflicting (p, conflicts, reg1, reg2)
REG2. */
reg1 = partition_find (p, reg1);
reg2 = partition_find (p, reg2);
-
+
/* If they're already in the same class, there's nothing to do. */
if (reg1 == reg2)
return 0;
@@ -1720,7 +1751,7 @@ coalesce_if_unconflicting (p, conflicts, reg1, reg2)
/* Find the new canonical reg for the merged class. */
reg = partition_find (p, reg1);
-
+
/* Merge conflicts from the two previous classes. */
conflict_graph_merge_regs (conflicts, reg, reg1);
conflict_graph_merge_regs (conflicts, reg, reg2);
@@ -1769,7 +1800,7 @@ coalesce_regs_in_copies (bb, p, conflicts)
/* Coalesce only if the reg modes are the same. As long as
each reg's rtx is unique, it can have only one mode, so two
- pseudos of different modes can't be coalesced into one.
+ pseudos of different modes can't be coalesced into one.
FIXME: We can probably get around this by inserting SUBREGs
where appropriate, but for now we don't bother. */
@@ -1779,7 +1810,7 @@ coalesce_regs_in_copies (bb, p, conflicts)
/* Found a copy; see if we can use the same reg for both the
source and destination (and thus eliminate the copy,
ultimately). */
- changed += coalesce_if_unconflicting (p, conflicts,
+ changed += coalesce_if_unconflicting (p, conflicts,
REGNO (src), REGNO (dest));
}
@@ -1805,12 +1836,12 @@ coalesce_reg_in_phi (insn, dest_regno, src_regno, data)
int src_regno;
void *data;
{
- struct phi_coalesce_context *context =
+ struct phi_coalesce_context *context =
(struct phi_coalesce_context *) data;
-
+
/* Attempt to use the same reg, if they don't conflict. */
- context->changed
- += coalesce_if_unconflicting (context->p, context->conflicts,
+ context->changed
+ += coalesce_if_unconflicting (context->p, context->conflicts,
dest_regno, src_regno);
return 0;
}
@@ -1818,10 +1849,10 @@ coalesce_reg_in_phi (insn, dest_regno, src_regno, data)
/* For each alternative in a phi function corresponding to basic block
BB (in phi nodes in successor block to BB), place the reg in the
phi alternative and the reg to which the phi value is set into the
- same class in partition P, if allowed by CONFLICTS.
+ same class in partition P, if allowed by CONFLICTS.
Return the number of changes that were made to P.
-
+
See Morgan figure 11.14. */
static int
@@ -1841,27 +1872,27 @@ coalesce_regs_in_successor_phi_nodes (bb, p, conflicts)
}
/* Compute and return a partition of pseudos. Where possible,
- non-conflicting pseudos are placed in the same class.
+ non-conflicting pseudos are placed in the same class.
The caller is responsible for deallocating the returned partition. */
static partition
compute_coalesced_reg_partition ()
{
- int bb;
+ basic_block bb;
int changed = 0;
regset_head phi_set_head;
regset phi_set = &phi_set_head;
- partition p =
+ partition p =
partition_new (ssa_definition->num_elements);
/* The first priority is to make sure registers that might have to
be copied on abnormal critical edges are placed in the same
partition. This saves us from having to split abnormal critical
edges (which can't be done). */
- for (bb = n_basic_blocks; --bb >= 0; )
- make_regs_equivalent_over_bad_edges (bb, p);
+ FOR_EACH_BB_REVERSE (bb)
+ make_regs_equivalent_over_bad_edges (bb->index, p);
INIT_REG_SET (phi_set);
@@ -1883,12 +1914,11 @@ compute_coalesced_reg_partition ()
blocks first, so that most frequently executed copies would
be more likely to be removed by register coalescing. But any
order will generate correct, if non-optimal, results. */
- for (bb = n_basic_blocks; --bb >= 0; )
+ FOR_EACH_BB_REVERSE (bb)
{
- basic_block block = BASIC_BLOCK (bb);
- changed += coalesce_regs_in_copies (block, p, conflicts);
- changed +=
- coalesce_regs_in_successor_phi_nodes (block, p, conflicts);
+ changed += coalesce_regs_in_copies (bb, p, conflicts);
+ changed +=
+ coalesce_regs_in_successor_phi_nodes (bb, p, conflicts);
}
conflict_graph_delete (conflicts);
@@ -1995,7 +2025,7 @@ rename_equivalent_regs_in_insn (ptr, data)
unsigned int new_regno = partition_find (reg_partition, regno);
rtx canonical_element_rtx = ssa_rename_from_lookup (new_regno);
- if (canonical_element_rtx != NULL_RTX &&
+ if (canonical_element_rtx != NULL_RTX &&
HARD_REGISTER_P (canonical_element_rtx))
{
if (REGNO (canonical_element_rtx) != regno)
@@ -2036,7 +2066,7 @@ record_canonical_element_1 (srfp, data)
((struct ssa_rename_from_hash_table_data *) data)->canonical_elements;
partition reg_partition =
((struct ssa_rename_from_hash_table_data *) data)->reg_partition;
-
+
SET_BIT (canonical_elements, partition_find (reg_partition, reg));
return 1;
}
@@ -2094,11 +2124,10 @@ static void
rename_equivalent_regs (reg_partition)
partition reg_partition;
{
- int bb;
+ basic_block b;
- for (bb = n_basic_blocks; --bb >= 0; )
+ FOR_EACH_BB_REVERSE (b)
{
- basic_block b = BASIC_BLOCK (bb);
rtx next = b->head;
rtx last = b->end;
rtx insn;
@@ -2108,11 +2137,11 @@ rename_equivalent_regs (reg_partition)
insn = next;
if (INSN_P (insn))
{
- for_each_rtx (&PATTERN (insn),
- rename_equivalent_regs_in_insn,
+ for_each_rtx (&PATTERN (insn),
+ rename_equivalent_regs_in_insn,
reg_partition);
- for_each_rtx (&REG_NOTES (insn),
- rename_equivalent_regs_in_insn,
+ for_each_rtx (&REG_NOTES (insn),
+ rename_equivalent_regs_in_insn,
reg_partition);
if (GET_CODE (PATTERN (insn)) == SEQUENCE)
@@ -2141,13 +2170,13 @@ rename_equivalent_regs (reg_partition)
void
convert_from_ssa ()
{
- int bb;
+ basic_block b, bb;
partition reg_partition;
rtx insns = get_insns ();
/* Need global_live_at_{start,end} up to date. There should not be
any significant dead code at this point, except perhaps dead
- stores. So do not take the time to perform dead code elimination.
+ stores. So do not take the time to perform dead code elimination.
Register coalescing needs death notes, so generate them. */
life_analysis (insns, NULL, PROP_DEATH_NOTES);
@@ -2167,9 +2196,8 @@ convert_from_ssa ()
rename_equivalent_regs (reg_partition);
/* Eliminate the PHI nodes. */
- for (bb = n_basic_blocks; --bb >= 0; )
+ FOR_EACH_BB_REVERSE (b)
{
- basic_block b = BASIC_BLOCK (bb);
edge e;
for (e = b->pred; e; e = e->pred_next)
@@ -2180,17 +2208,17 @@ convert_from_ssa ()
partition_delete (reg_partition);
/* Actually delete the PHI nodes. */
- for (bb = n_basic_blocks; --bb >= 0; )
+ FOR_EACH_BB_REVERSE (bb)
{
- rtx insn = BLOCK_HEAD (bb);
+ rtx insn = bb->head;
while (1)
{
/* If this is a PHI node delete it. */
if (PHI_NODE_P (insn))
{
- if (insn == BLOCK_END (bb))
- BLOCK_END (bb) = PREV_INSN (insn);
+ if (insn == bb->end)
+ bb->end = PREV_INSN (insn);
insn = delete_insn (insn);
}
/* Since all the phi nodes come at the beginning of the
@@ -2199,9 +2227,9 @@ convert_from_ssa ()
else if (INSN_P (insn))
break;
/* If we've reached the end of the block, stop. */
- else if (insn == BLOCK_END (bb))
+ else if (insn == bb->end)
break;
- else
+ else
insn = NEXT_INSN (insn);
}
}
@@ -2214,7 +2242,7 @@ convert_from_ssa ()
count_or_remove_death_notes (NULL, 1);
/* Deallocate the data structures. */
- VARRAY_FREE (ssa_definition);
+ ssa_definition = 0;
ssa_rename_from_free ();
}
@@ -2224,7 +2252,7 @@ convert_from_ssa ()
destination, the regno of the phi argument corresponding to BB,
and DATA.
- If FN ever returns non-zero, stops immediately and returns this
+ If FN ever returns nonzero, stops immediately and returns this
value. Otherwise, returns zero. */
int
@@ -2234,7 +2262,7 @@ for_each_successor_phi (bb, fn, data)
void *data;
{
edge e;
-
+
if (bb == EXIT_BLOCK_PTR)
return 0;
@@ -2244,7 +2272,7 @@ for_each_successor_phi (bb, fn, data)
rtx insn;
basic_block successor = e->dest;
- if (successor == ENTRY_BLOCK_PTR
+ if (successor == ENTRY_BLOCK_PTR
|| successor == EXIT_BLOCK_PTR)
continue;
@@ -2261,7 +2289,7 @@ for_each_successor_phi (bb, fn, data)
rtx phi_set = PATTERN (insn);
rtx *alternative = phi_alternative (phi_set, bb->index);
rtx phi_src;
-
+
/* This phi function may not have an alternative
corresponding to the incoming edge, indicating the
assigned variable is not defined along the edge. */
@@ -2270,7 +2298,7 @@ for_each_successor_phi (bb, fn, data)
phi_src = *alternative;
/* Invoke the callback. */
- result = (*fn) (insn, REGNO (SET_DEST (phi_set)),
+ result = (*fn) (insn, REGNO (SET_DEST (phi_set)),
REGNO (phi_src), data);
/* Terminate if requested. */
@@ -2301,6 +2329,6 @@ conflicting_hard_regs_p (reg1, reg2)
return 1;
if (!HARD_REGISTER_NUM_P (orig_reg1) && HARD_REGISTER_NUM_P (orig_reg2))
return 1;
-
+
return 0;
}
diff --git a/contrib/gcc/ssa.h b/contrib/gcc/ssa.h
index a0fc137..115f77d 100644
--- a/contrib/gcc/ssa.h
+++ b/contrib/gcc/ssa.h
@@ -27,7 +27,8 @@ typedef int (*successor_phi_fn) PARAMS ((rtx, int, int, void *));
extern int for_each_successor_phi PARAMS ((basic_block bb,
successor_phi_fn,
void *));
-void compute_dominance_frontiers PARAMS ((sbitmap *frontiers, int *idom));
+void compute_dominance_frontiers PARAMS ((sbitmap *frontiers,
+ dominance_info idom));
extern int remove_phi_alternative PARAMS ((rtx, basic_block));
@@ -44,7 +45,7 @@ extern void ssa_const_prop PARAMS ((void));
extern int in_ssa_form;
/* Element I is the single instruction that sets register I. */
-extern varray_type ssa_definition;
+extern GTY(()) varray_type ssa_definition;
/* Element I is an INSN_LIST of instructions that use register I. */
extern varray_type ssa_uses;
diff --git a/contrib/gcc/stab.def b/contrib/gcc/stab.def
index 81d442a..7a0b849 100644
--- a/contrib/gcc/stab.def
+++ b/contrib/gcc/stab.def
@@ -47,10 +47,10 @@ __define_stab (N_MAIN, 0x2a, "MAIN")
Supposedly the value is its line number; I'm skeptical. */
__define_stab (N_PC, 0x30, "PC")
-/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */
+/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */
__define_stab (N_NSYMS, 0x32, "NSYMS")
-/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */
+/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */
__define_stab (N_NOMAP, 0x34, "NOMAP")
/* New stab from Solaris. I don't know what it means, but it
@@ -84,13 +84,13 @@ __define_stab (N_BSLINE, 0x48, "BSLINE")
__define_stab (N_BROWS, 0x48, "BROWS")
/* GNU Modula-2 definition module dependency. Value is the modification time
- of the definition file. Other is non-zero if it is imported with the
+ of the definition file. Other is nonzero if it is imported with the
GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there
are enough empty fields? */
__define_stab(N_DEFD, 0x4a, "DEFD")
/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2
- and one is for C++. Still,... */
+ and one is for C++. Still,... */
/* GNU C++ exception variable. Name is variable name. */
__define_stab (N_EHDECL, 0x50, "EHDECL")
/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */
@@ -168,7 +168,7 @@ __define_stab (N_ECOML, 0xe8, "ECOML")
/* These STAB's are used on Gould systems for Non-Base register symbols
or something like that. FIXME. I have assigned the values at random
- since I don't have a Gould here. Fixups from Gould folk welcome... */
+ since I don't have a Gould here. Fixups from Gould folk welcome... */
__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
__define_stab (N_NBDATA, 0xF2, "NBDATA")
__define_stab (N_NBBSS, 0xF4, "NBBSS")
diff --git a/contrib/gcc/stmt.c b/contrib/gcc/stmt.c
index 05705e7..9800ee8 100644
--- a/contrib/gcc/stmt.c
+++ b/contrib/gcc/stmt.c
@@ -46,17 +46,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "expr.h"
#include "libfuncs.h"
#include "hard-reg-set.h"
-#include "obstack.h"
#include "loop.h"
#include "recog.h"
#include "machmode.h"
#include "toplev.h"
#include "output.h"
#include "ggc.h"
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-struct obstack stmt_obstack;
+#include "langhooks.h"
+#include "predict.h"
/* Assume that case vectors are not pc-relative. */
#ifndef CASE_VECTOR_PC_RELATIVE
@@ -87,7 +84,7 @@ struct obstack stmt_obstack;
and nodes on the right having higher values. We then output the tree
in order. */
-struct case_node
+struct case_node GTY(())
{
struct case_node *left; /* Left son in binary tree */
struct case_node *right; /* Right son in binary tree; also node chain */
@@ -137,16 +134,22 @@ static int cost_table_initialized;
The construct is visible if the `exit_label' field is non-null.
In that case, the value should be a CODE_LABEL rtx. */
-struct nesting
+struct nesting GTY(())
{
struct nesting *all;
struct nesting *next;
int depth;
rtx exit_label;
- union
+ enum nesting_desc {
+ COND_NESTING,
+ LOOP_NESTING,
+ BLOCK_NESTING,
+ CASE_NESTING
+ } desc;
+ union nesting_u
{
/* For conds (if-then and if-then-else statements). */
- struct
+ struct nesting_cond
{
/* Label for the end of the if construct.
There is none if EXITFLAG was not set
@@ -155,9 +158,9 @@ struct nesting
/* Label for the end of this alternative.
This may be the end of the if or the next else/elseif. */
rtx next_label;
- } cond;
+ } GTY ((tag ("COND_NESTING"))) cond;
/* For loops. */
- struct
+ struct nesting_loop
{
/* Label at the top of the loop; place to loop back to. */
rtx start_label;
@@ -169,9 +172,9 @@ struct nesting
/* Label for `continue' statement to jump to;
this is in front of the stepper of the loop. */
rtx continue_label;
- } loop;
+ } GTY ((tag ("LOOP_NESTING"))) loop;
/* For variable binding contours. */
- struct
+ struct nesting_block
{
/* Sequence number of this binding contour within the function,
in order of entry. */
@@ -203,7 +206,7 @@ struct nesting
struct label_chain *label_chain;
/* Number of function calls seen, as of start of this block. */
int n_function_calls;
- /* Nonzero if this is associated with a EH region. */
+ /* Nonzero if this is associated with an 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
@@ -221,14 +224,10 @@ struct nesting
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;
+ } GTY ((tag ("BLOCK_NESTING"))) block;
/* For switch (C) or case (Pascal) statements,
and also for dummies (see `expand_start_case_dummy'). */
- struct
+ struct nesting_case
{
/* The insn after which the case dispatch should finally
be emitted. Zero for a dummy. */
@@ -249,14 +248,14 @@ struct nesting
We set this to -1 when we see the first case label in this
case statement. */
int line_number_status;
- } case_stmt;
- } data;
+ } GTY ((tag ("CASE_NESTING"))) case_stmt;
+ } GTY ((desc ("%1.desc"))) data;
};
/* Allocate and return a new `struct nesting'. */
#define ALLOC_NESTING() \
- (struct nesting *) obstack_alloc (&stmt_obstack, sizeof (struct nesting))
+ (struct nesting *) ggc_alloc (sizeof (struct nesting))
/* Pop the nesting stack element by element until we pop off
the element which is at the top of STACK.
@@ -278,8 +277,7 @@ do { struct nesting *target = STACK; \
if (case_stack == this) \
case_stack = case_stack->next; \
nesting_depth = nesting_stack->depth - 1; \
- nesting_stack = this->all; \
- obstack_free (&stmt_obstack, this); } \
+ nesting_stack = this->all; } \
while (this != target); } while (0)
/* In some cases it is impossible to generate code for a forward goto
@@ -290,7 +288,7 @@ do { struct nesting *target = STACK; \
we check each fixup.
If the target label has now been defined, we can insert the proper code. */
-struct goto_fixup
+struct goto_fixup GTY(())
{
/* Points to following fixup. */
struct goto_fixup *next;
@@ -324,36 +322,36 @@ struct goto_fixup
/* Within any binding contour that must restore a stack level,
all labels are recorded with a chain of these structures. */
-struct label_chain
+struct label_chain GTY(())
{
/* Points to following fixup. */
struct label_chain *next;
tree label;
};
-struct stmt_status
+struct stmt_status GTY(())
{
/* Chain of all pending binding contours. */
- struct nesting *x_block_stack;
+ struct nesting * x_block_stack;
/* If any new stacks are added here, add them to POPSTACKS too. */
/* Chain of all pending binding contours that restore stack levels
or have cleanups. */
- struct nesting *x_stack_block_stack;
+ struct nesting * x_stack_block_stack;
/* Chain of all pending conditional statements. */
- struct nesting *x_cond_stack;
+ struct nesting * x_cond_stack;
/* Chain of all pending loops. */
- struct nesting *x_loop_stack;
+ struct nesting * x_loop_stack;
/* Chain of all pending case or switch statements. */
- struct nesting *x_case_stack;
+ struct nesting * x_case_stack;
/* Separate chain including all of the above,
chained through the `all' field. */
- struct nesting *x_nesting_stack;
+ struct nesting * x_nesting_stack;
/* Number of entries on nesting_stack now. */
int x_nesting_depth;
@@ -393,13 +391,14 @@ struct stmt_status
#define emit_lineno (cfun->stmt->x_emit_lineno)
#define goto_fixup_chain (cfun->stmt->x_goto_fixup_chain)
-/* Non-zero if we are using EH to handle cleanus. */
+/* Non-zero if we are using EH to handle cleanups. */
static int using_eh_for_cleanups_p = 0;
static int n_occurrences PARAMS ((int, const char *));
static bool parse_input_constraint PARAMS ((const char **, int, int, int,
int, const char * const *,
bool *, bool *));
+static bool decl_conflicts_with_clobbers_p PARAMS ((tree, const HARD_REG_SET));
static void expand_goto_internal PARAMS ((tree, rtx, rtx));
static int expand_fixup PARAMS ((tree, rtx, rtx));
static rtx expand_nl_handler_label PARAMS ((rtx, rtx));
@@ -413,6 +412,7 @@ static tree resolve_operand_names PARAMS ((tree, tree, tree,
const char **));
static char *resolve_operand_name_1 PARAMS ((char *, tree, tree));
static void expand_null_return_1 PARAMS ((rtx));
+static enum br_predictor return_prediction PARAMS ((rtx));
static void expand_value_return PARAMS ((rtx));
static int tail_recursion_args PARAMS ((tree, tree));
static void expand_cleanups PARAMS ((tree, tree, int, int));
@@ -428,13 +428,6 @@ static int node_is_bounded PARAMS ((case_node_ptr, tree));
static void emit_jump_if_reachable PARAMS ((rtx));
static void emit_case_nodes PARAMS ((rtx, case_node_ptr, rtx, tree));
static struct case_node *case_tree2list PARAMS ((case_node *, case_node *));
-static void mark_cond_nesting PARAMS ((struct nesting *));
-static void mark_loop_nesting PARAMS ((struct nesting *));
-static void mark_block_nesting PARAMS ((struct nesting *));
-static void mark_case_nesting PARAMS ((struct nesting *));
-static void mark_case_node PARAMS ((struct case_node *));
-static void mark_goto_fixup PARAMS ((struct goto_fixup *));
-static void free_case_nodes PARAMS ((case_node_ptr));
void
using_eh_for_cleanups ()
@@ -442,176 +435,10 @@ using_eh_for_cleanups ()
using_eh_for_cleanups_p = 1;
}
-/* Mark N (known to be a cond-nesting) for GC. */
-
-static void
-mark_cond_nesting (n)
- struct nesting *n;
-{
- while (n)
- {
- ggc_mark_rtx (n->exit_label);
- ggc_mark_rtx (n->data.cond.endif_label);
- ggc_mark_rtx (n->data.cond.next_label);
-
- n = n->next;
- }
-}
-
-/* Mark N (known to be a loop-nesting) for GC. */
-
-static void
-mark_loop_nesting (n)
- struct nesting *n;
-{
-
- while (n)
- {
- ggc_mark_rtx (n->exit_label);
- ggc_mark_rtx (n->data.loop.start_label);
- ggc_mark_rtx (n->data.loop.end_label);
- ggc_mark_rtx (n->data.loop.alt_end_label);
- ggc_mark_rtx (n->data.loop.continue_label);
-
- n = n->next;
- }
-}
-
-/* Mark N (known to be a block-nesting) for GC. */
-
-static void
-mark_block_nesting (n)
- struct nesting *n;
-{
- while (n)
- {
- struct label_chain *l;
-
- ggc_mark_rtx (n->exit_label);
- ggc_mark_rtx (n->data.block.stack_level);
- ggc_mark_rtx (n->data.block.first_insn);
- ggc_mark_tree (n->data.block.cleanups);
- ggc_mark_tree (n->data.block.outer_cleanups);
-
- for (l = n->data.block.label_chain; l != NULL; l = l->next)
- {
- ggc_mark (l);
- ggc_mark_tree (l->label);
- }
-
- ggc_mark_rtx (n->data.block.last_unconditional_cleanup);
-
- /* ??? cleanup_ptr never points outside the stack, does it? */
-
- n = n->next;
- }
-}
-
-/* Mark N (known to be a case-nesting) for GC. */
-
-static void
-mark_case_nesting (n)
- struct nesting *n;
-{
- while (n)
- {
- ggc_mark_rtx (n->exit_label);
- ggc_mark_rtx (n->data.case_stmt.start);
-
- ggc_mark_tree (n->data.case_stmt.default_label);
- ggc_mark_tree (n->data.case_stmt.index_expr);
- ggc_mark_tree (n->data.case_stmt.nominal_type);
-
- mark_case_node (n->data.case_stmt.case_list);
- n = n->next;
- }
-}
-
-/* Mark C for GC. */
-
-static void
-mark_case_node (c)
- struct case_node *c;
-{
- if (c != 0)
- {
- ggc_mark_tree (c->low);
- ggc_mark_tree (c->high);
- ggc_mark_tree (c->code_label);
-
- mark_case_node (c->right);
- mark_case_node (c->left);
- }
-}
-
-/* Mark G for GC. */
-
-static void
-mark_goto_fixup (g)
- struct goto_fixup *g;
-{
- while (g)
- {
- ggc_mark (g);
- ggc_mark_rtx (g->before_jump);
- ggc_mark_tree (g->target);
- ggc_mark_tree (g->context);
- ggc_mark_rtx (g->target_rtl);
- ggc_mark_rtx (g->stack_level);
- ggc_mark_tree (g->cleanup_list_list);
-
- g = g->next;
- }
-}
-
-/* Clear out all parts of the state in F that can safely be discarded
- after the function has been compiled, to let garbage collection
- reclaim the memory. */
-
-void
-free_stmt_status (f)
- struct function *f;
-{
- /* We're about to free the function obstack. If we hold pointers to
- things allocated there, then we'll try to mark them when we do
- GC. So, we clear them out here explicitly. */
- if (f->stmt)
- free (f->stmt);
- f->stmt = NULL;
-}
-
-/* Mark P for GC. */
-
-void
-mark_stmt_status (p)
- struct stmt_status *p;
-{
- if (p == 0)
- return;
-
- mark_block_nesting (p->x_block_stack);
- mark_cond_nesting (p->x_cond_stack);
- mark_loop_nesting (p->x_loop_stack);
- mark_case_nesting (p->x_case_stack);
-
- ggc_mark_tree (p->x_last_expr_type);
- /* last_epxr_value is only valid if last_expr_type is nonzero. */
- if (p->x_last_expr_type)
- ggc_mark_rtx (p->x_last_expr_value);
-
- mark_goto_fixup (p->x_goto_fixup_chain);
-}
-
-void
-init_stmt ()
-{
- gcc_obstack_init (&stmt_obstack);
-}
-
void
init_stmt_for_function ()
{
- cfun->stmt = (struct stmt_status *) xmalloc (sizeof (struct stmt_status));
+ cfun->stmt = ((struct stmt_status *)ggc_alloc (sizeof (struct stmt_status)));
/* We are not currently within any block, conditional, loop or case. */
block_stack = 0;
@@ -629,8 +456,7 @@ init_stmt_for_function ()
/* We are not processing a ({...}) grouping. */
expr_stmts_for_value = 0;
- last_expr_type = 0;
- last_expr_value = NULL_RTX;
+ clear_last_expr ();
}
/* Return nonzero if anything is pushed on the loop, condition, or case
@@ -715,10 +541,23 @@ expand_computed_goto (exp)
#endif
emit_queue ();
- do_pending_stack_adjust ();
- emit_indirect_jump (x);
- current_function_has_computed_jump = 1;
+ if (! cfun->computed_goto_common_label)
+ {
+ cfun->computed_goto_common_reg = copy_to_mode_reg (Pmode, x);
+ cfun->computed_goto_common_label = gen_label_rtx ();
+ emit_label (cfun->computed_goto_common_label);
+
+ do_pending_stack_adjust ();
+ emit_indirect_jump (cfun->computed_goto_common_reg);
+
+ current_function_has_computed_jump = 1;
+ }
+ else
+ {
+ emit_move_insn (cfun->computed_goto_common_reg, x);
+ emit_jump (cfun->computed_goto_common_label);
+ }
}
/* Handle goto statements and the labels that they can go to. */
@@ -845,7 +684,7 @@ expand_goto (label)
emit_indirect_jump (handler_slot);
}
- /* Search backwards to the jump insn and mark it as a
+ /* Search backwards to the jump insn and mark it as a
non-local goto. */
for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
{
@@ -1044,8 +883,8 @@ expand_fixup (tree_label, rtl_label, last_insn)
as a placeholder. */
{
- rtx original_before_jump
- = last_insn ? last_insn : get_last_insn ();
+ rtx original_before_jump
+ = last_insn ? last_insn : get_last_insn ();
rtx start;
rtx end;
tree block;
@@ -1054,7 +893,7 @@ expand_fixup (tree_label, rtl_label, last_insn)
TREE_USED (block) = 1;
if (!cfun->x_whole_function_mode_p)
- insert_block (block);
+ (*lang_hooks.decls.insert_block) (block);
else
{
BLOCK_CHAIN (block)
@@ -1063,17 +902,17 @@ expand_fixup (tree_label, rtl_label, last_insn)
= block;
}
- start_sequence ();
- start = emit_note (NULL, NOTE_INSN_BLOCK_BEG);
+ start_sequence ();
+ start = emit_note (NULL, NOTE_INSN_BLOCK_BEG);
if (cfun->x_whole_function_mode_p)
NOTE_BLOCK (start) = block;
fixup->before_jump = emit_note (NULL, NOTE_INSN_DELETED);
end = emit_note (NULL, NOTE_INSN_BLOCK_END);
if (cfun->x_whole_function_mode_p)
NOTE_BLOCK (end) = block;
- fixup->context = block;
- end_sequence ();
- emit_insns_after (start, original_before_jump);
+ fixup->context = block;
+ end_sequence ();
+ emit_insn_after (start, original_before_jump);
}
fixup->block_start_count = current_block_start_count;
@@ -1175,8 +1014,8 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
logically be inserting the fixup code. We do this for the
sake of getting the debugging information right. */
- pushlevel (0);
- set_block (f->context);
+ (*lang_hooks.decls.pushlevel) (0);
+ (*lang_hooks.decls.set_block) (f->context);
/* Expand the cleanups for blocks this jump exits. */
if (f->cleanup_list_list)
@@ -1215,10 +1054,10 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
destructed are still "in scope". */
cleanup_insns = get_insns ();
- poplevel (1, 0, 0);
+ (*lang_hooks.decls.poplevel) (1, 0, 0);
end_sequence ();
- emit_insns_after (cleanup_insns, f->before_jump);
+ emit_insn_after (cleanup_insns, f->before_jump);
f->before_jump = 0;
}
@@ -1249,16 +1088,16 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
if (TREE_CHAIN (lists) == thisblock->data.block.outer_cleanups)
{
start_sequence ();
- pushlevel (0);
- set_block (f->context);
+ (*lang_hooks.decls.pushlevel) (0);
+ (*lang_hooks.decls.set_block) (f->context);
expand_cleanups (TREE_VALUE (lists), NULL_TREE, 1, 1);
do_pending_stack_adjust ();
cleanup_insns = get_insns ();
- poplevel (1, 0, 0);
+ (*lang_hooks.decls.poplevel) (1, 0, 0);
end_sequence ();
if (cleanup_insns != 0)
f->before_jump
- = emit_insns_after (cleanup_insns, f->before_jump);
+ = emit_insn_after (cleanup_insns, f->before_jump);
f->cleanup_list_list = TREE_CHAIN (lists);
}
@@ -1284,6 +1123,7 @@ n_occurrences (c, s)
STRING is a STRING_CST node containing the assembler code text,
or an ADDR_EXPR containing a STRING_CST. VOL nonzero means the
insn is volatile; don't optimize it. */
+
void
expand_asm (string, vol)
tree string;
@@ -1299,8 +1139,8 @@ expand_asm (string, vol)
MEM_VOLATILE_P (body) = vol;
emit_insn (body);
-
- last_expr_type = 0;
+
+ clear_last_expr ();
}
/* Parse the output constraint pointed to by *CONSTRAINT_P. It is the
@@ -1386,7 +1226,7 @@ parse_output_constraint (constraint_p, operand_num, ninputs, noutputs,
case '=':
error ("operand constraint contains incorrectly positioned '+' or '='");
return false;
-
+
case '%':
if (operand_num + 1 == ninputs + noutputs)
{
@@ -1423,7 +1263,7 @@ parse_output_constraint (constraint_p, operand_num, ninputs, noutputs,
*allows_reg = true;
*allows_mem = true;
break;
-
+
case 'p': case 'r':
*allows_reg = true;
break;
@@ -1434,6 +1274,10 @@ parse_output_constraint (constraint_p, operand_num, ninputs, noutputs,
if (REG_CLASS_FROM_LETTER (*p) != NO_REGS)
*allows_reg = true;
#ifdef EXTRA_CONSTRAINT
+ else if (EXTRA_ADDRESS_CONSTRAINT (*p))
+ *allows_reg = true;
+ else if (EXTRA_MEMORY_CONSTRAINT (*p))
+ *allows_mem = true;
else
{
/* Otherwise we can't assume anything about the nature of
@@ -1559,6 +1403,10 @@ parse_input_constraint (constraint_p, input_num, ninputs, noutputs, ninout,
if (REG_CLASS_FROM_LETTER (constraint[j]) != NO_REGS)
*allows_reg = true;
#ifdef EXTRA_CONSTRAINT
+ else if (EXTRA_ADDRESS_CONSTRAINT (constraint[j]))
+ *allows_reg = true;
+ else if (EXTRA_MEMORY_CONSTRAINT (constraint[j]))
+ *allows_mem = true;
else
{
/* Otherwise we can't assume anything about the nature of
@@ -1574,12 +1422,49 @@ parse_input_constraint (constraint_p, input_num, ninputs, noutputs, ninout,
return true;
}
+/* Check for overlap between registers marked in CLOBBERED_REGS and
+ anything inappropriate in DECL. Emit error and return TRUE for error,
+ FALSE for ok. */
+
+static bool
+decl_conflicts_with_clobbers_p (decl, clobbered_regs)
+ tree decl;
+ const HARD_REG_SET clobbered_regs;
+{
+ /* Conflicts between asm-declared register variables and the clobber
+ list are not allowed. */
+ if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
+ && DECL_REGISTER (decl)
+ && REG_P (DECL_RTL (decl))
+ && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
+ {
+ rtx reg = DECL_RTL (decl);
+ unsigned int regno;
+
+ for (regno = REGNO (reg);
+ regno < (REGNO (reg)
+ + HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg)));
+ regno++)
+ if (TEST_HARD_REG_BIT (clobbered_regs, regno))
+ {
+ error ("asm-specifier for variable `%s' conflicts with asm clobber list",
+ IDENTIFIER_POINTER (DECL_NAME (decl)));
+
+ /* Reset registerness to stop multiple errors emitted for a
+ single variable. */
+ DECL_REGISTER (decl) = 0;
+ return true;
+ }
+ }
+ return false;
+}
+
/* Generate RTL for an asm statement with arguments.
STRING is the instruction template.
OUTPUTS is a list of output arguments (lvalues); INPUTS a list of inputs.
Each output or input has an expression in the TREE_VALUE and
and a tree list in TREE_PURPOSE which in turn contains a constraint
- name in TREE_VALUE (or NULL_TREE) and a constraint string
+ name in TREE_VALUE (or NULL_TREE) and a constraint string
in TREE_PURPOSE.
CLOBBERS is a list of STRING_CST nodes each naming a hard register
that is clobbered by this insn.
@@ -1604,6 +1489,8 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
int noutputs = list_length (outputs);
int ninout;
int nclobbers;
+ HARD_REG_SET clobbered_regs;
+ int clobber_conflict_found = 0;
tree tail;
int i;
/* Vector of RTX's of evaluated output operands. */
@@ -1641,6 +1528,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
/* Count the number of meaningful clobbered registers, ignoring what
we would ignore later. */
nclobbers = 0;
+ CLEAR_HARD_REG_SET (clobbered_regs);
for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
{
const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
@@ -1650,9 +1538,13 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
++nclobbers;
else if (i == -2)
error ("unknown register name `%s' in `asm'", regname);
+
+ /* Mark clobbered registers. */
+ if (i >= 0)
+ SET_HARD_REG_BIT (clobbered_regs, i);
}
- last_expr_type = 0;
+ clear_last_expr ();
/* First pass over inputs and outputs checks validity and sets
mark_addressable if needed. */
@@ -1684,7 +1576,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|| (DECL_P (val)
&& GET_CODE (DECL_RTL (val)) == REG
&& GET_MODE (DECL_RTL (val)) != TYPE_MODE (type))))
- mark_addressable (val);
+ (*lang_hooks.mark_addressable) (val);
if (is_inout)
ninout++;
@@ -1713,7 +1605,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
return;
if (! allows_reg && allows_mem)
- mark_addressable (TREE_VALUE (tail));
+ (*lang_hooks.mark_addressable) (TREE_VALUE (tail));
}
/* Second pass evaluates arguments. */
@@ -1726,6 +1618,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
bool is_inout;
bool allows_reg;
bool allows_mem;
+ rtx op;
if (!parse_output_constraint (&constraints[i], i, ninputs,
noutputs, &allows_mem, &allows_reg,
@@ -1749,24 +1642,28 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|| ! allows_reg
|| is_inout)
{
- output_rtx[i] = expand_expr (val, NULL_RTX, VOIDmode, EXPAND_WRITE);
+ op = expand_expr (val, NULL_RTX, VOIDmode, EXPAND_WRITE);
+ if (GET_CODE (op) == MEM)
+ op = validize_mem (op);
- if (! allows_reg && GET_CODE (output_rtx[i]) != MEM)
+ if (! allows_reg && GET_CODE (op) != MEM)
error ("output number %d not directly addressable", i);
- if ((! allows_mem && GET_CODE (output_rtx[i]) == MEM)
- || GET_CODE (output_rtx[i]) == CONCAT)
+ if ((! allows_mem && GET_CODE (op) == MEM)
+ || GET_CODE (op) == CONCAT)
{
- real_output_rtx[i] = protect_from_queue (output_rtx[i], 1);
- output_rtx[i] = gen_reg_rtx (GET_MODE (output_rtx[i]));
+ real_output_rtx[i] = protect_from_queue (op, 1);
+ op = gen_reg_rtx (GET_MODE (op));
if (is_inout)
- emit_move_insn (output_rtx[i], real_output_rtx[i]);
+ emit_move_insn (op, real_output_rtx[i]);
}
}
else
{
- output_rtx[i] = assign_temp (type, 0, 0, 1);
- TREE_VALUE (tail) = make_tree (type, output_rtx[i]);
+ op = assign_temp (type, 0, 0, 1);
+ op = validize_mem (op);
+ TREE_VALUE (tail) = make_tree (type, op);
}
+ output_rtx[i] = op;
generating_concat_p = old_generating_concat_p;
@@ -1775,6 +1672,9 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
inout_mode[ninout] = TYPE_MODE (type);
inout_opnum[ninout++] = i;
}
+
+ if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
+ clobber_conflict_found = 1;
}
/* Make vectors for the expression-rtx, constraint strings,
@@ -1785,7 +1685,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode
: GET_MODE (output_rtx[0])),
- TREE_STRING_POINTER (string),
+ TREE_STRING_POINTER (string),
empty_string, 0, argvec, constraintvec,
filename, line);
@@ -1810,11 +1710,15 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
val = TREE_VALUE (tail);
type = TREE_TYPE (val);
- op = expand_expr (val, NULL_RTX, VOIDmode, 0);
+ op = expand_expr (val, NULL_RTX, VOIDmode,
+ (allows_mem && !allows_reg
+ ? EXPAND_MEMORY : EXPAND_NORMAL));
/* Never pass a CONCAT to an ASM. */
if (GET_CODE (op) == CONCAT)
op = force_reg (GET_MODE (op), op);
+ else if (GET_CODE (op) == MEM)
+ op = validize_mem (op);
if (asm_operand_ok (op, constraint) <= 0)
{
@@ -1823,35 +1727,36 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
else if (!allows_mem)
warning ("asm operand %d probably doesn't match constraints",
i + noutputs);
- else if (CONSTANT_P (op))
- op = force_const_mem (TYPE_MODE (type), op);
- else if (GET_CODE (op) == REG
- || GET_CODE (op) == SUBREG
- || GET_CODE (op) == ADDRESSOF
- || GET_CODE (op) == CONCAT)
+ else if (GET_CODE (op) == MEM)
{
- tree qual_type = build_qualified_type (type,
- (TYPE_QUALS (type)
- | TYPE_QUAL_CONST));
- rtx memloc = assign_temp (qual_type, 1, 1, 1);
-
- emit_move_insn (memloc, op);
- op = memloc;
+ /* We won't recognize either volatile memory or memory
+ with a queued address as available a memory_operand
+ at this point. Ignore it: clearly this *is* a memory. */
}
-
- else if (GET_CODE (op) == MEM && MEM_VOLATILE_P (op))
+ else
{
- /* We won't recognize volatile memory as available a
- memory_operand at this point. Ignore it. */
+ warning ("use of memory input without lvalue in "
+ "asm operand %d is deprecated", i + noutputs);
+
+ if (CONSTANT_P (op))
+ {
+ op = force_const_mem (TYPE_MODE (type), op);
+ op = validize_mem (op);
+ }
+ else if (GET_CODE (op) == REG
+ || GET_CODE (op) == SUBREG
+ || GET_CODE (op) == ADDRESSOF
+ || GET_CODE (op) == CONCAT)
+ {
+ tree qual_type = build_qualified_type (type,
+ (TYPE_QUALS (type)
+ | TYPE_QUAL_CONST));
+ rtx memloc = assign_temp (qual_type, 1, 1, 1);
+ memloc = validize_mem (memloc);
+ emit_move_insn (memloc, op);
+ op = memloc;
+ }
}
- else if (queued_subexp_p (op))
- ;
- else
- /* ??? Leave this only until we have experience with what
- happens in combine and elsewhere when constraints are
- not satisfied. */
- warning ("asm operand %d probably doesn't match constraints",
- i + noutputs);
}
generating_concat_p = old_generating_concat_p;
@@ -1859,6 +1764,9 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, i)
= gen_rtx_ASM_INPUT (TYPE_MODE (type), constraints[i + noutputs]);
+
+ if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
+ clobber_conflict_found = 1;
}
/* Protect all the operands from the queue now that they have all been
@@ -1943,6 +1851,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
{
const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
int j = decode_reg_name (regname);
+ rtx clobbered_reg;
if (j < 0)
{
@@ -1964,8 +1873,29 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
}
/* Use QImode since that's guaranteed to clobber just one reg. */
+ clobbered_reg = gen_rtx_REG (QImode, j);
+
+ /* Do sanity check for overlap between clobbers and respectively
+ input and outputs that hasn't been handled. Such overlap
+ should have been detected and reported above. */
+ if (!clobber_conflict_found)
+ {
+ int opno;
+
+ /* We test the old body (obody) contents to avoid tripping
+ over the under-construction body. */
+ for (opno = 0; opno < noutputs; opno++)
+ if (reg_overlap_mentioned_p (clobbered_reg, output_rtx[opno]))
+ internal_error ("asm clobber conflict with output operand");
+
+ for (opno = 0; opno < ninputs - ninout; opno++)
+ if (reg_overlap_mentioned_p (clobbered_reg,
+ ASM_OPERANDS_INPUT (obody, opno)))
+ internal_error ("asm clobber conflict with input operand");
+ }
+
XVECEXP (body, 0, i++)
- = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (QImode, j));
+ = gen_rtx_CLOBBER (VOIDmode, clobbered_reg);
}
insn = emit_insn (body);
@@ -2040,7 +1970,7 @@ check_unique_operand_names (outputs, inputs)
continue;
for (j = TREE_CHAIN (i); j ; j = TREE_CHAIN (j))
- if (i_name == TREE_PURPOSE (TREE_PURPOSE (j)))
+ if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
goto failure;
}
@@ -2051,10 +1981,10 @@ check_unique_operand_names (outputs, inputs)
continue;
for (j = TREE_CHAIN (i); j ; j = TREE_CHAIN (j))
- if (i_name == TREE_PURPOSE (TREE_PURPOSE (j)))
+ if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
goto failure;
for (j = outputs; j ; j = TREE_CHAIN (j))
- if (i_name == TREE_PURPOSE (TREE_PURPOSE (j)))
+ if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
goto failure;
}
@@ -2062,7 +1992,7 @@ check_unique_operand_names (outputs, inputs)
failure:
error ("duplicate asm operand name '%s'",
- IDENTIFIER_POINTER (TREE_PURPOSE (TREE_PURPOSE (i))));
+ TREE_STRING_POINTER (TREE_PURPOSE (TREE_PURPOSE (i))));
return false;
}
@@ -2131,7 +2061,7 @@ resolve_operand_names (string, outputs, inputs, pconstraints)
/* A subroutine of resolve_operand_names. P points to the '[' for a
potential named operand of the form [<name>]. In place, replace
- the name and brackets with a number. Return a pointer to the
+ the name and brackets with a number. Return a pointer to the
balance of the string after substitution. */
static char *
@@ -2156,20 +2086,20 @@ resolve_operand_name_1 (p, outputs, inputs)
/* Resolve the name to a number. */
for (op = 0, t = outputs; t ; t = TREE_CHAIN (t), op++)
{
- tree id = TREE_PURPOSE (TREE_PURPOSE (t));
- if (id)
+ tree name = TREE_PURPOSE (TREE_PURPOSE (t));
+ if (name)
{
- const char *c = IDENTIFIER_POINTER (id);
+ const char *c = TREE_STRING_POINTER (name);
if (strncmp (c, p + 1, len) == 0 && c[len] == '\0')
goto found;
}
}
for (t = inputs; t ; t = TREE_CHAIN (t), op++)
{
- tree id = TREE_PURPOSE (TREE_PURPOSE (t));
- if (id)
+ tree name = TREE_PURPOSE (TREE_PURPOSE (t));
+ if (name)
{
- const char *c = IDENTIFIER_POINTER (id);
+ const char *c = TREE_STRING_POINTER (name);
if (strncmp (c, p + 1, len) == 0 && c[len] == '\0')
goto found;
}
@@ -2408,7 +2338,8 @@ warn_if_unused_value (exp)
void
clear_last_expr ()
{
- last_expr_type = 0;
+ last_expr_type = NULL_TREE;
+ last_expr_value = NULL_RTX;
}
/* Begin a statement-expression, i.e., a series of statements which
@@ -2434,7 +2365,6 @@ expand_start_stmt_expr (has_scope)
start_sequence ();
NO_DEFER_POP;
expr_stmts_for_value++;
- last_expr_value = NULL_RTX;
return t;
}
@@ -2480,7 +2410,7 @@ expand_end_stmt_expr (t)
/* Propagate volatility of the actual RTL expr. */
TREE_THIS_VOLATILE (t) = volatile_refs_p (last_expr_value);
- last_expr_type = 0;
+ clear_last_expr ();
expr_stmts_for_value--;
return t;
@@ -2501,6 +2431,7 @@ expand_start_cond (cond, exitflag)
/* Make an entry on cond_stack for the cond we are entering. */
+ thiscond->desc = COND_NESTING;
thiscond->next = cond_stack;
thiscond->all = nesting_stack;
thiscond->depth = ++nesting_depth;
@@ -2571,7 +2502,7 @@ expand_end_cond ()
emit_label (thiscond->data.cond.endif_label);
POPSTACK (cond_stack);
- last_expr_type = 0;
+ clear_last_expr ();
}
/* Generate RTL for the start of a loop. EXIT_FLAG is nonzero if this
@@ -2589,6 +2520,7 @@ expand_start_loop (exit_flag)
/* Make an entry on loop_stack for the loop we are entering. */
+ thisloop->desc = LOOP_NESTING;
thisloop->next = loop_stack;
thisloop->all = nesting_stack;
thisloop->depth = ++nesting_depth;
@@ -2630,6 +2562,7 @@ expand_start_null_loop ()
/* Make an entry on loop_stack for the loop we are entering. */
+ thisloop->desc = LOOP_NESTING;
thisloop->next = loop_stack;
thisloop->all = nesting_stack;
thisloop->depth = ++nesting_depth;
@@ -2701,7 +2634,7 @@ expand_end_loop ()
the end of the entry condtional. Without this, our lexical scan
can't tell the difference between an entry conditional and a
body conditional that exits the loop. Mistaking the two means
- that we can misplace the NOTE_INSN_LOOP_CONT note, which can
+ that we can misplace the NOTE_INSN_LOOP_CONT note, which can
screw up loop unrolling.
Things will be oh so much better when loop optimization is done
@@ -2742,7 +2675,7 @@ expand_end_loop ()
/* Likewise for debug scopes. In this case we'll either (1) move
all of the notes if they are properly nested or (2) leave the
- notes alone and only rotate the loop at high optimization
+ notes alone and only rotate the loop at high optimization
levels when we expect to scrog debug info. */
else if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_BLOCK_BEG)
debug_blocks++;
@@ -2805,7 +2738,7 @@ expand_end_loop ()
POPSTACK (loop_stack);
- last_expr_type = 0;
+ clear_last_expr ();
}
/* Finish a null loop, aka do { } while (0). */
@@ -2818,7 +2751,7 @@ expand_end_null_loop ()
POPSTACK (loop_stack);
- last_expr_type = 0;
+ clear_last_expr ();
}
/* Generate a jump to the current loop's continue-point.
@@ -2830,7 +2763,15 @@ int
expand_continue_loop (whichloop)
struct nesting *whichloop;
{
- last_expr_type = 0;
+ /* Emit information for branch prediction. */
+ rtx note;
+
+ if (flag_guess_branch_prob)
+ {
+ note = emit_note (NULL, NOTE_INSN_PREDICTION);
+ NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_CONTINUE, IS_TAKEN);
+ }
+ clear_last_expr ();
if (whichloop == 0)
whichloop = loop_stack;
if (whichloop == 0)
@@ -2847,7 +2788,7 @@ int
expand_exit_loop (whichloop)
struct nesting *whichloop;
{
- last_expr_type = 0;
+ clear_last_expr ();
if (whichloop == 0)
whichloop = loop_stack;
if (whichloop == 0)
@@ -2867,7 +2808,7 @@ expand_exit_loop_if_false (whichloop, cond)
{
rtx label = gen_label_rtx ();
rtx last_insn;
- last_expr_type = 0;
+ clear_last_expr ();
if (whichloop == 0)
whichloop = loop_stack;
@@ -2889,7 +2830,7 @@ expand_exit_loop_if_false (whichloop, cond)
}
/* Like expand_exit_loop_if_false except also emit a note marking
- the end of the conditional. Should only be used immediately
+ the end of the conditional. Should only be used immediately
after expand_loop_start. */
int
@@ -2915,7 +2856,7 @@ stmt_loop_nest_empty ()
return (cfun->stmt == NULL || loop_stack == NULL);
}
-/* Return non-zero if we should preserve sub-expressions as separate
+/* Return nonzero if we should preserve sub-expressions as separate
pseudos. We never do so if we aren't optimizing. We always do so
if -fexpensive-optimizations.
@@ -2954,7 +2895,7 @@ int
expand_exit_something ()
{
struct nesting *n;
- last_expr_type = 0;
+ clear_last_expr ();
for (n = nesting_stack; n; n = n->all)
if (n->exit_label != 0)
{
@@ -2971,7 +2912,9 @@ expand_exit_something ()
void
expand_null_return ()
{
- rtx last_insn = get_last_insn ();
+ rtx last_insn;
+
+ last_insn = get_last_insn ();
/* If this function was declared to return a value, but we
didn't, clobber the return registers so that they are not
@@ -2981,14 +2924,59 @@ expand_null_return ()
expand_null_return_1 (last_insn);
}
+/* Try to guess whether the value of return means error code. */
+static enum br_predictor
+return_prediction (val)
+ rtx val;
+{
+ /* Different heuristics for pointers and scalars. */
+ if (POINTER_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
+ {
+ /* NULL is usually not returned. */
+ if (val == const0_rtx)
+ return PRED_NULL_RETURN;
+ }
+ else
+ {
+ /* Negative return values are often used to indicate
+ errors. */
+ if (GET_CODE (val) == CONST_INT
+ && INTVAL (val) < 0)
+ return PRED_NEGATIVE_RETURN;
+ /* Constant return values are also usually erors,
+ zero/one often mean booleans so exclude them from the
+ heuristics. */
+ if (CONSTANT_P (val)
+ && (val != const0_rtx && val != const1_rtx))
+ return PRED_CONST_RETURN;
+ }
+ return PRED_NO_PREDICTION;
+}
+
/* Generate RTL to return from the current function, with value VAL. */
static void
expand_value_return (val)
rtx val;
{
- rtx last_insn = get_last_insn ();
- rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
+ rtx last_insn;
+ rtx return_reg;
+ enum br_predictor pred;
+
+ if (flag_guess_branch_prob
+ && (pred = return_prediction (val)) != PRED_NO_PREDICTION)
+ {
+ /* Emit information for branch prediction. */
+ rtx note;
+
+ note = emit_note (NULL, NOTE_INSN_PREDICTION);
+
+ NOTE_PREDICTION (note) = NOTE_PREDICT (pred, NOT_TAKEN);
+
+ }
+
+ last_insn = get_last_insn ();
+ return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
/* Copy the value to the return location
unless it's already there. */
@@ -3026,7 +3014,7 @@ expand_null_return_1 (last_insn)
clear_pending_stack_adjust ();
do_pending_stack_adjust ();
- last_expr_type = 0;
+ clear_last_expr ();
if (end_label == 0)
end_label = return_label = gen_label_rtx ();
@@ -3067,7 +3055,7 @@ expand_return (retval)
/* Treat this like a return of no value from a function that
returns a value. */
expand_null_return ();
- return;
+ return;
}
else if (TREE_CODE (retval) == RESULT_DECL)
retval_rhs = retval;
@@ -3153,7 +3141,6 @@ expand_return (retval)
machine, this means we must skip the empty high order bytes when
calculating the bit offset. */
if (BYTES_BIG_ENDIAN
- && !FUNCTION_ARG_REG_LITTLE_ENDIAN
&& bytes % UNITS_PER_WORD)
big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
* BITS_PER_UNIT));
@@ -3360,15 +3347,15 @@ tail_recursion_args (actuals, formals)
else
{
rtx tmp = argvec[i];
-
+ int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_VALUE (a)));
+ promote_mode(TREE_TYPE (TREE_VALUE (a)), GET_MODE (tmp),
+ &unsignedp, 0);
if (DECL_MODE (f) != GET_MODE (DECL_RTL (f)))
{
tmp = gen_reg_rtx (DECL_MODE (f));
- convert_move (tmp, argvec[i],
- TREE_UNSIGNED (TREE_TYPE (TREE_VALUE (a))));
+ convert_move (tmp, argvec[i], unsignedp);
}
- convert_move (DECL_RTL (f), tmp,
- TREE_UNSIGNED (TREE_TYPE (TREE_VALUE (a))));
+ convert_move (DECL_RTL (f), tmp, unsignedp);
}
}
@@ -3422,6 +3409,7 @@ expand_start_bindings_and_block (flags, block)
/* Make an entry on block_stack for the block we are entering. */
+ thisblock->desc = BLOCK_NESTING;
thisblock->next = block_stack;
thisblock->all = nesting_stack;
thisblock->depth = ++nesting_depth;
@@ -3440,7 +3428,6 @@ expand_start_bindings_and_block (flags, block)
instructions inserted after the last unconditional cleanup are
never the last instruction. */
emit_note (NULL, NOTE_INSN_DELETED);
- thisblock->data.block.cleanup_ptr = &thisblock->data.block.cleanups;
if (block_stack
&& !(block_stack->data.block.cleanups == NULL_TREE
@@ -3492,7 +3479,7 @@ expand_end_target_temps ()
pop_temp_slots ();
}
-/* Given a pointer to a BLOCK node return non-zero if (and only if) the node
+/* Given a pointer to a BLOCK node return nonzero if (and only if) the node
in question represents the outermost pair of curly braces (i.e. the "body
block") of a function or method.
@@ -3558,7 +3545,7 @@ expand_nl_handler_label (slot, before_insn)
emit_move_insn (slot, gen_rtx_LABEL_REF (Pmode, handler_label));
insns = get_insns ();
end_sequence ();
- emit_insns_before (insns, before_insn);
+ emit_insn_before (insns, before_insn);
emit_label (handler_label);
@@ -3645,7 +3632,7 @@ expand_nl_goto_receivers (thisblock)
emit_move_insn (save_receiver, XEXP (slot, 0));
insns = get_insns ();
end_sequence ();
- emit_insns_before (insns, thisblock->data.block.first_insn);
+ emit_insn_before (insns, thisblock->data.block.first_insn);
}
/* Jump around the handlers; they run only when specially invoked. */
@@ -3935,6 +3922,7 @@ expand_decl (decl)
&& !(flag_float_store
&& TREE_CODE (type) == REAL_TYPE)
&& ! TREE_THIS_VOLATILE (decl)
+ && ! DECL_NONLOCAL (decl)
&& (DECL_REGISTER (decl) || optimize))
{
/* Automatic variable that can go in a register. */
@@ -3962,7 +3950,7 @@ expand_decl (decl)
/* If something wants our address, try to use ADDRESSOF. */
if (TREE_ADDRESSABLE (decl))
- put_var_into_stack (decl);
+ put_var_into_stack (decl, /*rescan=*/false);
}
else if (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST
@@ -4062,6 +4050,8 @@ expand_decl_init (decl)
/* Compute and store the initial value now. */
+ push_temp_slots ();
+
if (DECL_INITIAL (decl) == error_mark_node)
{
enum tree_code code = TREE_CODE (TREE_TYPE (decl));
@@ -4085,6 +4075,7 @@ expand_decl_init (decl)
/* Free any temporaries we made while initializing the decl. */
preserve_temp_slots (NULL_RTX);
free_temp_slots ();
+ pop_temp_slots ();
}
/* CLEANUP is an expression to be executed at exit from this binding contour;
@@ -4131,21 +4122,22 @@ expand_decl_cleanup (decl, cleanup)
end_sequence ();
thisblock->data.block.last_unconditional_cleanup
- = emit_insns_after (set_flag_0,
+ = emit_insn_after (set_flag_0,
thisblock->data.block.last_unconditional_cleanup);
emit_move_insn (flag, const1_rtx);
- cond = build_decl (VAR_DECL, NULL_TREE, type_for_mode (word_mode, 1));
+ cond = build_decl (VAR_DECL, NULL_TREE,
+ (*lang_hooks.types.type_for_mode) (word_mode, 1));
SET_DECL_RTL (cond, flag);
/* Conditionalize the cleanup. */
cleanup = build (COND_EXPR, void_type_node,
- truthvalue_conversion (cond),
+ (*lang_hooks.truthvalue_conversion) (cond),
cleanup, integer_zero_node);
cleanup = fold (cleanup);
- cleanups = thisblock->data.block.cleanup_ptr;
+ cleanups = &thisblock->data.block.cleanups;
}
cleanup = unsave_expr (cleanup);
@@ -4172,8 +4164,8 @@ expand_decl_cleanup (decl, cleanup)
end_sequence ();
if (seq)
thisblock->data.block.last_unconditional_cleanup
- = emit_insns_after (seq,
- thisblock->data.block.last_unconditional_cleanup);
+ = emit_insn_after (seq,
+ thisblock->data.block.last_unconditional_cleanup);
}
else
{
@@ -4186,7 +4178,6 @@ expand_decl_cleanup (decl, cleanup)
instructions inserted after the last unconditional cleanup are
never the last instruction. */
emit_note (NULL, NOTE_INSN_DELETED);
- thisblock->data.block.cleanup_ptr = &thisblock->data.block.cleanups;
}
}
return 1;
@@ -4292,7 +4283,7 @@ expand_anon_union_decl (decl, cleanup, decl_elts)
This is sometimes used to avoid a cleanup associated with
a value that is being returned out of the scope.
- If IN_FIXUP is non-zero, we are generating this cleanup for a fixup
+ If IN_FIXUP is nonzero, we are generating this cleanup for a fixup
goto and handle protection regions specially in that case.
If REACHABLE, we emit code, otherwise just inform the exception handling
@@ -4450,6 +4441,7 @@ expand_start_case (exit_flag, expr, type, printname)
/* Make an entry on case_stack for the case we are entering. */
+ thiscase->desc = CASE_NESTING;
thiscase->next = case_stack;
thiscase->all = nesting_stack;
thiscase->depth = ++nesting_depth;
@@ -4464,6 +4456,7 @@ expand_start_case (exit_flag, expr, type, printname)
nesting_stack = thiscase;
do_pending_stack_adjust ();
+ emit_queue ();
/* Make sure case_stmt.start points to something that won't
need any transformation before expand_end_case. */
@@ -4487,6 +4480,7 @@ expand_start_case_dummy ()
/* Make an entry on case_stack for the dummy. */
+ thiscase->desc = CASE_NESTING;
thiscase->next = case_stack;
thiscase->all = nesting_stack;
thiscase->depth = ++nesting_depth;
@@ -4738,7 +4732,7 @@ add_case_node (low, high, label, duplicate)
/* Add this label to the chain, and succeed. */
- r = (struct case_node *) xmalloc (sizeof (struct case_node));
+ r = (struct case_node *) ggc_alloc (sizeof (struct case_node));
r->low = low;
/* If the bounds are equal, turn this into the one-value case. */
@@ -5132,16 +5126,23 @@ mark_seen_cases (type, cases_seen, count, sparseness)
}
}
-/* Called when the index of a switch statement is an enumerated type
- and there is no default label.
+/* Given a switch statement with an expression that is an enumeration
+ type, warn if any of the enumeration type's literals are not
+ covered by the case expressions of the switch. Also, warn if there
+ are any extra switch cases that are *not* elements of the
+ enumerated type.
- Checks that all enumeration literals are covered by the case
- expressions of a switch. Also, warn if there are any extra
- switch cases that are *not* elements of the enumerated type.
+ Historical note:
- If all enumeration literals were covered by the case expressions,
- turn one of the expressions into the default expression since it should
- not be possible to fall through such a switch. */
+ At one stage this function would: ``If all enumeration literals
+ were covered by the case expressions, turn one of the expressions
+ into the default expression since it should not be possible to fall
+ through such a switch.''
+
+ That code has since been removed as: ``This optimization is
+ disabled because it causes valid programs to fail. ANSI C does not
+ guarantee that an expression with enum type will have a value that
+ is the same as one of the enumeration literals.'' */
void
check_for_full_enumeration_handling (type)
@@ -5163,9 +5164,6 @@ check_for_full_enumeration_handling (type)
/* The allocated size of cases_seen, in chars. */
HOST_WIDE_INT bytes_needed;
- if (! warn_switch)
- return;
-
size = all_cases_count (type, &sparseness);
bytes_needed = (size + HOST_BITS_PER_CHAR) / HOST_BITS_PER_CHAR;
@@ -5181,7 +5179,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
+ However, if type is an ENUMERAL_TYPE whose values do not
increase monotonically, O(N*log(N)) time may be needed. */
mark_seen_cases (type, cases_seen, size, sparseness);
@@ -5203,62 +5201,47 @@ check_for_full_enumeration_handling (type)
&& 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)
- {
- for (chain = TYPE_VALUES (type);
- chain && !tree_int_cst_equal (n->low, TREE_VALUE (chain));
- chain = TREE_CHAIN (chain))
- ;
-
- if (!chain)
- {
- if (TYPE_NAME (type) == 0)
- warning ("case value `%ld' not in enumerated type",
- (long) TREE_INT_CST_LOW (n->low));
- else
- warning ("case value `%ld' not in enumerated type `%s'",
- (long) TREE_INT_CST_LOW (n->low),
- IDENTIFIER_POINTER ((TREE_CODE (TYPE_NAME (type))
- == IDENTIFIER_NODE)
- ? TYPE_NAME (type)
- : DECL_NAME (TYPE_NAME (type))));
- }
- if (!tree_int_cst_equal (n->low, n->high))
- {
- for (chain = TYPE_VALUES (type);
- chain && !tree_int_cst_equal (n->high, TREE_VALUE (chain));
- chain = TREE_CHAIN (chain))
- ;
-
- if (!chain)
- {
- if (TYPE_NAME (type) == 0)
- warning ("case value `%ld' not in enumerated type",
- (long) TREE_INT_CST_LOW (n->high));
- else
- warning ("case value `%ld' not in enumerated type `%s'",
- (long) TREE_INT_CST_LOW (n->high),
- IDENTIFIER_POINTER ((TREE_CODE (TYPE_NAME (type))
- == IDENTIFIER_NODE)
- ? TYPE_NAME (type)
- : DECL_NAME (TYPE_NAME (type))));
- }
- }
- }
-}
+ for (n = case_stack->data.case_stmt.case_list; n; n = n->right)
+ {
+ for (chain = TYPE_VALUES (type);
+ chain && !tree_int_cst_equal (n->low, TREE_VALUE (chain));
+ chain = TREE_CHAIN (chain))
+ ;
-/* Free CN, and its children. */
+ if (!chain)
+ {
+ if (TYPE_NAME (type) == 0)
+ warning ("case value `%ld' not in enumerated type",
+ (long) TREE_INT_CST_LOW (n->low));
+ else
+ warning ("case value `%ld' not in enumerated type `%s'",
+ (long) TREE_INT_CST_LOW (n->low),
+ IDENTIFIER_POINTER ((TREE_CODE (TYPE_NAME (type))
+ == IDENTIFIER_NODE)
+ ? TYPE_NAME (type)
+ : DECL_NAME (TYPE_NAME (type))));
+ }
+ if (!tree_int_cst_equal (n->low, n->high))
+ {
+ for (chain = TYPE_VALUES (type);
+ chain && !tree_int_cst_equal (n->high, TREE_VALUE (chain));
+ chain = TREE_CHAIN (chain))
+ ;
-static void
-free_case_nodes (cn)
- case_node_ptr cn;
-{
- if (cn)
- {
- free_case_nodes (cn->left);
- free_case_nodes (cn->right);
- free (cn);
+ if (!chain)
+ {
+ if (TYPE_NAME (type) == 0)
+ warning ("case value `%ld' not in enumerated type",
+ (long) TREE_INT_CST_LOW (n->high));
+ else
+ warning ("case value `%ld' not in enumerated type `%s'",
+ (long) TREE_INT_CST_LOW (n->high),
+ IDENTIFIER_POINTER ((TREE_CODE (TYPE_NAME (type))
+ == IDENTIFIER_NODE)
+ ? TYPE_NAME (type)
+ : DECL_NAME (TYPE_NAME (type))));
+ }
+ }
}
}
@@ -5301,7 +5284,7 @@ expand_end_case_type (orig_index, orig_type)
do_pending_stack_adjust ();
- /* This might get an spurious warning in the presence of a syntax error;
+ /* This might get a spurious warning in the presence of a syntax error;
it could be fixed by moving the call to check_seenlabel after the
check for error_mark_node, and copying the code of check_seenlabel that
deals with case_stack->data.case_stmt.line_number_status /
@@ -5313,15 +5296,19 @@ expand_end_case_type (orig_index, orig_type)
/* An ERROR_MARK occurs for various reasons including invalid data type. */
if (index_type != error_mark_node)
{
- /* If switch expression was an enumerated type, check that all
- enumeration literals are covered by the cases.
- No sense trying this if there's a default case, however. */
-
- if (!thiscase->data.case_stmt.default_label
+ /* If the switch expression was an enumerated type, check that
+ exactly all enumeration literals are covered by the cases.
+ The check is made when -Wswitch was specified and there is no
+ default case, or when -Wswitch-enum was specified. */
+ if (((warn_switch && !thiscase->data.case_stmt.default_label)
+ || warn_switch_enum)
&& TREE_CODE (orig_type) == ENUMERAL_TYPE
&& TREE_CODE (index_expr) != INTEGER_CST)
check_for_full_enumeration_handling (orig_type);
+ if (warn_switch_default && !thiscase->data.case_stmt.default_label)
+ warning ("switch missing default case");
+
/* If we don't have a default-label, create one here,
after the body of the switch. */
if (thiscase->data.case_stmt.default_label == 0)
@@ -5492,21 +5479,21 @@ expand_end_case_type (orig_index, orig_type)
{
index_type = thiscase->data.case_stmt.nominal_type;
- /* Index jumptables from zero for suitable values of
+ /* Index jumptables from zero for suitable values of
minval to avoid a subtraction. */
- if (! optimize_size
- && compare_tree_int (minval, 0) > 0
- && compare_tree_int (minval, 3) < 0)
- {
- minval = integer_zero_node;
- range = maxval;
- }
+ if (! optimize_size
+ && compare_tree_int (minval, 0) > 0
+ && compare_tree_int (minval, 3) < 0)
+ {
+ minval = integer_zero_node;
+ range = maxval;
+ }
if (! try_tablejump (index_type, index_expr, minval, range,
table_label, default_label))
abort ();
}
-
+
/* Get table of labels to jump to, in order of case index. */
ncases = tree_low_cst (range, 0) + 1;
@@ -5519,11 +5506,11 @@ expand_end_case_type (orig_index, orig_type)
value since that should fit in a HOST_WIDE_INT while the
actual values may not. */
HOST_WIDE_INT i_low
- = tree_low_cst (fold (build (MINUS_EXPR, index_type,
- n->low, minval)), 1);
+ = tree_low_cst (fold (build (MINUS_EXPR, index_type,
+ n->low, minval)), 1);
HOST_WIDE_INT i_high
- = tree_low_cst (fold (build (MINUS_EXPR, index_type,
- n->high, minval)), 1);
+ = tree_low_cst (fold (build (MINUS_EXPR, index_type,
+ n->high, minval)), 1);
HOST_WIDE_INT i;
for (i = i_low; i <= i_high; i ++)
@@ -5571,7 +5558,6 @@ expand_end_case_type (orig_index, orig_type)
if (thiscase->exit_label)
emit_label (thiscase->exit_label);
- free_case_nodes (case_stack->data.case_stmt.case_list);
POPSTACK (case_stack);
free_temp_slots ();
@@ -6341,7 +6327,7 @@ emit_case_nodes (index, node, default_label, index_type)
else if (!low_bound && !high_bound)
{
/* Widen LOW and HIGH to the same width as INDEX. */
- tree type = type_for_mode (mode, unsignedp);
+ tree type = (*lang_hooks.types.type_for_mode) (mode, unsignedp);
tree low = build1 (CONVERT_EXPR, type, node->low);
tree high = build1 (CONVERT_EXPR, type, node->high);
rtx low_rtx, new_index, new_bound;
@@ -6355,7 +6341,7 @@ emit_case_nodes (index, node, default_label, index_type)
new_bound = expand_expr (fold (build (MINUS_EXPR, type,
high, low)),
NULL_RTX, mode, 0);
-
+
emit_cmp_and_jump_insns (new_index, new_bound, GT, NULL_RTX,
mode, 1, default_label);
}
@@ -6364,3 +6350,5 @@ emit_case_nodes (index, node, default_label, index_type)
}
}
}
+
+#include "gt-stmt.h"
diff --git a/contrib/gcc/stor-layout.c b/contrib/gcc/stor-layout.c
index c330fb6..4fb2908 100644
--- a/contrib/gcc/stor-layout.c
+++ b/contrib/gcc/stor-layout.c
@@ -1,6 +1,6 @@
/* C-compiler utilities for types and variables storage layout
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1996, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "toplev.h"
#include "ggc.h"
#include "target.h"
+#include "langhooks.h"
/* Set to one when set_sizetype has been called. */
static int sizetype_set;
@@ -47,7 +48,7 @@ tree sizetype_tab[(int) TYPE_KIND_LAST];
The value is measured in bits. */
unsigned int maximum_field_alignment;
-/* If non-zero, the alignment of a bitstring or (power-)set value, in bits.
+/* If nonzero, the alignment of a bitstring or (power-)set value, in bits.
May be overridden by front-ends. */
unsigned int set_alignment = 0;
@@ -59,11 +60,14 @@ static int reference_types_internal = 0;
static void finalize_record_size PARAMS ((record_layout_info));
static void finalize_type_size PARAMS ((tree));
static void place_union_field PARAMS ((record_layout_info, tree));
+static unsigned int update_alignment_for_field
+ PARAMS ((record_layout_info, tree,
+ unsigned int));
extern void debug_rli PARAMS ((record_layout_info));
/* SAVE_EXPRs for sizes of types and decls, waiting to be expanded. */
-static tree pending_sizes;
+static GTY(()) tree pending_sizes;
/* Nonzero means cannot safely call expand_expr now,
so put variable sizes onto `pending_sizes' instead. */
@@ -95,7 +99,7 @@ get_pending_sizes ()
return chain;
}
-/* Return non-zero if EXPR is present on the pending sizes list. */
+/* Return nonzero if EXPR is present on the pending sizes list. */
int
is_pending_size (expr)
@@ -151,7 +155,8 @@ variable_size (size)
just return SIZE unchanged. Likewise for self-referential sizes and
constant sizes. */
if (TREE_CONSTANT (size)
- || global_bindings_p () < 0 || contains_placeholder_p (size))
+ || (*lang_hooks.decls.global_bindings_p) () < 0
+ || contains_placeholder_p (size))
return size;
size = save_expr (size);
@@ -167,7 +172,7 @@ variable_size (size)
if (TREE_CODE (size) == SAVE_EXPR)
SAVE_EXPR_PERSISTENT_P (size) = 1;
- if (global_bindings_p ())
+ if ((*lang_hooks.decls.global_bindings_p) ())
{
if (TREE_CONSTANT (size))
error ("type size can't be explicitly evaluated");
@@ -178,7 +183,7 @@ variable_size (size)
}
if (immediate_size_expand)
- /* NULL_RTX is not defined; neither is the rtx type.
+ /* NULL_RTX is not defined; neither is the rtx type.
Also, we would like to pass const0_rtx here, but don't have it. */
expand_expr (size, expand_expr (integer_zero_node, NULL_RTX, VOIDmode, 0),
VOIDmode, 0);
@@ -281,7 +286,7 @@ int_mode_for_mode (mode)
case MODE_RANDOM:
if (mode == BLKmode)
- break;
+ break;
/* ... fall through ... */
@@ -293,6 +298,29 @@ int_mode_for_mode (mode)
return mode;
}
+/* Return the alignment of MODE. This will be bounded by 1 and
+ BIGGEST_ALIGNMENT. */
+
+unsigned int
+get_mode_alignment (mode)
+ enum machine_mode mode;
+{
+ unsigned int alignment;
+
+ if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
+ || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
+ alignment = GET_MODE_UNIT_SIZE (mode);
+ else
+ alignment = GET_MODE_SIZE (mode);
+
+ /* Extract the LSB of the size. */
+ alignment = alignment & -alignment;
+ alignment *= BITS_PER_UNIT;
+
+ alignment = MIN (BIGGEST_ALIGNMENT, MAX (1, alignment));
+ return alignment;
+}
+
/* Return the value of VALUE, rounded up to a multiple of DIVISOR.
This can only be applied to objects of a sizetype. */
@@ -338,6 +366,7 @@ layout_decl (decl, known_align)
{
tree type = TREE_TYPE (decl);
enum tree_code code = TREE_CODE (decl);
+ rtx rtl = NULL_RTX;
if (code == CONST_DECL)
return;
@@ -345,6 +374,8 @@ layout_decl (decl, known_align)
&& code != TYPE_DECL && code != FIELD_DECL)
abort ();
+ rtl = DECL_RTL_IF_SET (decl);
+
if (type == error_mark_node)
type = void_type_node;
@@ -379,7 +410,7 @@ layout_decl (decl, known_align)
&& (DECL_ALIGN (decl) == 0
|| (! (code == FIELD_DECL && DECL_PACKED (decl))
&& TYPE_ALIGN (type) > DECL_ALIGN (decl))))
- {
+ {
DECL_ALIGN (decl) = TYPE_ALIGN (type);
DECL_USER_ALIGN (decl) = 0;
}
@@ -405,7 +436,7 @@ layout_decl (decl, known_align)
}
}
- /* See if we can use an ordinary integer mode for a bit-field.
+ /* See if we can use an ordinary integer mode for a bit-field.
Conditions are: a fixed size that is correct for another mode
and occupying a complete byte or bytes on proper boundary. */
if (code == FIELD_DECL && DECL_BIT_FIELD (decl)
@@ -459,6 +490,15 @@ layout_decl (decl, known_align)
larger_than_size);
}
}
+
+ /* If the RTL was already set, update its mode and mem attributes. */
+ if (rtl)
+ {
+ PUT_MODE (rtl, DECL_MODE (decl));
+ SET_DECL_RTL (decl, 0);
+ set_mem_attributes (rtl, decl, 1);
+ SET_DECL_RTL (decl, rtl);
+ }
}
/* Hook for a front-end function that can modify the record layout as needed
@@ -476,7 +516,7 @@ set_lang_adjust_rli (f)
/* Begin laying out type T, which may be a RECORD_TYPE, UNION_TYPE, or
QUAL_UNION_TYPE. Return a pointer to a struct record_layout_info which
is to be passed to all other layout functions for this record. It is the
- responsibility of the caller to call `free' for the storage returned.
+ responsibility of the caller to call `free' for the storage returned.
Note that garbage collection is not permitted until we finish laying
out the record. */
@@ -484,7 +524,7 @@ record_layout_info
start_record_layout (t)
tree t;
{
- record_layout_info rli
+ record_layout_info rli
= (record_layout_info) xmalloc (sizeof (struct record_layout_info_s));
rli->t = t;
@@ -585,7 +625,7 @@ normalize_offset (poffset, pbitpos, off_align)
= size_binop (PLUS_EXPR, *poffset,
size_binop (MULT_EXPR, convert (sizetype, extra_aligns),
size_int (off_align / BITS_PER_UNIT)));
-
+
*pbitpos
= size_binop (FLOOR_MOD_EXPR, *pbitpos, bitsize_int (off_align));
}
@@ -642,66 +682,154 @@ rli_size_so_far (rli)
return bit_from_pos (rli->offset, rli->bitpos);
}
-/* Called from place_field to handle unions. */
+/* FIELD is about to be added to RLI->T. The alignment (in bits) of
+ the next available location is given by KNOWN_ALIGN. Update the
+ variable alignment fields in RLI, and return the alignment to give
+ the FIELD. */
-static void
-place_union_field (rli, field)
+static unsigned int
+update_alignment_for_field (rli, field, known_align)
record_layout_info rli;
tree field;
+ unsigned int known_align;
{
+ /* The alignment required for FIELD. */
unsigned int desired_align;
+ /* The type of this field. */
+ tree type = TREE_TYPE (field);
+ /* True if the field was explicitly aligned by the user. */
+ bool user_align;
- layout_decl (field, 0);
-
- DECL_FIELD_OFFSET (field) = size_zero_node;
- DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
- SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);
-
+ /* Lay out the field so we know what alignment it needs. For a
+ packed field, use the alignment as specified, disregarding what
+ the type would want. */
desired_align = DECL_ALIGN (field);
+ user_align = DECL_USER_ALIGN (field);
+ layout_decl (field, known_align);
+ if (! DECL_PACKED (field))
+ {
+ desired_align = DECL_ALIGN (field);
+ user_align = DECL_USER_ALIGN (field);
+ }
-#ifdef BIGGEST_FIELD_ALIGNMENT
- /* Some targets (i.e. i386) limit union field alignment
+ /* Some targets (i.e. i386, VMS) limit struct field alignment
to a lower boundary than alignment of variables unless
it was overridden by attribute aligned. */
- if (! DECL_USER_ALIGN (field))
- desired_align =
- MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
+#ifdef BIGGEST_FIELD_ALIGNMENT
+ if (!user_align)
+ desired_align
+ = MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
#endif
#ifdef ADJUST_FIELD_ALIGN
- if (! DECL_USER_ALIGN (field))
+ if (!user_align)
desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
#endif
- TYPE_USER_ALIGN (rli->t) |= DECL_USER_ALIGN (field);
-
- /* Union must be at least as aligned as any field requires. */
- rli->record_align = MAX (rli->record_align, desired_align);
- rli->unpadded_align = MAX (rli->unpadded_align, desired_align);
-
+ /* Record must have at least as much alignment as any field.
+ Otherwise, the alignment of the field within the record is
+ meaningless. */
+ if ((* targetm.ms_bitfield_layout_p) (rli->t)
+ && type != error_mark_node
+ && DECL_BIT_FIELD_TYPE (field)
+ && ! integer_zerop (TYPE_SIZE (type)))
+ {
+ /* Here, the alignment of the underlying type of a bitfield can
+ affect the alignment of a record; even a zero-sized field
+ can do this. The alignment should be to the alignment of
+ the type, except that for zero-size bitfields this only
+ applies if there was an immediately prior, nonzero-size
+ bitfield. (That's the way it is, experimentally.) */
+ if (! integer_zerop (DECL_SIZE (field))
+ ? ! DECL_PACKED (field)
+ : (rli->prev_field
+ && DECL_BIT_FIELD_TYPE (rli->prev_field)
+ && ! integer_zerop (DECL_SIZE (rli->prev_field))))
+ {
+ unsigned int type_align = TYPE_ALIGN (type);
+ type_align = MAX (type_align, desired_align);
+ if (maximum_field_alignment != 0)
+ type_align = MIN (type_align, maximum_field_alignment);
+ rli->record_align = MAX (rli->record_align, type_align);
+ rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
+ rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field));
+ }
+ else
+ desired_align = 1;
+ }
+ else
#ifdef PCC_BITFIELD_TYPE_MATTERS
- /* On the m88000, a bit field of declare type `int' forces the
- entire union to have `int' alignment. */
- if (PCC_BITFIELD_TYPE_MATTERS && DECL_BIT_FIELD_TYPE (field))
+ if (PCC_BITFIELD_TYPE_MATTERS && type != error_mark_node
+ && ! (* targetm.ms_bitfield_layout_p) (rli->t)
+ && DECL_BIT_FIELD_TYPE (field)
+ && ! integer_zerop (TYPE_SIZE (type)))
{
- unsigned int type_align = TYPE_ALIGN (TREE_TYPE (field));
+ /* For these machines, a zero-length field does not
+ affect the alignment of the structure as a whole.
+ It does, however, affect the alignment of the next field
+ within the structure. */
+ if (! integer_zerop (DECL_SIZE (field)))
+ rli->record_align = MAX (rli->record_align, desired_align);
+ else if (! DECL_PACKED (field) && !user_align)
+ desired_align = TYPE_ALIGN (type);
+
+ /* A named bit field of declared type `int'
+ forces the entire structure to have `int' alignment. */
+ if (DECL_NAME (field) != 0)
+ {
+ unsigned int type_align = TYPE_ALIGN (type);
#ifdef ADJUST_FIELD_ALIGN
- if (! TYPE_USER_ALIGN (TREE_TYPE (field)))
- type_align = ADJUST_FIELD_ALIGN (field, type_align);
+ if (! TYPE_USER_ALIGN (type))
+ type_align = ADJUST_FIELD_ALIGN (field, type_align);
#endif
- rli->record_align = MAX (rli->record_align, type_align);
- rli->unpadded_align = MAX (rli->unpadded_align, type_align);
- TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (TREE_TYPE (field));
+
+ if (maximum_field_alignment != 0)
+ type_align = MIN (type_align, maximum_field_alignment);
+ else if (DECL_PACKED (field))
+ type_align = MIN (type_align, BITS_PER_UNIT);
+
+ rli->record_align = MAX (rli->record_align, type_align);
+ rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field));
+ if (warn_packed)
+ rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
+ user_align |= TYPE_USER_ALIGN (type);
+ }
}
+ else
#endif
+ {
+ rli->record_align = MAX (rli->record_align, desired_align);
+ rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
+ rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field));
+ }
+
+ TYPE_USER_ALIGN (rli->t) |= user_align;
+
+ DECL_ALIGN (field) = desired_align;
+
+ return desired_align;
+}
+
+/* Called from place_field to handle unions. */
+
+static void
+place_union_field (rli, field)
+ record_layout_info rli;
+ tree field;
+{
+ update_alignment_for_field (rli, field, /*known_align=*/0);
+
+ DECL_FIELD_OFFSET (field) = size_zero_node;
+ DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
+ SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);
/* We assume the union's size will be a multiple of a byte so we don't
bother with BITPOS. */
if (TREE_CODE (rli->t) == UNION_TYPE)
rli->offset = size_binop (MAX_EXPR, rli->offset, DECL_SIZE_UNIT (field));
else if (TREE_CODE (rli->t) == QUAL_UNION_TYPE)
- rli->offset = fold (build (COND_EXPR, sizetype,
+ rli->offset = fold (build (COND_EXPR, sizetype,
DECL_QUALIFIER (field),
DECL_SIZE_UNIT (field), rli->offset));
}
@@ -722,10 +850,9 @@ place_field (rli, field)
record as it presently stands. */
unsigned int known_align;
unsigned int actual_align;
- unsigned int user_align;
/* The type of this field. */
tree type = TREE_TYPE (field);
-
+
if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
return;
@@ -766,98 +893,8 @@ place_field (rli, field)
& - tree_low_cst (rli->offset, 1)));
else
known_align = rli->offset_align;
-
- /* Lay out the field so we know what alignment it needs. For a
- packed field, use the alignment as specified, disregarding what
- the type would want. */
- desired_align = DECL_ALIGN (field);
- user_align = DECL_USER_ALIGN (field);
- layout_decl (field, known_align);
- if (! DECL_PACKED (field))
- {
- desired_align = DECL_ALIGN (field);
- user_align = DECL_USER_ALIGN (field);
- }
-
- /* Some targets (i.e. i386, VMS) limit struct field alignment
- to a lower boundary than alignment of variables unless
- it was overridden by attribute aligned. */
-#ifdef BIGGEST_FIELD_ALIGNMENT
- if (! user_align)
- desired_align
- = MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
-#endif
-
-#ifdef ADJUST_FIELD_ALIGN
- if (! user_align)
- desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
-#endif
-
- /* Record must have at least as much alignment as any field.
- Otherwise, the alignment of the field within the record is
- meaningless. */
- if ((* targetm.ms_bitfield_layout_p) (rli->t)
- && type != error_mark_node
- && DECL_BIT_FIELD_TYPE (field)
- && ! integer_zerop (TYPE_SIZE (type))
- && integer_zerop (DECL_SIZE (field)))
- {
- if (rli->prev_field
- && DECL_BIT_FIELD_TYPE (rli->prev_field)
- && ! integer_zerop (DECL_SIZE (rli->prev_field)))
- {
- rli->record_align = MAX (rli->record_align, desired_align);
- rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
- }
- else
- desired_align = 1;
- }
- else
-#ifdef PCC_BITFIELD_TYPE_MATTERS
- if (PCC_BITFIELD_TYPE_MATTERS && type != error_mark_node
- && ! (* targetm.ms_bitfield_layout_p) (rli->t)
- && DECL_BIT_FIELD_TYPE (field)
- && ! integer_zerop (TYPE_SIZE (type)))
- {
- /* For these machines, a zero-length field does not
- affect the alignment of the structure as a whole.
- It does, however, affect the alignment of the next field
- within the structure. */
- if (! integer_zerop (DECL_SIZE (field)))
- rli->record_align = MAX (rli->record_align, desired_align);
- else if (! DECL_PACKED (field))
- desired_align = TYPE_ALIGN (type);
-
- /* A named bit field of declared type `int'
- forces the entire structure to have `int' alignment. */
- if (DECL_NAME (field) != 0)
- {
- unsigned int type_align = TYPE_ALIGN (type);
-
-#ifdef ADJUST_FIELD_ALIGN
- if (! TYPE_USER_ALIGN (type))
- type_align = ADJUST_FIELD_ALIGN (field, type_align);
-#endif
-
- if (maximum_field_alignment != 0)
- type_align = MIN (type_align, maximum_field_alignment);
- else if (DECL_PACKED (field))
- type_align = MIN (type_align, BITS_PER_UNIT);
-
- rli->record_align = MAX (rli->record_align, type_align);
- rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field));
- if (warn_packed)
- rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
- user_align |= TYPE_USER_ALIGN (type);
- }
- }
- else
-#endif
- {
- rli->record_align = MAX (rli->record_align, desired_align);
- rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
- rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field));
- }
+
+ desired_align = update_alignment_for_field (rli, field, known_align);
if (warn_packed && DECL_PACKED (field))
{
@@ -942,7 +979,7 @@ place_field (rli, field)
> tree_low_cst (TYPE_SIZE (type), 1) / type_align)
rli->bitpos = round_up (rli->bitpos, type_align);
- user_align |= TYPE_USER_ALIGN (type);
+ TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
}
#endif
@@ -985,52 +1022,153 @@ place_field (rli, field)
/ type_align))
rli->bitpos = round_up (rli->bitpos, type_align);
- user_align |= TYPE_USER_ALIGN (type);
+ TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
}
#endif
- /* See the docs for TARGET_MS_BITFIELD_LAYOUT_P for details. */
+ /* See the docs for TARGET_MS_BITFIELD_LAYOUT_P for details.
+ A subtlety:
+ When a bit field is inserted into a packed record, the whole
+ size of the underlying type is used by one or more same-size
+ adjacent bitfields. (That is, if its long:3, 32 bits is
+ used in the record, and any additional adjacent long bitfields are
+ packed into the same chunk of 32 bits. However, if the size
+ changes, a new field of that size is allocated.) In an unpacked
+ record, this is the same as using alignment, but not eqivalent
+ when packing.
+
+ Note: for compatability, we use the type size, not the type alignment
+ to determine alignment, since that matches the documentation */
+
if ((* targetm.ms_bitfield_layout_p) (rli->t)
- && TREE_CODE (field) == FIELD_DECL
- && type != error_mark_node
- && ! DECL_PACKED (field)
- && rli->prev_field
- && DECL_SIZE (field)
- && host_integerp (DECL_SIZE (field), 1)
- && DECL_SIZE (rli->prev_field)
- && host_integerp (DECL_SIZE (rli->prev_field), 1)
- && host_integerp (rli->offset, 1)
- && host_integerp (TYPE_SIZE (type), 1)
- && host_integerp (TYPE_SIZE (TREE_TYPE (rli->prev_field)), 1)
- && ((DECL_BIT_FIELD_TYPE (rli->prev_field)
- && ! integer_zerop (DECL_SIZE (rli->prev_field)))
- || (DECL_BIT_FIELD_TYPE (field)
- && ! integer_zerop (DECL_SIZE (field))))
- && (! simple_cst_equal (TYPE_SIZE (type),
- TYPE_SIZE (TREE_TYPE (rli->prev_field)))
- /* If the previous field was a zero-sized bit-field, either
- it was ignored, in which case we must ensure the proper
- alignment of this field here, or it already forced the
- alignment of this field, in which case forcing the
- alignment again is harmless. So, do it in both cases. */
- || (DECL_BIT_FIELD_TYPE (rli->prev_field)
- && integer_zerop (DECL_SIZE (rli->prev_field)))))
+ && ((DECL_BIT_FIELD_TYPE (field) && ! DECL_PACKED (field))
+ || (rli->prev_field && ! DECL_PACKED (rli->prev_field))))
{
- unsigned int type_align = TYPE_ALIGN (type);
+ /* At this point, either the prior or current are bitfields,
+ (possibly both), and we're dealing with MS packing. */
+ tree prev_saved = rli->prev_field;
- if (rli->prev_field
- && DECL_BIT_FIELD_TYPE (rli->prev_field)
- /* If the previous bit-field is zero-sized, we've already
- accounted for its alignment needs (or ignored it, if
- appropriate) while placing it. */
- && ! integer_zerop (DECL_SIZE (rli->prev_field)))
- type_align = MAX (type_align,
- TYPE_ALIGN (TREE_TYPE (rli->prev_field)));
+ /* Is the prior field a bitfield? If so, handle "runs" of same
+ type size fields. */
+ if (rli->prev_field /* necessarily a bitfield if it exists. */)
+ {
+ /* If both are bitfields, nonzero, and the same size, this is
+ the middle of a run. Zero declared size fields are special
+ and handled as "end of run". (Note: it's nonzero declared
+ size, but equal type sizes!) (Since we know that both
+ the current and previous fields are bitfields by the
+ time we check it, DECL_SIZE must be present for both.) */
+ if (DECL_BIT_FIELD_TYPE (field)
+ && !integer_zerop (DECL_SIZE (field))
+ && !integer_zerop (DECL_SIZE (rli->prev_field))
+ && simple_cst_equal (TYPE_SIZE (type),
+ TYPE_SIZE (TREE_TYPE (rli->prev_field))) )
+ {
+ /* We're in the middle of a run of equal type size fields; make
+ sure we realign if we run out of bits. (Not decl size,
+ type size!) */
+ int bitsize = TREE_INT_CST_LOW (DECL_SIZE (field));
+ tree type_size = TYPE_SIZE(TREE_TYPE(rli->prev_field));
+
+ if (rli->remaining_in_alignment < bitsize)
+ {
+ /* out of bits; bump up to next 'word'. */
+ rli->offset = DECL_FIELD_OFFSET (rli->prev_field);
+ rli->bitpos = size_binop (PLUS_EXPR,
+ type_size,
+ DECL_FIELD_BIT_OFFSET(rli->prev_field));
+ rli->prev_field = field;
+ rli->remaining_in_alignment = TREE_INT_CST_LOW (type_size);
+ }
+ rli->remaining_in_alignment -= bitsize;
+ }
+ else
+ {
+ /* End of a run: if leaving a run of bitfields of the same type
+ size, we have to "use up" the rest of the bits of the type
+ size.
+
+ Compute the new position as the sum of the size for the prior
+ type and where we first started working on that type.
+ Note: since the beginning of the field was aligned then
+ of course the end will be too. No round needed. */
+
+ if (!integer_zerop (DECL_SIZE (rli->prev_field)))
+ {
+ tree type_size = TYPE_SIZE(TREE_TYPE(rli->prev_field));
+ rli->bitpos = size_binop (PLUS_EXPR,
+ type_size,
+ DECL_FIELD_BIT_OFFSET(rli->prev_field));
+ }
+ else
+ {
+ /* We "use up" size zero fields; the code below should behave
+ as if the prior field was not a bitfield. */
+ prev_saved = NULL;
+ }
+
+ /* Cause a new bitfield to be captured, either this time (if
+ currently a bitfield) or next time we see one. */
+ if (!DECL_BIT_FIELD_TYPE(field)
+ || integer_zerop (DECL_SIZE (field)))
+ {
+ rli->prev_field = NULL;
+ }
+ }
+ normalize_rli (rli);
+ }
+
+ /* If we're starting a new run of same size type bitfields
+ (or a run of non-bitfields), set up the "first of the run"
+ fields.
+
+ That is, if the current field is not a bitfield, or if there
+ was a prior bitfield the type sizes differ, or if there wasn't
+ a prior bitfield the size of the current field is nonzero.
+
+ Note: we must be sure to test ONLY the type size if there was
+ a prior bitfield and ONLY for the current field being zero if
+ there wasn't. */
+
+ if (!DECL_BIT_FIELD_TYPE (field)
+ || ( prev_saved != NULL
+ ? !simple_cst_equal (TYPE_SIZE (type),
+ TYPE_SIZE (TREE_TYPE (prev_saved)))
+ : !integer_zerop (DECL_SIZE (field)) ))
+ {
+ unsigned int type_align = 8; /* Never below 8 for compatability */
+
+ /* (When not a bitfield), we could be seeing a flex array (with
+ no DECL_SIZE). Since we won't be using remaining_in_alignment
+ until we see a bitfield (and come by here again) we just skip
+ calculating it. */
+
+ if (DECL_SIZE (field) != NULL)
+ rli->remaining_in_alignment
+ = TREE_INT_CST_LOW (TYPE_SIZE(TREE_TYPE(field)))
+ - TREE_INT_CST_LOW (DECL_SIZE (field));
+
+ /* Now align (conventionally) for the new type. */
+ if (!DECL_PACKED(field))
+ type_align = MAX(TYPE_ALIGN (type), type_align);
+
+ if (prev_saved
+ && DECL_BIT_FIELD_TYPE (prev_saved)
+ /* If the previous bit-field is zero-sized, we've already
+ accounted for its alignment needs (or ignored it, if
+ appropriate) while placing it. */
+ && ! integer_zerop (DECL_SIZE (prev_saved)))
+ type_align = MAX (type_align,
+ TYPE_ALIGN (TREE_TYPE (prev_saved)));
- if (maximum_field_alignment != 0)
- type_align = MIN (type_align, maximum_field_alignment);
+ if (maximum_field_alignment != 0)
+ type_align = MIN (type_align, maximum_field_alignment);
- rli->bitpos = round_up (rli->bitpos, type_align);
+ rli->bitpos = round_up (rli->bitpos, type_align);
+ /* If we really aligned, don't allow subsequent bitfields
+ to undo that. */
+ rli->prev_field = NULL;
+ }
}
/* Offset so far becomes the position of this field after normalizing. */
@@ -1039,8 +1177,6 @@ place_field (rli, field)
DECL_FIELD_BIT_OFFSET (field) = rli->bitpos;
SET_DECL_OFFSET_ALIGN (field, rli->offset_align);
- TYPE_USER_ALIGN (rli->t) |= user_align;
-
/* If this field ended up more aligned than we thought it would be (we
approximate this by seeing if its position changed), lay out the field
again; perhaps we can use an integral mode for it now. */
@@ -1059,7 +1195,9 @@ place_field (rli, field)
if (known_align != actual_align)
layout_decl (field, actual_align);
- rli->prev_field = field;
+ /* Only the MS bitfields use this. */
+ if (rli->prev_field == NULL && DECL_BIT_FIELD_TYPE(field))
+ rli->prev_field = field;
/* Now add size of this field to the size of the record. If the size is
not constant, treat the field as being a multiple of bytes and just
@@ -1146,7 +1284,7 @@ finalize_record_size (rli)
if (warn_padded && TREE_CONSTANT (unpadded_size)
&& simple_cst_equal (unpadded_size, TYPE_SIZE (rli->t)) == 0)
warning ("padding struct size to alignment boundary");
-
+
if (warn_packed && TREE_CODE (rli->t) == RECORD_TYPE
&& TYPE_PACKED (rli->t) && ! rli->packed_maybe_necessary
&& TREE_CONSTANT (unpadded_size))
@@ -1233,7 +1371,7 @@ compute_record_mode (type)
return;
bitpos = int_bit_position (field);
-
+
/* Must be BLKmode if any field crosses a word boundary,
since extract_bit_field can't handle that in registers. */
if (bitpos / BITS_PER_WORD
@@ -1253,16 +1391,7 @@ compute_record_mode (type)
/* With some targets, eg. c4x, it is sub-optimal
to access an aligned BLKmode structure as a scalar. */
- /* On ia64-*-hpux we need to ensure that we don't change the
- mode of a structure containing a single field or else we
- will pass it incorrectly. Since a structure with a single
- field causes mode to get set above we can't allow the
- check for mode == VOIDmode in this case. Perhaps
- MEMBER_TYPE_FORCES_BLK should be extended to include mode
- as an argument and the check could be put in there for c4x. */
-
- if ((mode == VOIDmode || FUNCTION_ARG_REG_LITTLE_ENDIAN)
- && MEMBER_TYPE_FORCES_BLK (field))
+ if (MEMBER_TYPE_FORCES_BLK (field, mode))
return;
#endif /* MEMBER_TYPE_FORCES_BLK */
}
@@ -1377,11 +1506,14 @@ finalize_type_size (type)
/* Do all of the work required to layout the type indicated by RLI,
once the fields have been laid out. This function will call `free'
- for RLI. */
+ for RLI, unless FREE_P is false. Passing a value other than false
+ for FREE_P is bad practice; this option only exists to support the
+ G++ 3.2 ABI. */
void
-finish_record_layout (rli)
+finish_record_layout (rli, free_p)
record_layout_info rli;
+ int free_p;
{
/* Compute the final size. */
finalize_record_size (rli);
@@ -1401,7 +1533,8 @@ finish_record_layout (rli)
}
/* Clean up. */
- free (rli);
+ if (free_p)
+ free (rli);
}
/* Calculate the mode, size, and alignment for TYPE.
@@ -1602,7 +1735,7 @@ layout_type (type)
TYPE_MODE (type) = BLKmode;
if (TYPE_SIZE (type) != 0
#ifdef MEMBER_TYPE_FORCES_BLK
- && ! MEMBER_TYPE_FORCES_BLK (type)
+ && ! MEMBER_TYPE_FORCES_BLK (type, VOIDmode)
#endif
/* BLKmode elements force BLKmode aggregate;
else extract/store fields may lose. */
@@ -1656,7 +1789,7 @@ layout_type (type)
(*lang_adjust_rli) (rli);
/* Finish laying out the record. */
- finish_record_layout (rli);
+ finish_record_layout (rli, /*free_p=*/true);
}
break;
@@ -1705,7 +1838,7 @@ layout_type (type)
/* Compute the final TYPE_SIZE, TYPE_ALIGN, etc. for TYPE. For
records and unions, finish_record_layout already called this
function. */
- if (TREE_CODE (type) != RECORD_TYPE
+ if (TREE_CODE (type) != RECORD_TYPE
&& TREE_CODE (type) != UNION_TYPE
&& TREE_CODE (type) != QUAL_UNION_TYPE)
finalize_type_size (type);
@@ -1848,9 +1981,6 @@ set_sizetype (type)
TYPE_REFERENCE_TO (sizetype_tab[i]) = 0;
}
- ggc_add_tree_root ((tree *) &sizetype_tab,
- sizeof sizetype_tab / sizeof (tree));
-
/* Go down each of the types we already made and set the proper type
for the sizes in them. */
for (t = early_type_list; t != 0; t = TREE_CHAIN (t))
@@ -2006,10 +2136,4 @@ get_best_mode (bitsize, bitpos, align, largest_mode, volatilep)
return mode;
}
-/* This function is run once to initialize stor-layout.c. */
-
-void
-init_stor_layout_once ()
-{
- ggc_add_tree_root (&pending_sizes, 1);
-}
+#include "gt-stor-layout.h"
diff --git a/contrib/gcc/stringpool.c b/contrib/gcc/stringpool.c
index e5b674a..6390486 100644
--- a/contrib/gcc/stringpool.c
+++ b/contrib/gcc/stringpool.c
@@ -110,7 +110,7 @@ get_identifier (text)
/* Identical to get_identifier, except that the length is assumed
known. */
-
+
tree
get_identifier_with_length (text, length)
const char *text;
@@ -158,7 +158,7 @@ mark_ident (pfile, h, v)
hashnode h;
const PTR v ATTRIBUTE_UNUSED;
{
- ggc_mark_nonnull_tree (HT_IDENT_TO_GCC_IDENT (h));
+ ggc_mark_tree (HT_IDENT_TO_GCC_IDENT (h));
return 1;
}
diff --git a/contrib/gcc/system.h b/contrib/gcc/system.h
index ca8a21c..c9598ab 100644
--- a/contrib/gcc/system.h
+++ b/contrib/gcc/system.h
@@ -23,11 +23,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#ifndef GCC_SYSTEM_H
#define GCC_SYSTEM_H
-/* This is the location of the online document giving information how
- to report bugs. If you change this string, also check for strings
- not under control of the preprocessor. */
-#define GCCBUGURL "<URL:http://www.gnu.org/software/gcc/bugs.html>"
-
/* We must include stdarg.h/varargs.h before stdio.h. */
#ifdef ANSI_PROTOTYPES
#include <stdarg.h>
@@ -266,6 +261,12 @@ extern int errno;
#ifndef WSTOPSIG
#define WSTOPSIG WEXITSTATUS
#endif
+#ifndef WCOREDUMP
+#define WCOREDUMP(S) ((S) & WCOREFLG)
+#endif
+#ifndef WCOREFLG
+#define WCOREFLG 0200
+#endif
/* The HAVE_DECL_* macros are three-state, undefined, 0 or 1. If they
are defined to 0 then we must provide the relevant declaration
@@ -579,11 +580,19 @@ typedef char _Bool;
compiling gcc, so that the autoconf declaration tests for malloc
etc don't spuriously fail. */
#ifdef IN_GCC
-#undef malloc
-#undef realloc
#undef calloc
#undef strdup
- #pragma GCC poison malloc realloc calloc strdup
+ #pragma GCC poison calloc strdup
+
+#if defined(FLEX_SCANNER) || defined (YYBISON)
+/* Flex and bison use malloc and realloc. Yuk. */
+#define malloc xmalloc
+#define realloc xrealloc
+#else
+#undef malloc
+#undef realloc
+ #pragma GCC poison malloc realloc
+#endif
/* Old target macros that have moved to the target hooks structure. */
#pragma GCC poison ASM_OPEN_PAREN ASM_CLOSE_PAREN \
@@ -594,9 +603,12 @@ typedef char _Bool;
SET_DEFAULT_TYPE_ATTRIBUTES SET_DEFAULT_DECL_ATTRIBUTES \
MERGE_MACHINE_TYPE_ATTRIBUTES MERGE_MACHINE_DECL_ATTRIBUTES \
MD_INIT_BUILTINS MD_EXPAND_BUILTIN ASM_OUTPUT_CONSTRUCTOR \
- ASM_OUTPUT_DESTRUCTOR SIGNED_CHAR_SPEC
+ ASM_OUTPUT_DESTRUCTOR SIGNED_CHAR_SPEC MAX_CHAR_TYPE_SIZE \
+ WCHAR_UNSIGNED UNIQUE_SECTION SELECT_SECTION SELECT_RTX_SECTION \
+ ENCODE_SECTION_INFO STRIP_NAME_ENCODING ASM_GLOBALIZE_LABEL \
+ ASM_OUTPUT_MI_THUNK
-/* And other obsolete target macros, or macros that used to be in target
+/* Other obsolete target macros, or macros that used to be in target
headers and were not used, and may be obsolete or may never have
been used. */
#pragma GCC poison INT_ASM_OP ASM_OUTPUT_EH_REGION_BEG \
@@ -606,9 +618,16 @@ typedef char _Bool;
LONGJMP_RESTORE_FROM_STACK MAX_INT_TYPE_SIZE ASM_IDENTIFY_GCC \
STDC_VALUE TRAMPOLINE_ALIGN ASM_IDENTIFY_GCC_AFTER_SOURCE \
SLOW_ZERO_EXTEND SUBREG_REGNO_OFFSET DWARF_LINE_MIN_INSTR_LENGTH \
- BLOCK_PROFILER BLOCK_PROFILER_CODE FUNCTION_BLOCK_PROFILER \
- FUNCTION_BLOCK_PROFILER_EXIT MACHINE_STATE_SAVE \
- MACHINE_STATE_RESTORE
+ TRADITIONAL_RETURN_FLOAT NO_BUILTIN_SIZE_TYPE \
+ NO_BUILTIN_PTRDIFF_TYPE NO_BUILTIN_WCHAR_TYPE NO_BUILTIN_WINT_TYPE \
+ BLOCK_PROFILER BLOCK_PROFILER_CODE FUNCTION_BLOCK_PROFILER \
+ FUNCTION_BLOCK_PROFILER_EXIT MACHINE_STATE_SAVE \
+ MACHINE_STATE_RESTORE SCCS_DIRECTIVE SECTION_ASM_OP \
+ ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
+
+/* Hooks that are no longer used. */
+ #pragma GCC poison LANG_HOOKS_FUNCTION_MARK LANG_HOOKS_FUNCTION_FREE \
+ LANG_HOOKS_MARK_TREE
#endif /* IN_GCC */
diff --git a/contrib/gcc/target-def.h b/contrib/gcc/target-def.h
index 71987f5..154d58d 100644
--- a/contrib/gcc/target-def.h
+++ b/contrib/gcc/target-def.h
@@ -54,11 +54,31 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TARGET_ASM_INTEGER default_assemble_integer
+#ifndef TARGET_ASM_GLOBALIZE_LABEL
+#define TARGET_ASM_GLOBALIZE_LABEL default_globalize_label
+#endif
+
+#ifndef TARGET_ASM_ASSEMBLE_VISIBILITY
+#define TARGET_ASM_ASSEMBLE_VISIBILITY default_assemble_visibility
+#endif
+
#define TARGET_ASM_FUNCTION_PROLOGUE default_function_pro_epilogue
#define TARGET_ASM_FUNCTION_EPILOGUE default_function_pro_epilogue
#define TARGET_ASM_FUNCTION_END_PROLOGUE no_asm_to_stream
#define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE no_asm_to_stream
+#ifndef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION default_select_section
+#endif
+
+#ifndef TARGET_ASM_UNIQUE_SECTION
+#define TARGET_ASM_UNIQUE_SECTION default_unique_section
+#endif
+
+#ifndef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION default_select_rtx_section
+#endif
+
#if !defined(TARGET_ASM_CONSTRUCTOR) && !defined(USE_COLLECT2)
# ifdef CTORS_SECTION_ASM_OP
# define TARGET_ASM_CONSTRUCTOR default_ctor_section_asm_out_constructor
@@ -83,6 +103,9 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# endif
#endif
+#define TARGET_ASM_OUTPUT_MI_THUNK NULL
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_false
+
#if defined(TARGET_ASM_CONSTRUCTOR) && defined(TARGET_ASM_DESTRUCTOR)
#define TARGET_HAVE_CTORS_DTORS true
#else
@@ -98,6 +121,22 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TARGET_HAVE_NAMED_SECTIONS false
#endif
+#ifndef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS false
+#endif
+
+#ifndef TARGET_HAVE_SRODATA_SECTION
+#define TARGET_HAVE_SRODATA_SECTION false
+#endif
+
+#ifndef TARGET_TERMINATE_DW2_EH_FRAME_INFO
+#ifdef EH_FRAME_SECTION_NAME
+#define TARGET_TERMINATE_DW2_EH_FRAME_INFO false
+#else
+#define TARGET_TERMINATE_DW2_EH_FRAME_INFO true
+#endif
+#endif
+
#ifndef TARGET_ASM_EXCEPTION_SECTION
#define TARGET_ASM_EXCEPTION_SECTION default_exception_section
#endif
@@ -124,6 +163,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_ASM_ALIGNED_INT_OP, \
TARGET_ASM_UNALIGNED_INT_OP, \
TARGET_ASM_INTEGER, \
+ TARGET_ASM_GLOBALIZE_LABEL, \
+ TARGET_ASM_ASSEMBLE_VISIBILITY, \
TARGET_ASM_FUNCTION_PROLOGUE, \
TARGET_ASM_FUNCTION_END_PROLOGUE, \
TARGET_ASM_FUNCTION_BEGIN_EPILOGUE, \
@@ -131,8 +172,13 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_ASM_NAMED_SECTION, \
TARGET_ASM_EXCEPTION_SECTION, \
TARGET_ASM_EH_FRAME_SECTION, \
+ TARGET_ASM_SELECT_SECTION, \
+ TARGET_ASM_SELECT_RTX_SECTION, \
+ TARGET_ASM_UNIQUE_SECTION, \
TARGET_ASM_CONSTRUCTOR, \
- TARGET_ASM_DESTRUCTOR}
+ TARGET_ASM_DESTRUCTOR, \
+ TARGET_ASM_OUTPUT_MI_THUNK, \
+ TARGET_ASM_CAN_OUTPUT_MI_THUNK }
/* Scheduler hooks. All of these default to null pointers, which
haifa-sched.c looks for and handles. */
@@ -144,27 +190,37 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TARGET_SCHED_FINISH 0
#define TARGET_SCHED_REORDER 0
#define TARGET_SCHED_REORDER2 0
-#define TARGET_SCHED_CYCLE_DISPLAY 0
-
-#define TARGET_SCHED {TARGET_SCHED_ADJUST_COST, \
- TARGET_SCHED_ADJUST_PRIORITY, \
- TARGET_SCHED_ISSUE_RATE, \
- TARGET_SCHED_VARIABLE_ISSUE, \
- TARGET_SCHED_INIT, \
- TARGET_SCHED_FINISH, \
- TARGET_SCHED_REORDER, \
- TARGET_SCHED_REORDER2, \
- TARGET_SCHED_CYCLE_DISPLAY}
+#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE 0
+#define TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN 0
+#define TARGET_SCHED_DFA_PRE_CYCLE_INSN 0
+#define TARGET_SCHED_INIT_DFA_POST_CYCLE_INSN 0
+#define TARGET_SCHED_DFA_POST_CYCLE_INSN 0
+#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD 0
+#define TARGET_SCHED_INIT_DFA_BUBBLES 0
+#define TARGET_SCHED_DFA_BUBBLE 0
+
+#define TARGET_SCHED \
+ {TARGET_SCHED_ADJUST_COST, \
+ TARGET_SCHED_ADJUST_PRIORITY, \
+ TARGET_SCHED_ISSUE_RATE, \
+ TARGET_SCHED_VARIABLE_ISSUE, \
+ TARGET_SCHED_INIT, \
+ TARGET_SCHED_FINISH, \
+ TARGET_SCHED_REORDER, \
+ TARGET_SCHED_REORDER2, \
+ TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE, \
+ TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN, \
+ TARGET_SCHED_DFA_PRE_CYCLE_INSN, \
+ TARGET_SCHED_INIT_DFA_POST_CYCLE_INSN, \
+ TARGET_SCHED_DFA_POST_CYCLE_INSN, \
+ TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD, \
+ TARGET_SCHED_INIT_DFA_BUBBLES, \
+ TARGET_SCHED_DFA_BUBBLE}
/* All in tree.c. */
#define TARGET_MERGE_DECL_ATTRIBUTES merge_decl_attributes
#define TARGET_MERGE_TYPE_ATTRIBUTES merge_type_attributes
-#define TARGET_ATTRIBUTE_TABLE default_target_attribute_table
-#define TARGET_COMP_TYPE_ATTRIBUTES default_comp_type_attributes
-#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES default_set_default_type_attributes
-#define TARGET_INSERT_ATTRIBUTES default_insert_attributes
-#define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P default_function_attribute_inlinable_p
-#define TARGET_MS_BITFIELD_LAYOUT_P default_ms_bitfield_layout_p
+#define TARGET_ATTRIBUTE_TABLE NULL
/* In builtins.c. */
#define TARGET_INIT_BUILTINS default_init_builtins
@@ -175,8 +231,30 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TARGET_SECTION_TYPE_FLAGS default_section_type_flags
#endif
+#ifndef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING default_strip_name_encoding
+#endif
+
+#ifndef TARGET_BINDS_LOCAL_P
+#define TARGET_BINDS_LOCAL_P default_binds_local_p
+#endif
+
/* In hook.c. */
-#define TARGET_CANNOT_MODIFY_JUMPS_P hook_void_bool_false
+#define TARGET_CANNOT_MODIFY_JUMPS_P hook_bool_void_false
+#define TARGET_CANNOT_FORCE_CONST_MEM hook_bool_rtx_false
+#define TARGET_COMP_TYPE_ATTRIBUTES hook_int_tree_tree_1
+#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES hook_void_tree
+#define TARGET_INSERT_ATTRIBUTES hook_void_tree_treeptr
+#define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P hook_bool_tree_false
+#define TARGET_MS_BITFIELD_LAYOUT_P hook_bool_tree_false
+
+#ifndef TARGET_IN_SMALL_DATA_P
+#define TARGET_IN_SMALL_DATA_P hook_bool_tree_false
+#endif
+
+#ifndef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO hook_void_tree_int
+#endif
/* The whole shebang. */
#define TARGET_INITIALIZER \
@@ -194,9 +272,17 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_INIT_BUILTINS, \
TARGET_EXPAND_BUILTIN, \
TARGET_SECTION_TYPE_FLAGS, \
+ TARGET_CANNOT_MODIFY_JUMPS_P, \
+ TARGET_CANNOT_FORCE_CONST_MEM, \
+ TARGET_IN_SMALL_DATA_P, \
+ TARGET_BINDS_LOCAL_P, \
+ TARGET_ENCODE_SECTION_INFO, \
+ TARGET_STRIP_NAME_ENCODING, \
TARGET_HAVE_NAMED_SECTIONS, \
TARGET_HAVE_CTORS_DTORS, \
- TARGET_CANNOT_MODIFY_JUMPS_P \
+ TARGET_HAVE_TLS, \
+ TARGET_HAVE_SRODATA_SECTION, \
+ TARGET_TERMINATE_DW2_EH_FRAME_INFO \
}
#include "hooks.h"
diff --git a/contrib/gcc/target.h b/contrib/gcc/target.h
index 5ee9aa6..0ac1c5a 100644
--- a/contrib/gcc/target.h
+++ b/contrib/gcc/target.h
@@ -69,6 +69,13 @@ struct gcc_target
and UNALIGNED_OP are NULL. */
bool (* integer) PARAMS ((rtx x, unsigned int size, int aligned_p));
+ /* Output code that will globalize a label. */
+ void (* globalize_label) PARAMS ((FILE *, const char *));
+
+ /* Emit an assembler directive to set visibility for the symbol
+ associated with the tree decl. */
+ void (* visibility) PARAMS ((tree, int));
+
/* Output the assembler code for entry to a function. */
void (* function_prologue) PARAMS ((FILE *, HOST_WIDE_INT));
@@ -91,11 +98,48 @@ struct gcc_target
/* Switch to the section that holds the exception frames. */
void (* eh_frame_section) PARAMS ((void));
+ /* Select and switch to a section for EXP. It may be a DECL or a
+ constant for which TREE_CST_RTL is valid. RELOC is nonzero if
+ runtime relocations must be applied; bit 1 will be set if the
+ runtime relocations require non-local name resolution. ALIGN is
+ the required alignment of the data. */
+ void (* select_section) PARAMS ((tree, int, unsigned HOST_WIDE_INT));
+
+ /* Select and switch to a section for X with MODE. ALIGN is
+ the desired alignment of the data. */
+ void (* select_rtx_section) PARAMS ((enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT));
+
+ /* Select a unique section name for DECL. RELOC is the same as
+ for SELECT_SECTION. */
+ void (* unique_section) PARAMS ((tree, int));
+
/* Output a constructor for a symbol with a given priority. */
void (* constructor) PARAMS ((rtx, int));
/* Output a destructor for a symbol with a given priority. */
void (* destructor) PARAMS ((rtx, int));
+
+ /* Output the assembler code for a thunk function. THUNK_DECL is the
+ declaration for the thunk function itself, FUNCTION is the decl for
+ the target function. DELTA is an immediate constant offset to be
+ added to THIS. If VCALL_OFFSET is nonzero, the word at
+ *(*this + vcall_offset) should be added to THIS. */
+ void (* output_mi_thunk) PARAMS ((FILE *file, tree thunk_decl,
+ HOST_WIDE_INT delta,
+ HOST_WIDE_INT vcall_offset,
+ tree function_decl));
+
+ /* Determine whether output_mi_thunk would succeed. */
+ /* ??? Ideally, this hook would not exist, and success or failure
+ would be returned from output_mi_thunk directly. But there's
+ too much undo-able setup involved in invoking output_mi_thunk.
+ Could be fixed by making output_mi_thunk emit rtl instead of
+ text to the output file. */
+ bool (* can_output_mi_thunk) PARAMS ((tree thunk_decl,
+ HOST_WIDE_INT delta,
+ HOST_WIDE_INT vcall_offset,
+ tree function_decl));
} asm_out;
/* Functions relating to instruction scheduling. */
@@ -118,7 +162,7 @@ struct gcc_target
/* Calculate how much this insn affects how many more insns we
can emit this cycle. Default is they all cost the same. */
int (* variable_issue) PARAMS ((FILE *, int, rtx, int));
-
+
/* Initialize machine-dependent scheduling code. */
void (* md_init) PARAMS ((FILE *, int, int));
@@ -130,12 +174,47 @@ struct gcc_target
int (* reorder) PARAMS ((FILE *, int, rtx *, int *, int));
int (* reorder2) PARAMS ((FILE *, int, rtx *, int *, int));
- /* cycle_display is a pointer to a function which can emit
- data into the assembly stream about the current cycle.
- Arguments are CLOCK, the data to emit, and LAST, the last
- insn in the new chain we're building. Returns a new LAST.
- The default is to do nothing. */
- rtx (* cycle_display) PARAMS ((int clock, rtx last));
+ /* The following member value is a pointer to a function returning
+ nonzero if we should use DFA based scheduling. The default is
+ to use the old pipeline scheduler. */
+ int (* use_dfa_pipeline_interface) PARAMS ((void));
+ /* The values of all the following members are used only for the
+ DFA based scheduler: */
+ /* The values of the following four members are pointers to
+ functions used to simplify the automaton descriptions.
+ dfa_pre_cycle_insn and dfa_post_cycle_insn give functions
+ returning insns which are used to change the pipeline hazard
+ recognizer state when the new simulated processor cycle
+ correspondingly starts and finishes. The function defined by
+ init_dfa_pre_cycle_insn and init_dfa_post_cycle_insn are used
+ to initialize the corresponding insns. The default values of
+ the memebers result in not changing the automaton state when
+ the new simulated processor cycle correspondingly starts and
+ finishes. */
+ void (* init_dfa_pre_cycle_insn) PARAMS ((void));
+ rtx (* dfa_pre_cycle_insn) PARAMS ((void));
+ void (* init_dfa_post_cycle_insn) PARAMS ((void));
+ rtx (* dfa_post_cycle_insn) PARAMS ((void));
+ /* The following member value is a pointer to a function returning value
+ which defines how many insns in queue `ready' will we try for
+ multi-pass scheduling. if the member value is nonzero and the
+ function returns positive value, the DFA based scheduler will make
+ multi-pass scheduling for the first cycle. In other words, we will
+ try to choose ready insn which permits to start maximum number of
+ insns on the same cycle. */
+ int (* first_cycle_multipass_dfa_lookahead) PARAMS ((void));
+ /* The values of the following members are pointers to functions
+ used to improve the first cycle multipass scheduling by
+ inserting nop insns. dfa_scheduler_bubble gives a function
+ returning a nop insn with given index. The indexes start with
+ zero. The function should return NULL if there are no more nop
+ insns with indexes greater than given index. To initialize the
+ nop insn the function given by member
+ init_dfa_scheduler_bubbles is used. The default values of the
+ members result in not inserting nop insns during the multipass
+ scheduling. */
+ void (* init_dfa_bubbles) PARAMS ((void));
+ rtx (* dfa_bubble) PARAMS ((int));
} sched;
/* Given two decls, merge their attributes and return the result. */
@@ -144,7 +223,8 @@ struct gcc_target
/* Given two types, merge their attributes and return the result. */
tree (* merge_type_attributes) PARAMS ((tree, tree));
- /* Table of machine attributes and functions to handle them. */
+ /* Table of machine attributes and functions to handle them.
+ Ignored if NULL. */
const struct attribute_spec *attribute_table;
/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
@@ -178,6 +258,29 @@ struct gcc_target
/* ??? Should be merged with SELECT_SECTION and UNIQUE_SECTION. */
unsigned int (* section_type_flags) PARAMS ((tree, const char *, int));
+ /* True if new jumps cannot be created, to replace existing ones or
+ not, at the current point in the compilation. */
+ bool (* cannot_modify_jumps_p) PARAMS ((void));
+
+ /* True if the constant X cannot be placed in the constant pool. */
+ bool (* cannot_force_const_mem) PARAMS ((rtx));
+
+ /* True if EXP should be placed in a "small data" section. */
+ bool (* in_small_data_p) PARAMS ((tree));
+
+ /* True if EXP names an object for which name resolution must resolve
+ to the current module. */
+ bool (* binds_local_p) PARAMS ((tree));
+
+ /* Do something target-specific to record properties of the DECL into
+ the associated SYMBOL_REF. */
+ void (* encode_section_info) PARAMS ((tree, int));
+
+ /* Undo the effects of encode_section_info on the symbol string. */
+ const char * (* strip_name_encoding) PARAMS ((const char *));
+
+ /* Leave the boolean fields at the end. */
+
/* True if arbitrary sections are supported. */
bool have_named_sections;
@@ -185,9 +288,14 @@ struct gcc_target
false if we're using collect2 for the job. */
bool have_ctors_dtors;
- /* True if new jumps cannot be created, to replace existing ones or
- not, at the current point in the compilation. */
- bool (* cannot_modify_jumps_p) PARAMS ((void));
+ /* True if thread-local storage is supported. */
+ bool have_tls;
+
+ /* True if a small readonly data section is supported. */
+ bool have_srodata_section;
+
+ /* True if EH frame info sections should be zero-terminated. */
+ bool terminate_dw2_eh_frame_info;
};
extern struct gcc_target targetm;
diff --git a/contrib/gcc/timevar.c b/contrib/gcc/timevar.c
index 8d6ab8c..47f2a68 100644
--- a/contrib/gcc/timevar.c
+++ b/contrib/gcc/timevar.c
@@ -111,10 +111,11 @@ static float clocks_to_msec;
#include "flags.h"
#include "timevar.h"
+#include "toplev.h"
/* See timevar.h for an explanation of timing variables. */
-/* This macro evaluates to non-zero if timing variables are enabled. */
+/* This macro evaluates to nonzero if timing variables are enabled. */
#define TIMEVAR_ENABLE (time_report)
/* A timing variable. */
@@ -171,12 +172,12 @@ static struct timevar_time_def start_time;
static void get_time
PARAMS ((struct timevar_time_def *));
static void timevar_accumulate
- PARAMS ((struct timevar_time_def *, struct timevar_time_def *,
+ PARAMS ((struct timevar_time_def *, struct timevar_time_def *,
struct timevar_time_def *));
/* Fill the current times into TIME. The definition of this function
also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
- HAVA_WALL_TIME macros. */
+ HAVE_WALL_TIME macros. */
static void
get_time (now)
@@ -210,11 +211,11 @@ get_time (now)
/* Add the difference between STOP_TIME and START_TIME to TIMER. */
-static void
+static void
timevar_accumulate (timer, start_time, stop_time)
- struct timevar_time_def *timer;
- struct timevar_time_def *start_time;
- struct timevar_time_def *stop_time;
+ struct timevar_time_def *timer;
+ struct timevar_time_def *start_time;
+ struct timevar_time_def *stop_time;
{
timer->user += stop_time->user - start_time->user;
timer->sys += stop_time->sys - start_time->sys;
@@ -249,7 +250,7 @@ init_timevar ()
/* Push TIMEVAR onto the timing stack. No further elapsed time is
attributed to the previous topmost timing variable on the stack;
subsequent elapsed time is attributed to TIMEVAR, until it is
- popped or another element is pushed on top.
+ popped or another element is pushed on top.
TIMEVAR cannot be running as a standalone timer. */
@@ -285,13 +286,13 @@ timevar_push (timevar)
/* See if we have a previously-allocated stack instance. If so,
take it off the list. If not, malloc a new one. */
- if (unused_stack_instances != NULL)
+ if (unused_stack_instances != NULL)
{
context = unused_stack_instances;
unused_stack_instances = unused_stack_instances->next;
}
else
- context = (struct timevar_stack_def *)
+ context = (struct timevar_stack_def *)
xmalloc (sizeof (struct timevar_stack_def));
/* Fill it in and put it on the stack. */
@@ -317,7 +318,11 @@ timevar_pop (timevar)
return;
if (&timevars[timevar] != stack->timevar)
- abort ();
+ {
+ sorry ("cannot timevar_pop '%s' when top of timevars stack is '%s'",
+ timevars[timevar].name, stack->timevar->name);
+ abort ();
+ }
/* What time is it? */
get_time (&now);
@@ -396,7 +401,7 @@ timevar_get (timevar, elapsed)
struct timevar_time_def now;
*elapsed = tv->elapsed;
-
+
/* Is TIMEVAR currently running as a standalone timer? */
if (tv->standalone)
{
@@ -472,21 +477,21 @@ timevar_print (fp)
#ifdef HAVE_USER_TIME
/* Print user-mode time for this process. */
- fprintf (fp, "%7.2f (%2.0f%%) usr",
+ fprintf (fp, "%7.2f (%2.0f%%) usr",
tv->elapsed.user,
(total->user == 0 ? 0 : tv->elapsed.user / total->user) * 100);
#endif /* HAVE_USER_TIME */
#ifdef HAVE_SYS_TIME
/* Print system-mode time for this process. */
- fprintf (fp, "%7.2f (%2.0f%%) sys",
+ fprintf (fp, "%7.2f (%2.0f%%) sys",
tv->elapsed.sys,
(total->sys == 0 ? 0 : tv->elapsed.sys / total->sys) * 100);
#endif /* HAVE_SYS_TIME */
#ifdef HAVE_WALL_TIME
/* Print wall clock time elapsed. */
- fprintf (fp, "%7.2f (%2.0f%%) wall",
+ fprintf (fp, "%7.2f (%2.0f%%) wall",
tv->elapsed.wall,
(total->wall == 0 ? 0 : tv->elapsed.wall / total->wall) * 100);
#endif /* HAVE_WALL_TIME */
@@ -498,15 +503,15 @@ timevar_print (fp)
fputs (_(" TOTAL :"), fp);
#ifdef HAVE_USER_TIME
fprintf (fp, "%7.2f ", total->user);
-#endif
+#endif
#ifdef HAVE_SYS_TIME
fprintf (fp, "%7.2f ", total->sys);
#endif
#ifdef HAVE_WALL_TIME
fprintf (fp, "%7.2f\n", total->wall);
#endif
-
-#endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
+
+#endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
|| defined (HAVE_WALL_TIME) */
}
@@ -533,6 +538,6 @@ print_time (str, total)
fprintf (stderr,
_("time in %s: %ld.%06ld (%ld%%)\n"),
str, total / 1000000, total % 1000000,
- all_time == 0 ? 0
- : (long) (((100.0 * (double) total) / (double) all_time) + .5));
+ all_time == 0 ? 0
+ : (long) (((100.0 * (double) total) / (double) all_time) + .5));
}
diff --git a/contrib/gcc/timevar.def b/contrib/gcc/timevar.def
index 353a942..d26f10a 100644
--- a/contrib/gcc/timevar.def
+++ b/contrib/gcc/timevar.def
@@ -43,6 +43,7 @@ DEFTIMEVAR (TV_DUMP , "dump files")
DEFTIMEVAR (TV_CFG , "cfg construction")
/* Time spent by cleaning up CFG. */
DEFTIMEVAR (TV_CLEANUP_CFG , "cfg cleanup")
+DEFTIMEVAR (TV_DELETE_TRIVIALLY_DEAD , "trivially dead code")
/* Time spent by life analysis. */
DEFTIMEVAR (TV_LIFE , "life analysis")
DEFTIMEVAR (TV_LIFE_UPDATE , "life info update")
@@ -50,6 +51,9 @@ DEFTIMEVAR (TV_LIFE_UPDATE , "life info update")
DEFTIMEVAR (TV_CPP , "preprocessing")
DEFTIMEVAR (TV_LEX , "lexical analysis")
DEFTIMEVAR (TV_PARSE , "parser")
+DEFTIMEVAR (TV_NAME_LOOKUP , "name lookup")
+DEFTIMEVAR (TV_OVERLOAD , "overload resolution")
+DEFTIMEVAR (TV_TEMPLATE_INSTANTIATION, "template instantiation")
DEFTIMEVAR (TV_EXPAND , "expand")
DEFTIMEVAR (TV_VARCONST , "varconst")
DEFTIMEVAR (TV_INTEGRATION , "integration")
@@ -57,6 +61,7 @@ DEFTIMEVAR (TV_JUMP , "jump")
DEFTIMEVAR (TV_CSE , "CSE")
DEFTIMEVAR (TV_GCSE , "global CSE")
DEFTIMEVAR (TV_LOOP , "loop analysis")
+DEFTIMEVAR (TV_TRACER , "tracer")
DEFTIMEVAR (TV_CSE2 , "CSE 2")
DEFTIMEVAR (TV_BRANCH_PROB , "branch prediction")
DEFTIMEVAR (TV_FLOW , "flow analysis")
diff --git a/contrib/gcc/timevar.h b/contrib/gcc/timevar.h
index f0d2fd2..dcf1701 100644
--- a/contrib/gcc/timevar.h
+++ b/contrib/gcc/timevar.h
@@ -41,9 +41,9 @@
- As a standalone timer, using timevar_start and timevar_stop.
All time elapsed between the two calls is attributed to the
- variable.
+ variable.
*/
-
+
/* This structure stores the various varieties of time that can be
measured. Times are stored in seconds. The time may be an
absolute time or a time difference; in the former case, the time
@@ -67,7 +67,7 @@ struct timevar_time_def
the contents of timevar.def. */
#define DEFTIMEVAR(identifier__, name__) \
- identifier__,
+ identifier__,
typedef enum
{
#include "timevar.def"
@@ -76,6 +76,9 @@ typedef enum
timevar_id_t;
#undef DEFTIMEVAR
+/* Execute the sequence: timevar_pop (TV), return (E); */
+#define POP_TIMEVAR_AND_RETURN(TV, E) return (timevar_pop (TV), (E))
+
extern void init_timevar PARAMS ((void));
extern void timevar_push PARAMS ((timevar_id_t));
extern void timevar_pop PARAMS ((timevar_id_t));
diff --git a/contrib/gcc/tlink.c b/contrib/gcc/tlink.c
index 78840ca..a98b55b 100644
--- a/contrib/gcc/tlink.c
+++ b/contrib/gcc/tlink.c
@@ -24,27 +24,24 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
#include "intl.h"
-#include "hash.h"
+#include "obstack.h"
+#include "hashtab.h"
#include "demangle.h"
#include "collect2.h"
#define MAX_ITERATIONS 17
-/* Obstack allocation and deallocation routines. */
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
/* Defined in the automatically-generated underscore.c. */
extern int prepends_underscore;
static int tlink_verbose;
-/* Hash table boilerplate for working with hash.[ch]. We have hash tables
+/* Hash table boilerplate for working with htab_t. We have hash tables
for symbol names, file names, and demangled symbols. */
typedef struct symbol_hash_entry
{
- struct hash_entry root;
+ const char *key;
struct file_hash_entry *file;
int chosen;
int tweaking;
@@ -53,7 +50,7 @@ typedef struct symbol_hash_entry
typedef struct file_hash_entry
{
- struct hash_entry root;
+ const char *key;
const char *args;
const char *dir;
const char *main;
@@ -62,24 +59,38 @@ typedef struct file_hash_entry
typedef struct demangled_hash_entry
{
- struct hash_entry root;
+ const char *key;
const char *mangled;
} demangled;
-static struct hash_table symbol_table;
+/* Hash and comparison functions for these hash tables. */
+
+static int hash_string_eq PARAMS ((const void *, const void *));
+static hashval_t hash_string_hash PARAMS ((const void *));
+
+static int
+hash_string_eq (s1_p, s2_p)
+ const void *s1_p;
+ const void *s2_p;
+{
+ const char *const *s1 = (const char *const *) s1_p;
+ const char *s2 = (const char *) s2_p;
+ return strcmp (*s1, s2) == 0;
+}
+
+static hashval_t
+hash_string_hash (s_p)
+ const void *s_p;
+{
+ const char *const *s = (const char *const *) s_p;
+ return (*htab_hash_string) (*s);
+}
+
+static htab_t symbol_table;
-static struct hash_entry * symbol_hash_newfunc PARAMS ((struct hash_entry *,
- struct hash_table *,
- hash_table_key));
static struct symbol_hash_entry * symbol_hash_lookup PARAMS ((const char *,
int));
-static struct hash_entry * file_hash_newfunc PARAMS ((struct hash_entry *,
- struct hash_table *,
- hash_table_key));
static struct file_hash_entry * file_hash_lookup PARAMS ((const char *));
-static struct hash_entry * demangled_hash_newfunc PARAMS ((struct hash_entry *,
- struct hash_table *,
- hash_table_key));
static struct demangled_hash_entry *
demangled_hash_lookup PARAMS ((const char *, int));
static void symbol_push PARAMS ((symbol *));
@@ -100,30 +111,6 @@ static int read_repo_files PARAMS ((char **));
static void demangle_new_symbols PARAMS ((void));
static int scan_linker_output PARAMS ((const char *));
-/* Create a new entry for the symbol hash table.
- Passed to hash_table_init. */
-
-static struct hash_entry *
-symbol_hash_newfunc (entry, table, string)
- struct hash_entry *entry;
- struct hash_table *table;
- hash_table_key string ATTRIBUTE_UNUSED;
-{
- struct symbol_hash_entry *ret = (struct symbol_hash_entry *) entry;
- if (ret == NULL)
- {
- ret = ((struct symbol_hash_entry *)
- hash_allocate (table, sizeof (struct symbol_hash_entry)));
- if (ret == NULL)
- return NULL;
- }
- ret->file = NULL;
- ret->chosen = 0;
- ret->tweaking = 0;
- ret->tweaked = 0;
- return (struct hash_entry *) ret;
-}
-
/* Look up an entry in the symbol hash table. */
static struct symbol_hash_entry *
@@ -131,71 +118,44 @@ symbol_hash_lookup (string, create)
const char *string;
int create;
{
- return ((struct symbol_hash_entry *)
- hash_lookup (&symbol_table, (const hash_table_key) string,
- create, string_copy));
-}
-
-static struct hash_table file_table;
-
-/* Create a new entry for the file hash table.
- Passed to hash_table_init. */
-
-static struct hash_entry *
-file_hash_newfunc (entry, table, string)
- struct hash_entry *entry;
- struct hash_table *table;
- hash_table_key string ATTRIBUTE_UNUSED;
-{
- struct file_hash_entry *ret = (struct file_hash_entry *) entry;
- if (ret == NULL)
+ PTR *e;
+ e = htab_find_slot_with_hash (symbol_table, string,
+ (*htab_hash_string) (string),
+ create ? INSERT : NO_INSERT);
+ if (e == NULL)
+ return NULL;
+ if (*e == NULL)
{
- ret = ((struct file_hash_entry *)
- hash_allocate (table, sizeof (struct file_hash_entry)));
- if (ret == NULL)
- return NULL;
+ struct symbol_hash_entry *v;
+ *e = v = xcalloc (1, sizeof (*v));
+ v->key = xstrdup (string);
}
- ret->args = NULL;
- ret->dir = NULL;
- ret->main = NULL;
- ret->tweaking = 0;
- return (struct hash_entry *) ret;
+ return *e;
}
+static htab_t file_table;
+
/* Look up an entry in the file hash table. */
static struct file_hash_entry *
file_hash_lookup (string)
const char *string;
{
- return ((struct file_hash_entry *)
- hash_lookup (&file_table, (const hash_table_key) string, true,
- string_copy));
-}
-
-static struct hash_table demangled_table;
-
-/* Create a new entry for the demangled name hash table.
- Passed to hash_table_init. */
-
-static struct hash_entry *
-demangled_hash_newfunc (entry, table, string)
- struct hash_entry *entry;
- struct hash_table *table;
- hash_table_key string ATTRIBUTE_UNUSED;
-{
- struct demangled_hash_entry *ret = (struct demangled_hash_entry *) entry;
- if (ret == NULL)
+ PTR *e;
+ e = htab_find_slot_with_hash (file_table, string,
+ (*htab_hash_string) (string),
+ INSERT);
+ if (*e == NULL)
{
- ret = ((struct demangled_hash_entry *)
- hash_allocate (table, sizeof (struct demangled_hash_entry)));
- if (ret == NULL)
- return NULL;
+ struct file_hash_entry *v;
+ *e = v = xcalloc (1, sizeof (*v));
+ v->key = xstrdup (string);
}
- ret->mangled = NULL;
- return (struct hash_entry *) ret;
+ return *e;
}
+static htab_t demangled_table;
+
/* Look up an entry in the demangled name hash table. */
static struct demangled_hash_entry *
@@ -203,9 +163,19 @@ demangled_hash_lookup (string, create)
const char *string;
int create;
{
- return ((struct demangled_hash_entry *)
- hash_lookup (&demangled_table, (const hash_table_key) string,
- create, string_copy));
+ PTR *e;
+ e = htab_find_slot_with_hash (demangled_table, string,
+ (*htab_hash_string) (string),
+ create ? INSERT : NO_INSERT);
+ if (e == NULL)
+ return NULL;
+ if (*e == NULL)
+ {
+ struct demangled_hash_entry *v;
+ *e = v = xcalloc (1, sizeof (*v));
+ v->key = xstrdup (string);
+ }
+ return *e;
}
/* Stack code. */
@@ -290,12 +260,13 @@ tlink_init ()
{
const char *p;
- hash_table_init (&symbol_table, symbol_hash_newfunc, string_hash,
- string_compare);
- hash_table_init (&file_table, file_hash_newfunc, string_hash,
- string_compare);
- hash_table_init (&demangled_table, demangled_hash_newfunc,
- string_hash, string_compare);
+ symbol_table = htab_create (500, hash_string_hash, hash_string_eq,
+ NULL);
+ file_table = htab_create (500, hash_string_hash, hash_string_eq,
+ NULL);
+ demangled_table = htab_create (500, hash_string_hash, hash_string_eq,
+ NULL);
+
obstack_begin (&symbol_stack_obstack, 0);
obstack_begin (&file_stack_obstack, 0);
@@ -320,7 +291,7 @@ tlink_execute (prog, argv, redir)
{
collect_execute (prog, argv, redir);
return collect_wait (prog);
-}
+}
static char *
frob_extension (s, ext)
@@ -363,7 +334,7 @@ static char *
pfgets (stream)
FILE *stream;
{
- return obstack_fgets (stream, &permanent_obstack);
+ return xstrdup (tfgets (stream));
}
/* Real tlink code. */
@@ -422,11 +393,10 @@ read_repo_file (f)
file *f;
{
char c;
- FILE *stream = fopen ((char*) f->root.key, "r");
+ FILE *stream = fopen (f->key, "r");
if (tlink_verbose >= 2)
- fprintf (stderr, _("collect: reading %s\n"),
- (char*) f->root.key);
+ fprintf (stderr, _("collect: reading %s\n"), f->key);
while (fscanf (stream, "%c ", &c) == 1)
{
@@ -497,12 +467,12 @@ recompile_files ()
putenv (xstrdup ("COMPILER_PATH"));
putenv (xstrdup ("LIBRARY_PATH"));
-
+
while ((f = file_pop ()) != NULL)
{
char *line, *command;
- FILE *stream = fopen ((char*) f->root.key, "r");
- const char *const outname = frob_extension ((char*) f->root.key, ".rnw");
+ FILE *stream = fopen (f->key, "r");
+ const char *const outname = frob_extension (f->key, ".rnw");
FILE *output = fopen (outname, "w");
while ((line = tfgets (stream)) != NULL)
@@ -517,7 +487,7 @@ recompile_files ()
}
fclose (stream);
fclose (output);
- rename (outname, (char*) f->root.key);
+ rename (outname, f->key);
obstack_grow (&temporary_obstack, "cd ", 3);
obstack_grow (&temporary_obstack, f->dir, strlen (f->dir));
@@ -587,14 +557,13 @@ demangle_new_symbols ()
while ((sym = symbol_pop ()) != NULL)
{
demangled *dem;
- const char *p = cplus_demangle ((char*) sym->root.key,
- DMGL_PARAMS | DMGL_ANSI);
+ const char *p = cplus_demangle (sym->key, DMGL_PARAMS | DMGL_ANSI);
if (! p)
continue;
dem = demangled_hash_lookup (p, true);
- dem->mangled = (char*) sym->root.key;
+ dem->mangled = sym->key;
}
}
@@ -613,21 +582,21 @@ scan_linker_output (fname)
char *p = line, *q;
symbol *sym;
int end;
-
- while (*p && ISSPACE ((unsigned char)*p))
+
+ while (*p && ISSPACE ((unsigned char) *p))
++p;
if (! *p)
continue;
- for (q = p; *q && ! ISSPACE ((unsigned char)*q); ++q)
+ for (q = p; *q && ! ISSPACE ((unsigned char) *q); ++q)
;
/* Try the first word on the line. */
if (*p == '.')
++p;
- if (*p == '_' && prepends_underscore)
- ++p;
+ if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
+ p += strlen (USER_LABEL_PREFIX);
end = ! *q;
*q = 0;
@@ -636,21 +605,21 @@ scan_linker_output (fname)
/* Some SVR4 linkers produce messages like
ld: 0711-317 ERROR: Undefined symbol: .g__t3foo1Zi
*/
- if (! sym && ! end && strstr (q+1, "Undefined symbol: "))
+ if (! sym && ! end && strstr (q + 1, "Undefined symbol: "))
{
- char *p = strrchr (q+1, ' ');
+ char *p = strrchr (q + 1, ' ');
p++;
if (*p == '.')
p++;
- if (*p == '_' && prepends_underscore)
- p++;
+ if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
+ p += strlen (USER_LABEL_PREFIX);
sym = symbol_hash_lookup (p, false);
}
if (! sym && ! end)
/* Try a mangled name in quotes. */
{
- const char *oldq = q+1;
+ const char *oldq = q + 1;
demangled *dem = 0;
q = 0;
@@ -662,10 +631,16 @@ scan_linker_output (fname)
else if (p = strchr (oldq, '"'), p)
p++, q = strchr (p, '"');
- /* Don't let the strstr's below see the demangled name; we
- might get spurious matches. */
if (p)
- p[-1] = '\0';
+ {
+ /* Don't let the strstr's below see the demangled name; we
+ might get spurious matches. */
+ p[-1] = '\0';
+
+ /* powerpc64-linux references .foo when calling function foo. */
+ if (*p == '.')
+ p++;
+ }
/* We need to check for certain error keywords here, or we would
mistakenly use GNU ld's "In function `foo':" message. */
@@ -679,9 +654,10 @@ scan_linker_output (fname)
if (dem)
sym = symbol_hash_lookup (dem->mangled, false);
else
- {
- if (*p == '_' && prepends_underscore)
- ++p;
+ {
+ if (!strncmp (p, USER_LABEL_PREFIX,
+ strlen (USER_LABEL_PREFIX)))
+ p += strlen (USER_LABEL_PREFIX);
sym = symbol_hash_lookup (p, false);
}
}
@@ -696,11 +672,11 @@ scan_linker_output (fname)
{
if (tlink_verbose >= 2)
fprintf (stderr, _("collect: tweaking %s in %s\n"),
- (char*) sym->root.key, (char*) sym->file->root.key);
+ sym->key, sym->file->key);
sym->tweaking = 1;
file_push (sym->file);
}
-
+
obstack_free (&temporary_obstack, temporary_firstobj);
}
diff --git a/contrib/gcc/toplev.c b/contrib/gcc/toplev.c
index c40beea..f213f2d 100644
--- a/contrib/gcc/toplev.c
+++ b/contrib/gcc/toplev.c
@@ -1,6 +1,6 @@
/* Top level of GNU C compiler
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -29,7 +29,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#undef FFS /* Some systems define this in param.h. */
#include "system.h"
#include <signal.h>
-#include <setjmp.h>
#ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
@@ -67,9 +66,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "reload.h"
#include "dwarf2asm.h"
#include "integrate.h"
+#include "real.h"
#include "debug.h"
#include "target.h"
#include "langhooks.h"
+#include "cfglayout.h"
#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
#include "dwarf2out.h"
@@ -87,10 +88,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "xcoffout.h" /* Needed for external data
declarations for e.g. AIX 4.x. */
#endif
-
-#ifdef HALF_PIC_DEBUG
-#include "halfpic.h"
-#endif
/* Carry information from ASM_DECLARE_OBJECT_NAME
to ASM_FINISH_DECLARE_OBJECT. */
@@ -98,21 +95,20 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
extern int size_directive_output;
extern tree last_assemble_variable_decl;
+extern void reg_alloc PARAMS ((void));
+
static void general_init PARAMS ((char *));
static void parse_options_and_default_flags PARAMS ((int, char **));
static void do_compile PARAMS ((void));
static void process_options PARAMS ((void));
-static void lang_independent_init PARAMS ((void));
+static void backend_init PARAMS ((void));
static int lang_dependent_init PARAMS ((const char *));
static void init_asm_output PARAMS ((const char *));
static void finalize PARAMS ((void));
static void set_target_switch PARAMS ((const char *));
-static const char *decl_name PARAMS ((tree, int));
-static void float_signal PARAMS ((int)) ATTRIBUTE_NORETURN;
static void crash_signal PARAMS ((int)) ATTRIBUTE_NORETURN;
-static void set_float_handler PARAMS ((jmp_buf));
static void compile_file PARAMS ((void));
static void display_help PARAMS ((void));
static void display_target_options PARAMS ((void));
@@ -130,6 +126,9 @@ static int print_single_switch PARAMS ((FILE *, int, int, const char *,
static void print_switch_values PARAMS ((FILE *, int, int, const char *,
const char *, const char *));
+/* Nonzero to dump debug info whilst parsing (-dy option). */
+static int set_yydebug;
+
/* Length of line when printing switch values. */
#define MAX_LINE 75
@@ -170,6 +169,10 @@ int input_file_stack_tick;
const char *dump_base_name;
+/* Name to use as a base for auxiliary output files. */
+
+const char *aux_base_name;
+
/* Format to use to print dumpfile index value */
#ifndef DUMPFILE_FORMAT
#define DUMPFILE_FORMAT ".%02d."
@@ -181,9 +184,14 @@ const char *dump_base_name;
extern int target_flags;
+/* A mask of target_flags that includes bit X if X was set or cleared
+ on the command line. */
+
+int target_flags_explicit;
+
/* Debug hooks - dependent upon command line options. */
-struct gcc_debug_hooks *debug_hooks = &do_nothing_debug_hooks;
+const struct gcc_debug_hooks *debug_hooks = &do_nothing_debug_hooks;
/* Describes a dump file. */
@@ -217,16 +225,19 @@ enum dump_file_index
DFI_ssa_ccp,
DFI_ssa_dce,
DFI_ussa,
+ DFI_null,
DFI_cse,
DFI_addressof,
DFI_gcse,
DFI_loop,
- DFI_cse2,
DFI_cfg,
DFI_bp,
+ DFI_ce1,
+ DFI_tracer,
+ DFI_cse2,
DFI_life,
DFI_combine,
- DFI_ce,
+ DFI_ce2,
DFI_regmove,
DFI_sched,
DFI_lreg,
@@ -235,7 +246,7 @@ enum dump_file_index
DFI_flow2,
DFI_peephole2,
DFI_rnreg,
- DFI_ce2,
+ DFI_ce3,
DFI_sched2,
DFI_stack,
DFI_bbro,
@@ -249,7 +260,7 @@ enum dump_file_index
Remaining -d letters:
- " o q u "
+ " o q "
" H JK OPQ TUV YZ"
*/
@@ -263,16 +274,19 @@ static struct dump_file_info dump_file[DFI_MAX] =
{ "ssaccp", 'W', 1, 0, 0 },
{ "ssadce", 'X', 1, 0, 0 },
{ "ussa", 'e', 1, 0, 0 }, /* Yes, duplicate enable switch. */
+ { "null", 'u', 0, 0, 0 },
{ "cse", 's', 0, 0, 0 },
{ "addressof", 'F', 0, 0, 0 },
{ "gcse", 'G', 1, 0, 0 },
{ "loop", 'L', 1, 0, 0 },
- { "cse2", 't', 1, 0, 0 },
{ "cfg", 'f', 1, 0, 0 },
{ "bp", 'b', 1, 0, 0 },
+ { "ce1", 'C', 1, 0, 0 },
+ { "tracer", 'T', 1, 0, 0 },
+ { "cse2", 't', 1, 0, 0 },
{ "life", 'f', 1, 0, 0 }, /* Yes, duplicate enable switch. */
{ "combine", 'c', 1, 0, 0 },
- { "ce", 'C', 1, 0, 0 },
+ { "ce2", 'C', 1, 0, 0 },
{ "regmove", 'N', 1, 0, 0 },
{ "sched", 'S', 1, 0, 0 },
{ "lreg", 'l', 1, 0, 0 },
@@ -281,7 +295,7 @@ static struct dump_file_info dump_file[DFI_MAX] =
{ "flow2", 'w', 1, 0, 0 },
{ "peephole2", 'z', 1, 0, 0 },
{ "rnreg", 'n', 1, 0, 0 },
- { "ce2", 'E', 1, 0, 0 },
+ { "ce3", 'E', 1, 0, 0 },
{ "sched2", 'R', 1, 0, 0 },
{ "stack", 'k', 1, 0, 0 },
{ "bbro", 'B', 1, 0, 0 },
@@ -334,8 +348,8 @@ int use_gnu_debug_info_extensions = 0;
int optimize = 0;
/* Nonzero means optimize for size. -Os.
- The only valid values are zero and non-zero. When optimize_size is
- non-zero, optimize defaults to 2, but certain individual code
+ The only valid values are zero and nonzero. When optimize_size is
+ nonzero, optimize defaults to 2, but certain individual code
bloating optimizations are disabled. */
int optimize_size = 0;
@@ -351,29 +365,6 @@ tree current_function_decl;
if none. */
tree current_function_func_begin_label;
-/* 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++. */
-
-const char *(*decl_printable_name) PARAMS ((tree, int));
-
-/* Pointer to function to compute rtl for a language-specific tree code. */
-
-typedef rtx (*lang_expand_expr_t)
- PARAMS ((union tree_node *, rtx, enum machine_mode,
- enum expand_modifier modifier));
-
-lang_expand_expr_t lang_expand_expr = 0;
-
-/* Pointer to function to finish handling an incomplete decl at the
- end of compilation. */
-
-void (*incomplete_decl_finalize_hook) PARAMS ((tree)) = 0;
-
/* Nonzero if doing dwarf2 duplicate elimination. */
int flag_eliminate_dwarf2_dups = 0;
@@ -398,6 +389,10 @@ int flag_branch_probabilities = 0;
int flag_reorder_blocks = 0;
+/* Nonzero if functions should be reordered. */
+
+int flag_reorder_functions = 0;
+
/* Nonzero if registers should be renamed. */
int flag_rename_registers = 0;
@@ -582,12 +577,24 @@ int flag_errno_math = 1;
int flag_unsafe_math_optimizations = 0;
+/* Nonzero means that no NaNs or +-Infs are expected. */
+
+int flag_finite_math_only = 0;
+
/* Zero means that floating-point math operations cannot generate a
(user-visible) trap. This is the case, for example, in nonstop
- IEEE 754 arithmetic. */
+ IEEE 754 arithmetic. Trapping conditions include division by zero,
+ overflow, underflow, invalid and inexact, but does not include
+ operations on signaling NaNs (see below). */
int flag_trapping_math = 1;
+/* Nonzero means disable transformations observable by signaling NaNs.
+ This option implies that any operation on a IEEE signaling NaN can
+ generate a (user-visible) trap. */
+
+int flag_signaling_nans = 0;
+
/* 0 means straightforward implementation of complex divide acceptable.
1 means wide ranges of inputs must work for complex divide.
2 means C99-like requirements for complex divide (not yet implemented). */
@@ -614,6 +621,22 @@ int flag_syntax_only = 0;
static int flag_gcse;
+/* Nonzero means perform loop optimizer. */
+
+static int flag_loop_optimize;
+
+/* Nonzero means perform crossjumping. */
+
+static int flag_crossjumping;
+
+/* Nonzero means perform if conversion. */
+
+static int flag_if_conversion;
+
+/* Nonzero means perform if conversion after reload. */
+
+static int flag_if_conversion2;
+
/* Nonzero means to use global dataflow analysis to eliminate
useless null pointer tests. */
@@ -682,12 +705,15 @@ int flag_shared_data;
int flag_delayed_branch;
/* Nonzero if we are compiling pure (sharable) code.
- Value is 1 if we are doing reasonable (i.e. simple
- offset into offset table) pic. Value is 2 if we can
- only perform register offsets. */
+ Value is 1 if we are doing "small" pic; value is 2 if we're doing
+ "large" pic. */
int flag_pic;
+/* Set to the default thread-local storage (tls) model to use. */
+
+enum tls_model flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
+
/* Nonzero means generate extra code for exception handling and enable
exception handling. */
@@ -706,12 +732,6 @@ int flag_asynchronous_unwind_tables = 0;
int flag_no_common;
-/* Nonzero means pretend it is OK to examine bits of target floats,
- even if that isn't true. The resulting code will have incorrect constants,
- but the same series of instructions that the native compiler would make. */
-
-int flag_pretend_float;
-
/* Nonzero means change certain warnings into errors.
Usually these are warnings about failure to conform to some standard. */
@@ -783,6 +803,9 @@ int flag_gnu_linker = 0;
int flag_gnu_linker = 1;
#endif
+/* Nonzero means put zero initialized data in the bss section. */
+int flag_zero_initialized_in_bss = 1;
+
/* Enable SSA. */
int flag_ssa = 0;
@@ -837,19 +860,10 @@ int flag_peephole2 = 0;
/* This will try to guess branch probabilities. */
int flag_guess_branch_prob = 0;
-/* -fbounded-pointers causes gcc to compile pointers as composite
- objects occupying three words: the pointer value, the base address
- of the referent object, and the address immediately beyond the end
- of the referent object. The base and extent allow us to perform
- runtime bounds checking. -fbounded-pointers implies -fcheck-bounds. */
-int flag_bounded_pointers = 0;
-
/* -fcheck-bounds causes gcc to generate array bounds checks.
- For C, C++: defaults to value of flag_bounded_pointers.
- For ObjC: defaults to off.
+ For C, C++, ObjC: defaults to off.
For Java: defaults to on.
- For Fortran: defaults to off.
- For CHILL: defaults to off. */
+ For Fortran: defaults to off. */
int flag_bounds_check = 0;
/* This will attempt to merge constant section constants, if 1 only
@@ -862,6 +876,13 @@ int flag_merge_constants = 1;
one, unconditionally renumber instruction UIDs. */
int flag_renumber_insns = 1;
+/* If nonzero, use the graph coloring register allocator. */
+int flag_new_regalloc = 0;
+
+/* Nonzero if we perform superblock formation. */
+
+int flag_tracer = 0;
+
/* Values of the -falign-* flags: how much to align labels in code.
0 means `use default', 1 means `don't align'.
For each variable, there is an _log variant which is the power
@@ -948,11 +969,6 @@ static const param_info lang_independent_params[] = {
{ NULL, 0, NULL }
};
-/* A default for same. */
-#ifndef USER_LABEL_PREFIX
-#define USER_LABEL_PREFIX ""
-#endif
-
/* Table of language-independent -f options.
STRING is the option name. VARIABLE is the address of the variable.
ON_VALUE is the value to store in VARIABLE
@@ -977,6 +993,8 @@ static const lang_independent_options f_options[] =
N_("When possible do not generate stack frames") },
{"optimize-sibling-calls", &flag_optimize_sibling_calls, 1,
N_("Optimize sibling and tail recursive calls") },
+ {"tracer", &flag_tracer, 1,
+ N_("Perform superblock formation via tail duplication") },
{"cse-follow-jumps", &flag_cse_follow_jumps, 1,
N_("When running CSE, follow jumps to their targets") },
{"cse-skip-blocks", &flag_cse_skip_blocks, 1,
@@ -1033,14 +1051,20 @@ static const lang_independent_options f_options[] =
N_("Perform enhanced load motion during global subexpression elimination") },
{"gcse-sm", &flag_gcse_sm, 1,
N_("Perform store motion after global subexpression elimination") },
+ {"loop-optimize", &flag_loop_optimize, 1,
+ N_("Perform the loop optimizations") },
+ {"crossjumping", &flag_crossjumping, 1,
+ N_("Perform cross-jumping optimization") },
+ {"if-conversion", &flag_if_conversion, 1,
+ N_("Perform conversion of conditional jumps to branchless equivalents") },
+ {"if-conversion2", &flag_if_conversion2, 1,
+ N_("Perform conversion of conditional jumps to conditional execution") },
{"rerun-cse-after-loop", &flag_rerun_cse_after_loop, 1,
N_("Run CSE pass after loop optimizations") },
{"rerun-loop-opt", &flag_rerun_loop_opt, 1,
N_("Run the loop optimizer twice") },
{"delete-null-pointer-checks", &flag_delete_null_pointer_checks, 1,
N_("Delete useless null pointer checks") },
- {"pretend-float", &flag_pretend_float, 1,
- N_("Pretend that host and target use the same FP format") },
{"schedule-insns", &flag_schedule_insns, 1,
N_("Reschedule instructions before register allocation") },
{"schedule-insns2", &flag_schedule_insns_after_reload, 1,
@@ -1072,8 +1096,12 @@ static const lang_independent_options f_options[] =
N_("Create data files needed by gcov") },
{"branch-probabilities", &flag_branch_probabilities, 1,
N_("Use profiling information for branch probabilities") },
+ {"profile", &profile_flag, 1,
+ N_("Enable basic program profiling code") },
{"reorder-blocks", &flag_reorder_blocks, 1,
N_("Reorder basic blocks to improve code placement") },
+ {"reorder-functions", &flag_reorder_functions, 1,
+ N_("Reorder functions to improve code placement") },
{"rename-registers", &flag_rename_registers, 1,
N_("Do the register renaming optimization pass") },
{"cprop-registers", &flag_cprop_registers, 1,
@@ -1087,7 +1115,7 @@ static const lang_independent_options f_options[] =
{"data-sections", &flag_data_sections, 1,
N_("place data items into their own section") },
{"verbose-asm", &flag_verbose_asm, 1,
- N_("Add extra commentry to assembler output") },
+ N_("Add extra commentary to assembler output") },
{"gnu-linker", &flag_gnu_linker, 1,
N_("Output GNU ld formatted global initializers") },
{"regmove", &flag_regmove, 1,
@@ -1115,13 +1143,15 @@ static const lang_independent_options f_options[] =
{"align-functions", &align_functions, 0,
N_("Align the start of functions") },
{"merge-constants", &flag_merge_constants, 1,
- N_("Attempt to merge identical constants accross compilation units") },
+ N_("Attempt to merge identical constants across compilation units") },
{"merge-all-constants", &flag_merge_constants, 2,
N_("Attempt to merge identical constants and constant variables") },
{"dump-unnumbered", &flag_dump_unnumbered, 1,
N_("Suppress output of instruction numbers and line number notes in debugging dumps") },
{"instrument-functions", &flag_instrument_function_entry_exit, 1,
N_("Instrument function entry/exit with profiling calls") },
+ {"zero-initialized-in-bss", &flag_zero_initialized_in_bss, 1,
+ N_("Put zero initialized data in the bss section") },
{"ssa", &flag_ssa, 1,
N_("Enable SSA optimizations") },
{"ssa-ccp", &flag_ssa_ccp, 1,
@@ -1134,6 +1164,8 @@ static const lang_independent_options f_options[] =
N_("Process #ident directives") },
{ "peephole2", &flag_peephole2, 1,
N_("Enables an rtl peephole pass run before sched2") },
+ {"finite-math-only", &flag_finite_math_only, 1,
+ N_("Assume no NaNs or +-Infs are generated") },
{ "guess-branch-probability", &flag_guess_branch_prob, 1,
N_("Enables guessing of branch probabilities") },
{"math-errno", &flag_errno_math, 1,
@@ -1142,10 +1174,10 @@ static const lang_independent_options f_options[] =
N_("Floating-point operations can trap") },
{"unsafe-math-optimizations", &flag_unsafe_math_optimizations, 1,
N_("Allow math optimizations that may violate IEEE or ANSI standards") },
- {"bounded-pointers", &flag_bounded_pointers, 1,
- N_("Compile pointers as triples: value, base & end") },
+ {"signaling-nans", &flag_signaling_nans, 1,
+ N_("Disable optimizations observable by IEEE signaling NaNs") },
{"bounds-check", &flag_bounds_check, 1,
- N_("Generate code to check bounds before dereferencing pointers and arrays") },
+ N_("Generate code to check bounds before indexing arrays") },
{"single-precision-constant", &flag_single_precision_constant, 1,
N_("Convert floating point constant to single precision constant") },
{"time-report", &time_report, 1,
@@ -1154,6 +1186,8 @@ static const lang_independent_options f_options[] =
N_("Report on permanent memory allocation at end of run") },
{ "trapv", &flag_trapv, 1,
N_("Trap for signed overflow in addition / subtraction / multiplication") },
+ { "new-ra", &flag_new_regalloc, 1,
+ N_("Use graph coloring register allocation.") },
};
/* Table of language-specific options. */
@@ -1169,11 +1203,9 @@ documented_lang_options[] =
used here is to only describe those options which are not
enabled by default. */
- { "-ansi",
- N_("Compile just for ISO C89") },
- { "-fallow-single-precision",
- N_("Do not promote floats to double if using -traditional") },
- { "-std= ",
+ { "-ansi",
+ N_("Compile just for ISO C90") },
+ { "-std= ",
N_("Determine language standard") },
{ "-fsigned-bitfields", "" },
@@ -1181,104 +1213,103 @@ documented_lang_options[] =
N_("Make bit-fields by unsigned by default") },
{ "-fno-signed-bitfields", "" },
{ "-fno-unsigned-bitfields","" },
- { "-fsigned-char",
+ { "-fsigned-char",
N_("Make 'char' be signed by default") },
- { "-funsigned-char",
+ { "-funsigned-char",
N_("Make 'char' be unsigned by default") },
{ "-fno-signed-char", "" },
{ "-fno-unsigned-char", "" },
- { "-ftraditional", "" },
- { "-traditional",
- N_("Attempt to support traditional K&R style C") },
- { "-fnotraditional", "" },
- { "-fno-traditional", "" },
-
{ "-fasm", "" },
- { "-fno-asm",
+ { "-fno-asm",
N_("Do not recognize the 'asm' keyword") },
{ "-fbuiltin", "" },
- { "-fno-builtin",
+ { "-fno-builtin",
N_("Do not recognize any built in functions") },
- { "-fhosted",
+ { "-fhosted",
N_("Assume normal C execution environment") },
{ "-fno-hosted", "" },
{ "-ffreestanding",
N_("Assume that standard libraries & main might not exist") },
{ "-fno-freestanding", "" },
- { "-fcond-mismatch",
+ { "-fcond-mismatch",
N_("Allow different types as args of ? operator") },
{ "-fno-cond-mismatch", "" },
- { "-fdollars-in-identifiers",
+ { "-fdollars-in-identifiers",
N_("Allow the use of $ inside identifiers") },
{ "-fno-dollars-in-identifiers", "" },
{ "-fpreprocessed", "" },
{ "-fno-preprocessed", "" },
- { "-fshort-double",
+ { "-fshort-double",
N_("Use the same size for double as for float") },
{ "-fno-short-double", "" },
- { "-fshort-enums",
+ { "-fshort-enums",
N_("Use the smallest fitting integer to hold enums") },
{ "-fno-short-enums", "" },
- { "-fshort-wchar",
+ { "-fshort-wchar",
N_("Override the underlying type for wchar_t to `unsigned short'") },
{ "-fno-short-wchar", "" },
- { "-Wall",
+ { "-Wall",
N_("Enable most warning messages") },
{ "-Wbad-function-cast",
N_("Warn about casting functions to incompatible types") },
{ "-Wno-bad-function-cast", "" },
- { "-Wno-missing-noreturn", "" },
{ "-Wmissing-format-attribute",
N_("Warn about functions which might be candidates for format attributes") },
{ "-Wno-missing-format-attribute", "" },
- { "-Wcast-qual",
+ { "-Wcast-qual",
N_("Warn about casts which discard qualifiers") },
{ "-Wno-cast-qual", "" },
- { "-Wchar-subscripts",
+ { "-Wchar-subscripts",
N_("Warn about subscripts whose type is 'char'") },
{ "-Wno-char-subscripts", "" },
- { "-Wcomment",
+ { "-Wcomment",
N_("Warn if nested comments are detected") },
{ "-Wno-comment", "" },
- { "-Wcomments",
+ { "-Wcomments",
N_("Warn if nested comments are detected") },
{ "-Wno-comments", "" },
- { "-Wconversion",
+ { "-Wconversion",
N_("Warn about possibly confusing type conversions") },
{ "-Wno-conversion", "" },
- { "-Wformat",
+ { "-Wdiv-by-zero", "" },
+ { "-Wno-div-by-zero",
+ N_("Do not warn about compile-time integer division by zero") },
+ { "-Wfloat-equal",
+ N_("Warn about testing equality of floating point numbers") },
+ { "-Wno-float-equal", "" },
+ { "-Wformat",
N_("Warn about printf/scanf/strftime/strfmon format anomalies") },
{ "-Wno-format", "" },
- { "-Wformat-y2k", "" },
- { "-Wno-format-y2k",
- N_("Don't warn about strftime formats yielding 2 digit years") },
{ "-Wformat-extra-args", "" },
{ "-Wno-format-extra-args",
N_("Don't warn about too many arguments to format functions") },
- { "-Wformat-nonliteral",
+ { "-Wformat-nonliteral",
N_("Warn about non-string-literal format strings") },
{ "-Wno-format-nonliteral", "" },
{ "-Wformat-security",
N_("Warn about possible security problems with format functions") },
{ "-Wno-format-security", "" },
+ { "-Wformat-y2k", "" },
+ { "-Wno-format-y2k",
+ N_("Don't warn about strftime formats yielding 2 digit years") },
{ "-Wimplicit-function-declaration",
N_("Warn about implicit function declarations") },
{ "-Wno-implicit-function-declaration", "" },
{ "-Werror-implicit-function-declaration", "" },
- { "-Wimplicit-int",
+ { "-Wimplicit-int",
N_("Warn when a declaration does not specify a type") },
{ "-Wno-implicit-int", "" },
{ "-Wimplicit", "" },
{ "-Wno-implicit", "" },
- { "-Wimport",
+ { "-Wimport",
N_("Warn about the use of the #import directive") },
{ "-Wno-import", "" },
{ "-Wlong-long","" },
- { "-Wno-long-long",
+ { "-Wno-long-long",
N_("Do not warn about using 'long long' when -pedantic") },
- { "-Wmain",
+ { "-Wmain",
N_("Warn about suspicious declarations of main") },
{ "-Wno-main", "" },
{ "-Wmissing-braces",
@@ -1287,48 +1318,48 @@ documented_lang_options[] =
{ "-Wmissing-declarations",
N_("Warn about global funcs without previous declarations") },
{ "-Wno-missing-declarations", "" },
- { "-Wmissing-prototypes",
+ { "-Wmissing-prototypes",
N_("Warn about global funcs without prototypes") },
{ "-Wno-missing-prototypes", "" },
- { "-Wmultichar",
+ { "-Wmultichar",
N_("Warn about use of multicharacter literals") },
{ "-Wno-multichar", "" },
- { "-Wnested-externs",
+ { "-Wnested-externs",
N_("Warn about externs not at file scope level") },
{ "-Wno-nested-externs", "" },
- { "-Wparentheses",
+ { "-Wparentheses",
N_("Warn about possible missing parentheses") },
{ "-Wno-parentheses", "" },
- { "-Wsequence-point",
- N_("Warn about possible violations of sequence point rules") },
- { "-Wno-sequence-point", "" },
- { "-Wpointer-arith",
+ { "-Wpointer-arith",
N_("Warn about function pointer arithmetic") },
{ "-Wno-pointer-arith", "" },
{ "-Wredundant-decls",
N_("Warn about multiple declarations of the same object") },
{ "-Wno-redundant-decls", "" },
- { "-Wsign-compare",
+ { "-Wreturn-type",
+ N_("Warn whenever a function's return-type defaults to int") },
+ { "-Wno-return-type", "" },
+ { "-Wsequence-point",
+ N_("Warn about possible violations of sequence point rules") },
+ { "-Wno-sequence-point", "" },
+ { "-Wsign-compare",
N_("Warn about signed/unsigned comparisons") },
{ "-Wno-sign-compare", "" },
- { "-Wfloat-equal",
- N_("Warn about testing equality of floating point numbers") },
- { "-Wno-float-equal", "" },
- { "-Wunknown-pragmas",
- N_("Warn about unrecognized pragmas") },
- { "-Wno-unknown-pragmas", "" },
- { "-Wstrict-prototypes",
+ { "-Wstrict-prototypes",
N_("Warn about non-prototyped function decls") },
{ "-Wno-strict-prototypes", "" },
- { "-Wtraditional",
- N_("Warn about constructs whose meaning change in ISO C") },
+ { "-Wtraditional",
+ N_("Warn about constructs whose meanings change in ISO C") },
{ "-Wno-traditional", "" },
- { "-Wtrigraphs",
+ { "-Wtrigraphs",
N_("Warn when trigraphs are encountered") },
{ "-Wno-trigraphs", "" },
{ "-Wundef", "" },
{ "-Wno-undef", "" },
- { "-Wwrite-strings",
+ { "-Wunknown-pragmas",
+ N_("Warn about unrecognized pragmas") },
+ { "-Wno-unknown-pragmas", "" },
+ { "-Wwrite-strings",
N_("Mark strings as 'const char *'") },
{ "-Wno-write-strings", "" },
@@ -1350,7 +1381,7 @@ static const struct
const int value;
const char *const description;
}
-target_switches [] = TARGET_SWITCHES;
+target_switches[] = TARGET_SWITCHES;
/* This table is similar, but allows the switch to have a value. */
@@ -1361,7 +1392,7 @@ static const struct
const char **const variable;
const char *const description;
}
-target_options [] = TARGET_OPTIONS;
+target_options[] = TARGET_OPTIONS;
#endif
/* Options controlling warnings. */
@@ -1402,10 +1433,20 @@ int warn_uninitialized;
int warn_shadow;
-/* Warn if a switch on an enum fails to have a case for every enum value. */
+/* Warn if a switch on an enum, that does not have a default case,
+ fails to have a case for every enum value. */
int warn_switch;
+/* Warn if a switch does not have a default case. */
+
+int warn_switch_default;
+
+/* Warn if a switch on an enum fails to have a case for every enum
+ value (regardless of the presence or otherwise of a default case). */
+
+int warn_switch_enum;
+
/* Nonzero means warn about function definitions that default the return type
or that use a null return and have a return-type other than void. */
@@ -1449,11 +1490,16 @@ int warn_disabled_optimization;
int warn_missing_noreturn;
-/* Nonzero means warn about uses of __attribute__((deprecated))
+/* Nonzero means warn about uses of __attribute__((deprecated))
declarations. */
int warn_deprecated_decl = 1;
+/* Nonzero means warn about constructs which might not be
+ strict-aliasing safe. */
+
+int warn_strict_aliasing;
+
/* Likewise for -W. */
static const lang_independent_options W_options[] =
@@ -1475,7 +1521,11 @@ static const lang_independent_options W_options[] =
{"shadow", &warn_shadow, 1,
N_("Warn when one local variable shadows another") },
{"switch", &warn_switch, 1,
- N_("Warn about enumerated switches missing a specific case") },
+ N_("Warn about enumerated switches, with no default, missing a case") },
+ {"switch-default", &warn_switch_default, 1,
+ N_("Warn about enumerated switches missing a default case") },
+ {"switch-enum", &warn_switch_enum, 1,
+ N_("Warn about all enumerated switches missing a specific case") },
{"aggregate-return", &warn_aggregate_return, 1,
N_("Warn about returning structures, unions or arrays") },
{"cast-align", &warn_cast_align, 1,
@@ -1495,7 +1545,9 @@ static const lang_independent_options W_options[] =
{"deprecated-declarations", &warn_deprecated_decl, 1,
N_("Warn about uses of __attribute__((deprecated)) declarations") },
{"missing-noreturn", &warn_missing_noreturn, 1,
- N_("Warn about functions which might be candidates for attribute noreturn") }
+ N_("Warn about functions which might be candidates for attribute noreturn") },
+ {"strict-aliasing", &warn_strict_aliasing, 1,
+ N_ ("Warn about code which might break the strict aliasing rules") }
};
void
@@ -1519,19 +1571,25 @@ set_Wunused (setting)
-ffast-math and -fno-fast-math imply. */
void
-set_fast_math_flags ()
+set_fast_math_flags (set)
+ int set;
{
- flag_trapping_math = 0;
- flag_unsafe_math_optimizations = 1;
- flag_errno_math = 0;
+ flag_trapping_math = !set;
+ flag_unsafe_math_optimizations = set;
+ flag_finite_math_only = set;
+ flag_errno_math = !set;
+ if (set)
+ flag_signaling_nans = 0;
}
-void
-set_no_fast_math_flags ()
+/* Return true iff flags are set as if -ffast-math. */
+bool
+fast_math_flags_set_p ()
{
- flag_trapping_math = 1;
- flag_unsafe_math_optimizations = 0;
- flag_errno_math = 1;
+ return (!flag_trapping_math
+ && flag_unsafe_math_optimizations
+ && flag_finite_math_only
+ && !flag_errno_math);
}
@@ -1572,20 +1630,8 @@ read_integral_parameter (p, pname, defval)
return atoi (p);
}
-
-
-/* This is the default decl_printable_name function. */
-
-static const char *
-decl_name (decl, verbosity)
- tree decl;
- int verbosity ATTRIBUTE_UNUSED;
-{
- return IDENTIFIER_POINTER (DECL_NAME (decl));
-}
-
-/* This calls abort and is used to avoid problems when abort if a macro.
+/* This calls abort and is used to avoid problems when abort is a macro.
It is used when we need to pass the address of abort. */
void
@@ -1638,73 +1684,6 @@ floor_log2_wide (x)
return log;
}
-static int float_handler_set;
-int float_handled;
-jmp_buf float_handler;
-
-/* Signals actually come here. */
-
-static void
-float_signal (signo)
- /* If this is missing, some compilers complain. */
- int signo ATTRIBUTE_UNUSED;
-{
- if (float_handled == 0)
- crash_signal (signo);
- float_handled = 0;
-
- /* On System-V derived systems, we must reinstall the signal handler.
- This is harmless on BSD-derived systems. */
- signal (SIGFPE, float_signal);
- longjmp (float_handler, 1);
-}
-
-/* Specify where to longjmp to when a floating arithmetic error happens.
- If HANDLER is 0, it means don't handle the errors any more. */
-
-static void
-set_float_handler (handler)
- jmp_buf handler;
-{
- float_handled = (handler != 0);
- if (handler)
- memcpy (float_handler, handler, sizeof (float_handler));
-
- if (float_handled && ! float_handler_set)
- {
- signal (SIGFPE, float_signal);
- float_handler_set = 1;
- }
-}
-
-/* This is a wrapper function for code which might elicit an
- arithmetic exception. That code should be passed in as a function
- pointer FN, and one argument DATA. DATA is usually a struct which
- contains the real input and output for function FN. This function
- returns 0 (failure) if longjmp was called (i.e. an exception
- occurred.) It returns 1 (success) otherwise. */
-
-int
-do_float_handler (fn, data)
- void (*fn) PARAMS ((PTR));
- PTR data;
-{
- jmp_buf buf;
-
- if (setjmp (buf))
- {
- /* We got here via longjmp () caused by an exception in function
- fn (). */
- set_float_handler (NULL);
- return 0;
- }
-
- set_float_handler (buf);
- (*fn)(data);
- set_float_handler (NULL);
- return 1;
-}
-
/* Handler for fatal signals, such as SIGSEGV. These are transformed
into ICE messages, which is much more user friendly. */
@@ -1712,7 +1691,7 @@ static void
crash_signal (signo)
int signo;
{
- internal_error ("internal error: %s", strsignal (signo));
+ internal_error ("%s", strsignal (signo));
}
/* Strip off a legitimate source ending from the input string NAME of
@@ -1726,7 +1705,7 @@ strip_off_ending (name, len)
int len;
{
int i;
- for (i = 2; i < 6 && len > i; i++)
+ for (i = 2; i < 6 && len > i; i++)
{
if (name[len - i] == '.')
{
@@ -1758,12 +1737,30 @@ output_quoted_string (asm_file, string)
putc (c, asm_file);
}
else
- fprintf (asm_file, "\\%03o", c);
+ fprintf (asm_file, "\\%03o", (unsigned char) c);
}
putc ('\"', asm_file);
#endif
}
+/* Output NAME into FILE after having turned it into something
+ usable as an identifier in a target's assembly file. */
+void
+output_clean_symbol_name (file, name)
+ FILE *file;
+ const char *name;
+{
+ /* Make a copy of NAME. */
+ char *id = xstrdup (name);
+
+ /* Make it look like a valid identifier for an assembler. */
+ clean_symbol_name (id);
+
+ fputs (id, file);
+ free (id);
+}
+
+
/* Output a file name in the form wanted by System V. */
void
@@ -1778,7 +1775,7 @@ output_file_directive (asm_file, input_name)
while (na > input_name)
{
if (IS_DIR_SEPARATOR (na[-1]))
- break;
+ break;
na--;
}
@@ -1841,8 +1838,13 @@ open_dump_file (index, decl)
free (dump_name);
if (decl)
- fprintf (rtl_dump_file, "\n;; Function %s\n\n",
- decl_printable_name (decl, 2));
+ fprintf (rtl_dump_file, "\n;; Function %s%s\n\n",
+ (*lang_hooks.decl_printable_name) (decl, 2),
+ cfun->function_frequency == FUNCTION_FREQUENCY_HOT
+ ? " (hot)"
+ : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED
+ ? " (unlikely executed)"
+ : "");
timevar_pop (TV_DUMP);
return 1;
@@ -1886,7 +1888,7 @@ close_dump_file (index, func, insns)
/* Do any final processing required for the declarations in VEC, of
which there are LEN. We write out inline functions and variables
that have been deferred until this point, but which are required.
- Returns non-zero if anything was put out. */
+ Returns nonzero if anything was put out. */
int
wrapup_global_declarations (vec, len)
@@ -1902,12 +1904,13 @@ wrapup_global_declarations (vec, len)
{
decl = vec[i];
- /* We're not deferring this any longer. */
- DECL_DEFER_OUTPUT (decl) = 0;
+ /* We're not deferring this any longer. Assignment is
+ conditional to avoid needlessly dirtying PCH pages. */
+ if (DECL_DEFER_OUTPUT (decl) != 0)
+ DECL_DEFER_OUTPUT (decl) = 0;
- if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0
- && incomplete_decl_finalize_hook != 0)
- (*incomplete_decl_finalize_hook) (decl);
+ if (TREE_CODE (decl) == VAR_DECL && DECL_SIZE (decl) == 0)
+ (*lang_hooks.finish_incomplete_decl) (decl);
}
/* Now emit any global variables or functions that we have been
@@ -2034,27 +2037,33 @@ check_global_declarations (vec, len)
assemble_external (decl);
}
- /* Warn about static fns or vars defined but not used,
- but not about inline functions or static consts
- since defining those in header files is normal practice. */
- if (((warn_unused_function
- && TREE_CODE (decl) == FUNCTION_DECL && ! DECL_INLINE (decl))
+ /* Warn about static fns or vars defined but not used. */
+ if (((warn_unused_function && TREE_CODE (decl) == FUNCTION_DECL)
+ /* We don't warn about "static const" variables because the
+ "rcs_id" idiom uses that construction. */
|| (warn_unused_variable
&& TREE_CODE (decl) == VAR_DECL && ! TREE_READONLY (decl)))
&& ! DECL_IN_SYSTEM_HEADER (decl)
+ && ! TREE_USED (decl)
+ /* The TREE_USED bit for file-scope decls is kept in the identifier,
+ to handle multiple external decls in different scopes. */
+ && ! TREE_USED (DECL_NAME (decl))
&& ! DECL_EXTERNAL (decl)
&& ! TREE_PUBLIC (decl)
- && ! TREE_USED (decl)
- && (TREE_CODE (decl) == FUNCTION_DECL || ! DECL_REGISTER (decl))
- /* The TREE_USED bit for file-scope decls
- is kept in the identifier, to handle multiple
- external decls in different scopes. */
- && ! TREE_USED (DECL_NAME (decl)))
+ /* Global register variables must be declared to reserve them. */
+ && ! (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
+ /* Otherwise, ask the language. */
+ && (*lang_hooks.decls.warn_unused_global) (decl))
warning_with_decl (decl, "`%s' defined but not used");
- timevar_push (TV_SYMOUT);
- (*debug_hooks->global_decl) (decl);
- timevar_pop (TV_SYMOUT);
+ /* Avoid confusing the debug information machinery when there are
+ errors. */
+ if (errorcount == 0 && sorrycount == 0)
+ {
+ timevar_push (TV_SYMOUT);
+ (*debug_hooks->global_decl) (decl);
+ timevar_pop (TV_SYMOUT);
+ }
}
}
@@ -2078,7 +2087,6 @@ push_srcloc (file, line)
fs = (struct file_stack *) xmalloc (sizeof (struct file_stack));
fs->name = input_filename = file;
fs->line = lineno = line;
- fs->indent_level = 0;
fs->next = input_file_stack;
input_file_stack = fs;
input_file_stack_tick++;
@@ -2110,18 +2118,16 @@ pop_srcloc ()
static void
compile_file ()
{
- tree globals;
-
/* Initialize yet another pass. */
init_final (main_input_filename);
- init_branch_prob (dump_base_name);
+ init_branch_prob (aux_base_name);
timevar_push (TV_PARSE);
- /* Call the parser, which parses the entire file
- (calling rest_of_compilation for each function). */
- yyparse ();
+ /* Call the parser, which parses the entire file (calling
+ rest_of_compilation for each function). */
+ (*lang_hooks.parse_file) (set_yydebug);
/* In case there were missing block closers,
get us back to the global binding level. */
@@ -2129,31 +2135,12 @@ compile_file ()
/* Compilation is now finished except for writing
what's left of the symbol table output. */
-
timevar_pop (TV_PARSE);
if (flag_syntax_only)
return;
- globals = getdecls ();
-
- /* Really define vars that have had only a tentative definition.
- Really output inline functions that must actually be callable
- and have not been output so far. */
-
- {
- int len = list_length (globals);
- tree *vec = (tree *) xmalloc (sizeof (tree) * len);
- int i;
- tree decl;
-
- /* Process the decls in reverse order--earliest first.
- Put them into VEC from back to front, then take out from front. */
-
- for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
- vec[len - i - 1] = decl;
-
- wrapup_global_declarations (vec, len);
+ (*lang_hooks.decls.final_write_globals)();
/* This must occur after the loop to output deferred functions. Else
the profiler initializer would not be emitted if all the functions
@@ -2164,12 +2151,6 @@ compile_file ()
loop above. */
output_func_start_profiler ();
- check_global_declarations (vec, len);
-
- /* Clean up. */
- free (vec);
- }
-
/* Write out any pending weak symbol declarations. */
weak_finish ();
@@ -2189,7 +2170,7 @@ compile_file ()
dw2_output_indirect_constants ();
- end_final (dump_base_name);
+ end_final (aux_base_name);
if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
{
@@ -2261,7 +2242,7 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end)
{
alias = TREE_VALUE (TREE_VALUE (alias));
alias = get_identifier (TREE_STRING_POINTER (alias));
- assemble_alias (decl, alias);
+ assemble_alias (decl, alias);
}
}
@@ -2271,11 +2252,12 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end)
|| TREE_CODE (decl) == FUNCTION_DECL)
{
timevar_push (TV_VARCONST);
+
if (asmspec)
make_decl_rtl (decl, asmspec);
- /* Don't output anything
- when a tentative file-scope definition is seen.
- But at end of compilation, do output code for them. */
+
+ /* Don't output anything when a tentative file-scope definition
+ is seen. But at end of compilation, do output code for them. */
if (at_end || !DECL_DEFER_OUTPUT (decl))
assemble_variable (decl, top_level, at_end, 0);
if (decl == last_assemble_variable_decl)
@@ -2283,6 +2265,7 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end)
ASM_FINISH_DECLARE_OBJECT (asm_out_file, decl,
top_level, at_end);
}
+
timevar_pop (TV_VARCONST);
}
else if (DECL_REGISTER (decl) && asmspec != 0)
@@ -2318,6 +2301,17 @@ rest_of_decl_compilation (decl, asmspec, top_level, at_end)
timevar_pop (TV_SYMOUT);
}
#endif
+#ifdef DWARF2_DEBUGGING_INFO
+ else if ((write_symbols == DWARF2_DEBUG
+ || write_symbols == VMS_AND_DWARF2_DEBUG)
+ && top_level
+ && TREE_CODE (decl) == TYPE_DECL)
+ {
+ timevar_push (TV_SYMOUT);
+ dwarf2out_decl (decl);
+ timevar_pop (TV_SYMOUT);
+ }
+#endif
}
/* Called after finishing a record, union or enumeral type. */
@@ -2332,6 +2326,11 @@ rest_of_type_compilation (type, toplev)
int toplev ATTRIBUTE_UNUSED;
#endif
{
+ /* Avoid confusing the debug information machinery when there are
+ errors. */
+ if (errorcount != 0 || sorrycount != 0)
+ return;
+
timevar_push (TV_SYMOUT);
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
@@ -2350,7 +2349,7 @@ rest_of_type_compilation (type, toplev)
timevar_pop (TV_SYMOUT);
}
-/* This is called from finish_function (within yyparse)
+/* This is called from finish_function (within langhooks.parse_file)
after each top-level definition is parsed.
It is supposed to compile that function or variable
and output the assembler code for it.
@@ -2365,7 +2364,6 @@ rest_of_compilation (decl)
int failure = 0;
int rebuild_label_notes_after_reload;
int register_life_up_to_date;
- int cleanup_crossjump;
timevar_push (TV_REST_OF_COMPILATION);
@@ -2436,12 +2434,17 @@ rest_of_compilation (decl)
goto exit_rest_of_compilation;
}
}
- else
- /* ??? Note that this has the effect of making it look
- like "inline" was specified for a function if we choose
- to inline it. This isn't quite right, but it's
- probably not worth the trouble to fix. */
- inlinable = DECL_INLINE (decl) = 1;
+ else
+ {
+ /* ??? Note that we used to just make it look like if
+ the "inline" keyword was specified when we decide
+ to inline it (because of -finline-functions).
+ garloff at suse dot de, 2002-04-24: Add another flag to
+ actually record this piece of information. */
+ if (!DECL_INLINE (decl))
+ DID_INLINE_FUNC (decl) = 1;
+ inlinable = DECL_INLINE (decl) = 1;
+ }
}
insns = get_insns ();
@@ -2461,10 +2464,11 @@ rest_of_compilation (decl)
convert_from_eh_region_ranges ();
/* If function is inline, and we don't yet know whether to
- compile it by itself, defer decision till end of compilation.
- finish_compilation will call rest_of_compilation again
- for those functions that need to be output. Also defer those
- functions that we are supposed to defer. */
+ compile it by itself, defer decision till end of compilation.
+ wrapup_global_declarations will (indirectly) call
+ rest_of_compilation again for those functions that need to
+ be output. Also defer those functions that we are supposed
+ to defer. */
if (inlinable
|| (DECL_INLINE (decl)
@@ -2503,7 +2507,7 @@ rest_of_compilation (decl)
free_bb_for_insn ();
}
- current_function_nothrow = nothrow_function_p ();
+ set_nothrow_function_flags ();
if (current_function_nothrow)
/* Now we know that this can't throw; set the flag for the benefit
of other functions later in this translation unit. */
@@ -2558,7 +2562,7 @@ rest_of_compilation (decl)
distinguish between the return value of this function and the
return value of called functions. Also, we can remove all SETs
of subregs of hard registers; they are only here because of
- integrate. Also, we can now initialize pseudos intended to
+ integrate. Also, we can now initialize pseudos intended to
carry magic hard reg data throughout the function. */
rtx_equal_function_value_matters = 0;
purge_hard_subreg_sets (get_insns ());
@@ -2570,21 +2574,56 @@ rest_of_compilation (decl)
|| errorcount || sorrycount)
goto exit_rest_of_compilation;
+ timevar_push (TV_JUMP);
+ open_dump_file (DFI_sibling, decl);
+ insns = get_insns ();
+ rebuild_jump_labels (insns);
+ find_exception_handler_labels ();
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+
+ delete_unreachable_blocks ();
+
+ /* We have to issue these warnings now already, because CFG cleanups
+ further down may destroy the required information. */
+ check_function_return_warnings ();
+
+ /* Turn NOTE_INSN_PREDICTIONs into branch predictions. */
+ if (flag_guess_branch_prob)
+ {
+ timevar_push (TV_BRANCH_PROB);
+ note_prediction_to_br_prob ();
+ timevar_pop (TV_BRANCH_PROB);
+ }
+
/* We may have potential sibling or tail recursion sites. Select one
(of possibly multiple) methods of performing the call. */
if (flag_optimize_sibling_calls)
{
- timevar_push (TV_JUMP);
- open_dump_file (DFI_sibling, decl);
-
+ rtx insn;
optimize_sibling_and_tail_recursive_calls ();
- close_dump_file (DFI_sibling, print_rtl, get_insns ());
- timevar_pop (TV_JUMP);
+ /* Recompute the CFG as sibling optimization clobbers it randomly. */
+ free_bb_for_insn ();
+ find_exception_handler_labels ();
+ rebuild_jump_labels (insns);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+
+ /* There is pass ordering problem - we must lower NOTE_INSN_PREDICTION
+ notes before simplifying cfg and we must do lowering after sibcall
+ that unhides parts of RTL chain and cleans up the CFG.
+
+ Until sibcall is replaced by tree-level optimizer, lets just
+ sweep away the NOTE_INSN_PREDICTION notes that leaked out. */
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_PREDICTION)
+ delete_insn (insn);
}
+ close_dump_file (DFI_sibling, print_rtl, get_insns ());
+ timevar_pop (TV_JUMP);
+ scope_to_insns_initialize ();
/* Complete generation of exception handling code. */
- find_exception_handler_labels ();
if (doing_eh (0))
{
timevar_push (TV_JUMP);
@@ -2615,7 +2654,10 @@ rest_of_compilation (decl)
unshare_all_rtl (current_function_decl, insns);
#ifdef SETJMP_VIA_SAVE_AREA
- /* This must be performed before virtual register instantiation. */
+ /* This must be performed before virtual register instantiation.
+ Please be aware the everything in the compiler that can look
+ at the RTL up to this point must understand that REG_SAVE_AREA
+ is just like a use of the REG contained inside. */
if (current_function_calls_alloca)
optimize_save_area_alloca (insns);
#endif
@@ -2632,24 +2674,33 @@ rest_of_compilation (decl)
timevar_push (TV_JUMP);
/* Turn NOTE_INSN_EXPECTED_VALUE into REG_BR_PROB. Do this
before jump optimization switches branch directions. */
- expected_value_to_br_prob ();
+ if (flag_guess_branch_prob)
+ expected_value_to_br_prob ();
reg_scan (insns, max_reg_num (), 0);
rebuild_jump_labels (insns);
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP);
+ delete_trivially_dead_insns (insns, max_reg_num ());
+ if (rtl_dump_file)
+ dump_flow_info (rtl_dump_file);
+ cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP
+ | (flag_thread_jumps ? CLEANUP_THREADING : 0));
/* CFG is no longer maintained up-to-date. */
- free_bb_for_insn ();
- copy_loop_headers (insns);
+ if (optimize)
+ {
+ free_bb_for_insn ();
+ copy_loop_headers (insns);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ }
purge_line_number_notes (insns);
timevar_pop (TV_JUMP);
+ close_dump_file (DFI_jump, print_rtl, insns);
/* Now is when we stop if -fsyntax-only and -Wreturn-type. */
if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl))
{
- close_dump_file (DFI_jump, print_rtl, insns);
goto exit_rest_of_compilation;
}
@@ -2663,7 +2714,6 @@ rest_of_compilation (decl)
timevar_push (TV_TO_SSA);
open_dump_file (DFI_ssa, decl);
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
convert_to_ssa ();
@@ -2699,7 +2749,7 @@ rest_of_compilation (decl)
open_dump_file (DFI_ssa_dce, decl);
insns = get_insns ();
- ssa_eliminate_dead_code();
+ ssa_eliminate_dead_code ();
close_dump_file (DFI_ssa_dce, print_rtl_with_bb, insns);
timevar_pop (TV_SSA_DCE);
@@ -2718,31 +2768,23 @@ rest_of_compilation (decl)
timevar_pop (TV_FROM_SSA);
ggc_collect ();
- /* CFG is no longer maintained up-to-date. */
- free_bb_for_insn ();
}
timevar_push (TV_JUMP);
+ if (optimize)
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
- if (optimize > 0)
+ /* Try to identify useless null pointer tests and delete them. */
+ if (flag_delete_null_pointer_checks)
{
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP
- | (flag_thread_jumps ? CLEANUP_THREADING : 0));
+ open_dump_file (DFI_null, decl);
+ if (rtl_dump_file)
+ dump_flow_info (rtl_dump_file);
- /* ??? Run if-conversion before delete_null_pointer_checks,
- since the later does not preserve the CFG. This should
- be changed -- no since converting if's that are going to
- be deleted. */
- timevar_push (TV_IFCVT);
- if_convert (0);
- timevar_pop (TV_IFCVT);
+ if (delete_null_pointer_checks (insns))
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
- /* CFG is no longer maintained up-to-date. */
- free_bb_for_insn ();
- /* Try to identify useless null pointer tests and delete them. */
- if (flag_delete_null_pointer_checks)
- delete_null_pointer_checks (insns);
+ close_dump_file (DFI_null, print_rtl_with_bb, insns);
}
/* Jump optimization, and the removal of NULL pointer checks, may
@@ -2753,7 +2795,7 @@ rest_of_compilation (decl)
renumber_insns (rtl_dump_file);
timevar_pop (TV_JUMP);
- close_dump_file (DFI_jump, print_rtl, insns);
+ close_dump_file (DFI_jump, print_rtl_with_bb, insns);
ggc_collect ();
@@ -2765,44 +2807,32 @@ rest_of_compilation (decl)
if (optimize > 0)
{
open_dump_file (DFI_cse, decl);
+ if (rtl_dump_file)
+ dump_flow_info (rtl_dump_file);
timevar_push (TV_CSE);
reg_scan (insns, max_reg_num (), 1);
tem = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
+ if (tem)
+ rebuild_jump_labels (insns);
+ purge_all_dead_edges (0);
+
+ delete_trivially_dead_insns (insns, max_reg_num ());
/* If we are not running more CSE passes, then we are no longer
expecting CSE to be run. But always rerun it in a cheap mode. */
cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse;
if (tem || optimize > 1)
- {
- timevar_push (TV_JUMP);
- rebuild_jump_labels (insns);
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
- timevar_pop (TV_JUMP);
- /* CFG is no longer maintained up-to-date. */
- free_bb_for_insn ();
- }
-
- /* Run this after jump optmizations remove all the unreachable code
- so that unreachable code will not keep values live. */
- delete_trivially_dead_insns (insns, max_reg_num (), 0);
-
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
/* Try to identify useless null pointer tests and delete them. */
- if (flag_delete_null_pointer_checks || flag_thread_jumps)
+ if (flag_delete_null_pointer_checks)
{
timevar_push (TV_JUMP);
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP
- | (flag_thread_jumps ? CLEANUP_THREADING : 0));
-
- if (flag_delete_null_pointer_checks)
- delete_null_pointer_checks (insns);
- /* CFG is no longer maintained up-to-date. */
- free_bb_for_insn ();
+ if (delete_null_pointer_checks (insns))
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
timevar_pop (TV_JUMP);
}
@@ -2811,12 +2841,14 @@ rest_of_compilation (decl)
renumber_insns (rtl_dump_file);
timevar_pop (TV_CSE);
- close_dump_file (DFI_cse, print_rtl, insns);
+ close_dump_file (DFI_cse, print_rtl_with_bb, insns);
}
open_dump_file (DFI_addressof, decl);
purge_addressof (insns);
+ if (optimize)
+ purge_all_dead_edges (0);
reg_scan (insns, max_reg_num (), 1);
close_dump_file (DFI_addressof, print_rtl, insns);
@@ -2833,17 +2865,14 @@ rest_of_compilation (decl)
timevar_push (TV_GCSE);
open_dump_file (DFI_gcse, decl);
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
tem = gcse_main (insns, rtl_dump_file);
rebuild_jump_labels (insns);
+ delete_trivially_dead_insns (insns, max_reg_num ());
save_csb = flag_cse_skip_blocks;
save_cfj = flag_cse_follow_jumps;
flag_cse_skip_blocks = flag_cse_follow_jumps = 0;
- /* CFG is no longer maintained up-to-date. */
- free_bb_for_insn ();
/* If -fexpensive-optimizations, re-run CSE to clean up things done
by gcse. */
if (flag_expensive_optimizations)
@@ -2851,6 +2880,8 @@ rest_of_compilation (decl)
timevar_push (TV_CSE);
reg_scan (insns, max_reg_num (), 1);
tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
+ purge_all_dead_edges (0);
+ delete_trivially_dead_insns (insns, max_reg_num ());
timevar_pop (TV_CSE);
cse_not_expected = !flag_rerun_cse_after_loop;
}
@@ -2862,11 +2893,7 @@ rest_of_compilation (decl)
tem = tem2 = 0;
timevar_push (TV_JUMP);
rebuild_jump_labels (insns);
- delete_trivially_dead_insns (insns, max_reg_num (), 0);
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
- /* CFG is no longer maintained up-to-date. */
- free_bb_for_insn ();
timevar_pop (TV_JUMP);
if (flag_expensive_optimizations)
@@ -2874,123 +2901,78 @@ rest_of_compilation (decl)
timevar_push (TV_CSE);
reg_scan (insns, max_reg_num (), 1);
tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
+ purge_all_dead_edges (0);
+ delete_trivially_dead_insns (insns, max_reg_num ());
timevar_pop (TV_CSE);
}
}
- close_dump_file (DFI_gcse, print_rtl, insns);
+ close_dump_file (DFI_gcse, print_rtl_with_bb, insns);
timevar_pop (TV_GCSE);
ggc_collect ();
flag_cse_skip_blocks = save_csb;
flag_cse_follow_jumps = save_cfj;
+#ifdef ENABLE_CHECKING
+ verify_flow_info ();
+#endif
}
/* Move constant computations out of loops. */
- if (optimize > 0)
+ if (optimize > 0 && flag_loop_optimize)
{
+ int do_unroll, do_prefetch;
+
timevar_push (TV_LOOP);
+ delete_dead_jumptables ();
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
open_dump_file (DFI_loop, decl);
+ /* CFG is no longer maintained up-to-date. */
free_bb_for_insn ();
+ do_unroll = flag_unroll_loops ? LOOP_UNROLL : LOOP_AUTO_UNROLL;
+ do_prefetch = flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0;
if (flag_rerun_loop_opt)
{
cleanup_barriers ();
/* We only want to perform unrolling once. */
- loop_optimize (insns, rtl_dump_file, LOOP_FIRST_PASS);
+ loop_optimize (insns, rtl_dump_file, do_unroll);
+ do_unroll = 0;
/* The first call to loop_optimize makes some instructions
trivially dead. We delete those instructions now in the
hope that doing so will make the heuristics in loop work
better and possibly speed up compilation. */
- delete_trivially_dead_insns (insns, max_reg_num (), 0);
+ delete_trivially_dead_insns (insns, max_reg_num ());
/* The regscan pass is currently necessary as the alias
analysis code depends on this information. */
reg_scan (insns, max_reg_num (), 1);
}
cleanup_barriers ();
- loop_optimize (insns, rtl_dump_file,
- (flag_unroll_loops ? LOOP_UNROLL : 0) | LOOP_BCT
- | (flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0));
+ loop_optimize (insns, rtl_dump_file, do_unroll | LOOP_BCT | do_prefetch);
+ /* Loop can create trivially dead instructions. */
+ delete_trivially_dead_insns (insns, max_reg_num ());
close_dump_file (DFI_loop, print_rtl, insns);
timevar_pop (TV_LOOP);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
ggc_collect ();
}
- if (optimize > 0)
- {
- timevar_push (TV_CSE2);
- open_dump_file (DFI_cse2, decl);
-
- if (flag_rerun_cse_after_loop)
- {
- /* Running another jump optimization pass before the second
- cse pass sometimes simplifies the RTL enough to allow
- the second CSE pass to do a better job. Jump_optimize can change
- max_reg_num so we must rerun reg_scan afterwards.
- ??? Rework to not call reg_scan so often. */
- timevar_push (TV_JUMP);
-
- /* The previous call to loop_optimize makes some instructions
- trivially dead. We delete those instructions now in the
- hope that doing so will make the heuristics in jump work
- better and possibly speed up compilation. */
- delete_trivially_dead_insns (insns, max_reg_num (), 0);
-
- reg_scan (insns, max_reg_num (), 0);
-
- timevar_push (TV_IFCVT);
-
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (CLEANUP_EXPENSIVE);
- if_convert (0);
-
- timevar_pop(TV_IFCVT);
-
- timevar_pop (TV_JUMP);
-
- /* CFG is no longer maintained up-to-date. */
- free_bb_for_insn ();
- reg_scan (insns, max_reg_num (), 0);
- tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file);
-
- if (tem)
- {
- timevar_push (TV_JUMP);
- rebuild_jump_labels (insns);
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg (CLEANUP_EXPENSIVE);
- /* CFG is no longer maintained up-to-date. */
- free_bb_for_insn ();
- timevar_pop (TV_JUMP);
- }
- }
-
- close_dump_file (DFI_cse2, print_rtl, insns);
- timevar_pop (TV_CSE2);
-
- ggc_collect ();
- }
-
- cse_not_expected = 1;
-
- regclass_init ();
-
/* Do control and data flow analysis; wrote some of the results to
the dump file. */
timevar_push (TV_FLOW);
open_dump_file (DFI_cfg, decl);
-
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
- cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0)
- | (flag_thread_jumps ? CLEANUP_THREADING : 0));
- check_function_return_warnings ();
+ if (rtl_dump_file)
+ dump_flow_info (rtl_dump_file);
+ if (optimize)
+ cleanup_cfg (CLEANUP_EXPENSIVE
+ | (flag_thread_jumps ? CLEANUP_THREADING : 0));
/* It may make more sense to mark constant functions after dead code is
eliminated by life_analyzis, but we need to do it early, as -fprofile-arcs
@@ -2999,25 +2981,20 @@ rest_of_compilation (decl)
life_analyzis rarely eliminates modification of external memory.
*/
- mark_constant_function ();
+ if (optimize)
+ mark_constant_function ();
close_dump_file (DFI_cfg, print_rtl_with_bb, insns);
- if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
+ /* Do branch profiling and static profile estimation passes. */
+ if (optimize > 0 || cfun->arc_profile || flag_branch_probabilities)
{
+ struct loops loops;
+
timevar_push (TV_BRANCH_PROB);
open_dump_file (DFI_bp, decl);
-
- branch_prob ();
-
- close_dump_file (DFI_bp, print_rtl_with_bb, insns);
- timevar_pop (TV_BRANCH_PROB);
- }
-
- open_dump_file (DFI_life, decl);
- if (optimize)
- {
- struct loops loops;
+ if (cfun->arc_profile || flag_branch_probabilities)
+ branch_prob ();
/* Discover and record the loop depth at the head of each basic
block. The loop infrastructure does the real job for us. */
@@ -3031,12 +3008,79 @@ rest_of_compilation (decl)
estimate_probability (&loops);
flow_loops_free (&loops);
+ close_dump_file (DFI_bp, print_rtl_with_bb, insns);
+ timevar_pop (TV_BRANCH_PROB);
}
+ if (optimize > 0)
+ {
+ open_dump_file (DFI_ce1, decl);
+ if (flag_if_conversion)
+ {
+ timevar_push (TV_IFCVT);
+ if (rtl_dump_file)
+ dump_flow_info (rtl_dump_file);
+ cleanup_cfg (CLEANUP_EXPENSIVE);
+ reg_scan (insns, max_reg_num (), 0);
+ if_convert (0);
+ timevar_pop (TV_IFCVT);
+ }
+ timevar_push (TV_JUMP);
+ cleanup_cfg (CLEANUP_EXPENSIVE);
+ reg_scan (insns, max_reg_num (), 0);
+ timevar_pop (TV_JUMP);
+ close_dump_file (DFI_ce1, print_rtl_with_bb, get_insns ());
+ }
+ if (flag_tracer)
+ {
+ timevar_push (TV_TRACER);
+ open_dump_file (DFI_tracer, decl);
+ if (rtl_dump_file)
+ dump_flow_info (rtl_dump_file);
+ tracer ();
+ cleanup_cfg (CLEANUP_EXPENSIVE);
+ reg_scan (insns, max_reg_num (), 0);
+ close_dump_file (DFI_tracer, print_rtl_with_bb, get_insns ());
+ timevar_pop (TV_TRACER);
+ }
+
+ if (flag_rerun_cse_after_loop)
+ {
+ timevar_push (TV_CSE2);
+ open_dump_file (DFI_cse2, decl);
+ if (rtl_dump_file)
+ dump_flow_info (rtl_dump_file);
+ /* CFG is no longer maintained up-to-date. */
+ tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file);
+ purge_all_dead_edges (0);
+ delete_trivially_dead_insns (insns, max_reg_num ());
+
+ if (tem)
+ {
+ timevar_push (TV_JUMP);
+ rebuild_jump_labels (insns);
+ cleanup_cfg (CLEANUP_EXPENSIVE);
+ timevar_pop (TV_JUMP);
+ }
+ reg_scan (insns, max_reg_num (), 0);
+ close_dump_file (DFI_cse2, print_rtl_with_bb, insns);
+ ggc_collect ();
+ timevar_pop (TV_CSE2);
+ }
+
+ cse_not_expected = 1;
+
+ open_dump_file (DFI_life, decl);
+ regclass_init ();
+
+#ifdef ENABLE_CHECKING
+ verify_flow_info ();
+#endif
life_analysis (insns, rtl_dump_file, PROP_FINAL);
+ if (optimize)
+ cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_UPDATE_LIFE
+ | (flag_thread_jumps ? CLEANUP_THREADING : 0));
timevar_pop (TV_FLOW);
- no_new_pseudos = 1;
-
if (warn_uninitialized || extra_warnings)
{
uninitialized_vars_warning (DECL_INITIAL (decl));
@@ -3046,15 +3090,19 @@ rest_of_compilation (decl)
if (optimize)
{
- if (initialize_uninitialized_subregs ())
+ if (!flag_new_regalloc && initialize_uninitialized_subregs ())
{
- /* Insns were inserted, so things might look a bit different. */
+ /* Insns were inserted, and possibly pseudos created, so
+ things might look a bit different. */
insns = get_insns ();
- life_analysis (insns, rtl_dump_file,
- (PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES));
+ allocate_reg_life_data ();
+ update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
+ PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES);
}
}
+ no_new_pseudos = 1;
+
close_dump_file (DFI_life, print_rtl_with_bb, insns);
ggc_collect ();
@@ -3071,10 +3119,6 @@ rest_of_compilation (decl)
rebuild_jump_labels_after_combine
= combine_instructions (insns, max_reg_num ());
- /* Always purge dead edges, as we may eliminate an insn throwing
- exception. */
- rebuild_jump_labels_after_combine |= purge_all_dead_edges (true);
-
/* Combining insns may have turned an indirect jump into a
direct jump. Rebuid the JUMP_LABEL fields of jumping
instructions. */
@@ -3095,16 +3139,16 @@ rest_of_compilation (decl)
/* Rerun if-conversion, as combine may have simplified things enough to
now meet sequence length restrictions. */
- if (optimize > 0)
+ if (flag_if_conversion)
{
timevar_push (TV_IFCVT);
- open_dump_file (DFI_ce, decl);
+ open_dump_file (DFI_ce2, decl);
no_new_pseudos = 0;
if_convert (1);
no_new_pseudos = 1;
- close_dump_file (DFI_ce, print_rtl_with_bb, insns);
+ close_dump_file (DFI_ce2, print_rtl_with_bb, insns);
timevar_pop (TV_IFCVT);
}
@@ -3117,6 +3161,7 @@ rest_of_compilation (decl)
regmove_optimize (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE);
close_dump_file (DFI_regmove, print_rtl_with_bb, insns);
timevar_pop (TV_REGMOVE);
@@ -3135,13 +3180,7 @@ rest_of_compilation (decl)
timevar_push (TV_MODE_SWITCH);
no_new_pseudos = 0;
- if (optimize_mode_switching (NULL))
- {
- /* We did work, and so had to regenerate global life information.
- Take advantage of this and don't re-recompute register life
- information below. */
- register_life_up_to_date = 1;
- }
+ optimize_mode_switching (NULL);
no_new_pseudos = 1;
timevar_pop (TV_MODE_SWITCH);
@@ -3189,60 +3228,101 @@ rest_of_compilation (decl)
if (! register_life_up_to_date)
recompute_reg_usage (insns, ! optimize_size);
- /* Allocate the reg_renumber array. */
- allocate_reg_info (max_regno, FALSE, TRUE);
+ if (flag_new_regalloc)
+ {
+ delete_trivially_dead_insns (insns, max_reg_num ());
+ reg_alloc ();
+
+ timevar_pop (TV_LOCAL_ALLOC);
+ if (dump_file[DFI_lreg].enabled)
+ {
+ timevar_push (TV_DUMP);
- /* And the reg_equiv_memory_loc array. */
- reg_equiv_memory_loc = (rtx *) xcalloc (max_regno, sizeof (rtx));
+ close_dump_file (DFI_lreg, NULL, NULL);
+ timevar_pop (TV_DUMP);
+ }
- allocate_initial_values (reg_equiv_memory_loc);
+ /* XXX clean up the whole mess to bring live info in shape again. */
+ timevar_push (TV_GLOBAL_ALLOC);
+ open_dump_file (DFI_greg, decl);
- regclass (insns, max_reg_num (), rtl_dump_file);
- rebuild_label_notes_after_reload = local_alloc ();
+ build_insn_chain (insns);
+ failure = reload (insns, 0);
- timevar_pop (TV_LOCAL_ALLOC);
+ timevar_pop (TV_GLOBAL_ALLOC);
- if (dump_file[DFI_lreg].enabled)
- {
- timevar_push (TV_DUMP);
+ if (dump_file[DFI_greg].enabled)
+ {
+ timevar_push (TV_DUMP);
- dump_flow_info (rtl_dump_file);
- dump_local_alloc (rtl_dump_file);
+ dump_global_regs (rtl_dump_file);
- close_dump_file (DFI_lreg, print_rtl_with_bb, insns);
- timevar_pop (TV_DUMP);
+ close_dump_file (DFI_greg, print_rtl_with_bb, insns);
+ timevar_pop (TV_DUMP);
+ }
+
+ if (failure)
+ goto exit_rest_of_compilation;
+ reload_completed = 1;
+ rebuild_label_notes_after_reload = 0;
}
+ else
+ {
+ /* Allocate the reg_renumber array. */
+ allocate_reg_info (max_regno, FALSE, TRUE);
- ggc_collect ();
+ /* And the reg_equiv_memory_loc array. */
+ reg_equiv_memory_loc = (rtx *) xcalloc (max_regno, sizeof (rtx));
- timevar_push (TV_GLOBAL_ALLOC);
- open_dump_file (DFI_greg, decl);
+ allocate_initial_values (reg_equiv_memory_loc);
- /* If optimizing, allocate remaining pseudo-regs. Do the reload
- pass fixing up any insns that are invalid. */
+ regclass (insns, max_reg_num (), rtl_dump_file);
+ rebuild_label_notes_after_reload = local_alloc ();
- if (optimize)
- failure = global_alloc (rtl_dump_file);
- else
- {
- build_insn_chain (insns);
- failure = reload (insns, 0);
- }
+ timevar_pop (TV_LOCAL_ALLOC);
- timevar_pop (TV_GLOBAL_ALLOC);
+ if (dump_file[DFI_lreg].enabled)
+ {
+ timevar_push (TV_DUMP);
- if (dump_file[DFI_greg].enabled)
- {
- timevar_push (TV_DUMP);
+ dump_flow_info (rtl_dump_file);
+ dump_local_alloc (rtl_dump_file);
- dump_global_regs (rtl_dump_file);
+ close_dump_file (DFI_lreg, print_rtl_with_bb, insns);
+ timevar_pop (TV_DUMP);
+ }
- close_dump_file (DFI_greg, print_rtl_with_bb, insns);
- timevar_pop (TV_DUMP);
- }
+ ggc_collect ();
- if (failure)
- goto exit_rest_of_compilation;
+ timevar_push (TV_GLOBAL_ALLOC);
+ open_dump_file (DFI_greg, decl);
+
+ /* If optimizing, allocate remaining pseudo-regs. Do the reload
+ pass fixing up any insns that are invalid. */
+
+ if (optimize)
+ failure = global_alloc (rtl_dump_file);
+ else
+ {
+ build_insn_chain (insns);
+ failure = reload (insns, 0);
+ }
+
+ timevar_pop (TV_GLOBAL_ALLOC);
+
+ if (dump_file[DFI_greg].enabled)
+ {
+ timevar_push (TV_DUMP);
+
+ dump_global_regs (rtl_dump_file);
+
+ close_dump_file (DFI_greg, print_rtl_with_bb, insns);
+ timevar_pop (TV_DUMP);
+ }
+
+ if (failure)
+ goto exit_rest_of_compilation;
+ }
ggc_collect ();
@@ -3264,6 +3344,7 @@ rest_of_compilation (decl)
timevar_push (TV_JUMP);
rebuild_jump_labels (insns);
+ purge_all_dead_edges (0);
timevar_pop (TV_JUMP);
}
@@ -3279,10 +3360,13 @@ rest_of_compilation (decl)
#endif
/* If optimizing, then go ahead and split insns now. */
+#ifndef STACK_REGS
if (optimize > 0)
+#endif
split_all_insns (0);
- cleanup_cfg (optimize ? CLEANUP_EXPENSIVE : 0);
+ if (optimize)
+ cleanup_cfg (CLEANUP_EXPENSIVE);
/* On some machines, the prologue and epilogue code, or parts thereof,
can be represented as RTL. Doing so lets us schedule insns between
@@ -3290,22 +3374,11 @@ rest_of_compilation (decl)
scheduling to operate in the epilogue. */
thread_prologue_and_epilogue_insns (insns);
- /* Cross-jumping is O(N^3) on the number of edges, thus trying to
- perform cross-jumping on flow graphs which have a high connectivity
- will take a long time. This is similar to the test to disable GCSE. */
- cleanup_crossjump = CLEANUP_CROSSJUMP;
- if (n_basic_blocks > 1000 && n_edges / n_basic_blocks >= 20)
- {
- if (optimize && warn_disabled_optimization)
- warning ("crossjump disabled: %d > 1000 basic blocks and %d >= 20 edges/basic block",
- n_basic_blocks, n_edges / n_basic_blocks);
- cleanup_crossjump = 0;
- }
-
if (optimize)
{
- cleanup_cfg (CLEANUP_EXPENSIVE | cleanup_crossjump);
life_analysis (insns, rtl_dump_file, PROP_FINAL);
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE
+ | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0));
/* This is kind of a heuristic. We need to run combine_stack_adjustments
even for machines with possibly nonzero RETURN_POPS_ARGS
@@ -3343,28 +3416,24 @@ rest_of_compilation (decl)
open_dump_file (DFI_rnreg, decl);
if (flag_rename_registers)
- regrename_optimize ();
+ regrename_optimize ();
if (flag_cprop_registers)
- copyprop_hardreg_forward ();
+ copyprop_hardreg_forward ();
close_dump_file (DFI_rnreg, print_rtl_with_bb, insns);
timevar_pop (TV_RENAME_REGISTERS);
}
- if (optimize > 0)
+ if (flag_if_conversion2)
{
timevar_push (TV_IFCVT2);
- open_dump_file (DFI_ce2, decl);
+ open_dump_file (DFI_ce3, decl);
if_convert (1);
- close_dump_file (DFI_ce2, print_rtl_with_bb, insns);
+ close_dump_file (DFI_ce3, print_rtl_with_bb, insns);
timevar_pop (TV_IFCVT2);
}
-#ifdef STACK_REGS
- if (optimize)
- split_all_insns (1);
-#endif
#ifdef INSN_SCHEDULING
if (optimize > 0 && flag_schedule_insns_after_reload)
@@ -3407,12 +3476,12 @@ rest_of_compilation (decl)
timevar_push (TV_REORDER_BLOCKS);
open_dump_file (DFI_bbro, decl);
- /* Last attempt to optimize CFG, as life analysis possibly removed
- some instructions. Note that we can't rerun crossjump at this
- point, because it can turn a switch into a direct branch, which
- can leave the tablejump address calculation in the code, which
- can lead to referencing an undefined label. */
- cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
+ /* Last attempt to optimize CFG, as scheduling, peepholing and insn
+ splitting possibly introduced more crossjumping oppurtuntities.
+ Except that we can't actually run crossjumping without running
+ another DCE pass, which we can't do after reg-stack. */
+ cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK
+ | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0));
if (flag_reorder_blocks)
{
reorder_basic_blocks ();
@@ -3474,7 +3543,7 @@ rest_of_compilation (decl)
shorten_branches (get_insns ());
timevar_pop (TV_SHORTEN_BRANCH);
- current_function_nothrow = nothrow_function_p ();
+ set_nothrow_function_flags ();
if (current_function_nothrow)
/* Now we know that this can't throw; set the flag for the benefit
of other functions later in this translation unit. */
@@ -3535,9 +3604,10 @@ rest_of_compilation (decl)
know for certain that we will be generating an out-of-line copy,
the first invocation of this routine (rest_of_compilation) will
skip over this code by doing a `goto exit_rest_of_compilation;'.
- Later on, finish_compilation will call rest_of_compilation again
- for those inline functions that need to have out-of-line copies
- generated. During that call, we *will* be routed past here. */
+ Later on, wrapup_global_declarations will (indirectly) call
+ rest_of_compilation again for those inline functions that need
+ to have out-of-line copies generated. During that call, we
+ *will* be routed past here. */
timevar_push (TV_SYMOUT);
(*debug_hooks->function_decl) (decl);
@@ -3563,10 +3633,6 @@ rest_of_compilation (decl)
longer valid. */
init_insn_lengths ();
- /* Clear out the real_constant_chain before some of the rtx's
- it runs through become garbage. */
- clear_const_double_mem ();
-
/* Show no temporary slots allocated. */
init_temp_slots ();
@@ -3616,12 +3682,17 @@ display_help ()
printf (_(" -finline-limit=<number> Limits the size of inlined functions to <number>\n"));
printf (_(" -fmessage-length=<number> Limits diagnostics messages lengths to <number> characters per line. 0 suppresses line-wrapping\n"));
printf (_(" -fdiagnostics-show-location=[once | every-line] Indicates how often source location information should be emitted, as prefix, at the beginning of diagnostics when line-wrapping\n"));
+ printf (_(" -ftls-model=[global-dynamic | local-dynamic | initial-exec | local-exec] Indicates the default thread-local storage code generation model\n"));
+ printf (_(" -fstack-limit-register=<register> Trap if the stack goes past <register>\n"));
+ printf (_(" -fstack-limit-symbol=<name> Trap if the stack goes past symbol <name>\n"));
+ printf (_(" -frandom-seed=<string> Make compile reproducible using <string>\n"));
+
for (i = ARRAY_SIZE (f_options); i--;)
{
const char *description = f_options[i].description;
- if (description != NULL && * description != 0)
+ if (description != NULL && *description != 0)
printf (" -f%-21s %s\n",
f_options[i].string, _(description));
}
@@ -3631,9 +3702,9 @@ display_help ()
for (i = LAST_PARAM; i--;)
{
const char *description = compiler_params[i].help;
- const int length = 21-strlen(compiler_params[i].option);
+ const int length = 21 - strlen (compiler_params[i].option);
- if (description != NULL && * description != 0)
+ if (description != NULL && *description != 0)
printf (" --param %s=<value>%.*s%s\n",
compiler_params[i].option,
length > 0 ? length : 1, " ",
@@ -3648,7 +3719,7 @@ display_help ()
{
const char *description = W_options[i].description;
- if (description != NULL && * description != 0)
+ if (description != NULL && *description != 0)
printf (" -W%-21s %s\n",
W_options[i].string, _(description));
}
@@ -3768,7 +3839,7 @@ display_target_options ()
if (extra_warnings)
printf (_(" -m%-23.23s [undocumented]\n"), option);
}
- else if (* description != 0)
+ else if (*description != 0)
doc += printf (" -m%-23.23s %s\n", option, _(description));
}
@@ -3787,7 +3858,7 @@ display_target_options ()
if (extra_warnings)
printf (_(" -m%-23.23s [undocumented]\n"), option);
}
- else if (* description != 0)
+ else if (*description != 0)
doc += printf (" -m%-23.23s %s\n", option, _(description));
}
#endif
@@ -3823,9 +3894,9 @@ decode_d_option (arg)
flag_print_asm_name = 1;
break;
case 'P':
- flag_dump_rtl_in_asm = 1;
- flag_print_asm_name = 1;
- break;
+ flag_dump_rtl_in_asm = 1;
+ flag_print_asm_name = 1;
+ break;
case 'v':
graph_dump_format = vcg;
break;
@@ -3833,7 +3904,7 @@ decode_d_option (arg)
rtl_dump_and_exit = 1;
break;
case 'y':
- (*lang_hooks.set_yydebug) (1);
+ set_yydebug = 1;
break;
case 'D': /* These are handled by the preprocessor. */
case 'I':
@@ -3883,9 +3954,9 @@ decode_f_option (arg)
}
if (!strcmp (arg, "fast-math"))
- set_fast_math_flags ();
+ set_fast_math_flags (1);
else if (!strcmp (arg, "no-fast-math"))
- set_no_fast_math_flags ();
+ set_fast_math_flags (0);
else if ((option_value = skip_leading_substring (arg, "inline-limit-"))
|| (option_value = skip_leading_substring (arg, "inline-limit=")))
{
@@ -3893,6 +3964,29 @@ decode_f_option (arg)
read_integral_parameter (option_value, arg - 2,
MAX_INLINE_INSNS);
set_param_value ("max-inline-insns", val);
+ set_param_value ("max-inline-insns-single", val/2);
+ set_param_value ("max-inline-insns-auto", val/2);
+ set_param_value ("max-inline-insns-rtl", val);
+ if (val/4 < MIN_INLINE_INSNS)
+ {
+ if (val/4 > 10)
+ set_param_value ("min-inline-insns", val/4);
+ else
+ set_param_value ("min-inline-insns", 10);
+ }
+ }
+ else if ((option_value = skip_leading_substring (arg, "tls-model=")))
+ {
+ if (strcmp (option_value, "global-dynamic") == 0)
+ flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
+ else if (strcmp (option_value, "local-dynamic") == 0)
+ flag_tls_default = TLS_MODEL_LOCAL_DYNAMIC;
+ else if (strcmp (option_value, "initial-exec") == 0)
+ flag_tls_default = TLS_MODEL_INITIAL_EXEC;
+ else if (strcmp (option_value, "local-exec") == 0)
+ flag_tls_default = TLS_MODEL_LOCAL_EXEC;
+ else
+ warning ("`%s': unknown tls-model option", arg - 2);
}
#ifdef INSN_SCHEDULING
else if ((option_value = skip_leading_substring (arg, "sched-verbose=")))
@@ -3931,7 +4025,7 @@ decode_f_option (arg)
stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, nm);
}
else if ((option_value
- = skip_leading_substring (arg, "message-length=")))
+ = skip_leading_substring (arg, "message-length=")))
output_set_maximum_length
(&global_dc->buffer, read_integral_parameter
(option_value, arg - 2, diagnostic_line_cutoff (global_dc)));
@@ -3939,17 +4033,21 @@ decode_f_option (arg)
= skip_leading_substring (arg, "diagnostics-show-location=")))
{
if (!strcmp (option_value, "once"))
- diagnostic_prefixing_rule (global_dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
+ diagnostic_prefixing_rule (global_dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
else if (!strcmp (option_value, "every-line"))
- diagnostic_prefixing_rule (global_dc)
- = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
+ diagnostic_prefixing_rule (global_dc)
+ = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
else
error ("unrecognized option `%s'", arg - 2);
}
else if (!strcmp (arg, "no-stack-limit"))
stack_limit_rtx = NULL_RTX;
+ else if ((option_value = skip_leading_substring (arg, "random-seed=")))
+ flag_random_seed = option_value;
+ else if (!strcmp (arg, "no-random-seed"))
+ flag_random_seed = NULL;
else if (!strcmp (arg, "preprocessed"))
- /* Recognise this switch but do nothing. This prevents warnings
+ /* Recognize this switch but do nothing. This prevents warnings
about an unrecognized switch if cpplib has not been linked in. */
;
else
@@ -4017,7 +4115,7 @@ static int
decode_g_option (arg)
const char *arg;
{
- static unsigned level=0;
+ static unsigned level = 0;
/* A lot of code assumes write_symbols == NO_DEBUG if the
debugging level is 0 (thus -gstabs1 -gstabs0 would lose track
of what debugging type has been selected). This records the
@@ -4161,18 +4259,21 @@ independent_decode_option (argc, argv)
{
display_help ();
exit_after_options = 1;
+ return 1;
}
if (!strcmp (arg, "-target-help"))
{
display_target_options ();
exit_after_options = 1;
+ return 1;
}
if (!strcmp (arg, "-version"))
{
print_version (stderr, "");
exit_after_options = 1;
+ return 1;
}
/* Handle '--param <name>=<value>'. */
@@ -4237,7 +4338,9 @@ independent_decode_option (argc, argv)
if (argc == 1)
return 0;
- dump_base_name = argv[1];
+ if (argv[1][0])
+ dump_base_name = argv[1];
+
return 2;
}
else
@@ -4310,6 +4413,30 @@ independent_decode_option (argc, argv)
else
return 0;
}
+ else if (!strcmp (arg, "auxbase"))
+ {
+ if (argc == 1)
+ return 0;
+
+ if (argv[1][0])
+ aux_base_name = argv[1];
+
+ return 2;
+ }
+ else if (!strcmp (arg, "auxbase-strip"))
+ {
+ if (argc == 1)
+ return 0;
+
+ if (argv[1][0])
+ {
+ strip_off_ending (argv[1], strlen (argv[1]));
+ if (argv[1][0])
+ aux_base_name = argv[1];
+ }
+
+ return 2;
+ }
else
return 0;
break;
@@ -4376,6 +4503,13 @@ set_target_switch (name)
target_flags &= ~-target_switches[j].value;
else
target_flags |= target_switches[j].value;
+ if (name[0] != 0)
+ {
+ if (target_switches[j].value < 0)
+ target_flags_explicit |= -target_switches[j].value;
+ else
+ target_flags_explicit |= target_switches[j].value;
+ }
valid_target_option = 1;
}
@@ -4417,6 +4551,9 @@ print_version (file, indent)
, indent, *indent != 0 ? " " : "",
lang_hooks.name, version_string, TARGET_NAME,
indent, __VERSION__);
+ fnotice (file, "%s%sGGC heuristics: --param ggc-min-expand=%d --param ggc-min-heapsize=%d\n",
+ indent, *indent != 0 ? " " : "",
+ PARAM_VALUE (GGC_MIN_EXPAND), PARAM_VALUE (GGC_MIN_HEAPSIZE));
}
/* Print an option value and return the adjusted position in the line.
@@ -4463,6 +4600,12 @@ print_switch_values (file, pos, max, indent, sep, term)
size_t j;
char **p;
+ /* Fill in the -frandom-seed option, if the user didn't pass it, so
+ that it can be printed below. This helps reproducibility. Of
+ course, the string may never be used, but we can't tell that at
+ this point in the compile. */
+ default_flag_random_seed ();
+
/* Print the options as passed. */
pos = print_single_switch (file, pos, max, indent, *indent ? " " : "", term,
@@ -4541,25 +4684,25 @@ init_asm_output (name)
else
{
if (asm_file_name == 0)
- {
- int len = strlen (dump_base_name);
- char *dumpname = (char *) xmalloc (len + 6);
- memcpy (dumpname, dump_base_name, len + 1);
- strip_off_ending (dumpname, len);
- strcat (dumpname, ".s");
- asm_file_name = dumpname;
- }
+ {
+ int len = strlen (dump_base_name);
+ char *dumpname = (char *) xmalloc (len + 6);
+ memcpy (dumpname, dump_base_name, len + 1);
+ strip_off_ending (dumpname, len);
+ strcat (dumpname, ".s");
+ asm_file_name = dumpname;
+ }
if (!strcmp (asm_file_name, "-"))
- asm_out_file = stdout;
+ asm_out_file = stdout;
else
- asm_out_file = fopen (asm_file_name, "w");
+ asm_out_file = fopen (asm_file_name, "w");
if (asm_out_file == 0)
fatal_io_error ("can't open %s for writing", asm_file_name);
}
#ifdef IO_BUFFER_SIZE
setvbuf (asm_out_file, (char *) xmalloc (IO_BUFFER_SIZE),
- _IOFBF, IO_BUFFER_SIZE);
+ _IOFBF, IO_BUFFER_SIZE);
#endif
if (!flag_syntax_only)
@@ -4599,11 +4742,9 @@ general_init (argv0)
xmalloc_set_program_name (progname);
- gcc_init_libintl ();
+ hex_init ();
- /* Install handler for SIGFPE, which may be received while we do
- compile-time floating point arithmetic. */
- signal (SIGFPE, float_signal);
+ gcc_init_libintl ();
/* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages. */
#ifdef SIGSEGV
@@ -4621,16 +4762,27 @@ general_init (argv0)
#if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT)
signal (SIGIOT, crash_signal);
#endif
+#ifdef SIGFPE
+ signal (SIGFPE, crash_signal);
+#endif
/* Initialize the diagnostics reporting machinery, so option parsing
can give warnings and errors. */
diagnostic_initialize (global_dc);
+
+ /* Initialize the garbage-collector, string pools and tree type hash
+ table. */
+ init_ggc ();
+ init_stringpool ();
+ init_ttree ();
}
/* Parse command line options and set default flag values, called
after language-independent option-independent initialization. Do
minimal options processing. Outputting diagnostics is OK, but GC
- and identifier hashtables etc. are not initialized yet. */
+ and identifier hashtables etc. are not initialized yet.
+
+ Return nonzero to suppress compiler back end initialization. */
static void
parse_options_and_default_flags (argc, argv)
int argc;
@@ -4648,6 +4800,9 @@ parse_options_and_default_flags (argc, argv)
/* Register the language-independent parameters. */
add_params (lang_independent_params, LAST_PARAM);
+ /* This must be done after add_params but before argument processing. */
+ init_ggc_heuristics();
+
/* Perform language-specific options initialization. */
(*lang_hooks.init_options) ();
@@ -4701,6 +4856,10 @@ parse_options_and_default_flags (argc, argv)
#endif
flag_guess_branch_prob = 1;
flag_cprop_registers = 1;
+ flag_loop_optimize = 1;
+ flag_crossjumping = 1;
+ flag_if_conversion = 1;
+ flag_if_conversion2 = 1;
}
if (optimize >= 2)
@@ -4724,6 +4883,7 @@ parse_options_and_default_flags (argc, argv)
flag_strict_aliasing = 1;
flag_delete_null_pointer_checks = 1;
flag_reorder_blocks = 1;
+ flag_reorder_functions = 1;
}
if (optimize >= 3)
@@ -4738,6 +4898,15 @@ parse_options_and_default_flags (argc, argv)
align_jumps = 1;
align_labels = 1;
align_functions = 1;
+
+ /* Don't reorder blocks when optimizing for size because extra
+ jump insns may be created; also barrier may create extra padding.
+
+ More correctly we should have a block reordering mode that tried
+ to minimize the combined size of all the jumps. This would more
+ or less automatically remove extra jumps, but would also try to
+ use more short jumps instead of long jumps. */
+ flag_reorder_blocks = 0;
}
/* Initialize whether `char' is signed. */
@@ -4854,10 +5023,6 @@ parse_options_and_default_flags (argc, argv)
if (flag_really_no_inline == 2)
flag_really_no_inline = flag_no_inline;
-
- /* All command line options have been parsed; allow the front end to
- perform consistency checks, etc. */
- (*lang_hooks.post_options) ();
}
/* Process the options that have been parsed. */
@@ -4915,16 +5080,6 @@ process_options ()
warning ("this target machine does not have delayed branches");
#endif
- /* Some operating systems do not allow profiling without a frame
- pointer. */
- if (!TARGET_ALLOWS_PROFILING_WITHOUT_FRAME_POINTER
- && profile_flag
- && flag_omit_frame_pointer)
- {
- error ("profiling does not work without a frame pointer");
- flag_omit_frame_pointer = 0;
- }
-
user_label_prefix = USER_LABEL_PREFIX;
if (flag_leading_underscore != -1)
{
@@ -4949,7 +5104,7 @@ process_options ()
print_switch_values (stderr, 0, MAX_LINE, "", " ", "\n");
}
- if (! quiet_flag)
+ if (! quiet_flag || flag_detailed_statistics)
time_report = 1;
if (flag_syntax_only)
@@ -5041,30 +5196,19 @@ process_options ()
if (flag_function_sections && write_symbols != NO_DEBUG)
warning ("-ffunction-sections may affect debugging on some targets");
#endif
+
+ /* The presence of IEEE signaling NaNs, implies all math can trap. */
+ if (flag_signaling_nans)
+ flag_trapping_math = 1;
}
-/* Language-independent initialization, before language-dependent
- initialization. */
+/* Initialize the compiler back end. */
static void
-lang_independent_init ()
+backend_init ()
{
- decl_printable_name = decl_name;
- lang_expand_expr = (lang_expand_expr_t) do_abort;
-
- /* Set the language-dependent identifier size. */
- tree_code_length[(int) IDENTIFIER_NODE]
- = ((lang_hooks.identifier_size - sizeof (struct tree_common)
- + sizeof (tree) - 1) / sizeof (tree));
-
- /* Initialize the garbage-collector, and string pools. */
- init_ggc ();
- ggc_add_rtx_root (&stack_limit_rtx, 1);
- ggc_add_tree_root (&current_function_decl, 1);
- ggc_add_tree_root (&current_function_func_begin_label, 1);
-
- init_stringpool ();
- init_obstacks ();
-
+ /* init_emit_once uses reg_raw_mode and therefore must be called
+ after init_regs which initialized reg_raw_mode. */
+ init_regs ();
init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE
#ifdef VMS_DEBUGGING_INFO
@@ -5073,34 +5217,30 @@ lang_independent_init ()
#endif
|| flag_test_coverage
|| warn_notreached);
- init_regs ();
+ init_fake_stack_mems ();
init_alias_once ();
- init_stmt ();
init_loop ();
init_reload ();
init_function_once ();
- init_stor_layout_once ();
init_varasm_once ();
- init_EXPR_INSN_LIST_cache ();
/* The following initialization functions need to generate rtl, so
provide a dummy function context for them. */
init_dummy_function_start ();
init_expmed ();
- init_expr_once ();
if (flag_caller_saves)
init_caller_save ();
expand_dummy_function_end ();
}
-/* Language-dependent initialization. Returns non-zero on success. */
+/* Language-dependent initialization. Returns nonzero on success. */
static int
lang_dependent_init (name)
const char *name;
{
if (dump_base_name == 0)
dump_base_name = name ? name : "gccdump";
-
+
/* Front-end initialization. This hook can assume that GC,
identifier hashes etc. are set up, but debug initialization is
not done yet. This routine must return the original filename
@@ -5119,6 +5259,12 @@ lang_dependent_init (name)
init_eh ();
init_optabs ();
+ /* The following initialization functions need to generate rtl, so
+ provide a dummy function context for them. */
+ init_dummy_function_start ();
+ init_expr_once ();
+ expand_dummy_function_end ();
+
/* Put an entry on the input file stack for the main input file. */
push_srcloc (input_filename, 0);
@@ -5201,17 +5347,37 @@ finalize ()
static void
do_compile ()
{
+ /* All command line options have been parsed; allow the front end to
+ perform consistency checks, etc. */
+ bool no_backend = (*lang_hooks.post_options) ();
+
/* The bulk of command line switch processing. */
process_options ();
+ /* If an error has already occurred, give up. */
+ if (errorcount)
+ return;
+
+ if (aux_base_name)
+ /*NOP*/;
+ else if (filename)
+ {
+ char *name = xstrdup (lbasename (filename));
+
+ aux_base_name = name;
+ strip_off_ending (name, strlen (name));
+ }
+ else
+ aux_base_name = "gccaux";
+
/* We cannot start timing until after options are processed since that
says if we run timers or not. */
init_timevar ();
timevar_start (TV_TOTAL);
- /* Language-independent initialization. Also sets up GC, identifier
- hashes etc. */
- lang_independent_init ();
+ /* Set up the back-end if requested. */
+ if (!no_backend)
+ backend_init ();
/* Language-dependent initialization. Returns true on success. */
if (lang_dependent_init (filename))
@@ -5236,17 +5402,15 @@ toplev_main (argc, argv)
int argc;
char **argv;
{
- hex_init ();
-
/* Initialization of GCC's environment, and diagnostics. */
- general_init (argv [0]);
+ general_init (argv[0]);
/* Parse the options and do minimal processing; basically just
enough to default flags appropriately. */
parse_options_and_default_flags (argc, argv);
/* Exit early if we can (e.g. -help). */
- if (!errorcount && !exit_after_options)
+ if (!exit_after_options)
do_compile ();
if (errorcount || sorrycount)
diff --git a/contrib/gcc/toplev.h b/contrib/gcc/toplev.h
index 41ccedc..2dab244 100644
--- a/contrib/gcc/toplev.h
+++ b/contrib/gcc/toplev.h
@@ -29,7 +29,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
extern int toplev_main PARAMS ((int, char **));
extern int read_integral_parameter PARAMS ((const char *, const char *,
const int));
-extern int count_error PARAMS ((int));
extern void strip_off_ending PARAMS ((char *, int));
extern void print_time PARAMS ((const char *, long));
extern const char *trim_filename PARAMS ((const char *));
@@ -67,7 +66,6 @@ extern void warning_with_file_and_line PARAMS ((const char *, int,
extern void error_with_file_and_line PARAMS ((const char *, int,
const char *, ...));
extern void sorry PARAMS ((const char *, ...));
-extern void report_error_function PARAMS ((const char *));
extern void rest_of_decl_compilation PARAMS ((union tree_node *,
const char *, int, int));
@@ -88,8 +86,8 @@ extern void error_for_asm PARAMS ((struct rtx_def *,
extern void warning_for_asm PARAMS ((struct rtx_def *,
const char *, ...));
extern void warn_deprecated_use PARAMS ((union tree_node *));
-extern int do_float_handler PARAMS ((void (*) (PTR), PTR));
+extern void output_clean_symbol_name PARAMS ((FILE *, const char *));
#ifdef BUFSIZ
extern void output_quoted_string PARAMS ((FILE *, const char *));
extern void output_file_directive PARAMS ((FILE *, const char *));
@@ -110,15 +108,20 @@ extern void check_global_declarations PARAMS ((union tree_node **, int));
extern const char *progname;
extern const char *dump_base_name;
+extern const char *aux_base_name;
+
+extern int target_flags_explicit;
/* The hashtable, so that the C front ends can pass it to cpplib. */
extern struct ht *ident_hash;
-/* These functions can be used by targets to set the flags originally
- implied by -ffast-math and -fno-fast-math. */
+/* This function can be used by targets to set the flags originally
+ implied by -ffast-math and -fno-fast-math. */
+
+extern void set_fast_math_flags PARAMS ((int));
-extern void set_fast_math_flags PARAMS ((void));
-extern void set_no_fast_math_flags PARAMS ((void));
+/* Return true iff flags are set as if -ffast-math. */
+extern bool fast_math_flags_set_p PARAMS ((void));
/* The following functions accept a wide integer argument. Rather
than having to cast on every function call, we use a macro instead. */
diff --git a/contrib/gcc/tracer.c b/contrib/gcc/tracer.c
new file mode 100644
index 0000000..970b5f4
--- /dev/null
+++ b/contrib/gcc/tracer.c
@@ -0,0 +1,378 @@
+/* The tracer pass for the GNU compiler.
+ Contributed by Jan Hubicka, SuSE Labs.
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* This pass performs the tail duplication needed for superblock formation.
+ For more information see:
+
+ Design and Analysis of Profile-Based Optimization in Compaq's
+ Compilation Tools for Alpha; Journal of Instruction-Level
+ Parallelism 3 (2000) 1-25
+
+ Unlike Compaq's implementation we don't do the loop peeling as most
+ probably a better job can be done by a special pass and we don't
+ need to worry too much about the code size implications as the tail
+ duplicates are crossjumped again if optimizations are not
+ performed. */
+
+
+#include "config.h"
+#include "system.h"
+#include "tree.h"
+#include "rtl.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
+#include "output.h"
+#include "cfglayout.h"
+#include "fibheap.h"
+#include "flags.h"
+#include "params.h"
+#include "profile.h"
+
+static int count_insns PARAMS ((basic_block));
+static bool ignore_bb_p PARAMS ((basic_block));
+static bool better_p PARAMS ((edge, edge));
+static edge find_best_successor PARAMS ((basic_block));
+static edge find_best_predecessor PARAMS ((basic_block));
+static int find_trace PARAMS ((basic_block, basic_block *));
+static void tail_duplicate PARAMS ((void));
+static void layout_superblocks PARAMS ((void));
+static bool ignore_bb_p PARAMS ((basic_block));
+
+/* Minimal outgoing edge probability considered for superblock formation. */
+static int probability_cutoff;
+static int branch_ratio_cutoff;
+
+/* Return true if BB has been seen - it is connected to some trace
+ already. */
+
+#define seen(bb) (RBI (bb)->visited || RBI (bb)->next)
+
+/* Return true if we should ignore the basic block for purposes of tracing. */
+static bool
+ignore_bb_p (bb)
+ basic_block bb;
+{
+ if (bb->index < 0)
+ return true;
+ if (!maybe_hot_bb_p (bb))
+ return true;
+ return false;
+}
+
+/* Return number of instructions in the block. */
+
+static int
+count_insns (bb)
+ basic_block bb;
+{
+ rtx insn;
+ int n = 0;
+
+ for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = NEXT_INSN (insn))
+ if (active_insn_p (insn))
+ n++;
+ return n;
+}
+
+/* Return true if E1 is more frequent than E2. */
+static bool
+better_p (e1, e2)
+ edge e1, e2;
+{
+ if (e1->count != e2->count)
+ return e1->count > e2->count;
+ if (e1->src->frequency * e1->probability !=
+ e2->src->frequency * e2->probability)
+ return (e1->src->frequency * e1->probability
+ > e2->src->frequency * e2->probability);
+ /* This is needed to avoid changes in the decision after
+ CFG is modified. */
+ if (e1->src != e2->src)
+ return e1->src->index > e2->src->index;
+ return e1->dest->index > e2->dest->index;
+}
+
+/* Return most frequent successor of basic block BB. */
+
+static edge
+find_best_successor (bb)
+ basic_block bb;
+{
+ edge e;
+ edge best = NULL;
+
+ for (e = bb->succ; e; e = e->succ_next)
+ if (!best || better_p (e, best))
+ best = e;
+ if (!best || ignore_bb_p (best->dest))
+ return NULL;
+ if (best->probability <= probability_cutoff)
+ return NULL;
+ return best;
+}
+
+/* Return most frequent predecessor of basic block BB. */
+
+static edge
+find_best_predecessor (bb)
+ basic_block bb;
+{
+ edge e;
+ edge best = NULL;
+
+ for (e = bb->pred; e; e = e->pred_next)
+ if (!best || better_p (e, best))
+ best = e;
+ if (!best || ignore_bb_p (best->src))
+ return NULL;
+ if (EDGE_FREQUENCY (best) * REG_BR_PROB_BASE
+ < bb->frequency * branch_ratio_cutoff)
+ return NULL;
+ return best;
+}
+
+/* Find the trace using bb and record it in the TRACE array.
+ Return number of basic blocks recorded. */
+
+static int
+find_trace (bb, trace)
+ basic_block bb;
+ basic_block *trace;
+{
+ int i = 0;
+ edge e;
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Trace seed %i [%i]", bb->index, bb->frequency);
+
+ while ((e = find_best_predecessor (bb)) != NULL)
+ {
+ basic_block bb2 = e->src;
+ if (seen (bb2) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
+ || find_best_successor (bb2) != e)
+ break;
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, ",%i [%i]", bb->index, bb->frequency);
+ bb = bb2;
+ }
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, " forward %i [%i]", bb->index, bb->frequency);
+ trace[i++] = bb;
+
+ /* Follow the trace in forward direction. */
+ while ((e = find_best_successor (bb)) != NULL)
+ {
+ bb = e->dest;
+ if (seen (bb) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
+ || find_best_predecessor (bb) != e)
+ break;
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, ",%i [%i]", bb->index, bb->frequency);
+ trace[i++] = bb;
+ }
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "\n");
+ return i;
+}
+
+/* Look for basic blocks in frequency order, construct traces and tail duplicate
+ if profitable. */
+
+static void
+tail_duplicate ()
+{
+ fibnode_t *blocks = xcalloc (last_basic_block, sizeof (fibnode_t));
+ basic_block *trace = xmalloc (sizeof (basic_block) * n_basic_blocks);
+ int *counts = xmalloc (sizeof (int) * last_basic_block);
+ int ninsns = 0, nduplicated = 0;
+ gcov_type weighted_insns = 0, traced_insns = 0;
+ fibheap_t heap = fibheap_new ();
+ gcov_type cover_insns;
+ int max_dup_insns;
+ basic_block bb;
+
+ if (profile_info.count_profiles_merged && flag_branch_probabilities)
+ probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK);
+ else
+ probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY);
+ probability_cutoff = REG_BR_PROB_BASE / 100 * probability_cutoff;
+
+ branch_ratio_cutoff =
+ (REG_BR_PROB_BASE / 100 * PARAM_VALUE (TRACER_MIN_BRANCH_RATIO));
+
+ FOR_EACH_BB (bb)
+ {
+ int n = count_insns (bb);
+ if (!ignore_bb_p (bb))
+ blocks[bb->index] = fibheap_insert (heap, -bb->frequency,
+ bb);
+
+ counts [bb->index] = n;
+ ninsns += n;
+ weighted_insns += n * bb->frequency;
+ }
+
+ if (profile_info.count_profiles_merged && flag_branch_probabilities)
+ cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE_FEEDBACK);
+ else
+ cover_insns = PARAM_VALUE (TRACER_DYNAMIC_COVERAGE);
+ cover_insns = (weighted_insns * cover_insns + 50) / 100;
+ max_dup_insns = (ninsns * PARAM_VALUE (TRACER_MAX_CODE_GROWTH) + 50) / 100;
+
+ while (traced_insns < cover_insns && nduplicated < max_dup_insns
+ && !fibheap_empty (heap))
+ {
+ basic_block bb = fibheap_extract_min (heap);
+ int n, pos;
+
+ if (!bb)
+ break;
+
+ blocks[bb->index] = NULL;
+
+ if (ignore_bb_p (bb))
+ continue;
+ if (seen (bb))
+ abort ();
+
+ n = find_trace (bb, trace);
+
+ bb = trace[0];
+ traced_insns += bb->frequency * counts [bb->index];
+ if (blocks[bb->index])
+ {
+ fibheap_delete_node (heap, blocks[bb->index]);
+ blocks[bb->index] = NULL;
+ }
+
+ for (pos = 1; pos < n; pos++)
+ {
+ basic_block bb2 = trace[pos];
+
+ if (blocks[bb2->index])
+ {
+ fibheap_delete_node (heap, blocks[bb2->index]);
+ blocks[bb2->index] = NULL;
+ }
+ traced_insns += bb2->frequency * counts [bb2->index];
+ if (bb2->pred && bb2->pred->pred_next
+ && cfg_layout_can_duplicate_bb_p (bb2))
+ {
+ edge e = bb2->pred;
+ basic_block old = bb2;
+
+ while (e->src != bb)
+ e = e->pred_next;
+ nduplicated += counts [bb2->index];
+ bb2 = cfg_layout_duplicate_bb (bb2, e);
+
+ /* Reconsider the original copy of block we've duplicated.
+ Removing the most common predecesor may make it to be
+ head. */
+ blocks[old->index] =
+ fibheap_insert (heap, -old->frequency, old);
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Duplicated %i as %i [%i]\n",
+ old->index, bb2->index, bb2->frequency);
+ }
+ RBI (bb)->next = bb2;
+ RBI (bb2)->visited = 1;
+ bb = bb2;
+ /* In case the trace became infrequent, stop duplicating. */
+ if (ignore_bb_p (bb))
+ break;
+ }
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, " covered now %.1f\n\n",
+ traced_insns * 100.0 / weighted_insns);
+ }
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Duplicated %i insns (%i%%)\n", nduplicated,
+ nduplicated * 100 / ninsns);
+
+ free (blocks);
+ free (trace);
+ free (counts);
+ fibheap_delete (heap);
+}
+
+/* Connect the superblocks into linear seuqence. At the moment we attempt to keep
+ the original order as much as possible, but the algorithm may be made smarter
+ later if needed. BB reordering pass should void most of the benefits of such
+ change though. */
+
+static void
+layout_superblocks ()
+{
+ basic_block end = ENTRY_BLOCK_PTR->succ->dest;
+ basic_block bb = ENTRY_BLOCK_PTR->succ->dest->next_bb;
+
+ while (bb != EXIT_BLOCK_PTR)
+ {
+ edge e, best = NULL;
+ while (RBI (end)->next)
+ end = RBI (end)->next;
+
+ for (e = end->succ; e; e = e->succ_next)
+ if (e->dest != EXIT_BLOCK_PTR
+ && e->dest != ENTRY_BLOCK_PTR->succ->dest
+ && !RBI (e->dest)->visited
+ && (!best || EDGE_FREQUENCY (e) > EDGE_FREQUENCY (best)))
+ best = e;
+
+ if (best)
+ {
+ RBI (end)->next = best->dest;
+ RBI (best->dest)->visited = 1;
+ }
+ else
+ for (; bb != EXIT_BLOCK_PTR; bb=bb->next_bb)
+ {
+ if (!RBI (bb)->visited)
+ {
+ RBI (end)->next = bb;
+ RBI (bb)->visited = 1;
+ break;
+ }
+ }
+ }
+}
+
+/* Main entry point to this file. */
+
+void
+tracer ()
+{
+ if (n_basic_blocks <= 1)
+ return;
+ cfg_layout_initialize ();
+ mark_dfs_back_edges ();
+ if (rtl_dump_file)
+ dump_flow_info (rtl_dump_file);
+ tail_duplicate ();
+ layout_superblocks ();
+ if (rtl_dump_file)
+ dump_flow_info (rtl_dump_file);
+ cfg_layout_finalize ();
+ /* Merge basic blocks in duplicated traces. */
+ cleanup_cfg (CLEANUP_EXPENSIVE);
+}
diff --git a/contrib/gcc/tree-dump.c b/contrib/gcc/tree-dump.c
index d8d8e23..5b9f4f5 100644
--- a/contrib/gcc/tree-dump.c
+++ b/contrib/gcc/tree-dump.c
@@ -22,7 +22,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
#include "tree.h"
-#include "c-tree.h"
#include "splay-tree.h"
#include "diagnostic.h"
#include "toplev.h"
@@ -65,7 +64,7 @@ queue (di, t, flags)
dni = (dump_node_info_p) xmalloc (sizeof (struct dump_node_info));
dni->index = index;
dni->binfo_p = ((flags & DUMP_BINFO) != 0);
- dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
+ dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
(splay_tree_value) dni);
/* Add it to the end of the queue. */
@@ -156,7 +155,7 @@ dump_maybe_newline (di)
dump_info_p di;
{
int extra;
-
+
/* See if we need a new line. */
if (di->column > EOL_COLUMN)
dump_new_line (di);
@@ -225,29 +224,9 @@ dump_string_field (di, field, string)
di->column += 14;
}
-/* Dump information common to statements from STMT. */
-
-void
-dump_stmt (di, t)
- dump_info_p di;
- tree t;
-{
- dump_int (di, "line", STMT_LINENO (t));
-}
-
-/* Dump the next statement after STMT. */
-
-void
-dump_next_stmt (di, t)
- dump_info_p di;
- tree t;
-{
- dump_child ("next", TREE_CHAIN (t));
-}
-
/* Dump the next node in the queue. */
-static void
+static void
dequeue_and_dump (di)
dump_info_p di;
{
@@ -300,7 +279,7 @@ dequeue_and_dump (di)
dump_string (di, "priv");
if (TREE_VIA_VIRTUAL (t))
dump_string (di, "virt");
-
+
dump_child ("type", BINFO_TYPE (t));
dump_child ("base", BINFO_BASETYPES (t));
@@ -319,17 +298,17 @@ dequeue_and_dump (di)
case '1':
dump_child ("op 0", TREE_OPERAND (t, 0));
break;
-
+
case '2':
case '<':
dump_child ("op 0", TREE_OPERAND (t, 0));
dump_child ("op 1", TREE_OPERAND (t, 1));
break;
-
+
case 'e':
/* These nodes are handled explicitly below. */
break;
-
+
default:
abort ();
}
@@ -339,7 +318,7 @@ dequeue_and_dump (di)
/* All declarations have names. */
if (DECL_NAME (t))
dump_child ("name", DECL_NAME (t));
- if (DECL_ASSEMBLER_NAME_SET_P (t)
+ if (DECL_ASSEMBLER_NAME_SET_P (t)
&& DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
/* And types. */
@@ -356,7 +335,7 @@ dequeue_and_dump (di)
++filename;
dump_maybe_newline (di);
- fprintf (di->stream, "srcp: %s:%-6d ", filename,
+ fprintf (di->stream, "srcp: %s:%-6d ", filename,
DECL_SOURCE_LINE (t));
di->column += 6 + strlen (filename) + 8;
}
@@ -370,7 +349,7 @@ dequeue_and_dump (di)
{
/* All types have qualifiers. */
int quals = (*lang_hooks.tree_dump.type_quals) (t);
-
+
if (quals != TYPE_UNQUALIFIED)
{
fprintf (di->stream, "qual: %c%c%c ",
@@ -386,7 +365,7 @@ dequeue_and_dump (di)
/* All types have a main variant. */
if (TYPE_MAIN_VARIANT (t) != t)
dump_child ("unql", TYPE_MAIN_VARIANT (t));
-
+
/* And sizes. */
dump_child ("size", TYPE_SIZE (t));
@@ -473,10 +452,10 @@ dequeue_and_dump (di)
dump_string (di, "struct");
else
dump_string (di, "union");
-
+
dump_child ("flds", TYPE_FIELDS (t));
dump_child ("fncs", TYPE_METHODS (t));
- queue_and_dump_index (di, "binf", TYPE_BINFO (t),
+ queue_and_dump_index (di, "binf", TYPE_BINFO (t),
DUMP_BINFO);
break;
@@ -497,12 +476,10 @@ dequeue_and_dump (di)
if (TREE_CODE (t) == FIELD_DECL)
{
- if (DECL_C_BIT_FIELD (t))
- dump_string (di, "bitfield");
if (DECL_FIELD_OFFSET (t))
dump_child ("bpos", bit_position (t));
}
- else if (TREE_CODE (t) == VAR_DECL
+ else if (TREE_CODE (t) == VAR_DECL
|| TREE_CODE (t) == PARM_DECL)
{
dump_int (di, "used", TREE_USED (t));
@@ -523,125 +500,6 @@ dequeue_and_dump (di)
dump_child ("body", DECL_SAVED_TREE (t));
break;
- case ASM_STMT:
- dump_stmt (di, t);
- if (ASM_VOLATILE_P (t))
- dump_string (di, "volatile");
- dump_child ("strg", ASM_STRING (t));
- dump_child ("outs", ASM_OUTPUTS (t));
- dump_child ("ins", ASM_INPUTS (t));
- dump_child ("clbr", ASM_CLOBBERS (t));
- dump_next_stmt (di, t);
- break;
-
- case BREAK_STMT:
- case CONTINUE_STMT:
- dump_stmt (di, t);
- dump_next_stmt (di, t);
- break;
-
- case CASE_LABEL:
- /* Note that a case label is not like other statements; there is
- no way to get the line-number of a case label. */
- dump_child ("low", CASE_LOW (t));
- dump_child ("high", CASE_HIGH (t));
- dump_next_stmt (di, t);
- break;
-
- case CLEANUP_STMT:
- dump_stmt (di, t);
- dump_child ("decl", CLEANUP_DECL (t));
- dump_child ("expr", CLEANUP_EXPR (t));
- dump_next_stmt (di, t);
- break;
-
- case COMPOUND_STMT:
- dump_stmt (di, t);
- dump_child ("body", COMPOUND_BODY (t));
- dump_next_stmt (di, t);
- break;
-
- case DECL_STMT:
- dump_stmt (di, t);
- dump_child ("decl", DECL_STMT_DECL (t));
- dump_next_stmt (di, t);
- break;
-
- case DO_STMT:
- dump_stmt (di, t);
- dump_child ("body", DO_BODY (t));
- dump_child ("cond", DO_COND (t));
- dump_next_stmt (di, t);
- break;
-
- case EXPR_STMT:
- dump_stmt (di, t);
- dump_child ("expr", EXPR_STMT_EXPR (t));
- dump_next_stmt (di, t);
- break;
-
- case FOR_STMT:
- dump_stmt (di, t);
- dump_child ("init", FOR_INIT_STMT (t));
- dump_child ("cond", FOR_COND (t));
- dump_child ("expr", FOR_EXPR (t));
- dump_child ("body", FOR_BODY (t));
- dump_next_stmt (di, t);
- break;
-
- case GOTO_STMT:
- dump_stmt (di, t);
- dump_child ("dest", GOTO_DESTINATION (t));
- dump_next_stmt (di, t);
- break;
-
- case IF_STMT:
- dump_stmt (di, t);
- dump_child ("cond", IF_COND (t));
- dump_child ("then", THEN_CLAUSE (t));
- dump_child ("else", ELSE_CLAUSE (t));
- dump_next_stmt (di, t);
- break;
-
- case LABEL_STMT:
- dump_stmt (di, t);
- dump_child ("labl", LABEL_STMT_LABEL (t));
- dump_next_stmt (di, t);
- break;
-
- case RETURN_STMT:
- dump_stmt (di, t);
- dump_child ("expr", RETURN_EXPR (t));
- dump_next_stmt (di, t);
- break;
-
- case SWITCH_STMT:
- dump_stmt (di, t);
- dump_child ("cond", SWITCH_COND (t));
- dump_child ("body", SWITCH_BODY (t));
- dump_next_stmt (di, t);
- break;
-
- case WHILE_STMT:
- dump_stmt (di, t);
- dump_child ("cond", WHILE_COND (t));
- dump_child ("body", WHILE_BODY (t));
- dump_next_stmt (di, t);
- break;
-
- case SCOPE_STMT:
- dump_stmt (di, t);
- if (SCOPE_BEGIN_P (t))
- dump_string (di, "begn");
- else
- dump_string (di, "end");
- if (SCOPE_NULLIFIED_P (t))
- dump_string (di, "null");
- if (!SCOPE_NO_CLEANUPS_P (t))
- dump_string (di, "clnp");
- dump_next_stmt (di, t);
- break;
-
case INTEGER_CST:
if (TREE_INT_CST_HIGH (t))
dump_int (di, "high", TREE_INT_CST_HIGH (t));
@@ -693,10 +551,6 @@ dequeue_and_dump (di)
dump_child ("elts", TREE_OPERAND (t, 1));
break;
- case STMT_EXPR:
- dump_child ("stmt", STMT_EXPR_STMT (t));
- break;
-
case BIND_EXPR:
dump_child ("vars", TREE_OPERAND (t, 0));
dump_child ("body", TREE_OPERAND (t, 1));
@@ -720,7 +574,7 @@ dequeue_and_dump (di)
becomes NULL. */
dump_child ("init", TREE_OPERAND (t, 3));
break;
-
+
case EXPR_WITH_FILE_LOCATION:
dump_child ("expr", EXPR_WFL_NODE (t));
break;
@@ -733,12 +587,12 @@ dequeue_and_dump (di)
done:
if (dump_flag (di, TDF_ADDRESS, NULL))
dump_pointer (di, "addr", (void *)t);
-
+
/* Terminate the line. */
fprintf (di->stream, "\n");
}
-/* Return non-zero if FLAG has been specified for the dump, and NODE
+/* Return nonzero if FLAG has been specified for the dump, and NODE
is not the root node of the dump. */
int dump_flag (di, flag, node)
@@ -770,7 +624,7 @@ dump_node (t, flags, stream)
di.free_list = 0;
di.flags = flags;
di.node = t;
- di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
+ di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
(splay_tree_delete_value_fn) &free);
/* Queue up the first node. */
@@ -838,10 +692,10 @@ dump_begin (phase, flag_ptr)
{
FILE *stream;
char *name;
-
+
if (!dump_files[phase].state)
return NULL;
-
+
name = concat (dump_base_name, dump_files[phase].suffix, NULL);
stream = fopen (name, dump_files[phase].state < 0 ? "w" : "a");
if (!stream)
@@ -851,11 +705,11 @@ dump_begin (phase, flag_ptr)
free (name);
if (flag_ptr)
*flag_ptr = dump_files[phase].flags;
-
+
return stream;
}
-/* Returns non-zero if tree dump PHASE is enabled. */
+/* Returns nonzero if tree dump PHASE is enabled. */
int
dump_enabled_p (phase)
@@ -884,7 +738,7 @@ dump_end (phase, stream)
fclose (stream);
}
-/* Parse ARG as a dump switch. Return non-zero if it is, and store the
+/* Parse ARG as a dump switch. Return nonzero if it is, and store the
relevant details in the dump_files array. */
int
@@ -893,26 +747,26 @@ dump_switch_p (arg)
{
unsigned ix;
const char *option_value;
-
+
for (ix = 0; ix != TDI_end; ix++)
if ((option_value = skip_leading_substring (arg, dump_files[ix].swtch)))
{
const char *ptr = option_value;
int flags = 0;
-
+
while (*ptr)
{
const struct dump_option_value_info *option_ptr;
const char *end_ptr;
unsigned length;
-
+
while (*ptr == '-')
ptr++;
end_ptr = strchr (ptr, '-');
if (!end_ptr)
end_ptr = ptr + strlen (ptr);
length = end_ptr - ptr;
-
+
for (option_ptr = dump_options; option_ptr->name;
option_ptr++)
if (strlen (option_ptr->name) == length
@@ -926,10 +780,10 @@ dump_switch_p (arg)
found:;
ptr = end_ptr;
}
-
+
dump_files[ix].state = -1;
dump_files[ix].flags = flags;
-
+
return 1;
}
return 0;
diff --git a/contrib/gcc/tree-dump.h b/contrib/gcc/tree-dump.h
index 9e9888e..d4951d9 100644
--- a/contrib/gcc/tree-dump.h
+++ b/contrib/gcc/tree-dump.h
@@ -46,7 +46,7 @@ typedef struct dump_queue
struct dump_queue *next;
} *dump_queue_p;
-/* A dump_info gives information about how we should perform the dump
+/* A dump_info gives information about how we should perform the dump
and about the current state of the dump. */
struct dump_info
@@ -67,7 +67,7 @@ struct dump_info
dump_queue_p queue_end;
/* Free queue nodes. */
dump_queue_p free_list;
- /* The tree nodes which we have already written out. The
+ /* The tree nodes which we have already written out. The
keys are the addresses of the nodes; the values are the integer
indices we assigned them. */
splay_tree nodes;
@@ -79,17 +79,17 @@ struct dump_info
extern void dump_pointer
PARAMS ((dump_info_p, const char *, void *));
-extern void dump_int
+extern void dump_int
PARAMS ((dump_info_p, const char *, int));
-extern void dump_string
+extern void dump_string
PARAMS ((dump_info_p, const char *));
-extern void dump_stmt
+extern void dump_stmt
PARAMS ((dump_info_p, tree));
-extern void dump_next_stmt
+extern void dump_next_stmt
PARAMS ((dump_info_p, tree));
-extern void queue_and_dump_index
+extern void queue_and_dump_index
PARAMS ((dump_info_p, const char *, tree, int));
-extern void queue_and_dump_type
+extern void queue_and_dump_type
PARAMS ((dump_info_p, tree));
#endif /* ! GCC_TREE_DUMP_H */
diff --git a/contrib/gcc/tree-inline.c b/contrib/gcc/tree-inline.c
index 307c35c..28ceda1 100644
--- a/contrib/gcc/tree-inline.c
+++ b/contrib/gcc/tree-inline.c
@@ -38,11 +38,16 @@ Boston, MA 02111-1307, USA. */
/* This should be eventually be generalized to other languages, but
this would require a shared function-as-trees infrastructure. */
-#include "c-common.h"
+#ifndef INLINER_FOR_JAVA
+#include "c-common.h"
+#else /* INLINER_FOR_JAVA */
+#include "parse.h"
+#include "java-tree.h"
+#endif /* INLINER_FOR_JAVA */
/* 0 if we should not perform inlining.
- 1 if we should expand functions calls inline at the tree level.
- 2 if we should consider *all* functions to be inline
+ 1 if we should expand functions calls inline at the tree level.
+ 2 if we should consider *all* functions to be inline
candidates. */
int flag_inline_trees = 0;
@@ -102,7 +107,6 @@ typedef struct inline_data
/* Prototypes. */
-static tree initialize_inlined_parameters PARAMS ((inline_data *, tree, tree));
static tree declare_return_variable PARAMS ((inline_data *, tree *));
static tree copy_body_r PARAMS ((tree *, int *, void *));
static tree copy_body PARAMS ((inline_data *));
@@ -110,8 +114,19 @@ static tree expand_call_inline PARAMS ((tree *, int *, void *));
static void expand_calls_inline PARAMS ((tree *, inline_data *));
static int inlinable_function_p PARAMS ((tree, inline_data *));
static tree remap_decl PARAMS ((tree, inline_data *));
+#ifndef INLINER_FOR_JAVA
+static tree initialize_inlined_parameters PARAMS ((inline_data *, tree, tree));
static void remap_block PARAMS ((tree, tree, inline_data *));
static void copy_scope_stmt PARAMS ((tree *, int *, inline_data *));
+#else /* INLINER_FOR_JAVA */
+static tree initialize_inlined_parameters PARAMS ((inline_data *, tree, tree, tree));
+static void remap_block PARAMS ((tree *, tree, inline_data *));
+static tree add_stmt_to_compound PARAMS ((tree, tree, tree));
+#endif /* INLINER_FOR_JAVA */
+static tree find_alloca_call_1 PARAMS ((tree *, int *, void *));
+static tree find_alloca_call PARAMS ((tree));
+static tree find_builtin_longjmp_call_1 PARAMS ((tree *, int *, void *));
+static tree find_builtin_longjmp_call PARAMS ((tree));
/* The approximate number of instructions per statement. This number
need not be particularly accurate; it is used only to make
@@ -158,6 +173,7 @@ remap_decl (decl, id)
copy_body_r, id, NULL);
}
+#ifndef INLINER_FOR_JAVA
if (! DECL_NAME (t) && TREE_TYPE (t)
&& (*lang_hooks.tree_inlining.anon_aggr_type_p) (TREE_TYPE (t)))
{
@@ -166,7 +182,7 @@ remap_decl (decl, id)
DECL_ANON_UNION_ELEMS. */
tree members = NULL;
tree src;
-
+
for (src = DECL_ANON_UNION_ELEMS (t); src;
src = TREE_CHAIN (src))
{
@@ -178,7 +194,8 @@ remap_decl (decl, id)
}
DECL_ANON_UNION_ELEMS (t) = nreverse (members);
}
-
+#endif /* not INLINER_FOR_JAVA */
+
/* Remember it, so that if we encounter this local entity
again we can reuse this copy. */
n = splay_tree_insert (id->decl_map,
@@ -189,17 +206,28 @@ remap_decl (decl, id)
return (tree) n->value;
}
+#ifndef INLINER_FOR_JAVA
/* Copy the SCOPE_STMT_BLOCK associated with SCOPE_STMT to contain
remapped versions of the variables therein. And hook the new block
into the block-tree. If non-NULL, the DECLS are declarations to
add to use instead of the BLOCK_VARS in the old block. */
+#else /* INLINER_FOR_JAVA */
+/* Copy the BLOCK to contain remapped versions of the variables
+ therein. And hook the new block into the block-tree. */
+#endif /* INLINER_FOR_JAVA */
static void
+#ifndef INLINER_FOR_JAVA
remap_block (scope_stmt, decls, id)
tree scope_stmt;
+#else /* INLINER_FOR_JAVA */
+remap_block (block, decls, id)
+ tree *block;
+#endif /* INLINER_FOR_JAVA */
tree decls;
inline_data *id;
{
+#ifndef INLINER_FOR_JAVA
/* We cannot do this in the cleanup for a TARGET_EXPR since we do
not know whether or not expand_expr will actually write out the
code we put there. If it does not, then we'll have more BLOCKs
@@ -257,7 +285,7 @@ remap_block (scope_stmt, decls, id)
/* We're building a clone; DECL_INITIAL is still
error_mark_node, and current_binding_level is the parm
binding level. */
- insert_block (new_block);
+ (*lang_hooks.decls.insert_block) (new_block);
else
{
/* Attach this new block after the DECL_INITIAL block for the
@@ -289,8 +317,72 @@ remap_block (scope_stmt, decls, id)
abort ();
SCOPE_STMT_BLOCK (scope_stmt) = (tree) n->value;
}
+#else /* INLINER_FOR_JAVA */
+ tree old_block;
+ tree new_block;
+ tree old_var;
+ tree fn;
+
+ /* Make the new block. */
+ old_block = *block;
+ new_block = make_node (BLOCK);
+ TREE_USED (new_block) = TREE_USED (old_block);
+ BLOCK_ABSTRACT_ORIGIN (new_block) = old_block;
+ BLOCK_SUBBLOCKS (new_block) = BLOCK_SUBBLOCKS (old_block);
+ TREE_SIDE_EFFECTS (new_block) = TREE_SIDE_EFFECTS (old_block);
+ TREE_TYPE (new_block) = TREE_TYPE (old_block);
+ *block = new_block;
+
+ /* Remap its variables. */
+ for (old_var = decls ? decls : BLOCK_VARS (old_block);
+ old_var;
+ old_var = TREE_CHAIN (old_var))
+ {
+ tree new_var;
+
+ /* All local class initialization flags go in the outermost
+ scope. */
+ if (LOCAL_CLASS_INITIALIZATION_FLAG_P (old_var))
+ {
+ /* We may already have one. */
+ if (! splay_tree_lookup (id->decl_map, (splay_tree_key) old_var))
+ {
+ tree outermost_block;
+ new_var = remap_decl (old_var, id);
+ DECL_ABSTRACT_ORIGIN (new_var) = NULL;
+ outermost_block = DECL_SAVED_TREE (current_function_decl);
+ TREE_CHAIN (new_var) = BLOCK_VARS (outermost_block);
+ BLOCK_VARS (outermost_block) = new_var;
+ }
+ continue;
+ }
+
+ /* Remap the variable. */
+ new_var = remap_decl (old_var, id);
+ /* If we didn't remap this variable, so we can't mess with
+ its TREE_CHAIN. If we remapped this variable to
+ something other than a declaration (say, if we mapped it
+ to a constant), then we must similarly omit any mention
+ of it here. */
+ if (!new_var || !DECL_P (new_var))
+ ;
+ else
+ {
+ TREE_CHAIN (new_var) = BLOCK_VARS (new_block);
+ BLOCK_VARS (new_block) = new_var;
+ }
+ }
+ /* We put the BLOCK_VARS in reverse order; fix that now. */
+ BLOCK_VARS (new_block) = nreverse (BLOCK_VARS (new_block));
+ fn = VARRAY_TREE (id->fns, 0);
+ /* Remember the remapped block. */
+ splay_tree_insert (id->decl_map,
+ (splay_tree_key) old_block,
+ (splay_tree_value) new_block);
+#endif /* INLINER_FOR_JAVA */
}
+#ifndef INLINER_FOR_JAVA
/* Copy the SCOPE_STMT pointed to by TP. */
static void
@@ -314,10 +406,10 @@ copy_scope_stmt (tp, walk_subtrees, id)
/* Remap the associated block. */
remap_block (*tp, NULL_TREE, id);
}
+#endif /* not INLINER_FOR_JAVA */
/* Called from copy_body via walk_tree. DATA is really an
`inline_data *'. */
-
static tree
copy_body_r (tp, walk_subtrees, data)
tree *tp;
@@ -340,29 +432,53 @@ copy_body_r (tp, walk_subtrees, data)
abort ();
#endif
+#ifdef INLINER_FOR_JAVA
+ if (TREE_CODE (*tp) == BLOCK)
+ remap_block (tp, NULL_TREE, id);
+#endif
+
/* If this is a RETURN_STMT, change it into an EXPR_STMT and a
GOTO_STMT with the RET_LABEL as its target. */
+#ifndef INLINER_FOR_JAVA
if (TREE_CODE (*tp) == RETURN_STMT && id->ret_label)
+#else /* INLINER_FOR_JAVA */
+ if (TREE_CODE (*tp) == RETURN_EXPR && id->ret_label)
+#endif /* INLINER_FOR_JAVA */
{
tree return_stmt = *tp;
tree goto_stmt;
/* Build the GOTO_STMT. */
+#ifndef INLINER_FOR_JAVA
goto_stmt = build_stmt (GOTO_STMT, id->ret_label);
TREE_CHAIN (goto_stmt) = TREE_CHAIN (return_stmt);
GOTO_FAKE_P (goto_stmt) = 1;
+#else /* INLINER_FOR_JAVA */
+ tree assignment = TREE_OPERAND (return_stmt, 0);
+ goto_stmt = build1 (GOTO_EXPR, void_type_node, id->ret_label);
+ TREE_SIDE_EFFECTS (goto_stmt) = 1;
+#endif /* INLINER_FOR_JAVA */
/* If we're returning something, just turn that into an
assignment into the equivalent of the original
RESULT_DECL. */
- if (RETURN_EXPR (return_stmt))
+#ifndef INLINER_FOR_JAVA
+ if (RETURN_STMT_EXPR (return_stmt))
{
*tp = build_stmt (EXPR_STMT,
- RETURN_EXPR (return_stmt));
+ RETURN_STMT_EXPR (return_stmt));
STMT_IS_FULL_EXPR_P (*tp) = 1;
/* And then jump to the end of the function. */
TREE_CHAIN (*tp) = goto_stmt;
}
+#else /* INLINER_FOR_JAVA */
+ if (assignment)
+ {
+ copy_body_r (&assignment, walk_subtrees, data);
+ *tp = build (COMPOUND_EXPR, void_type_node, assignment, goto_stmt);
+ TREE_SIDE_EFFECTS (*tp) = 1;
+ }
+#endif /* INLINER_FOR_JAVA */
/* If we're not returning anything just do the jump. */
else
*tp = goto_stmt;
@@ -394,10 +510,35 @@ copy_body_r (tp, walk_subtrees, data)
else if (TREE_CODE (*tp) == UNSAVE_EXPR)
/* UNSAVE_EXPRs should not be generated until expansion time. */
abort ();
+#ifndef INLINER_FOR_JAVA
/* For a SCOPE_STMT, we must copy the associated block so that we
can write out debugging information for the inlined variables. */
else if (TREE_CODE (*tp) == SCOPE_STMT && !id->in_target_cleanup_p)
copy_scope_stmt (tp, walk_subtrees, id);
+#else /* INLINER_FOR_JAVA */
+ else if (TREE_CODE (*tp) == LABELED_BLOCK_EXPR)
+ {
+ /* We need a new copy of this labeled block; the EXIT_BLOCK_EXPR
+ will refer to it, so save a copy ready for remapping. We
+ save it in the decl_map, although it isn't a decl. */
+ tree new_block = copy_node (*tp);
+ splay_tree_insert (id->decl_map,
+ (splay_tree_key) *tp,
+ (splay_tree_value) new_block);
+ *tp = new_block;
+ }
+ else if (TREE_CODE (*tp) == EXIT_BLOCK_EXPR)
+ {
+ splay_tree_node n
+ = splay_tree_lookup (id->decl_map,
+ (splay_tree_key) TREE_OPERAND (*tp, 0));
+ /* We _must_ have seen the enclosing LABELED_BLOCK_EXPR. */
+ if (! n)
+ abort ();
+ *tp = copy_node (*tp);
+ TREE_OPERAND (*tp, 0) = (tree) n->value;
+ }
+#endif /* INLINER_FOR_JAVA */
/* Otherwise, just copy the node. Note that copy_tree_r already
knows not to copy VAR_DECLs, etc., so this is safe. */
else
@@ -456,15 +597,25 @@ copy_body (id)
top of the stack in ID from the ARGS (presented as a TREE_LIST). */
static tree
+#ifndef INLINER_FOR_JAVA
initialize_inlined_parameters (id, args, fn)
+#else /* INLINER_FOR_JAVA */
+initialize_inlined_parameters (id, args, fn, block)
+#endif /* INLINER_FOR_JAVA */
inline_data *id;
tree args;
tree fn;
+#ifdef INLINER_FOR_JAVA
+ tree block;
+#endif /* INLINER_FOR_JAVA */
{
tree init_stmts;
tree parms;
tree a;
tree p;
+#ifdef INLINER_FOR_JAVA
+ tree vars = NULL_TREE;
+#endif /* INLINER_FOR_JAVA */
/* Figure out what the parameters are. */
parms = DECL_ARGUMENTS (fn);
@@ -477,10 +628,13 @@ initialize_inlined_parameters (id, args, fn)
for (p = parms, a = args; p;
a = a ? TREE_CHAIN (a) : a, p = TREE_CHAIN (p))
{
+#ifndef INLINER_FOR_JAVA
tree init_stmt;
+ tree cleanup;
+#endif /* not INLINER_FOR_JAVA */
tree var;
tree value;
- tree cleanup;
+ tree var_sub;
/* Find the initializer. */
value = (*lang_hooks.tree_inlining.convert_parm_for_inlining)
@@ -509,6 +663,10 @@ initialize_inlined_parameters (id, args, fn)
if (DECL_P (value))
value = build1 (NOP_EXPR, TREE_TYPE (value), value);
+ /* If this is a constant, make sure it has the right type. */
+ else if (TREE_TYPE (value) != TREE_TYPE (p))
+ value = fold (build1 (NOP_EXPR, TREE_TYPE (p), value));
+
splay_tree_insert (id->decl_map,
(splay_tree_key) p,
(splay_tree_value) value);
@@ -518,17 +676,33 @@ initialize_inlined_parameters (id, args, fn)
/* Make an equivalent VAR_DECL. */
var = copy_decl_for_inlining (p, fn, VARRAY_TREE (id->fns, 0));
+
+ /* See if the frontend wants to pass this by invisible reference. If
+ so, our new VAR_DECL will have REFERENCE_TYPE, and we need to
+ replace uses of the PARM_DECL with dereferences. */
+ if (TREE_TYPE (var) != TREE_TYPE (p)
+ && POINTER_TYPE_P (TREE_TYPE (var))
+ && TREE_TYPE (TREE_TYPE (var)) == TREE_TYPE (p))
+ var_sub = build1 (INDIRECT_REF, TREE_TYPE (p), var);
+ else
+ var_sub = var;
+
/* Register the VAR_DECL as the equivalent for the PARM_DECL;
that way, when the PARM_DECL is encountered, it will be
automatically replaced by the VAR_DECL. */
splay_tree_insert (id->decl_map,
(splay_tree_key) p,
- (splay_tree_value) var);
+ (splay_tree_value) var_sub);
/* Declare this new variable. */
+#ifndef INLINER_FOR_JAVA
init_stmt = build_stmt (DECL_STMT, var);
TREE_CHAIN (init_stmt) = init_stmts;
init_stmts = init_stmt;
+#else /* INLINER_FOR_JAVA */
+ TREE_CHAIN (var) = vars;
+ vars = var;
+#endif /* INLINER_FOR_JAVA */
/* Initialize this VAR_DECL from the equivalent argument. If
the argument is an object, created via a constructor or copy,
@@ -536,6 +710,7 @@ initialize_inlined_parameters (id, args, fn)
representing the argument will be bound to VAR, and the
object will be constructed in VAR. */
if (! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (p)))
+#ifndef INLINER_FOR_JAVA
DECL_INITIAL (var) = value;
else
{
@@ -562,8 +737,8 @@ initialize_inlined_parameters (id, args, fn)
}
/* See if we need to clean up the declaration. */
- cleanup = maybe_build_cleanup (var);
- if (cleanup)
+ cleanup = (*lang_hooks.maybe_build_cleanup) (var);
+ if (cleanup)
{
tree cleanup_stmt;
/* Build the cleanup statement. */
@@ -573,8 +748,23 @@ initialize_inlined_parameters (id, args, fn)
TREE_CHAIN (cleanup_stmt) = init_stmts;
init_stmts = cleanup_stmt;
}
+#else /* INLINER_FOR_JAVA */
+ {
+ tree assignment = build (MODIFY_EXPR, TREE_TYPE (p), var, value);
+ init_stmts = add_stmt_to_compound (init_stmts, TREE_TYPE (p),
+ assignment);
+ }
+ else
+ {
+ /* Java objects don't ever need constructing when being
+ passed as arguments because only call by reference is
+ supported. */
+ abort ();
+ }
+#endif /* INLINER_FOR_JAVA */
}
+#ifndef INLINER_FOR_JAVA
/* Evaluate trailing arguments. */
for (; a; a = TREE_CHAIN (a))
{
@@ -592,6 +782,10 @@ initialize_inlined_parameters (id, args, fn)
/* The initialization statements have been built up in reverse
order. Straighten them out now. */
return nreverse (init_stmts);
+#else /* INLINER_FOR_JAVA */
+ BLOCK_VARS (block) = nreverse (vars);
+ return init_stmts;
+#endif /* INLINER_FOR_JAVA */
}
/* Declare a return variable to replace the RESULT_DECL for the
@@ -599,24 +793,38 @@ initialize_inlined_parameters (id, args, fn)
The USE_STMT is filled in to contain a use of the declaration to
indicate the return value of the function. */
+#ifndef INLINER_FOR_JAVA
static tree
declare_return_variable (id, use_stmt)
struct inline_data *id;
tree *use_stmt;
+#else /* INLINER_FOR_JAVA */
+static tree
+declare_return_variable (id, var)
+ struct inline_data *id;
+ tree *var;
+#endif /* INLINER_FOR_JAVA */
{
tree fn = VARRAY_TOP_TREE (id->fns);
tree result = DECL_RESULT (fn);
+#ifndef INLINER_FOR_JAVA
tree var;
+#endif /* not INLINER_FOR_JAVA */
int need_return_decl = 1;
/* We don't need to do anything for functions that don't return
anything. */
if (!result || VOID_TYPE_P (TREE_TYPE (result)))
{
+#ifndef INLINER_FOR_JAVA
*use_stmt = NULL_TREE;
+#else /* INLINER_FOR_JAVA */
+ *var = NULL_TREE;
+#endif /* INLINER_FOR_JAVA */
return NULL_TREE;
}
+#ifndef INLINER_FOR_JAVA
var = ((*lang_hooks.tree_inlining.copy_res_decl_for_inlining)
(result, fn, VARRAY_TREE (id->fns, 0), id->decl_map,
&need_return_decl, &id->target_exprs));
@@ -636,20 +844,31 @@ declare_return_variable (id, use_stmt)
*use_stmt = build_stmt (EXPR_STMT,
build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)),
var));
-
TREE_ADDRESSABLE (*use_stmt) = 1;
/* Build the declaration statement if FN does not return an
aggregate. */
if (need_return_decl)
return build_stmt (DECL_STMT, var);
+#else /* INLINER_FOR_JAVA */
+ *var = ((*lang_hooks.tree_inlining.copy_res_decl_for_inlining)
+ (result, fn, VARRAY_TREE (id->fns, 0), id->decl_map,
+ &need_return_decl, NULL_TREE));
+
+ splay_tree_insert (id->decl_map,
+ (splay_tree_key) result,
+ (splay_tree_value) *var);
+ DECL_IGNORED_P (*var) = 1;
+ if (need_return_decl)
+ return *var;
+#endif /* INLINER_FOR_JAVA */
/* If FN does return an aggregate, there's no need to declare the
return variable; we're using a variable in our caller's frame. */
else
return NULL_TREE;
}
-/* Returns non-zero if a function can be inlined as a tree. */
+/* Returns nonzero if a function can be inlined as a tree. */
int
tree_inlinable_function_p (fn)
@@ -658,7 +877,53 @@ tree_inlinable_function_p (fn)
return inlinable_function_p (fn, NULL);
}
-/* Returns non-zero if FN is a function that can be inlined into the
+/* If *TP is possibly call to alloca, return nonzero. */
+static tree
+find_alloca_call_1 (tp, walk_subtrees, data)
+ tree *tp;
+ int *walk_subtrees ATTRIBUTE_UNUSED;
+ void *data ATTRIBUTE_UNUSED;
+{
+ if (alloca_call_p (*tp))
+ return *tp;
+ return NULL;
+}
+
+/* Return subexpression representing possible alloca call, if any. */
+static tree
+find_alloca_call (exp)
+ tree exp;
+{
+ return walk_tree_without_duplicates (&exp, find_alloca_call_1, NULL);
+}
+
+static tree
+find_builtin_longjmp_call_1 (tp, walk_subtrees, data)
+ tree *tp;
+ int *walk_subtrees ATTRIBUTE_UNUSED;
+ void *data ATTRIBUTE_UNUSED;
+{
+ tree exp = *tp, decl;
+
+ if (TREE_CODE (exp) == CALL_EXPR
+ && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
+ && (decl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
+ TREE_CODE (decl) == FUNCTION_DECL)
+ && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
+ && DECL_FUNCTION_CODE (decl) == BUILT_IN_LONGJMP)
+ return decl;
+
+ return NULL;
+}
+
+static tree
+find_builtin_longjmp_call (exp)
+ tree exp;
+{
+ return walk_tree_without_duplicates (&exp, find_builtin_longjmp_call_1, NULL);
+}
+
+/* Returns nonzero if FN is a function that can be inlined into the
inlining context ID_. If ID_ is NULL, check whether the function
can be inlined at all. */
@@ -668,6 +933,8 @@ inlinable_function_p (fn, id)
inline_data *id;
{
int inlinable;
+ int currfn_insns;
+ int max_inline_insns_single = MAX_INLINE_INSNS_SINGLE;
/* If we've already decided this function shouldn't be inlined,
there's no need to check again. */
@@ -676,6 +943,15 @@ inlinable_function_p (fn, id)
/* Assume it is not inlinable. */
inlinable = 0;
+
+ /* We may be here either because fn is declared inline or because
+ we use -finline-functions. For the second case, we are more
+ restrictive. */
+ if (DID_INLINE_FUNC (fn))
+ max_inline_insns_single = MAX_INLINE_INSNS_AUTO;
+
+ /* The number of instructions (estimated) of current function. */
+ currfn_insns = DECL_NUM_STMTS (fn) * INSNS_PER_STMT;
/* If we're not inlining things, then nothing is inlinable. */
if (! flag_inline_trees)
@@ -688,11 +964,31 @@ inlinable_function_p (fn, id)
DECL_INLINE set. */
else if (! DECL_INLINE (fn))
;
+#ifdef INLINER_FOR_JAVA
+ /* Synchronized methods can't be inlined. This is a bug. */
+ else if (METHOD_SYNCHRONIZED (fn))
+ ;
+#endif /* INLINER_FOR_JAVA */
/* We can't inline functions that are too big. Only allow a single
- function to eat up half of our budget. Make special allowance
- for extern inline functions, though. */
+ function to be of MAX_INLINE_INSNS_SINGLE size. Make special
+ allowance for extern inline functions, though. */
else if (! (*lang_hooks.tree_inlining.disregard_inline_limits) (fn)
- && DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 2)
+ && currfn_insns > max_inline_insns_single)
+ ;
+ /* We can't inline functions that call __builtin_longjmp at all.
+ The non-local goto machenery really requires the destination
+ be in a different function. If we allow the function calling
+ __builtin_longjmp to be inlined into the function calling
+ __builtin_setjmp, Things will Go Awry. */
+ /* ??? Need front end help to identify "regular" non-local goto. */
+ else if (find_builtin_longjmp_call (DECL_SAVED_TREE (fn)))
+ ;
+ /* Refuse to inline alloca call unless user explicitly forced so as this may
+ change program's memory overhead drastically when the function using alloca
+ is called in loop. In GCC present in SPEC2000 inlining into schedule_block
+ cause it to require 2GB of ram instead of 256MB. */
+ else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL
+ && find_alloca_call (DECL_SAVED_TREE (fn)))
;
/* All is well. We can inline this function. Traditionally, GCC
has refused to inline functions using alloca, or functions whose
@@ -704,19 +1000,35 @@ inlinable_function_p (fn, id)
/* Squirrel away the result so that we don't have to check again. */
DECL_UNINLINABLE (fn) = ! inlinable;
- /* Even if this function is not itself too big to inline, it might
- be that we've done so much inlining already that we don't want to
- risk too much inlining any more and thus halve the acceptable
- size. */
+ /* In case we don't disregard the inlining limits and we basically
+ can inline this function, investigate further. */
if (! (*lang_hooks.tree_inlining.disregard_inline_limits) (fn)
- && ((DECL_NUM_STMTS (fn) + (id ? id->inlined_stmts : 0)) * INSNS_PER_STMT
- > MAX_INLINE_INSNS)
- && DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 4)
- inlinable = 0;
+ && inlinable)
+ {
+ int sum_insns = (id ? id->inlined_stmts : 0) * INSNS_PER_STMT
+ + currfn_insns;
+ /* In the extreme case that we have exceeded the recursive inlining
+ limit by a huge factor (128), we just say no. Should not happen
+ in real life. */
+ if (sum_insns > MAX_INLINE_INSNS * 128)
+ inlinable = 0;
+ /* If we did not hit the extreme limit, we use a linear function
+ with slope -1/MAX_INLINE_SLOPE to exceedingly decrease the
+ allowable size. We always allow a size of MIN_INLINE_INSNS
+ though. */
+ else if ((sum_insns > MAX_INLINE_INSNS)
+ && (currfn_insns > MIN_INLINE_INSNS))
+ {
+ int max_curr = MAX_INLINE_INSNS_SINGLE
+ - (sum_insns - MAX_INLINE_INSNS) / MAX_INLINE_SLOPE;
+ if (currfn_insns > max_curr)
+ inlinable = 0;
+ }
+ }
if (inlinable && (*lang_hooks.tree_inlining.cannot_inline_tree_fn) (&fn))
inlinable = 0;
-
+
/* If we don't have the function body available, we can't inline
it. */
if (! DECL_SAVED_TREE (fn))
@@ -763,10 +1075,14 @@ expand_call_inline (tp, walk_subtrees, data)
tree t;
tree expr;
tree stmt;
+#ifndef INLINER_FOR_JAVA
tree chain;
- tree fn;
tree scope_stmt;
tree use_stmt;
+#else /* INLINER_FOR_JAVA */
+ tree retvar;
+#endif /* INLINER_FOR_JAVA */
+ tree fn;
tree arg_inits;
tree *inlined_body;
splay_tree st;
@@ -779,6 +1095,7 @@ expand_call_inline (tp, walk_subtrees, data)
inside the body of a TARGET_EXPR. */
if (TREE_CODE (*tp) == TARGET_EXPR)
{
+#ifndef INLINER_FOR_JAVA
int i, len = first_rtl_op (TARGET_EXPR);
/* We're walking our own subtrees. */
@@ -804,6 +1121,22 @@ expand_call_inline (tp, walk_subtrees, data)
VARRAY_POP (id->target_exprs);
return NULL_TREE;
+#else /* INLINER_FOR_JAVA */
+ abort ();
+#endif /* INLINER_FOR_JAVA */
+ }
+ else if (TREE_CODE (t) == EXPR_WITH_FILE_LOCATION)
+ {
+ /* We're walking the subtree directly. */
+ *walk_subtrees = 0;
+ /* Update the source position. */
+ push_srcloc (EXPR_WFL_FILENAME (t), EXPR_WFL_LINENO (t));
+ walk_tree (&EXPR_WFL_NODE (t), expand_call_inline, data,
+ id->tree_pruner);
+ /* Restore the original source position. */
+ pop_srcloc ();
+
+ return NULL_TREE;
}
if (TYPE_P (t))
@@ -837,7 +1170,15 @@ expand_call_inline (tp, walk_subtrees, data)
/* Don't try to inline functions that are not well-suited to
inlining. */
if (!inlinable_function_p (fn, id))
- return NULL_TREE;
+ {
+ if (warn_inline && DECL_INLINE (fn) && !DID_INLINE_FUNC (fn)
+ && !DECL_IN_SYSTEM_HEADER (fn))
+ {
+ warning_with_decl (fn, "inlining failed in call to `%s'");
+ warning ("called from here");
+ }
+ return NULL_TREE;
+ }
if (! (*lang_hooks.tree_inlining.start_inlining) (fn))
return NULL_TREE;
@@ -847,8 +1188,9 @@ expand_call_inline (tp, walk_subtrees, data)
line numbers corresponding to the function we are calling. We
wrap the whole inlined body in an EXPR_WITH_FILE_AND_LINE as well
because individual statements don't record the filename. */
- push_srcloc (fn->decl.filename, fn->decl.linenum);
+ push_srcloc (DECL_SOURCE_FILE (fn), DECL_SOURCE_LINE (fn));
+#ifndef INLINER_FOR_JAVA
/* Build a statement-expression containing code to initialize the
arguments, the actual inline expansion of the body, and a label
for the return statements within the function to jump to. The
@@ -858,6 +1200,15 @@ expand_call_inline (tp, walk_subtrees, data)
/* There is no scope associated with the statement-expression. */
STMT_EXPR_NO_SCOPE (expr) = 1;
stmt = STMT_EXPR_STMT (expr);
+#else /* INLINER_FOR_JAVA */
+ /* Build a block containing code to initialize the arguments, the
+ actual inline expansion of the body, and a label for the return
+ statements within the function to jump to. The type of the
+ statement expression is the return type of the function call. */
+ stmt = NULL;
+ expr = build (BLOCK, TREE_TYPE (TREE_TYPE (fn)), stmt);
+#endif /* INLINER_FOR_JAVA */
+
/* Local declarations will be replaced by their equivalents in this
map. */
st = id->decl_map;
@@ -865,6 +1216,7 @@ expand_call_inline (tp, walk_subtrees, data)
NULL, NULL);
/* Initialize the parameters. */
+#ifndef INLINER_FOR_JAVA
arg_inits = initialize_inlined_parameters (id, TREE_OPERAND (t, 1), fn);
/* Expand any inlined calls in the initializers. Do this before we
push FN on the stack of functions we are inlining; we want to
@@ -873,6 +1225,22 @@ expand_call_inline (tp, walk_subtrees, data)
expand_calls_inline (&arg_inits, id);
/* And add them to the tree. */
COMPOUND_BODY (stmt) = chainon (COMPOUND_BODY (stmt), arg_inits);
+#else /* INLINER_FOR_JAVA */
+ arg_inits = initialize_inlined_parameters (id, TREE_OPERAND (t, 1), fn, expr);
+ if (arg_inits)
+ {
+ /* Expand any inlined calls in the initializers. Do this before we
+ push FN on the stack of functions we are inlining; we want to
+ inline calls to FN that appear in the initializers for the
+ parameters. */
+ expand_calls_inline (&arg_inits, id);
+
+ /* And add them to the tree. */
+ BLOCK_EXPR_BODY (expr) = add_stmt_to_compound (BLOCK_EXPR_BODY (expr),
+ TREE_TYPE (arg_inits),
+ arg_inits);
+ }
+#endif /* INLINER_FOR_JAVA */
/* Record the function we are about to inline so that we can avoid
recursing into it. */
@@ -900,6 +1268,7 @@ expand_call_inline (tp, walk_subtrees, data)
|| TREE_CODE (DECL_INITIAL (fn)) != BLOCK)
abort ();
+#ifndef INLINER_FOR_JAVA
/* Create a block to put the parameters in. We have to do this
after the parameters have been remapped because remapping
parameters is different from remapping ordinary variables. */
@@ -919,31 +1288,81 @@ expand_call_inline (tp, walk_subtrees, data)
COMPOUND_BODY (stmt)
= chainon (COMPOUND_BODY (stmt),
declare_return_variable (id, &use_stmt));
+#else /* INLINER_FOR_JAVA */
+ {
+ /* Declare the return variable for the function. */
+ tree decl = declare_return_variable (id, &retvar);
+ if (retvar)
+ {
+ tree *next = &BLOCK_VARS (expr);
+ while (*next)
+ next = &TREE_CHAIN (*next);
+ *next = decl;
+ }
+ }
+#endif /* INLINER_FOR_JAVA */
/* After we've initialized the parameters, we insert the body of the
function itself. */
+#ifndef INLINER_FOR_JAVA
inlined_body = &COMPOUND_BODY (stmt);
while (*inlined_body)
inlined_body = &TREE_CHAIN (*inlined_body);
*inlined_body = copy_body (id);
+#else /* INLINER_FOR_JAVA */
+ {
+ tree new_body;
+ java_inlining_map_static_initializers (fn, id->decl_map);
+ new_body = copy_body (id);
+ TREE_TYPE (new_body) = TREE_TYPE (TREE_TYPE (fn));
+ BLOCK_EXPR_BODY (expr)
+ = add_stmt_to_compound (BLOCK_EXPR_BODY (expr),
+ TREE_TYPE (new_body), new_body);
+ inlined_body = &BLOCK_EXPR_BODY (expr);
+ }
+#endif /* INLINER_FOR_JAVA */
/* After the body of the function comes the RET_LABEL. This must come
before we evaluate the returned value below, because that evalulation
may cause RTL to be generated. */
+#ifndef INLINER_FOR_JAVA
COMPOUND_BODY (stmt)
= chainon (COMPOUND_BODY (stmt),
build_stmt (LABEL_STMT, id->ret_label));
+#else /* INLINER_FOR_JAVA */
+ {
+ tree label = build1 (LABEL_EXPR, void_type_node, id->ret_label);
+ BLOCK_EXPR_BODY (expr)
+ = add_stmt_to_compound (BLOCK_EXPR_BODY (expr), void_type_node, label);
+ TREE_SIDE_EFFECTS (label) = TREE_SIDE_EFFECTS (t);
+ }
+#endif /* INLINER_FOR_JAVA */
/* Finally, mention the returned value so that the value of the
statement-expression is the returned value of the function. */
+#ifndef INLINER_FOR_JAVA
COMPOUND_BODY (stmt) = chainon (COMPOUND_BODY (stmt), use_stmt);
-
+
/* Close the block for the parameters. */
scope_stmt = build_stmt (SCOPE_STMT, DECL_INITIAL (fn));
SCOPE_NO_CLEANUPS_P (scope_stmt) = 1;
remap_block (scope_stmt, NULL_TREE, id);
COMPOUND_BODY (stmt)
= chainon (COMPOUND_BODY (stmt), scope_stmt);
+#else /* INLINER_FOR_JAVA */
+ if (retvar)
+ {
+ /* Mention the retvar. If the return type of the function was
+ promoted, convert it back to the expected type. */
+ if (TREE_TYPE (TREE_TYPE (fn)) != TREE_TYPE (retvar))
+ retvar = build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)), retvar);
+ BLOCK_EXPR_BODY (expr)
+ = add_stmt_to_compound (BLOCK_EXPR_BODY (expr),
+ TREE_TYPE (retvar), retvar);
+ }
+
+ java_inlining_merge_static_initializers (fn, id->decl_map);
+#endif /* INLINER_FOR_JAVA */
/* Clean up. */
splay_tree_delete (id->decl_map);
@@ -955,11 +1374,19 @@ expand_call_inline (tp, walk_subtrees, data)
/* Replace the call by the inlined body. Wrap it in an
EXPR_WITH_FILE_LOCATION so that we'll get debugging line notes
pointing to the right place. */
+#ifndef INLINER_FOR_JAVA
chain = TREE_CHAIN (*tp);
*tp = build_expr_wfl (expr, DECL_SOURCE_FILE (fn), DECL_SOURCE_LINE (fn),
/*col=*/0);
+#else /* INLINER_FOR_JAVA */
+ *tp = build_expr_wfl (expr, DECL_SOURCE_FILE (fn),
+ DECL_SOURCE_LINE_FIRST(fn),
+ /*col=*/0);
+#endif /* INLINER_FOR_JAVA */
EXPR_WFL_EMIT_LINE_NOTE (*tp) = 1;
+#ifndef INLINER_FOR_JAVA
TREE_CHAIN (*tp) = chain;
+#endif /* not INLINER_FOR_JAVA */
pop_srcloc ();
/* If the value of the new expression is ignored, that's OK. We
@@ -969,7 +1396,8 @@ expand_call_inline (tp, walk_subtrees, data)
/* Our function now has more statements than it did before. */
DECL_NUM_STMTS (VARRAY_TREE (id->fns, 0)) += DECL_NUM_STMTS (fn);
- id->inlined_stmts += DECL_NUM_STMTS (fn);
+ /* For accounting, subtract one for the saved call/ret. */
+ id->inlined_stmts += DECL_NUM_STMTS (fn) - 1;
/* Recurse into the body of the just inlined function. */
expand_calls_inline (inlined_body, id);
@@ -988,7 +1416,6 @@ expand_call_inline (tp, walk_subtrees, data)
/* Keep iterating. */
return NULL_TREE;
}
-
/* Walk over the entire tree *TP, replacing CALL_EXPRs with inline
expansions as appropriate. */
@@ -1014,7 +1441,7 @@ optimize_inline_calls (fn)
{
inline_data id;
tree prev_fn;
-
+
/* Clear out ID. */
memset (&id, 0, sizeof (id));
@@ -1031,7 +1458,7 @@ optimize_inline_calls (fn)
prev_fn = ((*lang_hooks.tree_inlining.add_pending_fn_decls)
(&id.fns, prev_fn));
-
+
/* Create the stack of TARGET_EXPRs. */
VARRAY_TREE_INIT (id.target_exprs, 32, "target_exprs");
@@ -1050,17 +1477,15 @@ optimize_inline_calls (fn)
/* Clean up. */
htab_delete (id.tree_pruner);
- VARRAY_FREE (id.fns);
- VARRAY_FREE (id.target_exprs);
if (DECL_LANG_SPECIFIC (fn))
{
tree ifn = make_tree_vec (VARRAY_ACTIVE_SIZE (id.inlined_fns));
-
- memcpy (&TREE_VEC_ELT (ifn, 0), &VARRAY_TREE (id.inlined_fns, 0),
- VARRAY_ACTIVE_SIZE (id.inlined_fns) * sizeof (tree));
+
+ if (VARRAY_ACTIVE_SIZE (id.inlined_fns))
+ memcpy (&TREE_VEC_ELT (ifn, 0), &VARRAY_TREE (id.inlined_fns, 0),
+ VARRAY_ACTIVE_SIZE (id.inlined_fns) * sizeof (tree));
DECL_INLINED_FNS (fn) = ifn;
}
- VARRAY_FREE (id.inlined_fns);
}
/* FN is a function that has a complete body, and CLONE is a function
@@ -1090,9 +1515,6 @@ clone_body (clone, fn, arg_map)
/* Actually copy the body. */
TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id);
-
- /* Clean up. */
- VARRAY_FREE (id.fns);
}
/* Apply FUNC to all the sub-trees of TP in a pre-order traversal.
@@ -1102,7 +1524,7 @@ clone_body (clone, fn, arg_map)
to record the nodes visited, and to avoid visiting a node more than
once. */
-tree
+tree
walk_tree (tp, func, data, htab_)
tree *tp;
walk_tree_fn func;
@@ -1113,7 +1535,7 @@ walk_tree (tp, func, data, htab_)
enum tree_code code;
int walk_subtrees;
tree result;
-
+
#define WALK_SUBTREE(NODE) \
do \
{ \
@@ -1139,13 +1561,12 @@ walk_tree (tp, func, data, htab_)
if (htab)
{
void **slot;
-
+
/* Don't walk the same tree twice, if the user has requested
that we avoid doing so. */
- if (htab_find (htab, *tp))
- return NULL_TREE;
- /* If we haven't already seen this node, add it to the table. */
slot = htab_find_slot (htab, *tp, INSERT);
+ if (*slot)
+ return NULL_TREE;
*slot = *tp;
}
@@ -1159,6 +1580,7 @@ walk_tree (tp, func, data, htab_)
code = TREE_CODE (*tp);
+#ifndef INLINER_FOR_JAVA
/* Even if we didn't, FUNC may have decided that there was nothing
interesting below this point in the tree. */
if (!walk_subtrees)
@@ -1175,13 +1597,22 @@ walk_tree (tp, func, data, htab_)
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
|| TREE_CODE_CLASS (code) == 'r'
|| TREE_CODE_CLASS (code) == 's')
+#else /* INLINER_FOR_JAVA */
+ if (code != EXIT_BLOCK_EXPR
+ && code != SAVE_EXPR
+ && (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
+ || TREE_CODE_CLASS (code) == 'r'
+ || TREE_CODE_CLASS (code) == 's'))
+#endif /* INLINER_FOR_JAVA */
{
int i, len;
+#ifndef INLINER_FOR_JAVA
/* Set lineno here so we get the right instantiation context
if we call instantiate_decl from inlinable_function_p. */
if (statement_code_p (code) && !STMT_LINENO_FOR_FN_P (*tp))
lineno = STMT_LINENO (*tp);
+#endif /* not INLINER_FOR_JAVA */
/* Walk over all the sub-trees of this operand. */
len = first_rtl_op (code);
@@ -1195,12 +1626,13 @@ walk_tree (tp, func, data, htab_)
for (i = 0; i < len; ++i)
WALK_SUBTREE (TREE_OPERAND (*tp, i));
+#ifndef INLINER_FOR_JAVA
/* For statements, we also walk the chain so that we cover the
entire statement tree. */
if (statement_code_p (code))
{
- if (code == DECL_STMT
- && DECL_STMT_DECL (*tp)
+ if (code == DECL_STMT
+ && DECL_STMT_DECL (*tp)
&& DECL_P (DECL_STMT_DECL (*tp)))
{
/* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk
@@ -1217,6 +1649,7 @@ walk_tree (tp, func, data, htab_)
WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
}
+#endif /* not INLINER_FOR_JAVA */
/* We didn't find what we were looking for. */
return NULL_TREE;
}
@@ -1255,6 +1688,7 @@ walk_tree (tp, func, data, htab_)
case ENUMERAL_TYPE:
case BLOCK:
case RECORD_TYPE:
+ case CHAR_TYPE:
/* None of thse have subtrees other than those already walked
above. */
break;
@@ -1318,6 +1752,14 @@ walk_tree (tp, func, data, htab_)
WALK_SUBTREE (TREE_TYPE (*tp));
WALK_SUBTREE_TAIL (TYPE_OFFSET_BASETYPE (*tp));
+#ifdef INLINER_FOR_JAVA
+ case EXIT_BLOCK_EXPR:
+ WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 1));
+
+ case SAVE_EXPR:
+ WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));
+#endif /* INLINER_FOR_JAVA */
+
default:
abort ();
}
@@ -1329,10 +1771,10 @@ walk_tree (tp, func, data, htab_)
#undef WALK_SUBTREE_TAIL
}
-/* Like walk_tree, but does not walk duplicate nodes more than
+/* Like walk_tree, but does not walk duplicate nodes more than
once. */
-tree
+tree
walk_tree_without_duplicates (tp, func, data)
tree *tp;
walk_tree_fn func;
@@ -1376,6 +1818,7 @@ copy_tree_r (tp, walk_subtrees, data)
/* Now, restore the chain, if appropriate. That will cause
walk_tree to walk into the chain as well. */
if (code == PARM_DECL || code == TREE_LIST
+#ifndef INLINER_FOR_JAVA
|| (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp)
|| statement_code_p (code))
TREE_CHAIN (*tp) = chain;
@@ -1384,6 +1827,10 @@ copy_tree_r (tp, walk_subtrees, data)
have to nullify all scope-statements. */
if (TREE_CODE (*tp) == SCOPE_STMT)
SCOPE_STMT_BLOCK (*tp) = NULL_TREE;
+#else /* INLINER_FOR_JAVA */
+ || (*lang_hooks.tree_inlining.tree_chain_matters_p) (*tp))
+ TREE_CHAIN (*tp) = chain;
+#endif /* INLINER_FOR_JAVA */
}
else if (TREE_CODE_CLASS (code) == 't' && !variably_modified_type_p (*tp))
/* Types only need to be copied if they are variably modified. */
@@ -1409,7 +1856,7 @@ remap_save_expr (tp, st_, fn, walk_subtrees)
/* See if we already encountered this SAVE_EXPR. */
n = splay_tree_lookup (st, (splay_tree_key) *tp);
-
+
/* If we didn't already remap this SAVE_EXPR, do so now. */
if (!n)
{
@@ -1436,3 +1883,21 @@ remap_save_expr (tp, st_, fn, walk_subtrees)
/* Replace this SAVE_EXPR with the copy. */
*tp = (tree) n->value;
}
+
+#ifdef INLINER_FOR_JAVA
+/* Add STMT to EXISTING if possible, otherwise create a new
+ COMPOUND_EXPR and add STMT to it. */
+
+static tree
+add_stmt_to_compound (existing, type, stmt)
+ tree existing, type, stmt;
+{
+ if (!stmt)
+ return existing;
+ else if (existing)
+ return build (COMPOUND_EXPR, type, existing, stmt);
+ else
+ return stmt;
+}
+
+#endif /* INLINER_FOR_JAVA */
diff --git a/contrib/gcc/tree-inline.h b/contrib/gcc/tree-inline.h
index e8bc90a..9c11436 100644
--- a/contrib/gcc/tree-inline.h
+++ b/contrib/gcc/tree-inline.h
@@ -33,8 +33,8 @@ void clone_body PARAMS ((tree, tree, void*));
void remap_save_expr PARAMS ((tree*, void*, tree, int*));
/* 0 if we should not perform inlining.
- 1 if we should expand functions calls inline at the tree level.
- 2 if we should consider *all* functions to be inline
+ 1 if we should expand functions calls inline at the tree level.
+ 2 if we should consider *all* functions to be inline
candidates. */
extern int flag_inline_trees;
diff --git a/contrib/gcc/tree.c b/contrib/gcc/tree.c
index 6c0c7dc..fbb47e9 100644
--- a/contrib/gcc/tree.c
+++ b/contrib/gcc/tree.c
@@ -27,16 +27,13 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
nodes of that code.
It is intended to be language-independent, but occasionally
- calls language-dependent routines defined (for C) in typecheck.c.
-
- The low-level allocation routines oballoc and permalloc
- are used also for allocating many other kinds of objects
- by all passes of the compiler. */
+ calls language-dependent routines defined (for C) in typecheck.c. */
#include "config.h"
#include "system.h"
#include "flags.h"
#include "tree.h"
+#include "real.h"
#include "tm_p.h"
#include "function.h"
#include "obstack.h"
@@ -47,48 +44,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "target.h"
#include "langhooks.h"
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
/* obstack.[ch] explicitly declined to prototype this. */
extern int _obstack_allocated_p PARAMS ((struct obstack *h, PTR obj));
-static void unsave_expr_now_r PARAMS ((tree));
-
-/* Objects allocated on this obstack last forever. */
-
-struct obstack permanent_obstack;
-
-/* Table indexed by tree code giving a string containing a character
- classifying the tree code. Possibilities are
- t, d, s, c, r, <, 1, 2 and e. See tree.def for details. */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
-
-char tree_code_type[MAX_TREE_CODES] = {
-#include "tree.def"
-};
-#undef DEFTREECODE
-
-/* Table indexed by tree code giving number of expression
- operands beyond the fixed part of the node structure.
- Not used for types or decls. */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
-
-int tree_code_length[MAX_TREE_CODES] = {
-#include "tree.def"
-};
-#undef DEFTREECODE
-
-/* Names of tree components.
- Used for printing out the tree and error messages. */
-#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
-
-const char *tree_code_name[MAX_TREE_CODES] = {
-#include "tree.def"
-};
-#undef DEFTREECODE
-
+#ifdef GATHER_STATISTICS
/* Statistics-gathering stuff. */
typedef enum
{
@@ -128,6 +87,7 @@ static const char * const tree_node_kind_names[] = {
"lang_decl kinds",
"lang_type kinds"
};
+#endif /* GATHER_STATISTICS */
/* Unique id for next decl created. */
static int next_decl_uid;
@@ -137,7 +97,7 @@ static int next_type_uid = 1;
/* Since we cannot rehash a type after it is in the table, we have to
keep the hash code. */
-struct type_hash
+struct type_hash GTY(())
{
unsigned long hash;
tree type;
@@ -153,111 +113,42 @@ struct type_hash
same table, they are completely independent, and the hash code is
computed differently for each of these. */
-htab_t type_hash_table;
+static GTY ((if_marked ("type_hash_marked_p"), param_is (struct type_hash)))
+ htab_t type_hash_table;
-static void build_real_from_int_cst_1 PARAMS ((PTR));
static void set_type_quals PARAMS ((tree, int));
static void append_random_chars PARAMS ((char *));
-static int type_hash_eq PARAMS ((const void*, const void*));
-static unsigned int type_hash_hash PARAMS ((const void*));
+static int type_hash_eq PARAMS ((const void *, const void *));
+static hashval_t type_hash_hash PARAMS ((const void *));
static void print_type_hash_statistics PARAMS((void));
static void finish_vector_type PARAMS((tree));
static tree make_vector PARAMS ((enum machine_mode, tree, int));
static int type_hash_marked_p PARAMS ((const void *));
-static void type_hash_mark PARAMS ((const void *));
-static int mark_tree_hashtable_entry PARAMS((void **, void *));
-
-/* If non-null, these are language-specific helper functions for
- unsave_expr_now. If present, LANG_UNSAVE is called before its
- argument (an UNSAVE_EXPR) is to be unsaved, and all other
- processing in unsave_expr_now is aborted. LANG_UNSAVE_EXPR_NOW is
- called from unsave_expr_1 for language-specific tree codes. */
-void (*lang_unsave) PARAMS ((tree *));
-void (*lang_unsave_expr_now) PARAMS ((tree));
-
-/* If non-null, these are language-specific helper functions for
- unsafe_for_reeval. Return negative to not handle some tree. */
-int (*lang_unsafe_for_reeval) PARAMS ((tree));
-
-/* Set the DECL_ASSEMBLER_NAME for a node. If it is the sort of thing
- that the assembler should talk about, set DECL_ASSEMBLER_NAME to an
- appropriate IDENTIFIER_NODE. Otherwise, set it to the
- ERROR_MARK_NODE to ensure that the assembler does not talk about
- it. */
-void (*lang_set_decl_assembler_name) PARAMS ((tree));
-
+
tree global_trees[TI_MAX];
tree integer_types[itk_none];
-/* Set the DECL_ASSEMBLER_NAME for DECL. */
-void
-set_decl_assembler_name (decl)
- tree decl;
-{
- /* The language-independent code should never use the
- DECL_ASSEMBLER_NAME for lots of DECLs. Only FUNCTION_DECLs and
- VAR_DECLs for variables with static storage duration need a real
- DECL_ASSEMBLER_NAME. */
- if (TREE_CODE (decl) == FUNCTION_DECL
- || (TREE_CODE (decl) == VAR_DECL
- && (TREE_STATIC (decl)
- || DECL_EXTERNAL (decl)
- || TREE_PUBLIC (decl))))
- /* By default, assume the name to use in assembly code is the
- same as that used in the source language. (That's correct
- for C, and GCC used to set DECL_ASSEMBLER_NAME to the same
- value as DECL_NAME in build_decl, so this choice provides
- backwards compatibility with existing front-ends. */
- SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
- else
- /* Nobody should ever be asking for the DECL_ASSEMBLER_NAME of
- these DECLs -- unless they're in language-dependent code, in
- which case lang_set_decl_assembler_name should handle things. */
- abort ();
-}
-
-/* Init the principal obstacks. */
+/* Init tree.c. */
void
-init_obstacks ()
+init_ttree ()
{
- gcc_obstack_init (&permanent_obstack);
-
/* Initialize the hash table of types. */
type_hash_table = htab_create (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
type_hash_eq, 0);
- ggc_add_deletable_htab (type_hash_table, type_hash_marked_p,
- type_hash_mark);
- ggc_add_tree_root (global_trees, TI_MAX);
- ggc_add_tree_root (integer_types, itk_none);
-
- /* Set lang_set_decl_set_assembler_name to a default value. */
- lang_set_decl_assembler_name = set_decl_assembler_name;
}
-/* Allocate SIZE bytes in the permanent obstack
- and return a pointer to them. */
-
-char *
-permalloc (size)
- int size;
-{
- return (char *) obstack_alloc (&permanent_obstack, size);
-}
-
-/* Allocate NELEM items of SIZE bytes in the permanent obstack
- and return a pointer to them. The storage is cleared before
- returning the value. */
-
-char *
-perm_calloc (nelem, size)
- int nelem;
- long size;
+/* The name of the object as the assembler will see it (but before any
+ translations made by ASM_OUTPUT_LABELREF). Often this is the same
+ as DECL_NAME. It is an IDENTIFIER_NODE. */
+tree
+decl_assembler_name (decl)
+ tree decl;
{
- char *rval = (char *) obstack_alloc (&permanent_obstack, nelem * size);
- memset (rval, 0, nelem * size);
- return rval;
+ if (!DECL_ASSEMBLER_NAME_SET_P (decl))
+ (*lang_hooks.set_decl_assembler_name) (decl);
+ return DECL_CHECK (decl)->decl.assembler_name;
}
/* Compute the number of bytes occupied by 'node'. This routine only
@@ -308,7 +199,7 @@ tree_size (node)
length = (sizeof (struct tree_common)
+ TREE_CODE_LENGTH (code) * sizeof (char *));
if (code == TREE_VEC)
- length += TREE_VEC_LENGTH (node) * sizeof (char *) - sizeof (char *);
+ length += TREE_VEC_LENGTH (node) * sizeof (char *) - sizeof (char *);
return length;
}
@@ -334,12 +225,12 @@ make_node (code)
tree_node_kind kind;
#endif
struct tree_common ttmp;
-
+
/* We can't allocate a TREE_VEC without knowing how many elements
it will have. */
if (code == TREE_VEC)
abort ();
-
+
TREE_SET_CODE ((tree)&ttmp, code);
length = tree_size ((tree)&ttmp);
@@ -463,21 +354,6 @@ make_node (code)
return t;
}
-
-/* A front-end can reset this to an appropriate function if types need
- special handling. */
-
-tree (*make_lang_type_fn) PARAMS ((enum tree_code)) = make_node;
-
-/* Return a new type (with the indicated CODE), doing whatever
- language-specific processing is required. */
-
-tree
-make_lang_type (code)
- enum tree_code code;
-{
- return (*make_lang_type_fn) (code);
-}
/* Return a new node with the same contents as NODE except that its
TREE_CHAIN is zero and it has a fresh uid. */
@@ -580,7 +456,7 @@ build_vector (type, vals)
over1 |= TREE_OVERFLOW (value);
over2 |= TREE_CONSTANT_OVERFLOW (value);
}
-
+
TREE_OVERFLOW (v) = over1;
TREE_CONSTANT_OVERFLOW (v) = over2;
@@ -595,17 +471,18 @@ build_real (type, d)
REAL_VALUE_TYPE d;
{
tree v;
+ REAL_VALUE_TYPE *dp;
int overflow = 0;
- /* Check for valid float value for this type on this target machine;
- if not, can print error message and store a valid value in D. */
-#ifdef CHECK_FLOAT_VALUE
- CHECK_FLOAT_VALUE (TYPE_MODE (type), d, overflow);
-#endif
+ /* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
+ Consider doing it via real_convert now. */
v = make_node (REAL_CST);
+ dp = ggc_alloc (sizeof (REAL_VALUE_TYPE));
+ memcpy (dp, &d, sizeof (REAL_VALUE_TYPE));
+
TREE_TYPE (v) = type;
- TREE_REAL_CST (v) = d;
+ TREE_REAL_CST_PTR (v) = dp;
TREE_OVERFLOW (v) = TREE_CONSTANT_OVERFLOW (v) = overflow;
return v;
}
@@ -613,15 +490,12 @@ build_real (type, d)
/* Return a new REAL_CST node whose type is TYPE
and whose value is the integer value of the INTEGER_CST node I. */
-#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
-
REAL_VALUE_TYPE
real_value_from_int_cst (type, i)
tree type ATTRIBUTE_UNUSED, i;
{
REAL_VALUE_TYPE d;
-#ifdef REAL_ARITHMETIC
/* Clear all bits of the real value type so that we can later do
bitwise comparisons to see if two values are the same. */
memset ((char *) &d, 0, sizeof d);
@@ -632,67 +506,11 @@ real_value_from_int_cst (type, i)
else
REAL_VALUE_FROM_UNSIGNED_INT (d, TREE_INT_CST_LOW (i),
TREE_INT_CST_HIGH (i), TYPE_MODE (type));
-#else /* not REAL_ARITHMETIC */
- /* Some 386 compilers mishandle unsigned int to float conversions,
- so introduce a temporary variable E to avoid those bugs. */
- if (TREE_INT_CST_HIGH (i) < 0 && ! TREE_UNSIGNED (TREE_TYPE (i)))
- {
- REAL_VALUE_TYPE e;
-
- d = (double) (~TREE_INT_CST_HIGH (i));
- e = ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))
- * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)));
- d *= e;
- e = (double) (~TREE_INT_CST_LOW (i));
- d += e;
- d = (- d - 1.0);
- }
- else
- {
- REAL_VALUE_TYPE e;
-
- d = (double) (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (i);
- e = ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))
- * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)));
- d *= e;
- e = (double) TREE_INT_CST_LOW (i);
- d += e;
- }
-#endif /* not REAL_ARITHMETIC */
return d;
}
-/* Args to pass to and from build_real_from_int_cst_1. */
-
-struct brfic_args
-{
- tree type; /* Input: type to conver to. */
- tree i; /* Input: operand to convert. */
- REAL_VALUE_TYPE d; /* Output: floating point value. */
-};
-
-/* Convert an integer to a floating point value while protected by a floating
- point exception handler. */
-
-static void
-build_real_from_int_cst_1 (data)
- PTR data;
-{
- struct brfic_args *args = (struct brfic_args *) data;
-
-#ifdef REAL_ARITHMETIC
- args->d = real_value_from_int_cst (args->type, args->i);
-#else
- args->d
- = REAL_VALUE_TRUNCATE (TYPE_MODE (args->type),
- real_value_from_int_cst (args->type, args->i));
-#endif
-}
-
/* Given a tree representing an integer constant I, return a tree
- representing the same value as a floating-point constant of type TYPE.
- We cannot perform this operation if there is no way of doing arithmetic
- on floating-point values. */
+ representing the same value as a floating-point constant of type TYPE. */
tree
build_real_from_int_cst (type, i)
@@ -701,39 +519,14 @@ build_real_from_int_cst (type, i)
{
tree v;
int overflow = TREE_OVERFLOW (i);
- REAL_VALUE_TYPE d;
- struct brfic_args args;
-
- v = make_node (REAL_CST);
- TREE_TYPE (v) = type;
-
- /* Setup input for build_real_from_int_cst_1() */
- args.type = type;
- args.i = i;
-
- if (do_float_handler (build_real_from_int_cst_1, (PTR) &args))
- /* Receive output from build_real_from_int_cst_1() */
- d = args.d;
- else
- {
- /* We got an exception from build_real_from_int_cst_1() */
- d = dconst0;
- overflow = 1;
- }
-
- /* Check for valid float value for this type on this target machine. */
-#ifdef CHECK_FLOAT_VALUE
- CHECK_FLOAT_VALUE (TYPE_MODE (type), d, overflow);
-#endif
+ v = build_real (type, real_value_from_int_cst (type, i));
- TREE_REAL_CST (v) = d;
- TREE_OVERFLOW (v) = TREE_CONSTANT_OVERFLOW (v) = overflow;
+ TREE_OVERFLOW (v) |= overflow;
+ TREE_CONSTANT_OVERFLOW (v) |= overflow;
return v;
}
-#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
-
/* Return a newly constructed STRING_CST node whose value is
the LEN characters at STR.
The TREE_TYPE is not initialized. */
@@ -779,11 +572,11 @@ make_tree_vec (len)
int len;
{
tree t;
- int length = (len-1) * sizeof (tree) + sizeof (struct tree_vec);
+ int length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
#ifdef GATHER_STATISTICS
- tree_node_counts[(int)vec_kind]++;
- tree_node_sizes[(int)vec_kind] += length;
+ tree_node_counts[(int) vec_kind]++;
+ tree_node_sizes[(int) vec_kind] += length;
#endif
t = ggc_alloc_tree (length);
@@ -1057,6 +850,22 @@ real_twop (expr)
&& real_zerop (TREE_IMAGPART (expr))));
}
+/* Return 1 if EXPR is the real constant minus one. */
+
+int
+real_minus_onep (expr)
+ tree expr;
+{
+ STRIP_NOPS (expr);
+
+ return ((TREE_CODE (expr) == REAL_CST
+ && ! TREE_CONSTANT_OVERFLOW (expr)
+ && REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1))
+ || (TREE_CODE (expr) == COMPLEX_CST
+ && real_minus_onep (TREE_REALPART (expr))
+ && real_zerop (TREE_IMAGPART (expr))));
+}
+
/* Nonzero if EXP is a constant or a cast of a constant. */
int
@@ -1224,8 +1033,8 @@ chainon (op1, op2)
TREE_CHAIN (t1) = op2;
#ifdef ENABLE_TREE_CHECKING
for (t2 = op2; t2; t2 = TREE_CHAIN (t2))
- if (t2 == t1)
- abort (); /* Circularity created. */
+ if (t2 == t1)
+ abort (); /* Circularity created. */
#endif
return op1;
}
@@ -1348,7 +1157,7 @@ size_in_bytes (type)
if (t == 0)
{
- incomplete_type_error (NULL_TREE, type);
+ (*lang_hooks.types.incomplete_type_error) (NULL_TREE, type);
return size_zero_node;
}
@@ -1510,12 +1319,13 @@ staticp (arg)
case FUNCTION_DECL:
/* Nested functions aren't static, since taking their address
involves a trampoline. */
- return (decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg))
- && ! DECL_NON_ADDR_CONST_P (arg);
+ return ((decl_function_context (arg) == 0 || DECL_NO_STATIC_CHAIN (arg))
+ && ! DECL_NON_ADDR_CONST_P (arg));
case VAR_DECL:
- return (TREE_STATIC (arg) || DECL_EXTERNAL (arg))
- && ! DECL_NON_ADDR_CONST_P (arg);
+ return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
+ && ! DECL_THREAD_LOCAL (arg)
+ && ! DECL_NON_ADDR_CONST_P (arg));
case CONSTRUCTOR:
return TREE_STATIC (arg);
@@ -1675,6 +1485,44 @@ first_rtl_op (code)
}
}
+/* Return which tree structure is used by T. */
+
+enum tree_node_structure_enum
+tree_node_structure (t)
+ tree t;
+{
+ enum tree_code code = TREE_CODE (t);
+
+ switch (TREE_CODE_CLASS (code))
+ {
+ case 'd': return TS_DECL;
+ case 't': return TS_TYPE;
+ case 'b': return TS_BLOCK;
+ case 'r': case '<': case '1': case '2': case 'e': case 's':
+ return TS_EXP;
+ default: /* 'c' and 'x' */
+ break;
+ }
+ switch (code)
+ {
+ /* 'c' cases. */
+ case INTEGER_CST: return TS_INT_CST;
+ case REAL_CST: return TS_REAL_CST;
+ case COMPLEX_CST: return TS_COMPLEX;
+ case VECTOR_CST: return TS_VECTOR;
+ case STRING_CST: return TS_STRING;
+ /* 'x' cases. */
+ case ERROR_MARK: return TS_COMMON;
+ case IDENTIFIER_NODE: return TS_IDENTIFIER;
+ case TREE_LIST: return TS_LIST;
+ case TREE_VEC: return TS_VEC;
+ case PLACEHOLDER_EXPR: return TS_COMMON;
+
+ default:
+ abort ();
+ }
+}
+
/* Perform any modifications to EXPR required when it is unsaved. Does
not recurse into EXPR's subtrees. */
@@ -1708,23 +1556,21 @@ unsave_expr_1 (expr)
break;
default:
- if (lang_unsave_expr_now != 0)
- (*lang_unsave_expr_now) (expr);
break;
}
}
-/* Helper function for unsave_expr_now. */
+/* Default lang hook for "unsave_expr_now". */
-static void
-unsave_expr_now_r (expr)
+tree
+lhd_unsave_expr_now (expr)
tree expr;
{
enum tree_code code;
/* There's nothing to do for NULL_TREE. */
if (expr == 0)
- return;
+ return expr;
unsave_expr_1 (expr);
@@ -1740,8 +1586,8 @@ unsave_expr_now_r (expr)
case 'x': /* miscellaneous: e.g., identifier, TREE_LIST or ERROR_MARK. */
if (code == TREE_LIST)
{
- unsave_expr_now_r (TREE_VALUE (expr));
- unsave_expr_now_r (TREE_CHAIN (expr));
+ lhd_unsave_expr_now (TREE_VALUE (expr));
+ lhd_unsave_expr_now (TREE_CHAIN (expr));
}
break;
@@ -1755,26 +1601,13 @@ unsave_expr_now_r (expr)
int i;
for (i = first_rtl_op (code) - 1; i >= 0; i--)
- unsave_expr_now_r (TREE_OPERAND (expr, i));
+ lhd_unsave_expr_now (TREE_OPERAND (expr, i));
}
break;
default:
abort ();
}
-}
-
-/* Modify a tree in place so that all the evaluate only once things
- are cleared out. Return the EXPR given. */
-
-tree
-unsave_expr_now (expr)
- tree expr;
-{
- if (lang_unsave!= 0)
- (*lang_unsave) (&expr);
- else
- unsave_expr_now_r (expr);
return expr;
}
@@ -1836,12 +1669,9 @@ unsafe_for_reeval (expr)
break;
default:
- if (lang_unsafe_for_reeval != 0)
- {
- tmp = (*lang_unsafe_for_reeval) (expr);
- if (tmp >= 0)
- return tmp;
- }
+ tmp = (*lang_hooks.unsafe_for_reeval) (expr);
+ if (tmp >= 0)
+ return tmp;
break;
}
@@ -2493,7 +2323,7 @@ build1 (code, type, node)
#endif
#ifdef ENABLE_CHECKING
- if (TREE_CODE_CLASS (code) == '2'
+ if (TREE_CODE_CLASS (code) == '2'
|| TREE_CODE_CLASS (code) == '<'
|| TREE_CODE_LENGTH (code) != 1)
abort ();
@@ -2678,7 +2508,7 @@ tree
build_type_attribute_variant (ttype, attribute)
tree ttype, attribute;
{
- if ( ! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute))
+ if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute))
{
unsigned int hashcode;
tree ntype;
@@ -2723,60 +2553,7 @@ build_type_attribute_variant (ttype, attribute)
return ttype;
}
-/* Default value of targetm.comp_type_attributes that always returns 1. */
-
-int
-default_comp_type_attributes (type1, type2)
- tree type1 ATTRIBUTE_UNUSED;
- tree type2 ATTRIBUTE_UNUSED;
-{
- return 1;
-}
-
-/* Default version of targetm.set_default_type_attributes that always does
- nothing. */
-
-void
-default_set_default_type_attributes (type)
- tree type ATTRIBUTE_UNUSED;
-{
-}
-
-/* Default version of targetm.insert_attributes that always does nothing. */
-void
-default_insert_attributes (decl, attr_ptr)
- tree decl ATTRIBUTE_UNUSED;
- tree *attr_ptr ATTRIBUTE_UNUSED;
-{
-}
-
-/* Default value of targetm.attribute_table that is empty. */
-const struct attribute_spec default_target_attribute_table[] =
-{
- { NULL, 0, 0, false, false, false, NULL }
-};
-
-/* Default value of targetm.function_attribute_inlinable_p that always
- returns false. */
-bool
-default_function_attribute_inlinable_p (fndecl)
- tree fndecl ATTRIBUTE_UNUSED;
-{
- /* By default, functions with machine attributes cannot be inlined. */
- return false;
-}
-
-/* Default value of targetm.ms_bitfield_layout_p that always returns
- false. */
-bool
-default_ms_bitfield_layout_p (record)
- tree record ATTRIBUTE_UNUSED;
-{
- /* By default, GCC does not use the MS VC++ bitfield layout rules. */
- return false;
-}
-
-/* Return non-zero if IDENT is a valid name for attribute ATTR,
+/* Return nonzero if IDENT is a valid name for attribute ATTR,
or zero if not.
We try both `text' and `__text__', ATTR may be either one. */
@@ -3006,7 +2783,8 @@ get_qualified_type (type, type_quals)
like the one we need to have. If so, use that existing one. We must
preserve the TYPE_NAME, since there is code that depends on this. */
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
- if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type))
+ if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type)
+ && TYPE_CONTEXT (t) == TYPE_CONTEXT (type))
return t;
return NULL_TREE;
@@ -3112,7 +2890,7 @@ type_hash_eq (va, vb)
/* Return the cached hash value. */
-static unsigned int
+static hashval_t
type_hash_hash (item)
const void *item;
{
@@ -3217,41 +2995,6 @@ type_hash_marked_p (p)
return ggc_marked_p (type) || TYPE_SYMTAB_POINTER (type);
}
-/* Mark the entry in the type hash table the type it points to is marked.
- Also mark the type in case we are considering this entry "marked" by
- virtue of TYPE_SYMTAB_POINTER being set. */
-
-static void
-type_hash_mark (p)
- const void *p;
-{
- ggc_mark (p);
- ggc_mark_tree (((struct type_hash *) p)->type);
-}
-
-/* Mark the hashtable slot pointed to by ENTRY (which is really a
- `tree**') for GC. */
-
-static int
-mark_tree_hashtable_entry (entry, data)
- void **entry;
- void *data ATTRIBUTE_UNUSED;
-{
- ggc_mark_tree ((tree) *entry);
- return 1;
-}
-
-/* Mark ARG (which is really a htab_t whose slots are trees) for
- GC. */
-
-void
-mark_tree_hashtable (arg)
- void *arg;
-{
- htab_t t = *(htab_t *) arg;
- htab_traverse (t, mark_tree_hashtable_entry, 0);
-}
-
static void
print_type_hash_statistics ()
{
@@ -3285,8 +3028,8 @@ int
attribute_list_equal (l1, l2)
tree l1, l2;
{
- return attribute_list_contained (l1, l2)
- && attribute_list_contained (l2, l1);
+ return attribute_list_contained (l1, l2)
+ && attribute_list_contained (l2, l1);
}
/* Given two lists of attributes, return true if list L2 is
@@ -3446,7 +3189,7 @@ tree_int_cst_compare (t1, t2)
return -1;
else if (tree_int_cst_lt (t2, t1))
return 1;
- else
+ else
return 0;
}
@@ -3974,6 +3717,32 @@ build_function_type (value_type, arg_types)
return t;
}
+/* Build a function type. The RETURN_TYPE is the type retured by the
+ function. If additional arguments are provided, they are
+ additional argument types. The list of argument types must always
+ be terminated by NULL_TREE. */
+
+tree
+build_function_type_list VPARAMS ((tree return_type, ...))
+{
+ tree t, args, last;
+
+ VA_OPEN (p, return_type);
+ VA_FIXEDARG (p, tree, return_type);
+
+ t = va_arg (p, tree);
+ for (args = NULL_TREE; t != NULL_TREE; t = va_arg (p, tree))
+ args = tree_cons (NULL_TREE, t, args);
+
+ last = args;
+ args = nreverse (args);
+ TREE_CHAIN (last) = void_list_node;
+ args = build_function_type (return_type, args);
+
+ VA_CLOSE (p);
+ return args;
+}
+
/* Construct, lay out and return the type of methods belonging to class
BASETYPE and whose arguments and values are described by TYPE.
If that type exists already, reuse it.
@@ -4185,8 +3954,8 @@ get_unwidened (op, for_type)
{
unsigned int innerprec
= tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1);
-
- type = type_for_size (innerprec, TREE_UNSIGNED (TREE_OPERAND (op, 1)));
+ int unsignedp = TREE_UNSIGNED (TREE_OPERAND (op, 1));
+ type = (*lang_hooks.types.type_for_size) (innerprec, unsignedp);
/* We can get this structure field in the narrowest type it fits in.
If FOR_TYPE is 0, do this only for a field that matches the
@@ -4196,8 +3965,7 @@ get_unwidened (op, for_type)
if (innerprec < TYPE_PRECISION (TREE_TYPE (op))
&& (for_type || ! DECL_BIT_FIELD (TREE_OPERAND (op, 1)))
- && (! uns || final_prec <= innerprec
- || TREE_UNSIGNED (TREE_OPERAND (op, 1)))
+ && (! uns || final_prec <= innerprec || unsignedp)
&& type != 0)
{
win = build (COMPONENT_REF, type, TREE_OPERAND (op, 0),
@@ -4236,10 +4004,10 @@ get_narrower (op, unsignedp_ptr)
/* See what's inside this conversion. If we decide to strip it,
we will set WIN. */
- op = TREE_OPERAND (op, 0);
if (bitschange > 0)
{
+ op = TREE_OPERAND (op, 0);
/* An extension: the outermost one can be stripped,
but remember whether it is zero or sign extension. */
if (first)
@@ -4258,6 +4026,7 @@ get_narrower (op, unsignedp_ptr)
if (first)
uns = TREE_UNSIGNED (TREE_TYPE (op));
first = 0;
+ op = TREE_OPERAND (op, 0);
}
win = op;
@@ -4271,7 +4040,8 @@ get_narrower (op, unsignedp_ptr)
{
unsigned HOST_WIDE_INT innerprec
= tree_low_cst (DECL_SIZE (TREE_OPERAND (op, 1)), 1);
- tree type = type_for_size (innerprec, TREE_UNSIGNED (op));
+ tree type = (*lang_hooks.types.type_for_size) (innerprec,
+ TREE_UNSIGNED (op));
/* We can get this structure field in a narrower type that fits it,
but the resulting extension to its nominal type (a fullword type)
@@ -4350,6 +4120,9 @@ bool
variably_modified_type_p (type)
tree type;
{
+ if (type == error_mark_node)
+ return false;
+
/* If TYPE itself has variable size, it is variably modified.
We do not yet have a representation of the C99 '[*]' syntax.
@@ -4456,6 +4229,9 @@ decl_type_context (decl)
while (context)
{
+ if (TREE_CODE (context) == NAMESPACE_DECL)
+ return NULL_TREE;
+
if (TREE_CODE (context) == RECORD_TYPE
|| TREE_CODE (context) == UNION_TYPE
|| TREE_CODE (context) == QUAL_UNION_TYPE)
@@ -4564,15 +4340,44 @@ dump_tree_statistics ()
#else
fprintf (stderr, "(No per-node statistics)\n");
#endif
- print_obstack_statistics ("permanent_obstack", &permanent_obstack);
print_type_hash_statistics ();
(*lang_hooks.print_statistics) ();
}
-#define FILE_FUNCTION_PREFIX_LEN 9
-
#define FILE_FUNCTION_FORMAT "_GLOBAL__%s_%s"
+const char *flag_random_seed;
+
+/* Set up a default flag_random_seed value, if there wasn't one already. */
+
+void
+default_flag_random_seed (void)
+{
+ unsigned HOST_WIDE_INT value;
+ char *new_random_seed;
+
+ if (flag_random_seed != NULL)
+ return;
+
+ /* Get some more or less random data. */
+#ifdef HAVE_GETTIMEOFDAY
+ {
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+ value = (((unsigned HOST_WIDE_INT) tv.tv_usec << 16)
+ ^ tv.tv_sec ^ getpid ());
+ }
+#else
+ value = getpid ();
+#endif
+
+ /* This slightly overestimates the space required. */
+ new_random_seed = xmalloc (HOST_BITS_PER_WIDE_INT / 3 + 2);
+ sprintf (new_random_seed, HOST_WIDE_INT_PRINT_UNSIGNED, value);
+ flag_random_seed = new_random_seed;
+}
+
/* Appends 6 random characters to TEMPLATE to (hopefully) avoid name
clashes in cases where we can't reliably choose a unique name.
@@ -4584,40 +4389,20 @@ append_random_chars (template)
{
static const char letters[]
= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- static unsigned HOST_WIDE_INT value;
unsigned HOST_WIDE_INT v;
+ size_t i;
- if (! value)
- {
- struct stat st;
-
- /* VALUE should be unique for each file and must not change between
- compiles since this can cause bootstrap comparison errors. */
+ default_flag_random_seed ();
- if (stat (main_input_filename, &st) < 0)
- {
- /* This can happen when preprocessed text is shipped between
- machines, e.g. with bug reports. Assume that uniqueness
- isn't actually an issue. */
- value = 1;
- }
- else
- {
- /* In VMS, ino is an array, so we have to use both values. We
- conditionalize that. */
-#ifdef VMS
-#define INO_TO_INT(INO) ((int) (INO)[1] << 16 ^ (int) (INO)[2])
-#else
-#define INO_TO_INT(INO) INO
-#endif
- value = st.st_dev ^ INO_TO_INT (st.st_ino) ^ st.st_mtime;
- }
- }
+ /* This isn't a very good hash, but it does guarantee no collisions
+ when the random string is generated by the code above and the time
+ delta is small. */
+ v = 0;
+ for (i = 0; i < strlen (flag_random_seed); i++)
+ v = (v << 4) ^ (v >> (HOST_BITS_PER_WIDE_INT - 4)) ^ flag_random_seed[i];
template += strlen (template);
- v = value;
-
/* Fill in the random bits. */
template[0] = letters[v % 62];
v /= 62;
@@ -4652,7 +4437,7 @@ clean_symbol_name (p)
))
*p = '_';
}
-
+
/* Generate a name for a function unique to this translation unit.
TYPE is some string to identify the purpose of this function to the
linker or collect2. */
@@ -4850,10 +4635,26 @@ tree_class_check_failed (node, cl, file, line, function)
tree_code_name[TREE_CODE (node)], function, trim_filename (file), line);
}
+/* Similar to above, except that the check is for the bounds of a TREE_VEC's
+ (dynamically sized) vector. */
+
+void
+tree_vec_elt_check_failed (idx, len, file, line, function)
+ int idx;
+ int len;
+ const char *file;
+ int line;
+ const char *function;
+{
+ internal_error
+ ("tree check: accessed elt %d of tree_vec with %d elts in %s, at %s:%d",
+ idx + 1, len, function, trim_filename (file), line);
+}
+
#endif /* ENABLE_TREE_CHECKING */
/* For a new vector type node T, build the information necessary for
- debuggint output. */
+ debugging output. */
static void
finish_vector_type (t)
@@ -5007,8 +4808,12 @@ build_common_tree_nodes_2 (short_double)
unsigned_V4SI_type_node
= make_vector (V4SImode, unsigned_intSI_type_node, 1);
+ unsigned_V2HI_type_node
+ = make_vector (V2HImode, unsigned_intHI_type_node, 1);
unsigned_V2SI_type_node
= make_vector (V2SImode, unsigned_intSI_type_node, 1);
+ unsigned_V2DI_type_node
+ = make_vector (V2DImode, unsigned_intDI_type_node, 1);
unsigned_V4HI_type_node
= make_vector (V4HImode, unsigned_intHI_type_node, 1);
unsigned_V8QI_type_node
@@ -5017,16 +4822,22 @@ build_common_tree_nodes_2 (short_double)
= make_vector (V8HImode, unsigned_intHI_type_node, 1);
unsigned_V16QI_type_node
= make_vector (V16QImode, unsigned_intQI_type_node, 1);
+ unsigned_V1DI_type_node
+ = make_vector (V1DImode, unsigned_intDI_type_node, 1);
V16SF_type_node = make_vector (V16SFmode, float_type_node, 0);
V4SF_type_node = make_vector (V4SFmode, float_type_node, 0);
V4SI_type_node = make_vector (V4SImode, intSI_type_node, 0);
+ V2HI_type_node = make_vector (V2HImode, intHI_type_node, 0);
V2SI_type_node = make_vector (V2SImode, intSI_type_node, 0);
+ V2DI_type_node = make_vector (V2DImode, intDI_type_node, 0);
V4HI_type_node = make_vector (V4HImode, intHI_type_node, 0);
V8QI_type_node = make_vector (V8QImode, intQI_type_node, 0);
V8HI_type_node = make_vector (V8HImode, intHI_type_node, 0);
V2SF_type_node = make_vector (V2SFmode, float_type_node, 0);
+ V2DF_type_node = make_vector (V2DFmode, double_type_node, 0);
V16QI_type_node = make_vector (V16QImode, intQI_type_node, 0);
+ V1DI_type_node = make_vector (V1DImode, intDI_type_node, 0);
}
/* Returns a vector tree node given a vector mode, the inner type, and
@@ -5048,3 +4859,47 @@ make_vector (mode, innertype, unsignedp)
return t;
}
+
+/* Given an initializer INIT, return TRUE if INIT is zero or some
+ aggregate of zeros. Otherwise return FALSE. */
+
+bool
+initializer_zerop (init)
+ tree init;
+{
+ STRIP_NOPS (init);
+
+ switch (TREE_CODE (init))
+ {
+ case INTEGER_CST:
+ return integer_zerop (init);
+ case REAL_CST:
+ return real_zerop (init)
+ && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (init));
+ case COMPLEX_CST:
+ return integer_zerop (init)
+ || (real_zerop (init)
+ && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_REALPART (init)))
+ && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_IMAGPART (init))));
+ case CONSTRUCTOR:
+ {
+ if (AGGREGATE_TYPE_P (TREE_TYPE (init)))
+ {
+ tree aggr_init = TREE_OPERAND (init, 1);
+
+ while (aggr_init)
+ {
+ if (! initializer_zerop (TREE_VALUE (aggr_init)))
+ return false;
+ aggr_init = TREE_CHAIN (aggr_init);
+ }
+ return true;
+ }
+ return false;
+ }
+ default:
+ return false;
+ }
+}
+
+#include "gt-tree.h"
diff --git a/contrib/gcc/tree.def b/contrib/gcc/tree.def
index f0f43a7..e05ec28 100644
--- a/contrib/gcc/tree.def
+++ b/contrib/gcc/tree.def
@@ -49,7 +49,7 @@ DEFTREECODE (ERROR_MARK, "error_mark", 'x', 0)
Internally it looks like a STRING_CST node.
There is only one IDENTIFIER_NODE ever made for any particular name.
Use `get_identifier' to get it (or create it, the first time). */
-DEFTREECODE (IDENTIFIER_NODE, "identifier_node", 'x', -1)
+DEFTREECODE (IDENTIFIER_NODE, "identifier_node", 'x', ((LANG_HOOKS_IDENTIFIER_SIZE - sizeof (struct tree_common) + sizeof (tree) - 1) / sizeof (tree)))
/* Has the TREE_VALUE and TREE_PURPOSE fields. */
/* These nodes are made into lists by chaining through the
@@ -76,10 +76,10 @@ DEFTREECODE (TREE_VEC, "tree_vec", 'x', 2)
could either point to another BLOCK node or it could point to a
FUNCTION_DECL node (e.g. in the case of a block representing the
outermost scope of a particular inlining of a function).
- BLOCK_ABSTRACT is non-zero if the block represents an abstract
+ BLOCK_ABSTRACT is nonzero if the block represents an abstract
instance of a block (i.e. one which is nested within an abstract
instance of an inline function).
- TREE_ASM_WRITTEN is non-zero if the block was actually referenced
+ TREE_ASM_WRITTEN is nonzero if the block was actually referenced
in the generated assembly. */
DEFTREECODE (BLOCK, "block", 'b', 0)
@@ -199,19 +199,17 @@ DEFTREECODE (FILE_TYPE, "file_type", 't', 0)
TREE_TYPE Type of an array element.
TYPE_DOMAIN Type to index by.
Its range of values specifies the array length.
- TYPE_SEP Expression for units from one elt to the next.
- TYPE_SEP_UNIT Number of bits in a unit for previous.
The field TYPE_POINTER_TO (TREE_TYPE (array_type)) is always nonzero
and holds the type to coerce a value of that array type to in C.
TYPE_STRING_FLAG indicates a string (in contrast to an array of chars)
- in languages (such as Chill) that make a distinction. */
+ in languages (such as Chill) that make a distinction. */
/* Array types in C or Pascal */
DEFTREECODE (ARRAY_TYPE, "array_type", 't', 0)
/* Types of sets for Pascal. Special fields are the same as
in an array type. The target type is always a boolean type.
Used for both bitstrings and powersets in Chill;
- TYPE_STRING_FLAG indicates a bitstring. */
+ TYPE_STRING_FLAG indicates a bitstring. */
DEFTREECODE (SET_TYPE, "set_type", 't', 0)
/* Struct in C, or record in Pascal. */
@@ -329,7 +327,7 @@ DEFTREECODE (STRING_CST, "string_cst", 'c', 3)
holds a line number. In some cases these can be the location of
a reference, if no definition has been seen.
- DECL_ABSTRACT is non-zero if the decl represents an abstract instance
+ DECL_ABSTRACT is nonzero if the decl represents an abstract instance
of a decl (i.e. one which is nested within an abstract instance of a
inline function. */
@@ -369,7 +367,7 @@ DEFTREECODE (INDIRECT_REF, "indirect_ref", 'r', 1)
DEFTREECODE (BUFFER_REF, "buffer_ref", 'r', 1)
/* Array indexing.
- Operand 0 is the array; operand 1 is a (single) array index. */
+ Operand 0 is the array; operand 1 is a (single) array index. */
DEFTREECODE (ARRAY_REF, "array_ref", 'r', 2)
/* Likewise, except that the result is a range ("slice") of the array. The
@@ -643,7 +641,7 @@ DEFTREECODE (BIT_NOT_EXPR, "bit_not_expr", '1', 1)
needed or not (for side effects). The operand may have
BOOLEAN_TYPE or INTEGER_TYPE. In either case, the argument will be
either zero or one. For example, a TRUTH_NOT_EXPR will never have
- a INTEGER_TYPE VAR_DECL as its argument; instead, a NE_EXPR will be
+ an INTEGER_TYPE VAR_DECL as its argument; instead, a NE_EXPR will be
used to compare the VAR_DECL to zero, thereby obtaining a node with
value zero or one. */
DEFTREECODE (TRUTH_ANDIF_EXPR, "truth_andif_expr", 'e', 2)
@@ -670,7 +668,7 @@ DEFTREECODE (NE_EXPR, "ne_expr", '<', 2)
DEFTREECODE (UNORDERED_EXPR, "unordered_expr", '<', 2)
DEFTREECODE (ORDERED_EXPR, "ordered_expr", '<', 2)
-/* These are equivalent to unordered or ... */
+/* These are equivalent to unordered or ... */
DEFTREECODE (UNLT_EXPR, "unlt_expr", '<', 2)
DEFTREECODE (UNLE_EXPR, "unle_expr", '<', 2)
DEFTREECODE (UNGT_EXPR, "ungt_expr", '<', 2)
@@ -757,12 +755,9 @@ DEFTREECODE (CONJ_EXPR, "conj_expr", '1', 1)
DEFTREECODE (REALPART_EXPR, "realpart_expr", '1', 1)
DEFTREECODE (IMAGPART_EXPR, "imagpart_expr", '1', 1)
-/* The first argument is the lvalue to be incremented or decremented.
- The second argument is the value that should be added or
- subtracted. If the first argument has pointer type, the second
- argument is interpreted as the number of bytes to add or subtract
- from the address. The second argument must not be a constant
- zero. */
+/* Nodes for ++ and -- in C.
+ The second arg is how much to increment or decrement by.
+ For a pointer, it would be the size of the object pointed to. */
DEFTREECODE (PREDECREMENT_EXPR, "predecrement_expr", 'e', 2)
DEFTREECODE (PREINCREMENT_EXPR, "preincrement_expr", 'e', 2)
DEFTREECODE (POSTDECREMENT_EXPR, "postdecrement_expr", 'e', 2)
@@ -779,7 +774,7 @@ DEFTREECODE (VA_ARG_EXPR, "va_arg_expr", 'e', 1)
DEFTREECODE (TRY_CATCH_EXPR, "try_catch_expr", 'e', 2)
/* Evaluate the first operand.
- The second operand is a a cleanup expression which is evaluated
+ The second operand is a cleanup expression which is evaluated
before an exit (normal, exception, or jump out) from this expression.
Like a CLEANUP_POINT_EXPR/WITH_CLEANUP_EXPR combination, but those
@@ -849,7 +844,7 @@ DEFTREECODE (EXPR_WITH_FILE_LOCATION, "expr_with_file_location", 'e', 3)
/* Switch expression.
Operand 0 is the expression used to perform the branch,
Operand 1 contains the case values. The way they're organized is
- front-end implementation defined. */
+ front-end implementation defined. */
DEFTREECODE (SWITCH_EXPR, "switch_expr", 'e', 2)
/* The exception object from the runtime. */
diff --git a/contrib/gcc/tree.h b/contrib/gcc/tree.h
index 4a05eff..a64175f 100644
--- a/contrib/gcc/tree.h
+++ b/contrib/gcc/tree.h
@@ -19,8 +19,12 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
+#ifndef GCC_TREE_H
+#define GCC_TREE_H
+
#include "machmode.h"
#include "version.h"
+#include "location.h"
/* Codes of tree nodes */
@@ -46,10 +50,10 @@ enum tree_code {
and `x' for anything else (TREE_LIST, IDENTIFIER, etc). */
#define MAX_TREE_CODES 256
-extern char tree_code_type[MAX_TREE_CODES];
+extern const char tree_code_type[];
#define TREE_CODE_CLASS(CODE) tree_code_type[(int) (CODE)]
-/* Returns non-zero iff CLASS is the tree-code class of an
+/* Returns nonzero iff CLASS is the tree-code class of an
expression. */
#define IS_EXPR_CODE_CLASS(CLASS) \
@@ -57,12 +61,12 @@ extern char tree_code_type[MAX_TREE_CODES];
/* Number of argument-words in each kind of tree-node. */
-extern int tree_code_length[MAX_TREE_CODES];
+extern const unsigned char tree_code_length[];
#define TREE_CODE_LENGTH(CODE) tree_code_length[(int) (CODE)]
/* Names of tree components. */
-extern const char *tree_code_name[MAX_TREE_CODES];
+extern const char *const tree_code_name[];
/* Classify which part of the compiler has defined a given builtin function.
Note that we assume below that this is no more than two bits. */
@@ -80,7 +84,7 @@ extern const char *const built_in_class_names[4];
/* Codes that identify the various built in functions
so that expand_call can identify them quickly. */
-#define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA) ENUM,
+#define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA, AT) ENUM,
enum built_in_function
{
#include "builtins.def"
@@ -118,7 +122,7 @@ extern tree built_in_decls[(int) END_BUILTINS];
See the accessor macros, defined below, for documentation of the
fields. */
-struct tree_common
+struct tree_common GTY(())
{
tree chain;
tree type;
@@ -313,12 +317,26 @@ struct tree_common
__FUNCTION__); \
__t; })
+#define TREE_VEC_ELT_CHECK(t, i) __extension__ \
+(*({const tree __t = t; \
+ const int __i = (i); \
+ if (TREE_CODE (__t) != TREE_VEC) \
+ tree_check_failed (__t, TREE_VEC, \
+ __FILE__, __LINE__, __FUNCTION__); \
+ if (__i < 0 || __i >= __t->vec.length) \
+ tree_vec_elt_check_failed (__i, __t->vec.length, \
+ __FILE__, __LINE__, __FUNCTION__); \
+ &__t->vec.a[__i]; }))
+
extern void tree_check_failed PARAMS ((const tree, enum tree_code,
const char *, int, const char *))
ATTRIBUTE_NORETURN;
extern void tree_class_check_failed PARAMS ((const tree, int,
const char *, int, const char *))
ATTRIBUTE_NORETURN;
+extern void tree_vec_elt_check_failed PARAMS ((int, int, const char *,
+ int, const char *))
+ ATTRIBUTE_NORETURN;
#else /* not ENABLE_TREE_CHECKING, or not gcc */
@@ -326,6 +344,7 @@ extern void tree_class_check_failed PARAMS ((const tree, int,
#define TREE_CLASS_CHECK(t, code) (t)
#define CST_OR_CONSTRUCTOR_CHECK(t) (t)
#define EXPR_CHECK(t) (t)
+#define TREE_VEC_ELT_CHECK(t, i) ((t)->vec.a[i])
#endif
@@ -438,7 +457,7 @@ extern void tree_class_check_failed PARAMS ((const tree, int,
is sufficient to check bounds at the time the reference is seated,
and assume that all future uses of the reference are safe, since
the address of references cannot change. (2) When a reference
- supertype is seated to an subtype object. The bounds "remember"
+ supertype is seated to a subtype object. The bounds "remember"
the true size of the complete object, so that subsequent upcasts of
the address of the reference will be checked properly (is such a
thing valid C++?). */
@@ -492,7 +511,7 @@ extern void tree_class_check_failed PARAMS ((const tree, int,
construct the address of this field. This is used for aliasing
purposes: see record_component_aliases.
In CONSTRUCTOR nodes, it means object constructed must be in memory.
- In LABEL_DECL nodes, it means a goto for this label has been seen
+ In LABEL_DECL nodes, it means a goto for this label has been seen
from a place outside all binding contours that restore stack levels.
In ..._TYPE nodes, it means that objects of this type must
be fully addressable. This means that pieces of this
@@ -667,7 +686,7 @@ extern void tree_class_check_failed PARAMS ((const tree, int,
#define TREE_BOUNDED(NODE) ((NODE)->common.bounded_flag)
-/* Nonzero in a IDENTIFIER_NODE if the use of the name is defined as a
+/* Nonzero in an IDENTIFIER_NODE if the use of the name is defined as a
deprecated feature by __attribute__((deprecated)). */
#define TREE_DEPRECATED(NODE) ((NODE)->common.deprecated_flag)
@@ -699,10 +718,10 @@ extern void tree_class_check_failed PARAMS ((const tree, int,
(((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (A) \
< (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (B)) \
|| (((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (A) \
- == (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (B)) \
+ == (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (B)) \
&& TREE_INT_CST_LOW (A) < TREE_INT_CST_LOW (B)))
-struct tree_int_cst
+struct tree_int_cst GTY(())
{
struct tree_common common;
rtx rtl; /* acts as link to register transfer language
@@ -710,7 +729,7 @@ struct tree_int_cst
/* A sub-struct is necessary here because the function `const_hash'
wants to scan both words as a unit and taking the address of the
sub-struct yields the properly inclusive bounded pointer. */
- struct {
+ struct tree_int_cst_lowhi {
unsigned HOST_WIDE_INT low;
HOST_WIDE_INT high;
} int_cst;
@@ -722,27 +741,26 @@ struct tree_int_cst
#define TREE_CST_RTL(NODE) (CST_OR_CONSTRUCTOR_CHECK (NODE)->real_cst.rtl)
-/* In a REAL_CST node.
-
- We can represent a real value as either a `double' or an array of
- longs. */
+/* In a REAL_CST node. struct real_value is an opaque entity, with
+ manipulators defined in real.h. We don't want tree.h depending on
+ real.h and transitively on tm.h. */
+struct real_value;
-#define TREE_REAL_CST(NODE) (REAL_CST_CHECK (NODE)->real_cst.real_cst)
+#define TREE_REAL_CST_PTR(NODE) (REAL_CST_CHECK (NODE)->real_cst.real_cst_ptr)
+#define TREE_REAL_CST(NODE) (*TREE_REAL_CST_PTR (NODE))
-#include "real.h"
-
-struct tree_real_cst
+struct tree_real_cst GTY(())
{
struct tree_common common;
rtx rtl; /* acts as link to register transfer language (rtl) info */
- REAL_VALUE_TYPE real_cst;
+ struct real_value * real_cst_ptr;
};
/* In a STRING_CST */
#define TREE_STRING_LENGTH(NODE) (STRING_CST_CHECK (NODE)->string.length)
#define TREE_STRING_POINTER(NODE) (STRING_CST_CHECK (NODE)->string.pointer)
-struct tree_string
+struct tree_string GTY(())
{
struct tree_common common;
rtx rtl; /* acts as link to register transfer language (rtl) info */
@@ -754,7 +772,7 @@ struct tree_string
#define TREE_REALPART(NODE) (COMPLEX_CST_CHECK (NODE)->complex.real)
#define TREE_IMAGPART(NODE) (COMPLEX_CST_CHECK (NODE)->complex.imag)
-struct tree_complex
+struct tree_complex GTY(())
{
struct tree_common common;
rtx rtl; /* acts as link to register transfer language (rtl) info */
@@ -765,7 +783,7 @@ struct tree_complex
/* In a VECTOR_CST node. */
#define TREE_VECTOR_CST_ELTS(NODE) (VECTOR_CST_CHECK (NODE)->vector.elements)
-struct tree_vector
+struct tree_vector GTY(())
{
struct tree_common common;
rtx rtl;
@@ -780,6 +798,8 @@ struct tree_vector
(IDENTIFIER_NODE_CHECK (NODE)->identifier.id.len)
#define IDENTIFIER_POINTER(NODE) \
((const char *) IDENTIFIER_NODE_CHECK (NODE)->identifier.id.str)
+#define IDENTIFIER_HASH_VALUE(NODE) \
+ (IDENTIFIER_NODE_CHECK (NODE)->identifier.id.hash_value)
/* Translate a hash table identifier pointer to a tree_identifier
pointer, and vice versa. */
@@ -788,7 +808,7 @@ struct tree_vector
((tree) ((char *) (NODE) - sizeof (struct tree_common)))
#define GCC_IDENT_TO_HT_IDENT(NODE) (&((struct tree_identifier *) (NODE))->id)
-struct tree_identifier
+struct tree_identifier GTY(())
{
struct tree_common common;
struct ht_identifier id;
@@ -798,7 +818,7 @@ struct tree_identifier
#define TREE_PURPOSE(NODE) (TREE_LIST_CHECK (NODE)->list.purpose)
#define TREE_VALUE(NODE) (TREE_LIST_CHECK (NODE)->list.value)
-struct tree_list
+struct tree_list GTY(())
{
struct tree_common common;
tree purpose;
@@ -807,15 +827,16 @@ struct tree_list
/* In a TREE_VEC node. */
#define TREE_VEC_LENGTH(NODE) (TREE_VEC_CHECK (NODE)->vec.length)
-#define TREE_VEC_ELT(NODE,I) (TREE_VEC_CHECK (NODE)->vec.a[I])
#define TREE_VEC_END(NODE) \
((void) TREE_VEC_CHECK (NODE), &((NODE)->vec.a[(NODE)->vec.length]))
-struct tree_vec
+#define TREE_VEC_ELT(NODE,I) TREE_VEC_ELT_CHECK (NODE, I)
+
+struct tree_vec GTY(())
{
struct tree_common common;
int length;
- tree a[1];
+ tree GTY ((length ("TREE_VEC_LENGTH ((tree)&%h)"))) a[1];
};
/* Define fields and accessors for some nodes that represent expressions. */
@@ -852,7 +873,7 @@ struct tree_vec
#define LABELED_BLOCK_BODY(NODE) \
TREE_OPERAND (LABELED_BLOCK_EXPR_CHECK (NODE), 1)
-/* In a EXIT_BLOCK_EXPR node. */
+/* In an EXIT_BLOCK_EXPR node. */
#define EXIT_BLOCK_LABELED_BLOCK(NODE) \
TREE_OPERAND (EXIT_BLOCK_EXPR_CHECK (NODE), 0)
#define EXIT_BLOCK_RETURN(NODE) TREE_OPERAND (EXIT_BLOCK_EXPR_CHECK (NODE), 1)
@@ -860,7 +881,7 @@ struct tree_vec
/* In a LOOP_EXPR node. */
#define LOOP_EXPR_BODY(NODE) TREE_OPERAND (LOOP_EXPR_CHECK (NODE), 0)
-/* In a EXPR_WITH_FILE_LOCATION node. */
+/* In an EXPR_WITH_FILE_LOCATION node. */
#define EXPR_WFL_EMIT_LINE_NOTE(NODE) \
(EXPR_WITH_FILE_LOCATION_CHECK (NODE)->common.public_flag)
#define EXPR_WFL_NODE(NODE) \
@@ -876,11 +897,18 @@ struct tree_vec
#define EXPR_WFL_SET_LINECOL(NODE, LINE, COL) \
(EXPR_WFL_LINECOL(NODE) = ((LINE) << 12) | ((COL) & 0xfff))
-struct tree_exp
+/* In a TARGET_EXPR node. */
+#define TARGET_EXPR_SLOT(NODE) TREE_OPERAND (TARGET_EXPR_CHECK (NODE), 0)
+#define TARGET_EXPR_INITIAL(NODE) TREE_OPERAND (TARGET_EXPR_CHECK (NODE), 1)
+#define TARGET_EXPR_CLEANUP(NODE) TREE_OPERAND (TARGET_EXPR_CHECK (NODE), 2)
+
+struct tree_exp GTY(())
{
struct tree_common common;
int complexity;
- tree operands[1];
+ tree GTY ((special ("tree_exp"),
+ desc ("TREE_CODE ((tree) &%0)")))
+ operands[1];
};
/* In a BLOCK node. */
@@ -922,13 +950,13 @@ struct tree_exp
One of the logical block fragments is arbitrarily chosen to be
the ORIGIN. The other fragments will point to the origin via
BLOCK_FRAGMENT_ORIGIN; the origin itself will have this pointer
- be null. The list of fragments will be chained through
+ be null. The list of fragments will be chained through
BLOCK_FRAGMENT_CHAIN from the origin. */
#define BLOCK_FRAGMENT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.fragment_origin)
#define BLOCK_FRAGMENT_CHAIN(NODE) (BLOCK_CHECK (NODE)->block.fragment_chain)
-struct tree_block
+struct tree_block GTY(())
{
struct tree_common common;
@@ -968,6 +996,7 @@ struct tree_block
#define TYPE_PRECISION(NODE) (TYPE_CHECK (NODE)->type.precision)
#define TYPE_SYMTAB_ADDRESS(NODE) (TYPE_CHECK (NODE)->type.symtab.address)
#define TYPE_SYMTAB_POINTER(NODE) (TYPE_CHECK (NODE)->type.symtab.pointer)
+#define TYPE_SYMTAB_DIE(NODE) (TYPE_CHECK (NODE)->type.symtab.die)
#define TYPE_NAME(NODE) (TYPE_CHECK (NODE)->type.name)
#define TYPE_NEXT_VARIANT(NODE) (TYPE_CHECK (NODE)->type.next_variant)
#define TYPE_MAIN_VARIANT(NODE) (TYPE_CHECK (NODE)->type.main_variant)
@@ -1205,7 +1234,9 @@ struct tree_block
#define MAX_POINTER_DEPTH 2
#define VA_LIST_POINTER_DEPTH 3
-struct tree_type
+struct die_struct;
+
+struct tree_type GTY(())
{
struct tree_common common;
tree values;
@@ -1237,7 +1268,12 @@ struct tree_type
unsigned int align;
tree pointer_to;
tree reference_to;
- union {int address; char *pointer; } symtab;
+ union tree_type_symtab {
+ int address;
+ char * GTY ((tag ("1"))) pointer;
+ struct die_struct * GTY ((tag ("2"), skip (""))) die;
+ } GTY ((desc ("debug_hooks == &sdb_debug_hooks ? 1 : debug_hooks == &dwarf2_debug_hooks ? 2 : 0"),
+ descbits ("2"))) symtab;
tree name;
tree minval;
tree maxval;
@@ -1273,7 +1309,7 @@ struct tree_type
from the base of the complete object to the base of the part of the
object that is allocated on behalf of this `type'.
This is always 0 except when there is multiple inheritance. */
-
+
#define BINFO_OFFSET(NODE) TREE_VEC_ELT ((NODE), 1)
#define TYPE_BINFO_OFFSET(NODE) BINFO_OFFSET (TYPE_BINFO (NODE))
#define BINFO_OFFSET_ZEROP(NODE) (integer_zerop (BINFO_OFFSET (NODE)))
@@ -1319,7 +1355,7 @@ struct tree_type
base. The actual contents are language-dependent. Under the old
ABI, the C++ front-end uses a FIELD_DECL whose contents are a
pointer to the virtual base; under the new ABI this field is
- instead a INTEGER_CST giving an offset into the vtable where the
+ instead an INTEGER_CST giving an offset into the vtable where the
offset to the virtual base can be found. */
#define BINFO_VPTR_FIELD(NODE) TREE_VEC_ELT (NODE, 5)
@@ -1355,13 +1391,9 @@ struct tree_type
/* The name of the object as the assembler will see it (but before any
translations made by ASM_OUTPUT_LABELREF). Often this is the same
as DECL_NAME. It is an IDENTIFIER_NODE. */
-#define DECL_ASSEMBLER_NAME(NODE) \
- ((DECL_ASSEMBLER_NAME_SET_P (NODE) \
- ? (void) 0 \
- : (*lang_set_decl_assembler_name) (NODE)), \
- DECL_CHECK (NODE)->decl.assembler_name)
+#define DECL_ASSEMBLER_NAME(NODE) decl_assembler_name (NODE)
-/* Returns non-zero if the DECL_ASSEMBLER_NAME for NODE has been set. If zero,
+/* Returns nonzero if the DECL_ASSEMBLER_NAME for NODE has been set. If zero,
the NODE might still have a DECL_ASSEMBLER_NAME -- it just hasn't been set
yet. */
#define DECL_ASSEMBLER_NAME_SET_P(NODE) \
@@ -1375,15 +1407,15 @@ struct tree_type
DECL_ASSEMBLER_NAME has not yet been set, using this macro will not cause
the DECL_ASSEMBLER_NAME of either DECL to be set. In other words, the
semantics of using this macro, are different than saying:
-
+
SET_DECL_ASSEMBLER_NAME(DECL2, DECL_ASSEMBLER_NAME (DECL1))
which will try to set the DECL_ASSEMBLER_NAME for DECL1. */
#define COPY_DECL_ASSEMBLER_NAME(DECL1, DECL2) \
(DECL_ASSEMBLER_NAME_SET_P (DECL1) \
- ? (void) SET_DECL_ASSEMBLER_NAME (DECL2, \
- DECL_ASSEMBLER_NAME (DECL1)) \
+ ? (void) SET_DECL_ASSEMBLER_NAME (DECL2, \
+ DECL_ASSEMBLER_NAME (DECL1)) \
: (void) 0)
/* Records the section name in a section attribute. Used to pass
@@ -1439,8 +1471,9 @@ struct tree_type
was. If the declaration appears in several places (as for a C
function that is declared first and then defined later), this
information should refer to the definition. */
-#define DECL_SOURCE_FILE(NODE) (DECL_CHECK (NODE)->decl.filename)
-#define DECL_SOURCE_LINE(NODE) (DECL_CHECK (NODE)->decl.linenum)
+#define DECL_SOURCE_LOCATION(NODE) (DECL_CHECK (NODE)->decl.locus)
+#define DECL_SOURCE_FILE(NODE) (DECL_SOURCE_LOCATION (NODE).file)
+#define DECL_SOURCE_LINE(NODE) (DECL_SOURCE_LOCATION (NODE).line)
/* Holds the size of the datum, in bits, as a tree expression.
Need not be constant. */
#define DECL_SIZE(NODE) (DECL_CHECK (NODE)->decl.size)
@@ -1470,7 +1503,7 @@ struct tree_type
PROMOTED_MODE is defined, the mode of this expression may not be same
as DECL_MODE. In that case, DECL_MODE contains the mode corresponding
to the variable's data type, while the mode
- of DECL_RTL is the mode actually used to contain the data.
+ of DECL_RTL is the mode actually used to contain the data.
This value can be evaluated lazily for functions, variables with
static storage duration, and labels. */
@@ -1480,7 +1513,7 @@ struct tree_type
: (make_decl_rtl (NODE, NULL), (NODE)->decl.rtl))
/* Set the DECL_RTL for NODE to RTL. */
#define SET_DECL_RTL(NODE, RTL) (DECL_CHECK (NODE)->decl.rtl = (RTL))
-/* Returns non-zero if the DECL_RTL for NODE has already been set. */
+/* Returns nonzero if the DECL_RTL for NODE has already been set. */
#define DECL_RTL_SET_P(NODE) (DECL_CHECK (NODE)->decl.rtl != NULL)
/* Copy the RTL from NODE1 to NODE2. If the RTL was not set for
NODE1, it will not be set for NODE2; this is a lazy copy. */
@@ -1578,7 +1611,7 @@ struct tree_type
/* In a TYPE_DECL
nonzero means the detail info about this type is not dumped into stabs.
- Instead it will generate cross reference ('x') of names.
+ Instead it will generate cross reference ('x') of names.
This uses the same flag as DECL_EXTERNAL. */
#define TYPE_DECL_SUPPRESS_DEBUG(NODE) \
(TYPE_DECL_CHECK (NODE)->decl.external_flag)
@@ -1593,7 +1626,7 @@ struct tree_type
/* In a FIELD_DECL, indicates this field should be bit-packed. */
#define DECL_PACKED(NODE) (FIELD_DECL_CHECK (NODE)->decl.regdecl_flag)
-/* In a FUNCTION_DECL with a non-zero DECL_CONTEXT, indicates that a
+/* In a FUNCTION_DECL with a nonzero DECL_CONTEXT, indicates that a
static chain is not needed. */
#define DECL_NO_STATIC_CHAIN(NODE) \
(FUNCTION_DECL_CHECK (NODE)->decl.regdecl_flag)
@@ -1611,9 +1644,18 @@ struct tree_type
where it is called. */
#define DECL_INLINE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.inline_flag)
+/* Nonzero in a FUNCTION_DECL means this function has been found inlinable
+ only by virtue of -finline-functions */
+#define DID_INLINE_FUNC(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->decl.inlined_function_flag)
+
/* In a FUNCTION_DECL, nonzero if the function cannot be inlined. */
#define DECL_UNINLINABLE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.uninlinable)
+/* In a VAR_DECL, nonzero if the data should be allocated from
+ thread-local storage. */
+#define DECL_THREAD_LOCAL(NODE) (VAR_DECL_CHECK (NODE)->decl.thread_local_flag)
+
/* In a FUNCTION_DECL, the saved representation of the body of the
entire function. Usually a COMPOUND_STMT, but in C++ this may also
be a RETURN_INIT, CTOR_INITIALIZER, or TRY_BLOCK. */
@@ -1753,11 +1795,10 @@ struct tree_type
struct function;
-struct tree_decl
+struct tree_decl GTY(())
{
struct tree_common common;
- const char *filename;
- int linenum;
+ location_t locus;
unsigned int uid;
tree size;
ENUM_BITFIELD(machine_mode) mode : 8;
@@ -1792,7 +1833,9 @@ struct tree_decl
unsigned non_addressable : 1;
unsigned user_align : 1;
unsigned uninlinable : 1;
- /* Three unused bits. */
+ unsigned thread_local_flag : 1;
+ unsigned inlined_function_flag : 1;
+ /* One unused bit. */
unsigned lang_flag_0 : 1;
unsigned lang_flag_1 : 1;
@@ -1803,17 +1846,20 @@ struct tree_decl
unsigned lang_flag_6 : 1;
unsigned lang_flag_7 : 1;
- union {
+ union tree_decl_u1 {
/* In a FUNCTION_DECL for which DECL_BUILT_IN holds, this is
DECL_FUNCTION_CODE. */
enum built_in_function f;
- /* In a FUNCITON_DECL for which DECL_BUILT_IN does not hold, this
+ /* In a FUNCTION_DECL for which DECL_BUILT_IN does not hold, this
is used by language-dependent code. */
HOST_WIDE_INT i;
/* DECL_ALIGN and DECL_OFFSET_ALIGN. (These are not used for
FUNCTION_DECLs). */
- struct {unsigned int align : 24; unsigned int off_align : 8;} a;
- } u1;
+ struct tree_decl_u1_a {
+ unsigned int align : 24;
+ unsigned int off_align : 8;
+ } a;
+ } GTY ((skip (""))) u1;
tree size_unit;
tree name;
@@ -1833,12 +1879,12 @@ struct tree_decl
In PARM_DECL, holds an RTL for the stack slot
of register where the data was actually passed.
Used by Chill and Java in LABEL_DECL and by C++ and Java in VAR_DECL. */
- union {
- struct function *f;
- rtx r;
- tree t;
+ union tree_decl_u2 {
+ struct function * GTY ((tag ("FUNCTION_DECL"))) f;
+ rtx GTY ((tag ("PARM_DECL"))) r;
+ tree GTY ((tag ("FIELD_DECL"))) t;
int i;
- } u2;
+ } GTY ((desc ("TREE_CODE((tree) &(%0))"))) u2;
/* In a FUNCTION_DECL, this is DECL_SAVED_TREE. */
tree saved_tree;
@@ -1853,25 +1899,43 @@ struct tree_decl
struct lang_decl *lang_specific;
};
+enum tree_node_structure_enum {
+ TS_COMMON,
+ TS_INT_CST,
+ TS_REAL_CST,
+ TS_VECTOR,
+ TS_STRING,
+ TS_COMPLEX,
+ TS_IDENTIFIER,
+ TS_DECL,
+ TS_TYPE,
+ TS_LIST,
+ TS_VEC,
+ TS_EXP,
+ TS_BLOCK,
+ LAST_TS_ENUM
+};
+
/* Define the overall contents of a tree node.
It may be any of the structures declared above
for various types of node. */
-union tree_node
+union tree_node GTY ((ptr_alias (union lang_tree_node),
+ desc ("tree_node_structure (&%h)")))
{
- struct tree_common common;
- struct tree_int_cst int_cst;
- struct tree_real_cst real_cst;
- struct tree_vector vector;
- struct tree_string string;
- struct tree_complex complex;
- struct tree_identifier identifier;
- struct tree_decl decl;
- struct tree_type type;
- struct tree_list list;
- struct tree_vec vec;
- struct tree_exp exp;
- struct tree_block block;
+ struct tree_common GTY ((tag ("TS_COMMON"))) common;
+ struct tree_int_cst GTY ((tag ("TS_INT_CST"))) int_cst;
+ struct tree_real_cst GTY ((tag ("TS_REAL_CST"))) real_cst;
+ struct tree_vector GTY ((tag ("TS_VECTOR"))) vector;
+ struct tree_string GTY ((tag ("TS_STRING"))) string;
+ struct tree_complex GTY ((tag ("TS_COMPLEX"))) complex;
+ struct tree_identifier GTY ((tag ("TS_IDENTIFIER"))) identifier;
+ struct tree_decl GTY ((tag ("TS_DECL"))) decl;
+ struct tree_type GTY ((tag ("TS_TYPE"))) type;
+ struct tree_list GTY ((tag ("TS_LIST"))) list;
+ struct tree_vec GTY ((tag ("TS_VEC"))) vec;
+ struct tree_exp GTY ((tag ("TS_EXP"))) exp;
+ struct tree_block GTY ((tag ("TS_BLOCK"))) block;
};
/* Standard named or nameless data types of the C compiler. */
@@ -1890,7 +1954,7 @@ enum tree_index
TI_UINTSI_TYPE,
TI_UINTDI_TYPE,
TI_UINTTI_TYPE,
-
+
TI_INTEGER_ZERO,
TI_INTEGER_ONE,
TI_INTEGER_MINUS_ONE,
@@ -1926,8 +1990,11 @@ enum tree_index
TI_UV8HI_TYPE,
TI_UV8QI_TYPE,
TI_UV4HI_TYPE,
+ TI_UV2HI_TYPE,
TI_UV2SI_TYPE,
TI_UV2SF_TYPE,
+ TI_UV2DI_TYPE,
+ TI_UV1DI_TYPE,
TI_UV16QI_TYPE,
TI_V4SF_TYPE,
@@ -1936,8 +2003,12 @@ enum tree_index
TI_V8HI_TYPE,
TI_V8QI_TYPE,
TI_V4HI_TYPE,
+ TI_V2HI_TYPE,
TI_V2SI_TYPE,
TI_V2SF_TYPE,
+ TI_V2DF_TYPE,
+ TI_V2DI_TYPE,
+ TI_V1DI_TYPE,
TI_V16QI_TYPE,
TI_MAIN_IDENTIFIER,
@@ -1945,10 +2016,10 @@ enum tree_index
TI_MAX
};
-extern tree global_trees[TI_MAX];
+extern GTY(()) tree global_trees[TI_MAX];
#define error_mark_node global_trees[TI_ERROR_MARK]
-
+
#define intQI_type_node global_trees[TI_INTQI_TYPE]
#define intHI_type_node global_trees[TI_INTHI_TYPE]
#define intSI_type_node global_trees[TI_INTSI_TYPE]
@@ -2006,7 +2077,10 @@ extern tree global_trees[TI_MAX];
#define unsigned_V8QI_type_node global_trees[TI_UV8QI_TYPE]
#define unsigned_V8HI_type_node global_trees[TI_UV8HI_TYPE]
#define unsigned_V4HI_type_node global_trees[TI_UV4HI_TYPE]
+#define unsigned_V2HI_type_node global_trees[TI_UV2HI_TYPE]
#define unsigned_V2SI_type_node global_trees[TI_UV2SI_TYPE]
+#define unsigned_V2DI_type_node global_trees[TI_UV2DI_TYPE]
+#define unsigned_V1DI_type_node global_trees[TI_UV1DI_TYPE]
#define V16QI_type_node global_trees[TI_V16QI_TYPE]
#define V4SF_type_node global_trees[TI_V4SF_TYPE]
@@ -2014,13 +2088,19 @@ extern tree global_trees[TI_MAX];
#define V8QI_type_node global_trees[TI_V8QI_TYPE]
#define V8HI_type_node global_trees[TI_V8HI_TYPE]
#define V4HI_type_node global_trees[TI_V4HI_TYPE]
+#define V2HI_type_node global_trees[TI_V2HI_TYPE]
#define V2SI_type_node global_trees[TI_V2SI_TYPE]
#define V2SF_type_node global_trees[TI_V2SF_TYPE]
+#define V2DI_type_node global_trees[TI_V2DI_TYPE]
+#define V2DF_type_node global_trees[TI_V2DF_TYPE]
#define V16SF_type_node global_trees[TI_V16SF_TYPE]
+#define V1DI_type_node global_trees[TI_V1DI_TYPE]
/* An enumeration of the standard C integer types. These must be
- ordered so that shorter types appear before longer ones. */
-enum integer_type_kind
+ ordered so that shorter types appear before longer ones, and so
+ that signed types appear before unsigned ones, for the correct
+ functioning of interpret_integer() in c-lex.c. */
+enum integer_type_kind
{
itk_char,
itk_signed_char,
@@ -2040,7 +2120,7 @@ typedef enum integer_type_kind integer_type_kind;
/* The standard C integer types. Use integer_type_kind to index into
this array. */
-extern tree integer_types[itk_none];
+extern GTY(()) tree integer_types[itk_none];
#define char_type_node integer_types[itk_char]
#define signed_char_type_node integer_types[itk_signed_char]
@@ -2053,7 +2133,27 @@ extern tree integer_types[itk_none];
#define long_unsigned_type_node integer_types[itk_unsigned_long]
#define long_long_integer_type_node integer_types[itk_long_long]
#define long_long_unsigned_type_node integer_types[itk_unsigned_long_long]
+
+/* Set to the default thread-local storage (tls) model to use. */
+
+enum tls_model {
+ TLS_MODEL_GLOBAL_DYNAMIC = 1,
+ TLS_MODEL_LOCAL_DYNAMIC,
+ TLS_MODEL_INITIAL_EXEC,
+ TLS_MODEL_LOCAL_EXEC
+};
+
+extern enum tls_model flag_tls_default;
+/* Enumerate visibility settings. */
+
+enum symbol_visibility
+{
+ VISIBILITY_DEFAULT,
+ VISIBILITY_INTERNAL,
+ VISIBILITY_HIDDEN,
+ VISIBILITY_PROTECTED
+};
/* A pointer-to-function member type looks like:
@@ -2088,8 +2188,7 @@ enum ptrmemfunc_vbit_where_t
statistical reports, not code generation. */
extern double approx_sqrt PARAMS ((double));
-extern char *permalloc PARAMS ((int));
-extern char *expralloc PARAMS ((int));
+extern tree decl_assembler_name PARAMS ((tree));
/* Compute the number of bytes occupied by 'node'. This routine only
looks at TREE_CODE and, if the code is TREE_VEC, TREE_VEC_LENGTH. */
@@ -2101,12 +2200,8 @@ extern size_t tree_size PARAMS ((tree));
to zero except for a few of the common fields. */
extern tree make_node PARAMS ((enum tree_code));
-extern tree make_lang_type PARAMS ((enum tree_code));
-extern tree (*make_lang_type_fn) PARAMS ((enum tree_code));
-/* Make a copy of a node, with all the same contents except
- for TREE_PERMANENT. (The copy is permanent
- iff nodes being made now are permanent.) */
+/* Make a copy of a node, with all the same contents. */
extern tree copy_node PARAMS ((tree));
@@ -2144,7 +2239,6 @@ extern tree build_nt PARAMS ((enum tree_code, ...));
extern tree build_int_2_wide PARAMS ((unsigned HOST_WIDE_INT, HOST_WIDE_INT));
extern tree build_vector PARAMS ((tree, tree));
-extern tree build_real PARAMS ((tree, REAL_VALUE_TYPE));
extern tree build_real_from_int_cst PARAMS ((tree, tree));
extern tree build_complex PARAMS ((tree, tree, tree));
extern tree build_string PARAMS ((int, const char *));
@@ -2160,7 +2254,6 @@ extern tree make_signed_type PARAMS ((int));
extern tree make_unsigned_type PARAMS ((int));
extern void initialize_sizetypes PARAMS ((void));
extern void set_sizetype PARAMS ((tree));
-extern tree signed_or_unsigned_type PARAMS ((int, tree));
extern void fixup_unsigned_type PARAMS ((tree));
extern tree build_pointer_type PARAMS ((tree));
extern tree build_reference_type PARAMS ((tree));
@@ -2169,6 +2262,7 @@ extern tree build_index_type PARAMS ((tree));
extern tree build_index_2_type PARAMS ((tree, tree));
extern tree build_array_type PARAMS ((tree, tree));
extern tree build_function_type PARAMS ((tree, tree));
+extern tree build_function_type_list PARAMS ((tree, ...));
extern tree build_method_type PARAMS ((tree, tree));
extern tree build_offset_type PARAMS ((tree, tree));
extern tree build_complex_type PARAMS ((tree));
@@ -2252,8 +2346,6 @@ struct attribute_spec
int flags, bool *no_add_attrs));
};
-extern const struct attribute_spec default_target_attribute_table[];
-
/* Flags that may be passed in the third argument of decl_attributes, and
to handler functions for attributes. */
enum attribute_flags
@@ -2283,11 +2375,8 @@ enum attribute_flags
extern tree merge_decl_attributes PARAMS ((tree, tree));
extern tree merge_type_attributes PARAMS ((tree, tree));
-extern int default_comp_type_attributes PARAMS ((tree, tree));
-extern void default_set_default_type_attributes PARAMS ((tree));
-extern void default_insert_attributes PARAMS ((tree, tree *));
-extern bool default_function_attribute_inlinable_p PARAMS ((tree));
-extern bool default_ms_bitfield_layout_p PARAMS ((tree));
+struct cpp_reader;
+extern void default_register_cpp_builtins PARAMS ((struct cpp_reader *));
/* Split a list of declspecs and attributes into two. */
@@ -2301,7 +2390,7 @@ extern tree strip_attrs PARAMS ((tree));
extern int valid_machine_attribute PARAMS ((tree, tree, tree, tree));
-/* Given a tree node and a string, return non-zero if the tree node is
+/* Given a tree node and a string, return nonzero if the tree node is
a valid attribute name for the string. */
extern int is_attribute_p PARAMS ((const char *, tree));
@@ -2382,6 +2471,8 @@ typedef struct record_layout_info_s
/* The static variables (i.e., class variables, as opposed to
instance variables) encountered in T. */
tree pending_statics;
+ /* Bits remaining in the current alignment group */
+ int remaining_in_alignment;
int packed_maybe_necessary;
} *record_layout_info;
@@ -2401,7 +2492,7 @@ extern tree rli_size_so_far PARAMS ((record_layout_info));
extern void normalize_rli PARAMS ((record_layout_info));
extern void place_field PARAMS ((record_layout_info, tree));
extern void compute_record_mode PARAMS ((tree));
-extern void finish_record_layout PARAMS ((record_layout_info));
+extern void finish_record_layout PARAMS ((record_layout_info, int));
/* Given a hashcode and a ..._TYPE node (for which the hashcode was made),
return a canonicalized ..._TYPE node, so that duplicates are not made.
@@ -2455,7 +2546,7 @@ enum size_type_kind
UBITSIZETYPE, /* Unsifgned representation of sizes in bits. */
TYPE_KIND_LAST};
-extern tree sizetype_tab[(int) TYPE_KIND_LAST];
+extern GTY(()) tree sizetype_tab[(int) TYPE_KIND_LAST];
#define sizetype sizetype_tab[(int) SIZETYPE]
#define bitsizetype sizetype_tab[(int) BITSIZETYPE]
@@ -2493,7 +2584,7 @@ extern void put_pending_sizes PARAMS ((tree));
/* If nonzero, an upper limit on alignment of structure fields, in bits. */
extern unsigned int maximum_field_alignment;
-/* If non-zero, the alignment of a bitstring or (power-)set value, in bits. */
+/* If nonzero, the alignment of a bitstring or (power-)set value, in bits. */
extern unsigned int set_alignment;
/* Concatenate two lists (chains of TREE_LIST nodes) X and Y
@@ -2523,6 +2614,11 @@ extern int list_length PARAMS ((tree));
extern int fields_length PARAMS ((tree));
+/* Given an initializer INIT, return TRUE if INIT is zero or some
+ aggregate of zeros. Otherwise return FALSE. */
+
+extern bool initializer_zerop PARAMS ((tree));
+
/* integer_zerop (tree x) is nonzero if X is an integer constant of value 0 */
extern int integer_zerop PARAMS ((tree));
@@ -2562,6 +2658,10 @@ extern tree save_expr PARAMS ((tree));
extern int first_rtl_op PARAMS ((enum tree_code));
+/* Return which tree structure is used by T. */
+
+enum tree_node_structure_enum tree_node_structure PARAMS ((tree));
+
/* unsave_expr (EXP) returns an expression equivalent to EXP but it
can be used multiple times and will evaluate EXP in its entirety
each time. */
@@ -2573,27 +2673,11 @@ extern tree unsave_expr PARAMS ((tree));
extern void unsave_expr_1 PARAMS ((tree));
-/* Like unsave_expr_1, but recurses into all subtrees. */
-
-extern tree unsave_expr_now PARAMS ((tree));
-
-/* If non-null, these are language-specific helper functions for
- unsave_expr_now. If present, LANG_UNSAVE is called before its
- argument (an UNSAVE_EXPR) is to be unsaved, and all other
- processing in unsave_expr_now is aborted. LANG_UNSAVE_EXPR_NOW is
- called from unsave_expr_1 for language-specific tree codes. */
-extern void (*lang_unsave) PARAMS ((tree *));
-extern void (*lang_unsave_expr_now) PARAMS ((tree));
-
/* Return 0 if it is safe to evaluate EXPR multiple times,
return 1 if it is safe if EXPR is unsaved afterward, or
return 2 if it is completely unsafe. */
extern int unsafe_for_reeval PARAMS ((tree));
-/* If non-null, these are language-specific helper functions for
- unsafe_for_reeval. Return negative to not handle some tree. */
-extern int (*lang_unsafe_for_reeval) PARAMS ((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.
@@ -2648,40 +2732,6 @@ extern tree get_unwidened PARAMS ((tree, tree));
extern tree get_narrower PARAMS ((tree, int *));
-/* Given MODE and UNSIGNEDP, return a suitable type-tree
- with that mode.
- The definition of this resides in language-specific code
- as the repertoire of available types may vary. */
-
-extern tree type_for_mode PARAMS ((enum machine_mode, int));
-
-/* Given PRECISION and UNSIGNEDP, return a suitable type-tree
- for an integer type with at least that precision.
- The definition of this resides in language-specific code
- as the repertoire of available types may vary. */
-
-extern tree type_for_size PARAMS ((unsigned, int));
-
-/* Given an integer type T, return a type like T but unsigned.
- If T is unsigned, the value is T.
- The definition of this resides in language-specific code
- as the repertoire of available types may vary. */
-
-extern tree unsigned_type PARAMS ((tree));
-
-/* Given an integer type T, return a type like T but signed.
- If T is signed, the value is T.
- The definition of this resides in language-specific code
- as the repertoire of available types may vary. */
-
-extern tree signed_type PARAMS ((tree));
-
-/* This function must be defined in the language-specific files.
- expand_expr calls it to build the cleanup-expression for a TARGET_EXPR.
- This is defined in a language-specific file. */
-
-extern tree maybe_build_cleanup PARAMS ((tree));
-
/* Given an expression EXP that may be a COMPONENT_REF or an ARRAY_REF,
look for nested component-refs or array-refs at constant positions
and find the ultimate containing object, which is returned. */
@@ -2739,38 +2789,22 @@ extern int immediate_size_expand;
/* Points to the FUNCTION_DECL of the function whose body we are reading. */
-extern tree current_function_decl;
+extern GTY(()) tree current_function_decl;
/* Nonzero means a FUNC_BEGIN label was emitted. */
-extern tree current_function_func_begin_label;
+extern GTY(()) tree current_function_func_begin_label;
/* Nonzero means all ..._TYPE nodes should be allocated permanently. */
extern int all_types_permanent;
-/* 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 const char *(*decl_printable_name) PARAMS ((tree, int));
-
-/* Pointer to function to finish handling an incomplete decl at the
- end of compilation. */
-
-extern void (*incomplete_decl_finalize_hook) PARAMS ((tree));
-
/* Declare a predefined function. Return the declaration. This function is
provided by each language frontend. */
-extern tree builtin_function PARAMS ((const char *, tree, int,
- enum built_in_class,
- const char *));
+extern tree builtin_function PARAMS ((const char *, tree, int,
+ enum built_in_class,
+ const char *, tree));
/* In tree.c */
-extern char *perm_calloc PARAMS ((int, long));
extern void clean_symbol_name PARAMS ((char *));
extern tree get_file_function_name_long PARAMS ((const char *));
extern tree get_set_constructor_bits PARAMS ((tree, char *, int));
@@ -2779,6 +2813,8 @@ extern tree get_set_constructor_bytes PARAMS ((tree,
extern tree get_callee_fndecl PARAMS ((tree));
extern void set_decl_assembler_name PARAMS ((tree));
extern int type_num_arguments PARAMS ((tree));
+extern tree lhd_unsave_expr_now PARAMS ((tree));
+
/* In stmt.c */
@@ -2883,42 +2919,8 @@ extern void rrotate_double PARAMS ((unsigned HOST_WIDE_INT, HOST_WIDE_INT,
extern int operand_equal_p PARAMS ((tree, tree, int));
extern tree invert_truthvalue PARAMS ((tree));
-/* In builtins.c. Given a type, apply default promotions wrt unnamed
- function arguments and return the new type. Return NULL_TREE if no
- change. Required by any language that supports variadic arguments. */
-
-extern tree (*lang_type_promotes_to) PARAMS ((tree));
extern tree fold_builtin PARAMS ((tree));
-/* The language front-end must define these functions. */
-
-/* Function to replace the DECL_LANG_SPECIFIC field of a DECL with a copy. */
-extern void copy_lang_decl PARAMS ((tree));
-
-/* Function called with no arguments to parse and compile the input. */
-extern int yyparse PARAMS ((void));
-/* Functions for processing symbol declarations. */
-/* Function to enter a new lexical scope.
- Takes one argument: always zero when called from outside the front end. */
-extern void pushlevel PARAMS ((int));
-/* Function to exit a lexical scope. It returns a BINDING for that scope.
- Takes three arguments:
- KEEP -- nonzero if there were declarations in this scope.
- REVERSE -- reverse the order of decls before returning them.
- FUNCTIONBODY -- nonzero if this level is the body of a function. */
-extern tree poplevel PARAMS ((int, int, int));
-/* Set the BLOCK node for the current scope level. */
-extern void set_block PARAMS ((tree));
-/* Function to add a decl to the current scope level.
- Takes one argument, a decl to add.
- Returns that decl, or, if the same symbol is already declared, may
- return a different decl for that name. */
-extern tree pushdecl PARAMS ((tree));
-/* Function to return the chain of decls so far in the current scope level. */
-extern tree getdecls PARAMS ((void));
-/* Function to return the chain of structure tags in the current scope level. */
-extern tree gettags PARAMS ((void));
-
extern tree build_range_type PARAMS ((tree, tree, tree));
/* In alias.c */
@@ -2929,13 +2931,6 @@ extern int alias_sets_conflict_p PARAMS ((HOST_WIDE_INT,
extern int readonly_fields_p PARAMS ((tree));
extern int objects_must_conflict_p PARAMS ((tree, tree));
-/* Set the DECL_ASSEMBLER_NAME for a node. If it is the sort of thing
- that the assembler should talk about, set DECL_ASSEMBLER_NAME to an
- appropriate IDENTIFIER_NODE. Otherwise, set it to the
- ERROR_MARK_NODE to ensure that the assembler does not talk about
- it. */
-extern void (*lang_set_decl_assembler_name) PARAMS ((tree));
-
struct obstack;
/* In tree.c */
@@ -2944,9 +2939,6 @@ extern int int_fits_type_p PARAMS ((tree, tree));
extern bool variably_modified_type_p PARAMS ((tree));
extern int tree_log2 PARAMS ((tree));
extern int tree_floor_log2 PARAMS ((tree));
-extern void preserve_data PARAMS ((void));
-extern int object_permanent_p PARAMS ((tree));
-extern int type_precision PARAMS ((tree));
extern int simple_cst_equal PARAMS ((tree, tree));
extern int compare_tree_int PARAMS ((tree,
unsigned HOST_WIDE_INT));
@@ -2972,23 +2964,22 @@ extern void expand_pending_sizes PARAMS ((tree));
extern int real_onep PARAMS ((tree));
extern int real_twop PARAMS ((tree));
+extern int real_minus_onep PARAMS ((tree));
extern void gcc_obstack_init PARAMS ((struct obstack *));
-extern void init_obstacks PARAMS ((void));
+extern void init_ttree PARAMS ((void));
extern void build_common_tree_nodes PARAMS ((int));
extern void build_common_tree_nodes_2 PARAMS ((int));
-extern void mark_tree_hashtable PARAMS ((void *));
/* In function.c */
extern void setjmp_protect_args PARAMS ((void));
extern void setjmp_protect PARAMS ((tree));
extern void expand_main_function PARAMS ((void));
-extern void mark_varargs PARAMS ((void));
extern void init_dummy_function_start PARAMS ((void));
extern void expand_dummy_function_end PARAMS ((void));
extern void init_function_for_compilation PARAMS ((void));
extern void init_function_start PARAMS ((tree, const char *, int));
extern void assign_parms PARAMS ((tree));
-extern void put_var_into_stack PARAMS ((tree));
+extern void put_var_into_stack PARAMS ((tree, int));
extern void flush_addressof PARAMS ((tree));
extern void uninitialized_vars_warning PARAMS ((tree));
extern void setjmp_args_warning PARAMS ((void));
@@ -3009,7 +3000,6 @@ extern void push_function_context PARAMS ((void));
extern void pop_function_context PARAMS ((void));
extern void push_function_context_to PARAMS ((tree));
extern void pop_function_context_from PARAMS ((tree));
-extern void ggc_mark_struct_function PARAMS ((struct function *));
/* In print-rtl.c */
#ifdef BUFSIZ
@@ -3039,6 +3029,7 @@ extern rtx emit_line_note PARAMS ((const char *, int));
/* In calls.c */
extern int setjmp_call_p PARAMS ((tree));
+extern bool alloca_call_p PARAMS ((tree));
/* In attribs.c. */
@@ -3052,30 +3043,6 @@ extern int setjmp_call_p PARAMS ((tree));
a decl attribute to the declaration rather than to its type). */
extern tree decl_attributes PARAMS ((tree *, tree, int));
-/* The following function must be provided by front ends
- using attribs.c. */
-
-/* Possibly apply default attributes to a function (represented by
- a FUNCTION_DECL). */
-extern void insert_default_attributes PARAMS ((tree));
-
-/* Table of machine-independent attributes for checking formats, if used. */
-extern const struct attribute_spec *format_attribute_table;
-
-/* Table of machine-independent attributes for a particular language. */
-extern const struct attribute_spec *lang_attribute_table;
-
-/* Flag saying whether common language attributes are to be supported. */
-extern int lang_attribute_common;
-
-/* In front end. */
-
-extern int mark_addressable PARAMS ((tree));
-extern void incomplete_type_error PARAMS ((tree, tree));
-extern tree truthvalue_conversion PARAMS ((tree));
-extern int global_bindings_p PARAMS ((void));
-extern void insert_block PARAMS ((tree));
-
/* In integrate.c */
extern void save_for_inline PARAMS ((tree));
extern void set_decl_abstract_flags PARAMS ((tree, int));
@@ -3091,6 +3058,8 @@ extern void make_decl_rtl PARAMS ((tree, const char *));
extern void make_decl_one_only PARAMS ((tree));
extern int supports_one_only PARAMS ((void));
extern void variable_section PARAMS ((tree, int));
+enum tls_model decl_tls_model PARAMS ((tree));
+enum symbol_visibility decl_visibility PARAMS ((tree));
/* In fold-const.c */
extern int div_and_round_double PARAMS ((enum tree_code, int,
@@ -3112,7 +3081,6 @@ extern bool parse_output_constraint PARAMS ((const char **,
extern void expand_asm_operands PARAMS ((tree, tree, tree, tree, int,
const char *, int));
extern int any_pending_cleanups PARAMS ((int));
-extern void init_stmt PARAMS ((void));
extern void init_stmt_for_function PARAMS ((void));
extern int drop_through_at_end_p PARAMS ((void));
extern void expand_start_target_temps PARAMS ((void));
@@ -3130,6 +3098,7 @@ extern tree case_index_expr_type PARAMS ((void));
extern HOST_WIDE_INT all_cases_count PARAMS ((tree, int *));
extern void check_for_full_enumeration_handling PARAMS ((tree));
extern void declare_nonlocal_label PARAMS ((tree));
+extern void default_flag_random_seed PARAMS ((void));
/* If KIND=='I', return a suitable global initializer (constructor) name.
If KIND=='D', return a suitable global clean-up (destructor) name. */
@@ -3211,3 +3180,5 @@ extern const char *dump_flag_name PARAMS ((enum tree_dump_index));
extern void fancy_abort PARAMS ((const char *, int, const char *))
ATTRIBUTE_NORETURN;
#define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)
+
+#endif /* GCC_TREE_H */
diff --git a/contrib/gcc/tsystem.h b/contrib/gcc/tsystem.h
index 97333bb..5b81e48 100644
--- a/contrib/gcc/tsystem.h
+++ b/contrib/gcc/tsystem.h
@@ -19,6 +19,14 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
+/* 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. */
+
+
#ifndef GCC_TSYSTEM_H
#define GCC_TSYSTEM_H
@@ -33,8 +41,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define HAVE_DECL_GETOPT 1
#endif
-/* GCC supplies this header. */
+/* GCC supplies these headers. */
#include <stddef.h>
+#include <float.h>
#ifdef inhibit_libc
diff --git a/contrib/gcc/unroll.c b/contrib/gcc/unroll.c
index 83327c7..7f5a983 100644
--- a/contrib/gcc/unroll.c
+++ b/contrib/gcc/unroll.c
@@ -147,6 +147,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "hard-reg-set.h"
#include "basic-block.h"
#include "predict.h"
+#include "params.h"
/* The prime factors looked for when trying to unroll a loop by some
number which is modulo the total number of iterations. Just checking
@@ -169,14 +170,7 @@ enum unroll_types
UNROLL_NAIVE
};
-/* This controls which loops are unrolled, and by how much we unroll
- them. */
-
-#ifndef MAX_UNROLLED_INSNS
-#define MAX_UNROLLED_INSNS 100
-#endif
-
-/* Indexed by register number, if non-zero, then it contains a pointer
+/* Indexed by register number, if nonzero, then it contains a pointer
to a struct induction for a DEST_REG giv which has been combined with
one of more address givs. This is needed because whenever such a DEST_REG
giv is modified, we must modify the value of all split address givs
@@ -199,6 +193,9 @@ static int *splittable_regs_updates;
/* Forward declarations. */
+static rtx simplify_cmp_and_jump_insns PARAMS ((enum rtx_code,
+ enum machine_mode,
+ rtx, rtx, rtx));
static void init_reg_map PARAMS ((struct inline_remap *, int));
static rtx calculate_giv_inc PARAMS ((rtx, rtx, unsigned int));
static rtx initial_reg_note_copy PARAMS ((rtx, struct inline_remap *));
@@ -213,7 +210,6 @@ static int find_splittable_givs PARAMS ((const struct loop *,
rtx, int));
static int reg_dead_after_loop PARAMS ((const struct loop *, rtx));
static rtx fold_rtx_mult_add PARAMS ((rtx, rtx, rtx, enum machine_mode));
-static int verify_addresses PARAMS ((struct induction *, rtx, int));
static rtx remap_split_bivs PARAMS ((struct loop *, rtx));
static rtx find_common_reg_term PARAMS ((rtx, rtx));
static rtx subtract_reg_term PARAMS ((rtx, rtx));
@@ -274,53 +270,6 @@ unroll_loop (loop, insn_count, strength_reduce_p)
return;
}
- /* When emitting debugger info, we can't unroll loops with unequal numbers
- of block_beg and block_end notes, because that would unbalance the block
- structure of the function. This can happen as a result of the
- "if (foo) bar; else break;" optimization in jump.c. */
- /* ??? Gcc has a general policy that -g is never supposed to change the code
- that the compiler emits, so we must disable this optimization always,
- even if debug info is not being output. This is rare, so this should
- not be a significant performance problem. */
-
- if (1 /* write_symbols != NO_DEBUG */)
- {
- int block_begins = 0;
- int block_ends = 0;
-
- for (insn = loop_start; insn != loop_end; insn = NEXT_INSN (insn))
- {
- if (GET_CODE (insn) == NOTE)
- {
- if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
- block_begins++;
- else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
- block_ends++;
- if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
- || NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
- {
- /* Note, would be nice to add code to unroll EH
- regions, but until that time, we punt (don't
- unroll). For the proper way of doing it, see
- expand_inline_function. */
-
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Unrolling failure: cannot unroll EH regions.\n");
- return;
- }
- }
- }
-
- if (block_begins != block_ends)
- {
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Unrolling failure: Unbalanced block notes.\n");
- return;
- }
- }
-
/* Determine type of unroll to perform. Depends on the number of iterations
and the size of the loop. */
@@ -353,9 +302,11 @@ unroll_loop (loop, insn_count, strength_reduce_p)
jump to the loop condition. Make sure to delete the jump
insn, otherwise the loop body will never execute. */
+ /* FIXME this actually checks for a jump to the continue point, which
+ is not the same as the condition in a for loop. As a result, this
+ optimization fails for most for loops. We should really use flow
+ information rather than instruction pattern matching. */
rtx ujump = ujump_to_loop_cont (loop->start, loop->cont);
- if (ujump)
- delete_related_insns (ujump);
/* If number of iterations is exactly 1, then eliminate the compare and
branch at the end of the loop since they will never be taken.
@@ -367,9 +318,10 @@ unroll_loop (loop, insn_count, strength_reduce_p)
if (GET_CODE (last_loop_insn) == BARRIER)
{
/* Delete the jump insn. This will delete the barrier also. */
- delete_related_insns (PREV_INSN (last_loop_insn));
+ last_loop_insn = PREV_INSN (last_loop_insn);
}
- else if (GET_CODE (last_loop_insn) == JUMP_INSN)
+
+ if (ujump && GET_CODE (last_loop_insn) == JUMP_INSN)
{
#ifdef HAVE_cc0
rtx prev = PREV_INSN (last_loop_insn);
@@ -381,24 +333,27 @@ unroll_loop (loop, insn_count, strength_reduce_p)
if (only_sets_cc0_p (prev))
delete_related_insns (prev);
#endif
- }
- /* Remove the loop notes since this is no longer a loop. */
- if (loop->vtop)
- delete_related_insns (loop->vtop);
- if (loop->cont)
- delete_related_insns (loop->cont);
- if (loop_start)
- delete_related_insns (loop_start);
- if (loop_end)
- delete_related_insns (loop_end);
+ delete_related_insns (ujump);
- return;
+ /* Remove the loop notes since this is no longer a loop. */
+ if (loop->vtop)
+ delete_related_insns (loop->vtop);
+ if (loop->cont)
+ delete_related_insns (loop->cont);
+ if (loop_start)
+ delete_related_insns (loop_start);
+ if (loop_end)
+ delete_related_insns (loop_end);
+
+ return;
+ }
}
- else if (loop_info->n_iterations > 0
- /* Avoid overflow in the next expression. */
- && loop_info->n_iterations < MAX_UNROLLED_INSNS
- && loop_info->n_iterations * insn_count < MAX_UNROLLED_INSNS)
+
+ if (loop_info->n_iterations > 0
+ /* Avoid overflow in the next expression. */
+ && loop_info->n_iterations < (unsigned) MAX_UNROLLED_INSNS
+ && loop_info->n_iterations * insn_count < (unsigned) MAX_UNROLLED_INSNS)
{
unroll_number = loop_info->n_iterations;
unroll_type = UNROLL_COMPLETELY;
@@ -428,7 +383,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
for (i = 3; i >= 0; i--)
while (factors[i].count--)
{
- if (temp * factors[i].factor < MAX_UNROLLED_INSNS)
+ if (temp * factors[i].factor < (unsigned) MAX_UNROLLED_INSNS)
{
unroll_number *= factors[i].factor;
temp *= factors[i].factor;
@@ -837,9 +792,9 @@ unroll_loop (loop, insn_count, strength_reduce_p)
/* We must limit the generic test to max_reg_before_loop, because only
these pseudo registers have valid regno_first_uid info. */
for (r = FIRST_PSEUDO_REGISTER; r < max_reg_before_loop; ++r)
- if (REGNO_FIRST_UID (r) > 0 && REGNO_FIRST_UID (r) <= max_uid_for_loop
+ if (REGNO_FIRST_UID (r) > 0 && REGNO_FIRST_UID (r) < max_uid_for_loop
&& REGNO_FIRST_LUID (r) >= copy_start_luid
- && REGNO_LAST_UID (r) > 0 && REGNO_LAST_UID (r) <= max_uid_for_loop
+ && REGNO_LAST_UID (r) > 0 && REGNO_LAST_UID (r) < max_uid_for_loop
&& REGNO_LAST_LUID (r) <= copy_end_luid)
{
/* However, we must also check for loop-carried dependencies.
@@ -897,7 +852,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
&initial_value, &final_value, &increment,
&mode))
{
- rtx diff;
+ rtx diff, insn;
rtx *labels;
int abs_inc, neg_inc;
enum rtx_code cc = loop_info->comparison_code;
@@ -929,26 +884,20 @@ unroll_loop (loop, insn_count, strength_reduce_p)
start_sequence ();
+ /* We must copy the final and initial values here to avoid
+ improperly shared rtl. */
+ final_value = copy_rtx (final_value);
+ initial_value = copy_rtx (initial_value);
+
/* Final value may have form of (PLUS val1 const1_rtx). We need
to convert it into general operand, so compute the real value. */
- if (GET_CODE (final_value) == PLUS)
- {
- final_value = expand_simple_binop (mode, PLUS,
- copy_rtx (XEXP (final_value, 0)),
- copy_rtx (XEXP (final_value, 1)),
- NULL_RTX, 0, OPTAB_LIB_WIDEN);
- }
+ final_value = force_operand (final_value, NULL_RTX);
if (!nonmemory_operand (final_value, VOIDmode))
- final_value = force_reg (mode, copy_rtx (final_value));
+ final_value = force_reg (mode, final_value);
/* Calculate the difference between the final and initial values.
Final value may be a (plus (reg x) (const_int 1)) rtx.
- Let the following cse pass simplify this if initial value is
- a constant.
-
- We must copy the final and initial values here to avoid
- improperly shared rtl.
We have to deal with for (i = 0; --i < 6;) type loops.
For such loops the real final value is the first time the
@@ -961,18 +910,18 @@ unroll_loop (loop, insn_count, strength_reduce_p)
so we can pretend that the overflow value is 0/~0. */
if (cc == NE || less_p != neg_inc)
- diff = expand_simple_binop (mode, MINUS, final_value,
- copy_rtx (initial_value), NULL_RTX, 0,
- OPTAB_LIB_WIDEN);
+ diff = simplify_gen_binary (MINUS, mode, final_value,
+ initial_value);
else
- diff = expand_simple_unop (mode, neg_inc ? NOT : NEG,
- copy_rtx (initial_value), NULL_RTX, 0);
+ diff = simplify_gen_unary (neg_inc ? NOT : NEG, mode,
+ initial_value, mode);
+ diff = force_operand (diff, NULL_RTX);
/* Now calculate (diff % (unroll * abs (increment))) by using an
and instruction. */
- diff = expand_simple_binop (GET_MODE (diff), AND, diff,
- GEN_INT (unroll_number * abs_inc - 1),
- NULL_RTX, 0, OPTAB_LIB_WIDEN);
+ diff = simplify_gen_binary (AND, mode, diff,
+ GEN_INT (unroll_number*abs_inc - 1));
+ diff = force_operand (diff, NULL_RTX);
/* Now emit a sequence of branches to jump to the proper precond
loop entry point. */
@@ -990,18 +939,22 @@ unroll_loop (loop, insn_count, strength_reduce_p)
if (cc != NE)
{
rtx incremented_initval;
- incremented_initval = expand_simple_binop (mode, PLUS,
- initial_value,
- increment,
- NULL_RTX, 0,
- OPTAB_LIB_WIDEN);
- emit_cmp_and_jump_insns (incremented_initval, final_value,
- less_p ? GE : LE, NULL_RTX,
- mode, unsigned_p, labels[1]);
- predict_insn_def (get_last_insn (), PRED_LOOP_CONDITION,
- TAKEN);
- JUMP_LABEL (get_last_insn ()) = labels[1];
- LABEL_NUSES (labels[1])++;
+ enum rtx_code cmp_code;
+
+ incremented_initval
+ = simplify_gen_binary (PLUS, mode, initial_value, increment);
+ incremented_initval
+ = force_operand (incremented_initval, NULL_RTX);
+
+ cmp_code = (less_p
+ ? (unsigned_p ? GEU : GE)
+ : (unsigned_p ? LEU : LE));
+
+ insn = simplify_cmp_and_jump_insns (cmp_code, mode,
+ incremented_initval,
+ final_value, labels[1]);
+ if (insn)
+ predict_insn_def (insn, PRED_LOOP_CONDITION, TAKEN);
}
/* Assuming the unroll_number is 4, and the increment is 2, then
@@ -1040,12 +993,12 @@ unroll_loop (loop, insn_count, strength_reduce_p)
cmp_code = LE;
}
- emit_cmp_and_jump_insns (diff, GEN_INT (abs_inc * cmp_const),
- cmp_code, NULL_RTX, mode, 0, labels[i]);
- JUMP_LABEL (get_last_insn ()) = labels[i];
- LABEL_NUSES (labels[i])++;
- predict_insn (get_last_insn (), PRED_LOOP_PRECONDITIONING,
- REG_BR_PROB_BASE / (unroll_number - i));
+ insn = simplify_cmp_and_jump_insns (cmp_code, mode, diff,
+ GEN_INT (abs_inc*cmp_const),
+ labels[i]);
+ if (insn)
+ predict_insn (insn, PRED_LOOP_PRECONDITIONING,
+ REG_BR_PROB_BASE / (unroll_number - i));
}
/* If the increment is greater than one, then we need another branch,
@@ -1073,13 +1026,11 @@ unroll_loop (loop, insn_count, strength_reduce_p)
cmp_code = GE;
}
- emit_cmp_and_jump_insns (diff, GEN_INT (cmp_const), cmp_code,
- NULL_RTX, mode, 0, labels[0]);
- JUMP_LABEL (get_last_insn ()) = labels[0];
- LABEL_NUSES (labels[0])++;
+ simplify_cmp_and_jump_insns (cmp_code, mode, diff,
+ GEN_INT (cmp_const), labels[0]);
}
- sequence = gen_sequence ();
+ sequence = get_insns ();
end_sequence ();
loop_insn_hoist (loop, sequence);
@@ -1191,6 +1142,9 @@ unroll_loop (loop, insn_count, strength_reduce_p)
/* And whether the loop has been preconditioned. */
loop_info->preconditioned = loop_preconditioned;
+ /* Remember whether it was preconditioned for the second loop pass. */
+ NOTE_PRECONDITIONED (loop->end) = loop_preconditioned;
+
/* For each biv and giv, determine whether it can be safely split into
a different variable for each unrolled copy of the loop body.
We precalculate and save this info here, since computing it is
@@ -1378,6 +1332,43 @@ unroll_loop (loop, insn_count, strength_reduce_p)
free (map->reg_map);
free (map);
}
+
+/* A helper function for unroll_loop. Emit a compare and branch to
+ satisfy (CMP OP1 OP2), but pass this through the simplifier first.
+ If the branch turned out to be conditional, return it, otherwise
+ return NULL. */
+
+static rtx
+simplify_cmp_and_jump_insns (code, mode, op0, op1, label)
+ enum rtx_code code;
+ enum machine_mode mode;
+ rtx op0, op1, label;
+{
+ rtx t, insn;
+
+ t = simplify_relational_operation (code, mode, op0, op1);
+ if (!t)
+ {
+ enum rtx_code scode = signed_condition (code);
+ emit_cmp_and_jump_insns (op0, op1, scode, NULL_RTX, mode,
+ code != scode, label);
+ insn = get_last_insn ();
+
+ JUMP_LABEL (insn) = label;
+ LABEL_NUSES (label) += 1;
+
+ return insn;
+ }
+ else if (t == const_true_rtx)
+ {
+ insn = emit_jump_insn (gen_jump (label));
+ emit_barrier ();
+ JUMP_LABEL (insn) = label;
+ LABEL_NUSES (label) += 1;
+ }
+
+ return NULL_RTX;
+}
/* Return true if the loop can be safely, and profitably, preconditioned
so that the unrolled copies of the loop body don't need exit tests.
@@ -1636,15 +1627,17 @@ calculate_giv_inc (pattern, src_insn, regno)
}
else if (GET_CODE (increment) == IOR
+ || GET_CODE (increment) == PLUS
|| GET_CODE (increment) == ASHIFT
- || GET_CODE (increment) == PLUS)
+ || GET_CODE (increment) == LSHIFTRT)
{
/* The rs6000 port loads some constants with IOR.
- The alpha port loads some constants with ASHIFT and PLUS. */
+ The alpha port loads some constants with ASHIFT and PLUS.
+ The sparc64 port loads some constants with LSHIFTRT. */
rtx second_part = XEXP (increment, 1);
enum rtx_code code = GET_CODE (increment);
- increment = find_last_value (XEXP (increment, 0),
+ increment = find_last_value (XEXP (increment, 0),
&src_insn, NULL_RTX, 0);
/* Don't need the last insn anymore. */
delete_related_insns (get_last_insn ());
@@ -1657,8 +1650,10 @@ calculate_giv_inc (pattern, src_insn, regno)
increment = GEN_INT (INTVAL (increment) | INTVAL (second_part));
else if (code == PLUS)
increment = GEN_INT (INTVAL (increment) + INTVAL (second_part));
- else
+ else if (code == ASHIFT)
increment = GEN_INT (INTVAL (increment) << INTVAL (second_part));
+ else
+ increment = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (increment) >> INTVAL (second_part));
}
if (GET_CODE (increment) != CONST_INT)
@@ -1741,7 +1736,7 @@ final_reg_note_copy (notesp, map)
while (*notesp)
{
rtx note = *notesp;
-
+
if (GET_CODE (note) == INSN_LIST)
{
/* Sometimes, we have a REG_WAS_0 note that points to a
@@ -1814,12 +1809,6 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
start_sequence ();
- /* Emit a NOTE_INSN_DELETED to force at least two insns onto the sequence.
- Else gen_sequence could return a raw pattern for a jump which we pass
- off to emit_insn_before (instead of emit_jump_insn_before) which causes
- a variety of losing behaviors later. */
- emit_note (0, NOTE_INSN_DELETED);
-
insn = copy_start;
do
{
@@ -2055,6 +2044,14 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
copy = emit_insn (pattern);
}
REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);
+ INSN_SCOPE (copy) = INSN_SCOPE (insn);
+
+ /* If there is a REG_EQUAL note present whose value
+ is not loop invariant, then delete it, since it
+ may cause problems with later optimization passes. */
+ if ((tem = find_reg_note (copy, REG_EQUAL, NULL_RTX))
+ && !loop_invariant_p (loop, XEXP (tem, 0)))
+ remove_note (copy, tem);
#ifdef HAVE_cc0
/* If this insn is setting CC0, it may need to look at
@@ -2101,6 +2098,7 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
pattern = copy_rtx_and_substitute (PATTERN (insn), map, 0);
copy = emit_jump_insn (pattern);
REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);
+ INSN_SCOPE (copy) = INSN_SCOPE (insn);
if (JUMP_LABEL (insn))
{
@@ -2224,7 +2222,9 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
pattern = copy_rtx_and_substitute (PATTERN (insn), map, 0);
copy = emit_call_insn (pattern);
REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);
+ INSN_SCOPE (copy) = INSN_SCOPE (insn);
SIBLING_CALL_P (copy) = SIBLING_CALL_P (insn);
+ CONST_OR_PURE_CALL_P (copy) = CONST_OR_PURE_CALL_P (insn);
/* Because the USAGE information potentially contains objects other
than hard registers, we need to copy it. */
@@ -2315,15 +2315,15 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
{
/* VTOP notes are valid only before the loop exit test.
If placed anywhere else, loop may generate bad code.
- There is no need to test for NOTE_INSN_LOOP_CONT notes
- here, since COPY_NOTES_FROM will be at most one or two (for cc0)
- instructions before the last insn in the loop, and if the
- end test is that short, there will be a VTOP note between
- the CONT note and the test. */
+ Although COPY_NOTES_FROM will be at most one or two (for cc0)
+ instructions before the last insn in the loop, COPY_NOTES_FROM
+ can be a NOTE_INSN_LOOP_CONT note if there is no VTOP note,
+ as in a do .. while loop. */
if (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
- && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP)
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP
+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_CONT)
emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
}
}
@@ -2331,7 +2331,7 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
if (final_label && LABEL_NUSES (final_label) > 0)
emit_label (final_label);
- tem = gen_sequence ();
+ tem = get_insns ();
end_sequence ();
loop_insn_emit_before (loop, 0, insert_before, tem);
}
@@ -2476,7 +2476,8 @@ biv_total_increment (bl)
for (v = bl->biv; v; v = v->next_iv)
{
if (v->always_computable && v->mult_val == const1_rtx
- && ! v->maybe_multiple)
+ && ! v->maybe_multiple
+ && SCALAR_INT_MODE_P (v->mode))
result = fold_rtx_mult_add (result, const1_rtx, v->add_val, v->mode);
else
return 0;
@@ -2538,7 +2539,7 @@ find_splittable_regs (loop, unroll_type, unroll_number)
it is unsafe to split the biv since it may not have the proper
value on loop exit. */
- /* loop_number_exit_count is non-zero if the loop has an exit other than
+ /* loop_number_exit_count is nonzero if the loop has an exit other than
a fall through at the end. */
biv_splittable = 1;
@@ -2563,7 +2564,7 @@ find_splittable_regs (loop, unroll_type, unroll_number)
|| GET_CODE (SET_SRC (tem)) != PLUS)
biv_splittable = 0;
- /* If final value is non-zero, then must emit an instruction which sets
+ /* If final value is nonzero, then must emit an instruction which sets
the value of the biv to the proper value. This is done after
handling all of the givs, since some of them may need to use the
biv's value in their initialization code. */
@@ -2588,7 +2589,7 @@ find_splittable_regs (loop, unroll_type, unroll_number)
rtx tem = gen_reg_rtx (bl->biv->mode);
record_base_value (REGNO (tem), bl->biv->add_val, 0);
- loop_insn_hoist (loop,
+ loop_insn_hoist (loop,
gen_move_insn (tem, bl->biv->src_reg));
if (loop_dump_stream)
@@ -2623,7 +2624,7 @@ find_splittable_regs (loop, unroll_type, unroll_number)
result += find_splittable_givs (loop, bl, unroll_type, increment,
unroll_number);
- /* If final value is non-zero, then must emit an instruction which sets
+ /* If final value is nonzero, then must emit an instruction which sets
the value of the biv to the proper value. This is done after
handling all of the givs, since some of them may need to use the
biv's value in their initialization code. */
@@ -2663,35 +2664,6 @@ find_splittable_regs (loop, unroll_type, unroll_number)
return result;
}
-/* Return 1 if the first and last unrolled copy of the address giv V is valid
- for the instruction that is using it. Do not make any changes to that
- instruction. */
-
-static int
-verify_addresses (v, giv_inc, unroll_number)
- struct induction *v;
- rtx giv_inc;
- int unroll_number;
-{
- int ret = 1;
- rtx orig_addr = *v->location;
- rtx last_addr = plus_constant (v->dest_reg,
- INTVAL (giv_inc) * (unroll_number - 1));
-
- /* First check to see if either address would fail. Handle the fact
- that we have may have a match_dup. */
- if (! validate_replace_rtx (*v->location, v->dest_reg, v->insn)
- || ! validate_replace_rtx (*v->location, last_addr, v->insn))
- ret = 0;
-
- /* Now put things back the way they were before. This should always
- succeed. */
- if (! validate_replace_rtx (*v->location, orig_addr, v->insn))
- abort ();
-
- return ret;
-}
-
/* For every giv based on the biv BL, check to determine whether it is
splittable. This is a subroutine to find_splittable_regs ().
@@ -2703,7 +2675,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
struct iv_class *bl;
enum unroll_types unroll_type;
rtx increment;
- int unroll_number;
+ int unroll_number ATTRIBUTE_UNUSED;
{
struct loop_ivs *ivs = LOOP_IVS (loop);
struct induction *v, *v2;
@@ -2781,7 +2753,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
/* Should emit insns after the loop if possible, as the biv final value
code below does. */
- /* If the final value is non-zero, and the giv has not been reduced,
+ /* If the final value is nonzero, and the giv has not been reduced,
then must emit an instruction to set the final value. */
if (final_value && !v->new_reg)
{
@@ -2874,203 +2846,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
splittable_regs[reg_or_subregno (v->new_reg)] = value;
}
else
- {
- /* Splitting address givs is useful since it will often allow us
- to eliminate some increment insns for the base giv as
- unnecessary. */
-
- /* If the addr giv is combined with a dest_reg giv, then all
- references to that dest reg will be remapped, which is NOT
- what we want for split addr regs. We always create a new
- register for the split addr giv, just to be safe. */
-
- /* If we have multiple identical address givs within a
- single instruction, then use a single pseudo reg for
- both. This is necessary in case one is a match_dup
- of the other. */
-
- v->const_adjust = 0;
-
- if (v->same_insn)
- {
- v->dest_reg = v->same_insn->dest_reg;
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Sharing address givs in insn %d\n",
- INSN_UID (v->insn));
- }
- /* If multiple address GIVs have been combined with the
- same dest_reg GIV, do not create a new register for
- each. */
- else if (unroll_type != UNROLL_COMPLETELY
- && v->giv_type == DEST_ADDR
- && v->same && v->same->giv_type == DEST_ADDR
- && v->same->unrolled
- /* combine_givs_p may return true for some cases
- where the add and mult values are not equal.
- To share a register here, the values must be
- equal. */
- && rtx_equal_p (v->same->mult_val, v->mult_val)
- && rtx_equal_p (v->same->add_val, v->add_val)
- /* If the memory references have different modes,
- then the address may not be valid and we must
- not share registers. */
- && verify_addresses (v, giv_inc, unroll_number))
- {
- v->dest_reg = v->same->dest_reg;
- v->shared = 1;
- }
- else if (unroll_type != UNROLL_COMPLETELY)
- {
- /* If not completely unrolling the loop, then create a new
- register to hold the split value of the DEST_ADDR giv.
- Emit insn to initialize its value before loop start. */
-
- rtx tem = gen_reg_rtx (v->mode);
- struct induction *same = v->same;
- rtx new_reg = v->new_reg;
- record_base_value (REGNO (tem), v->add_val, 0);
-
- /* If the address giv has a constant in its new_reg value,
- then this constant can be pulled out and put in value,
- instead of being part of the initialization code. */
-
- if (GET_CODE (new_reg) == PLUS
- && GET_CODE (XEXP (new_reg, 1)) == CONST_INT)
- {
- v->dest_reg
- = plus_constant (tem, INTVAL (XEXP (new_reg, 1)));
-
- /* Only succeed if this will give valid addresses.
- Try to validate both the first and the last
- address resulting from loop unrolling, if
- one fails, then can't do const elim here. */
- if (verify_addresses (v, giv_inc, unroll_number))
- {
- /* Save the negative of the eliminated const, so
- that we can calculate the dest_reg's increment
- value later. */
- v->const_adjust = -INTVAL (XEXP (new_reg, 1));
-
- new_reg = XEXP (new_reg, 0);
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Eliminating constant from giv %d\n",
- REGNO (tem));
- }
- else
- v->dest_reg = tem;
- }
- else
- v->dest_reg = tem;
-
- /* If the address hasn't been checked for validity yet, do so
- now, and fail completely if either the first or the last
- unrolled copy of the address is not a valid address
- for the instruction that uses it. */
- if (v->dest_reg == tem
- && ! verify_addresses (v, giv_inc, unroll_number))
- {
- for (v2 = v->next_iv; v2; v2 = v2->next_iv)
- if (v2->same_insn == v)
- v2->same_insn = 0;
-
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Invalid address for giv at insn %d\n",
- INSN_UID (v->insn));
- continue;
- }
-
- v->new_reg = new_reg;
- v->same = same;
-
- /* We set this after the address check, to guarantee that
- the register will be initialized. */
- v->unrolled = 1;
-
- /* To initialize the new register, just move the value of
- new_reg into it. This is not guaranteed to give a valid
- instruction on machines with complex addressing modes.
- If we can't recognize it, then delete it and emit insns
- to calculate the value from scratch. */
- loop_insn_hoist (loop, gen_rtx_SET (VOIDmode, tem,
- copy_rtx (v->new_reg)));
- if (recog_memoized (PREV_INSN (loop->start)) < 0)
- {
- rtx sequence, ret;
-
- /* We can't use bl->initial_value to compute the initial
- value, because the loop may have been preconditioned.
- We must calculate it from NEW_REG. */
- delete_related_insns (PREV_INSN (loop->start));
-
- start_sequence ();
- ret = force_operand (v->new_reg, tem);
- if (ret != tem)
- emit_move_insn (tem, ret);
- sequence = gen_sequence ();
- end_sequence ();
- loop_insn_hoist (loop, sequence);
-
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Invalid init insn, rewritten.\n");
- }
- }
- else
- {
- v->dest_reg = value;
-
- /* Check the resulting address for validity, and fail
- if the resulting address would be invalid. */
- if (! verify_addresses (v, giv_inc, unroll_number))
- {
- for (v2 = v->next_iv; v2; v2 = v2->next_iv)
- if (v2->same_insn == v)
- v2->same_insn = 0;
-
- if (loop_dump_stream)
- fprintf (loop_dump_stream,
- "Invalid address for giv at insn %d\n",
- INSN_UID (v->insn));
- continue;
- }
- }
-
- /* Store the value of dest_reg into the insn. This sharing
- will not be a problem as this insn will always be copied
- later. */
-
- *v->location = v->dest_reg;
-
- /* If this address giv is combined with a dest reg giv, then
- save the base giv's induction pointer so that we will be
- able to handle this address giv properly. The base giv
- itself does not have to be splittable. */
-
- if (v->same && v->same->giv_type == DEST_REG)
- addr_combined_regs[reg_or_subregno (v->same->new_reg)] = v->same;
-
- if (GET_CODE (v->new_reg) == REG)
- {
- /* This giv maybe hasn't been combined with any others.
- Make sure that it's giv is marked as splittable here. */
-
- splittable_regs[reg_or_subregno (v->new_reg)] = value;
-
- /* Make it appear to depend upon itself, so that the
- giv will be properly split in the main loop above. */
- if (! v->same)
- {
- v->same = v;
- addr_combined_regs[reg_or_subregno (v->new_reg)] = v;
- }
- }
-
- if (loop_dump_stream)
- fprintf (loop_dump_stream, "DEST_ADDR giv being split.\n");
- }
+ continue;
}
else
{
@@ -3171,11 +2947,15 @@ reg_dead_after_loop (loop, reg)
code = GET_CODE (insn);
if (GET_RTX_CLASS (code) == 'i')
{
- rtx set;
+ rtx set, note;
if (reg_referenced_p (reg, PATTERN (insn)))
return 0;
+ note = find_reg_equal_equiv_note (insn);
+ if (note && reg_overlap_mentioned_p (reg, XEXP (note, 0)))
+ return 0;
+
set = single_set (insn);
if (set && rtx_equal_p (SET_DEST (set), reg))
break;
@@ -3367,7 +3147,7 @@ final_giv_value (loop, v)
tem = expand_simple_binop (GET_MODE (tem), MINUS, tem,
biv->add_val, NULL_RTX, 0,
OPTAB_LIB_WIDEN);
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
loop_insn_sink (loop, seq);
}
@@ -3605,7 +3385,7 @@ loop_iterations (loop)
&& INSN_LUID (JUMP_LABEL (temp)) < INSN_LUID (loop->cont))
{
if (loop_dump_stream)
- fprintf
+ fprintf
(loop_dump_stream,
"Loop iterations: Loop has multiple back edges.\n");
return 0;
diff --git a/contrib/gcc/unwind-c.c b/contrib/gcc/unwind-c.c
new file mode 100644
index 0000000..9ce0956
--- /dev/null
+++ b/contrib/gcc/unwind-c.c
@@ -0,0 +1,186 @@
+/* Supporting functions for C exception handling.
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Contributed by Aldy Hernandez <aldy@quesejoda.com>.
+ Shamelessly stolen from the Java front end.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "unwind.h"
+#include "unwind-pe.h"
+
+typedef struct
+{
+ _Unwind_Ptr Start;
+ _Unwind_Ptr LPStart;
+ _Unwind_Ptr ttype_base;
+ const unsigned char *TType;
+ const unsigned char *action_table;
+ unsigned char ttype_encoding;
+ unsigned char call_site_encoding;
+} lsda_header_info;
+
+static const unsigned char *
+parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
+ lsda_header_info *info)
+{
+ _Unwind_Word tmp;
+ unsigned char lpstart_encoding;
+
+ info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
+
+ /* Find @LPStart, the base to which landing pad offsets are relative. */
+ lpstart_encoding = *p++;
+ if (lpstart_encoding != DW_EH_PE_omit)
+ p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
+ else
+ info->LPStart = info->Start;
+
+ /* Find @TType, the base of the handler and exception spec type data. */
+ info->ttype_encoding = *p++;
+ if (info->ttype_encoding != DW_EH_PE_omit)
+ {
+ p = read_uleb128 (p, &tmp);
+ info->TType = p + tmp;
+ }
+ else
+ info->TType = 0;
+
+ /* The encoding and length of the call-site table; the action table
+ immediately follows. */
+ info->call_site_encoding = *p++;
+ p = read_uleb128 (p, &tmp);
+ info->action_table = p + tmp;
+
+ return p;
+}
+
+#ifdef __USING_SJLJ_EXCEPTIONS__
+#define PERSONALITY_FUNCTION __gcc_personality_sj0
+#define __builtin_eh_return_data_regno(x) x
+#else
+#define PERSONALITY_FUNCTION __gcc_personality_v0
+#endif
+#define PERSONALITY_FUNCTION __gcc_personality_v0
+
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class,
+ struct _Unwind_Exception *, struct _Unwind_Context *);
+
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (int version,
+ _Unwind_Action actions,
+ _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED,
+ struct _Unwind_Exception *ue_header,
+ struct _Unwind_Context *context)
+{
+ lsda_header_info info;
+ const unsigned char *language_specific_data, *p, *action_record;
+ _Unwind_Ptr landing_pad, ip;
+
+ if (version != 1)
+ return _URC_FATAL_PHASE1_ERROR;
+
+ /* Currently we only support cleanups for C. */
+ if ((actions & _UA_CLEANUP_PHASE) == 0)
+ return _URC_CONTINUE_UNWIND;
+
+ language_specific_data = (const unsigned char *)
+ _Unwind_GetLanguageSpecificData (context);
+
+ /* If no LSDA, then there are no handlers or cleanups. */
+ if (! language_specific_data)
+ return _URC_CONTINUE_UNWIND;
+
+ /* Parse the LSDA header. */
+ p = parse_lsda_header (context, language_specific_data, &info);
+ ip = _Unwind_GetIP (context) - 1;
+ landing_pad = 0;
+
+#ifdef __USING_SJLJ_EXCEPTIONS__
+ /* The given "IP" is an index into the call-site table, with two
+ exceptions -- -1 means no-action, and 0 means terminate. But
+ since we're using uleb128 values, we've not got random access
+ to the array. */
+ if ((int) ip <= 0)
+ return _URC_CONTINUE_UNWIND;
+ else
+ {
+ _Unwind_Word cs_lp, cs_action;
+ do
+ {
+ p = read_uleb128 (p, &cs_lp);
+ p = read_uleb128 (p, &cs_action);
+ }
+ while (--ip);
+
+ /* Can never have null landing pad for sjlj -- that would have
+ been indicated by a -1 call site index. */
+ landing_pad = cs_lp + 1;
+ if (cs_action)
+ action_record = info.action_table + cs_action - 1;
+ goto found_something;
+ }
+#else
+ /* Search the call-site table for the action associated with this IP. */
+ while (p < info.action_table)
+ {
+ _Unwind_Ptr cs_start, cs_len, cs_lp;
+ _Unwind_Word cs_action;
+
+ /* Note that all call-site encodings are "absolute" displacements. */
+ p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
+ p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
+ p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
+ p = read_uleb128 (p, &cs_action);
+
+ /* The table is sorted, so if we've passed the ip, stop. */
+ if (ip < info.Start + cs_start)
+ p = info.action_table;
+ else if (ip < info.Start + cs_start + cs_len)
+ {
+ if (cs_lp)
+ landing_pad = info.LPStart + cs_lp;
+ if (cs_action)
+ action_record = info.action_table + cs_action - 1;
+ goto found_something;
+ }
+ }
+
+#endif
+
+ /* IP is not in table. No associated cleanups. */
+ /* ??? This is where C++ calls std::terminate to catch throw
+ from a destructor. */
+ return _URC_CONTINUE_UNWIND;
+
+ found_something:
+ if (landing_pad == 0)
+ {
+ /* IP is present, but has a null landing pad.
+ No handler to be run. */
+ return _URC_CONTINUE_UNWIND;
+ }
+
+ _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
+ (_Unwind_Ptr) ue_header);
+ _Unwind_SetGR (context, __builtin_eh_return_data_regno (1), 0);
+ _Unwind_SetIP (context, landing_pad);
+ return _URC_INSTALL_CONTEXT;
+}
diff --git a/contrib/gcc/unwind-dw2-fde-darwin.c b/contrib/gcc/unwind-dw2-fde-darwin.c
new file mode 100644
index 0000000..630ffaf
--- /dev/null
+++ b/contrib/gcc/unwind-dw2-fde-darwin.c
@@ -0,0 +1,241 @@
+/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* 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. */
+
+/* Locate the FDE entry for a given address, using Darwin's keymgr support. */
+
+#include "tconfig.h"
+#include <string.h>
+#include <stdlib.h>
+#include "dwarf2.h"
+#include "unwind.h"
+#define NO_BASE_OF_ENCODED_VALUE
+#define DWARF2_OBJECT_END_PTR_EXTENSION
+#include "unwind-pe.h"
+#include "unwind-dw2-fde.h"
+/* Carefully don't include gthr.h. */
+
+typedef int __gthread_mutex_t;
+#define __gthread_mutex_lock(x) (void)(x)
+#define __gthread_mutex_unlock(x) (void)(x)
+
+static fde * _Unwind_Find_registered_FDE (void *pc,
+ struct dwarf_eh_bases *bases);
+
+#define _Unwind_Find_FDE _Unwind_Find_registered_FDE
+#include "unwind-dw2-fde.c"
+#undef _Unwind_Find_FDE
+
+/* KeyMgr stuff. */
+#define KEYMGR_GCC3_LIVE_IMAGE_LIST 301 /* loaded images */
+#define KEYMGR_GCC3_DW2_OBJ_LIST 302 /* Dwarf2 object list */
+
+extern void *_keymgr_get_and_lock_processwide_ptr (int);
+extern void _keymgr_set_and_unlock_processwide_ptr (int, void *);
+extern void _keymgr_unlock_processwide_ptr (int);
+
+struct mach_header;
+extern char *getsectdatafromheader (struct mach_header*, const char*,
+ const char *, unsigned long *);
+
+/* This is referenced from KEYMGR_GCC3_DW2_OBJ_LIST. */
+struct km_object_info {
+ struct object *seen_objects;
+ struct object *unseen_objects;
+ unsigned spare[2];
+};
+
+/* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST. Info about each resident image. */
+struct live_images {
+ unsigned long this_size; /* sizeof (live_images) */
+ struct mach_header *mh; /* the image info */
+ unsigned long vm_slide;
+ void (*destructor)(struct live_images *); /* destructor for this */
+ struct live_images *next;
+ unsigned int examined_p;
+ void *fde;
+ void *object_info;
+ unsigned long info[2]; /* Future use. */
+};
+
+/* Bits in the examined_p field of struct live_images. */
+enum {
+ EXAMINED_IMAGE_MASK = 1, /* We've seen this one. */
+ ALLOCED_IMAGE_MASK = 2, /* The FDE entries were allocated by
+ malloc, and must be freed. This isn't
+ used by newer libgcc versions. */
+ IMAGE_IS_TEXT_MASK = 4, /* This image is in the TEXT segment. */
+ DESTRUCTOR_MAY_BE_CALLED_LIVE = 8 /* The destructor may be called on an
+ object that's part of the live
+ image list. */
+};
+
+/* Delete any data we allocated on a live_images structure. Either
+ IMAGE has already been removed from the
+ KEYMGR_GCC3_LIVE_IMAGE_LIST and the struct will be deleted
+ after we return, or that list is locked and we're being called
+ because this object might be about to be unloaded. Called by
+ KeyMgr. */
+
+static void
+live_image_destructor (struct live_images *image)
+{
+ if (image->object_info)
+ {
+ /* Free any sorted arrays. */
+ __deregister_frame_info_bases (image->fde);
+
+ free (image->object_info);
+ image->object_info = NULL;
+ if (image->examined_p & ALLOCED_IMAGE_MASK)
+ free (image->fde);
+ image->fde = NULL;
+ }
+ image->examined_p = 0;
+ image->destructor = NULL;
+}
+
+/* Run through the list of live images. If we can allocate memory,
+ give each unseen image a new `struct object'. Even if we can't,
+ check whether the PC is inside the FDE of each unseen image.
+ */
+
+static inline fde *
+examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc)
+{
+ fde *result = NULL;
+ struct live_images *image;
+
+ image = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
+
+ for (; image != NULL; image = image->next)
+ if ((image->examined_p & EXAMINED_IMAGE_MASK) == 0)
+ {
+ char *fde;
+ unsigned long sz;
+
+ fde = getsectdatafromheader (image->mh, "__DATA", "__eh_frame", &sz);
+ if (fde == NULL)
+ {
+ fde = getsectdatafromheader (image->mh, "__TEXT",
+ "__eh_frame", &sz);
+ if (fde != NULL)
+ image->examined_p |= IMAGE_IS_TEXT_MASK;
+ }
+
+ /* If .eh_frame is empty, don't register at all. */
+ if (fde != NULL && sz > 0)
+ {
+ char *real_fde = (fde + image->vm_slide);
+ struct object *ob = NULL;
+ struct object panicob;
+
+ if (! dont_alloc)
+ ob = calloc (1, sizeof (struct object));
+ dont_alloc |= ob == NULL;
+ if (dont_alloc)
+ ob = &panicob;
+
+ ob->pc_begin = (void *)-1;
+ ob->tbase = 0;
+ ob->dbase = 0;
+ ob->u.single = (struct dwarf_fde *)real_fde;
+ ob->s.i = 0;
+ ob->s.b.encoding = DW_EH_PE_omit;
+ ob->fde_end = real_fde + sz;
+
+ if (! dont_alloc)
+ {
+ ob->next = unseen_objects;
+ unseen_objects = ob;
+
+ image->destructor = live_image_destructor;
+ image->object_info = ob;
+
+ image->examined_p |= (EXAMINED_IMAGE_MASK
+ | DESTRUCTOR_MAY_BE_CALLED_LIVE);
+ }
+ image->fde = real_fde;
+
+ result = search_object (ob, pc);
+ if (result)
+ {
+ int encoding;
+
+ bases->tbase = ob->tbase;
+ bases->dbase = ob->dbase;
+
+ encoding = ob->s.b.encoding;
+ if (ob->s.b.mixed_encoding)
+ encoding = get_fde_encoding (result);
+ read_encoded_value_with_base (encoding,
+ base_from_object (encoding, ob),
+ result->pc_begin,
+ (_Unwind_Ptr *)&bases->func);
+ break;
+ }
+ }
+ else
+ image->examined_p |= EXAMINED_IMAGE_MASK;
+ }
+
+ _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST);
+
+ return result;
+}
+
+fde *
+_Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
+{
+ struct km_object_info *the_obj_info;
+ fde *ret = NULL;
+
+ the_obj_info =
+ _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST);
+ if (! the_obj_info)
+ the_obj_info = calloc (1, sizeof (*the_obj_info));
+
+ if (the_obj_info != NULL)
+ {
+ seen_objects = the_obj_info->seen_objects;
+ unseen_objects = the_obj_info->unseen_objects;
+
+ ret = _Unwind_Find_registered_FDE (pc, bases);
+ }
+
+ /* OK, didn't find it in the list of FDEs we've seen before,
+ so go through and look at the new ones. */
+ if (ret == NULL)
+ ret = examine_objects (pc, bases, the_obj_info == NULL);
+
+ if (the_obj_info != NULL)
+ {
+ the_obj_info->seen_objects = seen_objects;
+ the_obj_info->unseen_objects = unseen_objects;
+ _keymgr_set_and_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST,
+ the_obj_info);
+ }
+ return ret;
+}
diff --git a/contrib/gcc/unwind-dw2-fde-glibc.c b/contrib/gcc/unwind-dw2-fde-glibc.c
index 94fe6d1..21b3321 100644
--- a/contrib/gcc/unwind-dw2-fde-glibc.c
+++ b/contrib/gcc/unwind-dw2-fde-glibc.c
@@ -79,9 +79,9 @@ struct unw_eh_frame_hdr
unsigned char table_enc;
};
-/* Like base_of_encoded_value, but take the base from a struct object
- instead of an _Unwind_Context. */
-
+/* Like base_of_encoded_value, but take the base from a struct
+ unw_eh_callback_data instead of an _Unwind_Context. */
+
static _Unwind_Ptr
base_from_cb_data (unsigned char encoding, struct unw_eh_callback_data *data)
{
@@ -94,7 +94,7 @@ base_from_cb_data (unsigned char encoding, struct unw_eh_callback_data *data)
case DW_EH_PE_pcrel:
case DW_EH_PE_aligned:
return 0;
-
+
case DW_EH_PE_textrel:
return (_Unwind_Ptr) data->tbase;
case DW_EH_PE_datarel:
diff --git a/contrib/gcc/unwind-dw2-fde.c b/contrib/gcc/unwind-dw2-fde.c
index 460d7f0..f4cb4bb 100644
--- a/contrib/gcc/unwind-dw2-fde.c
+++ b/contrib/gcc/unwind-dw2-fde.c
@@ -1,5 +1,5 @@
/* Subroutines needed for unwinding stack frames for exception handling. */
-/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Jason Merrill <jason@cygnus.com>.
This file is part of GCC.
@@ -53,7 +53,7 @@ static __gthread_mutex_t object_mutex;
#endif
#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
-static void
+static void
init_object_mutex (void)
{
__GTHREAD_MUTEX_INIT_FUNCTION (&object_mutex);
@@ -85,6 +85,9 @@ __register_frame_info_bases (void *begin, struct object *ob,
ob->u.single = begin;
ob->s.i = 0;
ob->s.b.encoding = DW_EH_PE_omit;
+#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
+ ob->fde_end = NULL;
+#endif
init_object_mutex_once ();
__gthread_mutex_lock (&object_mutex);
@@ -111,7 +114,7 @@ __register_frame (void *begin)
return;
ob = (struct object *) malloc (sizeof (struct object));
- __register_frame_info (begin, ob);
+ __register_frame_info (begin, ob);
}
/* Similar, but BEGIN is actually a pointer to a table of unwind entries
@@ -161,7 +164,7 @@ __register_frame_table (void *begin)
Since the registration did not happen there, we'll abort.
Therefore, declare a new deregistration entry point that does the
- exact same thing, but will resolve to the same library as
+ exact same thing, but will resolve to the same library as
implements __register_frame_info_bases. */
void *
@@ -398,7 +401,7 @@ start_fde_sort (struct fde_accumulator *accu, size_t count)
return 1;
}
else
- return 0;
+ return 0;
}
static inline void
@@ -411,7 +414,7 @@ fde_insert (struct fde_accumulator *accu, fde *this_fde)
/* Split LINEAR into a linear sequence with low values and an erratic
sequence with high values, put the linear one (of longest possible
length) into LINEAR and the erratic one into ERRATIC. This is O(N).
-
+
Because the longest linear sequence we are trying to locate within the
incoming LINEAR array can be interspersed with (high valued) erratic
entries. We construct a chain indicating the sequenced entries.
@@ -434,18 +437,18 @@ fde_split (struct object *ob, fde_compare_t fde_compare,
them and the overlaying onto ERRATIC will not work. */
if (sizeof (fde *) != sizeof (fde **))
abort ();
-
+
for (i = 0; i < count; i++)
{
fde **probe;
-
+
for (probe = chain_end;
- probe != &marker && fde_compare (ob, linear->array[i], *probe) < 0;
- probe = chain_end)
- {
- chain_end = (fde **) erratic->array[probe - linear->array];
- erratic->array[probe - linear->array] = NULL;
- }
+ probe != &marker && fde_compare (ob, linear->array[i], *probe) < 0;
+ probe = chain_end)
+ {
+ chain_end = (fde **) erratic->array[probe - linear->array];
+ erratic->array[probe - linear->array] = NULL;
+ }
erratic->array[i] = (fde *) chain_end;
chain_end = &linear->array[i];
}
@@ -486,22 +489,22 @@ frame_heapsort (struct object *ob, fde_compare_t fde_compare,
/* Invariant: a[m..n-1] is a heap. */
m--;
for (i = m; 2*i+1 < n; )
- {
- if (2*i+2 < n
- && fde_compare (ob, a[2*i+2], a[2*i+1]) > 0
- && fde_compare (ob, a[2*i+2], a[i]) > 0)
- {
- SWAP (a[i], a[2*i+2]);
- i = 2*i+2;
- }
- else if (fde_compare (ob, a[2*i+1], a[i]) > 0)
- {
- SWAP (a[i], a[2*i+1]);
- i = 2*i+1;
- }
- else
- break;
- }
+ {
+ if (2*i+2 < n
+ && fde_compare (ob, a[2*i+2], a[2*i+1]) > 0
+ && fde_compare (ob, a[2*i+2], a[i]) > 0)
+ {
+ SWAP (a[i], a[2*i+2]);
+ i = 2*i+2;
+ }
+ else if (fde_compare (ob, a[2*i+1], a[i]) > 0)
+ {
+ SWAP (a[i], a[2*i+1]);
+ i = 2*i+1;
+ }
+ else
+ break;
+ }
}
while (n > 1)
{
@@ -509,22 +512,22 @@ frame_heapsort (struct object *ob, fde_compare_t fde_compare,
n--;
SWAP (a[0], a[n]);
for (i = 0; 2*i+1 < n; )
- {
- if (2*i+2 < n
- && fde_compare (ob, a[2*i+2], a[2*i+1]) > 0
- && fde_compare (ob, a[2*i+2], a[i]) > 0)
- {
- SWAP (a[i], a[2*i+2]);
- i = 2*i+2;
- }
- else if (fde_compare (ob, a[2*i+1], a[i]) > 0)
- {
- SWAP (a[i], a[2*i+1]);
- i = 2*i+1;
- }
- else
- break;
- }
+ {
+ if (2*i+2 < n
+ && fde_compare (ob, a[2*i+2], a[2*i+1]) > 0
+ && fde_compare (ob, a[2*i+2], a[i]) > 0)
+ {
+ SWAP (a[i], a[2*i+2]);
+ i = 2*i+2;
+ }
+ else if (fde_compare (ob, a[2*i+1], a[i]) > 0)
+ {
+ SWAP (a[i], a[2*i+1]);
+ i = 2*i+1;
+ }
+ else
+ break;
+ }
}
#undef SWAP
}
@@ -550,7 +553,7 @@ fde_merge (struct object *ob, fde_compare_t fde_compare,
v1->array[i1+i2] = v1->array[i1-1];
i1--;
}
- v1->array[i1+i2] = fde2;
+ v1->array[i1+i2] = fde2;
}
while (i2 > 0);
v1->count += v2->count;
@@ -590,7 +593,7 @@ end_fde_sort (struct object *ob, struct fde_accumulator *accu, size_t count)
}
-/* Update encoding, mixed_encoding, and pc_begin for OB for the
+/* Update encoding, mixed_encoding, and pc_begin for OB for the
fde array beginning at THIS_FDE. Return the number of fdes
encountered along the way. */
@@ -602,7 +605,7 @@ classify_object_over_fdes (struct object *ob, fde *this_fde)
int encoding = DW_EH_PE_absptr;
_Unwind_Ptr base = 0;
- for (; this_fde->length != 0; this_fde = next_fde (this_fde))
+ for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
{
struct dwarf_cie *this_cie;
_Unwind_Ptr mask, pc_begin;
@@ -656,7 +659,7 @@ add_fdes (struct object *ob, struct fde_accumulator *accu, fde *this_fde)
int encoding = ob->s.b.encoding;
_Unwind_Ptr base = base_from_object (ob->s.b.encoding, ob);
- for (; this_fde->length != 0; this_fde = next_fde (this_fde))
+ for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
{
struct dwarf_cie *this_cie;
@@ -747,7 +750,7 @@ init_object (struct object* ob)
{
fde **p;
for (p = ob->u.array; *p; ++p)
- add_fdes (ob, &accu, *p);
+ add_fdes (ob, &accu, *p);
}
else
add_fdes (ob, &accu, ob->u.single);
@@ -773,7 +776,7 @@ linear_search_fdes (struct object *ob, fde *this_fde, void *pc)
int encoding = ob->s.b.encoding;
_Unwind_Ptr base = base_from_object (ob->s.b.encoding, ob);
- for (; this_fde->length != 0; this_fde = next_fde (this_fde))
+ for (; ! last_fde (ob, this_fde); this_fde = next_fde (this_fde))
{
struct dwarf_cie *this_cie;
_Unwind_Ptr pc_begin, pc_range;
@@ -826,7 +829,7 @@ linear_search_fdes (struct object *ob, fde *this_fde, void *pc)
}
if ((_Unwind_Ptr) pc - pc_begin < pc_range)
- return this_fde;
+ return this_fde;
}
return NULL;
@@ -840,7 +843,7 @@ binary_search_unencoded_fdes (struct object *ob, void *pc)
{
struct fde_vector *vec = ob->u.sort;
size_t lo, hi;
-
+
for (lo = 0, hi = vec->count; lo < hi; )
{
size_t i = (lo + hi) / 2;
@@ -869,7 +872,7 @@ binary_search_single_encoding_fdes (struct object *ob, void *pc)
int encoding = ob->s.b.encoding;
_Unwind_Ptr base = base_from_object (encoding, ob);
size_t lo, hi;
-
+
for (lo = 0, hi = vec->count; lo < hi; )
{
size_t i = (lo + hi) / 2;
@@ -897,7 +900,7 @@ binary_search_mixed_encoding_fdes (struct object *ob, void *pc)
{
struct fde_vector *vec = ob->u.sort;
size_t lo, hi;
-
+
for (lo = 0, hi = vec->count; lo < hi; )
{
size_t i = (lo + hi) / 2;
@@ -952,14 +955,14 @@ search_object (struct object* ob, void *pc)
{
/* Long slow labourious linear search, cos we've no memory. */
if (ob->s.b.from_array)
- {
- fde **p;
+ {
+ fde **p;
for (p = ob->u.array; *p ; p++)
{
fde *f = linear_search_fdes (ob, *p, pc);
- if (f)
+ if (f)
return f;
- }
+ }
return NULL;
}
else
diff --git a/contrib/gcc/unwind-dw2-fde.h b/contrib/gcc/unwind-dw2-fde.h
index b06ff41..7565c49 100644
--- a/contrib/gcc/unwind-dw2-fde.h
+++ b/contrib/gcc/unwind-dw2-fde.h
@@ -1,5 +1,5 @@
/* Subroutines needed for unwinding stack frames for exception handling. */
-/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
+/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
Contributed by Jason Merrill <jason@cygnus.com>.
@@ -61,6 +61,10 @@ struct object
size_t i;
} s;
+#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
+ char *fde_end;
+#endif
+
struct object *next;
};
@@ -122,7 +126,7 @@ typedef unsigned char ubyte;
a) in a linear search, find the shared image (i.e. DLL) containing
the PC
b) using the FDE table for that shared object, locate the FDE using
- binary search (which requires the sorting). */
+ binary search (which requires the sorting). */
/* The first few fields of a CIE. The CIE_id field is 0 for a CIE,
to distinguish it from a valid FDE. FDEs are aligned to an addressing
@@ -160,3 +164,13 @@ next_fde (fde *f)
}
extern fde * _Unwind_Find_FDE (void *, struct dwarf_eh_bases *);
+
+static inline int
+last_fde (struct object *obj __attribute__ ((__unused__)), fde *f)
+{
+#ifdef DWARF2_OBJECT_END_PTR_EXTENSION
+ return (char *)f == obj->fde_end || f->length == 0;
+#else
+ return f->length == 0;
+#endif
+}
diff --git a/contrib/gcc/unwind-dw2.c b/contrib/gcc/unwind-dw2.c
index 8151d69..6d7219e 100644
--- a/contrib/gcc/unwind-dw2.c
+++ b/contrib/gcc/unwind-dw2.c
@@ -48,7 +48,9 @@
#define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS
#endif
-/* This is the register and unwind state for a particular frame. */
+/* This is the register and unwind state for a particular frame. This
+ provides the information necessary to unwind up past a frame and return
+ to its caller. */
struct _Unwind_Context
{
void *reg[DWARF_FRAME_REGISTERS+1];
@@ -164,6 +166,14 @@ _Unwind_GetGR (struct _Unwind_Context *context, int index)
return * (_Unwind_Word *) context->reg[index];
}
+/* Get the value of the CFA as saved in CONTEXT. */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+ return (_Unwind_Ptr) context->cfa;
+}
+
/* Overwrite the saved value for register REG in CONTEXT with VAL. */
inline void
@@ -200,6 +210,17 @@ _Unwind_GetRegionStart (struct _Unwind_Context *context)
return (_Unwind_Ptr) context->bases.func;
}
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+ struct dwarf_eh_bases bases;
+ struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
+ if (fde)
+ return bases.func;
+ else
+ return NULL;
+}
+
#ifndef __ia64__
_Unwind_Ptr
_Unwind_GetDataRelBase (struct _Unwind_Context *context)
@@ -589,68 +610,68 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
{
/* Binary operations. */
_Unwind_Word first, second;
- if ((stack_elt -= 2) < 0)
- abort ();
- second = stack[stack_elt];
- first = stack[stack_elt + 1];
-
- switch (op)
- {
- case DW_OP_and:
- result = second & first;
- break;
- case DW_OP_div:
- result = (_Unwind_Sword) second / (_Unwind_Sword) first;
- break;
- case DW_OP_minus:
- result = second - first;
- break;
- case DW_OP_mod:
- result = (_Unwind_Sword) second % (_Unwind_Sword) first;
- break;
- case DW_OP_mul:
- result = second * first;
- break;
- case DW_OP_or:
- result = second | first;
- break;
- case DW_OP_plus:
- result = second + first;
- break;
- case DW_OP_shl:
- result = second << first;
- break;
- case DW_OP_shr:
- result = second >> first;
- break;
- case DW_OP_shra:
- result = (_Unwind_Sword) second >> first;
- break;
- case DW_OP_xor:
- result = second ^ first;
- break;
- case DW_OP_le:
- result = (_Unwind_Sword) first <= (_Unwind_Sword) second;
- break;
- case DW_OP_ge:
- result = (_Unwind_Sword) first >= (_Unwind_Sword) second;
- break;
- case DW_OP_eq:
- result = (_Unwind_Sword) first == (_Unwind_Sword) second;
- break;
- case DW_OP_lt:
- result = (_Unwind_Sword) first < (_Unwind_Sword) second;
- break;
- case DW_OP_gt:
- result = (_Unwind_Sword) first > (_Unwind_Sword) second;
- break;
- case DW_OP_ne:
- result = (_Unwind_Sword) first != (_Unwind_Sword) second;
- break;
-
- default:
+ if ((stack_elt -= 2) < 0)
abort ();
- }
+ second = stack[stack_elt];
+ first = stack[stack_elt + 1];
+
+ switch (op)
+ {
+ case DW_OP_and:
+ result = second & first;
+ break;
+ case DW_OP_div:
+ result = (_Unwind_Sword) second / (_Unwind_Sword) first;
+ break;
+ case DW_OP_minus:
+ result = second - first;
+ break;
+ case DW_OP_mod:
+ result = (_Unwind_Sword) second % (_Unwind_Sword) first;
+ break;
+ case DW_OP_mul:
+ result = second * first;
+ break;
+ case DW_OP_or:
+ result = second | first;
+ break;
+ case DW_OP_plus:
+ result = second + first;
+ break;
+ case DW_OP_shl:
+ result = second << first;
+ break;
+ case DW_OP_shr:
+ result = second >> first;
+ break;
+ case DW_OP_shra:
+ result = (_Unwind_Sword) second >> first;
+ break;
+ case DW_OP_xor:
+ result = second ^ first;
+ break;
+ case DW_OP_le:
+ result = (_Unwind_Sword) first <= (_Unwind_Sword) second;
+ break;
+ case DW_OP_ge:
+ result = (_Unwind_Sword) first >= (_Unwind_Sword) second;
+ break;
+ case DW_OP_eq:
+ result = (_Unwind_Sword) first == (_Unwind_Sword) second;
+ break;
+ case DW_OP_lt:
+ result = (_Unwind_Sword) first < (_Unwind_Sword) second;
+ break;
+ case DW_OP_gt:
+ result = (_Unwind_Sword) first > (_Unwind_Sword) second;
+ break;
+ case DW_OP_ne:
+ result = (_Unwind_Sword) first != (_Unwind_Sword) second;
+ break;
+
+ default:
+ abort ();
+ }
}
break;
@@ -679,7 +700,7 @@ execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end,
/* Most things push a result value. */
if ((size_t) stack_elt >= sizeof(stack)/sizeof(*stack))
abort ();
- stack[++stack_elt] = result;
+ stack[stack_elt++] = result;
no_push:;
}
@@ -784,7 +805,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
fs->regs.reg[reg].loc.reg = reg2;
}
break;
-
+
case DW_CFA_remember_state:
{
struct frame_state_reg_info *new_rs;
@@ -829,17 +850,17 @@ execute_cfa_program (const unsigned char *insn_ptr,
break;
case DW_CFA_def_cfa_expression:
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
fs->cfa_exp = insn_ptr;
fs->cfa_how = CFA_EXP;
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
insn_ptr += utmp;
break;
case DW_CFA_expression:
insn_ptr = read_uleb128 (insn_ptr, &reg);
- insn_ptr = read_uleb128 (insn_ptr, &utmp);
fs->regs.reg[reg].how = REG_SAVED_EXP;
fs->regs.reg[reg].loc.exp = insn_ptr;
+ insn_ptr = read_uleb128 (insn_ptr, &utmp);
insn_ptr += utmp;
break;
@@ -851,7 +872,7 @@ execute_cfa_program (const unsigned char *insn_ptr,
fs->regs.reg[reg].how = REG_SAVED_OFFSET;
fs->regs.reg[reg].loc.offset = offset;
break;
-
+
case DW_CFA_def_cfa_sf:
insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg);
insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset);
@@ -892,6 +913,11 @@ execute_cfa_program (const unsigned char *insn_ptr,
}
}
+/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
+ its caller and decode it into FS. This function also sets the
+ args_size and lsda members of CONTEXT, as they are really information
+ about the caller's frame. */
+
static _Unwind_Reason_Code
uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
{
@@ -1023,34 +1049,48 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
void *cfa;
long i;
+#ifdef EH_RETURN_STACKADJ_RTX
+ /* Special handling here: Many machines do not use a frame pointer,
+ and track the CFA only through offsets from the stack pointer from
+ one frame to the next. In this case, the stack pointer is never
+ stored, so it has no saved address in the context. What we do
+ have is the CFA from the previous stack frame.
+
+ In very special situations (such as unwind info for signal return),
+ there may be location expressions that use the stack pointer as well.
+
+ Do this conditionally for one frame. This allows the unwind info
+ for one frame to save a copy of the stack pointer from the previous
+ frame, and be able to use much easier CFA mechanisms to do it.
+ Always zap the saved stack pointer value for the next frame; carrying
+ the value over from one frame to another doesn't make sense. */
+
+ _Unwind_Word tmp_sp;
+
+ if (!orig_context.reg[__builtin_dwarf_sp_column ()])
+ {
+ tmp_sp = (_Unwind_Ptr) context->cfa;
+ orig_context.reg[__builtin_dwarf_sp_column ()] = &tmp_sp;
+ }
+ context->reg[__builtin_dwarf_sp_column ()] = NULL;
+#endif
+
/* Compute this frame's CFA. */
switch (fs->cfa_how)
{
case CFA_REG_OFFSET:
- /* Special handling here: Many machines do not use a frame pointer,
- and track the CFA only through offsets from the stack pointer from
- one frame to the next. In this case, the stack pointer is never
- stored, so it has no saved address in the context. What we do
- have is the CFA from the previous stack frame. */
- if (context->reg[fs->cfa_reg] == NULL)
- cfa = context->cfa;
- else
- cfa = (void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->cfa_reg);
+ cfa = (void *) (_Unwind_Ptr) _Unwind_GetGR (&orig_context, fs->cfa_reg);
cfa += fs->cfa_offset;
break;
case CFA_EXP:
- /* ??? No way of knowing what register number is the stack pointer
- to do the same sort of handling as above. Assume that if the
- CFA calculation is so complicated as to require a stack program
- that this will not be a problem. */
{
const unsigned char *exp = fs->cfa_exp;
_Unwind_Word len;
exp = read_uleb128 (exp, &len);
cfa = (void *) (_Unwind_Ptr)
- execute_stack_op (exp, exp + len, context, 0);
+ execute_stack_op (exp, exp + len, &orig_context, 0);
break;
}
@@ -1065,12 +1105,15 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
{
case REG_UNSAVED:
break;
+
case REG_SAVED_OFFSET:
context->reg[i] = cfa + fs->regs.reg[i].loc.offset;
break;
+
case REG_SAVED_REG:
context->reg[i] = orig_context.reg[fs->regs.reg[i].loc.reg];
break;
+
case REG_SAVED_EXP:
{
const unsigned char *exp = fs->regs.reg[i].loc.exp;
@@ -1086,6 +1129,11 @@ uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
}
}
+/* CONTEXT describes the unwind state for a frame, and FS describes the FDE
+ of its caller. Update CONTEXT to refer to the caller as well. Note
+ that the args_size and lsda members are not updated here, but later in
+ uw_frame_state_for. */
+
static void
uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
{
@@ -1099,7 +1147,7 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
/* Fill in CONTEXT for top-of-stack. The only valid registers at this
level will be the return address and the CFA. */
-
+
#define uw_init_context(CONTEXT) \
do \
{ \
@@ -1117,6 +1165,7 @@ uw_init_context_1 (struct _Unwind_Context *context,
{
void *ra = __builtin_extract_return_addr (__builtin_return_address (0));
_Unwind_FrameState fs;
+ _Unwind_Word sp_slot;
memset (context, 0, sizeof (struct _Unwind_Context));
context->ra = ra;
@@ -1125,9 +1174,10 @@ uw_init_context_1 (struct _Unwind_Context *context,
abort ();
/* Force the frame state to use the known cfa value. */
- context->cfa = outer_cfa;
+ sp_slot = (_Unwind_Ptr) outer_cfa;
+ context->reg[__builtin_dwarf_sp_column ()] = &sp_slot;
fs.cfa_how = CFA_REG_OFFSET;
- fs.cfa_reg = 0;
+ fs.cfa_reg = __builtin_dwarf_sp_column ();
fs.cfa_offset = 0;
uw_update_context_1 (context, &fs);
@@ -1184,11 +1234,26 @@ uw_install_context_1 (struct _Unwind_Context *current,
memcpy (c, t, dwarf_reg_size_table[i]);
}
- /* We adjust SP by the difference between CURRENT and TARGET's CFA. */
- if (STACK_GROWS_DOWNWARD)
- return target->cfa - current->cfa + target->args_size;
- else
- return current->cfa - target->cfa - target->args_size;
+#ifdef EH_RETURN_STACKADJ_RTX
+ {
+ void *target_cfa;
+
+ /* If the last frame records a saved stack pointer, use it. */
+ if (target->reg[__builtin_dwarf_sp_column ()])
+ target_cfa = (void *)(_Unwind_Ptr)
+ _Unwind_GetGR (target, __builtin_dwarf_sp_column ());
+ else
+ target_cfa = target->cfa;
+
+ /* We adjust SP by the difference between CURRENT and TARGET's CFA. */
+ if (STACK_GROWS_DOWNWARD)
+ return target_cfa - current->cfa + target->args_size;
+ else
+ return current->cfa - target_cfa - target->args_size;
+ }
+#else
+ return 0;
+#endif
}
static inline _Unwind_Ptr
diff --git a/contrib/gcc/unwind-pe.h b/contrib/gcc/unwind-pe.h
index 01e05ebf..d32e506 100644
--- a/contrib/gcc/unwind-pe.h
+++ b/contrib/gcc/unwind-pe.h
@@ -179,13 +179,13 @@ read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
} __attribute__((__packed__));
union unaligned *u = (union unaligned *) p;
- _Unwind_Ptr result;
+ _Unwind_Internal_Ptr result;
if (encoding == DW_EH_PE_aligned)
{
- _Unwind_Ptr a = (_Unwind_Ptr) p;
+ _Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p;
a = (a + sizeof (void *) - 1) & - sizeof(void *);
- result = *(_Unwind_Ptr *) a;
+ result = *(_Unwind_Internal_Ptr *) a;
p = (const unsigned char *) (a + sizeof (void *));
}
else
@@ -193,7 +193,7 @@ read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
switch (encoding & 0x0f)
{
case DW_EH_PE_absptr:
- result = (_Unwind_Ptr) u->ptr;
+ result = (_Unwind_Internal_Ptr) u->ptr;
p += sizeof (void *);
break;
@@ -201,7 +201,7 @@ read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
{
_Unwind_Word tmp;
p = read_uleb128 (p, &tmp);
- result = (_Unwind_Ptr) tmp;
+ result = (_Unwind_Internal_Ptr) tmp;
}
break;
@@ -209,7 +209,7 @@ read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
{
_Unwind_Sword tmp;
p = read_sleb128 (p, &tmp);
- result = (_Unwind_Ptr) tmp;
+ result = (_Unwind_Internal_Ptr) tmp;
}
break;
@@ -246,9 +246,9 @@ read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
if (result != 0)
{
result += ((encoding & 0x70) == DW_EH_PE_pcrel
- ? (_Unwind_Ptr) u : base);
+ ? (_Unwind_Internal_Ptr) u : base);
if (encoding & DW_EH_PE_indirect)
- result = *(_Unwind_Ptr *) result;
+ result = *(_Unwind_Internal_Ptr *) result;
}
}
diff --git a/contrib/gcc/unwind-sjlj.c b/contrib/gcc/unwind-sjlj.c
index 2161b71..7b52338 100644
--- a/contrib/gcc/unwind-sjlj.c
+++ b/contrib/gcc/unwind-sjlj.c
@@ -63,7 +63,7 @@ struct SjLj_Function_Context
#ifdef DONT_USE_BUILTIN_SETJMP
/* We don't know what sort of alignment requirements the system
jmp_buf has. We over estimated in except.c, and now we have
- to match that here just in case the system *didn't* have more
+ to match that here just in case the system *didn't* have more
restrictive requirements. */
jmp_buf jbuf __attribute__((aligned));
#else
@@ -76,7 +76,7 @@ struct _Unwind_Context
struct SjLj_Function_Context *fc;
};
-typedef struct
+typedef struct
{
_Unwind_Personality_Fn personality;
} _Unwind_FrameState;
@@ -174,6 +174,15 @@ _Unwind_GetGR (struct _Unwind_Context *context, int index)
return context->fc->data[index];
}
+/* Get the value of the CFA as saved in CONTEXT. */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+ /* ??? Ideally __builtin_setjmp places the CFA in the jmpbuf. */
+ return NULL;
+}
+
void
_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
{
@@ -208,6 +217,12 @@ _Unwind_GetRegionStart (struct _Unwind_Context *context __attribute__((unused))
return 0;
}
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+ return NULL;
+}
+
#ifndef __ia64__
_Unwind_Ptr
_Unwind_GetDataRelBase (struct _Unwind_Context *context __attribute__((unused)) )
@@ -244,14 +259,14 @@ uw_update_context (struct _Unwind_Context *context,
context->fc = context->fc->prev;
}
-static inline void
+static inline void
uw_init_context (struct _Unwind_Context *context)
{
context->fc = _Unwind_SjLj_GetContext ();
}
/* ??? There appear to be bugs in integrate.c wrt __builtin_longjmp and
- virtual-stack-vars. An inline version of this segfaults on Sparc. */
+ virtual-stack-vars. An inline version of this segfaults on SPARC. */
#define uw_install_context(CURRENT, TARGET) \
do \
{ \
@@ -274,6 +289,7 @@ uw_identify_context (struct _Unwind_Context *context)
#define _Unwind_RaiseException _Unwind_SjLj_RaiseException
#define _Unwind_ForcedUnwind _Unwind_SjLj_ForcedUnwind
#define _Unwind_Resume _Unwind_SjLj_Resume
+#define _Unwind_Resume_or_Rethrow _Unwind_SjLj_Resume_or_Rethrow
#include "unwind.inc"
diff --git a/contrib/gcc/unwind.h b/contrib/gcc/unwind.h
index fc36913..af4e8af 100644
--- a/contrib/gcc/unwind.h
+++ b/contrib/gcc/unwind.h
@@ -1,5 +1,5 @@
/* Exception handling and frame unwind runtime interface routines.
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -18,6 +18,13 @@
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
+/* As a special exception, if you include this header file into source
+ files compiled by GCC, this header file does not by itself cause
+ the resulting executable to be covered by the GNU General Public
+ License. This exception does not however invalidate any other
+ reasons why the executable file might be covered by the GNU General
+ Public License. */
+
/* This is derived from the C++ ABI for IA-64. Where we diverge
for cross-architecture compatibility are noted with "@@@". */
@@ -31,7 +38,12 @@ extern "C" {
inefficient for 32-bit and smaller machines. */
typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
typedef signed _Unwind_Sword __attribute__((__mode__(__word__)));
+#if defined(__ia64__) && defined(__hpux__)
+typedef unsigned _Unwind_Ptr __attribute__((__mode__(__word__)));
+#else
typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
+#endif
+typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__)));
/* @@@ The IA-64 ABI uses a 64-bit word to identify the producer and
consumer of an exception. We'll go along with this for now even on
@@ -115,6 +127,18 @@ extern void _Unwind_DeleteException (struct _Unwind_Exception *);
e.g. executing cleanup code, and not to implement rethrowing. */
extern void _Unwind_Resume (struct _Unwind_Exception *);
+/* @@@ Resume propagation of an FORCE_UNWIND exception, or to rethrow
+ a normal exception that was handled. */
+extern _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *);
+
+/* @@@ Use unwind data to perform a stack backtrace. The trace callback
+ is called for every stack frame in the call chain, but no cleanup
+ actions are performed. */
+typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)
+ (struct _Unwind_Context *, void *);
+
+extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *);
+
/* These functions are used for communicating information about the unwind
context (i.e. the unwind descriptors and the user register state) between
the unwind library and the personality routine and landing pad. Only
@@ -126,6 +150,9 @@ extern void _Unwind_SetGR (struct _Unwind_Context *, int, _Unwind_Word);
extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *);
extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr);
+/* @@@ Retrieve the CFA of the given context. */
+extern _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *);
+
extern void *_Unwind_GetLanguageSpecificData (struct _Unwind_Context *);
extern _Unwind_Ptr _Unwind_GetRegionStart (struct _Unwind_Context *);
@@ -136,15 +163,15 @@ extern _Unwind_Ptr _Unwind_GetRegionStart (struct _Unwind_Context *);
library and language-specific exception handling semantics. It is
specific to the code fragment described by an unwind info block, and
it is always referenced via the pointer in the unwind info block, and
- hence it has no ABI-specified name.
+ hence it has no ABI-specified name.
Note that this implies that two different C++ implementations can
use different names, and have different contents in the language
- specific data area. Moreover, that the language specific data
+ specific data area. Moreover, that the language specific data
area contains no version info because name of the function invoked
provides more effective versioning by detecting at link time the
lack of code to handle the different data format. */
-
+
typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)
(int, _Unwind_Action, _Unwind_Exception_Class,
struct _Unwind_Exception *, struct _Unwind_Context *);
@@ -161,6 +188,7 @@ extern _Unwind_Reason_Code _Unwind_SjLj_RaiseException
extern _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind
(struct _Unwind_Exception *, _Unwind_Stop_Fn, void *);
extern void _Unwind_SjLj_Resume (struct _Unwind_Exception *);
+extern _Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow (struct _Unwind_Exception *);
/* @@@ The following provide access to the base addresses for text
and data-relative addressing in the LDSA. In order to stay link
@@ -187,6 +215,10 @@ extern _Unwind_Ptr _Unwind_GetDataRelBase (struct _Unwind_Context *);
extern _Unwind_Ptr _Unwind_GetTextRelBase (struct _Unwind_Context *);
#endif
+/* @@@ Given an address, return the entry point of the function that
+ contains it. */
+extern void * _Unwind_FindEnclosingFunction (void *pc);
+
#ifdef __cplusplus
}
#endif
diff --git a/contrib/gcc/unwind.inc b/contrib/gcc/unwind.inc
index f00441e..0938d50 100644
--- a/contrib/gcc/unwind.inc
+++ b/contrib/gcc/unwind.inc
@@ -72,7 +72,6 @@ _Unwind_RaiseException_Phase2(struct _Unwind_Exception *exc,
return code;
}
-
/* Raise an exception, passing along the given exception object. */
_Unwind_Reason_Code
@@ -81,6 +80,7 @@ _Unwind_RaiseException(struct _Unwind_Exception *exc)
struct _Unwind_Context this_context, cur_context;
_Unwind_Reason_Code code;
+ /* Set up this_context to describe the current stack frame. */
uw_init_context (&this_context);
cur_context = this_context;
@@ -90,6 +90,8 @@ _Unwind_RaiseException(struct _Unwind_Exception *exc)
{
_Unwind_FrameState fs;
+ /* Set up fs to describe the FDE for the caller of cur_context. The
+ first time through the loop, that means __cxa_throw. */
code = uw_frame_state_for (&cur_context, &fs);
if (code == _URC_END_OF_STACK)
@@ -112,6 +114,7 @@ _Unwind_RaiseException(struct _Unwind_Exception *exc)
return _URC_FATAL_PHASE1_ERROR;
}
+ /* Update cur_context to describe the same frame as fs. */
uw_update_context (&cur_context, &fs);
}
@@ -144,6 +147,7 @@ _Unwind_ForcedUnwind_Phase2(struct _Unwind_Exception *exc,
_Unwind_FrameState fs;
int action;
+ /* Set up fs to describe the FDE for the caller of cur_context. */
code = uw_frame_state_for (context, &fs);
if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
return _URC_FATAL_PHASE2_ERROR;
@@ -172,6 +176,7 @@ _Unwind_ForcedUnwind_Phase2(struct _Unwind_Exception *exc,
return _URC_FATAL_PHASE2_ERROR;
}
+ /* Update cur_context to describe the same frame as fs. */
uw_update_context (context, &fs);
}
@@ -227,10 +232,73 @@ _Unwind_Resume (struct _Unwind_Exception *exc)
uw_install_context (&this_context, &cur_context);
}
+
+/* Resume propagation of an FORCE_UNWIND exception, or to rethrow
+ a normal exception that was handled. */
+
+_Unwind_Reason_Code
+_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc)
+{
+ struct _Unwind_Context this_context, cur_context;
+ _Unwind_Reason_Code code;
+
+ /* Choose between continuing to process _Unwind_RaiseException
+ or _Unwind_ForcedUnwind. */
+ if (exc->private_1 == 0)
+ return _Unwind_RaiseException (exc);
+
+ uw_init_context (&this_context);
+ cur_context = this_context;
+
+ code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
+
+ if (code != _URC_INSTALL_CONTEXT)
+ abort ();
+
+ uw_install_context (&this_context, &cur_context);
+}
+
+
/* A convenience function that calls the exception_cleanup field. */
void
_Unwind_DeleteException (struct _Unwind_Exception *exc)
{
- (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
+ if (exc->exception_cleanup)
+ (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
+}
+
+
+/* Perform stack backtrace through unwind data. */
+
+_Unwind_Reason_Code
+_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument)
+{
+ struct _Unwind_Context context;
+ _Unwind_Reason_Code code;
+
+ uw_init_context (&context);
+
+ while (1)
+ {
+ _Unwind_FrameState fs;
+
+ /* Set up fs to describe the FDE for the caller of context. */
+ code = uw_frame_state_for (&context, &fs);
+ if (code != _URC_NO_REASON && code != _URC_END_OF_STACK)
+ return _URC_FATAL_PHASE1_ERROR;
+
+ /* Call trace function. */
+ if ((*trace) (&context, trace_argument) != _URC_NO_REASON)
+ return _URC_FATAL_PHASE1_ERROR;
+
+ /* We're done at end of stack. */
+ if (code == _URC_END_OF_STACK)
+ break;
+
+ /* Update context to describe the same frame as fs. */
+ uw_update_context (&context, &fs);
+ }
+
+ return code;
}
diff --git a/contrib/gcc/varasm.c b/contrib/gcc/varasm.c
index dcfe381..94be2d4 100644
--- a/contrib/gcc/varasm.c
+++ b/contrib/gcc/varasm.c
@@ -1,6 +1,6 @@
/* Output variables, constants and external declarations, for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -36,12 +36,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "expr.h"
#include "hard-reg-set.h"
#include "regs.h"
-#include "output.h"
#include "real.h"
+#include "output.h"
#include "toplev.h"
-#include "obstack.h"
#include "hashtab.h"
#include "c-pragma.h"
+#include "c-tree.h"
#include "ggc.h"
#include "langhooks.h"
#include "tm_p.h"
@@ -65,17 +65,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
const char *first_global_object_name;
const char *weak_global_object_name;
-extern struct obstack permanent_obstack;
-#define obstack_chunk_alloc xmalloc
-
struct addr_const;
-struct constant_descriptor;
+struct constant_descriptor_rtx;
struct rtx_const;
struct pool_constant;
#define MAX_RTX_HASH_TABLE 61
-struct varasm_status
+struct varasm_status GTY(())
{
/* Hash facility for making memory-constants
from constant rtl-expressions. It is used on RISC machines
@@ -85,19 +82,18 @@ struct varasm_status
This pool of constants is reinitialized for each function
so each function gets its own constants-pool that comes right before
it. */
- struct constant_descriptor **x_const_rtx_hash_table;
- struct pool_constant **x_const_rtx_sym_hash_table;
+ struct constant_descriptor_rtx ** GTY ((length ("MAX_RTX_HASH_TABLE")))
+ x_const_rtx_hash_table;
+ struct pool_constant ** GTY ((length ("MAX_RTX_HASH_TABLE")))
+ x_const_rtx_sym_hash_table;
/* Pointers to first and last constant in pool. */
- struct pool_constant *x_first_pool, *x_last_pool;
+ struct pool_constant *x_first_pool;
+ struct pool_constant *x_last_pool;
/* Current offset in constant pool (does not include any machine-specific
header). */
HOST_WIDE_INT x_pool_offset;
-
- /* Chain of all CONST_DOUBLE rtx's constructed for the current function.
- They are chained through the CONST_DOUBLE_CHAIN. */
- rtx x_const_double_chain;
};
#define const_rtx_hash_table (cfun->varasm->x_const_rtx_hash_table)
@@ -105,7 +101,6 @@ struct varasm_status
#define first_pool (cfun->varasm->x_first_pool)
#define last_pool (cfun->varasm->x_last_pool)
#define pool_offset (cfun->varasm->x_pool_offset)
-#define const_double_chain (cfun->varasm->x_const_double_chain)
/* Number for making the label on the next
constant that is stored in memory. */
@@ -141,21 +136,18 @@ static HOST_WIDE_INT const_alias_set;
static const char *strip_reg_name PARAMS ((const char *));
static int contains_pointers_p PARAMS ((tree));
static void decode_addr_const PARAMS ((tree, struct addr_const *));
-static int const_hash PARAMS ((tree));
-static int compare_constant PARAMS ((tree,
- struct constant_descriptor *));
-static const unsigned char *compare_constant_1 PARAMS ((tree, const unsigned char *));
-static struct constant_descriptor *record_constant PARAMS ((tree));
-static void record_constant_1 PARAMS ((tree));
+static unsigned int const_hash PARAMS ((tree));
+static unsigned int const_hash_1 PARAMS ((tree));
+static int compare_constant PARAMS ((tree, tree));
static tree copy_constant PARAMS ((tree));
static void output_constant_def_contents PARAMS ((tree, int, int));
static void decode_rtx_const PARAMS ((enum machine_mode, rtx,
struct rtx_const *));
-static int const_hash_rtx PARAMS ((enum machine_mode, rtx));
-static int compare_constant_rtx PARAMS ((enum machine_mode, rtx,
- struct constant_descriptor *));
-static struct constant_descriptor *record_constant_rtx PARAMS ((enum machine_mode,
- rtx));
+static unsigned int const_hash_rtx PARAMS ((enum machine_mode, rtx));
+static int compare_constant_rtx
+ PARAMS ((enum machine_mode, rtx, struct constant_descriptor_rtx *));
+static struct constant_descriptor_rtx * record_constant_rtx
+ PARAMS ((enum machine_mode, rtx));
static struct pool_constant *find_pool_constant PARAMS ((struct function *, rtx));
static void mark_constant_pool PARAMS ((void));
static void mark_constants PARAMS ((rtx));
@@ -167,6 +159,7 @@ static unsigned min_align PARAMS ((unsigned, unsigned));
static void output_constructor PARAMS ((tree, HOST_WIDE_INT,
unsigned int));
static void globalize_decl PARAMS ((tree));
+static void maybe_assemble_visibility PARAMS ((tree));
static int in_named_entry_eq PARAMS ((const PTR, const PTR));
static hashval_t in_named_entry_hash PARAMS ((const PTR));
#ifdef ASM_OUTPUT_BSS
@@ -178,14 +171,9 @@ static void asm_output_aligned_bss PARAMS ((FILE *, tree, const char *,
int, int));
#endif
#endif /* BSS_SECTION_ASM_OP */
-static void mark_pool_constant PARAMS ((struct pool_constant *));
-static void mark_const_hash_entry PARAMS ((void *));
-static int mark_const_str_htab_1 PARAMS ((void **, void *));
-static void mark_const_str_htab PARAMS ((void *));
static hashval_t const_str_htab_hash PARAMS ((const void *x));
static int const_str_htab_eq PARAMS ((const void *x, const void *y));
-static void const_str_htab_del PARAMS ((void *));
-static void asm_emit_uninitialised PARAMS ((tree, const char*, int, int));
+static bool asm_emit_uninitialised PARAMS ((tree, const char*, int, int));
static void resolve_unique_section PARAMS ((tree, int, int));
static void mark_weak PARAMS ((tree));
@@ -199,12 +187,15 @@ static enum in_section { no_section, in_text, in_data, in_named
#ifdef DTORS_SECTION_ASM_OP
, in_dtors
#endif
+#ifdef READONLY_DATA_SECTION_ASM_OP
+ , in_readonly_data
+#endif
#ifdef EXTRA_SECTIONS
, EXTRA_SECTIONS
#endif
} in_section = no_section;
-/* Return a non-zero value if DECL has a section attribute. */
+/* Return a nonzero value if DECL has a section attribute. */
#ifndef IN_NAMED_SECTION
#define IN_NAMED_SECTION(DECL) \
((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \
@@ -237,12 +228,12 @@ text_section ()
{
if (in_section != in_text)
{
+ in_section = in_text;
#ifdef TEXT_SECTION
TEXT_SECTION ();
#else
fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
#endif
- in_section = in_text;
}
}
@@ -253,6 +244,7 @@ data_section ()
{
if (in_section != in_data)
{
+ in_section = in_data;
if (flag_shared_data)
{
#ifdef SHARED_SECTION_ASM_OP
@@ -263,10 +255,9 @@ data_section ()
}
else
fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
-
- in_section = in_data;
}
}
+
/* Tell assembler to ALWAYS switch to data section, in case
it's not sure where it is. */
@@ -286,8 +277,17 @@ readonly_data_section ()
#ifdef READONLY_DATA_SECTION
READONLY_DATA_SECTION (); /* Note this can call data_section. */
#else
+#ifdef READONLY_DATA_SECTION_ASM_OP
+ if (in_section != in_readonly_data)
+ {
+ in_section = in_readonly_data;
+ fputs (READONLY_DATA_SECTION_ASM_OP, asm_out_file);
+ fputc ('\n', asm_out_file);
+ }
+#else
text_section ();
#endif
+#endif
}
/* Determine if we're in the text section. */
@@ -338,7 +338,7 @@ get_named_section_flags (section)
{
struct in_named_entry **slot;
- slot = (struct in_named_entry**)
+ slot = (struct in_named_entry **)
htab_find_slot_with_hash (in_named_htab, section,
htab_hash_string (section), NO_INSERT);
@@ -346,7 +346,7 @@ get_named_section_flags (section)
}
/* Returns true if the section has been declared before. Sets internal
- flag on this section in in_named_hash so subsequent calls on this
+ flag on this section in in_named_hash so subsequent calls on this
section will return false. */
bool
@@ -355,15 +355,15 @@ named_section_first_declaration (name)
{
struct in_named_entry **slot;
- slot = (struct in_named_entry**)
- htab_find_slot_with_hash (in_named_htab, name,
+ slot = (struct in_named_entry **)
+ htab_find_slot_with_hash (in_named_htab, name,
htab_hash_string (name), NO_INSERT);
if (! (*slot)->declared)
{
(*slot)->declared = true;
return true;
}
- else
+ else
{
return false;
}
@@ -380,7 +380,7 @@ set_named_section_flags (section, flags)
{
struct in_named_entry **slot, *entry;
- slot = (struct in_named_entry**)
+ slot = (struct in_named_entry **)
htab_find_slot_with_hash (in_named_htab, section,
htab_hash_string (section), INSERT);
entry = *slot;
@@ -411,7 +411,7 @@ named_section_flags (name, flags)
if (! set_named_section_flags (name, flags))
abort ();
- (* targetm.asm_out.named_section) (name, flags);
+ (*targetm.asm_out.named_section) (name, flags);
if (flags & SECTION_FORGET)
in_section = no_section;
@@ -467,10 +467,10 @@ resolve_unique_section (decl, reloc, flag_function_or_data_sections)
int flag_function_or_data_sections;
{
if (DECL_SECTION_NAME (decl) == NULL_TREE
+ && targetm.have_named_sections
&& (flag_function_or_data_sections
- || (targetm.have_named_sections
- && DECL_ONE_ONLY (decl))))
- UNIQUE_SECTION (decl, reloc);
+ || DECL_ONE_ONLY (decl)))
+ (*targetm.asm_out.unique_section) (decl, reloc);
}
#ifdef BSS_SECTION_ASM_OP
@@ -507,7 +507,7 @@ asm_output_bss (file, decl, name, size, rounded)
const char *name;
int size ATTRIBUTE_UNUSED, rounded;
{
- ASM_GLOBALIZE_LABEL (file, name);
+ (*targetm.asm_out.globalize_label) (file, name);
bss_section ();
#ifdef ASM_DECLARE_OBJECT_NAME
last_assemble_variable_decl = decl;
@@ -568,9 +568,8 @@ function_section (decl)
text_section ();
}
-/* Switch to section for variable DECL.
-
- RELOC is the `reloc' argument to SELECT_SECTION. */
+/* Switch to section for variable DECL. RELOC is the same as the
+ argument to SELECT_SECTION. */
void
variable_section (decl, reloc)
@@ -580,52 +579,16 @@ variable_section (decl, 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, DECL_ALIGN (decl));
-#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
-default_exception_section ()
-{
- if (targetm.have_named_sections)
- named_section (NULL_TREE, ".gcc_except_table", 0);
- else if (flag_pic)
- data_section ();
- else
- readonly_data_section ();
+ (*targetm.asm_out.select_section) (decl, reloc, DECL_ALIGN (decl));
}
/* Tell assembler to switch to the section for string merging. */
void
mergeable_string_section (decl, align, flags)
- tree decl ATTRIBUTE_UNUSED;
- unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
- unsigned int flags ATTRIBUTE_UNUSED;
+ tree decl ATTRIBUTE_UNUSED;
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+ unsigned int flags ATTRIBUTE_UNUSED;
{
#ifdef HAVE_GAS_SHF_MERGE
if (flag_merge_constants
@@ -656,7 +619,7 @@ mergeable_string_section (decl, align, flags)
for (i = 0; i < len; i += unit)
{
for (j = 0; j < unit; j++)
- if (str [i + j] != '\0')
+ if (str[i + j] != '\0')
break;
if (j == unit)
break;
@@ -692,15 +655,15 @@ mergeable_string_section (decl, align, flags)
}
#endif
readonly_data_section ();
-}
+}
/* Tell assembler to switch to the section for constant merging. */
void
mergeable_constant_section (mode, align, flags)
- enum machine_mode mode ATTRIBUTE_UNUSED;
- unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
- unsigned int flags ATTRIBUTE_UNUSED;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+ unsigned int flags ATTRIBUTE_UNUSED;
{
#ifdef HAVE_GAS_SHF_MERGE
unsigned int modesize = GET_MODE_BITSIZE (mode);
@@ -719,7 +682,7 @@ mergeable_constant_section (mode, align, flags)
flags |= (align / 8) | SECTION_MERGE;
named_section_flags (name, flags);
return;
- }
+ }
#endif
readonly_data_section ();
}
@@ -728,7 +691,7 @@ mergeable_constant_section (mode, align, flags)
static const char *
strip_reg_name (name)
- const char *name;
+ const char *name;
{
#ifdef REGISTER_PREFIX
if (!strncmp (name, REGISTER_PREFIX, strlen (REGISTER_PREFIX)))
@@ -749,7 +712,7 @@ strip_reg_name (name)
int
decode_reg_name (asmspec)
- const char *asmspec;
+ const char *asmspec;
{
if (asmspec != 0)
{
@@ -846,17 +809,15 @@ make_decl_rtl (decl, asmspec)
SET_DECL_RTL (decl, adjust_address_nv (DECL_RTL (decl),
DECL_MODE (decl), 0));
- /* ??? Another way to do this would be to do what halfpic.c does
- and maintain a hashed table of such critters. */
- /* ??? Another way to do this would be to pass a flag bit to
- ENCODE_SECTION_INFO saying whether this is a new decl or not. */
+ /* ??? Another way to do this would be to maintain a hashed
+ table of such critters. Instead of adding stuff to a DECL
+ to give certain attributes to it, we could use an external
+ hash map from DECL to set of attributes. */
+
/* Let the target reassign the RTL if it wants.
This is necessary, for example, when one machine specific
decl attribute overrides another. */
-#ifdef REDO_SECTION_INFO_P
- if (REDO_SECTION_INFO_P (decl))
- ENCODE_SECTION_INFO (decl);
-#endif
+ (* targetm.encode_section_info) (decl, false);
return;
}
@@ -940,6 +901,10 @@ make_decl_rtl (decl, asmspec)
&& DECL_COMMON (decl))
DECL_COMMON (decl) = 0;
+ /* Variables can't be both common and weak. */
+ if (TREE_CODE (decl) == VAR_DECL && DECL_WEAK (decl))
+ DECL_COMMON (decl) = 0;
+
/* Can't use just the variable's own name for a variable
whose scope is less than the whole file, unless it's a member
of a local class (which will already be unambiguous).
@@ -980,9 +945,7 @@ make_decl_rtl (decl, asmspec)
such as that it is a function name.
If the name is changed, the macro ASM_OUTPUT_LABELREF
will have to know how to strip this information. */
-#ifdef ENCODE_SECTION_INFO
- ENCODE_SECTION_INFO (decl);
-#endif
+ (* targetm.encode_section_info) (decl, true);
}
/* Make the rtl for variable VAR be volatile.
@@ -1160,7 +1123,7 @@ default_ctor_section_asm_out_constructor (symbol, priority)
#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
+ a nonzero 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. */
@@ -1203,11 +1166,12 @@ assemble_start_function (decl, fnname)
/* Handle a user-specified function alignment.
Note that we still need to align to FUNCTION_BOUNDARY, as above,
because ASM_OUTPUT_MAX_SKIP_ALIGN might not do any alignment at all. */
- if (align_functions_log > align)
+ if (align_functions_log > align
+ && cfun->function_frequency != FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
{
#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file,
- align_functions_log, align_functions-1);
+ align_functions_log, align_functions - 1);
#else
ASM_OUTPUT_ALIGN (asm_out_file, align_functions_log);
#endif
@@ -1228,9 +1192,8 @@ assemble_start_function (decl, fnname)
const char *p;
char *name;
- STRIP_NAME_ENCODING (p, fnname);
- name = permalloc (strlen (p) + 1);
- strcpy (name, p);
+ p = (* targetm.strip_name_encoding) (fnname);
+ name = xstrdup (p);
if (! DECL_WEAK (decl) && ! DECL_ONE_ONLY (decl))
first_global_object_name = name;
@@ -1239,6 +1202,8 @@ assemble_start_function (decl, fnname)
}
globalize_decl (decl);
+
+ maybe_assemble_visibility (decl);
}
/* Do any machine/system dependent processing of the function name */
@@ -1372,10 +1337,10 @@ assemble_string (p, size)
#endif
#endif
-static void
+static bool
asm_emit_uninitialised (decl, name, size, rounded)
tree decl;
- const char * name;
+ const char *name;
int size ATTRIBUTE_UNUSED;
int rounded ATTRIBUTE_UNUSED;
{
@@ -1387,13 +1352,17 @@ asm_emit_uninitialised (decl, name, size, rounded)
}
destination = asm_dest_local;
+ /* ??? We should handle .bss via select_section mechanisms rather than
+ via special target hooks. That would eliminate this special case. */
if (TREE_PUBLIC (decl))
{
-#if defined ASM_EMIT_BSS
- if (! DECL_COMMON (decl))
+ if (!DECL_COMMON (decl))
+#ifdef ASM_EMIT_BSS
destination = asm_dest_bss;
- else
+#else
+ return false;
#endif
+ else
destination = asm_dest_common;
}
@@ -1442,7 +1411,7 @@ asm_emit_uninitialised (decl, name, size, rounded)
abort ();
}
- return;
+ return true;
}
/* Assemble everything that is needed for a variable or function declaration.
@@ -1516,7 +1485,8 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
if (TREE_ASM_WRITTEN (decl))
return;
- /* Make sure ENCODE_SECTION_INFO is invoked before we set ASM_WRITTEN. */
+ /* Make sure targetm.encode_section_info is invoked before we set
+ ASM_WRITTEN. */
decl_rtl = DECL_RTL (decl);
TREE_ASM_WRITTEN (decl) = 1;
@@ -1545,9 +1515,8 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
const char *p;
char *xname;
- STRIP_NAME_ENCODING (p, name);
- xname = permalloc (strlen (p) + 1);
- strcpy (xname, p);
+ p = (* targetm.strip_name_encoding) (name);
+ xname = xstrdup (p);
first_global_object_name = xname;
}
@@ -1571,7 +1540,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
{
warning_with_decl (decl,
"alignment of `%s' is greater than maximum object file alignment. Using %d",
- MAX_OFILE_ALIGNMENT/BITS_PER_UNIT);
+ MAX_OFILE_ALIGNMENT/BITS_PER_UNIT);
align = MAX_OFILE_ALIGNMENT;
}
@@ -1583,7 +1552,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
#endif
#ifdef CONSTANT_ALIGNMENT
if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node)
- align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align);
+ align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align);
#endif
}
@@ -1592,16 +1561,34 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
DECL_ALIGN (decl) = align;
set_mem_align (decl_rtl, align);
+ if (TREE_PUBLIC (decl))
+ maybe_assemble_visibility (decl);
+
+ /* Output any data that we will need to use the address of. */
+ if (DECL_INITIAL (decl) == error_mark_node)
+ reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0;
+ else if (DECL_INITIAL (decl))
+ reloc = output_addressed_constants (DECL_INITIAL (decl));
+ resolve_unique_section (decl, reloc, flag_data_sections);
+
/* Handle uninitialized definitions. */
- 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_EMIT_BSS
- && DECL_COMMON (decl)
-#endif
- && DECL_SECTION_NAME (decl) == NULL_TREE
- && ! dont_output_data)
+ /* If the decl has been given an explicit section name, then it
+ isn't common, and shouldn't be handled as such. */
+ if (DECL_SECTION_NAME (decl) || dont_output_data)
+ ;
+ /* We don't implement common thread-local data at present. */
+ else if (DECL_THREAD_LOCAL (decl))
+ {
+ if (DECL_COMMON (decl))
+ sorry ("thread-local COMMON data not implemented");
+ }
+ else if (DECL_INITIAL (decl) == 0
+ || DECL_INITIAL (decl) == error_mark_node
+ || (flag_zero_initialized_in_bss
+ /* Leave constant zeroes in .rodata so they can be shared. */
+ && !TREE_READONLY (decl)
+ && initializer_zerop (DECL_INITIAL (decl))))
{
unsigned HOST_WIDE_INT size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
unsigned HOST_WIDE_INT rounded = size;
@@ -1617,16 +1604,16 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
* (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
-/* Don't continue this line--convex cc version 4.1 would lose. */
#if !defined(ASM_OUTPUT_ALIGNED_COMMON) && !defined(ASM_OUTPUT_ALIGNED_DECL_COMMON) && !defined(ASM_OUTPUT_ALIGNED_BSS)
if ((unsigned HOST_WIDE_INT) DECL_ALIGN (decl) / BITS_PER_UNIT > rounded)
- warning_with_decl
- (decl, "requested alignment for %s is greater than implemented alignment of %d",rounded);
+ warning_with_decl
+ (decl, "requested alignment for %s is greater than implemented alignment of %d",rounded);
#endif
- asm_emit_uninitialised (decl, name, size, rounded);
-
- return;
+ /* If the target cannot output uninitialized but not common global data
+ in .bss, then we have to use .data, so fall through. */
+ if (asm_emit_uninitialised (decl, name, size, rounded))
+ return;
}
/* Handle initialized definitions.
@@ -1637,14 +1624,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
if (TREE_PUBLIC (decl) && DECL_NAME (decl))
globalize_decl (decl);
- /* Output any data that we will need to use the address of. */
- if (DECL_INITIAL (decl) == error_mark_node)
- reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0;
- else if (DECL_INITIAL (decl))
- reloc = output_addressed_constants (DECL_INITIAL (decl));
-
/* Switch to the appropriate section. */
- resolve_unique_section (decl, reloc, flag_data_sections);
variable_section (decl, reloc);
/* dbxout.c needs to know this. */
@@ -1764,15 +1744,6 @@ assemble_external_libcall (fun)
#endif
}
-/* Declare the label NAME global. */
-
-void
-assemble_global (name)
- const char *name ATTRIBUTE_UNUSED;
-{
- ASM_GLOBALIZE_LABEL (asm_out_file, name);
-}
-
/* Assemble a label named NAME. */
void
@@ -1796,7 +1767,7 @@ assemble_name (file, name)
const char *real_name;
tree id;
- STRIP_NAME_ENCODING (real_name, name);
+ real_name = (* targetm.strip_name_encoding) (name);
id = maybe_get_identifier (real_name);
if (id)
@@ -1963,7 +1934,7 @@ default_assemble_integer (x, size, aligned_p)
/* Assemble the integer constant X into an object of SIZE bytes. ALIGN is
the alignment of the integer in bits. Return 1 if we were able to output
- the constant, otherwise 0. If FORCE is non-zero, abort if we can't output
+ the constant, otherwise 0. If FORCE is nonzero, abort if we can't output
the constant. */
bool
@@ -2096,202 +2067,12 @@ assemble_real (d, mode, align)
}
}
-/* Here we combine duplicate floating constants to make
- CONST_DOUBLE rtx's, and force those out to memory when necessary. */
-
-/* Return a CONST_DOUBLE or CONST_INT for a value specified as a pair of ints.
- For an integer, I0 is the low-order word and I1 is the high-order word.
- For a real number, I0 is the word with the low address
- and I1 is the word with the high address. */
-
-rtx
-immed_double_const (i0, i1, mode)
- HOST_WIDE_INT i0, i1;
- enum machine_mode mode;
-{
- rtx r;
-
- if (GET_MODE_CLASS (mode) == MODE_INT
- || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
- {
- /* We clear out all bits that don't belong in MODE, unless they and our
- sign bit are all one. So we get either a reasonable negative value
- or a reasonable unsigned value for this mode. */
- int width = GET_MODE_BITSIZE (mode);
- if (width < HOST_BITS_PER_WIDE_INT
- && ((i0 & ((HOST_WIDE_INT) (-1) << (width - 1)))
- != ((HOST_WIDE_INT) (-1) << (width - 1))))
- i0 &= ((HOST_WIDE_INT) 1 << width) - 1, i1 = 0;
- else if (width == HOST_BITS_PER_WIDE_INT
- && ! (i1 == ~0 && i0 < 0))
- i1 = 0;
- else if (width > 2 * HOST_BITS_PER_WIDE_INT)
- /* We cannot represent this value as a constant. */
- abort ();
-
- /* If this would be an entire word for the target, but is not for
- the host, then sign-extend on the host so that the number will look
- the same way on the host that it would on the target.
-
- For example, when building a 64 bit alpha hosted 32 bit sparc
- targeted compiler, then we want the 32 bit unsigned value -1 to be
- represented as a 64 bit value -1, and not as 0x00000000ffffffff.
- The later confuses the sparc backend. */
-
- if (width < HOST_BITS_PER_WIDE_INT
- && (i0 & ((HOST_WIDE_INT) 1 << (width - 1))))
- i0 |= ((HOST_WIDE_INT) (-1) << width);
-
- /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a CONST_INT.
-
- ??? Strictly speaking, this is wrong if we create a CONST_INT
- for a large unsigned constant with the size of MODE being
- HOST_BITS_PER_WIDE_INT and later try to interpret that constant in a
- wider mode. In that case we will mis-interpret it as a negative
- number.
-
- Unfortunately, the only alternative is to make a CONST_DOUBLE
- for any constant in any mode if it is an unsigned constant larger
- than the maximum signed integer in an int on the host. However,
- doing this will break everyone that always expects to see a CONST_INT
- for SImode and smaller.
-
- We have always been making CONST_INTs in this case, so nothing new
- is being broken. */
-
- if (width <= HOST_BITS_PER_WIDE_INT)
- i1 = (i0 < 0) ? ~(HOST_WIDE_INT) 0 : 0;
-
- /* If this integer fits in one word, return a CONST_INT. */
- if ((i1 == 0 && i0 >= 0)
- || (i1 == ~0 && i0 < 0))
- return GEN_INT (i0);
-
- /* We use VOIDmode for integers. */
- mode = VOIDmode;
- }
-
- /* Search the chain for an existing CONST_DOUBLE with the right value.
- If one is found, return it. */
- if (cfun != 0)
- for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r))
- if (CONST_DOUBLE_LOW (r) == i0 && CONST_DOUBLE_HIGH (r) == i1
- && GET_MODE (r) == mode)
- return r;
-
- /* No; make a new one and add it to the chain. */
- r = gen_rtx_CONST_DOUBLE (mode, i0, i1);
-
- /* Don't touch const_double_chain if not inside any function. */
- if (current_function_decl != 0)
- {
- CONST_DOUBLE_CHAIN (r) = const_double_chain;
- const_double_chain = r;
- }
-
- return r;
-}
-
-/* Return a CONST_DOUBLE for a specified `double' value
- and machine mode. */
-
-rtx
-immed_real_const_1 (d, mode)
- REAL_VALUE_TYPE d;
- enum machine_mode mode;
-{
- union real_extract u;
- rtx r;
-
- /* Get the desired `double' value as a sequence of ints
- since that is how they are stored in a CONST_DOUBLE. */
-
- u.d = d;
-
- /* Detect special cases. 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 dump here if we pass a NaN to REAL_VALUES_EQUAL
- and if REAL_VALUES_EQUAL does a floating point comparison. */
- if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_IDENTICAL (dconst0, d))
- return CONST0_RTX (mode);
- else if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_EQUAL (dconst1, d))
- return CONST1_RTX (mode);
- else if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_EQUAL (dconst2, d))
- return CONST2_RTX (mode);
-
- if (sizeof u == sizeof (HOST_WIDE_INT))
- return immed_double_const (u.i[0], 0, mode);
- if (sizeof u == 2 * sizeof (HOST_WIDE_INT))
- return immed_double_const (u.i[0], u.i[1], mode);
-
- /* The rest of this function handles the case where
- a float value requires more than 2 ints of space.
- It will be deleted as dead code on machines that don't need it. */
-
- /* Search the chain for an existing CONST_DOUBLE with the right value.
- If one is found, return it. */
- if (cfun != 0)
- for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r))
- if (! memcmp ((char *) &CONST_DOUBLE_LOW (r), (char *) &u, sizeof u)
- && GET_MODE (r) == mode)
- return r;
-
- /* No; make a new one and add it to the chain.
-
- We may be called by an optimizer which may be discarding any memory
- allocated during its processing (such as combine and loop). However,
- we will be leaving this constant on the chain, so we cannot tolerate
- freed memory. */
- r = rtx_alloc (CONST_DOUBLE);
- PUT_MODE (r, mode);
- memcpy ((char *) &CONST_DOUBLE_LOW (r), (char *) &u, sizeof u);
-
- /* If we aren't inside a function, don't put r on the
- const_double_chain. */
- if (current_function_decl != 0)
- {
- CONST_DOUBLE_CHAIN (r) = const_double_chain;
- const_double_chain = r;
- }
- else
- CONST_DOUBLE_CHAIN (r) = NULL_RTX;
-
- return r;
-}
-
-/* Return a CONST_DOUBLE rtx for a value specified by EXP,
- which must be a REAL_CST tree node. */
-
-rtx
-immed_real_const (exp)
- tree exp;
-{
- return immed_real_const_1 (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)));
-}
-
-/* At the end of a function, forget the memory-constants
- previously made for CONST_DOUBLEs. Mark them as not on real_constant_chain.
- Also clear out real_constant_chain and clear out all the chain-pointers. */
-
-void
-clear_const_double_mem ()
-{
- rtx r, next;
-
- for (r = const_double_chain; r; r = next)
- {
- next = CONST_DOUBLE_CHAIN (r);
- CONST_DOUBLE_CHAIN (r) = 0;
- }
- const_double_chain = 0;
-}
-
/* Given an expression EXP with a constant value,
reduce it to the sum of an assembler symbol and an integer.
Store them both in the structure *VALUE.
Abort if EXP does not reduce. */
-struct addr_const
+struct addr_const GTY(())
{
rtx base;
HOST_WIDE_INT offset;
@@ -2362,103 +2143,73 @@ decode_addr_const (exp, value)
}
/* We do RTX_UNSPEC + XINT (blah), so nothing can go after RTX_UNSPEC. */
-enum kind { RTX_UNKNOWN, RTX_DOUBLE, RTX_INT, RTX_VECTOR, RTX_UNSPEC };
-struct rtx_const
+enum kind { RTX_UNKNOWN, RTX_DOUBLE, RTX_VECTOR, RTX_INT, RTX_UNSPEC };
+struct rtx_const GTY(())
{
ENUM_BITFIELD(kind) kind : 16;
ENUM_BITFIELD(machine_mode) mode : 16;
- union {
- union real_extract du;
- struct addr_const addr;
- struct {HOST_WIDE_INT high, low;} di;
-
- /* The max vector size we have is 8 wide. This should be enough. */
- HOST_WIDE_INT veclo[16];
- HOST_WIDE_INT vechi[16];
- } un;
+ union rtx_const_un {
+ REAL_VALUE_TYPE du;
+ struct rtx_const_u_addr {
+ rtx base;
+ const char *symbol;
+ HOST_WIDE_INT offset;
+ } GTY ((tag ("1"))) addr;
+ struct rtx_const_u_di {
+ HOST_WIDE_INT high;
+ HOST_WIDE_INT low;
+ } GTY ((tag ("0"))) di;
+
+ /* The max vector size we have is 16 wide; two variants for
+ integral and floating point vectors. */
+ struct rtx_const_int_vec {
+ HOST_WIDE_INT high;
+ HOST_WIDE_INT low;
+ } GTY ((tag ("2"))) int_vec[16];
+
+ REAL_VALUE_TYPE GTY ((tag ("3"))) fp_vec[8];
+
+ } GTY ((desc ("%1.kind >= RTX_INT"), descbits ("1"))) un;
};
/* Uniquize all constants that appear in memory.
Each constant in memory thus far output is recorded
- in `const_hash_table' with a `struct constant_descriptor'
- that contains a polish representation of the value of
- the constant.
-
- We cannot store the trees in the hash table
- because the trees may be temporary. */
+ in `const_hash_table'. */
-struct constant_descriptor
+struct constant_descriptor_tree GTY(())
{
- struct constant_descriptor *next;
+ /* More constant_descriptors with the same hash code. */
+ struct constant_descriptor_tree *next;
+
+ /* The label of the constant. */
const char *label;
+
+ /* A MEM for the constant. */
rtx rtl;
- /* Make sure the data is reasonably aligned. */
- union
- {
- unsigned char contents[1];
-#ifdef HAVE_LONG_DOUBLE
- long double d;
-#else
- double d;
-#endif
- } u;
+
+ /* The value of the constant. */
+ tree value;
};
-#define HASHBITS 30
#define MAX_HASH_TABLE 1009
-static struct constant_descriptor *const_hash_table[MAX_HASH_TABLE];
+static GTY(()) struct constant_descriptor_tree *
+ const_hash_table[MAX_HASH_TABLE];
/* We maintain a hash table of STRING_CST values. Unless we are asked to force
out a string constant, we defer output of the constants until we know
they are actually used. This will be if something takes its address or if
there is a usage of the string in the RTL of a function. */
-#define STRHASH(x) ((hashval_t) ((long) (x) >> 3))
+#define STRHASH(x) htab_hash_pointer (x)
-struct deferred_string
+struct deferred_string GTY(())
{
const char *label;
tree exp;
int labelno;
};
-static htab_t const_str_htab;
-
-/* Mark a const_hash_table descriptor for GC. */
-
-static void
-mark_const_hash_entry (ptr)
- void *ptr;
-{
- struct constant_descriptor *desc = * (struct constant_descriptor **) ptr;
-
- while (desc)
- {
- ggc_mark_rtx (desc->rtl);
- desc = desc->next;
- }
-}
-
-/* Mark the hash-table element X (which is really a pointer to an
- struct deferred_string *). */
-
-static int
-mark_const_str_htab_1 (x, data)
- void **x;
- void *data ATTRIBUTE_UNUSED;
-{
- ggc_mark_tree (((struct deferred_string *) *x)->exp);
- return 1;
-}
-
-/* Mark a const_str_htab for GC. */
-
-static void
-mark_const_str_htab (htab)
- void *htab;
-{
- htab_traverse (*((htab_t *) htab), mark_const_str_htab_1, NULL);
-}
+static GTY ((param_is (struct deferred_string))) htab_t const_str_htab;
/* Returns a hash code for X (which is a really a
struct deferred_string *). */
@@ -2470,7 +2221,7 @@ const_str_htab_hash (x)
return STRHASH (((const struct deferred_string *) x)->label);
}
-/* Returns non-zero if the value represented by X (which is really a
+/* Returns nonzero if the value represented by X (which is really a
struct deferred_string *) is the same as that given by Y
(which is really a char *). */
@@ -2482,23 +2233,22 @@ const_str_htab_eq (x, y)
return (((const struct deferred_string *) x)->label == (const char *) y);
}
-/* Delete the hash table entry dfsp. */
+/* Compute a hash code for a constant expression. */
-static void
-const_str_htab_del (dfsp)
- void *dfsp;
+static unsigned int
+const_hash (exp)
+ tree exp;
{
- free (dfsp);
+ return const_hash_1 (exp) % MAX_HASH_TABLE;
}
-/* Compute a hash code for a constant expression. */
-
-static int
-const_hash (exp)
+static unsigned int
+const_hash_1 (exp)
tree exp;
{
const char *p;
- int len, hi, i;
+ unsigned int hi;
+ int len, i;
enum tree_code code = TREE_CODE (exp);
/* Either set P and LEN to the address and len of something to hash and
@@ -2512,9 +2262,7 @@ const_hash (exp)
break;
case REAL_CST:
- p = (char *) &TREE_REAL_CST (exp);
- len = sizeof TREE_REAL_CST (exp);
- break;
+ return real_hash (TREE_REAL_CST_PTR (exp));
case STRING_CST:
p = TREE_STRING_POINTER (exp);
@@ -2522,8 +2270,8 @@ const_hash (exp)
break;
case COMPLEX_CST:
- return (const_hash (TREE_REALPART (exp)) * 5
- + const_hash (TREE_IMAGPART (exp)));
+ return (const_hash_1 (TREE_REALPART (exp)) * 5
+ + const_hash_1 (TREE_IMAGPART (exp)));
case CONSTRUCTOR:
if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
@@ -2540,23 +2288,11 @@ const_hash (exp)
{
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 = ((unsigned long) 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;
+ hi = 5 + int_size_in_bytes (TREE_TYPE (exp));
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;
+ hi = hi * 603 + const_hash_1 (TREE_VALUE (link));
return hi;
}
@@ -2580,25 +2316,22 @@ const_hash (exp)
hi = value.offset + CODE_LABEL_NUMBER (XEXP (value.base, 0)) * 13;
else
abort ();
-
- 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)));
+ return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9
+ + const_hash_1 (TREE_OPERAND (exp, 1)));
case NOP_EXPR:
case CONVERT_EXPR:
case NON_LVALUE_EXPR:
- return const_hash (TREE_OPERAND (exp, 0)) * 7 + 2;
+ return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2;
default:
/* A language specific constant. Just hash the code. */
- return (int) code % MAX_HASH_TABLE;
+ return code;
}
/* Compute hashing function */
@@ -2606,462 +2339,161 @@ const_hash (exp)
for (i = 0; i < len; i++)
hi = ((hi * 613) + (unsigned) (p[i]));
- hi &= (1 << HASHBITS) - 1;
- hi %= MAX_HASH_TABLE;
return hi;
}
-
-/* Compare a constant expression EXP with a constant-descriptor DESC.
- Return 1 if DESC describes a constant with the same value as EXP. */
-
-static int
-compare_constant (exp, desc)
- tree exp;
- struct constant_descriptor *desc;
-{
- return 0 != compare_constant_1 (exp, desc->u.contents);
-}
-
-/* Compare constant expression EXP with a substring P of a constant descriptor.
- If they match, return a pointer to the end of the substring matched.
- If they do not match, return 0.
- Since descriptors are written in polish prefix notation,
- this function can be used recursively to test one operand of EXP
- against a subdescriptor, and if it succeeds it returns the
- address of the subdescriptor for the next operand. */
+/* Compare t1 and t2, and return 1 only if they are known to result in
+ the same bit pattern on output. */
-static const unsigned char *
-compare_constant_1 (exp, p)
- tree exp;
- const unsigned char *p;
+static int
+compare_constant (t1, t2)
+ tree t1;
+ tree t2;
{
- const unsigned char *strp;
- int len;
- enum tree_code code = TREE_CODE (exp);
+ enum tree_code typecode;
- if (code != (enum tree_code) *p++)
+ if (t1 == NULL_TREE)
+ return t2 == NULL_TREE;
+ if (t2 == NULL_TREE)
return 0;
- /* Either set STRP, P and LEN to pointers and length to compare and exit the
- switch, or return the result of the comparison. */
+ if (TREE_CODE (t1) != TREE_CODE (t2))
+ return 0;
- switch (code)
+ switch (TREE_CODE (t1))
{
case INTEGER_CST:
/* Integer constants are the same only if the same width of type. */
- if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
+ if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
return 0;
-
- strp = (unsigned char *) &TREE_INT_CST (exp);
- len = sizeof TREE_INT_CST (exp);
- break;
+ return tree_int_cst_equal (t1, t2);
case REAL_CST:
/* Real constants are the same only if the same width of type. */
- if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
+ if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
return 0;
- strp = (unsigned char *) &TREE_REAL_CST (exp);
- len = sizeof TREE_REAL_CST (exp);
- break;
+ return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
case STRING_CST:
if (flag_writable_strings)
return 0;
- if ((enum machine_mode) *p++ != TYPE_MODE (TREE_TYPE (exp)))
+ if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
return 0;
- strp = (const unsigned char *) TREE_STRING_POINTER (exp);
- len = TREE_STRING_LENGTH (exp);
- if (memcmp ((char *) &TREE_STRING_LENGTH (exp), p,
- sizeof TREE_STRING_LENGTH (exp)))
- return 0;
-
- p += sizeof TREE_STRING_LENGTH (exp);
- break;
+ return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
+ && ! memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
+ TREE_STRING_LENGTH (t1)));
case COMPLEX_CST:
- p = compare_constant_1 (TREE_REALPART (exp), p);
- if (p == 0)
- return 0;
-
- return compare_constant_1 (TREE_IMAGPART (exp), p);
+ return (compare_constant (TREE_REALPART (t1), TREE_REALPART (t2))
+ && compare_constant (TREE_IMAGPART (t1), TREE_IMAGPART (t2)));
case CONSTRUCTOR:
- if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
- {
- int xlen = len = int_size_in_bytes (TREE_TYPE (exp));
- unsigned char *tmp = (unsigned char *) alloca (len);
-
- get_set_constructor_bytes (exp, tmp, len);
- strp = (unsigned char *) tmp;
- if (memcmp ((char *) &xlen, p, sizeof xlen))
- return 0;
+ typecode = TREE_CODE (TREE_TYPE (t1));
+ if (typecode != TREE_CODE (TREE_TYPE (t2)))
+ return 0;
- p += sizeof xlen;
- break;
- }
- else
+ if (typecode == SET_TYPE)
{
- tree link;
- int length = list_length (CONSTRUCTOR_ELTS (exp));
- tree type;
- enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
- int have_purpose = 0;
+ int len = int_size_in_bytes (TREE_TYPE (t2));
+ unsigned char *tmp1, *tmp2;
- for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
- if (TREE_PURPOSE (link))
- have_purpose = 1;
-
- if (memcmp ((char *) &length, p, sizeof length))
+ if (int_size_in_bytes (TREE_TYPE (t1)) != len)
return 0;
- p += sizeof length;
-
- /* For record constructors, insist that the types match.
- For arrays, just verify both constructors are for arrays.
- Then insist that either both or none have any TREE_PURPOSE
- values. */
- if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
- type = TREE_TYPE (exp);
- else
- type = 0;
+ tmp1 = (unsigned char *) alloca (len);
+ tmp2 = (unsigned char *) alloca (len);
- if (memcmp ((char *) &type, p, sizeof type))
+ if (get_set_constructor_bytes (t1, tmp1, len) != NULL_TREE)
+ return 0;
+ if (get_set_constructor_bytes (t2, tmp2, len) != NULL_TREE)
return 0;
- if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+ return memcmp (tmp1, tmp2, len) != 0;
+ }
+ else
+ {
+ tree l1, l2;
+
+ if (typecode == ARRAY_TYPE)
{
- if (memcmp ((char *) &mode, p, sizeof mode))
+ HOST_WIDE_INT size_1 = int_size_in_bytes (TREE_TYPE (t1));
+ /* For arrays, check that the sizes all match. */
+ if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))
+ || size_1 == -1
+ || size_1 != int_size_in_bytes (TREE_TYPE (t2)))
return 0;
-
- p += sizeof mode;
}
-
- p += sizeof type;
-
- if (memcmp ((char *) &have_purpose, p, sizeof have_purpose))
- return 0;
-
- p += sizeof have_purpose;
-
- /* For arrays, insist that the size in bytes match. */
- if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+ else
{
- HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
-
- if (memcmp ((char *) &size, p, sizeof size))
+ /* For record and union constructors, require exact type
+ equality. */
+ if (TREE_TYPE (t1) != TREE_TYPE (t2))
return 0;
-
- p += sizeof size;
}
- for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
+ for (l1 = CONSTRUCTOR_ELTS (t1), l2 = CONSTRUCTOR_ELTS (t2);
+ l1 && l2;
+ l1 = TREE_CHAIN (l1), l2 = TREE_CHAIN (l2))
{
- if (TREE_VALUE (link))
+ /* Check that each value is the same... */
+ if (! compare_constant (TREE_VALUE (l1), TREE_VALUE (l2)))
+ return 0;
+ /* ... and that they apply to the same fields! */
+ if (typecode == ARRAY_TYPE)
{
- if ((p = compare_constant_1 (TREE_VALUE (link), p)) == 0)
+ if (! compare_constant (TREE_PURPOSE (l1),
+ TREE_PURPOSE (l2)))
return 0;
}
else
{
- tree zero = 0;
-
- if (memcmp ((char *) &zero, p, sizeof zero))
- return 0;
-
- p += sizeof zero;
- }
-
- if (TREE_PURPOSE (link)
- && TREE_CODE (TREE_PURPOSE (link)) == FIELD_DECL)
- {
- if (memcmp ((char *) &TREE_PURPOSE (link), p,
- sizeof TREE_PURPOSE (link)))
- return 0;
-
- p += sizeof TREE_PURPOSE (link);
- }
- else if (TREE_PURPOSE (link))
- {
- if ((p = compare_constant_1 (TREE_PURPOSE (link), p)) == 0)
+ if (TREE_PURPOSE (l1) != TREE_PURPOSE (l2))
return 0;
}
- else if (have_purpose)
- {
- int zero = 0;
-
- if (memcmp ((char *) &zero, p, sizeof zero))
- return 0;
-
- p += sizeof zero;
- }
}
- return p;
+ return l1 == NULL_TREE && l2 == NULL_TREE;
}
case ADDR_EXPR:
case FDESC_EXPR:
{
- struct addr_const value;
+ struct addr_const value1, value2;
- decode_addr_const (exp, &value);
- strp = (unsigned char *) &value.offset;
- len = sizeof value.offset;
- /* Compare the offset. */
- while (--len >= 0)
- if (*p++ != *strp++)
- return 0;
-
- /* Compare symbol name. */
- strp = (const unsigned char *) XSTR (value.base, 0);
- len = strlen ((const char *) strp) + 1;
+ decode_addr_const (t1, &value1);
+ decode_addr_const (t2, &value2);
+ return (value1.offset == value2.offset
+ && strcmp (XSTR (value1.base, 0), XSTR (value2.base, 0)) == 0);
}
- break;
case PLUS_EXPR:
case MINUS_EXPR:
case RANGE_EXPR:
- p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
- if (p == 0)
- return 0;
-
- return compare_constant_1 (TREE_OPERAND (exp, 1), p);
+ return (compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0))
+ && compare_constant(TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)));
case NOP_EXPR:
case CONVERT_EXPR:
case NON_LVALUE_EXPR:
- return compare_constant_1 (TREE_OPERAND (exp, 0), p);
+ return compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
default:
{
- tree new = (*lang_hooks.expand_constant) (exp);
-
- if (new != exp)
- return compare_constant_1 (new, p);
+ tree nt1, nt2;
+ nt1 = (*lang_hooks.expand_constant) (t1);
+ nt2 = (*lang_hooks.expand_constant) (t2);
+ if (nt1 != t1 || nt2 != t2)
+ return compare_constant (nt1, nt2);
else
return 0;
}
}
- /* Compare constant contents. */
- while (--len >= 0)
- if (*p++ != *strp++)
- return 0;
-
- return p;
-}
-
-/* Construct a constant descriptor for the expression EXP.
- It is up to the caller to enter the descriptor in the hash table. */
-
-static struct constant_descriptor *
-record_constant (exp)
- tree exp;
-{
- struct constant_descriptor *next = 0;
- char *label = 0;
- rtx rtl = 0;
- int pad;
-
- /* Make a struct constant_descriptor. The first three pointers will
- be filled in later. Here we just leave space for them. */
-
- obstack_grow (&permanent_obstack, (char *) &next, sizeof next);
- obstack_grow (&permanent_obstack, (char *) &label, sizeof label);
- obstack_grow (&permanent_obstack, (char *) &rtl, sizeof rtl);
-
- /* Align the descriptor for the data payload. */
- pad = (offsetof (struct constant_descriptor, u)
- - offsetof(struct constant_descriptor, rtl)
- - sizeof(next->rtl));
- if (pad > 0)
- obstack_blank (&permanent_obstack, pad);
-
- record_constant_1 (exp);
- return (struct constant_descriptor *) obstack_finish (&permanent_obstack);
-}
-
-/* Add a description of constant expression EXP
- to the object growing in `permanent_obstack'.
- No need to return its address; the caller will get that
- from the obstack when the object is complete. */
-
-static void
-record_constant_1 (exp)
- tree exp;
-{
- const unsigned char *strp;
- int len;
- enum tree_code code = TREE_CODE (exp);
-
- obstack_1grow (&permanent_obstack, (unsigned int) code);
-
- switch (code)
- {
- case INTEGER_CST:
- obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp)));
- strp = (unsigned char *) &TREE_INT_CST (exp);
- len = sizeof TREE_INT_CST (exp);
- break;
-
- case REAL_CST:
- obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp)));
- strp = (unsigned char *) &TREE_REAL_CST (exp);
- len = sizeof TREE_REAL_CST (exp);
- break;
-
- case STRING_CST:
- if (flag_writable_strings)
- return;
-
- obstack_1grow (&permanent_obstack, TYPE_MODE (TREE_TYPE (exp)));
- strp = (const unsigned char *) TREE_STRING_POINTER (exp);
- len = TREE_STRING_LENGTH (exp);
- obstack_grow (&permanent_obstack, (char *) &TREE_STRING_LENGTH (exp),
- sizeof TREE_STRING_LENGTH (exp));
- break;
-
- case COMPLEX_CST:
- record_constant_1 (TREE_REALPART (exp));
- record_constant_1 (TREE_IMAGPART (exp));
- return;
-
- case CONSTRUCTOR:
- if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
- {
- int nbytes = int_size_in_bytes (TREE_TYPE (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,
- nbytes);
- return;
- }
- else
- {
- tree link;
- int length = list_length (CONSTRUCTOR_ELTS (exp));
- enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
- tree type;
- int have_purpose = 0;
-
- for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
- if (TREE_PURPOSE (link))
- have_purpose = 1;
-
- obstack_grow (&permanent_obstack, (char *) &length, sizeof length);
-
- /* For record constructors, insist that the types match.
- For arrays, just verify both constructors are for arrays
- of the same mode. Then insist that either both or none
- have any TREE_PURPOSE values. */
- if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
- type = TREE_TYPE (exp);
- else
- type = 0;
-
- obstack_grow (&permanent_obstack, (char *) &type, sizeof type);
- if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
- obstack_grow (&permanent_obstack, &mode, sizeof mode);
-
- obstack_grow (&permanent_obstack, (char *) &have_purpose,
- sizeof have_purpose);
-
- /* For arrays, insist that the size in bytes match. */
- if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
- {
- HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
- obstack_grow (&permanent_obstack, (char *) &size, sizeof size);
- }
-
- for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
- {
- if (TREE_VALUE (link))
- record_constant_1 (TREE_VALUE (link));
- else
- {
- tree zero = 0;
-
- obstack_grow (&permanent_obstack,
- (char *) &zero, sizeof zero);
- }
-
- if (TREE_PURPOSE (link)
- && TREE_CODE (TREE_PURPOSE (link)) == FIELD_DECL)
- obstack_grow (&permanent_obstack,
- (char *) &TREE_PURPOSE (link),
- sizeof TREE_PURPOSE (link));
- else if (TREE_PURPOSE (link))
- record_constant_1 (TREE_PURPOSE (link));
- else if (have_purpose)
- {
- int zero = 0;
-
- obstack_grow (&permanent_obstack,
- (char *) &zero, sizeof zero);
- }
- }
- }
- return;
-
- case ADDR_EXPR:
- {
- struct addr_const value;
-
- decode_addr_const (exp, &value);
- /* Record the offset. */
- obstack_grow (&permanent_obstack,
- (char *) &value.offset, sizeof value.offset);
-
- switch (GET_CODE (value.base))
- {
- case SYMBOL_REF:
- /* Record the symbol name. */
- obstack_grow (&permanent_obstack, XSTR (value.base, 0),
- strlen (XSTR (value.base, 0)) + 1);
- break;
- case LABEL_REF:
- /* Record the address of the CODE_LABEL. It may not have
- been emitted yet, so it's UID may be zero. But pointer
- identity is good enough. */
- obstack_grow (&permanent_obstack, &XEXP (value.base, 0),
- sizeof (rtx));
- break;
- default:
- abort ();
- }
- }
- return;
-
- case PLUS_EXPR:
- case MINUS_EXPR:
- case RANGE_EXPR:
- record_constant_1 (TREE_OPERAND (exp, 0));
- record_constant_1 (TREE_OPERAND (exp, 1));
- return;
-
- case NOP_EXPR:
- case CONVERT_EXPR:
- case NON_LVALUE_EXPR:
- record_constant_1 (TREE_OPERAND (exp, 0));
- return;
-
- default:
- {
- tree new = (*lang_hooks.expand_constant) (exp);
-
- if (new != exp)
- record_constant_1 (new);
- return;
- }
- }
-
- /* Record constant contents. */
- obstack_grow (&permanent_obstack, strp, len);
+ /* Should not get here. */
+ abort ();
}
/* Record a list of constant expressions that were passed to
@@ -3133,9 +2565,8 @@ output_after_function_constants ()
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. */
+/* Make a copy of the whole tree structure for a constant. This
+ handles the same types of nodes that compare_constant handles. */
static tree
copy_constant (exp)
@@ -3191,7 +2622,14 @@ copy_constant (exp)
}
default:
- abort ();
+ {
+ tree t;
+ t = (*lang_hooks.expand_constant) (exp);
+ if (t != exp)
+ return copy_constant (t);
+ else
+ abort ();
+ }
}
}
@@ -3203,7 +2641,7 @@ copy_constant (exp)
Otherwise, output such a constant in memory (or defer it for later)
and generate an rtx for it.
- If DEFER is non-zero, the output of string constants can be deferred
+ If DEFER is nonzero, the output of string constants can be deferred
and output only if referenced in the function after all optimizations.
The TREE_CST_RTL of EXP is set up to point to that rtx.
@@ -3215,7 +2653,7 @@ output_constant_def (exp, defer)
int defer;
{
int hash;
- struct constant_descriptor *desc;
+ struct constant_descriptor_tree *desc;
struct deferred_string **defstr;
char label[256];
int reloc;
@@ -3224,8 +2662,8 @@ output_constant_def (exp, defer)
int labelno = -1;
rtx rtl;
- /* We can't just use the saved RTL if this is a defererred string constant
- and we are not to defer anymode. */
+ /* We can't just use the saved RTL if this is a deferred string constant
+ and we are not to defer anymore. */
if (TREE_CODE (exp) != INTEGER_CST && TREE_CST_RTL (exp)
&& (defer || !STRING_POOL_ADDRESS_P (XEXP (TREE_CST_RTL (exp), 0))))
return TREE_CST_RTL (exp);
@@ -3239,10 +2677,10 @@ output_constant_def (exp, defer)
to see if any of them describes EXP. If yes, the descriptor records
the label number already assigned. */
- hash = const_hash (exp) % MAX_HASH_TABLE;
+ hash = const_hash (exp);
for (desc = const_hash_table[hash]; desc; desc = desc->next)
- if (compare_constant (exp, desc))
+ if (compare_constant (exp, desc->value))
break;
if (desc == 0)
@@ -3256,9 +2694,10 @@ output_constant_def (exp, defer)
labelno = const_labelno++;
ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
- desc = record_constant (exp);
+ desc = ggc_alloc (sizeof (*desc));
desc->next = const_hash_table[hash];
desc->label = ggc_strdup (label);
+ desc->value = copy_constant (exp);
const_hash_table[hash] = desc;
/* We have a symbol name; construct the SYMBOL_REF and the MEM. */
@@ -3281,20 +2720,18 @@ output_constant_def (exp, defer)
/* Optionally set flags or add text to the name to record information
such as that it is a function name. If the name is changed, the macro
ASM_OUTPUT_LABELREF will have to know how to strip this information. */
-#ifdef ENCODE_SECTION_INFO
/* A previously-processed constant would already have section info
encoded in it. */
if (! found)
{
- /* Take care not to invoque ENCODE_SECTION_INFO for constants
- which don't have a TREE_CST_RTL. */
+ /* Take care not to invoke targetm.encode_section_info for
+ constants which don't have a TREE_CST_RTL. */
if (TREE_CODE (exp) != INTEGER_CST)
- ENCODE_SECTION_INFO (exp);
-
+ (*targetm.encode_section_info) (exp, true);
+
desc->rtl = rtl;
desc->label = XSTR (XEXP (desc->rtl, 0), 0);
}
-#endif
#ifdef CONSTANT_AFTER_FUNCTION_P
if (current_function_decl != 0
@@ -3330,7 +2767,7 @@ output_constant_def (exp, defer)
= (struct deferred_constant *)
xmalloc (sizeof (struct deferred_constant));
- p->exp = copy_constant (exp);
+ p->exp = desc->value;
p->reloc = reloc;
p->labelno = labelno;
if (after_function)
@@ -3363,9 +2800,9 @@ output_constant_def (exp, defer)
struct deferred_string *p;
p = (struct deferred_string *)
- xmalloc (sizeof (struct deferred_string));
+ ggc_alloc (sizeof (struct deferred_string));
- p->exp = copy_constant (exp);
+ p->exp = desc->value;
p->label = desc->label;
p->labelno = labelno;
*defstr = p;
@@ -3398,18 +2835,7 @@ output_constant_def_contents (exp, reloc, labelno)
if (IN_NAMED_SECTION (exp))
named_section (exp, NULL, reloc);
else
- {
- /* First switch to text section, except for writable strings. */
-#ifdef SELECT_SECTION
- SELECT_SECTION (exp, reloc, align);
-#else
- if (((TREE_CODE (exp) == STRING_CST) && flag_writable_strings)
- || (flag_pic && reloc))
- data_section ();
- else
- readonly_data_section ();
-#endif
- }
+ (*targetm.asm_out.select_section) (exp, reloc, align);
if (align > BITS_PER_UNIT)
{
@@ -3429,15 +2855,33 @@ output_constant_def_contents (exp, reloc, labelno)
}
+/* Used in the hash tables to avoid outputting the same constant
+ twice. Unlike 'struct constant_descriptor_tree', RTX constants
+ are output once per function, not once per file; there seems
+ to be no reason for the difference. */
+
+struct constant_descriptor_rtx GTY(())
+{
+ /* More constant_descriptors with the same hash code. */
+ struct constant_descriptor_rtx *next;
+
+ /* A MEM for the constant. */
+ rtx rtl;
+
+ /* The value of the constant. */
+ struct rtx_const value;
+};
+
/* Structure to represent sufficient information about a constant so that
it can be output when the constant pool is output, so that function
integration can be done, and to simplify handling on machines that reference
constant pool as base+displacement. */
-struct pool_constant
+struct pool_constant GTY(())
{
- struct constant_descriptor *desc;
- struct pool_constant *next, *next_sym;
+ struct constant_descriptor_rtx *desc;
+ struct pool_constant *next;
+ struct pool_constant *next_sym;
rtx constant;
enum machine_mode mode;
int labelno;
@@ -3449,8 +2893,7 @@ struct pool_constant
/* Hash code for a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true.
The argument is XSTR (... , 0) */
-#define SYMHASH(LABEL) \
- ((((unsigned long) (LABEL)) & ((1 << HASHBITS) - 1)) % MAX_RTX_HASH_TABLE)
+#define SYMHASH(LABEL) (((unsigned long) (LABEL)) % MAX_RTX_HASH_TABLE)
/* Initialize constant pool hashing for a new function. */
@@ -3459,81 +2902,19 @@ init_varasm_status (f)
struct function *f;
{
struct varasm_status *p;
- p = (struct varasm_status *) xmalloc (sizeof (struct varasm_status));
+ p = (struct varasm_status *) ggc_alloc (sizeof (struct varasm_status));
f->varasm = p;
p->x_const_rtx_hash_table
- = ((struct constant_descriptor **)
- xcalloc (MAX_RTX_HASH_TABLE, sizeof (struct constant_descriptor *)));
+ = ((struct constant_descriptor_rtx **)
+ ggc_alloc_cleared (MAX_RTX_HASH_TABLE
+ * sizeof (struct constant_descriptor_rtx *)));
p->x_const_rtx_sym_hash_table
= ((struct pool_constant **)
- xcalloc (MAX_RTX_HASH_TABLE, sizeof (struct pool_constant *)));
+ ggc_alloc_cleared (MAX_RTX_HASH_TABLE
+ * sizeof (struct pool_constant *)));
p->x_first_pool = p->x_last_pool = 0;
p->x_pool_offset = 0;
- p->x_const_double_chain = 0;
-}
-
-/* Mark PC for GC. */
-
-static void
-mark_pool_constant (pc)
- struct pool_constant *pc;
-{
- while (pc)
- {
- ggc_mark (pc);
- ggc_mark_rtx (pc->constant);
- ggc_mark_rtx (pc->desc->rtl);
- pc = pc->next;
- }
-}
-
-/* Mark P for GC. */
-
-void
-mark_varasm_status (p)
- struct varasm_status *p;
-{
- if (p == NULL)
- return;
-
- mark_pool_constant (p->x_first_pool);
- ggc_mark_rtx (p->x_const_double_chain);
-}
-
-/* Clear out all parts of the state in F that can safely be discarded
- after the function has been compiled, to let garbage collection
- reclaim the memory. */
-
-void
-free_varasm_status (f)
- struct function *f;
-{
- struct varasm_status *p;
- int i;
-
- p = f->varasm;
-
- /* Clear out the hash tables. */
- for (i = 0; i < MAX_RTX_HASH_TABLE; ++i)
- {
- struct constant_descriptor *cd;
-
- cd = p->x_const_rtx_hash_table[i];
- while (cd)
- {
- struct constant_descriptor *next = cd->next;
-
- free (cd);
- cd = next;
- }
- }
-
- free (p->x_const_rtx_hash_table);
- free (p->x_const_rtx_sym_hash_table);
- free (p);
-
- f->varasm = NULL;
}
@@ -3559,9 +2940,29 @@ decode_rtx_const (mode, x, value)
value->kind = RTX_DOUBLE;
if (GET_MODE (x) != VOIDmode)
{
+ const REAL_VALUE_TYPE *r = CONST_DOUBLE_REAL_VALUE (x);
+
value->mode = GET_MODE (x);
- memcpy ((char *) &value->un.du,
- (char *) &CONST_DOUBLE_LOW (x), sizeof value->un.du);
+
+ /* Copy the REAL_VALUE_TYPE by members so that we don't
+ copy garbage from the original structure into our
+ carefully cleaned hashing structure. */
+ value->un.du.class = r->class;
+ value->un.du.sign = r->sign;
+ switch (r->class)
+ {
+ case rvc_zero:
+ case rvc_inf:
+ break;
+ case rvc_normal:
+ value->un.du.exp = r->exp;
+ /* FALLTHRU */
+ case rvc_nan:
+ memcpy (value->un.du.sig, r->sig, sizeof (r->sig));
+ break;
+ default:
+ abort ();
+ }
}
else
{
@@ -3573,28 +2974,59 @@ decode_rtx_const (mode, x, value)
case CONST_VECTOR:
{
int units, i;
- rtx elt;
units = CONST_VECTOR_NUNITS (x);
value->kind = RTX_VECTOR;
value->mode = mode;
- for (i = 0; i < units; ++i)
+ if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
{
- elt = CONST_VECTOR_ELT (x, i);
- if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
+ for (i = 0; i < units; ++i)
{
- value->un.veclo[i] = (HOST_WIDE_INT) INTVAL (elt);
- value->un.vechi[i] = 0;
+ rtx elt = CONST_VECTOR_ELT (x, i);
+ if (GET_CODE (elt) == CONST_INT)
+ {
+ value->un.int_vec[i].low = INTVAL (elt);
+ value->un.int_vec[i].high = 0;
+ }
+ else
+ {
+ value->un.int_vec[i].low = CONST_DOUBLE_LOW (elt);
+ value->un.int_vec[i].high = CONST_DOUBLE_HIGH (elt);
+ }
}
- else if (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+ }
+ else if (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+ {
+ for (i = 0; i < units; ++i)
{
- value->un.veclo[i] = (HOST_WIDE_INT) CONST_DOUBLE_LOW (elt);
- value->un.vechi[i] = (HOST_WIDE_INT) CONST_DOUBLE_HIGH (elt);
+ const REAL_VALUE_TYPE *r
+ = CONST_DOUBLE_REAL_VALUE (CONST_VECTOR_ELT (x, i));
+ REAL_VALUE_TYPE *d = &value->un.fp_vec[i];
+
+ /* Copy the REAL_VALUE_TYPE by members so that we don't
+ copy garbage from the original structure into our
+ carefully cleaned hashing structure. */
+ d->class = r->class;
+ d->sign = r->sign;
+ switch (r->class)
+ {
+ case rvc_zero:
+ case rvc_inf:
+ break;
+ case rvc_normal:
+ d->exp = r->exp;
+ /* FALLTHRU */
+ case rvc_nan:
+ memcpy (d->sig, r->sig, sizeof (r->sig));
+ break;
+ default:
+ abort ();
+ }
}
- else
- abort ();
}
+ else
+ abort ();
}
break;
@@ -3634,28 +3066,29 @@ decode_rtx_const (mode, x, value)
if (value->kind == RTX_INT && value->un.addr.base != 0
&& GET_CODE (value->un.addr.base) == UNSPEC)
- {
+ {
/* For a simple UNSPEC, the base is set to the
operand, the kind field is set to the index of
- the unspec expression.
+ the unspec expression.
Together with the code below, in case that
- the operand is a SYMBOL_REF or LABEL_REF,
- the address of the string or the code_label
+ the operand is a SYMBOL_REF or LABEL_REF,
+ the address of the string or the code_label
is taken as base. */
if (XVECLEN (value->un.addr.base, 0) == 1)
- {
+ {
value->kind = RTX_UNSPEC + XINT (value->un.addr.base, 1);
value->un.addr.base = XVECEXP (value->un.addr.base, 0, 0);
}
}
- if (value->kind > RTX_DOUBLE && value->un.addr.base != 0)
+ if (value->kind >= RTX_INT && value->un.addr.base != 0)
switch (GET_CODE (value->un.addr.base))
{
case SYMBOL_REF:
/* Use the string's address, not the SYMBOL_REF's address,
for the sake of addresses of library routines. */
- value->un.addr.base = (rtx) XSTR (value->un.addr.base, 0);
+ value->un.addr.symbol = XSTR (value->un.addr.base, 0);
+ value->un.addr.base = NULL_RTX;
break;
case LABEL_REF:
@@ -3679,9 +3112,10 @@ simplify_subtraction (x)
decode_rtx_const (GET_MODE (x), XEXP (x, 0), &val0);
decode_rtx_const (GET_MODE (x), XEXP (x, 1), &val1);
- if (val0.kind > RTX_DOUBLE
+ if (val0.kind >= RTX_INT
&& val0.kind == val1.kind
- && val0.un.addr.base == val1.un.addr.base)
+ && val0.un.addr.base == val1.un.addr.base
+ && val0.un.addr.symbol == val1.un.addr.symbol)
return GEN_INT (val0.un.addr.offset - val1.un.addr.offset);
return x;
@@ -3689,25 +3123,27 @@ simplify_subtraction (x)
/* Compute a hash code for a constant RTL expression. */
-static int
+static unsigned int
const_hash_rtx (mode, x)
enum machine_mode mode;
rtx x;
{
- int hi;
+ union {
+ struct rtx_const value;
+ unsigned int data[sizeof(struct rtx_const) / sizeof (unsigned int)];
+ } u;
+
+ unsigned int hi;
size_t i;
- struct rtx_const value;
- decode_rtx_const (mode, x, &value);
+ decode_rtx_const (mode, x, &u.value);
/* Compute hashing function */
hi = 0;
- for (i = 0; i < sizeof value / sizeof (int); i++)
- hi += ((int *) &value)[i];
+ for (i = 0; i < ARRAY_SIZE (u.data); i++)
+ hi = hi * 613 + u.data[i];
- hi &= (1 << HASHBITS) - 1;
- hi %= MAX_RTX_HASH_TABLE;
- return hi;
+ return hi % MAX_RTX_HASH_TABLE;
}
/* Compare a constant rtl object X with a constant-descriptor DESC.
@@ -3717,39 +3153,28 @@ static int
compare_constant_rtx (mode, x, desc)
enum machine_mode mode;
rtx x;
- struct constant_descriptor *desc;
+ struct constant_descriptor_rtx *desc;
{
- int *p = (int *) desc->u.contents;
- int *strp;
- int len;
struct rtx_const value;
decode_rtx_const (mode, x, &value);
- strp = (int *) &value;
- len = sizeof value / sizeof (int);
/* Compare constant contents. */
- while (--len >= 0)
- if (*p++ != *strp++)
- return 0;
-
- return 1;
+ return memcmp (&value, &desc->value, sizeof (struct rtx_const)) == 0;
}
/* Construct a constant descriptor for the rtl-expression X.
It is up to the caller to enter the descriptor in the hash table. */
-static struct constant_descriptor *
+static struct constant_descriptor_rtx *
record_constant_rtx (mode, x)
enum machine_mode mode;
rtx x;
{
- struct constant_descriptor *ptr;
+ struct constant_descriptor_rtx *ptr;
- ptr = ((struct constant_descriptor *)
- xcalloc (1, (offsetof (struct constant_descriptor, u)
- + sizeof (struct rtx_const))));
- decode_rtx_const (mode, x, (struct rtx_const *) ptr->u.contents);
+ ptr = (struct constant_descriptor_rtx *) ggc_alloc (sizeof (*ptr));
+ decode_rtx_const (mode, x, &ptr->value);
return ptr;
}
@@ -3762,7 +3187,7 @@ mem_for_const_double (x)
rtx x;
{
enum machine_mode mode = GET_MODE (x);
- struct constant_descriptor *desc;
+ struct constant_descriptor_rtx *desc;
for (desc = const_rtx_hash_table[const_hash_rtx (mode, x)]; desc;
desc = desc->next)
@@ -3771,7 +3196,7 @@ mem_for_const_double (x)
return 0;
}
-
+
/* Given a constant rtx X, make (or find) a memory constant for its value
and return a MEM rtx to refer to it in memory. */
@@ -3781,12 +3206,16 @@ force_const_mem (mode, x)
rtx x;
{
int hash;
- struct constant_descriptor *desc;
+ struct constant_descriptor_rtx *desc;
char label[256];
rtx def;
struct pool_constant *pool;
unsigned int align;
+ /* If we're not allowed to drop X into the constant pool, don't. */
+ if ((*targetm.cannot_force_const_mem) (x))
+ return NULL_RTX;
+
/* Compute hash code of X. Search the descriptors for that hash code
to see if any of them describes X. If yes, we have an rtx to use. */
hash = const_hash_rtx (mode, x);
@@ -3800,11 +3229,12 @@ force_const_mem (mode, x)
desc = record_constant_rtx (mode, x);
desc->next = const_rtx_hash_table[hash];
const_rtx_hash_table[hash] = desc;
-
+
/* Align the location counter as required by EXP's data type. */
align = GET_MODE_ALIGNMENT (mode == VOIDmode ? word_mode : mode);
#ifdef CONSTANT_ALIGNMENT
- align = CONSTANT_ALIGNMENT (make_tree (type_for_mode (mode, 0), x), align);
+ align = CONSTANT_ALIGNMENT (make_tree ((*lang_hooks.types.type_for_mode)
+ (mode, 0), x), align);
#endif
pool_offset += (align / BITS_PER_UNIT) - 1;
@@ -3828,7 +3258,7 @@ force_const_mem (mode, x)
first_pool = pool;
else
last_pool->next = pool;
-
+
last_pool = pool;
pool_offset += GET_MODE_SIZE (mode);
@@ -3842,7 +3272,7 @@ force_const_mem (mode, x)
pool->desc->rtl = def
= gen_rtx_MEM (mode, gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label)));
set_mem_alias_set (def, const_alias_set);
- set_mem_attributes (def, type_for_mode (mode, 0), 1);
+ set_mem_attributes (def, (*lang_hooks.types.type_for_mode) (mode, 0), 1);
RTX_UNCHANGING_P (def) = 1;
/* Add label to symbol hash table. */
@@ -3946,12 +3376,12 @@ get_pool_size ()
void
output_constant_pool (fnname, fndecl)
- const char *fnname ATTRIBUTE_UNUSED;
- tree fndecl ATTRIBUTE_UNUSED;
+ const char *fnname ATTRIBUTE_UNUSED;
+ tree fndecl ATTRIBUTE_UNUSED;
{
struct pool_constant *pool;
rtx x;
- union real_extract u;
+ REAL_VALUE_TYPE r;
/* 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
@@ -4006,11 +3436,7 @@ output_constant_pool (fnname, fndecl)
}
/* First switch to correct section. */
-#ifdef SELECT_RTX_SECTION
- SELECT_RTX_SECTION (pool->mode, x, pool->align);
-#else
- readonly_data_section ();
-#endif
+ (*targetm.asm_out.select_rtx_section) (pool->mode, x, pool->align);
#ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
ASM_OUTPUT_SPECIAL_POOL_ENTRY (asm_out_file, x, pool->mode,
@@ -4029,8 +3455,8 @@ output_constant_pool (fnname, fndecl)
if (GET_CODE (x) != CONST_DOUBLE)
abort ();
- memcpy ((char *) &u, (char *) &CONST_DOUBLE_LOW (x), sizeof u);
- assemble_real (u.d, pool->mode, pool->align);
+ REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+ assemble_real (r, pool->mode, pool->align);
break;
case MODE_INT:
@@ -4051,15 +3477,13 @@ output_constant_pool (fnname, fndecl)
for (i = 0; i < units; i++)
{
elt = CONST_VECTOR_ELT (x, i);
- memcpy ((char *) &u,
- (char *) &CONST_DOUBLE_LOW (elt),
- sizeof u);
- assemble_real (u.d, GET_MODE_INNER (pool->mode), pool->align);
+ REAL_VALUE_FROM_CONST_DOUBLE (r, elt);
+ assemble_real (r, GET_MODE_INNER (pool->mode), pool->align);
}
}
break;
- case MODE_VECTOR_INT:
+ case MODE_VECTOR_INT:
{
int i, units;
rtx elt;
@@ -4082,6 +3506,13 @@ output_constant_pool (fnname, fndecl)
abort ();
}
+ /* Make sure all constants in SECTION_MERGE and not SECTION_STRINGS
+ sections have proper size. */
+ if (pool->align > GET_MODE_BITSIZE (pool->mode)
+ && in_section == in_named
+ && get_named_section_flags (in_named_name) & SECTION_MERGE)
+ assemble_align (pool->align);
+
#ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
done: ;
#endif
@@ -4103,6 +3534,7 @@ static void
mark_constant_pool ()
{
rtx insn;
+ rtx link;
struct pool_constant *pool;
if (first_pool == 0 && htab_elements (const_str_htab) == 0)
@@ -4115,11 +3547,15 @@ mark_constant_pool ()
if (INSN_P (insn))
mark_constants (PATTERN (insn));
- for (insn = current_function_epilogue_delay_list;
- insn;
- insn = XEXP (insn, 1))
- if (INSN_P (insn))
- mark_constants (PATTERN (insn));
+ for (link = current_function_epilogue_delay_list;
+ link;
+ link = XEXP (link, 1))
+ {
+ insn = XEXP (link, 0);
+
+ if (INSN_P (insn))
+ mark_constants (PATTERN (insn));
+ }
}
/* Look through appropriate parts of X, marking all entries in the
@@ -4179,6 +3615,7 @@ mark_constants (x)
case 'w':
case 'n':
case 'u':
+ case 'B':
break;
default:
@@ -4206,10 +3643,11 @@ mark_constant (current_rtx, data)
if (CONSTANT_POOL_ADDRESS_P (x))
{
struct pool_constant *pool = find_pool_constant (cfun, x);
- if (pool->mark == 0) {
- pool->mark = 1;
- for_each_rtx (&(pool->constant), &mark_constant, NULL);
- }
+ if (pool->mark == 0)
+ {
+ pool->mark = 1;
+ for_each_rtx (&(pool->constant), &mark_constant, NULL);
+ }
else
return -1;
}
@@ -4241,7 +3679,7 @@ static int
output_addressed_constants (exp)
tree exp;
{
- int reloc = 0;
+ int reloc = 0, reloc2;
tree tem;
/* Give the front-end a chance to convert VALUE to something that
@@ -4260,8 +3698,8 @@ output_addressed_constants (exp)
;
if (TREE_CODE_CLASS (TREE_CODE (tem)) == 'c'
- || TREE_CODE (tem) == CONSTRUCTOR)
- output_constant_def (tem, 0);
+ || TREE_CODE (tem) == CONSTRUCTOR)
+ output_constant_def (tem, 0);
if (TREE_PUBLIC (tem))
reloc |= 2;
@@ -4270,11 +3708,20 @@ output_addressed_constants (exp)
break;
case PLUS_EXPR:
- case MINUS_EXPR:
reloc = output_addressed_constants (TREE_OPERAND (exp, 0));
reloc |= output_addressed_constants (TREE_OPERAND (exp, 1));
break;
+ case MINUS_EXPR:
+ reloc = output_addressed_constants (TREE_OPERAND (exp, 0));
+ reloc2 = output_addressed_constants (TREE_OPERAND (exp, 1));
+ /* The difference of two local labels is computable at link time. */
+ if (reloc == 1 && reloc2 == 1)
+ reloc = 0;
+ else
+ reloc |= reloc2;
+ break;
+
case NOP_EXPR:
case CONVERT_EXPR:
case NON_LVALUE_EXPR:
@@ -4284,7 +3731,7 @@ output_addressed_constants (exp)
case CONSTRUCTOR:
for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem))
if (TREE_VALUE (tem) != 0)
- reloc |= output_addressed_constants (TREE_VALUE (tem));
+ reloc |= output_addressed_constants (TREE_VALUE (tem));
break;
@@ -4402,7 +3849,7 @@ initializer_constant_valid_p (value, endtype)
case PLUS_EXPR:
if (! INTEGRAL_TYPE_P (endtype)
|| TYPE_PRECISION (endtype) >= POINTER_SIZE)
- {
+ {
tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
@@ -4412,7 +3859,7 @@ initializer_constant_valid_p (value, endtype)
return valid1;
if (valid1 == null_pointer_node)
return valid0;
- }
+ }
break;
case MINUS_EXPR:
@@ -4619,7 +4066,7 @@ output_constant (exp, size, align)
if (TREE_CODE (exp) == INTEGER_CST)
assemble_integer (expand_expr (exp, NULL_RTX,
VOIDmode, EXPAND_INITIALIZER),
- thissize, align, 1);
+ thissize, align, 1);
else if (TREE_CODE (exp) == CONSTRUCTOR)
{
unsigned char *buffer = (unsigned char *) alloca (thissize);
@@ -4661,7 +4108,7 @@ array_size_for_constructor (val)
return TREE_STRING_LENGTH (val);
max_index = NULL_TREE;
- for (i = CONSTRUCTOR_ELTS (val); i ; i = TREE_CHAIN (i))
+ for (i = CONSTRUCTOR_ELTS (val); i; i = TREE_CHAIN (i))
{
tree index = TREE_PURPOSE (i);
@@ -4994,7 +4441,7 @@ output_constructor (exp, size, align)
/* This TREE_LIST contains any weak symbol declarations waiting
to be emitted. */
-static tree weak_decls;
+static GTY(()) tree weak_decls;
/* Mark DECL as weak. */
@@ -5010,7 +4457,7 @@ mark_weak (decl)
&& GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF)
SYMBOL_REF_WEAK (XEXP (DECL_RTL (decl), 0)) = 1;
}
-
+
/* Merge weak status between NEWDECL and OLDDECL. */
void
@@ -5024,7 +4471,7 @@ merge_weak (newdecl, olddecl)
if (DECL_WEAK (newdecl))
{
tree wd;
-
+
/* NEWDECL is weak, but OLDDECL is not. */
/* If we already output the OLDDECL, we're in trouble; we can't
@@ -5032,7 +4479,7 @@ merge_weak (newdecl, olddecl)
declare_weak because the NEWDECL and OLDDECL was not yet
been merged; therefore, TREE_ASM_WRITTEN was not set. */
if (TREE_ASM_WRITTEN (olddecl))
- error_with_decl (newdecl,
+ error_with_decl (newdecl,
"weak declaration of `%s' must precede definition");
/* If we've already generated rtl referencing OLDDECL, we may
@@ -5095,7 +4542,7 @@ weak_finish ()
{
tree t;
- for (t = weak_decls; t ; t = TREE_CHAIN (t))
+ for (t = weak_decls; t; t = TREE_CHAIN (t))
{
tree decl = TREE_VALUE (t);
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
@@ -5150,7 +4597,7 @@ globalize_decl (decl)
}
#endif
- ASM_GLOBALIZE_LABEL (asm_out_file, name);
+ (*targetm.asm_out.globalize_label) (asm_out_file, name);
}
/* Emit an assembler directive to make the symbol for DECL an alias to
@@ -5170,8 +4617,12 @@ assemble_alias (decl, target)
#ifdef ASM_OUTPUT_DEF
/* Make name accessible from other files, if appropriate. */
+
if (TREE_PUBLIC (decl))
- globalize_decl (decl);
+ {
+ globalize_decl (decl);
+ maybe_assemble_visibility (decl);
+ }
#ifdef ASM_OUTPUT_DEF_FROM_DECLS
ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, decl, target);
@@ -5198,6 +4649,44 @@ assemble_alias (decl, target)
TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1;
}
+/* Emit an assembler directive to set symbol for DECL visibility to
+ the visibility type VIS, which must not be VISIBILITY_DEFAULT. */
+
+void
+default_assemble_visibility (decl, vis)
+ tree decl;
+ int vis;
+{
+ static const char * const visibility_types[] = {
+ NULL, "internal", "hidden", "protected"
+ };
+
+ const char *name, *type;
+
+ name = (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+ type = visibility_types[vis];
+
+#ifdef HAVE_GAS_HIDDEN
+ fprintf (asm_out_file, "\t.%s\t", type);
+ assemble_name (asm_out_file, name);
+ fprintf (asm_out_file, "\n");
+#else
+ warning ("visibility attribute not supported in this configuration; ignored");
+#endif
+}
+
+/* A helper function to call assemble_visibility when needed for a decl. */
+
+static void
+maybe_assemble_visibility (decl)
+ tree decl;
+{
+ enum symbol_visibility vis = decl_visibility (decl);
+
+ if (vis != VISIBILITY_DEFAULT)
+ (* targetm.asm_out.visibility) (decl, vis);
+}
+
/* 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
@@ -5242,20 +4731,85 @@ make_decl_one_only (decl)
void
init_varasm_once ()
{
- const_str_htab = htab_create (128, const_str_htab_hash, const_str_htab_eq,
- const_str_htab_del);
+ const_str_htab = htab_create_ggc (128, const_str_htab_hash,
+ const_str_htab_eq, NULL);
in_named_htab = htab_create (31, in_named_entry_hash,
in_named_entry_eq, NULL);
- ggc_add_root (const_hash_table, MAX_HASH_TABLE, sizeof const_hash_table[0],
- mark_const_hash_entry);
- ggc_add_root (&const_str_htab, 1, sizeof const_str_htab,
- mark_const_str_htab);
- ggc_add_tree_root (&weak_decls, 1);
-
const_alias_set = new_alias_set ();
}
+enum tls_model
+decl_tls_model (decl)
+ tree decl;
+{
+ enum tls_model kind;
+ tree attr = lookup_attribute ("tls_model", DECL_ATTRIBUTES (decl));
+ bool is_local;
+
+ if (attr)
+ {
+ attr = TREE_VALUE (TREE_VALUE (attr));
+ if (TREE_CODE (attr) != STRING_CST)
+ abort ();
+ if (!strcmp (TREE_STRING_POINTER (attr), "local-exec"))
+ kind = TLS_MODEL_LOCAL_EXEC;
+ else if (!strcmp (TREE_STRING_POINTER (attr), "initial-exec"))
+ kind = TLS_MODEL_INITIAL_EXEC;
+ else if (!strcmp (TREE_STRING_POINTER (attr), "local-dynamic"))
+ kind = optimize ? TLS_MODEL_LOCAL_DYNAMIC : TLS_MODEL_GLOBAL_DYNAMIC;
+ else if (!strcmp (TREE_STRING_POINTER (attr), "global-dynamic"))
+ kind = TLS_MODEL_GLOBAL_DYNAMIC;
+ else
+ abort ();
+ return kind;
+ }
+
+ is_local = (*targetm.binds_local_p) (decl);
+ if (!flag_pic)
+ {
+ if (is_local)
+ kind = TLS_MODEL_LOCAL_EXEC;
+ else
+ kind = TLS_MODEL_INITIAL_EXEC;
+ }
+ /* Local dynamic is inefficient when we're not combining the
+ parts of the address. */
+ else if (optimize && is_local)
+ kind = TLS_MODEL_LOCAL_DYNAMIC;
+ else
+ kind = TLS_MODEL_GLOBAL_DYNAMIC;
+ if (kind < flag_tls_default)
+ kind = flag_tls_default;
+
+ return kind;
+}
+
+enum symbol_visibility
+decl_visibility (decl)
+ tree decl;
+{
+ tree attr = lookup_attribute ("visibility", DECL_ATTRIBUTES (decl));
+
+ if (attr)
+ {
+ const char *which = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)));
+
+ if (strcmp (which, "default") == 0)
+ return VISIBILITY_DEFAULT;
+ if (strcmp (which, "internal") == 0)
+ return VISIBILITY_INTERNAL;
+ if (strcmp (which, "hidden") == 0)
+ return VISIBILITY_HIDDEN;
+ if (strcmp (which, "protected") == 0)
+ return VISIBILITY_PROTECTED;
+
+ abort ();
+ }
+
+ return VISIBILITY_DEFAULT;
+}
+
/* Select a set of attributes for section NAME based on the properties
of DECL and whether or not RELOC indicates that DECL's initializer
might contain runtime relocations.
@@ -5269,11 +4823,21 @@ default_section_type_flags (decl, name, reloc)
const char *name;
int reloc;
{
+ return default_section_type_flags_1 (decl, name, reloc, flag_pic);
+}
+
+unsigned int
+default_section_type_flags_1 (decl, name, reloc, shlib)
+ tree decl;
+ const char *name;
+ int reloc;
+ int shlib;
+{
unsigned int flags;
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
flags = SECTION_CODE;
- else if (decl && DECL_READONLY_SECTION (decl, reloc))
+ else if (decl && decl_readonly_section_1 (decl, reloc, shlib))
flags = 0;
else
flags = SECTION_WRITE;
@@ -5281,14 +4845,36 @@ default_section_type_flags (decl, name, reloc)
if (decl && DECL_ONE_ONLY (decl))
flags |= SECTION_LINKONCE;
+ if (decl && TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
+ flags |= SECTION_TLS | SECTION_WRITE;
+
if (strcmp (name, ".bss") == 0
|| strncmp (name, ".bss.", 5) == 0
|| strncmp (name, ".gnu.linkonce.b.", 16) == 0
|| strcmp (name, ".sbss") == 0
|| strncmp (name, ".sbss.", 6) == 0
- || strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
+ || strncmp (name, ".gnu.linkonce.sb.", 17) == 0
+ || strcmp (name, ".tbss") == 0
+ || strncmp (name, ".gnu.linkonce.tb.", 17) == 0)
flags |= SECTION_BSS;
+ if (strcmp (name, ".tdata") == 0
+ || strcmp (name, ".tbss") == 0
+ || strncmp (name, ".gnu.linkonce.td.", 17) == 0
+ || strncmp (name, ".gnu.linkonce.tb.", 17) == 0)
+ flags |= SECTION_TLS;
+
+ /* These three sections have special ELF types. They are neither
+ SHT_PROGBITS nor SHT_NOBITS, so when changing sections we don't
+ want to print a section type (@progbits or @nobits). If someone
+ is silly enough to emit code or TLS variables to one of these
+ sections, then don't handle them specially. */
+ if (!(flags & (SECTION_CODE | SECTION_BSS | SECTION_TLS))
+ && (strcmp (name, ".init_array") == 0
+ || strcmp (name, ".fini_array") == 0
+ || strcmp (name, ".preinit_array") == 0))
+ flags |= SECTION_NOTYPE;
+
return flags;
}
@@ -5311,7 +4897,6 @@ default_elf_asm_named_section (name, flags)
unsigned int flags;
{
char flagchars[10], *f = flagchars;
- const char *type;
if (! named_section_first_declaration (name))
{
@@ -5331,19 +4916,28 @@ default_elf_asm_named_section (name, flags)
*f++ = 'M';
if (flags & SECTION_STRINGS)
*f++ = 'S';
+ if (flags & SECTION_TLS)
+ *f++ = 'T';
*f = '\0';
- if (flags & SECTION_BSS)
- type = "nobits";
- else
- type = "progbits";
+ fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
- if (flags & SECTION_ENTSIZE)
- fprintf (asm_out_file, "\t.section\t%s,\"%s\",@%s,%d\n",
- name, flagchars, type, flags & SECTION_ENTSIZE);
- else
- fprintf (asm_out_file, "\t.section\t%s,\"%s\",@%s\n",
- name, flagchars, type);
+ if (!(flags & SECTION_NOTYPE))
+ {
+ const char *type;
+
+ if (flags & SECTION_BSS)
+ type = "nobits";
+ else
+ type = "progbits";
+
+ fprintf (asm_out_file, ",@%s", type);
+
+ if (flags & SECTION_ENTSIZE)
+ fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
+ }
+
+ putc ('\n', asm_out_file);
}
void
@@ -5407,3 +5001,465 @@ assemble_vtable_inherit (child, parent)
output_addr_const (asm_out_file, parent);
fputc ('\n', asm_out_file);
}
+
+/* The lame default section selector. */
+
+void
+default_select_section (decl, reloc, align)
+ tree decl;
+ int reloc;
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+{
+ bool readonly = false;
+
+ if (DECL_P (decl))
+ {
+ if (decl_readonly_section (decl, reloc))
+ readonly = true;
+ }
+ else if (TREE_CODE (decl) == CONSTRUCTOR)
+ {
+ if (! ((flag_pic && reloc)
+ || !TREE_READONLY (decl)
+ || TREE_SIDE_EFFECTS (decl)
+ || !TREE_CONSTANT (decl)))
+ readonly = true;
+ }
+ else if (TREE_CODE (decl) == STRING_CST)
+ readonly = !flag_writable_strings;
+ else if (! (flag_pic && reloc))
+ readonly = true;
+
+ if (readonly)
+ readonly_data_section ();
+ else
+ data_section ();
+}
+
+/* A helper function for default_elf_select_section and
+ default_elf_unique_section. Categorizes the DECL. */
+
+enum section_category
+{
+ SECCAT_TEXT,
+
+ SECCAT_RODATA,
+ SECCAT_RODATA_MERGE_STR,
+ SECCAT_RODATA_MERGE_STR_INIT,
+ SECCAT_RODATA_MERGE_CONST,
+ SECCAT_SRODATA,
+
+ SECCAT_DATA,
+
+ /* To optimize loading of shared programs, define following subsections
+ of data section:
+ _REL Contains data that has relocations, so they get grouped
+ together and dynamic linker will visit fewer pages in memory.
+ _RO Contains data that is otherwise read-only. This is useful
+ with prelinking as most relocations won't be dynamically
+ linked and thus stay read only.
+ _LOCAL Marks data containing relocations only to local objects.
+ These relocations will get fully resolved by prelinking. */
+ SECCAT_DATA_REL,
+ SECCAT_DATA_REL_LOCAL,
+ SECCAT_DATA_REL_RO,
+ SECCAT_DATA_REL_RO_LOCAL,
+
+ SECCAT_SDATA,
+ SECCAT_TDATA,
+
+ SECCAT_BSS,
+ SECCAT_SBSS,
+ SECCAT_TBSS
+};
+
+static enum section_category
+categorize_decl_for_section PARAMS ((tree, int, int));
+
+static enum section_category
+categorize_decl_for_section (decl, reloc, shlib)
+ tree decl;
+ int reloc;
+ int shlib;
+{
+ enum section_category ret;
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ return SECCAT_TEXT;
+ else if (TREE_CODE (decl) == STRING_CST)
+ {
+ if (flag_writable_strings)
+ return SECCAT_DATA;
+ else
+ return SECCAT_RODATA_MERGE_STR;
+ }
+ else if (TREE_CODE (decl) == VAR_DECL)
+ {
+ if (DECL_INITIAL (decl) == NULL
+ || DECL_INITIAL (decl) == error_mark_node)
+ ret = SECCAT_BSS;
+ else if (! TREE_READONLY (decl)
+ || TREE_SIDE_EFFECTS (decl)
+ || ! TREE_CONSTANT (DECL_INITIAL (decl)))
+ {
+ if (shlib && (reloc & 2))
+ ret = SECCAT_DATA_REL;
+ else if (shlib && reloc)
+ ret = SECCAT_DATA_REL_LOCAL;
+ else
+ ret = SECCAT_DATA;
+ }
+ else if (shlib && (reloc & 2))
+ ret = SECCAT_DATA_REL_RO;
+ else if (shlib && reloc)
+ ret = SECCAT_DATA_REL_RO_LOCAL;
+ else if (reloc || flag_merge_constants < 2)
+ /* C and C++ don't allow different variables to share the same
+ location. -fmerge-all-constants allows even that (at the
+ expense of not conforming). */
+ ret = SECCAT_RODATA;
+ else if (TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
+ ret = SECCAT_RODATA_MERGE_STR_INIT;
+ else
+ ret = SECCAT_RODATA_MERGE_CONST;
+ }
+ else if (TREE_CODE (decl) == CONSTRUCTOR)
+ {
+ if ((shlib && reloc)
+ || TREE_SIDE_EFFECTS (decl)
+ || ! TREE_CONSTANT (decl))
+ ret = SECCAT_DATA;
+ else
+ ret = SECCAT_RODATA;
+ }
+ else
+ ret = SECCAT_RODATA;
+
+ /* There are no read-only thread-local sections. */
+ if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
+ {
+ if (ret == SECCAT_BSS)
+ ret = SECCAT_TBSS;
+ else
+ ret = SECCAT_TDATA;
+ }
+
+ /* If the target uses small data sections, select it. */
+ else if ((*targetm.in_small_data_p) (decl))
+ {
+ if (ret == SECCAT_BSS)
+ ret = SECCAT_SBSS;
+ else if (targetm.have_srodata_section && ret == SECCAT_RODATA)
+ ret = SECCAT_SRODATA;
+ else
+ ret = SECCAT_SDATA;
+ }
+
+ return ret;
+}
+
+bool
+decl_readonly_section (decl, reloc)
+ tree decl;
+ int reloc;
+{
+ return decl_readonly_section_1 (decl, reloc, flag_pic);
+}
+
+bool
+decl_readonly_section_1 (decl, reloc, shlib)
+ tree decl;
+ int reloc;
+ int shlib;
+{
+ switch (categorize_decl_for_section (decl, reloc, shlib))
+ {
+ case SECCAT_RODATA:
+ case SECCAT_RODATA_MERGE_STR:
+ case SECCAT_RODATA_MERGE_STR_INIT:
+ case SECCAT_RODATA_MERGE_CONST:
+ case SECCAT_SRODATA:
+ return true;
+ break;
+ default:
+ return false;
+ break;
+ }
+}
+
+/* Select a section based on the above categorization. */
+
+void
+default_elf_select_section (decl, reloc, align)
+ tree decl;
+ int reloc;
+ unsigned HOST_WIDE_INT align;
+{
+ default_elf_select_section_1 (decl, reloc, align, flag_pic);
+}
+
+void
+default_elf_select_section_1 (decl, reloc, align, shlib)
+ tree decl;
+ int reloc;
+ unsigned HOST_WIDE_INT align;
+ int shlib;
+{
+ switch (categorize_decl_for_section (decl, reloc, shlib))
+ {
+ case SECCAT_TEXT:
+ /* We're not supposed to be called on FUNCTION_DECLs. */
+ abort ();
+ case SECCAT_RODATA:
+ readonly_data_section ();
+ break;
+ case SECCAT_RODATA_MERGE_STR:
+ mergeable_string_section (decl, align, 0);
+ break;
+ case SECCAT_RODATA_MERGE_STR_INIT:
+ mergeable_string_section (DECL_INITIAL (decl), align, 0);
+ break;
+ case SECCAT_RODATA_MERGE_CONST:
+ mergeable_constant_section (DECL_MODE (decl), align, 0);
+ break;
+ case SECCAT_SRODATA:
+ named_section (NULL_TREE, ".sdata2", reloc);
+ break;
+ case SECCAT_DATA:
+ data_section ();
+ break;
+ case SECCAT_DATA_REL:
+ named_section (NULL_TREE, ".data.rel", reloc);
+ break;
+ case SECCAT_DATA_REL_LOCAL:
+ named_section (NULL_TREE, ".data.rel.local", reloc);
+ break;
+ case SECCAT_DATA_REL_RO:
+ named_section (NULL_TREE, ".data.rel.ro", reloc);
+ break;
+ case SECCAT_DATA_REL_RO_LOCAL:
+ named_section (NULL_TREE, ".data.rel.ro.local", reloc);
+ break;
+ case SECCAT_SDATA:
+ named_section (NULL_TREE, ".sdata", reloc);
+ break;
+ case SECCAT_TDATA:
+ named_section (NULL_TREE, ".tdata", reloc);
+ break;
+ case SECCAT_BSS:
+#ifdef BSS_SECTION_ASM_OP
+ bss_section ();
+#else
+ named_section (NULL_TREE, ".bss", reloc);
+#endif
+ break;
+ case SECCAT_SBSS:
+ named_section (NULL_TREE, ".sbss", reloc);
+ break;
+ case SECCAT_TBSS:
+ named_section (NULL_TREE, ".tbss", reloc);
+ break;
+ default:
+ abort ();
+ }
+}
+
+/* Construct a unique section name based on the decl name and the
+ categorization performed above. */
+
+void
+default_unique_section (decl, reloc)
+ tree decl;
+ int reloc;
+{
+ default_unique_section_1 (decl, reloc, flag_pic);
+}
+
+void
+default_unique_section_1 (decl, reloc, shlib)
+ tree decl;
+ int reloc;
+ int shlib;
+{
+ bool one_only = DECL_ONE_ONLY (decl);
+ const char *prefix, *name;
+ size_t nlen, plen;
+ char *string;
+
+ switch (categorize_decl_for_section (decl, reloc, shlib))
+ {
+ case SECCAT_TEXT:
+ prefix = one_only ? ".gnu.linkonce.t." : ".text.";
+ break;
+ case SECCAT_RODATA:
+ case SECCAT_RODATA_MERGE_STR:
+ case SECCAT_RODATA_MERGE_STR_INIT:
+ case SECCAT_RODATA_MERGE_CONST:
+ prefix = one_only ? ".gnu.linkonce.r." : ".rodata.";
+ break;
+ case SECCAT_SRODATA:
+ prefix = one_only ? ".gnu.linkonce.s2." : ".sdata2.";
+ break;
+ case SECCAT_DATA:
+ case SECCAT_DATA_REL:
+ case SECCAT_DATA_REL_LOCAL:
+ case SECCAT_DATA_REL_RO:
+ case SECCAT_DATA_REL_RO_LOCAL:
+ prefix = one_only ? ".gnu.linkonce.d." : ".data.";
+ break;
+ case SECCAT_SDATA:
+ prefix = one_only ? ".gnu.linkonce.s." : ".sdata.";
+ break;
+ case SECCAT_BSS:
+ prefix = one_only ? ".gnu.linkonce.b." : ".bss.";
+ break;
+ case SECCAT_SBSS:
+ prefix = one_only ? ".gnu.linkonce.sb." : ".sbss.";
+ break;
+ case SECCAT_TDATA:
+ prefix = one_only ? ".gnu.linkonce.td." : ".tdata.";
+ break;
+ case SECCAT_TBSS:
+ prefix = one_only ? ".gnu.linkonce.tb." : ".tbss.";
+ break;
+ default:
+ abort ();
+ }
+ plen = strlen (prefix);
+
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ name = (* targetm.strip_name_encoding) (name);
+ nlen = strlen (name);
+
+ string = alloca (nlen + plen + 1);
+ memcpy (string, prefix, plen);
+ memcpy (string + plen, name, nlen + 1);
+
+ DECL_SECTION_NAME (decl) = build_string (nlen + plen, string);
+}
+
+void
+default_select_rtx_section (mode, x, align)
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ rtx x;
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+{
+ if (flag_pic)
+ switch (GET_CODE (x))
+ {
+ case CONST:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ data_section ();
+ return;
+
+ default:
+ break;
+ }
+
+ readonly_data_section ();
+}
+
+void
+default_elf_select_rtx_section (mode, x, align)
+ enum machine_mode mode;
+ rtx x;
+ unsigned HOST_WIDE_INT align;
+{
+ /* ??? Handle small data here somehow. */
+
+ if (flag_pic)
+ switch (GET_CODE (x))
+ {
+ case CONST:
+ case SYMBOL_REF:
+ named_section (NULL_TREE, ".data.rel.ro", 3);
+ return;
+
+ case LABEL_REF:
+ named_section (NULL_TREE, ".data.rel.ro.local", 1);
+ return;
+
+ default:
+ break;
+ }
+
+ mergeable_constant_section (mode, align, 0);
+}
+
+/* By default, we do nothing for encode_section_info, so we need not
+ do anything but discard the '*' marker. */
+
+const char *
+default_strip_name_encoding (str)
+ const char *str;
+{
+ return str + (*str == '*');
+}
+
+/* Assume ELF-ish defaults, since that's pretty much the most liberal
+ wrt cross-module name binding. */
+
+bool
+default_binds_local_p (exp)
+ tree exp;
+{
+ return default_binds_local_p_1 (exp, flag_pic);
+}
+
+bool
+default_binds_local_p_1 (exp, shlib)
+ tree exp;
+ int shlib;
+{
+ bool local_p;
+
+ /* A non-decl is an entry in the constant pool. */
+ if (!DECL_P (exp))
+ local_p = true;
+ /* Static variables are always local. */
+ else if (! TREE_PUBLIC (exp))
+ local_p = true;
+ /* A variable is local if the user tells us so. */
+ else if (decl_visibility (exp) != VISIBILITY_DEFAULT)
+ local_p = true;
+ /* Otherwise, variables defined outside this object may not be local. */
+ else if (DECL_EXTERNAL (exp))
+ local_p = false;
+ /* Linkonce and weak data are never local. */
+ else if (DECL_ONE_ONLY (exp) || DECL_WEAK (exp))
+ local_p = false;
+ /* If PIC, then assume that any global name can be overridden by
+ symbols resolved from other modules. */
+ else if (shlib)
+ local_p = false;
+ /* Uninitialized COMMON variable may be unified with symbols
+ resolved from other modules. */
+ else if (DECL_COMMON (exp)
+ && (DECL_INITIAL (exp) == NULL
+ || DECL_INITIAL (exp) == error_mark_node))
+ local_p = false;
+ /* Otherwise we're left with initialized (or non-common) global data
+ which is of necessity defined locally. */
+ else
+ local_p = true;
+
+ return local_p;
+}
+
+/* Default function to output code that will globalize a label. A
+ target must define GLOBAL_ASM_OP or provide it's own function to
+ globalize a label. */
+#ifdef GLOBAL_ASM_OP
+void
+default_globalize_label (stream, name)
+ FILE * stream;
+ const char *name;
+{
+ fputs (GLOBAL_ASM_OP, stream);
+ assemble_name (stream, name);
+ putc ('\n', stream);
+}
+#endif /* GLOBAL_ASM_OP */
+
+#include "gt-varasm.h"
diff --git a/contrib/gcc/varray.c b/contrib/gcc/varray.c
index eef2234..51e3e8b 100644
--- a/contrib/gcc/varray.c
+++ b/contrib/gcc/varray.c
@@ -22,27 +22,59 @@
#include "config.h"
#include "errors.h"
#include "system.h"
-#include "rtl.h"
-#include "tree.h"
-#include "bitmap.h"
#include "varray.h"
+#include "ggc.h"
#define VARRAY_HDR_SIZE (sizeof (struct varray_head_tag) - sizeof (varray_data))
+static const size_t element_size[NUM_VARRAY_DATA] = {
+ sizeof (char),
+ sizeof (unsigned char),
+ sizeof (short),
+ sizeof (unsigned short),
+ sizeof (int),
+ sizeof (unsigned int),
+ sizeof (long),
+ sizeof (unsigned long),
+ sizeof (HOST_WIDE_INT),
+ sizeof (unsigned HOST_WIDE_INT),
+ sizeof (PTR),
+ sizeof (char *),
+ sizeof (struct rtx_def *),
+ sizeof (struct rtvec_def *),
+ sizeof (union tree_node *),
+ sizeof (struct bitmap_head_def *),
+ sizeof (struct reg_info_def *),
+ sizeof (struct const_equiv_data),
+ sizeof (struct basic_block_def *),
+ sizeof (struct elt_list *)
+};
+
+static const int uses_ggc[NUM_VARRAY_DATA] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* unsigned HOST_WIDE_INT */
+ 1, /* PTR */
+ 1, 1, 1, 1, 1, /* bitmap_head_def */
+ 0, 0, 0, 1
+};
+
/* Allocate a virtual array with NUM_ELEMENT elements, each of which is
ELEMENT_SIZE bytes long, named NAME. Array elements are zeroed. */
varray_type
-varray_init (num_elements, element_size, name)
+varray_init (num_elements, element_kind, name)
size_t num_elements;
- size_t element_size;
+ enum varray_data_enum element_kind;
const char *name;
{
- size_t data_size = num_elements * element_size;
- varray_type ptr = (varray_type) xcalloc (VARRAY_HDR_SIZE + data_size, 1);
+ size_t data_size = num_elements * element_size[element_kind];
+ varray_type ptr;
+ if (uses_ggc [element_kind])
+ ptr = (varray_type) ggc_alloc_cleared (VARRAY_HDR_SIZE + data_size);
+ else
+ ptr = (varray_type) xcalloc (VARRAY_HDR_SIZE + data_size, 1);
ptr->num_elements = num_elements;
ptr->elements_used = 0;
- ptr->element_size = element_size;
+ ptr->type = element_kind;
ptr->name = name;
return ptr;
}
@@ -58,11 +90,14 @@ varray_grow (va, n)
if (n != old_elements)
{
- size_t element_size = va->element_size;
- size_t old_data_size = old_elements * element_size;
- size_t data_size = n * element_size;
-
- va = (varray_type) xrealloc ((char *) va, VARRAY_HDR_SIZE + data_size);
+ size_t elem_size = element_size[va->type];
+ size_t old_data_size = old_elements * elem_size;
+ size_t data_size = n * elem_size;
+
+ if (uses_ggc[va->type])
+ va = (varray_type) ggc_realloc (va, VARRAY_HDR_SIZE + data_size);
+ else
+ va = (varray_type) xrealloc ((char *) va, VARRAY_HDR_SIZE + data_size);
va->num_elements = n;
if (n > old_elements)
memset (&va->data.c[old_data_size], 0, data_size - old_data_size);
@@ -71,6 +106,17 @@ varray_grow (va, n)
return va;
}
+/* Reset a varray to its original state. */
+void
+varray_clear (va)
+ varray_type va;
+{
+ size_t data_size = element_size[va->type] * va->num_elements;
+
+ memset (va->data.c, 0, data_size);
+ va->elements_used = 0;
+}
+
/* Check the bounds of a varray access. */
#if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
diff --git a/contrib/gcc/varray.h b/contrib/gcc/varray.h
index 66c4d39..8d4dafb 100644
--- a/contrib/gcc/varray.h
+++ b/contrib/gcc/varray.h
@@ -33,7 +33,7 @@
/* Auxiliary structure used inside the varray structure, used for
function integration data. */
-struct const_equiv_data {
+struct const_equiv_data GTY(()) {
/* Map pseudo reg number in calling function to equivalent constant. We
cannot in general substitute constants into parameter pseudo registers,
since some machine descriptions (many RISCs) won't always handle
@@ -54,107 +54,153 @@ struct const_equiv_data {
unsigned age;
};
+/* Enum indicating what the varray contains.
+ If this is changed, `element_size' in varray.c needs to be updated. */
+
+enum varray_data_enum {
+ VARRAY_DATA_C,
+ VARRAY_DATA_UC,
+ VARRAY_DATA_S,
+ VARRAY_DATA_US,
+ VARRAY_DATA_I,
+ VARRAY_DATA_U,
+ VARRAY_DATA_L,
+ VARRAY_DATA_UL,
+ VARRAY_DATA_HINT,
+ VARRAY_DATA_UHINT,
+ VARRAY_DATA_GENERIC,
+ VARRAY_DATA_CPTR,
+ VARRAY_DATA_RTX,
+ VARRAY_DATA_RTVEC,
+ VARRAY_DATA_TREE,
+ VARRAY_DATA_BITMAP,
+ VARRAY_DATA_REG,
+ VARRAY_DATA_CONST_EQUIV,
+ VARRAY_DATA_BB,
+ VARRAY_DATA_TE,
+ NUM_VARRAY_DATA
+};
+
/* Union of various array types that are used. */
-typedef union varray_data_tag {
- char c[1];
- unsigned char uc[1];
- short s[1];
- unsigned short us[1];
- int i[1];
- unsigned int u[1];
- long l[1];
- unsigned long ul[1];
- HOST_WIDE_INT hint[1];
- unsigned HOST_WIDE_INT uhint[1];
- PTR generic[1];
- char *cptr[1];
- struct rtx_def *rtx[1];
- struct rtvec_def *rtvec[1];
- union tree_node *tree[1];
- struct bitmap_head_def *bitmap[1];
- struct sched_info_tag *sched[1];
- struct reg_info_def *reg[1];
- struct const_equiv_data const_equiv[1];
- struct basic_block_def *bb[1];
- struct elt_list *te[1];
+typedef union varray_data_tag GTY (()) {
+ char GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_C"))) c[1];
+ unsigned char GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_UC"))) uc[1];
+ short GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_S"))) s[1];
+ unsigned short GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_US"))) us[1];
+ int GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_I"))) i[1];
+ unsigned int GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_U"))) u[1];
+ long GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_L"))) l[1];
+ unsigned long GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_UL"))) ul[1];
+ HOST_WIDE_INT GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_HINT"))) hint[1];
+ unsigned HOST_WIDE_INT GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_UHINT"))) uhint[1];
+ PTR GTY ((length ("%0.num_elements"), use_param (""),
+ tag ("VARRAY_DATA_GENERIC"))) generic[1];
+ char *GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_CPTR"))) cptr[1];
+ struct rtx_def *GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_RTX"))) rtx[1];
+ struct rtvec_def *GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_RTVEC"))) rtvec[1];
+ union tree_node *GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_TREE"))) tree[1];
+ struct bitmap_head_def *GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_BITMAP"))) bitmap[1];
+ struct reg_info_def *GTY ((length ("%0.num_elements"), skip (""),
+ tag ("VARRAY_DATA_REG"))) reg[1];
+ struct const_equiv_data GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_CONST_EQUIV"))) const_equiv[1];
+ struct basic_block_def *GTY ((length ("%0.num_elements"), skip (""),
+ tag ("VARRAY_DATA_BB"))) bb[1];
+ struct elt_list *GTY ((length ("%0.num_elements"),
+ tag ("VARRAY_DATA_TE"))) te[1];
} varray_data;
/* Virtual array of pointers header. */
-typedef struct varray_head_tag {
- size_t num_elements; /* maximum element number allocated */
- size_t elements_used; /* the number of elements used, if
+struct varray_head_tag GTY(()) {
+ size_t num_elements; /* Maximum element number allocated. */
+ size_t elements_used; /* The number of elements used, if
using VARRAY_PUSH/VARRAY_POP. */
- size_t element_size; /* size of each data element */
+ enum varray_data_enum type; /* The kind of elements in the varray. */
const char *name; /* name of the varray for reporting errors */
- varray_data data; /* data elements follow, must be last */
-} *varray_type;
+ varray_data GTY ((desc ("%0.type"))) data; /* The data elements follow,
+ must be last. */
+};
+typedef struct varray_head_tag *varray_type;
/* Allocate a virtual array with NUM elements, each of which is SIZE bytes
long, named NAME. Array elements are zeroed. */
-extern varray_type varray_init PARAMS ((size_t, size_t, const char *));
+extern varray_type varray_init PARAMS ((size_t, enum varray_data_enum,
+ const char *));
#define VARRAY_CHAR_INIT(va, num, name) \
- va = varray_init (num, sizeof (char), name)
+ va = varray_init (num, VARRAY_DATA_C, name)
#define VARRAY_UCHAR_INIT(va, num, name) \
- va = varray_init (num, sizeof (unsigned char), name)
+ va = varray_init (num, VARRAY_DATA_UC, name)
#define VARRAY_SHORT_INIT(va, num, name) \
- va = varray_init (num, sizeof (short), name)
+ va = varray_init (num, VARRAY_DATA_S, name)
#define VARRAY_USHORT_INIT(va, num, name) \
- va = varray_init (num, sizeof (unsigned short), name)
+ va = varray_init (num, VARRAY_DATA_US, name)
#define VARRAY_INT_INIT(va, num, name) \
- va = varray_init (num, sizeof (int), name)
+ va = varray_init (num, VARRAY_DATA_I, name)
#define VARRAY_UINT_INIT(va, num, name) \
- va = varray_init (num, sizeof (unsigned int), name)
+ va = varray_init (num, VARRAY_DATA_U, name)
#define VARRAY_LONG_INIT(va, num, name) \
- va = varray_init (num, sizeof (long), name)
+ va = varray_init (num, VARRAY_DATA_L, name)
#define VARRAY_ULONG_INIT(va, num, name) \
- va = varray_init (num, sizeof (unsigned long), name)
+ va = varray_init (num, VARRAY_DATA_UL, name)
#define VARRAY_WIDE_INT_INIT(va, num, name) \
- va = varray_init (num, sizeof (HOST_WIDE_INT), name)
+ va = varray_init (num, VARRAY_DATA_HINT, name)
#define VARRAY_UWIDE_INT_INIT(va, num, name) \
- va = varray_init (num, sizeof (unsigned HOST_WIDE_INT), name)
+ va = varray_init (num, VARRAY_DATA_UHINT, name)
#define VARRAY_GENERIC_PTR_INIT(va, num, name) \
- va = varray_init (num, sizeof (PTR), name)
+ va = varray_init (num, VARRAY_DATA_GENERIC, name)
#define VARRAY_CHAR_PTR_INIT(va, num, name) \
- va = varray_init (num, sizeof (char *), name)
+ va = varray_init (num, VARRAY_DATA_CPTR, name)
#define VARRAY_RTX_INIT(va, num, name) \
- va = varray_init (num, sizeof (struct rtx_def *), name)
+ va = varray_init (num, VARRAY_DATA_RTX, name)
#define VARRAY_RTVEC_INIT(va, num, name) \
- va = varray_init (num, sizeof (struct rtvec_def), name)
+ va = varray_init (num, VARRAY_DATA_RTVEC, name)
#define VARRAY_TREE_INIT(va, num, name) \
- va = varray_init (num, sizeof (union tree_node *), name)
+ va = varray_init (num, VARRAY_DATA_TREE, name)
#define VARRAY_BITMAP_INIT(va, num, name) \
- va = varray_init (num, sizeof (struct bitmap_head_def *), name)
-
-#define VARRAY_SCHED_INIT(va, num, name) \
- va = varray_init (num, sizeof (struct sched_info_tag *), name)
+ va = varray_init (num, VARRAY_DATA_BITMAP, name)
#define VARRAY_REG_INIT(va, num, name) \
- va = varray_init (num, sizeof (struct reg_info_def *), name)
+ va = varray_init (num, VARRAY_DATA_REG, name)
#define VARRAY_CONST_EQUIV_INIT(va, num, name) \
- va = varray_init (num, sizeof (struct const_equiv_data), name)
+ va = varray_init (num, VARRAY_DATA_CONST_EQUIV, name)
#define VARRAY_BB_INIT(va, num, name) \
- va = varray_init (num, sizeof (struct basic_block_def *), name)
+ va = varray_init (num, VARRAY_DATA_BB, name)
#define VARRAY_ELT_LIST_INIT(va, num, name) \
- va = varray_init (num, sizeof (struct elt_list *), name)
+ va = varray_init (num, VARRAY_DATA_TE, name)
/* Free up memory allocated by the virtual array, but do not free any of the
elements involved. */
@@ -171,14 +217,18 @@ extern varray_type varray_grow PARAMS ((varray_type, size_t));
#define VARRAY_ACTIVE_SIZE(VA) ((VA)->elements_used)
#define VARRAY_POP_ALL(VA) ((VA)->elements_used = 0)
+#define VARRAY_CLEAR(VA) varray_clear(VA)
+
+extern void varray_clear PARAMS ((varray_type));
+
/* Check for VARRAY_xxx macros being in bound. */
#if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
extern void varray_check_failed PARAMS ((varray_type, size_t,
const char *, int,
const char *)) ATTRIBUTE_NORETURN;
#define VARRAY_CHECK(VA, N, T) __extension__ \
-(*({ varray_type _va = VA; \
- size_t _n = N; \
+(*({ varray_type const _va = (VA); \
+ const size_t _n = (N); \
if (_n >= _va->num_elements) \
varray_check_failed (_va, _n, __FILE__, __LINE__, __FUNCTION__); \
&_va->data.T[_n]; }))
@@ -188,8 +238,8 @@ extern void varray_check_failed PARAMS ((varray_type, size_t,
/* Push X onto VA. T is the name of the field in varray_data
corresponding to the type of X. */
-#define VARRAY_PUSH(VA, T, X) \
- do \
+#define VARRAY_PUSH(VA, T, X) \
+ do \
{ \
if ((VA)->elements_used >= (VA)->num_elements) \
VARRAY_GROW ((VA), 2 * (VA)->num_elements); \
@@ -221,7 +271,6 @@ extern void varray_check_failed PARAMS ((varray_type, size_t,
#define VARRAY_RTVEC(VA, N) VARRAY_CHECK (VA, N, rtvec)
#define VARRAY_TREE(VA, N) VARRAY_CHECK (VA, N, tree)
#define VARRAY_BITMAP(VA, N) VARRAY_CHECK (VA, N, bitmap)
-#define VARRAY_SCHED(VA, N) VARRAY_CHECK (VA, N, sched)
#define VARRAY_REG(VA, N) VARRAY_CHECK (VA, N, reg)
#define VARRAY_CONST_EQUIV(VA, N) VARRAY_CHECK (VA, N, const_equiv)
#define VARRAY_BB(VA, N) VARRAY_CHECK (VA, N, bb)
@@ -244,7 +293,6 @@ extern void varray_check_failed PARAMS ((varray_type, size_t,
#define VARRAY_PUSH_RTVEC(VA, X) VARRAY_PUSH (VA, rtvec, X)
#define VARRAY_PUSH_TREE(VA, X) VARRAY_PUSH (VA, tree, X)
#define VARRAY_PUSH_BITMAP(VA, X) VARRAY_PUSH (VA, bitmap, X)
-#define VARRAY_PUSH_SCHED(VA, X) VARRAY_PUSH (VA, sched, X)
#define VARRAY_PUSH_REG(VA, X) VARRAY_PUSH (VA, reg, X)
#define VARRAY_PUSH_CONST_EQUIV(VA, X) VARRAY_PUSH (VA, const_equiv, X)
#define VARRAY_PUSH_BB(VA, X) VARRAY_PUSH (VA, bb, X)
@@ -266,7 +314,6 @@ extern void varray_check_failed PARAMS ((varray_type, size_t,
#define VARRAY_TOP_RTVEC(VA) VARRAY_TOP (VA, rtvec)
#define VARRAY_TOP_TREE(VA) VARRAY_TOP (VA, tree)
#define VARRAY_TOP_BITMAP(VA) VARRAY_TOP (VA, bitmap)
-#define VARRAY_TOP_SCHED(VA) VARRAY_TOP (VA, sched)
#define VARRAY_TOP_REG(VA) VARRAY_TOP (VA, reg)
#define VARRAY_TOP_CONST_EQUIV(VA) VARRAY_TOP (VA, const_equiv)
#define VARRAY_TOP_BB(VA) VARRAY_TOP (VA, bb)
diff --git a/contrib/gcc/version.c b/contrib/gcc/version.c
index a2d5c35..0fd5556 100644
--- a/contrib/gcc/version.c
+++ b/contrib/gcc/version.c
@@ -1,4 +1,18 @@
#include "ansidecl.h"
#include "version.h"
-const char *const version_string = "3.2.2";
+/* This is the string reported as the version number by all components
+ of the compiler. If you distribute a modified version of GCC,
+ please modify this string to indicate that, e.g. by putting your
+ organization's name in parentheses at the end of the string. */
+
+const char version_string[] = "3.3.1 20030711 (prerelease)";
+
+/* This is the location of the online document giving instructions for
+ reporting bugs. If you distribute a modified version of GCC,
+ please change this to refer to a document giving instructions for
+ reporting bugs to you, not us. (You are of course welcome to
+ forward us bugs reported to you, if you determine that they are
+ not bugs in your modifications.) */
+
+const char bug_report_url[] = "<URL:http://gcc.gnu.org/bugs.html>";
diff --git a/contrib/gcc/version.h b/contrib/gcc/version.h
index 9941649..8e944cc 100644
--- a/contrib/gcc/version.h
+++ b/contrib/gcc/version.h
@@ -1,4 +1,5 @@
#ifndef GCC_VERSION_H
#define GCC_VERSION_H
-extern const char *const version_string;
+extern const char version_string[];
+extern const char bug_report_url[];
#endif /* ! GCC_VERSION_H */
diff --git a/contrib/gcc/vmsdbg.h b/contrib/gcc/vmsdbg.h
index 8b7fcae..bb12bd9 100644
--- a/contrib/gcc/vmsdbg.h
+++ b/contrib/gcc/vmsdbg.h
@@ -190,7 +190,7 @@ typedef struct _DST_SOURCE_CORR
#define DST_K_SOURCE_CORR_HEADER_SIZE 4
/* Source file correlation codes. */
-
+
#define DST_K_SRC_DECLFILE 1
#define DST_K_SRC_SETFILE 2
#define DST_K_SRC_SETREC_L 3
@@ -251,5 +251,5 @@ typedef struct _DST_PROLOG
unsigned int dst_l_prolog_bkpt_addr;
} DST_PROLOG;
#define DST_K_PROLOG_SIZE 8
-
+
#endif /* GCC_VMSDBG_H */
diff --git a/contrib/gcc/vmsdbgout.c b/contrib/gcc/vmsdbgout.c
index 7332389..3b8b8f8 100644
--- a/contrib/gcc/vmsdbgout.c
+++ b/contrib/gcc/vmsdbgout.c
@@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "vmsdbg.h"
#include "debug.h"
#include "langhooks.h"
+#include "function.h"
/* Difference in seconds between the VMS Epoch and the Unix Epoch */
static const long long vms_epoch_offset = 3506716800ll;
@@ -79,14 +80,11 @@ dst_file_info_entry;
are only defaults. If the sizes are different for your target, you should
override these values by defining the appropriate symbols in your tm.h
file. */
-#ifndef CHAR_TYPE_SIZE
-#define CHAR_TYPE_SIZE BITS_PER_UNIT
-#endif
#ifndef PTR_SIZE
#define PTR_SIZE 4 /* Must be 32 bits for VMS debug info */
#endif
-/* Pointer to an structure of filenames referenced by this compilation unit. */
+/* Pointer to a structure of filenames referenced by this compilation unit. */
static dst_file_info_ref file_info_table;
/* Total number of entries in the table (i.e. array) pointed to by
@@ -126,13 +124,6 @@ static unsigned int line_info_table_in_use;
/* Size (in elements) of increments by which we may expand line_info_table. */
#define LINE_INFO_TABLE_INCREMENT 1024
-/* The number of the current function definition for which debugging
- information is being generated. These numbers range from 1 up to the
- maximum number of function definitions contained within the current
- compilation unit. These numbers are used to create unique label id's unique
- to each function definition. */
-static unsigned int current_funcdef_number = 0;
-
/* Forward declarations for functions defined in this file. */
static char *full_name PARAMS ((const char *));
static unsigned int lookup_filename PARAMS ((const char *));
@@ -165,7 +156,9 @@ static void vmsdbgout_end_block PARAMS ((unsigned int, unsigned int));
static bool vmsdbgout_ignore_block PARAMS ((tree));
static void vmsdbgout_source_line PARAMS ((unsigned int, const char *));
static void vmsdbgout_begin_prologue PARAMS ((unsigned int, const char *));
-static void vmsdbgout_end_epilogue PARAMS ((void));
+static void vmsdbgout_end_prologue PARAMS ((unsigned int, const char *));
+static void vmsdbgout_end_function PARAMS ((unsigned int));
+static void vmsdbgout_end_epilogue PARAMS ((unsigned int, const char *));
static void vmsdbgout_begin_function PARAMS ((tree));
static void vmsdbgout_decl PARAMS ((tree));
static void vmsdbgout_global_decl PARAMS ((tree));
@@ -173,7 +166,7 @@ static void vmsdbgout_abstract_function PARAMS ((tree));
/* The debug hooks structure. */
-struct gcc_debug_hooks vmsdbg_debug_hooks
+const struct gcc_debug_hooks vmsdbg_debug_hooks
= {vmsdbgout_init,
vmsdbgout_finish,
vmsdbgout_define,
@@ -185,10 +178,10 @@ struct gcc_debug_hooks vmsdbg_debug_hooks
vmsdbgout_ignore_block,
vmsdbgout_source_line,
vmsdbgout_begin_prologue,
- debug_nothing_int, /* end_prologue */
- vmsdbgout_end_epilogue, /* end_epilogue */
- vmsdbgout_begin_function, /* begin_function */
- debug_nothing_int, /* end_function */
+ vmsdbgout_end_prologue,
+ vmsdbgout_end_epilogue,
+ vmsdbgout_begin_function,
+ vmsdbgout_end_function,
vmsdbgout_decl,
vmsdbgout_global_decl,
debug_nothing_tree, /* deferred_inline_function */
@@ -241,11 +234,6 @@ struct gcc_debug_hooks vmsdbg_debug_hooks
: (NUMBYTES(OFFSET) == 2 ? UNALIGNED_SHORT_ASM_OP : ASM_BYTE_OP))
#endif
-/* Pseudo-op for defining a new section. */
-#ifndef SECTION_ASM_OP
-#define SECTION_ASM_OP ".section"
-#endif
-
/* Definitions of defaults for formats and names of various special
(artificial) labels which may be generated within this file (when the -g
options is used and VMS_DEBUGGING_INFO is in effect. If necessary, these
@@ -452,7 +440,7 @@ restart:
break;
case CONST:
- /* This used to output parentheses around the expression, but that does
+ /* This used to output parentheses around the expression, but that does
not work on the 386 (either ATT or BSD assembler). */
addr_const_to_string (buf1, XEXP (x, 0));
strcat (str, buf1);
@@ -538,7 +526,7 @@ restart:
/* Output the debug header HEADER. Also output COMMENT if flag_verbose_asm is
set. Return the header size. Just return the size if DOSIZEONLY is
- non-zero. */
+ nonzero. */
static int
write_debug_header (header, comment, dosizeonly)
@@ -570,7 +558,7 @@ write_debug_header (header, comment, dosizeonly)
/* Output the address of SYMBOL. Also output COMMENT if flag_verbose_asm is
set. Return the address size. Just return the size if DOSIZEONLY is
- non-zero. */
+ nonzero. */
static int
write_debug_addr (symbol, comment, dosizeonly)
@@ -591,7 +579,7 @@ write_debug_addr (symbol, comment, dosizeonly)
/* Output the single byte DATA1. Also output COMMENT if flag_verbose_asm is
set. Return the data size. Just return the size if DOSIZEONLY is
- non-zero. */
+ nonzero. */
static int
write_debug_data1 (data1, comment, dosizeonly)
@@ -612,7 +600,7 @@ write_debug_data1 (data1, comment, dosizeonly)
/* Output the single word DATA2. Also output COMMENT if flag_verbose_asm is
set. Return the data size. Just return the size if DOSIZEONLY is
- non-zero. */
+ nonzero. */
static int
write_debug_data2 (data2, comment, dosizeonly)
@@ -632,7 +620,7 @@ write_debug_data2 (data2, comment, dosizeonly)
}
/* Output double word DATA4. Also output COMMENT if flag_verbose_asm is set.
- Return the data size. Just return the size if DOSIZEONLY is non-zero. */
+ Return the data size. Just return the size if DOSIZEONLY is nonzero. */
static int
write_debug_data4 (data4, comment, dosizeonly)
@@ -647,12 +635,12 @@ write_debug_data4 (data4, comment, dosizeonly)
fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
fputc ('\n', asm_out_file);
}
-
+
return 4;
}
/* Output quad word DATA8. Also output COMMENT if flag_verbose_asm is set.
- Return the data size. Just return the size if DOSIZEONLY is non-zero. */
+ Return the data size. Just return the size if DOSIZEONLY is nonzero. */
static int
write_debug_data8 (data8, comment, dosizeonly)
@@ -673,7 +661,7 @@ write_debug_data8 (data8, comment, dosizeonly)
/* Output the difference between LABEL1 and LABEL2. Also output COMMENT if
flag_verbose_asm is set. Return the data size. Just return the size if
- DOSIZEONLY is non-zero. */
+ DOSIZEONLY is nonzero. */
static int
write_debug_delta4 (label1, label2, comment, dosizeonly)
@@ -695,7 +683,7 @@ write_debug_delta4 (label1, label2, comment, dosizeonly)
/* Output a character string STRING. Also write COMMENT if flag_verbose_asm is
set. Return the string length. Just return the length if DOSIZEONLY is
- non-zero. */
+ nonzero. */
static int
write_debug_string (string, comment, dosizeonly)
@@ -710,12 +698,12 @@ write_debug_string (string, comment, dosizeonly)
fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
fputc ('\n', asm_out_file);
}
-
+
return strlen (string);
}
/* Output a module begin header and return the header size. Just return the
- size if DOSIZEONLY is non-zero. */
+ size if DOSIZEONLY is nonzero. */
static int
write_modbeg (dosizeonly)
@@ -779,7 +767,7 @@ write_modbeg (dosizeonly)
}
/* Output a module end trailer and return the trailer size. Just return
- the size if DOSIZEONLY is non-zero. */
+ the size if DOSIZEONLY is nonzero. */
static int
write_modend (dosizeonly)
@@ -799,7 +787,7 @@ write_modend (dosizeonly)
}
/* Output a routine begin header routine RTNNUM and return the header size.
- Just return the size if DOSIZEONLY is non-zero. */
+ Just return the size if DOSIZEONLY is nonzero. */
static int
write_rtnbeg (rtnnum, dosizeonly)
@@ -807,7 +795,7 @@ write_rtnbeg (rtnnum, dosizeonly)
int dosizeonly;
{
char *rtnname;
- int rtnnamelen, rtnentrynamelen;
+ int rtnnamelen;
char *rtnentryname;
int totsize = 0;
char label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -816,10 +804,7 @@ write_rtnbeg (rtnnum, dosizeonly)
rtnname = func_table[rtnnum];
rtnnamelen = strlen (rtnname);
- rtnentrynamelen = rtnnamelen + 4; /* "..en" */
- rtnentryname = (char *) xmalloc (rtnentrynamelen + 1);
- strcpy (rtnentryname, rtnname);
- strcat (rtnentryname, "..en");
+ rtnentryname = concat (rtnname, "..en", NULL);
if (!strcmp (rtnname, "main"))
{
@@ -832,7 +817,7 @@ write_rtnbeg (rtnnum, dosizeonly)
/* header size - 1st byte + flag byte + STO_LW size
+ string count byte + string length */
header.dst__header_length.dst_w_length
- = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
+ = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
header.dst__header_type.dst_w_type = 0x17;
totsize += write_debug_header (&header, "transfer", dosizeonly);
@@ -897,7 +882,7 @@ write_rtnbeg (rtnnum, dosizeonly)
}
/* Output a routine end trailer for routine RTNNUM and return the header size.
- Just return the size if DOSIZEONLY is non-zero. */
+ Just return the size if DOSIZEONLY is nonzero. */
static int
write_rtnend (rtnnum, dosizeonly)
@@ -941,7 +926,7 @@ write_rtnend (rtnnum, dosizeonly)
: (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L)
/* Output the PC to line number correlations and return the size. Just return
- the size if DOSIZEONLY is non-zero */
+ the size if DOSIZEONLY is nonzero */
static int
write_pclines (dosizeonly)
@@ -1001,8 +986,8 @@ write_pclines (dosizeonly)
totsize += write_debug_data1 (pcline.dst_b_pcline_command,
"line_num (SET LINUM LONG)", dosizeonly);
- sprintf (buff, "line_num (%d)", ln - 1);
- totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
+ sprintf (buff, "line_num (%d)", ln ? ln - 1 : 0);
+ totsize += write_debug_data4 (ln ? ln - 1 : 0, buff, dosizeonly);
lastln = ln;
strcpy (lastlabel, TEXT_SECTION_ASM_OP);
@@ -1072,7 +1057,7 @@ write_pclines (dosizeonly)
/* Output a source correlation for file FILEID using information saved in
FILE_INFO_ENTRY and return the size. Just return the size if DOSIZEONLY is
- non-zero. */
+ nonzero. */
static int
write_srccorr (fileid, file_info_entry, dosizeonly)
@@ -1136,7 +1121,7 @@ write_srccorr (fileid, file_info_entry, dosizeonly)
= DST_K_SOURCE;
src_cmdtrlr.dst_b_src_df_libmodname = 0;
-
+
totsize += write_debug_header (&src_header.dst_a_source_corr_header,
"source corr", dosizeonly);
totsize += write_debug_data1 (src_command.dst_b_src_command,
@@ -1156,7 +1141,7 @@ write_srccorr (fileid, file_info_entry, dosizeonly)
totsize += write_debug_data8
(src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt,
"source_corr (creation date)", dosizeonly);
-
+
totsize += write_debug_data4
(src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk,
"source_corr (EOF block number)", dosizeonly);
@@ -1201,69 +1186,73 @@ write_srccorr (fileid, file_info_entry, dosizeonly)
src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
= DST_K_SOURCE;
- totsize += write_debug_header (&src_header.dst_a_source_corr_header,
- "source corr", dosizeonly);
-
- totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
- "source_corr (src setfile)", dosizeonly);
-
- totsize += write_debug_data2
- (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
- "source_corr (fileid)", dosizeonly);
-
- totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
- "source_corr (setrec)", dosizeonly);
-
- totsize += write_debug_data2
- (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
- "source_corr (recnum)", dosizeonly);
-
- totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
- "source_corr (setlnum)", dosizeonly);
+ if (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword)
+ {
+ totsize += write_debug_header (&src_header.dst_a_source_corr_header,
+ "source corr", dosizeonly);
- totsize += write_debug_data4
- (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
- "source_corr (linenum)", dosizeonly);
+ totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
+ "source_corr (src setfile)", dosizeonly);
- totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
- "source_corr (deflines)", dosizeonly);
+ totsize += write_debug_data2
+ (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
+ "source_corr (fileid)", dosizeonly);
- sprintf (buff, "source_corr (%d)",
- src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
- totsize += write_debug_data2
- (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword, buff, dosizeonly);
+ totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
+ "source_corr (setrec)", dosizeonly);
- while (linesleft > 0)
- {
- src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
- = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
- src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
- = DST_K_SOURCE;
- src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
+ totsize += write_debug_data2
+ (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
+ "source_corr (recnum)", dosizeonly);
- if (linesleft > 65534)
- linesleft = linesleft - 65534, linestodo = 65534;
- else
- linestodo = linesleft, linesleft = 0;
+ totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
+ "source_corr (setlnum)", dosizeonly);
- src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
+ totsize += write_debug_data4
+ (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
+ "source_corr (linenum)", dosizeonly);
- totsize += write_debug_header (&src_header.dst_a_source_corr_header,
- "source corr", dosizeonly);
totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
"source_corr (deflines)", dosizeonly);
+
sprintf (buff, "source_corr (%d)",
src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
totsize += write_debug_data2
(src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
buff, dosizeonly);
+
+ while (linesleft > 0)
+ {
+ src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
+ = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
+ src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
+ = DST_K_SOURCE;
+ src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
+
+ if (linesleft > 65534)
+ linesleft = linesleft - 65534, linestodo = 65534;
+ else
+ linestodo = linesleft, linesleft = 0;
+
+ src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
+
+ totsize += write_debug_header (&src_header.dst_a_source_corr_header,
+ "source corr", dosizeonly);
+ totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
+ "source_corr (deflines)", dosizeonly);
+ sprintf (buff, "source_corr (%d)",
+ src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
+ totsize += write_debug_data2
+ (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
+ buff, dosizeonly);
+ }
}
return totsize;
}
/* Output all the source correlation entries and return the size. Just return
- the size if DOSIZEONLY is non-zero. */
+ the size if DOSIZEONLY is nonzero. */
static int
write_srccorrs (dosizeonly)
@@ -1276,7 +1265,7 @@ write_srccorrs (dosizeonly)
totsize += write_srccorr (i, file_info_table[i], dosizeonly);
return totsize;
-}
+}
/* Output a marker (i.e. a label) for the beginning of a function, before
the prologue. */
@@ -1293,9 +1282,8 @@ vmsdbgout_begin_prologue (line, file)
if (debug_info_level > DINFO_LEVEL_NONE)
{
- current_funcdef_number++;
ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
- current_funcdef_number);
+ current_function_funcdef_no);
ASM_OUTPUT_LABEL (asm_out_file, label);
}
}
@@ -1303,38 +1291,61 @@ vmsdbgout_begin_prologue (line, file)
/* Output a marker (i.e. a label) for the beginning of a function, after
the prologue. */
-void
-vmsdbgout_after_prologue ()
+static void
+vmsdbgout_end_prologue (line, file)
+ unsigned int line;
+ const char *file;
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
+ if (write_symbols == VMS_AND_DWARF2_DEBUG)
+ (*dwarf2_debug_hooks.end_prologue) (line, file);
+
if (debug_info_level > DINFO_LEVEL_TERSE)
{
ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL,
- current_funcdef_number);
+ current_function_funcdef_no);
ASM_OUTPUT_LABEL (asm_out_file, label);
+
+ /* VMS PCA expects every PC range to correlate to some line and file */
+ vmsdbgout_source_line (line, file);
}
}
+/* No output for VMS debug, but make obligatory call to Dwarf2 debug */
+
+static void
+vmsdbgout_end_function (line)
+ unsigned int line;
+{
+ if (write_symbols == VMS_AND_DWARF2_DEBUG)
+ (*dwarf2_debug_hooks.end_function) (line);
+}
+
/* Output a marker (i.e. a label) for the absolute end of the generated code
for a function definition. This gets called *after* the epilogue code has
been generated. */
static void
-vmsdbgout_end_epilogue ()
+vmsdbgout_end_epilogue (line, file)
+ unsigned int line;
+ const char *file;
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
if (write_symbols == VMS_AND_DWARF2_DEBUG)
- (*dwarf2_debug_hooks.end_epilogue) ();
+ (*dwarf2_debug_hooks.end_epilogue) (line, file);
if (debug_info_level > DINFO_LEVEL_NONE)
{
/* Output a label to mark the endpoint of the code generated for this
function. */
ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
- current_funcdef_number);
+ current_function_funcdef_no);
ASM_OUTPUT_LABEL (asm_out_file, label);
+
+ /* VMS PCA expects every PC range to correlate to some line and file */
+ vmsdbgout_source_line (line, file);
}
}
@@ -1511,7 +1522,7 @@ lookup_filename (file_name)
}
}
- /* Prepare to add a new table entry by making sure there is enough space in
+ /* Prepare to add a new table entry by making sure there is enough space in
the table to do so. If not, expand the current table. */
if (file_info_table_in_use == file_info_table_allocated)
{
@@ -1563,7 +1574,7 @@ vmsdbgout_source_line (line, filename)
= (dst_line_info_ref) xrealloc (line_info_table,
(line_info_table_allocated
* sizeof (dst_line_info_entry)));
- }
+ }
/* Add the new entry at the end of the line_info_table. */
line_info = &line_info_table[line_info_table_in_use++];
@@ -1648,10 +1659,7 @@ vmsdbgout_init (main_input_filename)
else
module_language = DST_K_UNKNOWN;
- module_producer
- = (char *) xmalloc (strlen (language_string) + 1
- + strlen (version_string) + 1);
- sprintf (module_producer, "%s %s", language_string, version_string);
+ module_producer = concat (language_string, " ", version_string, NULL);
ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
diff --git a/contrib/gcc/xcoffout.c b/contrib/gcc/xcoffout.c
index 8396b7b..528bd7c 100644
--- a/contrib/gcc/xcoffout.c
+++ b/contrib/gcc/xcoffout.c
@@ -32,6 +32,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "toplev.h"
#include "output.h"
#include "ggc.h"
+#include "target.h"
#ifdef XCOFF_DEBUGGING_INFO
@@ -475,7 +476,9 @@ xcoffout_end_function (last_linenum)
Called after the epilogue is output. */
void
-xcoffout_end_epilogue ()
+xcoffout_end_epilogue (line, file)
+ unsigned int line ATTRIBUTE_UNUSED;
+ const char *file ATTRIBUTE_UNUSED;
{
/* We need to pass the correct function size to .function, otherwise,
the xas assembler can't figure out the correct size for the function
diff --git a/contrib/gcc/xcoffout.h b/contrib/gcc/xcoffout.h
index 12e4a74..dd630c9 100644
--- a/contrib/gcc/xcoffout.h
+++ b/contrib/gcc/xcoffout.h
@@ -1,6 +1,6 @@
/* XCOFF definitions. These are needed in dbxout.c, final.c,
- and xcoffout.h.
- Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+ and xcoffout.h.
+ Copyright (C) 1998, 2000, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -47,30 +47,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define DBX_STATIC_CONST_VAR_CODE N_STSYM
-/* For static variables, output code to define the start of a static block.
-
- ??? The IBM rs6000/AIX assembler has a bug that causes bss block debug
- info to be occasionally lost. A simple example is this:
- int a; static int b;
- The commands `gcc -g -c tmp.c; dump -t tmp.o' gives
-[10] m 0x00000016 1 0 0x8f 0x0000 .bs
-[11] m 0x00000000 1 0 0x90 0x0000 .es
-...
-[21] m 0x00000000 -2 0 0x85 0x0000 b:S-1
- which is wrong. The `b:S-1' must be between the `.bs' and `.es'.
- We can apparently work around the problem by forcing the text section
- (even if we are already in the text section) immediately before outputting
- the `.bs'. This should be fixed in the next major AIX release (3.3?). */
+/* For static variables, output code to define the start of a static block. */
#define DBX_STATIC_BLOCK_START(ASMFILE,CODE) \
{ \
if ((CODE) == N_STSYM) \
fprintf ((ASMFILE), "\t.bs\t%s[RW]\n", xcoff_private_data_section_name);\
else if ((CODE) == N_LCSYM) \
- { \
- fprintf ((ASMFILE), "%s\n", TEXT_SECTION_ASM_OP); \
- fprintf ((ASMFILE), "\t.bs\t%s\n", xcoff_bss_section_name); \
- } \
+ fprintf ((ASMFILE), "\t.bs\t%s\n", xcoff_bss_section_name); \
}
/* For static variables, output code to define the end of a static block. */
@@ -107,7 +91,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
if (*_p == '*') \
fprintf (asmfile, "%s", _p+1); \
else \
- for (; *_p != '[' && *_p; _p++) \
+ for (; *_p != '[' && *_p; _p++) \
fprintf (asmfile, "%c", *_p); \
} \
else if (current_sym_addr) \
@@ -202,7 +186,8 @@ extern int stab_to_sclass PARAMS ((int));
extern void xcoffout_begin_prologue PARAMS ((unsigned int,
const char *));
extern void xcoffout_begin_block PARAMS ((unsigned, unsigned));
-extern void xcoffout_end_epilogue PARAMS ((void));
+extern void xcoffout_end_epilogue PARAMS ((unsigned int,
+ const char *));
extern void xcoffout_end_function PARAMS ((unsigned int));
extern void xcoffout_end_block PARAMS ((unsigned, unsigned));
#endif /* BUFSIZ */
diff --git a/contrib/gcc/xmemdup.c b/contrib/gcc/xmemdup.c
new file mode 100644
index 0000000..9e9d66b
--- /dev/null
+++ b/contrib/gcc/xmemdup.c
@@ -0,0 +1,38 @@
+/* xmemdup.c -- Duplicate a memory buffer, using xcalloc.
+ This trivial function is in the public domain.
+ Jeff Garzik, September 1999. */
+
+/*
+
+@deftypefn Replacement void* xmemdup (void *@var{input}, size_t @var{copy_size}, size_t @var{alloc_size})
+
+Duplicates a region of memory without fail. First, @var{alloc_size} bytes
+are allocated, then @var{copy_size} bytes from @var{input} are copied into
+it, and the new memory is returned. If fewer bytes are copied than were
+allocated, the remaining memory is zeroed.
+
+@end deftypefn
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "ansidecl.h"
+#include "libiberty.h"
+
+#include <sys/types.h> /* For size_t. */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+PTR
+xmemdup (input, copy_size, alloc_size)
+ const PTR input;
+ size_t copy_size;
+ size_t alloc_size;
+{
+ PTR output = xcalloc (1, alloc_size);
+ memcpy (output, input, copy_size);
+ return output;
+}
OpenPOWER on IntegriCloud